From e7fc0c89d2367533dcd1b77e46acaeea7bc3f876 Mon Sep 17 00:00:00 2001 From: lizhirui Date: Thu, 18 Feb 2021 16:27:50 +0800 Subject: [PATCH 001/255] repair hard fault return bug before modify,when exception hook returns true,programs can't return to normal execution flow --- libcpu/arm/cortex-m7/context_rvds.S | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libcpu/arm/cortex-m7/context_rvds.S b/libcpu/arm/cortex-m7/context_rvds.S index d051f819c1..6caed09e38 100644 --- a/libcpu/arm/cortex-m7/context_rvds.S +++ b/libcpu/arm/cortex-m7/context_rvds.S @@ -10,6 +10,7 @@ ; * 2013-06-18 aozima add restore MSP feature. ; * 2013-06-23 aozima support lazy stack optimized. ; * 2018-07-24 aozima enhancement hard fault exception handler. +; * 2021-02-15 lizhirui repair hard fault return bug ; */ ;/** @@ -235,11 +236,6 @@ MemManage_Handler ENDIF STMFD r0!, {lr} ; push exec_return register - TST lr, #0x04 ; if(!EXC_RETURN[2]) - ITE EQ - MSREQ msp, r0 ; [2]=0 ==> Z=1, update stack pointer to MSP. - MSRNE psp, r0 ; [2]=1 ==> Z=0, update stack pointer to PSP. - PUSH {lr} BL rt_hw_hard_fault_exception POP {lr} From c618561cfa00d1bf2fb792d361d8101a98b7c6e6 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 15 Mar 2021 00:47:14 +0800 Subject: [PATCH 002/255] =?UTF-8?q?=E5=A2=9E=E5=8A=A0issue=20template?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/ISSUE_TEMPLATE.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..fd35feedcb --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,4 @@ +请清晰详细地描述你遇到的问题,描述问题时请使用数字或者点有条理地描述你的问题.。在问题得到解决后,请及时关闭issue。 + +Please describe your problem clearly and in detail. When describing the problem, please use numbers or bullet points to describe your problem coherently. After the problem is resolved, please close the issue in time. + From a5bea9818d3fa7c8630787cc34941af61d8fc010 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 15 Mar 2021 00:53:48 +0800 Subject: [PATCH 003/255] update --- .github/ISSUE_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index fd35feedcb..fc297dcaf3 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,4 @@ -请清晰详细地描述你遇到的问题,描述问题时请使用数字或者点有条理地描述你的问题.。在问题得到解决后,请及时关闭issue。 +请清晰详细地描述你遇到的问题,描述问题时请使用数字或者点有条理地描述你的问题.。在问题得到解决后,请及时关闭issue。欢迎到论坛提问:https://club.rt-thread.org/ -Please describe your problem clearly and in detail. When describing the problem, please use numbers or bullet points to describe your problem coherently. After the problem is resolved, please close the issue in time. +Please describe your problem clearly and in detail. When describing the problem, please use numbers or bullet points to describe your problem coherently. After the problem is resolved, please close the issue in time. Welcome to the forum to ask questions: https://club.rt-thread.io/ From b6453d8a6bb65b346ba788cd6aabd2686e193e7f Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 15 Mar 2021 00:54:49 +0800 Subject: [PATCH 004/255] remove period --- .github/ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index fc297dcaf3..75a7ea0721 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,4 @@ -请清晰详细地描述你遇到的问题,描述问题时请使用数字或者点有条理地描述你的问题.。在问题得到解决后,请及时关闭issue。欢迎到论坛提问:https://club.rt-thread.org/ +请清晰详细地描述你遇到的问题,描述问题时请使用数字或者点有条理地描述你的问题。在问题得到解决后,请及时关闭issue。欢迎到论坛提问:https://club.rt-thread.org/ Please describe your problem clearly and in detail. When describing the problem, please use numbers or bullet points to describe your problem coherently. After the problem is resolved, please close the issue in time. Welcome to the forum to ask questions: https://club.rt-thread.io/ From 5af908596659f7f0f18b4ab2bff66bb9384ba9e5 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Thu, 18 Mar 2021 15:07:09 +0800 Subject: [PATCH 005/255] [nuvoton] Fix ordering and configuration. 1. Update module starting ordering. 2. Fix QSPI PDMA configuration. --- bsp/nuvoton/libraries/m2354/rtt_port/drv_softi2c.c | 2 +- bsp/nuvoton/libraries/m480/rtt_port/drv_softi2c.c | 2 +- bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig | 13 +++++++++---- bsp/nuvoton/libraries/nuc980/rtt_port/drv_softi2c.c | 2 +- bsp/nuvoton/nk-980iot/applications/mnt.c | 2 +- bsp/nuvoton/nk-rtu980/applications/mnt.c | 2 +- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_softi2c.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_softi2c.c index a2a7ac7cc5..0d2039a563 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_softi2c.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_softi2c.c @@ -212,6 +212,6 @@ int rt_soft_i2c_init(void) return 0; } -INIT_BOARD_EXPORT(rt_soft_i2c_init); +INIT_DEVICE_EXPORT(rt_soft_i2c_init); #endif //#if (defined(BSP_USING_SOFT_I2C) && defined(BSP_USING_GPIO) && defined(RT_USING_I2C_BITOPS) && defined(RT_USING_I2C) && defined(RT_USING_PIN)) diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_softi2c.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_softi2c.c index 1549bf57f2..54208fbd61 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_softi2c.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_softi2c.c @@ -212,6 +212,6 @@ int rt_soft_i2c_init(void) return 0; } -INIT_BOARD_EXPORT(rt_soft_i2c_init); +INIT_DEVICE_EXPORT(rt_soft_i2c_init); #endif //#if (defined(BSP_USING_SOFT_I2C) && defined(BSP_USING_GPIO) && defined(RT_USING_I2C_BITOPS) && defined(RT_USING_I2C) && defined(RT_USING_PIN)) diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig b/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig index e7293b535d..08ea27c97a 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig @@ -472,12 +472,17 @@ config SOC_SERIES_NUC980 select BSP_USING_SPI if BSP_USING_QSPI - config BSP_USING_QSPI0 - bool "Enable QSPI0" + config BSP_USING_QSPI_PDMA + bool + select BSP_USING_SPI_PDMA + default n - config BSP_USING_QSPI0_PDMA + config BSP_USING_QSPI0 + bool "Enable QSPI0" + + config BSP_USING_QSPI0_PDMA bool "Enable PDMA for QSPI0" - select BSP_USING_SPI_PDMA + select BSP_USING_QSPI_PDMA depends on BSP_USING_QSPI0 endif diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_softi2c.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_softi2c.c index f638c51ff6..adc62cb4c1 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_softi2c.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_softi2c.c @@ -224,6 +224,6 @@ int rt_soft_i2c_init(void) return 0; } -INIT_BOARD_EXPORT(rt_soft_i2c_init); +INIT_DEVICE_EXPORT(rt_soft_i2c_init); #endif //#if (defined(BSP_USING_SOFT_I2C) && defined(RT_USING_I2C_BITOPS) && defined(RT_USING_I2C) && defined(RT_USING_PIN)) diff --git a/bsp/nuvoton/nk-980iot/applications/mnt.c b/bsp/nuvoton/nk-980iot/applications/mnt.c index 746d1e9a36..4ff5b1f252 100644 --- a/bsp/nuvoton/nk-980iot/applications/mnt.c +++ b/bsp/nuvoton/nk-980iot/applications/mnt.c @@ -235,6 +235,6 @@ exit_mnt_init_spiflash0: return 0; } -INIT_ENV_EXPORT(mnt_init_spiflash0); +INIT_APP_EXPORT(mnt_init_spiflash0); #endif diff --git a/bsp/nuvoton/nk-rtu980/applications/mnt.c b/bsp/nuvoton/nk-rtu980/applications/mnt.c index 779db2ffe8..ecfc390243 100644 --- a/bsp/nuvoton/nk-rtu980/applications/mnt.c +++ b/bsp/nuvoton/nk-rtu980/applications/mnt.c @@ -232,6 +232,6 @@ exit_mnt_init_spiflash0: return 0; } -INIT_ENV_EXPORT(mnt_init_spiflash0); +INIT_APP_EXPORT(mnt_init_spiflash0); #endif From dd986de78660d372ae973aeea6f5e215f81194cd Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Thu, 18 Mar 2021 15:10:43 +0800 Subject: [PATCH 006/255] [nuvoton][nk-980iot] Add SPI NOR flash configuration. Add SPI NOR flash main storage configuration file. --- bsp/nuvoton/nk-980iot/spinor.config | 827 ++++++++++++++++++++++++++++ 1 file changed, 827 insertions(+) create mode 100644 bsp/nuvoton/nk-980iot/spinor.config diff --git a/bsp/nuvoton/nk-980iot/spinor.config b/bsp/nuvoton/nk-980iot/spinor.config new file mode 100644 index 0000000000..d93d276436 --- /dev/null +++ b/bsp/nuvoton/nk-980iot/spinor.config @@ -0,0 +1,827 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=16 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=1000 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=2048 +# CONFIG_RT_USING_TIMER_SOFT 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=y + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +CONFIG_RT_USING_MEMHEAP=y +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_USERHEAP is not set +CONFIG_RT_USING_MEMTRACE=y +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=256 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" +CONFIG_RT_VER_NUM=0x40003 +CONFIG_ARCH_ARM=y +# CONFIG_RT_USING_CPU_FFS is not set +CONFIG_ARCH_ARM_ARM9=y +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_CMD_SIZE=80 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +# CONFIG_FINSH_USING_MSH_ONLY 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=16 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=16 +CONFIG_DFS_FD_MAX=64 +CONFIG_RT_USING_DFS_MNTTABLE=y +CONFIG_RT_USING_DFS_ELMFAT=y + +# +# elm-chan's FatFs, Generic FAT Filesystem Module +# +CONFIG_RT_DFS_ELM_CODE_PAGE=437 +CONFIG_RT_DFS_ELM_WORD_ACCESS=y +# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set +CONFIG_RT_DFS_ELM_USE_LFN_3=y +CONFIG_RT_DFS_ELM_USE_LFN=3 +CONFIG_RT_DFS_ELM_MAX_LFN=255 +CONFIG_RT_DFS_ELM_DRIVES=8 +CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=4096 +# CONFIG_RT_DFS_ELM_USE_ERASE is not set +CONFIG_RT_DFS_ELM_REENTRANT=y +CONFIG_RT_USING_DFS_DEVFS=y +# CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_RAMFS is not set +# CONFIG_RT_USING_DFS_UFFS is not set +# CONFIG_RT_USING_DFS_JFFS2 is not set +# 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=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=2048 +CONFIG_RT_USING_CAN=y +CONFIG_RT_CAN_USING_HDR=y +CONFIG_RT_USING_HWTIMER=y +CONFIG_RT_USING_CPUTIME=y +CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set +CONFIG_RT_USING_I2C_BITOPS=y +# CONFIG_RT_I2C_BITOPS_DEBUG is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +CONFIG_RT_USING_ADC=y +# CONFIG_RT_USING_DAC is not set +CONFIG_RT_USING_PWM=y +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +CONFIG_RT_USING_RTC=y +CONFIG_RT_USING_ALARM=y +# CONFIG_RT_USING_SOFT_RTC is not set +CONFIG_RTC_SYNC_USING_NTP=y +CONFIG_RTC_NTP_FIRST_SYNC_DELAY=30 +CONFIG_RTC_NTP_SYNC_PERIOD=3600 +# CONFIG_RT_USING_SDIO 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=y +CONFIG_RT_USING_AUDIO=y +CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_SIZE=4096 +CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_COUNT=2 +CONFIG_RT_AUDIO_RECORD_PIPE_SIZE=2048 +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +CONFIG_RT_USING_HWCRYPTO=y +CONFIG_RT_HWCRYPTO_DEFAULT_NAME="hwcryto" +CONFIG_RT_HWCRYPTO_IV_MAX_SIZE=16 +CONFIG_RT_HWCRYPTO_KEYBIT_MAX_SIZE=256 +# CONFIG_RT_HWCRYPTO_USING_GCM is not set +CONFIG_RT_HWCRYPTO_USING_AES=y +CONFIG_RT_HWCRYPTO_USING_AES_ECB=y +CONFIG_RT_HWCRYPTO_USING_AES_CBC=y +CONFIG_RT_HWCRYPTO_USING_AES_CFB=y +CONFIG_RT_HWCRYPTO_USING_AES_CTR=y +CONFIG_RT_HWCRYPTO_USING_AES_OFB=y +# CONFIG_RT_HWCRYPTO_USING_DES is not set +# CONFIG_RT_HWCRYPTO_USING_3DES is not set +# CONFIG_RT_HWCRYPTO_USING_RC4 is not set +# CONFIG_RT_HWCRYPTO_USING_MD5 is not set +CONFIG_RT_HWCRYPTO_USING_SHA1=y +CONFIG_RT_HWCRYPTO_USING_SHA2=y +CONFIG_RT_HWCRYPTO_USING_SHA2_224=y +CONFIG_RT_HWCRYPTO_USING_SHA2_256=y +CONFIG_RT_HWCRYPTO_USING_SHA2_384=y +CONFIG_RT_HWCRYPTO_USING_SHA2_512=y +CONFIG_RT_HWCRYPTO_USING_RNG=y +# CONFIG_RT_HWCRYPTO_USING_CRC is not set +# CONFIG_RT_HWCRYPTO_USING_BIGNUM 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=y +CONFIG_RT_USBH_MSTORAGE=y +CONFIG_UDISK_MOUNTPOINT="/mnt/udisk" +CONFIG_RT_USING_USB_DEVICE=y +CONFIG_RT_USBD_THREAD_STACK_SZ=4096 +CONFIG_USB_VENDOR_ID=0x0FFE +CONFIG_USB_PRODUCT_ID=0x0001 +CONFIG_RT_USB_DEVICE_COMPOSITE=y +CONFIG_RT_USB_DEVICE_CDC=y +CONFIG_RT_USB_DEVICE_NONE=y +CONFIG_RT_USB_DEVICE_MSTORAGE=y +# CONFIG_RT_USB_DEVICE_HID is not set +# CONFIG_RT_USB_DEVICE_RNDIS is not set +# CONFIG_RT_USB_DEVICE_ECM is not set +# CONFIG_RT_USB_DEVICE_WINUSB is not set +# CONFIG_RT_USB_DEVICE_AUDIO is not set +CONFIG_RT_VCOM_TASK_STK_SIZE=2048 +CONFIG_RT_CDC_RX_BUFSIZE=128 +# CONFIG_RT_VCOM_TX_USE_DMA is not set +CONFIG_RT_VCOM_SERNO="32021919830108" +CONFIG_RT_VCOM_SER_LEN=14 +CONFIG_RT_VCOM_TX_TIMEOUT=1000 +CONFIG_RT_USB_MSTORAGE_DISK_NAME="ramdisk1" + +# +# POSIX layer and C standard library +# +CONFIG_RT_USING_LIBC=y +# CONFIG_RT_USING_PTHREADS is not set +CONFIG_RT_USING_POSIX=y +# CONFIG_RT_USING_POSIX_MMAP is not set +# CONFIG_RT_USING_POSIX_TERMIOS is not set +# CONFIG_RT_USING_POSIX_GETLINE is not set +# CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_MODULE is not set + +# +# Network +# + +# +# Socket abstraction layer +# +CONFIG_RT_USING_SAL=y +CONFIG_SAL_INTERNET_CHECK=y + +# +# protocol stack implement +# +CONFIG_SAL_USING_LWIP=y +CONFIG_SAL_USING_POSIX=y + +# +# 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=y +# CONFIG_RT_USING_LWIP212 is not set +# 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=y +CONFIG_IP_SOF_BROADCAST=1 +CONFIG_IP_SOF_BROADCAST_RECV=1 + +# +# Static IPv4 Address +# +CONFIG_RT_LWIP_IPADDR="192.168.1.30" +CONFIG_RT_LWIP_GWADDR="192.168.1.1" +CONFIG_RT_LWIP_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=32 +CONFIG_RT_LWIP_PBUF_NUM=256 +CONFIG_RT_LWIP_RAW_PCB_NUM=32 +CONFIG_RT_LWIP_UDP_PCB_NUM=32 +CONFIG_RT_LWIP_TCP_PCB_NUM=32 +CONFIG_RT_LWIP_TCP_SEG_NUM=256 +CONFIG_RT_LWIP_TCP_SND_BUF=32768 +CONFIG_RT_LWIP_TCP_WND=10240 +CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10 +CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=32 +CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=4096 +# 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=32 +# 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=y +CONFIG_LWIP_NETIF_LOOPBACK=1 +CONFIG_RT_LWIP_STATS=y +# 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 is not set +CONFIG_RT_USING_UTEST=y +CONFIG_UTEST_THR_STACK_SIZE=4096 +CONFIG_UTEST_THR_PRIORITY=20 +# CONFIG_RT_USING_LWP 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=y +CONFIG_PKG_NETUTILS_PATH="/packages/iot/netutils" +CONFIG_PKG_NETUTILS_TFTP=y +CONFIG_PKG_NETUTILS_IPERF=y +# CONFIG_PKG_NETUTILS_NETIO is not set +CONFIG_PKG_NETUTILS_NTP=y +CONFIG_NETUTILS_NTP_TIMEZONE=8 +CONFIG_NETUTILS_NTP_HOSTNAME="0.tw.pool.ntp.org" +CONFIG_NETUTILS_NTP_HOSTNAME2="1.tw.pool.ntp.org" +CONFIG_NETUTILS_NTP_HOSTNAME3="2.tw.pool.ntp.org" +# CONFIG_PKG_NETUTILS_TELNET is not set +# CONFIG_PKG_NETUTILS_TCPDUMP is not set +CONFIG_PKG_USING_NETUTILS_V120=y +# CONFIG_PKG_USING_NETUTILS_V110 is not set +# CONFIG_PKG_USING_NETUTILS_V100 is not set +# CONFIG_PKG_USING_NETUTILS_LATEST_VERSION is not set +CONFIG_PKG_NETUTILS_VER="v1.2.0" +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set + +# +# multimedia packages +# +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set + +# +# system packages +# +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_PERSIMMON is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_PARTITION is not set +CONFIG_PKG_USING_FAL=y +CONFIG_PKG_FAL_PATH="/packages/system/fal" +CONFIG_FAL_DEBUG_CONFIG=y +CONFIG_FAL_DEBUG=1 +CONFIG_FAL_PART_HAS_TABLE_CFG=y +CONFIG_FAL_USING_SFUD_PORT=y +CONFIG_FAL_USING_NOR_FLASH_DEV_NAME="norflash0" +# CONFIG_PKG_USING_FAL_V00500 is not set +# CONFIG_PKG_USING_FAL_V00400 is not set +# CONFIG_PKG_USING_FAL_V00300 is not set +# CONFIG_PKG_USING_FAL_V00200 is not set +# CONFIG_PKG_USING_FAL_V00100 is not set +CONFIG_PKG_USING_FAL_LATEST_VERSION=y +CONFIG_PKG_FAL_VER="latest" +CONFIG_PKG_FAL_VER_NUM=0x99999 +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_CMSIS is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +CONFIG_PKG_USING_RAMDISK=y +CONFIG_PKG_RAMDISK_PATH="/packages/system/ramdisk" +# CONFIG_PKG_USING_RAMDISK_V010 is not set +CONFIG_PKG_USING_RAMDISK_LATEST_VERSION=y +CONFIG_PKG_RAMDISK_VER="latest" +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_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_PPOOL is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set + +# +# miscellaneous packages +# +# CONFIG_PKG_USING_LIBCSV is not set +CONFIG_PKG_USING_OPTPARSE=y +CONFIG_PKG_OPTPARSE_PATH="/packages/misc/optparse" +CONFIG_PKG_USING_OPTPARSE_V100=y +# CONFIG_PKG_USING_OPTPARSE_LATEST_VERSION is not set +CONFIG_PKG_OPTPARSE_VER="v1.0.0" +# CONFIG_OPTPARSE_USING_DEMO 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_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=y +CONFIG_PKG_VI_PATH="/packages/misc/vi" +CONFIG_VI_MAX_LEN=4096 +# CONFIG_VI_ENABLE_8BIT is not set +CONFIG_VI_ENABLE_COLON=y +CONFIG_VI_ENABLE_YANKMARK=y +CONFIG_VI_ENABLE_SEARCH=y +CONFIG_VI_ENABLE_DOT_CMD=y +CONFIG_VI_ENABLE_READONLY=y +CONFIG_VI_ENABLE_SETOPTS=y +CONFIG_VI_ENABLE_SET=y +CONFIG_VI_ENABLE_VI_ASK_TERMINAL=y +CONFIG_VI_ENABLE_UNDO=y +CONFIG_VI_ENABLE_UNDO_QUEUE=y +CONFIG_VI_UNDO_QUEUE_MAX=256 +CONFIG_PKG_USING_VI_LATEST_VERSION=y +CONFIG_PKG_VI_VER="latest" +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set + +# +# games: games run on RT-Thread console +# +# 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_LWGPS is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +CONFIG_NU_PKG_USING_DEMO=y +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +# CONFIG_NU_PKG_USING_NAU88L25 is not set +CONFIG_NU_PKG_USING_NAU8822=y +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set + +# +# Hardware Drivers Config +# + +# +# On-chip Peripheral Drivers +# +CONFIG_SOC_SERIES_NUC980=y +# CONFIG_BSP_USE_STDDRIVER_SOURCE is not set +CONFIG_BSP_USING_MMU=y +CONFIG_BSP_USING_PDMA=y +CONFIG_NU_PDMA_MEMFUN_ACTOR_MAX=2 +CONFIG_BSP_USING_GPIO=y +# CONFIG_BSP_USING_CLK is not set +CONFIG_BSP_USING_EMAC=y +CONFIG_BSP_USING_EMAC0=y +# CONFIG_BSP_USING_EMAC1 is not set +# CONFIG_NU_EMAC_PDMA_MEMCOPY is not set +CONFIG_BSP_USING_RTC=y +CONFIG_NU_RTC_SUPPORT_IO_RW=y +CONFIG_NU_RTC_SUPPORT_MSH_CMD=y +CONFIG_BSP_USING_ADC=y +CONFIG_BSP_USING_TMR=y +CONFIG_BSP_USING_TIMER=y +CONFIG_BSP_USING_TMR0=y +CONFIG_BSP_USING_TIMER0=y +# CONFIG_BSP_USING_TPWM0 is not set +# CONFIG_BSP_USING_TIMER0_CAPTURE is not set +CONFIG_BSP_USING_TMR1=y +CONFIG_BSP_USING_TIMER1=y +# CONFIG_BSP_USING_TPWM1 is not set +# CONFIG_BSP_USING_TIMER1_CAPTURE is not set +CONFIG_BSP_USING_TMR2=y +CONFIG_BSP_USING_TIMER2=y +# CONFIG_BSP_USING_TPWM2 is not set +# CONFIG_BSP_USING_TIMER2_CAPTURE is not set +CONFIG_BSP_USING_TMR3=y +CONFIG_BSP_USING_TIMER3=y +# CONFIG_BSP_USING_TPWM3 is not set +# CONFIG_BSP_USING_TIMER3_CAPTURE is not set +CONFIG_BSP_USING_TMR4=y +CONFIG_BSP_USING_TIMER4=y +# CONFIG_BSP_USING_TPWM4 is not set +# CONFIG_BSP_USING_TIMER4_CAPTURE is not set +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART0=y +# CONFIG_BSP_USING_UART0_TX_DMA is not set +# CONFIG_BSP_USING_UART0_RX_DMA is not set +CONFIG_BSP_USING_UART1=y +CONFIG_BSP_USING_UART1_TX_DMA=y +CONFIG_BSP_USING_UART1_RX_DMA=y +# CONFIG_BSP_USING_UART2 is not set +# CONFIG_BSP_USING_UART3 is not set +# CONFIG_BSP_USING_UART4 is not set +# CONFIG_BSP_USING_UART5 is not set +# CONFIG_BSP_USING_UART6 is not set +# CONFIG_BSP_USING_UART7 is not set +# CONFIG_BSP_USING_UART8 is not set +# CONFIG_BSP_USING_UART9 is not set +CONFIG_BSP_USING_I2C=y +CONFIG_BSP_USING_I2C0=y +# CONFIG_BSP_USING_I2C1 is not set +CONFIG_BSP_USING_I2C2=y +# CONFIG_BSP_USING_I2C3 is not set +CONFIG_BSP_USING_SDH=y +# CONFIG_BSP_USING_SDH0 is not set +CONFIG_BSP_USING_SDH1=y +CONFIG_NU_SDH_USING_PDMA=y +CONFIG_NU_SDH_HOTPLUG=y +# CONFIG_NU_SDH_MOUNT_ON_ROOT is not set +# CONFIG_BSP_USING_CAN is not set +CONFIG_BSP_USING_PWM=y +CONFIG_BSP_USING_PWM0=y +# CONFIG_BSP_USING_PWM1 is not set +CONFIG_BSP_USING_SPI=y +CONFIG_BSP_USING_SPI_PDMA=y +# CONFIG_BSP_USING_SPI0_NONE is not set +CONFIG_BSP_USING_SPI0=y +CONFIG_BSP_USING_SPI0_PDMA=y +CONFIG_BSP_USING_SPI1_NONE=y +# CONFIG_BSP_USING_SPI1 is not set +CONFIG_BSP_USING_I2S=y +CONFIG_NU_I2S_DMA_FIFO_SIZE=4096 +CONFIG_BSP_USING_QSPI=y +CONFIG_BSP_USING_QSPI0=y +CONFIG_BSP_USING_QSPI0_PDMA=y +# CONFIG_BSP_USING_SCUART is not set +CONFIG_BSP_USING_CRYPTO=y +# CONFIG_NU_PRNG_USE_SEED is not set +# CONFIG_BSP_USING_SOFT_I2C is not set +CONFIG_BSP_USING_WDT=y +# CONFIG_BSP_USING_EBI is not set +CONFIG_BSP_USING_USBD=y +CONFIG_BSP_USING_USBH=y + +# +# On-board Peripheral Drivers +# +CONFIG_BSP_USING_CONSOLE=y +CONFIG_BOARD_USING_IP101GR=y +CONFIG_BOARD_USING_NAU8822=y +CONFIG_BOARD_USING_STORAGE_SDCARD=y +CONFIG_BOARD_USING_STORAGE_SPIFLASH=y +# CONFIG_BOARD_USING_STORAGE_SPINAND is not set +CONFIG_BOARD_USING_USB0_DEVICE_HOST=y +CONFIG_BOARD_USING_USB1_HOST=y + +# +# Board extended module drivers +# +# CONFIG_BOARD_USING_MAX31875 is not set +# CONFIG_BOARD_USING_LCD_ILI9341 is not set +# CONFIG_BOARD_USING_ESP8266 is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk980-iot.test.utest." From 98622de932e97630af37ca6442c45df6f2c2839e Mon Sep 17 00:00:00 2001 From: Meco Jianting Man <920369182@qq.com> Date: Thu, 22 Apr 2021 10:18:11 +0800 Subject: [PATCH 007/255] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 75a7ea0721..5c8cd5d766 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,4 @@ -请清晰详细地描述你遇到的问题,描述问题时请使用数字或者点有条理地描述你的问题。在问题得到解决后,请及时关闭issue。欢迎到论坛提问:https://club.rt-thread.org/ + -Please describe your problem clearly and in detail. When describing the problem, please use numbers or bullet points to describe your problem coherently. After the problem is resolved, please close the issue in time. Welcome to the forum to ask questions: https://club.rt-thread.io/ + From ba37e722176bc93db0562117e67a03124ae30531 Mon Sep 17 00:00:00 2001 From: yangjie Date: Sat, 10 Apr 2021 18:34:13 +0800 Subject: [PATCH 008/255] [bsp]add copyright notice --- bsp/Copyright_Notice.md | 749 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 749 insertions(+) create mode 100644 bsp/Copyright_Notice.md diff --git a/bsp/Copyright_Notice.md b/bsp/Copyright_Notice.md new file mode 100644 index 0000000000..0f74a9567d --- /dev/null +++ b/bsp/Copyright_Notice.md @@ -0,0 +1,749 @@ +# 版权声明 Copyright Notice + +RT-Thread 是一套开源、开放的操作系统平台,自 3.1.1 版本开始以 Apache License v2.0 许可协议发布。 + +芯片厂商外设函数库或者厂商固件,按厂商的许可进行授权,并以原有许可协议发布。 + +RT-Thread is an open source operating system, which is released under Apache License V2.0 since version 3.1.1. + +The peripheral library or firmware library of the chip manufacturer is authorized according to the manufacturer's license, and these files are released according to the original license agreement. + +## BSP's License and Coyright: + +### apollo2 + +License: bsd-new + +Copyright: Copyright (c) 2017, Ambiq Micro + +Path: + +- bsp/apollo2/libraries + +### at32 + +License: st-mcd-2.0 + +Copyright: (c) COPYRIGHT 2018 ArteryTek + +Path: + +- bsp/at32/at32f407-start/board/msp + +------ + +License: bsd-new + +Copyright: Copyright (c) 2010-2015 ARM Limited + +Path: + +- bsp/at32/Libraries/AT32_Std_Driver/CMSIS + +### avr32uc3b0 + +License: bsd-new + +Copyright: Copyright (c) 2009 Atmel Corporation + +Path: + +- bsp/avr32uc3b0/SOFTWARE_FRAMEWORK + +### CME_M7 + +License: st-mcd-2.0 + +Copyright: (c) COPYRIGHT 2013 Capital-micro + +Path: + +- bsp/CME_M7/CMSIS/CME_M7 +- bsp/CME_M7/StdPeriph_Driver + +------ + +License: bsd-new + +Copyright: Copyright (c) 2009 - 2013 ARM LIMITED + +Path: + +- bsp/CME_M7/CMSIS/CMSIS + +### efm32 + +License: zlib + +Copyright: (C) Copyright 2012 Energy Micro AS, http://www.energymicro.com + +Path: + +- bsp/efm32/EFM32_Gxxx_DK +- bsp/efm32/EFM32GG_DK3750 +- bsp/efm32/graphics +- bsp/efm32/Libraries/Device/EnergyMicro +- bsp/efm32/Libraries/emlib + +------ + +License: arm-cortex-mx + +Copyright: Copyright (c) 2009-2012 ARM Limited + +Path: + +- bsp/efm32/Libraries/CMSIS/Include + +### essemi + +License: 未注明 + +Copyright: Copyright (c) 2018 Shanghai Eastsoft Microelectronics Co., Ltd. + +Path: + +- bsp/essemi/es32f0271/libraries/CMSIS/Device +- bsp/essemi/es32f0271/libraries/ES32F027x_MD_StdPeriph_Driver +- bsp/essemi/es32f0271/libraries/usblib +- bsp/essemi/es32f0334/libraries/ES32F033x_ALD_StdPeriph_Driver +- bsp/essemi/es32f0654/libraries/ES32F065x_ALD_StdPeriph_Driver +- bsp/essemi/es32f369x/libraries/ES32F36xx_ALD_StdPeriph_Driver +- bsp/essemi/es8p508x/libraries/CMSIS +- bsp/essemi/es8p508x/libraries/Library + +------ + +License: bsd-new + +Copyright: Copyright (c) 2013 ARM LIMITED + +Path: + +- bsp/essemi/es32f0271/libraries/CMSIS/RTOS +- bsp/essemi/es32f0334/libraries/CMSIS/Include +- bsp/essemi/es32f0654/libraries/CMSIS/Include +- bsp/essemi/es8p508x/libraries/CMSIS + +### fh8620 + +License: gpl-2.0-plus + +Copyright: Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd. + +Path: + +- bsp/fh8620 + +### frdm-k64f + +License: bsd-new + +Copyright: Copyright (c) 2015, Freescale Semiconductor, Inc. + +Path: + +- bsp/frdm-k64f/board +- bsp/frdm-k64f/device + +### gd32 + +bsp 列表: +- gd32103c-eval +- gd32303e-eval +- gd32450z-eval +- gd32e230k-start +- gd32vf103v-eval + +------ + +License: 未注明 + +Copyright: Copyright (c) 2017 GigaDevice + +Path: + +- bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral +- bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver + +------ + +License: bsd-new + +Copyright: Copyright (c) 2018, GigaDevice Semiconductor Inc. + +Path: + +- bsp/gd32e230k-start/Libraries/CMSIS/GD +- bsp/gd32e230k-start/Libraries/GD32E230_standard_peripheral +- bsp/gd32vf103v-eval/board/gd32vf103_libopt.h +- bsp/gd32vf103v-eval/libraries/GD32VF103_standard_peripheral + +------ + +License: bsd-new + +Copyright: Copyright (c) 2012 ARM LIMITED + +Path: + +- bsp/gd32103c-eval/Libraries/CMSIS/core_cm3.h +- bsp/gd32303e-eval/Libraries/CMSIS/core +- bsp/gd32303e-eval/Libraries/CMSIS/GD/GD32F30x/Include +- bsp/gd32450z-eval/Libraries/CMSIS/core +- bsp/gd32e230k-start/Libraries/CMSIS/GD/GD32E230/Include/system + +------ + +License: arm-cortex-mx + +Copyright: Copyright (c) 2009-2012 ARM Limited + +Path: + +- bsp/gd32103c-eval/Libraries/CMSIS/core +- bsp/gd32303e-eval/Libraries/CMSIS/core + +### gkipc + +License: gpl-2.0-plus + +Copyright: Copyright (c) 2017 GOKE Microelectronics Co., Ltd. + +Path: + +- bsp/gkipc/drivers + +------ + +License: 未注明 + +Copyright: Copyright 2012 - 2013 (c) GoKe Microelectronics ShangHai Branch + +Path: + +- bsp/gkipc/libraries + +### hc32f4a0 + +License: bsd-new + +Copyright: Copyright (c) 2020, Huada Semiconductor Co., Ltd. + +Path: + +- bsp/hc32f4a0/Libraries/CMSIS +- bsp/hc32f4a0/Libraries/HC32F4A0_StdPeriph_Driver + +### imx6sx + +License: other-permissive + +Copyright: Copyright (c) 2012, Freescale Semiconductor, Inc. + +Path: + +- bsp/imx6sx/cortex-a9/board + +------ + +License: bsd-new、robert-hubley、other-permissive、proprietary-license、gpl-2.0 + +Copyright: Copyright (c) 2012, Freescale Semiconductor, Inc. + +Path: + +- bsp/imx6sx/iMX6_Platform_SDK + +### imx6ul + +License: bsd-new、proprietary-license、robert-hubley、gpl-2.0 + +Copyright: Copyright (c) 2012, Freescale Semiconductor, Inc. + +Path: + +- bsp/imx6ul/platform + +### imxrt + +License: clear-bsd + +Copyright: Copyright 2016 - 2017 NXP + +Path: + +- bsp/imxrt/imxrt1052-nxp-evk/xip + +------ + +License: bsd-new + +Copyright: Copyright 2016 - 2017 NXP + +Path: + +- bsp/imxrt/imxrt1064-nxp-evk/board/MCUX_Config/clock_config.c +- bsp/imxrt/imxrt1064-nxp-evk/xip +- bsp/imxrt/libraries/drivers/drv_sdram.c +- bsp/imxrt/libraries/drivers/usb +- bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052 +- bsp/imxrt/libraries/MIMXRT1064/MIMXRT1064 + +### lm + +bsp 列表: + +- lm3s9b9x +- lm3s8962 +- lm4f232 + +------ + +License: unknown-license-reference 或 proprietary-license + +Copyright: Copyright (c) 2005-2011 Texas Instruments Incorporated + +Path: + +- bsp/lm3s8962/Libraries +- bsp/lm3s9b9x/Libraries +- bsp/lm4f232/Libraries + +### lpcxxx + +bsp 列表: + +- lpc408x +- lpc54114-lite +- lpc54608-LPCXpresso +- lpc55sxx + +------ + +License: arm-cortex-mx + +Copyright: Copyright (c) 2009 ARM Limited + +Path: + +- bsp/lpc176x/CMSIS/CM3 +- bsp/lpc178x/CMSIS/CM3 +- bsp/lpc408x/Libraries/CMSIS + +------ + +License: nxp-warranty-disclaimer + +Copyright: Copyright (c) 2011, NXP Semiconductor + +Path: + +- bsp/lpc178x/CMSIS/CM3 +- bsp/lpc178x/drivers +- bsp/lpc408x/Libraries/Device/NXP/LPC407x_8x_177x_8x +- bsp/lpc43xx/Libraries/Device/NXP/LPC43xx + +------ + +License: bsd-new + +Copyright: Copyright (c) 2009 - 2013 ARM Limited + +Path: + +- bsp/lpc176x/CMSIS/CMSI +- bsp/lpc43xx/Libraries/CMSIS +- bsp/lpc5410x/Libraries/CMSIS +- bsp/lpc54608-LPCXpresso/SDK_2.2_LPCXpresso54608 (Copyright 2016-2017 NXP) +- bsp/lpc55sxx/Libraries/LPC55S6X (Copyright 2016-2018 NXP) + +------ + +License: nxp-microcontroller-proprietary + +Copyright: Copyright (c) 2011, NXP Semiconductor + +Path: + +- bsp/lpc408x/Libraries/Drivers +- bsp/lpc5410x/Libraries +- bsp/lpc824/Libraries + +------ + +License: clear-bsd + +Copyright: Copyright 2016-2018 NXP + +Path: + +- bsp/lpc54114-lite/Libraries/devices/LPC54114 + +------ + +License: zlib + +Copyright: Copyright (c) 2013-2014 ARM Ltd. + +Path: + +- bsp/lpc54608-LPCXpresso/SDK_2.2_LPCXpresso54608 + +### maxim + +License: bsd-new + +Copyright: Copyright (c) 2016 Maxim Integrated Products, Inc. + +Path: + +- bsp/maxim/libraries/MAX32660PeriphDriver/CMSIS/Core + +------ + +License: x11-xconsortium + +Copyright: Copyright (c) 2016 Maxim Integrated Products, Inc. + +Path: + +- bsp/maxim/libraries/MAX32660PeriphDriver + +### mb9bf + +bsp 列表: + +- mb9bf500r +- mb9bf506r +- mb9bf568r +- mb9bf618s + +------ + +License: arm-cortex-mx + +Copyright: Copyright (c) 2009-2010 ARM Limited + +Path: + +- bsp/mb9bf500r/CMSIS/core_xx +- bsp/mb9bf506r/CMSIS/core_xx +- bsp/mb9bf506r/libraries/CMSIS +- bsp/mb9bf568r/CMSIS/Include/core_xx + +------ + +License: free-unknown + +Copyright: (c) Fujitsu Semiconductor Europe GmbH + +Path: + +- bsp/mb9bf500r/CMSIS +- sp/mb9bf506r/libraries/Device +- bsp/mb9bf618s/CMSIS/DeviceSupport + +------ + +License: warranty-disclaimer + +Copyright: Copyright (c) 2013 Spansion LLC. + +Path: + +- bsp/mb9bf568r/CMSIS/DeviceSupport + +------ + +License: bsd-new + +Copyright: Copyright (c) 2009 - 2013 ARM LIMITED + +Path: + +- bsp/mb9bf618s/CMSIS/Include + +### mm32 + +bsp 列表: + +- mm32l07x +- mm32l3xx + +------ + +License: bsd-new + +Copyright: Copyright (c) 2009 - 2013 ARM LIMITED + +Path: + +- bsp/mm32l07x/Libraries/CMSIS +- bsp/mm32l3xx/Libraries/CMSIS/IAR_CORE + +------ + +License: st-mcd-2.0 + +Copyright: (c) COPYRIGHT 2017 MindMotion + +Path: + +- bsp/mm32l07x/Libraries/MM32L0xx +- bsp/mm32l3xx/Libraries/MM32L3xx + +### nrf + +bsp 列表: + +- nrf5x +- nrf51822 + +------ + +License: bsd-new + +Copyright: Copyright (c) 2009 - 2013 ARM LIMITED + +Path: + +- bsp/nrf5x/libraries/cmsis +- bsp/nrf51822/Libraries/CMSIS +- bsp/nrf51822/Libraries/nrf51822 (Copyright (c) 2013, Nordic Semiconductor ASA) + +### nuvoton + +License: bsd-new + +Copyright: Copyright (c) 2014 - 2015 Bosch Sensortec GmbH + +Path: + +- bsp/nuvoton/libraries/nu_packages/BMX055/libraries/BMG160_driver +- bsp/nuvoton/libraries/nu_packages/BMX055/libraries/BMM050_driver + +------ + +License: warranty-disclaimer + +Copyright: Copyright (c) 2015 - 2016 Bosch Sensortec GmbH + +Path: + +- bsp/nuvoton/libraries/nu_packages/BMX055/libraries/BMA2x2_driver + +------ + +License: x11-xconsortium + +Copyright: Copyright (c) 2019 Maxim Integrated Products, Inc. + +Path: + +- bsp/nuvoton/libraries/nu_packages/MAX31875/libraries + +### raspberry-pi + +License: mit + +Copyright: Copyright (c) 2018 bzt + +Path: + +- bsp/raspberry-pi/raspi3-64/applications/test + +### raspberry-pico + +License: bsd-new、mit + +Copyright: Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + +Path: bsp/raspberry-pico/libraries/pico-sdk + +### rm48x50 + +License: 未注明 + +Copyright: (c) Texas Instruments 2009-2013 + +Path: + +- bsp/rm48x50/HALCoGen + +### rv32m1_vega + +License: bsd-new + +Copyright: Copyright 2016-2017 NXP + +Path: + +- bsp/rv32m1_vega/ri5cy/board +- bsp/rv32m1_vega/rv32m1_sdk_riscv + +### rx + +License: 未注明 + +Copyright: Copyright, 2011. Renesas Electronics Corporation and Renesas Solutions Corporation + +Path: + +- bsp/rx/RPDL + +### sam7x + +License: bsd-atmel + +Copyright: Copyright (c) 2006, Atmel Corporation + +Copyright: Copyright: Copyright (c) 2006, Atmel Corporation + +Path: + +- bsp/sam7x/drivers + +### samd21 + +License: bsd-new + +Copyright: Copyright (c) 2014-2015 Atmel Corporation + +Path: + +- bsp/samd21/asflib_config +- bsp/samd21/sam_d2x_asflib + +### simulator + +License: bsd-new、bsd-original-uc + +Copyright: Copyright (c) 2006 Paolo Abeni (Italy)、Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 The Regents of the University of California + +Path: + +- bsp/simulator/pcap + +------ + +License: zlib + +Copyright: Copyright (c) 1997-2017 Sam Lantinga + +Path: + +- bsp/simulator/SDL2-2.0.7 + +### smartfusion2 + +License: arm-cortex-mx + +Copyright: Copyright (c) 2009 ARM Limited + +Path: + +- bsp/smartfusion2/CMSIS/core + +### stm32 + +License: bsd-new + +Copyright: + +Path: + +- bsp/stm32/libraries/STM32xxxx_HAL +- bsp/stm32/libraries/templates +- bsp/stm32/stm32_bsp_name/board/CubeMX_Config + +------ + +License: mit + +Copyright: COPYRIGHT 2011 STMicroelectronics + +Path: + +- bsp/stm32/libraries (exclude bsp/stm32/libraries/HAL_Drivers) + +### SYNWIT + +bsp 列表: + +- swm320 +- swm320-lq100 + +------ + +License: st-mcd-2.0 + +Copyright: COPYRIGHT 2012 Synwit Technology + +Path: + +- bsp/swm320/libraries/CMSIS/DeviceSupport +- bsp/swm320-lq100/Libraries/SWM320_StdPeriph_Driver + +------ + +License: bsd-new + +Copyright: Copyright (c) 2009 - 2014 ARM LIMITED + +Path: + +- bsp/swm320/libraries/CMSIS +- bsp/swm320-lq100/Libraries/CMSIS/CoreSupport + +### tm4c + +License: unknown-license-reference(bsd-new) + +Copyright: Copyright (c) 2012-2017 Texas Instruments Incorporated + +Path: + +- bsp/tm4c123bsp/libraries +- bsp/tm4c129x/libraries + +### tms320f28379d + +License: bsd-new + +Copyright: Copyright (c) 2013-2018 Texas Instruments Incorporated - http://www.ti.com + +Path: + +- bsp/tms320f28379d/libraries + +### xplorer4330 + +License: bsd-new + +Copyright: Copyright (c) 2009 - 2013 ARM LIMITED + +Path: + +- bsp/xplorer4330/Libraries/CMSIS/Include + +------ + +License: nxp-warranty-disclaimer + +Copyright: Copyright (c) 2011, NXP Semiconductor + +Path: + +- bsp/xplorer4330/Libraries/Device/NXP/LPC43xx + +### zynqmp-r5-axu4ev + +License: mit + +Copyright: Copyright (c) 2014 - 2020 Xilinx, Inc. + +Path: + +- bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver + From d1ae1bed84abacb139fd2237675b6d248417bd9d Mon Sep 17 00:00:00 2001 From: yangjie Date: Mon, 26 Apr 2021 15:42:57 +0800 Subject: [PATCH 009/255] [bsp][Copyright_Notice]update --- bsp/Copyright_Notice.md | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/bsp/Copyright_Notice.md b/bsp/Copyright_Notice.md index 0f74a9567d..566c558c81 100644 --- a/bsp/Copyright_Notice.md +++ b/bsp/Copyright_Notice.md @@ -125,16 +125,6 @@ Path: - bsp/essemi/es32f0654/libraries/CMSIS/Include - bsp/essemi/es8p508x/libraries/CMSIS -### fh8620 - -License: gpl-2.0-plus - -Copyright: Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd. - -Path: - -- bsp/fh8620 - ### frdm-k64f License: bsd-new @@ -204,26 +194,6 @@ Path: - bsp/gd32103c-eval/Libraries/CMSIS/core - bsp/gd32303e-eval/Libraries/CMSIS/core -### gkipc - -License: gpl-2.0-plus - -Copyright: Copyright (c) 2017 GOKE Microelectronics Co., Ltd. - -Path: - -- bsp/gkipc/drivers - ------- - -License: 未注明 - -Copyright: Copyright 2012 - 2013 (c) GoKe Microelectronics ShangHai Branch - -Path: - -- bsp/gkipc/libraries - ### hc32f4a0 License: bsd-new @@ -247,7 +217,7 @@ Path: ------ -License: bsd-new、robert-hubley、other-permissive、proprietary-license、gpl-2.0 +License: bsd-new、robert-hubley、other-permissive、proprietary-license Copyright: Copyright (c) 2012, Freescale Semiconductor, Inc. @@ -257,7 +227,7 @@ Path: ### imx6ul -License: bsd-new、proprietary-license、robert-hubley、gpl-2.0 +License: bsd-new、proprietary-license、robert-hubley Copyright: Copyright (c) 2012, Freescale Semiconductor, Inc. From f4015029d2f4682783fb26e9aa31588de4377783 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 1 May 2021 14:18:46 +0800 Subject: [PATCH 010/255] =?UTF-8?q?gettimeofday()=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=97=B6=E5=8C=BA=EF=BC=9B=E8=A7=84=E8=8C=83?= =?UTF-8?q?set=5Ftimeval/get=5Ftimeval=E5=87=BD=E6=95=B0=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/libc/compilers/common/time.c | 57 ++++++++++++++----------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c index deda18a560..6a2b5620ad 100644 --- a/components/libc/compilers/common/time.c +++ b/components/libc/compilers/common/time.c @@ -17,6 +17,7 @@ * which found by Rob * 2021-02-12 Meco Man move all of the functions located in to this file * 2021-03-15 Meco Man fixed a bug of leaking memory in asctime() + * 2021-05-01 Meco Man support fixed timezone */ #include @@ -73,18 +74,18 @@ static void num2str(char *c, int i) } /** - * Get time from RTC device (without timezone) + * Get time from RTC device (without timezone, UTC+0) * @param tv: struct timeval - * @return -1 failure; 1 success + * @return the operation status, RT_EOK on successful */ -static int get_timeval(struct timeval *tv) +static rt_err_t get_timeval(struct timeval *tv) { #ifdef RT_USING_RTC static rt_device_t device = RT_NULL; rt_err_t rst = -RT_ERROR; if (tv == RT_NULL) - return -1; + return -RT_EINVAL; /* default is 0 */ tv->tv_sec = 0; @@ -110,22 +111,22 @@ static int get_timeval(struct timeval *tv) { /* LOG_W will cause a recursive printing if ulog timestamp function is enabled */ rt_kprintf("Cannot find a RTC device to provide time!\r\n"); - return -1; + return -RT_ENOSYS; } - return (rst < 0) ? -1 : 1; + return rst; #else /* LOG_W will cause a recursive printing if ulog timestamp function is enabled */ rt_kprintf("Cannot find a RTC device to provide time!\r\n"); - return -1; + return -RT_ENOSYS; #endif /* RT_USING_RTC */ } /** * Set time to RTC device (without timezone) * @param tv: struct timeval - * @return -1 failure; 1 success + * @return the operation status, RT_EOK on successful */ static int set_timeval(struct timeval *tv) { @@ -134,7 +135,7 @@ static int set_timeval(struct timeval *tv) rt_err_t rst = -RT_ERROR; if (tv == RT_NULL) - return -1; + return -RT_EINVAL; /* optimization: find rtc device only first */ if (device == RT_NULL) @@ -155,14 +156,14 @@ static int set_timeval(struct timeval *tv) else { LOG_W("Cannot find a RTC device to provide time!"); - return -1; + return -RT_ENOSYS; } - return (rst < 0) ? -1 : 1; + return rst; #else LOG_W("Cannot find a RTC device to provide time!"); - return -1; + return -RT_ENOSYS; #endif /* RT_USING_RTC */ } @@ -294,7 +295,7 @@ RT_WEAK time_t time(time_t *t) { struct timeval now; - if(get_timeval(&now) > 0) + if(get_timeval(&now) == RT_EOK) { if (t) { @@ -304,7 +305,7 @@ RT_WEAK time_t time(time_t *t) } else { - errno = EFAULT; + rt_set_errno(EFAULT); return ((time_t)-1); } } @@ -322,18 +323,18 @@ int stime(const time_t *t) if (!t) { - errno = EFAULT; + rt_set_errno(EFAULT); return -1; } tv.tv_sec = *t; - if (set_timeval(&tv) > 0) + if (set_timeval(&tv) == RT_EOK) { return 0; } else { - errno = EFAULT; + rt_set_errno(EFAULT); return -1; } } @@ -414,47 +415,53 @@ time_t timegm(struct tm * const t) } RTM_EXPORT(timegm); -/* TODO: timezone */ +/* TODO: Daylight Saving Time */ int gettimeofday(struct timeval *tv, struct timezone *tz) { - if (tv != RT_NULL && get_timeval(tv) > 0) + if(tz != RT_NULL) + { + tz->tz_dsttime = 0; + tz->tz_minuteswest = -(RT_LIBC_FIXED_TIMEZONE * 60); + } + + if (tv != RT_NULL && get_timeval(tv) == RT_EOK) { return 0; } else { - errno = EFAULT; + rt_set_errno(EFAULT); return -1; } } RTM_EXPORT(gettimeofday); -/* TODO: timezone */ +/* TODO: Daylight Saving Time */ int settimeofday(const struct timeval *tv, const struct timezone *tz) { if (tv != RT_NULL) { if(tv->tv_sec >= 0 && tv->tv_usec >= 0) { - if(set_timeval((struct timeval *)tv) > 0) + if(set_timeval((struct timeval *)tv) == RT_EOK) { return 0; } else { - errno = EFAULT; + rt_set_errno(EFAULT); return -1; } } else { - errno = EINVAL; + rt_set_errno(EINVAL); return -1; } } else { - errno = EFAULT; + rt_set_errno(EFAULT); return -1; } } From 6fa385b98743c78b61a72fa5d4ff8ea7be4a31fd Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 1 May 2021 14:23:50 +0800 Subject: [PATCH 011/255] =?UTF-8?q?[time]=20=E8=A1=A5=E5=85=85=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/libc/compilers/common/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c index 6a2b5620ad..388dc52ac3 100644 --- a/components/libc/compilers/common/time.c +++ b/components/libc/compilers/common/time.c @@ -124,11 +124,11 @@ static rt_err_t get_timeval(struct timeval *tv) } /** - * Set time to RTC device (without timezone) + * Set time to RTC device (without timezone, UTC+0) * @param tv: struct timeval * @return the operation status, RT_EOK on successful */ -static int set_timeval(struct timeval *tv) +static rt_err_t set_timeval(struct timeval *tv) { #ifdef RT_USING_RTC static rt_device_t device = RT_NULL; From 47de5265250f76ed1f48f7d1c51beda690a4bd74 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 1 May 2021 16:21:52 +0800 Subject: [PATCH 012/255] =?UTF-8?q?=E7=B2=BE=E7=AE=80settimeofday=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=EF=BC=9B=20=E5=9C=A8Linux=E4=B8=ADsettimeofday?= =?UTF-8?q?=E4=BB=A5=E5=8F=8Agettimeofday=E5=87=BD=E6=95=B0=E7=9A=84?= =?UTF-8?q?=E6=97=B6=E5=8C=BA=E5=8A=9F=E8=83=BD=E5=B7=B2=E7=BB=8F=E8=A2=AB?= =?UTF-8?q?=E5=BA=9F=E5=BC=83=EF=BC=8C=E5=9B=A0=E6=AD=A4=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E4=BA=88=E4=BB=A5=E6=8F=90=E7=A4=BA=E3=80=82?= =?UTF-8?q?=20gettimeofday=E5=AE=9E=E7=8E=B0=E4=BA=86tz=5Fminuteswest?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8Ctz=5Fdsttime=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E6=9C=AA=E5=AE=9E=E7=8E=B0=EF=BC=8C=E6=8C=89=E5=BA=9F=E5=BC=83?= =?UTF-8?q?=E5=A4=84=E7=90=86=EF=BC=9B=20settimeofday=E6=97=B6=E5=8C=BA?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=BA=9F=E5=BC=83=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/libc/compilers/common/time.c | 41 +++++++++++-------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c index 388dc52ac3..50fbe0d5cc 100644 --- a/components/libc/compilers/common/time.c +++ b/components/libc/compilers/common/time.c @@ -124,11 +124,11 @@ static rt_err_t get_timeval(struct timeval *tv) } /** - * Set time to RTC device (without timezone, UTC+0) + * Set time to RTC device (without timezone) * @param tv: struct timeval * @return the operation status, RT_EOK on successful */ -static rt_err_t set_timeval(struct timeval *tv) +static int set_timeval(const struct timeval *tv) { #ifdef RT_USING_RTC static rt_device_t device = RT_NULL; @@ -415,9 +415,13 @@ time_t timegm(struct tm * const t) } RTM_EXPORT(timegm); -/* TODO: Daylight Saving Time */ int gettimeofday(struct timeval *tv, struct timezone *tz) { + /* The use of the timezone structure is obsolete; + * the tz argument should normally be specified as NULL. + * The tz_dsttime field has never been used under Linux. + * Thus, the following is purely of historic interest. + */ if(tz != RT_NULL) { tz->tz_dsttime = 0; @@ -436,32 +440,23 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) } RTM_EXPORT(gettimeofday); -/* TODO: Daylight Saving Time */ int settimeofday(const struct timeval *tv, const struct timezone *tz) { - if (tv != RT_NULL) + /* The use of the timezone structure is obsolete; + * the tz argument should normally be specified as NULL. + * The tz_dsttime field has never been used under Linux. + * Thus, the following is purely of historic interest. + */ + if (tv != RT_NULL + && tv->tv_sec >= 0 + && tv->tv_usec >= 0 + && set_timeval(tv) == RT_EOK) { - if(tv->tv_sec >= 0 && tv->tv_usec >= 0) - { - if(set_timeval((struct timeval *)tv) == RT_EOK) - { - return 0; - } - else - { - rt_set_errno(EFAULT); - return -1; - } - } - else - { - rt_set_errno(EINVAL); - return -1; - } + return 0; } else { - rt_set_errno(EFAULT); + rt_set_errno(EINVAL); return -1; } } From 8ec1a63b2347ce70e9d4bbd6693fd3e73c41be65 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 2 May 2021 09:24:41 +0800 Subject: [PATCH 013/255] =?UTF-8?q?=E5=A2=9E=E5=8A=A0tz=5Fdsttime=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/libc/compilers/common/sys/mman.h | 2 +- components/libc/compilers/common/sys/time.h | 13 +++++++++++++ components/libc/compilers/common/time.c | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/components/libc/compilers/common/sys/mman.h b/components/libc/compilers/common/sys/mman.h index a9235d61f0..2da2ddf716 100644 --- a/components/libc/compilers/common/sys/mman.h +++ b/components/libc/compilers/common/sys/mman.h @@ -16,7 +16,7 @@ extern "C" { #endif #include - + #define MAP_FAILED ((void *) -1) #define MAP_SHARED 0x01 diff --git a/components/libc/compilers/common/sys/time.h b/components/libc/compilers/common/sys/time.h index 24da0b6c77..be453ba276 100644 --- a/components/libc/compilers/common/sys/time.h +++ b/components/libc/compilers/common/sys/time.h @@ -20,6 +20,19 @@ extern "C" { #ifndef _TIMEVAL_DEFINED #define _TIMEVAL_DEFINED + +#define DST_NONE 0 /* not on dst */ +#define DST_USA 1 /* USA style dst */ +#define DST_AUST 2 /* Australian style dst */ +#define DST_WET 3 /* Western European dst */ +#define DST_MET 4 /* Middle European dst */ +#define DST_EET 5 /* Eastern European dst */ +#define DST_CAN 6 /* Canada */ +#define DST_GB 7 /* Great Britain and Eire */ +#define DST_RUM 8 /* Rumania */ +#define DST_TUR 9 /* Turkey */ +#define DST_AUSTALT 10 /* Australian style with shift in 1986 */ + /* * Structure returned by gettimeofday(2) system call, * and used in other calls. diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c index 50fbe0d5cc..8c32ee1ed0 100644 --- a/components/libc/compilers/common/time.c +++ b/components/libc/compilers/common/time.c @@ -424,7 +424,7 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) */ if(tz != RT_NULL) { - tz->tz_dsttime = 0; + tz->tz_dsttime = DST_NONE; tz->tz_minuteswest = -(RT_LIBC_FIXED_TIMEZONE * 60); } From 3f74758f3189e3d126454a6e06d1fb818747a090 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 2 May 2021 09:29:46 +0800 Subject: [PATCH 014/255] =?UTF-8?q?=E5=B0=86=E6=94=B9=E4=B8=BA"s?= =?UTF-8?q?ys/time.h"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/libc/compilers/common/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c index 8c32ee1ed0..d5436e50e3 100644 --- a/components/libc/compilers/common/time.c +++ b/components/libc/compilers/common/time.c @@ -20,7 +20,7 @@ * 2021-05-01 Meco Man support fixed timezone */ -#include +#include "sys/time.h" #include #ifdef RT_USING_DEVICE From 1a55702ccb3f18f354c6f541d12e7a2eaa204569 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 2 May 2021 09:37:22 +0800 Subject: [PATCH 015/255] =?UTF-8?q?=E4=BF=AE=E5=A4=8DDST=5FNONE=20?= =?UTF-8?q?=E7=AD=89=E5=AE=8F=E5=AE=9A=E4=B9=89=E4=BD=8D=E7=BD=AE=E6=94=BE?= =?UTF-8?q?=E9=94=99=E5=AF=BC=E8=87=B4=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/libc/compilers/common/sys/time.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/libc/compilers/common/sys/time.h b/components/libc/compilers/common/sys/time.h index be453ba276..bb1a9c96fd 100644 --- a/components/libc/compilers/common/sys/time.h +++ b/components/libc/compilers/common/sys/time.h @@ -18,9 +18,6 @@ extern "C" { #endif -#ifndef _TIMEVAL_DEFINED -#define _TIMEVAL_DEFINED - #define DST_NONE 0 /* not on dst */ #define DST_USA 1 /* USA style dst */ #define DST_AUST 2 /* Australian style dst */ @@ -33,6 +30,8 @@ extern "C" { #define DST_TUR 9 /* Turkey */ #define DST_AUSTALT 10 /* Australian style with shift in 1986 */ +#ifndef _TIMEVAL_DEFINED +#define _TIMEVAL_DEFINED /* * Structure returned by gettimeofday(2) system call, * and used in other calls. From 8fee8d2c8cd30dea66cb60fa45e89538f2961c35 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 3 May 2021 09:17:46 +0800 Subject: [PATCH 016/255] remove const in set_timeval --- components/libc/compilers/common/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c index d5436e50e3..9996212444 100644 --- a/components/libc/compilers/common/time.c +++ b/components/libc/compilers/common/time.c @@ -128,7 +128,7 @@ static rt_err_t get_timeval(struct timeval *tv) * @param tv: struct timeval * @return the operation status, RT_EOK on successful */ -static int set_timeval(const struct timeval *tv) +static int set_timeval(struct timeval *tv) { #ifdef RT_USING_RTC static rt_device_t device = RT_NULL; @@ -450,7 +450,7 @@ int settimeofday(const struct timeval *tv, const struct timezone *tz) if (tv != RT_NULL && tv->tv_sec >= 0 && tv->tv_usec >= 0 - && set_timeval(tv) == RT_EOK) + && set_timeval((struct timeval *)tv) == RT_EOK) { return 0; } From 4ed550a96cb42c9bd70c254858dd92f0aa9c9bb9 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Mon, 3 May 2021 13:21:47 +0800 Subject: [PATCH 017/255] Bypass controlling commands in touch class to driver. --- components/drivers/touch/touch.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/components/drivers/touch/touch.c b/components/drivers/touch/touch.c index abe2c0fe24..1a747d8669 100644 --- a/components/drivers/touch/touch.c +++ b/components/drivers/touch/touch.c @@ -77,6 +77,8 @@ static void rt_touch_irq_enable(rt_touch_t touch) { rt_pin_irq_enable(touch->config.irq_pin.pin, RT_TRUE); } +#else + touch->ops->touch_control(touch, RT_TOUCH_CTRL_ENABLE_INT, RT_NULL); #endif } @@ -88,6 +90,8 @@ static void rt_touch_irq_disable(rt_touch_t touch) { rt_pin_irq_enable(touch->config.irq_pin.pin, RT_FALSE); } +#else + touch->ops->touch_control(touch, RT_TOUCH_CTRL_DISABLE_INT, RT_NULL); #endif } @@ -144,28 +148,6 @@ static rt_err_t rt_touch_control(rt_device_t dev, int cmd, void *args) switch (cmd) { - case RT_TOUCH_CTRL_GET_ID: - if (args) - { - result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_GET_ID, args); - } - else - { - result = -RT_ERROR; - } - - break; - case RT_TOUCH_CTRL_GET_INFO: - if (args) - { - result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_GET_INFO, args); - } - else - { - result = -RT_ERROR; - } - - break; case RT_TOUCH_CTRL_SET_MODE: result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_MODE, args); @@ -206,8 +188,11 @@ static rt_err_t rt_touch_control(rt_device_t dev, int cmd, void *args) case RT_TOUCH_CTRL_ENABLE_INT: rt_touch_irq_enable(touch); break; + + case RT_TOUCH_CTRL_GET_ID: + case RT_TOUCH_CTRL_GET_INFO: default: - return -RT_ERROR; + return touch->ops->touch_control(touch, cmd, args); } return result; From 787e46c6a3591d133e051f509b7a262a0eee034a Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Tue, 4 May 2021 13:06:24 +0800 Subject: [PATCH 018/255] =?UTF-8?q?[rtc]=E8=B0=83=E6=95=B4rtc=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=E6=A1=86=E6=9E=B6=E5=87=BD=E6=95=B0=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=EF=BC=8C=E5=8A=9F=E8=83=BD=E6=97=A0=E5=BD=B1=E5=93=8D=EF=BC=8C?= =?UTF-8?q?=E4=B8=BA=E5=90=8E=E7=BB=AD=E6=96=B0=E7=9A=84RTC=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=E9=93=BA=E8=B7=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/drivers/include/drivers/rtc.h | 4 + components/drivers/rtc/rtc.c | 120 +++++++++++------------ 2 files changed, 59 insertions(+), 65 deletions(-) diff --git a/components/drivers/include/drivers/rtc.h b/components/drivers/include/drivers/rtc.h index 4845937113..6eda9cbf53 100644 --- a/components/drivers/include/drivers/rtc.h +++ b/components/drivers/include/drivers/rtc.h @@ -11,10 +11,14 @@ #ifndef __RTC_H__ #define __RTC_H__ +#include + rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day); rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second); +#ifdef RTC_SYNC_USING_NTP int rt_soft_rtc_init(void); int rt_rtc_ntp_sync_init(void); +#endif /* RTC_SYNC_USING_NTP */ #endif /* __RTC_H__ */ diff --git a/components/drivers/rtc/rtc.c b/components/drivers/rtc/rtc.c index 98b60f9f95..2c184bad21 100644 --- a/components/drivers/rtc/rtc.c +++ b/components/drivers/rtc/rtc.c @@ -11,24 +11,12 @@ * 2018-02-16 armink add auto sync time by NTP */ -#include +#include #include +#include #include - #ifdef RT_USING_RTC -/* Using NTP auto sync RTC time */ -#ifdef RTC_SYNC_USING_NTP -/* NTP first sync delay time for network connect, unit: second */ -#ifndef RTC_NTP_FIRST_SYNC_DELAY -#define RTC_NTP_FIRST_SYNC_DELAY (30) -#endif -/* NTP sync period, unit: second */ -#ifndef RTC_NTP_SYNC_PERIOD -#define RTC_NTP_SYNC_PERIOD (1L*60L*60L) -#endif -#endif /* RTC_SYNC_USING_NTP */ - /** * Set system date(time not modify, local timezone). * @@ -129,51 +117,8 @@ rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) return ret; } -#ifdef RTC_SYNC_USING_NTP -static void ntp_sync_thread_enrty(void *param) -{ - extern time_t ntp_sync_to_rtc(const char *host_name); - /* first sync delay for network connect */ - rt_thread_delay(RTC_NTP_FIRST_SYNC_DELAY * RT_TICK_PER_SECOND); - - while (1) - { - ntp_sync_to_rtc(NULL); - rt_thread_delay(RTC_NTP_SYNC_PERIOD * RT_TICK_PER_SECOND); - } -} - -int rt_rtc_ntp_sync_init(void) -{ - static rt_bool_t init_ok = RT_FALSE; - rt_thread_t thread; - - if (init_ok) - { - return 0; - } - - thread = rt_thread_create("ntp_sync", ntp_sync_thread_enrty, RT_NULL, 1536, 26, 2); - if (thread) - { - rt_thread_startup(thread); - } - else - { - return -RT_ENOMEM; - } - - init_ok = RT_TRUE; - - return RT_EOK; -} -INIT_COMPONENT_EXPORT(rt_rtc_ntp_sync_init); -#endif /* RTC_SYNC_USING_NTP */ - -#ifdef RT_USING_FINSH +#ifdef FINSH_USING_MSH #include -#include - /** * show date and time (local timezone) */ @@ -184,12 +129,7 @@ void list_date(void) now = time(RT_NULL); rt_kprintf("%.*s\n", 25, ctime(&now)); } -FINSH_FUNCTION_EXPORT(list_date, show date and time (local timezone)) -FINSH_FUNCTION_EXPORT(set_date, set date(local timezone) e.g: set_date(2010,2,28)) -FINSH_FUNCTION_EXPORT(set_time, set time(local timezone) e.g: set_time(23,59,59)) - -#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) /** * get date and time or set (local timezone) [year month day hour min sec] */ @@ -254,7 +194,57 @@ static void date(uint8_t argc, char **argv) } MSH_CMD_EXPORT(list_date, show date and time (local timezone)) MSH_CMD_EXPORT(date, get date and time or set (local timezone) [year month day hour min sec]) +#endif /* FINSH_USING_MSH */ + +/* Using NTP auto sync RTC time */ +#ifdef RTC_SYNC_USING_NTP +/* NTP first sync delay time for network connect, unit: second */ +#ifndef RTC_NTP_FIRST_SYNC_DELAY +#define RTC_NTP_FIRST_SYNC_DELAY (30) +#endif +/* NTP sync period, unit: second */ +#ifndef RTC_NTP_SYNC_PERIOD +#define RTC_NTP_SYNC_PERIOD (1L*60L*60L) +#endif + +static void ntp_sync_thread_enrty(void *param) +{ + extern time_t ntp_sync_to_rtc(const char *host_name); + /* first sync delay for network connect */ + rt_thread_delay(RTC_NTP_FIRST_SYNC_DELAY * RT_TICK_PER_SECOND); + + while (1) + { + ntp_sync_to_rtc(NULL); + rt_thread_delay(RTC_NTP_SYNC_PERIOD * RT_TICK_PER_SECOND); + } +} + +int rt_rtc_ntp_sync_init(void) +{ + static rt_bool_t init_ok = RT_FALSE; + rt_thread_t thread; + + if (init_ok) + { + return 0; + } + + thread = rt_thread_create("ntp_sync", ntp_sync_thread_enrty, RT_NULL, 1536, 26, 2); + if (thread) + { + rt_thread_startup(thread); + } + else + { + return -RT_ENOMEM; + } + + init_ok = RT_TRUE; + + return RT_EOK; +} +INIT_COMPONENT_EXPORT(rt_rtc_ntp_sync_init); +#endif /* RTC_SYNC_USING_NTP */ -#endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */ -#endif /* RT_USING_FINSH */ #endif /* RT_USING_RTC */ From 22513fe86ceed359b0f6bd3ea055b65ff41a92df Mon Sep 17 00:00:00 2001 From: yanmowudi Date: Thu, 6 May 2021 10:10:29 +0800 Subject: [PATCH 019/255] update swm320 libraries --- .../libraries/CMSIS/DeviceSupport/SWM320.h | 6329 +++++++++-------- .../CMSIS/DeviceSupport/system_SWM320.c | 430 +- .../CMSIS/DeviceSupport/system_SWM320.h | 28 +- .../SWM320_StdPeriph_Driver/SWM320_adc.c | 298 +- .../SWM320_StdPeriph_Driver/SWM320_adc.h | 78 +- .../SWM320_StdPeriph_Driver/SWM320_can.c | 96 +- .../SWM320_StdPeriph_Driver/SWM320_can.h | 52 +- .../SWM320_StdPeriph_Driver/SWM320_crc.h | 30 +- .../SWM320_StdPeriph_Driver/SWM320_dma.h | 14 +- .../SWM320_StdPeriph_Driver/SWM320_exti.h | 22 +- .../SWM320_StdPeriph_Driver/SWM320_flash.c | 66 +- .../SWM320_StdPeriph_Driver/SWM320_flash.h | 2 +- .../SWM320_StdPeriph_Driver/SWM320_gpio.c | 2 +- .../SWM320_StdPeriph_Driver/SWM320_gpio.h | 18 +- .../SWM320_StdPeriph_Driver/SWM320_i2c.h | 22 +- .../SWM320_StdPeriph_Driver/SWM320_lcd.c | 119 +- .../SWM320_StdPeriph_Driver/SWM320_lcd.h | 9 +- .../SWM320_StdPeriph_Driver/SWM320_norflash.h | 10 +- .../SWM320_StdPeriph_Driver/SWM320_port.c | 30 +- .../SWM320_StdPeriph_Driver/SWM320_port.h | 8 +- .../SWM320_StdPeriph_Driver/SWM320_pwm.c | 230 +- .../SWM320_StdPeriph_Driver/SWM320_pwm.h | 70 +- .../SWM320_StdPeriph_Driver/SWM320_rtc.c | 284 +- .../SWM320_StdPeriph_Driver/SWM320_rtc.h | 14 +- .../SWM320_StdPeriph_Driver/SWM320_sdio.c | 164 +- .../SWM320_StdPeriph_Driver/SWM320_sdio.h | 16 +- .../SWM320_StdPeriph_Driver/SWM320_sdram.c | 46 +- .../SWM320_StdPeriph_Driver/SWM320_sdram.h | 16 +- .../SWM320_StdPeriph_Driver/SWM320_spi.c | 406 +- .../SWM320_StdPeriph_Driver/SWM320_spi.h | 42 +- .../SWM320_StdPeriph_Driver/SWM320_sram.c | 26 +- .../SWM320_StdPeriph_Driver/SWM320_sram.h | 4 +- .../SWM320_StdPeriph_Driver/SWM320_timr.c | 182 +- .../SWM320_StdPeriph_Driver/SWM320_timr.h | 24 +- .../SWM320_StdPeriph_Driver/SWM320_uart.c | 368 +- .../SWM320_StdPeriph_Driver/SWM320_uart.h | 32 +- .../SWM320_StdPeriph_Driver/SWM320_wdt.c | 88 +- .../SWM320_StdPeriph_Driver/SWM320_wdt.h | 14 +- 38 files changed, 4840 insertions(+), 4849 deletions(-) diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h b/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h index 55eb7812f0..4ac927b7b9 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h @@ -8,83 +8,83 @@ */ typedef enum IRQn { - /****** Cortex-M0 Processor Exceptions Numbers **********************************************/ - NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ - MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */ - BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */ - UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */ - SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */ - DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */ - PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */ - SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */ - - /****** Cortex-M4 specific Interrupt Numbers ************************************************/ - GPIOA0_IRQn = 0, - GPIOA1_IRQn = 1, - GPIOA2_IRQn = 2, - GPIOA3_IRQn = 3, - GPIOA4_IRQn = 4, - GPIOA5_IRQn = 5, - GPIOA6_IRQn = 6, - GPIOA7_IRQn = 7, - GPIOB0_IRQn = 8, - GPIOB1_IRQn = 9, - GPIOB2_IRQn = 10, - GPIOB3_IRQn = 11, - GPIOB4_IRQn = 12, - GPIOB5_IRQn = 13, - GPIOB6_IRQn = 14, - GPIOB7_IRQn = 15, - GPIOC0_IRQn = 16, - GPIOC1_IRQn = 17, - GPIOC2_IRQn = 18, - GPIOC3_IRQn = 19, - GPIOC4_IRQn = 20, - GPIOC5_IRQn = 21, - GPIOC6_IRQn = 22, - GPIOC7_IRQn = 23, - GPIOM0_IRQn = 24, - GPIOM1_IRQn = 25, - GPIOM2_IRQn = 26, - GPIOM3_IRQn = 27, - GPIOM4_IRQn = 28, - GPIOM5_IRQn = 29, - GPIOM6_IRQn = 30, - GPIOM7_IRQn = 31, - DMA_IRQn = 32, - LCD_IRQn = 33, - NORFLC_IRQn = 34, - CAN_IRQn = 35, - PULSE_IRQn = 36, - WDT_IRQn = 37, - PWM_IRQn = 38, - UART0_IRQn = 39, - UART1_IRQn = 40, - UART2_IRQn = 41, - UART3_IRQn = 42, - UART4_IRQn = 43, - I2C0_IRQn = 44, - I2C1_IRQn = 45, - SPI0_IRQn = 46, - ADC0_IRQn = 47, - RTC_IRQn = 48, - BOD_IRQn = 49, - SDIO_IRQn = 50, - GPIOA_IRQn = 51, - GPIOB_IRQn = 52, - GPIOC_IRQn = 53, - GPIOM_IRQn = 54, - GPION_IRQn = 55, - GPIOP_IRQn = 56, - ADC1_IRQn = 57, - FPU_IRQn = 58, - SPI1_IRQn = 59, - TIMR0_IRQn = 60, - TIMR1_IRQn = 61, - TIMR2_IRQn = 62, - TIMR3_IRQn = 63, - TIMR4_IRQn = 64, - TIMR5_IRQn = 65, +/****** Cortex-M0 Processor Exceptions Numbers **********************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */ + +/****** Cortex-M4 specific Interrupt Numbers ************************************************/ + GPIOA0_IRQn = 0, + GPIOA1_IRQn = 1, + GPIOA2_IRQn = 2, + GPIOA3_IRQn = 3, + GPIOA4_IRQn = 4, + GPIOA5_IRQn = 5, + GPIOA6_IRQn = 6, + GPIOA7_IRQn = 7, + GPIOB0_IRQn = 8, + GPIOB1_IRQn = 9, + GPIOB2_IRQn = 10, + GPIOB3_IRQn = 11, + GPIOB4_IRQn = 12, + GPIOB5_IRQn = 13, + GPIOB6_IRQn = 14, + GPIOB7_IRQn = 15, + GPIOC0_IRQn = 16, + GPIOC1_IRQn = 17, + GPIOC2_IRQn = 18, + GPIOC3_IRQn = 19, + GPIOC4_IRQn = 20, + GPIOC5_IRQn = 21, + GPIOC6_IRQn = 22, + GPIOC7_IRQn = 23, + GPIOM0_IRQn = 24, + GPIOM1_IRQn = 25, + GPIOM2_IRQn = 26, + GPIOM3_IRQn = 27, + GPIOM4_IRQn = 28, + GPIOM5_IRQn = 29, + GPIOM6_IRQn = 30, + GPIOM7_IRQn = 31, + DMA_IRQn = 32, + LCD_IRQn = 33, + NORFLC_IRQn = 34, + CAN_IRQn = 35, + PULSE_IRQn = 36, + WDT_IRQn = 37, + PWM_IRQn = 38, + UART0_IRQn = 39, + UART1_IRQn = 40, + UART2_IRQn = 41, + UART3_IRQn = 42, + UART4_IRQn = 43, + I2C0_IRQn = 44, + I2C1_IRQn = 45, + SPI0_IRQn = 46, + ADC0_IRQn = 47, + RTC_IRQn = 48, + BOD_IRQn = 49, + SDIO_IRQn = 50, + GPIOA_IRQn = 51, + GPIOB_IRQn = 52, + GPIOC_IRQn = 53, + GPIOM_IRQn = 54, + GPION_IRQn = 55, + GPIOP_IRQn = 56, + ADC1_IRQn = 57, + FPU_IRQn = 58, + SPI1_IRQn = 59, + TIMR0_IRQn = 60, + TIMR1_IRQn = 61, + TIMR2_IRQn = 62, + TIMR3_IRQn = 63, + TIMR4_IRQn = 64, + TIMR5_IRQn = 65, } IRQn_Type; /* @@ -94,3454 +94,3512 @@ typedef enum IRQn */ /* Configuration of the Cortex-M0 Processor and Core Peripherals */ -#define __CM4_REV 0x0001 /*!< Core revision r0p1 */ -#define __MPU_PRESENT 1 /*!< SWM320 provides an MPU */ -#define __NVIC_PRIO_BITS 3 /*!< SWM320 uses 3 Bits for the Priority Levels */ -#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ -#define __FPU_PRESENT 0 /*!< FPU present */ +#define __CM4_REV 0x0001 /*!< Core revision r0p1 */ +#define __MPU_PRESENT 1 /*!< SWM320 provides an MPU */ +#define __NVIC_PRIO_BITS 3 /*!< SWM320 uses 3 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 0 /*!< FPU present */ -#if defined(__CC_ARM) -#pragma anon_unions +#if defined ( __CC_ARM ) + #pragma anon_unions #endif #include -#include "core_cm4.h" /* Cortex-M0 processor and core peripherals */ +#include "core_cm4.h" /* Cortex-M0 processor and core peripherals */ #include "system_SWM320.h" + /******************************************************************************/ /* Device Specific Peripheral registers structures */ /******************************************************************************/ -typedef struct -{ - __IO uint32_t CLKSEL; //Clock Select +typedef struct { + __IO uint32_t CLKSEL; //Clock Select - __IO uint32_t CLKDIV; + __IO uint32_t CLKDIV; - __IO uint32_t CLKEN; //Clock Enable + __IO uint32_t CLKEN; //Clock Enable - __IO uint32_t SLEEP; + __IO uint32_t SLEEP; + + uint32_t RESERVED0[6]; + + __IO uint32_t RTCBKP_ISO; //[0] 1 RTCݵԴڸ״̬ 0 RTCݵԴɷ + + __IO uint32_t RTCWKEN; //[0] 1 ʹRTCѹ - uint32_t RESERVED0[6]; + uint32_t RESERVED[52+64]; - __IO uint32_t RTCBKP_ISO; //[0] 1 RTC备份电源域处于隔离状态 0 RTC备份电源域可访问 + __IO uint32_t PAWKEN; //Port A Wakeup Enable + __IO uint32_t PBWKEN; + __IO uint32_t PCWKEN; + + uint32_t RESERVED2[1+4]; - __IO uint32_t RTCWKEN; //[0] 1 使能RTC唤醒功能 + __IO uint32_t PAWKSR; //Port A Wakeup Status Registerд1 + __IO uint32_t PBWKSR; + __IO uint32_t PCWKSR; - uint32_t RESERVED[52 + 64]; + uint32_t RESERVED3[64-10]; - __IO uint32_t PAWKEN; //Port A Wakeup Enable - __IO uint32_t PBWKEN; - __IO uint32_t PCWKEN; + __IO uint32_t RSTCR; //Reset Control Register + __IO uint32_t RSTSR; //Reset Status Register - uint32_t RESERVED2[1 + 4]; - - __IO uint32_t PAWKSR; //Port A Wakeup Status Register,写1清零 - __IO uint32_t PBWKSR; - __IO uint32_t PCWKSR; - - uint32_t RESERVED3[64 - 10]; - - __IO uint32_t RSTCR; //Reset Control Register - __IO uint32_t RSTSR; //Reset Status Register - - uint32_t RESERVED4[61 + 64]; - - __IO uint32_t BKP[3]; //数据备份寄存器 + uint32_t RESERVED4[61+64]; + __IO uint32_t BKP[3]; //ݱݼĴ + //RTC Power Domain: 0x4001E000 - uint32_t RESERVED5[(0x4001E000 - 0x40000508) / 4 - 1]; - - __IO uint32_t RTCBKP[8]; //RTC电源域数据备份寄存器 - - __IO uint32_t LRCCR; //Low speed RC Control Register - __IO uint32_t LRCTRIM0; //Low speed RC Trim + uint32_t RESERVED5[(0x4001E000-0x40000508)/4-1]; + + __IO uint32_t RTCBKP[8]; //RTCԴݱݼĴ + + __IO uint32_t LRCCR; //Low speed RC Control Register + __IO uint32_t LRCTRIM0; //Low speed RC Trim __IO uint32_t LRCTRIM1; - - uint32_t RESERVED6; - - __IO uint32_t RTCLDOTRIM; //RTC Power Domain LDO Trim - + + uint32_t RESERVED6; + + __IO uint32_t RTCLDOTRIM; //RTC Power Domain LDO Trim + //Analog Control: 0x40031000 - uint32_t RESERVED7[(0x40031000 - 0x4001E030) / 4 - 1]; - - __IO uint32_t HRCCR; //High speed RC Control Register - - uint32_t RESERVED8[7]; - + uint32_t RESERVED7[(0x40031000-0x4001E030)/4-1]; + + __IO uint32_t HRCCR; //High speed RC Control Register + + uint32_t RESERVED8[7]; + __IO uint32_t XTALCR; - + __IO uint32_t PLLCR; __IO uint32_t PLLDIV; __IO uint32_t PLLSET; - __IO uint32_t PLLLOCK; //[0] 1 PLL已锁定 - + __IO uint32_t PLLLOCK; //[0] 1 PLL + __IO uint32_t BODIE; __IO uint32_t BODIF; - - __IO uint32_t ADC1IN7; + + __IO uint32_t ADC1IN7; } SYS_TypeDef; -#define SYS_CLKSEL_LFCK_Pos 0 //Low Frequency Clock Source 0 LRC 1 PLL -#define SYS_CLKSEL_LFCK_Msk (0x01 << SYS_CLKSEL_LFCK_Pos) -#define SYS_CLKSEL_HFCK_Pos 1 //High Frequency Clock Source 0 HRC 1 XTAL -#define SYS_CLKSEL_HFCK_Msk (0x01 << SYS_CLKSEL_HFCK_Pos) -#define SYS_CLKSEL_SYS_Pos 2 //系统时钟选择 0 LFCK 1 HFCK -#define SYS_CLKSEL_SYS_Msk (0x01 << SYS_CLKSEL_SYS_Pos) -#define SYS_CLKDIV_SYS_Pos 0 //系统时钟分频 0 1分频 1 2分频 -#define SYS_CLKDIV_SYS_Msk (0x01 << SYS_CLKDIV_SYS_Pos) -#define SYS_CLKDIV_PWM_Pos 1 //PWM 时钟分频 0 1分频 1 8分频 -#define SYS_CLKDIV_PWM_Msk (0x01 << SYS_CLKDIV_PWM_Pos) -#define SYS_CLKDIV_SDRAM_Pos 2 //SDRAM时钟分频 0 1分频 1 2分频 2 4分频 -#define SYS_CLKDIV_SDRAM_Msk (0x03 << SYS_CLKDIV_SDRAM_Pos) -#define SYS_CLKDIV_SDIO_Pos 4 //SDIO时钟分频 0 1分频 1 2分频 2 4分频 3 8分频 -#define SYS_CLKDIV_SDIO_Msk (0x03 << SYS_CLKDIV_SDIO_Pos) +#define SYS_CLKSEL_LFCK_Pos 0 //Low Frequency Clock Source 0 LRC 1 PLL +#define SYS_CLKSEL_LFCK_Msk (0x01 << SYS_CLKSEL_LFCK_Pos) +#define SYS_CLKSEL_HFCK_Pos 1 //High Frequency Clock Source 0 HRC 1 XTAL +#define SYS_CLKSEL_HFCK_Msk (0x01 << SYS_CLKSEL_HFCK_Pos) +#define SYS_CLKSEL_SYS_Pos 2 //ϵͳʱѡ 0 LFCK 1 HFCK +#define SYS_CLKSEL_SYS_Msk (0x01 << SYS_CLKSEL_SYS_Pos) -#define SYS_CLKEN_GPIOA_Pos 0 -#define SYS_CLKEN_GPIOA_Msk (0x01 << SYS_CLKEN_GPIOA_Pos) -#define SYS_CLKEN_GPIOB_Pos 1 -#define SYS_CLKEN_GPIOB_Msk (0x01 << SYS_CLKEN_GPIOB_Pos) -#define SYS_CLKEN_GPIOC_Pos 2 -#define SYS_CLKEN_GPIOC_Msk (0x01 << SYS_CLKEN_GPIOC_Pos) -#define SYS_CLKEN_GPIOM_Pos 4 -#define SYS_CLKEN_GPIOM_Msk (0x01 << SYS_CLKEN_GPIOM_Pos) -#define SYS_CLKEN_GPION_Pos 5 -#define SYS_CLKEN_GPION_Msk (0x01 << SYS_CLKEN_GPION_Pos) -#define SYS_CLKEN_TIMR_Pos 6 -#define SYS_CLKEN_TIMR_Msk (0x01 << SYS_CLKEN_TIMR_Pos) -#define SYS_CLKEN_WDT_Pos 7 -#define SYS_CLKEN_WDT_Msk (0x01 << SYS_CLKEN_WDT_Pos) -#define SYS_CLKEN_ADC0_Pos 8 -#define SYS_CLKEN_ADC0_Msk (0x01 << SYS_CLKEN_ADC0_Pos) -#define SYS_CLKEN_PWM_Pos 9 -#define SYS_CLKEN_PWM_Msk (0x01 << SYS_CLKEN_PWM_Pos) -#define SYS_CLKEN_RTC_Pos 10 -#define SYS_CLKEN_RTC_Msk (0x01 << SYS_CLKEN_RTC_Pos) -#define SYS_CLKEN_UART0_Pos 11 -#define SYS_CLKEN_UART0_Msk (0x01 << SYS_CLKEN_UART0_Pos) -#define SYS_CLKEN_UART1_Pos 12 -#define SYS_CLKEN_UART1_Msk (0x01 << SYS_CLKEN_UART1_Pos) -#define SYS_CLKEN_UART2_Pos 13 -#define SYS_CLKEN_UART2_Msk (0x01 << SYS_CLKEN_UART2_Pos) -#define SYS_CLKEN_UART3_Pos 14 -#define SYS_CLKEN_UART3_Msk (0x01 << SYS_CLKEN_UART3_Pos) -#define SYS_CLKEN_UART4_Pos 15 -#define SYS_CLKEN_UART4_Msk (0x01 << SYS_CLKEN_UART4_Pos) -#define SYS_CLKEN_SPI0_Pos 16 -#define SYS_CLKEN_SPI0_Msk (0x01 << SYS_CLKEN_SPI0_Pos) -#define SYS_CLKEN_I2C0_Pos 17 -#define SYS_CLKEN_I2C0_Msk (0x01 << SYS_CLKEN_I2C0_Pos) -#define SYS_CLKEN_I2C1_Pos 18 -#define SYS_CLKEN_I2C1_Msk (0x01 << SYS_CLKEN_I2C1_Pos) -#define SYS_CLKEN_I2C2_Pos 19 -#define SYS_CLKEN_I2C2_Msk (0x01 << SYS_CLKEN_I2C2_Pos) -#define SYS_CLKEN_LCD_Pos 20 -#define SYS_CLKEN_LCD_Msk (0x01 << SYS_CLKEN_LCD_Pos) -#define SYS_CLKEN_GPIOP_Pos 21 -#define SYS_CLKEN_GPIOP_Msk (0x01 << SYS_CLKEN_GPIOP_Pos) -#define SYS_CLKEN_ANAC_Pos 22 //模拟控制单元时钟使能 -#define SYS_CLKEN_ANAC_Msk (0x01 << SYS_CLKEN_ANAC_Pos) -#define SYS_CLKEN_CRC_Pos 23 -#define SYS_CLKEN_CRC_Msk (0x01 << SYS_CLKEN_CRC_Pos) -#define SYS_CLKEN_RTCBKP_Pos 24 -#define SYS_CLKEN_RTCBKP_Msk (0x01 << SYS_CLKEN_RTCBKP_Pos) -#define SYS_CLKEN_CAN_Pos 25 -#define SYS_CLKEN_CAN_Msk (0x01 << SYS_CLKEN_CAN_Pos) -#define SYS_CLKEN_SDRAM_Pos 26 -#define SYS_CLKEN_SDRAM_Msk (0x01 << SYS_CLKEN_SDRAM_Pos) -#define SYS_CLKEN_NORFL_Pos 27 //NOR Flash -#define SYS_CLKEN_NORFL_Msk (0x01 << SYS_CLKEN_NORFL_Pos) -#define SYS_CLKEN_RAMC_Pos 28 -#define SYS_CLKEN_RAMC_Msk (0x01 << SYS_CLKEN_RAMC_Pos) -#define SYS_CLKEN_SDIO_Pos 29 -#define SYS_CLKEN_SDIO_Msk (0x01 << SYS_CLKEN_SDIO_Pos) -#define SYS_CLKEN_ADC1_Pos 30 -#define SYS_CLKEN_ADC1_Msk (0x01 << SYS_CLKEN_ADC1_Pos) -#define SYS_CLKEN_ALIVE_Pos 31 //CHIPALIVE电源域系统时钟使能 -#define SYS_CLKEN_ALIVE_Msk (0x01 << SYS_CLKEN_ALIVE_Pos) +#define SYS_CLKDIV_SYS_Pos 0 //ϵͳʱӷƵ 0 1Ƶ 1 2Ƶ +#define SYS_CLKDIV_SYS_Msk (0x01 << SYS_CLKDIV_SYS_Pos) +#define SYS_CLKDIV_PWM_Pos 1 //PWM ʱӷƵ 0 1Ƶ 1 8Ƶ +#define SYS_CLKDIV_PWM_Msk (0x01 << SYS_CLKDIV_PWM_Pos) +#define SYS_CLKDIV_SDRAM_Pos 2 //SDRAMʱӷƵ 0 1Ƶ 1 2Ƶ 2 4Ƶ +#define SYS_CLKDIV_SDRAM_Msk (0x03 << SYS_CLKDIV_SDRAM_Pos) +#define SYS_CLKDIV_SDIO_Pos 4 //SDIOʱӷƵ 0 1Ƶ 1 2Ƶ 2 4Ƶ 3 8Ƶ +#define SYS_CLKDIV_SDIO_Msk (0x03 << SYS_CLKDIV_SDIO_Pos) -#define SYS_SLEEP_SLEEP_Pos 0 //将该位置1后,系统将进入SLEEP模式 -#define SYS_SLEEP_SLEEP_Msk (0x01 << SYS_SLEEP_SLEEP_Pos) -#define SYS_SLEEP_DEEP_Pos 1 //将该位置1后,系统将进入STOP SLEEP模式 -#define SYS_SLEEP_DEEP_Msk (0x01 << SYS_SLEEP_DEEP_Pos) +#define SYS_CLKEN_GPIOA_Pos 0 +#define SYS_CLKEN_GPIOA_Msk (0x01 << SYS_CLKEN_GPIOA_Pos) +#define SYS_CLKEN_GPIOB_Pos 1 +#define SYS_CLKEN_GPIOB_Msk (0x01 << SYS_CLKEN_GPIOB_Pos) +#define SYS_CLKEN_GPIOC_Pos 2 +#define SYS_CLKEN_GPIOC_Msk (0x01 << SYS_CLKEN_GPIOC_Pos) +#define SYS_CLKEN_GPIOM_Pos 4 +#define SYS_CLKEN_GPIOM_Msk (0x01 << SYS_CLKEN_GPIOM_Pos) +#define SYS_CLKEN_GPION_Pos 5 +#define SYS_CLKEN_GPION_Msk (0x01 << SYS_CLKEN_GPION_Pos) +#define SYS_CLKEN_TIMR_Pos 6 +#define SYS_CLKEN_TIMR_Msk (0x01 << SYS_CLKEN_TIMR_Pos) +#define SYS_CLKEN_WDT_Pos 7 +#define SYS_CLKEN_WDT_Msk (0x01 << SYS_CLKEN_WDT_Pos) +#define SYS_CLKEN_ADC0_Pos 8 +#define SYS_CLKEN_ADC0_Msk (0x01 << SYS_CLKEN_ADC0_Pos) +#define SYS_CLKEN_PWM_Pos 9 +#define SYS_CLKEN_PWM_Msk (0x01 << SYS_CLKEN_PWM_Pos) +#define SYS_CLKEN_RTC_Pos 10 +#define SYS_CLKEN_RTC_Msk (0x01 << SYS_CLKEN_RTC_Pos) +#define SYS_CLKEN_UART0_Pos 11 +#define SYS_CLKEN_UART0_Msk (0x01 << SYS_CLKEN_UART0_Pos) +#define SYS_CLKEN_UART1_Pos 12 +#define SYS_CLKEN_UART1_Msk (0x01 << SYS_CLKEN_UART1_Pos) +#define SYS_CLKEN_UART2_Pos 13 +#define SYS_CLKEN_UART2_Msk (0x01 << SYS_CLKEN_UART2_Pos) +#define SYS_CLKEN_UART3_Pos 14 +#define SYS_CLKEN_UART3_Msk (0x01 << SYS_CLKEN_UART3_Pos) +#define SYS_CLKEN_UART4_Pos 15 +#define SYS_CLKEN_UART4_Msk (0x01 << SYS_CLKEN_UART4_Pos) +#define SYS_CLKEN_SPI0_Pos 16 +#define SYS_CLKEN_SPI0_Msk (0x01 << SYS_CLKEN_SPI0_Pos) +#define SYS_CLKEN_I2C0_Pos 17 +#define SYS_CLKEN_I2C0_Msk (0x01 << SYS_CLKEN_I2C0_Pos) +#define SYS_CLKEN_I2C1_Pos 18 +#define SYS_CLKEN_I2C1_Msk (0x01 << SYS_CLKEN_I2C1_Pos) +#define SYS_CLKEN_I2C2_Pos 19 +#define SYS_CLKEN_I2C2_Msk (0x01 << SYS_CLKEN_I2C2_Pos) +#define SYS_CLKEN_LCD_Pos 20 +#define SYS_CLKEN_LCD_Msk (0x01 << SYS_CLKEN_LCD_Pos) +#define SYS_CLKEN_GPIOP_Pos 21 +#define SYS_CLKEN_GPIOP_Msk (0x01 << SYS_CLKEN_GPIOP_Pos) +#define SYS_CLKEN_ANAC_Pos 22 //ģƵԪʱʹ +#define SYS_CLKEN_ANAC_Msk (0x01 << SYS_CLKEN_ANAC_Pos) +#define SYS_CLKEN_CRC_Pos 23 +#define SYS_CLKEN_CRC_Msk (0x01 << SYS_CLKEN_CRC_Pos) +#define SYS_CLKEN_RTCBKP_Pos 24 +#define SYS_CLKEN_RTCBKP_Msk (0x01 << SYS_CLKEN_RTCBKP_Pos) +#define SYS_CLKEN_CAN_Pos 25 +#define SYS_CLKEN_CAN_Msk (0x01 << SYS_CLKEN_CAN_Pos) +#define SYS_CLKEN_SDRAM_Pos 26 +#define SYS_CLKEN_SDRAM_Msk (0x01 << SYS_CLKEN_SDRAM_Pos) +#define SYS_CLKEN_NORFL_Pos 27 //NOR Flash +#define SYS_CLKEN_NORFL_Msk (0x01 << SYS_CLKEN_NORFL_Pos) +#define SYS_CLKEN_RAMC_Pos 28 +#define SYS_CLKEN_RAMC_Msk (0x01 << SYS_CLKEN_RAMC_Pos) +#define SYS_CLKEN_SDIO_Pos 29 +#define SYS_CLKEN_SDIO_Msk (0x01 << SYS_CLKEN_SDIO_Pos) +#define SYS_CLKEN_ADC1_Pos 30 +#define SYS_CLKEN_ADC1_Msk (0x01 << SYS_CLKEN_ADC1_Pos) +#define SYS_CLKEN_ALIVE_Pos 31 //CHIPALIVEԴϵͳʱʹ +#define SYS_CLKEN_ALIVE_Msk (0x01 << SYS_CLKEN_ALIVE_Pos) -#define SYS_RSTCR_SYS_Pos 0 //写1进行系统复位,硬件自动清零 -#define SYS_RSTCR_SYS_Msk (0x01 << SYS_RSTCR_SYS_Pos) -#define SYS_RSTCR_FLASH_Pos 1 //写1对FLASH控制器进行一次复位,硬件自动清零 -#define SYS_RSTCR_FLASH_Msk (0x01 << SYS_RSTCR_FLASH_Pos) -#define SYS_RSTCR_PWM_Pos 2 //写1对PWM进行一次复位,硬件自动清零 -#define SYS_RSTCR_PWM_Msk (0x01 << SYS_RSTCR_PWM_Pos) -#define SYS_RSTCR_CPU_Pos 3 //写1对CPU进行一次复位,硬件自动清零 -#define SYS_RSTCR_CPU_Msk (0x01 << SYS_RSTCR_CPU_Pos) -#define SYS_RSTCR_DMA_Pos 4 //写1对DMA进行一次复位,硬件自动清零 -#define SYS_RSTCR_DMA_Msk (0x01 << SYS_RSTCR_DMA_Pos) -#define SYS_RSTCR_NORFLASH_Pos 5 //写1对NOR Flash控制器进行一次复位,硬件自动清零 -#define SYS_RSTCR_NORFLASH_Msk (0x01 << SYS_RSTCR_NORFLASH_Pos) -#define SYS_RSTCR_SRAM_Pos 6 //写1对SRAM控制器进行一次复位,硬件自动清零 -#define SYS_RSTCR_SRAM_Msk (0x01 << SYS_RSTCR_SRAM_Pos) -#define SYS_RSTCR_SDRAM_Pos 7 //写1对SDRAM控制器进行一次复位,硬件自动清零 -#define SYS_RSTCR_SDRAM_Msk (0x01 << SYS_RSTCR_SDRAM_Pos) -#define SYS_RSTCR_SDIO_Pos 8 //写1对SDIO进行一次复位,硬件自动清零 -#define SYS_RSTCR_SDIO_Msk (0x01 << SYS_RSTCR_SDIO_Pos) -#define SYS_RSTCR_LCD_Pos 9 //写1对LCD进行一次复位,硬件自动清零 -#define SYS_RSTCR_LCD_Msk (0x01 << SYS_RSTCR_LCD_Pos) -#define SYS_RSTCR_CAN_Pos 10 //写1对CAN进行一次复位,硬件自动清零 -#define SYS_RSTCR_CAN_Msk (0x01 << SYS_RSTCR_CAN_Pos) +#define SYS_SLEEP_SLEEP_Pos 0 //λ1ϵͳSLEEPģʽ +#define SYS_SLEEP_SLEEP_Msk (0x01 << SYS_SLEEP_SLEEP_Pos) +#define SYS_SLEEP_DEEP_Pos 1 //λ1ϵͳSTOP SLEEPģʽ +#define SYS_SLEEP_DEEP_Msk (0x01 << SYS_SLEEP_DEEP_Pos) -#define SYS_RSTSR_POR_Pos 0 //1 出现过POR复位,写1清零 -#define SYS_RSTSR_POR_Msk (0x01 << SYS_RSTSR_POR_Pos) -#define SYS_RSTSR_BOD_Pos 1 //1 出现过BOD复位,写1清零 -#define SYS_RSTSR_BOD_Msk (0x01 << SYS_RSTSR_BOD_Pos) -#define SYS_RSTSR_PIN_Pos 2 //1 出现过外部引脚复位,写1清零 -#define SYS_RSTSR_PIN_Msk (0x01 << SYS_RSTSR_PIN_Pos) -#define SYS_RSTSR_WDT_Pos 3 //1 出现过WDT复位,写1清零 -#define SYS_RSTSR_WDT_Msk (0x01 << SYS_RSTSR_WDT_Pos) -#define SYS_RSTSR_SWRST_Pos 4 //Software Reset, 1 出现过软件复位,写1清零 -#define SYS_RSTSR_SWRST_Msk (0x01 << SYS_RSTSR_SWRST_Pos) +#define SYS_RSTCR_SYS_Pos 0 //д1ϵͳλӲԶ +#define SYS_RSTCR_SYS_Msk (0x01 << SYS_RSTCR_SYS_Pos) +#define SYS_RSTCR_FLASH_Pos 1 //д1FLASHһθλӲԶ +#define SYS_RSTCR_FLASH_Msk (0x01 << SYS_RSTCR_FLASH_Pos) +#define SYS_RSTCR_PWM_Pos 2 //д1PWMһθλӲԶ +#define SYS_RSTCR_PWM_Msk (0x01 << SYS_RSTCR_PWM_Pos) +#define SYS_RSTCR_CPU_Pos 3 //д1CPUһθλӲԶ +#define SYS_RSTCR_CPU_Msk (0x01 << SYS_RSTCR_CPU_Pos) +#define SYS_RSTCR_DMA_Pos 4 //д1DMAһθλӲԶ +#define SYS_RSTCR_DMA_Msk (0x01 << SYS_RSTCR_DMA_Pos) +#define SYS_RSTCR_NORFLASH_Pos 5 //д1NOR FlashһθλӲԶ +#define SYS_RSTCR_NORFLASH_Msk (0x01 << SYS_RSTCR_NORFLASH_Pos) +#define SYS_RSTCR_SRAM_Pos 6 //д1SRAMһθλӲԶ +#define SYS_RSTCR_SRAM_Msk (0x01 << SYS_RSTCR_SRAM_Pos) +#define SYS_RSTCR_SDRAM_Pos 7 //д1SDRAMһθλӲԶ +#define SYS_RSTCR_SDRAM_Msk (0x01 << SYS_RSTCR_SDRAM_Pos) +#define SYS_RSTCR_SDIO_Pos 8 //д1SDIOһθλӲԶ +#define SYS_RSTCR_SDIO_Msk (0x01 << SYS_RSTCR_SDIO_Pos) +#define SYS_RSTCR_LCD_Pos 9 //д1LCDһθλӲԶ +#define SYS_RSTCR_LCD_Msk (0x01 << SYS_RSTCR_LCD_Pos) +#define SYS_RSTCR_CAN_Pos 10 //д1CANһθλӲԶ +#define SYS_RSTCR_CAN_Msk (0x01 << SYS_RSTCR_CAN_Pos) -#define SYS_LRCCR_OFF_Pos 0 //Low Speed RC Off -#define SYS_LRCCR_OFF_Msk (0x01 << SYS_LRCCR_OFF_Pos) +#define SYS_RSTSR_POR_Pos 0 //1 ֹPORλд1 +#define SYS_RSTSR_POR_Msk (0x01 << SYS_RSTSR_POR_Pos) +#define SYS_RSTSR_BOD_Pos 1 //1 ֹBODλд1 +#define SYS_RSTSR_BOD_Msk (0x01 << SYS_RSTSR_BOD_Pos) +#define SYS_RSTSR_PIN_Pos 2 //1 ֹⲿŸλд1 +#define SYS_RSTSR_PIN_Msk (0x01 << SYS_RSTSR_PIN_Pos) +#define SYS_RSTSR_WDT_Pos 3 //1 ֹWDTλд1 +#define SYS_RSTSR_WDT_Msk (0x01 << SYS_RSTSR_WDT_Pos) +#define SYS_RSTSR_SWRST_Pos 4 //Software Reset, 1 ֹλд1 +#define SYS_RSTSR_SWRST_Msk (0x01 << SYS_RSTSR_SWRST_Pos) -#define SYS_LRCTRIM0_R_Pos 0 //LRC粗调控制位 -#define SYS_LRCTRIM0_R_Msk (0x7FFF << SYS_LRCTRIM0_R_Pos) -#define SYS_LRCTRIM0_M_Pos 15 //LRC中调控制位 -#define SYS_LRCTRIM0_M_Msk (0x3F << SYS_LRCTRIM2_M_Pos) -#define SYS_LRCTRIM0_F_Pos 21 //LRC细调控制位 -#define SYS_LRCTRIM0_F_Msk (0x7FF << SYS_LRCTRIM0_F_Pos) +#define SYS_LRCCR_OFF_Pos 0 //Low Speed RC Off +#define SYS_LRCCR_OFF_Msk (0x01 << SYS_LRCCR_OFF_Pos) -#define SYS_LRCTRIM1_U_Pos 0 //LRC U调控制位 -#define SYS_LRCTRIM1_U_Msk (0x7FFF << SYS_LRCTRIM1_U_Pos) +#define SYS_LRCTRIM0_R_Pos 0 //LRCֵλ +#define SYS_LRCTRIM0_R_Msk (0x7FFF << SYS_LRCTRIM0_R_Pos) +#define SYS_LRCTRIM0_M_Pos 15 //LRCеλ +#define SYS_LRCTRIM0_M_Msk (0x3F << SYS_LRCTRIM2_M_Pos) +#define SYS_LRCTRIM0_F_Pos 21 //LRCϸλ +#define SYS_LRCTRIM0_F_Msk (0x7FF << SYS_LRCTRIM0_F_Pos) -#define SYS_HRCCR_DBL_Pos 0 //Double Frequency 0 20MHz 1 40MHz -#define SYS_HRCCR_DBL_Msk (0x01 << SYS_HRCCR_DBL_Pos) -#define SYS_HRCCR_OFF_Pos 1 //High speed RC Off -#define SYS_HRCCR_OFF_Msk (0x01 << SYS_HRCCR_OFF_Pos) +#define SYS_LRCTRIM1_U_Pos 0 //LRC Uλ +#define SYS_LRCTRIM1_U_Msk (0x7FFF << SYS_LRCTRIM1_U_Pos) -#define SYS_XTALCR_EN_Pos 0 -#define SYS_XTALCR_EN_Msk (0x01 << SYS_XTALCR_EN_Pos) -#define SYS_PLLCR_OUTEN_Pos 0 //只能LOCK后设置 -#define SYS_PLLCR_OUTEN_Msk (0x01 << SYS_PLLCR_OUTEN_Pos) -#define SYS_PLLCR_INSEL_Pos 1 //0 XTAL 1 HRC -#define SYS_PLLCR_INSEL_Msk (0x01 << SYS_PLLCR_INSEL_Pos) -#define SYS_PLLCR_OFF_Pos 2 -#define SYS_PLLCR_OFF_Msk (0x01 << SYS_PLLCR_OFF_Pos) +#define SYS_HRCCR_DBL_Pos 0 //Double Frequency 0 20MHz 1 40MHz +#define SYS_HRCCR_DBL_Msk (0x01 << SYS_HRCCR_DBL_Pos) +#define SYS_HRCCR_OFF_Pos 1 //High speed RC Off +#define SYS_HRCCR_OFF_Msk (0x01 << SYS_HRCCR_OFF_Pos) -#define SYS_PLLDIV_FBDIV_Pos 0 //PLL FeedBack分频寄存器 \ - //VCO输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV \ - //PLL输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV / OUTDIV = VCO输出频率 / OUTDIV -#define SYS_PLLDIV_FBDIV_Msk (0x1FF << SYS_PLLDIV_FBDIV_Pos) -#define SYS_PLLDIV_ADDIV_Pos 9 //ADC时钟基(即VCO输出分频后的时钟)经ADDIV分频后作为ADC的转换时钟 -#define SYS_PLLDIV_ADDIV_Msk (0x1F << SYS_PLLDIV_ADDIV_Pos) -#define SYS_PLLDIV_ADVCO_Pos 14 //0 VCO输出16分频作为ADC时钟基 1 VCO输出经过32分频作为ADC时钟基 2 VCO输出经过64分频作为ADC时钟基 -#define SYS_PLLDIV_ADVCO_Msk (0x03 << SYS_PLLDIV_ADVCO_Pos) -#define SYS_PLLDIV_INDIV_Pos 16 //PLL 输入源时钟分频 -#define SYS_PLLDIV_INDIV_Msk (0x1F << SYS_PLLDIV_INDIV_Pos) -#define SYS_PLLDIV_OUTDIV_Pos 24 //PLL 输出分频,0 8分频 1 4分频 0 2分频 -#define SYS_PLLDIV_OUTDIV_Msk (0x03 << SYS_PLLDIV_OUTDIV_Pos) +#define SYS_XTALCR_EN_Pos 0 +#define SYS_XTALCR_EN_Msk (0x01 << SYS_XTALCR_EN_Pos) -#define SYS_PLLSET_LPFBW_Pos 0 //PLL Low Pass Filter Bandwidth -#define SYS_PLLSET_LPFBW_Msk (0x0F << SYS_PLLSET_LPFBW_Pos) -#define SYS_PLLSET_BIASADJ_Pos 4 //PLL Current Bias Adjustment -#define SYS_PLLSET_BIASADJ_Msk (0x03 << SYS_PLLSET_BIASADJ_Pos) -#define SYS_PLLSET_REFVSEL_Pos 6 //PLL Reference Voltage Select -#define SYS_PLLSET_REFVSEL_Msk (0x03 << SYS_PLLSET_REFVSEL_Pos) -#define SYS_PLLSET_CHPADJL_Pos 8 //PLL charge pump LSB current Adjustment -#define SYS_PLLSET_CHPADJL_Msk (0x07 << SYS_PLLSET_CHPADJL_Pos) -#define SYS_PLLSET_CHPADJM_Pos 11 //PLL charge pump MSB current Adjustment -#define SYS_PLLSET_CHPADJM_Msk (0x03 << SYS_PLLSET_CHPADJM_Pos) +#define SYS_PLLCR_OUTEN_Pos 0 //ֻLOCK +#define SYS_PLLCR_OUTEN_Msk (0x01 << SYS_PLLCR_OUTEN_Pos) +#define SYS_PLLCR_INSEL_Pos 1 //0 XTAL 1 HRC +#define SYS_PLLCR_INSEL_Msk (0x01 << SYS_PLLCR_INSEL_Pos) +#define SYS_PLLCR_OFF_Pos 2 +#define SYS_PLLCR_OFF_Msk (0x01 << SYS_PLLCR_OFF_Pos) -#define SYS_BODIE_2V2_Pos 1 //BOD 2.2V等级触发中断使能 -#define SYS_BODIE_2V2_Msk (0x01 << SYS_BODIE_2V2_Pos) +#define SYS_PLLDIV_FBDIV_Pos 0 //PLL FeedBackƵĴ + //VCOƵ = PLLʱ / INDIV * 4 * FBDIV + //PLLƵ = PLLʱ / INDIV * 4 * FBDIV / OUTDIV = VCOƵ / OUTDIV +#define SYS_PLLDIV_FBDIV_Msk (0x1FF << SYS_PLLDIV_FBDIV_Pos) +#define SYS_PLLDIV_ADDIV_Pos 9 //ADCʱӻVCOƵʱӣADDIVƵΪADCתʱ +#define SYS_PLLDIV_ADDIV_Msk (0x1F << SYS_PLLDIV_ADDIV_Pos) +#define SYS_PLLDIV_ADVCO_Pos 14 //0 VCO16ƵΪADCʱӻ 1 VCO32ƵΪADCʱӻ 2 VCO64ƵΪADCʱӻ +#define SYS_PLLDIV_ADVCO_Msk (0x03 << SYS_PLLDIV_ADVCO_Pos) +#define SYS_PLLDIV_INDIV_Pos 16 //PLL ԴʱӷƵ +#define SYS_PLLDIV_INDIV_Msk (0x1F << SYS_PLLDIV_INDIV_Pos) +#define SYS_PLLDIV_OUTDIV_Pos 24 //PLL Ƶ0 8Ƶ 1 4Ƶ 0 2Ƶ +#define SYS_PLLDIV_OUTDIV_Msk (0x03 << SYS_PLLDIV_OUTDIV_Pos) -#define SYS_BODIF_2V2_Pos 1 //BOD 2.2V等级触发中断状态,写1清零 -#define SYS_BODIF_2V2_Msk (0x01 << SYS_BODIF_2V2_Pos) +#define SYS_PLLSET_LPFBW_Pos 0 //PLL Low Pass Filter Bandwidth +#define SYS_PLLSET_LPFBW_Msk (0x0F << SYS_PLLSET_LPFBW_Pos) +#define SYS_PLLSET_BIASADJ_Pos 4 //PLL Current Bias Adjustment +#define SYS_PLLSET_BIASADJ_Msk (0x03 << SYS_PLLSET_BIASADJ_Pos) +#define SYS_PLLSET_REFVSEL_Pos 6 //PLL Reference Voltage Select +#define SYS_PLLSET_REFVSEL_Msk (0x03 << SYS_PLLSET_REFVSEL_Pos) +#define SYS_PLLSET_CHPADJL_Pos 8 //PLL charge pump LSB current Adjustment +#define SYS_PLLSET_CHPADJL_Msk (0x07 << SYS_PLLSET_CHPADJL_Pos) +#define SYS_PLLSET_CHPADJM_Pos 11 //PLL charge pump MSB current Adjustment +#define SYS_PLLSET_CHPADJM_Msk (0x03 << SYS_PLLSET_CHPADJM_Pos) -#define SYS_ADC1IN7_SEL_Pos 0 //ADC1模块模拟通道7,1 温度传感器 2 电池电压 3 RTC电源域BG 4 主电源域BG 5 PDM33 -#define SYS_ADC1IN7_SEL_Msk (0x0F << SYS_ADC1IN7_SEL_Pos) -#define SYS_ADC1IN7_IOON_Pos 4 //ADC1模块模拟通道7所用IO开关 -#define SYS_ADC1IN7_IOON_Msk (0x01 << SYS_ADC1IN7_IOON_Pos) +#define SYS_BODIE_2V2_Pos 1 //BOD 2.2Vȼжʹ +#define SYS_BODIE_2V2_Msk (0x01 << SYS_BODIE_2V2_Pos) -typedef struct -{ - __IO uint32_t PORTA_SEL; //给PORTA_SEL[2n+2:2n]赋相应的值,将PORTA.PINn引脚配置成GPIO、模拟、数字等功能 - //当赋值为PORTA_PINn_FUNMUX时,PORTA.PINn引脚可通过PORTA_MUX寄存器连接到各种数字外设 - __IO uint32_t PORTB_SEL; +#define SYS_BODIF_2V2_Pos 1 //BOD 2.2Vȼж״̬д1 +#define SYS_BODIF_2V2_Msk (0x01 << SYS_BODIF_2V2_Pos) +#define SYS_ADC1IN7_SEL_Pos 0 //ADC1ģģͨ71 ¶ȴ 2 صѹ 3 RTCԴBG 4 ԴBG 5 PDM33 +#define SYS_ADC1IN7_SEL_Msk (0x0F << SYS_ADC1IN7_SEL_Pos) +#define SYS_ADC1IN7_IOON_Pos 4 //ADC1ģģͨ7IO +#define SYS_ADC1IN7_IOON_Msk (0x01 << SYS_ADC1IN7_IOON_Pos) + + + + +typedef struct { + __IO uint32_t PORTA_SEL; //PORTA_SEL[2n+2:2n]ӦֵPORTA.PINnóGPIOģ⡢ֵȹ + //ֵΪPORTA_PINn_FUNMUXʱPORTA.PINnſͨPORTA_MUXĴӵ + __IO uint32_t PORTB_SEL; + __IO uint32_t PORTC_SEL; - - uint32_t RESERVED[5]; - - __IO uint32_t PORTM_SEL0; - + + uint32_t RESERVED[5]; + + __IO uint32_t PORTM_SEL0; + __IO uint32_t PORTM_SEL1; - - uint32_t RESERVED2[2]; - + + uint32_t RESERVED2[2]; + __IO uint32_t PORTN_SEL0; - + __IO uint32_t PORTN_SEL1; - - uint32_t RESERVED3[2]; - + + uint32_t RESERVED3[2]; + __IO uint32_t PORTP_SEL0; - + __IO uint32_t PORTP_SEL1; - - uint32_t RESERVED4[46]; - + + uint32_t RESERVED4[46]; + __IO uint32_t PORTA_MUX0; - + __IO uint32_t PORTA_MUX1; - - uint32_t RESERVED5[2]; - + + uint32_t RESERVED5[2]; + __IO uint32_t PORTB_MUX0; - + __IO uint32_t PORTB_MUX1; - - uint32_t RESERVED6[2]; - + + uint32_t RESERVED6[2]; + __IO uint32_t PORTC_MUX0; - + __IO uint32_t PORTC_MUX1; - - uint32_t RESERVED7[14]; - + + uint32_t RESERVED7[14]; + __IO uint32_t PORTM_MUX0; - + __IO uint32_t PORTM_MUX1; __IO uint32_t PORTM_MUX2; - + __IO uint32_t PORTM_MUX3; - + __IO uint32_t PORTN_MUX0; - + __IO uint32_t PORTN_MUX1; - + __IO uint32_t PORTN_MUX2; - - uint32_t RESERVED8; - + + uint32_t RESERVED8; + __IO uint32_t PORTP_MUX0; - + __IO uint32_t PORTP_MUX1; - + __IO uint32_t PORTP_MUX2; - + __IO uint32_t PORTP_MUX3; - - uint32_t RESERVED9[28]; - - __IO uint32_t PORTA_PULLU; //上拉使能 - - uint32_t RESERVED10[3]; - + + uint32_t RESERVED9[28]; + + __IO uint32_t PORTA_PULLU; //ʹ + + uint32_t RESERVED10[3]; + __IO uint32_t PORTC_PULLU; - - uint32_t RESERVED11[3]; + + uint32_t RESERVED11[3]; __IO uint32_t PORTM_PULLU; - - uint32_t RESERVED12[3]; + + uint32_t RESERVED12[3]; __IO uint32_t PORTP_PULLU; - - uint32_t RESERVED13[51]; - - __IO uint32_t PORTB_PULLD; //下拉使能 - - uint32_t RESERVED14[3]; + + uint32_t RESERVED13[51]; + + __IO uint32_t PORTB_PULLD; //ʹ + + uint32_t RESERVED14[3]; __IO uint32_t PORTD_PULLD; - - uint32_t RESERVED15[3]; + + uint32_t RESERVED15[3]; __IO uint32_t PORTN_PULLD; - - uint32_t RESERVED16[135]; - - __IO uint32_t PORTM_DRIVS; //驱动强度 - - uint32_t RESERVED17[3]; + + uint32_t RESERVED16[135]; + + __IO uint32_t PORTM_DRIVS; //ǿ + + uint32_t RESERVED17[3]; __IO uint32_t PORTN_DRIVS; - - uint32_t RESERVED18[3]; + + uint32_t RESERVED18[3]; __IO uint32_t PORTP_DRIVS; - - uint32_t RESERVED19[39]; - - __IO uint32_t PORTA_INEN; //输入使能 - - uint32_t RESERVED20[3]; - + + uint32_t RESERVED19[39]; + + __IO uint32_t PORTA_INEN; //ʹ + + uint32_t RESERVED20[3]; + __IO uint32_t PORTB_INEN; - - uint32_t RESERVED21[3]; + + uint32_t RESERVED21[3]; __IO uint32_t PORTC_INEN; - - uint32_t RESERVED22[7]; + + uint32_t RESERVED22[7]; __IO uint32_t PORTM_INEN; - - uint32_t RESERVED23[3]; - + + uint32_t RESERVED23[3]; + __IO uint32_t PORTN_INEN; - - uint32_t RESERVED24[3]; + + uint32_t RESERVED24[3]; __IO uint32_t PORTP_INEN; } PORT_TypeDef; -#define PORT_PORTA_PULLU_PIN0_Pos 0 -#define PORT_PORTA_PULLU_PIN0_Msk (0x01 << PORT_PORTA_PULLU_PIN0_Pos) -#define PORT_PORTA_PULLU_PIN1_Pos 1 -#define PORT_PORTA_PULLU_PIN1_Msk (0x01 << PORT_PORTA_PULLU_PIN1_Pos) -#define PORT_PORTA_PULLU_PIN2_Pos 2 -#define PORT_PORTA_PULLU_PIN2_Msk (0x01 << PORT_PORTA_PULLU_PIN2_Pos) -#define PORT_PORTA_PULLU_PIN3_Pos 3 -#define PORT_PORTA_PULLU_PIN3_Msk (0x01 << PORT_PORTA_PULLU_PIN3_Pos) -#define PORT_PORTA_PULLU_PIN4_Pos 4 -#define PORT_PORTA_PULLU_PIN4_Msk (0x01 << PORT_PORTA_PULLU_PIN4_Pos) -#define PORT_PORTA_PULLU_PIN5_Pos 5 -#define PORT_PORTA_PULLU_PIN5_Msk (0x01 << PORT_PORTA_PULLU_PIN5_Pos) -#define PORT_PORTA_PULLU_PIN6_Pos 6 -#define PORT_PORTA_PULLU_PIN6_Msk (0x01 << PORT_PORTA_PULLU_PIN6_Pos) -#define PORT_PORTA_PULLU_PIN7_Pos 7 -#define PORT_PORTA_PULLU_PIN7_Msk (0x01 << PORT_PORTA_PULLU_PIN7_Pos) -#define PORT_PORTA_PULLU_PIN8_Pos 8 -#define PORT_PORTA_PULLU_PIN8_Msk (0x01 << PORT_PORTA_PULLU_PIN8_Pos) -#define PORT_PORTA_PULLU_PIN9_Pos 9 -#define PORT_PORTA_PULLU_PIN9_Msk (0x01 << PORT_PORTA_PULLU_PIN9_Pos) -#define PORT_PORTA_PULLU_PIN10_Pos 10 -#define PORT_PORTA_PULLU_PIN10_Msk (0x01 << PORT_PORTA_PULLU_PIN10_Pos) -#define PORT_PORTA_PULLU_PIN11_Pos 11 -#define PORT_PORTA_PULLU_PIN11_Msk (0x01 << PORT_PORTA_PULLU_PIN11_Pos) -#define PORT_PORTA_PULLU_PIN12_Pos 12 -#define PORT_PORTA_PULLU_PIN12_Msk (0x01 << PORT_PORTA_PULLU_PIN12_Pos) -#define PORT_PORTA_PULLU_PIN13_Pos 13 -#define PORT_PORTA_PULLU_PIN13_Msk (0x01 << PORT_PORTA_PULLU_PIN13_Pos) -#define PORT_PORTA_PULLU_PIN14_Pos 14 -#define PORT_PORTA_PULLU_PIN14_Msk (0x01 << PORT_PORTA_PULLU_PIN14_Pos) -#define PORT_PORTA_PULLU_PIN15_Pos 15 -#define PORT_PORTA_PULLU_PIN15_Msk (0x01 << PORT_PORTA_PULLU_PIN15_Pos) -#define PORT_PORTC_PULLU_PIN0_Pos 0 -#define PORT_PORTC_PULLU_PIN0_Msk (0x01 << PORT_PORTC_PULLU_PIN0_Pos) -#define PORT_PORTC_PULLU_PIN1_Pos 1 -#define PORT_PORTC_PULLU_PIN1_Msk (0x01 << PORT_PORTC_PULLU_PIN1_Pos) -#define PORT_PORTC_PULLU_PIN2_Pos 2 -#define PORT_PORTC_PULLU_PIN2_Msk (0x01 << PORT_PORTC_PULLU_PIN2_Pos) -#define PORT_PORTC_PULLU_PIN3_Pos 3 -#define PORT_PORTC_PULLU_PIN3_Msk (0x01 << PORT_PORTC_PULLU_PIN3_Pos) -#define PORT_PORTC_PULLU_PIN4_Pos 4 -#define PORT_PORTC_PULLU_PIN4_Msk (0x01 << PORT_PORTC_PULLU_PIN4_Pos) -#define PORT_PORTC_PULLU_PIN5_Pos 5 -#define PORT_PORTC_PULLU_PIN5_Msk (0x01 << PORT_PORTC_PULLU_PIN5_Pos) -#define PORT_PORTC_PULLU_PIN6_Pos 6 -#define PORT_PORTC_PULLU_PIN6_Msk (0x01 << PORT_PORTC_PULLU_PIN6_Pos) -#define PORT_PORTC_PULLU_PIN7_Pos 7 -#define PORT_PORTC_PULLU_PIN7_Msk (0x01 << PORT_PORTC_PULLU_PIN7_Pos) -#define PORT_PORTC_PULLU_PIN8_Pos 8 -#define PORT_PORTC_PULLU_PIN8_Msk (0x01 << PORT_PORTC_PULLU_PIN8_Pos) -#define PORT_PORTC_PULLU_PIN9_Pos 9 -#define PORT_PORTC_PULLU_PIN9_Msk (0x01 << PORT_PORTC_PULLU_PIN9_Pos) -#define PORT_PORTC_PULLU_PIN10_Pos 10 -#define PORT_PORTC_PULLU_PIN10_Msk (0x01 << PORT_PORTC_PULLU_PIN10_Pos) -#define PORT_PORTC_PULLU_PIN11_Pos 11 -#define PORT_PORTC_PULLU_PIN11_Msk (0x01 << PORT_PORTC_PULLU_PIN11_Pos) -#define PORT_PORTC_PULLU_PIN12_Pos 12 -#define PORT_PORTC_PULLU_PIN12_Msk (0x01 << PORT_PORTC_PULLU_PIN12_Pos) -#define PORT_PORTC_PULLU_PIN13_Pos 13 -#define PORT_PORTC_PULLU_PIN13_Msk (0x01 << PORT_PORTC_PULLU_PIN13_Pos) -#define PORT_PORTC_PULLU_PIN14_Pos 14 -#define PORT_PORTC_PULLU_PIN14_Msk (0x01 << PORT_PORTC_PULLU_PIN14_Pos) -#define PORT_PORTC_PULLU_PIN15_Pos 15 -#define PORT_PORTC_PULLU_PIN15_Msk (0x01 << PORT_PORTC_PULLU_PIN15_Pos) +#define PORT_PORTA_PULLU_PIN0_Pos 0 +#define PORT_PORTA_PULLU_PIN0_Msk (0x01 << PORT_PORTA_PULLU_PIN0_Pos) +#define PORT_PORTA_PULLU_PIN1_Pos 1 +#define PORT_PORTA_PULLU_PIN1_Msk (0x01 << PORT_PORTA_PULLU_PIN1_Pos) +#define PORT_PORTA_PULLU_PIN2_Pos 2 +#define PORT_PORTA_PULLU_PIN2_Msk (0x01 << PORT_PORTA_PULLU_PIN2_Pos) +#define PORT_PORTA_PULLU_PIN3_Pos 3 +#define PORT_PORTA_PULLU_PIN3_Msk (0x01 << PORT_PORTA_PULLU_PIN3_Pos) +#define PORT_PORTA_PULLU_PIN4_Pos 4 +#define PORT_PORTA_PULLU_PIN4_Msk (0x01 << PORT_PORTA_PULLU_PIN4_Pos) +#define PORT_PORTA_PULLU_PIN5_Pos 5 +#define PORT_PORTA_PULLU_PIN5_Msk (0x01 << PORT_PORTA_PULLU_PIN5_Pos) +#define PORT_PORTA_PULLU_PIN6_Pos 6 +#define PORT_PORTA_PULLU_PIN6_Msk (0x01 << PORT_PORTA_PULLU_PIN6_Pos) +#define PORT_PORTA_PULLU_PIN7_Pos 7 +#define PORT_PORTA_PULLU_PIN7_Msk (0x01 << PORT_PORTA_PULLU_PIN7_Pos) +#define PORT_PORTA_PULLU_PIN8_Pos 8 +#define PORT_PORTA_PULLU_PIN8_Msk (0x01 << PORT_PORTA_PULLU_PIN8_Pos) +#define PORT_PORTA_PULLU_PIN9_Pos 9 +#define PORT_PORTA_PULLU_PIN9_Msk (0x01 << PORT_PORTA_PULLU_PIN9_Pos) +#define PORT_PORTA_PULLU_PIN10_Pos 10 +#define PORT_PORTA_PULLU_PIN10_Msk (0x01 << PORT_PORTA_PULLU_PIN10_Pos) +#define PORT_PORTA_PULLU_PIN11_Pos 11 +#define PORT_PORTA_PULLU_PIN11_Msk (0x01 << PORT_PORTA_PULLU_PIN11_Pos) +#define PORT_PORTA_PULLU_PIN12_Pos 12 +#define PORT_PORTA_PULLU_PIN12_Msk (0x01 << PORT_PORTA_PULLU_PIN12_Pos) +#define PORT_PORTA_PULLU_PIN13_Pos 13 +#define PORT_PORTA_PULLU_PIN13_Msk (0x01 << PORT_PORTA_PULLU_PIN13_Pos) +#define PORT_PORTA_PULLU_PIN14_Pos 14 +#define PORT_PORTA_PULLU_PIN14_Msk (0x01 << PORT_PORTA_PULLU_PIN14_Pos) +#define PORT_PORTA_PULLU_PIN15_Pos 15 +#define PORT_PORTA_PULLU_PIN15_Msk (0x01 << PORT_PORTA_PULLU_PIN15_Pos) -#define PORT_PORTM_PULLU_PIN0_Pos 0 -#define PORT_PORTM_PULLU_PIN0_Msk (0x01 << PORT_PORTM_PULLU_PIN0_Pos) -#define PORT_PORTM_PULLU_PIN1_Pos 1 -#define PORT_PORTM_PULLU_PIN1_Msk (0x01 << PORT_PORTM_PULLU_PIN1_Pos) -#define PORT_PORTM_PULLU_PIN2_Pos 2 -#define PORT_PORTM_PULLU_PIN2_Msk (0x01 << PORT_PORTM_PULLU_PIN2_Pos) -#define PORT_PORTM_PULLU_PIN3_Pos 3 -#define PORT_PORTM_PULLU_PIN3_Msk (0x01 << PORT_PORTM_PULLU_PIN3_Pos) -#define PORT_PORTM_PULLU_PIN4_Pos 4 -#define PORT_PORTM_PULLU_PIN4_Msk (0x01 << PORT_PORTM_PULLU_PIN4_Pos) -#define PORT_PORTM_PULLU_PIN5_Pos 5 -#define PORT_PORTM_PULLU_PIN5_Msk (0x01 << PORT_PORTM_PULLU_PIN5_Pos) -#define PORT_PORTM_PULLU_PIN6_Pos 6 -#define PORT_PORTM_PULLU_PIN6_Msk (0x01 << PORT_PORTM_PULLU_PIN6_Pos) -#define PORT_PORTM_PULLU_PIN7_Pos 7 -#define PORT_PORTM_PULLU_PIN7_Msk (0x01 << PORT_PORTM_PULLU_PIN7_Pos) -#define PORT_PORTM_PULLU_PIN8_Pos 8 -#define PORT_PORTM_PULLU_PIN8_Msk (0x01 << PORT_PORTM_PULLU_PIN8_Pos) -#define PORT_PORTM_PULLU_PIN9_Pos 9 -#define PORT_PORTM_PULLU_PIN9_Msk (0x01 << PORT_PORTM_PULLU_PIN9_Pos) -#define PORT_PORTM_PULLU_PIN10_Pos 10 -#define PORT_PORTM_PULLU_PIN10_Msk (0x01 << PORT_PORTM_PULLU_PIN10_Pos) -#define PORT_PORTM_PULLU_PIN11_Pos 11 -#define PORT_PORTM_PULLU_PIN11_Msk (0x01 << PORT_PORTM_PULLU_PIN11_Pos) -#define PORT_PORTM_PULLU_PIN12_Pos 12 -#define PORT_PORTM_PULLU_PIN12_Msk (0x01 << PORT_PORTM_PULLU_PIN12_Pos) -#define PORT_PORTM_PULLU_PIN13_Pos 13 -#define PORT_PORTM_PULLU_PIN13_Msk (0x01 << PORT_PORTM_PULLU_PIN13_Pos) -#define PORT_PORTM_PULLU_PIN14_Pos 14 -#define PORT_PORTM_PULLU_PIN14_Msk (0x01 << PORT_PORTM_PULLU_PIN14_Pos) -#define PORT_PORTM_PULLU_PIN15_Pos 15 -#define PORT_PORTM_PULLU_PIN15_Msk (0x01 << PORT_PORTM_PULLU_PIN15_Pos) -#define PORT_PORTM_PULLU_PIN16_Pos 16 -#define PORT_PORTM_PULLU_PIN16_Msk (0x01 << PORT_PORTM_PULLU_PIN16_Pos) -#define PORT_PORTM_PULLU_PIN17_Pos 17 -#define PORT_PORTM_PULLU_PIN17_Msk (0x01 << PORT_PORTM_PULLU_PIN17_Pos) -#define PORT_PORTM_PULLU_PIN18_Pos 18 -#define PORT_PORTM_PULLU_PIN18_Msk (0x01 << PORT_PORTM_PULLU_PIN18_Pos) -#define PORT_PORTM_PULLU_PIN19_Pos 19 -#define PORT_PORTM_PULLU_PIN19_Msk (0x01 << PORT_PORTM_PULLU_PIN19_Pos) -#define PORT_PORTM_PULLU_PIN20_Pos 20 -#define PORT_PORTM_PULLU_PIN20_Msk (0x01 << PORT_PORTM_PULLU_PIN20_Pos) -#define PORT_PORTM_PULLU_PIN21_Pos 21 -#define PORT_PORTM_PULLU_PIN21_Msk (0x01 << PORT_PORTM_PULLU_PIN21_Pos) -#define PORT_PORTM_PULLU_PIN22_Pos 22 -#define PORT_PORTM_PULLU_PIN22_Msk (0x01 << PORT_PORTM_PULLU_PIN22_Pos) -#define PORT_PORTM_PULLU_PIN23_Pos 23 -#define PORT_PORTM_PULLU_PIN23_Msk (0x01 << PORT_PORTM_PULLU_PIN23_Pos) +#define PORT_PORTC_PULLU_PIN0_Pos 0 +#define PORT_PORTC_PULLU_PIN0_Msk (0x01 << PORT_PORTC_PULLU_PIN0_Pos) +#define PORT_PORTC_PULLU_PIN1_Pos 1 +#define PORT_PORTC_PULLU_PIN1_Msk (0x01 << PORT_PORTC_PULLU_PIN1_Pos) +#define PORT_PORTC_PULLU_PIN2_Pos 2 +#define PORT_PORTC_PULLU_PIN2_Msk (0x01 << PORT_PORTC_PULLU_PIN2_Pos) +#define PORT_PORTC_PULLU_PIN3_Pos 3 +#define PORT_PORTC_PULLU_PIN3_Msk (0x01 << PORT_PORTC_PULLU_PIN3_Pos) +#define PORT_PORTC_PULLU_PIN4_Pos 4 +#define PORT_PORTC_PULLU_PIN4_Msk (0x01 << PORT_PORTC_PULLU_PIN4_Pos) +#define PORT_PORTC_PULLU_PIN5_Pos 5 +#define PORT_PORTC_PULLU_PIN5_Msk (0x01 << PORT_PORTC_PULLU_PIN5_Pos) +#define PORT_PORTC_PULLU_PIN6_Pos 6 +#define PORT_PORTC_PULLU_PIN6_Msk (0x01 << PORT_PORTC_PULLU_PIN6_Pos) +#define PORT_PORTC_PULLU_PIN7_Pos 7 +#define PORT_PORTC_PULLU_PIN7_Msk (0x01 << PORT_PORTC_PULLU_PIN7_Pos) +#define PORT_PORTC_PULLU_PIN8_Pos 8 +#define PORT_PORTC_PULLU_PIN8_Msk (0x01 << PORT_PORTC_PULLU_PIN8_Pos) +#define PORT_PORTC_PULLU_PIN9_Pos 9 +#define PORT_PORTC_PULLU_PIN9_Msk (0x01 << PORT_PORTC_PULLU_PIN9_Pos) +#define PORT_PORTC_PULLU_PIN10_Pos 10 +#define PORT_PORTC_PULLU_PIN10_Msk (0x01 << PORT_PORTC_PULLU_PIN10_Pos) +#define PORT_PORTC_PULLU_PIN11_Pos 11 +#define PORT_PORTC_PULLU_PIN11_Msk (0x01 << PORT_PORTC_PULLU_PIN11_Pos) +#define PORT_PORTC_PULLU_PIN12_Pos 12 +#define PORT_PORTC_PULLU_PIN12_Msk (0x01 << PORT_PORTC_PULLU_PIN12_Pos) +#define PORT_PORTC_PULLU_PIN13_Pos 13 +#define PORT_PORTC_PULLU_PIN13_Msk (0x01 << PORT_PORTC_PULLU_PIN13_Pos) +#define PORT_PORTC_PULLU_PIN14_Pos 14 +#define PORT_PORTC_PULLU_PIN14_Msk (0x01 << PORT_PORTC_PULLU_PIN14_Pos) +#define PORT_PORTC_PULLU_PIN15_Pos 15 +#define PORT_PORTC_PULLU_PIN15_Msk (0x01 << PORT_PORTC_PULLU_PIN15_Pos) -#define PORT_PORTP_PULLU_PIN0_Pos 0 -#define PORT_PORTP_PULLU_PIN0_Msk (0x01 << PORT_PORTP_PULLU_PIN0_Pos) -#define PORT_PORTP_PULLU_PIN1_Pos 1 -#define PORT_PORTP_PULLU_PIN1_Msk (0x01 << PORT_PORTP_PULLU_PIN1_Pos) -#define PORT_PORTP_PULLU_PIN2_Pos 2 -#define PORT_PORTP_PULLU_PIN2_Msk (0x01 << PORT_PORTP_PULLU_PIN2_Pos) -#define PORT_PORTP_PULLU_PIN3_Pos 3 -#define PORT_PORTP_PULLU_PIN3_Msk (0x01 << PORT_PORTP_PULLU_PIN3_Pos) -#define PORT_PORTP_PULLU_PIN4_Pos 4 -#define PORT_PORTP_PULLU_PIN4_Msk (0x01 << PORT_PORTP_PULLU_PIN4_Pos) -#define PORT_PORTP_PULLU_PIN5_Pos 5 -#define PORT_PORTP_PULLU_PIN5_Msk (0x01 << PORT_PORTP_PULLU_PIN5_Pos) -#define PORT_PORTP_PULLU_PIN6_Pos 6 -#define PORT_PORTP_PULLU_PIN6_Msk (0x01 << PORT_PORTP_PULLU_PIN6_Pos) -#define PORT_PORTP_PULLU_PIN7_Pos 7 -#define PORT_PORTP_PULLU_PIN7_Msk (0x01 << PORT_PORTP_PULLU_PIN7_Pos) -#define PORT_PORTP_PULLU_PIN8_Pos 8 -#define PORT_PORTP_PULLU_PIN8_Msk (0x01 << PORT_PORTP_PULLU_PIN8_Pos) -#define PORT_PORTP_PULLU_PIN9_Pos 9 -#define PORT_PORTP_PULLU_PIN9_Msk (0x01 << PORT_PORTP_PULLU_PIN9_Pos) -#define PORT_PORTP_PULLU_PIN10_Pos 10 -#define PORT_PORTP_PULLU_PIN10_Msk (0x01 << PORT_PORTP_PULLU_PIN10_Pos) -#define PORT_PORTP_PULLU_PIN11_Pos 11 -#define PORT_PORTP_PULLU_PIN11_Msk (0x01 << PORT_PORTP_PULLU_PIN11_Pos) -#define PORT_PORTP_PULLU_PIN12_Pos 12 -#define PORT_PORTP_PULLU_PIN12_Msk (0x01 << PORT_PORTP_PULLU_PIN12_Pos) -#define PORT_PORTP_PULLU_PIN13_Pos 13 -#define PORT_PORTP_PULLU_PIN13_Msk (0x01 << PORT_PORTP_PULLU_PIN13_Pos) -#define PORT_PORTP_PULLU_PIN14_Pos 14 -#define PORT_PORTP_PULLU_PIN14_Msk (0x01 << PORT_PORTP_PULLU_PIN14_Pos) -#define PORT_PORTP_PULLU_PIN15_Pos 15 -#define PORT_PORTP_PULLU_PIN15_Msk (0x01 << PORT_PORTP_PULLU_PIN15_Pos) -#define PORT_PORTP_PULLU_PIN16_Pos 16 -#define PORT_PORTP_PULLU_PIN16_Msk (0x01 << PORT_PORTP_PULLU_PIN16_Pos) -#define PORT_PORTP_PULLU_PIN17_Pos 17 -#define PORT_PORTP_PULLU_PIN17_Msk (0x01 << PORT_PORTP_PULLU_PIN17_Pos) -#define PORT_PORTP_PULLU_PIN18_Pos 18 -#define PORT_PORTP_PULLU_PIN18_Msk (0x01 << PORT_PORTP_PULLU_PIN18_Pos) -#define PORT_PORTP_PULLU_PIN19_Pos 19 -#define PORT_PORTP_PULLU_PIN19_Msk (0x01 << PORT_PORTP_PULLU_PIN19_Pos) -#define PORT_PORTP_PULLU_PIN20_Pos 20 -#define PORT_PORTP_PULLU_PIN20_Msk (0x01 << PORT_PORTP_PULLU_PIN20_Pos) -#define PORT_PORTP_PULLU_PIN21_Pos 21 -#define PORT_PORTP_PULLU_PIN21_Msk (0x01 << PORT_PORTP_PULLU_PIN21_Pos) -#define PORT_PORTP_PULLU_PIN22_Pos 22 -#define PORT_PORTP_PULLU_PIN22_Msk (0x01 << PORT_PORTP_PULLU_PIN22_Pos) -#define PORT_PORTP_PULLU_PIN23_Pos 23 -#define PORT_PORTP_PULLU_PIN23_Msk (0x01 << PORT_PORTP_PULLU_PIN23_Pos) +#define PORT_PORTM_PULLU_PIN0_Pos 0 +#define PORT_PORTM_PULLU_PIN0_Msk (0x01 << PORT_PORTM_PULLU_PIN0_Pos) +#define PORT_PORTM_PULLU_PIN1_Pos 1 +#define PORT_PORTM_PULLU_PIN1_Msk (0x01 << PORT_PORTM_PULLU_PIN1_Pos) +#define PORT_PORTM_PULLU_PIN2_Pos 2 +#define PORT_PORTM_PULLU_PIN2_Msk (0x01 << PORT_PORTM_PULLU_PIN2_Pos) +#define PORT_PORTM_PULLU_PIN3_Pos 3 +#define PORT_PORTM_PULLU_PIN3_Msk (0x01 << PORT_PORTM_PULLU_PIN3_Pos) +#define PORT_PORTM_PULLU_PIN4_Pos 4 +#define PORT_PORTM_PULLU_PIN4_Msk (0x01 << PORT_PORTM_PULLU_PIN4_Pos) +#define PORT_PORTM_PULLU_PIN5_Pos 5 +#define PORT_PORTM_PULLU_PIN5_Msk (0x01 << PORT_PORTM_PULLU_PIN5_Pos) +#define PORT_PORTM_PULLU_PIN6_Pos 6 +#define PORT_PORTM_PULLU_PIN6_Msk (0x01 << PORT_PORTM_PULLU_PIN6_Pos) +#define PORT_PORTM_PULLU_PIN7_Pos 7 +#define PORT_PORTM_PULLU_PIN7_Msk (0x01 << PORT_PORTM_PULLU_PIN7_Pos) +#define PORT_PORTM_PULLU_PIN8_Pos 8 +#define PORT_PORTM_PULLU_PIN8_Msk (0x01 << PORT_PORTM_PULLU_PIN8_Pos) +#define PORT_PORTM_PULLU_PIN9_Pos 9 +#define PORT_PORTM_PULLU_PIN9_Msk (0x01 << PORT_PORTM_PULLU_PIN9_Pos) +#define PORT_PORTM_PULLU_PIN10_Pos 10 +#define PORT_PORTM_PULLU_PIN10_Msk (0x01 << PORT_PORTM_PULLU_PIN10_Pos) +#define PORT_PORTM_PULLU_PIN11_Pos 11 +#define PORT_PORTM_PULLU_PIN11_Msk (0x01 << PORT_PORTM_PULLU_PIN11_Pos) +#define PORT_PORTM_PULLU_PIN12_Pos 12 +#define PORT_PORTM_PULLU_PIN12_Msk (0x01 << PORT_PORTM_PULLU_PIN12_Pos) +#define PORT_PORTM_PULLU_PIN13_Pos 13 +#define PORT_PORTM_PULLU_PIN13_Msk (0x01 << PORT_PORTM_PULLU_PIN13_Pos) +#define PORT_PORTM_PULLU_PIN14_Pos 14 +#define PORT_PORTM_PULLU_PIN14_Msk (0x01 << PORT_PORTM_PULLU_PIN14_Pos) +#define PORT_PORTM_PULLU_PIN15_Pos 15 +#define PORT_PORTM_PULLU_PIN15_Msk (0x01 << PORT_PORTM_PULLU_PIN15_Pos) +#define PORT_PORTM_PULLU_PIN16_Pos 16 +#define PORT_PORTM_PULLU_PIN16_Msk (0x01 << PORT_PORTM_PULLU_PIN16_Pos) +#define PORT_PORTM_PULLU_PIN17_Pos 17 +#define PORT_PORTM_PULLU_PIN17_Msk (0x01 << PORT_PORTM_PULLU_PIN17_Pos) +#define PORT_PORTM_PULLU_PIN18_Pos 18 +#define PORT_PORTM_PULLU_PIN18_Msk (0x01 << PORT_PORTM_PULLU_PIN18_Pos) +#define PORT_PORTM_PULLU_PIN19_Pos 19 +#define PORT_PORTM_PULLU_PIN19_Msk (0x01 << PORT_PORTM_PULLU_PIN19_Pos) +#define PORT_PORTM_PULLU_PIN20_Pos 20 +#define PORT_PORTM_PULLU_PIN20_Msk (0x01 << PORT_PORTM_PULLU_PIN20_Pos) +#define PORT_PORTM_PULLU_PIN21_Pos 21 +#define PORT_PORTM_PULLU_PIN21_Msk (0x01 << PORT_PORTM_PULLU_PIN21_Pos) +#define PORT_PORTM_PULLU_PIN22_Pos 22 +#define PORT_PORTM_PULLU_PIN22_Msk (0x01 << PORT_PORTM_PULLU_PIN22_Pos) +#define PORT_PORTM_PULLU_PIN23_Pos 23 +#define PORT_PORTM_PULLU_PIN23_Msk (0x01 << PORT_PORTM_PULLU_PIN23_Pos) -#define PORT_PORTB_PULLD_PIN0_Pos 0 -#define PORT_PORTB_PULLD_PIN0_Msk (0x01 << PORT_PORTB_PULLD_PIN0_Pos) -#define PORT_PORTB_PULLD_PIN1_Pos 1 -#define PORT_PORTB_PULLD_PIN1_Msk (0x01 << PORT_PORTB_PULLD_PIN1_Pos) -#define PORT_PORTB_PULLD_PIN2_Pos 2 -#define PORT_PORTB_PULLD_PIN2_Msk (0x01 << PORT_PORTB_PULLD_PIN2_Pos) -#define PORT_PORTB_PULLD_PIN3_Pos 3 -#define PORT_PORTB_PULLD_PIN3_Msk (0x01 << PORT_PORTB_PULLD_PIN3_Pos) -#define PORT_PORTB_PULLD_PIN4_Pos 4 -#define PORT_PORTB_PULLD_PIN4_Msk (0x01 << PORT_PORTB_PULLD_PIN4_Pos) -#define PORT_PORTB_PULLD_PIN5_Pos 5 -#define PORT_PORTB_PULLD_PIN5_Msk (0x01 << PORT_PORTB_PULLD_PIN5_Pos) -#define PORT_PORTB_PULLD_PIN6_Pos 6 -#define PORT_PORTB_PULLD_PIN6_Msk (0x01 << PORT_PORTB_PULLD_PIN6_Pos) -#define PORT_PORTB_PULLD_PIN7_Pos 7 -#define PORT_PORTB_PULLD_PIN7_Msk (0x01 << PORT_PORTB_PULLD_PIN7_Pos) -#define PORT_PORTB_PULLD_PIN8_Pos 8 -#define PORT_PORTB_PULLD_PIN8_Msk (0x01 << PORT_PORTB_PULLD_PIN8_Pos) -#define PORT_PORTB_PULLD_PIN9_Pos 9 -#define PORT_PORTB_PULLD_PIN9_Msk (0x01 << PORT_PORTB_PULLD_PIN9_Pos) -#define PORT_PORTB_PULLD_PIN10_Pos 10 -#define PORT_PORTB_PULLD_PIN10_Msk (0x01 << PORT_PORTB_PULLD_PIN10_Pos) -#define PORT_PORTB_PULLD_PIN11_Pos 11 -#define PORT_PORTB_PULLD_PIN11_Msk (0x01 << PORT_PORTB_PULLD_PIN11_Pos) -#define PORT_PORTB_PULLD_PIN12_Pos 12 -#define PORT_PORTB_PULLD_PIN12_Msk (0x01 << PORT_PORTB_PULLD_PIN12_Pos) -#define PORT_PORTB_PULLD_PIN13_Pos 13 -#define PORT_PORTB_PULLD_PIN13_Msk (0x01 << PORT_PORTB_PULLD_PIN13_Pos) -#define PORT_PORTB_PULLD_PIN14_Pos 14 -#define PORT_PORTB_PULLD_PIN14_Msk (0x01 << PORT_PORTB_PULLD_PIN14_Pos) -#define PORT_PORTB_PULLD_PIN15_Pos 15 -#define PORT_PORTB_PULLD_PIN15_Msk (0x01 << PORT_PORTB_PULLD_PIN15_Pos) +#define PORT_PORTP_PULLU_PIN0_Pos 0 +#define PORT_PORTP_PULLU_PIN0_Msk (0x01 << PORT_PORTP_PULLU_PIN0_Pos) +#define PORT_PORTP_PULLU_PIN1_Pos 1 +#define PORT_PORTP_PULLU_PIN1_Msk (0x01 << PORT_PORTP_PULLU_PIN1_Pos) +#define PORT_PORTP_PULLU_PIN2_Pos 2 +#define PORT_PORTP_PULLU_PIN2_Msk (0x01 << PORT_PORTP_PULLU_PIN2_Pos) +#define PORT_PORTP_PULLU_PIN3_Pos 3 +#define PORT_PORTP_PULLU_PIN3_Msk (0x01 << PORT_PORTP_PULLU_PIN3_Pos) +#define PORT_PORTP_PULLU_PIN4_Pos 4 +#define PORT_PORTP_PULLU_PIN4_Msk (0x01 << PORT_PORTP_PULLU_PIN4_Pos) +#define PORT_PORTP_PULLU_PIN5_Pos 5 +#define PORT_PORTP_PULLU_PIN5_Msk (0x01 << PORT_PORTP_PULLU_PIN5_Pos) +#define PORT_PORTP_PULLU_PIN6_Pos 6 +#define PORT_PORTP_PULLU_PIN6_Msk (0x01 << PORT_PORTP_PULLU_PIN6_Pos) +#define PORT_PORTP_PULLU_PIN7_Pos 7 +#define PORT_PORTP_PULLU_PIN7_Msk (0x01 << PORT_PORTP_PULLU_PIN7_Pos) +#define PORT_PORTP_PULLU_PIN8_Pos 8 +#define PORT_PORTP_PULLU_PIN8_Msk (0x01 << PORT_PORTP_PULLU_PIN8_Pos) +#define PORT_PORTP_PULLU_PIN9_Pos 9 +#define PORT_PORTP_PULLU_PIN9_Msk (0x01 << PORT_PORTP_PULLU_PIN9_Pos) +#define PORT_PORTP_PULLU_PIN10_Pos 10 +#define PORT_PORTP_PULLU_PIN10_Msk (0x01 << PORT_PORTP_PULLU_PIN10_Pos) +#define PORT_PORTP_PULLU_PIN11_Pos 11 +#define PORT_PORTP_PULLU_PIN11_Msk (0x01 << PORT_PORTP_PULLU_PIN11_Pos) +#define PORT_PORTP_PULLU_PIN12_Pos 12 +#define PORT_PORTP_PULLU_PIN12_Msk (0x01 << PORT_PORTP_PULLU_PIN12_Pos) +#define PORT_PORTP_PULLU_PIN13_Pos 13 +#define PORT_PORTP_PULLU_PIN13_Msk (0x01 << PORT_PORTP_PULLU_PIN13_Pos) +#define PORT_PORTP_PULLU_PIN14_Pos 14 +#define PORT_PORTP_PULLU_PIN14_Msk (0x01 << PORT_PORTP_PULLU_PIN14_Pos) +#define PORT_PORTP_PULLU_PIN15_Pos 15 +#define PORT_PORTP_PULLU_PIN15_Msk (0x01 << PORT_PORTP_PULLU_PIN15_Pos) +#define PORT_PORTP_PULLU_PIN16_Pos 16 +#define PORT_PORTP_PULLU_PIN16_Msk (0x01 << PORT_PORTP_PULLU_PIN16_Pos) +#define PORT_PORTP_PULLU_PIN17_Pos 17 +#define PORT_PORTP_PULLU_PIN17_Msk (0x01 << PORT_PORTP_PULLU_PIN17_Pos) +#define PORT_PORTP_PULLU_PIN18_Pos 18 +#define PORT_PORTP_PULLU_PIN18_Msk (0x01 << PORT_PORTP_PULLU_PIN18_Pos) +#define PORT_PORTP_PULLU_PIN19_Pos 19 +#define PORT_PORTP_PULLU_PIN19_Msk (0x01 << PORT_PORTP_PULLU_PIN19_Pos) +#define PORT_PORTP_PULLU_PIN20_Pos 20 +#define PORT_PORTP_PULLU_PIN20_Msk (0x01 << PORT_PORTP_PULLU_PIN20_Pos) +#define PORT_PORTP_PULLU_PIN21_Pos 21 +#define PORT_PORTP_PULLU_PIN21_Msk (0x01 << PORT_PORTP_PULLU_PIN21_Pos) +#define PORT_PORTP_PULLU_PIN22_Pos 22 +#define PORT_PORTP_PULLU_PIN22_Msk (0x01 << PORT_PORTP_PULLU_PIN22_Pos) +#define PORT_PORTP_PULLU_PIN23_Pos 23 +#define PORT_PORTP_PULLU_PIN23_Msk (0x01 << PORT_PORTP_PULLU_PIN23_Pos) -#define PORT_PORTN_PULLD_PIN0_Pos 0 -#define PORT_PORTN_PULLD_PIN0_Msk (0x01 << PORT_PORTN_PULLD_PIN0_Pos) -#define PORT_PORTN_PULLD_PIN1_Pos 1 -#define PORT_PORTN_PULLD_PIN1_Msk (0x01 << PORT_PORTN_PULLD_PIN1_Pos) -#define PORT_PORTN_PULLD_PIN2_Pos 2 -#define PORT_PORTN_PULLD_PIN2_Msk (0x01 << PORT_PORTN_PULLD_PIN2_Pos) -#define PORT_PORTN_PULLD_PIN3_Pos 3 -#define PORT_PORTN_PULLD_PIN3_Msk (0x01 << PORT_PORTN_PULLD_PIN3_Pos) -#define PORT_PORTN_PULLD_PIN4_Pos 4 -#define PORT_PORTN_PULLD_PIN4_Msk (0x01 << PORT_PORTN_PULLD_PIN4_Pos) -#define PORT_PORTN_PULLD_PIN5_Pos 5 -#define PORT_PORTN_PULLD_PIN5_Msk (0x01 << PORT_PORTN_PULLD_PIN5_Pos) -#define PORT_PORTN_PULLD_PIN6_Pos 6 -#define PORT_PORTN_PULLD_PIN6_Msk (0x01 << PORT_PORTN_PULLD_PIN6_Pos) -#define PORT_PORTN_PULLD_PIN7_Pos 7 -#define PORT_PORTN_PULLD_PIN7_Msk (0x01 << PORT_PORTN_PULLD_PIN7_Pos) -#define PORT_PORTN_PULLD_PIN8_Pos 8 -#define PORT_PORTN_PULLD_PIN8_Msk (0x01 << PORT_PORTN_PULLD_PIN8_Pos) -#define PORT_PORTN_PULLD_PIN9_Pos 9 -#define PORT_PORTN_PULLD_PIN9_Msk (0x01 << PORT_PORTN_PULLD_PIN9_Pos) -#define PORT_PORTN_PULLD_PIN10_Pos 10 -#define PORT_PORTN_PULLD_PIN10_Msk (0x01 << PORT_PORTN_PULLD_PIN10_Pos) -#define PORT_PORTN_PULLD_PIN11_Pos 11 -#define PORT_PORTN_PULLD_PIN11_Msk (0x01 << PORT_PORTN_PULLD_PIN11_Pos) -#define PORT_PORTN_PULLD_PIN12_Pos 12 -#define PORT_PORTN_PULLD_PIN12_Msk (0x01 << PORT_PORTN_PULLD_PIN12_Pos) -#define PORT_PORTN_PULLD_PIN13_Pos 13 -#define PORT_PORTN_PULLD_PIN13_Msk (0x01 << PORT_PORTN_PULLD_PIN13_Pos) -#define PORT_PORTN_PULLD_PIN14_Pos 14 -#define PORT_PORTN_PULLD_PIN14_Msk (0x01 << PORT_PORTN_PULLD_PIN14_Pos) -#define PORT_PORTN_PULLD_PIN15_Pos 15 -#define PORT_PORTN_PULLD_PIN15_Msk (0x01 << PORT_PORTN_PULLD_PIN15_Pos) -#define PORT_PORTN_PULLD_PIN16_Pos 16 -#define PORT_PORTN_PULLD_PIN16_Msk (0x01 << PORT_PORTN_PULLD_PIN16_Pos) -#define PORT_PORTN_PULLD_PIN17_Pos 17 -#define PORT_PORTN_PULLD_PIN17_Msk (0x01 << PORT_PORTN_PULLD_PIN17_Pos) -#define PORT_PORTN_PULLD_PIN18_Pos 18 -#define PORT_PORTN_PULLD_PIN18_Msk (0x01 << PORT_PORTN_PULLD_PIN18_Pos) -#define PORT_PORTN_PULLD_PIN19_Pos 19 -#define PORT_PORTN_PULLD_PIN19_Msk (0x01 << PORT_PORTN_PULLD_PIN19_Pos) -#define PORT_PORTN_PULLD_PIN20_Pos 20 -#define PORT_PORTN_PULLD_PIN20_Msk (0x01 << PORT_PORTN_PULLD_PIN20_Pos) -#define PORT_PORTN_PULLD_PIN21_Pos 21 -#define PORT_PORTN_PULLD_PIN21_Msk (0x01 << PORT_PORTN_PULLD_PIN21_Pos) -#define PORT_PORTN_PULLD_PIN22_Pos 22 -#define PORT_PORTN_PULLD_PIN22_Msk (0x01 << PORT_PORTN_PULLD_PIN22_Pos) -#define PORT_PORTN_PULLD_PIN23_Pos 23 -#define PORT_PORTN_PULLD_PIN23_Msk (0x01 << PORT_PORTN_PULLD_PIN23_Pos) +#define PORT_PORTB_PULLD_PIN0_Pos 0 +#define PORT_PORTB_PULLD_PIN0_Msk (0x01 << PORT_PORTB_PULLD_PIN0_Pos) +#define PORT_PORTB_PULLD_PIN1_Pos 1 +#define PORT_PORTB_PULLD_PIN1_Msk (0x01 << PORT_PORTB_PULLD_PIN1_Pos) +#define PORT_PORTB_PULLD_PIN2_Pos 2 +#define PORT_PORTB_PULLD_PIN2_Msk (0x01 << PORT_PORTB_PULLD_PIN2_Pos) +#define PORT_PORTB_PULLD_PIN3_Pos 3 +#define PORT_PORTB_PULLD_PIN3_Msk (0x01 << PORT_PORTB_PULLD_PIN3_Pos) +#define PORT_PORTB_PULLD_PIN4_Pos 4 +#define PORT_PORTB_PULLD_PIN4_Msk (0x01 << PORT_PORTB_PULLD_PIN4_Pos) +#define PORT_PORTB_PULLD_PIN5_Pos 5 +#define PORT_PORTB_PULLD_PIN5_Msk (0x01 << PORT_PORTB_PULLD_PIN5_Pos) +#define PORT_PORTB_PULLD_PIN6_Pos 6 +#define PORT_PORTB_PULLD_PIN6_Msk (0x01 << PORT_PORTB_PULLD_PIN6_Pos) +#define PORT_PORTB_PULLD_PIN7_Pos 7 +#define PORT_PORTB_PULLD_PIN7_Msk (0x01 << PORT_PORTB_PULLD_PIN7_Pos) +#define PORT_PORTB_PULLD_PIN8_Pos 8 +#define PORT_PORTB_PULLD_PIN8_Msk (0x01 << PORT_PORTB_PULLD_PIN8_Pos) +#define PORT_PORTB_PULLD_PIN9_Pos 9 +#define PORT_PORTB_PULLD_PIN9_Msk (0x01 << PORT_PORTB_PULLD_PIN9_Pos) +#define PORT_PORTB_PULLD_PIN10_Pos 10 +#define PORT_PORTB_PULLD_PIN10_Msk (0x01 << PORT_PORTB_PULLD_PIN10_Pos) +#define PORT_PORTB_PULLD_PIN11_Pos 11 +#define PORT_PORTB_PULLD_PIN11_Msk (0x01 << PORT_PORTB_PULLD_PIN11_Pos) +#define PORT_PORTB_PULLD_PIN12_Pos 12 +#define PORT_PORTB_PULLD_PIN12_Msk (0x01 << PORT_PORTB_PULLD_PIN12_Pos) +#define PORT_PORTB_PULLD_PIN13_Pos 13 +#define PORT_PORTB_PULLD_PIN13_Msk (0x01 << PORT_PORTB_PULLD_PIN13_Pos) +#define PORT_PORTB_PULLD_PIN14_Pos 14 +#define PORT_PORTB_PULLD_PIN14_Msk (0x01 << PORT_PORTB_PULLD_PIN14_Pos) +#define PORT_PORTB_PULLD_PIN15_Pos 15 +#define PORT_PORTB_PULLD_PIN15_Msk (0x01 << PORT_PORTB_PULLD_PIN15_Pos) -#define PORT_PORTM_DRIVS_PIN0_Pos 0 -#define PORT_PORTM_DRIVS_PIN0_Msk (0x01 << PORT_PORTM_DRIVS_PIN0_Pos) -#define PORT_PORTM_DRIVS_PIN1_Pos 1 -#define PORT_PORTM_DRIVS_PIN1_Msk (0x01 << PORT_PORTM_DRIVS_PIN1_Pos) -#define PORT_PORTM_DRIVS_PIN2_Pos 2 -#define PORT_PORTM_DRIVS_PIN2_Msk (0x01 << PORT_PORTM_DRIVS_PIN2_Pos) -#define PORT_PORTM_DRIVS_PIN3_Pos 3 -#define PORT_PORTM_DRIVS_PIN3_Msk (0x01 << PORT_PORTM_DRIVS_PIN3_Pos) -#define PORT_PORTM_DRIVS_PIN4_Pos 4 -#define PORT_PORTM_DRIVS_PIN4_Msk (0x01 << PORT_PORTM_DRIVS_PIN4_Pos) -#define PORT_PORTM_DRIVS_PIN5_Pos 5 -#define PORT_PORTM_DRIVS_PIN5_Msk (0x01 << PORT_PORTM_DRIVS_PIN5_Pos) -#define PORT_PORTM_DRIVS_PIN6_Pos 6 -#define PORT_PORTM_DRIVS_PIN6_Msk (0x01 << PORT_PORTM_DRIVS_PIN6_Pos) -#define PORT_PORTM_DRIVS_PIN7_Pos 7 -#define PORT_PORTM_DRIVS_PIN7_Msk (0x01 << PORT_PORTM_DRIVS_PIN7_Pos) -#define PORT_PORTM_DRIVS_PIN8_Pos 8 -#define PORT_PORTM_DRIVS_PIN8_Msk (0x01 << PORT_PORTM_DRIVS_PIN8_Pos) -#define PORT_PORTM_DRIVS_PIN9_Pos 9 -#define PORT_PORTM_DRIVS_PIN9_Msk (0x01 << PORT_PORTM_DRIVS_PIN9_Pos) -#define PORT_PORTM_DRIVS_PIN10_Pos 10 -#define PORT_PORTM_DRIVS_PIN10_Msk (0x01 << PORT_PORTM_DRIVS_PIN10_Pos) -#define PORT_PORTM_DRIVS_PIN11_Pos 11 -#define PORT_PORTM_DRIVS_PIN11_Msk (0x01 << PORT_PORTM_DRIVS_PIN11_Pos) -#define PORT_PORTM_DRIVS_PIN12_Pos 12 -#define PORT_PORTM_DRIVS_PIN12_Msk (0x01 << PORT_PORTM_DRIVS_PIN12_Pos) -#define PORT_PORTM_DRIVS_PIN13_Pos 13 -#define PORT_PORTM_DRIVS_PIN13_Msk (0x01 << PORT_PORTM_DRIVS_PIN13_Pos) -#define PORT_PORTM_DRIVS_PIN14_Pos 14 -#define PORT_PORTM_DRIVS_PIN14_Msk (0x01 << PORT_PORTM_DRIVS_PIN14_Pos) -#define PORT_PORTM_DRIVS_PIN15_Pos 15 -#define PORT_PORTM_DRIVS_PIN15_Msk (0x01 << PORT_PORTM_DRIVS_PIN15_Pos) -#define PORT_PORTM_DRIVS_PIN16_Pos 16 -#define PORT_PORTM_DRIVS_PIN16_Msk (0x01 << PORT_PORTM_DRIVS_PIN16_Pos) -#define PORT_PORTM_DRIVS_PIN17_Pos 17 -#define PORT_PORTM_DRIVS_PIN17_Msk (0x01 << PORT_PORTM_DRIVS_PIN17_Pos) -#define PORT_PORTM_DRIVS_PIN18_Pos 18 -#define PORT_PORTM_DRIVS_PIN18_Msk (0x01 << PORT_PORTM_DRIVS_PIN18_Pos) -#define PORT_PORTM_DRIVS_PIN19_Pos 19 -#define PORT_PORTM_DRIVS_PIN19_Msk (0x01 << PORT_PORTM_DRIVS_PIN19_Pos) -#define PORT_PORTM_DRIVS_PIN20_Pos 20 -#define PORT_PORTM_DRIVS_PIN20_Msk (0x01 << PORT_PORTM_DRIVS_PIN20_Pos) -#define PORT_PORTM_DRIVS_PIN21_Pos 21 -#define PORT_PORTM_DRIVS_PIN21_Msk (0x01 << PORT_PORTM_DRIVS_PIN21_Pos) -#define PORT_PORTM_DRIVS_PIN22_Pos 22 -#define PORT_PORTM_DRIVS_PIN22_Msk (0x01 << PORT_PORTM_DRIVS_PIN22_Pos) -#define PORT_PORTM_DRIVS_PIN23_Pos 23 -#define PORT_PORTM_DRIVS_PIN23_Msk (0x01 << PORT_PORTM_DRIVS_PIN23_Pos) +#define PORT_PORTN_PULLD_PIN0_Pos 0 +#define PORT_PORTN_PULLD_PIN0_Msk (0x01 << PORT_PORTN_PULLD_PIN0_Pos) +#define PORT_PORTN_PULLD_PIN1_Pos 1 +#define PORT_PORTN_PULLD_PIN1_Msk (0x01 << PORT_PORTN_PULLD_PIN1_Pos) +#define PORT_PORTN_PULLD_PIN2_Pos 2 +#define PORT_PORTN_PULLD_PIN2_Msk (0x01 << PORT_PORTN_PULLD_PIN2_Pos) +#define PORT_PORTN_PULLD_PIN3_Pos 3 +#define PORT_PORTN_PULLD_PIN3_Msk (0x01 << PORT_PORTN_PULLD_PIN3_Pos) +#define PORT_PORTN_PULLD_PIN4_Pos 4 +#define PORT_PORTN_PULLD_PIN4_Msk (0x01 << PORT_PORTN_PULLD_PIN4_Pos) +#define PORT_PORTN_PULLD_PIN5_Pos 5 +#define PORT_PORTN_PULLD_PIN5_Msk (0x01 << PORT_PORTN_PULLD_PIN5_Pos) +#define PORT_PORTN_PULLD_PIN6_Pos 6 +#define PORT_PORTN_PULLD_PIN6_Msk (0x01 << PORT_PORTN_PULLD_PIN6_Pos) +#define PORT_PORTN_PULLD_PIN7_Pos 7 +#define PORT_PORTN_PULLD_PIN7_Msk (0x01 << PORT_PORTN_PULLD_PIN7_Pos) +#define PORT_PORTN_PULLD_PIN8_Pos 8 +#define PORT_PORTN_PULLD_PIN8_Msk (0x01 << PORT_PORTN_PULLD_PIN8_Pos) +#define PORT_PORTN_PULLD_PIN9_Pos 9 +#define PORT_PORTN_PULLD_PIN9_Msk (0x01 << PORT_PORTN_PULLD_PIN9_Pos) +#define PORT_PORTN_PULLD_PIN10_Pos 10 +#define PORT_PORTN_PULLD_PIN10_Msk (0x01 << PORT_PORTN_PULLD_PIN10_Pos) +#define PORT_PORTN_PULLD_PIN11_Pos 11 +#define PORT_PORTN_PULLD_PIN11_Msk (0x01 << PORT_PORTN_PULLD_PIN11_Pos) +#define PORT_PORTN_PULLD_PIN12_Pos 12 +#define PORT_PORTN_PULLD_PIN12_Msk (0x01 << PORT_PORTN_PULLD_PIN12_Pos) +#define PORT_PORTN_PULLD_PIN13_Pos 13 +#define PORT_PORTN_PULLD_PIN13_Msk (0x01 << PORT_PORTN_PULLD_PIN13_Pos) +#define PORT_PORTN_PULLD_PIN14_Pos 14 +#define PORT_PORTN_PULLD_PIN14_Msk (0x01 << PORT_PORTN_PULLD_PIN14_Pos) +#define PORT_PORTN_PULLD_PIN15_Pos 15 +#define PORT_PORTN_PULLD_PIN15_Msk (0x01 << PORT_PORTN_PULLD_PIN15_Pos) +#define PORT_PORTN_PULLD_PIN16_Pos 16 +#define PORT_PORTN_PULLD_PIN16_Msk (0x01 << PORT_PORTN_PULLD_PIN16_Pos) +#define PORT_PORTN_PULLD_PIN17_Pos 17 +#define PORT_PORTN_PULLD_PIN17_Msk (0x01 << PORT_PORTN_PULLD_PIN17_Pos) +#define PORT_PORTN_PULLD_PIN18_Pos 18 +#define PORT_PORTN_PULLD_PIN18_Msk (0x01 << PORT_PORTN_PULLD_PIN18_Pos) +#define PORT_PORTN_PULLD_PIN19_Pos 19 +#define PORT_PORTN_PULLD_PIN19_Msk (0x01 << PORT_PORTN_PULLD_PIN19_Pos) +#define PORT_PORTN_PULLD_PIN20_Pos 20 +#define PORT_PORTN_PULLD_PIN20_Msk (0x01 << PORT_PORTN_PULLD_PIN20_Pos) +#define PORT_PORTN_PULLD_PIN21_Pos 21 +#define PORT_PORTN_PULLD_PIN21_Msk (0x01 << PORT_PORTN_PULLD_PIN21_Pos) +#define PORT_PORTN_PULLD_PIN22_Pos 22 +#define PORT_PORTN_PULLD_PIN22_Msk (0x01 << PORT_PORTN_PULLD_PIN22_Pos) +#define PORT_PORTN_PULLD_PIN23_Pos 23 +#define PORT_PORTN_PULLD_PIN23_Msk (0x01 << PORT_PORTN_PULLD_PIN23_Pos) -#define PORT_PORTN_DRIVS_PIN0_Pos 0 -#define PORT_PORTN_DRIVS_PIN0_Msk (0x01 << PORT_PORTN_DRIVS_PIN0_Pos) -#define PORT_PORTN_DRIVS_PIN1_Pos 1 -#define PORT_PORTN_DRIVS_PIN1_Msk (0x01 << PORT_PORTN_DRIVS_PIN1_Pos) -#define PORT_PORTN_DRIVS_PIN2_Pos 2 -#define PORT_PORTN_DRIVS_PIN2_Msk (0x01 << PORT_PORTN_DRIVS_PIN2_Pos) -#define PORT_PORTN_DRIVS_PIN3_Pos 3 -#define PORT_PORTN_DRIVS_PIN3_Msk (0x01 << PORT_PORTN_DRIVS_PIN3_Pos) -#define PORT_PORTN_DRIVS_PIN4_Pos 4 -#define PORT_PORTN_DRIVS_PIN4_Msk (0x01 << PORT_PORTN_DRIVS_PIN4_Pos) -#define PORT_PORTN_DRIVS_PIN5_Pos 5 -#define PORT_PORTN_DRIVS_PIN5_Msk (0x01 << PORT_PORTN_DRIVS_PIN5_Pos) -#define PORT_PORTN_DRIVS_PIN6_Pos 6 -#define PORT_PORTN_DRIVS_PIN6_Msk (0x01 << PORT_PORTN_DRIVS_PIN6_Pos) -#define PORT_PORTN_DRIVS_PIN7_Pos 7 -#define PORT_PORTN_DRIVS_PIN7_Msk (0x01 << PORT_PORTN_DRIVS_PIN7_Pos) -#define PORT_PORTN_DRIVS_PIN8_Pos 8 -#define PORT_PORTN_DRIVS_PIN8_Msk (0x01 << PORT_PORTN_DRIVS_PIN8_Pos) -#define PORT_PORTN_DRIVS_PIN9_Pos 9 -#define PORT_PORTN_DRIVS_PIN9_Msk (0x01 << PORT_PORTN_DRIVS_PIN9_Pos) -#define PORT_PORTN_DRIVS_PIN10_Pos 10 -#define PORT_PORTN_DRIVS_PIN10_Msk (0x01 << PORT_PORTN_DRIVS_PIN10_Pos) -#define PORT_PORTN_DRIVS_PIN11_Pos 11 -#define PORT_PORTN_DRIVS_PIN11_Msk (0x01 << PORT_PORTN_DRIVS_PIN11_Pos) -#define PORT_PORTN_DRIVS_PIN12_Pos 12 -#define PORT_PORTN_DRIVS_PIN12_Msk (0x01 << PORT_PORTN_DRIVS_PIN12_Pos) -#define PORT_PORTN_DRIVS_PIN13_Pos 13 -#define PORT_PORTN_DRIVS_PIN13_Msk (0x01 << PORT_PORTN_DRIVS_PIN13_Pos) -#define PORT_PORTN_DRIVS_PIN14_Pos 14 -#define PORT_PORTN_DRIVS_PIN14_Msk (0x01 << PORT_PORTN_DRIVS_PIN14_Pos) -#define PORT_PORTN_DRIVS_PIN15_Pos 15 -#define PORT_PORTN_DRIVS_PIN15_Msk (0x01 << PORT_PORTN_DRIVS_PIN15_Pos) -#define PORT_PORTN_DRIVS_PIN16_Pos 16 -#define PORT_PORTN_DRIVS_PIN16_Msk (0x01 << PORT_PORTN_DRIVS_PIN16_Pos) -#define PORT_PORTN_DRIVS_PIN17_Pos 17 -#define PORT_PORTN_DRIVS_PIN17_Msk (0x01 << PORT_PORTN_DRIVS_PIN17_Pos) -#define PORT_PORTN_DRIVS_PIN18_Pos 18 -#define PORT_PORTN_DRIVS_PIN18_Msk (0x01 << PORT_PORTN_DRIVS_PIN18_Pos) -#define PORT_PORTN_DRIVS_PIN19_Pos 19 -#define PORT_PORTN_DRIVS_PIN19_Msk (0x01 << PORT_PORTN_DRIVS_PIN19_Pos) -#define PORT_PORTN_DRIVS_PIN20_Pos 20 -#define PORT_PORTN_DRIVS_PIN20_Msk (0x01 << PORT_PORTN_DRIVS_PIN20_Pos) -#define PORT_PORTN_DRIVS_PIN21_Pos 21 -#define PORT_PORTN_DRIVS_PIN21_Msk (0x01 << PORT_PORTN_DRIVS_PIN21_Pos) -#define PORT_PORTN_DRIVS_PIN22_Pos 22 -#define PORT_PORTN_DRIVS_PIN22_Msk (0x01 << PORT_PORTN_DRIVS_PIN22_Pos) -#define PORT_PORTN_DRIVS_PIN23_Pos 23 -#define PORT_PORTN_DRIVS_PIN23_Msk (0x01 << PORT_PORTN_DRIVS_PIN23_Pos) +#define PORT_PORTM_DRIVS_PIN0_Pos 0 +#define PORT_PORTM_DRIVS_PIN0_Msk (0x01 << PORT_PORTM_DRIVS_PIN0_Pos) +#define PORT_PORTM_DRIVS_PIN1_Pos 1 +#define PORT_PORTM_DRIVS_PIN1_Msk (0x01 << PORT_PORTM_DRIVS_PIN1_Pos) +#define PORT_PORTM_DRIVS_PIN2_Pos 2 +#define PORT_PORTM_DRIVS_PIN2_Msk (0x01 << PORT_PORTM_DRIVS_PIN2_Pos) +#define PORT_PORTM_DRIVS_PIN3_Pos 3 +#define PORT_PORTM_DRIVS_PIN3_Msk (0x01 << PORT_PORTM_DRIVS_PIN3_Pos) +#define PORT_PORTM_DRIVS_PIN4_Pos 4 +#define PORT_PORTM_DRIVS_PIN4_Msk (0x01 << PORT_PORTM_DRIVS_PIN4_Pos) +#define PORT_PORTM_DRIVS_PIN5_Pos 5 +#define PORT_PORTM_DRIVS_PIN5_Msk (0x01 << PORT_PORTM_DRIVS_PIN5_Pos) +#define PORT_PORTM_DRIVS_PIN6_Pos 6 +#define PORT_PORTM_DRIVS_PIN6_Msk (0x01 << PORT_PORTM_DRIVS_PIN6_Pos) +#define PORT_PORTM_DRIVS_PIN7_Pos 7 +#define PORT_PORTM_DRIVS_PIN7_Msk (0x01 << PORT_PORTM_DRIVS_PIN7_Pos) +#define PORT_PORTM_DRIVS_PIN8_Pos 8 +#define PORT_PORTM_DRIVS_PIN8_Msk (0x01 << PORT_PORTM_DRIVS_PIN8_Pos) +#define PORT_PORTM_DRIVS_PIN9_Pos 9 +#define PORT_PORTM_DRIVS_PIN9_Msk (0x01 << PORT_PORTM_DRIVS_PIN9_Pos) +#define PORT_PORTM_DRIVS_PIN10_Pos 10 +#define PORT_PORTM_DRIVS_PIN10_Msk (0x01 << PORT_PORTM_DRIVS_PIN10_Pos) +#define PORT_PORTM_DRIVS_PIN11_Pos 11 +#define PORT_PORTM_DRIVS_PIN11_Msk (0x01 << PORT_PORTM_DRIVS_PIN11_Pos) +#define PORT_PORTM_DRIVS_PIN12_Pos 12 +#define PORT_PORTM_DRIVS_PIN12_Msk (0x01 << PORT_PORTM_DRIVS_PIN12_Pos) +#define PORT_PORTM_DRIVS_PIN13_Pos 13 +#define PORT_PORTM_DRIVS_PIN13_Msk (0x01 << PORT_PORTM_DRIVS_PIN13_Pos) +#define PORT_PORTM_DRIVS_PIN14_Pos 14 +#define PORT_PORTM_DRIVS_PIN14_Msk (0x01 << PORT_PORTM_DRIVS_PIN14_Pos) +#define PORT_PORTM_DRIVS_PIN15_Pos 15 +#define PORT_PORTM_DRIVS_PIN15_Msk (0x01 << PORT_PORTM_DRIVS_PIN15_Pos) +#define PORT_PORTM_DRIVS_PIN16_Pos 16 +#define PORT_PORTM_DRIVS_PIN16_Msk (0x01 << PORT_PORTM_DRIVS_PIN16_Pos) +#define PORT_PORTM_DRIVS_PIN17_Pos 17 +#define PORT_PORTM_DRIVS_PIN17_Msk (0x01 << PORT_PORTM_DRIVS_PIN17_Pos) +#define PORT_PORTM_DRIVS_PIN18_Pos 18 +#define PORT_PORTM_DRIVS_PIN18_Msk (0x01 << PORT_PORTM_DRIVS_PIN18_Pos) +#define PORT_PORTM_DRIVS_PIN19_Pos 19 +#define PORT_PORTM_DRIVS_PIN19_Msk (0x01 << PORT_PORTM_DRIVS_PIN19_Pos) +#define PORT_PORTM_DRIVS_PIN20_Pos 20 +#define PORT_PORTM_DRIVS_PIN20_Msk (0x01 << PORT_PORTM_DRIVS_PIN20_Pos) +#define PORT_PORTM_DRIVS_PIN21_Pos 21 +#define PORT_PORTM_DRIVS_PIN21_Msk (0x01 << PORT_PORTM_DRIVS_PIN21_Pos) +#define PORT_PORTM_DRIVS_PIN22_Pos 22 +#define PORT_PORTM_DRIVS_PIN22_Msk (0x01 << PORT_PORTM_DRIVS_PIN22_Pos) +#define PORT_PORTM_DRIVS_PIN23_Pos 23 +#define PORT_PORTM_DRIVS_PIN23_Msk (0x01 << PORT_PORTM_DRIVS_PIN23_Pos) -#define PORT_PORTP_DRIVS_PIN0_Pos 0 -#define PORT_PORTP_DRIVS_PIN0_Msk (0x01 << PORT_PORTP_DRIVS_PIN0_Pos) -#define PORT_PORTP_DRIVS_PIN1_Pos 1 -#define PORT_PORTP_DRIVS_PIN1_Msk (0x01 << PORT_PORTP_DRIVS_PIN1_Pos) -#define PORT_PORTP_DRIVS_PIN2_Pos 2 -#define PORT_PORTP_DRIVS_PIN2_Msk (0x01 << PORT_PORTP_DRIVS_PIN2_Pos) -#define PORT_PORTP_DRIVS_PIN3_Pos 3 -#define PORT_PORTP_DRIVS_PIN3_Msk (0x01 << PORT_PORTP_DRIVS_PIN3_Pos) -#define PORT_PORTP_DRIVS_PIN4_Pos 4 -#define PORT_PORTP_DRIVS_PIN4_Msk (0x01 << PORT_PORTP_DRIVS_PIN4_Pos) -#define PORT_PORTP_DRIVS_PIN5_Pos 5 -#define PORT_PORTP_DRIVS_PIN5_Msk (0x01 << PORT_PORTP_DRIVS_PIN5_Pos) -#define PORT_PORTP_DRIVS_PIN6_Pos 6 -#define PORT_PORTP_DRIVS_PIN6_Msk (0x01 << PORT_PORTP_DRIVS_PIN6_Pos) -#define PORT_PORTP_DRIVS_PIN7_Pos 7 -#define PORT_PORTP_DRIVS_PIN7_Msk (0x01 << PORT_PORTP_DRIVS_PIN7_Pos) -#define PORT_PORTP_DRIVS_PIN8_Pos 8 -#define PORT_PORTP_DRIVS_PIN8_Msk (0x01 << PORT_PORTP_DRIVS_PIN8_Pos) -#define PORT_PORTP_DRIVS_PIN9_Pos 9 -#define PORT_PORTP_DRIVS_PIN9_Msk (0x01 << PORT_PORTP_DRIVS_PIN9_Pos) -#define PORT_PORTP_DRIVS_PIN10_Pos 10 -#define PORT_PORTP_DRIVS_PIN10_Msk (0x01 << PORT_PORTP_DRIVS_PIN10_Pos) -#define PORT_PORTP_DRIVS_PIN11_Pos 11 -#define PORT_PORTP_DRIVS_PIN11_Msk (0x01 << PORT_PORTP_DRIVS_PIN11_Pos) -#define PORT_PORTP_DRIVS_PIN12_Pos 12 -#define PORT_PORTP_DRIVS_PIN12_Msk (0x01 << PORT_PORTP_DRIVS_PIN12_Pos) -#define PORT_PORTP_DRIVS_PIN13_Pos 13 -#define PORT_PORTP_DRIVS_PIN13_Msk (0x01 << PORT_PORTP_DRIVS_PIN13_Pos) -#define PORT_PORTP_DRIVS_PIN14_Pos 14 -#define PORT_PORTP_DRIVS_PIN14_Msk (0x01 << PORT_PORTP_DRIVS_PIN14_Pos) -#define PORT_PORTP_DRIVS_PIN15_Pos 15 -#define PORT_PORTP_DRIVS_PIN15_Msk (0x01 << PORT_PORTP_DRIVS_PIN15_Pos) -#define PORT_PORTP_DRIVS_PIN16_Pos 16 -#define PORT_PORTP_DRIVS_PIN16_Msk (0x01 << PORT_PORTP_DRIVS_PIN16_Pos) -#define PORT_PORTP_DRIVS_PIN17_Pos 17 -#define PORT_PORTP_DRIVS_PIN17_Msk (0x01 << PORT_PORTP_DRIVS_PIN17_Pos) -#define PORT_PORTP_DRIVS_PIN18_Pos 18 -#define PORT_PORTP_DRIVS_PIN18_Msk (0x01 << PORT_PORTP_DRIVS_PIN18_Pos) -#define PORT_PORTP_DRIVS_PIN19_Pos 19 -#define PORT_PORTP_DRIVS_PIN19_Msk (0x01 << PORT_PORTP_DRIVS_PIN19_Pos) -#define PORT_PORTP_DRIVS_PIN20_Pos 20 -#define PORT_PORTP_DRIVS_PIN20_Msk (0x01 << PORT_PORTP_DRIVS_PIN20_Pos) -#define PORT_PORTP_DRIVS_PIN21_Pos 21 -#define PORT_PORTP_DRIVS_PIN21_Msk (0x01 << PORT_PORTP_DRIVS_PIN21_Pos) -#define PORT_PORTP_DRIVS_PIN22_Pos 22 -#define PORT_PORTP_DRIVS_PIN22_Msk (0x01 << PORT_PORTP_DRIVS_PIN22_Pos) -#define PORT_PORTP_DRIVS_PIN23_Pos 23 -#define PORT_PORTP_DRIVS_PIN23_Msk (0x01 << PORT_PORTP_DRIVS_PIN23_Pos) +#define PORT_PORTN_DRIVS_PIN0_Pos 0 +#define PORT_PORTN_DRIVS_PIN0_Msk (0x01 << PORT_PORTN_DRIVS_PIN0_Pos) +#define PORT_PORTN_DRIVS_PIN1_Pos 1 +#define PORT_PORTN_DRIVS_PIN1_Msk (0x01 << PORT_PORTN_DRIVS_PIN1_Pos) +#define PORT_PORTN_DRIVS_PIN2_Pos 2 +#define PORT_PORTN_DRIVS_PIN2_Msk (0x01 << PORT_PORTN_DRIVS_PIN2_Pos) +#define PORT_PORTN_DRIVS_PIN3_Pos 3 +#define PORT_PORTN_DRIVS_PIN3_Msk (0x01 << PORT_PORTN_DRIVS_PIN3_Pos) +#define PORT_PORTN_DRIVS_PIN4_Pos 4 +#define PORT_PORTN_DRIVS_PIN4_Msk (0x01 << PORT_PORTN_DRIVS_PIN4_Pos) +#define PORT_PORTN_DRIVS_PIN5_Pos 5 +#define PORT_PORTN_DRIVS_PIN5_Msk (0x01 << PORT_PORTN_DRIVS_PIN5_Pos) +#define PORT_PORTN_DRIVS_PIN6_Pos 6 +#define PORT_PORTN_DRIVS_PIN6_Msk (0x01 << PORT_PORTN_DRIVS_PIN6_Pos) +#define PORT_PORTN_DRIVS_PIN7_Pos 7 +#define PORT_PORTN_DRIVS_PIN7_Msk (0x01 << PORT_PORTN_DRIVS_PIN7_Pos) +#define PORT_PORTN_DRIVS_PIN8_Pos 8 +#define PORT_PORTN_DRIVS_PIN8_Msk (0x01 << PORT_PORTN_DRIVS_PIN8_Pos) +#define PORT_PORTN_DRIVS_PIN9_Pos 9 +#define PORT_PORTN_DRIVS_PIN9_Msk (0x01 << PORT_PORTN_DRIVS_PIN9_Pos) +#define PORT_PORTN_DRIVS_PIN10_Pos 10 +#define PORT_PORTN_DRIVS_PIN10_Msk (0x01 << PORT_PORTN_DRIVS_PIN10_Pos) +#define PORT_PORTN_DRIVS_PIN11_Pos 11 +#define PORT_PORTN_DRIVS_PIN11_Msk (0x01 << PORT_PORTN_DRIVS_PIN11_Pos) +#define PORT_PORTN_DRIVS_PIN12_Pos 12 +#define PORT_PORTN_DRIVS_PIN12_Msk (0x01 << PORT_PORTN_DRIVS_PIN12_Pos) +#define PORT_PORTN_DRIVS_PIN13_Pos 13 +#define PORT_PORTN_DRIVS_PIN13_Msk (0x01 << PORT_PORTN_DRIVS_PIN13_Pos) +#define PORT_PORTN_DRIVS_PIN14_Pos 14 +#define PORT_PORTN_DRIVS_PIN14_Msk (0x01 << PORT_PORTN_DRIVS_PIN14_Pos) +#define PORT_PORTN_DRIVS_PIN15_Pos 15 +#define PORT_PORTN_DRIVS_PIN15_Msk (0x01 << PORT_PORTN_DRIVS_PIN15_Pos) +#define PORT_PORTN_DRIVS_PIN16_Pos 16 +#define PORT_PORTN_DRIVS_PIN16_Msk (0x01 << PORT_PORTN_DRIVS_PIN16_Pos) +#define PORT_PORTN_DRIVS_PIN17_Pos 17 +#define PORT_PORTN_DRIVS_PIN17_Msk (0x01 << PORT_PORTN_DRIVS_PIN17_Pos) +#define PORT_PORTN_DRIVS_PIN18_Pos 18 +#define PORT_PORTN_DRIVS_PIN18_Msk (0x01 << PORT_PORTN_DRIVS_PIN18_Pos) +#define PORT_PORTN_DRIVS_PIN19_Pos 19 +#define PORT_PORTN_DRIVS_PIN19_Msk (0x01 << PORT_PORTN_DRIVS_PIN19_Pos) +#define PORT_PORTN_DRIVS_PIN20_Pos 20 +#define PORT_PORTN_DRIVS_PIN20_Msk (0x01 << PORT_PORTN_DRIVS_PIN20_Pos) +#define PORT_PORTN_DRIVS_PIN21_Pos 21 +#define PORT_PORTN_DRIVS_PIN21_Msk (0x01 << PORT_PORTN_DRIVS_PIN21_Pos) +#define PORT_PORTN_DRIVS_PIN22_Pos 22 +#define PORT_PORTN_DRIVS_PIN22_Msk (0x01 << PORT_PORTN_DRIVS_PIN22_Pos) +#define PORT_PORTN_DRIVS_PIN23_Pos 23 +#define PORT_PORTN_DRIVS_PIN23_Msk (0x01 << PORT_PORTN_DRIVS_PIN23_Pos) -#define PORT_PORTA_INEN_PIN0_Pos 0 -#define PORT_PORTA_INEN_PIN0_Msk (0x01 << PORT_PORTA_INEN_PIN0_Pos) -#define PORT_PORTA_INEN_PIN1_Pos 1 -#define PORT_PORTA_INEN_PIN1_Msk (0x01 << PORT_PORTA_INEN_PIN1_Pos) -#define PORT_PORTA_INEN_PIN2_Pos 2 -#define PORT_PORTA_INEN_PIN2_Msk (0x01 << PORT_PORTA_INEN_PIN2_Pos) -#define PORT_PORTA_INEN_PIN3_Pos 3 -#define PORT_PORTA_INEN_PIN3_Msk (0x01 << PORT_PORTA_INEN_PIN3_Pos) -#define PORT_PORTA_INEN_PIN4_Pos 4 -#define PORT_PORTA_INEN_PIN4_Msk (0x01 << PORT_PORTA_INEN_PIN4_Pos) -#define PORT_PORTA_INEN_PIN5_Pos 5 -#define PORT_PORTA_INEN_PIN5_Msk (0x01 << PORT_PORTA_INEN_PIN5_Pos) -#define PORT_PORTA_INEN_PIN6_Pos 6 -#define PORT_PORTA_INEN_PIN6_Msk (0x01 << PORT_PORTA_INEN_PIN6_Pos) -#define PORT_PORTA_INEN_PIN7_Pos 7 -#define PORT_PORTA_INEN_PIN7_Msk (0x01 << PORT_PORTA_INEN_PIN7_Pos) -#define PORT_PORTA_INEN_PIN8_Pos 8 -#define PORT_PORTA_INEN_PIN8_Msk (0x01 << PORT_PORTA_INEN_PIN8_Pos) -#define PORT_PORTA_INEN_PIN9_Pos 9 -#define PORT_PORTA_INEN_PIN9_Msk (0x01 << PORT_PORTA_INEN_PIN9_Pos) -#define PORT_PORTA_INEN_PIN10_Pos 10 -#define PORT_PORTA_INEN_PIN10_Msk (0x01 << PORT_PORTA_INEN_PIN10_Pos) -#define PORT_PORTA_INEN_PIN11_Pos 11 -#define PORT_PORTA_INEN_PIN11_Msk (0x01 << PORT_PORTA_INEN_PIN11_Pos) -#define PORT_PORTA_INEN_PIN12_Pos 12 -#define PORT_PORTA_INEN_PIN12_Msk (0x01 << PORT_PORTA_INEN_PIN12_Pos) -#define PORT_PORTA_INEN_PIN13_Pos 13 -#define PORT_PORTA_INEN_PIN13_Msk (0x01 << PORT_PORTA_INEN_PIN13_Pos) -#define PORT_PORTA_INEN_PIN14_Pos 14 -#define PORT_PORTA_INEN_PIN14_Msk (0x01 << PORT_PORTA_INEN_PIN14_Pos) -#define PORT_PORTA_INEN_PIN15_Pos 15 -#define PORT_PORTA_INEN_PIN15_Msk (0x01 << PORT_PORTA_INEN_PIN15_Pos) +#define PORT_PORTP_DRIVS_PIN0_Pos 0 +#define PORT_PORTP_DRIVS_PIN0_Msk (0x01 << PORT_PORTP_DRIVS_PIN0_Pos) +#define PORT_PORTP_DRIVS_PIN1_Pos 1 +#define PORT_PORTP_DRIVS_PIN1_Msk (0x01 << PORT_PORTP_DRIVS_PIN1_Pos) +#define PORT_PORTP_DRIVS_PIN2_Pos 2 +#define PORT_PORTP_DRIVS_PIN2_Msk (0x01 << PORT_PORTP_DRIVS_PIN2_Pos) +#define PORT_PORTP_DRIVS_PIN3_Pos 3 +#define PORT_PORTP_DRIVS_PIN3_Msk (0x01 << PORT_PORTP_DRIVS_PIN3_Pos) +#define PORT_PORTP_DRIVS_PIN4_Pos 4 +#define PORT_PORTP_DRIVS_PIN4_Msk (0x01 << PORT_PORTP_DRIVS_PIN4_Pos) +#define PORT_PORTP_DRIVS_PIN5_Pos 5 +#define PORT_PORTP_DRIVS_PIN5_Msk (0x01 << PORT_PORTP_DRIVS_PIN5_Pos) +#define PORT_PORTP_DRIVS_PIN6_Pos 6 +#define PORT_PORTP_DRIVS_PIN6_Msk (0x01 << PORT_PORTP_DRIVS_PIN6_Pos) +#define PORT_PORTP_DRIVS_PIN7_Pos 7 +#define PORT_PORTP_DRIVS_PIN7_Msk (0x01 << PORT_PORTP_DRIVS_PIN7_Pos) +#define PORT_PORTP_DRIVS_PIN8_Pos 8 +#define PORT_PORTP_DRIVS_PIN8_Msk (0x01 << PORT_PORTP_DRIVS_PIN8_Pos) +#define PORT_PORTP_DRIVS_PIN9_Pos 9 +#define PORT_PORTP_DRIVS_PIN9_Msk (0x01 << PORT_PORTP_DRIVS_PIN9_Pos) +#define PORT_PORTP_DRIVS_PIN10_Pos 10 +#define PORT_PORTP_DRIVS_PIN10_Msk (0x01 << PORT_PORTP_DRIVS_PIN10_Pos) +#define PORT_PORTP_DRIVS_PIN11_Pos 11 +#define PORT_PORTP_DRIVS_PIN11_Msk (0x01 << PORT_PORTP_DRIVS_PIN11_Pos) +#define PORT_PORTP_DRIVS_PIN12_Pos 12 +#define PORT_PORTP_DRIVS_PIN12_Msk (0x01 << PORT_PORTP_DRIVS_PIN12_Pos) +#define PORT_PORTP_DRIVS_PIN13_Pos 13 +#define PORT_PORTP_DRIVS_PIN13_Msk (0x01 << PORT_PORTP_DRIVS_PIN13_Pos) +#define PORT_PORTP_DRIVS_PIN14_Pos 14 +#define PORT_PORTP_DRIVS_PIN14_Msk (0x01 << PORT_PORTP_DRIVS_PIN14_Pos) +#define PORT_PORTP_DRIVS_PIN15_Pos 15 +#define PORT_PORTP_DRIVS_PIN15_Msk (0x01 << PORT_PORTP_DRIVS_PIN15_Pos) +#define PORT_PORTP_DRIVS_PIN16_Pos 16 +#define PORT_PORTP_DRIVS_PIN16_Msk (0x01 << PORT_PORTP_DRIVS_PIN16_Pos) +#define PORT_PORTP_DRIVS_PIN17_Pos 17 +#define PORT_PORTP_DRIVS_PIN17_Msk (0x01 << PORT_PORTP_DRIVS_PIN17_Pos) +#define PORT_PORTP_DRIVS_PIN18_Pos 18 +#define PORT_PORTP_DRIVS_PIN18_Msk (0x01 << PORT_PORTP_DRIVS_PIN18_Pos) +#define PORT_PORTP_DRIVS_PIN19_Pos 19 +#define PORT_PORTP_DRIVS_PIN19_Msk (0x01 << PORT_PORTP_DRIVS_PIN19_Pos) +#define PORT_PORTP_DRIVS_PIN20_Pos 20 +#define PORT_PORTP_DRIVS_PIN20_Msk (0x01 << PORT_PORTP_DRIVS_PIN20_Pos) +#define PORT_PORTP_DRIVS_PIN21_Pos 21 +#define PORT_PORTP_DRIVS_PIN21_Msk (0x01 << PORT_PORTP_DRIVS_PIN21_Pos) +#define PORT_PORTP_DRIVS_PIN22_Pos 22 +#define PORT_PORTP_DRIVS_PIN22_Msk (0x01 << PORT_PORTP_DRIVS_PIN22_Pos) +#define PORT_PORTP_DRIVS_PIN23_Pos 23 +#define PORT_PORTP_DRIVS_PIN23_Msk (0x01 << PORT_PORTP_DRIVS_PIN23_Pos) -#define PORT_PORTB_INEN_PIN0_Pos 0 -#define PORT_PORTB_INEN_PIN0_Msk (0x01 << PORT_PORTB_INEN_PIN0_Pos) -#define PORT_PORTB_INEN_PIN1_Pos 1 -#define PORT_PORTB_INEN_PIN1_Msk (0x01 << PORT_PORTB_INEN_PIN1_Pos) -#define PORT_PORTB_INEN_PIN2_Pos 2 -#define PORT_PORTB_INEN_PIN2_Msk (0x01 << PORT_PORTB_INEN_PIN2_Pos) -#define PORT_PORTB_INEN_PIN3_Pos 3 -#define PORT_PORTB_INEN_PIN3_Msk (0x01 << PORT_PORTB_INEN_PIN3_Pos) -#define PORT_PORTB_INEN_PIN4_Pos 4 -#define PORT_PORTB_INEN_PIN4_Msk (0x01 << PORT_PORTB_INEN_PIN4_Pos) -#define PORT_PORTB_INEN_PIN5_Pos 5 -#define PORT_PORTB_INEN_PIN5_Msk (0x01 << PORT_PORTB_INEN_PIN5_Pos) -#define PORT_PORTB_INEN_PIN6_Pos 6 -#define PORT_PORTB_INEN_PIN6_Msk (0x01 << PORT_PORTB_INEN_PIN6_Pos) -#define PORT_PORTB_INEN_PIN7_Pos 7 -#define PORT_PORTB_INEN_PIN7_Msk (0x01 << PORT_PORTB_INEN_PIN7_Pos) -#define PORT_PORTB_INEN_PIN8_Pos 8 -#define PORT_PORTB_INEN_PIN8_Msk (0x01 << PORT_PORTB_INEN_PIN8_Pos) -#define PORT_PORTB_INEN_PIN9_Pos 9 -#define PORT_PORTB_INEN_PIN9_Msk (0x01 << PORT_PORTB_INEN_PIN9_Pos) -#define PORT_PORTB_INEN_PIN10_Pos 10 -#define PORT_PORTB_INEN_PIN10_Msk (0x01 << PORT_PORTB_INEN_PIN10_Pos) -#define PORT_PORTB_INEN_PIN11_Pos 11 -#define PORT_PORTB_INEN_PIN11_Msk (0x01 << PORT_PORTB_INEN_PIN11_Pos) -#define PORT_PORTB_INEN_PIN12_Pos 12 -#define PORT_PORTB_INEN_PIN12_Msk (0x01 << PORT_PORTB_INEN_PIN12_Pos) -#define PORT_PORTB_INEN_PIN13_Pos 13 -#define PORT_PORTB_INEN_PIN13_Msk (0x01 << PORT_PORTB_INEN_PIN13_Pos) -#define PORT_PORTB_INEN_PIN14_Pos 14 -#define PORT_PORTB_INEN_PIN14_Msk (0x01 << PORT_PORTB_INEN_PIN14_Pos) -#define PORT_PORTB_INEN_PIN15_Pos 15 -#define PORT_PORTB_INEN_PIN15_Msk (0x01 << PORT_PORTB_INEN_PIN15_Pos) +#define PORT_PORTA_INEN_PIN0_Pos 0 +#define PORT_PORTA_INEN_PIN0_Msk (0x01 << PORT_PORTA_INEN_PIN0_Pos) +#define PORT_PORTA_INEN_PIN1_Pos 1 +#define PORT_PORTA_INEN_PIN1_Msk (0x01 << PORT_PORTA_INEN_PIN1_Pos) +#define PORT_PORTA_INEN_PIN2_Pos 2 +#define PORT_PORTA_INEN_PIN2_Msk (0x01 << PORT_PORTA_INEN_PIN2_Pos) +#define PORT_PORTA_INEN_PIN3_Pos 3 +#define PORT_PORTA_INEN_PIN3_Msk (0x01 << PORT_PORTA_INEN_PIN3_Pos) +#define PORT_PORTA_INEN_PIN4_Pos 4 +#define PORT_PORTA_INEN_PIN4_Msk (0x01 << PORT_PORTA_INEN_PIN4_Pos) +#define PORT_PORTA_INEN_PIN5_Pos 5 +#define PORT_PORTA_INEN_PIN5_Msk (0x01 << PORT_PORTA_INEN_PIN5_Pos) +#define PORT_PORTA_INEN_PIN6_Pos 6 +#define PORT_PORTA_INEN_PIN6_Msk (0x01 << PORT_PORTA_INEN_PIN6_Pos) +#define PORT_PORTA_INEN_PIN7_Pos 7 +#define PORT_PORTA_INEN_PIN7_Msk (0x01 << PORT_PORTA_INEN_PIN7_Pos) +#define PORT_PORTA_INEN_PIN8_Pos 8 +#define PORT_PORTA_INEN_PIN8_Msk (0x01 << PORT_PORTA_INEN_PIN8_Pos) +#define PORT_PORTA_INEN_PIN9_Pos 9 +#define PORT_PORTA_INEN_PIN9_Msk (0x01 << PORT_PORTA_INEN_PIN9_Pos) +#define PORT_PORTA_INEN_PIN10_Pos 10 +#define PORT_PORTA_INEN_PIN10_Msk (0x01 << PORT_PORTA_INEN_PIN10_Pos) +#define PORT_PORTA_INEN_PIN11_Pos 11 +#define PORT_PORTA_INEN_PIN11_Msk (0x01 << PORT_PORTA_INEN_PIN11_Pos) +#define PORT_PORTA_INEN_PIN12_Pos 12 +#define PORT_PORTA_INEN_PIN12_Msk (0x01 << PORT_PORTA_INEN_PIN12_Pos) +#define PORT_PORTA_INEN_PIN13_Pos 13 +#define PORT_PORTA_INEN_PIN13_Msk (0x01 << PORT_PORTA_INEN_PIN13_Pos) +#define PORT_PORTA_INEN_PIN14_Pos 14 +#define PORT_PORTA_INEN_PIN14_Msk (0x01 << PORT_PORTA_INEN_PIN14_Pos) +#define PORT_PORTA_INEN_PIN15_Pos 15 +#define PORT_PORTA_INEN_PIN15_Msk (0x01 << PORT_PORTA_INEN_PIN15_Pos) -#define PORT_PORTC_INEN_PIN0_Pos 0 -#define PORT_PORTC_INEN_PIN0_Msk (0x01 << PORT_PORTC_INEN_PIN0_Pos) -#define PORT_PORTC_INEN_PIN1_Pos 1 -#define PORT_PORTC_INEN_PIN1_Msk (0x01 << PORT_PORTC_INEN_PIN1_Pos) -#define PORT_PORTC_INEN_PIN2_Pos 2 -#define PORT_PORTC_INEN_PIN2_Msk (0x01 << PORT_PORTC_INEN_PIN2_Pos) -#define PORT_PORTC_INEN_PIN3_Pos 3 -#define PORT_PORTC_INEN_PIN3_Msk (0x01 << PORT_PORTC_INEN_PIN3_Pos) -#define PORT_PORTC_INEN_PIN4_Pos 4 -#define PORT_PORTC_INEN_PIN4_Msk (0x01 << PORT_PORTC_INEN_PIN4_Pos) -#define PORT_PORTC_INEN_PIN5_Pos 5 -#define PORT_PORTC_INEN_PIN5_Msk (0x01 << PORT_PORTC_INEN_PIN5_Pos) -#define PORT_PORTC_INEN_PIN6_Pos 6 -#define PORT_PORTC_INEN_PIN6_Msk (0x01 << PORT_PORTC_INEN_PIN6_Pos) -#define PORT_PORTC_INEN_PIN7_Pos 7 -#define PORT_PORTC_INEN_PIN7_Msk (0x01 << PORT_PORTC_INEN_PIN7_Pos) -#define PORT_PORTC_INEN_PIN8_Pos 8 -#define PORT_PORTC_INEN_PIN8_Msk (0x01 << PORT_PORTC_INEN_PIN8_Pos) -#define PORT_PORTC_INEN_PIN9_Pos 9 -#define PORT_PORTC_INEN_PIN9_Msk (0x01 << PORT_PORTC_INEN_PIN9_Pos) -#define PORT_PORTC_INEN_PIN10_Pos 10 -#define PORT_PORTC_INEN_PIN10_Msk (0x01 << PORT_PORTC_INEN_PIN10_Pos) -#define PORT_PORTC_INEN_PIN11_Pos 11 -#define PORT_PORTC_INEN_PIN11_Msk (0x01 << PORT_PORTC_INEN_PIN11_Pos) -#define PORT_PORTC_INEN_PIN12_Pos 12 -#define PORT_PORTC_INEN_PIN12_Msk (0x01 << PORT_PORTC_INEN_PIN12_Pos) -#define PORT_PORTC_INEN_PIN13_Pos 13 -#define PORT_PORTC_INEN_PIN13_Msk (0x01 << PORT_PORTC_INEN_PIN13_Pos) -#define PORT_PORTC_INEN_PIN14_Pos 14 -#define PORT_PORTC_INEN_PIN14_Msk (0x01 << PORT_PORTC_INEN_PIN14_Pos) -#define PORT_PORTC_INEN_PIN15_Pos 15 -#define PORT_PORTC_INEN_PIN15_Msk (0x01 << PORT_PORTC_INEN_PIN15_Pos) +#define PORT_PORTB_INEN_PIN0_Pos 0 +#define PORT_PORTB_INEN_PIN0_Msk (0x01 << PORT_PORTB_INEN_PIN0_Pos) +#define PORT_PORTB_INEN_PIN1_Pos 1 +#define PORT_PORTB_INEN_PIN1_Msk (0x01 << PORT_PORTB_INEN_PIN1_Pos) +#define PORT_PORTB_INEN_PIN2_Pos 2 +#define PORT_PORTB_INEN_PIN2_Msk (0x01 << PORT_PORTB_INEN_PIN2_Pos) +#define PORT_PORTB_INEN_PIN3_Pos 3 +#define PORT_PORTB_INEN_PIN3_Msk (0x01 << PORT_PORTB_INEN_PIN3_Pos) +#define PORT_PORTB_INEN_PIN4_Pos 4 +#define PORT_PORTB_INEN_PIN4_Msk (0x01 << PORT_PORTB_INEN_PIN4_Pos) +#define PORT_PORTB_INEN_PIN5_Pos 5 +#define PORT_PORTB_INEN_PIN5_Msk (0x01 << PORT_PORTB_INEN_PIN5_Pos) +#define PORT_PORTB_INEN_PIN6_Pos 6 +#define PORT_PORTB_INEN_PIN6_Msk (0x01 << PORT_PORTB_INEN_PIN6_Pos) +#define PORT_PORTB_INEN_PIN7_Pos 7 +#define PORT_PORTB_INEN_PIN7_Msk (0x01 << PORT_PORTB_INEN_PIN7_Pos) +#define PORT_PORTB_INEN_PIN8_Pos 8 +#define PORT_PORTB_INEN_PIN8_Msk (0x01 << PORT_PORTB_INEN_PIN8_Pos) +#define PORT_PORTB_INEN_PIN9_Pos 9 +#define PORT_PORTB_INEN_PIN9_Msk (0x01 << PORT_PORTB_INEN_PIN9_Pos) +#define PORT_PORTB_INEN_PIN10_Pos 10 +#define PORT_PORTB_INEN_PIN10_Msk (0x01 << PORT_PORTB_INEN_PIN10_Pos) +#define PORT_PORTB_INEN_PIN11_Pos 11 +#define PORT_PORTB_INEN_PIN11_Msk (0x01 << PORT_PORTB_INEN_PIN11_Pos) +#define PORT_PORTB_INEN_PIN12_Pos 12 +#define PORT_PORTB_INEN_PIN12_Msk (0x01 << PORT_PORTB_INEN_PIN12_Pos) +#define PORT_PORTB_INEN_PIN13_Pos 13 +#define PORT_PORTB_INEN_PIN13_Msk (0x01 << PORT_PORTB_INEN_PIN13_Pos) +#define PORT_PORTB_INEN_PIN14_Pos 14 +#define PORT_PORTB_INEN_PIN14_Msk (0x01 << PORT_PORTB_INEN_PIN14_Pos) +#define PORT_PORTB_INEN_PIN15_Pos 15 +#define PORT_PORTB_INEN_PIN15_Msk (0x01 << PORT_PORTB_INEN_PIN15_Pos) -#define PORT_PORTM_INEN_PIN0_Pos 0 -#define PORT_PORTM_INEN_PIN0_Msk (0x01 << PORT_PORTM_INEN_PIN0_Pos) -#define PORT_PORTM_INEN_PIN1_Pos 1 -#define PORT_PORTM_INEN_PIN1_Msk (0x01 << PORT_PORTM_INEN_PIN1_Pos) -#define PORT_PORTM_INEN_PIN2_Pos 2 -#define PORT_PORTM_INEN_PIN2_Msk (0x01 << PORT_PORTM_INEN_PIN2_Pos) -#define PORT_PORTM_INEN_PIN3_Pos 3 -#define PORT_PORTM_INEN_PIN3_Msk (0x01 << PORT_PORTM_INEN_PIN3_Pos) -#define PORT_PORTM_INEN_PIN4_Pos 4 -#define PORT_PORTM_INEN_PIN4_Msk (0x01 << PORT_PORTM_INEN_PIN4_Pos) -#define PORT_PORTM_INEN_PIN5_Pos 5 -#define PORT_PORTM_INEN_PIN5_Msk (0x01 << PORT_PORTM_INEN_PIN5_Pos) -#define PORT_PORTM_INEN_PIN6_Pos 6 -#define PORT_PORTM_INEN_PIN6_Msk (0x01 << PORT_PORTM_INEN_PIN6_Pos) -#define PORT_PORTM_INEN_PIN7_Pos 7 -#define PORT_PORTM_INEN_PIN7_Msk (0x01 << PORT_PORTM_INEN_PIN7_Pos) -#define PORT_PORTM_INEN_PIN8_Pos 8 -#define PORT_PORTM_INEN_PIN8_Msk (0x01 << PORT_PORTM_INEN_PIN8_Pos) -#define PORT_PORTM_INEN_PIN9_Pos 9 -#define PORT_PORTM_INEN_PIN9_Msk (0x01 << PORT_PORTM_INEN_PIN9_Pos) -#define PORT_PORTM_INEN_PIN10_Pos 10 -#define PORT_PORTM_INEN_PIN10_Msk (0x01 << PORT_PORTM_INEN_PIN10_Pos) -#define PORT_PORTM_INEN_PIN11_Pos 11 -#define PORT_PORTM_INEN_PIN11_Msk (0x01 << PORT_PORTM_INEN_PIN11_Pos) -#define PORT_PORTM_INEN_PIN12_Pos 12 -#define PORT_PORTM_INEN_PIN12_Msk (0x01 << PORT_PORTM_INEN_PIN12_Pos) -#define PORT_PORTM_INEN_PIN13_Pos 13 -#define PORT_PORTM_INEN_PIN13_Msk (0x01 << PORT_PORTM_INEN_PIN13_Pos) -#define PORT_PORTM_INEN_PIN14_Pos 14 -#define PORT_PORTM_INEN_PIN14_Msk (0x01 << PORT_PORTM_INEN_PIN14_Pos) -#define PORT_PORTM_INEN_PIN15_Pos 15 -#define PORT_PORTM_INEN_PIN15_Msk (0x01 << PORT_PORTM_INEN_PIN15_Pos) -#define PORT_PORTM_INEN_PIN16_Pos 16 -#define PORT_PORTM_INEN_PIN16_Msk (0x01 << PORT_PORTM_INEN_PIN16_Pos) -#define PORT_PORTM_INEN_PIN17_Pos 17 -#define PORT_PORTM_INEN_PIN17_Msk (0x01 << PORT_PORTM_INEN_PIN17_Pos) -#define PORT_PORTM_INEN_PIN18_Pos 18 -#define PORT_PORTM_INEN_PIN18_Msk (0x01 << PORT_PORTM_INEN_PIN18_Pos) -#define PORT_PORTM_INEN_PIN19_Pos 19 -#define PORT_PORTM_INEN_PIN19_Msk (0x01 << PORT_PORTM_INEN_PIN19_Pos) -#define PORT_PORTM_INEN_PIN20_Pos 20 -#define PORT_PORTM_INEN_PIN20_Msk (0x01 << PORT_PORTM_INEN_PIN20_Pos) -#define PORT_PORTM_INEN_PIN21_Pos 21 -#define PORT_PORTM_INEN_PIN21_Msk (0x01 << PORT_PORTM_INEN_PIN21_Pos) -#define PORT_PORTM_INEN_PIN22_Pos 22 -#define PORT_PORTM_INEN_PIN22_Msk (0x01 << PORT_PORTM_INEN_PIN22_Pos) -#define PORT_PORTM_INEN_PIN23_Pos 23 -#define PORT_PORTM_INEN_PIN23_Msk (0x01 << PORT_PORTM_INEN_PIN23_Pos) +#define PORT_PORTC_INEN_PIN0_Pos 0 +#define PORT_PORTC_INEN_PIN0_Msk (0x01 << PORT_PORTC_INEN_PIN0_Pos) +#define PORT_PORTC_INEN_PIN1_Pos 1 +#define PORT_PORTC_INEN_PIN1_Msk (0x01 << PORT_PORTC_INEN_PIN1_Pos) +#define PORT_PORTC_INEN_PIN2_Pos 2 +#define PORT_PORTC_INEN_PIN2_Msk (0x01 << PORT_PORTC_INEN_PIN2_Pos) +#define PORT_PORTC_INEN_PIN3_Pos 3 +#define PORT_PORTC_INEN_PIN3_Msk (0x01 << PORT_PORTC_INEN_PIN3_Pos) +#define PORT_PORTC_INEN_PIN4_Pos 4 +#define PORT_PORTC_INEN_PIN4_Msk (0x01 << PORT_PORTC_INEN_PIN4_Pos) +#define PORT_PORTC_INEN_PIN5_Pos 5 +#define PORT_PORTC_INEN_PIN5_Msk (0x01 << PORT_PORTC_INEN_PIN5_Pos) +#define PORT_PORTC_INEN_PIN6_Pos 6 +#define PORT_PORTC_INEN_PIN6_Msk (0x01 << PORT_PORTC_INEN_PIN6_Pos) +#define PORT_PORTC_INEN_PIN7_Pos 7 +#define PORT_PORTC_INEN_PIN7_Msk (0x01 << PORT_PORTC_INEN_PIN7_Pos) +#define PORT_PORTC_INEN_PIN8_Pos 8 +#define PORT_PORTC_INEN_PIN8_Msk (0x01 << PORT_PORTC_INEN_PIN8_Pos) +#define PORT_PORTC_INEN_PIN9_Pos 9 +#define PORT_PORTC_INEN_PIN9_Msk (0x01 << PORT_PORTC_INEN_PIN9_Pos) +#define PORT_PORTC_INEN_PIN10_Pos 10 +#define PORT_PORTC_INEN_PIN10_Msk (0x01 << PORT_PORTC_INEN_PIN10_Pos) +#define PORT_PORTC_INEN_PIN11_Pos 11 +#define PORT_PORTC_INEN_PIN11_Msk (0x01 << PORT_PORTC_INEN_PIN11_Pos) +#define PORT_PORTC_INEN_PIN12_Pos 12 +#define PORT_PORTC_INEN_PIN12_Msk (0x01 << PORT_PORTC_INEN_PIN12_Pos) +#define PORT_PORTC_INEN_PIN13_Pos 13 +#define PORT_PORTC_INEN_PIN13_Msk (0x01 << PORT_PORTC_INEN_PIN13_Pos) +#define PORT_PORTC_INEN_PIN14_Pos 14 +#define PORT_PORTC_INEN_PIN14_Msk (0x01 << PORT_PORTC_INEN_PIN14_Pos) +#define PORT_PORTC_INEN_PIN15_Pos 15 +#define PORT_PORTC_INEN_PIN15_Msk (0x01 << PORT_PORTC_INEN_PIN15_Pos) -#define PORT_PORTN_INEN_PIN0_Pos 0 -#define PORT_PORTN_INEN_PIN0_Msk (0x01 << PORT_PORTN_INEN_PIN0_Pos) -#define PORT_PORTN_INEN_PIN1_Pos 1 -#define PORT_PORTN_INEN_PIN1_Msk (0x01 << PORT_PORTN_INEN_PIN1_Pos) -#define PORT_PORTN_INEN_PIN2_Pos 2 -#define PORT_PORTN_INEN_PIN2_Msk (0x01 << PORT_PORTN_INEN_PIN2_Pos) -#define PORT_PORTN_INEN_PIN3_Pos 3 -#define PORT_PORTN_INEN_PIN3_Msk (0x01 << PORT_PORTN_INEN_PIN3_Pos) -#define PORT_PORTN_INEN_PIN4_Pos 4 -#define PORT_PORTN_INEN_PIN4_Msk (0x01 << PORT_PORTN_INEN_PIN4_Pos) -#define PORT_PORTN_INEN_PIN5_Pos 5 -#define PORT_PORTN_INEN_PIN5_Msk (0x01 << PORT_PORTN_INEN_PIN5_Pos) -#define PORT_PORTN_INEN_PIN6_Pos 6 -#define PORT_PORTN_INEN_PIN6_Msk (0x01 << PORT_PORTN_INEN_PIN6_Pos) -#define PORT_PORTN_INEN_PIN7_Pos 7 -#define PORT_PORTN_INEN_PIN7_Msk (0x01 << PORT_PORTN_INEN_PIN7_Pos) -#define PORT_PORTN_INEN_PIN8_Pos 8 -#define PORT_PORTN_INEN_PIN8_Msk (0x01 << PORT_PORTN_INEN_PIN8_Pos) -#define PORT_PORTN_INEN_PIN9_Pos 9 -#define PORT_PORTN_INEN_PIN9_Msk (0x01 << PORT_PORTN_INEN_PIN9_Pos) -#define PORT_PORTN_INEN_PIN10_Pos 10 -#define PORT_PORTN_INEN_PIN10_Msk (0x01 << PORT_PORTN_INEN_PIN10_Pos) -#define PORT_PORTN_INEN_PIN11_Pos 11 -#define PORT_PORTN_INEN_PIN11_Msk (0x01 << PORT_PORTN_INEN_PIN11_Pos) -#define PORT_PORTN_INEN_PIN12_Pos 12 -#define PORT_PORTN_INEN_PIN12_Msk (0x01 << PORT_PORTN_INEN_PIN12_Pos) -#define PORT_PORTN_INEN_PIN13_Pos 13 -#define PORT_PORTN_INEN_PIN13_Msk (0x01 << PORT_PORTN_INEN_PIN13_Pos) -#define PORT_PORTN_INEN_PIN14_Pos 14 -#define PORT_PORTN_INEN_PIN14_Msk (0x01 << PORT_PORTN_INEN_PIN14_Pos) -#define PORT_PORTN_INEN_PIN15_Pos 15 -#define PORT_PORTN_INEN_PIN15_Msk (0x01 << PORT_PORTN_INEN_PIN15_Pos) -#define PORT_PORTN_INEN_PIN16_Pos 16 -#define PORT_PORTN_INEN_PIN16_Msk (0x01 << PORT_PORTN_INEN_PIN16_Pos) -#define PORT_PORTN_INEN_PIN17_Pos 17 -#define PORT_PORTN_INEN_PIN17_Msk (0x01 << PORT_PORTN_INEN_PIN17_Pos) -#define PORT_PORTN_INEN_PIN18_Pos 18 -#define PORT_PORTN_INEN_PIN18_Msk (0x01 << PORT_PORTN_INEN_PIN18_Pos) -#define PORT_PORTN_INEN_PIN19_Pos 19 -#define PORT_PORTN_INEN_PIN19_Msk (0x01 << PORT_PORTN_INEN_PIN19_Pos) -#define PORT_PORTN_INEN_PIN20_Pos 20 -#define PORT_PORTN_INEN_PIN20_Msk (0x01 << PORT_PORTN_INEN_PIN20_Pos) -#define PORT_PORTN_INEN_PIN21_Pos 21 -#define PORT_PORTN_INEN_PIN21_Msk (0x01 << PORT_PORTN_INEN_PIN21_Pos) -#define PORT_PORTN_INEN_PIN22_Pos 22 -#define PORT_PORTN_INEN_PIN22_Msk (0x01 << PORT_PORTN_INEN_PIN22_Pos) -#define PORT_PORTN_INEN_PIN23_Pos 23 -#define PORT_PORTN_INEN_PIN23_Msk (0x01 << PORT_PORTN_INEN_PIN23_Pos) +#define PORT_PORTM_INEN_PIN0_Pos 0 +#define PORT_PORTM_INEN_PIN0_Msk (0x01 << PORT_PORTM_INEN_PIN0_Pos) +#define PORT_PORTM_INEN_PIN1_Pos 1 +#define PORT_PORTM_INEN_PIN1_Msk (0x01 << PORT_PORTM_INEN_PIN1_Pos) +#define PORT_PORTM_INEN_PIN2_Pos 2 +#define PORT_PORTM_INEN_PIN2_Msk (0x01 << PORT_PORTM_INEN_PIN2_Pos) +#define PORT_PORTM_INEN_PIN3_Pos 3 +#define PORT_PORTM_INEN_PIN3_Msk (0x01 << PORT_PORTM_INEN_PIN3_Pos) +#define PORT_PORTM_INEN_PIN4_Pos 4 +#define PORT_PORTM_INEN_PIN4_Msk (0x01 << PORT_PORTM_INEN_PIN4_Pos) +#define PORT_PORTM_INEN_PIN5_Pos 5 +#define PORT_PORTM_INEN_PIN5_Msk (0x01 << PORT_PORTM_INEN_PIN5_Pos) +#define PORT_PORTM_INEN_PIN6_Pos 6 +#define PORT_PORTM_INEN_PIN6_Msk (0x01 << PORT_PORTM_INEN_PIN6_Pos) +#define PORT_PORTM_INEN_PIN7_Pos 7 +#define PORT_PORTM_INEN_PIN7_Msk (0x01 << PORT_PORTM_INEN_PIN7_Pos) +#define PORT_PORTM_INEN_PIN8_Pos 8 +#define PORT_PORTM_INEN_PIN8_Msk (0x01 << PORT_PORTM_INEN_PIN8_Pos) +#define PORT_PORTM_INEN_PIN9_Pos 9 +#define PORT_PORTM_INEN_PIN9_Msk (0x01 << PORT_PORTM_INEN_PIN9_Pos) +#define PORT_PORTM_INEN_PIN10_Pos 10 +#define PORT_PORTM_INEN_PIN10_Msk (0x01 << PORT_PORTM_INEN_PIN10_Pos) +#define PORT_PORTM_INEN_PIN11_Pos 11 +#define PORT_PORTM_INEN_PIN11_Msk (0x01 << PORT_PORTM_INEN_PIN11_Pos) +#define PORT_PORTM_INEN_PIN12_Pos 12 +#define PORT_PORTM_INEN_PIN12_Msk (0x01 << PORT_PORTM_INEN_PIN12_Pos) +#define PORT_PORTM_INEN_PIN13_Pos 13 +#define PORT_PORTM_INEN_PIN13_Msk (0x01 << PORT_PORTM_INEN_PIN13_Pos) +#define PORT_PORTM_INEN_PIN14_Pos 14 +#define PORT_PORTM_INEN_PIN14_Msk (0x01 << PORT_PORTM_INEN_PIN14_Pos) +#define PORT_PORTM_INEN_PIN15_Pos 15 +#define PORT_PORTM_INEN_PIN15_Msk (0x01 << PORT_PORTM_INEN_PIN15_Pos) +#define PORT_PORTM_INEN_PIN16_Pos 16 +#define PORT_PORTM_INEN_PIN16_Msk (0x01 << PORT_PORTM_INEN_PIN16_Pos) +#define PORT_PORTM_INEN_PIN17_Pos 17 +#define PORT_PORTM_INEN_PIN17_Msk (0x01 << PORT_PORTM_INEN_PIN17_Pos) +#define PORT_PORTM_INEN_PIN18_Pos 18 +#define PORT_PORTM_INEN_PIN18_Msk (0x01 << PORT_PORTM_INEN_PIN18_Pos) +#define PORT_PORTM_INEN_PIN19_Pos 19 +#define PORT_PORTM_INEN_PIN19_Msk (0x01 << PORT_PORTM_INEN_PIN19_Pos) +#define PORT_PORTM_INEN_PIN20_Pos 20 +#define PORT_PORTM_INEN_PIN20_Msk (0x01 << PORT_PORTM_INEN_PIN20_Pos) +#define PORT_PORTM_INEN_PIN21_Pos 21 +#define PORT_PORTM_INEN_PIN21_Msk (0x01 << PORT_PORTM_INEN_PIN21_Pos) +#define PORT_PORTM_INEN_PIN22_Pos 22 +#define PORT_PORTM_INEN_PIN22_Msk (0x01 << PORT_PORTM_INEN_PIN22_Pos) +#define PORT_PORTM_INEN_PIN23_Pos 23 +#define PORT_PORTM_INEN_PIN23_Msk (0x01 << PORT_PORTM_INEN_PIN23_Pos) -#define PORT_PORTP_INEN_PIN0_Pos 0 -#define PORT_PORTP_INEN_PIN0_Msk (0x01 << PORT_PORTP_INEN_PIN0_Pos) -#define PORT_PORTP_INEN_PIN1_Pos 1 -#define PORT_PORTP_INEN_PIN1_Msk (0x01 << PORT_PORTP_INEN_PIN1_Pos) -#define PORT_PORTP_INEN_PIN2_Pos 2 -#define PORT_PORTP_INEN_PIN2_Msk (0x01 << PORT_PORTP_INEN_PIN2_Pos) -#define PORT_PORTP_INEN_PIN3_Pos 3 -#define PORT_PORTP_INEN_PIN3_Msk (0x01 << PORT_PORTP_INEN_PIN3_Pos) -#define PORT_PORTP_INEN_PIN4_Pos 4 -#define PORT_PORTP_INEN_PIN4_Msk (0x01 << PORT_PORTP_INEN_PIN4_Pos) -#define PORT_PORTP_INEN_PIN5_Pos 5 -#define PORT_PORTP_INEN_PIN5_Msk (0x01 << PORT_PORTP_INEN_PIN5_Pos) -#define PORT_PORTP_INEN_PIN6_Pos 6 -#define PORT_PORTP_INEN_PIN6_Msk (0x01 << PORT_PORTP_INEN_PIN6_Pos) -#define PORT_PORTP_INEN_PIN7_Pos 7 -#define PORT_PORTP_INEN_PIN7_Msk (0x01 << PORT_PORTP_INEN_PIN7_Pos) -#define PORT_PORTP_INEN_PIN8_Pos 8 -#define PORT_PORTP_INEN_PIN8_Msk (0x01 << PORT_PORTP_INEN_PIN8_Pos) -#define PORT_PORTP_INEN_PIN9_Pos 9 -#define PORT_PORTP_INEN_PIN9_Msk (0x01 << PORT_PORTP_INEN_PIN9_Pos) -#define PORT_PORTP_INEN_PIN10_Pos 10 -#define PORT_PORTP_INEN_PIN10_Msk (0x01 << PORT_PORTP_INEN_PIN10_Pos) -#define PORT_PORTP_INEN_PIN11_Pos 11 -#define PORT_PORTP_INEN_PIN11_Msk (0x01 << PORT_PORTP_INEN_PIN11_Pos) -#define PORT_PORTP_INEN_PIN12_Pos 12 -#define PORT_PORTP_INEN_PIN12_Msk (0x01 << PORT_PORTP_INEN_PIN12_Pos) -#define PORT_PORTP_INEN_PIN13_Pos 13 -#define PORT_PORTP_INEN_PIN13_Msk (0x01 << PORT_PORTP_INEN_PIN13_Pos) -#define PORT_PORTP_INEN_PIN14_Pos 14 -#define PORT_PORTP_INEN_PIN14_Msk (0x01 << PORT_PORTP_INEN_PIN14_Pos) -#define PORT_PORTP_INEN_PIN15_Pos 15 -#define PORT_PORTP_INEN_PIN15_Msk (0x01 << PORT_PORTP_INEN_PIN15_Pos) -#define PORT_PORTP_INEN_PIN16_Pos 16 -#define PORT_PORTP_INEN_PIN16_Msk (0x01 << PORT_PORTP_INEN_PIN16_Pos) -#define PORT_PORTP_INEN_PIN17_Pos 17 -#define PORT_PORTP_INEN_PIN17_Msk (0x01 << PORT_PORTP_INEN_PIN17_Pos) -#define PORT_PORTP_INEN_PIN18_Pos 18 -#define PORT_PORTP_INEN_PIN18_Msk (0x01 << PORT_PORTP_INEN_PIN18_Pos) -#define PORT_PORTP_INEN_PIN19_Pos 19 -#define PORT_PORTP_INEN_PIN19_Msk (0x01 << PORT_PORTP_INEN_PIN19_Pos) -#define PORT_PORTP_INEN_PIN20_Pos 20 -#define PORT_PORTP_INEN_PIN20_Msk (0x01 << PORT_PORTP_INEN_PIN20_Pos) -#define PORT_PORTP_INEN_PIN21_Pos 21 -#define PORT_PORTP_INEN_PIN21_Msk (0x01 << PORT_PORTP_INEN_PIN21_Pos) -#define PORT_PORTP_INEN_PIN22_Pos 22 -#define PORT_PORTP_INEN_PIN22_Msk (0x01 << PORT_PORTP_INEN_PIN22_Pos) -#define PORT_PORTP_INEN_PIN23_Pos 23 -#define PORT_PORTP_INEN_PIN23_Msk (0x01 << PORT_PORTP_INEN_PIN23_Pos) +#define PORT_PORTN_INEN_PIN0_Pos 0 +#define PORT_PORTN_INEN_PIN0_Msk (0x01 << PORT_PORTN_INEN_PIN0_Pos) +#define PORT_PORTN_INEN_PIN1_Pos 1 +#define PORT_PORTN_INEN_PIN1_Msk (0x01 << PORT_PORTN_INEN_PIN1_Pos) +#define PORT_PORTN_INEN_PIN2_Pos 2 +#define PORT_PORTN_INEN_PIN2_Msk (0x01 << PORT_PORTN_INEN_PIN2_Pos) +#define PORT_PORTN_INEN_PIN3_Pos 3 +#define PORT_PORTN_INEN_PIN3_Msk (0x01 << PORT_PORTN_INEN_PIN3_Pos) +#define PORT_PORTN_INEN_PIN4_Pos 4 +#define PORT_PORTN_INEN_PIN4_Msk (0x01 << PORT_PORTN_INEN_PIN4_Pos) +#define PORT_PORTN_INEN_PIN5_Pos 5 +#define PORT_PORTN_INEN_PIN5_Msk (0x01 << PORT_PORTN_INEN_PIN5_Pos) +#define PORT_PORTN_INEN_PIN6_Pos 6 +#define PORT_PORTN_INEN_PIN6_Msk (0x01 << PORT_PORTN_INEN_PIN6_Pos) +#define PORT_PORTN_INEN_PIN7_Pos 7 +#define PORT_PORTN_INEN_PIN7_Msk (0x01 << PORT_PORTN_INEN_PIN7_Pos) +#define PORT_PORTN_INEN_PIN8_Pos 8 +#define PORT_PORTN_INEN_PIN8_Msk (0x01 << PORT_PORTN_INEN_PIN8_Pos) +#define PORT_PORTN_INEN_PIN9_Pos 9 +#define PORT_PORTN_INEN_PIN9_Msk (0x01 << PORT_PORTN_INEN_PIN9_Pos) +#define PORT_PORTN_INEN_PIN10_Pos 10 +#define PORT_PORTN_INEN_PIN10_Msk (0x01 << PORT_PORTN_INEN_PIN10_Pos) +#define PORT_PORTN_INEN_PIN11_Pos 11 +#define PORT_PORTN_INEN_PIN11_Msk (0x01 << PORT_PORTN_INEN_PIN11_Pos) +#define PORT_PORTN_INEN_PIN12_Pos 12 +#define PORT_PORTN_INEN_PIN12_Msk (0x01 << PORT_PORTN_INEN_PIN12_Pos) +#define PORT_PORTN_INEN_PIN13_Pos 13 +#define PORT_PORTN_INEN_PIN13_Msk (0x01 << PORT_PORTN_INEN_PIN13_Pos) +#define PORT_PORTN_INEN_PIN14_Pos 14 +#define PORT_PORTN_INEN_PIN14_Msk (0x01 << PORT_PORTN_INEN_PIN14_Pos) +#define PORT_PORTN_INEN_PIN15_Pos 15 +#define PORT_PORTN_INEN_PIN15_Msk (0x01 << PORT_PORTN_INEN_PIN15_Pos) +#define PORT_PORTN_INEN_PIN16_Pos 16 +#define PORT_PORTN_INEN_PIN16_Msk (0x01 << PORT_PORTN_INEN_PIN16_Pos) +#define PORT_PORTN_INEN_PIN17_Pos 17 +#define PORT_PORTN_INEN_PIN17_Msk (0x01 << PORT_PORTN_INEN_PIN17_Pos) +#define PORT_PORTN_INEN_PIN18_Pos 18 +#define PORT_PORTN_INEN_PIN18_Msk (0x01 << PORT_PORTN_INEN_PIN18_Pos) +#define PORT_PORTN_INEN_PIN19_Pos 19 +#define PORT_PORTN_INEN_PIN19_Msk (0x01 << PORT_PORTN_INEN_PIN19_Pos) +#define PORT_PORTN_INEN_PIN20_Pos 20 +#define PORT_PORTN_INEN_PIN20_Msk (0x01 << PORT_PORTN_INEN_PIN20_Pos) +#define PORT_PORTN_INEN_PIN21_Pos 21 +#define PORT_PORTN_INEN_PIN21_Msk (0x01 << PORT_PORTN_INEN_PIN21_Pos) +#define PORT_PORTN_INEN_PIN22_Pos 22 +#define PORT_PORTN_INEN_PIN22_Msk (0x01 << PORT_PORTN_INEN_PIN22_Pos) +#define PORT_PORTN_INEN_PIN23_Pos 23 +#define PORT_PORTN_INEN_PIN23_Msk (0x01 << PORT_PORTN_INEN_PIN23_Pos) -typedef struct -{ - __IO uint32_t DATA; -#define PIN0 0 -#define PIN1 1 -#define PIN2 2 -#define PIN3 3 -#define PIN4 4 -#define PIN5 5 -#define PIN6 6 -#define PIN7 7 -#define PIN8 8 -#define PIN9 9 -#define PIN10 10 -#define PIN11 11 -#define PIN12 12 -#define PIN13 13 -#define PIN14 14 -#define PIN15 15 -#define PIN16 16 -#define PIN17 17 -#define PIN18 18 -#define PIN19 19 -#define PIN20 20 -#define PIN21 21 -#define PIN22 22 -#define PIN23 23 -#define PIN24 24 +#define PORT_PORTP_INEN_PIN0_Pos 0 +#define PORT_PORTP_INEN_PIN0_Msk (0x01 << PORT_PORTP_INEN_PIN0_Pos) +#define PORT_PORTP_INEN_PIN1_Pos 1 +#define PORT_PORTP_INEN_PIN1_Msk (0x01 << PORT_PORTP_INEN_PIN1_Pos) +#define PORT_PORTP_INEN_PIN2_Pos 2 +#define PORT_PORTP_INEN_PIN2_Msk (0x01 << PORT_PORTP_INEN_PIN2_Pos) +#define PORT_PORTP_INEN_PIN3_Pos 3 +#define PORT_PORTP_INEN_PIN3_Msk (0x01 << PORT_PORTP_INEN_PIN3_Pos) +#define PORT_PORTP_INEN_PIN4_Pos 4 +#define PORT_PORTP_INEN_PIN4_Msk (0x01 << PORT_PORTP_INEN_PIN4_Pos) +#define PORT_PORTP_INEN_PIN5_Pos 5 +#define PORT_PORTP_INEN_PIN5_Msk (0x01 << PORT_PORTP_INEN_PIN5_Pos) +#define PORT_PORTP_INEN_PIN6_Pos 6 +#define PORT_PORTP_INEN_PIN6_Msk (0x01 << PORT_PORTP_INEN_PIN6_Pos) +#define PORT_PORTP_INEN_PIN7_Pos 7 +#define PORT_PORTP_INEN_PIN7_Msk (0x01 << PORT_PORTP_INEN_PIN7_Pos) +#define PORT_PORTP_INEN_PIN8_Pos 8 +#define PORT_PORTP_INEN_PIN8_Msk (0x01 << PORT_PORTP_INEN_PIN8_Pos) +#define PORT_PORTP_INEN_PIN9_Pos 9 +#define PORT_PORTP_INEN_PIN9_Msk (0x01 << PORT_PORTP_INEN_PIN9_Pos) +#define PORT_PORTP_INEN_PIN10_Pos 10 +#define PORT_PORTP_INEN_PIN10_Msk (0x01 << PORT_PORTP_INEN_PIN10_Pos) +#define PORT_PORTP_INEN_PIN11_Pos 11 +#define PORT_PORTP_INEN_PIN11_Msk (0x01 << PORT_PORTP_INEN_PIN11_Pos) +#define PORT_PORTP_INEN_PIN12_Pos 12 +#define PORT_PORTP_INEN_PIN12_Msk (0x01 << PORT_PORTP_INEN_PIN12_Pos) +#define PORT_PORTP_INEN_PIN13_Pos 13 +#define PORT_PORTP_INEN_PIN13_Msk (0x01 << PORT_PORTP_INEN_PIN13_Pos) +#define PORT_PORTP_INEN_PIN14_Pos 14 +#define PORT_PORTP_INEN_PIN14_Msk (0x01 << PORT_PORTP_INEN_PIN14_Pos) +#define PORT_PORTP_INEN_PIN15_Pos 15 +#define PORT_PORTP_INEN_PIN15_Msk (0x01 << PORT_PORTP_INEN_PIN15_Pos) +#define PORT_PORTP_INEN_PIN16_Pos 16 +#define PORT_PORTP_INEN_PIN16_Msk (0x01 << PORT_PORTP_INEN_PIN16_Pos) +#define PORT_PORTP_INEN_PIN17_Pos 17 +#define PORT_PORTP_INEN_PIN17_Msk (0x01 << PORT_PORTP_INEN_PIN17_Pos) +#define PORT_PORTP_INEN_PIN18_Pos 18 +#define PORT_PORTP_INEN_PIN18_Msk (0x01 << PORT_PORTP_INEN_PIN18_Pos) +#define PORT_PORTP_INEN_PIN19_Pos 19 +#define PORT_PORTP_INEN_PIN19_Msk (0x01 << PORT_PORTP_INEN_PIN19_Pos) +#define PORT_PORTP_INEN_PIN20_Pos 20 +#define PORT_PORTP_INEN_PIN20_Msk (0x01 << PORT_PORTP_INEN_PIN20_Pos) +#define PORT_PORTP_INEN_PIN21_Pos 21 +#define PORT_PORTP_INEN_PIN21_Msk (0x01 << PORT_PORTP_INEN_PIN21_Pos) +#define PORT_PORTP_INEN_PIN22_Pos 22 +#define PORT_PORTP_INEN_PIN22_Msk (0x01 << PORT_PORTP_INEN_PIN22_Pos) +#define PORT_PORTP_INEN_PIN23_Pos 23 +#define PORT_PORTP_INEN_PIN23_Msk (0x01 << PORT_PORTP_INEN_PIN23_Pos) - __IO uint32_t DIR; //0 输入 1 输出 - __IO uint32_t INTLVLTRG; //Interrupt Level Trigger 1 电平触发中断 0 边沿触发中断 - __IO uint32_t INTBE; //Both Edge,当INTLVLTRG设为边沿触发中断时,此位置1表示上升沿和下降沿都触发中断,置0时触发边沿由INTRISEEN选择 - __IO uint32_t INTRISEEN; //Interrupt Rise Edge Enable 1 上升沿/高电平触发中断 0 下降沿/低电平触发中断 +typedef struct { + __IO uint32_t DATA; +#define PIN0 0 +#define PIN1 1 +#define PIN2 2 +#define PIN3 3 +#define PIN4 4 +#define PIN5 5 +#define PIN6 6 +#define PIN7 7 +#define PIN8 8 +#define PIN9 9 +#define PIN10 10 +#define PIN11 11 +#define PIN12 12 +#define PIN13 13 +#define PIN14 14 +#define PIN15 15 +#define PIN16 16 +#define PIN17 17 +#define PIN18 18 +#define PIN19 19 +#define PIN20 20 +#define PIN21 21 +#define PIN22 22 +#define PIN23 23 +#define PIN24 24 - __IO uint32_t INTEN; //1 中断使能 0 中断禁止 + __IO uint32_t DIR; //0 1 - __IO uint32_t INTRAWSTAT; //中断检测单元是否检测到了触发中断的条件 1 检测到了中断触发条件 0 没有检测到中断触发条件 + __IO uint32_t INTLVLTRG; //Interrupt Level Trigger 1 ƽж 0 شж - __IO uint32_t INTSTAT; //INTSTAT.PIN0 = INTRAWSTAT.PIN0 & INTEN.PIN0 + __IO uint32_t INTBE; //Both EdgeINTLVLTRGΪشжʱλ1ʾغ½ضжϣ0ʱINTRISEENѡ - __IO uint32_t INTCLR; //写1清除中断标志,只对边沿触发中断有用 + __IO uint32_t INTRISEEN; //Interrupt Rise Edge Enable 1 /ߵƽж 0 ½/͵ƽж + + __IO uint32_t INTEN; //1 жʹ 0 жϽֹ + + __IO uint32_t INTRAWSTAT; //жϼⵥԪǷ⵽˴жϵ 1 ⵽жϴ 0 ûм⵽жϴ + + __IO uint32_t INTSTAT; //INTSTAT.PIN0 = INTRAWSTAT.PIN0 & INTEN.PIN0 + + __IO uint32_t INTCLR; //д1жϱ־ֻԱشж } GPIO_TypeDef; -#define GPIO_DATA_PIN0_Pos 0 -#define GPIO_DATA_PIN0_Msk (0x01 << GPIO_DATA_PIN0_Pos) -#define GPIO_DATA_PIN1_Pos 1 -#define GPIO_DATA_PIN1_Msk (0x01 << GPIO_DATA_PIN1_Pos) -#define GPIO_DATA_PIN2_Pos 2 -#define GPIO_DATA_PIN2_Msk (0x01 << GPIO_DATA_PIN2_Pos) -#define GPIO_DATA_PIN3_Pos 3 -#define GPIO_DATA_PIN3_Msk (0x01 << GPIO_DATA_PIN3_Pos) -#define GPIO_DATA_PIN4_Pos 4 -#define GPIO_DATA_PIN4_Msk (0x01 << GPIO_DATA_PIN4_Pos) -#define GPIO_DATA_PIN5_Pos 5 -#define GPIO_DATA_PIN5_Msk (0x01 << GPIO_DATA_PIN5_Pos) -#define GPIO_DATA_PIN6_Pos 6 -#define GPIO_DATA_PIN6_Msk (0x01 << GPIO_DATA_PIN6_Pos) -#define GPIO_DATA_PIN7_Pos 7 -#define GPIO_DATA_PIN7_Msk (0x01 << GPIO_DATA_PIN7_Pos) -#define GPIO_DATA_PIN8_Pos 8 -#define GPIO_DATA_PIN8_Msk (0x01 << GPIO_DATA_PIN8_Pos) -#define GPIO_DATA_PIN9_Pos 9 -#define GPIO_DATA_PIN9_Msk (0x01 << GPIO_DATA_PIN9_Pos) -#define GPIO_DATA_PIN10_Pos 10 -#define GPIO_DATA_PIN10_Msk (0x01 << GPIO_DATA_PIN10_Pos) -#define GPIO_DATA_PIN11_Pos 11 -#define GPIO_DATA_PIN11_Msk (0x01 << GPIO_DATA_PIN11_Pos) -#define GPIO_DATA_PIN12_Pos 12 -#define GPIO_DATA_PIN12_Msk (0x01 << GPIO_DATA_PIN12_Pos) -#define GPIO_DATA_PIN13_Pos 13 -#define GPIO_DATA_PIN13_Msk (0x01 << GPIO_DATA_PIN13_Pos) -#define GPIO_DATA_PIN14_Pos 14 -#define GPIO_DATA_PIN14_Msk (0x01 << GPIO_DATA_PIN14_Pos) -#define GPIO_DATA_PIN15_Pos 15 -#define GPIO_DATA_PIN15_Msk (0x01 << GPIO_DATA_PIN15_Pos) -#define GPIO_DATA_PIN16_Pos 16 -#define GPIO_DATA_PIN16_Msk (0x01 << GPIO_DATA_PIN16_Pos) -#define GPIO_DATA_PIN17_Pos 17 -#define GPIO_DATA_PIN17_Msk (0x01 << GPIO_DATA_PIN17_Pos) -#define GPIO_DATA_PIN18_Pos 18 -#define GPIO_DATA_PIN18_Msk (0x01 << GPIO_DATA_PIN18_Pos) -#define GPIO_DATA_PIN19_Pos 19 -#define GPIO_DATA_PIN19_Msk (0x01 << GPIO_DATA_PIN19_Pos) -#define GPIO_DATA_PIN20_Pos 20 -#define GPIO_DATA_PIN20_Msk (0x01 << GPIO_DATA_PIN20_Pos) -#define GPIO_DATA_PIN21_Pos 21 -#define GPIO_DATA_PIN21_Msk (0x01 << GPIO_DATA_PIN21_Pos) -#define GPIO_DATA_PIN22_Pos 22 -#define GPIO_DATA_PIN22_Msk (0x01 << GPIO_DATA_PIN22_Pos) -#define GPIO_DATA_PIN23_Pos 23 -#define GPIO_DATA_PIN23_Msk (0x01 << GPIO_DATA_PIN23_Pos) -#define GPIO_DIR_PIN0_Pos 0 -#define GPIO_DIR_PIN0_Msk (0x01 << GPIO_DIR_PIN0_Pos) -#define GPIO_DIR_PIN1_Pos 1 -#define GPIO_DIR_PIN1_Msk (0x01 << GPIO_DIR_PIN1_Pos) -#define GPIO_DIR_PIN2_Pos 2 -#define GPIO_DIR_PIN2_Msk (0x01 << GPIO_DIR_PIN2_Pos) -#define GPIO_DIR_PIN3_Pos 3 -#define GPIO_DIR_PIN3_Msk (0x01 << GPIO_DIR_PIN3_Pos) -#define GPIO_DIR_PIN4_Pos 4 -#define GPIO_DIR_PIN4_Msk (0x01 << GPIO_DIR_PIN4_Pos) -#define GPIO_DIR_PIN5_Pos 5 -#define GPIO_DIR_PIN5_Msk (0x01 << GPIO_DIR_PIN5_Pos) -#define GPIO_DIR_PIN6_Pos 6 -#define GPIO_DIR_PIN6_Msk (0x01 << GPIO_DIR_PIN6_Pos) -#define GPIO_DIR_PIN7_Pos 7 -#define GPIO_DIR_PIN7_Msk (0x01 << GPIO_DIR_PIN7_Pos) -#define GPIO_DIR_PIN8_Pos 8 -#define GPIO_DIR_PIN8_Msk (0x01 << GPIO_DIR_PIN8_Pos) -#define GPIO_DIR_PIN9_Pos 9 -#define GPIO_DIR_PIN9_Msk (0x01 << GPIO_DIR_PIN9_Pos) -#define GPIO_DIR_PIN10_Pos 10 -#define GPIO_DIR_PIN10_Msk (0x01 << GPIO_DIR_PIN10_Pos) -#define GPIO_DIR_PIN11_Pos 11 -#define GPIO_DIR_PIN11_Msk (0x01 << GPIO_DIR_PIN11_Pos) -#define GPIO_DIR_PIN12_Pos 12 -#define GPIO_DIR_PIN12_Msk (0x01 << GPIO_DIR_PIN12_Pos) -#define GPIO_DIR_PIN13_Pos 13 -#define GPIO_DIR_PIN13_Msk (0x01 << GPIO_DIR_PIN13_Pos) -#define GPIO_DIR_PIN14_Pos 14 -#define GPIO_DIR_PIN14_Msk (0x01 << GPIO_DIR_PIN14_Pos) -#define GPIO_DIR_PIN15_Pos 15 -#define GPIO_DIR_PIN15_Msk (0x01 << GPIO_DIR_PIN15_Pos) -#define GPIO_DIR_PIN16_Pos 16 -#define GPIO_DIR_PIN16_Msk (0x01 << GPIO_DIR_PIN16_Pos) -#define GPIO_DIR_PIN17_Pos 17 -#define GPIO_DIR_PIN17_Msk (0x01 << GPIO_DIR_PIN17_Pos) -#define GPIO_DIR_PIN18_Pos 18 -#define GPIO_DIR_PIN18_Msk (0x01 << GPIO_DIR_PIN18_Pos) -#define GPIO_DIR_PIN19_Pos 19 -#define GPIO_DIR_PIN19_Msk (0x01 << GPIO_DIR_PIN19_Pos) -#define GPIO_DIR_PIN20_Pos 20 -#define GPIO_DIR_PIN20_Msk (0x01 << GPIO_DIR_PIN20_Pos) -#define GPIO_DIR_PIN21_Pos 21 -#define GPIO_DIR_PIN21_Msk (0x01 << GPIO_DIR_PIN21_Pos) -#define GPIO_DIR_PIN22_Pos 22 -#define GPIO_DIR_PIN22_Msk (0x01 << GPIO_DIR_PIN22_Pos) -#define GPIO_DIR_PIN23_Pos 23 -#define GPIO_DIR_PIN23_Msk (0x01 << GPIO_DIR_PIN23_Pos) +#define GPIO_DATA_PIN0_Pos 0 +#define GPIO_DATA_PIN0_Msk (0x01 << GPIO_DATA_PIN0_Pos) +#define GPIO_DATA_PIN1_Pos 1 +#define GPIO_DATA_PIN1_Msk (0x01 << GPIO_DATA_PIN1_Pos) +#define GPIO_DATA_PIN2_Pos 2 +#define GPIO_DATA_PIN2_Msk (0x01 << GPIO_DATA_PIN2_Pos) +#define GPIO_DATA_PIN3_Pos 3 +#define GPIO_DATA_PIN3_Msk (0x01 << GPIO_DATA_PIN3_Pos) +#define GPIO_DATA_PIN4_Pos 4 +#define GPIO_DATA_PIN4_Msk (0x01 << GPIO_DATA_PIN4_Pos) +#define GPIO_DATA_PIN5_Pos 5 +#define GPIO_DATA_PIN5_Msk (0x01 << GPIO_DATA_PIN5_Pos) +#define GPIO_DATA_PIN6_Pos 6 +#define GPIO_DATA_PIN6_Msk (0x01 << GPIO_DATA_PIN6_Pos) +#define GPIO_DATA_PIN7_Pos 7 +#define GPIO_DATA_PIN7_Msk (0x01 << GPIO_DATA_PIN7_Pos) +#define GPIO_DATA_PIN8_Pos 8 +#define GPIO_DATA_PIN8_Msk (0x01 << GPIO_DATA_PIN8_Pos) +#define GPIO_DATA_PIN9_Pos 9 +#define GPIO_DATA_PIN9_Msk (0x01 << GPIO_DATA_PIN9_Pos) +#define GPIO_DATA_PIN10_Pos 10 +#define GPIO_DATA_PIN10_Msk (0x01 << GPIO_DATA_PIN10_Pos) +#define GPIO_DATA_PIN11_Pos 11 +#define GPIO_DATA_PIN11_Msk (0x01 << GPIO_DATA_PIN11_Pos) +#define GPIO_DATA_PIN12_Pos 12 +#define GPIO_DATA_PIN12_Msk (0x01 << GPIO_DATA_PIN12_Pos) +#define GPIO_DATA_PIN13_Pos 13 +#define GPIO_DATA_PIN13_Msk (0x01 << GPIO_DATA_PIN13_Pos) +#define GPIO_DATA_PIN14_Pos 14 +#define GPIO_DATA_PIN14_Msk (0x01 << GPIO_DATA_PIN14_Pos) +#define GPIO_DATA_PIN15_Pos 15 +#define GPIO_DATA_PIN15_Msk (0x01 << GPIO_DATA_PIN15_Pos) +#define GPIO_DATA_PIN16_Pos 16 +#define GPIO_DATA_PIN16_Msk (0x01 << GPIO_DATA_PIN16_Pos) +#define GPIO_DATA_PIN17_Pos 17 +#define GPIO_DATA_PIN17_Msk (0x01 << GPIO_DATA_PIN17_Pos) +#define GPIO_DATA_PIN18_Pos 18 +#define GPIO_DATA_PIN18_Msk (0x01 << GPIO_DATA_PIN18_Pos) +#define GPIO_DATA_PIN19_Pos 19 +#define GPIO_DATA_PIN19_Msk (0x01 << GPIO_DATA_PIN19_Pos) +#define GPIO_DATA_PIN20_Pos 20 +#define GPIO_DATA_PIN20_Msk (0x01 << GPIO_DATA_PIN20_Pos) +#define GPIO_DATA_PIN21_Pos 21 +#define GPIO_DATA_PIN21_Msk (0x01 << GPIO_DATA_PIN21_Pos) +#define GPIO_DATA_PIN22_Pos 22 +#define GPIO_DATA_PIN22_Msk (0x01 << GPIO_DATA_PIN22_Pos) +#define GPIO_DATA_PIN23_Pos 23 +#define GPIO_DATA_PIN23_Msk (0x01 << GPIO_DATA_PIN23_Pos) -#define GPIO_INTLVLTRG_PIN0_Pos 0 -#define GPIO_INTLVLTRG_PIN0_Msk (0x01 << GPIO_INTLVLTRG_PIN0_Pos) -#define GPIO_INTLVLTRG_PIN1_Pos 1 -#define GPIO_INTLVLTRG_PIN1_Msk (0x01 << GPIO_INTLVLTRG_PIN1_Pos) -#define GPIO_INTLVLTRG_PIN2_Pos 2 -#define GPIO_INTLVLTRG_PIN2_Msk (0x01 << GPIO_INTLVLTRG_PIN2_Pos) -#define GPIO_INTLVLTRG_PIN3_Pos 3 -#define GPIO_INTLVLTRG_PIN3_Msk (0x01 << GPIO_INTLVLTRG_PIN3_Pos) -#define GPIO_INTLVLTRG_PIN4_Pos 4 -#define GPIO_INTLVLTRG_PIN4_Msk (0x01 << GPIO_INTLVLTRG_PIN4_Pos) -#define GPIO_INTLVLTRG_PIN5_Pos 5 -#define GPIO_INTLVLTRG_PIN5_Msk (0x01 << GPIO_INTLVLTRG_PIN5_Pos) -#define GPIO_INTLVLTRG_PIN6_Pos 6 -#define GPIO_INTLVLTRG_PIN6_Msk (0x01 << GPIO_INTLVLTRG_PIN6_Pos) -#define GPIO_INTLVLTRG_PIN7_Pos 7 -#define GPIO_INTLVLTRG_PIN7_Msk (0x01 << GPIO_INTLVLTRG_PIN7_Pos) -#define GPIO_INTLVLTRG_PIN8_Pos 8 -#define GPIO_INTLVLTRG_PIN8_Msk (0x01 << GPIO_INTLVLTRG_PIN8_Pos) -#define GPIO_INTLVLTRG_PIN9_Pos 9 -#define GPIO_INTLVLTRG_PIN9_Msk (0x01 << GPIO_INTLVLTRG_PIN9_Pos) -#define GPIO_INTLVLTRG_PIN10_Pos 10 -#define GPIO_INTLVLTRG_PIN10_Msk (0x01 << GPIO_INTLVLTRG_PIN10_Pos) -#define GPIO_INTLVLTRG_PIN11_Pos 11 -#define GPIO_INTLVLTRG_PIN11_Msk (0x01 << GPIO_INTLVLTRG_PIN11_Pos) -#define GPIO_INTLVLTRG_PIN12_Pos 12 -#define GPIO_INTLVLTRG_PIN12_Msk (0x01 << GPIO_INTLVLTRG_PIN12_Pos) -#define GPIO_INTLVLTRG_PIN13_Pos 13 -#define GPIO_INTLVLTRG_PIN13_Msk (0x01 << GPIO_INTLVLTRG_PIN13_Pos) -#define GPIO_INTLVLTRG_PIN14_Pos 14 -#define GPIO_INTLVLTRG_PIN14_Msk (0x01 << GPIO_INTLVLTRG_PIN14_Pos) -#define GPIO_INTLVLTRG_PIN15_Pos 15 -#define GPIO_INTLVLTRG_PIN15_Msk (0x01 << GPIO_INTLVLTRG_PIN15_Pos) -#define GPIO_INTLVLTRG_PIN16_Pos 16 -#define GPIO_INTLVLTRG_PIN16_Msk (0x01 << GPIO_INTLVLTRG_PIN16_Pos) -#define GPIO_INTLVLTRG_PIN17_Pos 17 -#define GPIO_INTLVLTRG_PIN17_Msk (0x01 << GPIO_INTLVLTRG_PIN17_Pos) -#define GPIO_INTLVLTRG_PIN18_Pos 18 -#define GPIO_INTLVLTRG_PIN18_Msk (0x01 << GPIO_INTLVLTRG_PIN18_Pos) -#define GPIO_INTLVLTRG_PIN19_Pos 19 -#define GPIO_INTLVLTRG_PIN19_Msk (0x01 << GPIO_INTLVLTRG_PIN19_Pos) -#define GPIO_INTLVLTRG_PIN20_Pos 20 -#define GPIO_INTLVLTRG_PIN20_Msk (0x01 << GPIO_INTLVLTRG_PIN20_Pos) -#define GPIO_INTLVLTRG_PIN21_Pos 21 -#define GPIO_INTLVLTRG_PIN21_Msk (0x01 << GPIO_INTLVLTRG_PIN21_Pos) -#define GPIO_INTLVLTRG_PIN22_Pos 22 -#define GPIO_INTLVLTRG_PIN22_Msk (0x01 << GPIO_INTLVLTRG_PIN22_Pos) -#define GPIO_INTLVLTRG_PIN23_Pos 23 -#define GPIO_INTLVLTRG_PIN23_Msk (0x01 << GPIO_INTLVLTRG_PIN23_Pos) +#define GPIO_DIR_PIN0_Pos 0 +#define GPIO_DIR_PIN0_Msk (0x01 << GPIO_DIR_PIN0_Pos) +#define GPIO_DIR_PIN1_Pos 1 +#define GPIO_DIR_PIN1_Msk (0x01 << GPIO_DIR_PIN1_Pos) +#define GPIO_DIR_PIN2_Pos 2 +#define GPIO_DIR_PIN2_Msk (0x01 << GPIO_DIR_PIN2_Pos) +#define GPIO_DIR_PIN3_Pos 3 +#define GPIO_DIR_PIN3_Msk (0x01 << GPIO_DIR_PIN3_Pos) +#define GPIO_DIR_PIN4_Pos 4 +#define GPIO_DIR_PIN4_Msk (0x01 << GPIO_DIR_PIN4_Pos) +#define GPIO_DIR_PIN5_Pos 5 +#define GPIO_DIR_PIN5_Msk (0x01 << GPIO_DIR_PIN5_Pos) +#define GPIO_DIR_PIN6_Pos 6 +#define GPIO_DIR_PIN6_Msk (0x01 << GPIO_DIR_PIN6_Pos) +#define GPIO_DIR_PIN7_Pos 7 +#define GPIO_DIR_PIN7_Msk (0x01 << GPIO_DIR_PIN7_Pos) +#define GPIO_DIR_PIN8_Pos 8 +#define GPIO_DIR_PIN8_Msk (0x01 << GPIO_DIR_PIN8_Pos) +#define GPIO_DIR_PIN9_Pos 9 +#define GPIO_DIR_PIN9_Msk (0x01 << GPIO_DIR_PIN9_Pos) +#define GPIO_DIR_PIN10_Pos 10 +#define GPIO_DIR_PIN10_Msk (0x01 << GPIO_DIR_PIN10_Pos) +#define GPIO_DIR_PIN11_Pos 11 +#define GPIO_DIR_PIN11_Msk (0x01 << GPIO_DIR_PIN11_Pos) +#define GPIO_DIR_PIN12_Pos 12 +#define GPIO_DIR_PIN12_Msk (0x01 << GPIO_DIR_PIN12_Pos) +#define GPIO_DIR_PIN13_Pos 13 +#define GPIO_DIR_PIN13_Msk (0x01 << GPIO_DIR_PIN13_Pos) +#define GPIO_DIR_PIN14_Pos 14 +#define GPIO_DIR_PIN14_Msk (0x01 << GPIO_DIR_PIN14_Pos) +#define GPIO_DIR_PIN15_Pos 15 +#define GPIO_DIR_PIN15_Msk (0x01 << GPIO_DIR_PIN15_Pos) +#define GPIO_DIR_PIN16_Pos 16 +#define GPIO_DIR_PIN16_Msk (0x01 << GPIO_DIR_PIN16_Pos) +#define GPIO_DIR_PIN17_Pos 17 +#define GPIO_DIR_PIN17_Msk (0x01 << GPIO_DIR_PIN17_Pos) +#define GPIO_DIR_PIN18_Pos 18 +#define GPIO_DIR_PIN18_Msk (0x01 << GPIO_DIR_PIN18_Pos) +#define GPIO_DIR_PIN19_Pos 19 +#define GPIO_DIR_PIN19_Msk (0x01 << GPIO_DIR_PIN19_Pos) +#define GPIO_DIR_PIN20_Pos 20 +#define GPIO_DIR_PIN20_Msk (0x01 << GPIO_DIR_PIN20_Pos) +#define GPIO_DIR_PIN21_Pos 21 +#define GPIO_DIR_PIN21_Msk (0x01 << GPIO_DIR_PIN21_Pos) +#define GPIO_DIR_PIN22_Pos 22 +#define GPIO_DIR_PIN22_Msk (0x01 << GPIO_DIR_PIN22_Pos) +#define GPIO_DIR_PIN23_Pos 23 +#define GPIO_DIR_PIN23_Msk (0x01 << GPIO_DIR_PIN23_Pos) -#define GPIO_INTBE_PIN0_Pos 0 -#define GPIO_INTBE_PIN0_Msk (0x01 << GPIO_INTBE_PIN0_Pos) -#define GPIO_INTBE_PIN1_Pos 1 -#define GPIO_INTBE_PIN1_Msk (0x01 << GPIO_INTBE_PIN1_Pos) -#define GPIO_INTBE_PIN2_Pos 2 -#define GPIO_INTBE_PIN2_Msk (0x01 << GPIO_INTBE_PIN2_Pos) -#define GPIO_INTBE_PIN3_Pos 3 -#define GPIO_INTBE_PIN3_Msk (0x01 << GPIO_INTBE_PIN3_Pos) -#define GPIO_INTBE_PIN4_Pos 4 -#define GPIO_INTBE_PIN4_Msk (0x01 << GPIO_INTBE_PIN4_Pos) -#define GPIO_INTBE_PIN5_Pos 5 -#define GPIO_INTBE_PIN5_Msk (0x01 << GPIO_INTBE_PIN5_Pos) -#define GPIO_INTBE_PIN6_Pos 6 -#define GPIO_INTBE_PIN6_Msk (0x01 << GPIO_INTBE_PIN6_Pos) -#define GPIO_INTBE_PIN7_Pos 7 -#define GPIO_INTBE_PIN7_Msk (0x01 << GPIO_INTBE_PIN7_Pos) -#define GPIO_INTBE_PIN8_Pos 8 -#define GPIO_INTBE_PIN8_Msk (0x01 << GPIO_INTBE_PIN8_Pos) -#define GPIO_INTBE_PIN9_Pos 9 -#define GPIO_INTBE_PIN9_Msk (0x01 << GPIO_INTBE_PIN9_Pos) -#define GPIO_INTBE_PIN10_Pos 10 -#define GPIO_INTBE_PIN10_Msk (0x01 << GPIO_INTBE_PIN10_Pos) -#define GPIO_INTBE_PIN11_Pos 11 -#define GPIO_INTBE_PIN11_Msk (0x01 << GPIO_INTBE_PIN11_Pos) -#define GPIO_INTBE_PIN12_Pos 12 -#define GPIO_INTBE_PIN12_Msk (0x01 << GPIO_INTBE_PIN12_Pos) -#define GPIO_INTBE_PIN13_Pos 13 -#define GPIO_INTBE_PIN13_Msk (0x01 << GPIO_INTBE_PIN13_Pos) -#define GPIO_INTBE_PIN14_Pos 14 -#define GPIO_INTBE_PIN14_Msk (0x01 << GPIO_INTBE_PIN14_Pos) -#define GPIO_INTBE_PIN15_Pos 15 -#define GPIO_INTBE_PIN15_Msk (0x01 << GPIO_INTBE_PIN15_Pos) -#define GPIO_INTBE_PIN16_Pos 16 -#define GPIO_INTBE_PIN16_Msk (0x01 << GPIO_INTBE_PIN16_Pos) -#define GPIO_INTBE_PIN17_Pos 17 -#define GPIO_INTBE_PIN17_Msk (0x01 << GPIO_INTBE_PIN17_Pos) -#define GPIO_INTBE_PIN18_Pos 18 -#define GPIO_INTBE_PIN18_Msk (0x01 << GPIO_INTBE_PIN18_Pos) -#define GPIO_INTBE_PIN19_Pos 19 -#define GPIO_INTBE_PIN19_Msk (0x01 << GPIO_INTBE_PIN19_Pos) -#define GPIO_INTBE_PIN20_Pos 20 -#define GPIO_INTBE_PIN20_Msk (0x01 << GPIO_INTBE_PIN20_Pos) -#define GPIO_INTBE_PIN21_Pos 21 -#define GPIO_INTBE_PIN21_Msk (0x01 << GPIO_INTBE_PIN21_Pos) -#define GPIO_INTBE_PIN22_Pos 22 -#define GPIO_INTBE_PIN22_Msk (0x01 << GPIO_INTBE_PIN22_Pos) -#define GPIO_INTBE_PIN23_Pos 23 -#define GPIO_INTBE_PIN23_Msk (0x01 << GPIO_INTBE_PIN23_Pos) +#define GPIO_INTLVLTRG_PIN0_Pos 0 +#define GPIO_INTLVLTRG_PIN0_Msk (0x01 << GPIO_INTLVLTRG_PIN0_Pos) +#define GPIO_INTLVLTRG_PIN1_Pos 1 +#define GPIO_INTLVLTRG_PIN1_Msk (0x01 << GPIO_INTLVLTRG_PIN1_Pos) +#define GPIO_INTLVLTRG_PIN2_Pos 2 +#define GPIO_INTLVLTRG_PIN2_Msk (0x01 << GPIO_INTLVLTRG_PIN2_Pos) +#define GPIO_INTLVLTRG_PIN3_Pos 3 +#define GPIO_INTLVLTRG_PIN3_Msk (0x01 << GPIO_INTLVLTRG_PIN3_Pos) +#define GPIO_INTLVLTRG_PIN4_Pos 4 +#define GPIO_INTLVLTRG_PIN4_Msk (0x01 << GPIO_INTLVLTRG_PIN4_Pos) +#define GPIO_INTLVLTRG_PIN5_Pos 5 +#define GPIO_INTLVLTRG_PIN5_Msk (0x01 << GPIO_INTLVLTRG_PIN5_Pos) +#define GPIO_INTLVLTRG_PIN6_Pos 6 +#define GPIO_INTLVLTRG_PIN6_Msk (0x01 << GPIO_INTLVLTRG_PIN6_Pos) +#define GPIO_INTLVLTRG_PIN7_Pos 7 +#define GPIO_INTLVLTRG_PIN7_Msk (0x01 << GPIO_INTLVLTRG_PIN7_Pos) +#define GPIO_INTLVLTRG_PIN8_Pos 8 +#define GPIO_INTLVLTRG_PIN8_Msk (0x01 << GPIO_INTLVLTRG_PIN8_Pos) +#define GPIO_INTLVLTRG_PIN9_Pos 9 +#define GPIO_INTLVLTRG_PIN9_Msk (0x01 << GPIO_INTLVLTRG_PIN9_Pos) +#define GPIO_INTLVLTRG_PIN10_Pos 10 +#define GPIO_INTLVLTRG_PIN10_Msk (0x01 << GPIO_INTLVLTRG_PIN10_Pos) +#define GPIO_INTLVLTRG_PIN11_Pos 11 +#define GPIO_INTLVLTRG_PIN11_Msk (0x01 << GPIO_INTLVLTRG_PIN11_Pos) +#define GPIO_INTLVLTRG_PIN12_Pos 12 +#define GPIO_INTLVLTRG_PIN12_Msk (0x01 << GPIO_INTLVLTRG_PIN12_Pos) +#define GPIO_INTLVLTRG_PIN13_Pos 13 +#define GPIO_INTLVLTRG_PIN13_Msk (0x01 << GPIO_INTLVLTRG_PIN13_Pos) +#define GPIO_INTLVLTRG_PIN14_Pos 14 +#define GPIO_INTLVLTRG_PIN14_Msk (0x01 << GPIO_INTLVLTRG_PIN14_Pos) +#define GPIO_INTLVLTRG_PIN15_Pos 15 +#define GPIO_INTLVLTRG_PIN15_Msk (0x01 << GPIO_INTLVLTRG_PIN15_Pos) +#define GPIO_INTLVLTRG_PIN16_Pos 16 +#define GPIO_INTLVLTRG_PIN16_Msk (0x01 << GPIO_INTLVLTRG_PIN16_Pos) +#define GPIO_INTLVLTRG_PIN17_Pos 17 +#define GPIO_INTLVLTRG_PIN17_Msk (0x01 << GPIO_INTLVLTRG_PIN17_Pos) +#define GPIO_INTLVLTRG_PIN18_Pos 18 +#define GPIO_INTLVLTRG_PIN18_Msk (0x01 << GPIO_INTLVLTRG_PIN18_Pos) +#define GPIO_INTLVLTRG_PIN19_Pos 19 +#define GPIO_INTLVLTRG_PIN19_Msk (0x01 << GPIO_INTLVLTRG_PIN19_Pos) +#define GPIO_INTLVLTRG_PIN20_Pos 20 +#define GPIO_INTLVLTRG_PIN20_Msk (0x01 << GPIO_INTLVLTRG_PIN20_Pos) +#define GPIO_INTLVLTRG_PIN21_Pos 21 +#define GPIO_INTLVLTRG_PIN21_Msk (0x01 << GPIO_INTLVLTRG_PIN21_Pos) +#define GPIO_INTLVLTRG_PIN22_Pos 22 +#define GPIO_INTLVLTRG_PIN22_Msk (0x01 << GPIO_INTLVLTRG_PIN22_Pos) +#define GPIO_INTLVLTRG_PIN23_Pos 23 +#define GPIO_INTLVLTRG_PIN23_Msk (0x01 << GPIO_INTLVLTRG_PIN23_Pos) -#define GPIO_INTRISEEN_PIN0_Pos 0 -#define GPIO_INTRISEEN_PIN0_Msk (0x01 << GPIO_INTRISEEN_PIN0_Pos) -#define GPIO_INTRISEEN_PIN1_Pos 1 -#define GPIO_INTRISEEN_PIN1_Msk (0x01 << GPIO_INTRISEEN_PIN1_Pos) -#define GPIO_INTRISEEN_PIN2_Pos 2 -#define GPIO_INTRISEEN_PIN2_Msk (0x01 << GPIO_INTRISEEN_PIN2_Pos) -#define GPIO_INTRISEEN_PIN3_Pos 3 -#define GPIO_INTRISEEN_PIN3_Msk (0x01 << GPIO_INTRISEEN_PIN3_Pos) -#define GPIO_INTRISEEN_PIN4_Pos 4 -#define GPIO_INTRISEEN_PIN4_Msk (0x01 << GPIO_INTRISEEN_PIN4_Pos) -#define GPIO_INTRISEEN_PIN5_Pos 5 -#define GPIO_INTRISEEN_PIN5_Msk (0x01 << GPIO_INTRISEEN_PIN5_Pos) -#define GPIO_INTRISEEN_PIN6_Pos 6 -#define GPIO_INTRISEEN_PIN6_Msk (0x01 << GPIO_INTRISEEN_PIN6_Pos) -#define GPIO_INTRISEEN_PIN7_Pos 7 -#define GPIO_INTRISEEN_PIN7_Msk (0x01 << GPIO_INTRISEEN_PIN7_Pos) -#define GPIO_INTRISEEN_PIN8_Pos 8 -#define GPIO_INTRISEEN_PIN8_Msk (0x01 << GPIO_INTRISEEN_PIN8_Pos) -#define GPIO_INTRISEEN_PIN9_Pos 9 -#define GPIO_INTRISEEN_PIN9_Msk (0x01 << GPIO_INTRISEEN_PIN9_Pos) -#define GPIO_INTRISEEN_PIN10_Pos 10 -#define GPIO_INTRISEEN_PIN10_Msk (0x01 << GPIO_INTRISEEN_PIN10_Pos) -#define GPIO_INTRISEEN_PIN11_Pos 11 -#define GPIO_INTRISEEN_PIN11_Msk (0x01 << GPIO_INTRISEEN_PIN11_Pos) -#define GPIO_INTRISEEN_PIN12_Pos 12 -#define GPIO_INTRISEEN_PIN12_Msk (0x01 << GPIO_INTRISEEN_PIN12_Pos) -#define GPIO_INTRISEEN_PIN13_Pos 13 -#define GPIO_INTRISEEN_PIN13_Msk (0x01 << GPIO_INTRISEEN_PIN13_Pos) -#define GPIO_INTRISEEN_PIN14_Pos 14 -#define GPIO_INTRISEEN_PIN14_Msk (0x01 << GPIO_INTRISEEN_PIN14_Pos) -#define GPIO_INTRISEEN_PIN15_Pos 15 -#define GPIO_INTRISEEN_PIN15_Msk (0x01 << GPIO_INTRISEEN_PIN15_Pos) -#define GPIO_INTRISEEN_PIN16_Pos 16 -#define GPIO_INTRISEEN_PIN16_Msk (0x01 << GPIO_INTRISEEN_PIN16_Pos) -#define GPIO_INTRISEEN_PIN17_Pos 17 -#define GPIO_INTRISEEN_PIN17_Msk (0x01 << GPIO_INTRISEEN_PIN17_Pos) -#define GPIO_INTRISEEN_PIN18_Pos 18 -#define GPIO_INTRISEEN_PIN18_Msk (0x01 << GPIO_INTRISEEN_PIN18_Pos) -#define GPIO_INTRISEEN_PIN19_Pos 19 -#define GPIO_INTRISEEN_PIN19_Msk (0x01 << GPIO_INTRISEEN_PIN19_Pos) -#define GPIO_INTRISEEN_PIN20_Pos 20 -#define GPIO_INTRISEEN_PIN20_Msk (0x01 << GPIO_INTRISEEN_PIN20_Pos) -#define GPIO_INTRISEEN_PIN21_Pos 21 -#define GPIO_INTRISEEN_PIN21_Msk (0x01 << GPIO_INTRISEEN_PIN21_Pos) -#define GPIO_INTRISEEN_PIN22_Pos 22 -#define GPIO_INTRISEEN_PIN22_Msk (0x01 << GPIO_INTRISEEN_PIN22_Pos) -#define GPIO_INTRISEEN_PIN23_Pos 23 -#define GPIO_INTRISEEN_PIN23_Msk (0x01 << GPIO_INTRISEEN_PIN23_Pos) +#define GPIO_INTBE_PIN0_Pos 0 +#define GPIO_INTBE_PIN0_Msk (0x01 << GPIO_INTBE_PIN0_Pos) +#define GPIO_INTBE_PIN1_Pos 1 +#define GPIO_INTBE_PIN1_Msk (0x01 << GPIO_INTBE_PIN1_Pos) +#define GPIO_INTBE_PIN2_Pos 2 +#define GPIO_INTBE_PIN2_Msk (0x01 << GPIO_INTBE_PIN2_Pos) +#define GPIO_INTBE_PIN3_Pos 3 +#define GPIO_INTBE_PIN3_Msk (0x01 << GPIO_INTBE_PIN3_Pos) +#define GPIO_INTBE_PIN4_Pos 4 +#define GPIO_INTBE_PIN4_Msk (0x01 << GPIO_INTBE_PIN4_Pos) +#define GPIO_INTBE_PIN5_Pos 5 +#define GPIO_INTBE_PIN5_Msk (0x01 << GPIO_INTBE_PIN5_Pos) +#define GPIO_INTBE_PIN6_Pos 6 +#define GPIO_INTBE_PIN6_Msk (0x01 << GPIO_INTBE_PIN6_Pos) +#define GPIO_INTBE_PIN7_Pos 7 +#define GPIO_INTBE_PIN7_Msk (0x01 << GPIO_INTBE_PIN7_Pos) +#define GPIO_INTBE_PIN8_Pos 8 +#define GPIO_INTBE_PIN8_Msk (0x01 << GPIO_INTBE_PIN8_Pos) +#define GPIO_INTBE_PIN9_Pos 9 +#define GPIO_INTBE_PIN9_Msk (0x01 << GPIO_INTBE_PIN9_Pos) +#define GPIO_INTBE_PIN10_Pos 10 +#define GPIO_INTBE_PIN10_Msk (0x01 << GPIO_INTBE_PIN10_Pos) +#define GPIO_INTBE_PIN11_Pos 11 +#define GPIO_INTBE_PIN11_Msk (0x01 << GPIO_INTBE_PIN11_Pos) +#define GPIO_INTBE_PIN12_Pos 12 +#define GPIO_INTBE_PIN12_Msk (0x01 << GPIO_INTBE_PIN12_Pos) +#define GPIO_INTBE_PIN13_Pos 13 +#define GPIO_INTBE_PIN13_Msk (0x01 << GPIO_INTBE_PIN13_Pos) +#define GPIO_INTBE_PIN14_Pos 14 +#define GPIO_INTBE_PIN14_Msk (0x01 << GPIO_INTBE_PIN14_Pos) +#define GPIO_INTBE_PIN15_Pos 15 +#define GPIO_INTBE_PIN15_Msk (0x01 << GPIO_INTBE_PIN15_Pos) +#define GPIO_INTBE_PIN16_Pos 16 +#define GPIO_INTBE_PIN16_Msk (0x01 << GPIO_INTBE_PIN16_Pos) +#define GPIO_INTBE_PIN17_Pos 17 +#define GPIO_INTBE_PIN17_Msk (0x01 << GPIO_INTBE_PIN17_Pos) +#define GPIO_INTBE_PIN18_Pos 18 +#define GPIO_INTBE_PIN18_Msk (0x01 << GPIO_INTBE_PIN18_Pos) +#define GPIO_INTBE_PIN19_Pos 19 +#define GPIO_INTBE_PIN19_Msk (0x01 << GPIO_INTBE_PIN19_Pos) +#define GPIO_INTBE_PIN20_Pos 20 +#define GPIO_INTBE_PIN20_Msk (0x01 << GPIO_INTBE_PIN20_Pos) +#define GPIO_INTBE_PIN21_Pos 21 +#define GPIO_INTBE_PIN21_Msk (0x01 << GPIO_INTBE_PIN21_Pos) +#define GPIO_INTBE_PIN22_Pos 22 +#define GPIO_INTBE_PIN22_Msk (0x01 << GPIO_INTBE_PIN22_Pos) +#define GPIO_INTBE_PIN23_Pos 23 +#define GPIO_INTBE_PIN23_Msk (0x01 << GPIO_INTBE_PIN23_Pos) -#define GPIO_INTEN_PIN0_Pos 0 -#define GPIO_INTEN_PIN0_Msk (0x01 << GPIO_INTEN_PIN0_Pos) -#define GPIO_INTEN_PIN1_Pos 1 -#define GPIO_INTEN_PIN1_Msk (0x01 << GPIO_INTEN_PIN1_Pos) -#define GPIO_INTEN_PIN2_Pos 2 -#define GPIO_INTEN_PIN2_Msk (0x01 << GPIO_INTEN_PIN2_Pos) -#define GPIO_INTEN_PIN3_Pos 3 -#define GPIO_INTEN_PIN3_Msk (0x01 << GPIO_INTEN_PIN3_Pos) -#define GPIO_INTEN_PIN4_Pos 4 -#define GPIO_INTEN_PIN4_Msk (0x01 << GPIO_INTEN_PIN4_Pos) -#define GPIO_INTEN_PIN5_Pos 5 -#define GPIO_INTEN_PIN5_Msk (0x01 << GPIO_INTEN_PIN5_Pos) -#define GPIO_INTEN_PIN6_Pos 6 -#define GPIO_INTEN_PIN6_Msk (0x01 << GPIO_INTEN_PIN6_Pos) -#define GPIO_INTEN_PIN7_Pos 7 -#define GPIO_INTEN_PIN7_Msk (0x01 << GPIO_INTEN_PIN7_Pos) -#define GPIO_INTEN_PIN8_Pos 8 -#define GPIO_INTEN_PIN8_Msk (0x01 << GPIO_INTEN_PIN8_Pos) -#define GPIO_INTEN_PIN9_Pos 9 -#define GPIO_INTEN_PIN9_Msk (0x01 << GPIO_INTEN_PIN9_Pos) -#define GPIO_INTEN_PIN10_Pos 10 -#define GPIO_INTEN_PIN10_Msk (0x01 << GPIO_INTEN_PIN10_Pos) -#define GPIO_INTEN_PIN11_Pos 11 -#define GPIO_INTEN_PIN11_Msk (0x01 << GPIO_INTEN_PIN11_Pos) -#define GPIO_INTEN_PIN12_Pos 12 -#define GPIO_INTEN_PIN12_Msk (0x01 << GPIO_INTEN_PIN12_Pos) -#define GPIO_INTEN_PIN13_Pos 13 -#define GPIO_INTEN_PIN13_Msk (0x01 << GPIO_INTEN_PIN13_Pos) -#define GPIO_INTEN_PIN14_Pos 14 -#define GPIO_INTEN_PIN14_Msk (0x01 << GPIO_INTEN_PIN14_Pos) -#define GPIO_INTEN_PIN15_Pos 15 -#define GPIO_INTEN_PIN15_Msk (0x01 << GPIO_INTEN_PIN15_Pos) -#define GPIO_INTEN_PIN16_Pos 16 -#define GPIO_INTEN_PIN16_Msk (0x01 << GPIO_INTEN_PIN16_Pos) -#define GPIO_INTEN_PIN17_Pos 17 -#define GPIO_INTEN_PIN17_Msk (0x01 << GPIO_INTEN_PIN17_Pos) -#define GPIO_INTEN_PIN18_Pos 18 -#define GPIO_INTEN_PIN18_Msk (0x01 << GPIO_INTEN_PIN18_Pos) -#define GPIO_INTEN_PIN19_Pos 19 -#define GPIO_INTEN_PIN19_Msk (0x01 << GPIO_INTEN_PIN19_Pos) -#define GPIO_INTEN_PIN20_Pos 20 -#define GPIO_INTEN_PIN20_Msk (0x01 << GPIO_INTEN_PIN20_Pos) -#define GPIO_INTEN_PIN21_Pos 21 -#define GPIO_INTEN_PIN21_Msk (0x01 << GPIO_INTEN_PIN21_Pos) -#define GPIO_INTEN_PIN22_Pos 22 -#define GPIO_INTEN_PIN22_Msk (0x01 << GPIO_INTEN_PIN22_Pos) -#define GPIO_INTEN_PIN23_Pos 23 -#define GPIO_INTEN_PIN23_Msk (0x01 << GPIO_INTEN_PIN23_Pos) +#define GPIO_INTRISEEN_PIN0_Pos 0 +#define GPIO_INTRISEEN_PIN0_Msk (0x01 << GPIO_INTRISEEN_PIN0_Pos) +#define GPIO_INTRISEEN_PIN1_Pos 1 +#define GPIO_INTRISEEN_PIN1_Msk (0x01 << GPIO_INTRISEEN_PIN1_Pos) +#define GPIO_INTRISEEN_PIN2_Pos 2 +#define GPIO_INTRISEEN_PIN2_Msk (0x01 << GPIO_INTRISEEN_PIN2_Pos) +#define GPIO_INTRISEEN_PIN3_Pos 3 +#define GPIO_INTRISEEN_PIN3_Msk (0x01 << GPIO_INTRISEEN_PIN3_Pos) +#define GPIO_INTRISEEN_PIN4_Pos 4 +#define GPIO_INTRISEEN_PIN4_Msk (0x01 << GPIO_INTRISEEN_PIN4_Pos) +#define GPIO_INTRISEEN_PIN5_Pos 5 +#define GPIO_INTRISEEN_PIN5_Msk (0x01 << GPIO_INTRISEEN_PIN5_Pos) +#define GPIO_INTRISEEN_PIN6_Pos 6 +#define GPIO_INTRISEEN_PIN6_Msk (0x01 << GPIO_INTRISEEN_PIN6_Pos) +#define GPIO_INTRISEEN_PIN7_Pos 7 +#define GPIO_INTRISEEN_PIN7_Msk (0x01 << GPIO_INTRISEEN_PIN7_Pos) +#define GPIO_INTRISEEN_PIN8_Pos 8 +#define GPIO_INTRISEEN_PIN8_Msk (0x01 << GPIO_INTRISEEN_PIN8_Pos) +#define GPIO_INTRISEEN_PIN9_Pos 9 +#define GPIO_INTRISEEN_PIN9_Msk (0x01 << GPIO_INTRISEEN_PIN9_Pos) +#define GPIO_INTRISEEN_PIN10_Pos 10 +#define GPIO_INTRISEEN_PIN10_Msk (0x01 << GPIO_INTRISEEN_PIN10_Pos) +#define GPIO_INTRISEEN_PIN11_Pos 11 +#define GPIO_INTRISEEN_PIN11_Msk (0x01 << GPIO_INTRISEEN_PIN11_Pos) +#define GPIO_INTRISEEN_PIN12_Pos 12 +#define GPIO_INTRISEEN_PIN12_Msk (0x01 << GPIO_INTRISEEN_PIN12_Pos) +#define GPIO_INTRISEEN_PIN13_Pos 13 +#define GPIO_INTRISEEN_PIN13_Msk (0x01 << GPIO_INTRISEEN_PIN13_Pos) +#define GPIO_INTRISEEN_PIN14_Pos 14 +#define GPIO_INTRISEEN_PIN14_Msk (0x01 << GPIO_INTRISEEN_PIN14_Pos) +#define GPIO_INTRISEEN_PIN15_Pos 15 +#define GPIO_INTRISEEN_PIN15_Msk (0x01 << GPIO_INTRISEEN_PIN15_Pos) +#define GPIO_INTRISEEN_PIN16_Pos 16 +#define GPIO_INTRISEEN_PIN16_Msk (0x01 << GPIO_INTRISEEN_PIN16_Pos) +#define GPIO_INTRISEEN_PIN17_Pos 17 +#define GPIO_INTRISEEN_PIN17_Msk (0x01 << GPIO_INTRISEEN_PIN17_Pos) +#define GPIO_INTRISEEN_PIN18_Pos 18 +#define GPIO_INTRISEEN_PIN18_Msk (0x01 << GPIO_INTRISEEN_PIN18_Pos) +#define GPIO_INTRISEEN_PIN19_Pos 19 +#define GPIO_INTRISEEN_PIN19_Msk (0x01 << GPIO_INTRISEEN_PIN19_Pos) +#define GPIO_INTRISEEN_PIN20_Pos 20 +#define GPIO_INTRISEEN_PIN20_Msk (0x01 << GPIO_INTRISEEN_PIN20_Pos) +#define GPIO_INTRISEEN_PIN21_Pos 21 +#define GPIO_INTRISEEN_PIN21_Msk (0x01 << GPIO_INTRISEEN_PIN21_Pos) +#define GPIO_INTRISEEN_PIN22_Pos 22 +#define GPIO_INTRISEEN_PIN22_Msk (0x01 << GPIO_INTRISEEN_PIN22_Pos) +#define GPIO_INTRISEEN_PIN23_Pos 23 +#define GPIO_INTRISEEN_PIN23_Msk (0x01 << GPIO_INTRISEEN_PIN23_Pos) -#define GPIO_INTRAWSTAT_PIN0_Pos 0 -#define GPIO_INTRAWSTAT_PIN0_Msk (0x01 << GPIO_INTRAWSTAT_PIN0_Pos) -#define GPIO_INTRAWSTAT_PIN1_Pos 1 -#define GPIO_INTRAWSTAT_PIN1_Msk (0x01 << GPIO_INTRAWSTAT_PIN1_Pos) -#define GPIO_INTRAWSTAT_PIN2_Pos 2 -#define GPIO_INTRAWSTAT_PIN2_Msk (0x01 << GPIO_INTRAWSTAT_PIN2_Pos) -#define GPIO_INTRAWSTAT_PIN3_Pos 3 -#define GPIO_INTRAWSTAT_PIN3_Msk (0x01 << GPIO_INTRAWSTAT_PIN3_Pos) -#define GPIO_INTRAWSTAT_PIN4_Pos 4 -#define GPIO_INTRAWSTAT_PIN4_Msk (0x01 << GPIO_INTRAWSTAT_PIN4_Pos) -#define GPIO_INTRAWSTAT_PIN5_Pos 5 -#define GPIO_INTRAWSTAT_PIN5_Msk (0x01 << GPIO_INTRAWSTAT_PIN5_Pos) -#define GPIO_INTRAWSTAT_PIN6_Pos 6 -#define GPIO_INTRAWSTAT_PIN6_Msk (0x01 << GPIO_INTRAWSTAT_PIN6_Pos) -#define GPIO_INTRAWSTAT_PIN7_Pos 7 -#define GPIO_INTRAWSTAT_PIN7_Msk (0x01 << GPIO_INTRAWSTAT_PIN7_Pos) -#define GPIO_INTRAWSTAT_PIN8_Pos 8 -#define GPIO_INTRAWSTAT_PIN8_Msk (0x01 << GPIO_INTRAWSTAT_PIN8_Pos) -#define GPIO_INTRAWSTAT_PIN9_Pos 9 -#define GPIO_INTRAWSTAT_PIN9_Msk (0x01 << GPIO_INTRAWSTAT_PIN9_Pos) -#define GPIO_INTRAWSTAT_PIN10_Pos 10 -#define GPIO_INTRAWSTAT_PIN10_Msk (0x01 << GPIO_INTRAWSTAT_PIN10_Pos) -#define GPIO_INTRAWSTAT_PIN11_Pos 11 -#define GPIO_INTRAWSTAT_PIN11_Msk (0x01 << GPIO_INTRAWSTAT_PIN11_Pos) -#define GPIO_INTRAWSTAT_PIN12_Pos 12 -#define GPIO_INTRAWSTAT_PIN12_Msk (0x01 << GPIO_INTRAWSTAT_PIN12_Pos) -#define GPIO_INTRAWSTAT_PIN13_Pos 13 -#define GPIO_INTRAWSTAT_PIN13_Msk (0x01 << GPIO_INTRAWSTAT_PIN13_Pos) -#define GPIO_INTRAWSTAT_PIN14_Pos 14 -#define GPIO_INTRAWSTAT_PIN14_Msk (0x01 << GPIO_INTRAWSTAT_PIN14_Pos) -#define GPIO_INTRAWSTAT_PIN15_Pos 15 -#define GPIO_INTRAWSTAT_PIN15_Msk (0x01 << GPIO_INTRAWSTAT_PIN15_Pos) -#define GPIO_INTRAWSTAT_PIN16_Pos 16 -#define GPIO_INTRAWSTAT_PIN16_Msk (0x01 << GPIO_INTRAWSTAT_PIN16_Pos) -#define GPIO_INTRAWSTAT_PIN17_Pos 17 -#define GPIO_INTRAWSTAT_PIN17_Msk (0x01 << GPIO_INTRAWSTAT_PIN17_Pos) -#define GPIO_INTRAWSTAT_PIN18_Pos 18 -#define GPIO_INTRAWSTAT_PIN18_Msk (0x01 << GPIO_INTRAWSTAT_PIN18_Pos) -#define GPIO_INTRAWSTAT_PIN19_Pos 19 -#define GPIO_INTRAWSTAT_PIN19_Msk (0x01 << GPIO_INTRAWSTAT_PIN19_Pos) -#define GPIO_INTRAWSTAT_PIN20_Pos 20 -#define GPIO_INTRAWSTAT_PIN20_Msk (0x01 << GPIO_INTRAWSTAT_PIN20_Pos) -#define GPIO_INTRAWSTAT_PIN21_Pos 21 -#define GPIO_INTRAWSTAT_PIN21_Msk (0x01 << GPIO_INTRAWSTAT_PIN21_Pos) -#define GPIO_INTRAWSTAT_PIN22_Pos 22 -#define GPIO_INTRAWSTAT_PIN22_Msk (0x01 << GPIO_INTRAWSTAT_PIN22_Pos) -#define GPIO_INTRAWSTAT_PIN23_Pos 23 -#define GPIO_INTRAWSTAT_PIN23_Msk (0x01 << GPIO_INTRAWSTAT_PIN23_Pos) +#define GPIO_INTEN_PIN0_Pos 0 +#define GPIO_INTEN_PIN0_Msk (0x01 << GPIO_INTEN_PIN0_Pos) +#define GPIO_INTEN_PIN1_Pos 1 +#define GPIO_INTEN_PIN1_Msk (0x01 << GPIO_INTEN_PIN1_Pos) +#define GPIO_INTEN_PIN2_Pos 2 +#define GPIO_INTEN_PIN2_Msk (0x01 << GPIO_INTEN_PIN2_Pos) +#define GPIO_INTEN_PIN3_Pos 3 +#define GPIO_INTEN_PIN3_Msk (0x01 << GPIO_INTEN_PIN3_Pos) +#define GPIO_INTEN_PIN4_Pos 4 +#define GPIO_INTEN_PIN4_Msk (0x01 << GPIO_INTEN_PIN4_Pos) +#define GPIO_INTEN_PIN5_Pos 5 +#define GPIO_INTEN_PIN5_Msk (0x01 << GPIO_INTEN_PIN5_Pos) +#define GPIO_INTEN_PIN6_Pos 6 +#define GPIO_INTEN_PIN6_Msk (0x01 << GPIO_INTEN_PIN6_Pos) +#define GPIO_INTEN_PIN7_Pos 7 +#define GPIO_INTEN_PIN7_Msk (0x01 << GPIO_INTEN_PIN7_Pos) +#define GPIO_INTEN_PIN8_Pos 8 +#define GPIO_INTEN_PIN8_Msk (0x01 << GPIO_INTEN_PIN8_Pos) +#define GPIO_INTEN_PIN9_Pos 9 +#define GPIO_INTEN_PIN9_Msk (0x01 << GPIO_INTEN_PIN9_Pos) +#define GPIO_INTEN_PIN10_Pos 10 +#define GPIO_INTEN_PIN10_Msk (0x01 << GPIO_INTEN_PIN10_Pos) +#define GPIO_INTEN_PIN11_Pos 11 +#define GPIO_INTEN_PIN11_Msk (0x01 << GPIO_INTEN_PIN11_Pos) +#define GPIO_INTEN_PIN12_Pos 12 +#define GPIO_INTEN_PIN12_Msk (0x01 << GPIO_INTEN_PIN12_Pos) +#define GPIO_INTEN_PIN13_Pos 13 +#define GPIO_INTEN_PIN13_Msk (0x01 << GPIO_INTEN_PIN13_Pos) +#define GPIO_INTEN_PIN14_Pos 14 +#define GPIO_INTEN_PIN14_Msk (0x01 << GPIO_INTEN_PIN14_Pos) +#define GPIO_INTEN_PIN15_Pos 15 +#define GPIO_INTEN_PIN15_Msk (0x01 << GPIO_INTEN_PIN15_Pos) +#define GPIO_INTEN_PIN16_Pos 16 +#define GPIO_INTEN_PIN16_Msk (0x01 << GPIO_INTEN_PIN16_Pos) +#define GPIO_INTEN_PIN17_Pos 17 +#define GPIO_INTEN_PIN17_Msk (0x01 << GPIO_INTEN_PIN17_Pos) +#define GPIO_INTEN_PIN18_Pos 18 +#define GPIO_INTEN_PIN18_Msk (0x01 << GPIO_INTEN_PIN18_Pos) +#define GPIO_INTEN_PIN19_Pos 19 +#define GPIO_INTEN_PIN19_Msk (0x01 << GPIO_INTEN_PIN19_Pos) +#define GPIO_INTEN_PIN20_Pos 20 +#define GPIO_INTEN_PIN20_Msk (0x01 << GPIO_INTEN_PIN20_Pos) +#define GPIO_INTEN_PIN21_Pos 21 +#define GPIO_INTEN_PIN21_Msk (0x01 << GPIO_INTEN_PIN21_Pos) +#define GPIO_INTEN_PIN22_Pos 22 +#define GPIO_INTEN_PIN22_Msk (0x01 << GPIO_INTEN_PIN22_Pos) +#define GPIO_INTEN_PIN23_Pos 23 +#define GPIO_INTEN_PIN23_Msk (0x01 << GPIO_INTEN_PIN23_Pos) -#define GPIO_INTSTAT_PIN0_Pos 0 -#define GPIO_INTSTAT_PIN0_Msk (0x01 << GPIO_INTSTAT_PIN0_Pos) -#define GPIO_INTSTAT_PIN1_Pos 1 -#define GPIO_INTSTAT_PIN1_Msk (0x01 << GPIO_INTSTAT_PIN1_Pos) -#define GPIO_INTSTAT_PIN2_Pos 2 -#define GPIO_INTSTAT_PIN2_Msk (0x01 << GPIO_INTSTAT_PIN2_Pos) -#define GPIO_INTSTAT_PIN3_Pos 3 -#define GPIO_INTSTAT_PIN3_Msk (0x01 << GPIO_INTSTAT_PIN3_Pos) -#define GPIO_INTSTAT_PIN4_Pos 4 -#define GPIO_INTSTAT_PIN4_Msk (0x01 << GPIO_INTSTAT_PIN4_Pos) -#define GPIO_INTSTAT_PIN5_Pos 5 -#define GPIO_INTSTAT_PIN5_Msk (0x01 << GPIO_INTSTAT_PIN5_Pos) -#define GPIO_INTSTAT_PIN6_Pos 6 -#define GPIO_INTSTAT_PIN6_Msk (0x01 << GPIO_INTSTAT_PIN6_Pos) -#define GPIO_INTSTAT_PIN7_Pos 7 -#define GPIO_INTSTAT_PIN7_Msk (0x01 << GPIO_INTSTAT_PIN7_Pos) -#define GPIO_INTSTAT_PIN8_Pos 8 -#define GPIO_INTSTAT_PIN8_Msk (0x01 << GPIO_INTSTAT_PIN8_Pos) -#define GPIO_INTSTAT_PIN9_Pos 9 -#define GPIO_INTSTAT_PIN9_Msk (0x01 << GPIO_INTSTAT_PIN9_Pos) -#define GPIO_INTSTAT_PIN10_Pos 10 -#define GPIO_INTSTAT_PIN10_Msk (0x01 << GPIO_INTSTAT_PIN10_Pos) -#define GPIO_INTSTAT_PIN11_Pos 11 -#define GPIO_INTSTAT_PIN11_Msk (0x01 << GPIO_INTSTAT_PIN11_Pos) -#define GPIO_INTSTAT_PIN12_Pos 12 -#define GPIO_INTSTAT_PIN12_Msk (0x01 << GPIO_INTSTAT_PIN12_Pos) -#define GPIO_INTSTAT_PIN13_Pos 13 -#define GPIO_INTSTAT_PIN13_Msk (0x01 << GPIO_INTSTAT_PIN13_Pos) -#define GPIO_INTSTAT_PIN14_Pos 14 -#define GPIO_INTSTAT_PIN14_Msk (0x01 << GPIO_INTSTAT_PIN14_Pos) -#define GPIO_INTSTAT_PIN15_Pos 15 -#define GPIO_INTSTAT_PIN15_Msk (0x01 << GPIO_INTSTAT_PIN15_Pos) -#define GPIO_INTSTAT_PIN16_Pos 16 -#define GPIO_INTSTAT_PIN16_Msk (0x01 << GPIO_INTSTAT_PIN16_Pos) -#define GPIO_INTSTAT_PIN17_Pos 17 -#define GPIO_INTSTAT_PIN17_Msk (0x01 << GPIO_INTSTAT_PIN17_Pos) -#define GPIO_INTSTAT_PIN18_Pos 18 -#define GPIO_INTSTAT_PIN18_Msk (0x01 << GPIO_INTSTAT_PIN18_Pos) -#define GPIO_INTSTAT_PIN19_Pos 19 -#define GPIO_INTSTAT_PIN19_Msk (0x01 << GPIO_INTSTAT_PIN19_Pos) -#define GPIO_INTSTAT_PIN20_Pos 20 -#define GPIO_INTSTAT_PIN20_Msk (0x01 << GPIO_INTSTAT_PIN20_Pos) -#define GPIO_INTSTAT_PIN21_Pos 21 -#define GPIO_INTSTAT_PIN21_Msk (0x01 << GPIO_INTSTAT_PIN21_Pos) -#define GPIO_INTSTAT_PIN22_Pos 22 -#define GPIO_INTSTAT_PIN22_Msk (0x01 << GPIO_INTSTAT_PIN22_Pos) -#define GPIO_INTSTAT_PIN23_Pos 23 -#define GPIO_INTSTAT_PIN23_Msk (0x01 << GPIO_INTSTAT_PIN23_Pos) +#define GPIO_INTRAWSTAT_PIN0_Pos 0 +#define GPIO_INTRAWSTAT_PIN0_Msk (0x01 << GPIO_INTRAWSTAT_PIN0_Pos) +#define GPIO_INTRAWSTAT_PIN1_Pos 1 +#define GPIO_INTRAWSTAT_PIN1_Msk (0x01 << GPIO_INTRAWSTAT_PIN1_Pos) +#define GPIO_INTRAWSTAT_PIN2_Pos 2 +#define GPIO_INTRAWSTAT_PIN2_Msk (0x01 << GPIO_INTRAWSTAT_PIN2_Pos) +#define GPIO_INTRAWSTAT_PIN3_Pos 3 +#define GPIO_INTRAWSTAT_PIN3_Msk (0x01 << GPIO_INTRAWSTAT_PIN3_Pos) +#define GPIO_INTRAWSTAT_PIN4_Pos 4 +#define GPIO_INTRAWSTAT_PIN4_Msk (0x01 << GPIO_INTRAWSTAT_PIN4_Pos) +#define GPIO_INTRAWSTAT_PIN5_Pos 5 +#define GPIO_INTRAWSTAT_PIN5_Msk (0x01 << GPIO_INTRAWSTAT_PIN5_Pos) +#define GPIO_INTRAWSTAT_PIN6_Pos 6 +#define GPIO_INTRAWSTAT_PIN6_Msk (0x01 << GPIO_INTRAWSTAT_PIN6_Pos) +#define GPIO_INTRAWSTAT_PIN7_Pos 7 +#define GPIO_INTRAWSTAT_PIN7_Msk (0x01 << GPIO_INTRAWSTAT_PIN7_Pos) +#define GPIO_INTRAWSTAT_PIN8_Pos 8 +#define GPIO_INTRAWSTAT_PIN8_Msk (0x01 << GPIO_INTRAWSTAT_PIN8_Pos) +#define GPIO_INTRAWSTAT_PIN9_Pos 9 +#define GPIO_INTRAWSTAT_PIN9_Msk (0x01 << GPIO_INTRAWSTAT_PIN9_Pos) +#define GPIO_INTRAWSTAT_PIN10_Pos 10 +#define GPIO_INTRAWSTAT_PIN10_Msk (0x01 << GPIO_INTRAWSTAT_PIN10_Pos) +#define GPIO_INTRAWSTAT_PIN11_Pos 11 +#define GPIO_INTRAWSTAT_PIN11_Msk (0x01 << GPIO_INTRAWSTAT_PIN11_Pos) +#define GPIO_INTRAWSTAT_PIN12_Pos 12 +#define GPIO_INTRAWSTAT_PIN12_Msk (0x01 << GPIO_INTRAWSTAT_PIN12_Pos) +#define GPIO_INTRAWSTAT_PIN13_Pos 13 +#define GPIO_INTRAWSTAT_PIN13_Msk (0x01 << GPIO_INTRAWSTAT_PIN13_Pos) +#define GPIO_INTRAWSTAT_PIN14_Pos 14 +#define GPIO_INTRAWSTAT_PIN14_Msk (0x01 << GPIO_INTRAWSTAT_PIN14_Pos) +#define GPIO_INTRAWSTAT_PIN15_Pos 15 +#define GPIO_INTRAWSTAT_PIN15_Msk (0x01 << GPIO_INTRAWSTAT_PIN15_Pos) +#define GPIO_INTRAWSTAT_PIN16_Pos 16 +#define GPIO_INTRAWSTAT_PIN16_Msk (0x01 << GPIO_INTRAWSTAT_PIN16_Pos) +#define GPIO_INTRAWSTAT_PIN17_Pos 17 +#define GPIO_INTRAWSTAT_PIN17_Msk (0x01 << GPIO_INTRAWSTAT_PIN17_Pos) +#define GPIO_INTRAWSTAT_PIN18_Pos 18 +#define GPIO_INTRAWSTAT_PIN18_Msk (0x01 << GPIO_INTRAWSTAT_PIN18_Pos) +#define GPIO_INTRAWSTAT_PIN19_Pos 19 +#define GPIO_INTRAWSTAT_PIN19_Msk (0x01 << GPIO_INTRAWSTAT_PIN19_Pos) +#define GPIO_INTRAWSTAT_PIN20_Pos 20 +#define GPIO_INTRAWSTAT_PIN20_Msk (0x01 << GPIO_INTRAWSTAT_PIN20_Pos) +#define GPIO_INTRAWSTAT_PIN21_Pos 21 +#define GPIO_INTRAWSTAT_PIN21_Msk (0x01 << GPIO_INTRAWSTAT_PIN21_Pos) +#define GPIO_INTRAWSTAT_PIN22_Pos 22 +#define GPIO_INTRAWSTAT_PIN22_Msk (0x01 << GPIO_INTRAWSTAT_PIN22_Pos) +#define GPIO_INTRAWSTAT_PIN23_Pos 23 +#define GPIO_INTRAWSTAT_PIN23_Msk (0x01 << GPIO_INTRAWSTAT_PIN23_Pos) -#define GPIO_INTCLR_PIN0_Pos 0 -#define GPIO_INTCLR_PIN0_Msk (0x01 << GPIO_INTCLR_PIN0_Pos) -#define GPIO_INTCLR_PIN1_Pos 1 -#define GPIO_INTCLR_PIN1_Msk (0x01 << GPIO_INTCLR_PIN1_Pos) -#define GPIO_INTCLR_PIN2_Pos 2 -#define GPIO_INTCLR_PIN2_Msk (0x01 << GPIO_INTCLR_PIN2_Pos) -#define GPIO_INTCLR_PIN3_Pos 3 -#define GPIO_INTCLR_PIN3_Msk (0x01 << GPIO_INTCLR_PIN3_Pos) -#define GPIO_INTCLR_PIN4_Pos 4 -#define GPIO_INTCLR_PIN4_Msk (0x01 << GPIO_INTCLR_PIN4_Pos) -#define GPIO_INTCLR_PIN5_Pos 5 -#define GPIO_INTCLR_PIN5_Msk (0x01 << GPIO_INTCLR_PIN5_Pos) -#define GPIO_INTCLR_PIN6_Pos 6 -#define GPIO_INTCLR_PIN6_Msk (0x01 << GPIO_INTCLR_PIN6_Pos) -#define GPIO_INTCLR_PIN7_Pos 7 -#define GPIO_INTCLR_PIN7_Msk (0x01 << GPIO_INTCLR_PIN7_Pos) -#define GPIO_INTCLR_PIN8_Pos 8 -#define GPIO_INTCLR_PIN8_Msk (0x01 << GPIO_INTCLR_PIN8_Pos) -#define GPIO_INTCLR_PIN9_Pos 9 -#define GPIO_INTCLR_PIN9_Msk (0x01 << GPIO_INTCLR_PIN9_Pos) -#define GPIO_INTCLR_PIN10_Pos 10 -#define GPIO_INTCLR_PIN10_Msk (0x01 << GPIO_INTCLR_PIN10_Pos) -#define GPIO_INTCLR_PIN11_Pos 11 -#define GPIO_INTCLR_PIN11_Msk (0x01 << GPIO_INTCLR_PIN11_Pos) -#define GPIO_INTCLR_PIN12_Pos 12 -#define GPIO_INTCLR_PIN12_Msk (0x01 << GPIO_INTCLR_PIN12_Pos) -#define GPIO_INTCLR_PIN13_Pos 13 -#define GPIO_INTCLR_PIN13_Msk (0x01 << GPIO_INTCLR_PIN13_Pos) -#define GPIO_INTCLR_PIN14_Pos 14 -#define GPIO_INTCLR_PIN14_Msk (0x01 << GPIO_INTCLR_PIN14_Pos) -#define GPIO_INTCLR_PIN15_Pos 15 -#define GPIO_INTCLR_PIN15_Msk (0x01 << GPIO_INTCLR_PIN15_Pos) -#define GPIO_INTCLR_PIN16_Pos 16 -#define GPIO_INTCLR_PIN16_Msk (0x01 << GPIO_INTCLR_PIN16_Pos) -#define GPIO_INTCLR_PIN17_Pos 17 -#define GPIO_INTCLR_PIN17_Msk (0x01 << GPIO_INTCLR_PIN17_Pos) -#define GPIO_INTCLR_PIN18_Pos 18 -#define GPIO_INTCLR_PIN18_Msk (0x01 << GPIO_INTCLR_PIN18_Pos) -#define GPIO_INTCLR_PIN19_Pos 19 -#define GPIO_INTCLR_PIN19_Msk (0x01 << GPIO_INTCLR_PIN19_Pos) -#define GPIO_INTCLR_PIN20_Pos 20 -#define GPIO_INTCLR_PIN20_Msk (0x01 << GPIO_INTCLR_PIN20_Pos) -#define GPIO_INTCLR_PIN21_Pos 21 -#define GPIO_INTCLR_PIN21_Msk (0x01 << GPIO_INTCLR_PIN21_Pos) -#define GPIO_INTCLR_PIN22_Pos 22 -#define GPIO_INTCLR_PIN22_Msk (0x01 << GPIO_INTCLR_PIN22_Pos) -#define GPIO_INTCLR_PIN23_Pos 23 -#define GPIO_INTCLR_PIN23_Msk (0x01 << GPIO_INTCLR_PIN23_Pos) +#define GPIO_INTSTAT_PIN0_Pos 0 +#define GPIO_INTSTAT_PIN0_Msk (0x01 << GPIO_INTSTAT_PIN0_Pos) +#define GPIO_INTSTAT_PIN1_Pos 1 +#define GPIO_INTSTAT_PIN1_Msk (0x01 << GPIO_INTSTAT_PIN1_Pos) +#define GPIO_INTSTAT_PIN2_Pos 2 +#define GPIO_INTSTAT_PIN2_Msk (0x01 << GPIO_INTSTAT_PIN2_Pos) +#define GPIO_INTSTAT_PIN3_Pos 3 +#define GPIO_INTSTAT_PIN3_Msk (0x01 << GPIO_INTSTAT_PIN3_Pos) +#define GPIO_INTSTAT_PIN4_Pos 4 +#define GPIO_INTSTAT_PIN4_Msk (0x01 << GPIO_INTSTAT_PIN4_Pos) +#define GPIO_INTSTAT_PIN5_Pos 5 +#define GPIO_INTSTAT_PIN5_Msk (0x01 << GPIO_INTSTAT_PIN5_Pos) +#define GPIO_INTSTAT_PIN6_Pos 6 +#define GPIO_INTSTAT_PIN6_Msk (0x01 << GPIO_INTSTAT_PIN6_Pos) +#define GPIO_INTSTAT_PIN7_Pos 7 +#define GPIO_INTSTAT_PIN7_Msk (0x01 << GPIO_INTSTAT_PIN7_Pos) +#define GPIO_INTSTAT_PIN8_Pos 8 +#define GPIO_INTSTAT_PIN8_Msk (0x01 << GPIO_INTSTAT_PIN8_Pos) +#define GPIO_INTSTAT_PIN9_Pos 9 +#define GPIO_INTSTAT_PIN9_Msk (0x01 << GPIO_INTSTAT_PIN9_Pos) +#define GPIO_INTSTAT_PIN10_Pos 10 +#define GPIO_INTSTAT_PIN10_Msk (0x01 << GPIO_INTSTAT_PIN10_Pos) +#define GPIO_INTSTAT_PIN11_Pos 11 +#define GPIO_INTSTAT_PIN11_Msk (0x01 << GPIO_INTSTAT_PIN11_Pos) +#define GPIO_INTSTAT_PIN12_Pos 12 +#define GPIO_INTSTAT_PIN12_Msk (0x01 << GPIO_INTSTAT_PIN12_Pos) +#define GPIO_INTSTAT_PIN13_Pos 13 +#define GPIO_INTSTAT_PIN13_Msk (0x01 << GPIO_INTSTAT_PIN13_Pos) +#define GPIO_INTSTAT_PIN14_Pos 14 +#define GPIO_INTSTAT_PIN14_Msk (0x01 << GPIO_INTSTAT_PIN14_Pos) +#define GPIO_INTSTAT_PIN15_Pos 15 +#define GPIO_INTSTAT_PIN15_Msk (0x01 << GPIO_INTSTAT_PIN15_Pos) +#define GPIO_INTSTAT_PIN16_Pos 16 +#define GPIO_INTSTAT_PIN16_Msk (0x01 << GPIO_INTSTAT_PIN16_Pos) +#define GPIO_INTSTAT_PIN17_Pos 17 +#define GPIO_INTSTAT_PIN17_Msk (0x01 << GPIO_INTSTAT_PIN17_Pos) +#define GPIO_INTSTAT_PIN18_Pos 18 +#define GPIO_INTSTAT_PIN18_Msk (0x01 << GPIO_INTSTAT_PIN18_Pos) +#define GPIO_INTSTAT_PIN19_Pos 19 +#define GPIO_INTSTAT_PIN19_Msk (0x01 << GPIO_INTSTAT_PIN19_Pos) +#define GPIO_INTSTAT_PIN20_Pos 20 +#define GPIO_INTSTAT_PIN20_Msk (0x01 << GPIO_INTSTAT_PIN20_Pos) +#define GPIO_INTSTAT_PIN21_Pos 21 +#define GPIO_INTSTAT_PIN21_Msk (0x01 << GPIO_INTSTAT_PIN21_Pos) +#define GPIO_INTSTAT_PIN22_Pos 22 +#define GPIO_INTSTAT_PIN22_Msk (0x01 << GPIO_INTSTAT_PIN22_Pos) +#define GPIO_INTSTAT_PIN23_Pos 23 +#define GPIO_INTSTAT_PIN23_Msk (0x01 << GPIO_INTSTAT_PIN23_Pos) -typedef struct -{ - __IO uint32_t LDVAL; //定时器加载值,使能后定时器从此数值开始向下递减计数 +#define GPIO_INTCLR_PIN0_Pos 0 +#define GPIO_INTCLR_PIN0_Msk (0x01 << GPIO_INTCLR_PIN0_Pos) +#define GPIO_INTCLR_PIN1_Pos 1 +#define GPIO_INTCLR_PIN1_Msk (0x01 << GPIO_INTCLR_PIN1_Pos) +#define GPIO_INTCLR_PIN2_Pos 2 +#define GPIO_INTCLR_PIN2_Msk (0x01 << GPIO_INTCLR_PIN2_Pos) +#define GPIO_INTCLR_PIN3_Pos 3 +#define GPIO_INTCLR_PIN3_Msk (0x01 << GPIO_INTCLR_PIN3_Pos) +#define GPIO_INTCLR_PIN4_Pos 4 +#define GPIO_INTCLR_PIN4_Msk (0x01 << GPIO_INTCLR_PIN4_Pos) +#define GPIO_INTCLR_PIN5_Pos 5 +#define GPIO_INTCLR_PIN5_Msk (0x01 << GPIO_INTCLR_PIN5_Pos) +#define GPIO_INTCLR_PIN6_Pos 6 +#define GPIO_INTCLR_PIN6_Msk (0x01 << GPIO_INTCLR_PIN6_Pos) +#define GPIO_INTCLR_PIN7_Pos 7 +#define GPIO_INTCLR_PIN7_Msk (0x01 << GPIO_INTCLR_PIN7_Pos) +#define GPIO_INTCLR_PIN8_Pos 8 +#define GPIO_INTCLR_PIN8_Msk (0x01 << GPIO_INTCLR_PIN8_Pos) +#define GPIO_INTCLR_PIN9_Pos 9 +#define GPIO_INTCLR_PIN9_Msk (0x01 << GPIO_INTCLR_PIN9_Pos) +#define GPIO_INTCLR_PIN10_Pos 10 +#define GPIO_INTCLR_PIN10_Msk (0x01 << GPIO_INTCLR_PIN10_Pos) +#define GPIO_INTCLR_PIN11_Pos 11 +#define GPIO_INTCLR_PIN11_Msk (0x01 << GPIO_INTCLR_PIN11_Pos) +#define GPIO_INTCLR_PIN12_Pos 12 +#define GPIO_INTCLR_PIN12_Msk (0x01 << GPIO_INTCLR_PIN12_Pos) +#define GPIO_INTCLR_PIN13_Pos 13 +#define GPIO_INTCLR_PIN13_Msk (0x01 << GPIO_INTCLR_PIN13_Pos) +#define GPIO_INTCLR_PIN14_Pos 14 +#define GPIO_INTCLR_PIN14_Msk (0x01 << GPIO_INTCLR_PIN14_Pos) +#define GPIO_INTCLR_PIN15_Pos 15 +#define GPIO_INTCLR_PIN15_Msk (0x01 << GPIO_INTCLR_PIN15_Pos) +#define GPIO_INTCLR_PIN16_Pos 16 +#define GPIO_INTCLR_PIN16_Msk (0x01 << GPIO_INTCLR_PIN16_Pos) +#define GPIO_INTCLR_PIN17_Pos 17 +#define GPIO_INTCLR_PIN17_Msk (0x01 << GPIO_INTCLR_PIN17_Pos) +#define GPIO_INTCLR_PIN18_Pos 18 +#define GPIO_INTCLR_PIN18_Msk (0x01 << GPIO_INTCLR_PIN18_Pos) +#define GPIO_INTCLR_PIN19_Pos 19 +#define GPIO_INTCLR_PIN19_Msk (0x01 << GPIO_INTCLR_PIN19_Pos) +#define GPIO_INTCLR_PIN20_Pos 20 +#define GPIO_INTCLR_PIN20_Msk (0x01 << GPIO_INTCLR_PIN20_Pos) +#define GPIO_INTCLR_PIN21_Pos 21 +#define GPIO_INTCLR_PIN21_Msk (0x01 << GPIO_INTCLR_PIN21_Pos) +#define GPIO_INTCLR_PIN22_Pos 22 +#define GPIO_INTCLR_PIN22_Msk (0x01 << GPIO_INTCLR_PIN22_Pos) +#define GPIO_INTCLR_PIN23_Pos 23 +#define GPIO_INTCLR_PIN23_Msk (0x01 << GPIO_INTCLR_PIN23_Pos) - __I uint32_t CVAL; //定时器当前值,LDVAL-CVAL 可计算出计时时长 - __IO uint32_t CTRL; + + +typedef struct { + __IO uint32_t LDVAL; //ʱֵʹܺʱӴֵʼµݼ + + __I uint32_t CVAL; //ʱǰֵLDVAL-CVAL ɼʱʱ + + __IO uint32_t CTRL; } TIMR_TypeDef; -#define TIMR_CTRL_EN_Pos 0 //此位赋1导致TIMR从LDVAL开始向下递减计数 -#define TIMR_CTRL_EN_Msk (0x01 << TIMR_CTRL_EN_Pos) -#define TIMR_CTRL_CLKSRC_Pos 1 //时钟源:0 内部系统时钟 1 外部引脚脉冲计数 -#define TIMR_CTRL_CLKSRC_Msk (0x01 << TIMR_CTRL_CLKSRC_Pos) -#define TIMR_CTRL_CASCADE_Pos 2 //1 TIMRx的计数时钟为TIMRx-1的溢出信号 -#define TIMR_CTRL_CASCADE_Msk (0x01 << TIMR_CTRL_CASCADE_Pos) -typedef struct -{ - __IO uint32_t PCTRL; //Pulse Control,脉宽测量模块控制寄存器 +#define TIMR_CTRL_EN_Pos 0 //λ1TIMRLDVALʼµݼ +#define TIMR_CTRL_EN_Msk (0x01 << TIMR_CTRL_EN_Pos) +#define TIMR_CTRL_CLKSRC_Pos 1 //ʱԴ0 ڲϵͳʱ 1 ⲿ +#define TIMR_CTRL_CLKSRC_Msk (0x01 << TIMR_CTRL_CLKSRC_Pos) +#define TIMR_CTRL_CASCADE_Pos 2 //1 TIMRxļʱΪTIMRx-1ź +#define TIMR_CTRL_CASCADE_Msk (0x01 << TIMR_CTRL_CASCADE_Pos) - __I uint32_t PCVAL; //脉宽测量定时器当前值 - uint32_t RESERVED[2]; +typedef struct { + __IO uint32_t PCTRL; //Pulse ControlģƼĴ - __IO uint32_t IE; + __I uint32_t PCVAL; //ʱǰֵ - __IO uint32_t IF; + uint32_t RESERVED[2]; - __IO uint32_t HALT; + __IO uint32_t IE; + + __IO uint32_t IF; + + __IO uint32_t HALT; } TIMRG_TypeDef; -#define TIMRG_PCTRL_EN_Pos 0 //开始测量脉宽,脉宽内32位计数器从0开始向上计数 -#define TIMRG_PCTRL_EN_Msk (0x01 << TIMRG_PCTRL_EN_Pos) -#define TIMRG_PCTRL_HIGH_Pos 1 //0 测量低电平长度 1 测量高电平长度 -#define TIMRG_PCTRL_HIGH_Msk (0x01 << TIMRG_PCTRL_HIGH_Pos) -#define TIMRG_PCTRL_CLKSRC_Pos 2 //时钟源:0 内部系统时钟 1 脉宽测量模块变成一个计数器,不再具有脉宽测量功能 -#define TIMRG_PCTRL_CLKSRC_Msk (0x01 << TIMRG_PCTRL_CLKSRC_Pos) -#define TIMRG_IE_TIMR0_Pos 0 -#define TIMRG_IE_TIMR0_Msk (0x01 << TIMRG_IE_TIMR0_Pos) -#define TIMRG_IE_TIMR1_Pos 1 -#define TIMRG_IE_TIMR1_Msk (0x01 << TIMRG_IE_TIMR1_Pos) -#define TIMRG_IE_TIMR2_Pos 2 -#define TIMRG_IE_TIMR2_Msk (0x01 << TIMRG_IE_TIMR2_Pos) -#define TIMRG_IE_TIMR3_Pos 3 -#define TIMRG_IE_TIMR3_Msk (0x01 << TIMRG_IE_TIMR3_Pos) -#define TIMRG_IE_TIMR4_Pos 4 -#define TIMRG_IE_TIMR4_Msk (0x01 << TIMRG_IE_TIMR4_Pos) -#define TIMRG_IE_TIMR5_Pos 5 -#define TIMRG_IE_TIMR5_Msk (0x01 << TIMRG_IE_TIMR5_Pos) -#define TIMRG_IE_PULSE_Pos 16 -#define TIMRG_IE_PULSE_Msk (0x01 << TIMRG_IE_PULSE_Pos) +#define TIMRG_PCTRL_EN_Pos 0 //ʼ32λ0ʼϼ +#define TIMRG_PCTRL_EN_Msk (0x01 << TIMRG_PCTRL_EN_Pos) +#define TIMRG_PCTRL_HIGH_Pos 1 //0 ͵ƽ 1 ߵƽ +#define TIMRG_PCTRL_HIGH_Msk (0x01 << TIMRG_PCTRL_HIGH_Pos) +#define TIMRG_PCTRL_CLKSRC_Pos 2 //ʱԴ0 ڲϵͳʱ 1 ģһپ +#define TIMRG_PCTRL_CLKSRC_Msk (0x01 << TIMRG_PCTRL_CLKSRC_Pos) -#define TIMRG_IF_TIMR0_Pos 0 //写1清零 -#define TIMRG_IF_TIMR0_Msk (0x01 << TIMRG_IF_TIMR0_Pos) -#define TIMRG_IF_TIMR1_Pos 1 -#define TIMRG_IF_TIMR1_Msk (0x01 << TIMRG_IF_TIMR1_Pos) -#define TIMRG_IF_TIMR2_Pos 2 -#define TIMRG_IF_TIMR2_Msk (0x01 << TIMRG_IF_TIMR2_Pos) -#define TIMRG_IF_TIMR3_Pos 3 -#define TIMRG_IF_TIMR3_Msk (0x01 << TIMRG_IF_TIMR3_Pos) -#define TIMRG_IF_TIMR4_Pos 4 -#define TIMRG_IF_TIMR4_Msk (0x01 << TIMRG_IF_TIMR4_Pos) -#define TIMRG_IF_TIMR5_Pos 5 -#define TIMRG_IF_TIMR5_Msk (0x01 << TIMRG_IF_TIMR5_Pos) -#define TIMRG_IF_PULSE_Pos 16 -#define TIMRG_IF_PULSE_Msk (0x01 << TIMRG_IF_PULSE_Pos) +#define TIMRG_IE_TIMR0_Pos 0 +#define TIMRG_IE_TIMR0_Msk (0x01 << TIMRG_IE_TIMR0_Pos) +#define TIMRG_IE_TIMR1_Pos 1 +#define TIMRG_IE_TIMR1_Msk (0x01 << TIMRG_IE_TIMR1_Pos) +#define TIMRG_IE_TIMR2_Pos 2 +#define TIMRG_IE_TIMR2_Msk (0x01 << TIMRG_IE_TIMR2_Pos) +#define TIMRG_IE_TIMR3_Pos 3 +#define TIMRG_IE_TIMR3_Msk (0x01 << TIMRG_IE_TIMR3_Pos) +#define TIMRG_IE_TIMR4_Pos 4 +#define TIMRG_IE_TIMR4_Msk (0x01 << TIMRG_IE_TIMR4_Pos) +#define TIMRG_IE_TIMR5_Pos 5 +#define TIMRG_IE_TIMR5_Msk (0x01 << TIMRG_IE_TIMR5_Pos) +#define TIMRG_IE_PULSE_Pos 16 +#define TIMRG_IE_PULSE_Msk (0x01 << TIMRG_IE_PULSE_Pos) -#define TIMRG_HALT_TIMR0_Pos 0 //1 暂停计数 -#define TIMRG_HALT_TIMR0_Msk (0x01 << TIMRG_HALT_TIMR0_Pos) -#define TIMRG_HALT_TIMR1_Pos 1 -#define TIMRG_HALT_TIMR1_Msk (0x01 << TIMRG_HALT_TIMR1_Pos) -#define TIMRG_HALT_TIMR2_Pos 2 -#define TIMRG_HALT_TIMR2_Msk (0x01 << TIMRG_HALT_TIMR2_Pos) -#define TIMRG_HALT_TIMR3_Pos 3 -#define TIMRG_HALT_TIMR3_Msk (0x01 << TIMRG_HALT_TIMR3_Pos) -#define TIMRG_HALT_TIMR4_Pos 4 -#define TIMRG_HALT_TIMR4_Msk (0x01 << TIMRG_HALT_TIMR4_Pos) -#define TIMRG_HALT_TIMR5_Pos 5 -#define TIMRG_HALT_TIMR5_Msk (0x01 << TIMRG_HALT_TIMR5_Pos) +#define TIMRG_IF_TIMR0_Pos 0 //д1 +#define TIMRG_IF_TIMR0_Msk (0x01 << TIMRG_IF_TIMR0_Pos) +#define TIMRG_IF_TIMR1_Pos 1 +#define TIMRG_IF_TIMR1_Msk (0x01 << TIMRG_IF_TIMR1_Pos) +#define TIMRG_IF_TIMR2_Pos 2 +#define TIMRG_IF_TIMR2_Msk (0x01 << TIMRG_IF_TIMR2_Pos) +#define TIMRG_IF_TIMR3_Pos 3 +#define TIMRG_IF_TIMR3_Msk (0x01 << TIMRG_IF_TIMR3_Pos) +#define TIMRG_IF_TIMR4_Pos 4 +#define TIMRG_IF_TIMR4_Msk (0x01 << TIMRG_IF_TIMR4_Pos) +#define TIMRG_IF_TIMR5_Pos 5 +#define TIMRG_IF_TIMR5_Msk (0x01 << TIMRG_IF_TIMR5_Pos) +#define TIMRG_IF_PULSE_Pos 16 +#define TIMRG_IF_PULSE_Msk (0x01 << TIMRG_IF_PULSE_Pos) -typedef struct -{ - __IO uint32_t DATA; +#define TIMRG_HALT_TIMR0_Pos 0 //1 ͣ +#define TIMRG_HALT_TIMR0_Msk (0x01 << TIMRG_HALT_TIMR0_Pos) +#define TIMRG_HALT_TIMR1_Pos 1 +#define TIMRG_HALT_TIMR1_Msk (0x01 << TIMRG_HALT_TIMR1_Pos) +#define TIMRG_HALT_TIMR2_Pos 2 +#define TIMRG_HALT_TIMR2_Msk (0x01 << TIMRG_HALT_TIMR2_Pos) +#define TIMRG_HALT_TIMR3_Pos 3 +#define TIMRG_HALT_TIMR3_Msk (0x01 << TIMRG_HALT_TIMR3_Pos) +#define TIMRG_HALT_TIMR4_Pos 4 +#define TIMRG_HALT_TIMR4_Msk (0x01 << TIMRG_HALT_TIMR4_Pos) +#define TIMRG_HALT_TIMR5_Pos 5 +#define TIMRG_HALT_TIMR5_Msk (0x01 << TIMRG_HALT_TIMR5_Pos) - __IO uint32_t CTRL; - __IO uint32_t BAUD; - __IO uint32_t FIFO; - __IO uint32_t LINCR; - - union { - __IO uint32_t CTSCR; - - __IO uint32_t RTSCR; - }; +typedef struct { + __IO uint32_t DATA; + + __IO uint32_t CTRL; + + __IO uint32_t BAUD; + + __IO uint32_t FIFO; + + __IO uint32_t LINCR; + + union { + __IO uint32_t CTSCR; + + __IO uint32_t RTSCR; + }; } UART_TypeDef; -#define UART_DATA_DATA_Pos 0 -#define UART_DATA_DATA_Msk (0x1FF << UART_DATA_DATA_Pos) -#define UART_DATA_VALID_Pos 9 //当DATA字段有有效的接收数据时,该位硬件置1,读取数据后自动清零 -#define UART_DATA_VALID_Msk (0x01 << UART_DATA_VALID_Pos) -#define UART_DATA_PAERR_Pos 10 //Parity Error -#define UART_DATA_PAERR_Msk (0x01 << UART_DATA_PAERR_Pos) -#define UART_CTRL_TXIDLE_Pos 0 //TX IDLE: 0 正在发送数据 1 空闲状态,没有数据发送 -#define UART_CTRL_TXIDLE_Msk (0x01 << UART_CTRL_TXIDLE_Pos) -#define UART_CTRL_TXFF_Pos 1 //TX FIFO Full -#define UART_CTRL_TXFF_Msk (0x01 << UART_CTRL_TXFF_Pos) -#define UART_CTRL_TXIE_Pos 2 //TX 中断使能: 1 TX FF 中数据少于设定个数时产生中断 -#define UART_CTRL_TXIE_Msk (0x01 << UART_CTRL_TXIE_Pos) -#define UART_CTRL_RXNE_Pos 3 //RX FIFO Not Empty -#define UART_CTRL_RXNE_Msk (0x01 << UART_CTRL_RXNE_Pos) -#define UART_CTRL_RXIE_Pos 4 //RX 中断使能: 1 RX FF 中数据达到设定个数时产生中断 -#define UART_CTRL_RXIE_Msk (0x01 << UART_CTRL_RXIE_Pos) -#define UART_CTRL_RXOV_Pos 5 //RX FIFO Overflow,写1清零 -#define UART_CTRL_RXOV_Msk (0x01 << UART_CTRL_RXOV_Pos) -#define UART_CTRL_TXDOIE_Pos 6 //TX Done 中断使能,发送FIFO空且发送发送移位寄存器已将最后一位发送出去 -#define UART_CTRL_TXDOIE_Msk (0x01 << UART_CTRL_TXDOIE_Pos) -#define UART_CTRL_EN_Pos 9 -#define UART_CTRL_EN_Msk (0x01 << UART_CTRL_EN_Pos) -#define UART_CTRL_LOOP_Pos 10 -#define UART_CTRL_LOOP_Msk (0x01 << UART_CTRL_LOOP_Pos) -#define UART_CTRL_BAUDEN_Pos 13 //必须写1 -#define UART_CTRL_BAUDEN_Msk (0x01 << UART_CTRL_BAUDEN_Pos) -#define UART_CTRL_TOIE_Pos 14 //TimeOut 中断使能,接收到上个字符后,超过 TOTIME/BAUDRAUD 秒没有接收到新的数据 -#define UART_CTRL_TOIE_Msk (0x01 << UART_CTRL_TOIE_Pos) -#define UART_CTRL_BRKDET_Pos 15 //LIN Break Detect,检测到LIN Break,即RX线上检测到连续11位低电平 -#define UART_CTRL_BRKDET_Msk (0x01 << UART_CTRL_BRKDET_Pos) -#define UART_CTRL_BRKIE_Pos 16 //LIN Break Detect 中断使能 -#define UART_CTRL_BRKIE_Msk (0x01 << UART_CTRL_BRKIE_Pos) -#define UART_CTRL_GENBRK_Pos 17 //Generate LIN Break,发送LIN Break -#define UART_CTRL_GENBRK_Msk (0x01 << UART_CTRL_GENBRK_Pos) -#define UART_CTRL_DATA9b_Pos 18 //1 9位数据位 0 8位数据位 -#define UART_CTRL_DATA9b_Msk (0x01 << UART_CTRL_DATA9b_Pos) -#define UART_CTRL_PARITY_Pos 19 //000 无校验 001 奇校验 011 偶校验 101 固定为1 111 固定为0 -#define UART_CTRL_PARITY_Msk (0x07 << UART_CTRL_PARITY_Pos) -#define UART_CTRL_STOP2b_Pos 22 //1 2位停止位 0 1位停止位 -#define UART_CTRL_STOP2b_Msk (0x03 << UART_CTRL_STOP2b_Pos) -#define UART_CTRL_TOTIME_Pos 24 //TimeOut 时长 = TOTIME/(BAUDRAUD/10) 秒 -#define UART_CTRL_TOTIME_Msk (0xFFu << UART_CTRL_TOTIME_Pos) +#define UART_DATA_DATA_Pos 0 +#define UART_DATA_DATA_Msk (0x1FF << UART_DATA_DATA_Pos) +#define UART_DATA_VALID_Pos 9 //DATAֶЧĽʱλӲ1ȡݺԶ +#define UART_DATA_VALID_Msk (0x01 << UART_DATA_VALID_Pos) +#define UART_DATA_PAERR_Pos 10 //Parity Error +#define UART_DATA_PAERR_Msk (0x01 << UART_DATA_PAERR_Pos) -#define UART_BAUD_BAUD_Pos 0 //串口波特率 = SYS_Freq/16/BAUD - 1 -#define UART_BAUD_BAUD_Msk (0x3FFF << UART_BAUD_BAUD_Pos) -#define UART_BAUD_TXD_Pos 14 //通过此位可直接读取串口TXD引脚上的电平 -#define UART_BAUD_TXD_Msk (0x01 << UART_BAUD_TXD_Pos) -#define UART_BAUD_RXD_Pos 15 //通过此位可直接读取串口RXD引脚上的电平 -#define UART_BAUD_RXD_Msk (0x01 << UART_BAUD_RXD_Pos) -#define UART_BAUD_RXTOIF_Pos 16 //接收&超时的中断标志 = RXIF | TOIF -#define UART_BAUD_RXTOIF_Msk (0x01 << UART_BAUD_RXTOIF_Pos) -#define UART_BAUD_TXIF_Pos 17 //发送中断标志 = TXTHRF & TXIE -#define UART_BAUD_TXIF_Msk (0x01 << UART_BAUD_TXIF_Pos) -#define UART_BAUD_BRKIF_Pos 18 //LIN Break Detect 中断标志,检测到LIN Break时若BRKIE=1,此位由硬件置位 -#define UART_BAUD_BRKIF_Msk (0x01 << UART_BAUD_BRKIF_Pos) -#define UART_BAUD_RXTHRF_Pos 19 //RX FIFO Threshold Flag,RX FIFO中数据达到设定个数(RXLVL >= RXTHR)时硬件置1 -#define UART_BAUD_RXTHRF_Msk (0x01 << UART_BAUD_RXTHRF_Pos) -#define UART_BAUD_TXTHRF_Pos 20 //TX FIFO Threshold Flag,TX FIFO中数据少于设定个数(TXLVL <= TXTHR)时硬件置1 -#define UART_BAUD_TXTHRF_Msk (0x01 << UART_BAUD_TXTHRF_Pos) -#define UART_BAUD_TOIF_Pos 21 //TimeOut 中断标志,超过 TOTIME/BAUDRAUD 秒没有接收到新的数据时若TOIE=1,此位由硬件置位 -#define UART_BAUD_TOIF_Msk (0x01 << UART_BAUD_TOIF_Pos) -#define UART_BAUD_RXIF_Pos 22 //接收中断标志 = RXTHRF & RXIE -#define UART_BAUD_RXIF_Msk (0x01 << UART_BAUD_RXIF_Pos) -#define UART_BAUD_ABREN_Pos 23 //Auto Baudrate Enable,写1启动自动波特率校准,完成后自动清零 -#define UART_BAUD_ABREN_Msk (0x01 << UART_BAUD_ABREN_Pos) -#define UART_BAUD_ABRBIT_Pos 24 //Auto Baudrate Bit,用于计算波特率的检测位长,0 1位,通过测起始位 脉宽计算波特率,要求发送端发送0xFF \ - // 1 2位,通过测起始位加1位数据位脉宽计算波特率,要求发送端发送0xFE \ - // 1 4位,通过测起始位加3位数据位脉宽计算波特率,要求发送端发送0xF8 \ - // 1 8位,通过测起始位加7位数据位脉宽计算波特率,要求发送端发送0x80 -#define UART_BAUD_ABRBIT_Msk (0x03 << UART_BAUD_ABRBIT_Pos) -#define UART_BAUD_ABRERR_Pos 26 //Auto Baudrate Error,0 自动波特率校准成功 1 自动波特率校准失败 -#define UART_BAUD_ABRERR_Msk (0x01 << UART_BAUD_ABRERR_Pos) -#define UART_BAUD_TXDOIF_Pos 27 //TX Done 中断标志,发送FIFO空且发送发送移位寄存器已将最后一位发送出去 -#define UART_BAUD_TXDOIF_Msk (0x01 << UART_BAUD_TXDOIF_Pos) +#define UART_CTRL_TXIDLE_Pos 0 //TX IDLE: 0 ڷ 1 ״̬ûݷ +#define UART_CTRL_TXIDLE_Msk (0x01 << UART_CTRL_TXIDLE_Pos) +#define UART_CTRL_TXFF_Pos 1 //TX FIFO Full +#define UART_CTRL_TXFF_Msk (0x01 << UART_CTRL_TXFF_Pos) +#define UART_CTRL_TXIE_Pos 2 //TX жʹ: 1 TX FF 趨ʱж +#define UART_CTRL_TXIE_Msk (0x01 << UART_CTRL_TXIE_Pos) +#define UART_CTRL_RXNE_Pos 3 //RX FIFO Not Empty +#define UART_CTRL_RXNE_Msk (0x01 << UART_CTRL_RXNE_Pos) +#define UART_CTRL_RXIE_Pos 4 //RX жʹ: 1 RX FF ݴﵽ趨ʱж +#define UART_CTRL_RXIE_Msk (0x01 << UART_CTRL_RXIE_Pos) +#define UART_CTRL_RXOV_Pos 5 //RX FIFO Overflowд1 +#define UART_CTRL_RXOV_Msk (0x01 << UART_CTRL_RXOV_Pos) +#define UART_CTRL_TXDOIE_Pos 6 //TX Done жʹܣFIFOҷͷλĴѽһλͳȥ +#define UART_CTRL_TXDOIE_Msk (0x01 << UART_CTRL_TXDOIE_Pos) +#define UART_CTRL_EN_Pos 9 +#define UART_CTRL_EN_Msk (0x01 << UART_CTRL_EN_Pos) +#define UART_CTRL_LOOP_Pos 10 +#define UART_CTRL_LOOP_Msk (0x01 << UART_CTRL_LOOP_Pos) +#define UART_CTRL_BAUDEN_Pos 13 //д1 +#define UART_CTRL_BAUDEN_Msk (0x01 << UART_CTRL_BAUDEN_Pos) +#define UART_CTRL_TOIE_Pos 14 //TimeOut жʹܣյϸַ󣬳 TOTIME/BAUDRAUD ûнյµ +#define UART_CTRL_TOIE_Msk (0x01 << UART_CTRL_TOIE_Pos) +#define UART_CTRL_BRKDET_Pos 15 //LIN Break Detect⵽LIN BreakRXϼ⵽11λ͵ƽ +#define UART_CTRL_BRKDET_Msk (0x01 << UART_CTRL_BRKDET_Pos) +#define UART_CTRL_BRKIE_Pos 16 //LIN Break Detect жʹ +#define UART_CTRL_BRKIE_Msk (0x01 << UART_CTRL_BRKIE_Pos) +#define UART_CTRL_GENBRK_Pos 17 //Generate LIN BreakLIN Break +#define UART_CTRL_GENBRK_Msk (0x01 << UART_CTRL_GENBRK_Pos) +#define UART_CTRL_DATA9b_Pos 18 //1 9λλ 0 8λλ +#define UART_CTRL_DATA9b_Msk (0x01 << UART_CTRL_DATA9b_Pos) +#define UART_CTRL_PARITY_Pos 19 //000 У 001 У 011 żУ 101 ̶Ϊ1 111 ̶Ϊ0 +#define UART_CTRL_PARITY_Msk (0x07 << UART_CTRL_PARITY_Pos) +#define UART_CTRL_STOP2b_Pos 22 //1 2λֹͣλ 0 1λֹͣλ +#define UART_CTRL_STOP2b_Msk (0x03 << UART_CTRL_STOP2b_Pos) +#define UART_CTRL_TOTIME_Pos 24 //TimeOut ʱ = TOTIME/(BAUDRAUD/10) +#define UART_CTRL_TOTIME_Msk (0xFFu<< UART_CTRL_TOTIME_Pos) -#define UART_FIFO_RXLVL_Pos 0 //RX FIFO Level,RX FIFO 中字符个数 -#define UART_FIFO_RXLVL_Msk (0xFF << UART_FIFO_RXLVL_Pos) -#define UART_FIFO_TXLVL_Pos 8 //TX FIFO Level,TX FIFO 中字符个数 -#define UART_FIFO_TXLVL_Msk (0xFF << UART_FIFO_TXLVL_Pos) -#define UART_FIFO_RXTHR_Pos 16 //RX FIFO Threshold,RX中断触发门限,中断使能时 RXLVL >= RXTHR 触发RX中断 -#define UART_FIFO_RXTHR_Msk (0xFF << UART_FIFO_RXTHR_Pos) -#define UART_FIFO_TXTHR_Pos 24 //TX FIFO Threshold,TX中断触发门限,中断使能时 TXLVL <= TXTHR 触发TX中断 -#define UART_FIFO_TXTHR_Msk (0xFFu << UART_FIFO_TXTHR_Pos) +#define UART_BAUD_BAUD_Pos 0 //ڲ = SYS_Freq/16/BAUD - 1 +#define UART_BAUD_BAUD_Msk (0x3FFF << UART_BAUD_BAUD_Pos) +#define UART_BAUD_TXD_Pos 14 //ͨλֱӶȡTXDϵĵƽ +#define UART_BAUD_TXD_Msk (0x01 << UART_BAUD_TXD_Pos) +#define UART_BAUD_RXD_Pos 15 //ͨλֱӶȡRXDϵĵƽ +#define UART_BAUD_RXD_Msk (0x01 << UART_BAUD_RXD_Pos) +#define UART_BAUD_RXTOIF_Pos 16 //&ʱжϱ־ = RXIF | TOIF +#define UART_BAUD_RXTOIF_Msk (0x01 << UART_BAUD_RXTOIF_Pos) +#define UART_BAUD_TXIF_Pos 17 //жϱ־ = TXTHRF & TXIE +#define UART_BAUD_TXIF_Msk (0x01 << UART_BAUD_TXIF_Pos) +#define UART_BAUD_BRKIF_Pos 18 //LIN Break Detect жϱ־⵽LIN BreakʱBRKIE=1λӲλ +#define UART_BAUD_BRKIF_Msk (0x01 << UART_BAUD_BRKIF_Pos) +#define UART_BAUD_RXTHRF_Pos 19 //RX FIFO Threshold FlagRX FIFOݴﵽ趨RXLVL >= RXTHRʱӲ1 +#define UART_BAUD_RXTHRF_Msk (0x01 << UART_BAUD_RXTHRF_Pos) +#define UART_BAUD_TXTHRF_Pos 20 //TX FIFO Threshold FlagTX FIFO趨TXLVL <= TXTHRʱӲ1 +#define UART_BAUD_TXTHRF_Msk (0x01 << UART_BAUD_TXTHRF_Pos) +#define UART_BAUD_TOIF_Pos 21 //TimeOut жϱ־ TOTIME/BAUDRAUD ûнյµʱTOIE=1λӲλ +#define UART_BAUD_TOIF_Msk (0x01 << UART_BAUD_TOIF_Pos) +#define UART_BAUD_RXIF_Pos 22 //жϱ־ = RXTHRF & RXIE +#define UART_BAUD_RXIF_Msk (0x01 << UART_BAUD_RXIF_Pos) +#define UART_BAUD_ABREN_Pos 23 //Auto Baudrate Enableд1ԶУ׼ɺԶ +#define UART_BAUD_ABREN_Msk (0x01 << UART_BAUD_ABREN_Pos) +#define UART_BAUD_ABRBIT_Pos 24 //Auto Baudrate Bitڼ㲨ʵļλ0 1λͨʼλ 㲨ʣҪͶ˷0xFF + // 1 2λͨʼλ1λλ㲨ʣҪͶ˷0xFE + // 1 4λͨʼλ3λλ㲨ʣҪͶ˷0xF8 + // 1 8λͨʼλ7λλ㲨ʣҪͶ˷0x80 +#define UART_BAUD_ABRBIT_Msk (0x03 << UART_BAUD_ABRBIT_Pos) +#define UART_BAUD_ABRERR_Pos 26 //Auto Baudrate Error0 ԶУ׼ɹ 1 ԶУ׼ʧ +#define UART_BAUD_ABRERR_Msk (0x01 << UART_BAUD_ABRERR_Pos) +#define UART_BAUD_TXDOIF_Pos 27 //TX Done жϱ־FIFOҷͷλĴѽһλͳȥ +#define UART_BAUD_TXDOIF_Msk (0x01 << UART_BAUD_TXDOIF_Pos) -#define UART_LINCR_BRKDETIE_Pos 0 //检测到LIN Break中断使能 -#define UART_LINCR_BRKDETIE_Msk (0x01 << UART_LINCR_BRKDETIE_Pos) -#define UART_LINCR_BRKDETIF_Pos 1 //检测到LIN Break中断状态 -#define UART_LINCR_BRKDETIF_Msk (0x01 << UART_LINCR_BRKDETIF_Pos) -#define UART_LINCR_GENBRKIE_Pos 2 //发送LIN Break完成中断使能 -#define UART_LINCR_GENBRKIE_Msk (0x01 << UART_LINCR_GENBRKIE_Pos) -#define UART_LINCR_GENBRKIF_Pos 3 //发送LIN Break完成中断状态 -#define UART_LINCR_GENBRKIF_Msk (0x01 << UART_LINCR_GENBRKIF_Pos) -#define UART_LINCR_GENBRK_Pos 4 //发送LIN Break,发送完成自动清零 -#define UART_LINCR_GENBRK_Msk (0x01 << UART_LINCR_GENBRK_Pos) +#define UART_FIFO_RXLVL_Pos 0 //RX FIFO LevelRX FIFO ַ +#define UART_FIFO_RXLVL_Msk (0xFF << UART_FIFO_RXLVL_Pos) +#define UART_FIFO_TXLVL_Pos 8 //TX FIFO LevelTX FIFO ַ +#define UART_FIFO_TXLVL_Msk (0xFF << UART_FIFO_TXLVL_Pos) +#define UART_FIFO_RXTHR_Pos 16 //RX FIFO ThresholdRXжϴޣжʹʱ RXLVL >= RXTHR RXж +#define UART_FIFO_RXTHR_Msk (0xFF << UART_FIFO_RXTHR_Pos) +#define UART_FIFO_TXTHR_Pos 24 //TX FIFO ThresholdTXжϴޣжʹʱ TXLVL <= TXTHR TXж +#define UART_FIFO_TXTHR_Msk (0xFFu<< UART_FIFO_TXTHR_Pos) -#define UART_CTSCR_EN_Pos 0 //CTS流控使能 -#define UART_CTSCR_EN_Msk (0x01 << UART_CTSCR_EN_Pos) -#define UART_CTSCR_POL_Pos 2 //CTS信号极性,0 低有效,CTS输入为低表示可以发送数据 -#define UART_CTSCR_POL_Msk (0x01 << UART_CTSCR_POL_Pos) -#define UART_CTSCR_STAT_Pos 7 //CTS信号的当前状态 -#define UART_CTSCR_STAT_Msk (0x01 << UART_CTSCR_STAT_Pos) +#define UART_LINCR_BRKDETIE_Pos 0 //⵽LIN Breakжʹ +#define UART_LINCR_BRKDETIE_Msk (0x01 << UART_LINCR_BRKDETIE_Pos) +#define UART_LINCR_BRKDETIF_Pos 1 //⵽LIN Breakж״̬ +#define UART_LINCR_BRKDETIF_Msk (0x01 << UART_LINCR_BRKDETIF_Pos) +#define UART_LINCR_GENBRKIE_Pos 2 //LIN Breakжʹ +#define UART_LINCR_GENBRKIE_Msk (0x01 << UART_LINCR_GENBRKIE_Pos) +#define UART_LINCR_GENBRKIF_Pos 3 //LIN Breakж״̬ +#define UART_LINCR_GENBRKIF_Msk (0x01 << UART_LINCR_GENBRKIF_Pos) +#define UART_LINCR_GENBRK_Pos 4 //LIN BreakԶ +#define UART_LINCR_GENBRK_Msk (0x01 << UART_LINCR_GENBRK_Pos) -#define UART_RTSCR_EN_Pos 1 //RTS流控使能 -#define UART_RTSCR_EN_Msk (0x01 << UART_RTSCR_EN_Pos) -#define UART_RTSCR_POL_Pos 3 //RTS信号极性 0 低有效,RTS输入为低表示可以接收数据 -#define UART_RTSCR_POL_Msk (0x01 << UART_RTSCR_POL_Pos) -#define UART_RTSCR_THR_Pos 4 //RTS流控的触发阈值 0 1字节 1 2字节 2 4字节 3 6字节 -#define UART_RTSCR_THR_Msk (0x07 << UART_RTSCR_THR_Pos) -#define UART_RTSCR_STAT_Pos 8 //RTS信号的当前状态 -#define UART_RTSCR_STAT_Msk (0x01 << UART_RTSCR_STAT_Pos) +#define UART_CTSCR_EN_Pos 0 //CTSʹ +#define UART_CTSCR_EN_Msk (0x01 << UART_CTSCR_EN_Pos) +#define UART_CTSCR_POL_Pos 2 //CTSźżԣ0 ЧCTSΪͱʾԷ +#define UART_CTSCR_POL_Msk (0x01 << UART_CTSCR_POL_Pos) +#define UART_CTSCR_STAT_Pos 7 //CTSźŵĵǰ״̬ +#define UART_CTSCR_STAT_Msk (0x01 << UART_CTSCR_STAT_Pos) -typedef struct -{ - __IO uint32_t CTRL; +#define UART_RTSCR_EN_Pos 1 //RTSʹ +#define UART_RTSCR_EN_Msk (0x01 << UART_RTSCR_EN_Pos) +#define UART_RTSCR_POL_Pos 3 //RTSźż 0 ЧRTSΪͱʾԽ +#define UART_RTSCR_POL_Msk (0x01 << UART_RTSCR_POL_Pos) +#define UART_RTSCR_THR_Pos 4 //RTSصĴֵ 0 1ֽ 1 2ֽ 2 4ֽ 3 6ֽ +#define UART_RTSCR_THR_Msk (0x07 << UART_RTSCR_THR_Pos) +#define UART_RTSCR_STAT_Pos 8 //RTSźŵĵǰ״̬ +#define UART_RTSCR_STAT_Msk (0x01 << UART_RTSCR_STAT_Pos) - __IO uint32_t DATA; - __IO uint32_t STAT; - __IO uint32_t IE; - __IO uint32_t IF; +typedef struct { + __IO uint32_t CTRL; + + __IO uint32_t DATA; + + __IO uint32_t STAT; + + __IO uint32_t IE; + + __IO uint32_t IF; } SPI_TypeDef; -#define SPI_CTRL_CLKDIV_Pos 0 //Clock Divider, SPI工作时钟 = SYS_Freq/pow(2, CLKDIV+2) -#define SPI_CTRL_CLKDIV_Msk (0x07 << SPI_CTRL_CLKDIV_Pos) -#define SPI_CTRL_EN_Pos 3 -#define SPI_CTRL_EN_Msk (0x01 << SPI_CTRL_EN_Pos) -#define SPI_CTRL_SIZE_Pos 4 //Data Size Select, 取值3--15,表示4--16位 -#define SPI_CTRL_SIZE_Msk (0x0F << SPI_CTRL_SIZE_Pos) -#define SPI_CTRL_CPHA_Pos 8 //0 在SCLK的第一个跳变沿采样数据 1 在SCLK的第二个跳变沿采样数据 -#define SPI_CTRL_CPHA_Msk (0x01 << SPI_CTRL_CPHA_Pos) -#define SPI_CTRL_CPOL_Pos 9 //0 空闲状态下SCLK为低电平 1 空闲状态下SCLK为高电平 -#define SPI_CTRL_CPOL_Msk (0x01 << SPI_CTRL_CPOL_Pos) -#define SPI_CTRL_FFS_Pos 10 //Frame Format Select, 0 SPI 1 TI SSI 2 SPI 3 SPI -#define SPI_CTRL_FFS_Msk (0x03 << SPI_CTRL_FFS_Pos) -#define SPI_CTRL_MSTR_Pos 12 //Master, 1 主模式 0 从模式 -#define SPI_CTRL_MSTR_Msk (0x01 << SPI_CTRL_MSTR_Pos) -#define SPI_CTRL_FAST_Pos 13 //1 SPI工作时钟 = SYS_Freq/2 0 SPI工作时钟由SPI->CTRL.CLKDIV设置 -#define SPI_CTRL_FAST_Msk (0x01 << SPI_CTRL_FAST_Pos) -#define SPI_CTRL_FILTE_Pos 16 //1 对SPI输入信号进行去抖操作 0 对SPI输入信号不进行去抖操作 -#define SPI_CTRL_FILTE_Msk (0x01 << SPI_CTRL_FILTE_Pos) -#define SPI_CTRL_SSN_H_Pos 17 //0 传输过程中SSN始终为0 1 传输过程中每字符之间会将SSN拉高半个SCLK周期 -#define SPI_CTRL_SSN_H_Msk (0x01 << SPI_CTRL_SSN_H_Pos) -#define SPI_CTRL_TFCLR_Pos 24 //TX FIFO Clear -#define SPI_CTRL_TFCLR_Msk (0x01 << SPI_CTRL_TFCLR_Pos) -#define SPI_CTRL_RFCLR_Pos 25 //RX FIFO Clear -#define SPI_CTRL_RFCLR_Msk (0x01 << SPI_CTRL_RFCLR_Pos) -#define SPI_STAT_WTC_Pos 0 //Word Transmit Complete,每传输完成一个数据字由硬件置1,软件写1清零 -#define SPI_STAT_WTC_Msk (0x01 << SPI_STAT_WTC_Pos) -#define SPI_STAT_TFE_Pos 1 //发送FIFO Empty -#define SPI_STAT_TFE_Msk (0x01 << SPI_STAT_TFE_Pos) -#define SPI_STAT_TFNF_Pos 2 //发送FIFO Not Full -#define SPI_STAT_TFNF_Msk (0x01 << SPI_STAT_TFNF_Pos) -#define SPI_STAT_RFNE_Pos 3 //接收FIFO Not Empty -#define SPI_STAT_RFNE_Msk (0x01 << SPI_STAT_RFNE_Pos) -#define SPI_STAT_RFF_Pos 4 //接收FIFO Full -#define SPI_STAT_RFF_Msk (0x01 << SPI_STAT_RFF_Pos) -#define SPI_STAT_RFOVF_Pos 5 //接收FIFO Overflow -#define SPI_STAT_RFOVF_Msk (0x01 << SPI_STAT_RFOVF_Pos) -#define SPI_STAT_TFLVL_Pos 6 //发送FIFO中数据个数, 0 TFNF=0时表示FIFO内有8个数据,TFNF=1时表示FIFO内有0个数据 1--7 FIFO内有1--7个数据 -#define SPI_STAT_TFLVL_Msk (0x07 << SPI_STAT_TFLVL_Pos) -#define SPI_STAT_RFLVL_Pos 9 //接收FIFO中数据个数, 0 RFF=1时表示FIFO内有8个数据, RFF=0时表示FIFO内有0个数据 1--7 FIFO内有1--7个数据 -#define SPI_STAT_RFLVL_Msk (0x07 << SPI_STAT_RFLVL_Pos) -#define SPI_STAT_BUSY_Pos 15 -#define SPI_STAT_BUSY_Msk (0x01 << SPI_STAT_BUSY_Pos) +#define SPI_CTRL_CLKDIV_Pos 0 //Clock Divider, SPIʱ = SYS_Freq/pow(2, CLKDIV+2) +#define SPI_CTRL_CLKDIV_Msk (0x07 << SPI_CTRL_CLKDIV_Pos) +#define SPI_CTRL_EN_Pos 3 +#define SPI_CTRL_EN_Msk (0x01 << SPI_CTRL_EN_Pos) +#define SPI_CTRL_SIZE_Pos 4 //Data Size Select, ȡֵ3--15ʾ4--16λ +#define SPI_CTRL_SIZE_Msk (0x0F << SPI_CTRL_SIZE_Pos) +#define SPI_CTRL_CPHA_Pos 8 //0 SCLKĵһز 1 SCLKĵڶز +#define SPI_CTRL_CPHA_Msk (0x01 << SPI_CTRL_CPHA_Pos) +#define SPI_CTRL_CPOL_Pos 9 //0 ״̬SCLKΪ͵ƽ 1 ״̬SCLKΪߵƽ +#define SPI_CTRL_CPOL_Msk (0x01 << SPI_CTRL_CPOL_Pos) +#define SPI_CTRL_FFS_Pos 10 //Frame Format Select, 0 SPI 1 TI SSI 2 SPI 3 SPI +#define SPI_CTRL_FFS_Msk (0x03 << SPI_CTRL_FFS_Pos) +#define SPI_CTRL_MSTR_Pos 12 //Master, 1 ģʽ 0 ģʽ +#define SPI_CTRL_MSTR_Msk (0x01 << SPI_CTRL_MSTR_Pos) +#define SPI_CTRL_FAST_Pos 13 //1 SPIʱ = SYS_Freq/2 0 SPIʱSPI->CTRL.CLKDIV +#define SPI_CTRL_FAST_Msk (0x01 << SPI_CTRL_FAST_Pos) +#define SPI_CTRL_FILTE_Pos 16 //1 SPIźŽȥ 0 SPIźŲȥ +#define SPI_CTRL_FILTE_Msk (0x01 << SPI_CTRL_FILTE_Pos) +#define SPI_CTRL_SSN_H_Pos 17 //0 SSNʼΪ0 1 ÿַ֮ὫSSN߰SCLK +#define SPI_CTRL_SSN_H_Msk (0x01 << SPI_CTRL_SSN_H_Pos) +#define SPI_CTRL_TFCLR_Pos 24 //TX FIFO Clear +#define SPI_CTRL_TFCLR_Msk (0x01 << SPI_CTRL_TFCLR_Pos) +#define SPI_CTRL_RFCLR_Pos 25 //RX FIFO Clear +#define SPI_CTRL_RFCLR_Msk (0x01 << SPI_CTRL_RFCLR_Pos) -#define SPI_IE_RFOVF_Pos 0 -#define SPI_IE_RFOVF_Msk (0x01 << SPI_IE_RFOVF_Pos) -#define SPI_IE_RFF_Pos 1 -#define SPI_IE_RFF_Msk (0x01 << SPI_IE_RFF_Pos) -#define SPI_IE_RFHF_Pos 2 -#define SPI_IE_RFHF_Msk (0x01 << SPI_IE_RFHF_Pos) -#define SPI_IE_TFE_Pos 3 -#define SPI_IE_TFE_Msk (0x01 << SPI_IE_TFE_Pos) -#define SPI_IE_TFHF_Pos 4 -#define SPI_IE_TFHF_Msk (0x01 << SPI_IE_TFHF_Pos) -#define SPI_IE_WTC_Pos 8 //Word Transmit Complete -#define SPI_IE_WTC_Msk (0x01 << SPI_IE_WTC_Pos) -#define SPI_IE_FTC_Pos 9 //Frame Transmit Complete -#define SPI_IE_FTC_Msk (0x01 << SPI_IE_FTC_Pos) +#define SPI_STAT_WTC_Pos 0 //Word Transmit CompleteÿһӲ1д1 +#define SPI_STAT_WTC_Msk (0x01 << SPI_STAT_WTC_Pos) +#define SPI_STAT_TFE_Pos 1 //FIFO Empty +#define SPI_STAT_TFE_Msk (0x01 << SPI_STAT_TFE_Pos) +#define SPI_STAT_TFNF_Pos 2 //FIFO Not Full +#define SPI_STAT_TFNF_Msk (0x01 << SPI_STAT_TFNF_Pos) +#define SPI_STAT_RFNE_Pos 3 //FIFO Not Empty +#define SPI_STAT_RFNE_Msk (0x01 << SPI_STAT_RFNE_Pos) +#define SPI_STAT_RFF_Pos 4 //FIFO Full +#define SPI_STAT_RFF_Msk (0x01 << SPI_STAT_RFF_Pos) +#define SPI_STAT_RFOVF_Pos 5 //FIFO Overflow +#define SPI_STAT_RFOVF_Msk (0x01 << SPI_STAT_RFOVF_Pos) +#define SPI_STAT_TFLVL_Pos 6 //FIFOݸ 0 TFNF=0ʱʾFIFO8ݣTFNF=1ʱʾFIFO0 1--7 FIFO1--7 +#define SPI_STAT_TFLVL_Msk (0x07 << SPI_STAT_TFLVL_Pos) +#define SPI_STAT_RFLVL_Pos 9 //FIFOݸ 0 RFF=1ʱʾFIFO8ݣ RFF=0ʱʾFIFO0 1--7 FIFO1--7 +#define SPI_STAT_RFLVL_Msk (0x07 << SPI_STAT_RFLVL_Pos) +#define SPI_STAT_BUSY_Pos 15 +#define SPI_STAT_BUSY_Msk (0x01 << SPI_STAT_BUSY_Pos) -#define SPI_IF_RFOVF_Pos 0 //写1清零 -#define SPI_IF_RFOVF_Msk (0x01 << SPI_IF_RFOVF_Pos) -#define SPI_IF_RFF_Pos 1 -#define SPI_IF_RFF_Msk (0x01 << SPI_IF_RFF_Pos) -#define SPI_IF_RFHF_Pos 2 -#define SPI_IF_RFHF_Msk (0x01 << SPI_IF_RFHF_Pos) -#define SPI_IF_TFE_Pos 3 -#define SPI_IF_TFE_Msk (0x01 << SPI_IF_TFE_Pos) -#define SPI_IF_TFHF_Pos 4 -#define SPI_IF_TFHF_Msk (0x01 << SPI_IF_TFHF_Pos) -#define SPI_IF_WTC_Pos 8 //Word Transmit Complete,每传输完成一个数据字由硬件置1 -#define SPI_IF_WTC_Msk (0x01 << SPI_IF_WTC_Pos) -#define SPI_IF_FTC_Pos 9 //Frame Transmit Complete,WTC置位时若TX FIFO是空的,则FTC置位 -#define SPI_IF_FTC_Msk (0x01 << SPI_IF_FTC_Pos) +#define SPI_IE_RFOVF_Pos 0 +#define SPI_IE_RFOVF_Msk (0x01 << SPI_IE_RFOVF_Pos) +#define SPI_IE_RFF_Pos 1 +#define SPI_IE_RFF_Msk (0x01 << SPI_IE_RFF_Pos) +#define SPI_IE_RFHF_Pos 2 +#define SPI_IE_RFHF_Msk (0x01 << SPI_IE_RFHF_Pos) +#define SPI_IE_TFE_Pos 3 +#define SPI_IE_TFE_Msk (0x01 << SPI_IE_TFE_Pos) +#define SPI_IE_TFHF_Pos 4 +#define SPI_IE_TFHF_Msk (0x01 << SPI_IE_TFHF_Pos) +#define SPI_IE_WTC_Pos 8 //Word Transmit Complete +#define SPI_IE_WTC_Msk (0x01 << SPI_IE_WTC_Pos) +#define SPI_IE_FTC_Pos 9 //Frame Transmit Complete +#define SPI_IE_FTC_Msk (0x01 << SPI_IE_FTC_Pos) -typedef struct -{ - __IO uint32_t CLKDIV; //[15:0] 须将内部工作频率分到SCL频率的5倍,即CLKDIV = SYS_Freq/5/SCL_Freq - 1 +#define SPI_IF_RFOVF_Pos 0 //д1 +#define SPI_IF_RFOVF_Msk (0x01 << SPI_IF_RFOVF_Pos) +#define SPI_IF_RFF_Pos 1 +#define SPI_IF_RFF_Msk (0x01 << SPI_IF_RFF_Pos) +#define SPI_IF_RFHF_Pos 2 +#define SPI_IF_RFHF_Msk (0x01 << SPI_IF_RFHF_Pos) +#define SPI_IF_TFE_Pos 3 +#define SPI_IF_TFE_Msk (0x01 << SPI_IF_TFE_Pos) +#define SPI_IF_TFHF_Pos 4 +#define SPI_IF_TFHF_Msk (0x01 << SPI_IF_TFHF_Pos) +#define SPI_IF_WTC_Pos 8 //Word Transmit CompleteÿһӲ1 +#define SPI_IF_WTC_Msk (0x01 << SPI_IF_WTC_Pos) +#define SPI_IF_FTC_Pos 9 //Frame Transmit CompleteWTCλʱTX FIFOǿյģFTCλ +#define SPI_IF_FTC_Msk (0x01 << SPI_IF_FTC_Pos) - __IO uint32_t CTRL; - __IO uint32_t MSTDAT; - __IO uint32_t MSTCMD; - __IO uint32_t SLVCR; +typedef struct { + __IO uint32_t CLKDIV; //[15:0] 뽫ڲƵʷֵSCLƵʵ5CLKDIV = SYS_Freq/5/SCL_Freq - 1 - __IO uint32_t SLVIF; + __IO uint32_t CTRL; - __IO uint32_t SLVTX; + __IO uint32_t MSTDAT; - __IO uint32_t SLVRX; + __IO uint32_t MSTCMD; + + __IO uint32_t SLVCR; + + __IO uint32_t SLVIF; + + __IO uint32_t SLVTX; + + __IO uint32_t SLVRX; } I2C_TypeDef; -#define I2C_CTRL_MSTIE_Pos 6 -#define I2C_CTRL_MSTIE_Msk (0x01 << I2C_CTRL_MSTIE_Pos) -#define I2C_CTRL_EN_Pos 7 -#define I2C_CTRL_EN_Msk (0x01 << I2C_CTRL_EN_Pos) -#define I2C_MSTCMD_IF_Pos 0 //1 有等待处理的中断,写1清零 有两种情况下此位硬件置位:1、一个字节传输完成 2、总线访问权丢失 -#define I2C_MSTCMD_IF_Msk (0x01 << I2C_MSTCMD_IF_Pos) -#define I2C_MSTCMD_TIP_Pos 1 //Transmission In Process -#define I2C_MSTCMD_TIP_Msk (0x01 << I2C_MSTCMD_TIP_Pos) -#define I2C_MSTCMD_ACK_Pos 3 //接收模式下,0 向发送端反馈ACK 1 向发送端反馈NACK -#define I2C_MSTCMD_ACK_Msk (0x01 << I2C_MSTCMD_ACK_Pos) -#define I2C_MSTCMD_WR_Pos 4 // 向Slave写数据时,把这一位写1,自动清零 -#define I2C_MSTCMD_WR_Msk (0x01 << I2C_MSTCMD_WR_Pos) -#define I2C_MSTCMD_RD_Pos 5 //写:从Slave读数据时,把这一位写1,自动清零 读:当I2C模块失去总线的访问权时硬件置1 -#define I2C_MSTCMD_RD_Msk (0x01 << I2C_MSTCMD_RD_Pos) -#define I2C_MSTCMD_BUSY_Pos 6 //读:当检测到START之后,这一位变1;当检测到STOP之后,这一位变0 -#define I2C_MSTCMD_BUSY_Msk (0x01 << I2C_MSTCMD_BUSY_Pos) -#define I2C_MSTCMD_STO_Pos 6 //写:产生STOP,自动清零 -#define I2C_MSTCMD_STO_Msk (0x01 << I2C_MSTCMD_STO_Pos) -#define I2C_MSTCMD_RXACK_Pos 7 //读:接收到的Slave的ACK位,0 收到ACK 1 收到NACK -#define I2C_MSTCMD_RXACK_Msk (0x01 << I2C_MSTCMD_RXACK_Pos) -#define I2C_MSTCMD_STA_Pos 7 //写:产生START,自动清零 -#define I2C_MSTCMD_STA_Msk (0x01 << I2C_MSTCMD_STA_Pos) +#define I2C_CTRL_MSTIE_Pos 6 +#define I2C_CTRL_MSTIE_Msk (0x01 << I2C_CTRL_MSTIE_Pos) +#define I2C_CTRL_EN_Pos 7 +#define I2C_CTRL_EN_Msk (0x01 << I2C_CTRL_EN_Pos) -#define I2C_SLVCR_IM_RXEND_Pos 0 //接收完成中断禁止 -#define I2C_SLVCR_IM_RXEND_Msk (0x01 << I2C_SLVCR_IM_RXEND_Pos) -#define I2C_SLVCR_IM_TXEND_Pos 1 //发送完成中断禁止 -#define I2C_SLVCR_IM_TXEND_Msk (0x01 << I2C_SLVCR_IM_TXEND_Pos) -#define I2C_SLVCR_IM_STADET_Pos 2 //检测到起始中断禁止 -#define I2C_SLVCR_IM_STADET_Msk (0x01 << I2C_SLVCR_IM_STADET_Pos) -#define I2C_SLVCR_IM_STODET_Pos 3 //检测到停止中断禁止 -#define I2C_SLVCR_IM_STODET_Msk (0x01 << I2C_SLVCR_IM_STODET_Pos) -#define I2C_SLVCR_IM_RDREQ_Pos 4 //接收到读请求中断禁止 -#define I2C_SLVCR_IM_RDREQ_Msk (0x01 << I2C_SLVCR_IM_RDREQ_Pos) -#define I2C_SLVCR_IM_WRREQ_Pos 5 //接收到写请求中断禁止 -#define I2C_SLVCR_IM_WRREQ_Msk (0x01 << I2C_SLVCR_IM_WRREQ_Pos) -#define I2C_SLVCR_ADDR7b_Pos 16 //1 7位地址模式 0 10位地址模式 -#define I2C_SLVCR_ADDR7b_Msk (0x01 << I2C_SLVCR_ADDR7b_Pos) -#define I2C_SLVCR_ACK_Pos 17 //1 应答ACK 0 应答NACK -#define I2C_SLVCR_ACK_Msk (0x01 << I2C_SLVCR_ACK_Pos) -#define I2C_SLVCR_SLAVE_Pos 18 //1 从机模式 0 主机模式 -#define I2C_SLVCR_SLAVE_Msk (0x01 << I2C_SLVCR_SLAVE_Pos) -#define I2C_SLVCR_DEBOUNCE_Pos 19 //去抖动使能 -#define I2C_SLVCR_DEBOUNCE_Msk (0x01 << I2C_SLVCR_DEBOUNCE_Pos) -#define I2C_SLVCR_ADDR_Pos 20 //从机地址 -#define I2C_SLVCR_ADDR_Msk (0x3FF << I2C_SLVCR_ADDR_Pos) +#define I2C_MSTCMD_IF_Pos 0 //1 еȴжϣд1 ´λӲλ1һֽڴ 2߷Ȩʧ +#define I2C_MSTCMD_IF_Msk (0x01 << I2C_MSTCMD_IF_Pos) +#define I2C_MSTCMD_TIP_Pos 1 //Transmission In Process +#define I2C_MSTCMD_TIP_Msk (0x01 << I2C_MSTCMD_TIP_Pos) +#define I2C_MSTCMD_ACK_Pos 3 //ģʽ£0 Ͷ˷ACK 1 Ͷ˷NACK +#define I2C_MSTCMD_ACK_Msk (0x01 << I2C_MSTCMD_ACK_Pos) +#define I2C_MSTCMD_WR_Pos 4 // Slaveдʱһλд1Զ +#define I2C_MSTCMD_WR_Msk (0x01 << I2C_MSTCMD_WR_Pos) +#define I2C_MSTCMD_RD_Pos 5 //дSlaveʱһλд1Զ I2CģʧȥߵķȨʱӲ1 +#define I2C_MSTCMD_RD_Msk (0x01 << I2C_MSTCMD_RD_Pos) +#define I2C_MSTCMD_BUSY_Pos 6 //⵽START֮һλ1⵽STOP֮һλ0 +#define I2C_MSTCMD_BUSY_Msk (0x01 << I2C_MSTCMD_BUSY_Pos) +#define I2C_MSTCMD_STO_Pos 6 //дSTOPԶ +#define I2C_MSTCMD_STO_Msk (0x01 << I2C_MSTCMD_STO_Pos) +#define I2C_MSTCMD_RXACK_Pos 7 //յSlaveACKλ0 յACK 1 յNACK +#define I2C_MSTCMD_RXACK_Msk (0x01 << I2C_MSTCMD_RXACK_Pos) +#define I2C_MSTCMD_STA_Pos 7 //дSTARTԶ +#define I2C_MSTCMD_STA_Msk (0x01 << I2C_MSTCMD_STA_Pos) -#define I2C_SLVIF_RXEND_Pos 0 //接收完成中断标志,写1清零 -#define I2C_SLVIF_RXEND_Msk (0x01 << I2C_SLVIF_RXEND_Pos) -#define I2C_SLVIF_TXEND_Pos 1 //发送完成中断标志,写1清零 -#define I2C_SLVIF_TXEND_Msk (0x01 << I2C_SLVIF_TXEND_Pos) -#define I2C_SLVIF_STADET_Pos 2 //检测到起始中断标志,写1清零 -#define I2C_SLVIF_STADET_Msk (0x01 << I2C_SLVIF_STADET_Pos) -#define I2C_SLVIF_STODET_Pos 3 //检测到停止中断标志,写1清零 -#define I2C_SLVIF_STODET_Msk (0x01 << I2C_SLVIF_STODET_Pos) -#define I2C_SLVIF_RDREQ_Pos 4 //接收到读请求中断标志 -#define I2C_SLVIF_RDREQ_Msk (0x01 << I2C_SLVIF_RDREQ_Pos) -#define I2C_SLVIF_WRREQ_Pos 5 //接收到写请求中断标志 -#define I2C_SLVIF_WRREQ_Msk (0x01 << I2C_SLVIF_WRREQ_Pos) -#define I2C_SLVIF_ACTIVE_Pos 6 //slave 有效 -#define I2C_SLVIF_ACTIVE_Msk (0x01 << I2C_SLVIF_ACTIVE_Pos) +#define I2C_SLVCR_IM_RXEND_Pos 0 //жϽֹ +#define I2C_SLVCR_IM_RXEND_Msk (0x01 << I2C_SLVCR_IM_RXEND_Pos) +#define I2C_SLVCR_IM_TXEND_Pos 1 //жϽֹ +#define I2C_SLVCR_IM_TXEND_Msk (0x01 << I2C_SLVCR_IM_TXEND_Pos) +#define I2C_SLVCR_IM_STADET_Pos 2 //⵽ʼжϽֹ +#define I2C_SLVCR_IM_STADET_Msk (0x01 << I2C_SLVCR_IM_STADET_Pos) +#define I2C_SLVCR_IM_STODET_Pos 3 //⵽ֹͣжϽֹ +#define I2C_SLVCR_IM_STODET_Msk (0x01 << I2C_SLVCR_IM_STODET_Pos) +#define I2C_SLVCR_IM_RDREQ_Pos 4 //յжϽֹ +#define I2C_SLVCR_IM_RDREQ_Msk (0x01 << I2C_SLVCR_IM_RDREQ_Pos) +#define I2C_SLVCR_IM_WRREQ_Pos 5 //յджϽֹ +#define I2C_SLVCR_IM_WRREQ_Msk (0x01 << I2C_SLVCR_IM_WRREQ_Pos) +#define I2C_SLVCR_ADDR7b_Pos 16 //1 7λַģʽ 0 10λַģʽ +#define I2C_SLVCR_ADDR7b_Msk (0x01 << I2C_SLVCR_ADDR7b_Pos) +#define I2C_SLVCR_ACK_Pos 17 //1 ӦACK 0 ӦNACK +#define I2C_SLVCR_ACK_Msk (0x01 << I2C_SLVCR_ACK_Pos) +#define I2C_SLVCR_SLAVE_Pos 18 //1 ӻģʽ 0 ģʽ +#define I2C_SLVCR_SLAVE_Msk (0x01 << I2C_SLVCR_SLAVE_Pos) +#define I2C_SLVCR_DEBOUNCE_Pos 19 //ȥʹ +#define I2C_SLVCR_DEBOUNCE_Msk (0x01 << I2C_SLVCR_DEBOUNCE_Pos) +#define I2C_SLVCR_ADDR_Pos 20 //ӻַ +#define I2C_SLVCR_ADDR_Msk (0x3FF << I2C_SLVCR_ADDR_Pos) -typedef struct -{ - __IO uint32_t CTRL; +#define I2C_SLVIF_RXEND_Pos 0 //жϱ־д1 +#define I2C_SLVIF_RXEND_Msk (0x01 << I2C_SLVIF_RXEND_Pos) +#define I2C_SLVIF_TXEND_Pos 1 //жϱ־д1 +#define I2C_SLVIF_TXEND_Msk (0x01 << I2C_SLVIF_TXEND_Pos) +#define I2C_SLVIF_STADET_Pos 2 //⵽ʼжϱ־д1 +#define I2C_SLVIF_STADET_Msk (0x01 << I2C_SLVIF_STADET_Pos) +#define I2C_SLVIF_STODET_Pos 3 //⵽ֹͣжϱ־д1 +#define I2C_SLVIF_STODET_Msk (0x01 << I2C_SLVIF_STODET_Pos) +#define I2C_SLVIF_RDREQ_Pos 4 //յжϱ־ +#define I2C_SLVIF_RDREQ_Msk (0x01 << I2C_SLVIF_RDREQ_Pos) +#define I2C_SLVIF_WRREQ_Pos 5 //յджϱ־ +#define I2C_SLVIF_WRREQ_Msk (0x01 << I2C_SLVIF_WRREQ_Pos) +#define I2C_SLVIF_ACTIVE_Pos 6 //slave Ч +#define I2C_SLVIF_ACTIVE_Msk (0x01 << I2C_SLVIF_ACTIVE_Pos) - __IO uint32_t START; - __IO uint32_t IE; - __IO uint32_t IF; - struct - { - __IO uint32_t STAT; - - __IO uint32_t DATA; - - uint32_t RESERVED[2]; - } CH[8]; - - __IO uint32_t CTRL1; - - __IO uint32_t CTRL2; - - uint32_t RESERVED[2]; - - __IO uint32_t CALIBSET; - - __IO uint32_t CALIBEN; +typedef struct { + __IO uint32_t CTRL; + + __IO uint32_t START; + + __IO uint32_t IE; + + __IO uint32_t IF; + + struct { + __IO uint32_t STAT; + + __IO uint32_t DATA; + + uint32_t RESERVED[2]; + } CH[8]; + + __IO uint32_t CTRL1; + + __IO uint32_t CTRL2; + + uint32_t RESERVED[2]; + + __IO uint32_t CALIBSET; + + __IO uint32_t CALIBEN; } ADC_TypeDef; -#define ADC_CTRL_CH0_Pos 0 //通道选中 -#define ADC_CTRL_CH0_Msk (0x01 << ADC_CTRL_CH0_Pos) -#define ADC_CTRL_CH1_Pos 1 -#define ADC_CTRL_CH1_Msk (0x01 << ADC_CTRL_CH1_Pos) -#define ADC_CTRL_CH2_Pos 2 -#define ADC_CTRL_CH2_Msk (0x01 << ADC_CTRL_CH2_Pos) -#define ADC_CTRL_CH3_Pos 3 -#define ADC_CTRL_CH3_Msk (0x01 << ADC_CTRL_CH3_Pos) -#define ADC_CTRL_CH4_Pos 4 -#define ADC_CTRL_CH4_Msk (0x01 << ADC_CTRL_CH4_Pos) -#define ADC_CTRL_CH5_Pos 5 -#define ADC_CTRL_CH5_Msk (0x01 << ADC_CTRL_CH5_Pos) -#define ADC_CTRL_CH6_Pos 6 -#define ADC_CTRL_CH6_Msk (0x01 << ADC_CTRL_CH6_Pos) -#define ADC_CTRL_CH7_Pos 7 -#define ADC_CTRL_CH7_Msk (0x01 << ADC_CTRL_CH7_Pos) -#define ADC_CTRL_AVG_Pos 8 //0 1次采样 1 2次采样取平均值 3 4次采样取平均值 7 8次采样取平均值 15 16次采样取平均值 -#define ADC_CTRL_AVG_Msk (0x0F << ADC_CTRL_AVG_Pos) -#define ADC_CTRL_EN_Pos 12 -#define ADC_CTRL_EN_Msk (0x01 << ADC_CTRL_EN_Pos) -#define ADC_CTRL_CONT_Pos 13 //Continuous conversion,只在软件启动模式下有效,0 单次转换,转换完成后START位自动清除停止转换 -#define ADC_CTRL_CONT_Msk (0x01 << ADC_CTRL_CONT_Pos) // 1 连续转换,启动后一直采样、转换,直到软件清除START位 -#define ADC_CTRL_TRIG_Pos 14 //转换触发方式:0 软件启动转换 1 PWM触发 -#define ADC_CTRL_TRIG_Msk (0x01 << ADC_CTRL_TRIG_Pos) -#define ADC_CTRL_CLKSRC_Pos 15 //0 VCO 1 HRC -#define ADC_CTRL_CLKSRC_Msk (0x01 << ADC_CTRL_CLKSRC_Pos) -#define ADC_CTRL_FIFOCLR_Pos 24 //[24] CH0_FIFO_CLR [25] CH1_FIFO_CLR ... [31] CH7_FIFO_CLR -#define ADC_CTRL_FIFOCLR_Msk (0xFFu << ADC_CTRL_FIFOCLR_Pos) -#define ADC_START_GO_Pos 0 //软件触发模式下,写1启动ADC采样和转换,在单次模式下转换完成后硬件自动清零,在扫描模式下必须软件写0停止ADC转换 -#define ADC_START_GO_Msk (0x01 << ADC_START_GO_Pos) -#define ADC_START_BUSY_Pos 4 -#define ADC_START_BUSY_Msk (0x01 << ADC_START_BUSY_Pos) +#define ADC_CTRL_CH0_Pos 0 //ͨѡ +#define ADC_CTRL_CH0_Msk (0x01 << ADC_CTRL_CH0_Pos) +#define ADC_CTRL_CH1_Pos 1 +#define ADC_CTRL_CH1_Msk (0x01 << ADC_CTRL_CH1_Pos) +#define ADC_CTRL_CH2_Pos 2 +#define ADC_CTRL_CH2_Msk (0x01 << ADC_CTRL_CH2_Pos) +#define ADC_CTRL_CH3_Pos 3 +#define ADC_CTRL_CH3_Msk (0x01 << ADC_CTRL_CH3_Pos) +#define ADC_CTRL_CH4_Pos 4 +#define ADC_CTRL_CH4_Msk (0x01 << ADC_CTRL_CH4_Pos) +#define ADC_CTRL_CH5_Pos 5 +#define ADC_CTRL_CH5_Msk (0x01 << ADC_CTRL_CH5_Pos) +#define ADC_CTRL_CH6_Pos 6 +#define ADC_CTRL_CH6_Msk (0x01 << ADC_CTRL_CH6_Pos) +#define ADC_CTRL_CH7_Pos 7 +#define ADC_CTRL_CH7_Msk (0x01 << ADC_CTRL_CH7_Pos) +#define ADC_CTRL_AVG_Pos 8 //0 1β 1 2βȡƽֵ 3 4βȡƽֵ 7 8βȡƽֵ 15 16βȡƽֵ +#define ADC_CTRL_AVG_Msk (0x0F << ADC_CTRL_AVG_Pos) +#define ADC_CTRL_EN_Pos 12 +#define ADC_CTRL_EN_Msk (0x01 << ADC_CTRL_EN_Pos) +#define ADC_CTRL_CONT_Pos 13 //Continuous conversionֻģʽЧ0 תתɺSTARTλԶֹͣת +#define ADC_CTRL_CONT_Msk (0x01 << ADC_CTRL_CONT_Pos) // 1 תһֱתֱSTARTλ +#define ADC_CTRL_TRIG_Pos 14 //תʽ0 ת 1 PWM +#define ADC_CTRL_TRIG_Msk (0x01 << ADC_CTRL_TRIG_Pos) +#define ADC_CTRL_CLKSRC_Pos 15 //0 VCO 1 HRC +#define ADC_CTRL_CLKSRC_Msk (0x01 << ADC_CTRL_CLKSRC_Pos) +#define ADC_CTRL_FIFOCLR_Pos 24 //[24] CH0_FIFO_CLR [25] CH1_FIFO_CLR ... [31] CH7_FIFO_CLR +#define ADC_CTRL_FIFOCLR_Msk (0xFFu<< ADC_CTRL_FIFOCLR_Pos) -#define ADC_IE_CH0EOC_Pos 0 //End Of Convertion -#define ADC_IE_CH0EOC_Msk (0x01 << ADC_IE_CH0EOC_Pos) -#define ADC_IE_CH0OVF_Pos 1 //Overflow -#define ADC_IE_CH0OVF_Msk (0x01 << ADC_IE_CH0OVF_Pos) -#define ADC_IE_CH0HFULL_Pos 2 //FIFO Half Full -#define ADC_IE_CH0HFULL_Msk (0x01 << ADC_IE_CH0HFULL_Pos) -#define ADC_IE_CH0FULL_Pos 3 //FIFO Full -#define ADC_IE_CH0FULL_Msk (0x01 << ADC_IE_CH0FULL_Pos) -#define ADC_IE_CH1EOC_Pos 4 -#define ADC_IE_CH1EOC_Msk (0x01 << ADC_IE_CH1EOC_Pos) -#define ADC_IE_CH1OVF_Pos 5 -#define ADC_IE_CH1OVF_Msk (0x01 << ADC_IE_CH1OVF_Pos) -#define ADC_IE_CH1HFULL_Pos 6 -#define ADC_IE_CH1HFULL_Msk (0x01 << ADC_IE_CH1HFULL_Pos) -#define ADC_IE_CH1FULL_Pos 7 -#define ADC_IE_CH1FULL_Msk (0x01 << ADC_IE_CH1FULL_Pos) -#define ADC_IE_CH2EOC_Pos 8 -#define ADC_IE_CH2EOC_Msk (0x01 << ADC_IE_CH2EOC_Pos) -#define ADC_IE_CH2OVF_Pos 9 -#define ADC_IE_CH2OVF_Msk (0x01 << ADC_IE_CH2OVF_Pos) -#define ADC_IE_CH2HFULL_Pos 10 -#define ADC_IE_CH2HFULL_Msk (0x01 << ADC_IE_CH2HFULL_Pos) -#define ADC_IE_CH2FULL_Pos 11 -#define ADC_IE_CH2FULL_Msk (0x01 << ADC_IE_CH2FULL_Pos) -#define ADC_IE_CH3EOC_Pos 12 -#define ADC_IE_CH3EOC_Msk (0x01 << ADC_IE_CH3EOC_Pos) -#define ADC_IE_CH3OVF_Pos 13 -#define ADC_IE_CH3OVF_Msk (0x01 << ADC_IE_CH3OVF_Pos) -#define ADC_IE_CH3HFULL_Pos 14 -#define ADC_IE_CH3HFULL_Msk (0x01 << ADC_IE_CH3HFULL_Pos) -#define ADC_IE_CH3FULL_Pos 15 -#define ADC_IE_CH3FULL_Msk (0x01 << ADC_IE_CH3FULL_Pos) -#define ADC_IE_CH4EOC_Pos 16 -#define ADC_IE_CH4EOC_Msk (0x01 << ADC_IE_CH4EOC_Pos) -#define ADC_IE_CH4OVF_Pos 17 -#define ADC_IE_CH4OVF_Msk (0x01 << ADC_IE_CH4OVF_Pos) -#define ADC_IE_CH4HFULL_Pos 18 -#define ADC_IE_CH4HFULL_Msk (0x01 << ADC_IE_CH4HFULL_Pos) -#define ADC_IE_CH4FULL_Pos 19 -#define ADC_IE_CH4FULL_Msk (0x01 << ADC_IE_CH4FULL_Pos) -#define ADC_IE_CH5EOC_Pos 20 -#define ADC_IE_CH5EOC_Msk (0x01 << ADC_IE_CH5EOC_Pos) -#define ADC_IE_CH5OVF_Pos 21 -#define ADC_IE_CH5OVF_Msk (0x01 << ADC_IE_CH5OVF_Pos) -#define ADC_IE_CH5HFULL_Pos 22 -#define ADC_IE_CH5HFULL_Msk (0x01 << ADC_IE_CH5HFULL_Pos) -#define ADC_IE_CH5FULL_Pos 23 -#define ADC_IE_CH5FULL_Msk (0x01 << ADC_IE_CH5FULL_Pos) -#define ADC_IE_CH6EOC_Pos 24 -#define ADC_IE_CH6EOC_Msk (0x01 << ADC_IE_CH6EOC_Pos) -#define ADC_IE_CH6OVF_Pos 25 -#define ADC_IE_CH6OVF_Msk (0x01 << ADC_IE_CH6OVF_Pos) -#define ADC_IE_CH6HFULL_Pos 26 -#define ADC_IE_CH6HFULL_Msk (0x01 << ADC_IE_CH6HFULL_Pos) -#define ADC_IE_CH6FULL_Pos 27 -#define ADC_IE_CH6FULL_Msk (0x01 << ADC_IE_CH6FULL_Pos) -#define ADC_IE_CH7EOC_Pos 28 -#define ADC_IE_CH7EOC_Msk (0x01 << ADC_IE_CH7EOC_Pos) -#define ADC_IE_CH7OVF_Pos 29 -#define ADC_IE_CH7OVF_Msk (0x01 << ADC_IE_CH7OVF_Pos) -#define ADC_IE_CH7HFULL_Pos 30 -#define ADC_IE_CH7HFULL_Msk (0x01 << ADC_IE_CH7HFULL_Pos) -#define ADC_IE_CH7FULL_Pos 31 -#define ADC_IE_CH7FULL_Msk (0x01u << ADC_IE_CH7FULL_Pos) +#define ADC_START_GO_Pos 0 //ģʽ£д1ADCתڵģʽתɺӲԶ㣬ɨģʽ±д0ֹͣADCת +#define ADC_START_GO_Msk (0x01 << ADC_START_GO_Pos) +#define ADC_START_BUSY_Pos 4 +#define ADC_START_BUSY_Msk (0x01 << ADC_START_BUSY_Pos) -#define ADC_IF_CH0EOC_Pos 0 //写1清零 -#define ADC_IF_CH0EOC_Msk (0x01 << ADC_IF_CH0EOC_Pos) -#define ADC_IF_CH0OVF_Pos 1 //写1清零 -#define ADC_IF_CH0OVF_Msk (0x01 << ADC_IF_CH0OVF_Pos) -#define ADC_IF_CH0HFULL_Pos 2 //写1清零 -#define ADC_IF_CH0HFULL_Msk (0x01 << ADC_IF_CH0HFULL_Pos) -#define ADC_IF_CH0FULL_Pos 3 //写1清零 -#define ADC_IF_CH0FULL_Msk (0x01 << ADC_IF_CH0FULL_Pos) -#define ADC_IF_CH1EOC_Pos 4 -#define ADC_IF_CH1EOC_Msk (0x01 << ADC_IF_CH1EOC_Pos) -#define ADC_IF_CH1OVF_Pos 5 -#define ADC_IF_CH1OVF_Msk (0x01 << ADC_IF_CH1OVF_Pos) -#define ADC_IF_CH1HFULL_Pos 6 -#define ADC_IF_CH1HFULL_Msk (0x01 << ADC_IF_CH1HFULL_Pos) -#define ADC_IF_CH1FULL_Pos 7 -#define ADC_IF_CH1FULL_Msk (0x01 << ADC_IF_CH1FULL_Pos) -#define ADC_IF_CH2EOC_Pos 8 -#define ADC_IF_CH2EOC_Msk (0x01 << ADC_IF_CH2EOC_Pos) -#define ADC_IF_CH2OVF_Pos 9 -#define ADC_IF_CH2OVF_Msk (0x01 << ADC_IF_CH2OVF_Pos) -#define ADC_IF_CH2HFULL_Pos 10 -#define ADC_IF_CH2HFULL_Msk (0x01 << ADC_IF_CH2HFULL_Pos) -#define ADC_IF_CH2FULL_Pos 11 -#define ADC_IF_CH2FULL_Msk (0x01 << ADC_IF_CH2FULL_Pos) -#define ADC_IF_CH3EOC_Pos 12 -#define ADC_IF_CH3EOC_Msk (0x01 << ADC_IF_CH3EOC_Pos) -#define ADC_IF_CH3OVF_Pos 13 -#define ADC_IF_CH3OVF_Msk (0x01 << ADC_IF_CH3OVF_Pos) -#define ADC_IF_CH3HFULL_Pos 14 -#define ADC_IF_CH3HFULL_Msk (0x01 << ADC_IF_CH3HFULL_Pos) -#define ADC_IF_CH3FULL_Pos 15 -#define ADC_IF_CH3FULL_Msk (0x01 << ADC_IF_CH3FULL_Pos) -#define ADC_IF_CH4EOC_Pos 16 -#define ADC_IF_CH4EOC_Msk (0x01 << ADC_IF_CH4EOC_Pos) -#define ADC_IF_CH4OVF_Pos 17 -#define ADC_IF_CH4OVF_Msk (0x01 << ADC_IF_CH4OVF_Pos) -#define ADC_IF_CH4HFULL_Pos 18 -#define ADC_IF_CH4HFULL_Msk (0x01 << ADC_IF_CH4HFULL_Pos) -#define ADC_IF_CH4FULL_Pos 19 -#define ADC_IF_CH4FULL_Msk (0x01 << ADC_IF_CH4FULL_Pos) -#define ADC_IF_CH5EOC_Pos 20 -#define ADC_IF_CH5EOC_Msk (0x01 << ADC_IF_CH5EOC_Pos) -#define ADC_IF_CH5OVF_Pos 21 -#define ADC_IF_CH5OVF_Msk (0x01 << ADC_IF_CH5OVF_Pos) -#define ADC_IF_CH5HFULL_Pos 22 -#define ADC_IF_CH5HFULL_Msk (0x01 << ADC_IF_CH5HFULL_Pos) -#define ADC_IF_CH5FULL_Pos 23 -#define ADC_IF_CH5FULL_Msk (0x01 << ADC_IF_CH5FULL_Pos) -#define ADC_IF_CH6EOC_Pos 24 -#define ADC_IF_CH6EOC_Msk (0x01 << ADC_IF_CH6EOC_Pos) -#define ADC_IF_CH6OVF_Pos 25 -#define ADC_IF_CH6OVF_Msk (0x01 << ADC_IF_CH6OVF_Pos) -#define ADC_IF_CH6HFULL_Pos 26 -#define ADC_IF_CH6HFULL_Msk (0x01 << ADC_IF_CH6HFULL_Pos) -#define ADC_IF_CH6FULL_Pos 27 -#define ADC_IF_CH6FULL_Msk (0x01 << ADC_IF_CH6FULL_Pos) -#define ADC_IF_CH7EOC_Pos 28 -#define ADC_IF_CH7EOC_Msk (0x01 << ADC_IF_CH7EOC_Pos) -#define ADC_IF_CH7OVF_Pos 29 -#define ADC_IF_CH7OVF_Msk (0x01 << ADC_IF_CH7OVF_Pos) -#define ADC_IF_CH7HFULL_Pos 30 -#define ADC_IF_CH7HFULL_Msk (0x01 << ADC_IF_CH7HFULL_Pos) -#define ADC_IF_CH7FULL_Pos 31 -#define ADC_IF_CH7FULL_Msk (0x01 << ADC_IF_CH7FULL_Pos) +#define ADC_IE_CH0EOC_Pos 0 //End Of Convertion +#define ADC_IE_CH0EOC_Msk (0x01 << ADC_IE_CH0EOC_Pos) +#define ADC_IE_CH0OVF_Pos 1 //Overflow +#define ADC_IE_CH0OVF_Msk (0x01 << ADC_IE_CH0OVF_Pos) +#define ADC_IE_CH0HFULL_Pos 2 //FIFO Half Full +#define ADC_IE_CH0HFULL_Msk (0x01 << ADC_IE_CH0HFULL_Pos) +#define ADC_IE_CH0FULL_Pos 3 //FIFO Full +#define ADC_IE_CH0FULL_Msk (0x01 << ADC_IE_CH0FULL_Pos) +#define ADC_IE_CH1EOC_Pos 4 +#define ADC_IE_CH1EOC_Msk (0x01 << ADC_IE_CH1EOC_Pos) +#define ADC_IE_CH1OVF_Pos 5 +#define ADC_IE_CH1OVF_Msk (0x01 << ADC_IE_CH1OVF_Pos) +#define ADC_IE_CH1HFULL_Pos 6 +#define ADC_IE_CH1HFULL_Msk (0x01 << ADC_IE_CH1HFULL_Pos) +#define ADC_IE_CH1FULL_Pos 7 +#define ADC_IE_CH1FULL_Msk (0x01 << ADC_IE_CH1FULL_Pos) +#define ADC_IE_CH2EOC_Pos 8 +#define ADC_IE_CH2EOC_Msk (0x01 << ADC_IE_CH2EOC_Pos) +#define ADC_IE_CH2OVF_Pos 9 +#define ADC_IE_CH2OVF_Msk (0x01 << ADC_IE_CH2OVF_Pos) +#define ADC_IE_CH2HFULL_Pos 10 +#define ADC_IE_CH2HFULL_Msk (0x01 << ADC_IE_CH2HFULL_Pos) +#define ADC_IE_CH2FULL_Pos 11 +#define ADC_IE_CH2FULL_Msk (0x01 << ADC_IE_CH2FULL_Pos) +#define ADC_IE_CH3EOC_Pos 12 +#define ADC_IE_CH3EOC_Msk (0x01 << ADC_IE_CH3EOC_Pos) +#define ADC_IE_CH3OVF_Pos 13 +#define ADC_IE_CH3OVF_Msk (0x01 << ADC_IE_CH3OVF_Pos) +#define ADC_IE_CH3HFULL_Pos 14 +#define ADC_IE_CH3HFULL_Msk (0x01 << ADC_IE_CH3HFULL_Pos) +#define ADC_IE_CH3FULL_Pos 15 +#define ADC_IE_CH3FULL_Msk (0x01 << ADC_IE_CH3FULL_Pos) +#define ADC_IE_CH4EOC_Pos 16 +#define ADC_IE_CH4EOC_Msk (0x01 << ADC_IE_CH4EOC_Pos) +#define ADC_IE_CH4OVF_Pos 17 +#define ADC_IE_CH4OVF_Msk (0x01 << ADC_IE_CH4OVF_Pos) +#define ADC_IE_CH4HFULL_Pos 18 +#define ADC_IE_CH4HFULL_Msk (0x01 << ADC_IE_CH4HFULL_Pos) +#define ADC_IE_CH4FULL_Pos 19 +#define ADC_IE_CH4FULL_Msk (0x01 << ADC_IE_CH4FULL_Pos) +#define ADC_IE_CH5EOC_Pos 20 +#define ADC_IE_CH5EOC_Msk (0x01 << ADC_IE_CH5EOC_Pos) +#define ADC_IE_CH5OVF_Pos 21 +#define ADC_IE_CH5OVF_Msk (0x01 << ADC_IE_CH5OVF_Pos) +#define ADC_IE_CH5HFULL_Pos 22 +#define ADC_IE_CH5HFULL_Msk (0x01 << ADC_IE_CH5HFULL_Pos) +#define ADC_IE_CH5FULL_Pos 23 +#define ADC_IE_CH5FULL_Msk (0x01 << ADC_IE_CH5FULL_Pos) +#define ADC_IE_CH6EOC_Pos 24 +#define ADC_IE_CH6EOC_Msk (0x01 << ADC_IE_CH6EOC_Pos) +#define ADC_IE_CH6OVF_Pos 25 +#define ADC_IE_CH6OVF_Msk (0x01 << ADC_IE_CH6OVF_Pos) +#define ADC_IE_CH6HFULL_Pos 26 +#define ADC_IE_CH6HFULL_Msk (0x01 << ADC_IE_CH6HFULL_Pos) +#define ADC_IE_CH6FULL_Pos 27 +#define ADC_IE_CH6FULL_Msk (0x01 << ADC_IE_CH6FULL_Pos) +#define ADC_IE_CH7EOC_Pos 28 +#define ADC_IE_CH7EOC_Msk (0x01 << ADC_IE_CH7EOC_Pos) +#define ADC_IE_CH7OVF_Pos 29 +#define ADC_IE_CH7OVF_Msk (0x01 << ADC_IE_CH7OVF_Pos) +#define ADC_IE_CH7HFULL_Pos 30 +#define ADC_IE_CH7HFULL_Msk (0x01 << ADC_IE_CH7HFULL_Pos) +#define ADC_IE_CH7FULL_Pos 31 +#define ADC_IE_CH7FULL_Msk (0x01u<< ADC_IE_CH7FULL_Pos) -#define ADC_STAT_EOC_Pos 0 //写1清零 -#define ADC_STAT_EOC_Msk (0x01 << ADC_STAT_EOC_Pos) -#define ADC_STAT_OVF_Pos 1 //读数据寄存器清除 -#define ADC_STAT_OVF_Msk (0x01 << ADC_STAT_OVF_Pos) -#define ADC_STAT_HFULL_Pos 2 -#define ADC_STAT_HFULL_Msk (0x01 << ADC_STAT_HFULL_Pos) -#define ADC_STAT_FULL_Pos 3 -#define ADC_STAT_FULL_Msk (0x01 << ADC_STAT_FULL_Pos) -#define ADC_STAT_EMPTY_Pos 4 -#define ADC_STAT_EMPTY_Msk (0x01 << ADC_STAT_EMPTY_Pos) +#define ADC_IF_CH0EOC_Pos 0 //д1 +#define ADC_IF_CH0EOC_Msk (0x01 << ADC_IF_CH0EOC_Pos) +#define ADC_IF_CH0OVF_Pos 1 //д1 +#define ADC_IF_CH0OVF_Msk (0x01 << ADC_IF_CH0OVF_Pos) +#define ADC_IF_CH0HFULL_Pos 2 //д1 +#define ADC_IF_CH0HFULL_Msk (0x01 << ADC_IF_CH0HFULL_Pos) +#define ADC_IF_CH0FULL_Pos 3 //д1 +#define ADC_IF_CH0FULL_Msk (0x01 << ADC_IF_CH0FULL_Pos) +#define ADC_IF_CH1EOC_Pos 4 +#define ADC_IF_CH1EOC_Msk (0x01 << ADC_IF_CH1EOC_Pos) +#define ADC_IF_CH1OVF_Pos 5 +#define ADC_IF_CH1OVF_Msk (0x01 << ADC_IF_CH1OVF_Pos) +#define ADC_IF_CH1HFULL_Pos 6 +#define ADC_IF_CH1HFULL_Msk (0x01 << ADC_IF_CH1HFULL_Pos) +#define ADC_IF_CH1FULL_Pos 7 +#define ADC_IF_CH1FULL_Msk (0x01 << ADC_IF_CH1FULL_Pos) +#define ADC_IF_CH2EOC_Pos 8 +#define ADC_IF_CH2EOC_Msk (0x01 << ADC_IF_CH2EOC_Pos) +#define ADC_IF_CH2OVF_Pos 9 +#define ADC_IF_CH2OVF_Msk (0x01 << ADC_IF_CH2OVF_Pos) +#define ADC_IF_CH2HFULL_Pos 10 +#define ADC_IF_CH2HFULL_Msk (0x01 << ADC_IF_CH2HFULL_Pos) +#define ADC_IF_CH2FULL_Pos 11 +#define ADC_IF_CH2FULL_Msk (0x01 << ADC_IF_CH2FULL_Pos) +#define ADC_IF_CH3EOC_Pos 12 +#define ADC_IF_CH3EOC_Msk (0x01 << ADC_IF_CH3EOC_Pos) +#define ADC_IF_CH3OVF_Pos 13 +#define ADC_IF_CH3OVF_Msk (0x01 << ADC_IF_CH3OVF_Pos) +#define ADC_IF_CH3HFULL_Pos 14 +#define ADC_IF_CH3HFULL_Msk (0x01 << ADC_IF_CH3HFULL_Pos) +#define ADC_IF_CH3FULL_Pos 15 +#define ADC_IF_CH3FULL_Msk (0x01 << ADC_IF_CH3FULL_Pos) +#define ADC_IF_CH4EOC_Pos 16 +#define ADC_IF_CH4EOC_Msk (0x01 << ADC_IF_CH4EOC_Pos) +#define ADC_IF_CH4OVF_Pos 17 +#define ADC_IF_CH4OVF_Msk (0x01 << ADC_IF_CH4OVF_Pos) +#define ADC_IF_CH4HFULL_Pos 18 +#define ADC_IF_CH4HFULL_Msk (0x01 << ADC_IF_CH4HFULL_Pos) +#define ADC_IF_CH4FULL_Pos 19 +#define ADC_IF_CH4FULL_Msk (0x01 << ADC_IF_CH4FULL_Pos) +#define ADC_IF_CH5EOC_Pos 20 +#define ADC_IF_CH5EOC_Msk (0x01 << ADC_IF_CH5EOC_Pos) +#define ADC_IF_CH5OVF_Pos 21 +#define ADC_IF_CH5OVF_Msk (0x01 << ADC_IF_CH5OVF_Pos) +#define ADC_IF_CH5HFULL_Pos 22 +#define ADC_IF_CH5HFULL_Msk (0x01 << ADC_IF_CH5HFULL_Pos) +#define ADC_IF_CH5FULL_Pos 23 +#define ADC_IF_CH5FULL_Msk (0x01 << ADC_IF_CH5FULL_Pos) +#define ADC_IF_CH6EOC_Pos 24 +#define ADC_IF_CH6EOC_Msk (0x01 << ADC_IF_CH6EOC_Pos) +#define ADC_IF_CH6OVF_Pos 25 +#define ADC_IF_CH6OVF_Msk (0x01 << ADC_IF_CH6OVF_Pos) +#define ADC_IF_CH6HFULL_Pos 26 +#define ADC_IF_CH6HFULL_Msk (0x01 << ADC_IF_CH6HFULL_Pos) +#define ADC_IF_CH6FULL_Pos 27 +#define ADC_IF_CH6FULL_Msk (0x01 << ADC_IF_CH6FULL_Pos) +#define ADC_IF_CH7EOC_Pos 28 +#define ADC_IF_CH7EOC_Msk (0x01 << ADC_IF_CH7EOC_Pos) +#define ADC_IF_CH7OVF_Pos 29 +#define ADC_IF_CH7OVF_Msk (0x01 << ADC_IF_CH7OVF_Pos) +#define ADC_IF_CH7HFULL_Pos 30 +#define ADC_IF_CH7HFULL_Msk (0x01 << ADC_IF_CH7HFULL_Pos) +#define ADC_IF_CH7FULL_Pos 31 +#define ADC_IF_CH7FULL_Msk (0x01 << ADC_IF_CH7FULL_Pos) -#define ADC_CTRL1_RIN_Pos 4 //输入阻抗:0 无穷大 1 105K 2 90K 3 75K 4 60K 5 45K 6 30K 7 15K -#define ADC_CTRL1_RIN_Msk (0x07 << ADC_CTRL1_RIN_Pos) +#define ADC_STAT_EOC_Pos 0 //д1 +#define ADC_STAT_EOC_Msk (0x01 << ADC_STAT_EOC_Pos) +#define ADC_STAT_OVF_Pos 1 //ݼĴ +#define ADC_STAT_OVF_Msk (0x01 << ADC_STAT_OVF_Pos) +#define ADC_STAT_HFULL_Pos 2 +#define ADC_STAT_HFULL_Msk (0x01 << ADC_STAT_HFULL_Pos) +#define ADC_STAT_FULL_Pos 3 +#define ADC_STAT_FULL_Msk (0x01 << ADC_STAT_FULL_Pos) +#define ADC_STAT_EMPTY_Pos 4 +#define ADC_STAT_EMPTY_Msk (0x01 << ADC_STAT_EMPTY_Pos) -#define ADC_CTRL2_RESET_Pos 0 //数字电路复位 -#define ADC_CTRL2_RESET_Msk (0x01 << ADC_CTRL2_RESET_Pos) -#define ADC_CTRL2_ADCEVCM_Pos 1 //ADC External VCM,ADC与PGA输出共模电平选择 -#define ADC_CTRL2_ADCEVCM_Msk (0x01 << ADC_CTRL2_ADCEVCM_Pos) -#define ADC_CTRL2_PGAIVCM_Pos 2 //PGA Internal VCM,PGA输入共模电平选择 -#define ADC_CTRL2_PGAIVCM_Msk (0x01 << ADC_CTRL2_PGAIVCM_Pos) -#define ADC_CTRL2_PGAGAIN_Pos 3 //0 25.1dB 1 21.6dB 2 11.1dB 3 3.5dB 4 0dB(1.8V) 5 -2.9dB 6 -5.3dB -#define ADC_CTRL2_PGAGAIN_Msk (0x07 << ADC_CTRL2_PGAGAIN_Pos) -#define ADC_CTRL2_REFPOUT_Pos 23 //1 ADC 内部 1.2V REFP电压输出到外部REFP引脚,用于测量,或在需要1.2V外部REFP时节省成本 +#define ADC_CTRL1_RIN_Pos 4 //迹0 1 105K 2 90K 3 75K 4 60K 5 45K 6 30K 7 15K +#define ADC_CTRL1_RIN_Msk (0x07 << ADC_CTRL1_RIN_Pos) + +#define ADC_CTRL2_RESET_Pos 0 //ֵ·λ +#define ADC_CTRL2_RESET_Msk (0x01 << ADC_CTRL2_RESET_Pos) +#define ADC_CTRL2_ADCEVCM_Pos 1 //ADC External VCMADCPGAģƽѡ +#define ADC_CTRL2_ADCEVCM_Msk (0x01 << ADC_CTRL2_ADCEVCM_Pos) +#define ADC_CTRL2_PGAIVCM_Pos 2 //PGA Internal VCMPGA빲ģƽѡ +#define ADC_CTRL2_PGAIVCM_Msk (0x01 << ADC_CTRL2_PGAIVCM_Pos) +#define ADC_CTRL2_PGAGAIN_Pos 3 //0 25.1dB 1 21.6dB 2 11.1dB 3 3.5dB 4 0dB(1.8V) 5 -2.9dB 6 -5.3dB +#define ADC_CTRL2_PGAGAIN_Msk (0x07 << ADC_CTRL2_PGAGAIN_Pos) +#define ADC_CTRL2_REFPOUT_Pos 23 //1 ADC ڲ 1.2V REFPѹⲿREFPţڲҪ1.2VⲿREFPʱʡɱ #define ADC_CTRL2_REFPOUT_Msk (0x01 << ADC_CTRL2_REFPOUT_Pos -#define ADC_CTRL2_CLKDIV_Pos 24 //时钟分频,只在时钟源为HRC时有效 -#define ADC_CTRL2_CLKDIV_Msk (0x1F << ADC_CTRL2_CLKDIV_Pos) -#define ADC_CTRL2_PGAVCM_Pos 29 -#define ADC_CTRL2_PGAVCM_Msk (0x07u << ADC_CTRL2_PGAVCM_Pos) +#define ADC_CTRL2_CLKDIV_Pos 24 //ʱӷƵֻʱԴΪHRCʱЧ +#define ADC_CTRL2_CLKDIV_Msk (0x1F << ADC_CTRL2_CLKDIV_Pos) +#define ADC_CTRL2_PGAVCM_Pos 29 +#define ADC_CTRL2_PGAVCM_Msk (0x07u<< ADC_CTRL2_PGAVCM_Pos) -#define ADC_CALIBSET_OFFSET_Pos 0 -#define ADC_CALIBSET_OFFSET_Msk (0x1FF << ADC_CALIBSET_OFFSET_Pos) -#define ADC_CALIBSET_K_Pos 16 -#define ADC_CALIBSET_K_Msk (0x1FF << ADC_CALIBSET_K_Pos) +#define ADC_CALIBSET_OFFSET_Pos 0 +#define ADC_CALIBSET_OFFSET_Msk (0x1FF<< ADC_CALIBSET_OFFSET_Pos) +#define ADC_CALIBSET_K_Pos 16 +#define ADC_CALIBSET_K_Msk (0x1FF<< ADC_CALIBSET_K_Pos) -#define ADC_CALIBEN_OFFSET_Pos 0 -#define ADC_CALIBEN_OFFSET_Msk (0x01 << ADC_CALIBEN_OFFSET_Pos) -#define ADC_CALIBEN_K_Pos 1 -#define ADC_CALIBEN_K_Msk (0x01 << ADC_CALIBEN_K_Pos) +#define ADC_CALIBEN_OFFSET_Pos 0 +#define ADC_CALIBEN_OFFSET_Msk (0x01 << ADC_CALIBEN_OFFSET_Pos) +#define ADC_CALIBEN_K_Pos 1 +#define ADC_CALIBEN_K_Msk (0x01 << ADC_CALIBEN_K_Pos) -typedef struct -{ - __IO uint32_t MODE; //0 普通模式,A、B两路输出互相独立 - //1 互补模式,A、B两路输出都由PERA、HIGHA控制,B路输出与A路输出极性相反,且DZA、DZB控制A、B路输出上升沿推迟时间 - //2 单次模式,同普通模式,但一个周期后自动停止 - //3 对称模式,A、B两路输出互相独立,以两个计数周期产生一个波形输出周期,分辨率提升一倍、频率降低一倍 - //4 对称互补模式,对称模式和互补模式的综合 - __IO uint32_t PERA; //[15:0] 周期 - __IO uint32_t HIGHA; //[15:0] 高电平持续时长 - __IO uint32_t DZA; //[9:0] 死区,即上升沿推迟时长,必须小于HIGHA - - __IO uint32_t PERB; - - __IO uint32_t HIGHB; - - __IO uint32_t DZB; - - __IO uint32_t INIOUT; //Init Output level,初始输出电平 +typedef struct { + __IO uint32_t MODE; //0 ͨģʽAB· + //1 ģʽAB·PERAHIGHAƣB·A·෴DZADZBAB·Ƴʱ + //2 ģʽͬͨģʽһںԶֹͣ + //3 ԳģʽAB·ڲһڣֱһƵʽһ + //4 ԳƻģʽԳģʽͻģʽۺ + + __IO uint32_t PERA; //[15:0] + + __IO uint32_t HIGHA; //[15:0] ߵƽʱ + + __IO uint32_t DZA; //[9:0] ƳʱСHIGHA + + __IO uint32_t PERB; + + __IO uint32_t HIGHB; + + __IO uint32_t DZB; + + __IO uint32_t INIOUT; //Init Output levelʼƽ } PWM_TypeDef; -#define PWM_INIOUT_PWMA_Pos 0 -#define PWM_INIOUT_PWMA_Msk (0x01 << PWM_INIOUT_PWMA_Pos) -#define PWM_INIOUT_PWMB_Pos 1 -#define PWM_INIOUT_PWMB_Msk (0x01 << PWM_INIOUT_PWMB_Pos) -typedef struct -{ - __IO uint32_t FORCEH; +#define PWM_INIOUT_PWMA_Pos 0 +#define PWM_INIOUT_PWMA_Msk (0x01 << PWM_INIOUT_PWMA_Pos) +#define PWM_INIOUT_PWMB_Pos 1 +#define PWM_INIOUT_PWMB_Msk (0x01 << PWM_INIOUT_PWMB_Pos) + +typedef struct { + __IO uint32_t FORCEH; + __IO uint32_t ADTRG0A; __IO uint32_t ADTRG0B; - + __IO uint32_t ADTRG1A; __IO uint32_t ADTRG1B; - + __IO uint32_t ADTRG2A; __IO uint32_t ADTRG2B; - + __IO uint32_t ADTRG3A; __IO uint32_t ADTRG3B; - + __IO uint32_t ADTRG4A; __IO uint32_t ADTRG4B; - + __IO uint32_t ADTRG5A; - __IO uint32_t ADTRG5B; - - uint32_t RESERVED[3]; - - __IO uint32_t HALT; //刹车控制 - - __IO uint32_t CHEN; - - __IO uint32_t IE; - - __IO uint32_t IF; - - __IO uint32_t IM; //Interrupt Mask - - __IO uint32_t IRS; //Interrupt Raw Stat + __IO uint32_t ADTRG5B; + + uint32_t RESERVED[3]; + + __IO uint32_t HALT; //ɲ + + __IO uint32_t CHEN; + + __IO uint32_t IE; + + __IO uint32_t IF; + + __IO uint32_t IM; //Interrupt Mask + + __IO uint32_t IRS; //Interrupt Raw Stat } PWMG_TypeDef; -#define PWMG_FORCEH_PWM0_Pos 0 -#define PWMG_FORCEH_PWM0_Msk (0x01 << PWMG_FORCEH_PWM0_Pos) -#define PWMG_FORCEH_PWM1_Pos 1 -#define PWMG_FORCEH_PWM1_Msk (0x01 << PWMG_FORCEH_PWM1_Pos) -#define PWMG_FORCEH_PWM2_Pos 2 -#define PWMG_FORCEH_PWM2_Msk (0x01 << PWMG_FORCEH_PWM2_Pos) -#define PWMG_FORCEH_PWM3_Pos 3 -#define PWMG_FORCEH_PWM3_Msk (0x01 << PWMG_FORCEH_PWM3_Pos) -#define PWMG_FORCEH_PWM4_Pos 4 -#define PWMG_FORCEH_PWM4_Msk (0x01 << PWMG_FORCEH_PWM4_Pos) -#define PWMG_FORCEH_PWM5_Pos 5 -#define PWMG_FORCEH_PWM5_Msk (0x01 << PWMG_FORCEH_PWM5_Pos) -#define PWMG_ADTRG_VALUE_Pos 0 -#define PWMG_ADTRG_VALUE_Msk (0xFFFF << PWMG_ADTRG0A_VALUE_Pos) -#define PWMG_ADTRG_EVEN_Pos 16 //1 偶数周期生效 0 奇数周期生效 -#define PWMG_ADTRG_EVEN_Msk (0x01 << PWMG_ADTRG0A_EVEN_Pos) -#define PWMG_ADTRG_EN_Pos 17 -#define PWMG_ADTRG_EN_Msk (0x01 << PWMG_ADTRG0A_EN_Pos) +#define PWMG_FORCEH_PWM0_Pos 0 +#define PWMG_FORCEH_PWM0_Msk (0x01 << PWMG_FORCEH_PWM0_Pos) +#define PWMG_FORCEH_PWM1_Pos 1 +#define PWMG_FORCEH_PWM1_Msk (0x01 << PWMG_FORCEH_PWM1_Pos) +#define PWMG_FORCEH_PWM2_Pos 2 +#define PWMG_FORCEH_PWM2_Msk (0x01 << PWMG_FORCEH_PWM2_Pos) +#define PWMG_FORCEH_PWM3_Pos 3 +#define PWMG_FORCEH_PWM3_Msk (0x01 << PWMG_FORCEH_PWM3_Pos) +#define PWMG_FORCEH_PWM4_Pos 4 +#define PWMG_FORCEH_PWM4_Msk (0x01 << PWMG_FORCEH_PWM4_Pos) +#define PWMG_FORCEH_PWM5_Pos 5 +#define PWMG_FORCEH_PWM5_Msk (0x01 << PWMG_FORCEH_PWM5_Pos) -#define PWMG_HALT_EN_Pos 0 -#define PWMG_HALT_EN_Msk (0x01 << PWMG_HALT_EN_Pos) -#define PWMG_HALT_PWM0_Pos 1 -#define PWMG_HALT_PWM0_Msk (0x01 << PWMG_HALT_PWM0_Pos) -#define PWMG_HALT_PWM1_Pos 2 -#define PWMG_HALT_PWM1_Msk (0x01 << PWMG_HALT_PWM1_Pos) -#define PWMG_HALT_PWM2_Pos 3 -#define PWMG_HALT_PWM2_Msk (0x01 << PWMG_HALT_PWM2_Pos) -#define PWMG_HALT_PWM3_Pos 4 -#define PWMG_HALT_PWM3_Msk (0x01 << PWMG_HALT_PWM3_Pos) -#define PWMG_HALT_PWM4_Pos 5 -#define PWMG_HALT_PWM4_Msk (0x01 << PWMG_HALT_PWM4_Pos) -#define PWMG_HALT_PWM5_Pos 6 -#define PWMG_HALT_PWM5_Msk (0x01 << PWMG_HALT_PWM5_Pos) -#define PWMG_HALT_STOPCNT_Pos 7 //1 刹车时将PWM计数器清零,停止计数 0 刹车时,PWM计数器继续计数 -#define PWMG_HALT_STOPCNT_Msk (0x01 << PWMG_HALT_STOPCNT_Pos) -#define PWMG_HALT_INLVL_Pos 8 //1 刹车输入高电平有效 -#define PWMG_HALT_INLVL_Msk (0x01 << PWMG_HALT_INLVL_Pos) -#define PWMG_HALT_OUTLVL_Pos 9 //1 刹车过程中输出高电平 -#define PWMG_HALT_OUTLVL_Msk (0x01 << PWMG_HALT_OUTLVL_Pos) -#define PWMG_HALT_STAT_Pos 10 //1 正在刹车 -#define PWMG_HALT_STAT_Msk (0x01 << PWMG_HALT_STAT_Pos) +#define PWMG_ADTRG_VALUE_Pos 0 +#define PWMG_ADTRG_VALUE_Msk (0xFFFF << PWMG_ADTRG0A_VALUE_Pos) +#define PWMG_ADTRG_EVEN_Pos 16 //1 żЧ 0 Ч +#define PWMG_ADTRG_EVEN_Msk (0x01 << PWMG_ADTRG0A_EVEN_Pos) +#define PWMG_ADTRG_EN_Pos 17 +#define PWMG_ADTRG_EN_Msk (0x01 << PWMG_ADTRG0A_EN_Pos) -#define PWMG_CHEN_PWM0A_Pos 0 -#define PWMG_CHEN_PWM0A_Msk (0x01 << PWMG_CHEN_PWM0A_Pos) -#define PWMG_CHEN_PWM0B_Pos 1 -#define PWMG_CHEN_PWM0B_Msk (0x01 << PWMG_CHEN_PWM0B_Pos) -#define PWMG_CHEN_PWM1A_Pos 2 -#define PWMG_CHEN_PWM1A_Msk (0x01 << PWMG_CHEN_PWM1A_Pos) -#define PWMG_CHEN_PWM1B_Pos 3 -#define PWMG_CHEN_PWM1B_Msk (0x01 << PWMG_CHEN_PWM1B_Pos) -#define PWMG_CHEN_PWM2A_Pos 4 -#define PWMG_CHEN_PWM2A_Msk (0x01 << PWMG_CHEN_PWM2A_Pos) -#define PWMG_CHEN_PWM2B_Pos 5 -#define PWMG_CHEN_PWM2B_Msk (0x01 << PWMG_CHEN_PWM2B_Pos) -#define PWMG_CHEN_PWM3A_Pos 6 -#define PWMG_CHEN_PWM3A_Msk (0x01 << PWMG_CHEN_PWM3A_Pos) -#define PWMG_CHEN_PWM3B_Pos 7 -#define PWMG_CHEN_PWM3B_Msk (0x01 << PWMG_CHEN_PWM3B_Pos) -#define PWMG_CHEN_PWM4A_Pos 8 -#define PWMG_CHEN_PWM4A_Msk (0x01 << PWMG_CHEN_PWM4A_Pos) -#define PWMG_CHEN_PWM4B_Pos 9 -#define PWMG_CHEN_PWM4B_Msk (0x01 << PWMG_CHEN_PWM4B_Pos) -#define PWMG_CHEN_PWM5A_Pos 10 -#define PWMG_CHEN_PWM5A_Msk (0x01 << PWMG_CHEN_PWM5A_Pos) -#define PWMG_CHEN_PWM5B_Pos 11 -#define PWMG_CHEN_PWM5B_Msk (0x01 << PWMG_CHEN_PWM5B_Pos) +#define PWMG_HALT_EN_Pos 0 +#define PWMG_HALT_EN_Msk (0x01 << PWMG_HALT_EN_Pos) +#define PWMG_HALT_PWM0_Pos 1 +#define PWMG_HALT_PWM0_Msk (0x01 << PWMG_HALT_PWM0_Pos) +#define PWMG_HALT_PWM1_Pos 2 +#define PWMG_HALT_PWM1_Msk (0x01 << PWMG_HALT_PWM1_Pos) +#define PWMG_HALT_PWM2_Pos 3 +#define PWMG_HALT_PWM2_Msk (0x01 << PWMG_HALT_PWM2_Pos) +#define PWMG_HALT_PWM3_Pos 4 +#define PWMG_HALT_PWM3_Msk (0x01 << PWMG_HALT_PWM3_Pos) +#define PWMG_HALT_PWM4_Pos 5 +#define PWMG_HALT_PWM4_Msk (0x01 << PWMG_HALT_PWM4_Pos) +#define PWMG_HALT_PWM5_Pos 6 +#define PWMG_HALT_PWM5_Msk (0x01 << PWMG_HALT_PWM5_Pos) +#define PWMG_HALT_STOPCNT_Pos 7 //1 ɲʱPWM㣬ֹͣ 0 ɲʱPWM +#define PWMG_HALT_STOPCNT_Msk (0x01 << PWMG_HALT_STOPCNT_Pos) +#define PWMG_HALT_INLVL_Pos 8 //1 ɲߵƽЧ +#define PWMG_HALT_INLVL_Msk (0x01 << PWMG_HALT_INLVL_Pos) +#define PWMG_HALT_OUTLVL_Pos 9 //1 ɲߵƽ +#define PWMG_HALT_OUTLVL_Msk (0x01 << PWMG_HALT_OUTLVL_Pos) +#define PWMG_HALT_STAT_Pos 10 //1 ɲ +#define PWMG_HALT_STAT_Msk (0x01 << PWMG_HALT_STAT_Pos) -#define PWMG_IE_NEWP0A_Pos 0 -#define PWMG_IE_NEWP0A_Msk (0x01 << PWMG_IE_NEWP0A_Pos) -#define PWMG_IE_NEWP0B_Pos 1 -#define PWMG_IE_NEWP0B_Msk (0x01 << PWMG_IE_NEWP0B_Pos) -#define PWMG_IE_NEWP1A_Pos 2 -#define PWMG_IE_NEWP1A_Msk (0x01 << PWMG_IE_NEWP1A_Pos) -#define PWMG_IE_NEWP1B_Pos 3 -#define PWMG_IE_NEWP1B_Msk (0x01 << PWMG_IE_NEWP1B_Pos) -#define PWMG_IE_NEWP2A_Pos 4 -#define PWMG_IE_NEWP2A_Msk (0x01 << PWMG_IE_NEWP2A_Pos) -#define PWMG_IE_NEWP2B_Pos 5 -#define PWMG_IE_NEWP2B_Msk (0x01 << PWMG_IE_NEWP2B_Pos) -#define PWMG_IE_NEWP3A_Pos 6 -#define PWMG_IE_NEWP3A_Msk (0x01 << PWMG_IE_NEWP3A_Pos) -#define PWMG_IE_NEWP3B_Pos 7 -#define PWMG_IE_NEWP3B_Msk (0x01 << PWMG_IE_NEWP3B_Pos) -#define PWMG_IE_NEWP4A_Pos 8 -#define PWMG_IE_NEWP4A_Msk (0x01 << PWMG_IE_NEWP4A_Pos) -#define PWMG_IE_NEWP4B_Pos 9 -#define PWMG_IE_NEWP4B_Msk (0x01 << PWMG_IE_NEWP4B_Pos) -#define PWMG_IE_NEWP5A_Pos 10 -#define PWMG_IE_NEWP5A_Msk (0x01 << PWMG_IE_NEWP5A_Pos) -#define PWMG_IE_NEWP5B_Pos 11 -#define PWMG_IE_NEWP5B_Msk (0x01 << PWMG_IE_NEWP5B_Pos) -#define PWMG_IE_HEND0A_Pos 12 -#define PWMG_IE_HEND0A_Msk (0x01 << PWMG_IE_HEND0A_Pos) -#define PWMG_IE_HEND0B_Pos 13 -#define PWMG_IE_HEND0B_Msk (0x01 << PWMG_IE_HEND0B_Pos) -#define PWMG_IE_HEND1A_Pos 14 -#define PWMG_IE_HEND1A_Msk (0x01 << PWMG_IE_HEND1A_Pos) -#define PWMG_IE_HEND1B_Pos 15 -#define PWMG_IE_HEND1B_Msk (0x01 << PWMG_IE_HEND1B_Pos) -#define PWMG_IE_HEND2A_Pos 16 -#define PWMG_IE_HEND2A_Msk (0x01 << PWMG_IE_HEND2A_Pos) -#define PWMG_IE_HEND2B_Pos 17 -#define PWMG_IE_HEND2B_Msk (0x01 << PWMG_IE_HEND2B_Pos) -#define PWMG_IE_HEND3A_Pos 18 -#define PWMG_IE_HEND3A_Msk (0x01 << PWMG_IE_HEND3A_Pos) -#define PWMG_IE_HEND3B_Pos 19 -#define PWMG_IE_HEND3B_Msk (0x01 << PWMG_IE_HEND3B_Pos) -#define PWMG_IE_HEND4A_Pos 20 -#define PWMG_IE_HEND4A_Msk (0x01 << PWMG_IE_HEND4A_Pos) -#define PWMG_IE_HEND4B_Pos 21 -#define PWMG_IE_HEND4B_Msk (0x01 << PWMG_IE_HEND4B_Pos) -#define PWMG_IE_HEND5A_Pos 22 -#define PWMG_IE_HEND5A_Msk (0x01 << PWMG_IE_HEND5A_Pos) -#define PWMG_IE_HEND5B_Pos 23 -#define PWMG_IE_HEND5B_Msk (0x01 << PWMG_IE_HEND5B_Pos) -#define PWMG_IE_HALT_Pos 24 -#define PWMG_IE_HALT_Msk (0x01 << PWMG_IE_HALT_Pos) +#define PWMG_CHEN_PWM0A_Pos 0 +#define PWMG_CHEN_PWM0A_Msk (0x01 << PWMG_CHEN_PWM0A_Pos) +#define PWMG_CHEN_PWM0B_Pos 1 +#define PWMG_CHEN_PWM0B_Msk (0x01 << PWMG_CHEN_PWM0B_Pos) +#define PWMG_CHEN_PWM1A_Pos 2 +#define PWMG_CHEN_PWM1A_Msk (0x01 << PWMG_CHEN_PWM1A_Pos) +#define PWMG_CHEN_PWM1B_Pos 3 +#define PWMG_CHEN_PWM1B_Msk (0x01 << PWMG_CHEN_PWM1B_Pos) +#define PWMG_CHEN_PWM2A_Pos 4 +#define PWMG_CHEN_PWM2A_Msk (0x01 << PWMG_CHEN_PWM2A_Pos) +#define PWMG_CHEN_PWM2B_Pos 5 +#define PWMG_CHEN_PWM2B_Msk (0x01 << PWMG_CHEN_PWM2B_Pos) +#define PWMG_CHEN_PWM3A_Pos 6 +#define PWMG_CHEN_PWM3A_Msk (0x01 << PWMG_CHEN_PWM3A_Pos) +#define PWMG_CHEN_PWM3B_Pos 7 +#define PWMG_CHEN_PWM3B_Msk (0x01 << PWMG_CHEN_PWM3B_Pos) +#define PWMG_CHEN_PWM4A_Pos 8 +#define PWMG_CHEN_PWM4A_Msk (0x01 << PWMG_CHEN_PWM4A_Pos) +#define PWMG_CHEN_PWM4B_Pos 9 +#define PWMG_CHEN_PWM4B_Msk (0x01 << PWMG_CHEN_PWM4B_Pos) +#define PWMG_CHEN_PWM5A_Pos 10 +#define PWMG_CHEN_PWM5A_Msk (0x01 << PWMG_CHEN_PWM5A_Pos) +#define PWMG_CHEN_PWM5B_Pos 11 +#define PWMG_CHEN_PWM5B_Msk (0x01 << PWMG_CHEN_PWM5B_Pos) -#define PWMG_IF_NEWP0A_Pos 0 -#define PWMG_IF_NEWP0A_Msk (0x01 << PWMG_IF_NEWP0A_Pos) -#define PWMG_IF_NEWP0B_Pos 1 -#define PWMG_IF_NEWP0B_Msk (0x01 << PWMG_IF_NEWP0B_Pos) -#define PWMG_IF_NEWP1A_Pos 2 -#define PWMG_IF_NEWP1A_Msk (0x01 << PWMG_IF_NEWP1A_Pos) -#define PWMG_IF_NEWP1B_Pos 3 -#define PWMG_IF_NEWP1B_Msk (0x01 << PWMG_IF_NEWP1B_Pos) -#define PWMG_IF_NEWP2A_Pos 4 -#define PWMG_IF_NEWP2A_Msk (0x01 << PWMG_IF_NEWP2A_Pos) -#define PWMG_IF_NEWP2B_Pos 5 -#define PWMG_IF_NEWP2B_Msk (0x01 << PWMG_IF_NEWP2B_Pos) -#define PWMG_IF_NEWP3A_Pos 6 -#define PWMG_IF_NEWP3A_Msk (0x01 << PWMG_IF_NEWP3A_Pos) -#define PWMG_IF_NEWP3B_Pos 7 -#define PWMG_IF_NEWP3B_Msk (0x01 << PWMG_IF_NEWP3B_Pos) -#define PWMG_IF_NEWP4A_Pos 8 -#define PWMG_IF_NEWP4A_Msk (0x01 << PWMG_IF_NEWP4A_Pos) -#define PWMG_IF_NEWP4B_Pos 9 -#define PWMG_IF_NEWP4B_Msk (0x01 << PWMG_IF_NEWP4B_Pos) -#define PWMG_IF_NEWP5A_Pos 10 -#define PWMG_IF_NEWP5A_Msk (0x01 << PWMG_IF_NEWP5A_Pos) -#define PWMG_IF_NEWP5B_Pos 11 -#define PWMG_IF_NEWP5B_Msk (0x01 << PWMG_IF_NEWP5B_Pos) -#define PWMG_IF_HEND0A_Pos 12 -#define PWMG_IF_HEND0A_Msk (0x01 << PWMG_IF_HEND0A_Pos) -#define PWMG_IF_HEND0B_Pos 13 -#define PWMG_IF_HEND0B_Msk (0x01 << PWMG_IF_HEND0B_Pos) -#define PWMG_IF_HEND1A_Pos 14 -#define PWMG_IF_HEND1A_Msk (0x01 << PWMG_IF_HEND1A_Pos) -#define PWMG_IF_HEND1B_Pos 15 -#define PWMG_IF_HEND1B_Msk (0x01 << PWMG_IF_HEND1B_Pos) -#define PWMG_IF_HEND2A_Pos 16 -#define PWMG_IF_HEND2A_Msk (0x01 << PWMG_IF_HEND2A_Pos) -#define PWMG_IF_HEND2B_Pos 17 -#define PWMG_IF_HEND2B_Msk (0x01 << PWMG_IF_HEND2B_Pos) -#define PWMG_IF_HEND3A_Pos 18 -#define PWMG_IF_HEND3A_Msk (0x01 << PWMG_IF_HEND3A_Pos) -#define PWMG_IF_HEND3B_Pos 19 -#define PWMG_IF_HEND3B_Msk (0x01 << PWMG_IF_HEND3B_Pos) -#define PWMG_IF_HEND4A_Pos 20 -#define PWMG_IF_HEND4A_Msk (0x01 << PWMG_IF_HEND4A_Pos) -#define PWMG_IF_HEND4B_Pos 21 -#define PWMG_IF_HEND4B_Msk (0x01 << PWMG_IF_HEND4B_Pos) -#define PWMG_IF_HEND5A_Pos 22 -#define PWMG_IF_HEND5A_Msk (0x01 << PWMG_IF_HEND5A_Pos) -#define PWMG_IF_HEND5B_Pos 23 -#define PWMG_IF_HEND5B_Msk (0x01 << PWMG_IF_HEND5B_Pos) -#define PWMG_IF_HALT_Pos 24 -#define PWMG_IF_HALT_Msk (0x01 << PWMG_IF_HALT_Pos) -#define PWMG_IM_NEWP0A_Pos 0 //Interrupt Mask -#define PWMG_IM_NEWP0A_Msk (0x01 << PWMG_IM_NEWP0A_Pos) -#define PWMG_IM_NEWP0B_Pos 1 -#define PWMG_IM_NEWP0B_Msk (0x01 << PWMG_IM_NEWP0B_Pos) -#define PWMG_IM_NEWP1A_Pos 2 -#define PWMG_IM_NEWP1A_Msk (0x01 << PWMG_IM_NEWP1A_Pos) -#define PWMG_IM_NEWP1B_Pos 3 -#define PWMG_IM_NEWP1B_Msk (0x01 << PWMG_IM_NEWP1B_Pos) -#define PWMG_IM_NEWP2A_Pos 4 -#define PWMG_IM_NEWP2A_Msk (0x01 << PWMG_IM_NEWP2A_Pos) -#define PWMG_IM_NEWP2B_Pos 5 -#define PWMG_IM_NEWP2B_Msk (0x01 << PWMG_IM_NEWP2B_Pos) -#define PWMG_IM_NEWP3A_Pos 6 -#define PWMG_IM_NEWP3A_Msk (0x01 << PWMG_IM_NEWP3A_Pos) -#define PWMG_IM_NEWP3B_Pos 7 -#define PWMG_IM_NEWP3B_Msk (0x01 << PWMG_IM_NEWP3B_Pos) -#define PWMG_IM_NEWP4A_Pos 8 -#define PWMG_IM_NEWP4A_Msk (0x01 << PWMG_IM_NEWP4A_Pos) -#define PWMG_IM_NEWP4B_Pos 9 -#define PWMG_IM_NEWP4B_Msk (0x01 << PWMG_IM_NEWP4B_Pos) -#define PWMG_IM_NEWP5A_Pos 10 -#define PWMG_IM_NEWP5A_Msk (0x01 << PWMG_IM_NEWP5A_Pos) -#define PWMG_IM_NEWP5B_Pos 11 -#define PWMG_IM_NEWP5B_Msk (0x01 << PWMG_IM_NEWP5B_Pos) -#define PWMG_IM_HEND0A_Pos 12 -#define PWMG_IM_HEND0A_Msk (0x01 << PWMG_IM_HEND0A_Pos) -#define PWMG_IM_HEND0B_Pos 13 -#define PWMG_IM_HEND0B_Msk (0x01 << PWMG_IM_HEND0B_Pos) -#define PWMG_IM_HEND1A_Pos 14 -#define PWMG_IM_HEND1A_Msk (0x01 << PWMG_IM_HEND1A_Pos) -#define PWMG_IM_HEND1B_Pos 15 -#define PWMG_IM_HEND1B_Msk (0x01 << PWMG_IM_HEND1B_Pos) -#define PWMG_IM_HEND2A_Pos 16 -#define PWMG_IM_HEND2A_Msk (0x01 << PWMG_IM_HEND2A_Pos) -#define PWMG_IM_HEND2B_Pos 17 -#define PWMG_IM_HEND2B_Msk (0x01 << PWMG_IM_HEND2B_Pos) -#define PWMG_IM_HEND3A_Pos 18 -#define PWMG_IM_HEND3A_Msk (0x01 << PWMG_IM_HEND3A_Pos) -#define PWMG_IM_HEND3B_Pos 19 -#define PWMG_IM_HEND3B_Msk (0x01 << PWMG_IM_HEND3B_Pos) -#define PWMG_IM_HEND4A_Pos 20 -#define PWMG_IM_HEND4A_Msk (0x01 << PWMG_IM_HEND4A_Pos) -#define PWMG_IM_HEND4B_Pos 21 -#define PWMG_IM_HEND4B_Msk (0x01 << PWMG_IM_HEND4B_Pos) -#define PWMG_IM_HEND5A_Pos 22 -#define PWMG_IM_HEND5A_Msk (0x01 << PWMG_IM_HEND5A_Pos) -#define PWMG_IM_HEND5B_Pos 23 -#define PWMG_IM_HEND5B_Msk (0x01 << PWMG_IM_HEND5B_Pos) -#define PWMG_IM_HALT_Pos 24 -#define PWMG_IM_HALT_Msk (0x01 << PWMG_IM_HALT_Pos) +#define PWMG_IE_NEWP0A_Pos 0 +#define PWMG_IE_NEWP0A_Msk (0x01 << PWMG_IE_NEWP0A_Pos) +#define PWMG_IE_NEWP0B_Pos 1 +#define PWMG_IE_NEWP0B_Msk (0x01 << PWMG_IE_NEWP0B_Pos) +#define PWMG_IE_NEWP1A_Pos 2 +#define PWMG_IE_NEWP1A_Msk (0x01 << PWMG_IE_NEWP1A_Pos) +#define PWMG_IE_NEWP1B_Pos 3 +#define PWMG_IE_NEWP1B_Msk (0x01 << PWMG_IE_NEWP1B_Pos) +#define PWMG_IE_NEWP2A_Pos 4 +#define PWMG_IE_NEWP2A_Msk (0x01 << PWMG_IE_NEWP2A_Pos) +#define PWMG_IE_NEWP2B_Pos 5 +#define PWMG_IE_NEWP2B_Msk (0x01 << PWMG_IE_NEWP2B_Pos) +#define PWMG_IE_NEWP3A_Pos 6 +#define PWMG_IE_NEWP3A_Msk (0x01 << PWMG_IE_NEWP3A_Pos) +#define PWMG_IE_NEWP3B_Pos 7 +#define PWMG_IE_NEWP3B_Msk (0x01 << PWMG_IE_NEWP3B_Pos) +#define PWMG_IE_NEWP4A_Pos 8 +#define PWMG_IE_NEWP4A_Msk (0x01 << PWMG_IE_NEWP4A_Pos) +#define PWMG_IE_NEWP4B_Pos 9 +#define PWMG_IE_NEWP4B_Msk (0x01 << PWMG_IE_NEWP4B_Pos) +#define PWMG_IE_NEWP5A_Pos 10 +#define PWMG_IE_NEWP5A_Msk (0x01 << PWMG_IE_NEWP5A_Pos) +#define PWMG_IE_NEWP5B_Pos 11 +#define PWMG_IE_NEWP5B_Msk (0x01 << PWMG_IE_NEWP5B_Pos) +#define PWMG_IE_HEND0A_Pos 12 +#define PWMG_IE_HEND0A_Msk (0x01 << PWMG_IE_HEND0A_Pos) +#define PWMG_IE_HEND0B_Pos 13 +#define PWMG_IE_HEND0B_Msk (0x01 << PWMG_IE_HEND0B_Pos) +#define PWMG_IE_HEND1A_Pos 14 +#define PWMG_IE_HEND1A_Msk (0x01 << PWMG_IE_HEND1A_Pos) +#define PWMG_IE_HEND1B_Pos 15 +#define PWMG_IE_HEND1B_Msk (0x01 << PWMG_IE_HEND1B_Pos) +#define PWMG_IE_HEND2A_Pos 16 +#define PWMG_IE_HEND2A_Msk (0x01 << PWMG_IE_HEND2A_Pos) +#define PWMG_IE_HEND2B_Pos 17 +#define PWMG_IE_HEND2B_Msk (0x01 << PWMG_IE_HEND2B_Pos) +#define PWMG_IE_HEND3A_Pos 18 +#define PWMG_IE_HEND3A_Msk (0x01 << PWMG_IE_HEND3A_Pos) +#define PWMG_IE_HEND3B_Pos 19 +#define PWMG_IE_HEND3B_Msk (0x01 << PWMG_IE_HEND3B_Pos) +#define PWMG_IE_HEND4A_Pos 20 +#define PWMG_IE_HEND4A_Msk (0x01 << PWMG_IE_HEND4A_Pos) +#define PWMG_IE_HEND4B_Pos 21 +#define PWMG_IE_HEND4B_Msk (0x01 << PWMG_IE_HEND4B_Pos) +#define PWMG_IE_HEND5A_Pos 22 +#define PWMG_IE_HEND5A_Msk (0x01 << PWMG_IE_HEND5A_Pos) +#define PWMG_IE_HEND5B_Pos 23 +#define PWMG_IE_HEND5B_Msk (0x01 << PWMG_IE_HEND5B_Pos) +#define PWMG_IE_HALT_Pos 24 +#define PWMG_IE_HALT_Msk (0x01 << PWMG_IE_HALT_Pos) -#define PWMG_IRS_NEWP0A_Pos 0 //Interrupt Raw State -#define PWMG_IRS_NEWP0A_Msk (0x01 << PWMG_IRS_NEWP0A_Pos) -#define PWMG_IRS_NEWP0B_Pos 1 -#define PWMG_IRS_NEWP0B_Msk (0x01 << PWMG_IRS_NEWP0B_Pos) -#define PWMG_IRS_NEWP1A_Pos 2 -#define PWMG_IRS_NEWP1A_Msk (0x01 << PWMG_IRS_NEWP1A_Pos) -#define PWMG_IRS_NEWP1B_Pos 3 -#define PWMG_IRS_NEWP1B_Msk (0x01 << PWMG_IRS_NEWP1B_Pos) -#define PWMG_IRS_NEWP2A_Pos 4 -#define PWMG_IRS_NEWP2A_Msk (0x01 << PWMG_IRS_NEWP2A_Pos) -#define PWMG_IRS_NEWP2B_Pos 5 -#define PWMG_IRS_NEWP2B_Msk (0x01 << PWMG_IRS_NEWP2B_Pos) -#define PWMG_IRS_NEWP3A_Pos 6 -#define PWMG_IRS_NEWP3A_Msk (0x01 << PWMG_IRS_NEWP3A_Pos) -#define PWMG_IRS_NEWP3B_Pos 7 -#define PWMG_IRS_NEWP3B_Msk (0x01 << PWMG_IRS_NEWP3B_Pos) -#define PWMG_IRS_NEWP4A_Pos 8 -#define PWMG_IRS_NEWP4A_Msk (0x01 << PWMG_IRS_NEWP4A_Pos) -#define PWMG_IRS_NEWP4B_Pos 9 -#define PWMG_IRS_NEWP4B_Msk (0x01 << PWMG_IRS_NEWP4B_Pos) -#define PWMG_IRS_NEWP5A_Pos 10 -#define PWMG_IRS_NEWP5A_Msk (0x01 << PWMG_IRS_NEWP5A_Pos) -#define PWMG_IRS_NEWP5B_Pos 11 -#define PWMG_IRS_NEWP5B_Msk (0x01 << PWMG_IRS_NEWP5B_Pos) -#define PWMG_IRS_HEND0A_Pos 12 -#define PWMG_IRS_HEND0A_Msk (0x01 << PWMG_IRS_HEND0A_Pos) -#define PWMG_IRS_HEND0B_Pos 13 -#define PWMG_IRS_HEND0B_Msk (0x01 << PWMG_IRS_HEND0B_Pos) -#define PWMG_IRS_HEND1A_Pos 14 -#define PWMG_IRS_HEND1A_Msk (0x01 << PWMG_IRS_HEND1A_Pos) -#define PWMG_IRS_HEND1B_Pos 15 -#define PWMG_IRS_HEND1B_Msk (0x01 << PWMG_IRS_HEND1B_Pos) -#define PWMG_IRS_HEND2A_Pos 16 -#define PWMG_IRS_HEND2A_Msk (0x01 << PWMG_IRS_HEND2A_Pos) -#define PWMG_IRS_HEND2B_Pos 17 -#define PWMG_IRS_HEND2B_Msk (0x01 << PWMG_IRS_HEND2B_Pos) -#define PWMG_IRS_HEND3A_Pos 18 -#define PWMG_IRS_HEND3A_Msk (0x01 << PWMG_IRS_HEND3A_Pos) -#define PWMG_IRS_HEND3B_Pos 19 -#define PWMG_IRS_HEND3B_Msk (0x01 << PWMG_IRS_HEND3B_Pos) -#define PWMG_IRS_HEND4A_Pos 20 -#define PWMG_IRS_HEND4A_Msk (0x01 << PWMG_IRS_HEND4A_Pos) -#define PWMG_IRS_HEND4B_Pos 21 -#define PWMG_IRS_HEND4B_Msk (0x01 << PWMG_IRS_HEND4B_Pos) -#define PWMG_IRS_HEND5A_Pos 22 -#define PWMG_IRS_HEND5A_Msk (0x01 << PWMG_IRS_HEND5A_Pos) -#define PWMG_IRS_HEND5B_Pos 23 -#define PWMG_IRS_HEND5B_Msk (0x01 << PWMG_IRS_HEND5B_Pos) -#define PWMG_IRS_HALT_Pos 24 -#define PWMG_IRS_HALT_Msk (0x01 << PWMG_IRS_HALT_Pos) +#define PWMG_IF_NEWP0A_Pos 0 +#define PWMG_IF_NEWP0A_Msk (0x01 << PWMG_IF_NEWP0A_Pos) +#define PWMG_IF_NEWP0B_Pos 1 +#define PWMG_IF_NEWP0B_Msk (0x01 << PWMG_IF_NEWP0B_Pos) +#define PWMG_IF_NEWP1A_Pos 2 +#define PWMG_IF_NEWP1A_Msk (0x01 << PWMG_IF_NEWP1A_Pos) +#define PWMG_IF_NEWP1B_Pos 3 +#define PWMG_IF_NEWP1B_Msk (0x01 << PWMG_IF_NEWP1B_Pos) +#define PWMG_IF_NEWP2A_Pos 4 +#define PWMG_IF_NEWP2A_Msk (0x01 << PWMG_IF_NEWP2A_Pos) +#define PWMG_IF_NEWP2B_Pos 5 +#define PWMG_IF_NEWP2B_Msk (0x01 << PWMG_IF_NEWP2B_Pos) +#define PWMG_IF_NEWP3A_Pos 6 +#define PWMG_IF_NEWP3A_Msk (0x01 << PWMG_IF_NEWP3A_Pos) +#define PWMG_IF_NEWP3B_Pos 7 +#define PWMG_IF_NEWP3B_Msk (0x01 << PWMG_IF_NEWP3B_Pos) +#define PWMG_IF_NEWP4A_Pos 8 +#define PWMG_IF_NEWP4A_Msk (0x01 << PWMG_IF_NEWP4A_Pos) +#define PWMG_IF_NEWP4B_Pos 9 +#define PWMG_IF_NEWP4B_Msk (0x01 << PWMG_IF_NEWP4B_Pos) +#define PWMG_IF_NEWP5A_Pos 10 +#define PWMG_IF_NEWP5A_Msk (0x01 << PWMG_IF_NEWP5A_Pos) +#define PWMG_IF_NEWP5B_Pos 11 +#define PWMG_IF_NEWP5B_Msk (0x01 << PWMG_IF_NEWP5B_Pos) +#define PWMG_IF_HEND0A_Pos 12 +#define PWMG_IF_HEND0A_Msk (0x01 << PWMG_IF_HEND0A_Pos) +#define PWMG_IF_HEND0B_Pos 13 +#define PWMG_IF_HEND0B_Msk (0x01 << PWMG_IF_HEND0B_Pos) +#define PWMG_IF_HEND1A_Pos 14 +#define PWMG_IF_HEND1A_Msk (0x01 << PWMG_IF_HEND1A_Pos) +#define PWMG_IF_HEND1B_Pos 15 +#define PWMG_IF_HEND1B_Msk (0x01 << PWMG_IF_HEND1B_Pos) +#define PWMG_IF_HEND2A_Pos 16 +#define PWMG_IF_HEND2A_Msk (0x01 << PWMG_IF_HEND2A_Pos) +#define PWMG_IF_HEND2B_Pos 17 +#define PWMG_IF_HEND2B_Msk (0x01 << PWMG_IF_HEND2B_Pos) +#define PWMG_IF_HEND3A_Pos 18 +#define PWMG_IF_HEND3A_Msk (0x01 << PWMG_IF_HEND3A_Pos) +#define PWMG_IF_HEND3B_Pos 19 +#define PWMG_IF_HEND3B_Msk (0x01 << PWMG_IF_HEND3B_Pos) +#define PWMG_IF_HEND4A_Pos 20 +#define PWMG_IF_HEND4A_Msk (0x01 << PWMG_IF_HEND4A_Pos) +#define PWMG_IF_HEND4B_Pos 21 +#define PWMG_IF_HEND4B_Msk (0x01 << PWMG_IF_HEND4B_Pos) +#define PWMG_IF_HEND5A_Pos 22 +#define PWMG_IF_HEND5A_Msk (0x01 << PWMG_IF_HEND5A_Pos) +#define PWMG_IF_HEND5B_Pos 23 +#define PWMG_IF_HEND5B_Msk (0x01 << PWMG_IF_HEND5B_Pos) +#define PWMG_IF_HALT_Pos 24 +#define PWMG_IF_HALT_Msk (0x01 << PWMG_IF_HALT_Pos) -typedef struct -{ - __IO uint32_t EN; //[0] ENABLE +#define PWMG_IM_NEWP0A_Pos 0 //Interrupt Mask +#define PWMG_IM_NEWP0A_Msk (0x01 << PWMG_IM_NEWP0A_Pos) +#define PWMG_IM_NEWP0B_Pos 1 +#define PWMG_IM_NEWP0B_Msk (0x01 << PWMG_IM_NEWP0B_Pos) +#define PWMG_IM_NEWP1A_Pos 2 +#define PWMG_IM_NEWP1A_Msk (0x01 << PWMG_IM_NEWP1A_Pos) +#define PWMG_IM_NEWP1B_Pos 3 +#define PWMG_IM_NEWP1B_Msk (0x01 << PWMG_IM_NEWP1B_Pos) +#define PWMG_IM_NEWP2A_Pos 4 +#define PWMG_IM_NEWP2A_Msk (0x01 << PWMG_IM_NEWP2A_Pos) +#define PWMG_IM_NEWP2B_Pos 5 +#define PWMG_IM_NEWP2B_Msk (0x01 << PWMG_IM_NEWP2B_Pos) +#define PWMG_IM_NEWP3A_Pos 6 +#define PWMG_IM_NEWP3A_Msk (0x01 << PWMG_IM_NEWP3A_Pos) +#define PWMG_IM_NEWP3B_Pos 7 +#define PWMG_IM_NEWP3B_Msk (0x01 << PWMG_IM_NEWP3B_Pos) +#define PWMG_IM_NEWP4A_Pos 8 +#define PWMG_IM_NEWP4A_Msk (0x01 << PWMG_IM_NEWP4A_Pos) +#define PWMG_IM_NEWP4B_Pos 9 +#define PWMG_IM_NEWP4B_Msk (0x01 << PWMG_IM_NEWP4B_Pos) +#define PWMG_IM_NEWP5A_Pos 10 +#define PWMG_IM_NEWP5A_Msk (0x01 << PWMG_IM_NEWP5A_Pos) +#define PWMG_IM_NEWP5B_Pos 11 +#define PWMG_IM_NEWP5B_Msk (0x01 << PWMG_IM_NEWP5B_Pos) +#define PWMG_IM_HEND0A_Pos 12 +#define PWMG_IM_HEND0A_Msk (0x01 << PWMG_IM_HEND0A_Pos) +#define PWMG_IM_HEND0B_Pos 13 +#define PWMG_IM_HEND0B_Msk (0x01 << PWMG_IM_HEND0B_Pos) +#define PWMG_IM_HEND1A_Pos 14 +#define PWMG_IM_HEND1A_Msk (0x01 << PWMG_IM_HEND1A_Pos) +#define PWMG_IM_HEND1B_Pos 15 +#define PWMG_IM_HEND1B_Msk (0x01 << PWMG_IM_HEND1B_Pos) +#define PWMG_IM_HEND2A_Pos 16 +#define PWMG_IM_HEND2A_Msk (0x01 << PWMG_IM_HEND2A_Pos) +#define PWMG_IM_HEND2B_Pos 17 +#define PWMG_IM_HEND2B_Msk (0x01 << PWMG_IM_HEND2B_Pos) +#define PWMG_IM_HEND3A_Pos 18 +#define PWMG_IM_HEND3A_Msk (0x01 << PWMG_IM_HEND3A_Pos) +#define PWMG_IM_HEND3B_Pos 19 +#define PWMG_IM_HEND3B_Msk (0x01 << PWMG_IM_HEND3B_Pos) +#define PWMG_IM_HEND4A_Pos 20 +#define PWMG_IM_HEND4A_Msk (0x01 << PWMG_IM_HEND4A_Pos) +#define PWMG_IM_HEND4B_Pos 21 +#define PWMG_IM_HEND4B_Msk (0x01 << PWMG_IM_HEND4B_Pos) +#define PWMG_IM_HEND5A_Pos 22 +#define PWMG_IM_HEND5A_Msk (0x01 << PWMG_IM_HEND5A_Pos) +#define PWMG_IM_HEND5B_Pos 23 +#define PWMG_IM_HEND5B_Msk (0x01 << PWMG_IM_HEND5B_Pos) +#define PWMG_IM_HALT_Pos 24 +#define PWMG_IM_HALT_Msk (0x01 << PWMG_IM_HALT_Pos) - __IO uint32_t IE; //只有为1时,IF[CHx]在DMA传输结束时才能变为1,否则将一直保持在0 +#define PWMG_IRS_NEWP0A_Pos 0 //Interrupt Raw State +#define PWMG_IRS_NEWP0A_Msk (0x01 << PWMG_IRS_NEWP0A_Pos) +#define PWMG_IRS_NEWP0B_Pos 1 +#define PWMG_IRS_NEWP0B_Msk (0x01 << PWMG_IRS_NEWP0B_Pos) +#define PWMG_IRS_NEWP1A_Pos 2 +#define PWMG_IRS_NEWP1A_Msk (0x01 << PWMG_IRS_NEWP1A_Pos) +#define PWMG_IRS_NEWP1B_Pos 3 +#define PWMG_IRS_NEWP1B_Msk (0x01 << PWMG_IRS_NEWP1B_Pos) +#define PWMG_IRS_NEWP2A_Pos 4 +#define PWMG_IRS_NEWP2A_Msk (0x01 << PWMG_IRS_NEWP2A_Pos) +#define PWMG_IRS_NEWP2B_Pos 5 +#define PWMG_IRS_NEWP2B_Msk (0x01 << PWMG_IRS_NEWP2B_Pos) +#define PWMG_IRS_NEWP3A_Pos 6 +#define PWMG_IRS_NEWP3A_Msk (0x01 << PWMG_IRS_NEWP3A_Pos) +#define PWMG_IRS_NEWP3B_Pos 7 +#define PWMG_IRS_NEWP3B_Msk (0x01 << PWMG_IRS_NEWP3B_Pos) +#define PWMG_IRS_NEWP4A_Pos 8 +#define PWMG_IRS_NEWP4A_Msk (0x01 << PWMG_IRS_NEWP4A_Pos) +#define PWMG_IRS_NEWP4B_Pos 9 +#define PWMG_IRS_NEWP4B_Msk (0x01 << PWMG_IRS_NEWP4B_Pos) +#define PWMG_IRS_NEWP5A_Pos 10 +#define PWMG_IRS_NEWP5A_Msk (0x01 << PWMG_IRS_NEWP5A_Pos) +#define PWMG_IRS_NEWP5B_Pos 11 +#define PWMG_IRS_NEWP5B_Msk (0x01 << PWMG_IRS_NEWP5B_Pos) +#define PWMG_IRS_HEND0A_Pos 12 +#define PWMG_IRS_HEND0A_Msk (0x01 << PWMG_IRS_HEND0A_Pos) +#define PWMG_IRS_HEND0B_Pos 13 +#define PWMG_IRS_HEND0B_Msk (0x01 << PWMG_IRS_HEND0B_Pos) +#define PWMG_IRS_HEND1A_Pos 14 +#define PWMG_IRS_HEND1A_Msk (0x01 << PWMG_IRS_HEND1A_Pos) +#define PWMG_IRS_HEND1B_Pos 15 +#define PWMG_IRS_HEND1B_Msk (0x01 << PWMG_IRS_HEND1B_Pos) +#define PWMG_IRS_HEND2A_Pos 16 +#define PWMG_IRS_HEND2A_Msk (0x01 << PWMG_IRS_HEND2A_Pos) +#define PWMG_IRS_HEND2B_Pos 17 +#define PWMG_IRS_HEND2B_Msk (0x01 << PWMG_IRS_HEND2B_Pos) +#define PWMG_IRS_HEND3A_Pos 18 +#define PWMG_IRS_HEND3A_Msk (0x01 << PWMG_IRS_HEND3A_Pos) +#define PWMG_IRS_HEND3B_Pos 19 +#define PWMG_IRS_HEND3B_Msk (0x01 << PWMG_IRS_HEND3B_Pos) +#define PWMG_IRS_HEND4A_Pos 20 +#define PWMG_IRS_HEND4A_Msk (0x01 << PWMG_IRS_HEND4A_Pos) +#define PWMG_IRS_HEND4B_Pos 21 +#define PWMG_IRS_HEND4B_Msk (0x01 << PWMG_IRS_HEND4B_Pos) +#define PWMG_IRS_HEND5A_Pos 22 +#define PWMG_IRS_HEND5A_Msk (0x01 << PWMG_IRS_HEND5A_Pos) +#define PWMG_IRS_HEND5B_Pos 23 +#define PWMG_IRS_HEND5B_Msk (0x01 << PWMG_IRS_HEND5B_Pos) +#define PWMG_IRS_HALT_Pos 24 +#define PWMG_IRS_HALT_Msk (0x01 << PWMG_IRS_HALT_Pos) - __IO uint32_t IM; //当为1时,即使IF[CHx]为1,dma_int也不会因此变1 - __IO uint32_t IF; //写1清零 - uint32_t RESERVED[12]; - struct - { - __IO uint32_t CR; - - __IO uint32_t AM; //Adress Mode - - __IO uint32_t SRC; - - __IO uint32_t SRCSGADDR1; //只在Scatter Gather模式下使用 - - __IO uint32_t SRCSGADDR2; //只在Scatter Gather模式下使用 - - __IO uint32_t SRCSGADDR3; //只在Scatter Gather模式下使用 - - __IO uint32_t SRCSGLEN; //只在Scatter Gather模式下使用 - - __IO uint32_t DST; - - __IO uint32_t DSTSGADDR1; //只在Scatter Gather模式下使用 - - __IO uint32_t DSTSGADDR2; //只在Scatter Gather模式下使用 - - __IO uint32_t DSTSGADDR3; //只在Scatter Gather模式下使用 - - __IO uint32_t DSTSGLEN; //只在Scatter Gather模式下使用 - - uint32_t RESERVED[4]; - } CH[3]; +typedef struct { + __IO uint32_t EN; //[0] ENABLE + + __IO uint32_t IE; //ֻΪ1ʱIF[CHx]DMAʱܱΪ1һֱ0 + + __IO uint32_t IM; //Ϊ1ʱʹIF[CHx]Ϊ1dma_intҲ˱1 + + __IO uint32_t IF; //д1 + + uint32_t RESERVED[12]; + + struct { + __IO uint32_t CR; + + __IO uint32_t AM; //Adress Mode + + __IO uint32_t SRC; + + __IO uint32_t SRCSGADDR1; //ֻScatter Gatherģʽʹ + + __IO uint32_t SRCSGADDR2; //ֻScatter Gatherģʽʹ + + __IO uint32_t SRCSGADDR3; //ֻScatter Gatherģʽʹ + + __IO uint32_t SRCSGLEN; //ֻScatter Gatherģʽʹ + + __IO uint32_t DST; + + __IO uint32_t DSTSGADDR1; //ֻScatter Gatherģʽʹ + + __IO uint32_t DSTSGADDR2; //ֻScatter Gatherģʽʹ + + __IO uint32_t DSTSGADDR3; //ֻScatter Gatherģʽʹ + + __IO uint32_t DSTSGLEN; //ֻScatter Gatherģʽʹ + + uint32_t RESERVED[4]; + } CH[3]; } DMA_TypeDef; -#define DMA_IE_CH0_Pos 0 -#define DMA_IE_CH0_Msk (0x01 << DMA_IE_CH0_Pos) -#define DMA_IE_CH1_Pos 1 -#define DMA_IE_CH1_Msk (0x01 << DMA_IE_CH1_Pos) -#define DMA_IE_CH2_Pos 2 -#define DMA_IE_CH2_Msk (0x01 << DMA_IE_CH2_Pos) -#define DMA_IE_CH3_Pos 3 -#define DMA_IE_CH3_Msk (0x01 << DMA_IE_CH3_Pos) -#define DMA_IE_CH4_Pos 4 -#define DMA_IE_CH4_Msk (0x01 << DMA_IE_CH4_Pos) -#define DMA_IE_CH5_Pos 5 -#define DMA_IE_CH5_Msk (0x01 << DMA_IE_CH5_Pos) -#define DMA_IE_CH6_Pos 6 -#define DMA_IE_CH6_Msk (0x01 << DMA_IE_CH6_Pos) -#define DMA_IE_CH7_Pos 7 -#define DMA_IE_CH7_Msk (0x01 << DMA_IE_CH7_Pos) -#define DMA_IM_CH0_Pos 0 -#define DMA_IM_CH0_Msk (0x01 << DMA_IM_CH0_Pos) -#define DMA_IM_CH1_Pos 1 -#define DMA_IM_CH1_Msk (0x01 << DMA_IM_CH1_Pos) -#define DMA_IM_CH2_Pos 2 -#define DMA_IM_CH2_Msk (0x01 << DMA_IM_CH2_Pos) -#define DMA_IM_CH3_Pos 3 -#define DMA_IM_CH3_Msk (0x01 << DMA_IM_CH3_Pos) -#define DMA_IM_CH4_Pos 4 -#define DMA_IM_CH4_Msk (0x01 << DMA_IM_CH4_Pos) -#define DMA_IM_CH5_Pos 5 -#define DMA_IM_CH5_Msk (0x01 << DMA_IM_CH5_Pos) -#define DMA_IM_CH6_Pos 6 -#define DMA_IM_CH6_Msk (0x01 << DMA_IM_CH6_Pos) -#define DMA_IM_CH7_Pos 7 -#define DMA_IM_CH7_Msk (0x01 << DMA_IM_CH7_Pos) +#define DMA_IE_CH0_Pos 0 +#define DMA_IE_CH0_Msk (0x01 << DMA_IE_CH0_Pos) +#define DMA_IE_CH1_Pos 1 +#define DMA_IE_CH1_Msk (0x01 << DMA_IE_CH1_Pos) +#define DMA_IE_CH2_Pos 2 +#define DMA_IE_CH2_Msk (0x01 << DMA_IE_CH2_Pos) +#define DMA_IE_CH3_Pos 3 +#define DMA_IE_CH3_Msk (0x01 << DMA_IE_CH3_Pos) +#define DMA_IE_CH4_Pos 4 +#define DMA_IE_CH4_Msk (0x01 << DMA_IE_CH4_Pos) +#define DMA_IE_CH5_Pos 5 +#define DMA_IE_CH5_Msk (0x01 << DMA_IE_CH5_Pos) +#define DMA_IE_CH6_Pos 6 +#define DMA_IE_CH6_Msk (0x01 << DMA_IE_CH6_Pos) +#define DMA_IE_CH7_Pos 7 +#define DMA_IE_CH7_Msk (0x01 << DMA_IE_CH7_Pos) -#define DMA_IF_CH0_Pos 0 -#define DMA_IF_CH0_Msk (0x01 << DMA_IF_CH0_Pos) -#define DMA_IF_CH1_Pos 1 -#define DMA_IF_CH1_Msk (0x01 << DMA_IF_CH1_Pos) -#define DMA_IF_CH2_Pos 2 -#define DMA_IF_CH2_Msk (0x01 << DMA_IF_CH2_Pos) -#define DMA_IF_CH3_Pos 3 -#define DMA_IF_CH3_Msk (0x01 << DMA_IF_CH3_Pos) -#define DMA_IF_CH4_Pos 4 -#define DMA_IF_CH4_Msk (0x01 << DMA_IF_CH4_Pos) -#define DMA_IF_CH5_Pos 5 -#define DMA_IF_CH5_Msk (0x01 << DMA_IF_CH5_Pos) -#define DMA_IF_CH6_Pos 6 -#define DMA_IF_CH6_Msk (0x01 << DMA_IF_CH6_Pos) -#define DMA_IF_CH7_Pos 7 -#define DMA_IF_CH7_Msk (0x01 << DMA_IF_CH7_Pos) +#define DMA_IM_CH0_Pos 0 +#define DMA_IM_CH0_Msk (0x01 << DMA_IM_CH0_Pos) +#define DMA_IM_CH1_Pos 1 +#define DMA_IM_CH1_Msk (0x01 << DMA_IM_CH1_Pos) +#define DMA_IM_CH2_Pos 2 +#define DMA_IM_CH2_Msk (0x01 << DMA_IM_CH2_Pos) +#define DMA_IM_CH3_Pos 3 +#define DMA_IM_CH3_Msk (0x01 << DMA_IM_CH3_Pos) +#define DMA_IM_CH4_Pos 4 +#define DMA_IM_CH4_Msk (0x01 << DMA_IM_CH4_Pos) +#define DMA_IM_CH5_Pos 5 +#define DMA_IM_CH5_Msk (0x01 << DMA_IM_CH5_Pos) +#define DMA_IM_CH6_Pos 6 +#define DMA_IM_CH6_Msk (0x01 << DMA_IM_CH6_Pos) +#define DMA_IM_CH7_Pos 7 +#define DMA_IM_CH7_Msk (0x01 << DMA_IM_CH7_Pos) -#define DMA_CR_LEN_Pos 0 //此通道传输总长度,0对应1字节,最大4096字节 -#define DMA_CR_LEN_Msk (0xFFF << DMA_CR_LEN_Pos) -#define DMA_CR_RXEN_Pos 16 -#define DMA_CR_RXEN_Msk (0x01 << DMA_CR_RXEN_Pos) -#define DMA_CR_TXEN_Pos 17 -#define DMA_CR_TXEN_Msk (0x01 << DMA_CR_TXEN_Pos) -#define DMA_CR_AUTORE_Pos 18 //Auto Restart, 通道在传输完成后,是否自动重新启动 -#define DMA_CR_AUTORE_Msk (0x01 << DMA_CR_AUTORE_Pos) +#define DMA_IF_CH0_Pos 0 +#define DMA_IF_CH0_Msk (0x01 << DMA_IF_CH0_Pos) +#define DMA_IF_CH1_Pos 1 +#define DMA_IF_CH1_Msk (0x01 << DMA_IF_CH1_Pos) +#define DMA_IF_CH2_Pos 2 +#define DMA_IF_CH2_Msk (0x01 << DMA_IF_CH2_Pos) +#define DMA_IF_CH3_Pos 3 +#define DMA_IF_CH3_Msk (0x01 << DMA_IF_CH3_Pos) +#define DMA_IF_CH4_Pos 4 +#define DMA_IF_CH4_Msk (0x01 << DMA_IF_CH4_Pos) +#define DMA_IF_CH5_Pos 5 +#define DMA_IF_CH5_Msk (0x01 << DMA_IF_CH5_Pos) +#define DMA_IF_CH6_Pos 6 +#define DMA_IF_CH6_Msk (0x01 << DMA_IF_CH6_Pos) +#define DMA_IF_CH7_Pos 7 +#define DMA_IF_CH7_Msk (0x01 << DMA_IF_CH7_Pos) -#define DMA_AM_SRCAM_Pos 0 //Address Mode 0 地址固定 1 地址递增 2 scatter gather模式 -#define DMA_AM_SRCAM_Msk (0x03 << DMA_AM_SRCAM_Pos) -#define DMA_AM_DSTAM_Pos 8 -#define DMA_AM_DSTAM_Msk (0x03 << DMA_AM_DSTAM_Pos) -#define DMA_AM_BURST_Pos 16 -#define DMA_AM_BURST_Msk (0x01 << DMA_AM_BURST_Pos) +#define DMA_CR_LEN_Pos 0 //ͨܳȣ0Ӧ1ֽڣ4096ֽ +#define DMA_CR_LEN_Msk (0xFFF << DMA_CR_LEN_Pos) +#define DMA_CR_RXEN_Pos 16 +#define DMA_CR_RXEN_Msk (0x01 << DMA_CR_RXEN_Pos) +#define DMA_CR_TXEN_Pos 17 +#define DMA_CR_TXEN_Msk (0x01 << DMA_CR_TXEN_Pos) +#define DMA_CR_AUTORE_Pos 18 //Auto Restart, ͨڴɺǷԶ +#define DMA_CR_AUTORE_Msk (0x01 << DMA_CR_AUTORE_Pos) -typedef struct -{ - __IO uint32_t CR; //Control Register +#define DMA_AM_SRCAM_Pos 0 //Address Mode 0 ̶ַ 1 ַ 2 scatter gatherģʽ +#define DMA_AM_SRCAM_Msk (0x03 << DMA_AM_SRCAM_Pos) +#define DMA_AM_DSTAM_Pos 8 +#define DMA_AM_DSTAM_Msk (0x03 << DMA_AM_DSTAM_Pos) +#define DMA_AM_BURST_Pos 16 +#define DMA_AM_BURST_Msk (0x01 << DMA_AM_BURST_Pos) - __O uint32_t CMD; //Command Register - __I uint32_t SR; //Status Register - __I uint32_t IF; //Interrupt Flag - __IO uint32_t IE; //Interrupt Enable - - uint32_t RESERVED; - - __IO uint32_t BT0; //Bit Time Register 0 - - __IO uint32_t BT1; //Bit Time Register 1 - - uint32_t RESERVED2[3]; - - __I uint32_t ALC; //Arbitration Lost Capture, 仲裁丢失捕捉 - - __I uint32_t ECC; //Error code capture, 错误代码捕捉 - - __IO uint32_t EWLIM; //Error Warning Limit, 错误报警限制 - - __IO uint32_t RXERR; //RX错误计数 - - __IO uint32_t TXERR; //TX错误计数 - - union { - struct - { //在复位时可读写,正常工作模式下不可访问 - __IO uint32_t ACR[4]; //Acceptance Check Register, 验收寄存器 - - __IO uint32_t AMR[4]; //Acceptance Mask Register, 验收屏蔽寄存器;对应位写0,ID必须和验收寄存器匹配 - - uint32_t RESERVED[5]; - } FILTER; - - union { //在正常工作模式下可读写,复位时不可访问 - struct - { - __O uint32_t INFO; - - __O uint32_t DATA[12]; - } TXFRAME; - - struct - { - __I uint32_t INFO; - - __I uint32_t DATA[12]; - } RXFRAME; - }; - }; - - __I uint32_t RMCNT; //Receive Message Count - - uint32_t RESERVED3[66]; - - struct - { //TXFRAME的读接口 - __I uint32_t INFO; - - __I uint32_t DATA[12]; - } TXFRAME_R; +typedef struct { + __IO uint32_t CR; //Control Register + + __O uint32_t CMD; //Command Register + + __I uint32_t SR; //Status Register + + __I uint32_t IF; //Interrupt Flagȡ + + __IO uint32_t IE; //Interrupt Enable + + uint32_t RESERVED; + + __IO uint32_t BT0; //Bit Time Register 0 + + __IO uint32_t BT1; //Bit Time Register 1 + + uint32_t RESERVED2[3]; + + __I uint32_t ALC; //Arbitration Lost Capture, ٲöʧ׽ + + __I uint32_t ECC; //Error code capture, 벶׽ + + __IO uint32_t EWLIM; //Error Warning Limit, 󱨾 + + __IO uint32_t RXERR; //RX + + __IO uint32_t TXERR; //TX + + union { + struct { //ڸλʱɶдģʽ²ɷ + __IO uint32_t ACR[4]; //Acceptance Check Register, ռĴ + + __IO uint32_t AMR[4]; //Acceptance Mask Register, μĴӦλд0IDռĴƥ + + uint32_t RESERVED[5]; + } FILTER; + + union { //ģʽ¿ɶдλʱɷ + struct { + __O uint32_t INFO; + + __O uint32_t DATA[12]; + } TXFRAME; + + struct { + __I uint32_t INFO; + + __I uint32_t DATA[12]; + } RXFRAME; + }; + }; + + __I uint32_t RMCNT; //Receive Message Count + + uint32_t RESERVED3[66]; + + struct { //TXFRAMEĶӿ + __I uint32_t INFO; + + __I uint32_t DATA[12]; + } TXFRAME_R; } CAN_TypeDef; -#define CAN_CR_RST_Pos 0 -#define CAN_CR_RST_Msk (0x01 << CAN_CR_RST_Pos) -#define CAN_CR_LOM_Pos 1 //Listen Only Mode -#define CAN_CR_LOM_Msk (0x01 << CAN_CR_LOM_Pos) -#define CAN_CR_STM_Pos 2 //Self Test Mode, 此模式下即使没有应答,CAN控制器也可以成功发送 -#define CAN_CR_STM_Msk (0x01 << CAN_CR_STM_Pos) -#define CAN_CR_AFM_Pos 3 //Acceptance Filter Mode, 1 单个验收滤波器(32位) 0 两个验收滤波器(16位) -#define CAN_CR_AFM_Msk (0x01 << CAN_CR_AFM_Pos) -#define CAN_CR_SLEEP_Pos 4 //写1进入睡眠模式,有总线活动或中断时唤醒并自动清零此位 -#define CAN_CR_SLEEP_Msk (0x01 << CAN_CR_SLEEP_Pos) -#define CAN_CMD_TXREQ_Pos 0 //Transmission Request -#define CAN_CMD_TXREQ_Msk (0x01 << CAN_CMD_TXREQ_Pos) -#define CAN_CMD_ABTTX_Pos 1 //Abort Transmission -#define CAN_CMD_ABTTX_Msk (0x01 << CAN_CMD_ABTTX_Pos) -#define CAN_CMD_RRB_Pos 2 //Release Receive Buffer -#define CAN_CMD_RRB_Msk (0x01 << CAN_CMD_RRB_Pos) -#define CAN_CMD_CLROV_Pos 3 //Clear Data Overrun -#define CAN_CMD_CLROV_Msk (0x01 << CAN_CMD_CLROV_Pos) -#define CAN_CMD_SRR_Pos 4 //Self Reception Request -#define CAN_CMD_SRR_Msk (0x01 << CAN_CMD_SRR_Pos) +#define CAN_CR_RST_Pos 0 +#define CAN_CR_RST_Msk (0x01 << CAN_CR_RST_Pos) +#define CAN_CR_LOM_Pos 1 //Listen Only Mode +#define CAN_CR_LOM_Msk (0x01 << CAN_CR_LOM_Pos) +#define CAN_CR_STM_Pos 2 //Self Test Mode, ģʽ¼ʹûӦCANҲԳɹ +#define CAN_CR_STM_Msk (0x01 << CAN_CR_STM_Pos) +#define CAN_CR_AFM_Pos 3 //Acceptance Filter Mode, 1 ˲32λ 0 ˲16λ +#define CAN_CR_AFM_Msk (0x01 << CAN_CR_AFM_Pos) +#define CAN_CR_SLEEP_Pos 4 //д1˯ģʽ߻жʱѲԶλ +#define CAN_CR_SLEEP_Msk (0x01 << CAN_CR_SLEEP_Pos) -#define CAN_SR_RXDA_Pos 0 //Receive Data Available,接收FIFO中有完整消息可以读取 -#define CAN_SR_RXDA_Msk (0x01 << CAN_SR_RXDA_Pos) -#define CAN_SR_RXOV_Pos 1 //Receive FIFO Overrun,新接收的信息由于接收FIFO已满而丢掉 -#define CAN_SR_RXOV_Msk (0x01 << CAN_SR_RXOV_Pos) -#define CAN_SR_TXBR_Pos 2 //Transmit Buffer Release,0 正在处理前面的发送,现在不能写新的消息 1 可以写入新的消息发送 -#define CAN_SR_TXBR_Msk (0x01 << CAN_SR_TXBR_Pos) -#define CAN_SR_TXOK_Pos 3 //Transmit OK,successfully completed -#define CAN_SR_TXOK_Msk (0x01 << CAN_SR_TXOK_Pos) -#define CAN_SR_RXBUSY_Pos 4 //Receive Busy,正在接收 -#define CAN_SR_RXBUSY_Msk (0x01 << CAN_SR_RXBUSY_Pos) -#define CAN_SR_TXBUSY_Pos 5 //Transmit Busy,正在发送 -#define CAN_SR_TXBUSY_Msk (0x01 << CAN_SR_TXBUSY_Pos) -#define CAN_SR_ERRWARN_Pos 6 //1 至少一个错误计数器达到 Warning Limit -#define CAN_SR_ERRWARN_Msk (0x01 << CAN_SR_ERRWARN_Pos) -#define CAN_SR_BUSOFF_Pos 7 //1 CAN 控制器处于总线关闭状态,没有参与到总线活动 -#define CAN_SR_BUSOFF_Msk (0x01 << CAN_SR_BUSOFF_Pos) +#define CAN_CMD_TXREQ_Pos 0 //Transmission Request +#define CAN_CMD_TXREQ_Msk (0x01 << CAN_CMD_TXREQ_Pos) +#define CAN_CMD_ABTTX_Pos 1 //Abort Transmission +#define CAN_CMD_ABTTX_Msk (0x01 << CAN_CMD_ABTTX_Pos) +#define CAN_CMD_RRB_Pos 2 //Release Receive Buffer +#define CAN_CMD_RRB_Msk (0x01 << CAN_CMD_RRB_Pos) +#define CAN_CMD_CLROV_Pos 3 //Clear Data Overrun +#define CAN_CMD_CLROV_Msk (0x01 << CAN_CMD_CLROV_Pos) +#define CAN_CMD_SRR_Pos 4 //Self Reception Request +#define CAN_CMD_SRR_Msk (0x01 << CAN_CMD_SRR_Pos) -#define CAN_IF_RXDA_Pos 0 //IF.RXDA = SR.RXDA & IE.RXDA -#define CAN_IF_RXDA_Msk (0x01 << CAN_IF_RXDA_Pos) -#define CAN_IF_TXBR_Pos 1 //当IE.TXBR=1时,SR.TXBR由0变成1将置位此位 -#define CAN_IF_TXBR_Msk (0x01 << CAN_IF_TXBR_Pos) -#define CAN_IF_ERRWARN_Pos 2 //当IE.ERRWARN=1时,SR.ERRWARN或SR.BUSOFF 0-to-1 或 1-to-0将置位此位 -#define CAN_IF_ERRWARN_Msk (0x01 << CAN_IF_ERRWARN_Pos) -#define CAN_IF_RXOV_Pos 3 //IF.RXOV = SR.RXOV & IE.RXOV -#define CAN_IF_RXOV_Msk (0x01 << CAN_IF_RXOV_Pos) -#define CAN_IF_WKUP_Pos 4 //当IE.WKUP=1时,在睡眠模式下的CAN控制器检测到总线活动时硬件置位 -#define CAN_IF_WKUP_Msk (0x01 << CAN_IF_WKUP_Pos) -#define CAN_IF_ERRPASS_Pos 5 // -#define CAN_IF_ERRPASS_Msk (0x01 << CAN_IF_ERRPASS_Pos) -#define CAN_IF_ARBLOST_Pos 6 //Arbitration Lost,当IE.ARBLOST=1时,CAN控制器丢失仲裁变成接收方时硬件置位 -#define CAN_IF_ARBLOST_Msk (0x01 << CAN_IF_ARBLOST_Pos) -#define CAN_IF_BUSERR_Pos 7 //当IE.BUSERR=1时,CAN控制器检测到总线错误时硬件置位 -#define CAN_IF_BUSERR_Msk (0x01 << CAN_IF_BUSERR_Pos) +#define CAN_SR_RXDA_Pos 0 //Receive Data AvailableFIFOϢԶȡ +#define CAN_SR_RXDA_Msk (0x01 << CAN_SR_RXDA_Pos) +#define CAN_SR_RXOV_Pos 1 //Receive FIFO Overrun½յϢڽFIFO +#define CAN_SR_RXOV_Msk (0x01 << CAN_SR_RXOV_Pos) +#define CAN_SR_TXBR_Pos 2 //Transmit Buffer Release0 ڴǰķͣڲдµϢ 1 дµϢ +#define CAN_SR_TXBR_Msk (0x01 << CAN_SR_TXBR_Pos) +#define CAN_SR_TXOK_Pos 3 //Transmit OKsuccessfully completed +#define CAN_SR_TXOK_Msk (0x01 << CAN_SR_TXOK_Pos) +#define CAN_SR_RXBUSY_Pos 4 //Receive Busyڽ +#define CAN_SR_RXBUSY_Msk (0x01 << CAN_SR_RXBUSY_Pos) +#define CAN_SR_TXBUSY_Pos 5 //Transmit Busyڷ +#define CAN_SR_TXBUSY_Msk (0x01 << CAN_SR_TXBUSY_Pos) +#define CAN_SR_ERRWARN_Pos 6 //1 һﵽ Warning Limit +#define CAN_SR_ERRWARN_Msk (0x01 << CAN_SR_ERRWARN_Pos) +#define CAN_SR_BUSOFF_Pos 7 //1 CAN ߹ر״̬ûв뵽߻ +#define CAN_SR_BUSOFF_Msk (0x01 << CAN_SR_BUSOFF_Pos) -#define CAN_IE_RXDA_Pos 0 -#define CAN_IE_RXDA_Msk (0x01 << CAN_IE_RXDA_Pos) -#define CAN_IE_TXBR_Pos 1 -#define CAN_IE_TXBR_Msk (0x01 << CAN_IE_TXBR_Pos) -#define CAN_IE_ERRWARN_Pos 2 -#define CAN_IE_ERRWARN_Msk (0x01 << CAN_IE_ERRWARN_Pos) -#define CAN_IE_RXOV_Pos 3 -#define CAN_IE_RXOV_Msk (0x01 << CAN_IE_RXOV_Pos) -#define CAN_IE_WKUP_Pos 4 -#define CAN_IE_WKUP_Msk (0x01 << CAN_IE_WKUP_Pos) -#define CAN_IE_ERRPASS_Pos 5 -#define CAN_IE_ERRPASS_Msk (0x01 << CAN_IE_ERRPASS_Pos) -#define CAN_IE_ARBLOST_Pos 6 -#define CAN_IE_ARBLOST_Msk (0x01 << CAN_IE_ARBLOST_Pos) -#define CAN_IE_BUSERR_Pos 7 -#define CAN_IE_BUSERR_Msk (0x01 << CAN_IE_BUSERR_Pos) +#define CAN_IF_RXDA_Pos 0 //IF.RXDA = SR.RXDA & IE.RXDA +#define CAN_IF_RXDA_Msk (0x01 << CAN_IF_RXDA_Pos) +#define CAN_IF_TXBR_Pos 1 //IE.TXBR=1ʱSR.TXBR01λλ +#define CAN_IF_TXBR_Msk (0x01 << CAN_IF_TXBR_Pos) +#define CAN_IF_ERRWARN_Pos 2 //IE.ERRWARN=1ʱSR.ERRWARNSR.BUSOFF 0-to-1 1-to-0λλ +#define CAN_IF_ERRWARN_Msk (0x01 << CAN_IF_ERRWARN_Pos) +#define CAN_IF_RXOV_Pos 3 //IF.RXOV = SR.RXOV & IE.RXOV +#define CAN_IF_RXOV_Msk (0x01 << CAN_IF_RXOV_Pos) +#define CAN_IF_WKUP_Pos 4 //IE.WKUP=1ʱ˯ģʽµCAN⵽߻ʱӲλ +#define CAN_IF_WKUP_Msk (0x01 << CAN_IF_WKUP_Pos) +#define CAN_IF_ERRPASS_Pos 5 // +#define CAN_IF_ERRPASS_Msk (0x01 << CAN_IF_ERRPASS_Pos) +#define CAN_IF_ARBLOST_Pos 6 //Arbitration LostIE.ARBLOST=1ʱCANʧٲñɽշʱӲλ +#define CAN_IF_ARBLOST_Msk (0x01 << CAN_IF_ARBLOST_Pos) +#define CAN_IF_BUSERR_Pos 7 //IE.BUSERR=1ʱCAN⵽ߴʱӲλ +#define CAN_IF_BUSERR_Msk (0x01 << CAN_IF_BUSERR_Pos) -#define CAN_BT0_BRP_Pos 0 //Baud Rate Prescaler,CAN时间单位=2*Tsysclk*(BRP+1) -#define CAN_BT0_BRP_Msk (0x3F << CAN_BT0_BRP_Pos) -#define CAN_BT0_SJW_Pos 6 //Synchronization Jump Width -#define CAN_BT0_SJW_Msk (0x03 << CAN_BT0_SJW_Pos) +#define CAN_IE_RXDA_Pos 0 +#define CAN_IE_RXDA_Msk (0x01 << CAN_IE_RXDA_Pos) +#define CAN_IE_TXBR_Pos 1 +#define CAN_IE_TXBR_Msk (0x01 << CAN_IE_TXBR_Pos) +#define CAN_IE_ERRWARN_Pos 2 +#define CAN_IE_ERRWARN_Msk (0x01 << CAN_IE_ERRWARN_Pos) +#define CAN_IE_RXOV_Pos 3 +#define CAN_IE_RXOV_Msk (0x01 << CAN_IE_RXOV_Pos) +#define CAN_IE_WKUP_Pos 4 +#define CAN_IE_WKUP_Msk (0x01 << CAN_IE_WKUP_Pos) +#define CAN_IE_ERRPASS_Pos 5 +#define CAN_IE_ERRPASS_Msk (0x01 << CAN_IE_ERRPASS_Pos) +#define CAN_IE_ARBLOST_Pos 6 +#define CAN_IE_ARBLOST_Msk (0x01 << CAN_IE_ARBLOST_Pos) +#define CAN_IE_BUSERR_Pos 7 +#define CAN_IE_BUSERR_Msk (0x01 << CAN_IE_BUSERR_Pos) -#define CAN_BT1_TSEG1_Pos 0 //t_tseg1 = CAN时间单位 * (TSEG1+1) -#define CAN_BT1_TSEG1_Msk (0x0F << CAN_BT1_TSEG1_Pos) -#define CAN_BT1_TSEG2_Pos 4 //t_tseg2 = CAN时间单位 * (TSEG2+1) -#define CAN_BT1_TSEG2_Msk (0x07 << CAN_BT1_TSEG2_Pos) -#define CAN_BT1_SAM_Pos 7 //采样次数 0: sampled once 1: sampled three times -#define CAN_BT1_SAM_Msk (0x01 << CAN_BT1_SAM_Pos) +#define CAN_BT0_BRP_Pos 0 //Baud Rate PrescalerCANʱ䵥λ=2*Tsysclk*(BRP+1) +#define CAN_BT0_BRP_Msk (0x3F << CAN_BT0_BRP_Pos) +#define CAN_BT0_SJW_Pos 6 //Synchronization Jump Width +#define CAN_BT0_SJW_Msk (0x03 << CAN_BT0_SJW_Pos) -#define CAN_ECC_SEGCODE_Pos 0 //Segment Code -#define CAN_ECC_SEGCODE_Msk (0x1F << CAN_ECC_SEGCODE_Pos) -#define CAN_ECC_DIR_Pos 5 //0 error occurred during transmission 1 during reception -#define CAN_ECC_DIR_Msk (0x01 << CAN_ECC_DIR_Pos) -#define CAN_ECC_ERRCODE_Pos 6 //Error Code:0 Bit error 1 Form error 2 Stuff error 3 other error -#define CAN_ECC_ERRCODE_Msk (0x03 << CAN_ECC_ERRCODE_Pos) +#define CAN_BT1_TSEG1_Pos 0 //t_tseg1 = CANʱ䵥λ * (TSEG1+1) +#define CAN_BT1_TSEG1_Msk (0x0F << CAN_BT1_TSEG1_Pos) +#define CAN_BT1_TSEG2_Pos 4 //t_tseg2 = CANʱ䵥λ * (TSEG2+1) +#define CAN_BT1_TSEG2_Msk (0x07 << CAN_BT1_TSEG2_Pos) +#define CAN_BT1_SAM_Pos 7 // 0: sampled once 1: sampled three times +#define CAN_BT1_SAM_Msk (0x01 << CAN_BT1_SAM_Pos) -#define CAN_INFO_DLC_Pos 0 //Data Length Control -#define CAN_INFO_DLC_Msk (0x0F << CAN_INFO_DLC_Pos) -#define CAN_INFO_RTR_Pos 6 //Remote Frame,1 远程帧 0 数据帧 -#define CAN_INFO_RTR_Msk (0x01 << CAN_INFO_RTR_Pos) -#define CAN_INFO_FF_Pos 7 //Frame Format,0 标准帧格式 1 扩展帧格式 -#define CAN_INFO_FF_Msk (0x01 << CAN_INFO_FF_Pos) +#define CAN_ECC_SEGCODE_Pos 0 //Segment Code +#define CAN_ECC_SEGCODE_Msk (0x1F << CAN_ECC_SEGCODE_Pos) +#define CAN_ECC_DIR_Pos 5 //0 error occurred during transmission 1 during reception +#define CAN_ECC_DIR_Msk (0x01 << CAN_ECC_DIR_Pos) +#define CAN_ECC_ERRCODE_Pos 6 //Error Code0 Bit error 1 Form error 2 Stuff error 3 other error +#define CAN_ECC_ERRCODE_Msk (0x03 << CAN_ECC_ERRCODE_Pos) -typedef struct -{ - __IO uint32_t IE; //[0] 为0的时候,IF[0]维持为0 +#define CAN_INFO_DLC_Pos 0 //Data Length Control +#define CAN_INFO_DLC_Msk (0x0F << CAN_INFO_DLC_Pos) +#define CAN_INFO_RTR_Pos 6 //Remote Frame1 Զ֡ 0 ֡ +#define CAN_INFO_RTR_Msk (0x01 << CAN_INFO_RTR_Pos) +#define CAN_INFO_FF_Pos 7 //Frame Format0 ׼֡ʽ 1 չ֡ʽ +#define CAN_INFO_FF_Msk (0x01 << CAN_INFO_FF_Pos) - __IO uint32_t IF; //[0] 当完成指定长度的数据传输时置1,写1清零 - __IO uint32_t IM; //[0] 当该寄存器为1时,LCDC的中断不会输出给系统的中断控制寄存器 + +typedef struct { + __IO uint32_t IE; //[0] Ϊ0ʱIF[0]άΪ0 + + __IO uint32_t IF; //[0] ָȵݴʱ1д1 + + __IO uint32_t IM; //[0] üĴΪ1ʱLCDCжϲϵͳжϿƼĴ + __IO uint32_t START; - - __IO uint32_t SRCADDR; //数据源地址寄存器,必须字对齐(即地址的低2位必须是0) - + + __IO uint32_t SRCADDR; //ԴַĴֶ루ַĵ2λ0 + __IO uint32_t CR0; - + __IO uint32_t CR1; - - __IO uint32_t PRECMDV; //在MPU接口中,发送数据前,RS拉低的那一拍,数据总线上的值 + + __IO uint32_t PRECMDV; //MPUӿУǰRS͵һģϵֵ } LCD_TypeDef; -#define LCD_START_MPUEN_Pos 0 //0 RGB接口 1 MPU接口 -#define LCD_START_MPUEN_Msk (0x01 << LCD_START_MPUEN_Pos) -#define LCD_START_GO_Pos 1 //写1开始传输数据,数据传输结束后自动清零 -#define LCD_START_GO_Msk (0x01 << LCD_START_GO_Pos) -#define LCD_START_BURST_Pos 2 -#define LCD_START_BURST_Msk (0x01 << LCD_START_BURST_Pos) -#define LCD_CR0_VPIX_Pos 0 //当portrait为0时,表示垂直方向的像素个数,0表示1个,最大为767 \ - //当portrait为1时,表示水平方向的像素个数,0表示1个,最大为767 -#define LCD_CR0_VPIX_Msk (0x3FF << LCD_CR0_VPIX_Pos) -#define LCD_CR0_HPIX_Pos 10 //当portrait为0时,表示水平方向的像素个数,0表示1个,最大为1023 \ - //当portrait为1时,表示垂直方向的像素个数,0表示1个,最大为1023 -#define LCD_CR0_HPIX_Msk (0x3FF << LCD_CR0_HPIX_Pos) -#define LCD_CR0_DCLK_Pos 20 //0 DOTCLK一直翻转 1 DOTCLK在空闲时停在1 -#define LCD_CR0_DCLK_Msk (0x01 << LCD_CR0_DCLK_Pos) -#define LCD_CR0_HLOW_Pos 21 //输出HSYNC低电平持续多少个DOTCLK周期,0表示1个周期 -#define LCD_CR0_HLOW_Msk (0x03 << LCD_CR0_HLOW_Pos) +#define LCD_START_GO_Pos 1 //д1ʼݣݴԶ +#define LCD_START_GO_Msk (0x01 << LCD_START_GO_Pos) +#define LCD_START_BURST_Pos 2 +#define LCD_START_BURST_Msk (0x01 << LCD_START_BURST_Pos) -#define LCD_CR1_VFP_Pos 1 -#define LCD_CR1_VFP_Msk (0x07 << LCD_CR1_VFP_Pos) -#define LCD_CR1_VBP_Pos 4 -#define LCD_CR1_VBP_Msk (0x1F << LCD_CR1_VBP_Pos) -#define LCD_CR1_HFP_Pos 9 -#define LCD_CR1_HFP_Msk (0x1F << LCD_CR1_HFP_Pos) -#define LCD_CR1_HBP_Pos 14 -#define LCD_CR1_HBP_Msk (0x7F << LCD_CR1_HBP_Pos) -#define LCD_CR1_DCLKDIV_Pos 21 //DOTCLK相对于模块时钟的分频比,0表示2分频,1表示4分频 ... -#define LCD_CR1_DCLKDIV_Msk (0x1F << LCD_CR1_DCLKDIV_Pos) -#define LCD_CR1_DCLKINV_Pos 26 //1 输出DOTCLK反向,应用于用DOTCLK下降沿采样数据的屏 -#define LCD_CR1_DCLKINV_Msk (0x01 << LCD_CR1_DCLKINV_Pos) +#define LCD_CR0_VPIX_Pos 0 //portraitΪ0ʱʾֱظ0ʾ1Ϊ767 + //portraitΪ1ʱʾˮƽظ0ʾ1Ϊ767 +#define LCD_CR0_VPIX_Msk (0x3FF << LCD_CR0_VPIX_Pos) +#define LCD_CR0_HPIX_Pos 10 //portraitΪ0ʱʾˮƽظ0ʾ1Ϊ1023 + //portraitΪ1ʱʾֱظ0ʾ1Ϊ1023 +#define LCD_CR0_HPIX_Msk (0x3FF << LCD_CR0_HPIX_Pos) +#define LCD_CR0_DCLK_Pos 20 //0 DOTCLKһֱת 1 DOTCLKڿʱͣ1 +#define LCD_CR0_DCLK_Msk (0x01 << LCD_CR0_DCLK_Pos) +#define LCD_CR0_HLOW_Pos 21 //HSYNC͵ƽٸDOTCLKڣ0ʾ1 +#define LCD_CR0_HLOW_Msk (0x03 << LCD_CR0_HLOW_Pos) -typedef struct -{ +#define LCD_CR1_VFP_Pos 1 +#define LCD_CR1_VFP_Msk (0x07 << LCD_CR1_VFP_Pos) +#define LCD_CR1_VBP_Pos 4 +#define LCD_CR1_VBP_Msk (0x1F << LCD_CR1_VBP_Pos) +#define LCD_CR1_HFP_Pos 9 +#define LCD_CR1_HFP_Msk (0x1F << LCD_CR1_HFP_Pos) +#define LCD_CR1_HBP_Pos 14 +#define LCD_CR1_HBP_Msk (0x7F << LCD_CR1_HBP_Pos) +#define LCD_CR1_DCLKDIV_Pos 21 //DOTCLKģʱӵķƵȣ0ʾ2Ƶ1ʾ4Ƶ ... +#define LCD_CR1_DCLKDIV_Msk (0x1F << LCD_CR1_DCLKDIV_Pos) +#define LCD_CR1_DCLKINV_Pos 26 //1 DOTCLKӦDOTCLK½زݵ +#define LCD_CR1_DCLKINV_Msk (0x01 << LCD_CR1_DCLKINV_Pos) + + + + +typedef struct { __IO uint32_t DMA_MEM_ADDR; - - __IO uint32_t BLK; //Block Size and Count - - __IO uint32_t ARG; //Argument - - __IO uint32_t CMD; //Command - - __IO uint32_t RESP[4]; //Response - + + __IO uint32_t BLK; //Block Size and Count + + __IO uint32_t ARG; //Argument + + __IO uint32_t CMD; //Command + + __IO uint32_t RESP[4]; //Response + __IO uint32_t DATA; - + __IO uint32_t STAT; - + __IO uint32_t CR1; - + __IO uint32_t CR2; - + __IO uint32_t IF; - - __IO uint32_t IFE; //Interrupt Flag Enable - - __IO uint32_t IE; //Interrupt Enalbe - + + __IO uint32_t IFE; //Interrupt Flag Enable + + __IO uint32_t IE; //Interrupt Enalbe + __IO uint32_t CMD12ERR; - + __IO uint32_t INFO; - + __IO uint32_t MAXCURR; } SDIO_TypeDef; -#define SDIO_BLK_SIZE_Pos 0 //0x200 512字节 0x400 1024字节 0x800 2048字节 -#define SDIO_BLK_SIZE_Msk (0xFFF << SDIO_BLK_SIZE_Pos) -#define SDIO_BLK_COUNT_Pos 16 //0 Stop Transfer 1 1块 2 2块 ... ... -#define SDIO_BLK_COUNT_Msk (0xFFF << SDIO_BLK_COUNT_Pos) -#define SDIO_CMD_DMAEN_Pos 0 -#define SDIO_CMD_DMAEN_Msk (0x01 << SDIO_CMD_DMAEN_Pos) -#define SDIO_CMD_BLKCNTEN_Pos 1 -#define SDIO_CMD_BLKCNTEN_Msk (0x01 << SDIO_CMD_BLKCNTEN_Pos) -#define SDIO_CMD_AUTOCMD12_Pos 2 -#define SDIO_CMD_AUTOCMD12_Msk (0x01 << SDIO_CMD_AUTOCMD12_Pos) -#define SDIO_CMD_DIRREAD_Pos 4 //0 Write, Host to Card 1 Read, Card to Host -#define SDIO_CMD_DIRREAD_Msk (0x01 << SDIO_CMD_DIRREAD_Pos) -#define SDIO_CMD_MULTBLK_Pos 5 //0 Single Block 1 Multiple Block -#define SDIO_CMD_MULTBLK_Msk (0x01 << SDIO_CMD_MULTBLK_Pos) -#define SDIO_CMD_RESPTYPE_Pos 16 //响应类型,0 无响应 1 136位响应 2 48位响应 3 48位响应,Busy after response -#define SDIO_CMD_RESPTYPE_Msk (0x03 << SDIO_CMD_RESPTYPE_Pos) -#define SDIO_CMD_CRCCHECK_Pos 19 //Command CRC Check Enable -#define SDIO_CMD_CRCCHECK_Msk (0x01 << SDIO_CMD_CRCCHECK_Pos) -#define SDIO_CMD_IDXCHECK_Pos 20 //Command Index Check Enable -#define SDIO_CMD_IDXCHECK_Msk (0x01 << SDIO_CMD_IDXCHECK_Pos) -#define SDIO_CMD_HAVEDATA_Pos 21 //0 No Data Present 1 Data Present -#define SDIO_CMD_HAVEDATA_Msk (0x01 << SDIO_CMD_HAVEDATA_Pos) -#define SDIO_CMD_CMDTYPE_Pos 22 //0 NORMAL 1 SUSPEND 2 RESUME 3 ABORT -#define SDIO_CMD_CMDTYPE_Msk (0x03 << SDIO_CMD_CMDTYPE_Pos) -#define SDIO_CMD_CMDINDX_Pos 24 //Command Index,CMD0-63、ACMD0-63 -#define SDIO_CMD_CMDINDX_Msk (0x3F << SDIO_CMD_CMDINDX_Pos) +#define SDIO_BLK_SIZE_Pos 0 //0x200 512ֽ 0x400 1024ֽ 0x800 2048ֽ +#define SDIO_BLK_SIZE_Msk (0xFFF << SDIO_BLK_SIZE_Pos) +#define SDIO_BLK_COUNT_Pos 16 //0 Stop Transfer 1 1 2 2 ... ... +#define SDIO_BLK_COUNT_Msk (0xFFF << SDIO_BLK_COUNT_Pos) -#define SDIO_CR1_4BIT_Pos 1 //1 4 bit mode 0 1 bit mode -#define SDIO_CR1_4BIT_Msk (0x01 << SDIO_CR1_4BIT_Pos) -#define SDIO_CR1_8BIT_Pos 5 //1 8 bit mode is selected 0 8 bit mode is not selected -#define SDIO_CR1_8BIT_Msk (0x01 << SDIO_CR1_8BIT_Pos) -#define SDIO_CR1_CDBIT_Pos 6 //0 No Card 1 Card Inserted -#define SDIO_CR1_CDBIT_Msk (0x01 << SDIO_CR1_CDBIT_Pos) -#define SDIO_CR1_CDSRC_Pos 7 //Card Detect Source, 1 CR1.CDBIT位 0 SD_Detect引脚 -#define SDIO_CR1_CDSRC_Msk (0x01 << SDIO_CR1_CDSRC_Pos) -#define SDIO_CR1_PWRON_Pos 8 //1 Power on 0 Power off -#define SDIO_CR1_PWRON_Msk (0x01 << SDIO_CR1_PWRON_Pos) -#define SDIO_CR1_VOLT_Pos 9 //7 3.3V 6 3.0V 5 1.8V -#define SDIO_CR1_VOLT_Msk (0x07 << SDIO_CR1_VOLT_Pos) +#define SDIO_CMD_DMAEN_Pos 0 +#define SDIO_CMD_DMAEN_Msk (0x01 << SDIO_CMD_DMAEN_Pos) +#define SDIO_CMD_BLKCNTEN_Pos 1 +#define SDIO_CMD_BLKCNTEN_Msk (0x01 << SDIO_CMD_BLKCNTEN_Pos) +#define SDIO_CMD_AUTOCMD12_Pos 2 +#define SDIO_CMD_AUTOCMD12_Msk (0x01 << SDIO_CMD_AUTOCMD12_Pos) +#define SDIO_CMD_DIRREAD_Pos 4 //0 Write, Host to Card 1 Read, Card to Host +#define SDIO_CMD_DIRREAD_Msk (0x01 << SDIO_CMD_DIRREAD_Pos) +#define SDIO_CMD_MULTBLK_Pos 5 //0 Single Block 1 Multiple Block +#define SDIO_CMD_MULTBLK_Msk (0x01 << SDIO_CMD_MULTBLK_Pos) +#define SDIO_CMD_RESPTYPE_Pos 16 //Ӧͣ0 Ӧ 1 136λӦ 2 48λӦ 3 48λӦBusy after response +#define SDIO_CMD_RESPTYPE_Msk (0x03 << SDIO_CMD_RESPTYPE_Pos) +#define SDIO_CMD_CRCCHECK_Pos 19 //Command CRC Check Enable +#define SDIO_CMD_CRCCHECK_Msk (0x01 << SDIO_CMD_CRCCHECK_Pos) +#define SDIO_CMD_IDXCHECK_Pos 20 //Command Index Check Enable +#define SDIO_CMD_IDXCHECK_Msk (0x01 << SDIO_CMD_IDXCHECK_Pos) +#define SDIO_CMD_HAVEDATA_Pos 21 //0 No Data Present 1 Data Present +#define SDIO_CMD_HAVEDATA_Msk (0x01 << SDIO_CMD_HAVEDATA_Pos) +#define SDIO_CMD_CMDTYPE_Pos 22 //0 NORMAL 1 SUSPEND 2 RESUME 3 ABORT +#define SDIO_CMD_CMDTYPE_Msk (0x03 << SDIO_CMD_CMDTYPE_Pos) +#define SDIO_CMD_CMDINDX_Pos 24 //Command IndexCMD0-63ACMD0-63 +#define SDIO_CMD_CMDINDX_Msk (0x3F << SDIO_CMD_CMDINDX_Pos) -#define SDIO_CR2_CLKEN_Pos 0 //Internal Clock Enable -#define SDIO_CR2_CLKEN_Msk (0x01 << SDIO_CR2_CLKEN_Pos) -#define SDIO_CR2_CLKRDY_Pos 1 //Internal Clock Stable/Ready -#define SDIO_CR2_CLKRDY_Msk (0x01 << SDIO_CR2_CLKRDY_Pos) -#define SDIO_CR2_SDCLKEN_Pos 2 //SDCLK Enable -#define SDIO_CR2_SDCLKEN_Msk (0x01 << SDIO_CR2_SDCLKEN_Pos) -#define SDIO_CR2_SDCLKDIV_Pos 8 //SDCLK Frequency Div, 0x00 不分频 0x01 2分频 0x02 4分频 0x04 8分频 0x08 16分频 ... 0x80 256分频 -#define SDIO_CR2_SDCLKDIV_Msk (0xFF << SDIO_CR2_SDCLKDIV_Pos) -#define SDIO_CR2_TIMEOUT_Pos 16 //0 TMCLK*2^13 1 TMCLK*2^14 ... 14 TMCLK*2^27 -#define SDIO_CR2_TIMEOUT_Msk (0x0F << SDIO_CR2_TIMEOUT_Pos) -#define SDIO_CR2_RSTALL_Pos 24 //Software Reset for All -#define SDIO_CR2_RSTALL_Msk (0x01 << SDIO_CR2_RSTALL_Pos) -#define SDIO_CR2_RSTCMD_Pos 25 //Software Reset for CMD Line -#define SDIO_CR2_RSTCMD_Msk (0x01 << SDIO_CR2_RSTCMD_Pos) -#define SDIO_CR2_RSTDAT_Pos 26 //Software Reset for DAT Line -#define SDIO_CR2_RSTDAT_Msk (0x01 << SDIO_CR2_RSTDAT_Pos) +#define SDIO_CR1_4BIT_Pos 1 //1 4 bit mode 0 1 bit mode +#define SDIO_CR1_4BIT_Msk (0x01 << SDIO_CR1_4BIT_Pos) +#define SDIO_CR1_8BIT_Pos 5 //1 8 bit mode is selected 0 8 bit mode is not selected +#define SDIO_CR1_8BIT_Msk (0x01 << SDIO_CR1_8BIT_Pos) +#define SDIO_CR1_CDBIT_Pos 6 //0 No Card 1 Card Inserted +#define SDIO_CR1_CDBIT_Msk (0x01 << SDIO_CR1_CDBIT_Pos) +#define SDIO_CR1_CDSRC_Pos 7 //Card Detect Source, 1 CR1.CDBITλ 0 SD_Detect +#define SDIO_CR1_CDSRC_Msk (0x01 << SDIO_CR1_CDSRC_Pos) +#define SDIO_CR1_PWRON_Pos 8 //1 Power on 0 Power off +#define SDIO_CR1_PWRON_Msk (0x01 << SDIO_CR1_PWRON_Pos) +#define SDIO_CR1_VOLT_Pos 9 //7 3.3V 6 3.0V 5 1.8V +#define SDIO_CR1_VOLT_Msk (0x07 << SDIO_CR1_VOLT_Pos) -#define SDIO_IF_CMDDONE_Pos 0 -#define SDIO_IF_CMDDONE_Msk (0x01 << SDIO_IF_CMDDONE_Pos) -#define SDIO_IF_TRXDONE_Pos 1 -#define SDIO_IF_TRXDONE_Msk (0x01 << SDIO_IF_TRXDONE_Pos) -#define SDIO_IF_BLKGAP_Pos 2 -#define SDIO_IF_BLKGAP_Msk (0x01 << SDIO_IF_BLKGAP_Pos) -#define SDIO_IF_DMADONE_Pos 3 -#define SDIO_IF_DMADONE_Msk (0x01 << SDIO_IF_DMADONE_Pos) -#define SDIO_IF_BUFWRRDY_Pos 4 -#define SDIO_IF_BUFWRRDY_Msk (0x01 << SDIO_IF_BUFWRRDY_Pos) -#define SDIO_IF_BUFRDRDY_Pos 5 -#define SDIO_IF_BUFRDRDY_Msk (0x01 << SDIO_IF_BUFRDRDY_Pos) -#define SDIO_IF_CARDINSR_Pos 6 -#define SDIO_IF_CARDINSR_Msk (0x01 << SDIO_IF_CARDINSR_Pos) -#define SDIO_IF_CARDRMOV_Pos 7 -#define SDIO_IF_CARDRMOV_Msk (0x01 << SDIO_IF_CARDRMOV_Pos) -#define SDIO_IF_CARD_Pos 8 -#define SDIO_IF_CARD_Msk (0x01 << SDIO_IF_CARD_Pos) -#define SDIO_IF_ERROR_Pos 15 -#define SDIO_IF_ERROR_Msk (0x01 << SDIO_IF_ERROR_Pos) -#define SDIO_IF_CMDTIMEOUT_Pos 16 -#define SDIO_IF_CMDTIMEOUT_Msk (0x01 << SDIO_IF_CMDTIMEOUT_Pos) -#define SDIO_IF_CMDCRCERR_Pos 17 -#define SDIO_IF_CMDCRCERR_Msk (0x01 << SDIO_IF_CMDCRCERR_Pos) -#define SDIO_IF_CMDENDERR_Pos 18 -#define SDIO_IF_CMDENDERR_Msk (0x01 << SDIO_IF_CMDENDCERR_Pos) -#define SDIO_IF_CMDIDXERR_Pos 19 -#define SDIO_IF_CMDIDXERR_Msk (0x01 << SDIO_IF_CMDIDXCERR_Pos) -#define SDIO_IF_DATTIMEOUT_Pos 20 -#define SDIO_IF_DATTIMEOUT_Msk (0x01 << SDIO_IF_DATTIMEOUT_Pos) -#define SDIO_IF_DATCRCERR_Pos 21 -#define SDIO_IF_DATCRCERR_Msk (0x01 << SDIO_IF_DATCRCERR_Pos) -#define SDIO_IF_DATENDERR_Pos 22 -#define SDIO_IF_DATENDERR_Msk (0x01 << SDIO_IF_DATENDCERR_Pos) -#define SDIO_IF_CURLIMERR_Pos 23 -#define SDIO_IF_CURLIMERR_Msk (0x01 << SDIO_IF_CURLIMERR_Pos) -#define SDIO_IF_CMD12ERR_Pos 24 -#define SDIO_IF_CMD12ERR_Msk (0x01 << SDIO_IF_CMD12ERR_Pos) -#define SDIO_IF_DMAERR_Pos 25 -#define SDIO_IF_DMAERR_Msk (0x01 << SDIO_IF_DMAERR_Pos) -#define SDIO_IF_RESPERR_Pos 28 -#define SDIO_IF_RESPERR_Msk (0x01 << SDIO_IF_RESPERR_Pos) +#define SDIO_CR2_CLKEN_Pos 0 //Internal Clock Enable +#define SDIO_CR2_CLKEN_Msk (0x01 << SDIO_CR2_CLKEN_Pos) +#define SDIO_CR2_CLKRDY_Pos 1 //Internal Clock Stable/Ready +#define SDIO_CR2_CLKRDY_Msk (0x01 << SDIO_CR2_CLKRDY_Pos) +#define SDIO_CR2_SDCLKEN_Pos 2 //SDCLK Enable +#define SDIO_CR2_SDCLKEN_Msk (0x01 << SDIO_CR2_SDCLKEN_Pos) +#define SDIO_CR2_SDCLKDIV_Pos 8 //SDCLK Frequency Div, 0x00 Ƶ 0x01 2Ƶ 0x02 4Ƶ 0x04 8Ƶ 0x08 16Ƶ ... 0x80 256Ƶ +#define SDIO_CR2_SDCLKDIV_Msk (0xFF << SDIO_CR2_SDCLKDIV_Pos) +#define SDIO_CR2_TIMEOUT_Pos 16 //0 TMCLK*2^13 1 TMCLK*2^14 ... 14 TMCLK*2^27 +#define SDIO_CR2_TIMEOUT_Msk (0x0F << SDIO_CR2_TIMEOUT_Pos) +#define SDIO_CR2_RSTALL_Pos 24 //Software Reset for All +#define SDIO_CR2_RSTALL_Msk (0x01 << SDIO_CR2_RSTALL_Pos) +#define SDIO_CR2_RSTCMD_Pos 25 //Software Reset for CMD Line +#define SDIO_CR2_RSTCMD_Msk (0x01 << SDIO_CR2_RSTCMD_Pos) +#define SDIO_CR2_RSTDAT_Pos 26 //Software Reset for DAT Line +#define SDIO_CR2_RSTDAT_Msk (0x01 << SDIO_CR2_RSTDAT_Pos) -#define SDIO_IE_CMDDONE_Pos 0 //Command Complete Status Enable -#define SDIO_IE_CMDDONE_Msk (0x01 << SDIO_IE_CMDDONE_Pos) -#define SDIO_IE_TRXDONE_Pos 1 //Transfer Complete Status Enable -#define SDIO_IE_TRXDONE_Msk (0x01 << SDIO_IE_TRXDONE_Pos) -#define SDIO_IE_BLKGAP_Pos 2 //Block Gap Event Status Enable -#define SDIO_IE_BLKGAP_Msk (0x01 << SDIO_IE_BLKGAP_Pos) -#define SDIO_IE_DMADONE_Pos 3 //DMA Interrupt Status Enable -#define SDIO_IE_DMADONE_Msk (0x01 << SDIO_IE_DMADONE_Pos) -#define SDIO_IE_BUFWRRDY_Pos 4 //Buffer Write Ready Status Enable -#define SDIO_IE_BUFWRRDY_Msk (0x01 << SDIO_IE_BUFWRRDY_Pos) -#define SDIO_IE_BUFRDRDY_Pos 5 //Buffer Read Ready Status Enable -#define SDIO_IE_BUFRDRDY_Msk (0x01 << SDIO_IE_BUFRDRDY_Pos) -#define SDIO_IE_CARDINSR_Pos 6 //Card Insertion Status Enable -#define SDIO_IE_CARDINSR_Msk (0x01 << SDIO_IE_CARDINSR_Pos) -#define SDIO_IE_CARDRMOV_Pos 7 //Card Removal Status Enable -#define SDIO_IE_CARDRMOV_Msk (0x01 << SDIO_IE_CARDRMOV_Pos) -#define SDIO_IE_CARD_Pos 8 -#define SDIO_IE_CARD_Msk (0x01 << SDIO_IE_CARD_Pos) -#define SDIO_IE_CMDTIMEOUT_Pos 16 //Command Timeout Error Status Enable -#define SDIO_IE_CMDTIMEOUT_Msk (0x01 << SDIO_IE_CMDTIMEOUT_Pos) -#define SDIO_IE_CMDCRCERR_Pos 17 //Command CRC Error Status Enable -#define SDIO_IE_CMDCRCERR_Msk (0x01 << SDIO_IE_CMDCRCERR_Pos) -#define SDIO_IE_CMDENDERR_Pos 18 //Command End Bit Error Status Enable -#define SDIO_IE_CMDENDERR_Msk (0x01 << SDIO_IE_CMDENDCERR_Pos) -#define SDIO_IE_CMDIDXERR_Pos 19 //Command Index Error Status Enable -#define SDIO_IE_CMDIDXERR_Msk (0x01 << SDIO_IE_CMDIDXCERR_Pos) -#define SDIO_IE_DATTIMEOUT_Pos 20 //Data Timeout Error Status Enable -#define SDIO_IE_DATTIMEOUT_Msk (0x01 << SDIO_IE_DATTIMEOUT_Pos) -#define SDIO_IE_DATCRCERR_Pos 21 //Data CRC Error Status Enable -#define SDIO_IE_DATCRCERR_Msk (0x01 << SDIO_IE_DATCRCERR_Pos) -#define SDIO_IE_DATENDERR_Pos 22 //Data End Bit Error Status Enable -#define SDIO_IE_DATENDERR_Msk (0x01 << SDIO_IE_DATENDCERR_Pos) -#define SDIO_IE_CURLIMERR_Pos 23 //Current Limit Error Status Enable -#define SDIO_IE_CURLIMERR_Msk (0x01 << SDIO_IE_CURLIMERR_Pos) -#define SDIO_IE_CMD12ERR_Pos 24 //Auto CMD12 Error Status Enable -#define SDIO_IE_CMD12ERR_Msk (0x01 << SDIO_IE_CMD12ERR_Pos) -#define SDIO_IE_DMAERR_Pos 25 //ADMA Error Status Enable -#define SDIO_IE_DMAERR_Msk (0x01 << SDIO_IE_DMAERR_Pos) -#define SDIO_IE_RESPERR_Pos 28 //Target Response Error Status Enable -#define SDIO_IE_RESPERR_Msk (0x01 << SDIO_IE_RESPERR_Pos) +#define SDIO_IF_CMDDONE_Pos 0 +#define SDIO_IF_CMDDONE_Msk (0x01 << SDIO_IF_CMDDONE_Pos) +#define SDIO_IF_TRXDONE_Pos 1 +#define SDIO_IF_TRXDONE_Msk (0x01 << SDIO_IF_TRXDONE_Pos) +#define SDIO_IF_BLKGAP_Pos 2 +#define SDIO_IF_BLKGAP_Msk (0x01 << SDIO_IF_BLKGAP_Pos) +#define SDIO_IF_DMADONE_Pos 3 +#define SDIO_IF_DMADONE_Msk (0x01 << SDIO_IF_DMADONE_Pos) +#define SDIO_IF_BUFWRRDY_Pos 4 +#define SDIO_IF_BUFWRRDY_Msk (0x01 << SDIO_IF_BUFWRRDY_Pos) +#define SDIO_IF_BUFRDRDY_Pos 5 +#define SDIO_IF_BUFRDRDY_Msk (0x01 << SDIO_IF_BUFRDRDY_Pos) +#define SDIO_IF_CARDINSR_Pos 6 +#define SDIO_IF_CARDINSR_Msk (0x01 << SDIO_IF_CARDINSR_Pos) +#define SDIO_IF_CARDRMOV_Pos 7 +#define SDIO_IF_CARDRMOV_Msk (0x01 << SDIO_IF_CARDRMOV_Pos) +#define SDIO_IF_CARD_Pos 8 +#define SDIO_IF_CARD_Msk (0x01 << SDIO_IF_CARD_Pos) +#define SDIO_IF_ERROR_Pos 15 +#define SDIO_IF_ERROR_Msk (0x01 << SDIO_IF_ERROR_Pos) +#define SDIO_IF_CMDTIMEOUT_Pos 16 +#define SDIO_IF_CMDTIMEOUT_Msk (0x01 << SDIO_IF_CMDTIMEOUT_Pos) +#define SDIO_IF_CMDCRCERR_Pos 17 +#define SDIO_IF_CMDCRCERR_Msk (0x01 << SDIO_IF_CMDCRCERR_Pos) +#define SDIO_IF_CMDENDERR_Pos 18 +#define SDIO_IF_CMDENDERR_Msk (0x01 << SDIO_IF_CMDENDCERR_Pos) +#define SDIO_IF_CMDIDXERR_Pos 19 +#define SDIO_IF_CMDIDXERR_Msk (0x01 << SDIO_IF_CMDIDXCERR_Pos) +#define SDIO_IF_DATTIMEOUT_Pos 20 +#define SDIO_IF_DATTIMEOUT_Msk (0x01 << SDIO_IF_DATTIMEOUT_Pos) +#define SDIO_IF_DATCRCERR_Pos 21 +#define SDIO_IF_DATCRCERR_Msk (0x01 << SDIO_IF_DATCRCERR_Pos) +#define SDIO_IF_DATENDERR_Pos 22 +#define SDIO_IF_DATENDERR_Msk (0x01 << SDIO_IF_DATENDCERR_Pos) +#define SDIO_IF_CURLIMERR_Pos 23 +#define SDIO_IF_CURLIMERR_Msk (0x01 << SDIO_IF_CURLIMERR_Pos) +#define SDIO_IF_CMD12ERR_Pos 24 +#define SDIO_IF_CMD12ERR_Msk (0x01 << SDIO_IF_CMD12ERR_Pos) +#define SDIO_IF_DMAERR_Pos 25 +#define SDIO_IF_DMAERR_Msk (0x01 << SDIO_IF_DMAERR_Pos) +#define SDIO_IF_RESPERR_Pos 28 +#define SDIO_IF_RESPERR_Msk (0x01 << SDIO_IF_RESPERR_Pos) -#define SDIO_IM_CMDDONE_Pos 0 -#define SDIO_IM_CMDDONE_Msk (0x01 << SDIO_IM_CMDDONE_Pos) -#define SDIO_IM_TRXDONE_Pos 1 -#define SDIO_IM_TRXDONE_Msk (0x01 << SDIO_IM_TRXDONE_Pos) -#define SDIO_IM_BLKGAP_Pos 2 -#define SDIO_IM_BLKGAP_Msk (0x01 << SDIO_IM_BLKGAP_Pos) -#define SDIO_IM_DMADONE_Pos 3 -#define SDIO_IM_DMADONE_Msk (0x01 << SDIO_IM_DMADONE_Pos) -#define SDIO_IM_BUFWRRDY_Pos 4 -#define SDIO_IM_BUFWRRDY_Msk (0x01 << SDIO_IM_BUFWRRDY_Pos) -#define SDIO_IM_BUFRDRDY_Pos 5 -#define SDIO_IM_BUFRDRDY_Msk (0x01 << SDIO_IM_BUFRDRDY_Pos) -#define SDIO_IM_CARDINSR_Pos 6 -#define SDIO_IM_CARDINSR_Msk (0x01 << SDIO_IM_CARDINSR_Pos) -#define SDIO_IM_CARDRMOV_Pos 7 -#define SDIO_IM_CARDRMOV_Msk (0x01 << SDIO_IM_CARDRMOV_Pos) -#define SDIO_IM_CARD_Pos 8 -#define SDIO_IM_CARD_Msk (0x01 << SDIO_IM_CARD_Pos) -#define SDIO_IM_CMDTIMEOUT_Pos 16 -#define SDIO_IM_CMDTIMEOUT_Msk (0x01 << SDIO_IM_CMDTIMEOUT_Pos) -#define SDIO_IM_CMDCRCERR_Pos 17 -#define SDIO_IM_CMDCRCERR_Msk (0x01 << SDIO_IM_CMDCRCERR_Pos) -#define SDIO_IM_CMDENDERR_Pos 18 -#define SDIO_IM_CMDENDERR_Msk (0x01 << SDIO_IM_CMDENDCERR_Pos) -#define SDIO_IM_CMDIDXERR_Pos 19 -#define SDIO_IM_CMDIDXERR_Msk (0x01 << SDIO_IM_CMDIDXCERR_Pos) -#define SDIO_IM_DATTIMEOUT_Pos 20 -#define SDIO_IM_DATTIMEOUT_Msk (0x01 << SDIO_IM_DATTIMEOUT_Pos) -#define SDIO_IM_DATCRCERR_Pos 21 -#define SDIO_IM_DATCRCERR_Msk (0x01 << SDIO_IM_DATCRCERR_Pos) -#define SDIO_IM_DATENDERR_Pos 22 -#define SDIO_IM_DATENDERR_Msk (0x01 << SDIO_IM_DATENDCERR_Pos) -#define SDIO_IM_CURLIMERR_Pos 23 -#define SDIO_IM_CURLIMERR_Msk (0x01 << SDIO_IM_CURLIMERR_Pos) -#define SDIO_IM_CMD12ERR_Pos 24 -#define SDIO_IM_CMD12ERR_Msk (0x01 << SDIO_IM_CMD12ERR_Pos) -#define SDIO_IM_DMAERR_Pos 25 -#define SDIO_IM_DMAERR_Msk (0x01 << SDIO_IM_DMAERR_Pos) -#define SDIO_IM_RESPERR_Pos 28 -#define SDIO_IM_RESPERR_Msk (0x01 << SDIO_IM_RESPERR_Pos) +#define SDIO_IE_CMDDONE_Pos 0 //Command Complete Status Enable +#define SDIO_IE_CMDDONE_Msk (0x01 << SDIO_IE_CMDDONE_Pos) +#define SDIO_IE_TRXDONE_Pos 1 //Transfer Complete Status Enable +#define SDIO_IE_TRXDONE_Msk (0x01 << SDIO_IE_TRXDONE_Pos) +#define SDIO_IE_BLKGAP_Pos 2 //Block Gap Event Status Enable +#define SDIO_IE_BLKGAP_Msk (0x01 << SDIO_IE_BLKGAP_Pos) +#define SDIO_IE_DMADONE_Pos 3 //DMA Interrupt Status Enable +#define SDIO_IE_DMADONE_Msk (0x01 << SDIO_IE_DMADONE_Pos) +#define SDIO_IE_BUFWRRDY_Pos 4 //Buffer Write Ready Status Enable +#define SDIO_IE_BUFWRRDY_Msk (0x01 << SDIO_IE_BUFWRRDY_Pos) +#define SDIO_IE_BUFRDRDY_Pos 5 //Buffer Read Ready Status Enable +#define SDIO_IE_BUFRDRDY_Msk (0x01 << SDIO_IE_BUFRDRDY_Pos) +#define SDIO_IE_CARDINSR_Pos 6 //Card Insertion Status Enable +#define SDIO_IE_CARDINSR_Msk (0x01 << SDIO_IE_CARDINSR_Pos) +#define SDIO_IE_CARDRMOV_Pos 7 //Card Removal Status Enable +#define SDIO_IE_CARDRMOV_Msk (0x01 << SDIO_IE_CARDRMOV_Pos) +#define SDIO_IE_CARD_Pos 8 +#define SDIO_IE_CARD_Msk (0x01 << SDIO_IE_CARD_Pos) +#define SDIO_IE_CMDTIMEOUT_Pos 16 //Command Timeout Error Status Enable +#define SDIO_IE_CMDTIMEOUT_Msk (0x01 << SDIO_IE_CMDTIMEOUT_Pos) +#define SDIO_IE_CMDCRCERR_Pos 17 //Command CRC Error Status Enable +#define SDIO_IE_CMDCRCERR_Msk (0x01 << SDIO_IE_CMDCRCERR_Pos) +#define SDIO_IE_CMDENDERR_Pos 18 //Command End Bit Error Status Enable +#define SDIO_IE_CMDENDERR_Msk (0x01 << SDIO_IE_CMDENDCERR_Pos) +#define SDIO_IE_CMDIDXERR_Pos 19 //Command Index Error Status Enable +#define SDIO_IE_CMDIDXERR_Msk (0x01 << SDIO_IE_CMDIDXCERR_Pos) +#define SDIO_IE_DATTIMEOUT_Pos 20 //Data Timeout Error Status Enable +#define SDIO_IE_DATTIMEOUT_Msk (0x01 << SDIO_IE_DATTIMEOUT_Pos) +#define SDIO_IE_DATCRCERR_Pos 21 //Data CRC Error Status Enable +#define SDIO_IE_DATCRCERR_Msk (0x01 << SDIO_IE_DATCRCERR_Pos) +#define SDIO_IE_DATENDERR_Pos 22 //Data End Bit Error Status Enable +#define SDIO_IE_DATENDERR_Msk (0x01 << SDIO_IE_DATENDCERR_Pos) +#define SDIO_IE_CURLIMERR_Pos 23 //Current Limit Error Status Enable +#define SDIO_IE_CURLIMERR_Msk (0x01 << SDIO_IE_CURLIMERR_Pos) +#define SDIO_IE_CMD12ERR_Pos 24 //Auto CMD12 Error Status Enable +#define SDIO_IE_CMD12ERR_Msk (0x01 << SDIO_IE_CMD12ERR_Pos) +#define SDIO_IE_DMAERR_Pos 25 //ADMA Error Status Enable +#define SDIO_IE_DMAERR_Msk (0x01 << SDIO_IE_DMAERR_Pos) +#define SDIO_IE_RESPERR_Pos 28 //Target Response Error Status Enable +#define SDIO_IE_RESPERR_Msk (0x01 << SDIO_IE_RESPERR_Pos) -typedef struct -{ - __IO uint32_t DATA; - __IO uint32_t ADDR; - __IO uint32_t _ERASE; //和mmcsd_cmd.h(59)名字冲突,这里修改为_ERASE - __IO uint32_t CACHE; - __IO uint32_t CFG0; - __IO uint32_t CFG1; - __IO uint32_t CFG2; - __IO uint32_t CFG3; - __IO uint32_t STAT; +#define SDIO_IM_CMDDONE_Pos 0 +#define SDIO_IM_CMDDONE_Msk (0x01 << SDIO_IM_CMDDONE_Pos) +#define SDIO_IM_TRXDONE_Pos 1 +#define SDIO_IM_TRXDONE_Msk (0x01 << SDIO_IM_TRXDONE_Pos) +#define SDIO_IM_BLKGAP_Pos 2 +#define SDIO_IM_BLKGAP_Msk (0x01 << SDIO_IM_BLKGAP_Pos) +#define SDIO_IM_DMADONE_Pos 3 +#define SDIO_IM_DMADONE_Msk (0x01 << SDIO_IM_DMADONE_Pos) +#define SDIO_IM_BUFWRRDY_Pos 4 +#define SDIO_IM_BUFWRRDY_Msk (0x01 << SDIO_IM_BUFWRRDY_Pos) +#define SDIO_IM_BUFRDRDY_Pos 5 +#define SDIO_IM_BUFRDRDY_Msk (0x01 << SDIO_IM_BUFRDRDY_Pos) +#define SDIO_IM_CARDINSR_Pos 6 +#define SDIO_IM_CARDINSR_Msk (0x01 << SDIO_IM_CARDINSR_Pos) +#define SDIO_IM_CARDRMOV_Pos 7 +#define SDIO_IM_CARDRMOV_Msk (0x01 << SDIO_IM_CARDRMOV_Pos) +#define SDIO_IM_CARD_Pos 8 +#define SDIO_IM_CARD_Msk (0x01 << SDIO_IM_CARD_Pos) +#define SDIO_IM_CMDTIMEOUT_Pos 16 +#define SDIO_IM_CMDTIMEOUT_Msk (0x01 << SDIO_IM_CMDTIMEOUT_Pos) +#define SDIO_IM_CMDCRCERR_Pos 17 +#define SDIO_IM_CMDCRCERR_Msk (0x01 << SDIO_IM_CMDCRCERR_Pos) +#define SDIO_IM_CMDENDERR_Pos 18 +#define SDIO_IM_CMDENDERR_Msk (0x01 << SDIO_IM_CMDENDCERR_Pos) +#define SDIO_IM_CMDIDXERR_Pos 19 +#define SDIO_IM_CMDIDXERR_Msk (0x01 << SDIO_IM_CMDIDXCERR_Pos) +#define SDIO_IM_DATTIMEOUT_Pos 20 +#define SDIO_IM_DATTIMEOUT_Msk (0x01 << SDIO_IM_DATTIMEOUT_Pos) +#define SDIO_IM_DATCRCERR_Pos 21 +#define SDIO_IM_DATCRCERR_Msk (0x01 << SDIO_IM_DATCRCERR_Pos) +#define SDIO_IM_DATENDERR_Pos 22 +#define SDIO_IM_DATENDERR_Msk (0x01 << SDIO_IM_DATENDCERR_Pos) +#define SDIO_IM_CURLIMERR_Pos 23 +#define SDIO_IM_CURLIMERR_Msk (0x01 << SDIO_IM_CURLIMERR_Pos) +#define SDIO_IM_CMD12ERR_Pos 24 +#define SDIO_IM_CMD12ERR_Msk (0x01 << SDIO_IM_CMD12ERR_Pos) +#define SDIO_IM_DMAERR_Pos 25 +#define SDIO_IM_DMAERR_Msk (0x01 << SDIO_IM_DMAERR_Pos) +#define SDIO_IM_RESPERR_Pos 28 +#define SDIO_IM_RESPERR_Msk (0x01 << SDIO_IM_RESPERR_Pos) + + + + +typedef struct { + __IO uint32_t DATA; + __IO uint32_t ADDR; + __IO uint32_t ERASE; + __IO uint32_t CACHE; + __IO uint32_t CFG0; + __IO uint32_t CFG1; + __IO uint32_t CFG2; + __IO uint32_t CFG3; + __IO uint32_t STAT; } FLASH_Typedef; -#define FLASH_ERASE_REQ_Pos 31 -#define FLASH_ERASE_REQ_Msk (0x01u << FLASH_ERASE_REQ_Pos) -#define FLASH_CACHE_PROG_Pos 2 -#define FLASH_CACHE_PROG_Msk (0x01 << FLASH_CACHE_PROG_Pos) -#define FLASH_CACHE_CLEAR_Pos 3 -#define FLASH_CACHE_CLEAR_Msk (0x01 << FLASH_CACHE_CLEAR_Pos) +#define FLASH_ERASE_REQ_Pos 31 +#define FLASH_ERASE_REQ_Msk (0x01u<< FLASH_ERASE_REQ_Pos) -#define FLASH_STAT_ERASE_GOING_Pos 0 -#define FLASH_STAT_ERASE_GOING_Msk (0X01 << FLASH_STAT_ERASE_GOING_Pos) -#define FLASH_STAT_PROG_GOING_Pos 1 -#define FLASH_STAT_PROG_GOING_Msk (0x01 << FLASH_STAT_PROG_GOING_Pos) -#define FALSH_STAT_FIFO_EMPTY_Pos 3 -#define FLASH_STAT_FIFO_EMPTY_Msk (0x01 << FALSH_STAT_FIFO_EMPTY_Pos) -#define FALSH_STAT_FIFO_FULL_Pos 4 -#define FLASH_STAT_FIFO_FULL_Msk (0x01 << FALSH_STAT_FIFO_FULL_Pos) +#define FLASH_CACHE_PROG_Pos 2 +#define FLASH_CACHE_PROG_Msk (0x01 << FLASH_CACHE_PROG_Pos) +#define FLASH_CACHE_CLEAR_Pos 3 +#define FLASH_CACHE_CLEAR_Msk (0x01 << FLASH_CACHE_CLEAR_Pos) -typedef struct -{ +#define FLASH_STAT_ERASE_GOING_Pos 0 +#define FLASH_STAT_ERASE_GOING_Msk (0X01 << FLASH_STAT_ERASE_GOING_Pos) +#define FLASH_STAT_PROG_GOING_Pos 1 +#define FLASH_STAT_PROG_GOING_Msk (0x01 << FLASH_STAT_PROG_GOING_Pos) +#define FALSH_STAT_FIFO_EMPTY_Pos 3 +#define FLASH_STAT_FIFO_EMPTY_Msk (0x01 << FALSH_STAT_FIFO_EMPTY_Pos) +#define FALSH_STAT_FIFO_FULL_Pos 4 +#define FLASH_STAT_FIFO_FULL_Msk (0x01 << FALSH_STAT_FIFO_FULL_Pos) + + + + +typedef struct { __IO uint32_t CR; } SRAMC_TypeDef; -#define SRAMC_CR_RWTIME_Pos 0 //读写操作持续多少个时钟周期。0表示1个时钟周期。最小设置为4 -#define SRAMC_CR_RWTIME_Msk (0x0F << SRAMC_CR_RWTIME_Pos) -#define SRAMC_CR_BYTEIF_Pos 4 //外部SRAM数据宽度,0 16位 1 8位 -#define SRAMC_CR_BYTEIF_Msk (0x01 << SRAMC_CR_BYTEIF_Pos) -#define SRAMC_CR_HBLBDIS_Pos 5 //1 ADDR[23:22]为地址线 0 ADDR[23]为高字节使能,ADDR[22]为低字节使能 -#define SRAMC_CR_HBLBDIS_Msk (0x01 << SRAMC_CR_HBLBDIS_Pos) -typedef struct -{ +#define SRAMC_CR_RWTIME_Pos 0 //дٸʱڡ0ʾ1ʱڡСΪ4 +#define SRAMC_CR_RWTIME_Msk (0x0F << SRAMC_CR_RWTIME_Pos) +#define SRAMC_CR_BYTEIF_Pos 4 //ⲿSRAMݿȣ0 16λ 1 8λ +#define SRAMC_CR_BYTEIF_Msk (0x01 << SRAMC_CR_BYTEIF_Pos) +#define SRAMC_CR_HBLBDIS_Pos 5 //1 ADDR[23:22]Ϊַ 0 ADDR[23]ΪֽʹܣADDR[22]Ϊֽʹ +#define SRAMC_CR_HBLBDIS_Msk (0x01 << SRAMC_CR_HBLBDIS_Pos) + + + +typedef struct { __IO uint32_t CR0; - + __IO uint32_t CR1; - + __IO uint32_t REFRESH; - - __IO uint32_t NOPNUM; //[15:0] 初始化完成后,在正常操作之前,发送多少个NOP命令 - + + __IO uint32_t NOPNUM; //[15:0] ʼɺ֮ǰͶٸNOP + __IO uint32_t LATCH; - - __IO uint32_t REFDONE; //[0] Frefresh Done,上电初始化完成 + + __IO uint32_t REFDONE; //[0] Frefresh Doneϵʼ } SDRAMC_TypeDef; -#define SDRAMC_CR0_BURSTLEN_Pos 0 //必须取2,表示Burst Length为4 -#define SDRAMC_CR0_BURSTLEN_Msk (0x07 << SDRAMC_CR0_BURSTLEN_Pos) -#define SDRAMC_CR0_CASDELAY_Pos 4 //CAS Latency, 2 2 3 3 -#define SDRAMC_CR0_CASDELAY_Msk (0x07 << SDRAMC_CR0_CASDELAY_Pos) -#define SDRAMC_CR1_TRP_Pos 0 -#define SDRAMC_CR1_TRP_Msk (0x07 << SDRAMC_CR1_TRP_Pos) -#define SDRAMC_CR1_TRCD_Pos 3 -#define SDRAMC_CR1_TRCD_Msk (0x07 << SDRAMC_CR1_TRCD_Pos) -#define SDRAMC_CR1_TRC_Pos 6 -#define SDRAMC_CR1_TRC_Msk (0x0F << SDRAMC_CR1_TRC_Pos) -#define SDRAMC_CR1_TRAS_Pos 10 -#define SDRAMC_CR1_TRAS_Msk (0x07 << SDRAMC_CR1_TRAS_Pos) -#define SDRAMC_CR1_TRRD_Pos 13 -#define SDRAMC_CR1_TRRD_Msk (0x03 << SDRAMC_CR1_TRRD_Pos) -#define SDRAMC_CR1_TMRD_Pos 15 -#define SDRAMC_CR1_TMRD_Msk (0x07 << SDRAMC_CR1_TMRD_Pos) -#define SDRAMC_CR1_32BIT_Pos 18 //SDRAMC的接口数据位宽,1 32bit 0 16bit -#define SDRAMC_CR1_32BIT_Msk (0x01 << SDRAMC_CR1_32BIT_Pos) -#define SDRAMC_CR1_BANK_Pos 19 //SDRAM每个颗粒有几个bank,0 2 banks 1 4 banks -#define SDRAMC_CR1_BANK_Msk (0x01 << SDRAMC_CR1_BANK_Pos) -#define SDRAMC_CR1_CELL32BIT_Pos 20 //SDRAM颗粒的位宽,1 32bit 0 16bit -#define SDRAMC_CR1_CELL32BIT_Msk (0x01 << SDRAMC_CR1_CELL32BIT_Pos) -#define SDRAMC_CR1_CELLSIZE_Pos 21 //SDRAM颗粒的容量,0 64Mb 1 128Mb 2 256Mb 3 16Mb -#define SDRAMC_CR1_CELLSIZE_Msk (0x03 << SDRAMC_CR1_CELLSIZE_Pos) -#define SDRAMC_CR1_HIGHSPEED_Pos 23 //当hclk大于100MHz时,这一位必须配置为1,否则为0 -#define SDRAMC_CR1_HIGHSPEED_Msk (0x01 << SDRAMC_CR1_HIGHSPEED_Pos) +#define SDRAMC_CR0_BURSTLEN_Pos 0 //ȡ2ʾBurst LengthΪ4 +#define SDRAMC_CR0_BURSTLEN_Msk (0x07 << SDRAMC_CR0_BURSTLEN_Pos) +#define SDRAMC_CR0_CASDELAY_Pos 4 //CAS Latency 2 2 3 3 +#define SDRAMC_CR0_CASDELAY_Msk (0x07 << SDRAMC_CR0_CASDELAY_Pos) -#define SDRAMC_REFRESH_RATE_Pos 0 -#define SDRAMC_REFRESH_RATE_Msk (0xFFF << SDRAMC_REFRESH_RATE_Pos) -#define SDRAMC_REFRESH_EN_Pos 12 -#define SDRAMC_REFRESH_EN_Msk (0x01 << SDRAMC_REFRESH_EN_Pos) +#define SDRAMC_CR1_TRP_Pos 0 +#define SDRAMC_CR1_TRP_Msk (0x07 << SDRAMC_CR1_TRP_Pos) +#define SDRAMC_CR1_TRCD_Pos 3 +#define SDRAMC_CR1_TRCD_Msk (0x07 << SDRAMC_CR1_TRCD_Pos) +#define SDRAMC_CR1_TRC_Pos 6 +#define SDRAMC_CR1_TRC_Msk (0x0F << SDRAMC_CR1_TRC_Pos) +#define SDRAMC_CR1_TRAS_Pos 10 +#define SDRAMC_CR1_TRAS_Msk (0x07 << SDRAMC_CR1_TRAS_Pos) +#define SDRAMC_CR1_TRRD_Pos 13 +#define SDRAMC_CR1_TRRD_Msk (0x03 << SDRAMC_CR1_TRRD_Pos) +#define SDRAMC_CR1_TMRD_Pos 15 +#define SDRAMC_CR1_TMRD_Msk (0x07 << SDRAMC_CR1_TMRD_Pos) +#define SDRAMC_CR1_32BIT_Pos 18 //SDRAMCĽӿλ1 32bit 0 16bit +#define SDRAMC_CR1_32BIT_Msk (0x01 << SDRAMC_CR1_32BIT_Pos) +#define SDRAMC_CR1_BANK_Pos 19 //SDRAMÿмbank0 2 banks 1 4 banks +#define SDRAMC_CR1_BANK_Msk (0x01 << SDRAMC_CR1_BANK_Pos) +#define SDRAMC_CR1_CELL32BIT_Pos 20 //SDRAMλ1 32bit 0 16bit +#define SDRAMC_CR1_CELL32BIT_Msk (0x01 << SDRAMC_CR1_CELL32BIT_Pos) +#define SDRAMC_CR1_CELLSIZE_Pos 21 //SDRAM0 64Mb 1 128Mb 2 256Mb 3 16Mb +#define SDRAMC_CR1_CELLSIZE_Msk (0x03 << SDRAMC_CR1_CELLSIZE_Pos) +#define SDRAMC_CR1_HIGHSPEED_Pos 23 //hclk100MHzʱһλΪ1Ϊ0 +#define SDRAMC_CR1_HIGHSPEED_Msk (0x01 << SDRAMC_CR1_HIGHSPEED_Pos) -#define SDRAMC_LATCH_INEDGE_Pos 0 //哪个沿来锁存从SDRAM中读回的数据,0 上升沿 1 下降沿 -#define SDRAMC_LATCH_INEDGE_Msk (0x01 << SDRAMC_LATCH_INEDGE_Pos) -#define SDRAMC_LATCH_OUTEDGE_Pos 1 //哪个沿去锁存送给SDRAM的数据,1 上升沿 0 下降沿 -#define SDRAMC_LATCH_OUTEDGE_Msk (0x01 << SDRAMC_LATCH_OUTEDGE_Pos) -#define SDRAMC_LATCH_WAITST_Pos 2 -#define SDRAMC_LATCH_WAITST_Msk (0x01 << SDRAMC_LATCH_WAITST_Pos) +#define SDRAMC_REFRESH_RATE_Pos 0 +#define SDRAMC_REFRESH_RATE_Msk (0xFFF << SDRAMC_REFRESH_RATE_Pos) +#define SDRAMC_REFRESH_EN_Pos 12 +#define SDRAMC_REFRESH_EN_Msk (0x01 << SDRAMC_REFRESH_EN_Pos) -typedef struct -{ +#define SDRAMC_LATCH_INEDGE_Pos 0 //ĸSDRAMжصݣ0 1 ½ +#define SDRAMC_LATCH_INEDGE_Msk (0x01 << SDRAMC_LATCH_INEDGE_Pos) +#define SDRAMC_LATCH_OUTEDGE_Pos 1 //ĸȥ͸SDRAMݣ1 0 ½ +#define SDRAMC_LATCH_OUTEDGE_Msk (0x01 << SDRAMC_LATCH_OUTEDGE_Pos) +#define SDRAMC_LATCH_WAITST_Pos 2 +#define SDRAMC_LATCH_WAITST_Msk (0x01 << SDRAMC_LATCH_WAITST_Pos) + + + + +typedef struct { __IO uint32_t IE; - - __IO uint32_t IF; //写1清零 - + + __IO uint32_t IF; //д1 + __IO uint32_t IM; - + __IO uint32_t CR; - + __IO uint32_t ADDR; - + __IO uint32_t CMD; } NORFLC_TypeDef; -#define NORFLC_IE_FINISH_Pos 0 -#define NORFLC_IE_FINISH_Msk (0x01 << NORFLC_IE_FINISH_Pos) -#define NORFLC_IE_TIMEOUT_Pos 1 -#define NORFLC_IE_TIMEOUT_Msk (0x01 << NORFLC_IE_TIMEOUT_Pos) -#define NORFLC_IF_FINISH_Pos 0 -#define NORFLC_IF_FINISH_Msk (0x01 << NORFLC_IF_FINISH_Pos) -#define NORFLC_IF_TIMEOUT_Pos 1 -#define NORFLC_IF_TIMEOUT_Msk (0x01 << NORFLC_IF_TIMEOUT_Pos) +#define NORFLC_IE_FINISH_Pos 0 +#define NORFLC_IE_FINISH_Msk (0x01 << NORFLC_IE_FINISH_Pos) +#define NORFLC_IE_TIMEOUT_Pos 1 +#define NORFLC_IE_TIMEOUT_Msk (0x01 << NORFLC_IE_TIMEOUT_Pos) -#define NORFLC_IM_FINISH_Pos 0 -#define NORFLC_IM_FINISH_Msk (0x01 << NORFLC_IM_FINISH_Pos) -#define NORFLC_IM_TIMEOUT_Pos 1 -#define NORFLC_IM_TIMEOUT_Msk (0x01 << NORFLC_IM_TIMEOUT_Pos) +#define NORFLC_IF_FINISH_Pos 0 +#define NORFLC_IF_FINISH_Msk (0x01 << NORFLC_IF_FINISH_Pos) +#define NORFLC_IF_TIMEOUT_Pos 1 +#define NORFLC_IF_TIMEOUT_Msk (0x01 << NORFLC_IF_TIMEOUT_Pos) -#define NORFLC_CR_RDTIME_Pos 0 //Oen下降沿后多少个时钟周期后采样读回的数据。0表示1个时钟周期 -#define NORFLC_CR_RDTIME_Msk (0x1F << NORFLC_CR_RDTIME_Pos) -#define NORFLC_CR_WRTIME_Pos 5 //输出Wen的低电平宽度。0表示1个时钟周期 -#define NORFLC_CR_WRTIME_Msk (0x07 << NORFLC_CR_WRTIME_Pos) -#define NORFLC_CR_BYTEIF_Pos 8 //外部NOR FLASH数据宽度,1 8位 0 16位 -#define NORFLC_CR_BYTEIF_Msk (0x01 << NORFLC_CR_BYTEIF_Pos) +#define NORFLC_IM_FINISH_Pos 0 +#define NORFLC_IM_FINISH_Msk (0x01 << NORFLC_IM_FINISH_Pos) +#define NORFLC_IM_TIMEOUT_Pos 1 +#define NORFLC_IM_TIMEOUT_Msk (0x01 << NORFLC_IM_TIMEOUT_Pos) -#define NORFLC_CMD_DATA_Pos 0 //在PROGRAM命令中,DATA是要写入NOR FLASH的数据;在READ命令中,DATA是从NOR FLASH读回的数据 -#define NORFLC_CMD_DATA_Msk (0xFFFF << NORFLC_CMD_DATA_Pos) -#define NORFLC_CMD_CMD_Pos 16 //需要执行的命令,0 READ 1 RESET 2 AUTOMATIC SELECT 3 PROGRAM 4 CHIP ERASE 5 SECTOR ERASE -#define NORFLC_CMD_CMD_Msk (0x07 << NORFLC_CMD_CMD_Pos) +#define NORFLC_CR_RDTIME_Pos 0 //Oen½غٸʱںصݡ0ʾ1ʱ +#define NORFLC_CR_RDTIME_Msk (0x1F << NORFLC_CR_RDTIME_Pos) +#define NORFLC_CR_WRTIME_Pos 5 //Wenĵ͵ƽȡ0ʾ1ʱ +#define NORFLC_CR_WRTIME_Msk (0x07 << NORFLC_CR_WRTIME_Pos) +#define NORFLC_CR_BYTEIF_Pos 8 //ⲿNOR FLASHݿȣ1 8λ 0 16λ +#define NORFLC_CR_BYTEIF_Msk (0x01 << NORFLC_CR_BYTEIF_Pos) -typedef struct -{ +#define NORFLC_CMD_DATA_Pos 0 //PROGRAMУDATAҪдNOR FLASHݣREADУDATAǴNOR FLASHص +#define NORFLC_CMD_DATA_Msk (0xFFFF << NORFLC_CMD_DATA_Pos) +#define NORFLC_CMD_CMD_Pos 16 //Ҫִе0 READ 1 RESET 2 AUTOMATIC SELECT 3 PROGRAM 4 CHIP ERASE 5 SECTOR ERASE +#define NORFLC_CMD_CMD_Msk (0x07 << NORFLC_CMD_CMD_Pos) + + + + +typedef struct { __IO uint32_t CR; - - __O uint32_t DATAIN; - + + __O uint32_t DATAIN; + __IO uint32_t INIVAL; - - __I uint32_t RESULT; + + __I uint32_t RESULT; } CRC_TypeDef; -#define CRC_CR_EN_Pos 0 -#define CRC_CR_EN_Msk (0x01 << CRC_CR_EN_Pos) -#define CRC_CR_OREV_Pos 1 //输出结果是否翻转 -#define CRC_CR_OREV_Msk (0x01 << CRC_CR_OREV_Pos) -#define CRC_CR_ONOT_Pos 2 //输出结果是否取反 -#define CRC_CR_ONOT_Msk (0x01 << CRC_CR_ONOT_Pos) -#define CRC_CR_CRC16_Pos 3 //1 CRC16 0 CRC32 -#define CRC_CR_CRC16_Msk (0x01 << CRC_CR_CRC16_Pos) -#define CRC_CR_IBITS_Pos 4 //输入数据有效位数 0 32位 1 16位 2 8位 -#define CRC_CR_IBITS_Msk (0x03 << CRC_CR_IBITS_Pos) -typedef struct -{ - __IO uint32_t MINSEC; //分秒计数 +#define CRC_CR_EN_Pos 0 +#define CRC_CR_EN_Msk (0x01 << CRC_CR_EN_Pos) +#define CRC_CR_OREV_Pos 1 //Ƿת +#define CRC_CR_OREV_Msk (0x01 << CRC_CR_OREV_Pos) +#define CRC_CR_ONOT_Pos 2 //Ƿȡ +#define CRC_CR_ONOT_Msk (0x01 << CRC_CR_ONOT_Pos) +#define CRC_CR_CRC16_Pos 3 //1 CRC16 0 CRC32 +#define CRC_CR_CRC16_Msk (0x01 << CRC_CR_CRC16_Pos) +#define CRC_CR_IBITS_Pos 4 //Чλ 0 32λ 1 16λ 2 8λ +#define CRC_CR_IBITS_Msk (0x03 << CRC_CR_IBITS_Pos) - __IO uint32_t DATHUR; //日时计数 - __IO uint32_t MONDAY; //月周计数 - __IO uint32_t YEAR; //[11:0] 年计数,支持1901-2199 - - __IO uint32_t MINSECAL; //分秒闹铃设置 - - __IO uint32_t DAYHURAL; //周时闹铃设置 - - __IO uint32_t LOAD; //将设置寄存器中的值同步到RTC中,同步完成自动清零 +typedef struct { + __IO uint32_t MINSEC; // + + __IO uint32_t DATHUR; //ʱ + + __IO uint32_t MONDAY; //ܼ + + __IO uint32_t YEAR; //[11:0] ֧1901-2199 + + __IO uint32_t MINSECAL; // + + __IO uint32_t DAYHURAL; //ʱ + + __IO uint32_t LOAD; //üĴеֵͬRTCУͬԶ + __IO uint32_t IE; - - __IO uint32_t IF; //写1清零 - - __IO uint32_t EN; //[0] 1 RTC使能 - - __IO uint32_t CFGABLE; //[0] 1 RTC可配置 - - __IO uint32_t TRIM; //时钟调整 - - __IO uint32_t TRIMM; //时钟微调整 + + __IO uint32_t IF; //д1 + + __IO uint32_t EN; //[0] 1 RTCʹ + + __IO uint32_t CFGABLE; //[0] 1 RTC + + __IO uint32_t TRIM; //ʱӵ + + __IO uint32_t TRIMM; //ʱ΢ } RTC_TypeDef; -#define RTC_LOAD_TIME_Pos 0 -#define RTC_LOAD_TIME_Msk (0x01 << RTC_LOAD_TIME_Pos) -#define RTC_LOAD_ALARM_Pos 1 -#define RTC_LOAD_ALARM_Msk (0x01 << RTC_LOAD_ALARM_Pos) -#define RTC_MINSEC_SEC_Pos 0 //秒计数,取值0--59 -#define RTC_MINSEC_SEC_Msk (0x3F << RTC_MINSEC_SEC_Pos) -#define RTC_MINSEC_MIN_Pos 6 //分钟计数,取值0--59 -#define RTC_MINSEC_MIN_Msk (0x3F << RTC_MINSEC_MIN_Pos) +#define RTC_LOAD_TIME_Pos 0 +#define RTC_LOAD_TIME_Msk (0x01 << RTC_LOAD_TIME_Pos) +#define RTC_LOAD_ALARM_Pos 1 +#define RTC_LOAD_ALARM_Msk (0x01 << RTC_LOAD_ALARM_Pos) -#define RTC_DATHUR_HOUR_Pos 0 //小时计数,取值0--23 -#define RTC_DATHUR_HOUR_Msk (0x1F << RTC_DATHUR_HOUR_Pos) -#define RTC_DATHUR_DATE_Pos 5 //date of month,取值1--31 -#define RTC_DATHUR_DATE_Msk (0x1F << RTC_DATHUR_DATE_Pos) +#define RTC_MINSEC_SEC_Pos 0 //ȡֵ0--59 +#define RTC_MINSEC_SEC_Msk (0x3F << RTC_MINSEC_SEC_Pos) +#define RTC_MINSEC_MIN_Pos 6 //Ӽȡֵ0--59 +#define RTC_MINSEC_MIN_Msk (0x3F << RTC_MINSEC_MIN_Pos) -#define RTC_MONDAY_DAY_Pos 0 //day of week,取值0--6 -#define RTC_MONDAY_DAY_Msk (0x07 << RTC_MONDAY_DAY_Pos) -#define RTC_MONDAY_MON_Pos 3 //月份计数,取值1--12 -#define RTC_MONDAY_MON_Msk (0x0F << RTC_MONDAY_MON_Pos) +#define RTC_DATHUR_HOUR_Pos 0 //Сʱȡֵ0--23 +#define RTC_DATHUR_HOUR_Msk (0x1F << RTC_DATHUR_HOUR_Pos) +#define RTC_DATHUR_DATE_Pos 5 //date of monthȡֵ1--31 +#define RTC_DATHUR_DATE_Msk (0x1F << RTC_DATHUR_DATE_Pos) -#define RTC_MINSECAL_SEC_Pos 0 //闹钟秒设置 -#define RTC_MINSECAL_SEC_Msk (0x3F << RTC_MINSECAL_SEC_Pos) -#define RTC_MINSECAL_MIN_Pos 6 //闹钟分钟设置 -#define RTC_MINSECAL_MIN_Msk (0x3F << RTC_MINSECAL_MIN_Pos) +#define RTC_MONDAY_DAY_Pos 0 //day of weekȡֵ0--6 +#define RTC_MONDAY_DAY_Msk (0x07 << RTC_MONDAY_DAY_Pos) +#define RTC_MONDAY_MON_Pos 3 //·ݼȡֵ1--12 +#define RTC_MONDAY_MON_Msk (0x0F << RTC_MONDAY_MON_Pos) -#define RTC_DAYHURAL_HOUR_Pos 0 //闹钟小时设置 -#define RTC_DAYHURAL_HOUR_Msk (0x1F << RTC_DAYHURAL_HOUR_Pos) -#define RTC_DAYHURAL_SUN_Pos 5 //周日闹钟有效 -#define RTC_DAYHURAL_SUN_Msk (0x01 << RTC_DAYHURAL_SUN_Pos) -#define RTC_DAYHURAL_MON_Pos 6 //周一闹钟有效 -#define RTC_DAYHURAL_MON_Msk (0x01 << RTC_DAYHURAL_MON_Pos) -#define RTC_DAYHURAL_TUE_Pos 7 //周二闹钟有效 -#define RTC_DAYHURAL_TUE_Msk (0x01 << RTC_DAYHURAL_TUE_Pos) -#define RTC_DAYHURAL_WED_Pos 8 //周三闹钟有效 -#define RTC_DAYHURAL_WED_Msk (0x01 << RTC_DAYHURAL_WED_Pos) -#define RTC_DAYHURAL_THU_Pos 9 //周四闹钟有效 -#define RTC_DAYHURAL_THU_Msk (0x01 << RTC_DAYHURAL_THU_Pos) -#define RTC_DAYHURAL_FRI_Pos 10 //周五闹钟有效 -#define RTC_DAYHURAL_FRI_Msk (0x01 << RTC_DAYHURAL_FRI_Pos) -#define RTC_DAYHURAL_SAT_Pos 11 //周六闹钟有效 -#define RTC_DAYHURAL_SAT_Msk (0x01 << RTC_DAYHURAL_SAT_Pos) +#define RTC_MINSECAL_SEC_Pos 0 // +#define RTC_MINSECAL_SEC_Msk (0x3F << RTC_MINSECAL_SEC_Pos) +#define RTC_MINSECAL_MIN_Pos 6 //ӷ +#define RTC_MINSECAL_MIN_Msk (0x3F << RTC_MINSECAL_MIN_Pos) -#define RTC_IE_SEC_Pos 0 //秒中断使能 -#define RTC_IE_SEC_Msk (0x01 << RTC_IE_SEC_Pos) -#define RTC_IE_MIN_Pos 1 -#define RTC_IE_MIN_Msk (0x01 << RTC_IE_MIN_Pos) -#define RTC_IE_HOUR_Pos 2 -#define RTC_IE_HOUR_Msk (0x01 << RTC_IE_HOUR_Pos) -#define RTC_IE_DATE_Pos 3 -#define RTC_IE_DATE_Msk (0x01 << RTC_IE_DATE_Pos) -#define RTC_IE_ALARM_Pos 4 -#define RTC_IE_ALARM_Msk (0x01 << RTC_IE_ALARM_Pos) +#define RTC_DAYHURAL_HOUR_Pos 0 //Сʱ +#define RTC_DAYHURAL_HOUR_Msk (0x1F << RTC_DAYHURAL_HOUR_Pos) +#define RTC_DAYHURAL_SUN_Pos 5 //Ч +#define RTC_DAYHURAL_SUN_Msk (0x01 << RTC_DAYHURAL_SUN_Pos) +#define RTC_DAYHURAL_MON_Pos 6 //һЧ +#define RTC_DAYHURAL_MON_Msk (0x01 << RTC_DAYHURAL_MON_Pos) +#define RTC_DAYHURAL_TUE_Pos 7 //ܶЧ +#define RTC_DAYHURAL_TUE_Msk (0x01 << RTC_DAYHURAL_TUE_Pos) +#define RTC_DAYHURAL_WED_Pos 8 //Ч +#define RTC_DAYHURAL_WED_Msk (0x01 << RTC_DAYHURAL_WED_Pos) +#define RTC_DAYHURAL_THU_Pos 9 //Ч +#define RTC_DAYHURAL_THU_Msk (0x01 << RTC_DAYHURAL_THU_Pos) +#define RTC_DAYHURAL_FRI_Pos 10 //Ч +#define RTC_DAYHURAL_FRI_Msk (0x01 << RTC_DAYHURAL_FRI_Pos) +#define RTC_DAYHURAL_SAT_Pos 11 //Ч +#define RTC_DAYHURAL_SAT_Msk (0x01 << RTC_DAYHURAL_SAT_Pos) -#define RTC_IF_SEC_Pos 0 //写1清零 -#define RTC_IF_SEC_Msk (0x01 << RTC_IF_SEC_Pos) -#define RTC_IF_MIN_Pos 1 -#define RTC_IF_MIN_Msk (0x01 << RTC_IF_MIN_Pos) -#define RTC_IF_HOUR_Pos 2 -#define RTC_IF_HOUR_Msk (0x01 << RTC_IF_HOUR_Pos) -#define RTC_IF_DATE_Pos 3 -#define RTC_IF_DATE_Msk (0x01 << RTC_IF_DATE_Pos) -#define RTC_IF_ALARM_Pos 4 -#define RTC_IF_ALARM_Msk (0x01 << RTC_IF_ALARM_Pos) +#define RTC_IE_SEC_Pos 0 //жʹ +#define RTC_IE_SEC_Msk (0x01 << RTC_IE_SEC_Pos) +#define RTC_IE_MIN_Pos 1 +#define RTC_IE_MIN_Msk (0x01 << RTC_IE_MIN_Pos) +#define RTC_IE_HOUR_Pos 2 +#define RTC_IE_HOUR_Msk (0x01 << RTC_IE_HOUR_Pos) +#define RTC_IE_DATE_Pos 3 +#define RTC_IE_DATE_Msk (0x01 << RTC_IE_DATE_Pos) +#define RTC_IE_ALARM_Pos 4 +#define RTC_IE_ALARM_Msk (0x01 << RTC_IE_ALARM_Pos) -#define RTC_TRIM_ADJ_Pos 0 //用于调整BASECNT的计数周期,默认为32768,如果DEC为1,则计数周期调整为32768-ADJ,否则调整为32768+ADJ -#define RTC_TRIM_ADJ_Msk (0xFF << RTC_TRIM_ADJ_Pos) -#define RTC_TRIM_DEC_Pos 8 -#define RTC_TRIM_DEC_Msk (0x01 << RTC_TRIM_DEC_Pos) +#define RTC_IF_SEC_Pos 0 //д1 +#define RTC_IF_SEC_Msk (0x01 << RTC_IF_SEC_Pos) +#define RTC_IF_MIN_Pos 1 +#define RTC_IF_MIN_Msk (0x01 << RTC_IF_MIN_Pos) +#define RTC_IF_HOUR_Pos 2 +#define RTC_IF_HOUR_Msk (0x01 << RTC_IF_HOUR_Pos) +#define RTC_IF_DATE_Pos 3 +#define RTC_IF_DATE_Msk (0x01 << RTC_IF_DATE_Pos) +#define RTC_IF_ALARM_Pos 4 +#define RTC_IF_ALARM_Msk (0x01 << RTC_IF_ALARM_Pos) -#define RTC_TRIMM_CYCLE_Pos 0 //用于计数周期微调,如果INC为1,则第n个计数周期调整为(32768±ADJ)+1,否则调整为(32768±ADJ)-1 \ - //cycles=0时,不进行微调整;cycles=1,则n为2;cycles=7,则n为8;以此类推 -#define RTC_TRIMM_CYCLE_Msk (0x07 << RTC_TRIMM_CYCLE_Pos) -#define RTC_TRIMM_INC_Pos 3 -#define RTC_TRIMM_INC_Msk (0x01 << RTC_TRIMM_INC_Pos) +#define RTC_TRIM_ADJ_Pos 0 //ڵBASECNTļڣĬΪ32768DECΪ1ڵΪ32768-ADJΪ32768+ADJ +#define RTC_TRIM_ADJ_Msk (0xFF << RTC_TRIM_ADJ_Pos) +#define RTC_TRIM_DEC_Pos 8 +#define RTC_TRIM_DEC_Msk (0x01 << RTC_TRIM_DEC_Pos) -typedef struct -{ - __IO uint32_t LOAD; //喂狗使计数器装载LOAD值 +#define RTC_TRIMM_CYCLE_Pos 0 //ڼ΢INCΪ1nڵΪ(32768ADJ)+1,Ϊ(32768ADJ)-1 + //cycles=0ʱ΢cycles=1nΪ2cycles=7nΪ8Դ +#define RTC_TRIMM_CYCLE_Msk (0x07 << RTC_TRIMM_CYCLE_Pos) +#define RTC_TRIMM_INC_Pos 3 +#define RTC_TRIMM_INC_Msk (0x01 << RTC_TRIMM_INC_Pos) - __I uint32_t VALUE; - __IO uint32_t CR; - __IO uint32_t IF; //计数到0时硬件置位,软件写1清除标志 - __IO uint32_t FEED; //写0x55喂狗 +typedef struct { + __IO uint32_t LOAD; //ιʹװLOADֵ + + __I uint32_t VALUE; + + __IO uint32_t CR; + + __IO uint32_t IF; //0ʱӲλд1־ + + __IO uint32_t FEED; //д0x55ι } WDT_TypeDef; -#define WDT_CR_EN_Pos 0 -#define WDT_CR_EN_Msk (0x01 << WDT_CR_EN_Pos) -#define WDT_CR_RSTEN_Pos 1 -#define WDT_CR_RSTEN_Msk (0x01 << WDT_CR_RSTEN_Pos) + +#define WDT_CR_EN_Pos 0 +#define WDT_CR_EN_Msk (0x01 << WDT_CR_EN_Pos) +#define WDT_CR_RSTEN_Pos 1 +#define WDT_CR_RSTEN_Msk (0x01 << WDT_CR_RSTEN_Pos) + /******************************************************************************/ /* Peripheral memory map */ /******************************************************************************/ -#define RAM_BASE 0x20000000 -#define AHB_BASE 0x40000000 -#define APB_BASE 0x40010000 +#define RAM_BASE 0x20000000 +#define AHB_BASE 0x40000000 +#define APB_BASE 0x40010000 -#define NORFLC_BASE 0x60000000 -#define NORFLM_BASE 0x61000000 +#define NORFLC_BASE 0x60000000 +#define NORFLM_BASE 0x61000000 -#define SRAMC_BASE 0x68000000 -#define SRAMM_BASE 0x69000000 +#define SRAMC_BASE 0x68000000 +#define SRAMM_BASE 0x69000000 -#define SDRAMC_BASE 0x78000000 -#define SDRAMM_BASE 0x70000000 +#define SDRAMC_BASE 0x78000000 +#define SDRAMM_BASE 0x70000000 /* AHB Peripheral memory map */ -#define SYS_BASE (AHB_BASE + 0x00000) +#define SYS_BASE (AHB_BASE + 0x00000) -#define DMA_BASE (AHB_BASE + 0x01000) +#define DMA_BASE (AHB_BASE + 0x01000) -#define LCD_BASE (AHB_BASE + 0x02000) +#define LCD_BASE (AHB_BASE + 0x02000) -#define CRC_BASE (AHB_BASE + 0x03000) +#define CRC_BASE (AHB_BASE + 0x03000) -#define SDIO_BASE (AHB_BASE + 0x04000) +#define SDIO_BASE (AHB_BASE + 0x04000) /* APB Peripheral memory map */ -#define PORT_BASE (APB_BASE + 0x00000) +#define PORT_BASE (APB_BASE + 0x00000) -#define GPIOA_BASE (APB_BASE + 0x01000) -#define GPIOB_BASE (APB_BASE + 0x02000) -#define GPIOC_BASE (APB_BASE + 0x03000) -#define GPIOD_BASE (APB_BASE + 0x04000) -#define GPIOM_BASE (APB_BASE + 0x05000) -#define GPION_BASE (APB_BASE + 0x06000) -#define GPIOP_BASE (APB_BASE + 0x08000) +#define GPIOA_BASE (APB_BASE + 0x01000) +#define GPIOB_BASE (APB_BASE + 0x02000) +#define GPIOC_BASE (APB_BASE + 0x03000) +#define GPIOD_BASE (APB_BASE + 0x04000) +#define GPIOM_BASE (APB_BASE + 0x05000) +#define GPION_BASE (APB_BASE + 0x06000) +#define GPIOP_BASE (APB_BASE + 0x08000) -#define TIMR0_BASE (APB_BASE + 0x07000) -#define TIMR1_BASE (APB_BASE + 0x0700C) -#define TIMR2_BASE (APB_BASE + 0x07018) -#define TIMR3_BASE (APB_BASE + 0x07024) -#define TIMR4_BASE (APB_BASE + 0x07030) -#define TIMR5_BASE (APB_BASE + 0x0703C) -#define TIMRG_BASE (APB_BASE + 0x07060) +#define TIMR0_BASE (APB_BASE + 0x07000) +#define TIMR1_BASE (APB_BASE + 0x0700C) +#define TIMR2_BASE (APB_BASE + 0x07018) +#define TIMR3_BASE (APB_BASE + 0x07024) +#define TIMR4_BASE (APB_BASE + 0x07030) +#define TIMR5_BASE (APB_BASE + 0x0703C) +#define TIMRG_BASE (APB_BASE + 0x07060) -#define WDT_BASE (APB_BASE + 0x09000) +#define WDT_BASE (APB_BASE + 0x09000) -#define PWM0_BASE (APB_BASE + 0x0A000) -#define PWM1_BASE (APB_BASE + 0x0A020) -#define PWM2_BASE (APB_BASE + 0x0A040) -#define PWM3_BASE (APB_BASE + 0x0A060) -#define PWM4_BASE (APB_BASE + 0x0A080) -#define PWM5_BASE (APB_BASE + 0x0A0A0) -#define PWMG_BASE (APB_BASE + 0x0A180) +#define PWM0_BASE (APB_BASE + 0x0A000) +#define PWM1_BASE (APB_BASE + 0x0A020) +#define PWM2_BASE (APB_BASE + 0x0A040) +#define PWM3_BASE (APB_BASE + 0x0A060) +#define PWM4_BASE (APB_BASE + 0x0A080) +#define PWM5_BASE (APB_BASE + 0x0A0A0) +#define PWMG_BASE (APB_BASE + 0x0A180) -#define RTC_BASE (APB_BASE + 0x0B000) +#define RTC_BASE (APB_BASE + 0x0B000) -#define ADC0_BASE (APB_BASE + 0x0C000) -#define ADC1_BASE (APB_BASE + 0x0D000) +#define ADC0_BASE (APB_BASE + 0x0C000) +#define ADC1_BASE (APB_BASE + 0x0D000) -#define FLASH_BASE (APB_BASE + 0x0F000) +#define FLASH_BASE (APB_BASE + 0x0F000) -#define UART0_BASE (APB_BASE + 0x10000) -#define UART1_BASE (APB_BASE + 0x11000) -#define UART2_BASE (APB_BASE + 0x12000) -#define UART3_BASE (APB_BASE + 0x13000) +#define UART0_BASE (APB_BASE + 0x10000) +#define UART1_BASE (APB_BASE + 0x11000) +#define UART2_BASE (APB_BASE + 0x12000) +#define UART3_BASE (APB_BASE + 0x13000) -#define I2C0_BASE (APB_BASE + 0x18000) -#define I2C1_BASE (APB_BASE + 0x19000) +#define I2C0_BASE (APB_BASE + 0x18000) +#define I2C1_BASE (APB_BASE + 0x19000) -#define SPI0_BASE (APB_BASE + 0x1C000) -#define SPI1_BASE (APB_BASE + 0x1D000) +#define SPI0_BASE (APB_BASE + 0x1C000) +#define SPI1_BASE (APB_BASE + 0x1D000) + +#define CAN_BASE (APB_BASE + 0x20000) -#define CAN_BASE (APB_BASE + 0x20000) /******************************************************************************/ /* Peripheral declaration */ /******************************************************************************/ -#define SYS ((SYS_TypeDef *)SYS_BASE) +#define SYS ((SYS_TypeDef *) SYS_BASE) -#define PORT ((PORT_TypeDef *)PORT_BASE) +#define PORT ((PORT_TypeDef *) PORT_BASE) -#define GPIOA ((GPIO_TypeDef *)GPIOA_BASE) -#define GPIOB ((GPIO_TypeDef *)GPIOB_BASE) -#define GPIOC ((GPIO_TypeDef *)GPIOC_BASE) -#define GPIOM ((GPIO_TypeDef *)GPIOM_BASE) -#define GPION ((GPIO_TypeDef *)GPION_BASE) -#define GPIOP ((GPIO_TypeDef *)GPIOP_BASE) +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOM ((GPIO_TypeDef *) GPIOM_BASE) +#define GPION ((GPIO_TypeDef *) GPION_BASE) +#define GPIOP ((GPIO_TypeDef *) GPIOP_BASE) -#define TIMR0 ((TIMR_TypeDef *)TIMR0_BASE) -#define TIMR1 ((TIMR_TypeDef *)TIMR1_BASE) -#define TIMR2 ((TIMR_TypeDef *)TIMR2_BASE) -#define TIMR3 ((TIMR_TypeDef *)TIMR3_BASE) -#define TIMR4 ((TIMR_TypeDef *)TIMR4_BASE) -#define TIMR5 ((TIMR_TypeDef *)TIMR5_BASE) -#define TIMRG ((TIMRG_TypeDef *)TIMRG_BASE) +#define TIMR0 ((TIMR_TypeDef *) TIMR0_BASE) +#define TIMR1 ((TIMR_TypeDef *) TIMR1_BASE) +#define TIMR2 ((TIMR_TypeDef *) TIMR2_BASE) +#define TIMR3 ((TIMR_TypeDef *) TIMR3_BASE) +#define TIMR4 ((TIMR_TypeDef *) TIMR4_BASE) +#define TIMR5 ((TIMR_TypeDef *) TIMR5_BASE) +#define TIMRG ((TIMRG_TypeDef*) TIMRG_BASE) -#define UART0 ((UART_TypeDef *)UART0_BASE) -#define UART1 ((UART_TypeDef *)UART1_BASE) -#define UART2 ((UART_TypeDef *)UART2_BASE) -#define UART3 ((UART_TypeDef *)UART3_BASE) +#define UART0 ((UART_TypeDef *) UART0_BASE) +#define UART1 ((UART_TypeDef *) UART1_BASE) +#define UART2 ((UART_TypeDef *) UART2_BASE) +#define UART3 ((UART_TypeDef *) UART3_BASE) -#define SPI0 ((SPI_TypeDef *)SPI0_BASE) -#define SPI1 ((SPI_TypeDef *)SPI1_BASE) +#define SPI0 ((SPI_TypeDef *) SPI0_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) -#define I2C0 ((I2C_TypeDef *)I2C0_BASE) -#define I2C1 ((I2C_TypeDef *)I2C1_BASE) +#define I2C0 ((I2C_TypeDef *) I2C0_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) -#define ADC0 ((ADC_TypeDef *)ADC0_BASE) -#define ADC1 ((ADC_TypeDef *)ADC1_BASE) +#define ADC0 ((ADC_TypeDef *) ADC0_BASE) +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) -#define PWM0 ((PWM_TypeDef *)PWM0_BASE) -#define PWM1 ((PWM_TypeDef *)PWM1_BASE) -#define PWM2 ((PWM_TypeDef *)PWM2_BASE) -#define PWM3 ((PWM_TypeDef *)PWM3_BASE) -#define PWM4 ((PWM_TypeDef *)PWM4_BASE) -#define PWM5 ((PWM_TypeDef *)PWM5_BASE) -#define PWMG ((PWMG_TypeDef *)PWMG_BASE) +#define PWM0 ((PWM_TypeDef *) PWM0_BASE) +#define PWM1 ((PWM_TypeDef *) PWM1_BASE) +#define PWM2 ((PWM_TypeDef *) PWM2_BASE) +#define PWM3 ((PWM_TypeDef *) PWM3_BASE) +#define PWM4 ((PWM_TypeDef *) PWM4_BASE) +#define PWM5 ((PWM_TypeDef *) PWM5_BASE) +#define PWMG ((PWMG_TypeDef *) PWMG_BASE) -#define SDIO ((SDIO_TypeDef *)SDIO_BASE) +#define SDIO ((SDIO_TypeDef *) SDIO_BASE) -#define DMA ((DMA_TypeDef *)DMA_BASE) +#define DMA ((DMA_TypeDef *) DMA_BASE) -#define CAN ((CAN_TypeDef *)CAN_BASE) +#define CAN ((CAN_TypeDef *) CAN_BASE) -#define LCD ((LCD_TypeDef *)LCD_BASE) +#define LCD ((LCD_TypeDef *) LCD_BASE) -#define CRC ((CRC_TypeDef *)CRC_BASE) +#define CRC ((CRC_TypeDef *) CRC_BASE) -#define RTC ((RTC_TypeDef *)RTC_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) -#define WDT ((WDT_TypeDef *)WDT_BASE) +#define WDT ((WDT_TypeDef *) WDT_BASE) -#define FLASH ((FLASH_Typedef *)FLASH_BASE) +#define FLASH ((FLASH_Typedef*) FLASH_BASE) -#define SRAMC ((SRAMC_TypeDef *)SRAMC_BASE) +#define SRAMC ((SRAMC_TypeDef*) SRAMC_BASE) -#define NORFLC ((NORFLC_TypeDef *)NORFLC_BASE) +#define NORFLC ((NORFLC_TypeDef*) NORFLC_BASE) -#define SDRAMC ((SDRAMC_TypeDef *)SDRAMC_BASE) +#define SDRAMC ((SDRAMC_TypeDef*) SDRAMC_BASE) + + + +typedef void (* Func_void_void) (void); -typedef void (*Func_void_void)(void); #include "SWM320_port.h" #include "SWM320_gpio.h" @@ -3564,4 +3622,5 @@ typedef void (*Func_void_void)(void); #include "SWM320_rtc.h" #include "SWM320_wdt.h" + #endif //__SWM320_H__ diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c b/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c index c367b17d11..a99fa78fc9 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c @@ -1,262 +1,280 @@ -/****************************************************************************************************************************************** -* 文件名称: system_SWM320.c -* 功能说明: SWM320单片机的时钟设置 -* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* 注意事项: -* 版本日期: V1.1.0 2017年10月25日 -* 升级记录: +/****************************************************************************************************************************************** +* ļ: system_SWM320.c +* ˵: SWM320Ƭʱ +* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* ע: +* 汾: V1.1.0 20171025 +* ¼: * * ******************************************************************************************************************************************* * @attention * -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION -* REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE -* FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION +* REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE +* FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN- * -ECTION WITH THEIR PRODUCTS. * * COPYRIGHT 2012 Synwit Technology -*******************************************************************************************************************************************/ +*******************************************************************************************************************************************/ #include #include "SWM320.h" + /****************************************************************************************************************************************** - * 系统时钟设定 + * ϵͳʱ趨 *****************************************************************************************************************************************/ -#define SYS_CLK_20MHz 0 //0 内部高频20MHz RC振荡器 -#define SYS_CLK_40MHz 1 //1 内部高频40MHz RC振荡器 -#define SYS_CLK_32KHz 2 //2 内部低频32KHz RC振荡器 -#define SYS_CLK_XTAL 3 //3 外部晶体振荡器(2-30MHz) -#define SYS_CLK_PLL 4 //4 片内锁相环输出 +#define SYS_CLK_20MHz 0 //0 ڲƵ20MHz RC +#define SYS_CLK_40MHz 1 //1 ڲƵ40MHz RC +#define SYS_CLK_32KHz 2 //2 ڲƵ32KHz RC +#define SYS_CLK_XTAL 3 //3 ⲿ2-30MHz +#define SYS_CLK_PLL 4 //4 Ƭ໷ -#define SYS_CLK SYS_CLK_PLL +#define SYS_CLK SYS_CLK_PLL -#define SYS_CLK_DIV_1 0 -#define SYS_CLK_DIV_2 1 -#define SYS_CLK_DIV SYS_CLK_DIV_1 +#define SYS_CLK_DIV_1 0 +#define SYS_CLK_DIV_2 1 -#define __HSI (20000000UL) //高速内部时钟 -#define __LSI (32000UL) //低速内部时钟 -#define __HSE (20000000UL) //高速外部时钟 +#define SYS_CLK_DIV SYS_CLK_DIV_1 -/********************************** PLL 设定 ********************************************** - * VCO输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV - * PLL输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV / OUTDIV = VCO输出频率 / OUTDIV - *****************************************************************************************/ -#define SYS_PLL_SRC SYS_CLK_20MHz //可取值SYS_CLK_20MHz、SYS_CLK_XTAL -#define PLL_IN_DIV 5 +#define __HSI (20000000UL) //ڲʱ +#define __LSI ( 32000UL) //ڲʱ +#define __HSE (20000000UL) //ⲿʱ -#define PLL_FB_DIV 60 -#define PLL_OUT_DIV8 0 -#define PLL_OUT_DIV4 1 -#define PLL_OUT_DIV2 2 +/********************************** PLL 趨 ********************************************** + * VCOƵ = PLLʱ / INDIV * 4 * FBDIV + * PLLƵ = PLLʱ / INDIV * 4 * FBDIV / OUTDIV = VCOƵ / OUTDIV + *****************************************************************************************/ +#define SYS_PLL_SRC SYS_CLK_20MHz //ȡֵSYS_CLK_20MHzSYS_CLK_XTAL -#define PLL_OUT_DIV PLL_OUT_DIV8 +#define PLL_IN_DIV 5 -uint32_t SystemCoreClock = __HSI; //System Clock Frequency (Core Clock) -uint32_t CyclesPerUs = (__HSI / 1000000); //Cycles per micro second +#define PLL_FB_DIV 60 -/****************************************************************************************************************************************** -* 函数名称: -* 功能说明: This function is used to update the variable SystemCoreClock and must be called whenever the core clock is changed -* 输 入: -* 输 出: -* 注意事项: + +#define PLL_OUT_DIV8 0 +#define PLL_OUT_DIV4 1 +#define PLL_OUT_DIV2 2 + +#define PLL_OUT_DIV PLL_OUT_DIV8 + + + +uint32_t SystemCoreClock = __HSI; //System Clock Frequency (Core Clock) +uint32_t CyclesPerUs = (__HSI / 1000000); //Cycles per micro second + + +/****************************************************************************************************************************************** +* : +* ˵: This function is used to update the variable SystemCoreClock and must be called whenever the core clock is changed +* : +* : +* ע: ******************************************************************************************************************************************/ -void SystemCoreClockUpdate(void) +void SystemCoreClockUpdate(void) { - if (SYS->CLKSEL & SYS_CLKSEL_SYS_Msk) //SYS_CLK <= HFCK - { - if (SYS->CLKSEL & SYS_CLKSEL_HFCK_Msk) //HFCK <= XTAL - { - SystemCoreClock = __HSE; - } - else //HFCK <= HRC - { - if (SYS->HRCCR & SYS_HRCCR_DBL_Msk) //HRC = 40MHz - { - SystemCoreClock = __HSI * 2; - } - else //HRC = 20MHz - { - SystemCoreClock = __HSI; - } - } - } - else //SYS_CLK <= LFCK - { - if (SYS->CLKSEL & SYS_CLKSEL_LFCK_Msk) //LFCK <= PLL - { - if (SYS->PLLCR & SYS_PLLCR_INSEL_Msk) //PLL_SRC <= HRC - { - SystemCoreClock = __HSI; - } - else //PLL_SRC <= XTAL - { - SystemCoreClock = __HSE; - } - - SystemCoreClock = SystemCoreClock / PLL_IN_DIV * PLL_FB_DIV * 4 / (2 << (2 - PLL_OUT_DIV)); - } - else //LFCK <= LRC - { - SystemCoreClock = __LSI; - } - } - - if (SYS->CLKDIV & SYS_CLKDIV_SYS_Msk) - SystemCoreClock /= 2; - - CyclesPerUs = SystemCoreClock / 1000000; + if(SYS->CLKSEL & SYS_CLKSEL_SYS_Msk) //SYS_CLK <= HFCK + { + if(SYS->CLKSEL & SYS_CLKSEL_HFCK_Msk) //HFCK <= XTAL + { + SystemCoreClock = __HSE; + } + else //HFCK <= HRC + { + if(SYS->HRCCR & SYS_HRCCR_DBL_Msk) //HRC = 40MHz + { + SystemCoreClock = __HSI*2; + } + else //HRC = 20MHz + { + SystemCoreClock = __HSI; + } + } + } + else //SYS_CLK <= LFCK + { + if(SYS->CLKSEL & SYS_CLKSEL_LFCK_Msk) //LFCK <= PLL + { + if(SYS->PLLCR & SYS_PLLCR_INSEL_Msk) //PLL_SRC <= HRC + { + SystemCoreClock = __HSI; + } + else //PLL_SRC <= XTAL + { + SystemCoreClock = __HSE; + } + + SystemCoreClock = SystemCoreClock / PLL_IN_DIV * PLL_FB_DIV * 4 / (2 << (2 - PLL_OUT_DIV)); + } + else //LFCK <= LRC + { + SystemCoreClock = __LSI; + } + } + + if(SYS->CLKDIV & SYS_CLKDIV_SYS_Msk) SystemCoreClock /= 2; + + CyclesPerUs = SystemCoreClock / 1000000; } -/****************************************************************************************************************************************** -* 函数名称: -* 功能说明: The necessary initializaiton of systerm -* 输 入: -* 输 出: -* 注意事项: +/****************************************************************************************************************************************** +* : +* ˵: The necessary initializaiton of systerm +* : +* : +* ע: ******************************************************************************************************************************************/ void SystemInit(void) -{ - SYS->CLKEN |= (1 << SYS_CLKEN_ANAC_Pos); - - switch (SYS_CLK) - { - case SYS_CLK_20MHz: //0 内部高频20MHz RC振荡器 - switchCLK_20MHz(); - break; - - case SYS_CLK_40MHz: //1 内部高频40MHz RC振荡器 - switchCLK_40MHz(); - break; - - case SYS_CLK_32KHz: //2 内部低频32KHz RC振荡器 - switchCLK_32KHz(); - break; - - case SYS_CLK_XTAL: //3 外部晶体振荡器(2-30MHz) - switchCLK_XTAL(); - break; - - case SYS_CLK_PLL: //4 片内锁相环输出 - switchCLK_PLL(); - break; - } - - SYS->CLKDIV &= ~SYS_CLKDIV_SYS_Msk; - SYS->CLKDIV |= (SYS_CLK_DIV << SYS_CLKDIV_SYS_Pos); - - SystemCoreClockUpdate(); +{ + SYS->CLKEN |= (1 << SYS_CLKEN_ANAC_Pos); + + Flash_Param_at_xMHz(120); + + switch(SYS_CLK) + { + case SYS_CLK_20MHz: //0 ڲƵ20MHz RC + switchCLK_20MHz(); + break; + + case SYS_CLK_40MHz: //1 ڲƵ40MHz RC + switchCLK_40MHz(); + break; + + case SYS_CLK_32KHz: //2 ڲƵ32KHz RC + switchCLK_32KHz(); + break; + + case SYS_CLK_XTAL: //3 ⲿ2-30MHz + switchCLK_XTAL(); + break; + + case SYS_CLK_PLL: //4 Ƭ໷ + switchCLK_PLL(); + break; + } + + SYS->CLKDIV &= ~SYS_CLKDIV_SYS_Msk; + SYS->CLKDIV |= (SYS_CLK_DIV << SYS_CLKDIV_SYS_Pos); + + SystemCoreClockUpdate(); + + if(SystemCoreClock > 80000000) + { + Flash_Param_at_xMHz(120); + } + else if(SystemCoreClock > 40000000) + { + Flash_Param_at_xMHz(80); + } + else if(SystemCoreClock > 30000000) + { + Flash_Param_at_xMHz(40); + } + else + { + Flash_Param_at_xMHz(30); + } } void switchCLK_20MHz(void) { - uint32_t i; - - SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | - (0 << SYS_HRCCR_DBL_Pos); //HRC = 20MHz - - for (i = 0; i < 1000; i++) - __NOP(); - - SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk; //HFCK <= HRC - SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK + uint32_t i; + + SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | + (0 << SYS_HRCCR_DBL_Pos); //HRC = 20MHz + + for(i = 0; i < 1000; i++) __NOP(); + + SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk; //HFCK <= HRC + SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK } void switchCLK_40MHz(void) { - uint32_t i; - - SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | - (1 << SYS_HRCCR_DBL_Pos); //HRC = 40MHz - - for (i = 0; i < 1000; i++) - __NOP(); - - SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk; //HFCK <= HRC - SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK + uint32_t i; + + SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | + (1 << SYS_HRCCR_DBL_Pos); //HRC = 40MHz + + for(i = 0; i < 1000; i++) __NOP(); + + SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk; //HFCK <= HRC + SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK } void switchCLK_32KHz(void) { - uint32_t i; - - SYS->CLKEN |= (1 << SYS_CLKEN_RTCBKP_Pos); - - SYS->LRCCR &= ~(1 << SYS_LRCCR_OFF_Pos); - - for (i = 0; i < 100; i++) - __NOP(); - - SYS->CLKSEL &= ~SYS_CLKSEL_LFCK_Msk; //LFCK <= LRC - SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk; //SYS_CLK <= LFCK + uint32_t i; + + SYS->CLKEN |= (1 << SYS_CLKEN_RTCBKP_Pos); + + SYS->LRCCR &= ~(1 << SYS_LRCCR_OFF_Pos); + + for(i = 0; i < 100; i++) __NOP(); + + SYS->CLKSEL &= ~SYS_CLKSEL_LFCK_Msk; //LFCK <= LRC + SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk; //SYS_CLK <= LFCK } void switchCLK_XTAL(void) { - uint32_t i; - - SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos); - - for (i = 0; i < 1000; i++) - __NOP(); - - SYS->CLKSEL |= (1 << SYS_CLKSEL_HFCK_Pos); //HFCK <= XTAL - SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK + uint32_t i; + + SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos); + + for(i = 0; i < 1000; i++) __NOP(); + + SYS->CLKSEL |= (1 << SYS_CLKSEL_HFCK_Pos); //HFCK <= XTAL + SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK } void switchCLK_PLL(void) { - uint32_t i; - - PLLInit(); - SYS->PLLCR |= (1 << SYS_PLLCR_OUTEN_Pos); - - for (i = 0; i < 10000; i++) - __NOP(); - - SYS->CLKSEL |= (1 << SYS_CLKSEL_LFCK_Pos); //LFCK <= PLL - SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk; //SYS_CLK <= LFCK + uint32_t i; + + PLLInit(); + SYS->PLLCR |= (1 << SYS_PLLCR_OUTEN_Pos); + + for(i = 0; i < 10000; i++) __NOP(); + + SYS->CLKSEL |= (1 << SYS_CLKSEL_LFCK_Pos); //LFCK <= PLL + SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk; //SYS_CLK <= LFCK } void PLLInit(void) { - uint32_t i; - - if (SYS_PLL_SRC == SYS_CLK_20MHz) - { - SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | - (0 << SYS_HRCCR_DBL_Pos); //HRC = 20MHz - - for (i = 0; i < 1000; i++) - __NOP(); - - SYS->PLLCR |= (1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= HRC - } - else if (SYS_PLL_SRC == SYS_CLK_XTAL) - { - SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos); - - for (i = 0; i < 20000; i++) - ; - - SYS->PLLCR &= ~(1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= XTAL - } - - SYS->PLLDIV &= ~(SYS_PLLDIV_INDIV_Msk | - SYS_PLLDIV_FBDIV_Msk | - SYS_PLLDIV_OUTDIV_Msk); - SYS->PLLDIV |= (PLL_IN_DIV << SYS_PLLDIV_INDIV_Pos) | - (PLL_FB_DIV << SYS_PLLDIV_FBDIV_Pos) | - (PLL_OUT_DIV << SYS_PLLDIV_OUTDIV_Pos); - - SYS->PLLCR &= ~(1 << SYS_PLLCR_OFF_Pos); - - while (SYS->PLLLOCK == 0) - ; //等待PLL锁定 + uint32_t i; + + if(SYS_PLL_SRC == SYS_CLK_20MHz) + { + SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | + (0 << SYS_HRCCR_DBL_Pos); //HRC = 20MHz + + for(i = 0; i < 1000; i++) __NOP(); + + SYS->PLLCR |= (1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= HRC + } + else if(SYS_PLL_SRC == SYS_CLK_XTAL) + { + SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos); + + for(i = 0; i < 20000; i++); + + SYS->PLLCR &= ~(1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= XTAL + } + + SYS->PLLDIV &= ~(SYS_PLLDIV_INDIV_Msk | + SYS_PLLDIV_FBDIV_Msk | + SYS_PLLDIV_OUTDIV_Msk); + SYS->PLLDIV |= (PLL_IN_DIV << SYS_PLLDIV_INDIV_Pos) | + (PLL_FB_DIV << SYS_PLLDIV_FBDIV_Pos) | + (PLL_OUT_DIV<< SYS_PLLDIV_OUTDIV_Pos); + + SYS->PLLCR &= ~(1 << SYS_PLLCR_OFF_Pos); + + while(SYS->PLLLOCK == 0); //ȴPLL } diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.h b/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.h index 4db7f29433..3967e4059c 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.h +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.h @@ -2,24 +2,28 @@ #define __SYSTEM_SWM320_H__ #ifdef __cplusplus -extern "C" -{ + extern "C" { #endif - extern uint32_t SystemCoreClock; // System Clock Frequency (Core Clock) - extern uint32_t CyclesPerUs; // Cycles per micro second - extern void SystemInit(void); +extern uint32_t SystemCoreClock; // System Clock Frequency (Core Clock) +extern uint32_t CyclesPerUs; // Cycles per micro second - extern void SystemCoreClockUpdate(void); - extern void switchCLK_20MHz(void); - extern void switchCLK_40MHz(void); - extern void switchCLK_32KHz(void); - extern void switchCLK_XTAL(void); - extern void switchCLK_PLL(void); +extern void SystemInit(void); + +extern void SystemCoreClockUpdate (void); + + + +extern void switchCLK_20MHz(void); +extern void switchCLK_40MHz(void); +extern void switchCLK_32KHz(void); +extern void switchCLK_XTAL(void); +extern void switchCLK_PLL(void); + +extern void PLLInit(void); - extern void PLLInit(void); #ifdef __cplusplus } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.c index 7f5f64e84e..8f73ec62c9 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_adc.c -* ˵: SWM320ƬADCģת -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_adc.c +* 功能说明: SWM320单片机的ADC数模转换器功能驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: ******************************************************************************************************************************************* * @attention * @@ -21,12 +21,12 @@ /****************************************************************************************************************************************** -* : ADC_Init() -* ˵: ADCģתʼ -* : ADC_TypeDef * ADCx ָҪõADCЧֵADC0ADC1 -* ADC_InitStructure * initStruct ADCضֵĽṹ -* : -* ע: +* 函数名称: ADC_Init() +* 功能说明: ADC模数转换器初始化 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,有效值包括ADC0、ADC1 +* ADC_InitStructure * initStruct 包含ADC各相关定值的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_Init(ADC_TypeDef * ADCx, ADC_InitStructure * initStruct) { @@ -41,7 +41,7 @@ void ADC_Init(ADC_TypeDef * ADCx, ADC_InitStructure * initStruct) break; } - ADC_Close(ADCx); //һЩؼĴֻADCرʱ + ADC_Close(ADCx); //一些关键寄存器只能在ADC关闭时设置 if(initStruct->clk_src == ADC_CLKSRC_HRC) { @@ -80,7 +80,7 @@ void ADC_Init(ADC_TypeDef * ADCx, ADC_InitStructure * initStruct) (initStruct->trig_src << ADC_CTRL_TRIG_Pos) | (initStruct->Continue << ADC_CTRL_CONT_Pos); - ADCx->IF = 0xFFFFFFFF; //жϱ־ + ADCx->IF = 0xFFFFFFFF; //清除中断标志 ADCx->IE &= ~(ADC_IE_CH0EOC_Msk | ADC_IE_CH1EOC_Msk | ADC_IE_CH2EOC_Msk | ADC_IE_CH3EOC_Msk | ADC_IE_CH4EOC_Msk | ADC_IE_CH5EOC_Msk | ADC_IE_CH6EOC_Msk | ADC_IE_CH7EOC_Msk); @@ -153,11 +153,11 @@ void ADC_Init(ADC_TypeDef * ADCx, ADC_InitStructure * initStruct) } /****************************************************************************************************************************************** -* : ADC_Open() -* ˵: ADCӲADCת -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* : -* ע: +* 函数名称: ADC_Open() +* 功能说明: ADC开启,可以软件启动、或硬件触发ADC转换 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_Open(ADC_TypeDef * ADCx) { @@ -165,11 +165,11 @@ void ADC_Open(ADC_TypeDef * ADCx) } /****************************************************************************************************************************************** -* : ADC_Close() -* ˵: ADCرգ޷ӲADCת -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* : -* ע: +* 函数名称: ADC_Close() +* 功能说明: ADC关闭,无法软件启动、或硬件触发ADC转换 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_Close(ADC_TypeDef * ADCx) { @@ -177,11 +177,11 @@ void ADC_Close(ADC_TypeDef * ADCx) } /****************************************************************************************************************************************** -* : ADC_Start() -* ˵: ģʽADCת -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* : -* ע: +* 函数名称: ADC_Start() +* 功能说明: 软件触发模式下启动ADC转换 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_Start(ADC_TypeDef * ADCx) { @@ -189,11 +189,11 @@ void ADC_Start(ADC_TypeDef * ADCx) } /****************************************************************************************************************************************** -* : ADC_Stop() -* ˵: ģʽֹͣADCת -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* : -* ע: +* 函数名称: ADC_Stop() +* 功能说明: 软件触发模式下停止ADC转换 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_Stop(ADC_TypeDef * ADCx) { @@ -220,12 +220,12 @@ static uint32_t chn2idx(uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_Read() -* ˵: ָͨȡת -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪȡתͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : uint32_t ȡת -* ע: +* 函数名称: ADC_Read() +* 功能说明: 从指定通道读取转换结果 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要读取转换结果的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: uint32_t 读取到的转换结果 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t ADC_Read(ADC_TypeDef * ADCx, uint32_t chn) { @@ -234,18 +234,18 @@ uint32_t ADC_Read(ADC_TypeDef * ADCx, uint32_t chn) dat = ADCx->CH[idx].DATA; - ADCx->CH[idx].STAT = 0x01; //EOC־ + ADCx->CH[idx].STAT = 0x01; //清除EOC标志 return dat; } /****************************************************************************************************************************************** -* : ADC_IsEOC() -* ˵: ָͨǷEnd Of Conversion -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn Ҫѯ״̬ͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : uint32_t 1 ͨת 0 ͨδת -* ע: +* 函数名称: ADC_IsEOC() +* 功能说明: 指定通道是否End Of Conversion +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要查询状态的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: uint32_t 1 该通道完成了转换 0 该通道未完成转换 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t ADC_IsEOC(ADC_TypeDef * ADCx, uint32_t chn) { @@ -255,12 +255,12 @@ uint32_t ADC_IsEOC(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_ChnSelect() -* ˵: ADCͨѡͨģתѡͨͨβת -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chns ҪѡͨͨЧֵADC_CH0ADC_CH1... ... ADC_CH7ϣλ㣩 -* : -* ע: +* 函数名称: ADC_ChnSelect() +* 功能说明: ADC通道选通,模数转换会在选通的通道上依次采样转换 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chns 要选通的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_ChnSelect(ADC_TypeDef * ADCx, uint32_t chns) { @@ -270,12 +270,12 @@ void ADC_ChnSelect(ADC_TypeDef * ADCx, uint32_t chns) /****************************************************************************************************************************************** -* : ADC_IntEOCEn() -* ˵: תжʹ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntEOCEn() +* 功能说明: 转换完成中断使能 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntEOCEn(ADC_TypeDef * ADCx, uint32_t chn) { @@ -285,12 +285,12 @@ void ADC_IntEOCEn(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntEOCDis() -* ˵: תжϽֹ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntEOCDis() +* 功能说明: 转换完成中断禁止 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntEOCDis(ADC_TypeDef * ADCx, uint32_t chn) { @@ -300,12 +300,12 @@ void ADC_IntEOCDis(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntEOCClr() -* ˵: תжϱ־ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntEOCClr() +* 功能说明: 转换完成中断标志清除 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntEOCClr(ADC_TypeDef * ADCx, uint32_t chn) { @@ -315,12 +315,12 @@ void ADC_IntEOCClr(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntEOCStat() -* ˵: תж״̬ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪѯͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : uint32_t 1 ͨת 0 ͨδת -* ע: +* 函数名称: ADC_IntEOCStat() +* 功能说明: 转换完成中断状态 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要查询的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: uint32_t 1 该通道完成了转换 0 该通道未完成转换 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t ADC_IntEOCStat(ADC_TypeDef * ADCx, uint32_t chn) { @@ -330,12 +330,12 @@ uint32_t ADC_IntEOCStat(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntOVFEn() -* ˵: жʹ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntOVFEn() +* 功能说明: 数据溢出中断使能 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntOVFEn(ADC_TypeDef * ADCx, uint32_t chn) { @@ -345,12 +345,12 @@ void ADC_IntOVFEn(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntOVFDis() -* ˵: жϽֹ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntOVFDis() +* 功能说明: 数据溢出中断禁止 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntOVFDis(ADC_TypeDef * ADCx, uint32_t chn) { @@ -360,12 +360,12 @@ void ADC_IntOVFDis(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntOVFClr() -* ˵: жϱ־ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntOVFClr() +* 功能说明: 数据溢出中断标志清除 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntOVFClr(ADC_TypeDef * ADCx, uint32_t chn) { @@ -375,12 +375,12 @@ void ADC_IntOVFClr(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntOVFStat() -* ˵: ж״̬ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪѯͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : uint32_t 1 ͨת 0 ͨδת -* ע: +* 函数名称: ADC_IntOVFStat() +* 功能说明: 数据溢出中断状态 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要查询的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: uint32_t 1 该通道完成了转换 0 该通道未完成转换 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t ADC_IntOVFStat(ADC_TypeDef * ADCx, uint32_t chn) { @@ -390,12 +390,12 @@ uint32_t ADC_IntOVFStat(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntHFULLEn() -* ˵: FIFOжʹ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntHFULLEn() +* 功能说明: FIFO半满中断使能 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntHFULLEn(ADC_TypeDef * ADCx, uint32_t chn) { @@ -405,12 +405,12 @@ void ADC_IntHFULLEn(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntHFULLDis() -* ˵: FIFOжϽֹ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntHFULLDis() +* 功能说明: FIFO半满中断禁止 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntHFULLDis(ADC_TypeDef * ADCx, uint32_t chn) { @@ -420,12 +420,12 @@ void ADC_IntHFULLDis(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntHFULLClr() -* ˵: FIFOжϱ־ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntHFULLClr() +* 功能说明: FIFO半满中断标志清除 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntHFULLClr(ADC_TypeDef * ADCx, uint32_t chn) { @@ -435,12 +435,12 @@ void ADC_IntHFULLClr(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntHFULLStat() -* ˵: FIFOж״̬ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪѯͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : uint32_t 1 ͨת 0 ͨδת -* ע: +* 函数名称: ADC_IntHFULLStat() +* 功能说明: FIFO半满中断状态 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要查询的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: uint32_t 1 该通道完成了转换 0 该通道未完成转换 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t ADC_IntHFULLStat(ADC_TypeDef * ADCx, uint32_t chn) { @@ -450,12 +450,12 @@ uint32_t ADC_IntHFULLStat(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntFULLEn() -* ˵: FIFOжʹ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntFULLEn() +* 功能说明: FIFO满中断使能 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntFULLEn(ADC_TypeDef * ADCx, uint32_t chn) { @@ -465,12 +465,12 @@ void ADC_IntFULLEn(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntFULLDis() -* ˵: FIFOжϽֹ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntFULLDis() +* 功能说明: FIFO满中断禁止 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntFULLDis(ADC_TypeDef * ADCx, uint32_t chn) { @@ -480,12 +480,12 @@ void ADC_IntFULLDis(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntFULLClr() -* ˵: FIFOжϱ־ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪõͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : -* ע: +* 函数名称: ADC_IntFULLClr() +* 功能说明: FIFO满中断标志清除 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要设置的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void ADC_IntFULLClr(ADC_TypeDef * ADCx, uint32_t chn) { @@ -495,12 +495,12 @@ void ADC_IntFULLClr(ADC_TypeDef * ADCx, uint32_t chn) } /****************************************************************************************************************************************** -* : ADC_IntFULLStat() -* ˵: FIFOж״̬ -* : ADC_TypeDef * ADCx ָҪõADCȡֵADC -* uint32_t chn ҪѯͨЧֵADC_CH0ADC_CH1... ... ADC_CH7 -* : uint32_t 1 ͨת 0 ͨδת -* ע: +* 函数名称: ADC_IntFULLStat() +* 功能说明: FIFO满中断状态 +* 输 入: ADC_TypeDef * ADCx 指定要被设置的ADC,可取值包括ADC +* uint32_t chn 要查询的通道,有效值ADC_CH0、ADC_CH1、... ... 、ADC_CH7 +* 输 出: uint32_t 1 该通道完成了转换 0 该通道未完成转换 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t ADC_IntFULLStat(ADC_TypeDef * ADCx, uint32_t chn) { diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.h index 56f93c66d8..96e10972e3 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.h @@ -2,18 +2,18 @@ #define __SWM320_ADC_H__ typedef struct { - uint8_t clk_src; //ADCתʱԴADC_CLKSRC_HRCADC_CLKSRC_VCO_DIV16ADC_CLKSRC_VCO_DIV32ADC_CLKSRC_VCO_DIV32 - uint8_t clk_div; //ADCתʱӷƵȡֵ1--31 - uint8_t pga_ref; //PGA׼PGA_REF_INTERNALPGA_REF_EXTERNAL - uint8_t channels; //ADCתͨѡУADC_CH0ADC_CH1... ... ADC_CH7ϣλ㣩 - uint8_t samplAvg; //ȡƽADCתADCһͨתΣǵƽֵΪͨת - uint8_t trig_src; //ADCʽADC_TRIGSRC_SWADC_TRIGSRC_PWMADC_TRIGSRC_TIMR2ADC_TRIGSRC_TIMR3 - uint8_t Continue; //ģʽ£1 תģʽһֱתֱSTARTλ - // 0 תģʽתɺSTARTλԶֹͣת - uint8_t EOC_IEn; //EOCжʹܣÿͨãЧֵΪADC_CH0ADC_CH1... ... ADC_CH7ϣλ㣩 - uint8_t OVF_IEn; //OVFжʹܣÿͨãЧֵΪADC_CH0ADC_CH1... ... ADC_CH7ϣλ㣩 - uint8_t HFULL_IEn; //FIFOжʹܣÿͨãЧֵΪADC_CH0ADC_CH1... ... ADC_CH7ϣλ㣩 - uint8_t FULL_IEn; //FIFO жʹܣÿͨãЧֵΪADC_CH0ADC_CH1... ... ADC_CH7ϣλ㣩 + uint8_t clk_src; //ADC转换时钟源:ADC_CLKSRC_HRC、ADC_CLKSRC_VCO_DIV16、ADC_CLKSRC_VCO_DIV32、ADC_CLKSRC_VCO_DIV32 + uint8_t clk_div; //ADC转换时钟分频,取值1--31 + uint8_t pga_ref; //PGA基准:PGA_REF_INTERNAL、PGA_REF_EXTERNAL + uint8_t channels; //ADC转换通道选中,ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) + uint8_t samplAvg; //采样取平均,触发启动ADC转换后,ADC在一个通道上连续采样、转换多次,并将它们的平均值作为该通道转换结果 + uint8_t trig_src; //ADC触发方式:ADC_TRIGSRC_SW、ADC_TRIGSRC_PWM、ADC_TRIGSRC_TIMR2、ADC_TRIGSRC_TIMR3 + uint8_t Continue; //在软件触发模式下:1 连续转换模式,启动后一直采样、转换,直到软件清除START位 + // 0 单次转换模式,转换完成后START位自动清除停止转换 + uint8_t EOC_IEn; //EOC中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) + uint8_t OVF_IEn; //OVF中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) + uint8_t HFULL_IEn; //FIFO半满中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) + uint8_t FULL_IEn; //FIFO 满中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) } ADC_InitStructure; #define ADC_CH0 0x01 @@ -31,49 +31,49 @@ typedef struct { #define ADC_CLKSRC_VCO_DIV64 4 #define ADC_AVG_SAMPLE1 0 -#define ADC_AVG_SAMPLE2 1 //һת2ΣνƽֵΪת +#define ADC_AVG_SAMPLE2 1 //一次启动连续采样、转换2次,并计算两次结果的平均值作为转换结果 #define ADC_AVG_SAMPLE4 3 #define ADC_AVG_SAMPLE8 7 #define ADC_AVG_SAMPLE16 15 -#define ADC_TRIGSRC_SW 0 //ADC->START.GOд1ת +#define ADC_TRIGSRC_SW 0 //软件触发,即ADC->START.GO写1启动转换 #define ADC_TRIGSRC_PWM 1 -#define PGA_REF_INTERNAL 1 //PGA빲ģƽڲ·ADC_REFPADC_REFN -#define PGA_REF_EXTERNAL 0 //PGA빲ģƽⲿṩ(ADC_REFP + ADC_REFN) ƽֵͬ +#define PGA_REF_INTERNAL 1 //PGA输入共模电平由内部电路产生,ADC_REFP和ADC_REFN可悬空 +#define PGA_REF_EXTERNAL 0 //PGA输入共模电平由外部引脚提供,(ADC_REFP + ADC_REFN) 电平值须与量程相同 -void ADC_Init(ADC_TypeDef * ADCx, ADC_InitStructure * initStruct); //ADCģתʼ -void ADC_Open(ADC_TypeDef * ADCx); //ADCӲADCת -void ADC_Close(ADC_TypeDef * ADCx); //ADCرգ޷ӲADCת -void ADC_Start(ADC_TypeDef * ADCx); //ָADCʼģת -void ADC_Stop(ADC_TypeDef * ADCx); //رָADCֹͣģת +void ADC_Init(ADC_TypeDef * ADCx, ADC_InitStructure * initStruct); //ADC模数转换器初始化 +void ADC_Open(ADC_TypeDef * ADCx); //ADC开启,可以软件启动、或硬件触发ADC转换 +void ADC_Close(ADC_TypeDef * ADCx); //ADC关闭,无法软件启动、或硬件触发ADC转换 +void ADC_Start(ADC_TypeDef * ADCx); //启动指定ADC,开始模数转换 +void ADC_Stop(ADC_TypeDef * ADCx); //关闭指定ADC,停止模数转换 -uint32_t ADC_Read(ADC_TypeDef * ADCx, uint32_t chn); //ָͨȡת -uint32_t ADC_IsEOC(ADC_TypeDef * ADCx, uint32_t chn); //ָͨǷEnd Of Conversion +uint32_t ADC_Read(ADC_TypeDef * ADCx, uint32_t chn); //从指定通道读取转换结果 +uint32_t ADC_IsEOC(ADC_TypeDef * ADCx, uint32_t chn); //指定通道是否End Of Conversion void ADC_ChnSelect(ADC_TypeDef * ADCx, uint32_t chns); -void ADC_IntEOCEn(ADC_TypeDef * ADCx, uint32_t chn); //תжʹ -void ADC_IntEOCDis(ADC_TypeDef * ADCx, uint32_t chn); //תжϽֹ -void ADC_IntEOCClr(ADC_TypeDef * ADCx, uint32_t chn); //תжϱ־ -uint32_t ADC_IntEOCStat(ADC_TypeDef * ADCx, uint32_t chn); //תж״̬ +void ADC_IntEOCEn(ADC_TypeDef * ADCx, uint32_t chn); //转换完成中断使能 +void ADC_IntEOCDis(ADC_TypeDef * ADCx, uint32_t chn); //转换完成中断禁止 +void ADC_IntEOCClr(ADC_TypeDef * ADCx, uint32_t chn); //转换完成中断标志清除 +uint32_t ADC_IntEOCStat(ADC_TypeDef * ADCx, uint32_t chn); //转换完成中断状态 -void ADC_IntOVFEn(ADC_TypeDef * ADCx, uint32_t chn); //жʹ -void ADC_IntOVFDis(ADC_TypeDef * ADCx, uint32_t chn); //жϽֹ -void ADC_IntOVFClr(ADC_TypeDef * ADCx, uint32_t chn); //жϱ־ -uint32_t ADC_IntOVFStat(ADC_TypeDef * ADCx, uint32_t chn); //ж״̬ +void ADC_IntOVFEn(ADC_TypeDef * ADCx, uint32_t chn); //数据溢出中断使能 +void ADC_IntOVFDis(ADC_TypeDef * ADCx, uint32_t chn); //数据溢出中断禁止 +void ADC_IntOVFClr(ADC_TypeDef * ADCx, uint32_t chn); //数据溢出中断标志清除 +uint32_t ADC_IntOVFStat(ADC_TypeDef * ADCx, uint32_t chn); //数据溢出中断状态 -void ADC_IntHFULLEn(ADC_TypeDef * ADCx, uint32_t chn); //FIFOжʹ -void ADC_IntHFULLDis(ADC_TypeDef * ADCx, uint32_t chn); //FIFOжϽֹ -void ADC_IntHFULLClr(ADC_TypeDef * ADCx, uint32_t chn); //FIFOжϱ־ -uint32_t ADC_IntHFULLStat(ADC_TypeDef * ADCx, uint32_t chn);//FIFOж״̬ +void ADC_IntHFULLEn(ADC_TypeDef * ADCx, uint32_t chn); //FIFO半满中断使能 +void ADC_IntHFULLDis(ADC_TypeDef * ADCx, uint32_t chn); //FIFO半满中断禁止 +void ADC_IntHFULLClr(ADC_TypeDef * ADCx, uint32_t chn); //FIFO半满中断标志清除 +uint32_t ADC_IntHFULLStat(ADC_TypeDef * ADCx, uint32_t chn);//FIFO半满中断状态 -void ADC_IntFULLEn(ADC_TypeDef * ADCx, uint32_t chn); //FIFOжʹ -void ADC_IntFULLDis(ADC_TypeDef * ADCx, uint32_t chn); //FIFOжϽֹ -void ADC_IntFULLClr(ADC_TypeDef * ADCx, uint32_t chn); //FIFOжϱ־ -uint32_t ADC_IntFULLStat(ADC_TypeDef * ADCx, uint32_t chn); //FIFOж״̬ +void ADC_IntFULLEn(ADC_TypeDef * ADCx, uint32_t chn); //FIFO满中断使能 +void ADC_IntFULLDis(ADC_TypeDef * ADCx, uint32_t chn); //FIFO满中断禁止 +void ADC_IntFULLClr(ADC_TypeDef * ADCx, uint32_t chn); //FIFO满中断标志清除 +uint32_t ADC_IntFULLStat(ADC_TypeDef * ADCx, uint32_t chn); //FIFO满中断状态 #endif //__SWM320_ADC_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.c index c5c5f34a45..e7b30e3cb2 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.c @@ -411,18 +411,6 @@ void CAN_INTRXNotEmptyDis(CAN_TypeDef * CANx) CANx->IE &= ~(1 << CAN_IE_RXDA_Pos); } -/****************************************************************************************************************************************** -* : CAN_INTRXNotEmptyStat() -* ˵: RX FIFOǿжǷ񴥷 -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 Ѵ 0 δ -* ע: -******************************************************************************************************************************************/ -uint32_t CAN_INTRXNotEmptyStat(CAN_TypeDef * CANx) -{ - return (CANx->IF & CAN_IF_RXDA_Msk) ? 1 : 0; -} - /****************************************************************************************************************************************** * : CAN_INTTXBufEmptyEn() * ˵: TX Bufferʱжʹ @@ -447,18 +435,6 @@ void CAN_INTTXBufEmptyDis(CAN_TypeDef * CANx) CANx->IE &= ~(1 << CAN_IE_TXBR_Pos); } -/****************************************************************************************************************************************** -* : CAN_INTTXBufEmptyStat() -* ˵: TX BufferжǷ񴥷 -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 Ѵ 0 δ -* ע: -******************************************************************************************************************************************/ -uint32_t CAN_INTTXBufEmptyStat(CAN_TypeDef * CANx) -{ - return (CANx->IF & CAN_IF_TXBR_Msk) ? 1 : 0; -} - /****************************************************************************************************************************************** * : CAN_INTErrWarningEn() * ˵: TXERR/RXERRֵﵽError Warning Limitʱжʹ @@ -483,18 +459,6 @@ void CAN_INTErrWarningDis(CAN_TypeDef * CANx) CANx->IE &= ~(1 << CAN_IE_ERRWARN_Pos); } -/****************************************************************************************************************************************** -* : CAN_INTErrWarningStat() -* ˵: TXERR/RXERRֵﵽError Warning LimitжǷ񴥷 -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 Ѵ 0 δ -* ע: -******************************************************************************************************************************************/ -uint32_t CAN_INTErrWarningStat(CAN_TypeDef * CANx) -{ - return (CANx->IF & CAN_IF_ERRWARN_Msk) ? 1 : 0; -} - /****************************************************************************************************************************************** * : CAN_INTRXOverflowEn() * ˵: RX FIFO ʱжʹ @@ -519,18 +483,6 @@ void CAN_INTRXOverflowDis(CAN_TypeDef * CANx) CANx->IE &= ~(1 << CAN_IE_RXOV_Pos); } -/****************************************************************************************************************************************** -* : CAN_INTRXOverflowStat() -* ˵: RX FIFO жǷ񴥷 -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 Ѵ 0 δ -* ע: -******************************************************************************************************************************************/ -uint32_t CAN_INTRXOverflowStat(CAN_TypeDef * CANx) -{ - return (CANx->IF & CAN_IF_RXOV_Msk) ? 1 : 0; -} - /****************************************************************************************************************************************** * : CAN_INTRXOverflowClear() * ˵: RX FIFO ж @@ -567,18 +519,6 @@ void CAN_INTWakeupDis(CAN_TypeDef * CANx) CANx->IE &= ~(1 << CAN_IE_WKUP_Pos); } -/****************************************************************************************************************************************** -* : CAN_INTWakeupStat() -* ˵: ¼жǷ񴥷 -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 Ѵ 0 δ -* ע: -******************************************************************************************************************************************/ -uint32_t CAN_INTWakeupStat(CAN_TypeDef * CANx) -{ - return (CANx->IF & CAN_IF_WKUP_Msk) ? 1 : 0; -} - /****************************************************************************************************************************************** * : CAN_INTErrPassiveEn() * ˵: TXERR/RXERRֵﵽ127ʱжʹ @@ -603,18 +543,6 @@ void CAN_INTErrPassiveDis(CAN_TypeDef * CANx) CANx->IE &= ~(1 << CAN_IE_ERRPASS_Pos); } -/****************************************************************************************************************************************** -* : CAN_INTErrPassiveStat() -* ˵: TXERR/RXERRֵﵽ127жǷ񴥷 -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 Ѵ 0 δ -* ע: -******************************************************************************************************************************************/ -uint32_t CAN_INTErrPassiveStat(CAN_TypeDef * CANx) -{ - return (CANx->IF & CAN_IF_ERRPASS_Msk) ? 1 : 0; -} - /****************************************************************************************************************************************** * : CAN_INTArbitrLostEn() * ˵: ٲʧжʹ @@ -639,18 +567,6 @@ void CAN_INTArbitrLostDis(CAN_TypeDef * CANx) CANx->IE &= ~(1 << CAN_IE_ARBLOST_Pos); } -/****************************************************************************************************************************************** -* : CAN_INTArbitrLostStat() -* ˵: ٲʧжǷ񴥷 -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 Ѵ 0 δ -* ע: -******************************************************************************************************************************************/ -uint32_t CAN_INTArbitrLostStat(CAN_TypeDef * CANx) -{ - return (CANx->IF & CAN_IF_ARBLOST_Msk) ? 1 : 0; -} - /****************************************************************************************************************************************** * : CAN_INTBusErrorEn() * ˵: ߴжʹ @@ -676,13 +592,13 @@ void CAN_INTBusErrorDis(CAN_TypeDef * CANx) } /****************************************************************************************************************************************** -* : CAN_INTBusErrorStat() -* ˵: ߴжǷ񴥷 +* : CAN_INTStat() +* ˵: ѯж״̬ * : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 Ѵ 0 δ -* ע: +* : uint32_t ǰж״̬ +* ע: CANx->IFȡ㣬жISRֻܶȡһΣܶζȡ ******************************************************************************************************************************************/ -uint32_t CAN_INTBusErrorStat(CAN_TypeDef * CANx) +uint32_t CAN_INTStat(CAN_TypeDef * CANx) { - return (CANx->IF & CAN_IF_BUSERR_Msk) ? 1 : 0; + return CANx->IF; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.h index 7b66ee4d5c..7cdd751ca5 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.h @@ -5,14 +5,14 @@ #define CAN_FRAME_EXT 1 typedef struct { - uint8_t Mode; //CAN_MODE_NORMALCAN_MODE_LISTENCAN_MODE_SELFTEST - uint8_t CAN_BS1; //CAN_BS1_1tqCAN_BS1_2tq... ... CAN_BS1_16tq - uint8_t CAN_BS2; //CAN_BS2_1tqCAN_BS2_2tq... ... CAN_BS2_8tq - uint8_t CAN_SJW; //CAN_SJW_1tqCAN_SJW_2tqCAN_SJW_3tqCAN_SJW_4tq - uint32_t Baudrate; //ʣλʣȡֵ1--1000000 - uint8_t FilterMode; //CAN_FILTER_16bCAN_FILTER_32b + uint8_t Mode; //CAN_MODE_NORMAL、CAN_MODE_LISTEN、CAN_MODE_SELFTEST + uint8_t CAN_BS1; //CAN_BS1_1tq、CAN_BS1_2tq、... ... 、CAN_BS1_16tq + uint8_t CAN_BS2; //CAN_BS2_1tq、CAN_BS2_2tq、... ... 、CAN_BS2_8tq + uint8_t CAN_SJW; //CAN_SJW_1tq、CAN_SJW_2tq、CAN_SJW_3tq、CAN_SJW_4tq + uint32_t Baudrate; //波特率,即位传输速率,取值1--1000000 + uint8_t FilterMode; //CAN_FILTER_16b、CAN_FILTER_32b union { - uint32_t FilterMask32b; //FilterCheck & (~FilterMask) == ID & (~FilterMask)Messageͨ + uint32_t FilterMask32b; //FilterCheck & (~FilterMask) == ID & (~FilterMask)的Message通过过滤 struct { // 0 must match 1 don't care uint16_t FilterMask16b1; uint16_t FilterMask16b2; @@ -25,15 +25,15 @@ typedef struct { uint16_t FilterCheck16b2; }; }; - uint8_t RXNotEmptyIEn; //FIFOǿգݿɶ - uint8_t RXOverflowIEn; //FIFOݶʧ - uint8_t ArbitrLostIEn; //ʧٲñɽշ - uint8_t ErrPassiveIEn; ///ʹֵﵽ127 + uint8_t RXNotEmptyIEn; //接收FIFO非空,有数据可读 + uint8_t RXOverflowIEn; //接收FIFO溢出,有数据丢失 + uint8_t ArbitrLostIEn; //控制器丢失仲裁变成接收方 + uint8_t ErrPassiveIEn; //接收/发送错误计数值达到127 } CAN_InitStructure; -#define CAN_MODE_NORMAL 0 //ģʽ -#define CAN_MODE_LISTEN 1 //ģʽ -#define CAN_MODE_SELFTEST 2 //Բģʽ +#define CAN_MODE_NORMAL 0 //常规模式 +#define CAN_MODE_LISTEN 1 //监听模式 +#define CAN_MODE_SELFTEST 2 //自测模式 #define CAN_BS1_1tq 0 #define CAN_BS1_2tq 1 @@ -66,15 +66,15 @@ typedef struct { #define CAN_SJW_3tq 2 #define CAN_SJW_4tq 3 -#define CAN_FILTER_16b 0 //16λ -#define CAN_FILTER_32b 1 //һ32λ +#define CAN_FILTER_16b 0 //两个16位过滤器 +#define CAN_FILTER_32b 1 //一个32位过滤器 typedef struct { - uint32_t id; //ϢID - uint8_t format; //֡ʽCAN_FRAME_STDCAN_FRAME_EXT - uint8_t remote; //ϢǷΪԶ֡ - uint8_t size; //յݸ - uint8_t data[8]; //յ + uint32_t id; //消息ID + uint8_t format; //帧格式:CAN_FRAME_STD、CAN_FRAME_EXT + uint8_t remote; //消息是否为远程帧 + uint8_t size; //接收到的数据个数 + uint8_t data[8]; //接收到的数据 } CAN_RXMessage; @@ -102,35 +102,29 @@ void CAN_SetFilter16b(CAN_TypeDef * CANx, uint16_t check1, uint16_t mask1, uint1 void CAN_INTRXNotEmptyEn(CAN_TypeDef * CANx); void CAN_INTRXNotEmptyDis(CAN_TypeDef * CANx); -uint32_t CAN_INTRXNotEmptyStat(CAN_TypeDef * CANx); void CAN_INTTXBufEmptyEn(CAN_TypeDef * CANx); void CAN_INTTXBufEmptyDis(CAN_TypeDef * CANx); -uint32_t CAN_INTTXBufEmptyStat(CAN_TypeDef * CANx); void CAN_INTErrWarningEn(CAN_TypeDef * CANx); void CAN_INTErrWarningDis(CAN_TypeDef * CANx); -uint32_t CAN_INTErrWarningStat(CAN_TypeDef * CANx); void CAN_INTRXOverflowEn(CAN_TypeDef * CANx); void CAN_INTRXOverflowDis(CAN_TypeDef * CANx); -uint32_t CAN_INTRXOverflowStat(CAN_TypeDef * CANx); void CAN_INTRXOverflowClear(CAN_TypeDef * CANx); void CAN_INTWakeupEn(CAN_TypeDef * CANx); void CAN_INTWakeupDis(CAN_TypeDef * CANx); -uint32_t CAN_INTWakeupStat(CAN_TypeDef * CANx); void CAN_INTErrPassiveEn(CAN_TypeDef * CANx); void CAN_INTErrPassiveDis(CAN_TypeDef * CANx); -uint32_t CAN_INTErrPassiveStat(CAN_TypeDef * CANx); void CAN_INTArbitrLostEn(CAN_TypeDef * CANx); void CAN_INTArbitrLostDis(CAN_TypeDef * CANx); -uint32_t CAN_INTArbitrLostStat(CAN_TypeDef * CANx); void CAN_INTBusErrorEn(CAN_TypeDef * CANx); void CAN_INTBusErrorDis(CAN_TypeDef * CANx); -uint32_t CAN_INTBusErrorStat(CAN_TypeDef * CANx); + +uint32_t CAN_INTStat(CAN_TypeDef * CANx); #endif //__SWM320_CAN_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.h index ce9f1f3731..6a5dd2f781 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.h @@ -2,22 +2,22 @@ #define __SWM320_CRC_H__ -#define CRC32_IN32 0 //CRC32㷨32λ -#define CRC32_IN16 2 //CRC32㷨16λ -#define CRC32_IN8 4 //CRC32㷨 8λ -#define CRC16_IN16 3 //CRC16㷨16λ -#define CRC16_IN8 5 //CRC16㷨 8λ +#define CRC32_IN32 0 //CRC32算法,输入数据32位 +#define CRC32_IN16 2 //CRC32算法,输入数据16位 +#define CRC32_IN8 4 //CRC32算法,输入数据 8位 +#define CRC16_IN16 3 //CRC16算法,输入数据16位 +#define CRC16_IN8 5 //CRC16算法,输入数据 8位 void CRC_Init(CRC_TypeDef * CRCx, uint32_t mode, uint32_t out_not, uint32_t out_rev, uint32_t ini_val); /****************************************************************************************************************************************** -* : CRC_Write() -* ˵: CRCд -* : uint32_t data Ҫд -* : -* ע: +* 函数名称: CRC_Write() +* 功能说明: CRC写入数据 +* 输 入: uint32_t data 要写入的数据 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ static __INLINE void CRC_Write(uint32_t data) { @@ -25,11 +25,11 @@ static __INLINE void CRC_Write(uint32_t data) } /****************************************************************************************************************************************** -* : CRC_Result() -* ˵: ȡCRC -* : -* : uint32_t CRC -* ע: +* 函数名称: CRC_Result() +* 功能说明: 获取CRC计算结果 +* 输 入: 无 +* 输 出: uint32_t CRC 计算结果 +* 注意事项: 无 ******************************************************************************************************************************************/ static __INLINE uint32_t CRC_Result(void) { diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.h index 817162cd65..0857f7d023 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.h @@ -7,14 +7,14 @@ #define DMA_CH2 2 -void DMA_CHM_Config(uint32_t chn, uint32_t src_addr, uint32_t src_addr_incr, uint32_t dst_addr, uint32_t dst_addr_incr, uint32_t num_word, uint32_t int_en); //DMAͨãڴ洢䣨FlashRAM䣩 -void DMA_CH_Open(uint32_t chn); //DMAͨ -void DMA_CH_Close(uint32_t chn); //DMAͨر +void DMA_CHM_Config(uint32_t chn, uint32_t src_addr, uint32_t src_addr_incr, uint32_t dst_addr, uint32_t dst_addr_incr, uint32_t num_word, uint32_t int_en); //DMA通道配置,用于存储器间(如Flash和RAM间)搬运数据 +void DMA_CH_Open(uint32_t chn); //DMA通道打开 +void DMA_CH_Close(uint32_t chn); //DMA通道关闭 -void DMA_CH_INTEn(uint32_t chn); //DMAжʹܣݰɺ󴥷ж -void DMA_CH_INTDis(uint32_t chn); //DMAжϽֹݰɺ󲻴ж -void DMA_CH_INTClr(uint32_t chn); //DMAжϱ־ -uint32_t DMA_CH_INTStat(uint32_t chn); //DMAж״̬ѯ1 ݰ 0 ݰδ +void DMA_CH_INTEn(uint32_t chn); //DMA中断使能,数据搬运完成后触发中断 +void DMA_CH_INTDis(uint32_t chn); //DMA中断禁止,数据搬运完成后不触发中断 +void DMA_CH_INTClr(uint32_t chn); //DMA中断标志清除 +uint32_t DMA_CH_INTStat(uint32_t chn); //DMA中断状态查询,1 数据搬运完成 0 数据搬运未完成 #endif //__SWM320_DMA_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.h index 088cd9a619..529770e6a6 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.h @@ -1,20 +1,20 @@ #ifndef __SWM320_EXTI_H__ #define __SWM320_EXTI_H__ -void EXTI_Init(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t mode); //ָⲿжϳʼ -void EXTI_Open(GPIO_TypeDef * GPIOx, uint32_t n); //ָⲿжϴ򿪣ʹܣ -void EXTI_Close(GPIO_TypeDef * GPIOx, uint32_t n); //ָⲿжϹرգܣ +void EXTI_Init(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t mode); //指定引脚外部中断初始化 +void EXTI_Open(GPIO_TypeDef * GPIOx, uint32_t n); //指定引脚外部中断打开(即使能) +void EXTI_Close(GPIO_TypeDef * GPIOx, uint32_t n); //指定引脚外部中断关闭(即禁能) -uint32_t EXTI_State(GPIO_TypeDef * GPIOx, uint32_t n); //ָǷ񴥷ж -uint32_t EXTI_RawState(GPIO_TypeDef * GPIOx, uint32_t n); //ָǷ/жϴжϹرʱͨô˺ԲѯķʽǷ/жϴ -void EXTI_Clear(GPIO_TypeDef * GPIOx, uint32_t n); //ָⲿжжϱ־ٴνжϣ +uint32_t EXTI_State(GPIO_TypeDef * GPIOx, uint32_t n); //指定引脚是否触发了中断 +uint32_t EXTI_RawState(GPIO_TypeDef * GPIOx, uint32_t n); //指定引脚是否满足过/了中断触发条件,当此中断关闭时可通过调用此函数以查询的方式检测引脚上是否满足过/了中断触发条件 +void EXTI_Clear(GPIO_TypeDef * GPIOx, uint32_t n); //指定引脚外部中断清除(即清除中断标志,以免再次进入此中断) -#define EXTI_FALL_EDGE 0x00 //½شж -#define EXTI_RISE_EDGE 0x01 //شж -#define EXTI_BOTH_EDGE 0x02 //˫شж -#define EXTI_LOW_LEVEL 0x10 //͵ƽж -#define EXTI_HIGH_LEVEL 0x11 //ߵƽж +#define EXTI_FALL_EDGE 0x00 //下降沿触发中断 +#define EXTI_RISE_EDGE 0x01 //上升沿触发中断 +#define EXTI_BOTH_EDGE 0x02 //双边沿触发中断 +#define EXTI_LOW_LEVEL 0x10 //低电平触发中断 +#define EXTI_HIGH_LEVEL 0x11 //高电平触发中断 #endif //__SWM320_EXTI_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.c index dbd0eca4bf..d384125db3 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_flash.c -* ˵: ʹоƬIAPܽƬFlashģEEPROMݣ󲻶ʧ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_flash.c +* 功能说明: 使用芯片的IAP功能将片上Flash模拟成EEPROM来保存数据,掉电后不丢失 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: ******************************************************************************************************************************************* * @attention * @@ -27,11 +27,11 @@ IAP_Flash_Write_t IAP_Flash_Write = (IAP_Flash_Write_t)0x11000801; /****************************************************************************************************************************************** -* : FLASH_Erase() -* ˵: ƬFlash -* : uint32_t addr ַСΪ4K Byte -* : -* ע: +* 函数名称: FLASH_Erase() +* 功能说明: 片内Flash擦除 +* 输 入: uint32_t addr 擦除地址,扇区大小为4K Byte +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void FLASH_Erase(uint32_t addr) { @@ -45,13 +45,13 @@ void FLASH_Erase(uint32_t addr) } /****************************************************************************************************************************************** -* : FLASH_Write() -* ˵: ƬFlashд -* : uint32_t addr дַ -* uint32_t buff[] Ҫд -* uint32_t count ҪдݵĸΪλұ4д4 -* : -* ע: дݸ4д4 +* 函数名称: FLASH_Write() +* 功能说明: 片内Flash写入 +* 输 入: uint32_t addr 写入地址 +* uint32_t buff[] 要写入的数据 +* uint32_t count 要写入数据的个数,以字为单位,且必须是4的整数倍,即最少写入4个字 +* 输 出: 无 +* 注意事项: 写入数据个数必须是4的整数倍,即最少写入4个字 ******************************************************************************************************************************************/ void FLASH_Write(uint32_t addr, uint32_t buff[], uint32_t count) { @@ -65,17 +65,33 @@ void FLASH_Write(uint32_t addr, uint32_t buff[], uint32_t count) } /****************************************************************************************************************************************** -* : Flash_Param_at_120MHz() -* ˵: Flashó120MHzƵʱIJ -* : -* : -* ע: +* 函数名称: Flash_Param_at_xMHz() +* 功能说明: 将Flash参数设置成xMHz主频下运行时所需的参数 +* 输 入: uint32_t x 可取值 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void Flash_Param_at_120MHz(void) +void Flash_Param_at_xMHz(uint32_t x) { __disable_irq(); + switch(x) + { + case 30: + IAP_Flash_Param(0x489, 0xabf41f25); + break; - IAP_Flash_Param(0x48a, 0xabfc7a6e); + case 40: + IAP_Flash_Param(0x489, 0xabf42929); + break; + case 80: + IAP_Flash_Param(0x489, 0xabf8524d); + break; + + case 120: + default: + IAP_Flash_Param(0x48a, 0xabfc7a6e); + break; + } __enable_irq(); } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.h index 113e2a2e07..40f64fac42 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.h @@ -5,7 +5,7 @@ void FLASH_Erase(uint32_t addr); void FLASH_Write(uint32_t addr, uint32_t buff[], uint32_t count); -void Flash_Param_at_120MHz(void); +void Flash_Param_at_xMHz(uint32_t x); diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.c index 1d2aa3a2ab..932608a9e9 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.c @@ -31,7 +31,7 @@ * uint32_t pull_up 裬0 ر 1 * uint32_t pull_down 裬0 ر 1 * : -* ע: GPIOAGPIOCGPIOMGPIOPֻGPIOBGPIONֻ +* ע: GPIOAGPIOCGPIOMGPIOPֻGPIOBGPIONֻPN0PN1PN2û ******************************************************************************************************************************************/ void GPIO_Init(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t dir, uint32_t pull_up, uint32_t pull_down) { diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.h index bcb59b0bee..3ced2d736e 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.h @@ -2,16 +2,16 @@ #define __SWM320_GPIO_H__ -void GPIO_Init(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t dir, uint32_t pull_up, uint32_t pull_down); //ųʼŷ衢 +void GPIO_Init(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t dir, uint32_t pull_up, uint32_t pull_down); //引脚初始化,包含引脚方向、上拉电阻、下拉电阻 -void GPIO_SetBit(GPIO_TypeDef * GPIOx, uint32_t n); //ָŵƽø -void GPIO_ClrBit(GPIO_TypeDef * GPIOx, uint32_t n); //ָŵƽõ -void GPIO_InvBit(GPIO_TypeDef * GPIOx, uint32_t n); //ָŵƽת -uint32_t GPIO_GetBit(GPIO_TypeDef * GPIOx, uint32_t n); //ȡָŵĵƽ״̬ -void GPIO_SetBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //ָĴnʼwλŵĵƽø -void GPIO_ClrBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //ָĴnʼwλŵĵƽõ -void GPIO_InvBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //ָĴnʼwλŵĵƽת -uint32_t GPIO_GetBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //ȡָĴnʼwλŵĵƽ״̬ +void GPIO_SetBit(GPIO_TypeDef * GPIOx, uint32_t n); //将参数指定的引脚电平置高 +void GPIO_ClrBit(GPIO_TypeDef * GPIOx, uint32_t n); //将参数指定的引脚电平置低 +void GPIO_InvBit(GPIO_TypeDef * GPIOx, uint32_t n); //将参数指定的引脚电平反转 +uint32_t GPIO_GetBit(GPIO_TypeDef * GPIOx, uint32_t n); //读取参数指定的引脚的电平状态 +void GPIO_SetBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //将参数指定的从n开始的w位连续引脚的电平置高 +void GPIO_ClrBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //将参数指定的从n开始的w位连续引脚的电平置低 +void GPIO_InvBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //将参数指定的从n开始的w位连续引脚的电平反转 +uint32_t GPIO_GetBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //读取参数指定的从n开始的w位连续引脚的电平状态 void GPIO_AtomicSetBit(GPIO_TypeDef * GPIOx, uint32_t n); void GPIO_AtomicClrBit(GPIO_TypeDef * GPIOx, uint32_t n); diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.h index fc52e9265e..02f1292a28 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.h @@ -2,19 +2,19 @@ #define __SWM320_I2C_H__ typedef struct { - uint8_t Master; //1 ģʽ - uint8_t Addr7b; //1 7λַ 0 10λַ + uint8_t Master; //1 主机模式 + uint8_t Addr7b; //1 7位地址 0 10位地址 - uint32_t MstClk; //ʱƵ - uint8_t MstIEn; //ģʽжʹ + uint32_t MstClk; //主机传输时钟频率 + uint8_t MstIEn; //主机模式中断使能 - uint16_t SlvAddr; //ӻַ - uint8_t SlvRxEndIEn; //ӻжʹ - uint8_t SlvTxEndIEn; //ӻжʹ - uint8_t SlvSTADetIEn; //ӻ⵽ʼжʹ - uint8_t SlvSTODetIEn; //ӻ⵽ֹжʹ - uint8_t SlvRdReqIEn; //ӻյжʹ - uint8_t SlvWrReqIEn; //ӻյджʹ + uint16_t SlvAddr; //从机地址 + uint8_t SlvRxEndIEn; //从机接收完成中断使能 + uint8_t SlvTxEndIEn; //从机发送完成中断使能 + uint8_t SlvSTADetIEn; //从机检测到起始中断使能 + uint8_t SlvSTODetIEn; //从机检测到终止中断使能 + uint8_t SlvRdReqIEn; //从机接收到读请求中断使能 + uint8_t SlvWrReqIEn; //从机接收到写请求中断使能 } I2C_InitStructure; diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.c index 5220cb8046..c26ea71f9d 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_lcd.c -* ˵: SWM320ƬLCD -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_lcd.c +* 功能说明: SWM320单片机的LCD功能驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -24,12 +24,12 @@ #include /****************************************************************************************************************************************** -* : LCD_Init() -* ˵: LCDʼ -* : LCD_TypeDef * LCDx ָҪõLCDЧֵLCD -* LCD_InitStructure * initStruct LCD趨ֵĽṹ -* : -* ע: +* 函数名称: LCD_Init() +* 功能说明: LCD初始化 +* 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD +* LCD_InitStructure * initStruct 包含LCD相关设定值的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void LCD_Init(LCD_TypeDef * LCDx, LCD_InitStructure * initStruct) { @@ -39,30 +39,21 @@ void LCD_Init(LCD_TypeDef * LCDx, LCD_InitStructure * initStruct) SYS->CLKEN |= (0x01 << SYS_CLKEN_LCD_Pos); break; } - - if(initStruct->Interface == LCD_INTERFACE_RGB) - { - LCDx->START = (0 << LCD_START_MPUEN_Pos); - - LCDx->CR0 = ((initStruct->HnPixel - 1) << LCD_CR0_HPIX_Pos) | - ((initStruct->VnPixel - 1) << LCD_CR0_VPIX_Pos) | - (initStruct->ClkAlways << LCD_CR0_DCLK_Pos) | - (initStruct->HsyncWidth << LCD_CR0_HLOW_Pos); - - LCDx->CR1 = ((initStruct->Hfp - 1) << LCD_CR1_HFP_Pos) | - ((initStruct->Hbp - 1) << LCD_CR1_HBP_Pos) | - ((initStruct->Vfp - 1) << LCD_CR1_VFP_Pos) | - ((initStruct->Vbp - 1) << LCD_CR1_VBP_Pos) | - (initStruct->ClkDiv << LCD_CR1_DCLKDIV_Pos) | - (initStruct->SamplEdge << LCD_CR1_DCLKINV_Pos); - } - else if(initStruct->Interface == LCD_INTERFACE_I80) - { - // - } + + LCDx->CR0 = ((initStruct->HnPixel - 1) << LCD_CR0_HPIX_Pos) | + ((initStruct->VnPixel - 1) << LCD_CR0_VPIX_Pos) | + (initStruct->ClkAlways << LCD_CR0_DCLK_Pos) | + (initStruct->HsyncWidth << LCD_CR0_HLOW_Pos); + + LCDx->CR1 = ((initStruct->Hfp - 1) << LCD_CR1_HFP_Pos) | + ((initStruct->Hbp - 1) << LCD_CR1_HBP_Pos) | + ((initStruct->Vfp - 1) << LCD_CR1_VFP_Pos) | + ((initStruct->Vbp - 1) << LCD_CR1_VBP_Pos) | + (initStruct->ClkDiv << LCD_CR1_DCLKDIV_Pos) | + (initStruct->SamplEdge << LCD_CR1_DCLKINV_Pos); LCDx->IE = 1; - LCDx->IF = 1; //־ + LCDx->IF = 1; //清除标志 if(initStruct->IntEOTEn) LCD_INTEn(LCDx); else LCD_INTDis(LCDx); @@ -82,11 +73,11 @@ void LCD_Init(LCD_TypeDef * LCDx, LCD_InitStructure * initStruct) } /****************************************************************************************************************************************** -* : LCD_Start() -* ˵: һݴ -* : LCD_TypeDef * LCDx ָҪõLCDЧֵLCD -* : -* ע: +* 函数名称: LCD_Start() +* 功能说明: 启动一次数据传输 +* 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void LCD_Start(LCD_TypeDef * LCDx) { @@ -94,11 +85,11 @@ void LCD_Start(LCD_TypeDef * LCDx) } /****************************************************************************************************************************************** -* : LCD_IsBusy() -* ˵: Ƿڽݴ -* : LCD_TypeDef * LCDx ָҪõLCDЧֵLCD -* : uint32_t 1 ڴ 0 ݴ -* ע: +* 函数名称: LCD_IsBusy() +* 功能说明: 是否正在进行数据传输 +* 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD +* 输 出: uint32_t 1 正在传输数据 0 数据传输已完成 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t LCD_IsBusy(LCD_TypeDef * LCDx) { @@ -106,11 +97,11 @@ uint32_t LCD_IsBusy(LCD_TypeDef * LCDx) } /****************************************************************************************************************************************** -* : LCD_INTEn() -* ˵: LCDжʹܣָȵݴʱж -* : LCD_TypeDef * LCDx ָҪõLCDЧֵLCD -* : -* ע: +* 函数名称: LCD_INTEn() +* 功能说明: LCD中断使能,完成指定长度的数据传输时触发中断 +* 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void LCD_INTEn(LCD_TypeDef * LCDx) { @@ -118,11 +109,11 @@ void LCD_INTEn(LCD_TypeDef * LCDx) } /****************************************************************************************************************************************** -* : LCD_INTDis() -* ˵: LCDжϽָֹȵݴʱж -* : LCD_TypeDef * LCDx ָҪõLCDЧֵLCD -* : -* ע: +* 函数名称: LCD_INTDis() +* 功能说明: LCD中断禁止,完成指定长度的数据传输时不触发中断 +* 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void LCD_INTDis(LCD_TypeDef * LCDx) { @@ -130,11 +121,11 @@ void LCD_INTDis(LCD_TypeDef * LCDx) } /****************************************************************************************************************************************** -* : LCD_INTClr() -* ˵: LCDжϱ־ -* : LCD_TypeDef * LCDx ָҪõLCDЧֵLCD -* : -* ע: +* 函数名称: LCD_INTClr() +* 功能说明: LCD中断标志清除 +* 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void LCD_INTClr(LCD_TypeDef * LCDx) { @@ -142,11 +133,11 @@ void LCD_INTClr(LCD_TypeDef * LCDx) } /****************************************************************************************************************************************** -* : LCD_INTStat() -* ˵: LCDж״̬ѯ -* : LCD_TypeDef * LCDx ָҪõLCDЧֵLCD -* : uint32_t 1 ָȵݴ 0 δָȵݴ -* ע: +* 函数名称: LCD_INTStat() +* 功能说明: LCD中断状态查询 +* 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD +* 输 出: uint32_t 1 完成指定长度的数据传输 0 未完成指定长度的数据传输 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t LCD_INTStat(LCD_TypeDef * LCDx) { diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.h index 490af3162f..8091a88f03 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.h @@ -2,10 +2,7 @@ #define __SWM320_LCD_H__ -typedef struct { - uint8_t Interface; //LCDӿڣLCD_INTERFACE_RGBLCD_INTERFACE_I80LCD_INTERFACE_M68 - - /* RGBͬӿڲ */ +typedef struct { uint16_t HnPixel; //ˮƽظȡֵ1024 uint16_t VnPixel; //ֱظȡֵ 768 uint8_t Hfp; //horizonal front porchȡֵ32 @@ -21,10 +18,6 @@ typedef struct { } LCD_InitStructure; -#define LCD_INTERFACE_RGB 0 -#define LCD_INTERFACE_I80 1 -#define LCD_INTERFACE_M68 2 - #define LCD_SAMPLEDGE_RISE 0 //ĻDOTCLKز #define LCD_SAMPLEDGE_FALL 1 //ĻDOTCLK½ز diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.h index 23f7e5f902..1714454dd7 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.h @@ -2,12 +2,12 @@ #define __SWM320_NORFLASH_H__ typedef struct { - uint8_t DataWidth; // 816 + uint8_t DataWidth; // 8、16 - uint8_t WELowPulseTime; // WE# pulse widthλΪϵͳʱڣֵΪ7 - uint8_t OEPreValidTime; // Valid data output after OE# lowλΪϵͳʱڣֵΪ15 + uint8_t WELowPulseTime; // WE# pulse width,单位为系统时钟周期,最大值为7 + uint8_t OEPreValidTime; // Valid data output after OE# low,单位为系统时钟周期,最大值为15 - uint8_t OperFinishIEn; // (д롢)жʹ + uint8_t OperFinishIEn; // 操作(写入、擦除)完成中断使能 uint8_t OperTimeoutIEn; } NORFL_InitStructure; @@ -21,7 +21,7 @@ uint32_t NORFL_Read(uint32_t addr); uint16_t NORFL_ReadID(uint32_t id_addr); -/* ǰ汾߶ֶֻ֧ +/* 当前版本总线读只支持字读 #define NORFL_Read8(addr) *((volatile uint8_t *)(NORFLM_BASE + addr)) #define NORFL_Read16(addr) *((volatile uint16_t *)(NORFLM_BASE + addr)) */ #define NORFL_Read32(addr) *((volatile uint32_t *)(NORFLM_BASE + addr)) diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.c index af21c1ffeb..55967f7cac 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_port.c -* ˵: SWM320ƬĶ˿Źѡ⺯ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_port.c +* 功能说明: SWM320单片机的端口引脚功能选择库函数 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -23,15 +23,15 @@ /****************************************************************************************************************************************** -* : PORT_Init() -* ˵: ˿Źѡ񣬿õĹܼ"SWM320_port.h"ļ -* : uint32_t PORTx ָPORT˿ڣЧֵPORTAPORTBPORTCPORTMPORTNPORTP -* uint32_t n ָPORTţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* uint32_t func ָ˿Ҫ趨Ĺܣȡֵ"SWM320_port.h"ļ -* uint32_t digit_in_en ʹ -* : -* ע: űnΪżʱfuncȡֵֻFUNMUX0ͷģFUNMUX0_UART0_RXD -* űnΪʱfuncȡֵֻFUNMUX1ͷģFUNMUX1_UART0_TXD +* 函数名称: PORT_Init() +* 功能说明: 端口引脚功能选择,可用的功能见"SWM320_port.h"文件 +* 输 入: uint32_t PORTx 指定PORT端口,有效值包括PORTA、PORTB、PORTC、PORTM、PORTN、PORTP +* uint32_t n 指定PORT引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* uint32_t func 指定端口引脚要设定的功能,其可取值见"SWM320_port.h"文件 +* uint32_t digit_in_en 数字输入使能 +* 输 出: 无 +* 注意事项: 当引脚标号n为偶数时,func取值只能是FUNMUX0开头的,如FUNMUX0_UART0_RXD +* 当引脚标号n为奇数时,func取值只能是FUNMUX1开头的,如FUNMUX1_UART0_TXD ******************************************************************************************************************************************/ void PORT_Init(uint32_t PORTx, uint32_t n, uint32_t func, uint32_t digit_in_en) { diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.h index 1e2f4f2244..9fa2a24b12 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.h @@ -1,7 +1,7 @@ #ifndef __SWM320_PORT_H__ #define __SWM320_PORT_H__ -void PORT_Init(uint32_t PORTx, uint32_t n, uint32_t func, uint32_t digit_in_en); //˿Źѡȡֵ£ +void PORT_Init(uint32_t PORTx, uint32_t n, uint32_t func, uint32_t digit_in_en); //端口引脚功能选择,其可取值如下: #define PORTA 0 #define PORTB 1 @@ -425,8 +425,8 @@ void PORT_Init(uint32_t PORTx, uint32_t n, uint32_t func, uint32_t digit_in_en); -/* 궨ȡֵȫȷֵĻϡ100궨ֵӶ⺯ıд*/ -/* ЩֵżŵĹȡֵPIN0PIN2... */ +/* 下面宏定义的取值全部在正确值的基础上“加100”,以区分上面宏定义的值,从而方便库函数的编写*/ +/* 下面这些值是偶数编号引脚的功能取值,如PIN0、PIN2、... */ #define FUNMUX0_UART0_RXD 100 #define FUNMUX0_UART1_RXD 101 #define FUNMUX0_UART2_RXD 102 @@ -452,7 +452,7 @@ void PORT_Init(uint32_t PORTx, uint32_t n, uint32_t func, uint32_t digit_in_en); #define FUNMUX0_UART2_CTS 123 #define FUNMUX0_UART3_CTS 124 -/* ЩֵŵĹȡֵPIN1PIN3... */ +/* 下面这些值是奇数编号引脚的功能取值,如PIN1、PIN3、... */ #define FUNMUX1_UART0_TXD 100 #define FUNMUX1_UART1_TXD 101 #define FUNMUX1_UART2_TXD 102 diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.c index e74334fc93..2c8e87cd9b 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_pwm.c -* ˵: SWM320ƬPWM -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_pwm.c +* 功能说明: SWM320单片机的PWM功能驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -23,12 +23,12 @@ /****************************************************************************************************************************************** -* : PWM_Init() -* ˵: PWMʼ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* PWM_InitStructure * initStruct PWM趨ֵĽṹ -* : -* ע: +* 函数名称: PWM_Init() +* 功能说明: PWM初始化 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* PWM_InitStructure * initStruct 包含PWM相关设定值的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_Init(PWM_TypeDef * PWMx, PWM_InitStructure * initStruct) { @@ -39,7 +39,7 @@ void PWM_Init(PWM_TypeDef * PWMx, PWM_InitStructure * initStruct) SYS->CLKDIV &= ~SYS_CLKDIV_PWM_Msk; SYS->CLKDIV |= (initStruct->clk_div << SYS_CLKDIV_PWM_Pos); - PWM_Stop(PWMx, 1, 1); //һЩؼĴֻPWMֹͣʱ + PWM_Stop(PWMx, 1, 1); //一些关键寄存器只能在PWM停止时设置 PWMx->MODE = initStruct->mode; @@ -84,7 +84,7 @@ void PWM_Init(PWM_TypeDef * PWMx, PWM_InitStructure * initStruct) break; } - PWMG->IRS = ((0x01 << bit_offset) | (0x01 << (bit_offset+1)) | (0x01 << (bit_offset+12)) | (0x01 << (bit_offset+13))); //жϱ־ + PWMG->IRS = ((0x01 << bit_offset) | (0x01 << (bit_offset+1)) | (0x01 << (bit_offset+12)) | (0x01 << (bit_offset+13))); //清除中断标志 PWMG->IE &= ~((0x01 << bit_offset) | (0x01 << (bit_offset+1)) | (0x01 << (bit_offset+12)) | (0x01 << (bit_offset+13))); PWMG->IE |= (initStruct->NCycleAIEn << bit_offset) | (initStruct->NCycleBIEn << (bit_offset+1)) | (initStruct->HEndAIEn << (bit_offset+12)) | (initStruct->HEndBIEn << (bit_offset+13)); @@ -100,13 +100,13 @@ void PWM_Init(PWM_TypeDef * PWMx, PWM_InitStructure * initStruct) } /****************************************************************************************************************************************** -* : PWM_Start() -* ˵: PWMʼPWM -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chA 0 ͨA 1 ͨA -* uint32_t chB 0 ͨB 1 ͨB -* : -* ע: +* 函数名称: PWM_Start() +* 功能说明: 启动PWM,开始PWM输出 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chA 0 通道A不启动 1 通道A启动 +* uint32_t chB 0 通道B不启动 1 通道B启动 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_Start(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB) { @@ -139,13 +139,13 @@ void PWM_Start(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB) } /****************************************************************************************************************************************** -* : PWM_Stop() -* ˵: رPWMֹͣPWM -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chA 0 ͨAر 1 ͨAر -* uint32_t chB 0 ͨBر 1 ͨBر -* : -* ע: +* 函数名称: PWM_Stop() +* 功能说明: 关闭PWM,停止PWM输出 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chA 0 通道A不关闭 1 通道A关闭 +* uint32_t chB 0 通道B不关闭 1 通道B关闭 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_Stop(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB) { @@ -178,13 +178,13 @@ void PWM_Stop(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB) } /****************************************************************************************************************************************** -* : PWM_SetCycle() -* ˵: -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪĸͨЧֵPWM_CH_APWM_CH_B -* uint16_t cycle Ҫ趨ֵ -* : -* ע: +* 函数名称: PWM_SetCycle() +* 功能说明: 设置周期 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要设置哪个通道,有效值:PWM_CH_A、PWM_CH_B +* uint16_t cycle 要设定的周期值 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_SetCycle(PWM_TypeDef * PWMx, uint32_t chn, uint16_t cycle) { @@ -195,12 +195,12 @@ void PWM_SetCycle(PWM_TypeDef * PWMx, uint32_t chn, uint16_t cycle) } /****************************************************************************************************************************************** -* : PWM_GetCycle() -* ˵: ȡ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪѯĸͨЧֵPWM_CH_APWM_CH_B -* : uint16_t ȡֵ -* ע: +* 函数名称: PWM_GetCycle() +* 功能说明: 获取周期 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要查询哪个通道,有效值:PWM_CH_A、PWM_CH_B +* 输 出: uint16_t 获取到的周期值 +* 注意事项: 无 ******************************************************************************************************************************************/ uint16_t PWM_GetCycle(PWM_TypeDef * PWMx, uint32_t chn) { @@ -215,13 +215,13 @@ uint16_t PWM_GetCycle(PWM_TypeDef * PWMx, uint32_t chn) } /****************************************************************************************************************************************** -* : PWM_SetHDuty() -* ˵: øߵƽʱ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪĸͨЧֵPWM_CH_APWM_CH_B -* uint16_t hduty Ҫ趨ĸߵƽʱ -* : -* ע: +* 函数名称: PWM_SetHDuty() +* 功能说明: 设置高电平时长 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要设置哪个通道,有效值:PWM_CH_A、PWM_CH_B +* uint16_t hduty 要设定的高电平时长 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_SetHDuty(PWM_TypeDef * PWMx, uint32_t chn, uint16_t hduty) { @@ -232,12 +232,12 @@ void PWM_SetHDuty(PWM_TypeDef * PWMx, uint32_t chn, uint16_t hduty) } /****************************************************************************************************************************************** -* : PWM_GetHDuty() -* ˵: ȡߵƽʱ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪѯĸͨЧֵPWM_CH_APWM_CH_B -* : uint16_t ȡĸߵƽʱ -* ע: +* 函数名称: PWM_GetHDuty() +* 功能说明: 获取高电平时长 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要查询哪个通道,有效值:PWM_CH_A、PWM_CH_B +* 输 出: uint16_t 获取到的高电平时长 +* 注意事项: 无 ******************************************************************************************************************************************/ uint16_t PWM_GetHDuty(PWM_TypeDef * PWMx, uint32_t chn) { @@ -252,13 +252,13 @@ uint16_t PWM_GetHDuty(PWM_TypeDef * PWMx, uint32_t chn) } /****************************************************************************************************************************************** -* : PWM_SetDeadzone() -* ˵: ʱ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪĸͨЧֵPWM_CH_APWM_CH_B -* uint8_t deadzone Ҫ趨ʱ -* : -* ע: +* 函数名称: PWM_SetDeadzone() +* 功能说明: 设置死区时长 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要设置哪个通道,有效值:PWM_CH_A、PWM_CH_B +* uint8_t deadzone 要设定的死区时长 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_SetDeadzone(PWM_TypeDef * PWMx, uint32_t chn, uint8_t deadzone) { @@ -269,12 +269,12 @@ void PWM_SetDeadzone(PWM_TypeDef * PWMx, uint32_t chn, uint8_t deadzone) } /****************************************************************************************************************************************** -* : PWM_GetDeadzone() -* ˵: ȡʱ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪѯĸͨЧֵPWM_CH_APWM_CH_B -* : uint8_t ȡʱ -* ע: +* 函数名称: PWM_GetDeadzone() +* 功能说明: 获取死区时长 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要查询哪个通道,有效值:PWM_CH_A、PWM_CH_B +* 输 出: uint8_t 获取到的死区时长 +* 注意事项: 无 ******************************************************************************************************************************************/ uint8_t PWM_GetDeadzone(PWM_TypeDef * PWMx, uint32_t chn) { @@ -290,12 +290,12 @@ uint8_t PWM_GetDeadzone(PWM_TypeDef * PWMx, uint32_t chn) /****************************************************************************************************************************************** -* : PWM_IntNCycleEn() -* ˵: ڿʼжʹ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪĸͨЧֵPWM_CH_APWM_CH_B -* : -* ע: +* 函数名称: PWM_IntNCycleEn() +* 功能说明: 新周期开始中断使能 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要设置哪个通道,有效值:PWM_CH_A、PWM_CH_B +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_IntNCycleEn(PWM_TypeDef * PWMx, uint32_t chn) { @@ -334,12 +334,12 @@ void PWM_IntNCycleEn(PWM_TypeDef * PWMx, uint32_t chn) } /****************************************************************************************************************************************** -* : PWM_IntNCycleDis() -* ˵: ڿʼжϽ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪĸͨЧֵPWM_CH_APWM_CH_B -* : -* ע: +* 函数名称: PWM_IntNCycleDis() +* 功能说明: 新周期开始中断禁能 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要设置哪个通道,有效值:PWM_CH_A、PWM_CH_B +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_IntNCycleDis(PWM_TypeDef * PWMx, uint32_t chn) { @@ -378,12 +378,12 @@ void PWM_IntNCycleDis(PWM_TypeDef * PWMx, uint32_t chn) } /****************************************************************************************************************************************** -* : PWM_IntNCycleClr() -* ˵: ڿʼжϱ־ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪĸͨЧֵPWM_CH_APWM_CH_B -* : -* ע: +* 函数名称: PWM_IntNCycleClr() +* 功能说明: 新周期开始中断标志清除 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要设置哪个通道,有效值:PWM_CH_A、PWM_CH_B +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_IntNCycleClr(PWM_TypeDef * PWMx, uint32_t chn) { @@ -422,12 +422,12 @@ void PWM_IntNCycleClr(PWM_TypeDef * PWMx, uint32_t chn) } /****************************************************************************************************************************************** -* : PWM_IntNCycleStat() -* ˵: ڿʼжǷ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪĸͨЧֵPWM_CH_APWM_CH_B -* : uint32_t 1 ڿʼжѷ 0 ڿʼжδ -* ע: +* 函数名称: PWM_IntNCycleStat() +* 功能说明: 新周期开始中断是否发生 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要设置哪个通道,有效值:PWM_CH_A、PWM_CH_B +* 输 出: uint32_t 1 新周期开始中断已发生 0 新周期开始中断未发生 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t PWM_IntNCycleStat(PWM_TypeDef * PWMx, uint32_t chn) { @@ -471,12 +471,12 @@ uint32_t PWM_IntNCycleStat(PWM_TypeDef * PWMx, uint32_t chn) /****************************************************************************************************************************************** -* : PWM_IntHEndEn() -* ˵: ߵƽжʹ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪĸͨЧֵPWM_CH_APWM_CH_B -* : -* ע: +* 函数名称: PWM_IntHEndEn() +* 功能说明: 高电平结束中断使能 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要设置哪个通道,有效值:PWM_CH_A、PWM_CH_B +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_IntHEndEn(PWM_TypeDef * PWMx, uint32_t chn) { @@ -515,12 +515,12 @@ void PWM_IntHEndEn(PWM_TypeDef * PWMx, uint32_t chn) } /****************************************************************************************************************************************** -* : PWM_IntHEndDis() -* ˵: ߵƽжϽ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪĸͨЧֵPWM_CH_APWM_CH_B -* : -* ע: +* 函数名称: PWM_IntHEndDis() +* 功能说明: 高电平结束中断禁能 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要设置哪个通道,有效值:PWM_CH_A、PWM_CH_B +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_IntHEndDis(PWM_TypeDef * PWMx, uint32_t chn) { @@ -559,12 +559,12 @@ void PWM_IntHEndDis(PWM_TypeDef * PWMx, uint32_t chn) } /****************************************************************************************************************************************** -* : PWM_IntHEndClr() -* ˵: ߵƽжϱ־ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪĸͨЧֵPWM_CH_APWM_CH_B -* : -* ע: +* 函数名称: PWM_IntHEndClr() +* 功能说明: 高电平结束中断标志清除 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要设置哪个通道,有效值:PWM_CH_A、PWM_CH_B +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void PWM_IntHEndClr(PWM_TypeDef * PWMx, uint32_t chn) { @@ -603,12 +603,12 @@ void PWM_IntHEndClr(PWM_TypeDef * PWMx, uint32_t chn) } /****************************************************************************************************************************************** -* : PWM_IntHEndStat() -* ˵: ߵƽжǷ -* : PWM_TypeDef * PWMx ָҪõPWMЧֵPWM0PWM1PWM2PWM3PWM4PWM5 -* uint32_t chn ѡҪĸͨЧֵPWM_CH_APWM_CH_B -* : uint32_t 1 ߵƽжѷ 0 ߵƽжδ -* ע: +* 函数名称: PWM_IntHEndStat() +* 功能说明: 高电平结束中断是否发生 +* 输 入: PWM_TypeDef * PWMx 指定要被设置的PWM,有效值包括PWM0、PWM1、PWM2、PWM3、PWM4、PWM5 +* uint32_t chn 选择要设置哪个通道,有效值:PWM_CH_A、PWM_CH_B +* 输 出: uint32_t 1 高电平结束中断已发生 0 高电平结束中断未发生 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t PWM_IntHEndStat(PWM_TypeDef * PWMx, uint32_t chn) { diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.h index 4565a05a94..6f857fae37 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.h @@ -2,57 +2,57 @@ #define __SWM320_PWM_H__ typedef struct { - uint8_t clk_div; //PWM_CLKDIV_1PWM_CLKDIV_8 + uint8_t clk_div; //PWM_CLKDIV_1、PWM_CLKDIV_8 - uint8_t mode; //PWM_MODE_INDEPPWM_MODE_COMPLPWM_MODE_INDEP_CALIGNPWM_MODE_COMPL_CALIGN + uint8_t mode; //PWM_MODE_INDEP、PWM_MODE_COMPL、PWM_MODE_INDEP_CALIGN、PWM_MODE_COMPL_CALIGN - uint16_t cycleA; //A· - uint16_t hdutyA; //A·ռձ - uint16_t deadzoneA; //A·ʱȡֵ0--1023 - uint8_t initLevelA; //A·ʼƽ0 ͵ƽ 1 ߵƽ + uint16_t cycleA; //A路周期 + uint16_t hdutyA; //A路占空比 + uint16_t deadzoneA; //A路死区时长,取值0--1023 + uint8_t initLevelA; //A路初始输出电平,0 低电平 1 高电平 - uint16_t cycleB; //B· - uint16_t hdutyB; //B·ռձ - uint16_t deadzoneB; //B·ʱȡֵ0--1023 - uint8_t initLevelB; //B·ʼƽ0 ͵ƽ 1 ߵƽ + uint16_t cycleB; //B路周期 + uint16_t hdutyB; //B路占空比 + uint16_t deadzoneB; //B路死区时长,取值0--1023 + uint8_t initLevelB; //B路初始输出电平,0 低电平 1 高电平 - uint8_t HEndAIEn; //A·ߵƽжʹ - uint8_t NCycleAIEn; //A·ڿʼжʹ - uint8_t HEndBIEn; //B·ߵƽжʹ - uint8_t NCycleBIEn; //B·ڿʼжʹ + uint8_t HEndAIEn; //A路高电平结束中断使能 + uint8_t NCycleAIEn; //A路新周期开始中断使能 + uint8_t HEndBIEn; //B路高电平结束中断使能 + uint8_t NCycleBIEn; //B路新周期开始中断使能 } PWM_InitStructure; #define PWM_CLKDIV_1 0 #define PWM_CLKDIV_8 1 -#define PWM_MODE_INDEP 0 //A·B·Ϊ· -#define PWM_MODE_COMPL 1 //A·B·Ϊһ· -#define PWM_MODE_INDEP_CALIGN 3 //A·B·Ϊ·Ķ -#define PWM_MODE_COMPL_CALIGN 4 //A·B·Ϊһ·Ķ +#define PWM_MODE_INDEP 0 //A路和B路为两路独立输出 +#define PWM_MODE_COMPL 1 //A路和B路为一路互补输出 +#define PWM_MODE_INDEP_CALIGN 3 //A路和B路为两路独立输出,中心对齐 +#define PWM_MODE_COMPL_CALIGN 4 //A路和B路为一路互补输出,中心对齐 #define PWM_CH_A 0 #define PWM_CH_B 1 -void PWM_Init(PWM_TypeDef * PWMx, PWM_InitStructure * initStruct); //PWMʼ -void PWM_Start(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB); //PWMʼPWM -void PWM_Stop(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB); //رPWMֹͣPWM +void PWM_Init(PWM_TypeDef * PWMx, PWM_InitStructure * initStruct); //PWM初始化 +void PWM_Start(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB); //启动PWM,开始PWM输出 +void PWM_Stop(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB); //关闭PWM,停止PWM输出 -void PWM_SetCycle(PWM_TypeDef * PWMx, uint32_t chn, uint16_t cycle); // -uint16_t PWM_GetCycle(PWM_TypeDef * PWMx, uint32_t chn); //ȡ -void PWM_SetHDuty(PWM_TypeDef * PWMx, uint32_t chn, uint16_t hduty); //øߵƽʱ -uint16_t PWM_GetHDuty(PWM_TypeDef * PWMx, uint32_t chn); //ȡߵƽʱ -void PWM_SetDeadzone(PWM_TypeDef * PWMx, uint32_t chn, uint8_t deadzone); //ʱ -uint8_t PWM_GetDeadzone(PWM_TypeDef * PWMx, uint32_t chn); //ȡʱ +void PWM_SetCycle(PWM_TypeDef * PWMx, uint32_t chn, uint16_t cycle); //设置周期 +uint16_t PWM_GetCycle(PWM_TypeDef * PWMx, uint32_t chn); //获取周期 +void PWM_SetHDuty(PWM_TypeDef * PWMx, uint32_t chn, uint16_t hduty); //设置高电平时长 +uint16_t PWM_GetHDuty(PWM_TypeDef * PWMx, uint32_t chn); //获取高电平时长 +void PWM_SetDeadzone(PWM_TypeDef * PWMx, uint32_t chn, uint8_t deadzone); //设置死区时长 +uint8_t PWM_GetDeadzone(PWM_TypeDef * PWMx, uint32_t chn); //获取死区时长 -void PWM_IntNCycleEn(PWM_TypeDef * PWMx, uint32_t chn); //ڿʼжʹ -void PWM_IntNCycleDis(PWM_TypeDef * PWMx, uint32_t chn); //ڿʼжϽ -void PWM_IntNCycleClr(PWM_TypeDef * PWMx, uint32_t chn); //ڿʼжϱ־ -uint32_t PWM_IntNCycleStat(PWM_TypeDef * PWMx, uint32_t chn); //ڿʼжǷ -void PWM_IntHEndEn(PWM_TypeDef * PWMx, uint32_t chn); //ߵƽжʹ -void PWM_IntHEndDis(PWM_TypeDef * PWMx, uint32_t chn); //ߵƽжϽ -void PWM_IntHEndClr(PWM_TypeDef * PWMx, uint32_t chn); //ߵƽжϱ־ -uint32_t PWM_IntHEndStat(PWM_TypeDef * PWMx, uint32_t chn); //ߵƽжǷ +void PWM_IntNCycleEn(PWM_TypeDef * PWMx, uint32_t chn); //新周期开始中断使能 +void PWM_IntNCycleDis(PWM_TypeDef * PWMx, uint32_t chn); //新周期开始中断禁能 +void PWM_IntNCycleClr(PWM_TypeDef * PWMx, uint32_t chn); //新周期开始中断标志清除 +uint32_t PWM_IntNCycleStat(PWM_TypeDef * PWMx, uint32_t chn); //新周期开始中断是否发生 +void PWM_IntHEndEn(PWM_TypeDef * PWMx, uint32_t chn); //高电平结束中断使能 +void PWM_IntHEndDis(PWM_TypeDef * PWMx, uint32_t chn); //高电平结束中断禁能 +void PWM_IntHEndClr(PWM_TypeDef * PWMx, uint32_t chn); //高电平结束中断标志清除 +uint32_t PWM_IntHEndStat(PWM_TypeDef * PWMx, uint32_t chn); //高电平结束中断是否发生 #endif //__SWM320_PWM_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.c index 2ce0f390b7..d43ee91f15 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_rtc.c -* ˵: SWM320ƬRTC -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_rtc.c +* 功能说明: SWM320单片机的RTC驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -24,18 +24,18 @@ static uint32_t calcWeekDay(uint32_t year, uint32_t month, uint32_t date); /****************************************************************************************************************************************** -* : RTC_Init() -* ˵: RTCʼ -* : RTC_TypeDef * RTCx ָҪõRTCЧֵRTC -* RTC_InitStructure * initStruct RTC趨ֵĽṹ -* : -* ע: +* 函数名称: RTC_Init() +* 功能说明: RTC初始化 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,有效值包括RTC +* RTC_InitStructure * initStruct 包含RTC相关设定值的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_Init(RTC_TypeDef * RTCx, RTC_InitStructure * initStruct) { SYS->CLKEN |= (1 << SYS_CLKEN_RTCBKP_Pos); - SYS->LRCCR &= ~(1 << SYS_LRCCR_OFF_Pos); //RTCʹ32KHz RCʱ + SYS->LRCCR &= ~(1 << SYS_LRCCR_OFF_Pos); //RTC使用32KHz RC时钟 SYS->CLKEN |= (1 << SYS_CLKEN_RTC_Pos) | ((uint32_t)1 << SYS_CLKEN_ALIVE_Pos); @@ -72,11 +72,11 @@ void RTC_Init(RTC_TypeDef * RTCx, RTC_InitStructure * initStruct) } /****************************************************************************************************************************************** -* : RTC_Start() -* ˵: RTC -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_Start() +* 功能说明: 启动RTC +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_Start(RTC_TypeDef * RTCx) { @@ -84,11 +84,11 @@ void RTC_Start(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_Stop() -* ˵: ֹͣRTC -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_Stop() +* 功能说明: 停止RTC +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_Stop(RTC_TypeDef * RTCx) { @@ -96,12 +96,12 @@ void RTC_Stop(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_GetDateTime() -* ˵: ȡǰʱ -* : RTC_TypeDef * RTCx ָҪõRTCЧֵRTC -* RTC_DateTime * dateTime ȡʱ䡢ֵָָĽṹ -* : -* ע: +* 函数名称: RTC_GetDateTime() +* 功能说明: 获取当前的时间和日期 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,有效值包括RTC +* RTC_DateTime * dateTime 获取到的时间、日期值存入此指针指向的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_GetDateTime(RTC_TypeDef * RTCx, RTC_DateTime * dateTime) { @@ -115,12 +115,12 @@ void RTC_GetDateTime(RTC_TypeDef * RTCx, RTC_DateTime * dateTime) } /****************************************************************************************************************************************** -* : RTC_AlarmSetup() -* ˵: RTC趨 -* : RTC_TypeDef * RTCx ָҪõRTCЧֵRTC -* RTC_AlarmStructure * alarmStruct RTC趨ֵĽṹ -* : -* ע: +* 函数名称: RTC_AlarmSetup() +* 功能说明: RTC闹钟设定 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,有效值包括RTC +* RTC_AlarmStructure * alarmStruct 包含RTC闹钟设定值的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_AlarmSetup(RTC_TypeDef * RTCx, RTC_AlarmStructure * alarmStruct) { @@ -143,13 +143,13 @@ void RTC_AlarmSetup(RTC_TypeDef * RTCx, RTC_AlarmStructure * alarmStruct) } /****************************************************************************************************************************************** -* : calcWeekDay() -* ˵: ָꡢ¡ڼ -* : uint32_t year -* uint32_t month -* uint32_t date -* : uint32_t 0 1 һ ... ... 6 -* ע: +* 函数名称: calcWeekDay() +* 功能说明: 计算指定年、月、日是星期几 +* 输 入: uint32_t year 年 +* uint32_t month 月 +* uint32_t date 日 +* 输 出: uint32_t 0 星期日 1 星期一 ... ... 6 星期六 +* 注意事项: 无 ******************************************************************************************************************************************/ static uint32_t calcWeekDay(uint32_t year, uint32_t month, uint32_t date) { @@ -173,11 +173,11 @@ static uint32_t calcWeekDay(uint32_t year, uint32_t month, uint32_t date) } /****************************************************************************************************************************************** -* : RTC_IntSecondEn() -* ˵: жʹ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntSecondEn() +* 功能说明: 秒中断使能 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntSecondEn(RTC_TypeDef * RTCx) { @@ -185,11 +185,11 @@ void RTC_IntSecondEn(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntSecondDis() -* ˵: жϽֹ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntSecondDis() +* 功能说明: 秒中断禁止 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntSecondDis(RTC_TypeDef * RTCx) { @@ -197,11 +197,11 @@ void RTC_IntSecondDis(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntSecondClr() -* ˵: жϱ־ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntSecondClr() +* 功能说明: 秒中断标志清除 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntSecondClr(RTC_TypeDef * RTCx) { @@ -209,11 +209,11 @@ void RTC_IntSecondClr(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntSecondStat() -* ˵: ж״̬ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : uint32_t 1 жϷ 0 жδ -* ע: +* 函数名称: RTC_IntSecondStat() +* 功能说明: 秒中断状态 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: uint32_t 1 秒中断发生 0 秒中断未发生 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t RTC_IntSecondStat(RTC_TypeDef * RTCx) { @@ -221,11 +221,11 @@ uint32_t RTC_IntSecondStat(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntMinuteEn() -* ˵: жʹ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntMinuteEn() +* 功能说明: 分中断使能 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntMinuteEn(RTC_TypeDef * RTCx) { @@ -233,11 +233,11 @@ void RTC_IntMinuteEn(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntMinuteDis() -* ˵: жϽֹ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntMinuteDis() +* 功能说明: 分中断禁止 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntMinuteDis(RTC_TypeDef * RTCx) { @@ -245,11 +245,11 @@ void RTC_IntMinuteDis(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntMinuteClr() -* ˵: жϱ־ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntMinuteClr() +* 功能说明: 分中断标志清除 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntMinuteClr(RTC_TypeDef * RTCx) { @@ -257,11 +257,11 @@ void RTC_IntMinuteClr(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntMinuteStat() -* ˵: ж״̬ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : uint32_t 1 жϷ 0 жδ -* ע: +* 函数名称: RTC_IntMinuteStat() +* 功能说明: 分中断状态 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: uint32_t 1 分中断发生 0 分中断未发生 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t RTC_IntMinuteStat(RTC_TypeDef * RTCx) { @@ -269,11 +269,11 @@ uint32_t RTC_IntMinuteStat(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntHourEn() -* ˵: ʱжʹ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntHourEn() +* 功能说明: 时中断使能 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntHourEn(RTC_TypeDef * RTCx) { @@ -281,11 +281,11 @@ void RTC_IntHourEn(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntHourDis() -* ˵: ʱжϽֹ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntHourDis() +* 功能说明: 时中断禁止 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntHourDis(RTC_TypeDef * RTCx) { @@ -293,11 +293,11 @@ void RTC_IntHourDis(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntHourClr() -* ˵: ʱжϱ־ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntHourClr() +* 功能说明: 时中断标志清除 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntHourClr(RTC_TypeDef * RTCx) { @@ -305,11 +305,11 @@ void RTC_IntHourClr(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntHourStat() -* ˵: ʱж״̬ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : uint32_t 1 ʱжϷ 0 ʱжδ -* ע: +* 函数名称: RTC_IntHourStat() +* 功能说明: 时中断状态 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: uint32_t 1 时中断发生 0 时中断未发生 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t RTC_IntHourStat(RTC_TypeDef * RTCx) { @@ -317,11 +317,11 @@ uint32_t RTC_IntHourStat(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntDateEn() -* ˵: жʹ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntDateEn() +* 功能说明: 日中断使能 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntDateEn(RTC_TypeDef * RTCx) { @@ -329,11 +329,11 @@ void RTC_IntDateEn(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntDateDis() -* ˵: жϽֹ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntDateDis() +* 功能说明: 日中断禁止 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntDateDis(RTC_TypeDef * RTCx) { @@ -341,11 +341,11 @@ void RTC_IntDateDis(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntDateClr() -* ˵: жϱ־ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntDateClr() +* 功能说明: 日中断标志清除 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntDateClr(RTC_TypeDef * RTCx) { @@ -353,11 +353,11 @@ void RTC_IntDateClr(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntDateStat() -* ˵: ж״̬ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : uint32_t 1 жϷ 0 жδ -* ע: +* 函数名称: RTC_IntDateStat() +* 功能说明: 日中断状态 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: uint32_t 1 日中断发生 0 日中断未发生 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t RTC_IntDateStat(RTC_TypeDef * RTCx) { @@ -365,11 +365,11 @@ uint32_t RTC_IntDateStat(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntAlarmEn() -* ˵: жʹ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntAlarmEn() +* 功能说明: 闹钟中断使能 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntAlarmEn(RTC_TypeDef * RTCx) { @@ -377,11 +377,11 @@ void RTC_IntAlarmEn(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntAlarmDis() -* ˵: жϽֹ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntAlarmDis() +* 功能说明: 闹钟中断禁止 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntAlarmDis(RTC_TypeDef * RTCx) { @@ -389,11 +389,11 @@ void RTC_IntAlarmDis(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntAlarmClr() -* ˵: жϱ־ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : -* ע: +* 函数名称: RTC_IntAlarmClr() +* 功能说明: 闹钟中断标志清除 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void RTC_IntAlarmClr(RTC_TypeDef * RTCx) { @@ -401,11 +401,11 @@ void RTC_IntAlarmClr(RTC_TypeDef * RTCx) } /****************************************************************************************************************************************** -* : RTC_IntAlarmStat() -* ˵: ж״̬ -* : RTC_TypeDef * RTCx ָҪõRTCȡֵRTC -* : uint32_t 1 жϷ 0 жδ -* ע: +* 函数名称: RTC_IntAlarmStat() +* 功能说明: 闹钟中断状态 +* 输 入: RTC_TypeDef * RTCx 指定要被设置的RTC,可取值包括RTC +* 输 出: uint32_t 1 闹钟中断发生 0 闹钟中断未发生 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t RTC_IntAlarmStat(RTC_TypeDef * RTCx) { diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.h index 513f885cf6..13cd0e6785 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.h @@ -13,17 +13,17 @@ typedef struct { uint16_t Year; - uint8_t Month; //ȡֵ1--12 - uint8_t Date; //ȡֵ1--31 - uint8_t Hour; //ȡֵ0--23 - uint8_t Minute; //ȡֵ0--59 - uint8_t Second; //ȡֵ0--59 + uint8_t Month; //取值1--12 + uint8_t Date; //取值1--31 + uint8_t Hour; //取值0--23 + uint8_t Minute; //取值0--59 + uint8_t Second; //取值0--59 uint8_t SecondIEn; uint8_t MinuteIEn; } RTC_InitStructure; typedef struct { - uint8_t Days; //RTC_SUNRTC_MONRTC_TUERTC_WEDRTC_THURTC_FRIRTC_SAT + uint8_t Days; //RTC_SUN、RTC_MON、RTC_TUE、RTC_WED、RTC_THU、RTC_FRI、RTC_SAT及其或运算组合 uint8_t Hour; uint8_t Minute; uint8_t Second; @@ -34,7 +34,7 @@ typedef struct { uint16_t Year; uint8_t Month; uint8_t Date; - uint8_t Day; //RTC_SUNRTC_MONRTC_TUERTC_WEDRTC_THURTC_FRIRTC_SAT + uint8_t Day; //RTC_SUN、RTC_MON、RTC_TUE、RTC_WED、RTC_THU、RTC_FRI、RTC_SAT uint8_t Hour; uint8_t Minute; uint8_t Second; diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.c index 2cb8b9e3e8..9175cce387 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_sdio.c -* ˵: SWM320ƬSDIOӿ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: Ϊͨԡԡԣֻ֧512ֽΪλĶд -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_sdio.c +* 功能说明: SWM320单片机的SDIO接口驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: 为了通用性、兼容性、易用性,只支持以512字节为单位的读写 +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -25,11 +25,11 @@ SD_CardInfo SD_cardInfo; /****************************************************************************************************************************************** -* : SDIO_Init() -* ˵: SDIOдSDʼʼɸ4ģʽд512ֽڴС -* : uint32_t freq SDIO_CLKʱƵ -* : uint32_t SD_RES_OK ɹ SD_RES_ERR ʧ SD_RES_TIMEOUT ʱ -* ע: +* 函数名称: SDIO_Init() +* 功能说明: SDIO读写SD卡初始化,初始化成高速4线模式、读写以512字节大小进行 +* 输 入: uint32_t freq SDIO_CLK时钟频率 +* 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SDIO_Init(uint32_t freq) { @@ -37,7 +37,7 @@ uint32_t SDIO_Init(uint32_t freq) uint32_t resp, resps[4]; SYS->CLKDIV &= ~SYS_CLKDIV_SDIO_Msk; - if(SystemCoreClock > 80000000) //SDIOʱҪС52MHz + if(SystemCoreClock > 80000000) //SDIO时钟需要小于52MHz SYS->CLKDIV |= (2 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 4 else SYS->CLKDIV |= (1 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 2 @@ -64,7 +64,7 @@ uint32_t SDIO_Init(uint32_t freq) SDIO_SendCmd(SD_CMD_GO_IDLE_STATE, 0x00, SD_RESP_NO, 0); //CMD0: GO_IDLE_STATE - res = SDIO_SendCmd(SD_CMD_SEND_IF_COND, 0x1AA, SD_RESP_32b, &resp); //CMD8: SEND_IF_COND, ⹤ѹǷ֧SD 2.0 + res = SDIO_SendCmd(SD_CMD_SEND_IF_COND, 0x1AA, SD_RESP_32b, &resp); //CMD8: SEND_IF_COND, 检测工作电压、检测是否支持SD 2.0 if(res != SD_RES_OK) return res; @@ -77,50 +77,50 @@ uint32_t SDIO_Init(uint32_t freq) if(res != SD_RES_OK) return res; - if(resp != 0x120) return SD_RES_ERR; //SDMMC + if(resp != 0x120) return SD_RES_ERR; //不是SD卡,可能是MMC卡 if(SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0) SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000|0x40000000, SD_RESP_32b, &resp); else SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000|0x00000000, SD_RESP_32b, &resp); - } while(((resp >> 31) & 0x01) == 0); //ϵûʱresp[31] == 0 + } while(((resp >> 31) & 0x01) == 0); //上电没完成时resp[31] == 0 if(((resp >> 30) & 0x01) == 1) SD_cardInfo.CardType = SDIO_HIGH_CAPACITY_SD_CARD; - SDIO_SendCmd(SD_CMD_ALL_SEND_CID, 0x00, SD_RESP_128b, resps); //CMD2: SD_CMD_ALL_SEND_CIDȡCID + SDIO_SendCmd(SD_CMD_ALL_SEND_CID, 0x00, SD_RESP_128b, resps); //CMD2: SD_CMD_ALL_SEND_CID,获取CID parseCID(resps); - SDIO_SendCmd(SD_CMD_SET_REL_ADDR, 0x00, SD_RESP_32b, &resp); //CMD3: SD_CMD_SET_REL_ADDRRCA + SDIO_SendCmd(SD_CMD_SET_REL_ADDR, 0x00, SD_RESP_32b, &resp); //CMD3: SD_CMD_SET_REL_ADDR,设置RCA SD_cardInfo.RCA = resp >> 16; - SDIO_SendCmd(SD_CMD_SEND_CSD, SD_cardInfo.RCA << 16, SD_RESP_128b, resps); //CMD9: SD_CMD_SEND_CSDȡCSD + SDIO_SendCmd(SD_CMD_SEND_CSD, SD_cardInfo.RCA << 16, SD_RESP_128b, resps); //CMD9: SD_CMD_SEND_CSD,获取CSD parseCSD(resps); - if(SD_cardInfo.CardBlockSize < 0x200) return SD_RES_ERR; //ֻ֧512ֽΪλĶддλ벻С512 + if(SD_cardInfo.CardBlockSize < 0x200) return SD_RES_ERR; //本驱动只支持以512字节为单位的读写,所以最大读写单位必须不小于512 SDIO->CR2 &= ~(SDIO_CR2_SDCLKEN_Msk | SDIO_CR2_SDCLKDIV_Msk); SDIO->CR2 |= (1 << SDIO_CR2_SDCLKEN_Pos) | - (calcSDCLKDiv(freq) << SDIO_CR2_SDCLKDIV_Pos); //ʼɣSDCLKл + (calcSDCLKDiv(freq) << SDIO_CR2_SDCLKDIV_Pos); //初始化完成,SDCLK切换到高速 - SDIO_SendCmd(SD_CMD_SEL_DESEL_CARD, SD_cardInfo.RCA << 16, SD_RESP_32b_busy, &resp); //CMD7: ѡпStandyģʽTransferģʽ + SDIO_SendCmd(SD_CMD_SEL_DESEL_CARD, SD_cardInfo.RCA << 16, SD_RESP_32b_busy, &resp); //CMD7: 选中卡,从Standy模式进入Transfer模式 SDIO->IF = SDIO_IF_TRXDONE_Msk; SDIO_SendCmd(SD_CMD_APP_CMD, SD_cardInfo.RCA << 16, SD_RESP_32b, &resp); - SDIO_SendCmd(SD_CMD_APP_SD_SET_BUSWIDTH, SD_BUSWIDTH_4b, SD_RESP_32b, &resp); //л4λģʽ + SDIO_SendCmd(SD_CMD_APP_SD_SET_BUSWIDTH, SD_BUSWIDTH_4b, SD_RESP_32b, &resp); //切换成4位总线模式 SDIO->CR1 |= (1 << SDIO_CR1_4BIT_Pos); - SDIO_SendCmd(SD_CMD_SET_BLOCKLEN, 512, SD_RESP_32b, &resp); //̶Сλ512ֽ + SDIO_SendCmd(SD_CMD_SET_BLOCKLEN, 512, SD_RESP_32b, &resp); //固定块大小位512字节 SDIO->BLK = 512; @@ -128,12 +128,12 @@ uint32_t SDIO_Init(uint32_t freq) } /****************************************************************************************************************************************** -* : SDIO_BlockWrite() -* ˵: SDд -* : uint32_t block_addr SDַÿ512ֽ -* uint32_t buff[] Ҫд -* : uint32_t SD_RES_OK ɹ SD_RES_ERR ʧ SD_RES_TIMEOUT ʱ -* ע: +* 函数名称: SDIO_BlockWrite() +* 功能说明: 向SD卡写入数据 +* 输 入: uint32_t block_addr SD卡块地址,每块512字节 +* uint32_t buff[] 要写入的数据 +* 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SDIO_BlockWrite(uint32_t block_addr, uint32_t buff[]) { @@ -159,13 +159,13 @@ uint32_t SDIO_BlockWrite(uint32_t block_addr, uint32_t buff[]) } /****************************************************************************************************************************************** -* : SDIO_MultiBlockWrite() -* ˵: SDд -* : uint32_t block_addr SDַÿ512ֽ -* uint16_t block_cnt ҪдĿ -* uint32_t buff[] Ҫд -* : uint32_t SD_RES_OK ɹ SD_RES_ERR ʧ SD_RES_TIMEOUT ʱ -* ע: +* 函数名称: SDIO_MultiBlockWrite() +* 功能说明: 向SD卡写入多块数据 +* 输 入: uint32_t block_addr SD卡块地址,每块512字节 +* uint16_t block_cnt 要写入的块数 +* uint32_t buff[] 要写入的数据 +* 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SDIO_MultiBlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]) { @@ -194,13 +194,13 @@ uint32_t SDIO_MultiBlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t } /****************************************************************************************************************************************** -* : SDIO_DMABlockWrite() -* ˵: ͨDMASDд -* : uint32_t block_addr SDַÿ512ֽ -* uint16_t block_cnt ҪдĿ -* uint32_t buff[] Ҫд -* : uint32_t SD_RES_OK ɹ SD_RES_ERR ʧ SD_RES_TIMEOUT ʱ -* ע: +* 函数名称: SDIO_DMABlockWrite() +* 功能说明: 通过DMA向SD卡写入多块数据 +* 输 入: uint32_t block_addr SD卡块地址,每块512字节 +* uint16_t block_cnt 要写入的块数 +* uint32_t buff[] 要写入的数据 +* 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SDIO_DMABlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]) { @@ -223,12 +223,12 @@ uint32_t SDIO_DMABlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t bu } /****************************************************************************************************************************************** -* : SDIO_BlockRead() -* ˵: SD -* : uint32_t block_addr SDַÿ512ֽ -* uint32_t buff[] -* : uint32_t SD_RES_OK ɹ SD_RES_ERR ʧ SD_RES_TIMEOUT ʱ -* ע: +* 函数名称: SDIO_BlockRead() +* 功能说明: 从SD卡读出数据 +* 输 入: uint32_t block_addr SD卡块地址,每块512字节 +* uint32_t buff[] 读出的数据 +* 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SDIO_BlockRead(uint32_t block_addr, uint32_t buff[]) { @@ -254,13 +254,13 @@ uint32_t SDIO_BlockRead(uint32_t block_addr, uint32_t buff[]) } /****************************************************************************************************************************************** -* : SDIO_MultiBlockRead() -* ˵: SD -* : uint32_t block_addr SDַÿ512ֽ -* uint16_t block_cnt ҪĿ -* uint32_t buff[] -* : uint32_t SD_RES_OK ɹ SD_RES_ERR ʧ SD_RES_TIMEOUT ʱ -* ע: +* 函数名称: SDIO_MultiBlockRead() +* 功能说明: 从SD卡读出多块数据 +* 输 入: uint32_t block_addr SD卡块地址,每块512字节 +* uint16_t block_cnt 要读出的块数 +* uint32_t buff[] 读出的数据 +* 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SDIO_MultiBlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]) { @@ -289,13 +289,13 @@ uint32_t SDIO_MultiBlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t b } /****************************************************************************************************************************************** -* : SDIO_DMABlockRead() -* ˵: ͨDMASD -* : uint32_t block_addr SDַÿ512ֽ -* uint16_t block_cnt ҪĿ -* uint32_t buff[] -* : uint32_t SD_RES_OK ɹ SD_RES_ERR ʧ SD_RES_TIMEOUT ʱ -* ע: +* 函数名称: SDIO_DMABlockRead() +* 功能说明: 通过DMA从SD卡读出多块数据 +* 输 入: uint32_t block_addr SD卡块地址,每块512字节 +* uint16_t block_cnt 要读出的块数 +* uint32_t buff[] 读出的数据 +* 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SDIO_DMABlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]) { @@ -318,20 +318,20 @@ uint32_t SDIO_DMABlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buf } /****************************************************************************************************************************************** -* : _SDIO_SendCmd() -* ˵: SDIOSD -* : uint32_t cmd -* uint32_t arg -* uint32_t _resp_type ӦͣȡֵSD_RESP_NOSD_RESP_32bSD_RESP_128bSD_RESP_32b_busy -* uint32_t *resp_data Ӧ -* uint32_t have_data Ƿݴ -* uint32_t data_read 1 SD 0 дSD -* uint16_t block_cnt д -* uint32_t use_dma 1 ʹDMA -* : uint32_t SD_RES_OK ɹ SD_RES_ERR ʧ SD_RES_TIMEOUT ʱ -* ע: +* 函数名称: _SDIO_SendCmd() +* 功能说明: SDIO向SD卡发送命令 +* 输 入: uint32_t cmd 命令索引 +* uint32_t arg 命令参数 +* uint32_t resp_type 响应类型,取值SD_RESP_NO、SD_RESP_32b、SD_RESP_128b、SD_RESP_32b_busy +* uint32_t *resp_data 响应内容 +* uint32_t have_data 是否有数据传输 +* uint32_t data_read 1 读SD卡 0 写SD卡 +* uint16_t block_cnt 读写块个数 +* uint32_t use_dma 1 使用DMA搬运数据 +* 输 出: uint32_t SD_RES_OK 操作成功 SD_RES_ERR 操作失败 SD_RES_TIMEOUT 操作超时 +* 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t _SDIO_SendCmd(uint32_t cmd, uint32_t arg, uint32_t _resp_type, uint32_t *resp_data, uint32_t have_data, uint32_t data_read, uint16_t block_cnt, uint32_t use_dma) +uint32_t _SDIO_SendCmd(uint32_t cmd, uint32_t arg, uint32_t resp_type, uint32_t *resp_data, uint32_t have_data, uint32_t data_read, uint16_t block_cnt, uint32_t use_dma) { SDIO->BLK &= ~SDIO_BLK_COUNT_Msk; SDIO->BLK |= (block_cnt << SDIO_BLK_COUNT_Pos); @@ -341,7 +341,7 @@ uint32_t _SDIO_SendCmd(uint32_t cmd, uint32_t arg, uint32_t _resp_type, uint32_t (0 << SDIO_CMD_CMDTYPE_Pos) | (0 << SDIO_CMD_IDXCHECK_Pos) | (0 << SDIO_CMD_CRCCHECK_Pos) | - (_resp_type << SDIO_CMD_RESPTYPE_Pos) | + (resp_type << SDIO_CMD_RESPTYPE_Pos) | (have_data << SDIO_CMD_HAVEDATA_Pos) | (data_read << SDIO_CMD_DIRREAD_Pos) | ((block_cnt > 1) << SDIO_CMD_MULTBLK_Pos) | @@ -366,14 +366,14 @@ uint32_t _SDIO_SendCmd(uint32_t cmd, uint32_t arg, uint32_t _resp_type, uint32_t } SDIO->IF = SDIO_IF_CMDDONE_Msk; - if(_resp_type == SD_RESP_32b) + if(resp_type == SD_RESP_32b) { resp_data[0] = SDIO->RESP[0]; } - else if(_resp_type == SD_RESP_128b) + else if(resp_type == SD_RESP_128b) { - //ĴнCID/CSD[127-8]δRESP3-0[119-0]λCRC - //ʱ˳򣬽CID/CSD[127-8]resp_data0-3[127-8]8λ0x00 + //寄存器中将CID/CSD[127-8]依次存放在了RESP3-0[119-0],最低位的CRC被丢掉 + //读出数据时调整了顺序,将CID/CSD[127-8]存放在resp_data0-3[127-8],最低8位填充0x00 resp_data[0] = (SDIO->RESP[3] << 8) + ((SDIO->RESP[2] >> 24) & 0xFF); resp_data[1] = (SDIO->RESP[2] << 8) + ((SDIO->RESP[1] >> 24) & 0xFF); resp_data[2] = (SDIO->RESP[1] << 8) + ((SDIO->RESP[0] >> 24) & 0xFF); @@ -538,7 +538,7 @@ void parseCSD(uint32_t CSD_Tab[4]) /*!< Byte 10 */ tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8); - SD_cardInfo.CardCapacity = (SD_cardInfo.SD_csd.DeviceSize + 1) * 512 * 1024; + SD_cardInfo.CardCapacity = (uint64_t)(SD_cardInfo.SD_csd.DeviceSize + 1) * 512 * 1024; SD_cardInfo.CardBlockSize = 512; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.h index ece2711ce4..52552eed99 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.h @@ -35,10 +35,10 @@ #define SD_CMD_SDIO_RW_EXTENDED ((uint8_t)53) -#define SD_RESP_NO 0 //0 Ӧ -#define SD_RESP_32b 2 //2 32λӦ -#define SD_RESP_128b 1 //1 128λӦ -#define SD_RESP_32b_busy 3 //3 32λӦcheck Busy after response +#define SD_RESP_NO 0 //0 无响应 +#define SD_RESP_32b 2 //2 32位响应 +#define SD_RESP_128b 1 //1 128位响应 +#define SD_RESP_32b_busy 3 //3 32位响应,check Busy after response #define SD_BUSWIDTH_1b 0 #define SD_BUSWIDTH_4b 2 @@ -133,11 +133,11 @@ uint32_t SDIO_MultiBlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t b uint32_t SDIO_DMABlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]); uint32_t SDIO_DMABlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]); -uint32_t _SDIO_SendCmd(uint32_t cmd, uint32_t arg, uint32_t _resp_type, uint32_t *resp_data, uint32_t have_data, uint32_t data_read, uint16_t block_cnt, uint32_t use_dma); +uint32_t _SDIO_SendCmd(uint32_t cmd, uint32_t arg, uint32_t resp_type, uint32_t *resp_data, uint32_t have_data, uint32_t data_read, uint16_t block_cnt, uint32_t use_dma); -#define SDIO_SendCmd(cmd, arg, _resp_type, resp_data) _SDIO_SendCmd(cmd, arg, _resp_type, resp_data, 0, 0, 0, 0) -#define SDIO_SendCmdWithData(cmd, arg, _resp_type, resp_data, data_read, block_cnt) _SDIO_SendCmd(cmd, arg, _resp_type, resp_data, 1, data_read, block_cnt, 0) -#define SDIO_SendCmdWithDataByDMA(cmd, arg, _resp_type, resp_data, data_read, block_cnt) _SDIO_SendCmd(cmd, arg, _resp_type, resp_data, 1, data_read, block_cnt, 1) +#define SDIO_SendCmd(cmd, arg, resp_type, resp_data) _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 0, 0, 0, 0) +#define SDIO_SendCmdWithData(cmd, arg, resp_type, resp_data, data_read, block_cnt) _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 1, data_read, block_cnt, 0) +#define SDIO_SendCmdWithDataByDMA(cmd, arg, resp_type, resp_data, data_read, block_cnt) _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 1, data_read, block_cnt, 1) void parseCID(uint32_t CID_Tab[4]); void parseCSD(uint32_t CID_Tab[4]); diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.c index 246f572eeb..e1075564cb 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_sdram.c -* ˵: SWM320ƬSDRAM -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_sdram.c +* 功能说明: SWM320单片机的SDRAM驱动程序 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -22,11 +22,11 @@ #include "SWM320_sdram.h" /****************************************************************************************************************************************** -* : SDRAM_Init() -* ˵: SDRAMʼ -* : SDRAM_InitStructure * initStruct SDRAM 趨ֵĽṹ -* : -* ע: +* 函数名称: SDRAM_Init() +* 功能说明: SDRAM控制器初始化 +* 输 入: SDRAM_InitStructure * initStruct 包含 SDRAM 控制器相关设定值的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SDRAM_Init(SDRAM_InitStructure * initStruct) { @@ -35,9 +35,9 @@ void SDRAM_Init(SDRAM_InitStructure * initStruct) SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); SYS->CLKDIV &= ~SYS_CLKDIV_SDRAM_Msk; - SYS->CLKDIV |= (1 << SYS_CLKDIV_SDRAM_Pos); //2Ƶ + SYS->CLKDIV |= (1 << SYS_CLKDIV_SDRAM_Pos); //2分频 - SDRAMC->CR0 = (2 << SDRAMC_CR0_BURSTLEN_Pos) | //2 Burst LengthΪ4 + SDRAMC->CR0 = (2 << SDRAMC_CR0_BURSTLEN_Pos) | //2 Burst Length为4 (initStruct->CASLatency << SDRAMC_CR0_CASDELAY_Pos); SDRAMC->CR1 = (initStruct->CellSize << SDRAMC_CR1_CELLSIZE_Pos) | @@ -69,11 +69,11 @@ void SDRAM_Init(SDRAM_InitStructure * initStruct) } /****************************************************************************************************************************************** -* : SDRAM_Enable() -* ˵: SDRAMʹܣʹܺɶдSDRAM -* : -* : -* ע: +* 函数名称: SDRAM_Enable() +* 功能说明: SDRAM使能,使能后可读写SDRAM +* 输 入: 无 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SDRAM_Enable(void) { @@ -86,11 +86,11 @@ void SDRAM_Enable(void) } /****************************************************************************************************************************************** -* : SDRAM_Disable() -* ˵: SDRAMܣܺSDRAM͹ģʽˢ£ɶд -* : -* : -* ע: +* 函数名称: SDRAM_Disable() +* 功能说明: SDRAM禁能,禁能后SDRAM颗粒进入低功耗模式、并自刷新,不可读写 +* 输 入: 无 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SDRAM_Disable(void) { diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.h index 5659b3e330..d6f6761226 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.h @@ -2,17 +2,17 @@ #define __SWM320_SDRAM_H__ typedef struct { - uint8_t CellSize; // SDRAMSDRAM_CELLSIZE_16MbSDRAM_CELLSIZE_64MbSDRAM_CELLSIZE_128MbSDRAM_CELLSIZE_256Mb - uint8_t CellBank; // SDRAMмbankSDRAM_CELLBANK_2SDRAM_CELLBANK_4 - uint8_t CellWidth; // SDRAMλSDRAM_CELLWIDTH_16SDRAM_CELLWIDTH_32 - uint8_t CASLatency; // еַЧSDRAM_CASLATENCY_2SDRAM_CASLATENCY_3 + uint8_t CellSize; // SDRAM颗粒的容量,SDRAM_CELLSIZE_16Mb、SDRAM_CELLSIZE_64Mb、SDRAM_CELLSIZE_128Mb、SDRAM_CELLSIZE_256Mb + uint8_t CellBank; // SDRAM颗粒有几个bank,SDRAM_CELLBANK_2、SDRAM_CELLBANK_4 + uint8_t CellWidth; // SDRAM颗粒的位宽,SDRAM_CELLWIDTH_16、SDRAM_CELLWIDTH_32 + uint8_t CASLatency; // 列地址到有效数据输出间隔,SDRAM_CASLATENCY_2、SDRAM_CASLATENCY_3 uint8_t TimeTMRD; // MRS to New Command uint8_t TimeTRRD; // Activate to activate on different banks - uint8_t TimeTRAS; // Self refresh timeСSelf-refresh - uint8_t TimeTRC; // Row cycle delayRefreshActivateʱҲRefreshʱ - uint8_t TimeTRCD; // Row to column delayеַеַʱҲActivateдʱ - uint8_t TimeTRP; // Row precharge delayPrechargeһʱ + uint8_t TimeTRAS; // Self refresh time,最小Self-refresh周期 + uint8_t TimeTRC; // Row cycle delay,Refresh命令到Activate命令间延时,也是两个连续Refresh命令间延时 + uint8_t TimeTRCD; // Row to column delay,行地址到列地址间延时,也即Activate命令到读写命令间延时 + uint8_t TimeTRP; // Row precharge delay,Precharge命令到另一个命令间延时 } SDRAM_InitStructure; #define SDRAM_CELLSIZE_16Mb 3 diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.c index fb38187a3f..dcd618ec92 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_spi.c -* ˵: SWM320ƬSPI -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_spi.c +* 功能说明: SWM320单片机的SPI功能驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -23,12 +23,12 @@ /****************************************************************************************************************************************** -* : SPI_Init() -* ˵: SPIͬнӿڳʼ֡趨ʱ趨ٶ趨ж趨FIFO趨 -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* SPI_InitStructure * initStruct SPI趨ֵĽṹ -* : -* ע: +* 函数名称: SPI_Init() +* 功能说明: SPI同步串行接口初始化,包括帧长度设定、时序设定、速度设定、中断设定、FIFO触发设定 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* SPI_InitStructure * initStruct 包含SPI相关设定值的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_Init(SPI_TypeDef * SPIx, SPI_InitStructure * initStruct) { @@ -39,11 +39,11 @@ void SPI_Init(SPI_TypeDef * SPIx, SPI_InitStructure * initStruct) break; case ((uint32_t)SPI1): - SYS->CLKEN |= (0x01 << SYS_CLKEN_SPI0_Pos); //SPI0ʹͬһλʱʹ + SYS->CLKEN |= (0x01 << SYS_CLKEN_SPI0_Pos); //与SPI0使用同一位时钟使能 break; } - SPI_Close(SPIx); //һЩؼĴֻSPIرʱ + SPI_Close(SPIx); //一些关键寄存器只能在SPI关闭时设置 SPIx->CTRL &= ~(SPI_CTRL_FFS_Msk | SPI_CTRL_CPHA_Msk | SPI_CTRL_CPOL_Msk | SPI_CTRL_SIZE_Msk | SPI_CTRL_MSTR_Msk | SPI_CTRL_CLKDIV_Msk | SPI_CTRL_SSN_H_Msk); @@ -55,7 +55,7 @@ void SPI_Init(SPI_TypeDef * SPIx, SPI_InitStructure * initStruct) (initStruct->clkDiv << SPI_CTRL_CLKDIV_Pos) | (0 << SPI_CTRL_SSN_H_Pos); - SPIx->IF = (0x01 << SPI_IF_RFOVF_Pos); //жϱ־ + SPIx->IF = (0x01 << SPI_IF_RFOVF_Pos); //清除中断标志 SPIx->IE &= ~(SPI_IE_RFHF_Msk | SPI_IE_TFHF_Msk | SPI_IE_FTC_Msk); SPIx->IE |= (initStruct->RXHFullIEn << SPI_IE_RFHF_Pos) | (initStruct->TXEmptyIEn << SPI_IE_TFHF_Pos) | @@ -88,11 +88,11 @@ void SPI_Init(SPI_TypeDef * SPIx, SPI_InitStructure * initStruct) } /****************************************************************************************************************************************** -* : SPI_Open() -* ˵: SPI򿪣շ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_Open() +* 功能说明: SPI打开,允许收发 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_Open(SPI_TypeDef * SPIx) { @@ -100,11 +100,11 @@ void SPI_Open(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_Close() -* ˵: SPIرգֹշ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_Close() +* 功能说明: SPI关闭,禁止收发 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_Close(SPI_TypeDef * SPIx) { @@ -112,11 +112,11 @@ void SPI_Close(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_Read() -* ˵: ȡһ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : uint32_t ȡ -* ע: +* 函数名称: SPI_Read() +* 功能说明: 读取一个数据 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: uint32_t 读取到的数据 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SPI_Read(SPI_TypeDef * SPIx) { @@ -124,12 +124,12 @@ uint32_t SPI_Read(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_Write() -* ˵: дһ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* uint32_t Ҫд -* : -* ע: +* 函数名称: SPI_Write() +* 功能说明: 写入一个数据 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* uint32_t 要写入的数据 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_Write(SPI_TypeDef * SPIx, uint32_t data) { @@ -137,12 +137,12 @@ void SPI_Write(SPI_TypeDef * SPIx, uint32_t data) } /****************************************************************************************************************************************** -* : SPI_WriteWithWait() -* ˵: дһݲȴȫͳȥ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1SPI1 -* uint32_t Ҫд -* : -* ע: +* 函数名称: SPI_WriteWithWait() +* 功能说明: 写入一个数据并等待数据完全发送出去 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1、SPI1 +* uint32_t 要写入的数据 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_WriteWithWait(SPI_TypeDef * SPIx, uint32_t data) { @@ -154,12 +154,12 @@ void SPI_WriteWithWait(SPI_TypeDef * SPIx, uint32_t data) } /****************************************************************************************************************************************** -* : SPI_ReadWrite() -* ˵: һݣط͹нյ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* uint32_t data Ҫ͵ -* : uint32_t յ -* ע: ͬһSPIģ飬˺ӦSPI_Write()ãΪSPI_Write()SPI_STAT_RFNE״̬ +* 函数名称: SPI_ReadWrite() +* 功能说明: 发送一个数据,并返回发送过程中接收到的 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* uint32_t data 要发送的数据 +* 输 出: uint32_t 接收到的数据 +* 注意事项: 对于同一个SPI模块,此函数不应与SPI_Write()混着用,因为SPI_Write()不清除SPI_STAT_RFNE状态 ******************************************************************************************************************************************/ uint32_t SPI_ReadWrite(SPI_TypeDef * SPIx, uint32_t data) { @@ -170,11 +170,11 @@ uint32_t SPI_ReadWrite(SPI_TypeDef * SPIx, uint32_t data) } /****************************************************************************************************************************************** -* : SPI_IsRXEmpty() -* ˵: FIFOǷգԼSPI_Read() -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : uint32_t 1 FIFO 0 FIFOǿ -* ע: +* 函数名称: SPI_IsRXEmpty() +* 功能说明: 接收FIFO是否空,如果不空则可以继续SPI_Read() +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: uint32_t 1 接收FIFO空 0 接收FIFO非空 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SPI_IsRXEmpty(SPI_TypeDef * SPIx) { @@ -182,11 +182,11 @@ uint32_t SPI_IsRXEmpty(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_IsTXFull() -* ˵: FIFOǷԼSPI_Write() -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : uint32_t 1 FIFO 0 FIFO -* ע: +* 函数名称: SPI_IsTXFull() +* 功能说明: 发送FIFO是否满,如果不满则可以继续SPI_Write() +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: uint32_t 1 发送FIFO满 0 发送FIFO不满 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SPI_IsTXFull(SPI_TypeDef * SPIx) { @@ -194,11 +194,11 @@ uint32_t SPI_IsTXFull(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_IsTXEmpty() -* ˵: FIFOǷ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : uint32_t 1 FIFO 0 FIFOǿ -* ע: +* 函数名称: SPI_IsTXEmpty() +* 功能说明: 发送FIFO是否空 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: uint32_t 1 发送FIFO空 0 发送FIFO非空 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SPI_IsTXEmpty(SPI_TypeDef * SPIx) { @@ -207,11 +207,11 @@ uint32_t SPI_IsTXEmpty(SPI_TypeDef * SPIx) /****************************************************************************************************************************************** -* : SPI_INTRXHalfFullEn() -* ˵: FIFOжʹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTRXHalfFullEn() +* 功能说明: 接收FIFO半满中断使能 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTRXHalfFullEn(SPI_TypeDef * SPIx) { @@ -219,11 +219,11 @@ void SPI_INTRXHalfFullEn(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTRXHalfFullDis() -* ˵: FIFOжϽֹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTRXHalfFullDis() +* 功能说明: 接收FIFO半满中断禁止 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTRXHalfFullDis(SPI_TypeDef * SPIx) { @@ -231,11 +231,11 @@ void SPI_INTRXHalfFullDis(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTRXHalfFullClr() -* ˵: FIFOжϱ־ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTRXHalfFullClr() +* 功能说明: 接收FIFO半满中断标志清除 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTRXHalfFullClr(SPI_TypeDef * SPIx) { @@ -243,11 +243,11 @@ void SPI_INTRXHalfFullClr(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTRXHalfFullStat() -* ˵: FIFOж״̬ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : uint32_t 1 FIFOﵽ 0 FIFOδﵽ -* ע: +* 函数名称: SPI_INTRXHalfFullStat() +* 功能说明: 接收FIFO半满中断状态 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: uint32_t 1 接收FIFO达到半满 0 接收FIFO未达到半满 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SPI_INTRXHalfFullStat(SPI_TypeDef * SPIx) { @@ -255,11 +255,11 @@ uint32_t SPI_INTRXHalfFullStat(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTRXFullEn() -* ˵: FIFOжʹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTRXFullEn() +* 功能说明: 接收FIFO满中断使能 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTRXFullEn(SPI_TypeDef * SPIx) { @@ -267,11 +267,11 @@ void SPI_INTRXFullEn(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTRXFullDis() -* ˵: FIFOжϽֹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTRXFullDis() +* 功能说明: 接收FIFO满中断禁止 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTRXFullDis(SPI_TypeDef * SPIx) { @@ -279,11 +279,11 @@ void SPI_INTRXFullDis(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTRXFullClr() -* ˵: FIFOжϱ־ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTRXFullClr() +* 功能说明: 接收FIFO满中断标志清除 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTRXFullClr(SPI_TypeDef * SPIx) { @@ -291,11 +291,11 @@ void SPI_INTRXFullClr(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTRXFullStat() -* ˵: FIFOж״̬ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : uint32_t 1 FIFO 0 FIFOδ -* ע: +* 函数名称: SPI_INTRXFullStat() +* 功能说明: 接收FIFO满中断状态 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: uint32_t 1 接收FIFO满 0 接收FIFO未满 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SPI_INTRXFullStat(SPI_TypeDef * SPIx) { @@ -303,11 +303,11 @@ uint32_t SPI_INTRXFullStat(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTRXOverflowEn() -* ˵: FIFOжʹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTRXOverflowEn() +* 功能说明: 接收FIFO溢出中断使能 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTRXOverflowEn(SPI_TypeDef * SPIx) { @@ -315,11 +315,11 @@ void SPI_INTRXOverflowEn(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTRXOverflowDis() -* ˵: FIFOжϽֹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTRXOverflowDis() +* 功能说明: 接收FIFO溢出中断禁止 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTRXOverflowDis(SPI_TypeDef * SPIx) { @@ -327,11 +327,11 @@ void SPI_INTRXOverflowDis(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTRXOverflowClr() -* ˵: FIFOжϱ־ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTRXOverflowClr() +* 功能说明: 接收FIFO溢出中断标志清除 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTRXOverflowClr(SPI_TypeDef * SPIx) { @@ -339,11 +339,11 @@ void SPI_INTRXOverflowClr(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTRXOverflowStat() -* ˵: FIFOж״̬ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : uint32_t 1 FIFO 0 FIFOδ -* ע: +* 函数名称: SPI_INTRXOverflowStat() +* 功能说明: 接收FIFO溢出中断状态 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: uint32_t 1 接收FIFO溢出 0 接收FIFO未溢出 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SPI_INTRXOverflowStat(SPI_TypeDef * SPIx) { @@ -351,11 +351,11 @@ uint32_t SPI_INTRXOverflowStat(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXHalfFullEn() -* ˵: FIFOжʹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXHalfFullEn() +* 功能说明: 发送FIFO半满中断使能 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXHalfFullEn(SPI_TypeDef * SPIx) { @@ -363,11 +363,11 @@ void SPI_INTTXHalfFullEn(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXHalfFullDis() -* ˵: FIFOжϽֹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXHalfFullDis() +* 功能说明: 发送FIFO半满中断禁止 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXHalfFullDis(SPI_TypeDef * SPIx) { @@ -375,11 +375,11 @@ void SPI_INTTXHalfFullDis(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXHalfFullClr() -* ˵: FIFOжϱ־ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXHalfFullClr() +* 功能说明: 发送FIFO半满中断标志清除 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXHalfFullClr(SPI_TypeDef * SPIx) { @@ -387,11 +387,11 @@ void SPI_INTTXHalfFullClr(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXHalfFullStat() -* ˵: FIFOж״̬ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : uint32_t 1 FIFOﵽ 0 FIFOδﵽ -* ע: +* 函数名称: SPI_INTTXHalfFullStat() +* 功能说明: 发送FIFO半满中断状态 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: uint32_t 1 发送FIFO达到半满 0 发送FIFO未达到半满 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SPI_INTTXHalfFullStat(SPI_TypeDef * SPIx) { @@ -399,11 +399,11 @@ uint32_t SPI_INTTXHalfFullStat(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXEmptyEn() -* ˵: FIFOжʹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXEmptyEn() +* 功能说明: 发送FIFO空中断使能 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXEmptyEn(SPI_TypeDef * SPIx) { @@ -411,11 +411,11 @@ void SPI_INTTXEmptyEn(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXEmptyDis() -* ˵: FIFOжϽֹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXEmptyDis() +* 功能说明: 发送FIFO空中断禁止 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXEmptyDis(SPI_TypeDef * SPIx) { @@ -423,11 +423,11 @@ void SPI_INTTXEmptyDis(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXEmptyClr() -* ˵: FIFOжϱ־ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXEmptyClr() +* 功能说明: 发送FIFO空中断标志清除 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXEmptyClr(SPI_TypeDef * SPIx) { @@ -435,11 +435,11 @@ void SPI_INTTXEmptyClr(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXEmptyStat() -* ˵: FIFOж״̬ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : uint32_t 1 FIFO 0 FIFOǿ -* ע: +* 函数名称: SPI_INTTXEmptyStat() +* 功能说明: 发送FIFO空中断状态 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: uint32_t 1 发送FIFO空 0 发送FIFO非空 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SPI_INTTXEmptyStat(SPI_TypeDef * SPIx) { @@ -447,11 +447,11 @@ uint32_t SPI_INTTXEmptyStat(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXCompleteEn() -* ˵: FIFOҷλĴжʹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXCompleteEn() +* 功能说明: 发送FIFO空且发送移位寄存器空中断使能 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXCompleteEn(SPI_TypeDef * SPIx) { @@ -459,11 +459,11 @@ void SPI_INTTXCompleteEn(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXCompleteDis() -* ˵: FIFOҷλĴжϽֹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXCompleteDis() +* 功能说明: 发送FIFO空且发送移位寄存器空中断禁止 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXCompleteDis(SPI_TypeDef * SPIx) { @@ -471,11 +471,11 @@ void SPI_INTTXCompleteDis(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXCompleteClr() -* ˵: FIFOҷλĴж״̬ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXCompleteClr() +* 功能说明: 发送FIFO空且发送移位寄存器空中断状态清除 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXCompleteClr(SPI_TypeDef * SPIx) { @@ -483,11 +483,11 @@ void SPI_INTTXCompleteClr(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXCompleteStat() -* ˵: FIFOҷλĴж״̬ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : uint32_t 1 FIFOҷλĴ 0 FIFOλĴǿ -* ע: +* 函数名称: SPI_INTTXCompleteStat() +* 功能说明: 发送FIFO空且发送移位寄存器空中断状态 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: uint32_t 1 发送FIFO空且发送移位寄存器空 0 发送FIFO或发送移位寄存器非空 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SPI_INTTXCompleteStat(SPI_TypeDef * SPIx) { @@ -495,11 +495,11 @@ uint32_t SPI_INTTXCompleteStat(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXWordCompleteEn() -* ˵: FIFOַжʹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXWordCompleteEn() +* 功能说明: 发送FIFO字发送完成中断使能 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXWordCompleteEn(SPI_TypeDef * SPIx) { @@ -507,11 +507,11 @@ void SPI_INTTXWordCompleteEn(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXWordCompleteDis() -* ˵: FIFOַжϽֹ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXWordCompleteDis() +* 功能说明: 发送FIFO字发送完成中断禁止 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXWordCompleteDis(SPI_TypeDef * SPIx) { @@ -519,11 +519,11 @@ void SPI_INTTXWordCompleteDis(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXWordCompleteClr() -* ˵: FIFOַжϱ־ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : -* ע: +* 函数名称: SPI_INTTXWordCompleteClr() +* 功能说明: 发送FIFO字发送完成中断标志清除 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SPI_INTTXWordCompleteClr(SPI_TypeDef * SPIx) { @@ -531,11 +531,11 @@ void SPI_INTTXWordCompleteClr(SPI_TypeDef * SPIx) } /****************************************************************************************************************************************** -* : SPI_INTTXWordCompleteStat() -* ˵: FIFOַж״̬ -* : SPI_TypeDef * SPIx ָҪõSPIЧֵSPI0SPI1 -* : uint32_t 1 жѷ 0 жδ -* ע: +* 函数名称: SPI_INTTXWordCompleteStat() +* 功能说明: 发送FIFO字发送完成中断状态 +* 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1 +* 输 出: uint32_t 1 发送完成中断已发生 0 发送完成中断未发生 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t SPI_INTTXWordCompleteStat(SPI_TypeDef * SPIx) { diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.h index 42c4d0cb70..a7725ee24e 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.h @@ -2,26 +2,26 @@ #define __SWM320_SPI_H__ typedef struct { - uint8_t FrameFormat; //֡ʽSPI_FORMAT_SPISPI_FORMAT_TI_SSI - uint8_t SampleEdge; //SPI֡ʽ£ѡݲأSPI_FIRST_EDGESPI_SECOND_EDGE - uint8_t IdleLevel; //SPI֡ʽ£ѡʱݴʱʱߵĵƽSPI_LOW_LEVELSPI_HIGH_LEVEL - uint8_t WordSize; //ֳ, Чֵ4-16 - uint8_t Master; //1 ģʽ 0 ӻģʽ - uint8_t clkDiv; //SPI_CLK = SYS_CLK / clkDivЧֵSPI_CLKDIV_4SPI_CLKDIV_8... ... SPI_CLKDIV_512 + uint8_t FrameFormat; //帧格式:SPI_FORMAT_SPI、SPI_FORMAT_TI_SSI + uint8_t SampleEdge; //在SPI帧格式下,选择数据采样边沿:SPI_FIRST_EDGE、SPI_SECOND_EDGE + uint8_t IdleLevel; //在SPI帧格式下,选择空闲时(无数据传输时)时钟线的电平:SPI_LOW_LEVEL、SPI_HIGH_LEVEL + uint8_t WordSize; //字长度, 有效值4-16 + uint8_t Master; //1 主机模式 0 从机模式 + uint8_t clkDiv; //SPI_CLK = SYS_CLK / clkDiv,有效值:SPI_CLKDIV_4、SPI_CLKDIV_8、... ... 、SPI_CLKDIV_512 - uint8_t RXHFullIEn; //FIFOжʹ - uint8_t TXEmptyIEn; //FIFO жʹ - uint8_t TXCompleteIEn; //FIFO ҷλĴжʹ + uint8_t RXHFullIEn; //接收FIFO半满中断使能 + uint8_t TXEmptyIEn; //发送FIFO 空中断使能 + uint8_t TXCompleteIEn; //发送FIFO 空且发送移位寄存器空中断使能 } SPI_InitStructure; -#define SPI_FORMAT_SPI 0 //Motorola SPI ʽ -#define SPI_FORMAT_TI_SSI 1 //TI SSI ʽ +#define SPI_FORMAT_SPI 0 //Motorola SPI 格式 +#define SPI_FORMAT_TI_SSI 1 //TI SSI 格式 -#define SPI_FIRST_EDGE 0 //һʱؿʼ -#define SPI_SECOND_EDGE 1 //ڶʱؿʼ +#define SPI_FIRST_EDGE 0 //第一个时钟沿开始采样 +#define SPI_SECOND_EDGE 1 //第二个时钟沿开始采样 -#define SPI_LOW_LEVEL 0 //ʱʱֵ߱͵ƽ -#define SPI_HIGH_LEVEL 1 //ʱʱָ߱ߵƽ +#define SPI_LOW_LEVEL 0 //空闲时时钟线保持低电平 +#define SPI_HIGH_LEVEL 1 //空闲时时钟线保持高电平 #define SPI_CLKDIV_4 0 #define SPI_CLKDIV_8 1 @@ -34,18 +34,18 @@ typedef struct { -void SPI_Init(SPI_TypeDef * SPIx, SPI_InitStructure * initStruct); //SPIʼ -void SPI_Open(SPI_TypeDef * SPIx); //SPI򿪣շ -void SPI_Close(SPI_TypeDef * SPIx); //SPIرգֹշ +void SPI_Init(SPI_TypeDef * SPIx, SPI_InitStructure * initStruct); //SPI初始化 +void SPI_Open(SPI_TypeDef * SPIx); //SPI打开,允许收发 +void SPI_Close(SPI_TypeDef * SPIx); //SPI关闭,禁止收发 uint32_t SPI_Read(SPI_TypeDef * SPIx); void SPI_Write(SPI_TypeDef * SPIx, uint32_t data); void SPI_WriteWithWait(SPI_TypeDef * SPIx, uint32_t data); uint32_t SPI_ReadWrite(SPI_TypeDef * SPIx, uint32_t data); -uint32_t SPI_IsRXEmpty(SPI_TypeDef * SPIx); //FIFOǷգԼSPI_Read() -uint32_t SPI_IsTXFull(SPI_TypeDef * SPIx); //FIFOǷԼSPI_Write() -uint32_t SPI_IsTXEmpty(SPI_TypeDef * SPIx); //FIFOǷ +uint32_t SPI_IsRXEmpty(SPI_TypeDef * SPIx); //接收FIFO是否空,如果不空则可以继续SPI_Read() +uint32_t SPI_IsTXFull(SPI_TypeDef * SPIx); //发送FIFO是否满,如果不满则可以继续SPI_Write() +uint32_t SPI_IsTXEmpty(SPI_TypeDef * SPIx); //发送FIFO是否空 void SPI_INTRXHalfFullEn(SPI_TypeDef * SPIx); diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.c index d1f421aaba..62e4c84eed 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_sram.c -* ˵: SWM320ƬSRAM -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_sram.c +* 功能说明: SWM320单片机的SRAM驱动程序 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -23,17 +23,17 @@ /****************************************************************************************************************************************** -* : SRAM_Init() -* ˵: SRAMʼ -* : SRAM_InitStructure * initStruct SRAM 趨ֵĽṹ -* : -* ע: +* 函数名称: SRAM_Init() +* 功能说明: SRAM控制器初始化 +* 输 入: SRAM_InitStructure * initStruct 包含 SRAM 控制器相关设定值的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void SRAM_Init(SRAM_InitStructure * initStruct) { uint32_t i; - // SRAMǰҪˢSDRAM + // 配置SRAM前需要刷新下SDRAM控制器 do { SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); @@ -49,5 +49,5 @@ void SRAM_Init(SRAM_InitStructure * initStruct) SRAMC->CR = (initStruct->ClkDiv << SRAMC_CR_RWTIME_Pos) | (initStruct->DataWidth << SRAMC_CR_BYTEIF_Pos) | - (0 << SRAMC_CR_HBLBDIS_Pos); // ʹֽڡַ + (0 << SRAMC_CR_HBLBDIS_Pos); // 使能字节、半字访问 } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.h index 2ef71b24ba..799b271a99 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.h @@ -2,8 +2,8 @@ #define __SWM320_SRAM_H__ typedef struct { - uint8_t ClkDiv; //SRAM_CLKDIV_5...SRAM_CLKDIV_16SRAMоƬܵƵѡʷƵ - uint8_t DataWidth; //SRAM_DATAWIDTH_8SRAM_DATAWIDTH_16 + uint8_t ClkDiv; //SRAM_CLKDIV_5...SRAM_CLKDIV_16,根据SRAM芯片所能跑的最高频率选择合适分频 + uint8_t DataWidth; //SRAM_DATAWIDTH_8、SRAM_DATAWIDTH_16 } SRAM_InitStructure; diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.c index d4cbe03238..b67711a49a 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_timr.c -* ˵: SWM320Ƭļ/ʱ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_timr.c +* 功能说明: SWM320单片机的计数器/定时器功能驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -23,20 +23,20 @@ /****************************************************************************************************************************************** -* : TIMR_Init() -* ˵: TIMRʱ/ʼ -* : TIMR_TypeDef * TIMRx ָҪõĶʱЧֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* uint32_t mode TIMR_MODE_TIMER ʱģʽ TIMR_MODE_COUNTER ģʽ -* uint32_t period ʱ/ -* uint32_t int_en жʹ -* : -* ע: +* 函数名称: TIMR_Init() +* 功能说明: TIMR定时器/计数器初始化 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,有效值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* uint32_t mode TIMR_MODE_TIMER 定时器模式 TIMR_MODE_COUNTER 计数器模式 +* uint32_t period 定时/计数周期 +* uint32_t int_en 中断使能 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void TIMR_Init(TIMR_TypeDef * TIMRx, uint32_t mode, uint32_t period, uint32_t int_en) { SYS->CLKEN |= (0x01 << SYS_CLKEN_TIMR_Pos); - TIMR_Stop(TIMRx); //һЩؼĴֻڶʱֹͣʱ + TIMR_Stop(TIMRx); //一些关键寄存器只能在定时器停止时设置 TIMRx->CTRL &= ~TIMR_CTRL_CLKSRC_Msk; TIMRx->CTRL |= mode << TIMR_CTRL_CLKSRC_Pos; @@ -46,7 +46,7 @@ void TIMR_Init(TIMR_TypeDef * TIMRx, uint32_t mode, uint32_t period, uint32_t in switch((uint32_t)TIMRx) { case ((uint32_t)TIMR0): - TIMRG->IF = (1 << TIMRG_IF_TIMR0_Pos); //ʹжǰжϱ־ + TIMRG->IF = (1 << TIMRG_IF_TIMR0_Pos); //使能中断前清除中断标志 TIMRG->IE &= ~TIMRG_IE_TIMR0_Msk; TIMRG->IE |= (int_en << TIMRG_IE_TIMR0_Pos); @@ -96,11 +96,11 @@ void TIMR_Init(TIMR_TypeDef * TIMRx, uint32_t mode, uint32_t period, uint32_t in } /****************************************************************************************************************************************** -* : TIMR_Start() -* ˵: ʱӳʼֵʼʱ/ -* : TIMR_TypeDef * TIMRx ָҪõĶʱȡֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* : -* ע: +* 函数名称: TIMR_Start() +* 功能说明: 启动定时器,从初始值开始计时/计数 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,可取值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void TIMR_Start(TIMR_TypeDef * TIMRx) { @@ -108,11 +108,11 @@ void TIMR_Start(TIMR_TypeDef * TIMRx) } /****************************************************************************************************************************************** -* : TIMR_Stop() -* ˵: ֹͣʱ -* : TIMR_TypeDef * TIMRx ָҪõĶʱȡֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* : -* ע: +* 函数名称: TIMR_Stop() +* 功能说明: 停止定时器 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,可取值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void TIMR_Stop(TIMR_TypeDef * TIMRx) { @@ -120,11 +120,11 @@ void TIMR_Stop(TIMR_TypeDef * TIMRx) } /****************************************************************************************************************************************** -* : TIMR_Halt() -* ˵: ͣʱֲֵ -* : TIMR_TypeDef * TIMRx ָҪõĶʱȡֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* : -* ע: +* 函数名称: TIMR_Halt() +* 功能说明: 暂停定时器,计数值保持不变 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,可取值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void TIMR_Halt(TIMR_TypeDef * TIMRx) { @@ -157,11 +157,11 @@ void TIMR_Halt(TIMR_TypeDef * TIMRx) } /****************************************************************************************************************************************** -* : TIMR_Resume() -* ˵: ָʱͣ -* : TIMR_TypeDef * TIMRx ָҪõĶʱȡֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* : -* ע: +* 函数名称: TIMR_Resume() +* 功能说明: 恢复定时器,从暂停处继续计数 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,可取值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void TIMR_Resume(TIMR_TypeDef * TIMRx) { @@ -194,12 +194,12 @@ void TIMR_Resume(TIMR_TypeDef * TIMRx) } /****************************************************************************************************************************************** -* : TIMR_SetPeriod() -* ˵: öʱ/ -* : TIMR_TypeDef * TIMRx ָҪõĶʱȡֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* uint32_t period ʱ/ -* : -* ע: +* 函数名称: TIMR_SetPeriod() +* 功能说明: 设置定时/计数周期 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,可取值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* uint32_t period 定时/计数周期 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void TIMR_SetPeriod(TIMR_TypeDef * TIMRx, uint32_t period) { @@ -207,11 +207,11 @@ void TIMR_SetPeriod(TIMR_TypeDef * TIMRx, uint32_t period) } /****************************************************************************************************************************************** -* : TIMR_GetPeriod() -* ˵: ȡʱ/ -* : TIMR_TypeDef * TIMRx ָҪõĶʱȡֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* : uint32_t ǰʱ/ -* ע: +* 函数名称: TIMR_GetPeriod() +* 功能说明: 获取定时/计数周期 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,可取值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* 输 出: uint32_t 当前定时/计数周期 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t TIMR_GetPeriod(TIMR_TypeDef * TIMRx) { @@ -219,11 +219,11 @@ uint32_t TIMR_GetPeriod(TIMR_TypeDef * TIMRx) } /****************************************************************************************************************************************** -* : TIMR_GetCurValue() -* ˵: ȡǰֵ -* : TIMR_TypeDef * TIMRx ָҪõĶʱȡֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* : uint32_t ǰֵ -* ע: +* 函数名称: TIMR_GetCurValue() +* 功能说明: 获取当前计数值 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,可取值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* 输 出: uint32_t 当前计数值 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t TIMR_GetCurValue(TIMR_TypeDef * TIMRx) { @@ -231,11 +231,11 @@ uint32_t TIMR_GetCurValue(TIMR_TypeDef * TIMRx) } /****************************************************************************************************************************************** -* : TIMR_INTEn() -* ˵: ʹж -* : TIMR_TypeDef * TIMRx ָҪõĶʱȡֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* : -* ע: +* 函数名称: TIMR_INTEn() +* 功能说明: 使能中断 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,可取值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void TIMR_INTEn(TIMR_TypeDef * TIMRx) { @@ -274,11 +274,11 @@ void TIMR_INTEn(TIMR_TypeDef * TIMRx) } /****************************************************************************************************************************************** -* : TIMR_INTDis() -* ˵: ж -* : TIMR_TypeDef * TIMRx ָҪõĶʱȡֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* : -* ע: +* 函数名称: TIMR_INTDis() +* 功能说明: 禁能中断 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,可取值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void TIMR_INTDis(TIMR_TypeDef * TIMRx) { @@ -311,11 +311,11 @@ void TIMR_INTDis(TIMR_TypeDef * TIMRx) } /****************************************************************************************************************************************** -* : TIMR_INTClr() -* ˵: жϱ־ -* : TIMR_TypeDef * TIMRx ָҪõĶʱȡֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* : -* ע: +* 函数名称: TIMR_INTClr() +* 功能说明: 清除中断标志 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,可取值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void TIMR_INTClr(TIMR_TypeDef * TIMRx) { @@ -348,11 +348,11 @@ void TIMR_INTClr(TIMR_TypeDef * TIMRx) } /****************************************************************************************************************************************** -* : TIMR_INTStat() -* ˵: ȡж״̬ -* : TIMR_TypeDef * TIMRx ָҪõĶʱȡֵTIMR0TIMR1TIMR2TIMR3TIMR4TIMR5 -* : uint32_t 0 TIMRxδж 1 TIMRxж -* ע: +* 函数名称: TIMR_INTStat() +* 功能说明: 获取中断状态 +* 输 入: TIMR_TypeDef * TIMRx 指定要被设置的定时器,可取值包括TIMR0、TIMR1、TIMR2、TIMR3、TIMR4、TIMR5 +* 输 出: uint32_t 0 TIMRx未产生中断 1 TIMRx产生了中断 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t TIMR_INTStat(TIMR_TypeDef * TIMRx) { @@ -382,32 +382,32 @@ uint32_t TIMR_INTStat(TIMR_TypeDef * TIMRx) /****************************************************************************************************************************************** -* : Pulse_Init() -* ˵: ܳʼ -* : uint32_t pulse PULSE_LOW PULSE_HIGH -* uint32_t int_en Ƿʹж -* : -* ע: +* 函数名称: Pulse_Init() +* 功能说明: 脉宽测量功能初始化 +* 输 入: uint32_t pulse PULSE_LOW 测量低脉冲宽度 PULSE_HIGH 测量高脉冲宽度 +* uint32_t int_en 是否使能脉冲测量完成中断 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void Pulse_Init(uint32_t pulse, uint32_t int_en) { SYS->CLKEN |= (0x01 << SYS_CLKEN_TIMR_Pos); - TIMRG->PCTRL = (0 << TIMRG_PCTRL_CLKSRC_Pos) | // ϵͳʱΪʱԴ + TIMRG->PCTRL = (0 << TIMRG_PCTRL_CLKSRC_Pos) | // 系统时钟作为时钟源 (pulse << TIMRG_PCTRL_HIGH_Pos) | (0 << TIMRG_PCTRL_EN_Pos); - TIMRG->IE |= (1 << TIMRG_IE_PULSE_Pos); //ʹܲܲѯжϱ־ + TIMRG->IE |= (1 << TIMRG_IE_PULSE_Pos); //使能才能查询中断标志 if(int_en) NVIC_EnableIRQ(PULSE_IRQn); } /****************************************************************************************************************************************** -* : Pulse_Start() -* ˵: Զرղ -* : -* : -* ע: +* 函数名称: Pulse_Start() +* 功能说明: 脉宽测量功能启动,测量到脉宽后会自动关闭测量功能 +* 输 入: 无 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void Pulse_Start(void) { @@ -415,17 +415,17 @@ void Pulse_Start(void) } /****************************************************************************************************************************************** -* : Pulse_Done() -* ˵: Ƿ -* : -* : uint32_t 1 0 δ -* ע: +* 函数名称: Pulse_Done() +* 功能说明: 脉宽测量是否完成 +* 输 入: 无 +* 输 出: uint32_t 1 测量已完成 0 测量未完成 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t Pulse_Done(void) { if(TIMRG->IF & TIMRG_IF_PULSE_Msk) { - TIMRG->IF = TIMRG_IF_PULSE_Msk; // жϱ־ + TIMRG->IF = TIMRG_IF_PULSE_Msk; // 清除中断标志 return 1; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.h index bd1aa2618d..5cfdce204d 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.h @@ -4,20 +4,20 @@ #define TIMR_MODE_TIMER 0 #define TIMR_MODE_COUNTER 1 -void TIMR_Init(TIMR_TypeDef * TIMRx, uint32_t mode, uint32_t period, uint32_t int_en); //ʱ/ʼ -void TIMR_Start(TIMR_TypeDef * TIMRx); //ʱӳʼֵʼʱ/ -void TIMR_Stop(TIMR_TypeDef * TIMRx); //ֹͣʱ -void TIMR_Halt(TIMR_TypeDef * TIMRx); //ͣʱֲֵ -void TIMR_Resume(TIMR_TypeDef * TIMRx); //ָʱͣ +void TIMR_Init(TIMR_TypeDef * TIMRx, uint32_t mode, uint32_t period, uint32_t int_en); //定时器/计数器初始化 +void TIMR_Start(TIMR_TypeDef * TIMRx); //启动定时器,从初始值开始计时/计数 +void TIMR_Stop(TIMR_TypeDef * TIMRx); //停止定时器 +void TIMR_Halt(TIMR_TypeDef * TIMRx); //暂停定时器,计数值保持不变 +void TIMR_Resume(TIMR_TypeDef * TIMRx); //恢复定时器,从暂停处继续计数 -void TIMR_SetPeriod(TIMR_TypeDef * TIMRx, uint32_t period); //öʱ/ -uint32_t TIMR_GetPeriod(TIMR_TypeDef * TIMRx); //ȡʱ/ -uint32_t TIMR_GetCurValue(TIMR_TypeDef * TIMRx); //ȡǰֵ +void TIMR_SetPeriod(TIMR_TypeDef * TIMRx, uint32_t period); //设置定时/计数周期 +uint32_t TIMR_GetPeriod(TIMR_TypeDef * TIMRx); //获取定时/计数周期 +uint32_t TIMR_GetCurValue(TIMR_TypeDef * TIMRx); //获取当前计数值 -void TIMR_INTEn(TIMR_TypeDef * TIMRx); //ʹж -void TIMR_INTDis(TIMR_TypeDef * TIMRx); //ж -void TIMR_INTClr(TIMR_TypeDef * TIMRx); //жϱ־ -uint32_t TIMR_INTStat(TIMR_TypeDef * TIMRx); //ȡж״̬ +void TIMR_INTEn(TIMR_TypeDef * TIMRx); //使能中断 +void TIMR_INTDis(TIMR_TypeDef * TIMRx); //禁能中断 +void TIMR_INTClr(TIMR_TypeDef * TIMRx); //清除中断标志 +uint32_t TIMR_INTStat(TIMR_TypeDef * TIMRx); //获取中断状态 diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.c index 6b3f046c75..73f219f7aa 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_uart.c -* ˵: SWM320ƬUARTڹ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: ûбдLINصĺ -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_uart.c +* 功能说明: SWM320单片机的UART串口功能驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: 没有编写LIN功能相关的函数 +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -23,12 +23,12 @@ /****************************************************************************************************************************************** -* : UART_Init() -* ˵: UARTڳʼ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* UART_InitStructure * initStruct UART趨ֵĽṹ -* : -* ע: +* 函数名称: UART_Init() +* 功能说明: UART串口初始化 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* UART_InitStructure * initStruct 包含UART串口相关设定值的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_Init(UART_TypeDef * UARTx, UART_InitStructure * initStruct) { @@ -51,7 +51,7 @@ void UART_Init(UART_TypeDef * UARTx, UART_InitStructure * initStruct) break; } - UART_Close(UARTx); //һЩؼĴֻڴڹرʱ + UART_Close(UARTx); //一些关键寄存器只能在串口关闭时设置 UARTx->CTRL |= (0x01 << UART_CTRL_BAUDEN_Pos); UARTx->BAUD &= ~UART_BAUD_BAUD_Msk; @@ -62,10 +62,10 @@ void UART_Init(UART_TypeDef * UARTx, UART_InitStructure * initStruct) (initStruct->Parity << UART_CTRL_PARITY_Pos) | (initStruct->StopBits << UART_CTRL_STOP2b_Pos); - /* SWM320У RXLVL >= RXTHR ʱжϣRXTHRΪ0Ļδյʱͻһֱжϣ - оƬУ RXLVL > RXTHR ʱжϣΪSWM320RXTHRΪ0⣬ͳһ⺯APIォRXTHRֵһ + /* 在SWM320中,当 RXLVL >= RXTHR 时触发中断,如果RXTHR设置为0的话,在未接收到数据时就会一直触发中断; + 其他芯片中,当 RXLVL > RXTHR 时触发中断,为解决SWM320中RXTHR不能为0的问题,并统一库函数API,这里将RXTHR设置值加一 */ - switch((uint32_t)UARTx) // λ NVIC ĴֶĴ RXTHR ʱᵼһֱ ISR + switch((uint32_t)UARTx) // 软件复位不能清零 NVIC 寄存器,若不手动清除,下面的代码清零 RXTHR 时会导致一直进入 ISR { case ((uint32_t)UART0): NVIC_DisableIRQ(UART0_IRQn); break; case ((uint32_t)UART1): NVIC_DisableIRQ(UART1_IRQn); break; @@ -133,11 +133,11 @@ void UART_Init(UART_TypeDef * UARTx, UART_InitStructure * initStruct) } /****************************************************************************************************************************************** -* : UART_Open() -* ˵: UARTڴ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : -* ע: +* 函数名称: UART_Open() +* 功能说明: UART串口打开 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_Open(UART_TypeDef * UARTx) { @@ -145,11 +145,11 @@ void UART_Open(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_Close() -* ˵: UARTڹر -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : -* ע: +* 函数名称: UART_Close() +* 功能说明: UART串口关闭 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_Close(UART_TypeDef * UARTx) { @@ -157,12 +157,12 @@ void UART_Close(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_WriteByte() -* ˵: һֽ -* : UART_TypeDef * UARTx ָҪõUARTڣȡֵUART0UART1UART2UART3UART4 -* uint32_t data Ҫ͵ֽ -* : -* ע: +* 函数名称: UART_WriteByte() +* 功能说明: 发送一个字节数据 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,可取值包括UART0、UART1、UART2、UART3、UART4 +* uint32_t data 要发送的字节 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_WriteByte(UART_TypeDef * UARTx, uint32_t data) { @@ -170,12 +170,12 @@ void UART_WriteByte(UART_TypeDef * UARTx, uint32_t data) } /****************************************************************************************************************************************** -* : UART_ReadByte() -* ˵: ȡһֽݣָǷValid -* : UART_TypeDef * UARTx ָҪõUARTڣȡֵUART0UART1UART2UART3UART4 -* uint32_t * data յ -* : uint32_t 0 ޴ UART_ERR_PARITY żУ -* ע: +* 函数名称: UART_ReadByte() +* 功能说明: 读取一个字节数据,并指出数据是否Valid +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,可取值包括UART0、UART1、UART2、UART3、UART4 +* uint32_t * data 接收到的数据 +* 输 出: uint32_t 0 无错误 UART_ERR_PARITY 奇偶校验错误 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_ReadByte(UART_TypeDef * UARTx, uint32_t * data) { @@ -189,11 +189,11 @@ uint32_t UART_ReadByte(UART_TypeDef * UARTx, uint32_t * data) } /****************************************************************************************************************************************** -* : UART_IsTXBusy() -* ˵: UARTǷڷ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 1 UARTڷ 0 ѷ -* ע: +* 函数名称: UART_IsTXBusy() +* 功能说明: UART是否正在发送数据 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 1 UART正在发送数据 0 数据已发完 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_IsTXBusy(UART_TypeDef * UARTx) { @@ -201,11 +201,11 @@ uint32_t UART_IsTXBusy(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_IsRXFIFOEmpty() -* ˵: FIFOǷΪգ˵ݿԶȡ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 1 FIFO 0 FIFOǿ -* ע: +* 函数名称: UART_IsRXFIFOEmpty() +* 功能说明: 接收FIFO是否为空,如果不空则说明其中有数据可以读取 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 1 接收FIFO空 0 接收FIFO非空 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_IsRXFIFOEmpty(UART_TypeDef * UARTx) { @@ -213,11 +213,11 @@ uint32_t UART_IsRXFIFOEmpty(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_IsTXFIFOFull() -* ˵: FIFOǷΪԼд -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 1 FIFO 0 FIFO -* ע: +* 函数名称: UART_IsTXFIFOFull() +* 功能说明: 发送FIFO是否为满,如果不满则可以继续向其中写入数据 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 1 发送FIFO满 0 发送FIFO不满 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_IsTXFIFOFull(UART_TypeDef * UARTx) { @@ -225,12 +225,12 @@ uint32_t UART_IsTXFIFOFull(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_SetBaudrate() -* ˵: ò -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* uint32_t baudrate ҪõIJ -* : -* ע: ҪڴڹʱIJʣʹô˺ǰȵUART_Close()رմ +* 函数名称: UART_SetBaudrate() +* 功能说明: 设置波特率 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* uint32_t baudrate 要设置的波特率 +* 输 出: 无 +* 注意事项: 不要在串口工作时更改波特率,使用此函数前请先调用UART_Close()关闭串口 ******************************************************************************************************************************************/ void UART_SetBaudrate(UART_TypeDef * UARTx, uint32_t baudrate) { @@ -239,11 +239,11 @@ void UART_SetBaudrate(UART_TypeDef * UARTx, uint32_t baudrate) } /****************************************************************************************************************************************** -* : UART_GetBaudrate() -* ˵: ѯ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t ǰ -* ע: +* 函数名称: UART_GetBaudrate() +* 功能说明: 查询波特率 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 当前波特率 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_GetBaudrate(UART_TypeDef * UARTx) { @@ -251,13 +251,13 @@ uint32_t UART_GetBaudrate(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_CTSConfig() -* ˵: UART CTS -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* uint32_t enable 1 ʹCTS 0 ֹCTS -* uint32_t polarity 0 CTSΪͱʾԷ 1 CTSΪ߱ʾԷ -* : -* ע: +* 函数名称: UART_CTSConfig() +* 功能说明: UART CTS流控配置 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* uint32_t enable 1 使能CTS流控 0 禁止CTS流控 +* uint32_t polarity 0 CTS输入为低表示可以发送数据 1 CTS输入为高表示可以发送数据 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_CTSConfig(UART_TypeDef * UARTx, uint32_t enable, uint32_t polarity) { @@ -267,11 +267,11 @@ void UART_CTSConfig(UART_TypeDef * UARTx, uint32_t enable, uint32_t polarity) } /****************************************************************************************************************************************** -* : UART_CTSLineState() -* ˵: UART CTSߵǰ״̬ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 0 CTSߵǰΪ͵ƽ 1 CTSߵǰΪߵƽ -* ע: +* 函数名称: UART_CTSLineState() +* 功能说明: UART CTS线当前状态 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 0 CTS线当前为低电平 1 CTS线当前为高电平 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_CTSLineState(UART_TypeDef * UARTx) { @@ -279,14 +279,14 @@ uint32_t UART_CTSLineState(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_RTSConfig() -* ˵: UART RTS -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* uint32_t enable 1 ʹRTS 0 ֹRTS -* uint32_t polarity 0 RTSͱʾԽ 1 RTS߱ʾԽ -* uint32_t threshold RTSصĴֵȡֵUART_RTS_1BYTEUART_RTS_2BYTEUART_RTS_4BYTEUART_RTS_6BYTE -* : -* ע: +* 函数名称: UART_RTSConfig() +* 功能说明: UART RTS流控配置 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* uint32_t enable 1 使能RTS流控 0 禁止RTS流控 +* uint32_t polarity 0 RTS输出低表示可以接收数据 1 RTS输出高表示可以接收数据 +* uint32_t threshold RTS流控的触发阈值,可取值UART_RTS_1BYTE、UART_RTS_2BYTE、UART_RTS_4BYTE、UART_RTS_6BYTE +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_RTSConfig(UART_TypeDef * UARTx, uint32_t enable, uint32_t polarity, uint32_t threshold) { @@ -297,11 +297,11 @@ void UART_RTSConfig(UART_TypeDef * UARTx, uint32_t enable, uint32_t polarity, ui } /****************************************************************************************************************************************** -* : UART_RTSLineState() -* ˵: UART RTSߵǰ״̬ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 0 RTSߵǰΪ͵ƽ 1 RTSߵǰΪߵƽ -* ע: +* 函数名称: UART_RTSLineState() +* 功能说明: UART RTS线当前状态 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 0 RTS线当前为低电平 1 RTS线当前为高电平 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_RTSLineState(UART_TypeDef * UARTx) { @@ -309,13 +309,13 @@ uint32_t UART_RTSLineState(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_LINConfig() -* ˵: UART LIN -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* uint32_t detectedIEn ⵽Breakжʹ -* uint32_t generatedIEn Breakжʹ -* : -* ע: +* 函数名称: UART_LINConfig() +* 功能说明: UART LIN功能配置 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* uint32_t detectedIEn 检测到Break中断使能 +* uint32_t generatedIEn Break发送完成中断使能 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_LINConfig(UART_TypeDef * UARTx, uint32_t detectedIEn, uint32_t generatedIEn) { @@ -325,11 +325,11 @@ void UART_LINConfig(UART_TypeDef * UARTx, uint32_t detectedIEn, uint32_t generat } /****************************************************************************************************************************************** -* : UART_LINGenerate() -* ˵: UART LIN/Break -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : -* ע: +* 函数名称: UART_LINGenerate() +* 功能说明: UART LIN产生/发送Break +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_LINGenerate(UART_TypeDef * UARTx) { @@ -337,11 +337,11 @@ void UART_LINGenerate(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_LINIsDetected() -* ˵: UART LINǷ⵽Break -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 1 ⵽LIN Break 0 δ⵽LIN Break -* ע: +* 函数名称: UART_LINIsDetected() +* 功能说明: UART LIN是否检测到Break +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 1 检测到LIN Break 0 未检测到LIN Break +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_LINIsDetected(UART_TypeDef * UARTx) { @@ -349,11 +349,11 @@ uint32_t UART_LINIsDetected(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_LINIsGenerated() -* ˵: UART LIN BreakǷ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 1 LIN Break 0 LIN Breakδ -* ע: +* 函数名称: UART_LINIsGenerated() +* 功能说明: UART LIN Break是否发送完成 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 1 LIN Break 发送完成 0 LIN Break发送未完成 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_LINIsGenerated(UART_TypeDef * UARTx) { @@ -361,14 +361,14 @@ uint32_t UART_LINIsGenerated(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_ABRStart() -* ˵: UART Զʼ⿪ʼ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* uint32_t detectChar Զ⡢㲨ʵļַ -* 8λʱȡֵ0xFF0xFE0xF80x80ֱʾͷ뷢0xFF0xFE0xF80x80 -* 9λʱȡֵ0x1FF0x1FE0x1F80x180ֱʾͷ뷢0x1FF0x1FE0x1F80x180 -* : -* ע: ԶʼʱܿżУ +* 函数名称: UART_ABRStart() +* 功能说明: UART 自动波特率检测开始 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* uint32_t detectChar 用于自动检测、计算波特率的检测字符 +* 8位数据时可取值:0xFF、0xFE、0xF8、0x80,分别表示发送方必须发送0xFF、0xFE、0xF8、0x80 +* 9位数据时可取值:0x1FF、0x1FE、0x1F8、0x180,分别表示发送方必须发送0x1FF、0x1FE、0x1F8、0x180 +* 输 出: 无 +* 注意事项: 自动波特率检测时不能开启奇偶校验 ******************************************************************************************************************************************/ void UART_ABRStart(UART_TypeDef * UARTx, uint32_t detectChar) { @@ -386,11 +386,11 @@ void UART_ABRStart(UART_TypeDef * UARTx, uint32_t detectChar) } /****************************************************************************************************************************************** -* : UART_ABRIsDone() -* ˵: UART ԶǷ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 0 δ UART_ABR_RES_OK ɣҳɹ UART_ABR_RES_ERR ɣʧܡ -* ע: +* 函数名称: UART_ABRIsDone() +* 功能说明: UART 自动波特率是否完成 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 0 未完成 UART_ABR_RES_OK 已完成,且成功 UART_ABR_RES_ERR 已完成,但失败、出错 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_ABRIsDone(UART_TypeDef * UARTx) { @@ -409,11 +409,11 @@ uint32_t UART_ABRIsDone(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTRXThresholdEn() -* ˵: RX FIFOݸ >= RXThresholdʱ ж -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : -* ע: +* 函数名称: UART_INTRXThresholdEn() +* 功能说明: 当RX FIFO中数据个数 >= RXThreshold时 触发中断 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_INTRXThresholdEn(UART_TypeDef * UARTx) { @@ -421,11 +421,11 @@ void UART_INTRXThresholdEn(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTRXThresholdDis() -* ˵: RX FIFOݸ >= RXThresholdʱ ж -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : -* ע: +* 函数名称: UART_INTRXThresholdDis() +* 功能说明: 当RX FIFO中数据个数 >= RXThreshold时 不触发中断 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_INTRXThresholdDis(UART_TypeDef * UARTx) { @@ -433,11 +433,11 @@ void UART_INTRXThresholdDis(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTRXThresholdStat() -* ˵: ǷRX FIFOݸ >= RXThreshold -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 1 RX FIFOݸ >= RXThreshold 0 RX FIFOݸ < RXThreshold -* ע: RXIF = RXTHRF & RXIE +* 函数名称: UART_INTRXThresholdStat() +* 功能说明: 是否RX FIFO中数据个数 >= RXThreshold +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 1 RX FIFO中数据个数 >= RXThreshold 0 RX FIFO中数据个数 < RXThreshold +* 注意事项: RXIF = RXTHRF & RXIE ******************************************************************************************************************************************/ uint32_t UART_INTRXThresholdStat(UART_TypeDef * UARTx) { @@ -445,11 +445,11 @@ uint32_t UART_INTRXThresholdStat(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTTXThresholdEn() -* ˵: TX FIFOݸ <= TXThresholdʱ ж -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : -* ע: +* 函数名称: UART_INTTXThresholdEn() +* 功能说明: 当TX FIFO中数据个数 <= TXThreshold时 触发中断 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_INTTXThresholdEn(UART_TypeDef * UARTx) { @@ -457,11 +457,11 @@ void UART_INTTXThresholdEn(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTTXThresholdDis() -* ˵: TX FIFOݸ <= TXThresholdʱ ж -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : -* ע: +* 函数名称: UART_INTTXThresholdDis() +* 功能说明: 当TX FIFO中数据个数 <= TXThreshold时 不触发中断 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_INTTXThresholdDis(UART_TypeDef * UARTx) { @@ -469,11 +469,11 @@ void UART_INTTXThresholdDis(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTTXThresholdStat() -* ˵: ǷTX FIFOݸ <= TXThreshold -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 1 TX FIFOݸ <= TXThreshold 0 TX FIFOݸ > TXThreshold -* ע: TXIF = TXTHRF & TXIE +* 函数名称: UART_INTTXThresholdStat() +* 功能说明: 是否TX FIFO中数据个数 <= TXThreshold +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 1 TX FIFO中数据个数 <= TXThreshold 0 TX FIFO中数据个数 > TXThreshold +* 注意事项: TXIF = TXTHRF & TXIE ******************************************************************************************************************************************/ uint32_t UART_INTTXThresholdStat(UART_TypeDef * UARTx) { @@ -481,11 +481,11 @@ uint32_t UART_INTTXThresholdStat(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTTimeoutEn() -* ˵: շʱʱ ж -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : -* ע: +* 函数名称: UART_INTTimeoutEn() +* 功能说明: 接收发生超时时 触发中断 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_INTTimeoutEn(UART_TypeDef * UARTx) { @@ -493,11 +493,11 @@ void UART_INTTimeoutEn(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTTimeoutDis() -* ˵: շʱʱ ж -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : -* ע: +* 函数名称: UART_INTTimeoutDis() +* 功能说明: 接收发生超时时 不触发中断 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_INTTimeoutDis(UART_TypeDef * UARTx) { @@ -505,11 +505,11 @@ void UART_INTTimeoutDis(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTTimeoutStat() -* ˵: Ƿ˽ճʱ TimeoutTime/(Baudrate/10) ûRXϽյʱж -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 1 ˽ճʱ 0 δճʱ -* ע: +* 函数名称: UART_INTTimeoutStat() +* 功能说明: 是否发生了接收超时,即超过 TimeoutTime/(Baudrate/10) 秒没有在RX线上接收到数据时触发中断 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 1 发生了接收超时 0 未发生接收超时 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_INTTimeoutStat(UART_TypeDef * UARTx) { @@ -517,11 +517,11 @@ uint32_t UART_INTTimeoutStat(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTTXDoneEn() -* ˵: FIFOҷλĴжʹ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : -* ע: +* 函数名称: UART_INTTXDoneEn() +* 功能说明: 发送FIFO空且发送移位寄存器空中断使能 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_INTTXDoneEn(UART_TypeDef * UARTx) { @@ -529,11 +529,11 @@ void UART_INTTXDoneEn(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTTXDoneDis() -* ˵: FIFOҷλĴжϽֹ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : -* ע: +* 函数名称: UART_INTTXDoneDis() +* 功能说明: 发送FIFO空且发送移位寄存器空中断禁止 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void UART_INTTXDoneDis(UART_TypeDef * UARTx) { @@ -541,11 +541,11 @@ void UART_INTTXDoneDis(UART_TypeDef * UARTx) } /****************************************************************************************************************************************** -* : UART_INTTXDoneStat() -* ˵: FIFOҷλĴж״̬ -* : UART_TypeDef * UARTx ָҪõUARTڣЧֵUART0UART1UART2UART3 -* : uint32_t 1 FIFOҷλĴ 0 FIFOλĴδ -* ע: +* 函数名称: UART_INTTXDoneStat() +* 功能说明: 发送FIFO空且发送移位寄存器空中断状态 +* 输 入: UART_TypeDef * UARTx 指定要被设置的UART串口,有效值包括UART0、UART1、UART2、UART3 +* 输 出: uint32_t 1 发送FIFO空且发送移位寄存器空 0 发送FIFO或发送移位寄存器未空 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t UART_INTTXDoneStat(UART_TypeDef * UARTx) { diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.h index 1611744cb7..bad63f420c 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.h @@ -4,20 +4,20 @@ typedef struct { uint32_t Baudrate; - uint8_t DataBits; //λλȡֵUART_DATA_8BITUART_DATA_9BIT + uint8_t DataBits; //数据位位数,可取值UART_DATA_8BIT、UART_DATA_9BIT - uint8_t Parity; //żУλȡֵUART_PARITY_NONEUART_PARITY_ODDUART_PARITY_EVENUART_PARITY_ONEUART_PARITY_ZERO + uint8_t Parity; //奇偶校验位,可取值UART_PARITY_NONE、UART_PARITY_ODD、UART_PARITY_EVEN、UART_PARITY_ONE、UART_PARITY_ZERO - uint8_t StopBits; //ֹͣλλȡֵUART_STOP_1BITUART_STOP_2BIT + uint8_t StopBits; //停止位位数,可取值UART_STOP_1BIT、UART_STOP_2BIT - uint8_t RXThreshold; //ȡֵ0--7 - uint8_t RXThresholdIEn; //RX FIFOݸ > RXThresholdʱж + uint8_t RXThreshold; //取值0--7 + uint8_t RXThresholdIEn; //当RX FIFO中数据个数 > RXThreshold时触发中断 - uint8_t TXThreshold; //ȡֵ0--7 - uint8_t TXThresholdIEn; //TX FIFOݸ <= TXThresholdʱж + uint8_t TXThreshold; //取值0--7 + uint8_t TXThresholdIEn; //当TX FIFO中数据个数 <= TXThreshold时触发中断 - uint8_t TimeoutTime; //ʱʱ = TimeoutTime/(Baudrate/10) - uint8_t TimeoutIEn; //ʱжϣRX FIFOǿգҳ TimeoutTime/(Baudrate/10) ûRXϽյʱж + uint8_t TimeoutTime; //超时时长 = TimeoutTime/(Baudrate/10) 秒 + uint8_t TimeoutIEn; //超时中断,RX FIFO非空,且超过 TimeoutTime/(Baudrate/10) 秒没有在RX线上接收到数据时触发中断 } UART_InitStructure; @@ -46,20 +46,20 @@ typedef struct { #define UART_ERR_NOISE 3 -void UART_Init(UART_TypeDef * UARTx, UART_InitStructure * initStruct); //UARTڳʼ +void UART_Init(UART_TypeDef * UARTx, UART_InitStructure * initStruct); //UART串口初始化 void UART_Open(UART_TypeDef * UARTx); void UART_Close(UART_TypeDef * UARTx); -void UART_WriteByte(UART_TypeDef * UARTx, uint32_t data); //һֽ -uint32_t UART_ReadByte(UART_TypeDef * UARTx, uint32_t * data); //ȡһֽݣָǷValid +void UART_WriteByte(UART_TypeDef * UARTx, uint32_t data); //发送一个字节数据 +uint32_t UART_ReadByte(UART_TypeDef * UARTx, uint32_t * data); //读取一个字节数据,并指出数据是否Valid uint32_t UART_IsTXBusy(UART_TypeDef * UARTx); -uint32_t UART_IsRXFIFOEmpty(UART_TypeDef * UARTx); //FIFOǷգԼUART_ReadByte() -uint32_t UART_IsTXFIFOFull(UART_TypeDef * UARTx); //FIFOǷԼUART_WriteByte() +uint32_t UART_IsRXFIFOEmpty(UART_TypeDef * UARTx); //接收FIFO是否空,如果不空则可以继续UART_ReadByte() +uint32_t UART_IsTXFIFOFull(UART_TypeDef * UARTx); //发送FIFO是否满,如果不满则可以继续UART_WriteByte() -void UART_SetBaudrate(UART_TypeDef * UARTx, uint32_t baudrate); //ò -uint32_t UART_GetBaudrate(UART_TypeDef * UARTx); //ȡǰʹõIJ +void UART_SetBaudrate(UART_TypeDef * UARTx, uint32_t baudrate); //设置波特率 +uint32_t UART_GetBaudrate(UART_TypeDef * UARTx); //获取当前使用的波特率 void UART_CTSConfig(UART_TypeDef * UARTx, uint32_t enable, uint32_t polarity); uint32_t UART_CTSLineState(UART_TypeDef * UARTx); diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.c index 762e79b3ae..59a358b69e 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_wdt.c -* ˵: SWM320ƬWDTŹ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_wdt.c +* 功能说明: SWM320单片机的WDT看门狗功能驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -23,19 +23,19 @@ /****************************************************************************************************************************************** -* : WDT_Init() -* ˵: WDTŹʼ -* : WDT_TypeDef * WDTx ָҪõĿŹЧֵWDT -* uint32_t peroid ȡֵ0--4294967295λΪƬϵͳʱ -* uint32_t mode WDT_MODE_RESET ʱλ WDT_MODE_INTERRUPT ʱж -* : -* ע: λʹʱжϲãΪڽʱоƬֱӸλˣ޷Ӧж +* 函数名称: WDT_Init() +* 功能说明: WDT看门狗初始化 +* 输 入: WDT_TypeDef * WDTx 指定要被设置的看门狗,有效值包括WDT +* uint32_t peroid 取值0--4294967295,单位为单片机系统时钟周期 +* uint32_t mode WDT_MODE_RESET 超时产生复位 WDT_MODE_INTERRUPT 超时产生中断 +* 输 出: 无 +* 注意事项: 复位使能时中断不起作用,因为计数周期结束时芯片直接复位了,无法响应中断 ******************************************************************************************************************************************/ void WDT_Init(WDT_TypeDef * WDTx, uint32_t peroid, uint32_t mode) { SYS->CLKEN |= (0x01 << SYS_CLKEN_WDT_Pos); - WDT_Stop(WDTx); //ǰȹر + WDT_Stop(WDTx); //设置前先关闭 WDTx->LOAD = peroid; @@ -54,11 +54,11 @@ void WDT_Init(WDT_TypeDef * WDTx, uint32_t peroid, uint32_t mode) } /****************************************************************************************************************************************** -* : WDT_Start() -* ˵: ָWDTʼʱ -* : WDT_TypeDef * WDTx ָҪõĿŹЧֵWDT -* : -* ע: +* 函数名称: WDT_Start() +* 功能说明: 启动指定WDT,开始倒计时 +* 输 入: WDT_TypeDef * WDTx 指定要被设置的看门狗,有效值包括WDT +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void WDT_Start(WDT_TypeDef * WDTx) { @@ -66,11 +66,11 @@ void WDT_Start(WDT_TypeDef * WDTx) } /****************************************************************************************************************************************** -* : WDT_Stop() -* ˵: رָWDTֹͣʱ -* : WDT_TypeDef * WDTx ָҪõĿŹЧֵWDT -* : -* ע: +* 函数名称: WDT_Stop() +* 功能说明: 关闭指定WDT,停止倒计时 +* 输 入: WDT_TypeDef * WDTx 指定要被设置的看门狗,有效值包括WDT +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void WDT_Stop(WDT_TypeDef * WDTx) { @@ -78,11 +78,11 @@ void WDT_Stop(WDT_TypeDef * WDTx) } /****************************************************************************************************************************************** -* : WDT_Feed() -* ˵: ι´װֵʼʱ -* : WDT_TypeDef * WDTx ָҪõĿŹЧֵWDT -* : -* ע: +* 函数名称: WDT_Feed() +* 功能说明: 喂狗,重新从装载值开始倒计时 +* 输 入: WDT_TypeDef * WDTx 指定要被设置的看门狗,有效值包括WDT +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void WDT_Feed(WDT_TypeDef * WDTx) { @@ -90,11 +90,11 @@ void WDT_Feed(WDT_TypeDef * WDTx) } /****************************************************************************************************************************************** -* : WDT_GetValue() -* ˵: ȡָŹʱĵǰʱֵ -* : WDT_TypeDef * WDTx ָҪõĿŹЧֵWDT -* : int32_t Źǰֵ -* ע: +* 函数名称: WDT_GetValue() +* 功能说明: 获取指定看门狗定时器的当前倒计时值 +* 输 入: WDT_TypeDef * WDTx 指定要被设置的看门狗,有效值包括WDT +* 输 出: int32_t 看门狗当前计数值 +* 注意事项: 无 ******************************************************************************************************************************************/ int32_t WDT_GetValue(WDT_TypeDef * WDTx) { @@ -102,11 +102,11 @@ int32_t WDT_GetValue(WDT_TypeDef * WDTx) } /****************************************************************************************************************************************** -* : WDT_INTClr() -* ˵: жϱ־ -* : WDT_TypeDef * WDTx ָҪõĿŹЧֵWDT -* : -* ע: +* 函数名称: WDT_INTClr() +* 功能说明: 中断标志清除 +* 输 入: WDT_TypeDef * WDTx 指定要被设置的看门狗,有效值包括WDT +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void WDT_INTClr(WDT_TypeDef * WDTx) { @@ -114,11 +114,11 @@ void WDT_INTClr(WDT_TypeDef * WDTx) } /****************************************************************************************************************************************** -* : WDT_INTStat() -* ˵: ж״̬ѯ -* : WDT_TypeDef * WDTx ָҪõĿŹЧֵWDT -* : int32_t 1 ж 0 δж -* ע: +* 函数名称: WDT_INTStat() +* 功能说明: 中断状态查询 +* 输 入: WDT_TypeDef * WDTx 指定要被设置的看门狗,有效值包括WDT +* 输 出: int32_t 1 发生中断溢出 0 未发生中断溢出 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t WDT_INTStat(WDT_TypeDef * WDTx) { diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.h index 1d056ba296..a02a60ba87 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.h @@ -4,16 +4,16 @@ #define WDT_MODE_RESET 0 #define WDT_MODE_INTERRUPT 1 -void WDT_Init(WDT_TypeDef * WDTx, uint32_t peroid, uint32_t mode); //WDTŹʼ -void WDT_Start(WDT_TypeDef * WDTx); //ָWDTʼʱ -void WDT_Stop(WDT_TypeDef * WDTx); //رָWDTֹͣʱ +void WDT_Init(WDT_TypeDef * WDTx, uint32_t peroid, uint32_t mode); //WDT看门狗初始化 +void WDT_Start(WDT_TypeDef * WDTx); //启动指定WDT,开始倒计时 +void WDT_Stop(WDT_TypeDef * WDTx); //关闭指定WDT,停止倒计时 -void WDT_Feed(WDT_TypeDef * WDTx); //ι´װֵʼʱ +void WDT_Feed(WDT_TypeDef * WDTx); //喂狗,重新从装载值开始倒计时 -int32_t WDT_GetValue(WDT_TypeDef * WDTx); //ȡָŹʱĵǰʱֵ +int32_t WDT_GetValue(WDT_TypeDef * WDTx); //获取指定看门狗定时器的当前倒计时值 -void WDT_INTClr(WDT_TypeDef * WDTx); //жϱ־ -uint32_t WDT_INTStat(WDT_TypeDef * WDTx); //ж״̬ѯ +void WDT_INTClr(WDT_TypeDef * WDTx); //中断标志清除 +uint32_t WDT_INTStat(WDT_TypeDef * WDTx); //中断状态查询 #endif //__SWM320_WDT_H__ From c00300d5f44d0feb7d1807c68600b4819146d467 Mon Sep 17 00:00:00 2001 From: yanmowudi Date: Thu, 6 May 2021 10:24:00 +0800 Subject: [PATCH 020/255] format utf-8 --- .../libraries/CMSIS/DeviceSupport/SWM320.h | 652 +++++++++--------- .../startup/arm/startup_SWM320.s | 12 +- .../CMSIS/DeviceSupport/system_SWM320.c | 70 +- 3 files changed, 367 insertions(+), 367 deletions(-) diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h b/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h index 4ac927b7b9..423290614f 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h @@ -123,9 +123,9 @@ typedef struct { uint32_t RESERVED0[6]; - __IO uint32_t RTCBKP_ISO; //[0] 1 RTCݵԴڸ״̬ 0 RTCݵԴɷ + __IO uint32_t RTCBKP_ISO; //[0] 1 RTC备份电源域处于隔离状态 0 RTC备份电源域可访问 - __IO uint32_t RTCWKEN; //[0] 1 ʹRTCѹ + __IO uint32_t RTCWKEN; //[0] 1 使能RTC唤醒功能 uint32_t RESERVED[52+64]; @@ -135,7 +135,7 @@ typedef struct { uint32_t RESERVED2[1+4]; - __IO uint32_t PAWKSR; //Port A Wakeup Status Registerд1 + __IO uint32_t PAWKSR; //Port A Wakeup Status Register,写1清零 __IO uint32_t PBWKSR; __IO uint32_t PCWKSR; @@ -146,12 +146,12 @@ typedef struct { uint32_t RESERVED4[61+64]; - __IO uint32_t BKP[3]; //ݱݼĴ + __IO uint32_t BKP[3]; //数据备份寄存器 //RTC Power Domain: 0x4001E000 uint32_t RESERVED5[(0x4001E000-0x40000508)/4-1]; - __IO uint32_t RTCBKP[8]; //RTCԴݱݼĴ + __IO uint32_t RTCBKP[8]; //RTC电源域数据备份寄存器 __IO uint32_t LRCCR; //Low speed RC Control Register __IO uint32_t LRCTRIM0; //Low speed RC Trim @@ -173,7 +173,7 @@ typedef struct { __IO uint32_t PLLCR; __IO uint32_t PLLDIV; __IO uint32_t PLLSET; - __IO uint32_t PLLLOCK; //[0] 1 PLL + __IO uint32_t PLLLOCK; //[0] 1 PLL已锁定 __IO uint32_t BODIE; __IO uint32_t BODIF; @@ -186,16 +186,16 @@ typedef struct { #define SYS_CLKSEL_LFCK_Msk (0x01 << SYS_CLKSEL_LFCK_Pos) #define SYS_CLKSEL_HFCK_Pos 1 //High Frequency Clock Source 0 HRC 1 XTAL #define SYS_CLKSEL_HFCK_Msk (0x01 << SYS_CLKSEL_HFCK_Pos) -#define SYS_CLKSEL_SYS_Pos 2 //ϵͳʱѡ 0 LFCK 1 HFCK +#define SYS_CLKSEL_SYS_Pos 2 //系统时钟选择 0 LFCK 1 HFCK #define SYS_CLKSEL_SYS_Msk (0x01 << SYS_CLKSEL_SYS_Pos) -#define SYS_CLKDIV_SYS_Pos 0 //ϵͳʱӷƵ 0 1Ƶ 1 2Ƶ +#define SYS_CLKDIV_SYS_Pos 0 //系统时钟分频 0 1分频 1 2分频 #define SYS_CLKDIV_SYS_Msk (0x01 << SYS_CLKDIV_SYS_Pos) -#define SYS_CLKDIV_PWM_Pos 1 //PWM ʱӷƵ 0 1Ƶ 1 8Ƶ +#define SYS_CLKDIV_PWM_Pos 1 //PWM 时钟分频 0 1分频 1 8分频 #define SYS_CLKDIV_PWM_Msk (0x01 << SYS_CLKDIV_PWM_Pos) -#define SYS_CLKDIV_SDRAM_Pos 2 //SDRAMʱӷƵ 0 1Ƶ 1 2Ƶ 2 4Ƶ +#define SYS_CLKDIV_SDRAM_Pos 2 //SDRAM时钟分频 0 1分频 1 2分频 2 4分频 #define SYS_CLKDIV_SDRAM_Msk (0x03 << SYS_CLKDIV_SDRAM_Pos) -#define SYS_CLKDIV_SDIO_Pos 4 //SDIOʱӷƵ 0 1Ƶ 1 2Ƶ 2 4Ƶ 3 8Ƶ +#define SYS_CLKDIV_SDIO_Pos 4 //SDIO时钟分频 0 1分频 1 2分频 2 4分频 3 8分频 #define SYS_CLKDIV_SDIO_Msk (0x03 << SYS_CLKDIV_SDIO_Pos) #define SYS_CLKEN_GPIOA_Pos 0 @@ -240,7 +240,7 @@ typedef struct { #define SYS_CLKEN_LCD_Msk (0x01 << SYS_CLKEN_LCD_Pos) #define SYS_CLKEN_GPIOP_Pos 21 #define SYS_CLKEN_GPIOP_Msk (0x01 << SYS_CLKEN_GPIOP_Pos) -#define SYS_CLKEN_ANAC_Pos 22 //ģƵԪʱʹ +#define SYS_CLKEN_ANAC_Pos 22 //模拟控制单元时钟使能 #define SYS_CLKEN_ANAC_Msk (0x01 << SYS_CLKEN_ANAC_Pos) #define SYS_CLKEN_CRC_Pos 23 #define SYS_CLKEN_CRC_Msk (0x01 << SYS_CLKEN_CRC_Pos) @@ -258,59 +258,59 @@ typedef struct { #define SYS_CLKEN_SDIO_Msk (0x01 << SYS_CLKEN_SDIO_Pos) #define SYS_CLKEN_ADC1_Pos 30 #define SYS_CLKEN_ADC1_Msk (0x01 << SYS_CLKEN_ADC1_Pos) -#define SYS_CLKEN_ALIVE_Pos 31 //CHIPALIVEԴϵͳʱʹ +#define SYS_CLKEN_ALIVE_Pos 31 //CHIPALIVE电源域系统时钟使能 #define SYS_CLKEN_ALIVE_Msk (0x01 << SYS_CLKEN_ALIVE_Pos) -#define SYS_SLEEP_SLEEP_Pos 0 //λ1ϵͳSLEEPģʽ +#define SYS_SLEEP_SLEEP_Pos 0 //将该位置1后,系统将进入SLEEP模式 #define SYS_SLEEP_SLEEP_Msk (0x01 << SYS_SLEEP_SLEEP_Pos) -#define SYS_SLEEP_DEEP_Pos 1 //λ1ϵͳSTOP SLEEPģʽ +#define SYS_SLEEP_DEEP_Pos 1 //将该位置1后,系统将进入STOP SLEEP模式 #define SYS_SLEEP_DEEP_Msk (0x01 << SYS_SLEEP_DEEP_Pos) -#define SYS_RSTCR_SYS_Pos 0 //д1ϵͳλӲԶ +#define SYS_RSTCR_SYS_Pos 0 //写1进行系统复位,硬件自动清零 #define SYS_RSTCR_SYS_Msk (0x01 << SYS_RSTCR_SYS_Pos) -#define SYS_RSTCR_FLASH_Pos 1 //д1FLASHһθλӲԶ +#define SYS_RSTCR_FLASH_Pos 1 //写1对FLASH控制器进行一次复位,硬件自动清零 #define SYS_RSTCR_FLASH_Msk (0x01 << SYS_RSTCR_FLASH_Pos) -#define SYS_RSTCR_PWM_Pos 2 //д1PWMһθλӲԶ +#define SYS_RSTCR_PWM_Pos 2 //写1对PWM进行一次复位,硬件自动清零 #define SYS_RSTCR_PWM_Msk (0x01 << SYS_RSTCR_PWM_Pos) -#define SYS_RSTCR_CPU_Pos 3 //д1CPUһθλӲԶ +#define SYS_RSTCR_CPU_Pos 3 //写1对CPU进行一次复位,硬件自动清零 #define SYS_RSTCR_CPU_Msk (0x01 << SYS_RSTCR_CPU_Pos) -#define SYS_RSTCR_DMA_Pos 4 //д1DMAһθλӲԶ +#define SYS_RSTCR_DMA_Pos 4 //写1对DMA进行一次复位,硬件自动清零 #define SYS_RSTCR_DMA_Msk (0x01 << SYS_RSTCR_DMA_Pos) -#define SYS_RSTCR_NORFLASH_Pos 5 //д1NOR FlashһθλӲԶ +#define SYS_RSTCR_NORFLASH_Pos 5 //写1对NOR Flash控制器进行一次复位,硬件自动清零 #define SYS_RSTCR_NORFLASH_Msk (0x01 << SYS_RSTCR_NORFLASH_Pos) -#define SYS_RSTCR_SRAM_Pos 6 //д1SRAMһθλӲԶ +#define SYS_RSTCR_SRAM_Pos 6 //写1对SRAM控制器进行一次复位,硬件自动清零 #define SYS_RSTCR_SRAM_Msk (0x01 << SYS_RSTCR_SRAM_Pos) -#define SYS_RSTCR_SDRAM_Pos 7 //д1SDRAMһθλӲԶ +#define SYS_RSTCR_SDRAM_Pos 7 //写1对SDRAM控制器进行一次复位,硬件自动清零 #define SYS_RSTCR_SDRAM_Msk (0x01 << SYS_RSTCR_SDRAM_Pos) -#define SYS_RSTCR_SDIO_Pos 8 //д1SDIOһθλӲԶ +#define SYS_RSTCR_SDIO_Pos 8 //写1对SDIO进行一次复位,硬件自动清零 #define SYS_RSTCR_SDIO_Msk (0x01 << SYS_RSTCR_SDIO_Pos) -#define SYS_RSTCR_LCD_Pos 9 //д1LCDһθλӲԶ +#define SYS_RSTCR_LCD_Pos 9 //写1对LCD进行一次复位,硬件自动清零 #define SYS_RSTCR_LCD_Msk (0x01 << SYS_RSTCR_LCD_Pos) -#define SYS_RSTCR_CAN_Pos 10 //д1CANһθλӲԶ +#define SYS_RSTCR_CAN_Pos 10 //写1对CAN进行一次复位,硬件自动清零 #define SYS_RSTCR_CAN_Msk (0x01 << SYS_RSTCR_CAN_Pos) -#define SYS_RSTSR_POR_Pos 0 //1 ֹPORλд1 +#define SYS_RSTSR_POR_Pos 0 //1 出现过POR复位,写1清零 #define SYS_RSTSR_POR_Msk (0x01 << SYS_RSTSR_POR_Pos) -#define SYS_RSTSR_BOD_Pos 1 //1 ֹBODλд1 +#define SYS_RSTSR_BOD_Pos 1 //1 出现过BOD复位,写1清零 #define SYS_RSTSR_BOD_Msk (0x01 << SYS_RSTSR_BOD_Pos) -#define SYS_RSTSR_PIN_Pos 2 //1 ֹⲿŸλд1 +#define SYS_RSTSR_PIN_Pos 2 //1 出现过外部引脚复位,写1清零 #define SYS_RSTSR_PIN_Msk (0x01 << SYS_RSTSR_PIN_Pos) -#define SYS_RSTSR_WDT_Pos 3 //1 ֹWDTλд1 +#define SYS_RSTSR_WDT_Pos 3 //1 出现过WDT复位,写1清零 #define SYS_RSTSR_WDT_Msk (0x01 << SYS_RSTSR_WDT_Pos) -#define SYS_RSTSR_SWRST_Pos 4 //Software Reset, 1 ֹλд1 +#define SYS_RSTSR_SWRST_Pos 4 //Software Reset, 1 出现过软件复位,写1清零 #define SYS_RSTSR_SWRST_Msk (0x01 << SYS_RSTSR_SWRST_Pos) #define SYS_LRCCR_OFF_Pos 0 //Low Speed RC Off #define SYS_LRCCR_OFF_Msk (0x01 << SYS_LRCCR_OFF_Pos) -#define SYS_LRCTRIM0_R_Pos 0 //LRCֵλ +#define SYS_LRCTRIM0_R_Pos 0 //LRC粗调控制位 #define SYS_LRCTRIM0_R_Msk (0x7FFF << SYS_LRCTRIM0_R_Pos) -#define SYS_LRCTRIM0_M_Pos 15 //LRCеλ +#define SYS_LRCTRIM0_M_Pos 15 //LRC中调控制位 #define SYS_LRCTRIM0_M_Msk (0x3F << SYS_LRCTRIM2_M_Pos) -#define SYS_LRCTRIM0_F_Pos 21 //LRCϸλ +#define SYS_LRCTRIM0_F_Pos 21 //LRC细调控制位 #define SYS_LRCTRIM0_F_Msk (0x7FF << SYS_LRCTRIM0_F_Pos) -#define SYS_LRCTRIM1_U_Pos 0 //LRC Uλ +#define SYS_LRCTRIM1_U_Pos 0 //LRC U调控制位 #define SYS_LRCTRIM1_U_Msk (0x7FFF << SYS_LRCTRIM1_U_Pos) @@ -322,24 +322,24 @@ typedef struct { #define SYS_XTALCR_EN_Pos 0 #define SYS_XTALCR_EN_Msk (0x01 << SYS_XTALCR_EN_Pos) -#define SYS_PLLCR_OUTEN_Pos 0 //ֻLOCK +#define SYS_PLLCR_OUTEN_Pos 0 //只能LOCK后设置 #define SYS_PLLCR_OUTEN_Msk (0x01 << SYS_PLLCR_OUTEN_Pos) #define SYS_PLLCR_INSEL_Pos 1 //0 XTAL 1 HRC #define SYS_PLLCR_INSEL_Msk (0x01 << SYS_PLLCR_INSEL_Pos) #define SYS_PLLCR_OFF_Pos 2 #define SYS_PLLCR_OFF_Msk (0x01 << SYS_PLLCR_OFF_Pos) -#define SYS_PLLDIV_FBDIV_Pos 0 //PLL FeedBackƵĴ - //VCOƵ = PLLʱ / INDIV * 4 * FBDIV - //PLLƵ = PLLʱ / INDIV * 4 * FBDIV / OUTDIV = VCOƵ / OUTDIV +#define SYS_PLLDIV_FBDIV_Pos 0 //PLL FeedBack分频寄存器 + //VCO输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV + //PLL输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV / OUTDIV = VCO输出频率 / OUTDIV #define SYS_PLLDIV_FBDIV_Msk (0x1FF << SYS_PLLDIV_FBDIV_Pos) -#define SYS_PLLDIV_ADDIV_Pos 9 //ADCʱӻVCOƵʱӣADDIVƵΪADCתʱ +#define SYS_PLLDIV_ADDIV_Pos 9 //ADC时钟基(即VCO输出分频后的时钟)经ADDIV分频后作为ADC的转换时钟 #define SYS_PLLDIV_ADDIV_Msk (0x1F << SYS_PLLDIV_ADDIV_Pos) -#define SYS_PLLDIV_ADVCO_Pos 14 //0 VCO16ƵΪADCʱӻ 1 VCO32ƵΪADCʱӻ 2 VCO64ƵΪADCʱӻ +#define SYS_PLLDIV_ADVCO_Pos 14 //0 VCO输出16分频作为ADC时钟基 1 VCO输出经过32分频作为ADC时钟基 2 VCO输出经过64分频作为ADC时钟基 #define SYS_PLLDIV_ADVCO_Msk (0x03 << SYS_PLLDIV_ADVCO_Pos) -#define SYS_PLLDIV_INDIV_Pos 16 //PLL ԴʱӷƵ +#define SYS_PLLDIV_INDIV_Pos 16 //PLL 输入源时钟分频 #define SYS_PLLDIV_INDIV_Msk (0x1F << SYS_PLLDIV_INDIV_Pos) -#define SYS_PLLDIV_OUTDIV_Pos 24 //PLL Ƶ0 8Ƶ 1 4Ƶ 0 2Ƶ +#define SYS_PLLDIV_OUTDIV_Pos 24 //PLL 输出分频,0 8分频 1 4分频 0 2分频 #define SYS_PLLDIV_OUTDIV_Msk (0x03 << SYS_PLLDIV_OUTDIV_Pos) #define SYS_PLLSET_LPFBW_Pos 0 //PLL Low Pass Filter Bandwidth @@ -353,23 +353,23 @@ typedef struct { #define SYS_PLLSET_CHPADJM_Pos 11 //PLL charge pump MSB current Adjustment #define SYS_PLLSET_CHPADJM_Msk (0x03 << SYS_PLLSET_CHPADJM_Pos) -#define SYS_BODIE_2V2_Pos 1 //BOD 2.2Vȼжʹ +#define SYS_BODIE_2V2_Pos 1 //BOD 2.2V等级触发中断使能 #define SYS_BODIE_2V2_Msk (0x01 << SYS_BODIE_2V2_Pos) -#define SYS_BODIF_2V2_Pos 1 //BOD 2.2Vȼж״̬д1 +#define SYS_BODIF_2V2_Pos 1 //BOD 2.2V等级触发中断状态,写1清零 #define SYS_BODIF_2V2_Msk (0x01 << SYS_BODIF_2V2_Pos) -#define SYS_ADC1IN7_SEL_Pos 0 //ADC1ģģͨ71 ¶ȴ 2 صѹ 3 RTCԴBG 4 ԴBG 5 PDM33 +#define SYS_ADC1IN7_SEL_Pos 0 //ADC1模块模拟通道7,1 温度传感器 2 电池电压 3 RTC电源域BG 4 主电源域BG 5 PDM33 #define SYS_ADC1IN7_SEL_Msk (0x0F << SYS_ADC1IN7_SEL_Pos) -#define SYS_ADC1IN7_IOON_Pos 4 //ADC1ģģͨ7IO +#define SYS_ADC1IN7_IOON_Pos 4 //ADC1模块模拟通道7所用IO开关 #define SYS_ADC1IN7_IOON_Msk (0x01 << SYS_ADC1IN7_IOON_Pos) typedef struct { - __IO uint32_t PORTA_SEL; //PORTA_SEL[2n+2:2n]ӦֵPORTA.PINnóGPIOģ⡢ֵȹ - //ֵΪPORTA_PINn_FUNMUXʱPORTA.PINnſͨPORTA_MUXĴӵ + __IO uint32_t PORTA_SEL; //给PORTA_SEL[2n+2:2n]赋相应的值,将PORTA.PINn引脚配置成GPIO、模拟、数字等功能 + //当赋值为PORTA_PINn_FUNMUX时,PORTA.PINn引脚可通过PORTA_MUX寄存器连接到各种数字外设 __IO uint32_t PORTB_SEL; __IO uint32_t PORTC_SEL; @@ -438,7 +438,7 @@ typedef struct { uint32_t RESERVED9[28]; - __IO uint32_t PORTA_PULLU; //ʹ + __IO uint32_t PORTA_PULLU; //上拉使能 uint32_t RESERVED10[3]; @@ -454,7 +454,7 @@ typedef struct { uint32_t RESERVED13[51]; - __IO uint32_t PORTB_PULLD; //ʹ + __IO uint32_t PORTB_PULLD; //下拉使能 uint32_t RESERVED14[3]; @@ -466,7 +466,7 @@ typedef struct { uint32_t RESERVED16[135]; - __IO uint32_t PORTM_DRIVS; //ǿ + __IO uint32_t PORTM_DRIVS; //驱动强度 uint32_t RESERVED17[3]; @@ -478,7 +478,7 @@ typedef struct { uint32_t RESERVED19[39]; - __IO uint32_t PORTA_INEN; //ʹ + __IO uint32_t PORTA_INEN; //输入使能 uint32_t RESERVED20[3]; @@ -1172,21 +1172,21 @@ typedef struct { #define PIN23 23 #define PIN24 24 - __IO uint32_t DIR; //0 1 + __IO uint32_t DIR; //0 输入 1 输出 - __IO uint32_t INTLVLTRG; //Interrupt Level Trigger 1 ƽж 0 شж + __IO uint32_t INTLVLTRG; //Interrupt Level Trigger 1 电平触发中断 0 边沿触发中断 - __IO uint32_t INTBE; //Both EdgeINTLVLTRGΪشжʱλ1ʾغ½ضжϣ0ʱINTRISEENѡ + __IO uint32_t INTBE; //Both Edge,当INTLVLTRG设为边沿触发中断时,此位置1表示上升沿和下降沿都触发中断,置0时触发边沿由INTRISEEN选择 - __IO uint32_t INTRISEEN; //Interrupt Rise Edge Enable 1 /ߵƽж 0 ½/͵ƽж + __IO uint32_t INTRISEEN; //Interrupt Rise Edge Enable 1 上升沿/高电平触发中断 0 下降沿/低电平触发中断 - __IO uint32_t INTEN; //1 жʹ 0 жϽֹ + __IO uint32_t INTEN; //1 中断使能 0 中断禁止 - __IO uint32_t INTRAWSTAT; //жϼⵥԪǷ⵽˴жϵ 1 ⵽жϴ 0 ûм⵽жϴ + __IO uint32_t INTRAWSTAT; //中断检测单元是否检测到了触发中断的条件 1 检测到了中断触发条件 0 没有检测到中断触发条件 __IO uint32_t INTSTAT; //INTSTAT.PIN0 = INTRAWSTAT.PIN0 & INTEN.PIN0 - __IO uint32_t INTCLR; //д1жϱ־ֻԱشж + __IO uint32_t INTCLR; //写1清除中断标志,只对边沿触发中断有用 } GPIO_TypeDef; @@ -1635,26 +1635,26 @@ typedef struct { typedef struct { - __IO uint32_t LDVAL; //ʱֵʹܺʱӴֵʼµݼ + __IO uint32_t LDVAL; //定时器加载值,使能后定时器从此数值开始向下递减计数 - __I uint32_t CVAL; //ʱǰֵLDVAL-CVAL ɼʱʱ + __I uint32_t CVAL; //定时器当前值,LDVAL-CVAL 可计算出计时时长 __IO uint32_t CTRL; } TIMR_TypeDef; -#define TIMR_CTRL_EN_Pos 0 //λ1TIMRLDVALʼµݼ +#define TIMR_CTRL_EN_Pos 0 //此位赋1导致TIMR从LDVAL开始向下递减计数 #define TIMR_CTRL_EN_Msk (0x01 << TIMR_CTRL_EN_Pos) -#define TIMR_CTRL_CLKSRC_Pos 1 //ʱԴ0 ڲϵͳʱ 1 ⲿ +#define TIMR_CTRL_CLKSRC_Pos 1 //时钟源:0 内部系统时钟 1 外部引脚脉冲计数 #define TIMR_CTRL_CLKSRC_Msk (0x01 << TIMR_CTRL_CLKSRC_Pos) -#define TIMR_CTRL_CASCADE_Pos 2 //1 TIMRxļʱΪTIMRx-1ź +#define TIMR_CTRL_CASCADE_Pos 2 //1 TIMRx的计数时钟为TIMRx-1的溢出信号 #define TIMR_CTRL_CASCADE_Msk (0x01 << TIMR_CTRL_CASCADE_Pos) typedef struct { - __IO uint32_t PCTRL; //Pulse ControlģƼĴ + __IO uint32_t PCTRL; //Pulse Control,脉宽测量模块控制寄存器 - __I uint32_t PCVAL; //ʱǰֵ + __I uint32_t PCVAL; //脉宽测量定时器当前值 uint32_t RESERVED[2]; @@ -1666,11 +1666,11 @@ typedef struct { } TIMRG_TypeDef; -#define TIMRG_PCTRL_EN_Pos 0 //ʼ32λ0ʼϼ +#define TIMRG_PCTRL_EN_Pos 0 //开始测量脉宽,脉宽内32位计数器从0开始向上计数 #define TIMRG_PCTRL_EN_Msk (0x01 << TIMRG_PCTRL_EN_Pos) -#define TIMRG_PCTRL_HIGH_Pos 1 //0 ͵ƽ 1 ߵƽ +#define TIMRG_PCTRL_HIGH_Pos 1 //0 测量低电平长度 1 测量高电平长度 #define TIMRG_PCTRL_HIGH_Msk (0x01 << TIMRG_PCTRL_HIGH_Pos) -#define TIMRG_PCTRL_CLKSRC_Pos 2 //ʱԴ0 ڲϵͳʱ 1 ģһپ +#define TIMRG_PCTRL_CLKSRC_Pos 2 //时钟源:0 内部系统时钟 1 脉宽测量模块变成一个计数器,不再具有脉宽测量功能 #define TIMRG_PCTRL_CLKSRC_Msk (0x01 << TIMRG_PCTRL_CLKSRC_Pos) #define TIMRG_IE_TIMR0_Pos 0 @@ -1688,7 +1688,7 @@ typedef struct { #define TIMRG_IE_PULSE_Pos 16 #define TIMRG_IE_PULSE_Msk (0x01 << TIMRG_IE_PULSE_Pos) -#define TIMRG_IF_TIMR0_Pos 0 //д1 +#define TIMRG_IF_TIMR0_Pos 0 //写1清零 #define TIMRG_IF_TIMR0_Msk (0x01 << TIMRG_IF_TIMR0_Pos) #define TIMRG_IF_TIMR1_Pos 1 #define TIMRG_IF_TIMR1_Msk (0x01 << TIMRG_IF_TIMR1_Pos) @@ -1703,7 +1703,7 @@ typedef struct { #define TIMRG_IF_PULSE_Pos 16 #define TIMRG_IF_PULSE_Msk (0x01 << TIMRG_IF_PULSE_Pos) -#define TIMRG_HALT_TIMR0_Pos 0 //1 ͣ +#define TIMRG_HALT_TIMR0_Pos 0 //1 暂停计数 #define TIMRG_HALT_TIMR0_Msk (0x01 << TIMRG_HALT_TIMR0_Pos) #define TIMRG_HALT_TIMR1_Pos 1 #define TIMRG_HALT_TIMR1_Msk (0x01 << TIMRG_HALT_TIMR1_Pos) @@ -1740,114 +1740,114 @@ typedef struct { #define UART_DATA_DATA_Pos 0 #define UART_DATA_DATA_Msk (0x1FF << UART_DATA_DATA_Pos) -#define UART_DATA_VALID_Pos 9 //DATAֶЧĽʱλӲ1ȡݺԶ +#define UART_DATA_VALID_Pos 9 //当DATA字段有有效的接收数据时,该位硬件置1,读取数据后自动清零 #define UART_DATA_VALID_Msk (0x01 << UART_DATA_VALID_Pos) #define UART_DATA_PAERR_Pos 10 //Parity Error #define UART_DATA_PAERR_Msk (0x01 << UART_DATA_PAERR_Pos) -#define UART_CTRL_TXIDLE_Pos 0 //TX IDLE: 0 ڷ 1 ״̬ûݷ +#define UART_CTRL_TXIDLE_Pos 0 //TX IDLE: 0 正在发送数据 1 空闲状态,没有数据发送 #define UART_CTRL_TXIDLE_Msk (0x01 << UART_CTRL_TXIDLE_Pos) #define UART_CTRL_TXFF_Pos 1 //TX FIFO Full #define UART_CTRL_TXFF_Msk (0x01 << UART_CTRL_TXFF_Pos) -#define UART_CTRL_TXIE_Pos 2 //TX жʹ: 1 TX FF 趨ʱж +#define UART_CTRL_TXIE_Pos 2 //TX 中断使能: 1 TX FF 中数据少于设定个数时产生中断 #define UART_CTRL_TXIE_Msk (0x01 << UART_CTRL_TXIE_Pos) #define UART_CTRL_RXNE_Pos 3 //RX FIFO Not Empty #define UART_CTRL_RXNE_Msk (0x01 << UART_CTRL_RXNE_Pos) -#define UART_CTRL_RXIE_Pos 4 //RX жʹ: 1 RX FF ݴﵽ趨ʱж +#define UART_CTRL_RXIE_Pos 4 //RX 中断使能: 1 RX FF 中数据达到设定个数时产生中断 #define UART_CTRL_RXIE_Msk (0x01 << UART_CTRL_RXIE_Pos) -#define UART_CTRL_RXOV_Pos 5 //RX FIFO Overflowд1 +#define UART_CTRL_RXOV_Pos 5 //RX FIFO Overflow,写1清零 #define UART_CTRL_RXOV_Msk (0x01 << UART_CTRL_RXOV_Pos) -#define UART_CTRL_TXDOIE_Pos 6 //TX Done жʹܣFIFOҷͷλĴѽһλͳȥ +#define UART_CTRL_TXDOIE_Pos 6 //TX Done 中断使能,发送FIFO空且发送发送移位寄存器已将最后一位发送出去 #define UART_CTRL_TXDOIE_Msk (0x01 << UART_CTRL_TXDOIE_Pos) #define UART_CTRL_EN_Pos 9 #define UART_CTRL_EN_Msk (0x01 << UART_CTRL_EN_Pos) #define UART_CTRL_LOOP_Pos 10 #define UART_CTRL_LOOP_Msk (0x01 << UART_CTRL_LOOP_Pos) -#define UART_CTRL_BAUDEN_Pos 13 //д1 +#define UART_CTRL_BAUDEN_Pos 13 //必须写1 #define UART_CTRL_BAUDEN_Msk (0x01 << UART_CTRL_BAUDEN_Pos) -#define UART_CTRL_TOIE_Pos 14 //TimeOut жʹܣյϸַ󣬳 TOTIME/BAUDRAUD ûнյµ +#define UART_CTRL_TOIE_Pos 14 //TimeOut 中断使能,接收到上个字符后,超过 TOTIME/BAUDRAUD 秒没有接收到新的数据 #define UART_CTRL_TOIE_Msk (0x01 << UART_CTRL_TOIE_Pos) -#define UART_CTRL_BRKDET_Pos 15 //LIN Break Detect⵽LIN BreakRXϼ⵽11λ͵ƽ +#define UART_CTRL_BRKDET_Pos 15 //LIN Break Detect,检测到LIN Break,即RX线上检测到连续11位低电平 #define UART_CTRL_BRKDET_Msk (0x01 << UART_CTRL_BRKDET_Pos) -#define UART_CTRL_BRKIE_Pos 16 //LIN Break Detect жʹ +#define UART_CTRL_BRKIE_Pos 16 //LIN Break Detect 中断使能 #define UART_CTRL_BRKIE_Msk (0x01 << UART_CTRL_BRKIE_Pos) -#define UART_CTRL_GENBRK_Pos 17 //Generate LIN BreakLIN Break +#define UART_CTRL_GENBRK_Pos 17 //Generate LIN Break,发送LIN Break #define UART_CTRL_GENBRK_Msk (0x01 << UART_CTRL_GENBRK_Pos) -#define UART_CTRL_DATA9b_Pos 18 //1 9λλ 0 8λλ +#define UART_CTRL_DATA9b_Pos 18 //1 9位数据位 0 8位数据位 #define UART_CTRL_DATA9b_Msk (0x01 << UART_CTRL_DATA9b_Pos) -#define UART_CTRL_PARITY_Pos 19 //000 У 001 У 011 żУ 101 ̶Ϊ1 111 ̶Ϊ0 +#define UART_CTRL_PARITY_Pos 19 //000 无校验 001 奇校验 011 偶校验 101 固定为1 111 固定为0 #define UART_CTRL_PARITY_Msk (0x07 << UART_CTRL_PARITY_Pos) -#define UART_CTRL_STOP2b_Pos 22 //1 2λֹͣλ 0 1λֹͣλ +#define UART_CTRL_STOP2b_Pos 22 //1 2位停止位 0 1位停止位 #define UART_CTRL_STOP2b_Msk (0x03 << UART_CTRL_STOP2b_Pos) -#define UART_CTRL_TOTIME_Pos 24 //TimeOut ʱ = TOTIME/(BAUDRAUD/10) +#define UART_CTRL_TOTIME_Pos 24 //TimeOut 时长 = TOTIME/(BAUDRAUD/10) 秒 #define UART_CTRL_TOTIME_Msk (0xFFu<< UART_CTRL_TOTIME_Pos) -#define UART_BAUD_BAUD_Pos 0 //ڲ = SYS_Freq/16/BAUD - 1 +#define UART_BAUD_BAUD_Pos 0 //串口波特率 = SYS_Freq/16/BAUD - 1 #define UART_BAUD_BAUD_Msk (0x3FFF << UART_BAUD_BAUD_Pos) -#define UART_BAUD_TXD_Pos 14 //ͨλֱӶȡTXDϵĵƽ +#define UART_BAUD_TXD_Pos 14 //通过此位可直接读取串口TXD引脚上的电平 #define UART_BAUD_TXD_Msk (0x01 << UART_BAUD_TXD_Pos) -#define UART_BAUD_RXD_Pos 15 //ͨλֱӶȡRXDϵĵƽ +#define UART_BAUD_RXD_Pos 15 //通过此位可直接读取串口RXD引脚上的电平 #define UART_BAUD_RXD_Msk (0x01 << UART_BAUD_RXD_Pos) -#define UART_BAUD_RXTOIF_Pos 16 //&ʱжϱ־ = RXIF | TOIF +#define UART_BAUD_RXTOIF_Pos 16 //接收&超时的中断标志 = RXIF | TOIF #define UART_BAUD_RXTOIF_Msk (0x01 << UART_BAUD_RXTOIF_Pos) -#define UART_BAUD_TXIF_Pos 17 //жϱ־ = TXTHRF & TXIE +#define UART_BAUD_TXIF_Pos 17 //发送中断标志 = TXTHRF & TXIE #define UART_BAUD_TXIF_Msk (0x01 << UART_BAUD_TXIF_Pos) -#define UART_BAUD_BRKIF_Pos 18 //LIN Break Detect жϱ־⵽LIN BreakʱBRKIE=1λӲλ +#define UART_BAUD_BRKIF_Pos 18 //LIN Break Detect 中断标志,检测到LIN Break时若BRKIE=1,此位由硬件置位 #define UART_BAUD_BRKIF_Msk (0x01 << UART_BAUD_BRKIF_Pos) -#define UART_BAUD_RXTHRF_Pos 19 //RX FIFO Threshold FlagRX FIFOݴﵽ趨RXLVL >= RXTHRʱӲ1 +#define UART_BAUD_RXTHRF_Pos 19 //RX FIFO Threshold Flag,RX FIFO中数据达到设定个数(RXLVL >= RXTHR)时硬件置1 #define UART_BAUD_RXTHRF_Msk (0x01 << UART_BAUD_RXTHRF_Pos) -#define UART_BAUD_TXTHRF_Pos 20 //TX FIFO Threshold FlagTX FIFO趨TXLVL <= TXTHRʱӲ1 +#define UART_BAUD_TXTHRF_Pos 20 //TX FIFO Threshold Flag,TX FIFO中数据少于设定个数(TXLVL <= TXTHR)时硬件置1 #define UART_BAUD_TXTHRF_Msk (0x01 << UART_BAUD_TXTHRF_Pos) -#define UART_BAUD_TOIF_Pos 21 //TimeOut жϱ־ TOTIME/BAUDRAUD ûнյµʱTOIE=1λӲλ +#define UART_BAUD_TOIF_Pos 21 //TimeOut 中断标志,超过 TOTIME/BAUDRAUD 秒没有接收到新的数据时若TOIE=1,此位由硬件置位 #define UART_BAUD_TOIF_Msk (0x01 << UART_BAUD_TOIF_Pos) -#define UART_BAUD_RXIF_Pos 22 //жϱ־ = RXTHRF & RXIE +#define UART_BAUD_RXIF_Pos 22 //接收中断标志 = RXTHRF & RXIE #define UART_BAUD_RXIF_Msk (0x01 << UART_BAUD_RXIF_Pos) -#define UART_BAUD_ABREN_Pos 23 //Auto Baudrate Enableд1ԶУ׼ɺԶ +#define UART_BAUD_ABREN_Pos 23 //Auto Baudrate Enable,写1启动自动波特率校准,完成后自动清零 #define UART_BAUD_ABREN_Msk (0x01 << UART_BAUD_ABREN_Pos) -#define UART_BAUD_ABRBIT_Pos 24 //Auto Baudrate Bitڼ㲨ʵļλ0 1λͨʼλ 㲨ʣҪͶ˷0xFF - // 1 2λͨʼλ1λλ㲨ʣҪͶ˷0xFE - // 1 4λͨʼλ3λλ㲨ʣҪͶ˷0xF8 - // 1 8λͨʼλ7λλ㲨ʣҪͶ˷0x80 +#define UART_BAUD_ABRBIT_Pos 24 //Auto Baudrate Bit,用于计算波特率的检测位长,0 1位,通过测起始位 脉宽计算波特率,要求发送端发送0xFF + // 1 2位,通过测起始位加1位数据位脉宽计算波特率,要求发送端发送0xFE + // 1 4位,通过测起始位加3位数据位脉宽计算波特率,要求发送端发送0xF8 + // 1 8位,通过测起始位加7位数据位脉宽计算波特率,要求发送端发送0x80 #define UART_BAUD_ABRBIT_Msk (0x03 << UART_BAUD_ABRBIT_Pos) -#define UART_BAUD_ABRERR_Pos 26 //Auto Baudrate Error0 ԶУ׼ɹ 1 ԶУ׼ʧ +#define UART_BAUD_ABRERR_Pos 26 //Auto Baudrate Error,0 自动波特率校准成功 1 自动波特率校准失败 #define UART_BAUD_ABRERR_Msk (0x01 << UART_BAUD_ABRERR_Pos) -#define UART_BAUD_TXDOIF_Pos 27 //TX Done жϱ־FIFOҷͷλĴѽһλͳȥ +#define UART_BAUD_TXDOIF_Pos 27 //TX Done 中断标志,发送FIFO空且发送发送移位寄存器已将最后一位发送出去 #define UART_BAUD_TXDOIF_Msk (0x01 << UART_BAUD_TXDOIF_Pos) -#define UART_FIFO_RXLVL_Pos 0 //RX FIFO LevelRX FIFO ַ +#define UART_FIFO_RXLVL_Pos 0 //RX FIFO Level,RX FIFO 中字符个数 #define UART_FIFO_RXLVL_Msk (0xFF << UART_FIFO_RXLVL_Pos) -#define UART_FIFO_TXLVL_Pos 8 //TX FIFO LevelTX FIFO ַ +#define UART_FIFO_TXLVL_Pos 8 //TX FIFO Level,TX FIFO 中字符个数 #define UART_FIFO_TXLVL_Msk (0xFF << UART_FIFO_TXLVL_Pos) -#define UART_FIFO_RXTHR_Pos 16 //RX FIFO ThresholdRXжϴޣжʹʱ RXLVL >= RXTHR RXж +#define UART_FIFO_RXTHR_Pos 16 //RX FIFO Threshold,RX中断触发门限,中断使能时 RXLVL >= RXTHR 触发RX中断 #define UART_FIFO_RXTHR_Msk (0xFF << UART_FIFO_RXTHR_Pos) -#define UART_FIFO_TXTHR_Pos 24 //TX FIFO ThresholdTXжϴޣжʹʱ TXLVL <= TXTHR TXж +#define UART_FIFO_TXTHR_Pos 24 //TX FIFO Threshold,TX中断触发门限,中断使能时 TXLVL <= TXTHR 触发TX中断 #define UART_FIFO_TXTHR_Msk (0xFFu<< UART_FIFO_TXTHR_Pos) -#define UART_LINCR_BRKDETIE_Pos 0 //⵽LIN Breakжʹ +#define UART_LINCR_BRKDETIE_Pos 0 //检测到LIN Break中断使能 #define UART_LINCR_BRKDETIE_Msk (0x01 << UART_LINCR_BRKDETIE_Pos) -#define UART_LINCR_BRKDETIF_Pos 1 //⵽LIN Breakж״̬ +#define UART_LINCR_BRKDETIF_Pos 1 //检测到LIN Break中断状态 #define UART_LINCR_BRKDETIF_Msk (0x01 << UART_LINCR_BRKDETIF_Pos) -#define UART_LINCR_GENBRKIE_Pos 2 //LIN Breakжʹ +#define UART_LINCR_GENBRKIE_Pos 2 //发送LIN Break完成中断使能 #define UART_LINCR_GENBRKIE_Msk (0x01 << UART_LINCR_GENBRKIE_Pos) -#define UART_LINCR_GENBRKIF_Pos 3 //LIN Breakж״̬ +#define UART_LINCR_GENBRKIF_Pos 3 //发送LIN Break完成中断状态 #define UART_LINCR_GENBRKIF_Msk (0x01 << UART_LINCR_GENBRKIF_Pos) -#define UART_LINCR_GENBRK_Pos 4 //LIN BreakԶ +#define UART_LINCR_GENBRK_Pos 4 //发送LIN Break,发送完成自动清零 #define UART_LINCR_GENBRK_Msk (0x01 << UART_LINCR_GENBRK_Pos) -#define UART_CTSCR_EN_Pos 0 //CTSʹ +#define UART_CTSCR_EN_Pos 0 //CTS流控使能 #define UART_CTSCR_EN_Msk (0x01 << UART_CTSCR_EN_Pos) -#define UART_CTSCR_POL_Pos 2 //CTSźżԣ0 ЧCTSΪͱʾԷ +#define UART_CTSCR_POL_Pos 2 //CTS信号极性,0 低有效,CTS输入为低表示可以发送数据 #define UART_CTSCR_POL_Msk (0x01 << UART_CTSCR_POL_Pos) -#define UART_CTSCR_STAT_Pos 7 //CTSźŵĵǰ״̬ +#define UART_CTSCR_STAT_Pos 7 //CTS信号的当前状态 #define UART_CTSCR_STAT_Msk (0x01 << UART_CTSCR_STAT_Pos) -#define UART_RTSCR_EN_Pos 1 //RTSʹ +#define UART_RTSCR_EN_Pos 1 //RTS流控使能 #define UART_RTSCR_EN_Msk (0x01 << UART_RTSCR_EN_Pos) -#define UART_RTSCR_POL_Pos 3 //RTSźż 0 ЧRTSΪͱʾԽ +#define UART_RTSCR_POL_Pos 3 //RTS信号极性 0 低有效,RTS输入为低表示可以接收数据 #define UART_RTSCR_POL_Msk (0x01 << UART_RTSCR_POL_Pos) -#define UART_RTSCR_THR_Pos 4 //RTSصĴֵ 0 1ֽ 1 2ֽ 2 4ֽ 3 6ֽ +#define UART_RTSCR_THR_Pos 4 //RTS流控的触发阈值 0 1字节 1 2字节 2 4字节 3 6字节 #define UART_RTSCR_THR_Msk (0x07 << UART_RTSCR_THR_Pos) -#define UART_RTSCR_STAT_Pos 8 //RTSźŵĵǰ״̬ +#define UART_RTSCR_STAT_Pos 8 //RTS信号的当前状态 #define UART_RTSCR_STAT_Msk (0x01 << UART_RTSCR_STAT_Pos) @@ -1866,46 +1866,46 @@ typedef struct { } SPI_TypeDef; -#define SPI_CTRL_CLKDIV_Pos 0 //Clock Divider, SPIʱ = SYS_Freq/pow(2, CLKDIV+2) +#define SPI_CTRL_CLKDIV_Pos 0 //Clock Divider, SPI工作时钟 = SYS_Freq/pow(2, CLKDIV+2) #define SPI_CTRL_CLKDIV_Msk (0x07 << SPI_CTRL_CLKDIV_Pos) #define SPI_CTRL_EN_Pos 3 #define SPI_CTRL_EN_Msk (0x01 << SPI_CTRL_EN_Pos) -#define SPI_CTRL_SIZE_Pos 4 //Data Size Select, ȡֵ3--15ʾ4--16λ +#define SPI_CTRL_SIZE_Pos 4 //Data Size Select, 取值3--15,表示4--16位 #define SPI_CTRL_SIZE_Msk (0x0F << SPI_CTRL_SIZE_Pos) -#define SPI_CTRL_CPHA_Pos 8 //0 SCLKĵһز 1 SCLKĵڶز +#define SPI_CTRL_CPHA_Pos 8 //0 在SCLK的第一个跳变沿采样数据 1 在SCLK的第二个跳变沿采样数据 #define SPI_CTRL_CPHA_Msk (0x01 << SPI_CTRL_CPHA_Pos) -#define SPI_CTRL_CPOL_Pos 9 //0 ״̬SCLKΪ͵ƽ 1 ״̬SCLKΪߵƽ +#define SPI_CTRL_CPOL_Pos 9 //0 空闲状态下SCLK为低电平 1 空闲状态下SCLK为高电平 #define SPI_CTRL_CPOL_Msk (0x01 << SPI_CTRL_CPOL_Pos) #define SPI_CTRL_FFS_Pos 10 //Frame Format Select, 0 SPI 1 TI SSI 2 SPI 3 SPI #define SPI_CTRL_FFS_Msk (0x03 << SPI_CTRL_FFS_Pos) -#define SPI_CTRL_MSTR_Pos 12 //Master, 1 ģʽ 0 ģʽ +#define SPI_CTRL_MSTR_Pos 12 //Master, 1 主模式 0 从模式 #define SPI_CTRL_MSTR_Msk (0x01 << SPI_CTRL_MSTR_Pos) -#define SPI_CTRL_FAST_Pos 13 //1 SPIʱ = SYS_Freq/2 0 SPIʱSPI->CTRL.CLKDIV +#define SPI_CTRL_FAST_Pos 13 //1 SPI工作时钟 = SYS_Freq/2 0 SPI工作时钟由SPI->CTRL.CLKDIV设置 #define SPI_CTRL_FAST_Msk (0x01 << SPI_CTRL_FAST_Pos) -#define SPI_CTRL_FILTE_Pos 16 //1 SPIźŽȥ 0 SPIźŲȥ +#define SPI_CTRL_FILTE_Pos 16 //1 对SPI输入信号进行去抖操作 0 对SPI输入信号不进行去抖操作 #define SPI_CTRL_FILTE_Msk (0x01 << SPI_CTRL_FILTE_Pos) -#define SPI_CTRL_SSN_H_Pos 17 //0 SSNʼΪ0 1 ÿַ֮ὫSSN߰SCLK +#define SPI_CTRL_SSN_H_Pos 17 //0 传输过程中SSN始终为0 1 传输过程中每字符之间会将SSN拉高半个SCLK周期 #define SPI_CTRL_SSN_H_Msk (0x01 << SPI_CTRL_SSN_H_Pos) #define SPI_CTRL_TFCLR_Pos 24 //TX FIFO Clear #define SPI_CTRL_TFCLR_Msk (0x01 << SPI_CTRL_TFCLR_Pos) #define SPI_CTRL_RFCLR_Pos 25 //RX FIFO Clear #define SPI_CTRL_RFCLR_Msk (0x01 << SPI_CTRL_RFCLR_Pos) -#define SPI_STAT_WTC_Pos 0 //Word Transmit CompleteÿһӲ1д1 +#define SPI_STAT_WTC_Pos 0 //Word Transmit Complete,每传输完成一个数据字由硬件置1,软件写1清零 #define SPI_STAT_WTC_Msk (0x01 << SPI_STAT_WTC_Pos) -#define SPI_STAT_TFE_Pos 1 //FIFO Empty +#define SPI_STAT_TFE_Pos 1 //发送FIFO Empty #define SPI_STAT_TFE_Msk (0x01 << SPI_STAT_TFE_Pos) -#define SPI_STAT_TFNF_Pos 2 //FIFO Not Full +#define SPI_STAT_TFNF_Pos 2 //发送FIFO Not Full #define SPI_STAT_TFNF_Msk (0x01 << SPI_STAT_TFNF_Pos) -#define SPI_STAT_RFNE_Pos 3 //FIFO Not Empty +#define SPI_STAT_RFNE_Pos 3 //接收FIFO Not Empty #define SPI_STAT_RFNE_Msk (0x01 << SPI_STAT_RFNE_Pos) -#define SPI_STAT_RFF_Pos 4 //FIFO Full +#define SPI_STAT_RFF_Pos 4 //接收FIFO Full #define SPI_STAT_RFF_Msk (0x01 << SPI_STAT_RFF_Pos) -#define SPI_STAT_RFOVF_Pos 5 //FIFO Overflow +#define SPI_STAT_RFOVF_Pos 5 //接收FIFO Overflow #define SPI_STAT_RFOVF_Msk (0x01 << SPI_STAT_RFOVF_Pos) -#define SPI_STAT_TFLVL_Pos 6 //FIFOݸ 0 TFNF=0ʱʾFIFO8ݣTFNF=1ʱʾFIFO0 1--7 FIFO1--7 +#define SPI_STAT_TFLVL_Pos 6 //发送FIFO中数据个数, 0 TFNF=0时表示FIFO内有8个数据,TFNF=1时表示FIFO内有0个数据 1--7 FIFO内有1--7个数据 #define SPI_STAT_TFLVL_Msk (0x07 << SPI_STAT_TFLVL_Pos) -#define SPI_STAT_RFLVL_Pos 9 //FIFOݸ 0 RFF=1ʱʾFIFO8ݣ RFF=0ʱʾFIFO0 1--7 FIFO1--7 +#define SPI_STAT_RFLVL_Pos 9 //接收FIFO中数据个数, 0 RFF=1时表示FIFO内有8个数据, RFF=0时表示FIFO内有0个数据 1--7 FIFO内有1--7个数据 #define SPI_STAT_RFLVL_Msk (0x07 << SPI_STAT_RFLVL_Pos) #define SPI_STAT_BUSY_Pos 15 #define SPI_STAT_BUSY_Msk (0x01 << SPI_STAT_BUSY_Pos) @@ -1925,7 +1925,7 @@ typedef struct { #define SPI_IE_FTC_Pos 9 //Frame Transmit Complete #define SPI_IE_FTC_Msk (0x01 << SPI_IE_FTC_Pos) -#define SPI_IF_RFOVF_Pos 0 //д1 +#define SPI_IF_RFOVF_Pos 0 //写1清零 #define SPI_IF_RFOVF_Msk (0x01 << SPI_IF_RFOVF_Pos) #define SPI_IF_RFF_Pos 1 #define SPI_IF_RFF_Msk (0x01 << SPI_IF_RFF_Pos) @@ -1935,16 +1935,16 @@ typedef struct { #define SPI_IF_TFE_Msk (0x01 << SPI_IF_TFE_Pos) #define SPI_IF_TFHF_Pos 4 #define SPI_IF_TFHF_Msk (0x01 << SPI_IF_TFHF_Pos) -#define SPI_IF_WTC_Pos 8 //Word Transmit CompleteÿһӲ1 +#define SPI_IF_WTC_Pos 8 //Word Transmit Complete,每传输完成一个数据字由硬件置1 #define SPI_IF_WTC_Msk (0x01 << SPI_IF_WTC_Pos) -#define SPI_IF_FTC_Pos 9 //Frame Transmit CompleteWTCλʱTX FIFOǿյģFTCλ +#define SPI_IF_FTC_Pos 9 //Frame Transmit Complete,WTC置位时若TX FIFO是空的,则FTC置位 #define SPI_IF_FTC_Msk (0x01 << SPI_IF_FTC_Pos) typedef struct { - __IO uint32_t CLKDIV; //[15:0] 뽫ڲƵʷֵSCLƵʵ5CLKDIV = SYS_Freq/5/SCL_Freq - 1 + __IO uint32_t CLKDIV; //[15:0] 须将内部工作频率分到SCL频率的5倍,即CLKDIV = SYS_Freq/5/SCL_Freq - 1 __IO uint32_t CTRL; @@ -1967,61 +1967,61 @@ typedef struct { #define I2C_CTRL_EN_Pos 7 #define I2C_CTRL_EN_Msk (0x01 << I2C_CTRL_EN_Pos) -#define I2C_MSTCMD_IF_Pos 0 //1 еȴжϣд1 ´λӲλ1һֽڴ 2߷Ȩʧ +#define I2C_MSTCMD_IF_Pos 0 //1 有等待处理的中断,写1清零 有两种情况下此位硬件置位:1、一个字节传输完成 2、总线访问权丢失 #define I2C_MSTCMD_IF_Msk (0x01 << I2C_MSTCMD_IF_Pos) #define I2C_MSTCMD_TIP_Pos 1 //Transmission In Process #define I2C_MSTCMD_TIP_Msk (0x01 << I2C_MSTCMD_TIP_Pos) -#define I2C_MSTCMD_ACK_Pos 3 //ģʽ£0 Ͷ˷ACK 1 Ͷ˷NACK +#define I2C_MSTCMD_ACK_Pos 3 //接收模式下,0 向发送端反馈ACK 1 向发送端反馈NACK #define I2C_MSTCMD_ACK_Msk (0x01 << I2C_MSTCMD_ACK_Pos) -#define I2C_MSTCMD_WR_Pos 4 // Slaveдʱһλд1Զ +#define I2C_MSTCMD_WR_Pos 4 // 向Slave写数据时,把这一位写1,自动清零 #define I2C_MSTCMD_WR_Msk (0x01 << I2C_MSTCMD_WR_Pos) -#define I2C_MSTCMD_RD_Pos 5 //дSlaveʱһλд1Զ I2CģʧȥߵķȨʱӲ1 +#define I2C_MSTCMD_RD_Pos 5 //写:从Slave读数据时,把这一位写1,自动清零 读:当I2C模块失去总线的访问权时硬件置1 #define I2C_MSTCMD_RD_Msk (0x01 << I2C_MSTCMD_RD_Pos) -#define I2C_MSTCMD_BUSY_Pos 6 //⵽START֮һλ1⵽STOP֮һλ0 +#define I2C_MSTCMD_BUSY_Pos 6 //读:当检测到START之后,这一位变1;当检测到STOP之后,这一位变0 #define I2C_MSTCMD_BUSY_Msk (0x01 << I2C_MSTCMD_BUSY_Pos) -#define I2C_MSTCMD_STO_Pos 6 //дSTOPԶ +#define I2C_MSTCMD_STO_Pos 6 //写:产生STOP,自动清零 #define I2C_MSTCMD_STO_Msk (0x01 << I2C_MSTCMD_STO_Pos) -#define I2C_MSTCMD_RXACK_Pos 7 //յSlaveACKλ0 յACK 1 յNACK +#define I2C_MSTCMD_RXACK_Pos 7 //读:接收到的Slave的ACK位,0 收到ACK 1 收到NACK #define I2C_MSTCMD_RXACK_Msk (0x01 << I2C_MSTCMD_RXACK_Pos) -#define I2C_MSTCMD_STA_Pos 7 //дSTARTԶ +#define I2C_MSTCMD_STA_Pos 7 //写:产生START,自动清零 #define I2C_MSTCMD_STA_Msk (0x01 << I2C_MSTCMD_STA_Pos) -#define I2C_SLVCR_IM_RXEND_Pos 0 //жϽֹ +#define I2C_SLVCR_IM_RXEND_Pos 0 //接收完成中断禁止 #define I2C_SLVCR_IM_RXEND_Msk (0x01 << I2C_SLVCR_IM_RXEND_Pos) -#define I2C_SLVCR_IM_TXEND_Pos 1 //жϽֹ +#define I2C_SLVCR_IM_TXEND_Pos 1 //发送完成中断禁止 #define I2C_SLVCR_IM_TXEND_Msk (0x01 << I2C_SLVCR_IM_TXEND_Pos) -#define I2C_SLVCR_IM_STADET_Pos 2 //⵽ʼжϽֹ +#define I2C_SLVCR_IM_STADET_Pos 2 //检测到起始中断禁止 #define I2C_SLVCR_IM_STADET_Msk (0x01 << I2C_SLVCR_IM_STADET_Pos) -#define I2C_SLVCR_IM_STODET_Pos 3 //⵽ֹͣжϽֹ +#define I2C_SLVCR_IM_STODET_Pos 3 //检测到停止中断禁止 #define I2C_SLVCR_IM_STODET_Msk (0x01 << I2C_SLVCR_IM_STODET_Pos) -#define I2C_SLVCR_IM_RDREQ_Pos 4 //յжϽֹ +#define I2C_SLVCR_IM_RDREQ_Pos 4 //接收到读请求中断禁止 #define I2C_SLVCR_IM_RDREQ_Msk (0x01 << I2C_SLVCR_IM_RDREQ_Pos) -#define I2C_SLVCR_IM_WRREQ_Pos 5 //յджϽֹ +#define I2C_SLVCR_IM_WRREQ_Pos 5 //接收到写请求中断禁止 #define I2C_SLVCR_IM_WRREQ_Msk (0x01 << I2C_SLVCR_IM_WRREQ_Pos) -#define I2C_SLVCR_ADDR7b_Pos 16 //1 7λַģʽ 0 10λַģʽ +#define I2C_SLVCR_ADDR7b_Pos 16 //1 7位地址模式 0 10位地址模式 #define I2C_SLVCR_ADDR7b_Msk (0x01 << I2C_SLVCR_ADDR7b_Pos) -#define I2C_SLVCR_ACK_Pos 17 //1 ӦACK 0 ӦNACK +#define I2C_SLVCR_ACK_Pos 17 //1 应答ACK 0 应答NACK #define I2C_SLVCR_ACK_Msk (0x01 << I2C_SLVCR_ACK_Pos) -#define I2C_SLVCR_SLAVE_Pos 18 //1 ӻģʽ 0 ģʽ +#define I2C_SLVCR_SLAVE_Pos 18 //1 从机模式 0 主机模式 #define I2C_SLVCR_SLAVE_Msk (0x01 << I2C_SLVCR_SLAVE_Pos) -#define I2C_SLVCR_DEBOUNCE_Pos 19 //ȥʹ +#define I2C_SLVCR_DEBOUNCE_Pos 19 //去抖动使能 #define I2C_SLVCR_DEBOUNCE_Msk (0x01 << I2C_SLVCR_DEBOUNCE_Pos) -#define I2C_SLVCR_ADDR_Pos 20 //ӻַ +#define I2C_SLVCR_ADDR_Pos 20 //从机地址 #define I2C_SLVCR_ADDR_Msk (0x3FF << I2C_SLVCR_ADDR_Pos) -#define I2C_SLVIF_RXEND_Pos 0 //жϱ־д1 +#define I2C_SLVIF_RXEND_Pos 0 //接收完成中断标志,写1清零 #define I2C_SLVIF_RXEND_Msk (0x01 << I2C_SLVIF_RXEND_Pos) -#define I2C_SLVIF_TXEND_Pos 1 //жϱ־д1 +#define I2C_SLVIF_TXEND_Pos 1 //发送完成中断标志,写1清零 #define I2C_SLVIF_TXEND_Msk (0x01 << I2C_SLVIF_TXEND_Pos) -#define I2C_SLVIF_STADET_Pos 2 //⵽ʼжϱ־д1 +#define I2C_SLVIF_STADET_Pos 2 //检测到起始中断标志,写1清零 #define I2C_SLVIF_STADET_Msk (0x01 << I2C_SLVIF_STADET_Pos) -#define I2C_SLVIF_STODET_Pos 3 //⵽ֹͣжϱ־д1 +#define I2C_SLVIF_STODET_Pos 3 //检测到停止中断标志,写1清零 #define I2C_SLVIF_STODET_Msk (0x01 << I2C_SLVIF_STODET_Pos) -#define I2C_SLVIF_RDREQ_Pos 4 //յжϱ־ +#define I2C_SLVIF_RDREQ_Pos 4 //接收到读请求中断标志 #define I2C_SLVIF_RDREQ_Msk (0x01 << I2C_SLVIF_RDREQ_Pos) -#define I2C_SLVIF_WRREQ_Pos 5 //յджϱ־ +#define I2C_SLVIF_WRREQ_Pos 5 //接收到写请求中断标志 #define I2C_SLVIF_WRREQ_Msk (0x01 << I2C_SLVIF_WRREQ_Pos) -#define I2C_SLVIF_ACTIVE_Pos 6 //slave Ч +#define I2C_SLVIF_ACTIVE_Pos 6 //slave 有效 #define I2C_SLVIF_ACTIVE_Msk (0x01 << I2C_SLVIF_ACTIVE_Pos) @@ -2056,7 +2056,7 @@ typedef struct { } ADC_TypeDef; -#define ADC_CTRL_CH0_Pos 0 //ͨѡ +#define ADC_CTRL_CH0_Pos 0 //通道选中 #define ADC_CTRL_CH0_Msk (0x01 << ADC_CTRL_CH0_Pos) #define ADC_CTRL_CH1_Pos 1 #define ADC_CTRL_CH1_Msk (0x01 << ADC_CTRL_CH1_Pos) @@ -2072,20 +2072,20 @@ typedef struct { #define ADC_CTRL_CH6_Msk (0x01 << ADC_CTRL_CH6_Pos) #define ADC_CTRL_CH7_Pos 7 #define ADC_CTRL_CH7_Msk (0x01 << ADC_CTRL_CH7_Pos) -#define ADC_CTRL_AVG_Pos 8 //0 1β 1 2βȡƽֵ 3 4βȡƽֵ 7 8βȡƽֵ 15 16βȡƽֵ +#define ADC_CTRL_AVG_Pos 8 //0 1次采样 1 2次采样取平均值 3 4次采样取平均值 7 8次采样取平均值 15 16次采样取平均值 #define ADC_CTRL_AVG_Msk (0x0F << ADC_CTRL_AVG_Pos) #define ADC_CTRL_EN_Pos 12 #define ADC_CTRL_EN_Msk (0x01 << ADC_CTRL_EN_Pos) -#define ADC_CTRL_CONT_Pos 13 //Continuous conversionֻģʽЧ0 תתɺSTARTλԶֹͣת -#define ADC_CTRL_CONT_Msk (0x01 << ADC_CTRL_CONT_Pos) // 1 תһֱתֱSTARTλ -#define ADC_CTRL_TRIG_Pos 14 //תʽ0 ת 1 PWM +#define ADC_CTRL_CONT_Pos 13 //Continuous conversion,只在软件启动模式下有效,0 单次转换,转换完成后START位自动清除停止转换 +#define ADC_CTRL_CONT_Msk (0x01 << ADC_CTRL_CONT_Pos) // 1 连续转换,启动后一直采样、转换,直到软件清除START位 +#define ADC_CTRL_TRIG_Pos 14 //转换触发方式:0 软件启动转换 1 PWM触发 #define ADC_CTRL_TRIG_Msk (0x01 << ADC_CTRL_TRIG_Pos) #define ADC_CTRL_CLKSRC_Pos 15 //0 VCO 1 HRC #define ADC_CTRL_CLKSRC_Msk (0x01 << ADC_CTRL_CLKSRC_Pos) #define ADC_CTRL_FIFOCLR_Pos 24 //[24] CH0_FIFO_CLR [25] CH1_FIFO_CLR ... [31] CH7_FIFO_CLR #define ADC_CTRL_FIFOCLR_Msk (0xFFu<< ADC_CTRL_FIFOCLR_Pos) -#define ADC_START_GO_Pos 0 //ģʽ£д1ADCתڵģʽתɺӲԶ㣬ɨģʽ±д0ֹͣADCת +#define ADC_START_GO_Pos 0 //软件触发模式下,写1启动ADC采样和转换,在单次模式下转换完成后硬件自动清零,在扫描模式下必须软件写0停止ADC转换 #define ADC_START_GO_Msk (0x01 << ADC_START_GO_Pos) #define ADC_START_BUSY_Pos 4 #define ADC_START_BUSY_Msk (0x01 << ADC_START_BUSY_Pos) @@ -2155,13 +2155,13 @@ typedef struct { #define ADC_IE_CH7FULL_Pos 31 #define ADC_IE_CH7FULL_Msk (0x01u<< ADC_IE_CH7FULL_Pos) -#define ADC_IF_CH0EOC_Pos 0 //д1 +#define ADC_IF_CH0EOC_Pos 0 //写1清零 #define ADC_IF_CH0EOC_Msk (0x01 << ADC_IF_CH0EOC_Pos) -#define ADC_IF_CH0OVF_Pos 1 //д1 +#define ADC_IF_CH0OVF_Pos 1 //写1清零 #define ADC_IF_CH0OVF_Msk (0x01 << ADC_IF_CH0OVF_Pos) -#define ADC_IF_CH0HFULL_Pos 2 //д1 +#define ADC_IF_CH0HFULL_Pos 2 //写1清零 #define ADC_IF_CH0HFULL_Msk (0x01 << ADC_IF_CH0HFULL_Pos) -#define ADC_IF_CH0FULL_Pos 3 //д1 +#define ADC_IF_CH0FULL_Pos 3 //写1清零 #define ADC_IF_CH0FULL_Msk (0x01 << ADC_IF_CH0FULL_Pos) #define ADC_IF_CH1EOC_Pos 4 #define ADC_IF_CH1EOC_Msk (0x01 << ADC_IF_CH1EOC_Pos) @@ -2220,9 +2220,9 @@ typedef struct { #define ADC_IF_CH7FULL_Pos 31 #define ADC_IF_CH7FULL_Msk (0x01 << ADC_IF_CH7FULL_Pos) -#define ADC_STAT_EOC_Pos 0 //д1 +#define ADC_STAT_EOC_Pos 0 //写1清零 #define ADC_STAT_EOC_Msk (0x01 << ADC_STAT_EOC_Pos) -#define ADC_STAT_OVF_Pos 1 //ݼĴ +#define ADC_STAT_OVF_Pos 1 //读数据寄存器清除 #define ADC_STAT_OVF_Msk (0x01 << ADC_STAT_OVF_Pos) #define ADC_STAT_HFULL_Pos 2 #define ADC_STAT_HFULL_Msk (0x01 << ADC_STAT_HFULL_Pos) @@ -2231,20 +2231,20 @@ typedef struct { #define ADC_STAT_EMPTY_Pos 4 #define ADC_STAT_EMPTY_Msk (0x01 << ADC_STAT_EMPTY_Pos) -#define ADC_CTRL1_RIN_Pos 4 //迹0 1 105K 2 90K 3 75K 4 60K 5 45K 6 30K 7 15K +#define ADC_CTRL1_RIN_Pos 4 //输入阻抗:0 无穷大 1 105K 2 90K 3 75K 4 60K 5 45K 6 30K 7 15K #define ADC_CTRL1_RIN_Msk (0x07 << ADC_CTRL1_RIN_Pos) -#define ADC_CTRL2_RESET_Pos 0 //ֵ·λ +#define ADC_CTRL2_RESET_Pos 0 //数字电路复位 #define ADC_CTRL2_RESET_Msk (0x01 << ADC_CTRL2_RESET_Pos) -#define ADC_CTRL2_ADCEVCM_Pos 1 //ADC External VCMADCPGAģƽѡ +#define ADC_CTRL2_ADCEVCM_Pos 1 //ADC External VCM,ADC与PGA输出共模电平选择 #define ADC_CTRL2_ADCEVCM_Msk (0x01 << ADC_CTRL2_ADCEVCM_Pos) -#define ADC_CTRL2_PGAIVCM_Pos 2 //PGA Internal VCMPGA빲ģƽѡ +#define ADC_CTRL2_PGAIVCM_Pos 2 //PGA Internal VCM,PGA输入共模电平选择 #define ADC_CTRL2_PGAIVCM_Msk (0x01 << ADC_CTRL2_PGAIVCM_Pos) #define ADC_CTRL2_PGAGAIN_Pos 3 //0 25.1dB 1 21.6dB 2 11.1dB 3 3.5dB 4 0dB(1.8V) 5 -2.9dB 6 -5.3dB #define ADC_CTRL2_PGAGAIN_Msk (0x07 << ADC_CTRL2_PGAGAIN_Pos) -#define ADC_CTRL2_REFPOUT_Pos 23 //1 ADC ڲ 1.2V REFPѹⲿREFPţڲҪ1.2VⲿREFPʱʡɱ +#define ADC_CTRL2_REFPOUT_Pos 23 //1 ADC 内部 1.2V REFP电压输出到外部REFP引脚,用于测量,或在需要1.2V外部REFP时节省成本 #define ADC_CTRL2_REFPOUT_Msk (0x01 << ADC_CTRL2_REFPOUT_Pos -#define ADC_CTRL2_CLKDIV_Pos 24 //ʱӷƵֻʱԴΪHRCʱЧ +#define ADC_CTRL2_CLKDIV_Pos 24 //时钟分频,只在时钟源为HRC时有效 #define ADC_CTRL2_CLKDIV_Msk (0x1F << ADC_CTRL2_CLKDIV_Pos) #define ADC_CTRL2_PGAVCM_Pos 29 #define ADC_CTRL2_PGAVCM_Msk (0x07u<< ADC_CTRL2_PGAVCM_Pos) @@ -2263,17 +2263,17 @@ typedef struct { typedef struct { - __IO uint32_t MODE; //0 ͨģʽAB· - //1 ģʽAB·PERAHIGHAƣB·A·෴DZADZBAB·Ƴʱ - //2 ģʽͬͨģʽһںԶֹͣ - //3 ԳģʽAB·ڲһڣֱһƵʽһ - //4 ԳƻģʽԳģʽͻģʽۺ + __IO uint32_t MODE; //0 普通模式,A、B两路输出互相独立 + //1 互补模式,A、B两路输出都由PERA、HIGHA控制,B路输出与A路输出极性相反,且DZA、DZB控制A、B路输出上升沿推迟时间 + //2 单次模式,同普通模式,但一个周期后自动停止 + //3 对称模式,A、B两路输出互相独立,以两个计数周期产生一个波形输出周期,分辨率提升一倍、频率降低一倍 + //4 对称互补模式,对称模式和互补模式的综合 - __IO uint32_t PERA; //[15:0] + __IO uint32_t PERA; //[15:0] 周期 - __IO uint32_t HIGHA; //[15:0] ߵƽʱ + __IO uint32_t HIGHA; //[15:0] 高电平持续时长 - __IO uint32_t DZA; //[9:0] ƳʱСHIGHA + __IO uint32_t DZA; //[9:0] 死区,即上升沿推迟时长,必须小于HIGHA __IO uint32_t PERB; @@ -2281,7 +2281,7 @@ typedef struct { __IO uint32_t DZB; - __IO uint32_t INIOUT; //Init Output levelʼƽ + __IO uint32_t INIOUT; //Init Output level,初始输出电平 } PWM_TypeDef; @@ -2314,7 +2314,7 @@ typedef struct { uint32_t RESERVED[3]; - __IO uint32_t HALT; //ɲ + __IO uint32_t HALT; //刹车控制 __IO uint32_t CHEN; @@ -2343,7 +2343,7 @@ typedef struct { #define PWMG_ADTRG_VALUE_Pos 0 #define PWMG_ADTRG_VALUE_Msk (0xFFFF << PWMG_ADTRG0A_VALUE_Pos) -#define PWMG_ADTRG_EVEN_Pos 16 //1 żЧ 0 Ч +#define PWMG_ADTRG_EVEN_Pos 16 //1 偶数周期生效 0 奇数周期生效 #define PWMG_ADTRG_EVEN_Msk (0x01 << PWMG_ADTRG0A_EVEN_Pos) #define PWMG_ADTRG_EN_Pos 17 #define PWMG_ADTRG_EN_Msk (0x01 << PWMG_ADTRG0A_EN_Pos) @@ -2362,13 +2362,13 @@ typedef struct { #define PWMG_HALT_PWM4_Msk (0x01 << PWMG_HALT_PWM4_Pos) #define PWMG_HALT_PWM5_Pos 6 #define PWMG_HALT_PWM5_Msk (0x01 << PWMG_HALT_PWM5_Pos) -#define PWMG_HALT_STOPCNT_Pos 7 //1 ɲʱPWM㣬ֹͣ 0 ɲʱPWM +#define PWMG_HALT_STOPCNT_Pos 7 //1 刹车时将PWM计数器清零,停止计数 0 刹车时,PWM计数器继续计数 #define PWMG_HALT_STOPCNT_Msk (0x01 << PWMG_HALT_STOPCNT_Pos) -#define PWMG_HALT_INLVL_Pos 8 //1 ɲߵƽЧ +#define PWMG_HALT_INLVL_Pos 8 //1 刹车输入高电平有效 #define PWMG_HALT_INLVL_Msk (0x01 << PWMG_HALT_INLVL_Pos) -#define PWMG_HALT_OUTLVL_Pos 9 //1 ɲߵƽ +#define PWMG_HALT_OUTLVL_Pos 9 //1 刹车过程中输出高电平 #define PWMG_HALT_OUTLVL_Msk (0x01 << PWMG_HALT_OUTLVL_Pos) -#define PWMG_HALT_STAT_Pos 10 //1 ɲ +#define PWMG_HALT_STAT_Pos 10 //1 正在刹车 #define PWMG_HALT_STAT_Msk (0x01 << PWMG_HALT_STAT_Pos) #define PWMG_CHEN_PWM0A_Pos 0 @@ -2607,11 +2607,11 @@ typedef struct { typedef struct { __IO uint32_t EN; //[0] ENABLE - __IO uint32_t IE; //ֻΪ1ʱIF[CHx]DMAʱܱΪ1һֱ0 + __IO uint32_t IE; //只有为1时,IF[CHx]在DMA传输结束时才能变为1,否则将一直保持在0 - __IO uint32_t IM; //Ϊ1ʱʹIF[CHx]Ϊ1dma_intҲ˱1 + __IO uint32_t IM; //当为1时,即使IF[CHx]为1,dma_int也不会因此变1 - __IO uint32_t IF; //д1 + __IO uint32_t IF; //写1清零 uint32_t RESERVED[12]; @@ -2622,23 +2622,23 @@ typedef struct { __IO uint32_t SRC; - __IO uint32_t SRCSGADDR1; //ֻScatter Gatherģʽʹ + __IO uint32_t SRCSGADDR1; //只在Scatter Gather模式下使用 - __IO uint32_t SRCSGADDR2; //ֻScatter Gatherģʽʹ + __IO uint32_t SRCSGADDR2; //只在Scatter Gather模式下使用 - __IO uint32_t SRCSGADDR3; //ֻScatter Gatherģʽʹ + __IO uint32_t SRCSGADDR3; //只在Scatter Gather模式下使用 - __IO uint32_t SRCSGLEN; //ֻScatter Gatherģʽʹ + __IO uint32_t SRCSGLEN; //只在Scatter Gather模式下使用 __IO uint32_t DST; - __IO uint32_t DSTSGADDR1; //ֻScatter Gatherģʽʹ + __IO uint32_t DSTSGADDR1; //只在Scatter Gather模式下使用 - __IO uint32_t DSTSGADDR2; //ֻScatter Gatherģʽʹ + __IO uint32_t DSTSGADDR2; //只在Scatter Gather模式下使用 - __IO uint32_t DSTSGADDR3; //ֻScatter Gatherģʽʹ + __IO uint32_t DSTSGADDR3; //只在Scatter Gather模式下使用 - __IO uint32_t DSTSGLEN; //ֻScatter Gatherģʽʹ + __IO uint32_t DSTSGLEN; //只在Scatter Gather模式下使用 uint32_t RESERVED[4]; } CH[3]; @@ -2696,16 +2696,16 @@ typedef struct { #define DMA_IF_CH7_Pos 7 #define DMA_IF_CH7_Msk (0x01 << DMA_IF_CH7_Pos) -#define DMA_CR_LEN_Pos 0 //ͨܳȣ0Ӧ1ֽڣ4096ֽ +#define DMA_CR_LEN_Pos 0 //此通道传输总长度,0对应1字节,最大4096字节 #define DMA_CR_LEN_Msk (0xFFF << DMA_CR_LEN_Pos) #define DMA_CR_RXEN_Pos 16 #define DMA_CR_RXEN_Msk (0x01 << DMA_CR_RXEN_Pos) #define DMA_CR_TXEN_Pos 17 #define DMA_CR_TXEN_Msk (0x01 << DMA_CR_TXEN_Pos) -#define DMA_CR_AUTORE_Pos 18 //Auto Restart, ͨڴɺǷԶ +#define DMA_CR_AUTORE_Pos 18 //Auto Restart, 通道在传输完成后,是否自动重新启动 #define DMA_CR_AUTORE_Msk (0x01 << DMA_CR_AUTORE_Pos) -#define DMA_AM_SRCAM_Pos 0 //Address Mode 0 ̶ַ 1 ַ 2 scatter gatherģʽ +#define DMA_AM_SRCAM_Pos 0 //Address Mode 0 地址固定 1 地址递增 2 scatter gather模式 #define DMA_AM_SRCAM_Msk (0x03 << DMA_AM_SRCAM_Pos) #define DMA_AM_DSTAM_Pos 8 #define DMA_AM_DSTAM_Msk (0x03 << DMA_AM_DSTAM_Pos) @@ -2722,7 +2722,7 @@ typedef struct { __I uint32_t SR; //Status Register - __I uint32_t IF; //Interrupt Flagȡ + __I uint32_t IF; //Interrupt Flag,读取清零 __IO uint32_t IE; //Interrupt Enable @@ -2734,26 +2734,26 @@ typedef struct { uint32_t RESERVED2[3]; - __I uint32_t ALC; //Arbitration Lost Capture, ٲöʧ׽ + __I uint32_t ALC; //Arbitration Lost Capture, 仲裁丢失捕捉 - __I uint32_t ECC; //Error code capture, 벶׽ + __I uint32_t ECC; //Error code capture, 错误代码捕捉 - __IO uint32_t EWLIM; //Error Warning Limit, 󱨾 + __IO uint32_t EWLIM; //Error Warning Limit, 错误报警限制 - __IO uint32_t RXERR; //RX + __IO uint32_t RXERR; //RX错误计数 - __IO uint32_t TXERR; //TX + __IO uint32_t TXERR; //TX错误计数 union { - struct { //ڸλʱɶдģʽ²ɷ - __IO uint32_t ACR[4]; //Acceptance Check Register, ռĴ + struct { //在复位时可读写,正常工作模式下不可访问 + __IO uint32_t ACR[4]; //Acceptance Check Register, 验收寄存器 - __IO uint32_t AMR[4]; //Acceptance Mask Register, μĴӦλд0IDռĴƥ + __IO uint32_t AMR[4]; //Acceptance Mask Register, 验收屏蔽寄存器;对应位写0,ID必须和验收寄存器匹配 uint32_t RESERVED[5]; } FILTER; - union { //ģʽ¿ɶдλʱɷ + union { //在正常工作模式下可读写,复位时不可访问 struct { __O uint32_t INFO; @@ -2772,7 +2772,7 @@ typedef struct { uint32_t RESERVED3[66]; - struct { //TXFRAMEĶӿ + struct { //TXFRAME的读接口 __I uint32_t INFO; __I uint32_t DATA[12]; @@ -2784,11 +2784,11 @@ typedef struct { #define CAN_CR_RST_Msk (0x01 << CAN_CR_RST_Pos) #define CAN_CR_LOM_Pos 1 //Listen Only Mode #define CAN_CR_LOM_Msk (0x01 << CAN_CR_LOM_Pos) -#define CAN_CR_STM_Pos 2 //Self Test Mode, ģʽ¼ʹûӦCANҲԳɹ +#define CAN_CR_STM_Pos 2 //Self Test Mode, 此模式下即使没有应答,CAN控制器也可以成功发送 #define CAN_CR_STM_Msk (0x01 << CAN_CR_STM_Pos) -#define CAN_CR_AFM_Pos 3 //Acceptance Filter Mode, 1 ˲32λ 0 ˲16λ +#define CAN_CR_AFM_Pos 3 //Acceptance Filter Mode, 1 单个验收滤波器(32位) 0 两个验收滤波器(16位) #define CAN_CR_AFM_Msk (0x01 << CAN_CR_AFM_Pos) -#define CAN_CR_SLEEP_Pos 4 //д1˯ģʽ߻жʱѲԶλ +#define CAN_CR_SLEEP_Pos 4 //写1进入睡眠模式,有总线活动或中断时唤醒并自动清零此位 #define CAN_CR_SLEEP_Msk (0x01 << CAN_CR_SLEEP_Pos) #define CAN_CMD_TXREQ_Pos 0 //Transmission Request @@ -2802,38 +2802,38 @@ typedef struct { #define CAN_CMD_SRR_Pos 4 //Self Reception Request #define CAN_CMD_SRR_Msk (0x01 << CAN_CMD_SRR_Pos) -#define CAN_SR_RXDA_Pos 0 //Receive Data AvailableFIFOϢԶȡ +#define CAN_SR_RXDA_Pos 0 //Receive Data Available,接收FIFO中有完整消息可以读取 #define CAN_SR_RXDA_Msk (0x01 << CAN_SR_RXDA_Pos) -#define CAN_SR_RXOV_Pos 1 //Receive FIFO Overrun½յϢڽFIFO +#define CAN_SR_RXOV_Pos 1 //Receive FIFO Overrun,新接收的信息由于接收FIFO已满而丢掉 #define CAN_SR_RXOV_Msk (0x01 << CAN_SR_RXOV_Pos) -#define CAN_SR_TXBR_Pos 2 //Transmit Buffer Release0 ڴǰķͣڲдµϢ 1 дµϢ +#define CAN_SR_TXBR_Pos 2 //Transmit Buffer Release,0 正在处理前面的发送,现在不能写新的消息 1 可以写入新的消息发送 #define CAN_SR_TXBR_Msk (0x01 << CAN_SR_TXBR_Pos) -#define CAN_SR_TXOK_Pos 3 //Transmit OKsuccessfully completed +#define CAN_SR_TXOK_Pos 3 //Transmit OK,successfully completed #define CAN_SR_TXOK_Msk (0x01 << CAN_SR_TXOK_Pos) -#define CAN_SR_RXBUSY_Pos 4 //Receive Busyڽ +#define CAN_SR_RXBUSY_Pos 4 //Receive Busy,正在接收 #define CAN_SR_RXBUSY_Msk (0x01 << CAN_SR_RXBUSY_Pos) -#define CAN_SR_TXBUSY_Pos 5 //Transmit Busyڷ +#define CAN_SR_TXBUSY_Pos 5 //Transmit Busy,正在发送 #define CAN_SR_TXBUSY_Msk (0x01 << CAN_SR_TXBUSY_Pos) -#define CAN_SR_ERRWARN_Pos 6 //1 һﵽ Warning Limit +#define CAN_SR_ERRWARN_Pos 6 //1 至少一个错误计数器达到 Warning Limit #define CAN_SR_ERRWARN_Msk (0x01 << CAN_SR_ERRWARN_Pos) -#define CAN_SR_BUSOFF_Pos 7 //1 CAN ߹ر״̬ûв뵽߻ +#define CAN_SR_BUSOFF_Pos 7 //1 CAN 控制器处于总线关闭状态,没有参与到总线活动 #define CAN_SR_BUSOFF_Msk (0x01 << CAN_SR_BUSOFF_Pos) #define CAN_IF_RXDA_Pos 0 //IF.RXDA = SR.RXDA & IE.RXDA #define CAN_IF_RXDA_Msk (0x01 << CAN_IF_RXDA_Pos) -#define CAN_IF_TXBR_Pos 1 //IE.TXBR=1ʱSR.TXBR01λλ +#define CAN_IF_TXBR_Pos 1 //当IE.TXBR=1时,SR.TXBR由0变成1将置位此位 #define CAN_IF_TXBR_Msk (0x01 << CAN_IF_TXBR_Pos) -#define CAN_IF_ERRWARN_Pos 2 //IE.ERRWARN=1ʱSR.ERRWARNSR.BUSOFF 0-to-1 1-to-0λλ +#define CAN_IF_ERRWARN_Pos 2 //当IE.ERRWARN=1时,SR.ERRWARN或SR.BUSOFF 0-to-1 或 1-to-0将置位此位 #define CAN_IF_ERRWARN_Msk (0x01 << CAN_IF_ERRWARN_Pos) #define CAN_IF_RXOV_Pos 3 //IF.RXOV = SR.RXOV & IE.RXOV #define CAN_IF_RXOV_Msk (0x01 << CAN_IF_RXOV_Pos) -#define CAN_IF_WKUP_Pos 4 //IE.WKUP=1ʱ˯ģʽµCAN⵽߻ʱӲλ +#define CAN_IF_WKUP_Pos 4 //当IE.WKUP=1时,在睡眠模式下的CAN控制器检测到总线活动时硬件置位 #define CAN_IF_WKUP_Msk (0x01 << CAN_IF_WKUP_Pos) #define CAN_IF_ERRPASS_Pos 5 // #define CAN_IF_ERRPASS_Msk (0x01 << CAN_IF_ERRPASS_Pos) -#define CAN_IF_ARBLOST_Pos 6 //Arbitration LostIE.ARBLOST=1ʱCANʧٲñɽշʱӲλ +#define CAN_IF_ARBLOST_Pos 6 //Arbitration Lost,当IE.ARBLOST=1时,CAN控制器丢失仲裁变成接收方时硬件置位 #define CAN_IF_ARBLOST_Msk (0x01 << CAN_IF_ARBLOST_Pos) -#define CAN_IF_BUSERR_Pos 7 //IE.BUSERR=1ʱCAN⵽ߴʱӲλ +#define CAN_IF_BUSERR_Pos 7 //当IE.BUSERR=1时,CAN控制器检测到总线错误时硬件置位 #define CAN_IF_BUSERR_Msk (0x01 << CAN_IF_BUSERR_Pos) #define CAN_IE_RXDA_Pos 0 @@ -2853,68 +2853,68 @@ typedef struct { #define CAN_IE_BUSERR_Pos 7 #define CAN_IE_BUSERR_Msk (0x01 << CAN_IE_BUSERR_Pos) -#define CAN_BT0_BRP_Pos 0 //Baud Rate PrescalerCANʱ䵥λ=2*Tsysclk*(BRP+1) +#define CAN_BT0_BRP_Pos 0 //Baud Rate Prescaler,CAN时间单位=2*Tsysclk*(BRP+1) #define CAN_BT0_BRP_Msk (0x3F << CAN_BT0_BRP_Pos) #define CAN_BT0_SJW_Pos 6 //Synchronization Jump Width #define CAN_BT0_SJW_Msk (0x03 << CAN_BT0_SJW_Pos) -#define CAN_BT1_TSEG1_Pos 0 //t_tseg1 = CANʱ䵥λ * (TSEG1+1) +#define CAN_BT1_TSEG1_Pos 0 //t_tseg1 = CAN时间单位 * (TSEG1+1) #define CAN_BT1_TSEG1_Msk (0x0F << CAN_BT1_TSEG1_Pos) -#define CAN_BT1_TSEG2_Pos 4 //t_tseg2 = CANʱ䵥λ * (TSEG2+1) +#define CAN_BT1_TSEG2_Pos 4 //t_tseg2 = CAN时间单位 * (TSEG2+1) #define CAN_BT1_TSEG2_Msk (0x07 << CAN_BT1_TSEG2_Pos) -#define CAN_BT1_SAM_Pos 7 // 0: sampled once 1: sampled three times +#define CAN_BT1_SAM_Pos 7 //采样次数 0: sampled once 1: sampled three times #define CAN_BT1_SAM_Msk (0x01 << CAN_BT1_SAM_Pos) #define CAN_ECC_SEGCODE_Pos 0 //Segment Code #define CAN_ECC_SEGCODE_Msk (0x1F << CAN_ECC_SEGCODE_Pos) #define CAN_ECC_DIR_Pos 5 //0 error occurred during transmission 1 during reception #define CAN_ECC_DIR_Msk (0x01 << CAN_ECC_DIR_Pos) -#define CAN_ECC_ERRCODE_Pos 6 //Error Code0 Bit error 1 Form error 2 Stuff error 3 other error +#define CAN_ECC_ERRCODE_Pos 6 //Error Code:0 Bit error 1 Form error 2 Stuff error 3 other error #define CAN_ECC_ERRCODE_Msk (0x03 << CAN_ECC_ERRCODE_Pos) #define CAN_INFO_DLC_Pos 0 //Data Length Control #define CAN_INFO_DLC_Msk (0x0F << CAN_INFO_DLC_Pos) -#define CAN_INFO_RTR_Pos 6 //Remote Frame1 Զ֡ 0 ֡ +#define CAN_INFO_RTR_Pos 6 //Remote Frame,1 远程帧 0 数据帧 #define CAN_INFO_RTR_Msk (0x01 << CAN_INFO_RTR_Pos) -#define CAN_INFO_FF_Pos 7 //Frame Format0 ׼֡ʽ 1 չ֡ʽ +#define CAN_INFO_FF_Pos 7 //Frame Format,0 标准帧格式 1 扩展帧格式 #define CAN_INFO_FF_Msk (0x01 << CAN_INFO_FF_Pos) typedef struct { - __IO uint32_t IE; //[0] Ϊ0ʱIF[0]άΪ0 + __IO uint32_t IE; //[0] 为0的时候,IF[0]维持为0 - __IO uint32_t IF; //[0] ָȵݴʱ1д1 + __IO uint32_t IF; //[0] 当完成指定长度的数据传输时置1,写1清零 - __IO uint32_t IM; //[0] üĴΪ1ʱLCDCжϲϵͳжϿƼĴ + __IO uint32_t IM; //[0] 当该寄存器为1时,LCDC的中断不会输出给系统的中断控制寄存器 __IO uint32_t START; - __IO uint32_t SRCADDR; //ԴַĴֶ루ַĵ2λ0 + __IO uint32_t SRCADDR; //数据源地址寄存器,必须字对齐(即地址的低2位必须是0) __IO uint32_t CR0; __IO uint32_t CR1; - __IO uint32_t PRECMDV; //MPUӿУǰRS͵һģϵֵ + __IO uint32_t PRECMDV; //在MPU接口中,发送数据前,RS拉低的那一拍,数据总线上的值 } LCD_TypeDef; -#define LCD_START_GO_Pos 1 //д1ʼݣݴԶ +#define LCD_START_GO_Pos 1 //写1开始传输数据,数据传输结束后自动清零 #define LCD_START_GO_Msk (0x01 << LCD_START_GO_Pos) #define LCD_START_BURST_Pos 2 #define LCD_START_BURST_Msk (0x01 << LCD_START_BURST_Pos) -#define LCD_CR0_VPIX_Pos 0 //portraitΪ0ʱʾֱظ0ʾ1Ϊ767 - //portraitΪ1ʱʾˮƽظ0ʾ1Ϊ767 +#define LCD_CR0_VPIX_Pos 0 //当portrait为0时,表示垂直方向的像素个数,0表示1个,最大为767 + //当portrait为1时,表示水平方向的像素个数,0表示1个,最大为767 #define LCD_CR0_VPIX_Msk (0x3FF << LCD_CR0_VPIX_Pos) -#define LCD_CR0_HPIX_Pos 10 //portraitΪ0ʱʾˮƽظ0ʾ1Ϊ1023 - //portraitΪ1ʱʾֱظ0ʾ1Ϊ1023 +#define LCD_CR0_HPIX_Pos 10 //当portrait为0时,表示水平方向的像素个数,0表示1个,最大为1023 + //当portrait为1时,表示垂直方向的像素个数,0表示1个,最大为1023 #define LCD_CR0_HPIX_Msk (0x3FF << LCD_CR0_HPIX_Pos) -#define LCD_CR0_DCLK_Pos 20 //0 DOTCLKһֱת 1 DOTCLKڿʱͣ1 +#define LCD_CR0_DCLK_Pos 20 //0 DOTCLK一直翻转 1 DOTCLK在空闲时停在1 #define LCD_CR0_DCLK_Msk (0x01 << LCD_CR0_DCLK_Pos) -#define LCD_CR0_HLOW_Pos 21 //HSYNC͵ƽٸDOTCLKڣ0ʾ1 +#define LCD_CR0_HLOW_Pos 21 //输出HSYNC低电平持续多少个DOTCLK周期,0表示1个周期 #define LCD_CR0_HLOW_Msk (0x03 << LCD_CR0_HLOW_Pos) #define LCD_CR1_VFP_Pos 1 @@ -2925,9 +2925,9 @@ typedef struct { #define LCD_CR1_HFP_Msk (0x1F << LCD_CR1_HFP_Pos) #define LCD_CR1_HBP_Pos 14 #define LCD_CR1_HBP_Msk (0x7F << LCD_CR1_HBP_Pos) -#define LCD_CR1_DCLKDIV_Pos 21 //DOTCLKģʱӵķƵȣ0ʾ2Ƶ1ʾ4Ƶ ... +#define LCD_CR1_DCLKDIV_Pos 21 //DOTCLK相对于模块时钟的分频比,0表示2分频,1表示4分频 ... #define LCD_CR1_DCLKDIV_Msk (0x1F << LCD_CR1_DCLKDIV_Pos) -#define LCD_CR1_DCLKINV_Pos 26 //1 DOTCLKӦDOTCLK½زݵ +#define LCD_CR1_DCLKINV_Pos 26 //1 输出DOTCLK反向,应用于用DOTCLK下降沿采样数据的屏 #define LCD_CR1_DCLKINV_Msk (0x01 << LCD_CR1_DCLKINV_Pos) @@ -2966,9 +2966,9 @@ typedef struct { } SDIO_TypeDef; -#define SDIO_BLK_SIZE_Pos 0 //0x200 512ֽ 0x400 1024ֽ 0x800 2048ֽ +#define SDIO_BLK_SIZE_Pos 0 //0x200 512字节 0x400 1024字节 0x800 2048字节 #define SDIO_BLK_SIZE_Msk (0xFFF << SDIO_BLK_SIZE_Pos) -#define SDIO_BLK_COUNT_Pos 16 //0 Stop Transfer 1 1 2 2 ... ... +#define SDIO_BLK_COUNT_Pos 16 //0 Stop Transfer 1 1块 2 2块 ... ... #define SDIO_BLK_COUNT_Msk (0xFFF << SDIO_BLK_COUNT_Pos) #define SDIO_CMD_DMAEN_Pos 0 @@ -2981,7 +2981,7 @@ typedef struct { #define SDIO_CMD_DIRREAD_Msk (0x01 << SDIO_CMD_DIRREAD_Pos) #define SDIO_CMD_MULTBLK_Pos 5 //0 Single Block 1 Multiple Block #define SDIO_CMD_MULTBLK_Msk (0x01 << SDIO_CMD_MULTBLK_Pos) -#define SDIO_CMD_RESPTYPE_Pos 16 //Ӧͣ0 Ӧ 1 136λӦ 2 48λӦ 3 48λӦBusy after response +#define SDIO_CMD_RESPTYPE_Pos 16 //响应类型,0 无响应 1 136位响应 2 48位响应 3 48位响应,Busy after response #define SDIO_CMD_RESPTYPE_Msk (0x03 << SDIO_CMD_RESPTYPE_Pos) #define SDIO_CMD_CRCCHECK_Pos 19 //Command CRC Check Enable #define SDIO_CMD_CRCCHECK_Msk (0x01 << SDIO_CMD_CRCCHECK_Pos) @@ -2991,7 +2991,7 @@ typedef struct { #define SDIO_CMD_HAVEDATA_Msk (0x01 << SDIO_CMD_HAVEDATA_Pos) #define SDIO_CMD_CMDTYPE_Pos 22 //0 NORMAL 1 SUSPEND 2 RESUME 3 ABORT #define SDIO_CMD_CMDTYPE_Msk (0x03 << SDIO_CMD_CMDTYPE_Pos) -#define SDIO_CMD_CMDINDX_Pos 24 //Command IndexCMD0-63ACMD0-63 +#define SDIO_CMD_CMDINDX_Pos 24 //Command Index,CMD0-63、ACMD0-63 #define SDIO_CMD_CMDINDX_Msk (0x3F << SDIO_CMD_CMDINDX_Pos) #define SDIO_CR1_4BIT_Pos 1 //1 4 bit mode 0 1 bit mode @@ -3000,7 +3000,7 @@ typedef struct { #define SDIO_CR1_8BIT_Msk (0x01 << SDIO_CR1_8BIT_Pos) #define SDIO_CR1_CDBIT_Pos 6 //0 No Card 1 Card Inserted #define SDIO_CR1_CDBIT_Msk (0x01 << SDIO_CR1_CDBIT_Pos) -#define SDIO_CR1_CDSRC_Pos 7 //Card Detect Source, 1 CR1.CDBITλ 0 SD_Detect +#define SDIO_CR1_CDSRC_Pos 7 //Card Detect Source, 1 CR1.CDBIT位 0 SD_Detect引脚 #define SDIO_CR1_CDSRC_Msk (0x01 << SDIO_CR1_CDSRC_Pos) #define SDIO_CR1_PWRON_Pos 8 //1 Power on 0 Power off #define SDIO_CR1_PWRON_Msk (0x01 << SDIO_CR1_PWRON_Pos) @@ -3013,7 +3013,7 @@ typedef struct { #define SDIO_CR2_CLKRDY_Msk (0x01 << SDIO_CR2_CLKRDY_Pos) #define SDIO_CR2_SDCLKEN_Pos 2 //SDCLK Enable #define SDIO_CR2_SDCLKEN_Msk (0x01 << SDIO_CR2_SDCLKEN_Pos) -#define SDIO_CR2_SDCLKDIV_Pos 8 //SDCLK Frequency Div, 0x00 Ƶ 0x01 2Ƶ 0x02 4Ƶ 0x04 8Ƶ 0x08 16Ƶ ... 0x80 256Ƶ +#define SDIO_CR2_SDCLKDIV_Pos 8 //SDCLK Frequency Div, 0x00 不分频 0x01 2分频 0x02 4分频 0x04 8分频 0x08 16分频 ... 0x80 256分频 #define SDIO_CR2_SDCLKDIV_Msk (0xFF << SDIO_CR2_SDCLKDIV_Pos) #define SDIO_CR2_TIMEOUT_Pos 16 //0 TMCLK*2^13 1 TMCLK*2^14 ... 14 TMCLK*2^27 #define SDIO_CR2_TIMEOUT_Msk (0x0F << SDIO_CR2_TIMEOUT_Pos) @@ -3190,11 +3190,11 @@ typedef struct { } SRAMC_TypeDef; -#define SRAMC_CR_RWTIME_Pos 0 //дٸʱڡ0ʾ1ʱڡСΪ4 +#define SRAMC_CR_RWTIME_Pos 0 //读写操作持续多少个时钟周期。0表示1个时钟周期。最小设置为4 #define SRAMC_CR_RWTIME_Msk (0x0F << SRAMC_CR_RWTIME_Pos) -#define SRAMC_CR_BYTEIF_Pos 4 //ⲿSRAMݿȣ0 16λ 1 8λ +#define SRAMC_CR_BYTEIF_Pos 4 //外部SRAM数据宽度,0 16位 1 8位 #define SRAMC_CR_BYTEIF_Msk (0x01 << SRAMC_CR_BYTEIF_Pos) -#define SRAMC_CR_HBLBDIS_Pos 5 //1 ADDR[23:22]Ϊַ 0 ADDR[23]ΪֽʹܣADDR[22]Ϊֽʹ +#define SRAMC_CR_HBLBDIS_Pos 5 //1 ADDR[23:22]为地址线 0 ADDR[23]为高字节使能,ADDR[22]为低字节使能 #define SRAMC_CR_HBLBDIS_Msk (0x01 << SRAMC_CR_HBLBDIS_Pos) @@ -3206,17 +3206,17 @@ typedef struct { __IO uint32_t REFRESH; - __IO uint32_t NOPNUM; //[15:0] ʼɺ֮ǰͶٸNOP + __IO uint32_t NOPNUM; //[15:0] 初始化完成后,在正常操作之前,发送多少个NOP命令 __IO uint32_t LATCH; - __IO uint32_t REFDONE; //[0] Frefresh Doneϵʼ + __IO uint32_t REFDONE; //[0] Frefresh Done,上电初始化完成 } SDRAMC_TypeDef; -#define SDRAMC_CR0_BURSTLEN_Pos 0 //ȡ2ʾBurst LengthΪ4 +#define SDRAMC_CR0_BURSTLEN_Pos 0 //必须取2,表示Burst Length为4 #define SDRAMC_CR0_BURSTLEN_Msk (0x07 << SDRAMC_CR0_BURSTLEN_Pos) -#define SDRAMC_CR0_CASDELAY_Pos 4 //CAS Latency 2 2 3 3 +#define SDRAMC_CR0_CASDELAY_Pos 4 //CAS Latency, 2 2 3 3 #define SDRAMC_CR0_CASDELAY_Msk (0x07 << SDRAMC_CR0_CASDELAY_Pos) #define SDRAMC_CR1_TRP_Pos 0 @@ -3231,15 +3231,15 @@ typedef struct { #define SDRAMC_CR1_TRRD_Msk (0x03 << SDRAMC_CR1_TRRD_Pos) #define SDRAMC_CR1_TMRD_Pos 15 #define SDRAMC_CR1_TMRD_Msk (0x07 << SDRAMC_CR1_TMRD_Pos) -#define SDRAMC_CR1_32BIT_Pos 18 //SDRAMCĽӿλ1 32bit 0 16bit +#define SDRAMC_CR1_32BIT_Pos 18 //SDRAMC的接口数据位宽,1 32bit 0 16bit #define SDRAMC_CR1_32BIT_Msk (0x01 << SDRAMC_CR1_32BIT_Pos) -#define SDRAMC_CR1_BANK_Pos 19 //SDRAMÿмbank0 2 banks 1 4 banks +#define SDRAMC_CR1_BANK_Pos 19 //SDRAM每个颗粒有几个bank,0 2 banks 1 4 banks #define SDRAMC_CR1_BANK_Msk (0x01 << SDRAMC_CR1_BANK_Pos) -#define SDRAMC_CR1_CELL32BIT_Pos 20 //SDRAMλ1 32bit 0 16bit +#define SDRAMC_CR1_CELL32BIT_Pos 20 //SDRAM颗粒的位宽,1 32bit 0 16bit #define SDRAMC_CR1_CELL32BIT_Msk (0x01 << SDRAMC_CR1_CELL32BIT_Pos) -#define SDRAMC_CR1_CELLSIZE_Pos 21 //SDRAM0 64Mb 1 128Mb 2 256Mb 3 16Mb +#define SDRAMC_CR1_CELLSIZE_Pos 21 //SDRAM颗粒的容量,0 64Mb 1 128Mb 2 256Mb 3 16Mb #define SDRAMC_CR1_CELLSIZE_Msk (0x03 << SDRAMC_CR1_CELLSIZE_Pos) -#define SDRAMC_CR1_HIGHSPEED_Pos 23 //hclk100MHzʱһλΪ1Ϊ0 +#define SDRAMC_CR1_HIGHSPEED_Pos 23 //当hclk大于100MHz时,这一位必须配置为1,否则为0 #define SDRAMC_CR1_HIGHSPEED_Msk (0x01 << SDRAMC_CR1_HIGHSPEED_Pos) #define SDRAMC_REFRESH_RATE_Pos 0 @@ -3247,9 +3247,9 @@ typedef struct { #define SDRAMC_REFRESH_EN_Pos 12 #define SDRAMC_REFRESH_EN_Msk (0x01 << SDRAMC_REFRESH_EN_Pos) -#define SDRAMC_LATCH_INEDGE_Pos 0 //ĸSDRAMжصݣ0 1 ½ +#define SDRAMC_LATCH_INEDGE_Pos 0 //哪个沿来锁存从SDRAM中读回的数据,0 上升沿 1 下降沿 #define SDRAMC_LATCH_INEDGE_Msk (0x01 << SDRAMC_LATCH_INEDGE_Pos) -#define SDRAMC_LATCH_OUTEDGE_Pos 1 //ĸȥ͸SDRAMݣ1 0 ½ +#define SDRAMC_LATCH_OUTEDGE_Pos 1 //哪个沿去锁存送给SDRAM的数据,1 上升沿 0 下降沿 #define SDRAMC_LATCH_OUTEDGE_Msk (0x01 << SDRAMC_LATCH_OUTEDGE_Pos) #define SDRAMC_LATCH_WAITST_Pos 2 #define SDRAMC_LATCH_WAITST_Msk (0x01 << SDRAMC_LATCH_WAITST_Pos) @@ -3260,7 +3260,7 @@ typedef struct { typedef struct { __IO uint32_t IE; - __IO uint32_t IF; //д1 + __IO uint32_t IF; //写1清零 __IO uint32_t IM; @@ -3287,16 +3287,16 @@ typedef struct { #define NORFLC_IM_TIMEOUT_Pos 1 #define NORFLC_IM_TIMEOUT_Msk (0x01 << NORFLC_IM_TIMEOUT_Pos) -#define NORFLC_CR_RDTIME_Pos 0 //Oen½غٸʱںصݡ0ʾ1ʱ +#define NORFLC_CR_RDTIME_Pos 0 //Oen下降沿后多少个时钟周期后采样读回的数据。0表示1个时钟周期 #define NORFLC_CR_RDTIME_Msk (0x1F << NORFLC_CR_RDTIME_Pos) -#define NORFLC_CR_WRTIME_Pos 5 //Wenĵ͵ƽȡ0ʾ1ʱ +#define NORFLC_CR_WRTIME_Pos 5 //输出Wen的低电平宽度。0表示1个时钟周期 #define NORFLC_CR_WRTIME_Msk (0x07 << NORFLC_CR_WRTIME_Pos) -#define NORFLC_CR_BYTEIF_Pos 8 //ⲿNOR FLASHݿȣ1 8λ 0 16λ +#define NORFLC_CR_BYTEIF_Pos 8 //外部NOR FLASH数据宽度,1 8位 0 16位 #define NORFLC_CR_BYTEIF_Msk (0x01 << NORFLC_CR_BYTEIF_Pos) -#define NORFLC_CMD_DATA_Pos 0 //PROGRAMУDATAҪдNOR FLASHݣREADУDATAǴNOR FLASHص +#define NORFLC_CMD_DATA_Pos 0 //在PROGRAM命令中,DATA是要写入NOR FLASH的数据;在READ命令中,DATA是从NOR FLASH读回的数据 #define NORFLC_CMD_DATA_Msk (0xFFFF << NORFLC_CMD_DATA_Pos) -#define NORFLC_CMD_CMD_Pos 16 //Ҫִе0 READ 1 RESET 2 AUTOMATIC SELECT 3 PROGRAM 4 CHIP ERASE 5 SECTOR ERASE +#define NORFLC_CMD_CMD_Pos 16 //需要执行的命令,0 READ 1 RESET 2 AUTOMATIC SELECT 3 PROGRAM 4 CHIP ERASE 5 SECTOR ERASE #define NORFLC_CMD_CMD_Msk (0x07 << NORFLC_CMD_CMD_Pos) @@ -3315,44 +3315,44 @@ typedef struct { #define CRC_CR_EN_Pos 0 #define CRC_CR_EN_Msk (0x01 << CRC_CR_EN_Pos) -#define CRC_CR_OREV_Pos 1 //Ƿת +#define CRC_CR_OREV_Pos 1 //输出结果是否翻转 #define CRC_CR_OREV_Msk (0x01 << CRC_CR_OREV_Pos) -#define CRC_CR_ONOT_Pos 2 //Ƿȡ +#define CRC_CR_ONOT_Pos 2 //输出结果是否取反 #define CRC_CR_ONOT_Msk (0x01 << CRC_CR_ONOT_Pos) #define CRC_CR_CRC16_Pos 3 //1 CRC16 0 CRC32 #define CRC_CR_CRC16_Msk (0x01 << CRC_CR_CRC16_Pos) -#define CRC_CR_IBITS_Pos 4 //Чλ 0 32λ 1 16λ 2 8λ +#define CRC_CR_IBITS_Pos 4 //输入数据有效位数 0 32位 1 16位 2 8位 #define CRC_CR_IBITS_Msk (0x03 << CRC_CR_IBITS_Pos) typedef struct { - __IO uint32_t MINSEC; // + __IO uint32_t MINSEC; //分秒计数 - __IO uint32_t DATHUR; //ʱ + __IO uint32_t DATHUR; //日时计数 - __IO uint32_t MONDAY; //ܼ + __IO uint32_t MONDAY; //月周计数 - __IO uint32_t YEAR; //[11:0] ֧1901-2199 + __IO uint32_t YEAR; //[11:0] 年计数,支持1901-2199 - __IO uint32_t MINSECAL; // + __IO uint32_t MINSECAL; //分秒闹铃设置 - __IO uint32_t DAYHURAL; //ʱ + __IO uint32_t DAYHURAL; //周时闹铃设置 - __IO uint32_t LOAD; //üĴеֵͬRTCУͬԶ + __IO uint32_t LOAD; //将设置寄存器中的值同步到RTC中,同步完成自动清零 __IO uint32_t IE; - __IO uint32_t IF; //д1 + __IO uint32_t IF; //写1清零 - __IO uint32_t EN; //[0] 1 RTCʹ + __IO uint32_t EN; //[0] 1 RTC使能 - __IO uint32_t CFGABLE; //[0] 1 RTC + __IO uint32_t CFGABLE; //[0] 1 RTC可配置 - __IO uint32_t TRIM; //ʱӵ + __IO uint32_t TRIM; //时钟调整 - __IO uint32_t TRIMM; //ʱ΢ + __IO uint32_t TRIMM; //时钟微调整 } RTC_TypeDef; @@ -3361,44 +3361,44 @@ typedef struct { #define RTC_LOAD_ALARM_Pos 1 #define RTC_LOAD_ALARM_Msk (0x01 << RTC_LOAD_ALARM_Pos) -#define RTC_MINSEC_SEC_Pos 0 //ȡֵ0--59 +#define RTC_MINSEC_SEC_Pos 0 //秒计数,取值0--59 #define RTC_MINSEC_SEC_Msk (0x3F << RTC_MINSEC_SEC_Pos) -#define RTC_MINSEC_MIN_Pos 6 //Ӽȡֵ0--59 +#define RTC_MINSEC_MIN_Pos 6 //分钟计数,取值0--59 #define RTC_MINSEC_MIN_Msk (0x3F << RTC_MINSEC_MIN_Pos) -#define RTC_DATHUR_HOUR_Pos 0 //Сʱȡֵ0--23 +#define RTC_DATHUR_HOUR_Pos 0 //小时计数,取值0--23 #define RTC_DATHUR_HOUR_Msk (0x1F << RTC_DATHUR_HOUR_Pos) -#define RTC_DATHUR_DATE_Pos 5 //date of monthȡֵ1--31 +#define RTC_DATHUR_DATE_Pos 5 //date of month,取值1--31 #define RTC_DATHUR_DATE_Msk (0x1F << RTC_DATHUR_DATE_Pos) -#define RTC_MONDAY_DAY_Pos 0 //day of weekȡֵ0--6 +#define RTC_MONDAY_DAY_Pos 0 //day of week,取值0--6 #define RTC_MONDAY_DAY_Msk (0x07 << RTC_MONDAY_DAY_Pos) -#define RTC_MONDAY_MON_Pos 3 //·ݼȡֵ1--12 +#define RTC_MONDAY_MON_Pos 3 //月份计数,取值1--12 #define RTC_MONDAY_MON_Msk (0x0F << RTC_MONDAY_MON_Pos) -#define RTC_MINSECAL_SEC_Pos 0 // +#define RTC_MINSECAL_SEC_Pos 0 //闹钟秒设置 #define RTC_MINSECAL_SEC_Msk (0x3F << RTC_MINSECAL_SEC_Pos) -#define RTC_MINSECAL_MIN_Pos 6 //ӷ +#define RTC_MINSECAL_MIN_Pos 6 //闹钟分钟设置 #define RTC_MINSECAL_MIN_Msk (0x3F << RTC_MINSECAL_MIN_Pos) -#define RTC_DAYHURAL_HOUR_Pos 0 //Сʱ +#define RTC_DAYHURAL_HOUR_Pos 0 //闹钟小时设置 #define RTC_DAYHURAL_HOUR_Msk (0x1F << RTC_DAYHURAL_HOUR_Pos) -#define RTC_DAYHURAL_SUN_Pos 5 //Ч +#define RTC_DAYHURAL_SUN_Pos 5 //周日闹钟有效 #define RTC_DAYHURAL_SUN_Msk (0x01 << RTC_DAYHURAL_SUN_Pos) -#define RTC_DAYHURAL_MON_Pos 6 //һЧ +#define RTC_DAYHURAL_MON_Pos 6 //周一闹钟有效 #define RTC_DAYHURAL_MON_Msk (0x01 << RTC_DAYHURAL_MON_Pos) -#define RTC_DAYHURAL_TUE_Pos 7 //ܶЧ +#define RTC_DAYHURAL_TUE_Pos 7 //周二闹钟有效 #define RTC_DAYHURAL_TUE_Msk (0x01 << RTC_DAYHURAL_TUE_Pos) -#define RTC_DAYHURAL_WED_Pos 8 //Ч +#define RTC_DAYHURAL_WED_Pos 8 //周三闹钟有效 #define RTC_DAYHURAL_WED_Msk (0x01 << RTC_DAYHURAL_WED_Pos) -#define RTC_DAYHURAL_THU_Pos 9 //Ч +#define RTC_DAYHURAL_THU_Pos 9 //周四闹钟有效 #define RTC_DAYHURAL_THU_Msk (0x01 << RTC_DAYHURAL_THU_Pos) -#define RTC_DAYHURAL_FRI_Pos 10 //Ч +#define RTC_DAYHURAL_FRI_Pos 10 //周五闹钟有效 #define RTC_DAYHURAL_FRI_Msk (0x01 << RTC_DAYHURAL_FRI_Pos) -#define RTC_DAYHURAL_SAT_Pos 11 //Ч +#define RTC_DAYHURAL_SAT_Pos 11 //周六闹钟有效 #define RTC_DAYHURAL_SAT_Msk (0x01 << RTC_DAYHURAL_SAT_Pos) -#define RTC_IE_SEC_Pos 0 //жʹ +#define RTC_IE_SEC_Pos 0 //秒中断使能 #define RTC_IE_SEC_Msk (0x01 << RTC_IE_SEC_Pos) #define RTC_IE_MIN_Pos 1 #define RTC_IE_MIN_Msk (0x01 << RTC_IE_MIN_Pos) @@ -3409,7 +3409,7 @@ typedef struct { #define RTC_IE_ALARM_Pos 4 #define RTC_IE_ALARM_Msk (0x01 << RTC_IE_ALARM_Pos) -#define RTC_IF_SEC_Pos 0 //д1 +#define RTC_IF_SEC_Pos 0 //写1清零 #define RTC_IF_SEC_Msk (0x01 << RTC_IF_SEC_Pos) #define RTC_IF_MIN_Pos 1 #define RTC_IF_MIN_Msk (0x01 << RTC_IF_MIN_Pos) @@ -3420,13 +3420,13 @@ typedef struct { #define RTC_IF_ALARM_Pos 4 #define RTC_IF_ALARM_Msk (0x01 << RTC_IF_ALARM_Pos) -#define RTC_TRIM_ADJ_Pos 0 //ڵBASECNTļڣĬΪ32768DECΪ1ڵΪ32768-ADJΪ32768+ADJ +#define RTC_TRIM_ADJ_Pos 0 //用于调整BASECNT的计数周期,默认为32768,如果DEC为1,则计数周期调整为32768-ADJ,否则调整为32768+ADJ #define RTC_TRIM_ADJ_Msk (0xFF << RTC_TRIM_ADJ_Pos) #define RTC_TRIM_DEC_Pos 8 #define RTC_TRIM_DEC_Msk (0x01 << RTC_TRIM_DEC_Pos) -#define RTC_TRIMM_CYCLE_Pos 0 //ڼ΢INCΪ1nڵΪ(32768ADJ)+1,Ϊ(32768ADJ)-1 - //cycles=0ʱ΢cycles=1nΪ2cycles=7nΪ8Դ +#define RTC_TRIMM_CYCLE_Pos 0 //用于计数周期微调,如果INC为1,则第n个计数周期调整为(32768±ADJ)+1,否则调整为(32768±ADJ)-1 + //cycles=0时,不进行微调整;cycles=1,则n为2;cycles=7,则n为8;以此类推 #define RTC_TRIMM_CYCLE_Msk (0x07 << RTC_TRIMM_CYCLE_Pos) #define RTC_TRIMM_INC_Pos 3 #define RTC_TRIMM_INC_Msk (0x01 << RTC_TRIMM_INC_Pos) @@ -3435,15 +3435,15 @@ typedef struct { typedef struct { - __IO uint32_t LOAD; //ιʹװLOADֵ + __IO uint32_t LOAD; //喂狗使计数器装载LOAD值 __I uint32_t VALUE; __IO uint32_t CR; - __IO uint32_t IF; //0ʱӲλд1־ + __IO uint32_t IF; //计数到0时硬件置位,软件写1清除标志 - __IO uint32_t FEED; //д0x55ι + __IO uint32_t FEED; //写0x55喂狗 } WDT_TypeDef; diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/arm/startup_SWM320.s b/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/arm/startup_SWM320.s index 72562473f2..aa7fb9c2cf 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/arm/startup_SWM320.s +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/arm/startup_SWM320.s @@ -1,10 +1,10 @@ ;****************************************************************************************************************************************** -; ļ: startup_SWM320.s -; ˵: SWM2400Ƭļ -; ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -; ע: -; 汾: V1.1.0 20171025 -; ¼: +; 文件名称: startup_SWM320.s +; 功能说明: SWM2400单片机的启动文件 +; 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +; 注意事项: +; 版本日期: V1.1.0 2017年10月25日 +; 升级记录: ; ; ;****************************************************************************************************************************************** diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c b/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c index a99fa78fc9..08f5a59bc3 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: system_SWM320.c -* ˵: SWM320Ƭʱ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: system_SWM320.c +* 功能说明: SWM320单片机的时钟设置 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -23,13 +23,13 @@ /****************************************************************************************************************************************** - * ϵͳʱ趨 + * 系统时钟设定 *****************************************************************************************************************************************/ -#define SYS_CLK_20MHz 0 //0 ڲƵ20MHz RC -#define SYS_CLK_40MHz 1 //1 ڲƵ40MHz RC -#define SYS_CLK_32KHz 2 //2 ڲƵ32KHz RC -#define SYS_CLK_XTAL 3 //3 ⲿ2-30MHz -#define SYS_CLK_PLL 4 //4 Ƭ໷ +#define SYS_CLK_20MHz 0 //0 内部高频20MHz RC振荡器 +#define SYS_CLK_40MHz 1 //1 内部高频40MHz RC振荡器 +#define SYS_CLK_32KHz 2 //2 内部低频32KHz RC振荡器 +#define SYS_CLK_XTAL 3 //3 外部晶体振荡器(2-30MHz) +#define SYS_CLK_PLL 4 //4 片内锁相环输出 #define SYS_CLK SYS_CLK_PLL @@ -40,16 +40,16 @@ #define SYS_CLK_DIV SYS_CLK_DIV_1 -#define __HSI (20000000UL) //ڲʱ -#define __LSI ( 32000UL) //ڲʱ -#define __HSE (20000000UL) //ⲿʱ +#define __HSI (20000000UL) //高速内部时钟 +#define __LSI ( 32000UL) //低速内部时钟 +#define __HSE (20000000UL) //高速外部时钟 -/********************************** PLL 趨 ********************************************** - * VCOƵ = PLLʱ / INDIV * 4 * FBDIV - * PLLƵ = PLLʱ / INDIV * 4 * FBDIV / OUTDIV = VCOƵ / OUTDIV +/********************************** PLL 设定 ********************************************** + * VCO输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV + * PLL输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV / OUTDIV = VCO输出频率 / OUTDIV *****************************************************************************************/ -#define SYS_PLL_SRC SYS_CLK_20MHz //ȡֵSYS_CLK_20MHzSYS_CLK_XTAL +#define SYS_PLL_SRC SYS_CLK_20MHz //可取值SYS_CLK_20MHz、SYS_CLK_XTAL #define PLL_IN_DIV 5 @@ -69,11 +69,11 @@ uint32_t CyclesPerUs = (__HSI / 1000000); //Cycles per micro second /****************************************************************************************************************************************** -* : -* ˵: This function is used to update the variable SystemCoreClock and must be called whenever the core clock is changed -* : -* : -* ע: +* 函数名称: +* 功能说明: This function is used to update the variable SystemCoreClock and must be called whenever the core clock is changed +* 输 入: +* 输 出: +* 注意事项: ******************************************************************************************************************************************/ void SystemCoreClockUpdate(void) { @@ -122,11 +122,11 @@ void SystemCoreClockUpdate(void) } /****************************************************************************************************************************************** -* : -* ˵: The necessary initializaiton of systerm -* : -* : -* ע: +* 函数名称: +* 功能说明: The necessary initializaiton of systerm +* 输 入: +* 输 出: +* 注意事项: ******************************************************************************************************************************************/ void SystemInit(void) { @@ -136,23 +136,23 @@ void SystemInit(void) switch(SYS_CLK) { - case SYS_CLK_20MHz: //0 ڲƵ20MHz RC + case SYS_CLK_20MHz: //0 内部高频20MHz RC振荡器 switchCLK_20MHz(); break; - case SYS_CLK_40MHz: //1 ڲƵ40MHz RC + case SYS_CLK_40MHz: //1 内部高频40MHz RC振荡器 switchCLK_40MHz(); break; - case SYS_CLK_32KHz: //2 ڲƵ32KHz RC + case SYS_CLK_32KHz: //2 内部低频32KHz RC振荡器 switchCLK_32KHz(); break; - case SYS_CLK_XTAL: //3 ⲿ2-30MHz + case SYS_CLK_XTAL: //3 外部晶体振荡器(2-30MHz) switchCLK_XTAL(); break; - case SYS_CLK_PLL: //4 Ƭ໷ + case SYS_CLK_PLL: //4 片内锁相环输出 switchCLK_PLL(); break; } @@ -276,5 +276,5 @@ void PLLInit(void) SYS->PLLCR &= ~(1 << SYS_PLLCR_OFF_Pos); - while(SYS->PLLLOCK == 0); //ȴPLL + while(SYS->PLLLOCK == 0); //等待PLL锁定 } From 2c052969488d39d918b30699917c4036c11d209c Mon Sep 17 00:00:00 2001 From: yanmowudi Date: Thu, 6 May 2021 10:42:41 +0800 Subject: [PATCH 021/255] format utf-8 --- .../libraries/CMSIS/DeviceSupport/SWM320.h | 6330 ++++++++--------- .../startup/arm/startup_SWM320.s | 30 +- .../startup/gcc/startup_SWM320.s | 2 +- .../startup/iar/startup_SWM320.s | 2 +- .../CMSIS/DeviceSupport/system_SWM320.c | 397 +- .../CMSIS/DeviceSupport/system_SWM320.h | 28 +- .../SWM320_StdPeriph_Driver/SWM320_adc.c | 469 +- .../SWM320_StdPeriph_Driver/SWM320_adc.h | 122 +- .../SWM320_StdPeriph_Driver/SWM320_can.c | 857 ++- .../SWM320_StdPeriph_Driver/SWM320_can.h | 204 +- .../SWM320_StdPeriph_Driver/SWM320_crc.c | 59 +- .../SWM320_StdPeriph_Driver/SWM320_crc.h | 19 +- .../SWM320_StdPeriph_Driver/SWM320_dma.c | 164 +- .../SWM320_StdPeriph_Driver/SWM320_dma.h | 23 +- .../SWM320_StdPeriph_Driver/SWM320_exti.c | 172 +- .../SWM320_StdPeriph_Driver/SWM320_exti.h | 26 +- .../SWM320_StdPeriph_Driver/SWM320_flash.c | 74 +- .../SWM320_StdPeriph_Driver/SWM320_flash.h | 4 - .../SWM320_StdPeriph_Driver/SWM320_gpio.c | 591 +- .../SWM320_StdPeriph_Driver/SWM320_gpio.h | 34 +- .../SWM320_StdPeriph_Driver/SWM320_i2c.c | 332 +- .../SWM320_StdPeriph_Driver/SWM320_i2c.h | 44 +- .../SWM320_StdPeriph_Driver/SWM320_lcd.c | 104 +- .../SWM320_StdPeriph_Driver/SWM320_lcd.h | 119 +- .../SWM320_StdPeriph_Driver/SWM320_norflash.c | 257 +- .../SWM320_StdPeriph_Driver/SWM320_norflash.h | 38 +- .../SWM320_StdPeriph_Driver/SWM320_port.c | 367 +- .../SWM320_StdPeriph_Driver/SWM320_port.h | 828 ++- .../SWM320_StdPeriph_Driver/SWM320_pwm.c | 947 +-- .../SWM320_StdPeriph_Driver/SWM320_pwm.h | 93 +- .../SWM320_StdPeriph_Driver/SWM320_rtc.c | 274 +- .../SWM320_StdPeriph_Driver/SWM320_rtc.h | 116 +- .../SWM320_StdPeriph_Driver/SWM320_sdio.c | 934 +-- .../SWM320_StdPeriph_Driver/SWM320_sdio.h | 200 +- .../SWM320_StdPeriph_Driver/SWM320_sdram.c | 111 +- .../SWM320_StdPeriph_Driver/SWM320_sdram.h | 123 +- .../SWM320_StdPeriph_Driver/SWM320_spi.c | 272 +- .../SWM320_StdPeriph_Driver/SWM320_spi.h | 131 +- .../SWM320_StdPeriph_Driver/SWM320_sram.c | 45 +- .../SWM320_StdPeriph_Driver/SWM320_sram.h | 42 +- .../SWM320_StdPeriph_Driver/SWM320_timr.c | 521 +- .../SWM320_StdPeriph_Driver/SWM320_timr.h | 35 +- .../SWM320_StdPeriph_Driver/SWM320_uart.c | 402 +- .../SWM320_StdPeriph_Driver/SWM320_uart.h | 140 +- .../SWM320_StdPeriph_Driver/SWM320_wdt.c | 63 +- .../SWM320_StdPeriph_Driver/SWM320_wdt.h | 21 +- 46 files changed, 8127 insertions(+), 8039 deletions(-) diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h b/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h index 423290614f..5aa6db83fa 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/SWM320.h @@ -8,83 +8,83 @@ */ typedef enum IRQn { -/****** Cortex-M0 Processor Exceptions Numbers **********************************************/ - NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ - MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */ - BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */ - UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */ - SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */ - DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */ - PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */ - SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */ - -/****** Cortex-M4 specific Interrupt Numbers ************************************************/ - GPIOA0_IRQn = 0, - GPIOA1_IRQn = 1, - GPIOA2_IRQn = 2, - GPIOA3_IRQn = 3, - GPIOA4_IRQn = 4, - GPIOA5_IRQn = 5, - GPIOA6_IRQn = 6, - GPIOA7_IRQn = 7, - GPIOB0_IRQn = 8, - GPIOB1_IRQn = 9, - GPIOB2_IRQn = 10, - GPIOB3_IRQn = 11, - GPIOB4_IRQn = 12, - GPIOB5_IRQn = 13, - GPIOB6_IRQn = 14, - GPIOB7_IRQn = 15, - GPIOC0_IRQn = 16, - GPIOC1_IRQn = 17, - GPIOC2_IRQn = 18, - GPIOC3_IRQn = 19, - GPIOC4_IRQn = 20, - GPIOC5_IRQn = 21, - GPIOC6_IRQn = 22, - GPIOC7_IRQn = 23, - GPIOM0_IRQn = 24, - GPIOM1_IRQn = 25, - GPIOM2_IRQn = 26, - GPIOM3_IRQn = 27, - GPIOM4_IRQn = 28, - GPIOM5_IRQn = 29, - GPIOM6_IRQn = 30, - GPIOM7_IRQn = 31, - DMA_IRQn = 32, - LCD_IRQn = 33, - NORFLC_IRQn = 34, - CAN_IRQn = 35, - PULSE_IRQn = 36, - WDT_IRQn = 37, - PWM_IRQn = 38, - UART0_IRQn = 39, - UART1_IRQn = 40, - UART2_IRQn = 41, - UART3_IRQn = 42, - UART4_IRQn = 43, - I2C0_IRQn = 44, - I2C1_IRQn = 45, - SPI0_IRQn = 46, - ADC0_IRQn = 47, - RTC_IRQn = 48, - BOD_IRQn = 49, - SDIO_IRQn = 50, - GPIOA_IRQn = 51, - GPIOB_IRQn = 52, - GPIOC_IRQn = 53, - GPIOM_IRQn = 54, - GPION_IRQn = 55, - GPIOP_IRQn = 56, - ADC1_IRQn = 57, - FPU_IRQn = 58, - SPI1_IRQn = 59, - TIMR0_IRQn = 60, - TIMR1_IRQn = 61, - TIMR2_IRQn = 62, - TIMR3_IRQn = 63, - TIMR4_IRQn = 64, - TIMR5_IRQn = 65, + /****** Cortex-M0 Processor Exceptions Numbers **********************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */ + + /****** Cortex-M4 specific Interrupt Numbers ************************************************/ + GPIOA0_IRQn = 0, + GPIOA1_IRQn = 1, + GPIOA2_IRQn = 2, + GPIOA3_IRQn = 3, + GPIOA4_IRQn = 4, + GPIOA5_IRQn = 5, + GPIOA6_IRQn = 6, + GPIOA7_IRQn = 7, + GPIOB0_IRQn = 8, + GPIOB1_IRQn = 9, + GPIOB2_IRQn = 10, + GPIOB3_IRQn = 11, + GPIOB4_IRQn = 12, + GPIOB5_IRQn = 13, + GPIOB6_IRQn = 14, + GPIOB7_IRQn = 15, + GPIOC0_IRQn = 16, + GPIOC1_IRQn = 17, + GPIOC2_IRQn = 18, + GPIOC3_IRQn = 19, + GPIOC4_IRQn = 20, + GPIOC5_IRQn = 21, + GPIOC6_IRQn = 22, + GPIOC7_IRQn = 23, + GPIOM0_IRQn = 24, + GPIOM1_IRQn = 25, + GPIOM2_IRQn = 26, + GPIOM3_IRQn = 27, + GPIOM4_IRQn = 28, + GPIOM5_IRQn = 29, + GPIOM6_IRQn = 30, + GPIOM7_IRQn = 31, + DMA_IRQn = 32, + LCD_IRQn = 33, + NORFLC_IRQn = 34, + CAN_IRQn = 35, + PULSE_IRQn = 36, + WDT_IRQn = 37, + PWM_IRQn = 38, + UART0_IRQn = 39, + UART1_IRQn = 40, + UART2_IRQn = 41, + UART3_IRQn = 42, + UART4_IRQn = 43, + I2C0_IRQn = 44, + I2C1_IRQn = 45, + SPI0_IRQn = 46, + ADC0_IRQn = 47, + RTC_IRQn = 48, + BOD_IRQn = 49, + SDIO_IRQn = 50, + GPIOA_IRQn = 51, + GPIOB_IRQn = 52, + GPIOC_IRQn = 53, + GPIOM_IRQn = 54, + GPION_IRQn = 55, + GPIOP_IRQn = 56, + ADC1_IRQn = 57, + FPU_IRQn = 58, + SPI1_IRQn = 59, + TIMR0_IRQn = 60, + TIMR1_IRQn = 61, + TIMR2_IRQn = 62, + TIMR3_IRQn = 63, + TIMR4_IRQn = 64, + TIMR5_IRQn = 65, } IRQn_Type; /* @@ -94,3512 +94,3455 @@ typedef enum IRQn */ /* Configuration of the Cortex-M0 Processor and Core Peripherals */ -#define __CM4_REV 0x0001 /*!< Core revision r0p1 */ -#define __MPU_PRESENT 1 /*!< SWM320 provides an MPU */ -#define __NVIC_PRIO_BITS 3 /*!< SWM320 uses 3 Bits for the Priority Levels */ -#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ -#define __FPU_PRESENT 0 /*!< FPU present */ +#define __CM4_REV 0x0001 /*!< Core revision r0p1 */ +#define __MPU_PRESENT 1 /*!< SWM320 provides an MPU */ +#define __NVIC_PRIO_BITS 3 /*!< SWM320 uses 3 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 0 /*!< FPU present */ -#if defined ( __CC_ARM ) - #pragma anon_unions +#if defined(__CC_ARM) +#pragma anon_unions #endif #include -#include "core_cm4.h" /* Cortex-M0 processor and core peripherals */ +#include "core_cm4.h" /* Cortex-M0 processor and core peripherals */ #include "system_SWM320.h" - /******************************************************************************/ /* Device Specific Peripheral registers structures */ /******************************************************************************/ -typedef struct { - __IO uint32_t CLKSEL; //Clock Select +typedef struct +{ + __IO uint32_t CLKSEL; //Clock Select - __IO uint32_t CLKDIV; + __IO uint32_t CLKDIV; - __IO uint32_t CLKEN; //Clock Enable + __IO uint32_t CLKEN; //Clock Enable - __IO uint32_t SLEEP; - - uint32_t RESERVED0[6]; - - __IO uint32_t RTCBKP_ISO; //[0] 1 RTC备份电源域处于隔离状态 0 RTC备份电源域可访问 - - __IO uint32_t RTCWKEN; //[0] 1 使能RTC唤醒功能 + __IO uint32_t SLEEP; - uint32_t RESERVED[52+64]; + uint32_t RESERVED0[6]; - __IO uint32_t PAWKEN; //Port A Wakeup Enable - __IO uint32_t PBWKEN; - __IO uint32_t PCWKEN; - - uint32_t RESERVED2[1+4]; + __IO uint32_t RTCBKP_ISO; //[0] 1 RTC备份电源域处于隔离状态 0 RTC备份电源域可访问 - __IO uint32_t PAWKSR; //Port A Wakeup Status Register,写1清零 - __IO uint32_t PBWKSR; - __IO uint32_t PCWKSR; + __IO uint32_t RTCWKEN; //[0] 1 使能RTC唤醒功能 - uint32_t RESERVED3[64-10]; + uint32_t RESERVED[52 + 64]; - __IO uint32_t RSTCR; //Reset Control Register - __IO uint32_t RSTSR; //Reset Status Register + __IO uint32_t PAWKEN; //Port A Wakeup Enable + __IO uint32_t PBWKEN; + __IO uint32_t PCWKEN; - uint32_t RESERVED4[61+64]; + uint32_t RESERVED2[1 + 4]; + + __IO uint32_t PAWKSR; //Port A Wakeup Status Register,写1清零 + __IO uint32_t PBWKSR; + __IO uint32_t PCWKSR; + + uint32_t RESERVED3[64 - 10]; + + __IO uint32_t RSTCR; //Reset Control Register + __IO uint32_t RSTSR; //Reset Status Register + + uint32_t RESERVED4[61 + 64]; + + __IO uint32_t BKP[3]; //数据备份寄存器 - __IO uint32_t BKP[3]; //数据备份寄存器 - //RTC Power Domain: 0x4001E000 - uint32_t RESERVED5[(0x4001E000-0x40000508)/4-1]; - - __IO uint32_t RTCBKP[8]; //RTC电源域数据备份寄存器 - - __IO uint32_t LRCCR; //Low speed RC Control Register - __IO uint32_t LRCTRIM0; //Low speed RC Trim + uint32_t RESERVED5[(0x4001E000 - 0x40000508) / 4 - 1]; + + __IO uint32_t RTCBKP[8]; //RTC电源域数据备份寄存器 + + __IO uint32_t LRCCR; //Low speed RC Control Register + __IO uint32_t LRCTRIM0; //Low speed RC Trim __IO uint32_t LRCTRIM1; - - uint32_t RESERVED6; - - __IO uint32_t RTCLDOTRIM; //RTC Power Domain LDO Trim - + + uint32_t RESERVED6; + + __IO uint32_t RTCLDOTRIM; //RTC Power Domain LDO Trim + //Analog Control: 0x40031000 - uint32_t RESERVED7[(0x40031000-0x4001E030)/4-1]; - - __IO uint32_t HRCCR; //High speed RC Control Register - - uint32_t RESERVED8[7]; - + uint32_t RESERVED7[(0x40031000 - 0x4001E030) / 4 - 1]; + + __IO uint32_t HRCCR; //High speed RC Control Register + + uint32_t RESERVED8[7]; + __IO uint32_t XTALCR; - + __IO uint32_t PLLCR; __IO uint32_t PLLDIV; __IO uint32_t PLLSET; - __IO uint32_t PLLLOCK; //[0] 1 PLL已锁定 - + __IO uint32_t PLLLOCK; //[0] 1 PLL已锁定 + __IO uint32_t BODIE; __IO uint32_t BODIF; - - __IO uint32_t ADC1IN7; + + __IO uint32_t ADC1IN7; } SYS_TypeDef; +#define SYS_CLKSEL_LFCK_Pos 0 //Low Frequency Clock Source 0 LRC 1 PLL +#define SYS_CLKSEL_LFCK_Msk (0x01 << SYS_CLKSEL_LFCK_Pos) +#define SYS_CLKSEL_HFCK_Pos 1 //High Frequency Clock Source 0 HRC 1 XTAL +#define SYS_CLKSEL_HFCK_Msk (0x01 << SYS_CLKSEL_HFCK_Pos) +#define SYS_CLKSEL_SYS_Pos 2 //系统时钟选择 0 LFCK 1 HFCK +#define SYS_CLKSEL_SYS_Msk (0x01 << SYS_CLKSEL_SYS_Pos) -#define SYS_CLKSEL_LFCK_Pos 0 //Low Frequency Clock Source 0 LRC 1 PLL -#define SYS_CLKSEL_LFCK_Msk (0x01 << SYS_CLKSEL_LFCK_Pos) -#define SYS_CLKSEL_HFCK_Pos 1 //High Frequency Clock Source 0 HRC 1 XTAL -#define SYS_CLKSEL_HFCK_Msk (0x01 << SYS_CLKSEL_HFCK_Pos) -#define SYS_CLKSEL_SYS_Pos 2 //系统时钟选择 0 LFCK 1 HFCK -#define SYS_CLKSEL_SYS_Msk (0x01 << SYS_CLKSEL_SYS_Pos) +#define SYS_CLKDIV_SYS_Pos 0 //系统时钟分频 0 1分频 1 2分频 +#define SYS_CLKDIV_SYS_Msk (0x01 << SYS_CLKDIV_SYS_Pos) +#define SYS_CLKDIV_PWM_Pos 1 //PWM 时钟分频 0 1分频 1 8分频 +#define SYS_CLKDIV_PWM_Msk (0x01 << SYS_CLKDIV_PWM_Pos) +#define SYS_CLKDIV_SDRAM_Pos 2 //SDRAM时钟分频 0 1分频 1 2分频 2 4分频 +#define SYS_CLKDIV_SDRAM_Msk (0x03 << SYS_CLKDIV_SDRAM_Pos) +#define SYS_CLKDIV_SDIO_Pos 4 //SDIO时钟分频 0 1分频 1 2分频 2 4分频 3 8分频 +#define SYS_CLKDIV_SDIO_Msk (0x03 << SYS_CLKDIV_SDIO_Pos) -#define SYS_CLKDIV_SYS_Pos 0 //系统时钟分频 0 1分频 1 2分频 -#define SYS_CLKDIV_SYS_Msk (0x01 << SYS_CLKDIV_SYS_Pos) -#define SYS_CLKDIV_PWM_Pos 1 //PWM 时钟分频 0 1分频 1 8分频 -#define SYS_CLKDIV_PWM_Msk (0x01 << SYS_CLKDIV_PWM_Pos) -#define SYS_CLKDIV_SDRAM_Pos 2 //SDRAM时钟分频 0 1分频 1 2分频 2 4分频 -#define SYS_CLKDIV_SDRAM_Msk (0x03 << SYS_CLKDIV_SDRAM_Pos) -#define SYS_CLKDIV_SDIO_Pos 4 //SDIO时钟分频 0 1分频 1 2分频 2 4分频 3 8分频 -#define SYS_CLKDIV_SDIO_Msk (0x03 << SYS_CLKDIV_SDIO_Pos) +#define SYS_CLKEN_GPIOA_Pos 0 +#define SYS_CLKEN_GPIOA_Msk (0x01 << SYS_CLKEN_GPIOA_Pos) +#define SYS_CLKEN_GPIOB_Pos 1 +#define SYS_CLKEN_GPIOB_Msk (0x01 << SYS_CLKEN_GPIOB_Pos) +#define SYS_CLKEN_GPIOC_Pos 2 +#define SYS_CLKEN_GPIOC_Msk (0x01 << SYS_CLKEN_GPIOC_Pos) +#define SYS_CLKEN_GPIOM_Pos 4 +#define SYS_CLKEN_GPIOM_Msk (0x01 << SYS_CLKEN_GPIOM_Pos) +#define SYS_CLKEN_GPION_Pos 5 +#define SYS_CLKEN_GPION_Msk (0x01 << SYS_CLKEN_GPION_Pos) +#define SYS_CLKEN_TIMR_Pos 6 +#define SYS_CLKEN_TIMR_Msk (0x01 << SYS_CLKEN_TIMR_Pos) +#define SYS_CLKEN_WDT_Pos 7 +#define SYS_CLKEN_WDT_Msk (0x01 << SYS_CLKEN_WDT_Pos) +#define SYS_CLKEN_ADC0_Pos 8 +#define SYS_CLKEN_ADC0_Msk (0x01 << SYS_CLKEN_ADC0_Pos) +#define SYS_CLKEN_PWM_Pos 9 +#define SYS_CLKEN_PWM_Msk (0x01 << SYS_CLKEN_PWM_Pos) +#define SYS_CLKEN_RTC_Pos 10 +#define SYS_CLKEN_RTC_Msk (0x01 << SYS_CLKEN_RTC_Pos) +#define SYS_CLKEN_UART0_Pos 11 +#define SYS_CLKEN_UART0_Msk (0x01 << SYS_CLKEN_UART0_Pos) +#define SYS_CLKEN_UART1_Pos 12 +#define SYS_CLKEN_UART1_Msk (0x01 << SYS_CLKEN_UART1_Pos) +#define SYS_CLKEN_UART2_Pos 13 +#define SYS_CLKEN_UART2_Msk (0x01 << SYS_CLKEN_UART2_Pos) +#define SYS_CLKEN_UART3_Pos 14 +#define SYS_CLKEN_UART3_Msk (0x01 << SYS_CLKEN_UART3_Pos) +#define SYS_CLKEN_UART4_Pos 15 +#define SYS_CLKEN_UART4_Msk (0x01 << SYS_CLKEN_UART4_Pos) +#define SYS_CLKEN_SPI0_Pos 16 +#define SYS_CLKEN_SPI0_Msk (0x01 << SYS_CLKEN_SPI0_Pos) +#define SYS_CLKEN_I2C0_Pos 17 +#define SYS_CLKEN_I2C0_Msk (0x01 << SYS_CLKEN_I2C0_Pos) +#define SYS_CLKEN_I2C1_Pos 18 +#define SYS_CLKEN_I2C1_Msk (0x01 << SYS_CLKEN_I2C1_Pos) +#define SYS_CLKEN_I2C2_Pos 19 +#define SYS_CLKEN_I2C2_Msk (0x01 << SYS_CLKEN_I2C2_Pos) +#define SYS_CLKEN_LCD_Pos 20 +#define SYS_CLKEN_LCD_Msk (0x01 << SYS_CLKEN_LCD_Pos) +#define SYS_CLKEN_GPIOP_Pos 21 +#define SYS_CLKEN_GPIOP_Msk (0x01 << SYS_CLKEN_GPIOP_Pos) +#define SYS_CLKEN_ANAC_Pos 22 //模拟控制单元时钟使能 +#define SYS_CLKEN_ANAC_Msk (0x01 << SYS_CLKEN_ANAC_Pos) +#define SYS_CLKEN_CRC_Pos 23 +#define SYS_CLKEN_CRC_Msk (0x01 << SYS_CLKEN_CRC_Pos) +#define SYS_CLKEN_RTCBKP_Pos 24 +#define SYS_CLKEN_RTCBKP_Msk (0x01 << SYS_CLKEN_RTCBKP_Pos) +#define SYS_CLKEN_CAN_Pos 25 +#define SYS_CLKEN_CAN_Msk (0x01 << SYS_CLKEN_CAN_Pos) +#define SYS_CLKEN_SDRAM_Pos 26 +#define SYS_CLKEN_SDRAM_Msk (0x01 << SYS_CLKEN_SDRAM_Pos) +#define SYS_CLKEN_NORFL_Pos 27 //NOR Flash +#define SYS_CLKEN_NORFL_Msk (0x01 << SYS_CLKEN_NORFL_Pos) +#define SYS_CLKEN_RAMC_Pos 28 +#define SYS_CLKEN_RAMC_Msk (0x01 << SYS_CLKEN_RAMC_Pos) +#define SYS_CLKEN_SDIO_Pos 29 +#define SYS_CLKEN_SDIO_Msk (0x01 << SYS_CLKEN_SDIO_Pos) +#define SYS_CLKEN_ADC1_Pos 30 +#define SYS_CLKEN_ADC1_Msk (0x01 << SYS_CLKEN_ADC1_Pos) +#define SYS_CLKEN_ALIVE_Pos 31 //CHIPALIVE电源域系统时钟使能 +#define SYS_CLKEN_ALIVE_Msk (0x01 << SYS_CLKEN_ALIVE_Pos) -#define SYS_CLKEN_GPIOA_Pos 0 -#define SYS_CLKEN_GPIOA_Msk (0x01 << SYS_CLKEN_GPIOA_Pos) -#define SYS_CLKEN_GPIOB_Pos 1 -#define SYS_CLKEN_GPIOB_Msk (0x01 << SYS_CLKEN_GPIOB_Pos) -#define SYS_CLKEN_GPIOC_Pos 2 -#define SYS_CLKEN_GPIOC_Msk (0x01 << SYS_CLKEN_GPIOC_Pos) -#define SYS_CLKEN_GPIOM_Pos 4 -#define SYS_CLKEN_GPIOM_Msk (0x01 << SYS_CLKEN_GPIOM_Pos) -#define SYS_CLKEN_GPION_Pos 5 -#define SYS_CLKEN_GPION_Msk (0x01 << SYS_CLKEN_GPION_Pos) -#define SYS_CLKEN_TIMR_Pos 6 -#define SYS_CLKEN_TIMR_Msk (0x01 << SYS_CLKEN_TIMR_Pos) -#define SYS_CLKEN_WDT_Pos 7 -#define SYS_CLKEN_WDT_Msk (0x01 << SYS_CLKEN_WDT_Pos) -#define SYS_CLKEN_ADC0_Pos 8 -#define SYS_CLKEN_ADC0_Msk (0x01 << SYS_CLKEN_ADC0_Pos) -#define SYS_CLKEN_PWM_Pos 9 -#define SYS_CLKEN_PWM_Msk (0x01 << SYS_CLKEN_PWM_Pos) -#define SYS_CLKEN_RTC_Pos 10 -#define SYS_CLKEN_RTC_Msk (0x01 << SYS_CLKEN_RTC_Pos) -#define SYS_CLKEN_UART0_Pos 11 -#define SYS_CLKEN_UART0_Msk (0x01 << SYS_CLKEN_UART0_Pos) -#define SYS_CLKEN_UART1_Pos 12 -#define SYS_CLKEN_UART1_Msk (0x01 << SYS_CLKEN_UART1_Pos) -#define SYS_CLKEN_UART2_Pos 13 -#define SYS_CLKEN_UART2_Msk (0x01 << SYS_CLKEN_UART2_Pos) -#define SYS_CLKEN_UART3_Pos 14 -#define SYS_CLKEN_UART3_Msk (0x01 << SYS_CLKEN_UART3_Pos) -#define SYS_CLKEN_UART4_Pos 15 -#define SYS_CLKEN_UART4_Msk (0x01 << SYS_CLKEN_UART4_Pos) -#define SYS_CLKEN_SPI0_Pos 16 -#define SYS_CLKEN_SPI0_Msk (0x01 << SYS_CLKEN_SPI0_Pos) -#define SYS_CLKEN_I2C0_Pos 17 -#define SYS_CLKEN_I2C0_Msk (0x01 << SYS_CLKEN_I2C0_Pos) -#define SYS_CLKEN_I2C1_Pos 18 -#define SYS_CLKEN_I2C1_Msk (0x01 << SYS_CLKEN_I2C1_Pos) -#define SYS_CLKEN_I2C2_Pos 19 -#define SYS_CLKEN_I2C2_Msk (0x01 << SYS_CLKEN_I2C2_Pos) -#define SYS_CLKEN_LCD_Pos 20 -#define SYS_CLKEN_LCD_Msk (0x01 << SYS_CLKEN_LCD_Pos) -#define SYS_CLKEN_GPIOP_Pos 21 -#define SYS_CLKEN_GPIOP_Msk (0x01 << SYS_CLKEN_GPIOP_Pos) -#define SYS_CLKEN_ANAC_Pos 22 //模拟控制单元时钟使能 -#define SYS_CLKEN_ANAC_Msk (0x01 << SYS_CLKEN_ANAC_Pos) -#define SYS_CLKEN_CRC_Pos 23 -#define SYS_CLKEN_CRC_Msk (0x01 << SYS_CLKEN_CRC_Pos) -#define SYS_CLKEN_RTCBKP_Pos 24 -#define SYS_CLKEN_RTCBKP_Msk (0x01 << SYS_CLKEN_RTCBKP_Pos) -#define SYS_CLKEN_CAN_Pos 25 -#define SYS_CLKEN_CAN_Msk (0x01 << SYS_CLKEN_CAN_Pos) -#define SYS_CLKEN_SDRAM_Pos 26 -#define SYS_CLKEN_SDRAM_Msk (0x01 << SYS_CLKEN_SDRAM_Pos) -#define SYS_CLKEN_NORFL_Pos 27 //NOR Flash -#define SYS_CLKEN_NORFL_Msk (0x01 << SYS_CLKEN_NORFL_Pos) -#define SYS_CLKEN_RAMC_Pos 28 -#define SYS_CLKEN_RAMC_Msk (0x01 << SYS_CLKEN_RAMC_Pos) -#define SYS_CLKEN_SDIO_Pos 29 -#define SYS_CLKEN_SDIO_Msk (0x01 << SYS_CLKEN_SDIO_Pos) -#define SYS_CLKEN_ADC1_Pos 30 -#define SYS_CLKEN_ADC1_Msk (0x01 << SYS_CLKEN_ADC1_Pos) -#define SYS_CLKEN_ALIVE_Pos 31 //CHIPALIVE电源域系统时钟使能 -#define SYS_CLKEN_ALIVE_Msk (0x01 << SYS_CLKEN_ALIVE_Pos) +#define SYS_SLEEP_SLEEP_Pos 0 //将该位置1后,系统将进入SLEEP模式 +#define SYS_SLEEP_SLEEP_Msk (0x01 << SYS_SLEEP_SLEEP_Pos) +#define SYS_SLEEP_DEEP_Pos 1 //将该位置1后,系统将进入STOP SLEEP模式 +#define SYS_SLEEP_DEEP_Msk (0x01 << SYS_SLEEP_DEEP_Pos) -#define SYS_SLEEP_SLEEP_Pos 0 //将该位置1后,系统将进入SLEEP模式 -#define SYS_SLEEP_SLEEP_Msk (0x01 << SYS_SLEEP_SLEEP_Pos) -#define SYS_SLEEP_DEEP_Pos 1 //将该位置1后,系统将进入STOP SLEEP模式 -#define SYS_SLEEP_DEEP_Msk (0x01 << SYS_SLEEP_DEEP_Pos) +#define SYS_RSTCR_SYS_Pos 0 //写1进行系统复位,硬件自动清零 +#define SYS_RSTCR_SYS_Msk (0x01 << SYS_RSTCR_SYS_Pos) +#define SYS_RSTCR_FLASH_Pos 1 //写1对FLASH控制器进行一次复位,硬件自动清零 +#define SYS_RSTCR_FLASH_Msk (0x01 << SYS_RSTCR_FLASH_Pos) +#define SYS_RSTCR_PWM_Pos 2 //写1对PWM进行一次复位,硬件自动清零 +#define SYS_RSTCR_PWM_Msk (0x01 << SYS_RSTCR_PWM_Pos) +#define SYS_RSTCR_CPU_Pos 3 //写1对CPU进行一次复位,硬件自动清零 +#define SYS_RSTCR_CPU_Msk (0x01 << SYS_RSTCR_CPU_Pos) +#define SYS_RSTCR_DMA_Pos 4 //写1对DMA进行一次复位,硬件自动清零 +#define SYS_RSTCR_DMA_Msk (0x01 << SYS_RSTCR_DMA_Pos) +#define SYS_RSTCR_NORFLASH_Pos 5 //写1对NOR Flash控制器进行一次复位,硬件自动清零 +#define SYS_RSTCR_NORFLASH_Msk (0x01 << SYS_RSTCR_NORFLASH_Pos) +#define SYS_RSTCR_SRAM_Pos 6 //写1对SRAM控制器进行一次复位,硬件自动清零 +#define SYS_RSTCR_SRAM_Msk (0x01 << SYS_RSTCR_SRAM_Pos) +#define SYS_RSTCR_SDRAM_Pos 7 //写1对SDRAM控制器进行一次复位,硬件自动清零 +#define SYS_RSTCR_SDRAM_Msk (0x01 << SYS_RSTCR_SDRAM_Pos) +#define SYS_RSTCR_SDIO_Pos 8 //写1对SDIO进行一次复位,硬件自动清零 +#define SYS_RSTCR_SDIO_Msk (0x01 << SYS_RSTCR_SDIO_Pos) +#define SYS_RSTCR_LCD_Pos 9 //写1对LCD进行一次复位,硬件自动清零 +#define SYS_RSTCR_LCD_Msk (0x01 << SYS_RSTCR_LCD_Pos) +#define SYS_RSTCR_CAN_Pos 10 //写1对CAN进行一次复位,硬件自动清零 +#define SYS_RSTCR_CAN_Msk (0x01 << SYS_RSTCR_CAN_Pos) -#define SYS_RSTCR_SYS_Pos 0 //写1进行系统复位,硬件自动清零 -#define SYS_RSTCR_SYS_Msk (0x01 << SYS_RSTCR_SYS_Pos) -#define SYS_RSTCR_FLASH_Pos 1 //写1对FLASH控制器进行一次复位,硬件自动清零 -#define SYS_RSTCR_FLASH_Msk (0x01 << SYS_RSTCR_FLASH_Pos) -#define SYS_RSTCR_PWM_Pos 2 //写1对PWM进行一次复位,硬件自动清零 -#define SYS_RSTCR_PWM_Msk (0x01 << SYS_RSTCR_PWM_Pos) -#define SYS_RSTCR_CPU_Pos 3 //写1对CPU进行一次复位,硬件自动清零 -#define SYS_RSTCR_CPU_Msk (0x01 << SYS_RSTCR_CPU_Pos) -#define SYS_RSTCR_DMA_Pos 4 //写1对DMA进行一次复位,硬件自动清零 -#define SYS_RSTCR_DMA_Msk (0x01 << SYS_RSTCR_DMA_Pos) -#define SYS_RSTCR_NORFLASH_Pos 5 //写1对NOR Flash控制器进行一次复位,硬件自动清零 -#define SYS_RSTCR_NORFLASH_Msk (0x01 << SYS_RSTCR_NORFLASH_Pos) -#define SYS_RSTCR_SRAM_Pos 6 //写1对SRAM控制器进行一次复位,硬件自动清零 -#define SYS_RSTCR_SRAM_Msk (0x01 << SYS_RSTCR_SRAM_Pos) -#define SYS_RSTCR_SDRAM_Pos 7 //写1对SDRAM控制器进行一次复位,硬件自动清零 -#define SYS_RSTCR_SDRAM_Msk (0x01 << SYS_RSTCR_SDRAM_Pos) -#define SYS_RSTCR_SDIO_Pos 8 //写1对SDIO进行一次复位,硬件自动清零 -#define SYS_RSTCR_SDIO_Msk (0x01 << SYS_RSTCR_SDIO_Pos) -#define SYS_RSTCR_LCD_Pos 9 //写1对LCD进行一次复位,硬件自动清零 -#define SYS_RSTCR_LCD_Msk (0x01 << SYS_RSTCR_LCD_Pos) -#define SYS_RSTCR_CAN_Pos 10 //写1对CAN进行一次复位,硬件自动清零 -#define SYS_RSTCR_CAN_Msk (0x01 << SYS_RSTCR_CAN_Pos) +#define SYS_RSTSR_POR_Pos 0 //1 出现过POR复位,写1清零 +#define SYS_RSTSR_POR_Msk (0x01 << SYS_RSTSR_POR_Pos) +#define SYS_RSTSR_BOD_Pos 1 //1 出现过BOD复位,写1清零 +#define SYS_RSTSR_BOD_Msk (0x01 << SYS_RSTSR_BOD_Pos) +#define SYS_RSTSR_PIN_Pos 2 //1 出现过外部引脚复位,写1清零 +#define SYS_RSTSR_PIN_Msk (0x01 << SYS_RSTSR_PIN_Pos) +#define SYS_RSTSR_WDT_Pos 3 //1 出现过WDT复位,写1清零 +#define SYS_RSTSR_WDT_Msk (0x01 << SYS_RSTSR_WDT_Pos) +#define SYS_RSTSR_SWRST_Pos 4 //Software Reset, 1 出现过软件复位,写1清零 +#define SYS_RSTSR_SWRST_Msk (0x01 << SYS_RSTSR_SWRST_Pos) -#define SYS_RSTSR_POR_Pos 0 //1 出现过POR复位,写1清零 -#define SYS_RSTSR_POR_Msk (0x01 << SYS_RSTSR_POR_Pos) -#define SYS_RSTSR_BOD_Pos 1 //1 出现过BOD复位,写1清零 -#define SYS_RSTSR_BOD_Msk (0x01 << SYS_RSTSR_BOD_Pos) -#define SYS_RSTSR_PIN_Pos 2 //1 出现过外部引脚复位,写1清零 -#define SYS_RSTSR_PIN_Msk (0x01 << SYS_RSTSR_PIN_Pos) -#define SYS_RSTSR_WDT_Pos 3 //1 出现过WDT复位,写1清零 -#define SYS_RSTSR_WDT_Msk (0x01 << SYS_RSTSR_WDT_Pos) -#define SYS_RSTSR_SWRST_Pos 4 //Software Reset, 1 出现过软件复位,写1清零 -#define SYS_RSTSR_SWRST_Msk (0x01 << SYS_RSTSR_SWRST_Pos) +#define SYS_LRCCR_OFF_Pos 0 //Low Speed RC Off +#define SYS_LRCCR_OFF_Msk (0x01 << SYS_LRCCR_OFF_Pos) -#define SYS_LRCCR_OFF_Pos 0 //Low Speed RC Off -#define SYS_LRCCR_OFF_Msk (0x01 << SYS_LRCCR_OFF_Pos) +#define SYS_LRCTRIM0_R_Pos 0 //LRC粗调控制位 +#define SYS_LRCTRIM0_R_Msk (0x7FFF << SYS_LRCTRIM0_R_Pos) +#define SYS_LRCTRIM0_M_Pos 15 //LRC中调控制位 +#define SYS_LRCTRIM0_M_Msk (0x3F << SYS_LRCTRIM2_M_Pos) +#define SYS_LRCTRIM0_F_Pos 21 //LRC细调控制位 +#define SYS_LRCTRIM0_F_Msk (0x7FF << SYS_LRCTRIM0_F_Pos) -#define SYS_LRCTRIM0_R_Pos 0 //LRC粗调控制位 -#define SYS_LRCTRIM0_R_Msk (0x7FFF << SYS_LRCTRIM0_R_Pos) -#define SYS_LRCTRIM0_M_Pos 15 //LRC中调控制位 -#define SYS_LRCTRIM0_M_Msk (0x3F << SYS_LRCTRIM2_M_Pos) -#define SYS_LRCTRIM0_F_Pos 21 //LRC细调控制位 -#define SYS_LRCTRIM0_F_Msk (0x7FF << SYS_LRCTRIM0_F_Pos) +#define SYS_LRCTRIM1_U_Pos 0 //LRC U调控制位 +#define SYS_LRCTRIM1_U_Msk (0x7FFF << SYS_LRCTRIM1_U_Pos) -#define SYS_LRCTRIM1_U_Pos 0 //LRC U调控制位 -#define SYS_LRCTRIM1_U_Msk (0x7FFF << SYS_LRCTRIM1_U_Pos) +#define SYS_HRCCR_DBL_Pos 0 //Double Frequency 0 20MHz 1 40MHz +#define SYS_HRCCR_DBL_Msk (0x01 << SYS_HRCCR_DBL_Pos) +#define SYS_HRCCR_OFF_Pos 1 //High speed RC Off +#define SYS_HRCCR_OFF_Msk (0x01 << SYS_HRCCR_OFF_Pos) +#define SYS_XTALCR_EN_Pos 0 +#define SYS_XTALCR_EN_Msk (0x01 << SYS_XTALCR_EN_Pos) -#define SYS_HRCCR_DBL_Pos 0 //Double Frequency 0 20MHz 1 40MHz -#define SYS_HRCCR_DBL_Msk (0x01 << SYS_HRCCR_DBL_Pos) -#define SYS_HRCCR_OFF_Pos 1 //High speed RC Off -#define SYS_HRCCR_OFF_Msk (0x01 << SYS_HRCCR_OFF_Pos) +#define SYS_PLLCR_OUTEN_Pos 0 //只能LOCK后设置 +#define SYS_PLLCR_OUTEN_Msk (0x01 << SYS_PLLCR_OUTEN_Pos) +#define SYS_PLLCR_INSEL_Pos 1 //0 XTAL 1 HRC +#define SYS_PLLCR_INSEL_Msk (0x01 << SYS_PLLCR_INSEL_Pos) +#define SYS_PLLCR_OFF_Pos 2 +#define SYS_PLLCR_OFF_Msk (0x01 << SYS_PLLCR_OFF_Pos) -#define SYS_XTALCR_EN_Pos 0 -#define SYS_XTALCR_EN_Msk (0x01 << SYS_XTALCR_EN_Pos) +#define SYS_PLLDIV_FBDIV_Pos 0 //PLL FeedBack分频寄存器 \ + //VCO输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV \ + //PLL输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV / OUTDIV = VCO输出频率 / OUTDIV +#define SYS_PLLDIV_FBDIV_Msk (0x1FF << SYS_PLLDIV_FBDIV_Pos) +#define SYS_PLLDIV_ADDIV_Pos 9 //ADC时钟基(即VCO输出分频后的时钟)经ADDIV分频后作为ADC的转换时钟 +#define SYS_PLLDIV_ADDIV_Msk (0x1F << SYS_PLLDIV_ADDIV_Pos) +#define SYS_PLLDIV_ADVCO_Pos 14 //0 VCO输出16分频作为ADC时钟基 1 VCO输出经过32分频作为ADC时钟基 2 VCO输出经过64分频作为ADC时钟基 +#define SYS_PLLDIV_ADVCO_Msk (0x03 << SYS_PLLDIV_ADVCO_Pos) +#define SYS_PLLDIV_INDIV_Pos 16 //PLL 输入源时钟分频 +#define SYS_PLLDIV_INDIV_Msk (0x1F << SYS_PLLDIV_INDIV_Pos) +#define SYS_PLLDIV_OUTDIV_Pos 24 //PLL 输出分频,0 8分频 1 4分频 0 2分频 +#define SYS_PLLDIV_OUTDIV_Msk (0x03 << SYS_PLLDIV_OUTDIV_Pos) -#define SYS_PLLCR_OUTEN_Pos 0 //只能LOCK后设置 -#define SYS_PLLCR_OUTEN_Msk (0x01 << SYS_PLLCR_OUTEN_Pos) -#define SYS_PLLCR_INSEL_Pos 1 //0 XTAL 1 HRC -#define SYS_PLLCR_INSEL_Msk (0x01 << SYS_PLLCR_INSEL_Pos) -#define SYS_PLLCR_OFF_Pos 2 -#define SYS_PLLCR_OFF_Msk (0x01 << SYS_PLLCR_OFF_Pos) +#define SYS_PLLSET_LPFBW_Pos 0 //PLL Low Pass Filter Bandwidth +#define SYS_PLLSET_LPFBW_Msk (0x0F << SYS_PLLSET_LPFBW_Pos) +#define SYS_PLLSET_BIASADJ_Pos 4 //PLL Current Bias Adjustment +#define SYS_PLLSET_BIASADJ_Msk (0x03 << SYS_PLLSET_BIASADJ_Pos) +#define SYS_PLLSET_REFVSEL_Pos 6 //PLL Reference Voltage Select +#define SYS_PLLSET_REFVSEL_Msk (0x03 << SYS_PLLSET_REFVSEL_Pos) +#define SYS_PLLSET_CHPADJL_Pos 8 //PLL charge pump LSB current Adjustment +#define SYS_PLLSET_CHPADJL_Msk (0x07 << SYS_PLLSET_CHPADJL_Pos) +#define SYS_PLLSET_CHPADJM_Pos 11 //PLL charge pump MSB current Adjustment +#define SYS_PLLSET_CHPADJM_Msk (0x03 << SYS_PLLSET_CHPADJM_Pos) -#define SYS_PLLDIV_FBDIV_Pos 0 //PLL FeedBack分频寄存器 - //VCO输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV - //PLL输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV / OUTDIV = VCO输出频率 / OUTDIV -#define SYS_PLLDIV_FBDIV_Msk (0x1FF << SYS_PLLDIV_FBDIV_Pos) -#define SYS_PLLDIV_ADDIV_Pos 9 //ADC时钟基(即VCO输出分频后的时钟)经ADDIV分频后作为ADC的转换时钟 -#define SYS_PLLDIV_ADDIV_Msk (0x1F << SYS_PLLDIV_ADDIV_Pos) -#define SYS_PLLDIV_ADVCO_Pos 14 //0 VCO输出16分频作为ADC时钟基 1 VCO输出经过32分频作为ADC时钟基 2 VCO输出经过64分频作为ADC时钟基 -#define SYS_PLLDIV_ADVCO_Msk (0x03 << SYS_PLLDIV_ADVCO_Pos) -#define SYS_PLLDIV_INDIV_Pos 16 //PLL 输入源时钟分频 -#define SYS_PLLDIV_INDIV_Msk (0x1F << SYS_PLLDIV_INDIV_Pos) -#define SYS_PLLDIV_OUTDIV_Pos 24 //PLL 输出分频,0 8分频 1 4分频 0 2分频 -#define SYS_PLLDIV_OUTDIV_Msk (0x03 << SYS_PLLDIV_OUTDIV_Pos) +#define SYS_BODIE_2V2_Pos 1 //BOD 2.2V等级触发中断使能 +#define SYS_BODIE_2V2_Msk (0x01 << SYS_BODIE_2V2_Pos) -#define SYS_PLLSET_LPFBW_Pos 0 //PLL Low Pass Filter Bandwidth -#define SYS_PLLSET_LPFBW_Msk (0x0F << SYS_PLLSET_LPFBW_Pos) -#define SYS_PLLSET_BIASADJ_Pos 4 //PLL Current Bias Adjustment -#define SYS_PLLSET_BIASADJ_Msk (0x03 << SYS_PLLSET_BIASADJ_Pos) -#define SYS_PLLSET_REFVSEL_Pos 6 //PLL Reference Voltage Select -#define SYS_PLLSET_REFVSEL_Msk (0x03 << SYS_PLLSET_REFVSEL_Pos) -#define SYS_PLLSET_CHPADJL_Pos 8 //PLL charge pump LSB current Adjustment -#define SYS_PLLSET_CHPADJL_Msk (0x07 << SYS_PLLSET_CHPADJL_Pos) -#define SYS_PLLSET_CHPADJM_Pos 11 //PLL charge pump MSB current Adjustment -#define SYS_PLLSET_CHPADJM_Msk (0x03 << SYS_PLLSET_CHPADJM_Pos) +#define SYS_BODIF_2V2_Pos 1 //BOD 2.2V等级触发中断状态,写1清零 +#define SYS_BODIF_2V2_Msk (0x01 << SYS_BODIF_2V2_Pos) -#define SYS_BODIE_2V2_Pos 1 //BOD 2.2V等级触发中断使能 -#define SYS_BODIE_2V2_Msk (0x01 << SYS_BODIE_2V2_Pos) +#define SYS_ADC1IN7_SEL_Pos 0 //ADC1模块模拟通道7,1 温度传感器 2 电池电压 3 RTC电源域BG 4 主电源域BG 5 PDM33 +#define SYS_ADC1IN7_SEL_Msk (0x0F << SYS_ADC1IN7_SEL_Pos) +#define SYS_ADC1IN7_IOON_Pos 4 //ADC1模块模拟通道7所用IO开关 +#define SYS_ADC1IN7_IOON_Msk (0x01 << SYS_ADC1IN7_IOON_Pos) -#define SYS_BODIF_2V2_Pos 1 //BOD 2.2V等级触发中断状态,写1清零 -#define SYS_BODIF_2V2_Msk (0x01 << SYS_BODIF_2V2_Pos) +typedef struct +{ + __IO uint32_t PORTA_SEL; //给PORTA_SEL[2n+2:2n]赋相应的值,将PORTA.PINn引脚配置成GPIO、模拟、数字等功能 + //当赋值为PORTA_PINn_FUNMUX时,PORTA.PINn引脚可通过PORTA_MUX寄存器连接到各种数字外设 + __IO uint32_t PORTB_SEL; -#define SYS_ADC1IN7_SEL_Pos 0 //ADC1模块模拟通道7,1 温度传感器 2 电池电压 3 RTC电源域BG 4 主电源域BG 5 PDM33 -#define SYS_ADC1IN7_SEL_Msk (0x0F << SYS_ADC1IN7_SEL_Pos) -#define SYS_ADC1IN7_IOON_Pos 4 //ADC1模块模拟通道7所用IO开关 -#define SYS_ADC1IN7_IOON_Msk (0x01 << SYS_ADC1IN7_IOON_Pos) - - - - -typedef struct { - __IO uint32_t PORTA_SEL; //给PORTA_SEL[2n+2:2n]赋相应的值,将PORTA.PINn引脚配置成GPIO、模拟、数字等功能 - //当赋值为PORTA_PINn_FUNMUX时,PORTA.PINn引脚可通过PORTA_MUX寄存器连接到各种数字外设 - __IO uint32_t PORTB_SEL; - __IO uint32_t PORTC_SEL; - - uint32_t RESERVED[5]; - - __IO uint32_t PORTM_SEL0; - + + uint32_t RESERVED[5]; + + __IO uint32_t PORTM_SEL0; + __IO uint32_t PORTM_SEL1; - - uint32_t RESERVED2[2]; - + + uint32_t RESERVED2[2]; + __IO uint32_t PORTN_SEL0; - + __IO uint32_t PORTN_SEL1; - - uint32_t RESERVED3[2]; - + + uint32_t RESERVED3[2]; + __IO uint32_t PORTP_SEL0; - + __IO uint32_t PORTP_SEL1; - - uint32_t RESERVED4[46]; - + + uint32_t RESERVED4[46]; + __IO uint32_t PORTA_MUX0; - + __IO uint32_t PORTA_MUX1; - - uint32_t RESERVED5[2]; - + + uint32_t RESERVED5[2]; + __IO uint32_t PORTB_MUX0; - + __IO uint32_t PORTB_MUX1; - - uint32_t RESERVED6[2]; - + + uint32_t RESERVED6[2]; + __IO uint32_t PORTC_MUX0; - + __IO uint32_t PORTC_MUX1; - - uint32_t RESERVED7[14]; - + + uint32_t RESERVED7[14]; + __IO uint32_t PORTM_MUX0; - + __IO uint32_t PORTM_MUX1; __IO uint32_t PORTM_MUX2; - + __IO uint32_t PORTM_MUX3; - + __IO uint32_t PORTN_MUX0; - + __IO uint32_t PORTN_MUX1; - + __IO uint32_t PORTN_MUX2; - - uint32_t RESERVED8; - + + uint32_t RESERVED8; + __IO uint32_t PORTP_MUX0; - + __IO uint32_t PORTP_MUX1; - + __IO uint32_t PORTP_MUX2; - + __IO uint32_t PORTP_MUX3; - - uint32_t RESERVED9[28]; - - __IO uint32_t PORTA_PULLU; //上拉使能 - - uint32_t RESERVED10[3]; - + + uint32_t RESERVED9[28]; + + __IO uint32_t PORTA_PULLU; //上拉使能 + + uint32_t RESERVED10[3]; + __IO uint32_t PORTC_PULLU; - - uint32_t RESERVED11[3]; + + uint32_t RESERVED11[3]; __IO uint32_t PORTM_PULLU; - - uint32_t RESERVED12[3]; + + uint32_t RESERVED12[3]; __IO uint32_t PORTP_PULLU; - - uint32_t RESERVED13[51]; - - __IO uint32_t PORTB_PULLD; //下拉使能 - - uint32_t RESERVED14[3]; + + uint32_t RESERVED13[51]; + + __IO uint32_t PORTB_PULLD; //下拉使能 + + uint32_t RESERVED14[3]; __IO uint32_t PORTD_PULLD; - - uint32_t RESERVED15[3]; + + uint32_t RESERVED15[3]; __IO uint32_t PORTN_PULLD; - - uint32_t RESERVED16[135]; - - __IO uint32_t PORTM_DRIVS; //驱动强度 - - uint32_t RESERVED17[3]; + + uint32_t RESERVED16[135]; + + __IO uint32_t PORTM_DRIVS; //驱动强度 + + uint32_t RESERVED17[3]; __IO uint32_t PORTN_DRIVS; - - uint32_t RESERVED18[3]; + + uint32_t RESERVED18[3]; __IO uint32_t PORTP_DRIVS; - - uint32_t RESERVED19[39]; - - __IO uint32_t PORTA_INEN; //输入使能 - - uint32_t RESERVED20[3]; - + + uint32_t RESERVED19[39]; + + __IO uint32_t PORTA_INEN; //输入使能 + + uint32_t RESERVED20[3]; + __IO uint32_t PORTB_INEN; - - uint32_t RESERVED21[3]; + + uint32_t RESERVED21[3]; __IO uint32_t PORTC_INEN; - - uint32_t RESERVED22[7]; + + uint32_t RESERVED22[7]; __IO uint32_t PORTM_INEN; - - uint32_t RESERVED23[3]; - + + uint32_t RESERVED23[3]; + __IO uint32_t PORTN_INEN; - - uint32_t RESERVED24[3]; + + uint32_t RESERVED24[3]; __IO uint32_t PORTP_INEN; } PORT_TypeDef; +#define PORT_PORTA_PULLU_PIN0_Pos 0 +#define PORT_PORTA_PULLU_PIN0_Msk (0x01 << PORT_PORTA_PULLU_PIN0_Pos) +#define PORT_PORTA_PULLU_PIN1_Pos 1 +#define PORT_PORTA_PULLU_PIN1_Msk (0x01 << PORT_PORTA_PULLU_PIN1_Pos) +#define PORT_PORTA_PULLU_PIN2_Pos 2 +#define PORT_PORTA_PULLU_PIN2_Msk (0x01 << PORT_PORTA_PULLU_PIN2_Pos) +#define PORT_PORTA_PULLU_PIN3_Pos 3 +#define PORT_PORTA_PULLU_PIN3_Msk (0x01 << PORT_PORTA_PULLU_PIN3_Pos) +#define PORT_PORTA_PULLU_PIN4_Pos 4 +#define PORT_PORTA_PULLU_PIN4_Msk (0x01 << PORT_PORTA_PULLU_PIN4_Pos) +#define PORT_PORTA_PULLU_PIN5_Pos 5 +#define PORT_PORTA_PULLU_PIN5_Msk (0x01 << PORT_PORTA_PULLU_PIN5_Pos) +#define PORT_PORTA_PULLU_PIN6_Pos 6 +#define PORT_PORTA_PULLU_PIN6_Msk (0x01 << PORT_PORTA_PULLU_PIN6_Pos) +#define PORT_PORTA_PULLU_PIN7_Pos 7 +#define PORT_PORTA_PULLU_PIN7_Msk (0x01 << PORT_PORTA_PULLU_PIN7_Pos) +#define PORT_PORTA_PULLU_PIN8_Pos 8 +#define PORT_PORTA_PULLU_PIN8_Msk (0x01 << PORT_PORTA_PULLU_PIN8_Pos) +#define PORT_PORTA_PULLU_PIN9_Pos 9 +#define PORT_PORTA_PULLU_PIN9_Msk (0x01 << PORT_PORTA_PULLU_PIN9_Pos) +#define PORT_PORTA_PULLU_PIN10_Pos 10 +#define PORT_PORTA_PULLU_PIN10_Msk (0x01 << PORT_PORTA_PULLU_PIN10_Pos) +#define PORT_PORTA_PULLU_PIN11_Pos 11 +#define PORT_PORTA_PULLU_PIN11_Msk (0x01 << PORT_PORTA_PULLU_PIN11_Pos) +#define PORT_PORTA_PULLU_PIN12_Pos 12 +#define PORT_PORTA_PULLU_PIN12_Msk (0x01 << PORT_PORTA_PULLU_PIN12_Pos) +#define PORT_PORTA_PULLU_PIN13_Pos 13 +#define PORT_PORTA_PULLU_PIN13_Msk (0x01 << PORT_PORTA_PULLU_PIN13_Pos) +#define PORT_PORTA_PULLU_PIN14_Pos 14 +#define PORT_PORTA_PULLU_PIN14_Msk (0x01 << PORT_PORTA_PULLU_PIN14_Pos) +#define PORT_PORTA_PULLU_PIN15_Pos 15 +#define PORT_PORTA_PULLU_PIN15_Msk (0x01 << PORT_PORTA_PULLU_PIN15_Pos) -#define PORT_PORTA_PULLU_PIN0_Pos 0 -#define PORT_PORTA_PULLU_PIN0_Msk (0x01 << PORT_PORTA_PULLU_PIN0_Pos) -#define PORT_PORTA_PULLU_PIN1_Pos 1 -#define PORT_PORTA_PULLU_PIN1_Msk (0x01 << PORT_PORTA_PULLU_PIN1_Pos) -#define PORT_PORTA_PULLU_PIN2_Pos 2 -#define PORT_PORTA_PULLU_PIN2_Msk (0x01 << PORT_PORTA_PULLU_PIN2_Pos) -#define PORT_PORTA_PULLU_PIN3_Pos 3 -#define PORT_PORTA_PULLU_PIN3_Msk (0x01 << PORT_PORTA_PULLU_PIN3_Pos) -#define PORT_PORTA_PULLU_PIN4_Pos 4 -#define PORT_PORTA_PULLU_PIN4_Msk (0x01 << PORT_PORTA_PULLU_PIN4_Pos) -#define PORT_PORTA_PULLU_PIN5_Pos 5 -#define PORT_PORTA_PULLU_PIN5_Msk (0x01 << PORT_PORTA_PULLU_PIN5_Pos) -#define PORT_PORTA_PULLU_PIN6_Pos 6 -#define PORT_PORTA_PULLU_PIN6_Msk (0x01 << PORT_PORTA_PULLU_PIN6_Pos) -#define PORT_PORTA_PULLU_PIN7_Pos 7 -#define PORT_PORTA_PULLU_PIN7_Msk (0x01 << PORT_PORTA_PULLU_PIN7_Pos) -#define PORT_PORTA_PULLU_PIN8_Pos 8 -#define PORT_PORTA_PULLU_PIN8_Msk (0x01 << PORT_PORTA_PULLU_PIN8_Pos) -#define PORT_PORTA_PULLU_PIN9_Pos 9 -#define PORT_PORTA_PULLU_PIN9_Msk (0x01 << PORT_PORTA_PULLU_PIN9_Pos) -#define PORT_PORTA_PULLU_PIN10_Pos 10 -#define PORT_PORTA_PULLU_PIN10_Msk (0x01 << PORT_PORTA_PULLU_PIN10_Pos) -#define PORT_PORTA_PULLU_PIN11_Pos 11 -#define PORT_PORTA_PULLU_PIN11_Msk (0x01 << PORT_PORTA_PULLU_PIN11_Pos) -#define PORT_PORTA_PULLU_PIN12_Pos 12 -#define PORT_PORTA_PULLU_PIN12_Msk (0x01 << PORT_PORTA_PULLU_PIN12_Pos) -#define PORT_PORTA_PULLU_PIN13_Pos 13 -#define PORT_PORTA_PULLU_PIN13_Msk (0x01 << PORT_PORTA_PULLU_PIN13_Pos) -#define PORT_PORTA_PULLU_PIN14_Pos 14 -#define PORT_PORTA_PULLU_PIN14_Msk (0x01 << PORT_PORTA_PULLU_PIN14_Pos) -#define PORT_PORTA_PULLU_PIN15_Pos 15 -#define PORT_PORTA_PULLU_PIN15_Msk (0x01 << PORT_PORTA_PULLU_PIN15_Pos) +#define PORT_PORTC_PULLU_PIN0_Pos 0 +#define PORT_PORTC_PULLU_PIN0_Msk (0x01 << PORT_PORTC_PULLU_PIN0_Pos) +#define PORT_PORTC_PULLU_PIN1_Pos 1 +#define PORT_PORTC_PULLU_PIN1_Msk (0x01 << PORT_PORTC_PULLU_PIN1_Pos) +#define PORT_PORTC_PULLU_PIN2_Pos 2 +#define PORT_PORTC_PULLU_PIN2_Msk (0x01 << PORT_PORTC_PULLU_PIN2_Pos) +#define PORT_PORTC_PULLU_PIN3_Pos 3 +#define PORT_PORTC_PULLU_PIN3_Msk (0x01 << PORT_PORTC_PULLU_PIN3_Pos) +#define PORT_PORTC_PULLU_PIN4_Pos 4 +#define PORT_PORTC_PULLU_PIN4_Msk (0x01 << PORT_PORTC_PULLU_PIN4_Pos) +#define PORT_PORTC_PULLU_PIN5_Pos 5 +#define PORT_PORTC_PULLU_PIN5_Msk (0x01 << PORT_PORTC_PULLU_PIN5_Pos) +#define PORT_PORTC_PULLU_PIN6_Pos 6 +#define PORT_PORTC_PULLU_PIN6_Msk (0x01 << PORT_PORTC_PULLU_PIN6_Pos) +#define PORT_PORTC_PULLU_PIN7_Pos 7 +#define PORT_PORTC_PULLU_PIN7_Msk (0x01 << PORT_PORTC_PULLU_PIN7_Pos) +#define PORT_PORTC_PULLU_PIN8_Pos 8 +#define PORT_PORTC_PULLU_PIN8_Msk (0x01 << PORT_PORTC_PULLU_PIN8_Pos) +#define PORT_PORTC_PULLU_PIN9_Pos 9 +#define PORT_PORTC_PULLU_PIN9_Msk (0x01 << PORT_PORTC_PULLU_PIN9_Pos) +#define PORT_PORTC_PULLU_PIN10_Pos 10 +#define PORT_PORTC_PULLU_PIN10_Msk (0x01 << PORT_PORTC_PULLU_PIN10_Pos) +#define PORT_PORTC_PULLU_PIN11_Pos 11 +#define PORT_PORTC_PULLU_PIN11_Msk (0x01 << PORT_PORTC_PULLU_PIN11_Pos) +#define PORT_PORTC_PULLU_PIN12_Pos 12 +#define PORT_PORTC_PULLU_PIN12_Msk (0x01 << PORT_PORTC_PULLU_PIN12_Pos) +#define PORT_PORTC_PULLU_PIN13_Pos 13 +#define PORT_PORTC_PULLU_PIN13_Msk (0x01 << PORT_PORTC_PULLU_PIN13_Pos) +#define PORT_PORTC_PULLU_PIN14_Pos 14 +#define PORT_PORTC_PULLU_PIN14_Msk (0x01 << PORT_PORTC_PULLU_PIN14_Pos) +#define PORT_PORTC_PULLU_PIN15_Pos 15 +#define PORT_PORTC_PULLU_PIN15_Msk (0x01 << PORT_PORTC_PULLU_PIN15_Pos) -#define PORT_PORTC_PULLU_PIN0_Pos 0 -#define PORT_PORTC_PULLU_PIN0_Msk (0x01 << PORT_PORTC_PULLU_PIN0_Pos) -#define PORT_PORTC_PULLU_PIN1_Pos 1 -#define PORT_PORTC_PULLU_PIN1_Msk (0x01 << PORT_PORTC_PULLU_PIN1_Pos) -#define PORT_PORTC_PULLU_PIN2_Pos 2 -#define PORT_PORTC_PULLU_PIN2_Msk (0x01 << PORT_PORTC_PULLU_PIN2_Pos) -#define PORT_PORTC_PULLU_PIN3_Pos 3 -#define PORT_PORTC_PULLU_PIN3_Msk (0x01 << PORT_PORTC_PULLU_PIN3_Pos) -#define PORT_PORTC_PULLU_PIN4_Pos 4 -#define PORT_PORTC_PULLU_PIN4_Msk (0x01 << PORT_PORTC_PULLU_PIN4_Pos) -#define PORT_PORTC_PULLU_PIN5_Pos 5 -#define PORT_PORTC_PULLU_PIN5_Msk (0x01 << PORT_PORTC_PULLU_PIN5_Pos) -#define PORT_PORTC_PULLU_PIN6_Pos 6 -#define PORT_PORTC_PULLU_PIN6_Msk (0x01 << PORT_PORTC_PULLU_PIN6_Pos) -#define PORT_PORTC_PULLU_PIN7_Pos 7 -#define PORT_PORTC_PULLU_PIN7_Msk (0x01 << PORT_PORTC_PULLU_PIN7_Pos) -#define PORT_PORTC_PULLU_PIN8_Pos 8 -#define PORT_PORTC_PULLU_PIN8_Msk (0x01 << PORT_PORTC_PULLU_PIN8_Pos) -#define PORT_PORTC_PULLU_PIN9_Pos 9 -#define PORT_PORTC_PULLU_PIN9_Msk (0x01 << PORT_PORTC_PULLU_PIN9_Pos) -#define PORT_PORTC_PULLU_PIN10_Pos 10 -#define PORT_PORTC_PULLU_PIN10_Msk (0x01 << PORT_PORTC_PULLU_PIN10_Pos) -#define PORT_PORTC_PULLU_PIN11_Pos 11 -#define PORT_PORTC_PULLU_PIN11_Msk (0x01 << PORT_PORTC_PULLU_PIN11_Pos) -#define PORT_PORTC_PULLU_PIN12_Pos 12 -#define PORT_PORTC_PULLU_PIN12_Msk (0x01 << PORT_PORTC_PULLU_PIN12_Pos) -#define PORT_PORTC_PULLU_PIN13_Pos 13 -#define PORT_PORTC_PULLU_PIN13_Msk (0x01 << PORT_PORTC_PULLU_PIN13_Pos) -#define PORT_PORTC_PULLU_PIN14_Pos 14 -#define PORT_PORTC_PULLU_PIN14_Msk (0x01 << PORT_PORTC_PULLU_PIN14_Pos) -#define PORT_PORTC_PULLU_PIN15_Pos 15 -#define PORT_PORTC_PULLU_PIN15_Msk (0x01 << PORT_PORTC_PULLU_PIN15_Pos) +#define PORT_PORTM_PULLU_PIN0_Pos 0 +#define PORT_PORTM_PULLU_PIN0_Msk (0x01 << PORT_PORTM_PULLU_PIN0_Pos) +#define PORT_PORTM_PULLU_PIN1_Pos 1 +#define PORT_PORTM_PULLU_PIN1_Msk (0x01 << PORT_PORTM_PULLU_PIN1_Pos) +#define PORT_PORTM_PULLU_PIN2_Pos 2 +#define PORT_PORTM_PULLU_PIN2_Msk (0x01 << PORT_PORTM_PULLU_PIN2_Pos) +#define PORT_PORTM_PULLU_PIN3_Pos 3 +#define PORT_PORTM_PULLU_PIN3_Msk (0x01 << PORT_PORTM_PULLU_PIN3_Pos) +#define PORT_PORTM_PULLU_PIN4_Pos 4 +#define PORT_PORTM_PULLU_PIN4_Msk (0x01 << PORT_PORTM_PULLU_PIN4_Pos) +#define PORT_PORTM_PULLU_PIN5_Pos 5 +#define PORT_PORTM_PULLU_PIN5_Msk (0x01 << PORT_PORTM_PULLU_PIN5_Pos) +#define PORT_PORTM_PULLU_PIN6_Pos 6 +#define PORT_PORTM_PULLU_PIN6_Msk (0x01 << PORT_PORTM_PULLU_PIN6_Pos) +#define PORT_PORTM_PULLU_PIN7_Pos 7 +#define PORT_PORTM_PULLU_PIN7_Msk (0x01 << PORT_PORTM_PULLU_PIN7_Pos) +#define PORT_PORTM_PULLU_PIN8_Pos 8 +#define PORT_PORTM_PULLU_PIN8_Msk (0x01 << PORT_PORTM_PULLU_PIN8_Pos) +#define PORT_PORTM_PULLU_PIN9_Pos 9 +#define PORT_PORTM_PULLU_PIN9_Msk (0x01 << PORT_PORTM_PULLU_PIN9_Pos) +#define PORT_PORTM_PULLU_PIN10_Pos 10 +#define PORT_PORTM_PULLU_PIN10_Msk (0x01 << PORT_PORTM_PULLU_PIN10_Pos) +#define PORT_PORTM_PULLU_PIN11_Pos 11 +#define PORT_PORTM_PULLU_PIN11_Msk (0x01 << PORT_PORTM_PULLU_PIN11_Pos) +#define PORT_PORTM_PULLU_PIN12_Pos 12 +#define PORT_PORTM_PULLU_PIN12_Msk (0x01 << PORT_PORTM_PULLU_PIN12_Pos) +#define PORT_PORTM_PULLU_PIN13_Pos 13 +#define PORT_PORTM_PULLU_PIN13_Msk (0x01 << PORT_PORTM_PULLU_PIN13_Pos) +#define PORT_PORTM_PULLU_PIN14_Pos 14 +#define PORT_PORTM_PULLU_PIN14_Msk (0x01 << PORT_PORTM_PULLU_PIN14_Pos) +#define PORT_PORTM_PULLU_PIN15_Pos 15 +#define PORT_PORTM_PULLU_PIN15_Msk (0x01 << PORT_PORTM_PULLU_PIN15_Pos) +#define PORT_PORTM_PULLU_PIN16_Pos 16 +#define PORT_PORTM_PULLU_PIN16_Msk (0x01 << PORT_PORTM_PULLU_PIN16_Pos) +#define PORT_PORTM_PULLU_PIN17_Pos 17 +#define PORT_PORTM_PULLU_PIN17_Msk (0x01 << PORT_PORTM_PULLU_PIN17_Pos) +#define PORT_PORTM_PULLU_PIN18_Pos 18 +#define PORT_PORTM_PULLU_PIN18_Msk (0x01 << PORT_PORTM_PULLU_PIN18_Pos) +#define PORT_PORTM_PULLU_PIN19_Pos 19 +#define PORT_PORTM_PULLU_PIN19_Msk (0x01 << PORT_PORTM_PULLU_PIN19_Pos) +#define PORT_PORTM_PULLU_PIN20_Pos 20 +#define PORT_PORTM_PULLU_PIN20_Msk (0x01 << PORT_PORTM_PULLU_PIN20_Pos) +#define PORT_PORTM_PULLU_PIN21_Pos 21 +#define PORT_PORTM_PULLU_PIN21_Msk (0x01 << PORT_PORTM_PULLU_PIN21_Pos) +#define PORT_PORTM_PULLU_PIN22_Pos 22 +#define PORT_PORTM_PULLU_PIN22_Msk (0x01 << PORT_PORTM_PULLU_PIN22_Pos) +#define PORT_PORTM_PULLU_PIN23_Pos 23 +#define PORT_PORTM_PULLU_PIN23_Msk (0x01 << PORT_PORTM_PULLU_PIN23_Pos) -#define PORT_PORTM_PULLU_PIN0_Pos 0 -#define PORT_PORTM_PULLU_PIN0_Msk (0x01 << PORT_PORTM_PULLU_PIN0_Pos) -#define PORT_PORTM_PULLU_PIN1_Pos 1 -#define PORT_PORTM_PULLU_PIN1_Msk (0x01 << PORT_PORTM_PULLU_PIN1_Pos) -#define PORT_PORTM_PULLU_PIN2_Pos 2 -#define PORT_PORTM_PULLU_PIN2_Msk (0x01 << PORT_PORTM_PULLU_PIN2_Pos) -#define PORT_PORTM_PULLU_PIN3_Pos 3 -#define PORT_PORTM_PULLU_PIN3_Msk (0x01 << PORT_PORTM_PULLU_PIN3_Pos) -#define PORT_PORTM_PULLU_PIN4_Pos 4 -#define PORT_PORTM_PULLU_PIN4_Msk (0x01 << PORT_PORTM_PULLU_PIN4_Pos) -#define PORT_PORTM_PULLU_PIN5_Pos 5 -#define PORT_PORTM_PULLU_PIN5_Msk (0x01 << PORT_PORTM_PULLU_PIN5_Pos) -#define PORT_PORTM_PULLU_PIN6_Pos 6 -#define PORT_PORTM_PULLU_PIN6_Msk (0x01 << PORT_PORTM_PULLU_PIN6_Pos) -#define PORT_PORTM_PULLU_PIN7_Pos 7 -#define PORT_PORTM_PULLU_PIN7_Msk (0x01 << PORT_PORTM_PULLU_PIN7_Pos) -#define PORT_PORTM_PULLU_PIN8_Pos 8 -#define PORT_PORTM_PULLU_PIN8_Msk (0x01 << PORT_PORTM_PULLU_PIN8_Pos) -#define PORT_PORTM_PULLU_PIN9_Pos 9 -#define PORT_PORTM_PULLU_PIN9_Msk (0x01 << PORT_PORTM_PULLU_PIN9_Pos) -#define PORT_PORTM_PULLU_PIN10_Pos 10 -#define PORT_PORTM_PULLU_PIN10_Msk (0x01 << PORT_PORTM_PULLU_PIN10_Pos) -#define PORT_PORTM_PULLU_PIN11_Pos 11 -#define PORT_PORTM_PULLU_PIN11_Msk (0x01 << PORT_PORTM_PULLU_PIN11_Pos) -#define PORT_PORTM_PULLU_PIN12_Pos 12 -#define PORT_PORTM_PULLU_PIN12_Msk (0x01 << PORT_PORTM_PULLU_PIN12_Pos) -#define PORT_PORTM_PULLU_PIN13_Pos 13 -#define PORT_PORTM_PULLU_PIN13_Msk (0x01 << PORT_PORTM_PULLU_PIN13_Pos) -#define PORT_PORTM_PULLU_PIN14_Pos 14 -#define PORT_PORTM_PULLU_PIN14_Msk (0x01 << PORT_PORTM_PULLU_PIN14_Pos) -#define PORT_PORTM_PULLU_PIN15_Pos 15 -#define PORT_PORTM_PULLU_PIN15_Msk (0x01 << PORT_PORTM_PULLU_PIN15_Pos) -#define PORT_PORTM_PULLU_PIN16_Pos 16 -#define PORT_PORTM_PULLU_PIN16_Msk (0x01 << PORT_PORTM_PULLU_PIN16_Pos) -#define PORT_PORTM_PULLU_PIN17_Pos 17 -#define PORT_PORTM_PULLU_PIN17_Msk (0x01 << PORT_PORTM_PULLU_PIN17_Pos) -#define PORT_PORTM_PULLU_PIN18_Pos 18 -#define PORT_PORTM_PULLU_PIN18_Msk (0x01 << PORT_PORTM_PULLU_PIN18_Pos) -#define PORT_PORTM_PULLU_PIN19_Pos 19 -#define PORT_PORTM_PULLU_PIN19_Msk (0x01 << PORT_PORTM_PULLU_PIN19_Pos) -#define PORT_PORTM_PULLU_PIN20_Pos 20 -#define PORT_PORTM_PULLU_PIN20_Msk (0x01 << PORT_PORTM_PULLU_PIN20_Pos) -#define PORT_PORTM_PULLU_PIN21_Pos 21 -#define PORT_PORTM_PULLU_PIN21_Msk (0x01 << PORT_PORTM_PULLU_PIN21_Pos) -#define PORT_PORTM_PULLU_PIN22_Pos 22 -#define PORT_PORTM_PULLU_PIN22_Msk (0x01 << PORT_PORTM_PULLU_PIN22_Pos) -#define PORT_PORTM_PULLU_PIN23_Pos 23 -#define PORT_PORTM_PULLU_PIN23_Msk (0x01 << PORT_PORTM_PULLU_PIN23_Pos) +#define PORT_PORTP_PULLU_PIN0_Pos 0 +#define PORT_PORTP_PULLU_PIN0_Msk (0x01 << PORT_PORTP_PULLU_PIN0_Pos) +#define PORT_PORTP_PULLU_PIN1_Pos 1 +#define PORT_PORTP_PULLU_PIN1_Msk (0x01 << PORT_PORTP_PULLU_PIN1_Pos) +#define PORT_PORTP_PULLU_PIN2_Pos 2 +#define PORT_PORTP_PULLU_PIN2_Msk (0x01 << PORT_PORTP_PULLU_PIN2_Pos) +#define PORT_PORTP_PULLU_PIN3_Pos 3 +#define PORT_PORTP_PULLU_PIN3_Msk (0x01 << PORT_PORTP_PULLU_PIN3_Pos) +#define PORT_PORTP_PULLU_PIN4_Pos 4 +#define PORT_PORTP_PULLU_PIN4_Msk (0x01 << PORT_PORTP_PULLU_PIN4_Pos) +#define PORT_PORTP_PULLU_PIN5_Pos 5 +#define PORT_PORTP_PULLU_PIN5_Msk (0x01 << PORT_PORTP_PULLU_PIN5_Pos) +#define PORT_PORTP_PULLU_PIN6_Pos 6 +#define PORT_PORTP_PULLU_PIN6_Msk (0x01 << PORT_PORTP_PULLU_PIN6_Pos) +#define PORT_PORTP_PULLU_PIN7_Pos 7 +#define PORT_PORTP_PULLU_PIN7_Msk (0x01 << PORT_PORTP_PULLU_PIN7_Pos) +#define PORT_PORTP_PULLU_PIN8_Pos 8 +#define PORT_PORTP_PULLU_PIN8_Msk (0x01 << PORT_PORTP_PULLU_PIN8_Pos) +#define PORT_PORTP_PULLU_PIN9_Pos 9 +#define PORT_PORTP_PULLU_PIN9_Msk (0x01 << PORT_PORTP_PULLU_PIN9_Pos) +#define PORT_PORTP_PULLU_PIN10_Pos 10 +#define PORT_PORTP_PULLU_PIN10_Msk (0x01 << PORT_PORTP_PULLU_PIN10_Pos) +#define PORT_PORTP_PULLU_PIN11_Pos 11 +#define PORT_PORTP_PULLU_PIN11_Msk (0x01 << PORT_PORTP_PULLU_PIN11_Pos) +#define PORT_PORTP_PULLU_PIN12_Pos 12 +#define PORT_PORTP_PULLU_PIN12_Msk (0x01 << PORT_PORTP_PULLU_PIN12_Pos) +#define PORT_PORTP_PULLU_PIN13_Pos 13 +#define PORT_PORTP_PULLU_PIN13_Msk (0x01 << PORT_PORTP_PULLU_PIN13_Pos) +#define PORT_PORTP_PULLU_PIN14_Pos 14 +#define PORT_PORTP_PULLU_PIN14_Msk (0x01 << PORT_PORTP_PULLU_PIN14_Pos) +#define PORT_PORTP_PULLU_PIN15_Pos 15 +#define PORT_PORTP_PULLU_PIN15_Msk (0x01 << PORT_PORTP_PULLU_PIN15_Pos) +#define PORT_PORTP_PULLU_PIN16_Pos 16 +#define PORT_PORTP_PULLU_PIN16_Msk (0x01 << PORT_PORTP_PULLU_PIN16_Pos) +#define PORT_PORTP_PULLU_PIN17_Pos 17 +#define PORT_PORTP_PULLU_PIN17_Msk (0x01 << PORT_PORTP_PULLU_PIN17_Pos) +#define PORT_PORTP_PULLU_PIN18_Pos 18 +#define PORT_PORTP_PULLU_PIN18_Msk (0x01 << PORT_PORTP_PULLU_PIN18_Pos) +#define PORT_PORTP_PULLU_PIN19_Pos 19 +#define PORT_PORTP_PULLU_PIN19_Msk (0x01 << PORT_PORTP_PULLU_PIN19_Pos) +#define PORT_PORTP_PULLU_PIN20_Pos 20 +#define PORT_PORTP_PULLU_PIN20_Msk (0x01 << PORT_PORTP_PULLU_PIN20_Pos) +#define PORT_PORTP_PULLU_PIN21_Pos 21 +#define PORT_PORTP_PULLU_PIN21_Msk (0x01 << PORT_PORTP_PULLU_PIN21_Pos) +#define PORT_PORTP_PULLU_PIN22_Pos 22 +#define PORT_PORTP_PULLU_PIN22_Msk (0x01 << PORT_PORTP_PULLU_PIN22_Pos) +#define PORT_PORTP_PULLU_PIN23_Pos 23 +#define PORT_PORTP_PULLU_PIN23_Msk (0x01 << PORT_PORTP_PULLU_PIN23_Pos) -#define PORT_PORTP_PULLU_PIN0_Pos 0 -#define PORT_PORTP_PULLU_PIN0_Msk (0x01 << PORT_PORTP_PULLU_PIN0_Pos) -#define PORT_PORTP_PULLU_PIN1_Pos 1 -#define PORT_PORTP_PULLU_PIN1_Msk (0x01 << PORT_PORTP_PULLU_PIN1_Pos) -#define PORT_PORTP_PULLU_PIN2_Pos 2 -#define PORT_PORTP_PULLU_PIN2_Msk (0x01 << PORT_PORTP_PULLU_PIN2_Pos) -#define PORT_PORTP_PULLU_PIN3_Pos 3 -#define PORT_PORTP_PULLU_PIN3_Msk (0x01 << PORT_PORTP_PULLU_PIN3_Pos) -#define PORT_PORTP_PULLU_PIN4_Pos 4 -#define PORT_PORTP_PULLU_PIN4_Msk (0x01 << PORT_PORTP_PULLU_PIN4_Pos) -#define PORT_PORTP_PULLU_PIN5_Pos 5 -#define PORT_PORTP_PULLU_PIN5_Msk (0x01 << PORT_PORTP_PULLU_PIN5_Pos) -#define PORT_PORTP_PULLU_PIN6_Pos 6 -#define PORT_PORTP_PULLU_PIN6_Msk (0x01 << PORT_PORTP_PULLU_PIN6_Pos) -#define PORT_PORTP_PULLU_PIN7_Pos 7 -#define PORT_PORTP_PULLU_PIN7_Msk (0x01 << PORT_PORTP_PULLU_PIN7_Pos) -#define PORT_PORTP_PULLU_PIN8_Pos 8 -#define PORT_PORTP_PULLU_PIN8_Msk (0x01 << PORT_PORTP_PULLU_PIN8_Pos) -#define PORT_PORTP_PULLU_PIN9_Pos 9 -#define PORT_PORTP_PULLU_PIN9_Msk (0x01 << PORT_PORTP_PULLU_PIN9_Pos) -#define PORT_PORTP_PULLU_PIN10_Pos 10 -#define PORT_PORTP_PULLU_PIN10_Msk (0x01 << PORT_PORTP_PULLU_PIN10_Pos) -#define PORT_PORTP_PULLU_PIN11_Pos 11 -#define PORT_PORTP_PULLU_PIN11_Msk (0x01 << PORT_PORTP_PULLU_PIN11_Pos) -#define PORT_PORTP_PULLU_PIN12_Pos 12 -#define PORT_PORTP_PULLU_PIN12_Msk (0x01 << PORT_PORTP_PULLU_PIN12_Pos) -#define PORT_PORTP_PULLU_PIN13_Pos 13 -#define PORT_PORTP_PULLU_PIN13_Msk (0x01 << PORT_PORTP_PULLU_PIN13_Pos) -#define PORT_PORTP_PULLU_PIN14_Pos 14 -#define PORT_PORTP_PULLU_PIN14_Msk (0x01 << PORT_PORTP_PULLU_PIN14_Pos) -#define PORT_PORTP_PULLU_PIN15_Pos 15 -#define PORT_PORTP_PULLU_PIN15_Msk (0x01 << PORT_PORTP_PULLU_PIN15_Pos) -#define PORT_PORTP_PULLU_PIN16_Pos 16 -#define PORT_PORTP_PULLU_PIN16_Msk (0x01 << PORT_PORTP_PULLU_PIN16_Pos) -#define PORT_PORTP_PULLU_PIN17_Pos 17 -#define PORT_PORTP_PULLU_PIN17_Msk (0x01 << PORT_PORTP_PULLU_PIN17_Pos) -#define PORT_PORTP_PULLU_PIN18_Pos 18 -#define PORT_PORTP_PULLU_PIN18_Msk (0x01 << PORT_PORTP_PULLU_PIN18_Pos) -#define PORT_PORTP_PULLU_PIN19_Pos 19 -#define PORT_PORTP_PULLU_PIN19_Msk (0x01 << PORT_PORTP_PULLU_PIN19_Pos) -#define PORT_PORTP_PULLU_PIN20_Pos 20 -#define PORT_PORTP_PULLU_PIN20_Msk (0x01 << PORT_PORTP_PULLU_PIN20_Pos) -#define PORT_PORTP_PULLU_PIN21_Pos 21 -#define PORT_PORTP_PULLU_PIN21_Msk (0x01 << PORT_PORTP_PULLU_PIN21_Pos) -#define PORT_PORTP_PULLU_PIN22_Pos 22 -#define PORT_PORTP_PULLU_PIN22_Msk (0x01 << PORT_PORTP_PULLU_PIN22_Pos) -#define PORT_PORTP_PULLU_PIN23_Pos 23 -#define PORT_PORTP_PULLU_PIN23_Msk (0x01 << PORT_PORTP_PULLU_PIN23_Pos) +#define PORT_PORTB_PULLD_PIN0_Pos 0 +#define PORT_PORTB_PULLD_PIN0_Msk (0x01 << PORT_PORTB_PULLD_PIN0_Pos) +#define PORT_PORTB_PULLD_PIN1_Pos 1 +#define PORT_PORTB_PULLD_PIN1_Msk (0x01 << PORT_PORTB_PULLD_PIN1_Pos) +#define PORT_PORTB_PULLD_PIN2_Pos 2 +#define PORT_PORTB_PULLD_PIN2_Msk (0x01 << PORT_PORTB_PULLD_PIN2_Pos) +#define PORT_PORTB_PULLD_PIN3_Pos 3 +#define PORT_PORTB_PULLD_PIN3_Msk (0x01 << PORT_PORTB_PULLD_PIN3_Pos) +#define PORT_PORTB_PULLD_PIN4_Pos 4 +#define PORT_PORTB_PULLD_PIN4_Msk (0x01 << PORT_PORTB_PULLD_PIN4_Pos) +#define PORT_PORTB_PULLD_PIN5_Pos 5 +#define PORT_PORTB_PULLD_PIN5_Msk (0x01 << PORT_PORTB_PULLD_PIN5_Pos) +#define PORT_PORTB_PULLD_PIN6_Pos 6 +#define PORT_PORTB_PULLD_PIN6_Msk (0x01 << PORT_PORTB_PULLD_PIN6_Pos) +#define PORT_PORTB_PULLD_PIN7_Pos 7 +#define PORT_PORTB_PULLD_PIN7_Msk (0x01 << PORT_PORTB_PULLD_PIN7_Pos) +#define PORT_PORTB_PULLD_PIN8_Pos 8 +#define PORT_PORTB_PULLD_PIN8_Msk (0x01 << PORT_PORTB_PULLD_PIN8_Pos) +#define PORT_PORTB_PULLD_PIN9_Pos 9 +#define PORT_PORTB_PULLD_PIN9_Msk (0x01 << PORT_PORTB_PULLD_PIN9_Pos) +#define PORT_PORTB_PULLD_PIN10_Pos 10 +#define PORT_PORTB_PULLD_PIN10_Msk (0x01 << PORT_PORTB_PULLD_PIN10_Pos) +#define PORT_PORTB_PULLD_PIN11_Pos 11 +#define PORT_PORTB_PULLD_PIN11_Msk (0x01 << PORT_PORTB_PULLD_PIN11_Pos) +#define PORT_PORTB_PULLD_PIN12_Pos 12 +#define PORT_PORTB_PULLD_PIN12_Msk (0x01 << PORT_PORTB_PULLD_PIN12_Pos) +#define PORT_PORTB_PULLD_PIN13_Pos 13 +#define PORT_PORTB_PULLD_PIN13_Msk (0x01 << PORT_PORTB_PULLD_PIN13_Pos) +#define PORT_PORTB_PULLD_PIN14_Pos 14 +#define PORT_PORTB_PULLD_PIN14_Msk (0x01 << PORT_PORTB_PULLD_PIN14_Pos) +#define PORT_PORTB_PULLD_PIN15_Pos 15 +#define PORT_PORTB_PULLD_PIN15_Msk (0x01 << PORT_PORTB_PULLD_PIN15_Pos) -#define PORT_PORTB_PULLD_PIN0_Pos 0 -#define PORT_PORTB_PULLD_PIN0_Msk (0x01 << PORT_PORTB_PULLD_PIN0_Pos) -#define PORT_PORTB_PULLD_PIN1_Pos 1 -#define PORT_PORTB_PULLD_PIN1_Msk (0x01 << PORT_PORTB_PULLD_PIN1_Pos) -#define PORT_PORTB_PULLD_PIN2_Pos 2 -#define PORT_PORTB_PULLD_PIN2_Msk (0x01 << PORT_PORTB_PULLD_PIN2_Pos) -#define PORT_PORTB_PULLD_PIN3_Pos 3 -#define PORT_PORTB_PULLD_PIN3_Msk (0x01 << PORT_PORTB_PULLD_PIN3_Pos) -#define PORT_PORTB_PULLD_PIN4_Pos 4 -#define PORT_PORTB_PULLD_PIN4_Msk (0x01 << PORT_PORTB_PULLD_PIN4_Pos) -#define PORT_PORTB_PULLD_PIN5_Pos 5 -#define PORT_PORTB_PULLD_PIN5_Msk (0x01 << PORT_PORTB_PULLD_PIN5_Pos) -#define PORT_PORTB_PULLD_PIN6_Pos 6 -#define PORT_PORTB_PULLD_PIN6_Msk (0x01 << PORT_PORTB_PULLD_PIN6_Pos) -#define PORT_PORTB_PULLD_PIN7_Pos 7 -#define PORT_PORTB_PULLD_PIN7_Msk (0x01 << PORT_PORTB_PULLD_PIN7_Pos) -#define PORT_PORTB_PULLD_PIN8_Pos 8 -#define PORT_PORTB_PULLD_PIN8_Msk (0x01 << PORT_PORTB_PULLD_PIN8_Pos) -#define PORT_PORTB_PULLD_PIN9_Pos 9 -#define PORT_PORTB_PULLD_PIN9_Msk (0x01 << PORT_PORTB_PULLD_PIN9_Pos) -#define PORT_PORTB_PULLD_PIN10_Pos 10 -#define PORT_PORTB_PULLD_PIN10_Msk (0x01 << PORT_PORTB_PULLD_PIN10_Pos) -#define PORT_PORTB_PULLD_PIN11_Pos 11 -#define PORT_PORTB_PULLD_PIN11_Msk (0x01 << PORT_PORTB_PULLD_PIN11_Pos) -#define PORT_PORTB_PULLD_PIN12_Pos 12 -#define PORT_PORTB_PULLD_PIN12_Msk (0x01 << PORT_PORTB_PULLD_PIN12_Pos) -#define PORT_PORTB_PULLD_PIN13_Pos 13 -#define PORT_PORTB_PULLD_PIN13_Msk (0x01 << PORT_PORTB_PULLD_PIN13_Pos) -#define PORT_PORTB_PULLD_PIN14_Pos 14 -#define PORT_PORTB_PULLD_PIN14_Msk (0x01 << PORT_PORTB_PULLD_PIN14_Pos) -#define PORT_PORTB_PULLD_PIN15_Pos 15 -#define PORT_PORTB_PULLD_PIN15_Msk (0x01 << PORT_PORTB_PULLD_PIN15_Pos) +#define PORT_PORTN_PULLD_PIN0_Pos 0 +#define PORT_PORTN_PULLD_PIN0_Msk (0x01 << PORT_PORTN_PULLD_PIN0_Pos) +#define PORT_PORTN_PULLD_PIN1_Pos 1 +#define PORT_PORTN_PULLD_PIN1_Msk (0x01 << PORT_PORTN_PULLD_PIN1_Pos) +#define PORT_PORTN_PULLD_PIN2_Pos 2 +#define PORT_PORTN_PULLD_PIN2_Msk (0x01 << PORT_PORTN_PULLD_PIN2_Pos) +#define PORT_PORTN_PULLD_PIN3_Pos 3 +#define PORT_PORTN_PULLD_PIN3_Msk (0x01 << PORT_PORTN_PULLD_PIN3_Pos) +#define PORT_PORTN_PULLD_PIN4_Pos 4 +#define PORT_PORTN_PULLD_PIN4_Msk (0x01 << PORT_PORTN_PULLD_PIN4_Pos) +#define PORT_PORTN_PULLD_PIN5_Pos 5 +#define PORT_PORTN_PULLD_PIN5_Msk (0x01 << PORT_PORTN_PULLD_PIN5_Pos) +#define PORT_PORTN_PULLD_PIN6_Pos 6 +#define PORT_PORTN_PULLD_PIN6_Msk (0x01 << PORT_PORTN_PULLD_PIN6_Pos) +#define PORT_PORTN_PULLD_PIN7_Pos 7 +#define PORT_PORTN_PULLD_PIN7_Msk (0x01 << PORT_PORTN_PULLD_PIN7_Pos) +#define PORT_PORTN_PULLD_PIN8_Pos 8 +#define PORT_PORTN_PULLD_PIN8_Msk (0x01 << PORT_PORTN_PULLD_PIN8_Pos) +#define PORT_PORTN_PULLD_PIN9_Pos 9 +#define PORT_PORTN_PULLD_PIN9_Msk (0x01 << PORT_PORTN_PULLD_PIN9_Pos) +#define PORT_PORTN_PULLD_PIN10_Pos 10 +#define PORT_PORTN_PULLD_PIN10_Msk (0x01 << PORT_PORTN_PULLD_PIN10_Pos) +#define PORT_PORTN_PULLD_PIN11_Pos 11 +#define PORT_PORTN_PULLD_PIN11_Msk (0x01 << PORT_PORTN_PULLD_PIN11_Pos) +#define PORT_PORTN_PULLD_PIN12_Pos 12 +#define PORT_PORTN_PULLD_PIN12_Msk (0x01 << PORT_PORTN_PULLD_PIN12_Pos) +#define PORT_PORTN_PULLD_PIN13_Pos 13 +#define PORT_PORTN_PULLD_PIN13_Msk (0x01 << PORT_PORTN_PULLD_PIN13_Pos) +#define PORT_PORTN_PULLD_PIN14_Pos 14 +#define PORT_PORTN_PULLD_PIN14_Msk (0x01 << PORT_PORTN_PULLD_PIN14_Pos) +#define PORT_PORTN_PULLD_PIN15_Pos 15 +#define PORT_PORTN_PULLD_PIN15_Msk (0x01 << PORT_PORTN_PULLD_PIN15_Pos) +#define PORT_PORTN_PULLD_PIN16_Pos 16 +#define PORT_PORTN_PULLD_PIN16_Msk (0x01 << PORT_PORTN_PULLD_PIN16_Pos) +#define PORT_PORTN_PULLD_PIN17_Pos 17 +#define PORT_PORTN_PULLD_PIN17_Msk (0x01 << PORT_PORTN_PULLD_PIN17_Pos) +#define PORT_PORTN_PULLD_PIN18_Pos 18 +#define PORT_PORTN_PULLD_PIN18_Msk (0x01 << PORT_PORTN_PULLD_PIN18_Pos) +#define PORT_PORTN_PULLD_PIN19_Pos 19 +#define PORT_PORTN_PULLD_PIN19_Msk (0x01 << PORT_PORTN_PULLD_PIN19_Pos) +#define PORT_PORTN_PULLD_PIN20_Pos 20 +#define PORT_PORTN_PULLD_PIN20_Msk (0x01 << PORT_PORTN_PULLD_PIN20_Pos) +#define PORT_PORTN_PULLD_PIN21_Pos 21 +#define PORT_PORTN_PULLD_PIN21_Msk (0x01 << PORT_PORTN_PULLD_PIN21_Pos) +#define PORT_PORTN_PULLD_PIN22_Pos 22 +#define PORT_PORTN_PULLD_PIN22_Msk (0x01 << PORT_PORTN_PULLD_PIN22_Pos) +#define PORT_PORTN_PULLD_PIN23_Pos 23 +#define PORT_PORTN_PULLD_PIN23_Msk (0x01 << PORT_PORTN_PULLD_PIN23_Pos) -#define PORT_PORTN_PULLD_PIN0_Pos 0 -#define PORT_PORTN_PULLD_PIN0_Msk (0x01 << PORT_PORTN_PULLD_PIN0_Pos) -#define PORT_PORTN_PULLD_PIN1_Pos 1 -#define PORT_PORTN_PULLD_PIN1_Msk (0x01 << PORT_PORTN_PULLD_PIN1_Pos) -#define PORT_PORTN_PULLD_PIN2_Pos 2 -#define PORT_PORTN_PULLD_PIN2_Msk (0x01 << PORT_PORTN_PULLD_PIN2_Pos) -#define PORT_PORTN_PULLD_PIN3_Pos 3 -#define PORT_PORTN_PULLD_PIN3_Msk (0x01 << PORT_PORTN_PULLD_PIN3_Pos) -#define PORT_PORTN_PULLD_PIN4_Pos 4 -#define PORT_PORTN_PULLD_PIN4_Msk (0x01 << PORT_PORTN_PULLD_PIN4_Pos) -#define PORT_PORTN_PULLD_PIN5_Pos 5 -#define PORT_PORTN_PULLD_PIN5_Msk (0x01 << PORT_PORTN_PULLD_PIN5_Pos) -#define PORT_PORTN_PULLD_PIN6_Pos 6 -#define PORT_PORTN_PULLD_PIN6_Msk (0x01 << PORT_PORTN_PULLD_PIN6_Pos) -#define PORT_PORTN_PULLD_PIN7_Pos 7 -#define PORT_PORTN_PULLD_PIN7_Msk (0x01 << PORT_PORTN_PULLD_PIN7_Pos) -#define PORT_PORTN_PULLD_PIN8_Pos 8 -#define PORT_PORTN_PULLD_PIN8_Msk (0x01 << PORT_PORTN_PULLD_PIN8_Pos) -#define PORT_PORTN_PULLD_PIN9_Pos 9 -#define PORT_PORTN_PULLD_PIN9_Msk (0x01 << PORT_PORTN_PULLD_PIN9_Pos) -#define PORT_PORTN_PULLD_PIN10_Pos 10 -#define PORT_PORTN_PULLD_PIN10_Msk (0x01 << PORT_PORTN_PULLD_PIN10_Pos) -#define PORT_PORTN_PULLD_PIN11_Pos 11 -#define PORT_PORTN_PULLD_PIN11_Msk (0x01 << PORT_PORTN_PULLD_PIN11_Pos) -#define PORT_PORTN_PULLD_PIN12_Pos 12 -#define PORT_PORTN_PULLD_PIN12_Msk (0x01 << PORT_PORTN_PULLD_PIN12_Pos) -#define PORT_PORTN_PULLD_PIN13_Pos 13 -#define PORT_PORTN_PULLD_PIN13_Msk (0x01 << PORT_PORTN_PULLD_PIN13_Pos) -#define PORT_PORTN_PULLD_PIN14_Pos 14 -#define PORT_PORTN_PULLD_PIN14_Msk (0x01 << PORT_PORTN_PULLD_PIN14_Pos) -#define PORT_PORTN_PULLD_PIN15_Pos 15 -#define PORT_PORTN_PULLD_PIN15_Msk (0x01 << PORT_PORTN_PULLD_PIN15_Pos) -#define PORT_PORTN_PULLD_PIN16_Pos 16 -#define PORT_PORTN_PULLD_PIN16_Msk (0x01 << PORT_PORTN_PULLD_PIN16_Pos) -#define PORT_PORTN_PULLD_PIN17_Pos 17 -#define PORT_PORTN_PULLD_PIN17_Msk (0x01 << PORT_PORTN_PULLD_PIN17_Pos) -#define PORT_PORTN_PULLD_PIN18_Pos 18 -#define PORT_PORTN_PULLD_PIN18_Msk (0x01 << PORT_PORTN_PULLD_PIN18_Pos) -#define PORT_PORTN_PULLD_PIN19_Pos 19 -#define PORT_PORTN_PULLD_PIN19_Msk (0x01 << PORT_PORTN_PULLD_PIN19_Pos) -#define PORT_PORTN_PULLD_PIN20_Pos 20 -#define PORT_PORTN_PULLD_PIN20_Msk (0x01 << PORT_PORTN_PULLD_PIN20_Pos) -#define PORT_PORTN_PULLD_PIN21_Pos 21 -#define PORT_PORTN_PULLD_PIN21_Msk (0x01 << PORT_PORTN_PULLD_PIN21_Pos) -#define PORT_PORTN_PULLD_PIN22_Pos 22 -#define PORT_PORTN_PULLD_PIN22_Msk (0x01 << PORT_PORTN_PULLD_PIN22_Pos) -#define PORT_PORTN_PULLD_PIN23_Pos 23 -#define PORT_PORTN_PULLD_PIN23_Msk (0x01 << PORT_PORTN_PULLD_PIN23_Pos) +#define PORT_PORTM_DRIVS_PIN0_Pos 0 +#define PORT_PORTM_DRIVS_PIN0_Msk (0x01 << PORT_PORTM_DRIVS_PIN0_Pos) +#define PORT_PORTM_DRIVS_PIN1_Pos 1 +#define PORT_PORTM_DRIVS_PIN1_Msk (0x01 << PORT_PORTM_DRIVS_PIN1_Pos) +#define PORT_PORTM_DRIVS_PIN2_Pos 2 +#define PORT_PORTM_DRIVS_PIN2_Msk (0x01 << PORT_PORTM_DRIVS_PIN2_Pos) +#define PORT_PORTM_DRIVS_PIN3_Pos 3 +#define PORT_PORTM_DRIVS_PIN3_Msk (0x01 << PORT_PORTM_DRIVS_PIN3_Pos) +#define PORT_PORTM_DRIVS_PIN4_Pos 4 +#define PORT_PORTM_DRIVS_PIN4_Msk (0x01 << PORT_PORTM_DRIVS_PIN4_Pos) +#define PORT_PORTM_DRIVS_PIN5_Pos 5 +#define PORT_PORTM_DRIVS_PIN5_Msk (0x01 << PORT_PORTM_DRIVS_PIN5_Pos) +#define PORT_PORTM_DRIVS_PIN6_Pos 6 +#define PORT_PORTM_DRIVS_PIN6_Msk (0x01 << PORT_PORTM_DRIVS_PIN6_Pos) +#define PORT_PORTM_DRIVS_PIN7_Pos 7 +#define PORT_PORTM_DRIVS_PIN7_Msk (0x01 << PORT_PORTM_DRIVS_PIN7_Pos) +#define PORT_PORTM_DRIVS_PIN8_Pos 8 +#define PORT_PORTM_DRIVS_PIN8_Msk (0x01 << PORT_PORTM_DRIVS_PIN8_Pos) +#define PORT_PORTM_DRIVS_PIN9_Pos 9 +#define PORT_PORTM_DRIVS_PIN9_Msk (0x01 << PORT_PORTM_DRIVS_PIN9_Pos) +#define PORT_PORTM_DRIVS_PIN10_Pos 10 +#define PORT_PORTM_DRIVS_PIN10_Msk (0x01 << PORT_PORTM_DRIVS_PIN10_Pos) +#define PORT_PORTM_DRIVS_PIN11_Pos 11 +#define PORT_PORTM_DRIVS_PIN11_Msk (0x01 << PORT_PORTM_DRIVS_PIN11_Pos) +#define PORT_PORTM_DRIVS_PIN12_Pos 12 +#define PORT_PORTM_DRIVS_PIN12_Msk (0x01 << PORT_PORTM_DRIVS_PIN12_Pos) +#define PORT_PORTM_DRIVS_PIN13_Pos 13 +#define PORT_PORTM_DRIVS_PIN13_Msk (0x01 << PORT_PORTM_DRIVS_PIN13_Pos) +#define PORT_PORTM_DRIVS_PIN14_Pos 14 +#define PORT_PORTM_DRIVS_PIN14_Msk (0x01 << PORT_PORTM_DRIVS_PIN14_Pos) +#define PORT_PORTM_DRIVS_PIN15_Pos 15 +#define PORT_PORTM_DRIVS_PIN15_Msk (0x01 << PORT_PORTM_DRIVS_PIN15_Pos) +#define PORT_PORTM_DRIVS_PIN16_Pos 16 +#define PORT_PORTM_DRIVS_PIN16_Msk (0x01 << PORT_PORTM_DRIVS_PIN16_Pos) +#define PORT_PORTM_DRIVS_PIN17_Pos 17 +#define PORT_PORTM_DRIVS_PIN17_Msk (0x01 << PORT_PORTM_DRIVS_PIN17_Pos) +#define PORT_PORTM_DRIVS_PIN18_Pos 18 +#define PORT_PORTM_DRIVS_PIN18_Msk (0x01 << PORT_PORTM_DRIVS_PIN18_Pos) +#define PORT_PORTM_DRIVS_PIN19_Pos 19 +#define PORT_PORTM_DRIVS_PIN19_Msk (0x01 << PORT_PORTM_DRIVS_PIN19_Pos) +#define PORT_PORTM_DRIVS_PIN20_Pos 20 +#define PORT_PORTM_DRIVS_PIN20_Msk (0x01 << PORT_PORTM_DRIVS_PIN20_Pos) +#define PORT_PORTM_DRIVS_PIN21_Pos 21 +#define PORT_PORTM_DRIVS_PIN21_Msk (0x01 << PORT_PORTM_DRIVS_PIN21_Pos) +#define PORT_PORTM_DRIVS_PIN22_Pos 22 +#define PORT_PORTM_DRIVS_PIN22_Msk (0x01 << PORT_PORTM_DRIVS_PIN22_Pos) +#define PORT_PORTM_DRIVS_PIN23_Pos 23 +#define PORT_PORTM_DRIVS_PIN23_Msk (0x01 << PORT_PORTM_DRIVS_PIN23_Pos) -#define PORT_PORTM_DRIVS_PIN0_Pos 0 -#define PORT_PORTM_DRIVS_PIN0_Msk (0x01 << PORT_PORTM_DRIVS_PIN0_Pos) -#define PORT_PORTM_DRIVS_PIN1_Pos 1 -#define PORT_PORTM_DRIVS_PIN1_Msk (0x01 << PORT_PORTM_DRIVS_PIN1_Pos) -#define PORT_PORTM_DRIVS_PIN2_Pos 2 -#define PORT_PORTM_DRIVS_PIN2_Msk (0x01 << PORT_PORTM_DRIVS_PIN2_Pos) -#define PORT_PORTM_DRIVS_PIN3_Pos 3 -#define PORT_PORTM_DRIVS_PIN3_Msk (0x01 << PORT_PORTM_DRIVS_PIN3_Pos) -#define PORT_PORTM_DRIVS_PIN4_Pos 4 -#define PORT_PORTM_DRIVS_PIN4_Msk (0x01 << PORT_PORTM_DRIVS_PIN4_Pos) -#define PORT_PORTM_DRIVS_PIN5_Pos 5 -#define PORT_PORTM_DRIVS_PIN5_Msk (0x01 << PORT_PORTM_DRIVS_PIN5_Pos) -#define PORT_PORTM_DRIVS_PIN6_Pos 6 -#define PORT_PORTM_DRIVS_PIN6_Msk (0x01 << PORT_PORTM_DRIVS_PIN6_Pos) -#define PORT_PORTM_DRIVS_PIN7_Pos 7 -#define PORT_PORTM_DRIVS_PIN7_Msk (0x01 << PORT_PORTM_DRIVS_PIN7_Pos) -#define PORT_PORTM_DRIVS_PIN8_Pos 8 -#define PORT_PORTM_DRIVS_PIN8_Msk (0x01 << PORT_PORTM_DRIVS_PIN8_Pos) -#define PORT_PORTM_DRIVS_PIN9_Pos 9 -#define PORT_PORTM_DRIVS_PIN9_Msk (0x01 << PORT_PORTM_DRIVS_PIN9_Pos) -#define PORT_PORTM_DRIVS_PIN10_Pos 10 -#define PORT_PORTM_DRIVS_PIN10_Msk (0x01 << PORT_PORTM_DRIVS_PIN10_Pos) -#define PORT_PORTM_DRIVS_PIN11_Pos 11 -#define PORT_PORTM_DRIVS_PIN11_Msk (0x01 << PORT_PORTM_DRIVS_PIN11_Pos) -#define PORT_PORTM_DRIVS_PIN12_Pos 12 -#define PORT_PORTM_DRIVS_PIN12_Msk (0x01 << PORT_PORTM_DRIVS_PIN12_Pos) -#define PORT_PORTM_DRIVS_PIN13_Pos 13 -#define PORT_PORTM_DRIVS_PIN13_Msk (0x01 << PORT_PORTM_DRIVS_PIN13_Pos) -#define PORT_PORTM_DRIVS_PIN14_Pos 14 -#define PORT_PORTM_DRIVS_PIN14_Msk (0x01 << PORT_PORTM_DRIVS_PIN14_Pos) -#define PORT_PORTM_DRIVS_PIN15_Pos 15 -#define PORT_PORTM_DRIVS_PIN15_Msk (0x01 << PORT_PORTM_DRIVS_PIN15_Pos) -#define PORT_PORTM_DRIVS_PIN16_Pos 16 -#define PORT_PORTM_DRIVS_PIN16_Msk (0x01 << PORT_PORTM_DRIVS_PIN16_Pos) -#define PORT_PORTM_DRIVS_PIN17_Pos 17 -#define PORT_PORTM_DRIVS_PIN17_Msk (0x01 << PORT_PORTM_DRIVS_PIN17_Pos) -#define PORT_PORTM_DRIVS_PIN18_Pos 18 -#define PORT_PORTM_DRIVS_PIN18_Msk (0x01 << PORT_PORTM_DRIVS_PIN18_Pos) -#define PORT_PORTM_DRIVS_PIN19_Pos 19 -#define PORT_PORTM_DRIVS_PIN19_Msk (0x01 << PORT_PORTM_DRIVS_PIN19_Pos) -#define PORT_PORTM_DRIVS_PIN20_Pos 20 -#define PORT_PORTM_DRIVS_PIN20_Msk (0x01 << PORT_PORTM_DRIVS_PIN20_Pos) -#define PORT_PORTM_DRIVS_PIN21_Pos 21 -#define PORT_PORTM_DRIVS_PIN21_Msk (0x01 << PORT_PORTM_DRIVS_PIN21_Pos) -#define PORT_PORTM_DRIVS_PIN22_Pos 22 -#define PORT_PORTM_DRIVS_PIN22_Msk (0x01 << PORT_PORTM_DRIVS_PIN22_Pos) -#define PORT_PORTM_DRIVS_PIN23_Pos 23 -#define PORT_PORTM_DRIVS_PIN23_Msk (0x01 << PORT_PORTM_DRIVS_PIN23_Pos) +#define PORT_PORTN_DRIVS_PIN0_Pos 0 +#define PORT_PORTN_DRIVS_PIN0_Msk (0x01 << PORT_PORTN_DRIVS_PIN0_Pos) +#define PORT_PORTN_DRIVS_PIN1_Pos 1 +#define PORT_PORTN_DRIVS_PIN1_Msk (0x01 << PORT_PORTN_DRIVS_PIN1_Pos) +#define PORT_PORTN_DRIVS_PIN2_Pos 2 +#define PORT_PORTN_DRIVS_PIN2_Msk (0x01 << PORT_PORTN_DRIVS_PIN2_Pos) +#define PORT_PORTN_DRIVS_PIN3_Pos 3 +#define PORT_PORTN_DRIVS_PIN3_Msk (0x01 << PORT_PORTN_DRIVS_PIN3_Pos) +#define PORT_PORTN_DRIVS_PIN4_Pos 4 +#define PORT_PORTN_DRIVS_PIN4_Msk (0x01 << PORT_PORTN_DRIVS_PIN4_Pos) +#define PORT_PORTN_DRIVS_PIN5_Pos 5 +#define PORT_PORTN_DRIVS_PIN5_Msk (0x01 << PORT_PORTN_DRIVS_PIN5_Pos) +#define PORT_PORTN_DRIVS_PIN6_Pos 6 +#define PORT_PORTN_DRIVS_PIN6_Msk (0x01 << PORT_PORTN_DRIVS_PIN6_Pos) +#define PORT_PORTN_DRIVS_PIN7_Pos 7 +#define PORT_PORTN_DRIVS_PIN7_Msk (0x01 << PORT_PORTN_DRIVS_PIN7_Pos) +#define PORT_PORTN_DRIVS_PIN8_Pos 8 +#define PORT_PORTN_DRIVS_PIN8_Msk (0x01 << PORT_PORTN_DRIVS_PIN8_Pos) +#define PORT_PORTN_DRIVS_PIN9_Pos 9 +#define PORT_PORTN_DRIVS_PIN9_Msk (0x01 << PORT_PORTN_DRIVS_PIN9_Pos) +#define PORT_PORTN_DRIVS_PIN10_Pos 10 +#define PORT_PORTN_DRIVS_PIN10_Msk (0x01 << PORT_PORTN_DRIVS_PIN10_Pos) +#define PORT_PORTN_DRIVS_PIN11_Pos 11 +#define PORT_PORTN_DRIVS_PIN11_Msk (0x01 << PORT_PORTN_DRIVS_PIN11_Pos) +#define PORT_PORTN_DRIVS_PIN12_Pos 12 +#define PORT_PORTN_DRIVS_PIN12_Msk (0x01 << PORT_PORTN_DRIVS_PIN12_Pos) +#define PORT_PORTN_DRIVS_PIN13_Pos 13 +#define PORT_PORTN_DRIVS_PIN13_Msk (0x01 << PORT_PORTN_DRIVS_PIN13_Pos) +#define PORT_PORTN_DRIVS_PIN14_Pos 14 +#define PORT_PORTN_DRIVS_PIN14_Msk (0x01 << PORT_PORTN_DRIVS_PIN14_Pos) +#define PORT_PORTN_DRIVS_PIN15_Pos 15 +#define PORT_PORTN_DRIVS_PIN15_Msk (0x01 << PORT_PORTN_DRIVS_PIN15_Pos) +#define PORT_PORTN_DRIVS_PIN16_Pos 16 +#define PORT_PORTN_DRIVS_PIN16_Msk (0x01 << PORT_PORTN_DRIVS_PIN16_Pos) +#define PORT_PORTN_DRIVS_PIN17_Pos 17 +#define PORT_PORTN_DRIVS_PIN17_Msk (0x01 << PORT_PORTN_DRIVS_PIN17_Pos) +#define PORT_PORTN_DRIVS_PIN18_Pos 18 +#define PORT_PORTN_DRIVS_PIN18_Msk (0x01 << PORT_PORTN_DRIVS_PIN18_Pos) +#define PORT_PORTN_DRIVS_PIN19_Pos 19 +#define PORT_PORTN_DRIVS_PIN19_Msk (0x01 << PORT_PORTN_DRIVS_PIN19_Pos) +#define PORT_PORTN_DRIVS_PIN20_Pos 20 +#define PORT_PORTN_DRIVS_PIN20_Msk (0x01 << PORT_PORTN_DRIVS_PIN20_Pos) +#define PORT_PORTN_DRIVS_PIN21_Pos 21 +#define PORT_PORTN_DRIVS_PIN21_Msk (0x01 << PORT_PORTN_DRIVS_PIN21_Pos) +#define PORT_PORTN_DRIVS_PIN22_Pos 22 +#define PORT_PORTN_DRIVS_PIN22_Msk (0x01 << PORT_PORTN_DRIVS_PIN22_Pos) +#define PORT_PORTN_DRIVS_PIN23_Pos 23 +#define PORT_PORTN_DRIVS_PIN23_Msk (0x01 << PORT_PORTN_DRIVS_PIN23_Pos) -#define PORT_PORTN_DRIVS_PIN0_Pos 0 -#define PORT_PORTN_DRIVS_PIN0_Msk (0x01 << PORT_PORTN_DRIVS_PIN0_Pos) -#define PORT_PORTN_DRIVS_PIN1_Pos 1 -#define PORT_PORTN_DRIVS_PIN1_Msk (0x01 << PORT_PORTN_DRIVS_PIN1_Pos) -#define PORT_PORTN_DRIVS_PIN2_Pos 2 -#define PORT_PORTN_DRIVS_PIN2_Msk (0x01 << PORT_PORTN_DRIVS_PIN2_Pos) -#define PORT_PORTN_DRIVS_PIN3_Pos 3 -#define PORT_PORTN_DRIVS_PIN3_Msk (0x01 << PORT_PORTN_DRIVS_PIN3_Pos) -#define PORT_PORTN_DRIVS_PIN4_Pos 4 -#define PORT_PORTN_DRIVS_PIN4_Msk (0x01 << PORT_PORTN_DRIVS_PIN4_Pos) -#define PORT_PORTN_DRIVS_PIN5_Pos 5 -#define PORT_PORTN_DRIVS_PIN5_Msk (0x01 << PORT_PORTN_DRIVS_PIN5_Pos) -#define PORT_PORTN_DRIVS_PIN6_Pos 6 -#define PORT_PORTN_DRIVS_PIN6_Msk (0x01 << PORT_PORTN_DRIVS_PIN6_Pos) -#define PORT_PORTN_DRIVS_PIN7_Pos 7 -#define PORT_PORTN_DRIVS_PIN7_Msk (0x01 << PORT_PORTN_DRIVS_PIN7_Pos) -#define PORT_PORTN_DRIVS_PIN8_Pos 8 -#define PORT_PORTN_DRIVS_PIN8_Msk (0x01 << PORT_PORTN_DRIVS_PIN8_Pos) -#define PORT_PORTN_DRIVS_PIN9_Pos 9 -#define PORT_PORTN_DRIVS_PIN9_Msk (0x01 << PORT_PORTN_DRIVS_PIN9_Pos) -#define PORT_PORTN_DRIVS_PIN10_Pos 10 -#define PORT_PORTN_DRIVS_PIN10_Msk (0x01 << PORT_PORTN_DRIVS_PIN10_Pos) -#define PORT_PORTN_DRIVS_PIN11_Pos 11 -#define PORT_PORTN_DRIVS_PIN11_Msk (0x01 << PORT_PORTN_DRIVS_PIN11_Pos) -#define PORT_PORTN_DRIVS_PIN12_Pos 12 -#define PORT_PORTN_DRIVS_PIN12_Msk (0x01 << PORT_PORTN_DRIVS_PIN12_Pos) -#define PORT_PORTN_DRIVS_PIN13_Pos 13 -#define PORT_PORTN_DRIVS_PIN13_Msk (0x01 << PORT_PORTN_DRIVS_PIN13_Pos) -#define PORT_PORTN_DRIVS_PIN14_Pos 14 -#define PORT_PORTN_DRIVS_PIN14_Msk (0x01 << PORT_PORTN_DRIVS_PIN14_Pos) -#define PORT_PORTN_DRIVS_PIN15_Pos 15 -#define PORT_PORTN_DRIVS_PIN15_Msk (0x01 << PORT_PORTN_DRIVS_PIN15_Pos) -#define PORT_PORTN_DRIVS_PIN16_Pos 16 -#define PORT_PORTN_DRIVS_PIN16_Msk (0x01 << PORT_PORTN_DRIVS_PIN16_Pos) -#define PORT_PORTN_DRIVS_PIN17_Pos 17 -#define PORT_PORTN_DRIVS_PIN17_Msk (0x01 << PORT_PORTN_DRIVS_PIN17_Pos) -#define PORT_PORTN_DRIVS_PIN18_Pos 18 -#define PORT_PORTN_DRIVS_PIN18_Msk (0x01 << PORT_PORTN_DRIVS_PIN18_Pos) -#define PORT_PORTN_DRIVS_PIN19_Pos 19 -#define PORT_PORTN_DRIVS_PIN19_Msk (0x01 << PORT_PORTN_DRIVS_PIN19_Pos) -#define PORT_PORTN_DRIVS_PIN20_Pos 20 -#define PORT_PORTN_DRIVS_PIN20_Msk (0x01 << PORT_PORTN_DRIVS_PIN20_Pos) -#define PORT_PORTN_DRIVS_PIN21_Pos 21 -#define PORT_PORTN_DRIVS_PIN21_Msk (0x01 << PORT_PORTN_DRIVS_PIN21_Pos) -#define PORT_PORTN_DRIVS_PIN22_Pos 22 -#define PORT_PORTN_DRIVS_PIN22_Msk (0x01 << PORT_PORTN_DRIVS_PIN22_Pos) -#define PORT_PORTN_DRIVS_PIN23_Pos 23 -#define PORT_PORTN_DRIVS_PIN23_Msk (0x01 << PORT_PORTN_DRIVS_PIN23_Pos) +#define PORT_PORTP_DRIVS_PIN0_Pos 0 +#define PORT_PORTP_DRIVS_PIN0_Msk (0x01 << PORT_PORTP_DRIVS_PIN0_Pos) +#define PORT_PORTP_DRIVS_PIN1_Pos 1 +#define PORT_PORTP_DRIVS_PIN1_Msk (0x01 << PORT_PORTP_DRIVS_PIN1_Pos) +#define PORT_PORTP_DRIVS_PIN2_Pos 2 +#define PORT_PORTP_DRIVS_PIN2_Msk (0x01 << PORT_PORTP_DRIVS_PIN2_Pos) +#define PORT_PORTP_DRIVS_PIN3_Pos 3 +#define PORT_PORTP_DRIVS_PIN3_Msk (0x01 << PORT_PORTP_DRIVS_PIN3_Pos) +#define PORT_PORTP_DRIVS_PIN4_Pos 4 +#define PORT_PORTP_DRIVS_PIN4_Msk (0x01 << PORT_PORTP_DRIVS_PIN4_Pos) +#define PORT_PORTP_DRIVS_PIN5_Pos 5 +#define PORT_PORTP_DRIVS_PIN5_Msk (0x01 << PORT_PORTP_DRIVS_PIN5_Pos) +#define PORT_PORTP_DRIVS_PIN6_Pos 6 +#define PORT_PORTP_DRIVS_PIN6_Msk (0x01 << PORT_PORTP_DRIVS_PIN6_Pos) +#define PORT_PORTP_DRIVS_PIN7_Pos 7 +#define PORT_PORTP_DRIVS_PIN7_Msk (0x01 << PORT_PORTP_DRIVS_PIN7_Pos) +#define PORT_PORTP_DRIVS_PIN8_Pos 8 +#define PORT_PORTP_DRIVS_PIN8_Msk (0x01 << PORT_PORTP_DRIVS_PIN8_Pos) +#define PORT_PORTP_DRIVS_PIN9_Pos 9 +#define PORT_PORTP_DRIVS_PIN9_Msk (0x01 << PORT_PORTP_DRIVS_PIN9_Pos) +#define PORT_PORTP_DRIVS_PIN10_Pos 10 +#define PORT_PORTP_DRIVS_PIN10_Msk (0x01 << PORT_PORTP_DRIVS_PIN10_Pos) +#define PORT_PORTP_DRIVS_PIN11_Pos 11 +#define PORT_PORTP_DRIVS_PIN11_Msk (0x01 << PORT_PORTP_DRIVS_PIN11_Pos) +#define PORT_PORTP_DRIVS_PIN12_Pos 12 +#define PORT_PORTP_DRIVS_PIN12_Msk (0x01 << PORT_PORTP_DRIVS_PIN12_Pos) +#define PORT_PORTP_DRIVS_PIN13_Pos 13 +#define PORT_PORTP_DRIVS_PIN13_Msk (0x01 << PORT_PORTP_DRIVS_PIN13_Pos) +#define PORT_PORTP_DRIVS_PIN14_Pos 14 +#define PORT_PORTP_DRIVS_PIN14_Msk (0x01 << PORT_PORTP_DRIVS_PIN14_Pos) +#define PORT_PORTP_DRIVS_PIN15_Pos 15 +#define PORT_PORTP_DRIVS_PIN15_Msk (0x01 << PORT_PORTP_DRIVS_PIN15_Pos) +#define PORT_PORTP_DRIVS_PIN16_Pos 16 +#define PORT_PORTP_DRIVS_PIN16_Msk (0x01 << PORT_PORTP_DRIVS_PIN16_Pos) +#define PORT_PORTP_DRIVS_PIN17_Pos 17 +#define PORT_PORTP_DRIVS_PIN17_Msk (0x01 << PORT_PORTP_DRIVS_PIN17_Pos) +#define PORT_PORTP_DRIVS_PIN18_Pos 18 +#define PORT_PORTP_DRIVS_PIN18_Msk (0x01 << PORT_PORTP_DRIVS_PIN18_Pos) +#define PORT_PORTP_DRIVS_PIN19_Pos 19 +#define PORT_PORTP_DRIVS_PIN19_Msk (0x01 << PORT_PORTP_DRIVS_PIN19_Pos) +#define PORT_PORTP_DRIVS_PIN20_Pos 20 +#define PORT_PORTP_DRIVS_PIN20_Msk (0x01 << PORT_PORTP_DRIVS_PIN20_Pos) +#define PORT_PORTP_DRIVS_PIN21_Pos 21 +#define PORT_PORTP_DRIVS_PIN21_Msk (0x01 << PORT_PORTP_DRIVS_PIN21_Pos) +#define PORT_PORTP_DRIVS_PIN22_Pos 22 +#define PORT_PORTP_DRIVS_PIN22_Msk (0x01 << PORT_PORTP_DRIVS_PIN22_Pos) +#define PORT_PORTP_DRIVS_PIN23_Pos 23 +#define PORT_PORTP_DRIVS_PIN23_Msk (0x01 << PORT_PORTP_DRIVS_PIN23_Pos) -#define PORT_PORTP_DRIVS_PIN0_Pos 0 -#define PORT_PORTP_DRIVS_PIN0_Msk (0x01 << PORT_PORTP_DRIVS_PIN0_Pos) -#define PORT_PORTP_DRIVS_PIN1_Pos 1 -#define PORT_PORTP_DRIVS_PIN1_Msk (0x01 << PORT_PORTP_DRIVS_PIN1_Pos) -#define PORT_PORTP_DRIVS_PIN2_Pos 2 -#define PORT_PORTP_DRIVS_PIN2_Msk (0x01 << PORT_PORTP_DRIVS_PIN2_Pos) -#define PORT_PORTP_DRIVS_PIN3_Pos 3 -#define PORT_PORTP_DRIVS_PIN3_Msk (0x01 << PORT_PORTP_DRIVS_PIN3_Pos) -#define PORT_PORTP_DRIVS_PIN4_Pos 4 -#define PORT_PORTP_DRIVS_PIN4_Msk (0x01 << PORT_PORTP_DRIVS_PIN4_Pos) -#define PORT_PORTP_DRIVS_PIN5_Pos 5 -#define PORT_PORTP_DRIVS_PIN5_Msk (0x01 << PORT_PORTP_DRIVS_PIN5_Pos) -#define PORT_PORTP_DRIVS_PIN6_Pos 6 -#define PORT_PORTP_DRIVS_PIN6_Msk (0x01 << PORT_PORTP_DRIVS_PIN6_Pos) -#define PORT_PORTP_DRIVS_PIN7_Pos 7 -#define PORT_PORTP_DRIVS_PIN7_Msk (0x01 << PORT_PORTP_DRIVS_PIN7_Pos) -#define PORT_PORTP_DRIVS_PIN8_Pos 8 -#define PORT_PORTP_DRIVS_PIN8_Msk (0x01 << PORT_PORTP_DRIVS_PIN8_Pos) -#define PORT_PORTP_DRIVS_PIN9_Pos 9 -#define PORT_PORTP_DRIVS_PIN9_Msk (0x01 << PORT_PORTP_DRIVS_PIN9_Pos) -#define PORT_PORTP_DRIVS_PIN10_Pos 10 -#define PORT_PORTP_DRIVS_PIN10_Msk (0x01 << PORT_PORTP_DRIVS_PIN10_Pos) -#define PORT_PORTP_DRIVS_PIN11_Pos 11 -#define PORT_PORTP_DRIVS_PIN11_Msk (0x01 << PORT_PORTP_DRIVS_PIN11_Pos) -#define PORT_PORTP_DRIVS_PIN12_Pos 12 -#define PORT_PORTP_DRIVS_PIN12_Msk (0x01 << PORT_PORTP_DRIVS_PIN12_Pos) -#define PORT_PORTP_DRIVS_PIN13_Pos 13 -#define PORT_PORTP_DRIVS_PIN13_Msk (0x01 << PORT_PORTP_DRIVS_PIN13_Pos) -#define PORT_PORTP_DRIVS_PIN14_Pos 14 -#define PORT_PORTP_DRIVS_PIN14_Msk (0x01 << PORT_PORTP_DRIVS_PIN14_Pos) -#define PORT_PORTP_DRIVS_PIN15_Pos 15 -#define PORT_PORTP_DRIVS_PIN15_Msk (0x01 << PORT_PORTP_DRIVS_PIN15_Pos) -#define PORT_PORTP_DRIVS_PIN16_Pos 16 -#define PORT_PORTP_DRIVS_PIN16_Msk (0x01 << PORT_PORTP_DRIVS_PIN16_Pos) -#define PORT_PORTP_DRIVS_PIN17_Pos 17 -#define PORT_PORTP_DRIVS_PIN17_Msk (0x01 << PORT_PORTP_DRIVS_PIN17_Pos) -#define PORT_PORTP_DRIVS_PIN18_Pos 18 -#define PORT_PORTP_DRIVS_PIN18_Msk (0x01 << PORT_PORTP_DRIVS_PIN18_Pos) -#define PORT_PORTP_DRIVS_PIN19_Pos 19 -#define PORT_PORTP_DRIVS_PIN19_Msk (0x01 << PORT_PORTP_DRIVS_PIN19_Pos) -#define PORT_PORTP_DRIVS_PIN20_Pos 20 -#define PORT_PORTP_DRIVS_PIN20_Msk (0x01 << PORT_PORTP_DRIVS_PIN20_Pos) -#define PORT_PORTP_DRIVS_PIN21_Pos 21 -#define PORT_PORTP_DRIVS_PIN21_Msk (0x01 << PORT_PORTP_DRIVS_PIN21_Pos) -#define PORT_PORTP_DRIVS_PIN22_Pos 22 -#define PORT_PORTP_DRIVS_PIN22_Msk (0x01 << PORT_PORTP_DRIVS_PIN22_Pos) -#define PORT_PORTP_DRIVS_PIN23_Pos 23 -#define PORT_PORTP_DRIVS_PIN23_Msk (0x01 << PORT_PORTP_DRIVS_PIN23_Pos) +#define PORT_PORTA_INEN_PIN0_Pos 0 +#define PORT_PORTA_INEN_PIN0_Msk (0x01 << PORT_PORTA_INEN_PIN0_Pos) +#define PORT_PORTA_INEN_PIN1_Pos 1 +#define PORT_PORTA_INEN_PIN1_Msk (0x01 << PORT_PORTA_INEN_PIN1_Pos) +#define PORT_PORTA_INEN_PIN2_Pos 2 +#define PORT_PORTA_INEN_PIN2_Msk (0x01 << PORT_PORTA_INEN_PIN2_Pos) +#define PORT_PORTA_INEN_PIN3_Pos 3 +#define PORT_PORTA_INEN_PIN3_Msk (0x01 << PORT_PORTA_INEN_PIN3_Pos) +#define PORT_PORTA_INEN_PIN4_Pos 4 +#define PORT_PORTA_INEN_PIN4_Msk (0x01 << PORT_PORTA_INEN_PIN4_Pos) +#define PORT_PORTA_INEN_PIN5_Pos 5 +#define PORT_PORTA_INEN_PIN5_Msk (0x01 << PORT_PORTA_INEN_PIN5_Pos) +#define PORT_PORTA_INEN_PIN6_Pos 6 +#define PORT_PORTA_INEN_PIN6_Msk (0x01 << PORT_PORTA_INEN_PIN6_Pos) +#define PORT_PORTA_INEN_PIN7_Pos 7 +#define PORT_PORTA_INEN_PIN7_Msk (0x01 << PORT_PORTA_INEN_PIN7_Pos) +#define PORT_PORTA_INEN_PIN8_Pos 8 +#define PORT_PORTA_INEN_PIN8_Msk (0x01 << PORT_PORTA_INEN_PIN8_Pos) +#define PORT_PORTA_INEN_PIN9_Pos 9 +#define PORT_PORTA_INEN_PIN9_Msk (0x01 << PORT_PORTA_INEN_PIN9_Pos) +#define PORT_PORTA_INEN_PIN10_Pos 10 +#define PORT_PORTA_INEN_PIN10_Msk (0x01 << PORT_PORTA_INEN_PIN10_Pos) +#define PORT_PORTA_INEN_PIN11_Pos 11 +#define PORT_PORTA_INEN_PIN11_Msk (0x01 << PORT_PORTA_INEN_PIN11_Pos) +#define PORT_PORTA_INEN_PIN12_Pos 12 +#define PORT_PORTA_INEN_PIN12_Msk (0x01 << PORT_PORTA_INEN_PIN12_Pos) +#define PORT_PORTA_INEN_PIN13_Pos 13 +#define PORT_PORTA_INEN_PIN13_Msk (0x01 << PORT_PORTA_INEN_PIN13_Pos) +#define PORT_PORTA_INEN_PIN14_Pos 14 +#define PORT_PORTA_INEN_PIN14_Msk (0x01 << PORT_PORTA_INEN_PIN14_Pos) +#define PORT_PORTA_INEN_PIN15_Pos 15 +#define PORT_PORTA_INEN_PIN15_Msk (0x01 << PORT_PORTA_INEN_PIN15_Pos) -#define PORT_PORTA_INEN_PIN0_Pos 0 -#define PORT_PORTA_INEN_PIN0_Msk (0x01 << PORT_PORTA_INEN_PIN0_Pos) -#define PORT_PORTA_INEN_PIN1_Pos 1 -#define PORT_PORTA_INEN_PIN1_Msk (0x01 << PORT_PORTA_INEN_PIN1_Pos) -#define PORT_PORTA_INEN_PIN2_Pos 2 -#define PORT_PORTA_INEN_PIN2_Msk (0x01 << PORT_PORTA_INEN_PIN2_Pos) -#define PORT_PORTA_INEN_PIN3_Pos 3 -#define PORT_PORTA_INEN_PIN3_Msk (0x01 << PORT_PORTA_INEN_PIN3_Pos) -#define PORT_PORTA_INEN_PIN4_Pos 4 -#define PORT_PORTA_INEN_PIN4_Msk (0x01 << PORT_PORTA_INEN_PIN4_Pos) -#define PORT_PORTA_INEN_PIN5_Pos 5 -#define PORT_PORTA_INEN_PIN5_Msk (0x01 << PORT_PORTA_INEN_PIN5_Pos) -#define PORT_PORTA_INEN_PIN6_Pos 6 -#define PORT_PORTA_INEN_PIN6_Msk (0x01 << PORT_PORTA_INEN_PIN6_Pos) -#define PORT_PORTA_INEN_PIN7_Pos 7 -#define PORT_PORTA_INEN_PIN7_Msk (0x01 << PORT_PORTA_INEN_PIN7_Pos) -#define PORT_PORTA_INEN_PIN8_Pos 8 -#define PORT_PORTA_INEN_PIN8_Msk (0x01 << PORT_PORTA_INEN_PIN8_Pos) -#define PORT_PORTA_INEN_PIN9_Pos 9 -#define PORT_PORTA_INEN_PIN9_Msk (0x01 << PORT_PORTA_INEN_PIN9_Pos) -#define PORT_PORTA_INEN_PIN10_Pos 10 -#define PORT_PORTA_INEN_PIN10_Msk (0x01 << PORT_PORTA_INEN_PIN10_Pos) -#define PORT_PORTA_INEN_PIN11_Pos 11 -#define PORT_PORTA_INEN_PIN11_Msk (0x01 << PORT_PORTA_INEN_PIN11_Pos) -#define PORT_PORTA_INEN_PIN12_Pos 12 -#define PORT_PORTA_INEN_PIN12_Msk (0x01 << PORT_PORTA_INEN_PIN12_Pos) -#define PORT_PORTA_INEN_PIN13_Pos 13 -#define PORT_PORTA_INEN_PIN13_Msk (0x01 << PORT_PORTA_INEN_PIN13_Pos) -#define PORT_PORTA_INEN_PIN14_Pos 14 -#define PORT_PORTA_INEN_PIN14_Msk (0x01 << PORT_PORTA_INEN_PIN14_Pos) -#define PORT_PORTA_INEN_PIN15_Pos 15 -#define PORT_PORTA_INEN_PIN15_Msk (0x01 << PORT_PORTA_INEN_PIN15_Pos) +#define PORT_PORTB_INEN_PIN0_Pos 0 +#define PORT_PORTB_INEN_PIN0_Msk (0x01 << PORT_PORTB_INEN_PIN0_Pos) +#define PORT_PORTB_INEN_PIN1_Pos 1 +#define PORT_PORTB_INEN_PIN1_Msk (0x01 << PORT_PORTB_INEN_PIN1_Pos) +#define PORT_PORTB_INEN_PIN2_Pos 2 +#define PORT_PORTB_INEN_PIN2_Msk (0x01 << PORT_PORTB_INEN_PIN2_Pos) +#define PORT_PORTB_INEN_PIN3_Pos 3 +#define PORT_PORTB_INEN_PIN3_Msk (0x01 << PORT_PORTB_INEN_PIN3_Pos) +#define PORT_PORTB_INEN_PIN4_Pos 4 +#define PORT_PORTB_INEN_PIN4_Msk (0x01 << PORT_PORTB_INEN_PIN4_Pos) +#define PORT_PORTB_INEN_PIN5_Pos 5 +#define PORT_PORTB_INEN_PIN5_Msk (0x01 << PORT_PORTB_INEN_PIN5_Pos) +#define PORT_PORTB_INEN_PIN6_Pos 6 +#define PORT_PORTB_INEN_PIN6_Msk (0x01 << PORT_PORTB_INEN_PIN6_Pos) +#define PORT_PORTB_INEN_PIN7_Pos 7 +#define PORT_PORTB_INEN_PIN7_Msk (0x01 << PORT_PORTB_INEN_PIN7_Pos) +#define PORT_PORTB_INEN_PIN8_Pos 8 +#define PORT_PORTB_INEN_PIN8_Msk (0x01 << PORT_PORTB_INEN_PIN8_Pos) +#define PORT_PORTB_INEN_PIN9_Pos 9 +#define PORT_PORTB_INEN_PIN9_Msk (0x01 << PORT_PORTB_INEN_PIN9_Pos) +#define PORT_PORTB_INEN_PIN10_Pos 10 +#define PORT_PORTB_INEN_PIN10_Msk (0x01 << PORT_PORTB_INEN_PIN10_Pos) +#define PORT_PORTB_INEN_PIN11_Pos 11 +#define PORT_PORTB_INEN_PIN11_Msk (0x01 << PORT_PORTB_INEN_PIN11_Pos) +#define PORT_PORTB_INEN_PIN12_Pos 12 +#define PORT_PORTB_INEN_PIN12_Msk (0x01 << PORT_PORTB_INEN_PIN12_Pos) +#define PORT_PORTB_INEN_PIN13_Pos 13 +#define PORT_PORTB_INEN_PIN13_Msk (0x01 << PORT_PORTB_INEN_PIN13_Pos) +#define PORT_PORTB_INEN_PIN14_Pos 14 +#define PORT_PORTB_INEN_PIN14_Msk (0x01 << PORT_PORTB_INEN_PIN14_Pos) +#define PORT_PORTB_INEN_PIN15_Pos 15 +#define PORT_PORTB_INEN_PIN15_Msk (0x01 << PORT_PORTB_INEN_PIN15_Pos) -#define PORT_PORTB_INEN_PIN0_Pos 0 -#define PORT_PORTB_INEN_PIN0_Msk (0x01 << PORT_PORTB_INEN_PIN0_Pos) -#define PORT_PORTB_INEN_PIN1_Pos 1 -#define PORT_PORTB_INEN_PIN1_Msk (0x01 << PORT_PORTB_INEN_PIN1_Pos) -#define PORT_PORTB_INEN_PIN2_Pos 2 -#define PORT_PORTB_INEN_PIN2_Msk (0x01 << PORT_PORTB_INEN_PIN2_Pos) -#define PORT_PORTB_INEN_PIN3_Pos 3 -#define PORT_PORTB_INEN_PIN3_Msk (0x01 << PORT_PORTB_INEN_PIN3_Pos) -#define PORT_PORTB_INEN_PIN4_Pos 4 -#define PORT_PORTB_INEN_PIN4_Msk (0x01 << PORT_PORTB_INEN_PIN4_Pos) -#define PORT_PORTB_INEN_PIN5_Pos 5 -#define PORT_PORTB_INEN_PIN5_Msk (0x01 << PORT_PORTB_INEN_PIN5_Pos) -#define PORT_PORTB_INEN_PIN6_Pos 6 -#define PORT_PORTB_INEN_PIN6_Msk (0x01 << PORT_PORTB_INEN_PIN6_Pos) -#define PORT_PORTB_INEN_PIN7_Pos 7 -#define PORT_PORTB_INEN_PIN7_Msk (0x01 << PORT_PORTB_INEN_PIN7_Pos) -#define PORT_PORTB_INEN_PIN8_Pos 8 -#define PORT_PORTB_INEN_PIN8_Msk (0x01 << PORT_PORTB_INEN_PIN8_Pos) -#define PORT_PORTB_INEN_PIN9_Pos 9 -#define PORT_PORTB_INEN_PIN9_Msk (0x01 << PORT_PORTB_INEN_PIN9_Pos) -#define PORT_PORTB_INEN_PIN10_Pos 10 -#define PORT_PORTB_INEN_PIN10_Msk (0x01 << PORT_PORTB_INEN_PIN10_Pos) -#define PORT_PORTB_INEN_PIN11_Pos 11 -#define PORT_PORTB_INEN_PIN11_Msk (0x01 << PORT_PORTB_INEN_PIN11_Pos) -#define PORT_PORTB_INEN_PIN12_Pos 12 -#define PORT_PORTB_INEN_PIN12_Msk (0x01 << PORT_PORTB_INEN_PIN12_Pos) -#define PORT_PORTB_INEN_PIN13_Pos 13 -#define PORT_PORTB_INEN_PIN13_Msk (0x01 << PORT_PORTB_INEN_PIN13_Pos) -#define PORT_PORTB_INEN_PIN14_Pos 14 -#define PORT_PORTB_INEN_PIN14_Msk (0x01 << PORT_PORTB_INEN_PIN14_Pos) -#define PORT_PORTB_INEN_PIN15_Pos 15 -#define PORT_PORTB_INEN_PIN15_Msk (0x01 << PORT_PORTB_INEN_PIN15_Pos) +#define PORT_PORTC_INEN_PIN0_Pos 0 +#define PORT_PORTC_INEN_PIN0_Msk (0x01 << PORT_PORTC_INEN_PIN0_Pos) +#define PORT_PORTC_INEN_PIN1_Pos 1 +#define PORT_PORTC_INEN_PIN1_Msk (0x01 << PORT_PORTC_INEN_PIN1_Pos) +#define PORT_PORTC_INEN_PIN2_Pos 2 +#define PORT_PORTC_INEN_PIN2_Msk (0x01 << PORT_PORTC_INEN_PIN2_Pos) +#define PORT_PORTC_INEN_PIN3_Pos 3 +#define PORT_PORTC_INEN_PIN3_Msk (0x01 << PORT_PORTC_INEN_PIN3_Pos) +#define PORT_PORTC_INEN_PIN4_Pos 4 +#define PORT_PORTC_INEN_PIN4_Msk (0x01 << PORT_PORTC_INEN_PIN4_Pos) +#define PORT_PORTC_INEN_PIN5_Pos 5 +#define PORT_PORTC_INEN_PIN5_Msk (0x01 << PORT_PORTC_INEN_PIN5_Pos) +#define PORT_PORTC_INEN_PIN6_Pos 6 +#define PORT_PORTC_INEN_PIN6_Msk (0x01 << PORT_PORTC_INEN_PIN6_Pos) +#define PORT_PORTC_INEN_PIN7_Pos 7 +#define PORT_PORTC_INEN_PIN7_Msk (0x01 << PORT_PORTC_INEN_PIN7_Pos) +#define PORT_PORTC_INEN_PIN8_Pos 8 +#define PORT_PORTC_INEN_PIN8_Msk (0x01 << PORT_PORTC_INEN_PIN8_Pos) +#define PORT_PORTC_INEN_PIN9_Pos 9 +#define PORT_PORTC_INEN_PIN9_Msk (0x01 << PORT_PORTC_INEN_PIN9_Pos) +#define PORT_PORTC_INEN_PIN10_Pos 10 +#define PORT_PORTC_INEN_PIN10_Msk (0x01 << PORT_PORTC_INEN_PIN10_Pos) +#define PORT_PORTC_INEN_PIN11_Pos 11 +#define PORT_PORTC_INEN_PIN11_Msk (0x01 << PORT_PORTC_INEN_PIN11_Pos) +#define PORT_PORTC_INEN_PIN12_Pos 12 +#define PORT_PORTC_INEN_PIN12_Msk (0x01 << PORT_PORTC_INEN_PIN12_Pos) +#define PORT_PORTC_INEN_PIN13_Pos 13 +#define PORT_PORTC_INEN_PIN13_Msk (0x01 << PORT_PORTC_INEN_PIN13_Pos) +#define PORT_PORTC_INEN_PIN14_Pos 14 +#define PORT_PORTC_INEN_PIN14_Msk (0x01 << PORT_PORTC_INEN_PIN14_Pos) +#define PORT_PORTC_INEN_PIN15_Pos 15 +#define PORT_PORTC_INEN_PIN15_Msk (0x01 << PORT_PORTC_INEN_PIN15_Pos) -#define PORT_PORTC_INEN_PIN0_Pos 0 -#define PORT_PORTC_INEN_PIN0_Msk (0x01 << PORT_PORTC_INEN_PIN0_Pos) -#define PORT_PORTC_INEN_PIN1_Pos 1 -#define PORT_PORTC_INEN_PIN1_Msk (0x01 << PORT_PORTC_INEN_PIN1_Pos) -#define PORT_PORTC_INEN_PIN2_Pos 2 -#define PORT_PORTC_INEN_PIN2_Msk (0x01 << PORT_PORTC_INEN_PIN2_Pos) -#define PORT_PORTC_INEN_PIN3_Pos 3 -#define PORT_PORTC_INEN_PIN3_Msk (0x01 << PORT_PORTC_INEN_PIN3_Pos) -#define PORT_PORTC_INEN_PIN4_Pos 4 -#define PORT_PORTC_INEN_PIN4_Msk (0x01 << PORT_PORTC_INEN_PIN4_Pos) -#define PORT_PORTC_INEN_PIN5_Pos 5 -#define PORT_PORTC_INEN_PIN5_Msk (0x01 << PORT_PORTC_INEN_PIN5_Pos) -#define PORT_PORTC_INEN_PIN6_Pos 6 -#define PORT_PORTC_INEN_PIN6_Msk (0x01 << PORT_PORTC_INEN_PIN6_Pos) -#define PORT_PORTC_INEN_PIN7_Pos 7 -#define PORT_PORTC_INEN_PIN7_Msk (0x01 << PORT_PORTC_INEN_PIN7_Pos) -#define PORT_PORTC_INEN_PIN8_Pos 8 -#define PORT_PORTC_INEN_PIN8_Msk (0x01 << PORT_PORTC_INEN_PIN8_Pos) -#define PORT_PORTC_INEN_PIN9_Pos 9 -#define PORT_PORTC_INEN_PIN9_Msk (0x01 << PORT_PORTC_INEN_PIN9_Pos) -#define PORT_PORTC_INEN_PIN10_Pos 10 -#define PORT_PORTC_INEN_PIN10_Msk (0x01 << PORT_PORTC_INEN_PIN10_Pos) -#define PORT_PORTC_INEN_PIN11_Pos 11 -#define PORT_PORTC_INEN_PIN11_Msk (0x01 << PORT_PORTC_INEN_PIN11_Pos) -#define PORT_PORTC_INEN_PIN12_Pos 12 -#define PORT_PORTC_INEN_PIN12_Msk (0x01 << PORT_PORTC_INEN_PIN12_Pos) -#define PORT_PORTC_INEN_PIN13_Pos 13 -#define PORT_PORTC_INEN_PIN13_Msk (0x01 << PORT_PORTC_INEN_PIN13_Pos) -#define PORT_PORTC_INEN_PIN14_Pos 14 -#define PORT_PORTC_INEN_PIN14_Msk (0x01 << PORT_PORTC_INEN_PIN14_Pos) -#define PORT_PORTC_INEN_PIN15_Pos 15 -#define PORT_PORTC_INEN_PIN15_Msk (0x01 << PORT_PORTC_INEN_PIN15_Pos) +#define PORT_PORTM_INEN_PIN0_Pos 0 +#define PORT_PORTM_INEN_PIN0_Msk (0x01 << PORT_PORTM_INEN_PIN0_Pos) +#define PORT_PORTM_INEN_PIN1_Pos 1 +#define PORT_PORTM_INEN_PIN1_Msk (0x01 << PORT_PORTM_INEN_PIN1_Pos) +#define PORT_PORTM_INEN_PIN2_Pos 2 +#define PORT_PORTM_INEN_PIN2_Msk (0x01 << PORT_PORTM_INEN_PIN2_Pos) +#define PORT_PORTM_INEN_PIN3_Pos 3 +#define PORT_PORTM_INEN_PIN3_Msk (0x01 << PORT_PORTM_INEN_PIN3_Pos) +#define PORT_PORTM_INEN_PIN4_Pos 4 +#define PORT_PORTM_INEN_PIN4_Msk (0x01 << PORT_PORTM_INEN_PIN4_Pos) +#define PORT_PORTM_INEN_PIN5_Pos 5 +#define PORT_PORTM_INEN_PIN5_Msk (0x01 << PORT_PORTM_INEN_PIN5_Pos) +#define PORT_PORTM_INEN_PIN6_Pos 6 +#define PORT_PORTM_INEN_PIN6_Msk (0x01 << PORT_PORTM_INEN_PIN6_Pos) +#define PORT_PORTM_INEN_PIN7_Pos 7 +#define PORT_PORTM_INEN_PIN7_Msk (0x01 << PORT_PORTM_INEN_PIN7_Pos) +#define PORT_PORTM_INEN_PIN8_Pos 8 +#define PORT_PORTM_INEN_PIN8_Msk (0x01 << PORT_PORTM_INEN_PIN8_Pos) +#define PORT_PORTM_INEN_PIN9_Pos 9 +#define PORT_PORTM_INEN_PIN9_Msk (0x01 << PORT_PORTM_INEN_PIN9_Pos) +#define PORT_PORTM_INEN_PIN10_Pos 10 +#define PORT_PORTM_INEN_PIN10_Msk (0x01 << PORT_PORTM_INEN_PIN10_Pos) +#define PORT_PORTM_INEN_PIN11_Pos 11 +#define PORT_PORTM_INEN_PIN11_Msk (0x01 << PORT_PORTM_INEN_PIN11_Pos) +#define PORT_PORTM_INEN_PIN12_Pos 12 +#define PORT_PORTM_INEN_PIN12_Msk (0x01 << PORT_PORTM_INEN_PIN12_Pos) +#define PORT_PORTM_INEN_PIN13_Pos 13 +#define PORT_PORTM_INEN_PIN13_Msk (0x01 << PORT_PORTM_INEN_PIN13_Pos) +#define PORT_PORTM_INEN_PIN14_Pos 14 +#define PORT_PORTM_INEN_PIN14_Msk (0x01 << PORT_PORTM_INEN_PIN14_Pos) +#define PORT_PORTM_INEN_PIN15_Pos 15 +#define PORT_PORTM_INEN_PIN15_Msk (0x01 << PORT_PORTM_INEN_PIN15_Pos) +#define PORT_PORTM_INEN_PIN16_Pos 16 +#define PORT_PORTM_INEN_PIN16_Msk (0x01 << PORT_PORTM_INEN_PIN16_Pos) +#define PORT_PORTM_INEN_PIN17_Pos 17 +#define PORT_PORTM_INEN_PIN17_Msk (0x01 << PORT_PORTM_INEN_PIN17_Pos) +#define PORT_PORTM_INEN_PIN18_Pos 18 +#define PORT_PORTM_INEN_PIN18_Msk (0x01 << PORT_PORTM_INEN_PIN18_Pos) +#define PORT_PORTM_INEN_PIN19_Pos 19 +#define PORT_PORTM_INEN_PIN19_Msk (0x01 << PORT_PORTM_INEN_PIN19_Pos) +#define PORT_PORTM_INEN_PIN20_Pos 20 +#define PORT_PORTM_INEN_PIN20_Msk (0x01 << PORT_PORTM_INEN_PIN20_Pos) +#define PORT_PORTM_INEN_PIN21_Pos 21 +#define PORT_PORTM_INEN_PIN21_Msk (0x01 << PORT_PORTM_INEN_PIN21_Pos) +#define PORT_PORTM_INEN_PIN22_Pos 22 +#define PORT_PORTM_INEN_PIN22_Msk (0x01 << PORT_PORTM_INEN_PIN22_Pos) +#define PORT_PORTM_INEN_PIN23_Pos 23 +#define PORT_PORTM_INEN_PIN23_Msk (0x01 << PORT_PORTM_INEN_PIN23_Pos) -#define PORT_PORTM_INEN_PIN0_Pos 0 -#define PORT_PORTM_INEN_PIN0_Msk (0x01 << PORT_PORTM_INEN_PIN0_Pos) -#define PORT_PORTM_INEN_PIN1_Pos 1 -#define PORT_PORTM_INEN_PIN1_Msk (0x01 << PORT_PORTM_INEN_PIN1_Pos) -#define PORT_PORTM_INEN_PIN2_Pos 2 -#define PORT_PORTM_INEN_PIN2_Msk (0x01 << PORT_PORTM_INEN_PIN2_Pos) -#define PORT_PORTM_INEN_PIN3_Pos 3 -#define PORT_PORTM_INEN_PIN3_Msk (0x01 << PORT_PORTM_INEN_PIN3_Pos) -#define PORT_PORTM_INEN_PIN4_Pos 4 -#define PORT_PORTM_INEN_PIN4_Msk (0x01 << PORT_PORTM_INEN_PIN4_Pos) -#define PORT_PORTM_INEN_PIN5_Pos 5 -#define PORT_PORTM_INEN_PIN5_Msk (0x01 << PORT_PORTM_INEN_PIN5_Pos) -#define PORT_PORTM_INEN_PIN6_Pos 6 -#define PORT_PORTM_INEN_PIN6_Msk (0x01 << PORT_PORTM_INEN_PIN6_Pos) -#define PORT_PORTM_INEN_PIN7_Pos 7 -#define PORT_PORTM_INEN_PIN7_Msk (0x01 << PORT_PORTM_INEN_PIN7_Pos) -#define PORT_PORTM_INEN_PIN8_Pos 8 -#define PORT_PORTM_INEN_PIN8_Msk (0x01 << PORT_PORTM_INEN_PIN8_Pos) -#define PORT_PORTM_INEN_PIN9_Pos 9 -#define PORT_PORTM_INEN_PIN9_Msk (0x01 << PORT_PORTM_INEN_PIN9_Pos) -#define PORT_PORTM_INEN_PIN10_Pos 10 -#define PORT_PORTM_INEN_PIN10_Msk (0x01 << PORT_PORTM_INEN_PIN10_Pos) -#define PORT_PORTM_INEN_PIN11_Pos 11 -#define PORT_PORTM_INEN_PIN11_Msk (0x01 << PORT_PORTM_INEN_PIN11_Pos) -#define PORT_PORTM_INEN_PIN12_Pos 12 -#define PORT_PORTM_INEN_PIN12_Msk (0x01 << PORT_PORTM_INEN_PIN12_Pos) -#define PORT_PORTM_INEN_PIN13_Pos 13 -#define PORT_PORTM_INEN_PIN13_Msk (0x01 << PORT_PORTM_INEN_PIN13_Pos) -#define PORT_PORTM_INEN_PIN14_Pos 14 -#define PORT_PORTM_INEN_PIN14_Msk (0x01 << PORT_PORTM_INEN_PIN14_Pos) -#define PORT_PORTM_INEN_PIN15_Pos 15 -#define PORT_PORTM_INEN_PIN15_Msk (0x01 << PORT_PORTM_INEN_PIN15_Pos) -#define PORT_PORTM_INEN_PIN16_Pos 16 -#define PORT_PORTM_INEN_PIN16_Msk (0x01 << PORT_PORTM_INEN_PIN16_Pos) -#define PORT_PORTM_INEN_PIN17_Pos 17 -#define PORT_PORTM_INEN_PIN17_Msk (0x01 << PORT_PORTM_INEN_PIN17_Pos) -#define PORT_PORTM_INEN_PIN18_Pos 18 -#define PORT_PORTM_INEN_PIN18_Msk (0x01 << PORT_PORTM_INEN_PIN18_Pos) -#define PORT_PORTM_INEN_PIN19_Pos 19 -#define PORT_PORTM_INEN_PIN19_Msk (0x01 << PORT_PORTM_INEN_PIN19_Pos) -#define PORT_PORTM_INEN_PIN20_Pos 20 -#define PORT_PORTM_INEN_PIN20_Msk (0x01 << PORT_PORTM_INEN_PIN20_Pos) -#define PORT_PORTM_INEN_PIN21_Pos 21 -#define PORT_PORTM_INEN_PIN21_Msk (0x01 << PORT_PORTM_INEN_PIN21_Pos) -#define PORT_PORTM_INEN_PIN22_Pos 22 -#define PORT_PORTM_INEN_PIN22_Msk (0x01 << PORT_PORTM_INEN_PIN22_Pos) -#define PORT_PORTM_INEN_PIN23_Pos 23 -#define PORT_PORTM_INEN_PIN23_Msk (0x01 << PORT_PORTM_INEN_PIN23_Pos) +#define PORT_PORTN_INEN_PIN0_Pos 0 +#define PORT_PORTN_INEN_PIN0_Msk (0x01 << PORT_PORTN_INEN_PIN0_Pos) +#define PORT_PORTN_INEN_PIN1_Pos 1 +#define PORT_PORTN_INEN_PIN1_Msk (0x01 << PORT_PORTN_INEN_PIN1_Pos) +#define PORT_PORTN_INEN_PIN2_Pos 2 +#define PORT_PORTN_INEN_PIN2_Msk (0x01 << PORT_PORTN_INEN_PIN2_Pos) +#define PORT_PORTN_INEN_PIN3_Pos 3 +#define PORT_PORTN_INEN_PIN3_Msk (0x01 << PORT_PORTN_INEN_PIN3_Pos) +#define PORT_PORTN_INEN_PIN4_Pos 4 +#define PORT_PORTN_INEN_PIN4_Msk (0x01 << PORT_PORTN_INEN_PIN4_Pos) +#define PORT_PORTN_INEN_PIN5_Pos 5 +#define PORT_PORTN_INEN_PIN5_Msk (0x01 << PORT_PORTN_INEN_PIN5_Pos) +#define PORT_PORTN_INEN_PIN6_Pos 6 +#define PORT_PORTN_INEN_PIN6_Msk (0x01 << PORT_PORTN_INEN_PIN6_Pos) +#define PORT_PORTN_INEN_PIN7_Pos 7 +#define PORT_PORTN_INEN_PIN7_Msk (0x01 << PORT_PORTN_INEN_PIN7_Pos) +#define PORT_PORTN_INEN_PIN8_Pos 8 +#define PORT_PORTN_INEN_PIN8_Msk (0x01 << PORT_PORTN_INEN_PIN8_Pos) +#define PORT_PORTN_INEN_PIN9_Pos 9 +#define PORT_PORTN_INEN_PIN9_Msk (0x01 << PORT_PORTN_INEN_PIN9_Pos) +#define PORT_PORTN_INEN_PIN10_Pos 10 +#define PORT_PORTN_INEN_PIN10_Msk (0x01 << PORT_PORTN_INEN_PIN10_Pos) +#define PORT_PORTN_INEN_PIN11_Pos 11 +#define PORT_PORTN_INEN_PIN11_Msk (0x01 << PORT_PORTN_INEN_PIN11_Pos) +#define PORT_PORTN_INEN_PIN12_Pos 12 +#define PORT_PORTN_INEN_PIN12_Msk (0x01 << PORT_PORTN_INEN_PIN12_Pos) +#define PORT_PORTN_INEN_PIN13_Pos 13 +#define PORT_PORTN_INEN_PIN13_Msk (0x01 << PORT_PORTN_INEN_PIN13_Pos) +#define PORT_PORTN_INEN_PIN14_Pos 14 +#define PORT_PORTN_INEN_PIN14_Msk (0x01 << PORT_PORTN_INEN_PIN14_Pos) +#define PORT_PORTN_INEN_PIN15_Pos 15 +#define PORT_PORTN_INEN_PIN15_Msk (0x01 << PORT_PORTN_INEN_PIN15_Pos) +#define PORT_PORTN_INEN_PIN16_Pos 16 +#define PORT_PORTN_INEN_PIN16_Msk (0x01 << PORT_PORTN_INEN_PIN16_Pos) +#define PORT_PORTN_INEN_PIN17_Pos 17 +#define PORT_PORTN_INEN_PIN17_Msk (0x01 << PORT_PORTN_INEN_PIN17_Pos) +#define PORT_PORTN_INEN_PIN18_Pos 18 +#define PORT_PORTN_INEN_PIN18_Msk (0x01 << PORT_PORTN_INEN_PIN18_Pos) +#define PORT_PORTN_INEN_PIN19_Pos 19 +#define PORT_PORTN_INEN_PIN19_Msk (0x01 << PORT_PORTN_INEN_PIN19_Pos) +#define PORT_PORTN_INEN_PIN20_Pos 20 +#define PORT_PORTN_INEN_PIN20_Msk (0x01 << PORT_PORTN_INEN_PIN20_Pos) +#define PORT_PORTN_INEN_PIN21_Pos 21 +#define PORT_PORTN_INEN_PIN21_Msk (0x01 << PORT_PORTN_INEN_PIN21_Pos) +#define PORT_PORTN_INEN_PIN22_Pos 22 +#define PORT_PORTN_INEN_PIN22_Msk (0x01 << PORT_PORTN_INEN_PIN22_Pos) +#define PORT_PORTN_INEN_PIN23_Pos 23 +#define PORT_PORTN_INEN_PIN23_Msk (0x01 << PORT_PORTN_INEN_PIN23_Pos) -#define PORT_PORTN_INEN_PIN0_Pos 0 -#define PORT_PORTN_INEN_PIN0_Msk (0x01 << PORT_PORTN_INEN_PIN0_Pos) -#define PORT_PORTN_INEN_PIN1_Pos 1 -#define PORT_PORTN_INEN_PIN1_Msk (0x01 << PORT_PORTN_INEN_PIN1_Pos) -#define PORT_PORTN_INEN_PIN2_Pos 2 -#define PORT_PORTN_INEN_PIN2_Msk (0x01 << PORT_PORTN_INEN_PIN2_Pos) -#define PORT_PORTN_INEN_PIN3_Pos 3 -#define PORT_PORTN_INEN_PIN3_Msk (0x01 << PORT_PORTN_INEN_PIN3_Pos) -#define PORT_PORTN_INEN_PIN4_Pos 4 -#define PORT_PORTN_INEN_PIN4_Msk (0x01 << PORT_PORTN_INEN_PIN4_Pos) -#define PORT_PORTN_INEN_PIN5_Pos 5 -#define PORT_PORTN_INEN_PIN5_Msk (0x01 << PORT_PORTN_INEN_PIN5_Pos) -#define PORT_PORTN_INEN_PIN6_Pos 6 -#define PORT_PORTN_INEN_PIN6_Msk (0x01 << PORT_PORTN_INEN_PIN6_Pos) -#define PORT_PORTN_INEN_PIN7_Pos 7 -#define PORT_PORTN_INEN_PIN7_Msk (0x01 << PORT_PORTN_INEN_PIN7_Pos) -#define PORT_PORTN_INEN_PIN8_Pos 8 -#define PORT_PORTN_INEN_PIN8_Msk (0x01 << PORT_PORTN_INEN_PIN8_Pos) -#define PORT_PORTN_INEN_PIN9_Pos 9 -#define PORT_PORTN_INEN_PIN9_Msk (0x01 << PORT_PORTN_INEN_PIN9_Pos) -#define PORT_PORTN_INEN_PIN10_Pos 10 -#define PORT_PORTN_INEN_PIN10_Msk (0x01 << PORT_PORTN_INEN_PIN10_Pos) -#define PORT_PORTN_INEN_PIN11_Pos 11 -#define PORT_PORTN_INEN_PIN11_Msk (0x01 << PORT_PORTN_INEN_PIN11_Pos) -#define PORT_PORTN_INEN_PIN12_Pos 12 -#define PORT_PORTN_INEN_PIN12_Msk (0x01 << PORT_PORTN_INEN_PIN12_Pos) -#define PORT_PORTN_INEN_PIN13_Pos 13 -#define PORT_PORTN_INEN_PIN13_Msk (0x01 << PORT_PORTN_INEN_PIN13_Pos) -#define PORT_PORTN_INEN_PIN14_Pos 14 -#define PORT_PORTN_INEN_PIN14_Msk (0x01 << PORT_PORTN_INEN_PIN14_Pos) -#define PORT_PORTN_INEN_PIN15_Pos 15 -#define PORT_PORTN_INEN_PIN15_Msk (0x01 << PORT_PORTN_INEN_PIN15_Pos) -#define PORT_PORTN_INEN_PIN16_Pos 16 -#define PORT_PORTN_INEN_PIN16_Msk (0x01 << PORT_PORTN_INEN_PIN16_Pos) -#define PORT_PORTN_INEN_PIN17_Pos 17 -#define PORT_PORTN_INEN_PIN17_Msk (0x01 << PORT_PORTN_INEN_PIN17_Pos) -#define PORT_PORTN_INEN_PIN18_Pos 18 -#define PORT_PORTN_INEN_PIN18_Msk (0x01 << PORT_PORTN_INEN_PIN18_Pos) -#define PORT_PORTN_INEN_PIN19_Pos 19 -#define PORT_PORTN_INEN_PIN19_Msk (0x01 << PORT_PORTN_INEN_PIN19_Pos) -#define PORT_PORTN_INEN_PIN20_Pos 20 -#define PORT_PORTN_INEN_PIN20_Msk (0x01 << PORT_PORTN_INEN_PIN20_Pos) -#define PORT_PORTN_INEN_PIN21_Pos 21 -#define PORT_PORTN_INEN_PIN21_Msk (0x01 << PORT_PORTN_INEN_PIN21_Pos) -#define PORT_PORTN_INEN_PIN22_Pos 22 -#define PORT_PORTN_INEN_PIN22_Msk (0x01 << PORT_PORTN_INEN_PIN22_Pos) -#define PORT_PORTN_INEN_PIN23_Pos 23 -#define PORT_PORTN_INEN_PIN23_Msk (0x01 << PORT_PORTN_INEN_PIN23_Pos) +#define PORT_PORTP_INEN_PIN0_Pos 0 +#define PORT_PORTP_INEN_PIN0_Msk (0x01 << PORT_PORTP_INEN_PIN0_Pos) +#define PORT_PORTP_INEN_PIN1_Pos 1 +#define PORT_PORTP_INEN_PIN1_Msk (0x01 << PORT_PORTP_INEN_PIN1_Pos) +#define PORT_PORTP_INEN_PIN2_Pos 2 +#define PORT_PORTP_INEN_PIN2_Msk (0x01 << PORT_PORTP_INEN_PIN2_Pos) +#define PORT_PORTP_INEN_PIN3_Pos 3 +#define PORT_PORTP_INEN_PIN3_Msk (0x01 << PORT_PORTP_INEN_PIN3_Pos) +#define PORT_PORTP_INEN_PIN4_Pos 4 +#define PORT_PORTP_INEN_PIN4_Msk (0x01 << PORT_PORTP_INEN_PIN4_Pos) +#define PORT_PORTP_INEN_PIN5_Pos 5 +#define PORT_PORTP_INEN_PIN5_Msk (0x01 << PORT_PORTP_INEN_PIN5_Pos) +#define PORT_PORTP_INEN_PIN6_Pos 6 +#define PORT_PORTP_INEN_PIN6_Msk (0x01 << PORT_PORTP_INEN_PIN6_Pos) +#define PORT_PORTP_INEN_PIN7_Pos 7 +#define PORT_PORTP_INEN_PIN7_Msk (0x01 << PORT_PORTP_INEN_PIN7_Pos) +#define PORT_PORTP_INEN_PIN8_Pos 8 +#define PORT_PORTP_INEN_PIN8_Msk (0x01 << PORT_PORTP_INEN_PIN8_Pos) +#define PORT_PORTP_INEN_PIN9_Pos 9 +#define PORT_PORTP_INEN_PIN9_Msk (0x01 << PORT_PORTP_INEN_PIN9_Pos) +#define PORT_PORTP_INEN_PIN10_Pos 10 +#define PORT_PORTP_INEN_PIN10_Msk (0x01 << PORT_PORTP_INEN_PIN10_Pos) +#define PORT_PORTP_INEN_PIN11_Pos 11 +#define PORT_PORTP_INEN_PIN11_Msk (0x01 << PORT_PORTP_INEN_PIN11_Pos) +#define PORT_PORTP_INEN_PIN12_Pos 12 +#define PORT_PORTP_INEN_PIN12_Msk (0x01 << PORT_PORTP_INEN_PIN12_Pos) +#define PORT_PORTP_INEN_PIN13_Pos 13 +#define PORT_PORTP_INEN_PIN13_Msk (0x01 << PORT_PORTP_INEN_PIN13_Pos) +#define PORT_PORTP_INEN_PIN14_Pos 14 +#define PORT_PORTP_INEN_PIN14_Msk (0x01 << PORT_PORTP_INEN_PIN14_Pos) +#define PORT_PORTP_INEN_PIN15_Pos 15 +#define PORT_PORTP_INEN_PIN15_Msk (0x01 << PORT_PORTP_INEN_PIN15_Pos) +#define PORT_PORTP_INEN_PIN16_Pos 16 +#define PORT_PORTP_INEN_PIN16_Msk (0x01 << PORT_PORTP_INEN_PIN16_Pos) +#define PORT_PORTP_INEN_PIN17_Pos 17 +#define PORT_PORTP_INEN_PIN17_Msk (0x01 << PORT_PORTP_INEN_PIN17_Pos) +#define PORT_PORTP_INEN_PIN18_Pos 18 +#define PORT_PORTP_INEN_PIN18_Msk (0x01 << PORT_PORTP_INEN_PIN18_Pos) +#define PORT_PORTP_INEN_PIN19_Pos 19 +#define PORT_PORTP_INEN_PIN19_Msk (0x01 << PORT_PORTP_INEN_PIN19_Pos) +#define PORT_PORTP_INEN_PIN20_Pos 20 +#define PORT_PORTP_INEN_PIN20_Msk (0x01 << PORT_PORTP_INEN_PIN20_Pos) +#define PORT_PORTP_INEN_PIN21_Pos 21 +#define PORT_PORTP_INEN_PIN21_Msk (0x01 << PORT_PORTP_INEN_PIN21_Pos) +#define PORT_PORTP_INEN_PIN22_Pos 22 +#define PORT_PORTP_INEN_PIN22_Msk (0x01 << PORT_PORTP_INEN_PIN22_Pos) +#define PORT_PORTP_INEN_PIN23_Pos 23 +#define PORT_PORTP_INEN_PIN23_Msk (0x01 << PORT_PORTP_INEN_PIN23_Pos) -#define PORT_PORTP_INEN_PIN0_Pos 0 -#define PORT_PORTP_INEN_PIN0_Msk (0x01 << PORT_PORTP_INEN_PIN0_Pos) -#define PORT_PORTP_INEN_PIN1_Pos 1 -#define PORT_PORTP_INEN_PIN1_Msk (0x01 << PORT_PORTP_INEN_PIN1_Pos) -#define PORT_PORTP_INEN_PIN2_Pos 2 -#define PORT_PORTP_INEN_PIN2_Msk (0x01 << PORT_PORTP_INEN_PIN2_Pos) -#define PORT_PORTP_INEN_PIN3_Pos 3 -#define PORT_PORTP_INEN_PIN3_Msk (0x01 << PORT_PORTP_INEN_PIN3_Pos) -#define PORT_PORTP_INEN_PIN4_Pos 4 -#define PORT_PORTP_INEN_PIN4_Msk (0x01 << PORT_PORTP_INEN_PIN4_Pos) -#define PORT_PORTP_INEN_PIN5_Pos 5 -#define PORT_PORTP_INEN_PIN5_Msk (0x01 << PORT_PORTP_INEN_PIN5_Pos) -#define PORT_PORTP_INEN_PIN6_Pos 6 -#define PORT_PORTP_INEN_PIN6_Msk (0x01 << PORT_PORTP_INEN_PIN6_Pos) -#define PORT_PORTP_INEN_PIN7_Pos 7 -#define PORT_PORTP_INEN_PIN7_Msk (0x01 << PORT_PORTP_INEN_PIN7_Pos) -#define PORT_PORTP_INEN_PIN8_Pos 8 -#define PORT_PORTP_INEN_PIN8_Msk (0x01 << PORT_PORTP_INEN_PIN8_Pos) -#define PORT_PORTP_INEN_PIN9_Pos 9 -#define PORT_PORTP_INEN_PIN9_Msk (0x01 << PORT_PORTP_INEN_PIN9_Pos) -#define PORT_PORTP_INEN_PIN10_Pos 10 -#define PORT_PORTP_INEN_PIN10_Msk (0x01 << PORT_PORTP_INEN_PIN10_Pos) -#define PORT_PORTP_INEN_PIN11_Pos 11 -#define PORT_PORTP_INEN_PIN11_Msk (0x01 << PORT_PORTP_INEN_PIN11_Pos) -#define PORT_PORTP_INEN_PIN12_Pos 12 -#define PORT_PORTP_INEN_PIN12_Msk (0x01 << PORT_PORTP_INEN_PIN12_Pos) -#define PORT_PORTP_INEN_PIN13_Pos 13 -#define PORT_PORTP_INEN_PIN13_Msk (0x01 << PORT_PORTP_INEN_PIN13_Pos) -#define PORT_PORTP_INEN_PIN14_Pos 14 -#define PORT_PORTP_INEN_PIN14_Msk (0x01 << PORT_PORTP_INEN_PIN14_Pos) -#define PORT_PORTP_INEN_PIN15_Pos 15 -#define PORT_PORTP_INEN_PIN15_Msk (0x01 << PORT_PORTP_INEN_PIN15_Pos) -#define PORT_PORTP_INEN_PIN16_Pos 16 -#define PORT_PORTP_INEN_PIN16_Msk (0x01 << PORT_PORTP_INEN_PIN16_Pos) -#define PORT_PORTP_INEN_PIN17_Pos 17 -#define PORT_PORTP_INEN_PIN17_Msk (0x01 << PORT_PORTP_INEN_PIN17_Pos) -#define PORT_PORTP_INEN_PIN18_Pos 18 -#define PORT_PORTP_INEN_PIN18_Msk (0x01 << PORT_PORTP_INEN_PIN18_Pos) -#define PORT_PORTP_INEN_PIN19_Pos 19 -#define PORT_PORTP_INEN_PIN19_Msk (0x01 << PORT_PORTP_INEN_PIN19_Pos) -#define PORT_PORTP_INEN_PIN20_Pos 20 -#define PORT_PORTP_INEN_PIN20_Msk (0x01 << PORT_PORTP_INEN_PIN20_Pos) -#define PORT_PORTP_INEN_PIN21_Pos 21 -#define PORT_PORTP_INEN_PIN21_Msk (0x01 << PORT_PORTP_INEN_PIN21_Pos) -#define PORT_PORTP_INEN_PIN22_Pos 22 -#define PORT_PORTP_INEN_PIN22_Msk (0x01 << PORT_PORTP_INEN_PIN22_Pos) -#define PORT_PORTP_INEN_PIN23_Pos 23 -#define PORT_PORTP_INEN_PIN23_Msk (0x01 << PORT_PORTP_INEN_PIN23_Pos) +typedef struct +{ + __IO uint32_t DATA; +#define PIN0 0 +#define PIN1 1 +#define PIN2 2 +#define PIN3 3 +#define PIN4 4 +#define PIN5 5 +#define PIN6 6 +#define PIN7 7 +#define PIN8 8 +#define PIN9 9 +#define PIN10 10 +#define PIN11 11 +#define PIN12 12 +#define PIN13 13 +#define PIN14 14 +#define PIN15 15 +#define PIN16 16 +#define PIN17 17 +#define PIN18 18 +#define PIN19 19 +#define PIN20 20 +#define PIN21 21 +#define PIN22 22 +#define PIN23 23 +#define PIN24 24 + __IO uint32_t DIR; //0 输入 1 输出 + __IO uint32_t INTLVLTRG; //Interrupt Level Trigger 1 电平触发中断 0 边沿触发中断 + __IO uint32_t INTBE; //Both Edge,当INTLVLTRG设为边沿触发中断时,此位置1表示上升沿和下降沿都触发中断,置0时触发边沿由INTRISEEN选择 -typedef struct { - __IO uint32_t DATA; -#define PIN0 0 -#define PIN1 1 -#define PIN2 2 -#define PIN3 3 -#define PIN4 4 -#define PIN5 5 -#define PIN6 6 -#define PIN7 7 -#define PIN8 8 -#define PIN9 9 -#define PIN10 10 -#define PIN11 11 -#define PIN12 12 -#define PIN13 13 -#define PIN14 14 -#define PIN15 15 -#define PIN16 16 -#define PIN17 17 -#define PIN18 18 -#define PIN19 19 -#define PIN20 20 -#define PIN21 21 -#define PIN22 22 -#define PIN23 23 -#define PIN24 24 + __IO uint32_t INTRISEEN; //Interrupt Rise Edge Enable 1 上升沿/高电平触发中断 0 下降沿/低电平触发中断 - __IO uint32_t DIR; //0 输入 1 输出 + __IO uint32_t INTEN; //1 中断使能 0 中断禁止 - __IO uint32_t INTLVLTRG; //Interrupt Level Trigger 1 电平触发中断 0 边沿触发中断 + __IO uint32_t INTRAWSTAT; //中断检测单元是否检测到了触发中断的条件 1 检测到了中断触发条件 0 没有检测到中断触发条件 - __IO uint32_t INTBE; //Both Edge,当INTLVLTRG设为边沿触发中断时,此位置1表示上升沿和下降沿都触发中断,置0时触发边沿由INTRISEEN选择 + __IO uint32_t INTSTAT; //INTSTAT.PIN0 = INTRAWSTAT.PIN0 & INTEN.PIN0 - __IO uint32_t INTRISEEN; //Interrupt Rise Edge Enable 1 上升沿/高电平触发中断 0 下降沿/低电平触发中断 - - __IO uint32_t INTEN; //1 中断使能 0 中断禁止 - - __IO uint32_t INTRAWSTAT; //中断检测单元是否检测到了触发中断的条件 1 检测到了中断触发条件 0 没有检测到中断触发条件 - - __IO uint32_t INTSTAT; //INTSTAT.PIN0 = INTRAWSTAT.PIN0 & INTEN.PIN0 - - __IO uint32_t INTCLR; //写1清除中断标志,只对边沿触发中断有用 + __IO uint32_t INTCLR; //写1清除中断标志,只对边沿触发中断有用 } GPIO_TypeDef; +#define GPIO_DATA_PIN0_Pos 0 +#define GPIO_DATA_PIN0_Msk (0x01 << GPIO_DATA_PIN0_Pos) +#define GPIO_DATA_PIN1_Pos 1 +#define GPIO_DATA_PIN1_Msk (0x01 << GPIO_DATA_PIN1_Pos) +#define GPIO_DATA_PIN2_Pos 2 +#define GPIO_DATA_PIN2_Msk (0x01 << GPIO_DATA_PIN2_Pos) +#define GPIO_DATA_PIN3_Pos 3 +#define GPIO_DATA_PIN3_Msk (0x01 << GPIO_DATA_PIN3_Pos) +#define GPIO_DATA_PIN4_Pos 4 +#define GPIO_DATA_PIN4_Msk (0x01 << GPIO_DATA_PIN4_Pos) +#define GPIO_DATA_PIN5_Pos 5 +#define GPIO_DATA_PIN5_Msk (0x01 << GPIO_DATA_PIN5_Pos) +#define GPIO_DATA_PIN6_Pos 6 +#define GPIO_DATA_PIN6_Msk (0x01 << GPIO_DATA_PIN6_Pos) +#define GPIO_DATA_PIN7_Pos 7 +#define GPIO_DATA_PIN7_Msk (0x01 << GPIO_DATA_PIN7_Pos) +#define GPIO_DATA_PIN8_Pos 8 +#define GPIO_DATA_PIN8_Msk (0x01 << GPIO_DATA_PIN8_Pos) +#define GPIO_DATA_PIN9_Pos 9 +#define GPIO_DATA_PIN9_Msk (0x01 << GPIO_DATA_PIN9_Pos) +#define GPIO_DATA_PIN10_Pos 10 +#define GPIO_DATA_PIN10_Msk (0x01 << GPIO_DATA_PIN10_Pos) +#define GPIO_DATA_PIN11_Pos 11 +#define GPIO_DATA_PIN11_Msk (0x01 << GPIO_DATA_PIN11_Pos) +#define GPIO_DATA_PIN12_Pos 12 +#define GPIO_DATA_PIN12_Msk (0x01 << GPIO_DATA_PIN12_Pos) +#define GPIO_DATA_PIN13_Pos 13 +#define GPIO_DATA_PIN13_Msk (0x01 << GPIO_DATA_PIN13_Pos) +#define GPIO_DATA_PIN14_Pos 14 +#define GPIO_DATA_PIN14_Msk (0x01 << GPIO_DATA_PIN14_Pos) +#define GPIO_DATA_PIN15_Pos 15 +#define GPIO_DATA_PIN15_Msk (0x01 << GPIO_DATA_PIN15_Pos) +#define GPIO_DATA_PIN16_Pos 16 +#define GPIO_DATA_PIN16_Msk (0x01 << GPIO_DATA_PIN16_Pos) +#define GPIO_DATA_PIN17_Pos 17 +#define GPIO_DATA_PIN17_Msk (0x01 << GPIO_DATA_PIN17_Pos) +#define GPIO_DATA_PIN18_Pos 18 +#define GPIO_DATA_PIN18_Msk (0x01 << GPIO_DATA_PIN18_Pos) +#define GPIO_DATA_PIN19_Pos 19 +#define GPIO_DATA_PIN19_Msk (0x01 << GPIO_DATA_PIN19_Pos) +#define GPIO_DATA_PIN20_Pos 20 +#define GPIO_DATA_PIN20_Msk (0x01 << GPIO_DATA_PIN20_Pos) +#define GPIO_DATA_PIN21_Pos 21 +#define GPIO_DATA_PIN21_Msk (0x01 << GPIO_DATA_PIN21_Pos) +#define GPIO_DATA_PIN22_Pos 22 +#define GPIO_DATA_PIN22_Msk (0x01 << GPIO_DATA_PIN22_Pos) +#define GPIO_DATA_PIN23_Pos 23 +#define GPIO_DATA_PIN23_Msk (0x01 << GPIO_DATA_PIN23_Pos) -#define GPIO_DATA_PIN0_Pos 0 -#define GPIO_DATA_PIN0_Msk (0x01 << GPIO_DATA_PIN0_Pos) -#define GPIO_DATA_PIN1_Pos 1 -#define GPIO_DATA_PIN1_Msk (0x01 << GPIO_DATA_PIN1_Pos) -#define GPIO_DATA_PIN2_Pos 2 -#define GPIO_DATA_PIN2_Msk (0x01 << GPIO_DATA_PIN2_Pos) -#define GPIO_DATA_PIN3_Pos 3 -#define GPIO_DATA_PIN3_Msk (0x01 << GPIO_DATA_PIN3_Pos) -#define GPIO_DATA_PIN4_Pos 4 -#define GPIO_DATA_PIN4_Msk (0x01 << GPIO_DATA_PIN4_Pos) -#define GPIO_DATA_PIN5_Pos 5 -#define GPIO_DATA_PIN5_Msk (0x01 << GPIO_DATA_PIN5_Pos) -#define GPIO_DATA_PIN6_Pos 6 -#define GPIO_DATA_PIN6_Msk (0x01 << GPIO_DATA_PIN6_Pos) -#define GPIO_DATA_PIN7_Pos 7 -#define GPIO_DATA_PIN7_Msk (0x01 << GPIO_DATA_PIN7_Pos) -#define GPIO_DATA_PIN8_Pos 8 -#define GPIO_DATA_PIN8_Msk (0x01 << GPIO_DATA_PIN8_Pos) -#define GPIO_DATA_PIN9_Pos 9 -#define GPIO_DATA_PIN9_Msk (0x01 << GPIO_DATA_PIN9_Pos) -#define GPIO_DATA_PIN10_Pos 10 -#define GPIO_DATA_PIN10_Msk (0x01 << GPIO_DATA_PIN10_Pos) -#define GPIO_DATA_PIN11_Pos 11 -#define GPIO_DATA_PIN11_Msk (0x01 << GPIO_DATA_PIN11_Pos) -#define GPIO_DATA_PIN12_Pos 12 -#define GPIO_DATA_PIN12_Msk (0x01 << GPIO_DATA_PIN12_Pos) -#define GPIO_DATA_PIN13_Pos 13 -#define GPIO_DATA_PIN13_Msk (0x01 << GPIO_DATA_PIN13_Pos) -#define GPIO_DATA_PIN14_Pos 14 -#define GPIO_DATA_PIN14_Msk (0x01 << GPIO_DATA_PIN14_Pos) -#define GPIO_DATA_PIN15_Pos 15 -#define GPIO_DATA_PIN15_Msk (0x01 << GPIO_DATA_PIN15_Pos) -#define GPIO_DATA_PIN16_Pos 16 -#define GPIO_DATA_PIN16_Msk (0x01 << GPIO_DATA_PIN16_Pos) -#define GPIO_DATA_PIN17_Pos 17 -#define GPIO_DATA_PIN17_Msk (0x01 << GPIO_DATA_PIN17_Pos) -#define GPIO_DATA_PIN18_Pos 18 -#define GPIO_DATA_PIN18_Msk (0x01 << GPIO_DATA_PIN18_Pos) -#define GPIO_DATA_PIN19_Pos 19 -#define GPIO_DATA_PIN19_Msk (0x01 << GPIO_DATA_PIN19_Pos) -#define GPIO_DATA_PIN20_Pos 20 -#define GPIO_DATA_PIN20_Msk (0x01 << GPIO_DATA_PIN20_Pos) -#define GPIO_DATA_PIN21_Pos 21 -#define GPIO_DATA_PIN21_Msk (0x01 << GPIO_DATA_PIN21_Pos) -#define GPIO_DATA_PIN22_Pos 22 -#define GPIO_DATA_PIN22_Msk (0x01 << GPIO_DATA_PIN22_Pos) -#define GPIO_DATA_PIN23_Pos 23 -#define GPIO_DATA_PIN23_Msk (0x01 << GPIO_DATA_PIN23_Pos) +#define GPIO_DIR_PIN0_Pos 0 +#define GPIO_DIR_PIN0_Msk (0x01 << GPIO_DIR_PIN0_Pos) +#define GPIO_DIR_PIN1_Pos 1 +#define GPIO_DIR_PIN1_Msk (0x01 << GPIO_DIR_PIN1_Pos) +#define GPIO_DIR_PIN2_Pos 2 +#define GPIO_DIR_PIN2_Msk (0x01 << GPIO_DIR_PIN2_Pos) +#define GPIO_DIR_PIN3_Pos 3 +#define GPIO_DIR_PIN3_Msk (0x01 << GPIO_DIR_PIN3_Pos) +#define GPIO_DIR_PIN4_Pos 4 +#define GPIO_DIR_PIN4_Msk (0x01 << GPIO_DIR_PIN4_Pos) +#define GPIO_DIR_PIN5_Pos 5 +#define GPIO_DIR_PIN5_Msk (0x01 << GPIO_DIR_PIN5_Pos) +#define GPIO_DIR_PIN6_Pos 6 +#define GPIO_DIR_PIN6_Msk (0x01 << GPIO_DIR_PIN6_Pos) +#define GPIO_DIR_PIN7_Pos 7 +#define GPIO_DIR_PIN7_Msk (0x01 << GPIO_DIR_PIN7_Pos) +#define GPIO_DIR_PIN8_Pos 8 +#define GPIO_DIR_PIN8_Msk (0x01 << GPIO_DIR_PIN8_Pos) +#define GPIO_DIR_PIN9_Pos 9 +#define GPIO_DIR_PIN9_Msk (0x01 << GPIO_DIR_PIN9_Pos) +#define GPIO_DIR_PIN10_Pos 10 +#define GPIO_DIR_PIN10_Msk (0x01 << GPIO_DIR_PIN10_Pos) +#define GPIO_DIR_PIN11_Pos 11 +#define GPIO_DIR_PIN11_Msk (0x01 << GPIO_DIR_PIN11_Pos) +#define GPIO_DIR_PIN12_Pos 12 +#define GPIO_DIR_PIN12_Msk (0x01 << GPIO_DIR_PIN12_Pos) +#define GPIO_DIR_PIN13_Pos 13 +#define GPIO_DIR_PIN13_Msk (0x01 << GPIO_DIR_PIN13_Pos) +#define GPIO_DIR_PIN14_Pos 14 +#define GPIO_DIR_PIN14_Msk (0x01 << GPIO_DIR_PIN14_Pos) +#define GPIO_DIR_PIN15_Pos 15 +#define GPIO_DIR_PIN15_Msk (0x01 << GPIO_DIR_PIN15_Pos) +#define GPIO_DIR_PIN16_Pos 16 +#define GPIO_DIR_PIN16_Msk (0x01 << GPIO_DIR_PIN16_Pos) +#define GPIO_DIR_PIN17_Pos 17 +#define GPIO_DIR_PIN17_Msk (0x01 << GPIO_DIR_PIN17_Pos) +#define GPIO_DIR_PIN18_Pos 18 +#define GPIO_DIR_PIN18_Msk (0x01 << GPIO_DIR_PIN18_Pos) +#define GPIO_DIR_PIN19_Pos 19 +#define GPIO_DIR_PIN19_Msk (0x01 << GPIO_DIR_PIN19_Pos) +#define GPIO_DIR_PIN20_Pos 20 +#define GPIO_DIR_PIN20_Msk (0x01 << GPIO_DIR_PIN20_Pos) +#define GPIO_DIR_PIN21_Pos 21 +#define GPIO_DIR_PIN21_Msk (0x01 << GPIO_DIR_PIN21_Pos) +#define GPIO_DIR_PIN22_Pos 22 +#define GPIO_DIR_PIN22_Msk (0x01 << GPIO_DIR_PIN22_Pos) +#define GPIO_DIR_PIN23_Pos 23 +#define GPIO_DIR_PIN23_Msk (0x01 << GPIO_DIR_PIN23_Pos) -#define GPIO_DIR_PIN0_Pos 0 -#define GPIO_DIR_PIN0_Msk (0x01 << GPIO_DIR_PIN0_Pos) -#define GPIO_DIR_PIN1_Pos 1 -#define GPIO_DIR_PIN1_Msk (0x01 << GPIO_DIR_PIN1_Pos) -#define GPIO_DIR_PIN2_Pos 2 -#define GPIO_DIR_PIN2_Msk (0x01 << GPIO_DIR_PIN2_Pos) -#define GPIO_DIR_PIN3_Pos 3 -#define GPIO_DIR_PIN3_Msk (0x01 << GPIO_DIR_PIN3_Pos) -#define GPIO_DIR_PIN4_Pos 4 -#define GPIO_DIR_PIN4_Msk (0x01 << GPIO_DIR_PIN4_Pos) -#define GPIO_DIR_PIN5_Pos 5 -#define GPIO_DIR_PIN5_Msk (0x01 << GPIO_DIR_PIN5_Pos) -#define GPIO_DIR_PIN6_Pos 6 -#define GPIO_DIR_PIN6_Msk (0x01 << GPIO_DIR_PIN6_Pos) -#define GPIO_DIR_PIN7_Pos 7 -#define GPIO_DIR_PIN7_Msk (0x01 << GPIO_DIR_PIN7_Pos) -#define GPIO_DIR_PIN8_Pos 8 -#define GPIO_DIR_PIN8_Msk (0x01 << GPIO_DIR_PIN8_Pos) -#define GPIO_DIR_PIN9_Pos 9 -#define GPIO_DIR_PIN9_Msk (0x01 << GPIO_DIR_PIN9_Pos) -#define GPIO_DIR_PIN10_Pos 10 -#define GPIO_DIR_PIN10_Msk (0x01 << GPIO_DIR_PIN10_Pos) -#define GPIO_DIR_PIN11_Pos 11 -#define GPIO_DIR_PIN11_Msk (0x01 << GPIO_DIR_PIN11_Pos) -#define GPIO_DIR_PIN12_Pos 12 -#define GPIO_DIR_PIN12_Msk (0x01 << GPIO_DIR_PIN12_Pos) -#define GPIO_DIR_PIN13_Pos 13 -#define GPIO_DIR_PIN13_Msk (0x01 << GPIO_DIR_PIN13_Pos) -#define GPIO_DIR_PIN14_Pos 14 -#define GPIO_DIR_PIN14_Msk (0x01 << GPIO_DIR_PIN14_Pos) -#define GPIO_DIR_PIN15_Pos 15 -#define GPIO_DIR_PIN15_Msk (0x01 << GPIO_DIR_PIN15_Pos) -#define GPIO_DIR_PIN16_Pos 16 -#define GPIO_DIR_PIN16_Msk (0x01 << GPIO_DIR_PIN16_Pos) -#define GPIO_DIR_PIN17_Pos 17 -#define GPIO_DIR_PIN17_Msk (0x01 << GPIO_DIR_PIN17_Pos) -#define GPIO_DIR_PIN18_Pos 18 -#define GPIO_DIR_PIN18_Msk (0x01 << GPIO_DIR_PIN18_Pos) -#define GPIO_DIR_PIN19_Pos 19 -#define GPIO_DIR_PIN19_Msk (0x01 << GPIO_DIR_PIN19_Pos) -#define GPIO_DIR_PIN20_Pos 20 -#define GPIO_DIR_PIN20_Msk (0x01 << GPIO_DIR_PIN20_Pos) -#define GPIO_DIR_PIN21_Pos 21 -#define GPIO_DIR_PIN21_Msk (0x01 << GPIO_DIR_PIN21_Pos) -#define GPIO_DIR_PIN22_Pos 22 -#define GPIO_DIR_PIN22_Msk (0x01 << GPIO_DIR_PIN22_Pos) -#define GPIO_DIR_PIN23_Pos 23 -#define GPIO_DIR_PIN23_Msk (0x01 << GPIO_DIR_PIN23_Pos) +#define GPIO_INTLVLTRG_PIN0_Pos 0 +#define GPIO_INTLVLTRG_PIN0_Msk (0x01 << GPIO_INTLVLTRG_PIN0_Pos) +#define GPIO_INTLVLTRG_PIN1_Pos 1 +#define GPIO_INTLVLTRG_PIN1_Msk (0x01 << GPIO_INTLVLTRG_PIN1_Pos) +#define GPIO_INTLVLTRG_PIN2_Pos 2 +#define GPIO_INTLVLTRG_PIN2_Msk (0x01 << GPIO_INTLVLTRG_PIN2_Pos) +#define GPIO_INTLVLTRG_PIN3_Pos 3 +#define GPIO_INTLVLTRG_PIN3_Msk (0x01 << GPIO_INTLVLTRG_PIN3_Pos) +#define GPIO_INTLVLTRG_PIN4_Pos 4 +#define GPIO_INTLVLTRG_PIN4_Msk (0x01 << GPIO_INTLVLTRG_PIN4_Pos) +#define GPIO_INTLVLTRG_PIN5_Pos 5 +#define GPIO_INTLVLTRG_PIN5_Msk (0x01 << GPIO_INTLVLTRG_PIN5_Pos) +#define GPIO_INTLVLTRG_PIN6_Pos 6 +#define GPIO_INTLVLTRG_PIN6_Msk (0x01 << GPIO_INTLVLTRG_PIN6_Pos) +#define GPIO_INTLVLTRG_PIN7_Pos 7 +#define GPIO_INTLVLTRG_PIN7_Msk (0x01 << GPIO_INTLVLTRG_PIN7_Pos) +#define GPIO_INTLVLTRG_PIN8_Pos 8 +#define GPIO_INTLVLTRG_PIN8_Msk (0x01 << GPIO_INTLVLTRG_PIN8_Pos) +#define GPIO_INTLVLTRG_PIN9_Pos 9 +#define GPIO_INTLVLTRG_PIN9_Msk (0x01 << GPIO_INTLVLTRG_PIN9_Pos) +#define GPIO_INTLVLTRG_PIN10_Pos 10 +#define GPIO_INTLVLTRG_PIN10_Msk (0x01 << GPIO_INTLVLTRG_PIN10_Pos) +#define GPIO_INTLVLTRG_PIN11_Pos 11 +#define GPIO_INTLVLTRG_PIN11_Msk (0x01 << GPIO_INTLVLTRG_PIN11_Pos) +#define GPIO_INTLVLTRG_PIN12_Pos 12 +#define GPIO_INTLVLTRG_PIN12_Msk (0x01 << GPIO_INTLVLTRG_PIN12_Pos) +#define GPIO_INTLVLTRG_PIN13_Pos 13 +#define GPIO_INTLVLTRG_PIN13_Msk (0x01 << GPIO_INTLVLTRG_PIN13_Pos) +#define GPIO_INTLVLTRG_PIN14_Pos 14 +#define GPIO_INTLVLTRG_PIN14_Msk (0x01 << GPIO_INTLVLTRG_PIN14_Pos) +#define GPIO_INTLVLTRG_PIN15_Pos 15 +#define GPIO_INTLVLTRG_PIN15_Msk (0x01 << GPIO_INTLVLTRG_PIN15_Pos) +#define GPIO_INTLVLTRG_PIN16_Pos 16 +#define GPIO_INTLVLTRG_PIN16_Msk (0x01 << GPIO_INTLVLTRG_PIN16_Pos) +#define GPIO_INTLVLTRG_PIN17_Pos 17 +#define GPIO_INTLVLTRG_PIN17_Msk (0x01 << GPIO_INTLVLTRG_PIN17_Pos) +#define GPIO_INTLVLTRG_PIN18_Pos 18 +#define GPIO_INTLVLTRG_PIN18_Msk (0x01 << GPIO_INTLVLTRG_PIN18_Pos) +#define GPIO_INTLVLTRG_PIN19_Pos 19 +#define GPIO_INTLVLTRG_PIN19_Msk (0x01 << GPIO_INTLVLTRG_PIN19_Pos) +#define GPIO_INTLVLTRG_PIN20_Pos 20 +#define GPIO_INTLVLTRG_PIN20_Msk (0x01 << GPIO_INTLVLTRG_PIN20_Pos) +#define GPIO_INTLVLTRG_PIN21_Pos 21 +#define GPIO_INTLVLTRG_PIN21_Msk (0x01 << GPIO_INTLVLTRG_PIN21_Pos) +#define GPIO_INTLVLTRG_PIN22_Pos 22 +#define GPIO_INTLVLTRG_PIN22_Msk (0x01 << GPIO_INTLVLTRG_PIN22_Pos) +#define GPIO_INTLVLTRG_PIN23_Pos 23 +#define GPIO_INTLVLTRG_PIN23_Msk (0x01 << GPIO_INTLVLTRG_PIN23_Pos) -#define GPIO_INTLVLTRG_PIN0_Pos 0 -#define GPIO_INTLVLTRG_PIN0_Msk (0x01 << GPIO_INTLVLTRG_PIN0_Pos) -#define GPIO_INTLVLTRG_PIN1_Pos 1 -#define GPIO_INTLVLTRG_PIN1_Msk (0x01 << GPIO_INTLVLTRG_PIN1_Pos) -#define GPIO_INTLVLTRG_PIN2_Pos 2 -#define GPIO_INTLVLTRG_PIN2_Msk (0x01 << GPIO_INTLVLTRG_PIN2_Pos) -#define GPIO_INTLVLTRG_PIN3_Pos 3 -#define GPIO_INTLVLTRG_PIN3_Msk (0x01 << GPIO_INTLVLTRG_PIN3_Pos) -#define GPIO_INTLVLTRG_PIN4_Pos 4 -#define GPIO_INTLVLTRG_PIN4_Msk (0x01 << GPIO_INTLVLTRG_PIN4_Pos) -#define GPIO_INTLVLTRG_PIN5_Pos 5 -#define GPIO_INTLVLTRG_PIN5_Msk (0x01 << GPIO_INTLVLTRG_PIN5_Pos) -#define GPIO_INTLVLTRG_PIN6_Pos 6 -#define GPIO_INTLVLTRG_PIN6_Msk (0x01 << GPIO_INTLVLTRG_PIN6_Pos) -#define GPIO_INTLVLTRG_PIN7_Pos 7 -#define GPIO_INTLVLTRG_PIN7_Msk (0x01 << GPIO_INTLVLTRG_PIN7_Pos) -#define GPIO_INTLVLTRG_PIN8_Pos 8 -#define GPIO_INTLVLTRG_PIN8_Msk (0x01 << GPIO_INTLVLTRG_PIN8_Pos) -#define GPIO_INTLVLTRG_PIN9_Pos 9 -#define GPIO_INTLVLTRG_PIN9_Msk (0x01 << GPIO_INTLVLTRG_PIN9_Pos) -#define GPIO_INTLVLTRG_PIN10_Pos 10 -#define GPIO_INTLVLTRG_PIN10_Msk (0x01 << GPIO_INTLVLTRG_PIN10_Pos) -#define GPIO_INTLVLTRG_PIN11_Pos 11 -#define GPIO_INTLVLTRG_PIN11_Msk (0x01 << GPIO_INTLVLTRG_PIN11_Pos) -#define GPIO_INTLVLTRG_PIN12_Pos 12 -#define GPIO_INTLVLTRG_PIN12_Msk (0x01 << GPIO_INTLVLTRG_PIN12_Pos) -#define GPIO_INTLVLTRG_PIN13_Pos 13 -#define GPIO_INTLVLTRG_PIN13_Msk (0x01 << GPIO_INTLVLTRG_PIN13_Pos) -#define GPIO_INTLVLTRG_PIN14_Pos 14 -#define GPIO_INTLVLTRG_PIN14_Msk (0x01 << GPIO_INTLVLTRG_PIN14_Pos) -#define GPIO_INTLVLTRG_PIN15_Pos 15 -#define GPIO_INTLVLTRG_PIN15_Msk (0x01 << GPIO_INTLVLTRG_PIN15_Pos) -#define GPIO_INTLVLTRG_PIN16_Pos 16 -#define GPIO_INTLVLTRG_PIN16_Msk (0x01 << GPIO_INTLVLTRG_PIN16_Pos) -#define GPIO_INTLVLTRG_PIN17_Pos 17 -#define GPIO_INTLVLTRG_PIN17_Msk (0x01 << GPIO_INTLVLTRG_PIN17_Pos) -#define GPIO_INTLVLTRG_PIN18_Pos 18 -#define GPIO_INTLVLTRG_PIN18_Msk (0x01 << GPIO_INTLVLTRG_PIN18_Pos) -#define GPIO_INTLVLTRG_PIN19_Pos 19 -#define GPIO_INTLVLTRG_PIN19_Msk (0x01 << GPIO_INTLVLTRG_PIN19_Pos) -#define GPIO_INTLVLTRG_PIN20_Pos 20 -#define GPIO_INTLVLTRG_PIN20_Msk (0x01 << GPIO_INTLVLTRG_PIN20_Pos) -#define GPIO_INTLVLTRG_PIN21_Pos 21 -#define GPIO_INTLVLTRG_PIN21_Msk (0x01 << GPIO_INTLVLTRG_PIN21_Pos) -#define GPIO_INTLVLTRG_PIN22_Pos 22 -#define GPIO_INTLVLTRG_PIN22_Msk (0x01 << GPIO_INTLVLTRG_PIN22_Pos) -#define GPIO_INTLVLTRG_PIN23_Pos 23 -#define GPIO_INTLVLTRG_PIN23_Msk (0x01 << GPIO_INTLVLTRG_PIN23_Pos) +#define GPIO_INTBE_PIN0_Pos 0 +#define GPIO_INTBE_PIN0_Msk (0x01 << GPIO_INTBE_PIN0_Pos) +#define GPIO_INTBE_PIN1_Pos 1 +#define GPIO_INTBE_PIN1_Msk (0x01 << GPIO_INTBE_PIN1_Pos) +#define GPIO_INTBE_PIN2_Pos 2 +#define GPIO_INTBE_PIN2_Msk (0x01 << GPIO_INTBE_PIN2_Pos) +#define GPIO_INTBE_PIN3_Pos 3 +#define GPIO_INTBE_PIN3_Msk (0x01 << GPIO_INTBE_PIN3_Pos) +#define GPIO_INTBE_PIN4_Pos 4 +#define GPIO_INTBE_PIN4_Msk (0x01 << GPIO_INTBE_PIN4_Pos) +#define GPIO_INTBE_PIN5_Pos 5 +#define GPIO_INTBE_PIN5_Msk (0x01 << GPIO_INTBE_PIN5_Pos) +#define GPIO_INTBE_PIN6_Pos 6 +#define GPIO_INTBE_PIN6_Msk (0x01 << GPIO_INTBE_PIN6_Pos) +#define GPIO_INTBE_PIN7_Pos 7 +#define GPIO_INTBE_PIN7_Msk (0x01 << GPIO_INTBE_PIN7_Pos) +#define GPIO_INTBE_PIN8_Pos 8 +#define GPIO_INTBE_PIN8_Msk (0x01 << GPIO_INTBE_PIN8_Pos) +#define GPIO_INTBE_PIN9_Pos 9 +#define GPIO_INTBE_PIN9_Msk (0x01 << GPIO_INTBE_PIN9_Pos) +#define GPIO_INTBE_PIN10_Pos 10 +#define GPIO_INTBE_PIN10_Msk (0x01 << GPIO_INTBE_PIN10_Pos) +#define GPIO_INTBE_PIN11_Pos 11 +#define GPIO_INTBE_PIN11_Msk (0x01 << GPIO_INTBE_PIN11_Pos) +#define GPIO_INTBE_PIN12_Pos 12 +#define GPIO_INTBE_PIN12_Msk (0x01 << GPIO_INTBE_PIN12_Pos) +#define GPIO_INTBE_PIN13_Pos 13 +#define GPIO_INTBE_PIN13_Msk (0x01 << GPIO_INTBE_PIN13_Pos) +#define GPIO_INTBE_PIN14_Pos 14 +#define GPIO_INTBE_PIN14_Msk (0x01 << GPIO_INTBE_PIN14_Pos) +#define GPIO_INTBE_PIN15_Pos 15 +#define GPIO_INTBE_PIN15_Msk (0x01 << GPIO_INTBE_PIN15_Pos) +#define GPIO_INTBE_PIN16_Pos 16 +#define GPIO_INTBE_PIN16_Msk (0x01 << GPIO_INTBE_PIN16_Pos) +#define GPIO_INTBE_PIN17_Pos 17 +#define GPIO_INTBE_PIN17_Msk (0x01 << GPIO_INTBE_PIN17_Pos) +#define GPIO_INTBE_PIN18_Pos 18 +#define GPIO_INTBE_PIN18_Msk (0x01 << GPIO_INTBE_PIN18_Pos) +#define GPIO_INTBE_PIN19_Pos 19 +#define GPIO_INTBE_PIN19_Msk (0x01 << GPIO_INTBE_PIN19_Pos) +#define GPIO_INTBE_PIN20_Pos 20 +#define GPIO_INTBE_PIN20_Msk (0x01 << GPIO_INTBE_PIN20_Pos) +#define GPIO_INTBE_PIN21_Pos 21 +#define GPIO_INTBE_PIN21_Msk (0x01 << GPIO_INTBE_PIN21_Pos) +#define GPIO_INTBE_PIN22_Pos 22 +#define GPIO_INTBE_PIN22_Msk (0x01 << GPIO_INTBE_PIN22_Pos) +#define GPIO_INTBE_PIN23_Pos 23 +#define GPIO_INTBE_PIN23_Msk (0x01 << GPIO_INTBE_PIN23_Pos) -#define GPIO_INTBE_PIN0_Pos 0 -#define GPIO_INTBE_PIN0_Msk (0x01 << GPIO_INTBE_PIN0_Pos) -#define GPIO_INTBE_PIN1_Pos 1 -#define GPIO_INTBE_PIN1_Msk (0x01 << GPIO_INTBE_PIN1_Pos) -#define GPIO_INTBE_PIN2_Pos 2 -#define GPIO_INTBE_PIN2_Msk (0x01 << GPIO_INTBE_PIN2_Pos) -#define GPIO_INTBE_PIN3_Pos 3 -#define GPIO_INTBE_PIN3_Msk (0x01 << GPIO_INTBE_PIN3_Pos) -#define GPIO_INTBE_PIN4_Pos 4 -#define GPIO_INTBE_PIN4_Msk (0x01 << GPIO_INTBE_PIN4_Pos) -#define GPIO_INTBE_PIN5_Pos 5 -#define GPIO_INTBE_PIN5_Msk (0x01 << GPIO_INTBE_PIN5_Pos) -#define GPIO_INTBE_PIN6_Pos 6 -#define GPIO_INTBE_PIN6_Msk (0x01 << GPIO_INTBE_PIN6_Pos) -#define GPIO_INTBE_PIN7_Pos 7 -#define GPIO_INTBE_PIN7_Msk (0x01 << GPIO_INTBE_PIN7_Pos) -#define GPIO_INTBE_PIN8_Pos 8 -#define GPIO_INTBE_PIN8_Msk (0x01 << GPIO_INTBE_PIN8_Pos) -#define GPIO_INTBE_PIN9_Pos 9 -#define GPIO_INTBE_PIN9_Msk (0x01 << GPIO_INTBE_PIN9_Pos) -#define GPIO_INTBE_PIN10_Pos 10 -#define GPIO_INTBE_PIN10_Msk (0x01 << GPIO_INTBE_PIN10_Pos) -#define GPIO_INTBE_PIN11_Pos 11 -#define GPIO_INTBE_PIN11_Msk (0x01 << GPIO_INTBE_PIN11_Pos) -#define GPIO_INTBE_PIN12_Pos 12 -#define GPIO_INTBE_PIN12_Msk (0x01 << GPIO_INTBE_PIN12_Pos) -#define GPIO_INTBE_PIN13_Pos 13 -#define GPIO_INTBE_PIN13_Msk (0x01 << GPIO_INTBE_PIN13_Pos) -#define GPIO_INTBE_PIN14_Pos 14 -#define GPIO_INTBE_PIN14_Msk (0x01 << GPIO_INTBE_PIN14_Pos) -#define GPIO_INTBE_PIN15_Pos 15 -#define GPIO_INTBE_PIN15_Msk (0x01 << GPIO_INTBE_PIN15_Pos) -#define GPIO_INTBE_PIN16_Pos 16 -#define GPIO_INTBE_PIN16_Msk (0x01 << GPIO_INTBE_PIN16_Pos) -#define GPIO_INTBE_PIN17_Pos 17 -#define GPIO_INTBE_PIN17_Msk (0x01 << GPIO_INTBE_PIN17_Pos) -#define GPIO_INTBE_PIN18_Pos 18 -#define GPIO_INTBE_PIN18_Msk (0x01 << GPIO_INTBE_PIN18_Pos) -#define GPIO_INTBE_PIN19_Pos 19 -#define GPIO_INTBE_PIN19_Msk (0x01 << GPIO_INTBE_PIN19_Pos) -#define GPIO_INTBE_PIN20_Pos 20 -#define GPIO_INTBE_PIN20_Msk (0x01 << GPIO_INTBE_PIN20_Pos) -#define GPIO_INTBE_PIN21_Pos 21 -#define GPIO_INTBE_PIN21_Msk (0x01 << GPIO_INTBE_PIN21_Pos) -#define GPIO_INTBE_PIN22_Pos 22 -#define GPIO_INTBE_PIN22_Msk (0x01 << GPIO_INTBE_PIN22_Pos) -#define GPIO_INTBE_PIN23_Pos 23 -#define GPIO_INTBE_PIN23_Msk (0x01 << GPIO_INTBE_PIN23_Pos) +#define GPIO_INTRISEEN_PIN0_Pos 0 +#define GPIO_INTRISEEN_PIN0_Msk (0x01 << GPIO_INTRISEEN_PIN0_Pos) +#define GPIO_INTRISEEN_PIN1_Pos 1 +#define GPIO_INTRISEEN_PIN1_Msk (0x01 << GPIO_INTRISEEN_PIN1_Pos) +#define GPIO_INTRISEEN_PIN2_Pos 2 +#define GPIO_INTRISEEN_PIN2_Msk (0x01 << GPIO_INTRISEEN_PIN2_Pos) +#define GPIO_INTRISEEN_PIN3_Pos 3 +#define GPIO_INTRISEEN_PIN3_Msk (0x01 << GPIO_INTRISEEN_PIN3_Pos) +#define GPIO_INTRISEEN_PIN4_Pos 4 +#define GPIO_INTRISEEN_PIN4_Msk (0x01 << GPIO_INTRISEEN_PIN4_Pos) +#define GPIO_INTRISEEN_PIN5_Pos 5 +#define GPIO_INTRISEEN_PIN5_Msk (0x01 << GPIO_INTRISEEN_PIN5_Pos) +#define GPIO_INTRISEEN_PIN6_Pos 6 +#define GPIO_INTRISEEN_PIN6_Msk (0x01 << GPIO_INTRISEEN_PIN6_Pos) +#define GPIO_INTRISEEN_PIN7_Pos 7 +#define GPIO_INTRISEEN_PIN7_Msk (0x01 << GPIO_INTRISEEN_PIN7_Pos) +#define GPIO_INTRISEEN_PIN8_Pos 8 +#define GPIO_INTRISEEN_PIN8_Msk (0x01 << GPIO_INTRISEEN_PIN8_Pos) +#define GPIO_INTRISEEN_PIN9_Pos 9 +#define GPIO_INTRISEEN_PIN9_Msk (0x01 << GPIO_INTRISEEN_PIN9_Pos) +#define GPIO_INTRISEEN_PIN10_Pos 10 +#define GPIO_INTRISEEN_PIN10_Msk (0x01 << GPIO_INTRISEEN_PIN10_Pos) +#define GPIO_INTRISEEN_PIN11_Pos 11 +#define GPIO_INTRISEEN_PIN11_Msk (0x01 << GPIO_INTRISEEN_PIN11_Pos) +#define GPIO_INTRISEEN_PIN12_Pos 12 +#define GPIO_INTRISEEN_PIN12_Msk (0x01 << GPIO_INTRISEEN_PIN12_Pos) +#define GPIO_INTRISEEN_PIN13_Pos 13 +#define GPIO_INTRISEEN_PIN13_Msk (0x01 << GPIO_INTRISEEN_PIN13_Pos) +#define GPIO_INTRISEEN_PIN14_Pos 14 +#define GPIO_INTRISEEN_PIN14_Msk (0x01 << GPIO_INTRISEEN_PIN14_Pos) +#define GPIO_INTRISEEN_PIN15_Pos 15 +#define GPIO_INTRISEEN_PIN15_Msk (0x01 << GPIO_INTRISEEN_PIN15_Pos) +#define GPIO_INTRISEEN_PIN16_Pos 16 +#define GPIO_INTRISEEN_PIN16_Msk (0x01 << GPIO_INTRISEEN_PIN16_Pos) +#define GPIO_INTRISEEN_PIN17_Pos 17 +#define GPIO_INTRISEEN_PIN17_Msk (0x01 << GPIO_INTRISEEN_PIN17_Pos) +#define GPIO_INTRISEEN_PIN18_Pos 18 +#define GPIO_INTRISEEN_PIN18_Msk (0x01 << GPIO_INTRISEEN_PIN18_Pos) +#define GPIO_INTRISEEN_PIN19_Pos 19 +#define GPIO_INTRISEEN_PIN19_Msk (0x01 << GPIO_INTRISEEN_PIN19_Pos) +#define GPIO_INTRISEEN_PIN20_Pos 20 +#define GPIO_INTRISEEN_PIN20_Msk (0x01 << GPIO_INTRISEEN_PIN20_Pos) +#define GPIO_INTRISEEN_PIN21_Pos 21 +#define GPIO_INTRISEEN_PIN21_Msk (0x01 << GPIO_INTRISEEN_PIN21_Pos) +#define GPIO_INTRISEEN_PIN22_Pos 22 +#define GPIO_INTRISEEN_PIN22_Msk (0x01 << GPIO_INTRISEEN_PIN22_Pos) +#define GPIO_INTRISEEN_PIN23_Pos 23 +#define GPIO_INTRISEEN_PIN23_Msk (0x01 << GPIO_INTRISEEN_PIN23_Pos) -#define GPIO_INTRISEEN_PIN0_Pos 0 -#define GPIO_INTRISEEN_PIN0_Msk (0x01 << GPIO_INTRISEEN_PIN0_Pos) -#define GPIO_INTRISEEN_PIN1_Pos 1 -#define GPIO_INTRISEEN_PIN1_Msk (0x01 << GPIO_INTRISEEN_PIN1_Pos) -#define GPIO_INTRISEEN_PIN2_Pos 2 -#define GPIO_INTRISEEN_PIN2_Msk (0x01 << GPIO_INTRISEEN_PIN2_Pos) -#define GPIO_INTRISEEN_PIN3_Pos 3 -#define GPIO_INTRISEEN_PIN3_Msk (0x01 << GPIO_INTRISEEN_PIN3_Pos) -#define GPIO_INTRISEEN_PIN4_Pos 4 -#define GPIO_INTRISEEN_PIN4_Msk (0x01 << GPIO_INTRISEEN_PIN4_Pos) -#define GPIO_INTRISEEN_PIN5_Pos 5 -#define GPIO_INTRISEEN_PIN5_Msk (0x01 << GPIO_INTRISEEN_PIN5_Pos) -#define GPIO_INTRISEEN_PIN6_Pos 6 -#define GPIO_INTRISEEN_PIN6_Msk (0x01 << GPIO_INTRISEEN_PIN6_Pos) -#define GPIO_INTRISEEN_PIN7_Pos 7 -#define GPIO_INTRISEEN_PIN7_Msk (0x01 << GPIO_INTRISEEN_PIN7_Pos) -#define GPIO_INTRISEEN_PIN8_Pos 8 -#define GPIO_INTRISEEN_PIN8_Msk (0x01 << GPIO_INTRISEEN_PIN8_Pos) -#define GPIO_INTRISEEN_PIN9_Pos 9 -#define GPIO_INTRISEEN_PIN9_Msk (0x01 << GPIO_INTRISEEN_PIN9_Pos) -#define GPIO_INTRISEEN_PIN10_Pos 10 -#define GPIO_INTRISEEN_PIN10_Msk (0x01 << GPIO_INTRISEEN_PIN10_Pos) -#define GPIO_INTRISEEN_PIN11_Pos 11 -#define GPIO_INTRISEEN_PIN11_Msk (0x01 << GPIO_INTRISEEN_PIN11_Pos) -#define GPIO_INTRISEEN_PIN12_Pos 12 -#define GPIO_INTRISEEN_PIN12_Msk (0x01 << GPIO_INTRISEEN_PIN12_Pos) -#define GPIO_INTRISEEN_PIN13_Pos 13 -#define GPIO_INTRISEEN_PIN13_Msk (0x01 << GPIO_INTRISEEN_PIN13_Pos) -#define GPIO_INTRISEEN_PIN14_Pos 14 -#define GPIO_INTRISEEN_PIN14_Msk (0x01 << GPIO_INTRISEEN_PIN14_Pos) -#define GPIO_INTRISEEN_PIN15_Pos 15 -#define GPIO_INTRISEEN_PIN15_Msk (0x01 << GPIO_INTRISEEN_PIN15_Pos) -#define GPIO_INTRISEEN_PIN16_Pos 16 -#define GPIO_INTRISEEN_PIN16_Msk (0x01 << GPIO_INTRISEEN_PIN16_Pos) -#define GPIO_INTRISEEN_PIN17_Pos 17 -#define GPIO_INTRISEEN_PIN17_Msk (0x01 << GPIO_INTRISEEN_PIN17_Pos) -#define GPIO_INTRISEEN_PIN18_Pos 18 -#define GPIO_INTRISEEN_PIN18_Msk (0x01 << GPIO_INTRISEEN_PIN18_Pos) -#define GPIO_INTRISEEN_PIN19_Pos 19 -#define GPIO_INTRISEEN_PIN19_Msk (0x01 << GPIO_INTRISEEN_PIN19_Pos) -#define GPIO_INTRISEEN_PIN20_Pos 20 -#define GPIO_INTRISEEN_PIN20_Msk (0x01 << GPIO_INTRISEEN_PIN20_Pos) -#define GPIO_INTRISEEN_PIN21_Pos 21 -#define GPIO_INTRISEEN_PIN21_Msk (0x01 << GPIO_INTRISEEN_PIN21_Pos) -#define GPIO_INTRISEEN_PIN22_Pos 22 -#define GPIO_INTRISEEN_PIN22_Msk (0x01 << GPIO_INTRISEEN_PIN22_Pos) -#define GPIO_INTRISEEN_PIN23_Pos 23 -#define GPIO_INTRISEEN_PIN23_Msk (0x01 << GPIO_INTRISEEN_PIN23_Pos) +#define GPIO_INTEN_PIN0_Pos 0 +#define GPIO_INTEN_PIN0_Msk (0x01 << GPIO_INTEN_PIN0_Pos) +#define GPIO_INTEN_PIN1_Pos 1 +#define GPIO_INTEN_PIN1_Msk (0x01 << GPIO_INTEN_PIN1_Pos) +#define GPIO_INTEN_PIN2_Pos 2 +#define GPIO_INTEN_PIN2_Msk (0x01 << GPIO_INTEN_PIN2_Pos) +#define GPIO_INTEN_PIN3_Pos 3 +#define GPIO_INTEN_PIN3_Msk (0x01 << GPIO_INTEN_PIN3_Pos) +#define GPIO_INTEN_PIN4_Pos 4 +#define GPIO_INTEN_PIN4_Msk (0x01 << GPIO_INTEN_PIN4_Pos) +#define GPIO_INTEN_PIN5_Pos 5 +#define GPIO_INTEN_PIN5_Msk (0x01 << GPIO_INTEN_PIN5_Pos) +#define GPIO_INTEN_PIN6_Pos 6 +#define GPIO_INTEN_PIN6_Msk (0x01 << GPIO_INTEN_PIN6_Pos) +#define GPIO_INTEN_PIN7_Pos 7 +#define GPIO_INTEN_PIN7_Msk (0x01 << GPIO_INTEN_PIN7_Pos) +#define GPIO_INTEN_PIN8_Pos 8 +#define GPIO_INTEN_PIN8_Msk (0x01 << GPIO_INTEN_PIN8_Pos) +#define GPIO_INTEN_PIN9_Pos 9 +#define GPIO_INTEN_PIN9_Msk (0x01 << GPIO_INTEN_PIN9_Pos) +#define GPIO_INTEN_PIN10_Pos 10 +#define GPIO_INTEN_PIN10_Msk (0x01 << GPIO_INTEN_PIN10_Pos) +#define GPIO_INTEN_PIN11_Pos 11 +#define GPIO_INTEN_PIN11_Msk (0x01 << GPIO_INTEN_PIN11_Pos) +#define GPIO_INTEN_PIN12_Pos 12 +#define GPIO_INTEN_PIN12_Msk (0x01 << GPIO_INTEN_PIN12_Pos) +#define GPIO_INTEN_PIN13_Pos 13 +#define GPIO_INTEN_PIN13_Msk (0x01 << GPIO_INTEN_PIN13_Pos) +#define GPIO_INTEN_PIN14_Pos 14 +#define GPIO_INTEN_PIN14_Msk (0x01 << GPIO_INTEN_PIN14_Pos) +#define GPIO_INTEN_PIN15_Pos 15 +#define GPIO_INTEN_PIN15_Msk (0x01 << GPIO_INTEN_PIN15_Pos) +#define GPIO_INTEN_PIN16_Pos 16 +#define GPIO_INTEN_PIN16_Msk (0x01 << GPIO_INTEN_PIN16_Pos) +#define GPIO_INTEN_PIN17_Pos 17 +#define GPIO_INTEN_PIN17_Msk (0x01 << GPIO_INTEN_PIN17_Pos) +#define GPIO_INTEN_PIN18_Pos 18 +#define GPIO_INTEN_PIN18_Msk (0x01 << GPIO_INTEN_PIN18_Pos) +#define GPIO_INTEN_PIN19_Pos 19 +#define GPIO_INTEN_PIN19_Msk (0x01 << GPIO_INTEN_PIN19_Pos) +#define GPIO_INTEN_PIN20_Pos 20 +#define GPIO_INTEN_PIN20_Msk (0x01 << GPIO_INTEN_PIN20_Pos) +#define GPIO_INTEN_PIN21_Pos 21 +#define GPIO_INTEN_PIN21_Msk (0x01 << GPIO_INTEN_PIN21_Pos) +#define GPIO_INTEN_PIN22_Pos 22 +#define GPIO_INTEN_PIN22_Msk (0x01 << GPIO_INTEN_PIN22_Pos) +#define GPIO_INTEN_PIN23_Pos 23 +#define GPIO_INTEN_PIN23_Msk (0x01 << GPIO_INTEN_PIN23_Pos) -#define GPIO_INTEN_PIN0_Pos 0 -#define GPIO_INTEN_PIN0_Msk (0x01 << GPIO_INTEN_PIN0_Pos) -#define GPIO_INTEN_PIN1_Pos 1 -#define GPIO_INTEN_PIN1_Msk (0x01 << GPIO_INTEN_PIN1_Pos) -#define GPIO_INTEN_PIN2_Pos 2 -#define GPIO_INTEN_PIN2_Msk (0x01 << GPIO_INTEN_PIN2_Pos) -#define GPIO_INTEN_PIN3_Pos 3 -#define GPIO_INTEN_PIN3_Msk (0x01 << GPIO_INTEN_PIN3_Pos) -#define GPIO_INTEN_PIN4_Pos 4 -#define GPIO_INTEN_PIN4_Msk (0x01 << GPIO_INTEN_PIN4_Pos) -#define GPIO_INTEN_PIN5_Pos 5 -#define GPIO_INTEN_PIN5_Msk (0x01 << GPIO_INTEN_PIN5_Pos) -#define GPIO_INTEN_PIN6_Pos 6 -#define GPIO_INTEN_PIN6_Msk (0x01 << GPIO_INTEN_PIN6_Pos) -#define GPIO_INTEN_PIN7_Pos 7 -#define GPIO_INTEN_PIN7_Msk (0x01 << GPIO_INTEN_PIN7_Pos) -#define GPIO_INTEN_PIN8_Pos 8 -#define GPIO_INTEN_PIN8_Msk (0x01 << GPIO_INTEN_PIN8_Pos) -#define GPIO_INTEN_PIN9_Pos 9 -#define GPIO_INTEN_PIN9_Msk (0x01 << GPIO_INTEN_PIN9_Pos) -#define GPIO_INTEN_PIN10_Pos 10 -#define GPIO_INTEN_PIN10_Msk (0x01 << GPIO_INTEN_PIN10_Pos) -#define GPIO_INTEN_PIN11_Pos 11 -#define GPIO_INTEN_PIN11_Msk (0x01 << GPIO_INTEN_PIN11_Pos) -#define GPIO_INTEN_PIN12_Pos 12 -#define GPIO_INTEN_PIN12_Msk (0x01 << GPIO_INTEN_PIN12_Pos) -#define GPIO_INTEN_PIN13_Pos 13 -#define GPIO_INTEN_PIN13_Msk (0x01 << GPIO_INTEN_PIN13_Pos) -#define GPIO_INTEN_PIN14_Pos 14 -#define GPIO_INTEN_PIN14_Msk (0x01 << GPIO_INTEN_PIN14_Pos) -#define GPIO_INTEN_PIN15_Pos 15 -#define GPIO_INTEN_PIN15_Msk (0x01 << GPIO_INTEN_PIN15_Pos) -#define GPIO_INTEN_PIN16_Pos 16 -#define GPIO_INTEN_PIN16_Msk (0x01 << GPIO_INTEN_PIN16_Pos) -#define GPIO_INTEN_PIN17_Pos 17 -#define GPIO_INTEN_PIN17_Msk (0x01 << GPIO_INTEN_PIN17_Pos) -#define GPIO_INTEN_PIN18_Pos 18 -#define GPIO_INTEN_PIN18_Msk (0x01 << GPIO_INTEN_PIN18_Pos) -#define GPIO_INTEN_PIN19_Pos 19 -#define GPIO_INTEN_PIN19_Msk (0x01 << GPIO_INTEN_PIN19_Pos) -#define GPIO_INTEN_PIN20_Pos 20 -#define GPIO_INTEN_PIN20_Msk (0x01 << GPIO_INTEN_PIN20_Pos) -#define GPIO_INTEN_PIN21_Pos 21 -#define GPIO_INTEN_PIN21_Msk (0x01 << GPIO_INTEN_PIN21_Pos) -#define GPIO_INTEN_PIN22_Pos 22 -#define GPIO_INTEN_PIN22_Msk (0x01 << GPIO_INTEN_PIN22_Pos) -#define GPIO_INTEN_PIN23_Pos 23 -#define GPIO_INTEN_PIN23_Msk (0x01 << GPIO_INTEN_PIN23_Pos) +#define GPIO_INTRAWSTAT_PIN0_Pos 0 +#define GPIO_INTRAWSTAT_PIN0_Msk (0x01 << GPIO_INTRAWSTAT_PIN0_Pos) +#define GPIO_INTRAWSTAT_PIN1_Pos 1 +#define GPIO_INTRAWSTAT_PIN1_Msk (0x01 << GPIO_INTRAWSTAT_PIN1_Pos) +#define GPIO_INTRAWSTAT_PIN2_Pos 2 +#define GPIO_INTRAWSTAT_PIN2_Msk (0x01 << GPIO_INTRAWSTAT_PIN2_Pos) +#define GPIO_INTRAWSTAT_PIN3_Pos 3 +#define GPIO_INTRAWSTAT_PIN3_Msk (0x01 << GPIO_INTRAWSTAT_PIN3_Pos) +#define GPIO_INTRAWSTAT_PIN4_Pos 4 +#define GPIO_INTRAWSTAT_PIN4_Msk (0x01 << GPIO_INTRAWSTAT_PIN4_Pos) +#define GPIO_INTRAWSTAT_PIN5_Pos 5 +#define GPIO_INTRAWSTAT_PIN5_Msk (0x01 << GPIO_INTRAWSTAT_PIN5_Pos) +#define GPIO_INTRAWSTAT_PIN6_Pos 6 +#define GPIO_INTRAWSTAT_PIN6_Msk (0x01 << GPIO_INTRAWSTAT_PIN6_Pos) +#define GPIO_INTRAWSTAT_PIN7_Pos 7 +#define GPIO_INTRAWSTAT_PIN7_Msk (0x01 << GPIO_INTRAWSTAT_PIN7_Pos) +#define GPIO_INTRAWSTAT_PIN8_Pos 8 +#define GPIO_INTRAWSTAT_PIN8_Msk (0x01 << GPIO_INTRAWSTAT_PIN8_Pos) +#define GPIO_INTRAWSTAT_PIN9_Pos 9 +#define GPIO_INTRAWSTAT_PIN9_Msk (0x01 << GPIO_INTRAWSTAT_PIN9_Pos) +#define GPIO_INTRAWSTAT_PIN10_Pos 10 +#define GPIO_INTRAWSTAT_PIN10_Msk (0x01 << GPIO_INTRAWSTAT_PIN10_Pos) +#define GPIO_INTRAWSTAT_PIN11_Pos 11 +#define GPIO_INTRAWSTAT_PIN11_Msk (0x01 << GPIO_INTRAWSTAT_PIN11_Pos) +#define GPIO_INTRAWSTAT_PIN12_Pos 12 +#define GPIO_INTRAWSTAT_PIN12_Msk (0x01 << GPIO_INTRAWSTAT_PIN12_Pos) +#define GPIO_INTRAWSTAT_PIN13_Pos 13 +#define GPIO_INTRAWSTAT_PIN13_Msk (0x01 << GPIO_INTRAWSTAT_PIN13_Pos) +#define GPIO_INTRAWSTAT_PIN14_Pos 14 +#define GPIO_INTRAWSTAT_PIN14_Msk (0x01 << GPIO_INTRAWSTAT_PIN14_Pos) +#define GPIO_INTRAWSTAT_PIN15_Pos 15 +#define GPIO_INTRAWSTAT_PIN15_Msk (0x01 << GPIO_INTRAWSTAT_PIN15_Pos) +#define GPIO_INTRAWSTAT_PIN16_Pos 16 +#define GPIO_INTRAWSTAT_PIN16_Msk (0x01 << GPIO_INTRAWSTAT_PIN16_Pos) +#define GPIO_INTRAWSTAT_PIN17_Pos 17 +#define GPIO_INTRAWSTAT_PIN17_Msk (0x01 << GPIO_INTRAWSTAT_PIN17_Pos) +#define GPIO_INTRAWSTAT_PIN18_Pos 18 +#define GPIO_INTRAWSTAT_PIN18_Msk (0x01 << GPIO_INTRAWSTAT_PIN18_Pos) +#define GPIO_INTRAWSTAT_PIN19_Pos 19 +#define GPIO_INTRAWSTAT_PIN19_Msk (0x01 << GPIO_INTRAWSTAT_PIN19_Pos) +#define GPIO_INTRAWSTAT_PIN20_Pos 20 +#define GPIO_INTRAWSTAT_PIN20_Msk (0x01 << GPIO_INTRAWSTAT_PIN20_Pos) +#define GPIO_INTRAWSTAT_PIN21_Pos 21 +#define GPIO_INTRAWSTAT_PIN21_Msk (0x01 << GPIO_INTRAWSTAT_PIN21_Pos) +#define GPIO_INTRAWSTAT_PIN22_Pos 22 +#define GPIO_INTRAWSTAT_PIN22_Msk (0x01 << GPIO_INTRAWSTAT_PIN22_Pos) +#define GPIO_INTRAWSTAT_PIN23_Pos 23 +#define GPIO_INTRAWSTAT_PIN23_Msk (0x01 << GPIO_INTRAWSTAT_PIN23_Pos) -#define GPIO_INTRAWSTAT_PIN0_Pos 0 -#define GPIO_INTRAWSTAT_PIN0_Msk (0x01 << GPIO_INTRAWSTAT_PIN0_Pos) -#define GPIO_INTRAWSTAT_PIN1_Pos 1 -#define GPIO_INTRAWSTAT_PIN1_Msk (0x01 << GPIO_INTRAWSTAT_PIN1_Pos) -#define GPIO_INTRAWSTAT_PIN2_Pos 2 -#define GPIO_INTRAWSTAT_PIN2_Msk (0x01 << GPIO_INTRAWSTAT_PIN2_Pos) -#define GPIO_INTRAWSTAT_PIN3_Pos 3 -#define GPIO_INTRAWSTAT_PIN3_Msk (0x01 << GPIO_INTRAWSTAT_PIN3_Pos) -#define GPIO_INTRAWSTAT_PIN4_Pos 4 -#define GPIO_INTRAWSTAT_PIN4_Msk (0x01 << GPIO_INTRAWSTAT_PIN4_Pos) -#define GPIO_INTRAWSTAT_PIN5_Pos 5 -#define GPIO_INTRAWSTAT_PIN5_Msk (0x01 << GPIO_INTRAWSTAT_PIN5_Pos) -#define GPIO_INTRAWSTAT_PIN6_Pos 6 -#define GPIO_INTRAWSTAT_PIN6_Msk (0x01 << GPIO_INTRAWSTAT_PIN6_Pos) -#define GPIO_INTRAWSTAT_PIN7_Pos 7 -#define GPIO_INTRAWSTAT_PIN7_Msk (0x01 << GPIO_INTRAWSTAT_PIN7_Pos) -#define GPIO_INTRAWSTAT_PIN8_Pos 8 -#define GPIO_INTRAWSTAT_PIN8_Msk (0x01 << GPIO_INTRAWSTAT_PIN8_Pos) -#define GPIO_INTRAWSTAT_PIN9_Pos 9 -#define GPIO_INTRAWSTAT_PIN9_Msk (0x01 << GPIO_INTRAWSTAT_PIN9_Pos) -#define GPIO_INTRAWSTAT_PIN10_Pos 10 -#define GPIO_INTRAWSTAT_PIN10_Msk (0x01 << GPIO_INTRAWSTAT_PIN10_Pos) -#define GPIO_INTRAWSTAT_PIN11_Pos 11 -#define GPIO_INTRAWSTAT_PIN11_Msk (0x01 << GPIO_INTRAWSTAT_PIN11_Pos) -#define GPIO_INTRAWSTAT_PIN12_Pos 12 -#define GPIO_INTRAWSTAT_PIN12_Msk (0x01 << GPIO_INTRAWSTAT_PIN12_Pos) -#define GPIO_INTRAWSTAT_PIN13_Pos 13 -#define GPIO_INTRAWSTAT_PIN13_Msk (0x01 << GPIO_INTRAWSTAT_PIN13_Pos) -#define GPIO_INTRAWSTAT_PIN14_Pos 14 -#define GPIO_INTRAWSTAT_PIN14_Msk (0x01 << GPIO_INTRAWSTAT_PIN14_Pos) -#define GPIO_INTRAWSTAT_PIN15_Pos 15 -#define GPIO_INTRAWSTAT_PIN15_Msk (0x01 << GPIO_INTRAWSTAT_PIN15_Pos) -#define GPIO_INTRAWSTAT_PIN16_Pos 16 -#define GPIO_INTRAWSTAT_PIN16_Msk (0x01 << GPIO_INTRAWSTAT_PIN16_Pos) -#define GPIO_INTRAWSTAT_PIN17_Pos 17 -#define GPIO_INTRAWSTAT_PIN17_Msk (0x01 << GPIO_INTRAWSTAT_PIN17_Pos) -#define GPIO_INTRAWSTAT_PIN18_Pos 18 -#define GPIO_INTRAWSTAT_PIN18_Msk (0x01 << GPIO_INTRAWSTAT_PIN18_Pos) -#define GPIO_INTRAWSTAT_PIN19_Pos 19 -#define GPIO_INTRAWSTAT_PIN19_Msk (0x01 << GPIO_INTRAWSTAT_PIN19_Pos) -#define GPIO_INTRAWSTAT_PIN20_Pos 20 -#define GPIO_INTRAWSTAT_PIN20_Msk (0x01 << GPIO_INTRAWSTAT_PIN20_Pos) -#define GPIO_INTRAWSTAT_PIN21_Pos 21 -#define GPIO_INTRAWSTAT_PIN21_Msk (0x01 << GPIO_INTRAWSTAT_PIN21_Pos) -#define GPIO_INTRAWSTAT_PIN22_Pos 22 -#define GPIO_INTRAWSTAT_PIN22_Msk (0x01 << GPIO_INTRAWSTAT_PIN22_Pos) -#define GPIO_INTRAWSTAT_PIN23_Pos 23 -#define GPIO_INTRAWSTAT_PIN23_Msk (0x01 << GPIO_INTRAWSTAT_PIN23_Pos) +#define GPIO_INTSTAT_PIN0_Pos 0 +#define GPIO_INTSTAT_PIN0_Msk (0x01 << GPIO_INTSTAT_PIN0_Pos) +#define GPIO_INTSTAT_PIN1_Pos 1 +#define GPIO_INTSTAT_PIN1_Msk (0x01 << GPIO_INTSTAT_PIN1_Pos) +#define GPIO_INTSTAT_PIN2_Pos 2 +#define GPIO_INTSTAT_PIN2_Msk (0x01 << GPIO_INTSTAT_PIN2_Pos) +#define GPIO_INTSTAT_PIN3_Pos 3 +#define GPIO_INTSTAT_PIN3_Msk (0x01 << GPIO_INTSTAT_PIN3_Pos) +#define GPIO_INTSTAT_PIN4_Pos 4 +#define GPIO_INTSTAT_PIN4_Msk (0x01 << GPIO_INTSTAT_PIN4_Pos) +#define GPIO_INTSTAT_PIN5_Pos 5 +#define GPIO_INTSTAT_PIN5_Msk (0x01 << GPIO_INTSTAT_PIN5_Pos) +#define GPIO_INTSTAT_PIN6_Pos 6 +#define GPIO_INTSTAT_PIN6_Msk (0x01 << GPIO_INTSTAT_PIN6_Pos) +#define GPIO_INTSTAT_PIN7_Pos 7 +#define GPIO_INTSTAT_PIN7_Msk (0x01 << GPIO_INTSTAT_PIN7_Pos) +#define GPIO_INTSTAT_PIN8_Pos 8 +#define GPIO_INTSTAT_PIN8_Msk (0x01 << GPIO_INTSTAT_PIN8_Pos) +#define GPIO_INTSTAT_PIN9_Pos 9 +#define GPIO_INTSTAT_PIN9_Msk (0x01 << GPIO_INTSTAT_PIN9_Pos) +#define GPIO_INTSTAT_PIN10_Pos 10 +#define GPIO_INTSTAT_PIN10_Msk (0x01 << GPIO_INTSTAT_PIN10_Pos) +#define GPIO_INTSTAT_PIN11_Pos 11 +#define GPIO_INTSTAT_PIN11_Msk (0x01 << GPIO_INTSTAT_PIN11_Pos) +#define GPIO_INTSTAT_PIN12_Pos 12 +#define GPIO_INTSTAT_PIN12_Msk (0x01 << GPIO_INTSTAT_PIN12_Pos) +#define GPIO_INTSTAT_PIN13_Pos 13 +#define GPIO_INTSTAT_PIN13_Msk (0x01 << GPIO_INTSTAT_PIN13_Pos) +#define GPIO_INTSTAT_PIN14_Pos 14 +#define GPIO_INTSTAT_PIN14_Msk (0x01 << GPIO_INTSTAT_PIN14_Pos) +#define GPIO_INTSTAT_PIN15_Pos 15 +#define GPIO_INTSTAT_PIN15_Msk (0x01 << GPIO_INTSTAT_PIN15_Pos) +#define GPIO_INTSTAT_PIN16_Pos 16 +#define GPIO_INTSTAT_PIN16_Msk (0x01 << GPIO_INTSTAT_PIN16_Pos) +#define GPIO_INTSTAT_PIN17_Pos 17 +#define GPIO_INTSTAT_PIN17_Msk (0x01 << GPIO_INTSTAT_PIN17_Pos) +#define GPIO_INTSTAT_PIN18_Pos 18 +#define GPIO_INTSTAT_PIN18_Msk (0x01 << GPIO_INTSTAT_PIN18_Pos) +#define GPIO_INTSTAT_PIN19_Pos 19 +#define GPIO_INTSTAT_PIN19_Msk (0x01 << GPIO_INTSTAT_PIN19_Pos) +#define GPIO_INTSTAT_PIN20_Pos 20 +#define GPIO_INTSTAT_PIN20_Msk (0x01 << GPIO_INTSTAT_PIN20_Pos) +#define GPIO_INTSTAT_PIN21_Pos 21 +#define GPIO_INTSTAT_PIN21_Msk (0x01 << GPIO_INTSTAT_PIN21_Pos) +#define GPIO_INTSTAT_PIN22_Pos 22 +#define GPIO_INTSTAT_PIN22_Msk (0x01 << GPIO_INTSTAT_PIN22_Pos) +#define GPIO_INTSTAT_PIN23_Pos 23 +#define GPIO_INTSTAT_PIN23_Msk (0x01 << GPIO_INTSTAT_PIN23_Pos) -#define GPIO_INTSTAT_PIN0_Pos 0 -#define GPIO_INTSTAT_PIN0_Msk (0x01 << GPIO_INTSTAT_PIN0_Pos) -#define GPIO_INTSTAT_PIN1_Pos 1 -#define GPIO_INTSTAT_PIN1_Msk (0x01 << GPIO_INTSTAT_PIN1_Pos) -#define GPIO_INTSTAT_PIN2_Pos 2 -#define GPIO_INTSTAT_PIN2_Msk (0x01 << GPIO_INTSTAT_PIN2_Pos) -#define GPIO_INTSTAT_PIN3_Pos 3 -#define GPIO_INTSTAT_PIN3_Msk (0x01 << GPIO_INTSTAT_PIN3_Pos) -#define GPIO_INTSTAT_PIN4_Pos 4 -#define GPIO_INTSTAT_PIN4_Msk (0x01 << GPIO_INTSTAT_PIN4_Pos) -#define GPIO_INTSTAT_PIN5_Pos 5 -#define GPIO_INTSTAT_PIN5_Msk (0x01 << GPIO_INTSTAT_PIN5_Pos) -#define GPIO_INTSTAT_PIN6_Pos 6 -#define GPIO_INTSTAT_PIN6_Msk (0x01 << GPIO_INTSTAT_PIN6_Pos) -#define GPIO_INTSTAT_PIN7_Pos 7 -#define GPIO_INTSTAT_PIN7_Msk (0x01 << GPIO_INTSTAT_PIN7_Pos) -#define GPIO_INTSTAT_PIN8_Pos 8 -#define GPIO_INTSTAT_PIN8_Msk (0x01 << GPIO_INTSTAT_PIN8_Pos) -#define GPIO_INTSTAT_PIN9_Pos 9 -#define GPIO_INTSTAT_PIN9_Msk (0x01 << GPIO_INTSTAT_PIN9_Pos) -#define GPIO_INTSTAT_PIN10_Pos 10 -#define GPIO_INTSTAT_PIN10_Msk (0x01 << GPIO_INTSTAT_PIN10_Pos) -#define GPIO_INTSTAT_PIN11_Pos 11 -#define GPIO_INTSTAT_PIN11_Msk (0x01 << GPIO_INTSTAT_PIN11_Pos) -#define GPIO_INTSTAT_PIN12_Pos 12 -#define GPIO_INTSTAT_PIN12_Msk (0x01 << GPIO_INTSTAT_PIN12_Pos) -#define GPIO_INTSTAT_PIN13_Pos 13 -#define GPIO_INTSTAT_PIN13_Msk (0x01 << GPIO_INTSTAT_PIN13_Pos) -#define GPIO_INTSTAT_PIN14_Pos 14 -#define GPIO_INTSTAT_PIN14_Msk (0x01 << GPIO_INTSTAT_PIN14_Pos) -#define GPIO_INTSTAT_PIN15_Pos 15 -#define GPIO_INTSTAT_PIN15_Msk (0x01 << GPIO_INTSTAT_PIN15_Pos) -#define GPIO_INTSTAT_PIN16_Pos 16 -#define GPIO_INTSTAT_PIN16_Msk (0x01 << GPIO_INTSTAT_PIN16_Pos) -#define GPIO_INTSTAT_PIN17_Pos 17 -#define GPIO_INTSTAT_PIN17_Msk (0x01 << GPIO_INTSTAT_PIN17_Pos) -#define GPIO_INTSTAT_PIN18_Pos 18 -#define GPIO_INTSTAT_PIN18_Msk (0x01 << GPIO_INTSTAT_PIN18_Pos) -#define GPIO_INTSTAT_PIN19_Pos 19 -#define GPIO_INTSTAT_PIN19_Msk (0x01 << GPIO_INTSTAT_PIN19_Pos) -#define GPIO_INTSTAT_PIN20_Pos 20 -#define GPIO_INTSTAT_PIN20_Msk (0x01 << GPIO_INTSTAT_PIN20_Pos) -#define GPIO_INTSTAT_PIN21_Pos 21 -#define GPIO_INTSTAT_PIN21_Msk (0x01 << GPIO_INTSTAT_PIN21_Pos) -#define GPIO_INTSTAT_PIN22_Pos 22 -#define GPIO_INTSTAT_PIN22_Msk (0x01 << GPIO_INTSTAT_PIN22_Pos) -#define GPIO_INTSTAT_PIN23_Pos 23 -#define GPIO_INTSTAT_PIN23_Msk (0x01 << GPIO_INTSTAT_PIN23_Pos) +#define GPIO_INTCLR_PIN0_Pos 0 +#define GPIO_INTCLR_PIN0_Msk (0x01 << GPIO_INTCLR_PIN0_Pos) +#define GPIO_INTCLR_PIN1_Pos 1 +#define GPIO_INTCLR_PIN1_Msk (0x01 << GPIO_INTCLR_PIN1_Pos) +#define GPIO_INTCLR_PIN2_Pos 2 +#define GPIO_INTCLR_PIN2_Msk (0x01 << GPIO_INTCLR_PIN2_Pos) +#define GPIO_INTCLR_PIN3_Pos 3 +#define GPIO_INTCLR_PIN3_Msk (0x01 << GPIO_INTCLR_PIN3_Pos) +#define GPIO_INTCLR_PIN4_Pos 4 +#define GPIO_INTCLR_PIN4_Msk (0x01 << GPIO_INTCLR_PIN4_Pos) +#define GPIO_INTCLR_PIN5_Pos 5 +#define GPIO_INTCLR_PIN5_Msk (0x01 << GPIO_INTCLR_PIN5_Pos) +#define GPIO_INTCLR_PIN6_Pos 6 +#define GPIO_INTCLR_PIN6_Msk (0x01 << GPIO_INTCLR_PIN6_Pos) +#define GPIO_INTCLR_PIN7_Pos 7 +#define GPIO_INTCLR_PIN7_Msk (0x01 << GPIO_INTCLR_PIN7_Pos) +#define GPIO_INTCLR_PIN8_Pos 8 +#define GPIO_INTCLR_PIN8_Msk (0x01 << GPIO_INTCLR_PIN8_Pos) +#define GPIO_INTCLR_PIN9_Pos 9 +#define GPIO_INTCLR_PIN9_Msk (0x01 << GPIO_INTCLR_PIN9_Pos) +#define GPIO_INTCLR_PIN10_Pos 10 +#define GPIO_INTCLR_PIN10_Msk (0x01 << GPIO_INTCLR_PIN10_Pos) +#define GPIO_INTCLR_PIN11_Pos 11 +#define GPIO_INTCLR_PIN11_Msk (0x01 << GPIO_INTCLR_PIN11_Pos) +#define GPIO_INTCLR_PIN12_Pos 12 +#define GPIO_INTCLR_PIN12_Msk (0x01 << GPIO_INTCLR_PIN12_Pos) +#define GPIO_INTCLR_PIN13_Pos 13 +#define GPIO_INTCLR_PIN13_Msk (0x01 << GPIO_INTCLR_PIN13_Pos) +#define GPIO_INTCLR_PIN14_Pos 14 +#define GPIO_INTCLR_PIN14_Msk (0x01 << GPIO_INTCLR_PIN14_Pos) +#define GPIO_INTCLR_PIN15_Pos 15 +#define GPIO_INTCLR_PIN15_Msk (0x01 << GPIO_INTCLR_PIN15_Pos) +#define GPIO_INTCLR_PIN16_Pos 16 +#define GPIO_INTCLR_PIN16_Msk (0x01 << GPIO_INTCLR_PIN16_Pos) +#define GPIO_INTCLR_PIN17_Pos 17 +#define GPIO_INTCLR_PIN17_Msk (0x01 << GPIO_INTCLR_PIN17_Pos) +#define GPIO_INTCLR_PIN18_Pos 18 +#define GPIO_INTCLR_PIN18_Msk (0x01 << GPIO_INTCLR_PIN18_Pos) +#define GPIO_INTCLR_PIN19_Pos 19 +#define GPIO_INTCLR_PIN19_Msk (0x01 << GPIO_INTCLR_PIN19_Pos) +#define GPIO_INTCLR_PIN20_Pos 20 +#define GPIO_INTCLR_PIN20_Msk (0x01 << GPIO_INTCLR_PIN20_Pos) +#define GPIO_INTCLR_PIN21_Pos 21 +#define GPIO_INTCLR_PIN21_Msk (0x01 << GPIO_INTCLR_PIN21_Pos) +#define GPIO_INTCLR_PIN22_Pos 22 +#define GPIO_INTCLR_PIN22_Msk (0x01 << GPIO_INTCLR_PIN22_Pos) +#define GPIO_INTCLR_PIN23_Pos 23 +#define GPIO_INTCLR_PIN23_Msk (0x01 << GPIO_INTCLR_PIN23_Pos) -#define GPIO_INTCLR_PIN0_Pos 0 -#define GPIO_INTCLR_PIN0_Msk (0x01 << GPIO_INTCLR_PIN0_Pos) -#define GPIO_INTCLR_PIN1_Pos 1 -#define GPIO_INTCLR_PIN1_Msk (0x01 << GPIO_INTCLR_PIN1_Pos) -#define GPIO_INTCLR_PIN2_Pos 2 -#define GPIO_INTCLR_PIN2_Msk (0x01 << GPIO_INTCLR_PIN2_Pos) -#define GPIO_INTCLR_PIN3_Pos 3 -#define GPIO_INTCLR_PIN3_Msk (0x01 << GPIO_INTCLR_PIN3_Pos) -#define GPIO_INTCLR_PIN4_Pos 4 -#define GPIO_INTCLR_PIN4_Msk (0x01 << GPIO_INTCLR_PIN4_Pos) -#define GPIO_INTCLR_PIN5_Pos 5 -#define GPIO_INTCLR_PIN5_Msk (0x01 << GPIO_INTCLR_PIN5_Pos) -#define GPIO_INTCLR_PIN6_Pos 6 -#define GPIO_INTCLR_PIN6_Msk (0x01 << GPIO_INTCLR_PIN6_Pos) -#define GPIO_INTCLR_PIN7_Pos 7 -#define GPIO_INTCLR_PIN7_Msk (0x01 << GPIO_INTCLR_PIN7_Pos) -#define GPIO_INTCLR_PIN8_Pos 8 -#define GPIO_INTCLR_PIN8_Msk (0x01 << GPIO_INTCLR_PIN8_Pos) -#define GPIO_INTCLR_PIN9_Pos 9 -#define GPIO_INTCLR_PIN9_Msk (0x01 << GPIO_INTCLR_PIN9_Pos) -#define GPIO_INTCLR_PIN10_Pos 10 -#define GPIO_INTCLR_PIN10_Msk (0x01 << GPIO_INTCLR_PIN10_Pos) -#define GPIO_INTCLR_PIN11_Pos 11 -#define GPIO_INTCLR_PIN11_Msk (0x01 << GPIO_INTCLR_PIN11_Pos) -#define GPIO_INTCLR_PIN12_Pos 12 -#define GPIO_INTCLR_PIN12_Msk (0x01 << GPIO_INTCLR_PIN12_Pos) -#define GPIO_INTCLR_PIN13_Pos 13 -#define GPIO_INTCLR_PIN13_Msk (0x01 << GPIO_INTCLR_PIN13_Pos) -#define GPIO_INTCLR_PIN14_Pos 14 -#define GPIO_INTCLR_PIN14_Msk (0x01 << GPIO_INTCLR_PIN14_Pos) -#define GPIO_INTCLR_PIN15_Pos 15 -#define GPIO_INTCLR_PIN15_Msk (0x01 << GPIO_INTCLR_PIN15_Pos) -#define GPIO_INTCLR_PIN16_Pos 16 -#define GPIO_INTCLR_PIN16_Msk (0x01 << GPIO_INTCLR_PIN16_Pos) -#define GPIO_INTCLR_PIN17_Pos 17 -#define GPIO_INTCLR_PIN17_Msk (0x01 << GPIO_INTCLR_PIN17_Pos) -#define GPIO_INTCLR_PIN18_Pos 18 -#define GPIO_INTCLR_PIN18_Msk (0x01 << GPIO_INTCLR_PIN18_Pos) -#define GPIO_INTCLR_PIN19_Pos 19 -#define GPIO_INTCLR_PIN19_Msk (0x01 << GPIO_INTCLR_PIN19_Pos) -#define GPIO_INTCLR_PIN20_Pos 20 -#define GPIO_INTCLR_PIN20_Msk (0x01 << GPIO_INTCLR_PIN20_Pos) -#define GPIO_INTCLR_PIN21_Pos 21 -#define GPIO_INTCLR_PIN21_Msk (0x01 << GPIO_INTCLR_PIN21_Pos) -#define GPIO_INTCLR_PIN22_Pos 22 -#define GPIO_INTCLR_PIN22_Msk (0x01 << GPIO_INTCLR_PIN22_Pos) -#define GPIO_INTCLR_PIN23_Pos 23 -#define GPIO_INTCLR_PIN23_Msk (0x01 << GPIO_INTCLR_PIN23_Pos) +typedef struct +{ + __IO uint32_t LDVAL; //定时器加载值,使能后定时器从此数值开始向下递减计数 + __I uint32_t CVAL; //定时器当前值,LDVAL-CVAL 可计算出计时时长 - - -typedef struct { - __IO uint32_t LDVAL; //定时器加载值,使能后定时器从此数值开始向下递减计数 - - __I uint32_t CVAL; //定时器当前值,LDVAL-CVAL 可计算出计时时长 - - __IO uint32_t CTRL; + __IO uint32_t CTRL; } TIMR_TypeDef; +#define TIMR_CTRL_EN_Pos 0 //此位赋1导致TIMR从LDVAL开始向下递减计数 +#define TIMR_CTRL_EN_Msk (0x01 << TIMR_CTRL_EN_Pos) +#define TIMR_CTRL_CLKSRC_Pos 1 //时钟源:0 内部系统时钟 1 外部引脚脉冲计数 +#define TIMR_CTRL_CLKSRC_Msk (0x01 << TIMR_CTRL_CLKSRC_Pos) +#define TIMR_CTRL_CASCADE_Pos 2 //1 TIMRx的计数时钟为TIMRx-1的溢出信号 +#define TIMR_CTRL_CASCADE_Msk (0x01 << TIMR_CTRL_CASCADE_Pos) -#define TIMR_CTRL_EN_Pos 0 //此位赋1导致TIMR从LDVAL开始向下递减计数 -#define TIMR_CTRL_EN_Msk (0x01 << TIMR_CTRL_EN_Pos) -#define TIMR_CTRL_CLKSRC_Pos 1 //时钟源:0 内部系统时钟 1 外部引脚脉冲计数 -#define TIMR_CTRL_CLKSRC_Msk (0x01 << TIMR_CTRL_CLKSRC_Pos) -#define TIMR_CTRL_CASCADE_Pos 2 //1 TIMRx的计数时钟为TIMRx-1的溢出信号 -#define TIMR_CTRL_CASCADE_Msk (0x01 << TIMR_CTRL_CASCADE_Pos) +typedef struct +{ + __IO uint32_t PCTRL; //Pulse Control,脉宽测量模块控制寄存器 + __I uint32_t PCVAL; //脉宽测量定时器当前值 -typedef struct { - __IO uint32_t PCTRL; //Pulse Control,脉宽测量模块控制寄存器 + uint32_t RESERVED[2]; - __I uint32_t PCVAL; //脉宽测量定时器当前值 + __IO uint32_t IE; - uint32_t RESERVED[2]; + __IO uint32_t IF; - __IO uint32_t IE; - - __IO uint32_t IF; - - __IO uint32_t HALT; + __IO uint32_t HALT; } TIMRG_TypeDef; +#define TIMRG_PCTRL_EN_Pos 0 //开始测量脉宽,脉宽内32位计数器从0开始向上计数 +#define TIMRG_PCTRL_EN_Msk (0x01 << TIMRG_PCTRL_EN_Pos) +#define TIMRG_PCTRL_HIGH_Pos 1 //0 测量低电平长度 1 测量高电平长度 +#define TIMRG_PCTRL_HIGH_Msk (0x01 << TIMRG_PCTRL_HIGH_Pos) +#define TIMRG_PCTRL_CLKSRC_Pos 2 //时钟源:0 内部系统时钟 1 脉宽测量模块变成一个计数器,不再具有脉宽测量功能 +#define TIMRG_PCTRL_CLKSRC_Msk (0x01 << TIMRG_PCTRL_CLKSRC_Pos) -#define TIMRG_PCTRL_EN_Pos 0 //开始测量脉宽,脉宽内32位计数器从0开始向上计数 -#define TIMRG_PCTRL_EN_Msk (0x01 << TIMRG_PCTRL_EN_Pos) -#define TIMRG_PCTRL_HIGH_Pos 1 //0 测量低电平长度 1 测量高电平长度 -#define TIMRG_PCTRL_HIGH_Msk (0x01 << TIMRG_PCTRL_HIGH_Pos) -#define TIMRG_PCTRL_CLKSRC_Pos 2 //时钟源:0 内部系统时钟 1 脉宽测量模块变成一个计数器,不再具有脉宽测量功能 -#define TIMRG_PCTRL_CLKSRC_Msk (0x01 << TIMRG_PCTRL_CLKSRC_Pos) +#define TIMRG_IE_TIMR0_Pos 0 +#define TIMRG_IE_TIMR0_Msk (0x01 << TIMRG_IE_TIMR0_Pos) +#define TIMRG_IE_TIMR1_Pos 1 +#define TIMRG_IE_TIMR1_Msk (0x01 << TIMRG_IE_TIMR1_Pos) +#define TIMRG_IE_TIMR2_Pos 2 +#define TIMRG_IE_TIMR2_Msk (0x01 << TIMRG_IE_TIMR2_Pos) +#define TIMRG_IE_TIMR3_Pos 3 +#define TIMRG_IE_TIMR3_Msk (0x01 << TIMRG_IE_TIMR3_Pos) +#define TIMRG_IE_TIMR4_Pos 4 +#define TIMRG_IE_TIMR4_Msk (0x01 << TIMRG_IE_TIMR4_Pos) +#define TIMRG_IE_TIMR5_Pos 5 +#define TIMRG_IE_TIMR5_Msk (0x01 << TIMRG_IE_TIMR5_Pos) +#define TIMRG_IE_PULSE_Pos 16 +#define TIMRG_IE_PULSE_Msk (0x01 << TIMRG_IE_PULSE_Pos) -#define TIMRG_IE_TIMR0_Pos 0 -#define TIMRG_IE_TIMR0_Msk (0x01 << TIMRG_IE_TIMR0_Pos) -#define TIMRG_IE_TIMR1_Pos 1 -#define TIMRG_IE_TIMR1_Msk (0x01 << TIMRG_IE_TIMR1_Pos) -#define TIMRG_IE_TIMR2_Pos 2 -#define TIMRG_IE_TIMR2_Msk (0x01 << TIMRG_IE_TIMR2_Pos) -#define TIMRG_IE_TIMR3_Pos 3 -#define TIMRG_IE_TIMR3_Msk (0x01 << TIMRG_IE_TIMR3_Pos) -#define TIMRG_IE_TIMR4_Pos 4 -#define TIMRG_IE_TIMR4_Msk (0x01 << TIMRG_IE_TIMR4_Pos) -#define TIMRG_IE_TIMR5_Pos 5 -#define TIMRG_IE_TIMR5_Msk (0x01 << TIMRG_IE_TIMR5_Pos) -#define TIMRG_IE_PULSE_Pos 16 -#define TIMRG_IE_PULSE_Msk (0x01 << TIMRG_IE_PULSE_Pos) +#define TIMRG_IF_TIMR0_Pos 0 //写1清零 +#define TIMRG_IF_TIMR0_Msk (0x01 << TIMRG_IF_TIMR0_Pos) +#define TIMRG_IF_TIMR1_Pos 1 +#define TIMRG_IF_TIMR1_Msk (0x01 << TIMRG_IF_TIMR1_Pos) +#define TIMRG_IF_TIMR2_Pos 2 +#define TIMRG_IF_TIMR2_Msk (0x01 << TIMRG_IF_TIMR2_Pos) +#define TIMRG_IF_TIMR3_Pos 3 +#define TIMRG_IF_TIMR3_Msk (0x01 << TIMRG_IF_TIMR3_Pos) +#define TIMRG_IF_TIMR4_Pos 4 +#define TIMRG_IF_TIMR4_Msk (0x01 << TIMRG_IF_TIMR4_Pos) +#define TIMRG_IF_TIMR5_Pos 5 +#define TIMRG_IF_TIMR5_Msk (0x01 << TIMRG_IF_TIMR5_Pos) +#define TIMRG_IF_PULSE_Pos 16 +#define TIMRG_IF_PULSE_Msk (0x01 << TIMRG_IF_PULSE_Pos) -#define TIMRG_IF_TIMR0_Pos 0 //写1清零 -#define TIMRG_IF_TIMR0_Msk (0x01 << TIMRG_IF_TIMR0_Pos) -#define TIMRG_IF_TIMR1_Pos 1 -#define TIMRG_IF_TIMR1_Msk (0x01 << TIMRG_IF_TIMR1_Pos) -#define TIMRG_IF_TIMR2_Pos 2 -#define TIMRG_IF_TIMR2_Msk (0x01 << TIMRG_IF_TIMR2_Pos) -#define TIMRG_IF_TIMR3_Pos 3 -#define TIMRG_IF_TIMR3_Msk (0x01 << TIMRG_IF_TIMR3_Pos) -#define TIMRG_IF_TIMR4_Pos 4 -#define TIMRG_IF_TIMR4_Msk (0x01 << TIMRG_IF_TIMR4_Pos) -#define TIMRG_IF_TIMR5_Pos 5 -#define TIMRG_IF_TIMR5_Msk (0x01 << TIMRG_IF_TIMR5_Pos) -#define TIMRG_IF_PULSE_Pos 16 -#define TIMRG_IF_PULSE_Msk (0x01 << TIMRG_IF_PULSE_Pos) +#define TIMRG_HALT_TIMR0_Pos 0 //1 暂停计数 +#define TIMRG_HALT_TIMR0_Msk (0x01 << TIMRG_HALT_TIMR0_Pos) +#define TIMRG_HALT_TIMR1_Pos 1 +#define TIMRG_HALT_TIMR1_Msk (0x01 << TIMRG_HALT_TIMR1_Pos) +#define TIMRG_HALT_TIMR2_Pos 2 +#define TIMRG_HALT_TIMR2_Msk (0x01 << TIMRG_HALT_TIMR2_Pos) +#define TIMRG_HALT_TIMR3_Pos 3 +#define TIMRG_HALT_TIMR3_Msk (0x01 << TIMRG_HALT_TIMR3_Pos) +#define TIMRG_HALT_TIMR4_Pos 4 +#define TIMRG_HALT_TIMR4_Msk (0x01 << TIMRG_HALT_TIMR4_Pos) +#define TIMRG_HALT_TIMR5_Pos 5 +#define TIMRG_HALT_TIMR5_Msk (0x01 << TIMRG_HALT_TIMR5_Pos) -#define TIMRG_HALT_TIMR0_Pos 0 //1 暂停计数 -#define TIMRG_HALT_TIMR0_Msk (0x01 << TIMRG_HALT_TIMR0_Pos) -#define TIMRG_HALT_TIMR1_Pos 1 -#define TIMRG_HALT_TIMR1_Msk (0x01 << TIMRG_HALT_TIMR1_Pos) -#define TIMRG_HALT_TIMR2_Pos 2 -#define TIMRG_HALT_TIMR2_Msk (0x01 << TIMRG_HALT_TIMR2_Pos) -#define TIMRG_HALT_TIMR3_Pos 3 -#define TIMRG_HALT_TIMR3_Msk (0x01 << TIMRG_HALT_TIMR3_Pos) -#define TIMRG_HALT_TIMR4_Pos 4 -#define TIMRG_HALT_TIMR4_Msk (0x01 << TIMRG_HALT_TIMR4_Pos) -#define TIMRG_HALT_TIMR5_Pos 5 -#define TIMRG_HALT_TIMR5_Msk (0x01 << TIMRG_HALT_TIMR5_Pos) +typedef struct +{ + __IO uint32_t DATA; + __IO uint32_t CTRL; + __IO uint32_t BAUD; + __IO uint32_t FIFO; -typedef struct { - __IO uint32_t DATA; - - __IO uint32_t CTRL; - - __IO uint32_t BAUD; - - __IO uint32_t FIFO; - - __IO uint32_t LINCR; - - union { - __IO uint32_t CTSCR; - - __IO uint32_t RTSCR; - }; + __IO uint32_t LINCR; + + union + { + __IO uint32_t CTSCR; + + __IO uint32_t RTSCR; + }; } UART_TypeDef; +#define UART_DATA_DATA_Pos 0 +#define UART_DATA_DATA_Msk (0x1FF << UART_DATA_DATA_Pos) +#define UART_DATA_VALID_Pos 9 //当DATA字段有有效的接收数据时,该位硬件置1,读取数据后自动清零 +#define UART_DATA_VALID_Msk (0x01 << UART_DATA_VALID_Pos) +#define UART_DATA_PAERR_Pos 10 //Parity Error +#define UART_DATA_PAERR_Msk (0x01 << UART_DATA_PAERR_Pos) -#define UART_DATA_DATA_Pos 0 -#define UART_DATA_DATA_Msk (0x1FF << UART_DATA_DATA_Pos) -#define UART_DATA_VALID_Pos 9 //当DATA字段有有效的接收数据时,该位硬件置1,读取数据后自动清零 -#define UART_DATA_VALID_Msk (0x01 << UART_DATA_VALID_Pos) -#define UART_DATA_PAERR_Pos 10 //Parity Error -#define UART_DATA_PAERR_Msk (0x01 << UART_DATA_PAERR_Pos) +#define UART_CTRL_TXIDLE_Pos 0 //TX IDLE: 0 正在发送数据 1 空闲状态,没有数据发送 +#define UART_CTRL_TXIDLE_Msk (0x01 << UART_CTRL_TXIDLE_Pos) +#define UART_CTRL_TXFF_Pos 1 //TX FIFO Full +#define UART_CTRL_TXFF_Msk (0x01 << UART_CTRL_TXFF_Pos) +#define UART_CTRL_TXIE_Pos 2 //TX 中断使能: 1 TX FF 中数据少于设定个数时产生中断 +#define UART_CTRL_TXIE_Msk (0x01 << UART_CTRL_TXIE_Pos) +#define UART_CTRL_RXNE_Pos 3 //RX FIFO Not Empty +#define UART_CTRL_RXNE_Msk (0x01 << UART_CTRL_RXNE_Pos) +#define UART_CTRL_RXIE_Pos 4 //RX 中断使能: 1 RX FF 中数据达到设定个数时产生中断 +#define UART_CTRL_RXIE_Msk (0x01 << UART_CTRL_RXIE_Pos) +#define UART_CTRL_RXOV_Pos 5 //RX FIFO Overflow,写1清零 +#define UART_CTRL_RXOV_Msk (0x01 << UART_CTRL_RXOV_Pos) +#define UART_CTRL_TXDOIE_Pos 6 //TX Done 中断使能,发送FIFO空且发送发送移位寄存器已将最后一位发送出去 +#define UART_CTRL_TXDOIE_Msk (0x01 << UART_CTRL_TXDOIE_Pos) +#define UART_CTRL_EN_Pos 9 +#define UART_CTRL_EN_Msk (0x01 << UART_CTRL_EN_Pos) +#define UART_CTRL_LOOP_Pos 10 +#define UART_CTRL_LOOP_Msk (0x01 << UART_CTRL_LOOP_Pos) +#define UART_CTRL_BAUDEN_Pos 13 //必须写1 +#define UART_CTRL_BAUDEN_Msk (0x01 << UART_CTRL_BAUDEN_Pos) +#define UART_CTRL_TOIE_Pos 14 //TimeOut 中断使能,接收到上个字符后,超过 TOTIME/BAUDRAUD 秒没有接收到新的数据 +#define UART_CTRL_TOIE_Msk (0x01 << UART_CTRL_TOIE_Pos) +#define UART_CTRL_BRKDET_Pos 15 //LIN Break Detect,检测到LIN Break,即RX线上检测到连续11位低电平 +#define UART_CTRL_BRKDET_Msk (0x01 << UART_CTRL_BRKDET_Pos) +#define UART_CTRL_BRKIE_Pos 16 //LIN Break Detect 中断使能 +#define UART_CTRL_BRKIE_Msk (0x01 << UART_CTRL_BRKIE_Pos) +#define UART_CTRL_GENBRK_Pos 17 //Generate LIN Break,发送LIN Break +#define UART_CTRL_GENBRK_Msk (0x01 << UART_CTRL_GENBRK_Pos) +#define UART_CTRL_DATA9b_Pos 18 //1 9位数据位 0 8位数据位 +#define UART_CTRL_DATA9b_Msk (0x01 << UART_CTRL_DATA9b_Pos) +#define UART_CTRL_PARITY_Pos 19 //000 无校验 001 奇校验 011 偶校验 101 固定为1 111 固定为0 +#define UART_CTRL_PARITY_Msk (0x07 << UART_CTRL_PARITY_Pos) +#define UART_CTRL_STOP2b_Pos 22 //1 2位停止位 0 1位停止位 +#define UART_CTRL_STOP2b_Msk (0x03 << UART_CTRL_STOP2b_Pos) +#define UART_CTRL_TOTIME_Pos 24 //TimeOut 时长 = TOTIME/(BAUDRAUD/10) 秒 +#define UART_CTRL_TOTIME_Msk (0xFFu << UART_CTRL_TOTIME_Pos) -#define UART_CTRL_TXIDLE_Pos 0 //TX IDLE: 0 正在发送数据 1 空闲状态,没有数据发送 -#define UART_CTRL_TXIDLE_Msk (0x01 << UART_CTRL_TXIDLE_Pos) -#define UART_CTRL_TXFF_Pos 1 //TX FIFO Full -#define UART_CTRL_TXFF_Msk (0x01 << UART_CTRL_TXFF_Pos) -#define UART_CTRL_TXIE_Pos 2 //TX 中断使能: 1 TX FF 中数据少于设定个数时产生中断 -#define UART_CTRL_TXIE_Msk (0x01 << UART_CTRL_TXIE_Pos) -#define UART_CTRL_RXNE_Pos 3 //RX FIFO Not Empty -#define UART_CTRL_RXNE_Msk (0x01 << UART_CTRL_RXNE_Pos) -#define UART_CTRL_RXIE_Pos 4 //RX 中断使能: 1 RX FF 中数据达到设定个数时产生中断 -#define UART_CTRL_RXIE_Msk (0x01 << UART_CTRL_RXIE_Pos) -#define UART_CTRL_RXOV_Pos 5 //RX FIFO Overflow,写1清零 -#define UART_CTRL_RXOV_Msk (0x01 << UART_CTRL_RXOV_Pos) -#define UART_CTRL_TXDOIE_Pos 6 //TX Done 中断使能,发送FIFO空且发送发送移位寄存器已将最后一位发送出去 -#define UART_CTRL_TXDOIE_Msk (0x01 << UART_CTRL_TXDOIE_Pos) -#define UART_CTRL_EN_Pos 9 -#define UART_CTRL_EN_Msk (0x01 << UART_CTRL_EN_Pos) -#define UART_CTRL_LOOP_Pos 10 -#define UART_CTRL_LOOP_Msk (0x01 << UART_CTRL_LOOP_Pos) -#define UART_CTRL_BAUDEN_Pos 13 //必须写1 -#define UART_CTRL_BAUDEN_Msk (0x01 << UART_CTRL_BAUDEN_Pos) -#define UART_CTRL_TOIE_Pos 14 //TimeOut 中断使能,接收到上个字符后,超过 TOTIME/BAUDRAUD 秒没有接收到新的数据 -#define UART_CTRL_TOIE_Msk (0x01 << UART_CTRL_TOIE_Pos) -#define UART_CTRL_BRKDET_Pos 15 //LIN Break Detect,检测到LIN Break,即RX线上检测到连续11位低电平 -#define UART_CTRL_BRKDET_Msk (0x01 << UART_CTRL_BRKDET_Pos) -#define UART_CTRL_BRKIE_Pos 16 //LIN Break Detect 中断使能 -#define UART_CTRL_BRKIE_Msk (0x01 << UART_CTRL_BRKIE_Pos) -#define UART_CTRL_GENBRK_Pos 17 //Generate LIN Break,发送LIN Break -#define UART_CTRL_GENBRK_Msk (0x01 << UART_CTRL_GENBRK_Pos) -#define UART_CTRL_DATA9b_Pos 18 //1 9位数据位 0 8位数据位 -#define UART_CTRL_DATA9b_Msk (0x01 << UART_CTRL_DATA9b_Pos) -#define UART_CTRL_PARITY_Pos 19 //000 无校验 001 奇校验 011 偶校验 101 固定为1 111 固定为0 -#define UART_CTRL_PARITY_Msk (0x07 << UART_CTRL_PARITY_Pos) -#define UART_CTRL_STOP2b_Pos 22 //1 2位停止位 0 1位停止位 -#define UART_CTRL_STOP2b_Msk (0x03 << UART_CTRL_STOP2b_Pos) -#define UART_CTRL_TOTIME_Pos 24 //TimeOut 时长 = TOTIME/(BAUDRAUD/10) 秒 -#define UART_CTRL_TOTIME_Msk (0xFFu<< UART_CTRL_TOTIME_Pos) +#define UART_BAUD_BAUD_Pos 0 //串口波特率 = SYS_Freq/16/BAUD - 1 +#define UART_BAUD_BAUD_Msk (0x3FFF << UART_BAUD_BAUD_Pos) +#define UART_BAUD_TXD_Pos 14 //通过此位可直接读取串口TXD引脚上的电平 +#define UART_BAUD_TXD_Msk (0x01 << UART_BAUD_TXD_Pos) +#define UART_BAUD_RXD_Pos 15 //通过此位可直接读取串口RXD引脚上的电平 +#define UART_BAUD_RXD_Msk (0x01 << UART_BAUD_RXD_Pos) +#define UART_BAUD_RXTOIF_Pos 16 //接收&超时的中断标志 = RXIF | TOIF +#define UART_BAUD_RXTOIF_Msk (0x01 << UART_BAUD_RXTOIF_Pos) +#define UART_BAUD_TXIF_Pos 17 //发送中断标志 = TXTHRF & TXIE +#define UART_BAUD_TXIF_Msk (0x01 << UART_BAUD_TXIF_Pos) +#define UART_BAUD_BRKIF_Pos 18 //LIN Break Detect 中断标志,检测到LIN Break时若BRKIE=1,此位由硬件置位 +#define UART_BAUD_BRKIF_Msk (0x01 << UART_BAUD_BRKIF_Pos) +#define UART_BAUD_RXTHRF_Pos 19 //RX FIFO Threshold Flag,RX FIFO中数据达到设定个数(RXLVL >= RXTHR)时硬件置1 +#define UART_BAUD_RXTHRF_Msk (0x01 << UART_BAUD_RXTHRF_Pos) +#define UART_BAUD_TXTHRF_Pos 20 //TX FIFO Threshold Flag,TX FIFO中数据少于设定个数(TXLVL <= TXTHR)时硬件置1 +#define UART_BAUD_TXTHRF_Msk (0x01 << UART_BAUD_TXTHRF_Pos) +#define UART_BAUD_TOIF_Pos 21 //TimeOut 中断标志,超过 TOTIME/BAUDRAUD 秒没有接收到新的数据时若TOIE=1,此位由硬件置位 +#define UART_BAUD_TOIF_Msk (0x01 << UART_BAUD_TOIF_Pos) +#define UART_BAUD_RXIF_Pos 22 //接收中断标志 = RXTHRF & RXIE +#define UART_BAUD_RXIF_Msk (0x01 << UART_BAUD_RXIF_Pos) +#define UART_BAUD_ABREN_Pos 23 //Auto Baudrate Enable,写1启动自动波特率校准,完成后自动清零 +#define UART_BAUD_ABREN_Msk (0x01 << UART_BAUD_ABREN_Pos) +#define UART_BAUD_ABRBIT_Pos 24 //Auto Baudrate Bit,用于计算波特率的检测位长,0 1位,通过测起始位 脉宽计算波特率,要求发送端发送0xFF \ + // 1 2位,通过测起始位加1位数据位脉宽计算波特率,要求发送端发送0xFE \ + // 1 4位,通过测起始位加3位数据位脉宽计算波特率,要求发送端发送0xF8 \ + // 1 8位,通过测起始位加7位数据位脉宽计算波特率,要求发送端发送0x80 +#define UART_BAUD_ABRBIT_Msk (0x03 << UART_BAUD_ABRBIT_Pos) +#define UART_BAUD_ABRERR_Pos 26 //Auto Baudrate Error,0 自动波特率校准成功 1 自动波特率校准失败 +#define UART_BAUD_ABRERR_Msk (0x01 << UART_BAUD_ABRERR_Pos) +#define UART_BAUD_TXDOIF_Pos 27 //TX Done 中断标志,发送FIFO空且发送发送移位寄存器已将最后一位发送出去 +#define UART_BAUD_TXDOIF_Msk (0x01 << UART_BAUD_TXDOIF_Pos) -#define UART_BAUD_BAUD_Pos 0 //串口波特率 = SYS_Freq/16/BAUD - 1 -#define UART_BAUD_BAUD_Msk (0x3FFF << UART_BAUD_BAUD_Pos) -#define UART_BAUD_TXD_Pos 14 //通过此位可直接读取串口TXD引脚上的电平 -#define UART_BAUD_TXD_Msk (0x01 << UART_BAUD_TXD_Pos) -#define UART_BAUD_RXD_Pos 15 //通过此位可直接读取串口RXD引脚上的电平 -#define UART_BAUD_RXD_Msk (0x01 << UART_BAUD_RXD_Pos) -#define UART_BAUD_RXTOIF_Pos 16 //接收&超时的中断标志 = RXIF | TOIF -#define UART_BAUD_RXTOIF_Msk (0x01 << UART_BAUD_RXTOIF_Pos) -#define UART_BAUD_TXIF_Pos 17 //发送中断标志 = TXTHRF & TXIE -#define UART_BAUD_TXIF_Msk (0x01 << UART_BAUD_TXIF_Pos) -#define UART_BAUD_BRKIF_Pos 18 //LIN Break Detect 中断标志,检测到LIN Break时若BRKIE=1,此位由硬件置位 -#define UART_BAUD_BRKIF_Msk (0x01 << UART_BAUD_BRKIF_Pos) -#define UART_BAUD_RXTHRF_Pos 19 //RX FIFO Threshold Flag,RX FIFO中数据达到设定个数(RXLVL >= RXTHR)时硬件置1 -#define UART_BAUD_RXTHRF_Msk (0x01 << UART_BAUD_RXTHRF_Pos) -#define UART_BAUD_TXTHRF_Pos 20 //TX FIFO Threshold Flag,TX FIFO中数据少于设定个数(TXLVL <= TXTHR)时硬件置1 -#define UART_BAUD_TXTHRF_Msk (0x01 << UART_BAUD_TXTHRF_Pos) -#define UART_BAUD_TOIF_Pos 21 //TimeOut 中断标志,超过 TOTIME/BAUDRAUD 秒没有接收到新的数据时若TOIE=1,此位由硬件置位 -#define UART_BAUD_TOIF_Msk (0x01 << UART_BAUD_TOIF_Pos) -#define UART_BAUD_RXIF_Pos 22 //接收中断标志 = RXTHRF & RXIE -#define UART_BAUD_RXIF_Msk (0x01 << UART_BAUD_RXIF_Pos) -#define UART_BAUD_ABREN_Pos 23 //Auto Baudrate Enable,写1启动自动波特率校准,完成后自动清零 -#define UART_BAUD_ABREN_Msk (0x01 << UART_BAUD_ABREN_Pos) -#define UART_BAUD_ABRBIT_Pos 24 //Auto Baudrate Bit,用于计算波特率的检测位长,0 1位,通过测起始位 脉宽计算波特率,要求发送端发送0xFF - // 1 2位,通过测起始位加1位数据位脉宽计算波特率,要求发送端发送0xFE - // 1 4位,通过测起始位加3位数据位脉宽计算波特率,要求发送端发送0xF8 - // 1 8位,通过测起始位加7位数据位脉宽计算波特率,要求发送端发送0x80 -#define UART_BAUD_ABRBIT_Msk (0x03 << UART_BAUD_ABRBIT_Pos) -#define UART_BAUD_ABRERR_Pos 26 //Auto Baudrate Error,0 自动波特率校准成功 1 自动波特率校准失败 -#define UART_BAUD_ABRERR_Msk (0x01 << UART_BAUD_ABRERR_Pos) -#define UART_BAUD_TXDOIF_Pos 27 //TX Done 中断标志,发送FIFO空且发送发送移位寄存器已将最后一位发送出去 -#define UART_BAUD_TXDOIF_Msk (0x01 << UART_BAUD_TXDOIF_Pos) +#define UART_FIFO_RXLVL_Pos 0 //RX FIFO Level,RX FIFO 中字符个数 +#define UART_FIFO_RXLVL_Msk (0xFF << UART_FIFO_RXLVL_Pos) +#define UART_FIFO_TXLVL_Pos 8 //TX FIFO Level,TX FIFO 中字符个数 +#define UART_FIFO_TXLVL_Msk (0xFF << UART_FIFO_TXLVL_Pos) +#define UART_FIFO_RXTHR_Pos 16 //RX FIFO Threshold,RX中断触发门限,中断使能时 RXLVL >= RXTHR 触发RX中断 +#define UART_FIFO_RXTHR_Msk (0xFF << UART_FIFO_RXTHR_Pos) +#define UART_FIFO_TXTHR_Pos 24 //TX FIFO Threshold,TX中断触发门限,中断使能时 TXLVL <= TXTHR 触发TX中断 +#define UART_FIFO_TXTHR_Msk (0xFFu << UART_FIFO_TXTHR_Pos) -#define UART_FIFO_RXLVL_Pos 0 //RX FIFO Level,RX FIFO 中字符个数 -#define UART_FIFO_RXLVL_Msk (0xFF << UART_FIFO_RXLVL_Pos) -#define UART_FIFO_TXLVL_Pos 8 //TX FIFO Level,TX FIFO 中字符个数 -#define UART_FIFO_TXLVL_Msk (0xFF << UART_FIFO_TXLVL_Pos) -#define UART_FIFO_RXTHR_Pos 16 //RX FIFO Threshold,RX中断触发门限,中断使能时 RXLVL >= RXTHR 触发RX中断 -#define UART_FIFO_RXTHR_Msk (0xFF << UART_FIFO_RXTHR_Pos) -#define UART_FIFO_TXTHR_Pos 24 //TX FIFO Threshold,TX中断触发门限,中断使能时 TXLVL <= TXTHR 触发TX中断 -#define UART_FIFO_TXTHR_Msk (0xFFu<< UART_FIFO_TXTHR_Pos) +#define UART_LINCR_BRKDETIE_Pos 0 //检测到LIN Break中断使能 +#define UART_LINCR_BRKDETIE_Msk (0x01 << UART_LINCR_BRKDETIE_Pos) +#define UART_LINCR_BRKDETIF_Pos 1 //检测到LIN Break中断状态 +#define UART_LINCR_BRKDETIF_Msk (0x01 << UART_LINCR_BRKDETIF_Pos) +#define UART_LINCR_GENBRKIE_Pos 2 //发送LIN Break完成中断使能 +#define UART_LINCR_GENBRKIE_Msk (0x01 << UART_LINCR_GENBRKIE_Pos) +#define UART_LINCR_GENBRKIF_Pos 3 //发送LIN Break完成中断状态 +#define UART_LINCR_GENBRKIF_Msk (0x01 << UART_LINCR_GENBRKIF_Pos) +#define UART_LINCR_GENBRK_Pos 4 //发送LIN Break,发送完成自动清零 +#define UART_LINCR_GENBRK_Msk (0x01 << UART_LINCR_GENBRK_Pos) -#define UART_LINCR_BRKDETIE_Pos 0 //检测到LIN Break中断使能 -#define UART_LINCR_BRKDETIE_Msk (0x01 << UART_LINCR_BRKDETIE_Pos) -#define UART_LINCR_BRKDETIF_Pos 1 //检测到LIN Break中断状态 -#define UART_LINCR_BRKDETIF_Msk (0x01 << UART_LINCR_BRKDETIF_Pos) -#define UART_LINCR_GENBRKIE_Pos 2 //发送LIN Break完成中断使能 -#define UART_LINCR_GENBRKIE_Msk (0x01 << UART_LINCR_GENBRKIE_Pos) -#define UART_LINCR_GENBRKIF_Pos 3 //发送LIN Break完成中断状态 -#define UART_LINCR_GENBRKIF_Msk (0x01 << UART_LINCR_GENBRKIF_Pos) -#define UART_LINCR_GENBRK_Pos 4 //发送LIN Break,发送完成自动清零 -#define UART_LINCR_GENBRK_Msk (0x01 << UART_LINCR_GENBRK_Pos) +#define UART_CTSCR_EN_Pos 0 //CTS流控使能 +#define UART_CTSCR_EN_Msk (0x01 << UART_CTSCR_EN_Pos) +#define UART_CTSCR_POL_Pos 2 //CTS信号极性,0 低有效,CTS输入为低表示可以发送数据 +#define UART_CTSCR_POL_Msk (0x01 << UART_CTSCR_POL_Pos) +#define UART_CTSCR_STAT_Pos 7 //CTS信号的当前状态 +#define UART_CTSCR_STAT_Msk (0x01 << UART_CTSCR_STAT_Pos) -#define UART_CTSCR_EN_Pos 0 //CTS流控使能 -#define UART_CTSCR_EN_Msk (0x01 << UART_CTSCR_EN_Pos) -#define UART_CTSCR_POL_Pos 2 //CTS信号极性,0 低有效,CTS输入为低表示可以发送数据 -#define UART_CTSCR_POL_Msk (0x01 << UART_CTSCR_POL_Pos) -#define UART_CTSCR_STAT_Pos 7 //CTS信号的当前状态 -#define UART_CTSCR_STAT_Msk (0x01 << UART_CTSCR_STAT_Pos) +#define UART_RTSCR_EN_Pos 1 //RTS流控使能 +#define UART_RTSCR_EN_Msk (0x01 << UART_RTSCR_EN_Pos) +#define UART_RTSCR_POL_Pos 3 //RTS信号极性 0 低有效,RTS输入为低表示可以接收数据 +#define UART_RTSCR_POL_Msk (0x01 << UART_RTSCR_POL_Pos) +#define UART_RTSCR_THR_Pos 4 //RTS流控的触发阈值 0 1字节 1 2字节 2 4字节 3 6字节 +#define UART_RTSCR_THR_Msk (0x07 << UART_RTSCR_THR_Pos) +#define UART_RTSCR_STAT_Pos 8 //RTS信号的当前状态 +#define UART_RTSCR_STAT_Msk (0x01 << UART_RTSCR_STAT_Pos) -#define UART_RTSCR_EN_Pos 1 //RTS流控使能 -#define UART_RTSCR_EN_Msk (0x01 << UART_RTSCR_EN_Pos) -#define UART_RTSCR_POL_Pos 3 //RTS信号极性 0 低有效,RTS输入为低表示可以接收数据 -#define UART_RTSCR_POL_Msk (0x01 << UART_RTSCR_POL_Pos) -#define UART_RTSCR_THR_Pos 4 //RTS流控的触发阈值 0 1字节 1 2字节 2 4字节 3 6字节 -#define UART_RTSCR_THR_Msk (0x07 << UART_RTSCR_THR_Pos) -#define UART_RTSCR_STAT_Pos 8 //RTS信号的当前状态 -#define UART_RTSCR_STAT_Msk (0x01 << UART_RTSCR_STAT_Pos) +typedef struct +{ + __IO uint32_t CTRL; + __IO uint32_t DATA; + __IO uint32_t STAT; + __IO uint32_t IE; -typedef struct { - __IO uint32_t CTRL; - - __IO uint32_t DATA; - - __IO uint32_t STAT; - - __IO uint32_t IE; - - __IO uint32_t IF; + __IO uint32_t IF; } SPI_TypeDef; +#define SPI_CTRL_CLKDIV_Pos 0 //Clock Divider, SPI工作时钟 = SYS_Freq/pow(2, CLKDIV+2) +#define SPI_CTRL_CLKDIV_Msk (0x07 << SPI_CTRL_CLKDIV_Pos) +#define SPI_CTRL_EN_Pos 3 +#define SPI_CTRL_EN_Msk (0x01 << SPI_CTRL_EN_Pos) +#define SPI_CTRL_SIZE_Pos 4 //Data Size Select, 取值3--15,表示4--16位 +#define SPI_CTRL_SIZE_Msk (0x0F << SPI_CTRL_SIZE_Pos) +#define SPI_CTRL_CPHA_Pos 8 //0 在SCLK的第一个跳变沿采样数据 1 在SCLK的第二个跳变沿采样数据 +#define SPI_CTRL_CPHA_Msk (0x01 << SPI_CTRL_CPHA_Pos) +#define SPI_CTRL_CPOL_Pos 9 //0 空闲状态下SCLK为低电平 1 空闲状态下SCLK为高电平 +#define SPI_CTRL_CPOL_Msk (0x01 << SPI_CTRL_CPOL_Pos) +#define SPI_CTRL_FFS_Pos 10 //Frame Format Select, 0 SPI 1 TI SSI 2 SPI 3 SPI +#define SPI_CTRL_FFS_Msk (0x03 << SPI_CTRL_FFS_Pos) +#define SPI_CTRL_MSTR_Pos 12 //Master, 1 主模式 0 从模式 +#define SPI_CTRL_MSTR_Msk (0x01 << SPI_CTRL_MSTR_Pos) +#define SPI_CTRL_FAST_Pos 13 //1 SPI工作时钟 = SYS_Freq/2 0 SPI工作时钟由SPI->CTRL.CLKDIV设置 +#define SPI_CTRL_FAST_Msk (0x01 << SPI_CTRL_FAST_Pos) +#define SPI_CTRL_FILTE_Pos 16 //1 对SPI输入信号进行去抖操作 0 对SPI输入信号不进行去抖操作 +#define SPI_CTRL_FILTE_Msk (0x01 << SPI_CTRL_FILTE_Pos) +#define SPI_CTRL_SSN_H_Pos 17 //0 传输过程中SSN始终为0 1 传输过程中每字符之间会将SSN拉高半个SCLK周期 +#define SPI_CTRL_SSN_H_Msk (0x01 << SPI_CTRL_SSN_H_Pos) +#define SPI_CTRL_TFCLR_Pos 24 //TX FIFO Clear +#define SPI_CTRL_TFCLR_Msk (0x01 << SPI_CTRL_TFCLR_Pos) +#define SPI_CTRL_RFCLR_Pos 25 //RX FIFO Clear +#define SPI_CTRL_RFCLR_Msk (0x01 << SPI_CTRL_RFCLR_Pos) -#define SPI_CTRL_CLKDIV_Pos 0 //Clock Divider, SPI工作时钟 = SYS_Freq/pow(2, CLKDIV+2) -#define SPI_CTRL_CLKDIV_Msk (0x07 << SPI_CTRL_CLKDIV_Pos) -#define SPI_CTRL_EN_Pos 3 -#define SPI_CTRL_EN_Msk (0x01 << SPI_CTRL_EN_Pos) -#define SPI_CTRL_SIZE_Pos 4 //Data Size Select, 取值3--15,表示4--16位 -#define SPI_CTRL_SIZE_Msk (0x0F << SPI_CTRL_SIZE_Pos) -#define SPI_CTRL_CPHA_Pos 8 //0 在SCLK的第一个跳变沿采样数据 1 在SCLK的第二个跳变沿采样数据 -#define SPI_CTRL_CPHA_Msk (0x01 << SPI_CTRL_CPHA_Pos) -#define SPI_CTRL_CPOL_Pos 9 //0 空闲状态下SCLK为低电平 1 空闲状态下SCLK为高电平 -#define SPI_CTRL_CPOL_Msk (0x01 << SPI_CTRL_CPOL_Pos) -#define SPI_CTRL_FFS_Pos 10 //Frame Format Select, 0 SPI 1 TI SSI 2 SPI 3 SPI -#define SPI_CTRL_FFS_Msk (0x03 << SPI_CTRL_FFS_Pos) -#define SPI_CTRL_MSTR_Pos 12 //Master, 1 主模式 0 从模式 -#define SPI_CTRL_MSTR_Msk (0x01 << SPI_CTRL_MSTR_Pos) -#define SPI_CTRL_FAST_Pos 13 //1 SPI工作时钟 = SYS_Freq/2 0 SPI工作时钟由SPI->CTRL.CLKDIV设置 -#define SPI_CTRL_FAST_Msk (0x01 << SPI_CTRL_FAST_Pos) -#define SPI_CTRL_FILTE_Pos 16 //1 对SPI输入信号进行去抖操作 0 对SPI输入信号不进行去抖操作 -#define SPI_CTRL_FILTE_Msk (0x01 << SPI_CTRL_FILTE_Pos) -#define SPI_CTRL_SSN_H_Pos 17 //0 传输过程中SSN始终为0 1 传输过程中每字符之间会将SSN拉高半个SCLK周期 -#define SPI_CTRL_SSN_H_Msk (0x01 << SPI_CTRL_SSN_H_Pos) -#define SPI_CTRL_TFCLR_Pos 24 //TX FIFO Clear -#define SPI_CTRL_TFCLR_Msk (0x01 << SPI_CTRL_TFCLR_Pos) -#define SPI_CTRL_RFCLR_Pos 25 //RX FIFO Clear -#define SPI_CTRL_RFCLR_Msk (0x01 << SPI_CTRL_RFCLR_Pos) +#define SPI_STAT_WTC_Pos 0 //Word Transmit Complete,每传输完成一个数据字由硬件置1,软件写1清零 +#define SPI_STAT_WTC_Msk (0x01 << SPI_STAT_WTC_Pos) +#define SPI_STAT_TFE_Pos 1 //发送FIFO Empty +#define SPI_STAT_TFE_Msk (0x01 << SPI_STAT_TFE_Pos) +#define SPI_STAT_TFNF_Pos 2 //发送FIFO Not Full +#define SPI_STAT_TFNF_Msk (0x01 << SPI_STAT_TFNF_Pos) +#define SPI_STAT_RFNE_Pos 3 //接收FIFO Not Empty +#define SPI_STAT_RFNE_Msk (0x01 << SPI_STAT_RFNE_Pos) +#define SPI_STAT_RFF_Pos 4 //接收FIFO Full +#define SPI_STAT_RFF_Msk (0x01 << SPI_STAT_RFF_Pos) +#define SPI_STAT_RFOVF_Pos 5 //接收FIFO Overflow +#define SPI_STAT_RFOVF_Msk (0x01 << SPI_STAT_RFOVF_Pos) +#define SPI_STAT_TFLVL_Pos 6 //发送FIFO中数据个数, 0 TFNF=0时表示FIFO内有8个数据,TFNF=1时表示FIFO内有0个数据 1--7 FIFO内有1--7个数据 +#define SPI_STAT_TFLVL_Msk (0x07 << SPI_STAT_TFLVL_Pos) +#define SPI_STAT_RFLVL_Pos 9 //接收FIFO中数据个数, 0 RFF=1时表示FIFO内有8个数据, RFF=0时表示FIFO内有0个数据 1--7 FIFO内有1--7个数据 +#define SPI_STAT_RFLVL_Msk (0x07 << SPI_STAT_RFLVL_Pos) +#define SPI_STAT_BUSY_Pos 15 +#define SPI_STAT_BUSY_Msk (0x01 << SPI_STAT_BUSY_Pos) -#define SPI_STAT_WTC_Pos 0 //Word Transmit Complete,每传输完成一个数据字由硬件置1,软件写1清零 -#define SPI_STAT_WTC_Msk (0x01 << SPI_STAT_WTC_Pos) -#define SPI_STAT_TFE_Pos 1 //发送FIFO Empty -#define SPI_STAT_TFE_Msk (0x01 << SPI_STAT_TFE_Pos) -#define SPI_STAT_TFNF_Pos 2 //发送FIFO Not Full -#define SPI_STAT_TFNF_Msk (0x01 << SPI_STAT_TFNF_Pos) -#define SPI_STAT_RFNE_Pos 3 //接收FIFO Not Empty -#define SPI_STAT_RFNE_Msk (0x01 << SPI_STAT_RFNE_Pos) -#define SPI_STAT_RFF_Pos 4 //接收FIFO Full -#define SPI_STAT_RFF_Msk (0x01 << SPI_STAT_RFF_Pos) -#define SPI_STAT_RFOVF_Pos 5 //接收FIFO Overflow -#define SPI_STAT_RFOVF_Msk (0x01 << SPI_STAT_RFOVF_Pos) -#define SPI_STAT_TFLVL_Pos 6 //发送FIFO中数据个数, 0 TFNF=0时表示FIFO内有8个数据,TFNF=1时表示FIFO内有0个数据 1--7 FIFO内有1--7个数据 -#define SPI_STAT_TFLVL_Msk (0x07 << SPI_STAT_TFLVL_Pos) -#define SPI_STAT_RFLVL_Pos 9 //接收FIFO中数据个数, 0 RFF=1时表示FIFO内有8个数据, RFF=0时表示FIFO内有0个数据 1--7 FIFO内有1--7个数据 -#define SPI_STAT_RFLVL_Msk (0x07 << SPI_STAT_RFLVL_Pos) -#define SPI_STAT_BUSY_Pos 15 -#define SPI_STAT_BUSY_Msk (0x01 << SPI_STAT_BUSY_Pos) +#define SPI_IE_RFOVF_Pos 0 +#define SPI_IE_RFOVF_Msk (0x01 << SPI_IE_RFOVF_Pos) +#define SPI_IE_RFF_Pos 1 +#define SPI_IE_RFF_Msk (0x01 << SPI_IE_RFF_Pos) +#define SPI_IE_RFHF_Pos 2 +#define SPI_IE_RFHF_Msk (0x01 << SPI_IE_RFHF_Pos) +#define SPI_IE_TFE_Pos 3 +#define SPI_IE_TFE_Msk (0x01 << SPI_IE_TFE_Pos) +#define SPI_IE_TFHF_Pos 4 +#define SPI_IE_TFHF_Msk (0x01 << SPI_IE_TFHF_Pos) +#define SPI_IE_WTC_Pos 8 //Word Transmit Complete +#define SPI_IE_WTC_Msk (0x01 << SPI_IE_WTC_Pos) +#define SPI_IE_FTC_Pos 9 //Frame Transmit Complete +#define SPI_IE_FTC_Msk (0x01 << SPI_IE_FTC_Pos) -#define SPI_IE_RFOVF_Pos 0 -#define SPI_IE_RFOVF_Msk (0x01 << SPI_IE_RFOVF_Pos) -#define SPI_IE_RFF_Pos 1 -#define SPI_IE_RFF_Msk (0x01 << SPI_IE_RFF_Pos) -#define SPI_IE_RFHF_Pos 2 -#define SPI_IE_RFHF_Msk (0x01 << SPI_IE_RFHF_Pos) -#define SPI_IE_TFE_Pos 3 -#define SPI_IE_TFE_Msk (0x01 << SPI_IE_TFE_Pos) -#define SPI_IE_TFHF_Pos 4 -#define SPI_IE_TFHF_Msk (0x01 << SPI_IE_TFHF_Pos) -#define SPI_IE_WTC_Pos 8 //Word Transmit Complete -#define SPI_IE_WTC_Msk (0x01 << SPI_IE_WTC_Pos) -#define SPI_IE_FTC_Pos 9 //Frame Transmit Complete -#define SPI_IE_FTC_Msk (0x01 << SPI_IE_FTC_Pos) +#define SPI_IF_RFOVF_Pos 0 //写1清零 +#define SPI_IF_RFOVF_Msk (0x01 << SPI_IF_RFOVF_Pos) +#define SPI_IF_RFF_Pos 1 +#define SPI_IF_RFF_Msk (0x01 << SPI_IF_RFF_Pos) +#define SPI_IF_RFHF_Pos 2 +#define SPI_IF_RFHF_Msk (0x01 << SPI_IF_RFHF_Pos) +#define SPI_IF_TFE_Pos 3 +#define SPI_IF_TFE_Msk (0x01 << SPI_IF_TFE_Pos) +#define SPI_IF_TFHF_Pos 4 +#define SPI_IF_TFHF_Msk (0x01 << SPI_IF_TFHF_Pos) +#define SPI_IF_WTC_Pos 8 //Word Transmit Complete,每传输完成一个数据字由硬件置1 +#define SPI_IF_WTC_Msk (0x01 << SPI_IF_WTC_Pos) +#define SPI_IF_FTC_Pos 9 //Frame Transmit Complete,WTC置位时若TX FIFO是空的,则FTC置位 +#define SPI_IF_FTC_Msk (0x01 << SPI_IF_FTC_Pos) -#define SPI_IF_RFOVF_Pos 0 //写1清零 -#define SPI_IF_RFOVF_Msk (0x01 << SPI_IF_RFOVF_Pos) -#define SPI_IF_RFF_Pos 1 -#define SPI_IF_RFF_Msk (0x01 << SPI_IF_RFF_Pos) -#define SPI_IF_RFHF_Pos 2 -#define SPI_IF_RFHF_Msk (0x01 << SPI_IF_RFHF_Pos) -#define SPI_IF_TFE_Pos 3 -#define SPI_IF_TFE_Msk (0x01 << SPI_IF_TFE_Pos) -#define SPI_IF_TFHF_Pos 4 -#define SPI_IF_TFHF_Msk (0x01 << SPI_IF_TFHF_Pos) -#define SPI_IF_WTC_Pos 8 //Word Transmit Complete,每传输完成一个数据字由硬件置1 -#define SPI_IF_WTC_Msk (0x01 << SPI_IF_WTC_Pos) -#define SPI_IF_FTC_Pos 9 //Frame Transmit Complete,WTC置位时若TX FIFO是空的,则FTC置位 -#define SPI_IF_FTC_Msk (0x01 << SPI_IF_FTC_Pos) +typedef struct +{ + __IO uint32_t CLKDIV; //[15:0] 须将内部工作频率分到SCL频率的5倍,即CLKDIV = SYS_Freq/5/SCL_Freq - 1 + __IO uint32_t CTRL; + __IO uint32_t MSTDAT; + __IO uint32_t MSTCMD; -typedef struct { - __IO uint32_t CLKDIV; //[15:0] 须将内部工作频率分到SCL频率的5倍,即CLKDIV = SYS_Freq/5/SCL_Freq - 1 + __IO uint32_t SLVCR; - __IO uint32_t CTRL; + __IO uint32_t SLVIF; - __IO uint32_t MSTDAT; + __IO uint32_t SLVTX; - __IO uint32_t MSTCMD; - - __IO uint32_t SLVCR; - - __IO uint32_t SLVIF; - - __IO uint32_t SLVTX; - - __IO uint32_t SLVRX; + __IO uint32_t SLVRX; } I2C_TypeDef; +#define I2C_CTRL_MSTIE_Pos 6 +#define I2C_CTRL_MSTIE_Msk (0x01 << I2C_CTRL_MSTIE_Pos) +#define I2C_CTRL_EN_Pos 7 +#define I2C_CTRL_EN_Msk (0x01 << I2C_CTRL_EN_Pos) -#define I2C_CTRL_MSTIE_Pos 6 -#define I2C_CTRL_MSTIE_Msk (0x01 << I2C_CTRL_MSTIE_Pos) -#define I2C_CTRL_EN_Pos 7 -#define I2C_CTRL_EN_Msk (0x01 << I2C_CTRL_EN_Pos) +#define I2C_MSTCMD_IF_Pos 0 //1 有等待处理的中断,写1清零 有两种情况下此位硬件置位:1、一个字节传输完成 2、总线访问权丢失 +#define I2C_MSTCMD_IF_Msk (0x01 << I2C_MSTCMD_IF_Pos) +#define I2C_MSTCMD_TIP_Pos 1 //Transmission In Process +#define I2C_MSTCMD_TIP_Msk (0x01 << I2C_MSTCMD_TIP_Pos) +#define I2C_MSTCMD_ACK_Pos 3 //接收模式下,0 向发送端反馈ACK 1 向发送端反馈NACK +#define I2C_MSTCMD_ACK_Msk (0x01 << I2C_MSTCMD_ACK_Pos) +#define I2C_MSTCMD_WR_Pos 4 // 向Slave写数据时,把这一位写1,自动清零 +#define I2C_MSTCMD_WR_Msk (0x01 << I2C_MSTCMD_WR_Pos) +#define I2C_MSTCMD_RD_Pos 5 //写:从Slave读数据时,把这一位写1,自动清零 读:当I2C模块失去总线的访问权时硬件置1 +#define I2C_MSTCMD_RD_Msk (0x01 << I2C_MSTCMD_RD_Pos) +#define I2C_MSTCMD_BUSY_Pos 6 //读:当检测到START之后,这一位变1;当检测到STOP之后,这一位变0 +#define I2C_MSTCMD_BUSY_Msk (0x01 << I2C_MSTCMD_BUSY_Pos) +#define I2C_MSTCMD_STO_Pos 6 //写:产生STOP,自动清零 +#define I2C_MSTCMD_STO_Msk (0x01 << I2C_MSTCMD_STO_Pos) +#define I2C_MSTCMD_RXACK_Pos 7 //读:接收到的Slave的ACK位,0 收到ACK 1 收到NACK +#define I2C_MSTCMD_RXACK_Msk (0x01 << I2C_MSTCMD_RXACK_Pos) +#define I2C_MSTCMD_STA_Pos 7 //写:产生START,自动清零 +#define I2C_MSTCMD_STA_Msk (0x01 << I2C_MSTCMD_STA_Pos) -#define I2C_MSTCMD_IF_Pos 0 //1 有等待处理的中断,写1清零 有两种情况下此位硬件置位:1、一个字节传输完成 2、总线访问权丢失 -#define I2C_MSTCMD_IF_Msk (0x01 << I2C_MSTCMD_IF_Pos) -#define I2C_MSTCMD_TIP_Pos 1 //Transmission In Process -#define I2C_MSTCMD_TIP_Msk (0x01 << I2C_MSTCMD_TIP_Pos) -#define I2C_MSTCMD_ACK_Pos 3 //接收模式下,0 向发送端反馈ACK 1 向发送端反馈NACK -#define I2C_MSTCMD_ACK_Msk (0x01 << I2C_MSTCMD_ACK_Pos) -#define I2C_MSTCMD_WR_Pos 4 // 向Slave写数据时,把这一位写1,自动清零 -#define I2C_MSTCMD_WR_Msk (0x01 << I2C_MSTCMD_WR_Pos) -#define I2C_MSTCMD_RD_Pos 5 //写:从Slave读数据时,把这一位写1,自动清零 读:当I2C模块失去总线的访问权时硬件置1 -#define I2C_MSTCMD_RD_Msk (0x01 << I2C_MSTCMD_RD_Pos) -#define I2C_MSTCMD_BUSY_Pos 6 //读:当检测到START之后,这一位变1;当检测到STOP之后,这一位变0 -#define I2C_MSTCMD_BUSY_Msk (0x01 << I2C_MSTCMD_BUSY_Pos) -#define I2C_MSTCMD_STO_Pos 6 //写:产生STOP,自动清零 -#define I2C_MSTCMD_STO_Msk (0x01 << I2C_MSTCMD_STO_Pos) -#define I2C_MSTCMD_RXACK_Pos 7 //读:接收到的Slave的ACK位,0 收到ACK 1 收到NACK -#define I2C_MSTCMD_RXACK_Msk (0x01 << I2C_MSTCMD_RXACK_Pos) -#define I2C_MSTCMD_STA_Pos 7 //写:产生START,自动清零 -#define I2C_MSTCMD_STA_Msk (0x01 << I2C_MSTCMD_STA_Pos) +#define I2C_SLVCR_IM_RXEND_Pos 0 //接收完成中断禁止 +#define I2C_SLVCR_IM_RXEND_Msk (0x01 << I2C_SLVCR_IM_RXEND_Pos) +#define I2C_SLVCR_IM_TXEND_Pos 1 //发送完成中断禁止 +#define I2C_SLVCR_IM_TXEND_Msk (0x01 << I2C_SLVCR_IM_TXEND_Pos) +#define I2C_SLVCR_IM_STADET_Pos 2 //检测到起始中断禁止 +#define I2C_SLVCR_IM_STADET_Msk (0x01 << I2C_SLVCR_IM_STADET_Pos) +#define I2C_SLVCR_IM_STODET_Pos 3 //检测到停止中断禁止 +#define I2C_SLVCR_IM_STODET_Msk (0x01 << I2C_SLVCR_IM_STODET_Pos) +#define I2C_SLVCR_IM_RDREQ_Pos 4 //接收到读请求中断禁止 +#define I2C_SLVCR_IM_RDREQ_Msk (0x01 << I2C_SLVCR_IM_RDREQ_Pos) +#define I2C_SLVCR_IM_WRREQ_Pos 5 //接收到写请求中断禁止 +#define I2C_SLVCR_IM_WRREQ_Msk (0x01 << I2C_SLVCR_IM_WRREQ_Pos) +#define I2C_SLVCR_ADDR7b_Pos 16 //1 7位地址模式 0 10位地址模式 +#define I2C_SLVCR_ADDR7b_Msk (0x01 << I2C_SLVCR_ADDR7b_Pos) +#define I2C_SLVCR_ACK_Pos 17 //1 应答ACK 0 应答NACK +#define I2C_SLVCR_ACK_Msk (0x01 << I2C_SLVCR_ACK_Pos) +#define I2C_SLVCR_SLAVE_Pos 18 //1 从机模式 0 主机模式 +#define I2C_SLVCR_SLAVE_Msk (0x01 << I2C_SLVCR_SLAVE_Pos) +#define I2C_SLVCR_DEBOUNCE_Pos 19 //去抖动使能 +#define I2C_SLVCR_DEBOUNCE_Msk (0x01 << I2C_SLVCR_DEBOUNCE_Pos) +#define I2C_SLVCR_ADDR_Pos 20 //从机地址 +#define I2C_SLVCR_ADDR_Msk (0x3FF << I2C_SLVCR_ADDR_Pos) -#define I2C_SLVCR_IM_RXEND_Pos 0 //接收完成中断禁止 -#define I2C_SLVCR_IM_RXEND_Msk (0x01 << I2C_SLVCR_IM_RXEND_Pos) -#define I2C_SLVCR_IM_TXEND_Pos 1 //发送完成中断禁止 -#define I2C_SLVCR_IM_TXEND_Msk (0x01 << I2C_SLVCR_IM_TXEND_Pos) -#define I2C_SLVCR_IM_STADET_Pos 2 //检测到起始中断禁止 -#define I2C_SLVCR_IM_STADET_Msk (0x01 << I2C_SLVCR_IM_STADET_Pos) -#define I2C_SLVCR_IM_STODET_Pos 3 //检测到停止中断禁止 -#define I2C_SLVCR_IM_STODET_Msk (0x01 << I2C_SLVCR_IM_STODET_Pos) -#define I2C_SLVCR_IM_RDREQ_Pos 4 //接收到读请求中断禁止 -#define I2C_SLVCR_IM_RDREQ_Msk (0x01 << I2C_SLVCR_IM_RDREQ_Pos) -#define I2C_SLVCR_IM_WRREQ_Pos 5 //接收到写请求中断禁止 -#define I2C_SLVCR_IM_WRREQ_Msk (0x01 << I2C_SLVCR_IM_WRREQ_Pos) -#define I2C_SLVCR_ADDR7b_Pos 16 //1 7位地址模式 0 10位地址模式 -#define I2C_SLVCR_ADDR7b_Msk (0x01 << I2C_SLVCR_ADDR7b_Pos) -#define I2C_SLVCR_ACK_Pos 17 //1 应答ACK 0 应答NACK -#define I2C_SLVCR_ACK_Msk (0x01 << I2C_SLVCR_ACK_Pos) -#define I2C_SLVCR_SLAVE_Pos 18 //1 从机模式 0 主机模式 -#define I2C_SLVCR_SLAVE_Msk (0x01 << I2C_SLVCR_SLAVE_Pos) -#define I2C_SLVCR_DEBOUNCE_Pos 19 //去抖动使能 -#define I2C_SLVCR_DEBOUNCE_Msk (0x01 << I2C_SLVCR_DEBOUNCE_Pos) -#define I2C_SLVCR_ADDR_Pos 20 //从机地址 -#define I2C_SLVCR_ADDR_Msk (0x3FF << I2C_SLVCR_ADDR_Pos) +#define I2C_SLVIF_RXEND_Pos 0 //接收完成中断标志,写1清零 +#define I2C_SLVIF_RXEND_Msk (0x01 << I2C_SLVIF_RXEND_Pos) +#define I2C_SLVIF_TXEND_Pos 1 //发送完成中断标志,写1清零 +#define I2C_SLVIF_TXEND_Msk (0x01 << I2C_SLVIF_TXEND_Pos) +#define I2C_SLVIF_STADET_Pos 2 //检测到起始中断标志,写1清零 +#define I2C_SLVIF_STADET_Msk (0x01 << I2C_SLVIF_STADET_Pos) +#define I2C_SLVIF_STODET_Pos 3 //检测到停止中断标志,写1清零 +#define I2C_SLVIF_STODET_Msk (0x01 << I2C_SLVIF_STODET_Pos) +#define I2C_SLVIF_RDREQ_Pos 4 //接收到读请求中断标志 +#define I2C_SLVIF_RDREQ_Msk (0x01 << I2C_SLVIF_RDREQ_Pos) +#define I2C_SLVIF_WRREQ_Pos 5 //接收到写请求中断标志 +#define I2C_SLVIF_WRREQ_Msk (0x01 << I2C_SLVIF_WRREQ_Pos) +#define I2C_SLVIF_ACTIVE_Pos 6 //slave 有效 +#define I2C_SLVIF_ACTIVE_Msk (0x01 << I2C_SLVIF_ACTIVE_Pos) -#define I2C_SLVIF_RXEND_Pos 0 //接收完成中断标志,写1清零 -#define I2C_SLVIF_RXEND_Msk (0x01 << I2C_SLVIF_RXEND_Pos) -#define I2C_SLVIF_TXEND_Pos 1 //发送完成中断标志,写1清零 -#define I2C_SLVIF_TXEND_Msk (0x01 << I2C_SLVIF_TXEND_Pos) -#define I2C_SLVIF_STADET_Pos 2 //检测到起始中断标志,写1清零 -#define I2C_SLVIF_STADET_Msk (0x01 << I2C_SLVIF_STADET_Pos) -#define I2C_SLVIF_STODET_Pos 3 //检测到停止中断标志,写1清零 -#define I2C_SLVIF_STODET_Msk (0x01 << I2C_SLVIF_STODET_Pos) -#define I2C_SLVIF_RDREQ_Pos 4 //接收到读请求中断标志 -#define I2C_SLVIF_RDREQ_Msk (0x01 << I2C_SLVIF_RDREQ_Pos) -#define I2C_SLVIF_WRREQ_Pos 5 //接收到写请求中断标志 -#define I2C_SLVIF_WRREQ_Msk (0x01 << I2C_SLVIF_WRREQ_Pos) -#define I2C_SLVIF_ACTIVE_Pos 6 //slave 有效 -#define I2C_SLVIF_ACTIVE_Msk (0x01 << I2C_SLVIF_ACTIVE_Pos) +typedef struct +{ + __IO uint32_t CTRL; + __IO uint32_t START; + __IO uint32_t IE; + __IO uint32_t IF; -typedef struct { - __IO uint32_t CTRL; - - __IO uint32_t START; - - __IO uint32_t IE; - - __IO uint32_t IF; - - struct { - __IO uint32_t STAT; - - __IO uint32_t DATA; - - uint32_t RESERVED[2]; - } CH[8]; - - __IO uint32_t CTRL1; - - __IO uint32_t CTRL2; - - uint32_t RESERVED[2]; - - __IO uint32_t CALIBSET; - - __IO uint32_t CALIBEN; + struct + { + __IO uint32_t STAT; + + __IO uint32_t DATA; + + uint32_t RESERVED[2]; + } CH[8]; + + __IO uint32_t CTRL1; + + __IO uint32_t CTRL2; + + uint32_t RESERVED[2]; + + __IO uint32_t CALIBSET; + + __IO uint32_t CALIBEN; } ADC_TypeDef; +#define ADC_CTRL_CH0_Pos 0 //通道选中 +#define ADC_CTRL_CH0_Msk (0x01 << ADC_CTRL_CH0_Pos) +#define ADC_CTRL_CH1_Pos 1 +#define ADC_CTRL_CH1_Msk (0x01 << ADC_CTRL_CH1_Pos) +#define ADC_CTRL_CH2_Pos 2 +#define ADC_CTRL_CH2_Msk (0x01 << ADC_CTRL_CH2_Pos) +#define ADC_CTRL_CH3_Pos 3 +#define ADC_CTRL_CH3_Msk (0x01 << ADC_CTRL_CH3_Pos) +#define ADC_CTRL_CH4_Pos 4 +#define ADC_CTRL_CH4_Msk (0x01 << ADC_CTRL_CH4_Pos) +#define ADC_CTRL_CH5_Pos 5 +#define ADC_CTRL_CH5_Msk (0x01 << ADC_CTRL_CH5_Pos) +#define ADC_CTRL_CH6_Pos 6 +#define ADC_CTRL_CH6_Msk (0x01 << ADC_CTRL_CH6_Pos) +#define ADC_CTRL_CH7_Pos 7 +#define ADC_CTRL_CH7_Msk (0x01 << ADC_CTRL_CH7_Pos) +#define ADC_CTRL_AVG_Pos 8 //0 1次采样 1 2次采样取平均值 3 4次采样取平均值 7 8次采样取平均值 15 16次采样取平均值 +#define ADC_CTRL_AVG_Msk (0x0F << ADC_CTRL_AVG_Pos) +#define ADC_CTRL_EN_Pos 12 +#define ADC_CTRL_EN_Msk (0x01 << ADC_CTRL_EN_Pos) +#define ADC_CTRL_CONT_Pos 13 //Continuous conversion,只在软件启动模式下有效,0 单次转换,转换完成后START位自动清除停止转换 +#define ADC_CTRL_CONT_Msk (0x01 << ADC_CTRL_CONT_Pos) // 1 连续转换,启动后一直采样、转换,直到软件清除START位 +#define ADC_CTRL_TRIG_Pos 14 //转换触发方式:0 软件启动转换 1 PWM触发 +#define ADC_CTRL_TRIG_Msk (0x01 << ADC_CTRL_TRIG_Pos) +#define ADC_CTRL_CLKSRC_Pos 15 //0 VCO 1 HRC +#define ADC_CTRL_CLKSRC_Msk (0x01 << ADC_CTRL_CLKSRC_Pos) +#define ADC_CTRL_FIFOCLR_Pos 24 //[24] CH0_FIFO_CLR [25] CH1_FIFO_CLR ... [31] CH7_FIFO_CLR +#define ADC_CTRL_FIFOCLR_Msk (0xFFu << ADC_CTRL_FIFOCLR_Pos) -#define ADC_CTRL_CH0_Pos 0 //通道选中 -#define ADC_CTRL_CH0_Msk (0x01 << ADC_CTRL_CH0_Pos) -#define ADC_CTRL_CH1_Pos 1 -#define ADC_CTRL_CH1_Msk (0x01 << ADC_CTRL_CH1_Pos) -#define ADC_CTRL_CH2_Pos 2 -#define ADC_CTRL_CH2_Msk (0x01 << ADC_CTRL_CH2_Pos) -#define ADC_CTRL_CH3_Pos 3 -#define ADC_CTRL_CH3_Msk (0x01 << ADC_CTRL_CH3_Pos) -#define ADC_CTRL_CH4_Pos 4 -#define ADC_CTRL_CH4_Msk (0x01 << ADC_CTRL_CH4_Pos) -#define ADC_CTRL_CH5_Pos 5 -#define ADC_CTRL_CH5_Msk (0x01 << ADC_CTRL_CH5_Pos) -#define ADC_CTRL_CH6_Pos 6 -#define ADC_CTRL_CH6_Msk (0x01 << ADC_CTRL_CH6_Pos) -#define ADC_CTRL_CH7_Pos 7 -#define ADC_CTRL_CH7_Msk (0x01 << ADC_CTRL_CH7_Pos) -#define ADC_CTRL_AVG_Pos 8 //0 1次采样 1 2次采样取平均值 3 4次采样取平均值 7 8次采样取平均值 15 16次采样取平均值 -#define ADC_CTRL_AVG_Msk (0x0F << ADC_CTRL_AVG_Pos) -#define ADC_CTRL_EN_Pos 12 -#define ADC_CTRL_EN_Msk (0x01 << ADC_CTRL_EN_Pos) -#define ADC_CTRL_CONT_Pos 13 //Continuous conversion,只在软件启动模式下有效,0 单次转换,转换完成后START位自动清除停止转换 -#define ADC_CTRL_CONT_Msk (0x01 << ADC_CTRL_CONT_Pos) // 1 连续转换,启动后一直采样、转换,直到软件清除START位 -#define ADC_CTRL_TRIG_Pos 14 //转换触发方式:0 软件启动转换 1 PWM触发 -#define ADC_CTRL_TRIG_Msk (0x01 << ADC_CTRL_TRIG_Pos) -#define ADC_CTRL_CLKSRC_Pos 15 //0 VCO 1 HRC -#define ADC_CTRL_CLKSRC_Msk (0x01 << ADC_CTRL_CLKSRC_Pos) -#define ADC_CTRL_FIFOCLR_Pos 24 //[24] CH0_FIFO_CLR [25] CH1_FIFO_CLR ... [31] CH7_FIFO_CLR -#define ADC_CTRL_FIFOCLR_Msk (0xFFu<< ADC_CTRL_FIFOCLR_Pos) +#define ADC_START_GO_Pos 0 //软件触发模式下,写1启动ADC采样和转换,在单次模式下转换完成后硬件自动清零,在扫描模式下必须软件写0停止ADC转换 +#define ADC_START_GO_Msk (0x01 << ADC_START_GO_Pos) +#define ADC_START_BUSY_Pos 4 +#define ADC_START_BUSY_Msk (0x01 << ADC_START_BUSY_Pos) -#define ADC_START_GO_Pos 0 //软件触发模式下,写1启动ADC采样和转换,在单次模式下转换完成后硬件自动清零,在扫描模式下必须软件写0停止ADC转换 -#define ADC_START_GO_Msk (0x01 << ADC_START_GO_Pos) -#define ADC_START_BUSY_Pos 4 -#define ADC_START_BUSY_Msk (0x01 << ADC_START_BUSY_Pos) +#define ADC_IE_CH0EOC_Pos 0 //End Of Convertion +#define ADC_IE_CH0EOC_Msk (0x01 << ADC_IE_CH0EOC_Pos) +#define ADC_IE_CH0OVF_Pos 1 //Overflow +#define ADC_IE_CH0OVF_Msk (0x01 << ADC_IE_CH0OVF_Pos) +#define ADC_IE_CH0HFULL_Pos 2 //FIFO Half Full +#define ADC_IE_CH0HFULL_Msk (0x01 << ADC_IE_CH0HFULL_Pos) +#define ADC_IE_CH0FULL_Pos 3 //FIFO Full +#define ADC_IE_CH0FULL_Msk (0x01 << ADC_IE_CH0FULL_Pos) +#define ADC_IE_CH1EOC_Pos 4 +#define ADC_IE_CH1EOC_Msk (0x01 << ADC_IE_CH1EOC_Pos) +#define ADC_IE_CH1OVF_Pos 5 +#define ADC_IE_CH1OVF_Msk (0x01 << ADC_IE_CH1OVF_Pos) +#define ADC_IE_CH1HFULL_Pos 6 +#define ADC_IE_CH1HFULL_Msk (0x01 << ADC_IE_CH1HFULL_Pos) +#define ADC_IE_CH1FULL_Pos 7 +#define ADC_IE_CH1FULL_Msk (0x01 << ADC_IE_CH1FULL_Pos) +#define ADC_IE_CH2EOC_Pos 8 +#define ADC_IE_CH2EOC_Msk (0x01 << ADC_IE_CH2EOC_Pos) +#define ADC_IE_CH2OVF_Pos 9 +#define ADC_IE_CH2OVF_Msk (0x01 << ADC_IE_CH2OVF_Pos) +#define ADC_IE_CH2HFULL_Pos 10 +#define ADC_IE_CH2HFULL_Msk (0x01 << ADC_IE_CH2HFULL_Pos) +#define ADC_IE_CH2FULL_Pos 11 +#define ADC_IE_CH2FULL_Msk (0x01 << ADC_IE_CH2FULL_Pos) +#define ADC_IE_CH3EOC_Pos 12 +#define ADC_IE_CH3EOC_Msk (0x01 << ADC_IE_CH3EOC_Pos) +#define ADC_IE_CH3OVF_Pos 13 +#define ADC_IE_CH3OVF_Msk (0x01 << ADC_IE_CH3OVF_Pos) +#define ADC_IE_CH3HFULL_Pos 14 +#define ADC_IE_CH3HFULL_Msk (0x01 << ADC_IE_CH3HFULL_Pos) +#define ADC_IE_CH3FULL_Pos 15 +#define ADC_IE_CH3FULL_Msk (0x01 << ADC_IE_CH3FULL_Pos) +#define ADC_IE_CH4EOC_Pos 16 +#define ADC_IE_CH4EOC_Msk (0x01 << ADC_IE_CH4EOC_Pos) +#define ADC_IE_CH4OVF_Pos 17 +#define ADC_IE_CH4OVF_Msk (0x01 << ADC_IE_CH4OVF_Pos) +#define ADC_IE_CH4HFULL_Pos 18 +#define ADC_IE_CH4HFULL_Msk (0x01 << ADC_IE_CH4HFULL_Pos) +#define ADC_IE_CH4FULL_Pos 19 +#define ADC_IE_CH4FULL_Msk (0x01 << ADC_IE_CH4FULL_Pos) +#define ADC_IE_CH5EOC_Pos 20 +#define ADC_IE_CH5EOC_Msk (0x01 << ADC_IE_CH5EOC_Pos) +#define ADC_IE_CH5OVF_Pos 21 +#define ADC_IE_CH5OVF_Msk (0x01 << ADC_IE_CH5OVF_Pos) +#define ADC_IE_CH5HFULL_Pos 22 +#define ADC_IE_CH5HFULL_Msk (0x01 << ADC_IE_CH5HFULL_Pos) +#define ADC_IE_CH5FULL_Pos 23 +#define ADC_IE_CH5FULL_Msk (0x01 << ADC_IE_CH5FULL_Pos) +#define ADC_IE_CH6EOC_Pos 24 +#define ADC_IE_CH6EOC_Msk (0x01 << ADC_IE_CH6EOC_Pos) +#define ADC_IE_CH6OVF_Pos 25 +#define ADC_IE_CH6OVF_Msk (0x01 << ADC_IE_CH6OVF_Pos) +#define ADC_IE_CH6HFULL_Pos 26 +#define ADC_IE_CH6HFULL_Msk (0x01 << ADC_IE_CH6HFULL_Pos) +#define ADC_IE_CH6FULL_Pos 27 +#define ADC_IE_CH6FULL_Msk (0x01 << ADC_IE_CH6FULL_Pos) +#define ADC_IE_CH7EOC_Pos 28 +#define ADC_IE_CH7EOC_Msk (0x01 << ADC_IE_CH7EOC_Pos) +#define ADC_IE_CH7OVF_Pos 29 +#define ADC_IE_CH7OVF_Msk (0x01 << ADC_IE_CH7OVF_Pos) +#define ADC_IE_CH7HFULL_Pos 30 +#define ADC_IE_CH7HFULL_Msk (0x01 << ADC_IE_CH7HFULL_Pos) +#define ADC_IE_CH7FULL_Pos 31 +#define ADC_IE_CH7FULL_Msk (0x01u << ADC_IE_CH7FULL_Pos) -#define ADC_IE_CH0EOC_Pos 0 //End Of Convertion -#define ADC_IE_CH0EOC_Msk (0x01 << ADC_IE_CH0EOC_Pos) -#define ADC_IE_CH0OVF_Pos 1 //Overflow -#define ADC_IE_CH0OVF_Msk (0x01 << ADC_IE_CH0OVF_Pos) -#define ADC_IE_CH0HFULL_Pos 2 //FIFO Half Full -#define ADC_IE_CH0HFULL_Msk (0x01 << ADC_IE_CH0HFULL_Pos) -#define ADC_IE_CH0FULL_Pos 3 //FIFO Full -#define ADC_IE_CH0FULL_Msk (0x01 << ADC_IE_CH0FULL_Pos) -#define ADC_IE_CH1EOC_Pos 4 -#define ADC_IE_CH1EOC_Msk (0x01 << ADC_IE_CH1EOC_Pos) -#define ADC_IE_CH1OVF_Pos 5 -#define ADC_IE_CH1OVF_Msk (0x01 << ADC_IE_CH1OVF_Pos) -#define ADC_IE_CH1HFULL_Pos 6 -#define ADC_IE_CH1HFULL_Msk (0x01 << ADC_IE_CH1HFULL_Pos) -#define ADC_IE_CH1FULL_Pos 7 -#define ADC_IE_CH1FULL_Msk (0x01 << ADC_IE_CH1FULL_Pos) -#define ADC_IE_CH2EOC_Pos 8 -#define ADC_IE_CH2EOC_Msk (0x01 << ADC_IE_CH2EOC_Pos) -#define ADC_IE_CH2OVF_Pos 9 -#define ADC_IE_CH2OVF_Msk (0x01 << ADC_IE_CH2OVF_Pos) -#define ADC_IE_CH2HFULL_Pos 10 -#define ADC_IE_CH2HFULL_Msk (0x01 << ADC_IE_CH2HFULL_Pos) -#define ADC_IE_CH2FULL_Pos 11 -#define ADC_IE_CH2FULL_Msk (0x01 << ADC_IE_CH2FULL_Pos) -#define ADC_IE_CH3EOC_Pos 12 -#define ADC_IE_CH3EOC_Msk (0x01 << ADC_IE_CH3EOC_Pos) -#define ADC_IE_CH3OVF_Pos 13 -#define ADC_IE_CH3OVF_Msk (0x01 << ADC_IE_CH3OVF_Pos) -#define ADC_IE_CH3HFULL_Pos 14 -#define ADC_IE_CH3HFULL_Msk (0x01 << ADC_IE_CH3HFULL_Pos) -#define ADC_IE_CH3FULL_Pos 15 -#define ADC_IE_CH3FULL_Msk (0x01 << ADC_IE_CH3FULL_Pos) -#define ADC_IE_CH4EOC_Pos 16 -#define ADC_IE_CH4EOC_Msk (0x01 << ADC_IE_CH4EOC_Pos) -#define ADC_IE_CH4OVF_Pos 17 -#define ADC_IE_CH4OVF_Msk (0x01 << ADC_IE_CH4OVF_Pos) -#define ADC_IE_CH4HFULL_Pos 18 -#define ADC_IE_CH4HFULL_Msk (0x01 << ADC_IE_CH4HFULL_Pos) -#define ADC_IE_CH4FULL_Pos 19 -#define ADC_IE_CH4FULL_Msk (0x01 << ADC_IE_CH4FULL_Pos) -#define ADC_IE_CH5EOC_Pos 20 -#define ADC_IE_CH5EOC_Msk (0x01 << ADC_IE_CH5EOC_Pos) -#define ADC_IE_CH5OVF_Pos 21 -#define ADC_IE_CH5OVF_Msk (0x01 << ADC_IE_CH5OVF_Pos) -#define ADC_IE_CH5HFULL_Pos 22 -#define ADC_IE_CH5HFULL_Msk (0x01 << ADC_IE_CH5HFULL_Pos) -#define ADC_IE_CH5FULL_Pos 23 -#define ADC_IE_CH5FULL_Msk (0x01 << ADC_IE_CH5FULL_Pos) -#define ADC_IE_CH6EOC_Pos 24 -#define ADC_IE_CH6EOC_Msk (0x01 << ADC_IE_CH6EOC_Pos) -#define ADC_IE_CH6OVF_Pos 25 -#define ADC_IE_CH6OVF_Msk (0x01 << ADC_IE_CH6OVF_Pos) -#define ADC_IE_CH6HFULL_Pos 26 -#define ADC_IE_CH6HFULL_Msk (0x01 << ADC_IE_CH6HFULL_Pos) -#define ADC_IE_CH6FULL_Pos 27 -#define ADC_IE_CH6FULL_Msk (0x01 << ADC_IE_CH6FULL_Pos) -#define ADC_IE_CH7EOC_Pos 28 -#define ADC_IE_CH7EOC_Msk (0x01 << ADC_IE_CH7EOC_Pos) -#define ADC_IE_CH7OVF_Pos 29 -#define ADC_IE_CH7OVF_Msk (0x01 << ADC_IE_CH7OVF_Pos) -#define ADC_IE_CH7HFULL_Pos 30 -#define ADC_IE_CH7HFULL_Msk (0x01 << ADC_IE_CH7HFULL_Pos) -#define ADC_IE_CH7FULL_Pos 31 -#define ADC_IE_CH7FULL_Msk (0x01u<< ADC_IE_CH7FULL_Pos) +#define ADC_IF_CH0EOC_Pos 0 //写1清零 +#define ADC_IF_CH0EOC_Msk (0x01 << ADC_IF_CH0EOC_Pos) +#define ADC_IF_CH0OVF_Pos 1 //写1清零 +#define ADC_IF_CH0OVF_Msk (0x01 << ADC_IF_CH0OVF_Pos) +#define ADC_IF_CH0HFULL_Pos 2 //写1清零 +#define ADC_IF_CH0HFULL_Msk (0x01 << ADC_IF_CH0HFULL_Pos) +#define ADC_IF_CH0FULL_Pos 3 //写1清零 +#define ADC_IF_CH0FULL_Msk (0x01 << ADC_IF_CH0FULL_Pos) +#define ADC_IF_CH1EOC_Pos 4 +#define ADC_IF_CH1EOC_Msk (0x01 << ADC_IF_CH1EOC_Pos) +#define ADC_IF_CH1OVF_Pos 5 +#define ADC_IF_CH1OVF_Msk (0x01 << ADC_IF_CH1OVF_Pos) +#define ADC_IF_CH1HFULL_Pos 6 +#define ADC_IF_CH1HFULL_Msk (0x01 << ADC_IF_CH1HFULL_Pos) +#define ADC_IF_CH1FULL_Pos 7 +#define ADC_IF_CH1FULL_Msk (0x01 << ADC_IF_CH1FULL_Pos) +#define ADC_IF_CH2EOC_Pos 8 +#define ADC_IF_CH2EOC_Msk (0x01 << ADC_IF_CH2EOC_Pos) +#define ADC_IF_CH2OVF_Pos 9 +#define ADC_IF_CH2OVF_Msk (0x01 << ADC_IF_CH2OVF_Pos) +#define ADC_IF_CH2HFULL_Pos 10 +#define ADC_IF_CH2HFULL_Msk (0x01 << ADC_IF_CH2HFULL_Pos) +#define ADC_IF_CH2FULL_Pos 11 +#define ADC_IF_CH2FULL_Msk (0x01 << ADC_IF_CH2FULL_Pos) +#define ADC_IF_CH3EOC_Pos 12 +#define ADC_IF_CH3EOC_Msk (0x01 << ADC_IF_CH3EOC_Pos) +#define ADC_IF_CH3OVF_Pos 13 +#define ADC_IF_CH3OVF_Msk (0x01 << ADC_IF_CH3OVF_Pos) +#define ADC_IF_CH3HFULL_Pos 14 +#define ADC_IF_CH3HFULL_Msk (0x01 << ADC_IF_CH3HFULL_Pos) +#define ADC_IF_CH3FULL_Pos 15 +#define ADC_IF_CH3FULL_Msk (0x01 << ADC_IF_CH3FULL_Pos) +#define ADC_IF_CH4EOC_Pos 16 +#define ADC_IF_CH4EOC_Msk (0x01 << ADC_IF_CH4EOC_Pos) +#define ADC_IF_CH4OVF_Pos 17 +#define ADC_IF_CH4OVF_Msk (0x01 << ADC_IF_CH4OVF_Pos) +#define ADC_IF_CH4HFULL_Pos 18 +#define ADC_IF_CH4HFULL_Msk (0x01 << ADC_IF_CH4HFULL_Pos) +#define ADC_IF_CH4FULL_Pos 19 +#define ADC_IF_CH4FULL_Msk (0x01 << ADC_IF_CH4FULL_Pos) +#define ADC_IF_CH5EOC_Pos 20 +#define ADC_IF_CH5EOC_Msk (0x01 << ADC_IF_CH5EOC_Pos) +#define ADC_IF_CH5OVF_Pos 21 +#define ADC_IF_CH5OVF_Msk (0x01 << ADC_IF_CH5OVF_Pos) +#define ADC_IF_CH5HFULL_Pos 22 +#define ADC_IF_CH5HFULL_Msk (0x01 << ADC_IF_CH5HFULL_Pos) +#define ADC_IF_CH5FULL_Pos 23 +#define ADC_IF_CH5FULL_Msk (0x01 << ADC_IF_CH5FULL_Pos) +#define ADC_IF_CH6EOC_Pos 24 +#define ADC_IF_CH6EOC_Msk (0x01 << ADC_IF_CH6EOC_Pos) +#define ADC_IF_CH6OVF_Pos 25 +#define ADC_IF_CH6OVF_Msk (0x01 << ADC_IF_CH6OVF_Pos) +#define ADC_IF_CH6HFULL_Pos 26 +#define ADC_IF_CH6HFULL_Msk (0x01 << ADC_IF_CH6HFULL_Pos) +#define ADC_IF_CH6FULL_Pos 27 +#define ADC_IF_CH6FULL_Msk (0x01 << ADC_IF_CH6FULL_Pos) +#define ADC_IF_CH7EOC_Pos 28 +#define ADC_IF_CH7EOC_Msk (0x01 << ADC_IF_CH7EOC_Pos) +#define ADC_IF_CH7OVF_Pos 29 +#define ADC_IF_CH7OVF_Msk (0x01 << ADC_IF_CH7OVF_Pos) +#define ADC_IF_CH7HFULL_Pos 30 +#define ADC_IF_CH7HFULL_Msk (0x01 << ADC_IF_CH7HFULL_Pos) +#define ADC_IF_CH7FULL_Pos 31 +#define ADC_IF_CH7FULL_Msk (0x01 << ADC_IF_CH7FULL_Pos) -#define ADC_IF_CH0EOC_Pos 0 //写1清零 -#define ADC_IF_CH0EOC_Msk (0x01 << ADC_IF_CH0EOC_Pos) -#define ADC_IF_CH0OVF_Pos 1 //写1清零 -#define ADC_IF_CH0OVF_Msk (0x01 << ADC_IF_CH0OVF_Pos) -#define ADC_IF_CH0HFULL_Pos 2 //写1清零 -#define ADC_IF_CH0HFULL_Msk (0x01 << ADC_IF_CH0HFULL_Pos) -#define ADC_IF_CH0FULL_Pos 3 //写1清零 -#define ADC_IF_CH0FULL_Msk (0x01 << ADC_IF_CH0FULL_Pos) -#define ADC_IF_CH1EOC_Pos 4 -#define ADC_IF_CH1EOC_Msk (0x01 << ADC_IF_CH1EOC_Pos) -#define ADC_IF_CH1OVF_Pos 5 -#define ADC_IF_CH1OVF_Msk (0x01 << ADC_IF_CH1OVF_Pos) -#define ADC_IF_CH1HFULL_Pos 6 -#define ADC_IF_CH1HFULL_Msk (0x01 << ADC_IF_CH1HFULL_Pos) -#define ADC_IF_CH1FULL_Pos 7 -#define ADC_IF_CH1FULL_Msk (0x01 << ADC_IF_CH1FULL_Pos) -#define ADC_IF_CH2EOC_Pos 8 -#define ADC_IF_CH2EOC_Msk (0x01 << ADC_IF_CH2EOC_Pos) -#define ADC_IF_CH2OVF_Pos 9 -#define ADC_IF_CH2OVF_Msk (0x01 << ADC_IF_CH2OVF_Pos) -#define ADC_IF_CH2HFULL_Pos 10 -#define ADC_IF_CH2HFULL_Msk (0x01 << ADC_IF_CH2HFULL_Pos) -#define ADC_IF_CH2FULL_Pos 11 -#define ADC_IF_CH2FULL_Msk (0x01 << ADC_IF_CH2FULL_Pos) -#define ADC_IF_CH3EOC_Pos 12 -#define ADC_IF_CH3EOC_Msk (0x01 << ADC_IF_CH3EOC_Pos) -#define ADC_IF_CH3OVF_Pos 13 -#define ADC_IF_CH3OVF_Msk (0x01 << ADC_IF_CH3OVF_Pos) -#define ADC_IF_CH3HFULL_Pos 14 -#define ADC_IF_CH3HFULL_Msk (0x01 << ADC_IF_CH3HFULL_Pos) -#define ADC_IF_CH3FULL_Pos 15 -#define ADC_IF_CH3FULL_Msk (0x01 << ADC_IF_CH3FULL_Pos) -#define ADC_IF_CH4EOC_Pos 16 -#define ADC_IF_CH4EOC_Msk (0x01 << ADC_IF_CH4EOC_Pos) -#define ADC_IF_CH4OVF_Pos 17 -#define ADC_IF_CH4OVF_Msk (0x01 << ADC_IF_CH4OVF_Pos) -#define ADC_IF_CH4HFULL_Pos 18 -#define ADC_IF_CH4HFULL_Msk (0x01 << ADC_IF_CH4HFULL_Pos) -#define ADC_IF_CH4FULL_Pos 19 -#define ADC_IF_CH4FULL_Msk (0x01 << ADC_IF_CH4FULL_Pos) -#define ADC_IF_CH5EOC_Pos 20 -#define ADC_IF_CH5EOC_Msk (0x01 << ADC_IF_CH5EOC_Pos) -#define ADC_IF_CH5OVF_Pos 21 -#define ADC_IF_CH5OVF_Msk (0x01 << ADC_IF_CH5OVF_Pos) -#define ADC_IF_CH5HFULL_Pos 22 -#define ADC_IF_CH5HFULL_Msk (0x01 << ADC_IF_CH5HFULL_Pos) -#define ADC_IF_CH5FULL_Pos 23 -#define ADC_IF_CH5FULL_Msk (0x01 << ADC_IF_CH5FULL_Pos) -#define ADC_IF_CH6EOC_Pos 24 -#define ADC_IF_CH6EOC_Msk (0x01 << ADC_IF_CH6EOC_Pos) -#define ADC_IF_CH6OVF_Pos 25 -#define ADC_IF_CH6OVF_Msk (0x01 << ADC_IF_CH6OVF_Pos) -#define ADC_IF_CH6HFULL_Pos 26 -#define ADC_IF_CH6HFULL_Msk (0x01 << ADC_IF_CH6HFULL_Pos) -#define ADC_IF_CH6FULL_Pos 27 -#define ADC_IF_CH6FULL_Msk (0x01 << ADC_IF_CH6FULL_Pos) -#define ADC_IF_CH7EOC_Pos 28 -#define ADC_IF_CH7EOC_Msk (0x01 << ADC_IF_CH7EOC_Pos) -#define ADC_IF_CH7OVF_Pos 29 -#define ADC_IF_CH7OVF_Msk (0x01 << ADC_IF_CH7OVF_Pos) -#define ADC_IF_CH7HFULL_Pos 30 -#define ADC_IF_CH7HFULL_Msk (0x01 << ADC_IF_CH7HFULL_Pos) -#define ADC_IF_CH7FULL_Pos 31 -#define ADC_IF_CH7FULL_Msk (0x01 << ADC_IF_CH7FULL_Pos) +#define ADC_STAT_EOC_Pos 0 //写1清零 +#define ADC_STAT_EOC_Msk (0x01 << ADC_STAT_EOC_Pos) +#define ADC_STAT_OVF_Pos 1 //读数据寄存器清除 +#define ADC_STAT_OVF_Msk (0x01 << ADC_STAT_OVF_Pos) +#define ADC_STAT_HFULL_Pos 2 +#define ADC_STAT_HFULL_Msk (0x01 << ADC_STAT_HFULL_Pos) +#define ADC_STAT_FULL_Pos 3 +#define ADC_STAT_FULL_Msk (0x01 << ADC_STAT_FULL_Pos) +#define ADC_STAT_EMPTY_Pos 4 +#define ADC_STAT_EMPTY_Msk (0x01 << ADC_STAT_EMPTY_Pos) -#define ADC_STAT_EOC_Pos 0 //写1清零 -#define ADC_STAT_EOC_Msk (0x01 << ADC_STAT_EOC_Pos) -#define ADC_STAT_OVF_Pos 1 //读数据寄存器清除 -#define ADC_STAT_OVF_Msk (0x01 << ADC_STAT_OVF_Pos) -#define ADC_STAT_HFULL_Pos 2 -#define ADC_STAT_HFULL_Msk (0x01 << ADC_STAT_HFULL_Pos) -#define ADC_STAT_FULL_Pos 3 -#define ADC_STAT_FULL_Msk (0x01 << ADC_STAT_FULL_Pos) -#define ADC_STAT_EMPTY_Pos 4 -#define ADC_STAT_EMPTY_Msk (0x01 << ADC_STAT_EMPTY_Pos) +#define ADC_CTRL1_RIN_Pos 4 //输入阻抗:0 无穷大 1 105K 2 90K 3 75K 4 60K 5 45K 6 30K 7 15K +#define ADC_CTRL1_RIN_Msk (0x07 << ADC_CTRL1_RIN_Pos) -#define ADC_CTRL1_RIN_Pos 4 //输入阻抗:0 无穷大 1 105K 2 90K 3 75K 4 60K 5 45K 6 30K 7 15K -#define ADC_CTRL1_RIN_Msk (0x07 << ADC_CTRL1_RIN_Pos) - -#define ADC_CTRL2_RESET_Pos 0 //数字电路复位 -#define ADC_CTRL2_RESET_Msk (0x01 << ADC_CTRL2_RESET_Pos) -#define ADC_CTRL2_ADCEVCM_Pos 1 //ADC External VCM,ADC与PGA输出共模电平选择 -#define ADC_CTRL2_ADCEVCM_Msk (0x01 << ADC_CTRL2_ADCEVCM_Pos) -#define ADC_CTRL2_PGAIVCM_Pos 2 //PGA Internal VCM,PGA输入共模电平选择 -#define ADC_CTRL2_PGAIVCM_Msk (0x01 << ADC_CTRL2_PGAIVCM_Pos) -#define ADC_CTRL2_PGAGAIN_Pos 3 //0 25.1dB 1 21.6dB 2 11.1dB 3 3.5dB 4 0dB(1.8V) 5 -2.9dB 6 -5.3dB -#define ADC_CTRL2_PGAGAIN_Msk (0x07 << ADC_CTRL2_PGAGAIN_Pos) -#define ADC_CTRL2_REFPOUT_Pos 23 //1 ADC 内部 1.2V REFP电压输出到外部REFP引脚,用于测量,或在需要1.2V外部REFP时节省成本 +#define ADC_CTRL2_RESET_Pos 0 //数字电路复位 +#define ADC_CTRL2_RESET_Msk (0x01 << ADC_CTRL2_RESET_Pos) +#define ADC_CTRL2_ADCEVCM_Pos 1 //ADC External VCM,ADC与PGA输出共模电平选择 +#define ADC_CTRL2_ADCEVCM_Msk (0x01 << ADC_CTRL2_ADCEVCM_Pos) +#define ADC_CTRL2_PGAIVCM_Pos 2 //PGA Internal VCM,PGA输入共模电平选择 +#define ADC_CTRL2_PGAIVCM_Msk (0x01 << ADC_CTRL2_PGAIVCM_Pos) +#define ADC_CTRL2_PGAGAIN_Pos 3 //0 25.1dB 1 21.6dB 2 11.1dB 3 3.5dB 4 0dB(1.8V) 5 -2.9dB 6 -5.3dB +#define ADC_CTRL2_PGAGAIN_Msk (0x07 << ADC_CTRL2_PGAGAIN_Pos) +#define ADC_CTRL2_REFPOUT_Pos 23 //1 ADC 内部 1.2V REFP电压输出到外部REFP引脚,用于测量,或在需要1.2V外部REFP时节省成本 #define ADC_CTRL2_REFPOUT_Msk (0x01 << ADC_CTRL2_REFPOUT_Pos -#define ADC_CTRL2_CLKDIV_Pos 24 //时钟分频,只在时钟源为HRC时有效 -#define ADC_CTRL2_CLKDIV_Msk (0x1F << ADC_CTRL2_CLKDIV_Pos) -#define ADC_CTRL2_PGAVCM_Pos 29 -#define ADC_CTRL2_PGAVCM_Msk (0x07u<< ADC_CTRL2_PGAVCM_Pos) +#define ADC_CTRL2_CLKDIV_Pos 24 //时钟分频,只在时钟源为HRC时有效 +#define ADC_CTRL2_CLKDIV_Msk (0x1F << ADC_CTRL2_CLKDIV_Pos) +#define ADC_CTRL2_PGAVCM_Pos 29 +#define ADC_CTRL2_PGAVCM_Msk (0x07u << ADC_CTRL2_PGAVCM_Pos) -#define ADC_CALIBSET_OFFSET_Pos 0 -#define ADC_CALIBSET_OFFSET_Msk (0x1FF<< ADC_CALIBSET_OFFSET_Pos) -#define ADC_CALIBSET_K_Pos 16 -#define ADC_CALIBSET_K_Msk (0x1FF<< ADC_CALIBSET_K_Pos) +#define ADC_CALIBSET_OFFSET_Pos 0 +#define ADC_CALIBSET_OFFSET_Msk (0x1FF << ADC_CALIBSET_OFFSET_Pos) +#define ADC_CALIBSET_K_Pos 16 +#define ADC_CALIBSET_K_Msk (0x1FF << ADC_CALIBSET_K_Pos) -#define ADC_CALIBEN_OFFSET_Pos 0 -#define ADC_CALIBEN_OFFSET_Msk (0x01 << ADC_CALIBEN_OFFSET_Pos) -#define ADC_CALIBEN_K_Pos 1 -#define ADC_CALIBEN_K_Msk (0x01 << ADC_CALIBEN_K_Pos) +#define ADC_CALIBEN_OFFSET_Pos 0 +#define ADC_CALIBEN_OFFSET_Msk (0x01 << ADC_CALIBEN_OFFSET_Pos) +#define ADC_CALIBEN_K_Pos 1 +#define ADC_CALIBEN_K_Msk (0x01 << ADC_CALIBEN_K_Pos) +typedef struct +{ + __IO uint32_t MODE; //0 普通模式,A、B两路输出互相独立 + //1 互补模式,A、B两路输出都由PERA、HIGHA控制,B路输出与A路输出极性相反,且DZA、DZB控制A、B路输出上升沿推迟时间 + //2 单次模式,同普通模式,但一个周期后自动停止 + //3 对称模式,A、B两路输出互相独立,以两个计数周期产生一个波形输出周期,分辨率提升一倍、频率降低一倍 + //4 对称互补模式,对称模式和互补模式的综合 + __IO uint32_t PERA; //[15:0] 周期 + __IO uint32_t HIGHA; //[15:0] 高电平持续时长 -typedef struct { - __IO uint32_t MODE; //0 普通模式,A、B两路输出互相独立 - //1 互补模式,A、B两路输出都由PERA、HIGHA控制,B路输出与A路输出极性相反,且DZA、DZB控制A、B路输出上升沿推迟时间 - //2 单次模式,同普通模式,但一个周期后自动停止 - //3 对称模式,A、B两路输出互相独立,以两个计数周期产生一个波形输出周期,分辨率提升一倍、频率降低一倍 - //4 对称互补模式,对称模式和互补模式的综合 - - __IO uint32_t PERA; //[15:0] 周期 - - __IO uint32_t HIGHA; //[15:0] 高电平持续时长 - - __IO uint32_t DZA; //[9:0] 死区,即上升沿推迟时长,必须小于HIGHA - - __IO uint32_t PERB; - - __IO uint32_t HIGHB; - - __IO uint32_t DZB; - - __IO uint32_t INIOUT; //Init Output level,初始输出电平 + __IO uint32_t DZA; //[9:0] 死区,即上升沿推迟时长,必须小于HIGHA + + __IO uint32_t PERB; + + __IO uint32_t HIGHB; + + __IO uint32_t DZB; + + __IO uint32_t INIOUT; //Init Output level,初始输出电平 } PWM_TypeDef; +#define PWM_INIOUT_PWMA_Pos 0 +#define PWM_INIOUT_PWMA_Msk (0x01 << PWM_INIOUT_PWMA_Pos) +#define PWM_INIOUT_PWMB_Pos 1 +#define PWM_INIOUT_PWMB_Msk (0x01 << PWM_INIOUT_PWMB_Pos) -#define PWM_INIOUT_PWMA_Pos 0 -#define PWM_INIOUT_PWMA_Msk (0x01 << PWM_INIOUT_PWMA_Pos) -#define PWM_INIOUT_PWMB_Pos 1 -#define PWM_INIOUT_PWMB_Msk (0x01 << PWM_INIOUT_PWMB_Pos) +typedef struct +{ + __IO uint32_t FORCEH; - -typedef struct { - __IO uint32_t FORCEH; - __IO uint32_t ADTRG0A; __IO uint32_t ADTRG0B; - + __IO uint32_t ADTRG1A; __IO uint32_t ADTRG1B; - + __IO uint32_t ADTRG2A; __IO uint32_t ADTRG2B; - + __IO uint32_t ADTRG3A; __IO uint32_t ADTRG3B; - + __IO uint32_t ADTRG4A; __IO uint32_t ADTRG4B; - + __IO uint32_t ADTRG5A; - __IO uint32_t ADTRG5B; - - uint32_t RESERVED[3]; - - __IO uint32_t HALT; //刹车控制 - - __IO uint32_t CHEN; - - __IO uint32_t IE; - - __IO uint32_t IF; - - __IO uint32_t IM; //Interrupt Mask - - __IO uint32_t IRS; //Interrupt Raw Stat + __IO uint32_t ADTRG5B; + + uint32_t RESERVED[3]; + + __IO uint32_t HALT; //刹车控制 + + __IO uint32_t CHEN; + + __IO uint32_t IE; + + __IO uint32_t IF; + + __IO uint32_t IM; //Interrupt Mask + + __IO uint32_t IRS; //Interrupt Raw Stat } PWMG_TypeDef; +#define PWMG_FORCEH_PWM0_Pos 0 +#define PWMG_FORCEH_PWM0_Msk (0x01 << PWMG_FORCEH_PWM0_Pos) +#define PWMG_FORCEH_PWM1_Pos 1 +#define PWMG_FORCEH_PWM1_Msk (0x01 << PWMG_FORCEH_PWM1_Pos) +#define PWMG_FORCEH_PWM2_Pos 2 +#define PWMG_FORCEH_PWM2_Msk (0x01 << PWMG_FORCEH_PWM2_Pos) +#define PWMG_FORCEH_PWM3_Pos 3 +#define PWMG_FORCEH_PWM3_Msk (0x01 << PWMG_FORCEH_PWM3_Pos) +#define PWMG_FORCEH_PWM4_Pos 4 +#define PWMG_FORCEH_PWM4_Msk (0x01 << PWMG_FORCEH_PWM4_Pos) +#define PWMG_FORCEH_PWM5_Pos 5 +#define PWMG_FORCEH_PWM5_Msk (0x01 << PWMG_FORCEH_PWM5_Pos) -#define PWMG_FORCEH_PWM0_Pos 0 -#define PWMG_FORCEH_PWM0_Msk (0x01 << PWMG_FORCEH_PWM0_Pos) -#define PWMG_FORCEH_PWM1_Pos 1 -#define PWMG_FORCEH_PWM1_Msk (0x01 << PWMG_FORCEH_PWM1_Pos) -#define PWMG_FORCEH_PWM2_Pos 2 -#define PWMG_FORCEH_PWM2_Msk (0x01 << PWMG_FORCEH_PWM2_Pos) -#define PWMG_FORCEH_PWM3_Pos 3 -#define PWMG_FORCEH_PWM3_Msk (0x01 << PWMG_FORCEH_PWM3_Pos) -#define PWMG_FORCEH_PWM4_Pos 4 -#define PWMG_FORCEH_PWM4_Msk (0x01 << PWMG_FORCEH_PWM4_Pos) -#define PWMG_FORCEH_PWM5_Pos 5 -#define PWMG_FORCEH_PWM5_Msk (0x01 << PWMG_FORCEH_PWM5_Pos) +#define PWMG_ADTRG_VALUE_Pos 0 +#define PWMG_ADTRG_VALUE_Msk (0xFFFF << PWMG_ADTRG0A_VALUE_Pos) +#define PWMG_ADTRG_EVEN_Pos 16 //1 偶数周期生效 0 奇数周期生效 +#define PWMG_ADTRG_EVEN_Msk (0x01 << PWMG_ADTRG0A_EVEN_Pos) +#define PWMG_ADTRG_EN_Pos 17 +#define PWMG_ADTRG_EN_Msk (0x01 << PWMG_ADTRG0A_EN_Pos) -#define PWMG_ADTRG_VALUE_Pos 0 -#define PWMG_ADTRG_VALUE_Msk (0xFFFF << PWMG_ADTRG0A_VALUE_Pos) -#define PWMG_ADTRG_EVEN_Pos 16 //1 偶数周期生效 0 奇数周期生效 -#define PWMG_ADTRG_EVEN_Msk (0x01 << PWMG_ADTRG0A_EVEN_Pos) -#define PWMG_ADTRG_EN_Pos 17 -#define PWMG_ADTRG_EN_Msk (0x01 << PWMG_ADTRG0A_EN_Pos) +#define PWMG_HALT_EN_Pos 0 +#define PWMG_HALT_EN_Msk (0x01 << PWMG_HALT_EN_Pos) +#define PWMG_HALT_PWM0_Pos 1 +#define PWMG_HALT_PWM0_Msk (0x01 << PWMG_HALT_PWM0_Pos) +#define PWMG_HALT_PWM1_Pos 2 +#define PWMG_HALT_PWM1_Msk (0x01 << PWMG_HALT_PWM1_Pos) +#define PWMG_HALT_PWM2_Pos 3 +#define PWMG_HALT_PWM2_Msk (0x01 << PWMG_HALT_PWM2_Pos) +#define PWMG_HALT_PWM3_Pos 4 +#define PWMG_HALT_PWM3_Msk (0x01 << PWMG_HALT_PWM3_Pos) +#define PWMG_HALT_PWM4_Pos 5 +#define PWMG_HALT_PWM4_Msk (0x01 << PWMG_HALT_PWM4_Pos) +#define PWMG_HALT_PWM5_Pos 6 +#define PWMG_HALT_PWM5_Msk (0x01 << PWMG_HALT_PWM5_Pos) +#define PWMG_HALT_STOPCNT_Pos 7 //1 刹车时将PWM计数器清零,停止计数 0 刹车时,PWM计数器继续计数 +#define PWMG_HALT_STOPCNT_Msk (0x01 << PWMG_HALT_STOPCNT_Pos) +#define PWMG_HALT_INLVL_Pos 8 //1 刹车输入高电平有效 +#define PWMG_HALT_INLVL_Msk (0x01 << PWMG_HALT_INLVL_Pos) +#define PWMG_HALT_OUTLVL_Pos 9 //1 刹车过程中输出高电平 +#define PWMG_HALT_OUTLVL_Msk (0x01 << PWMG_HALT_OUTLVL_Pos) +#define PWMG_HALT_STAT_Pos 10 //1 正在刹车 +#define PWMG_HALT_STAT_Msk (0x01 << PWMG_HALT_STAT_Pos) -#define PWMG_HALT_EN_Pos 0 -#define PWMG_HALT_EN_Msk (0x01 << PWMG_HALT_EN_Pos) -#define PWMG_HALT_PWM0_Pos 1 -#define PWMG_HALT_PWM0_Msk (0x01 << PWMG_HALT_PWM0_Pos) -#define PWMG_HALT_PWM1_Pos 2 -#define PWMG_HALT_PWM1_Msk (0x01 << PWMG_HALT_PWM1_Pos) -#define PWMG_HALT_PWM2_Pos 3 -#define PWMG_HALT_PWM2_Msk (0x01 << PWMG_HALT_PWM2_Pos) -#define PWMG_HALT_PWM3_Pos 4 -#define PWMG_HALT_PWM3_Msk (0x01 << PWMG_HALT_PWM3_Pos) -#define PWMG_HALT_PWM4_Pos 5 -#define PWMG_HALT_PWM4_Msk (0x01 << PWMG_HALT_PWM4_Pos) -#define PWMG_HALT_PWM5_Pos 6 -#define PWMG_HALT_PWM5_Msk (0x01 << PWMG_HALT_PWM5_Pos) -#define PWMG_HALT_STOPCNT_Pos 7 //1 刹车时将PWM计数器清零,停止计数 0 刹车时,PWM计数器继续计数 -#define PWMG_HALT_STOPCNT_Msk (0x01 << PWMG_HALT_STOPCNT_Pos) -#define PWMG_HALT_INLVL_Pos 8 //1 刹车输入高电平有效 -#define PWMG_HALT_INLVL_Msk (0x01 << PWMG_HALT_INLVL_Pos) -#define PWMG_HALT_OUTLVL_Pos 9 //1 刹车过程中输出高电平 -#define PWMG_HALT_OUTLVL_Msk (0x01 << PWMG_HALT_OUTLVL_Pos) -#define PWMG_HALT_STAT_Pos 10 //1 正在刹车 -#define PWMG_HALT_STAT_Msk (0x01 << PWMG_HALT_STAT_Pos) +#define PWMG_CHEN_PWM0A_Pos 0 +#define PWMG_CHEN_PWM0A_Msk (0x01 << PWMG_CHEN_PWM0A_Pos) +#define PWMG_CHEN_PWM0B_Pos 1 +#define PWMG_CHEN_PWM0B_Msk (0x01 << PWMG_CHEN_PWM0B_Pos) +#define PWMG_CHEN_PWM1A_Pos 2 +#define PWMG_CHEN_PWM1A_Msk (0x01 << PWMG_CHEN_PWM1A_Pos) +#define PWMG_CHEN_PWM1B_Pos 3 +#define PWMG_CHEN_PWM1B_Msk (0x01 << PWMG_CHEN_PWM1B_Pos) +#define PWMG_CHEN_PWM2A_Pos 4 +#define PWMG_CHEN_PWM2A_Msk (0x01 << PWMG_CHEN_PWM2A_Pos) +#define PWMG_CHEN_PWM2B_Pos 5 +#define PWMG_CHEN_PWM2B_Msk (0x01 << PWMG_CHEN_PWM2B_Pos) +#define PWMG_CHEN_PWM3A_Pos 6 +#define PWMG_CHEN_PWM3A_Msk (0x01 << PWMG_CHEN_PWM3A_Pos) +#define PWMG_CHEN_PWM3B_Pos 7 +#define PWMG_CHEN_PWM3B_Msk (0x01 << PWMG_CHEN_PWM3B_Pos) +#define PWMG_CHEN_PWM4A_Pos 8 +#define PWMG_CHEN_PWM4A_Msk (0x01 << PWMG_CHEN_PWM4A_Pos) +#define PWMG_CHEN_PWM4B_Pos 9 +#define PWMG_CHEN_PWM4B_Msk (0x01 << PWMG_CHEN_PWM4B_Pos) +#define PWMG_CHEN_PWM5A_Pos 10 +#define PWMG_CHEN_PWM5A_Msk (0x01 << PWMG_CHEN_PWM5A_Pos) +#define PWMG_CHEN_PWM5B_Pos 11 +#define PWMG_CHEN_PWM5B_Msk (0x01 << PWMG_CHEN_PWM5B_Pos) -#define PWMG_CHEN_PWM0A_Pos 0 -#define PWMG_CHEN_PWM0A_Msk (0x01 << PWMG_CHEN_PWM0A_Pos) -#define PWMG_CHEN_PWM0B_Pos 1 -#define PWMG_CHEN_PWM0B_Msk (0x01 << PWMG_CHEN_PWM0B_Pos) -#define PWMG_CHEN_PWM1A_Pos 2 -#define PWMG_CHEN_PWM1A_Msk (0x01 << PWMG_CHEN_PWM1A_Pos) -#define PWMG_CHEN_PWM1B_Pos 3 -#define PWMG_CHEN_PWM1B_Msk (0x01 << PWMG_CHEN_PWM1B_Pos) -#define PWMG_CHEN_PWM2A_Pos 4 -#define PWMG_CHEN_PWM2A_Msk (0x01 << PWMG_CHEN_PWM2A_Pos) -#define PWMG_CHEN_PWM2B_Pos 5 -#define PWMG_CHEN_PWM2B_Msk (0x01 << PWMG_CHEN_PWM2B_Pos) -#define PWMG_CHEN_PWM3A_Pos 6 -#define PWMG_CHEN_PWM3A_Msk (0x01 << PWMG_CHEN_PWM3A_Pos) -#define PWMG_CHEN_PWM3B_Pos 7 -#define PWMG_CHEN_PWM3B_Msk (0x01 << PWMG_CHEN_PWM3B_Pos) -#define PWMG_CHEN_PWM4A_Pos 8 -#define PWMG_CHEN_PWM4A_Msk (0x01 << PWMG_CHEN_PWM4A_Pos) -#define PWMG_CHEN_PWM4B_Pos 9 -#define PWMG_CHEN_PWM4B_Msk (0x01 << PWMG_CHEN_PWM4B_Pos) -#define PWMG_CHEN_PWM5A_Pos 10 -#define PWMG_CHEN_PWM5A_Msk (0x01 << PWMG_CHEN_PWM5A_Pos) -#define PWMG_CHEN_PWM5B_Pos 11 -#define PWMG_CHEN_PWM5B_Msk (0x01 << PWMG_CHEN_PWM5B_Pos) +#define PWMG_IE_NEWP0A_Pos 0 +#define PWMG_IE_NEWP0A_Msk (0x01 << PWMG_IE_NEWP0A_Pos) +#define PWMG_IE_NEWP0B_Pos 1 +#define PWMG_IE_NEWP0B_Msk (0x01 << PWMG_IE_NEWP0B_Pos) +#define PWMG_IE_NEWP1A_Pos 2 +#define PWMG_IE_NEWP1A_Msk (0x01 << PWMG_IE_NEWP1A_Pos) +#define PWMG_IE_NEWP1B_Pos 3 +#define PWMG_IE_NEWP1B_Msk (0x01 << PWMG_IE_NEWP1B_Pos) +#define PWMG_IE_NEWP2A_Pos 4 +#define PWMG_IE_NEWP2A_Msk (0x01 << PWMG_IE_NEWP2A_Pos) +#define PWMG_IE_NEWP2B_Pos 5 +#define PWMG_IE_NEWP2B_Msk (0x01 << PWMG_IE_NEWP2B_Pos) +#define PWMG_IE_NEWP3A_Pos 6 +#define PWMG_IE_NEWP3A_Msk (0x01 << PWMG_IE_NEWP3A_Pos) +#define PWMG_IE_NEWP3B_Pos 7 +#define PWMG_IE_NEWP3B_Msk (0x01 << PWMG_IE_NEWP3B_Pos) +#define PWMG_IE_NEWP4A_Pos 8 +#define PWMG_IE_NEWP4A_Msk (0x01 << PWMG_IE_NEWP4A_Pos) +#define PWMG_IE_NEWP4B_Pos 9 +#define PWMG_IE_NEWP4B_Msk (0x01 << PWMG_IE_NEWP4B_Pos) +#define PWMG_IE_NEWP5A_Pos 10 +#define PWMG_IE_NEWP5A_Msk (0x01 << PWMG_IE_NEWP5A_Pos) +#define PWMG_IE_NEWP5B_Pos 11 +#define PWMG_IE_NEWP5B_Msk (0x01 << PWMG_IE_NEWP5B_Pos) +#define PWMG_IE_HEND0A_Pos 12 +#define PWMG_IE_HEND0A_Msk (0x01 << PWMG_IE_HEND0A_Pos) +#define PWMG_IE_HEND0B_Pos 13 +#define PWMG_IE_HEND0B_Msk (0x01 << PWMG_IE_HEND0B_Pos) +#define PWMG_IE_HEND1A_Pos 14 +#define PWMG_IE_HEND1A_Msk (0x01 << PWMG_IE_HEND1A_Pos) +#define PWMG_IE_HEND1B_Pos 15 +#define PWMG_IE_HEND1B_Msk (0x01 << PWMG_IE_HEND1B_Pos) +#define PWMG_IE_HEND2A_Pos 16 +#define PWMG_IE_HEND2A_Msk (0x01 << PWMG_IE_HEND2A_Pos) +#define PWMG_IE_HEND2B_Pos 17 +#define PWMG_IE_HEND2B_Msk (0x01 << PWMG_IE_HEND2B_Pos) +#define PWMG_IE_HEND3A_Pos 18 +#define PWMG_IE_HEND3A_Msk (0x01 << PWMG_IE_HEND3A_Pos) +#define PWMG_IE_HEND3B_Pos 19 +#define PWMG_IE_HEND3B_Msk (0x01 << PWMG_IE_HEND3B_Pos) +#define PWMG_IE_HEND4A_Pos 20 +#define PWMG_IE_HEND4A_Msk (0x01 << PWMG_IE_HEND4A_Pos) +#define PWMG_IE_HEND4B_Pos 21 +#define PWMG_IE_HEND4B_Msk (0x01 << PWMG_IE_HEND4B_Pos) +#define PWMG_IE_HEND5A_Pos 22 +#define PWMG_IE_HEND5A_Msk (0x01 << PWMG_IE_HEND5A_Pos) +#define PWMG_IE_HEND5B_Pos 23 +#define PWMG_IE_HEND5B_Msk (0x01 << PWMG_IE_HEND5B_Pos) +#define PWMG_IE_HALT_Pos 24 +#define PWMG_IE_HALT_Msk (0x01 << PWMG_IE_HALT_Pos) +#define PWMG_IF_NEWP0A_Pos 0 +#define PWMG_IF_NEWP0A_Msk (0x01 << PWMG_IF_NEWP0A_Pos) +#define PWMG_IF_NEWP0B_Pos 1 +#define PWMG_IF_NEWP0B_Msk (0x01 << PWMG_IF_NEWP0B_Pos) +#define PWMG_IF_NEWP1A_Pos 2 +#define PWMG_IF_NEWP1A_Msk (0x01 << PWMG_IF_NEWP1A_Pos) +#define PWMG_IF_NEWP1B_Pos 3 +#define PWMG_IF_NEWP1B_Msk (0x01 << PWMG_IF_NEWP1B_Pos) +#define PWMG_IF_NEWP2A_Pos 4 +#define PWMG_IF_NEWP2A_Msk (0x01 << PWMG_IF_NEWP2A_Pos) +#define PWMG_IF_NEWP2B_Pos 5 +#define PWMG_IF_NEWP2B_Msk (0x01 << PWMG_IF_NEWP2B_Pos) +#define PWMG_IF_NEWP3A_Pos 6 +#define PWMG_IF_NEWP3A_Msk (0x01 << PWMG_IF_NEWP3A_Pos) +#define PWMG_IF_NEWP3B_Pos 7 +#define PWMG_IF_NEWP3B_Msk (0x01 << PWMG_IF_NEWP3B_Pos) +#define PWMG_IF_NEWP4A_Pos 8 +#define PWMG_IF_NEWP4A_Msk (0x01 << PWMG_IF_NEWP4A_Pos) +#define PWMG_IF_NEWP4B_Pos 9 +#define PWMG_IF_NEWP4B_Msk (0x01 << PWMG_IF_NEWP4B_Pos) +#define PWMG_IF_NEWP5A_Pos 10 +#define PWMG_IF_NEWP5A_Msk (0x01 << PWMG_IF_NEWP5A_Pos) +#define PWMG_IF_NEWP5B_Pos 11 +#define PWMG_IF_NEWP5B_Msk (0x01 << PWMG_IF_NEWP5B_Pos) +#define PWMG_IF_HEND0A_Pos 12 +#define PWMG_IF_HEND0A_Msk (0x01 << PWMG_IF_HEND0A_Pos) +#define PWMG_IF_HEND0B_Pos 13 +#define PWMG_IF_HEND0B_Msk (0x01 << PWMG_IF_HEND0B_Pos) +#define PWMG_IF_HEND1A_Pos 14 +#define PWMG_IF_HEND1A_Msk (0x01 << PWMG_IF_HEND1A_Pos) +#define PWMG_IF_HEND1B_Pos 15 +#define PWMG_IF_HEND1B_Msk (0x01 << PWMG_IF_HEND1B_Pos) +#define PWMG_IF_HEND2A_Pos 16 +#define PWMG_IF_HEND2A_Msk (0x01 << PWMG_IF_HEND2A_Pos) +#define PWMG_IF_HEND2B_Pos 17 +#define PWMG_IF_HEND2B_Msk (0x01 << PWMG_IF_HEND2B_Pos) +#define PWMG_IF_HEND3A_Pos 18 +#define PWMG_IF_HEND3A_Msk (0x01 << PWMG_IF_HEND3A_Pos) +#define PWMG_IF_HEND3B_Pos 19 +#define PWMG_IF_HEND3B_Msk (0x01 << PWMG_IF_HEND3B_Pos) +#define PWMG_IF_HEND4A_Pos 20 +#define PWMG_IF_HEND4A_Msk (0x01 << PWMG_IF_HEND4A_Pos) +#define PWMG_IF_HEND4B_Pos 21 +#define PWMG_IF_HEND4B_Msk (0x01 << PWMG_IF_HEND4B_Pos) +#define PWMG_IF_HEND5A_Pos 22 +#define PWMG_IF_HEND5A_Msk (0x01 << PWMG_IF_HEND5A_Pos) +#define PWMG_IF_HEND5B_Pos 23 +#define PWMG_IF_HEND5B_Msk (0x01 << PWMG_IF_HEND5B_Pos) +#define PWMG_IF_HALT_Pos 24 +#define PWMG_IF_HALT_Msk (0x01 << PWMG_IF_HALT_Pos) -#define PWMG_IE_NEWP0A_Pos 0 -#define PWMG_IE_NEWP0A_Msk (0x01 << PWMG_IE_NEWP0A_Pos) -#define PWMG_IE_NEWP0B_Pos 1 -#define PWMG_IE_NEWP0B_Msk (0x01 << PWMG_IE_NEWP0B_Pos) -#define PWMG_IE_NEWP1A_Pos 2 -#define PWMG_IE_NEWP1A_Msk (0x01 << PWMG_IE_NEWP1A_Pos) -#define PWMG_IE_NEWP1B_Pos 3 -#define PWMG_IE_NEWP1B_Msk (0x01 << PWMG_IE_NEWP1B_Pos) -#define PWMG_IE_NEWP2A_Pos 4 -#define PWMG_IE_NEWP2A_Msk (0x01 << PWMG_IE_NEWP2A_Pos) -#define PWMG_IE_NEWP2B_Pos 5 -#define PWMG_IE_NEWP2B_Msk (0x01 << PWMG_IE_NEWP2B_Pos) -#define PWMG_IE_NEWP3A_Pos 6 -#define PWMG_IE_NEWP3A_Msk (0x01 << PWMG_IE_NEWP3A_Pos) -#define PWMG_IE_NEWP3B_Pos 7 -#define PWMG_IE_NEWP3B_Msk (0x01 << PWMG_IE_NEWP3B_Pos) -#define PWMG_IE_NEWP4A_Pos 8 -#define PWMG_IE_NEWP4A_Msk (0x01 << PWMG_IE_NEWP4A_Pos) -#define PWMG_IE_NEWP4B_Pos 9 -#define PWMG_IE_NEWP4B_Msk (0x01 << PWMG_IE_NEWP4B_Pos) -#define PWMG_IE_NEWP5A_Pos 10 -#define PWMG_IE_NEWP5A_Msk (0x01 << PWMG_IE_NEWP5A_Pos) -#define PWMG_IE_NEWP5B_Pos 11 -#define PWMG_IE_NEWP5B_Msk (0x01 << PWMG_IE_NEWP5B_Pos) -#define PWMG_IE_HEND0A_Pos 12 -#define PWMG_IE_HEND0A_Msk (0x01 << PWMG_IE_HEND0A_Pos) -#define PWMG_IE_HEND0B_Pos 13 -#define PWMG_IE_HEND0B_Msk (0x01 << PWMG_IE_HEND0B_Pos) -#define PWMG_IE_HEND1A_Pos 14 -#define PWMG_IE_HEND1A_Msk (0x01 << PWMG_IE_HEND1A_Pos) -#define PWMG_IE_HEND1B_Pos 15 -#define PWMG_IE_HEND1B_Msk (0x01 << PWMG_IE_HEND1B_Pos) -#define PWMG_IE_HEND2A_Pos 16 -#define PWMG_IE_HEND2A_Msk (0x01 << PWMG_IE_HEND2A_Pos) -#define PWMG_IE_HEND2B_Pos 17 -#define PWMG_IE_HEND2B_Msk (0x01 << PWMG_IE_HEND2B_Pos) -#define PWMG_IE_HEND3A_Pos 18 -#define PWMG_IE_HEND3A_Msk (0x01 << PWMG_IE_HEND3A_Pos) -#define PWMG_IE_HEND3B_Pos 19 -#define PWMG_IE_HEND3B_Msk (0x01 << PWMG_IE_HEND3B_Pos) -#define PWMG_IE_HEND4A_Pos 20 -#define PWMG_IE_HEND4A_Msk (0x01 << PWMG_IE_HEND4A_Pos) -#define PWMG_IE_HEND4B_Pos 21 -#define PWMG_IE_HEND4B_Msk (0x01 << PWMG_IE_HEND4B_Pos) -#define PWMG_IE_HEND5A_Pos 22 -#define PWMG_IE_HEND5A_Msk (0x01 << PWMG_IE_HEND5A_Pos) -#define PWMG_IE_HEND5B_Pos 23 -#define PWMG_IE_HEND5B_Msk (0x01 << PWMG_IE_HEND5B_Pos) -#define PWMG_IE_HALT_Pos 24 -#define PWMG_IE_HALT_Msk (0x01 << PWMG_IE_HALT_Pos) +#define PWMG_IM_NEWP0A_Pos 0 //Interrupt Mask +#define PWMG_IM_NEWP0A_Msk (0x01 << PWMG_IM_NEWP0A_Pos) +#define PWMG_IM_NEWP0B_Pos 1 +#define PWMG_IM_NEWP0B_Msk (0x01 << PWMG_IM_NEWP0B_Pos) +#define PWMG_IM_NEWP1A_Pos 2 +#define PWMG_IM_NEWP1A_Msk (0x01 << PWMG_IM_NEWP1A_Pos) +#define PWMG_IM_NEWP1B_Pos 3 +#define PWMG_IM_NEWP1B_Msk (0x01 << PWMG_IM_NEWP1B_Pos) +#define PWMG_IM_NEWP2A_Pos 4 +#define PWMG_IM_NEWP2A_Msk (0x01 << PWMG_IM_NEWP2A_Pos) +#define PWMG_IM_NEWP2B_Pos 5 +#define PWMG_IM_NEWP2B_Msk (0x01 << PWMG_IM_NEWP2B_Pos) +#define PWMG_IM_NEWP3A_Pos 6 +#define PWMG_IM_NEWP3A_Msk (0x01 << PWMG_IM_NEWP3A_Pos) +#define PWMG_IM_NEWP3B_Pos 7 +#define PWMG_IM_NEWP3B_Msk (0x01 << PWMG_IM_NEWP3B_Pos) +#define PWMG_IM_NEWP4A_Pos 8 +#define PWMG_IM_NEWP4A_Msk (0x01 << PWMG_IM_NEWP4A_Pos) +#define PWMG_IM_NEWP4B_Pos 9 +#define PWMG_IM_NEWP4B_Msk (0x01 << PWMG_IM_NEWP4B_Pos) +#define PWMG_IM_NEWP5A_Pos 10 +#define PWMG_IM_NEWP5A_Msk (0x01 << PWMG_IM_NEWP5A_Pos) +#define PWMG_IM_NEWP5B_Pos 11 +#define PWMG_IM_NEWP5B_Msk (0x01 << PWMG_IM_NEWP5B_Pos) +#define PWMG_IM_HEND0A_Pos 12 +#define PWMG_IM_HEND0A_Msk (0x01 << PWMG_IM_HEND0A_Pos) +#define PWMG_IM_HEND0B_Pos 13 +#define PWMG_IM_HEND0B_Msk (0x01 << PWMG_IM_HEND0B_Pos) +#define PWMG_IM_HEND1A_Pos 14 +#define PWMG_IM_HEND1A_Msk (0x01 << PWMG_IM_HEND1A_Pos) +#define PWMG_IM_HEND1B_Pos 15 +#define PWMG_IM_HEND1B_Msk (0x01 << PWMG_IM_HEND1B_Pos) +#define PWMG_IM_HEND2A_Pos 16 +#define PWMG_IM_HEND2A_Msk (0x01 << PWMG_IM_HEND2A_Pos) +#define PWMG_IM_HEND2B_Pos 17 +#define PWMG_IM_HEND2B_Msk (0x01 << PWMG_IM_HEND2B_Pos) +#define PWMG_IM_HEND3A_Pos 18 +#define PWMG_IM_HEND3A_Msk (0x01 << PWMG_IM_HEND3A_Pos) +#define PWMG_IM_HEND3B_Pos 19 +#define PWMG_IM_HEND3B_Msk (0x01 << PWMG_IM_HEND3B_Pos) +#define PWMG_IM_HEND4A_Pos 20 +#define PWMG_IM_HEND4A_Msk (0x01 << PWMG_IM_HEND4A_Pos) +#define PWMG_IM_HEND4B_Pos 21 +#define PWMG_IM_HEND4B_Msk (0x01 << PWMG_IM_HEND4B_Pos) +#define PWMG_IM_HEND5A_Pos 22 +#define PWMG_IM_HEND5A_Msk (0x01 << PWMG_IM_HEND5A_Pos) +#define PWMG_IM_HEND5B_Pos 23 +#define PWMG_IM_HEND5B_Msk (0x01 << PWMG_IM_HEND5B_Pos) +#define PWMG_IM_HALT_Pos 24 +#define PWMG_IM_HALT_Msk (0x01 << PWMG_IM_HALT_Pos) -#define PWMG_IF_NEWP0A_Pos 0 -#define PWMG_IF_NEWP0A_Msk (0x01 << PWMG_IF_NEWP0A_Pos) -#define PWMG_IF_NEWP0B_Pos 1 -#define PWMG_IF_NEWP0B_Msk (0x01 << PWMG_IF_NEWP0B_Pos) -#define PWMG_IF_NEWP1A_Pos 2 -#define PWMG_IF_NEWP1A_Msk (0x01 << PWMG_IF_NEWP1A_Pos) -#define PWMG_IF_NEWP1B_Pos 3 -#define PWMG_IF_NEWP1B_Msk (0x01 << PWMG_IF_NEWP1B_Pos) -#define PWMG_IF_NEWP2A_Pos 4 -#define PWMG_IF_NEWP2A_Msk (0x01 << PWMG_IF_NEWP2A_Pos) -#define PWMG_IF_NEWP2B_Pos 5 -#define PWMG_IF_NEWP2B_Msk (0x01 << PWMG_IF_NEWP2B_Pos) -#define PWMG_IF_NEWP3A_Pos 6 -#define PWMG_IF_NEWP3A_Msk (0x01 << PWMG_IF_NEWP3A_Pos) -#define PWMG_IF_NEWP3B_Pos 7 -#define PWMG_IF_NEWP3B_Msk (0x01 << PWMG_IF_NEWP3B_Pos) -#define PWMG_IF_NEWP4A_Pos 8 -#define PWMG_IF_NEWP4A_Msk (0x01 << PWMG_IF_NEWP4A_Pos) -#define PWMG_IF_NEWP4B_Pos 9 -#define PWMG_IF_NEWP4B_Msk (0x01 << PWMG_IF_NEWP4B_Pos) -#define PWMG_IF_NEWP5A_Pos 10 -#define PWMG_IF_NEWP5A_Msk (0x01 << PWMG_IF_NEWP5A_Pos) -#define PWMG_IF_NEWP5B_Pos 11 -#define PWMG_IF_NEWP5B_Msk (0x01 << PWMG_IF_NEWP5B_Pos) -#define PWMG_IF_HEND0A_Pos 12 -#define PWMG_IF_HEND0A_Msk (0x01 << PWMG_IF_HEND0A_Pos) -#define PWMG_IF_HEND0B_Pos 13 -#define PWMG_IF_HEND0B_Msk (0x01 << PWMG_IF_HEND0B_Pos) -#define PWMG_IF_HEND1A_Pos 14 -#define PWMG_IF_HEND1A_Msk (0x01 << PWMG_IF_HEND1A_Pos) -#define PWMG_IF_HEND1B_Pos 15 -#define PWMG_IF_HEND1B_Msk (0x01 << PWMG_IF_HEND1B_Pos) -#define PWMG_IF_HEND2A_Pos 16 -#define PWMG_IF_HEND2A_Msk (0x01 << PWMG_IF_HEND2A_Pos) -#define PWMG_IF_HEND2B_Pos 17 -#define PWMG_IF_HEND2B_Msk (0x01 << PWMG_IF_HEND2B_Pos) -#define PWMG_IF_HEND3A_Pos 18 -#define PWMG_IF_HEND3A_Msk (0x01 << PWMG_IF_HEND3A_Pos) -#define PWMG_IF_HEND3B_Pos 19 -#define PWMG_IF_HEND3B_Msk (0x01 << PWMG_IF_HEND3B_Pos) -#define PWMG_IF_HEND4A_Pos 20 -#define PWMG_IF_HEND4A_Msk (0x01 << PWMG_IF_HEND4A_Pos) -#define PWMG_IF_HEND4B_Pos 21 -#define PWMG_IF_HEND4B_Msk (0x01 << PWMG_IF_HEND4B_Pos) -#define PWMG_IF_HEND5A_Pos 22 -#define PWMG_IF_HEND5A_Msk (0x01 << PWMG_IF_HEND5A_Pos) -#define PWMG_IF_HEND5B_Pos 23 -#define PWMG_IF_HEND5B_Msk (0x01 << PWMG_IF_HEND5B_Pos) -#define PWMG_IF_HALT_Pos 24 -#define PWMG_IF_HALT_Msk (0x01 << PWMG_IF_HALT_Pos) +#define PWMG_IRS_NEWP0A_Pos 0 //Interrupt Raw State +#define PWMG_IRS_NEWP0A_Msk (0x01 << PWMG_IRS_NEWP0A_Pos) +#define PWMG_IRS_NEWP0B_Pos 1 +#define PWMG_IRS_NEWP0B_Msk (0x01 << PWMG_IRS_NEWP0B_Pos) +#define PWMG_IRS_NEWP1A_Pos 2 +#define PWMG_IRS_NEWP1A_Msk (0x01 << PWMG_IRS_NEWP1A_Pos) +#define PWMG_IRS_NEWP1B_Pos 3 +#define PWMG_IRS_NEWP1B_Msk (0x01 << PWMG_IRS_NEWP1B_Pos) +#define PWMG_IRS_NEWP2A_Pos 4 +#define PWMG_IRS_NEWP2A_Msk (0x01 << PWMG_IRS_NEWP2A_Pos) +#define PWMG_IRS_NEWP2B_Pos 5 +#define PWMG_IRS_NEWP2B_Msk (0x01 << PWMG_IRS_NEWP2B_Pos) +#define PWMG_IRS_NEWP3A_Pos 6 +#define PWMG_IRS_NEWP3A_Msk (0x01 << PWMG_IRS_NEWP3A_Pos) +#define PWMG_IRS_NEWP3B_Pos 7 +#define PWMG_IRS_NEWP3B_Msk (0x01 << PWMG_IRS_NEWP3B_Pos) +#define PWMG_IRS_NEWP4A_Pos 8 +#define PWMG_IRS_NEWP4A_Msk (0x01 << PWMG_IRS_NEWP4A_Pos) +#define PWMG_IRS_NEWP4B_Pos 9 +#define PWMG_IRS_NEWP4B_Msk (0x01 << PWMG_IRS_NEWP4B_Pos) +#define PWMG_IRS_NEWP5A_Pos 10 +#define PWMG_IRS_NEWP5A_Msk (0x01 << PWMG_IRS_NEWP5A_Pos) +#define PWMG_IRS_NEWP5B_Pos 11 +#define PWMG_IRS_NEWP5B_Msk (0x01 << PWMG_IRS_NEWP5B_Pos) +#define PWMG_IRS_HEND0A_Pos 12 +#define PWMG_IRS_HEND0A_Msk (0x01 << PWMG_IRS_HEND0A_Pos) +#define PWMG_IRS_HEND0B_Pos 13 +#define PWMG_IRS_HEND0B_Msk (0x01 << PWMG_IRS_HEND0B_Pos) +#define PWMG_IRS_HEND1A_Pos 14 +#define PWMG_IRS_HEND1A_Msk (0x01 << PWMG_IRS_HEND1A_Pos) +#define PWMG_IRS_HEND1B_Pos 15 +#define PWMG_IRS_HEND1B_Msk (0x01 << PWMG_IRS_HEND1B_Pos) +#define PWMG_IRS_HEND2A_Pos 16 +#define PWMG_IRS_HEND2A_Msk (0x01 << PWMG_IRS_HEND2A_Pos) +#define PWMG_IRS_HEND2B_Pos 17 +#define PWMG_IRS_HEND2B_Msk (0x01 << PWMG_IRS_HEND2B_Pos) +#define PWMG_IRS_HEND3A_Pos 18 +#define PWMG_IRS_HEND3A_Msk (0x01 << PWMG_IRS_HEND3A_Pos) +#define PWMG_IRS_HEND3B_Pos 19 +#define PWMG_IRS_HEND3B_Msk (0x01 << PWMG_IRS_HEND3B_Pos) +#define PWMG_IRS_HEND4A_Pos 20 +#define PWMG_IRS_HEND4A_Msk (0x01 << PWMG_IRS_HEND4A_Pos) +#define PWMG_IRS_HEND4B_Pos 21 +#define PWMG_IRS_HEND4B_Msk (0x01 << PWMG_IRS_HEND4B_Pos) +#define PWMG_IRS_HEND5A_Pos 22 +#define PWMG_IRS_HEND5A_Msk (0x01 << PWMG_IRS_HEND5A_Pos) +#define PWMG_IRS_HEND5B_Pos 23 +#define PWMG_IRS_HEND5B_Msk (0x01 << PWMG_IRS_HEND5B_Pos) +#define PWMG_IRS_HALT_Pos 24 +#define PWMG_IRS_HALT_Msk (0x01 << PWMG_IRS_HALT_Pos) -#define PWMG_IM_NEWP0A_Pos 0 //Interrupt Mask -#define PWMG_IM_NEWP0A_Msk (0x01 << PWMG_IM_NEWP0A_Pos) -#define PWMG_IM_NEWP0B_Pos 1 -#define PWMG_IM_NEWP0B_Msk (0x01 << PWMG_IM_NEWP0B_Pos) -#define PWMG_IM_NEWP1A_Pos 2 -#define PWMG_IM_NEWP1A_Msk (0x01 << PWMG_IM_NEWP1A_Pos) -#define PWMG_IM_NEWP1B_Pos 3 -#define PWMG_IM_NEWP1B_Msk (0x01 << PWMG_IM_NEWP1B_Pos) -#define PWMG_IM_NEWP2A_Pos 4 -#define PWMG_IM_NEWP2A_Msk (0x01 << PWMG_IM_NEWP2A_Pos) -#define PWMG_IM_NEWP2B_Pos 5 -#define PWMG_IM_NEWP2B_Msk (0x01 << PWMG_IM_NEWP2B_Pos) -#define PWMG_IM_NEWP3A_Pos 6 -#define PWMG_IM_NEWP3A_Msk (0x01 << PWMG_IM_NEWP3A_Pos) -#define PWMG_IM_NEWP3B_Pos 7 -#define PWMG_IM_NEWP3B_Msk (0x01 << PWMG_IM_NEWP3B_Pos) -#define PWMG_IM_NEWP4A_Pos 8 -#define PWMG_IM_NEWP4A_Msk (0x01 << PWMG_IM_NEWP4A_Pos) -#define PWMG_IM_NEWP4B_Pos 9 -#define PWMG_IM_NEWP4B_Msk (0x01 << PWMG_IM_NEWP4B_Pos) -#define PWMG_IM_NEWP5A_Pos 10 -#define PWMG_IM_NEWP5A_Msk (0x01 << PWMG_IM_NEWP5A_Pos) -#define PWMG_IM_NEWP5B_Pos 11 -#define PWMG_IM_NEWP5B_Msk (0x01 << PWMG_IM_NEWP5B_Pos) -#define PWMG_IM_HEND0A_Pos 12 -#define PWMG_IM_HEND0A_Msk (0x01 << PWMG_IM_HEND0A_Pos) -#define PWMG_IM_HEND0B_Pos 13 -#define PWMG_IM_HEND0B_Msk (0x01 << PWMG_IM_HEND0B_Pos) -#define PWMG_IM_HEND1A_Pos 14 -#define PWMG_IM_HEND1A_Msk (0x01 << PWMG_IM_HEND1A_Pos) -#define PWMG_IM_HEND1B_Pos 15 -#define PWMG_IM_HEND1B_Msk (0x01 << PWMG_IM_HEND1B_Pos) -#define PWMG_IM_HEND2A_Pos 16 -#define PWMG_IM_HEND2A_Msk (0x01 << PWMG_IM_HEND2A_Pos) -#define PWMG_IM_HEND2B_Pos 17 -#define PWMG_IM_HEND2B_Msk (0x01 << PWMG_IM_HEND2B_Pos) -#define PWMG_IM_HEND3A_Pos 18 -#define PWMG_IM_HEND3A_Msk (0x01 << PWMG_IM_HEND3A_Pos) -#define PWMG_IM_HEND3B_Pos 19 -#define PWMG_IM_HEND3B_Msk (0x01 << PWMG_IM_HEND3B_Pos) -#define PWMG_IM_HEND4A_Pos 20 -#define PWMG_IM_HEND4A_Msk (0x01 << PWMG_IM_HEND4A_Pos) -#define PWMG_IM_HEND4B_Pos 21 -#define PWMG_IM_HEND4B_Msk (0x01 << PWMG_IM_HEND4B_Pos) -#define PWMG_IM_HEND5A_Pos 22 -#define PWMG_IM_HEND5A_Msk (0x01 << PWMG_IM_HEND5A_Pos) -#define PWMG_IM_HEND5B_Pos 23 -#define PWMG_IM_HEND5B_Msk (0x01 << PWMG_IM_HEND5B_Pos) -#define PWMG_IM_HALT_Pos 24 -#define PWMG_IM_HALT_Msk (0x01 << PWMG_IM_HALT_Pos) +typedef struct +{ + __IO uint32_t EN; //[0] ENABLE -#define PWMG_IRS_NEWP0A_Pos 0 //Interrupt Raw State -#define PWMG_IRS_NEWP0A_Msk (0x01 << PWMG_IRS_NEWP0A_Pos) -#define PWMG_IRS_NEWP0B_Pos 1 -#define PWMG_IRS_NEWP0B_Msk (0x01 << PWMG_IRS_NEWP0B_Pos) -#define PWMG_IRS_NEWP1A_Pos 2 -#define PWMG_IRS_NEWP1A_Msk (0x01 << PWMG_IRS_NEWP1A_Pos) -#define PWMG_IRS_NEWP1B_Pos 3 -#define PWMG_IRS_NEWP1B_Msk (0x01 << PWMG_IRS_NEWP1B_Pos) -#define PWMG_IRS_NEWP2A_Pos 4 -#define PWMG_IRS_NEWP2A_Msk (0x01 << PWMG_IRS_NEWP2A_Pos) -#define PWMG_IRS_NEWP2B_Pos 5 -#define PWMG_IRS_NEWP2B_Msk (0x01 << PWMG_IRS_NEWP2B_Pos) -#define PWMG_IRS_NEWP3A_Pos 6 -#define PWMG_IRS_NEWP3A_Msk (0x01 << PWMG_IRS_NEWP3A_Pos) -#define PWMG_IRS_NEWP3B_Pos 7 -#define PWMG_IRS_NEWP3B_Msk (0x01 << PWMG_IRS_NEWP3B_Pos) -#define PWMG_IRS_NEWP4A_Pos 8 -#define PWMG_IRS_NEWP4A_Msk (0x01 << PWMG_IRS_NEWP4A_Pos) -#define PWMG_IRS_NEWP4B_Pos 9 -#define PWMG_IRS_NEWP4B_Msk (0x01 << PWMG_IRS_NEWP4B_Pos) -#define PWMG_IRS_NEWP5A_Pos 10 -#define PWMG_IRS_NEWP5A_Msk (0x01 << PWMG_IRS_NEWP5A_Pos) -#define PWMG_IRS_NEWP5B_Pos 11 -#define PWMG_IRS_NEWP5B_Msk (0x01 << PWMG_IRS_NEWP5B_Pos) -#define PWMG_IRS_HEND0A_Pos 12 -#define PWMG_IRS_HEND0A_Msk (0x01 << PWMG_IRS_HEND0A_Pos) -#define PWMG_IRS_HEND0B_Pos 13 -#define PWMG_IRS_HEND0B_Msk (0x01 << PWMG_IRS_HEND0B_Pos) -#define PWMG_IRS_HEND1A_Pos 14 -#define PWMG_IRS_HEND1A_Msk (0x01 << PWMG_IRS_HEND1A_Pos) -#define PWMG_IRS_HEND1B_Pos 15 -#define PWMG_IRS_HEND1B_Msk (0x01 << PWMG_IRS_HEND1B_Pos) -#define PWMG_IRS_HEND2A_Pos 16 -#define PWMG_IRS_HEND2A_Msk (0x01 << PWMG_IRS_HEND2A_Pos) -#define PWMG_IRS_HEND2B_Pos 17 -#define PWMG_IRS_HEND2B_Msk (0x01 << PWMG_IRS_HEND2B_Pos) -#define PWMG_IRS_HEND3A_Pos 18 -#define PWMG_IRS_HEND3A_Msk (0x01 << PWMG_IRS_HEND3A_Pos) -#define PWMG_IRS_HEND3B_Pos 19 -#define PWMG_IRS_HEND3B_Msk (0x01 << PWMG_IRS_HEND3B_Pos) -#define PWMG_IRS_HEND4A_Pos 20 -#define PWMG_IRS_HEND4A_Msk (0x01 << PWMG_IRS_HEND4A_Pos) -#define PWMG_IRS_HEND4B_Pos 21 -#define PWMG_IRS_HEND4B_Msk (0x01 << PWMG_IRS_HEND4B_Pos) -#define PWMG_IRS_HEND5A_Pos 22 -#define PWMG_IRS_HEND5A_Msk (0x01 << PWMG_IRS_HEND5A_Pos) -#define PWMG_IRS_HEND5B_Pos 23 -#define PWMG_IRS_HEND5B_Msk (0x01 << PWMG_IRS_HEND5B_Pos) -#define PWMG_IRS_HALT_Pos 24 -#define PWMG_IRS_HALT_Msk (0x01 << PWMG_IRS_HALT_Pos) + __IO uint32_t IE; //只有为1时,IF[CHx]在DMA传输结束时才能变为1,否则将一直保持在0 + __IO uint32_t IM; //当为1时,即使IF[CHx]为1,dma_int也不会因此变1 + __IO uint32_t IF; //写1清零 + uint32_t RESERVED[12]; -typedef struct { - __IO uint32_t EN; //[0] ENABLE - - __IO uint32_t IE; //只有为1时,IF[CHx]在DMA传输结束时才能变为1,否则将一直保持在0 - - __IO uint32_t IM; //当为1时,即使IF[CHx]为1,dma_int也不会因此变1 - - __IO uint32_t IF; //写1清零 - - uint32_t RESERVED[12]; - - struct { - __IO uint32_t CR; - - __IO uint32_t AM; //Adress Mode - - __IO uint32_t SRC; - - __IO uint32_t SRCSGADDR1; //只在Scatter Gather模式下使用 - - __IO uint32_t SRCSGADDR2; //只在Scatter Gather模式下使用 - - __IO uint32_t SRCSGADDR3; //只在Scatter Gather模式下使用 - - __IO uint32_t SRCSGLEN; //只在Scatter Gather模式下使用 - - __IO uint32_t DST; - - __IO uint32_t DSTSGADDR1; //只在Scatter Gather模式下使用 - - __IO uint32_t DSTSGADDR2; //只在Scatter Gather模式下使用 - - __IO uint32_t DSTSGADDR3; //只在Scatter Gather模式下使用 - - __IO uint32_t DSTSGLEN; //只在Scatter Gather模式下使用 - - uint32_t RESERVED[4]; - } CH[3]; + struct + { + __IO uint32_t CR; + + __IO uint32_t AM; //Adress Mode + + __IO uint32_t SRC; + + __IO uint32_t SRCSGADDR1; //只在Scatter Gather模式下使用 + + __IO uint32_t SRCSGADDR2; //只在Scatter Gather模式下使用 + + __IO uint32_t SRCSGADDR3; //只在Scatter Gather模式下使用 + + __IO uint32_t SRCSGLEN; //只在Scatter Gather模式下使用 + + __IO uint32_t DST; + + __IO uint32_t DSTSGADDR1; //只在Scatter Gather模式下使用 + + __IO uint32_t DSTSGADDR2; //只在Scatter Gather模式下使用 + + __IO uint32_t DSTSGADDR3; //只在Scatter Gather模式下使用 + + __IO uint32_t DSTSGLEN; //只在Scatter Gather模式下使用 + + uint32_t RESERVED[4]; + } CH[3]; } DMA_TypeDef; +#define DMA_IE_CH0_Pos 0 +#define DMA_IE_CH0_Msk (0x01 << DMA_IE_CH0_Pos) +#define DMA_IE_CH1_Pos 1 +#define DMA_IE_CH1_Msk (0x01 << DMA_IE_CH1_Pos) +#define DMA_IE_CH2_Pos 2 +#define DMA_IE_CH2_Msk (0x01 << DMA_IE_CH2_Pos) +#define DMA_IE_CH3_Pos 3 +#define DMA_IE_CH3_Msk (0x01 << DMA_IE_CH3_Pos) +#define DMA_IE_CH4_Pos 4 +#define DMA_IE_CH4_Msk (0x01 << DMA_IE_CH4_Pos) +#define DMA_IE_CH5_Pos 5 +#define DMA_IE_CH5_Msk (0x01 << DMA_IE_CH5_Pos) +#define DMA_IE_CH6_Pos 6 +#define DMA_IE_CH6_Msk (0x01 << DMA_IE_CH6_Pos) +#define DMA_IE_CH7_Pos 7 +#define DMA_IE_CH7_Msk (0x01 << DMA_IE_CH7_Pos) -#define DMA_IE_CH0_Pos 0 -#define DMA_IE_CH0_Msk (0x01 << DMA_IE_CH0_Pos) -#define DMA_IE_CH1_Pos 1 -#define DMA_IE_CH1_Msk (0x01 << DMA_IE_CH1_Pos) -#define DMA_IE_CH2_Pos 2 -#define DMA_IE_CH2_Msk (0x01 << DMA_IE_CH2_Pos) -#define DMA_IE_CH3_Pos 3 -#define DMA_IE_CH3_Msk (0x01 << DMA_IE_CH3_Pos) -#define DMA_IE_CH4_Pos 4 -#define DMA_IE_CH4_Msk (0x01 << DMA_IE_CH4_Pos) -#define DMA_IE_CH5_Pos 5 -#define DMA_IE_CH5_Msk (0x01 << DMA_IE_CH5_Pos) -#define DMA_IE_CH6_Pos 6 -#define DMA_IE_CH6_Msk (0x01 << DMA_IE_CH6_Pos) -#define DMA_IE_CH7_Pos 7 -#define DMA_IE_CH7_Msk (0x01 << DMA_IE_CH7_Pos) +#define DMA_IM_CH0_Pos 0 +#define DMA_IM_CH0_Msk (0x01 << DMA_IM_CH0_Pos) +#define DMA_IM_CH1_Pos 1 +#define DMA_IM_CH1_Msk (0x01 << DMA_IM_CH1_Pos) +#define DMA_IM_CH2_Pos 2 +#define DMA_IM_CH2_Msk (0x01 << DMA_IM_CH2_Pos) +#define DMA_IM_CH3_Pos 3 +#define DMA_IM_CH3_Msk (0x01 << DMA_IM_CH3_Pos) +#define DMA_IM_CH4_Pos 4 +#define DMA_IM_CH4_Msk (0x01 << DMA_IM_CH4_Pos) +#define DMA_IM_CH5_Pos 5 +#define DMA_IM_CH5_Msk (0x01 << DMA_IM_CH5_Pos) +#define DMA_IM_CH6_Pos 6 +#define DMA_IM_CH6_Msk (0x01 << DMA_IM_CH6_Pos) +#define DMA_IM_CH7_Pos 7 +#define DMA_IM_CH7_Msk (0x01 << DMA_IM_CH7_Pos) -#define DMA_IM_CH0_Pos 0 -#define DMA_IM_CH0_Msk (0x01 << DMA_IM_CH0_Pos) -#define DMA_IM_CH1_Pos 1 -#define DMA_IM_CH1_Msk (0x01 << DMA_IM_CH1_Pos) -#define DMA_IM_CH2_Pos 2 -#define DMA_IM_CH2_Msk (0x01 << DMA_IM_CH2_Pos) -#define DMA_IM_CH3_Pos 3 -#define DMA_IM_CH3_Msk (0x01 << DMA_IM_CH3_Pos) -#define DMA_IM_CH4_Pos 4 -#define DMA_IM_CH4_Msk (0x01 << DMA_IM_CH4_Pos) -#define DMA_IM_CH5_Pos 5 -#define DMA_IM_CH5_Msk (0x01 << DMA_IM_CH5_Pos) -#define DMA_IM_CH6_Pos 6 -#define DMA_IM_CH6_Msk (0x01 << DMA_IM_CH6_Pos) -#define DMA_IM_CH7_Pos 7 -#define DMA_IM_CH7_Msk (0x01 << DMA_IM_CH7_Pos) +#define DMA_IF_CH0_Pos 0 +#define DMA_IF_CH0_Msk (0x01 << DMA_IF_CH0_Pos) +#define DMA_IF_CH1_Pos 1 +#define DMA_IF_CH1_Msk (0x01 << DMA_IF_CH1_Pos) +#define DMA_IF_CH2_Pos 2 +#define DMA_IF_CH2_Msk (0x01 << DMA_IF_CH2_Pos) +#define DMA_IF_CH3_Pos 3 +#define DMA_IF_CH3_Msk (0x01 << DMA_IF_CH3_Pos) +#define DMA_IF_CH4_Pos 4 +#define DMA_IF_CH4_Msk (0x01 << DMA_IF_CH4_Pos) +#define DMA_IF_CH5_Pos 5 +#define DMA_IF_CH5_Msk (0x01 << DMA_IF_CH5_Pos) +#define DMA_IF_CH6_Pos 6 +#define DMA_IF_CH6_Msk (0x01 << DMA_IF_CH6_Pos) +#define DMA_IF_CH7_Pos 7 +#define DMA_IF_CH7_Msk (0x01 << DMA_IF_CH7_Pos) -#define DMA_IF_CH0_Pos 0 -#define DMA_IF_CH0_Msk (0x01 << DMA_IF_CH0_Pos) -#define DMA_IF_CH1_Pos 1 -#define DMA_IF_CH1_Msk (0x01 << DMA_IF_CH1_Pos) -#define DMA_IF_CH2_Pos 2 -#define DMA_IF_CH2_Msk (0x01 << DMA_IF_CH2_Pos) -#define DMA_IF_CH3_Pos 3 -#define DMA_IF_CH3_Msk (0x01 << DMA_IF_CH3_Pos) -#define DMA_IF_CH4_Pos 4 -#define DMA_IF_CH4_Msk (0x01 << DMA_IF_CH4_Pos) -#define DMA_IF_CH5_Pos 5 -#define DMA_IF_CH5_Msk (0x01 << DMA_IF_CH5_Pos) -#define DMA_IF_CH6_Pos 6 -#define DMA_IF_CH6_Msk (0x01 << DMA_IF_CH6_Pos) -#define DMA_IF_CH7_Pos 7 -#define DMA_IF_CH7_Msk (0x01 << DMA_IF_CH7_Pos) +#define DMA_CR_LEN_Pos 0 //此通道传输总长度,0对应1字节,最大4096字节 +#define DMA_CR_LEN_Msk (0xFFF << DMA_CR_LEN_Pos) +#define DMA_CR_RXEN_Pos 16 +#define DMA_CR_RXEN_Msk (0x01 << DMA_CR_RXEN_Pos) +#define DMA_CR_TXEN_Pos 17 +#define DMA_CR_TXEN_Msk (0x01 << DMA_CR_TXEN_Pos) +#define DMA_CR_AUTORE_Pos 18 //Auto Restart, 通道在传输完成后,是否自动重新启动 +#define DMA_CR_AUTORE_Msk (0x01 << DMA_CR_AUTORE_Pos) -#define DMA_CR_LEN_Pos 0 //此通道传输总长度,0对应1字节,最大4096字节 -#define DMA_CR_LEN_Msk (0xFFF << DMA_CR_LEN_Pos) -#define DMA_CR_RXEN_Pos 16 -#define DMA_CR_RXEN_Msk (0x01 << DMA_CR_RXEN_Pos) -#define DMA_CR_TXEN_Pos 17 -#define DMA_CR_TXEN_Msk (0x01 << DMA_CR_TXEN_Pos) -#define DMA_CR_AUTORE_Pos 18 //Auto Restart, 通道在传输完成后,是否自动重新启动 -#define DMA_CR_AUTORE_Msk (0x01 << DMA_CR_AUTORE_Pos) +#define DMA_AM_SRCAM_Pos 0 //Address Mode 0 地址固定 1 地址递增 2 scatter gather模式 +#define DMA_AM_SRCAM_Msk (0x03 << DMA_AM_SRCAM_Pos) +#define DMA_AM_DSTAM_Pos 8 +#define DMA_AM_DSTAM_Msk (0x03 << DMA_AM_DSTAM_Pos) +#define DMA_AM_BURST_Pos 16 +#define DMA_AM_BURST_Msk (0x01 << DMA_AM_BURST_Pos) -#define DMA_AM_SRCAM_Pos 0 //Address Mode 0 地址固定 1 地址递增 2 scatter gather模式 -#define DMA_AM_SRCAM_Msk (0x03 << DMA_AM_SRCAM_Pos) -#define DMA_AM_DSTAM_Pos 8 -#define DMA_AM_DSTAM_Msk (0x03 << DMA_AM_DSTAM_Pos) -#define DMA_AM_BURST_Pos 16 -#define DMA_AM_BURST_Msk (0x01 << DMA_AM_BURST_Pos) +typedef struct +{ + __IO uint32_t CR; //Control Register + __O uint32_t CMD; //Command Register + __I uint32_t SR; //Status Register + __I uint32_t IF; //Interrupt Flag,读取清零 -typedef struct { - __IO uint32_t CR; //Control Register - - __O uint32_t CMD; //Command Register - - __I uint32_t SR; //Status Register - - __I uint32_t IF; //Interrupt Flag,读取清零 - - __IO uint32_t IE; //Interrupt Enable - - uint32_t RESERVED; - - __IO uint32_t BT0; //Bit Time Register 0 - - __IO uint32_t BT1; //Bit Time Register 1 - - uint32_t RESERVED2[3]; - - __I uint32_t ALC; //Arbitration Lost Capture, 仲裁丢失捕捉 - - __I uint32_t ECC; //Error code capture, 错误代码捕捉 - - __IO uint32_t EWLIM; //Error Warning Limit, 错误报警限制 - - __IO uint32_t RXERR; //RX错误计数 - - __IO uint32_t TXERR; //TX错误计数 - - union { - struct { //在复位时可读写,正常工作模式下不可访问 - __IO uint32_t ACR[4]; //Acceptance Check Register, 验收寄存器 - - __IO uint32_t AMR[4]; //Acceptance Mask Register, 验收屏蔽寄存器;对应位写0,ID必须和验收寄存器匹配 - - uint32_t RESERVED[5]; - } FILTER; - - union { //在正常工作模式下可读写,复位时不可访问 - struct { - __O uint32_t INFO; - - __O uint32_t DATA[12]; - } TXFRAME; - - struct { - __I uint32_t INFO; - - __I uint32_t DATA[12]; - } RXFRAME; - }; - }; - - __I uint32_t RMCNT; //Receive Message Count - - uint32_t RESERVED3[66]; - - struct { //TXFRAME的读接口 - __I uint32_t INFO; - - __I uint32_t DATA[12]; - } TXFRAME_R; + __IO uint32_t IE; //Interrupt Enable + + uint32_t RESERVED; + + __IO uint32_t BT0; //Bit Time Register 0 + + __IO uint32_t BT1; //Bit Time Register 1 + + uint32_t RESERVED2[3]; + + __I uint32_t ALC; //Arbitration Lost Capture, 仲裁丢失捕捉 + + __I uint32_t ECC; //Error code capture, 错误代码捕捉 + + __IO uint32_t EWLIM; //Error Warning Limit, 错误报警限制 + + __IO uint32_t RXERR; //RX错误计数 + + __IO uint32_t TXERR; //TX错误计数 + + union + { + struct + { //在复位时可读写,正常工作模式下不可访问 + __IO uint32_t ACR[4]; //Acceptance Check Register, 验收寄存器 + + __IO uint32_t AMR[4]; //Acceptance Mask Register, 验收屏蔽寄存器;对应位写0,ID必须和验收寄存器匹配 + + uint32_t RESERVED[5]; + } FILTER; + + union + { //在正常工作模式下可读写,复位时不可访问 + struct + { + __O uint32_t INFO; + + __O uint32_t DATA[12]; + } TXFRAME; + + struct + { + __I uint32_t INFO; + + __I uint32_t DATA[12]; + } RXFRAME; + }; + }; + + __I uint32_t RMCNT; //Receive Message Count + + uint32_t RESERVED3[66]; + + struct + { //TXFRAME的读接口 + __I uint32_t INFO; + + __I uint32_t DATA[12]; + } TXFRAME_R; } CAN_TypeDef; +#define CAN_CR_RST_Pos 0 +#define CAN_CR_RST_Msk (0x01 << CAN_CR_RST_Pos) +#define CAN_CR_LOM_Pos 1 //Listen Only Mode +#define CAN_CR_LOM_Msk (0x01 << CAN_CR_LOM_Pos) +#define CAN_CR_STM_Pos 2 //Self Test Mode, 此模式下即使没有应答,CAN控制器也可以成功发送 +#define CAN_CR_STM_Msk (0x01 << CAN_CR_STM_Pos) +#define CAN_CR_AFM_Pos 3 //Acceptance Filter Mode, 1 单个验收滤波器(32位) 0 两个验收滤波器(16位) +#define CAN_CR_AFM_Msk (0x01 << CAN_CR_AFM_Pos) +#define CAN_CR_SLEEP_Pos 4 //写1进入睡眠模式,有总线活动或中断时唤醒并自动清零此位 +#define CAN_CR_SLEEP_Msk (0x01 << CAN_CR_SLEEP_Pos) -#define CAN_CR_RST_Pos 0 -#define CAN_CR_RST_Msk (0x01 << CAN_CR_RST_Pos) -#define CAN_CR_LOM_Pos 1 //Listen Only Mode -#define CAN_CR_LOM_Msk (0x01 << CAN_CR_LOM_Pos) -#define CAN_CR_STM_Pos 2 //Self Test Mode, 此模式下即使没有应答,CAN控制器也可以成功发送 -#define CAN_CR_STM_Msk (0x01 << CAN_CR_STM_Pos) -#define CAN_CR_AFM_Pos 3 //Acceptance Filter Mode, 1 单个验收滤波器(32位) 0 两个验收滤波器(16位) -#define CAN_CR_AFM_Msk (0x01 << CAN_CR_AFM_Pos) -#define CAN_CR_SLEEP_Pos 4 //写1进入睡眠模式,有总线活动或中断时唤醒并自动清零此位 -#define CAN_CR_SLEEP_Msk (0x01 << CAN_CR_SLEEP_Pos) +#define CAN_CMD_TXREQ_Pos 0 //Transmission Request +#define CAN_CMD_TXREQ_Msk (0x01 << CAN_CMD_TXREQ_Pos) +#define CAN_CMD_ABTTX_Pos 1 //Abort Transmission +#define CAN_CMD_ABTTX_Msk (0x01 << CAN_CMD_ABTTX_Pos) +#define CAN_CMD_RRB_Pos 2 //Release Receive Buffer +#define CAN_CMD_RRB_Msk (0x01 << CAN_CMD_RRB_Pos) +#define CAN_CMD_CLROV_Pos 3 //Clear Data Overrun +#define CAN_CMD_CLROV_Msk (0x01 << CAN_CMD_CLROV_Pos) +#define CAN_CMD_SRR_Pos 4 //Self Reception Request +#define CAN_CMD_SRR_Msk (0x01 << CAN_CMD_SRR_Pos) -#define CAN_CMD_TXREQ_Pos 0 //Transmission Request -#define CAN_CMD_TXREQ_Msk (0x01 << CAN_CMD_TXREQ_Pos) -#define CAN_CMD_ABTTX_Pos 1 //Abort Transmission -#define CAN_CMD_ABTTX_Msk (0x01 << CAN_CMD_ABTTX_Pos) -#define CAN_CMD_RRB_Pos 2 //Release Receive Buffer -#define CAN_CMD_RRB_Msk (0x01 << CAN_CMD_RRB_Pos) -#define CAN_CMD_CLROV_Pos 3 //Clear Data Overrun -#define CAN_CMD_CLROV_Msk (0x01 << CAN_CMD_CLROV_Pos) -#define CAN_CMD_SRR_Pos 4 //Self Reception Request -#define CAN_CMD_SRR_Msk (0x01 << CAN_CMD_SRR_Pos) +#define CAN_SR_RXDA_Pos 0 //Receive Data Available,接收FIFO中有完整消息可以读取 +#define CAN_SR_RXDA_Msk (0x01 << CAN_SR_RXDA_Pos) +#define CAN_SR_RXOV_Pos 1 //Receive FIFO Overrun,新接收的信息由于接收FIFO已满而丢掉 +#define CAN_SR_RXOV_Msk (0x01 << CAN_SR_RXOV_Pos) +#define CAN_SR_TXBR_Pos 2 //Transmit Buffer Release,0 正在处理前面的发送,现在不能写新的消息 1 可以写入新的消息发送 +#define CAN_SR_TXBR_Msk (0x01 << CAN_SR_TXBR_Pos) +#define CAN_SR_TXOK_Pos 3 //Transmit OK,successfully completed +#define CAN_SR_TXOK_Msk (0x01 << CAN_SR_TXOK_Pos) +#define CAN_SR_RXBUSY_Pos 4 //Receive Busy,正在接收 +#define CAN_SR_RXBUSY_Msk (0x01 << CAN_SR_RXBUSY_Pos) +#define CAN_SR_TXBUSY_Pos 5 //Transmit Busy,正在发送 +#define CAN_SR_TXBUSY_Msk (0x01 << CAN_SR_TXBUSY_Pos) +#define CAN_SR_ERRWARN_Pos 6 //1 至少一个错误计数器达到 Warning Limit +#define CAN_SR_ERRWARN_Msk (0x01 << CAN_SR_ERRWARN_Pos) +#define CAN_SR_BUSOFF_Pos 7 //1 CAN 控制器处于总线关闭状态,没有参与到总线活动 +#define CAN_SR_BUSOFF_Msk (0x01 << CAN_SR_BUSOFF_Pos) -#define CAN_SR_RXDA_Pos 0 //Receive Data Available,接收FIFO中有完整消息可以读取 -#define CAN_SR_RXDA_Msk (0x01 << CAN_SR_RXDA_Pos) -#define CAN_SR_RXOV_Pos 1 //Receive FIFO Overrun,新接收的信息由于接收FIFO已满而丢掉 -#define CAN_SR_RXOV_Msk (0x01 << CAN_SR_RXOV_Pos) -#define CAN_SR_TXBR_Pos 2 //Transmit Buffer Release,0 正在处理前面的发送,现在不能写新的消息 1 可以写入新的消息发送 -#define CAN_SR_TXBR_Msk (0x01 << CAN_SR_TXBR_Pos) -#define CAN_SR_TXOK_Pos 3 //Transmit OK,successfully completed -#define CAN_SR_TXOK_Msk (0x01 << CAN_SR_TXOK_Pos) -#define CAN_SR_RXBUSY_Pos 4 //Receive Busy,正在接收 -#define CAN_SR_RXBUSY_Msk (0x01 << CAN_SR_RXBUSY_Pos) -#define CAN_SR_TXBUSY_Pos 5 //Transmit Busy,正在发送 -#define CAN_SR_TXBUSY_Msk (0x01 << CAN_SR_TXBUSY_Pos) -#define CAN_SR_ERRWARN_Pos 6 //1 至少一个错误计数器达到 Warning Limit -#define CAN_SR_ERRWARN_Msk (0x01 << CAN_SR_ERRWARN_Pos) -#define CAN_SR_BUSOFF_Pos 7 //1 CAN 控制器处于总线关闭状态,没有参与到总线活动 -#define CAN_SR_BUSOFF_Msk (0x01 << CAN_SR_BUSOFF_Pos) +#define CAN_IF_RXDA_Pos 0 //IF.RXDA = SR.RXDA & IE.RXDA +#define CAN_IF_RXDA_Msk (0x01 << CAN_IF_RXDA_Pos) +#define CAN_IF_TXBR_Pos 1 //当IE.TXBR=1时,SR.TXBR由0变成1将置位此位 +#define CAN_IF_TXBR_Msk (0x01 << CAN_IF_TXBR_Pos) +#define CAN_IF_ERRWARN_Pos 2 //当IE.ERRWARN=1时,SR.ERRWARN或SR.BUSOFF 0-to-1 或 1-to-0将置位此位 +#define CAN_IF_ERRWARN_Msk (0x01 << CAN_IF_ERRWARN_Pos) +#define CAN_IF_RXOV_Pos 3 //IF.RXOV = SR.RXOV & IE.RXOV +#define CAN_IF_RXOV_Msk (0x01 << CAN_IF_RXOV_Pos) +#define CAN_IF_WKUP_Pos 4 //当IE.WKUP=1时,在睡眠模式下的CAN控制器检测到总线活动时硬件置位 +#define CAN_IF_WKUP_Msk (0x01 << CAN_IF_WKUP_Pos) +#define CAN_IF_ERRPASS_Pos 5 // +#define CAN_IF_ERRPASS_Msk (0x01 << CAN_IF_ERRPASS_Pos) +#define CAN_IF_ARBLOST_Pos 6 //Arbitration Lost,当IE.ARBLOST=1时,CAN控制器丢失仲裁变成接收方时硬件置位 +#define CAN_IF_ARBLOST_Msk (0x01 << CAN_IF_ARBLOST_Pos) +#define CAN_IF_BUSERR_Pos 7 //当IE.BUSERR=1时,CAN控制器检测到总线错误时硬件置位 +#define CAN_IF_BUSERR_Msk (0x01 << CAN_IF_BUSERR_Pos) -#define CAN_IF_RXDA_Pos 0 //IF.RXDA = SR.RXDA & IE.RXDA -#define CAN_IF_RXDA_Msk (0x01 << CAN_IF_RXDA_Pos) -#define CAN_IF_TXBR_Pos 1 //当IE.TXBR=1时,SR.TXBR由0变成1将置位此位 -#define CAN_IF_TXBR_Msk (0x01 << CAN_IF_TXBR_Pos) -#define CAN_IF_ERRWARN_Pos 2 //当IE.ERRWARN=1时,SR.ERRWARN或SR.BUSOFF 0-to-1 或 1-to-0将置位此位 -#define CAN_IF_ERRWARN_Msk (0x01 << CAN_IF_ERRWARN_Pos) -#define CAN_IF_RXOV_Pos 3 //IF.RXOV = SR.RXOV & IE.RXOV -#define CAN_IF_RXOV_Msk (0x01 << CAN_IF_RXOV_Pos) -#define CAN_IF_WKUP_Pos 4 //当IE.WKUP=1时,在睡眠模式下的CAN控制器检测到总线活动时硬件置位 -#define CAN_IF_WKUP_Msk (0x01 << CAN_IF_WKUP_Pos) -#define CAN_IF_ERRPASS_Pos 5 // -#define CAN_IF_ERRPASS_Msk (0x01 << CAN_IF_ERRPASS_Pos) -#define CAN_IF_ARBLOST_Pos 6 //Arbitration Lost,当IE.ARBLOST=1时,CAN控制器丢失仲裁变成接收方时硬件置位 -#define CAN_IF_ARBLOST_Msk (0x01 << CAN_IF_ARBLOST_Pos) -#define CAN_IF_BUSERR_Pos 7 //当IE.BUSERR=1时,CAN控制器检测到总线错误时硬件置位 -#define CAN_IF_BUSERR_Msk (0x01 << CAN_IF_BUSERR_Pos) +#define CAN_IE_RXDA_Pos 0 +#define CAN_IE_RXDA_Msk (0x01 << CAN_IE_RXDA_Pos) +#define CAN_IE_TXBR_Pos 1 +#define CAN_IE_TXBR_Msk (0x01 << CAN_IE_TXBR_Pos) +#define CAN_IE_ERRWARN_Pos 2 +#define CAN_IE_ERRWARN_Msk (0x01 << CAN_IE_ERRWARN_Pos) +#define CAN_IE_RXOV_Pos 3 +#define CAN_IE_RXOV_Msk (0x01 << CAN_IE_RXOV_Pos) +#define CAN_IE_WKUP_Pos 4 +#define CAN_IE_WKUP_Msk (0x01 << CAN_IE_WKUP_Pos) +#define CAN_IE_ERRPASS_Pos 5 +#define CAN_IE_ERRPASS_Msk (0x01 << CAN_IE_ERRPASS_Pos) +#define CAN_IE_ARBLOST_Pos 6 +#define CAN_IE_ARBLOST_Msk (0x01 << CAN_IE_ARBLOST_Pos) +#define CAN_IE_BUSERR_Pos 7 +#define CAN_IE_BUSERR_Msk (0x01 << CAN_IE_BUSERR_Pos) -#define CAN_IE_RXDA_Pos 0 -#define CAN_IE_RXDA_Msk (0x01 << CAN_IE_RXDA_Pos) -#define CAN_IE_TXBR_Pos 1 -#define CAN_IE_TXBR_Msk (0x01 << CAN_IE_TXBR_Pos) -#define CAN_IE_ERRWARN_Pos 2 -#define CAN_IE_ERRWARN_Msk (0x01 << CAN_IE_ERRWARN_Pos) -#define CAN_IE_RXOV_Pos 3 -#define CAN_IE_RXOV_Msk (0x01 << CAN_IE_RXOV_Pos) -#define CAN_IE_WKUP_Pos 4 -#define CAN_IE_WKUP_Msk (0x01 << CAN_IE_WKUP_Pos) -#define CAN_IE_ERRPASS_Pos 5 -#define CAN_IE_ERRPASS_Msk (0x01 << CAN_IE_ERRPASS_Pos) -#define CAN_IE_ARBLOST_Pos 6 -#define CAN_IE_ARBLOST_Msk (0x01 << CAN_IE_ARBLOST_Pos) -#define CAN_IE_BUSERR_Pos 7 -#define CAN_IE_BUSERR_Msk (0x01 << CAN_IE_BUSERR_Pos) +#define CAN_BT0_BRP_Pos 0 //Baud Rate Prescaler,CAN时间单位=2*Tsysclk*(BRP+1) +#define CAN_BT0_BRP_Msk (0x3F << CAN_BT0_BRP_Pos) +#define CAN_BT0_SJW_Pos 6 //Synchronization Jump Width +#define CAN_BT0_SJW_Msk (0x03 << CAN_BT0_SJW_Pos) -#define CAN_BT0_BRP_Pos 0 //Baud Rate Prescaler,CAN时间单位=2*Tsysclk*(BRP+1) -#define CAN_BT0_BRP_Msk (0x3F << CAN_BT0_BRP_Pos) -#define CAN_BT0_SJW_Pos 6 //Synchronization Jump Width -#define CAN_BT0_SJW_Msk (0x03 << CAN_BT0_SJW_Pos) +#define CAN_BT1_TSEG1_Pos 0 //t_tseg1 = CAN时间单位 * (TSEG1+1) +#define CAN_BT1_TSEG1_Msk (0x0F << CAN_BT1_TSEG1_Pos) +#define CAN_BT1_TSEG2_Pos 4 //t_tseg2 = CAN时间单位 * (TSEG2+1) +#define CAN_BT1_TSEG2_Msk (0x07 << CAN_BT1_TSEG2_Pos) +#define CAN_BT1_SAM_Pos 7 //采样次数 0: sampled once 1: sampled three times +#define CAN_BT1_SAM_Msk (0x01 << CAN_BT1_SAM_Pos) -#define CAN_BT1_TSEG1_Pos 0 //t_tseg1 = CAN时间单位 * (TSEG1+1) -#define CAN_BT1_TSEG1_Msk (0x0F << CAN_BT1_TSEG1_Pos) -#define CAN_BT1_TSEG2_Pos 4 //t_tseg2 = CAN时间单位 * (TSEG2+1) -#define CAN_BT1_TSEG2_Msk (0x07 << CAN_BT1_TSEG2_Pos) -#define CAN_BT1_SAM_Pos 7 //采样次数 0: sampled once 1: sampled three times -#define CAN_BT1_SAM_Msk (0x01 << CAN_BT1_SAM_Pos) +#define CAN_ECC_SEGCODE_Pos 0 //Segment Code +#define CAN_ECC_SEGCODE_Msk (0x1F << CAN_ECC_SEGCODE_Pos) +#define CAN_ECC_DIR_Pos 5 //0 error occurred during transmission 1 during reception +#define CAN_ECC_DIR_Msk (0x01 << CAN_ECC_DIR_Pos) +#define CAN_ECC_ERRCODE_Pos 6 //Error Code:0 Bit error 1 Form error 2 Stuff error 3 other error +#define CAN_ECC_ERRCODE_Msk (0x03 << CAN_ECC_ERRCODE_Pos) -#define CAN_ECC_SEGCODE_Pos 0 //Segment Code -#define CAN_ECC_SEGCODE_Msk (0x1F << CAN_ECC_SEGCODE_Pos) -#define CAN_ECC_DIR_Pos 5 //0 error occurred during transmission 1 during reception -#define CAN_ECC_DIR_Msk (0x01 << CAN_ECC_DIR_Pos) -#define CAN_ECC_ERRCODE_Pos 6 //Error Code:0 Bit error 1 Form error 2 Stuff error 3 other error -#define CAN_ECC_ERRCODE_Msk (0x03 << CAN_ECC_ERRCODE_Pos) +#define CAN_INFO_DLC_Pos 0 //Data Length Control +#define CAN_INFO_DLC_Msk (0x0F << CAN_INFO_DLC_Pos) +#define CAN_INFO_RTR_Pos 6 //Remote Frame,1 远程帧 0 数据帧 +#define CAN_INFO_RTR_Msk (0x01 << CAN_INFO_RTR_Pos) +#define CAN_INFO_FF_Pos 7 //Frame Format,0 标准帧格式 1 扩展帧格式 +#define CAN_INFO_FF_Msk (0x01 << CAN_INFO_FF_Pos) -#define CAN_INFO_DLC_Pos 0 //Data Length Control -#define CAN_INFO_DLC_Msk (0x0F << CAN_INFO_DLC_Pos) -#define CAN_INFO_RTR_Pos 6 //Remote Frame,1 远程帧 0 数据帧 -#define CAN_INFO_RTR_Msk (0x01 << CAN_INFO_RTR_Pos) -#define CAN_INFO_FF_Pos 7 //Frame Format,0 标准帧格式 1 扩展帧格式 -#define CAN_INFO_FF_Msk (0x01 << CAN_INFO_FF_Pos) +typedef struct +{ + __IO uint32_t IE; //[0] 为0的时候,IF[0]维持为0 + __IO uint32_t IF; //[0] 当完成指定长度的数据传输时置1,写1清零 + __IO uint32_t IM; //[0] 当该寄存器为1时,LCDC的中断不会输出给系统的中断控制寄存器 - -typedef struct { - __IO uint32_t IE; //[0] 为0的时候,IF[0]维持为0 - - __IO uint32_t IF; //[0] 当完成指定长度的数据传输时置1,写1清零 - - __IO uint32_t IM; //[0] 当该寄存器为1时,LCDC的中断不会输出给系统的中断控制寄存器 - __IO uint32_t START; - - __IO uint32_t SRCADDR; //数据源地址寄存器,必须字对齐(即地址的低2位必须是0) - + + __IO uint32_t SRCADDR; //数据源地址寄存器,必须字对齐(即地址的低2位必须是0) + __IO uint32_t CR0; - + __IO uint32_t CR1; - - __IO uint32_t PRECMDV; //在MPU接口中,发送数据前,RS拉低的那一拍,数据总线上的值 + + __IO uint32_t PRECMDV; //在MPU接口中,发送数据前,RS拉低的那一拍,数据总线上的值 } LCD_TypeDef; +#define LCD_START_GO_Pos 1 //写1开始传输数据,数据传输结束后自动清零 +#define LCD_START_GO_Msk (0x01 << LCD_START_GO_Pos) +#define LCD_START_BURST_Pos 2 +#define LCD_START_BURST_Msk (0x01 << LCD_START_BURST_Pos) -#define LCD_START_GO_Pos 1 //写1开始传输数据,数据传输结束后自动清零 -#define LCD_START_GO_Msk (0x01 << LCD_START_GO_Pos) -#define LCD_START_BURST_Pos 2 -#define LCD_START_BURST_Msk (0x01 << LCD_START_BURST_Pos) +#define LCD_CR0_VPIX_Pos 0 //当portrait为0时,表示垂直方向的像素个数,0表示1个,最大为767 \ + //当portrait为1时,表示水平方向的像素个数,0表示1个,最大为767 +#define LCD_CR0_VPIX_Msk (0x3FF << LCD_CR0_VPIX_Pos) +#define LCD_CR0_HPIX_Pos 10 //当portrait为0时,表示水平方向的像素个数,0表示1个,最大为1023 \ + //当portrait为1时,表示垂直方向的像素个数,0表示1个,最大为1023 +#define LCD_CR0_HPIX_Msk (0x3FF << LCD_CR0_HPIX_Pos) +#define LCD_CR0_DCLK_Pos 20 //0 DOTCLK一直翻转 1 DOTCLK在空闲时停在1 +#define LCD_CR0_DCLK_Msk (0x01 << LCD_CR0_DCLK_Pos) +#define LCD_CR0_HLOW_Pos 21 //输出HSYNC低电平持续多少个DOTCLK周期,0表示1个周期 +#define LCD_CR0_HLOW_Msk (0x03 << LCD_CR0_HLOW_Pos) -#define LCD_CR0_VPIX_Pos 0 //当portrait为0时,表示垂直方向的像素个数,0表示1个,最大为767 - //当portrait为1时,表示水平方向的像素个数,0表示1个,最大为767 -#define LCD_CR0_VPIX_Msk (0x3FF << LCD_CR0_VPIX_Pos) -#define LCD_CR0_HPIX_Pos 10 //当portrait为0时,表示水平方向的像素个数,0表示1个,最大为1023 - //当portrait为1时,表示垂直方向的像素个数,0表示1个,最大为1023 -#define LCD_CR0_HPIX_Msk (0x3FF << LCD_CR0_HPIX_Pos) -#define LCD_CR0_DCLK_Pos 20 //0 DOTCLK一直翻转 1 DOTCLK在空闲时停在1 -#define LCD_CR0_DCLK_Msk (0x01 << LCD_CR0_DCLK_Pos) -#define LCD_CR0_HLOW_Pos 21 //输出HSYNC低电平持续多少个DOTCLK周期,0表示1个周期 -#define LCD_CR0_HLOW_Msk (0x03 << LCD_CR0_HLOW_Pos) +#define LCD_CR1_VFP_Pos 1 +#define LCD_CR1_VFP_Msk (0x07 << LCD_CR1_VFP_Pos) +#define LCD_CR1_VBP_Pos 4 +#define LCD_CR1_VBP_Msk (0x1F << LCD_CR1_VBP_Pos) +#define LCD_CR1_HFP_Pos 9 +#define LCD_CR1_HFP_Msk (0x1F << LCD_CR1_HFP_Pos) +#define LCD_CR1_HBP_Pos 14 +#define LCD_CR1_HBP_Msk (0x7F << LCD_CR1_HBP_Pos) +#define LCD_CR1_DCLKDIV_Pos 21 //DOTCLK相对于模块时钟的分频比,0表示2分频,1表示4分频 ... +#define LCD_CR1_DCLKDIV_Msk (0x1F << LCD_CR1_DCLKDIV_Pos) +#define LCD_CR1_DCLKINV_Pos 26 //1 输出DOTCLK反向,应用于用DOTCLK下降沿采样数据的屏 +#define LCD_CR1_DCLKINV_Msk (0x01 << LCD_CR1_DCLKINV_Pos) -#define LCD_CR1_VFP_Pos 1 -#define LCD_CR1_VFP_Msk (0x07 << LCD_CR1_VFP_Pos) -#define LCD_CR1_VBP_Pos 4 -#define LCD_CR1_VBP_Msk (0x1F << LCD_CR1_VBP_Pos) -#define LCD_CR1_HFP_Pos 9 -#define LCD_CR1_HFP_Msk (0x1F << LCD_CR1_HFP_Pos) -#define LCD_CR1_HBP_Pos 14 -#define LCD_CR1_HBP_Msk (0x7F << LCD_CR1_HBP_Pos) -#define LCD_CR1_DCLKDIV_Pos 21 //DOTCLK相对于模块时钟的分频比,0表示2分频,1表示4分频 ... -#define LCD_CR1_DCLKDIV_Msk (0x1F << LCD_CR1_DCLKDIV_Pos) -#define LCD_CR1_DCLKINV_Pos 26 //1 输出DOTCLK反向,应用于用DOTCLK下降沿采样数据的屏 -#define LCD_CR1_DCLKINV_Msk (0x01 << LCD_CR1_DCLKINV_Pos) - - - - -typedef struct { +typedef struct +{ __IO uint32_t DMA_MEM_ADDR; - - __IO uint32_t BLK; //Block Size and Count - - __IO uint32_t ARG; //Argument - - __IO uint32_t CMD; //Command - - __IO uint32_t RESP[4]; //Response - + + __IO uint32_t BLK; //Block Size and Count + + __IO uint32_t ARG; //Argument + + __IO uint32_t CMD; //Command + + __IO uint32_t RESP[4]; //Response + __IO uint32_t DATA; - + __IO uint32_t STAT; - + __IO uint32_t CR1; - + __IO uint32_t CR2; - + __IO uint32_t IF; - - __IO uint32_t IFE; //Interrupt Flag Enable - - __IO uint32_t IE; //Interrupt Enalbe - + + __IO uint32_t IFE; //Interrupt Flag Enable + + __IO uint32_t IE; //Interrupt Enalbe + __IO uint32_t CMD12ERR; - + __IO uint32_t INFO; - + __IO uint32_t MAXCURR; } SDIO_TypeDef; +#define SDIO_BLK_SIZE_Pos 0 //0x200 512字节 0x400 1024字节 0x800 2048字节 +#define SDIO_BLK_SIZE_Msk (0xFFF << SDIO_BLK_SIZE_Pos) +#define SDIO_BLK_COUNT_Pos 16 //0 Stop Transfer 1 1块 2 2块 ... ... +#define SDIO_BLK_COUNT_Msk (0xFFF << SDIO_BLK_COUNT_Pos) -#define SDIO_BLK_SIZE_Pos 0 //0x200 512字节 0x400 1024字节 0x800 2048字节 -#define SDIO_BLK_SIZE_Msk (0xFFF << SDIO_BLK_SIZE_Pos) -#define SDIO_BLK_COUNT_Pos 16 //0 Stop Transfer 1 1块 2 2块 ... ... -#define SDIO_BLK_COUNT_Msk (0xFFF << SDIO_BLK_COUNT_Pos) +#define SDIO_CMD_DMAEN_Pos 0 +#define SDIO_CMD_DMAEN_Msk (0x01 << SDIO_CMD_DMAEN_Pos) +#define SDIO_CMD_BLKCNTEN_Pos 1 +#define SDIO_CMD_BLKCNTEN_Msk (0x01 << SDIO_CMD_BLKCNTEN_Pos) +#define SDIO_CMD_AUTOCMD12_Pos 2 +#define SDIO_CMD_AUTOCMD12_Msk (0x01 << SDIO_CMD_AUTOCMD12_Pos) +#define SDIO_CMD_DIRREAD_Pos 4 //0 Write, Host to Card 1 Read, Card to Host +#define SDIO_CMD_DIRREAD_Msk (0x01 << SDIO_CMD_DIRREAD_Pos) +#define SDIO_CMD_MULTBLK_Pos 5 //0 Single Block 1 Multiple Block +#define SDIO_CMD_MULTBLK_Msk (0x01 << SDIO_CMD_MULTBLK_Pos) +#define SDIO_CMD_RESPTYPE_Pos 16 //响应类型,0 无响应 1 136位响应 2 48位响应 3 48位响应,Busy after response +#define SDIO_CMD_RESPTYPE_Msk (0x03 << SDIO_CMD_RESPTYPE_Pos) +#define SDIO_CMD_CRCCHECK_Pos 19 //Command CRC Check Enable +#define SDIO_CMD_CRCCHECK_Msk (0x01 << SDIO_CMD_CRCCHECK_Pos) +#define SDIO_CMD_IDXCHECK_Pos 20 //Command Index Check Enable +#define SDIO_CMD_IDXCHECK_Msk (0x01 << SDIO_CMD_IDXCHECK_Pos) +#define SDIO_CMD_HAVEDATA_Pos 21 //0 No Data Present 1 Data Present +#define SDIO_CMD_HAVEDATA_Msk (0x01 << SDIO_CMD_HAVEDATA_Pos) +#define SDIO_CMD_CMDTYPE_Pos 22 //0 NORMAL 1 SUSPEND 2 RESUME 3 ABORT +#define SDIO_CMD_CMDTYPE_Msk (0x03 << SDIO_CMD_CMDTYPE_Pos) +#define SDIO_CMD_CMDINDX_Pos 24 //Command Index,CMD0-63、ACMD0-63 +#define SDIO_CMD_CMDINDX_Msk (0x3F << SDIO_CMD_CMDINDX_Pos) -#define SDIO_CMD_DMAEN_Pos 0 -#define SDIO_CMD_DMAEN_Msk (0x01 << SDIO_CMD_DMAEN_Pos) -#define SDIO_CMD_BLKCNTEN_Pos 1 -#define SDIO_CMD_BLKCNTEN_Msk (0x01 << SDIO_CMD_BLKCNTEN_Pos) -#define SDIO_CMD_AUTOCMD12_Pos 2 -#define SDIO_CMD_AUTOCMD12_Msk (0x01 << SDIO_CMD_AUTOCMD12_Pos) -#define SDIO_CMD_DIRREAD_Pos 4 //0 Write, Host to Card 1 Read, Card to Host -#define SDIO_CMD_DIRREAD_Msk (0x01 << SDIO_CMD_DIRREAD_Pos) -#define SDIO_CMD_MULTBLK_Pos 5 //0 Single Block 1 Multiple Block -#define SDIO_CMD_MULTBLK_Msk (0x01 << SDIO_CMD_MULTBLK_Pos) -#define SDIO_CMD_RESPTYPE_Pos 16 //响应类型,0 无响应 1 136位响应 2 48位响应 3 48位响应,Busy after response -#define SDIO_CMD_RESPTYPE_Msk (0x03 << SDIO_CMD_RESPTYPE_Pos) -#define SDIO_CMD_CRCCHECK_Pos 19 //Command CRC Check Enable -#define SDIO_CMD_CRCCHECK_Msk (0x01 << SDIO_CMD_CRCCHECK_Pos) -#define SDIO_CMD_IDXCHECK_Pos 20 //Command Index Check Enable -#define SDIO_CMD_IDXCHECK_Msk (0x01 << SDIO_CMD_IDXCHECK_Pos) -#define SDIO_CMD_HAVEDATA_Pos 21 //0 No Data Present 1 Data Present -#define SDIO_CMD_HAVEDATA_Msk (0x01 << SDIO_CMD_HAVEDATA_Pos) -#define SDIO_CMD_CMDTYPE_Pos 22 //0 NORMAL 1 SUSPEND 2 RESUME 3 ABORT -#define SDIO_CMD_CMDTYPE_Msk (0x03 << SDIO_CMD_CMDTYPE_Pos) -#define SDIO_CMD_CMDINDX_Pos 24 //Command Index,CMD0-63、ACMD0-63 -#define SDIO_CMD_CMDINDX_Msk (0x3F << SDIO_CMD_CMDINDX_Pos) +#define SDIO_CR1_4BIT_Pos 1 //1 4 bit mode 0 1 bit mode +#define SDIO_CR1_4BIT_Msk (0x01 << SDIO_CR1_4BIT_Pos) +#define SDIO_CR1_8BIT_Pos 5 //1 8 bit mode is selected 0 8 bit mode is not selected +#define SDIO_CR1_8BIT_Msk (0x01 << SDIO_CR1_8BIT_Pos) +#define SDIO_CR1_CDBIT_Pos 6 //0 No Card 1 Card Inserted +#define SDIO_CR1_CDBIT_Msk (0x01 << SDIO_CR1_CDBIT_Pos) +#define SDIO_CR1_CDSRC_Pos 7 //Card Detect Source, 1 CR1.CDBIT位 0 SD_Detect引脚 +#define SDIO_CR1_CDSRC_Msk (0x01 << SDIO_CR1_CDSRC_Pos) +#define SDIO_CR1_PWRON_Pos 8 //1 Power on 0 Power off +#define SDIO_CR1_PWRON_Msk (0x01 << SDIO_CR1_PWRON_Pos) +#define SDIO_CR1_VOLT_Pos 9 //7 3.3V 6 3.0V 5 1.8V +#define SDIO_CR1_VOLT_Msk (0x07 << SDIO_CR1_VOLT_Pos) -#define SDIO_CR1_4BIT_Pos 1 //1 4 bit mode 0 1 bit mode -#define SDIO_CR1_4BIT_Msk (0x01 << SDIO_CR1_4BIT_Pos) -#define SDIO_CR1_8BIT_Pos 5 //1 8 bit mode is selected 0 8 bit mode is not selected -#define SDIO_CR1_8BIT_Msk (0x01 << SDIO_CR1_8BIT_Pos) -#define SDIO_CR1_CDBIT_Pos 6 //0 No Card 1 Card Inserted -#define SDIO_CR1_CDBIT_Msk (0x01 << SDIO_CR1_CDBIT_Pos) -#define SDIO_CR1_CDSRC_Pos 7 //Card Detect Source, 1 CR1.CDBIT位 0 SD_Detect引脚 -#define SDIO_CR1_CDSRC_Msk (0x01 << SDIO_CR1_CDSRC_Pos) -#define SDIO_CR1_PWRON_Pos 8 //1 Power on 0 Power off -#define SDIO_CR1_PWRON_Msk (0x01 << SDIO_CR1_PWRON_Pos) -#define SDIO_CR1_VOLT_Pos 9 //7 3.3V 6 3.0V 5 1.8V -#define SDIO_CR1_VOLT_Msk (0x07 << SDIO_CR1_VOLT_Pos) +#define SDIO_CR2_CLKEN_Pos 0 //Internal Clock Enable +#define SDIO_CR2_CLKEN_Msk (0x01 << SDIO_CR2_CLKEN_Pos) +#define SDIO_CR2_CLKRDY_Pos 1 //Internal Clock Stable/Ready +#define SDIO_CR2_CLKRDY_Msk (0x01 << SDIO_CR2_CLKRDY_Pos) +#define SDIO_CR2_SDCLKEN_Pos 2 //SDCLK Enable +#define SDIO_CR2_SDCLKEN_Msk (0x01 << SDIO_CR2_SDCLKEN_Pos) +#define SDIO_CR2_SDCLKDIV_Pos 8 //SDCLK Frequency Div, 0x00 不分频 0x01 2分频 0x02 4分频 0x04 8分频 0x08 16分频 ... 0x80 256分频 +#define SDIO_CR2_SDCLKDIV_Msk (0xFF << SDIO_CR2_SDCLKDIV_Pos) +#define SDIO_CR2_TIMEOUT_Pos 16 //0 TMCLK*2^13 1 TMCLK*2^14 ... 14 TMCLK*2^27 +#define SDIO_CR2_TIMEOUT_Msk (0x0F << SDIO_CR2_TIMEOUT_Pos) +#define SDIO_CR2_RSTALL_Pos 24 //Software Reset for All +#define SDIO_CR2_RSTALL_Msk (0x01 << SDIO_CR2_RSTALL_Pos) +#define SDIO_CR2_RSTCMD_Pos 25 //Software Reset for CMD Line +#define SDIO_CR2_RSTCMD_Msk (0x01 << SDIO_CR2_RSTCMD_Pos) +#define SDIO_CR2_RSTDAT_Pos 26 //Software Reset for DAT Line +#define SDIO_CR2_RSTDAT_Msk (0x01 << SDIO_CR2_RSTDAT_Pos) -#define SDIO_CR2_CLKEN_Pos 0 //Internal Clock Enable -#define SDIO_CR2_CLKEN_Msk (0x01 << SDIO_CR2_CLKEN_Pos) -#define SDIO_CR2_CLKRDY_Pos 1 //Internal Clock Stable/Ready -#define SDIO_CR2_CLKRDY_Msk (0x01 << SDIO_CR2_CLKRDY_Pos) -#define SDIO_CR2_SDCLKEN_Pos 2 //SDCLK Enable -#define SDIO_CR2_SDCLKEN_Msk (0x01 << SDIO_CR2_SDCLKEN_Pos) -#define SDIO_CR2_SDCLKDIV_Pos 8 //SDCLK Frequency Div, 0x00 不分频 0x01 2分频 0x02 4分频 0x04 8分频 0x08 16分频 ... 0x80 256分频 -#define SDIO_CR2_SDCLKDIV_Msk (0xFF << SDIO_CR2_SDCLKDIV_Pos) -#define SDIO_CR2_TIMEOUT_Pos 16 //0 TMCLK*2^13 1 TMCLK*2^14 ... 14 TMCLK*2^27 -#define SDIO_CR2_TIMEOUT_Msk (0x0F << SDIO_CR2_TIMEOUT_Pos) -#define SDIO_CR2_RSTALL_Pos 24 //Software Reset for All -#define SDIO_CR2_RSTALL_Msk (0x01 << SDIO_CR2_RSTALL_Pos) -#define SDIO_CR2_RSTCMD_Pos 25 //Software Reset for CMD Line -#define SDIO_CR2_RSTCMD_Msk (0x01 << SDIO_CR2_RSTCMD_Pos) -#define SDIO_CR2_RSTDAT_Pos 26 //Software Reset for DAT Line -#define SDIO_CR2_RSTDAT_Msk (0x01 << SDIO_CR2_RSTDAT_Pos) +#define SDIO_IF_CMDDONE_Pos 0 +#define SDIO_IF_CMDDONE_Msk (0x01 << SDIO_IF_CMDDONE_Pos) +#define SDIO_IF_TRXDONE_Pos 1 +#define SDIO_IF_TRXDONE_Msk (0x01 << SDIO_IF_TRXDONE_Pos) +#define SDIO_IF_BLKGAP_Pos 2 +#define SDIO_IF_BLKGAP_Msk (0x01 << SDIO_IF_BLKGAP_Pos) +#define SDIO_IF_DMADONE_Pos 3 +#define SDIO_IF_DMADONE_Msk (0x01 << SDIO_IF_DMADONE_Pos) +#define SDIO_IF_BUFWRRDY_Pos 4 +#define SDIO_IF_BUFWRRDY_Msk (0x01 << SDIO_IF_BUFWRRDY_Pos) +#define SDIO_IF_BUFRDRDY_Pos 5 +#define SDIO_IF_BUFRDRDY_Msk (0x01 << SDIO_IF_BUFRDRDY_Pos) +#define SDIO_IF_CARDINSR_Pos 6 +#define SDIO_IF_CARDINSR_Msk (0x01 << SDIO_IF_CARDINSR_Pos) +#define SDIO_IF_CARDRMOV_Pos 7 +#define SDIO_IF_CARDRMOV_Msk (0x01 << SDIO_IF_CARDRMOV_Pos) +#define SDIO_IF_CARD_Pos 8 +#define SDIO_IF_CARD_Msk (0x01 << SDIO_IF_CARD_Pos) +#define SDIO_IF_ERROR_Pos 15 +#define SDIO_IF_ERROR_Msk (0x01 << SDIO_IF_ERROR_Pos) +#define SDIO_IF_CMDTIMEOUT_Pos 16 +#define SDIO_IF_CMDTIMEOUT_Msk (0x01 << SDIO_IF_CMDTIMEOUT_Pos) +#define SDIO_IF_CMDCRCERR_Pos 17 +#define SDIO_IF_CMDCRCERR_Msk (0x01 << SDIO_IF_CMDCRCERR_Pos) +#define SDIO_IF_CMDENDERR_Pos 18 +#define SDIO_IF_CMDENDERR_Msk (0x01 << SDIO_IF_CMDENDCERR_Pos) +#define SDIO_IF_CMDIDXERR_Pos 19 +#define SDIO_IF_CMDIDXERR_Msk (0x01 << SDIO_IF_CMDIDXCERR_Pos) +#define SDIO_IF_DATTIMEOUT_Pos 20 +#define SDIO_IF_DATTIMEOUT_Msk (0x01 << SDIO_IF_DATTIMEOUT_Pos) +#define SDIO_IF_DATCRCERR_Pos 21 +#define SDIO_IF_DATCRCERR_Msk (0x01 << SDIO_IF_DATCRCERR_Pos) +#define SDIO_IF_DATENDERR_Pos 22 +#define SDIO_IF_DATENDERR_Msk (0x01 << SDIO_IF_DATENDCERR_Pos) +#define SDIO_IF_CURLIMERR_Pos 23 +#define SDIO_IF_CURLIMERR_Msk (0x01 << SDIO_IF_CURLIMERR_Pos) +#define SDIO_IF_CMD12ERR_Pos 24 +#define SDIO_IF_CMD12ERR_Msk (0x01 << SDIO_IF_CMD12ERR_Pos) +#define SDIO_IF_DMAERR_Pos 25 +#define SDIO_IF_DMAERR_Msk (0x01 << SDIO_IF_DMAERR_Pos) +#define SDIO_IF_RESPERR_Pos 28 +#define SDIO_IF_RESPERR_Msk (0x01 << SDIO_IF_RESPERR_Pos) -#define SDIO_IF_CMDDONE_Pos 0 -#define SDIO_IF_CMDDONE_Msk (0x01 << SDIO_IF_CMDDONE_Pos) -#define SDIO_IF_TRXDONE_Pos 1 -#define SDIO_IF_TRXDONE_Msk (0x01 << SDIO_IF_TRXDONE_Pos) -#define SDIO_IF_BLKGAP_Pos 2 -#define SDIO_IF_BLKGAP_Msk (0x01 << SDIO_IF_BLKGAP_Pos) -#define SDIO_IF_DMADONE_Pos 3 -#define SDIO_IF_DMADONE_Msk (0x01 << SDIO_IF_DMADONE_Pos) -#define SDIO_IF_BUFWRRDY_Pos 4 -#define SDIO_IF_BUFWRRDY_Msk (0x01 << SDIO_IF_BUFWRRDY_Pos) -#define SDIO_IF_BUFRDRDY_Pos 5 -#define SDIO_IF_BUFRDRDY_Msk (0x01 << SDIO_IF_BUFRDRDY_Pos) -#define SDIO_IF_CARDINSR_Pos 6 -#define SDIO_IF_CARDINSR_Msk (0x01 << SDIO_IF_CARDINSR_Pos) -#define SDIO_IF_CARDRMOV_Pos 7 -#define SDIO_IF_CARDRMOV_Msk (0x01 << SDIO_IF_CARDRMOV_Pos) -#define SDIO_IF_CARD_Pos 8 -#define SDIO_IF_CARD_Msk (0x01 << SDIO_IF_CARD_Pos) -#define SDIO_IF_ERROR_Pos 15 -#define SDIO_IF_ERROR_Msk (0x01 << SDIO_IF_ERROR_Pos) -#define SDIO_IF_CMDTIMEOUT_Pos 16 -#define SDIO_IF_CMDTIMEOUT_Msk (0x01 << SDIO_IF_CMDTIMEOUT_Pos) -#define SDIO_IF_CMDCRCERR_Pos 17 -#define SDIO_IF_CMDCRCERR_Msk (0x01 << SDIO_IF_CMDCRCERR_Pos) -#define SDIO_IF_CMDENDERR_Pos 18 -#define SDIO_IF_CMDENDERR_Msk (0x01 << SDIO_IF_CMDENDCERR_Pos) -#define SDIO_IF_CMDIDXERR_Pos 19 -#define SDIO_IF_CMDIDXERR_Msk (0x01 << SDIO_IF_CMDIDXCERR_Pos) -#define SDIO_IF_DATTIMEOUT_Pos 20 -#define SDIO_IF_DATTIMEOUT_Msk (0x01 << SDIO_IF_DATTIMEOUT_Pos) -#define SDIO_IF_DATCRCERR_Pos 21 -#define SDIO_IF_DATCRCERR_Msk (0x01 << SDIO_IF_DATCRCERR_Pos) -#define SDIO_IF_DATENDERR_Pos 22 -#define SDIO_IF_DATENDERR_Msk (0x01 << SDIO_IF_DATENDCERR_Pos) -#define SDIO_IF_CURLIMERR_Pos 23 -#define SDIO_IF_CURLIMERR_Msk (0x01 << SDIO_IF_CURLIMERR_Pos) -#define SDIO_IF_CMD12ERR_Pos 24 -#define SDIO_IF_CMD12ERR_Msk (0x01 << SDIO_IF_CMD12ERR_Pos) -#define SDIO_IF_DMAERR_Pos 25 -#define SDIO_IF_DMAERR_Msk (0x01 << SDIO_IF_DMAERR_Pos) -#define SDIO_IF_RESPERR_Pos 28 -#define SDIO_IF_RESPERR_Msk (0x01 << SDIO_IF_RESPERR_Pos) +#define SDIO_IE_CMDDONE_Pos 0 //Command Complete Status Enable +#define SDIO_IE_CMDDONE_Msk (0x01 << SDIO_IE_CMDDONE_Pos) +#define SDIO_IE_TRXDONE_Pos 1 //Transfer Complete Status Enable +#define SDIO_IE_TRXDONE_Msk (0x01 << SDIO_IE_TRXDONE_Pos) +#define SDIO_IE_BLKGAP_Pos 2 //Block Gap Event Status Enable +#define SDIO_IE_BLKGAP_Msk (0x01 << SDIO_IE_BLKGAP_Pos) +#define SDIO_IE_DMADONE_Pos 3 //DMA Interrupt Status Enable +#define SDIO_IE_DMADONE_Msk (0x01 << SDIO_IE_DMADONE_Pos) +#define SDIO_IE_BUFWRRDY_Pos 4 //Buffer Write Ready Status Enable +#define SDIO_IE_BUFWRRDY_Msk (0x01 << SDIO_IE_BUFWRRDY_Pos) +#define SDIO_IE_BUFRDRDY_Pos 5 //Buffer Read Ready Status Enable +#define SDIO_IE_BUFRDRDY_Msk (0x01 << SDIO_IE_BUFRDRDY_Pos) +#define SDIO_IE_CARDINSR_Pos 6 //Card Insertion Status Enable +#define SDIO_IE_CARDINSR_Msk (0x01 << SDIO_IE_CARDINSR_Pos) +#define SDIO_IE_CARDRMOV_Pos 7 //Card Removal Status Enable +#define SDIO_IE_CARDRMOV_Msk (0x01 << SDIO_IE_CARDRMOV_Pos) +#define SDIO_IE_CARD_Pos 8 +#define SDIO_IE_CARD_Msk (0x01 << SDIO_IE_CARD_Pos) +#define SDIO_IE_CMDTIMEOUT_Pos 16 //Command Timeout Error Status Enable +#define SDIO_IE_CMDTIMEOUT_Msk (0x01 << SDIO_IE_CMDTIMEOUT_Pos) +#define SDIO_IE_CMDCRCERR_Pos 17 //Command CRC Error Status Enable +#define SDIO_IE_CMDCRCERR_Msk (0x01 << SDIO_IE_CMDCRCERR_Pos) +#define SDIO_IE_CMDENDERR_Pos 18 //Command End Bit Error Status Enable +#define SDIO_IE_CMDENDERR_Msk (0x01 << SDIO_IE_CMDENDCERR_Pos) +#define SDIO_IE_CMDIDXERR_Pos 19 //Command Index Error Status Enable +#define SDIO_IE_CMDIDXERR_Msk (0x01 << SDIO_IE_CMDIDXCERR_Pos) +#define SDIO_IE_DATTIMEOUT_Pos 20 //Data Timeout Error Status Enable +#define SDIO_IE_DATTIMEOUT_Msk (0x01 << SDIO_IE_DATTIMEOUT_Pos) +#define SDIO_IE_DATCRCERR_Pos 21 //Data CRC Error Status Enable +#define SDIO_IE_DATCRCERR_Msk (0x01 << SDIO_IE_DATCRCERR_Pos) +#define SDIO_IE_DATENDERR_Pos 22 //Data End Bit Error Status Enable +#define SDIO_IE_DATENDERR_Msk (0x01 << SDIO_IE_DATENDCERR_Pos) +#define SDIO_IE_CURLIMERR_Pos 23 //Current Limit Error Status Enable +#define SDIO_IE_CURLIMERR_Msk (0x01 << SDIO_IE_CURLIMERR_Pos) +#define SDIO_IE_CMD12ERR_Pos 24 //Auto CMD12 Error Status Enable +#define SDIO_IE_CMD12ERR_Msk (0x01 << SDIO_IE_CMD12ERR_Pos) +#define SDIO_IE_DMAERR_Pos 25 //ADMA Error Status Enable +#define SDIO_IE_DMAERR_Msk (0x01 << SDIO_IE_DMAERR_Pos) +#define SDIO_IE_RESPERR_Pos 28 //Target Response Error Status Enable +#define SDIO_IE_RESPERR_Msk (0x01 << SDIO_IE_RESPERR_Pos) -#define SDIO_IE_CMDDONE_Pos 0 //Command Complete Status Enable -#define SDIO_IE_CMDDONE_Msk (0x01 << SDIO_IE_CMDDONE_Pos) -#define SDIO_IE_TRXDONE_Pos 1 //Transfer Complete Status Enable -#define SDIO_IE_TRXDONE_Msk (0x01 << SDIO_IE_TRXDONE_Pos) -#define SDIO_IE_BLKGAP_Pos 2 //Block Gap Event Status Enable -#define SDIO_IE_BLKGAP_Msk (0x01 << SDIO_IE_BLKGAP_Pos) -#define SDIO_IE_DMADONE_Pos 3 //DMA Interrupt Status Enable -#define SDIO_IE_DMADONE_Msk (0x01 << SDIO_IE_DMADONE_Pos) -#define SDIO_IE_BUFWRRDY_Pos 4 //Buffer Write Ready Status Enable -#define SDIO_IE_BUFWRRDY_Msk (0x01 << SDIO_IE_BUFWRRDY_Pos) -#define SDIO_IE_BUFRDRDY_Pos 5 //Buffer Read Ready Status Enable -#define SDIO_IE_BUFRDRDY_Msk (0x01 << SDIO_IE_BUFRDRDY_Pos) -#define SDIO_IE_CARDINSR_Pos 6 //Card Insertion Status Enable -#define SDIO_IE_CARDINSR_Msk (0x01 << SDIO_IE_CARDINSR_Pos) -#define SDIO_IE_CARDRMOV_Pos 7 //Card Removal Status Enable -#define SDIO_IE_CARDRMOV_Msk (0x01 << SDIO_IE_CARDRMOV_Pos) -#define SDIO_IE_CARD_Pos 8 -#define SDIO_IE_CARD_Msk (0x01 << SDIO_IE_CARD_Pos) -#define SDIO_IE_CMDTIMEOUT_Pos 16 //Command Timeout Error Status Enable -#define SDIO_IE_CMDTIMEOUT_Msk (0x01 << SDIO_IE_CMDTIMEOUT_Pos) -#define SDIO_IE_CMDCRCERR_Pos 17 //Command CRC Error Status Enable -#define SDIO_IE_CMDCRCERR_Msk (0x01 << SDIO_IE_CMDCRCERR_Pos) -#define SDIO_IE_CMDENDERR_Pos 18 //Command End Bit Error Status Enable -#define SDIO_IE_CMDENDERR_Msk (0x01 << SDIO_IE_CMDENDCERR_Pos) -#define SDIO_IE_CMDIDXERR_Pos 19 //Command Index Error Status Enable -#define SDIO_IE_CMDIDXERR_Msk (0x01 << SDIO_IE_CMDIDXCERR_Pos) -#define SDIO_IE_DATTIMEOUT_Pos 20 //Data Timeout Error Status Enable -#define SDIO_IE_DATTIMEOUT_Msk (0x01 << SDIO_IE_DATTIMEOUT_Pos) -#define SDIO_IE_DATCRCERR_Pos 21 //Data CRC Error Status Enable -#define SDIO_IE_DATCRCERR_Msk (0x01 << SDIO_IE_DATCRCERR_Pos) -#define SDIO_IE_DATENDERR_Pos 22 //Data End Bit Error Status Enable -#define SDIO_IE_DATENDERR_Msk (0x01 << SDIO_IE_DATENDCERR_Pos) -#define SDIO_IE_CURLIMERR_Pos 23 //Current Limit Error Status Enable -#define SDIO_IE_CURLIMERR_Msk (0x01 << SDIO_IE_CURLIMERR_Pos) -#define SDIO_IE_CMD12ERR_Pos 24 //Auto CMD12 Error Status Enable -#define SDIO_IE_CMD12ERR_Msk (0x01 << SDIO_IE_CMD12ERR_Pos) -#define SDIO_IE_DMAERR_Pos 25 //ADMA Error Status Enable -#define SDIO_IE_DMAERR_Msk (0x01 << SDIO_IE_DMAERR_Pos) -#define SDIO_IE_RESPERR_Pos 28 //Target Response Error Status Enable -#define SDIO_IE_RESPERR_Msk (0x01 << SDIO_IE_RESPERR_Pos) +#define SDIO_IM_CMDDONE_Pos 0 +#define SDIO_IM_CMDDONE_Msk (0x01 << SDIO_IM_CMDDONE_Pos) +#define SDIO_IM_TRXDONE_Pos 1 +#define SDIO_IM_TRXDONE_Msk (0x01 << SDIO_IM_TRXDONE_Pos) +#define SDIO_IM_BLKGAP_Pos 2 +#define SDIO_IM_BLKGAP_Msk (0x01 << SDIO_IM_BLKGAP_Pos) +#define SDIO_IM_DMADONE_Pos 3 +#define SDIO_IM_DMADONE_Msk (0x01 << SDIO_IM_DMADONE_Pos) +#define SDIO_IM_BUFWRRDY_Pos 4 +#define SDIO_IM_BUFWRRDY_Msk (0x01 << SDIO_IM_BUFWRRDY_Pos) +#define SDIO_IM_BUFRDRDY_Pos 5 +#define SDIO_IM_BUFRDRDY_Msk (0x01 << SDIO_IM_BUFRDRDY_Pos) +#define SDIO_IM_CARDINSR_Pos 6 +#define SDIO_IM_CARDINSR_Msk (0x01 << SDIO_IM_CARDINSR_Pos) +#define SDIO_IM_CARDRMOV_Pos 7 +#define SDIO_IM_CARDRMOV_Msk (0x01 << SDIO_IM_CARDRMOV_Pos) +#define SDIO_IM_CARD_Pos 8 +#define SDIO_IM_CARD_Msk (0x01 << SDIO_IM_CARD_Pos) +#define SDIO_IM_CMDTIMEOUT_Pos 16 +#define SDIO_IM_CMDTIMEOUT_Msk (0x01 << SDIO_IM_CMDTIMEOUT_Pos) +#define SDIO_IM_CMDCRCERR_Pos 17 +#define SDIO_IM_CMDCRCERR_Msk (0x01 << SDIO_IM_CMDCRCERR_Pos) +#define SDIO_IM_CMDENDERR_Pos 18 +#define SDIO_IM_CMDENDERR_Msk (0x01 << SDIO_IM_CMDENDCERR_Pos) +#define SDIO_IM_CMDIDXERR_Pos 19 +#define SDIO_IM_CMDIDXERR_Msk (0x01 << SDIO_IM_CMDIDXCERR_Pos) +#define SDIO_IM_DATTIMEOUT_Pos 20 +#define SDIO_IM_DATTIMEOUT_Msk (0x01 << SDIO_IM_DATTIMEOUT_Pos) +#define SDIO_IM_DATCRCERR_Pos 21 +#define SDIO_IM_DATCRCERR_Msk (0x01 << SDIO_IM_DATCRCERR_Pos) +#define SDIO_IM_DATENDERR_Pos 22 +#define SDIO_IM_DATENDERR_Msk (0x01 << SDIO_IM_DATENDCERR_Pos) +#define SDIO_IM_CURLIMERR_Pos 23 +#define SDIO_IM_CURLIMERR_Msk (0x01 << SDIO_IM_CURLIMERR_Pos) +#define SDIO_IM_CMD12ERR_Pos 24 +#define SDIO_IM_CMD12ERR_Msk (0x01 << SDIO_IM_CMD12ERR_Pos) +#define SDIO_IM_DMAERR_Pos 25 +#define SDIO_IM_DMAERR_Msk (0x01 << SDIO_IM_DMAERR_Pos) +#define SDIO_IM_RESPERR_Pos 28 +#define SDIO_IM_RESPERR_Msk (0x01 << SDIO_IM_RESPERR_Pos) -#define SDIO_IM_CMDDONE_Pos 0 -#define SDIO_IM_CMDDONE_Msk (0x01 << SDIO_IM_CMDDONE_Pos) -#define SDIO_IM_TRXDONE_Pos 1 -#define SDIO_IM_TRXDONE_Msk (0x01 << SDIO_IM_TRXDONE_Pos) -#define SDIO_IM_BLKGAP_Pos 2 -#define SDIO_IM_BLKGAP_Msk (0x01 << SDIO_IM_BLKGAP_Pos) -#define SDIO_IM_DMADONE_Pos 3 -#define SDIO_IM_DMADONE_Msk (0x01 << SDIO_IM_DMADONE_Pos) -#define SDIO_IM_BUFWRRDY_Pos 4 -#define SDIO_IM_BUFWRRDY_Msk (0x01 << SDIO_IM_BUFWRRDY_Pos) -#define SDIO_IM_BUFRDRDY_Pos 5 -#define SDIO_IM_BUFRDRDY_Msk (0x01 << SDIO_IM_BUFRDRDY_Pos) -#define SDIO_IM_CARDINSR_Pos 6 -#define SDIO_IM_CARDINSR_Msk (0x01 << SDIO_IM_CARDINSR_Pos) -#define SDIO_IM_CARDRMOV_Pos 7 -#define SDIO_IM_CARDRMOV_Msk (0x01 << SDIO_IM_CARDRMOV_Pos) -#define SDIO_IM_CARD_Pos 8 -#define SDIO_IM_CARD_Msk (0x01 << SDIO_IM_CARD_Pos) -#define SDIO_IM_CMDTIMEOUT_Pos 16 -#define SDIO_IM_CMDTIMEOUT_Msk (0x01 << SDIO_IM_CMDTIMEOUT_Pos) -#define SDIO_IM_CMDCRCERR_Pos 17 -#define SDIO_IM_CMDCRCERR_Msk (0x01 << SDIO_IM_CMDCRCERR_Pos) -#define SDIO_IM_CMDENDERR_Pos 18 -#define SDIO_IM_CMDENDERR_Msk (0x01 << SDIO_IM_CMDENDCERR_Pos) -#define SDIO_IM_CMDIDXERR_Pos 19 -#define SDIO_IM_CMDIDXERR_Msk (0x01 << SDIO_IM_CMDIDXCERR_Pos) -#define SDIO_IM_DATTIMEOUT_Pos 20 -#define SDIO_IM_DATTIMEOUT_Msk (0x01 << SDIO_IM_DATTIMEOUT_Pos) -#define SDIO_IM_DATCRCERR_Pos 21 -#define SDIO_IM_DATCRCERR_Msk (0x01 << SDIO_IM_DATCRCERR_Pos) -#define SDIO_IM_DATENDERR_Pos 22 -#define SDIO_IM_DATENDERR_Msk (0x01 << SDIO_IM_DATENDCERR_Pos) -#define SDIO_IM_CURLIMERR_Pos 23 -#define SDIO_IM_CURLIMERR_Msk (0x01 << SDIO_IM_CURLIMERR_Pos) -#define SDIO_IM_CMD12ERR_Pos 24 -#define SDIO_IM_CMD12ERR_Msk (0x01 << SDIO_IM_CMD12ERR_Pos) -#define SDIO_IM_DMAERR_Pos 25 -#define SDIO_IM_DMAERR_Msk (0x01 << SDIO_IM_DMAERR_Pos) -#define SDIO_IM_RESPERR_Pos 28 -#define SDIO_IM_RESPERR_Msk (0x01 << SDIO_IM_RESPERR_Pos) - - - - -typedef struct { - __IO uint32_t DATA; - __IO uint32_t ADDR; - __IO uint32_t ERASE; - __IO uint32_t CACHE; - __IO uint32_t CFG0; - __IO uint32_t CFG1; - __IO uint32_t CFG2; - __IO uint32_t CFG3; - __IO uint32_t STAT; +typedef struct +{ + __IO uint32_t DATA; + __IO uint32_t ADDR; + __IO uint32_t ERASE; + __IO uint32_t CACHE; + __IO uint32_t CFG0; + __IO uint32_t CFG1; + __IO uint32_t CFG2; + __IO uint32_t CFG3; + __IO uint32_t STAT; } FLASH_Typedef; +#define FLASH_ERASE_REQ_Pos 31 +#define FLASH_ERASE_REQ_Msk (0x01u << FLASH_ERASE_REQ_Pos) -#define FLASH_ERASE_REQ_Pos 31 -#define FLASH_ERASE_REQ_Msk (0x01u<< FLASH_ERASE_REQ_Pos) +#define FLASH_CACHE_PROG_Pos 2 +#define FLASH_CACHE_PROG_Msk (0x01 << FLASH_CACHE_PROG_Pos) +#define FLASH_CACHE_CLEAR_Pos 3 +#define FLASH_CACHE_CLEAR_Msk (0x01 << FLASH_CACHE_CLEAR_Pos) -#define FLASH_CACHE_PROG_Pos 2 -#define FLASH_CACHE_PROG_Msk (0x01 << FLASH_CACHE_PROG_Pos) -#define FLASH_CACHE_CLEAR_Pos 3 -#define FLASH_CACHE_CLEAR_Msk (0x01 << FLASH_CACHE_CLEAR_Pos) +#define FLASH_STAT_ERASE_GOING_Pos 0 +#define FLASH_STAT_ERASE_GOING_Msk (0X01 << FLASH_STAT_ERASE_GOING_Pos) +#define FLASH_STAT_PROG_GOING_Pos 1 +#define FLASH_STAT_PROG_GOING_Msk (0x01 << FLASH_STAT_PROG_GOING_Pos) +#define FALSH_STAT_FIFO_EMPTY_Pos 3 +#define FLASH_STAT_FIFO_EMPTY_Msk (0x01 << FALSH_STAT_FIFO_EMPTY_Pos) +#define FALSH_STAT_FIFO_FULL_Pos 4 +#define FLASH_STAT_FIFO_FULL_Msk (0x01 << FALSH_STAT_FIFO_FULL_Pos) -#define FLASH_STAT_ERASE_GOING_Pos 0 -#define FLASH_STAT_ERASE_GOING_Msk (0X01 << FLASH_STAT_ERASE_GOING_Pos) -#define FLASH_STAT_PROG_GOING_Pos 1 -#define FLASH_STAT_PROG_GOING_Msk (0x01 << FLASH_STAT_PROG_GOING_Pos) -#define FALSH_STAT_FIFO_EMPTY_Pos 3 -#define FLASH_STAT_FIFO_EMPTY_Msk (0x01 << FALSH_STAT_FIFO_EMPTY_Pos) -#define FALSH_STAT_FIFO_FULL_Pos 4 -#define FLASH_STAT_FIFO_FULL_Msk (0x01 << FALSH_STAT_FIFO_FULL_Pos) - - - - -typedef struct { +typedef struct +{ __IO uint32_t CR; } SRAMC_TypeDef; +#define SRAMC_CR_RWTIME_Pos 0 //读写操作持续多少个时钟周期。0表示1个时钟周期。最小设置为4 +#define SRAMC_CR_RWTIME_Msk (0x0F << SRAMC_CR_RWTIME_Pos) +#define SRAMC_CR_BYTEIF_Pos 4 //外部SRAM数据宽度,0 16位 1 8位 +#define SRAMC_CR_BYTEIF_Msk (0x01 << SRAMC_CR_BYTEIF_Pos) +#define SRAMC_CR_HBLBDIS_Pos 5 //1 ADDR[23:22]为地址线 0 ADDR[23]为高字节使能,ADDR[22]为低字节使能 +#define SRAMC_CR_HBLBDIS_Msk (0x01 << SRAMC_CR_HBLBDIS_Pos) -#define SRAMC_CR_RWTIME_Pos 0 //读写操作持续多少个时钟周期。0表示1个时钟周期。最小设置为4 -#define SRAMC_CR_RWTIME_Msk (0x0F << SRAMC_CR_RWTIME_Pos) -#define SRAMC_CR_BYTEIF_Pos 4 //外部SRAM数据宽度,0 16位 1 8位 -#define SRAMC_CR_BYTEIF_Msk (0x01 << SRAMC_CR_BYTEIF_Pos) -#define SRAMC_CR_HBLBDIS_Pos 5 //1 ADDR[23:22]为地址线 0 ADDR[23]为高字节使能,ADDR[22]为低字节使能 -#define SRAMC_CR_HBLBDIS_Msk (0x01 << SRAMC_CR_HBLBDIS_Pos) - - - -typedef struct { +typedef struct +{ __IO uint32_t CR0; - + __IO uint32_t CR1; - + __IO uint32_t REFRESH; - - __IO uint32_t NOPNUM; //[15:0] 初始化完成后,在正常操作之前,发送多少个NOP命令 - + + __IO uint32_t NOPNUM; //[15:0] 初始化完成后,在正常操作之前,发送多少个NOP命令 + __IO uint32_t LATCH; - - __IO uint32_t REFDONE; //[0] Frefresh Done,上电初始化完成 + + __IO uint32_t REFDONE; //[0] Frefresh Done,上电初始化完成 } SDRAMC_TypeDef; +#define SDRAMC_CR0_BURSTLEN_Pos 0 //必须取2,表示Burst Length为4 +#define SDRAMC_CR0_BURSTLEN_Msk (0x07 << SDRAMC_CR0_BURSTLEN_Pos) +#define SDRAMC_CR0_CASDELAY_Pos 4 //CAS Latency, 2 2 3 3 +#define SDRAMC_CR0_CASDELAY_Msk (0x07 << SDRAMC_CR0_CASDELAY_Pos) -#define SDRAMC_CR0_BURSTLEN_Pos 0 //必须取2,表示Burst Length为4 -#define SDRAMC_CR0_BURSTLEN_Msk (0x07 << SDRAMC_CR0_BURSTLEN_Pos) -#define SDRAMC_CR0_CASDELAY_Pos 4 //CAS Latency, 2 2 3 3 -#define SDRAMC_CR0_CASDELAY_Msk (0x07 << SDRAMC_CR0_CASDELAY_Pos) +#define SDRAMC_CR1_TRP_Pos 0 +#define SDRAMC_CR1_TRP_Msk (0x07 << SDRAMC_CR1_TRP_Pos) +#define SDRAMC_CR1_TRCD_Pos 3 +#define SDRAMC_CR1_TRCD_Msk (0x07 << SDRAMC_CR1_TRCD_Pos) +#define SDRAMC_CR1_TRC_Pos 6 +#define SDRAMC_CR1_TRC_Msk (0x0F << SDRAMC_CR1_TRC_Pos) +#define SDRAMC_CR1_TRAS_Pos 10 +#define SDRAMC_CR1_TRAS_Msk (0x07 << SDRAMC_CR1_TRAS_Pos) +#define SDRAMC_CR1_TRRD_Pos 13 +#define SDRAMC_CR1_TRRD_Msk (0x03 << SDRAMC_CR1_TRRD_Pos) +#define SDRAMC_CR1_TMRD_Pos 15 +#define SDRAMC_CR1_TMRD_Msk (0x07 << SDRAMC_CR1_TMRD_Pos) +#define SDRAMC_CR1_32BIT_Pos 18 //SDRAMC的接口数据位宽,1 32bit 0 16bit +#define SDRAMC_CR1_32BIT_Msk (0x01 << SDRAMC_CR1_32BIT_Pos) +#define SDRAMC_CR1_BANK_Pos 19 //SDRAM每个颗粒有几个bank,0 2 banks 1 4 banks +#define SDRAMC_CR1_BANK_Msk (0x01 << SDRAMC_CR1_BANK_Pos) +#define SDRAMC_CR1_CELL32BIT_Pos 20 //SDRAM颗粒的位宽,1 32bit 0 16bit +#define SDRAMC_CR1_CELL32BIT_Msk (0x01 << SDRAMC_CR1_CELL32BIT_Pos) +#define SDRAMC_CR1_CELLSIZE_Pos 21 //SDRAM颗粒的容量,0 64Mb 1 128Mb 2 256Mb 3 16Mb +#define SDRAMC_CR1_CELLSIZE_Msk (0x03 << SDRAMC_CR1_CELLSIZE_Pos) +#define SDRAMC_CR1_HIGHSPEED_Pos 23 //当hclk大于100MHz时,这一位必须配置为1,否则为0 +#define SDRAMC_CR1_HIGHSPEED_Msk (0x01 << SDRAMC_CR1_HIGHSPEED_Pos) -#define SDRAMC_CR1_TRP_Pos 0 -#define SDRAMC_CR1_TRP_Msk (0x07 << SDRAMC_CR1_TRP_Pos) -#define SDRAMC_CR1_TRCD_Pos 3 -#define SDRAMC_CR1_TRCD_Msk (0x07 << SDRAMC_CR1_TRCD_Pos) -#define SDRAMC_CR1_TRC_Pos 6 -#define SDRAMC_CR1_TRC_Msk (0x0F << SDRAMC_CR1_TRC_Pos) -#define SDRAMC_CR1_TRAS_Pos 10 -#define SDRAMC_CR1_TRAS_Msk (0x07 << SDRAMC_CR1_TRAS_Pos) -#define SDRAMC_CR1_TRRD_Pos 13 -#define SDRAMC_CR1_TRRD_Msk (0x03 << SDRAMC_CR1_TRRD_Pos) -#define SDRAMC_CR1_TMRD_Pos 15 -#define SDRAMC_CR1_TMRD_Msk (0x07 << SDRAMC_CR1_TMRD_Pos) -#define SDRAMC_CR1_32BIT_Pos 18 //SDRAMC的接口数据位宽,1 32bit 0 16bit -#define SDRAMC_CR1_32BIT_Msk (0x01 << SDRAMC_CR1_32BIT_Pos) -#define SDRAMC_CR1_BANK_Pos 19 //SDRAM每个颗粒有几个bank,0 2 banks 1 4 banks -#define SDRAMC_CR1_BANK_Msk (0x01 << SDRAMC_CR1_BANK_Pos) -#define SDRAMC_CR1_CELL32BIT_Pos 20 //SDRAM颗粒的位宽,1 32bit 0 16bit -#define SDRAMC_CR1_CELL32BIT_Msk (0x01 << SDRAMC_CR1_CELL32BIT_Pos) -#define SDRAMC_CR1_CELLSIZE_Pos 21 //SDRAM颗粒的容量,0 64Mb 1 128Mb 2 256Mb 3 16Mb -#define SDRAMC_CR1_CELLSIZE_Msk (0x03 << SDRAMC_CR1_CELLSIZE_Pos) -#define SDRAMC_CR1_HIGHSPEED_Pos 23 //当hclk大于100MHz时,这一位必须配置为1,否则为0 -#define SDRAMC_CR1_HIGHSPEED_Msk (0x01 << SDRAMC_CR1_HIGHSPEED_Pos) +#define SDRAMC_REFRESH_RATE_Pos 0 +#define SDRAMC_REFRESH_RATE_Msk (0xFFF << SDRAMC_REFRESH_RATE_Pos) +#define SDRAMC_REFRESH_EN_Pos 12 +#define SDRAMC_REFRESH_EN_Msk (0x01 << SDRAMC_REFRESH_EN_Pos) -#define SDRAMC_REFRESH_RATE_Pos 0 -#define SDRAMC_REFRESH_RATE_Msk (0xFFF << SDRAMC_REFRESH_RATE_Pos) -#define SDRAMC_REFRESH_EN_Pos 12 -#define SDRAMC_REFRESH_EN_Msk (0x01 << SDRAMC_REFRESH_EN_Pos) +#define SDRAMC_LATCH_INEDGE_Pos 0 //哪个沿来锁存从SDRAM中读回的数据,0 上升沿 1 下降沿 +#define SDRAMC_LATCH_INEDGE_Msk (0x01 << SDRAMC_LATCH_INEDGE_Pos) +#define SDRAMC_LATCH_OUTEDGE_Pos 1 //哪个沿去锁存送给SDRAM的数据,1 上升沿 0 下降沿 +#define SDRAMC_LATCH_OUTEDGE_Msk (0x01 << SDRAMC_LATCH_OUTEDGE_Pos) +#define SDRAMC_LATCH_WAITST_Pos 2 +#define SDRAMC_LATCH_WAITST_Msk (0x01 << SDRAMC_LATCH_WAITST_Pos) -#define SDRAMC_LATCH_INEDGE_Pos 0 //哪个沿来锁存从SDRAM中读回的数据,0 上升沿 1 下降沿 -#define SDRAMC_LATCH_INEDGE_Msk (0x01 << SDRAMC_LATCH_INEDGE_Pos) -#define SDRAMC_LATCH_OUTEDGE_Pos 1 //哪个沿去锁存送给SDRAM的数据,1 上升沿 0 下降沿 -#define SDRAMC_LATCH_OUTEDGE_Msk (0x01 << SDRAMC_LATCH_OUTEDGE_Pos) -#define SDRAMC_LATCH_WAITST_Pos 2 -#define SDRAMC_LATCH_WAITST_Msk (0x01 << SDRAMC_LATCH_WAITST_Pos) - - - - -typedef struct { +typedef struct +{ __IO uint32_t IE; - - __IO uint32_t IF; //写1清零 - + + __IO uint32_t IF; //写1清零 + __IO uint32_t IM; - + __IO uint32_t CR; - + __IO uint32_t ADDR; - + __IO uint32_t CMD; } NORFLC_TypeDef; +#define NORFLC_IE_FINISH_Pos 0 +#define NORFLC_IE_FINISH_Msk (0x01 << NORFLC_IE_FINISH_Pos) +#define NORFLC_IE_TIMEOUT_Pos 1 +#define NORFLC_IE_TIMEOUT_Msk (0x01 << NORFLC_IE_TIMEOUT_Pos) -#define NORFLC_IE_FINISH_Pos 0 -#define NORFLC_IE_FINISH_Msk (0x01 << NORFLC_IE_FINISH_Pos) -#define NORFLC_IE_TIMEOUT_Pos 1 -#define NORFLC_IE_TIMEOUT_Msk (0x01 << NORFLC_IE_TIMEOUT_Pos) +#define NORFLC_IF_FINISH_Pos 0 +#define NORFLC_IF_FINISH_Msk (0x01 << NORFLC_IF_FINISH_Pos) +#define NORFLC_IF_TIMEOUT_Pos 1 +#define NORFLC_IF_TIMEOUT_Msk (0x01 << NORFLC_IF_TIMEOUT_Pos) -#define NORFLC_IF_FINISH_Pos 0 -#define NORFLC_IF_FINISH_Msk (0x01 << NORFLC_IF_FINISH_Pos) -#define NORFLC_IF_TIMEOUT_Pos 1 -#define NORFLC_IF_TIMEOUT_Msk (0x01 << NORFLC_IF_TIMEOUT_Pos) +#define NORFLC_IM_FINISH_Pos 0 +#define NORFLC_IM_FINISH_Msk (0x01 << NORFLC_IM_FINISH_Pos) +#define NORFLC_IM_TIMEOUT_Pos 1 +#define NORFLC_IM_TIMEOUT_Msk (0x01 << NORFLC_IM_TIMEOUT_Pos) -#define NORFLC_IM_FINISH_Pos 0 -#define NORFLC_IM_FINISH_Msk (0x01 << NORFLC_IM_FINISH_Pos) -#define NORFLC_IM_TIMEOUT_Pos 1 -#define NORFLC_IM_TIMEOUT_Msk (0x01 << NORFLC_IM_TIMEOUT_Pos) +#define NORFLC_CR_RDTIME_Pos 0 //Oen下降沿后多少个时钟周期后采样读回的数据。0表示1个时钟周期 +#define NORFLC_CR_RDTIME_Msk (0x1F << NORFLC_CR_RDTIME_Pos) +#define NORFLC_CR_WRTIME_Pos 5 //输出Wen的低电平宽度。0表示1个时钟周期 +#define NORFLC_CR_WRTIME_Msk (0x07 << NORFLC_CR_WRTIME_Pos) +#define NORFLC_CR_BYTEIF_Pos 8 //外部NOR FLASH数据宽度,1 8位 0 16位 +#define NORFLC_CR_BYTEIF_Msk (0x01 << NORFLC_CR_BYTEIF_Pos) -#define NORFLC_CR_RDTIME_Pos 0 //Oen下降沿后多少个时钟周期后采样读回的数据。0表示1个时钟周期 -#define NORFLC_CR_RDTIME_Msk (0x1F << NORFLC_CR_RDTIME_Pos) -#define NORFLC_CR_WRTIME_Pos 5 //输出Wen的低电平宽度。0表示1个时钟周期 -#define NORFLC_CR_WRTIME_Msk (0x07 << NORFLC_CR_WRTIME_Pos) -#define NORFLC_CR_BYTEIF_Pos 8 //外部NOR FLASH数据宽度,1 8位 0 16位 -#define NORFLC_CR_BYTEIF_Msk (0x01 << NORFLC_CR_BYTEIF_Pos) +#define NORFLC_CMD_DATA_Pos 0 //在PROGRAM命令中,DATA是要写入NOR FLASH的数据;在READ命令中,DATA是从NOR FLASH读回的数据 +#define NORFLC_CMD_DATA_Msk (0xFFFF << NORFLC_CMD_DATA_Pos) +#define NORFLC_CMD_CMD_Pos 16 //需要执行的命令,0 READ 1 RESET 2 AUTOMATIC SELECT 3 PROGRAM 4 CHIP ERASE 5 SECTOR ERASE +#define NORFLC_CMD_CMD_Msk (0x07 << NORFLC_CMD_CMD_Pos) -#define NORFLC_CMD_DATA_Pos 0 //在PROGRAM命令中,DATA是要写入NOR FLASH的数据;在READ命令中,DATA是从NOR FLASH读回的数据 -#define NORFLC_CMD_DATA_Msk (0xFFFF << NORFLC_CMD_DATA_Pos) -#define NORFLC_CMD_CMD_Pos 16 //需要执行的命令,0 READ 1 RESET 2 AUTOMATIC SELECT 3 PROGRAM 4 CHIP ERASE 5 SECTOR ERASE -#define NORFLC_CMD_CMD_Msk (0x07 << NORFLC_CMD_CMD_Pos) - - - - -typedef struct { +typedef struct +{ __IO uint32_t CR; - - __O uint32_t DATAIN; - + + __O uint32_t DATAIN; + __IO uint32_t INIVAL; - - __I uint32_t RESULT; + + __I uint32_t RESULT; } CRC_TypeDef; +#define CRC_CR_EN_Pos 0 +#define CRC_CR_EN_Msk (0x01 << CRC_CR_EN_Pos) +#define CRC_CR_OREV_Pos 1 //输出结果是否翻转 +#define CRC_CR_OREV_Msk (0x01 << CRC_CR_OREV_Pos) +#define CRC_CR_ONOT_Pos 2 //输出结果是否取反 +#define CRC_CR_ONOT_Msk (0x01 << CRC_CR_ONOT_Pos) +#define CRC_CR_CRC16_Pos 3 //1 CRC16 0 CRC32 +#define CRC_CR_CRC16_Msk (0x01 << CRC_CR_CRC16_Pos) +#define CRC_CR_IBITS_Pos 4 //输入数据有效位数 0 32位 1 16位 2 8位 +#define CRC_CR_IBITS_Msk (0x03 << CRC_CR_IBITS_Pos) -#define CRC_CR_EN_Pos 0 -#define CRC_CR_EN_Msk (0x01 << CRC_CR_EN_Pos) -#define CRC_CR_OREV_Pos 1 //输出结果是否翻转 -#define CRC_CR_OREV_Msk (0x01 << CRC_CR_OREV_Pos) -#define CRC_CR_ONOT_Pos 2 //输出结果是否取反 -#define CRC_CR_ONOT_Msk (0x01 << CRC_CR_ONOT_Pos) -#define CRC_CR_CRC16_Pos 3 //1 CRC16 0 CRC32 -#define CRC_CR_CRC16_Msk (0x01 << CRC_CR_CRC16_Pos) -#define CRC_CR_IBITS_Pos 4 //输入数据有效位数 0 32位 1 16位 2 8位 -#define CRC_CR_IBITS_Msk (0x03 << CRC_CR_IBITS_Pos) +typedef struct +{ + __IO uint32_t MINSEC; //分秒计数 + __IO uint32_t DATHUR; //日时计数 + __IO uint32_t MONDAY; //月周计数 + __IO uint32_t YEAR; //[11:0] 年计数,支持1901-2199 + + __IO uint32_t MINSECAL; //分秒闹铃设置 + + __IO uint32_t DAYHURAL; //周时闹铃设置 + + __IO uint32_t LOAD; //将设置寄存器中的值同步到RTC中,同步完成自动清零 -typedef struct { - __IO uint32_t MINSEC; //分秒计数 - - __IO uint32_t DATHUR; //日时计数 - - __IO uint32_t MONDAY; //月周计数 - - __IO uint32_t YEAR; //[11:0] 年计数,支持1901-2199 - - __IO uint32_t MINSECAL; //分秒闹铃设置 - - __IO uint32_t DAYHURAL; //周时闹铃设置 - - __IO uint32_t LOAD; //将设置寄存器中的值同步到RTC中,同步完成自动清零 - __IO uint32_t IE; - - __IO uint32_t IF; //写1清零 - - __IO uint32_t EN; //[0] 1 RTC使能 - - __IO uint32_t CFGABLE; //[0] 1 RTC可配置 - - __IO uint32_t TRIM; //时钟调整 - - __IO uint32_t TRIMM; //时钟微调整 + + __IO uint32_t IF; //写1清零 + + __IO uint32_t EN; //[0] 1 RTC使能 + + __IO uint32_t CFGABLE; //[0] 1 RTC可配置 + + __IO uint32_t TRIM; //时钟调整 + + __IO uint32_t TRIMM; //时钟微调整 } RTC_TypeDef; +#define RTC_LOAD_TIME_Pos 0 +#define RTC_LOAD_TIME_Msk (0x01 << RTC_LOAD_TIME_Pos) +#define RTC_LOAD_ALARM_Pos 1 +#define RTC_LOAD_ALARM_Msk (0x01 << RTC_LOAD_ALARM_Pos) -#define RTC_LOAD_TIME_Pos 0 -#define RTC_LOAD_TIME_Msk (0x01 << RTC_LOAD_TIME_Pos) -#define RTC_LOAD_ALARM_Pos 1 -#define RTC_LOAD_ALARM_Msk (0x01 << RTC_LOAD_ALARM_Pos) +#define RTC_MINSEC_SEC_Pos 0 //秒计数,取值0--59 +#define RTC_MINSEC_SEC_Msk (0x3F << RTC_MINSEC_SEC_Pos) +#define RTC_MINSEC_MIN_Pos 6 //分钟计数,取值0--59 +#define RTC_MINSEC_MIN_Msk (0x3F << RTC_MINSEC_MIN_Pos) -#define RTC_MINSEC_SEC_Pos 0 //秒计数,取值0--59 -#define RTC_MINSEC_SEC_Msk (0x3F << RTC_MINSEC_SEC_Pos) -#define RTC_MINSEC_MIN_Pos 6 //分钟计数,取值0--59 -#define RTC_MINSEC_MIN_Msk (0x3F << RTC_MINSEC_MIN_Pos) +#define RTC_DATHUR_HOUR_Pos 0 //小时计数,取值0--23 +#define RTC_DATHUR_HOUR_Msk (0x1F << RTC_DATHUR_HOUR_Pos) +#define RTC_DATHUR_DATE_Pos 5 //date of month,取值1--31 +#define RTC_DATHUR_DATE_Msk (0x1F << RTC_DATHUR_DATE_Pos) -#define RTC_DATHUR_HOUR_Pos 0 //小时计数,取值0--23 -#define RTC_DATHUR_HOUR_Msk (0x1F << RTC_DATHUR_HOUR_Pos) -#define RTC_DATHUR_DATE_Pos 5 //date of month,取值1--31 -#define RTC_DATHUR_DATE_Msk (0x1F << RTC_DATHUR_DATE_Pos) +#define RTC_MONDAY_DAY_Pos 0 //day of week,取值0--6 +#define RTC_MONDAY_DAY_Msk (0x07 << RTC_MONDAY_DAY_Pos) +#define RTC_MONDAY_MON_Pos 3 //月份计数,取值1--12 +#define RTC_MONDAY_MON_Msk (0x0F << RTC_MONDAY_MON_Pos) -#define RTC_MONDAY_DAY_Pos 0 //day of week,取值0--6 -#define RTC_MONDAY_DAY_Msk (0x07 << RTC_MONDAY_DAY_Pos) -#define RTC_MONDAY_MON_Pos 3 //月份计数,取值1--12 -#define RTC_MONDAY_MON_Msk (0x0F << RTC_MONDAY_MON_Pos) +#define RTC_MINSECAL_SEC_Pos 0 //闹钟秒设置 +#define RTC_MINSECAL_SEC_Msk (0x3F << RTC_MINSECAL_SEC_Pos) +#define RTC_MINSECAL_MIN_Pos 6 //闹钟分钟设置 +#define RTC_MINSECAL_MIN_Msk (0x3F << RTC_MINSECAL_MIN_Pos) -#define RTC_MINSECAL_SEC_Pos 0 //闹钟秒设置 -#define RTC_MINSECAL_SEC_Msk (0x3F << RTC_MINSECAL_SEC_Pos) -#define RTC_MINSECAL_MIN_Pos 6 //闹钟分钟设置 -#define RTC_MINSECAL_MIN_Msk (0x3F << RTC_MINSECAL_MIN_Pos) +#define RTC_DAYHURAL_HOUR_Pos 0 //闹钟小时设置 +#define RTC_DAYHURAL_HOUR_Msk (0x1F << RTC_DAYHURAL_HOUR_Pos) +#define RTC_DAYHURAL_SUN_Pos 5 //周日闹钟有效 +#define RTC_DAYHURAL_SUN_Msk (0x01 << RTC_DAYHURAL_SUN_Pos) +#define RTC_DAYHURAL_MON_Pos 6 //周一闹钟有效 +#define RTC_DAYHURAL_MON_Msk (0x01 << RTC_DAYHURAL_MON_Pos) +#define RTC_DAYHURAL_TUE_Pos 7 //周二闹钟有效 +#define RTC_DAYHURAL_TUE_Msk (0x01 << RTC_DAYHURAL_TUE_Pos) +#define RTC_DAYHURAL_WED_Pos 8 //周三闹钟有效 +#define RTC_DAYHURAL_WED_Msk (0x01 << RTC_DAYHURAL_WED_Pos) +#define RTC_DAYHURAL_THU_Pos 9 //周四闹钟有效 +#define RTC_DAYHURAL_THU_Msk (0x01 << RTC_DAYHURAL_THU_Pos) +#define RTC_DAYHURAL_FRI_Pos 10 //周五闹钟有效 +#define RTC_DAYHURAL_FRI_Msk (0x01 << RTC_DAYHURAL_FRI_Pos) +#define RTC_DAYHURAL_SAT_Pos 11 //周六闹钟有效 +#define RTC_DAYHURAL_SAT_Msk (0x01 << RTC_DAYHURAL_SAT_Pos) -#define RTC_DAYHURAL_HOUR_Pos 0 //闹钟小时设置 -#define RTC_DAYHURAL_HOUR_Msk (0x1F << RTC_DAYHURAL_HOUR_Pos) -#define RTC_DAYHURAL_SUN_Pos 5 //周日闹钟有效 -#define RTC_DAYHURAL_SUN_Msk (0x01 << RTC_DAYHURAL_SUN_Pos) -#define RTC_DAYHURAL_MON_Pos 6 //周一闹钟有效 -#define RTC_DAYHURAL_MON_Msk (0x01 << RTC_DAYHURAL_MON_Pos) -#define RTC_DAYHURAL_TUE_Pos 7 //周二闹钟有效 -#define RTC_DAYHURAL_TUE_Msk (0x01 << RTC_DAYHURAL_TUE_Pos) -#define RTC_DAYHURAL_WED_Pos 8 //周三闹钟有效 -#define RTC_DAYHURAL_WED_Msk (0x01 << RTC_DAYHURAL_WED_Pos) -#define RTC_DAYHURAL_THU_Pos 9 //周四闹钟有效 -#define RTC_DAYHURAL_THU_Msk (0x01 << RTC_DAYHURAL_THU_Pos) -#define RTC_DAYHURAL_FRI_Pos 10 //周五闹钟有效 -#define RTC_DAYHURAL_FRI_Msk (0x01 << RTC_DAYHURAL_FRI_Pos) -#define RTC_DAYHURAL_SAT_Pos 11 //周六闹钟有效 -#define RTC_DAYHURAL_SAT_Msk (0x01 << RTC_DAYHURAL_SAT_Pos) +#define RTC_IE_SEC_Pos 0 //秒中断使能 +#define RTC_IE_SEC_Msk (0x01 << RTC_IE_SEC_Pos) +#define RTC_IE_MIN_Pos 1 +#define RTC_IE_MIN_Msk (0x01 << RTC_IE_MIN_Pos) +#define RTC_IE_HOUR_Pos 2 +#define RTC_IE_HOUR_Msk (0x01 << RTC_IE_HOUR_Pos) +#define RTC_IE_DATE_Pos 3 +#define RTC_IE_DATE_Msk (0x01 << RTC_IE_DATE_Pos) +#define RTC_IE_ALARM_Pos 4 +#define RTC_IE_ALARM_Msk (0x01 << RTC_IE_ALARM_Pos) -#define RTC_IE_SEC_Pos 0 //秒中断使能 -#define RTC_IE_SEC_Msk (0x01 << RTC_IE_SEC_Pos) -#define RTC_IE_MIN_Pos 1 -#define RTC_IE_MIN_Msk (0x01 << RTC_IE_MIN_Pos) -#define RTC_IE_HOUR_Pos 2 -#define RTC_IE_HOUR_Msk (0x01 << RTC_IE_HOUR_Pos) -#define RTC_IE_DATE_Pos 3 -#define RTC_IE_DATE_Msk (0x01 << RTC_IE_DATE_Pos) -#define RTC_IE_ALARM_Pos 4 -#define RTC_IE_ALARM_Msk (0x01 << RTC_IE_ALARM_Pos) +#define RTC_IF_SEC_Pos 0 //写1清零 +#define RTC_IF_SEC_Msk (0x01 << RTC_IF_SEC_Pos) +#define RTC_IF_MIN_Pos 1 +#define RTC_IF_MIN_Msk (0x01 << RTC_IF_MIN_Pos) +#define RTC_IF_HOUR_Pos 2 +#define RTC_IF_HOUR_Msk (0x01 << RTC_IF_HOUR_Pos) +#define RTC_IF_DATE_Pos 3 +#define RTC_IF_DATE_Msk (0x01 << RTC_IF_DATE_Pos) +#define RTC_IF_ALARM_Pos 4 +#define RTC_IF_ALARM_Msk (0x01 << RTC_IF_ALARM_Pos) -#define RTC_IF_SEC_Pos 0 //写1清零 -#define RTC_IF_SEC_Msk (0x01 << RTC_IF_SEC_Pos) -#define RTC_IF_MIN_Pos 1 -#define RTC_IF_MIN_Msk (0x01 << RTC_IF_MIN_Pos) -#define RTC_IF_HOUR_Pos 2 -#define RTC_IF_HOUR_Msk (0x01 << RTC_IF_HOUR_Pos) -#define RTC_IF_DATE_Pos 3 -#define RTC_IF_DATE_Msk (0x01 << RTC_IF_DATE_Pos) -#define RTC_IF_ALARM_Pos 4 -#define RTC_IF_ALARM_Msk (0x01 << RTC_IF_ALARM_Pos) +#define RTC_TRIM_ADJ_Pos 0 //用于调整BASECNT的计数周期,默认为32768,如果DEC为1,则计数周期调整为32768-ADJ,否则调整为32768+ADJ +#define RTC_TRIM_ADJ_Msk (0xFF << RTC_TRIM_ADJ_Pos) +#define RTC_TRIM_DEC_Pos 8 +#define RTC_TRIM_DEC_Msk (0x01 << RTC_TRIM_DEC_Pos) -#define RTC_TRIM_ADJ_Pos 0 //用于调整BASECNT的计数周期,默认为32768,如果DEC为1,则计数周期调整为32768-ADJ,否则调整为32768+ADJ -#define RTC_TRIM_ADJ_Msk (0xFF << RTC_TRIM_ADJ_Pos) -#define RTC_TRIM_DEC_Pos 8 -#define RTC_TRIM_DEC_Msk (0x01 << RTC_TRIM_DEC_Pos) +#define RTC_TRIMM_CYCLE_Pos 0 //用于计数周期微调,如果INC为1,则第n个计数周期调整为(32768±ADJ)+1,否则调整为(32768±ADJ)-1 \ + //cycles=0时,不进行微调整;cycles=1,则n为2;cycles=7,则n为8;以此类推 +#define RTC_TRIMM_CYCLE_Msk (0x07 << RTC_TRIMM_CYCLE_Pos) +#define RTC_TRIMM_INC_Pos 3 +#define RTC_TRIMM_INC_Msk (0x01 << RTC_TRIMM_INC_Pos) -#define RTC_TRIMM_CYCLE_Pos 0 //用于计数周期微调,如果INC为1,则第n个计数周期调整为(32768±ADJ)+1,否则调整为(32768±ADJ)-1 - //cycles=0时,不进行微调整;cycles=1,则n为2;cycles=7,则n为8;以此类推 -#define RTC_TRIMM_CYCLE_Msk (0x07 << RTC_TRIMM_CYCLE_Pos) -#define RTC_TRIMM_INC_Pos 3 -#define RTC_TRIMM_INC_Msk (0x01 << RTC_TRIMM_INC_Pos) +typedef struct +{ + __IO uint32_t LOAD; //喂狗使计数器装载LOAD值 + __I uint32_t VALUE; + __IO uint32_t CR; + __IO uint32_t IF; //计数到0时硬件置位,软件写1清除标志 -typedef struct { - __IO uint32_t LOAD; //喂狗使计数器装载LOAD值 - - __I uint32_t VALUE; - - __IO uint32_t CR; - - __IO uint32_t IF; //计数到0时硬件置位,软件写1清除标志 - - __IO uint32_t FEED; //写0x55喂狗 + __IO uint32_t FEED; //写0x55喂狗 } WDT_TypeDef; - -#define WDT_CR_EN_Pos 0 -#define WDT_CR_EN_Msk (0x01 << WDT_CR_EN_Pos) -#define WDT_CR_RSTEN_Pos 1 -#define WDT_CR_RSTEN_Msk (0x01 << WDT_CR_RSTEN_Pos) - +#define WDT_CR_EN_Pos 0 +#define WDT_CR_EN_Msk (0x01 << WDT_CR_EN_Pos) +#define WDT_CR_RSTEN_Pos 1 +#define WDT_CR_RSTEN_Msk (0x01 << WDT_CR_RSTEN_Pos) /******************************************************************************/ /* Peripheral memory map */ /******************************************************************************/ -#define RAM_BASE 0x20000000 -#define AHB_BASE 0x40000000 -#define APB_BASE 0x40010000 +#define RAM_BASE 0x20000000 +#define AHB_BASE 0x40000000 +#define APB_BASE 0x40010000 -#define NORFLC_BASE 0x60000000 -#define NORFLM_BASE 0x61000000 +#define NORFLC_BASE 0x60000000 +#define NORFLM_BASE 0x61000000 -#define SRAMC_BASE 0x68000000 -#define SRAMM_BASE 0x69000000 +#define SRAMC_BASE 0x68000000 +#define SRAMM_BASE 0x69000000 -#define SDRAMC_BASE 0x78000000 -#define SDRAMM_BASE 0x70000000 +#define SDRAMC_BASE 0x78000000 +#define SDRAMM_BASE 0x70000000 /* AHB Peripheral memory map */ -#define SYS_BASE (AHB_BASE + 0x00000) +#define SYS_BASE (AHB_BASE + 0x00000) -#define DMA_BASE (AHB_BASE + 0x01000) +#define DMA_BASE (AHB_BASE + 0x01000) -#define LCD_BASE (AHB_BASE + 0x02000) +#define LCD_BASE (AHB_BASE + 0x02000) -#define CRC_BASE (AHB_BASE + 0x03000) +#define CRC_BASE (AHB_BASE + 0x03000) -#define SDIO_BASE (AHB_BASE + 0x04000) +#define SDIO_BASE (AHB_BASE + 0x04000) /* APB Peripheral memory map */ -#define PORT_BASE (APB_BASE + 0x00000) +#define PORT_BASE (APB_BASE + 0x00000) -#define GPIOA_BASE (APB_BASE + 0x01000) -#define GPIOB_BASE (APB_BASE + 0x02000) -#define GPIOC_BASE (APB_BASE + 0x03000) -#define GPIOD_BASE (APB_BASE + 0x04000) -#define GPIOM_BASE (APB_BASE + 0x05000) -#define GPION_BASE (APB_BASE + 0x06000) -#define GPIOP_BASE (APB_BASE + 0x08000) +#define GPIOA_BASE (APB_BASE + 0x01000) +#define GPIOB_BASE (APB_BASE + 0x02000) +#define GPIOC_BASE (APB_BASE + 0x03000) +#define GPIOD_BASE (APB_BASE + 0x04000) +#define GPIOM_BASE (APB_BASE + 0x05000) +#define GPION_BASE (APB_BASE + 0x06000) +#define GPIOP_BASE (APB_BASE + 0x08000) -#define TIMR0_BASE (APB_BASE + 0x07000) -#define TIMR1_BASE (APB_BASE + 0x0700C) -#define TIMR2_BASE (APB_BASE + 0x07018) -#define TIMR3_BASE (APB_BASE + 0x07024) -#define TIMR4_BASE (APB_BASE + 0x07030) -#define TIMR5_BASE (APB_BASE + 0x0703C) -#define TIMRG_BASE (APB_BASE + 0x07060) +#define TIMR0_BASE (APB_BASE + 0x07000) +#define TIMR1_BASE (APB_BASE + 0x0700C) +#define TIMR2_BASE (APB_BASE + 0x07018) +#define TIMR3_BASE (APB_BASE + 0x07024) +#define TIMR4_BASE (APB_BASE + 0x07030) +#define TIMR5_BASE (APB_BASE + 0x0703C) +#define TIMRG_BASE (APB_BASE + 0x07060) -#define WDT_BASE (APB_BASE + 0x09000) +#define WDT_BASE (APB_BASE + 0x09000) -#define PWM0_BASE (APB_BASE + 0x0A000) -#define PWM1_BASE (APB_BASE + 0x0A020) -#define PWM2_BASE (APB_BASE + 0x0A040) -#define PWM3_BASE (APB_BASE + 0x0A060) -#define PWM4_BASE (APB_BASE + 0x0A080) -#define PWM5_BASE (APB_BASE + 0x0A0A0) -#define PWMG_BASE (APB_BASE + 0x0A180) +#define PWM0_BASE (APB_BASE + 0x0A000) +#define PWM1_BASE (APB_BASE + 0x0A020) +#define PWM2_BASE (APB_BASE + 0x0A040) +#define PWM3_BASE (APB_BASE + 0x0A060) +#define PWM4_BASE (APB_BASE + 0x0A080) +#define PWM5_BASE (APB_BASE + 0x0A0A0) +#define PWMG_BASE (APB_BASE + 0x0A180) -#define RTC_BASE (APB_BASE + 0x0B000) +#define RTC_BASE (APB_BASE + 0x0B000) -#define ADC0_BASE (APB_BASE + 0x0C000) -#define ADC1_BASE (APB_BASE + 0x0D000) +#define ADC0_BASE (APB_BASE + 0x0C000) +#define ADC1_BASE (APB_BASE + 0x0D000) -#define FLASH_BASE (APB_BASE + 0x0F000) +#define FLASH_BASE (APB_BASE + 0x0F000) -#define UART0_BASE (APB_BASE + 0x10000) -#define UART1_BASE (APB_BASE + 0x11000) -#define UART2_BASE (APB_BASE + 0x12000) -#define UART3_BASE (APB_BASE + 0x13000) +#define UART0_BASE (APB_BASE + 0x10000) +#define UART1_BASE (APB_BASE + 0x11000) +#define UART2_BASE (APB_BASE + 0x12000) +#define UART3_BASE (APB_BASE + 0x13000) -#define I2C0_BASE (APB_BASE + 0x18000) -#define I2C1_BASE (APB_BASE + 0x19000) +#define I2C0_BASE (APB_BASE + 0x18000) +#define I2C1_BASE (APB_BASE + 0x19000) -#define SPI0_BASE (APB_BASE + 0x1C000) -#define SPI1_BASE (APB_BASE + 0x1D000) - -#define CAN_BASE (APB_BASE + 0x20000) +#define SPI0_BASE (APB_BASE + 0x1C000) +#define SPI1_BASE (APB_BASE + 0x1D000) +#define CAN_BASE (APB_BASE + 0x20000) /******************************************************************************/ /* Peripheral declaration */ /******************************************************************************/ -#define SYS ((SYS_TypeDef *) SYS_BASE) +#define SYS ((SYS_TypeDef *)SYS_BASE) -#define PORT ((PORT_TypeDef *) PORT_BASE) +#define PORT ((PORT_TypeDef *)PORT_BASE) -#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) -#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) -#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) -#define GPIOM ((GPIO_TypeDef *) GPIOM_BASE) -#define GPION ((GPIO_TypeDef *) GPION_BASE) -#define GPIOP ((GPIO_TypeDef *) GPIOP_BASE) +#define GPIOA ((GPIO_TypeDef *)GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *)GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *)GPIOC_BASE) +#define GPIOM ((GPIO_TypeDef *)GPIOM_BASE) +#define GPION ((GPIO_TypeDef *)GPION_BASE) +#define GPIOP ((GPIO_TypeDef *)GPIOP_BASE) -#define TIMR0 ((TIMR_TypeDef *) TIMR0_BASE) -#define TIMR1 ((TIMR_TypeDef *) TIMR1_BASE) -#define TIMR2 ((TIMR_TypeDef *) TIMR2_BASE) -#define TIMR3 ((TIMR_TypeDef *) TIMR3_BASE) -#define TIMR4 ((TIMR_TypeDef *) TIMR4_BASE) -#define TIMR5 ((TIMR_TypeDef *) TIMR5_BASE) -#define TIMRG ((TIMRG_TypeDef*) TIMRG_BASE) +#define TIMR0 ((TIMR_TypeDef *)TIMR0_BASE) +#define TIMR1 ((TIMR_TypeDef *)TIMR1_BASE) +#define TIMR2 ((TIMR_TypeDef *)TIMR2_BASE) +#define TIMR3 ((TIMR_TypeDef *)TIMR3_BASE) +#define TIMR4 ((TIMR_TypeDef *)TIMR4_BASE) +#define TIMR5 ((TIMR_TypeDef *)TIMR5_BASE) +#define TIMRG ((TIMRG_TypeDef *)TIMRG_BASE) -#define UART0 ((UART_TypeDef *) UART0_BASE) -#define UART1 ((UART_TypeDef *) UART1_BASE) -#define UART2 ((UART_TypeDef *) UART2_BASE) -#define UART3 ((UART_TypeDef *) UART3_BASE) +#define UART0 ((UART_TypeDef *)UART0_BASE) +#define UART1 ((UART_TypeDef *)UART1_BASE) +#define UART2 ((UART_TypeDef *)UART2_BASE) +#define UART3 ((UART_TypeDef *)UART3_BASE) -#define SPI0 ((SPI_TypeDef *) SPI0_BASE) -#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define SPI0 ((SPI_TypeDef *)SPI0_BASE) +#define SPI1 ((SPI_TypeDef *)SPI1_BASE) -#define I2C0 ((I2C_TypeDef *) I2C0_BASE) -#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C0 ((I2C_TypeDef *)I2C0_BASE) +#define I2C1 ((I2C_TypeDef *)I2C1_BASE) -#define ADC0 ((ADC_TypeDef *) ADC0_BASE) -#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC0 ((ADC_TypeDef *)ADC0_BASE) +#define ADC1 ((ADC_TypeDef *)ADC1_BASE) -#define PWM0 ((PWM_TypeDef *) PWM0_BASE) -#define PWM1 ((PWM_TypeDef *) PWM1_BASE) -#define PWM2 ((PWM_TypeDef *) PWM2_BASE) -#define PWM3 ((PWM_TypeDef *) PWM3_BASE) -#define PWM4 ((PWM_TypeDef *) PWM4_BASE) -#define PWM5 ((PWM_TypeDef *) PWM5_BASE) -#define PWMG ((PWMG_TypeDef *) PWMG_BASE) +#define PWM0 ((PWM_TypeDef *)PWM0_BASE) +#define PWM1 ((PWM_TypeDef *)PWM1_BASE) +#define PWM2 ((PWM_TypeDef *)PWM2_BASE) +#define PWM3 ((PWM_TypeDef *)PWM3_BASE) +#define PWM4 ((PWM_TypeDef *)PWM4_BASE) +#define PWM5 ((PWM_TypeDef *)PWM5_BASE) +#define PWMG ((PWMG_TypeDef *)PWMG_BASE) -#define SDIO ((SDIO_TypeDef *) SDIO_BASE) +#define SDIO ((SDIO_TypeDef *)SDIO_BASE) -#define DMA ((DMA_TypeDef *) DMA_BASE) +#define DMA ((DMA_TypeDef *)DMA_BASE) -#define CAN ((CAN_TypeDef *) CAN_BASE) +#define CAN ((CAN_TypeDef *)CAN_BASE) -#define LCD ((LCD_TypeDef *) LCD_BASE) +#define LCD ((LCD_TypeDef *)LCD_BASE) -#define CRC ((CRC_TypeDef *) CRC_BASE) +#define CRC ((CRC_TypeDef *)CRC_BASE) -#define RTC ((RTC_TypeDef *) RTC_BASE) +#define RTC ((RTC_TypeDef *)RTC_BASE) -#define WDT ((WDT_TypeDef *) WDT_BASE) +#define WDT ((WDT_TypeDef *)WDT_BASE) -#define FLASH ((FLASH_Typedef*) FLASH_BASE) +#define FLASH ((FLASH_Typedef *)FLASH_BASE) -#define SRAMC ((SRAMC_TypeDef*) SRAMC_BASE) +#define SRAMC ((SRAMC_TypeDef *)SRAMC_BASE) -#define NORFLC ((NORFLC_TypeDef*) NORFLC_BASE) +#define NORFLC ((NORFLC_TypeDef *)NORFLC_BASE) -#define SDRAMC ((SDRAMC_TypeDef*) SDRAMC_BASE) - - - -typedef void (* Func_void_void) (void); +#define SDRAMC ((SDRAMC_TypeDef *)SDRAMC_BASE) +typedef void (*Func_void_void)(void); #include "SWM320_port.h" #include "SWM320_gpio.h" @@ -3622,5 +3565,4 @@ typedef void (* Func_void_void) (void); #include "SWM320_rtc.h" #include "SWM320_wdt.h" - #endif //__SWM320_H__ diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/arm/startup_SWM320.s b/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/arm/startup_SWM320.s index aa7fb9c2cf..db1c455bf9 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/arm/startup_SWM320.s +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/arm/startup_SWM320.s @@ -79,7 +79,7 @@ __Vectors DCD __initial_sp ; Top of Stack DCD GPIOA5_Handler DCD GPIOA6_Handler DCD GPIOA7_Handler - DCD GPIOB0_Handler + DCD GPIOB0_Handler DCD GPIOB1_Handler DCD GPIOB2_Handler DCD GPIOB3_Handler @@ -103,19 +103,19 @@ __Vectors DCD __initial_sp ; Top of Stack DCD GPIOM5_Handler DCD GPIOM6_Handler DCD GPIOM7_Handler - DCD DMA_Handler + DCD DMA_Handler DCD LCD_Handler DCD NORFLC_Handler - DCD CAN_Handler + DCD CAN_Handler DCD PULSE_Handler DCD WDT_Handler DCD PWM_Handler DCD UART0_Handler - DCD UART1_Handler - DCD UART2_Handler - DCD UART3_Handler - DCD 0 - DCD I2C0_Handler + DCD UART1_Handler + DCD UART2_Handler + DCD UART3_Handler + DCD 0 + DCD I2C0_Handler DCD I2C1_Handler DCD SPI0_Handler DCD ADC0_Handler @@ -130,13 +130,13 @@ __Vectors DCD __initial_sp ; Top of Stack DCD GPIOP_Handler DCD ADC1_Handler DCD FPU_Handler - DCD SPI1_Handler - DCD TIMR0_Handler - DCD TIMR1_Handler - DCD TIMR2_Handler - DCD TIMR3_Handler - DCD TIMR4_Handler - DCD TIMR5_Handler + DCD SPI1_Handler + DCD TIMR0_Handler + DCD TIMR1_Handler + DCD TIMR2_Handler + DCD TIMR3_Handler + DCD TIMR4_Handler + DCD TIMR5_Handler __Vectors_End diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/gcc/startup_SWM320.s b/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/gcc/startup_SWM320.s index 9d8742e969..1a59a2318a 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/gcc/startup_SWM320.s +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/gcc/startup_SWM320.s @@ -113,7 +113,7 @@ __isr_vector: .long TIMR4_Handler .long TIMR5_Handler - .section .text.Reset_Handler + .section .text.Reset_Handler .align 2 .globl Reset_Handler .type Reset_Handler, %function diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/iar/startup_SWM320.s b/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/iar/startup_SWM320.s index 7463384892..a7a4d89f50 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/iar/startup_SWM320.s +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/startup/iar/startup_SWM320.s @@ -84,7 +84,7 @@ __vector_table DCD DMA_Handler DCD LCD_Handler DCD NORFLC_Handler - DCD CAN_Handler + DCD CAN_Handler DCD PULSE_Handler DCD WDT_Handler DCD PWM_Handler diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c b/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c index 08f5a59bc3..0797d828f9 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.c @@ -17,56 +17,48 @@ * -ECTION WITH THEIR PRODUCTS. * * COPYRIGHT 2012 Synwit Technology -*******************************************************************************************************************************************/ +*******************************************************************************************************************************************/ #include #include "SWM320.h" - /****************************************************************************************************************************************** * 系统时钟设定 *****************************************************************************************************************************************/ -#define SYS_CLK_20MHz 0 //0 内部高频20MHz RC振荡器 -#define SYS_CLK_40MHz 1 //1 内部高频40MHz RC振荡器 -#define SYS_CLK_32KHz 2 //2 内部低频32KHz RC振荡器 -#define SYS_CLK_XTAL 3 //3 外部晶体振荡器(2-30MHz) -#define SYS_CLK_PLL 4 //4 片内锁相环输出 +#define SYS_CLK_20MHz 0 //0 内部高频20MHz RC振荡器 +#define SYS_CLK_40MHz 1 //1 内部高频40MHz RC振荡器 +#define SYS_CLK_32KHz 2 //2 内部低频32KHz RC振荡器 +#define SYS_CLK_XTAL 3 //3 外部晶体振荡器(2-30MHz) +#define SYS_CLK_PLL 4 //4 片内锁相环输出 -#define SYS_CLK SYS_CLK_PLL +#define SYS_CLK SYS_CLK_PLL +#define SYS_CLK_DIV_1 0 +#define SYS_CLK_DIV_2 1 -#define SYS_CLK_DIV_1 0 -#define SYS_CLK_DIV_2 1 - -#define SYS_CLK_DIV SYS_CLK_DIV_1 - - -#define __HSI (20000000UL) //高速内部时钟 -#define __LSI ( 32000UL) //低速内部时钟 -#define __HSE (20000000UL) //高速外部时钟 +#define SYS_CLK_DIV SYS_CLK_DIV_1 +#define __HSI (20000000UL) //高速内部时钟 +#define __LSI (32000UL) //低速内部时钟 +#define __HSE (20000000UL) //高速外部时钟 /********************************** PLL 设定 ********************************************** * VCO输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV * PLL输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV / OUTDIV = VCO输出频率 / OUTDIV - *****************************************************************************************/ -#define SYS_PLL_SRC SYS_CLK_20MHz //可取值SYS_CLK_20MHz、SYS_CLK_XTAL + *****************************************************************************************/ +#define SYS_PLL_SRC SYS_CLK_20MHz //可取值SYS_CLK_20MHz、SYS_CLK_XTAL -#define PLL_IN_DIV 5 +#define PLL_IN_DIV 5 -#define PLL_FB_DIV 60 +#define PLL_FB_DIV 60 +#define PLL_OUT_DIV8 0 +#define PLL_OUT_DIV4 1 +#define PLL_OUT_DIV2 2 -#define PLL_OUT_DIV8 0 -#define PLL_OUT_DIV4 1 -#define PLL_OUT_DIV2 2 - -#define PLL_OUT_DIV PLL_OUT_DIV8 - - - -uint32_t SystemCoreClock = __HSI; //System Clock Frequency (Core Clock) -uint32_t CyclesPerUs = (__HSI / 1000000); //Cycles per micro second +#define PLL_OUT_DIV PLL_OUT_DIV8 +uint32_t SystemCoreClock = __HSI; //System Clock Frequency (Core Clock) +uint32_t CyclesPerUs = (__HSI / 1000000); //Cycles per micro second /****************************************************************************************************************************************** * 函数名称: @@ -75,50 +67,51 @@ uint32_t CyclesPerUs = (__HSI / 1000000); //Cycles per micro second * 输 出: * 注意事项: ******************************************************************************************************************************************/ -void SystemCoreClockUpdate(void) +void SystemCoreClockUpdate(void) { - if(SYS->CLKSEL & SYS_CLKSEL_SYS_Msk) //SYS_CLK <= HFCK - { - if(SYS->CLKSEL & SYS_CLKSEL_HFCK_Msk) //HFCK <= XTAL - { - SystemCoreClock = __HSE; - } - else //HFCK <= HRC - { - if(SYS->HRCCR & SYS_HRCCR_DBL_Msk) //HRC = 40MHz - { - SystemCoreClock = __HSI*2; - } - else //HRC = 20MHz - { - SystemCoreClock = __HSI; - } - } - } - else //SYS_CLK <= LFCK - { - if(SYS->CLKSEL & SYS_CLKSEL_LFCK_Msk) //LFCK <= PLL - { - if(SYS->PLLCR & SYS_PLLCR_INSEL_Msk) //PLL_SRC <= HRC - { - SystemCoreClock = __HSI; - } - else //PLL_SRC <= XTAL - { - SystemCoreClock = __HSE; - } - - SystemCoreClock = SystemCoreClock / PLL_IN_DIV * PLL_FB_DIV * 4 / (2 << (2 - PLL_OUT_DIV)); - } - else //LFCK <= LRC - { - SystemCoreClock = __LSI; - } - } - - if(SYS->CLKDIV & SYS_CLKDIV_SYS_Msk) SystemCoreClock /= 2; - - CyclesPerUs = SystemCoreClock / 1000000; + if (SYS->CLKSEL & SYS_CLKSEL_SYS_Msk) //SYS_CLK <= HFCK + { + if (SYS->CLKSEL & SYS_CLKSEL_HFCK_Msk) //HFCK <= XTAL + { + SystemCoreClock = __HSE; + } + else //HFCK <= HRC + { + if (SYS->HRCCR & SYS_HRCCR_DBL_Msk) //HRC = 40MHz + { + SystemCoreClock = __HSI * 2; + } + else //HRC = 20MHz + { + SystemCoreClock = __HSI; + } + } + } + else //SYS_CLK <= LFCK + { + if (SYS->CLKSEL & SYS_CLKSEL_LFCK_Msk) //LFCK <= PLL + { + if (SYS->PLLCR & SYS_PLLCR_INSEL_Msk) //PLL_SRC <= HRC + { + SystemCoreClock = __HSI; + } + else //PLL_SRC <= XTAL + { + SystemCoreClock = __HSE; + } + + SystemCoreClock = SystemCoreClock / PLL_IN_DIV * PLL_FB_DIV * 4 / (2 << (2 - PLL_OUT_DIV)); + } + else //LFCK <= LRC + { + SystemCoreClock = __LSI; + } + } + + if (SYS->CLKDIV & SYS_CLKDIV_SYS_Msk) + SystemCoreClock /= 2; + + CyclesPerUs = SystemCoreClock / 1000000; } /****************************************************************************************************************************************** @@ -129,152 +122,160 @@ void SystemCoreClockUpdate(void) * 注意事项: ******************************************************************************************************************************************/ void SystemInit(void) -{ - SYS->CLKEN |= (1 << SYS_CLKEN_ANAC_Pos); - - Flash_Param_at_xMHz(120); - - switch(SYS_CLK) - { - case SYS_CLK_20MHz: //0 内部高频20MHz RC振荡器 - switchCLK_20MHz(); - break; - - case SYS_CLK_40MHz: //1 内部高频40MHz RC振荡器 - switchCLK_40MHz(); - break; - - case SYS_CLK_32KHz: //2 内部低频32KHz RC振荡器 - switchCLK_32KHz(); - break; - - case SYS_CLK_XTAL: //3 外部晶体振荡器(2-30MHz) - switchCLK_XTAL(); - break; - - case SYS_CLK_PLL: //4 片内锁相环输出 - switchCLK_PLL(); - break; - } - - SYS->CLKDIV &= ~SYS_CLKDIV_SYS_Msk; - SYS->CLKDIV |= (SYS_CLK_DIV << SYS_CLKDIV_SYS_Pos); - - SystemCoreClockUpdate(); - - if(SystemCoreClock > 80000000) - { - Flash_Param_at_xMHz(120); - } - else if(SystemCoreClock > 40000000) - { - Flash_Param_at_xMHz(80); - } - else if(SystemCoreClock > 30000000) - { - Flash_Param_at_xMHz(40); - } - else - { - Flash_Param_at_xMHz(30); - } +{ + SYS->CLKEN |= (1 << SYS_CLKEN_ANAC_Pos); + + Flash_Param_at_xMHz(120); + + switch (SYS_CLK) + { + case SYS_CLK_20MHz: //0 内部高频20MHz RC振荡器 + switchCLK_20MHz(); + break; + + case SYS_CLK_40MHz: //1 内部高频40MHz RC振荡器 + switchCLK_40MHz(); + break; + + case SYS_CLK_32KHz: //2 内部低频32KHz RC振荡器 + switchCLK_32KHz(); + break; + + case SYS_CLK_XTAL: //3 外部晶体振荡器(2-30MHz) + switchCLK_XTAL(); + break; + + case SYS_CLK_PLL: //4 片内锁相环输出 + switchCLK_PLL(); + break; + } + + SYS->CLKDIV &= ~SYS_CLKDIV_SYS_Msk; + SYS->CLKDIV |= (SYS_CLK_DIV << SYS_CLKDIV_SYS_Pos); + + SystemCoreClockUpdate(); + + if (SystemCoreClock > 80000000) + { + Flash_Param_at_xMHz(120); + } + else if (SystemCoreClock > 40000000) + { + Flash_Param_at_xMHz(80); + } + else if (SystemCoreClock > 30000000) + { + Flash_Param_at_xMHz(40); + } + else + { + Flash_Param_at_xMHz(30); + } } void switchCLK_20MHz(void) { - uint32_t i; - - SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | - (0 << SYS_HRCCR_DBL_Pos); //HRC = 20MHz - - for(i = 0; i < 1000; i++) __NOP(); - - SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk; //HFCK <= HRC - SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK + uint32_t i; + + SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | + (0 << SYS_HRCCR_DBL_Pos); //HRC = 20MHz + + for (i = 0; i < 1000; i++) + __NOP(); + + SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk; //HFCK <= HRC + SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK } void switchCLK_40MHz(void) { - uint32_t i; - - SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | - (1 << SYS_HRCCR_DBL_Pos); //HRC = 40MHz - - for(i = 0; i < 1000; i++) __NOP(); - - SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk; //HFCK <= HRC - SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK + uint32_t i; + + SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | + (1 << SYS_HRCCR_DBL_Pos); //HRC = 40MHz + + for (i = 0; i < 1000; i++) + __NOP(); + + SYS->CLKSEL &= ~SYS_CLKSEL_HFCK_Msk; //HFCK <= HRC + SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK } void switchCLK_32KHz(void) { - uint32_t i; - - SYS->CLKEN |= (1 << SYS_CLKEN_RTCBKP_Pos); - - SYS->LRCCR &= ~(1 << SYS_LRCCR_OFF_Pos); - - for(i = 0; i < 100; i++) __NOP(); - - SYS->CLKSEL &= ~SYS_CLKSEL_LFCK_Msk; //LFCK <= LRC - SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk; //SYS_CLK <= LFCK + uint32_t i; + + SYS->CLKEN |= (1 << SYS_CLKEN_RTCBKP_Pos); + + SYS->LRCCR &= ~(1 << SYS_LRCCR_OFF_Pos); + + for (i = 0; i < 100; i++) + __NOP(); + + SYS->CLKSEL &= ~SYS_CLKSEL_LFCK_Msk; //LFCK <= LRC + SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk; //SYS_CLK <= LFCK } void switchCLK_XTAL(void) { - uint32_t i; - - SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos); - - for(i = 0; i < 1000; i++) __NOP(); - - SYS->CLKSEL |= (1 << SYS_CLKSEL_HFCK_Pos); //HFCK <= XTAL - SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK + uint32_t i; + + SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos); + + for (i = 0; i < 1000; i++) + __NOP(); + + SYS->CLKSEL |= (1 << SYS_CLKSEL_HFCK_Pos); //HFCK <= XTAL + SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos); //SYS_CLK <= HFCK } void switchCLK_PLL(void) { - uint32_t i; - - PLLInit(); - SYS->PLLCR |= (1 << SYS_PLLCR_OUTEN_Pos); - - for(i = 0; i < 10000; i++) __NOP(); - - SYS->CLKSEL |= (1 << SYS_CLKSEL_LFCK_Pos); //LFCK <= PLL - SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk; //SYS_CLK <= LFCK + uint32_t i; + + PLLInit(); + SYS->PLLCR |= (1 << SYS_PLLCR_OUTEN_Pos); + + for (i = 0; i < 10000; i++) + __NOP(); + + SYS->CLKSEL |= (1 << SYS_CLKSEL_LFCK_Pos); //LFCK <= PLL + SYS->CLKSEL &= ~SYS_CLKSEL_SYS_Msk; //SYS_CLK <= LFCK } void PLLInit(void) { - uint32_t i; - - if(SYS_PLL_SRC == SYS_CLK_20MHz) - { - SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | - (0 << SYS_HRCCR_DBL_Pos); //HRC = 20MHz - - for(i = 0; i < 1000; i++) __NOP(); - - SYS->PLLCR |= (1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= HRC - } - else if(SYS_PLL_SRC == SYS_CLK_XTAL) - { - SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos); - - for(i = 0; i < 20000; i++); - - SYS->PLLCR &= ~(1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= XTAL - } - - SYS->PLLDIV &= ~(SYS_PLLDIV_INDIV_Msk | - SYS_PLLDIV_FBDIV_Msk | - SYS_PLLDIV_OUTDIV_Msk); - SYS->PLLDIV |= (PLL_IN_DIV << SYS_PLLDIV_INDIV_Pos) | - (PLL_FB_DIV << SYS_PLLDIV_FBDIV_Pos) | - (PLL_OUT_DIV<< SYS_PLLDIV_OUTDIV_Pos); - - SYS->PLLCR &= ~(1 << SYS_PLLCR_OFF_Pos); - - while(SYS->PLLLOCK == 0); //等待PLL锁定 + uint32_t i; + + if (SYS_PLL_SRC == SYS_CLK_20MHz) + { + SYS->HRCCR = (0 << SYS_HRCCR_OFF_Pos) | + (0 << SYS_HRCCR_DBL_Pos); //HRC = 20MHz + + for (i = 0; i < 1000; i++) + __NOP(); + + SYS->PLLCR |= (1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= HRC + } + else if (SYS_PLL_SRC == SYS_CLK_XTAL) + { + SYS->XTALCR = (1 << SYS_XTALCR_EN_Pos); + + for (i = 0; i < 20000; i++) + ; + + SYS->PLLCR &= ~(1 << SYS_PLLCR_INSEL_Pos); //PLL_SRC <= XTAL + } + + SYS->PLLDIV &= ~(SYS_PLLDIV_INDIV_Msk | + SYS_PLLDIV_FBDIV_Msk | + SYS_PLLDIV_OUTDIV_Msk); + SYS->PLLDIV |= (PLL_IN_DIV << SYS_PLLDIV_INDIV_Pos) | + (PLL_FB_DIV << SYS_PLLDIV_FBDIV_Pos) | + (PLL_OUT_DIV << SYS_PLLDIV_OUTDIV_Pos); + + SYS->PLLCR &= ~(1 << SYS_PLLCR_OFF_Pos); + + while (SYS->PLLLOCK == 0) + ; //等待PLL锁定 } diff --git a/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.h b/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.h index 3967e4059c..4db7f29433 100644 --- a/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.h +++ b/bsp/swm320/libraries/CMSIS/DeviceSupport/system_SWM320.h @@ -2,28 +2,24 @@ #define __SYSTEM_SWM320_H__ #ifdef __cplusplus - extern "C" { +extern "C" +{ #endif + extern uint32_t SystemCoreClock; // System Clock Frequency (Core Clock) + extern uint32_t CyclesPerUs; // Cycles per micro second -extern uint32_t SystemCoreClock; // System Clock Frequency (Core Clock) -extern uint32_t CyclesPerUs; // Cycles per micro second + extern void SystemInit(void); + extern void SystemCoreClockUpdate(void); -extern void SystemInit(void); - -extern void SystemCoreClockUpdate (void); - - - -extern void switchCLK_20MHz(void); -extern void switchCLK_40MHz(void); -extern void switchCLK_32KHz(void); -extern void switchCLK_XTAL(void); -extern void switchCLK_PLL(void); - -extern void PLLInit(void); + extern void switchCLK_20MHz(void); + extern void switchCLK_40MHz(void); + extern void switchCLK_32KHz(void); + extern void switchCLK_XTAL(void); + extern void switchCLK_PLL(void); + extern void PLLInit(void); #ifdef __cplusplus } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.c index 8f73ec62c9..983b4bcff1 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.c @@ -19,7 +19,6 @@ #include "SWM320.h" #include "SWM320_adc.h" - /****************************************************************************************************************************************** * 函数名称: ADC_Init() * 功能说明: ADC模数转换器初始化 @@ -28,128 +27,129 @@ * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_Init(ADC_TypeDef * ADCx, ADC_InitStructure * initStruct) +void ADC_Init(ADC_TypeDef *ADCx, ADC_InitStructure *initStruct) { - switch((uint32_t)ADCx) - { - case ((uint32_t)ADC0): - SYS->CLKEN |= (0x01 << SYS_CLKEN_ADC0_Pos); - break; - - case ((uint32_t)ADC1): - SYS->CLKEN |= (0x01 << SYS_CLKEN_ADC1_Pos); - break; - } - - ADC_Close(ADCx); //一些关键寄存器只能在ADC关闭时设置 - - if(initStruct->clk_src == ADC_CLKSRC_HRC) - { - ADCx->CTRL |= (1 << ADC_CTRL_CLKSRC_Pos); - - ADCx->CTRL2 &= ~ADC_CTRL2_CLKDIV_Msk; - ADCx->CTRL2 |= (initStruct->clk_div << ADC_CTRL2_CLKDIV_Pos); - } - else - { - if(SYS->PLLCR & SYS_PLLCR_OFF_Msk) PLLInit(); - - ADCx->CTRL &= ~(1 << ADC_CTRL_CLKSRC_Pos); - - SYS->PLLDIV &= ~SYS_PLLDIV_ADVCO_Msk; - SYS->PLLDIV |= ((initStruct->clk_src - 2) << SYS_PLLDIV_ADVCO_Pos); - - SYS->PLLDIV &= ~SYS_PLLDIV_ADDIV_Msk; - SYS->PLLDIV |= (initStruct->clk_div << SYS_PLLDIV_ADDIV_Pos); - } - - ADCx->CALIBSET = (ADCx == ADC0) ? SYS->BKP[0] : SYS->BKP[1]; - ADCx->CALIBEN = (1 << ADC_CALIBEN_OFFSET_Pos) | (1 << ADC_CALIBEN_K_Pos); - - ADCx->CTRL2 &= ~(ADC_CTRL2_ADCEVCM_Msk | ADC_CTRL2_PGAIVCM_Msk | ADC_CTRL2_PGAGAIN_Msk | ADC_CTRL2_PGAVCM_Msk); - ADCx->CTRL2 |= (0 << ADC_CTRL2_ADCEVCM_Pos) | - (initStruct->pga_ref << ADC_CTRL2_PGAIVCM_Pos) | - (6 << ADC_CTRL2_PGAGAIN_Pos) | - ((uint32_t)6 << ADC_CTRL2_PGAVCM_Pos); - - ADCx->CTRL &= ~( 0xFF << ADC_CTRL_CH0_Pos); - ADCx->CTRL |= (initStruct->channels << ADC_CTRL_CH0_Pos); - - ADCx->CTRL &= ~(ADC_CTRL_AVG_Msk | ADC_CTRL_TRIG_Msk | ADC_CTRL_CONT_Msk); - ADCx->CTRL |= (initStruct->samplAvg << ADC_CTRL_AVG_Pos) | - (initStruct->trig_src << ADC_CTRL_TRIG_Pos) | - (initStruct->Continue << ADC_CTRL_CONT_Pos); - - ADCx->IF = 0xFFFFFFFF; //清除中断标志 - - ADCx->IE &= ~(ADC_IE_CH0EOC_Msk | ADC_IE_CH1EOC_Msk | ADC_IE_CH2EOC_Msk | ADC_IE_CH3EOC_Msk | - ADC_IE_CH4EOC_Msk | ADC_IE_CH5EOC_Msk | ADC_IE_CH6EOC_Msk | ADC_IE_CH7EOC_Msk); - ADCx->IE |= (((initStruct->EOC_IEn & ADC_CH0) ? 1 : 0) << ADC_IE_CH0EOC_Pos) | - (((initStruct->EOC_IEn & ADC_CH1) ? 1 : 0) << ADC_IE_CH1EOC_Pos) | - (((initStruct->EOC_IEn & ADC_CH2) ? 1 : 0) << ADC_IE_CH2EOC_Pos) | - (((initStruct->EOC_IEn & ADC_CH3) ? 1 : 0) << ADC_IE_CH3EOC_Pos) | - (((initStruct->EOC_IEn & ADC_CH4) ? 1 : 0) << ADC_IE_CH4EOC_Pos) | - (((initStruct->EOC_IEn & ADC_CH5) ? 1 : 0) << ADC_IE_CH5EOC_Pos) | - (((initStruct->EOC_IEn & ADC_CH6) ? 1 : 0) << ADC_IE_CH6EOC_Pos) | - (((initStruct->EOC_IEn & ADC_CH7) ? 1 : 0) << ADC_IE_CH7EOC_Pos); - - ADCx->IE &= ~(ADC_IE_CH0OVF_Msk | ADC_IE_CH1OVF_Msk | ADC_IE_CH2OVF_Msk | ADC_IE_CH3OVF_Msk | - ADC_IE_CH4OVF_Msk | ADC_IE_CH5OVF_Msk | ADC_IE_CH6OVF_Msk | ADC_IE_CH7OVF_Msk); - ADCx->IE |= (((initStruct->OVF_IEn & ADC_CH0) ? 1 : 0) << ADC_IE_CH0OVF_Pos) | - (((initStruct->OVF_IEn & ADC_CH1) ? 1 : 0) << ADC_IE_CH1OVF_Pos) | - (((initStruct->OVF_IEn & ADC_CH2) ? 1 : 0) << ADC_IE_CH2OVF_Pos) | - (((initStruct->OVF_IEn & ADC_CH3) ? 1 : 0) << ADC_IE_CH3OVF_Pos) | - (((initStruct->OVF_IEn & ADC_CH4) ? 1 : 0) << ADC_IE_CH4OVF_Pos) | - (((initStruct->OVF_IEn & ADC_CH5) ? 1 : 0) << ADC_IE_CH5OVF_Pos) | - (((initStruct->OVF_IEn & ADC_CH6) ? 1 : 0) << ADC_IE_CH6OVF_Pos) | - (((initStruct->OVF_IEn & ADC_CH7) ? 1 : 0) << ADC_IE_CH7OVF_Pos); - - ADCx->IE &= ~(ADC_IE_CH0HFULL_Msk | ADC_IE_CH1HFULL_Msk | ADC_IE_CH2HFULL_Msk | ADC_IE_CH3HFULL_Msk | - ADC_IE_CH4HFULL_Msk | ADC_IE_CH5HFULL_Msk | ADC_IE_CH6HFULL_Msk | ADC_IE_CH7HFULL_Msk); - ADCx->IE |= (((initStruct->HFULL_IEn & ADC_CH0) ? 1 : 0) << ADC_IE_CH0HFULL_Pos) | - (((initStruct->HFULL_IEn & ADC_CH1) ? 1 : 0) << ADC_IE_CH1HFULL_Pos) | - (((initStruct->HFULL_IEn & ADC_CH2) ? 1 : 0) << ADC_IE_CH2HFULL_Pos) | - (((initStruct->HFULL_IEn & ADC_CH3) ? 1 : 0) << ADC_IE_CH3HFULL_Pos) | - (((initStruct->HFULL_IEn & ADC_CH4) ? 1 : 0) << ADC_IE_CH4HFULL_Pos) | - (((initStruct->HFULL_IEn & ADC_CH5) ? 1 : 0) << ADC_IE_CH5HFULL_Pos) | - (((initStruct->HFULL_IEn & ADC_CH6) ? 1 : 0) << ADC_IE_CH6HFULL_Pos) | - (((initStruct->HFULL_IEn & ADC_CH7) ? 1 : 0) << ADC_IE_CH7HFULL_Pos); - - ADCx->IE &= ~(uint32_t)(ADC_IE_CH0FULL_Msk | ADC_IE_CH1FULL_Msk | ADC_IE_CH2FULL_Msk | ADC_IE_CH3FULL_Msk | - ADC_IE_CH4FULL_Msk | ADC_IE_CH5FULL_Msk | ADC_IE_CH6FULL_Msk | ADC_IE_CH7FULL_Msk); - ADCx->IE |= (((initStruct->FULL_IEn & ADC_CH0) ? 1 : 0) << ADC_IE_CH0FULL_Pos) | - (((initStruct->FULL_IEn & ADC_CH1) ? 1 : 0) << ADC_IE_CH1FULL_Pos) | - (((initStruct->FULL_IEn & ADC_CH2) ? 1 : 0) << ADC_IE_CH2FULL_Pos) | - (((initStruct->FULL_IEn & ADC_CH3) ? 1 : 0) << ADC_IE_CH3FULL_Pos) | - (((initStruct->FULL_IEn & ADC_CH4) ? 1 : 0) << ADC_IE_CH4FULL_Pos) | - (((initStruct->FULL_IEn & ADC_CH5) ? 1 : 0) << ADC_IE_CH5FULL_Pos) | - (((initStruct->FULL_IEn & ADC_CH6) ? 1 : 0) << ADC_IE_CH6FULL_Pos) | - (((initStruct->FULL_IEn & ADC_CH7) ? 1 : 0) << ADC_IE_CH7FULL_Pos); - - switch((uint32_t)ADCx) - { - case ((uint32_t)ADC0): - if(initStruct->EOC_IEn | initStruct->OVF_IEn | initStruct->HFULL_IEn | initStruct->FULL_IEn) - { - NVIC_EnableIRQ(ADC0_IRQn); - } - else - { - NVIC_DisableIRQ(ADC0_IRQn); - } - break; - - case ((uint32_t)ADC1): - if(initStruct->EOC_IEn | initStruct->OVF_IEn | initStruct->HFULL_IEn | initStruct->FULL_IEn) - { - NVIC_EnableIRQ(ADC1_IRQn); - } - else - { - NVIC_DisableIRQ(ADC1_IRQn); - } - break; - } + switch ((uint32_t)ADCx) + { + case ((uint32_t)ADC0): + SYS->CLKEN |= (0x01 << SYS_CLKEN_ADC0_Pos); + break; + + case ((uint32_t)ADC1): + SYS->CLKEN |= (0x01 << SYS_CLKEN_ADC1_Pos); + break; + } + + ADC_Close(ADCx); //一些关键寄存器只能在ADC关闭时设置 + + if (initStruct->clk_src == ADC_CLKSRC_HRC) + { + ADCx->CTRL |= (1 << ADC_CTRL_CLKSRC_Pos); + + ADCx->CTRL2 &= ~ADC_CTRL2_CLKDIV_Msk; + ADCx->CTRL2 |= (initStruct->clk_div << ADC_CTRL2_CLKDIV_Pos); + } + else + { + if (SYS->PLLCR & SYS_PLLCR_OFF_Msk) + PLLInit(); + + ADCx->CTRL &= ~(1 << ADC_CTRL_CLKSRC_Pos); + + SYS->PLLDIV &= ~SYS_PLLDIV_ADVCO_Msk; + SYS->PLLDIV |= ((initStruct->clk_src - 2) << SYS_PLLDIV_ADVCO_Pos); + + SYS->PLLDIV &= ~SYS_PLLDIV_ADDIV_Msk; + SYS->PLLDIV |= (initStruct->clk_div << SYS_PLLDIV_ADDIV_Pos); + } + + ADCx->CALIBSET = (ADCx == ADC0) ? SYS->BKP[0] : SYS->BKP[1]; + ADCx->CALIBEN = (1 << ADC_CALIBEN_OFFSET_Pos) | (1 << ADC_CALIBEN_K_Pos); + + ADCx->CTRL2 &= ~(ADC_CTRL2_ADCEVCM_Msk | ADC_CTRL2_PGAIVCM_Msk | ADC_CTRL2_PGAGAIN_Msk | ADC_CTRL2_PGAVCM_Msk); + ADCx->CTRL2 |= (0 << ADC_CTRL2_ADCEVCM_Pos) | + (initStruct->pga_ref << ADC_CTRL2_PGAIVCM_Pos) | + (6 << ADC_CTRL2_PGAGAIN_Pos) | + ((uint32_t)6 << ADC_CTRL2_PGAVCM_Pos); + + ADCx->CTRL &= ~(0xFF << ADC_CTRL_CH0_Pos); + ADCx->CTRL |= (initStruct->channels << ADC_CTRL_CH0_Pos); + + ADCx->CTRL &= ~(ADC_CTRL_AVG_Msk | ADC_CTRL_TRIG_Msk | ADC_CTRL_CONT_Msk); + ADCx->CTRL |= (initStruct->samplAvg << ADC_CTRL_AVG_Pos) | + (initStruct->trig_src << ADC_CTRL_TRIG_Pos) | + (initStruct->Continue << ADC_CTRL_CONT_Pos); + + ADCx->IF = 0xFFFFFFFF; //清除中断标志 + + ADCx->IE &= ~(ADC_IE_CH0EOC_Msk | ADC_IE_CH1EOC_Msk | ADC_IE_CH2EOC_Msk | ADC_IE_CH3EOC_Msk | + ADC_IE_CH4EOC_Msk | ADC_IE_CH5EOC_Msk | ADC_IE_CH6EOC_Msk | ADC_IE_CH7EOC_Msk); + ADCx->IE |= (((initStruct->EOC_IEn & ADC_CH0) ? 1 : 0) << ADC_IE_CH0EOC_Pos) | + (((initStruct->EOC_IEn & ADC_CH1) ? 1 : 0) << ADC_IE_CH1EOC_Pos) | + (((initStruct->EOC_IEn & ADC_CH2) ? 1 : 0) << ADC_IE_CH2EOC_Pos) | + (((initStruct->EOC_IEn & ADC_CH3) ? 1 : 0) << ADC_IE_CH3EOC_Pos) | + (((initStruct->EOC_IEn & ADC_CH4) ? 1 : 0) << ADC_IE_CH4EOC_Pos) | + (((initStruct->EOC_IEn & ADC_CH5) ? 1 : 0) << ADC_IE_CH5EOC_Pos) | + (((initStruct->EOC_IEn & ADC_CH6) ? 1 : 0) << ADC_IE_CH6EOC_Pos) | + (((initStruct->EOC_IEn & ADC_CH7) ? 1 : 0) << ADC_IE_CH7EOC_Pos); + + ADCx->IE &= ~(ADC_IE_CH0OVF_Msk | ADC_IE_CH1OVF_Msk | ADC_IE_CH2OVF_Msk | ADC_IE_CH3OVF_Msk | + ADC_IE_CH4OVF_Msk | ADC_IE_CH5OVF_Msk | ADC_IE_CH6OVF_Msk | ADC_IE_CH7OVF_Msk); + ADCx->IE |= (((initStruct->OVF_IEn & ADC_CH0) ? 1 : 0) << ADC_IE_CH0OVF_Pos) | + (((initStruct->OVF_IEn & ADC_CH1) ? 1 : 0) << ADC_IE_CH1OVF_Pos) | + (((initStruct->OVF_IEn & ADC_CH2) ? 1 : 0) << ADC_IE_CH2OVF_Pos) | + (((initStruct->OVF_IEn & ADC_CH3) ? 1 : 0) << ADC_IE_CH3OVF_Pos) | + (((initStruct->OVF_IEn & ADC_CH4) ? 1 : 0) << ADC_IE_CH4OVF_Pos) | + (((initStruct->OVF_IEn & ADC_CH5) ? 1 : 0) << ADC_IE_CH5OVF_Pos) | + (((initStruct->OVF_IEn & ADC_CH6) ? 1 : 0) << ADC_IE_CH6OVF_Pos) | + (((initStruct->OVF_IEn & ADC_CH7) ? 1 : 0) << ADC_IE_CH7OVF_Pos); + + ADCx->IE &= ~(ADC_IE_CH0HFULL_Msk | ADC_IE_CH1HFULL_Msk | ADC_IE_CH2HFULL_Msk | ADC_IE_CH3HFULL_Msk | + ADC_IE_CH4HFULL_Msk | ADC_IE_CH5HFULL_Msk | ADC_IE_CH6HFULL_Msk | ADC_IE_CH7HFULL_Msk); + ADCx->IE |= (((initStruct->HFULL_IEn & ADC_CH0) ? 1 : 0) << ADC_IE_CH0HFULL_Pos) | + (((initStruct->HFULL_IEn & ADC_CH1) ? 1 : 0) << ADC_IE_CH1HFULL_Pos) | + (((initStruct->HFULL_IEn & ADC_CH2) ? 1 : 0) << ADC_IE_CH2HFULL_Pos) | + (((initStruct->HFULL_IEn & ADC_CH3) ? 1 : 0) << ADC_IE_CH3HFULL_Pos) | + (((initStruct->HFULL_IEn & ADC_CH4) ? 1 : 0) << ADC_IE_CH4HFULL_Pos) | + (((initStruct->HFULL_IEn & ADC_CH5) ? 1 : 0) << ADC_IE_CH5HFULL_Pos) | + (((initStruct->HFULL_IEn & ADC_CH6) ? 1 : 0) << ADC_IE_CH6HFULL_Pos) | + (((initStruct->HFULL_IEn & ADC_CH7) ? 1 : 0) << ADC_IE_CH7HFULL_Pos); + + ADCx->IE &= ~(uint32_t)(ADC_IE_CH0FULL_Msk | ADC_IE_CH1FULL_Msk | ADC_IE_CH2FULL_Msk | ADC_IE_CH3FULL_Msk | + ADC_IE_CH4FULL_Msk | ADC_IE_CH5FULL_Msk | ADC_IE_CH6FULL_Msk | ADC_IE_CH7FULL_Msk); + ADCx->IE |= (((initStruct->FULL_IEn & ADC_CH0) ? 1 : 0) << ADC_IE_CH0FULL_Pos) | + (((initStruct->FULL_IEn & ADC_CH1) ? 1 : 0) << ADC_IE_CH1FULL_Pos) | + (((initStruct->FULL_IEn & ADC_CH2) ? 1 : 0) << ADC_IE_CH2FULL_Pos) | + (((initStruct->FULL_IEn & ADC_CH3) ? 1 : 0) << ADC_IE_CH3FULL_Pos) | + (((initStruct->FULL_IEn & ADC_CH4) ? 1 : 0) << ADC_IE_CH4FULL_Pos) | + (((initStruct->FULL_IEn & ADC_CH5) ? 1 : 0) << ADC_IE_CH5FULL_Pos) | + (((initStruct->FULL_IEn & ADC_CH6) ? 1 : 0) << ADC_IE_CH6FULL_Pos) | + (((initStruct->FULL_IEn & ADC_CH7) ? 1 : 0) << ADC_IE_CH7FULL_Pos); + + switch ((uint32_t)ADCx) + { + case ((uint32_t)ADC0): + if (initStruct->EOC_IEn | initStruct->OVF_IEn | initStruct->HFULL_IEn | initStruct->FULL_IEn) + { + NVIC_EnableIRQ(ADC0_IRQn); + } + else + { + NVIC_DisableIRQ(ADC0_IRQn); + } + break; + + case ((uint32_t)ADC1): + if (initStruct->EOC_IEn | initStruct->OVF_IEn | initStruct->HFULL_IEn | initStruct->FULL_IEn) + { + NVIC_EnableIRQ(ADC1_IRQn); + } + else + { + NVIC_DisableIRQ(ADC1_IRQn); + } + break; + } } /****************************************************************************************************************************************** @@ -159,9 +159,9 @@ void ADC_Init(ADC_TypeDef * ADCx, ADC_InitStructure * initStruct) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_Open(ADC_TypeDef * ADCx) +void ADC_Open(ADC_TypeDef *ADCx) { - ADCx->CTRL |= (0x01 << ADC_CTRL_EN_Pos); + ADCx->CTRL |= (0x01 << ADC_CTRL_EN_Pos); } /****************************************************************************************************************************************** @@ -171,9 +171,9 @@ void ADC_Open(ADC_TypeDef * ADCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_Close(ADC_TypeDef * ADCx) +void ADC_Close(ADC_TypeDef *ADCx) { - ADCx->CTRL &= ~(0x01 << ADC_CTRL_EN_Pos); + ADCx->CTRL &= ~(0x01 << ADC_CTRL_EN_Pos); } /****************************************************************************************************************************************** @@ -183,9 +183,9 @@ void ADC_Close(ADC_TypeDef * ADCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_Start(ADC_TypeDef * ADCx) +void ADC_Start(ADC_TypeDef *ADCx) { - ADCx->START |= (0x01 << ADC_START_GO_Pos); + ADCx->START |= (0x01 << ADC_START_GO_Pos); } /****************************************************************************************************************************************** @@ -195,28 +195,44 @@ void ADC_Start(ADC_TypeDef * ADCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_Stop(ADC_TypeDef * ADCx) -{ - ADCx->START &= ~(0x01 << ADC_START_GO_Pos); +void ADC_Stop(ADC_TypeDef *ADCx) +{ + ADCx->START &= ~(0x01 << ADC_START_GO_Pos); } static uint32_t chn2idx(uint32_t chn) { - uint32_t idx = 0; - - switch(chn) - { - case 0x01: idx = 0; break; - case 0x02: idx = 1; break; - case 0x04: idx = 2; break; - case 0x08: idx = 3; break; - case 0x10: idx = 4; break; - case 0x20: idx = 5; break; - case 0x40: idx = 6; break; - case 0x80: idx = 7; break; - } - - return idx; + uint32_t idx = 0; + + switch (chn) + { + case 0x01: + idx = 0; + break; + case 0x02: + idx = 1; + break; + case 0x04: + idx = 2; + break; + case 0x08: + idx = 3; + break; + case 0x10: + idx = 4; + break; + case 0x20: + idx = 5; + break; + case 0x40: + idx = 6; + break; + case 0x80: + idx = 7; + break; + } + + return idx; } /****************************************************************************************************************************************** @@ -227,16 +243,16 @@ static uint32_t chn2idx(uint32_t chn) * 输 出: uint32_t 读取到的转换结果 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t ADC_Read(ADC_TypeDef * ADCx, uint32_t chn) +uint32_t ADC_Read(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t dat = 0; - uint32_t idx = chn2idx(chn); - - dat = ADCx->CH[idx].DATA; - - ADCx->CH[idx].STAT = 0x01; //清除EOC标志 - - return dat; + uint32_t dat = 0; + uint32_t idx = chn2idx(chn); + + dat = ADCx->CH[idx].DATA; + + ADCx->CH[idx].STAT = 0x01; //清除EOC标志 + + return dat; } /****************************************************************************************************************************************** @@ -247,11 +263,11 @@ uint32_t ADC_Read(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: uint32_t 1 该通道完成了转换 0 该通道未完成转换 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t ADC_IsEOC(ADC_TypeDef * ADCx, uint32_t chn) +uint32_t ADC_IsEOC(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - return (ADCx->CH[idx].STAT & ADC_STAT_EOC_Msk) ? 1 : 0; + uint32_t idx = chn2idx(chn); + + return (ADCx->CH[idx].STAT & ADC_STAT_EOC_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -262,13 +278,12 @@ uint32_t ADC_IsEOC(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_ChnSelect(ADC_TypeDef * ADCx, uint32_t chns) +void ADC_ChnSelect(ADC_TypeDef *ADCx, uint32_t chns) { - ADCx->CTRL &= ~(0xFF << ADC_CTRL_CH0_Pos); - ADCx->CTRL |= (chns << ADC_CTRL_CH0_Pos); + ADCx->CTRL &= ~(0xFF << ADC_CTRL_CH0_Pos); + ADCx->CTRL |= (chns << ADC_CTRL_CH0_Pos); } - /****************************************************************************************************************************************** * 函数名称: ADC_IntEOCEn() * 功能说明: 转换完成中断使能 @@ -277,11 +292,11 @@ void ADC_ChnSelect(ADC_TypeDef * ADCx, uint32_t chns) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntEOCEn(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntEOCEn(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IE |= (0x01 << (idx*4)); + uint32_t idx = chn2idx(chn); + + ADCx->IE |= (0x01 << (idx * 4)); } /****************************************************************************************************************************************** @@ -292,11 +307,11 @@ void ADC_IntEOCEn(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntEOCDis(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntEOCDis(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IE &= ~(0x01 << (idx*4)); + uint32_t idx = chn2idx(chn); + + ADCx->IE &= ~(0x01 << (idx * 4)); } /****************************************************************************************************************************************** @@ -307,11 +322,11 @@ void ADC_IntEOCDis(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntEOCClr(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntEOCClr(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IF = (0x01 << (idx*4)); + uint32_t idx = chn2idx(chn); + + ADCx->IF = (0x01 << (idx * 4)); } /****************************************************************************************************************************************** @@ -322,11 +337,11 @@ void ADC_IntEOCClr(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: uint32_t 1 该通道完成了转换 0 该通道未完成转换 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t ADC_IntEOCStat(ADC_TypeDef * ADCx, uint32_t chn) +uint32_t ADC_IntEOCStat(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - return (ADCx->IF & (0x01 << (idx*4))) ? 1 : 0; + uint32_t idx = chn2idx(chn); + + return (ADCx->IF & (0x01 << (idx * 4))) ? 1 : 0; } /****************************************************************************************************************************************** @@ -337,11 +352,11 @@ uint32_t ADC_IntEOCStat(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntOVFEn(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntOVFEn(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IE |= (0x01 << (idx*4+1)); + uint32_t idx = chn2idx(chn); + + ADCx->IE |= (0x01 << (idx * 4 + 1)); } /****************************************************************************************************************************************** @@ -352,11 +367,11 @@ void ADC_IntOVFEn(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntOVFDis(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntOVFDis(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IE &= ~(0x01 << (idx*4+1)); + uint32_t idx = chn2idx(chn); + + ADCx->IE &= ~(0x01 << (idx * 4 + 1)); } /****************************************************************************************************************************************** @@ -367,11 +382,11 @@ void ADC_IntOVFDis(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntOVFClr(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntOVFClr(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IF = (0x01 << (idx*4+1)); + uint32_t idx = chn2idx(chn); + + ADCx->IF = (0x01 << (idx * 4 + 1)); } /****************************************************************************************************************************************** @@ -382,11 +397,11 @@ void ADC_IntOVFClr(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: uint32_t 1 该通道完成了转换 0 该通道未完成转换 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t ADC_IntOVFStat(ADC_TypeDef * ADCx, uint32_t chn) +uint32_t ADC_IntOVFStat(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - return (ADCx->IF & (0x01 << (idx*4+1))) ? 1 : 0; + uint32_t idx = chn2idx(chn); + + return (ADCx->IF & (0x01 << (idx * 4 + 1))) ? 1 : 0; } /****************************************************************************************************************************************** @@ -397,11 +412,11 @@ uint32_t ADC_IntOVFStat(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntHFULLEn(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntHFULLEn(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IE |= (0x01 << (idx*4+2)); + uint32_t idx = chn2idx(chn); + + ADCx->IE |= (0x01 << (idx * 4 + 2)); } /****************************************************************************************************************************************** @@ -412,11 +427,11 @@ void ADC_IntHFULLEn(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntHFULLDis(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntHFULLDis(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IE &= ~(0x01 << (idx*4+2)); + uint32_t idx = chn2idx(chn); + + ADCx->IE &= ~(0x01 << (idx * 4 + 2)); } /****************************************************************************************************************************************** @@ -427,11 +442,11 @@ void ADC_IntHFULLDis(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntHFULLClr(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntHFULLClr(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IF = (0x01 << (idx*4+2)); + uint32_t idx = chn2idx(chn); + + ADCx->IF = (0x01 << (idx * 4 + 2)); } /****************************************************************************************************************************************** @@ -442,11 +457,11 @@ void ADC_IntHFULLClr(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: uint32_t 1 该通道完成了转换 0 该通道未完成转换 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t ADC_IntHFULLStat(ADC_TypeDef * ADCx, uint32_t chn) +uint32_t ADC_IntHFULLStat(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - return (ADCx->IF & (0x01 << (idx*4+2))) ? 1 : 0; + uint32_t idx = chn2idx(chn); + + return (ADCx->IF & (0x01 << (idx * 4 + 2))) ? 1 : 0; } /****************************************************************************************************************************************** @@ -457,11 +472,11 @@ uint32_t ADC_IntHFULLStat(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntFULLEn(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntFULLEn(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IE |= (0x01 << (idx*4+3)); + uint32_t idx = chn2idx(chn); + + ADCx->IE |= (0x01 << (idx * 4 + 3)); } /****************************************************************************************************************************************** @@ -472,11 +487,11 @@ void ADC_IntFULLEn(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntFULLDis(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntFULLDis(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IE &= ~(0x01 << (idx*4+3)); + uint32_t idx = chn2idx(chn); + + ADCx->IE &= ~(0x01 << (idx * 4 + 3)); } /****************************************************************************************************************************************** @@ -487,11 +502,11 @@ void ADC_IntFULLDis(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void ADC_IntFULLClr(ADC_TypeDef * ADCx, uint32_t chn) +void ADC_IntFULLClr(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - ADCx->IF = (0x01 << (idx*4+3)); + uint32_t idx = chn2idx(chn); + + ADCx->IF = (0x01 << (idx * 4 + 3)); } /****************************************************************************************************************************************** @@ -502,9 +517,9 @@ void ADC_IntFULLClr(ADC_TypeDef * ADCx, uint32_t chn) * 输 出: uint32_t 1 该通道完成了转换 0 该通道未完成转换 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t ADC_IntFULLStat(ADC_TypeDef * ADCx, uint32_t chn) +uint32_t ADC_IntFULLStat(ADC_TypeDef *ADCx, uint32_t chn) { - uint32_t idx = chn2idx(chn); - - return (ADCx->IF & (0x01 << (idx*4+3))) ? 1 : 0; + uint32_t idx = chn2idx(chn); + + return (ADCx->IF & (0x01 << (idx * 4 + 3))) ? 1 : 0; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.h index 96e10972e3..10b4437527 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_adc.h @@ -1,79 +1,77 @@ #ifndef __SWM320_ADC_H__ -#define __SWM320_ADC_H__ +#define __SWM320_ADC_H__ -typedef struct { - uint8_t clk_src; //ADC转换时钟源:ADC_CLKSRC_HRC、ADC_CLKSRC_VCO_DIV16、ADC_CLKSRC_VCO_DIV32、ADC_CLKSRC_VCO_DIV32 - uint8_t clk_div; //ADC转换时钟分频,取值1--31 - uint8_t pga_ref; //PGA基准:PGA_REF_INTERNAL、PGA_REF_EXTERNAL - uint8_t channels; //ADC转换通道选中,ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) - uint8_t samplAvg; //采样取平均,触发启动ADC转换后,ADC在一个通道上连续采样、转换多次,并将它们的平均值作为该通道转换结果 - uint8_t trig_src; //ADC触发方式:ADC_TRIGSRC_SW、ADC_TRIGSRC_PWM、ADC_TRIGSRC_TIMR2、ADC_TRIGSRC_TIMR3 - uint8_t Continue; //在软件触发模式下:1 连续转换模式,启动后一直采样、转换,直到软件清除START位 - // 0 单次转换模式,转换完成后START位自动清除停止转换 - uint8_t EOC_IEn; //EOC中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) - uint8_t OVF_IEn; //OVF中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) - uint8_t HFULL_IEn; //FIFO半满中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) - uint8_t FULL_IEn; //FIFO 满中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) +typedef struct +{ + uint8_t clk_src; //ADC转换时钟源:ADC_CLKSRC_HRC、ADC_CLKSRC_VCO_DIV16、ADC_CLKSRC_VCO_DIV32、ADC_CLKSRC_VCO_DIV32 + uint8_t clk_div; //ADC转换时钟分频,取值1--31 + uint8_t pga_ref; //PGA基准:PGA_REF_INTERNAL、PGA_REF_EXTERNAL + uint8_t channels; //ADC转换通道选中,ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) + uint8_t samplAvg; //采样取平均,触发启动ADC转换后,ADC在一个通道上连续采样、转换多次,并将它们的平均值作为该通道转换结果 + uint8_t trig_src; //ADC触发方式:ADC_TRIGSRC_SW、ADC_TRIGSRC_PWM、ADC_TRIGSRC_TIMR2、ADC_TRIGSRC_TIMR3 + uint8_t Continue; //在软件触发模式下:1 连续转换模式,启动后一直采样、转换,直到软件清除START位 + // 0 单次转换模式,转换完成后START位自动清除停止转换 + uint8_t EOC_IEn; //EOC中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) + uint8_t OVF_IEn; //OVF中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) + uint8_t HFULL_IEn; //FIFO半满中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) + uint8_t FULL_IEn; //FIFO 满中断使能,可针对每个通道设置,其有效值为ADC_CH0、ADC_CH1、... ... 、ADC_CH7及其组合(即“按位或”运算) } ADC_InitStructure; -#define ADC_CH0 0x01 -#define ADC_CH1 0x02 -#define ADC_CH2 0x04 -#define ADC_CH3 0x08 -#define ADC_CH4 0x10 -#define ADC_CH5 0x20 -#define ADC_CH6 0x40 -#define ADC_CH7 0x80 +#define ADC_CH0 0x01 +#define ADC_CH1 0x02 +#define ADC_CH2 0x04 +#define ADC_CH3 0x08 +#define ADC_CH4 0x10 +#define ADC_CH5 0x20 +#define ADC_CH6 0x40 +#define ADC_CH7 0x80 -#define ADC_CLKSRC_HRC 1 -#define ADC_CLKSRC_VCO_DIV16 2 -#define ADC_CLKSRC_VCO_DIV32 3 -#define ADC_CLKSRC_VCO_DIV64 4 +#define ADC_CLKSRC_HRC 1 +#define ADC_CLKSRC_VCO_DIV16 2 +#define ADC_CLKSRC_VCO_DIV32 3 +#define ADC_CLKSRC_VCO_DIV64 4 -#define ADC_AVG_SAMPLE1 0 -#define ADC_AVG_SAMPLE2 1 //一次启动连续采样、转换2次,并计算两次结果的平均值作为转换结果 -#define ADC_AVG_SAMPLE4 3 -#define ADC_AVG_SAMPLE8 7 -#define ADC_AVG_SAMPLE16 15 +#define ADC_AVG_SAMPLE1 0 +#define ADC_AVG_SAMPLE2 1 //一次启动连续采样、转换2次,并计算两次结果的平均值作为转换结果 +#define ADC_AVG_SAMPLE4 3 +#define ADC_AVG_SAMPLE8 7 +#define ADC_AVG_SAMPLE16 15 -#define ADC_TRIGSRC_SW 0 //软件触发,即ADC->START.GO写1启动转换 -#define ADC_TRIGSRC_PWM 1 +#define ADC_TRIGSRC_SW 0 //软件触发,即ADC->START.GO写1启动转换 +#define ADC_TRIGSRC_PWM 1 -#define PGA_REF_INTERNAL 1 //PGA输入共模电平由内部电路产生,ADC_REFP和ADC_REFN可悬空 -#define PGA_REF_EXTERNAL 0 //PGA输入共模电平由外部引脚提供,(ADC_REFP + ADC_REFN) 电平值须与量程相同 +#define PGA_REF_INTERNAL 1 //PGA输入共模电平由内部电路产生,ADC_REFP和ADC_REFN可悬空 +#define PGA_REF_EXTERNAL 0 //PGA输入共模电平由外部引脚提供,(ADC_REFP + ADC_REFN) 电平值须与量程相同 +void ADC_Init(ADC_TypeDef *ADCx, ADC_InitStructure *initStruct); //ADC模数转换器初始化 +void ADC_Open(ADC_TypeDef *ADCx); //ADC开启,可以软件启动、或硬件触发ADC转换 +void ADC_Close(ADC_TypeDef *ADCx); //ADC关闭,无法软件启动、或硬件触发ADC转换 +void ADC_Start(ADC_TypeDef *ADCx); //启动指定ADC,开始模数转换 +void ADC_Stop(ADC_TypeDef *ADCx); //关闭指定ADC,停止模数转换 -void ADC_Init(ADC_TypeDef * ADCx, ADC_InitStructure * initStruct); //ADC模数转换器初始化 -void ADC_Open(ADC_TypeDef * ADCx); //ADC开启,可以软件启动、或硬件触发ADC转换 -void ADC_Close(ADC_TypeDef * ADCx); //ADC关闭,无法软件启动、或硬件触发ADC转换 -void ADC_Start(ADC_TypeDef * ADCx); //启动指定ADC,开始模数转换 -void ADC_Stop(ADC_TypeDef * ADCx); //关闭指定ADC,停止模数转换 +uint32_t ADC_Read(ADC_TypeDef *ADCx, uint32_t chn); //从指定通道读取转换结果 +uint32_t ADC_IsEOC(ADC_TypeDef *ADCx, uint32_t chn); //指定通道是否End Of Conversion -uint32_t ADC_Read(ADC_TypeDef * ADCx, uint32_t chn); //从指定通道读取转换结果 -uint32_t ADC_IsEOC(ADC_TypeDef * ADCx, uint32_t chn); //指定通道是否End Of Conversion +void ADC_ChnSelect(ADC_TypeDef *ADCx, uint32_t chns); -void ADC_ChnSelect(ADC_TypeDef * ADCx, uint32_t chns); +void ADC_IntEOCEn(ADC_TypeDef *ADCx, uint32_t chn); //转换完成中断使能 +void ADC_IntEOCDis(ADC_TypeDef *ADCx, uint32_t chn); //转换完成中断禁止 +void ADC_IntEOCClr(ADC_TypeDef *ADCx, uint32_t chn); //转换完成中断标志清除 +uint32_t ADC_IntEOCStat(ADC_TypeDef *ADCx, uint32_t chn); //转换完成中断状态 +void ADC_IntOVFEn(ADC_TypeDef *ADCx, uint32_t chn); //数据溢出中断使能 +void ADC_IntOVFDis(ADC_TypeDef *ADCx, uint32_t chn); //数据溢出中断禁止 +void ADC_IntOVFClr(ADC_TypeDef *ADCx, uint32_t chn); //数据溢出中断标志清除 +uint32_t ADC_IntOVFStat(ADC_TypeDef *ADCx, uint32_t chn); //数据溢出中断状态 -void ADC_IntEOCEn(ADC_TypeDef * ADCx, uint32_t chn); //转换完成中断使能 -void ADC_IntEOCDis(ADC_TypeDef * ADCx, uint32_t chn); //转换完成中断禁止 -void ADC_IntEOCClr(ADC_TypeDef * ADCx, uint32_t chn); //转换完成中断标志清除 -uint32_t ADC_IntEOCStat(ADC_TypeDef * ADCx, uint32_t chn); //转换完成中断状态 - -void ADC_IntOVFEn(ADC_TypeDef * ADCx, uint32_t chn); //数据溢出中断使能 -void ADC_IntOVFDis(ADC_TypeDef * ADCx, uint32_t chn); //数据溢出中断禁止 -void ADC_IntOVFClr(ADC_TypeDef * ADCx, uint32_t chn); //数据溢出中断标志清除 -uint32_t ADC_IntOVFStat(ADC_TypeDef * ADCx, uint32_t chn); //数据溢出中断状态 - -void ADC_IntHFULLEn(ADC_TypeDef * ADCx, uint32_t chn); //FIFO半满中断使能 -void ADC_IntHFULLDis(ADC_TypeDef * ADCx, uint32_t chn); //FIFO半满中断禁止 -void ADC_IntHFULLClr(ADC_TypeDef * ADCx, uint32_t chn); //FIFO半满中断标志清除 -uint32_t ADC_IntHFULLStat(ADC_TypeDef * ADCx, uint32_t chn);//FIFO半满中断状态 - -void ADC_IntFULLEn(ADC_TypeDef * ADCx, uint32_t chn); //FIFO满中断使能 -void ADC_IntFULLDis(ADC_TypeDef * ADCx, uint32_t chn); //FIFO满中断禁止 -void ADC_IntFULLClr(ADC_TypeDef * ADCx, uint32_t chn); //FIFO满中断标志清除 -uint32_t ADC_IntFULLStat(ADC_TypeDef * ADCx, uint32_t chn); //FIFO满中断状态 +void ADC_IntHFULLEn(ADC_TypeDef *ADCx, uint32_t chn); //FIFO半满中断使能 +void ADC_IntHFULLDis(ADC_TypeDef *ADCx, uint32_t chn); //FIFO半满中断禁止 +void ADC_IntHFULLClr(ADC_TypeDef *ADCx, uint32_t chn); //FIFO半满中断标志清除 +uint32_t ADC_IntHFULLStat(ADC_TypeDef *ADCx, uint32_t chn); //FIFO半满中断状态 +void ADC_IntFULLEn(ADC_TypeDef *ADCx, uint32_t chn); //FIFO满中断使能 +void ADC_IntFULLDis(ADC_TypeDef *ADCx, uint32_t chn); //FIFO满中断禁止 +void ADC_IntFULLClr(ADC_TypeDef *ADCx, uint32_t chn); //FIFO满中断标志清除 +uint32_t ADC_IntFULLStat(ADC_TypeDef *ADCx, uint32_t chn); //FIFO满中断状态 #endif //__SWM320_ADC_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.c index e7b30e3cb2..f1f7a36ba7 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_can.c -* ˵: SWM320ƬCANģ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_can.c +* 功能说明: SWM320单片机的CAN模块驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -21,584 +21,583 @@ #include "SWM320.h" #include "SWM320_can.h" - /****************************************************************************************************************************************** -* : CAN_Init() -* ˵: CANӿڳʼ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* CAN_InitStructure * initStruct CANӿ趨ֵĽṹ -* : -* ע: +* 函数名称: CAN_Init() +* 功能说明: CAN接口初始化 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* CAN_InitStructure * initStruct 包含CAN接口相关设定值的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_Init(CAN_TypeDef * CANx, CAN_InitStructure * initStruct) -{ - switch((uint32_t)CANx) - { - case ((uint32_t)CAN): - SYS->CLKEN |= (0x01 << SYS_CLKEN_CAN_Pos); - break; - } - - CAN_Close(CANx); //һЩؼĴֻCANرʱ - - CANx->CR &= ~(CAN_CR_LOM_Msk | CAN_CR_STM_Msk | CAN_CR_AFM_Msk); - CANx->CR |= (initStruct->Mode << CAN_CR_LOM_Pos) | - (initStruct->FilterMode << CAN_CR_AFM_Pos); - - CANx->FILTER.AMR[3] = initStruct->FilterMask32b & 0xFF; - CANx->FILTER.AMR[2] = (initStruct->FilterMask32b >> 8) & 0xFF; - CANx->FILTER.AMR[1] = (initStruct->FilterMask32b >> 16) & 0xFF; - CANx->FILTER.AMR[0] = (initStruct->FilterMask32b >> 24) & 0xFF; - - CANx->FILTER.ACR[3] = initStruct->FilterCheck32b & 0xFF; - CANx->FILTER.ACR[2] = (initStruct->FilterCheck32b >> 8) & 0xFF; - CANx->FILTER.ACR[1] = (initStruct->FilterCheck32b >> 16) & 0xFF; - CANx->FILTER.ACR[0] = (initStruct->FilterCheck32b >> 24) & 0xFF; - - CANx->BT1 = (0 << CAN_BT1_SAM_Pos) | - (initStruct->CAN_BS1 << CAN_BT1_TSEG1_Pos) | - (initStruct->CAN_BS2 << CAN_BT1_TSEG2_Pos); - - CANx->BT0 = (initStruct->CAN_SJW << CAN_BT0_SJW_Pos) | - ((SystemCoreClock/2/initStruct->Baudrate/(1 + (initStruct->CAN_BS1 + 1) + (initStruct->CAN_BS2 + 1)) - 1) << CAN_BT0_BRP_Pos); - - CANx->RXERR = 0; //ֻڸλģʽ - CANx->TXERR = 0; - - CANx->IE = (initStruct->RXNotEmptyIEn << CAN_IE_RXDA_Pos) | - (initStruct->RXOverflowIEn << CAN_IE_RXOV_Pos) | - (initStruct->ArbitrLostIEn << CAN_IE_ARBLOST_Pos) | - (initStruct->ErrPassiveIEn << CAN_IE_ERRPASS_Pos); - - switch((uint32_t)CANx) - { - case ((uint32_t)CAN): - if(initStruct->RXNotEmptyIEn | initStruct->RXOverflowIEn | initStruct->ArbitrLostIEn | initStruct->ErrPassiveIEn) - { - NVIC_EnableIRQ(CAN_IRQn); - } - else - { - NVIC_DisableIRQ(CAN_IRQn); - } - break; - } -} - -/****************************************************************************************************************************************** -* : CAN_Open() -* ˵: CANӿڴ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: -******************************************************************************************************************************************/ -void CAN_Open(CAN_TypeDef * CANx) +void CAN_Init(CAN_TypeDef *CANx, CAN_InitStructure *initStruct) { - CANx->CR &= ~(0x01 << CAN_CR_RST_Pos); //˳λģʽ빤ģʽ + switch ((uint32_t)CANx) + { + case ((uint32_t)CAN): + SYS->CLKEN |= (0x01 << SYS_CLKEN_CAN_Pos); + break; + } + + CAN_Close(CANx); //一些关键寄存器只能在CAN关闭时设置 + + CANx->CR &= ~(CAN_CR_LOM_Msk | CAN_CR_STM_Msk | CAN_CR_AFM_Msk); + CANx->CR |= (initStruct->Mode << CAN_CR_LOM_Pos) | + (initStruct->FilterMode << CAN_CR_AFM_Pos); + + CANx->FILTER.AMR[3] = initStruct->FilterMask32b & 0xFF; + CANx->FILTER.AMR[2] = (initStruct->FilterMask32b >> 8) & 0xFF; + CANx->FILTER.AMR[1] = (initStruct->FilterMask32b >> 16) & 0xFF; + CANx->FILTER.AMR[0] = (initStruct->FilterMask32b >> 24) & 0xFF; + + CANx->FILTER.ACR[3] = initStruct->FilterCheck32b & 0xFF; + CANx->FILTER.ACR[2] = (initStruct->FilterCheck32b >> 8) & 0xFF; + CANx->FILTER.ACR[1] = (initStruct->FilterCheck32b >> 16) & 0xFF; + CANx->FILTER.ACR[0] = (initStruct->FilterCheck32b >> 24) & 0xFF; + + CANx->BT1 = (0 << CAN_BT1_SAM_Pos) | + (initStruct->CAN_BS1 << CAN_BT1_TSEG1_Pos) | + (initStruct->CAN_BS2 << CAN_BT1_TSEG2_Pos); + + CANx->BT0 = (initStruct->CAN_SJW << CAN_BT0_SJW_Pos) | + ((SystemCoreClock / 2 / initStruct->Baudrate / (1 + (initStruct->CAN_BS1 + 1) + (initStruct->CAN_BS2 + 1)) - 1) << CAN_BT0_BRP_Pos); + + CANx->RXERR = 0; //只能在复位模式下清除 + CANx->TXERR = 0; + + CANx->IE = (initStruct->RXNotEmptyIEn << CAN_IE_RXDA_Pos) | + (initStruct->RXOverflowIEn << CAN_IE_RXOV_Pos) | + (initStruct->ArbitrLostIEn << CAN_IE_ARBLOST_Pos) | + (initStruct->ErrPassiveIEn << CAN_IE_ERRPASS_Pos); + + switch ((uint32_t)CANx) + { + case ((uint32_t)CAN): + if (initStruct->RXNotEmptyIEn | initStruct->RXOverflowIEn | initStruct->ArbitrLostIEn | initStruct->ErrPassiveIEn) + { + NVIC_EnableIRQ(CAN_IRQn); + } + else + { + NVIC_DisableIRQ(CAN_IRQn); + } + break; + } } /****************************************************************************************************************************************** -* : CAN_Close() -* ˵: CANӿڹر -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_Open() +* 功能说明: CAN接口打开 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_Close(CAN_TypeDef * CANx) +void CAN_Open(CAN_TypeDef *CANx) { - CANx->CR |= (0x01 << CAN_CR_RST_Pos); //븴λģʽܷͺͽ + CANx->CR &= ~(0x01 << CAN_CR_RST_Pos); //退出复位模式,进入工作模式 } /****************************************************************************************************************************************** -* : CAN_Transmit() -* ˵: CAN -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* uint32_t format CAN_FRAME_STD ׼֡ CAN_FRAME_EXT չ֡ -* uint32_t id ϢID -* uint8_t data[] Ҫ͵ -* uint32_t size Ҫ͵ݵĸ -* uint32_t once ֻһΣʹʧܣٲöʧͳNAKҲط -* : -* ע: +* 函数名称: CAN_Close() +* 功能说明: CAN接口关闭 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_Transmit(CAN_TypeDef * CANx, uint32_t format, uint32_t id, uint8_t data[], uint32_t size, uint32_t once) +void CAN_Close(CAN_TypeDef *CANx) { - uint32_t i; - - if(format == CAN_FRAME_STD) - { - CANx->TXFRAME.INFO = (0 << CAN_INFO_FF_Pos) | - (0 << CAN_INFO_RTR_Pos) | - (size << CAN_INFO_DLC_Pos); - - CANx->TXFRAME.DATA[0] = id >> 3; - CANx->TXFRAME.DATA[1] = id << 5; - - for(i = 0; i < size; i++) - { - CANx->TXFRAME.DATA[i+2] = data[i]; - } - } - else //if(format == CAN_FRAME_EXT) - { - CANx->TXFRAME.INFO = (1 << CAN_INFO_FF_Pos) | - (0 << CAN_INFO_RTR_Pos) | - (size << CAN_INFO_DLC_Pos); - - CANx->TXFRAME.DATA[0] = id >> 21; - CANx->TXFRAME.DATA[1] = id >> 13; - CANx->TXFRAME.DATA[2] = id >> 5; - CANx->TXFRAME.DATA[3] = id << 3; - - for(i = 0; i < size; i++) - { - CANx->TXFRAME.DATA[i+4] = data[i]; - } - } - - if(CANx->CR & CAN_CR_STM_Msk) - { - CANx->CMD = (1 << CAN_CMD_SRR_Pos); - } - else - { - if(once == 0) - { - CANx->CMD = (1 << CAN_CMD_TXREQ_Pos); - } - else - { - CANx->CMD = (1 << CAN_CMD_TXREQ_Pos) | (1 << CAN_CMD_ABTTX_Pos); - } - } + CANx->CR |= (0x01 << CAN_CR_RST_Pos); //进入复位模式,不能发送和接收数据 } /****************************************************************************************************************************************** -* : CAN_TransmitRequest() -* ˵: CANԶԶ̽ڵ㷢 -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* uint32_t format CAN_FRAME_STD ׼֡ CAN_FRAME_EXT չ֡ -* uint32_t id ϢID -* uint32_t once ֻһΣʹʧܣٲöʧͳNAKҲط -* : -* ע: +* 函数名称: CAN_Transmit() +* 功能说明: CAN发送数据 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* uint32_t format CAN_FRAME_STD 标准帧 CAN_FRAME_EXT 扩展帧 +* uint32_t id 消息ID +* uint8_t data[] 要发送的数据 +* uint32_t size 要发送的数据的个数 +* uint32_t once 只发送一次,即使发送失败(仲裁丢失、发送出错、NAK)也不尝试重发 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_TransmitRequest(CAN_TypeDef * CANx, uint32_t format, uint32_t id, uint32_t once) +void CAN_Transmit(CAN_TypeDef *CANx, uint32_t format, uint32_t id, uint8_t data[], uint32_t size, uint32_t once) { - if(format == CAN_FRAME_STD) - { - CANx->TXFRAME.INFO = (0 << CAN_INFO_FF_Pos) | - (1 << CAN_INFO_RTR_Pos) | - (0 << CAN_INFO_DLC_Pos); - - CANx->TXFRAME.DATA[0] = id >> 3; - CANx->TXFRAME.DATA[1] = id << 5; - } - else //if(format == CAN_FRAME_EXT) - { - CANx->TXFRAME.INFO = (1 << CAN_INFO_FF_Pos) | - (1 << CAN_INFO_RTR_Pos) | - (0 << CAN_INFO_DLC_Pos); - - CANx->TXFRAME.DATA[0] = id >> 21; - CANx->TXFRAME.DATA[1] = id >> 13; - CANx->TXFRAME.DATA[2] = id >> 5; - CANx->TXFRAME.DATA[3] = id << 3; - } - - if(once == 0) - { - CANx->CMD = (1 << CAN_CMD_TXREQ_Pos); - } - else - { - CANx->CMD = (1 << CAN_CMD_TXREQ_Pos) | (1 << CAN_CMD_ABTTX_Pos); - } + uint32_t i; + + if (format == CAN_FRAME_STD) + { + CANx->TXFRAME.INFO = (0 << CAN_INFO_FF_Pos) | + (0 << CAN_INFO_RTR_Pos) | + (size << CAN_INFO_DLC_Pos); + + CANx->TXFRAME.DATA[0] = id >> 3; + CANx->TXFRAME.DATA[1] = id << 5; + + for (i = 0; i < size; i++) + { + CANx->TXFRAME.DATA[i + 2] = data[i]; + } + } + else //if(format == CAN_FRAME_EXT) + { + CANx->TXFRAME.INFO = (1 << CAN_INFO_FF_Pos) | + (0 << CAN_INFO_RTR_Pos) | + (size << CAN_INFO_DLC_Pos); + + CANx->TXFRAME.DATA[0] = id >> 21; + CANx->TXFRAME.DATA[1] = id >> 13; + CANx->TXFRAME.DATA[2] = id >> 5; + CANx->TXFRAME.DATA[3] = id << 3; + + for (i = 0; i < size; i++) + { + CANx->TXFRAME.DATA[i + 4] = data[i]; + } + } + + if (CANx->CR & CAN_CR_STM_Msk) + { + CANx->CMD = (1 << CAN_CMD_SRR_Pos); + } + else + { + if (once == 0) + { + CANx->CMD = (1 << CAN_CMD_TXREQ_Pos); + } + else + { + CANx->CMD = (1 << CAN_CMD_TXREQ_Pos) | (1 << CAN_CMD_ABTTX_Pos); + } + } } /****************************************************************************************************************************************** -* : CAN_Receive() -* ˵: CAN -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* CAN_RXMessage *msg յϢ洢ڴ˽ṹ -* : -* ע: +* 函数名称: CAN_TransmitRequest() +* 功能说明: CAN发送远程请求,请求远程节点发送数据 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* uint32_t format CAN_FRAME_STD 标准帧 CAN_FRAME_EXT 扩展帧 +* uint32_t id 消息ID +* uint32_t once 只发送一次,即使发送失败(仲裁丢失、发送出错、NAK)也不尝试重发 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_Receive(CAN_TypeDef * CANx, CAN_RXMessage *msg) +void CAN_TransmitRequest(CAN_TypeDef *CANx, uint32_t format, uint32_t id, uint32_t once) { - uint32_t i; - msg->format = (CANx->RXFRAME.INFO & CAN_INFO_FF_Msk) >> CAN_INFO_FF_Pos; - - msg->remote = (CANx->RXFRAME.INFO & CAN_INFO_RTR_Msk) >> CAN_INFO_RTR_Pos; - msg->size = (CANx->RXFRAME.INFO & CAN_INFO_DLC_Msk) >> CAN_INFO_DLC_Pos; - - if(msg->format == CAN_FRAME_STD) - { - msg->id = (CANx->RXFRAME.DATA[0] << 3) | (CANx->RXFRAME.DATA[1] >> 5); - - for(i = 0; i < msg->size; i++) - { - msg->data[i] = CANx->RXFRAME.DATA[i+2]; - } - } - else //if(msg->format == CAN_FRAME_EXT) - { - msg->id = (CANx->RXFRAME.DATA[0] << 21) | (CANx->RXFRAME.DATA[1] << 13) | (CANx->RXFRAME.DATA[2] << 5) | (CANx->RXFRAME.DATA[3] >> 3); - - for(i = 0; i < msg->size; i++) - { - msg->data[i] = CANx->RXFRAME.DATA[i+4]; - } - } - - CANx->CMD = (1 << CAN_CMD_RRB_Pos); + if (format == CAN_FRAME_STD) + { + CANx->TXFRAME.INFO = (0 << CAN_INFO_FF_Pos) | + (1 << CAN_INFO_RTR_Pos) | + (0 << CAN_INFO_DLC_Pos); + + CANx->TXFRAME.DATA[0] = id >> 3; + CANx->TXFRAME.DATA[1] = id << 5; + } + else //if(format == CAN_FRAME_EXT) + { + CANx->TXFRAME.INFO = (1 << CAN_INFO_FF_Pos) | + (1 << CAN_INFO_RTR_Pos) | + (0 << CAN_INFO_DLC_Pos); + + CANx->TXFRAME.DATA[0] = id >> 21; + CANx->TXFRAME.DATA[1] = id >> 13; + CANx->TXFRAME.DATA[2] = id >> 5; + CANx->TXFRAME.DATA[3] = id << 3; + } + + if (once == 0) + { + CANx->CMD = (1 << CAN_CMD_TXREQ_Pos); + } + else + { + CANx->CMD = (1 << CAN_CMD_TXREQ_Pos) | (1 << CAN_CMD_ABTTX_Pos); + } } /****************************************************************************************************************************************** -* : CAN_TXComplete() -* ˵: Ƿ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 Ѿ 0 δ -* ע: ͱAbortҲᴥɣᴥͳɹ +* 函数名称: CAN_Receive() +* 功能说明: CAN接收数据 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* CAN_RXMessage *msg 接收到的消息存储在此结构体变量中 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t CAN_TXComplete(CAN_TypeDef * CANx) +void CAN_Receive(CAN_TypeDef *CANx, CAN_RXMessage *msg) { - return (CANx->SR & CAN_SR_TXBR_Msk) ? 1 : 0; + uint32_t i; + msg->format = (CANx->RXFRAME.INFO & CAN_INFO_FF_Msk) >> CAN_INFO_FF_Pos; + + msg->remote = (CANx->RXFRAME.INFO & CAN_INFO_RTR_Msk) >> CAN_INFO_RTR_Pos; + msg->size = (CANx->RXFRAME.INFO & CAN_INFO_DLC_Msk) >> CAN_INFO_DLC_Pos; + + if (msg->format == CAN_FRAME_STD) + { + msg->id = (CANx->RXFRAME.DATA[0] << 3) | (CANx->RXFRAME.DATA[1] >> 5); + + for (i = 0; i < msg->size; i++) + { + msg->data[i] = CANx->RXFRAME.DATA[i + 2]; + } + } + else //if(msg->format == CAN_FRAME_EXT) + { + msg->id = (CANx->RXFRAME.DATA[0] << 21) | (CANx->RXFRAME.DATA[1] << 13) | (CANx->RXFRAME.DATA[2] << 5) | (CANx->RXFRAME.DATA[3] >> 3); + + for (i = 0; i < msg->size; i++) + { + msg->data[i] = CANx->RXFRAME.DATA[i + 4]; + } + } + + CANx->CMD = (1 << CAN_CMD_RRB_Pos); } /****************************************************************************************************************************************** -* : CAN_TXSuccess() -* ˵: Ƿɹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 ͳɹ 0 ʧ -* ע: +* 函数名称: CAN_TXComplete() +* 功能说明: 发送是否完成 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: uint32_t 1 已经完成 0 还未完成 +* 注意事项: 发送被Abort也会触发发送完成,但不会触发发送成功 ******************************************************************************************************************************************/ -uint32_t CAN_TXSuccess(CAN_TypeDef * CANx) +uint32_t CAN_TXComplete(CAN_TypeDef *CANx) { - return (CANx->SR & CAN_SR_TXOK_Msk) ? 1 : 0; + return (CANx->SR & CAN_SR_TXBR_Msk) ? 1 : 0; } /****************************************************************************************************************************************** -* : CAN_AbortTransmit() -* ˵: ֹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: ڽеķ޷ִֹдʧܲط +* 函数名称: CAN_TXSuccess() +* 功能说明: 发送是否成功 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: uint32_t 1 发送成功 0 发送失败 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_AbortTransmit(CAN_TypeDef * CANx) +uint32_t CAN_TXSuccess(CAN_TypeDef *CANx) { - CANx->CMD = (1 << CAN_CMD_ABTTX_Pos); + return (CANx->SR & CAN_SR_TXOK_Msk) ? 1 : 0; } /****************************************************************************************************************************************** -* : CAN_TXBufferReady() -* ˵: TX BufferǷ׼ÿдϢ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 ׼ 0 δ׼ -* ע: +* 函数名称: CAN_AbortTransmit() +* 功能说明: 终止发送 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 正在进行的发送无法终止,但执行此命令后若发送失败不会再重发 ******************************************************************************************************************************************/ -uint32_t CAN_TXBufferReady(CAN_TypeDef * CANx) +void CAN_AbortTransmit(CAN_TypeDef *CANx) { - return (CANx->SR & CAN_SR_TXBR_Msk) ? 1 : 0; + CANx->CMD = (1 << CAN_CMD_ABTTX_Pos); } /****************************************************************************************************************************************** -* : CAN_RXDataAvailable() -* ˵: RX FIFOǷݿɶ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t 1 ݿɶ 0 û -* ע: +* 函数名称: CAN_TXBufferReady() +* 功能说明: TX Buffer是否准备好可以写入消息 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: uint32_t 1 已准备好 0 未准备好 +* 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t CAN_RXDataAvailable(CAN_TypeDef * CANx) +uint32_t CAN_TXBufferReady(CAN_TypeDef *CANx) { - return (CANx->SR & CAN_SR_RXDA_Msk) ? 1 : 0; + return (CANx->SR & CAN_SR_TXBR_Msk) ? 1 : 0; } /****************************************************************************************************************************************** -* : CAN_SetBaudrate() -* ˵: ò -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* uint32_t baudrate ʣλ -* uint32_t CAN_BS1 CAN_BS1_1tqCAN_BS1_2tq... ... CAN_BS1_16tq -* uint32_t CAN_BS2 CAN_BS2_1tqCAN_BS2_2tq... ... CAN_BS2_8tq -* uint32_t CAN_SJW CAN_SJW_1tqCAN_SJW_2tqCAN_SJW_3tqCAN_SJW_4tq -* : -* ע: ǰҪȵCAN_Close()رCANģ +* 函数名称: CAN_RXDataAvailable() +* 功能说明: RX FIFO中是否有数据可读出 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: uint32_t 1 有数据可读出 0 没有数据 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_SetBaudrate(CAN_TypeDef * CANx, uint32_t baudrate, uint32_t CAN_BS1, uint32_t CAN_BS2, uint32_t CAN_SJW) +uint32_t CAN_RXDataAvailable(CAN_TypeDef *CANx) { - CANx->BT1 = (0 << CAN_BT1_SAM_Pos) | - (CAN_BS1 << CAN_BT1_TSEG1_Pos) | - (CAN_BS2 << CAN_BT1_TSEG2_Pos); - - CANx->BT0 = (CAN_SJW << CAN_BT0_SJW_Pos) | - ((SystemCoreClock/2/baudrate/(1 + (CAN_BS1 + 1) + (CAN_BS2 + 1)) - 1) << CAN_BT0_BRP_Pos); + return (CANx->SR & CAN_SR_RXDA_Msk) ? 1 : 0; } /****************************************************************************************************************************************** -* : CAN_SetFilter32b() -* ˵: ý˲132λ˲ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* uint32_t check maskһ˽յMessageǷԼҪģcheck & (~mask) == ID & (~mask)Messageͨ +* 函数名称: CAN_SetBaudrate() +* 功能说明: 设置波特率 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* uint32_t baudrate 波特率,即位传输速率 +* uint32_t CAN_BS1 CAN_BS1_1tq、CAN_BS1_2tq、... ... 、CAN_BS1_16tq +* uint32_t CAN_BS2 CAN_BS2_1tq、CAN_BS2_2tq、... ... 、CAN_BS2_8tq +* uint32_t CAN_SJW CAN_SJW_1tq、CAN_SJW_2tq、CAN_SJW_3tq、CAN_SJW_4tq +* 输 出: 无 +* 注意事项: 设置前需要先调用CAN_Close()关闭CAN模块 +******************************************************************************************************************************************/ +void CAN_SetBaudrate(CAN_TypeDef *CANx, uint32_t baudrate, uint32_t CAN_BS1, uint32_t CAN_BS2, uint32_t CAN_SJW) +{ + CANx->BT1 = (0 << CAN_BT1_SAM_Pos) | + (CAN_BS1 << CAN_BT1_TSEG1_Pos) | + (CAN_BS2 << CAN_BT1_TSEG2_Pos); + + CANx->BT0 = (CAN_SJW << CAN_BT0_SJW_Pos) | + ((SystemCoreClock / 2 / baudrate / (1 + (CAN_BS1 + 1) + (CAN_BS2 + 1)) - 1) << CAN_BT0_BRP_Pos); +} + +/****************************************************************************************************************************************** +* 函数名称: CAN_SetFilter32b() +* 功能说明: 设置接收滤波器,1个32位滤波器 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* uint32_t check 与mask一起决定了接收到的Message是否是自己需要的:check & (~mask) == ID & (~mask)的Message通过过滤 * uint32_t mask -* : -* ע: ǰҪȵCAN_Close()رCANģ +* 输 出: 无 +* 注意事项: 设置前需要先调用CAN_Close()关闭CAN模块 ******************************************************************************************************************************************/ -void CAN_SetFilter32b(CAN_TypeDef * CANx, uint32_t check, uint32_t mask) +void CAN_SetFilter32b(CAN_TypeDef *CANx, uint32_t check, uint32_t mask) { - CANx->CR &= ~CAN_CR_AFM_Msk; - CANx->CR |= (CAN_FILTER_32b << CAN_CR_AFM_Pos); - - CANx->FILTER.AMR[3] = mask & 0xFF; - CANx->FILTER.AMR[2] = (mask >> 8) & 0xFF; - CANx->FILTER.AMR[1] = (mask >> 16) & 0xFF; - CANx->FILTER.AMR[0] = (mask >> 24) & 0xFF; - - CANx->FILTER.ACR[3] = check & 0xFF; - CANx->FILTER.ACR[2] = (check >> 8) & 0xFF; - CANx->FILTER.ACR[1] = (check >> 16) & 0xFF; - CANx->FILTER.ACR[0] = (check >> 24) & 0xFF; + CANx->CR &= ~CAN_CR_AFM_Msk; + CANx->CR |= (CAN_FILTER_32b << CAN_CR_AFM_Pos); + + CANx->FILTER.AMR[3] = mask & 0xFF; + CANx->FILTER.AMR[2] = (mask >> 8) & 0xFF; + CANx->FILTER.AMR[1] = (mask >> 16) & 0xFF; + CANx->FILTER.AMR[0] = (mask >> 24) & 0xFF; + + CANx->FILTER.ACR[3] = check & 0xFF; + CANx->FILTER.ACR[2] = (check >> 8) & 0xFF; + CANx->FILTER.ACR[1] = (check >> 16) & 0xFF; + CANx->FILTER.ACR[0] = (check >> 24) & 0xFF; } /****************************************************************************************************************************************** -* : CAN_SetFilter16b() -* ˵: ý˲216λ˲ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* uint16_t check1 maskһ˽յMessageǷԼҪģcheck & (~mask) == ID & (~mask)Messageͨ +* 函数名称: CAN_SetFilter16b() +* 功能说明: 设置接收滤波器,2个16位滤波器 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* uint16_t check1 与mask一起决定了接收到的Message是否是自己需要的:check & (~mask) == ID & (~mask)的Message通过过滤 * uint16_t mask1 * uint16_t check2 * uint16_t mask2 -* : -* ע: ǰҪȵCAN_Close()رCANģ +* 输 出: 无 +* 注意事项: 设置前需要先调用CAN_Close()关闭CAN模块 ******************************************************************************************************************************************/ -void CAN_SetFilter16b(CAN_TypeDef * CANx, uint16_t check1, uint16_t mask1, uint16_t check2, uint16_t mask2) +void CAN_SetFilter16b(CAN_TypeDef *CANx, uint16_t check1, uint16_t mask1, uint16_t check2, uint16_t mask2) { - CANx->CR &= ~CAN_CR_AFM_Msk; - CANx->CR |= (CAN_FILTER_16b << CAN_CR_AFM_Pos); - - CANx->FILTER.AMR[3] = mask1 & 0xFF; - CANx->FILTER.AMR[2] = (mask1 >> 8) & 0xFF; - CANx->FILTER.AMR[1] = mask2 & 0xFF; - CANx->FILTER.AMR[0] = (mask2 >> 8) & 0xFF; - - CANx->FILTER.ACR[3] = check1 & 0xFF; - CANx->FILTER.ACR[2] = (check1 >> 8) & 0xFF; - CANx->FILTER.ACR[1] = check2 & 0xFF; - CANx->FILTER.ACR[0] = (check2 >> 8) & 0xFF; + CANx->CR &= ~CAN_CR_AFM_Msk; + CANx->CR |= (CAN_FILTER_16b << CAN_CR_AFM_Pos); + + CANx->FILTER.AMR[3] = mask1 & 0xFF; + CANx->FILTER.AMR[2] = (mask1 >> 8) & 0xFF; + CANx->FILTER.AMR[1] = mask2 & 0xFF; + CANx->FILTER.AMR[0] = (mask2 >> 8) & 0xFF; + + CANx->FILTER.ACR[3] = check1 & 0xFF; + CANx->FILTER.ACR[2] = (check1 >> 8) & 0xFF; + CANx->FILTER.ACR[1] = check2 & 0xFF; + CANx->FILTER.ACR[0] = (check2 >> 8) & 0xFF; } /****************************************************************************************************************************************** -* : CAN_INTRXNotEmptyEn() -* ˵: RX FIFOʱǿգжʹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTRXNotEmptyEn() +* 功能说明: 当RX FIFO中有数据时(非空)触发中断使能 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTRXNotEmptyEn(CAN_TypeDef * CANx) +void CAN_INTRXNotEmptyEn(CAN_TypeDef *CANx) { - CANx->IE |= (1 << CAN_IE_RXDA_Pos); + CANx->IE |= (1 << CAN_IE_RXDA_Pos); } /****************************************************************************************************************************************** -* : CAN_INTRXNotEmptyDis() -* ˵: RX FIFOʱǿգжϽֹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTRXNotEmptyDis() +* 功能说明: 当RX FIFO中有数据时(非空)触发中断禁止 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTRXNotEmptyDis(CAN_TypeDef * CANx) +void CAN_INTRXNotEmptyDis(CAN_TypeDef *CANx) { - CANx->IE &= ~(1 << CAN_IE_RXDA_Pos); + CANx->IE &= ~(1 << CAN_IE_RXDA_Pos); } /****************************************************************************************************************************************** -* : CAN_INTTXBufEmptyEn() -* ˵: TX Bufferʱжʹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTTXBufEmptyEn() +* 功能说明: 当TX Buffer空时触发中断使能 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTTXBufEmptyEn(CAN_TypeDef * CANx) +void CAN_INTTXBufEmptyEn(CAN_TypeDef *CANx) { - CANx->IE |= (1 << CAN_IE_TXBR_Pos); + CANx->IE |= (1 << CAN_IE_TXBR_Pos); } /****************************************************************************************************************************************** -* : CAN_INTTXBufEmptyDis() -* ˵: TX BufferʱжϽֹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTTXBufEmptyDis() +* 功能说明: 当TX Buffer空时触发中断禁止 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTTXBufEmptyDis(CAN_TypeDef * CANx) +void CAN_INTTXBufEmptyDis(CAN_TypeDef *CANx) { - CANx->IE &= ~(1 << CAN_IE_TXBR_Pos); + CANx->IE &= ~(1 << CAN_IE_TXBR_Pos); } /****************************************************************************************************************************************** -* : CAN_INTErrWarningEn() -* ˵: TXERR/RXERRֵﵽError Warning Limitʱжʹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTErrWarningEn() +* 功能说明: TXERR/RXERR计数值达到Error Warning Limit时触发中断使能 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTErrWarningEn(CAN_TypeDef * CANx) +void CAN_INTErrWarningEn(CAN_TypeDef *CANx) { - CANx->IE |= (1 << CAN_IE_ERRWARN_Pos); + CANx->IE |= (1 << CAN_IE_ERRWARN_Pos); } /****************************************************************************************************************************************** -* : CAN_INTErrWarningDis() -* ˵: TXERR/RXERRֵﵽError Warning LimitʱжϽֹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTErrWarningDis() +* 功能说明: TXERR/RXERR计数值达到Error Warning Limit时触发中断禁止 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTErrWarningDis(CAN_TypeDef * CANx) +void CAN_INTErrWarningDis(CAN_TypeDef *CANx) { - CANx->IE &= ~(1 << CAN_IE_ERRWARN_Pos); + CANx->IE &= ~(1 << CAN_IE_ERRWARN_Pos); } /****************************************************************************************************************************************** -* : CAN_INTRXOverflowEn() -* ˵: RX FIFO ʱжʹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTRXOverflowEn() +* 功能说明: RX FIFO 溢出时触发中断使能 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTRXOverflowEn(CAN_TypeDef * CANx) +void CAN_INTRXOverflowEn(CAN_TypeDef *CANx) { - CANx->IE |= (1 << CAN_IE_RXOV_Pos); + CANx->IE |= (1 << CAN_IE_RXOV_Pos); } /****************************************************************************************************************************************** -* : CAN_INTRXOverflowDis() -* ˵: RX FIFO ʱжϽֹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTRXOverflowDis() +* 功能说明: RX FIFO 溢出时触发中断禁止 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTRXOverflowDis(CAN_TypeDef * CANx) +void CAN_INTRXOverflowDis(CAN_TypeDef *CANx) { - CANx->IE &= ~(1 << CAN_IE_RXOV_Pos); + CANx->IE &= ~(1 << CAN_IE_RXOV_Pos); } /****************************************************************************************************************************************** -* : CAN_INTRXOverflowClear() -* ˵: RX FIFO ж -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTRXOverflowClear() +* 功能说明: RX FIFO 溢出中断清除 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTRXOverflowClear(CAN_TypeDef * CANx) +void CAN_INTRXOverflowClear(CAN_TypeDef *CANx) { - CANx->CMD = (1 << CAN_CMD_CLROV_Pos); + CANx->CMD = (1 << CAN_CMD_CLROV_Pos); } /****************************************************************************************************************************************** -* : CAN_INTWakeupEn() -* ˵: ¼жʹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTWakeupEn() +* 功能说明: 唤醒事件触发中断使能 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTWakeupEn(CAN_TypeDef * CANx) +void CAN_INTWakeupEn(CAN_TypeDef *CANx) { - CANx->IE |= (1 << CAN_IE_WKUP_Pos); + CANx->IE |= (1 << CAN_IE_WKUP_Pos); } /****************************************************************************************************************************************** -* : CAN_INTWakeupDis() -* ˵: ¼жϽֹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTWakeupDis() +* 功能说明: 唤醒事件触发中断禁止 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTWakeupDis(CAN_TypeDef * CANx) +void CAN_INTWakeupDis(CAN_TypeDef *CANx) { - CANx->IE &= ~(1 << CAN_IE_WKUP_Pos); + CANx->IE &= ~(1 << CAN_IE_WKUP_Pos); } /****************************************************************************************************************************************** -* : CAN_INTErrPassiveEn() -* ˵: TXERR/RXERRֵﵽ127ʱжʹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTErrPassiveEn() +* 功能说明: TXERR/RXERR计数值达到127时中断使能 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTErrPassiveEn(CAN_TypeDef * CANx) +void CAN_INTErrPassiveEn(CAN_TypeDef *CANx) { - CANx->IE |= (1 << CAN_IE_ERRPASS_Pos); + CANx->IE |= (1 << CAN_IE_ERRPASS_Pos); } /****************************************************************************************************************************************** -* : CAN_INTErrPassiveDis() -* ˵: TXERR/RXERRֵﵽ127ʱжϽֹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTErrPassiveDis() +* 功能说明: TXERR/RXERR计数值达到127时中断禁止 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTErrPassiveDis(CAN_TypeDef * CANx) +void CAN_INTErrPassiveDis(CAN_TypeDef *CANx) { - CANx->IE &= ~(1 << CAN_IE_ERRPASS_Pos); + CANx->IE &= ~(1 << CAN_IE_ERRPASS_Pos); } /****************************************************************************************************************************************** -* : CAN_INTArbitrLostEn() -* ˵: ٲʧжʹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTArbitrLostEn() +* 功能说明: 仲裁失败中断使能 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTArbitrLostEn(CAN_TypeDef * CANx) +void CAN_INTArbitrLostEn(CAN_TypeDef *CANx) { - CANx->IE |= (1 << CAN_IE_ARBLOST_Pos); + CANx->IE |= (1 << CAN_IE_ARBLOST_Pos); } /****************************************************************************************************************************************** -* : CAN_INTArbitrLostDis() -* ˵: ٲʧжϽֹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTArbitrLostDis() +* 功能说明: 仲裁失败中断禁止 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTArbitrLostDis(CAN_TypeDef * CANx) +void CAN_INTArbitrLostDis(CAN_TypeDef *CANx) { - CANx->IE &= ~(1 << CAN_IE_ARBLOST_Pos); + CANx->IE &= ~(1 << CAN_IE_ARBLOST_Pos); } /****************************************************************************************************************************************** -* : CAN_INTBusErrorEn() -* ˵: ߴжʹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTBusErrorEn() +* 功能说明: 总线错误中断使能 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTBusErrorEn(CAN_TypeDef * CANx) +void CAN_INTBusErrorEn(CAN_TypeDef *CANx) { - CANx->IE |= (1 << CAN_IE_BUSERR_Pos); + CANx->IE |= (1 << CAN_IE_BUSERR_Pos); } /****************************************************************************************************************************************** -* : CAN_INTBusErrorDis() -* ˵: ߴжϽֹ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : -* ע: +* 函数名称: CAN_INTBusErrorDis() +* 功能说明: 总线错误中断禁止 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CAN_INTBusErrorDis(CAN_TypeDef * CANx) +void CAN_INTBusErrorDis(CAN_TypeDef *CANx) { - CANx->IE &= ~(1 << CAN_IE_BUSERR_Pos); + CANx->IE &= ~(1 << CAN_IE_BUSERR_Pos); } /****************************************************************************************************************************************** -* : CAN_INTStat() -* ˵: ѯж״̬ -* : CAN_TypeDef * CANx ָҪõCANӿڣЧֵCAN -* : uint32_t ǰж״̬ -* ע: CANx->IFȡ㣬жISRֻܶȡһΣܶζȡ +* 函数名称: CAN_INTStat() +* 功能说明: 查询中断状态 +* 输 入: CAN_TypeDef * CANx 指定要被设置的CAN接口,有效值包括CAN +* 输 出: uint32_t 当前中断状态 +* 注意事项: CANx->IF读取清零,因此在中断ISR中只能读取一次,不能多次读取 ******************************************************************************************************************************************/ -uint32_t CAN_INTStat(CAN_TypeDef * CANx) +uint32_t CAN_INTStat(CAN_TypeDef *CANx) { - return CANx->IF; + return CANx->IF; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.h index 7cdd751ca5..2b31a97c7d 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_can.h @@ -1,130 +1,134 @@ #ifndef __SWM320_CAN_H__ #define __SWM320_CAN_H__ -#define CAN_FRAME_STD 0 -#define CAN_FRAME_EXT 1 +#define CAN_FRAME_STD 0 +#define CAN_FRAME_EXT 1 -typedef struct { - uint8_t Mode; //CAN_MODE_NORMAL、CAN_MODE_LISTEN、CAN_MODE_SELFTEST - uint8_t CAN_BS1; //CAN_BS1_1tq、CAN_BS1_2tq、... ... 、CAN_BS1_16tq - uint8_t CAN_BS2; //CAN_BS2_1tq、CAN_BS2_2tq、... ... 、CAN_BS2_8tq - uint8_t CAN_SJW; //CAN_SJW_1tq、CAN_SJW_2tq、CAN_SJW_3tq、CAN_SJW_4tq - uint32_t Baudrate; //波特率,即位传输速率,取值1--1000000 - uint8_t FilterMode; //CAN_FILTER_16b、CAN_FILTER_32b - union { - uint32_t FilterMask32b; //FilterCheck & (~FilterMask) == ID & (~FilterMask)的Message通过过滤 - struct { // 0 must match 1 don't care - uint16_t FilterMask16b1; - uint16_t FilterMask16b2; - }; - }; - union { - uint32_t FilterCheck32b; - struct { - uint16_t FilterCheck16b1; - uint16_t FilterCheck16b2; - }; - }; - uint8_t RXNotEmptyIEn; //接收FIFO非空,有数据可读 - uint8_t RXOverflowIEn; //接收FIFO溢出,有数据丢失 - uint8_t ArbitrLostIEn; //控制器丢失仲裁变成接收方 - uint8_t ErrPassiveIEn; //接收/发送错误计数值达到127 +typedef struct +{ + uint8_t Mode; //CAN_MODE_NORMAL、CAN_MODE_LISTEN、CAN_MODE_SELFTEST + uint8_t CAN_BS1; //CAN_BS1_1tq、CAN_BS1_2tq、... ... 、CAN_BS1_16tq + uint8_t CAN_BS2; //CAN_BS2_1tq、CAN_BS2_2tq、... ... 、CAN_BS2_8tq + uint8_t CAN_SJW; //CAN_SJW_1tq、CAN_SJW_2tq、CAN_SJW_3tq、CAN_SJW_4tq + uint32_t Baudrate; //波特率,即位传输速率,取值1--1000000 + uint8_t FilterMode; //CAN_FILTER_16b、CAN_FILTER_32b + union + { + uint32_t FilterMask32b; //FilterCheck & (~FilterMask) == ID & (~FilterMask)的Message通过过滤 + struct + { // 0 must match 1 don't care + uint16_t FilterMask16b1; + uint16_t FilterMask16b2; + }; + }; + union + { + uint32_t FilterCheck32b; + struct + { + uint16_t FilterCheck16b1; + uint16_t FilterCheck16b2; + }; + }; + uint8_t RXNotEmptyIEn; //接收FIFO非空,有数据可读 + uint8_t RXOverflowIEn; //接收FIFO溢出,有数据丢失 + uint8_t ArbitrLostIEn; //控制器丢失仲裁变成接收方 + uint8_t ErrPassiveIEn; //接收/发送错误计数值达到127 } CAN_InitStructure; -#define CAN_MODE_NORMAL 0 //常规模式 -#define CAN_MODE_LISTEN 1 //监听模式 -#define CAN_MODE_SELFTEST 2 //自测模式 +#define CAN_MODE_NORMAL 0 //常规模式 +#define CAN_MODE_LISTEN 1 //监听模式 +#define CAN_MODE_SELFTEST 2 //自测模式 -#define CAN_BS1_1tq 0 -#define CAN_BS1_2tq 1 -#define CAN_BS1_3tq 2 -#define CAN_BS1_4tq 3 -#define CAN_BS1_5tq 4 -#define CAN_BS1_6tq 5 -#define CAN_BS1_7tq 6 -#define CAN_BS1_8tq 7 -#define CAN_BS1_9tq 8 -#define CAN_BS1_10tq 9 -#define CAN_BS1_11tq 10 -#define CAN_BS1_12tq 11 -#define CAN_BS1_13tq 12 -#define CAN_BS1_14tq 13 -#define CAN_BS1_15tq 14 -#define CAN_BS1_16tq 15 +#define CAN_BS1_1tq 0 +#define CAN_BS1_2tq 1 +#define CAN_BS1_3tq 2 +#define CAN_BS1_4tq 3 +#define CAN_BS1_5tq 4 +#define CAN_BS1_6tq 5 +#define CAN_BS1_7tq 6 +#define CAN_BS1_8tq 7 +#define CAN_BS1_9tq 8 +#define CAN_BS1_10tq 9 +#define CAN_BS1_11tq 10 +#define CAN_BS1_12tq 11 +#define CAN_BS1_13tq 12 +#define CAN_BS1_14tq 13 +#define CAN_BS1_15tq 14 +#define CAN_BS1_16tq 15 -#define CAN_BS2_1tq 0 -#define CAN_BS2_2tq 1 -#define CAN_BS2_3tq 2 -#define CAN_BS2_4tq 3 -#define CAN_BS2_5tq 4 -#define CAN_BS2_6tq 5 -#define CAN_BS2_7tq 6 -#define CAN_BS2_8tq 7 +#define CAN_BS2_1tq 0 +#define CAN_BS2_2tq 1 +#define CAN_BS2_3tq 2 +#define CAN_BS2_4tq 3 +#define CAN_BS2_5tq 4 +#define CAN_BS2_6tq 5 +#define CAN_BS2_7tq 6 +#define CAN_BS2_8tq 7 -#define CAN_SJW_1tq 0 -#define CAN_SJW_2tq 1 -#define CAN_SJW_3tq 2 -#define CAN_SJW_4tq 3 +#define CAN_SJW_1tq 0 +#define CAN_SJW_2tq 1 +#define CAN_SJW_3tq 2 +#define CAN_SJW_4tq 3 -#define CAN_FILTER_16b 0 //两个16位过滤器 -#define CAN_FILTER_32b 1 //一个32位过滤器 +#define CAN_FILTER_16b 0 //两个16位过滤器 +#define CAN_FILTER_32b 1 //一个32位过滤器 -typedef struct { - uint32_t id; //消息ID - uint8_t format; //帧格式:CAN_FRAME_STD、CAN_FRAME_EXT - uint8_t remote; //消息是否为远程帧 - uint8_t size; //接收到的数据个数 - uint8_t data[8]; //接收到的数据 +typedef struct +{ + uint32_t id; //消息ID + uint8_t format; //帧格式:CAN_FRAME_STD、CAN_FRAME_EXT + uint8_t remote; //消息是否为远程帧 + uint8_t size; //接收到的数据个数 + uint8_t data[8]; //接收到的数据 } CAN_RXMessage; +void CAN_Init(CAN_TypeDef *CANx, CAN_InitStructure *initStruct); +void CAN_Open(CAN_TypeDef *CANx); +void CAN_Close(CAN_TypeDef *CANx); -void CAN_Init(CAN_TypeDef * CANx, CAN_InitStructure * initStruct); -void CAN_Open(CAN_TypeDef * CANx); -void CAN_Close(CAN_TypeDef * CANx); +void CAN_Transmit(CAN_TypeDef *CANx, uint32_t format, uint32_t id, uint8_t data[], uint32_t size, uint32_t once); +void CAN_TransmitRequest(CAN_TypeDef *CANx, uint32_t format, uint32_t id, uint32_t once); +void CAN_Receive(CAN_TypeDef *CANx, CAN_RXMessage *msg); -void CAN_Transmit(CAN_TypeDef * CANx, uint32_t format, uint32_t id, uint8_t data[], uint32_t size, uint32_t once); -void CAN_TransmitRequest(CAN_TypeDef * CANx, uint32_t format, uint32_t id, uint32_t once); -void CAN_Receive(CAN_TypeDef * CANx, CAN_RXMessage *msg); +uint32_t CAN_TXComplete(CAN_TypeDef *CANx); +uint32_t CAN_TXSuccess(CAN_TypeDef *CANx); -uint32_t CAN_TXComplete(CAN_TypeDef * CANx); -uint32_t CAN_TXSuccess(CAN_TypeDef * CANx); +void CAN_AbortTransmit(CAN_TypeDef *CANx); -void CAN_AbortTransmit(CAN_TypeDef * CANx); +uint32_t CAN_TXBufferReady(CAN_TypeDef *CANx); +uint32_t CAN_RXDataAvailable(CAN_TypeDef *CANx); -uint32_t CAN_TXBufferReady(CAN_TypeDef * CANx); -uint32_t CAN_RXDataAvailable(CAN_TypeDef * CANx); +void CAN_SetBaudrate(CAN_TypeDef *CANx, uint32_t baudrate, uint32_t CAN_BS1, uint32_t CAN_BS2, uint32_t CAN_SJW); -void CAN_SetBaudrate(CAN_TypeDef * CANx, uint32_t baudrate, uint32_t CAN_BS1, uint32_t CAN_BS2, uint32_t CAN_SJW); +void CAN_SetFilter32b(CAN_TypeDef *CANx, uint32_t check, uint32_t mask); +void CAN_SetFilter16b(CAN_TypeDef *CANx, uint16_t check1, uint16_t mask1, uint16_t check2, uint16_t mask2); -void CAN_SetFilter32b(CAN_TypeDef * CANx, uint32_t check, uint32_t mask); -void CAN_SetFilter16b(CAN_TypeDef * CANx, uint16_t check1, uint16_t mask1, uint16_t check2, uint16_t mask2); +void CAN_INTRXNotEmptyEn(CAN_TypeDef *CANx); +void CAN_INTRXNotEmptyDis(CAN_TypeDef *CANx); +void CAN_INTTXBufEmptyEn(CAN_TypeDef *CANx); +void CAN_INTTXBufEmptyDis(CAN_TypeDef *CANx); -void CAN_INTRXNotEmptyEn(CAN_TypeDef * CANx); -void CAN_INTRXNotEmptyDis(CAN_TypeDef * CANx); +void CAN_INTErrWarningEn(CAN_TypeDef *CANx); +void CAN_INTErrWarningDis(CAN_TypeDef *CANx); -void CAN_INTTXBufEmptyEn(CAN_TypeDef * CANx); -void CAN_INTTXBufEmptyDis(CAN_TypeDef * CANx); +void CAN_INTRXOverflowEn(CAN_TypeDef *CANx); +void CAN_INTRXOverflowDis(CAN_TypeDef *CANx); +void CAN_INTRXOverflowClear(CAN_TypeDef *CANx); -void CAN_INTErrWarningEn(CAN_TypeDef * CANx); -void CAN_INTErrWarningDis(CAN_TypeDef * CANx); +void CAN_INTWakeupEn(CAN_TypeDef *CANx); +void CAN_INTWakeupDis(CAN_TypeDef *CANx); -void CAN_INTRXOverflowEn(CAN_TypeDef * CANx); -void CAN_INTRXOverflowDis(CAN_TypeDef * CANx); -void CAN_INTRXOverflowClear(CAN_TypeDef * CANx); +void CAN_INTErrPassiveEn(CAN_TypeDef *CANx); +void CAN_INTErrPassiveDis(CAN_TypeDef *CANx); -void CAN_INTWakeupEn(CAN_TypeDef * CANx); -void CAN_INTWakeupDis(CAN_TypeDef * CANx); +void CAN_INTArbitrLostEn(CAN_TypeDef *CANx); +void CAN_INTArbitrLostDis(CAN_TypeDef *CANx); -void CAN_INTErrPassiveEn(CAN_TypeDef * CANx); -void CAN_INTErrPassiveDis(CAN_TypeDef * CANx); +void CAN_INTBusErrorEn(CAN_TypeDef *CANx); +void CAN_INTBusErrorDis(CAN_TypeDef *CANx); -void CAN_INTArbitrLostEn(CAN_TypeDef * CANx); -void CAN_INTArbitrLostDis(CAN_TypeDef * CANx); - -void CAN_INTBusErrorEn(CAN_TypeDef * CANx); -void CAN_INTBusErrorDis(CAN_TypeDef * CANx); - -uint32_t CAN_INTStat(CAN_TypeDef * CANx); +uint32_t CAN_INTStat(CAN_TypeDef *CANx); #endif //__SWM320_CAN_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.c index 52634deebb..d07cd28689 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_crc.c -* ˵: SWM320ƬCRCģ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_crc.c +* 功能说明: SWM320单片机的CRC模块驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -21,31 +21,30 @@ #include "SWM320.h" #include "SWM320_crc.h" - /****************************************************************************************************************************************** -* : CRC_Init() -* ˵: CRC ʼ -* : CRC_TypeDef * CRCx ָҪõCRCӿڣЧֵCRC -* uint32_t mode ģʽЧֵУCRC32_IN32CRC32_IN16CRC32_IN8CRC16_IN16CRC16_IN8 -* uint32_t out_not Ƿȡ -* uint32_t out_rev Ƿת -* uint32_t ini_val CRCʼֵ -* : -* ע: +* 函数名称: CRC_Init() +* 功能说明: CRC 初始化 +* 输 入: CRC_TypeDef * CRCx 指定要被设置的CRC接口,有效值包括CRC +* uint32_t mode 工作模式,有效值有:CRC32_IN32、CRC32_IN16、CRC32_IN8、CRC16_IN16、CRC16_IN8 +* uint32_t out_not 输出结果是否取反 +* uint32_t out_rev 输出结果是否翻转 +* uint32_t ini_val CRC初始值 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void CRC_Init(CRC_TypeDef * CRCx, uint32_t mode, uint32_t out_not, uint32_t out_rev, uint32_t ini_val) +void CRC_Init(CRC_TypeDef *CRCx, uint32_t mode, uint32_t out_not, uint32_t out_rev, uint32_t ini_val) { - switch((uint32_t)CRCx) - { - case ((uint32_t)CRC): - SYS->CLKEN |= (0x01 << SYS_CLKEN_CRC_Pos); - break; - } - - CRCx->CR = (1 << CRC_CR_EN_Pos) | - (mode << CRC_CR_CRC16_Pos) | - (out_not << CRC_CR_ONOT_Pos) | - (out_rev << CRC_CR_OREV_Pos); - - CRCx->INIVAL = ini_val; + switch ((uint32_t)CRCx) + { + case ((uint32_t)CRC): + SYS->CLKEN |= (0x01 << SYS_CLKEN_CRC_Pos); + break; + } + + CRCx->CR = (1 << CRC_CR_EN_Pos) | + (mode << CRC_CR_CRC16_Pos) | + (out_not << CRC_CR_ONOT_Pos) | + (out_rev << CRC_CR_OREV_Pos); + + CRCx->INIVAL = ini_val; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.h index 6a5dd2f781..639db18cd0 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_crc.h @@ -1,16 +1,13 @@ #ifndef __SWM320_CRC_H__ #define __SWM320_CRC_H__ +#define CRC32_IN32 0 //CRC32算法,输入数据32位 +#define CRC32_IN16 2 //CRC32算法,输入数据16位 +#define CRC32_IN8 4 //CRC32算法,输入数据 8位 +#define CRC16_IN16 3 //CRC16算法,输入数据16位 +#define CRC16_IN8 5 //CRC16算法,输入数据 8位 -#define CRC32_IN32 0 //CRC32算法,输入数据32位 -#define CRC32_IN16 2 //CRC32算法,输入数据16位 -#define CRC32_IN8 4 //CRC32算法,输入数据 8位 -#define CRC16_IN16 3 //CRC16算法,输入数据16位 -#define CRC16_IN8 5 //CRC16算法,输入数据 8位 - - -void CRC_Init(CRC_TypeDef * CRCx, uint32_t mode, uint32_t out_not, uint32_t out_rev, uint32_t ini_val); - +void CRC_Init(CRC_TypeDef *CRCx, uint32_t mode, uint32_t out_not, uint32_t out_rev, uint32_t ini_val); /****************************************************************************************************************************************** * 函数名称: CRC_Write() @@ -21,7 +18,7 @@ void CRC_Init(CRC_TypeDef * CRCx, uint32_t mode, uint32_t out_not, uint32_t out_ ******************************************************************************************************************************************/ static __INLINE void CRC_Write(uint32_t data) { - CRC->DATAIN = data; + CRC->DATAIN = data; } /****************************************************************************************************************************************** @@ -33,7 +30,7 @@ static __INLINE void CRC_Write(uint32_t data) ******************************************************************************************************************************************/ static __INLINE uint32_t CRC_Result(void) { - return CRC->RESULT; + return CRC->RESULT; } #endif //__SWM320_CRC_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.c index 78db4ee2dd..b52e8b5f39 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_dma.c -* ˵: SWM320ƬDMA -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_dma.c +* 功能说明: SWM320单片机的DMA功能驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -22,117 +22,119 @@ #include "SWM320_dma.h" /****************************************************************************************************************************************** -* : DMA_CHM_Config() -* ˵: DMAͨãڴ洢䣨FlashRAM䣩 -* : uint32_t chn ָҪõͨЧֵDMA_CH0DMA_CH1DMA_CH2 -* uint32_t src_addr Դֶַ룬ַ2λ00 -* uint32_t src_addr_incr 0 ̶ַ 1 ַ -* uint32_t dst_addr Ŀĵֶַ룬ַ2λ00 -* uint32_t dst_addr_incr 0 ̶ַ 1 ַ -* uint32_t num_word Ҫ˵1024 -* uint32_t int_en жʹܣ1 ݰɺж 0 ݰɺ󲻲ж -* : -* ע: ΪԪֽ +* 函数名称: DMA_CHM_Config() +* 功能说明: DMA通道配置,用于存储器间(如Flash和RAM间)搬运数据 +* 输 入: uint32_t chn 指定要配置的通道,有效值有DMA_CH0、DMA_CH1、DMA_CH2 +* uint32_t src_addr 源地址,必须字对齐,即地址的最低2位必须是00 +* uint32_t src_addr_incr 0 固定地址 1 地址递增 +* uint32_t dst_addr 目的地址,必须字对齐,即地址的最低2位必须是00 +* uint32_t dst_addr_incr 0 固定地址 1 地址递增 +* uint32_t num_word 要搬运的数据字数,最大1024 +* uint32_t int_en 中断使能,1 数据搬运完成后产生中断 0 数据搬运完成后不产生中断 +* 输 出: 无 +* 注意事项: 搬运数据量以字为单元,不是字节 ******************************************************************************************************************************************/ void DMA_CHM_Config(uint32_t chn, uint32_t src_addr, uint32_t src_addr_incr, uint32_t dst_addr, uint32_t dst_addr_incr, uint32_t num_word, uint32_t int_en) { - DMA->EN = 1; //ÿͨԼĿؿƣܿؿһֱ - - DMA_CH_Close(chn); //ǰȹرոͨ - - DMA->CH[chn].SRC = src_addr; - DMA->CH[chn].DST = dst_addr; - - DMA->CH[chn].CR = ((num_word*4-1) << DMA_CR_LEN_Pos) | - (0 << DMA_CR_AUTORE_Pos); - - DMA->CH[chn].AM = (src_addr_incr << DMA_AM_SRCAM_Pos) | - (dst_addr_incr << DMA_AM_DSTAM_Pos) | - (0 << DMA_AM_BURST_Pos); - - DMA->IF = (1 << chn); //жϱ־ - DMA->IE |= (1 << chn); - if(int_en) DMA->IM &= ~(1 << chn); - else DMA->IM |= (1 << chn); - - if(int_en) - { - NVIC_EnableIRQ(DMA_IRQn); - } - else - { - //ܵNVIC_DisalbeIRQ(DMA_IRQn)ΪͨʹDMAж - } + DMA->EN = 1; //每个通道都有自己独立的开关控制,所以总开关可以是一直开启的 + + DMA_CH_Close(chn); //配置前先关闭该通道 + + DMA->CH[chn].SRC = src_addr; + DMA->CH[chn].DST = dst_addr; + + DMA->CH[chn].CR = ((num_word * 4 - 1) << DMA_CR_LEN_Pos) | + (0 << DMA_CR_AUTORE_Pos); + + DMA->CH[chn].AM = (src_addr_incr << DMA_AM_SRCAM_Pos) | + (dst_addr_incr << DMA_AM_DSTAM_Pos) | + (0 << DMA_AM_BURST_Pos); + + DMA->IF = (1 << chn); //清除中断标志 + DMA->IE |= (1 << chn); + if (int_en) + DMA->IM &= ~(1 << chn); + else + DMA->IM |= (1 << chn); + + if (int_en) + { + NVIC_EnableIRQ(DMA_IRQn); + } + else + { + //不能调用NVIC_DisalbeIRQ(DMA_IRQn),因为其他通道可能使用DMA中断 + } } /****************************************************************************************************************************************** -* : DMA_CH_Open() -* ˵: DMAͨ -* : uint32_t chn ָҪõͨЧֵDMA_CH0DMA_CH1DMA_CH2 -* : -* ע: +* 函数名称: DMA_CH_Open() +* 功能说明: DMA通道打开 +* 输 入: uint32_t chn 指定要配置的通道,有效值有DMA_CH0、DMA_CH1、DMA_CH2 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void DMA_CH_Open(uint32_t chn) { - DMA->CH[chn].CR |= (1 << DMA_CR_TXEN_Pos); + DMA->CH[chn].CR |= (1 << DMA_CR_TXEN_Pos); } /****************************************************************************************************************************************** -* : DMA_CH_Close() -* ˵: DMAͨر -* : uint32_t chn ָҪõͨЧֵDMA_CH0DMA_CH1DMA_CH2 -* : -* ע: +* 函数名称: DMA_CH_Close() +* 功能说明: DMA通道关闭 +* 输 入: uint32_t chn 指定要配置的通道,有效值有DMA_CH0、DMA_CH1、DMA_CH2 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void DMA_CH_Close(uint32_t chn) { - DMA->CH[chn].CR &= ~(1 << DMA_CR_TXEN_Pos); + DMA->CH[chn].CR &= ~(1 << DMA_CR_TXEN_Pos); } /****************************************************************************************************************************************** -* : DMA_CH_INTEn() -* ˵: DMAжʹܣݰɺ󴥷ж -* : uint32_t chn ָҪõͨЧֵDMA_CH0DMA_CH1DMA_CH2 -* : -* ע: +* 函数名称: DMA_CH_INTEn() +* 功能说明: DMA中断使能,数据搬运完成后触发中断 +* 输 入: uint32_t chn 指定要配置的通道,有效值有DMA_CH0、DMA_CH1、DMA_CH2 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void DMA_CH_INTEn(uint32_t chn) { - DMA->IM &= ~(1 << chn); + DMA->IM &= ~(1 << chn); } /****************************************************************************************************************************************** -* : DMA_CH_INTDis() -* ˵: DMAжϽֹݰɺ󲻴ж -* : uint32_t chn ָҪõͨЧֵDMA_CH0DMA_CH1DMA_CH2 -* : -* ע: +* 函数名称: DMA_CH_INTDis() +* 功能说明: DMA中断禁止,数据搬运完成后不触发中断 +* 输 入: uint32_t chn 指定要配置的通道,有效值有DMA_CH0、DMA_CH1、DMA_CH2 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void DMA_CH_INTDis(uint32_t chn) { - DMA->IM |= (1 << chn); + DMA->IM |= (1 << chn); } /****************************************************************************************************************************************** -* : DMA_CH_INTClr() -* ˵: DMAжϱ־ -* : uint32_t chn ָҪõͨЧֵDMA_CH0DMA_CH1DMA_CH2 -* : -* ע: +* 函数名称: DMA_CH_INTClr() +* 功能说明: DMA中断标志清除 +* 输 入: uint32_t chn 指定要配置的通道,有效值有DMA_CH0、DMA_CH1、DMA_CH2 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ void DMA_CH_INTClr(uint32_t chn) { - DMA->IF = (1 << chn); + DMA->IF = (1 << chn); } /****************************************************************************************************************************************** -* : DMA_CH_INTStat() -* ˵: DMAж״̬ѯ -* : uint32_t chn ָҪõͨЧֵDMA_CH0DMA_CH1DMA_CH2 -* : uint32_t 1 ݰ 0 ݰδ -* ע: +* 函数名称: DMA_CH_INTStat() +* 功能说明: DMA中断状态查询 +* 输 入: uint32_t chn 指定要配置的通道,有效值有DMA_CH0、DMA_CH1、DMA_CH2 +* 输 出: uint32_t 1 数据搬运完成 0 数据搬运未完成 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t DMA_CH_INTStat(uint32_t chn) -{ - return (DMA->IF & (1 << chn)) ? 1 : 0; +{ + return (DMA->IF & (1 << chn)) ? 1 : 0; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.h index 0857f7d023..b7391a0e9e 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_dma.h @@ -1,20 +1,17 @@ #ifndef __SWM320_DMA_H__ #define __SWM320_DMA_H__ +#define DMA_CH0 0 +#define DMA_CH1 1 +#define DMA_CH2 2 -#define DMA_CH0 0 -#define DMA_CH1 1 -#define DMA_CH2 2 - - -void DMA_CHM_Config(uint32_t chn, uint32_t src_addr, uint32_t src_addr_incr, uint32_t dst_addr, uint32_t dst_addr_incr, uint32_t num_word, uint32_t int_en); //DMA通道配置,用于存储器间(如Flash和RAM间)搬运数据 -void DMA_CH_Open(uint32_t chn); //DMA通道打开 -void DMA_CH_Close(uint32_t chn); //DMA通道关闭 - -void DMA_CH_INTEn(uint32_t chn); //DMA中断使能,数据搬运完成后触发中断 -void DMA_CH_INTDis(uint32_t chn); //DMA中断禁止,数据搬运完成后不触发中断 -void DMA_CH_INTClr(uint32_t chn); //DMA中断标志清除 -uint32_t DMA_CH_INTStat(uint32_t chn); //DMA中断状态查询,1 数据搬运完成 0 数据搬运未完成 +void DMA_CHM_Config(uint32_t chn, uint32_t src_addr, uint32_t src_addr_incr, uint32_t dst_addr, uint32_t dst_addr_incr, uint32_t num_word, uint32_t int_en); //DMA通道配置,用于存储器间(如Flash和RAM间)搬运数据 +void DMA_CH_Open(uint32_t chn); //DMA通道打开 +void DMA_CH_Close(uint32_t chn); //DMA通道关闭 +void DMA_CH_INTEn(uint32_t chn); //DMA中断使能,数据搬运完成后触发中断 +void DMA_CH_INTDis(uint32_t chn); //DMA中断禁止,数据搬运完成后不触发中断 +void DMA_CH_INTClr(uint32_t chn); //DMA中断标志清除 +uint32_t DMA_CH_INTStat(uint32_t chn); //DMA中断状态查询,1 数据搬运完成 0 数据搬运未完成 #endif //__SWM320_DMA_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.c index 8275b602d1..f4a15e8c2c 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_exti.c -* ˵: SWM320ƬⲿжϹ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_exti.c +* 功能说明: SWM320单片机的外部中断功能驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * ******************************************************************************************************************************************* * @attention @@ -21,111 +21,111 @@ #include "SWM320_exti.h" /****************************************************************************************************************************************** -* : EXTI_Init() -* ˵: ָⲿжϳʼ -* : GPIO_TypeDef * GPIOx ָⲿжϵGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָⲿжϵGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* uint32_t mode ЧֵEXTI_FALL_EDGEEXTI_RISE_EDGEEXTI_BOTH_EDGEEXTI_LOW_LEVELEXTI_HIGH_LEVEL -* : -* ע: GPIOAGPIOBGPIOCGPIOMPIN0--7żԽNVICежϣGPIOA0_IRQnҲԽNVICжϣGPIOA_IRQn -* Բڴ˺еNVIC_EnableIRQ()ʹNVICжϣӶԸҪNVIC_EnableIRQ(GPIOA0_IRQn)NVIC_EnableIRQ(GPIOA_IRQn) +* 函数名称: EXTI_Init() +* 功能说明: 指定引脚外部中断初始化 +* 输 入: GPIO_TypeDef * GPIOx 指定产生外部中断的GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定产生外部中断的GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* uint32_t mode 有效值有EXTI_FALL_EDGE、EXTI_RISE_EDGE、EXTI_BOTH_EDGE、EXTI_LOW_LEVEL、EXTI_HIGH_LEVEL +* 输 出: 无 +* 注意事项: 由于GPIOA、GPIOB、GPIOC、GPIOM的PIN0--7引脚即可以接入NVIC中的引脚中断(如GPIOA0_IRQn),也可以接入NVIC的组中断(GPIOA_IRQn), +* 所以不在此函数中调用NVIC_EnableIRQ()使能NVIC中断,从而可以根据需要调用NVIC_EnableIRQ(GPIOA0_IRQn)和NVIC_EnableIRQ(GPIOA_IRQn) ******************************************************************************************************************************************/ -void EXTI_Init(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t mode) +void EXTI_Init(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t mode) { - EXTI_Close(GPIOx, n); //ùؼĴǰȹر - - if(mode & 0x10) - { - GPIOx->INTLVLTRG |= (0x01 << n); //ƽ - - if(mode & 0x01) - GPIOx->INTRISEEN |= (0x01 << n); //ߵƽ - else - GPIOx->INTRISEEN &= ~(0x01 << n); //͵ƽ - } - else - { - GPIOx->INTLVLTRG &= ~(0x01 << n); //ش - - if(mode & 0x02) - { - GPIOx->INTBE |= (0x01 << n); //˫ش - } - else - { - GPIOx->INTBE &= ~(0x01 << n); //ش - - if(mode & 0x01) - GPIOx->INTRISEEN |= (0x01 << n); //ش - else - GPIOx->INTRISEEN &= ~(0x01 << n); //½ش - } - } - - GPIOx->INTCLR = (1 << n); //Ϊģʽÿܲж + EXTI_Close(GPIOx, n); //配置关键寄存器前先关闭 + + if (mode & 0x10) + { + GPIOx->INTLVLTRG |= (0x01 << n); //电平触发 + + if (mode & 0x01) + GPIOx->INTRISEEN |= (0x01 << n); //高电平触发 + else + GPIOx->INTRISEEN &= ~(0x01 << n); //低电平触发 + } + else + { + GPIOx->INTLVLTRG &= ~(0x01 << n); //边沿触发 + + if (mode & 0x02) + { + GPIOx->INTBE |= (0x01 << n); //双边沿触发 + } + else + { + GPIOx->INTBE &= ~(0x01 << n); //单边沿触发 + + if (mode & 0x01) + GPIOx->INTRISEEN |= (0x01 << n); //上升沿触发 + else + GPIOx->INTRISEEN &= ~(0x01 << n); //下降沿触发 + } + } + + GPIOx->INTCLR = (1 << n); //清除掉因为模式配置可能产生的中断 } /****************************************************************************************************************************************** -* : EXTI_Open() -* ˵: ָⲿжϴ򿪣ʹܣ -* : GPIO_TypeDef * GPIOx ָⲿжϵGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָⲿжϵGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* : -* ע: +* 函数名称: EXTI_Open() +* 功能说明: 指定引脚外部中断打开(即使能) +* 输 入: GPIO_TypeDef * GPIOx 指定产生外部中断的GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定产生外部中断的GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void EXTI_Open(GPIO_TypeDef * GPIOx, uint32_t n) +void EXTI_Open(GPIO_TypeDef *GPIOx, uint32_t n) { - GPIOx->INTEN |= (0x01 << n); + GPIOx->INTEN |= (0x01 << n); } /****************************************************************************************************************************************** -* : EXTI_Close() -* ˵: ָⲿжϹرգܣ -* : GPIO_TypeDef * GPIOx ָⲿжϵGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָⲿжϵGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* : -* ע: +* 函数名称: EXTI_Close() +* 功能说明: 指定引脚外部中断关闭(即禁能) +* 输 入: GPIO_TypeDef * GPIOx 指定产生外部中断的GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定产生外部中断的GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void EXTI_Close(GPIO_TypeDef * GPIOx, uint32_t n) +void EXTI_Close(GPIO_TypeDef *GPIOx, uint32_t n) { - GPIOx->INTEN &= ~(0x01 << n); + GPIOx->INTEN &= ~(0x01 << n); } /****************************************************************************************************************************************** -* : EXTI_State() -* ˵: ָǷ񴥷ж -* : GPIO_TypeDef * GPIOx ָⲿжϵGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָⲿжϵGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* : uint32_t 1 Ŵж 0 δж -* ע: +* 函数名称: EXTI_State() +* 功能说明: 指定引脚是否触发了中断 +* 输 入: GPIO_TypeDef * GPIOx 指定产生外部中断的GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定产生外部中断的GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* 输 出: uint32_t 1 此引脚触发了中断 0 此引脚未触发中断 +* 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t EXTI_State(GPIO_TypeDef * GPIOx, uint32_t n) +uint32_t EXTI_State(GPIO_TypeDef *GPIOx, uint32_t n) { - return (GPIOx->INTSTAT >> n) & 0x01; + return (GPIOx->INTSTAT >> n) & 0x01; } /****************************************************************************************************************************************** -* : EXTI_RawState() -* ˵: ָǷ/жϴжϹرʱͨô˺ԲѯķʽǷ/жϴ -* : GPIO_TypeDef * GPIOx ָⲿжϵGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָⲿжϵGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* : uint32_t 1 /жϴ 0 δ/жϴ -* ע: +* 函数名称: EXTI_RawState() +* 功能说明: 指定引脚是否满足过/了中断触发条件,当此中断关闭时可通过调用此函数以查询的方式检测引脚上是否满足过/了中断触发条件 +* 输 入: GPIO_TypeDef * GPIOx 指定产生外部中断的GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定产生外部中断的GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* 输 出: uint32_t 1 此引脚满足过/了中断触发条件 0 此引脚未满足过/了中断触发条件 +* 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t EXTI_RawState(GPIO_TypeDef * GPIOx, uint32_t n) +uint32_t EXTI_RawState(GPIO_TypeDef *GPIOx, uint32_t n) { - return (GPIOx->INTRAWSTAT >> n) & 0x01; + return (GPIOx->INTRAWSTAT >> n) & 0x01; } /****************************************************************************************************************************************** -* : EXTI_Clear() -* ˵: ָⲿжжϱ־ٴνжϣ -* : GPIO_TypeDef * GPIOx ָⲿжϵGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָⲿжϵGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* : -* ע: ֻشжϵı־ƽжϵı־޷ֻŵƽжϴӲԶ +* 函数名称: EXTI_Clear() +* 功能说明: 指定引脚外部中断清除(即清除中断标志,以免再次进入此中断) +* 输 入: GPIO_TypeDef * GPIOx 指定产生外部中断的GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定产生外部中断的GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* 输 出: 无 +* 注意事项: 只能清除边沿触发中断的标志,电平触发中断的标志无法清除,只能在引脚电平不符合中断触发条件后硬件自动清除 ******************************************************************************************************************************************/ -void EXTI_Clear(GPIO_TypeDef * GPIOx, uint32_t n) +void EXTI_Clear(GPIO_TypeDef *GPIOx, uint32_t n) { - GPIOx->INTCLR = (0x01 << n); + GPIOx->INTCLR = (0x01 << n); } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.h index 529770e6a6..818d647745 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_exti.h @@ -1,20 +1,18 @@ #ifndef __SWM320_EXTI_H__ -#define __SWM320_EXTI_H__ +#define __SWM320_EXTI_H__ -void EXTI_Init(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t mode); //指定引脚外部中断初始化 -void EXTI_Open(GPIO_TypeDef * GPIOx, uint32_t n); //指定引脚外部中断打开(即使能) -void EXTI_Close(GPIO_TypeDef * GPIOx, uint32_t n); //指定引脚外部中断关闭(即禁能) +void EXTI_Init(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t mode); //指定引脚外部中断初始化 +void EXTI_Open(GPIO_TypeDef *GPIOx, uint32_t n); //指定引脚外部中断打开(即使能) +void EXTI_Close(GPIO_TypeDef *GPIOx, uint32_t n); //指定引脚外部中断关闭(即禁能) -uint32_t EXTI_State(GPIO_TypeDef * GPIOx, uint32_t n); //指定引脚是否触发了中断 -uint32_t EXTI_RawState(GPIO_TypeDef * GPIOx, uint32_t n); //指定引脚是否满足过/了中断触发条件,当此中断关闭时可通过调用此函数以查询的方式检测引脚上是否满足过/了中断触发条件 -void EXTI_Clear(GPIO_TypeDef * GPIOx, uint32_t n); //指定引脚外部中断清除(即清除中断标志,以免再次进入此中断) - - -#define EXTI_FALL_EDGE 0x00 //下降沿触发中断 -#define EXTI_RISE_EDGE 0x01 //上升沿触发中断 -#define EXTI_BOTH_EDGE 0x02 //双边沿触发中断 -#define EXTI_LOW_LEVEL 0x10 //低电平触发中断 -#define EXTI_HIGH_LEVEL 0x11 //高电平触发中断 +uint32_t EXTI_State(GPIO_TypeDef *GPIOx, uint32_t n); //指定引脚是否触发了中断 +uint32_t EXTI_RawState(GPIO_TypeDef *GPIOx, uint32_t n); //指定引脚是否满足过/了中断触发条件,当此中断关闭时可通过调用此函数以查询的方式检测引脚上是否满足过/了中断触发条件 +void EXTI_Clear(GPIO_TypeDef *GPIOx, uint32_t n); //指定引脚外部中断清除(即清除中断标志,以免再次进入此中断) +#define EXTI_FALL_EDGE 0x00 //下降沿触发中断 +#define EXTI_RISE_EDGE 0x01 //上升沿触发中断 +#define EXTI_BOTH_EDGE 0x02 //双边沿触发中断 +#define EXTI_LOW_LEVEL 0x10 //低电平触发中断 +#define EXTI_HIGH_LEVEL 0x11 //高电平触发中断 #endif //__SWM320_EXTI_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.c index d384125db3..0d2b19812f 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.c @@ -19,13 +19,11 @@ #include "SWM320.h" #include "SWM320_flash.h" - IAP_Cache_Reset_t IAP_Cache_Reset = (IAP_Cache_Reset_t)0x11000601; IAP_Flash_Param_t IAP_Flash_Param = (IAP_Flash_Param_t)0x11000681; IAP_Flash_Erase_t IAP_Flash_Erase = (IAP_Flash_Erase_t)0x11000781; IAP_Flash_Write_t IAP_Flash_Write = (IAP_Flash_Write_t)0x11000801; - /****************************************************************************************************************************************** * 函数名称: FLASH_Erase() * 功能说明: 片内Flash擦除 @@ -34,14 +32,14 @@ IAP_Flash_Write_t IAP_Flash_Write = (IAP_Flash_Write_t)0x11000801; * 注意事项: 无 ******************************************************************************************************************************************/ void FLASH_Erase(uint32_t addr) -{ - __disable_irq(); - - IAP_Flash_Erase(addr / 0x1000); - - IAP_Cache_Reset(); - - __enable_irq(); +{ + __disable_irq(); + + IAP_Flash_Erase(addr / 0x1000); + + IAP_Cache_Reset(); + + __enable_irq(); } /****************************************************************************************************************************************** @@ -55,13 +53,13 @@ void FLASH_Erase(uint32_t addr) ******************************************************************************************************************************************/ void FLASH_Write(uint32_t addr, uint32_t buff[], uint32_t count) { - __disable_irq(); - - IAP_Flash_Write(addr, (uint32_t)buff, count/4); - - IAP_Cache_Reset(); - - __enable_irq(); + __disable_irq(); + + IAP_Flash_Write(addr, (uint32_t)buff, count / 4); + + IAP_Cache_Reset(); + + __enable_irq(); } /****************************************************************************************************************************************** @@ -73,25 +71,25 @@ void FLASH_Write(uint32_t addr, uint32_t buff[], uint32_t count) ******************************************************************************************************************************************/ void Flash_Param_at_xMHz(uint32_t x) { - __disable_irq(); - switch(x) - { - case 30: - IAP_Flash_Param(0x489, 0xabf41f25); - break; - - case 40: - IAP_Flash_Param(0x489, 0xabf42929); - break; - - case 80: - IAP_Flash_Param(0x489, 0xabf8524d); - break; - - case 120: - default: - IAP_Flash_Param(0x48a, 0xabfc7a6e); - break; - } - __enable_irq(); + __disable_irq(); + switch (x) + { + case 30: + IAP_Flash_Param(0x489, 0xabf41f25); + break; + + case 40: + IAP_Flash_Param(0x489, 0xabf42929); + break; + + case 80: + IAP_Flash_Param(0x489, 0xabf8524d); + break; + + case 120: + default: + IAP_Flash_Param(0x48a, 0xabfc7a6e); + break; + } + __enable_irq(); } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.h index 40f64fac42..0352eeef82 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_flash.h @@ -1,14 +1,11 @@ #ifndef __SWM320_FLASH_H__ #define __SWM320_FLASH_H__ - void FLASH_Erase(uint32_t addr); void FLASH_Write(uint32_t addr, uint32_t buff[], uint32_t count); void Flash_Param_at_xMHz(uint32_t x); - - typedef void (*IAP_Cache_Reset_t)(void); typedef void (*IAP_Flash_Param_t)(uint32_t cfg0, uint32_t cfg1); typedef void (*IAP_Flash_Erase_t)(uint32_t sector); @@ -19,5 +16,4 @@ extern IAP_Flash_Param_t IAP_Flash_Param; extern IAP_Flash_Erase_t IAP_Flash_Erase; extern IAP_Flash_Write_t IAP_Flash_Write; - #endif //__SWM320_FLASH_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.c index 932608a9e9..29c10c132f 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_gpio.c -* ˵: SWM320Ƭͨ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_gpio.c +* 功能说明: SWM320单片机的通用输入输出功能驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -21,358 +21,357 @@ #include "SWM320.h" #include "SWM320_gpio.h" - /****************************************************************************************************************************************** -* : GPIO_Init() -* ˵: ųʼŷ衢衢© -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* uint32_t dir ŷ0 1 -* uint32_t pull_up 裬0 ر 1 -* uint32_t pull_down 裬0 ر 1 -* : -* ע: GPIOAGPIOCGPIOMGPIOPֻGPIOBGPIONֻPN0PN1PN2û +* 函数名称: GPIO_Init() +* 功能说明: 引脚初始化,包含引脚方向、上拉电阻、下拉电阻、开漏输出 +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* uint32_t dir 引脚方向,0 输入 1 输出 +* uint32_t pull_up 上拉电阻,0 关闭上拉 1 开启上拉 +* uint32_t pull_down 下拉电阻,0 关闭下拉 1 开启下拉 +* 输 出: 无 +* 注意事项: GPIOA、GPIOC、GPIOM、GPIOP只有上拉,GPIOB、GPION只有下拉(PN0、PN1、PN2三个引脚有上拉没下拉) ******************************************************************************************************************************************/ -void GPIO_Init(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t dir, uint32_t pull_up, uint32_t pull_down) +void GPIO_Init(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t dir, uint32_t pull_up, uint32_t pull_down) { - switch((uint32_t)GPIOx) - { - case ((uint32_t)GPIOA): - SYS->CLKEN |= (0x01 << SYS_CLKEN_GPIOA_Pos); - - PORT_Init(PORTA, n, 0, 1); //PORTA.PINnΪGPIOܣ뿪 - if(dir == 1) - { - GPIOA->DIR |= (0x01 << n); - } - else - { - GPIOA->DIR &= ~(0x01 << n); - } - - if(pull_up == 1) - PORT->PORTA_PULLU |= (0x01 << n); - else - PORT->PORTA_PULLU &= ~(0x01 << n); - break; - - case ((uint32_t)GPIOB): - SYS->CLKEN |= (0x01 << SYS_CLKEN_GPIOB_Pos); - - PORT_Init(PORTB, n, 0, 1); //PORTB.PINnΪGPIOܣ뿪 - if(dir == 1) - { - GPIOB->DIR |= (0x01 << n); - } - else - { - GPIOB->DIR &= ~(0x01 << n); - } - - if(pull_down == 1) - PORT->PORTB_PULLD |= (0x01 << n); - else - PORT->PORTB_PULLD &= ~(0x01 << n); - break; + switch ((uint32_t)GPIOx) + { + case ((uint32_t)GPIOA): + SYS->CLKEN |= (0x01 << SYS_CLKEN_GPIOA_Pos); - case ((uint32_t)GPIOC): - SYS->CLKEN |= (0x01 << SYS_CLKEN_GPIOC_Pos); - - PORT_Init(PORTC, n, 0, 1); //PORTC.PINnΪGPIOܣ뿪 - if(dir == 1) - { - GPIOC->DIR |= (0x01 << n); - } - else - { - GPIOC->DIR &= ~(0x01 << n); - } - - if(pull_up == 1) - PORT->PORTC_PULLU |= (0x01 << n); - else - PORT->PORTC_PULLU &= ~(0x01 << n); - break; - - case ((uint32_t)GPIOM): - SYS->CLKEN |= (0x01 << SYS_CLKEN_GPIOM_Pos); - - PORT_Init(PORTM, n, 0, 1); //PORTM.PINnΪGPIOܣ뿪 - if(dir == 1) - { - GPIOM->DIR |= (0x01 << n); - } - else - { - GPIOM->DIR &= ~(0x01 << n); - } - - if(pull_up == 1) - PORT->PORTM_PULLU |= (0x01 << n); - else - PORT->PORTM_PULLU &= ~(0x01 << n); - break; - - case ((uint32_t)GPION): - SYS->CLKEN |= (0x01 << SYS_CLKEN_GPION_Pos); - - PORT_Init(PORTN, n, 0, 1); //PORTN.PINnΪGPIOܣ뿪 - if(dir == 1) - { - GPION->DIR |= (0x01 << n); - } - else - { - GPION->DIR &= ~(0x01 << n); - } - - if(pull_down == 1) - PORT->PORTN_PULLD |= (0x01 << n); - else - PORT->PORTN_PULLD &= ~(0x01 << n); - break; - - case ((uint32_t)GPIOP): - SYS->CLKEN |= (0x01 << SYS_CLKEN_GPIOP_Pos); - - PORT_Init(PORTP, n, 0, 1); //PORTP.PINnΪGPIOܣ뿪 - if(dir == 1) - { - GPIOP->DIR |= (0x01 << n); - } - else - { - GPIOP->DIR &= ~(0x01 << n); - } - - if(pull_up == 1) - PORT->PORTP_PULLU |= (0x01 << n); - else - PORT->PORTP_PULLU &= ~(0x01 << n); - break; - } + PORT_Init(PORTA, n, 0, 1); //PORTA.PINn引脚配置为GPIO功能,数字输入开启 + if (dir == 1) + { + GPIOA->DIR |= (0x01 << n); + } + else + { + GPIOA->DIR &= ~(0x01 << n); + } + + if (pull_up == 1) + PORT->PORTA_PULLU |= (0x01 << n); + else + PORT->PORTA_PULLU &= ~(0x01 << n); + break; + + case ((uint32_t)GPIOB): + SYS->CLKEN |= (0x01 << SYS_CLKEN_GPIOB_Pos); + + PORT_Init(PORTB, n, 0, 1); //PORTB.PINn引脚配置为GPIO功能,数字输入开启 + if (dir == 1) + { + GPIOB->DIR |= (0x01 << n); + } + else + { + GPIOB->DIR &= ~(0x01 << n); + } + + if (pull_down == 1) + PORT->PORTB_PULLD |= (0x01 << n); + else + PORT->PORTB_PULLD &= ~(0x01 << n); + break; + + case ((uint32_t)GPIOC): + SYS->CLKEN |= (0x01 << SYS_CLKEN_GPIOC_Pos); + + PORT_Init(PORTC, n, 0, 1); //PORTC.PINn引脚配置为GPIO功能,数字输入开启 + if (dir == 1) + { + GPIOC->DIR |= (0x01 << n); + } + else + { + GPIOC->DIR &= ~(0x01 << n); + } + + if (pull_up == 1) + PORT->PORTC_PULLU |= (0x01 << n); + else + PORT->PORTC_PULLU &= ~(0x01 << n); + break; + + case ((uint32_t)GPIOM): + SYS->CLKEN |= (0x01 << SYS_CLKEN_GPIOM_Pos); + + PORT_Init(PORTM, n, 0, 1); //PORTM.PINn引脚配置为GPIO功能,数字输入开启 + if (dir == 1) + { + GPIOM->DIR |= (0x01 << n); + } + else + { + GPIOM->DIR &= ~(0x01 << n); + } + + if (pull_up == 1) + PORT->PORTM_PULLU |= (0x01 << n); + else + PORT->PORTM_PULLU &= ~(0x01 << n); + break; + + case ((uint32_t)GPION): + SYS->CLKEN |= (0x01 << SYS_CLKEN_GPION_Pos); + + PORT_Init(PORTN, n, 0, 1); //PORTN.PINn引脚配置为GPIO功能,数字输入开启 + if (dir == 1) + { + GPION->DIR |= (0x01 << n); + } + else + { + GPION->DIR &= ~(0x01 << n); + } + + if (pull_down == 1) + PORT->PORTN_PULLD |= (0x01 << n); + else + PORT->PORTN_PULLD &= ~(0x01 << n); + break; + + case ((uint32_t)GPIOP): + SYS->CLKEN |= (0x01 << SYS_CLKEN_GPIOP_Pos); + + PORT_Init(PORTP, n, 0, 1); //PORTP.PINn引脚配置为GPIO功能,数字输入开启 + if (dir == 1) + { + GPIOP->DIR |= (0x01 << n); + } + else + { + GPIOP->DIR &= ~(0x01 << n); + } + + if (pull_up == 1) + PORT->PORTP_PULLU |= (0x01 << n); + else + PORT->PORTP_PULLU &= ~(0x01 << n); + break; + } } /****************************************************************************************************************************************** -* : GPIO_SetBit() -* ˵: ָŵƽø -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* : -* ע: +* 函数名称: GPIO_SetBit() +* 功能说明: 将参数指定的引脚电平置高 +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void GPIO_SetBit(GPIO_TypeDef * GPIOx, uint32_t n) +void GPIO_SetBit(GPIO_TypeDef *GPIOx, uint32_t n) { - GPIOx->DATA |= (0x01 << n); + GPIOx->DATA |= (0x01 << n); } /****************************************************************************************************************************************** -* : GPIO_ClrBit() -* ˵: ָŵƽõ -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* : -* ע: +* 函数名称: GPIO_ClrBit() +* 功能说明: 将参数指定的引脚电平置低 +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void GPIO_ClrBit(GPIO_TypeDef * GPIOx, uint32_t n) +void GPIO_ClrBit(GPIO_TypeDef *GPIOx, uint32_t n) { - GPIOx->DATA &= ~(0x01 << n); + GPIOx->DATA &= ~(0x01 << n); } /****************************************************************************************************************************************** -* : GPIO_InvBit() -* ˵: ָŵƽת -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* : -* ע: +* 函数名称: GPIO_InvBit() +* 功能说明: 将参数指定的引脚电平反转 +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void GPIO_InvBit(GPIO_TypeDef * GPIOx, uint32_t n) +void GPIO_InvBit(GPIO_TypeDef *GPIOx, uint32_t n) { - GPIOx->DATA ^= (0x01 << n); + GPIOx->DATA ^= (0x01 << n); } /****************************************************************************************************************************************** -* : GPIO_GetBit() -* ˵: ȡָŵĵƽ״̬ -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* : ָŵĵƽ״̬ 0 ͵ƽ 1 ߵƽ -* ע: +* 函数名称: GPIO_GetBit() +* 功能说明: 读取参数指定的引脚的电平状态 +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* 输 出: 参数指定的引脚的电平状态 0 低电平 1 高电平 +* 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t GPIO_GetBit(GPIO_TypeDef * GPIOx, uint32_t n) -{ - return ((GPIOx->DATA >> n) & 0x01); -} - -/****************************************************************************************************************************************** -* : GPIO_SetBits() -* ˵: ָĴnʼwλŵĵƽø -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* uint32_t w ָҪŵƽøߵŵĸ -* : -* ע: -******************************************************************************************************************************************/ -void GPIO_SetBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w) +uint32_t GPIO_GetBit(GPIO_TypeDef *GPIOx, uint32_t n) { - uint32_t bits; - - bits = 0xFFFFFF >> (24 - w); - - GPIOx->DATA |= (bits << n); + return ((GPIOx->DATA >> n) & 0x01); } /****************************************************************************************************************************************** -* : GPIO_ClrBits() -* ˵: ָĴnʼwλŵĵƽõ -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* uint32_t w ָҪŵƽõ͵ŵĸ -* : -* ע: +* 函数名称: GPIO_SetBits() +* 功能说明: 将参数指定的从n开始的w位连续引脚的电平置高 +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* uint32_t w 指定要将引脚电平置高的引脚的个数 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void GPIO_ClrBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w) +void GPIO_SetBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w) { - uint32_t bits; - - bits = 0xFFFFFF >> (24 - w); - - GPIOx->DATA &= ~(bits << n); + uint32_t bits; + + bits = 0xFFFFFF >> (24 - w); + + GPIOx->DATA |= (bits << n); } /****************************************************************************************************************************************** -* : GPIO_InvBits() -* ˵: ָĴnʼwλŵĵƽת -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* uint32_t w ָҪŵƽתŵĸ -* : -* ע: +* 函数名称: GPIO_ClrBits() +* 功能说明: 将参数指定的从n开始的w位连续引脚的电平置低 +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* uint32_t w 指定要将引脚电平置低的引脚的个数 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void GPIO_InvBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w) +void GPIO_ClrBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w) { - uint32_t bits; - - bits = 0xFFFFFF >> (24 - w); - - GPIOx->DATA ^= (bits << n); + uint32_t bits; + + bits = 0xFFFFFF >> (24 - w); + + GPIOx->DATA &= ~(bits << n); } /****************************************************************************************************************************************** -* : GPIO_GetBits() -* ˵: ȡָĴnʼwλŵĵƽ״̬ -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOMGPIONGPIOP -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN22PIN23 -* uint32_t w ָҪŵƽøߵŵĸ -* : ָĴnʼwλŵĵƽ״̬ 0 ͵ƽ 1 ߵƽ -* ֵĵ0λʾnĵƽ״ֵ̬ĵ1λʾn+1ĵƽ״̬... ...ֵĵwλʾn+wĵƽ״̬ -* ע: +* 函数名称: GPIO_InvBits() +* 功能说明: 将参数指定的从n开始的w位连续引脚的电平反转 +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* uint32_t w 指定要将引脚电平反转的引脚的个数 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t GPIO_GetBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w) +void GPIO_InvBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w) { - uint32_t bits; - - bits = 0xFFFFFF >> (24 - w); - - return ((GPIOx->DATA >> n) & bits); + uint32_t bits; + + bits = 0xFFFFFF >> (24 - w); + + GPIOx->DATA ^= (bits << n); } /****************************************************************************************************************************************** -* : GPIO_AtomicSetBit() -* ˵: ָŵƽøߣȷš--дԭԣжISRϣ -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOD -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN14PIN15 -* : -* ע: GPIOx16УЩѭвЩжISRвʱGPIOxű붼GPIO_Atomicͺ +* 函数名称: GPIO_GetBits() +* 功能说明: 读取参数指定的从n开始的w位连续引脚的电平状态 +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23 +* uint32_t w 指定要将引脚电平置高的引脚的个数 +* 输 出: 参数指定的从n开始的w位连续引脚的电平状态 0 低电平 1 高电平 +* 返回值的第0位表示引脚n的电平状态、返回值的第1位表示引脚n+1的电平状态... ...返回值的第w位表示引脚n+w的电平状态 +* 注意事项: 无 ******************************************************************************************************************************************/ -void GPIO_AtomicSetBit(GPIO_TypeDef * GPIOx, uint32_t n) -{ - *((volatile uint32_t *)(0x42000000 + ((uint32_t)&GPIOx->DATA - 0x40000000)*32 + n*4)) = 1; -} - -/****************************************************************************************************************************************** -* : GPIO_AtomicClrBit() -* ˵: ָŵƽõͣȷš--дԭԣжISRϣ -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOD -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN14PIN15 -* : -* ע: GPIOx16УЩѭвЩжISRвʱGPIOxű붼GPIO_Atomicͺ -******************************************************************************************************************************************/ -void GPIO_AtomicClrBit(GPIO_TypeDef * GPIOx, uint32_t n) +uint32_t GPIO_GetBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w) { - *((volatile uint32_t *)(0x42000000 + ((uint32_t)&GPIOx->DATA - 0x40000000)*32 + n*4)) = 0; + uint32_t bits; + + bits = 0xFFFFFF >> (24 - w); + + return ((GPIOx->DATA >> n) & bits); } /****************************************************************************************************************************************** -* : GPIO_AtomicInvBit() -* ˵: ָŵƽתȷš--дԭԣжISRϣ -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOD -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN14PIN15 -* : -* ע: GPIOx16УЩѭвЩжISRвʱGPIOxű붼GPIO_Atomicͺ +* 函数名称: GPIO_AtomicSetBit() +* 功能说明: 将参数指定的引脚电平置高,确保引脚”读-改-写“操作的原子性(不被中断ISR打断) +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOD +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN14、PIN15 +* 输 出: 无 +* 注意事项: 当GPIOx的16个引脚中,有些在主循环中操作,有些在中断ISR中操作时,GPIOx的引脚必须都用GPIO_Atomic类型函数操作 ******************************************************************************************************************************************/ -void GPIO_AtomicInvBit(GPIO_TypeDef * GPIOx, uint32_t n) +void GPIO_AtomicSetBit(GPIO_TypeDef *GPIOx, uint32_t n) { - *((volatile uint32_t *)(0x42000000 + ((uint32_t)&GPIOx->DATA - 0x40000000)*32 + n*4)) = 1 - *((volatile uint32_t *)(0x42000000 + ((uint32_t)&GPIOx->DATA - 0x40000000)*32 + n*4)); + *((volatile uint32_t *)(0x42000000 + ((uint32_t)&GPIOx->DATA - 0x40000000) * 32 + n * 4)) = 1; } /****************************************************************************************************************************************** -* : GPIO_AtomicSetBits() -* ˵: ָĴnʼwλŵĵƽøߣȷš--дԭԣжISRϣ -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOD -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN14PIN15 -* uint32_t w ָҪŵƽøߵŵĸ -* : -* ע: GPIOx16УЩѭвЩжISRвʱGPIOxű붼GPIO_Atomicͺ +* 函数名称: GPIO_AtomicClrBit() +* 功能说明: 将参数指定的引脚电平置低,确保引脚”读-改-写“操作的原子性(不被中断ISR打断) +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOD +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN14、PIN15 +* 输 出: 无 +* 注意事项: 当GPIOx的16个引脚中,有些在主循环中操作,有些在中断ISR中操作时,GPIOx的引脚必须都用GPIO_Atomic类型函数操作 ******************************************************************************************************************************************/ -void GPIO_AtomicSetBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w) +void GPIO_AtomicClrBit(GPIO_TypeDef *GPIOx, uint32_t n) { - uint32_t bits; - - bits = 0xFFFFFF >> (24 - w); - - __disable_irq(); - GPIOx->DATA |= (bits << n); - __enable_irq(); + *((volatile uint32_t *)(0x42000000 + ((uint32_t)&GPIOx->DATA - 0x40000000) * 32 + n * 4)) = 0; } /****************************************************************************************************************************************** -* : GPIO_AtomicClrBits() -* ˵: ָĴnʼwλŵĵƽõͣȷš--дԭԣжISRϣ -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOD -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN14PIN15 -* uint32_t w ָҪŵƽõ͵ŵĸ -* : -* ע: GPIOx16УЩѭвЩжISRвʱGPIOxű붼GPIO_Atomicͺ +* 函数名称: GPIO_AtomicInvBit() +* 功能说明: 将参数指定的引脚电平反转,确保引脚”读-改-写“操作的原子性(不被中断ISR打断) +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOD +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN14、PIN15 +* 输 出: 无 +* 注意事项: 当GPIOx的16个引脚中,有些在主循环中操作,有些在中断ISR中操作时,GPIOx的引脚必须都用GPIO_Atomic类型函数操作 ******************************************************************************************************************************************/ -void GPIO_AtomicClrBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w) +void GPIO_AtomicInvBit(GPIO_TypeDef *GPIOx, uint32_t n) { - uint32_t bits; - - bits = 0xFFFFFF >> (24 - w); - - __disable_irq(); - GPIOx->DATA &= ~(bits << n); - __enable_irq(); + *((volatile uint32_t *)(0x42000000 + ((uint32_t)&GPIOx->DATA - 0x40000000) * 32 + n * 4)) = 1 - *((volatile uint32_t *)(0x42000000 + ((uint32_t)&GPIOx->DATA - 0x40000000) * 32 + n * 4)); } /****************************************************************************************************************************************** -* : GPIO_AtomicInvBits() -* ˵: ָĴnʼwλŵĵƽתȷš--дԭԣжISRϣ -* : GPIO_TypeDef * GPIOx ָGPIO˿ڣЧֵGPIOAGPIOBGPIOCGPIOD -* uint32_t n ָGPIOţЧֵPIN0PIN1PIN2... ... PIN14PIN15 -* uint32_t w ָҪŵƽתŵĸ -* : -* ע: GPIOx16УЩѭвЩжISRвʱGPIOxű붼GPIO_Atomicͺ +* 函数名称: GPIO_AtomicSetBits() +* 功能说明: 将参数指定的从n开始的w位连续引脚的电平置高,确保引脚”读-改-写“操作的原子性(不被中断ISR打断) +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOD +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN14、PIN15 +* uint32_t w 指定要将引脚电平置高的引脚的个数 +* 输 出: 无 +* 注意事项: 当GPIOx的16个引脚中,有些在主循环中操作,有些在中断ISR中操作时,GPIOx的引脚必须都用GPIO_Atomic类型函数操作 ******************************************************************************************************************************************/ -void GPIO_AtomicInvBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w) +void GPIO_AtomicSetBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w) { - uint32_t bits; - - bits = 0xFFFFFF >> (24 - w); - - __disable_irq(); - GPIOx->DATA ^= (bits << n); - __enable_irq(); + uint32_t bits; + + bits = 0xFFFFFF >> (24 - w); + + __disable_irq(); + GPIOx->DATA |= (bits << n); + __enable_irq(); +} + +/****************************************************************************************************************************************** +* 函数名称: GPIO_AtomicClrBits() +* 功能说明: 将参数指定的从n开始的w位连续引脚的电平置低,确保引脚”读-改-写“操作的原子性(不被中断ISR打断) +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOD +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN14、PIN15 +* uint32_t w 指定要将引脚电平置低的引脚的个数 +* 输 出: 无 +* 注意事项: 当GPIOx的16个引脚中,有些在主循环中操作,有些在中断ISR中操作时,GPIOx的引脚必须都用GPIO_Atomic类型函数操作 +******************************************************************************************************************************************/ +void GPIO_AtomicClrBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w) +{ + uint32_t bits; + + bits = 0xFFFFFF >> (24 - w); + + __disable_irq(); + GPIOx->DATA &= ~(bits << n); + __enable_irq(); +} + +/****************************************************************************************************************************************** +* 函数名称: GPIO_AtomicInvBits() +* 功能说明: 将参数指定的从n开始的w位连续引脚的电平反转,确保引脚”读-改-写“操作的原子性(不被中断ISR打断) +* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOD +* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN14、PIN15 +* uint32_t w 指定要将引脚电平反转的引脚的个数 +* 输 出: 无 +* 注意事项: 当GPIOx的16个引脚中,有些在主循环中操作,有些在中断ISR中操作时,GPIOx的引脚必须都用GPIO_Atomic类型函数操作 +******************************************************************************************************************************************/ +void GPIO_AtomicInvBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w) +{ + uint32_t bits; + + bits = 0xFFFFFF >> (24 - w); + + __disable_irq(); + GPIOx->DATA ^= (bits << n); + __enable_irq(); } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.h index 3ced2d736e..056f17b07b 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_gpio.h @@ -1,24 +1,22 @@ #ifndef __SWM320_GPIO_H__ -#define __SWM320_GPIO_H__ +#define __SWM320_GPIO_H__ +void GPIO_Init(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t dir, uint32_t pull_up, uint32_t pull_down); //引脚初始化,包含引脚方向、上拉电阻、下拉电阻 -void GPIO_Init(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t dir, uint32_t pull_up, uint32_t pull_down); //引脚初始化,包含引脚方向、上拉电阻、下拉电阻 - -void GPIO_SetBit(GPIO_TypeDef * GPIOx, uint32_t n); //将参数指定的引脚电平置高 -void GPIO_ClrBit(GPIO_TypeDef * GPIOx, uint32_t n); //将参数指定的引脚电平置低 -void GPIO_InvBit(GPIO_TypeDef * GPIOx, uint32_t n); //将参数指定的引脚电平反转 -uint32_t GPIO_GetBit(GPIO_TypeDef * GPIOx, uint32_t n); //读取参数指定的引脚的电平状态 -void GPIO_SetBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //将参数指定的从n开始的w位连续引脚的电平置高 -void GPIO_ClrBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //将参数指定的从n开始的w位连续引脚的电平置低 -void GPIO_InvBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //将参数指定的从n开始的w位连续引脚的电平反转 -uint32_t GPIO_GetBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); //读取参数指定的从n开始的w位连续引脚的电平状态 - -void GPIO_AtomicSetBit(GPIO_TypeDef * GPIOx, uint32_t n); -void GPIO_AtomicClrBit(GPIO_TypeDef * GPIOx, uint32_t n); -void GPIO_AtomicInvBit(GPIO_TypeDef * GPIOx, uint32_t n); -void GPIO_AtomicSetBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); -void GPIO_AtomicClrBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); -void GPIO_AtomicInvBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w); +void GPIO_SetBit(GPIO_TypeDef *GPIOx, uint32_t n); //将参数指定的引脚电平置高 +void GPIO_ClrBit(GPIO_TypeDef *GPIOx, uint32_t n); //将参数指定的引脚电平置低 +void GPIO_InvBit(GPIO_TypeDef *GPIOx, uint32_t n); //将参数指定的引脚电平反转 +uint32_t GPIO_GetBit(GPIO_TypeDef *GPIOx, uint32_t n); //读取参数指定的引脚的电平状态 +void GPIO_SetBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w); //将参数指定的从n开始的w位连续引脚的电平置高 +void GPIO_ClrBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w); //将参数指定的从n开始的w位连续引脚的电平置低 +void GPIO_InvBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w); //将参数指定的从n开始的w位连续引脚的电平反转 +uint32_t GPIO_GetBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w); //读取参数指定的从n开始的w位连续引脚的电平状态 +void GPIO_AtomicSetBit(GPIO_TypeDef *GPIOx, uint32_t n); +void GPIO_AtomicClrBit(GPIO_TypeDef *GPIOx, uint32_t n); +void GPIO_AtomicInvBit(GPIO_TypeDef *GPIOx, uint32_t n); +void GPIO_AtomicSetBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w); +void GPIO_AtomicClrBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w); +void GPIO_AtomicInvBits(GPIO_TypeDef *GPIOx, uint32_t n, uint32_t w); #endif //__SWM320_GPIO_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.c index 04c414085f..8e093f14ee 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_i2c.c -* ˵: SWM320ƬI2Cнӿڹ -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_i2c.c +* 功能说明: SWM320单片机的I2C串行接口功能驱动库 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -22,194 +22,198 @@ #include "SWM320_i2c.h" /****************************************************************************************************************************************** -* : I2C_Init() -* ˵: I2Cʼ -* : I2C_TypeDef * I2Cx ָҪõI2CЧֵI2C0I2C1 -* I2C_InitStructure * initStruct I2C趨ֵĽṹ -* : -* ע: ģֻܹģʽ +* 函数名称: I2C_Init() +* 功能说明: I2C初始化 +* 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1 +* I2C_InitStructure * initStruct 包含I2C相关设定值的结构体 +* 输 出: 无 +* 注意事项: 模块只能工作于主机模式 ******************************************************************************************************************************************/ -void I2C_Init(I2C_TypeDef * I2Cx, I2C_InitStructure * initStruct) +void I2C_Init(I2C_TypeDef *I2Cx, I2C_InitStructure *initStruct) { - switch((uint32_t)I2Cx) - { - case ((uint32_t)I2C0): - SYS->CLKEN |= (0x01 << SYS_CLKEN_I2C0_Pos); - break; - - case ((uint32_t)I2C1): - SYS->CLKEN |= (0x01 << SYS_CLKEN_I2C1_Pos); - break; - } - - I2C_Close(I2Cx); //һЩؼĴֻI2Cرʱ - - if(initStruct->Master == 1) - { - I2Cx->CLKDIV = SystemCoreClock/5/initStruct->MstClk; - - I2Cx->MSTCMD = (I2Cx->MSTCMD & (~I2C_MSTCMD_IF_Msk)) | (1 << I2C_MSTCMD_IF_Pos); //ʹж֮ǰжϱ־ - I2Cx->CTRL &= ~I2C_CTRL_MSTIE_Msk; - I2Cx->CTRL |= (initStruct->MstIEn << I2C_CTRL_MSTIE_Pos); - - switch((uint32_t)I2Cx) - { - case ((uint32_t)I2C0): - if(initStruct->MstIEn) - { - NVIC_EnableIRQ(I2C0_IRQn); - } - else - { - NVIC_DisableIRQ(I2C0_IRQn); - } - break; - - case ((uint32_t)I2C1): - if(initStruct->MstIEn) - { - NVIC_EnableIRQ(I2C1_IRQn); - } - else - { - NVIC_DisableIRQ(I2C1_IRQn); - } - break; - } - } - else - { - I2Cx->SLVCR |= (1 << I2C_SLVCR_SLAVE_Pos); - - I2Cx->SLVCR &= ~(I2C_SLVCR_ADDR7b_Msk | I2C_SLVCR_ADDR_Msk); - I2Cx->SLVCR |= (1 << I2C_SLVCR_ACK_Pos) | - (initStruct->Addr7b << I2C_SLVCR_ADDR7b_Pos) | - (initStruct->SlvAddr << I2C_SLVCR_ADDR_Pos); - - I2Cx->SLVIF = I2C_SLVIF_RXEND_Msk | I2C_SLVIF_TXEND_Msk | I2C_SLVIF_STADET_Msk | I2C_SLVIF_STODET_Msk; //жϱ־ - I2Cx->SLVCR &= ~(I2C_SLVCR_IM_RXEND_Msk | I2C_SLVCR_IM_TXEND_Msk | I2C_SLVCR_IM_STADET_Msk | I2C_SLVCR_IM_STODET_Msk | - I2C_SLVCR_IM_RDREQ_Msk | I2C_SLVCR_IM_WRREQ_Msk); - I2Cx->SLVCR |= ((initStruct->SlvRxEndIEn ? 0 : 1) << I2C_SLVCR_IM_RXEND_Pos) | - ((initStruct->SlvTxEndIEn ? 0 : 1) << I2C_SLVCR_IM_TXEND_Pos) | - ((initStruct->SlvSTADetIEn ? 0 : 1) << I2C_SLVCR_IM_STADET_Pos) | - ((initStruct->SlvSTODetIEn ? 0 : 1) << I2C_SLVCR_IM_STODET_Pos) | - ((initStruct->SlvRdReqIEn ? 0 : 1) << I2C_SLVCR_IM_RDREQ_Pos) | - ((initStruct->SlvWrReqIEn ? 0 : 1) << I2C_SLVCR_IM_WRREQ_Pos); - - switch((uint32_t)I2Cx) - { - case ((uint32_t)I2C0): - if(initStruct->SlvRxEndIEn | initStruct->SlvTxEndIEn | initStruct->SlvSTADetIEn | - initStruct->SlvSTODetIEn | initStruct->SlvRdReqIEn | initStruct->SlvWrReqIEn) - { - NVIC_EnableIRQ(I2C0_IRQn); - } - else - { - NVIC_DisableIRQ(I2C0_IRQn); - } - break; - - case ((uint32_t)I2C1): - if(initStruct->SlvRxEndIEn | initStruct->SlvTxEndIEn | initStruct->SlvSTADetIEn | - initStruct->SlvSTODetIEn | initStruct->SlvRdReqIEn | initStruct->SlvWrReqIEn) - { - NVIC_EnableIRQ(I2C1_IRQn); - } - else - { - NVIC_DisableIRQ(I2C1_IRQn); - } - break; - } - } + switch ((uint32_t)I2Cx) + { + case ((uint32_t)I2C0): + SYS->CLKEN |= (0x01 << SYS_CLKEN_I2C0_Pos); + break; + + case ((uint32_t)I2C1): + SYS->CLKEN |= (0x01 << SYS_CLKEN_I2C1_Pos); + break; + } + + I2C_Close(I2Cx); //一些关键寄存器只能在I2C关闭时设置 + + if (initStruct->Master == 1) + { + I2Cx->CLKDIV = SystemCoreClock / 5 / initStruct->MstClk; + + I2Cx->MSTCMD = (I2Cx->MSTCMD & (~I2C_MSTCMD_IF_Msk)) | (1 << I2C_MSTCMD_IF_Pos); //使能中断之前先清除中断标志 + I2Cx->CTRL &= ~I2C_CTRL_MSTIE_Msk; + I2Cx->CTRL |= (initStruct->MstIEn << I2C_CTRL_MSTIE_Pos); + + switch ((uint32_t)I2Cx) + { + case ((uint32_t)I2C0): + if (initStruct->MstIEn) + { + NVIC_EnableIRQ(I2C0_IRQn); + } + else + { + NVIC_DisableIRQ(I2C0_IRQn); + } + break; + + case ((uint32_t)I2C1): + if (initStruct->MstIEn) + { + NVIC_EnableIRQ(I2C1_IRQn); + } + else + { + NVIC_DisableIRQ(I2C1_IRQn); + } + break; + } + } + else + { + I2Cx->SLVCR |= (1 << I2C_SLVCR_SLAVE_Pos); + + I2Cx->SLVCR &= ~(I2C_SLVCR_ADDR7b_Msk | I2C_SLVCR_ADDR_Msk); + I2Cx->SLVCR |= (1 << I2C_SLVCR_ACK_Pos) | + (initStruct->Addr7b << I2C_SLVCR_ADDR7b_Pos) | + (initStruct->SlvAddr << I2C_SLVCR_ADDR_Pos); + + I2Cx->SLVIF = I2C_SLVIF_RXEND_Msk | I2C_SLVIF_TXEND_Msk | I2C_SLVIF_STADET_Msk | I2C_SLVIF_STODET_Msk; //清中断标志 + I2Cx->SLVCR &= ~(I2C_SLVCR_IM_RXEND_Msk | I2C_SLVCR_IM_TXEND_Msk | I2C_SLVCR_IM_STADET_Msk | I2C_SLVCR_IM_STODET_Msk | + I2C_SLVCR_IM_RDREQ_Msk | I2C_SLVCR_IM_WRREQ_Msk); + I2Cx->SLVCR |= ((initStruct->SlvRxEndIEn ? 0 : 1) << I2C_SLVCR_IM_RXEND_Pos) | + ((initStruct->SlvTxEndIEn ? 0 : 1) << I2C_SLVCR_IM_TXEND_Pos) | + ((initStruct->SlvSTADetIEn ? 0 : 1) << I2C_SLVCR_IM_STADET_Pos) | + ((initStruct->SlvSTODetIEn ? 0 : 1) << I2C_SLVCR_IM_STODET_Pos) | + ((initStruct->SlvRdReqIEn ? 0 : 1) << I2C_SLVCR_IM_RDREQ_Pos) | + ((initStruct->SlvWrReqIEn ? 0 : 1) << I2C_SLVCR_IM_WRREQ_Pos); + + switch ((uint32_t)I2Cx) + { + case ((uint32_t)I2C0): + if (initStruct->SlvRxEndIEn | initStruct->SlvTxEndIEn | initStruct->SlvSTADetIEn | + initStruct->SlvSTODetIEn | initStruct->SlvRdReqIEn | initStruct->SlvWrReqIEn) + { + NVIC_EnableIRQ(I2C0_IRQn); + } + else + { + NVIC_DisableIRQ(I2C0_IRQn); + } + break; + + case ((uint32_t)I2C1): + if (initStruct->SlvRxEndIEn | initStruct->SlvTxEndIEn | initStruct->SlvSTADetIEn | + initStruct->SlvSTODetIEn | initStruct->SlvRdReqIEn | initStruct->SlvWrReqIEn) + { + NVIC_EnableIRQ(I2C1_IRQn); + } + else + { + NVIC_DisableIRQ(I2C1_IRQn); + } + break; + } + } } /****************************************************************************************************************************************** -* : I2C_Open() -* ˵: I2C򿪣շ -* : I2C_TypeDef * I2Cx ָҪõI2CЧֵI2C0I2C1 -* : -* ע: +* 函数名称: I2C_Open() +* 功能说明: I2C打开,允许收发 +* 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void I2C_Open(I2C_TypeDef * I2Cx) +void I2C_Open(I2C_TypeDef *I2Cx) { - I2Cx->CTRL |= (0x01 << I2C_CTRL_EN_Pos); + I2Cx->CTRL |= (0x01 << I2C_CTRL_EN_Pos); } /****************************************************************************************************************************************** -* : I2C_Close() -* ˵: I2Cرգֹշ -* : I2C_TypeDef * I2Cx ָҪõI2CЧֵI2C0I2C1 -* : -* ע: +* 函数名称: I2C_Close() +* 功能说明: I2C关闭,禁止收发 +* 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void I2C_Close(I2C_TypeDef * I2Cx) +void I2C_Close(I2C_TypeDef *I2Cx) { - I2Cx->CTRL &= ~I2C_CTRL_EN_Msk; + I2Cx->CTRL &= ~I2C_CTRL_EN_Msk; } /****************************************************************************************************************************************** -* : I2C_Start() -* ˵: ʼźŲ豸ַ -* : I2C_TypeDef * I2Cx ָҪõI2CЧֵI2C0I2C1 -* uint8_t addr 豸ַ -* : uint8_t 1 յACK 0 յNACK -* ע: +* 函数名称: I2C_Start() +* 功能说明: 产生起始信号并发送设备地址 +* 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1 +* uint8_t addr 设备地址 +* 输 出: uint8_t 1 接收到ACK 0 接收到NACK +* 注意事项: 无 ******************************************************************************************************************************************/ -uint8_t I2C_Start(I2C_TypeDef * I2Cx, uint8_t addr) +uint8_t I2C_Start(I2C_TypeDef *I2Cx, uint8_t addr) { - I2Cx->MSTDAT = addr; - I2Cx->MSTCMD = (1 << I2C_MSTCMD_STA_Pos) | - (1 << I2C_MSTCMD_WR_Pos); //ʼλʹӻַ - while(I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) __NOP(); //ȴ - - return (I2Cx->MSTCMD & I2C_MSTCMD_RXACK_Msk) ? 0 : 1; + I2Cx->MSTDAT = addr; + I2Cx->MSTCMD = (1 << I2C_MSTCMD_STA_Pos) | + (1 << I2C_MSTCMD_WR_Pos); //发送起始位和从机地址 + while (I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) + __NOP(); //等待发送完成 + + return (I2Cx->MSTCMD & I2C_MSTCMD_RXACK_Msk) ? 0 : 1; } /****************************************************************************************************************************************** -* : I2C_Stop() -* ˵: ֹͣź -* : I2C_TypeDef * I2Cx ָҪõI2CЧֵI2C0I2C1 -* : -* ע: +* 函数名称: I2C_Stop() +* 功能说明: 产生停止信号 +* 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void I2C_Stop(I2C_TypeDef * I2Cx) +void I2C_Stop(I2C_TypeDef *I2Cx) { - I2Cx->MSTCMD = (1 << I2C_MSTCMD_STO_Pos); - while(I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) __NOP(); //ȴ + I2Cx->MSTCMD = (1 << I2C_MSTCMD_STO_Pos); + while (I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) + __NOP(); //等待发送完成 } /****************************************************************************************************************************************** -* : I2C_Write() -* ˵: дһ -* : I2C_TypeDef * I2Cx ָҪõI2CЧֵI2C0I2C1 -* uint8_t data Ҫд -* : uint8_t 1 յACK 0 յNACK -* ע: +* 函数名称: I2C_Write() +* 功能说明: 写入一个数据 +* 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1 +* uint8_t data 要写的数据 +* 输 出: uint8_t 1 接收到ACK 0 接收到NACK +* 注意事项: 无 ******************************************************************************************************************************************/ -uint8_t I2C_Write(I2C_TypeDef * I2Cx, uint8_t data) -{ - I2Cx->MSTDAT = data; - I2Cx->MSTCMD = (1 << I2C_MSTCMD_WR_Pos); - while(I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) __NOP(); //ȴ - - return (I2Cx->MSTCMD & I2C_MSTCMD_RXACK_Msk) ? 0 : 1; +uint8_t I2C_Write(I2C_TypeDef *I2Cx, uint8_t data) +{ + I2Cx->MSTDAT = data; + I2Cx->MSTCMD = (1 << I2C_MSTCMD_WR_Pos); + while (I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) + __NOP(); //等待发送完成 + + return (I2Cx->MSTCMD & I2C_MSTCMD_RXACK_Msk) ? 0 : 1; } /****************************************************************************************************************************************** -* : I2C_Read() -* ˵: ȡһ -* : I2C_TypeDef * I2Cx ָҪõI2CЧֵI2C0I2C1 -* uint8_t ack 1 ACK 0 NACK -* : uint8_t ȡ -* ע: +* 函数名称: I2C_Read() +* 功能说明: 读取一个数据 +* 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1 +* uint8_t ack 1 发送ACK 0 发送NACK +* 输 出: uint8_t 读取到的数据 +* 注意事项: 无 ******************************************************************************************************************************************/ -uint8_t I2C_Read(I2C_TypeDef * I2Cx, uint8_t ack) +uint8_t I2C_Read(I2C_TypeDef *I2Cx, uint8_t ack) { - I2Cx->MSTCMD = (1 << I2C_MSTCMD_RD_Pos) | - ((ack ? 0 : 1) << I2C_MSTCMD_ACK_Pos); - while(I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) __NOP(); //ȴ - + I2Cx->MSTCMD = (1 << I2C_MSTCMD_RD_Pos) | + ((ack ? 0 : 1) << I2C_MSTCMD_ACK_Pos); + while (I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) + __NOP(); //等待接收完成 + return I2Cx->MSTDAT; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.h index 02f1292a28..8547328b35 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_i2c.h @@ -1,31 +1,31 @@ #ifndef __SWM320_I2C_H__ #define __SWM320_I2C_H__ -typedef struct { - uint8_t Master; //1 主机模式 - uint8_t Addr7b; //1 7位地址 0 10位地址 - - uint32_t MstClk; //主机传输时钟频率 - uint8_t MstIEn; //主机模式中断使能 - - uint16_t SlvAddr; //从机地址 - uint8_t SlvRxEndIEn; //从机接收完成中断使能 - uint8_t SlvTxEndIEn; //从机发送完成中断使能 - uint8_t SlvSTADetIEn; //从机检测到起始中断使能 - uint8_t SlvSTODetIEn; //从机检测到终止中断使能 - uint8_t SlvRdReqIEn; //从机接收到读请求中断使能 - uint8_t SlvWrReqIEn; //从机接收到写请求中断使能 +typedef struct +{ + uint8_t Master; //1 主机模式 + uint8_t Addr7b; //1 7位地址 0 10位地址 + + uint32_t MstClk; //主机传输时钟频率 + uint8_t MstIEn; //主机模式中断使能 + + uint16_t SlvAddr; //从机地址 + uint8_t SlvRxEndIEn; //从机接收完成中断使能 + uint8_t SlvTxEndIEn; //从机发送完成中断使能 + uint8_t SlvSTADetIEn; //从机检测到起始中断使能 + uint8_t SlvSTODetIEn; //从机检测到终止中断使能 + uint8_t SlvRdReqIEn; //从机接收到读请求中断使能 + uint8_t SlvWrReqIEn; //从机接收到写请求中断使能 } I2C_InitStructure; +void I2C_Init(I2C_TypeDef *I2Cx, I2C_InitStructure *initStruct); -void I2C_Init(I2C_TypeDef * I2Cx, I2C_InitStructure * initStruct); +void I2C_Open(I2C_TypeDef *I2Cx); +void I2C_Close(I2C_TypeDef *I2Cx); -void I2C_Open(I2C_TypeDef * I2Cx); -void I2C_Close(I2C_TypeDef * I2Cx); - -uint8_t I2C_Start(I2C_TypeDef * I2Cx, uint8_t addr); -void I2C_Stop(I2C_TypeDef * I2Cx); -uint8_t I2C_Write(I2C_TypeDef * I2Cx, uint8_t data); -uint8_t I2C_Read(I2C_TypeDef * I2Cx, uint8_t ack); +uint8_t I2C_Start(I2C_TypeDef *I2Cx, uint8_t addr); +void I2C_Stop(I2C_TypeDef *I2Cx); +uint8_t I2C_Write(I2C_TypeDef *I2Cx, uint8_t data); +uint8_t I2C_Read(I2C_TypeDef *I2Cx, uint8_t ack); #endif //__SWM320_I2C_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.c index c26ea71f9d..427df0d4b6 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.c @@ -31,45 +31,47 @@ * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void LCD_Init(LCD_TypeDef * LCDx, LCD_InitStructure * initStruct) -{ - switch((uint32_t)LCDx) - { - case ((uint32_t)LCD): - SYS->CLKEN |= (0x01 << SYS_CLKEN_LCD_Pos); - break; - } - - LCDx->CR0 = ((initStruct->HnPixel - 1) << LCD_CR0_HPIX_Pos) | - ((initStruct->VnPixel - 1) << LCD_CR0_VPIX_Pos) | - (initStruct->ClkAlways << LCD_CR0_DCLK_Pos) | - (initStruct->HsyncWidth << LCD_CR0_HLOW_Pos); - - LCDx->CR1 = ((initStruct->Hfp - 1) << LCD_CR1_HFP_Pos) | - ((initStruct->Hbp - 1) << LCD_CR1_HBP_Pos) | - ((initStruct->Vfp - 1) << LCD_CR1_VFP_Pos) | - ((initStruct->Vbp - 1) << LCD_CR1_VBP_Pos) | - (initStruct->ClkDiv << LCD_CR1_DCLKDIV_Pos) | - (initStruct->SamplEdge << LCD_CR1_DCLKINV_Pos); - - LCDx->IE = 1; - LCDx->IF = 1; //清除标志 - if(initStruct->IntEOTEn) LCD_INTEn(LCDx); - else LCD_INTDis(LCDx); - - switch((uint32_t)LCDx) - { - case ((uint32_t)LCD): - if(initStruct->IntEOTEn) - { - NVIC_EnableIRQ(LCD_IRQn); - } - else - { - NVIC_DisableIRQ(LCD_IRQn); - } - break; - } +void LCD_Init(LCD_TypeDef *LCDx, LCD_InitStructure *initStruct) +{ + switch ((uint32_t)LCDx) + { + case ((uint32_t)LCD): + SYS->CLKEN |= (0x01 << SYS_CLKEN_LCD_Pos); + break; + } + + LCDx->CR0 = ((initStruct->HnPixel - 1) << LCD_CR0_HPIX_Pos) | + ((initStruct->VnPixel - 1) << LCD_CR0_VPIX_Pos) | + (initStruct->ClkAlways << LCD_CR0_DCLK_Pos) | + (initStruct->HsyncWidth << LCD_CR0_HLOW_Pos); + + LCDx->CR1 = ((initStruct->Hfp - 1) << LCD_CR1_HFP_Pos) | + ((initStruct->Hbp - 1) << LCD_CR1_HBP_Pos) | + ((initStruct->Vfp - 1) << LCD_CR1_VFP_Pos) | + ((initStruct->Vbp - 1) << LCD_CR1_VBP_Pos) | + (initStruct->ClkDiv << LCD_CR1_DCLKDIV_Pos) | + (initStruct->SamplEdge << LCD_CR1_DCLKINV_Pos); + + LCDx->IE = 1; + LCDx->IF = 1; //清除标志 + if (initStruct->IntEOTEn) + LCD_INTEn(LCDx); + else + LCD_INTDis(LCDx); + + switch ((uint32_t)LCDx) + { + case ((uint32_t)LCD): + if (initStruct->IntEOTEn) + { + NVIC_EnableIRQ(LCD_IRQn); + } + else + { + NVIC_DisableIRQ(LCD_IRQn); + } + break; + } } /****************************************************************************************************************************************** @@ -79,9 +81,9 @@ void LCD_Init(LCD_TypeDef * LCDx, LCD_InitStructure * initStruct) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void LCD_Start(LCD_TypeDef * LCDx) +void LCD_Start(LCD_TypeDef *LCDx) { - LCDx->START |= (1 << LCD_START_GO_Pos) | (1 << LCD_START_BURST_Pos); + LCDx->START |= (1 << LCD_START_GO_Pos) | (1 << LCD_START_BURST_Pos); } /****************************************************************************************************************************************** @@ -91,9 +93,9 @@ void LCD_Start(LCD_TypeDef * LCDx) * 输 出: uint32_t 1 正在传输数据 0 数据传输已完成 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t LCD_IsBusy(LCD_TypeDef * LCDx) +uint32_t LCD_IsBusy(LCD_TypeDef *LCDx) { - return (LCDx->START & LCD_START_GO_Msk) ? 1 : 0; + return (LCDx->START & LCD_START_GO_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -103,9 +105,9 @@ uint32_t LCD_IsBusy(LCD_TypeDef * LCDx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void LCD_INTEn(LCD_TypeDef * LCDx) +void LCD_INTEn(LCD_TypeDef *LCDx) { - LCDx->IM = 0; + LCDx->IM = 0; } /****************************************************************************************************************************************** @@ -115,9 +117,9 @@ void LCD_INTEn(LCD_TypeDef * LCDx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void LCD_INTDis(LCD_TypeDef * LCDx) +void LCD_INTDis(LCD_TypeDef *LCDx) { - LCDx->IM = 1; + LCDx->IM = 1; } /****************************************************************************************************************************************** @@ -127,9 +129,9 @@ void LCD_INTDis(LCD_TypeDef * LCDx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void LCD_INTClr(LCD_TypeDef * LCDx) +void LCD_INTClr(LCD_TypeDef *LCDx) { - LCDx->IF = 1; + LCDx->IF = 1; } /****************************************************************************************************************************************** @@ -139,7 +141,7 @@ void LCD_INTClr(LCD_TypeDef * LCDx) * 输 出: uint32_t 1 完成指定长度的数据传输 0 未完成指定长度的数据传输 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t LCD_INTStat(LCD_TypeDef * LCDx) +uint32_t LCD_INTStat(LCD_TypeDef *LCDx) { - return (LCDx->IF & 0x01) ? 1 : 0; + return (LCDx->IF & 0x01) ? 1 : 0; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.h index 8091a88f03..d9c78f8d1f 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_lcd.h @@ -1,73 +1,70 @@ #ifndef __SWM320_LCD_H__ #define __SWM320_LCD_H__ +typedef struct +{ + uint16_t HnPixel; //水平方向像素个数,最大取值1024 + uint16_t VnPixel; //垂直方向像素个数,最大取值 768 + uint8_t Hfp; //horizonal front porch,最大取值32 + uint8_t Hbp; //horizonal back porch, 最大取值128 + uint8_t Vfp; //vertical front porch, 最大取值8 + uint8_t Vbp; //vertical back porch, 最大取值32 + uint8_t ClkDiv; //系统时钟经ClkDiv分频后产生DOCCLK,0 2分频 1 4分频 2 6分频 ... ... 31 64分频 + uint8_t SamplEdge; //屏幕在DOTCLK的哪个边沿采样数据:LCD_SAMPLEDGE_RISE、LCD_SAMPLEDGE_FALL + uint8_t ClkAlways; //1 一直输出DOTCLK 0 只在传输数据时输出DOTCLK + uint8_t HsyncWidth; //HSYNC低电平持续多少个DOTCLK,取值:LCD_HSYNC_1DOTCLK、LCD_HSYNC_2DOTCLK、LCD_HSYNC_3DOTCLK、LCD_HSYNC_4DOTCLK -typedef struct { - uint16_t HnPixel; //ˮƽظȡֵ1024 - uint16_t VnPixel; //ֱظȡֵ 768 - uint8_t Hfp; //horizonal front porchȡֵ32 - uint8_t Hbp; //horizonal back porch ȡֵ128 - uint8_t Vfp; //vertical front porch ȡֵ8 - uint8_t Vbp; //vertical back porch ȡֵ32 - uint8_t ClkDiv; //ϵͳʱӾClkDivƵDOCCLK0 2Ƶ 1 4Ƶ 2 6Ƶ ... ... 31 64Ƶ - uint8_t SamplEdge; //ĻDOTCLKĸزݣLCD_SAMPLEDGE_RISELCD_SAMPLEDGE_FALL - uint8_t ClkAlways; //1 һֱDOTCLK 0 ֻڴʱDOTCLK - uint8_t HsyncWidth; //HSYNC͵ƽٸDOTCLKȡֵLCD_HSYNC_1DOTCLKLCD_HSYNC_2DOTCLKLCD_HSYNC_3DOTCLKLCD_HSYNC_4DOTCLK - - uint8_t IntEOTEn; //End of Transterɣжʹ + uint8_t IntEOTEn; //End of Transter(传输完成)中断使能 } LCD_InitStructure; +#define LCD_SAMPLEDGE_RISE 0 //屏幕在DOTCLK的上升沿采样数据 +#define LCD_SAMPLEDGE_FALL 1 //屏幕在DOTCLK的下降沿采样数据 -#define LCD_SAMPLEDGE_RISE 0 //ĻDOTCLKز -#define LCD_SAMPLEDGE_FALL 1 //ĻDOTCLK½ز +#define LCD_HSYNC_1DOTCLK 0 //1个DOTCLK +#define LCD_HSYNC_2DOTCLK 1 +#define LCD_HSYNC_3DOTCLK 2 +#define LCD_HSYNC_4DOTCLK 3 -#define LCD_HSYNC_1DOTCLK 0 //1DOTCLK -#define LCD_HSYNC_2DOTCLK 1 -#define LCD_HSYNC_3DOTCLK 2 -#define LCD_HSYNC_4DOTCLK 3 +#define LCD_CLKDIV_2 0 +#define LCD_CLKDIV_4 1 +#define LCD_CLKDIV_6 2 +#define LCD_CLKDIV_8 3 +#define LCD_CLKDIV_10 4 +#define LCD_CLKDIV_12 5 +#define LCD_CLKDIV_14 6 +#define LCD_CLKDIV_16 7 +#define LCD_CLKDIV_18 8 +#define LCD_CLKDIV_20 9 +#define LCD_CLKDIV_22 10 +#define LCD_CLKDIV_24 11 +#define LCD_CLKDIV_26 12 +#define LCD_CLKDIV_28 13 +#define LCD_CLKDIV_30 14 +#define LCD_CLKDIV_32 15 +#define LCD_CLKDIV_34 16 +#define LCD_CLKDIV_36 17 +#define LCD_CLKDIV_38 18 +#define LCD_CLKDIV_40 19 +#define LCD_CLKDIV_42 20 +#define LCD_CLKDIV_44 21 +#define LCD_CLKDIV_46 22 +#define LCD_CLKDIV_48 23 +#define LCD_CLKDIV_50 24 +#define LCD_CLKDIV_52 25 +#define LCD_CLKDIV_54 26 +#define LCD_CLKDIV_56 27 +#define LCD_CLKDIV_58 28 +#define LCD_CLKDIV_60 29 +#define LCD_CLKDIV_62 30 +#define LCD_CLKDIV_64 31 -#define LCD_CLKDIV_2 0 -#define LCD_CLKDIV_4 1 -#define LCD_CLKDIV_6 2 -#define LCD_CLKDIV_8 3 -#define LCD_CLKDIV_10 4 -#define LCD_CLKDIV_12 5 -#define LCD_CLKDIV_14 6 -#define LCD_CLKDIV_16 7 -#define LCD_CLKDIV_18 8 -#define LCD_CLKDIV_20 9 -#define LCD_CLKDIV_22 10 -#define LCD_CLKDIV_24 11 -#define LCD_CLKDIV_26 12 -#define LCD_CLKDIV_28 13 -#define LCD_CLKDIV_30 14 -#define LCD_CLKDIV_32 15 -#define LCD_CLKDIV_34 16 -#define LCD_CLKDIV_36 17 -#define LCD_CLKDIV_38 18 -#define LCD_CLKDIV_40 19 -#define LCD_CLKDIV_42 20 -#define LCD_CLKDIV_44 21 -#define LCD_CLKDIV_46 22 -#define LCD_CLKDIV_48 23 -#define LCD_CLKDIV_50 24 -#define LCD_CLKDIV_52 25 -#define LCD_CLKDIV_54 26 -#define LCD_CLKDIV_56 27 -#define LCD_CLKDIV_58 28 -#define LCD_CLKDIV_60 29 -#define LCD_CLKDIV_62 30 -#define LCD_CLKDIV_64 31 - - -void LCD_Init(LCD_TypeDef * LCDx, LCD_InitStructure * initStruct); -void LCD_Start(LCD_TypeDef * LCDx); -uint32_t LCD_IsBusy(LCD_TypeDef * LCDx); - -void LCD_INTEn(LCD_TypeDef * LCDx); -void LCD_INTDis(LCD_TypeDef * LCDx); -void LCD_INTClr(LCD_TypeDef * LCDx); -uint32_t LCD_INTStat(LCD_TypeDef * LCDx); +void LCD_Init(LCD_TypeDef *LCDx, LCD_InitStructure *initStruct); +void LCD_Start(LCD_TypeDef *LCDx); +uint32_t LCD_IsBusy(LCD_TypeDef *LCDx); +void LCD_INTEn(LCD_TypeDef *LCDx); +void LCD_INTDis(LCD_TypeDef *LCDx); +void LCD_INTClr(LCD_TypeDef *LCDx); +uint32_t LCD_INTStat(LCD_TypeDef *LCDx); #endif //__SWM320_LCD_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.c index d811ea46e8..a8f6611ffe 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.c @@ -1,10 +1,10 @@ /****************************************************************************************************************************************** -* ļ: SWM320_norflash.c -* ˵: SWM320ƬNOR Flash -* ֧: http://www.synwit.com.cn/e/tool/gbook/?bid=1 -* ע: -* 汾: V1.1.0 20171025 -* ¼: +* 文件名称: SWM320_norflash.c +* 功能说明: SWM320单片机的NOR Flash驱动程序 +* 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 +* 注意事项: +* 版本日期: V1.1.0 2017年10月25日 +* 升级记录: * * ******************************************************************************************************************************************* @@ -21,152 +21,167 @@ #include "SWM320.h" #include "SWM320_norflash.h" - /****************************************************************************************************************************************** -* : NORFL_Init() -* ˵: NOR Flashʼ -* : NORFL_InitStructure * initStruct NOR Flash趨ֵĽṹ -* : -* ע: +* 函数名称: NORFL_Init() +* 功能说明: NOR Flash控制器初始化 +* 输 入: NORFL_InitStructure * initStruct 包含NOR Flash控制器相关设定值的结构体 +* 输 出: 无 +* 注意事项: 无 ******************************************************************************************************************************************/ -void NORFL_Init(NORFL_InitStructure * initStruct) +void NORFL_Init(NORFL_InitStructure *initStruct) { - uint32_t i; - - // SRAMǰҪˢSDRAM - do { - SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); - - while(SDRAMC->REFDONE == 0); - SDRAMC->REFRESH &= ~(1 << SDRAMC_REFRESH_EN_Pos); - - for(i = 0; i < 1000; i++) __NOP(); - SYS->CLKEN &= ~(1 << SYS_CLKEN_SDRAM_Pos); - } while(0); - - SYS->CLKEN |= (1 << SYS_CLKEN_NORFL_Pos); - - NORFLC->CR = ((initStruct->DataWidth == 8 ? 1 : 0) << NORFLC_CR_BYTEIF_Pos) | - (initStruct->WELowPulseTime << NORFLC_CR_WRTIME_Pos) | - (initStruct->OEPreValidTime << NORFLC_CR_RDTIME_Pos); - - NORFLC->IE = 3; - NORFLC->IF = 3; // жϱ־ - if(initStruct->OperFinishIEn) NORFLC->IM &= ~(1 << NORFLC_IM_FINISH_Pos); - else NORFLC->IM |= (1 << NORFLC_IM_FINISH_Pos); - if(initStruct->OperTimeoutIEn) NORFLC->IM &= ~(1 << NORFLC_IM_TIMEOUT_Pos); - else NORFLC->IM |= (1 << NORFLC_IM_TIMEOUT_Pos); + uint32_t i; + + // 配置SRAM前需要刷新下SDRAM控制器 + do + { + SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); + + while (SDRAMC->REFDONE == 0) + ; + SDRAMC->REFRESH &= ~(1 << SDRAMC_REFRESH_EN_Pos); + + for (i = 0; i < 1000; i++) + __NOP(); + SYS->CLKEN &= ~(1 << SYS_CLKEN_SDRAM_Pos); + } while (0); + + SYS->CLKEN |= (1 << SYS_CLKEN_NORFL_Pos); + + NORFLC->CR = ((initStruct->DataWidth == 8 ? 1 : 0) << NORFLC_CR_BYTEIF_Pos) | + (initStruct->WELowPulseTime << NORFLC_CR_WRTIME_Pos) | + (initStruct->OEPreValidTime << NORFLC_CR_RDTIME_Pos); + + NORFLC->IE = 3; + NORFLC->IF = 3; // 清除中断标志 + if (initStruct->OperFinishIEn) + NORFLC->IM &= ~(1 << NORFLC_IM_FINISH_Pos); + else + NORFLC->IM |= (1 << NORFLC_IM_FINISH_Pos); + if (initStruct->OperTimeoutIEn) + NORFLC->IM &= ~(1 << NORFLC_IM_TIMEOUT_Pos); + else + NORFLC->IM |= (1 << NORFLC_IM_TIMEOUT_Pos); } /****************************************************************************************************************************************** -* : NORFL_ChipErase() -* ˵: NOR FlashƬ -* : -* : uint32_t 0 ɹ 1 ʱ -* ע: +* 函数名称: NORFL_ChipErase() +* 功能说明: NOR Flash整片擦除 +* 输 入: 无 +* 输 出: uint32_t 0 擦除成功 1 擦除超时 +* 注意事项: 无 ******************************************************************************************************************************************/ uint32_t NORFL_ChipErase(void) { - uint32_t res; - - NORFLC->CMD = (NORFL_CMD_CHIP_ERASE << NORFLC_CMD_CMD_Pos); - - while(((NORFLC->IF & NORFLC_IF_FINISH_Msk) == 0) && - ((NORFLC->IF & NORFLC_IF_TIMEOUT_Msk) == 0)) __NOP(); - - if(NORFLC->IF & NORFLC_IF_FINISH_Msk) res = 0; - else res = 1; - - NORFLC->IF = NORFLC_IF_FINISH_Msk | NORFLC_IF_TIMEOUT_Msk; - - return res; + uint32_t res; + + NORFLC->CMD = (NORFL_CMD_CHIP_ERASE << NORFLC_CMD_CMD_Pos); + + while (((NORFLC->IF & NORFLC_IF_FINISH_Msk) == 0) && + ((NORFLC->IF & NORFLC_IF_TIMEOUT_Msk) == 0)) + __NOP(); + + if (NORFLC->IF & NORFLC_IF_FINISH_Msk) + res = 0; + else + res = 1; + + NORFLC->IF = NORFLC_IF_FINISH_Msk | NORFLC_IF_TIMEOUT_Msk; + + return res; } /****************************************************************************************************************************************** -* : NORFL_SectorErase() -* ˵: NOR Flash -* : uint32_t addr Ҫʼַ -* : uint32_t 0 ɹ 1 ʱ -* ע: MX29LV128DB ǰ8Ϊ8K255Ϊ64K MX29LV128DT ǰ255Ϊ64K8Ϊ8K +* 函数名称: NORFL_SectorErase() +* 功能说明: NOR Flash扇区擦除 +* 输 入: uint32_t addr 要擦除扇区的起始地址 +* 输 出: uint32_t 0 擦除成功 1 擦除超时 +* 注意事项: MX29LV128DB 前8扇区为8K、后255扇区为64K MX29LV128DT 前255扇区为64K、后8扇区为8K ******************************************************************************************************************************************/ uint32_t NORFL_SectorErase(uint32_t addr) { - uint32_t res; - - NORFLC->ADDR = addr; - NORFLC->CMD = (NORFL_CMD_SECTOR_ERASE << NORFLC_CMD_CMD_Pos); - - while(((NORFLC->IF & NORFLC_IF_FINISH_Msk) == 0) && - ((NORFLC->IF & NORFLC_IF_TIMEOUT_Msk) == 0)) __NOP(); - - if(NORFLC->IF & NORFLC_IF_FINISH_Msk) res = 0; - else res = 1; - - NORFLC->IF = NORFLC_IF_FINISH_Msk | NORFLC_IF_TIMEOUT_Msk; - - return res; + uint32_t res; + + NORFLC->ADDR = addr; + NORFLC->CMD = (NORFL_CMD_SECTOR_ERASE << NORFLC_CMD_CMD_Pos); + + while (((NORFLC->IF & NORFLC_IF_FINISH_Msk) == 0) && + ((NORFLC->IF & NORFLC_IF_TIMEOUT_Msk) == 0)) + __NOP(); + + if (NORFLC->IF & NORFLC_IF_FINISH_Msk) + res = 0; + else + res = 1; + + NORFLC->IF = NORFLC_IF_FINISH_Msk | NORFLC_IF_TIMEOUT_Msk; + + return res; } /****************************************************************************************************************************************** -* : NORFL_Write() -* ˵: NOR Flashд -* : uint32_t addr Ҫдĵַ -* uint32_t data Ҫд -* : uint32_t 0 дɹ 1 д볬ʱ -* ע: ӲӣΪ16λʱд룻Ϊ8λʱֽд +* 函数名称: NORFL_Write() +* 功能说明: NOR Flash写 +* 输 入: uint32_t addr 数据要写入的地址 +* uint32_t data 要写入的数据 +* 输 出: uint32_t 0 写入成功 1 写入超时 +* 注意事项: 硬件连接,数据线为16位时,半字写入;数据线为8位时,字节写入 ******************************************************************************************************************************************/ uint32_t NORFL_Write(uint32_t addr, uint32_t data) { - uint32_t res; - - NORFLC->ADDR = addr; - NORFLC->CMD = (NORFL_CMD_PROGRAM << NORFLC_CMD_CMD_Pos) | (data << NORFLC_CMD_DATA_Pos); - - while(((NORFLC->IF & NORFLC_IF_FINISH_Msk) == 0) && - ((NORFLC->IF & NORFLC_IF_TIMEOUT_Msk) == 0)) __NOP(); - - if(NORFLC->IF & NORFLC_IF_FINISH_Msk) res = 0; - else res = 1; - - NORFLC->IF = NORFLC_IF_FINISH_Msk | NORFLC_IF_TIMEOUT_Msk; - - return res; + uint32_t res; + + NORFLC->ADDR = addr; + NORFLC->CMD = (NORFL_CMD_PROGRAM << NORFLC_CMD_CMD_Pos) | (data << NORFLC_CMD_DATA_Pos); + + while (((NORFLC->IF & NORFLC_IF_FINISH_Msk) == 0) && + ((NORFLC->IF & NORFLC_IF_TIMEOUT_Msk) == 0)) + __NOP(); + + if (NORFLC->IF & NORFLC_IF_FINISH_Msk) + res = 0; + else + res = 1; + + NORFLC->IF = NORFLC_IF_FINISH_Msk | NORFLC_IF_TIMEOUT_Msk; + + return res; } /****************************************************************************************************************************************** -* : NORFL_Read() -* ˵: NOR Flash -* : uint32_t addr Ҫĵַ -* : uint32_t -* ע: ӲӣΪ16λʱֶΪ8λʱֽڶ +* 函数名称: NORFL_Read() +* 功能说明: NOR Flash读 +* 输 入: uint32_t addr 数据要读出的地址 +* 输 出: uint32_t 读出的数据 +* 注意事项: 硬件连接,数据线为16位时,半字读出;数据线为8位时,字节读出 ******************************************************************************************************************************************/ uint32_t NORFL_Read(uint32_t addr) { - NORFLC->ADDR = addr; - NORFLC->CMD = (NORFL_CMD_READ << NORFLC_CMD_CMD_Pos); - - return (NORFLC->CMD & NORFLC_CMD_DATA_Msk); + NORFLC->ADDR = addr; + NORFLC->CMD = (NORFL_CMD_READ << NORFLC_CMD_CMD_Pos); + + return (NORFLC->CMD & NORFLC_CMD_DATA_Msk); } /****************************************************************************************************************************************** -* : NORFL_ReadID() -* ˵: NOR FlashID -* : uint32_t id_addr IDַ˲оƬصģÿоƬͬ -* : uint16_t ȡID -* ע: +* 函数名称: NORFL_ReadID() +* 功能说明: NOR Flash读ID +* 输 入: uint32_t id_addr ID地址,此参数是芯片相关的,每种芯片都不同 +* 输 出: uint16_t 读取到的ID +* 注意事项: 无 ******************************************************************************************************************************************/ uint16_t NORFL_ReadID(uint32_t id_addr) { - uint16_t id; - - NORFLC->CMD = (NORFL_CMD_AUTO_SELECT << NORFLC_CMD_CMD_Pos); - - NORFLC->ADDR = id_addr; - NORFLC->CMD = (NORFL_CMD_READ << NORFLC_CMD_CMD_Pos); - - id = NORFLC->CMD & NORFLC_CMD_DATA_Msk; - - NORFLC->CMD = (NORFL_CMD_RESET << NORFLC_CMD_CMD_Pos); // ˳IDȡģʽ - - return id; + uint16_t id; + + NORFLC->CMD = (NORFL_CMD_AUTO_SELECT << NORFLC_CMD_CMD_Pos); + + NORFLC->ADDR = id_addr; + NORFLC->CMD = (NORFL_CMD_READ << NORFLC_CMD_CMD_Pos); + + id = NORFLC->CMD & NORFLC_CMD_DATA_Msk; + + NORFLC->CMD = (NORFL_CMD_RESET << NORFLC_CMD_CMD_Pos); // 退出ID读取模式 + + return id; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.h index 1714454dd7..228ff7032d 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_norflash.h @@ -1,38 +1,34 @@ #ifndef __SWM320_NORFLASH_H__ #define __SWM320_NORFLASH_H__ -typedef struct { - uint8_t DataWidth; // 8、16 - - uint8_t WELowPulseTime; // WE# pulse width,单位为系统时钟周期,最大值为7 - uint8_t OEPreValidTime; // Valid data output after OE# low,单位为系统时钟周期,最大值为15 - - uint8_t OperFinishIEn; // 操作(写入、擦除)完成中断使能 - uint8_t OperTimeoutIEn; +typedef struct +{ + uint8_t DataWidth; // 8、16 + + uint8_t WELowPulseTime; // WE# pulse width,单位为系统时钟周期,最大值为7 + uint8_t OEPreValidTime; // Valid data output after OE# low,单位为系统时钟周期,最大值为15 + + uint8_t OperFinishIEn; // 操作(写入、擦除)完成中断使能 + uint8_t OperTimeoutIEn; } NORFL_InitStructure; - - -void NORFL_Init(NORFL_InitStructure * initStruct); +void NORFL_Init(NORFL_InitStructure *initStruct); uint32_t NORFL_ChipErase(void); uint32_t NORFL_SectorErase(uint32_t addr); uint32_t NORFL_Write(uint32_t addr, uint32_t data); uint32_t NORFL_Read(uint32_t addr); uint16_t NORFL_ReadID(uint32_t id_addr); - /* 当前版本总线读只支持字读 #define NORFL_Read8(addr) *((volatile uint8_t *)(NORFLM_BASE + addr)) #define NORFL_Read16(addr) *((volatile uint16_t *)(NORFLM_BASE + addr)) */ -#define NORFL_Read32(addr) *((volatile uint32_t *)(NORFLM_BASE + addr)) +#define NORFL_Read32(addr) *((volatile uint32_t *)(NORFLM_BASE + addr)) - - -#define NORFL_CMD_READ 0 -#define NORFL_CMD_RESET 1 -#define NORFL_CMD_AUTO_SELECT 2 -#define NORFL_CMD_PROGRAM 3 -#define NORFL_CMD_CHIP_ERASE 4 -#define NORFL_CMD_SECTOR_ERASE 5 +#define NORFL_CMD_READ 0 +#define NORFL_CMD_RESET 1 +#define NORFL_CMD_AUTO_SELECT 2 +#define NORFL_CMD_PROGRAM 3 +#define NORFL_CMD_CHIP_ERASE 4 +#define NORFL_CMD_SECTOR_ERASE 5 #endif // __SWM320_NORFLASH_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.c index 55967f7cac..bb4c7f0731 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.c @@ -21,7 +21,6 @@ #include "SWM320.h" #include "SWM320_port.h" - /****************************************************************************************************************************************** * 函数名称: PORT_Init() * 功能说明: 端口引脚功能选择,可用的功能见"SWM320_port.h"文件 @@ -35,187 +34,187 @@ ******************************************************************************************************************************************/ void PORT_Init(uint32_t PORTx, uint32_t n, uint32_t func, uint32_t digit_in_en) { - switch((uint32_t)PORTx) - { - case ((uint32_t)PORTA): - if(func > 99) - { - if(n < PIN6) - { - PORT->PORTA_MUX0 &= ~(0x1F << (n*5)); - PORT->PORTA_MUX0 |= (func-100) << (n*5); - } - else if(n < PIN12) - { - PORT->PORTA_MUX1 &= ~(0x1F << ((n-6)*5)); - PORT->PORTA_MUX1 |= (func-100) << ((n-6)*5); - } - } - - PORT->PORTA_SEL &= ~(0x03 << (n*2)); - PORT->PORTA_SEL |= (func > 99 ? 1 : func) << (n*2); - - PORT->PORTA_INEN &= ~(0x01 << n); - PORT->PORTA_INEN |= (digit_in_en << n); - break; - - case ((uint32_t)PORTB): - if(func > 99) - { - if(n < PIN6) - { - PORT->PORTB_MUX0 &= ~(0x1F << (n*5)); - PORT->PORTB_MUX0 |= (func-100) << (n*5); - } - else if(n < PIN12) - { - PORT->PORTB_MUX1 &= ~(0x1F << ((n-6)*5)); - PORT->PORTB_MUX1 |= (func-100) << ((n-6)*5); - } - } - - PORT->PORTB_SEL &= ~(0x03 << (n*2)); - PORT->PORTB_SEL |= (func > 99 ? 1 : func) << (n*2); - - PORT->PORTB_INEN &= ~(0x01 << n); - PORT->PORTB_INEN |= (digit_in_en << n); - break; - - case ((uint32_t)PORTC): - if(func > 99) - { - if(n < PIN6) - { - PORT->PORTC_MUX0 &= ~(0x1F << (n*5)); - PORT->PORTC_MUX0 |= (func-100) << (n*5); - } - else if(n < PIN12) - { - PORT->PORTC_MUX1 &= ~(0x1F << ((n-6)*5)); - PORT->PORTC_MUX1 |= (func-100) << ((n-6)*5); - } - } - - PORT->PORTC_SEL &= ~(0x03 << (n*2)); - PORT->PORTC_SEL |= (func > 99 ? 1 : func) << (n*2); - - PORT->PORTC_INEN &= ~(0x01 << n); - PORT->PORTC_INEN |= (digit_in_en << n); - break; - - case ((uint32_t)PORTM): - if(func > 99) - { - if(n < PIN6) - { - PORT->PORTM_MUX0 &= ~(0x1F << (n*5)); - PORT->PORTM_MUX0 |= (func-100) << (n*5); - } - else if(n < PIN12) - { - PORT->PORTM_MUX1 &= ~(0x1F << ((n-6)*5)); - PORT->PORTM_MUX1 |= (func-100) << ((n-6)*5); - } - else if(n < PIN18) - { - PORT->PORTM_MUX2 &= ~(0x1F << ((n-12)*5)); - PORT->PORTM_MUX2 |= (func-100) << ((n-12)*5); - } - else if(n < PIN24) - { - PORT->PORTM_MUX3 &= ~(0x1F << ((n-18)*5)); - PORT->PORTM_MUX3 |= (func-100) << ((n-18)*5); - } - } - - if(n < 16) - { - PORT->PORTM_SEL0 &= ~(0x03 << (n*2)); - PORT->PORTM_SEL0 |= (func > 99 ? 1 : func) << (n*2); - } - else - { - PORT->PORTM_SEL1 &= ~(0x03 << ((n-16)*2)); - PORT->PORTM_SEL1 |= (func > 99 ? 1 : func) << ((n-16)*2); - } - - PORT->PORTM_INEN &= ~(0x01 << n); - PORT->PORTM_INEN |= (digit_in_en << n); - break; - - case ((uint32_t)PORTN): - if(func > 99) - { - if(n < PIN6) - { - PORT->PORTN_MUX0 &= ~(0x1F << (n*5)); - PORT->PORTN_MUX0 |= (func-100) << (n*5); - } - else if(n < PIN12) - { - PORT->PORTN_MUX1 &= ~(0x1F << ((n-6)*5)); - PORT->PORTN_MUX1 |= (func-100) << ((n-6)*5); - } - else if(n < PIN18) - { - PORT->PORTN_MUX2 &= ~(0x1F << ((n-12)*5)); - PORT->PORTN_MUX2 |= (func-100) << ((n-12)*5); - } - } - - if(n < 16) - { - PORT->PORTN_SEL0 &= ~(0x03 << (n*2)); - PORT->PORTN_SEL0 |= (func > 99 ? 1 : func) << (n*2); - } - else - { - PORT->PORTN_SEL1 &= ~(0x03 << ((n-16)*2)); - PORT->PORTN_SEL1 |= (func > 99 ? 1 : func) << ((n-16)*2); - } - - PORT->PORTN_INEN &= ~(0x01 << n); - PORT->PORTN_INEN |= (digit_in_en << n); - break; - - case ((uint32_t)PORTP): - if(func > 99) - { - if(n < PIN6) - { - PORT->PORTP_MUX0 &= ~(0x1F << (n*5)); - PORT->PORTP_MUX0 |= (func-100) << (n*5); - } - else if(n < PIN12) - { - PORT->PORTP_MUX1 &= ~(0x1F << ((n-6)*5)); - PORT->PORTP_MUX1 |= (func-100) << ((n-6)*5); - } - else if(n < PIN18) - { - PORT->PORTP_MUX2 &= ~(0x1F << ((n-12)*5)); - PORT->PORTP_MUX2 |= (func-100) << ((n-12)*5); - } - else if(n < PIN24) - { - PORT->PORTP_MUX3 &= ~(0x1F << ((n-18)*5)); - PORT->PORTP_MUX3 |= (func-100) << ((n-18)*5); - } - } - - if(n < 16) - { - PORT->PORTP_SEL0 &= ~(0x03 << (n*2)); - PORT->PORTP_SEL0 |= (func > 99 ? 1 : func) << (n*2); - } - else - { - PORT->PORTP_SEL1 &= ~(0x03 << ((n-16)*2)); - PORT->PORTP_SEL1 |= (func > 99 ? 1 : func) << ((n-16)*2); - } - - PORT->PORTP_INEN &= ~(0x01 << n); - PORT->PORTP_INEN |= (digit_in_en << n); - break; - } + switch ((uint32_t)PORTx) + { + case ((uint32_t)PORTA): + if (func > 99) + { + if (n < PIN6) + { + PORT->PORTA_MUX0 &= ~(0x1F << (n * 5)); + PORT->PORTA_MUX0 |= (func - 100) << (n * 5); + } + else if (n < PIN12) + { + PORT->PORTA_MUX1 &= ~(0x1F << ((n - 6) * 5)); + PORT->PORTA_MUX1 |= (func - 100) << ((n - 6) * 5); + } + } + + PORT->PORTA_SEL &= ~(0x03 << (n * 2)); + PORT->PORTA_SEL |= (func > 99 ? 1 : func) << (n * 2); + + PORT->PORTA_INEN &= ~(0x01 << n); + PORT->PORTA_INEN |= (digit_in_en << n); + break; + + case ((uint32_t)PORTB): + if (func > 99) + { + if (n < PIN6) + { + PORT->PORTB_MUX0 &= ~(0x1F << (n * 5)); + PORT->PORTB_MUX0 |= (func - 100) << (n * 5); + } + else if (n < PIN12) + { + PORT->PORTB_MUX1 &= ~(0x1F << ((n - 6) * 5)); + PORT->PORTB_MUX1 |= (func - 100) << ((n - 6) * 5); + } + } + + PORT->PORTB_SEL &= ~(0x03 << (n * 2)); + PORT->PORTB_SEL |= (func > 99 ? 1 : func) << (n * 2); + + PORT->PORTB_INEN &= ~(0x01 << n); + PORT->PORTB_INEN |= (digit_in_en << n); + break; + + case ((uint32_t)PORTC): + if (func > 99) + { + if (n < PIN6) + { + PORT->PORTC_MUX0 &= ~(0x1F << (n * 5)); + PORT->PORTC_MUX0 |= (func - 100) << (n * 5); + } + else if (n < PIN12) + { + PORT->PORTC_MUX1 &= ~(0x1F << ((n - 6) * 5)); + PORT->PORTC_MUX1 |= (func - 100) << ((n - 6) * 5); + } + } + + PORT->PORTC_SEL &= ~(0x03 << (n * 2)); + PORT->PORTC_SEL |= (func > 99 ? 1 : func) << (n * 2); + + PORT->PORTC_INEN &= ~(0x01 << n); + PORT->PORTC_INEN |= (digit_in_en << n); + break; + + case ((uint32_t)PORTM): + if (func > 99) + { + if (n < PIN6) + { + PORT->PORTM_MUX0 &= ~(0x1F << (n * 5)); + PORT->PORTM_MUX0 |= (func - 100) << (n * 5); + } + else if (n < PIN12) + { + PORT->PORTM_MUX1 &= ~(0x1F << ((n - 6) * 5)); + PORT->PORTM_MUX1 |= (func - 100) << ((n - 6) * 5); + } + else if (n < PIN18) + { + PORT->PORTM_MUX2 &= ~(0x1F << ((n - 12) * 5)); + PORT->PORTM_MUX2 |= (func - 100) << ((n - 12) * 5); + } + else if (n < PIN24) + { + PORT->PORTM_MUX3 &= ~(0x1F << ((n - 18) * 5)); + PORT->PORTM_MUX3 |= (func - 100) << ((n - 18) * 5); + } + } + + if (n < 16) + { + PORT->PORTM_SEL0 &= ~(0x03 << (n * 2)); + PORT->PORTM_SEL0 |= (func > 99 ? 1 : func) << (n * 2); + } + else + { + PORT->PORTM_SEL1 &= ~(0x03 << ((n - 16) * 2)); + PORT->PORTM_SEL1 |= (func > 99 ? 1 : func) << ((n - 16) * 2); + } + + PORT->PORTM_INEN &= ~(0x01 << n); + PORT->PORTM_INEN |= (digit_in_en << n); + break; + + case ((uint32_t)PORTN): + if (func > 99) + { + if (n < PIN6) + { + PORT->PORTN_MUX0 &= ~(0x1F << (n * 5)); + PORT->PORTN_MUX0 |= (func - 100) << (n * 5); + } + else if (n < PIN12) + { + PORT->PORTN_MUX1 &= ~(0x1F << ((n - 6) * 5)); + PORT->PORTN_MUX1 |= (func - 100) << ((n - 6) * 5); + } + else if (n < PIN18) + { + PORT->PORTN_MUX2 &= ~(0x1F << ((n - 12) * 5)); + PORT->PORTN_MUX2 |= (func - 100) << ((n - 12) * 5); + } + } + + if (n < 16) + { + PORT->PORTN_SEL0 &= ~(0x03 << (n * 2)); + PORT->PORTN_SEL0 |= (func > 99 ? 1 : func) << (n * 2); + } + else + { + PORT->PORTN_SEL1 &= ~(0x03 << ((n - 16) * 2)); + PORT->PORTN_SEL1 |= (func > 99 ? 1 : func) << ((n - 16) * 2); + } + + PORT->PORTN_INEN &= ~(0x01 << n); + PORT->PORTN_INEN |= (digit_in_en << n); + break; + + case ((uint32_t)PORTP): + if (func > 99) + { + if (n < PIN6) + { + PORT->PORTP_MUX0 &= ~(0x1F << (n * 5)); + PORT->PORTP_MUX0 |= (func - 100) << (n * 5); + } + else if (n < PIN12) + { + PORT->PORTP_MUX1 &= ~(0x1F << ((n - 6) * 5)); + PORT->PORTP_MUX1 |= (func - 100) << ((n - 6) * 5); + } + else if (n < PIN18) + { + PORT->PORTP_MUX2 &= ~(0x1F << ((n - 12) * 5)); + PORT->PORTP_MUX2 |= (func - 100) << ((n - 12) * 5); + } + else if (n < PIN24) + { + PORT->PORTP_MUX3 &= ~(0x1F << ((n - 18) * 5)); + PORT->PORTP_MUX3 |= (func - 100) << ((n - 18) * 5); + } + } + + if (n < 16) + { + PORT->PORTP_SEL0 &= ~(0x03 << (n * 2)); + PORT->PORTP_SEL0 |= (func > 99 ? 1 : func) << (n * 2); + } + else + { + PORT->PORTP_SEL1 &= ~(0x03 << ((n - 16) * 2)); + PORT->PORTP_SEL1 |= (func > 99 ? 1 : func) << ((n - 16) * 2); + } + + PORT->PORTP_INEN &= ~(0x01 << n); + PORT->PORTP_INEN |= (digit_in_en << n); + break; + } } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.h index 9fa2a24b12..0d1ec56db1 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_port.h @@ -1,482 +1,474 @@ #ifndef __SWM320_PORT_H__ #define __SWM320_PORT_H__ -void PORT_Init(uint32_t PORTx, uint32_t n, uint32_t func, uint32_t digit_in_en); //端口引脚功能选择,其可取值如下: +void PORT_Init(uint32_t PORTx, uint32_t n, uint32_t func, uint32_t digit_in_en); //端口引脚功能选择,其可取值如下: -#define PORTA 0 -#define PORTB 1 -#define PORTC 2 -#define PORTM 3 -#define PORTN 4 -#define PORTP 5 +#define PORTA 0 +#define PORTB 1 +#define PORTC 2 +#define PORTM 3 +#define PORTN 4 +#define PORTP 5 -#define PORTA_PIN0_GPIO 0 -#define PORTA_PIN0_FUNMUX 1 -#define PORTA_PIN0_SWCLK 2 +#define PORTA_PIN0_GPIO 0 +#define PORTA_PIN0_FUNMUX 1 +#define PORTA_PIN0_SWCLK 2 -#define PORTA_PIN1_GPIO 0 -#define PORTA_PIN1_FUNMUX 1 -#define PORTA_PIN1_SWDIO 2 +#define PORTA_PIN1_GPIO 0 +#define PORTA_PIN1_FUNMUX 1 +#define PORTA_PIN1_SWDIO 2 -#define PORTA_PIN2_GPIO 0 -#define PORTA_PIN2_FUNMUX 1 +#define PORTA_PIN2_GPIO 0 +#define PORTA_PIN2_FUNMUX 1 -#define PORTA_PIN3_GPIO 0 -#define PORTA_PIN3_FUNMUX 1 +#define PORTA_PIN3_GPIO 0 +#define PORTA_PIN3_FUNMUX 1 -#define PORTA_PIN4_GPIO 0 -#define PORTA_PIN4_FUNMUX 1 +#define PORTA_PIN4_GPIO 0 +#define PORTA_PIN4_FUNMUX 1 -#define PORTA_PIN5_GPIO 0 -#define PORTA_PIN5_FUNMUX 1 +#define PORTA_PIN5_GPIO 0 +#define PORTA_PIN5_FUNMUX 1 -#define PORTA_PIN6_GPIO 0 -#define PORTA_PIN6_FUNMUX 1 +#define PORTA_PIN6_GPIO 0 +#define PORTA_PIN6_FUNMUX 1 -#define PORTA_PIN7_GPIO 0 -#define PORTA_PIN7_FUNMUX 1 +#define PORTA_PIN7_GPIO 0 +#define PORTA_PIN7_FUNMUX 1 -#define PORTA_PIN8_GPIO 0 -#define PORTA_PIN8_FUNMUX 1 +#define PORTA_PIN8_GPIO 0 +#define PORTA_PIN8_FUNMUX 1 -#define PORTA_PIN9_GPIO 0 -#define PORTA_PIN9_FUNMUX 1 -#define PORTA_PIN9_ADC0_IN7 3 +#define PORTA_PIN9_GPIO 0 +#define PORTA_PIN9_FUNMUX 1 +#define PORTA_PIN9_ADC0_IN7 3 -#define PORTA_PIN10_GPIO 0 -#define PORTA_PIN10_FUNMUX 1 -#define PORTA_PIN10_ADC0_IN6 3 +#define PORTA_PIN10_GPIO 0 +#define PORTA_PIN10_FUNMUX 1 +#define PORTA_PIN10_ADC0_IN6 3 -#define PORTA_PIN11_GPIO 0 -#define PORTA_PIN11_FUNMUX 1 -#define PORTA_PIN11_ADC0_IN5 3 +#define PORTA_PIN11_GPIO 0 +#define PORTA_PIN11_FUNMUX 1 +#define PORTA_PIN11_ADC0_IN5 3 -#define PORTA_PIN12_GPIO 0 -#define PORTA_PIN12_ADC0_IN4 3 +#define PORTA_PIN12_GPIO 0 +#define PORTA_PIN12_ADC0_IN4 3 +#define PORTB_PIN0_GPIO 0 +#define PORTB_PIN0_FUNMUX 1 +#define PORTB_PIN0_SD_DETECT 2 -#define PORTB_PIN0_GPIO 0 -#define PORTB_PIN0_FUNMUX 1 -#define PORTB_PIN0_SD_DETECT 2 +#define PORTB_PIN1_GPIO 0 +#define PORTB_PIN1_FUNMUX 1 +#define PORTB_PIN1_SD_CLK 2 -#define PORTB_PIN1_GPIO 0 -#define PORTB_PIN1_FUNMUX 1 -#define PORTB_PIN1_SD_CLK 2 +#define PORTB_PIN2_GPIO 0 +#define PORTB_PIN2_FUNMUX 1 +#define PORTB_PIN2_SD_CMD 2 -#define PORTB_PIN2_GPIO 0 -#define PORTB_PIN2_FUNMUX 1 -#define PORTB_PIN2_SD_CMD 2 +#define PORTB_PIN3_GPIO 0 +#define PORTB_PIN3_FUNMUX 1 +#define PORTB_PIN3_SD_D0 2 -#define PORTB_PIN3_GPIO 0 -#define PORTB_PIN3_FUNMUX 1 -#define PORTB_PIN3_SD_D0 2 +#define PORTB_PIN4_GPIO 0 +#define PORTB_PIN4_FUNMUX 1 +#define PORTB_PIN4_SD_D1 2 -#define PORTB_PIN4_GPIO 0 -#define PORTB_PIN4_FUNMUX 1 -#define PORTB_PIN4_SD_D1 2 +#define PORTB_PIN5_GPIO 0 +#define PORTB_PIN5_FUNMUX 1 +#define PORTB_PIN5_SD_D2 2 -#define PORTB_PIN5_GPIO 0 -#define PORTB_PIN5_FUNMUX 1 -#define PORTB_PIN5_SD_D2 2 +#define PORTB_PIN6_GPIO 0 +#define PORTB_PIN6_FUNMUX 1 +#define PORTB_PIN6_SD_D3 2 -#define PORTB_PIN6_GPIO 0 -#define PORTB_PIN6_FUNMUX 1 -#define PORTB_PIN6_SD_D3 2 +#define PORTB_PIN7_GPIO 0 +#define PORTB_PIN7_FUNMUX 1 +#define PORTB_PIN7_SD_D4 2 -#define PORTB_PIN7_GPIO 0 -#define PORTB_PIN7_FUNMUX 1 -#define PORTB_PIN7_SD_D4 2 +#define PORTB_PIN8_GPIO 0 +#define PORTB_PIN8_FUNMUX 1 +#define PORTB_PIN8_SD_D5 2 -#define PORTB_PIN8_GPIO 0 -#define PORTB_PIN8_FUNMUX 1 -#define PORTB_PIN8_SD_D5 2 +#define PORTB_PIN9_GPIO 0 +#define PORTB_PIN9_FUNMUX 1 +#define PORTB_PIN9_SD_D6 2 -#define PORTB_PIN9_GPIO 0 -#define PORTB_PIN9_FUNMUX 1 -#define PORTB_PIN9_SD_D6 2 +#define PORTB_PIN10_GPIO 0 +#define PORTB_PIN10_FUNMUX 1 +#define PORTB_PIN10_SD_D7 2 -#define PORTB_PIN10_GPIO 0 -#define PORTB_PIN10_FUNMUX 1 -#define PORTB_PIN10_SD_D7 2 +#define PORTB_PIN11_GPIO 0 +#define PORTB_PIN11_FUNMUX 1 -#define PORTB_PIN11_GPIO 0 -#define PORTB_PIN11_FUNMUX 1 +#define PORTB_PIN12_GPIO 0 -#define PORTB_PIN12_GPIO 0 +#define PORTC_PIN0_GPIO 0 +#define PORTC_PIN0_FUNMUX 1 +#define PORTC_PIN1_GPIO 0 +#define PORTC_PIN1_FUNMUX 1 -#define PORTC_PIN0_GPIO 0 -#define PORTC_PIN0_FUNMUX 1 +#define PORTC_PIN2_GPIO 0 +#define PORTC_PIN2_FUNMUX 1 -#define PORTC_PIN1_GPIO 0 -#define PORTC_PIN1_FUNMUX 1 +#define PORTC_PIN3_GPIO 0 +#define PORTC_PIN3_FUNMUX 1 -#define PORTC_PIN2_GPIO 0 -#define PORTC_PIN2_FUNMUX 1 +#define PORTC_PIN4_GPIO 0 +#define PORTC_PIN4_FUNMUX 1 +#define PORTC_PIN4_ADC1_IN3 3 -#define PORTC_PIN3_GPIO 0 -#define PORTC_PIN3_FUNMUX 1 +#define PORTC_PIN5_GPIO 0 +#define PORTC_PIN5_FUNMUX 1 +#define PORTC_PIN5_ADC1_IN2 3 -#define PORTC_PIN4_GPIO 0 -#define PORTC_PIN4_FUNMUX 1 -#define PORTC_PIN4_ADC1_IN3 3 +#define PORTC_PIN6_GPIO 0 +#define PORTC_PIN6_FUNMUX 1 +#define PORTC_PIN6_ADC1_IN1 3 -#define PORTC_PIN5_GPIO 0 -#define PORTC_PIN5_FUNMUX 1 -#define PORTC_PIN5_ADC1_IN2 3 +#define PORTC_PIN7_GPIO 0 +#define PORTC_PIN7_FUNMUX 1 +#define PORTC_PIN7_ADC1_IN0 3 -#define PORTC_PIN6_GPIO 0 -#define PORTC_PIN6_FUNMUX 1 -#define PORTC_PIN6_ADC1_IN1 3 +#define PORTM_PIN0_GPIO 0 +#define PORTM_PIN0_FUNMUX 1 +#define PORTM_PIN0_NORFL_D15 2 -#define PORTC_PIN7_GPIO 0 -#define PORTC_PIN7_FUNMUX 1 -#define PORTC_PIN7_ADC1_IN0 3 +#define PORTM_PIN1_GPIO 0 +#define PORTM_PIN1_FUNMUX 1 +#define PORTM_PIN1_NORFL_D14 2 +#define PORTM_PIN2_GPIO 0 +#define PORTM_PIN2_FUNMUX 1 +#define PORTM_PIN2_NORFL_D13 2 -#define PORTM_PIN0_GPIO 0 -#define PORTM_PIN0_FUNMUX 1 -#define PORTM_PIN0_NORFL_D15 2 +#define PORTM_PIN3_GPIO 0 +#define PORTM_PIN3_FUNMUX 1 +#define PORTM_PIN3_NORFL_D12 2 -#define PORTM_PIN1_GPIO 0 -#define PORTM_PIN1_FUNMUX 1 -#define PORTM_PIN1_NORFL_D14 2 +#define PORTM_PIN4_GPIO 0 +#define PORTM_PIN4_FUNMUX 1 +#define PORTM_PIN4_NORFL_D11 2 -#define PORTM_PIN2_GPIO 0 -#define PORTM_PIN2_FUNMUX 1 -#define PORTM_PIN2_NORFL_D13 2 +#define PORTM_PIN5_GPIO 0 +#define PORTM_PIN5_FUNMUX 1 +#define PORTM_PIN5_NORFL_D10 2 -#define PORTM_PIN3_GPIO 0 -#define PORTM_PIN3_FUNMUX 1 -#define PORTM_PIN3_NORFL_D12 2 +#define PORTM_PIN6_GPIO 0 +#define PORTM_PIN6_FUNMUX 1 +#define PORTM_PIN6_NORFL_D9 2 -#define PORTM_PIN4_GPIO 0 -#define PORTM_PIN4_FUNMUX 1 -#define PORTM_PIN4_NORFL_D11 2 +#define PORTM_PIN7_GPIO 0 +#define PORTM_PIN7_FUNMUX 1 +#define PORTM_PIN7_NORFL_D8 2 -#define PORTM_PIN5_GPIO 0 -#define PORTM_PIN5_FUNMUX 1 -#define PORTM_PIN5_NORFL_D10 2 +#define PORTM_PIN8_GPIO 0 +#define PORTM_PIN8_FUNMUX 1 +#define PORTM_PIN8_NORFL_D7 2 -#define PORTM_PIN6_GPIO 0 -#define PORTM_PIN6_FUNMUX 1 -#define PORTM_PIN6_NORFL_D9 2 +#define PORTM_PIN9_GPIO 0 +#define PORTM_PIN9_FUNMUX 1 +#define PORTM_PIN9_NORFL_D6 2 -#define PORTM_PIN7_GPIO 0 -#define PORTM_PIN7_FUNMUX 1 -#define PORTM_PIN7_NORFL_D8 2 +#define PORTM_PIN10_GPIO 0 +#define PORTM_PIN10_FUNMUX 1 +#define PORTM_PIN10_NORFL_D5 2 -#define PORTM_PIN8_GPIO 0 -#define PORTM_PIN8_FUNMUX 1 -#define PORTM_PIN8_NORFL_D7 2 +#define PORTM_PIN11_GPIO 0 +#define PORTM_PIN11_FUNMUX 1 +#define PORTM_PIN11_NORFL_D4 2 -#define PORTM_PIN9_GPIO 0 -#define PORTM_PIN9_FUNMUX 1 -#define PORTM_PIN9_NORFL_D6 2 +#define PORTM_PIN12_GPIO 0 +#define PORTM_PIN12_FUNMUX 1 +#define PORTM_PIN12_NORFL_D3 2 -#define PORTM_PIN10_GPIO 0 -#define PORTM_PIN10_FUNMUX 1 -#define PORTM_PIN10_NORFL_D5 2 +#define PORTM_PIN13_GPIO 0 +#define PORTM_PIN13_FUNMUX 1 +#define PORTM_PIN13_NORFL_D2 2 -#define PORTM_PIN11_GPIO 0 -#define PORTM_PIN11_FUNMUX 1 -#define PORTM_PIN11_NORFL_D4 2 +#define PORTM_PIN14_GPIO 0 +#define PORTM_PIN14_FUNMUX 1 +#define PORTM_PIN14_NORFL_D1 2 -#define PORTM_PIN12_GPIO 0 -#define PORTM_PIN12_FUNMUX 1 -#define PORTM_PIN12_NORFL_D3 2 +#define PORTM_PIN15_GPIO 0 +#define PORTM_PIN15_FUNMUX 1 +#define PORTM_PIN15_NORFL_D0 2 -#define PORTM_PIN13_GPIO 0 -#define PORTM_PIN13_FUNMUX 1 -#define PORTM_PIN13_NORFL_D2 2 - -#define PORTM_PIN14_GPIO 0 -#define PORTM_PIN14_FUNMUX 1 -#define PORTM_PIN14_NORFL_D1 2 - -#define PORTM_PIN15_GPIO 0 -#define PORTM_PIN15_FUNMUX 1 -#define PORTM_PIN15_NORFL_D0 2 - -#define PORTM_PIN16_GPIO 0 -#define PORTM_PIN16_FUNMUX 1 -#define PORTM_PIN16_NORFL_OEN 2 - -#define PORTM_PIN17_GPIO 0 -#define PORTM_PIN17_FUNMUX 1 -#define PORTM_PIN17_NORFL_WEN 2 - -#define PORTM_PIN18_GPIO 0 -#define PORTM_PIN18_FUNMUX 1 -#define PORTM_PIN18_NORFL_CSN 2 - -#define PORTM_PIN19_GPIO 0 -#define PORTM_PIN19_FUNMUX 1 -#define PORTM_PIN19_SDRAM_CSN 2 - -#define PORTM_PIN20_GPIO 0 -#define PORTM_PIN20_FUNMUX 1 -#define PORTM_PIN20_SRAM_CSN 2 - -#define PORTM_PIN21_GPIO 0 -#define PORTM_PIN21_FUNMUX 1 -#define PORTM_PIN21_SDRAM_CKE 2 - - -#define PORTN_PIN0_GPIO 0 -#define PORTN_PIN0_FUNMUX 1 -#define PORTN_PIN0_LCD_D0 2 -#define PORTN_PIN0_ADC1_IN4 3 - -#define PORTN_PIN1_GPIO 0 -#define PORTN_PIN1_FUNMUX 1 -#define PORTN_PIN1_LCD_D1 2 -#define PORTN_PIN1_ADC1_IN5 3 - -#define PORTN_PIN2_GPIO 0 -#define PORTN_PIN2_FUNMUX 1 -#define PORTN_PIN2_LCD_D2 2 -#define PORTN_PIN2_ADC1_IN6 3 - -#define PORTN_PIN3_GPIO 0 -#define PORTN_PIN3_FUNMUX 1 -#define PORTN_PIN3_LCD_D3 2 - -#define PORTN_PIN4_GPIO 0 -#define PORTN_PIN4_FUNMUX 1 -#define PORTN_PIN4_LCD_D4 2 - -#define PORTN_PIN5_GPIO 0 -#define PORTN_PIN5_FUNMUX 1 -#define PORTN_PIN5_LCD_D5 2 - -#define PORTN_PIN6_GPIO 0 -#define PORTN_PIN6_FUNMUX 1 -#define PORTN_PIN6_LCD_D6 2 - -#define PORTN_PIN7_GPIO 0 -#define PORTN_PIN7_FUNMUX 1 -#define PORTN_PIN7_LCD_D7 2 - -#define PORTN_PIN8_GPIO 0 -#define PORTN_PIN8_FUNMUX 1 -#define PORTN_PIN8_LCD_D8 2 - -#define PORTN_PIN9_GPIO 0 -#define PORTN_PIN9_FUNMUX 1 -#define PORTN_PIN9_LCD_D9 2 - -#define PORTN_PIN10_GPIO 0 -#define PORTN_PIN10_FUNMUX 1 -#define PORTN_PIN10_LCD_D10 2 - -#define PORTN_PIN11_GPIO 0 -#define PORTN_PIN11_FUNMUX 1 -#define PORTN_PIN11_LCD_D11 2 - -#define PORTN_PIN12_GPIO 0 -#define PORTN_PIN12_FUNMUX 1 -#define PORTN_PIN12_LCD_D12 2 - -#define PORTN_PIN13_GPIO 0 -#define PORTN_PIN13_FUNMUX 1 -#define PORTN_PIN13_LCD_D13 2 - -#define PORTN_PIN14_GPIO 0 -#define PORTN_PIN14_FUNMUX 1 -#define PORTN_PIN14_LCD_D14 2 - -#define PORTN_PIN15_GPIO 0 -#define PORTN_PIN15_FUNMUX 1 -#define PORTN_PIN15_LCD_D15 2 - -#define PORTN_PIN16_GPIO 0 -#define PORTN_PIN16_FUNMUX 1 -#define PORTN_PIN16_LCD_RD 2 -#define PORTN_PIN16_LCD_DOTCK 2 - -#define PORTN_PIN17_GPIO 0 -#define PORTN_PIN17_FUNMUX 1 -#define PORTN_PIN17_LCD_CS 2 -#define PORTN_PIN17_LCD_VSYNC 2 - -#define PORTN_PIN18_GPIO 0 -#define PORTN_PIN18_LCD_RS 2 -#define PORTN_PIN18_LCD_DATEN 2 //Data Enable - -#define PORTN_PIN19_GPIO 0 -#define PORTN_PIN19_LCD_WR 2 -#define PORTN_PIN19_LCD_HSYNC 2 - - -#define PORTP_PIN0_GPIO 0 -#define PORTP_PIN0_FUNMUX 1 -#define PORTP_PIN0_NORFL_A0 2 - -#define PORTP_PIN1_GPIO 0 -#define PORTP_PIN1_FUNMUX 1 -#define PORTP_PIN1_NORFL_A1 2 - -#define PORTP_PIN2_GPIO 0 -#define PORTP_PIN2_FUNMUX 1 -#define PORTP_PIN2_NORFL_A2 2 -#define PORTP_PIN2_SD_D7 3 - -#define PORTP_PIN3_GPIO 0 -#define PORTP_PIN3_FUNMUX 1 -#define PORTP_PIN3_NORFL_A3 2 -#define PORTP_PIN3_SD_D6 3 - -#define PORTP_PIN4_GPIO 0 -#define PORTP_PIN4_FUNMUX 1 -#define PORTP_PIN4_NORFL_A4 2 -#define PORTP_PIN4_SD_D5 3 - -#define PORTP_PIN5_GPIO 0 -#define PORTP_PIN5_FUNMUX 1 -#define PORTP_PIN5_NORFL_A5 2 -#define PORTP_PIN5_SD_D4 3 - -#define PORTP_PIN6_GPIO 0 -#define PORTP_PIN6_FUNMUX 1 -#define PORTP_PIN6_NORFL_A6 2 -#define PORTP_PIN6_SD_D3 3 - -#define PORTP_PIN7_GPIO 0 -#define PORTP_PIN7_FUNMUX 1 -#define PORTP_PIN7_NORFL_A7 2 -#define PORTP_PIN7_SD_D2 3 - -#define PORTP_PIN8_GPIO 0 -#define PORTP_PIN8_FUNMUX 1 -#define PORTP_PIN8_NORFL_A8 2 -#define PORTP_PIN8_SD_D1 3 - -#define PORTP_PIN9_GPIO 0 -#define PORTP_PIN9_FUNMUX 1 -#define PORTP_PIN9_NORFL_A9 2 -#define PORTP_PIN9_SD_D0 3 - -#define PORTP_PIN10_GPIO 0 -#define PORTP_PIN10_FUNMUX 1 -#define PORTP_PIN10_NORFL_A10 2 -#define PORTP_PIN10_SD_CMD 3 - -#define PORTP_PIN11_GPIO 0 -#define PORTP_PIN11_FUNMUX 1 -#define PORTP_PIN11_NORFL_A11 2 -#define PORTP_PIN11_SD_CLK 3 - -#define PORTP_PIN12_GPIO 0 -#define PORTP_PIN12_FUNMUX 1 -#define PORTP_PIN12_NORFL_A12 2 -#define PORTP_PIN12_SD_DETECT 3 - -#define PORTP_PIN13_GPIO 0 -#define PORTP_PIN13_FUNMUX 1 -#define PORTP_PIN13_NORFL_A13 2 -#define PORTP_PIN13_SDRAM_CLK 2 - -#define PORTP_PIN14_GPIO 0 -#define PORTP_PIN14_FUNMUX 1 -#define PORTP_PIN14_NORFL_A14 2 -#define PORTP_PIN14_SDRAM_CAS 2 - -#define PORTP_PIN15_GPIO 0 -#define PORTP_PIN15_FUNMUX 1 -#define PORTP_PIN15_NORFL_A15 2 -#define PORTP_PIN15_SDRAM_RAS 2 - -#define PORTP_PIN16_GPIO 0 -#define PORTP_PIN16_FUNMUX 1 -#define PORTP_PIN16_NORFL_A16 2 -#define PORTP_PIN16_SDRAM_LDQ 2 - -#define PORTP_PIN17_GPIO 0 -#define PORTP_PIN17_FUNMUX 1 -#define PORTP_PIN17_NORFL_A17 2 -#define PORTP_PIN17_SDRAM_UDQ 2 - -#define PORTP_PIN18_GPIO 0 -#define PORTP_PIN18_FUNMUX 1 -#define PORTP_PIN18_NORFL_A18 2 - -#define PORTP_PIN19_GPIO 0 -#define PORTP_PIN19_FUNMUX 1 -#define PORTP_PIN19_NORFL_A19 2 - -#define PORTP_PIN20_GPIO 0 -#define PORTP_PIN20_FUNMUX 1 -#define PORTP_PIN20_NORFL_A20 2 -#define PORTP_PIN20_SDRAM_BA0 2 - -#define PORTP_PIN21_GPIO 0 -#define PORTP_PIN21_FUNMUX 1 -#define PORTP_PIN21_NORFL_A21 2 -#define PORTP_PIN21_SDRAM_BA1 2 - -#define PORTP_PIN22_GPIO 0 -#define PORTP_PIN22_FUNMUX 1 -#define PORTP_PIN22_NORFL_A22 2 - -#define PORTP_PIN23_GPIO 0 -#define PORTP_PIN23_FUNMUX 1 -#define PORTP_PIN23_NORFL_A23 2 +#define PORTM_PIN16_GPIO 0 +#define PORTM_PIN16_FUNMUX 1 +#define PORTM_PIN16_NORFL_OEN 2 +#define PORTM_PIN17_GPIO 0 +#define PORTM_PIN17_FUNMUX 1 +#define PORTM_PIN17_NORFL_WEN 2 +#define PORTM_PIN18_GPIO 0 +#define PORTM_PIN18_FUNMUX 1 +#define PORTM_PIN18_NORFL_CSN 2 + +#define PORTM_PIN19_GPIO 0 +#define PORTM_PIN19_FUNMUX 1 +#define PORTM_PIN19_SDRAM_CSN 2 + +#define PORTM_PIN20_GPIO 0 +#define PORTM_PIN20_FUNMUX 1 +#define PORTM_PIN20_SRAM_CSN 2 + +#define PORTM_PIN21_GPIO 0 +#define PORTM_PIN21_FUNMUX 1 +#define PORTM_PIN21_SDRAM_CKE 2 + +#define PORTN_PIN0_GPIO 0 +#define PORTN_PIN0_FUNMUX 1 +#define PORTN_PIN0_LCD_D0 2 +#define PORTN_PIN0_ADC1_IN4 3 + +#define PORTN_PIN1_GPIO 0 +#define PORTN_PIN1_FUNMUX 1 +#define PORTN_PIN1_LCD_D1 2 +#define PORTN_PIN1_ADC1_IN5 3 + +#define PORTN_PIN2_GPIO 0 +#define PORTN_PIN2_FUNMUX 1 +#define PORTN_PIN2_LCD_D2 2 +#define PORTN_PIN2_ADC1_IN6 3 + +#define PORTN_PIN3_GPIO 0 +#define PORTN_PIN3_FUNMUX 1 +#define PORTN_PIN3_LCD_D3 2 + +#define PORTN_PIN4_GPIO 0 +#define PORTN_PIN4_FUNMUX 1 +#define PORTN_PIN4_LCD_D4 2 + +#define PORTN_PIN5_GPIO 0 +#define PORTN_PIN5_FUNMUX 1 +#define PORTN_PIN5_LCD_D5 2 + +#define PORTN_PIN6_GPIO 0 +#define PORTN_PIN6_FUNMUX 1 +#define PORTN_PIN6_LCD_D6 2 + +#define PORTN_PIN7_GPIO 0 +#define PORTN_PIN7_FUNMUX 1 +#define PORTN_PIN7_LCD_D7 2 + +#define PORTN_PIN8_GPIO 0 +#define PORTN_PIN8_FUNMUX 1 +#define PORTN_PIN8_LCD_D8 2 + +#define PORTN_PIN9_GPIO 0 +#define PORTN_PIN9_FUNMUX 1 +#define PORTN_PIN9_LCD_D9 2 + +#define PORTN_PIN10_GPIO 0 +#define PORTN_PIN10_FUNMUX 1 +#define PORTN_PIN10_LCD_D10 2 + +#define PORTN_PIN11_GPIO 0 +#define PORTN_PIN11_FUNMUX 1 +#define PORTN_PIN11_LCD_D11 2 + +#define PORTN_PIN12_GPIO 0 +#define PORTN_PIN12_FUNMUX 1 +#define PORTN_PIN12_LCD_D12 2 + +#define PORTN_PIN13_GPIO 0 +#define PORTN_PIN13_FUNMUX 1 +#define PORTN_PIN13_LCD_D13 2 + +#define PORTN_PIN14_GPIO 0 +#define PORTN_PIN14_FUNMUX 1 +#define PORTN_PIN14_LCD_D14 2 + +#define PORTN_PIN15_GPIO 0 +#define PORTN_PIN15_FUNMUX 1 +#define PORTN_PIN15_LCD_D15 2 + +#define PORTN_PIN16_GPIO 0 +#define PORTN_PIN16_FUNMUX 1 +#define PORTN_PIN16_LCD_RD 2 +#define PORTN_PIN16_LCD_DOTCK 2 + +#define PORTN_PIN17_GPIO 0 +#define PORTN_PIN17_FUNMUX 1 +#define PORTN_PIN17_LCD_CS 2 +#define PORTN_PIN17_LCD_VSYNC 2 + +#define PORTN_PIN18_GPIO 0 +#define PORTN_PIN18_LCD_RS 2 +#define PORTN_PIN18_LCD_DATEN 2 //Data Enable + +#define PORTN_PIN19_GPIO 0 +#define PORTN_PIN19_LCD_WR 2 +#define PORTN_PIN19_LCD_HSYNC 2 + +#define PORTP_PIN0_GPIO 0 +#define PORTP_PIN0_FUNMUX 1 +#define PORTP_PIN0_NORFL_A0 2 + +#define PORTP_PIN1_GPIO 0 +#define PORTP_PIN1_FUNMUX 1 +#define PORTP_PIN1_NORFL_A1 2 + +#define PORTP_PIN2_GPIO 0 +#define PORTP_PIN2_FUNMUX 1 +#define PORTP_PIN2_NORFL_A2 2 +#define PORTP_PIN2_SD_D7 3 + +#define PORTP_PIN3_GPIO 0 +#define PORTP_PIN3_FUNMUX 1 +#define PORTP_PIN3_NORFL_A3 2 +#define PORTP_PIN3_SD_D6 3 + +#define PORTP_PIN4_GPIO 0 +#define PORTP_PIN4_FUNMUX 1 +#define PORTP_PIN4_NORFL_A4 2 +#define PORTP_PIN4_SD_D5 3 + +#define PORTP_PIN5_GPIO 0 +#define PORTP_PIN5_FUNMUX 1 +#define PORTP_PIN5_NORFL_A5 2 +#define PORTP_PIN5_SD_D4 3 + +#define PORTP_PIN6_GPIO 0 +#define PORTP_PIN6_FUNMUX 1 +#define PORTP_PIN6_NORFL_A6 2 +#define PORTP_PIN6_SD_D3 3 + +#define PORTP_PIN7_GPIO 0 +#define PORTP_PIN7_FUNMUX 1 +#define PORTP_PIN7_NORFL_A7 2 +#define PORTP_PIN7_SD_D2 3 + +#define PORTP_PIN8_GPIO 0 +#define PORTP_PIN8_FUNMUX 1 +#define PORTP_PIN8_NORFL_A8 2 +#define PORTP_PIN8_SD_D1 3 + +#define PORTP_PIN9_GPIO 0 +#define PORTP_PIN9_FUNMUX 1 +#define PORTP_PIN9_NORFL_A9 2 +#define PORTP_PIN9_SD_D0 3 + +#define PORTP_PIN10_GPIO 0 +#define PORTP_PIN10_FUNMUX 1 +#define PORTP_PIN10_NORFL_A10 2 +#define PORTP_PIN10_SD_CMD 3 + +#define PORTP_PIN11_GPIO 0 +#define PORTP_PIN11_FUNMUX 1 +#define PORTP_PIN11_NORFL_A11 2 +#define PORTP_PIN11_SD_CLK 3 + +#define PORTP_PIN12_GPIO 0 +#define PORTP_PIN12_FUNMUX 1 +#define PORTP_PIN12_NORFL_A12 2 +#define PORTP_PIN12_SD_DETECT 3 + +#define PORTP_PIN13_GPIO 0 +#define PORTP_PIN13_FUNMUX 1 +#define PORTP_PIN13_NORFL_A13 2 +#define PORTP_PIN13_SDRAM_CLK 2 + +#define PORTP_PIN14_GPIO 0 +#define PORTP_PIN14_FUNMUX 1 +#define PORTP_PIN14_NORFL_A14 2 +#define PORTP_PIN14_SDRAM_CAS 2 + +#define PORTP_PIN15_GPIO 0 +#define PORTP_PIN15_FUNMUX 1 +#define PORTP_PIN15_NORFL_A15 2 +#define PORTP_PIN15_SDRAM_RAS 2 + +#define PORTP_PIN16_GPIO 0 +#define PORTP_PIN16_FUNMUX 1 +#define PORTP_PIN16_NORFL_A16 2 +#define PORTP_PIN16_SDRAM_LDQ 2 + +#define PORTP_PIN17_GPIO 0 +#define PORTP_PIN17_FUNMUX 1 +#define PORTP_PIN17_NORFL_A17 2 +#define PORTP_PIN17_SDRAM_UDQ 2 + +#define PORTP_PIN18_GPIO 0 +#define PORTP_PIN18_FUNMUX 1 +#define PORTP_PIN18_NORFL_A18 2 + +#define PORTP_PIN19_GPIO 0 +#define PORTP_PIN19_FUNMUX 1 +#define PORTP_PIN19_NORFL_A19 2 + +#define PORTP_PIN20_GPIO 0 +#define PORTP_PIN20_FUNMUX 1 +#define PORTP_PIN20_NORFL_A20 2 +#define PORTP_PIN20_SDRAM_BA0 2 + +#define PORTP_PIN21_GPIO 0 +#define PORTP_PIN21_FUNMUX 1 +#define PORTP_PIN21_NORFL_A21 2 +#define PORTP_PIN21_SDRAM_BA1 2 + +#define PORTP_PIN22_GPIO 0 +#define PORTP_PIN22_FUNMUX 1 +#define PORTP_PIN22_NORFL_A22 2 + +#define PORTP_PIN23_GPIO 0 +#define PORTP_PIN23_FUNMUX 1 +#define PORTP_PIN23_NORFL_A23 2 /* 下面宏定义的取值全部在正确值的基础上“加100”,以区分上面宏定义的值,从而方便库函数的编写*/ /* 下面这些值是偶数编号引脚的功能取值,如PIN0、PIN2、... */ -#define FUNMUX0_UART0_RXD 100 -#define FUNMUX0_UART1_RXD 101 -#define FUNMUX0_UART2_RXD 102 -#define FUNMUX0_UART3_RXD 103 -#define FUNMUX0_I2C0_SCL 105 -#define FUNMUX0_I2C1_SCL 106 -#define FUNMUX0_PWM0A_OUT 107 -#define FUNMUX0_PWM2A_OUT 108 -#define FUNMUX0_PWM4A_OUT 109 -#define FUNMUX0_PWM0B_OUT 110 -#define FUNMUX0_PWM2B_OUT 111 -#define FUNMUX0_PWM4B_OUT 112 -#define FUNMUX0_PWM_BREAK 113 -#define FUNMUX0_TIMR0_IN 114 -#define FUNMUX0_TIMR2_IN 115 -#define FUNMUX0_CAN_RX 116 -#define FUNMUX0_SPI0_SSEL 117 -#define FUNMUX0_SPI0_MOSI 118 -#define FUNMUX0_SPI1_SSEL 119 -#define FUNMUX0_SPI1_MOSI 120 -#define FUNMUX0_UART0_CTS 121 -#define FUNMUX0_UART1_CTS 122 -#define FUNMUX0_UART2_CTS 123 -#define FUNMUX0_UART3_CTS 124 +#define FUNMUX0_UART0_RXD 100 +#define FUNMUX0_UART1_RXD 101 +#define FUNMUX0_UART2_RXD 102 +#define FUNMUX0_UART3_RXD 103 +#define FUNMUX0_I2C0_SCL 105 +#define FUNMUX0_I2C1_SCL 106 +#define FUNMUX0_PWM0A_OUT 107 +#define FUNMUX0_PWM2A_OUT 108 +#define FUNMUX0_PWM4A_OUT 109 +#define FUNMUX0_PWM0B_OUT 110 +#define FUNMUX0_PWM2B_OUT 111 +#define FUNMUX0_PWM4B_OUT 112 +#define FUNMUX0_PWM_BREAK 113 +#define FUNMUX0_TIMR0_IN 114 +#define FUNMUX0_TIMR2_IN 115 +#define FUNMUX0_CAN_RX 116 +#define FUNMUX0_SPI0_SSEL 117 +#define FUNMUX0_SPI0_MOSI 118 +#define FUNMUX0_SPI1_SSEL 119 +#define FUNMUX0_SPI1_MOSI 120 +#define FUNMUX0_UART0_CTS 121 +#define FUNMUX0_UART1_CTS 122 +#define FUNMUX0_UART2_CTS 123 +#define FUNMUX0_UART3_CTS 124 /* 下面这些值是奇数编号引脚的功能取值,如PIN1、PIN3、... */ -#define FUNMUX1_UART0_TXD 100 -#define FUNMUX1_UART1_TXD 101 -#define FUNMUX1_UART2_TXD 102 -#define FUNMUX1_UART3_TXD 103 -#define FUNMUX1_I2C0_SDA 105 -#define FUNMUX1_I2C1_SDA 106 -#define FUNMUX1_PWM1A_OUT 107 -#define FUNMUX1_PWM3A_OUT 108 -#define FUNMUX1_PWM5A_OUT 109 -#define FUNMUX1_PWM1B_OUT 110 -#define FUNMUX1_PWM3B_OUT 111 -#define FUNMUX1_PWM5B_OUT 112 -#define FUNMUX1_PULSE_IN 113 -#define FUNMUX1_TIMR1_IN 114 -#define FUNMUX1_TIMR3_IN 115 -#define FUNMUX1_CAN_TX 116 -#define FUNMUX1_SPI0_SCLK 117 -#define FUNMUX1_SPI0_MISO 118 -#define FUNMUX1_SPI1_SCLK 119 -#define FUNMUX1_SPI1_MISO 120 -#define FUNMUX1_UART0_RTS 121 -#define FUNMUX1_UART1_RTS 122 -#define FUNMUX1_UART2_RTS 123 -#define FUNMUX1_UART3_RTS 124 - +#define FUNMUX1_UART0_TXD 100 +#define FUNMUX1_UART1_TXD 101 +#define FUNMUX1_UART2_TXD 102 +#define FUNMUX1_UART3_TXD 103 +#define FUNMUX1_I2C0_SDA 105 +#define FUNMUX1_I2C1_SDA 106 +#define FUNMUX1_PWM1A_OUT 107 +#define FUNMUX1_PWM3A_OUT 108 +#define FUNMUX1_PWM5A_OUT 109 +#define FUNMUX1_PWM1B_OUT 110 +#define FUNMUX1_PWM3B_OUT 111 +#define FUNMUX1_PWM5B_OUT 112 +#define FUNMUX1_PULSE_IN 113 +#define FUNMUX1_TIMR1_IN 114 +#define FUNMUX1_TIMR3_IN 115 +#define FUNMUX1_CAN_TX 116 +#define FUNMUX1_SPI0_SCLK 117 +#define FUNMUX1_SPI0_MISO 118 +#define FUNMUX1_SPI1_SCLK 119 +#define FUNMUX1_SPI1_MISO 120 +#define FUNMUX1_UART0_RTS 121 +#define FUNMUX1_UART1_RTS 122 +#define FUNMUX1_UART2_RTS 123 +#define FUNMUX1_UART3_RTS 124 #endif //__SWM320_PORT_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.c index 2c8e87cd9b..45152822e8 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.c @@ -21,7 +21,6 @@ #include "SWM320.h" #include "SWM320_pwm.h" - /****************************************************************************************************************************************** * 函数名称: PWM_Init() * 功能说明: PWM初始化 @@ -30,73 +29,73 @@ * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_Init(PWM_TypeDef * PWMx, PWM_InitStructure * initStruct) +void PWM_Init(PWM_TypeDef *PWMx, PWM_InitStructure *initStruct) { - uint32_t bit_offset = 0; - - SYS->CLKEN |= (0x01 << SYS_CLKEN_PWM_Pos); - - SYS->CLKDIV &= ~SYS_CLKDIV_PWM_Msk; - SYS->CLKDIV |= (initStruct->clk_div << SYS_CLKDIV_PWM_Pos); - - PWM_Stop(PWMx, 1, 1); //一些关键寄存器只能在PWM停止时设置 - - PWMx->MODE = initStruct->mode; - - PWMx->PERA = initStruct->cycleA; - PWMx->HIGHA = initStruct->hdutyA; - PWMx->DZA = initStruct->deadzoneA; - - PWMx->PERB = initStruct->cycleB; - PWMx->HIGHB = initStruct->hdutyB; - PWMx->DZB = initStruct->deadzoneB; - - PWMx->INIOUT &= ~(PWM_INIOUT_PWMA_Msk | PWM_INIOUT_PWMB_Msk); - PWMx->INIOUT |= (initStruct->initLevelA << PWM_INIOUT_PWMA_Pos) | - (initStruct->initLevelB << PWM_INIOUT_PWMB_Pos); - - PWMG->IM = 0x00000000; - - switch((uint32_t)PWMx) - { - case((uint32_t)PWM0): - bit_offset = 0; - break; + uint32_t bit_offset = 0; - case((uint32_t)PWM1): - bit_offset = 2; - break; + SYS->CLKEN |= (0x01 << SYS_CLKEN_PWM_Pos); - case((uint32_t)PWM2): - bit_offset = 4; - break; - - case((uint32_t)PWM3): - bit_offset = 6; - break; - - case((uint32_t)PWM4): - bit_offset = 8; - break; - - case((uint32_t)PWM5): - bit_offset = 10; - break; - } - - PWMG->IRS = ((0x01 << bit_offset) | (0x01 << (bit_offset+1)) | (0x01 << (bit_offset+12)) | (0x01 << (bit_offset+13))); //清除中断标志 - PWMG->IE &= ~((0x01 << bit_offset) | (0x01 << (bit_offset+1)) | (0x01 << (bit_offset+12)) | (0x01 << (bit_offset+13))); - PWMG->IE |= (initStruct->NCycleAIEn << bit_offset) | (initStruct->NCycleBIEn << (bit_offset+1)) | - (initStruct->HEndAIEn << (bit_offset+12)) | (initStruct->HEndBIEn << (bit_offset+13)); - - if(initStruct->NCycleAIEn | initStruct->NCycleBIEn | initStruct->HEndAIEn | initStruct->HEndBIEn) - { - NVIC_EnableIRQ(PWM_IRQn); - } - else if((PWMG->IE & (~((0x01 << bit_offset) | (0x01 << (bit_offset+1)) | (0x01 << (bit_offset+12)) | (0x01 << (bit_offset+13))))) == 0) - { - NVIC_DisableIRQ(PWM_IRQn); - } + SYS->CLKDIV &= ~SYS_CLKDIV_PWM_Msk; + SYS->CLKDIV |= (initStruct->clk_div << SYS_CLKDIV_PWM_Pos); + + PWM_Stop(PWMx, 1, 1); //一些关键寄存器只能在PWM停止时设置 + + PWMx->MODE = initStruct->mode; + + PWMx->PERA = initStruct->cycleA; + PWMx->HIGHA = initStruct->hdutyA; + PWMx->DZA = initStruct->deadzoneA; + + PWMx->PERB = initStruct->cycleB; + PWMx->HIGHB = initStruct->hdutyB; + PWMx->DZB = initStruct->deadzoneB; + + PWMx->INIOUT &= ~(PWM_INIOUT_PWMA_Msk | PWM_INIOUT_PWMB_Msk); + PWMx->INIOUT |= (initStruct->initLevelA << PWM_INIOUT_PWMA_Pos) | + (initStruct->initLevelB << PWM_INIOUT_PWMB_Pos); + + PWMG->IM = 0x00000000; + + switch ((uint32_t)PWMx) + { + case ((uint32_t)PWM0): + bit_offset = 0; + break; + + case ((uint32_t)PWM1): + bit_offset = 2; + break; + + case ((uint32_t)PWM2): + bit_offset = 4; + break; + + case ((uint32_t)PWM3): + bit_offset = 6; + break; + + case ((uint32_t)PWM4): + bit_offset = 8; + break; + + case ((uint32_t)PWM5): + bit_offset = 10; + break; + } + + PWMG->IRS = ((0x01 << bit_offset) | (0x01 << (bit_offset + 1)) | (0x01 << (bit_offset + 12)) | (0x01 << (bit_offset + 13))); //清除中断标志 + PWMG->IE &= ~((0x01 << bit_offset) | (0x01 << (bit_offset + 1)) | (0x01 << (bit_offset + 12)) | (0x01 << (bit_offset + 13))); + PWMG->IE |= (initStruct->NCycleAIEn << bit_offset) | (initStruct->NCycleBIEn << (bit_offset + 1)) | + (initStruct->HEndAIEn << (bit_offset + 12)) | (initStruct->HEndBIEn << (bit_offset + 13)); + + if (initStruct->NCycleAIEn | initStruct->NCycleBIEn | initStruct->HEndAIEn | initStruct->HEndBIEn) + { + NVIC_EnableIRQ(PWM_IRQn); + } + else if ((PWMG->IE & (~((0x01 << bit_offset) | (0x01 << (bit_offset + 1)) | (0x01 << (bit_offset + 12)) | (0x01 << (bit_offset + 13))))) == 0) + { + NVIC_DisableIRQ(PWM_IRQn); + } } /****************************************************************************************************************************************** @@ -108,34 +107,34 @@ void PWM_Init(PWM_TypeDef * PWMx, PWM_InitStructure * initStruct) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_Start(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB) +void PWM_Start(PWM_TypeDef *PWMx, uint32_t chA, uint32_t chB) { - switch((uint32_t)PWMx) - { - case((uint32_t)PWM0): - PWMG->CHEN |= (chA << PWMG_CHEN_PWM0A_Pos) | (chB << PWMG_CHEN_PWM0B_Pos); - break; + switch ((uint32_t)PWMx) + { + case ((uint32_t)PWM0): + PWMG->CHEN |= (chA << PWMG_CHEN_PWM0A_Pos) | (chB << PWMG_CHEN_PWM0B_Pos); + break; - case((uint32_t)PWM1): - PWMG->CHEN |= (chA << PWMG_CHEN_PWM1A_Pos) | (chB << PWMG_CHEN_PWM1B_Pos); - break; + case ((uint32_t)PWM1): + PWMG->CHEN |= (chA << PWMG_CHEN_PWM1A_Pos) | (chB << PWMG_CHEN_PWM1B_Pos); + break; - case((uint32_t)PWM2): - PWMG->CHEN |= (chA << PWMG_CHEN_PWM2A_Pos) | (chB << PWMG_CHEN_PWM2B_Pos); - break; - - case((uint32_t)PWM3): - PWMG->CHEN |= (chA << PWMG_CHEN_PWM3A_Pos) | (chB << PWMG_CHEN_PWM3B_Pos); - break; - - case((uint32_t)PWM4): - PWMG->CHEN |= (chA << PWMG_CHEN_PWM4A_Pos) | (chB << PWMG_CHEN_PWM4B_Pos); - break; - - case((uint32_t)PWM5): - PWMG->CHEN |= (chA << PWMG_CHEN_PWM5A_Pos) | (chB << PWMG_CHEN_PWM5B_Pos); - break; - } + case ((uint32_t)PWM2): + PWMG->CHEN |= (chA << PWMG_CHEN_PWM2A_Pos) | (chB << PWMG_CHEN_PWM2B_Pos); + break; + + case ((uint32_t)PWM3): + PWMG->CHEN |= (chA << PWMG_CHEN_PWM3A_Pos) | (chB << PWMG_CHEN_PWM3B_Pos); + break; + + case ((uint32_t)PWM4): + PWMG->CHEN |= (chA << PWMG_CHEN_PWM4A_Pos) | (chB << PWMG_CHEN_PWM4B_Pos); + break; + + case ((uint32_t)PWM5): + PWMG->CHEN |= (chA << PWMG_CHEN_PWM5A_Pos) | (chB << PWMG_CHEN_PWM5B_Pos); + break; + } } /****************************************************************************************************************************************** @@ -147,34 +146,34 @@ void PWM_Start(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_Stop(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB) +void PWM_Stop(PWM_TypeDef *PWMx, uint32_t chA, uint32_t chB) { - switch((uint32_t)PWMx) - { - case((uint32_t)PWM0): - PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM0A_Pos) | (chB << PWMG_CHEN_PWM0B_Pos)); - break; + switch ((uint32_t)PWMx) + { + case ((uint32_t)PWM0): + PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM0A_Pos) | (chB << PWMG_CHEN_PWM0B_Pos)); + break; - case((uint32_t)PWM1): - PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM1A_Pos) | (chB << PWMG_CHEN_PWM1B_Pos)); - break; + case ((uint32_t)PWM1): + PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM1A_Pos) | (chB << PWMG_CHEN_PWM1B_Pos)); + break; - case((uint32_t)PWM2): - PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM2A_Pos) | (chB << PWMG_CHEN_PWM2B_Pos)); - break; - - case((uint32_t)PWM3): - PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM3A_Pos) | (chB << PWMG_CHEN_PWM3B_Pos)); - break; - - case((uint32_t)PWM4): - PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM4A_Pos) | (chB << PWMG_CHEN_PWM4B_Pos)); - break; - - case((uint32_t)PWM5): - PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM5A_Pos) | (chB << PWMG_CHEN_PWM5B_Pos)); - break; - } + case ((uint32_t)PWM2): + PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM2A_Pos) | (chB << PWMG_CHEN_PWM2B_Pos)); + break; + + case ((uint32_t)PWM3): + PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM3A_Pos) | (chB << PWMG_CHEN_PWM3B_Pos)); + break; + + case ((uint32_t)PWM4): + PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM4A_Pos) | (chB << PWMG_CHEN_PWM4B_Pos)); + break; + + case ((uint32_t)PWM5): + PWMG->CHEN &= ~((chA << PWMG_CHEN_PWM5A_Pos) | (chB << PWMG_CHEN_PWM5B_Pos)); + break; + } } /****************************************************************************************************************************************** @@ -186,12 +185,12 @@ void PWM_Stop(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_SetCycle(PWM_TypeDef * PWMx, uint32_t chn, uint16_t cycle) +void PWM_SetCycle(PWM_TypeDef *PWMx, uint32_t chn, uint16_t cycle) { - if(chn == PWM_CH_A) - PWMx->PERA = cycle; - else if(chn == PWM_CH_B) - PWMx->PERB = cycle; + if (chn == PWM_CH_A) + PWMx->PERA = cycle; + else if (chn == PWM_CH_B) + PWMx->PERB = cycle; } /****************************************************************************************************************************************** @@ -202,16 +201,16 @@ void PWM_SetCycle(PWM_TypeDef * PWMx, uint32_t chn, uint16_t cycle) * 输 出: uint16_t 获取到的周期值 * 注意事项: 无 ******************************************************************************************************************************************/ -uint16_t PWM_GetCycle(PWM_TypeDef * PWMx, uint32_t chn) +uint16_t PWM_GetCycle(PWM_TypeDef *PWMx, uint32_t chn) { - uint16_t cycle = 0; - - if(chn == PWM_CH_A) - cycle = PWMx->PERA; - else if(chn == PWM_CH_B) - cycle = PWMx->PERB; - - return cycle; + uint16_t cycle = 0; + + if (chn == PWM_CH_A) + cycle = PWMx->PERA; + else if (chn == PWM_CH_B) + cycle = PWMx->PERB; + + return cycle; } /****************************************************************************************************************************************** @@ -223,12 +222,12 @@ uint16_t PWM_GetCycle(PWM_TypeDef * PWMx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_SetHDuty(PWM_TypeDef * PWMx, uint32_t chn, uint16_t hduty) +void PWM_SetHDuty(PWM_TypeDef *PWMx, uint32_t chn, uint16_t hduty) { - if(chn == PWM_CH_A) - PWMx->HIGHA = hduty; - else if(chn == PWM_CH_B) - PWMx->HIGHB = hduty; + if (chn == PWM_CH_A) + PWMx->HIGHA = hduty; + else if (chn == PWM_CH_B) + PWMx->HIGHB = hduty; } /****************************************************************************************************************************************** @@ -239,16 +238,16 @@ void PWM_SetHDuty(PWM_TypeDef * PWMx, uint32_t chn, uint16_t hduty) * 输 出: uint16_t 获取到的高电平时长 * 注意事项: 无 ******************************************************************************************************************************************/ -uint16_t PWM_GetHDuty(PWM_TypeDef * PWMx, uint32_t chn) +uint16_t PWM_GetHDuty(PWM_TypeDef *PWMx, uint32_t chn) { - uint16_t hduty = 0; - - if(chn == PWM_CH_A) - hduty = PWMx->HIGHA; - else if(chn == PWM_CH_B) - hduty = PWMx->HIGHB; - - return hduty; + uint16_t hduty = 0; + + if (chn == PWM_CH_A) + hduty = PWMx->HIGHA; + else if (chn == PWM_CH_B) + hduty = PWMx->HIGHB; + + return hduty; } /****************************************************************************************************************************************** @@ -260,12 +259,12 @@ uint16_t PWM_GetHDuty(PWM_TypeDef * PWMx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_SetDeadzone(PWM_TypeDef * PWMx, uint32_t chn, uint8_t deadzone) +void PWM_SetDeadzone(PWM_TypeDef *PWMx, uint32_t chn, uint8_t deadzone) { - if(chn == PWM_CH_A) - PWMx->DZA = deadzone; - else if(chn == PWM_CH_B) - PWMx->DZB = deadzone; + if (chn == PWM_CH_A) + PWMx->DZA = deadzone; + else if (chn == PWM_CH_B) + PWMx->DZB = deadzone; } /****************************************************************************************************************************************** @@ -276,18 +275,17 @@ void PWM_SetDeadzone(PWM_TypeDef * PWMx, uint32_t chn, uint8_t deadzone) * 输 出: uint8_t 获取到的死区时长 * 注意事项: 无 ******************************************************************************************************************************************/ -uint8_t PWM_GetDeadzone(PWM_TypeDef * PWMx, uint32_t chn) +uint8_t PWM_GetDeadzone(PWM_TypeDef *PWMx, uint32_t chn) { - uint8_t deadzone = 0; - - if(chn == PWM_CH_A) - deadzone = PWMx->DZA; - else if(chn == PWM_CH_B) - deadzone = PWMx->DZB; - - return deadzone; -} + uint8_t deadzone = 0; + if (chn == PWM_CH_A) + deadzone = PWMx->DZA; + else if (chn == PWM_CH_B) + deadzone = PWMx->DZB; + + return deadzone; +} /****************************************************************************************************************************************** * 函数名称: PWM_IntNCycleEn() @@ -297,40 +295,52 @@ uint8_t PWM_GetDeadzone(PWM_TypeDef * PWMx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_IntNCycleEn(PWM_TypeDef * PWMx, uint32_t chn) +void PWM_IntNCycleEn(PWM_TypeDef *PWMx, uint32_t chn) { - switch((uint32_t)PWMx) - { - case((uint32_t)PWM0): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_NEWP0A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_NEWP0B_Pos); - break; - - case((uint32_t)PWM1): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_NEWP1A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_NEWP1B_Pos); - break; - - case((uint32_t)PWM2): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_NEWP2A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_NEWP2B_Pos); - break; - - case((uint32_t)PWM3): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_NEWP3A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_NEWP3B_Pos); - break; - - case((uint32_t)PWM4): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_NEWP4A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_NEWP4B_Pos); - break; - - case((uint32_t)PWM5): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_NEWP5A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_NEWP5B_Pos); - break; - } + switch ((uint32_t)PWMx) + { + case ((uint32_t)PWM0): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_NEWP0A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_NEWP0B_Pos); + break; + + case ((uint32_t)PWM1): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_NEWP1A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_NEWP1B_Pos); + break; + + case ((uint32_t)PWM2): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_NEWP2A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_NEWP2B_Pos); + break; + + case ((uint32_t)PWM3): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_NEWP3A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_NEWP3B_Pos); + break; + + case ((uint32_t)PWM4): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_NEWP4A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_NEWP4B_Pos); + break; + + case ((uint32_t)PWM5): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_NEWP5A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_NEWP5B_Pos); + break; + } } /****************************************************************************************************************************************** @@ -341,40 +351,52 @@ void PWM_IntNCycleEn(PWM_TypeDef * PWMx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_IntNCycleDis(PWM_TypeDef * PWMx, uint32_t chn) +void PWM_IntNCycleDis(PWM_TypeDef *PWMx, uint32_t chn) { - switch((uint32_t)PWMx) - { - case((uint32_t)PWM0): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_NEWP0A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_NEWP0B_Pos); - break; - - case((uint32_t)PWM1): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_NEWP1A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_NEWP1B_Pos); - break; - - case((uint32_t)PWM2): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_NEWP2A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_NEWP2B_Pos); - break; - - case((uint32_t)PWM3): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_NEWP3A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_NEWP3B_Pos); - break; - - case((uint32_t)PWM4): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_NEWP4A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_NEWP4B_Pos); - break; - - case((uint32_t)PWM5): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_NEWP5A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_NEWP5B_Pos); - break; - } + switch ((uint32_t)PWMx) + { + case ((uint32_t)PWM0): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP0A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP0B_Pos); + break; + + case ((uint32_t)PWM1): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP1A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP1B_Pos); + break; + + case ((uint32_t)PWM2): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP2A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP2B_Pos); + break; + + case ((uint32_t)PWM3): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP3A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP3B_Pos); + break; + + case ((uint32_t)PWM4): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP4A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP4B_Pos); + break; + + case ((uint32_t)PWM5): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP5A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_NEWP5B_Pos); + break; + } } /****************************************************************************************************************************************** @@ -385,40 +407,52 @@ void PWM_IntNCycleDis(PWM_TypeDef * PWMx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_IntNCycleClr(PWM_TypeDef * PWMx, uint32_t chn) +void PWM_IntNCycleClr(PWM_TypeDef *PWMx, uint32_t chn) { - switch((uint32_t)PWMx) - { - case((uint32_t)PWM0): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_NEWP0A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_NEWP0B_Pos); - break; - - case((uint32_t)PWM1): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_NEWP1A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_NEWP1B_Pos); - break; - - case((uint32_t)PWM2): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_NEWP2A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_NEWP2B_Pos); - break; - - case((uint32_t)PWM3): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_NEWP3A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_NEWP3B_Pos); - break; - - case((uint32_t)PWM4): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_NEWP4A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_NEWP4B_Pos); - break; - - case((uint32_t)PWM5): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_NEWP5A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_NEWP5B_Pos); - break; - } + switch ((uint32_t)PWMx) + { + case ((uint32_t)PWM0): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_NEWP0A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_NEWP0B_Pos); + break; + + case ((uint32_t)PWM1): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_NEWP1A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_NEWP1B_Pos); + break; + + case ((uint32_t)PWM2): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_NEWP2A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_NEWP2B_Pos); + break; + + case ((uint32_t)PWM3): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_NEWP3A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_NEWP3B_Pos); + break; + + case ((uint32_t)PWM4): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_NEWP4A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_NEWP4B_Pos); + break; + + case ((uint32_t)PWM5): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_NEWP5A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_NEWP5B_Pos); + break; + } } /****************************************************************************************************************************************** @@ -429,47 +463,58 @@ void PWM_IntNCycleClr(PWM_TypeDef * PWMx, uint32_t chn) * 输 出: uint32_t 1 新周期开始中断已发生 0 新周期开始中断未发生 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t PWM_IntNCycleStat(PWM_TypeDef * PWMx, uint32_t chn) +uint32_t PWM_IntNCycleStat(PWM_TypeDef *PWMx, uint32_t chn) { - uint32_t int_stat = 0; - - switch((uint32_t)PWMx) - { - case((uint32_t)PWM0): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_NEWP0A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_NEWP0B_Msk); - break; + uint32_t int_stat = 0; - case((uint32_t)PWM1): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_NEWP1A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_NEWP1B_Msk); - break; + switch ((uint32_t)PWMx) + { + case ((uint32_t)PWM0): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_NEWP0A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_NEWP0B_Msk); + break; - case((uint32_t)PWM2): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_NEWP2A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_NEWP2B_Msk); - break; - - case((uint32_t)PWM3): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_NEWP3A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_NEWP3B_Msk); - break; - - case((uint32_t)PWM4): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_NEWP4A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_NEWP4B_Msk); - break; - - case((uint32_t)PWM5): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_NEWP5A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_NEWP5B_Msk); - break; - } - - return int_stat; + case ((uint32_t)PWM1): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_NEWP1A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_NEWP1B_Msk); + break; + + case ((uint32_t)PWM2): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_NEWP2A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_NEWP2B_Msk); + break; + + case ((uint32_t)PWM3): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_NEWP3A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_NEWP3B_Msk); + break; + + case ((uint32_t)PWM4): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_NEWP4A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_NEWP4B_Msk); + break; + + case ((uint32_t)PWM5): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_NEWP5A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_NEWP5B_Msk); + break; + } + + return int_stat; } - /****************************************************************************************************************************************** * 函数名称: PWM_IntHEndEn() * 功能说明: 高电平结束中断使能 @@ -478,40 +523,52 @@ uint32_t PWM_IntNCycleStat(PWM_TypeDef * PWMx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_IntHEndEn(PWM_TypeDef * PWMx, uint32_t chn) +void PWM_IntHEndEn(PWM_TypeDef *PWMx, uint32_t chn) { - switch((uint32_t)PWMx) - { - case((uint32_t)PWM0): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_HEND0A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_HEND0B_Pos); - break; - - case((uint32_t)PWM1): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_HEND1A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_HEND1B_Pos); - break; - - case((uint32_t)PWM2): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_HEND2A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_HEND2B_Pos); - break; - - case((uint32_t)PWM3): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_HEND3A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_HEND3B_Pos); - break; - - case((uint32_t)PWM4): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_HEND4A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_HEND4B_Pos); - break; - - case((uint32_t)PWM5): - if(chn == PWM_CH_A) PWMG->IE |= (0x01 << PWMG_IE_HEND5A_Pos); - else PWMG->IE |= (0x01 << PWMG_IE_HEND5B_Pos); - break; - } + switch ((uint32_t)PWMx) + { + case ((uint32_t)PWM0): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_HEND0A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_HEND0B_Pos); + break; + + case ((uint32_t)PWM1): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_HEND1A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_HEND1B_Pos); + break; + + case ((uint32_t)PWM2): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_HEND2A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_HEND2B_Pos); + break; + + case ((uint32_t)PWM3): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_HEND3A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_HEND3B_Pos); + break; + + case ((uint32_t)PWM4): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_HEND4A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_HEND4B_Pos); + break; + + case ((uint32_t)PWM5): + if (chn == PWM_CH_A) + PWMG->IE |= (0x01 << PWMG_IE_HEND5A_Pos); + else + PWMG->IE |= (0x01 << PWMG_IE_HEND5B_Pos); + break; + } } /****************************************************************************************************************************************** @@ -522,40 +579,52 @@ void PWM_IntHEndEn(PWM_TypeDef * PWMx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_IntHEndDis(PWM_TypeDef * PWMx, uint32_t chn) +void PWM_IntHEndDis(PWM_TypeDef *PWMx, uint32_t chn) { - switch((uint32_t)PWMx) - { - case((uint32_t)PWM0): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_HEND0A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_HEND0B_Pos); - break; - - case((uint32_t)PWM1): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_HEND1A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_HEND1B_Pos); - break; - - case((uint32_t)PWM2): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_HEND2A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_HEND2B_Pos); - break; - - case((uint32_t)PWM3): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_HEND3A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_HEND3B_Pos); - break; - - case((uint32_t)PWM4): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_HEND4A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_HEND4B_Pos); - break; - - case((uint32_t)PWM5): - if(chn == PWM_CH_A) PWMG->IE &= ~(0x01 << PWMG_IE_HEND5A_Pos); - else PWMG->IE &= ~(0x01 << PWMG_IE_HEND5B_Pos); - break; - } + switch ((uint32_t)PWMx) + { + case ((uint32_t)PWM0): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_HEND0A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_HEND0B_Pos); + break; + + case ((uint32_t)PWM1): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_HEND1A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_HEND1B_Pos); + break; + + case ((uint32_t)PWM2): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_HEND2A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_HEND2B_Pos); + break; + + case ((uint32_t)PWM3): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_HEND3A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_HEND3B_Pos); + break; + + case ((uint32_t)PWM4): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_HEND4A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_HEND4B_Pos); + break; + + case ((uint32_t)PWM5): + if (chn == PWM_CH_A) + PWMG->IE &= ~(0x01 << PWMG_IE_HEND5A_Pos); + else + PWMG->IE &= ~(0x01 << PWMG_IE_HEND5B_Pos); + break; + } } /****************************************************************************************************************************************** @@ -566,40 +635,52 @@ void PWM_IntHEndDis(PWM_TypeDef * PWMx, uint32_t chn) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void PWM_IntHEndClr(PWM_TypeDef * PWMx, uint32_t chn) +void PWM_IntHEndClr(PWM_TypeDef *PWMx, uint32_t chn) { - switch((uint32_t)PWMx) - { - case((uint32_t)PWM0): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_HEND0A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_HEND0B_Pos); - break; - - case((uint32_t)PWM1): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_HEND1A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_HEND1B_Pos); - break; - - case((uint32_t)PWM2): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_HEND2A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_HEND2B_Pos); - break; - - case((uint32_t)PWM3): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_HEND3A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_HEND3B_Pos); - break; - - case((uint32_t)PWM4): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_HEND4A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_HEND4B_Pos); - break; - - case((uint32_t)PWM5): - if(chn == PWM_CH_A) PWMG->IRS = (0x01 << PWMG_IRS_HEND5A_Pos); - else PWMG->IRS = (0x01 << PWMG_IRS_HEND5B_Pos); - break; - } + switch ((uint32_t)PWMx) + { + case ((uint32_t)PWM0): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_HEND0A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_HEND0B_Pos); + break; + + case ((uint32_t)PWM1): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_HEND1A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_HEND1B_Pos); + break; + + case ((uint32_t)PWM2): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_HEND2A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_HEND2B_Pos); + break; + + case ((uint32_t)PWM3): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_HEND3A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_HEND3B_Pos); + break; + + case ((uint32_t)PWM4): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_HEND4A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_HEND4B_Pos); + break; + + case ((uint32_t)PWM5): + if (chn == PWM_CH_A) + PWMG->IRS = (0x01 << PWMG_IRS_HEND5A_Pos); + else + PWMG->IRS = (0x01 << PWMG_IRS_HEND5B_Pos); + break; + } } /****************************************************************************************************************************************** @@ -610,42 +691,54 @@ void PWM_IntHEndClr(PWM_TypeDef * PWMx, uint32_t chn) * 输 出: uint32_t 1 高电平结束中断已发生 0 高电平结束中断未发生 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t PWM_IntHEndStat(PWM_TypeDef * PWMx, uint32_t chn) +uint32_t PWM_IntHEndStat(PWM_TypeDef *PWMx, uint32_t chn) { - uint32_t int_stat = 0; - - switch((uint32_t)PWMx) - { - case((uint32_t)PWM0): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_HEND0A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_HEND0B_Msk); - break; + uint32_t int_stat = 0; - case((uint32_t)PWM1): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_HEND1A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_HEND1B_Msk); - break; + switch ((uint32_t)PWMx) + { + case ((uint32_t)PWM0): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_HEND0A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_HEND0B_Msk); + break; - case((uint32_t)PWM2): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_HEND2A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_HEND2B_Msk); - break; - - case((uint32_t)PWM3): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_HEND3A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_HEND3B_Msk); - break; - - case((uint32_t)PWM4): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_HEND4A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_HEND4B_Msk); - break; - - case((uint32_t)PWM5): - if(chn == PWM_CH_A) int_stat = (PWMG->IF & PWMG_IF_HEND5A_Msk); - else int_stat = (PWMG->IF & PWMG_IF_HEND5B_Msk); - break; - } - - return int_stat; + case ((uint32_t)PWM1): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_HEND1A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_HEND1B_Msk); + break; + + case ((uint32_t)PWM2): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_HEND2A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_HEND2B_Msk); + break; + + case ((uint32_t)PWM3): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_HEND3A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_HEND3B_Msk); + break; + + case ((uint32_t)PWM4): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_HEND4A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_HEND4B_Msk); + break; + + case ((uint32_t)PWM5): + if (chn == PWM_CH_A) + int_stat = (PWMG->IF & PWMG_IF_HEND5A_Msk); + else + int_stat = (PWMG->IF & PWMG_IF_HEND5B_Msk); + break; + } + + return int_stat; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.h index 6f857fae37..888e0c5e39 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_pwm.h @@ -1,58 +1,57 @@ #ifndef __SWM320_PWM_H__ -#define __SWM320_PWM_H__ +#define __SWM320_PWM_H__ -typedef struct { - uint8_t clk_div; //PWM_CLKDIV_1、PWM_CLKDIV_8 - - uint8_t mode; //PWM_MODE_INDEP、PWM_MODE_COMPL、PWM_MODE_INDEP_CALIGN、PWM_MODE_COMPL_CALIGN - - uint16_t cycleA; //A路周期 - uint16_t hdutyA; //A路占空比 - uint16_t deadzoneA; //A路死区时长,取值0--1023 - uint8_t initLevelA; //A路初始输出电平,0 低电平 1 高电平 - - uint16_t cycleB; //B路周期 - uint16_t hdutyB; //B路占空比 - uint16_t deadzoneB; //B路死区时长,取值0--1023 - uint8_t initLevelB; //B路初始输出电平,0 低电平 1 高电平 - - uint8_t HEndAIEn; //A路高电平结束中断使能 - uint8_t NCycleAIEn; //A路新周期开始中断使能 - uint8_t HEndBIEn; //B路高电平结束中断使能 - uint8_t NCycleBIEn; //B路新周期开始中断使能 +typedef struct +{ + uint8_t clk_div; //PWM_CLKDIV_1、PWM_CLKDIV_8 + + uint8_t mode; //PWM_MODE_INDEP、PWM_MODE_COMPL、PWM_MODE_INDEP_CALIGN、PWM_MODE_COMPL_CALIGN + + uint16_t cycleA; //A路周期 + uint16_t hdutyA; //A路占空比 + uint16_t deadzoneA; //A路死区时长,取值0--1023 + uint8_t initLevelA; //A路初始输出电平,0 低电平 1 高电平 + + uint16_t cycleB; //B路周期 + uint16_t hdutyB; //B路占空比 + uint16_t deadzoneB; //B路死区时长,取值0--1023 + uint8_t initLevelB; //B路初始输出电平,0 低电平 1 高电平 + + uint8_t HEndAIEn; //A路高电平结束中断使能 + uint8_t NCycleAIEn; //A路新周期开始中断使能 + uint8_t HEndBIEn; //B路高电平结束中断使能 + uint8_t NCycleBIEn; //B路新周期开始中断使能 } PWM_InitStructure; -#define PWM_CLKDIV_1 0 -#define PWM_CLKDIV_8 1 +#define PWM_CLKDIV_1 0 +#define PWM_CLKDIV_8 1 -#define PWM_MODE_INDEP 0 //A路和B路为两路独立输出 -#define PWM_MODE_COMPL 1 //A路和B路为一路互补输出 -#define PWM_MODE_INDEP_CALIGN 3 //A路和B路为两路独立输出,中心对齐 -#define PWM_MODE_COMPL_CALIGN 4 //A路和B路为一路互补输出,中心对齐 +#define PWM_MODE_INDEP 0 //A路和B路为两路独立输出 +#define PWM_MODE_COMPL 1 //A路和B路为一路互补输出 +#define PWM_MODE_INDEP_CALIGN 3 //A路和B路为两路独立输出,中心对齐 +#define PWM_MODE_COMPL_CALIGN 4 //A路和B路为一路互补输出,中心对齐 -#define PWM_CH_A 0 -#define PWM_CH_B 1 +#define PWM_CH_A 0 +#define PWM_CH_B 1 +void PWM_Init(PWM_TypeDef *PWMx, PWM_InitStructure *initStruct); //PWM初始化 +void PWM_Start(PWM_TypeDef *PWMx, uint32_t chA, uint32_t chB); //启动PWM,开始PWM输出 +void PWM_Stop(PWM_TypeDef *PWMx, uint32_t chA, uint32_t chB); //关闭PWM,停止PWM输出 -void PWM_Init(PWM_TypeDef * PWMx, PWM_InitStructure * initStruct); //PWM初始化 -void PWM_Start(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB); //启动PWM,开始PWM输出 -void PWM_Stop(PWM_TypeDef * PWMx, uint32_t chA, uint32_t chB); //关闭PWM,停止PWM输出 - -void PWM_SetCycle(PWM_TypeDef * PWMx, uint32_t chn, uint16_t cycle); //设置周期 -uint16_t PWM_GetCycle(PWM_TypeDef * PWMx, uint32_t chn); //获取周期 -void PWM_SetHDuty(PWM_TypeDef * PWMx, uint32_t chn, uint16_t hduty); //设置高电平时长 -uint16_t PWM_GetHDuty(PWM_TypeDef * PWMx, uint32_t chn); //获取高电平时长 -void PWM_SetDeadzone(PWM_TypeDef * PWMx, uint32_t chn, uint8_t deadzone); //设置死区时长 -uint8_t PWM_GetDeadzone(PWM_TypeDef * PWMx, uint32_t chn); //获取死区时长 - -void PWM_IntNCycleEn(PWM_TypeDef * PWMx, uint32_t chn); //新周期开始中断使能 -void PWM_IntNCycleDis(PWM_TypeDef * PWMx, uint32_t chn); //新周期开始中断禁能 -void PWM_IntNCycleClr(PWM_TypeDef * PWMx, uint32_t chn); //新周期开始中断标志清除 -uint32_t PWM_IntNCycleStat(PWM_TypeDef * PWMx, uint32_t chn); //新周期开始中断是否发生 -void PWM_IntHEndEn(PWM_TypeDef * PWMx, uint32_t chn); //高电平结束中断使能 -void PWM_IntHEndDis(PWM_TypeDef * PWMx, uint32_t chn); //高电平结束中断禁能 -void PWM_IntHEndClr(PWM_TypeDef * PWMx, uint32_t chn); //高电平结束中断标志清除 -uint32_t PWM_IntHEndStat(PWM_TypeDef * PWMx, uint32_t chn); //高电平结束中断是否发生 +void PWM_SetCycle(PWM_TypeDef *PWMx, uint32_t chn, uint16_t cycle); //设置周期 +uint16_t PWM_GetCycle(PWM_TypeDef *PWMx, uint32_t chn); //获取周期 +void PWM_SetHDuty(PWM_TypeDef *PWMx, uint32_t chn, uint16_t hduty); //设置高电平时长 +uint16_t PWM_GetHDuty(PWM_TypeDef *PWMx, uint32_t chn); //获取高电平时长 +void PWM_SetDeadzone(PWM_TypeDef *PWMx, uint32_t chn, uint8_t deadzone); //设置死区时长 +uint8_t PWM_GetDeadzone(PWM_TypeDef *PWMx, uint32_t chn); //获取死区时长 +void PWM_IntNCycleEn(PWM_TypeDef *PWMx, uint32_t chn); //新周期开始中断使能 +void PWM_IntNCycleDis(PWM_TypeDef *PWMx, uint32_t chn); //新周期开始中断禁能 +void PWM_IntNCycleClr(PWM_TypeDef *PWMx, uint32_t chn); //新周期开始中断标志清除 +uint32_t PWM_IntNCycleStat(PWM_TypeDef *PWMx, uint32_t chn); //新周期开始中断是否发生 +void PWM_IntHEndEn(PWM_TypeDef *PWMx, uint32_t chn); //高电平结束中断使能 +void PWM_IntHEndDis(PWM_TypeDef *PWMx, uint32_t chn); //高电平结束中断禁能 +void PWM_IntHEndClr(PWM_TypeDef *PWMx, uint32_t chn); //高电平结束中断标志清除 +uint32_t PWM_IntHEndStat(PWM_TypeDef *PWMx, uint32_t chn); //高电平结束中断是否发生 #endif //__SWM320_PWM_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.c index d43ee91f15..0489551511 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.c @@ -21,7 +21,6 @@ #include "SWM320.h" #include "SWM320_rtc.h" - static uint32_t calcWeekDay(uint32_t year, uint32_t month, uint32_t date); /****************************************************************************************************************************************** * 函数名称: RTC_Init() @@ -31,44 +30,45 @@ static uint32_t calcWeekDay(uint32_t year, uint32_t month, uint32_t date); * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_Init(RTC_TypeDef * RTCx, RTC_InitStructure * initStruct) -{ - SYS->CLKEN |= (1 << SYS_CLKEN_RTCBKP_Pos); - - SYS->LRCCR &= ~(1 << SYS_LRCCR_OFF_Pos); //RTC使用32KHz RC时钟 - - SYS->CLKEN |= (1 << SYS_CLKEN_RTC_Pos) | - ((uint32_t)1 << SYS_CLKEN_ALIVE_Pos); - - RTC_Stop(RTCx); - - while(RTCx->CFGABLE == 0); - - RTCx->MINSEC = (initStruct->Second << RTC_MINSEC_SEC_Pos) | - (initStruct->Minute << RTC_MINSEC_MIN_Pos); - - RTCx->DATHUR = (initStruct->Hour << RTC_DATHUR_HOUR_Pos) | - (initStruct->Date << RTC_DATHUR_DATE_Pos); - - RTCx->MONDAY = (calcWeekDay(initStruct->Year, initStruct->Month, initStruct->Date) << RTC_MONDAY_DAY_Pos) | - (initStruct->Month << RTC_MONDAY_MON_Pos); - - RTCx->YEAR = initStruct->Year - 1901; - - RTCx->LOAD = 1 << RTC_LOAD_TIME_Pos; - - RTCx->IF = 0x1F; - RTCx->IE = (initStruct->SecondIEn << RTC_IE_SEC_Pos) | - (initStruct->MinuteIEn << RTC_IE_MIN_Pos); - - if(initStruct->SecondIEn | initStruct->MinuteIEn) - { - NVIC_EnableIRQ(RTC_IRQn); - } - else - { - NVIC_DisableIRQ(RTC_IRQn); - } +void RTC_Init(RTC_TypeDef *RTCx, RTC_InitStructure *initStruct) +{ + SYS->CLKEN |= (1 << SYS_CLKEN_RTCBKP_Pos); + + SYS->LRCCR &= ~(1 << SYS_LRCCR_OFF_Pos); //RTC使用32KHz RC时钟 + + SYS->CLKEN |= (1 << SYS_CLKEN_RTC_Pos) | + ((uint32_t)1 << SYS_CLKEN_ALIVE_Pos); + + RTC_Stop(RTCx); + + while (RTCx->CFGABLE == 0) + ; + + RTCx->MINSEC = (initStruct->Second << RTC_MINSEC_SEC_Pos) | + (initStruct->Minute << RTC_MINSEC_MIN_Pos); + + RTCx->DATHUR = (initStruct->Hour << RTC_DATHUR_HOUR_Pos) | + (initStruct->Date << RTC_DATHUR_DATE_Pos); + + RTCx->MONDAY = (calcWeekDay(initStruct->Year, initStruct->Month, initStruct->Date) << RTC_MONDAY_DAY_Pos) | + (initStruct->Month << RTC_MONDAY_MON_Pos); + + RTCx->YEAR = initStruct->Year - 1901; + + RTCx->LOAD = 1 << RTC_LOAD_TIME_Pos; + + RTCx->IF = 0x1F; + RTCx->IE = (initStruct->SecondIEn << RTC_IE_SEC_Pos) | + (initStruct->MinuteIEn << RTC_IE_MIN_Pos); + + if (initStruct->SecondIEn | initStruct->MinuteIEn) + { + NVIC_EnableIRQ(RTC_IRQn); + } + else + { + NVIC_DisableIRQ(RTC_IRQn); + } } /****************************************************************************************************************************************** @@ -78,9 +78,9 @@ void RTC_Init(RTC_TypeDef * RTCx, RTC_InitStructure * initStruct) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_Start(RTC_TypeDef * RTCx) +void RTC_Start(RTC_TypeDef *RTCx) { - RTCx->EN = 1; + RTCx->EN = 1; } /****************************************************************************************************************************************** @@ -90,9 +90,9 @@ void RTC_Start(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_Stop(RTC_TypeDef * RTCx) +void RTC_Stop(RTC_TypeDef *RTCx) { - RTCx->EN = 0; + RTCx->EN = 0; } /****************************************************************************************************************************************** @@ -103,15 +103,15 @@ void RTC_Stop(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_GetDateTime(RTC_TypeDef * RTCx, RTC_DateTime * dateTime) +void RTC_GetDateTime(RTC_TypeDef *RTCx, RTC_DateTime *dateTime) { - dateTime->Year = RTCx->YEAR + 1901; - dateTime->Month = (RTCx->MONDAY & RTC_MONDAY_MON_Msk) >> RTC_MONDAY_MON_Pos; - dateTime->Date = (RTCx->DATHUR & RTC_DATHUR_DATE_Msk) >> RTC_DATHUR_DATE_Pos; - dateTime->Day = 1 << ((RTCx->MONDAY & RTC_MONDAY_DAY_Msk) >> RTC_MONDAY_DAY_Pos); - dateTime->Hour = (RTCx->DATHUR & RTC_DATHUR_HOUR_Msk) >> RTC_DATHUR_HOUR_Pos; - dateTime->Minute = (RTCx->MINSEC & RTC_MINSEC_MIN_Msk) >> RTC_MINSEC_MIN_Pos; - dateTime->Second = (RTCx->MINSEC & RTC_MINSEC_SEC_Msk) >> RTC_MINSEC_SEC_Pos; + dateTime->Year = RTCx->YEAR + 1901; + dateTime->Month = (RTCx->MONDAY & RTC_MONDAY_MON_Msk) >> RTC_MONDAY_MON_Pos; + dateTime->Date = (RTCx->DATHUR & RTC_DATHUR_DATE_Msk) >> RTC_DATHUR_DATE_Pos; + dateTime->Day = 1 << ((RTCx->MONDAY & RTC_MONDAY_DAY_Msk) >> RTC_MONDAY_DAY_Pos); + dateTime->Hour = (RTCx->DATHUR & RTC_DATHUR_HOUR_Msk) >> RTC_DATHUR_HOUR_Pos; + dateTime->Minute = (RTCx->MINSEC & RTC_MINSEC_MIN_Msk) >> RTC_MINSEC_MIN_Pos; + dateTime->Second = (RTCx->MINSEC & RTC_MINSEC_SEC_Msk) >> RTC_MINSEC_SEC_Pos; } /****************************************************************************************************************************************** @@ -122,24 +122,27 @@ void RTC_GetDateTime(RTC_TypeDef * RTCx, RTC_DateTime * dateTime) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_AlarmSetup(RTC_TypeDef * RTCx, RTC_AlarmStructure * alarmStruct) +void RTC_AlarmSetup(RTC_TypeDef *RTCx, RTC_AlarmStructure *alarmStruct) { - while(RTCx->CFGABLE == 0); - - RTCx->MINSECAL = (alarmStruct->Second << RTC_MINSECAL_SEC_Pos) | - (alarmStruct->Minute << RTC_MINSECAL_MIN_Pos); - - RTCx->DAYHURAL = (alarmStruct->Hour << RTC_DAYHURAL_HOUR_Pos) | - (alarmStruct->Days << RTC_DAYHURAL_SUN_Pos); - - RTCx->LOAD = 1 << RTC_LOAD_ALARM_Pos; - while(RTCx->LOAD & RTC_LOAD_ALARM_Msk); - - RTCx->IF = (1 << RTC_IF_ALARM_Pos); - RTCx->IE &= ~RTC_IE_ALARM_Msk; - RTCx->IE |= (alarmStruct->AlarmIEn << RTC_IE_ALARM_Pos); - - if(alarmStruct->AlarmIEn) NVIC_EnableIRQ(RTC_IRQn); + while (RTCx->CFGABLE == 0) + ; + + RTCx->MINSECAL = (alarmStruct->Second << RTC_MINSECAL_SEC_Pos) | + (alarmStruct->Minute << RTC_MINSECAL_MIN_Pos); + + RTCx->DAYHURAL = (alarmStruct->Hour << RTC_DAYHURAL_HOUR_Pos) | + (alarmStruct->Days << RTC_DAYHURAL_SUN_Pos); + + RTCx->LOAD = 1 << RTC_LOAD_ALARM_Pos; + while (RTCx->LOAD & RTC_LOAD_ALARM_Msk) + ; + + RTCx->IF = (1 << RTC_IF_ALARM_Pos); + RTCx->IE &= ~RTC_IE_ALARM_Msk; + RTCx->IE |= (alarmStruct->AlarmIEn << RTC_IE_ALARM_Pos); + + if (alarmStruct->AlarmIEn) + NVIC_EnableIRQ(RTC_IRQn); } /****************************************************************************************************************************************** @@ -155,21 +158,24 @@ static uint32_t calcWeekDay(uint32_t year, uint32_t month, uint32_t date) { uint32_t i, cnt = 0; const uint32_t daysOfMonth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - - for(i = 1; i < month; i++) cnt += daysOfMonth[i]; - + + for (i = 1; i < month; i++) + cnt += daysOfMonth[i]; + cnt += date; - - if((year%4 == 0) && ((year%100 != 0) || (year%400 == 0)) && (month >= 3)) cnt += 1; - + + if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)) && (month >= 3)) + cnt += 1; + cnt += (year - 1901) * 365; - - for(i = 1901; i < year; i++) + + for (i = 1901; i < year; i++) { - if((i%4 == 0) && ((i%100 != 0) || (i%400 == 0))) cnt += 1; + if ((i % 4 == 0) && ((i % 100 != 0) || (i % 400 == 0))) + cnt += 1; } - - return (cnt+1) % 7; + + return (cnt + 1) % 7; } /****************************************************************************************************************************************** @@ -179,9 +185,9 @@ static uint32_t calcWeekDay(uint32_t year, uint32_t month, uint32_t date) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntSecondEn(RTC_TypeDef * RTCx) -{ - RTCx->IE |= (1 << RTC_IE_SEC_Pos); +void RTC_IntSecondEn(RTC_TypeDef *RTCx) +{ + RTCx->IE |= (1 << RTC_IE_SEC_Pos); } /****************************************************************************************************************************************** @@ -191,9 +197,9 @@ void RTC_IntSecondEn(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntSecondDis(RTC_TypeDef * RTCx) -{ - RTCx->IE &= ~(1 << RTC_IE_SEC_Pos); +void RTC_IntSecondDis(RTC_TypeDef *RTCx) +{ + RTCx->IE &= ~(1 << RTC_IE_SEC_Pos); } /****************************************************************************************************************************************** @@ -203,9 +209,9 @@ void RTC_IntSecondDis(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntSecondClr(RTC_TypeDef * RTCx) -{ - RTCx->IF = (1 << RTC_IF_SEC_Pos); +void RTC_IntSecondClr(RTC_TypeDef *RTCx) +{ + RTCx->IF = (1 << RTC_IF_SEC_Pos); } /****************************************************************************************************************************************** @@ -215,9 +221,9 @@ void RTC_IntSecondClr(RTC_TypeDef * RTCx) * 输 出: uint32_t 1 秒中断发生 0 秒中断未发生 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t RTC_IntSecondStat(RTC_TypeDef * RTCx) +uint32_t RTC_IntSecondStat(RTC_TypeDef *RTCx) { - return (RTCx->IF & RTC_IF_SEC_Msk) ? 1 : 0; + return (RTCx->IF & RTC_IF_SEC_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -227,9 +233,9 @@ uint32_t RTC_IntSecondStat(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntMinuteEn(RTC_TypeDef * RTCx) -{ - RTCx->IE |= (1 << RTC_IE_MIN_Pos); +void RTC_IntMinuteEn(RTC_TypeDef *RTCx) +{ + RTCx->IE |= (1 << RTC_IE_MIN_Pos); } /****************************************************************************************************************************************** @@ -239,9 +245,9 @@ void RTC_IntMinuteEn(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntMinuteDis(RTC_TypeDef * RTCx) -{ - RTCx->IE &= ~(1 << RTC_IE_MIN_Pos); +void RTC_IntMinuteDis(RTC_TypeDef *RTCx) +{ + RTCx->IE &= ~(1 << RTC_IE_MIN_Pos); } /****************************************************************************************************************************************** @@ -251,9 +257,9 @@ void RTC_IntMinuteDis(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntMinuteClr(RTC_TypeDef * RTCx) -{ - RTCx->IF = (1 << RTC_IF_MIN_Pos); +void RTC_IntMinuteClr(RTC_TypeDef *RTCx) +{ + RTCx->IF = (1 << RTC_IF_MIN_Pos); } /****************************************************************************************************************************************** @@ -263,9 +269,9 @@ void RTC_IntMinuteClr(RTC_TypeDef * RTCx) * 输 出: uint32_t 1 分中断发生 0 分中断未发生 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t RTC_IntMinuteStat(RTC_TypeDef * RTCx) +uint32_t RTC_IntMinuteStat(RTC_TypeDef *RTCx) { - return (RTCx->IF & RTC_IF_MIN_Msk) ? 1 : 0; + return (RTCx->IF & RTC_IF_MIN_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -275,9 +281,9 @@ uint32_t RTC_IntMinuteStat(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntHourEn(RTC_TypeDef * RTCx) -{ - RTCx->IE |= (1 << RTC_IE_HOUR_Pos); +void RTC_IntHourEn(RTC_TypeDef *RTCx) +{ + RTCx->IE |= (1 << RTC_IE_HOUR_Pos); } /****************************************************************************************************************************************** @@ -287,9 +293,9 @@ void RTC_IntHourEn(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntHourDis(RTC_TypeDef * RTCx) -{ - RTCx->IE &= ~(1 << RTC_IE_HOUR_Pos); +void RTC_IntHourDis(RTC_TypeDef *RTCx) +{ + RTCx->IE &= ~(1 << RTC_IE_HOUR_Pos); } /****************************************************************************************************************************************** @@ -299,9 +305,9 @@ void RTC_IntHourDis(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntHourClr(RTC_TypeDef * RTCx) -{ - RTCx->IF = (1 << RTC_IF_HOUR_Pos); +void RTC_IntHourClr(RTC_TypeDef *RTCx) +{ + RTCx->IF = (1 << RTC_IF_HOUR_Pos); } /****************************************************************************************************************************************** @@ -311,9 +317,9 @@ void RTC_IntHourClr(RTC_TypeDef * RTCx) * 输 出: uint32_t 1 时中断发生 0 时中断未发生 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t RTC_IntHourStat(RTC_TypeDef * RTCx) +uint32_t RTC_IntHourStat(RTC_TypeDef *RTCx) { - return (RTCx->IF & RTC_IF_HOUR_Msk) ? 1 : 0; + return (RTCx->IF & RTC_IF_HOUR_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -323,9 +329,9 @@ uint32_t RTC_IntHourStat(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntDateEn(RTC_TypeDef * RTCx) -{ - RTCx->IE |= (1 << RTC_IE_DATE_Pos); +void RTC_IntDateEn(RTC_TypeDef *RTCx) +{ + RTCx->IE |= (1 << RTC_IE_DATE_Pos); } /****************************************************************************************************************************************** @@ -335,9 +341,9 @@ void RTC_IntDateEn(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntDateDis(RTC_TypeDef * RTCx) -{ - RTCx->IE &= ~(1 << RTC_IE_DATE_Pos); +void RTC_IntDateDis(RTC_TypeDef *RTCx) +{ + RTCx->IE &= ~(1 << RTC_IE_DATE_Pos); } /****************************************************************************************************************************************** @@ -347,9 +353,9 @@ void RTC_IntDateDis(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntDateClr(RTC_TypeDef * RTCx) -{ - RTCx->IF = (1 << RTC_IF_DATE_Pos); +void RTC_IntDateClr(RTC_TypeDef *RTCx) +{ + RTCx->IF = (1 << RTC_IF_DATE_Pos); } /****************************************************************************************************************************************** @@ -359,9 +365,9 @@ void RTC_IntDateClr(RTC_TypeDef * RTCx) * 输 出: uint32_t 1 日中断发生 0 日中断未发生 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t RTC_IntDateStat(RTC_TypeDef * RTCx) +uint32_t RTC_IntDateStat(RTC_TypeDef *RTCx) { - return (RTCx->IF & RTC_IF_DATE_Msk) ? 1 : 0; + return (RTCx->IF & RTC_IF_DATE_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -371,9 +377,9 @@ uint32_t RTC_IntDateStat(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntAlarmEn(RTC_TypeDef * RTCx) -{ - RTCx->IE |= (1 << RTC_IE_ALARM_Pos); +void RTC_IntAlarmEn(RTC_TypeDef *RTCx) +{ + RTCx->IE |= (1 << RTC_IE_ALARM_Pos); } /****************************************************************************************************************************************** @@ -383,9 +389,9 @@ void RTC_IntAlarmEn(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntAlarmDis(RTC_TypeDef * RTCx) -{ - RTCx->IE &= ~(1 << RTC_IE_ALARM_Pos); +void RTC_IntAlarmDis(RTC_TypeDef *RTCx) +{ + RTCx->IE &= ~(1 << RTC_IE_ALARM_Pos); } /****************************************************************************************************************************************** @@ -395,9 +401,9 @@ void RTC_IntAlarmDis(RTC_TypeDef * RTCx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void RTC_IntAlarmClr(RTC_TypeDef * RTCx) -{ - RTCx->IF = (1 << RTC_IF_ALARM_Pos); +void RTC_IntAlarmClr(RTC_TypeDef *RTCx) +{ + RTCx->IF = (1 << RTC_IF_ALARM_Pos); } /****************************************************************************************************************************************** @@ -407,7 +413,7 @@ void RTC_IntAlarmClr(RTC_TypeDef * RTCx) * 输 出: uint32_t 1 闹钟中断发生 0 闹钟中断未发生 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t RTC_IntAlarmStat(RTC_TypeDef * RTCx) +uint32_t RTC_IntAlarmStat(RTC_TypeDef *RTCx) { - return (RTCx->IF & RTC_IF_ALARM_Msk) ? 1 : 0; + return (RTCx->IF & RTC_IF_ALARM_Msk) ? 1 : 0; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.h index 13cd0e6785..d534fa4788 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_rtc.h @@ -1,73 +1,73 @@ #ifndef __SWM320_RTC_H__ #define __SWM320_RTC_H__ +#define RTC_SUN 0x01 +#define RTC_MON 0x02 +#define RTC_TUE 0x04 +#define RTC_WED 0x08 +#define RTC_THU 0x10 +#define RTC_FRI 0x20 +#define RTC_SAT 0x40 -#define RTC_SUN 0x01 -#define RTC_MON 0x02 -#define RTC_TUE 0x04 -#define RTC_WED 0x08 -#define RTC_THU 0x10 -#define RTC_FRI 0x20 -#define RTC_SAT 0x40 - - -typedef struct { - uint16_t Year; - uint8_t Month; //取值1--12 - uint8_t Date; //取值1--31 - uint8_t Hour; //取值0--23 - uint8_t Minute; //取值0--59 - uint8_t Second; //取值0--59 - uint8_t SecondIEn; - uint8_t MinuteIEn; +typedef struct +{ + uint16_t Year; + uint8_t Month; //取值1--12 + uint8_t Date; //取值1--31 + uint8_t Hour; //取值0--23 + uint8_t Minute; //取值0--59 + uint8_t Second; //取值0--59 + uint8_t SecondIEn; + uint8_t MinuteIEn; } RTC_InitStructure; -typedef struct { - uint8_t Days; //RTC_SUN、RTC_MON、RTC_TUE、RTC_WED、RTC_THU、RTC_FRI、RTC_SAT及其或运算组合 - uint8_t Hour; - uint8_t Minute; - uint8_t Second; - uint8_t AlarmIEn; +typedef struct +{ + uint8_t Days; //RTC_SUN、RTC_MON、RTC_TUE、RTC_WED、RTC_THU、RTC_FRI、RTC_SAT及其或运算组合 + uint8_t Hour; + uint8_t Minute; + uint8_t Second; + uint8_t AlarmIEn; } RTC_AlarmStructure; -typedef struct { - uint16_t Year; - uint8_t Month; - uint8_t Date; - uint8_t Day; //RTC_SUN、RTC_MON、RTC_TUE、RTC_WED、RTC_THU、RTC_FRI、RTC_SAT - uint8_t Hour; - uint8_t Minute; - uint8_t Second; +typedef struct +{ + uint16_t Year; + uint8_t Month; + uint8_t Date; + uint8_t Day; //RTC_SUN、RTC_MON、RTC_TUE、RTC_WED、RTC_THU、RTC_FRI、RTC_SAT + uint8_t Hour; + uint8_t Minute; + uint8_t Second; } RTC_DateTime; -void RTC_Init(RTC_TypeDef * RTCx, RTC_InitStructure * initStruct); -void RTC_Start(RTC_TypeDef * RTCx); -void RTC_Stop(RTC_TypeDef * RTCx); +void RTC_Init(RTC_TypeDef *RTCx, RTC_InitStructure *initStruct); +void RTC_Start(RTC_TypeDef *RTCx); +void RTC_Stop(RTC_TypeDef *RTCx); -void RTC_GetDateTime(RTC_TypeDef * RTCx, RTC_DateTime * dateTime); +void RTC_GetDateTime(RTC_TypeDef *RTCx, RTC_DateTime *dateTime); -void RTC_AlarmSetup(RTC_TypeDef * RTCx, RTC_AlarmStructure * alarmStruct); +void RTC_AlarmSetup(RTC_TypeDef *RTCx, RTC_AlarmStructure *alarmStruct); - -void RTC_IntSecondEn(RTC_TypeDef * RTCx); -void RTC_IntSecondDis(RTC_TypeDef * RTCx); -void RTC_IntSecondClr(RTC_TypeDef * RTCx); -uint32_t RTC_IntSecondStat(RTC_TypeDef * RTCx); -void RTC_IntMinuteEn(RTC_TypeDef * RTCx); -void RTC_IntMinuteDis(RTC_TypeDef * RTCx); -void RTC_IntMinuteClr(RTC_TypeDef * RTCx); -uint32_t RTC_IntMinuteStat(RTC_TypeDef * RTCx); -void RTC_IntHourEn(RTC_TypeDef * RTCx); -void RTC_IntHourDis(RTC_TypeDef * RTCx); -void RTC_IntHourClr(RTC_TypeDef * RTCx); -uint32_t RTC_IntHourStat(RTC_TypeDef * RTCx); -void RTC_IntDateEn(RTC_TypeDef * RTCx); -void RTC_IntDateDis(RTC_TypeDef * RTCx); -void RTC_IntDateClr(RTC_TypeDef * RTCx); -uint32_t RTC_IntDateStat(RTC_TypeDef * RTCx); -void RTC_IntAlarmEn(RTC_TypeDef * RTCx); -void RTC_IntAlarmDis(RTC_TypeDef * RTCx); -void RTC_IntAlarmClr(RTC_TypeDef * RTCx); -uint32_t RTC_IntAlarmStat(RTC_TypeDef * RTCx); +void RTC_IntSecondEn(RTC_TypeDef *RTCx); +void RTC_IntSecondDis(RTC_TypeDef *RTCx); +void RTC_IntSecondClr(RTC_TypeDef *RTCx); +uint32_t RTC_IntSecondStat(RTC_TypeDef *RTCx); +void RTC_IntMinuteEn(RTC_TypeDef *RTCx); +void RTC_IntMinuteDis(RTC_TypeDef *RTCx); +void RTC_IntMinuteClr(RTC_TypeDef *RTCx); +uint32_t RTC_IntMinuteStat(RTC_TypeDef *RTCx); +void RTC_IntHourEn(RTC_TypeDef *RTCx); +void RTC_IntHourDis(RTC_TypeDef *RTCx); +void RTC_IntHourClr(RTC_TypeDef *RTCx); +uint32_t RTC_IntHourStat(RTC_TypeDef *RTCx); +void RTC_IntDateEn(RTC_TypeDef *RTCx); +void RTC_IntDateDis(RTC_TypeDef *RTCx); +void RTC_IntDateClr(RTC_TypeDef *RTCx); +uint32_t RTC_IntDateStat(RTC_TypeDef *RTCx); +void RTC_IntAlarmEn(RTC_TypeDef *RTCx); +void RTC_IntAlarmDis(RTC_TypeDef *RTCx); +void RTC_IntAlarmClr(RTC_TypeDef *RTCx); +uint32_t RTC_IntAlarmStat(RTC_TypeDef *RTCx); #endif //__SWM320_RTC_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.c index 9175cce387..15d5dac922 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.c @@ -21,7 +21,6 @@ #include "SWM320.h" #include "SWM320_sdio.h" - SD_CardInfo SD_cardInfo; /****************************************************************************************************************************************** @@ -33,98 +32,97 @@ SD_CardInfo SD_cardInfo; ******************************************************************************************************************************************/ uint32_t SDIO_Init(uint32_t freq) { - uint32_t res; - uint32_t resp, resps[4]; - - SYS->CLKDIV &= ~SYS_CLKDIV_SDIO_Msk; - if(SystemCoreClock > 80000000) //SDIO时钟需要小于52MHz - SYS->CLKDIV |= (2 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 4 - else - SYS->CLKDIV |= (1 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 2 - - SYS->CLKEN |= (0x01 << SYS_CLKEN_SDIO_Pos); - - SDIO->CR2 = (1 << SDIO_CR2_RSTALL_Pos); - - SDIO->CR1 = (1 << SDIO_CR1_CDSRC_Pos) | - (0 << SDIO_CR1_8BIT_Pos) | - (0 << SDIO_CR1_4BIT_Pos) | - (1 << SDIO_CR1_PWRON_Pos) | - (7 << SDIO_CR1_VOLT_Pos); - - SDIO->CR2 = (1 << SDIO_CR2_CLKEN_Pos) | - (1 << SDIO_CR2_SDCLKEN_Pos) | - (calcSDCLKDiv(100000) << SDIO_CR2_SDCLKDIV_Pos) | - (0xC << SDIO_CR2_TIMEOUT_Pos); // 2**25 SDIO_CLK - - while((SDIO->CR2 & SDIO_CR2_CLKRDY_Msk) == 0); - - SDIO->IFE = 0xFFFFFFFF; - - - SDIO_SendCmd(SD_CMD_GO_IDLE_STATE, 0x00, SD_RESP_NO, 0); //CMD0: GO_IDLE_STATE - - res = SDIO_SendCmd(SD_CMD_SEND_IF_COND, 0x1AA, SD_RESP_32b, &resp); //CMD8: SEND_IF_COND, 检测工作电压、检测是否支持SD 2.0 - if(res != SD_RES_OK) - return res; - - if(resp == 0x1AA) SD_cardInfo.CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0; - else SD_cardInfo.CardType = SDIO_STD_CAPACITY_SD_CARD_V1_1; - - do //ACMD41: SD_CMD_SD_APP_OP_COND - { - res = SDIO_SendCmd(SD_CMD_APP_CMD, 0x00, SD_RESP_32b, &resp); - if(res != SD_RES_OK) - return res; - - if(resp != 0x120) return SD_RES_ERR; //不是SD卡,可能是MMC卡 - - if(SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0) - SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000|0x40000000, SD_RESP_32b, &resp); - else - SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000|0x00000000, SD_RESP_32b, &resp); - } while(((resp >> 31) & 0x01) == 0); //上电没完成时resp[31] == 0 - - if(((resp >> 30) & 0x01) == 1) SD_cardInfo.CardType = SDIO_HIGH_CAPACITY_SD_CARD; - - - SDIO_SendCmd(SD_CMD_ALL_SEND_CID, 0x00, SD_RESP_128b, resps); //CMD2: SD_CMD_ALL_SEND_CID,获取CID - - parseCID(resps); - - - SDIO_SendCmd(SD_CMD_SET_REL_ADDR, 0x00, SD_RESP_32b, &resp); //CMD3: SD_CMD_SET_REL_ADDR,设置RCA - - SD_cardInfo.RCA = resp >> 16; - - - SDIO_SendCmd(SD_CMD_SEND_CSD, SD_cardInfo.RCA << 16, SD_RESP_128b, resps); //CMD9: SD_CMD_SEND_CSD,获取CSD - - parseCSD(resps); - - if(SD_cardInfo.CardBlockSize < 0x200) return SD_RES_ERR; //本驱动只支持以512字节为单位的读写,所以最大读写单位必须不小于512 - - - SDIO->CR2 &= ~(SDIO_CR2_SDCLKEN_Msk | SDIO_CR2_SDCLKDIV_Msk); - SDIO->CR2 |= (1 << SDIO_CR2_SDCLKEN_Pos) | - (calcSDCLKDiv(freq) << SDIO_CR2_SDCLKDIV_Pos); //初始化完成,SDCLK切换到高速 - - - SDIO_SendCmd(SD_CMD_SEL_DESEL_CARD, SD_cardInfo.RCA << 16, SD_RESP_32b_busy, &resp); //CMD7: 选中卡,从Standy模式进入Transfer模式 - SDIO->IF = SDIO_IF_TRXDONE_Msk; - - SDIO_SendCmd(SD_CMD_APP_CMD, SD_cardInfo.RCA << 16, SD_RESP_32b, &resp); - - SDIO_SendCmd(SD_CMD_APP_SD_SET_BUSWIDTH, SD_BUSWIDTH_4b, SD_RESP_32b, &resp); //切换成4位总线模式 - - SDIO->CR1 |= (1 << SDIO_CR1_4BIT_Pos); - - - SDIO_SendCmd(SD_CMD_SET_BLOCKLEN, 512, SD_RESP_32b, &resp); //固定块大小位512字节 - - SDIO->BLK = 512; - - return SD_RES_OK; + uint32_t res; + uint32_t resp, resps[4]; + + SYS->CLKDIV &= ~SYS_CLKDIV_SDIO_Msk; + if (SystemCoreClock > 80000000) //SDIO时钟需要小于52MHz + SYS->CLKDIV |= (2 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 4 + else + SYS->CLKDIV |= (1 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 2 + + SYS->CLKEN |= (0x01 << SYS_CLKEN_SDIO_Pos); + + SDIO->CR2 = (1 << SDIO_CR2_RSTALL_Pos); + + SDIO->CR1 = (1 << SDIO_CR1_CDSRC_Pos) | + (0 << SDIO_CR1_8BIT_Pos) | + (0 << SDIO_CR1_4BIT_Pos) | + (1 << SDIO_CR1_PWRON_Pos) | + (7 << SDIO_CR1_VOLT_Pos); + + SDIO->CR2 = (1 << SDIO_CR2_CLKEN_Pos) | + (1 << SDIO_CR2_SDCLKEN_Pos) | + (calcSDCLKDiv(100000) << SDIO_CR2_SDCLKDIV_Pos) | + (0xC << SDIO_CR2_TIMEOUT_Pos); // 2**25 SDIO_CLK + + while ((SDIO->CR2 & SDIO_CR2_CLKRDY_Msk) == 0) + ; + + SDIO->IFE = 0xFFFFFFFF; + + SDIO_SendCmd(SD_CMD_GO_IDLE_STATE, 0x00, SD_RESP_NO, 0); //CMD0: GO_IDLE_STATE + + res = SDIO_SendCmd(SD_CMD_SEND_IF_COND, 0x1AA, SD_RESP_32b, &resp); //CMD8: SEND_IF_COND, 检测工作电压、检测是否支持SD 2.0 + if (res != SD_RES_OK) + return res; + + if (resp == 0x1AA) + SD_cardInfo.CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0; + else + SD_cardInfo.CardType = SDIO_STD_CAPACITY_SD_CARD_V1_1; + + do //ACMD41: SD_CMD_SD_APP_OP_COND + { + res = SDIO_SendCmd(SD_CMD_APP_CMD, 0x00, SD_RESP_32b, &resp); + if (res != SD_RES_OK) + return res; + + if (resp != 0x120) + return SD_RES_ERR; //不是SD卡,可能是MMC卡 + + if (SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0) + SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000 | 0x40000000, SD_RESP_32b, &resp); + else + SDIO_SendCmd(SD_CMD_SD_APP_OP_COND, 0x80100000 | 0x00000000, SD_RESP_32b, &resp); + } while (((resp >> 31) & 0x01) == 0); //上电没完成时resp[31] == 0 + + if (((resp >> 30) & 0x01) == 1) + SD_cardInfo.CardType = SDIO_HIGH_CAPACITY_SD_CARD; + + SDIO_SendCmd(SD_CMD_ALL_SEND_CID, 0x00, SD_RESP_128b, resps); //CMD2: SD_CMD_ALL_SEND_CID,获取CID + + parseCID(resps); + + SDIO_SendCmd(SD_CMD_SET_REL_ADDR, 0x00, SD_RESP_32b, &resp); //CMD3: SD_CMD_SET_REL_ADDR,设置RCA + + SD_cardInfo.RCA = resp >> 16; + + SDIO_SendCmd(SD_CMD_SEND_CSD, SD_cardInfo.RCA << 16, SD_RESP_128b, resps); //CMD9: SD_CMD_SEND_CSD,获取CSD + + parseCSD(resps); + + if (SD_cardInfo.CardBlockSize < 0x200) + return SD_RES_ERR; //本驱动只支持以512字节为单位的读写,所以最大读写单位必须不小于512 + + SDIO->CR2 &= ~(SDIO_CR2_SDCLKEN_Msk | SDIO_CR2_SDCLKDIV_Msk); + SDIO->CR2 |= (1 << SDIO_CR2_SDCLKEN_Pos) | + (calcSDCLKDiv(freq) << SDIO_CR2_SDCLKDIV_Pos); //初始化完成,SDCLK切换到高速 + + SDIO_SendCmd(SD_CMD_SEL_DESEL_CARD, SD_cardInfo.RCA << 16, SD_RESP_32b_busy, &resp); //CMD7: 选中卡,从Standy模式进入Transfer模式 + SDIO->IF = SDIO_IF_TRXDONE_Msk; + + SDIO_SendCmd(SD_CMD_APP_CMD, SD_cardInfo.RCA << 16, SD_RESP_32b, &resp); + + SDIO_SendCmd(SD_CMD_APP_SD_SET_BUSWIDTH, SD_BUSWIDTH_4b, SD_RESP_32b, &resp); //切换成4位总线模式 + + SDIO->CR1 |= (1 << SDIO_CR1_4BIT_Pos); + + SDIO_SendCmd(SD_CMD_SET_BLOCKLEN, 512, SD_RESP_32b, &resp); //固定块大小位512字节 + + SDIO->BLK = 512; + + return SD_RES_OK; } /****************************************************************************************************************************************** @@ -137,25 +135,30 @@ uint32_t SDIO_Init(uint32_t freq) ******************************************************************************************************************************************/ uint32_t SDIO_BlockWrite(uint32_t block_addr, uint32_t buff[]) { - uint32_t res, i; - uint32_t addr, resp; - - if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr; - else addr = block_addr * 512; - - res = SDIO_SendCmdWithData(SD_CMD_WRITE_SINGLE_BLOCK, addr, SD_RESP_32b, &resp, 0, 1); - if(res != SD_RES_OK) - return res; - - while((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0) __NOP(); - SDIO->IF = SDIO_IF_BUFWRRDY_Msk; - - for(i = 0; i < 512/4; i++) SDIO->DATA = buff[i]; - - while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP(); - SDIO->IF = SDIO_IF_TRXDONE_Msk; - - return SD_RES_OK; + uint32_t res, i; + uint32_t addr, resp; + + if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) + addr = block_addr; + else + addr = block_addr * 512; + + res = SDIO_SendCmdWithData(SD_CMD_WRITE_SINGLE_BLOCK, addr, SD_RESP_32b, &resp, 0, 1); + if (res != SD_RES_OK) + return res; + + while ((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0) + __NOP(); + SDIO->IF = SDIO_IF_BUFWRRDY_Msk; + + for (i = 0; i < 512 / 4; i++) + SDIO->DATA = buff[i]; + + while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) + __NOP(); + SDIO->IF = SDIO_IF_TRXDONE_Msk; + + return SD_RES_OK; } /****************************************************************************************************************************************** @@ -169,28 +172,33 @@ uint32_t SDIO_BlockWrite(uint32_t block_addr, uint32_t buff[]) ******************************************************************************************************************************************/ uint32_t SDIO_MultiBlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]) { - uint32_t res, i, j; - uint32_t addr, resp; - - if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr; - else addr = block_addr * 512; - - res = SDIO_SendCmdWithData(SD_CMD_WRITE_MULT_BLOCK, addr, SD_RESP_32b, &resp, 0, block_cnt); - if(res != SD_RES_OK) - return res; - - for(i = 0; i < block_cnt; i++) - { - while((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0) __NOP(); - SDIO->IF = SDIO_IF_BUFWRRDY_Msk; - - for(j = 0; j < 512/4; j++) SDIO->DATA = buff[i*(512/4) + j]; - } - - while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP(); - SDIO->IF = SDIO_IF_TRXDONE_Msk; - - return SD_RES_OK; + uint32_t res, i, j; + uint32_t addr, resp; + + if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) + addr = block_addr; + else + addr = block_addr * 512; + + res = SDIO_SendCmdWithData(SD_CMD_WRITE_MULT_BLOCK, addr, SD_RESP_32b, &resp, 0, block_cnt); + if (res != SD_RES_OK) + return res; + + for (i = 0; i < block_cnt; i++) + { + while ((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0) + __NOP(); + SDIO->IF = SDIO_IF_BUFWRRDY_Msk; + + for (j = 0; j < 512 / 4; j++) + SDIO->DATA = buff[i * (512 / 4) + j]; + } + + while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) + __NOP(); + SDIO->IF = SDIO_IF_TRXDONE_Msk; + + return SD_RES_OK; } /****************************************************************************************************************************************** @@ -204,22 +212,25 @@ uint32_t SDIO_MultiBlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t ******************************************************************************************************************************************/ uint32_t SDIO_DMABlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]) { - uint32_t res; - uint32_t addr, resp; - - if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr; - else addr = block_addr * 512; - - SDIO->DMA_MEM_ADDR = (uint32_t) buff; - - res = SDIO_SendCmdWithDataByDMA(SD_CMD_WRITE_MULT_BLOCK, addr, SD_RESP_32b, &resp, 0, block_cnt); - if(res != SD_RES_OK) - return res; - - while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP(); - SDIO->IF = SDIO_IF_TRXDONE_Msk; - - return SD_RES_OK; + uint32_t res; + uint32_t addr, resp; + + if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) + addr = block_addr; + else + addr = block_addr * 512; + + SDIO->DMA_MEM_ADDR = (uint32_t)buff; + + res = SDIO_SendCmdWithDataByDMA(SD_CMD_WRITE_MULT_BLOCK, addr, SD_RESP_32b, &resp, 0, block_cnt); + if (res != SD_RES_OK) + return res; + + while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) + __NOP(); + SDIO->IF = SDIO_IF_TRXDONE_Msk; + + return SD_RES_OK; } /****************************************************************************************************************************************** @@ -232,25 +243,30 @@ uint32_t SDIO_DMABlockWrite(uint32_t block_addr, uint16_t block_cnt, uint32_t bu ******************************************************************************************************************************************/ uint32_t SDIO_BlockRead(uint32_t block_addr, uint32_t buff[]) { - uint32_t res, i; + uint32_t res, i; uint32_t addr, resp; - - if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr; - else addr = block_addr * 512; - - res = SDIO_SendCmdWithData(SD_CMD_READ_SINGLE_BLOCK, addr, SD_RESP_32b, &resp, 1, 1); - if(res != SD_RES_OK) - return res; - - while((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0) __NOP(); - SDIO->IF = SDIO_IF_BUFRDRDY_Msk; - - for(i = 0; i < 512/4; i++) buff[i] = SDIO->DATA; - - while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP(); - SDIO->IF = SDIO_IF_TRXDONE_Msk; - - return SD_RES_OK; + + if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) + addr = block_addr; + else + addr = block_addr * 512; + + res = SDIO_SendCmdWithData(SD_CMD_READ_SINGLE_BLOCK, addr, SD_RESP_32b, &resp, 1, 1); + if (res != SD_RES_OK) + return res; + + while ((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0) + __NOP(); + SDIO->IF = SDIO_IF_BUFRDRDY_Msk; + + for (i = 0; i < 512 / 4; i++) + buff[i] = SDIO->DATA; + + while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) + __NOP(); + SDIO->IF = SDIO_IF_TRXDONE_Msk; + + return SD_RES_OK; } /****************************************************************************************************************************************** @@ -264,28 +280,33 @@ uint32_t SDIO_BlockRead(uint32_t block_addr, uint32_t buff[]) ******************************************************************************************************************************************/ uint32_t SDIO_MultiBlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]) { - uint32_t res, i, j; + uint32_t res, i, j; uint32_t addr, resp; - - if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr; - else addr = block_addr * 512; - - res = SDIO_SendCmdWithData(SD_CMD_READ_MULT_BLOCK, addr, SD_RESP_32b, &resp, 1, block_cnt); - if(res != SD_RES_OK) - return res; - - for(i = 0; i < block_cnt; i++) - { - while((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0) __NOP(); - SDIO->IF = SDIO_IF_BUFRDRDY_Msk; - - for(j = 0; j < 512/4; j++) buff[i*(512/4) + j] = SDIO->DATA; - } - - while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP(); - SDIO->IF = SDIO_IF_TRXDONE_Msk; - - return SD_RES_OK; + + if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) + addr = block_addr; + else + addr = block_addr * 512; + + res = SDIO_SendCmdWithData(SD_CMD_READ_MULT_BLOCK, addr, SD_RESP_32b, &resp, 1, block_cnt); + if (res != SD_RES_OK) + return res; + + for (i = 0; i < block_cnt; i++) + { + while ((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0) + __NOP(); + SDIO->IF = SDIO_IF_BUFRDRDY_Msk; + + for (j = 0; j < 512 / 4; j++) + buff[i * (512 / 4) + j] = SDIO->DATA; + } + + while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) + __NOP(); + SDIO->IF = SDIO_IF_TRXDONE_Msk; + + return SD_RES_OK; } /****************************************************************************************************************************************** @@ -299,22 +320,25 @@ uint32_t SDIO_MultiBlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t b ******************************************************************************************************************************************/ uint32_t SDIO_DMABlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buff[]) { - uint32_t res; + uint32_t res; uint32_t addr, resp; - - if(SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) addr = block_addr; - else addr = block_addr * 512; - - SDIO->DMA_MEM_ADDR = (uint32_t)buff; - - res = SDIO_SendCmdWithDataByDMA(SD_CMD_READ_MULT_BLOCK, addr, SD_RESP_32b, &resp, 1, block_cnt); - if(res != SD_RES_OK) - return res; - - while((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) __NOP(); - SDIO->IF = SDIO_IF_TRXDONE_Msk; - - return SD_RES_OK; + + if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) + addr = block_addr; + else + addr = block_addr * 512; + + SDIO->DMA_MEM_ADDR = (uint32_t)buff; + + res = SDIO_SendCmdWithDataByDMA(SD_CMD_READ_MULT_BLOCK, addr, SD_RESP_32b, &resp, 1, block_cnt); + if (res != SD_RES_OK) + return res; + + while ((SDIO->IF & SDIO_IF_TRXDONE_Msk) == 0) + __NOP(); + SDIO->IF = SDIO_IF_TRXDONE_Msk; + + return SD_RES_OK; } /****************************************************************************************************************************************** @@ -332,263 +356,271 @@ uint32_t SDIO_DMABlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buf * 注意事项: 无 ******************************************************************************************************************************************/ uint32_t _SDIO_SendCmd(uint32_t cmd, uint32_t arg, uint32_t resp_type, uint32_t *resp_data, uint32_t have_data, uint32_t data_read, uint16_t block_cnt, uint32_t use_dma) -{ - SDIO->BLK &= ~SDIO_BLK_COUNT_Msk; - SDIO->BLK |= (block_cnt << SDIO_BLK_COUNT_Pos); - - SDIO->ARG = arg; - SDIO->CMD = (cmd << SDIO_CMD_CMDINDX_Pos) | - (0 << SDIO_CMD_CMDTYPE_Pos) | - (0 << SDIO_CMD_IDXCHECK_Pos) | - (0 << SDIO_CMD_CRCCHECK_Pos) | - (resp_type << SDIO_CMD_RESPTYPE_Pos) | - (have_data << SDIO_CMD_HAVEDATA_Pos) | - (data_read << SDIO_CMD_DIRREAD_Pos) | - ((block_cnt > 1) << SDIO_CMD_MULTBLK_Pos) | - ((block_cnt > 1) << SDIO_CMD_BLKCNTEN_Pos) | - ((block_cnt > 1) << SDIO_CMD_AUTOCMD12_Pos) | - (use_dma << SDIO_CMD_DMAEN_Pos); - - while((SDIO->IF & SDIO_IF_CMDDONE_Msk) == 0) - { - if(SDIO->IF & SDIO_IF_CMDTIMEOUT_Msk) - { - SDIO->IF = SDIO_IF_CMDTIMEOUT_Msk; - - return SD_RES_TIMEOUT; - } - else if(SDIO->IF & SDIO_IF_ERROR_Msk) - { - SDIO->IF = 0xFFFFFFFF; - - return SD_RES_ERR; - } - } - SDIO->IF = SDIO_IF_CMDDONE_Msk; - - if(resp_type == SD_RESP_32b) - { - resp_data[0] = SDIO->RESP[0]; - } - else if(resp_type == SD_RESP_128b) - { - //寄存器中将CID/CSD[127-8]依次存放在了RESP3-0[119-0],最低位的CRC被丢掉 - //读出数据时调整了顺序,将CID/CSD[127-8]存放在resp_data0-3[127-8],最低8位填充0x00 - resp_data[0] = (SDIO->RESP[3] << 8) + ((SDIO->RESP[2] >> 24) & 0xFF); - resp_data[1] = (SDIO->RESP[2] << 8) + ((SDIO->RESP[1] >> 24) & 0xFF); - resp_data[2] = (SDIO->RESP[1] << 8) + ((SDIO->RESP[0] >> 24) & 0xFF); - resp_data[3] = (SDIO->RESP[0] << 8) + 0x00; - } - - return SD_RES_OK; -} +{ + SDIO->BLK &= ~SDIO_BLK_COUNT_Msk; + SDIO->BLK |= (block_cnt << SDIO_BLK_COUNT_Pos); + SDIO->ARG = arg; + SDIO->CMD = (cmd << SDIO_CMD_CMDINDX_Pos) | + (0 << SDIO_CMD_CMDTYPE_Pos) | + (0 << SDIO_CMD_IDXCHECK_Pos) | + (0 << SDIO_CMD_CRCCHECK_Pos) | + (resp_type << SDIO_CMD_RESPTYPE_Pos) | + (have_data << SDIO_CMD_HAVEDATA_Pos) | + (data_read << SDIO_CMD_DIRREAD_Pos) | + ((block_cnt > 1) << SDIO_CMD_MULTBLK_Pos) | + ((block_cnt > 1) << SDIO_CMD_BLKCNTEN_Pos) | + ((block_cnt > 1) << SDIO_CMD_AUTOCMD12_Pos) | + (use_dma << SDIO_CMD_DMAEN_Pos); + + while ((SDIO->IF & SDIO_IF_CMDDONE_Msk) == 0) + { + if (SDIO->IF & SDIO_IF_CMDTIMEOUT_Msk) + { + SDIO->IF = SDIO_IF_CMDTIMEOUT_Msk; + + return SD_RES_TIMEOUT; + } + else if (SDIO->IF & SDIO_IF_ERROR_Msk) + { + SDIO->IF = 0xFFFFFFFF; + + return SD_RES_ERR; + } + } + SDIO->IF = SDIO_IF_CMDDONE_Msk; + + if (resp_type == SD_RESP_32b) + { + resp_data[0] = SDIO->RESP[0]; + } + else if (resp_type == SD_RESP_128b) + { + //寄存器中将CID/CSD[127-8]依次存放在了RESP3-0[119-0],最低位的CRC被丢掉 + //读出数据时调整了顺序,将CID/CSD[127-8]存放在resp_data0-3[127-8],最低8位填充0x00 + resp_data[0] = (SDIO->RESP[3] << 8) + ((SDIO->RESP[2] >> 24) & 0xFF); + resp_data[1] = (SDIO->RESP[2] << 8) + ((SDIO->RESP[1] >> 24) & 0xFF); + resp_data[2] = (SDIO->RESP[1] << 8) + ((SDIO->RESP[0] >> 24) & 0xFF); + resp_data[3] = (SDIO->RESP[0] << 8) + 0x00; + } + + return SD_RES_OK; +} void parseCID(uint32_t CID_Tab[4]) { - uint8_t tmp = 0; - - /*!< Byte 0 */ - tmp = (uint8_t)((CID_Tab[0] & 0xFF000000) >> 24); - SD_cardInfo.SD_cid.ManufacturerID = tmp; - - /*!< Byte 1 */ - tmp = (uint8_t)((CID_Tab[0] & 0x00FF0000) >> 16); - SD_cardInfo.SD_cid.OEM_AppliID = tmp << 8; - - /*!< Byte 2 */ - tmp = (uint8_t)((CID_Tab[0] & 0x000000FF00) >> 8); - SD_cardInfo.SD_cid.OEM_AppliID |= tmp; - - /*!< Byte 3 */ - tmp = (uint8_t)(CID_Tab[0] & 0x000000FF); - SD_cardInfo.SD_cid.ProdName1 = tmp << 24; - - /*!< Byte 4 */ - tmp = (uint8_t)((CID_Tab[1] & 0xFF000000) >> 24); - SD_cardInfo.SD_cid.ProdName1 |= tmp << 16; - - /*!< Byte 5 */ - tmp = (uint8_t)((CID_Tab[1] & 0x00FF0000) >> 16); - SD_cardInfo.SD_cid.ProdName1 |= tmp << 8; - - /*!< Byte 6 */ - tmp = (uint8_t)((CID_Tab[1] & 0x0000FF00) >> 8); - SD_cardInfo.SD_cid.ProdName1 |= tmp; - - /*!< Byte 7 */ - tmp = (uint8_t)(CID_Tab[1] & 0x000000FF); - SD_cardInfo.SD_cid.ProdName2 = tmp; - - /*!< Byte 8 */ - tmp = (uint8_t)((CID_Tab[2] & 0xFF000000) >> 24); - SD_cardInfo.SD_cid.ProdRev = tmp; - - /*!< Byte 9 */ - tmp = (uint8_t)((CID_Tab[2] & 0x00FF0000) >> 16); - SD_cardInfo.SD_cid.ProdSN = tmp << 24; - - /*!< Byte 10 */ - tmp = (uint8_t)((CID_Tab[2] & 0x0000FF00) >> 8); - SD_cardInfo.SD_cid.ProdSN |= tmp << 16; - - /*!< Byte 11 */ - tmp = (uint8_t)(CID_Tab[2] & 0x000000FF); - SD_cardInfo.SD_cid.ProdSN |= tmp << 8; - - /*!< Byte 12 */ - tmp = (uint8_t)((CID_Tab[3] & 0xFF000000) >> 24); - SD_cardInfo.SD_cid.ProdSN |= tmp; - - /*!< Byte 13 */ - tmp = (uint8_t)((CID_Tab[3] & 0x00FF0000) >> 16); - SD_cardInfo.SD_cid.Reserved1 |= (tmp & 0xF0) >> 4; - SD_cardInfo.SD_cid.ManufactDate = (tmp & 0x0F) << 8; - - /*!< Byte 14 */ - tmp = (uint8_t)((CID_Tab[3] & 0x0000FF00) >> 8); - SD_cardInfo.SD_cid.ManufactDate |= tmp; + uint8_t tmp = 0; + + /*!< Byte 0 */ + tmp = (uint8_t)((CID_Tab[0] & 0xFF000000) >> 24); + SD_cardInfo.SD_cid.ManufacturerID = tmp; + + /*!< Byte 1 */ + tmp = (uint8_t)((CID_Tab[0] & 0x00FF0000) >> 16); + SD_cardInfo.SD_cid.OEM_AppliID = tmp << 8; + + /*!< Byte 2 */ + tmp = (uint8_t)((CID_Tab[0] & 0x000000FF00) >> 8); + SD_cardInfo.SD_cid.OEM_AppliID |= tmp; + + /*!< Byte 3 */ + tmp = (uint8_t)(CID_Tab[0] & 0x000000FF); + SD_cardInfo.SD_cid.ProdName1 = tmp << 24; + + /*!< Byte 4 */ + tmp = (uint8_t)((CID_Tab[1] & 0xFF000000) >> 24); + SD_cardInfo.SD_cid.ProdName1 |= tmp << 16; + + /*!< Byte 5 */ + tmp = (uint8_t)((CID_Tab[1] & 0x00FF0000) >> 16); + SD_cardInfo.SD_cid.ProdName1 |= tmp << 8; + + /*!< Byte 6 */ + tmp = (uint8_t)((CID_Tab[1] & 0x0000FF00) >> 8); + SD_cardInfo.SD_cid.ProdName1 |= tmp; + + /*!< Byte 7 */ + tmp = (uint8_t)(CID_Tab[1] & 0x000000FF); + SD_cardInfo.SD_cid.ProdName2 = tmp; + + /*!< Byte 8 */ + tmp = (uint8_t)((CID_Tab[2] & 0xFF000000) >> 24); + SD_cardInfo.SD_cid.ProdRev = tmp; + + /*!< Byte 9 */ + tmp = (uint8_t)((CID_Tab[2] & 0x00FF0000) >> 16); + SD_cardInfo.SD_cid.ProdSN = tmp << 24; + + /*!< Byte 10 */ + tmp = (uint8_t)((CID_Tab[2] & 0x0000FF00) >> 8); + SD_cardInfo.SD_cid.ProdSN |= tmp << 16; + + /*!< Byte 11 */ + tmp = (uint8_t)(CID_Tab[2] & 0x000000FF); + SD_cardInfo.SD_cid.ProdSN |= tmp << 8; + + /*!< Byte 12 */ + tmp = (uint8_t)((CID_Tab[3] & 0xFF000000) >> 24); + SD_cardInfo.SD_cid.ProdSN |= tmp; + + /*!< Byte 13 */ + tmp = (uint8_t)((CID_Tab[3] & 0x00FF0000) >> 16); + SD_cardInfo.SD_cid.Reserved1 |= (tmp & 0xF0) >> 4; + SD_cardInfo.SD_cid.ManufactDate = (tmp & 0x0F) << 8; + + /*!< Byte 14 */ + tmp = (uint8_t)((CID_Tab[3] & 0x0000FF00) >> 8); + SD_cardInfo.SD_cid.ManufactDate |= tmp; } void parseCSD(uint32_t CSD_Tab[4]) { - uint8_t tmp = 0; - - /*!< Byte 0 */ - tmp = (uint8_t)((CSD_Tab[0] & 0xFF000000) >> 24); - SD_cardInfo.SD_csd.CSDStruct = (tmp & 0xC0) >> 6; - SD_cardInfo.SD_csd.SysSpecVersion = (tmp & 0x3C) >> 2; - SD_cardInfo.SD_csd.Reserved1 = tmp & 0x03; - - /*!< Byte 1 */ - tmp = (uint8_t)((CSD_Tab[0] & 0x00FF0000) >> 16); - SD_cardInfo.SD_csd.TAAC = tmp; - - /*!< Byte 2 */ - tmp = (uint8_t)((CSD_Tab[0] & 0x0000FF00) >> 8); - SD_cardInfo.SD_csd.NSAC = tmp; - - /*!< Byte 3 */ - tmp = (uint8_t)(CSD_Tab[0] & 0x000000FF); - SD_cardInfo.SD_csd.MaxBusClkFrec = tmp; - - /*!< Byte 4 */ - tmp = (uint8_t)((CSD_Tab[1] & 0xFF000000) >> 24); - SD_cardInfo.SD_csd.CardComdClasses = tmp << 4; - - /*!< Byte 5 */ - tmp = (uint8_t)((CSD_Tab[1] & 0x00FF0000) >> 16); - SD_cardInfo.SD_csd.CardComdClasses |= (tmp & 0xF0) >> 4; - SD_cardInfo.SD_csd.RdBlockLen = tmp & 0x0F; - - /*!< Byte 6 */ - tmp = (uint8_t)((CSD_Tab[1] & 0x0000FF00) >> 8); - SD_cardInfo.SD_csd.PartBlockRead = (tmp & 0x80) >> 7; - SD_cardInfo.SD_csd.WrBlockMisalign = (tmp & 0x40) >> 6; - SD_cardInfo.SD_csd.RdBlockMisalign = (tmp & 0x20) >> 5; - SD_cardInfo.SD_csd.DSRImpl = (tmp & 0x10) >> 4; - SD_cardInfo.SD_csd.Reserved2 = 0; /*!< Reserved */ - - if ((SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V1_1) || - (SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0)) - { - SD_cardInfo.SD_csd.DeviceSize = (tmp & 0x03) << 10; - - /*!< Byte 7 */ - tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF); - SD_cardInfo.SD_csd.DeviceSize |= (tmp) << 2; - - /*!< Byte 8 */ - tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24); - SD_cardInfo.SD_csd.DeviceSize |= (tmp & 0xC0) >> 6; - - SD_cardInfo.SD_csd.MaxRdCurrentVDDMin = (tmp & 0x38) >> 3; - SD_cardInfo.SD_csd.MaxRdCurrentVDDMax = (tmp & 0x07); - - /*!< Byte 9 */ - tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16); - SD_cardInfo.SD_csd.MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5; - SD_cardInfo.SD_csd.MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2; - SD_cardInfo.SD_csd.DeviceSizeMul = (tmp & 0x03) << 1; - /*!< Byte 10 */ - tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8); - SD_cardInfo.SD_csd.DeviceSizeMul |= (tmp & 0x80) >> 7; - - SD_cardInfo.CardCapacity = (SD_cardInfo.SD_csd.DeviceSize + 1) ; - SD_cardInfo.CardCapacity *= (1 << (SD_cardInfo.SD_csd.DeviceSizeMul + 2)); - SD_cardInfo.CardBlockSize = 1 << (SD_cardInfo.SD_csd.RdBlockLen); - SD_cardInfo.CardCapacity *= SD_cardInfo.CardBlockSize; - } - else if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) - { - /*!< Byte 7 */ - tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF); - SD_cardInfo.SD_csd.DeviceSize = (tmp & 0x3F) << 16; - - /*!< Byte 8 */ - tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24); - - SD_cardInfo.SD_csd.DeviceSize |= (tmp << 8); - - /*!< Byte 9 */ - tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16); - - SD_cardInfo.SD_csd.DeviceSize |= (tmp); - - /*!< Byte 10 */ - tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8); - - SD_cardInfo.CardCapacity = (uint64_t)(SD_cardInfo.SD_csd.DeviceSize + 1) * 512 * 1024; - SD_cardInfo.CardBlockSize = 512; - } - - SD_cardInfo.SD_csd.EraseGrSize = (tmp & 0x40) >> 6; - SD_cardInfo.SD_csd.EraseGrMul = (tmp & 0x3F) << 1; - - /*!< Byte 11 */ - tmp = (uint8_t)(CSD_Tab[2] & 0x000000FF); - SD_cardInfo.SD_csd.EraseGrMul |= (tmp & 0x80) >> 7; - SD_cardInfo.SD_csd.WrProtectGrSize = (tmp & 0x7F); - - /*!< Byte 12 */ - tmp = (uint8_t)((CSD_Tab[3] & 0xFF000000) >> 24); - SD_cardInfo.SD_csd.WrProtectGrEnable = (tmp & 0x80) >> 7; - SD_cardInfo.SD_csd.ManDeflECC = (tmp & 0x60) >> 5; - SD_cardInfo.SD_csd.WrSpeedFact = (tmp & 0x1C) >> 2; - SD_cardInfo.SD_csd.MaxWrBlockLen = (tmp & 0x03) << 2; - - /*!< Byte 13 */ - tmp = (uint8_t)((CSD_Tab[3] & 0x00FF0000) >> 16); - SD_cardInfo.SD_csd.MaxWrBlockLen |= (tmp & 0xC0) >> 6; - SD_cardInfo.SD_csd.WriteBlockPaPartial = (tmp & 0x20) >> 5; - SD_cardInfo.SD_csd.Reserved3 = 0; - SD_cardInfo.SD_csd.ContentProtectAppli = (tmp & 0x01); - - /*!< Byte 14 */ - tmp = (uint8_t)((CSD_Tab[3] & 0x0000FF00) >> 8); - SD_cardInfo.SD_csd.FileFormatGrouop = (tmp & 0x80) >> 7; - SD_cardInfo.SD_csd.CopyFlag = (tmp & 0x40) >> 6; - SD_cardInfo.SD_csd.PermWrProtect = (tmp & 0x20) >> 5; - SD_cardInfo.SD_csd.TempWrProtect = (tmp & 0x10) >> 4; - SD_cardInfo.SD_csd.FileFormat = (tmp & 0x0C) >> 2; - SD_cardInfo.SD_csd.ECC = (tmp & 0x03); + uint8_t tmp = 0; + + /*!< Byte 0 */ + tmp = (uint8_t)((CSD_Tab[0] & 0xFF000000) >> 24); + SD_cardInfo.SD_csd.CSDStruct = (tmp & 0xC0) >> 6; + SD_cardInfo.SD_csd.SysSpecVersion = (tmp & 0x3C) >> 2; + SD_cardInfo.SD_csd.Reserved1 = tmp & 0x03; + + /*!< Byte 1 */ + tmp = (uint8_t)((CSD_Tab[0] & 0x00FF0000) >> 16); + SD_cardInfo.SD_csd.TAAC = tmp; + + /*!< Byte 2 */ + tmp = (uint8_t)((CSD_Tab[0] & 0x0000FF00) >> 8); + SD_cardInfo.SD_csd.NSAC = tmp; + + /*!< Byte 3 */ + tmp = (uint8_t)(CSD_Tab[0] & 0x000000FF); + SD_cardInfo.SD_csd.MaxBusClkFrec = tmp; + + /*!< Byte 4 */ + tmp = (uint8_t)((CSD_Tab[1] & 0xFF000000) >> 24); + SD_cardInfo.SD_csd.CardComdClasses = tmp << 4; + + /*!< Byte 5 */ + tmp = (uint8_t)((CSD_Tab[1] & 0x00FF0000) >> 16); + SD_cardInfo.SD_csd.CardComdClasses |= (tmp & 0xF0) >> 4; + SD_cardInfo.SD_csd.RdBlockLen = tmp & 0x0F; + + /*!< Byte 6 */ + tmp = (uint8_t)((CSD_Tab[1] & 0x0000FF00) >> 8); + SD_cardInfo.SD_csd.PartBlockRead = (tmp & 0x80) >> 7; + SD_cardInfo.SD_csd.WrBlockMisalign = (tmp & 0x40) >> 6; + SD_cardInfo.SD_csd.RdBlockMisalign = (tmp & 0x20) >> 5; + SD_cardInfo.SD_csd.DSRImpl = (tmp & 0x10) >> 4; + SD_cardInfo.SD_csd.Reserved2 = 0; /*!< Reserved */ + + if ((SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V1_1) || + (SD_cardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0)) + { + SD_cardInfo.SD_csd.DeviceSize = (tmp & 0x03) << 10; + + /*!< Byte 7 */ + tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF); + SD_cardInfo.SD_csd.DeviceSize |= (tmp) << 2; + + /*!< Byte 8 */ + tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24); + SD_cardInfo.SD_csd.DeviceSize |= (tmp & 0xC0) >> 6; + + SD_cardInfo.SD_csd.MaxRdCurrentVDDMin = (tmp & 0x38) >> 3; + SD_cardInfo.SD_csd.MaxRdCurrentVDDMax = (tmp & 0x07); + + /*!< Byte 9 */ + tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16); + SD_cardInfo.SD_csd.MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5; + SD_cardInfo.SD_csd.MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2; + SD_cardInfo.SD_csd.DeviceSizeMul = (tmp & 0x03) << 1; + /*!< Byte 10 */ + tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8); + SD_cardInfo.SD_csd.DeviceSizeMul |= (tmp & 0x80) >> 7; + + SD_cardInfo.CardCapacity = (SD_cardInfo.SD_csd.DeviceSize + 1); + SD_cardInfo.CardCapacity *= (1 << (SD_cardInfo.SD_csd.DeviceSizeMul + 2)); + SD_cardInfo.CardBlockSize = 1 << (SD_cardInfo.SD_csd.RdBlockLen); + SD_cardInfo.CardCapacity *= SD_cardInfo.CardBlockSize; + } + else if (SD_cardInfo.CardType == SDIO_HIGH_CAPACITY_SD_CARD) + { + /*!< Byte 7 */ + tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF); + SD_cardInfo.SD_csd.DeviceSize = (tmp & 0x3F) << 16; + + /*!< Byte 8 */ + tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24); + + SD_cardInfo.SD_csd.DeviceSize |= (tmp << 8); + + /*!< Byte 9 */ + tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16); + + SD_cardInfo.SD_csd.DeviceSize |= (tmp); + + /*!< Byte 10 */ + tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8); + + SD_cardInfo.CardCapacity = (uint64_t)(SD_cardInfo.SD_csd.DeviceSize + 1) * 512 * 1024; + SD_cardInfo.CardBlockSize = 512; + } + + SD_cardInfo.SD_csd.EraseGrSize = (tmp & 0x40) >> 6; + SD_cardInfo.SD_csd.EraseGrMul = (tmp & 0x3F) << 1; + + /*!< Byte 11 */ + tmp = (uint8_t)(CSD_Tab[2] & 0x000000FF); + SD_cardInfo.SD_csd.EraseGrMul |= (tmp & 0x80) >> 7; + SD_cardInfo.SD_csd.WrProtectGrSize = (tmp & 0x7F); + + /*!< Byte 12 */ + tmp = (uint8_t)((CSD_Tab[3] & 0xFF000000) >> 24); + SD_cardInfo.SD_csd.WrProtectGrEnable = (tmp & 0x80) >> 7; + SD_cardInfo.SD_csd.ManDeflECC = (tmp & 0x60) >> 5; + SD_cardInfo.SD_csd.WrSpeedFact = (tmp & 0x1C) >> 2; + SD_cardInfo.SD_csd.MaxWrBlockLen = (tmp & 0x03) << 2; + + /*!< Byte 13 */ + tmp = (uint8_t)((CSD_Tab[3] & 0x00FF0000) >> 16); + SD_cardInfo.SD_csd.MaxWrBlockLen |= (tmp & 0xC0) >> 6; + SD_cardInfo.SD_csd.WriteBlockPaPartial = (tmp & 0x20) >> 5; + SD_cardInfo.SD_csd.Reserved3 = 0; + SD_cardInfo.SD_csd.ContentProtectAppli = (tmp & 0x01); + + /*!< Byte 14 */ + tmp = (uint8_t)((CSD_Tab[3] & 0x0000FF00) >> 8); + SD_cardInfo.SD_csd.FileFormatGrouop = (tmp & 0x80) >> 7; + SD_cardInfo.SD_csd.CopyFlag = (tmp & 0x40) >> 6; + SD_cardInfo.SD_csd.PermWrProtect = (tmp & 0x20) >> 5; + SD_cardInfo.SD_csd.TempWrProtect = (tmp & 0x10) >> 4; + SD_cardInfo.SD_csd.FileFormat = (tmp & 0x0C) >> 2; + SD_cardInfo.SD_csd.ECC = (tmp & 0x03); } uint32_t calcSDCLKDiv(uint32_t freq) { - uint32_t prediv = ((SYS->CLKDIV & SYS_CLKDIV_SDIO_Msk) >> SYS_CLKDIV_SDIO_Pos); - uint32_t clkdiv = (SystemCoreClock / (1 << prediv)) / freq; - uint32_t regdiv = 0; - - if(clkdiv > 128) regdiv = 0x80; - else if(clkdiv > 64) regdiv = 0x40; - else if(clkdiv > 32) regdiv = 0x20; - else if(clkdiv > 16) regdiv = 0x10; - else if(clkdiv > 8) regdiv = 0x08; - else if(clkdiv > 4) regdiv = 0x04; - else if(clkdiv > 2) regdiv = 0x02; - else if(clkdiv > 1) regdiv = 0x01; - else regdiv = 0x00; - - return regdiv; + uint32_t prediv = ((SYS->CLKDIV & SYS_CLKDIV_SDIO_Msk) >> SYS_CLKDIV_SDIO_Pos); + uint32_t clkdiv = (SystemCoreClock / (1 << prediv)) / freq; + uint32_t regdiv = 0; + + if (clkdiv > 128) + regdiv = 0x80; + else if (clkdiv > 64) + regdiv = 0x40; + else if (clkdiv > 32) + regdiv = 0x20; + else if (clkdiv > 16) + regdiv = 0x10; + else if (clkdiv > 8) + regdiv = 0x08; + else if (clkdiv > 4) + regdiv = 0x04; + else if (clkdiv > 2) + regdiv = 0x02; + else if (clkdiv > 1) + regdiv = 0x01; + else + regdiv = 0x00; + + return regdiv; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.h index 52552eed99..d9834291ac 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdio.h @@ -1,126 +1,120 @@ #ifndef __SWM320_SDIO_H__ #define __SWM320_SDIO_H__ - -#define SD_CMD_GO_IDLE_STATE ((uint8_t)0) -#define SD_CMD_SEND_OP_COND ((uint8_t)1) -#define SD_CMD_ALL_SEND_CID ((uint8_t)2) -#define SD_CMD_SET_REL_ADDR ((uint8_t)3) -#define SD_CMD_SET_DSR ((uint8_t)4) -#define SD_CMD_HS_SWITCH ((uint8_t)6) -#define SD_CMD_SEL_DESEL_CARD ((uint8_t)7) -#define SD_CMD_SEND_IF_COND ((uint8_t)8) -#define SD_CMD_SEND_CSD ((uint8_t)9) -#define SD_CMD_SEND_CID ((uint8_t)10) -#define SD_CMD_STOP_TRANSMISSION ((uint8_t)12) -#define SD_CMD_SEND_STATUS ((uint8_t)13) -#define SD_CMD_SET_BLOCKLEN ((uint8_t)16) -#define SD_CMD_READ_SINGLE_BLOCK ((uint8_t)17) -#define SD_CMD_READ_MULT_BLOCK ((uint8_t)18) -#define SD_CMD_WRITE_SINGLE_BLOCK ((uint8_t)24) -#define SD_CMD_WRITE_MULT_BLOCK ((uint8_t)25) -#define SD_CMD_PROG_CID ((uint8_t)26) -#define SD_CMD_PROG_CSD ((uint8_t)27) -#define SD_CMD_APP_CMD ((uint8_t)55) +#define SD_CMD_GO_IDLE_STATE ((uint8_t)0) +#define SD_CMD_SEND_OP_COND ((uint8_t)1) +#define SD_CMD_ALL_SEND_CID ((uint8_t)2) +#define SD_CMD_SET_REL_ADDR ((uint8_t)3) +#define SD_CMD_SET_DSR ((uint8_t)4) +#define SD_CMD_HS_SWITCH ((uint8_t)6) +#define SD_CMD_SEL_DESEL_CARD ((uint8_t)7) +#define SD_CMD_SEND_IF_COND ((uint8_t)8) +#define SD_CMD_SEND_CSD ((uint8_t)9) +#define SD_CMD_SEND_CID ((uint8_t)10) +#define SD_CMD_STOP_TRANSMISSION ((uint8_t)12) +#define SD_CMD_SEND_STATUS ((uint8_t)13) +#define SD_CMD_SET_BLOCKLEN ((uint8_t)16) +#define SD_CMD_READ_SINGLE_BLOCK ((uint8_t)17) +#define SD_CMD_READ_MULT_BLOCK ((uint8_t)18) +#define SD_CMD_WRITE_SINGLE_BLOCK ((uint8_t)24) +#define SD_CMD_WRITE_MULT_BLOCK ((uint8_t)25) +#define SD_CMD_PROG_CID ((uint8_t)26) +#define SD_CMD_PROG_CSD ((uint8_t)27) +#define SD_CMD_APP_CMD ((uint8_t)55) /*Following commands are SD Card Specific commands. SDIO_APP_CMD should be sent before sending these commands. */ -#define SD_CMD_APP_SD_SET_BUSWIDTH ((uint8_t)6) -#define SD_CMD_SD_APP_STAUS ((uint8_t)13) -#define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS ((uint8_t)22) -#define SD_CMD_SD_APP_OP_COND ((uint8_t)41) -#define SD_CMD_SD_APP_SET_CLR_CARD_DETECT ((uint8_t)42) -#define SD_CMD_SD_APP_SEND_SCR ((uint8_t)51) -#define SD_CMD_SDIO_RW_DIRECT ((uint8_t)52) -#define SD_CMD_SDIO_RW_EXTENDED ((uint8_t)53) +#define SD_CMD_APP_SD_SET_BUSWIDTH ((uint8_t)6) +#define SD_CMD_SD_APP_STAUS ((uint8_t)13) +#define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS ((uint8_t)22) +#define SD_CMD_SD_APP_OP_COND ((uint8_t)41) +#define SD_CMD_SD_APP_SET_CLR_CARD_DETECT ((uint8_t)42) +#define SD_CMD_SD_APP_SEND_SCR ((uint8_t)51) +#define SD_CMD_SDIO_RW_DIRECT ((uint8_t)52) +#define SD_CMD_SDIO_RW_EXTENDED ((uint8_t)53) +#define SD_RESP_NO 0 //0 无响应 +#define SD_RESP_32b 2 //2 32位响应 +#define SD_RESP_128b 1 //1 128位响应 +#define SD_RESP_32b_busy 3 //3 32位响应,check Busy after response -#define SD_RESP_NO 0 //0 无响应 -#define SD_RESP_32b 2 //2 32位响应 -#define SD_RESP_128b 1 //1 128位响应 -#define SD_RESP_32b_busy 3 //3 32位响应,check Busy after response - -#define SD_BUSWIDTH_1b 0 -#define SD_BUSWIDTH_4b 2 - -#define SD_RES_OK 0 -#define SD_RES_ERR 1 -#define SD_RES_TIMEOUT 2 +#define SD_BUSWIDTH_1b 0 +#define SD_BUSWIDTH_4b 2 +#define SD_RES_OK 0 +#define SD_RES_ERR 1 +#define SD_RES_TIMEOUT 2 typedef struct { - __IO uint8_t CSDStruct; // CSD structure - __IO uint8_t SysSpecVersion; // System specification version - __IO uint8_t Reserved1; // Reserved - __IO uint8_t TAAC; // Data read access-time 1 - __IO uint8_t NSAC; // Data read access-time 2 in CLK cycles - __IO uint8_t MaxBusClkFrec; // Max. bus clock frequency - __IO uint16_t CardComdClasses; //< Card command classes - __IO uint8_t RdBlockLen; // Max. read data block length - __IO uint8_t PartBlockRead; // Partial blocks for read allowed - __IO uint8_t WrBlockMisalign; // Write block misalignment - __IO uint8_t RdBlockMisalign; // Read block misalignment - __IO uint8_t DSRImpl; // DSR implemented - __IO uint8_t Reserved2; // Reserved - __IO uint32_t DeviceSize; // Device Size - __IO uint8_t MaxRdCurrentVDDMin; // Max. read current @ VDD min - __IO uint8_t MaxRdCurrentVDDMax; // Max. read current @ VDD max - __IO uint8_t MaxWrCurrentVDDMin; // Max. write current @ VDD min - __IO uint8_t MaxWrCurrentVDDMax; // Max. write current @ VDD max - __IO uint8_t DeviceSizeMul; // Device size multiplier - __IO uint8_t EraseGrSize; // Erase group size - __IO uint8_t EraseGrMul; // Erase group size multiplier - __IO uint8_t WrProtectGrSize; // Write protect group size - __IO uint8_t WrProtectGrEnable; // Write protect group enable - __IO uint8_t ManDeflECC; // Manufacturer default ECC - __IO uint8_t WrSpeedFact; // Write speed factor - __IO uint8_t MaxWrBlockLen; // Max. write data block length - __IO uint8_t WriteBlockPaPartial; // Partial blocks for write allowed - __IO uint8_t Reserved3; // Reserded - __IO uint8_t ContentProtectAppli; // Content protection application - __IO uint8_t FileFormatGrouop; // File format group - __IO uint8_t CopyFlag; // Copy flag (OTP) - __IO uint8_t PermWrProtect; // Permanent write protection - __IO uint8_t TempWrProtect; // Temporary write protection - __IO uint8_t FileFormat; // File Format - __IO uint8_t ECC; // ECC code + __IO uint8_t CSDStruct; // CSD structure + __IO uint8_t SysSpecVersion; // System specification version + __IO uint8_t Reserved1; // Reserved + __IO uint8_t TAAC; // Data read access-time 1 + __IO uint8_t NSAC; // Data read access-time 2 in CLK cycles + __IO uint8_t MaxBusClkFrec; // Max. bus clock frequency + __IO uint16_t CardComdClasses; //< Card command classes + __IO uint8_t RdBlockLen; // Max. read data block length + __IO uint8_t PartBlockRead; // Partial blocks for read allowed + __IO uint8_t WrBlockMisalign; // Write block misalignment + __IO uint8_t RdBlockMisalign; // Read block misalignment + __IO uint8_t DSRImpl; // DSR implemented + __IO uint8_t Reserved2; // Reserved + __IO uint32_t DeviceSize; // Device Size + __IO uint8_t MaxRdCurrentVDDMin; // Max. read current @ VDD min + __IO uint8_t MaxRdCurrentVDDMax; // Max. read current @ VDD max + __IO uint8_t MaxWrCurrentVDDMin; // Max. write current @ VDD min + __IO uint8_t MaxWrCurrentVDDMax; // Max. write current @ VDD max + __IO uint8_t DeviceSizeMul; // Device size multiplier + __IO uint8_t EraseGrSize; // Erase group size + __IO uint8_t EraseGrMul; // Erase group size multiplier + __IO uint8_t WrProtectGrSize; // Write protect group size + __IO uint8_t WrProtectGrEnable; // Write protect group enable + __IO uint8_t ManDeflECC; // Manufacturer default ECC + __IO uint8_t WrSpeedFact; // Write speed factor + __IO uint8_t MaxWrBlockLen; // Max. write data block length + __IO uint8_t WriteBlockPaPartial; // Partial blocks for write allowed + __IO uint8_t Reserved3; // Reserded + __IO uint8_t ContentProtectAppli; // Content protection application + __IO uint8_t FileFormatGrouop; // File format group + __IO uint8_t CopyFlag; // Copy flag (OTP) + __IO uint8_t PermWrProtect; // Permanent write protection + __IO uint8_t TempWrProtect; // Temporary write protection + __IO uint8_t FileFormat; // File Format + __IO uint8_t ECC; // ECC code } SD_CSD; typedef struct { - __IO uint8_t ManufacturerID; // ManufacturerID - __IO uint16_t OEM_AppliID; // OEM/Application ID - __IO uint32_t ProdName1; // Product Name part1 - __IO uint8_t ProdName2; // Product Name part2 - __IO uint8_t ProdRev; // Product Revision - __IO uint32_t ProdSN; // Product Serial Number - __IO uint8_t Reserved1; // Reserved1 - __IO uint16_t ManufactDate; // Manufacturing Date + __IO uint8_t ManufacturerID; // ManufacturerID + __IO uint16_t OEM_AppliID; // OEM/Application ID + __IO uint32_t ProdName1; // Product Name part1 + __IO uint8_t ProdName2; // Product Name part2 + __IO uint8_t ProdRev; // Product Revision + __IO uint32_t ProdSN; // Product Serial Number + __IO uint8_t Reserved1; // Reserved1 + __IO uint16_t ManufactDate; // Manufacturing Date } SD_CID; - -#define SDIO_STD_CAPACITY_SD_CARD_V1_1 ((uint32_t)0x00000000) -#define SDIO_STD_CAPACITY_SD_CARD_V2_0 ((uint32_t)0x00000001) -#define SDIO_HIGH_CAPACITY_SD_CARD ((uint32_t)0x00000002) -#define SDIO_MULTIMEDIA_CARD ((uint32_t)0x00000003) -#define SDIO_SECURE_DIGITAL_IO_CARD ((uint32_t)0x00000004) -#define SDIO_HIGH_SPEED_MULTIMEDIA_CARD ((uint32_t)0x00000005) -#define SDIO_SECURE_DIGITAL_IO_COMBO_CARD ((uint32_t)0x00000006) -#define SDIO_HIGH_CAPACITY_MMC_CARD ((uint32_t)0x00000007) - +#define SDIO_STD_CAPACITY_SD_CARD_V1_1 ((uint32_t)0x00000000) +#define SDIO_STD_CAPACITY_SD_CARD_V2_0 ((uint32_t)0x00000001) +#define SDIO_HIGH_CAPACITY_SD_CARD ((uint32_t)0x00000002) +#define SDIO_MULTIMEDIA_CARD ((uint32_t)0x00000003) +#define SDIO_SECURE_DIGITAL_IO_CARD ((uint32_t)0x00000004) +#define SDIO_HIGH_SPEED_MULTIMEDIA_CARD ((uint32_t)0x00000005) +#define SDIO_SECURE_DIGITAL_IO_COMBO_CARD ((uint32_t)0x00000006) +#define SDIO_HIGH_CAPACITY_MMC_CARD ((uint32_t)0x00000007) typedef struct { - SD_CSD SD_csd; - SD_CID SD_cid; - uint64_t CardCapacity; // Card Capacity - uint32_t CardBlockSize; // Card Block Size - uint16_t RCA; - uint8_t CardType; + SD_CSD SD_csd; + SD_CID SD_cid; + uint64_t CardCapacity; // Card Capacity + uint32_t CardBlockSize; // Card Block Size + uint16_t RCA; + uint8_t CardType; } SD_CardInfo; - extern SD_CardInfo SD_cardInfo; uint32_t SDIO_Init(uint32_t freq); @@ -135,9 +129,9 @@ uint32_t SDIO_DMABlockRead(uint32_t block_addr, uint16_t block_cnt, uint32_t buf uint32_t _SDIO_SendCmd(uint32_t cmd, uint32_t arg, uint32_t resp_type, uint32_t *resp_data, uint32_t have_data, uint32_t data_read, uint16_t block_cnt, uint32_t use_dma); -#define SDIO_SendCmd(cmd, arg, resp_type, resp_data) _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 0, 0, 0, 0) -#define SDIO_SendCmdWithData(cmd, arg, resp_type, resp_data, data_read, block_cnt) _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 1, data_read, block_cnt, 0) -#define SDIO_SendCmdWithDataByDMA(cmd, arg, resp_type, resp_data, data_read, block_cnt) _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 1, data_read, block_cnt, 1) +#define SDIO_SendCmd(cmd, arg, resp_type, resp_data) _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 0, 0, 0, 0) +#define SDIO_SendCmdWithData(cmd, arg, resp_type, resp_data, data_read, block_cnt) _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 1, data_read, block_cnt, 0) +#define SDIO_SendCmdWithDataByDMA(cmd, arg, resp_type, resp_data, data_read, block_cnt) _SDIO_SendCmd(cmd, arg, resp_type, resp_data, 1, data_read, block_cnt, 1) void parseCID(uint32_t CID_Tab[4]); void parseCSD(uint32_t CID_Tab[4]); diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.c index e1075564cb..90178f07e8 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.c @@ -28,44 +28,55 @@ * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SDRAM_Init(SDRAM_InitStructure * initStruct) +void SDRAM_Init(SDRAM_InitStructure *initStruct) { - uint32_t row_n; - - SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); - - SYS->CLKDIV &= ~SYS_CLKDIV_SDRAM_Msk; - SYS->CLKDIV |= (1 << SYS_CLKDIV_SDRAM_Pos); //2分频 - - SDRAMC->CR0 = (2 << SDRAMC_CR0_BURSTLEN_Pos) | //2 Burst Length为4 - (initStruct->CASLatency << SDRAMC_CR0_CASDELAY_Pos); - - SDRAMC->CR1 = (initStruct->CellSize << SDRAMC_CR1_CELLSIZE_Pos) | - (initStruct->CellWidth << SDRAMC_CR1_CELL32BIT_Pos) | - (initStruct->CellBank << SDRAMC_CR1_BANK_Pos) | - (0 << SDRAMC_CR1_32BIT_Pos) | - (initStruct->TimeTMRD << SDRAMC_CR1_TMRD_Pos) | - (initStruct->TimeTRRD << SDRAMC_CR1_TRRD_Pos) | - (initStruct->TimeTRAS << SDRAMC_CR1_TRAS_Pos) | - (initStruct->TimeTRC << SDRAMC_CR1_TRC_Pos) | - (initStruct->TimeTRCD << SDRAMC_CR1_TRCD_Pos) | - (initStruct->TimeTRP << SDRAMC_CR1_TRP_Pos); - - SDRAMC->LATCH = 0x02; - - switch(initStruct->CellSize) - { - case SDRAM_CELLSIZE_16Mb: row_n = 11; break; - case SDRAM_CELLSIZE_64Mb: row_n = 12; break; - case SDRAM_CELLSIZE_128Mb: row_n = 12; break; - case SDRAM_CELLSIZE_256Mb: row_n = 13; break; - default: row_n = 13; break; - } - - SDRAMC->REFRESH = (1 << SDRAMC_REFRESH_EN_Pos) | - (((SystemCoreClock/2)/1000*64 / (1 << row_n)) << SDRAMC_REFRESH_RATE_Pos); - - while(SDRAMC->REFDONE == 0); + uint32_t row_n; + + SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); + + SYS->CLKDIV &= ~SYS_CLKDIV_SDRAM_Msk; + SYS->CLKDIV |= (1 << SYS_CLKDIV_SDRAM_Pos); //2分频 + + SDRAMC->CR0 = (2 << SDRAMC_CR0_BURSTLEN_Pos) | //2 Burst Length为4 + (initStruct->CASLatency << SDRAMC_CR0_CASDELAY_Pos); + + SDRAMC->CR1 = (initStruct->CellSize << SDRAMC_CR1_CELLSIZE_Pos) | + (initStruct->CellWidth << SDRAMC_CR1_CELL32BIT_Pos) | + (initStruct->CellBank << SDRAMC_CR1_BANK_Pos) | + (0 << SDRAMC_CR1_32BIT_Pos) | + (initStruct->TimeTMRD << SDRAMC_CR1_TMRD_Pos) | + (initStruct->TimeTRRD << SDRAMC_CR1_TRRD_Pos) | + (initStruct->TimeTRAS << SDRAMC_CR1_TRAS_Pos) | + (initStruct->TimeTRC << SDRAMC_CR1_TRC_Pos) | + (initStruct->TimeTRCD << SDRAMC_CR1_TRCD_Pos) | + (initStruct->TimeTRP << SDRAMC_CR1_TRP_Pos); + + SDRAMC->LATCH = 0x02; + + switch (initStruct->CellSize) + { + case SDRAM_CELLSIZE_16Mb: + row_n = 11; + break; + case SDRAM_CELLSIZE_64Mb: + row_n = 12; + break; + case SDRAM_CELLSIZE_128Mb: + row_n = 12; + break; + case SDRAM_CELLSIZE_256Mb: + row_n = 13; + break; + default: + row_n = 13; + break; + } + + SDRAMC->REFRESH = (1 << SDRAMC_REFRESH_EN_Pos) | + (((SystemCoreClock / 2) / 1000 * 64 / (1 << row_n)) << SDRAMC_REFRESH_RATE_Pos); + + while (SDRAMC->REFDONE == 0) + ; } /****************************************************************************************************************************************** @@ -77,12 +88,13 @@ void SDRAM_Init(SDRAM_InitStructure * initStruct) ******************************************************************************************************************************************/ void SDRAM_Enable(void) { - uint32_t i; - - SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); - SDRAMC->REFRESH |= (1 << SDRAMC_REFRESH_EN_Pos); - - for(i = 0; i < 100; i++) __NOP(); + uint32_t i; + + SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); + SDRAMC->REFRESH |= (1 << SDRAMC_REFRESH_EN_Pos); + + for (i = 0; i < 100; i++) + __NOP(); } /****************************************************************************************************************************************** @@ -94,10 +106,11 @@ void SDRAM_Enable(void) ******************************************************************************************************************************************/ void SDRAM_Disable(void) { - uint32_t i; - - SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); - SDRAMC->REFRESH &= ~(1 << SDRAMC_REFRESH_EN_Pos); - - for(i = 0; i < 100; i++) __NOP(); + uint32_t i; + + SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); + SDRAMC->REFRESH &= ~(1 << SDRAMC_REFRESH_EN_Pos); + + for (i = 0; i < 100; i++) + __NOP(); } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.h index d6f6761226..cf8ca88a7c 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sdram.h @@ -1,80 +1,79 @@ #ifndef __SWM320_SDRAM_H__ #define __SWM320_SDRAM_H__ -typedef struct { - uint8_t CellSize; // SDRAM颗粒的容量,SDRAM_CELLSIZE_16Mb、SDRAM_CELLSIZE_64Mb、SDRAM_CELLSIZE_128Mb、SDRAM_CELLSIZE_256Mb - uint8_t CellBank; // SDRAM颗粒有几个bank,SDRAM_CELLBANK_2、SDRAM_CELLBANK_4 - uint8_t CellWidth; // SDRAM颗粒的位宽,SDRAM_CELLWIDTH_16、SDRAM_CELLWIDTH_32 - uint8_t CASLatency; // 列地址到有效数据输出间隔,SDRAM_CASLATENCY_2、SDRAM_CASLATENCY_3 - - uint8_t TimeTMRD; // MRS to New Command - uint8_t TimeTRRD; // Activate to activate on different banks - uint8_t TimeTRAS; // Self refresh time,最小Self-refresh周期 - uint8_t TimeTRC; // Row cycle delay,Refresh命令到Activate命令间延时,也是两个连续Refresh命令间延时 - uint8_t TimeTRCD; // Row to column delay,行地址到列地址间延时,也即Activate命令到读写命令间延时 - uint8_t TimeTRP; // Row precharge delay,Precharge命令到另一个命令间延时 +typedef struct +{ + uint8_t CellSize; // SDRAM颗粒的容量,SDRAM_CELLSIZE_16Mb、SDRAM_CELLSIZE_64Mb、SDRAM_CELLSIZE_128Mb、SDRAM_CELLSIZE_256Mb + uint8_t CellBank; // SDRAM颗粒有几个bank,SDRAM_CELLBANK_2、SDRAM_CELLBANK_4 + uint8_t CellWidth; // SDRAM颗粒的位宽,SDRAM_CELLWIDTH_16、SDRAM_CELLWIDTH_32 + uint8_t CASLatency; // 列地址到有效数据输出间隔,SDRAM_CASLATENCY_2、SDRAM_CASLATENCY_3 + + uint8_t TimeTMRD; // MRS to New Command + uint8_t TimeTRRD; // Activate to activate on different banks + uint8_t TimeTRAS; // Self refresh time,最小Self-refresh周期 + uint8_t TimeTRC; // Row cycle delay,Refresh命令到Activate命令间延时,也是两个连续Refresh命令间延时 + uint8_t TimeTRCD; // Row to column delay,行地址到列地址间延时,也即Activate命令到读写命令间延时 + uint8_t TimeTRP; // Row precharge delay,Precharge命令到另一个命令间延时 } SDRAM_InitStructure; -#define SDRAM_CELLSIZE_16Mb 3 -#define SDRAM_CELLSIZE_64Mb 0 -#define SDRAM_CELLSIZE_128Mb 1 -#define SDRAM_CELLSIZE_256Mb 2 +#define SDRAM_CELLSIZE_16Mb 3 +#define SDRAM_CELLSIZE_64Mb 0 +#define SDRAM_CELLSIZE_128Mb 1 +#define SDRAM_CELLSIZE_256Mb 2 -#define SDRAM_CELLBANK_2 0 -#define SDRAM_CELLBANK_4 1 +#define SDRAM_CELLBANK_2 0 +#define SDRAM_CELLBANK_4 1 -#define SDRAM_CELLWIDTH_16 0 -#define SDRAM_CELLWIDTH_32 1 +#define SDRAM_CELLWIDTH_16 0 +#define SDRAM_CELLWIDTH_32 1 -#define SDRAM_CASLATENCY_2 2 -#define SDRAM_CASLATENCY_3 3 +#define SDRAM_CASLATENCY_2 2 +#define SDRAM_CASLATENCY_3 3 -#define SDRAM_TMRD_3 3 -#define SDRAM_TMRD_4 4 -#define SDRAM_TMRD_5 5 -#define SDRAM_TMRD_6 6 -#define SDRAM_TMRD_7 7 +#define SDRAM_TMRD_3 3 +#define SDRAM_TMRD_4 4 +#define SDRAM_TMRD_5 5 +#define SDRAM_TMRD_6 6 +#define SDRAM_TMRD_7 7 -#define SDRAM_TRRD_2 2 -#define SDRAM_TRRD_3 3 +#define SDRAM_TRRD_2 2 +#define SDRAM_TRRD_3 3 -#define SDRAM_TRAS_2 2 -#define SDRAM_TRAS_3 3 -#define SDRAM_TRAS_4 4 -#define SDRAM_TRAS_5 5 -#define SDRAM_TRAS_6 6 -#define SDRAM_TRAS_7 7 +#define SDRAM_TRAS_2 2 +#define SDRAM_TRAS_3 3 +#define SDRAM_TRAS_4 4 +#define SDRAM_TRAS_5 5 +#define SDRAM_TRAS_6 6 +#define SDRAM_TRAS_7 7 -#define SDRAM_TRC_2 2 -#define SDRAM_TRC_3 3 -#define SDRAM_TRC_4 4 -#define SDRAM_TRC_5 5 -#define SDRAM_TRC_6 6 -#define SDRAM_TRC_7 7 -#define SDRAM_TRC_8 8 -#define SDRAM_TRC_9 9 -#define SDRAM_TRC_10 10 -#define SDRAM_TRC_11 11 -#define SDRAM_TRC_12 12 -#define SDRAM_TRC_13 13 -#define SDRAM_TRC_14 14 -#define SDRAM_TRC_15 15 +#define SDRAM_TRC_2 2 +#define SDRAM_TRC_3 3 +#define SDRAM_TRC_4 4 +#define SDRAM_TRC_5 5 +#define SDRAM_TRC_6 6 +#define SDRAM_TRC_7 7 +#define SDRAM_TRC_8 8 +#define SDRAM_TRC_9 9 +#define SDRAM_TRC_10 10 +#define SDRAM_TRC_11 11 +#define SDRAM_TRC_12 12 +#define SDRAM_TRC_13 13 +#define SDRAM_TRC_14 14 +#define SDRAM_TRC_15 15 -#define SDRAM_TRCD_3 3 -#define SDRAM_TRCD_4 4 -#define SDRAM_TRCD_5 5 -#define SDRAM_TRCD_6 6 -#define SDRAM_TRCD_7 7 +#define SDRAM_TRCD_3 3 +#define SDRAM_TRCD_4 4 +#define SDRAM_TRCD_5 5 +#define SDRAM_TRCD_6 6 +#define SDRAM_TRCD_7 7 -#define SDRAM_TRP_3 3 -#define SDRAM_TRP_4 4 -#define SDRAM_TRP_5 5 -#define SDRAM_TRP_6 6 -#define SDRAM_TRP_7 7 +#define SDRAM_TRP_3 3 +#define SDRAM_TRP_4 4 +#define SDRAM_TRP_5 5 +#define SDRAM_TRP_6 6 +#define SDRAM_TRP_7 7 - - -void SDRAM_Init(SDRAM_InitStructure * initStruct); +void SDRAM_Init(SDRAM_InitStructure *initStruct); void SDRAM_Enable(void); void SDRAM_Disable(void); diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.c index dcd618ec92..f6025a6e86 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.c @@ -21,7 +21,6 @@ #include "SWM320.h" #include "SWM320_spi.h" - /****************************************************************************************************************************************** * 函数名称: SPI_Init() * 功能说明: SPI同步串行接口初始化,包括帧长度设定、时序设定、速度设定、中断设定、FIFO触发设定 @@ -30,61 +29,61 @@ * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_Init(SPI_TypeDef * SPIx, SPI_InitStructure * initStruct) +void SPI_Init(SPI_TypeDef *SPIx, SPI_InitStructure *initStruct) { - switch((uint32_t)SPIx) - { - case ((uint32_t)SPI0): - SYS->CLKEN |= (0x01 << SYS_CLKEN_SPI0_Pos); - break; + switch ((uint32_t)SPIx) + { + case ((uint32_t)SPI0): + SYS->CLKEN |= (0x01 << SYS_CLKEN_SPI0_Pos); + break; - case ((uint32_t)SPI1): - SYS->CLKEN |= (0x01 << SYS_CLKEN_SPI0_Pos); //与SPI0使用同一位时钟使能 - break; - } - - SPI_Close(SPIx); //一些关键寄存器只能在SPI关闭时设置 - - SPIx->CTRL &= ~(SPI_CTRL_FFS_Msk | SPI_CTRL_CPHA_Msk | SPI_CTRL_CPOL_Msk | - SPI_CTRL_SIZE_Msk | SPI_CTRL_MSTR_Msk | SPI_CTRL_CLKDIV_Msk | SPI_CTRL_SSN_H_Msk); - SPIx->CTRL |= (initStruct->FrameFormat << SPI_CTRL_FFS_Pos) | - (initStruct->SampleEdge << SPI_CTRL_CPHA_Pos) | - (initStruct->IdleLevel << SPI_CTRL_CPOL_Pos) | - ((initStruct->WordSize-1) << SPI_CTRL_SIZE_Pos) | - (initStruct->Master << SPI_CTRL_MSTR_Pos) | - (initStruct->clkDiv << SPI_CTRL_CLKDIV_Pos) | - (0 << SPI_CTRL_SSN_H_Pos); - - SPIx->IF = (0x01 << SPI_IF_RFOVF_Pos); //清除中断标志 - SPIx->IE &= ~(SPI_IE_RFHF_Msk | SPI_IE_TFHF_Msk | SPI_IE_FTC_Msk); - SPIx->IE |= (initStruct->RXHFullIEn << SPI_IE_RFHF_Pos) | - (initStruct->TXEmptyIEn << SPI_IE_TFHF_Pos) | - (initStruct->TXCompleteIEn << SPI_IE_FTC_Pos); - - switch((uint32_t)SPIx) - { - case ((uint32_t)SPI0): - if(initStruct->RXHFullIEn | initStruct->TXEmptyIEn | initStruct->TXCompleteIEn) - { - NVIC_EnableIRQ(SPI0_IRQn); - } - else - { - NVIC_DisableIRQ(SPI0_IRQn); - } - break; - - case ((uint32_t)SPI1): - if(initStruct->RXHFullIEn | initStruct->TXEmptyIEn | initStruct->TXCompleteIEn) - { - NVIC_EnableIRQ(SPI1_IRQn); - } - else - { - NVIC_DisableIRQ(SPI1_IRQn); - } - break; - } + case ((uint32_t)SPI1): + SYS->CLKEN |= (0x01 << SYS_CLKEN_SPI0_Pos); //与SPI0使用同一位时钟使能 + break; + } + + SPI_Close(SPIx); //一些关键寄存器只能在SPI关闭时设置 + + SPIx->CTRL &= ~(SPI_CTRL_FFS_Msk | SPI_CTRL_CPHA_Msk | SPI_CTRL_CPOL_Msk | + SPI_CTRL_SIZE_Msk | SPI_CTRL_MSTR_Msk | SPI_CTRL_CLKDIV_Msk | SPI_CTRL_SSN_H_Msk); + SPIx->CTRL |= (initStruct->FrameFormat << SPI_CTRL_FFS_Pos) | + (initStruct->SampleEdge << SPI_CTRL_CPHA_Pos) | + (initStruct->IdleLevel << SPI_CTRL_CPOL_Pos) | + ((initStruct->WordSize - 1) << SPI_CTRL_SIZE_Pos) | + (initStruct->Master << SPI_CTRL_MSTR_Pos) | + (initStruct->clkDiv << SPI_CTRL_CLKDIV_Pos) | + (0 << SPI_CTRL_SSN_H_Pos); + + SPIx->IF = (0x01 << SPI_IF_RFOVF_Pos); //清除中断标志 + SPIx->IE &= ~(SPI_IE_RFHF_Msk | SPI_IE_TFHF_Msk | SPI_IE_FTC_Msk); + SPIx->IE |= (initStruct->RXHFullIEn << SPI_IE_RFHF_Pos) | + (initStruct->TXEmptyIEn << SPI_IE_TFHF_Pos) | + (initStruct->TXCompleteIEn << SPI_IE_FTC_Pos); + + switch ((uint32_t)SPIx) + { + case ((uint32_t)SPI0): + if (initStruct->RXHFullIEn | initStruct->TXEmptyIEn | initStruct->TXCompleteIEn) + { + NVIC_EnableIRQ(SPI0_IRQn); + } + else + { + NVIC_DisableIRQ(SPI0_IRQn); + } + break; + + case ((uint32_t)SPI1): + if (initStruct->RXHFullIEn | initStruct->TXEmptyIEn | initStruct->TXCompleteIEn) + { + NVIC_EnableIRQ(SPI1_IRQn); + } + else + { + NVIC_DisableIRQ(SPI1_IRQn); + } + break; + } } /****************************************************************************************************************************************** @@ -94,9 +93,9 @@ void SPI_Init(SPI_TypeDef * SPIx, SPI_InitStructure * initStruct) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_Open(SPI_TypeDef * SPIx) +void SPI_Open(SPI_TypeDef *SPIx) { - SPIx->CTRL |= (0x01 << SPI_CTRL_EN_Pos); + SPIx->CTRL |= (0x01 << SPI_CTRL_EN_Pos); } /****************************************************************************************************************************************** @@ -106,9 +105,9 @@ void SPI_Open(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_Close(SPI_TypeDef * SPIx) +void SPI_Close(SPI_TypeDef *SPIx) { - SPIx->CTRL &= ~SPI_CTRL_EN_Msk; + SPIx->CTRL &= ~SPI_CTRL_EN_Msk; } /****************************************************************************************************************************************** @@ -118,9 +117,9 @@ void SPI_Close(SPI_TypeDef * SPIx) * 输 出: uint32_t 读取到的数据 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t SPI_Read(SPI_TypeDef * SPIx) +uint32_t SPI_Read(SPI_TypeDef *SPIx) { - return SPIx->DATA; + return SPIx->DATA; } /****************************************************************************************************************************************** @@ -131,9 +130,9 @@ uint32_t SPI_Read(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_Write(SPI_TypeDef * SPIx, uint32_t data) +void SPI_Write(SPI_TypeDef *SPIx, uint32_t data) { - SPIx->DATA = data; + SPIx->DATA = data; } /****************************************************************************************************************************************** @@ -144,13 +143,14 @@ void SPI_Write(SPI_TypeDef * SPIx, uint32_t data) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_WriteWithWait(SPI_TypeDef * SPIx, uint32_t data) +void SPI_WriteWithWait(SPI_TypeDef *SPIx, uint32_t data) { - SPIx->STAT |= (1 << SPI_STAT_WTC_Pos); - - SPIx->DATA = data; - - while((SPIx->STAT & SPI_STAT_WTC_Msk) == 0); + SPIx->STAT |= (1 << SPI_STAT_WTC_Pos); + + SPIx->DATA = data; + + while ((SPIx->STAT & SPI_STAT_WTC_Msk) == 0) + ; } /****************************************************************************************************************************************** @@ -161,12 +161,13 @@ void SPI_WriteWithWait(SPI_TypeDef * SPIx, uint32_t data) * 输 出: uint32_t 接收到的数据 * 注意事项: 对于同一个SPI模块,此函数不应与SPI_Write()混着用,因为SPI_Write()不清除SPI_STAT_RFNE状态 ******************************************************************************************************************************************/ -uint32_t SPI_ReadWrite(SPI_TypeDef * SPIx, uint32_t data) +uint32_t SPI_ReadWrite(SPI_TypeDef *SPIx, uint32_t data) { - SPIx->DATA = data; - while(!(SPIx->STAT & SPI_STAT_RFNE_Msk)); - - return SPIx->DATA; + SPIx->DATA = data; + while (!(SPIx->STAT & SPI_STAT_RFNE_Msk)) + ; + + return SPIx->DATA; } /****************************************************************************************************************************************** @@ -176,9 +177,9 @@ uint32_t SPI_ReadWrite(SPI_TypeDef * SPIx, uint32_t data) * 输 出: uint32_t 1 接收FIFO空 0 接收FIFO非空 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t SPI_IsRXEmpty(SPI_TypeDef * SPIx) +uint32_t SPI_IsRXEmpty(SPI_TypeDef *SPIx) { - return (SPIx->STAT & SPI_STAT_RFNE_Msk) ? 0 : 1; + return (SPIx->STAT & SPI_STAT_RFNE_Msk) ? 0 : 1; } /****************************************************************************************************************************************** @@ -188,9 +189,9 @@ uint32_t SPI_IsRXEmpty(SPI_TypeDef * SPIx) * 输 出: uint32_t 1 发送FIFO满 0 发送FIFO不满 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t SPI_IsTXFull(SPI_TypeDef * SPIx) +uint32_t SPI_IsTXFull(SPI_TypeDef *SPIx) { - return (SPIx->STAT & SPI_STAT_TFNF_Msk) ? 0 : 1; + return (SPIx->STAT & SPI_STAT_TFNF_Msk) ? 0 : 1; } /****************************************************************************************************************************************** @@ -200,12 +201,11 @@ uint32_t SPI_IsTXFull(SPI_TypeDef * SPIx) * 输 出: uint32_t 1 发送FIFO空 0 发送FIFO非空 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t SPI_IsTXEmpty(SPI_TypeDef * SPIx) +uint32_t SPI_IsTXEmpty(SPI_TypeDef *SPIx) { - return (SPIx->STAT & SPI_STAT_TFE_Msk) ? 1 : 0; + return (SPIx->STAT & SPI_STAT_TFE_Msk) ? 1 : 0; } - /****************************************************************************************************************************************** * 函数名称: SPI_INTRXHalfFullEn() * 功能说明: 接收FIFO半满中断使能 @@ -213,9 +213,9 @@ uint32_t SPI_IsTXEmpty(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTRXHalfFullEn(SPI_TypeDef * SPIx) +void SPI_INTRXHalfFullEn(SPI_TypeDef *SPIx) { - SPIx->IE |= (0x01 << SPI_IE_RFHF_Pos); + SPIx->IE |= (0x01 << SPI_IE_RFHF_Pos); } /****************************************************************************************************************************************** @@ -225,9 +225,9 @@ void SPI_INTRXHalfFullEn(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTRXHalfFullDis(SPI_TypeDef * SPIx) +void SPI_INTRXHalfFullDis(SPI_TypeDef *SPIx) { - SPIx->IE &= ~(0x01 << SPI_IE_RFHF_Pos); + SPIx->IE &= ~(0x01 << SPI_IE_RFHF_Pos); } /****************************************************************************************************************************************** @@ -237,9 +237,9 @@ void SPI_INTRXHalfFullDis(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTRXHalfFullClr(SPI_TypeDef * SPIx) +void SPI_INTRXHalfFullClr(SPI_TypeDef *SPIx) { - SPIx->IF = (1 << SPI_IF_RFHF_Pos); + SPIx->IF = (1 << SPI_IF_RFHF_Pos); } /****************************************************************************************************************************************** @@ -249,9 +249,9 @@ void SPI_INTRXHalfFullClr(SPI_TypeDef * SPIx) * 输 出: uint32_t 1 接收FIFO达到半满 0 接收FIFO未达到半满 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t SPI_INTRXHalfFullStat(SPI_TypeDef * SPIx) +uint32_t SPI_INTRXHalfFullStat(SPI_TypeDef *SPIx) { - return (SPIx->IF & SPI_IF_RFHF_Msk) ? 1 : 0; + return (SPIx->IF & SPI_IF_RFHF_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -261,9 +261,9 @@ uint32_t SPI_INTRXHalfFullStat(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTRXFullEn(SPI_TypeDef * SPIx) +void SPI_INTRXFullEn(SPI_TypeDef *SPIx) { - SPIx->IE |= (0x01 << SPI_IE_RFF_Pos); + SPIx->IE |= (0x01 << SPI_IE_RFF_Pos); } /****************************************************************************************************************************************** @@ -273,9 +273,9 @@ void SPI_INTRXFullEn(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTRXFullDis(SPI_TypeDef * SPIx) +void SPI_INTRXFullDis(SPI_TypeDef *SPIx) { - SPIx->IE &= ~(0x01 << SPI_IE_RFF_Pos); + SPIx->IE &= ~(0x01 << SPI_IE_RFF_Pos); } /****************************************************************************************************************************************** @@ -285,9 +285,9 @@ void SPI_INTRXFullDis(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTRXFullClr(SPI_TypeDef * SPIx) +void SPI_INTRXFullClr(SPI_TypeDef *SPIx) { - SPIx->IF = (1 << SPI_IF_RFF_Pos); + SPIx->IF = (1 << SPI_IF_RFF_Pos); } /****************************************************************************************************************************************** @@ -297,9 +297,9 @@ void SPI_INTRXFullClr(SPI_TypeDef * SPIx) * 输 出: uint32_t 1 接收FIFO满 0 接收FIFO未满 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t SPI_INTRXFullStat(SPI_TypeDef * SPIx) +uint32_t SPI_INTRXFullStat(SPI_TypeDef *SPIx) { - return (SPIx->IF & SPI_IF_RFF_Msk) ? 1 : 0; + return (SPIx->IF & SPI_IF_RFF_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -309,9 +309,9 @@ uint32_t SPI_INTRXFullStat(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTRXOverflowEn(SPI_TypeDef * SPIx) +void SPI_INTRXOverflowEn(SPI_TypeDef *SPIx) { - SPIx->IE |= (0x01 << SPI_IE_RFOVF_Pos); + SPIx->IE |= (0x01 << SPI_IE_RFOVF_Pos); } /****************************************************************************************************************************************** @@ -321,9 +321,9 @@ void SPI_INTRXOverflowEn(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTRXOverflowDis(SPI_TypeDef * SPIx) +void SPI_INTRXOverflowDis(SPI_TypeDef *SPIx) { - SPIx->IE &= ~(0x01 << SPI_IE_RFOVF_Pos); + SPIx->IE &= ~(0x01 << SPI_IE_RFOVF_Pos); } /****************************************************************************************************************************************** @@ -333,9 +333,9 @@ void SPI_INTRXOverflowDis(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTRXOverflowClr(SPI_TypeDef * SPIx) +void SPI_INTRXOverflowClr(SPI_TypeDef *SPIx) { - SPIx->IF = (0x01 << SPI_IF_RFOVF_Pos); + SPIx->IF = (0x01 << SPI_IF_RFOVF_Pos); } /****************************************************************************************************************************************** @@ -345,9 +345,9 @@ void SPI_INTRXOverflowClr(SPI_TypeDef * SPIx) * 输 出: uint32_t 1 接收FIFO溢出 0 接收FIFO未溢出 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t SPI_INTRXOverflowStat(SPI_TypeDef * SPIx) +uint32_t SPI_INTRXOverflowStat(SPI_TypeDef *SPIx) { - return (SPIx->IF & SPI_IF_RFOVF_Msk) ? 1 : 0; + return (SPIx->IF & SPI_IF_RFOVF_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -357,9 +357,9 @@ uint32_t SPI_INTRXOverflowStat(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXHalfFullEn(SPI_TypeDef * SPIx) +void SPI_INTTXHalfFullEn(SPI_TypeDef *SPIx) { - SPIx->IE |= (0x01 << SPI_IE_TFHF_Pos); + SPIx->IE |= (0x01 << SPI_IE_TFHF_Pos); } /****************************************************************************************************************************************** @@ -369,9 +369,9 @@ void SPI_INTTXHalfFullEn(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXHalfFullDis(SPI_TypeDef * SPIx) +void SPI_INTTXHalfFullDis(SPI_TypeDef *SPIx) { - SPIx->IE &= ~(0x01 << SPI_IE_TFHF_Pos); + SPIx->IE &= ~(0x01 << SPI_IE_TFHF_Pos); } /****************************************************************************************************************************************** @@ -381,9 +381,9 @@ void SPI_INTTXHalfFullDis(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXHalfFullClr(SPI_TypeDef * SPIx) +void SPI_INTTXHalfFullClr(SPI_TypeDef *SPIx) { - SPIx->IF = (1 << SPI_IF_TFHF_Pos); + SPIx->IF = (1 << SPI_IF_TFHF_Pos); } /****************************************************************************************************************************************** @@ -393,9 +393,9 @@ void SPI_INTTXHalfFullClr(SPI_TypeDef * SPIx) * 输 出: uint32_t 1 发送FIFO达到半满 0 发送FIFO未达到半满 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t SPI_INTTXHalfFullStat(SPI_TypeDef * SPIx) +uint32_t SPI_INTTXHalfFullStat(SPI_TypeDef *SPIx) { - return (SPIx->IF & SPI_IF_TFHF_Msk) ? 1 : 0; + return (SPIx->IF & SPI_IF_TFHF_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -405,9 +405,9 @@ uint32_t SPI_INTTXHalfFullStat(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXEmptyEn(SPI_TypeDef * SPIx) +void SPI_INTTXEmptyEn(SPI_TypeDef *SPIx) { - SPIx->IE |= (0x01 << SPI_IE_TFE_Pos); + SPIx->IE |= (0x01 << SPI_IE_TFE_Pos); } /****************************************************************************************************************************************** @@ -417,9 +417,9 @@ void SPI_INTTXEmptyEn(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXEmptyDis(SPI_TypeDef * SPIx) +void SPI_INTTXEmptyDis(SPI_TypeDef *SPIx) { - SPIx->IE &= ~(0x01 << SPI_IE_TFE_Pos); + SPIx->IE &= ~(0x01 << SPI_IE_TFE_Pos); } /****************************************************************************************************************************************** @@ -429,9 +429,9 @@ void SPI_INTTXEmptyDis(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXEmptyClr(SPI_TypeDef * SPIx) +void SPI_INTTXEmptyClr(SPI_TypeDef *SPIx) { - SPIx->IF = (1 << SPI_IF_TFE_Pos); + SPIx->IF = (1 << SPI_IF_TFE_Pos); } /****************************************************************************************************************************************** @@ -441,9 +441,9 @@ void SPI_INTTXEmptyClr(SPI_TypeDef * SPIx) * 输 出: uint32_t 1 发送FIFO空 0 发送FIFO非空 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t SPI_INTTXEmptyStat(SPI_TypeDef * SPIx) +uint32_t SPI_INTTXEmptyStat(SPI_TypeDef *SPIx) { - return (SPIx->IF & SPI_IF_TFE_Msk) ? 1 : 0; + return (SPIx->IF & SPI_IF_TFE_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -453,9 +453,9 @@ uint32_t SPI_INTTXEmptyStat(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXCompleteEn(SPI_TypeDef * SPIx) +void SPI_INTTXCompleteEn(SPI_TypeDef *SPIx) { - SPIx->IE |= (0x01 << SPI_IE_FTC_Pos); + SPIx->IE |= (0x01 << SPI_IE_FTC_Pos); } /****************************************************************************************************************************************** @@ -465,9 +465,9 @@ void SPI_INTTXCompleteEn(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXCompleteDis(SPI_TypeDef * SPIx) +void SPI_INTTXCompleteDis(SPI_TypeDef *SPIx) { - SPIx->IE &= ~(0x01 << SPI_IE_FTC_Pos); + SPIx->IE &= ~(0x01 << SPI_IE_FTC_Pos); } /****************************************************************************************************************************************** @@ -477,9 +477,9 @@ void SPI_INTTXCompleteDis(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXCompleteClr(SPI_TypeDef * SPIx) +void SPI_INTTXCompleteClr(SPI_TypeDef *SPIx) { - SPIx->IF = (1 << SPI_IF_FTC_Pos); + SPIx->IF = (1 << SPI_IF_FTC_Pos); } /****************************************************************************************************************************************** @@ -489,9 +489,9 @@ void SPI_INTTXCompleteClr(SPI_TypeDef * SPIx) * 输 出: uint32_t 1 发送FIFO空且发送移位寄存器空 0 发送FIFO或发送移位寄存器非空 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t SPI_INTTXCompleteStat(SPI_TypeDef * SPIx) +uint32_t SPI_INTTXCompleteStat(SPI_TypeDef *SPIx) { - return (SPIx->IF & SPI_IF_FTC_Msk) ? 1 : 0; + return (SPIx->IF & SPI_IF_FTC_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -501,9 +501,9 @@ uint32_t SPI_INTTXCompleteStat(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXWordCompleteEn(SPI_TypeDef * SPIx) +void SPI_INTTXWordCompleteEn(SPI_TypeDef *SPIx) { - SPIx->IE |= (0x01 << SPI_IE_WTC_Pos); + SPIx->IE |= (0x01 << SPI_IE_WTC_Pos); } /****************************************************************************************************************************************** @@ -513,9 +513,9 @@ void SPI_INTTXWordCompleteEn(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXWordCompleteDis(SPI_TypeDef * SPIx) +void SPI_INTTXWordCompleteDis(SPI_TypeDef *SPIx) { - SPIx->IE &= ~(0x01 << SPI_IE_WTC_Pos); + SPIx->IE &= ~(0x01 << SPI_IE_WTC_Pos); } /****************************************************************************************************************************************** @@ -525,9 +525,9 @@ void SPI_INTTXWordCompleteDis(SPI_TypeDef * SPIx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SPI_INTTXWordCompleteClr(SPI_TypeDef * SPIx) +void SPI_INTTXWordCompleteClr(SPI_TypeDef *SPIx) { - SPIx->IF = (1 << SPI_IF_WTC_Pos); + SPIx->IF = (1 << SPI_IF_WTC_Pos); } /****************************************************************************************************************************************** @@ -537,7 +537,7 @@ void SPI_INTTXWordCompleteClr(SPI_TypeDef * SPIx) * 输 出: uint32_t 1 发送完成中断已发生 0 发送完成中断未发生 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t SPI_INTTXWordCompleteStat(SPI_TypeDef * SPIx) +uint32_t SPI_INTTXWordCompleteStat(SPI_TypeDef *SPIx) { - return (SPIx->IF & SPI_IF_WTC_Msk) ? 1 : 0; + return (SPIx->IF & SPI_IF_WTC_Msk) ? 1 : 0; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.h index a7725ee24e..db024d6bca 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_spi.h @@ -1,83 +1,80 @@ #ifndef __SWM320_SPI_H__ #define __SWM320_SPI_H__ -typedef struct { - uint8_t FrameFormat; //帧格式:SPI_FORMAT_SPI、SPI_FORMAT_TI_SSI - uint8_t SampleEdge; //在SPI帧格式下,选择数据采样边沿:SPI_FIRST_EDGE、SPI_SECOND_EDGE - uint8_t IdleLevel; //在SPI帧格式下,选择空闲时(无数据传输时)时钟线的电平:SPI_LOW_LEVEL、SPI_HIGH_LEVEL - uint8_t WordSize; //字长度, 有效值4-16 - uint8_t Master; //1 主机模式 0 从机模式 - uint8_t clkDiv; //SPI_CLK = SYS_CLK / clkDiv,有效值:SPI_CLKDIV_4、SPI_CLKDIV_8、... ... 、SPI_CLKDIV_512 - - uint8_t RXHFullIEn; //接收FIFO半满中断使能 - uint8_t TXEmptyIEn; //发送FIFO 空中断使能 - uint8_t TXCompleteIEn; //发送FIFO 空且发送移位寄存器空中断使能 +typedef struct +{ + uint8_t FrameFormat; //帧格式:SPI_FORMAT_SPI、SPI_FORMAT_TI_SSI + uint8_t SampleEdge; //在SPI帧格式下,选择数据采样边沿:SPI_FIRST_EDGE、SPI_SECOND_EDGE + uint8_t IdleLevel; //在SPI帧格式下,选择空闲时(无数据传输时)时钟线的电平:SPI_LOW_LEVEL、SPI_HIGH_LEVEL + uint8_t WordSize; //字长度, 有效值4-16 + uint8_t Master; //1 主机模式 0 从机模式 + uint8_t clkDiv; //SPI_CLK = SYS_CLK / clkDiv,有效值:SPI_CLKDIV_4、SPI_CLKDIV_8、... ... 、SPI_CLKDIV_512 + + uint8_t RXHFullIEn; //接收FIFO半满中断使能 + uint8_t TXEmptyIEn; //发送FIFO 空中断使能 + uint8_t TXCompleteIEn; //发送FIFO 空且发送移位寄存器空中断使能 } SPI_InitStructure; -#define SPI_FORMAT_SPI 0 //Motorola SPI 格式 -#define SPI_FORMAT_TI_SSI 1 //TI SSI 格式 +#define SPI_FORMAT_SPI 0 //Motorola SPI 格式 +#define SPI_FORMAT_TI_SSI 1 //TI SSI 格式 -#define SPI_FIRST_EDGE 0 //第一个时钟沿开始采样 -#define SPI_SECOND_EDGE 1 //第二个时钟沿开始采样 +#define SPI_FIRST_EDGE 0 //第一个时钟沿开始采样 +#define SPI_SECOND_EDGE 1 //第二个时钟沿开始采样 -#define SPI_LOW_LEVEL 0 //空闲时时钟线保持低电平 -#define SPI_HIGH_LEVEL 1 //空闲时时钟线保持高电平 +#define SPI_LOW_LEVEL 0 //空闲时时钟线保持低电平 +#define SPI_HIGH_LEVEL 1 //空闲时时钟线保持高电平 -#define SPI_CLKDIV_4 0 -#define SPI_CLKDIV_8 1 -#define SPI_CLKDIV_16 2 -#define SPI_CLKDIV_32 3 -#define SPI_CLKDIV_64 4 -#define SPI_CLKDIV_128 5 -#define SPI_CLKDIV_256 6 -#define SPI_CLKDIV_512 7 +#define SPI_CLKDIV_4 0 +#define SPI_CLKDIV_8 1 +#define SPI_CLKDIV_16 2 +#define SPI_CLKDIV_32 3 +#define SPI_CLKDIV_64 4 +#define SPI_CLKDIV_128 5 +#define SPI_CLKDIV_256 6 +#define SPI_CLKDIV_512 7 +void SPI_Init(SPI_TypeDef *SPIx, SPI_InitStructure *initStruct); //SPI初始化 +void SPI_Open(SPI_TypeDef *SPIx); //SPI打开,允许收发 +void SPI_Close(SPI_TypeDef *SPIx); //SPI关闭,禁止收发 +uint32_t SPI_Read(SPI_TypeDef *SPIx); +void SPI_Write(SPI_TypeDef *SPIx, uint32_t data); +void SPI_WriteWithWait(SPI_TypeDef *SPIx, uint32_t data); +uint32_t SPI_ReadWrite(SPI_TypeDef *SPIx, uint32_t data); -void SPI_Init(SPI_TypeDef * SPIx, SPI_InitStructure * initStruct); //SPI初始化 -void SPI_Open(SPI_TypeDef * SPIx); //SPI打开,允许收发 -void SPI_Close(SPI_TypeDef * SPIx); //SPI关闭,禁止收发 +uint32_t SPI_IsRXEmpty(SPI_TypeDef *SPIx); //接收FIFO是否空,如果不空则可以继续SPI_Read() +uint32_t SPI_IsTXFull(SPI_TypeDef *SPIx); //发送FIFO是否满,如果不满则可以继续SPI_Write() +uint32_t SPI_IsTXEmpty(SPI_TypeDef *SPIx); //发送FIFO是否空 -uint32_t SPI_Read(SPI_TypeDef * SPIx); -void SPI_Write(SPI_TypeDef * SPIx, uint32_t data); -void SPI_WriteWithWait(SPI_TypeDef * SPIx, uint32_t data); -uint32_t SPI_ReadWrite(SPI_TypeDef * SPIx, uint32_t data); +void SPI_INTRXHalfFullEn(SPI_TypeDef *SPIx); +void SPI_INTRXHalfFullDis(SPI_TypeDef *SPIx); +void SPI_INTRXHalfFullClr(SPI_TypeDef *SPIx); +uint32_t SPI_INTRXHalfFullStat(SPI_TypeDef *SPIx); +void SPI_INTRXFullEn(SPI_TypeDef *SPIx); +void SPI_INTRXFullDis(SPI_TypeDef *SPIx); +void SPI_INTRXFullClr(SPI_TypeDef *SPIx); +uint32_t SPI_INTRXFullStat(SPI_TypeDef *SPIx); +void SPI_INTRXOverflowEn(SPI_TypeDef *SPIx); +void SPI_INTRXOverflowDis(SPI_TypeDef *SPIx); +void SPI_INTRXOverflowClr(SPI_TypeDef *SPIx); +uint32_t SPI_INTRXOverflowStat(SPI_TypeDef *SPIx); -uint32_t SPI_IsRXEmpty(SPI_TypeDef * SPIx); //接收FIFO是否空,如果不空则可以继续SPI_Read() -uint32_t SPI_IsTXFull(SPI_TypeDef * SPIx); //发送FIFO是否满,如果不满则可以继续SPI_Write() -uint32_t SPI_IsTXEmpty(SPI_TypeDef * SPIx); //发送FIFO是否空 - - -void SPI_INTRXHalfFullEn(SPI_TypeDef * SPIx); -void SPI_INTRXHalfFullDis(SPI_TypeDef * SPIx); -void SPI_INTRXHalfFullClr(SPI_TypeDef * SPIx); -uint32_t SPI_INTRXHalfFullStat(SPI_TypeDef * SPIx); -void SPI_INTRXFullEn(SPI_TypeDef * SPIx); -void SPI_INTRXFullDis(SPI_TypeDef * SPIx); -void SPI_INTRXFullClr(SPI_TypeDef * SPIx); -uint32_t SPI_INTRXFullStat(SPI_TypeDef * SPIx); -void SPI_INTRXOverflowEn(SPI_TypeDef * SPIx); -void SPI_INTRXOverflowDis(SPI_TypeDef * SPIx); -void SPI_INTRXOverflowClr(SPI_TypeDef * SPIx); -uint32_t SPI_INTRXOverflowStat(SPI_TypeDef * SPIx); - -void SPI_INTTXHalfFullEn(SPI_TypeDef * SPIx); -void SPI_INTTXHalfFullDis(SPI_TypeDef * SPIx); -void SPI_INTTXHalfFullClr(SPI_TypeDef * SPIx); -uint32_t SPI_INTTXHalfFullStat(SPI_TypeDef * SPIx); -void SPI_INTTXEmptyEn(SPI_TypeDef * SPIx); -void SPI_INTTXEmptyDis(SPI_TypeDef * SPIx); -void SPI_INTTXEmptyClr(SPI_TypeDef * SPIx); -uint32_t SPI_INTTXEmptyStat(SPI_TypeDef * SPIx); -void SPI_INTTXCompleteEn(SPI_TypeDef * SPIx); -void SPI_INTTXCompleteDis(SPI_TypeDef * SPIx); -void SPI_INTTXCompleteClr(SPI_TypeDef * SPIx); -uint32_t SPI_INTTXCompleteStat(SPI_TypeDef * SPIx); - -void SPI_INTTXWordCompleteEn(SPI_TypeDef * SPIx); -void SPI_INTTXWordCompleteDis(SPI_TypeDef * SPIx); -void SPI_INTTXWordCompleteClr(SPI_TypeDef * SPIx); -uint32_t SPI_INTTXWordCompleteStat(SPI_TypeDef * SPIx); +void SPI_INTTXHalfFullEn(SPI_TypeDef *SPIx); +void SPI_INTTXHalfFullDis(SPI_TypeDef *SPIx); +void SPI_INTTXHalfFullClr(SPI_TypeDef *SPIx); +uint32_t SPI_INTTXHalfFullStat(SPI_TypeDef *SPIx); +void SPI_INTTXEmptyEn(SPI_TypeDef *SPIx); +void SPI_INTTXEmptyDis(SPI_TypeDef *SPIx); +void SPI_INTTXEmptyClr(SPI_TypeDef *SPIx); +uint32_t SPI_INTTXEmptyStat(SPI_TypeDef *SPIx); +void SPI_INTTXCompleteEn(SPI_TypeDef *SPIx); +void SPI_INTTXCompleteDis(SPI_TypeDef *SPIx); +void SPI_INTTXCompleteClr(SPI_TypeDef *SPIx); +uint32_t SPI_INTTXCompleteStat(SPI_TypeDef *SPIx); +void SPI_INTTXWordCompleteEn(SPI_TypeDef *SPIx); +void SPI_INTTXWordCompleteDis(SPI_TypeDef *SPIx); +void SPI_INTTXWordCompleteClr(SPI_TypeDef *SPIx); +uint32_t SPI_INTTXWordCompleteStat(SPI_TypeDef *SPIx); #endif //__SWM320_SPI_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.c index 62e4c84eed..2818f5a8c1 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.c @@ -21,7 +21,6 @@ #include "SWM320.h" #include "SWM320_sram.h" - /****************************************************************************************************************************************** * 函数名称: SRAM_Init() * 功能说明: SRAM控制器初始化 @@ -29,25 +28,29 @@ * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void SRAM_Init(SRAM_InitStructure * initStruct) +void SRAM_Init(SRAM_InitStructure *initStruct) { - uint32_t i; - - // 配置SRAM前需要刷新下SDRAM控制器 - do { - SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); - - while(SDRAMC->REFDONE == 0); - SDRAMC->REFRESH &= ~(1 << SDRAMC_REFRESH_EN_Pos); - - for(i = 0; i < 1000; i++) __NOP(); - SYS->CLKEN &= ~(1 << SYS_CLKEN_SDRAM_Pos); - } while(0); - - SYS->CLKEN |= (1 << SYS_CLKEN_RAMC_Pos); - for(i = 0; i < 10; i++) __NOP(); - - SRAMC->CR = (initStruct->ClkDiv << SRAMC_CR_RWTIME_Pos) | - (initStruct->DataWidth << SRAMC_CR_BYTEIF_Pos) | - (0 << SRAMC_CR_HBLBDIS_Pos); // 使能字节、半字访问 + uint32_t i; + + // 配置SRAM前需要刷新下SDRAM控制器 + do + { + SYS->CLKEN |= (1 << SYS_CLKEN_SDRAM_Pos); + + while (SDRAMC->REFDONE == 0) + ; + SDRAMC->REFRESH &= ~(1 << SDRAMC_REFRESH_EN_Pos); + + for (i = 0; i < 1000; i++) + __NOP(); + SYS->CLKEN &= ~(1 << SYS_CLKEN_SDRAM_Pos); + } while (0); + + SYS->CLKEN |= (1 << SYS_CLKEN_RAMC_Pos); + for (i = 0; i < 10; i++) + __NOP(); + + SRAMC->CR = (initStruct->ClkDiv << SRAMC_CR_RWTIME_Pos) | + (initStruct->DataWidth << SRAMC_CR_BYTEIF_Pos) | + (0 << SRAMC_CR_HBLBDIS_Pos); // 使能字节、半字访问 } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.h index 799b271a99..ca3aa92dcc 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_sram.h @@ -1,31 +1,29 @@ #ifndef __SWM320_SRAM_H__ #define __SWM320_SRAM_H__ -typedef struct { - uint8_t ClkDiv; //SRAM_CLKDIV_5...SRAM_CLKDIV_16,根据SRAM芯片所能跑的最高频率选择合适分频 - uint8_t DataWidth; //SRAM_DATAWIDTH_8、SRAM_DATAWIDTH_16 +typedef struct +{ + uint8_t ClkDiv; //SRAM_CLKDIV_5...SRAM_CLKDIV_16,根据SRAM芯片所能跑的最高频率选择合适分频 + uint8_t DataWidth; //SRAM_DATAWIDTH_8、SRAM_DATAWIDTH_16 } SRAM_InitStructure; +#define SRAM_CLKDIV_4 3 +#define SRAM_CLKDIV_5 4 +#define SRAM_CLKDIV_6 5 +#define SRAM_CLKDIV_7 6 +#define SRAM_CLKDIV_8 7 +#define SRAM_CLKDIV_9 8 +#define SRAM_CLKDIV_10 9 +#define SRAM_CLKDIV_11 10 +#define SRAM_CLKDIV_12 11 +#define SRAM_CLKDIV_13 12 +#define SRAM_CLKDIV_14 13 +#define SRAM_CLKDIV_15 14 +#define SRAM_CLKDIV_16 15 -#define SRAM_CLKDIV_4 3 -#define SRAM_CLKDIV_5 4 -#define SRAM_CLKDIV_6 5 -#define SRAM_CLKDIV_7 6 -#define SRAM_CLKDIV_8 7 -#define SRAM_CLKDIV_9 8 -#define SRAM_CLKDIV_10 9 -#define SRAM_CLKDIV_11 10 -#define SRAM_CLKDIV_12 11 -#define SRAM_CLKDIV_13 12 -#define SRAM_CLKDIV_14 13 -#define SRAM_CLKDIV_15 14 -#define SRAM_CLKDIV_16 15 - -#define SRAM_DATAWIDTH_8 1 -#define SRAM_DATAWIDTH_16 0 - - -void SRAM_Init(SRAM_InitStructure * initStruct); +#define SRAM_DATAWIDTH_8 1 +#define SRAM_DATAWIDTH_16 0 +void SRAM_Init(SRAM_InitStructure *initStruct); #endif //__SWM320_SRAM_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.c index b67711a49a..1451037f0c 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.c @@ -21,7 +21,6 @@ #include "SWM320.h" #include "SWM320_timr.h" - /****************************************************************************************************************************************** * 函数名称: TIMR_Init() * 功能说明: TIMR定时器/计数器初始化 @@ -32,67 +31,73 @@ * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void TIMR_Init(TIMR_TypeDef * TIMRx, uint32_t mode, uint32_t period, uint32_t int_en) +void TIMR_Init(TIMR_TypeDef *TIMRx, uint32_t mode, uint32_t period, uint32_t int_en) { - SYS->CLKEN |= (0x01 << SYS_CLKEN_TIMR_Pos); - - TIMR_Stop(TIMRx); //一些关键寄存器只能在定时器停止时设置 - - TIMRx->CTRL &= ~TIMR_CTRL_CLKSRC_Msk; - TIMRx->CTRL |= mode << TIMR_CTRL_CLKSRC_Pos; - - TIMRx->LDVAL = period; - - switch((uint32_t)TIMRx) - { - case ((uint32_t)TIMR0): - TIMRG->IF = (1 << TIMRG_IF_TIMR0_Pos); //使能中断前清除中断标志 - TIMRG->IE &= ~TIMRG_IE_TIMR0_Msk; - TIMRG->IE |= (int_en << TIMRG_IE_TIMR0_Pos); - - if(int_en) NVIC_EnableIRQ(TIMR0_IRQn); - break; - - case ((uint32_t)TIMR1): - TIMRG->IF = (1 << TIMRG_IF_TIMR1_Pos); - TIMRG->IE &= ~TIMRG_IE_TIMR1_Msk; - TIMRG->IE |= (int_en << TIMRG_IE_TIMR1_Pos); - - if(int_en) NVIC_EnableIRQ(TIMR1_IRQn); - break; - - case ((uint32_t)TIMR2): - TIMRG->IF = (1 << TIMRG_IF_TIMR2_Pos); - TIMRG->IE &= ~TIMRG_IE_TIMR2_Msk; - TIMRG->IE |= (int_en << TIMRG_IE_TIMR2_Pos); - - if(int_en) NVIC_EnableIRQ(TIMR2_IRQn); - break; - - case ((uint32_t)TIMR3): - TIMRG->IF = (1 << TIMRG_IF_TIMR3_Pos); - TIMRG->IE &= ~TIMRG_IE_TIMR3_Msk; - TIMRG->IE |= (int_en << TIMRG_IE_TIMR3_Pos); - - if(int_en) NVIC_EnableIRQ(TIMR3_IRQn); - break; - - case ((uint32_t)TIMR4): - TIMRG->IF = (1 << TIMRG_IF_TIMR4_Pos); - TIMRG->IE &= ~TIMRG_IE_TIMR4_Msk; - TIMRG->IE |= (int_en << TIMRG_IE_TIMR4_Pos); - - if(int_en) NVIC_EnableIRQ(TIMR4_IRQn); - break; - - case ((uint32_t)TIMR5): - TIMRG->IF = (1 << TIMRG_IF_TIMR5_Pos); - TIMRG->IE &= ~TIMRG_IE_TIMR5_Msk; - TIMRG->IE |= (int_en << TIMRG_IE_TIMR5_Pos); - - if(int_en) NVIC_EnableIRQ(TIMR5_IRQn); - break; - } + SYS->CLKEN |= (0x01 << SYS_CLKEN_TIMR_Pos); + + TIMR_Stop(TIMRx); //一些关键寄存器只能在定时器停止时设置 + + TIMRx->CTRL &= ~TIMR_CTRL_CLKSRC_Msk; + TIMRx->CTRL |= mode << TIMR_CTRL_CLKSRC_Pos; + + TIMRx->LDVAL = period; + + switch ((uint32_t)TIMRx) + { + case ((uint32_t)TIMR0): + TIMRG->IF = (1 << TIMRG_IF_TIMR0_Pos); //使能中断前清除中断标志 + TIMRG->IE &= ~TIMRG_IE_TIMR0_Msk; + TIMRG->IE |= (int_en << TIMRG_IE_TIMR0_Pos); + + if (int_en) + NVIC_EnableIRQ(TIMR0_IRQn); + break; + + case ((uint32_t)TIMR1): + TIMRG->IF = (1 << TIMRG_IF_TIMR1_Pos); + TIMRG->IE &= ~TIMRG_IE_TIMR1_Msk; + TIMRG->IE |= (int_en << TIMRG_IE_TIMR1_Pos); + + if (int_en) + NVIC_EnableIRQ(TIMR1_IRQn); + break; + + case ((uint32_t)TIMR2): + TIMRG->IF = (1 << TIMRG_IF_TIMR2_Pos); + TIMRG->IE &= ~TIMRG_IE_TIMR2_Msk; + TIMRG->IE |= (int_en << TIMRG_IE_TIMR2_Pos); + + if (int_en) + NVIC_EnableIRQ(TIMR2_IRQn); + break; + + case ((uint32_t)TIMR3): + TIMRG->IF = (1 << TIMRG_IF_TIMR3_Pos); + TIMRG->IE &= ~TIMRG_IE_TIMR3_Msk; + TIMRG->IE |= (int_en << TIMRG_IE_TIMR3_Pos); + + if (int_en) + NVIC_EnableIRQ(TIMR3_IRQn); + break; + + case ((uint32_t)TIMR4): + TIMRG->IF = (1 << TIMRG_IF_TIMR4_Pos); + TIMRG->IE &= ~TIMRG_IE_TIMR4_Msk; + TIMRG->IE |= (int_en << TIMRG_IE_TIMR4_Pos); + + if (int_en) + NVIC_EnableIRQ(TIMR4_IRQn); + break; + + case ((uint32_t)TIMR5): + TIMRG->IF = (1 << TIMRG_IF_TIMR5_Pos); + TIMRG->IE &= ~TIMRG_IE_TIMR5_Msk; + TIMRG->IE |= (int_en << TIMRG_IE_TIMR5_Pos); + + if (int_en) + NVIC_EnableIRQ(TIMR5_IRQn); + break; + } } /****************************************************************************************************************************************** @@ -102,9 +107,9 @@ void TIMR_Init(TIMR_TypeDef * TIMRx, uint32_t mode, uint32_t period, uint32_t in * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void TIMR_Start(TIMR_TypeDef * TIMRx) +void TIMR_Start(TIMR_TypeDef *TIMRx) { - TIMRx->CTRL |= TIMR_CTRL_EN_Msk; + TIMRx->CTRL |= TIMR_CTRL_EN_Msk; } /****************************************************************************************************************************************** @@ -114,9 +119,9 @@ void TIMR_Start(TIMR_TypeDef * TIMRx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void TIMR_Stop(TIMR_TypeDef * TIMRx) +void TIMR_Stop(TIMR_TypeDef *TIMRx) { - TIMRx->CTRL &= ~TIMR_CTRL_EN_Msk; + TIMRx->CTRL &= ~TIMR_CTRL_EN_Msk; } /****************************************************************************************************************************************** @@ -126,34 +131,34 @@ void TIMR_Stop(TIMR_TypeDef * TIMRx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void TIMR_Halt(TIMR_TypeDef * TIMRx) +void TIMR_Halt(TIMR_TypeDef *TIMRx) { - switch((uint32_t)TIMRx) - { - case ((uint32_t)TIMR0): - TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR0_Pos); - break; - - case ((uint32_t)TIMR1): - TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR1_Pos); - break; - - case ((uint32_t)TIMR2): - TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR2_Pos); - break; - - case ((uint32_t)TIMR3): - TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR3_Pos); - break; - - case ((uint32_t)TIMR4): - TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR4_Pos); - break; - - case ((uint32_t)TIMR5): - TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR5_Pos); - break; - } + switch ((uint32_t)TIMRx) + { + case ((uint32_t)TIMR0): + TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR0_Pos); + break; + + case ((uint32_t)TIMR1): + TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR1_Pos); + break; + + case ((uint32_t)TIMR2): + TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR2_Pos); + break; + + case ((uint32_t)TIMR3): + TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR3_Pos); + break; + + case ((uint32_t)TIMR4): + TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR4_Pos); + break; + + case ((uint32_t)TIMR5): + TIMRG->HALT |= (0x01 << TIMRG_HALT_TIMR5_Pos); + break; + } } /****************************************************************************************************************************************** @@ -163,34 +168,34 @@ void TIMR_Halt(TIMR_TypeDef * TIMRx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void TIMR_Resume(TIMR_TypeDef * TIMRx) +void TIMR_Resume(TIMR_TypeDef *TIMRx) { - switch((uint32_t)TIMRx) - { - case ((uint32_t)TIMR0): - TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR0_Pos); - break; - - case ((uint32_t)TIMR1): - TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR1_Pos); - break; - - case ((uint32_t)TIMR2): - TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR2_Pos); - break; - - case ((uint32_t)TIMR3): - TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR3_Pos); - break; - - case ((uint32_t)TIMR4): - TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR4_Pos); - break; - - case ((uint32_t)TIMR5): - TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR5_Pos); - break; - } + switch ((uint32_t)TIMRx) + { + case ((uint32_t)TIMR0): + TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR0_Pos); + break; + + case ((uint32_t)TIMR1): + TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR1_Pos); + break; + + case ((uint32_t)TIMR2): + TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR2_Pos); + break; + + case ((uint32_t)TIMR3): + TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR3_Pos); + break; + + case ((uint32_t)TIMR4): + TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR4_Pos); + break; + + case ((uint32_t)TIMR5): + TIMRG->HALT &= ~(0x01 << TIMRG_HALT_TIMR5_Pos); + break; + } } /****************************************************************************************************************************************** @@ -201,9 +206,9 @@ void TIMR_Resume(TIMR_TypeDef * TIMRx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void TIMR_SetPeriod(TIMR_TypeDef * TIMRx, uint32_t period) +void TIMR_SetPeriod(TIMR_TypeDef *TIMRx, uint32_t period) { - TIMRx->LDVAL = period; + TIMRx->LDVAL = period; } /****************************************************************************************************************************************** @@ -213,9 +218,9 @@ void TIMR_SetPeriod(TIMR_TypeDef * TIMRx, uint32_t period) * 输 出: uint32_t 当前定时/计数周期 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t TIMR_GetPeriod(TIMR_TypeDef * TIMRx) +uint32_t TIMR_GetPeriod(TIMR_TypeDef *TIMRx) { - return TIMRx->LDVAL; + return TIMRx->LDVAL; } /****************************************************************************************************************************************** @@ -225,9 +230,9 @@ uint32_t TIMR_GetPeriod(TIMR_TypeDef * TIMRx) * 输 出: uint32_t 当前计数值 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t TIMR_GetCurValue(TIMR_TypeDef * TIMRx) +uint32_t TIMR_GetCurValue(TIMR_TypeDef *TIMRx) { - return TIMRx->CVAL; + return TIMRx->CVAL; } /****************************************************************************************************************************************** @@ -237,40 +242,40 @@ uint32_t TIMR_GetCurValue(TIMR_TypeDef * TIMRx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void TIMR_INTEn(TIMR_TypeDef * TIMRx) +void TIMR_INTEn(TIMR_TypeDef *TIMRx) { - switch((uint32_t)TIMRx) - { - case ((uint32_t)TIMR0): - TIMRG->IE |= (0x01 << TIMRG_IE_TIMR0_Pos); - NVIC_EnableIRQ(TIMR0_IRQn); - break; - - case ((uint32_t)TIMR1): - TIMRG->IE |= (0x01 << TIMRG_IE_TIMR1_Pos); - NVIC_EnableIRQ(TIMR1_IRQn); - break; - - case ((uint32_t)TIMR2): - TIMRG->IE |= (0x01 << TIMRG_IE_TIMR2_Pos); - NVIC_EnableIRQ(TIMR2_IRQn); - break; - - case ((uint32_t)TIMR3): - TIMRG->IE |= (0x01 << TIMRG_IE_TIMR3_Pos); - NVIC_EnableIRQ(TIMR3_IRQn); - break; - - case ((uint32_t)TIMR4): - TIMRG->IE |= (0x01 << TIMRG_IE_TIMR4_Pos); - NVIC_EnableIRQ(TIMR4_IRQn); - break; - - case ((uint32_t)TIMR5): - TIMRG->IE |= (0x01 << TIMRG_IE_TIMR5_Pos); - NVIC_EnableIRQ(TIMR5_IRQn); - break; - } + switch ((uint32_t)TIMRx) + { + case ((uint32_t)TIMR0): + TIMRG->IE |= (0x01 << TIMRG_IE_TIMR0_Pos); + NVIC_EnableIRQ(TIMR0_IRQn); + break; + + case ((uint32_t)TIMR1): + TIMRG->IE |= (0x01 << TIMRG_IE_TIMR1_Pos); + NVIC_EnableIRQ(TIMR1_IRQn); + break; + + case ((uint32_t)TIMR2): + TIMRG->IE |= (0x01 << TIMRG_IE_TIMR2_Pos); + NVIC_EnableIRQ(TIMR2_IRQn); + break; + + case ((uint32_t)TIMR3): + TIMRG->IE |= (0x01 << TIMRG_IE_TIMR3_Pos); + NVIC_EnableIRQ(TIMR3_IRQn); + break; + + case ((uint32_t)TIMR4): + TIMRG->IE |= (0x01 << TIMRG_IE_TIMR4_Pos); + NVIC_EnableIRQ(TIMR4_IRQn); + break; + + case ((uint32_t)TIMR5): + TIMRG->IE |= (0x01 << TIMRG_IE_TIMR5_Pos); + NVIC_EnableIRQ(TIMR5_IRQn); + break; + } } /****************************************************************************************************************************************** @@ -280,34 +285,34 @@ void TIMR_INTEn(TIMR_TypeDef * TIMRx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void TIMR_INTDis(TIMR_TypeDef * TIMRx) +void TIMR_INTDis(TIMR_TypeDef *TIMRx) { - switch((uint32_t)TIMRx) - { - case ((uint32_t)TIMR0): - TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR0_Pos); - break; - - case ((uint32_t)TIMR1): - TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR1_Pos); - break; - - case ((uint32_t)TIMR2): - TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR2_Pos); - break; - - case ((uint32_t)TIMR3): - TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR3_Pos); - break; - - case ((uint32_t)TIMR4): - TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR4_Pos); - break; - - case ((uint32_t)TIMR5): - TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR5_Pos); - break; - } + switch ((uint32_t)TIMRx) + { + case ((uint32_t)TIMR0): + TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR0_Pos); + break; + + case ((uint32_t)TIMR1): + TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR1_Pos); + break; + + case ((uint32_t)TIMR2): + TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR2_Pos); + break; + + case ((uint32_t)TIMR3): + TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR3_Pos); + break; + + case ((uint32_t)TIMR4): + TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR4_Pos); + break; + + case ((uint32_t)TIMR5): + TIMRG->IE &= ~(0x01 << TIMRG_IE_TIMR5_Pos); + break; + } } /****************************************************************************************************************************************** @@ -317,34 +322,34 @@ void TIMR_INTDis(TIMR_TypeDef * TIMRx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void TIMR_INTClr(TIMR_TypeDef * TIMRx) +void TIMR_INTClr(TIMR_TypeDef *TIMRx) { - switch((uint32_t)TIMRx) - { - case ((uint32_t)TIMR0): - TIMRG->IF = (0x01 << TIMRG_IF_TIMR0_Pos); - break; - - case ((uint32_t)TIMR1): - TIMRG->IF = (0x01 << TIMRG_IF_TIMR1_Pos); - break; - - case ((uint32_t)TIMR2): - TIMRG->IF = (0x01 << TIMRG_IF_TIMR2_Pos); - break; - - case ((uint32_t)TIMR3): - TIMRG->IF = (0x01 << TIMRG_IF_TIMR3_Pos); - break; - - case ((uint32_t)TIMR4): - TIMRG->IF = (0x01 << TIMRG_IF_TIMR4_Pos); - break; - - case ((uint32_t)TIMR5): - TIMRG->IF = (0x01 << TIMRG_IF_TIMR5_Pos); - break; - } + switch ((uint32_t)TIMRx) + { + case ((uint32_t)TIMR0): + TIMRG->IF = (0x01 << TIMRG_IF_TIMR0_Pos); + break; + + case ((uint32_t)TIMR1): + TIMRG->IF = (0x01 << TIMRG_IF_TIMR1_Pos); + break; + + case ((uint32_t)TIMR2): + TIMRG->IF = (0x01 << TIMRG_IF_TIMR2_Pos); + break; + + case ((uint32_t)TIMR3): + TIMRG->IF = (0x01 << TIMRG_IF_TIMR3_Pos); + break; + + case ((uint32_t)TIMR4): + TIMRG->IF = (0x01 << TIMRG_IF_TIMR4_Pos); + break; + + case ((uint32_t)TIMR5): + TIMRG->IF = (0x01 << TIMRG_IF_TIMR5_Pos); + break; + } } /****************************************************************************************************************************************** @@ -354,32 +359,31 @@ void TIMR_INTClr(TIMR_TypeDef * TIMRx) * 输 出: uint32_t 0 TIMRx未产生中断 1 TIMRx产生了中断 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t TIMR_INTStat(TIMR_TypeDef * TIMRx) +uint32_t TIMR_INTStat(TIMR_TypeDef *TIMRx) { - switch((uint32_t)TIMRx) - { - case ((uint32_t)TIMR0): - return (TIMRG->IF & TIMRG_IF_TIMR0_Msk) ? 1 : 0; - - case ((uint32_t)TIMR1): - return (TIMRG->IF & TIMRG_IF_TIMR1_Msk) ? 1 : 0; - - case ((uint32_t)TIMR2): - return (TIMRG->IF & TIMRG_IF_TIMR2_Msk) ? 1 : 0; - - case ((uint32_t)TIMR3): - return (TIMRG->IF & TIMRG_IF_TIMR3_Msk) ? 1 : 0; - - case ((uint32_t)TIMR4): - return (TIMRG->IF & TIMRG_IF_TIMR4_Msk) ? 1 : 0; - - case ((uint32_t)TIMR5): - return (TIMRG->IF & TIMRG_IF_TIMR5_Msk) ? 1 : 0; - } - - return 0; -} + switch ((uint32_t)TIMRx) + { + case ((uint32_t)TIMR0): + return (TIMRG->IF & TIMRG_IF_TIMR0_Msk) ? 1 : 0; + case ((uint32_t)TIMR1): + return (TIMRG->IF & TIMRG_IF_TIMR1_Msk) ? 1 : 0; + + case ((uint32_t)TIMR2): + return (TIMRG->IF & TIMRG_IF_TIMR2_Msk) ? 1 : 0; + + case ((uint32_t)TIMR3): + return (TIMRG->IF & TIMRG_IF_TIMR3_Msk) ? 1 : 0; + + case ((uint32_t)TIMR4): + return (TIMRG->IF & TIMRG_IF_TIMR4_Msk) ? 1 : 0; + + case ((uint32_t)TIMR5): + return (TIMRG->IF & TIMRG_IF_TIMR5_Msk) ? 1 : 0; + } + + return 0; +} /****************************************************************************************************************************************** * 函数名称: Pulse_Init() @@ -390,16 +394,17 @@ uint32_t TIMR_INTStat(TIMR_TypeDef * TIMRx) * 注意事项: 无 ******************************************************************************************************************************************/ void Pulse_Init(uint32_t pulse, uint32_t int_en) -{ - SYS->CLKEN |= (0x01 << SYS_CLKEN_TIMR_Pos); - - TIMRG->PCTRL = (0 << TIMRG_PCTRL_CLKSRC_Pos) | // 系统时钟作为时钟源 - (pulse << TIMRG_PCTRL_HIGH_Pos) | - (0 << TIMRG_PCTRL_EN_Pos); - - TIMRG->IE |= (1 << TIMRG_IE_PULSE_Pos); //使能才能查询中断标志 - - if(int_en) NVIC_EnableIRQ(PULSE_IRQn); +{ + SYS->CLKEN |= (0x01 << SYS_CLKEN_TIMR_Pos); + + TIMRG->PCTRL = (0 << TIMRG_PCTRL_CLKSRC_Pos) | // 系统时钟作为时钟源 + (pulse << TIMRG_PCTRL_HIGH_Pos) | + (0 << TIMRG_PCTRL_EN_Pos); + + TIMRG->IE |= (1 << TIMRG_IE_PULSE_Pos); //使能才能查询中断标志 + + if (int_en) + NVIC_EnableIRQ(PULSE_IRQn); } /****************************************************************************************************************************************** @@ -410,8 +415,8 @@ void Pulse_Init(uint32_t pulse, uint32_t int_en) * 注意事项: 无 ******************************************************************************************************************************************/ void Pulse_Start(void) -{ - TIMRG->PCTRL |= (1 << TIMRG_PCTRL_EN_Pos); +{ + TIMRG->PCTRL |= (1 << TIMRG_PCTRL_EN_Pos); } /****************************************************************************************************************************************** @@ -423,14 +428,14 @@ void Pulse_Start(void) ******************************************************************************************************************************************/ uint32_t Pulse_Done(void) { - if(TIMRG->IF & TIMRG_IF_PULSE_Msk) - { - TIMRG->IF = TIMRG_IF_PULSE_Msk; // 清除中断标志 - - return 1; - } - else - { - return 0; - } + if (TIMRG->IF & TIMRG_IF_PULSE_Msk) + { + TIMRG->IF = TIMRG_IF_PULSE_Msk; // 清除中断标志 + + return 1; + } + else + { + return 0; + } } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.h index 5cfdce204d..38eaffacd8 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_timr.h @@ -1,32 +1,29 @@ #ifndef __SWM320_TIMR_H__ #define __SWM320_TIMR_H__ -#define TIMR_MODE_TIMER 0 -#define TIMR_MODE_COUNTER 1 +#define TIMR_MODE_TIMER 0 +#define TIMR_MODE_COUNTER 1 -void TIMR_Init(TIMR_TypeDef * TIMRx, uint32_t mode, uint32_t period, uint32_t int_en); //定时器/计数器初始化 -void TIMR_Start(TIMR_TypeDef * TIMRx); //启动定时器,从初始值开始计时/计数 -void TIMR_Stop(TIMR_TypeDef * TIMRx); //停止定时器 -void TIMR_Halt(TIMR_TypeDef * TIMRx); //暂停定时器,计数值保持不变 -void TIMR_Resume(TIMR_TypeDef * TIMRx); //恢复定时器,从暂停处继续计数 +void TIMR_Init(TIMR_TypeDef *TIMRx, uint32_t mode, uint32_t period, uint32_t int_en); //定时器/计数器初始化 +void TIMR_Start(TIMR_TypeDef *TIMRx); //启动定时器,从初始值开始计时/计数 +void TIMR_Stop(TIMR_TypeDef *TIMRx); //停止定时器 +void TIMR_Halt(TIMR_TypeDef *TIMRx); //暂停定时器,计数值保持不变 +void TIMR_Resume(TIMR_TypeDef *TIMRx); //恢复定时器,从暂停处继续计数 -void TIMR_SetPeriod(TIMR_TypeDef * TIMRx, uint32_t period); //设置定时/计数周期 -uint32_t TIMR_GetPeriod(TIMR_TypeDef * TIMRx); //获取定时/计数周期 -uint32_t TIMR_GetCurValue(TIMR_TypeDef * TIMRx); //获取当前计数值 +void TIMR_SetPeriod(TIMR_TypeDef *TIMRx, uint32_t period); //设置定时/计数周期 +uint32_t TIMR_GetPeriod(TIMR_TypeDef *TIMRx); //获取定时/计数周期 +uint32_t TIMR_GetCurValue(TIMR_TypeDef *TIMRx); //获取当前计数值 -void TIMR_INTEn(TIMR_TypeDef * TIMRx); //使能中断 -void TIMR_INTDis(TIMR_TypeDef * TIMRx); //禁能中断 -void TIMR_INTClr(TIMR_TypeDef * TIMRx); //清除中断标志 -uint32_t TIMR_INTStat(TIMR_TypeDef * TIMRx); //获取中断状态 +void TIMR_INTEn(TIMR_TypeDef *TIMRx); //使能中断 +void TIMR_INTDis(TIMR_TypeDef *TIMRx); //禁能中断 +void TIMR_INTClr(TIMR_TypeDef *TIMRx); //清除中断标志 +uint32_t TIMR_INTStat(TIMR_TypeDef *TIMRx); //获取中断状态 - - -#define PULSE_LOW 0 -#define PULSE_HIGH 1 +#define PULSE_LOW 0 +#define PULSE_HIGH 1 void Pulse_Init(uint32_t pulse, uint32_t int_en); void Pulse_Start(void); uint32_t Pulse_Done(void); - #endif //__SWM320_TIMR_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.c index 73f219f7aa..721184fd94 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.c @@ -21,7 +21,6 @@ #include "SWM320.h" #include "SWM320_uart.h" - /****************************************************************************************************************************************** * 函数名称: UART_Init() * 功能说明: UART串口初始化 @@ -30,106 +29,114 @@ * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_Init(UART_TypeDef * UARTx, UART_InitStructure * initStruct) -{ - switch((uint32_t)UARTx) - { - case ((uint32_t)UART0): - SYS->CLKEN |= (0x01 << SYS_CLKEN_UART0_Pos); - break; - - case ((uint32_t)UART1): - SYS->CLKEN |= (0x01 << SYS_CLKEN_UART1_Pos); - break; - - case ((uint32_t)UART2): - SYS->CLKEN |= (0x01 << SYS_CLKEN_UART2_Pos); - break; - - case ((uint32_t)UART3): - SYS->CLKEN |= (0x01 << SYS_CLKEN_UART3_Pos); - break; - } - - UART_Close(UARTx); //一些关键寄存器只能在串口关闭时设置 - - UARTx->CTRL |= (0x01 << UART_CTRL_BAUDEN_Pos); - UARTx->BAUD &= ~UART_BAUD_BAUD_Msk; - UARTx->BAUD |= ((SystemCoreClock/16/initStruct->Baudrate - 1) << UART_BAUD_BAUD_Pos); - - UARTx->CTRL &= ~(UART_CTRL_DATA9b_Msk | UART_CTRL_PARITY_Msk | UART_CTRL_STOP2b_Msk); - UARTx->CTRL |= (initStruct->DataBits << UART_CTRL_DATA9b_Pos) | - (initStruct->Parity << UART_CTRL_PARITY_Pos) | - (initStruct->StopBits << UART_CTRL_STOP2b_Pos); - - /* 在SWM320中,当 RXLVL >= RXTHR 时触发中断,如果RXTHR设置为0的话,在未接收到数据时就会一直触发中断; +void UART_Init(UART_TypeDef *UARTx, UART_InitStructure *initStruct) +{ + switch ((uint32_t)UARTx) + { + case ((uint32_t)UART0): + SYS->CLKEN |= (0x01 << SYS_CLKEN_UART0_Pos); + break; + + case ((uint32_t)UART1): + SYS->CLKEN |= (0x01 << SYS_CLKEN_UART1_Pos); + break; + + case ((uint32_t)UART2): + SYS->CLKEN |= (0x01 << SYS_CLKEN_UART2_Pos); + break; + + case ((uint32_t)UART3): + SYS->CLKEN |= (0x01 << SYS_CLKEN_UART3_Pos); + break; + } + + UART_Close(UARTx); //一些关键寄存器只能在串口关闭时设置 + + UARTx->CTRL |= (0x01 << UART_CTRL_BAUDEN_Pos); + UARTx->BAUD &= ~UART_BAUD_BAUD_Msk; + UARTx->BAUD |= ((SystemCoreClock / 16 / initStruct->Baudrate - 1) << UART_BAUD_BAUD_Pos); + + UARTx->CTRL &= ~(UART_CTRL_DATA9b_Msk | UART_CTRL_PARITY_Msk | UART_CTRL_STOP2b_Msk); + UARTx->CTRL |= (initStruct->DataBits << UART_CTRL_DATA9b_Pos) | + (initStruct->Parity << UART_CTRL_PARITY_Pos) | + (initStruct->StopBits << UART_CTRL_STOP2b_Pos); + + /* 在SWM320中,当 RXLVL >= RXTHR 时触发中断,如果RXTHR设置为0的话,在未接收到数据时就会一直触发中断; 其他芯片中,当 RXLVL > RXTHR 时触发中断,为解决SWM320中RXTHR不能为0的问题,并统一库函数API,这里将RXTHR设置值加一 */ - switch((uint32_t)UARTx) // 软件复位不能清零 NVIC 寄存器,若不手动清除,下面的代码清零 RXTHR 时会导致一直进入 ISR + switch ((uint32_t)UARTx) // 软件复位不能清零 NVIC 寄存器,若不手动清除,下面的代码清零 RXTHR 时会导致一直进入 ISR { - case ((uint32_t)UART0): NVIC_DisableIRQ(UART0_IRQn); break; - case ((uint32_t)UART1): NVIC_DisableIRQ(UART1_IRQn); break; - case ((uint32_t)UART2): NVIC_DisableIRQ(UART2_IRQn); break; - case ((uint32_t)UART3): NVIC_DisableIRQ(UART3_IRQn); break; + case ((uint32_t)UART0): + NVIC_DisableIRQ(UART0_IRQn); + break; + case ((uint32_t)UART1): + NVIC_DisableIRQ(UART1_IRQn); + break; + case ((uint32_t)UART2): + NVIC_DisableIRQ(UART2_IRQn); + break; + case ((uint32_t)UART3): + NVIC_DisableIRQ(UART3_IRQn); + break; + } + UARTx->FIFO &= ~(UART_FIFO_RXTHR_Msk | UART_FIFO_TXTHR_Msk); + UARTx->FIFO |= ((initStruct->RXThreshold + 1) << UART_FIFO_RXTHR_Pos) | + (initStruct->TXThreshold << UART_FIFO_TXTHR_Pos); + + UARTx->CTRL &= ~UART_CTRL_TOTIME_Msk; + UARTx->CTRL |= (initStruct->TimeoutTime << UART_CTRL_TOTIME_Pos); + + UARTx->CTRL &= ~(UART_CTRL_RXIE_Msk | UART_CTRL_TXIE_Msk | UART_CTRL_TOIE_Msk); + UARTx->CTRL |= (initStruct->RXThresholdIEn << UART_CTRL_RXIE_Pos) | + (initStruct->TXThresholdIEn << UART_CTRL_TXIE_Pos) | + (initStruct->TimeoutIEn << UART_CTRL_TOIE_Pos); + + switch ((uint32_t)UARTx) + { + case ((uint32_t)UART0): + if (initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TimeoutIEn) + { + NVIC_EnableIRQ(UART0_IRQn); + } + else + { + NVIC_DisableIRQ(UART0_IRQn); + } + break; + + case ((uint32_t)UART1): + if (initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TimeoutIEn) + { + NVIC_EnableIRQ(UART1_IRQn); + } + else + { + NVIC_DisableIRQ(UART1_IRQn); + } + break; + + case ((uint32_t)UART2): + if (initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TimeoutIEn) + { + NVIC_EnableIRQ(UART2_IRQn); + } + else + { + NVIC_DisableIRQ(UART2_IRQn); + } + break; + + case ((uint32_t)UART3): + if (initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TimeoutIEn) + { + NVIC_EnableIRQ(UART3_IRQn); + } + else + { + NVIC_DisableIRQ(UART3_IRQn); + } + break; } - UARTx->FIFO &= ~(UART_FIFO_RXTHR_Msk | UART_FIFO_TXTHR_Msk); - UARTx->FIFO |= ((initStruct->RXThreshold + 1) << UART_FIFO_RXTHR_Pos) | - (initStruct->TXThreshold << UART_FIFO_TXTHR_Pos); - - UARTx->CTRL &= ~UART_CTRL_TOTIME_Msk; - UARTx->CTRL |= (initStruct->TimeoutTime << UART_CTRL_TOTIME_Pos); - - UARTx->CTRL &= ~(UART_CTRL_RXIE_Msk | UART_CTRL_TXIE_Msk | UART_CTRL_TOIE_Msk); - UARTx->CTRL |= (initStruct->RXThresholdIEn << UART_CTRL_RXIE_Pos) | - (initStruct->TXThresholdIEn << UART_CTRL_TXIE_Pos) | - (initStruct->TimeoutIEn << UART_CTRL_TOIE_Pos); - - switch((uint32_t)UARTx) - { - case ((uint32_t)UART0): - if(initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TimeoutIEn) - { - NVIC_EnableIRQ(UART0_IRQn); - } - else - { - NVIC_DisableIRQ(UART0_IRQn); - } - break; - - case ((uint32_t)UART1): - if(initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TimeoutIEn) - { - NVIC_EnableIRQ(UART1_IRQn); - } - else - { - NVIC_DisableIRQ(UART1_IRQn); - } - break; - - case ((uint32_t)UART2): - if(initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TimeoutIEn) - { - NVIC_EnableIRQ(UART2_IRQn); - } - else - { - NVIC_DisableIRQ(UART2_IRQn); - } - break; - - case ((uint32_t)UART3): - if(initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TimeoutIEn) - { - NVIC_EnableIRQ(UART3_IRQn); - } - else - { - NVIC_DisableIRQ(UART3_IRQn); - } - break; - } } /****************************************************************************************************************************************** @@ -139,9 +146,9 @@ void UART_Init(UART_TypeDef * UARTx, UART_InitStructure * initStruct) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_Open(UART_TypeDef * UARTx) +void UART_Open(UART_TypeDef *UARTx) { - UARTx->CTRL |= (0x01 << UART_CTRL_EN_Pos); + UARTx->CTRL |= (0x01 << UART_CTRL_EN_Pos); } /****************************************************************************************************************************************** @@ -151,9 +158,9 @@ void UART_Open(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_Close(UART_TypeDef * UARTx) +void UART_Close(UART_TypeDef *UARTx) { - UARTx->CTRL &= ~(0x01 << UART_CTRL_EN_Pos); + UARTx->CTRL &= ~(0x01 << UART_CTRL_EN_Pos); } /****************************************************************************************************************************************** @@ -164,9 +171,9 @@ void UART_Close(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_WriteByte(UART_TypeDef * UARTx, uint32_t data) +void UART_WriteByte(UART_TypeDef *UARTx, uint32_t data) { - UARTx->DATA = data; + UARTx->DATA = data; } /****************************************************************************************************************************************** @@ -177,15 +184,16 @@ void UART_WriteByte(UART_TypeDef * UARTx, uint32_t data) * 输 出: uint32_t 0 无错误 UART_ERR_PARITY 奇偶校验错误 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_ReadByte(UART_TypeDef * UARTx, uint32_t * data) +uint32_t UART_ReadByte(UART_TypeDef *UARTx, uint32_t *data) { - uint32_t reg = UARTx->DATA; - - *data = (reg & UART_DATA_DATA_Msk); - - if(reg & UART_DATA_PAERR_Msk) return UART_ERR_PARITY; - - return 0; + uint32_t reg = UARTx->DATA; + + *data = (reg & UART_DATA_DATA_Msk); + + if (reg & UART_DATA_PAERR_Msk) + return UART_ERR_PARITY; + + return 0; } /****************************************************************************************************************************************** @@ -195,9 +203,9 @@ uint32_t UART_ReadByte(UART_TypeDef * UARTx, uint32_t * data) * 输 出: uint32_t 1 UART正在发送数据 0 数据已发完 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_IsTXBusy(UART_TypeDef * UARTx) +uint32_t UART_IsTXBusy(UART_TypeDef *UARTx) { - return (UARTx->CTRL & UART_CTRL_TXIDLE_Msk) ? 0 : 1; + return (UARTx->CTRL & UART_CTRL_TXIDLE_Msk) ? 0 : 1; } /****************************************************************************************************************************************** @@ -207,9 +215,9 @@ uint32_t UART_IsTXBusy(UART_TypeDef * UARTx) * 输 出: uint32_t 1 接收FIFO空 0 接收FIFO非空 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_IsRXFIFOEmpty(UART_TypeDef * UARTx) +uint32_t UART_IsRXFIFOEmpty(UART_TypeDef *UARTx) { - return (UARTx->CTRL & UART_CTRL_RXNE_Msk) ? 0 : 1; + return (UARTx->CTRL & UART_CTRL_RXNE_Msk) ? 0 : 1; } /****************************************************************************************************************************************** @@ -219,9 +227,9 @@ uint32_t UART_IsRXFIFOEmpty(UART_TypeDef * UARTx) * 输 出: uint32_t 1 发送FIFO满 0 发送FIFO不满 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_IsTXFIFOFull(UART_TypeDef * UARTx) +uint32_t UART_IsTXFIFOFull(UART_TypeDef *UARTx) { - return (UARTx->CTRL & UART_CTRL_TXFF_Msk) ? 1 : 0; + return (UARTx->CTRL & UART_CTRL_TXFF_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -232,10 +240,10 @@ uint32_t UART_IsTXFIFOFull(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 不要在串口工作时更改波特率,使用此函数前请先调用UART_Close()关闭串口 ******************************************************************************************************************************************/ -void UART_SetBaudrate(UART_TypeDef * UARTx, uint32_t baudrate) +void UART_SetBaudrate(UART_TypeDef *UARTx, uint32_t baudrate) { - UARTx->BAUD &= ~UART_BAUD_BAUD_Msk; - UARTx->BAUD |= ((SystemCoreClock/16/baudrate - 1) << UART_BAUD_BAUD_Pos); + UARTx->BAUD &= ~UART_BAUD_BAUD_Msk; + UARTx->BAUD |= ((SystemCoreClock / 16 / baudrate - 1) << UART_BAUD_BAUD_Pos); } /****************************************************************************************************************************************** @@ -245,9 +253,9 @@ void UART_SetBaudrate(UART_TypeDef * UARTx, uint32_t baudrate) * 输 出: uint32_t 当前波特率 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_GetBaudrate(UART_TypeDef * UARTx) +uint32_t UART_GetBaudrate(UART_TypeDef *UARTx) { - return SystemCoreClock/16/(((UARTx->BAUD & UART_BAUD_BAUD_Msk) >> UART_BAUD_BAUD_Pos) + 1); + return SystemCoreClock / 16 / (((UARTx->BAUD & UART_BAUD_BAUD_Msk) >> UART_BAUD_BAUD_Pos) + 1); } /****************************************************************************************************************************************** @@ -259,11 +267,11 @@ uint32_t UART_GetBaudrate(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_CTSConfig(UART_TypeDef * UARTx, uint32_t enable, uint32_t polarity) +void UART_CTSConfig(UART_TypeDef *UARTx, uint32_t enable, uint32_t polarity) { - UARTx->CTSCR &= ~(UART_CTSCR_EN_Msk | UART_CTSCR_POL_Msk); - UARTx->CTSCR |= (enable << UART_CTSCR_EN_Pos) | - (polarity << UART_CTSCR_POL_Pos); + UARTx->CTSCR &= ~(UART_CTSCR_EN_Msk | UART_CTSCR_POL_Msk); + UARTx->CTSCR |= (enable << UART_CTSCR_EN_Pos) | + (polarity << UART_CTSCR_POL_Pos); } /****************************************************************************************************************************************** @@ -273,9 +281,9 @@ void UART_CTSConfig(UART_TypeDef * UARTx, uint32_t enable, uint32_t polarity) * 输 出: uint32_t 0 CTS线当前为低电平 1 CTS线当前为高电平 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_CTSLineState(UART_TypeDef * UARTx) +uint32_t UART_CTSLineState(UART_TypeDef *UARTx) { - return (UARTx->CTSCR & UART_CTSCR_STAT_Msk) ? 1 : 0; + return (UARTx->CTSCR & UART_CTSCR_STAT_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -288,12 +296,12 @@ uint32_t UART_CTSLineState(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_RTSConfig(UART_TypeDef * UARTx, uint32_t enable, uint32_t polarity, uint32_t threshold) +void UART_RTSConfig(UART_TypeDef *UARTx, uint32_t enable, uint32_t polarity, uint32_t threshold) { - UARTx->RTSCR &= ~(UART_RTSCR_EN_Msk | UART_RTSCR_POL_Msk | UART_RTSCR_THR_Msk); - UARTx->RTSCR |= (enable << UART_RTSCR_EN_Pos) | - (polarity << UART_RTSCR_POL_Pos) | - (threshold << UART_RTSCR_THR_Pos); + UARTx->RTSCR &= ~(UART_RTSCR_EN_Msk | UART_RTSCR_POL_Msk | UART_RTSCR_THR_Msk); + UARTx->RTSCR |= (enable << UART_RTSCR_EN_Pos) | + (polarity << UART_RTSCR_POL_Pos) | + (threshold << UART_RTSCR_THR_Pos); } /****************************************************************************************************************************************** @@ -303,9 +311,9 @@ void UART_RTSConfig(UART_TypeDef * UARTx, uint32_t enable, uint32_t polarity, ui * 输 出: uint32_t 0 RTS线当前为低电平 1 RTS线当前为高电平 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_RTSLineState(UART_TypeDef * UARTx) +uint32_t UART_RTSLineState(UART_TypeDef *UARTx) { - return (UARTx->RTSCR & UART_RTSCR_STAT_Msk) ? 1 : 0; + return (UARTx->RTSCR & UART_RTSCR_STAT_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -317,11 +325,11 @@ uint32_t UART_RTSLineState(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_LINConfig(UART_TypeDef * UARTx, uint32_t detectedIEn, uint32_t generatedIEn) +void UART_LINConfig(UART_TypeDef *UARTx, uint32_t detectedIEn, uint32_t generatedIEn) { - UARTx->LINCR &= ~(UART_LINCR_BRKDETIE_Msk | UART_LINCR_GENBRKIE_Msk); - UARTx->LINCR |= (detectedIEn << UART_LINCR_BRKDETIE_Pos) | - (generatedIEn << UART_LINCR_GENBRKIE_Pos); + UARTx->LINCR &= ~(UART_LINCR_BRKDETIE_Msk | UART_LINCR_GENBRKIE_Msk); + UARTx->LINCR |= (detectedIEn << UART_LINCR_BRKDETIE_Pos) | + (generatedIEn << UART_LINCR_GENBRKIE_Pos); } /****************************************************************************************************************************************** @@ -331,9 +339,9 @@ void UART_LINConfig(UART_TypeDef * UARTx, uint32_t detectedIEn, uint32_t generat * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_LINGenerate(UART_TypeDef * UARTx) +void UART_LINGenerate(UART_TypeDef *UARTx) { - UARTx->LINCR |= (1 << UART_LINCR_GENBRK_Pos); + UARTx->LINCR |= (1 << UART_LINCR_GENBRK_Pos); } /****************************************************************************************************************************************** @@ -343,9 +351,9 @@ void UART_LINGenerate(UART_TypeDef * UARTx) * 输 出: uint32_t 1 检测到LIN Break 0 未检测到LIN Break * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_LINIsDetected(UART_TypeDef * UARTx) +uint32_t UART_LINIsDetected(UART_TypeDef *UARTx) { - return (UARTx->LINCR & UART_LINCR_BRKDETIF_Msk) ? 1 : 0; + return (UARTx->LINCR & UART_LINCR_BRKDETIF_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -355,9 +363,9 @@ uint32_t UART_LINIsDetected(UART_TypeDef * UARTx) * 输 出: uint32_t 1 LIN Break 发送完成 0 LIN Break发送未完成 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_LINIsGenerated(UART_TypeDef * UARTx) +uint32_t UART_LINIsGenerated(UART_TypeDef *UARTx) { - return (UARTx->LINCR & UART_LINCR_GENBRKIF_Msk) ? 1 : 0; + return (UARTx->LINCR & UART_LINCR_GENBRKIF_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -370,19 +378,25 @@ uint32_t UART_LINIsGenerated(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 自动波特率检测时不能开启奇偶校验 ******************************************************************************************************************************************/ -void UART_ABRStart(UART_TypeDef * UARTx, uint32_t detectChar) +void UART_ABRStart(UART_TypeDef *UARTx, uint32_t detectChar) { - uint32_t bits; - - if((detectChar == 0xFF) || (detectChar == 0x1FF)) bits = 0; - else if((detectChar == 0xFE) || (detectChar == 0x1FE)) bits = 1; - else if((detectChar == 0xF8) || (detectChar == 0x1F8)) bits = 2; - else if((detectChar == 0x80) || (detectChar == 0x180)) bits = 3; - else while(1); - - UARTx->BAUD &= ~(UART_BAUD_ABREN_Msk | UART_BAUD_ABRBIT_Msk); - UARTx->BAUD |= (1 << UART_BAUD_ABREN_Pos) | - (bits << UART_BAUD_ABRBIT_Pos); + uint32_t bits; + + if ((detectChar == 0xFF) || (detectChar == 0x1FF)) + bits = 0; + else if ((detectChar == 0xFE) || (detectChar == 0x1FE)) + bits = 1; + else if ((detectChar == 0xF8) || (detectChar == 0x1F8)) + bits = 2; + else if ((detectChar == 0x80) || (detectChar == 0x180)) + bits = 3; + else + while (1) + ; + + UARTx->BAUD &= ~(UART_BAUD_ABREN_Msk | UART_BAUD_ABRBIT_Msk); + UARTx->BAUD |= (1 << UART_BAUD_ABREN_Pos) | + (bits << UART_BAUD_ABRBIT_Pos); } /****************************************************************************************************************************************** @@ -392,20 +406,20 @@ void UART_ABRStart(UART_TypeDef * UARTx, uint32_t detectChar) * 输 出: uint32_t 0 未完成 UART_ABR_RES_OK 已完成,且成功 UART_ABR_RES_ERR 已完成,但失败、出错 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_ABRIsDone(UART_TypeDef * UARTx) +uint32_t UART_ABRIsDone(UART_TypeDef *UARTx) { - if(UARTx->BAUD & UART_BAUD_ABREN_Msk) - { - return 0; - } - else if(UARTx->BAUD & UART_BAUD_ABRERR_Msk) - { - return UART_ABR_RES_ERR; - } - else - { - return UART_ABR_RES_OK; - } + if (UARTx->BAUD & UART_BAUD_ABREN_Msk) + { + return 0; + } + else if (UARTx->BAUD & UART_BAUD_ABRERR_Msk) + { + return UART_ABR_RES_ERR; + } + else + { + return UART_ABR_RES_OK; + } } /****************************************************************************************************************************************** @@ -415,9 +429,9 @@ uint32_t UART_ABRIsDone(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_INTRXThresholdEn(UART_TypeDef * UARTx) +void UART_INTRXThresholdEn(UART_TypeDef *UARTx) { - UARTx->CTRL |= (0x01 << UART_CTRL_RXIE_Pos); + UARTx->CTRL |= (0x01 << UART_CTRL_RXIE_Pos); } /****************************************************************************************************************************************** @@ -427,9 +441,9 @@ void UART_INTRXThresholdEn(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_INTRXThresholdDis(UART_TypeDef * UARTx) +void UART_INTRXThresholdDis(UART_TypeDef *UARTx) { - UARTx->CTRL &= ~(0x01 << UART_CTRL_RXIE_Pos); + UARTx->CTRL &= ~(0x01 << UART_CTRL_RXIE_Pos); } /****************************************************************************************************************************************** @@ -439,9 +453,9 @@ void UART_INTRXThresholdDis(UART_TypeDef * UARTx) * 输 出: uint32_t 1 RX FIFO中数据个数 >= RXThreshold 0 RX FIFO中数据个数 < RXThreshold * 注意事项: RXIF = RXTHRF & RXIE ******************************************************************************************************************************************/ -uint32_t UART_INTRXThresholdStat(UART_TypeDef * UARTx) +uint32_t UART_INTRXThresholdStat(UART_TypeDef *UARTx) { - return (UARTx->BAUD & UART_BAUD_RXIF_Msk) ? 1 : 0; + return (UARTx->BAUD & UART_BAUD_RXIF_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -451,9 +465,9 @@ uint32_t UART_INTRXThresholdStat(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_INTTXThresholdEn(UART_TypeDef * UARTx) +void UART_INTTXThresholdEn(UART_TypeDef *UARTx) { - UARTx->CTRL |= (0x01 << UART_CTRL_TXIE_Pos); + UARTx->CTRL |= (0x01 << UART_CTRL_TXIE_Pos); } /****************************************************************************************************************************************** @@ -463,9 +477,9 @@ void UART_INTTXThresholdEn(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_INTTXThresholdDis(UART_TypeDef * UARTx) +void UART_INTTXThresholdDis(UART_TypeDef *UARTx) { - UARTx->CTRL &= ~(0x01 << UART_CTRL_TXIE_Pos); + UARTx->CTRL &= ~(0x01 << UART_CTRL_TXIE_Pos); } /****************************************************************************************************************************************** @@ -475,9 +489,9 @@ void UART_INTTXThresholdDis(UART_TypeDef * UARTx) * 输 出: uint32_t 1 TX FIFO中数据个数 <= TXThreshold 0 TX FIFO中数据个数 > TXThreshold * 注意事项: TXIF = TXTHRF & TXIE ******************************************************************************************************************************************/ -uint32_t UART_INTTXThresholdStat(UART_TypeDef * UARTx) +uint32_t UART_INTTXThresholdStat(UART_TypeDef *UARTx) { - return (UARTx->BAUD & UART_BAUD_TXIF_Msk) ? 1 : 0; + return (UARTx->BAUD & UART_BAUD_TXIF_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -487,9 +501,9 @@ uint32_t UART_INTTXThresholdStat(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_INTTimeoutEn(UART_TypeDef * UARTx) +void UART_INTTimeoutEn(UART_TypeDef *UARTx) { - UARTx->CTRL |= (0x01 << UART_CTRL_TOIE_Pos); + UARTx->CTRL |= (0x01 << UART_CTRL_TOIE_Pos); } /****************************************************************************************************************************************** @@ -499,9 +513,9 @@ void UART_INTTimeoutEn(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_INTTimeoutDis(UART_TypeDef * UARTx) +void UART_INTTimeoutDis(UART_TypeDef *UARTx) { - UARTx->CTRL &= ~(0x01 << UART_CTRL_TOIE_Pos); + UARTx->CTRL &= ~(0x01 << UART_CTRL_TOIE_Pos); } /****************************************************************************************************************************************** @@ -511,9 +525,9 @@ void UART_INTTimeoutDis(UART_TypeDef * UARTx) * 输 出: uint32_t 1 发生了接收超时 0 未发生接收超时 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_INTTimeoutStat(UART_TypeDef * UARTx) +uint32_t UART_INTTimeoutStat(UART_TypeDef *UARTx) { - return (UARTx->BAUD & UART_BAUD_TOIF_Msk) ? 1 : 0; + return (UARTx->BAUD & UART_BAUD_TOIF_Msk) ? 1 : 0; } /****************************************************************************************************************************************** @@ -523,9 +537,9 @@ uint32_t UART_INTTimeoutStat(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_INTTXDoneEn(UART_TypeDef * UARTx) +void UART_INTTXDoneEn(UART_TypeDef *UARTx) { - UARTx->CTRL |= (0x01 << UART_CTRL_TXDOIE_Pos); + UARTx->CTRL |= (0x01 << UART_CTRL_TXDOIE_Pos); } /****************************************************************************************************************************************** @@ -535,9 +549,9 @@ void UART_INTTXDoneEn(UART_TypeDef * UARTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void UART_INTTXDoneDis(UART_TypeDef * UARTx) +void UART_INTTXDoneDis(UART_TypeDef *UARTx) { - UARTx->CTRL &= ~(0x01 << UART_CTRL_TXDOIE_Pos); + UARTx->CTRL &= ~(0x01 << UART_CTRL_TXDOIE_Pos); } /****************************************************************************************************************************************** @@ -547,7 +561,7 @@ void UART_INTTXDoneDis(UART_TypeDef * UARTx) * 输 出: uint32_t 1 发送FIFO空且发送移位寄存器空 0 发送FIFO或发送移位寄存器未空 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t UART_INTTXDoneStat(UART_TypeDef * UARTx) +uint32_t UART_INTTXDoneStat(UART_TypeDef *UARTx) { - return (UARTx->BAUD & UART_BAUD_TXDOIF_Msk) ? 1 : 0; + return (UARTx->BAUD & UART_BAUD_TXDOIF_Msk) ? 1 : 0; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.h index bad63f420c..08bd6f805b 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_uart.h @@ -1,94 +1,90 @@ #ifndef __SWM320_UART_H__ #define __SWM320_UART_H__ -typedef struct { - uint32_t Baudrate; - - uint8_t DataBits; //数据位位数,可取值UART_DATA_8BIT、UART_DATA_9BIT - - uint8_t Parity; //奇偶校验位,可取值UART_PARITY_NONE、UART_PARITY_ODD、UART_PARITY_EVEN、UART_PARITY_ONE、UART_PARITY_ZERO - - uint8_t StopBits; //停止位位数,可取值UART_STOP_1BIT、UART_STOP_2BIT - - uint8_t RXThreshold; //取值0--7 - uint8_t RXThresholdIEn; //当RX FIFO中数据个数 > RXThreshold时触发中断 - - uint8_t TXThreshold; //取值0--7 - uint8_t TXThresholdIEn; //当TX FIFO中数据个数 <= TXThreshold时触发中断 - - uint8_t TimeoutTime; //超时时长 = TimeoutTime/(Baudrate/10) 秒 - uint8_t TimeoutIEn; //超时中断,RX FIFO非空,且超过 TimeoutTime/(Baudrate/10) 秒没有在RX线上接收到数据时触发中断 +typedef struct +{ + uint32_t Baudrate; + + uint8_t DataBits; //数据位位数,可取值UART_DATA_8BIT、UART_DATA_9BIT + + uint8_t Parity; //奇偶校验位,可取值UART_PARITY_NONE、UART_PARITY_ODD、UART_PARITY_EVEN、UART_PARITY_ONE、UART_PARITY_ZERO + + uint8_t StopBits; //停止位位数,可取值UART_STOP_1BIT、UART_STOP_2BIT + + uint8_t RXThreshold; //取值0--7 + uint8_t RXThresholdIEn; //当RX FIFO中数据个数 > RXThreshold时触发中断 + + uint8_t TXThreshold; //取值0--7 + uint8_t TXThresholdIEn; //当TX FIFO中数据个数 <= TXThreshold时触发中断 + + uint8_t TimeoutTime; //超时时长 = TimeoutTime/(Baudrate/10) 秒 + uint8_t TimeoutIEn; //超时中断,RX FIFO非空,且超过 TimeoutTime/(Baudrate/10) 秒没有在RX线上接收到数据时触发中断 } UART_InitStructure; +#define UART_DATA_8BIT 0 +#define UART_DATA_9BIT 1 -#define UART_DATA_8BIT 0 -#define UART_DATA_9BIT 1 +#define UART_PARITY_NONE 0 +#define UART_PARITY_ODD 1 +#define UART_PARITY_EVEN 3 +#define UART_PARITY_ONE 5 +#define UART_PARITY_ZERO 7 -#define UART_PARITY_NONE 0 -#define UART_PARITY_ODD 1 -#define UART_PARITY_EVEN 3 -#define UART_PARITY_ONE 5 -#define UART_PARITY_ZERO 7 +#define UART_STOP_1BIT 0 +#define UART_STOP_2BIT 1 -#define UART_STOP_1BIT 0 -#define UART_STOP_2BIT 1 +#define UART_RTS_1BYTE 0 +#define UART_RTS_2BYTE 1 +#define UART_RTS_4BYTE 2 +#define UART_RTS_6BYTE 3 -#define UART_RTS_1BYTE 0 -#define UART_RTS_2BYTE 1 -#define UART_RTS_4BYTE 2 -#define UART_RTS_6BYTE 3 +#define UART_ABR_RES_OK 1 +#define UART_ABR_RES_ERR 2 -#define UART_ABR_RES_OK 1 -#define UART_ABR_RES_ERR 2 +#define UART_ERR_FRAME 1 +#define UART_ERR_PARITY 2 +#define UART_ERR_NOISE 3 -#define UART_ERR_FRAME 1 -#define UART_ERR_PARITY 2 -#define UART_ERR_NOISE 3 +void UART_Init(UART_TypeDef *UARTx, UART_InitStructure *initStruct); //UART串口初始化 +void UART_Open(UART_TypeDef *UARTx); +void UART_Close(UART_TypeDef *UARTx); +void UART_WriteByte(UART_TypeDef *UARTx, uint32_t data); //发送一个字节数据 +uint32_t UART_ReadByte(UART_TypeDef *UARTx, uint32_t *data); //读取一个字节数据,并指出数据是否Valid -void UART_Init(UART_TypeDef * UARTx, UART_InitStructure * initStruct); //UART串口初始化 -void UART_Open(UART_TypeDef * UARTx); -void UART_Close(UART_TypeDef * UARTx); +uint32_t UART_IsTXBusy(UART_TypeDef *UARTx); +uint32_t UART_IsRXFIFOEmpty(UART_TypeDef *UARTx); //接收FIFO是否空,如果不空则可以继续UART_ReadByte() +uint32_t UART_IsTXFIFOFull(UART_TypeDef *UARTx); //发送FIFO是否满,如果不满则可以继续UART_WriteByte() -void UART_WriteByte(UART_TypeDef * UARTx, uint32_t data); //发送一个字节数据 -uint32_t UART_ReadByte(UART_TypeDef * UARTx, uint32_t * data); //读取一个字节数据,并指出数据是否Valid +void UART_SetBaudrate(UART_TypeDef *UARTx, uint32_t baudrate); //设置波特率 +uint32_t UART_GetBaudrate(UART_TypeDef *UARTx); //获取当前使用的波特率 -uint32_t UART_IsTXBusy(UART_TypeDef * UARTx); -uint32_t UART_IsRXFIFOEmpty(UART_TypeDef * UARTx); //接收FIFO是否空,如果不空则可以继续UART_ReadByte() -uint32_t UART_IsTXFIFOFull(UART_TypeDef * UARTx); //发送FIFO是否满,如果不满则可以继续UART_WriteByte() +void UART_CTSConfig(UART_TypeDef *UARTx, uint32_t enable, uint32_t polarity); +uint32_t UART_CTSLineState(UART_TypeDef *UARTx); +void UART_RTSConfig(UART_TypeDef *UARTx, uint32_t enable, uint32_t polarity, uint32_t threshold); +uint32_t UART_RTSLineState(UART_TypeDef *UARTx); -void UART_SetBaudrate(UART_TypeDef * UARTx, uint32_t baudrate); //设置波特率 -uint32_t UART_GetBaudrate(UART_TypeDef * UARTx); //获取当前使用的波特率 +void UART_LINConfig(UART_TypeDef *UARTx, uint32_t detectedIEn, uint32_t generatedIEn); +void UART_LINGenerate(UART_TypeDef *UARTx); +uint32_t UART_LINIsDetected(UART_TypeDef *UARTx); +uint32_t UART_LINIsGenerated(UART_TypeDef *UARTx); -void UART_CTSConfig(UART_TypeDef * UARTx, uint32_t enable, uint32_t polarity); -uint32_t UART_CTSLineState(UART_TypeDef * UARTx); +void UART_ABRStart(UART_TypeDef *UARTx, uint32_t detectChar); +uint32_t UART_ABRIsDone(UART_TypeDef *UARTx); -void UART_RTSConfig(UART_TypeDef * UARTx, uint32_t enable, uint32_t polarity, uint32_t threshold); -uint32_t UART_RTSLineState(UART_TypeDef * UARTx); - -void UART_LINConfig(UART_TypeDef * UARTx, uint32_t detectedIEn, uint32_t generatedIEn); -void UART_LINGenerate(UART_TypeDef * UARTx); -uint32_t UART_LINIsDetected(UART_TypeDef * UARTx); -uint32_t UART_LINIsGenerated(UART_TypeDef * UARTx); - -void UART_ABRStart(UART_TypeDef * UARTx, uint32_t detectChar); -uint32_t UART_ABRIsDone(UART_TypeDef * UARTx); - - -void UART_INTRXThresholdEn(UART_TypeDef * UARTx); -void UART_INTRXThresholdDis(UART_TypeDef * UARTx); -uint32_t UART_INTRXThresholdStat(UART_TypeDef * UARTx); -void UART_INTTXThresholdEn(UART_TypeDef * UARTx); -void UART_INTTXThresholdDis(UART_TypeDef * UARTx); -uint32_t UART_INTTXThresholdStat(UART_TypeDef * UARTx); -void UART_INTTimeoutEn(UART_TypeDef * UARTx); -void UART_INTTimeoutDis(UART_TypeDef * UARTx); -uint32_t UART_INTTimeoutStat(UART_TypeDef * UARTx); - -void UART_INTTXDoneEn(UART_TypeDef * UARTx); -void UART_INTTXDoneDis(UART_TypeDef * UARTx); -uint32_t UART_INTTXDoneStat(UART_TypeDef * UARTx); +void UART_INTRXThresholdEn(UART_TypeDef *UARTx); +void UART_INTRXThresholdDis(UART_TypeDef *UARTx); +uint32_t UART_INTRXThresholdStat(UART_TypeDef *UARTx); +void UART_INTTXThresholdEn(UART_TypeDef *UARTx); +void UART_INTTXThresholdDis(UART_TypeDef *UARTx); +uint32_t UART_INTTXThresholdStat(UART_TypeDef *UARTx); +void UART_INTTimeoutEn(UART_TypeDef *UARTx); +void UART_INTTimeoutDis(UART_TypeDef *UARTx); +uint32_t UART_INTTimeoutStat(UART_TypeDef *UARTx); +void UART_INTTXDoneEn(UART_TypeDef *UARTx); +void UART_INTTXDoneDis(UART_TypeDef *UARTx); +uint32_t UART_INTTXDoneStat(UART_TypeDef *UARTx); #endif //__SWM320_UART_H__ diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.c b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.c index 59a358b69e..7cc8244685 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.c +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.c @@ -21,7 +21,6 @@ #include "SWM320.h" #include "SWM320_wdt.h" - /****************************************************************************************************************************************** * 函数名称: WDT_Init() * 功能说明: WDT看门狗初始化 @@ -31,26 +30,26 @@ * 输 出: 无 * 注意事项: 复位使能时中断不起作用,因为计数周期结束时芯片直接复位了,无法响应中断 ******************************************************************************************************************************************/ -void WDT_Init(WDT_TypeDef * WDTx, uint32_t peroid, uint32_t mode) +void WDT_Init(WDT_TypeDef *WDTx, uint32_t peroid, uint32_t mode) { - SYS->CLKEN |= (0x01 << SYS_CLKEN_WDT_Pos); - - WDT_Stop(WDTx); //设置前先关闭 - - WDTx->LOAD = peroid; - - if(mode == WDT_MODE_RESET) - { - NVIC_DisableIRQ(WDT_IRQn); - - WDTx->CR |= (1 << WDT_CR_RSTEN_Pos); - } - else //mode == WDT_MODE_INTERRUPT - { - NVIC_EnableIRQ(WDT_IRQn); - - WDTx->CR &= ~(1 << WDT_CR_RSTEN_Pos); - } + SYS->CLKEN |= (0x01 << SYS_CLKEN_WDT_Pos); + + WDT_Stop(WDTx); //设置前先关闭 + + WDTx->LOAD = peroid; + + if (mode == WDT_MODE_RESET) + { + NVIC_DisableIRQ(WDT_IRQn); + + WDTx->CR |= (1 << WDT_CR_RSTEN_Pos); + } + else //mode == WDT_MODE_INTERRUPT + { + NVIC_EnableIRQ(WDT_IRQn); + + WDTx->CR &= ~(1 << WDT_CR_RSTEN_Pos); + } } /****************************************************************************************************************************************** @@ -60,9 +59,9 @@ void WDT_Init(WDT_TypeDef * WDTx, uint32_t peroid, uint32_t mode) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void WDT_Start(WDT_TypeDef * WDTx) +void WDT_Start(WDT_TypeDef *WDTx) { - WDTx->CR |= (0x01 << WDT_CR_EN_Pos); + WDTx->CR |= (0x01 << WDT_CR_EN_Pos); } /****************************************************************************************************************************************** @@ -72,9 +71,9 @@ void WDT_Start(WDT_TypeDef * WDTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void WDT_Stop(WDT_TypeDef * WDTx) +void WDT_Stop(WDT_TypeDef *WDTx) { - WDTx->CR &= ~(0x01 << WDT_CR_EN_Pos); + WDTx->CR &= ~(0x01 << WDT_CR_EN_Pos); } /****************************************************************************************************************************************** @@ -84,9 +83,9 @@ void WDT_Stop(WDT_TypeDef * WDTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void WDT_Feed(WDT_TypeDef * WDTx) +void WDT_Feed(WDT_TypeDef *WDTx) { - WDTx->FEED = 0x55; + WDTx->FEED = 0x55; } /****************************************************************************************************************************************** @@ -96,9 +95,9 @@ void WDT_Feed(WDT_TypeDef * WDTx) * 输 出: int32_t 看门狗当前计数值 * 注意事项: 无 ******************************************************************************************************************************************/ -int32_t WDT_GetValue(WDT_TypeDef * WDTx) +int32_t WDT_GetValue(WDT_TypeDef *WDTx) { - return WDTx->VALUE; + return WDTx->VALUE; } /****************************************************************************************************************************************** @@ -108,9 +107,9 @@ int32_t WDT_GetValue(WDT_TypeDef * WDTx) * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ -void WDT_INTClr(WDT_TypeDef * WDTx) +void WDT_INTClr(WDT_TypeDef *WDTx) { - WDTx->IF = 1; + WDTx->IF = 1; } /****************************************************************************************************************************************** @@ -120,7 +119,7 @@ void WDT_INTClr(WDT_TypeDef * WDTx) * 输 出: int32_t 1 发生中断溢出 0 未发生中断溢出 * 注意事项: 无 ******************************************************************************************************************************************/ -uint32_t WDT_INTStat(WDT_TypeDef * WDTx) +uint32_t WDT_INTStat(WDT_TypeDef *WDTx) { - return WDTx->IF; + return WDTx->IF; } diff --git a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.h b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.h index a02a60ba87..692d1fe65b 100644 --- a/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.h +++ b/bsp/swm320/libraries/SWM320_StdPeriph_Driver/SWM320_wdt.h @@ -1,19 +1,18 @@ #ifndef __SWM320_WDT_H__ -#define __SWM320_WDT_H__ +#define __SWM320_WDT_H__ -#define WDT_MODE_RESET 0 -#define WDT_MODE_INTERRUPT 1 +#define WDT_MODE_RESET 0 +#define WDT_MODE_INTERRUPT 1 -void WDT_Init(WDT_TypeDef * WDTx, uint32_t peroid, uint32_t mode); //WDT看门狗初始化 -void WDT_Start(WDT_TypeDef * WDTx); //启动指定WDT,开始倒计时 -void WDT_Stop(WDT_TypeDef * WDTx); //关闭指定WDT,停止倒计时 +void WDT_Init(WDT_TypeDef *WDTx, uint32_t peroid, uint32_t mode); //WDT看门狗初始化 +void WDT_Start(WDT_TypeDef *WDTx); //启动指定WDT,开始倒计时 +void WDT_Stop(WDT_TypeDef *WDTx); //关闭指定WDT,停止倒计时 -void WDT_Feed(WDT_TypeDef * WDTx); //喂狗,重新从装载值开始倒计时 +void WDT_Feed(WDT_TypeDef *WDTx); //喂狗,重新从装载值开始倒计时 -int32_t WDT_GetValue(WDT_TypeDef * WDTx); //获取指定看门狗定时器的当前倒计时值 +int32_t WDT_GetValue(WDT_TypeDef *WDTx); //获取指定看门狗定时器的当前倒计时值 +void WDT_INTClr(WDT_TypeDef *WDTx); //中断标志清除 +uint32_t WDT_INTStat(WDT_TypeDef *WDTx); //中断状态查询 -void WDT_INTClr(WDT_TypeDef * WDTx); //中断标志清除 -uint32_t WDT_INTStat(WDT_TypeDef * WDTx); //中断状态查询 - #endif //__SWM320_WDT_H__ From f982d813892971a7e9ba75ace7061805cd8f2458 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Thu, 6 May 2021 23:43:44 +0800 Subject: [PATCH 022/255] [rtc driver]remove NTP --- components/drivers/include/drivers/rtc.h | 5 --- components/drivers/rtc/rtc.c | 51 ------------------------ 2 files changed, 56 deletions(-) diff --git a/components/drivers/include/drivers/rtc.h b/components/drivers/include/drivers/rtc.h index 6eda9cbf53..a9e1c17a9d 100644 --- a/components/drivers/include/drivers/rtc.h +++ b/components/drivers/include/drivers/rtc.h @@ -16,9 +16,4 @@ rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day); rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second); -#ifdef RTC_SYNC_USING_NTP -int rt_soft_rtc_init(void); -int rt_rtc_ntp_sync_init(void); -#endif /* RTC_SYNC_USING_NTP */ - #endif /* __RTC_H__ */ diff --git a/components/drivers/rtc/rtc.c b/components/drivers/rtc/rtc.c index 2c184bad21..f15b8a7754 100644 --- a/components/drivers/rtc/rtc.c +++ b/components/drivers/rtc/rtc.c @@ -196,55 +196,4 @@ MSH_CMD_EXPORT(list_date, show date and time (local timezone)) MSH_CMD_EXPORT(date, get date and time or set (local timezone) [year month day hour min sec]) #endif /* FINSH_USING_MSH */ -/* Using NTP auto sync RTC time */ -#ifdef RTC_SYNC_USING_NTP -/* NTP first sync delay time for network connect, unit: second */ -#ifndef RTC_NTP_FIRST_SYNC_DELAY -#define RTC_NTP_FIRST_SYNC_DELAY (30) -#endif -/* NTP sync period, unit: second */ -#ifndef RTC_NTP_SYNC_PERIOD -#define RTC_NTP_SYNC_PERIOD (1L*60L*60L) -#endif - -static void ntp_sync_thread_enrty(void *param) -{ - extern time_t ntp_sync_to_rtc(const char *host_name); - /* first sync delay for network connect */ - rt_thread_delay(RTC_NTP_FIRST_SYNC_DELAY * RT_TICK_PER_SECOND); - - while (1) - { - ntp_sync_to_rtc(NULL); - rt_thread_delay(RTC_NTP_SYNC_PERIOD * RT_TICK_PER_SECOND); - } -} - -int rt_rtc_ntp_sync_init(void) -{ - static rt_bool_t init_ok = RT_FALSE; - rt_thread_t thread; - - if (init_ok) - { - return 0; - } - - thread = rt_thread_create("ntp_sync", ntp_sync_thread_enrty, RT_NULL, 1536, 26, 2); - if (thread) - { - rt_thread_startup(thread); - } - else - { - return -RT_ENOMEM; - } - - init_ok = RT_TRUE; - - return RT_EOK; -} -INIT_COMPONENT_EXPORT(rt_rtc_ntp_sync_init); -#endif /* RTC_SYNC_USING_NTP */ - #endif /* RT_USING_RTC */ From 43e9aec85e560e50b1bbefa300c50b34d1268ab5 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Thu, 6 May 2021 23:47:33 +0800 Subject: [PATCH 023/255] =?UTF-8?q?=E5=B0=86rt=5Fsoft=5Frtc=5Finit?= =?UTF-8?q?=E8=AE=BE=E4=B8=BA=E7=A7=81=E6=9C=89=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/drivers/rtc/README.md | 2 -- components/drivers/rtc/soft_rtc.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/components/drivers/rtc/README.md b/components/drivers/rtc/README.md index 23010cf4b7..f2a40f5056 100644 --- a/components/drivers/rtc/README.md +++ b/components/drivers/rtc/README.md @@ -76,5 +76,3 @@ msh /> 在 menuconfig 中启用 `RT_USING_SOFT_RTC` 配置。 -> 注意:如果没有使用组件自动初始化功能,则需手动调用 `int rt_soft_rtc_init(void)` ,完成该功能初始化。 - diff --git a/components/drivers/rtc/soft_rtc.c b/components/drivers/rtc/soft_rtc.c index 9e1b7c35fd..255579f35e 100644 --- a/components/drivers/rtc/soft_rtc.c +++ b/components/drivers/rtc/soft_rtc.c @@ -104,7 +104,7 @@ const static struct rt_device_ops soft_rtc_ops = }; #endif -int rt_soft_rtc_init(void) +static int rt_soft_rtc_init(void) { static rt_bool_t init_ok = RT_FALSE; struct tm time_new = SOFT_RTC_TIME_DEFAULT; From 86f9b001c77090e695b8df4d4bd3af9315099a7c Mon Sep 17 00:00:00 2001 From: thread-liu Date: Fri, 7 May 2021 11:06:15 +0800 Subject: [PATCH 024/255] [update] file_check.py --- tools/file_check.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/file_check.py b/tools/file_check.py index e79332b325..046b2a009f 100644 --- a/tools/file_check.py +++ b/tools/file_check.py @@ -144,7 +144,7 @@ class FormatCheck: logging.warning("There are no files to check format.") return True encoding_check_result = True - format_check_result = True + format_check_fail_files = 0 for file_path in self.file_list: code = '' if file_path.endswith(".c") or file_path.endswith(".h"): @@ -166,9 +166,10 @@ class FormatCheck: with open(file_path, 'r', encoding = "utf-8") as f: file_lines = f.readlines() - format_check_result = self.__check_file(file_lines, file_path) + if not self.__check_file(file_lines, file_path): + format_check_fail_files += 1 - if not encoding_check_result or not format_check_result: + if (not encoding_check_result) or (format_check_fail_files != 0): logging.error("files format check fail.") return False From 6cb39a15a672d1f58951baf726fcb924899fa50e Mon Sep 17 00:00:00 2001 From: Tao_eternal Date: Fri, 7 May 2021 13:52:33 +0800 Subject: [PATCH 025/255] fixed some bugs about interrupt When I used the pin's interrupt, I always get a FALSE state. So I read the drv_gpio.c and has found that function gpio_exti_source_select has not truly set yet and the GPIO input mode and the EXTI_(bitno) should be correct. --- bsp/gd32vf103v-eval/drivers/drv_gpio.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/bsp/gd32vf103v-eval/drivers/drv_gpio.c b/bsp/gd32vf103v-eval/drivers/drv_gpio.c index ca56bf54a2..47f9b52009 100644 --- a/bsp/gd32vf103v-eval/drivers/drv_gpio.c +++ b/bsp/gd32vf103v-eval/drivers/drv_gpio.c @@ -350,8 +350,6 @@ static rt_err_t gd32vf_pin_irq_enable(struct rt_device *device, rt_base_t pin, return RT_ENOSYS; } - /* configure pin as input */ - gpio_init(index->gpio_periph, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, index->pin); if (enabled == PIN_IRQ_ENABLE) { irqindex = bit2bitno(index->pin); @@ -372,24 +370,31 @@ static rt_err_t gd32vf_pin_irq_enable(struct rt_device *device, rt_base_t pin, /* enable and set EXTI interrupt to the lowest priority */ eclic_irq_enable(irqmap->irqno, 1, 1); - gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_0); + /* select SOURCE_PORT_x and SOURCE_PIN_x */ + gpio_exti_source_select(index->index >> 4, irqindex); /* Configure GPIO_InitStructure */ switch (pin_irq_hdr_tab[irqindex].mode) { case PIN_IRQ_MODE_RISING: + gpio_init( index->gpio_periph, GPIO_MODE_IPD, GPIO_OSPEED_50MHZ, + index->pin ); exti_init(EXTI_(irqindex), EXTI_INTERRUPT, EXTI_TRIG_RISING); break; case PIN_IRQ_MODE_FALLING: + gpio_init( index->gpio_periph, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, + index->pin ); exti_init(EXTI_(irqindex), EXTI_INTERRUPT, EXTI_TRIG_FALLING); break; case PIN_IRQ_MODE_RISING_FALLING: + gpio_init(index->gpio_periph, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, + index->pin); exti_init(EXTI_(irqindex), EXTI_INTERRUPT, EXTI_TRIG_BOTH); break; } pin_irq_enable_mask |= irqmap->pinbit; - - exti_interrupt_flag_clear(EXTI_(index->pin)); + /* irqindex should be bitno and then EXTI_(x) can be the bit */ + exti_interrupt_flag_clear(EXTI_(irqindex)); rt_hw_interrupt_enable(level); } @@ -408,7 +413,7 @@ static rt_err_t gd32vf_pin_irq_enable(struct rt_device *device, rt_base_t pin, pin_irq_enable_mask &= ~irqmap->pinbit; eclic_irq_disable(irqmap->irqno); - exti_interrupt_flag_clear(EXTI_(index->pin)); + exti_interrupt_flag_clear(EXTI_(irqindex)); rt_hw_interrupt_enable(level); } From ac2c734583fdaddeebdbb2a168b0f643b2dbaa2b Mon Sep 17 00:00:00 2001 From: geniusgogo Date: Fri, 7 May 2021 14:53:48 +0800 Subject: [PATCH 026/255] fixed rt_kprintf %s precision print error. --- src/kservice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kservice.c b/src/kservice.c index e9972dba97..7ed05b6651 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -922,7 +922,7 @@ rt_int32_t rt_vsnprintf(char *buf, s = va_arg(args, char *); if (!s) s = "(NULL)"; - len = rt_strlen(s); + for (len = 0; (len != field_width) && (s[len] != '\0'); len++); #ifdef RT_PRINTF_PRECISION if (precision > 0 && len > precision) len = precision; #endif From 7ab2cae3fa28b525baf4c75615a86adffa21feed Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Fri, 7 May 2021 17:33:40 +0800 Subject: [PATCH 027/255] [bsp]add seeed Arch_Mix bsp --- bsp/imxrt/imxrt1052-seeed-ArchMix/.config | 562 +++++++++++++ bsp/imxrt/imxrt1052-seeed-ArchMix/Kconfig | 16 + bsp/imxrt/imxrt1052-seeed-ArchMix/README.md | 76 ++ bsp/imxrt/imxrt1052-seeed-ArchMix/SConscript | 14 + bsp/imxrt/imxrt1052-seeed-ArchMix/SConstruct | 71 ++ .../applications/SConscript | 16 + .../applications/main.c | 31 + .../imxrt1052-seeed-ArchMix/board/Kconfig | 122 +++ .../board/MCUX_Config/MCUX_Config.mex | 746 +++++++++++++++++ .../board/MCUX_Config/clock_config.c | 464 +++++++++++ .../board/MCUX_Config/clock_config.h | 66 ++ .../board/MCUX_Config/pin_mux.c | 81 ++ .../board/MCUX_Config/pin_mux.h | 182 +++++ .../board/MIMXRT105x_QuadSPI_4KB_SEC.FLM | Bin 0 -> 1509352 bytes .../imxrt1052-seeed-ArchMix/board/SConscript | 20 + .../imxrt1052-seeed-ArchMix/board/board.c | 138 ++++ .../imxrt1052-seeed-ArchMix/board/board.h | 42 + .../board/linker_scripts/link.icf | 95 +++ .../board/linker_scripts/link.lds | 276 +++++++ .../board/linker_scripts/link.sct | 112 +++ .../board/ports/sdram_port.h | 49 ++ .../figures/Arch_Mix.jpg | Bin 0 -> 290625 bytes .../imxrt1052-seeed-ArchMix/project.uvoptx | 189 +++++ .../imxrt1052-seeed-ArchMix/project.uvprojx | 755 ++++++++++++++++++ bsp/imxrt/imxrt1052-seeed-ArchMix/rtconfig.h | 177 ++++ bsp/imxrt/imxrt1052-seeed-ArchMix/rtconfig.py | 162 ++++ .../imxrt1052-seeed-ArchMix/template.uvoptx | 189 +++++ .../imxrt1052-seeed-ArchMix/template.uvprojx | 391 +++++++++ bsp/imxrt/libraries/MIMXRT1050/SConscript | 4 +- 29 files changed, 5044 insertions(+), 2 deletions(-) create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/.config create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/Kconfig create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/README.md create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/SConscript create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/SConstruct create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/applications/SConscript create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/applications/main.c create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/Kconfig create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/MCUX_Config.mex create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/clock_config.c create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/clock_config.h create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/pin_mux.c create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/pin_mux.h create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/MIMXRT105x_QuadSPI_4KB_SEC.FLM create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/SConscript create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/board.c create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/board.h create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.icf create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.lds create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.sct create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/board/ports/sdram_port.h create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/figures/Arch_Mix.jpg create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/project.uvoptx create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/project.uvprojx create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/rtconfig.h create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/rtconfig.py create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/template.uvoptx create mode 100644 bsp/imxrt/imxrt1052-seeed-ArchMix/template.uvprojx diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/.config b/bsp/imxrt/imxrt1052-seeed-ArchMix/.config new file mode 100644 index 0000000000..585af44037 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/.config @@ -0,0 +1,562 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=1000 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# 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=y +CONFIG_RT_USING_MEMHEAP=y +# CONFIG_RT_USING_NOHEAP is not set +# CONFIG_RT_USING_SMALL_MEM is not set +# CONFIG_RT_USING_SLAB is not set +CONFIG_RT_USING_MEMHEAP_AS_HEAP=y +# 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 is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +CONFIG_RT_VER_NUM=0x40003 +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_CMD_SIZE=80 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +CONFIG_FINSH_USING_MSH_ONLY=y +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set +# CONFIG__RT_USB_DEVICE_NONE is not set +# CONFIG__RT_USB_DEVICE_CDC is not set +# CONFIG__RT_USB_DEVICE_MSTORAGE is not set +# CONFIG__RT_USB_DEVICE_HID is not set +# CONFIG__RT_USB_DEVICE_WINUSB is not set +# CONFIG__RT_USB_DEVICE_AUDIO is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +# CONFIG_RT_USING_PTHREADS is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_FIXED_TIMEZONE=8 + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_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_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 +# +# CONFIG_PKG_USING_GUIENGINE 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 + +# +# 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_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# 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 +# 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_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 + +# +# Hardware Drivers Config +# +CONFIG_SOC_IMXRT1052CVL5B=y + +# +# Onboard Peripheral Drivers +# +# CONFIG_BSP_USING_SDRAM is not set + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_DMA=y +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_LPUART=y +CONFIG_BSP_USING_LPUART1=y +# CONFIG_BSP_LPUART1_RX_USING_DMA is not set +# CONFIG_BSP_LPUART1_TX_USING_DMA is not set +# CONFIG_BSP_USING_LPUART4 is not set +# CONFIG_BSP_USING_SPI is not set diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/Kconfig b/bsp/imxrt/imxrt1052-seeed-ArchMix/Kconfig new file mode 100644 index 0000000000..c9221717cb --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/Kconfig @@ -0,0 +1,16 @@ +mainmenu "RT-Thread Configuration" + +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" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/README.md b/bsp/imxrt/imxrt1052-seeed-ArchMix/README.md new file mode 100644 index 0000000000..7d3d1195ac --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/README.md @@ -0,0 +1,76 @@ +# Seeed i.MX RT1052 Arch Mix 开发板 BSP 说明 + +## 简介 + +![Arch_Mix](figures/Arch_Mix.jpg) + +Arch Mix 是 [Seeed Studio](https://www.seeedstudio.com/) 推出的一款基于 i.MX RT 1050 系列芯片的开发板,板载一颗 RGB 灯和一个用户按键,外扩 32M SDRAM,板载资源丰富,运行速度快(主频可达 600MHZ),并且支持外接 LCD 屏幕。Seeed Studio 是一家致力于促进开源硬件发展的服务型企业。目前,已经与众多设计者建立了紧密的合作关系,并且合作推出了涉及新媒体艺术、嵌入式平台、物联网、智能家居、便携式仪器等领域的一系列明星产品和方案。 + +### 板载资源: + +| 硬件 | 描述 | +| ---- | ---- | +| 芯片 | i.MX RT 1052 | +| 架构 | ARM Cortex-M7 | +| 最高频率 | 600MHz | +| 内部存储器 | 512KB SRAM | +| 外部存储器 | 32M SDRAM、8M QSPI FLASH(存储代码) | + +## 编译说明 + +Arch Mix 板级包支持MDK5﹑IAR开发环境和GCC编译器,以下是具体版本信息: + +| IDE/编译器 | 已测试版本 | +| ---------- | --------- | +| MDK5 | MDK525 | +| IAR | IAR 8.11.3.13984 | +| GCC | GCC 5.4.1 20160919 (release) | + +## BSP使用 + +### 配置工程 + +- 在 bsp 下打开 env 工具 +- 输入`menuconfig`命令配置工程,配置好之后保存退出。 +- 输入`scons --target=mdk5 -s`或`scons --target=iar`来生成需要的工程 + +### 下载和仿真 + +开发板支持 SWD 调试接口,连接外置仿真器后,就可以进行下载和仿真。 + +> 注意:下载算法默认使用 board目录下的 MIMXRT105x_QuadSPI_4KB_SEC.FLM 文件,将此文件拷贝到 Keil5安装目录下 `ARM\Flash` 目录下即可。 +> +> 下载失败时:先按下 `Reset 按键`,再按下 `Boot Mode 按键`,先松开 `Reset 按键`,再松开 `Boot Mode 按键`,即可进入`下载模式`。 + +### 运行结果 + +下载程序成功之后,系统会自动运行,观察开发板上 LED 的运行效果,绿色 DS1 会周期性闪烁。 + +使用 TTL 转串口工具连接开发板上 RXD/TXD ,在终端工具里打开相应的串口(115200-N-8-1)。如果编译 & 烧写无误,当复位设备后,可以看到RT-Thread的输出信息: + +``` + \ | / +- RT - Thread Operating System + / | \ 4.0.3 build May 7 2021 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +## 驱动支持情况及计划 + +| 驱动 | 支持情况 | 备注 | +| ------ | ---- | ------ | +| UART | 支持 | UART 1 | +| GPIO | 支持 | GPIO1~GPIO5 | +| IIC | 暂不支持 | | +| SPI | 暂不支持 | | +| LCD | 暂不支持 | | +| RTC | 暂不支持 | | +| SDIO | 暂不支持 | | +| SDRAM | 支持 | 32M SDRAM,后面 2M 作为 Non Cache 区域 | + +## 联系人信息 + +维护人: + +- [guozhanxin](https://github.com/Guozhanxin) diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/SConscript b/bsp/imxrt/imxrt1052-seeed-ArchMix/SConscript new file mode 100644 index 0000000000..c7ef7659ec --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/SConscript @@ -0,0 +1,14 @@ +# for module compiling +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/SConstruct b/bsp/imxrt/imxrt1052-seeed-ArchMix/SConstruct new file mode 100644 index 0000000000..9e5cd55bc0 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/SConstruct @@ -0,0 +1,71 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT +DefaultEnvironment(tools=[]) +if rtconfig.PLATFORM == 'armcc': + env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS, + # overwrite cflags, because cflags has '--C99' + CXXCOM = '$CXX -o $TARGET --cpp -c $CXXFLAGS $_CCCOMCOM $SOURCES') +else: + env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS, + CXXCOM = '$CXX -o $TARGET -c $CXXFLAGS $_CCCOMCOM $SOURCES') + +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +imxrt_library = 'MIMXRT1050' +rtconfig.BSP_LIBRARY_TYPE = imxrt_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, imxrt_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/applications/SConscript b/bsp/imxrt/imxrt1052-seeed-ArchMix/applications/SConscript new file mode 100644 index 0000000000..78952a658e --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/applications/SConscript @@ -0,0 +1,16 @@ +import rtconfig +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +# add for startup script +if rtconfig.CROSS_TOOL == 'gcc': + CPPDEFINES = ['__START=entry'] +else: + CPPDEFINES = [] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES=CPPDEFINES) + +Return('group') diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/applications/main.c b/bsp/imxrt/imxrt1052-seeed-ArchMix/applications/main.c new file mode 100644 index 0000000000..86c7dfb31a --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/applications/main.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-10-10 Tanek first version + */ + +#include +#include +#include "drv_gpio.h" + +/* USER_LED_G,GPIO_IO01,GPIO_AD_B0_10 */ +#define LED0_PIN GET_PIN(1,10) + +int main(void) +{ + /* set LED0 pin mode to output */ + rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); + + while (1) + { + rt_pin_write(LED0_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED0_PIN, PIN_LOW); + rt_thread_mdelay(500); + } +} + diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/Kconfig b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/Kconfig new file mode 100644 index 0000000000..2644641ba5 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/Kconfig @@ -0,0 +1,122 @@ +menu "Hardware Drivers Config" + +config SOC_IMXRT1052CVL5B + bool + select SOC_MIMXRT1050_SERIES + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + + config BSP_USING_SDRAM + bool "Enable SDRAM" + default n + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_DMA + bool "Enable DMA" + default n + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_LPUART + bool "Enable UART" + select RT_USING_SERIAL + default y + + if BSP_USING_LPUART + config BSP_USING_LPUART1 + bool "Enable LPUART1" + default y + + config BSP_LPUART1_RX_USING_DMA + bool "Enable LPUART1 RX DMA" + depends on BSP_USING_LPUART1 + select BSP_USING_DMA + select RT_SERIAL_USING_DMA + default n + + config BSP_LPUART1_RX_DMA_CHANNEL + depends on BSP_LPUART1_RX_USING_DMA + int "Set LPUART1 RX DMA channel (0-32)" + default 0 + + config BSP_LPUART1_TX_USING_DMA + bool "Enable LPUART1 TX DMA" + depends on BSP_USING_LPUART1 + select BSP_USING_DMA + select RT_SERIAL_USING_DMA + default n + + config BSP_LPUART1_TX_DMA_CHANNEL + depends on BSP_LPUART1_TX_USING_DMA + int "Set LPUART1 TX DMA channel (0-32)" + default 1 + + config BSP_USING_LPUART4 + bool "Enable LPUART4" + default n + + config BSP_LPUART4_RX_USING_DMA + bool "Enable LPUART4 RX DMA" + depends on BSP_USING_LPUART4 + select BSP_USING_DMA + select RT_SERIAL_USING_DMA + default n + + config BSP_LPUART4_RX_DMA_CHANNEL + depends on BSP_LPUART4_RX_USING_DMA + int "Set LPUART4 RX DMA channel (0-32)" + default 2 + + config BSP_LPUART4_TX_USING_DMA + bool "Enable LPUART4 TX DMA" + depends on BSP_USING_LPUART4 + select BSP_USING_DMA + select RT_SERIAL_USING_DMA + default n + + config BSP_LPUART4_TX_DMA_CHANNEL + depends on BSP_LPUART4_TX_USING_DMA + int "Set LPUART4 TX DMA channel (0-32)" + default 3 + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI" + select RT_USING_SPI + select RT_USING_PIN + default n + + if BSP_USING_SPI + config BSP_USING_SPI3 + bool "Enable SPI3" + default n + + config BSP_SPI3_USING_DMA + bool "Enable SPI3 DMA xfer" + depends on BSP_USING_SPI3 + select BSP_USING_DMA + default n + + config BSP_SPI3_RX_DMA_CHANNEL + depends on BSP_SPI3_USING_DMA + int "Set SPI3 RX DMA channel (0-32)" + default 4 + + config BSP_SPI3_TX_DMA_CHANNEL + depends on BSP_SPI3_USING_DMA + int "Set SPI3 TX DMA channel (0-32)" + default 5 + endif + +endmenu + +endmenu diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/MCUX_Config.mex b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/MCUX_Config.mex new file mode 100644 index 0000000000..bd254aa553 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/MCUX_Config.mex @@ -0,0 +1,746 @@ + + + + MIMXRT1052xxxxB + MIMXRT1052DVL6B + IMXRT1050-EVKB + A + ksdk2_0 + + + + + + + false + false + + + + + 5.0.2 + + + + + Configures pin routing and optionally pin electrical features. + + false + core0 + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5.0.2 + + + + + + + + + true + + + + + INPUT + + + + + true + + + + + OUTPUT + + + + + true + + + + + INPUT + + + + + true + + + + + OUTPUT + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + true + + + + + 2.2.4 + + + + + true + + + + + 2.0.0 + + + + + true + + + + + 2.1.5 + + + + + true + + + + + 2.3.0 + + + + + true + + + + + 2.0.0 + + + + + 5.0.2 + + + + + + + + + + + + + + + 0 + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + 0 + + + + + 0 + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + true + + + + + 0 + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + kELCDIF_CurFrameDoneInterruptEnable + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/clock_config.c b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/clock_config.c new file mode 100644 index 0000000000..87b20a1e25 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/clock_config.c @@ -0,0 +1,464 @@ +/* + * How to setup clock using clock driver functions: + * + * 1. Call CLOCK_InitXXXPLL() to configure corresponding PLL clock. + * + * 2. Call CLOCK_InitXXXpfd() to configure corresponding PLL pfd clock. + * + * 3. Call CLOCK_SetMux() to configure corresponding clock source for target clock out. + * + * 4. Call CLOCK_SetDiv() to configure corresponding clock divider for target clock out. + * + * 5. Call CLOCK_SetXtalFreq() to set XTAL frequency based on board settings. + * + */ + +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!GlobalInfo +product: Clocks v5.0 +processor: MIMXRT1052xxxxB +package_id: MIMXRT1052DVL6B +mcu_data: ksdk2_0 +processor_version: 5.0.2 +board: IMXRT1050-EVKB + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ + +#include "clock_config.h" +#include "fsl_iomuxc.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ +/* System clock frequency. */ +extern uint32_t SystemCoreClock; + +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ +void BOARD_InitBootClocks(void) +{ + BOARD_BootClockRUN(); +} + +/******************************************************************************* + ********************** Configuration BOARD_BootClockRUN *********************** + ******************************************************************************/ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!Configuration +name: BOARD_BootClockRUN +called_from_default_init: true +outputs: +- {id: AHB_CLK_ROOT.outFreq, value: 600 MHz} +- {id: CAN_CLK_ROOT.outFreq, value: 40 MHz} +- {id: CKIL_SYNC_CLK_ROOT.outFreq, value: 32.768 kHz} +- {id: CLK_1M.outFreq, value: 1 MHz} +- {id: CLK_24M.outFreq, value: 24 MHz} +- {id: CSI_CLK_ROOT.outFreq, value: 12 MHz} +- {id: ENET1_TX_CLK.outFreq, value: 2.4 MHz} +- {id: ENET_125M_CLK.outFreq, value: 2.4 MHz} +- {id: ENET_25M_REF_CLK.outFreq, value: 1.2 MHz} +- {id: FLEXIO1_CLK_ROOT.outFreq, value: 30 MHz} +- {id: FLEXIO2_CLK_ROOT.outFreq, value: 30 MHz} +- {id: FLEXSPI_CLK_ROOT.outFreq, value: 2880/11 MHz} +- {id: GPT1_ipg_clk_highfreq.outFreq, value: 75 MHz} +- {id: GPT2_ipg_clk_highfreq.outFreq, value: 75 MHz} +- {id: IPG_CLK_ROOT.outFreq, value: 150 MHz} +- {id: LCDIF_CLK_ROOT.outFreq, value: 67.5/7 MHz} +- {id: LPI2C_CLK_ROOT.outFreq, value: 60 MHz} +- {id: LPSPI_CLK_ROOT.outFreq, value: 105.6 MHz} +- {id: LVDS1_CLK.outFreq, value: 1.2 GHz} +- {id: MQS_MCLK.outFreq, value: 1080/17 MHz} +- {id: PERCLK_CLK_ROOT.outFreq, value: 75 MHz} +- {id: PLL7_MAIN_CLK.outFreq, value: 24 MHz} +- {id: SAI1_CLK_ROOT.outFreq, value: 1080/17 MHz} +- {id: SAI1_MCLK1.outFreq, value: 1080/17 MHz} +- {id: SAI1_MCLK2.outFreq, value: 1080/17 MHz} +- {id: SAI1_MCLK3.outFreq, value: 30 MHz} +- {id: SAI2_CLK_ROOT.outFreq, value: 1080/17 MHz} +- {id: SAI2_MCLK1.outFreq, value: 1080/17 MHz} +- {id: SAI2_MCLK3.outFreq, value: 30 MHz} +- {id: SAI3_CLK_ROOT.outFreq, value: 1080/17 MHz} +- {id: SAI3_MCLK1.outFreq, value: 1080/17 MHz} +- {id: SAI3_MCLK3.outFreq, value: 30 MHz} +- {id: SEMC_CLK_ROOT.outFreq, value: 75 MHz} +- {id: SPDIF0_CLK_ROOT.outFreq, value: 30 MHz} +- {id: TRACE_CLK_ROOT.outFreq, value: 352/3 MHz} +- {id: UART_CLK_ROOT.outFreq, value: 80 MHz} +- {id: USDHC1_CLK_ROOT.outFreq, value: 198 MHz} +- {id: USDHC2_CLK_ROOT.outFreq, value: 198 MHz} +settings: +- {id: CCM.AHB_PODF.scale, value: '1', locked: true} +- {id: CCM.ARM_PODF.scale, value: '2', locked: true} +- {id: CCM.FLEXSPI_PODF.scale, value: '1', locked: true} +- {id: CCM.FLEXSPI_SEL.sel, value: CCM_ANALOG.PLL3_PFD0_CLK} +- {id: CCM.LCDIF_PODF.scale, value: '8', locked: true} +- {id: CCM.LCDIF_PRED.scale, value: '7', locked: true} +- {id: CCM.LPSPI_PODF.scale, value: '5', locked: true} +- {id: CCM.PERCLK_PODF.scale, value: '2', locked: true} +- {id: CCM.SEMC_PODF.scale, value: '8'} +- {id: CCM.TRACE_PODF.scale, value: '3', locked: true} +- {id: CCM_ANALOG.PLL1_BYPASS.sel, value: CCM_ANALOG.PLL1} +- {id: CCM_ANALOG.PLL1_PREDIV.scale, value: '1', locked: true} +- {id: CCM_ANALOG.PLL1_VDIV.scale, value: '50', locked: true} +- {id: CCM_ANALOG.PLL2.denom, value: '1', locked: true} +- {id: CCM_ANALOG.PLL2.num, value: '0', locked: true} +- {id: CCM_ANALOG.PLL2_BYPASS.sel, value: CCM_ANALOG.PLL2_OUT_CLK} +- {id: CCM_ANALOG.PLL2_PFD0_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD0} +- {id: CCM_ANALOG.PLL2_PFD1_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD1} +- {id: CCM_ANALOG.PLL2_PFD2_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD2} +- {id: CCM_ANALOG.PLL2_PFD3_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD3} +- {id: CCM_ANALOG.PLL3_BYPASS.sel, value: CCM_ANALOG.PLL3} +- {id: CCM_ANALOG.PLL3_PFD0_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD0} +- {id: CCM_ANALOG.PLL3_PFD0_DIV.scale, value: '33', locked: true} +- {id: CCM_ANALOG.PLL3_PFD0_MUL.scale, value: '18', locked: true} +- {id: CCM_ANALOG.PLL3_PFD1_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD1} +- {id: CCM_ANALOG.PLL3_PFD2_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD2} +- {id: CCM_ANALOG.PLL3_PFD3_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD3} +- {id: CCM_ANALOG.PLL4.denom, value: '50'} +- {id: CCM_ANALOG.PLL4.div, value: '47'} +- {id: CCM_ANALOG.PLL5.denom, value: '1'} +- {id: CCM_ANALOG.PLL5.div, value: '40'} +- {id: CCM_ANALOG.PLL5.num, value: '0'} +- {id: CCM_ANALOG_PLL_ENET_POWERDOWN_CFG, value: 'Yes'} +- {id: CCM_ANALOG_PLL_USB1_POWER_CFG, value: 'Yes'} +sources: +- {id: XTALOSC24M.OSC.outFreq, value: 24 MHz, enabled: true} +- {id: XTALOSC24M.RTC_OSC.outFreq, value: 32.768 kHz, enabled: true} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ + +/******************************************************************************* + * Variables for BOARD_BootClockRUN configuration + ******************************************************************************/ +const clock_arm_pll_config_t armPllConfig_BOARD_BootClockRUN = + { + .loopDivider = 100, /* PLL loop divider, Fout = Fin * 50 */ + .src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */ + }; +const clock_sys_pll_config_t sysPllConfig_BOARD_BootClockRUN = + { + .loopDivider = 1, /* PLL loop divider, Fout = Fin * ( 20 + loopDivider*2 + numerator / denominator ) */ + .numerator = 0, /* 30 bit numerator of fractional loop divider */ + .denominator = 1, /* 30 bit denominator of fractional loop divider */ + .src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */ + }; +const clock_usb_pll_config_t usb1PllConfig_BOARD_BootClockRUN = + { + .loopDivider = 0, /* PLL loop divider, Fout = Fin * 20 */ + .src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */ + }; +/******************************************************************************* + * Code for BOARD_BootClockRUN configuration + ******************************************************************************/ +void BOARD_BootClockRUN(void) +{ + /* Init RTC OSC clock frequency. */ + CLOCK_SetRtcXtalFreq(32768U); + /* Enable 1MHz clock output. */ + XTALOSC24M->OSC_CONFIG2 |= XTALOSC24M_OSC_CONFIG2_ENABLE_1M_MASK; + /* Use free 1MHz clock output. */ + XTALOSC24M->OSC_CONFIG2 &= ~XTALOSC24M_OSC_CONFIG2_MUX_1M_MASK; + /* Set XTAL 24MHz clock frequency. */ + CLOCK_SetXtalFreq(24000000U); + /* Enable XTAL 24MHz clock source. */ + CLOCK_InitExternalClk(0); + /* Enable internal RC. */ + CLOCK_InitRcOsc24M(); + /* Switch clock source to external OSC. */ + CLOCK_SwitchOsc(kCLOCK_XtalOsc); + /* Set Oscillator ready counter value. */ + CCM->CCR = (CCM->CCR & (~CCM_CCR_OSCNT_MASK)) | CCM_CCR_OSCNT(127); + /* Setting PeriphClk2Mux and PeriphMux to provide stable clock before PLLs are initialed */ + CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 1); /* Set PERIPH_CLK2 MUX to OSC */ + CLOCK_SetMux(kCLOCK_PeriphMux, 1); /* Set PERIPH_CLK MUX to PERIPH_CLK2 */ + /* Setting the VDD_SOC to 1.275V. It is necessary to config AHB to 600Mhz. */ + DCDC->REG3 = (DCDC->REG3 & (~DCDC_REG3_TRG_MASK)) | DCDC_REG3_TRG(0x13); + /* Waiting for DCDC_STS_DC_OK bit is asserted */ + while (DCDC_REG0_STS_DC_OK_MASK != (DCDC_REG0_STS_DC_OK_MASK & DCDC->REG0)) + { + } + /* Set AHB_PODF. */ + CLOCK_SetDiv(kCLOCK_AhbDiv, 0); + /* Disable IPG clock gate. */ + CLOCK_DisableClock(kCLOCK_Adc1); + CLOCK_DisableClock(kCLOCK_Adc2); + CLOCK_DisableClock(kCLOCK_Xbar1); + CLOCK_DisableClock(kCLOCK_Xbar2); + CLOCK_DisableClock(kCLOCK_Xbar3); + /* Set IPG_PODF. */ + CLOCK_SetDiv(kCLOCK_IpgDiv, 3); + /* Set ARM_PODF. */ + CLOCK_SetDiv(kCLOCK_ArmDiv, 1); + /* Set PERIPH_CLK2_PODF. */ + CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0); + /* Disable PERCLK clock gate. */ + CLOCK_DisableClock(kCLOCK_Gpt1); + CLOCK_DisableClock(kCLOCK_Gpt1S); + CLOCK_DisableClock(kCLOCK_Gpt2); + CLOCK_DisableClock(kCLOCK_Gpt2S); + CLOCK_DisableClock(kCLOCK_Pit); + /* Set PERCLK_PODF. */ + CLOCK_SetDiv(kCLOCK_PerclkDiv, 1); + /* Disable USDHC1 clock gate. */ + CLOCK_DisableClock(kCLOCK_Usdhc1); + /* Set USDHC1_PODF. */ + CLOCK_SetDiv(kCLOCK_Usdhc1Div, 1); + /* Set Usdhc1 clock source. */ + CLOCK_SetMux(kCLOCK_Usdhc1Mux, 0); + /* Disable USDHC2 clock gate. */ + CLOCK_DisableClock(kCLOCK_Usdhc2); + /* Set USDHC2_PODF. */ + CLOCK_SetDiv(kCLOCK_Usdhc2Div, 1); + /* Set Usdhc2 clock source. */ + CLOCK_SetMux(kCLOCK_Usdhc2Mux, 0); + /* In SDK projects, SDRAM (configured by SEMC) will be initialized in either debug script or dcd. + * With this macro SKIP_SYSCLK_INIT, system pll (selected to be SEMC source clock in SDK projects) will be left unchanged. + * Note: If another clock source is selected for SEMC, user may want to avoid changing that clock as well.*/ +#ifndef SKIP_SYSCLK_INIT + /* Disable Semc clock gate. */ + CLOCK_DisableClock(kCLOCK_Semc); + /* Set SEMC_PODF. */ + CLOCK_SetDiv(kCLOCK_SemcDiv, 7); + /* Set Semc alt clock source. */ + CLOCK_SetMux(kCLOCK_SemcAltMux, 0); + /* Set Semc clock source. */ + CLOCK_SetMux(kCLOCK_SemcMux, 0); +#endif + /* In SDK projects, external flash (configured by FLEXSPI) will be initialized by dcd. + * With this macro XIP_EXTERNAL_FLASH, usb1 pll (selected to be FLEXSPI clock source in SDK projects) will be left unchanged. + * Note: If another clock source is selected for FLEXSPI, user may want to avoid changing that clock as well.*/ +#if !(defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1)) + /* Disable Flexspi clock gate. */ + CLOCK_DisableClock(kCLOCK_FlexSpi); + /* Set FLEXSPI_PODF. */ + CLOCK_SetDiv(kCLOCK_FlexspiDiv, 0); + /* Set Flexspi clock source. */ + CLOCK_SetMux(kCLOCK_FlexspiMux, 3); +#endif + /* Disable CSI clock gate. */ + CLOCK_DisableClock(kCLOCK_Csi); + /* Set CSI_PODF. */ + CLOCK_SetDiv(kCLOCK_CsiDiv, 1); + /* Set Csi clock source. */ + CLOCK_SetMux(kCLOCK_CsiMux, 0); + /* Disable LPSPI clock gate. */ + CLOCK_DisableClock(kCLOCK_Lpspi1); + CLOCK_DisableClock(kCLOCK_Lpspi2); + CLOCK_DisableClock(kCLOCK_Lpspi3); + CLOCK_DisableClock(kCLOCK_Lpspi4); + /* Set LPSPI_PODF. */ + CLOCK_SetDiv(kCLOCK_LpspiDiv, 4); + /* Set Lpspi clock source. */ + CLOCK_SetMux(kCLOCK_LpspiMux, 2); + /* Disable TRACE clock gate. */ + CLOCK_DisableClock(kCLOCK_Trace); + /* Set TRACE_PODF. */ + CLOCK_SetDiv(kCLOCK_TraceDiv, 2); + /* Set Trace clock source. */ + CLOCK_SetMux(kCLOCK_TraceMux, 2); + /* Disable SAI1 clock gate. */ + CLOCK_DisableClock(kCLOCK_Sai1); + /* Set SAI1_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Sai1PreDiv, 3); + /* Set SAI1_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Sai1Div, 1); + /* Set Sai1 clock source. */ + CLOCK_SetMux(kCLOCK_Sai1Mux, 0); + /* Disable SAI2 clock gate. */ + CLOCK_DisableClock(kCLOCK_Sai2); + /* Set SAI2_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Sai2PreDiv, 3); + /* Set SAI2_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Sai2Div, 1); + /* Set Sai2 clock source. */ + CLOCK_SetMux(kCLOCK_Sai2Mux, 0); + /* Disable SAI3 clock gate. */ + CLOCK_DisableClock(kCLOCK_Sai3); + /* Set SAI3_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Sai3PreDiv, 3); + /* Set SAI3_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Sai3Div, 1); + /* Set Sai3 clock source. */ + CLOCK_SetMux(kCLOCK_Sai3Mux, 0); + /* Disable Lpi2c clock gate. */ + CLOCK_DisableClock(kCLOCK_Lpi2c1); + CLOCK_DisableClock(kCLOCK_Lpi2c2); + CLOCK_DisableClock(kCLOCK_Lpi2c3); + /* Set LPI2C_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Lpi2cDiv, 0); + /* Set Lpi2c clock source. */ + CLOCK_SetMux(kCLOCK_Lpi2cMux, 0); + /* Disable CAN clock gate. */ + CLOCK_DisableClock(kCLOCK_Can1); + CLOCK_DisableClock(kCLOCK_Can2); + CLOCK_DisableClock(kCLOCK_Can1S); + CLOCK_DisableClock(kCLOCK_Can2S); + /* Set CAN_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_CanDiv, 1); + /* Set Can clock source. */ + CLOCK_SetMux(kCLOCK_CanMux, 2); + /* Disable UART clock gate. */ + CLOCK_DisableClock(kCLOCK_Lpuart1); + CLOCK_DisableClock(kCLOCK_Lpuart2); + CLOCK_DisableClock(kCLOCK_Lpuart3); + CLOCK_DisableClock(kCLOCK_Lpuart4); + CLOCK_DisableClock(kCLOCK_Lpuart5); + CLOCK_DisableClock(kCLOCK_Lpuart6); + CLOCK_DisableClock(kCLOCK_Lpuart7); + CLOCK_DisableClock(kCLOCK_Lpuart8); + /* Set UART_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_UartDiv, 0); + /* Set Uart clock source. */ + CLOCK_SetMux(kCLOCK_UartMux, 0); + /* Disable LCDIF clock gate. */ + CLOCK_DisableClock(kCLOCK_LcdPixel); + /* Set LCDIF_PRED. */ + CLOCK_SetDiv(kCLOCK_LcdifPreDiv, 6); + /* Set LCDIF_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_LcdifDiv, 7); + /* Set Lcdif pre clock source. */ + CLOCK_SetMux(kCLOCK_LcdifPreMux, 5); + /* Disable SPDIF clock gate. */ + CLOCK_DisableClock(kCLOCK_Spdif); + /* Set SPDIF0_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Spdif0PreDiv, 1); + /* Set SPDIF0_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Spdif0Div, 7); + /* Set Spdif clock source. */ + CLOCK_SetMux(kCLOCK_SpdifMux, 3); + /* Disable Flexio1 clock gate. */ + CLOCK_DisableClock(kCLOCK_Flexio1); + /* Set FLEXIO1_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Flexio1PreDiv, 1); + /* Set FLEXIO1_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Flexio1Div, 7); + /* Set Flexio1 clock source. */ + CLOCK_SetMux(kCLOCK_Flexio1Mux, 3); + /* Disable Flexio2 clock gate. */ + CLOCK_DisableClock(kCLOCK_Flexio2); + /* Set FLEXIO2_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Flexio2PreDiv, 1); + /* Set FLEXIO2_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Flexio2Div, 7); + /* Set Flexio2 clock source. */ + CLOCK_SetMux(kCLOCK_Flexio2Mux, 3); + /* Set Pll3 sw clock source. */ + CLOCK_SetMux(kCLOCK_Pll3SwMux, 0); + /* Init ARM PLL. */ + CLOCK_InitArmPll(&armPllConfig_BOARD_BootClockRUN); + /* In SDK projects, SDRAM (configured by SEMC) will be initialized in either debug script or dcd. + * With this macro SKIP_SYSCLK_INIT, system pll (selected to be SEMC source clock in SDK projects) will be left unchanged. + * Note: If another clock source is selected for SEMC, user may want to avoid changing that clock as well.*/ +#ifndef SKIP_SYSCLK_INIT + /* Init System PLL. */ + CLOCK_InitSysPll(&sysPllConfig_BOARD_BootClockRUN); + /* Init System pfd0. */ + CLOCK_InitSysPfd(kCLOCK_Pfd0, 27); + /* Init System pfd1. */ + CLOCK_InitSysPfd(kCLOCK_Pfd1, 16); + /* Init System pfd2. */ + CLOCK_InitSysPfd(kCLOCK_Pfd2, 24); + /* Init System pfd3. */ + CLOCK_InitSysPfd(kCLOCK_Pfd3, 16); + /* Disable pfd offset. */ + CCM_ANALOG->PLL_SYS &= ~CCM_ANALOG_PLL_SYS_PFD_OFFSET_EN_MASK; +#endif + /* In SDK projects, external flash (configured by FLEXSPI) will be initialized by dcd. + * With this macro XIP_EXTERNAL_FLASH, usb1 pll (selected to be FLEXSPI clock source in SDK projects) will be left unchanged. + * Note: If another clock source is selected for FLEXSPI, user may want to avoid changing that clock as well.*/ +#if !(defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1)) + /* Init Usb1 PLL. */ + CLOCK_InitUsb1Pll(&usb1PllConfig_BOARD_BootClockRUN); + /* Init Usb1 pfd0. */ + CLOCK_InitUsb1Pfd(kCLOCK_Pfd0, 33); + /* Init Usb1 pfd1. */ + CLOCK_InitUsb1Pfd(kCLOCK_Pfd1, 16); + /* Init Usb1 pfd2. */ + CLOCK_InitUsb1Pfd(kCLOCK_Pfd2, 17); + /* Init Usb1 pfd3. */ + CLOCK_InitUsb1Pfd(kCLOCK_Pfd3, 19); + /* Disable Usb1 PLL output for USBPHY1. */ + CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK; +#endif + /* DeInit Audio PLL. */ + CLOCK_DeinitAudioPll(); + /* Bypass Audio PLL. */ + CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllAudio, 1); + /* Set divider for Audio PLL. */ + CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK; + CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK; + /* Enable Audio PLL output. */ + CCM_ANALOG->PLL_AUDIO |= CCM_ANALOG_PLL_AUDIO_ENABLE_MASK; + /* DeInit Video PLL. */ + CLOCK_DeinitVideoPll(); + /* Bypass Video PLL. */ + CCM_ANALOG->PLL_VIDEO |= CCM_ANALOG_PLL_VIDEO_BYPASS_MASK; + /* Set divider for Video PLL. */ + CCM_ANALOG->MISC2 = (CCM_ANALOG->MISC2 & (~CCM_ANALOG_MISC2_VIDEO_DIV_MASK)) | CCM_ANALOG_MISC2_VIDEO_DIV(0); + /* Enable Video PLL output. */ + CCM_ANALOG->PLL_VIDEO |= CCM_ANALOG_PLL_VIDEO_ENABLE_MASK; + /* DeInit Enet PLL. */ + CLOCK_DeinitEnetPll(); + /* Bypass Enet PLL. */ + CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllEnet, 1); + /* Set Enet output divider. */ + CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK)) | CCM_ANALOG_PLL_ENET_DIV_SELECT(1); + /* Enable Enet output. */ + CCM_ANALOG->PLL_ENET |= CCM_ANALOG_PLL_ENET_ENABLE_MASK; + /* Enable Enet25M output. */ + CCM_ANALOG->PLL_ENET |= CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_MASK; + /* DeInit Usb2 PLL. */ + CLOCK_DeinitUsb2Pll(); + /* Bypass Usb2 PLL. */ + CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllUsb2, 1); + /* Enable Usb2 PLL output. */ + CCM_ANALOG->PLL_USB2 |= CCM_ANALOG_PLL_USB2_ENABLE_MASK; + /* Set preperiph clock source. */ + CLOCK_SetMux(kCLOCK_PrePeriphMux, 3); + /* Set periph clock source. */ + CLOCK_SetMux(kCLOCK_PeriphMux, 0); + /* Set periph clock2 clock source. */ + CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 0); + /* Set per clock source. */ + CLOCK_SetMux(kCLOCK_PerclkMux, 0); + /* Set lvds1 clock source. */ + CCM_ANALOG->MISC1 = (CCM_ANALOG->MISC1 & (~CCM_ANALOG_MISC1_LVDS1_CLK_SEL_MASK)) | CCM_ANALOG_MISC1_LVDS1_CLK_SEL(0); + /* Set clock out1 divider. */ + CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO1_DIV_MASK)) | CCM_CCOSR_CLKO1_DIV(0); + /* Set clock out1 source. */ + CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO1_SEL_MASK)) | CCM_CCOSR_CLKO1_SEL(1); + /* Set clock out2 divider. */ + CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO2_DIV_MASK)) | CCM_CCOSR_CLKO2_DIV(0); + /* Set clock out2 source. */ + CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO2_SEL_MASK)) | CCM_CCOSR_CLKO2_SEL(18); + /* Set clock out1 drives clock out1. */ + CCM->CCOSR &= ~CCM_CCOSR_CLK_OUT_SEL_MASK; + /* Disable clock out1. */ + CCM->CCOSR &= ~CCM_CCOSR_CLKO1_EN_MASK; + /* Disable clock out2. */ + CCM->CCOSR &= ~CCM_CCOSR_CLKO2_EN_MASK; + /* Set SAI1 MCLK1 clock source. */ + IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk1Sel, 0); + /* Set SAI1 MCLK2 clock source. */ + IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk2Sel, 0); + /* Set SAI1 MCLK3 clock source. */ + IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk3Sel, 0); + /* Set SAI2 MCLK3 clock source. */ + IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI2MClk3Sel, 0); + /* Set SAI3 MCLK3 clock source. */ + IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI3MClk3Sel, 0); + /* Set MQS configuration. */ + IOMUXC_MQSConfig(IOMUXC_GPR,kIOMUXC_MqsPwmOverSampleRate32, 0); + /* Set ENET Tx clock source. */ + IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1RefClkMode, false); + /* Set GPT1 High frequency reference clock source. */ + IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT1_MASK; + /* Set GPT2 High frequency reference clock source. */ + IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK; + /* Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; +} + diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/clock_config.h b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/clock_config.h new file mode 100644 index 0000000000..43fbb9d805 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/clock_config.h @@ -0,0 +1,66 @@ +#ifndef _CLOCK_CONFIG_H_ +#define _CLOCK_CONFIG_H_ + +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define BOARD_XTAL0_CLK_HZ 24000000U /*!< Board xtal0 frequency in Hz */ + +#define BOARD_XTAL32K_CLK_HZ 32768U /*!< Board xtal32k frequency in Hz */ +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes default configuration of clocks. + * + */ +void BOARD_InitBootClocks(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ********************** Configuration BOARD_BootClockRUN *********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockRUN configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKRUN_CORE_CLOCK 600000000U /*!< Core clock frequency: 600000000Hz */ + +/*! @brief Arm PLL set for BOARD_BootClockRUN configuration. + */ +extern const clock_arm_pll_config_t armPllConfig_BOARD_BootClockRUN; +/*! @brief Usb1 PLL set for BOARD_BootClockRUN configuration. + */ +extern const clock_usb_pll_config_t usb1PllConfig_BOARD_BootClockRUN; +/*! @brief Sys PLL for BOARD_BootClockRUN configuration. + */ +extern const clock_sys_pll_config_t sysPllConfig_BOARD_BootClockRUN; + +/******************************************************************************* + * API for BOARD_BootClockRUN configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockRUN(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +#endif /* _CLOCK_CONFIG_H_ */ + diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/pin_mux.c b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/pin_mux.c new file mode 100644 index 0000000000..8ed0a9d069 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/pin_mux.c @@ -0,0 +1,81 @@ +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!GlobalInfo +product: Pins v5.0 +processor: MIMXRT1052xxxxB +package_id: MIMXRT1052DVL6B +mcu_data: ksdk2_0 +processor_version: 5.0.2 +board: IMXRT1050-EVKB + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ + +#include "fsl_common.h" +#include "fsl_iomuxc.h" +#include "pin_mux.h" + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitBootPins + * Description : Calls initialization functions. + * + * END ****************************************************************************************************************/ +void BOARD_InitBootPins(void) { +} + +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitPins: +- options: {callFromInitBoot: 'false', coreID: core0, enableClock: 'true'} +- pin_list: + - {pin_num: L14, peripheral: LPUART1, signal: RX, pin_signal: GPIO_AD_B0_13} + - {pin_num: K14, peripheral: LPUART1, signal: TX, pin_signal: GPIO_AD_B0_12} + - {pin_num: M14, peripheral: LPSPI3, signal: SCK, pin_signal: GPIO_AD_B0_00} + - {pin_num: M11, peripheral: LPSPI3, signal: SDI, pin_signal: GPIO_AD_B0_02} + - {pin_num: H10, peripheral: LPSPI3, signal: SDO, pin_signal: GPIO_AD_B0_01} + - {pin_num: M5, peripheral: LPUART4, signal: RX, pin_signal: GPIO_SD_B1_01} + - {pin_num: L5, peripheral: LPUART4, signal: TX, pin_signal: GPIO_SD_B1_00} + - {pin_num: F11, peripheral: GPIO1, signal: 'gpio_io, 04', pin_signal: GPIO_AD_B0_04} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitPins(void) { + CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03U */ + + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_00_LPSPI3_SCK, /* GPIO_AD_B0_00 is configured as LPSPI3_SCK */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_01_LPSPI3_SDO, /* GPIO_AD_B0_01 is configured as LPSPI3_SDO */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_02_LPSPI3_SDI, /* GPIO_AD_B0_02 is configured as LPSPI3_SDI */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 is configured as LPUART1_TX */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 is configured as LPUART1_RX */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_SD_B1_00_LPUART4_TX, /* GPIO_SD_B1_00 is configured as LPUART4_TX */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_SD_B1_01_LPUART4_RX, /* GPIO_SD_B1_01 is configured as LPUART4_RX */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ +} + +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/pin_mux.h b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/pin_mux.h new file mode 100644 index 0000000000..b1d61c2782 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MCUX_Config/pin_mux.h @@ -0,0 +1,182 @@ +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +#ifndef _PIN_MUX_H_ +#define _PIN_MUX_H_ + +/*********************************************************************************************************************** + * Definitions + **********************************************************************************************************************/ + +/*! @brief Direction type */ +typedef enum _pin_mux_direction +{ + kPIN_MUX_DirectionInput = 0U, /* Input direction */ + kPIN_MUX_DirectionOutput = 1U, /* Output direction */ + kPIN_MUX_DirectionInputOrOutput = 2U /* Input or output direction */ +} pin_mux_direction_t; + +/*! + * @addtogroup pin_mux + * @{ + */ + +/*********************************************************************************************************************** + * API + **********************************************************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @brief Calls initialization functions. + * + */ +void BOARD_InitBootPins(void); + +/* GPIO_AD_B0_13 (coord L14), UART1_RXD */ +#define BOARD_INITPINS_UART1_RXD_PERIPHERAL LPUART1 /*!< Device name: LPUART1 */ +#define BOARD_INITPINS_UART1_RXD_SIGNAL RX /*!< LPUART1 signal: RX */ + +/* GPIO_AD_B0_12 (coord K14), UART1_TXD */ +#define BOARD_INITPINS_UART1_TXD_PERIPHERAL LPUART1 /*!< Device name: LPUART1 */ +#define BOARD_INITPINS_UART1_TXD_SIGNAL TX /*!< LPUART1 signal: TX */ + +/* GPIO_SD_B1_03 (coord M4), FlexSPI_D0_B */ +#define BOARD_INITPINS_FlexSPI_D0_B_GPIO GPIO3 /*!< GPIO device name: GPIO3 */ +#define BOARD_INITPINS_FlexSPI_D0_B_PORT GPIO3 /*!< PORT device name: GPIO3 */ +#define BOARD_INITPINS_FlexSPI_D0_B_PIN 3U /*!< GPIO3 pin index: 3 */ + +/* PMIC_ON_REQ (coord K7), PMIC_ON_REQ */ +#define BOARD_INITPINS_PMIC_ON_REQ_GPIO GPIO5 /*!< GPIO device name: GPIO5 */ +#define BOARD_INITPINS_PMIC_ON_REQ_PORT GPIO5 /*!< PORT device name: GPIO5 */ +#define BOARD_INITPINS_PMIC_ON_REQ_PIN 1U /*!< GPIO5 pin index: 1 */ + +/* GPIO_AD_B0_05 (coord G14), CAN_STBY/BOOT_MODE[1]/Flash_RST/U12[8] */ +#define BOARD_INITPINS_CAN_STBY_GPIO GPIO1 /*!< GPIO device name: GPIO1 */ +#define BOARD_INITPINS_CAN_STBY_PORT GPIO1 /*!< PORT device name: GPIO1 */ +#define BOARD_INITPINS_CAN_STBY_PIN 5U /*!< GPIO1 pin index: 5 */ + +/* GPIO_EMC_40 (coord A7), ENET_MDC */ +#define BOARD_INITPINS_ENET_MDC_GPIO GPIO3 /*!< GPIO device name: GPIO3 */ +#define BOARD_INITPINS_ENET_MDC_PORT GPIO3 /*!< PORT device name: GPIO3 */ +#define BOARD_INITPINS_ENET_MDC_PIN 26U /*!< GPIO3 pin index: 26 */ + +/* GPIO_B0_00 (coord D7), LCDIF_CLK */ +#define BOARD_INITPINS_LCDIF_CLK_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_CLK_SIGNAL lcdif_clk /*!< LCDIF signal: lcdif_clk */ + +/* GPIO_B0_04 (coord C8), LCDIF_D0/BT_CFG[0] */ +#define BOARD_INITPINS_LCDIF_D0_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D0_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D0_CHANNEL 0U /*!< LCDIF lcdif_data channel: 00 */ + +/* GPIO_B0_05 (coord B8), LCDIF_D1/BT_CFG[1] */ +#define BOARD_INITPINS_LCDIF_D1_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D1_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D1_CHANNEL 1U /*!< LCDIF lcdif_data channel: 01 */ + +/* GPIO_B0_06 (coord A8), LCDIF_D2/BT_CFG[2] */ +#define BOARD_INITPINS_LCDIF_D2_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D2_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D2_CHANNEL 2U /*!< LCDIF lcdif_data channel: 02 */ + +/* GPIO_B0_08 (coord B9), LCDIF_D4/BT_CFG[4] */ +#define BOARD_INITPINS_LCDIF_D4_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D4_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D4_CHANNEL 4U /*!< LCDIF lcdif_data channel: 04 */ + +/* GPIO_B0_07 (coord A9), LCDIF_D3/BT_CFG[3] */ +#define BOARD_INITPINS_LCDIF_D3_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D3_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D3_CHANNEL 3U /*!< LCDIF lcdif_data channel: 03 */ + +/* GPIO_B0_09 (coord C9), LCDIF_D5/BT_CFG[5] */ +#define BOARD_INITPINS_LCDIF_D5_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D5_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D5_CHANNEL 5U /*!< LCDIF lcdif_data channel: 05 */ + +/* GPIO_B0_10 (coord D9), LCDIF_D6/BT_CFG[6] */ +#define BOARD_INITPINS_LCDIF_D6_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D6_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D6_CHANNEL 6U /*!< LCDIF lcdif_data channel: 06 */ + +/* GPIO_B0_11 (coord A10), LCDIF_D7/BT_CFG[7] */ +#define BOARD_INITPINS_LCDIF_D7_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D7_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D7_CHANNEL 7U /*!< LCDIF lcdif_data channel: 07 */ + +/* GPIO_B0_12 (coord C10), LCDIF_D8/BT_CFG[8] */ +#define BOARD_INITPINS_LCDIF_D8_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D8_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D8_CHANNEL 8U /*!< LCDIF lcdif_data channel: 08 */ + +/* GPIO_B0_13 (coord D10), LCDIF_D9/BT_CFG[9] */ +#define BOARD_INITPINS_LCDIF_D9_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D9_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D9_CHANNEL 9U /*!< LCDIF lcdif_data channel: 09 */ + +/* GPIO_B0_14 (coord E10), LCDIF_D10/BT_CFG[10] */ +#define BOARD_INITPINS_LCDIF_D10_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D10_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D10_CHANNEL 10U /*!< LCDIF lcdif_data channel: 10 */ + +/* GPIO_B0_15 (coord E11), LCDIF_D11/BT_CFG[11] */ +#define BOARD_INITPINS_LCDIF_D11_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D11_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D11_CHANNEL 11U /*!< LCDIF lcdif_data channel: 11 */ + +/* GPIO_B1_00 (coord A11), LCDIF_D12 */ +#define BOARD_INITPINS_LCDIF_D12_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D12_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D12_CHANNEL 12U /*!< LCDIF lcdif_data channel: 12 */ + +/* GPIO_B1_01 (coord B11), LCDIF_D13 */ +#define BOARD_INITPINS_LCDIF_D13_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D13_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D13_CHANNEL 13U /*!< LCDIF lcdif_data channel: 13 */ + +/* GPIO_B1_02 (coord C11), LCDIF_D14 */ +#define BOARD_INITPINS_LCDIF_D14_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D14_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D14_CHANNEL 14U /*!< LCDIF lcdif_data channel: 14 */ + +/* GPIO_B1_03 (coord D11), LCDIF_D15 */ +#define BOARD_INITPINS_LCDIF_D15_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_D15_SIGNAL lcdif_data /*!< LCDIF signal: lcdif_data */ +#define BOARD_INITPINS_LCDIF_D15_CHANNEL 15U /*!< LCDIF lcdif_data channel: 15 */ + +/* GPIO_B0_01 (coord E7), LCDIF_ENABLE */ +#define BOARD_INITPINS_LCDIF_ENABLE_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_ENABLE_SIGNAL lcdif_enable /*!< LCDIF signal: lcdif_enable */ + +/* GPIO_B0_02 (coord E8), LCDIF_HSYNC */ +#define BOARD_INITPINS_LCDIF_HSYNC_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_HSYNC_SIGNAL lcdif_hsync /*!< LCDIF signal: lcdif_hsync */ + +/* GPIO_B0_03 (coord D8), LCDIF_VSYNC */ +#define BOARD_INITPINS_LCDIF_VSYNC_PERIPHERAL LCDIF /*!< Device name: LCDIF */ +#define BOARD_INITPINS_LCDIF_VSYNC_SIGNAL lcdif_vsync /*!< LCDIF signal: lcdif_vsync */ + + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitPins(void); + +#if defined(__cplusplus) +} +#endif + +/*! + * @} + */ +#endif /* _PIN_MUX_H_ */ + +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MIMXRT105x_QuadSPI_4KB_SEC.FLM b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/MIMXRT105x_QuadSPI_4KB_SEC.FLM new file mode 100644 index 0000000000000000000000000000000000000000..ac4c378c6aa4c1fbb942663a952ab994fe97ed60 GIT binary patch literal 1509352 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
BJqCs^_<8U@eAHO!UHe)N_s{+1!PjinN_ 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 <9ElrMfQ4bzDnzLmd{HSm?8tRIOVZYgkt=>p?Oq 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 M5XZ-rT8svkwx3if+r<>1z!6*8 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 C71mt< literal 0 HcmV?d00001 diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/SConscript b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/SConscript new file mode 100644 index 0000000000..e6008ae576 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/SConscript @@ -0,0 +1,20 @@ +from building import * + +cwd = GetCurrentDir() + +# add the general drivers. +src = Split(""" +board.c +MCUX_Config/clock_config.c +MCUX_Config/pin_mux.c +""") + +CPPPATH = [cwd,cwd + '/MCUX_Config',cwd + '/ports'] +CPPDEFINES = ['CPU_MIMXRT1052CVL5B', 'SKIP_SYSCLK_INIT', 'EVK_MCIMXRM', 'FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1','XIP_EXTERNAL_FLASH=1'] + +if GetDepend(['BSP_USING_SPI_FLASH']): + src += Glob('ports/spi_flash_init.c') + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES=CPPDEFINES) + +Return('group') diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/board.c b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/board.c new file mode 100644 index 0000000000..e50e511070 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/board.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2009-01-05 Bernard first implementation + */ + +#include +#include +#include "board.h" +#include "pin_mux.h" + +#ifdef BSP_USING_DMA +#include "fsl_dmamux.h" +#include "fsl_edma.h" +#endif + +#define NVIC_PRIORITYGROUP_0 0x00000007U /*!< 0 bits for pre-emption priority + 4 bits for subpriority */ +#define NVIC_PRIORITYGROUP_1 0x00000006U /*!< 1 bits for pre-emption priority + 3 bits for subpriority */ +#define NVIC_PRIORITYGROUP_2 0x00000005U /*!< 2 bits for pre-emption priority + 2 bits for subpriority */ +#define NVIC_PRIORITYGROUP_3 0x00000004U /*!< 3 bits for pre-emption priority + 1 bits for subpriority */ +#define NVIC_PRIORITYGROUP_4 0x00000003U /*!< 4 bits for pre-emption priority + 0 bits for subpriority */ + +/* MPU configuration. */ +static void BOARD_ConfigMPU(void) +{ + /* Disable I cache and D cache */ + SCB_DisableICache(); + SCB_DisableDCache(); + + /* Disable MPU */ + ARM_MPU_Disable(); + + /* Region 0 setting */ + MPU->RBAR = ARM_MPU_RBAR(0, 0xC0000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB); + + /* Region 1 setting */ + MPU->RBAR = ARM_MPU_RBAR(1, 0x80000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB); + + /* Region 2 setting */ + // spi flash: normal type, cacheable, no bufferable, no shareable + MPU->RBAR = ARM_MPU_RBAR(2, 0x60000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_512MB); + + /* Region 3 setting */ + MPU->RBAR = ARM_MPU_RBAR(3, 0x00000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB); + + /* Region 4 setting */ + MPU->RBAR = ARM_MPU_RBAR(4, 0x00000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB); + + /* Region 5 setting */ + MPU->RBAR = ARM_MPU_RBAR(5, 0x20000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB); + + /* Region 6 setting */ + MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB); + +#if defined(BSP_USING_SDRAM) + /* Region 7 setting */ + MPU->RBAR = ARM_MPU_RBAR(7, 0x80000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_32MB); + + /* Region 8 setting */ + MPU->RBAR = ARM_MPU_RBAR(8, 0x81E00000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 1, 0, 0, 0, ARM_MPU_REGION_SIZE_2MB); +#endif + + /* Enable MPU */ + ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk); + + /* Enable I cache and D cache */ + SCB_EnableDCache(); + SCB_EnableICache(); +} + + +/* This is the timer interrupt service routine. */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +#ifdef BSP_USING_DMA +void imxrt_dma_init(void) +{ + edma_config_t config; + + DMAMUX_Init(DMAMUX); + EDMA_GetDefaultConfig(&config); + EDMA_Init(DMA0, &config); +} +#endif + +void rt_hw_board_init() +{ + BOARD_ConfigMPU(); + BOARD_InitPins(); + BOARD_BootClockRUN(); + + NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + +#ifdef BSP_USING_DMA + imxrt_dma_init(); +#endif + +#ifdef RT_USING_HEAP + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif +} + diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/board.h b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/board.h new file mode 100644 index 0000000000..100b932ebd --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/board.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2009-09-22 Bernard add board.h to this bsp + */ + +// <<< Use Configuration Wizard in Context Menu >>> +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "fsl_common.h" +#include "clock_config.h" + +#ifdef __CC_ARM +extern int Image$$RTT_HEAP$$ZI$$Base; +extern int Image$$RTT_HEAP$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RTT_HEAP$$ZI$$Base) +#define HEAP_END (&Image$$RTT_HEAP$$ZI$$Limit) + +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +extern void __RTT_HEAP_END; +#define HEAP_END (&__RTT_HEAP_END) + +#else +extern int heap_start; +extern int heap_end; +#define HEAP_BEGIN (&heap_start) +#define HEAP_END (&heap_end) +#endif + +#define HEAP_SIZE ((uint32_t)HEAP_END - (uint32_t)HEAP_BEGIN) + +void rt_hw_board_init(void); + +#endif + diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.icf b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.icf new file mode 100644 index 0000000000..e1dd5a7ea4 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.icf @@ -0,0 +1,95 @@ +/* +** ################################################################### +** Processors: MIMXRT1052CVJ5B +** MIMXRT1052CVL5B +** MIMXRT1052DVJ6B +** MIMXRT1052DVL6B +** +** Compiler: IAR ANSI C/C++ Compiler for ARM +** Reference manual: IMXRT1050RM Rev.1, 03/2018 +** Version: rev. 1.0, 2018-09-21 +** Build: b180921 +** +** Abstract: +** Linker file for the IAR ANSI C/C++ Compiler for ARM +** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2018 NXP +** All rights reserved. +** +** SPDX-License-Identifier: BSD-3-Clause +** +** http: www.nxp.com +** mail: support@nxp.com +** +** ################################################################### +*/ + +define symbol m_interrupts_start = 0x60002000; +define symbol m_interrupts_end = 0x600023FF; + +define symbol m_text_start = 0x60002400; +define symbol m_text_end = 0x607FFFFF; + +define symbol m_data_start = 0x20000000; +define symbol m_data_end = 0x2001FFFF; + +define symbol m_data2_start = 0x20200000; +define symbol m_data2_end = 0x2023FFFF; + +define exported symbol m_boot_hdr_conf_start = 0x60000000; +define symbol m_boot_hdr_ivt_start = 0x60001000; +define symbol m_boot_hdr_boot_data_start = 0x60001020; +define symbol m_boot_hdr_dcd_data_start = 0x60001030; + +/* Sizes */ +if (isdefinedsymbol(__stack_size__)) { + define symbol __size_cstack__ = __stack_size__; +} else { + define symbol __size_cstack__ = 0x0400; +} + +if (isdefinedsymbol(__heap_size__)) { + define symbol __size_heap__ = __heap_size__; +} else { + define symbol __size_heap__ = 0x0400; +} + +define exported symbol __VECTOR_TABLE = m_interrupts_start; +define exported symbol __VECTOR_RAM = m_interrupts_start; +define exported symbol __RAM_VECTOR_TABLE_SIZE = 0x0; +define exported symbol __RTT_HEAP_END = m_data_end; + +define memory mem with size = 4G; +define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end] + | mem:[from m_text_start to m_text_end]; + +define region DATA_region = mem:[from m_data_start to m_data_end-__size_cstack__]; +define region DATA2_region = mem:[from m_data2_start to m_data2_end]; +define region CSTACK_region = mem:[from m_data_end-__size_cstack__+1 to m_data_end]; + +define block CSTACK with alignment = 8, size = __size_cstack__ { }; +define block HEAP with alignment = 8, size = __size_heap__ { }; +define block RW { readwrite }; +define block ZI { zi }; +define block NCACHE_VAR { section NonCacheable , section NonCacheable.init }; + +initialize by copy { readwrite, section .textrw }; +do not initialize { section .noinit }; + +place at address mem: m_interrupts_start { readonly section .intvec }; + +place at address mem:m_boot_hdr_conf_start { section .boot_hdr.conf }; +place at address mem:m_boot_hdr_ivt_start { section .boot_hdr.ivt }; +place at address mem:m_boot_hdr_boot_data_start { readonly section .boot_hdr.boot_data }; +place at address mem:m_boot_hdr_dcd_data_start { readonly section .boot_hdr.dcd_data }; + +keep{ section .boot_hdr.conf, section .boot_hdr.ivt, section .boot_hdr.boot_data, section .boot_hdr.dcd_data }; + +place in TEXT_region { readonly }; +place in DATA_region { block RW }; +place in DATA_region { block ZI }; +place in DATA_region { last block HEAP }; +place in DATA_region { block NCACHE_VAR }; +place in CSTACK_region { block CSTACK }; + diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.lds b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.lds new file mode 100644 index 0000000000..b8c229ae3c --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.lds @@ -0,0 +1,276 @@ +/* +** ################################################################### +** Processors: MIMXRT1052CVL5A +** MIMXRT1052DVL6A +** +** Compiler: GNU C Compiler +** Reference manual: IMXRT1050RM Rev.C, 08/2017 +** Version: rev. 0.1, 2017-01-10 +** Build: b170927 +** +** Abstract: +** Linker file for the GNU C Compiler +** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2017 NXP +** Redistribution and use in source and binary forms, with or without modification, +** are permitted provided that the following conditions are met: +** +** 1. Redistributions of source code must retain the above copyright notice, this list +** of conditions and the following disclaimer. +** +** 2. Redistributions in binary form must reproduce the above copyright notice, this +** list of conditions and the following disclaimer in the documentation and/or +** other materials provided with the distribution. +** +** 3. Neither the name of the copyright holder nor the names of its +** contributors may be used to endorse or promote products derived from this +** software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** http: www.nxp.com +** mail: support@nxp.com +** +** ################################################################### +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400; +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400; + +/* Specify the memory areas */ +MEMORY +{ + m_boot_data (RX) : ORIGIN = 0x60000000, LENGTH = 0x00001000 + m_image_vertor_table (RX) : ORIGIN = 0x60001000, LENGTH = 0x00001000 + + m_interrupts (RX) : ORIGIN = 0x60002000, LENGTH = 0x00000400 + m_text (RX) : ORIGIN = 0x60002400, LENGTH = 0x1F7FDC00 + + m_itcm (RW) : ORIGIN = 0x00000000, LENGTH = 0x00020000 + m_dtcm (RW) : ORIGIN = 0x20000000, LENGTH = 0x00020000 + m_ocram (RW) : ORIGIN = 0x20200000, LENGTH = 0x00040000 + + m_sdram (RW) : ORIGIN = 0x80000000, LENGTH = 0x01E00000 + m_nocache (RW) : ORIGIN = 0x81E00000, LENGTH = 0x00200000 +} + +/* Define output sections */ +SECTIONS +{ + .boot_data : + { + KEEP(*(.boot_hdr.conf)) + } > m_boot_data + + .image_vertor_table : + { + KEEP(*(.boot_hdr.ivt)) + KEEP(*(.boot_hdr.boot_data)) + KEEP(*(.boot_hdr.dcd_data)) + } > m_image_vertor_table + + /* The startup code goes first into internal RAM */ + .interrupts : + { + __VECTOR_TABLE = .; + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } > m_interrupts + + __VECTOR_RAM = __VECTOR_TABLE; + __RAM_VECTOR_TABLE_SIZE_BYTES = 0x0; + + /* The program code and other data goes into internal RAM */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + } > m_text + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > m_text + + .ARM : + { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } > m_text + + .ctors : + { + PROVIDE(__ctors_start__ = .); + /* __CTOR_LIST__ = .; */ + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + /* __CTOR_END__ = .; */ + PROVIDE(__ctors_end__ = .); + } > m_text + + .dtors : + { + PROVIDE(__dtors_start__ = .); + /* __DTOR_LIST__ = .; */ + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* __DTOR_END__ = .; */ + PROVIDE(__dtors_end__ = .); + } > m_text + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > m_text + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } > m_text + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } > m_text + + __etext = .; /* define a global symbol at end of code */ + __DATA_ROM = .; /* Symbol is used by startup for data initialization */ + + .data : AT(__DATA_ROM) + { + . = ALIGN(4); + __DATA_RAM = .; + __data_start__ = .; /* create a global symbol at data start */ + *(m_usb_dma_init_data) + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + KEEP(*(.jcr*)) + . = ALIGN(4); + __data_end__ = .; /* define a global symbol at data end */ + } > m_dtcm + + __NDATA_ROM = __DATA_ROM + (__data_end__ - __data_start__); + .ncache.init : AT(__NDATA_ROM) + { + __noncachedata_start__ = .; /* create a global symbol at ncache data start */ + *(NonCacheable.init) + . = ALIGN(4); + __noncachedata_init_end__ = .; /* create a global symbol at initialized ncache data end */ + } > m_nocache + . = __noncachedata_init_end__; + .ncache : + { + *(NonCacheable) + . = ALIGN(4); + __noncachedata_end__ = .; /* define a global symbol at ncache data end */ + } > m_nocache + + __DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__); + text_end = ORIGIN(m_text) + LENGTH(m_text); + ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data") + + /* Uninitialized data section */ + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + . = ALIGN(4); + __START_BSS = .; + __bss_start__ = .; + *(m_usb_dma_noninit_data) + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + __END_BSS = .; + } > m_dtcm + + .stack : + { + . = ALIGN(8); + stack_start = .; + . += STACK_SIZE; + stack_end = .; + __StackTop = .; + } > m_dtcm + + .RTT_HEAP : + { + heap_start = .; + . = ALIGN(8); + } > m_dtcm + + PROVIDE(heap_end = ORIGIN(m_dtcm) + LENGTH(m_dtcm)); + + .ARM.attributes 0 : { *(.ARM.attributes) } + +} + diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.sct b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.sct new file mode 100644 index 0000000000..7200f9d479 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/linker_scripts/link.sct @@ -0,0 +1,112 @@ +#! armcc -E +/* +** ################################################################### +** Processors: MIMXRT1052CVL5A +** MIMXRT1052DVL6A +** +** Compiler: Keil ARM C/C++ Compiler +** Reference manual: IMXRT1050RM Rev.C, 08/2017 +** Version: rev. 0.1, 2017-01-10 +** Build: b170927 +** +** Abstract: +** Linker file for the Keil ARM C/C++ Compiler +** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2017 NXP +** Redistribution and use in source and binary forms, with or without modification, +** are permitted provided that the following conditions are met: +** +** 1. Redistributions of source code must retain the above copyright notice, this list +** of conditions and the following disclaimer. +** +** 2. Redistributions in binary form must reproduce the above copyright notice, this +** list of conditions and the following disclaimer in the documentation and/or +** other materials provided with the distribution. +** +** 3. Neither the name of the copyright holder nor the names of its +** contributors may be used to endorse or promote products derived from this +** software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** http: www.nxp.com +** mail: support@nxp.com +** +** ################################################################### +*/ + +#define m_flash_config_start 0x60000000 +#define m_flash_config_size 0x00001000 + +#define m_ivt_start 0x60001000 +#define m_ivt_size 0x00001000 + +#define m_text_start 0x60002000 +#define m_text_size 0x1F7FE000 + +#define m_data_start 0x20000000 +#define m_data_size 0x00020000 + +#define m_ncache_start 0x81E00000 +#define m_ncache_size 0x00200000 + +/* Sizes */ +#if (defined(__stack_size__)) + #define Stack_Size __stack_size__ +#else + #define Stack_Size 0x1000 +#endif + +#if (defined(__heap_size__)) + #define Heap_Size __heap_size__ +#else + #define Heap_Size 0x0400 +#endif + +#define RTT_HEAP_SIZE (m_data_size-ImageLength(RW_m_data)-ImageLength(ARM_LIB_HEAP)-ImageLength(ARM_LIB_STACK)) + +; load region size_region +LR_IROM1 m_text_start m_text_size +{ + ER_IROM1 m_text_start m_text_size ; load address = execution address + { + * (RESET,+FIRST) + * (InRoot$$Sections) + .ANY (+RO) + } + + RW_m_data m_data_start m_data_size-Stack_Size-Heap_Size ; RW data + { + .ANY (+RW +ZI) + } + + ARM_LIB_HEAP +0 EMPTY Heap_Size{} ; Heap region growing up + ARM_LIB_STACK +0 EMPTY Stack_Size{} ; Stack region growing down + RTT_HEAP +0 EMPTY RTT_HEAP_SIZE{} + + ; ncache RW data + RW_m_ncache m_ncache_start m_ncache_size + { + * (NonCacheable.init) + * (NonCacheable) + } + ITCM 0x400 0xFBFF { + ;drv_flexspi_hyper.o(+RO) + ;fsl_flexspi.o(+RO) + * (*CLOCK_DisableClock) + * (*CLOCK_ControlGate) + * (*CLOCK_EnableClock) + * (*CLOCK_SetDiv) + * (itcm) + } +} diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/board/ports/sdram_port.h b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/ports/sdram_port.h new file mode 100644 index 0000000000..477987b4e7 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/board/ports/sdram_port.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-12-05 zylx The first version for STM32F4xx + * 2019-4-25 misonyo port to IMXRT + */ + +#ifndef SDRAM_PORT_H__ +#define SDRAM_PORT_H__ + +/* parameters for sdram peripheral */ + +#define SDRAM_BANK_ADDR ((uint32_t)0x80000000U) +/* region#0/1/2/3: kSEMC_SDRAM_CS0/1/2/3 */ +#define SDRAM_REGION kSEMC_SDRAM_CS0 +/* CS pin: kSEMC_MUXCSX0/1/2/3 */ +#define SDRAM_CS_PIN kSEMC_MUXCSX0 +/* size(kbyte):32MB = 32*1024*1KBytes */ +#define SDRAM_SIZE ((uint32_t)0x8000) +/* data width: kSEMC_PortSize8Bit,kSEMC_PortSize16Bit */ +#define SDRAM_DATA_WIDTH kSEMC_PortSize16Bit +/* column bit numbers: kSEMC_SdramColunm_9/10/11/12bit */ +#define SDRAM_COLUMN_BITS kSEMC_SdramColunm_9bit +/* cas latency clock number: kSEMC_LatencyOne/Two/Three */ +#define SDRAM_CAS_LATENCY kSEMC_LatencyThree + +/* Timing configuration for W9825G6KH */ +/* TRP:precharge to active command time (ns) */ +#define SDRAM_TRP 18 +/* TRCD:active to read/write command delay time (ns) */ +#define SDRAM_TRCD 18 +/* The time between two refresh commands,Use the maximum of the (Trfc , Txsr).(ns) */ +#define SDRAM_REFRESH_RECOVERY 67 +/* TWR:write recovery time (ns). */ +#define SDRAM_TWR 12 +/* TRAS:active to precharge command time (ns). */ +#define SDRAM_TRAS 42 +/* TRC time (ns). */ +#define SDRAM_TRC 60 +/* active to active time (ns). */ +#define SDRAM_ACT2ACT 60 +/* refresh time (ns). 64ms */ +#define SDRAM_REFRESH_ROW 64 * 1000000 / 8192 + +#endif /* SDRAM_PORT_H__ */ diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/figures/Arch_Mix.jpg b/bsp/imxrt/imxrt1052-seeed-ArchMix/figures/Arch_Mix.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d430d0e19a3e4fe8f8583c599c0b1621207b24e8 GIT binary patch literal 290625 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

!F=!G%@a0(qa>nVJb}7AM9zs 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�q8`X{Tk9s(~oWPV(;!pX4#zED> zp{kEbrDUtKIxO&NjN%a^3WwKvG64pb%UEbUr#0N0DBY#T_y{Wbe!cy@!8p!8Op3+> z^`Eq|Lwa70kONaPHEaoOxOo`s*babp*x)y(YKEhMAsPwyEVb@HLcBI1 zOVQaL!;ePGgeM#(r3MQ`K&vN*^@^o_w8?dYmeyZ06%;$fEem>!G=2 z2S*fVfmoaud+1UQ3o_|>>k@>JRe4m|n60V3DceEVSfj+4x!sUTmB|rn;mT#_5hZEF zyj5p^L*pdg0B5~c7leHx4Ec0YCBYwMBo2a0of>vQ#de%V%v0U3zn0z7|FVKsF-LMb z=EzDGc37G-tWi`wELEFQK@3NG+jtW8$yt8TMe2RZD!%#ZVYW0uJJhWfz|cc8L(#b! zLClPNvXM~p!ZPLv8 z7cfFZ&rspa&MkK_8*3|AZkN>>Y8k||kve5;;Ki_tNh*g$ojwaAUo~jiHjnl@r+K}X z`GYgK_SI@+DkHtbYknh63HhrI8*Rl;as)@CQCH+vvK%ck9=ICFB^m4@u2JGc@NU>n zb=B6l3gTO6w$IDzBJFR3RY^ei|E#UypPrcfhY4m~s=caG!C7p_&$!ep7d7!#KiqzJy=cYkL;FlW+BejQ zKC+kiA?CevkKm)b)rWS8ZG4o^?z@6x+P`?N*SA_*kF9?AQa_9%?CqEC)n+>dj;QG= z`;=`7{2HUXSblZl&*aWuPm#kp3*-gW9pJ#+E z?&!+}p0(6=`uUWHuaC=jg|0{qHTYUE`LxE>(2$p@pAS9Kez?53WpUdyxvf!pvzG@I zPG|kd|1kbAfA=oiVf`iK69Wvf?5 zE}OgRRXyK6=^y3?t=g6^KW=qrY2U)ihij#Mb^;d$Pw{Tqx^t3;SV^Q4r-;GVQ(ATl z8-HEDzHe#EuWzeg&ktMtb+uL9QQ%66>fDTfFM*3u4}Z6l + + + 1.0 + +

### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc; *.md + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rtthread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\keil\List\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 8 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + .\flexspi_nor.ini + BIN\CMSIS_AGDI.dll + + + + 0 + CMSIS_AGDI + -X"Any" -UAny -O206 -S8 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(0BD11477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC8000 -FN1 -FF0MIMXRT105x_QuadSPI_4KB_SEC.FLM -FS060000000 -FL0800000 -FP0($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_QuadSPI_4KB_SEC.FLM) + + + 0 + JL2CM3 + -U30000299 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(0BD11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC8000 -FN1 -FF0MIMXRT105x_QuadSPI_4KB_SEC -FS060000000 -FL0800000 -FP0($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_QuadSPI_4KB_SEC.FLM) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 ) -FN2 -FC8000 -FD20000000 -FF0MIMXRT105x_HYPER_256KB_SEC -FF1MIMXRT105x_QuadSPI_4KB_SEC -FL04000000 -FL1800000 -FS060000000 -FS160000000 -FP0($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_HYPER_256KB_SEC.FLM) -FP1($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_QuadSPI_4KB_SEC.FLM) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + 1 + 1 + 0 + 2 + 10000000 + + + + + diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/project.uvprojx b/bsp/imxrt/imxrt1052-seeed-ArchMix/project.uvprojx new file mode 100644 index 0000000000..96e2bbb2c2 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/project.uvprojx @@ -0,0 +1,755 @@ + + + 2.1 +
### uVision Project, (C) Keil Software
+ + + rtthread + 0x4 + ARM-ADS + 5060528::V5.06 update 5 (build 528)::ARMCC + 0 + + + MIMXRT1052CVL5B + NXP + NXP.MIMXRT1052_DFP.13.0.0 + https://mcuxpresso.nxp.com/cmsis_pack/repo/ + IRAM(0x20000000,0x020000) IRAM2(0x00000000,0x020000) XRAM(0x20200000,0x040000) CPUTYPE("Cortex-M7") FPU3(DFPU) CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC8000 -FN2 -FF0MIMXRT105x_HYPER_256KB_SEC -FS060000000 -FL04000000 -FF1MIMXRT105x_QuadSPI_4KB_SEC -FS160000000 -FL1800000 -FP0($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_HYPER_256KB_SEC.FLM) -FP1($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_QuadSPI_4KB_SEC.FLM)) + 0 + $$Device:MIMXRT1052CVL5B$fsl_device_registers.h + + + + + + + + + + $$Device:MIMXRT1052CVL5B$MIMXRT1052.xml + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\keil\Obj\ + rtthread + 1 + 0 + 0 + 1 + 1 + .\build\keil\List\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM7 + SARMCM3.DLL + + TCM.DLL + -pCM7 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M7" + + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 3 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x0 + 0x8000 + + + 1 + 0x20200000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 0 + 0x20200000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 0 + 0x0 + 0x20000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + --library_interface=armcc --library_type=standardlib --diag_suppress=66,1296,186 + SKIP_SYSCLK_INIT, CPU_MIMXRT1052CVL5B, __CLK_TCK=RT_TICK_PER_SECOND, __RTTHREAD__, FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1, XIP_EXTERNAL_FLASH=1, EVK_MCIMXRM + + applications;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m7;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\MCUX_Config;board\ports;..\libraries\drivers;..\libraries\drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\libraries\MIMXRT1050\CMSIS\Include;..\libraries\MIMXRT1050\MIMXRT1052;..\libraries\MIMXRT1050\MIMXRT1052\drivers + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x00000000 + 0x10000000 + + .\board\linker_scripts\link.sct + + + + + 6314 + + + + + + Applications + + + mnt.c + 1 + applications\mnt.c + + + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m7\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m7\context_rvds.S + + + + + cpu_cache.c + 1 + ..\..\..\libcpu\arm\cortex-m7\cpu_cache.c + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + Drivers + + + pin_mux.c + 1 + board\MCUX_Config\pin_mux.c + + + + + board.c + 1 + board\board.c + + + + + clock_config.c + 1 + board\MCUX_Config\clock_config.c + + + + + drv_gpio.c + 1 + ..\libraries\drivers\drv_gpio.c + + + + + drv_uart.c + 1 + ..\libraries\drivers\drv_uart.c + + + + + finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + Kernel + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + memheap.c + 1 + ..\..\..\src\memheap.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + system_MIMXRT1052.c + 1 + ..\libraries\MIMXRT1050\MIMXRT1052\system_MIMXRT1052.c + + + + + fsl_gpio.c + 1 + ..\libraries\MIMXRT1050\MIMXRT1052\drivers\fsl_gpio.c + + + + + fsl_lpuart.c + 1 + ..\libraries\MIMXRT1050\MIMXRT1052\drivers\fsl_lpuart.c + + + + + fsl_edma.c + 1 + ..\libraries\MIMXRT1050\MIMXRT1052\drivers\fsl_edma.c + + + + + fsl_lpuart_edma.c + 1 + ..\libraries\MIMXRT1050\MIMXRT1052\drivers\fsl_lpuart_edma.c + + + + + fsl_clock.c + 1 + ..\libraries\MIMXRT1050\MIMXRT1052\drivers\fsl_clock.c + + + + + fsl_dmamux.c + 1 + ..\libraries\MIMXRT1050\MIMXRT1052\drivers\fsl_dmamux.c + + + + + fsl_cache.c + 1 + ..\libraries\MIMXRT1050\MIMXRT1052\drivers\fsl_cache.c + + + + + fsl_common.c + 1 + ..\libraries\MIMXRT1050\MIMXRT1052\drivers\fsl_common.c + + + + + startup_MIMXRT1052.s + 2 + ..\libraries\MIMXRT1050\MIMXRT1052\arm\startup_MIMXRT1052.s + + + + + + + + + + + +
diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/rtconfig.h b/bsp/imxrt/imxrt1052-seeed-ArchMix/rtconfig.h new file mode 100644 index 0000000000..e40ae0ab78 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/rtconfig.h @@ -0,0 +1,177 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 1000 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_MEMHEAP +#define RT_USING_MEMHEAP_AS_HEAP +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40003 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_CMD_SIZE 80 +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +#define FINSH_USING_MSH_ONLY +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SERIAL +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_FIXED_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + + +/* tools packages */ + + +/* system packages */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_IMXRT1052CVL5B + +/* Onboard Peripheral Drivers */ + + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_DMA +#define BSP_USING_GPIO +#define BSP_USING_LPUART +#define BSP_USING_LPUART1 + +#endif diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/rtconfig.py b/bsp/imxrt/imxrt1052-seeed-ArchMix/rtconfig.py new file mode 100644 index 0000000000..cf79de685a --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/rtconfig.py @@ -0,0 +1,162 @@ +import os +import sys + +# toolchains options +ARCH='arm' +CPU='cortex-m7' +CROSS_TOOL='gcc' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' +#BUILD = 'release' + +if PLATFORM == 'gcc': + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + CXX = PREFIX + 'g++' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + STRIP = PREFIX + 'strip' + + DEVICE = ' -mcpu=' + CPU + ' -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Wall -D__FPU_PRESENT -eentry' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb -D__START=entry' + LFLAGS = DEVICE + ' -lm -lgcc -lc' + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.lds' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -gdwarf-2' + AFLAGS += ' -gdwarf-2' + CFLAGS += ' -O0' + else: + CFLAGS += ' -O2 -Os' + + POST_ACTION = OBJCPY + ' -O binary --remove-section=.boot_data --remove-section=.image_vertor_table --remove-section=.ncache $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + + # module setting + CXXFLAGS = ' -Woverloaded-virtual -fno-exceptions -fno-rtti ' + M_CFLAGS = CFLAGS + ' -mlong-calls -fPIC ' + M_CXXFLAGS = CXXFLAGS + ' -mlong-calls -fPIC' + M_LFLAGS = DEVICE + CXXFLAGS + ' -Wl,--gc-sections,-z,max-page-size=0x4' +\ + ' -shared -fPIC -nostartfiles -static-libgcc' + M_POST_ACTION = STRIP + ' -R .hash $TARGET\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu ' + CPU + '.fp.sp' + CFLAGS = DEVICE + ' --apcs=interwork' + AFLAGS = DEVICE + LFLAGS = DEVICE + ' --libpath "' + EXEC_PATH + '\ARM\ARMCC\lib" --info sizes --info totals --info unused --info veneers --list rtthread.map --scatter "board\linker_scripts\link.sct"' + + CFLAGS += ' --diag_suppress=66,1296,186,6134' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/RV31/INC' + LFLAGS += ' --libpath ' + EXEC_PATH + '/ARM/RV31/LIB' + + EXEC_PATH += '/arm/bin40/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' --c99' + + POST_ACTION = 'fromelf -z $TARGET' + # POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = ' -D__FPU_PRESENT' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --debug' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=' + CPU + CFLAGS += ' -e' + CFLAGS += ' --fpu=None' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' -Ol' + CFLAGS += ' --use_c++_inline' + + AFLAGS = '' + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu ' + CPU + AFLAGS += ' --fpu None' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --redirect _Printf=_PrintfTiny' + LFLAGS += ' --redirect _Scanf=_ScanfSmall' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) + \ No newline at end of file diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/template.uvoptx b/bsp/imxrt/imxrt1052-seeed-ArchMix/template.uvoptx new file mode 100644 index 0000000000..283fcc0e30 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/template.uvoptx @@ -0,0 +1,189 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc; *.md + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rtthread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\keil\List\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 8 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + .\flexspi_nor.ini + BIN\CMSIS_AGDI.dll + + + + 0 + CMSIS_AGDI + -X"Any" -UAny -O206 -S8 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(0BD11477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC8000 -FN1 -FF0MIMXRT105x_QuadSPI_4KB_SEC.FLM -FS060000000 -FL0800000 -FP0($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_QuadSPI_4KB_SEC.FLM) + + + 0 + JL2CM3 + -U30000299 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(0BD11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC8000 -FN1 -FF0MIMXRT105x_QuadSPI_4KB_SEC -FS060000000 -FL0800000 -FP0($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_QuadSPI_4KB_SEC.FLM) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 ) -FN2 -FC8000 -FD20000000 -FF0MIMXRT105x_HYPER_256KB_SEC -FF1MIMXRT105x_QuadSPI_4KB_SEC -FL04000000 -FL1800000 -FS060000000 -FS160000000 -FP0($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_HYPER_256KB_SEC.FLM) -FP1($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_QuadSPI_4KB_SEC.FLM) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + 1 + 1 + 0 + 2 + 10000000 + + + + +
diff --git a/bsp/imxrt/imxrt1052-seeed-ArchMix/template.uvprojx b/bsp/imxrt/imxrt1052-seeed-ArchMix/template.uvprojx new file mode 100644 index 0000000000..794ecf4f95 --- /dev/null +++ b/bsp/imxrt/imxrt1052-seeed-ArchMix/template.uvprojx @@ -0,0 +1,391 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rtthread + 0x4 + ARM-ADS + 5060528::V5.06 update 5 (build 528)::ARMCC + 0 + + + MIMXRT1052CVL5B + NXP + NXP.MIMXRT1052_DFP.13.0.0 + https://mcuxpresso.nxp.com/cmsis_pack/repo/ + IRAM(0x20000000,0x020000) IRAM2(0x00000000,0x020000) XRAM(0x20200000,0x040000) CPUTYPE("Cortex-M7") FPU3(DFPU) CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC8000 -FN2 -FF0MIMXRT105x_HYPER_256KB_SEC -FS060000000 -FL04000000 -FF1MIMXRT105x_QuadSPI_4KB_SEC -FS160000000 -FL1800000 -FP0($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_HYPER_256KB_SEC.FLM) -FP1($$Device:MIMXRT1052CVL5B$arm\MIMXRT105x_QuadSPI_4KB_SEC.FLM)) + 0 + $$Device:MIMXRT1052CVL5B$fsl_device_registers.h + + + + + + + + + + $$Device:MIMXRT1052CVL5B$MIMXRT1052.xml + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\keil\Obj\ + rtthread + 1 + 0 + 0 + 1 + 1 + .\build\keil\List\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM7 + SARMCM3.DLL + + TCM.DLL + -pCM7 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M7" + + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 3 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x0 + 0x8000 + + + 1 + 0x20200000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 0 + 0x20200000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 0 + 0x0 + 0x20000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + --library_interface=armcc --library_type=standardlib --diag_suppress=66,1296,186 + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x00000000 + 0x10000000 + + .\board\linker_scripts\link.sct + + + + + 6314 + + + + + + + + + + + + +
diff --git a/bsp/imxrt/libraries/MIMXRT1050/SConscript b/bsp/imxrt/libraries/MIMXRT1050/SConscript index 7f8f971b82..75fde95bc1 100644 --- a/bsp/imxrt/libraries/MIMXRT1050/SConscript +++ b/bsp/imxrt/libraries/MIMXRT1050/SConscript @@ -73,8 +73,8 @@ if GetDepend(['BSP_USING_DMA']): src += ['MIMXRT1052/drivers/fsl_dmamux.c'] src += ['MIMXRT1052/drivers/fsl_edma.c'] src += ['MIMXRT1052/drivers/fsl_lpuart_edma.c'] - src += ['MIMXRT1052/drivers/fsl_lpspi_edma.c'] - + if GetDepend(['BSP_USING_SPI']): + src += ['MIMXRT1052/drivers/fsl_lpspi_edma.c'] if rtconfig.CROSS_TOOL == 'gcc': group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, ASFLAGS = '$ASFLAGS -D __STARTUP_CLEAR_BSS') From 9de977a0461f9fad5d9c606dbccc93bece1133f5 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 8 May 2021 23:51:47 +0800 Subject: [PATCH 028/255] remove list_date --- components/drivers/rtc/SConscript | 12 +++--------- components/drivers/rtc/rtc.c | 15 +++------------ 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/components/drivers/rtc/SConscript b/components/drivers/rtc/SConscript index e1f8f433c1..6ec8bcb3c5 100644 --- a/components/drivers/rtc/SConscript +++ b/components/drivers/rtc/SConscript @@ -3,21 +3,15 @@ from building import * cwd = GetCurrentDir() src = [] -rtc = ['rtc.c'] - -rtc_alarm = ['alarm.c'] - -soft_rtc = ['soft_rtc.c'] - CPPPATH = [cwd + '/../include'] group = [] if GetDepend(['RT_USING_RTC']): - src = src + rtc + src = src + ['rtc.c'] if GetDepend(['RT_USING_ALARM']): - src = src + rtc_alarm + src = src + ['alarm.c'] if GetDepend(['RT_USING_SOFT_RTC']): - src = src + soft_rtc + src = src + ['soft_rtc.c'] group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_RTC'], CPPPATH = CPPPATH) diff --git a/components/drivers/rtc/rtc.c b/components/drivers/rtc/rtc.c index f15b8a7754..8278c12da2 100644 --- a/components/drivers/rtc/rtc.c +++ b/components/drivers/rtc/rtc.c @@ -15,8 +15,11 @@ #include #include #include + #ifdef RT_USING_RTC + + /** * Set system date(time not modify, local timezone). * @@ -119,17 +122,6 @@ rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) #ifdef FINSH_USING_MSH #include -/** - * show date and time (local timezone) - */ -void list_date(void) -{ - time_t now; - - now = time(RT_NULL); - rt_kprintf("%.*s\n", 25, ctime(&now)); -} - /** * get date and time or set (local timezone) [year month day hour min sec] */ @@ -192,7 +184,6 @@ static void date(uint8_t argc, char **argv) rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n"); } } -MSH_CMD_EXPORT(list_date, show date and time (local timezone)) MSH_CMD_EXPORT(date, get date and time or set (local timezone) [year month day hour min sec]) #endif /* FINSH_USING_MSH */ From 14d64a1dffa40fc09aa2afb11ca04bf3ac2ea9b5 Mon Sep 17 00:00:00 2001 From: Tao_eternal Date: Sun, 9 May 2021 15:30:36 +0800 Subject: [PATCH 029/255] Update drv_gpio.c one more bug fixed --- bsp/gd32vf103v-eval/drivers/drv_gpio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bsp/gd32vf103v-eval/drivers/drv_gpio.c b/bsp/gd32vf103v-eval/drivers/drv_gpio.c index 47f9b52009..77d6472718 100644 --- a/bsp/gd32vf103v-eval/drivers/drv_gpio.c +++ b/bsp/gd32vf103v-eval/drivers/drv_gpio.c @@ -349,15 +349,15 @@ static rt_err_t gd32vf_pin_irq_enable(struct rt_device *device, rt_base_t pin, { return RT_ENOSYS; } - + + irqindex = bit2bitno(index->pin); + if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) + { + return RT_ENOSYS; + } + if (enabled == PIN_IRQ_ENABLE) { - irqindex = bit2bitno(index->pin); - if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) - { - return RT_ENOSYS; - } - level = rt_hw_interrupt_disable(); if (pin_irq_hdr_tab[irqindex].pin == -1) From 3fd276bb44904876d4a487d903d8a806db0d83fd Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 9 May 2021 15:59:27 +0800 Subject: [PATCH 030/255] add comment --- components/drivers/rtc/rtc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/drivers/rtc/rtc.c b/components/drivers/rtc/rtc.c index 8278c12da2..b5005429a0 100644 --- a/components/drivers/rtc/rtc.c +++ b/components/drivers/rtc/rtc.c @@ -9,6 +9,7 @@ * 2012-04-12 aozima optimization: find rtc device only first. * 2012-04-16 aozima add scheduler lock for set_date and set_time. * 2018-02-16 armink add auto sync time by NTP + * 2021-05-09 Meco Man remove NTP */ #include From e71e693fd1a6536294958b45f133713f029bfda9 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 9 May 2021 16:10:58 +0800 Subject: [PATCH 031/255] =?UTF-8?q?=E7=A7=BB=E9=99=A4readme=E5=85=B3?= =?UTF-8?q?=E4=BA=8ENTP=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/drivers/rtc/README.md | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/components/drivers/rtc/README.md b/components/drivers/rtc/README.md index f2a40f5056..dff71f9d67 100644 --- a/components/drivers/rtc/README.md +++ b/components/drivers/rtc/README.md @@ -55,24 +55,11 @@ msh />date 2018 02 16 01 15 30 # 设置当前时间为 2018-02-16 01:15:30 msh /> ``` -### 2.4 启用 NTP 时间自动同步 - -如果 RT-Thread 已接入互联网,可启用 NTP 时间自动同步功能,定期同步本地时间。 - -在 menuconfig 中启用 `RTC_SYNC_USING_NTP` 配置。启用该功能后,会自动开启 [netutils package](https://github.com/RT-Thread-packages/netutils) 的 NTP 功能。同时务必确保 RT-Thread 网络访问正常。 - -启用该配置后,还有两个配置是用户可选配置: - -- `RTC_NTP_FIRST_SYNC_DELAY`: 首次执行 NTP 时间同步的延时。延时的目的在于,给网络连接预留一定的时间,尽量提高第一次执行 NTP 时间同步时的成功率。默认时间为 30S; -- `RTC_NTP_SYNC_PERIOD`: NTP 自动同步周期,单位为秒,默认一小时(即 3600S)同步一次。 - -> 注意:如果没有使用组件自动初始化功能,则需手动调用 `int rt_rtc_ntp_sync_init(void)` ,完成该功能初始化。 - -### 2.5 启用 Soft RTC (软件模拟 RTC) +### 2.4 启用 Soft RTC (软件模拟 RTC) 这个模式非常适用于对时间精度要求不高,没有硬件 RTC 的产品。 -#### 2.5.1 使用方法 +#### 2.4.1 使用方法 在 menuconfig 中启用 `RT_USING_SOFT_RTC` 配置。 From 7e7066f74183a43e738a19aa2c567f6fa5f4b628 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 9 May 2021 19:43:50 +0800 Subject: [PATCH 032/255] =?UTF-8?q?[Kconfig][driver]=E5=88=A0=E9=99=A4NTP?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/drivers/Kconfig | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index b0caabc73c..c7fec6cba9 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -153,20 +153,6 @@ config RT_USING_RTC config RT_USING_SOFT_RTC bool "Using software simulation RTC device" default n - - config RTC_SYNC_USING_NTP - bool "Using NTP auto sync RTC time" - depends on PKG_NETUTILS_NTP - default y - - if RTC_SYNC_USING_NTP - config RTC_NTP_FIRST_SYNC_DELAY - int "NTP first sync delay time(second) for network connect" - default 30 - config RTC_NTP_SYNC_PERIOD - int "NTP auto sync period(second)" - default 3600 - endif endif config RT_USING_SDIO From fdd2859cb581759d2448272225a5bc466d9d2530 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 9 May 2021 20:37:12 +0800 Subject: [PATCH 033/255] =?UTF-8?q?[network][lwip][kconfig]=20=E9=BB=98?= =?UTF-8?q?=E8=AE=A4LWIP=E5=8D=8F=E8=AE=AE=E6=A0=88=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E7=94=B12.0.2=E8=BD=AC=E4=B8=BA2.1.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/net/Kconfig b/components/net/Kconfig index e1c34f754e..ad1db0c0fc 100644 --- a/components/net/Kconfig +++ b/components/net/Kconfig @@ -114,7 +114,7 @@ config RT_USING_LWIP if RT_USING_LWIP choice prompt "lwIP version" - default RT_USING_LWIP202 + default RT_USING_LWIP212 help Select the lwIP version From efa64e0da4b6b5ad7d5260f71fe29aff3130bb54 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 9 May 2021 21:30:14 +0800 Subject: [PATCH 034/255] =?UTF-8?q?[bsp-stm32f407-explorer]=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84F407=E6=8E=A2=E8=B7=AF=E8=80=85=E7=BD=91=E7=BB=9Cboard?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/stm32f407-atk-explorer/board/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig index 84aa84e42c..5959d41437 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig +++ b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig @@ -54,6 +54,9 @@ menu "Onboard Peripheral Drivers" default n select RT_USING_LWIP select PHY_USING_LAN8720A + select RT_LWIP_USING_HW_CHECKSUM + select RT_USING_SAL + select SAL_USING_POSIX config BSP_USING_MPU6050 bool "Enable MPU6050 (i2c1)" From c61419b69bd3895aac2da8a36d9db0b2ff682f26 Mon Sep 17 00:00:00 2001 From: armink Date: Mon, 10 May 2021 09:10:54 +0800 Subject: [PATCH 035/255] Update the version number to 4.0.4 --- include/rtdef.h | 3 ++- src/Kconfig | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/rtdef.h b/include/rtdef.h index 111ac4a12c..d125c970c9 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -34,6 +34,7 @@ * 2019-12-20 Bernard change version number to v4.0.3 * 2020-08-10 Meco Man add macro for struct rt_device_ops * 2020-10-23 Meco Man define maximum value of ipc type + * 2021-05-10 armink change version number to v4.0.4 */ #ifndef __RT_DEF_H__ @@ -55,7 +56,7 @@ extern "C" { /* RT-Thread version information */ #define RT_VERSION 4L /**< major version number */ #define RT_SUBVERSION 0L /**< minor version number */ -#define RT_REVISION 3L /**< revise version number */ +#define RT_REVISION 4L /**< revise version number */ /* RT-Thread version */ #define RTTHREAD_VERSION ((RT_VERSION * 10000) + \ diff --git a/src/Kconfig b/src/Kconfig index 6afb719395..9a49146dff 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -353,7 +353,7 @@ endmenu config RT_VER_NUM hex - default 0x40003 + default 0x40004 help RT-Thread version number From 61ec310591d3d75b4702fdad4b46829b68b83b13 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 10 May 2021 14:22:06 +0800 Subject: [PATCH 036/255] implement BSP_USING_ETH_SAL --- bsp/stm32/stm32f407-atk-explorer/board/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig index 5959d41437..8aa3a6f9fa 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig +++ b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig @@ -55,6 +55,11 @@ menu "Onboard Peripheral Drivers" select RT_USING_LWIP select PHY_USING_LAN8720A select RT_LWIP_USING_HW_CHECKSUM + + config BSP_USING_ETH_SAL + bool "Enable Ethernet with SAL" + depends on BSP_USING_ETH + default y select RT_USING_SAL select SAL_USING_POSIX From d81be2e8fdff9a018fedc201d189b8798b62fcfe Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 10 May 2021 15:14:50 +0800 Subject: [PATCH 037/255] [bsp][stm32f407-explorer] fix a bug that cannot use fatfs in the main thread at starting up --- .../ports/{sdcard_port.c => drv_sdcard.c} | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) rename bsp/stm32/stm32f407-atk-explorer/board/ports/{sdcard_port.c => drv_sdcard.c} (59%) diff --git a/bsp/stm32/stm32f407-atk-explorer/board/ports/sdcard_port.c b/bsp/stm32/stm32f407-atk-explorer/board/ports/drv_sdcard.c similarity index 59% rename from bsp/stm32/stm32f407-atk-explorer/board/ports/sdcard_port.c rename to bsp/stm32/stm32f407-atk-explorer/board/ports/drv_sdcard.c index bc7e8b676e..4ad71158f4 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32f407-atk-explorer/board/ports/drv_sdcard.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2018-12-13 balanceTWK add sdcard port file + * 2021-05-10 Meco Man fix a bug that cannot use fatfs in the main thread at starting up */ #include @@ -20,7 +21,7 @@ #define DBG_LVL DBG_INFO #include -void sd_mount(void *parameter) +static void sd_mount(void *parameter) { while (1) { @@ -40,23 +41,30 @@ void sd_mount(void *parameter) } } -int stm32_sdcard_mount(void) +static int onboard_sdcard_mount(void) { rt_thread_t tid; - tid = rt_thread_create("sd_mount", sd_mount, RT_NULL, - 1024, RT_THREAD_PRIORITY_MAX - 2, 20); - if (tid != RT_NULL) + if (dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK) { - rt_thread_startup(tid); + LOG_I("sd card mount to '/'"); } else { - LOG_E("create sd_mount thread err!"); + tid = rt_thread_create("sd_mount", sd_mount, RT_NULL, + 1024, RT_THREAD_PRIORITY_MAX - 2, 20); + if (tid != RT_NULL) + { + rt_thread_startup(tid); + } + else + { + LOG_E("create sd_mount thread err!"); + } } + return RT_EOK; } -INIT_APP_EXPORT(stm32_sdcard_mount); +INIT_APP_EXPORT(onboard_sdcard_mount); #endif /* BSP_USING_SDCARD */ - From 0da2fb5f9b8ceaec84e51f31b23aeee2107f42b5 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Mon, 10 May 2021 16:17:11 +0800 Subject: [PATCH 038/255] Correct rvds.S including for armclang platform. --- bsp/nuvoton/numaker-m2354/README.md | 1 - bsp/nuvoton/numaker-m2354/rtconfig.py | 6 +++--- libcpu/arm/cortex-m23/SConscript | 2 ++ 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bsp/nuvoton/numaker-m2354/README.md b/bsp/nuvoton/numaker-m2354/README.md index 5cc0d34fb8..de4e03ad01 100644 --- a/bsp/nuvoton/numaker-m2354/README.md +++ b/bsp/nuvoton/numaker-m2354/README.md @@ -41,7 +41,6 @@ Support GCC, MDK5, IAR IDE/compilers. More information of these compiler version Notice: (1) Please install Nu-Link_Keil_Driver or Nu-Link_IAR_Driver for development. -(2) You must remove '--c99' flag in /components/drivers/spi/SConscript before generating MDK5 project file. ## 3. Program firmware ### Step 1: diff --git a/bsp/nuvoton/numaker-m2354/rtconfig.py b/bsp/nuvoton/numaker-m2354/rtconfig.py index aba7250bc3..2a59f1a4f0 100644 --- a/bsp/nuvoton/numaker-m2354/rtconfig.py +++ b/bsp/nuvoton/numaker-m2354/rtconfig.py @@ -15,7 +15,7 @@ if CROSS_TOOL == 'gcc': PLATFORM = 'gcc' EXEC_PATH = r'C:\Program Files (x86)\GNU Tools ARM Embedded\6 2017-q1-update\bin' elif CROSS_TOOL == 'keil': - PLATFORM = 'armcc' + PLATFORM = 'armclang' EXEC_PATH = r'C:\Keil_v5' elif CROSS_TOOL == 'iar': PLATFORM = 'iar' @@ -56,9 +56,9 @@ if PLATFORM == 'gcc': POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' -elif PLATFORM == 'armcc': +elif PLATFORM == 'armclang': # toolchains - CC = 'armcc' + CC = 'armclang' AS = 'armasm' AR = 'armar' LINK = 'armlink' diff --git a/libcpu/arm/cortex-m23/SConscript b/libcpu/arm/cortex-m23/SConscript index 28af7ba651..a4535c03ea 100644 --- a/libcpu/arm/cortex-m23/SConscript +++ b/libcpu/arm/cortex-m23/SConscript @@ -10,6 +10,8 @@ CPPPATH = [cwd] if rtconfig.PLATFORM == 'armcc': src += Glob('*_rvds.S') +elif rtconfig.PLATFORM == 'armclang': + src += Glob('*_rvds.S') if rtconfig.PLATFORM == 'gcc': src += Glob('*_init.S') From ab6c69fe9e1efc8f4c5c24d4d5898297809a0ed5 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 10 May 2021 16:45:00 +0800 Subject: [PATCH 039/255] =?UTF-8?q?=E4=BC=98=E5=8C=96SDIO=5FMAX=5FFREQ?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=20=E5=88=A0=E9=99=A4PHY=5FUSING=5FLAN8720A?= =?UTF-8?q?=E6=97=A0=E7=94=A8=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/stm32f407-atk-explorer/board/Kconfig | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig index 8aa3a6f9fa..8f198ecd2f 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig +++ b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig @@ -45,9 +45,6 @@ menu "Onboard Peripheral Drivers" bool "Enable I2C EEPROM (i2c1)" select BSP_USING_I2C1 default n - - config PHY_USING_LAN8720A - bool config BSP_USING_ETH bool "Enable Ethernet" @@ -75,12 +72,12 @@ menu "Onboard Peripheral Drivers" select RT_USING_DFS select RT_USING_DFS_ELMFAT default n - if BSP_USING_SDCARD + config SDIO_MAX_FREQ int "sdio max freq" range 0 24000000 + depends on BSP_USING_SDCARD default 1000000 - endif endmenu From dc55b1e19c8b505192dd3e74ed39b9fdf9f63fd3 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 10 May 2021 16:49:02 +0800 Subject: [PATCH 040/255] =?UTF-8?q?[bsp][stm32f407-explorer]=20=E9=87=8D?= =?UTF-8?q?=E5=91=BD=E5=90=8Dsram=5Fport.h=E4=B8=BAdrv=5Fsram.h?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/stm32f407-atk-explorer/board/ports/drv_sram.c | 2 +- .../board/ports/{sram_port.h => drv_sram.h} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename bsp/stm32/stm32f407-atk-explorer/board/ports/{sram_port.h => drv_sram.h} (100%) diff --git a/bsp/stm32/stm32f407-atk-explorer/board/ports/drv_sram.c b/bsp/stm32/stm32f407-atk-explorer/board/ports/drv_sram.c index dba9ec5e29..c947c759f2 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/ports/drv_sram.c +++ b/bsp/stm32/stm32f407-atk-explorer/board/ports/drv_sram.c @@ -13,7 +13,7 @@ #include #ifdef BSP_USING_SRAM -#include +#include "drv_sram.h" #define DRV_DEBUG #define LOG_TAG "drv.sram" diff --git a/bsp/stm32/stm32f407-atk-explorer/board/ports/sram_port.h b/bsp/stm32/stm32f407-atk-explorer/board/ports/drv_sram.h similarity index 100% rename from bsp/stm32/stm32f407-atk-explorer/board/ports/sram_port.h rename to bsp/stm32/stm32f407-atk-explorer/board/ports/drv_sram.h From 39417ac51a4bd213973e5a19253b1246a0e60553 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 10 May 2021 17:15:46 +0800 Subject: [PATCH 041/255] =?UTF-8?q?[kconfig]=E4=BC=98=E5=8C=96=20PHY=5FUSI?= =?UTF-8?q?NG=5FLAN8720A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/stm32f407-atk-explorer/board/Kconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig index 8f198ecd2f..7e36d691f8 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig +++ b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig @@ -50,7 +50,6 @@ menu "Onboard Peripheral Drivers" bool "Enable Ethernet" default n select RT_USING_LWIP - select PHY_USING_LAN8720A select RT_LWIP_USING_HW_CHECKSUM config BSP_USING_ETH_SAL @@ -60,6 +59,11 @@ menu "Onboard Peripheral Drivers" select RT_USING_SAL select SAL_USING_POSIX + config PHY_USING_LAN8720A + bool + depends on BSP_USING_ETH + default y + config BSP_USING_MPU6050 bool "Enable MPU6050 (i2c1)" default n From 119c04d0f25136a8f395082fc4e46c5c56b2fabe Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 10 May 2021 20:20:29 +0800 Subject: [PATCH 042/255] =?UTF-8?q?[Kconfig]=20=E9=81=BF=E5=85=8DCOM2?= =?UTF-8?q?=E4=B8=8E=E4=BB=A5=E5=A4=AA=E7=BD=91=E6=88=96PWM=E5=86=B2?= =?UTF-8?q?=E7=AA=81=20=E5=9B=A0=E6=AD=A4=E5=A2=9E=E5=8A=A0depends=20on?= =?UTF-8?q?=E6=8C=87=E4=BB=A4=EF=BC=8C=E5=9C=A8=E5=BC=80=E5=90=AF=E4=BB=A5?= =?UTF-8?q?=E5=A4=AA=E7=BD=91=E6=88=96=E8=80=85PWM=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E5=90=8E=EF=BC=8C=E4=B8=8D=E5=86=8D=E6=98=BE=E7=A4=BACOM2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/stm32f407-atk-explorer/board/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig index 84aa84e42c..f411904234 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig +++ b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig @@ -17,6 +17,7 @@ menu "Onboard Peripheral Drivers" config BSP_USING_COM2 bool "Enable COM2 (uart2 pin conflict with Ethernet and PWM)" + depends on (!BSP_USING_ETH && !BSP_USING_PWM) select BSP_USING_UART select BSP_USING_UART2 default n From 3906f3b948100bfafe03daecf9bc7b1d1ce9fb0b Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Mon, 10 May 2021 20:34:33 +0800 Subject: [PATCH 043/255] [add] auto test ci. --- .github/workflows/action_utest.yml | 40 +++ Kconfig | 1 + examples/utest/README.md | 79 ++++++ examples/utest/configs/utest_self/config.h | 297 +++++++++++++++++++++ examples/utest/testcases/Kconfig | 14 + examples/utest/testcases/SConscript | 15 ++ examples/utest/testcases/utest/Kconfig | 7 + examples/utest/testcases/utest/SConscript | 14 + examples/utest/testcases/utest/pass_tc.c | 46 ++++ tools/building.py | 4 + 10 files changed, 517 insertions(+) create mode 100644 .github/workflows/action_utest.yml create mode 100644 examples/utest/README.md create mode 100644 examples/utest/configs/utest_self/config.h create mode 100644 examples/utest/testcases/Kconfig create mode 100644 examples/utest/testcases/SConscript create mode 100644 examples/utest/testcases/utest/Kconfig create mode 100644 examples/utest/testcases/utest/SConscript create mode 100644 examples/utest/testcases/utest/pass_tc.c diff --git a/.github/workflows/action_utest.yml b/.github/workflows/action_utest.yml new file mode 100644 index 0000000000..43abe6539c --- /dev/null +++ b/.github/workflows/action_utest.yml @@ -0,0 +1,40 @@ +name: AutoTestCI +on: push +jobs: + test: + runs-on: ubuntu-latest + name: ${{ matrix.legs.UTEST }} + strategy: + fail-fast: false + matrix: + legs: + - {UTEST: "kernel/ipc", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"} + - {UTEST: "components/utest", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"} + + env: + TEST_BSP_ROOT: ${{ matrix.legs.RTT_BSP }} + TEST_CONFIG_FILE: ${{ matrix.legs.CONFIG_FILE }} + steps: + - uses: actions/checkout@v1 + - name: Prepare env + run: | + sudo apt-get update > /dev/null + sudo apt-get -yqq install scons qemu-system-arm git + wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/arm-2017q2-v6/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 + sudo tar xjf gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 -C /opt + - name: Build bsp + run: | + export RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-6-2017-q2-update/bin + /opt/gcc-arm-none-eabi-6-2017-q2-update/bin/arm-none-eabi-gcc --version + cp $TEST_CONFIG_FILE $TEST_BSP_ROOT/rtconfig.h + scons -j$(nproc) -C $TEST_BSP_ROOT + - name: Start test + run: | + git clone https://github.com/armink/UtestRunner.git + pushd $TEST_BSP_ROOT + dd if=/dev/zero of=sd.bin bs=1024 count=65536 + popd + pushd UtestRunner + python3 qemu_runner.py --elf ../$TEST_BSP_ROOT/rtthread.elf --sd ../$TEST_BSP_ROOT/sd.bin + cat rtt_console.log + popd diff --git a/Kconfig b/Kconfig index b32f7dafbe..1ebcbc9830 100644 --- a/Kconfig +++ b/Kconfig @@ -1,3 +1,4 @@ source "$RTT_DIR/src/Kconfig" source "$RTT_DIR/libcpu/Kconfig" source "$RTT_DIR/components/Kconfig" +source "$RTT_DIR/examples/utest/testcases/Kconfig" diff --git a/examples/utest/README.md b/examples/utest/README.md new file mode 100644 index 0000000000..eb54ff170e --- /dev/null +++ b/examples/utest/README.md @@ -0,0 +1,79 @@ +# RT-Thread 测试用例集合 + +## 简介 + +为了保证某一部分代码的质量,通常可以通过编写测试用例的方式,验证此代码的功能。为了保证 RT-Thread 的代码质量,我们搭建了一套简易的自动化测试环境。每当向 RT-Thread 提交代码时,都应该编写对应的测试用例,来保证提交的代码能够正常工作。 + +## 目录结构 + +| 目录 | 用途 | +| --------- | ------------------------------------------------------------ | +| configs | 配置文件集合(每一个目录代表一种功能集合,如:kernel,net等) | +| testcases | 测试用例源代码 | + +## 如何贡献 + +### 1. 编写测试用例 + +参考已有的测试用例在 examples\utest\testcases 目录下添加自己的测试用例。测试用例的编写方法参考文档中心《utest 测试框架》章节。 + +### 2. 本地测试 + +1. 在 bsp\qemu-vexpress-a9 目录下打开 menuconfig,使能对应的测试用例,如下: + +``` +RT-Thread Utestcases ---> + [*] RT-Thread Utestcases + Utest Self Testcase ---> + [*] Pass test +``` + +2. 保存并退出,输入 scons 编译当前 bsp。 + +3. 输入 .\qemu.bat 运行当前 bsp,在 msh 环境下执行 utest_run 命令,验证代码运行是否正常。 + +``` +msh />utest_run +[I/utest] [==========] [ utest ] loop 1/1 +[I/utest] [==========] [ utest ] started +[I/utest] [----------] [ testcase ] (testcases.utest.pass_tc) started +[D/utest] [ OK ] [ unit ] (test_assert_pass:16) is passed +[D/utest] [ OK ] [ unit ] (test_assert_pass:17) is passed +[D/utest] [ OK ] [ unit ] (test_assert_pass:19) is passed +[D/utest] [ OK ] [ unit ] (test_assert_pass:20) is passed +[D/utest] [ OK ] [ unit ] (test_assert_pass:22) is passed +[D/utest] [ OK ] [ unit ] (test_assert_pass:23) is passed +[D/utest] [ OK ] [ unit ] (test_assert_pass:25) is passed +[D/utest] [ OK ] [ unit ] (test_assert_pass:26) is passed +[D/utest] [ OK ] [ unit ] (test_assert_pass:28) is passed +[D/utest] [ OK ] [ unit ] (test_assert_pass:29) is passed +[I/utest] [ PASSED ] [ result ] testcase (testcases.utest.pass_tc) +[I/utest] [----------] [ testcase ] (testcases.utest.pass_tc) finished +[I/utest] [==========] [ utest ] finished +``` + +### 3. 提交 + +1. 如果是对已有测试集合的完善,需要把添加的测试用例的配置项添加到对应测试集合的配置文件里,如:`examples\utest\configs\utest_self\config.h`。 + +``` +/* RT-Thread Utestcases */ + +#define RT_USING_UTESTCASES + +/* Utest Self Testcase */ + +#define UTEST_SELF_PASS_TC + +/* xxx Testcase */ +#define UTEST_XXX_TC +``` + +2. 如果要添加新的测试集合,需要参考已有的测试集合,在 `examples\utest\configs` 目录下添加新的测试集合配置项。并更新 `.github\workflows\action_utest.yml` 内的测试集合。 + +``` +- {UTEST: "kernel/ipc", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"} +- {UTEST: "components/utest", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"} +``` + +3. 向 RT-Thread 主仓库提交合并请求。 \ No newline at end of file diff --git a/examples/utest/configs/utest_self/config.h b/examples/utest/configs/utest_self/config.h new file mode 100644 index 0000000000..287f0f539d --- /dev/null +++ b/examples/utest/configs/utest_self/config.h @@ -0,0 +1,297 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Project Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_USING_SMP +#define RT_CPUS_NR 2 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 1024 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 1024 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE +#define RT_USING_SIGNALS + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_MEMHEAP +#define RT_USING_SMALL_MEM +#define RT_USING_MEMTRACE +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_DEVICE_OPS +#define RT_USING_INTERRUPT_INFO +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 256 +#define RT_CONSOLE_DEVICE_NAME "uart0" +#define RT_VER_NUM 0x40004 +#define ARCH_ARM +#define ARCH_ARM_CORTEX_A +#define ARCH_ARM_CORTEX_A9 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + +#define RT_USING_CPLUSPLUS + +/* Command shell */ + +#define RT_USING_FINSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_CMD_SIZE 80 +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + +#define RT_USING_DFS +#define DFS_USING_WORKDIR +#define DFS_FILESYSTEMS_MAX 2 +#define DFS_FILESYSTEM_TYPES_MAX 8 +#define DFS_FD_MAX 16 +#define RT_USING_DFS_ELMFAT + +/* elm-chan's FatFs, Generic FAT Filesystem Module */ + +#define RT_DFS_ELM_CODE_PAGE 437 +#define RT_DFS_ELM_WORD_ACCESS +#define RT_DFS_ELM_USE_LFN_3 +#define RT_DFS_ELM_USE_LFN 3 +#define RT_DFS_ELM_LFN_UNICODE_0 +#define RT_DFS_ELM_LFN_UNICODE 0 +#define RT_DFS_ELM_MAX_LFN 255 +#define RT_DFS_ELM_DRIVES 2 +#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 +#define RT_DFS_ELM_REENTRANT +#define RT_USING_DFS_DEVFS +#define RT_USING_DFS_ROMFS +#define RT_USING_DFS_RAMFS + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_I2C +#define RT_USING_I2C_BITOPS +#define RT_USING_PIN +#define RT_USING_MTD_NOR +#define RT_USING_MTD_NAND +#define RT_MTD_NAND_DEBUG +#define RT_USING_RTC +#define RT_USING_SOFT_RTC +#define RT_USING_SDIO +#define RT_SDIO_STACK_SIZE 512 +#define RT_SDIO_THREAD_PRIORITY 15 +#define RT_MMCSD_STACK_SIZE 1024 +#define RT_MMCSD_THREAD_PREORITY 22 +#define RT_MMCSD_MAX_PARTITION 16 +#define RT_USING_SPI +#define RT_USING_SPI_MSD +#define RT_USING_SFUD +#define RT_SFUD_USING_SFDP +#define RT_SFUD_USING_FLASH_INFO_TABLE +#define RT_SFUD_SPI_MAX_HZ 50000000 +#define RT_USING_WDT + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_USING_LIBC +#define RT_USING_PTHREADS +#define PTHREAD_NUM_MAX 8 +#define RT_USING_POSIX +#define RT_USING_POSIX_MMAP +#define RT_USING_POSIX_TERMIOS +#define RT_USING_POSIX_AIO +#define RT_LIBC_FIXED_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + +#define RT_USING_SAL +#define SAL_INTERNET_CHECK + +/* protocol stack implement */ + +#define SAL_USING_LWIP +#define SAL_USING_POSIX + +/* Network interface device */ + +#define RT_USING_NETDEV +#define NETDEV_USING_IFCONFIG +#define NETDEV_USING_PING +#define NETDEV_USING_NETSTAT +#define NETDEV_USING_AUTO_DEFAULT +#define NETDEV_IPV4 1 +#define NETDEV_IPV6 0 + +/* light weight TCP/IP stack */ + +#define RT_USING_LWIP +#define RT_USING_LWIP202 +#define RT_LWIP_MEM_ALIGNMENT 4 +#define RT_LWIP_ICMP +#define RT_LWIP_DNS +#define RT_LWIP_DHCP +#define IP_SOF_BROADCAST 1 +#define IP_SOF_BROADCAST_RECV 1 + +/* Static IPv4 Address */ + +#define RT_LWIP_IPADDR "192.168.1.30" +#define RT_LWIP_GWADDR "192.168.1.1" +#define RT_LWIP_MSKADDR "255.255.255.0" +#define RT_LWIP_UDP +#define RT_LWIP_TCP +#define RT_LWIP_RAW +#define RT_MEMP_NUM_NETCONN 8 +#define RT_LWIP_PBUF_NUM 16 +#define RT_LWIP_RAW_PCB_NUM 4 +#define RT_LWIP_UDP_PCB_NUM 4 +#define RT_LWIP_TCP_PCB_NUM 4 +#define RT_LWIP_TCP_SEG_NUM 40 +#define RT_LWIP_TCP_SND_BUF 8196 +#define RT_LWIP_TCP_WND 8196 +#define RT_LWIP_TCPTHREAD_PRIORITY 10 +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 +#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_PRIORITY 12 +#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 +#define RT_LWIP_REASSEMBLY_FRAG +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define SO_REUSE 1 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_RCVBUF 1 +#define LWIP_SO_LINGER 0 +#define LWIP_NETIF_LOOPBACK 0 +#define RT_LWIP_USING_PING + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + +#define RT_USING_UTEST +#define UTEST_THR_STACK_SIZE 4096 +#define UTEST_THR_PRIORITY 20 +#define RT_USING_LWP + +/* RT-Thread Utestcases */ + +#define RT_USING_UTESTCASES + +/* Utest Self Testcase */ + +#define UTEST_SELF_PASS_TC + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + + +/* tools packages */ + + +/* system packages */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + +#define SOC_VEXPRESS_A9 +#define RT_USING_UART0 +#define RT_USING_UART1 +#define BSP_DRV_EMAC + +#endif diff --git a/examples/utest/testcases/Kconfig b/examples/utest/testcases/Kconfig new file mode 100644 index 0000000000..da80eb30ae --- /dev/null +++ b/examples/utest/testcases/Kconfig @@ -0,0 +1,14 @@ +menu "RT-Thread Utestcases" + +config RT_USING_UTESTCASES + bool "RT-Thread Utestcases" + default n + select RT_USING_UTEST + +if RT_USING_UTESTCASES + +source "$RTT_DIR/examples/utest/testcases/utest/Kconfig" + +endif + +endmenu diff --git a/examples/utest/testcases/SConscript b/examples/utest/testcases/SConscript new file mode 100644 index 0000000000..4c815c49b8 --- /dev/null +++ b/examples/utest/testcases/SConscript @@ -0,0 +1,15 @@ +# RT-Thread building script for bridge + +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/examples/utest/testcases/utest/Kconfig b/examples/utest/testcases/utest/Kconfig new file mode 100644 index 0000000000..85b4d796bd --- /dev/null +++ b/examples/utest/testcases/utest/Kconfig @@ -0,0 +1,7 @@ +menu "Utest Self Testcase" + +config UTEST_SELF_PASS_TC + bool "Pass test" + default y + +endmenu diff --git a/examples/utest/testcases/utest/SConscript b/examples/utest/testcases/utest/SConscript new file mode 100644 index 0000000000..362de4d949 --- /dev/null +++ b/examples/utest/testcases/utest/SConscript @@ -0,0 +1,14 @@ +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +src = [] + +if GetDepend('UTEST_SELF_PASS_TC'): + src += ['pass_tc.c'] + +CPPPATH = [cwd] + +group = DefineGroup('utestcases', src, depend = ['UTEST_SELF_PASS_TC'], CPPPATH = CPPPATH) + +Return('group') diff --git a/examples/utest/testcases/utest/pass_tc.c b/examples/utest/testcases/utest/pass_tc.c new file mode 100644 index 0000000000..8e93e35b9b --- /dev/null +++ b/examples/utest/testcases/utest/pass_tc.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-01-16 MurphyZhao the first version + */ + +#include +#include "utest.h" + +static void test_assert_pass(void) +{ + uassert_true(1); + uassert_false(0); + + uassert_null(RT_NULL); + uassert_not_null(!RT_NULL); + + uassert_int_equal(1, 1); + uassert_int_not_equal(1, 2); + + uassert_str_equal("Hello RT-Thread!", "Hello RT-Thread!"); + uassert_str_not_equal("Hello RT-Thread!", "Hello"); + + uassert_in_range(2048, 1024, 4096); + uassert_not_in_range(0, 1024, 4096); +} + +static rt_err_t utest_tc_init(void) +{ + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(test_assert_pass); +} +UTEST_TC_EXPORT(testcase, "testcases.utest.pass_tc", utest_tc_init, utest_tc_cleanup, 10); \ No newline at end of file diff --git a/tools/building.py b/tools/building.py index a768cd8519..90554a3082 100644 --- a/tools/building.py +++ b/tools/building.py @@ -447,6 +447,10 @@ def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = [ variant_dir=kernel_vdir + '/components', duplicate=0, exports='remove_components')) + # include testcases + objs.extend(SConscript(Rtt_Root + '/examples/utest/testcases/SConscript', + variant_dir=kernel_vdir + '/examples/utest/testcases', + duplicate=0)) return objs From 0e4228dbecf762c695af53841e13fda9c94ad855 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Mon, 10 May 2021 20:38:58 +0800 Subject: [PATCH 044/255] =?UTF-8?q?[=E6=B7=BB=E5=8A=A0]=20ci=20=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/action_utest.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/action_utest.yml b/.github/workflows/action_utest.yml index 43abe6539c..b8fea056e1 100644 --- a/.github/workflows/action_utest.yml +++ b/.github/workflows/action_utest.yml @@ -1,5 +1,8 @@ name: AutoTestCI -on: push + +# Controls when the action will run. Triggers the workflow on push or pull request +on: [push, pull_request] + jobs: test: runs-on: ubuntu-latest From 7aded3c65f5c7e753e9b3971c1f4de0859b6d827 Mon Sep 17 00:00:00 2001 From: Tao_eternal Date: Mon, 10 May 2021 21:57:51 +0800 Subject: [PATCH 045/255] Update drv_gpio.c From 2b5970e94a2fb07a1bd2de80104acb0a8261a551 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Tue, 11 May 2021 09:15:10 +0800 Subject: [PATCH 046/255] tab->spaces --- bsp/stm32/stm32f407-atk-explorer/board/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig index 7e36d691f8..8df593f4e1 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig +++ b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig @@ -59,10 +59,10 @@ menu "Onboard Peripheral Drivers" select RT_USING_SAL select SAL_USING_POSIX - config PHY_USING_LAN8720A - bool - depends on BSP_USING_ETH - default y + config PHY_USING_LAN8720A + bool + depends on BSP_USING_ETH + default y config BSP_USING_MPU6050 bool "Enable MPU6050 (i2c1)" From 7d57170a686fb16e3222f1fac750bc20f7d56963 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Tue, 11 May 2021 09:22:49 +0800 Subject: [PATCH 047/255] =?UTF-8?q?=E3=80=90=E6=9B=B4=E6=96=B0=E3=80=91REA?= =?UTF-8?q?DME.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/utest/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/utest/README.md b/examples/utest/README.md index eb54ff170e..f2fe327473 100644 --- a/examples/utest/README.md +++ b/examples/utest/README.md @@ -2,7 +2,7 @@ ## 简介 -为了保证某一部分代码的质量,通常可以通过编写测试用例的方式,验证此代码的功能。为了保证 RT-Thread 的代码质量,我们搭建了一套简易的自动化测试环境。每当向 RT-Thread 提交代码时,都应该编写对应的测试用例,来保证提交的代码能够正常工作。 +为了保证某一部分代码的质量,通常可以通过编写测试用例的方式,验证此代码的功能。为了保证 RT-Thread 相关仓库的代码质量,我们基于 utest 框架搭建了一套简易的自动化测试环境。有兴趣,有精力的小伙伴可以利用这套机制完善自己的代码检查。如果有意愿让社区上更多的小伙伴收益,也可以在提交代码的时候,把对应的测试用例也提交上来。 ## 目录结构 @@ -15,11 +15,11 @@ ### 1. 编写测试用例 -参考已有的测试用例在 examples\utest\testcases 目录下添加自己的测试用例。测试用例的编写方法参考文档中心《utest 测试框架》章节。 +参考已有的测试用例在 `examples\utest\testcases` 目录下添加自己的测试用例。测试用例的编写方法参考文档中心《utest 测试框架》章节。 ### 2. 本地测试 -1. 在 bsp\qemu-vexpress-a9 目录下打开 menuconfig,使能对应的测试用例,如下: +1. 在 `bsp\qemu-vexpress-a9` 目录下打开 `menuconfig`,使能对应的测试用例,如下: ``` RT-Thread Utestcases ---> From 2a56598c8c9b86e94075ac502605f98d908d26d5 Mon Sep 17 00:00:00 2001 From: Tao_eternal Date: Tue, 11 May 2021 12:04:53 +0800 Subject: [PATCH 048/255] Update drv_gpio.c --- bsp/gd32vf103v-eval/drivers/drv_gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsp/gd32vf103v-eval/drivers/drv_gpio.c b/bsp/gd32vf103v-eval/drivers/drv_gpio.c index 77d6472718..f4d9c0923b 100644 --- a/bsp/gd32vf103v-eval/drivers/drv_gpio.c +++ b/bsp/gd32vf103v-eval/drivers/drv_gpio.c @@ -349,13 +349,13 @@ static rt_err_t gd32vf_pin_irq_enable(struct rt_device *device, rt_base_t pin, { return RT_ENOSYS; } - + irqindex = bit2bitno(index->pin); if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) { return RT_ENOSYS; } - + if (enabled == PIN_IRQ_ENABLE) { level = rt_hw_interrupt_disable(); From e3ee4f2846d89d1b33d414bba79e2bbcac191c7e Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Tue, 11 May 2021 18:43:05 +0800 Subject: [PATCH 049/255] =?UTF-8?q?[=E6=9B=B4=E6=96=B0]=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/utest/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/utest/README.md b/examples/utest/README.md index f2fe327473..cc84651966 100644 --- a/examples/utest/README.md +++ b/examples/utest/README.md @@ -15,7 +15,7 @@ ### 1. 编写测试用例 -参考已有的测试用例在 `examples\utest\testcases` 目录下添加自己的测试用例。测试用例的编写方法参考文档中心《utest 测试框架》章节。 +参考已有的测试用例在 [examples\utest\testcases](./testcases) 目录下添加自己的测试用例。测试用例的编写方法参考文档中心《utest 测试框架》章节。 ### 2. 本地测试 @@ -54,7 +54,7 @@ msh />utest_run ### 3. 提交 -1. 如果是对已有测试集合的完善,需要把添加的测试用例的配置项添加到对应测试集合的配置文件里,如:`examples\utest\configs\utest_self\config.h`。 +1. 如果是对已有测试集合的完善,需要把添加的测试用例的配置项添加到对应测试集合的配置文件里,如:[examples\utest\configs\utest_self\config.h](./configs/utest_self/config.h)。 ``` /* RT-Thread Utestcases */ @@ -69,7 +69,7 @@ msh />utest_run #define UTEST_XXX_TC ``` -2. 如果要添加新的测试集合,需要参考已有的测试集合,在 `examples\utest\configs` 目录下添加新的测试集合配置项。并更新 `.github\workflows\action_utest.yml` 内的测试集合。 +2. 如果要添加新的测试集合,需要参考已有的测试集合,在 [examples\utest\configs](./configs) 目录下添加新的测试集合配置项。并更新 [.github\workflows\action_utest.yml](../../.github/workflows/action_utest.yml) 内的测试集合。 ``` - {UTEST: "kernel/ipc", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"} From 5767c2e0f4792adfe7d8031591bfdf95ba004bdb Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Wed, 12 May 2021 09:50:40 +0800 Subject: [PATCH 050/255] =?UTF-8?q?=E3=80=90=E5=AE=8C=E5=96=84=E3=80=91SCo?= =?UTF-8?q?nscript=20=E8=84=9A=E6=9C=AC=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/utest/testcases/utest/SConscript | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/utest/testcases/utest/SConscript b/examples/utest/testcases/utest/SConscript index 362de4d949..1b35042e44 100644 --- a/examples/utest/testcases/utest/SConscript +++ b/examples/utest/testcases/utest/SConscript @@ -2,10 +2,9 @@ Import('rtconfig') from building import * cwd = GetCurrentDir() -src = [] - -if GetDepend('UTEST_SELF_PASS_TC'): - src += ['pass_tc.c'] +src = Split(''' +pass_tc.c +''') CPPPATH = [cwd] From dfb8df71c90e6f306e7abebd7ad94ef93e970ca9 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 12 May 2021 14:17:17 +0800 Subject: [PATCH 051/255] =?UTF-8?q?[libc]=E4=BF=AE=E5=A4=8D=E5=9B=A0libc?= =?UTF-8?q?=E7=A7=BB=E9=99=A4sys/errno.h=E6=96=87=E4=BB=B6=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E7=9A=84=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/libc/pthreads/posix_types.h | 7 ------- components/net/lwip-2.1.2/src/arch/include/arch/cc.h | 9 ++++----- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/components/libc/pthreads/posix_types.h b/components/libc/pthreads/posix_types.h index f2d806cc9a..942657ef39 100644 --- a/components/libc/pthreads/posix_types.h +++ b/components/libc/pthreads/posix_types.h @@ -19,16 +19,9 @@ #include #include - -/* errno for Keil MDK */ -#if defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) -#include -#include -#else #include #include #include -#endif #endif diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h index 320beb53e0..413fef65df 100644 --- a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h @@ -46,17 +46,16 @@ #define X32_F "lx" #ifdef RT_USING_LIBC -#if defined(__CC_ARM) || defined(__CLANG_ARM) || defined(__IAR_SYSTEMS_ICC__) -#include -#else #include -/* some errno not defined in newlib */ +#ifndef ENSRNOTFOUND #define ENSRNOTFOUND 163 /* Domain name not found */ +#endif +#ifndef ESHUTDOWN /* WARNING: ESHUTDOWN also not defined in newlib. We chose 180 here because the number "108" which is used in arch.h has been assigned to another error code. */ #define ESHUTDOWN 180 -#endif /* __CC_ARM/__IAR_SYSTEMS_ICC__ */ +#endif #endif /* RT_USING_LIBC */ #if defined(RT_USING_LIBC) || defined(RT_LIBC_USING_TIME) || (defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) From 6f3f58dae0ccaa7059168deacb41dd59d183cee0 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 12 May 2021 14:41:15 +0800 Subject: [PATCH 052/255] =?UTF-8?q?[bsp][qemu-vexpress-a9]=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=B7=A5=E7=A8=8B=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/qemu-vexpress-a9/.config | 204 ++++++++++++++++++++++--- bsp/qemu-vexpress-a9/drivers/automac.h | 6 +- bsp/qemu-vexpress-a9/rtconfig.h | 37 +++-- 3 files changed, 208 insertions(+), 39 deletions(-) diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config index d333d8865b..2441462035 100644 --- a/bsp/qemu-vexpress-a9/.config +++ b/bsp/qemu-vexpress-a9/.config @@ -24,6 +24,12 @@ CONFIG_IDLE_THREAD_STACK_SIZE=1024 CONFIG_RT_USING_TIMER_SOFT=y CONFIG_RT_TIMER_THREAD_PRIO=4 CONFIG_RT_TIMER_THREAD_STACK_SIZE=1024 + +# +# 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 @@ -56,6 +62,7 @@ CONFIG_RT_USING_MEMHEAP=y CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set # CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_USERHEAP is not set CONFIG_RT_USING_MEMTRACE=y CONFIG_RT_USING_HEAP=y @@ -68,7 +75,7 @@ CONFIG_RT_USING_INTERRUPT_INFO=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x40002 +CONFIG_RT_VER_NUM=0x40004 CONFIG_ARCH_ARM=y # CONFIG_RT_USING_CPU_FFS is not set CONFIG_ARCH_ARM_CORTEX_A=y @@ -112,9 +119,9 @@ CONFIG_FINSH_ARG_MAX=10 # CONFIG_RT_USING_DFS=y CONFIG_DFS_USING_WORKDIR=y -CONFIG_DFS_FILESYSTEMS_MAX=2 +CONFIG_DFS_FILESYSTEMS_MAX=4 CONFIG_DFS_FILESYSTEM_TYPES_MAX=8 -CONFIG_DFS_FD_MAX=16 +CONFIG_DFS_FD_MAX=32 # CONFIG_RT_USING_DFS_MNTTABLE is not set CONFIG_RT_USING_DFS_ELMFAT=y @@ -128,6 +135,11 @@ CONFIG_RT_DFS_ELM_WORD_ACCESS=y # 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=4096 @@ -136,8 +148,6 @@ CONFIG_RT_DFS_ELM_REENTRANT=y CONFIG_RT_USING_DFS_DEVFS=y CONFIG_RT_USING_DFS_ROMFS=y CONFIG_RT_USING_DFS_RAMFS=y -# CONFIG_RT_USING_DFS_UFFS is not set -# CONFIG_RT_USING_DFS_JFFS2 is not set # CONFIG_RT_USING_DFS_NFS is not set # @@ -155,14 +165,17 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set CONFIG_RT_USING_I2C_BITOPS=y +# CONFIG_RT_I2C_BITOPS_DEBUG is not set +# CONFIG_RT_USING_PHY is not set CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set # CONFIG_RT_USING_PWM is not set CONFIG_RT_USING_MTD_NOR=y CONFIG_RT_USING_MTD_NAND=y CONFIG_RT_MTD_NAND_DEBUG=y -# CONFIG_RT_USING_MTD is not set # CONFIG_RT_USING_PM is not set CONFIG_RT_USING_RTC=y # CONFIG_RT_USING_ALARM is not set @@ -181,6 +194,7 @@ CONFIG_RT_USING_SFUD=y CONFIG_RT_SFUD_USING_SFDP=y CONFIG_RT_SFUD_USING_FLASH_INFO_TABLE=y # CONFIG_RT_SFUD_USING_QSPI is not set +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 @@ -188,15 +202,9 @@ CONFIG_RT_USING_WDT=y # CONFIG_RT_USING_AUDIO is not set # CONFIG_RT_USING_SENSOR is not set # CONFIG_RT_USING_TOUCH is not set - -# -# Using Hardware Crypto drivers -# # CONFIG_RT_USING_HWCRYPTO is not set - -# -# Using WiFi -# +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set # CONFIG_RT_USING_WIFI is not set # @@ -214,8 +222,10 @@ CONFIG_PTHREAD_NUM_MAX=8 CONFIG_RT_USING_POSIX=y CONFIG_RT_USING_POSIX_MMAP=y CONFIG_RT_USING_POSIX_TERMIOS=y +CONFIG_RT_USING_POSIX_GETLINE=y CONFIG_RT_USING_POSIX_AIO=y # CONFIG_RT_USING_MODULE is not set +CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # # Network @@ -225,6 +235,7 @@ CONFIG_RT_USING_POSIX_AIO=y # Socket abstraction layer # CONFIG_RT_USING_SAL=y +CONFIG_SAL_INTERNET_CHECK=y # # protocol stack implement @@ -250,9 +261,10 @@ CONFIG_NETDEV_IPV6=0 # CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set -CONFIG_RT_USING_LWIP202=y -# CONFIG_RT_USING_LWIP210 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 is not set CONFIG_RT_LWIP_ICMP=y # CONFIG_RT_LWIP_SNMP is not set @@ -294,6 +306,7 @@ 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 @@ -301,11 +314,6 @@ CONFIG_LWIP_NETIF_LOOPBACK=0 CONFIG_RT_LWIP_USING_PING=y # CONFIG_RT_LWIP_DEBUG is not set -# -# Modbus master and slave stack -# -# CONFIG_RT_USING_MODBUS is not set - # # AT commands # @@ -320,7 +328,9 @@ CONFIG_RT_LWIP_USING_PING=y # # Utilities # -# CONFIG_RT_USING_RYM is not set +CONFIG_RT_USING_RYM=y +# CONFIG_YMODEM_USING_CRC_TABLE is not set +CONFIG_YMODEM_USING_FILE_TRANSFER=y # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set CONFIG_RT_USING_LWP=y @@ -332,14 +342,20 @@ CONFIG_RT_USING_LWP=y # # 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 @@ -361,6 +377,8 @@ CONFIG_RT_USING_LWP=y # 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 @@ -372,13 +390,34 @@ CONFIG_RT_USING_LWP=y # CONFIG_PKG_USING_GAGENT_CLOUD is not set # CONFIG_PKG_USING_ALI_IOTKIT is not set # CONFIG_PKG_USING_AZURE is not set -# CONFIG_PKG_USING_TENCENT_IOTHUB is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set # CONFIG_PKG_USING_NIMBLE is not set # CONFIG_PKG_USING_OTA_DOWNLOADER is not set # CONFIG_PKG_USING_IPMSG is not set # CONFIG_PKG_USING_LSSDP is not set # CONFIG_PKG_USING_AIRKISS_OPEN is not set # CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set # # security packages @@ -386,6 +425,8 @@ CONFIG_RT_USING_LWP=y # 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 @@ -400,6 +441,11 @@ CONFIG_RT_USING_LWP=y # CONFIG_PKG_USING_OPENMV is not set # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set # # tools packages @@ -411,7 +457,31 @@ CONFIG_RT_USING_LWP=y # 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 # # system packages @@ -423,6 +493,7 @@ CONFIG_RT_USING_LWP=y # CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set @@ -430,6 +501,32 @@ CONFIG_RT_USING_LWP=y # CONFIG_PKG_USING_DFS_YAFFS is not set # CONFIG_PKG_USING_LITTLEFS is not set # CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_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_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# 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 +# CONFIG_PKG_USING_LPM is not set # # peripheral libraries and drivers @@ -437,6 +534,8 @@ CONFIG_RT_USING_LWP=y # 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 @@ -445,10 +544,16 @@ CONFIG_RT_USING_LWP=y # 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 @@ -456,6 +561,34 @@ CONFIG_RT_USING_LWP=y # 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 # # miscellaneous packages @@ -465,13 +598,17 @@ CONFIG_RT_USING_LWP=y # 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_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 @@ -482,7 +619,28 @@ CONFIG_RT_USING_LWP=y # CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set # CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set + +# +# games: games run on RT-Thread console +# +# 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_LWGPS is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO 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_SOC_VEXPRESS_A9=y CONFIG_RT_USING_UART0=y CONFIG_RT_USING_UART1=y diff --git a/bsp/qemu-vexpress-a9/drivers/automac.h b/bsp/qemu-vexpress-a9/drivers/automac.h index 7c4ca08fbc..567b1f82fb 100644 --- a/bsp/qemu-vexpress-a9/drivers/automac.h +++ b/bsp/qemu-vexpress-a9/drivers/automac.h @@ -8,8 +8,8 @@ #define AUTOMAC0 0x52 #define AUTOMAC1 0x54 #define AUTOMAC2 0x00 -#define AUTOMAC3 0xa0 -#define AUTOMAC4 0x0e -#define AUTOMAC5 0xe4 +#define AUTOMAC3 0x78 +#define AUTOMAC4 0xe7 +#define AUTOMAC5 0x23 #endif diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h index cec4ec6ba4..673ec3e792 100644 --- a/bsp/qemu-vexpress-a9/rtconfig.h +++ b/bsp/qemu-vexpress-a9/rtconfig.h @@ -21,6 +21,9 @@ #define RT_USING_TIMER_SOFT #define RT_TIMER_THREAD_PRIO 4 #define RT_TIMER_THREAD_STACK_SIZE 1024 + +/* kservice optimization */ + #define RT_DEBUG #define RT_DEBUG_COLOR @@ -49,7 +52,7 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 256 #define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40002 +#define RT_VER_NUM 0x40004 #define ARCH_ARM #define ARCH_ARM_CORTEX_A #define ARCH_ARM_CORTEX_A9 @@ -84,9 +87,9 @@ #define RT_USING_DFS #define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 2 +#define DFS_FILESYSTEMS_MAX 4 #define DFS_FILESYSTEM_TYPES_MAX 8 -#define DFS_FD_MAX 16 +#define DFS_FD_MAX 32 #define RT_USING_DFS_ELMFAT /* elm-chan's FatFs, Generic FAT Filesystem Module */ @@ -95,6 +98,8 @@ #define RT_DFS_ELM_WORD_ACCESS #define RT_DFS_ELM_USE_LFN_3 #define RT_DFS_ELM_USE_LFN 3 +#define RT_DFS_ELM_LFN_UNICODE_0 +#define RT_DFS_ELM_LFN_UNICODE 0 #define RT_DFS_ELM_MAX_LFN 255 #define RT_DFS_ELM_DRIVES 2 #define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 @@ -132,14 +137,9 @@ #define RT_USING_SFUD #define RT_SFUD_USING_SFDP #define RT_SFUD_USING_FLASH_INFO_TABLE +#define RT_SFUD_SPI_MAX_HZ 50000000 #define RT_USING_WDT -/* Using Hardware Crypto drivers */ - - -/* Using WiFi */ - - /* Using USB */ @@ -151,13 +151,16 @@ #define RT_USING_POSIX #define RT_USING_POSIX_MMAP #define RT_USING_POSIX_TERMIOS +#define RT_USING_POSIX_GETLINE #define RT_USING_POSIX_AIO +#define RT_LIBC_FIXED_TIMEZONE 8 /* Network */ /* Socket abstraction layer */ #define RT_USING_SAL +#define SAL_INTERNET_CHECK /* protocol stack implement */ @@ -177,7 +180,8 @@ /* light weight TCP/IP stack */ #define RT_USING_LWIP -#define RT_USING_LWIP202 +#define RT_USING_LWIP212 +#define RT_LWIP_MEM_ALIGNMENT 4 #define RT_LWIP_ICMP #define RT_LWIP_DNS #define RT_LWIP_DHCP @@ -213,12 +217,10 @@ #define LWIP_SO_RCVTIMEO 1 #define LWIP_SO_SNDTIMEO 1 #define LWIP_SO_RCVBUF 1 +#define LWIP_SO_LINGER 0 #define LWIP_NETIF_LOOPBACK 0 #define RT_LWIP_USING_PING -/* Modbus master and slave stack */ - - /* AT commands */ @@ -226,6 +228,9 @@ /* Utilities */ + +#define RT_USING_RYM +#define YMODEM_USING_FILE_TRANSFER #define RT_USING_LWP /* RT-Thread online packages */ @@ -259,6 +264,9 @@ /* system packages */ +/* Micrium: Micrium software products porting for RT-Thread */ + + /* peripheral libraries and drivers */ @@ -267,6 +275,9 @@ /* samples: kernel and components samples */ + +/* games: games run on RT-Thread console */ + #define SOC_VEXPRESS_A9 #define RT_USING_UART0 #define RT_USING_UART1 From e13827ec7fe88a592c0b0cfa477c9d122b8450f4 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 12 May 2021 14:48:49 +0800 Subject: [PATCH 053/255] =?UTF-8?q?[bsp][qemu-vexpress-a9]=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/qemu-vexpress-a9/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bsp/qemu-vexpress-a9/README.md b/bsp/qemu-vexpress-a9/README.md index 7ad3f30aa8..47ba61c4e8 100644 --- a/bsp/qemu-vexpress-a9/README.md +++ b/bsp/qemu-vexpress-a9/README.md @@ -34,7 +34,7 @@ QEMU/VExpress A9是QEMU模拟器针对ARM VExpress-A9 FPGA开发板进行软件 ## 3. 执行 -当要执行编译好的RT-Thread时,在这个bsp目录下已经提供了运行脚本文件:qemu.bat/qemu.sh +当要执行编译好的RT-Thread时,在这个bsp目录下已经提供了运行脚本文件:qemu.bat和qemu.sh。可以在bsp目录下运行env,在env中敲入qemu.bat即可直接运行。 这个执行脚本默认把串口输出到stdio(即控制台)上,所以直接执行脚本后就可以输出结果了。 @@ -99,7 +99,7 @@ start qemu-system-arm -M vexpress-a9 -kernel rtthread.elf -serial stdio -sd sd.b 维护人:[bernard][4] - [1]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.boards.express/index.html - [2]: https://www.rt-thread.org/page/download.html - [3]: https://launchpad.net/gcc-arm-embedded/5.0/5-2016-q3-update/+download/gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2 - [4]: https://github.com/BernardXiong +[1]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.boards.express/index.html +[2]: https://www.rt-thread.org/page/download.html +[3]: https://launchpad.net/gcc-arm-embedded/5.0/5-2016-q3-update/+download/gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2 +[4]: https://github.com/BernardXiong \ No newline at end of file From f58fbe5e788404fd89da0a75f4043ba7dad70358 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 12 May 2021 18:28:29 +0800 Subject: [PATCH 054/255] rever ymodem --- bsp/qemu-vexpress-a9/.config | 4 +--- bsp/qemu-vexpress-a9/rtconfig.h | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config index 2441462035..00929cbed0 100644 --- a/bsp/qemu-vexpress-a9/.config +++ b/bsp/qemu-vexpress-a9/.config @@ -328,9 +328,7 @@ CONFIG_RT_LWIP_USING_PING=y # # Utilities # -CONFIG_RT_USING_RYM=y -# CONFIG_YMODEM_USING_CRC_TABLE is not set -CONFIG_YMODEM_USING_FILE_TRANSFER=y +# CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set CONFIG_RT_USING_LWP=y diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h index 673ec3e792..4ca586afff 100644 --- a/bsp/qemu-vexpress-a9/rtconfig.h +++ b/bsp/qemu-vexpress-a9/rtconfig.h @@ -229,8 +229,6 @@ /* Utilities */ -#define RT_USING_RYM -#define YMODEM_USING_FILE_TRANSFER #define RT_USING_LWP /* RT-Thread online packages */ From d3131ee55ff88a6a2e25631773e1b4a781e17631 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Wed, 12 May 2021 18:49:31 +0800 Subject: [PATCH 055/255] Nuvoton release/update. (1) Support NK-N9H30 board. (2) Change Mutex's flag to RT_IPC_FLAG_PRIO from RT_IPC_FLAG_FIFO. --- bsp/nuvoton/README.md | 7 +- .../libraries/m2354/rtt_port/drv_crc.c | 2 +- .../libraries/m2354/rtt_port/drv_crypto.c | 6 +- .../libraries/m2354/rtt_port/drv_fmc.c | 2 +- .../libraries/m2354/rtt_port/drv_pdma.c | 6 +- .../libraries/m2354/rtt_port/drv_qspi.c | 11 +- .../libraries/m2354/rtt_port/drv_slcd.c | 2 +- .../libraries/m2354/rtt_port/drv_trng.c | 2 +- .../libraries/m480/StdDriver/src/nu_emac.c | 11 +- .../libraries/m480/StdDriver/src/nu_qspi.c | 156 +-- bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c | 2 +- .../libraries/m480/rtt_port/drv_crypto.c | 8 +- bsp/nuvoton/libraries/m480/rtt_port/drv_fmc.c | 2 +- .../libraries/m480/rtt_port/drv_pdma.c | 6 +- .../libraries/m480/rtt_port/drv_qspi.c | 11 +- .../libraries/m480/rtt_port/drv_trng.c | 2 +- .../nu_packages/AudioCodec/audio_test.c | 42 + .../nu_packages/SPINAND/drv_spinand.c | 2 +- .../nuc980/Driver/Source/nu_crypto.c | 2 + .../libraries/nuc980/Driver/Source/nu_emac.c | 4 +- .../libraries/nuc980/rtt_port/drv_crypto.c | 6 +- .../libraries/nuc980/rtt_port/drv_pdma.c | 2 +- .../libraries/nuc980/rtt_port/drv_rtc.c | 2 + bsp/nuvoton/nk-980iot/.config | 92 +- .../nk-980iot/linking_scripts/nuc980.ld | 9 +- bsp/nuvoton/nk-n9h30/.config | 894 ++++++++++++++++++ bsp/nuvoton/nk-n9h30/Kconfig | 29 + bsp/nuvoton/nk-n9h30/README.md | 136 +++ bsp/nuvoton/nk-n9h30/SConscript | 14 + bsp/nuvoton/nk-n9h30/SConstruct | 55 ++ bsp/nuvoton/nk-n9h30/applications/SConscript | 11 + bsp/nuvoton/nk-n9h30/applications/main.c | 118 +++ bsp/nuvoton/nk-n9h30/applications/mnt.c | 243 +++++ bsp/nuvoton/nk-n9h30/board/Kconfig | 75 ++ bsp/nuvoton/nk-n9h30/board/SConscript | 14 + bsp/nuvoton/nk-n9h30/board/board.h | 37 + bsp/nuvoton/nk-n9h30/board/board_dev.c | 333 +++++++ bsp/nuvoton/nk-n9h30/board/fal_cfg.h | 46 + bsp/nuvoton/nk-n9h30/board/nu_pin_init.c | 155 +++ bsp/nuvoton/nk-n9h30/linking_scripts/n9h30.ld | 111 +++ .../nk-n9h30/linking_scripts/n9h30.sct | 11 + bsp/nuvoton/nk-n9h30/rtconfig.py | 88 ++ bsp/nuvoton/nk-n9h30/template.uvproj | 394 ++++++++ bsp/nuvoton/nk-n9h30/template.uvprojx | 387 ++++++++ .../nk-rtu980/linking_scripts/nuc980.ld | 9 +- bsp/nuvoton/numaker-m2354/Nu_Link_Driver.ini | 10 +- 46 files changed, 3407 insertions(+), 160 deletions(-) create mode 100644 bsp/nuvoton/nk-n9h30/.config create mode 100644 bsp/nuvoton/nk-n9h30/Kconfig create mode 100644 bsp/nuvoton/nk-n9h30/README.md create mode 100644 bsp/nuvoton/nk-n9h30/SConscript create mode 100644 bsp/nuvoton/nk-n9h30/SConstruct create mode 100644 bsp/nuvoton/nk-n9h30/applications/SConscript create mode 100644 bsp/nuvoton/nk-n9h30/applications/main.c create mode 100644 bsp/nuvoton/nk-n9h30/applications/mnt.c create mode 100644 bsp/nuvoton/nk-n9h30/board/Kconfig create mode 100644 bsp/nuvoton/nk-n9h30/board/SConscript create mode 100644 bsp/nuvoton/nk-n9h30/board/board.h create mode 100644 bsp/nuvoton/nk-n9h30/board/board_dev.c create mode 100644 bsp/nuvoton/nk-n9h30/board/fal_cfg.h create mode 100644 bsp/nuvoton/nk-n9h30/board/nu_pin_init.c create mode 100644 bsp/nuvoton/nk-n9h30/linking_scripts/n9h30.ld create mode 100644 bsp/nuvoton/nk-n9h30/linking_scripts/n9h30.sct create mode 100644 bsp/nuvoton/nk-n9h30/rtconfig.py create mode 100644 bsp/nuvoton/nk-n9h30/template.uvproj create mode 100644 bsp/nuvoton/nk-n9h30/template.uvprojx diff --git a/bsp/nuvoton/README.md b/bsp/nuvoton/README.md index 9d0c433984..1bd95a9edc 100644 --- a/bsp/nuvoton/README.md +++ b/bsp/nuvoton/README.md @@ -1,10 +1,11 @@ -? Nuvoton BSP descriptions +Nuvoton BSP descriptions Current supported BSP shown in below table: -| **BSP folder** | **Board name** | +| **BSP Folder** | **Board Name** | |:------------------------- |:-------------------------- | | [numaker-iot-m487](numaker-iot-m487) | Nuvoton NuMaker-IoT-M487 | | [numaker-pfm-m487](numaker-pfm-m487) | Nuvoton NuMaker-PFM-M487 | | [nk-980iot](nk-980iot) | Nuvoton NK-980IOT | | [numaker-m2354](numaker-m2354) | Nuvoton NuMaker-M2354 | -| [nk-rtu980](nk-rtu980) | Nuvoton NK-RTU980 | \ No newline at end of file +| [nk-rtu980](nk-rtu980) | Nuvoton NK-RTU980 | +| [nk-n9h30](nk-n9h30) | Nuvoton NK-N9H30 | \ No newline at end of file diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_crc.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_crc.c index 11051deef0..5e82c82367 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_crc.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_crc.c @@ -94,7 +94,7 @@ rt_err_t nu_crc_init(void) { SYS_ResetModule(CRC_RST); - rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_FIFO); + rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO); return RT_EOK; } diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_crypto.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_crypto.c index c528cdc100..91f1d26819 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_crypto.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_crypto.c @@ -82,11 +82,11 @@ static rt_err_t nu_crypto_init(void) SHA_ENABLE_INT(CRPT); //init cipher mutex - rt_mutex_init(&s_AES_mutex, NU_HWCRYPTO_AES_NAME, RT_IPC_FLAG_FIFO); - rt_mutex_init(&s_SHA_mutex, NU_HWCRYPTO_SHA_NAME, RT_IPC_FLAG_FIFO); + rt_mutex_init(&s_AES_mutex, NU_HWCRYPTO_AES_NAME, RT_IPC_FLAG_PRIO); + rt_mutex_init(&s_SHA_mutex, NU_HWCRYPTO_SHA_NAME, RT_IPC_FLAG_PRIO); #if !defined(BSP_USING_TRNG) PRNG_ENABLE_INT(CRPT); - rt_mutex_init(&s_PRNG_mutex, NU_HWCRYPTO_PRNG_NAME, RT_IPC_FLAG_FIFO); + rt_mutex_init(&s_PRNG_mutex, NU_HWCRYPTO_PRNG_NAME, RT_IPC_FLAG_PRIO); #endif return RT_EOK; diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_fmc.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_fmc.c index a5a97bea1b..66e251c020 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_fmc.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_fmc.c @@ -314,7 +314,7 @@ static int nu_fmc_init(void) FMC_ENABLE_ISP(); SYS_LockReg(); - g_mutex_fmc = rt_mutex_create("nu_fmc_lock", RT_IPC_FLAG_FIFO); + g_mutex_fmc = rt_mutex_create("nu_fmc_lock", RT_IPC_FLAG_PRIO); /* PKG_USING_FAL */ #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_pdma.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_pdma.c index 6cbe151347..96c29a5e4e 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_pdma.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_pdma.c @@ -210,7 +210,7 @@ static void nu_pdma_init(void) if (nu_pdma_inited) return; - g_mutex_sg = rt_mutex_create("sgtbles", RT_IPC_FLAG_FIFO); + g_mutex_sg = rt_mutex_create("sgtbles", RT_IPC_FLAG_PRIO); RT_ASSERT(g_mutex_sg != RT_NULL); nu_pdma_chn_mask = ~(NU_PDMA_CH_Msk); @@ -534,7 +534,7 @@ rt_err_t nu_pdma_desc_setup(int i32ChannID, nu_pdma_desc_t dma_desc, uint32_t u3 goto exit_nu_pdma_desc_setup; else if ((u32AddrSrc % (u32DataWidth / 8)) || (u32AddrDst % (u32DataWidth / 8))) goto exit_nu_pdma_desc_setup; - else if ( i32TransferCnt > NU_PDMA_MAX_TXCNT ) + else if (i32TransferCnt > NU_PDMA_MAX_TXCNT) goto exit_nu_pdma_desc_setup; PDMA = NU_PDMA_GET_BASE(i32ChannID); @@ -890,7 +890,7 @@ static void nu_pdma_memfun_actor_init(void) nu_pdma_memfun_actor_maxnum = i; nu_pdma_memfun_actor_mask = ~(((1 << i) - 1)); nu_pdma_memfun_actor_pool_sem = rt_sem_create("mempool_sem", nu_pdma_memfun_actor_maxnum, RT_IPC_FLAG_FIFO); - nu_pdma_memfun_actor_pool_lock = rt_mutex_create("mempool_lock", RT_IPC_FLAG_FIFO); + nu_pdma_memfun_actor_pool_lock = rt_mutex_create("mempool_lock", RT_IPC_FLAG_PRIO); } } diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_qspi.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_qspi.c index 279d4b4276..bf023aefa6 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_qspi.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_qspi.c @@ -161,10 +161,10 @@ exit_nu_qspi_bus_configure: return -(ret); } -#if defined(RT_SFUD_USING_QSPI) static int nu_qspi_mode_config(struct nu_spi *qspi_bus, rt_uint8_t *tx, rt_uint8_t *rx, int qspi_lines) { QSPI_T *qspi_base = (QSPI_T *)qspi_bus->spi_base; +#if defined(RT_SFUD_USING_QSPI) if (qspi_lines > 1) { if (tx) @@ -199,13 +199,13 @@ static int nu_qspi_mode_config(struct nu_spi *qspi_bus, rt_uint8_t *tx, rt_uint8 } } else +#endif { QSPI_DISABLE_DUAL_MODE(qspi_base); QSPI_DISABLE_QUAD_MODE(qspi_base); } return qspi_lines; } -#endif static rt_uint32_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message) { @@ -298,9 +298,11 @@ static rt_uint32_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_ qspi_message->dummy_cycles / (8 / u8last), 1); } - /* Data stage */ nu_qspi_mode_config(qspi_bus, (rt_uint8_t *) message->send_buf, (rt_uint8_t *) message->recv_buf, qspi_message->qspi_data_lines); +#else + /* Data stage */ + nu_qspi_mode_config(qspi_bus, RT_NULL, RT_NULL, 1); #endif //#if defined(RT_SFUD_USING_QSPI) if (message->length != 0) @@ -350,8 +352,7 @@ static int rt_hw_qspi_init(void) #if defined(BSP_USING_SPI_PDMA) nu_qspi_arr[i].pdma_chanid_tx = -1; nu_qspi_arr[i].pdma_chanid_rx = -1; -#endif -#if defined(BSP_USING_QSPI_PDMA) + if ((nu_qspi_arr[i].pdma_perp_tx != NU_PDMA_UNUSED) && (nu_qspi_arr[i].pdma_perp_rx != NU_PDMA_UNUSED)) { if (nu_hw_spi_pdma_allocate(&nu_qspi_arr[i]) != RT_EOK) diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_slcd.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_slcd.c index 3a673983a0..d9c17295b0 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_slcd.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_slcd.c @@ -222,7 +222,7 @@ static int rt_hw_slcd_init(void) { ret = rt_hw_slcd_register(&nu_slcd_arr[i].dev, nu_slcd_arr[i].name, RT_DEVICE_FLAG_RDWR, NULL); RT_ASSERT(ret == RT_EOK); - nu_slcd_arr[i].lock = rt_mutex_create(nu_slcd_arr[i].name, RT_IPC_FLAG_FIFO); + nu_slcd_arr[i].lock = rt_mutex_create(nu_slcd_arr[i].name, RT_IPC_FLAG_PRIO); RT_ASSERT(nu_slcd_arr[i].lock != RT_NULL); } diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_trng.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_trng.c index 5640494ce4..485ff8fea2 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_trng.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_trng.c @@ -50,7 +50,7 @@ rt_err_t nu_trng_init(void) { rt_err_t result; - result = rt_mutex_init(&s_TRNG_mutex, NU_CRYPTO_TRNG_NAME, RT_IPC_FLAG_FIFO); + result = rt_mutex_init(&s_TRNG_mutex, NU_CRYPTO_TRNG_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); s_i32TRNGEnable = 1; diff --git a/bsp/nuvoton/libraries/m480/StdDriver/src/nu_emac.c b/bsp/nuvoton/libraries/m480/StdDriver/src/nu_emac.c index 2b93f1ddd9..18fdfc699b 100644 --- a/bsp/nuvoton/libraries/m480/StdDriver/src/nu_emac.c +++ b/bsp/nuvoton/libraries/m480/StdDriver/src/nu_emac.c @@ -209,7 +209,7 @@ void EMAC_PhyInit(void) while (!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID)) { - if (i++ > 80000UL) /* Cable not connected */ + if (i++ > 10000UL) /* Cable not connected */ { EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk; EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk; @@ -217,7 +217,7 @@ void EMAC_PhyInit(void) } } - if (i <= 80000UL) + if (i <= 10000UL) { /* Configure auto negotiation capability */ EMAC_MdioWrite(PHY_ANA_REG, EMAC_PHY_ADDR, PHY_ANA_DR100_TX_FULL | @@ -747,7 +747,8 @@ uint32_t EMAC_SendPktDone(void) desc->u32Next = desc->u32Backup2; /* go to next descriptor in link */ desc = (EMAC_DESCRIPTOR_T *)desc->u32Next; - } while (last_tx_desc != (uint32_t)desc); /* If we reach last sent Tx descriptor, leave the loop */ + } + while (last_tx_desc != (uint32_t)desc); /* If we reach last sent Tx descriptor, leave the loop */ /* Save last processed Tx descriptor */ u32CurrentTxDesc = (uint32_t)desc; @@ -1115,7 +1116,7 @@ uint8_t *EMAC_ClaimFreeTXBuf(void) * @return An data length of avaiable RX buffer. * @note This API should be called before EMAC_RecvPktDone_WoTrigger calling. Caller will do data-copy. */ -uint32_t EMAC_GetAvailRXBufSize(uint8_t** ppuDataBuf) +uint32_t EMAC_GetAvailRXBufSize(uint8_t **ppuDataBuf) { EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc; @@ -1126,7 +1127,7 @@ uint32_t EMAC_GetAvailRXBufSize(uint8_t** ppuDataBuf) /* It is good and no CRC error. */ if ((status & EMAC_RXFD_RXGD) && !(status & EMAC_RXFD_CRCE)) { - *ppuDataBuf = (uint8_t*)desc->u32Backup1; + *ppuDataBuf = (uint8_t *)desc->u32Backup1; return desc->u32Status1 & 0xFFFFUL; } else diff --git a/bsp/nuvoton/libraries/m480/StdDriver/src/nu_qspi.c b/bsp/nuvoton/libraries/m480/StdDriver/src/nu_qspi.c index b0f3ff2b5a..ea08e43f70 100644 --- a/bsp/nuvoton/libraries/m480/StdDriver/src/nu_qspi.c +++ b/bsp/nuvoton/libraries/m480/StdDriver/src/nu_qspi.c @@ -46,9 +46,9 @@ uint32_t QSPI_Open(QSPI_T *qspi, uint32_t u32DataWidth, uint32_t u32BusClock) { - uint32_t u32ClkSrc = 0U, u32Div, u32HCLKFreq, u32RetValue=0U; + uint32_t u32ClkSrc = 0U, u32Div, u32HCLKFreq, u32RetValue = 0U; - if(u32DataWidth == 32U) + if (u32DataWidth == 32U) { u32DataWidth = 0U; } @@ -56,7 +56,7 @@ uint32_t QSPI_Open(QSPI_T *qspi, /* Get system clock frequency */ u32HCLKFreq = CLK_GetHCLKFreq(); - if(u32MasterSlave == QSPI_MASTER) + if (u32MasterSlave == QSPI_MASTER) { /* Default setting: slave selection signal is active low; disable automatic slave selection function. */ qspi->SSCTL = QSPI_SS_ACTIVE_LOW; @@ -64,7 +64,7 @@ uint32_t QSPI_Open(QSPI_T *qspi, /* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */ qspi->CTL = u32MasterSlave | (u32DataWidth << QSPI_CTL_DWIDTH_Pos) | (u32QSPIMode) | QSPI_CTL_QSPIEN_Msk; - if(u32BusClock >= u32HCLKFreq) + if (u32BusClock >= u32HCLKFreq) { /* Select PCLK as the clock source of QSPI */ if (qspi == QSPI0) @@ -76,15 +76,15 @@ uint32_t QSPI_Open(QSPI_T *qspi, /* Check clock source of QSPI */ if (qspi == QSPI0) { - if((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT) + if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT) { u32ClkSrc = __HXT; /* Clock source is HXT */ } - else if((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL) + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL) { u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ } - else if((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0) + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0) { /* Clock source is PCLK0 */ u32ClkSrc = CLK_GetPCLK0Freq(); @@ -96,15 +96,15 @@ uint32_t QSPI_Open(QSPI_T *qspi, } else if (qspi == QSPI1) { - if((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_HXT) + if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_HXT) { u32ClkSrc = __HXT; /* Clock source is HXT */ } - else if((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PLL) + else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PLL) { u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ } - else if((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PCLK1) + else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PCLK1) { /* Clock source is PCLK1 */ u32ClkSrc = CLK_GetPCLK1Freq(); @@ -115,21 +115,21 @@ uint32_t QSPI_Open(QSPI_T *qspi, } } - if(u32BusClock >= u32HCLKFreq) + if (u32BusClock >= u32HCLKFreq) { /* Set DIVIDER = 0 */ qspi->CLKDIV = 0U; /* Return master peripheral clock rate */ u32RetValue = u32ClkSrc; } - else if(u32BusClock >= u32ClkSrc) + else if (u32BusClock >= u32ClkSrc) { /* Set DIVIDER = 0 */ qspi->CLKDIV = 0U; /* Return master peripheral clock rate */ u32RetValue = u32ClkSrc; } - else if(u32BusClock == 0U) + else if (u32BusClock == 0U) { /* Set DIVIDER to the maximum value 0xFF. f_qspi = f_qspi_clk_src / (DIVIDER + 1) */ qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk; @@ -139,7 +139,7 @@ uint32_t QSPI_Open(QSPI_T *qspi, else { u32Div = (((u32ClkSrc * 10U) / u32BusClock + 5U) / 10U) - 1U; /* Round to the nearest integer */ - if(u32Div > 0xFFU) + if (u32Div > 0xFFU) { u32Div = 0xFFU; qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk; @@ -272,7 +272,7 @@ uint32_t QSPI_SetBusClock(QSPI_T *qspi, uint32_t u32BusClock) /* Get system clock frequency */ u32HCLKFreq = CLK_GetHCLKFreq(); - if(u32BusClock >= u32HCLKFreq) + if (u32BusClock >= u32HCLKFreq) { /* Select PCLK as the clock source of QSPI */ if (qspi == QSPI0) @@ -284,15 +284,15 @@ uint32_t QSPI_SetBusClock(QSPI_T *qspi, uint32_t u32BusClock) /* Check clock source of QSPI */ if (qspi == QSPI0) { - if((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT) + if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT) { u32ClkSrc = __HXT; /* Clock source is HXT */ } - else if((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL) + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL) { u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ } - else if((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0) + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0) { /* Clock source is PCLK0 */ u32ClkSrc = CLK_GetPCLK0Freq(); @@ -304,15 +304,15 @@ uint32_t QSPI_SetBusClock(QSPI_T *qspi, uint32_t u32BusClock) } else if (qspi == QSPI1) { - if((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_HXT) + if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_HXT) { u32ClkSrc = __HXT; /* Clock source is HXT */ } - else if((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PLL) + else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PLL) { u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ } - else if((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PCLK1) + else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PCLK1) { /* Clock source is PCLK1 */ u32ClkSrc = CLK_GetPCLK1Freq(); @@ -323,21 +323,21 @@ uint32_t QSPI_SetBusClock(QSPI_T *qspi, uint32_t u32BusClock) } } - if(u32BusClock >= u32HCLKFreq) + if (u32BusClock >= u32HCLKFreq) { /* Set DIVIDER = 0 */ qspi->CLKDIV = 0U; /* Return master peripheral clock rate */ u32RetValue = u32ClkSrc; } - else if(u32BusClock >= u32ClkSrc) + else if (u32BusClock >= u32ClkSrc) { /* Set DIVIDER = 0 */ qspi->CLKDIV = 0U; /* Return master peripheral clock rate */ u32RetValue = u32ClkSrc; } - else if(u32BusClock == 0U) + else if (u32BusClock == 0U) { /* Set DIVIDER to the maximum value 0xFF. f_qspi = f_qspi_clk_src / (DIVIDER + 1) */ qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk; @@ -347,7 +347,7 @@ uint32_t QSPI_SetBusClock(QSPI_T *qspi, uint32_t u32BusClock) else { u32Div = (((u32ClkSrc * 10U) / u32BusClock + 5U) / 10U) - 1U; /* Round to the nearest integer */ - if(u32Div > 0x1FFU) + if (u32Div > 0x1FFU) { u32Div = 0x1FFU; qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk; @@ -389,7 +389,7 @@ void QSPI_SetFIFO(QSPI_T *qspi, uint32_t u32TxThreshold, uint32_t u32RxThreshold uint32_t QSPI_GetBusClock(QSPI_T *qspi) { uint32_t u32Div; - uint32_t u32ClkSrc; + uint32_t u32ClkSrc = 0; /* Get DIVIDER setting */ u32Div = (qspi->CLKDIV & QSPI_CLKDIV_DIVIDER_Msk) >> QSPI_CLKDIV_DIVIDER_Pos; @@ -397,15 +397,15 @@ uint32_t QSPI_GetBusClock(QSPI_T *qspi) /* Check clock source of QSPI */ if (qspi == QSPI0) { - if((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT) + if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT) { u32ClkSrc = __HXT; /* Clock source is HXT */ } - else if((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL) + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL) { u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ } - else if((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0) + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0) { /* Clock source is PCLK0 */ u32ClkSrc = CLK_GetPCLK0Freq(); @@ -417,15 +417,15 @@ uint32_t QSPI_GetBusClock(QSPI_T *qspi) } else if (qspi == QSPI1) { - if((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_HXT) + if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_HXT) { u32ClkSrc = __HXT; /* Clock source is HXT */ } - else if((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PLL) + else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PLL) { u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ } - else if((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PCLK1) + else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PCLK1) { /* Clock source is PCLK1 */ u32ClkSrc = CLK_GetPCLK1Freq(); @@ -463,61 +463,61 @@ uint32_t QSPI_GetBusClock(QSPI_T *qspi) void QSPI_EnableInt(QSPI_T *qspi, uint32_t u32Mask) { /* Enable unit transfer interrupt flag */ - if((u32Mask & QSPI_UNIT_INT_MASK) == QSPI_UNIT_INT_MASK) + if ((u32Mask & QSPI_UNIT_INT_MASK) == QSPI_UNIT_INT_MASK) { qspi->CTL |= QSPI_CTL_UNITIEN_Msk; } /* Enable slave selection signal active interrupt flag */ - if((u32Mask & QSPI_SSACT_INT_MASK) == QSPI_SSACT_INT_MASK) + if ((u32Mask & QSPI_SSACT_INT_MASK) == QSPI_SSACT_INT_MASK) { qspi->SSCTL |= QSPI_SSCTL_SSACTIEN_Msk; } /* Enable slave selection signal inactive interrupt flag */ - if((u32Mask & QSPI_SSINACT_INT_MASK) == QSPI_SSINACT_INT_MASK) + if ((u32Mask & QSPI_SSINACT_INT_MASK) == QSPI_SSINACT_INT_MASK) { qspi->SSCTL |= QSPI_SSCTL_SSINAIEN_Msk; } /* Enable slave TX under run interrupt flag */ - if((u32Mask & QSPI_SLVUR_INT_MASK) == QSPI_SLVUR_INT_MASK) + if ((u32Mask & QSPI_SLVUR_INT_MASK) == QSPI_SLVUR_INT_MASK) { qspi->SSCTL |= QSPI_SSCTL_SLVURIEN_Msk; } /* Enable slave bit count error interrupt flag */ - if((u32Mask & QSPI_SLVBE_INT_MASK) == QSPI_SLVBE_INT_MASK) + if ((u32Mask & QSPI_SLVBE_INT_MASK) == QSPI_SLVBE_INT_MASK) { qspi->SSCTL |= QSPI_SSCTL_SLVBEIEN_Msk; } /* Enable slave TX underflow interrupt flag */ - if((u32Mask & QSPI_TXUF_INT_MASK) == QSPI_TXUF_INT_MASK) + if ((u32Mask & QSPI_TXUF_INT_MASK) == QSPI_TXUF_INT_MASK) { qspi->FIFOCTL |= QSPI_FIFOCTL_TXUFIEN_Msk; } /* Enable TX threshold interrupt flag */ - if((u32Mask & QSPI_FIFO_TXTH_INT_MASK) == QSPI_FIFO_TXTH_INT_MASK) + if ((u32Mask & QSPI_FIFO_TXTH_INT_MASK) == QSPI_FIFO_TXTH_INT_MASK) { qspi->FIFOCTL |= QSPI_FIFOCTL_TXTHIEN_Msk; } /* Enable RX threshold interrupt flag */ - if((u32Mask & QSPI_FIFO_RXTH_INT_MASK) == QSPI_FIFO_RXTH_INT_MASK) + if ((u32Mask & QSPI_FIFO_RXTH_INT_MASK) == QSPI_FIFO_RXTH_INT_MASK) { qspi->FIFOCTL |= QSPI_FIFOCTL_RXTHIEN_Msk; } /* Enable RX overrun interrupt flag */ - if((u32Mask & QSPI_FIFO_RXOV_INT_MASK) == QSPI_FIFO_RXOV_INT_MASK) + if ((u32Mask & QSPI_FIFO_RXOV_INT_MASK) == QSPI_FIFO_RXOV_INT_MASK) { qspi->FIFOCTL |= QSPI_FIFOCTL_RXOVIEN_Msk; } /* Enable RX time-out interrupt flag */ - if((u32Mask & QSPI_FIFO_RXTO_INT_MASK) == QSPI_FIFO_RXTO_INT_MASK) + if ((u32Mask & QSPI_FIFO_RXTO_INT_MASK) == QSPI_FIFO_RXTO_INT_MASK) { qspi->FIFOCTL |= QSPI_FIFOCTL_RXTOIEN_Msk; } @@ -546,61 +546,61 @@ void QSPI_EnableInt(QSPI_T *qspi, uint32_t u32Mask) void QSPI_DisableInt(QSPI_T *qspi, uint32_t u32Mask) { /* Disable unit transfer interrupt flag */ - if((u32Mask & QSPI_UNIT_INT_MASK) == QSPI_UNIT_INT_MASK) + if ((u32Mask & QSPI_UNIT_INT_MASK) == QSPI_UNIT_INT_MASK) { qspi->CTL &= ~QSPI_CTL_UNITIEN_Msk; } /* Disable slave selection signal active interrupt flag */ - if((u32Mask & QSPI_SSACT_INT_MASK) == QSPI_SSACT_INT_MASK) + if ((u32Mask & QSPI_SSACT_INT_MASK) == QSPI_SSACT_INT_MASK) { qspi->SSCTL &= ~QSPI_SSCTL_SSACTIEN_Msk; } /* Disable slave selection signal inactive interrupt flag */ - if((u32Mask & QSPI_SSINACT_INT_MASK) == QSPI_SSINACT_INT_MASK) + if ((u32Mask & QSPI_SSINACT_INT_MASK) == QSPI_SSINACT_INT_MASK) { qspi->SSCTL &= ~QSPI_SSCTL_SSINAIEN_Msk; } /* Disable slave TX under run interrupt flag */ - if((u32Mask & QSPI_SLVUR_INT_MASK) == QSPI_SLVUR_INT_MASK) + if ((u32Mask & QSPI_SLVUR_INT_MASK) == QSPI_SLVUR_INT_MASK) { qspi->SSCTL &= ~QSPI_SSCTL_SLVURIEN_Msk; } /* Disable slave bit count error interrupt flag */ - if((u32Mask & QSPI_SLVBE_INT_MASK) == QSPI_SLVBE_INT_MASK) + if ((u32Mask & QSPI_SLVBE_INT_MASK) == QSPI_SLVBE_INT_MASK) { qspi->SSCTL &= ~QSPI_SSCTL_SLVBEIEN_Msk; } /* Disable slave TX underflow interrupt flag */ - if((u32Mask & QSPI_TXUF_INT_MASK) == QSPI_TXUF_INT_MASK) + if ((u32Mask & QSPI_TXUF_INT_MASK) == QSPI_TXUF_INT_MASK) { qspi->FIFOCTL &= ~QSPI_FIFOCTL_TXUFIEN_Msk; } /* Disable TX threshold interrupt flag */ - if((u32Mask & QSPI_FIFO_TXTH_INT_MASK) == QSPI_FIFO_TXTH_INT_MASK) + if ((u32Mask & QSPI_FIFO_TXTH_INT_MASK) == QSPI_FIFO_TXTH_INT_MASK) { qspi->FIFOCTL &= ~QSPI_FIFOCTL_TXTHIEN_Msk; } /* Disable RX threshold interrupt flag */ - if((u32Mask & QSPI_FIFO_RXTH_INT_MASK) == QSPI_FIFO_RXTH_INT_MASK) + if ((u32Mask & QSPI_FIFO_RXTH_INT_MASK) == QSPI_FIFO_RXTH_INT_MASK) { qspi->FIFOCTL &= ~QSPI_FIFOCTL_RXTHIEN_Msk; } /* Disable RX overrun interrupt flag */ - if((u32Mask & QSPI_FIFO_RXOV_INT_MASK) == QSPI_FIFO_RXOV_INT_MASK) + if ((u32Mask & QSPI_FIFO_RXOV_INT_MASK) == QSPI_FIFO_RXOV_INT_MASK) { qspi->FIFOCTL &= ~QSPI_FIFOCTL_RXOVIEN_Msk; } /* Disable RX time-out interrupt flag */ - if((u32Mask & QSPI_FIFO_RXTO_INT_MASK) == QSPI_FIFO_RXTO_INT_MASK) + if ((u32Mask & QSPI_FIFO_RXTO_INT_MASK) == QSPI_FIFO_RXTO_INT_MASK) { qspi->FIFOCTL &= ~QSPI_FIFOCTL_RXTOIEN_Msk; } @@ -632,70 +632,70 @@ uint32_t QSPI_GetIntFlag(QSPI_T *qspi, uint32_t u32Mask) u32TmpVal = qspi->STATUS & QSPI_STATUS_UNITIF_Msk; /* Check unit transfer interrupt flag */ - if((u32Mask & QSPI_UNIT_INT_MASK) && (u32TmpVal)) + if ((u32Mask & QSPI_UNIT_INT_MASK) && (u32TmpVal)) { u32IntFlag |= QSPI_UNIT_INT_MASK; } u32TmpVal = qspi->STATUS & QSPI_STATUS_SSACTIF_Msk; /* Check slave selection signal active interrupt flag */ - if((u32Mask & QSPI_SSACT_INT_MASK) && (u32TmpVal)) + if ((u32Mask & QSPI_SSACT_INT_MASK) && (u32TmpVal)) { u32IntFlag |= QSPI_SSACT_INT_MASK; } u32TmpVal = qspi->STATUS & QSPI_STATUS_SSINAIF_Msk; /* Check slave selection signal inactive interrupt flag */ - if((u32Mask & QSPI_SSINACT_INT_MASK) && (u32TmpVal)) + if ((u32Mask & QSPI_SSINACT_INT_MASK) && (u32TmpVal)) { u32IntFlag |= QSPI_SSINACT_INT_MASK; } u32TmpVal = qspi->STATUS & QSPI_STATUS_SLVURIF_Msk; /* Check slave TX under run interrupt flag */ - if((u32Mask & QSPI_SLVUR_INT_MASK) && (u32TmpVal)) + if ((u32Mask & QSPI_SLVUR_INT_MASK) && (u32TmpVal)) { u32IntFlag |= QSPI_SLVUR_INT_MASK; } u32TmpVal = qspi->STATUS & QSPI_STATUS_SLVBEIF_Msk; /* Check slave bit count error interrupt flag */ - if((u32Mask & QSPI_SLVBE_INT_MASK) && (u32TmpVal)) + if ((u32Mask & QSPI_SLVBE_INT_MASK) && (u32TmpVal)) { u32IntFlag |= QSPI_SLVBE_INT_MASK; } u32TmpVal = qspi->STATUS & QSPI_STATUS_TXUFIF_Msk; /* Check slave TX underflow interrupt flag */ - if((u32Mask & QSPI_TXUF_INT_MASK) && (u32TmpVal)) + if ((u32Mask & QSPI_TXUF_INT_MASK) && (u32TmpVal)) { u32IntFlag |= QSPI_TXUF_INT_MASK; } u32TmpVal = qspi->STATUS & QSPI_STATUS_TXTHIF_Msk; /* Check TX threshold interrupt flag */ - if((u32Mask & QSPI_FIFO_TXTH_INT_MASK) && (u32TmpVal)) + if ((u32Mask & QSPI_FIFO_TXTH_INT_MASK) && (u32TmpVal)) { u32IntFlag |= QSPI_FIFO_TXTH_INT_MASK; } u32TmpVal = qspi->STATUS & QSPI_STATUS_RXTHIF_Msk; /* Check RX threshold interrupt flag */ - if((u32Mask & QSPI_FIFO_RXTH_INT_MASK) && (u32TmpVal)) + if ((u32Mask & QSPI_FIFO_RXTH_INT_MASK) && (u32TmpVal)) { u32IntFlag |= QSPI_FIFO_RXTH_INT_MASK; } u32TmpVal = qspi->STATUS & QSPI_STATUS_RXOVIF_Msk; /* Check RX overrun interrupt flag */ - if((u32Mask & QSPI_FIFO_RXOV_INT_MASK) && (u32TmpVal)) + if ((u32Mask & QSPI_FIFO_RXOV_INT_MASK) && (u32TmpVal)) { u32IntFlag |= QSPI_FIFO_RXOV_INT_MASK; } u32TmpVal = qspi->STATUS & QSPI_STATUS_RXTOIF_Msk; /* Check RX time-out interrupt flag */ - if((u32Mask & QSPI_FIFO_RXTO_INT_MASK) && (u32TmpVal)) + if ((u32Mask & QSPI_FIFO_RXTO_INT_MASK) && (u32TmpVal)) { u32IntFlag |= QSPI_FIFO_RXTO_INT_MASK; } @@ -723,42 +723,42 @@ uint32_t QSPI_GetIntFlag(QSPI_T *qspi, uint32_t u32Mask) */ void QSPI_ClearIntFlag(QSPI_T *qspi, uint32_t u32Mask) { - if(u32Mask & QSPI_UNIT_INT_MASK) + if (u32Mask & QSPI_UNIT_INT_MASK) { qspi->STATUS = QSPI_STATUS_UNITIF_Msk; /* Clear unit transfer interrupt flag */ } - if(u32Mask & QSPI_SSACT_INT_MASK) + if (u32Mask & QSPI_SSACT_INT_MASK) { qspi->STATUS = QSPI_STATUS_SSACTIF_Msk; /* Clear slave selection signal active interrupt flag */ } - if(u32Mask & QSPI_SSINACT_INT_MASK) + if (u32Mask & QSPI_SSINACT_INT_MASK) { qspi->STATUS = QSPI_STATUS_SSINAIF_Msk; /* Clear slave selection signal inactive interrupt flag */ } - if(u32Mask & QSPI_SLVUR_INT_MASK) + if (u32Mask & QSPI_SLVUR_INT_MASK) { qspi->STATUS = QSPI_STATUS_SLVURIF_Msk; /* Clear slave TX under run interrupt flag */ } - if(u32Mask & QSPI_SLVBE_INT_MASK) + if (u32Mask & QSPI_SLVBE_INT_MASK) { qspi->STATUS = QSPI_STATUS_SLVBEIF_Msk; /* Clear slave bit count error interrupt flag */ } - if(u32Mask & QSPI_TXUF_INT_MASK) + if (u32Mask & QSPI_TXUF_INT_MASK) { qspi->STATUS = QSPI_STATUS_TXUFIF_Msk; /* Clear slave TX underflow interrupt flag */ } - if(u32Mask & QSPI_FIFO_RXOV_INT_MASK) + if (u32Mask & QSPI_FIFO_RXOV_INT_MASK) { qspi->STATUS = QSPI_STATUS_RXOVIF_Msk; /* Clear RX overrun interrupt flag */ } - if(u32Mask & QSPI_FIFO_RXTO_INT_MASK) + if (u32Mask & QSPI_FIFO_RXTO_INT_MASK) { qspi->STATUS = QSPI_STATUS_RXTOIF_Msk; /* Clear RX time-out interrupt flag */ } @@ -788,56 +788,56 @@ uint32_t QSPI_GetStatus(QSPI_T *qspi, uint32_t u32Mask) u32TmpValue = qspi->STATUS & QSPI_STATUS_BUSY_Msk; /* Check busy status */ - if((u32Mask & QSPI_BUSY_MASK) && (u32TmpValue)) + if ((u32Mask & QSPI_BUSY_MASK) && (u32TmpValue)) { u32Flag |= QSPI_BUSY_MASK; } u32TmpValue = qspi->STATUS & QSPI_STATUS_RXEMPTY_Msk; /* Check RX empty flag */ - if((u32Mask & QSPI_RX_EMPTY_MASK) && (u32TmpValue)) + if ((u32Mask & QSPI_RX_EMPTY_MASK) && (u32TmpValue)) { u32Flag |= QSPI_RX_EMPTY_MASK; } u32TmpValue = qspi->STATUS & QSPI_STATUS_RXFULL_Msk; /* Check RX full flag */ - if((u32Mask & QSPI_RX_FULL_MASK) && (u32TmpValue)) + if ((u32Mask & QSPI_RX_FULL_MASK) && (u32TmpValue)) { u32Flag |= QSPI_RX_FULL_MASK; } u32TmpValue = qspi->STATUS & QSPI_STATUS_TXEMPTY_Msk; /* Check TX empty flag */ - if((u32Mask & QSPI_TX_EMPTY_MASK) && (u32TmpValue)) + if ((u32Mask & QSPI_TX_EMPTY_MASK) && (u32TmpValue)) { u32Flag |= QSPI_TX_EMPTY_MASK; } u32TmpValue = qspi->STATUS & QSPI_STATUS_TXFULL_Msk; /* Check TX full flag */ - if((u32Mask & QSPI_TX_FULL_MASK) && (u32TmpValue)) + if ((u32Mask & QSPI_TX_FULL_MASK) && (u32TmpValue)) { u32Flag |= QSPI_TX_FULL_MASK; } u32TmpValue = qspi->STATUS & QSPI_STATUS_TXRXRST_Msk; /* Check TX/RX reset flag */ - if((u32Mask & QSPI_TXRX_RESET_MASK) && (u32TmpValue)) + if ((u32Mask & QSPI_TXRX_RESET_MASK) && (u32TmpValue)) { u32Flag |= QSPI_TXRX_RESET_MASK; } u32TmpValue = qspi->STATUS & QSPI_STATUS_QSPIENSTS_Msk; /* Check QSPIEN flag */ - if((u32Mask & QSPI_QSPIEN_STS_MASK) && (u32TmpValue)) + if ((u32Mask & QSPI_QSPIEN_STS_MASK) && (u32TmpValue)) { u32Flag |= QSPI_QSPIEN_STS_MASK; } u32TmpValue = qspi->STATUS & QSPI_STATUS_SSLINE_Msk; /* Check QSPIx_SS line status */ - if((u32Mask & QSPI_SSLINE_STS_MASK) && (u32TmpValue)) + if ((u32Mask & QSPI_SSLINE_STS_MASK) && (u32TmpValue)) { u32Flag |= QSPI_SSLINE_STS_MASK; } diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c index dfea26708c..3eb2a19356 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c @@ -100,7 +100,7 @@ rt_err_t nu_crc_init(void) SYS_ResetModule(CRC_RST); - result = rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_FIFO); + result = rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); return RT_EOK; diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_crypto.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_crypto.c index 0c30ec520a..eda0392c53 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_crypto.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_crypto.c @@ -91,18 +91,18 @@ static rt_err_t nu_crypto_init(void) SHA_ENABLE_INT(CRPT); //init cipher mutex - result = rt_mutex_init(&s_AES_mutex, NU_HWCRYPTO_AES_NAME, RT_IPC_FLAG_FIFO); + result = rt_mutex_init(&s_AES_mutex, NU_HWCRYPTO_AES_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); - result = rt_mutex_init(&s_TDES_mutex, NU_HWCRYPTO_TDES_NAME, RT_IPC_FLAG_FIFO); + result = rt_mutex_init(&s_TDES_mutex, NU_HWCRYPTO_TDES_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); - result = rt_mutex_init(&s_SHA_mutex, NU_HWCRYPTO_SHA_NAME, RT_IPC_FLAG_FIFO); + result = rt_mutex_init(&s_SHA_mutex, NU_HWCRYPTO_SHA_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); #if !defined(BSP_USING_TRNG) PRNG_ENABLE_INT(CRPT); - result = rt_mutex_init(&s_PRNG_mutex, NU_HWCRYPTO_PRNG_NAME, RT_IPC_FLAG_FIFO); + result = rt_mutex_init(&s_PRNG_mutex, NU_HWCRYPTO_PRNG_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); #endif diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_fmc.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_fmc.c index 2ec2bef071..07cc212ede 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_fmc.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_fmc.c @@ -331,7 +331,7 @@ static int nu_fmc_init(void) FMC_ENABLE_ISP(); SYS_LockReg(); - g_mutex_fmc = rt_mutex_create("nu_fmc_lock", RT_IPC_FLAG_FIFO); + g_mutex_fmc = rt_mutex_create("nu_fmc_lock", RT_IPC_FLAG_PRIO); RT_ASSERT(g_mutex_fmc != RT_NULL); /* PKG_USING_FAL */ diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.c index dc7a67970f..06c199c234 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_pdma.c @@ -208,10 +208,10 @@ static void nu_pdma_init(void) if (nu_pdma_inited) return; - g_mutex_res = rt_mutex_create("pdmalock", RT_IPC_FLAG_FIFO); + g_mutex_res = rt_mutex_create("pdmalock", RT_IPC_FLAG_PRIO); RT_ASSERT(g_mutex_res != RT_NULL); - g_mutex_sg = rt_mutex_create("sgtbles", RT_IPC_FLAG_FIFO); + g_mutex_sg = rt_mutex_create("sgtbles", RT_IPC_FLAG_PRIO); RT_ASSERT(g_mutex_sg != RT_NULL); nu_pdma_chn_mask = ~NU_PDMA_CH_Msk; @@ -894,7 +894,7 @@ static void nu_pdma_memfun_actor_init(void) nu_pdma_memfun_actor_pool_sem = rt_sem_create("mempool_sem", nu_pdma_memfun_actor_maxnum, RT_IPC_FLAG_FIFO); RT_ASSERT(nu_pdma_memfun_actor_pool_sem != RT_NULL); - nu_pdma_memfun_actor_pool_lock = rt_mutex_create("mempool_lock", RT_IPC_FLAG_FIFO); + nu_pdma_memfun_actor_pool_lock = rt_mutex_create("mempool_lock", RT_IPC_FLAG_PRIO); RT_ASSERT(nu_pdma_memfun_actor_pool_lock != RT_NULL); } } diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_qspi.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_qspi.c index 69e384479a..b22aeefd20 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_qspi.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_qspi.c @@ -180,10 +180,10 @@ exit_nu_qspi_bus_configure: return -(ret); } -#if defined(RT_SFUD_USING_QSPI) static int nu_qspi_mode_config(struct nu_spi *qspi_bus, rt_uint8_t *tx, rt_uint8_t *rx, int qspi_lines) { QSPI_T *qspi_base = (QSPI_T *)qspi_bus->spi_base; +#if defined(RT_SFUD_USING_QSPI) if (qspi_lines > 1) { if (tx) @@ -218,13 +218,13 @@ static int nu_qspi_mode_config(struct nu_spi *qspi_bus, rt_uint8_t *tx, rt_uint8 } } else +#endif { QSPI_DISABLE_DUAL_MODE(qspi_base); QSPI_DISABLE_QUAD_MODE(qspi_base); } return qspi_lines; } -#endif static rt_uint32_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message) { @@ -317,9 +317,11 @@ static rt_uint32_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_ qspi_message->dummy_cycles / (8 / u8last), 1); } - /* Data stage */ nu_qspi_mode_config(qspi_bus, (rt_uint8_t *) message->send_buf, (rt_uint8_t *) message->recv_buf, qspi_message->qspi_data_lines); +#else + /* Data stage */ + nu_qspi_mode_config(qspi_bus, RT_NULL, RT_NULL, 1); #endif //#if defined(RT_SFUD_USING_QSPI) if (message->length != 0) @@ -369,8 +371,7 @@ static int rt_hw_qspi_init(void) #if defined(BSP_USING_SPI_PDMA) nu_qspi_arr[i].pdma_chanid_tx = -1; nu_qspi_arr[i].pdma_chanid_rx = -1; -#endif -#if defined(BSP_USING_QSPI_PDMA) + if ((nu_qspi_arr[i].pdma_perp_tx != NU_PDMA_UNUSED) && (nu_qspi_arr[i].pdma_perp_rx != NU_PDMA_UNUSED)) { if (nu_hw_spi_pdma_allocate(&nu_qspi_arr[i]) != RT_EOK) diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.c index 8bba65221c..dfffc0ebb3 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.c @@ -50,7 +50,7 @@ rt_err_t nu_trng_init(void) { rt_err_t result; - result = rt_mutex_init(&s_TRNG_mutex, NU_CRYPTO_TRNG_NAME, RT_IPC_FLAG_FIFO); + result = rt_mutex_init(&s_TRNG_mutex, NU_CRYPTO_TRNG_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0) diff --git a/bsp/nuvoton/libraries/nu_packages/AudioCodec/audio_test.c b/bsp/nuvoton/libraries/nu_packages/AudioCodec/audio_test.c index b36db998a8..d978fa4ded 100644 --- a/bsp/nuvoton/libraries/nu_packages/AudioCodec/audio_test.c +++ b/bsp/nuvoton/libraries/nu_packages/AudioCodec/audio_test.c @@ -83,4 +83,46 @@ static int audio_test(int argc, char **argv) #ifdef FINSH_USING_MSH MSH_CMD_EXPORT(audio_test, Audio record / replay); #endif + + +static int audio_overnight(int argc, char **argv) +{ +#define DEF_MAX_TEST_SECOND 5 + + struct wavrecord_info info; + char strbuf[128]; + struct stat stat_buf; + + snprintf(strbuf, sizeof(strbuf), "/test.wav"); + while (1) + { + rt_kprintf("Recording file at %s\n", strbuf); + info.uri = strbuf; + info.samplerate = 16000; + info.samplebits = 16; + info.channels = 2; + wavrecorder_start(&info); + rt_thread_mdelay(DEF_MAX_TEST_SECOND * 1000); + wavrecorder_stop(); + rt_thread_mdelay(1000); + + if (stat((const char *)strbuf, &stat_buf) < 0) + { + rt_kprintf("%s non-exist.\n", strbuf); + break; + } + + rt_kprintf("Replay file at %s\n", strbuf); + wavplayer_play(strbuf); + rt_thread_mdelay(DEF_MAX_TEST_SECOND * 1000); + wavplayer_stop(); + rt_thread_mdelay(1000); + } + return 0; +} + +#ifdef FINSH_USING_MSH + MSH_CMD_EXPORT(audio_overnight, auto test record / replay); +#endif + #endif /* PKG_USING_WAVPLAYER */ diff --git a/bsp/nuvoton/libraries/nu_packages/SPINAND/drv_spinand.c b/bsp/nuvoton/libraries/nu_packages/SPINAND/drv_spinand.c index 88e4ac80bc..c8daa5d9b7 100644 --- a/bsp/nuvoton/libraries/nu_packages/SPINAND/drv_spinand.c +++ b/bsp/nuvoton/libraries/nu_packages/SPINAND/drv_spinand.c @@ -494,7 +494,7 @@ rt_err_t rt_hw_mtd_spinand_init(void) if (u32IsInited) return RT_EOK; - result = rt_mutex_init(SPINAND_FLASH_LOCK, "spinand", RT_IPC_FLAG_FIFO); + result = rt_mutex_init(SPINAND_FLASH_LOCK, "spinand", RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); result = spinand_flash_init(SPINAND_FLASH_QSPI); diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c index a9d44e3938..b9564346f8 100644 --- a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c @@ -2170,6 +2170,8 @@ static uint32_t mpShortDiv(uint32_t q[], const uint32_t u[], uint32_t v, bitmask >>= 1; } + if (shift == BITS_PER_DIGIT) return 0; /* Avoid cppcheck false-alarm. */ + v <<= shift; overflow = mpShiftLeft(q, u, shift, ndigits); uu = q; diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_emac.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_emac.c index 92f5afc2a8..703c686311 100644 --- a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_emac.c +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_emac.c @@ -191,7 +191,7 @@ void EMAC_PhyInit(EMAC_T *EMAC) while (!(EMAC_MdioRead(EMAC, PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID)) { - if (i++ > 2000000UL) /* Cable not connected */ + if (i++ > 10000UL) /* Cable not connected */ { EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk; EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk; @@ -199,7 +199,7 @@ void EMAC_PhyInit(EMAC_T *EMAC) } } - if (i <= 2000000UL) + if (i <= 10000UL) { /* Configure auto negotiation capability */ EMAC_MdioWrite(EMAC, PHY_ANA_REG, EMAC_PHY_ADDR, PHY_ANA_DR100_TX_FULL | diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_crypto.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_crypto.c index 3b2963640d..4a31151c29 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_crypto.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_crypto.c @@ -750,19 +750,19 @@ int nu_hwcrypto_device_init(void) /* init cipher mutex */ #if defined(RT_HWCRYPTO_USING_AES) - result = rt_mutex_init(&s_AES_mutex, NU_HWCRYPTO_AES_NAME, RT_IPC_FLAG_FIFO); + result = rt_mutex_init(&s_AES_mutex, NU_HWCRYPTO_AES_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); AES_ENABLE_INT(CRPT); #endif #if defined(RT_HWCRYPTO_USING_SHA1) || defined(RT_HWCRYPTO_USING_SHA2) - result = rt_mutex_init(&s_SHA_mutex, NU_HWCRYPTO_SHA_NAME, RT_IPC_FLAG_FIFO); + result = rt_mutex_init(&s_SHA_mutex, NU_HWCRYPTO_SHA_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); SHA_ENABLE_INT(CRPT); #endif #if defined(RT_HWCRYPTO_USING_RNG) - result = rt_mutex_init(&s_PRNG_mutex, NU_HWCRYPTO_PRNG_NAME, RT_IPC_FLAG_FIFO); + result = rt_mutex_init(&s_PRNG_mutex, NU_HWCRYPTO_PRNG_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); #endif diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_pdma.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_pdma.c index 979d2b1f01..63998bf647 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_pdma.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_pdma.c @@ -972,7 +972,7 @@ static void nu_pdma_memfun_actor_init(void) nu_pdma_memfun_actor_pool_sem = rt_sem_create("mempool_sem", nu_pdma_memfun_actor_maxnum, RT_IPC_FLAG_FIFO); RT_ASSERT(nu_pdma_memfun_actor_pool_sem != RT_NULL); - nu_pdma_memfun_actor_pool_lock = rt_mutex_create("mempool_lock", RT_IPC_FLAG_FIFO); + nu_pdma_memfun_actor_pool_lock = rt_mutex_create("mempool_lock", RT_IPC_FLAG_PRIO); RT_ASSERT(nu_pdma_memfun_actor_pool_lock != RT_NULL); } } diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_rtc.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_rtc.c index e3866e7d22..d11195c8c9 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_rtc.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_rtc.c @@ -263,6 +263,8 @@ static rt_err_t nu_rtc_control(rt_device_t dev, int cmd, void *args) case RT_DEVICE_CTRL_RTC_SET_ALARM: + RTC_GetDateAndTime(&hw_alarm); + wkalarm = (struct rt_rtc_wkalarm *) args; hw_alarm.u32Hour = wkalarm->tm_hour; hw_alarm.u32Minute = wkalarm->tm_min; diff --git a/bsp/nuvoton/nk-980iot/.config b/bsp/nuvoton/nk-980iot/.config index a69c66a0ba..9db9075ec2 100644 --- a/bsp/nuvoton/nk-980iot/.config +++ b/bsp/nuvoton/nk-980iot/.config @@ -138,13 +138,6 @@ CONFIG_RT_DFS_ELM_REENTRANT=y CONFIG_RT_USING_DFS_DEVFS=y # CONFIG_RT_USING_DFS_ROMFS is not set # CONFIG_RT_USING_DFS_RAMFS is not set -CONFIG_RT_USING_DFS_UFFS=y -# CONFIG_RT_UFFS_ECC_MODE_0 is not set -# CONFIG_RT_UFFS_ECC_MODE_1 is not set -# CONFIG_RT_UFFS_ECC_MODE_2 is not set -CONFIG_RT_UFFS_ECC_MODE_3=y -CONFIG_RT_UFFS_ECC_MODE=3 -# CONFIG_RT_USING_DFS_JFFS2 is not set # CONFIG_RT_USING_DFS_NFS is not set # @@ -229,6 +222,7 @@ CONFIG_RT_HWCRYPTO_USING_RNG=y CONFIG_RT_USING_USB_HOST=y CONFIG_RT_USBH_MSTORAGE=y CONFIG_UDISK_MOUNTPOINT="/mnt/udisk" +# CONFIG_RT_USBH_HID is not set CONFIG_RT_USING_USB_DEVICE=y CONFIG_RT_USBD_THREAD_STACK_SZ=4096 CONFIG_USB_VENDOR_ID=0x0FFE @@ -453,8 +447,6 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_LIBRWS is not set # CONFIG_PKG_USING_TCPSERVER is not set # CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set # CONFIG_PKG_USING_DLT645 is not set # CONFIG_PKG_USING_QXWZ is not set # CONFIG_PKG_USING_SMTP_CLIENT is not set @@ -468,6 +460,13 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # 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 @@ -507,6 +506,8 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # 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 @@ -520,6 +521,16 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # 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 # # system packages @@ -528,7 +539,6 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set -# CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set # CONFIG_PKG_USING_FLASHDB is not set @@ -538,6 +548,18 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # 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=y +CONFIG_PKG_UFFS_PATH="/packages/system/uffs" +CONFIG_RT_USING_DFS_UFFS=y +# CONFIG_RT_UFFS_ECC_MODE_0 is not set +# CONFIG_RT_UFFS_ECC_MODE_1 is not set +# CONFIG_RT_UFFS_ECC_MODE_2 is not set +CONFIG_RT_UFFS_ECC_MODE_3=y +CONFIG_RT_UFFS_ECC_MODE=3 +CONFIG_PKG_USING_DFS_UFFS_LATEST_VERSION=y +CONFIG_PKG_UFFS_VER="latest" +# 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 @@ -562,6 +584,14 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_UC_COMMON is not set # CONFIG_PKG_USING_UC_MODBUS 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_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 +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set # # peripheral libraries and drivers @@ -570,6 +600,7 @@ CONFIG_PKG_RAMDISK_VER="latest" # 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 @@ -619,6 +650,28 @@ CONFIG_PKG_RAMDISK_VER="latest" # 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 + +# +# 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 @@ -626,9 +679,8 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_LIBCSV is not set CONFIG_PKG_USING_OPTPARSE=y CONFIG_PKG_OPTPARSE_PATH="/packages/misc/optparse" -CONFIG_PKG_USING_OPTPARSE_V100=y -# CONFIG_PKG_USING_OPTPARSE_LATEST_VERSION is not set -CONFIG_PKG_OPTPARSE_VER="v1.0.0" +CONFIG_PKG_USING_OPTPARSE_LATEST_VERSION=y +CONFIG_PKG_OPTPARSE_VER="latest" # CONFIG_OPTPARSE_USING_DEMO is not set # CONFIG_PKG_USING_FASTLZ is not set # CONFIG_PKG_USING_MINILZO is not set @@ -671,24 +723,24 @@ CONFIG_VI_UNDO_QUEUE_MAX=256 CONFIG_PKG_USING_VI_LATEST_VERSION=y CONFIG_PKG_VI_VER="latest" # CONFIG_PKG_USING_KI is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_ELAPACK is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set # CONFIG_PKG_USING_VT100 is not set -# CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set # -# games: games run on RT-Thread console +# 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_TENSORFLOWLITEMICRO 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 # # Nuvoton Packages Config @@ -715,7 +767,6 @@ CONFIG_BSP_USING_MMU=y CONFIG_BSP_USING_PDMA=y CONFIG_NU_PDMA_MEMFUN_ACTOR_MAX=2 CONFIG_BSP_USING_GPIO=y -# CONFIG_BSP_USING_CLK is not set CONFIG_BSP_USING_EMAC=y CONFIG_BSP_USING_EMAC0=y # CONFIG_BSP_USING_EMAC1 is not set @@ -781,6 +832,7 @@ CONFIG_BSP_USING_SPI1_NONE=y CONFIG_BSP_USING_I2S=y CONFIG_NU_I2S_DMA_FIFO_SIZE=4096 CONFIG_BSP_USING_QSPI=y +CONFIG_BSP_USING_QSPI_PDMA=y CONFIG_BSP_USING_QSPI0=y CONFIG_BSP_USING_QSPI0_PDMA=y # CONFIG_BSP_USING_SCUART is not set diff --git a/bsp/nuvoton/nk-980iot/linking_scripts/nuc980.ld b/bsp/nuvoton/nk-980iot/linking_scripts/nuc980.ld index 1004f039fb..bdecf1da02 100644 --- a/bsp/nuvoton/nk-980iot/linking_scripts/nuc980.ld +++ b/bsp/nuvoton/nk-980iot/linking_scripts/nuc980.ld @@ -23,18 +23,14 @@ SECTIONS __fsymtab_start = .; KEEP(*(FSymTab)) __fsymtab_end = .; + . = ALIGN(4); + . = ALIGN(4); __vsymtab_start = .; KEEP(*(VSymTab)) __vsymtab_end = .; . = ALIGN(4); - . = ALIGN(4); - __rt_init_start = .; - KEEP(*(SORT(.rti_fn*))) - __rt_init_end = .; - . = ALIGN(4); - /* section information for modules */ . = ALIGN(4); __rtmsymtab_start = .; @@ -54,6 +50,7 @@ SECTIONS __rt_utest_tc_tab_start = .; KEEP(*(UtestTcTab)) __rt_utest_tc_tab_end = .; + . = ALIGN(4); } . = ALIGN(4); diff --git a/bsp/nuvoton/nk-n9h30/.config b/bsp/nuvoton/nk-n9h30/.config new file mode 100644 index 0000000000..cb100b55e1 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/.config @@ -0,0 +1,894 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=16 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=1000 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=2048 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# 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=y + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +CONFIG_RT_USING_MEMHEAP=y +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_USERHEAP is not set +CONFIG_RT_USING_MEMTRACE=y +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +CONFIG_RT_USING_INTERRUPT_INFO=y +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=256 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" +CONFIG_RT_VER_NUM=0x40003 +CONFIG_ARCH_ARM=y +# CONFIG_RT_USING_CPU_FFS is not set +CONFIG_ARCH_ARM_ARM9=y +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_CMD_SIZE=80 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +# CONFIG_FINSH_USING_MSH_ONLY 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=16 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=16 +CONFIG_DFS_FD_MAX=64 +CONFIG_RT_USING_DFS_MNTTABLE=y +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=8 +CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=4096 +# 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=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +# CONFIG_RT_SERIAL_USING_DMA is not set +CONFIG_RT_SERIAL_RB_BUFSZ=2048 +CONFIG_RT_USING_CAN=y +# CONFIG_RT_CAN_USING_HDR is not set +CONFIG_RT_USING_HWTIMER=y +# CONFIG_RT_USING_CPUTIME is not set +CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set +CONFIG_RT_USING_I2C_BITOPS=y +# CONFIG_RT_I2C_BITOPS_DEBUG is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +CONFIG_RT_USING_ADC=y +# CONFIG_RT_USING_DAC is not set +CONFIG_RT_USING_PWM=y +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +CONFIG_RT_USING_RTC=y +CONFIG_RT_USING_ALARM=y +# CONFIG_RT_USING_SOFT_RTC is not set +# CONFIG_RT_USING_SDIO 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=y +CONFIG_RT_USING_AUDIO=y +CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_SIZE=4096 +CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_COUNT=2 +CONFIG_RT_AUDIO_RECORD_PIPE_SIZE=2048 +# CONFIG_RT_USING_SENSOR is not set +CONFIG_RT_USING_TOUCH=y +# CONFIG_RT_TOUCH_PIN_IRQ is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +CONFIG_RT_USING_INPUT_CAPTURE=y +CONFIG_RT_INPUT_CAPTURE_RB_SIZE=100 +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +CONFIG_RT_USING_USB_HOST=y +CONFIG_RT_USBH_MSTORAGE=y +CONFIG_UDISK_MOUNTPOINT="/mnt/udisk" +# CONFIG_RT_USBH_HID is not set +CONFIG_RT_USING_USB_DEVICE=y +CONFIG_RT_USBD_THREAD_STACK_SZ=4096 +CONFIG_USB_VENDOR_ID=0x0FFE +CONFIG_USB_PRODUCT_ID=0x0001 +CONFIG_RT_USB_DEVICE_COMPOSITE=y +CONFIG_RT_USB_DEVICE_CDC=y +CONFIG_RT_USB_DEVICE_NONE=y +CONFIG_RT_USB_DEVICE_MSTORAGE=y +# CONFIG_RT_USB_DEVICE_HID is not set +# CONFIG_RT_USB_DEVICE_RNDIS is not set +# CONFIG_RT_USB_DEVICE_ECM is not set +# CONFIG_RT_USB_DEVICE_WINUSB is not set +# CONFIG_RT_USB_DEVICE_AUDIO is not set +CONFIG_RT_VCOM_TASK_STK_SIZE=512 +CONFIG_RT_CDC_RX_BUFSIZE=128 +# CONFIG_RT_VCOM_TX_USE_DMA is not set +CONFIG_RT_VCOM_SERNO="32021919830108" +CONFIG_RT_VCOM_SER_LEN=14 +CONFIG_RT_VCOM_TX_TIMEOUT=1000 +CONFIG_RT_USB_MSTORAGE_DISK_NAME="ramdisk1" + +# +# 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=y +CONFIG_SAL_INTERNET_CHECK=y + +# +# protocol stack implement +# +CONFIG_SAL_USING_LWIP=y +CONFIG_SAL_USING_POSIX=y + +# +# 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=y +# CONFIG_RT_USING_LWIP212 is not set +# 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=y +CONFIG_IP_SOF_BROADCAST=1 +CONFIG_IP_SOF_BROADCAST_RECV=1 + +# +# Static IPv4 Address +# +CONFIG_RT_LWIP_IPADDR="192.168.1.30" +CONFIG_RT_LWIP_GWADDR="192.168.1.1" +CONFIG_RT_LWIP_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=32 +CONFIG_RT_LWIP_PBUF_NUM=256 +CONFIG_RT_LWIP_RAW_PCB_NUM=32 +CONFIG_RT_LWIP_UDP_PCB_NUM=32 +CONFIG_RT_LWIP_TCP_PCB_NUM=32 +CONFIG_RT_LWIP_TCP_SEG_NUM=256 +CONFIG_RT_LWIP_TCP_SND_BUF=32768 +CONFIG_RT_LWIP_TCP_WND=10240 +CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10 +CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=32 +CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=4096 +# 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=32 +# 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=y +CONFIG_LWIP_NETIF_LOOPBACK=1 +CONFIG_RT_LWIP_STATS=y +# 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 is not set +CONFIG_RT_USING_UTEST=y +CONFIG_UTEST_THR_STACK_SIZE=4096 +CONFIG_UTEST_THR_PRIORITY=20 +# CONFIG_RT_USING_LWP 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=y +CONFIG_PKG_WAVPLAYER_PATH="/packages/multimedia/wavplayer" +CONFIG_PKG_WP_USING_PLAY=y +CONFIG_PKG_WP_PLAY_DEVICE="sound0" +CONFIG_PKG_WP_USING_RECORD=y +CONFIG_PKG_WP_RECORD_DEVICE="sound0" +# CONFIG_PKG_USING_WAVPLAYER_V020 is not set +CONFIG_PKG_USING_WAVPLAYER_LATEST_VERSION=y +CONFIG_PKG_WAVPLAYER_VER="latest" +# 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=y +CONFIG_PKG_NUEMWIN_PATH="/packages/multimedia/NUemWin" +CONFIG_PKG_NUEMWIN_MEM_SIZE=4 +CONFIG_PKG_USING_NUEMWIN_EXAMPLE=y +CONFIG_PKG_USING_NUEMWIN_GUIDEMO=y +# CONFIG_PKG_USING_NUEMWIN_SIMPLEDEMO is not set +CONFIG_PKG_USING_NUEMWIN_LATEST_VERSION=y +CONFIG_PKG_NUEMWIN_VER="latest" +CONFIG_PKG_NUEMWIN_VER_NUM=0x99999 + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_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=y +CONFIG_PKG_MEM_SANDBOX_PATH="/packages/tools/mem_sandbox" +CONFIG_PKG_USING_MEM_SANDBOX_LATEST_VERSION=y +CONFIG_PKG_MEM_SANDBOX_VER="latest" +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set + +# +# system packages +# +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_PERSIMMON is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +CONFIG_PKG_USING_FAL=y +CONFIG_PKG_FAL_PATH="/packages/system/fal" +CONFIG_FAL_DEBUG_CONFIG=y +CONFIG_FAL_DEBUG=1 +CONFIG_FAL_PART_HAS_TABLE_CFG=y +CONFIG_FAL_USING_SFUD_PORT=y +CONFIG_FAL_USING_NOR_FLASH_DEV_NAME="norflash0" +# CONFIG_PKG_USING_FAL_V00500 is not set +# CONFIG_PKG_USING_FAL_V00400 is not set +# CONFIG_PKG_USING_FAL_V00300 is not set +# CONFIG_PKG_USING_FAL_V00200 is not set +# CONFIG_PKG_USING_FAL_V00100 is not set +CONFIG_PKG_USING_FAL_LATEST_VERSION=y +CONFIG_PKG_FAL_VER="latest" +CONFIG_PKG_FAL_VER_NUM=0x99999 +# 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=y +CONFIG_PKG_LITTLEVGL2RTT_PATH="/packages/system/LittlevGL2RTT" +CONFIG_PKG_USING_LITTLEVGL2RTT_V001=y +# CONFIG_PKG_USING_LITTLEVGL2RTT_LATEST_VERSION is not set +CONFIG_PKG_LITTLEVGL2RTT_VER="v0.0.1" + +# +# LittlevGL2RTT Options +# +# CONFIG_LV_MEM_STATIC is not set +CONFIG_LV_MEM_DYNAMIC=y +CONFIG_LV_MEM_CUSTOM=1 +# CONFIG_LV_COLOR_DEPTH_1 is not set +# CONFIG_LV_COLOR_DEPTH_8 is not set +# CONFIG_LV_COLOR_DEPTH_16 is not set +# CONFIG_LV_COLOR_DEPTH_24 is not set +CONFIG_LV_COLOR_DEPTH_32=y +CONFIG_LV_COLOR_DEPTH=32 +CONFIG_LV_HOR_RES=800 +CONFIG_LV_VER_RES=480 +CONFIG_LV_DPI=50 +CONFIG_LV_GC_DISABLE=y +# CONFIG_LV_GC_ENABLE is not set +CONFIG_LV_ENABLE_GC=0 +CONFIG_LITTLEVGL2RTT_USING_DEMO=y +# 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=y +CONFIG_PKG_RAMDISK_PATH="/packages/system/ramdisk" +# CONFIG_PKG_USING_RAMDISK_V010 is not set +CONFIG_PKG_USING_RAMDISK_LATEST_VERSION=y +CONFIG_PKG_RAMDISK_VER="latest" +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_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_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# 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 +# 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=y +CONFIG_PKG_OPTPARSE_PATH="/packages/misc/optparse" +CONFIG_PKG_USING_OPTPARSE_LATEST_VERSION=y +CONFIG_PKG_OPTPARSE_VER="latest" +# CONFIG_OPTPARSE_USING_DEMO 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_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=y +CONFIG_PKG_VI_PATH="/packages/misc/vi" +CONFIG_VI_SANDBOX_SIZE_KB=20 +CONFIG_VI_MAX_LEN=4096 +# CONFIG_VI_ENABLE_8BIT is not set +CONFIG_VI_ENABLE_COLON=y +CONFIG_VI_ENABLE_COLON_EXPAND=y +CONFIG_VI_ENABLE_YANKMARK=y +CONFIG_VI_ENABLE_SEARCH=y +CONFIG_VI_ENABLE_DOT_CMD=y +CONFIG_VI_ENABLE_READONLY=y +CONFIG_VI_ENABLE_SETOPTS=y +CONFIG_VI_ENABLE_SET=y +# CONFIG_VI_ENABLE_WIN_RESIZE is not set +CONFIG_VI_ENABLE_VI_ASK_TERMINAL=y +CONFIG_VI_ENABLE_UNDO=y +CONFIG_VI_ENABLE_UNDO_QUEUE=y +CONFIG_VI_UNDO_QUEUE_MAX=256 +CONFIG_VI_ENABLE_VERBOSE_STATUS=y +CONFIG_PKG_USING_VI_LATEST_VERSION=y +CONFIG_PKG_VI_VER="latest" +# 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 + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +# CONFIG_NU_PKG_USING_DEMO is not set +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +# CONFIG_NU_PKG_USING_NAU88L25 is not set +CONFIG_NU_PKG_USING_NAU8822=y +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set + +# +# Hardware Drivers Config +# + +# +# On-chip Peripheral Drivers +# +CONFIG_SOC_SERIES_N9H30=y +# CONFIG_BSP_USE_STDDRIVER_SOURCE is not set +CONFIG_BSP_USING_MMU=y +CONFIG_BSP_USING_GPIO=y +# CONFIG_BSP_USING_CLK is not set +CONFIG_BSP_USING_EMAC=y +CONFIG_BSP_USING_EMAC0=y +CONFIG_BSP_USING_EMAC1=y +CONFIG_BSP_USING_RTC=y +# CONFIG_NU_RTC_SUPPORT_IO_RW is not set +# CONFIG_NU_RTC_SUPPORT_MSH_CMD is not set +CONFIG_BSP_USING_ADC=y +CONFIG_BSP_USING_ADC_TOUCH=y +CONFIG_BSP_USING_ETMR=y +CONFIG_BSP_USING_ETIMER=y +CONFIG_BSP_USING_ETIMER_CAPTURE=y +CONFIG_BSP_USING_ETMR0=y +CONFIG_BSP_USING_ETIMER0=y +# CONFIG_BSP_USING_ETIMER0_CAPTURE is not set +CONFIG_BSP_USING_ETMR1=y +CONFIG_BSP_USING_ETIMER1=y +# CONFIG_BSP_USING_ETIMER1_CAPTURE is not set +CONFIG_BSP_USING_ETMR2=y +# CONFIG_BSP_USING_ETIMER2 is not set +CONFIG_BSP_USING_ETIMER2_CAPTURE=y +CONFIG_BSP_USING_ETMR3=y +# CONFIG_BSP_USING_ETIMER3 is not set +CONFIG_BSP_USING_ETIMER3_CAPTURE=y +CONFIG_BSP_USING_TMR=y +CONFIG_BSP_USING_TIMER=y +CONFIG_BSP_USING_TIMER0=y +CONFIG_BSP_USING_TIMER1=y +CONFIG_BSP_USING_TIMER2=y +CONFIG_BSP_USING_TIMER3=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART0=y +# CONFIG_BSP_USING_UART1 is not set +# CONFIG_BSP_USING_UART2 is not set +# CONFIG_BSP_USING_UART3 is not set +# CONFIG_BSP_USING_UART4 is not set +# CONFIG_BSP_USING_UART5 is not set +# CONFIG_BSP_USING_UART6 is not set +# CONFIG_BSP_USING_UART7 is not set +# CONFIG_BSP_USING_UART8 is not set +# CONFIG_BSP_USING_UART9 is not set +# CONFIG_BSP_USING_UART10 is not set +CONFIG_BSP_USING_I2C=y +CONFIG_BSP_USING_I2C0=y +# CONFIG_BSP_USING_I2C1 is not set +CONFIG_BSP_USING_SDH=y +# CONFIG_BSP_USING_SDH0 is not set +CONFIG_BSP_USING_SDH1=y +CONFIG_NU_SDH_HOTPLUG=y +# CONFIG_NU_SDH_MOUNT_ON_ROOT is not set +CONFIG_BSP_USING_CAN=y +CONFIG_BSP_USING_CAN0=y +# CONFIG_BSP_USING_CAN1 is not set +CONFIG_BSP_USING_PWM=y +CONFIG_BSP_USING_PWM0=y +CONFIG_BSP_USING_QSPI=y +# CONFIG_BSP_USING_QSPI0_NONE is not set +CONFIG_BSP_USING_QSPI0=y +CONFIG_BSP_USING_QSPI1_NONE=y +# CONFIG_BSP_USING_QSPI1 is not set +CONFIG_BSP_USING_I2S=y +CONFIG_NU_I2S_DMA_FIFO_SIZE=2048 +# CONFIG_BSP_USING_SCUART is not set +# CONFIG_BSP_USING_CRYPTO is not set +# CONFIG_BSP_USING_SOFT_I2C is not set +CONFIG_BSP_USING_WDT=y +CONFIG_BSP_USING_EBI=y +CONFIG_BSP_USING_VPOST=y +# CONFIG_LCM_USING_E50A2V1 is not set +# CONFIG_LCM_USING_LSA40AT9001 is not set +CONFIG_LCM_USING_FW070TFT=y +CONFIG_VPOST_USING_LCD_IDX=3 +CONFIG_LCM_USING_BPP=4 +CONFIG_BSP_USING_VPOST_OSD=y +CONFIG_BSP_USING_USBD=y +CONFIG_BSP_USING_USBH=y + +# +# On-board Peripheral Drivers +# +CONFIG_BSP_USING_CONSOLE=y +CONFIG_BOARD_USING_IP101GR=y +CONFIG_BOARD_USING_NAU8822=y +CONFIG_BOARD_USING_STORAGE_SDCARD=y +CONFIG_BOARD_USING_STORAGE_SPIFLASH=y +CONFIG_BOARD_USING_BUZZER=y +CONFIG_BOARD_USING_LCM=y +CONFIG_BOARD_USING_USB0_DEVICE_HOST=y +CONFIG_BOARD_USING_USB1_HOST=y + +# +# Board extended module drivers +# +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk-n9h30.test.utest." diff --git a/bsp/nuvoton/nk-n9h30/Kconfig b/bsp/nuvoton/nk-n9h30/Kconfig new file mode 100644 index 0000000000..5c55e87c61 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/Kconfig @@ -0,0 +1,29 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +# you can change the RTT_ROOT default "../../.." to your rtthread_root, +# example : default "F:/git_repositories/rt-thread" + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +config NU_PKGS_DIR + string + option env="NU_PKGS_ROOT" + default "../libraries/nu_packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "$NU_PKGS_DIR/Kconfig" +source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/nk-n9h30/README.md b/bsp/nuvoton/nk-n9h30/README.md new file mode 100644 index 0000000000..5dc4a7aec6 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/README.md @@ -0,0 +1,136 @@ +# NK-N9H30 +## 1. Introduction +Nuvoton offers the emWin platform which is embedded with Nuvoton N9H MPU, it provides complete HMI solutions which are further enhanced by the emWin software. The N9H series with ARM926EJ-S core can operate at up to 300 MHz and can drive up to 1024x768 pixels in parallel port. It integrated TFT LCD controller and 2D graphics accelerator, up to 16 million colors (24-bit) LCD screen output, and provides high resolution and high chroma to deliver gorgeous display effects. To play compressed video in HMI screens smoothly, the N9H series is equipped with H.264 video decompression engine. It also offers built-in voice decoder, which can streamline the peripheral circuits of HMI applications with sound playback. It embedded up to 64 MB DDR memory, along with ample hardware storage and computing space for excellent design flexibility. + +[![NK-N9H30](https://i.imgur.com/B04MCCf.png "NK-N9H30")](https://i.imgur.com/B04MCCf.png "NK-N9H30") + +### 1.1 MCU specification + +| | Features | +| -- | -- | +| Part NO. | N9H30F61IEC (LQFP216 pin MCP package with DDR (64 MB) | +| CPU ARCH. | 32-bit ARM926EJ-S | +| Operation frequency | 300 MHz | +| Embedded SDRAM size | Built-in 64MB | +| Crypto engine | AES, DES,HMAC and SHA crypto accelerator | +| RMII interface | 10/100 Mbps x2 | +| USB 2.0 | High Speed Host/Device x1 | +| Audio | Mono microphone / Stereo headphone | +| Extern storage | 32MB SPI-NOR Flash | +| SD card slot | SD | + +### 1.2 Interface + +| Interface | +| -- | +| Two RJ45 Ethernet | +| An USB 2.0 HS Dual role(Host/Device) port | +| A microSD slot | +| A 3.5mm Audio connector | +| An ICE connector | + +### 1.3 On-board devices + +| Device | Description | Driver supporting status | +| -- | -- | -- | +|Ethernet PHY | IP101GR | Supported | +|Keypad | | Supported | +|LEDs | | Supported | +|Audio Codec | NAU8822, Supports MIC and earphone | Supported | +|USB Device | VCOM + MStorage | Supported | +|USB Host | MStorage | Supported | +|SPI NOR flash | W25Q256JVEQ (32 MB) | Supported | + +## 2. Supported compiler +Support GCC, MDK4 and MDK5 IDE/compilers. More information of these compiler version as following: + +| IDE/Compiler | Tested version | +| ---------- | ---------------------------- | +| MDK5 | 5.26.2 | +| GCC | GCC 5.4.1 20160919 (release) | + +Notice: Please install ICE driver for development. + +## 3. Program firmware +### 3.1 SDRAM Downloading using NuWriter +You can use NuWriter to download rtthread.bin into SDRAM, then run it. +[![SDRAM Downloading using NuWriter](https://i.imgur.com/UqFvQOb.gif "SDRAM Downloading using NuWriter")](https://i.imgur.com/UqFvQOb.gif "SDRAM Downloading using NuWriter") +
+Choose type: DDR/SRAM
+<< Press Re-Connect >>
+Choose file: Specify your rtthread.bin file.
+Execute Address: 0x0
+Option: Download and run
+<< Press Download >>
+Enjoy!!
+
+ +### 3.2 SPI NOR flash using NuWriter +You can use NuWriter to program rtthread.bin into SPI NOR flash. +[![SPI NOR flash](https://i.imgur.com/6Fw3tc7.gif "SPI NOR flash")](https://i.imgur.com/6Fw3tc7.gif "SPI NOR flash using NuWriter") +
+Choose type: SPI
+<< Press Re-Connect >>
+Choose file: Specify your rtthread.bin file.
+Image Type: Loader
+Execute Address: 0x0
+<< Press Program >>
+<< Press OK & Wait it down >>
+<< Set Power-on setting to SPI NOR booting >>
+<< Press Reset button on board >>
+Enjoy!!
+
+ +## 4. Test +You can use Tera Term terminate emulator (or other software) to type commands of RTT. All parameters of serial communication are shown in below image. Here, you can find out the corresponding port number of Nuvoton Virtual Com Port in window device manager. + +[![Serial settings](https://i.imgur.com/5NYuSNM.png "Serial settings")](https://i.imgur.com/5NYuSNM.png "Serial settings") + +## 5. Demo + +* Run NUemWin2RTT on NK-N9H30 + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.3 build May 12 2021 + 2006 - 2021 Copyright by rt-thread team + +msh /> nu_touch_start +msh /> nuemwin_start + + + +msh /> nuemwin_stop +``` + + [![NUemWin2RTT on NK-N9H30](https://img.youtube.com/vi/TAfkOKpySQk/0.jpg)](https://www.youtube.com/watch?v=TAfkOKpySQk) + + +* Run LittlevGL2RTT on NK-N9H30 + + **Please check out modified version with GE2D accelerating from [HERE](https://github.com/wosayttn/LittlevGL2RTT).** + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.3 build May 12 2021 + 2006 - 2021 Copyright by rt-thread team + +msh /> nu_touch_start +msh /> lv_demo + + +``` + + + + [![LvGL2RTT on NK-N9H30](https://img.youtube.com/vi/djz0jAKrfjs/0.jpg)](https://www.youtube.com/watch?v=djz0jAKrfjs) + +## 6. Purchase +* [Nuvoton Direct](https://direct.nuvoton.com/en/numaker-emwin-n9h30) + +## 7. Resources +* [Board Schematic](https://www.nuvoton.com/resource-download.jsp?tp_GUID=HL1020201117191514) +* [Download NK-N9H30 Quick Start Guide](https://www.nuvoton.com/resource-download.jsp?tp_GUID=UG1320210329155300) +* [Download NuWriter](https://github.com/OpenNuvoton/NUC970_NuWriter) diff --git a/bsp/nuvoton/nk-n9h30/SConscript b/bsp/nuvoton/nk-n9h30/SConscript new file mode 100644 index 0000000000..fe0ae941ae --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/SConscript @@ -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') diff --git a/bsp/nuvoton/nk-n9h30/SConstruct b/bsp/nuvoton/nk-n9h30/SConstruct new file mode 100644 index 0000000000..b280d35fb9 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/SConstruct @@ -0,0 +1,55 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +nuvoton_library = 'n9h30' +rtconfig.BSP_LIBRARY_TYPE = nuvoton_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, nuvoton_library, 'SConscript'))) + +# include nu_pkgs +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'nu_packages', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/nuvoton/nk-n9h30/applications/SConscript b/bsp/nuvoton/nk-n9h30/applications/SConscript new file mode 100644 index 0000000000..9ffdbcd0f9 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/applications/SConscript @@ -0,0 +1,11 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/nuvoton/nk-n9h30/applications/main.c b/bsp/nuvoton/nk-n9h30/applications/main.c new file mode 100644 index 0000000000..90ebda5181 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/applications/main.c @@ -0,0 +1,118 @@ +/**************************************************************************//** +* +* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#include +#include + +#if defined(RT_USING_PIN) +#include + +/* defined the INDICATOR_LED pin: PH2 */ +#define INDICATOR_LED NU_GET_PININDEX(NU_PH, 2) + + +#define MATRIX_COL_NUM 2 +#define MATRIX_ROW_NUM 3 + +/* defined the KEY_COl_0 pin: PB4 */ +#define KEY_COL_0 NU_GET_PININDEX(NU_PB, 4) + +/* defined the KEY_COl_1 pin: PB5 */ +#define KEY_COL_1 NU_GET_PININDEX(NU_PB, 5) + +/* defined the KEY_ROW_0 pin: PF10 */ +#define KEY_ROW_0 NU_GET_PININDEX(NU_PF, 10) + +/* defined the KEY_ROW_1 pin: PE15 */ +#define KEY_ROW_1 NU_GET_PININDEX(NU_PE, 15) + +/* defined the KEY_ROW_2 pin: PE14 */ +#define KEY_ROW_2 NU_GET_PININDEX(NU_PE, 14) + +uint32_t au32KeyMatrix_Col[MATRIX_COL_NUM] = { KEY_COL_0, KEY_COL_1 }; +uint32_t au32KeyMatrix_Row[MATRIX_ROW_NUM] = { KEY_ROW_0, KEY_ROW_1, KEY_ROW_2 }; + +const char *szKeyLabel[] = +{ + "K1", + "K2", + "K3", + "K4", + "K5", + "K6" +}; + +static void nu_key_matrix_cb(void *args) +{ + uint32_t ri = (uint32_t)args; + int ci; + for (ci = 0; ci < MATRIX_COL_NUM; ci++) + { + /* Find column bit is low. */ + if (!rt_pin_read(au32KeyMatrix_Col[ci])) + { + break; + } + } + rt_kprintf("[%d %d] Pressed %s button.\n", ci, ri, szKeyLabel[(ci) + MATRIX_COL_NUM * ri]); +} + +static void nu_key_matrix_switch(uint32_t counter) +{ + int i; + for (i = 0; i < MATRIX_COL_NUM; i++) + { + /* set pin value to high */ + rt_pin_write(au32KeyMatrix_Col[i], PIN_HIGH); + } + /* set pin value to low */ + rt_pin_write(au32KeyMatrix_Col[counter % MATRIX_COL_NUM], PIN_LOW); +} +#endif + +int main(int argc, char **argv) +{ +#if defined(RT_USING_PIN) + uint32_t counter = 1; + int i = 0; + + for (i = 0; i < MATRIX_ROW_NUM; i++) + { + /* set pin mode to input */ + rt_pin_mode(au32KeyMatrix_Row[i], PIN_MODE_INPUT_PULLUP); + + rt_pin_attach_irq(au32KeyMatrix_Row[i], PIN_IRQ_MODE_FALLING, nu_key_matrix_cb, (void *)i); + rt_pin_irq_enable(au32KeyMatrix_Row[i], PIN_IRQ_ENABLE); + } + + for (i = 0; i < MATRIX_COL_NUM; i++) + { + /* set pin mode to output */ + rt_pin_mode(au32KeyMatrix_Col[i], PIN_MODE_OUTPUT); + } + + /* set INDICATOR_LED pin mode to output */ + rt_pin_mode(INDICATOR_LED, PIN_MODE_OUTPUT); + + /* Toggle column pins in key matrix. */ + while (counter++ > 0) + { + rt_pin_write(INDICATOR_LED, PIN_HIGH); + rt_thread_mdelay(200); + rt_pin_write(INDICATOR_LED, PIN_LOW); + rt_thread_mdelay(200); + nu_key_matrix_switch(counter); + } +#endif + + return 0; +} diff --git a/bsp/nuvoton/nk-n9h30/applications/mnt.c b/bsp/nuvoton/nk-n9h30/applications/mnt.c new file mode 100644 index 0000000000..23c44a7282 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/applications/mnt.c @@ -0,0 +1,243 @@ +/**************************************************************************//** +* +* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#include "rtconfig.h" + +#include + +#define LOG_TAG "mnt" +#define DBG_ENABLE +#define DBG_SECTION_NAME "mnt" +#define DBG_LEVEL DBG_ERROR +#define DBG_COLOR +#include + +#if defined(RT_USING_DFS) + #include + #include +#endif + +#if defined(PKG_USING_FAL) + #include +#endif + +#if defined(PKG_USING_RAMDISK) + #define RAMDISK_NAME "ramdisk0" + #define RAMDISK_UDC "ramdisk1" + #define MOUNT_POINT_RAMDISK0 "/" +#endif + +#if defined(BOARD_USING_STORAGE_SPIFLASH) + #define PARTITION_NAME_FILESYSTEM "filesystem" + #define MOUNT_POINT_SPIFLASH0 "/mnt/"PARTITION_NAME_FILESYSTEM +#endif + +#ifdef RT_USING_DFS_MNTTABLE + +/* +const char *device_name; +const char *path; +const char *filesystemtype; +unsigned long rwflag; +const void *data; +*/ + +const struct dfs_mount_tbl mount_table[] = +{ +#if defined(PKG_USING_RAMDISK) + { RAMDISK_UDC, "/mnt/ram_usbd", "elm", 0, RT_NULL }, +#endif + {0}, +}; +#endif + + +#if defined(PKG_USING_RAMDISK) + +extern rt_err_t ramdisk_init(const char *dev_name, rt_uint8_t *disk_addr, rt_size_t block_size, rt_size_t num_block); +int ramdisk_device_init(void) +{ + rt_err_t result = RT_EOK; + + /* Create a 8MB RAMDISK */ + result = ramdisk_init(RAMDISK_NAME, NULL, 512, 2 * 4096); + RT_ASSERT(result == RT_EOK); + + /* Create a 4MB RAMDISK */ + result = ramdisk_init(RAMDISK_UDC, NULL, 512, 2 * 4096); + RT_ASSERT(result == RT_EOK); + + return 0; +} +INIT_DEVICE_EXPORT(ramdisk_device_init); + +/* Recursive mkdir */ +static int mkdir_p(const char *dir, const mode_t mode) +{ + int ret = -1; + char *tmp = NULL; + char *p = NULL; + struct stat sb; + rt_size_t len; + + if (!dir) + goto exit_mkdir_p; + + /* Copy path */ + /* Get the string length */ + len = strlen(dir); + tmp = rt_strdup(dir); + + /* Remove trailing slash */ + if (tmp[len - 1] == '/') + { + tmp[len - 1] = '\0'; + len--; + } + + /* check if path exists and is a directory */ + if (stat(tmp, &sb) == 0) + { + if (S_ISDIR(sb.st_mode)) + { + ret = 0; + goto exit_mkdir_p; + } + } + + /* Recursive mkdir */ + for (p = tmp + 1; p - tmp <= len; p++) + { + if ((*p == '/') || (p - tmp == len)) + { + *p = 0; + + /* Test path */ + if (stat(tmp, &sb) != 0) + { + /* Path does not exist - create directory */ + if (mkdir(tmp, mode) < 0) + { + goto exit_mkdir_p; + } + } + else if (!S_ISDIR(sb.st_mode)) + { + /* Not a directory */ + goto exit_mkdir_p; + } + if (p - tmp != len) + *p = '/'; + } + } + + ret = 0; + +exit_mkdir_p: + + if (tmp) + rt_free(tmp); + + return ret; +} + +/* Initialize the filesystem */ +int filesystem_init(void) +{ + rt_err_t result = RT_EOK; + + // ramdisk as root + if (!rt_device_find(RAMDISK_NAME)) + { + LOG_E("cannot find %s device", RAMDISK_NAME); + goto exit_filesystem_init; + } + else + { + /* Format these ramdisk */ + result = (rt_err_t)dfs_mkfs("elm", RAMDISK_NAME); + RT_ASSERT(result == RT_EOK); + + /* mount ramdisk0 as root directory */ + if (dfs_mount(RAMDISK_NAME, "/", "elm", 0, RT_NULL) == 0) + { + LOG_I("ramdisk mounted on \"/\"."); + + /* now you can create dir dynamically. */ + mkdir_p("/mnt", 0x777); + mkdir_p("/cache", 0x777); + mkdir_p("/download", 0x777); + mkdir_p("/mnt/ram_usbd", 0x777); +#if defined(RT_USBH_MSTORAGE) && defined(UDISK_MOUNTPOINT) + mkdir_p(UDISK_MOUNTPOINT, 0x777); +#endif + } + else + { + LOG_E("root folder creation failed!\n"); + goto exit_filesystem_init; + } + } + + if (!rt_device_find(RAMDISK_UDC)) + { + LOG_E("cannot find %s device", RAMDISK_UDC); + goto exit_filesystem_init; + } + else + { + /* Format these ramdisk */ + result = (rt_err_t)dfs_mkfs("elm", RAMDISK_UDC); + RT_ASSERT(result == RT_EOK); + } + +exit_filesystem_init: + + return -result; +} +INIT_ENV_EXPORT(filesystem_init); +#endif + +#if defined(BOARD_USING_STORAGE_SPIFLASH) +int mnt_init_spiflash0(void) +{ +#if defined(PKG_USING_FAL) + extern int fal_init_check(void); + if (!fal_init_check()) + fal_init(); +#endif + struct rt_device *psNorFlash = fal_blk_device_create(PARTITION_NAME_FILESYSTEM); + if (!psNorFlash) + { + rt_kprintf("Failed to create block device for %s.\n", PARTITION_NAME_FILESYSTEM); + goto exit_mnt_init_spiflash0; + } + else if (mkdir(MOUNT_POINT_SPIFLASH0, 0x777) < 0) + { + rt_kprintf("Failed to make folder for %s.\n", MOUNT_POINT_SPIFLASH0); + goto exit_mnt_init_spiflash0; + } + else if (dfs_mount(psNorFlash->parent.name, MOUNT_POINT_SPIFLASH0, "elm", 0, 0) != 0) + { + rt_kprintf("Failed to mount elm on %s.\n", MOUNT_POINT_SPIFLASH0); + rt_kprintf("Try to execute 'mkfs -t elm %s' first, then reboot.\n", PARTITION_NAME_FILESYSTEM); + goto exit_mnt_init_spiflash0; + } + rt_kprintf("mount %s with elmfat type: ok\n", PARTITION_NAME_FILESYSTEM); + +exit_mnt_init_spiflash0: + + return 0; +} +INIT_ENV_EXPORT(mnt_init_spiflash0); +#endif + diff --git a/bsp/nuvoton/nk-n9h30/board/Kconfig b/bsp/nuvoton/nk-n9h30/board/Kconfig new file mode 100644 index 0000000000..b5aff1bc9e --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/board/Kconfig @@ -0,0 +1,75 @@ +menu "Hardware Drivers Config" + + menu "On-chip Peripheral Drivers" + source "$BSP_DIR/../libraries/n9h30/rtt_port/Kconfig" + endmenu + + menu "On-board Peripheral Drivers" + + config BSP_USING_CONSOLE + bool "Enable UART0 for RTT Console(uart0)" + select BSP_USING_UART + select BSP_USING_UART0 + default y + + config BOARD_USING_IP101GR + bool "Enable ethernet phy supporting(over emac/mdio)" + select BSP_USING_EMAC + select BSP_USING_EMAC0 + select BSP_USING_EMAC1 + default n + + config BOARD_USING_NAU8822 + bool "NAU8822 Audio Codec supporting(over i2s, i2c0)" + select NU_PKG_USING_NAU8822 + select BSP_USING_I2C0 + select BSP_USING_I2S + select BSP_USING_I2S0 + default n + + config BOARD_USING_STORAGE_SDCARD + bool "SDCARD supporting(over sdh1)" + select BSP_USING_SDH + select BSP_USING_SDH1 + default y + + config BOARD_USING_STORAGE_SPIFLASH + bool "SPIFLASH supporting(over qspi0)" + select BSP_USING_QSPI + select BSP_USING_QSPI0 + default y + + config BOARD_USING_BUZZER + bool "BUZZER.(over pwm0_ch1)" + select BSP_USING_PWM + select BSP_USING_PWM0 + default n + + config BOARD_USING_LCM + bool "NuDesign TFT-LCD7(over vpost)" + select BSP_USING_VPOST + select LCM_USING_FW070TFT + default y + + config BOARD_USING_USB0_DEVICE_HOST + select BSP_USING_USBH + select BSP_USING_USBD + bool "Enable USB0 Device/Host" + help + Choose this option if you need USB device or host function mode. + If you need USB host, please remember short to ground on JP1 jumper. + + config BOARD_USING_USB1_HOST + select BSP_USING_USBH + bool "Enable USB1 Host" + help + Choose this option if you need USB1 HOST. + + endmenu + + menu "Board extended module drivers" + + endmenu + + +endmenu diff --git a/bsp/nuvoton/nk-n9h30/board/SConscript b/bsp/nuvoton/nk-n9h30/board/SConscript new file mode 100644 index 0000000000..3f8e1c167f --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/board/SConscript @@ -0,0 +1,14 @@ +# RT-Thread building script for component + +from building import * + + +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +CPPPATH = [ cwd ] + +group = DefineGroup('board', src, depend = [''], CPPPATH = CPPPATH) +Return('group') diff --git a/bsp/nuvoton/nk-n9h30/board/board.h b/bsp/nuvoton/nk-n9h30/board/board.h new file mode 100644 index 0000000000..ea06d85742 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/board/board.h @@ -0,0 +1,37 @@ +/**************************************************************************//** +* +* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-1-16 Wayne First version +* +******************************************************************************/ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "NuMicro.h" +#include "drv_sys.h" + +#if defined(__CC_ARM) + extern int Image$$RW_RAM1$$ZI$$Limit; + #define BOARD_HEAP_START (void*)&Image$$RW_RAM1$$ZI$$Limit +#else + extern int __bss_end; + #define BOARD_HEAP_START ((void *)&__bss_end) +#endif + +#define BOARD_SDRAM_START 0x0 +#define BOARD_SDRAM_SIZE 0x04000000 +#define BOARD_HEAP_END ((void*)BOARD_SDRAM_SIZE) + +extern void rt_hw_board_init(void); +extern void nu_clock_init(void); +extern void nu_clock_deinit(void); +extern void nu_pin_init(void); +extern void nu_pin_deinit(void); + +#endif /* BOARD_H_ */ diff --git a/bsp/nuvoton/nk-n9h30/board/board_dev.c b/bsp/nuvoton/nk-n9h30/board/board_dev.c new file mode 100644 index 0000000000..297b79351f --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/board/board_dev.c @@ -0,0 +1,333 @@ +/**************************************************************************//** +* +* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#include +#include + +#if defined(BOARD_USING_STORAGE_SPIFLASH) + +#include + +#if defined(RT_USING_SFUD) + #include "spi_flash.h" + #include "spi_flash_sfud.h" +#endif + + +#define W25X_REG_READSTATUS (0x05) +#define W25X_REG_READSTATUS2 (0x35) +#define W25X_REG_WRITEENABLE (0x06) +#define W25X_REG_WRITESTATUS (0x01) +#define W25X_REG_QUADENABLE (0x02) + +static rt_uint8_t SpiFlash_ReadStatusReg(struct rt_qspi_device *qspi_device) +{ + rt_uint8_t u8Val; + rt_err_t result = RT_EOK; + rt_uint8_t w25x_txCMD1 = W25X_REG_READSTATUS; + + result = rt_qspi_send_then_recv(qspi_device, &w25x_txCMD1, 1, &u8Val, 1); + RT_ASSERT(result > 0); + + return u8Val; +} + +static rt_uint8_t SpiFlash_ReadStatusReg2(struct rt_qspi_device *qspi_device) +{ + rt_uint8_t u8Val; + rt_err_t result = RT_EOK; + rt_uint8_t w25x_txCMD1 = W25X_REG_READSTATUS2; + + result = rt_qspi_send_then_recv(qspi_device, &w25x_txCMD1, 1, &u8Val, 1); + RT_ASSERT(result > 0); + + return u8Val; +} + +static rt_err_t SpiFlash_WriteStatusReg(struct rt_qspi_device *qspi_device, uint8_t u8Value1, uint8_t u8Value2) +{ + rt_uint8_t w25x_txCMD1; + rt_uint8_t au8Val[2]; + rt_err_t result; + struct rt_qspi_message qspi_message = {0}; + + /* Enable WE */ + w25x_txCMD1 = W25X_REG_WRITEENABLE; + result = rt_qspi_send(qspi_device, &w25x_txCMD1, sizeof(w25x_txCMD1)); + if (result != sizeof(w25x_txCMD1)) + goto exit_SpiFlash_WriteStatusReg; + + /* Prepare status-1, 2 data */ + au8Val[0] = u8Value1; + au8Val[1] = u8Value2; + + /* 1-bit mode: Instruction+payload */ + qspi_message.instruction.content = W25X_REG_WRITESTATUS; + qspi_message.instruction.qspi_lines = 1; + + qspi_message.qspi_data_lines = 1; + qspi_message.parent.cs_take = 1; + qspi_message.parent.cs_release = 1; + qspi_message.parent.send_buf = &au8Val[0]; + qspi_message.parent.length = sizeof(au8Val); + qspi_message.parent.next = RT_NULL; + + if (rt_qspi_transfer_message(qspi_device, &qspi_message) != sizeof(au8Val)) + { + result = -RT_ERROR; + } + + result = RT_EOK; + +exit_SpiFlash_WriteStatusReg: + + return result; +} + +static void SpiFlash_WaitReady(struct rt_qspi_device *qspi_device) +{ + volatile uint8_t u8ReturnValue; + + do + { + u8ReturnValue = SpiFlash_ReadStatusReg(qspi_device); + u8ReturnValue = u8ReturnValue & 1; + } + while (u8ReturnValue != 0); // check the BUSY bit +} + +static void SpiFlash_EnterQspiMode(struct rt_qspi_device *qspi_device) +{ + rt_err_t result = RT_EOK; + + uint8_t u8Status1 = SpiFlash_ReadStatusReg(qspi_device); + uint8_t u8Status2 = SpiFlash_ReadStatusReg2(qspi_device); + + u8Status2 |= W25X_REG_QUADENABLE; + + result = SpiFlash_WriteStatusReg(qspi_device, u8Status1, u8Status2); + RT_ASSERT(result == RT_EOK); + + SpiFlash_WaitReady(qspi_device); +} + +static void SpiFlash_ExitQspiMode(struct rt_qspi_device *qspi_device) +{ + rt_err_t result = RT_EOK; + uint8_t u8Status1 = SpiFlash_ReadStatusReg(qspi_device); + uint8_t u8Status2 = SpiFlash_ReadStatusReg2(qspi_device); + + u8Status2 &= ~W25X_REG_QUADENABLE; + + result = SpiFlash_WriteStatusReg(qspi_device, u8Status1, u8Status2); + RT_ASSERT(result == RT_EOK); + + SpiFlash_WaitReady(qspi_device); +} + +static int rt_hw_spiflash_init(void) +{ + if (nu_qspi_bus_attach_device("qspi0", "qspi01", 4, SpiFlash_EnterQspiMode, SpiFlash_ExitQspiMode) != RT_EOK) + return -1; + +#if defined(RT_USING_SFUD) + if (rt_sfud_flash_probe(FAL_USING_NOR_FLASH_DEV_NAME, "qspi01") == RT_NULL) + { + return -(RT_ERROR); + } +#endif + return 0; +} +INIT_COMPONENT_EXPORT(rt_hw_spiflash_init); +#endif /* BOARD_USING_STORAGE_SPIFLASH */ + +#if defined(BOARD_USING_NAU8822) && defined(NU_PKG_USING_NAU8822) +#include +S_NU_NAU8822_CONFIG sCodecConfig = +{ + .i2c_bus_name = "i2c0", + + .i2s_bus_name = "sound0", + + .pin_phonejack_en = 0, + + .pin_phonejack_det = 0, +}; + +int rt_hw_nau8822_port(void) +{ + if (nu_hw_nau8822_init(&sCodecConfig) != RT_EOK) + return -1; + + return 0; +} +INIT_COMPONENT_EXPORT(rt_hw_nau8822_port); +#endif /* BOARD_USING_NAU8822 */ + +#if defined(BOARD_USING_BUZZER) + +#define PWM_DEV_NAME "pwm0" +#define PWM_DEV_CHANNEL (1) + +static void PlayRingTone(void) +{ + struct rt_device_pwm *pwm_dev; + rt_uint32_t period; + int i, j; + + period = 1000; + + if ((pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME)) != RT_NULL) + { + rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, period); + rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL); + + for (j = 0; j < 3; j++) + { + for (i = 0; i < 10; i++) + { + rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, period); + rt_thread_mdelay(50); + + rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, period / 2); + rt_thread_mdelay(50); + } + + /* Mute 2 seconds */ + rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, period); + rt_thread_mdelay(2000); + } + rt_pwm_disable(pwm_dev, PWM_DEV_CHANNEL); + } + else + { + rt_kprintf("Can't find %s\n", PWM_DEV_NAME); + } +} + +#if defined(BOARD_USING_LCM) + +#if defined(PKG_USING_GUIENGINE) + #include +#endif + +#if defined(RT_USING_PIN) + #include + + /* defined the LCM_BLEN pin: PH3 */ + #define LCM_BLEN NU_GET_PININDEX(NU_PH, 3) +#endif + +#define PWM_DEV_NAME "pwm0" +#define LCM_PWM_CHANNEL (0) + +static void LCMLightOn(void) +{ + struct rt_device_pwm *pwm_dev; + + if ((pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME)) != RT_NULL) + { + rt_pwm_enable(pwm_dev, LCM_PWM_CHANNEL); + rt_pwm_set(pwm_dev, LCM_PWM_CHANNEL, 100000, 100); + } + else + { + rt_kprintf("Can't find %s\n", PWM_DEV_NAME); + } +} +#ifdef FINSH_USING_MSH + MSH_CMD_EXPORT(LCMLightOn, LCM - light on panel); +#endif + +int rt_hw_lcm_port(void) +{ +#if defined(PKG_USING_GUIENGINE) + rt_device_t lcm_vpost; + lcm_vpost = rt_device_find("lcd"); + if (lcm_vpost) + { + rtgui_graphic_set_device(lcm_vpost); + } +#endif + +#if defined(RT_USING_PIN) + /* set LCM_BLEN pin mode to output */ + rt_pin_mode(LCM_BLEN, PIN_MODE_OUTPUT); + rt_pin_write(LCM_BLEN, PIN_HIGH); +#endif + + LCMLightOn(); + + return 0; +} +INIT_COMPONENT_EXPORT(rt_hw_lcm_port); +#endif /* BOARD_USING_LCM */ + + +int buzzer_test(void) +{ + PlayRingTone(); + return 0; +} +#ifdef FINSH_USING_MSH + MSH_CMD_EXPORT(buzzer_test, Buzzer - Play ring tone); +#endif +#endif /* BOARD_USING_BUZZER */ + +#if defined(BOARD_USING_RS485) + +#include + +int test_rs485(int argc, char **argv) +{ + rt_device_t serial; + char txbuf[16]; + rt_err_t ret; + int str_len; + + if (argc < 2) + goto exit_test_rs485; + + serial = rt_device_find(argv[1]); + if (!serial) + { + rt_kprintf("Can't find %s. EXIT.\n", argv[1]); + goto exit_test_rs485; + } + + /* Interrupt RX */ + ret = rt_device_open(serial, RT_DEVICE_FLAG_INT_RX); + RT_ASSERT(ret == RT_EOK); + + /* Nuvoton private command */ + nu_uart_set_rs485aud((struct rt_serial_device *)serial, RT_FALSE); + + rt_snprintf(&txbuf[0], sizeof(txbuf), "Hello World!\r\n"); + str_len = rt_strlen(txbuf); + + /* Say Hello */ + ret = rt_device_write(serial, 0, &txbuf[0], str_len); + RT_ASSERT(ret == str_len); + + ret = rt_device_close(serial); + RT_ASSERT(ret == RT_EOK); + + return 0; + +exit_test_rs485: + + return -1; +} +MSH_CMD_EXPORT(test_rs485, test rs485 communication); + +#endif //defined(BOARD_USING_RS485) + diff --git a/bsp/nuvoton/nk-n9h30/board/fal_cfg.h b/bsp/nuvoton/nk-n9h30/board/fal_cfg.h new file mode 100644 index 0000000000..a8ff4ecd86 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/board/fal_cfg.h @@ -0,0 +1,46 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-3-03 FYChou First version +* +******************************************************************************/ + +#ifndef _FAL_CFG_H_ +#define _FAL_CFG_H_ + +#include +#include + +/* ===================== Flash device Configuration ========================= */ +#if defined(RT_USING_SFUD) +extern struct fal_flash_dev nor_flash0; + +/* -flash device table------------------------------------------------------- */ +#define FAL_FLASH_DEV_TABLE \ +{ \ + &nor_flash0, \ +} +#else +#define FAL_FLASH_DEV_TABLE \ +{ \ + 0 \ +} +#endif + +/* ====================== Partition Configuration ============================ */ +#ifdef FAL_PART_HAS_TABLE_CFG + +/* partition table------------------------------------------------------------ */ +#define FAL_PART_TABLE \ +{ \ + {FAL_PART_MAGIC_WORD, "rtthread", FAL_USING_NOR_FLASH_DEV_NAME, 0, 4*1024*1024, 0}, \ + {FAL_PART_MAGIC_WORD, "filesystem", FAL_USING_NOR_FLASH_DEV_NAME, 4*1024*1024, 12*1024*1024, 0}, \ +} +#endif /* FAL_PART_HAS_TABLE_CFG */ + +#endif /* _FAL_CFG_H_ */ diff --git a/bsp/nuvoton/nk-n9h30/board/nu_pin_init.c b/bsp/nuvoton/nk-n9h30/board/nu_pin_init.c new file mode 100644 index 0000000000..d6038a4a2e --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/board/nu_pin_init.c @@ -0,0 +1,155 @@ +/**************************************************************************//** +* +* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#include "board.h" + + +static void nu_pin_uart_init(void) +{ + /* UART0: PE[0, 1] */ + outpw(REG_SYS_GPE_MFPL, (inpw(REG_SYS_GPE_MFPL) & 0xffffff00) | 0x00000099); + + /* UART1: PH[4, 7] */ + outpw(REG_SYS_GPH_MFPL, (inpw(REG_SYS_GPH_MFPL) & 0x0000ffff) | 0x99990000); + + /* UART2: PF[11, 14] */ + outpw(REG_SYS_GPF_MFPH, (inpw(REG_SYS_GPF_MFPH) & 0xf0000fff) | 0x09999000); + + /* UART3: PE[12, 13] */ + outpw(REG_SYS_GPE_MFPH, (inpw(REG_SYS_GPE_MFPH) & 0xff00ffff) | 0x00990000); + + /* UART4: PH[8, 11] */ + outpw(REG_SYS_GPH_MFPH, (inpw(REG_SYS_GPH_MFPH) & 0xffff0000) | 0x00009999); + + /* UART5: PB[0, 1] */ + outpw(REG_SYS_GPB_MFPL, (inpw(REG_SYS_GPB_MFPL) & 0xffffff00) | 0x00000099); + + /* UART7: PI[1, 2] */ + outpw(REG_SYS_GPI_MFPL, (inpw(REG_SYS_GPI_MFPL) & 0xfffff00f) | 0x00000990); + + /* UART8: PH[12, 15] */ + outpw(REG_SYS_GPH_MFPH, (inpw(REG_SYS_GPH_MFPH) & 0x0000ffff) | 0x99990000); + + /* UART10: PB[12, 15] */ + outpw(REG_SYS_GPB_MFPH, (inpw(REG_SYS_GPB_MFPH) & 0x0000ffff) | 0x99990000); +} + +static void nu_pin_emac_init(void) +{ + /* EMAC0: PF[0, 9] */ + outpw(REG_SYS_GPF_MFPL, 0x11111111); + outpw(REG_SYS_GPF_MFPH, (inpw(REG_SYS_GPF_MFPH) & 0xffffff00) | 0x00000011); + + /* EMAC1: PE[2, 11] */ + outpw(REG_SYS_GPE_MFPL, (inpw(REG_SYS_GPE_MFPL) & 0x000000ff) | 0x11111100); + outpw(REG_SYS_GPE_MFPH, (inpw(REG_SYS_GPE_MFPH) & 0xffff0000) | 0x00001111); +} + +static void nu_pin_sdh_init(void) +{ + /* SDH0: PD[0, 6] */ + outpw(REG_SYS_GPD_MFPL, (inpw(REG_SYS_GPD_MFPL) & 0xf0000000) | 0x06666666); +} + +static void nu_pin_spi_init(void) +{ + /* QSPI0: PB[6, 11] */ + outpw(REG_SYS_GPB_MFPL, (inpw(REG_SYS_GPB_MFPL) & 0x00ffffff) | 0xbb000000); + outpw(REG_SYS_GPB_MFPH, (inpw(REG_SYS_GPB_MFPH) & 0xffff0000) | 0x0000bbbb); +} + +static void nu_pin_i2c_init(void) +{ + /* I2C0: PG[0, 1] */ + outpw(REG_SYS_GPG_MFPL, (inpw(REG_SYS_GPG_MFPL) & 0xffffff00) | 0x00000088); + + /* I2C1: PG[2, 3] */ + outpw(REG_SYS_GPG_MFPL, (inpw(REG_SYS_GPG_MFPL) & 0xffff00ff) | 0x00008800); +} + +static void nu_pin_pwm_init(void) +{ + /* PWM0: PB2, LCD_PWM */ + outpw(REG_SYS_GPB_MFPL, (inpw(REG_SYS_GPB_MFPL) & 0xfffff0ff) | 0x00000d00); + + /* PWM1: PB3, Buzzer */ + outpw(REG_SYS_GPB_MFPL, (inpw(REG_SYS_GPB_MFPL) & 0xffff0fff) | 0x0000d000); +} + +static void nu_pin_i2s_init(void) +{ + /* I2S: PG[10, 14] */ + outpw(REG_SYS_GPG_MFPH, (inpw(REG_SYS_GPG_MFPH) & 0xf00000ff) | 0x08888800); +} + +static void nu_pin_can_init(void) +{ + /* CAN0: PI[3, 4] */ + outpw(REG_SYS_GPI_MFPL, (inpw(REG_SYS_GPI_MFPL) & 0xfff00fff) | 0x000cc000); +} + +static void nu_pin_usbd_init(void) +{ + /* USB0_VBUSVLD, PH0 */ + outpw(REG_SYS_GPH_MFPL, (inpw(REG_SYS_GPH_MFPL) & 0xfffffff0) | 0x00000007); +} + +static void nu_pin_vpost_init(void) +{ + /* CLK: PG6, HSYNC: PG7 */ + outpw(REG_SYS_GPG_MFPL, (inpw(REG_SYS_GPG_MFPL) & 0x00ffffff) | 0x22000000); + /* VSYNC: PG8, DEN: PG9 */ + outpw(REG_SYS_GPG_MFPH, (inpw(REG_SYS_GPG_MFPH) & 0xffffff00) | 0x00000022); + + /* DATA pin: 24bit RGB */ + /* PA[0, 7] */ + outpw(REG_SYS_GPA_MFPL, 0x22222222); + /* PA[8, 15] */ + outpw(REG_SYS_GPA_MFPH, 0x22222222); +#if (LCM_USING_BPP==4) + /* PD[8, 15 ] */ + outpw(REG_SYS_GPD_MFPH, 0x22222222); +#endif +} + +static void nu_pin_fmi_init(void) +{ + /* NAND: PC[0, 14] */ + outpw(REG_SYS_GPC_MFPL, 0x55555555); + outpw(REG_SYS_GPC_MFPH, 0x05555555); +} + +static void nu_pin_usbh_init(void) +{ + +} + +void nu_pin_init(void) +{ + nu_pin_uart_init(); + nu_pin_emac_init(); + nu_pin_sdh_init(); + nu_pin_spi_init(); + nu_pin_i2c_init(); + nu_pin_pwm_init(); + nu_pin_i2s_init(); + nu_pin_can_init(); + nu_pin_vpost_init(); + nu_pin_fmi_init(); + nu_pin_usbd_init(); + nu_pin_usbh_init(); +} + +void nu_pin_deinit(void) +{ + +} diff --git a/bsp/nuvoton/nk-n9h30/linking_scripts/n9h30.ld b/bsp/nuvoton/nk-n9h30/linking_scripts/n9h30.ld new file mode 100644 index 0000000000..bdecf1da02 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/linking_scripts/n9h30.ld @@ -0,0 +1,111 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(system_vectors) + +MEMORY +{ + RAM (rwx) : ORIGIN = 0x000000, LENGTH = 0x04000000 +} + +SECTIONS +{ + . = 0x0; + + . = ALIGN(4); + .text : + { + *(.vectors) + *(.text) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for modules */ + . = ALIGN(4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + /* section information for utest */ + . = ALIGN(4); + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + . = ALIGN(4); + } + + . = ALIGN(4); + .rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r*) *(.eh_frame) } + + . = ALIGN(4); + .ctors : + { + PROVIDE(__ctors_start__ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(__ctors_end__ = .); + } + + .dtors : + { + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + } + + . = ALIGN(4); + .data : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + } + + . = ALIGN(4); + .nobss : { *(.nobss) } + + . = ALIGN(4); + __bss_start__ = .; + __bss_start = .; + .bss : { *(.bss)} + . = ALIGN(4); + __bss_end = .; + __bss_end__ = .; + . = ALIGN(4); + + /* 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) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } + + _end = .; +} diff --git a/bsp/nuvoton/nk-n9h30/linking_scripts/n9h30.sct b/bsp/nuvoton/nk-n9h30/linking_scripts/n9h30.sct new file mode 100644 index 0000000000..114b346e8c --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/linking_scripts/n9h30.sct @@ -0,0 +1,11 @@ +LR_IROM1 0x00000000 0x800000 { ; load region size_region + ER_IROM1 0x00000000 0x800000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_RAM1 +0 { ; RW_RAM1 start address is after ER_ROM1 + .ANY (+RW +ZI) + } +} + diff --git a/bsp/nuvoton/nk-n9h30/rtconfig.py b/bsp/nuvoton/nk-n9h30/rtconfig.py new file mode 100644 index 0000000000..f99f6be692 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/rtconfig.py @@ -0,0 +1,88 @@ +import os +# toolchains options +ARCH = 'arm' +CPU = 'arm926' +# toolchains options +CROSS_TOOL = 'gcc' + +#------- toolchains path ------------------------------------------------------- +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Program Files (x86)\GNU Tools ARM Embedded\6 2017-q1-update\bin' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:\Keil_v5' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' +#BUILD = 'release' + +CORE = 'arm926ej-s' +MAP_FILE = 'rtthread_n9h30.map' +LINK_FILE = 'linking_scripts/n9h30' +TARGET_NAME = 'rtthread.bin' + +#------- GCC settings ---------------------------------------------------------- +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + CXX = PREFIX + 'g++' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=arm926ej-s' + CFLAGS = DEVICE + AFLAGS = '-c'+ DEVICE + ' -x assembler-with-cpp' + AFLAGS += ' -Iplatform' + LFLAGS = DEVICE + LFLAGS += ' -Wl,--gc-sections,-cref,-Map=' + MAP_FILE + LFLAGS += ' -T ' + LINK_FILE + '.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O0' + + POST_ACTION = OBJCPY + ' -O binary $TARGET ' + TARGET_NAME + '\n' + POST_ACTION += SIZE + ' $TARGET\n' +#------- Keil settings --------------------------------------------------------- +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + EXEC_PATH += '/arm/armcc/bin/' + + DEVICE = ' --cpu=' + CORE + CFLAGS = DEVICE + ' --apcs=interwork --diag_suppress=870' + AFLAGS = DEVICE + ' -Iplatform' + LFLAGS = DEVICE + ' --strict' + LFLAGS += ' --info sizes --info totals --info unused --info veneers' + LFLAGS += ' --list ' + MAP_FILE + LFLAGS += ' --scatter ' + LINK_FILE + '.sct' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + POST_ACTION = 'fromelf --bin $TARGET --output ' + TARGET_NAME + ' \n' + POST_ACTION += 'fromelf -z $TARGET\n' \ No newline at end of file diff --git a/bsp/nuvoton/nk-n9h30/template.uvproj b/bsp/nuvoton/nk-n9h30/template.uvproj new file mode 100644 index 0000000000..2a4f8efb44 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/template.uvproj @@ -0,0 +1,394 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rtthread + 0x4 + ARM-ADS + + + Nuvoton_ARM9_Series + Nuvoton + + + + + 0 + + + + + + + + + + + + 0 + + + + Atmel\SAM9260\ + Atmel\SAM9260\ + + 0 + 0 + 0 + 0 + 1 + + .\Objects\ + rtthread + 1 + 0 + 0 + 1 + 1 + .\Listings\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + + + 0 + 0 + + + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + + + SARM.DLL + -cAT91SAM9 + DARMATS9.DLL + -p91SAM9260 + SARM.DLL + + TARMATS9.DLL + -p91SAM9260 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + + + 1 + 1 + 0 + 1 + 1 + 1 + 0 + 1 + 1 + + 0 + 6 + + + + + + + + + + + + + ..\libraries\nuc980\Script\NUC980xx61.ini + Segger\JLTAgdi.dll + + + + + 1 + 0 + 0 + 0 + 1 + 4098 + + 0 + Segger\JLTAgdi.dll + "" () + + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x200000 + 0x1000 + + + 1 + 0x100000 + 0x8000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + + --c99 + RT_USING_INTERRUPT_INFO + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x20000000 + 0x20800000 + .\linking_scripts\n9h30.sct + + + + + + + + + + + +
diff --git a/bsp/nuvoton/nk-n9h30/template.uvprojx b/bsp/nuvoton/nk-n9h30/template.uvprojx new file mode 100644 index 0000000000..f3525c7031 --- /dev/null +++ b/bsp/nuvoton/nk-n9h30/template.uvprojx @@ -0,0 +1,387 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rtthread + 0x4 + ARM-ADS + 0 + + + Nuvoton_ARM9_Series + Nuvoton + + + + + 0 + + + + + + + + + + + + 0 + 0 + + + + Atmel\SAM9260\ + Atmel\SAM9260\ + + 0 + 0 + 0 + 0 + 1 + + .\build\keil5\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\keil5\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARM.DLL + -cAT91SAM9260 + DARMATS9.DLL + -p91SAM9260 + SARM.DLL + + TARMATS9.DLL + -p91SAM9260 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 0 + 1 + 4098 + + 0 + Segger\JLTAgdi.dll + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + ARM926EJ-S + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x200000 + 0x1000 + + + 1 + 0x100000 + 0x8000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x20000000 + 0x800000 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x100000 + 0x8000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x20800000 + 0x1800000 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x200000 + 0x1000 + + + 0 + 0x300000 + 0x1000 + + + + + + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + --c99 + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x20000000 + 0x20800000 + + .\linking_scripts\n9h30.sct + + + + + + + + + + + + + + + + + +
diff --git a/bsp/nuvoton/nk-rtu980/linking_scripts/nuc980.ld b/bsp/nuvoton/nk-rtu980/linking_scripts/nuc980.ld index 1004f039fb..bdecf1da02 100644 --- a/bsp/nuvoton/nk-rtu980/linking_scripts/nuc980.ld +++ b/bsp/nuvoton/nk-rtu980/linking_scripts/nuc980.ld @@ -23,18 +23,14 @@ SECTIONS __fsymtab_start = .; KEEP(*(FSymTab)) __fsymtab_end = .; + . = ALIGN(4); + . = ALIGN(4); __vsymtab_start = .; KEEP(*(VSymTab)) __vsymtab_end = .; . = ALIGN(4); - . = ALIGN(4); - __rt_init_start = .; - KEEP(*(SORT(.rti_fn*))) - __rt_init_end = .; - . = ALIGN(4); - /* section information for modules */ . = ALIGN(4); __rtmsymtab_start = .; @@ -54,6 +50,7 @@ SECTIONS __rt_utest_tc_tab_start = .; KEEP(*(UtestTcTab)) __rt_utest_tc_tab_end = .; + . = ALIGN(4); } . = ALIGN(4); diff --git a/bsp/nuvoton/numaker-m2354/Nu_Link_Driver.ini b/bsp/nuvoton/numaker-m2354/Nu_Link_Driver.ini index 51ce76204b..aae0ad5cb6 100644 --- a/bsp/nuvoton/numaker-m2354/Nu_Link_Driver.ini +++ b/bsp/nuvoton/numaker-m2354/Nu_Link_Driver.ini @@ -1,12 +1,12 @@ [Version] Nu_LinkVersion=V5.14 [Process] -ProcessID=0x00003fc4 -ProcessCreationTime_L=0xfa4b822c -ProcessCreationTime_H=0x01d6fb6d -NuLinkID=0x1800002d +ProcessID=0x00009908 +ProcessCreationTime_L=0xda6c5f90 +ProcessCreationTime_H=0x01d74571 +NuLinkID=0x1800003c NuLinkIDs_Count=0x00000001 -NuLinkID0=0x1800002d +NuLinkID0=0x1800003c [ChipSelect] ;ChipName= ChipName=M2354 From 972aa93a2774b442ded77992921ed6630b74b36e Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Wed, 12 May 2021 19:15:17 +0800 Subject: [PATCH 056/255] Update N9H30 porting. --- .../libraries/n9h30/Driver/Include/N9H30.h | 2097 ++++++++++ .../libraries/n9h30/Driver/Include/NuMicro.h | 51 + .../libraries/n9h30/Driver/Include/emac_reg.h | 2063 ++++++++++ .../libraries/n9h30/Driver/Include/nu_2d.h | 190 + .../libraries/n9h30/Driver/Include/nu_adc.h | 198 + .../libraries/n9h30/Driver/Include/nu_can.h | 459 +++ .../libraries/n9h30/Driver/Include/nu_cap.h | 316 ++ .../n9h30/Driver/Include/nu_crypto.h | 689 ++++ .../libraries/n9h30/Driver/Include/nu_emac.h | 396 ++ .../n9h30/Driver/Include/nu_etimer.h | 717 ++++ .../libraries/n9h30/Driver/Include/nu_fmi.h | 315 ++ .../libraries/n9h30/Driver/Include/nu_gpio.h | 162 + .../libraries/n9h30/Driver/Include/nu_i2c.h | 105 + .../libraries/n9h30/Driver/Include/nu_i2s.h | 130 + .../libraries/n9h30/Driver/Include/nu_jpeg.h | 398 ++ .../n9h30/Driver/Include/nu_jpegcodec.h | 227 ++ .../libraries/n9h30/Driver/Include/nu_lcd.h | 247 ++ .../libraries/n9h30/Driver/Include/nu_pwm.h | 238 ++ .../libraries/n9h30/Driver/Include/nu_rtc.h | 508 +++ .../n9h30/Driver/Include/nu_scuart.h | 335 ++ .../libraries/n9h30/Driver/Include/nu_sdh.h | 757 ++++ .../libraries/n9h30/Driver/Include/nu_spi.h | 121 + .../libraries/n9h30/Driver/Include/nu_sys.h | 373 ++ .../libraries/n9h30/Driver/Include/nu_timer.h | 61 + .../libraries/n9h30/Driver/Include/nu_uart.h | 773 ++++ .../libraries/n9h30/Driver/Include/nu_usbd.h | 937 +++++ .../libraries/n9h30/Driver/Include/nu_wdt.h | 185 + .../libraries/n9h30/Driver/Include/nu_wwdt.h | 120 + bsp/nuvoton/libraries/n9h30/Driver/SConscript | 26 + .../libraries/n9h30/Driver/Source/nu_can.c | 1286 ++++++ .../libraries/n9h30/Driver/Source/nu_cap.c | 1520 ++++++++ .../libraries/n9h30/Driver/Source/nu_crypto.c | 394 ++ .../libraries/n9h30/Driver/Source/nu_emac.c | 1158 ++++++ .../libraries/n9h30/Driver/Source/nu_etimer.c | 341 ++ .../libraries/n9h30/Driver/Source/nu_fmi.c | 920 +++++ .../libraries/n9h30/Driver/Source/nu_gpio.c | 500 +++ .../libraries/n9h30/Driver/Source/nu_i2s.c | 461 +++ .../libraries/n9h30/Driver/Source/nu_lcd.c | 764 ++++ .../libraries/n9h30/Driver/Source/nu_pwm.c | 1117 ++++++ .../libraries/n9h30/Driver/Source/nu_rtc.c | 1153 ++++++ .../libraries/n9h30/Driver/Source/nu_scuart.c | 246 ++ .../libraries/n9h30/Driver/Source/nu_sdh.c | 1193 ++++++ .../libraries/n9h30/Driver/Source/nu_spi.c | 336 ++ .../libraries/n9h30/Driver/Source/nu_sys.c | 675 ++++ .../libraries/n9h30/Driver/Source/nu_timer.c | 146 + .../libraries/n9h30/Driver/Source/nu_uart.c | 2200 +++++++++++ .../libraries/n9h30/Driver/Source/nu_usbd.c | 619 +++ .../libraries/n9h30/Driver/Source/nu_wdt.c | 66 + .../libraries/n9h30/Driver/Source/nu_wwdt.c | 72 + bsp/nuvoton/libraries/n9h30/README.md | 32 + bsp/nuvoton/libraries/n9h30/SConscript | 14 + .../libraries/n9h30/UsbHostLib/SConscript | 12 + .../libraries/n9h30/UsbHostLib/inc/config.h | 1524 ++++++++ .../libraries/n9h30/UsbHostLib/inc/ehci.h | 279 ++ .../libraries/n9h30/UsbHostLib/inc/hub.h | 124 + .../libraries/n9h30/UsbHostLib/inc/ohci.h | 147 + .../libraries/n9h30/UsbHostLib/inc/usb.h | 394 ++ .../libraries/n9h30/UsbHostLib/inc/usbh_lib.h | 188 + .../libraries/n9h30/UsbHostLib/src/ehci.c | 1288 ++++++ .../libraries/n9h30/UsbHostLib/src/ehci_iso.c | 918 +++++ .../n9h30/UsbHostLib/src/mem_alloc.c | 540 +++ .../libraries/n9h30/UsbHostLib/src/ohci.c | 1301 ++++++ .../libraries/n9h30/UsbHostLib/src/support.c | 324 ++ .../libraries/n9h30/UsbHostLib/src/usb_core.c | 312 ++ bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig | 500 +++ .../libraries/n9h30/rtt_port/SConscript | 14 + .../libraries/n9h30/rtt_port/drv_adc.c | 728 ++++ .../libraries/n9h30/rtt_port/drv_adc.h | 64 + .../libraries/n9h30/rtt_port/drv_adc_touch.c | 274 ++ .../libraries/n9h30/rtt_port/drv_can.c | 544 +++ .../libraries/n9h30/rtt_port/drv_common.c | 78 + .../libraries/n9h30/rtt_port/drv_common.h | 20 + .../libraries/n9h30/rtt_port/drv_crypto.c | 996 +++++ .../libraries/n9h30/rtt_port/drv_emac.c | 621 +++ .../libraries/n9h30/rtt_port/drv_etimer.c | 283 ++ .../n9h30/rtt_port/drv_etimer_capture.c | 226 ++ .../libraries/n9h30/rtt_port/drv_ge2d.c | 3470 +++++++++++++++++ .../libraries/n9h30/rtt_port/drv_gpio.c | 388 ++ .../libraries/n9h30/rtt_port/drv_gpio.h | 36 + .../libraries/n9h30/rtt_port/drv_i2c.c | 520 +++ .../libraries/n9h30/rtt_port/drv_i2s.c | 630 +++ .../libraries/n9h30/rtt_port/drv_i2s.h | 98 + .../libraries/n9h30/rtt_port/drv_jpegcodec.c | 1412 +++++++ .../libraries/n9h30/rtt_port/drv_pwm.c | 293 ++ .../libraries/n9h30/rtt_port/drv_qspi.c | 557 +++ .../libraries/n9h30/rtt_port/drv_qspi.h | 20 + .../libraries/n9h30/rtt_port/drv_rtc.c | 386 ++ .../libraries/n9h30/rtt_port/drv_scuart.c | 333 ++ .../libraries/n9h30/rtt_port/drv_sdh.c | 642 +++ .../libraries/n9h30/rtt_port/drv_softi2c.c | 238 ++ .../libraries/n9h30/rtt_port/drv_sys.c | 330 ++ .../libraries/n9h30/rtt_port/drv_sys.h | 281 ++ .../libraries/n9h30/rtt_port/drv_systick.c | 92 + .../libraries/n9h30/rtt_port/drv_timer.c | 285 ++ .../libraries/n9h30/rtt_port/drv_uart.c | 482 +++ .../libraries/n9h30/rtt_port/drv_uart.h | 21 + .../libraries/n9h30/rtt_port/drv_usbd.c | 932 +++++ .../libraries/n9h30/rtt_port/drv_usbhost.c | 893 +++++ .../libraries/n9h30/rtt_port/drv_vpost.c | 352 ++ .../libraries/n9h30/rtt_port/drv_wdt.c | 283 ++ 100 files changed, 53080 insertions(+) create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/N9H30.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/NuMicro.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/emac_reg.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_2d.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_adc.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_can.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_cap.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_crypto.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_emac.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_etimer.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_fmi.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_gpio.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_i2c.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_i2s.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_jpeg.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_jpegcodec.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_pwm.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_rtc.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_scuart.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_sdh.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_spi.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_sys.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_timer.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_usbd.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_wdt.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Include/nu_wwdt.h create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/SConscript create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_can.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_cap.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_crypto.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_emac.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_etimer.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_fmi.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_gpio.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_i2s.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_pwm.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_rtc.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_scuart.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sdh.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_spi.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sys.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_timer.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_uart.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_usbd.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_wdt.c create mode 100644 bsp/nuvoton/libraries/n9h30/Driver/Source/nu_wwdt.c create mode 100644 bsp/nuvoton/libraries/n9h30/README.md create mode 100644 bsp/nuvoton/libraries/n9h30/SConscript create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/SConscript create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/config.h create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/ehci.h create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/hub.h create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/ohci.h create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usb.h create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usbh_lib.h create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci.c create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci_iso.c create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/src/mem_alloc.c create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ohci.c create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/src/support.c create mode 100644 bsp/nuvoton/libraries/n9h30/UsbHostLib/src/usb_core.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/SConscript create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.h create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_crypto.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_emac.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_etimer.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_etimer_capture.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_ge2d.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_gpio.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_gpio.h create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2s.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2s.h create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_jpegcodec.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_pwm.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.h create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_rtc.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_scuart.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_softi2c.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_sys.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_sys.h create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_systick.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_timer.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_uart.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_uart.h create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbd.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c create mode 100644 bsp/nuvoton/libraries/n9h30/rtt_port/drv_wdt.c diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/N9H30.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/N9H30.h new file mode 100644 index 0000000000..2bdc5ebddd --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/N9H30.h @@ -0,0 +1,2097 @@ +/**************************************************************************//** + * @file N9H30.h + * @version V1.00 + * @brief N9H30 peripheral access layer header file. + * This file contains all the peripheral register's definitions + * and memory mapping for NuMicro N9H30 MCU. + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +/** + \mainpage NuMicro N9H30 Family Driver Reference Guide + * + * Introduction + * + * This user manual describes the usage of N9H30 family device driver + * + * Disclaimer + * + * The Software is furnished "AS IS", without warranty as to performance or results, and + * the entire risk as to performance or results is assumed by YOU. Nuvoton disclaims all + * warranties, express, implied or otherwise, with regard to the Software, its use, or + * operation, including without limitation any and all warranties of merchantability, fitness + * for a particular purpose, and non-infringement of intellectual property rights. + * + * Important Notice + * + * Nuvoton Products are neither intended nor warranted for usage in systems or equipment, + * any malfunction or failure of which may cause loss of human life, bodily injury or severe + * property damage. Such applications are deemed, "Insecure Usage". + * + * Insecure usage includes, but is not limited to: equipment for surgical implementation, + * atomic energy control instruments, airplane or spaceship instruments, the control or + * operation of dynamic, brake or safety systems designed for vehicular use, traffic signal + * instruments, all types of safety devices, and other applications intended to support or + * sustain life. + * + * All Insecure Usage shall be made at customer's risk, and in the event that third parties + * lay claims to Nuvoton as a result of customer's Insecure Usage, customer shall indemnify + * the damages and liabilities thus incurred by Nuvoton. + * + * Please note that all data and specifications are subject to change without notice. All the + * trademarks of products and companies mentioned in this document belong to their respective + * owners. + * + * Copyright Notice + * + * Copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. + */ + +#ifndef __N9H30_H__ + #define __N9H30_H__ + + #include + + /** @addtogroup N9H30_PERIPHERAL_MEM_MAP N9H30 Peripheral Memory Base + Memory Mapped Structure for N9H30 Peripheral + @{ + */ + + /*!< AHB peripherals */ + #define SYS_BA 0xB0000000 /*!< System Global Control */ + #define CLK_BA 0xB0000200 /*!< Clock Control */ + #define EBI_BA 0xB0001000 /*!< EBI Control */ + #define SDIC_BA 0xB0001800 /*!< SDRAM (SDR/DDR/DDR2) Control */ + #define EMC0_BA 0xB0002000 /*!< Ethernet MAC 0 Control */ + #define EMC1_BA 0xB0003000 /*!< Ethernet MAC 1 Control */ + #define GDMA_BA 0xB0004000 /*!< GDMA control */ + #define USBH_BA 0xB0005000 /*!< USB Host EHCI Control */ + #define USBD_BA 0xB0006000 /*!< USB Device Control */ + #define USBO_BA 0xB0007000 /*!< OHCI USB Host Control */ + #define LCM_BA 0xB0008000 /*!< Display, LCM Interface */ + #define ACTL_BA 0xB0009000 /*!< Audio Control */ + #define JPEG_BA 0xB000A000 /*!< JPEG Engine Control */ + #define GE_BA 0xB000B000 /*!< 2-D Graphic Engine */ + #define SDH_BA 0xB000C000 /*!< SD/SDIO Host Controller */ + #define FMI_BA 0xB000D000 /*!< Flash Memory Card Interface */ + #define CAP_BA 0xB000E000 /*!< Sensor (Capture) Interface Control */ + #define CRPT_BA 0xB000F000 /*!< Crypto Engine Control */ + + /*!< APB peripherals */ + #define UART0_BA 0xB8000000 /*!< UART0 Control */ + #define UART1_BA 0xB8000100 /*!< UART1 Control (High-Speed UART) */ + #define UART2_BA 0xB8000200 /*!< UART2 Control (High-Speed UART) */ + #define UART3_BA 0xB8000300 /*!< UART3 Control */ + #define UART4_BA 0xB8000400 /*!< UART4 Control (High-Speed UART) */ + #define UART5_BA 0xB8000500 /*!< UART5 Control */ + #define UART6_BA 0xB8000600 /*!< UART6 Control (High-Speed UART) */ + #define UART7_BA 0xB8000700 /*!< UART7 Control */ + #define UART8_BA 0xB8000800 /*!< UART8 Control (High-Speed UART) */ + #define UART9_BA 0xB8000900 /*!< UART9 Control */ + #define UARTA_BA 0xB8000A00 /*!< UARTA Control (High-Speed UART) */ + #define TMR0_BA 0xB8001000 /*!< Timer 0 */ + #define TMR1_BA 0xB8001010 /*!< Timer 1 */ + #define TMR2_BA 0xB8001020 /*!< Timer 2 */ + #define TMR3_BA 0xB8001030 /*!< Timer 3 */ + #define TMR4_BA 0xB8001040 /*!< Timer 4 */ + #define ETMR0_BA 0xB8001400 /*!< Enhanced Timer 0 */ + #define ETMR1_BA 0xB8001500 /*!< Enhanced Timer 1 */ + #define ETMR2_BA 0xB8001600 /*!< Enhanced Timer 2 */ + #define ETMR3_BA 0xB8001700 /*!< Enhanced Timer 3 */ + #define WDT_BA 0xB8001800 /*!< Watch Dog Timer */ + #define WWDT_BA 0xB8001900 /*!< Window Watch Dog Timer */ + #define AIC_BA 0xB8002000 /*!< Interrupt Controller */ + #define GPIO_BA 0xB8003000 /*!< GPIO Control */ + #define RTC_BA 0xB8004000 /*!< Real Time Clock Control */ + #define SC0_BA 0xB8005000 /*!< Smart Card 0 Control */ + #define SC1_BA 0xB8005400 /*!< Smart Card 1 Control */ + #define I2C0_BA 0xB8006000 /*!< I2C 0 Control */ + #define I2C1_BA 0xB8006100 /*!< I2C 1 Control */ + #define SPI0_BA 0xB8006200 /*!< Serial Peripheral Interface 0 */ + #define SPI1_BA 0xB8006300 /*!< Serial Peripheral Interface 1 */ + #define PWM_BA 0xB8007000 /*!< Pulse Width Modulation (PWM) Control */ + #define ADC_BA 0xB800A000 /*!< ADC Control */ + #define CAN0_BA 0xB800B000 /*!< CAN 0 Control */ + #define CAN1_BA 0xB800B400 /*!< CAN 1 Control */ + #define MTP_BA 0xB800C000 /*!< MTP Control */ + + /*@}*/ /* end of group N9H30_PERIPHERAL_MEM_MAP */ + + /******************************************************************************/ + /* Device Specific Peripheral registers structures */ + /******************************************************************************/ + /** @addtogroup N9H30_Peripherals N9H30 Control Register + N9H30 Device Specific Peripheral registers structures + @{ + */ + + /*---------------------- System Manger Controller -------------------------*/ + /** + @addtogroup SYS System Manger Controller(SYS) + Memory Mapped Structure for SYS Controller + @{ */ + + #define REG_SYS_PDID (SYS_BA+0x000) /*!< Product Identifier Register */ + #define REG_SYS_PWRON (SYS_BA+0x004) /*!< Power-On Setting Register */ + #define REG_SYS_ARBCON (SYS_BA+0x008) /*!< Arbitration Control Register */ + #define REG_SYS_LVRDCR (SYS_BA+0x020) /*!< Low Voltage Reset & Detect Control Register */ + #define REG_SYS_MISCFCR (SYS_BA+0x030) /*!< Miscellaneous Function Control Register */ + #define REG_SYS_MISCIER (SYS_BA+0x040) /*!< Miscellaneous Interrupt Enable Register */ + #define REG_SYS_MISCISR (SYS_BA+0x044) /*!< Miscellaneous Interrupt Status Register */ + #define REG_SYS_WKUPSER (SYS_BA+0x058) /*!< System Wakeup Source Enable Register */ + #define REG_SYS_WKUPSSR (SYS_BA+0x05C) /*!< System Wakeup Source Status Register */ + #define REG_SYS_AHBIPRST (SYS_BA+0x060) /*!< AHB IP Reset Control Register */ + #define REG_SYS_APBIPRST0 (SYS_BA+0x064) /*!< APB IP Reset Control Register 0 */ + #define REG_SYS_APBIPRST1 (SYS_BA+0x068) /*!< APB IP Reset Control Register 1 */ + #define REG_SYS_RSTSTS (SYS_BA+0x06C) /*!< Reset Source Active Status Register */ + #define REG_SYS_GPA_MFPL (SYS_BA+0x070) /*!< GPIOA Low Byte Multiple Function Control Register */ + #define REG_SYS_GPA_MFPH (SYS_BA+0x074) /*!< GPIOA High Byte Multiple Function Control Register */ + #define REG_SYS_GPB_MFPL (SYS_BA+0x078) /*!< GPIOB Low Byte Multiple Function Control Register */ + #define REG_SYS_GPB_MFPH (SYS_BA+0x07C) /*!< GPIOB High Byte Multiple Function Control Register */ + #define REG_SYS_GPC_MFPL (SYS_BA+0x080) /*!< GPIOC Low Byte Multiple Function Control Register */ + #define REG_SYS_GPC_MFPH (SYS_BA+0x084) /*!< GPIOC High Byte Multiple Function Control Register */ + #define REG_SYS_GPD_MFPL (SYS_BA+0x088) /*!< GPIOD Low Byte Multiple Function Control Register */ + #define REG_SYS_GPD_MFPH (SYS_BA+0x08C) /*!< GPIOD High Byte Multiple Function Control Register */ + #define REG_SYS_GPE_MFPL (SYS_BA+0x090) /*!< GPIOE Low Byte Multiple Function Control Register */ + #define REG_SYS_GPE_MFPH (SYS_BA+0x094) /*!< GPIOE High Byte Multiple Function Control Register */ + #define REG_SYS_GPF_MFPL (SYS_BA+0x098) /*!< GPIOF Low Byte Multiple Function Control Register */ + #define REG_SYS_GPF_MFPH (SYS_BA+0x09C) /*!< GPIOF High Byte Multiple Function Control Register */ + #define REG_SYS_GPG_MFPL (SYS_BA+0x0A0) /*!< GPIOG Low Byte Multiple Function Control Register */ + #define REG_SYS_GPG_MFPH (SYS_BA+0x0A4) /*!< GPIOG High Byte Multiple Function Control Register */ + #define REG_SYS_GPH_MFPL (SYS_BA+0x0A8) /*!< GPIOH Low Byte Multiple Function Control Register */ + #define REG_SYS_GPH_MFPH (SYS_BA+0x0AC) /*!< GPIOH High Byte Multiple Function Control Register */ + #define REG_SYS_GPI_MFPL (SYS_BA+0x0B0) /*!< GPIOI Low Byte Multiple Function Control Register */ + #define REG_SYS_GPI_MFPH (SYS_BA+0x0B4) /*!< GPIOI High Byte Multiple Function Control Register */ + #define REG_SYS_GPJ_MFPL (SYS_BA+0x0B8) /*!< GPIOJ Low Byte Multiple Function Control Register */ + #define REG_SYS_DDR_DSCTL (SYS_BA+0x0F0) /*!< DDR I/O Driving Strength Control Register */ + #define REG_SYS_PORDISCR (SYS_BA+0x100) /*!< Power-On-Reset Disable Control Register */ + #define REG_SYS_ICEDBGCR (SYS_BA+0x104) /*!< ICE Debug Interface Control Register */ + #define REG_SYS_ERRADDCR (SYS_BA+0x108) /*!< Error Response Address Control Regsiter */ + #define REG_SYS_REGWPCTL (SYS_BA+0x1FC) /*!< Register Write-Protection Control Register */ + + /**@}*/ /* end of SYS register group */ + + /*---------------------- System Clock Controller -------------------------*/ + /** + @addtogroup CLK System Clock Controller(CLK) + Memory Mapped Structure for CLK Controller + @{ */ + + #define REG_CLK_PMCON (CLK_BA+0x00) /*!< Power Management Control Register */ + #define REG_CLK_HCLKEN (CLK_BA+0x10) /*!< AHB IP Clock Enable Control Register */ + #define REG_CLK_PCLKEN0 (CLK_BA+0x18) /*!< APB IP Clock Enable Control Register 0 */ + #define REG_CLK_PCLKEN1 (CLK_BA+0x1C) /*!< APB IP Clock Enable Control Register 1 */ + #define REG_CLK_DIVCTL0 (CLK_BA+0x20) /*!< Clock Divider Control Register 0 */ + #define REG_CLK_DIVCTL1 (CLK_BA+0x24) /*!< Clock Divider Control Register 1 */ + #define REG_CLK_DIVCTL2 (CLK_BA+0x28) /*!< Clock Divider Control Register 2 */ + #define REG_CLK_DIVCTL3 (CLK_BA+0x2C) /*!< Clock Divider Control Register 3 */ + #define REG_CLK_DIVCTL4 (CLK_BA+0x30) /*!< Clock Divider Control Register 4 */ + #define REG_CLK_DIVCTL5 (CLK_BA+0x34) /*!< Clock Divider Control Register 5 */ + #define REG_CLK_DIVCTL6 (CLK_BA+0x38) /*!< Clock Divider Control Register 6 */ + #define REG_CLK_DIVCTL7 (CLK_BA+0x3C) /*!< Clock Divider Control Register 7 */ + #define REG_CLK_DIVCTL8 (CLK_BA+0x40) /*!< Clock Divider Control Register 8 */ + #define REG_CLK_DIVCTL9 (CLK_BA+0x44) /*!< Clock Divider Control Register 9 */ + #define REG_CLK_APLLCON (CLK_BA+0x60) /*!< APLL Control Register */ + #define REG_CLK_UPLLCON (CLK_BA+0x64) /*!< UPLL Control Register */ + #define REG_CLK_PLLSTBCNTR (CLK_BA+0x80) /*!< PLL Stable Counter and Test Clock Control Register */ + + /**@}*/ /* end of CLK register group */ + + + /*---------------------- External Bus Interface Controller -------------------------*/ + /** + @addtogroup EBI External Bus Interface Controller(EBI) + Memory Mapped Structure for EBI Controller + @{ */ + + #define REG_EBI_CTL (EBI_BA+0x000) /*!< EBI control register */ + #define REG_EBI_BNKCTL0 (EBI_BA+0x018) /*!< External I/O 0 control register */ + #define REG_EBI_BNKCTL1 (EBI_BA+0x01C) /*!< External I/O 1 control register */ + #define REG_EBI_BNKCTL2 (EBI_BA+0x020) /*!< External I/O 2 control register */ + #define REG_EBI_BNKCTL3 (EBI_BA+0x024) /*!< External I/O 3 control register */ + #define REG_EBI_BNKCTL4 (EBI_BA+0x028) /*!< External I/O 4 control register */ + + /**@}*/ /* end of EBI register group */ + + + /*---------------------- Ethernet MAC Controller -------------------------*/ + /** + @addtogroup EMAC Ethernet MAC Controller(EMAC) + Memory Mapped Structure for EMAC Controller + @{ */ + + #define REG_EMAC0_CAMCMR (EMC0_BA+0x000) /*!< CAM Command Register */ + #define REG_EMAC0_CAMEN (EMC0_BA+0x004) /*!< CAM Enable Register */ + #define REG_EMAC0_CAM0M (EMC0_BA+0x008) /*!< CAM0 Most Significant Word Register */ + #define REG_EMAC0_CAM0L (EMC0_BA+0x00c) /*!< CAM0 Least Significant Word Register */ + #define REG_EMAC0_CAMxM_Reg(x)(REG_EMAC0_CAM0M+(x)*0x8) /*!< CAMx Most Significant Word Register */ + #define REG_EMAC0_CAMxL_Reg(x)(REG_EMAC0_CAM0L+(x)*0x8) /*!< CAMx Least Significant Word Register */ + #define REG_EMAC0_TXDLSA (EMC0_BA+0x088) /*!< Transmit Descriptor Link List Start Address Register */ + #define REG_EMAC0_RXDLSA (EMC0_BA+0x08C) /*!< Receive Descriptor Link List Start Address Register */ + #define REG_EMAC0_MCMDR (EMC0_BA+0x090) /*!< MAC Command Register */ + #define REG_EMAC0_MIID (EMC0_BA+0x094) /*!< MII Management Data Register */ + #define REG_EMAC0_MIIDA (EMC0_BA+0x098) /*!< MII Management Control and Address Register */ + #define REG_EMAC0_FFTCR (EMC0_BA+0x09C) /*!< FIFO Threshold Control Register */ + #define REG_EMAC0_TSDR (EMC0_BA+0x0a0) /*!< Transmit Start Demand Register */ + #define REG_EMAC0_RSDR (EMC0_BA+0x0a4) /*!< Receive Start Demand Register */ + #define REG_EMAC0_DMARFC (EMC0_BA+0x0a8) /*!< Maximum Receive Frame Control Register */ + #define REG_EMAC0_MIEN (EMC0_BA+0x0ac) /*!< MAC Interrupt Enable Register */ + #define REG_EMAC0_MISTA (EMC0_BA+0x0b0) /*!< MAC Interrupt Status Register */ + #define REG_EMAC0_MGSTA (EMC0_BA+0x0b4) /*!< MAC General Status Register */ + #define REG_EMAC0_MPCNT (EMC0_BA+0x0b8) /*!< Missed Packet Count Register */ + #define REG_EMAC0_MRPC (EMC0_BA+0x0bc) /*!< MAC Receive Pause Count Register */ + #define REG_EMAC0_DMARFS (EMC0_BA+0x0c8) /*!< DMA Receive Frame Status Register */ + #define REG_EMAC0_CTXDSA (EMC0_BA+0x0cc) /*!< Current Transmit Descriptor Start Address Register */ + #define REG_EMAC0_CTXBSA (EMC0_BA+0x0d0) /*!< Current Transmit Buffer Start Address Register */ + #define REG_EMAC0_CRXDSA (EMC0_BA+0x0d4) /*!< Current Receive Descriptor Start Address Register */ + #define REG_EMAC0_CRXBSA (EMC0_BA+0x0d8) /*!< Current Receive Buffer Start Address Register */ + #define REG_EMAC0_TSCTL (EMC0_BA+0x100) /*!< Time Stamp Control Register */ + #define REG_EMAC0_TSSEC (EMC0_BA+0x110) /*!< Time Stamp Counter Second Register */ + #define REG_EMAC0_TSSUBSEC (EMC0_BA+0x114) /*!< Time Stamp Counter Sub Second Register */ + #define REG_EMAC0_TSINC (EMC0_BA+0x118) /*!< Time Stamp Increment Register */ + #define REG_EMAC0_TSADDEN (EMC0_BA+0x11c) /*!< Time Stamp Addend Register */ + #define REG_EMAC0_TSUPDSEC (EMC0_BA+0x120) /*!< Time Stamp Update Second Register */ + #define REG_EMAC0_TSUPDSUBSEC (EMC0_BA+0x124) /*!< Time Stamp Update Sub Second Register */ + #define REG_EMAC0_TSALMSEC (EMC0_BA+0x128) /*!< Time Stamp Alarm Second Register */ + #define REG_EMAC0_TSALMSUBSEC (EMC0_BA+0x12c) /*!< Time Stamp Alarm Sub Second Register */ + + #define REG_EMAC1_CAMCMR (EMC1_BA+0x000) /*!< CAM Command Register */ + #define REG_EMAC1_CAMEN (EMC1_BA+0x004) /*!< CAM Enable Register */ + #define REG_EMAC1_CAM0M (EMC1_BA+0x008) /*!< CAM0 Most Significant Word Register */ + #define REG_EMAC1_CAM0L (EMC1_BA+0x00c) /*!< CAM0 Least Significant Word Register */ + #define REG_EMAC1_CAMxM_Reg(x)(REG_EMAC1_CAM0M+(x)*0x8) /*!< CAMx Most Significant Word Register */ + #define REG_EMAC1_CAMxL_Reg(x)(REG_EMAC1_CAM0L+(x)*0x8) /*!< CAMx Least Significant Word Register */ + #define REG_EMAC1_TXDLSA (EMC1_BA+0x088) /*!< Transmit Descriptor Link List Start Address Register */ + #define REG_EMAC1_RXDLSA (EMC1_BA+0x08C) /*!< Receive Descriptor Link List Start Address Register */ + #define REG_EMAC1_MCMDR (EMC1_BA+0x090) /*!< MAC Command Register */ + #define REG_EMAC1_MIID (EMC1_BA+0x094) /*!< MII Management Data Register */ + #define REG_EMAC1_MIIDA (EMC1_BA+0x098) /*!< MII Management Control and Address Register */ + #define REG_EMAC1_FFTCR (EMC1_BA+0x09C) /*!< FIFO Threshold Control Register */ + #define REG_EMAC1_TSDR (EMC1_BA+0x0a0) /*!< Transmit Start Demand Register */ + #define REG_EMAC1_RSDR (EMC1_BA+0x0a4) /*!< Receive Start Demand Register */ + #define REG_EMAC1_DMARFC (EMC1_BA+0x0a8) /*!< Maximum Receive Frame Control Register */ + #define REG_EMAC1_MIEN (EMC1_BA+0x0ac) /*!< MAC Interrupt Enable Register */ + #define REG_EMAC1_MISTA (EMC1_BA+0x0b0) /*!< MAC Interrupt Status Register */ + #define REG_EMAC1_MGSTA (EMC1_BA+0x0b4) /*!< MAC General Status Register */ + #define REG_EMAC1_MPCNT (EMC1_BA+0x0b8) /*!< Missed Packet Count Register */ + #define REG_EMAC1_MRPC (EMC1_BA+0x0bc) /*!< MAC Receive Pause Count Register */ + #define REG_EMAC1_DMARFS (EMC1_BA+0x0c8) /*!< DMA Receive Frame Status Register */ + #define REG_EMAC1_CTXDSA (EMC1_BA+0x0cc) /*!< Current Transmit Descriptor Start Address Register */ + #define REG_EMAC1_CTXBSA (EMC1_BA+0x0d0) /*!< Current Transmit Buffer Start Address Register */ + #define REG_EMAC1_CRXDSA (EMC1_BA+0x0d4) /*!< Current Receive Descriptor Start Address Register */ + #define REG_EMAC1_CRXBSA (EMC1_BA+0x0d8) /*!< Current Receive Buffer Start Address Register */ + #define REG_EMAC1_TSCTL (EMC1_BA+0x100) /*!< Time Stamp Control Register */ + #define REG_EMAC1_TSSEC (EMC1_BA+0x110) /*!< Time Stamp Counter Second Register */ + #define REG_EMAC1_TSSUBSEC (EMC1_BA+0x114) /*!< Time Stamp Counter Sub Second Register */ + #define REG_EMAC1_TSINC (EMC1_BA+0x118) /*!< Time Stamp Increment Register */ + #define REG_EMAC1_TSADDEN (EMC1_BA+0x11c) /*!< Time Stamp Addend Register */ + #define REG_EMAC1_TSUPDSEC (EMC1_BA+0x120) /*!< Time Stamp Update Second Register */ + #define REG_EMAC1_TSUPDSUBSEC (EMC1_BA+0x124) /*!< Time Stamp Update Sub Second Register */ + #define REG_EMAC1_TSALMSEC (EMC1_BA+0x128) /*!< Time Stamp Alarm Second Register */ + #define REG_EMAC1_TSALMSUBSEC (EMC1_BA+0x12c) /*!< Time Stamp Alarm Sub Second Register */ + + /**@}*/ /* end of EMAC register group */ + + /*---------------------- General Direct Memory Access Controller -------------------------*/ + /** + @addtogroup GDMA General Direct Memory Access Controller(GDMA) + Memory Mapped Structure for GDMA Controller + @{ */ + + #define REG_GDMA_CTL0 (GDMA_BA+0x000) /*!< Channel 0 Control Register */ + #define REG_GDMA_SRCB0 (GDMA_BA+0x004) /*!< Channel 0 Source Base Address Register */ + #define REG_GDMA_DSTB0 (GDMA_BA+0x008) /*!< Channel 0 Destination Base Address Register */ + #define REG_GDMA_TCNT0 (GDMA_BA+0x00C) /*!< Channel 0 Transfer Count Register */ + #define REG_GDMA_CSRC0 (GDMA_BA+0x010) /*!< Channel 0 Current Source Address Register */ + #define REG_GDMA_CDST0 (GDMA_BA+0x014) /*!< Channel 0 Current Destination Address Register */ + #define REG_GDMA_CTCNT0 (GDMA_BA+0x018) /*!< Channel 0 Current Transfer Count Register */ + #define REG_GDMA_DADR0 (GDMA_BA+0x01C) /*!< Channel 0 Descriptor Address Register */ + #define REG_GDMA_CTL1 (GDMA_BA+0x020) /*!< Channel 1 Control Register */ + #define REG_GDMA_SRCB1 (GDMA_BA+0x024) /*!< Channel 1 Source Base Address Register */ + #define REG_GDMA_DSTB1 (GDMA_BA+0x028) /*!< Channel 1 Destination Base Address Register */ + #define REG_GDMA_TCNT1 (GDMA_BA+0x02C) /*!< Channel 1 Transfer Count Register */ + #define REG_GDMA_CSRC1 (GDMA_BA+0x030) /*!< Channel 1 Current Source Address Register */ + #define REG_GDMA_CDST1 (GDMA_BA+0x034) /*!< Channel 1 Current Destination Address Register */ + #define REG_GDMA_CTCNT1 (GDMA_BA+0x038) /*!< Channel 1 Current Transfer Count Register */ + #define REG_GDMA_DADR1 (GDMA_BA+0x03C) /*!< Channel 1 Descriptor Address Register */ + #define REG_GDMA_INTBUF0 (GDMA_BA+0x080) /*!< GDMA Internal Buffer Word 0 */ + #define REG_GDMA_INTBUF1 (GDMA_BA+0x084) /*!< GDMA Internal Buffer Word 1 */ + #define REG_GDMA_INTBUF2 (GDMA_BA+0x088) /*!< GDMA Internal Buffer Word 2 */ + #define REG_GDMA_INTBUF3 (GDMA_BA+0x08C) /*!< GDMA Internal Buffer Word 3 */ + #define REG_GDMA_INTBUF4 (GDMA_BA+0x090) /*!< GDMA Internal Buffer Word 4 */ + #define REG_GDMA_INTBUF5 (GDMA_BA+0x094) /*!< GDMA Internal Buffer Word 5 */ + #define REG_GDMA_INTBUF6 (GDMA_BA+0x098) /*!< GDMA Internal Buffer Word 6 */ + #define REG_GDMA_INTBUF7 (GDMA_BA+0x09C) /*!< GDMA Internal Buffer Word 7 */ + #define REG_GDMA_INTCS (GDMA_BA+0x0A0) /*!< Interrupt Control and Status Register */ + + /**@}*/ /* end of GDMA register group */ + + + + /*---------------------- USB Device Controller -------------------------*/ + /** + @addtogroup USBD USB Device Controller(USBD) + Memory Mapped Structure for USBD Controller + @{ */ + #define REG_USBD_GINTSTS (USBD_BA+0x00) /*!< Interrupt Status Low Register */ + #define REG_USBD_GINTEN (USBD_BA+0x08) /*!< Interrupt Enable Low Register */ + #define REG_USBD_BUSINTSTS (USBD_BA+0x10) /*!< USB Bus Interrupt Status Register */ + #define REG_USBD_BUSINTEN (USBD_BA+0x14) /*!< USB Bus Interrupt Enable Register */ + #define REG_USBD_OPER (USBD_BA+0x18) /*!< USB Operational Register */ + #define REG_USBD_FRAMECNT (USBD_BA+0x1C) /*!< USB Frame Count Register */ + #define REG_USBD_FADDR (USBD_BA+0x20) /*!< USB Function Address Register */ + #define REG_USBD_TEST (USBD_BA+0x24) /*!< USB Test Mode Register */ + #define REG_USBD_CEPDAT (USBD_BA+0x28) /*!< Control-ep data buffer register */ + #define REG_USBD_CEPCTL (USBD_BA+0x2C) /*!< Control-ep control and status register */ + #define REG_USBD_CEPINTEN (USBD_BA+0x30) /*!< Control-ep interrupt enable register */ + #define REG_USBD_CEPINTSTS (USBD_BA+0x34) /*!< Control-ep interrupt status register */ + #define REG_USBD_CEPTXCNT (USBD_BA+0x38) /*!< In-transfer data count register */ + #define REG_USBD_CEPRXCNT (USBD_BA+0x3C) /*!< Out-transfer data count register */ + #define REG_USBD_CEPDATCNT (USBD_BA+0x40) /*!< Control-ep data count register */ + #define REG_USBD_SETUP1_0 (USBD_BA+0x44) /*!< Setup byte1 & byte0 register */ + #define REG_USBD_SETUP3_2 (USBD_BA+0x48) /*!< Setup byte3 & byte2 register */ + #define REG_USBD_SETUP5_4 (USBD_BA+0x4C) /*!< Setup byte5 & byte4 register */ + #define REG_USBD_SETUP7_6 (USBD_BA+0x50) /*!< Setup byte7 & byte6 register */ + #define REG_USBD_CEPBUFSTART (USBD_BA+0x54) /*!< Control-ep ram start address register */ + #define REG_USBD_CEPBUFEND (USBD_BA+0x58) /*!< Control-ep ram end address register */ + #define REG_USBD_DMACTL (USBD_BA+0x5C) /*!< Dma control and status register */ + #define REG_USBD_DMACNT (USBD_BA+0x60) /*!< Dma count register */ + + #define REG_USBD_EPADAT (USBD_BA+0x64) /*!< Endpoint A data buffer register */ + #define REG_USBD_EPAINTSTS (USBD_BA+0x68) /*!< Endpoint A interrupt status register */ + #define REG_USBD_EPAINTEN (USBD_BA+0x6C) /*!< Endpoint A interrupt enable register */ + #define REG_USBD_EPADATCNT (USBD_BA+0x70) /*!< Data count available in endpoint A buffer */ + #define REG_USBD_EPARSPCTL (USBD_BA+0x74) /*!< Endpoint A response register set/clear */ + #define REG_USBD_EPAMPS (USBD_BA+0x78) /*!< Endpoint A max packet size register */ + #define REG_USBD_EPATXCNT (USBD_BA+0x7C) /*!< Endpoint A transfer count register */ + #define REG_USBD_EPACFG (USBD_BA+0x80) /*!< Endpoint A configuration register */ + #define REG_USBD_EPABUFSTART (USBD_BA+0x84) /*!< Endpoint A ram start address register */ + #define REG_USBD_EPABUFEND (USBD_BA+0x88) /*!< Endpoint A ram end address register */ + + #define REG_USBD_EPBDAT (USBD_BA+0x8C) /*!< Endpoint B data buffer register */ + #define REG_USBD_EPBINTSTS (USBD_BA+0x90) /*!< Endpoint B interrupt status register */ + #define REG_USBD_EPBINTEN (USBD_BA+0x94) /*!< Endpoint B interrupt enable register */ + #define REG_USBD_EPBDATCNT (USBD_BA+0x98) /*!< Data count available in endpoint B buffer */ + #define REG_USBD_EPBRSPCTL (USBD_BA+0x9C) /*!< Endpoint B response register set/clear */ + #define REG_USBD_EPBMPS (USBD_BA+0xA0) /*!< Endpoint B max packet size register */ + #define REG_USBD_EPBTXCNT (USBD_BA+0xA4) /*!< Endpoint B transfer count register */ + #define REG_USBD_EPBCFG (USBD_BA+0xA8) /*!< Endpoint B configuration register */ + #define REG_USBD_EPBBUFSTART (USBD_BA+0xAC) /*!< Endpoint B ram start address register */ + #define REG_USBD_EPBBUFEND (USBD_BA+0xB0) /*!< Endpoint B ram end address register */ + + #define REG_USBD_EPCDAT (USBD_BA+0xB4) /*!< Endpoint C data buffer register */ + #define REG_USBD_EPCINTSTS (USBD_BA+0xB8) /*!< Endpoint C interrupt status register */ + #define REG_USBD_EPCINTEN (USBD_BA+0xBC) /*!< Endpoint C interrupt enable register */ + #define REG_USBD_EPCDATCNT (USBD_BA+0xC0) /*!< Data count available in endpoint C buffer */ + #define REG_USBD_EPCRSPCTL (USBD_BA+0xC4) /*!< Endpoint C response register set/clear */ + #define REG_USBD_EPCMPS (USBD_BA+0xC8) /*!< Endpoint C max packet size register */ + #define REG_USBD_EPCTXCNT (USBD_BA+0xCC) /*!< Endpoint C transfer count register */ + #define REG_USBD_EPCCFG (USBD_BA+0xD0) /*!< Endpoint C configuration register */ + #define REG_USBD_EPCBUFSTART (USBD_BA+0xD4) /*!< Endpoint C ram start address register */ + #define REG_USBD_EPCBUFEND (USBD_BA+0xD8) /*!< Endpoint C ram end address register */ + + #define REG_USBD_EPDDAT (USBD_BA+0xDC) /*!< Endpoint D data buffer register */ + #define REG_USBD_EPDINTSTS (USBD_BA+0xE0) /*!< Endpoint D interrupt status register */ + #define REG_USBD_EPDINTEN (USBD_BA+0xE4) /*!< Endpoint D interrupt enable register */ + #define REG_USBD_EPDDATCNT (USBD_BA+0xE8) /*!< Data count available in endpoint D buffer */ + #define REG_USBD_EPDRSPCTL (USBD_BA+0xEC) /*!< Endpoint D response register set/clear */ + #define REG_USBD_EPDMPS (USBD_BA+0xF0) /*!< Endpoint D max packet size register */ + #define REG_USBD_EPDTXCNT (USBD_BA+0xF4) /*!< Endpoint D transfer count register */ + #define REG_USBD_EPDCFG (USBD_BA+0xF8) /*!< Endpoint D configuration register */ + #define REG_USBD_EPDBUFSTART (USBD_BA+0xFC) /*!< Endpoint D ram start address register */ + #define REG_USBD_EPDBUFEND (USBD_BA+0x100) /*!< Endpoint D ram end address register */ + + #define REG_USBD_EPEDAT (USBD_BA+0x104) /*!< Endpoint E data buffer register */ + #define REG_USBD_EPEINTSTS (USBD_BA+0x108) /*!< Endpoint E interrupt status register */ + #define REG_USBD_EPEINTEN (USBD_BA+0x10C) /*!< Endpoint E interrupt enable register */ + #define REG_USBD_EPEDATCNT (USBD_BA+0x110) /*!< Data count available in endpoint E buffer */ + #define REG_USBD_EPERSPCTL (USBD_BA+0x114) /*!< Endpoint E response register set/clear */ + #define REG_USBD_EPEMPS (USBD_BA+0x118) /*!< Endpoint E max packet size register */ + #define REG_USBD_EPETXCNT (USBD_BA+0x11C) /*!< Endpoint E transfer count register */ + #define REG_USBD_EPECFG (USBD_BA+0x120) /*!< Endpoint E configuration register */ + #define REG_USBD_EPEBUFSTART (USBD_BA+0x124) /*!< Endpoint E ram start address register */ + #define REG_USBD_EPEBUFEND (USBD_BA+0x128) /*!< Endpoint E ram end address register */ + + #define REG_USBD_EPFDAT (USBD_BA+0x12C) /*!< Endpoint F data buffer register */ + #define REG_USBD_EPFINTSTS (USBD_BA+0x130) /*!< Endpoint F interrupt status register */ + #define REG_USBD_EPFINTEN (USBD_BA+0x134) /*!< Endpoint F interrupt enable register */ + #define REG_USBD_EPFDATCNT (USBD_BA+0x138) /*!< Data count available in endpoint F buffer */ + #define REG_USBD_EPFRSPCTL (USBD_BA+0x13C) /*!< Endpoint F response register set/clear */ + #define REG_USBD_EPFMPS (USBD_BA+0x140) /*!< Endpoint F max packet size register */ + #define REG_USBD_EPFTXCNT (USBD_BA+0x144) /*!< Endpoint F transfer count register */ + #define REG_USBD_EPFCFG (USBD_BA+0x148) /*!< Endpoint F configuration register */ + #define REG_USBD_EPFBUFSTART (USBD_BA+0x14C) /*!< Endpoint F ram start address register */ + #define REG_USBD_EPFBUFEND (USBD_BA+0x150) /*!< Endpoint F ram end address register */ + + #define REG_USBD_EPGDAT (USBD_BA+0x154) /*!< Endpoint G data buffer register */ + #define REG_USBD_EPGINTSTS (USBD_BA+0x158) /*!< Endpoint G interrupt status register */ + #define REG_USBD_EPGINTEN (USBD_BA+0x15C) /*!< Endpoint G interrupt enable register */ + #define REG_USBD_EPGDATCNT (USBD_BA+0x160) /*!< Data count available in endpoint G buffer */ + #define REG_USBD_EPGRSPCTL (USBD_BA+0x164) /*!< Endpoint G response register set/clear */ + #define REG_USBD_EPGMPS (USBD_BA+0x168) /*!< Endpoint G max packet size register */ + #define REG_USBD_EPGTXCNT (USBD_BA+0x16C) /*!< Endpoint G transfer count register */ + #define REG_USBD_EPGCFG (USBD_BA+0x170) /*!< Endpoint G configuration register */ + #define REG_USBD_EPGBUFSTART (USBD_BA+0x174) /*!< Endpoint G ram start address register */ + #define REG_USBD_EPGBUFEND (USBD_BA+0x178) /*!< Endpoint G ram end address register */ + + #define REG_USBD_EPHDAT (USBD_BA+0x17C) /*!< Endpoint H data buffer register */ + #define REG_USBD_EPHINTSTS (USBD_BA+0x180) /*!< Endpoint H interrupt status register */ + #define REG_USBD_EPHINTEN (USBD_BA+0x184) /*!< Endpoint H interrupt enable register */ + #define REG_USBD_EPHDATCNT (USBD_BA+0x188) /*!< Data count available in endpoint H buffer */ + #define REG_USBD_EPHRSPCTL (USBD_BA+0x18C) /*!< Endpoint H response register set/clear */ + #define REG_USBD_EPHMPS (USBD_BA+0x190) /*!< Endpoint H max packet size register */ + #define REG_USBD_EPHTXCNT (USBD_BA+0x194) /*!< Endpoint H transfer count register */ + #define REG_USBD_EPHCFG (USBD_BA+0x198) /*!< Endpoint H configuration register */ + #define REG_USBD_EPHBUFSTART (USBD_BA+0x19C) /*!< Endpoint H ram start address register */ + #define REG_USBD_EPHBUFEND (USBD_BA+0x1A0) /*!< Endpoint H ram end address register */ + + #define REG_USBD_EPIDAT (USBD_BA+0x1A4) /*!< Endpoint I data buffer register */ + #define REG_USBD_EPIINTSTS (USBD_BA+0x1A8) /*!< Endpoint I interrupt status register */ + #define REG_USBD_EPIINTEN (USBD_BA+0x1AC) /*!< Endpoint I interrupt enable register */ + #define REG_USBD_EPIDATCNT (USBD_BA+0x1B0) /*!< Data count available in endpoint I buffer */ + #define REG_USBD_EPIRSPCTL (USBD_BA+0x1B4) /*!< Endpoint I response register set/clear */ + #define REG_USBD_EPIMPS (USBD_BA+0x1B8) /*!< Endpoint I max packet size register */ + #define REG_USBD_EPITXCNT (USBD_BA+0x1BC) /*!< Endpoint I transfer count register */ + #define REG_USBD_EPICFG (USBD_BA+0x1C0) /*!< Endpoint I configuration register */ + #define REG_USBD_EPIBUFSTART (USBD_BA+0x1C4) /*!< Endpoint I ram start address register */ + #define REG_USBD_EPIBUFEND (USBD_BA+0x1C8) /*!< Endpoint I ram end address register */ + + #define REG_USBD_EPJDAT (USBD_BA+0x1CC) /*!< Endpoint J data buffer register */ + #define REG_USBD_EPJINTSTS (USBD_BA+0x1D0) /*!< Endpoint J interrupt status register */ + #define REG_USBD_EPJINTEN (USBD_BA+0x1D4) /*!< Endpoint J interrupt enable register */ + #define REG_USBD_EPJDATCNT (USBD_BA+0x1D8) /*!< Data count available in endpoint J buffer */ + #define REG_USBD_EPJRSPCTL (USBD_BA+0x1DC) /*!< Endpoint J response register set/clear */ + #define REG_USBD_EPJMPS (USBD_BA+0x1E0) /*!< Endpoint J max packet size register */ + #define REG_USBD_EPJTXCNT (USBD_BA+0x1E4) /*!< Endpoint J transfer count register */ + #define REG_USBD_EPJCFG (USBD_BA+0x1E8) /*!< Endpoint J configuration register */ + #define REG_USBD_EPJBUFSTART (USBD_BA+0x1EC) /*!< Endpoint J ram start address register */ + #define REG_USBD_EPJBUFEND (USBD_BA+0x1F0) /*!< Endpoint J ram end address register */ + + #define REG_USBD_EPKDAT (USBD_BA+0x1F4) /*!< Endpoint K data buffer register */ + #define REG_USBD_EPKINTSTS (USBD_BA+0x1F8) /*!< Endpoint K interrupt status register */ + #define REG_USBD_EPKINTEN (USBD_BA+0x1FC) /*!< Endpoint K interrupt enable register */ + #define REG_USBD_EPKDATCNT (USBD_BA+0x200) /*!< Data count available in endpoint K buffer */ + #define REG_USBD_EPKRSPCTL (USBD_BA+0x204) /*!< Endpoint K response register set/clear */ + #define REG_USBD_EPKMPS (USBD_BA+0x208) /*!< Endpoint K max packet size register */ + #define REG_USBD_EPKTXCNT (USBD_BA+0x20C) /*!< Endpoint K transfer count register */ + #define REG_USBD_EPKCFG (USBD_BA+0x210) /*!< Endpoint K configuration register */ + #define REG_USBD_EPKBUFSTART (USBD_BA+0x214) /*!< Endpoint K ram start address register */ + #define REG_USBD_EPKBUFEND (USBD_BA+0x218) /*!< Endpoint K ram end address register */ + + #define REG_USBD_EPLDAT (USBD_BA+0x21C) /*!< Endpoint L data buffer register */ + #define REG_USBD_EPLINTSTS (USBD_BA+0x220) /*!< Endpoint L interrupt status register */ + #define REG_USBD_EPLINTEN (USBD_BA+0x224) /*!< Endpoint L interrupt enable register */ + #define REG_USBD_EPLDATCNT (USBD_BA+0x228) /*!< Data count available in endpoint L buffer */ + #define REG_USBD_EPLRSPCTL (USBD_BA+0x22C) /*!< Endpoint L response register set/clear */ + #define REG_USBD_EPLMPS (USBD_BA+0x230) /*!< Endpoint L max packet size register */ + #define REG_USBD_EPLTXCNT (USBD_BA+0x234) /*!< Endpoint L transfer count register */ + #define REG_USBD_EPLCFG (USBD_BA+0x238) /*!< Endpoint L configuration register */ + #define REG_USBD_EPLBUFSTART (USBD_BA+0x23C) /*!< Endpoint L ram start address register */ + #define REG_USBD_EPLBUFEND (USBD_BA+0x240) /*!< Endpoint L ram end address register */ + #define REG_USBD_DMAADDR (USBD_BA+0x700) /*!< AHB_DMA address register */ + #define REG_USBD_PHYCTL (USBD_BA+0x704) /*!< USB PHY control register */ + + /**@}*/ /* end of USBD register group */ + + + /*---------------------- LCD Display Interface Controller -------------------------*/ + /** + @addtogroup LCM LCD Display Interface Controller(LCM) + Memory Mapped Structure for LCM Controller + @{ */ + + #define REG_LCM_DCCS (LCM_BA+0x00) /*!< Display Controller Control/Status Register */ + #define REG_LCM_DEV_CTRL (LCM_BA+0x04) /*!< Display Output Device Control Register */ + #define REG_LCM_MPU_CMD (LCM_BA+0x08) /*!< MPU-Interface LCD Write Command */ + #define REG_LCM_INT_CS (LCM_BA+0x0c) /*!< Interrupt Control/Status Register */ + #define REG_LCM_CRTC_SIZE (LCM_BA+0x10) /*!< CRTC Display Size Control Register */ + #define REG_LCM_CRTC_DEND (LCM_BA+0x14) /*!< CRTC Display Enable End */ + #define REG_LCM_CRTC_HR (LCM_BA+0x18) /*!< CRTC Internal Horizontal Retrace Control Register */ + #define REG_LCM_CRTC_HSYNC (LCM_BA+0x1C) /*!< CRTC Horizontal Sync Control Register */ + #define REG_LCM_CRTC_VR (LCM_BA+0x20) /*!< CRTC Internal Vertical Retrace Control Register */ + #define REG_LCM_VA_BADDR0 (LCM_BA+0x24) /*!< Video Stream Frame Buffer-0 Starting Address */ + #define REG_LCM_VA_BADDR1 (LCM_BA+0x28) /*!< Video Stream Frame Buffer-1 Starting Address */ + #define REG_LCM_VA_FBCTRL (LCM_BA+0x2C) /*!< Video Stream Frame Buffer Control Register */ + #define REG_LCM_VA_SCALE (LCM_BA+0x30) /*!< Video Stream Scaling Control Register */ + #define REG_LCM_VA_WIN (LCM_BA+0x38) /*!< Image Stream Active Window Coordinates */ + #define REG_LCM_VA_STUFF (LCM_BA+0x3C) /*!< Image Stream Stuff Pixel */ + #define REG_LCM_OSD_WINS (LCM_BA+0x40) /*!< OSD Window Starting Coordinates */ + #define REG_LCM_OSD_WINE (LCM_BA+0x44) /*!< OSD Window Ending Coordinates */ + #define REG_LCM_OSD_BADDR (LCM_BA+0x48) /*!< OSD Stream Frame Buffer Starting Address */ + #define REG_LCM_OSD_FBCTRL (LCM_BA+0x4c) /*!< OSD Stream Frame Buffer Control Register */ + #define REG_LCM_OSD_OVERLAY (LCM_BA+0x50) /*!< OSD Overlay Control Register */ + #define REG_LCM_OSD_CKEY (LCM_BA+0x54) /*!< OSD Overlay Color-Key Pattern Register */ + #define REG_LCM_OSD_CMASK (LCM_BA+0x58) /*!< OSD Overlay Color-Key Mask Register */ + #define REG_LCM_OSD_SKIP1 (LCM_BA+0x5C) /*!< OSD Window Skip1 Register */ + #define REG_LCM_OSD_SKIP2 (LCM_BA+0x60) /*!< OSD Window Skip2 Register */ + #define REG_LCM_OSD_SCALE (LCM_BA+0x64) /*!< OSD horizontal up scaling control register */ + #define REG_LCM_MPU_VSYNC (LCM_BA+0x68) /*!< MPU Vsync control register */ + #define REG_LCM_HC_CTRL (LCM_BA+0x6C) /*!< Hardware cursor control Register */ + #define REG_LCM_HC_POS (LCM_BA+0x70) /*!< Hardware cursot tip point potison on va picture */ + #define REG_LCM_HC_WBCTRL (LCM_BA+0x74) /*!< Hardware Cursor Window Buffer Control Register */ + #define REG_LCM_HC_BADDR (LCM_BA+0x78) /*!< Hardware cursor memory base address register */ + #define REG_LCM_HC_COLOR0 (LCM_BA+0x7C) /*!< Hardware cursor color ram register mapped to bpp = 0 */ + #define REG_LCM_HC_COLOR1 (LCM_BA+0x80) /*!< Hardware cursor color ram register mapped to bpp = 1 */ + #define REG_LCM_HC_COLOR2 (LCM_BA+0x84) /*!< Hardware cursor color ram register mapped to bpp = 2 */ + #define REG_LCM_HC_COLOR3 (LCM_BA+0x88) /*!< Hardware cursor color ram register mapped to bpp = 3 */ + + /**@}*/ /* end of LCM register group */ + + + /*---------------------- I2S Interface Controller -------------------------*/ + /** + @addtogroup I2S I2S Interface Controller(I2S) + Memory Mapped Structure for I2S Controller + @{ */ + + #define REG_ACTL_CON (ACTL_BA+0x00) /*!< Audio controller control register */ + #define REG_ACTL_RESET (ACTL_BA+0x04) /*!< Sub block reset control register */ + #define REG_ACTL_RDESB (ACTL_BA+0x08) /*!< DMA destination base address register for record */ + #define REG_ACTL_RDES_LENGTH (ACTL_BA+0x0C) /*!< DMA destination length register for record */ + #define REG_ACTL_RDESC (ACTL_BA+0x10) /*!< DMA destination current address for record */ + #define REG_ACTL_PDESB (ACTL_BA+0x14) /*!< DMA destination current address for play */ + #define REG_ACTL_PDES_LENGTH (ACTL_BA+0x18) /*!< DMA destination length register for play */ + #define REG_ACTL_PDESC (ACTL_BA+0x1C) /*!< DMA destination current address register for play */ + #define REG_ACTL_RSR (ACTL_BA+0x20) /*!< Record status register */ + #define REG_ACTL_PSR (ACTL_BA+0x24) /*!< Play status register */ + #define REG_ACTL_I2SCON (ACTL_BA+0x28) /*!< I2S control register */ + #define REG_ACTL_COUNTER (ACTL_BA+0x2C) /*!< DMA count down values */ + #define REG_ACTL_PCMCON (ACTL_BA+0x30) /*!< PCM interface control register */ + #define REG_ACTL_PCMS1ST (ACTL_BA+0x34) /*!< PCM interface slot1 start register */ + #define REG_ACTL_PCMS2ST (ACTL_BA+0x38) /*!< PCM interface slot2 start register */ + #define REG_ACTL_RDESB2 (ACTL_BA+0x40) /*!< DMA destination base address register for record right channel */ + #define REG_ACTL_PDESB2 (ACTL_BA+0x44) /*!< DMA destination base address register for play right channel */ + + /**@}*/ /* end of I2S register group */ + + /*---------------------- 2D Graphic Engine -------------------------*/ + /** + @addtogroup GE2D 2D Graphic Engine(GE2D) + Memory Mapped Structure for GE2D Controller + @{ */ + + #define REG_GE2D_TRG (GE_BA+0x00) /*!< Graphic Engine Trigger Control Register */ + #define REG_GE2D_XYSORG (GE_BA+0x04) /*!< Graphic Engine XY Mode Source Origin Starting Register */ + #define REG_GE2D_TCNTVHSF (GE_BA+0x08) /*!< Graphic Engine Tile Width/Height or V/H Scale Factor N/M */ + #define REG_GE2D_XYRRP (GE_BA+0x0C) /*!< Graphic Engine Rotate Reference Point XY Address */ + #define REG_GE2D_INTSTS (GE_BA+0x10) /*!< Graphic Engine Interrupt Status Register */ + #define REG_GE2D_PATSA (GE_BA+0x14) /*!< Graphic Engine Pattern Location Starting Address Register */ + #define REG_GE2D_BETSC (GE_BA+0x18) /*!< GE Bresenham Error Term Stepping Constant Register */ + #define REG_GE2D_BIEPC (GE_BA+0x1C) /*!< GE Bresenham Initial Error, Pixel Count Major M Register */ + #define REG_GE2D_CTL (GE_BA+0x20) /*!< Graphic Engine Control Register */ + #define REG_GE2D_BGCOLR (GE_BA+0x24) /*!< Graphic Engine Background Color Register */ + #define REG_GE2D_FGCOLR (GE_BA+0x28) /*!< Graphic Engine Foreground Color Register */ + #define REG_GE2D_TRNSCOLR (GE_BA+0x2C) /*!< Graphic Engine Transparency Color Register */ + #define REG_GE2D_TCMSK (GE_BA+0x30) /*!< Graphic Engine Transparency Color Mask Register */ + #define REG_GE2D_XYDORG (GE_BA+0x34) /*!< Graphic Engine XY Mode Display Origin Starting Register */ + #define REG_GE2D_SDPITCH (GE_BA+0x38) /*!< Graphic Engine Source/Destination Pitch Register */ + #define REG_GE2D_SRCSPA (GE_BA+0x3C) /*!< Graphic Engine Source Start XY/Linear Address Register */ + #define REG_GE2D_DSTSPA (GE_BA+0x40) /*!< Graphic Engine Destination Start XY/Linear Register */ + #define REG_GE2D_RTGLSZ (GE_BA+0x44) /*!< Graphic Engine Dimension XY/Linear Register */ + #define REG_GE2D_CLPBTL (GE_BA+0x48) /*!< Graphic Engine Clipping Boundary Top/Left Register */ + #define REG_GE2D_CLPBBR (GE_BA+0x4C) /*!< Graphic Engine Clipping Boundary Bottom/Right Register */ + #define REG_GE2D_PTNA (GE_BA+0x50) /*!< Graphic Engine Pattern A Register */ + #define REG_GE2D_PTNB (GE_BA+0x54) /*!< Graphic Engine Pattern B Register */ + #define REG_GE2D_WRPLNMSK (GE_BA+0x58) /*!< Graphic Engine Write Plane Mask Register */ + #define REG_GE2D_MISCTL (GE_BA+0x5C) /*!< Graphic Engine Miscellaneous Control Register */ + #define REG_GE2D_GEHBDW0 (GE_BA+0x60) /*!< Graphic Engine HostBLT data Port 0 Register */ + #define REG_GE2D_GEHBDW1 (GE_BA+0x64) /*!< Graphic Engine HostBLT data Port 1 Register */ + #define REG_GE2D_GEHBDW2 (GE_BA+0x68) /*!< Graphic Engine HostBLT data Port 2 Register */ + #define REG_GE2D_GEHBDW3 (GE_BA+0x6C) /*!< Graphic Engine HostBLT data Port 3 Register */ + #define REG_GE2D_GEHBDW4 (GE_BA+0x70) /*!< Graphic Engine HostBLT data Port 4 Register */ + #define REG_GE2D_GEHBDW5 (GE_BA+0x74) /*!< Graphic Engine HostBLT data Port 5 Register */ + #define REG_GE2D_GEHBDW6 (GE_BA+0x78) /*!< Graphic Engine HostBLT data Port 6 Register */ + #define REG_GE2D_GEHBDW7 (GE_BA+0x7C) /*!< Graphic Engine HostBLT data Port 7 Register */ + + /**@}*/ /* end of GE2D register group */ + + /*---------------------- Flash Memory Interface -------------------------*/ + /** + @addtogroup FMI Flash Memory Interface(FMI) + Memory Mapped Structure for FMI Controller + @{ */ + + /* DMAC Control Registers*/ + #define REG_FMI_BUFFER (FMI_BA+0x000) /*!< FMI Embedded Buffer Word */ + #define REG_FMI_DMACTL (FMI_BA+0x400) /*!< FMI DMA Control Register */ + #define REG_FMI_DMASA (FMI_BA+0x408) /*!< FMI DMA Transfer Starting Address Register */ + #define REG_FMI_DMABCNT (FMI_BA+0x40C) /*!< FMI DMA Transfer Byte Count Register */ + #define REG_FMI_DMAINTEN (FMI_BA+0x410) /*!< FMI DMA Interrupt Enable Register */ + #define REG_FMI_DMAINTSTS (FMI_BA+0x414) /*!< FMI DMA Interrupt Status Register */ + + #define REG_FMI_CTL (FMI_BA+0x800) /*!< Global Control and Status Register */ + #define REG_FMI_INTEN (FMI_BA+0x804) /*!< Global Interrupt Control Register */ + #define REG_FMI_INTSTS (FMI_BA+0x808) /*!< Global Interrupt Status Register */ + + /* eMMC Registers */ + #define REG_FMI_EMMCCTL (FMI_BA+0x820) /*!< eMMC control and status register */ + #define REG_FMI_EMMCCMD (FMI_BA+0x824) /*!< eMMC command argument register */ + #define REG_FMI_EMMCINTEN (FMI_BA+0x828) /*!< eMMC interrupt enable register */ + #define REG_FMI_EMMCINTSTS (FMI_BA+0x82C) /*!< eMMC interrupt status register */ + #define REG_FMI_EMMCRESP0 (FMI_BA+0x830) /*!< eMMC receive response token register 0 */ + #define REG_FMI_EMMCRESP1 (FMI_BA+0x834) /*!< eMMC receive response token register 1 */ + #define REG_FMI_EMMCBLEN (FMI_BA+0x838) /*!< eMMC block length register */ + #define REG_FMI_EMMCTOUT (FMI_BA+0x83C) /*!< eMMC block length register */ + + /* NAND-type Flash Registers */ + #define REG_NANDCTL (FMI_BA+0x8A0) /*!< NAND Flash Control and Status Register */ + #define REG_NANDTMCTL (FMI_BA+0x8A4) /*!< NAND Flash Timing Control Register */ + #define REG_NANDINTEN (FMI_BA+0x8A8) /*!< NAND Flash Interrupt Control Register */ + #define REG_NANDINTSTS (FMI_BA+0x8AC) /*!< NAND Flash Interrupt Status Register */ + #define REG_NANDCMD (FMI_BA+0x8B0) /*!< NAND Flash Command Port Register */ + #define REG_NANDADDR (FMI_BA+0x8B4) /*!< NAND Flash Address Port Register */ + #define REG_NANDDATA (FMI_BA+0x8B8) /*!< NAND Flash Data Port Register */ + #define REG_NANDRACTL (FMI_BA+0x8BC) /*!< NAND Flash Redundant Area Control Register */ + #define REG_NANDECTL (FMI_BA+0x8C0) /*!< NAND Flash Extend Control Regsiter */ + #define REG_NANDECCES0 (FMI_BA+0x8D0) /*!< NAND Flash ECC Error Status 0 */ + #define REG_NANDECCES1 (FMI_BA+0x8D4) /*!< NAND Flash ECC Error Status 1 */ + #define REG_NANDECCES2 (FMI_BA+0x8D8) /*!< NAND Flash ECC Error Status 2 */ + #define REG_NANDECCES3 (FMI_BA+0x8DC) /*!< NAND Flash ECC Error Status 3 */ + #define REG_NANDPROTA0 (FMI_BA+0x8E0) /*!< NAND Flash Protect Region End Address 0 */ + #define REG_NANDPROTA1 (FMI_BA+0x8E4) /*!< NAND Flash Protect Region End Address 1 */ + + /* NAND-type Flash BCH Error Address Registers */ + #define REG_NANDECCEA0 (FMI_BA+0x900) /*!< NAND Flash ECC Error Byte Address 0 */ + #define REG_NANDECCEA1 (FMI_BA+0x904) /*!< NAND Flash ECC Error Byte Address 1 */ + #define REG_NANDECCEA2 (FMI_BA+0x908) /*!< NAND Flash ECC Error Byte Address 2 */ + #define REG_NANDECCEA3 (FMI_BA+0x90C) /*!< NAND Flash ECC Error Byte Address 3 */ + #define REG_NANDECCEA4 (FMI_BA+0x910) /*!< NAND Flash ECC Error Byte Address 4 */ + #define REG_NANDECCEA5 (FMI_BA+0x914) /*!< NAND Flash ECC Error Byte Address 5 */ + #define REG_NANDECCEA6 (FMI_BA+0x918) /*!< NAND Flash ECC Error Byte Address 6 */ + #define REG_NANDECCEA7 (FMI_BA+0x91C) /*!< NAND Flash ECC Error Byte Address 7 */ + #define REG_NANDECCEA8 (FMI_BA+0x920) /*!< NAND Flash ECC Error Byte Address 8 */ + #define REG_NANDECCEA9 (FMI_BA+0x924) /*!< NAND Flash ECC Error Byte Address 9 */ + #define REG_NANDECCEA10 (FMI_BA+0x928) /*!< NAND Flash ECC Error Byte Address 10 */ + #define REG_NANDECCEA11 (FMI_BA+0x92C) /*!< NAND Flash ECC Error Byte Address 11 */ + + /* NAND-type Flash BCH Error Data Registers */ + #define REG_NANDECCED0 (FMI_BA+0x960) /*!< NAND Flash ECC Error Data Register 0 */ + #define REG_NANDECCED1 (FMI_BA+0x964) /*!< NAND Flash ECC Error Data Register 1 */ + #define REG_NANDECCED2 (FMI_BA+0x968) /*!< NAND Flash ECC Error Data Register 2 */ + #define REG_NANDECCED3 (FMI_BA+0x96C) /*!< NAND Flash ECC Error Data Register 3 */ + #define REG_NANDECCED4 (FMI_BA+0x970) /*!< NAND Flash ECC Error Data Register 4 */ + #define REG_NANDECCED5 (FMI_BA+0x974) /*!< NAND Flash ECC Error Data Register 5 */ + + /* NAND-type Flash Redundant Area Registers */ + #define REG_NANDRA0 (FMI_BA+0xA00) /*!< NAND Flash Redundant Area Register */ + #define REG_NANDRA1 (FMI_BA+0xA04) /*!< NAND Flash Redundant Area Register */ + + /**@}*/ /* end of FMI register group */ + + + /*---------------------- SD/SDIO Host Controller -------------------------*/ + /** + @addtogroup SDH SD/SDIO Host Controller(SDH) + Memory Mapped Structure for SDH Controller + @{ */ + + /* DMAC Control Registers*/ + #define REG_SDH_FB0 (SDH_BA+0x000) /*!< SD Host Embedded Buffer Word */ + #define REG_SDH_DMACTL (SDH_BA+0x400) /*!< SD Host DMA Control and Status Register */ + #define REG_SDH_DMASA (SDH_BA+0x408) /*!< SD Host DMA Transfer Starting Address Register */ + #define REG_SDH_DMABCNT (SDH_BA+0x40C) /*!< SD Host DMA Transfer Byte Count Register */ + #define REG_SDH_DMAINTEN (SDH_BA+0x410) /*!< SD Host DMA Interrupt Enable Register */ + #define REG_SDH_DMAINTSTS (SDH_BA+0x414) /*!< SD Host DMA Interrupt Status Register */ + + #define REG_SDH_GCTL (SDH_BA+0x800) /*!< SD Host Global Control and Status Register */ + #define REG_SDH_GINTEN (SDH_BA+0x804) /*!< SD Host Global Interrupt Control Register */ + #define REG_SDH_GINTSTS (SDH_BA+0x808) /*!< SD Host Global Interrupt Status Register */ + + /* Secure Digit Registers */ + #define REG_SDH_CTL (SDH_BA+0x820) /*!< SD Host control and status register */ + #define REG_SDH_CMD (SDH_BA+0x824) /*!< SD Host command argument register */ + #define REG_SDH_INTEN (SDH_BA+0x828) /*!< SD Host interrupt enable register */ + #define REG_SDH_INTSTS (SDH_BA+0x82C) /*!< SD Host interrupt status register */ + #define REG_SDH_RESP0 (SDH_BA+0x830) /*!< SD Host receive response token register 0 */ + #define REG_SDH_RESP1 (SDH_BA+0x834) /*!< SD Host receive response token register 1 */ + #define REG_SDH_BLEN (SDH_BA+0x838) /*!< SD Host block length register */ + #define REG_SDH_TMOUT (SDH_BA+0x83C) /*!< SD Host Response/Data-in Time-out register */ + #define REG_SDH_ECTL (SDH_BA+0x840) /*!< SD Host Extend Control Register */ + + /**@}*/ /* end of SDH register group */ + + + /*---------------------- Cryptographic Accelerator -------------------------*/ + /** + @addtogroup CRYPTO Cryptographic Accelerator(CRYPTO) + Memory Mapped Structure for Cryptographic Accelerator registers + @{ */ + + /* Crypto Control Registers */ + #define CRPT_INTEN (CRPT_BA+0x000) /*!< Crypto Interrupt Enable Control Register */ + #define CRPT_INTSTS (CRPT_BA+0x004) /*!< Crypto Interrupt Flag */ + + /* PRNG Registers */ + #define CRPT_PRNG_CTL (CRPT_BA+0x008) /*!< PRNG Control Register */ + #define CRPT_PRNG_SEED (CRPT_BA+0x00C) /*!< Seed for PRNG */ + #define CRPT_PRNG_KEY0 (CRPT_BA+0x010) /*!< PRNG Generated Key 0 */ + #define CRPT_PRNG_KEY1 (CRPT_BA+0x014) /*!< PRNG Generated Key 1 */ + #define CRPT_PRNG_KEY2 (CRPT_BA+0x018) /*!< PRNG Generated Key 2 */ + #define CRPT_PRNG_KEY3 (CRPT_BA+0x01C) /*!< PRNG Generated Key 3 */ + #define CRPT_PRNG_KEY4 (CRPT_BA+0x020) /*!< PRNG Generated Key 4 */ + #define CRPT_PRNG_KEY5 (CRPT_BA+0x024) /*!< PRNG Generated Key 5 */ + #define CRPT_PRNG_KEY6 (CRPT_BA+0x028) /*!< PRNG Generated Key 6 */ + #define CRPT_PRNG_KEY7 (CRPT_BA+0x02C) /*!< PRNG Generated Key 7 */ + + /* AES/TDES feedback Registers */ + #define CRPT_AES_FDBCK0 (CRPT_BA+0x050) /*!< AES Engine Output Feedback Data after Cryptographic Operation */ + #define CRPT_AES_FDBCK1 (CRPT_BA+0x054) /*!< AES Engine Output Feedback Data after Cryptographic Operation */ + #define CRPT_AES_FDBCK2 (CRPT_BA+0x058) /*!< AES Engine Output Feedback Data after Cryptographic Operation */ + #define CRPT_AES_FDBCK3 (CRPT_BA+0x05C) /*!< AES Engine Output Feedback Data after Cryptographic Operation */ + #define CRPT_TDES_FDBCKH (CRPT_BA+0x060) /*!< TDES/DES Engine Output Feedback High Word Data after Cryptographic Operation */ + #define CRPT_TDES_FDBCKL (CRPT_BA+0x064) /*!< TDES/DES Engine Output Feedback Low Word Data after Cryptographic Operation */ + + /* AES Control Registers */ + #define CRPT_AES_CTL (CRPT_BA+0x100) /*!< AES Control Register */ + #define CRPT_AES_STS (CRPT_BA+0x104) /*!< AES Engine Flag */ + #define CRPT_AES_DATIN (CRPT_BA+0x108) /*!< AES Engine Data Input Port Register */ + #define CRPT_AES_DATOUT (CRPT_BA+0x10C) /*!< AES Engine Data Output Port Register */ + #define CRPT_AES0_KEY0 (CRPT_BA+0x110) /*!< AES Key Word 0 Register for Channel 0 */ + #define CRPT_AES0_KEY1 (CRPT_BA+0x114) /*!< AES Key Word 1 Register for Channel 0 */ + #define CRPT_AES0_KEY2 (CRPT_BA+0x118) /*!< AES Key Word 2 Register for Channel 0 */ + #define CRPT_AES0_KEY3 (CRPT_BA+0x11C) /*!< AES Key Word 3 Register for Channel 0 */ + #define CRPT_AES0_KEY4 (CRPT_BA+0x120) /*!< AES Key Word 4 Register for Channel 0 */ + #define CRPT_AES0_KEY5 (CRPT_BA+0x124) /*!< AES Key Word 5 Register for Channel 0 */ + #define CRPT_AES0_KEY6 (CRPT_BA+0x128) /*!< AES Key Word 6 Register for Channel 0 */ + #define CRPT_AES0_KEY7 (CRPT_BA+0x12C) /*!< AES Key Word 7 Register for Channel 0 */ + #define CRPT_AES0_IV0 (CRPT_BA+0x130) /*!< AES Initial Vector Word 0 Register for Channel 0 */ + #define CRPT_AES0_IV1 (CRPT_BA+0x134) /*!< AES Initial Vector Word 1 Register for Channel 0 */ + #define CRPT_AES0_IV2 (CRPT_BA+0x138) /*!< AES Initial Vector Word 2 Register for Channel 0 */ + #define CRPT_AES0_IV3 (CRPT_BA+0x13C) /*!< AES Initial Vector Word 3 Register for Channel 0 */ + #define CRPT_AES0_SADDR (CRPT_BA+0x140) /*!< AES DMA Source Address Register for Channel 0 */ + #define CRPT_AES0_DADDR (CRPT_BA+0x144) /*!< AES DMA Destination Address Register for Channel 0 */ + #define CRPT_AES0_CNT (CRPT_BA+0x148) /*!< AES Byte Count Register for Channel 0 */ + #define CRPT_AES1_KEY0 (CRPT_BA+0x14C) /*!< AES Key Word 0 Register for Channel 1 */ + #define CRPT_AES1_KEY1 (CRPT_BA+0x150) /*!< AES Key Word 1 Register for Channel 1 */ + #define CRPT_AES1_KEY2 (CRPT_BA+0x154) /*!< AES Key Word 2 Register for Channel 1 */ + #define CRPT_AES1_KEY3 (CRPT_BA+0x158) /*!< AES Key Word 3 Register for Channel 1 */ + #define CRPT_AES1_KEY4 (CRPT_BA+0x15C) /*!< AES Key Word 4 Register for Channel 1 */ + #define CRPT_AES1_KEY5 (CRPT_BA+0x160) /*!< AES Key Word 5 Register for Channel 1 */ + #define CRPT_AES1_KEY6 (CRPT_BA+0x164) /*!< AES Key Word 6 Register for Channel 1 */ + #define CRPT_AES1_KEY7 (CRPT_BA+0x168) /*!< AES Key Word 7 Register for Channel 1 */ + #define CRPT_AES1_IV0 (CRPT_BA+0x16C) /*!< AES Initial Vector Word 0 Register for Channel 1 */ + #define CRPT_AES1_IV1 (CRPT_BA+0x170) /*!< AES Initial Vector Word 1 Register for Channel 1 */ + #define CRPT_AES1_IV2 (CRPT_BA+0x174) /*!< AES Initial Vector Word 2 Register for Channel 1 */ + #define CRPT_AES1_IV3 (CRPT_BA+0x178) /*!< AES Initial Vector Word 3 Register for Channel 1 */ + #define CRPT_AES1_SADDR (CRPT_BA+0x17C) /*!< AES DMA Source Address Register for Channel 1 */ + #define CRPT_AES1_DADDR (CRPT_BA+0x180) /*!< AES DMA Destination Address Register for Channel 1 */ + #define CRPT_AES1_CNT (CRPT_BA+0x184) /*!< AES Byte Count Register for Channel 1 */ + #define CRPT_AES2_KEY0 (CRPT_BA+0x188) /*!< AES Key Word 0 Register for Channel 2 */ + #define CRPT_AES2_KEY1 (CRPT_BA+0x18C) /*!< AES Key Word 1 Register for Channel 2 */ + #define CRPT_AES2_KEY2 (CRPT_BA+0x190) /*!< AES Key Word 2 Register for Channel 2 */ + #define CRPT_AES2_KEY3 (CRPT_BA+0x194) /*!< AES Key Word 3 Register for Channel 2 */ + #define CRPT_AES2_KEY4 (CRPT_BA+0x198) /*!< AES Key Word 4 Register for Channel 2 */ + #define CRPT_AES2_KEY5 (CRPT_BA+0x19C) /*!< AES Key Word 5 Register for Channel 2 */ + #define CRPT_AES2_KEY6 (CRPT_BA+0x1A0) /*!< AES Key Word 6 Register for Channel 2 */ + #define CRPT_AES2_KEY7 (CRPT_BA+0x1A4) /*!< AES Key Word 7 Register for Channel 2 */ + #define CRPT_AES2_IV0 (CRPT_BA+0x1A8) /*!< AES Initial Vector Word 0 Register for Channel 2 */ + #define CRPT_AES2_IV1 (CRPT_BA+0x1AC) /*!< AES Initial Vector Word 1 Register for Channel 2 */ + #define CRPT_AES2_IV2 (CRPT_BA+0x1B0) /*!< AES Initial Vector Word 2 Register for Channel 2 */ + #define CRPT_AES2_IV3 (CRPT_BA+0x1B4) /*!< AES Initial Vector Word 3 Register for Channel 2 */ + #define CRPT_AES2_SADDR (CRPT_BA+0x1B8) /*!< AES DMA Source Address Register for Channel 2 */ + #define CRPT_AES2_DADDR (CRPT_BA+0x1BC) /*!< AES DMA Destination Address Register for Channel 2 */ + #define CRPT_AES2_CNT (CRPT_BA+0x1C0) /*!< AES Byte Count Register for Channel 2 */ + #define CRPT_AES3_KEY0 (CRPT_BA+0x1C4) /*!< AES Key Word 0 Register for Channel 3 */ + #define CRPT_AES3_KEY1 (CRPT_BA+0x1C8) /*!< AES Key Word 1 Register for Channel 3 */ + #define CRPT_AES3_KEY2 (CRPT_BA+0x1CC) /*!< AES Key Word 2 Register for Channel 3 */ + #define CRPT_AES3_KEY3 (CRPT_BA+0x1D0) /*!< AES Key Word 3 Register for Channel 3 */ + #define CRPT_AES3_KEY4 (CRPT_BA+0x1D4) /*!< AES Key Word 4 Register for Channel 3 */ + #define CRPT_AES3_KEY5 (CRPT_BA+0x1D8) /*!< AES Key Word 5 Register for Channel 3 */ + #define CRPT_AES3_KEY6 (CRPT_BA+0x1DC) /*!< AES Key Word 6 Register for Channel 3 */ + #define CRPT_AES3_KEY7 (CRPT_BA+0x1E0) /*!< AES Key Word 7 Register for Channel 3 */ + #define CRPT_AES3_IV0 (CRPT_BA+0x1E4) /*!< AES Initial Vector Word 0 Register for Channel 3 */ + #define CRPT_AES3_IV1 (CRPT_BA+0x1E8) /*!< AES Initial Vector Word 1 Register for Channel 3 */ + #define CRPT_AES3_IV2 (CRPT_BA+0x1EC) /*!< AES Initial Vector Word 2 Register for Channel 3 */ + #define CRPT_AES3_IV3 (CRPT_BA+0x1F0) /*!< AES Initial Vector Word 3 Register for Channel 3 */ + #define CRPT_AES3_SADDR (CRPT_BA+0x1F4) /*!< AES DMA Source Address Register for Channel 3 */ + #define CRPT_AES3_DADDR (CRPT_BA+0x1F8) /*!< AES DMA Destination Address Register for Channel 3 */ + #define CRPT_AES3_CNT (CRPT_BA+0x1FC) /*!< AES Byte Count Register for Channel 3 */ + + /* DES/TDES Control Registers */ + #define CRPT_TDES_CTL (CRPT_BA+0x200) /*!< TDES/DES Control Register */ + #define CRPT_TDES_STS (CRPT_BA+0x204) /*!< TDES/DES Engine Flag */ + #define CRPT_TDES0_KEY1H (CRPT_BA+0x208) /*!< TDES/DES Key 1 High Word Register for Channel 0 */ + #define CRPT_TDES0_KEY1L (CRPT_BA+0x20C) /*!< TDES/DES Key 1 Low Word Register for Channel 0 */ + #define CRPT_TDES0_KEY2H (CRPT_BA+0x210) /*!< TDES/DES Key 2 High Word Register for Channel 0 */ + #define CRPT_TDES0_KEY2L (CRPT_BA+0x214) /*!< TDES/DES Key 2 Low Word Register for Channel 0 */ + #define CRPT_TDES0_KEY3H (CRPT_BA+0x218) /*!< TDES/DES Key 3 High Word Register for Channel 0 */ + #define CRPT_TDES0_KEY3L (CRPT_BA+0x21C) /*!< TDES/DES Key 3 Low Word Register for Channel 0 */ + #define CRPT_TDES0_IVH (CRPT_BA+0x220) /*!< TDES/DES Initial Vector High Word Register for Channel 0 */ + #define CRPT_TDES0_IVL (CRPT_BA+0x224) /*!< TDES/DES Initial Vector Low Word Register for Channel 0 */ + #define CRPT_TDES0_SADDR (CRPT_BA+0x228) /*!< TDES/DES DMA Source Address Register for Channel 0 */ + #define CRPT_TDES0_DADDR (CRPT_BA+0x22C) /*!< TDES/DES DMA Destination Address Register for Channel 0 */ + #define CRPT_TDES0_CNT (CRPT_BA+0x230) /*!< TDES/DES Byte Count Register for Channel 0 */ + #define CRPT_TDES_DATIN (CRPT_BA+0x234) /*!< TDES/DES Engine Input data Word Register */ + #define CRPT_TDES_DATOUT (CRPT_BA+0x238) /*!< TDES/DES Engine Output data Word Register */ + #define CRPT_TDES1_KEY1H (CRPT_BA+0x248) /*!< TDES/DES Key 1 High Word Register for Channel 1 */ + #define CRPT_TDES1_KEY1L (CRPT_BA+0x24C) /*!< TDES/DES Key 1 Low Word Register for Channel 1 */ + #define CRPT_TDES1_KEY2H (CRPT_BA+0x250) /*!< TDES/DES Key 2 High Word Register for Channel 1 */ + #define CRPT_TDES1_KEY2L (CRPT_BA+0x254) /*!< TDES/DES Key 2 Low Word Register for Channel 1 */ + #define CRPT_TDES1_KEY3H (CRPT_BA+0x258) /*!< TDES/DES Key 3 High Word Register for Channel 1 */ + #define CRPT_TDES1_KEY3L (CRPT_BA+0x25C) /*!< TDES/DES Key 3 Low Word Register for Channel 1 */ + #define CRPT_TDES1_IVH (CRPT_BA+0x260) /*!< TDES/DES Initial Vector High Word Register for Channel 1 */ + #define CRPT_TDES1_IVL (CRPT_BA+0x264) /*!< TDES/DES Initial Vector Low Word Register for Channel 1 */ + #define CRPT_TDES1_SADDR (CRPT_BA+0x268) /*!< TDES/DES DMA Source Address Register for Channel 1 */ + #define CRPT_TDES1_DADDR (CRPT_BA+0x26C) /*!< TDES/DES DMA Destination Address Register for Channel 1 */ + #define CRPT_TDES1_CNT (CRPT_BA+0x270) /*!< TDES/DES Byte Count Register for Channel 1 */ + #define CRPT_TDES2_KEY1H (CRPT_BA+0x288) /*!< TDES/DES Key 1 High Word Register for Channel 2 */ + #define CRPT_TDES2_KEY1L (CRPT_BA+0x28C) /*!< TDES/DES Key 1 Low Word Register for Channel 2 */ + #define CRPT_TDES2_KEY2H (CRPT_BA+0x290) /*!< TDES/DES Key 2 High Word Register for Channel 2 */ + #define CRPT_TDES2_KEY2L (CRPT_BA+0x294) /*!< TDES/DES Key 2 Low Word Register for Channel 2 */ + #define CRPT_TDES2_KEY3H (CRPT_BA+0x298) /*!< TDES/DES Key 3 High Word Register for Channel 2 */ + #define CRPT_TDES2_KEY3L (CRPT_BA+0x29C) /*!< TDES/DES Key 3 Low Word Register for Channel 2 */ + #define CRPT_TDES2_IVH (CRPT_BA+0x2A0) /*!< TDES/DES Initial Vector High Word Register for Channel 2 */ + #define CRPT_TDES2_IVL (CRPT_BA+0x2A4) /*!< TDES/DES Initial Vector Low Word Register for Channel 2 */ + #define CRPT_TDES2_SADDR (CRPT_BA+0x2A8) /*!< TDES/DES DMA Source Address Register for Channel 2 */ + #define CRPT_TDES2_DADDR (CRPT_BA+0x2AC) /*!< TDES/DES DMA Destination Address Register for Channel 2 */ + #define CRPT_TDES2_CNT (CRPT_BA+0x2B0) /*!< TDES/DES Byte Count Register for Channel 3 */ + #define CRPT_TDES3_KEY1H (CRPT_BA+0x2C8) /*!< TDES/DES Key 1 High Word Register for Channel 3 */ + #define CRPT_TDES3_KEY1L (CRPT_BA+0x2CC) /*!< TDES/DES Key 1 Low Word Register for Channel 3 */ + #define CRPT_TDES3_KEY2H (CRPT_BA+0x2D0) /*!< TDES/DES Key 2 High Word Register for Channel 3 */ + #define CRPT_TDES3_KEY2L (CRPT_BA+0x2D4) /*!< TDES/DES Key 2 Low Word Register for Channel 3 */ + #define CRPT_TDES3_KEY3H (CRPT_BA+0x2D8) /*!< TDES/DES Key 3 High Word Register for Channel 3 */ + #define CRPT_TDES3_KEY3L (CRPT_BA+0x2DC) /*!< TDES/DES Key 3 Low Word Register for Channel 3 */ + #define CRPT_TDES3_IVH (CRPT_BA+0x2E0) /*!< TDES/DES Initial Vector High Word Register for Channel 3 */ + #define CRPT_TDES3_IVL (CRPT_BA+0x2E4) /*!< TDES/DES Initial Vector Low Word Register for Channel 3 */ + #define CRPT_TDES3_SADDR (CRPT_BA+0x2E8) /*!< TDES/DES DMA Source Address Register for Channel 3 */ + #define CRPT_TDES3_DADDR (CRPT_BA+0x2EC) /*!< TDES/DES DMA Destination Address Register for Channel 3 */ + #define CRPT_TDES3_CNT (CRPT_BA+0x2F0) /*!< TDES/DES Byte Count Register for Channel 3 */ + + /* SHA/HMAC Control Registers */ + #define CRPT_HMAC_CTL (CRPT_BA+0x300) /*!< SHA/HMAC Control Register */ + #define CRPT_HMAC_STS (CRPT_BA+0x304) /*!< SHA/HMAC Status Flag */ + #define CRPT_HMAC_DGST0 (CRPT_BA+0x308) /*!< SHA/HMAC Digest Message 0 */ + #define CRPT_HMAC_DGST1 (CRPT_BA+0x30C) /*!< SHA/HMAC Digest Message 1 */ + #define CRPT_HMAC_DGST2 (CRPT_BA+0x310) /*!< SHA/HMAC Digest Message 2 */ + #define CRPT_HMAC_DGST3 (CRPT_BA+0x314) /*!< SHA/HMAC Digest Message 3 */ + #define CRPT_HMAC_DGST4 (CRPT_BA+0x318) /*!< SHA/HMAC Digest Message 4 */ + #define CRPT_HMAC_DGST5 (CRPT_BA+0x31C) /*!< SHA/HMAC Digest Message 5 */ + #define CRPT_HMAC_DGST6 (CRPT_BA+0x320) /*!< SHA/HMAC Digest Message 6 */ + #define CRPT_HMAC_DGST7 (CRPT_BA+0x324) /*!< SHA/HMAC Digest Message 7 */ + #define CRPT_HMAC_DGST8 (CRPT_BA+0x328) /*!< SHA/HMAC Digest Message 8 */ + #define CRPT_HMAC_DGST9 (CRPT_BA+0x32C) /*!< SHA/HMAC Digest Message 8 */ + #define CRPT_HMAC_DGST10 (CRPT_BA+0x330) /*!< SHA/HMAC Digest Message 10 */ + #define CRPT_HMAC_DGST11 (CRPT_BA+0x334) /*!< SHA/HMAC Digest Message 11 */ + #define CRPT_HMAC_DGST12 (CRPT_BA+0x338) /*!< SHA/HMAC Digest Message 12 */ + #define CRPT_HMAC_DGST13 (CRPT_BA+0x33C) /*!< SHA/HMAC Digest Message 13 */ + #define CRPT_HMAC_DGST14 (CRPT_BA+0x340) /*!< SHA/HMAC Digest Message 14 */ + #define CRPT_HMAC_DGST15 (CRPT_BA+0x344) /*!< SHA/HMAC Digest Message 15 */ + #define CRPT_HMAC_KEYCNT (CRPT_BA+0x348) /*!< SHA/HMAC Key Byte Count */ + #define CRPT_HMAC_SADDR (CRPT_BA+0x34C) /*!< SHA/HMAC Key Byte Count */ + #define CRPT_HMAC_DMACNT (CRPT_BA+0x350) /*!< SHA/HMAC Byte Count Register */ + #define CRPT_HMAC_DATIN (CRPT_BA+0x354) /*!< SHA/HMAC Engine Non-DMA Mode Data Input Port Register */ + + /**@}*/ /* end of Cryptographic Accelerator register group */ + + + + + /*---------------------- Universal Asynchronous Receiver/Transmitter Controller -------------------------*/ + /** + @addtogroup UART Universal Asynchronous Receiver/Transmitter Controller(UART) + Memory Mapped Structure for UART Controller + @{ */ + + #define REG_UART0_RBR (UART0_BA+0x00) /*!< Receive Buffer Register */ + #define REG_UART0_THR (UART0_BA+0x00) /*!< Transmit Holding Register */ + #define REG_UART0_IER (UART0_BA+0x04) /*!< Interrupt Enable Register */ + #define REG_UART0_FCR (UART0_BA+0x08) /*!< FIFO Control Register */ + #define REG_UART0_LCR (UART0_BA+0x0C) /*!< Line Control Register */ + #define REG_UART0_MCR (UART0_BA+0x10) /*!< Modem Control Register */ + #define REG_UART0_MSR (UART0_BA+0x14) /*!< MODEM Status Register */ + #define REG_UART0_FSR (UART0_BA+0x18) /*!< FIFO Status Register */ + #define REG_UART0_ISR (UART0_BA+0x1C) /*!< Interrupt Status Control Register */ + #define REG_UART0_TOR (UART0_BA+0x20) /*!< Time-out Register */ + #define REG_UART0_BAUD (UART0_BA+0x24) /*!< Baud Rate Divider Register */ + #define REG_UART0_IRCR (UART0_BA+0x28) /*!< IrDA Control Register */ + #define REG_UART0_ALT_CSR (UART0_BA+0x2C) /*!< Alternate Control Register */ + #define REG_UART0_FUN_SEL (UART0_BA+0x30) /*!< UART Function Select REgister */ + #define REG_UART0_LIN_CTL (UART0_BA+0x34) /*!< UART LIN Control Register */ + #define REG_UART0_LIN_SR (UART0_BA+0x38) /*!< LIN Status Register */ + + + + + /* + UART1 Control Registers + */ + #define REG_UART1_RBR (UART1_BA+0x00) /*!< Receive Buffer Register */ + #define REG_UART1_THR (UART1_BA+0x00) /*!< Transmit Holding Register */ + #define REG_UART1_IER (UART1_BA+0x04) /*!< Interrupt Enable Register */ + #define REG_UART1_FCR (UART1_BA+0x08) /*!< FIFO Control Register */ + #define REG_UART1_LCR (UART1_BA+0x0C) /*!< Line Control Register */ + #define REG_UART1_MCR (UART1_BA+0x10) /*!< Modem Control Register */ + #define REG_UART1_MSR (UART1_BA+0x14) /*!< MODEM Status Register */ + #define REG_UART1_FSR (UART1_BA+0x18) /*!< FIFO Status Register */ + #define REG_UART1_ISR (UART1_BA+0x1C) /*!< Interrupt Status Control Register */ + #define REG_UART1_TOR (UART1_BA+0x20) /*!< Time-out Register */ + #define REG_UART1_BAUD (UART1_BA+0x24) /*!< Baud Rate Divider Register */ + #define REG_UART1_IRCR (UART1_BA+0x28) /*!< IrDA Control Register */ + #define REG_UART1_ALT_CSR (UART1_BA+0x2C) /*!< Alternate Control Register */ + #define REG_UART1_FUN_SEL (UART1_BA+0x30) /*!< UART Function Select REgister */ + #define REG_UART1_LIN_CTL (UART1_BA+0x34) /*!< UART LIN Control Register */ + #define REG_UART1_LIN_SR (UART1_BA+0x38) /*!< LIN Status Register */ + + /* + UART2 Control Registers + */ + #define REG_UART2_RBR (UART2_BA+0x00) /*!< Receive Buffer Register */ + #define REG_UART2_THR (UART2_BA+0x00) /*!< Transmit Holding Register */ + #define REG_UART2_IER (UART2_BA+0x04) /*!< Interrupt Enable Register */ + #define REG_UART2_FCR (UART2_BA+0x08) /*!< FIFO Control Register */ + #define REG_UART2_LCR (UART2_BA+0x0C) /*!< Line Control Register */ + #define REG_UART2_MCR (UART2_BA+0x10) /*!< Modem Control Register */ + #define REG_UART2_MSR (UART2_BA+0x14) /*!< MODEM Status Register */ + #define REG_UART2_FSR (UART2_BA+0x18) /*!< FIFO Status Register */ + #define REG_UART2_ISR (UART2_BA+0x1C) /*!< Interrupt Status Control Register */ + #define REG_UART2_TOR (UART2_BA+0x20) /*!< Time-out Register */ + #define REG_UART2_BAUD (UART2_BA+0x24) /*!< Baud Rate Divider Register */ + #define REG_UART2_IRCR (UART2_BA+0x28) /*!< IrDA Control Register */ + #define REG_UART2_ALT_CSR (UART2_BA+0x2C) /*!< Alternate Control Register */ + #define REG_UART2_FUN_SEL (UART2_BA+0x30) /*!< UART Function Select REgister */ + #define REG_UART2_LIN_CTL (UART2_BA+0x34) /*!< UART LIN Control Register */ + #define REG_UART2_LIN_SR (UART2_BA+0x38) /*!< LIN Status Register */ + + /* + UART3 Control Registers + */ + #define REG_UART3_RBR (UART3_BA+0x00) /*!< Receive Buffer Register */ + #define REG_UART3_THR (UART3_BA+0x00) /*!< Transmit Holding Register */ + #define REG_UART3_IER (UART3_BA+0x04) /*!< Interrupt Enable Register */ + #define REG_UART3_FCR (UART3_BA+0x08) /*!< FIFO Control Register */ + #define REG_UART3_LCR (UART3_BA+0x0C) /*!< Line Control Register */ + #define REG_UART3_MCR (UART3_BA+0x10) /*!< Modem Control Register */ + #define REG_UART3_MSR (UART3_BA+0x14) /*!< MODEM Status Register */ + #define REG_UART3_FSR (UART3_BA+0x18) /*!< FIFO Status Register */ + #define REG_UART3_ISR (UART3_BA+0x1C) /*!< Interrupt Status Control Register */ + #define REG_UART3_TOR (UART3_BA+0x20) /*!< Time-out Register */ + #define REG_UART3_BAUD (UART3_BA+0x24) /*!< Baud Rate Divider Register */ + #define REG_UART3_IRCR (UART3_BA+0x28) /*!< IrDA Control Register */ + #define REG_UART3_ALT_CSR (UART3_BA+0x2C) /*!< Alternate Control Register */ + #define REG_UART3_FUN_SEL (UART3_BA+0x30) /*!< UART Function Select REgister */ + #define REG_UART3_LIN_CTL (UART3_BA+0x34) /*!< UART LIN Control Register */ + #define REG_UART3_LIN_SR (UART3_BA+0x38) /*!< LIN Status Register */ + + + /* + UART4 Control Registers + */ + #define REG_UART4_RBR (UART4_BA+0x00) /*!< Receive Buffer Register */ + #define REG_UART4_THR (UART4_BA+0x00) /*!< Transmit Holding Register */ + #define REG_UART4_IER (UART4_BA+0x04) /*!< Interrupt Enable Register */ + #define REG_UART4_FCR (UART4_BA+0x08) /*!< FIFO Control Register */ + #define REG_UART4_LCR (UART4_BA+0x0C) /*!< Line Control Register */ + #define REG_UART4_MCR (UART4_BA+0x10) /*!< Modem Control Register */ + #define REG_UART4_MSR (UART4_BA+0x14) /*!< MODEM Status Register */ + #define REG_UART4_FSR (UART4_BA+0x18) /*!< FIFO Status Register */ + #define REG_UART4_ISR (UART4_BA+0x1C) /*!< Interrupt Status Control Register */ + #define REG_UART4_TOR (UART4_BA+0x20) /*!< Time-out Register */ + #define REG_UART4_BAUD (UART4_BA+0x24) /*!< Baud Rate Divider Register */ + #define REG_UART4_IRCR (UART4_BA+0x28) /*!< IrDA Control Register */ + #define REG_UART4_ALT_CSR (UART4_BA+0x2C) /*!< Alternate Control Register */ + #define REG_UART4_FUN_SEL (UART4_BA+0x30) /*!< UART Function Select REgister */ + #define REG_UART4_LIN_CTL (UART4_BA+0x34) /*!< UART LIN Control Register */ + #define REG_UART4_LIN_SR (UART4_BA+0x38) /*!< LIN Status Register */ + + /* + UART5 Control Registers + */ + #define REG_UART5_RBR (UART5_BA+0x00) /*!< Receive Buffer Register */ + #define REG_UART5_THR (UART5_BA+0x00) /*!< Transmit Holding Register */ + #define REG_UART5_IER (UART5_BA+0x04) /*!< Interrupt Enable Register */ + #define REG_UART5_FCR (UART5_BA+0x08) /*!< FIFO Control Register */ + #define REG_UART5_LCR (UART5_BA+0x0C) /*!< Line Control Register */ + #define REG_UART5_MCR (UART5_BA+0x10) /*!< Modem Control Register */ + #define REG_UART5_MSR (UART5_BA+0x14) /*!< MODEM Status Register */ + #define REG_UART5_FSR (UART5_BA+0x18) /*!< FIFO Status Register */ + #define REG_UART5_ISR (UART5_BA+0x1C) /*!< Interrupt Status Control Register */ + #define REG_UART5_TOR (UART5_BA+0x20) /*!< Time-out Register */ + #define REG_UART5_BAUD (UART5_BA+0x24) /*!< Baud Rate Divider Register */ + #define REG_UART5_IRCR (UART5_BA+0x28) /*!< IrDA Control Register */ + #define REG_UART5_ALT_CSR (UART5_BA+0x2C) /*!< Alternate Control Register */ + #define REG_UART5_FUN_SEL (UART5_BA+0x30) /*!< UART Function Select REgister */ + #define REG_UART5_LIN_CTL (UART5_BA+0x34) /*!< UART LIN Control Register */ + #define REG_UART5_LIN_SR (UART5_BA+0x38) /*!< LIN Status Register */ + + /* + UART6 Control Registers + */ + #define REG_UART6_RBR (UART6_BA+0x00) /*!< Receive Buffer Register */ + #define REG_UART6_THR (UART6_BA+0x00) /*!< Transmit Holding Register */ + #define REG_UART6_IER (UART6_BA+0x04) /*!< Interrupt Enable Register */ + #define REG_UART6_FCR (UART6_BA+0x08) /*!< FIFO Control Register */ + #define REG_UART6_LCR (UART6_BA+0x0C) /*!< Line Control Register */ + #define REG_UART6_MCR (UART6_BA+0x10) /*!< Modem Control Register */ + #define REG_UART6_MSR (UART6_BA+0x14) /*!< MODEM Status Register */ + #define REG_UART6_FSR (UART6_BA+0x18) /*!< FIFO Status Register */ + #define REG_UART6_ISR (UART6_BA+0x1C) /*!< Interrupt Status Control Register */ + #define REG_UART6_TOR (UART6_BA+0x20) /*!< Time-out Register */ + #define REG_UART6_BAUD (UART6_BA+0x24) /*!< Baud Rate Divider Register */ + #define REG_UART6_IRCR (UART6_BA+0x28) /*!< IrDA Control Register */ + #define REG_UART6_ALT_CSR (UART6_BA+0x2C) /*!< Alternate Control Register */ + #define REG_UART6_FUN_SEL (UART6_BA+0x30) /*!< UART Function Select REgister */ + #define REG_UART6_LIN_CTL (UART6_BA+0x34) /*!< UART LIN Control Register */ + #define REG_UART6_LIN_SR (UART6_BA+0x38) /*!< LIN Status Register */ + + /* + UART7 Control Registers + */ + #define REG_UART7_RBR (UART7_BA+0x00) /*!< Receive Buffer Register */ + #define REG_UART7_THR (UART7_BA+0x00) /*!< Transmit Holding Register */ + #define REG_UART7_IER (UART7_BA+0x04) /*!< Interrupt Enable Register */ + #define REG_UART7_FCR (UART7_BA+0x08) /*!< FIFO Control Register */ + #define REG_UART7_LCR (UART7_BA+0x0C) /*!< Line Control Register */ + #define REG_UART7_MCR (UART7_BA+0x10) /*!< Modem Control Register */ + #define REG_UART7_MSR (UART7_BA+0x14) /*!< MODEM Status Register */ + #define REG_UART7_FSR (UART7_BA+0x18) /*!< FIFO Status Register */ + #define REG_UART7_ISR (UART7_BA+0x1C) /*!< Interrupt Status Control Register */ + #define REG_UART7_TOR (UART7_BA+0x20) /*!< Time-out Register */ + #define REG_UART7_BAUD (UART7_BA+0x24) /*!< Baud Rate Divider Register */ + #define REG_UART7_IRCR (UART7_BA+0x28) /*!< IrDA Control Register */ + #define REG_UART7_ALT_CSR (UART7_BA+0x2C) /*!< Alternate Control Register */ + #define REG_UART7_FUN_SEL (UART7_BA+0x30) /*!< UART Function Select REgister */ + #define REG_UART7_LIN_CTL (UART7_BA+0x34) /*!< UART LIN Control Register */ + #define REG_UART7_LIN_SR (UART7_BA+0x38) /*!< LIN Status Register */ + + /* + UART8 Control Registers + */ + #define REG_UART8_RBR (UART8_BA+0x00) /*!< Receive Buffer Register */ + #define REG_UART8_THR (UART8_BA+0x00) /*!< Transmit Holding Register */ + #define REG_UART8_IER (UART8_BA+0x04) /*!< Interrupt Enable Register */ + #define REG_UART8_FCR (UART8_BA+0x08) /*!< FIFO Control Register */ + #define REG_UART8_LCR (UART8_BA+0x0C) /*!< Line Control Register */ + #define REG_UART8_MCR (UART8_BA+0x10) /*!< Modem Control Register */ + #define REG_UART8_MSR (UART8_BA+0x14) /*!< MODEM Status Register */ + #define REG_UART8_FSR (UART8_BA+0x18) /*!< FIFO Status Register */ + #define REG_UART8_ISR (UART8_BA+0x1C) /*!< Interrupt Status Control Register */ + #define REG_UART8_TOR (UART8_BA+0x20) /*!< Time-out Register */ + #define REG_UART8_BAUD (UART8_BA+0x24) /*!< Baud Rate Divider Register */ + #define REG_UART8_IRCR (UART8_BA+0x28) /*!< IrDA Control Register */ + #define REG_UART8_ALT_CSR (UART8_BA+0x2C) /*!< Alternate Control Register */ + #define REG_UART8_FUN_SEL (UART8_BA+0x30) /*!< UART Function Select REgister */ + #define REG_UART8_LIN_CTL (UART8_BA+0x34) /*!< UART LIN Control Register */ + #define REG_UART8_LIN_SR (UART8_BA+0x38) /*!< LIN Status Register */ + + /* + UART9 Control Registers + */ + #define REG_UART9_RBR (UART9_BA+0x00) /*!< Receive Buffer Register */ + #define REG_UART9_THR (UART9_BA+0x00) /*!< Transmit Holding Register */ + #define REG_UART9_IER (UART9_BA+0x04) /*!< Interrupt Enable Register */ + #define REG_UART9_FCR (UART9_BA+0x08) /*!< FIFO Control Register */ + #define REG_UART9_LCR (UART9_BA+0x0C) /*!< Line Control Register */ + #define REG_UART9_MCR (UART9_BA+0x10) /*!< Modem Control Register */ + #define REG_UART9_MSR (UART9_BA+0x14) /*!< MODEM Status Register */ + #define REG_UART9_FSR (UART9_BA+0x18) /*!< FIFO Status Register */ + #define REG_UART9_ISR (UART9_BA+0x1C) /*!< Interrupt Status Control Register */ + #define REG_UART9_TOR (UART9_BA+0x20) /*!< Time-out Register */ + #define REG_UART9_BAUD (UART9_BA+0x24) /*!< Baud Rate Divider Register */ + #define REG_UART9_IRCR (UART9_BA+0x28) /*!< IrDA Control Register */ + #define REG_UART9_ALT_CSR (UART9_BA+0x2C) /*!< Alternate Control Register */ + #define REG_UART9_FUN_SEL (UART9_BA+0x30) /*!< UART Function Select REgister */ + #define REG_UART9_LIN_CTL (UART9_BA+0x34) /*!< UART LIN Control Register */ + #define REG_UART9_LIN_SR (UART9_BA+0x38) /*!< LIN Status Register */ + + /* + UARTA Control Registers + */ + #define REG_UARTA_RBR (UARTA_BA+0x00) /*!< Receive Buffer Register */ + #define REG_UARTA_THR (UARTA_BA+0x00) /*!< Transmit Holding Register */ + #define REG_UARTA_IER (UARTA_BA+0x04) /*!< Interrupt Enable Register */ + #define REG_UARTA_FCR (UARTA_BA+0x08) /*!< FIFO Control Register */ + #define REG_UARTA_LCR (UARTA_BA+0x0C) /*!< Line Control Register */ + #define REG_UARTA_MCR (UARTA_BA+0x10) /*!< Modem Control Register */ + #define REG_UARTA_MSR (UARTA_BA+0x14) /*!< MODEM Status Register */ + #define REG_UARTA_FSR (UARTA_BA+0x18) /*!< FIFO Status Register */ + #define REG_UARTA_ISR (UARTA_BA+0x1C) /*!< Interrupt Status Control Register */ + #define REG_UARTA_TOR (UARTA_BA+0x20) /*!< Time-out Register */ + #define REG_UARTA_BAUD (UARTA_BA+0x24) /*!< Baud Rate Divider Register */ + #define REG_UARTA_IRCR (UARTA_BA+0x28) /*!< IrDA Control Register */ + #define REG_UARTA_ALT_CSR (UARTA_BA+0x2C) /*!< Alternate Control Register */ + #define REG_UARTA_FUN_SEL (UARTA_BA+0x30) /*!< UART Function Select REgister */ + #define REG_UARTA_LIN_CTL (UARTA_BA+0x34) /*!< UART LIN Control Register */ + #define REG_UARTA_LIN_SR (UARTA_BA+0x38) /*!< LIN Status Register */ + + + /**@}*/ /* end of UART register group */ + + + /*---------------------- Timer Controller -------------------------*/ + /** + @addtogroup TIMER Timer Controller(TIMER) + Memory Mapped Structure for TIMER Controller + @{ */ + + #define REG_TMR0_CSR (TMR0_BA+0x00) /*!< Timer Control and Status Register 0 */ + #define REG_TMR0_CMPR (TMR0_BA+0x04) /*!< Timer Compare Register 0 */ + #define REG_TMR0_DR (TMR0_BA+0x08) /*!< Timer Data Register 0 */ + + #define REG_TMR1_CSR (TMR1_BA+0x00) /*!< Timer Control and Status Register 1 */ + #define REG_TMR1_CMPR (TMR1_BA+0x04) /*!< Timer Compare Register 1 */ + #define REG_TMR1_TDR (TMR1_BA+0x08) /*!< Timer Data Register 1 */ + + #define REG_TMR2_CSR (TMR2_BA+0x00) /*!< Timer Control and Status Register 2 */ + #define REG_TMR2_CMPR (TMR2_BA+0x04) /*!< Timer Compare Register 2 */ + #define REG_TMR2_DR (TMR2_BA+0x08) /*!< Timer Data Register 2 */ + + #define REG_TMR3_CSR (TMR3_BA+0x00) /*!< Timer Control and Status Register 3 */ + #define REG_TMR3_CMPR (TMR3_BA+0x04) /*!< Timer Compare Register 3 */ + #define REG_TMR3_DR (TMR3_BA+0x08) /*!< Timer Data Register 3 */ + + #define REG_TMR4_CSR (TMR4_BA+0x00) /*!< Timer Control and Status Register 4 */ + #define REG_TMR4_CMPR (TMR4_BA+0x04) /*!< Timer Compare Register 4 */ + #define REG_TMR4_DR (TMR4_BA+0x08) /*!< Timer Data Register 4 */ + + #define REG_TMR_ISR (TMR0_BA+0x60) /*!< Timer Interrupt Status Register */ + + /**@}*/ /* end of TIMER register group */ + + /*---------------------- Enhance Timer Controller -------------------------*/ + /** + @addtogroup ETIMER Enhance Timer Controller(ETIMER) + Memory Mapped Structure for TIMER Controller + @{ */ + + #define REG_ETMR0_CTL (ETMR0_BA+0x00) /*!< Enhance Timer 0 Control Register */ + #define REG_ETMR0_PRECNT (ETMR0_BA+0x04) /*!< Enhance Timer 0 Pre-Scale Counter Register */ + #define REG_ETMR0_CMPR (ETMR0_BA+0x08) /*!< Enhance Timer 0 Compare Register */ + #define REG_ETMR0_IER (ETMR0_BA+0x0C) /*!< Enhance Timer 0 Interrupt Enable Register */ + #define REG_ETMR0_ISR (ETMR0_BA+0x10) /*!< Enhance Timer 0 Interrupt Status Register */ + #define REG_ETMR0_DR (ETMR0_BA+0x14) /*!< Enhance Timer 0 Data Register */ + #define REG_ETMR0_TCAP (ETMR0_BA+0x18) /*!< Enhance Timer 0 Capture Data Register */ + + #define REG_ETMR1_CTL (ETMR1_BA+0x00) /*!< Enhance Timer 1 Control Register */ + #define REG_ETMR1_PRECNT (ETMR1_BA+0x04) /*!< Enhance Timer 1 Pre-Scale Counter Register */ + #define REG_ETMR1_CMPR (ETMR1_BA+0x08) /*!< Enhance Timer 1 Compare Register */ + #define REG_ETMR1_IER (ETMR1_BA+0x0C) /*!< Enhance Timer 1 Interrupt Enable Register */ + #define REG_ETMR1_ISR (ETMR1_BA+0x10) /*!< Enhance Timer 1 Interrupt Status Register */ + #define REG_ETMR1_DR (ETMR1_BA+0x14) /*!< Enhance Timer 1 Data Register */ + #define REG_ETMR1_TCAP (ETMR1_BA+0x18) /*!< Enhance Timer 1 Capture Data Register */ + + #define REG_ETMR2_CTL (ETMR2_BA+0x00) /*!< Enhance Timer 2 Control Register */ + #define REG_ETMR2_PRECNT (ETMR2_BA+0x04) /*!< Enhance Timer 2 Pre-Scale Counter Register */ + #define REG_ETMR2_CMPR (ETMR2_BA+0x08) /*!< Enhance Timer 2 Compare Register */ + #define REG_ETMR2_IER (ETMR2_BA+0x0C) /*!< Enhance Timer 2 Interrupt Enable Register */ + #define REG_ETMR2_ISR (ETMR2_BA+0x10) /*!< Enhance Timer 2 Interrupt Status Register */ + #define REG_ETMR2_DR (ETMR2_BA+0x14) /*!< Enhance Timer 2 Data Register */ + #define REG_ETMR2_TCAP (ETMR2_BA+0x18) /*!< Enhance Timer 2 Capture Data Register */ + + #define REG_ETMR3_CTL (ETMR3_BA+0x00) /*!< Enhance Timer 3 Control Register */ + #define REG_ETMR3_PRECNT (ETMR3_BA+0x04) /*!< Enhance Timer 3 Pre-Scale Counter Register */ + #define REG_ETMR3_CMPR (ETMR3_BA+0x08) /*!< Enhance Timer 3 Compare Register */ + #define REG_ETMR3_IER (ETMR3_BA+0x0C) /*!< Enhance Timer 3 Interrupt Enable Register */ + #define REG_ETMR3_ISR (ETMR3_BA+0x10) /*!< Enhance Timer 3 Interrupt Status Register */ + #define REG_ETMR3_DR (ETMR3_BA+0x14) /*!< Enhance Timer 3 Data Register */ + #define REG_ETMR3_TCAP (ETMR3_BA+0x18) /*!< Enhance Timer 3 Capture Data Register */ + /**@}*/ /* end of ETIMER register group */ + + /*---------------------- WDT Controller -------------------------*/ + /** + @addtogroup WDT Watch Dog Timer Controller(WDT) + Memory Mapped Structure for WDT Controller + @{ */ + + #define REG_WDT_CTL (WDT_BA+0x00) /*!< WDT Control Register */ + #define REG_WDT_ALTCTL (WDT_BA+0x04) /*!< WDT Alternative Control Register */ + + /**@}*/ /* end of WDT register group */ + + /*---------------------- WWDT Controller -------------------------*/ + /** + @addtogroup WWDT Window Watch Dog Timer Controller(WWDT) + Memory Mapped Structure for WWDT Controller + @{ */ + + #define REG_WWDT_RLDCNT (WWDT_BA+0x00) /*!< WWDT Reload Counter Register */ + #define REG_WWDT_CTL (WWDT_BA+0x04) /*!< WWDT Control Register */ + #define REG_WWDT_STATUS (WWDT_BA+0x08) /*!< WWDT Status Register */ + #define REG_WWDT_CNT (WWDT_BA+0x0C) /*!< WWDT Counter Value Register */ + + /**@}*/ /* end of WWDT register group */ + + /*---------------------- SC Host Interface -------------------------*/ + /** + @addtogroup SC Smart Card Host Interface (SC) + Memory Mapped Structure for Smart Card Host Interface + @{ */ + + #define REG_SC0_DAT (SC0_BA+0x00) /*!< SC0 Receiving/Transmit Holding Buffer Register */ + #define REG_SC0_CTL (SC0_BA+0x04) /*!< SC0 Control Register */ + #define REG_SC0_ALTCTL (SC0_BA+0x08) /*!< SC0 Alternate Control Register */ + #define REG_SC0_EGT (SC0_BA+0x0C) /*!< SC0 Extend Guard Time Register */ + #define REG_SC0_RXTOUT (SC0_BA+0x10) /*!< SC0 Receive Buffer Time-out Register */ + #define REG_SC0_ETUCTL (SC0_BA+0x14) /*!< SC0 ETU Control Register */ + #define REG_SC0_INTEN (SC0_BA+0x18) /*!< SC0 Interrupt Enable Control Register */ + #define REG_SC0_INTSTS (SC0_BA+0x1C) /*!< SC0 Interrupt Status Register */ + #define REG_SC0_STATUS (SC0_BA+0x20) /*!< SC0 Status Register */ + #define REG_SC0_PINCTL (SC0_BA+0x24) /*!< SC0 Pin Control State Register */ + #define REG_SC0_TMRCTL0 (SC0_BA+0x28) /*!< SC0 Internal Timer Control Register 0 */ + #define REG_SC0_TMRCTL1 (SC0_BA+0x2C) /*!< SC0 Internal Timer Control Register 1 */ + #define REG_SC0_TMRCTL2 (SC0_BA+0x30) /*!< SC0 Internal Timer Control Register 2 */ + #define REG_SC0_UARTCTL (SC0_BA+0x34) /*!< SC0 UART Mode Control Register */ + #define REG_SC0_TMRDAT0 (SC0_BA+0x38) /*!< SC0 Timer Current Data Register 0 */ + #define REG_SC0_TMRDAT1 (SC0_BA+0x3C) /*!< SC0 Timer Current Data Register 1 */ + + #define REG_SC1_DAT (SC1_BA+0x00) /*!< SC1 Receiving/Transmit Holding Buffer Register */ + #define REG_SC1_CTL (SC1_BA+0x04) /*!< SC1 Control Register */ + #define REG_SC1_ALTCTL (SC1_BA+0x08) /*!< SC1 Alternate Control Register */ + #define REG_SC1_EGT (SC1_BA+0x0C) /*!< SC1 Extend Guard Time Register */ + #define REG_SC1_RXTOUT (SC1_BA+0x10) /*!< SC1 Receive Buffer Time-out Register */ + #define REG_SC1_ETUCTL (SC1_BA+0x14) /*!< SC1 ETU Control Register */ + #define REG_SC1_INTEN (SC1_BA+0x18) /*!< SC1 Interrupt Enable Control Register */ + #define REG_SC1_INTSTS (SC1_BA+0x1C) /*!< SC1 Interrupt Status Register */ + #define REG_SC1_STATUS (SC1_BA+0x20) /*!< SC1 Status Register */ + #define REG_SC1_PINCTL (SC1_BA+0x24) /*!< SC1 Pin Control State Register */ + #define REG_SC1_TMRCTL0 (SC1_BA+0x28) /*!< SC1 Internal Timer Control Register 0 */ + #define REG_SC1_TMRCTL1 (SC1_BA+0x2C) /*!< SC1 Internal Timer Control Register 1 */ + #define REG_SC1_TMRCTL2 (SC1_BA+0x30) /*!< SC1 Internal Timer Control Register 2 */ + #define REG_SC1_UARTCTL (SC1_BA+0x34) /*!< SC1 UART Mode Control Register */ + #define REG_SC1_TMRDAT0 (SC1_BA+0x38) /*!< SC1 Timer Current Data Register 0 */ + #define REG_SC1_TMRDAT1 (SC1_BA+0x3C) /*!< SC1 Timer Current Data Register 1 */ + + /**@}*/ /* end of SC register group */ + + + /*---------------------- Advance Interrupt Controller -------------------------*/ + /** + @addtogroup AIC Advance Interrupt Controller(AIC) + Memory Mapped Structure for AIC Controller + @{ */ + + #define REG_AIC_SCR1 (AIC_BA+0x00) /*!< Source control register 1 */ + #define REG_AIC_SCR2 (AIC_BA+0x04) /*!< Source control register 2 */ + #define REG_AIC_SCR3 (AIC_BA+0x08) /*!< Source control register 3 */ + #define REG_AIC_SCR4 (AIC_BA+0x0C) /*!< Source control register 4 */ + #define REG_AIC_SCR5 (AIC_BA+0x10) /*!< Source control register 5 */ + #define REG_AIC_SCR6 (AIC_BA+0x14) /*!< Source control register 6 */ + #define REG_AIC_SCR7 (AIC_BA+0x18) /*!< Source control register 7 */ + #define REG_AIC_SCR8 (AIC_BA+0x1C) /*!< Source control register 8 */ + #define REG_AIC_SCR9 (AIC_BA+0x20) /*!< Source control register 9 */ + #define REG_AIC_SCR10 (AIC_BA+0x24) /*!< Source control register 10 */ + #define REG_AIC_SCR11 (AIC_BA+0x28) /*!< Source control register 11 */ + #define REG_AIC_SCR12 (AIC_BA+0x2C) /*!< Source control register 12 */ + #define REG_AIC_SCR13 (AIC_BA+0x30) /*!< Source control register 13 */ + #define REG_AIC_SCR14 (AIC_BA+0x34) /*!< Source control register 14 */ + #define REG_AIC_SCR15 (AIC_BA+0x38) /*!< Source control register 15 */ + #define REG_AIC_SCR16 (AIC_BA+0x3C) /*!< Source control register 16 */ + #define REG_AIC_IRSR (AIC_BA+0x100) /*!< Interrupt raw status register */ + #define REG_AIC_IRSRH (AIC_BA+0x104) /*!< Interrupt raw status register (Hign) */ + #define REG_AIC_IASR (AIC_BA+0x108) /*!< Interrupt active status register */ + #define REG_AIC_IASRH (AIC_BA+0x10C) /*!< Interrupt active status register (Hign) */ + #define REG_AIC_ISR (AIC_BA+0x110) /*!< Interrupt status register */ + #define REG_AIC_ISRH (AIC_BA+0x114) /*!< Interrupt status register (High) */ + #define REG_AIC_IPER (AIC_BA+0x118) /*!< Interrupt priority encoding register */ + #define REG_AIC_ISNR (AIC_BA+0x120) /*!< Interrupt source number register */ + #define REG_AIC_OISR (AIC_BA+0x124) /*!< Output interrupt status register */ + #define REG_AIC_IMR (AIC_BA+0x128) /*!< Interrupt mask register */ + #define REG_AIC_IMRH (AIC_BA+0x12C) /*!< Interrupt mask register (High) */ + #define REG_AIC_MECR (AIC_BA+0x130) /*!< Mask enable command register */ + #define REG_AIC_MECRH (AIC_BA+0x134) /*!< Mask enable command register (High) */ + #define REG_AIC_MDCR (AIC_BA+0x138) /*!< Mask disable command register */ + #define REG_AIC_MDCRH (AIC_BA+0x13C) /*!< Mask disable command register (High) */ + #define REG_AIC_SSCR (AIC_BA+0x140) /*!< Source Set Command Register */ + #define REG_AIC_SSCRH (AIC_BA+0x144) /*!< Source Set Command Register (High) */ + #define REG_AIC_SCCR (AIC_BA+0x148) /*!< Source Clear Command Register */ + #define REG_AIC_SCCRH (AIC_BA+0x14C) /*!< Source Clear Command Register (High) */ + #define REG_AIC_EOSCR (AIC_BA+0x150) /*!< End of service command register */ + + /**@}*/ /* end of AIC register group */ + + + /*---------------------- General Purpose Input/Output Controller -------------------------*/ + /** + @addtogroup GPIO General Purpose Input/Output Controller(GPIO) + Memory Mapped Structure for GPIO Controller + @{ */ + + #define REG_GPIOA_DIR (GPIO_BA+0x000) /*!< GPIO portA direction control register */ + #define REG_GPIOA_DATAOUT (GPIO_BA+0x004) /*!< GPIO portA data output register */ + #define REG_GPIOA_DATAIN (GPIO_BA+0x008) /*!< GPIO portA data input register */ + #define REG_GPIOA_IMD (GPIO_BA+0x00C) /*!< GPIO Port A Interrupt Mode Register */ + #define REG_GPIOA_IREN (GPIO_BA+0x010) /*!< GPIO Port A Interrupt Rising-Edge or Level-High Enable Register */ + #define REG_GPIOA_IFEN (GPIO_BA+0x014) /*!< GPIO Port A Interrupt Falling-Edge or Level-Low Enable Register */ + #define REG_GPIOA_ISR (GPIO_BA+0x018) /*!< GPIO Port A Interrupt Status Register */ + #define REG_GPIOA_DBEN (GPIO_BA+0x01C) /*!< GPIO Port A De-bounce Enable Register */ + #define REG_GPIOA_PUEN (GPIO_BA+0x020) /*!< GPIO Port A Pull-Up Enable Register */ + #define REG_GPIOA_PDEN (GPIO_BA+0x024) /*!< GPIO Port A Pull-Down Enable Register */ + #define REG_GPIOA_ICEN (GPIO_BA+0x028) /*!< GPIO Port A CMOS Input Enable Register */ + #define REG_GPIOA_ISEN (GPIO_BA+0x02C) /*!< GPIO Port A Schmitt-Trigger Input Enable Register */ + + #define REG_GPIOB_DIR (GPIO_BA+0x040) /*!< GPIO port B direction control register */ + #define REG_GPIOB_DATAOUT (GPIO_BA+0x044) /*!< GPIO port B data output register */ + #define REG_GPIOB_DATAIN (GPIO_BA+0x048) /*!< GPIO port B data input register */ + #define REG_GPIOB_IMD (GPIO_BA+0x04C) /*!< GPIO Port B Interrupt Mode Register */ + #define REG_GPIOB_IREN (GPIO_BA+0x050) /*!< GPIO Port B Interrupt Rising-Edge or Level-High Enable Register */ + #define REG_GPIOB_IFEN (GPIO_BA+0x054) /*!< GPIO Port B Interrupt Falling-Edge or Level-Low Enable Register */ + #define REG_GPIOB_ISR (GPIO_BA+0x058) /*!< GPIO Port B Interrupt Status Register */ + #define REG_GPIOB_DBEN (GPIO_BA+0x05C) /*!< GPIO Port B De-bounce Enable Register */ + #define REG_GPIOB_PUEN (GPIO_BA+0x060) /*!< GPIO Port B Pull-Up Enable Register */ + #define REG_GPIOB_PDEN (GPIO_BA+0x064) /*!< GPIO Port B Pull-Down Enable Register */ + #define REG_GPIOB_ICEN (GPIO_BA+0x068) /*!< GPIO Port B CMOS Input Enable Register */ + #define REG_GPIOB_ISEN (GPIO_BA+0x06C) /*!< GPIO Port B Schmitt-Trigger Input Enable Register */ + + #define REG_GPIOC_DIR (GPIO_BA+0x080) /*!< GPIO port C direction control register */ + #define REG_GPIOC_DATAOUT (GPIO_BA+0x084) /*!< GPIO port C data output register */ + #define REG_GPIOC_DATAIN (GPIO_BA+0x088) /*!< GPIO port C data input register */ + #define REG_GPIOC_IMD (GPIO_BA+0x08C) /*!< GPIO Port C Interrupt Mode Register */ + #define REG_GPIOC_IREN (GPIO_BA+0x090) /*!< GPIO Port C Interrupt Rising-Edge or Level-High Enable Register */ + #define REG_GPIOC_IFEN (GPIO_BA+0x094) /*!< GPIO Port C Interrupt Falling-Edge or Level-Low Enable Register */ + #define REG_GPIOC_ISR (GPIO_BA+0x098) /*!< GPIO Port C Interrupt Status Register */ + #define REG_GPIOC_DBEN (GPIO_BA+0x09C) /*!< GPIO Port C De-bounce Enable Register */ + #define REG_GPIOC_PUEN (GPIO_BA+0x0A0) /*!< GPIO Port C Pull-Up Enable Register */ + #define REG_GPIOC_PDEN (GPIO_BA+0x0A4) /*!< GPIO Port C Pull-Down Enable Register */ + #define REG_GPIOC_ICEN (GPIO_BA+0x0A8) /*!< GPIO Port C CMOS Input Enable Register */ + #define REG_GPIOC_ISEN (GPIO_BA+0x0AC) /*!< GPIO Port C Schmitt-Trigger Input Enable Register */ + + #define REG_GPIOD_DIR (GPIO_BA+0x0C0) /*!< GPIO port D direction control register */ + #define REG_GPIOD_DATAOUT (GPIO_BA+0x0C4) /*!< GPIO port D data output register */ + #define REG_GPIOD_DATAIN (GPIO_BA+0x0C8) /*!< GPIO port D data input register */ + #define REG_GPIOD_IMD (GPIO_BA+0x0CC) /*!< GPIO Port D Interrupt Mode Register */ + #define REG_GPIOD_IREN (GPIO_BA+0x0D0) /*!< GPIO Port D Interrupt Rising-Edge or Level-High Enable Register */ + #define REG_GPIOD_IFEN (GPIO_BA+0x0D4) /*!< GPIO Port D Interrupt Falling-Edge or Level-Low Enable Register */ + #define REG_GPIOD_ISR (GPIO_BA+0x0D8) /*!< GPIO Port D Interrupt Status Register */ + #define REG_GPIOD_DBEN (GPIO_BA+0x0DC) /*!< GPIO Port D De-bounce Enable Register */ + #define REG_GPIOD_PUEN (GPIO_BA+0x0E0) /*!< GPIO Port D Pull-Up Enable Register */ + #define REG_GPIOD_PDEN (GPIO_BA+0x0E4) /*!< GPIO Port D Pull-Down Enable Register */ + #define REG_GPIOD_ICEN (GPIO_BA+0x0E8) /*!< GPIO Port D CMOS Input Enable Register */ + #define REG_GPIOD_ISEN (GPIO_BA+0x0EC) /*!< GPIO Port D Schmitt-Trigger Input Enable Register */ + + #define REG_GPIOE_DIR (GPIO_BA+0x100) /*!< GPIO port E direction control register */ + #define REG_GPIOE_DATAOUT (GPIO_BA+0x104) /*!< GPIO port E data output register */ + #define REG_GPIOE_DATAIN (GPIO_BA+0x108) /*!< GPIO port E data input register */ + #define REG_GPIOE_IMD (GPIO_BA+0x10C) /*!< GPIO Port E Interrupt Mode Register */ + #define REG_GPIOE_IREN (GPIO_BA+0x110) /*!< GPIO Port E Interrupt Rising-Edge or Level-High Enable Register */ + #define REG_GPIOE_IFEN (GPIO_BA+0x114) /*!< GPIO Port E Interrupt Falling-Edge or Level-Low Enable Register */ + #define REG_GPIOE_ISR (GPIO_BA+0x118) /*!< GPIO Port E Interrupt Status Register */ + #define REG_GPIOE_DBEN (GPIO_BA+0x11C) /*!< GPIO Port E De-bounce Enable Register */ + #define REG_GPIOE_PUEN (GPIO_BA+0x120) /*!< GPIO Port E Pull-Up Enable Register */ + #define REG_GPIOE_PDEN (GPIO_BA+0x124) /*!< GPIO Port E Pull-Down Enable Register */ + #define REG_GPIOE_ICEN (GPIO_BA+0x128) /*!< GPIO Port E CMOS Input Enable Register */ + #define REG_GPIOE_ISEN (GPIO_BA+0x12C) /*!< GPIO Port E Schmitt-Trigger Input Enable Register */ + + #define REG_GPIOF_DIR (GPIO_BA+0x140) /*!< GPIO port F direction control register */ + #define REG_GPIOF_DATAOUT (GPIO_BA+0x144) /*!< GPIO port F data output register */ + #define REG_GPIOF_DATAIN (GPIO_BA+0x148) /*!< GPIO port F data input register */ + #define REG_GPIOF_IMD (GPIO_BA+0x14C) /*!< GPIO Port F Interrupt Mode Register */ + #define REG_GPIOF_IREN (GPIO_BA+0x150) /*!< GPIO Port F Interrupt Rising-Edge or Level-High Enable Register */ + #define REG_GPIOF_IFEN (GPIO_BA+0x154) /*!< GPIO Port F Interrupt Falling-Edge or Level-Low Enable Register */ + #define REG_GPIOF_ISR (GPIO_BA+0x158) /*!< GPIO Port F Interrupt Status Register */ + #define REG_GPIOF_DBEN (GPIO_BA+0x15C) /*!< GPIO Port F De-bounce Enable Register */ + #define REG_GPIOF_PUEN (GPIO_BA+0x160) /*!< GPIO Port F Pull-Up Enable Register */ + #define REG_GPIOF_PDEN (GPIO_BA+0x164) /*!< GPIO Port F Pull-Down Enable Register */ + #define REG_GPIOF_ICEN (GPIO_BA+0x168) /*!< GPIO Port F CMOS Input Enable Register */ + #define REG_GPIOF_ISEN (GPIO_BA+0x16C) /*!< GPIO Port F Schmitt-Trigger Input Enable Register */ + + #define REG_GPIOG_DIR (GPIO_BA+0x180) /*!< GPIO port G direction control register */ + #define REG_GPIOG_DATAOUT (GPIO_BA+0x184) /*!< GPIO port G data output register */ + #define REG_GPIOG_DATAIN (GPIO_BA+0x188) /*!< GPIO port G data input register */ + #define REG_GPIOG_IMD (GPIO_BA+0x18C) /*!< GPIO Port G Interrupt Mode Register */ + #define REG_GPIOG_IREN (GPIO_BA+0x190) /*!< GPIO Port G Interrupt Rising-Edge or Level-High Enable Register */ + #define REG_GPIOG_IFEN (GPIO_BA+0x194) /*!< GPIO Port G Interrupt Falling-Edge or Level-Low Enable Register */ + #define REG_GPIOG_ISR (GPIO_BA+0x198) /*!< GPIO Port G Interrupt Status Register */ + #define REG_GPIOG_DBEN (GPIO_BA+0x19C) /*!< GPIO Port G De-bounce Enable Register */ + #define REG_GPIOG_PUEN (GPIO_BA+0x1A0) /*!< GPIO Port G Pull-Up Enable Register */ + #define REG_GPIOG_PDEN (GPIO_BA+0x1A4) /*!< GPIO Port G Pull-Down Enable Register */ + #define REG_GPIOG_ICEN (GPIO_BA+0x1A8) /*!< GPIO Port G CMOS Input Enable Register */ + #define REG_GPIOG_ISEN (GPIO_BA+0x1AC) /*!< GPIO Port G Schmitt-Trigger Input Enable Register */ + + #define REG_GPIOH_DIR (GPIO_BA+0x1C0) /*!< GPIO port H direction control register */ + #define REG_GPIOH_DATAOUT (GPIO_BA+0x1C4) /*!< GPIO port H data output register */ + #define REG_GPIOH_DATAIN (GPIO_BA+0x1C8) /*!< GPIO port H data input register */ + #define REG_GPIOH_IMD (GPIO_BA+0x1CC) /*!< GPIO Port H Interrupt Mode Register */ + #define REG_GPIOH_IREN (GPIO_BA+0x1D0) /*!< GPIO Port H Interrupt Rising-Edge or Level-High Enable Register */ + #define REG_GPIOH_IFEN (GPIO_BA+0x1D4) /*!< GPIO Port H Interrupt Falling-Edge or Level-Low Enable Register */ + #define REG_GPIOH_ISR (GPIO_BA+0x1D8) /*!< GPIO Port H Interrupt Status Register */ + #define REG_GPIOH_DBEN (GPIO_BA+0x1DC) /*!< GPIO Port H De-bounce Enable Register */ + #define REG_GPIOH_PUEN (GPIO_BA+0x1E0) /*!< GPIO Port H Pull-Up Enable Register */ + #define REG_GPIOH_PDEN (GPIO_BA+0x1E4) /*!< GPIO Port H Pull-Down Enable Register */ + #define REG_GPIOH_ICEN (GPIO_BA+0x1E8) /*!< GPIO Port H CMOS Input Enable Register */ + #define REG_GPIOH_ISEN (GPIO_BA+0x1EC) /*!< GPIO Port H Schmitt-Trigger Input Enable Register */ + + #define REG_GPIOI_DIR (GPIO_BA+0x200) /*!< GPIO port I direction control register */ + #define REG_GPIOI_DATAOUT (GPIO_BA+0x204) /*!< GPIO port I data output register */ + #define REG_GPIOI_DATAIN (GPIO_BA+0x208) /*!< GPIO port I data input register */ + #define REG_GPIOI_IMD (GPIO_BA+0x20C) /*!< GPIO Port I Interrupt Mode Register */ + #define REG_GPIOI_IREN (GPIO_BA+0x210) /*!< GPIO Port I Interrupt Rising-Edge or Level-High Enable Register */ + #define REG_GPIOI_IFEN (GPIO_BA+0x214) /*!< GPIO Port I Interrupt Falling-Edge or Level-Low Enable Register */ + #define REG_GPIOI_ISR (GPIO_BA+0x218) /*!< GPIO Port I Interrupt Status Register */ + #define REG_GPIOI_DBEN (GPIO_BA+0x21C) /*!< GPIO Port I De-bounce Enable Register */ + #define REG_GPIOI_PUEN (GPIO_BA+0x220) /*!< GPIO Port I Pull-Up Enable Register */ + #define REG_GPIOI_PDEN (GPIO_BA+0x224) /*!< GPIO Port I Pull-Down Enable Register */ + #define REG_GPIOI_ICEN (GPIO_BA+0x228) /*!< GPIO Port I CMOS Input Enable Register */ + #define REG_GPIOI_ISEN (GPIO_BA+0x22C) /*!< GPIO Port I Schmitt-Trigger Input Enable Register */ + + #define REG_GPIOJ_DIR (GPIO_BA+0x240) /*!< GPIO port J direction control register */ + #define REG_GPIOJ_DATAOUT (GPIO_BA+0x244) /*!< GPIO port J data output register */ + #define REG_GPIOJ_DATAIN (GPIO_BA+0x248) /*!< GPIO port J data input register */ + #define REG_GPIOJ_IMD (GPIO_BA+0x24C) /*!< GPIO Port J Interrupt Mode Register */ + #define REG_GPIOJ_IREN (GPIO_BA+0x250) /*!< GPIO Port J Interrupt Rising-Edge or Level-High Enable Register */ + #define REG_GPIOJ_IFEN (GPIO_BA+0x254) /*!< GPIO Port J Interrupt Falling-Edge or Level-Low Enable Register */ + #define REG_GPIOJ_ISR (GPIO_BA+0x258) /*!< GPIO Port J Interrupt Status Register */ + #define REG_GPIOJ_DBEN (GPIO_BA+0x25C) /*!< GPIO Port J De-bounce Enable Register */ + #define REG_GPIOJ_PUEN (GPIO_BA+0x260) /*!< GPIO Port J Pull-Up Enable Register */ + #define REG_GPIOJ_PDEN (GPIO_BA+0x264) /*!< GPIO Port J Pull-Down Enable Register */ + #define REG_GPIOJ_ICEN (GPIO_BA+0x268) /*!< GPIO Port J CMOS Input Enable Register */ + #define REG_GPIOJ_ISEN (GPIO_BA+0x26C) /*!< GPIO Port J Schmitt-Trigger Input Enable Register */ + + #define REG_GPIO_DBNCECON (GPIO_BA+0x3F0) /*!< GPIO Debounce Control Register */ + #define REG_GPIO_ISR (GPIO_BA+0x3FC) /*!< GPIO Port Interrupt Status Register */ + + /**@}*/ /* end of GPIO register group */ + + + /*---------------------- Real Time Clock Controller -------------------------*/ + /** + @addtogroup RTC Real Time Clock Controller(RTC) + Memory Mapped Structure for RTC Controller + @{ */ + + #define REG_RTC_INIT (RTC_BA+0x00) /*!< RTC Initiation Register */ + #define REG_RTC_RWEN (RTC_BA+0x04) /*!< RTC Access Enable Register */ + #define REG_RTC_FREQADJ (RTC_BA+0x08) /*!< RTC Frequency Compensation Register */ + #define REG_RTC_TIME (RTC_BA+0x0C) /*!< Time Loading Register */ + #define REG_RTC_CAL (RTC_BA+0x10) /*!< Calendar Loading Register */ + #define REG_RTC_TIMEFMT (RTC_BA+0x14) /*!< Time Format Selection Register */ + #define REG_RTC_WEEKDAY (RTC_BA+0x18) /*!< Day of the Week Register */ + #define REG_RTC_TALM (RTC_BA+0x1C) /*!< Time Alarm Register */ + #define REG_RTC_CALM (RTC_BA+0x20) /*!< Calendar Alarm Register */ + #define REG_RTC_LEAPYEAR (RTC_BA+0x24) /*!< Leap year Indicator Register */ + #define REG_RTC_INTEN (RTC_BA+0x28) /*!< RTC Interrupt Enable Register */ + #define REG_RTC_INTSTS (RTC_BA+0x2C) /*!< RTC Interrupt Indicator Register */ + #define REG_RTC_TICK (RTC_BA+0x30) /*!< RTC Time Tick Register */ + #define REG_RTC_PWRCTL (RTC_BA+0x34) /*!< Power Control Register */ + #define REG_RTC_PWRCNT (RTC_BA+0x38) /*!< Power Control Counter Register */ + #define REG_RTC_SPR0 (RTC_BA+0x40) /*!< Spare REgistger 0 */ + #define REG_RTC_SPR1 (RTC_BA+0x44) /*!< Spare REgistger 1 */ + #define REG_RTC_SPR2 (RTC_BA+0x48) /*!< Spare REgistger 2 */ + #define REG_RTC_SPR3 (RTC_BA+0x4C) /*!< Spare REgistger 3 */ + #define REG_RTC_SPR4 (RTC_BA+0x50) /*!< Spare REgistger 4 */ + #define REG_RTC_SPR5 (RTC_BA+0x54) /*!< Spare REgistger 5 */ + #define REG_RTC_SPR6 (RTC_BA+0x58) /*!< Spare REgistger 6 */ + #define REG_RTC_SPR7 (RTC_BA+0x5C) /*!< Spare REgistger 7 */ + #define REG_RTC_SPR8 (RTC_BA+0x60) /*!< Spare REgistger 8 */ + #define REG_RTC_SPR9 (RTC_BA+0x64) /*!< Spare REgistger 9 */ + #define REG_RTC_SPR10 (RTC_BA+0x68) /*!< Spare REgistger 10 */ + #define REG_RTC_SPR11 (RTC_BA+0x6C) /*!< Spare REgistger 11 */ + #define REG_RTC_SPR12 (RTC_BA+0x70) /*!< Spare REgistger 12 */ + #define REG_RTC_SPR13 (RTC_BA+0x74) /*!< Spare REgistger 13 */ + #define REG_RTC_SPR14 (RTC_BA+0x78) /*!< Spare REgistger 14 */ + #define REG_RTC_SPR15 (RTC_BA+0x7C) /*!< Spare REgistger 15 */ + + /**@}*/ /* end of RTC register group */ + + /*---------------------- Inter-IC Bus Controller -------------------------*/ + /** + @addtogroup I2C Inter-IC Bus Controller(I2C) + Memory Mapped Structure for I2C Controller + @{ */ + + #define REG_I2C0_CSR (I2C0_BA+0x00) /*!< Control and Status Register */ + #define REG_I2C0_DIVIDER (I2C0_BA+0x04) /*!< Clock Prescale Register */ + #define REG_I2C0_CMDR (I2C0_BA+0x08) /*!< Command Register */ + #define REG_I2C0_SWR (I2C0_BA+0x0C) /*!< Software Mode Control Register */ + #define REG_I2C0_RXR (I2C0_BA+0x10) /*!< Data Receive Register */ + #define REG_I2C0_TXR (I2C0_BA+0x14) /*!< Data Transmit Register */ + + #define REG_I2C1_CSR (I2C1_BA+0x00) /*!< Control and Status Register */ + #define REG_I2C1_DIVIDER (I2C1_BA+0x04) /*!< Clock Prescale Register */ + #define REG_I2C1_CMDR (I2C1_BA+0x08) /*!< Command Register */ + #define REG_I2C1_SWR (I2C1_BA+0x0C) /*!< Software Mode Control Register */ + #define REG_I2C1_RXR (I2C1_BA+0x10) /*!< Data Receive Register */ + #define REG_I2C1_TXR (I2C1_BA+0x14) /*!< Data Transmit Register */ + + /**@}*/ /* end of I2C register group */ + + + /*---------------------- Serial Peripheral Interface Controller -------------------------*/ + /** + @addtogroup SPI Serial Peripheral Interface Controller(SPI) + Memory Mapped Structure for SPI Controller + @{ */ + + #define REG_SPI0_CNTRL (SPI0_BA+0x00) /*!< Control and Status Register */ + #define REG_SPI0_DIVIDER (SPI0_BA+0x04) /*!< Clock Divider Register */ + #define REG_SPI0_SSR (SPI0_BA+0x08) /*!< Slave Select Register */ + #define REG_SPI0_RX0 (SPI0_BA+0x10) /*!< Data Receive Register 0 */ + #define REG_SPI0_RX1 (SPI0_BA+0x14) /*!< Data Receive Register 1 */ + #define REG_SPI0_RX2 (SPI0_BA+0x18) /*!< Data Receive Register 2 */ + #define REG_SPI0_RX3 (SPI0_BA+0x1C) /*!< Data Receive Register 3 */ + #define REG_SPI0_TX0 (SPI0_BA+0x10) /*!< Data Transmit Register 0 */ + #define REG_SPI0_TX1 (SPI0_BA+0x14) /*!< Data Transmit Register 1 */ + #define REG_SPI0_TX2 (SPI0_BA+0x18) /*!< Data Transmit Register 2 */ + #define REG_SPI0_TX3 (SPI0_BA+0x1C) /*!< Data Transmit Register 3 */ + + #define REG_SPI1_CNTRL (SPI1_BA+0x00) /*!< Control and Status Register */ + #define REG_SPI1_DIVIDER (SPI1_BA+0x04) /*!< Clock Divider Register */ + #define REG_SPI1_SSR (SPI1_BA+0x08) /*!< Slave Select Register */ + #define REG_SPI1_RX0 (SPI1_BA+0x10) /*!< Data Receive Register 0 */ + #define REG_SPI1_RX1 (SPI1_BA+0x14) /*!< Data Receive Register 1 */ + #define REG_SPI1_RX2 (SPI1_BA+0x18) /*!< Data Receive Register 2 */ + #define REG_SPI1_RX3 (SPI1_BA+0x1C) /*!< Data Receive Register 3 */ + #define REG_SPI1_TX0 (SPI1_BA+0x10) /*!< Data Transmit Register 0 */ + #define REG_SPI1_TX1 (SPI1_BA+0x14) /*!< Data Transmit Register 1 */ + #define REG_SPI1_TX2 (SPI1_BA+0x18) /*!< Data Transmit Register 2 */ + #define REG_SPI1_TX3 (SPI1_BA+0x1C) /*!< Data Transmit Register 3 */ + + /**@}*/ /* end of SPI register group */ + + + /*---------------------- Pulse Width Modulation Controller -------------------------*/ + /** + @addtogroup PWM Pulse Width Modulation Controller(PWM) + Memory Mapped Structure for PWM Controller + @{ */ + + #define REG_PWM_PPR (PWM_BA+0x00) /*!< PWM Pre-scale Register 0 */ + #define REG_PWM_CSR (PWM_BA+0x04) /*!< PWM Clock Select Register */ + #define REG_PWM_PCR (PWM_BA+0x08) /*!< PWM Control Register */ + #define REG_PWM_CNR0 (PWM_BA+0x0C) /*!< PWM Counter Register 0 */ + #define REG_PWM_CMR0 (PWM_BA+0x10) /*!< PWM Comparator Register 0 */ + #define REG_PWM_PDR0 (PWM_BA+0x14) /*!< PWM Data Register 0 */ + #define REG_PWM_CNR1 (PWM_BA+0x18) /*!< PWM Counter Register 1 */ + #define REG_PWM_CMR1 (PWM_BA+0x1C) /*!< PWM Comparator Register 1 */ + #define REG_PWM_PDR1 (PWM_BA+0x20) /*!< PWM Data Register 1 */ + #define REG_PWM_CNR2 (PWM_BA+0x24) /*!< PWM Counter Register 2 */ + #define REG_PWM_CMR2 (PWM_BA+0x28) /*!< PWM Comparator Register 2 */ + #define REG_PWM_PDR2 (PWM_BA+0x2C) /*!< PWM Data Register 2 */ + #define REG_PWM_CNR3 (PWM_BA+0x30) /*!< PWM Counter Register 3 */ + #define REG_PWM_CMR3 (PWM_BA+0x34) /*!< PWM Comparator Register 3 */ + #define REG_PWM_PDR3 (PWM_BA+0x38) /*!< PWM Data Register 3 */ + #define REG_PWM_PIER (PWM_BA+0x3C) /*!< PWM Timer Interrupt Enable Register */ + #define REG_PWM_PIIR (PWM_BA+0x40) /*!< PWM Timer Interrupt Identification Register */ + + /**@}*/ /* end of PWM register group */ + + + /*---------------------- Analog to Digital Converter -------------------------*/ + /** + @addtogroup ADC Analog to Digital Converter(ADC) + Memory Mapped Structure for ADC Controller + @{ */ + + #define REG_ADC_CTL (ADC_BA+0x000) /*!< ADC Contrl */ + #define REG_ADC_CONF (ADC_BA+0x004) /*!< ADC Configure */ + #define REG_ADC_IER (ADC_BA+0x008) /*!< ADC Interrupt Enable Register */ + #define REG_ADC_ISR (ADC_BA+0x00C) /*!< ADC Interrupt Status Register */ + #define REG_ADC_WKISR (ADC_BA+0x010) /*!< ADC Wake Up Interrupt Status Register */ + #define REG_ADC_XYDATA (ADC_BA+0x020) /*!< ADC Touch XY Pressure Data */ + #define REG_ADC_ZDATA (ADC_BA+0x024) /*!< ADC Touch Z Pressure Data */ + #define REG_ADC_DATA (ADC_BA+0x028) /*!< ADC Normal Conversion Data */ + #define REG_ADC_VBADATA (ADC_BA+0x02C) /*!< ADC Battery Detection Data */ + #define REG_ADC_KPDATA (ADC_BA+0x030) /*!< ADC Key Pad Data */ + #define REG_ADC_SELFDATA (ADC_BA+0x034) /*!< ADC Self-Test Data */ + #define REG_ADC_XYSORT0 (ADC_BA+0x1F4) /*!< ADC Touch XY Position Mean Value Sort 0 */ + #define REG_ADC_XYSORT1 (ADC_BA+0x1F8) /*!< ADC Touch XY Position Mean Value Sort 1 */ + #define REG_ADC_XYSORT2 (ADC_BA+0x1FC) /*!< ADC Touch XY Position Mean Value Sort 2 */ + #define REG_ADC_XYSORT3 (ADC_BA+0x200) /*!< ADC Touch XY Position Mean Value Sort 3 */ + #define REG_ADC_ZSORT0 (ADC_BA+0x204) /*!< ADC Touch Z Pressure Mean Value Sort 0 */ + #define REG_ADC_ZSORT1 (ADC_BA+0x208) /*!< ADC Touch Z Pressure Mean Value Sort 1 */ + #define REG_ADC_ZSORT2 (ADC_BA+0x20C) /*!< ADC Touch Z Pressure Mean Value Sort 2 */ + #define REG_ADC_ZSORT3 (ADC_BA+0x210) /*!< ADC Touch Z Pressure Mean Value Sort 3 */ + #define REG_ADC_MTMULCK (ADC_BA+0x220) /*!< ADC Manual Test Mode Unlock */ + #define REG_ADC_MTCONF (ADC_BA+0x224) /*!< ADC Manual Test Mode Configure */ + #define REG_ADC_MTCON (ADC_BA+0x228) /*!< ADC Manual Test Mode Control */ + #define REG_ADC_ADCAII (ADC_BA+0x22C) /*!< ADC Analog Interface Information */ + #define REG_ADC_ADCAIIRLT (ADC_BA+0x230) /*!< ADC Analog Interface Information Result */ + + /**@}*/ /* end of ADC register group */ + + /*------------------ Capture Sensor Interface Controller ---------------------*/ + /** + @addtogroup CAP Capture Sensor Interface Controller(CAP) + Memory Mapped Structure for CAP Controller + @{ */ + + #define REG_CAP_CTL (CAP_BA+0x000) /*!< Image Capture Interface Control Register */ + #define REG_CAP_PAR (CAP_BA+0x004) /*!< Image Capture Interface Parameter Register */ + #define REG_CAP_INT (CAP_BA+0x008) /*!< Image Capture Interface Interrupt Registe */ + #define REG_CAP_POSTERIZE (CAP_BA+0x00C) /*!< YUV Component Posterizing Factor Register */ + #define REG_CAP_MD (CAP_BA+0x010) /*!< Motion Detection Register */ + #define REG_CAP_MDADDR (CAP_BA+0x014) /*!< Motion Detection Output Address Register */ + #define REG_CAP_MDYADDR (CAP_BA+0x018) /*!< Motion Detection Temp YOutput Address Register */ + #define REG_CAP_SEPIA (CAP_BA+0x01C) /*!< Sepia Effect Control Register */ + #define REG_CAP_CWSP (CAP_BA+0x020) /*!< Cropping Window Starting Address Register */ + #define REG_CAP_CWS (CAP_BA+0x024) /*!< Cropping Window Size Register */ + #define REG_CAP_PKTSL (CAP_BA+0x028) /*!< Packet Scaling Vertical/Horizontal Factor Register (LSB) */ + #define REG_CAP_PLNSL (CAP_BA+0x02C) /*!< Planar Scaling Vertical/Horizontal Factor Register (LSB) */ + #define REG_CAP_FRCTL (CAP_BA+0x030) /*!< Scaling Frame Rate Factor Register */ + #define REG_CAP_STRIDE (CAP_BA+0x034) /*!< Frame Output Pixel Stride Register */ + #define REG_CAP_FIFOTH (CAP_BA+0x03C) /*!< FIFO threshold Register */ + #define REG_CAP_CMPADDR (CAP_BA+0x040) /*!< Compare Packet Memory Base Address Register */ + #define REG_CAP_PKTSM (CAP_BA+0x048) /*!< Packet Scaling Vertical/Horizontal Factor Register (MSB) */ + #define REG_CAP_PLNSM (CAP_BA+0x04C) /*!< Planar Scaling Vertical/Horizontal Factor Register (MSB) */ + #define REG_CAP_CURADDRP (CAP_BA+0x050) /*!< Current Packet System Memory Address Register */ + #define REG_CAP_CURADDRY (CAP_BA+0x054) /*!< Current Planar Y System Memory Address Register */ + #define REG_CAP_CURADDRU (CAP_BA+0x058) /*!< Current Planar U System Memory Address Register */ + #define REG_CAP_CURADDRV (CAP_BA+0x05C) /*!< Current Planar V System Memory Address Register */ + #define REG_CAP_PKTBA0 (CAP_BA+0x060) /*!< System Memory Packet Base Address Register */ + #define REG_CAP_PKTBA1 (CAP_BA+0x064) /*!< System Memory Packet Base Address Register */ + #define REG_CAP_YBA (CAP_BA+0x080) /*!< System Memory Planar Y Base Address Register */ + #define REG_CAP_UBA (CAP_BA+0x084) /*!< System Memory Planar U Base Address Register */ + #define REG_CAP_VBA (CAP_BA+0x088) /*!< System Memory Planar V Base Address Register */ + + /**@}*/ /* end of CAP register group */ + + /*------------------ SDRAM Interface Controller ---------------------*/ + /** + @addtogroup SDIC SDRAM Interface Controller(SDIC) + Memory Mapped Structure for SDIC Controller + @{ */ + + #define REG_SDIC_OPMCTL (SDIC_BA+0x000) /*!< SDRAM Controller Operation Mode Control Register */ + #define REG_SDIC_CMD (SDIC_BA+0x004) /*!< SDRAM Command Register */ + #define REG_SDIC_REFCTL (SDIC_BA+0x008) /*!< SDRAM Controller Refresh Control Register */ + #define REG_SDIC_SIZE0 (SDIC_BA+0x010) /*!< SDRAM 0 Size Register */ + #define REG_SDIC_SIZE1 (SDIC_BA+0x014) /*!< SDRAM 1 Size Register */ + #define REG_SDIC_MR (SDIC_BA+0x018) /*!< SDRAM Mode Register */ + #define REG_SDIC_EMR (SDIC_BA+0x01C) /*!< SDRAM Extended Mode Register */ + #define REG_SDIC_EMR2 (SDIC_BA+0x020) /*!< SDRAM Extended Mode Register 2 */ + #define REG_SDIC_EMR3 (SDIC_BA+0x024) /*!< SDRAM Extended Mode Register 3 */ + #define REG_SDIC_TIME (SDIC_BA+0x028) /*!< SDRAM Timing Control Register */ + #define REG_SDIC_DQSODS (SDIC_BA+0x030) /*!< DQS Output Delay Selection Register */ + #define REG_SDIC_CKDQSDS (SDIC_BA+0x034) /*!< Clock and DQS Delay Selection Register */ + #define REG_SDIC_DAENSEL (SDIC_BA+0x038) /*!< Data Latch Enable Selection Register */ + + /**@}*/ /* end of SDIC register group */ + + /*---------------------- Controller Area Network -------------------------*/ + /** + @addtogroup CAN Controller Area Network(CAN) + Memory Mapped Structure for CAN Controller + @{ */ + + #define REG_CAN0_CON (CAN0_BA+0x00) /*!< Control Register */ + #define REG_CAN0_STATUS (CAN0_BA+0x04) /*!< Status Register */ + #define REG_CAN0_ERR (CAN0_BA+0x08) /*!< Error Counter Register */ + #define REG_CAN0_BTIME (CAN0_BA+0x0C) /*!< Bit Time Register */ + #define REG_CAN0_IIDR (CAN0_BA+0x10) /*!< Interrupt Identifier Register */ + #define REG_CAN0_TEST (CAN0_BA+0x14) /*!< Test Register */ + #define REG_CAN0_BRPE (CAN0_BA+0x18) /*!< BRP Extension Register */ + #define REG_CAN0_IF1_CREQ (CAN0_BA+0x20) /*!< IF1 Command Request Register */ + #define REG_CAN0_IF2_CREQ (CAN0_BA+0x80) /*!< IF2 Command Request Register */ + #define REG_CAN0_IF1_CMASK (CAN0_BA+0x24) /*!< IF1 Command Mask Register */ + #define REG_CAN0_IF2_CMASK (CAN0_BA+0x84) /*!< IF2 Command Mask Register */ + #define REG_CAN0_IF1_MASK1 (CAN0_BA+0x28) /*!< IF1 Msak 1 Register */ + #define REG_CNA0_IF2_MASK1 (CAN0_BA+0x88) /*!< IF2 Mask 1 Register */ + #define REG_CAN0_IF1_MASK2 (CAN0_BA+0x2C) /*!< IF1 Mask 2 Register */ + #define REG_CAN0_IF2_MASK2 (CAN0_BA+0x8C) /*!< IF2 Mask 2 REgister */ + #define REG_CAN0_IF1_ARB1 (CAN0_BA+0x30) /*!< IF1 Arbitration 1 Register */ + #define REG_CAN0_IF2_ARB1 (CAN0_BA+0x90) /*!< IF2 Arbitration 1 Register */ + #define REG_CAN0_IF1_ARB2 (CAN0_BA+0x34) /*!< IF1 Arbitration 2 Register */ + #define REG_CAN0_IF2_ARB2 (CAN0_BA+0x94) /*!< IF2 Arbitration 2 Register */ + #define REG_CAN0_IF1_MCON (CAN0_BA+0x38) /*!< IF1 Message Control Register */ + #define REG_CAN0_IF2_MCON (CAN0_BA+0x98) /*!< IF2 Message Control Register */ + #define REG_CAN0_IF1_DAT_A1 (CAN0_BA+0x3C) /*!< IF1 Data A1 Register */ + #define REG_CAN0_IF1_DAT_A2 (CAN0_BA+0x40) /*!< IF1 Data A2 Register */ + #define REG_CAN0_IF1_DAT_B1 (CAN0_BA+0x44) /*!< IF1 Data B1 Register */ + #define REG_CAN0_IF1_DAT_B2 (CAN0_BA+0x48) /*!< IF1 Data B2 Register */ + #define REG_CAN0_IF2_DAT_A1 (CAN0_BA+0x9C) /*!< IF2 Data A1 Register */ + #define REG_CAN0_IF2_DAT_A2 (CAN0_BA+0xA0) /*!< IF2 Data A2 Register */ + #define REG_CAN0_IF2_DAT_B1 (CAN0_BA+0xA4) /*!< IF2 Data B1 Register */ + #define REG_CAN0_IF2_DAT_B2 (CAN0_BA+0xA8) /*!< IF2 Data B2 Register */ + #define REG_CAN0_TXREQ1 (CAN0_BA+0x100) /*!< Transmission Request Register 1 */ + #define REG_CAN0_TXREQ2 (CAN0_BA+0x104) /*!< Transmission Request Register 2 */ + #define REG_CAN0_NDAT1 (CAN0_BA+0x120) /*!< New Data Register 1 */ + #define REG_CAN0_NDAT2 (CAN0_BA+0x124) /*!< New Data Register 2 */ + #define REG_CAN0_IPND1 (CAN0_BA+0x140) /*!< Interrupt Pending Register 1 */ + #define REG_CAN0_IPND2 (CAN0_BA+0x142) /*!< Interrupt Pending Register 2 */ + #define REG_CAN0_MVLD1 (CAN0_BA+0x160) /*!< Message Valid Register 1 */ + #define REG_CAN0_MVLD2 (CAN0_BA+0x164) /*!< Message Valid Register 2 */ + #define REG_CAN0_WU_EN (CAN0_BA+0x168) /*!< Wake-up Function Enable */ + #define REG_CAN0_WU_STATUS (CAN0_BA+0x16C) /*!< Wake-up Function Status */ + + #define REG_CAN1_CON (CAN1_BA+0x00) /*!< Control Register */ + #define REG_CAN1_STATUS (CAN1_BA+0x04) /*!< Status Register */ + #define REG_CAN1_ERR (CAN1_BA+0x08) /*!< Error Counter Register */ + #define REG_CAN1_BTIME (CAN1_BA+0x0C) /*!< Bit Time Register */ + #define REG_CAN1_IIDR (CAN1_BA+0x10) /*!< Interrupt Identifier Register */ + #define REG_CAN1_TEST (CAN1_BA+0x14) /*!< Test Register */ + #define REG_CAN1_BRPE (CAN1_BA+0x18) /*!< BRP Extension Register */ + #define REG_CAN1_IF1_CREQ (CAN1_BA+0x20) /*!< IF1 Command Request Register */ + #define REG_CAN1_IF2_CREQ (CAN1_BA+0x80) /*!< IF2 Command Request Register */ + #define REG_CAN1_IF1_CMASK (CAN1_BA+0x24) /*!< IF1 Command Mask Register */ + #define REG_CAN1_IF2_CMASK (CAN1_BA+0x84) /*!< IF2 Command Mask Register */ + #define REG_CAN1_IF1_MASK1 (CAN1_BA+0x28) /*!< IF1 Msak 1 Register */ + #define REG_CNA1_IF2_MASK1 (CAN1_BA+0x88) /*!< IF2 Mask 1 Register */ + #define REG_CAN1_IF1_MASK2 (CAN1_BA+0x2C) /*!< IF1 Mask 2 Register */ + #define REG_CAN1_IF2_MASK2 (CAN1_BA+0x8C) /*!< IF2 Mask 2 REgister */ + #define REG_CAN1_IF1_ARB1 (CAN1_BA+0x30) /*!< IF1 Arbitration 1 Register */ + #define REG_CAN1_IF2_ARB1 (CAN1_BA+0x90) /*!< IF2 Arbitration 1 Register */ + #define REG_CAN1_IF1_ARB2 (CAN1_BA+0x34) /*!< IF1 Arbitration 2 Register */ + #define REG_CAN1_IF2_ARB2 (CAN1_BA+0x94) /*!< IF2 Arbitration 2 Register */ + #define REG_CAN1_IF1_MCON (CAN1_BA+0x38) /*!< IF1 Message Control Register */ + #define REG_CAN1_IF2_MCON (CAN1_BA+0x98) /*!< IF2 Message Control Register */ + #define REG_CAN1_IF1_DAT_A1 (CAN1_BA+0x3C) /*!< IF1 Data A1 Register */ + #define REG_CAN1_IF1_DAT_A2 (CAN1_BA+0x40) /*!< IF1 Data A2 Register */ + #define REG_CAN1_IF1_DAT_B1 (CAN1_BA+0x44) /*!< IF1 Data B1 Register */ + #define REG_CAN1_IF1_DAT_B2 (CAN1_BA+0x48) /*!< IF1 Data B2 Register */ + #define REG_CAN1_IF2_DAT_A1 (CAN1_BA+0x9C) /*!< IF2 Data A1 Register */ + #define REG_CAN1_IF2_DAT_A2 (CAN1_BA+0xA0) /*!< IF2 Data A2 Register */ + #define REG_CAN1_IF2_DAT_B1 (CAN1_BA+0xA4) /*!< IF2 Data B1 Register */ + #define REG_CAN1_IF2_DAT_B2 (CAN1_BA+0xA8) /*!< IF2 Data B2 Register */ + #define REG_CAN1_TXREQ1 (CAN1_BA+0x100) /*!< Transmission Request Register 1 */ + #define REG_CAN1_TXREQ2 (CAN1_BA+0x104) /*!< Transmission Request Register 2 */ + #define REG_CAN1_NDAT1 (CAN1_BA+0x120) /*!< New Data Register 1 */ + #define REG_CAN1_NDAT2 (CAN1_BA+0x124) /*!< New Data Register 2 */ + #define REG_CAN1_IPND1 (CAN1_BA+0x140) /*!< Interrupt Pending Register 1 */ + #define REG_CAN1_IPND2 (CAN1_BA+0x142) /*!< Interrupt Pending Register 2 */ + #define REG_CAN1_MVLD1 (CAN1_BA+0x160) /*!< Message Valid Register 1 */ + #define REG_CAN1_MVLD2 (CAN1_BA+0x164) /*!< Message Valid Register 2 */ + #define REG_CAN1_WU_EN (CAN1_BA+0x168) /*!< Wake-up Function Enable */ + #define REG_CAN1_WU_STATUS (CAN1_BA+0x16C) /*!< Wake-up Function Status */ + + /**@}*/ /* end of CAN register group */ + + + /*------------------- Multi-Time Programmable Controller --------------------*/ + /** + @addtogroup MTP Multi-Time Programmable Controller (MTP) + Memory Mapped Structure for MTP Controller + @{ */ + + #define MTP_KEYEN (MTP_BA+0x000) /*!< MTP Key Enable Register */ + #define MTP_USERDATA (MTP_BA+0x00C) /*!< MTP User Defined Data Register */ + #define MTP_KEY0 (MTP_BA+0x010) /*!< MTP KEY 0 Register */ + #define MTP_KEY1 (MTP_BA+0x014) /*!< MTP KEY 1 Register */ + #define MTP_KEY2 (MTP_BA+0x018) /*!< MTP KEY 2 Register */ + #define MTP_KEY3 (MTP_BA+0x01C) /*!< MTP KEY 3 Register */ + #define MTP_KEY4 (MTP_BA+0x020) /*!< MTP KEY 4 Register */ + #define MTP_KEY5 (MTP_BA+0x024) /*!< MTP KEY 5 Register */ + #define MTP_KEY6 (MTP_BA+0x028) /*!< MTP KEY 6 Register */ + #define MTP_KEY7 (MTP_BA+0x02C) /*!< MTP KEY 7 Register */ + #define MTP_PCYCLE (MTP_BA+0x030) /*!< MTP Program Cycle Program Count Register */ + #define MTP_CTL (MTP_BA+0x034) /*!< MTP Control Register */ + #define MTP_PSTART (MTP_BA+0x038) /*!< MTP Program Start Registe */ + #define MTP_STATUS (MTP_BA+0x040) /*!< MTP Status Registe */ + #define MTP_REGLCTL (MTP_BA+0x050) /*!< MTP Register Write-Protection Control Register*/ + + /**@}*/ /* end of MTP register group */ + + + /*------------------- JPEG Controller --------------------*/ + /** + @addtogroup JPEG JPEG Controller (JPEG) + Memory Mapped Structure for JPEG Controller + @{ */ + #define JMCR (JPEG_BA+0x00) /*!< JPEG Mode Control Register */ + #define JHEADER (JPEG_BA+0x04) /*!< JPEG Encode Header Control Register */ + #define JITCR (JPEG_BA+0x08) /*!< JPEG Image Type Control Register */ + #define JPRIQC (JPEG_BA+0x10) /*!< JPEG Primary Q-Table Control Register */ + #define JTHBQC (JPEG_BA+0x14) /*!< JPEG Thumbnail Q-Table Control Register */ + #define JPRIWH (JPEG_BA+0x18) /*!< JPEG Encode Primary Width/Height Register */ + #define JTHBWH (JPEG_BA+0x1C) /*!< JPEG Encode Thumbnail Width/Height Register */ + #define JPRST (JPEG_BA+0x20) /*!< JPEG Encode Primary Restart Interval Register */ + #define JTRST (JPEG_BA+0x24) /*!< JPEG Encode Thumbnail Restart Interval */ + #define JDECWH (JPEG_BA+0x28) /*!< JPEG Decode Image Width/Height Register */ + #define JINTCR (JPEG_BA+0x2C) /*!< JPEG Interrupt Control and Status Register */ + #define JDOWFBS (JPEG_BA+0x3c) /*!< JPEG Decoding Output Wait Frame Buffer Size */ + #define JPEG_BSBAD (JPEG_BA+0x40) /*!< JPEG Test Control Register */ + #define JWINDEC0 (JPEG_BA+0x44) /*!< JPEG Window Decode Mode Control Register 0 */ + #define JWINDEC1 (JPEG_BA+0x48) /*!< JPEG Window Decode Mode Control Register 1 */ + #define JWINDEC2 (JPEG_BA+0x4C) /*!< JPEG Window Decode Mode Control Register 2 */ + #define JMACR (JPEG_BA+0x50) /*!< JPEG Memory Address Mode Control Register */ + #define JPSCALU (JPEG_BA+0x54) /*!< JPEG Primary Scaling-Up Control Register */ + #define JPSCALD (JPEG_BA+0x58) /*!< JPEG Primary Scaling-Down Control Register */ + #define JTSCALD (JPEG_BA+0x5C) /*!< JPEG Thumbnail Scaling-Down Control Register */ + #define JDBCR (JPEG_BA+0x60) /*!< JPEG Dual-Buffer Control Register */ + #define JRESERVE (JPEG_BA+0x70) /*!< JPEG Encode Primary Bit-stream Reserved Size Register */ + #define JOFFSET (JPEG_BA+0x74) /*!< JPEG Offset Between Primary & Thumbnail Register */ + #define JFSTRIDE (JPEG_BA+0x78) /*!< JPEG Encode Bit-stream Frame Stride Register */ + #define JYADDR0 (JPEG_BA+0x7C) /*!< JPEG Y Component Frame Buffer-0 Starting Address Register */ + #define JUADDR0 (JPEG_BA+0x80) /*!< JPEG U Component Frame Buffer-0 Starting Address Register */ + #define JVADDR0 (JPEG_BA+0x84) /*!< JPEG V Component Frame Buffer-0 Starting Address Register */ + #define JYADDR1 (JPEG_BA+0x88) /*!< JPEG Y Component Frame Buffer-1 Starting Address Register */ + #define JUADDR1 (JPEG_BA+0x8C) /*!< JPEG U Component Frame Buffer-1 Starting Address Register */ + #define JVADDR1 (JPEG_BA+0x90) /*!< JPEG V Component Frame Buffer-1 Starting Address Register */ + #define JYSTRIDE (JPEG_BA+0x94) /*!< JPEG Y Component Frame Buffer Stride Register */ + #define JUSTRIDE (JPEG_BA+0x98) /*!< JPEG U Component Frame Buffer Stride Register */ + #define JVSTRIDE (JPEG_BA+0x9C) /*!< JPEG V Component Frame Buffer Stride Register */ + #define JIOADDR0 (JPEG_BA+0xA0) /*!< JPEG Bit-stream Frame Buffer-0 Starting Address Register */ + #define JIOADDR1 (JPEG_BA+0xA4) /*!< JPEG Bit-stream Frame Buffer-1 Starting Address Register */ + #define JPRI_SIZE (JPEG_BA+0xA8) /*!< JPEG Encode Primary Image Bit-stream Size Register */ + #define JTHB_SIZE (JPEG_BA+0xAC) /*!< JPEG Encode Thumbnail Image Bit-stream Size Register */ + #define JUPRAT (JPEG_BA+0xB0) /*!< JPEG Encode Up-Scale Ratio Register */ + #define JBSFIFO (JPEG_BA+0xB4) /*!< JPEG Bit-stream FIFO Control Register */ + #define JSRCH (JPEG_BA+0xB8) /*!< JPEG Encode Source Image Height */ + #define JQTAB0 (JPEG_BA+0x100) /*!< JPEG Quantization-Table 0 Register */ + #define JQTAB1 (JPEG_BA+0x140) /*!< JPEG Quantization-Table 1 Register */ + #define JQTAB2 (JPEG_BA+0x180) /*!< JPEG Quantization-Table 2 Register */ + + /**@}*/ /* end of JPEG register group */ + + + + /*@}*/ /* end of group N9H30_Peripherals */ + + + /** @addtogroup N9H30_IO_ROUTINE N9H30 I/O Routines + The Declaration of N9H30 I/O Routines + @{ + */ + + typedef volatile unsigned char vu8; ///< Define 8-bit unsigned volatile data type + typedef volatile unsigned short vu16; ///< Define 16-bit unsigned volatile data type + typedef volatile unsigned long vu32; ///< Define 32-bit unsigned volatile data type + + /** + * @brief Get a 8-bit unsigned value from specified address + * @param[in] addr Address to get 8-bit data from + * @return 8-bit unsigned value stored in specified address + */ + #define M8(addr) (*((vu8 *) (addr))) + + /** + * @brief Get a 16-bit unsigned value from specified address + * @param[in] addr Address to get 16-bit data from + * @return 16-bit unsigned value stored in specified address + * @note The input address must be 16-bit aligned + */ + #define M16(addr) (*((vu16 *) (addr))) + + /** + * @brief Get a 32-bit unsigned value from specified address + * @param[in] addr Address to get 32-bit data from + * @return 32-bit unsigned value stored in specified address + * @note The input address must be 32-bit aligned + */ + #define M32(addr) (*((vu32 *) (addr))) + + /** + * @brief Set a 32-bit unsigned value to specified I/O port + * @param[in] port Port address to set 32-bit data + * @param[in] value Value to write to I/O port + * @return None + * @note The output port must be 32-bit aligned + */ + #define outpw(port,value) *((volatile unsigned int *)(port)) = value + + /** + * @brief Get a 32-bit unsigned value from specified I/O port + * @param[in] port Port address to get 32-bit data from + * @return 32-bit unsigned value stored in specified I/O port + * @note The input port must be 32-bit aligned + */ + #define inpw(port) (*((volatile unsigned int *)(port))) + + /** + * @brief Set a 16-bit unsigned value to specified I/O port + * @param[in] port Port address to set 16-bit data + * @param[in] value Value to write to I/O port + * @return None + * @note The output port must be 16-bit aligned + */ + #define outps(port,value) *((volatile unsigned short *)(port)) = value + + /** + * @brief Get a 16-bit unsigned value from specified I/O port + * @param[in] port Port address to get 16-bit data from + * @return 16-bit unsigned value stored in specified I/O port + * @note The input port must be 16-bit aligned + */ + #define inps(port) (*((volatile unsigned short *)(port))) + + /** + * @brief Set a 8-bit unsigned value to specified I/O port + * @param[in] port Port address to set 8-bit data + * @param[in] value Value to write to I/O port + * @return None + */ + #define outpb(port,value) *((volatile unsigned char *)(port)) = value + + /** + * @brief Get a 8-bit unsigned value from specified I/O port + * @param[in] port Port address to get 8-bit data from + * @return 8-bit unsigned value stored in specified I/O port + */ + #define inpb(port) (*((volatile unsigned char *)(port))) + + /** + * @brief Set a 32-bit unsigned value to specified I/O port + * @param[in] port Port address to set 32-bit data + * @param[in] value Value to write to I/O port + * @return None + * @note The output port must be 32-bit aligned + */ + #define outp32(port,value) *((volatile unsigned int *)(port)) = value + + /** + * @brief Get a 32-bit unsigned value from specified I/O port + * @param[in] port Port address to get 32-bit data from + * @return 32-bit unsigned value stored in specified I/O port + * @note The input port must be 32-bit aligned + */ + #define inp32(port) (*((volatile unsigned int *)(port))) + + /** + * @brief Set a 16-bit unsigned value to specified I/O port + * @param[in] port Port address to set 16-bit data + * @param[in] value Value to write to I/O port + * @return None + * @note The output port must be 16-bit aligned + */ + #define outp16(port,value) *((volatile unsigned short *)(port)) = value + + /** + * @brief Get a 16-bit unsigned value from specified I/O port + * @param[in] port Port address to get 16-bit data from + * @return 16-bit unsigned value stored in specified I/O port + * @note The input port must be 16-bit aligned + */ + #define inp16(port) (*((volatile unsigned short *)(port))) + + /** + * @brief Set a 8-bit unsigned value to specified I/O port + * @param[in] port Port address to set 8-bit data + * @param[in] value Value to write to I/O port + * @return None + */ + #define outp8(port,value) *((volatile unsigned char *)(port)) = value + + /** + * @brief Get a 8-bit unsigned value from specified I/O port + * @param[in] port Port address to get 8-bit data from + * @return 8-bit unsigned value stored in specified I/O port + */ + #define inp8(port) (*((volatile unsigned char *)(port))) + + + /*@}*/ /* end of group N9H30_IO_ROUTINE */ + + /******************************************************************************/ + /* Legacy Constants */ + /******************************************************************************/ + /** @addtogroup N9H30_legacy_Constants N9H30 Legacy Constants + N9H30 Legacy Constants + @{ + */ + typedef void *PVOID; ///< Define void pointer data type + typedef void VOID; ///< Define void data type + typedef char BOOL; ///< Define bool data type + typedef char *PBOOL; ///< Define bool pointer data type + + typedef char INT8; ///< Define 8-bit singed data type + typedef char CHAR; ///< Define char data type + typedef char *PINT8; ///< Define 8-bit singed pointer data type + typedef char *PCHAR; ///< Define char pointer data type + typedef unsigned char UINT8; ///< Define 8-bit unsigned data type + typedef unsigned char UCHAR; ///< Define char unsigned data type + typedef unsigned char *PUINT8; ///< Define 8-bit unsigned pointer data type + typedef unsigned char *PUCHAR; ///< Define char unsigned pointer data type + typedef char *PSTR; ///< Define string pointer data type + typedef const char *PCSTR; ///< Define constant string pointer data type + + typedef short SHORT; ///< Define short signed data type + typedef short *PSHORT; ///< Define short signed pointer data type + typedef unsigned short USHORT; ///< Define short unsigned data type + typedef unsigned short *PUSHORT; ///< Define short unsigned pointer data type + + typedef short INT16; ///< Define 16-bit signed data type + typedef short *PINT16; ///< Define 16-bit signed pointer data type + typedef unsigned short UINT16; ///< Define 16-bit unsigned data type + typedef unsigned short *PUINT16; ///< Define 16-bit unsigned pointer data type + + typedef int INT; ///< Define integer signed data type + typedef int *PINT; ///< Define integer signed pointer data type + typedef unsigned int UINT; ///< Define integer unsigned data type + typedef unsigned int *PUINT; ///< Define integer unsigned pointer data type + + typedef int INT32; ///< Define 32-bit signed data type + typedef int *PINT32; ///< Define 32-bit signed pointer data type + typedef unsigned int UINT32; ///< Define 32-bit unsigned data type + typedef unsigned int *PUINT32; ///< Define 32-bit unsigned pointer data type + + #if defined ( __GNUC__ ) && !(__CC_ARM) + typedef long long INT64; + typedef unsigned long long UINT64; + #else + typedef __int64 INT64; ///< Define 64-bit signed data type + typedef unsigned __int64 UINT64; ///< Define 64-bit unsigned data type + #endif + + typedef float FLOAT; ///< Define float data type + typedef float *PFLOAT; ///< Define float pointer data type + + typedef double DOUBLE; ///< Define double data type + typedef double *PDOUBLE; ///< Define double pointer data type + + typedef int SIZE_T; ///< Define size of data type + + typedef unsigned char REG8; ///< Define 8-bit register data type + typedef unsigned short REG16; ///< Define 16-bit register data type + typedef unsigned int REG32; ///< Define 32-bit register data type + + + #ifndef NULL + #define NULL (0) ///< NULL pointer + #endif + + #define TRUE (1) ///< Boolean true, define to use in API parameters or return value + #define FALSE (0) ///< Boolean false, define to use in API parameters or return value + + #define ENABLE (1) ///< Enable, define to use in API parameters + #define DISABLE (0) ///< Disable, define to use in API parameters + + + #define Successful 0 ///< Function return value success + #define Fail 1 ///< Function return value failed + + /* Define one bit mask */ + #define BIT0 (0x00000001) ///< Bit 0 mask of an 32 bit integer + #define BIT1 (0x00000002) ///< Bit 1 mask of an 32 bit integer + #define BIT2 (0x00000004) ///< Bit 2 mask of an 32 bit integer + #define BIT3 (0x00000008) ///< Bit 3 mask of an 32 bit integer + #define BIT4 (0x00000010) ///< Bit 4 mask of an 32 bit integer + #define BIT5 (0x00000020) ///< Bit 5 mask of an 32 bit integer + #define BIT6 (0x00000040) ///< Bit 6 mask of an 32 bit integer + #define BIT7 (0x00000080) ///< Bit 7 mask of an 32 bit integer + #define BIT8 (0x00000100) ///< Bit 8 mask of an 32 bit integer + #define BIT9 (0x00000200) ///< Bit 9 mask of an 32 bit integer + #define BIT10 (0x00000400) ///< Bit 10 mask of an 32 bit integer + #define BIT11 (0x00000800) ///< Bit 11 mask of an 32 bit integer + #define BIT12 (0x00001000) ///< Bit 12 mask of an 32 bit integer + #define BIT13 (0x00002000) ///< Bit 13 mask of an 32 bit integer + #define BIT14 (0x00004000) ///< Bit 14 mask of an 32 bit integer + #define BIT15 (0x00008000) ///< Bit 15 mask of an 32 bit integer + #define BIT16 (0x00010000) ///< Bit 16 mask of an 32 bit integer + #define BIT17 (0x00020000) ///< Bit 17 mask of an 32 bit integer + #define BIT18 (0x00040000) ///< Bit 18 mask of an 32 bit integer + #define BIT19 (0x00080000) ///< Bit 19 mask of an 32 bit integer + #define BIT20 (0x00100000) ///< Bit 20 mask of an 32 bit integer + #define BIT21 (0x00200000) ///< Bit 21 mask of an 32 bit integer + #define BIT22 (0x00400000) ///< Bit 22 mask of an 32 bit integer + #define BIT23 (0x00800000) ///< Bit 23 mask of an 32 bit integer + #define BIT24 (0x01000000) ///< Bit 24 mask of an 32 bit integer + #define BIT25 (0x02000000) ///< Bit 25 mask of an 32 bit integer + #define BIT26 (0x04000000) ///< Bit 26 mask of an 32 bit integer + #define BIT27 (0x08000000) ///< Bit 27 mask of an 32 bit integer + #define BIT28 (0x10000000) ///< Bit 28 mask of an 32 bit integer + #define BIT29 (0x20000000) ///< Bit 29 mask of an 32 bit integer + #define BIT30 (0x40000000) ///< Bit 30 mask of an 32 bit integer + #define BIT31 (0x80000000) ///< Bit 31 mask of an 32 bit integer + + /* Byte Mask Definitions */ + #define BYTE0_Msk (0x000000FF) ///< Mask to get bit0~bit7 from a 32 bit integer + #define BYTE1_Msk (0x0000FF00) ///< Mask to get bit8~bit15 from a 32 bit integer + #define BYTE2_Msk (0x00FF0000) ///< Mask to get bit16~bit23 from a 32 bit integer + #define BYTE3_Msk (0xFF000000) ///< Mask to get bit24~bit31 from a 32 bit integer + + #define GET_BYTE0(u32Param) ((u32Param & BYTE0_Msk) ) /*!< Extract Byte 0 (Bit 0~ 7) from parameter u32Param */ + #define GET_BYTE1(u32Param) ((u32Param & BYTE1_Msk) >> 8) /*!< Extract Byte 1 (Bit 8~15) from parameter u32Param */ + #define GET_BYTE2(u32Param) ((u32Param & BYTE2_Msk) >> 16) /*!< Extract Byte 2 (Bit 16~23) from parameter u32Param */ + #define GET_BYTE3(u32Param) ((u32Param & BYTE3_Msk) >> 24) /*!< Extract Byte 3 (Bit 24~31) from parameter u32Param */ + + #ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ + #else + #define __I volatile const /*!< Defines 'read only' permissions */ + #endif + #define __O volatile /*!< Defines 'write only' permissions */ + #define __IO volatile /*!< Defines 'read / write' permissions */ + + extern void __nop(void); + +#endif /* __N9H30_H__ */ + +/*@}*/ /* end of group N9H30_legacy_Constants */ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/NuMicro.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/NuMicro.h new file mode 100644 index 0000000000..6e949c843d --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/NuMicro.h @@ -0,0 +1,51 @@ +/**************************************************************************//** + * @file NuMicro.h + * @version V1.00 + * @brief NuMicro peripheral access layer header file. + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2017-2020 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NUMICRO_H__ +#define __NUMICRO_H__ + +#include "N9H30.h" +#include "nu_adc.h" +#include "nu_uart.h" +#include "nu_spi.h" +#include "nu_i2c.h" +#include "nu_etimer.h" +#include "nu_emac.h" +#include "nu_sdh.h" +#include "nu_gpio.h" +#include "nu_rtc.h" +#include "nu_wdt.h" +//#include "nu_ebi.h" +#include "nu_scuart.h" +#include "nu_pwm.h" +//#include "nu_crypto.h" +#include "nu_can.h" +#include "nu_i2s.h" +#include "nu_usbd.h" +#include "nu_lcd.h" +#include "nu_jpegcodec.h" +#include "nu_2d.h" +#include "nu_crypto.h" + +#include "nu_sys.h" + +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif + +#ifndef __CLZ + #if defined(__CC_ARM) + #define __CLZ __clz + #else + #define __CLZ __builtin_clz + #endif +#endif + +#endif /* __NUMICRO_H__ */ + + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/emac_reg.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/emac_reg.h new file mode 100644 index 0000000000..f9ad5efceb --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/emac_reg.h @@ -0,0 +1,2063 @@ +/**************************************************************************//** + * @file emac_reg.h + * @version V1.00 + * @brief EMAC register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2017-2020 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __EMAC_REG_H__ +#define __EMAC_REG_H__ + +#if defined ( __CC_ARM ) + #pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup EMAC Ethernet MAC Controller(EMAC) + Memory Mapped Structure for EMAC Controller +@{ */ + +typedef struct +{ + + /** + * @var EMAC_T::CAMCTL + * Offset: 0x00 CAM Comparison Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |AUP |Accept Unicast Packet + * | | |The AUP controls the unicast packet reception + * | | |If AUP is enabled, EMAC receives all incoming packet its destination MAC address is a unicast address. + * | | |0 = EMAC receives packet depends on the CAM comparison result. + * | | |1 = EMAC receives all unicast packets. + * |[1] |AMP |Accept Multicast Packet + * | | |The AMP controls the multicast packet reception + * | | |If AMP is enabled, EMAC receives all incoming packet its destination MAC address is a multicast address. + * | | |0 = EMAC receives packet depends on the CAM comparison result. + * | | |1 = EMAC receives all multicast packets. + * |[2] |ABP |Accept Broadcast Packet + * | | |The ABP controls the broadcast packet reception + * | | |If ABP is enabled, EMAC receives all incoming packet its destination MAC address is a broadcast address. + * | | |0 = EMAC receives packet depends on the CAM comparison result. + * | | |1 = EMAC receives all broadcast packets. + * |[3] |COMPEN |Complement CAM Comparison Enable Bit + * | | |The COMPEN controls the complement of the CAM comparison result + * | | |If the CMPEN and COMPEN are both enabled, the incoming packet with specific destination MAC address + * | | |configured in CAM entry will be dropped + * | | |And the incoming packet with destination MAC address does not configured in any CAM entry will be received. + * | | |0 = Complement CAM comparison result Disabled. + * | | |1 = Complement CAM comparison result Enabled. + * |[4] |CMPEN |CAM Compare Enable Bit + * | | |The CMPEN controls the enable of CAM comparison function for destination MAC address recognition + * | | |If software wants to receive a packet with specific destination MAC address, configures the MAC address + * | | |into CAM 12~0, then enables that CAM entry and set CMPEN to 1. + * | | |0 = CAM comparison function for destination MAC address recognition Disabled. + * | | |1 = CAM comparison function for destination MAC address recognition Enabled. + * @var EMAC_T::CAMEN + * Offset: 0x04 CAM Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CAMxEN |CAM Entry X Enable Bit + * | | |The CAMxEN controls the validation of CAM entry x. + * | | |The CAM entry 13, 14 and 15 are for PAUSE control frame transmission + * | | |If software wants to transmit a PAUSE control frame out to network, the enable bits of these three CAM + * | | |entries all must be enabled first. + * | | |0 = CAM entry x Disabled. + * | | |1 = CAM entry x Enabled. + * @var EMAC_T::CAM0M + * Offset: 0x08 CAM0 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM0L + * Offset: 0x0C CAM0 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM1M + * Offset: 0x10 CAM1 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM1L + * Offset: 0x14 CAM1 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM2M + * Offset: 0x18 CAM2 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM2L + * Offset: 0x1C CAM2 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM3M + * Offset: 0x20 CAM3 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM3L + * Offset: 0x24 CAM3 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM4M + * Offset: 0x28 CAM4 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM4L + * Offset: 0x2C CAM4 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM5M + * Offset: 0x30 CAM5 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM5L + * Offset: 0x34 CAM5 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM6M + * Offset: 0x38 CAM6 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM6L + * Offset: 0x3C CAM6 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM7M + * Offset: 0x40 CAM7 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM7L + * Offset: 0x44 CAM7 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM8M + * Offset: 0x48 CAM8 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM8L + * Offset: 0x4C CAM8 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM9M + * Offset: 0x50 CAM9 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM9L + * Offset: 0x54 CAM9 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM10M + * Offset: 0x58 CAM10 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM10L + * Offset: 0x5C CAM10 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM11M + * Offset: 0x60 CAM11 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM11L + * Offset: 0x64 CAM11 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM12M + * Offset: 0x68 CAM12 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM12L + * Offset: 0x6C CAM12 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM13M + * Offset: 0x70 CAM13 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM13L + * Offset: 0x74 CAM13 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM14M + * Offset: 0x78 CAM14 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |MACADDR2 |MAC Address Byte 2 + * |[15:8] |MACADDR3 |MAC Address Byte 3 + * |[23:16] |MACADDR4 |MAC Address Byte 4 + * |[31:24] |MACADDR5 |MAC Address Byte 5 + * | | |The CAMxM keeps the bit 47~16 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM14L + * Offset: 0x7C CAM14 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:16] |MACADDR0 |MAC Address Byte 0 + * |[31:24] |MACADDR1 |MAC Address Byte 1 + * | | |The CAMxL keeps the bit 15~0 of MAC address + * | | |The x can be the 0~14 + * | | |The register pair {EMAC_CAMxM, EMAC_CAMxL} represents a CAM entry and keeps a MAC address. + * | | |For example, if the MAC address 00-50-BA-33-BA-44 kept in CAM entry 1, the register EMAC_CAM1M is + * | | |0x0050_BA33 and EMAC_CAM1L is 0xBA44_0000. + * @var EMAC_T::CAM15MSB + * Offset: 0x80 CAM15 Most Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |OPCODE |OP Code Field of PAUSE Control Frame + * | | |In the PAUSE control frame, an op code field defined and is 0x0001. + * |[31:16] |LENGTH |LENGTH Field of PAUSE Control Frame + * | | |In the PAUSE control frame, a LENGTH field defined and is 0x8808. + * @var EMAC_T::CAM15LSB + * Offset: 0x84 CAM15 Least Significant Word Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:24] |OPERAND |Pause Parameter + * | | |In the PAUSE control frame, an OPERAND field defined and controls how much time the destination + * | | |Ethernet MAC Controller paused + * | | |The unit of the OPERAND is a slot time, the 512-bit time. + * @var EMAC_T::TXDSA + * Offset: 0x88 Transmit Descriptor Link List Start Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |TXDSA |Transmit Descriptor Link-list Start Address + * | | |The TXDSA keeps the start address of transmit descriptor link-list + * | | |If the software enables the bit TXON (EMAC_CTL[8]), the content of TXDSA will be loaded into the + * | | |current transmit descriptor start address register (EMAC_CTXDSA) + * | | |The TXDSA does not be updated by EMAC + * | | |During the operation, EMAC will ignore the bits [1:0] of TXDSA + * | | |This means that TX descriptors must locate at word boundary memory address. + * @var EMAC_T::RXDSA + * Offset: 0x8C Receive Descriptor Link List Start Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |RXDSA |Receive Descriptor Link-list Start Address + * | | |The RXDSA keeps the start address of receive descriptor link-list + * | | |If the S/W enables the bit RXON (EMAC_CTL[0]), the content of RXDSA will be loaded into the current + * | | |receive descriptor start address register (EMAC_CRXDSA) + * | | |The RXDSA does not be updated by EMAC + * | | |During the operation, EMAC will ignore the bits [1:0] of RXDSA + * | | |This means that RX descriptors must locate at word boundary memory address. + * @var EMAC_T::CTL + * Offset: 0x90 MAC Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RXON |Frame Reception ON + * | | |The RXON controls the normal packet reception of EMAC + * | | |If the RXON is set to high, the EMAC starts the packet reception process, including the RX + * | | |descriptor fetching, packet reception and RX descriptor modification. + * | | |It is necessary to finish EMAC initial sequence before enable RXON + * | | |Otherwise, the EMAC operation is undefined. + * | | |If the RXON is disabled during EMAC is receiving an incoming packet, the EMAC stops the packet + * | | |reception process after the current packet reception finished. + * | | |0 = Packet reception process stopped. + * | | |1 = Packet reception process started. + * |[1] |ALP |Accept Long Packet + * | | |The ALP controls the long packet, which packet length is greater than 1518 bytes, reception + * | | |If the ALP is set to high, the EMAC will accept the long packet. + * | | |Otherwise, the long packet will be dropped. + * | | |0 = Ethernet MAC controller dropped the long packet. + * | | |1 = Ethernet MAC controller received the long packet. + * |[2] |ARP |Accept Runt Packet + * | | |The ARP controls the runt packet, which length is less than 64 bytes, reception + * | | |If the ARP is set to high, the EMAC will accept the runt packet. + * | | |Otherwise, the runt packet will be dropped. + * | | |0 = Ethernet MAC controller dropped the runt packet. + * | | |1 = Ethernet MAC controller received the runt packet. + * |[3] |ACP |Accept Control Packet + * | | |The ACP controls the control frame reception + * | | |If the ACP is set to high, the EMAC will accept the control frame + * | | |Otherwise, the control frame will be dropped + * | | |It is recommended that S/W only enable ACP while EMAC is operating on full duplex mode. + * | | |0 = Ethernet MAC controller dropped the control frame. + * | | |1 = Ethernet MAC controller received the control frame. + * |[4] |AEP |Accept CRC Error Packet + * | | |The AEP controls the EMAC accepts or drops the CRC error packet + * | | |If the AEP is set to high, the incoming packet with CRC error will be received by EMAC as a good packet. + * | | |0 = Ethernet MAC controller dropped the CRC error packet. + * | | |1 = Ethernet MAC controller received the CRC error packet. + * |[5] |STRIPCRC |Strip CRC Checksum + * | | |The STRIPCRC controls if the length of incoming packet is calculated with 4 bytes CRC checksum + * | | |If the STRIPCRC is set to high, 4 bytes CRC checksum is excluded from length calculation of incoming packet. + * | | |0 = The 4 bytes CRC checksum is included in packet length calculation. + * | | |1 = The 4 bytes CRC checksum is excluded in packet length calculation. + * |[6] |WOLEN |Wake on LAN Enable Bit + * | | |The WOLEN high enables the functionality that Ethernet MAC controller checked if the incoming packet + * | | |is Magic Packet and wakeup system from Power-down mode. + * | | |If incoming packet was a Magic Packet and the system was in Power-down, the Ethernet MAC controller + * | | |would generate a wakeup event to wake system up from Power-down mode. + * | | |0 = Wake-up by Magic Packet function Disabled. + * | | |1 = Wake-up by Magic Packet function Enabled. + * |[8] |TXON |Frame Transmission ON + * | | |The TXON controls the normal packet transmission of EMAC + * | | |If the TXON is set to high, the EMAC starts the packet transmission process, including the TX + * | | |descriptor fetching, packet transmission and TX descriptor modification. + * | | |It is must to finish EMAC initial sequence before enable TXON + * | | |Otherwise, the EMAC operation is undefined. + * | | |If the TXON is disabled during EMAC is transmitting a packet out, the EMAC stops the packet + * | | |transmission process after the current packet transmission finished. + * | | |0 = Packet transmission process stopped. + * | | |1 = Packet transmission process started. + * |[9] |NODEF |No Deferral + * | | |The NODEF controls the enable of deferral exceed counter + * | | |If NODEF is set to high, the deferral exceed counter is disabled + * | | |The NODEF is only useful while EMAC is operating on half duplex mode. + * | | |0 = The deferral exceed counter Enabled. + * | | |1 = The deferral exceed counter Disabled. + * |[16] |SDPZ |Send PAUSE Frame + * | | |The SDPZ controls the PAUSE control frame transmission. + * | | |If S/W wants to send a PAUSE control frame out, the CAM entry 13, 14 and 15 must be configured + * | | |first and the corresponding CAM enable bit of CAMEN register also must be set. + * | | |Then, set SDPZ to 1 enables the PAUSE control frame transmission. + * | | |The SDPZ is a self-clear bit + * | | |This means after the PAUSE control frame transmission has completed, the SDPZ will be cleared automatically. + * | | |It is recommended that only enabling SNDPAUSE while EMAC is operating in Full Duplex mode. + * | | |0 = PAUSE control frame transmission completed. + * | | |1 = PAUSE control frame transmission Enabled. + * |[17] |SQECHKEN |SQE Checking Enable Bit + * | | |The SQECHKEN controls the enable of SQE checking + * | | |The SQE checking is only available while EMAC is operating on 10M bps and half duplex mode + * | | |In other words, the SQECHKEN cannot affect EMAC operation, if the EMAC is operating on 100Mbps + * | | |or full duplex mode. + * | | |0 = SQE checking Disabled while EMAC is operating in 10Mbps and Half Duplex mode. + * | | |1 = SQE checking Enabled while EMAC is operating in 10Mbps and Half Duplex mode. + * |[18] |FUDUP |Full Duplex Mode Selection + * | | |The FUDUP controls that if EMAC is operating on full or half duplex mode. + * | | |0 = EMAC operates in half duplex mode. + * | | |1 = EMAC operates in full duplex mode. + * |[19] |RMIIRXCTL |RMII RX Control + * | | |The RMIIRXCTL control the receive data sample in RMII mode + * | | |It's necessary to set this bit high when RMIIEN (EMAC_CTL[ [22]) is high. + * | | |0 = RMII RX control disabled. + * | | |1 = RMII RX control enabled. + * |[20] |OPMODE |Operation Mode Selection + * | | |The OPMODE defines that if the EMAC is operating on 10M or 100M bps mode + * | | |The RST (EMAC_CTL[24]) would not affect OPMODE value. + * | | |0 = EMAC operates in 10Mbps mode. + * | | |1 = EMAC operates in 100Mbps mode. + * |[22] |RMIIEN |RMII Mode Enable Bit + * | | |This bit controls if Ethernet MAC controller connected with off-chip Ethernet PHY by MII + * | | |interface or RMII interface + * | | |The RST (EMAC_CTL[24]) would not affect RMIIEN value. + * | | |0 = Ethernet MAC controller RMII mode Disabled. + * | | |1 = Ethernet MAC controller RMII mode Enabled. + * | | |NOTE: This field must keep 1. + * |[24] |RST |Software Reset + * | | |The RST implements a reset function to make the EMAC return default state + * | | |The RST is a self-clear bit + * | | |This means after the software reset finished, the RST will be cleared automatically + * | | |Enable RST can also reset all control and status registers, exclusive of the control bits + * | | |RMIIEN (EMAC_CTL[22]), and OPMODE (EMAC_CTL[20]). + * | | |The EMAC re-initial is necessary after the software reset completed. + * | | |0 = Software reset completed. + * | | |1 = Software reset Enabled. + * @var EMAC_T::MIIMDAT + * Offset: 0x94 MII Management Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |DATA |MII Management Data + * | | |The DATA is the 16 bits data that will be written into the registers of external PHY for MII + * | | |Management write command or the data from the registers of external PHY for MII Management read command. + * @var EMAC_T::MIIMCTL + * Offset: 0x98 MII Management Control and Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[4:0] |PHYREG |PHY Register Address + * | | |The PHYREG keeps the address to indicate which register of external PHY is the target of the + * | | |MII management command. + * |[12:8] |PHYADDR |PHY Address + * | | |The PHYADDR keeps the address to differentiate which external PHY is the target of the MII management command. + * |[16] |WRITE |Write Command + * | | |The Write defines the MII management command is a read or write. + * | | |0 = MII management command is a read command. + * | | |1 = MII management command is a write command. + * |[17] |BUSY |Busy Bit + * | | |The BUSY controls the enable of the MII management frame generation + * | | |If S/W wants to access registers of external PHY, it set BUSY to high and EMAC generates + * | | |the MII management frame to external PHY through MII Management I/F + * | | |The BUSY is a self-clear bit + * | | |This means the BUSY will be cleared automatically after the MII management command finished. + * | | |0 = MII management command generation finished. + * | | |1 = MII management command generation Enabled. + * |[18] |PREAMSP |Preamble Suppress + * | | |The PREAMSP controls the preamble field generation of MII management frame + * | | |If the PREAMSP is set to high, the preamble field generation of MII management frame is skipped. + * | | |0 = Preamble field generation of MII management frame not skipped. + * | | |1 = Preamble field generation of MII management frame skipped. + * |[19] |MDCON |MDC Clock ON + * | | |The MDC controls the MDC clock generation. If the MDCON is set to high, the MDC clock is turned on. + * | | |0 = MDC clock off. + * | | |1 = MDC clock on. + * @var EMAC_T::FIFOCTL + * Offset: 0x9C FIFO Threshold Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |RXFIFOTH |RXFIFO Low Threshold + * | | |The RXFIFOTH controls when RXDMA requests internal arbiter for data transfer between RXFIFO + * | | |and system memory + * | | |The RXFIFOTH defines not only the high threshold of RXFIFO, but also the low threshold + * | | |The low threshold is the half of high threshold always + * | | |During the packet reception, if the RXFIFO reaches the high threshold, the RXDMA starts to + * | | |transfer frame data from RXFIFO to system memory + * | | |If the frame data in RXFIFO is less than low threshold, RXDMA stops to transfer the frame + * | | |data to system memory. + * | | |00 = Depend on the burst length setting + * | | |If the burst length is 8 words, high threshold is 8 words, too. + * | | |01 = RXFIFO high threshold is 64B and low threshold is 32B. + * | | |10 = RXFIFO high threshold is 128B and low threshold is 64B. + * | | |11 = RXFIFO high threshold is 192B and low threshold is 96B. + * |[9:8] |TXFIFOTH |TXFIFO Low Threshold + * | | |The TXFIFOTH controls when TXDMA requests internal arbiter for data transfer between system + * | | |memory and TXFIFO + * | | |The TXFIFOTH defines not only the low threshold of TXFIFO, but also the high threshold + * | | |The high threshold is the twice of low threshold always + * | | |During the packet transmission, if the TXFIFO reaches the high threshold, the TXDMA stops + * | | |generate request to transfer frame data from system memory to TXFIFO + * | | |If the frame data in TXFIFO is less than low threshold, TXDMA starts to transfer frame data + * | | |from system memory to TXFIFO. + * | | |The TXFIFOTH also defines when the TXMAC starts to transmit frame out to network + * | | |The TXMAC starts to transmit the frame out while the TXFIFO first time reaches the high threshold + * | | |during the transmission of the frame + * | | |If the frame data length is less than TXFIFO high threshold, the TXMAC starts to transmit the frame + * | | |out after the frame data are all inside the TXFIFO. + * | | |00 = Undefined. + * | | |01 = TXFIFO low threshold is 64B and high threshold is 128B. + * | | |10 = TXFIFO low threshold is 80B and high threshold is 160B. + * | | |11 = TXFIFO low threshold is 96B and high threshold is 192B. + * |[21:20] |BURSTLEN |DMA Burst Length + * | | |This defines the burst length of AHB bus cycle while EMAC accesses system memory. + * | | |00 = 4 words. + * | | |01 = 8 words. + * | | |10 = 16 words. + * | | |11 = 16 words. + * @var EMAC_T::TXST + * Offset: 0xA0 Transmit Start Demand Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |TXST |Transmit Start Demand + * | | |If the TX descriptor is not available for use of TXDMA after the TXON (EMAC_CTL[8]) is enabled, + * | | |the FSM (Finite State Machine) of TXDMA enters the Halt state and the frame transmission is halted + * | | |After the S/W has prepared the new TX descriptor for frame transmission, it must issue a write + * | | |command to EMAC_TXST register to make TXDMA to leave Halt state and continue the frame transmission. + * | | |The EMAC_TXST is a write only register and read from this register is undefined. + * | | |The write to EMAC_TXST register takes effect only when TXDMA stayed at Halt state. + * @var EMAC_T::RXST + * Offset: 0xA4 Receive Start Demand Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |RXST |Receive Start Demand + * | | |If the RX descriptor is not available for use of RXDMA after the RXON (EMAC_CTL[0]) is enabled, + * | | |the FSM (Finite State Machine) of RXDMA enters the Halt state and the frame reception is halted + * | | |After the S/W has prepared the new RX descriptor for frame reception, it must issue a write + * | | |command to EMAC_RXST register to make RXDMA to leave Halt state and continue the frame reception. + * | | |The EMAC_RXST is a write only register and read from this register is undefined. + * | | |The write to EMAC_RXST register take effect only when RXDMA stayed at Halt state. + * @var EMAC_T::MRFL + * Offset: 0xA8 Maximum Receive Frame Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |MRFL |Maximum Receive Frame Length + * | | |The MRFL defines the maximum frame length for received frame + * | | |If the frame length of received frame is greater than MRFL, and bit MFLEIEN (EMAC_INTEN[8]) + * | | |is also enabled, the bit MFLEIF (EMAC_INTSTS[8]) is set and the RX interrupt is triggered. + * | | |It is recommended that only use MRFL to qualify the length of received frame while S/W wants to + * | | |receive a frame which length is greater than 1518 bytes. + * @var EMAC_T::INTEN + * Offset: 0xAC MAC Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RXIEN |Receive Interrupt Enable Bit + * | | |The RXIEN controls the RX interrupt generation. + * | | |If RXIEN is enabled and RXIF (EMAC_INTSTS[0]) is high, EMAC generates the RX interrupt to CPU + * | | |If RXIEN is disabled, no RX interrupt is generated to CPU even any status bit EMAC_INTSTS[15:1] + * | | |is set and the corresponding bit of EMAC_INTEN is enabled + * | | |In other words, if S/W wants to receive RX interrupt from EMAC, this bit must be enabled + * | | |And, if S/W doesn't want to receive any RX interrupt from EMAC, disables this bit. + * | | |0 = RXIF (EMAC_INTSTS[0]) is masked and RX interrupt generation Disabled. + * | | |1 = RXIF (EMAC_INTSTS[0]) is not masked and RX interrupt generation Enabled. + * |[1] |CRCEIEN |CRC Error Interrupt Enable Bit + * | | |The CRCEIEN controls the CRCEIF (EMAC_INTSTS[1]) interrupt generation + * | | |If CRCEIF (EMAC_INTSTS[1]) is set, and both CRCEIEN and RXIEN (EMAC_INTEN[0]) are enabled, the + * | | |EMAC generates the RX interrupt to CPU + * | | |If CRCEIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |CRCEIF (EMAC_INTSTS[1]) is set. + * | | |0 = CRCEIF (EMAC_INTSTS[1]) trigger RX interrupt Disabled. + * | | |1 = CRCEIF (EMAC_INTSTS[1]) trigger RX interrupt Enabled. + * |[2] |RXOVIEN |Receive FIFO Overflow Interrupt Enable Bit + * | | |The RXOVIEN controls the RXOVIF (EMAC_INTSTS[2]) interrupt generation + * | | |If RXOVIF (EMAC_INTSTS[2]) is set, and both RXOVIEN and RXIEN (EMAC_INTEN[0]) are enabled, the + * | | |EMAC generates the RX interrupt to CPU + * | | |If RXOVIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |RXOVIF (EMAC_INTSTS[2]) is set. + * | | |0 = RXOVIF (EMAC_INTSTS[2]) trigger RX interrupt Disabled. + * | | |1 = RXOVIF (EMAC_INTSTS[2]) trigger RX interrupt Enabled. + * |[3] |LPIEN |Long Packet Interrupt Enable Bit + * | | |The LPIEN controls the LPIF (EMAC_INTSTS[3]) interrupt generation + * | | |If LPIF (EMAC_INTSTS[3]) is set, and both LPIEN and RXIEN (EMAC_INTEN[0]) are enabled, the EMAC + * | | |generates the RX interrupt to CPU + * | | |If LPIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the LPIF + * | | |(EMAC_INTSTS[3]) is set. + * | | |0 = LPIF (EMAC_INTSTS[3]) trigger RX interrupt Disabled. + * | | |1 = LPIF (EMAC_INTSTS[3]) trigger RX interrupt Enabled. + * |[4] |RXGDIEN |Receive Good Interrupt Enable Bit + * | | |The RXGDIEN controls the RXGDIF (EMAC_INTSTS[4]) interrupt generation + * | | |If RXGDIF (EMAC_INTSTS[4]) is set, and both RXGDIEN and RXIEN (EMAC_INTEN[0]) are enabled, the + * | | |EMAC generates the RX interrupt to CPU + * | | |If RXGDIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |RXGDIF (EMAC_INTSTS[4]) is set. + * | | |0 = RXGDIF (EMAC_INTSTS[4]) trigger RX interrupt Disabled. + * | | |1 = RXGDIF (EMAC_INTSTS[4]) trigger RX interrupt Enabled. + * |[5] |ALIEIEN |Alignment Error Interrupt Enable Bit + * | | |The ALIEIEN controls the ALIEIF (EMAC_INTSTS[5]) interrupt generation + * | | |If ALIEIF (EMAC_INTSTS[5]) is set, and both ALIEIEN and RXIEN (EMAC_INTEN[0]) are enabled, the + * | | |EMAC generates the RX interrupt to CPU + * | | |If ALIEIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |ALIEIF (EMAC_INTSTS[5]) is set. + * | | |0 = ALIEIF (EMAC_INTSTS[5]) trigger RX interrupt Disabled. + * | | |1 = ALIEIF (EMAC_INTSTS[5]) trigger RX interrupt Enabled. + * |[6] |RPIEN |Runt Packet Interrupt Enable Bit + * | | |The RPIEN controls the RPIF (EMAC_INTSTS[6]) interrupt generation + * | | |If RPIF (EMAC_INTSTS[6]) is set, and both RPIEN and RXIEN (EMAC_INTEN[0]) are enabled, the EMAC + * | | |generates the RX interrupt to CPU + * | | |If RPIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |RPIF (EMAC_INTSTS[6]) is set. + * | | |0 = RPIF (EMAC_INTSTS[6]) trigger RX interrupt Disabled. + * | | |1 = RPIF (EMAC_INTSTS[6]) trigger RX interrupt Enabled. + * |[7] |MPCOVIEN |Miss Packet Counter Overrun Interrupt Enable Bit + * | | |The MPCOVIEN controls the MPCOVIF (EMAC_INTSTS[7]) interrupt generation + * | | |If MPCOVIF (EMAC_INTSTS[7]) is set, and both MPCOVIEN and RXIEN (EMAC_INTEN[0]) are enabled, + * | | |the EMAC generates the RX interrupt to CPU + * | | |If MPCOVIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |MPCOVIF (EMAC_INTSTS[7]) is set. + * | | |0 = MPCOVIF (EMAC_INTSTS[7]) trigger RX interrupt Disabled. + * | | |1 = MPCOVIF (EMAC_INTSTS[7]) trigger RX interrupt Enabled. + * |[8] |MFLEIEN |Maximum Frame Length Exceed Interrupt Enable Bit + * | | |The MFLEIEN controls the MFLEIF (EMAC_INTSTS[8]) interrupt generation + * | | |If MFLEIF (EMAC_INTSTS[8]) is set, and both MFLEIEN and RXIEN (EMAC_INTEN[0]) are enabled, the + * | | |EMAC generates the RX interrupt to CPU + * | | |If MFLEIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |MFLEIF (EMAC_INTSTS[8]) is set. + * | | |0 = MFLEIF (EMAC_INTSTS[8]) trigger RX interrupt Disabled. + * | | |1 = MFLEIF (EMAC_INTSTS[8]) trigger RX interrupt Enabled. + * |[9] |DENIEN |DMA Early Notification Interrupt Enable Bit + * | | |The DENIEN controls the DENIF (EMAC_INTSTS[9]) interrupt generation + * | | |If DENIF (EMAC_INTSTS[9]) is set, and both DENIEN and RXIEN (EMAC_INTEN[0]) are enabled, the + * | | |EMAC generates the RX interrupt to CPU + * | | |If DENIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |DENIF (EMAC_INTSTS[9]) is set. + * | | |0 = TDENIF (EMAC_INTSTS[9]) trigger RX interrupt Disabled. + * | | |1 = TDENIF (EMAC_INTSTS[9]) trigger RX interrupt Enabled. + * |[10] |RDUIEN |Receive Descriptor Unavailable Interrupt Enable Bit + * | | |The RDUIEN controls the RDUIF (EMAC_INTSTS[10]) interrupt generation + * | | |If RDUIF (EMAC_INTSTS[10]) is set, and both RDUIEN and RXIEN (EMAC_INTEN[0]) are enabled, the + * | | |EMAC generates the RX interrupt to CPU + * | | |If RDUIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |RDUIF (EMAC_MIOSTA[10]) register is set. + * | | |0 = RDUIF (EMAC_INTSTS[10]) trigger RX interrupt Disabled. + * | | |1 = RDUIF (EMAC_INTSTS[10]) trigger RX interrupt Enabled. + * |[11] |RXBEIEN |Receive Bus Error Interrupt Enable Bit + * | | |The RXBEIEN controls the RXBEIF (EMAC_INTSTS[11]) interrupt generation + * | | |If RXBEIF (EMAC_INTSTS[11]) is set, and both RXBEIEN and RXIEN (EMAC_INTEN[0]) are enabled, the + * | | |EMAC generates the RX interrupt to CPU + * | | |If RXBEIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |RXBEIF (EMAC_INTSTS[11]) is set. + * | | |0 = RXBEIF (EMAC_INTSTS[11]) trigger RX interrupt Disabled. + * | | |1 = RXBEIF (EMAC_INTSTS[11]) trigger RX interrupt Enabled. + * |[14] |CFRIEN |Control Frame Receive Interrupt Enable Bit + * | | |The CFRIEN controls the CFRIF (EMAC_INTSTS[14]) interrupt generation + * | | |If CFRIF (EMAC_INTSTS[14]) is set, and both CFRIEN and RXIEN (EMAC_INTEN[0]) are enabled, the + * | | |EMAC generates the RX interrupt to CPU + * | | |If CFRIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |CFRIF (EMAC_INTSTS[14]) register is set. + * | | |0 = CFRIF (EMAC_INTSTS[14]) trigger RX interrupt Disabled. + * | | |1 = CFRIF (EMAC_INTSTS[14]) trigger RX interrupt Enabled. + * |[15] |WOLIEN |Wake on LAN Interrupt Enable Bit + * | | |The WOLIEN controls the WOLIF (EMAC_INTSTS[15]) interrupt generation + * | | |If WOLIF (EMAC_INTSTS[15]) is set, and both WOLIEN and RXIEN (EMAC_INTEN[0]) are enabled, + * | | |the EMAC generates the RX interrupt to CPU + * | | |If WOLIEN or RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated to CPU even the + * | | |WOLIF (EMAC_INTSTS[15]) is set. + * | | |0 = WOLIF (EMAC_INTSTS[15]) trigger RX interrupt Disabled. + * | | |1 = WOLIF (EMAC_INTSTS[15]) trigger RX interrupt Enabled. + * |[16] |TXIEN |Transmit Interrupt Enable Bit + * | | |The TXIEN controls the TX interrupt generation. + * | | |If TXIEN is enabled and TXIF (EMAC_INTSTS[16]) is high, EMAC generates the TX interrupt to CPU + * | | |If TXIEN is disabled, no TX interrupt is generated to CPU even any status bit of + * | | |EMAC_INTSTS[24:17] set and the corresponding bit of EMAC_INTEN is enabled + * | | |In other words, if S/W wants to receive TX interrupt from EMAC, this bit must be enabled + * | | |And, if S/W doesn't want to receive any TX interrupt from EMAC, disables this bit. + * | | |0 = TXIF (EMAC_INTSTS[16]) is masked and TX interrupt generation Disabled. + * | | |1 = TXIF (EMAC_INTSTS[16]) is not masked and TX interrupt generation Enabled. + * |[17] |TXUDIEN |Transmit FIFO Underflow Interrupt Enable Bit + * | | |The TXUDIEN controls the TXUDIF (EMAC_INTSTS[17]) interrupt generation + * | | |If TXUDIF (EMAC_INTSTS[17]) is set, and both TXUDIEN and TXIEN (EMAC_INTEN[16]) are enabled, + * | | |the EMAC generates the TX interrupt to CPU + * | | |If TXUDIEN or TXIEN (EMAC_INTEN[16]) is disabled, no TX interrupt is generated to CPU even + * | | |the TXUDIF (EMAC_INTSTS[17]) is set. + * | | |0 = TXUDIF (EMAC_INTSTS[17]) TX interrupt Disabled. + * | | |1 = TXUDIF (EMAC_INTSTS[17]) TX interrupt Enabled. + * |[18] |TXCPIEN |Transmit Completion Interrupt Enable Bit + * | | |The TXCPIEN controls the TXCPIF (EMAC_INTSTS[18]) interrupt generation + * | | |If TXCPIF (EMAC_INTSTS[18]) is set, and both TXCPIEN and TXIEN (EMAC_INTEN[16]) are enabled, + * | | |the EMAC generates the TX interrupt to CPU + * | | |If TXCPIEN or TXIEN (EMAC_INTEN[16]) is disabled, no TX interrupt is generated to CPU even the + * | | |TXCPIF (EMAC_INTSTS[18]) is set. + * | | |0 = TXCPIF (EMAC_INTSTS[18]) trigger TX interrupt Disabled. + * | | |1 = TXCPIF (EMAC_INTSTS[18]) trigger TX interrupt Enabled. + * |[19] |EXDEFIEN |Defer Exceed Interrupt Enable Bit + * | | |The EXDEFIEN controls the EXDEFIF (EMAC_INTSTS[19]) interrupt generation + * | | |If EXDEFIF (EMAC_INTSTS[19]) is set, and both EXDEFIEN and TXIEN (EMAC_INTEN[16]) are enabled, + * | | |the EMAC generates the TX interrupt to CPU + * | | |If EXDEFIEN or TXIEN (EMAC_INTEN[16]) is disabled, no TX interrupt is generated to CPU even the + * | | |EXDEFIF (EMAC_INTSTS[19]) is set. + * | | |0 = EXDEFIF (EMAC_INTSTS[19]) trigger TX interrupt Disabled. + * | | |1 = EXDEFIF (EMAC_INTSTS[19]) trigger TX interrupt Enabled. + * |[20] |NCSIEN |No Carrier Sense Interrupt Enable Bit + * | | |The NCSIEN controls the NCSIF (EMAC_INTSTS[20]) interrupt generation + * | | |If NCSIF (EMAC_INTSTS[20]) is set, and both NCSIEN and TXIEN (EMAC_INTEN[16]) are enabled, the + * | | |EMAC generates the TX interrupt to CPU + * | | |If NCSIEN or TXIEN (EMAC_INTEN[16]) is disabled, no TX interrupt is generated to CPU even the + * | | |NCSIF (EMAC_INTSTS[20]) is set. + * | | |0 = NCSIF (EMAC_INTSTS[20]) trigger TX interrupt Disabled. + * | | |1 = NCSIF (EMAC_INTSTS[20]) trigger TX interrupt Enabled. + * |[21] |TXABTIEN |Transmit Abort Interrupt Enable Bit + * | | |The TXABTIEN controls the TXABTIF (EMAC_INTSTS[21]) interrupt generation + * | | |If TXABTIF (EMAC_INTSTS[21]) is set, and both TXABTIEN and TXIEN (EMAC_INTEN[16]) are enabled, + * | | |the EMAC generates the TX interrupt to CPU + * | | |If TXABTIEN or TXIEN (EMAC_INTEN[16]) is disabled, no TX interrupt is generated to CPU even the + * | | |TXABTIF (EMAC_INTSTS[21]) is set. + * | | |0 = TXABTIF (EMAC_INTSTS[21]) trigger TX interrupt Disabled. + * | | |1 = TXABTIF (EMAC_INTSTS[21]) trigger TX interrupt Enabled. + * |[22] |LCIEN |Late Collision Interrupt Enable Bit + * | | |The LCIEN controls the LCIF (EMAC_INTSTS[22]) interrupt generation + * | | |If LCIF (EMAC_INTSTS[22]) is set, and both LCIEN and TXIEN (EMAC_INTEN[16]) are enabled, the + * | | |EMAC generates the TX interrupt to CPU + * | | |If LCIEN or TXIEN (EMAC_INTEN[16]) is disabled, no TX interrupt is generated to CPU even the + * | | |LCIF (EMAC_INTSTS[22]) is set. + * | | |0 = LCIF (EMAC_INTSTS[22]) trigger TX interrupt Disabled. + * | | |1 = LCIF (EMAC_INTSTS[22]) trigger TX interrupt Enabled. + * |[23] |TDUIEN |Transmit Descriptor Unavailable Interrupt Enable Bit + * | | |The TDUIEN controls the TDUIF (EMAC_INTSTS[23]) interrupt generation + * | | |If TDUIF (EMAC_INTSTS[23]) is set, and both TDUIEN and TXIEN (EMAC_INTEN[16]) are enabled, the + * | | |EMAC generates the TX interrupt to CPU + * | | |If TDUIEN or TXIEN (EMAC_INTEN[16]) is disabled, no TX interrupt is generated to CPU even the + * | | |TDUIF (EMAC_INTSTS[23]) is set. + * | | |0 = TDUIF (EMAC_INTSTS[23]) trigger TX interrupt Disabled. + * | | |1 = TDUIF (EMAC_INTSTS[23]) trigger TX interrupt Enabled. + * |[24] |TXBEIEN |Transmit Bus Error Interrupt Enable Bit + * | | |The TXBEIEN controls the TXBEIF (EMAC_INTSTS[24]) interrupt generation + * | | |If TXBEIF (EMAC_INTSTS[24]) is set, and both TXBEIEN and TXIEN (EMAC_INTEN[16]) are enabled, the + * | | |EMAC generates the TX interrupt to CPU + * | | |If TXBEIEN or TXIEN (EMAC_INTEN[16]) is disabled, no TX interrupt is generated to CPU even the + * | | |TXBEIF (EMAC_INTSTS[24]) is set. + * | | |0 = TXBEIF (EMAC_INTSTS[24]) trigger TX interrupt Disabled. + * | | |1 = TXBEIF (EMAC_INTSTS[24]) trigger TX interrupt Enabled. + * |[28] |TSALMIEN |Time Stamp Alarm Interrupt Enable Bit + * | | |The TSALMIEN controls the TSALMIF (EMAC_INTSTS[28]) interrupt generation + * | | |If TSALMIF (EMAC_INTSTS[28]) is set, and both TSALMIEN and TXIEN (EMAC_INTEN[16]) enabled, the + * | | |EMAC generates the TX interrupt to CPU + * | | |If TSALMIEN or TXIEN (EMAC_INTEN[16]) disabled, no TX interrupt generated to CPU even the + * | | |TXTSALMIF (EMAC_INTEN[28]) is set. + * | | |0 = TXTSALMIF (EMAC_INTSTS[28]) trigger TX interrupt Disabled. + * | | |1 = TXTSALMIF (EMAC_INTSTS[28]) trigger TX interrupt Enabled. + * @var EMAC_T::INTSTS + * Offset: 0xB0 MAC Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RXIF |Receive Interrupt + * | | |The RXIF indicates the RX interrupt status. + * | | |If RXIF high and its corresponding enable bit, RXIEN (EMAC_INTEN[0]), is also high indicates + * | | |the EMAC generates RX interrupt to CPU + * | | |If RXIF is high but RXIEN (EMAC_INTEN[0]) is disabled, no RX interrupt is generated. + * | | |The RXIF is logic OR result of bit logic AND result of EMAC_INTSTS[15:1] and EMAC_INTEN[15:1] + * | | |In other words, if any bit of EMAC_INTSTS[15:1] is high and its corresponding enable bit in + * | | |EMAC_INTEN[15:1] is also enabled, the RXIF will be high. + * | | |Because the RXIF is a logic OR result, clears EMAC_INTSTS[15:1] makes RXIF be cleared, too. + * | | |0 = No status bit in EMAC_INTSTS[15:1] is set or no enable bit in EMAC_INTEN[15:1] is enabled. + * | | |1 = At least one status in EMAC_INTSTS[15:1] is set and its corresponding enable bit in + * | | |EMAC_INTEN[15:1] is enabled, too. + * |[1] |CRCEIF |CRC Error Interrupt + * | | |The CRCEIF high indicates the incoming packet incurred the CRC error and the packet is dropped + * | | |If the AEP (EMAC_CTL[4]) is set, the CRC error packet will be regarded as a good packet and + * | | |CRCEIF will not be set. + * | | |If the CRCEIF is high and CRCEIEN (EMAC_INTEN[1]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the CRCEIF status. + * | | |0 = The frame does not incur CRC error. + * | | |1 = The frame incurred CRC error. + * |[2] |RXOVIF |Receive FIFO Overflow Interrupt + * | | |The RXOVIF high indicates the RXFIFO overflow occurred during packet reception + * | | |While the RXFIFO overflow occurred, the EMAC drops the current receiving packer + * | | |If the RXFIFO overflow occurred often, it is recommended that modify RXFIFO threshold control, + * | | |the RXFIFOTH of FFTCR register, to higher level. + * | | |If the RXOVIF is high and RXOVIEN (EMAC_INTEN[2]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the RXOVIF status. + * | | |0 = No RXFIFO overflow occurred during packet reception. + * | | |1 = RXFIFO overflow occurred during packet reception. + * |[3] |LPIF |Long Packet Interrupt Flag + * | | |The LPIF high indicates the length of the incoming packet is greater than 1518 bytes and the + * | | |incoming packet is dropped + * | | |If the ALP (EMAC_CTL[1]) is set, the long packet will be regarded as a good packet and LPIF will not be set. + * | | |If the LPIF is high and LPIEN (EMAC_INTEN[3]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the LPIF status. + * | | |0 = The incoming frame is not a long frame or S/W wants to receive a long frame. + * | | |1 = The incoming frame is a long frame and dropped. + * |[4] |RXGDIF |Receive Good Interrupt + * | | |The RXGDIF high indicates the frame reception has completed. + * | | |If the RXGDIF is high and RXGDIEN (EAMC_MIEN[4]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the RXGDIF status. + * | | |0 = The frame reception has not complete yet. + * | | |1 = The frame reception has completed. + * |[5] |ALIEIF |Alignment Error Interrupt + * | | |The ALIEIF high indicates the length of the incoming frame is not a multiple of byte + * | | |If the ALIEIF is high and ALIEIEN (EMAC_INTEN[5]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the ALIEIF status. + * | | |0 = The frame length is a multiple of byte. + * | | |1 = The frame length is not a multiple of byte. + * |[6] |RPIF |Runt Packet Interrupt + * | | |The RPIF high indicates the length of the incoming packet is less than 64 bytes and the packet is dropped + * | | |If the ARP (EMAC_CTL[2]) is set, the short packet is regarded as a good packet and RPIF will not be set. + * | | |If the RPIF is high and RPIEN (EMAC_INTEN[6]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the RPIF status. + * | | |0 = The incoming frame is not a short frame or S/W wants to receive a short frame. + * | | |1 = The incoming frame is a short frame and dropped. + * |[7] |MPCOVIF |Missed Packet Counter Overrun Interrupt Flag + * | | |The MPCOVIF high indicates the MPCNT, Missed Packet Count, has overflow + * | | |If the MPCOVIF is high and MPCOVIEN (EMAC_INTEN[7]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the MPCOVIF status. + * | | |0 = The MPCNT has not rolled over yet. + * | | |1 = The MPCNT has rolled over yet. + * |[8] |MFLEIF |Maximum Frame Length Exceed Interrupt Flag + * | | |The MFLEIF high indicates the length of the incoming packet has exceeded the length limitation + * | | |configured in DMARFC register and the incoming packet is dropped + * | | |If the MFLEIF is high and MFLEIEN (EMAC_INTEN[8]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the MFLEIF status. + * | | |0 = The length of the incoming packet does not exceed the length limitation configured in DMARFC. + * | | |1 = The length of the incoming packet has exceeded the length limitation configured in DMARFC. + * |[9] |DENIF |DMA Early Notification Interrupt + * | | |The DENIF high indicates the EMAC has received the LENGTH field of the incoming packet. + * | | |If the DENIF is high and DENIENI (EMAC_INTEN[9]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the DENIF status. + * | | |0 = The LENGTH field of incoming packet has not received yet. + * | | |1 = The LENGTH field of incoming packet has received. + * |[10] |RDUIF |Receive Descriptor Unavailable Interrupt + * | | |The RDUIF high indicates that there is no available RX descriptor for packet reception and + * | | |RXDMA will stay at Halt state + * | | |Once, the RXDMA enters the Halt state, S/W must issues a write command to RSDR register to + * | | |make RXDMA leave Halt state while new RX descriptor is available. + * | | |If the RDUIF is high and RDUIEN (EMAC_INTEN[10]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the RDUIF status. + * | | |0 = RX descriptor is available. + * | | |1 = RX descriptor is unavailable. + * |[11] |RXBEIF |Receive Bus Error Interrupt + * | | |The RXBEIF high indicates the memory controller replies ERROR response while EMAC access + * | | |system memory through RXDMA during packet reception process + * | | |Reset EMAC is recommended while RXBEIF status is high. + * | | |If the RXBEIF is high and RXBEIEN (EMAC_INTEN[11]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the RXBEIF status. + * | | |0 = No ERROR response is received. + * | | |1 = ERROR response is received. + * |[14] |CFRIF |Control Frame Receive Interrupt + * | | |The CFRIF high indicates EMAC receives a flow control frame + * | | |The CFRIF only available while EMAC is operating on full duplex mode. + * | | |If the CFRIF is high and CFRIEN (EMAC_INTEN[14]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the CFRIF status. + * | | |0 = The EMAC does not receive the flow control frame. + * | | |1 = The EMAC receives a flow control frame. + * |[15] |WOLIF |Wake on LAN Interrupt Flag + * | | |The WOLIF high indicates EMAC receives a Magic Packet + * | | |The CFRIF only available while system is in power down mode and WOLEN is set high. + * | | |If the WOLIF is high and WOLIEN (EMAC_INTEN[15]) is enabled, the RXIF will be high + * | | |Write 1 to this bit clears the WOLIF status. + * | | |0 = The EMAC does not receive the Magic Packet. + * | | |1 = The EMAC receives a Magic Packet. + * |[16] |TXIF |Transmit Interrupt + * | | |The TXIF indicates the TX interrupt status. + * | | |If TXIF high and its corresponding enable bit, TXIEN (EMAC_INTEN[16]), is also high indicates + * | | |the EMAC generates TX interrupt to CPU + * | | |If TXIF is high but TXIEN (EMAC_INTEN[16]) is disabled, no TX interrupt is generated. + * | | |The TXIF is logic OR result of bit logic AND result of EMAC_INTSTS[28:17] and EMAC_INTEN[28:17] + * | | |In other words, if any bit of EMAC_INTSTS[28:17] is high and its corresponding enable bit + * | | |in EMAC_INTEN[28:17] is also enabled, the TXIF will be high + * | | |Because the TXIF is a logic OR result, clears EMAC_INTSTS[28:17] makes TXIF be cleared, too. + * | | |0 = No status bit in EMAC_INTSTS[28:17] is set or no enable bit in EMAC_INTEN[28:17] is enabled. + * | | |1 = At least one status in EMAC_INTSTS[28:17] is set and its corresponding enable bit + * | | |in EMAC_INTEN[28:17] is enabled, too. + * |[17] |TXUDIF |Transmit FIFO Underflow Interrupt + * | | |The TXUDIF high indicates the TXFIFO underflow occurred during packet transmission + * | | |While the TXFIFO underflow occurred, the EMAC will retransmit the packet automatically + * | | |without S/W intervention + * | | |If the TXFIFO underflow occurred often, it is recommended that modify TXFIFO threshold control, + * | | |the TXFIFOTH of FFTCR register, to higher level. + * | | |If the TXUDIF is high and TXUDIEN (EMAC_INTEN[17]) is enabled, the TXIF will be high + * | | |Write 1 to this bit clears the TXUDIF status. + * | | |0 = No TXFIFO underflow occurred during packet transmission. + * | | |1 = TXFIFO underflow occurred during packet transmission. + * |[18] |TXCPIF |Transmit Completion Interrupt + * | | |The TXCPIF indicates the packet transmission has completed correctly. + * | | |If the TXCPIF is high and TXCPIEN (EMAC_INTEN[18]) is enabled, the TXIF will be high + * | | |Write 1 to this bit clears the TXCPIF status. + * | | |0 = The packet transmission not completed. + * | | |1 = The packet transmission has completed. + * |[19] |EXDEFIF |Defer Exceed Interrupt + * | | |The EXDEFIF high indicates the frame waiting for transmission has deferred over 0.32768ms + * | | |on 100Mbps mode, or 3.2768ms on 10Mbps mode. + * | | |The deferral exceed check will only be done while bit NODEF of MCMDR is disabled, and EMAC + * | | |is operating on half-duplex mode. + * | | |If the EXDEFIF is high and EXDEFIEN (EMAC_INTEN[19]) is enabled, the TXIF will be high + * | | |Write 1 to this bit clears the EXDEFIF status. + * | | |0 = Frame waiting for transmission has not deferred over 0.32768ms (100Mbps) or 3.2768ms (10Mbps). + * | | |1 = Frame waiting for transmission has deferred over 0.32768ms (100Mbps) or 3.2768ms (10Mbps). + * |[20] |NCSIF |No Carrier Sense Interrupt + * | | |The NCSIF high indicates the MII I/F signal CRS does not active at the start of or during + * | | |the packet transmission + * | | |The NCSIF is only available while EMAC is operating on half-duplex mode + * | | |If the NCSIF is high and NCSIEN (EMAC_INTEN[20]) is enabled, the TXIF will be high. + * | | |Write 1 to this bit clears the NCSIF status. + * | | |0 = CRS signal actives correctly. + * | | |1 = CRS signal does not active at the start of or during the packet transmission. + * |[21] |TXABTIF |Transmit Abort Interrupt + * | | |The TXABTIF high indicates the packet incurred 16 consecutive collisions during transmission, + * | | |and then the transmission process for this packet is aborted + * | | |The transmission abort is only available while EMAC is operating on half-duplex mode. + * | | |If the TXABTIF is high and TXABTIEN (EMAC_INTEN[21]) is enabled, the TXIF will be high + * | | |Write 1 to this bit clears the TXABTIF status. + * | | |0 = Packet does not incur 16 consecutive collisions during transmission. + * | | |1 = Packet incurred 16 consecutive collisions during transmission. + * |[22] |LCIF |Late Collision Interrupt + * | | |The LCIF high indicates the collision occurred in the outside of 64 bytes collision window + * | | |This means after the 64 bytes of a frame has been transmitted out to the network, the collision + * | | |still occurred. + * | | |The late collision check will only be done while EMAC is operating on half-duplex mode + * | | |If the LCIF is high and LCIEN (EMAC_INTEN[22]) is enabled, the TXIF will be high. + * | | |Write 1 to this bit clears the LCIF status. + * | | |0 = No collision occurred in the outside of 64 bytes collision window. + * | | |1 = Collision occurred in the outside of 64 bytes collision window. + * |[23] |TDUIF |Transmit Descriptor Unavailable Interrupt + * | | |The TDUIF high indicates that there is no available TX descriptor for packet transmission and + * | | |TXDMA will stay at Halt state. + * | | |Once, the TXDMA enters the Halt state, S/W must issues a write command to TSDR register to make + * | | |TXDMA leave Halt state while new TX descriptor is available. + * | | |If the TDUIF is high and TDUIEN (EMAC_INTEN[23]) is enabled, the TXIF will be high. + * | | |Write 1 to this bit clears the TDUIF status. + * | | |0 = TX descriptor is available. + * | | |1 = TX descriptor is unavailable. + * |[24] |TXBEIF |Transmit Bus Error Interrupt + * | | |The TXBEIF high indicates the memory controller replies ERROR response while EMAC access system + * | | |memory through TXDMA during packet transmission process + * | | |Reset EMAC is recommended while TXBEIF status is high. + * | | |If the TXBEIF is high and TXBEIEN (EMAC_INTEN[24]) is enabled, the TXIF will be high. + * | | |Write 1 to this bit clears the TXBEIF status. + * | | |0 = No ERROR response is received. + * | | |1 = ERROR response is received. + * |[28] |TSALMIF |Time Stamp Alarm Interrupt + * | | |The TSALMIF high indicates the EMAC_TSSEC register value equals to EMAC_ALMSEC register and + * | | |EMAC_TSSUBSEC register value equals to register EMAC_ALMSUBLSR. + * | | |If TSALMIF is high and TSALMIEN (EMAC_INTEN[28]) enabled, the TXIF will be high. + * | | |Write 1 to this bit clears the TSALMIF status. + * | | |0 = EMAC_TSSEC did not equal EMAC_ALMSEC or EMAC_TSSUBSEC did not equal EMAC_ALMSUBSEC. + * | | |1 = EMAC_TSSEC equals EMAC_ALMSEC and EMAC_TSSUBSEC equals EMAC_ALMSUBSEC. + * @var EMAC_T::GENSTS + * Offset: 0xB4 MAC General Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CFR |Control Frame Received + * | | |The CFRIF high indicates EMAC receives a flow control frame + * | | |The CFRIF only available while EMAC is operating on full duplex mode. + * | | |0 = The EMAC does not receive the flow control frame. + * | | |1 = The EMAC receives a flow control frame. + * |[1] |RXHALT |Receive Halted + * | | |The RXHALT high indicates the next normal packet reception process will be halted because + * | | |the bit RXON of MCMDR is disabled be S/W. + * | | |0 = Next normal packet reception process will go on. + * | | |1 = Next normal packet reception process will be halted. + * |[2] |RXFFULL |RXFIFO Full + * | | |The RXFFULL indicates the RXFIFO is full due to four 64-byte packets are kept in RXFIFO + * | | |and the following incoming packet will be dropped. + * | | |0 = The RXFIFO is not full. + * | | |1 = The RXFIFO is full and the following incoming packet will be dropped. + * |[7:4] |COLCNT |Collision Count + * | | |The COLCNT indicates that how many collisions occurred consecutively during a packet transmission + * | | |If the packet incurred 16 consecutive collisions during transmission, the COLCNT will be + * | | |0 and bit TXABTIF will be set to 1. + * |[8] |DEF |Deferred Transmission + * | | |The DEF high indicates the packet transmission has deferred once + * | | |The DEF is only available while EMAC is operating on half-duplex mode. + * | | |0 = Packet transmission does not defer. + * | | |1 = Packet transmission has deferred once. + * |[9] |TXPAUSED |Transmission Paused + * | | |The TXPAUSED high indicates the next normal packet transmission process will be paused temporally + * | | |because EMAC received a PAUSE control frame. + * | | |0 = Next normal packet transmission process will go on. + * | | |1 = Next normal packet transmission process will be paused. + * |[10] |SQE |Signal Quality Error + * | | |The SQE high indicates the SQE error found at end of packet transmission on 10Mbps half-duplex mode + * | | |The SQE error check will only be done while both bit SQECHKEN (EMAC_CTL[17]) is enabled and EMAC + * | | |is operating on 10Mbps half-duplex mode. + * | | |0 = No SQE error found at end of packet transmission. + * | | |1 = SQE error found at end of packet transmission. + * |[11] |TXHALT |Transmission Halted + * | | |The TXHALT high indicates the next normal packet transmission process will be halted because + * | | |the bit TXON (EMAC_CTL[8]) is disabled be S/W. + * | | |0 = Next normal packet transmission process will go on. + * | | |1 = Next normal packet transmission process will be halted. + * |[12] |RPSTS |Remote Pause Status + * | | |The RPSTS indicates that remote pause counter down counting actives. + * | | |After Ethernet MAC controller sent PAUSE frame out successfully, it starts the remote pause + * | | |counter down counting + * | | |When this bit high, it's predictable that remote Ethernet MAC controller wouldn't start the packet + * | | |transmission until the down counting done. + * | | |0 = Remote pause counter down counting done. + * | | |1 = Remote pause counter down counting actives. + * @var EMAC_T::MPCNT + * Offset: 0xB8 Missed Packet Count Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |MPCNT |Miss Packet Count + * | | |The MPCNT indicates the number of packets that were dropped due to various types of receive errors + * | | |The following type of receiving error makes missed packet counter increase: + * | | |1. Incoming packet is incurred RXFIFO overflow. + * | | |2. Incoming packet is dropped due to RXON is disabled. + * | | |3. Incoming packet is incurred CRC error. + * @var EMAC_T::RPCNT + * Offset: 0xBC MAC Receive Pause Count Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RPCNT |MAC Receive Pause Count + * | | |The RPCNT keeps the OPERAND field of the PAUSE control frame + * | | |It indicates how many slot time (512 bit time) the TX of EMAC will be paused. + * @var EMAC_T::FRSTS + * Offset: 0xC8 DMA Receive Frame Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RXFLT |Receive Frame LENGTH + * | | |The RXFLT keeps the LENGTH field of each incoming Ethernet packet + * | | |If the bit DENIEN (EMAC_INTEN[9]) is enabled and the LENGTH field of incoming packet has + * | | |received, the bit DENIF (EMAC_INTSTS[9]) will be set and trigger interrupt. + * | | |And, the content of LENGTH field will be stored in RXFLT. + * @var EMAC_T::CTXDSA + * Offset: 0xCC Current Transmit Descriptor Start Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |CTXDSA |Current Transmit Descriptor Start Address + * | | |The CTXDSA keeps the start address of TX descriptor that is used by TXDMA currently + * | | |The CTXDSA is read only and write to this register has no effect. + * @var EMAC_T::CTXBSA + * Offset: 0xD0 Current Transmit Buffer Start Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |CTXBSA |Current Transmit Buffer Start Address + * | | |The CTXDSA keeps the start address of TX frame buffer that is used by TXDMA currently + * | | |The CTXBSA is read only and write to this register has no effect. + * @var EMAC_T::CRXDSA + * Offset: 0xD4 Current Receive Descriptor Start Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |CRXDSA |Current Receive Descriptor Start Address + * | | |The CRXDSA keeps the start address of RX descriptor that is used by RXDMA currently + * | | |The CRXDSA is read only and write to this register has no effect. + * @var EMAC_T::CRXBSA + * Offset: 0xD8 Current Receive Buffer Start Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |CRXBSA |Current Receive Buffer Start Address + * | | |The CRXBSA keeps the start address of RX frame buffer that is used by RXDMA currently + * | | |The CRXBSA is read only and write to this register has no effect. + * @var EMAC_T::TSCTL + * Offset: 0x100 Time Stamp Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |TSEN |Time Stamp Function Enable Bit + * | | |This bit controls if the IEEE 1588 PTP time stamp function is enabled or not. + * | | |Set this bit high to enable IEEE 1588 PTP time stamp function while set this bit low + * | | |to disable IEEE 1588 PTP time stamp function. + * | | |0 = I EEE 1588 PTP time stamp function Disabled. + * | | |1 = IEEE 1588 PTP time stamp function Enabled. + * |[1] |TSIEN |Time Stamp Counter Initialization Enable Bit + * | | |Set this bit high enables Ethernet MAC controller to load value of register EMAC_UPDSEC + * | | |and EMAC_UPDSUBSEC to PTP time stamp counter. + * | | |After the load operation finished, Ethernet MAC controller clear this bit to low automatically. + * | | |0 = Time stamp counter initialization done. + * | | |1 = Time stamp counter initialization Enabled. + * |[2] |TSMODE |Time Stamp Fine Update Enable Bit + * | | |This bit chooses the time stamp counter update mode. + * | | |0 = Time stamp counter is in coarse update mode. + * | | |1 = Time stamp counter is in fine update mode. + * |[3] |TSUPDATE |Time Stamp Counter Time Update Enable Bit + * | | |Set this bit high enables Ethernet MAC controller to add value of register EMAC_UPDSEC and + * | | |EMAC_UPDSUBSEC to PTP time stamp counter. + * | | |After the add operation finished, Ethernet MAC controller clear this bit to low automatically. + * | | |0 = No action. + * | | |1 = EMAC_UPDSEC updated to EMAC_TSSEC and EMAC_UPDSUBSEC updated to EMAC_TSSUBSEC. + * |[5] |TSALMEN |Time Stamp Alarm Enable Bit + * | | |Set this bit high enable Ethernet MAC controller to set TSALMIF (EMAC_INTSTS[28]) high when + * | | |EMAC_TSSEC equals to EMAC_ALMSEC and EMAC_TSSUBSEC equals to EMAC_ALMSUBSEC. + * | | |0 = Alarm disabled when EMAC_TSSEC equals to EMAC_ALMSEC and EMAC_TSSUBSEC equals to EMAC_ALMSUBSEC. + * | | |1 = Alarm enabled when EMAC_TSSEC equals to EMAC_ALMSEC and EMAC_TSSUBSEC equals to EMAC_ALMSUBSEC. + * @var EMAC_T::TSSEC + * Offset: 0x110 Time Stamp Counter Second Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SEC |Time Stamp Counter Second + * | | |This register reflects the bit [63:32] value of 64-bit reference timing counter + * | | |This 32-bit value is used as the second part of time stamp when TSEN (EMAC_TSCTL[0]) is high. + * @var EMAC_T::TSSUBSEC + * Offset: 0x114 Time Stamp Counter Sub Second Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SUBSEC |Time Stamp Counter Sub-second + * | | |This register reflects the bit [31:0] value of 64-bit reference timing counter + * | | |This 32-bit value is used as the sub-second part of time stamp when TSEN (EMAC_TSCTL[0]) is high. + * @var EMAC_T::TSINC + * Offset: 0x118 Time Stamp Increment Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |CNTINC |Time Stamp Counter Increment + * | | |Time stamp counter increment value. + * | | |If TSEN (EMAC_TSCTL[0]) is high, EMAC adds EMAC_TSSUBSEC with this 8-bit value every + * | | |time when it wants to increase the EMAC_TSSUBSEC value. + * @var EMAC_T::TSADDEND + * Offset: 0x11C Time Stamp Addend Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |ADDEND |Time Stamp Counter Addend + * | | |This register keeps a 32-bit value for accumulator to enable increment of EMAC_TSSUBSEC. + * | | |If TSEN (EMAC_TSCTL[0]) and TSMODE (EMAC_TSCTL[2]) are both high, EMAC increases accumulator + * | | |with this 32-bit value in each HCLK + * | | |Once the accumulator is overflow, it generates a enable to increase EMAC_TSSUBSEC with an 8-bit + * | | |value kept in register EMAC_TSINC. + * @var EMAC_T::UPDSEC + * Offset: 0x120 Time Stamp Update Second Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SEC |Time Stamp Counter Second Update + * | | |When TSIEN (EMAC_TSCTL[1]) is high + * | | |EMAC loads this 32-bit value to EMAC_TSSEC directly + * | | |When TSUPDATE (EMAC_TSCTL[3]) is high, EMAC increases EMAC_TSSEC with this 32-bit value. + * @var EMAC_T::UPDSUBSEC + * Offset: 0x124 Time Stamp Update Sub Second Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SUBSEC |Time Stamp Counter Sub-second Update + * | | |When TSIEN (EMAC_TSCTL[1]) is high + * | | |EMAC loads this 32-bit value to EMAC_TSSUBSEC directly + * | | |When TSUPDATE (EMAC_TSCTL[3]) is high, EMAC increases EMAC_TSSUBSEC with this 32-bit value. + * @var EMAC_T::ALMSEC + * Offset: 0x128 Time Stamp Alarm Second Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SEC |Time Stamp Counter Second Alarm + * | | |Time stamp counter second part alarm value. + * | | |This value is only useful when ALMEN (EMAC_TSCTL[5]) high + * | | |If ALMEN (EMAC_TSCTL[5]) is high, EMAC_TSSEC equals to EMAC_ALMSEC and EMAC_TSSUBSEC equals to + * | | |EMAC_ALMSUBSEC, Ethernet MAC controller set TSALMIF (EMAC_INTSTS[28]) high. + * @var EMAC_T::ALMSUBSEC + * Offset: 0x12C Time Stamp Alarm Sub Second Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SUBSEC |Time Stamp Counter Sub-second Alarm + * | | |Time stamp counter sub-second part alarm value. + * | | |This value is only useful when ALMEN (EMAC_TSCTL[5]) high + * | | |If ALMEN (EMAC_TSCTL[5]) is high, EMAC_TSSEC equals to EMAC_ALMSEC and EMAC_TSSUBSEC equals to + * | | |EMAC_ALMSUBSEC, Ethernet MAC controller set TSALMIF (EMAC_INTSTS[28]) high. + */ + __IO uint32_t CAMCTL; /*!< [0x0000] CAM Comparison Control Register */ + __IO uint32_t CAMEN; /*!< [0x0004] CAM Enable Register */ + __IO uint32_t CAM0M; /*!< [0x0008] CAM0 Most Significant Word Register */ + __IO uint32_t CAM0L; /*!< [0x000c] CAM0 Least Significant Word Register */ + __IO uint32_t CAM1M; /*!< [0x0010] CAM1 Most Significant Word Register */ + __IO uint32_t CAM1L; /*!< [0x0014] CAM1 Least Significant Word Register */ + __IO uint32_t CAM2M; /*!< [0x0018] CAM2 Most Significant Word Register */ + __IO uint32_t CAM2L; /*!< [0x001c] CAM2 Least Significant Word Register */ + __IO uint32_t CAM3M; /*!< [0x0020] CAM3 Most Significant Word Register */ + __IO uint32_t CAM3L; /*!< [0x0024] CAM3 Least Significant Word Register */ + __IO uint32_t CAM4M; /*!< [0x0028] CAM4 Most Significant Word Register */ + __IO uint32_t CAM4L; /*!< [0x002c] CAM4 Least Significant Word Register */ + __IO uint32_t CAM5M; /*!< [0x0030] CAM5 Most Significant Word Register */ + __IO uint32_t CAM5L; /*!< [0x0034] CAM5 Least Significant Word Register */ + __IO uint32_t CAM6M; /*!< [0x0038] CAM6 Most Significant Word Register */ + __IO uint32_t CAM6L; /*!< [0x003c] CAM6 Least Significant Word Register */ + __IO uint32_t CAM7M; /*!< [0x0040] CAM7 Most Significant Word Register */ + __IO uint32_t CAM7L; /*!< [0x0044] CAM7 Least Significant Word Register */ + __IO uint32_t CAM8M; /*!< [0x0048] CAM8 Most Significant Word Register */ + __IO uint32_t CAM8L; /*!< [0x004c] CAM8 Least Significant Word Register */ + __IO uint32_t CAM9M; /*!< [0x0050] CAM9 Most Significant Word Register */ + __IO uint32_t CAM9L; /*!< [0x0054] CAM9 Least Significant Word Register */ + __IO uint32_t CAM10M; /*!< [0x0058] CAM10 Most Significant Word Register */ + __IO uint32_t CAM10L; /*!< [0x005c] CAM10 Least Significant Word Register */ + __IO uint32_t CAM11M; /*!< [0x0060] CAM11 Most Significant Word Register */ + __IO uint32_t CAM11L; /*!< [0x0064] CAM11 Least Significant Word Register */ + __IO uint32_t CAM12M; /*!< [0x0068] CAM12 Most Significant Word Register */ + __IO uint32_t CAM12L; /*!< [0x006c] CAM12 Least Significant Word Register */ + __IO uint32_t CAM13M; /*!< [0x0070] CAM13 Most Significant Word Register */ + __IO uint32_t CAM13L; /*!< [0x0074] CAM13 Least Significant Word Register */ + __IO uint32_t CAM14M; /*!< [0x0078] CAM14 Most Significant Word Register */ + __IO uint32_t CAM14L; /*!< [0x007c] CAM14 Least Significant Word Register */ + __IO uint32_t CAM15MSB; /*!< [0x0080] CAM15 Most Significant Word Register */ + __IO uint32_t CAM15LSB; /*!< [0x0084] CAM15 Least Significant Word Register */ + __IO uint32_t TXDSA; /*!< [0x0088] Transmit Descriptor Link List Start Address Register */ + __IO uint32_t RXDSA; /*!< [0x008c] Receive Descriptor Link List Start Address Register */ + __IO uint32_t CTL; /*!< [0x0090] MAC Control Register */ + __IO uint32_t MIIMDAT; /*!< [0x0094] MII Management Data Register */ + __IO uint32_t MIIMCTL; /*!< [0x0098] MII Management Control and Address Register */ + __IO uint32_t FIFOCTL; /*!< [0x009c] FIFO Threshold Control Register */ + __O uint32_t TXST; /*!< [0x00a0] Transmit Start Demand Register */ + __O uint32_t RXST; /*!< [0x00a4] Receive Start Demand Register */ + __IO uint32_t MRFL; /*!< [0x00a8] Maximum Receive Frame Control Register */ + __IO uint32_t INTEN; /*!< [0x00ac] MAC Interrupt Enable Register */ + __IO uint32_t INTSTS; /*!< [0x00b0] MAC Interrupt Status Register */ + __IO uint32_t GENSTS; /*!< [0x00b4] MAC General Status Register */ + __IO uint32_t MPCNT; /*!< [0x00b8] Missed Packet Count Register */ + __I uint32_t RPCNT; /*!< [0x00bc] MAC Receive Pause Count Register */ + /** @cond HIDDEN_SYMBOLS */ + __I uint32_t RESERVE0[2]; + /** @endcond */ + __IO uint32_t FRSTS; /*!< [0x00c8] DMA Receive Frame Status Register */ + __I uint32_t CTXDSA; /*!< [0x00cc] Current Transmit Descriptor Start Address Register */ + __I uint32_t CTXBSA; /*!< [0x00d0] Current Transmit Buffer Start Address Register */ + __I uint32_t CRXDSA; /*!< [0x00d4] Current Receive Descriptor Start Address Register */ + __I uint32_t CRXBSA; /*!< [0x00d8] Current Receive Buffer Start Address Register */ + /** @cond HIDDEN_SYMBOLS */ + __I uint32_t RESERVE1[9]; + /** @endcond */ + __IO uint32_t TSCTL; /*!< [0x0100] Time Stamp Control Register */ + /** @cond HIDDEN_SYMBOLS */ + __I uint32_t RESERVE2[3]; + /** @endcond */ + __I uint32_t TSSEC; /*!< [0x0110] Time Stamp Counter Second Register */ + __I uint32_t TSSUBSEC; /*!< [0x0114] Time Stamp Counter Sub Second Register */ + __IO uint32_t TSINC; /*!< [0x0118] Time Stamp Increment Register */ + __IO uint32_t TSADDEND; /*!< [0x011c] Time Stamp Addend Register */ + __IO uint32_t UPDSEC; /*!< [0x0120] Time Stamp Update Second Register */ + __IO uint32_t UPDSUBSEC; /*!< [0x0124] Time Stamp Update Sub Second Register */ + __IO uint32_t ALMSEC; /*!< [0x0128] Time Stamp Alarm Second Register */ + __IO uint32_t ALMSUBSEC; /*!< [0x012c] Time Stamp Alarm Sub Second Register */ + +} EMAC_T; + +/** + @addtogroup EMAC_CONST EMAC Bit Field Definition + Constant Definitions for EMAC Controller +@{ */ + +#define EMAC_CAMCTL_AUP_Pos (0) /*!< EMAC_T::CAMCTL: AUP Position */ +#define EMAC_CAMCTL_AUP_Msk (0x1ul << EMAC_CAMCTL_AUP_Pos) /*!< EMAC_T::CAMCTL: AUP Mask */ + +#define EMAC_CAMCTL_AMP_Pos (1) /*!< EMAC_T::CAMCTL: AMP Position */ +#define EMAC_CAMCTL_AMP_Msk (0x1ul << EMAC_CAMCTL_AMP_Pos) /*!< EMAC_T::CAMCTL: AMP Mask */ + +#define EMAC_CAMCTL_ABP_Pos (2) /*!< EMAC_T::CAMCTL: ABP Position */ +#define EMAC_CAMCTL_ABP_Msk (0x1ul << EMAC_CAMCTL_ABP_Pos) /*!< EMAC_T::CAMCTL: ABP Mask */ + +#define EMAC_CAMCTL_COMPEN_Pos (3) /*!< EMAC_T::CAMCTL: COMPEN Position */ +#define EMAC_CAMCTL_COMPEN_Msk (0x1ul << EMAC_CAMCTL_COMPEN_Pos) /*!< EMAC_T::CAMCTL: COMPEN Mask */ + +#define EMAC_CAMCTL_CMPEN_Pos (4) /*!< EMAC_T::CAMCTL: CMPEN Position */ +#define EMAC_CAMCTL_CMPEN_Msk (0x1ul << EMAC_CAMCTL_CMPEN_Pos) /*!< EMAC_T::CAMCTL: CMPEN Mask */ + +#define EMAC_CAMEN_CAMxEN_Pos (0) /*!< EMAC_T::CAMEN: CAMxEN Position */ +#define EMAC_CAMEN_CAMxEN_Msk (0x1ul << EMAC_CAMEN_CAMxEN_Pos) /*!< EMAC_T::CAMEN: CAMxEN Mask */ + +#define EMAC_CAM0M_MACADDR2_Pos (0) /*!< EMAC_T::CAM0M: MACADDR2 Position */ +#define EMAC_CAM0M_MACADDR2_Msk (0xfful << EMAC_CAM0M_MACADDR2_Pos) /*!< EMAC_T::CAM0M: MACADDR2 Mask */ + +#define EMAC_CAM0M_MACADDR3_Pos (8) /*!< EMAC_T::CAM0M: MACADDR3 Position */ +#define EMAC_CAM0M_MACADDR3_Msk (0xfful << EMAC_CAM0M_MACADDR3_Pos) /*!< EMAC_T::CAM0M: MACADDR3 Mask */ + +#define EMAC_CAM0M_MACADDR4_Pos (16) /*!< EMAC_T::CAM0M: MACADDR4 Position */ +#define EMAC_CAM0M_MACADDR4_Msk (0xfful << EMAC_CAM0M_MACADDR4_Pos) /*!< EMAC_T::CAM0M: MACADDR4 Mask */ + +#define EMAC_CAM0M_MACADDR5_Pos (24) /*!< EMAC_T::CAM0M: MACADDR5 Position */ +#define EMAC_CAM0M_MACADDR5_Msk (0xfful << EMAC_CAM0M_MACADDR5_Pos) /*!< EMAC_T::CAM0M: MACADDR5 Mask */ + +#define EMAC_CAM0L_MACADDR0_Pos (16) /*!< EMAC_T::CAM0L: MACADDR0 Position */ +#define EMAC_CAM0L_MACADDR0_Msk (0xfful << EMAC_CAM0L_MACADDR0_Pos) /*!< EMAC_T::CAM0L: MACADDR0 Mask */ + +#define EMAC_CAM0L_MACADDR1_Pos (24) /*!< EMAC_T::CAM0L: MACADDR1 Position */ +#define EMAC_CAM0L_MACADDR1_Msk (0xfful << EMAC_CAM0L_MACADDR1_Pos) /*!< EMAC_T::CAM0L: MACADDR1 Mask */ + +#define EMAC_CAM1M_MACADDR2_Pos (0) /*!< EMAC_T::CAM1M: MACADDR2 Position */ +#define EMAC_CAM1M_MACADDR2_Msk (0xfful << EMAC_CAM1M_MACADDR2_Pos) /*!< EMAC_T::CAM1M: MACADDR2 Mask */ + +#define EMAC_CAM1M_MACADDR3_Pos (8) /*!< EMAC_T::CAM1M: MACADDR3 Position */ +#define EMAC_CAM1M_MACADDR3_Msk (0xfful << EMAC_CAM1M_MACADDR3_Pos) /*!< EMAC_T::CAM1M: MACADDR3 Mask */ + +#define EMAC_CAM1M_MACADDR4_Pos (16) /*!< EMAC_T::CAM1M: MACADDR4 Position */ +#define EMAC_CAM1M_MACADDR4_Msk (0xfful << EMAC_CAM1M_MACADDR4_Pos) /*!< EMAC_T::CAM1M: MACADDR4 Mask */ + +#define EMAC_CAM1M_MACADDR5_Pos (24) /*!< EMAC_T::CAM1M: MACADDR5 Position */ +#define EMAC_CAM1M_MACADDR5_Msk (0xfful << EMAC_CAM1M_MACADDR5_Pos) /*!< EMAC_T::CAM1M: MACADDR5 Mask */ + +#define EMAC_CAM1L_MACADDR0_Pos (16) /*!< EMAC_T::CAM1L: MACADDR0 Position */ +#define EMAC_CAM1L_MACADDR0_Msk (0xfful << EMAC_CAM1L_MACADDR0_Pos) /*!< EMAC_T::CAM1L: MACADDR0 Mask */ + +#define EMAC_CAM1L_MACADDR1_Pos (24) /*!< EMAC_T::CAM1L: MACADDR1 Position */ +#define EMAC_CAM1L_MACADDR1_Msk (0xfful << EMAC_CAM1L_MACADDR1_Pos) /*!< EMAC_T::CAM1L: MACADDR1 Mask */ + +#define EMAC_CAM2M_MACADDR2_Pos (0) /*!< EMAC_T::CAM2M: MACADDR2 Position */ +#define EMAC_CAM2M_MACADDR2_Msk (0xfful << EMAC_CAM2M_MACADDR2_Pos) /*!< EMAC_T::CAM2M: MACADDR2 Mask */ + +#define EMAC_CAM2M_MACADDR3_Pos (8) /*!< EMAC_T::CAM2M: MACADDR3 Position */ +#define EMAC_CAM2M_MACADDR3_Msk (0xfful << EMAC_CAM2M_MACADDR3_Pos) /*!< EMAC_T::CAM2M: MACADDR3 Mask */ + +#define EMAC_CAM2M_MACADDR4_Pos (16) /*!< EMAC_T::CAM2M: MACADDR4 Position */ +#define EMAC_CAM2M_MACADDR4_Msk (0xfful << EMAC_CAM2M_MACADDR4_Pos) /*!< EMAC_T::CAM2M: MACADDR4 Mask */ + +#define EMAC_CAM2M_MACADDR5_Pos (24) /*!< EMAC_T::CAM2M: MACADDR5 Position */ +#define EMAC_CAM2M_MACADDR5_Msk (0xfful << EMAC_CAM2M_MACADDR5_Pos) /*!< EMAC_T::CAM2M: MACADDR5 Mask */ + +#define EMAC_CAM2L_MACADDR0_Pos (16) /*!< EMAC_T::CAM2L: MACADDR0 Position */ +#define EMAC_CAM2L_MACADDR0_Msk (0xfful << EMAC_CAM2L_MACADDR0_Pos) /*!< EMAC_T::CAM2L: MACADDR0 Mask */ + +#define EMAC_CAM2L_MACADDR1_Pos (24) /*!< EMAC_T::CAM2L: MACADDR1 Position */ +#define EMAC_CAM2L_MACADDR1_Msk (0xfful << EMAC_CAM2L_MACADDR1_Pos) /*!< EMAC_T::CAM2L: MACADDR1 Mask */ + +#define EMAC_CAM3M_MACADDR2_Pos (0) /*!< EMAC_T::CAM3M: MACADDR2 Position */ +#define EMAC_CAM3M_MACADDR2_Msk (0xfful << EMAC_CAM3M_MACADDR2_Pos) /*!< EMAC_T::CAM3M: MACADDR2 Mask */ + +#define EMAC_CAM3M_MACADDR3_Pos (8) /*!< EMAC_T::CAM3M: MACADDR3 Position */ +#define EMAC_CAM3M_MACADDR3_Msk (0xfful << EMAC_CAM3M_MACADDR3_Pos) /*!< EMAC_T::CAM3M: MACADDR3 Mask */ + +#define EMAC_CAM3M_MACADDR4_Pos (16) /*!< EMAC_T::CAM3M: MACADDR4 Position */ +#define EMAC_CAM3M_MACADDR4_Msk (0xfful << EMAC_CAM3M_MACADDR4_Pos) /*!< EMAC_T::CAM3M: MACADDR4 Mask */ + +#define EMAC_CAM3M_MACADDR5_Pos (24) /*!< EMAC_T::CAM3M: MACADDR5 Position */ +#define EMAC_CAM3M_MACADDR5_Msk (0xfful << EMAC_CAM3M_MACADDR5_Pos) /*!< EMAC_T::CAM3M: MACADDR5 Mask */ + +#define EMAC_CAM3L_MACADDR0_Pos (16) /*!< EMAC_T::CAM3L: MACADDR0 Position */ +#define EMAC_CAM3L_MACADDR0_Msk (0xfful << EMAC_CAM3L_MACADDR0_Pos) /*!< EMAC_T::CAM3L: MACADDR0 Mask */ + +#define EMAC_CAM3L_MACADDR1_Pos (24) /*!< EMAC_T::CAM3L: MACADDR1 Position */ +#define EMAC_CAM3L_MACADDR1_Msk (0xfful << EMAC_CAM3L_MACADDR1_Pos) /*!< EMAC_T::CAM3L: MACADDR1 Mask */ + +#define EMAC_CAM4M_MACADDR2_Pos (0) /*!< EMAC_T::CAM4M: MACADDR2 Position */ +#define EMAC_CAM4M_MACADDR2_Msk (0xfful << EMAC_CAM4M_MACADDR2_Pos) /*!< EMAC_T::CAM4M: MACADDR2 Mask */ + +#define EMAC_CAM4M_MACADDR3_Pos (8) /*!< EMAC_T::CAM4M: MACADDR3 Position */ +#define EMAC_CAM4M_MACADDR3_Msk (0xfful << EMAC_CAM4M_MACADDR3_Pos) /*!< EMAC_T::CAM4M: MACADDR3 Mask */ + +#define EMAC_CAM4M_MACADDR4_Pos (16) /*!< EMAC_T::CAM4M: MACADDR4 Position */ +#define EMAC_CAM4M_MACADDR4_Msk (0xfful << EMAC_CAM4M_MACADDR4_Pos) /*!< EMAC_T::CAM4M: MACADDR4 Mask */ + +#define EMAC_CAM4M_MACADDR5_Pos (24) /*!< EMAC_T::CAM4M: MACADDR5 Position */ +#define EMAC_CAM4M_MACADDR5_Msk (0xfful << EMAC_CAM4M_MACADDR5_Pos) /*!< EMAC_T::CAM4M: MACADDR5 Mask */ + +#define EMAC_CAM4L_MACADDR0_Pos (16) /*!< EMAC_T::CAM4L: MACADDR0 Position */ +#define EMAC_CAM4L_MACADDR0_Msk (0xfful << EMAC_CAM4L_MACADDR0_Pos) /*!< EMAC_T::CAM4L: MACADDR0 Mask */ + +#define EMAC_CAM4L_MACADDR1_Pos (24) /*!< EMAC_T::CAM4L: MACADDR1 Position */ +#define EMAC_CAM4L_MACADDR1_Msk (0xfful << EMAC_CAM4L_MACADDR1_Pos) /*!< EMAC_T::CAM4L: MACADDR1 Mask */ + +#define EMAC_CAM5M_MACADDR2_Pos (0) /*!< EMAC_T::CAM5M: MACADDR2 Position */ +#define EMAC_CAM5M_MACADDR2_Msk (0xfful << EMAC_CAM5M_MACADDR2_Pos) /*!< EMAC_T::CAM5M: MACADDR2 Mask */ + +#define EMAC_CAM5M_MACADDR3_Pos (8) /*!< EMAC_T::CAM5M: MACADDR3 Position */ +#define EMAC_CAM5M_MACADDR3_Msk (0xfful << EMAC_CAM5M_MACADDR3_Pos) /*!< EMAC_T::CAM5M: MACADDR3 Mask */ + +#define EMAC_CAM5M_MACADDR4_Pos (16) /*!< EMAC_T::CAM5M: MACADDR4 Position */ +#define EMAC_CAM5M_MACADDR4_Msk (0xfful << EMAC_CAM5M_MACADDR4_Pos) /*!< EMAC_T::CAM5M: MACADDR4 Mask */ + +#define EMAC_CAM5M_MACADDR5_Pos (24) /*!< EMAC_T::CAM5M: MACADDR5 Position */ +#define EMAC_CAM5M_MACADDR5_Msk (0xfful << EMAC_CAM5M_MACADDR5_Pos) /*!< EMAC_T::CAM5M: MACADDR5 Mask */ + +#define EMAC_CAM5L_MACADDR0_Pos (16) /*!< EMAC_T::CAM5L: MACADDR0 Position */ +#define EMAC_CAM5L_MACADDR0_Msk (0xfful << EMAC_CAM5L_MACADDR0_Pos) /*!< EMAC_T::CAM5L: MACADDR0 Mask */ + +#define EMAC_CAM5L_MACADDR1_Pos (24) /*!< EMAC_T::CAM5L: MACADDR1 Position */ +#define EMAC_CAM5L_MACADDR1_Msk (0xfful << EMAC_CAM5L_MACADDR1_Pos) /*!< EMAC_T::CAM5L: MACADDR1 Mask */ + +#define EMAC_CAM6M_MACADDR2_Pos (0) /*!< EMAC_T::CAM6M: MACADDR2 Position */ +#define EMAC_CAM6M_MACADDR2_Msk (0xfful << EMAC_CAM6M_MACADDR2_Pos) /*!< EMAC_T::CAM6M: MACADDR2 Mask */ + +#define EMAC_CAM6M_MACADDR3_Pos (8) /*!< EMAC_T::CAM6M: MACADDR3 Position */ +#define EMAC_CAM6M_MACADDR3_Msk (0xfful << EMAC_CAM6M_MACADDR3_Pos) /*!< EMAC_T::CAM6M: MACADDR3 Mask */ + +#define EMAC_CAM6M_MACADDR4_Pos (16) /*!< EMAC_T::CAM6M: MACADDR4 Position */ +#define EMAC_CAM6M_MACADDR4_Msk (0xfful << EMAC_CAM6M_MACADDR4_Pos) /*!< EMAC_T::CAM6M: MACADDR4 Mask */ + +#define EMAC_CAM6M_MACADDR5_Pos (24) /*!< EMAC_T::CAM6M: MACADDR5 Position */ +#define EMAC_CAM6M_MACADDR5_Msk (0xfful << EMAC_CAM6M_MACADDR5_Pos) /*!< EMAC_T::CAM6M: MACADDR5 Mask */ + +#define EMAC_CAM6L_MACADDR0_Pos (16) /*!< EMAC_T::CAM6L: MACADDR0 Position */ +#define EMAC_CAM6L_MACADDR0_Msk (0xfful << EMAC_CAM6L_MACADDR0_Pos) /*!< EMAC_T::CAM6L: MACADDR0 Mask */ + +#define EMAC_CAM6L_MACADDR1_Pos (24) /*!< EMAC_T::CAM6L: MACADDR1 Position */ +#define EMAC_CAM6L_MACADDR1_Msk (0xfful << EMAC_CAM6L_MACADDR1_Pos) /*!< EMAC_T::CAM6L: MACADDR1 Mask */ + +#define EMAC_CAM7M_MACADDR2_Pos (0) /*!< EMAC_T::CAM7M: MACADDR2 Position */ +#define EMAC_CAM7M_MACADDR2_Msk (0xfful << EMAC_CAM7M_MACADDR2_Pos) /*!< EMAC_T::CAM7M: MACADDR2 Mask */ + +#define EMAC_CAM7M_MACADDR3_Pos (8) /*!< EMAC_T::CAM7M: MACADDR3 Position */ +#define EMAC_CAM7M_MACADDR3_Msk (0xfful << EMAC_CAM7M_MACADDR3_Pos) /*!< EMAC_T::CAM7M: MACADDR3 Mask */ + +#define EMAC_CAM7M_MACADDR4_Pos (16) /*!< EMAC_T::CAM7M: MACADDR4 Position */ +#define EMAC_CAM7M_MACADDR4_Msk (0xfful << EMAC_CAM7M_MACADDR4_Pos) /*!< EMAC_T::CAM7M: MACADDR4 Mask */ + +#define EMAC_CAM7M_MACADDR5_Pos (24) /*!< EMAC_T::CAM7M: MACADDR5 Position */ +#define EMAC_CAM7M_MACADDR5_Msk (0xfful << EMAC_CAM7M_MACADDR5_Pos) /*!< EMAC_T::CAM7M: MACADDR5 Mask */ + +#define EMAC_CAM7L_MACADDR0_Pos (16) /*!< EMAC_T::CAM7L: MACADDR0 Position */ +#define EMAC_CAM7L_MACADDR0_Msk (0xfful << EMAC_CAM7L_MACADDR0_Pos) /*!< EMAC_T::CAM7L: MACADDR0 Mask */ + +#define EMAC_CAM7L_MACADDR1_Pos (24) /*!< EMAC_T::CAM7L: MACADDR1 Position */ +#define EMAC_CAM7L_MACADDR1_Msk (0xfful << EMAC_CAM7L_MACADDR1_Pos) /*!< EMAC_T::CAM7L: MACADDR1 Mask */ + +#define EMAC_CAM8M_MACADDR2_Pos (0) /*!< EMAC_T::CAM8M: MACADDR2 Position */ +#define EMAC_CAM8M_MACADDR2_Msk (0xfful << EMAC_CAM8M_MACADDR2_Pos) /*!< EMAC_T::CAM8M: MACADDR2 Mask */ + +#define EMAC_CAM8M_MACADDR3_Pos (8) /*!< EMAC_T::CAM8M: MACADDR3 Position */ +#define EMAC_CAM8M_MACADDR3_Msk (0xfful << EMAC_CAM8M_MACADDR3_Pos) /*!< EMAC_T::CAM8M: MACADDR3 Mask */ + +#define EMAC_CAM8M_MACADDR4_Pos (16) /*!< EMAC_T::CAM8M: MACADDR4 Position */ +#define EMAC_CAM8M_MACADDR4_Msk (0xfful << EMAC_CAM8M_MACADDR4_Pos) /*!< EMAC_T::CAM8M: MACADDR4 Mask */ + +#define EMAC_CAM8M_MACADDR5_Pos (24) /*!< EMAC_T::CAM8M: MACADDR5 Position */ +#define EMAC_CAM8M_MACADDR5_Msk (0xfful << EMAC_CAM8M_MACADDR5_Pos) /*!< EMAC_T::CAM8M: MACADDR5 Mask */ + +#define EMAC_CAM8L_MACADDR0_Pos (16) /*!< EMAC_T::CAM8L: MACADDR0 Position */ +#define EMAC_CAM8L_MACADDR0_Msk (0xfful << EMAC_CAM8L_MACADDR0_Pos) /*!< EMAC_T::CAM8L: MACADDR0 Mask */ + +#define EMAC_CAM8L_MACADDR1_Pos (24) /*!< EMAC_T::CAM8L: MACADDR1 Position */ +#define EMAC_CAM8L_MACADDR1_Msk (0xfful << EMAC_CAM8L_MACADDR1_Pos) /*!< EMAC_T::CAM8L: MACADDR1 Mask */ + +#define EMAC_CAM9M_MACADDR2_Pos (0) /*!< EMAC_T::CAM9M: MACADDR2 Position */ +#define EMAC_CAM9M_MACADDR2_Msk (0xfful << EMAC_CAM9M_MACADDR2_Pos) /*!< EMAC_T::CAM9M: MACADDR2 Mask */ + +#define EMAC_CAM9M_MACADDR3_Pos (8) /*!< EMAC_T::CAM9M: MACADDR3 Position */ +#define EMAC_CAM9M_MACADDR3_Msk (0xfful << EMAC_CAM9M_MACADDR3_Pos) /*!< EMAC_T::CAM9M: MACADDR3 Mask */ + +#define EMAC_CAM9M_MACADDR4_Pos (16) /*!< EMAC_T::CAM9M: MACADDR4 Position */ +#define EMAC_CAM9M_MACADDR4_Msk (0xfful << EMAC_CAM9M_MACADDR4_Pos) /*!< EMAC_T::CAM9M: MACADDR4 Mask */ + +#define EMAC_CAM9M_MACADDR5_Pos (24) /*!< EMAC_T::CAM9M: MACADDR5 Position */ +#define EMAC_CAM9M_MACADDR5_Msk (0xfful << EMAC_CAM9M_MACADDR5_Pos) /*!< EMAC_T::CAM9M: MACADDR5 Mask */ + +#define EMAC_CAM9L_MACADDR0_Pos (16) /*!< EMAC_T::CAM9L: MACADDR0 Position */ +#define EMAC_CAM9L_MACADDR0_Msk (0xfful << EMAC_CAM9L_MACADDR0_Pos) /*!< EMAC_T::CAM9L: MACADDR0 Mask */ + +#define EMAC_CAM9L_MACADDR1_Pos (24) /*!< EMAC_T::CAM9L: MACADDR1 Position */ +#define EMAC_CAM9L_MACADDR1_Msk (0xfful << EMAC_CAM9L_MACADDR1_Pos) /*!< EMAC_T::CAM9L: MACADDR1 Mask */ + +#define EMAC_CAM10M_MACADDR2_Pos (0) /*!< EMAC_T::CAM10M: MACADDR2 Position */ +#define EMAC_CAM10M_MACADDR2_Msk (0xfful << EMAC_CAM10M_MACADDR2_Pos) /*!< EMAC_T::CAM10M: MACADDR2 Mask */ + +#define EMAC_CAM10M_MACADDR3_Pos (8) /*!< EMAC_T::CAM10M: MACADDR3 Position */ +#define EMAC_CAM10M_MACADDR3_Msk (0xfful << EMAC_CAM10M_MACADDR3_Pos) /*!< EMAC_T::CAM10M: MACADDR3 Mask */ + +#define EMAC_CAM10M_MACADDR4_Pos (16) /*!< EMAC_T::CAM10M: MACADDR4 Position */ +#define EMAC_CAM10M_MACADDR4_Msk (0xfful << EMAC_CAM10M_MACADDR4_Pos) /*!< EMAC_T::CAM10M: MACADDR4 Mask */ + +#define EMAC_CAM10M_MACADDR5_Pos (24) /*!< EMAC_T::CAM10M: MACADDR5 Position */ +#define EMAC_CAM10M_MACADDR5_Msk (0xfful << EMAC_CAM10M_MACADDR5_Pos) /*!< EMAC_T::CAM10M: MACADDR5 Mask */ + +#define EMAC_CAM10L_MACADDR0_Pos (16) /*!< EMAC_T::CAM10L: MACADDR0 Position */ +#define EMAC_CAM10L_MACADDR0_Msk (0xfful << EMAC_CAM10L_MACADDR0_Pos) /*!< EMAC_T::CAM10L: MACADDR0 Mask */ + +#define EMAC_CAM10L_MACADDR1_Pos (24) /*!< EMAC_T::CAM10L: MACADDR1 Position */ +#define EMAC_CAM10L_MACADDR1_Msk (0xfful << EMAC_CAM10L_MACADDR1_Pos) /*!< EMAC_T::CAM10L: MACADDR1 Mask */ + +#define EMAC_CAM11M_MACADDR2_Pos (0) /*!< EMAC_T::CAM11M: MACADDR2 Position */ +#define EMAC_CAM11M_MACADDR2_Msk (0xfful << EMAC_CAM11M_MACADDR2_Pos) /*!< EMAC_T::CAM11M: MACADDR2 Mask */ + +#define EMAC_CAM11M_MACADDR3_Pos (8) /*!< EMAC_T::CAM11M: MACADDR3 Position */ +#define EMAC_CAM11M_MACADDR3_Msk (0xfful << EMAC_CAM11M_MACADDR3_Pos) /*!< EMAC_T::CAM11M: MACADDR3 Mask */ + +#define EMAC_CAM11M_MACADDR4_Pos (16) /*!< EMAC_T::CAM11M: MACADDR4 Position */ +#define EMAC_CAM11M_MACADDR4_Msk (0xfful << EMAC_CAM11M_MACADDR4_Pos) /*!< EMAC_T::CAM11M: MACADDR4 Mask */ + +#define EMAC_CAM11M_MACADDR5_Pos (24) /*!< EMAC_T::CAM11M: MACADDR5 Position */ +#define EMAC_CAM11M_MACADDR5_Msk (0xfful << EMAC_CAM11M_MACADDR5_Pos) /*!< EMAC_T::CAM11M: MACADDR5 Mask */ + +#define EMAC_CAM11L_MACADDR0_Pos (16) /*!< EMAC_T::CAM11L: MACADDR0 Position */ +#define EMAC_CAM11L_MACADDR0_Msk (0xfful << EMAC_CAM11L_MACADDR0_Pos) /*!< EMAC_T::CAM11L: MACADDR0 Mask */ + +#define EMAC_CAM11L_MACADDR1_Pos (24) /*!< EMAC_T::CAM11L: MACADDR1 Position */ +#define EMAC_CAM11L_MACADDR1_Msk (0xfful << EMAC_CAM11L_MACADDR1_Pos) /*!< EMAC_T::CAM11L: MACADDR1 Mask */ + +#define EMAC_CAM12M_MACADDR2_Pos (0) /*!< EMAC_T::CAM12M: MACADDR2 Position */ +#define EMAC_CAM12M_MACADDR2_Msk (0xfful << EMAC_CAM12M_MACADDR2_Pos) /*!< EMAC_T::CAM12M: MACADDR2 Mask */ + +#define EMAC_CAM12M_MACADDR3_Pos (8) /*!< EMAC_T::CAM12M: MACADDR3 Position */ +#define EMAC_CAM12M_MACADDR3_Msk (0xfful << EMAC_CAM12M_MACADDR3_Pos) /*!< EMAC_T::CAM12M: MACADDR3 Mask */ + +#define EMAC_CAM12M_MACADDR4_Pos (16) /*!< EMAC_T::CAM12M: MACADDR4 Position */ +#define EMAC_CAM12M_MACADDR4_Msk (0xfful << EMAC_CAM12M_MACADDR4_Pos) /*!< EMAC_T::CAM12M: MACADDR4 Mask */ + +#define EMAC_CAM12M_MACADDR5_Pos (24) /*!< EMAC_T::CAM12M: MACADDR5 Position */ +#define EMAC_CAM12M_MACADDR5_Msk (0xfful << EMAC_CAM12M_MACADDR5_Pos) /*!< EMAC_T::CAM12M: MACADDR5 Mask */ + +#define EMAC_CAM12L_MACADDR0_Pos (16) /*!< EMAC_T::CAM12L: MACADDR0 Position */ +#define EMAC_CAM12L_MACADDR0_Msk (0xfful << EMAC_CAM12L_MACADDR0_Pos) /*!< EMAC_T::CAM12L: MACADDR0 Mask */ + +#define EMAC_CAM12L_MACADDR1_Pos (24) /*!< EMAC_T::CAM12L: MACADDR1 Position */ +#define EMAC_CAM12L_MACADDR1_Msk (0xfful << EMAC_CAM12L_MACADDR1_Pos) /*!< EMAC_T::CAM12L: MACADDR1 Mask */ + +#define EMAC_CAM13M_MACADDR2_Pos (0) /*!< EMAC_T::CAM13M: MACADDR2 Position */ +#define EMAC_CAM13M_MACADDR2_Msk (0xfful << EMAC_CAM13M_MACADDR2_Pos) /*!< EMAC_T::CAM13M: MACADDR2 Mask */ + +#define EMAC_CAM13M_MACADDR3_Pos (8) /*!< EMAC_T::CAM13M: MACADDR3 Position */ +#define EMAC_CAM13M_MACADDR3_Msk (0xfful << EMAC_CAM13M_MACADDR3_Pos) /*!< EMAC_T::CAM13M: MACADDR3 Mask */ + +#define EMAC_CAM13M_MACADDR4_Pos (16) /*!< EMAC_T::CAM13M: MACADDR4 Position */ +#define EMAC_CAM13M_MACADDR4_Msk (0xfful << EMAC_CAM13M_MACADDR4_Pos) /*!< EMAC_T::CAM13M: MACADDR4 Mask */ + +#define EMAC_CAM13M_MACADDR5_Pos (24) /*!< EMAC_T::CAM13M: MACADDR5 Position */ +#define EMAC_CAM13M_MACADDR5_Msk (0xfful << EMAC_CAM13M_MACADDR5_Pos) /*!< EMAC_T::CAM13M: MACADDR5 Mask */ + +#define EMAC_CAM13L_MACADDR0_Pos (16) /*!< EMAC_T::CAM13L: MACADDR0 Position */ +#define EMAC_CAM13L_MACADDR0_Msk (0xfful << EMAC_CAM13L_MACADDR0_Pos) /*!< EMAC_T::CAM13L: MACADDR0 Mask */ + +#define EMAC_CAM13L_MACADDR1_Pos (24) /*!< EMAC_T::CAM13L: MACADDR1 Position */ +#define EMAC_CAM13L_MACADDR1_Msk (0xfful << EMAC_CAM13L_MACADDR1_Pos) /*!< EMAC_T::CAM13L: MACADDR1 Mask */ + +#define EMAC_CAM14M_MACADDR2_Pos (0) /*!< EMAC_T::CAM14M: MACADDR2 Position */ +#define EMAC_CAM14M_MACADDR2_Msk (0xfful << EMAC_CAM14M_MACADDR2_Pos) /*!< EMAC_T::CAM14M: MACADDR2 Mask */ + +#define EMAC_CAM14M_MACADDR3_Pos (8) /*!< EMAC_T::CAM14M: MACADDR3 Position */ +#define EMAC_CAM14M_MACADDR3_Msk (0xfful << EMAC_CAM14M_MACADDR3_Pos) /*!< EMAC_T::CAM14M: MACADDR3 Mask */ + +#define EMAC_CAM14M_MACADDR4_Pos (16) /*!< EMAC_T::CAM14M: MACADDR4 Position */ +#define EMAC_CAM14M_MACADDR4_Msk (0xfful << EMAC_CAM14M_MACADDR4_Pos) /*!< EMAC_T::CAM14M: MACADDR4 Mask */ + +#define EMAC_CAM14M_MACADDR5_Pos (24) /*!< EMAC_T::CAM14M: MACADDR5 Position */ +#define EMAC_CAM14M_MACADDR5_Msk (0xfful << EMAC_CAM14M_MACADDR5_Pos) /*!< EMAC_T::CAM14M: MACADDR5 Mask */ + +#define EMAC_CAM14L_MACADDR0_Pos (16) /*!< EMAC_T::CAM14L: MACADDR0 Position */ +#define EMAC_CAM14L_MACADDR0_Msk (0xfful << EMAC_CAM14L_MACADDR0_Pos) /*!< EMAC_T::CAM14L: MACADDR0 Mask */ + +#define EMAC_CAM14L_MACADDR1_Pos (24) /*!< EMAC_T::CAM14L: MACADDR1 Position */ +#define EMAC_CAM14L_MACADDR1_Msk (0xfful << EMAC_CAM14L_MACADDR1_Pos) /*!< EMAC_T::CAM14L: MACADDR1 Mask */ + +#define EMAC_CAM15MSB_OPCODE_Pos (0) /*!< EMAC_T::CAM15MSB: OPCODE Position */ +#define EMAC_CAM15MSB_OPCODE_Msk (0xfffful << EMAC_CAM15MSB_OPCODE_Pos) /*!< EMAC_T::CAM15MSB: OPCODE Mask */ + +#define EMAC_CAM15MSB_LENGTH_Pos (16) /*!< EMAC_T::CAM15MSB: LENGTH Position */ +#define EMAC_CAM15MSB_LENGTH_Msk (0xfffful << EMAC_CAM15MSB_LENGTH_Pos) /*!< EMAC_T::CAM15MSB: LENGTH Mask */ + +#define EMAC_CAM15LSB_OPERAND_Pos (24) /*!< EMAC_T::CAM15LSB: OPERAND Position */ +#define EMAC_CAM15LSB_OPERAND_Msk (0xfful << EMAC_CAM15LSB_OPERAND_Pos) /*!< EMAC_T::CAM15LSB: OPERAND Mask */ + +#define EMAC_TXDSA_TXDSA_Pos (0) /*!< EMAC_T::TXDSA: TXDSA Position */ +#define EMAC_TXDSA_TXDSA_Msk (0xfffffffful << EMAC_TXDSA_TXDSA_Pos) /*!< EMAC_T::TXDSA: TXDSA Mask */ + +#define EMAC_RXDSA_RXDSA_Pos (0) /*!< EMAC_T::RXDSA: RXDSA Position */ +#define EMAC_RXDSA_RXDSA_Msk (0xfffffffful << EMAC_RXDSA_RXDSA_Pos) /*!< EMAC_T::RXDSA: RXDSA Mask */ + +#define EMAC_CTL_RXON_Pos (0) /*!< EMAC_T::CTL: RXON Position */ +#define EMAC_CTL_RXON_Msk (0x1ul << EMAC_CTL_RXON_Pos) /*!< EMAC_T::CTL: RXON Mask */ + +#define EMAC_CTL_ALP_Pos (1) /*!< EMAC_T::CTL: ALP Position */ +#define EMAC_CTL_ALP_Msk (0x1ul << EMAC_CTL_ALP_Pos) /*!< EMAC_T::CTL: ALP Mask */ + +#define EMAC_CTL_ARP_Pos (2) /*!< EMAC_T::CTL: ARP Position */ +#define EMAC_CTL_ARP_Msk (0x1ul << EMAC_CTL_ARP_Pos) /*!< EMAC_T::CTL: ARP Mask */ + +#define EMAC_CTL_ACP_Pos (3) /*!< EMAC_T::CTL: ACP Position */ +#define EMAC_CTL_ACP_Msk (0x1ul << EMAC_CTL_ACP_Pos) /*!< EMAC_T::CTL: ACP Mask */ + +#define EMAC_CTL_AEP_Pos (4) /*!< EMAC_T::CTL: AEP Position */ +#define EMAC_CTL_AEP_Msk (0x1ul << EMAC_CTL_AEP_Pos) /*!< EMAC_T::CTL: AEP Mask */ + +#define EMAC_CTL_STRIPCRC_Pos (5) /*!< EMAC_T::CTL: STRIPCRC Position */ +#define EMAC_CTL_STRIPCRC_Msk (0x1ul << EMAC_CTL_STRIPCRC_Pos) /*!< EMAC_T::CTL: STRIPCRC Mask */ + +#define EMAC_CTL_WOLEN_Pos (6) /*!< EMAC_T::CTL: WOLEN Position */ +#define EMAC_CTL_WOLEN_Msk (0x1ul << EMAC_CTL_WOLEN_Pos) /*!< EMAC_T::CTL: WOLEN Mask */ + +#define EMAC_CTL_TXON_Pos (8) /*!< EMAC_T::CTL: TXON Position */ +#define EMAC_CTL_TXON_Msk (0x1ul << EMAC_CTL_TXON_Pos) /*!< EMAC_T::CTL: TXON Mask */ + +#define EMAC_CTL_NODEF_Pos (9) /*!< EMAC_T::CTL: NODEF Position */ +#define EMAC_CTL_NODEF_Msk (0x1ul << EMAC_CTL_NODEF_Pos) /*!< EMAC_T::CTL: NODEF Mask */ + +#define EMAC_CTL_SDPZ_Pos (16) /*!< EMAC_T::CTL: SDPZ Position */ +#define EMAC_CTL_SDPZ_Msk (0x1ul << EMAC_CTL_SDPZ_Pos) /*!< EMAC_T::CTL: SDPZ Mask */ + +#define EMAC_CTL_SQECHKEN_Pos (17) /*!< EMAC_T::CTL: SQECHKEN Position */ +#define EMAC_CTL_SQECHKEN_Msk (0x1ul << EMAC_CTL_SQECHKEN_Pos) /*!< EMAC_T::CTL: SQECHKEN Mask */ + +#define EMAC_CTL_FUDUP_Pos (18) /*!< EMAC_T::CTL: FUDUP Position */ +#define EMAC_CTL_FUDUP_Msk (0x1ul << EMAC_CTL_FUDUP_Pos) /*!< EMAC_T::CTL: FUDUP Mask */ + +#define EMAC_CTL_RMIIRXCTL_Pos (19) /*!< EMAC_T::CTL: RMIIRXCTL Position */ +#define EMAC_CTL_RMIIRXCTL_Msk (0x1ul << EMAC_CTL_RMIIRXCTL_Pos) /*!< EMAC_T::CTL: RMIIRXCTL Mask */ + +#define EMAC_CTL_OPMODE_Pos (20) /*!< EMAC_T::CTL: OPMODE Position */ +#define EMAC_CTL_OPMODE_Msk (0x1ul << EMAC_CTL_OPMODE_Pos) /*!< EMAC_T::CTL: OPMODE Mask */ + +#define EMAC_CTL_RMIIEN_Pos (22) /*!< EMAC_T::CTL: RMIIEN Position */ +#define EMAC_CTL_RMIIEN_Msk (0x1ul << EMAC_CTL_RMIIEN_Pos) /*!< EMAC_T::CTL: RMIIEN Mask */ + +#define EMAC_CTL_RST_Pos (24) /*!< EMAC_T::CTL: RST Position */ +#define EMAC_CTL_RST_Msk (0x1ul << EMAC_CTL_RST_Pos) /*!< EMAC_T::CTL: RST Mask */ + +#define EMAC_MIIMDAT_DATA_Pos (0) /*!< EMAC_T::MIIMDAT: DATA Position */ +#define EMAC_MIIMDAT_DATA_Msk (0xfffful << EMAC_MIIMDAT_DATA_Pos) /*!< EMAC_T::MIIMDAT: DATA Mask */ + +#define EMAC_MIIMCTL_PHYREG_Pos (0) /*!< EMAC_T::MIIMCTL: PHYREG Position */ +#define EMAC_MIIMCTL_PHYREG_Msk (0x1ful << EMAC_MIIMCTL_PHYREG_Pos) /*!< EMAC_T::MIIMCTL: PHYREG Mask */ + +#define EMAC_MIIMCTL_PHYADDR_Pos (8) /*!< EMAC_T::MIIMCTL: PHYADDR Position */ +#define EMAC_MIIMCTL_PHYADDR_Msk (0x1ful << EMAC_MIIMCTL_PHYADDR_Pos) /*!< EMAC_T::MIIMCTL: PHYADDR Mask */ + +#define EMAC_MIIMCTL_WRITE_Pos (16) /*!< EMAC_T::MIIMCTL: WRITE Position */ +#define EMAC_MIIMCTL_WRITE_Msk (0x1ul << EMAC_MIIMCTL_WRITE_Pos) /*!< EMAC_T::MIIMCTL: WRITE Mask */ + +#define EMAC_MIIMCTL_BUSY_Pos (17) /*!< EMAC_T::MIIMCTL: BUSY Position */ +#define EMAC_MIIMCTL_BUSY_Msk (0x1ul << EMAC_MIIMCTL_BUSY_Pos) /*!< EMAC_T::MIIMCTL: BUSY Mask */ + +#define EMAC_MIIMCTL_PREAMSP_Pos (18) /*!< EMAC_T::MIIMCTL: PREAMSP Position */ +#define EMAC_MIIMCTL_PREAMSP_Msk (0x1ul << EMAC_MIIMCTL_PREAMSP_Pos) /*!< EMAC_T::MIIMCTL: PREAMSP Mask */ + +#define EMAC_MIIMCTL_MDCON_Pos (19) /*!< EMAC_T::MIIMCTL: MDCON Position */ +#define EMAC_MIIMCTL_MDCON_Msk (0x1ul << EMAC_MIIMCTL_MDCON_Pos) /*!< EMAC_T::MIIMCTL: MDCON Mask */ + +#define EMAC_FIFOCTL_RXFIFOTH_Pos (0) /*!< EMAC_T::FIFOCTL: RXFIFOTH Position */ +#define EMAC_FIFOCTL_RXFIFOTH_Msk (0x3ul << EMAC_FIFOCTL_RXFIFOTH_Pos) /*!< EMAC_T::FIFOCTL: RXFIFOTH Mask */ + +#define EMAC_FIFOCTL_TXFIFOTH_Pos (8) /*!< EMAC_T::FIFOCTL: TXFIFOTH Position */ +#define EMAC_FIFOCTL_TXFIFOTH_Msk (0x3ul << EMAC_FIFOCTL_TXFIFOTH_Pos) /*!< EMAC_T::FIFOCTL: TXFIFOTH Mask */ + +#define EMAC_FIFOCTL_BURSTLEN_Pos (20) /*!< EMAC_T::FIFOCTL: BURSTLEN Position */ +#define EMAC_FIFOCTL_BURSTLEN_Msk (0x3ul << EMAC_FIFOCTL_BURSTLEN_Pos) /*!< EMAC_T::FIFOCTL: BURSTLEN Mask */ + +#define EMAC_TXST_TXST_Pos (0) /*!< EMAC_T::TXST: TXST Position */ +#define EMAC_TXST_TXST_Msk (0xfffffffful << EMAC_TXST_TXST_Pos) /*!< EMAC_T::TXST: TXST Mask */ + +#define EMAC_RXST_RXST_Pos (0) /*!< EMAC_T::RXST: RXST Position */ +#define EMAC_RXST_RXST_Msk (0xfffffffful << EMAC_RXST_RXST_Pos) /*!< EMAC_T::RXST: RXST Mask */ + +#define EMAC_MRFL_MRFL_Pos (0) /*!< EMAC_T::MRFL: MRFL Position */ +#define EMAC_MRFL_MRFL_Msk (0xfffful << EMAC_MRFL_MRFL_Pos) /*!< EMAC_T::MRFL: MRFL Mask */ + +#define EMAC_INTEN_RXIEN_Pos (0) /*!< EMAC_T::INTEN: RXIEN Position */ +#define EMAC_INTEN_RXIEN_Msk (0x1ul << EMAC_INTEN_RXIEN_Pos) /*!< EMAC_T::INTEN: RXIEN Mask */ + +#define EMAC_INTEN_CRCEIEN_Pos (1) /*!< EMAC_T::INTEN: CRCEIEN Position */ +#define EMAC_INTEN_CRCEIEN_Msk (0x1ul << EMAC_INTEN_CRCEIEN_Pos) /*!< EMAC_T::INTEN: CRCEIEN Mask */ + +#define EMAC_INTEN_RXOVIEN_Pos (2) /*!< EMAC_T::INTEN: RXOVIEN Position */ +#define EMAC_INTEN_RXOVIEN_Msk (0x1ul << EMAC_INTEN_RXOVIEN_Pos) /*!< EMAC_T::INTEN: RXOVIEN Mask */ + +#define EMAC_INTEN_LPIEN_Pos (3) /*!< EMAC_T::INTEN: LPIEN Position */ +#define EMAC_INTEN_LPIEN_Msk (0x1ul << EMAC_INTEN_LPIEN_Pos) /*!< EMAC_T::INTEN: LPIEN Mask */ + +#define EMAC_INTEN_RXGDIEN_Pos (4) /*!< EMAC_T::INTEN: RXGDIEN Position */ +#define EMAC_INTEN_RXGDIEN_Msk (0x1ul << EMAC_INTEN_RXGDIEN_Pos) /*!< EMAC_T::INTEN: RXGDIEN Mask */ + +#define EMAC_INTEN_ALIEIEN_Pos (5) /*!< EMAC_T::INTEN: ALIEIEN Position */ +#define EMAC_INTEN_ALIEIEN_Msk (0x1ul << EMAC_INTEN_ALIEIEN_Pos) /*!< EMAC_T::INTEN: ALIEIEN Mask */ + +#define EMAC_INTEN_RPIEN_Pos (6) /*!< EMAC_T::INTEN: RPIEN Position */ +#define EMAC_INTEN_RPIEN_Msk (0x1ul << EMAC_INTEN_RPIEN_Pos) /*!< EMAC_T::INTEN: RPIEN Mask */ + +#define EMAC_INTEN_MPCOVIEN_Pos (7) /*!< EMAC_T::INTEN: MPCOVIEN Position */ +#define EMAC_INTEN_MPCOVIEN_Msk (0x1ul << EMAC_INTEN_MPCOVIEN_Pos) /*!< EMAC_T::INTEN: MPCOVIEN Mask */ + +#define EMAC_INTEN_MFLEIEN_Pos (8) /*!< EMAC_T::INTEN: MFLEIEN Position */ +#define EMAC_INTEN_MFLEIEN_Msk (0x1ul << EMAC_INTEN_MFLEIEN_Pos) /*!< EMAC_T::INTEN: MFLEIEN Mask */ + +#define EMAC_INTEN_DENIEN_Pos (9) /*!< EMAC_T::INTEN: DENIEN Position */ +#define EMAC_INTEN_DENIEN_Msk (0x1ul << EMAC_INTEN_DENIEN_Pos) /*!< EMAC_T::INTEN: DENIEN Mask */ + +#define EMAC_INTEN_RDUIEN_Pos (10) /*!< EMAC_T::INTEN: RDUIEN Position */ +#define EMAC_INTEN_RDUIEN_Msk (0x1ul << EMAC_INTEN_RDUIEN_Pos) /*!< EMAC_T::INTEN: RDUIEN Mask */ + +#define EMAC_INTEN_RXBEIEN_Pos (11) /*!< EMAC_T::INTEN: RXBEIEN Position */ +#define EMAC_INTEN_RXBEIEN_Msk (0x1ul << EMAC_INTEN_RXBEIEN_Pos) /*!< EMAC_T::INTEN: RXBEIEN Mask */ + +#define EMAC_INTEN_CFRIEN_Pos (14) /*!< EMAC_T::INTEN: CFRIEN Position */ +#define EMAC_INTEN_CFRIEN_Msk (0x1ul << EMAC_INTEN_CFRIEN_Pos) /*!< EMAC_T::INTEN: CFRIEN Mask */ + +#define EMAC_INTEN_WOLIEN_Pos (15) /*!< EMAC_T::INTEN: WOLIEN Position */ +#define EMAC_INTEN_WOLIEN_Msk (0x1ul << EMAC_INTEN_WOLIEN_Pos) /*!< EMAC_T::INTEN: WOLIEN Mask */ + +#define EMAC_INTEN_TXIEN_Pos (16) /*!< EMAC_T::INTEN: TXIEN Position */ +#define EMAC_INTEN_TXIEN_Msk (0x1ul << EMAC_INTEN_TXIEN_Pos) /*!< EMAC_T::INTEN: TXIEN Mask */ + +#define EMAC_INTEN_TXUDIEN_Pos (17) /*!< EMAC_T::INTEN: TXUDIEN Position */ +#define EMAC_INTEN_TXUDIEN_Msk (0x1ul << EMAC_INTEN_TXUDIEN_Pos) /*!< EMAC_T::INTEN: TXUDIEN Mask */ + +#define EMAC_INTEN_TXCPIEN_Pos (18) /*!< EMAC_T::INTEN: TXCPIEN Position */ +#define EMAC_INTEN_TXCPIEN_Msk (0x1ul << EMAC_INTEN_TXCPIEN_Pos) /*!< EMAC_T::INTEN: TXCPIEN Mask */ + +#define EMAC_INTEN_EXDEFIEN_Pos (19) /*!< EMAC_T::INTEN: EXDEFIEN Position */ +#define EMAC_INTEN_EXDEFIEN_Msk (0x1ul << EMAC_INTEN_EXDEFIEN_Pos) /*!< EMAC_T::INTEN: EXDEFIEN Mask */ + +#define EMAC_INTEN_NCSIEN_Pos (20) /*!< EMAC_T::INTEN: NCSIEN Position */ +#define EMAC_INTEN_NCSIEN_Msk (0x1ul << EMAC_INTEN_NCSIEN_Pos) /*!< EMAC_T::INTEN: NCSIEN Mask */ + +#define EMAC_INTEN_TXABTIEN_Pos (21) /*!< EMAC_T::INTEN: TXABTIEN Position */ +#define EMAC_INTEN_TXABTIEN_Msk (0x1ul << EMAC_INTEN_TXABTIEN_Pos) /*!< EMAC_T::INTEN: TXABTIEN Mask */ + +#define EMAC_INTEN_LCIEN_Pos (22) /*!< EMAC_T::INTEN: LCIEN Position */ +#define EMAC_INTEN_LCIEN_Msk (0x1ul << EMAC_INTEN_LCIEN_Pos) /*!< EMAC_T::INTEN: LCIEN Mask */ + +#define EMAC_INTEN_TDUIEN_Pos (23) /*!< EMAC_T::INTEN: TDUIEN Position */ +#define EMAC_INTEN_TDUIEN_Msk (0x1ul << EMAC_INTEN_TDUIEN_Pos) /*!< EMAC_T::INTEN: TDUIEN Mask */ + +#define EMAC_INTEN_TXBEIEN_Pos (24) /*!< EMAC_T::INTEN: TXBEIEN Position */ +#define EMAC_INTEN_TXBEIEN_Msk (0x1ul << EMAC_INTEN_TXBEIEN_Pos) /*!< EMAC_T::INTEN: TXBEIEN Mask */ + +#define EMAC_INTEN_TSALMIEN_Pos (28) /*!< EMAC_T::INTEN: TSALMIEN Position */ +#define EMAC_INTEN_TSALMIEN_Msk (0x1ul << EMAC_INTEN_TSALMIEN_Pos) /*!< EMAC_T::INTEN: TSALMIEN Mask */ + +#define EMAC_INTSTS_RXIF_Pos (0) /*!< EMAC_T::INTSTS: RXIF Position */ +#define EMAC_INTSTS_RXIF_Msk (0x1ul << EMAC_INTSTS_RXIF_Pos) /*!< EMAC_T::INTSTS: RXIF Mask */ + +#define EMAC_INTSTS_CRCEIF_Pos (1) /*!< EMAC_T::INTSTS: CRCEIF Position */ +#define EMAC_INTSTS_CRCEIF_Msk (0x1ul << EMAC_INTSTS_CRCEIF_Pos) /*!< EMAC_T::INTSTS: CRCEIF Mask */ + +#define EMAC_INTSTS_RXOVIF_Pos (2) /*!< EMAC_T::INTSTS: RXOVIF Position */ +#define EMAC_INTSTS_RXOVIF_Msk (0x1ul << EMAC_INTSTS_RXOVIF_Pos) /*!< EMAC_T::INTSTS: RXOVIF Mask */ + +#define EMAC_INTSTS_LPIF_Pos (3) /*!< EMAC_T::INTSTS: LPIF Position */ +#define EMAC_INTSTS_LPIF_Msk (0x1ul << EMAC_INTSTS_LPIF_Pos) /*!< EMAC_T::INTSTS: LPIF Mask */ + +#define EMAC_INTSTS_RXGDIF_Pos (4) /*!< EMAC_T::INTSTS: RXGDIF Position */ +#define EMAC_INTSTS_RXGDIF_Msk (0x1ul << EMAC_INTSTS_RXGDIF_Pos) /*!< EMAC_T::INTSTS: RXGDIF Mask */ + +#define EMAC_INTSTS_ALIEIF_Pos (5) /*!< EMAC_T::INTSTS: ALIEIF Position */ +#define EMAC_INTSTS_ALIEIF_Msk (0x1ul << EMAC_INTSTS_ALIEIF_Pos) /*!< EMAC_T::INTSTS: ALIEIF Mask */ + +#define EMAC_INTSTS_RPIF_Pos (6) /*!< EMAC_T::INTSTS: RPIF Position */ +#define EMAC_INTSTS_RPIF_Msk (0x1ul << EMAC_INTSTS_RPIF_Pos) /*!< EMAC_T::INTSTS: RPIF Mask */ + +#define EMAC_INTSTS_MPCOVIF_Pos (7) /*!< EMAC_T::INTSTS: MPCOVIF Position */ +#define EMAC_INTSTS_MPCOVIF_Msk (0x1ul << EMAC_INTSTS_MPCOVIF_Pos) /*!< EMAC_T::INTSTS: MPCOVIF Mask */ + +#define EMAC_INTSTS_MFLEIF_Pos (8) /*!< EMAC_T::INTSTS: MFLEIF Position */ +#define EMAC_INTSTS_MFLEIF_Msk (0x1ul << EMAC_INTSTS_MFLEIF_Pos) /*!< EMAC_T::INTSTS: MFLEIF Mask */ + +#define EMAC_INTSTS_DENIF_Pos (9) /*!< EMAC_T::INTSTS: DENIF Position */ +#define EMAC_INTSTS_DENIF_Msk (0x1ul << EMAC_INTSTS_DENIF_Pos) /*!< EMAC_T::INTSTS: DENIF Mask */ + +#define EMAC_INTSTS_RDUIF_Pos (10) /*!< EMAC_T::INTSTS: RDUIF Position */ +#define EMAC_INTSTS_RDUIF_Msk (0x1ul << EMAC_INTSTS_RDUIF_Pos) /*!< EMAC_T::INTSTS: RDUIF Mask */ + +#define EMAC_INTSTS_RXBEIF_Pos (11) /*!< EMAC_T::INTSTS: RXBEIF Position */ +#define EMAC_INTSTS_RXBEIF_Msk (0x1ul << EMAC_INTSTS_RXBEIF_Pos) /*!< EMAC_T::INTSTS: RXBEIF Mask */ + +#define EMAC_INTSTS_CFRIF_Pos (14) /*!< EMAC_T::INTSTS: CFRIF Position */ +#define EMAC_INTSTS_CFRIF_Msk (0x1ul << EMAC_INTSTS_CFRIF_Pos) /*!< EMAC_T::INTSTS: CFRIF Mask */ + +#define EMAC_INTSTS_WOLIF_Pos (15) /*!< EMAC_T::INTSTS: WOLIF Position */ +#define EMAC_INTSTS_WOLIF_Msk (0x1ul << EMAC_INTSTS_WOLIF_Pos) /*!< EMAC_T::INTSTS: WOLIF Mask */ + +#define EMAC_INTSTS_TXIF_Pos (16) /*!< EMAC_T::INTSTS: TXIF Position */ +#define EMAC_INTSTS_TXIF_Msk (0x1ul << EMAC_INTSTS_TXIF_Pos) /*!< EMAC_T::INTSTS: TXIF Mask */ + +#define EMAC_INTSTS_TXUDIF_Pos (17) /*!< EMAC_T::INTSTS: TXUDIF Position */ +#define EMAC_INTSTS_TXUDIF_Msk (0x1ul << EMAC_INTSTS_TXUDIF_Pos) /*!< EMAC_T::INTSTS: TXUDIF Mask */ + +#define EMAC_INTSTS_TXCPIF_Pos (18) /*!< EMAC_T::INTSTS: TXCPIF Position */ +#define EMAC_INTSTS_TXCPIF_Msk (0x1ul << EMAC_INTSTS_TXCPIF_Pos) /*!< EMAC_T::INTSTS: TXCPIF Mask */ + +#define EMAC_INTSTS_EXDEFIF_Pos (19) /*!< EMAC_T::INTSTS: EXDEFIF Position */ +#define EMAC_INTSTS_EXDEFIF_Msk (0x1ul << EMAC_INTSTS_EXDEFIF_Pos) /*!< EMAC_T::INTSTS: EXDEFIF Mask */ + +#define EMAC_INTSTS_NCSIF_Pos (20) /*!< EMAC_T::INTSTS: NCSIF Position */ +#define EMAC_INTSTS_NCSIF_Msk (0x1ul << EMAC_INTSTS_NCSIF_Pos) /*!< EMAC_T::INTSTS: NCSIF Mask */ + +#define EMAC_INTSTS_TXABTIF_Pos (21) /*!< EMAC_T::INTSTS: TXABTIF Position */ +#define EMAC_INTSTS_TXABTIF_Msk (0x1ul << EMAC_INTSTS_TXABTIF_Pos) /*!< EMAC_T::INTSTS: TXABTIF Mask */ + +#define EMAC_INTSTS_LCIF_Pos (22) /*!< EMAC_T::INTSTS: LCIF Position */ +#define EMAC_INTSTS_LCIF_Msk (0x1ul << EMAC_INTSTS_LCIF_Pos) /*!< EMAC_T::INTSTS: LCIF Mask */ + +#define EMAC_INTSTS_TDUIF_Pos (23) /*!< EMAC_T::INTSTS: TDUIF Position */ +#define EMAC_INTSTS_TDUIF_Msk (0x1ul << EMAC_INTSTS_TDUIF_Pos) /*!< EMAC_T::INTSTS: TDUIF Mask */ + +#define EMAC_INTSTS_TXBEIF_Pos (24) /*!< EMAC_T::INTSTS: TXBEIF Position */ +#define EMAC_INTSTS_TXBEIF_Msk (0x1ul << EMAC_INTSTS_TXBEIF_Pos) /*!< EMAC_T::INTSTS: TXBEIF Mask */ + +#define EMAC_INTSTS_TSALMIF_Pos (28) /*!< EMAC_T::INTSTS: TSALMIF Position */ +#define EMAC_INTSTS_TSALMIF_Msk (0x1ul << EMAC_INTSTS_TSALMIF_Pos) /*!< EMAC_T::INTSTS: TSALMIF Mask */ + +#define EMAC_GENSTS_CFR_Pos (0) /*!< EMAC_T::GENSTS: CFR Position */ +#define EMAC_GENSTS_CFR_Msk (0x1ul << EMAC_GENSTS_CFR_Pos) /*!< EMAC_T::GENSTS: CFR Mask */ + +#define EMAC_GENSTS_RXHALT_Pos (1) /*!< EMAC_T::GENSTS: RXHALT Position */ +#define EMAC_GENSTS_RXHALT_Msk (0x1ul << EMAC_GENSTS_RXHALT_Pos) /*!< EMAC_T::GENSTS: RXHALT Mask */ + +#define EMAC_GENSTS_RXFFULL_Pos (2) /*!< EMAC_T::GENSTS: RXFFULL Position */ +#define EMAC_GENSTS_RXFFULL_Msk (0x1ul << EMAC_GENSTS_RXFFULL_Pos) /*!< EMAC_T::GENSTS: RXFFULL Mask */ + +#define EMAC_GENSTS_COLCNT_Pos (4) /*!< EMAC_T::GENSTS: COLCNT Position */ +#define EMAC_GENSTS_COLCNT_Msk (0xful << EMAC_GENSTS_COLCNT_Pos) /*!< EMAC_T::GENSTS: COLCNT Mask */ + +#define EMAC_GENSTS_DEF_Pos (8) /*!< EMAC_T::GENSTS: DEF Position */ +#define EMAC_GENSTS_DEF_Msk (0x1ul << EMAC_GENSTS_DEF_Pos) /*!< EMAC_T::GENSTS: DEF Mask */ + +#define EMAC_GENSTS_TXPAUSED_Pos (9) /*!< EMAC_T::GENSTS: TXPAUSED Position */ +#define EMAC_GENSTS_TXPAUSED_Msk (0x1ul << EMAC_GENSTS_TXPAUSED_Pos) /*!< EMAC_T::GENSTS: TXPAUSED Mask */ + +#define EMAC_GENSTS_SQE_Pos (10) /*!< EMAC_T::GENSTS: SQE Position */ +#define EMAC_GENSTS_SQE_Msk (0x1ul << EMAC_GENSTS_SQE_Pos) /*!< EMAC_T::GENSTS: SQE Mask */ + +#define EMAC_GENSTS_TXHALT_Pos (11) /*!< EMAC_T::GENSTS: TXHALT Position */ +#define EMAC_GENSTS_TXHALT_Msk (0x1ul << EMAC_GENSTS_TXHALT_Pos) /*!< EMAC_T::GENSTS: TXHALT Mask */ + +#define EMAC_GENSTS_RPSTS_Pos (12) /*!< EMAC_T::GENSTS: RPSTS Position */ +#define EMAC_GENSTS_RPSTS_Msk (0x1ul << EMAC_GENSTS_RPSTS_Pos) /*!< EMAC_T::GENSTS: RPSTS Mask */ + +#define EMAC_MPCNT_MPCNT_Pos (0) /*!< EMAC_T::MPCNT: MPCNT Position */ +#define EMAC_MPCNT_MPCNT_Msk (0xfffful << EMAC_MPCNT_MPCNT_Pos) /*!< EMAC_T::MPCNT: MPCNT Mask */ + +#define EMAC_RPCNT_RPCNT_Pos (0) /*!< EMAC_T::RPCNT: RPCNT Position */ +#define EMAC_RPCNT_RPCNT_Msk (0xfffful << EMAC_RPCNT_RPCNT_Pos) /*!< EMAC_T::RPCNT: RPCNT Mask */ + +#define EMAC_FRSTS_RXFLT_Pos (0) /*!< EMAC_T::FRSTS: RXFLT Position */ +#define EMAC_FRSTS_RXFLT_Msk (0xfffful << EMAC_FRSTS_RXFLT_Pos) /*!< EMAC_T::FRSTS: RXFLT Mask */ + +#define EMAC_CTXDSA_CTXDSA_Pos (0) /*!< EMAC_T::CTXDSA: CTXDSA Position */ +#define EMAC_CTXDSA_CTXDSA_Msk (0xfffffffful << EMAC_CTXDSA_CTXDSA_Pos) /*!< EMAC_T::CTXDSA: CTXDSA Mask */ + +#define EMAC_CTXBSA_CTXBSA_Pos (0) /*!< EMAC_T::CTXBSA: CTXBSA Position */ +#define EMAC_CTXBSA_CTXBSA_Msk (0xfffffffful << EMAC_CTXBSA_CTXBSA_Pos) /*!< EMAC_T::CTXBSA: CTXBSA Mask */ + +#define EMAC_CRXDSA_CRXDSA_Pos (0) /*!< EMAC_T::CRXDSA: CRXDSA Position */ +#define EMAC_CRXDSA_CRXDSA_Msk (0xfffffffful << EMAC_CRXDSA_CRXDSA_Pos) /*!< EMAC_T::CRXDSA: CRXDSA Mask */ + +#define EMAC_CRXBSA_CRXBSA_Pos (0) /*!< EMAC_T::CRXBSA: CRXBSA Position */ +#define EMAC_CRXBSA_CRXBSA_Msk (0xfffffffful << EMAC_CRXBSA_CRXBSA_Pos) /*!< EMAC_T::CRXBSA: CRXBSA Mask */ + +#define EMAC_TSCTL_TSEN_Pos (0) /*!< EMAC_T::TSCTL: TSEN Position */ +#define EMAC_TSCTL_TSEN_Msk (0x1ul << EMAC_TSCTL_TSEN_Pos) /*!< EMAC_T::TSCTL: TSEN Mask */ + +#define EMAC_TSCTL_TSIEN_Pos (1) /*!< EMAC_T::TSCTL: TSIEN Position */ +#define EMAC_TSCTL_TSIEN_Msk (0x1ul << EMAC_TSCTL_TSIEN_Pos) /*!< EMAC_T::TSCTL: TSIEN Mask */ + +#define EMAC_TSCTL_TSMODE_Pos (2) /*!< EMAC_T::TSCTL: TSMODE Position */ +#define EMAC_TSCTL_TSMODE_Msk (0x1ul << EMAC_TSCTL_TSMODE_Pos) /*!< EMAC_T::TSCTL: TSMODE Mask */ + +#define EMAC_TSCTL_TSUPDATE_Pos (3) /*!< EMAC_T::TSCTL: TSUPDATE Position */ +#define EMAC_TSCTL_TSUPDATE_Msk (0x1ul << EMAC_TSCTL_TSUPDATE_Pos) /*!< EMAC_T::TSCTL: TSUPDATE Mask */ + +#define EMAC_TSCTL_TSALMEN_Pos (5) /*!< EMAC_T::TSCTL: TSALMEN Position */ +#define EMAC_TSCTL_TSALMEN_Msk (0x1ul << EMAC_TSCTL_TSALMEN_Pos) /*!< EMAC_T::TSCTL: TSALMEN Mask */ + +#define EMAC_TSSEC_SEC_Pos (0) /*!< EMAC_T::TSSEC: SEC Position */ +#define EMAC_TSSEC_SEC_Msk (0xfffffffful << EMAC_TSSEC_SEC_Pos) /*!< EMAC_T::TSSEC: SEC Mask */ + +#define EMAC_TSSUBSEC_SUBSEC_Pos (0) /*!< EMAC_T::TSSUBSEC: SUBSEC Position */ +#define EMAC_TSSUBSEC_SUBSEC_Msk (0xfffffffful << EMAC_TSSUBSEC_SUBSEC_Pos) /*!< EMAC_T::TSSUBSEC: SUBSEC Mask */ + +#define EMAC_TSINC_CNTINC_Pos (0) /*!< EMAC_T::TSINC: CNTINC Position */ +#define EMAC_TSINC_CNTINC_Msk (0xfful << EMAC_TSINC_CNTINC_Pos) /*!< EMAC_T::TSINC: CNTINC Mask */ + +#define EMAC_TSADDEND_ADDEND_Pos (0) /*!< EMAC_T::TSADDEND: ADDEND Position */ +#define EMAC_TSADDEND_ADDEND_Msk (0xfffffffful << EMAC_TSADDEND_ADDEND_Pos) /*!< EMAC_T::TSADDEND: ADDEND Mask */ + +#define EMAC_UPDSEC_SEC_Pos (0) /*!< EMAC_T::UPDSEC: SEC Position */ +#define EMAC_UPDSEC_SEC_Msk (0xfffffffful << EMAC_UPDSEC_SEC_Pos) /*!< EMAC_T::UPDSEC: SEC Mask */ + +#define EMAC_UPDSUBSEC_SUBSEC_Pos (0) /*!< EMAC_T::UPDSUBSEC: SUBSEC Position */ +#define EMAC_UPDSUBSEC_SUBSEC_Msk (0xfffffffful << EMAC_UPDSUBSEC_SUBSEC_Pos) /*!< EMAC_T::UPDSUBSEC: SUBSEC Mask */ + +#define EMAC_ALMSEC_SEC_Pos (0) /*!< EMAC_T::ALMSEC: SEC Position */ +#define EMAC_ALMSEC_SEC_Msk (0xfffffffful << EMAC_ALMSEC_SEC_Pos) /*!< EMAC_T::ALMSEC: SEC Mask */ + +#define EMAC_ALMSUBSEC_SUBSEC_Pos (0) /*!< EMAC_T::ALMSUBSEC: SUBSEC Position */ +#define EMAC_ALMSUBSEC_SUBSEC_Msk (0xfffffffful << EMAC_ALMSUBSEC_SUBSEC_Pos) /*!< EMAC_T::ALMSUBSEC: SUBSEC Mask */ + +/**@}*/ /* EMAC_CONST */ +/**@}*/ /* end of EMAC register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) + #pragma no_anon_unions +#endif + +#endif /* __EMAC_REG_H__ */ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_2d.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_2d.h new file mode 100644 index 0000000000..36275b15ea --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_2d.h @@ -0,0 +1,190 @@ +/**************************************************************************//** +* @file 2d.h +* @brief N9H30 2DGE driver header file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_2D_H__ +#define __NU_2D_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_GE2D_Driver GE2D Driver + @{ +*/ + +/** @addtogroup N9H30_GE2D_EXPORTED_CONSTANTS GE2D Exported Constants + @{ +*/ + +/// @cond HIDDEN_SYMBOLS +typedef struct +{ + UINT32 PatternA; + UINT32 PatternB; +} MONOPATTERN; + +#define COLOR_KEY 0xFF000000 +/// @endcond HIDDEN_SYMBOLS + +/////////////////////////////////////////////////////////////////////////////// +// Definition of ROP2 +/////////////////////////////////////////////////////////////////////////////// +#define BLACKNESS 0x00 /*!< rop code: 0 */ +#define DSTINVERT 0x55 /*!< rop code: Dn */ +#define MERGECOPY 0xC0 /*!< rop code: PSa */ +#define MERGEPAINT 0xBB /*!< rop code: DSno */ +#define NOTSRCCOPY 0x33 /*!< rop code: Sn */ +#define NOTSRCERASE 0x11 /*!< rop code: DSon */ +#define PATCOPY 0xF0 /*!< rop code: P */ +#define PATINVERT 0x5A /*!< rop code: DPx */ +#define PATPAINT 0xFB /*!< rop code: DPSnoo */ +#define SRCAND 0x88 /*!< rop code: DSa */ +#define SRCCOPY 0xCC /*!< rop code: S */ +#define SRCERASE 0x44 /*!< rop code: SDna */ +#define SRCINVERT 0x66 /*!< rop code: DSx */ +#define SRCPAINT 0xEE /*!< rop code: DSo */ +#define WHITENESS 0xFF /*!< rop code: 1 */ + +/////////////////////////////////////////////////////////////////////////////// +// Definition of Pen Styles +/////////////////////////////////////////////////////////////////////////////// +#define PS_SOLID 0xffff /*!< pan style: solid */ //1111111111111111 (1111111111111111) +#define PS_DASH 0xcccc /*!< pan style: dash */ //1100110011001100 (1111000011110000) +#define PS_DOT 0xaaaa /*!< pan style: dot */ //1010101010101010 (1100110011001100) +#define PS_DASHDOT 0xe4e4 /*!< pan style: dash and dot */ //1110010011100100 (1111110000110000) +#define PS_DASHDOTDOT 0xeaea /*!< pan style: dash and two dots */ //1110101011101010 (1111110011001100) +#define PS_NULL 0x0000 /*!< pan style: null */ //0000000000000000 (0000000000000000) + +/////////////////////////////////////////////////////////////////////////////// +// Definition of Brush Styles +// +// HS_HORIZONTAL: 00000000 HS_BDIAGONAL: 00000001 +// 00000000 00000010 +// 00000000 00000100 +// 00000000 00001000 +// 11111111 00010000 +// 00000000 00100000 +// 00000000 01000000 +// 00000000 10000000 +// +// HS_VERTICAL: 00001000 HS_CROSS: 00001000 +// 00001000 00001000 +// 00001000 00001000 +// 00001000 00001000 +// 00001000 11111111 +// 00001000 00001000 +// 00001000 00001000 +// 00001000 00001000 +// +// HS_FDIAGONAL: 10000000 HS_DIAGCROSS: 10000001 +// 01000000 01000010 +// 00100000 00100100 +// 00010000 00011000 +// 00001000 00011000 +// 00000100 00100100 +// 00000010 01000010 +// 00000001 10000001 +/////////////////////////////////////////////////////////////////////////////// +#define HS_HORIZONTAL 0 /*!< brush style: horizontal */ +#define HS_VERTICAL 1 /*!< brush style: vertical */ +#define HS_FDIAGONAL 2 /*!< brush style: fdiagonal */ +#define HS_BDIAGONAL 3 /*!< brush style: bdiagonal */ +#define HS_CROSS 4 /*!< brush style: cross */ +#define HS_DIAGCROSS 5 /*!< brush style: diagcross */ + +#define MODE_OPAQUE 0 /*!< opaque mode */ +#define MODE_TRANSPARENT 1 /*!< transparent mode */ +#define MODE_SRC_TRANSPARENT MODE_TRANSPARENT /*!< source transparent mode */ +#define MODE_DEST_TRANSPARENT 2 /*!< destination transparent mode */ + +#define MODE_INSIDE_CLIP 0 /*!< clip inside */ +#define MODE_OUTSIDE_CLIP 1 /*!< clip outside */ + +#define TYPE_MONO 0 /*!< mono */ +#define TYPE_COLOR 1 /*!< color */ + +#define GE_BPP_8 0x00000000 /*!< 8bpp display */ +#define GE_BPP_16 0x00000010 /*!< 16bpp display */ +#define GE_BPP_32 0x00000020 /*!< 32bpp display */ + +#define RGB332 1 /*!< 8bpp display */ +#define RGB565 2 /*!< 16bpp display */ +#define RGB888 3 /*!< 24bpp display */ + +#define F8x8 0 /*!< 8x8 font support */ +#define F8x16 1 /*!< 8x16 font support */ + +/*@}*/ /* end of group N9H30_GE2D_EXPORTED_CONSTANTS */ + +/** @addtogroup N9H30_GE2D_EXPORTED_FUNCTIONS GE2D Exported Functions + @{ +*/ + +void ge2dClearScreen(int color); +void ge2dSetWriteMask(int mask); +void ge2dSetSourceOriginStarting(void *ptr); +void ge2dSetDestinationOriginStarting(void *ptr); +void ge2dInit(int bpp, int width, int height, void *destination); +void ge2dReset(void); +void ge2dResetFIFO(void); +void ge2dBitblt_SetDrawMode(int opt, int ckey, int mask); +int ge2dBitblt_SetAlphaMode(int opt, int ks, int kd); +void ge2dBitblt_ScreenToScreen(int srcx, int srcy, int destx, int desty, int width, int height); +void ge2dBitblt_ScreenToScreenRop(int srcx, int srcy, int destx, int desty, int width, int height, int rop); +void ge2dBitblt_SourceToDestination(int srcx, int srcy, int destx, int desty, int width, int height, int srcpitch, int destpitch); +void ge2dClip_SetClip(int x1, int y1, int x2, int y2); +void ge2dClip_SetClipMode(int opt); +void ge2dDrawFrame(int x1, int y1, int x2, int y2, int color, int opt); +void ge2dLine_DrawSolidLine(int x1, int y1, int x2, int y2, int color); +void ge2dLine_DrawSolidLine_RGB565(int x1, int y1, int x2, int y2, int color); +void ge2dLine_DrawStyledLine(int x1, int y1, int x2, int y2, int style, int fgcolor, int bkcolor, int draw_mode); +void ge2dLine_DrawStyledLine_RGB565(int x1, int y1, int x2, int y2, int style, int fgcolor, int bkcolor, int draw_mode); +void ge2dFill_Solid(int dx, int dy, int width, int height, int color); +void ge2dFill_Solid_RGB565(int dx, int dy, int width, int height, int color); +void ge2dFill_SolidBackground(int dx, int dy, int width, int height, int color); +void ge2dFill_ColorPattern(int dx, int dy, int width, int height); +void ge2dFill_MonoPattern(int dx, int dy, int width, int height, int opt); +void ge2dFill_ColorPatternROP(int sx, int sy, int width, int height, int rop); +void ge2dFill_MonoPatternROP(int sx, int sy, int width, int height, int rop, int opt); +void ge2dFill_TileBlt(int srcx, int srcy, int destx, int desty, int width, int height, int x_count, int y_count); +void ge2dHostBlt_Write(int x, int y, int width, int height, void *buf); +void ge2dHostBlt_Read(int x, int y, int width, int height, void *buf); +void ge2dHostBlt_Sprite(int x, int y, int width, int height, void *buf); +void ge2dRotation(int srcx, int srcy, int destx, int desty, int width, int height, int ctl); +void ge2dSpriteBlt_Screen(int destx, int desty, int sprite_width, int sprite_height, void *buf); +void ge2dSpriteBltx_Screen(int x, int y, int sprite_sx, int sprite_sy, int width, int height, int sprite_width, int sprite_height, void *buf); +void ge2dSpriteBlt_ScreenRop(int x, int y, int sprite_width, int sprite_height, void *buf, int rop); +void ge2dSpriteBltx_ScreenRop(int x, int y, int sprite_sx, int sprite_sy, int width, int height, int sprite_width, int sprite_height, void *buf, int rop); +void ge2dColorExpansionBlt(int x, int y, int width, int height, int fore_color, int back_color, int opt, void *buf); +void ge2dHostColorExpansionBlt(int x, int y, int width, int height, int fore_color, int back_color, int opt, void *buf); +void ge2dInitMonoPattern(int opt, int fore_color, int back_color); +void ge2dInitMonoInputPattern(UINT32 PatternA, UINT32 PatternB, int fore_color, int back_color); +void ge2dInitColorPattern(int patformat, void *patdata); +void ge2dFont_PutChar(int x, int y, char asc_code, int fore_color, int back_color, int draw_mode, int font_id); +void ge2dFont_PutString(int x, int y, char *str, int fore_color, int back_color, int draw_mode, int font_id); + +/*@}*/ /* end of group N9H30_GE2D_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_GE2D_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + + +#ifdef __cplusplus +} +#endif + +#endif //__NU_2D_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_adc.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_adc.h new file mode 100644 index 0000000000..6747946db5 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_adc.h @@ -0,0 +1,198 @@ +/**************************************************************************//** +* @file adc.h +* @brief N9H30 ADC driver header file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_ADC_H__ +#define __NU_ADC_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_ADC_Driver ADC Driver + @{ +*/ + +/** @addtogroup N9H30_ADC_EXPORTED_CONSTANTS ADC Exported Constants + @{ +*/ + +#define ADC_ERR_ARGS 1 /*!< The arguments is wrong */ +#define ADC_ERR_CMD 2 /*!< The command is wrong */ + +/// @cond HIDDEN_SYMBOLS +typedef int32_t(*ADC_CALLBACK)(uint32_t status, uint32_t userData); +/// @endcond HIDDEN_SYMBOLS +/*---------------------------------------------------------------------------------------------------------*/ +/* ADC_CTL constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define ADC_CTL_ADEN 0x00000001 /*!< ADC Power Control */ +#define ADC_CTL_VBGEN 0x00000002 /*!< ADC Internal Bandgap Power Control */ +#define ADC_CTL_PWKPEN 0x00000004 /*!< ADC Keypad Power Enable Control */ +#define ADC_CTL_MST 0x00000100 /*!< Menu Start Conversion */ +#define ADC_CTL_PEDEEN 0x00000200 /*!< Pen Down Event Enable */ +#define ADC_CTL_WKPEN 0x00000400 /*!< Keypad Press Wake Up Enable */ +#define ADC_CTL_WKTEN 0x00000800 /*!< Touch Wake Up Enable */ +#define ADC_CTL_WMSWCH 0x00010000 /*!< Wire Mode Switch For 5-Wire/4-Wire Configuration */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* ADC_CONF constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define ADC_CONF_TEN 0x00000001 /*!< Touch Enable */ +#define ADC_CONF_ZEN 0x00000002 /*!< Press Enable */ +#define ADC_CONF_NACEN 0x00000004 /*!< Normal AD Conversion Enable */ +#define ADC_CONF_VBATEN 0x00000100 /*!< Voltage Battery Enable */ +#define ADC_CONF_KPCEN 0x00000200 /*!< Keypad Press Conversion Enable */ +#define ADC_CONF_SELFTEN 0x00000400 /*!< Selft Test Enable */ +#define ADC_CONF_DISTMAVEN (1<<20) /*!< Display T Mean Average Enable */ +#define ADC_CONF_DISZMAVEN (1<<21) /*!< Display Z Mean Average Enable */ +#define ADC_CONF_HSPEED (1<<22) /*!< High Speed Enable */ + +#define ADC_CONF_CHSEL_Pos 3 /*!< Channel Selection Position */ +#define ADC_CONF_CHSEL_Msk (7<<3) /*!< Channel Selection Mask */ +#define ADC_CONF_CHSEL_VBT (0<<3) /*!< ADC input channel select VBT */ +#define ADC_CONF_CHSEL_VHS (1<<3) /*!< ADC input channel select VHS */ +#define ADC_CONF_CHSEL_A2 (2<<3) /*!< ADC input channel select A2 */ +#define ADC_CONF_CHSEL_A3 (3<<3) /*!< ADC input channel select A3 */ +#define ADC_CONF_CHSEL_YM (4<<3) /*!< ADC input channel select YM */ +#define ADC_CONF_CHSEL_YP (5<<3) /*!< ADC input channel select YP */ +#define ADC_CONF_CHSEL_XM (6<<3) /*!< ADC input channel select XM */ +#define ADC_CONF_CHSEL_XP (7<<3) /*!< ADC input channel select XP */ + +#define ADC_CONF_REFSEL_Pos 6 /*!< Reference Selection Position */ +#define ADC_CONF_REFSEL_Msk (3<<6) /*!< Reference Selection Mask */ +#define ADC_CONF_REFSEL_VREF (0<<6) /*!< ADC reference select VREF input or 2.5v buffer output */ +#define ADC_CONF_REFSEL_YMYP (1<<6) /*!< ADC reference select YM vs YP */ +#define ADC_CONF_REFSEL_XMXP (2<<6) /*!< ADC reference select XM vs XP */ +#define ADC_CONF_REFSEL_AVDD33 (3<<6) /*!< ADC reference select AGND33 vs AVDD33 */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* ADC_IER constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define ADC_IER_MIEN 0x00000001 /*!< Menu Interrupt Enable */ +#define ADC_IER_KPEIEN 0x00000002 /*!< Keypad Press Event Interrupt Enable */ +#define ADC_IER_PEDEIEN 0x00000004 /*!< Pen Down Even Interrupt Enable */ +#define ADC_IER_WKTIEN 0x00000008 /*!< Wake Up Touch Interrupt Enable */ +#define ADC_IER_WKPIEN 0x00000010 /*!< Wake Up Keypad Press Interrupt Enable */ +#define ADC_IER_KPUEIEN 0x00000020 /*!< Keypad Press Up Event Interrupt Enable */ +#define ADC_IER_PEUEIEN 0x00000040 /*!< Pen Up Event Interrupt Enable */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* ADC_ISR constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define ADC_ISR_MF 0x00000001 /*!< Menu Complete Flag */ +#define ADC_ISR_KPEF 0x00000002 /*!< Keypad Press Event Flag */ +#define ADC_ISR_PEDEF 0x00000004 /*!< Pen Down Event Flag */ +#define ADC_ISR_KPUEF 0x00000008 /*!< Keypad Press Up Event Flag */ +#define ADC_ISR_PEUEF 0x00000010 /*!< Pen Up Event Flag */ +#define ADC_ISR_TF 0x00000100 /*!< Touch Conversion Finish */ +#define ADC_ISR_ZF 0x00000200 /*!< Press Conversion Finish */ +#define ADC_ISR_NACF 0x00000400 /*!< Normal AD Conversion Finish */ +#define ADC_ISR_VBF 0x00000800 /*!< Voltage Battery Conversion Finish */ +#define ADC_ISR_KPCF 0x00001000 /*!< Keypad Press Conversion Finish */ +#define ADC_ISR_SELFTF 0x00002000 /*!< Self-Test Conversion Finish */ +#define ADC_ISR_INTKP 0x00010000 /*!< Interrupt Signal For Keypad Detection */ +#define ADC_ISR_INTTC 0x00020000 /*!< Interrupt Signal For Touch Screen Touching Detection */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* ADC_WKISR constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define ADC_WKISR_WKPEF 0x00000001 /*!< Wake Up Pen Down Event Flag */ +#define ADC_WKISR_WPEDEF 0x00000002 /*!< Wake Up Keypad Press Event Flage */ + +/** \brief Structure type of ADC_CHAN + */ +typedef enum +{ + AIN0 = ADC_CONF_CHSEL_VBT, /*!< ADC input channel select \ref ADC_CONF_CHSEL_VBT */ + AIN1 = ADC_CONF_CHSEL_VHS, /*!< ADC input channel select \ref ADC_CONF_CHSEL_VHS */ + AIN2 = ADC_CONF_CHSEL_A2, /*!< ADC input channel select \ref ADC_CONF_CHSEL_A2 */ + AIN3 = ADC_CONF_CHSEL_A3, /*!< ADC input channel select \ref ADC_CONF_CHSEL_A3 */ + AIN4 = ADC_CONF_CHSEL_YM, /*!< ADC input channel select \ref ADC_CONF_CHSEL_YM */ + AIN5 = ADC_CONF_CHSEL_XP, /*!< ADC input channel select \ref ADC_CONF_CHSEL_XP */ + AIN6 = ADC_CONF_CHSEL_XM, /*!< ADC input channel select \ref ADC_CONF_CHSEL_XM */ + AIN7 = ADC_CONF_CHSEL_XP /*!< ADC input channel select \ref ADC_CONF_CHSEL_XP */ +} ADC_CHAN; + +/** \brief Structure type of ADC_CMD + */ +typedef enum +{ + START_MST, /*!
STATUS) + +/** + * @brief Get specified interrupt pending status. + * + * @param[in] can The base address of can module. + * + * @return The source of the interrupt. + * + * @details If several interrupts are pending, the CAN Interrupt Register will point to the pending interrupt + * with the highest priority, disregarding their chronological order. + * \hideinitializer + */ +#define CAN_GET_INT_PENDING_STATUS(can) ((can)->IIDR) + +/** + * @brief Disable wake-up function. + * + * @param[in] can The base address of can module. + * + * @return None + * + * @details The macro is used to disable wake-up function. + * \hideinitializer + */ +#define CAN_DISABLE_WAKEUP(can) ((can)->WU_EN = 0ul) + +/** + * @brief Enable wake-up function. + * + * @param[in] can The base address of can module. + * + * @return None + * + * @details User can wake-up system when there is a falling edge in the CAN_Rx pin. + * \hideinitializer + */ +#define CAN_ENABLE_WAKEUP(can) ((can)->WU_EN = CAN_WU_EN_WAKUP_EN_Msk) + +/** + * @brief Get specified Message Object new data into bit value. + * + * @param[in] can The base address of can module. + * @param[in] u32MsgNum Specified Message Object number, valid value are from 0 to 31. + * + * @return Specified Message Object new data into bit value. + * + * @details The NewDat bit (CAN_IFn_MCON[15]) of a specific Message Object can be set/reset by the software through the IFn Message Interface Registers + * or by the Message Handler after reception of a Data Frame or after a successful transmission. + * \hideinitializer + */ +#define CAN_GET_NEW_DATA_IN_BIT(can, u32MsgNum) ((u32MsgNum) < 16 ? (can)->NDAT1 & (1 << (u32MsgNum)) : (can)->NDAT2 & (1 << ((u32MsgNum)-16))) + + +/*---------------------------------------------------------------------------------------------------------*/ +/* Define CAN functions prototype */ +/*---------------------------------------------------------------------------------------------------------*/ +uint32_t CAN_SetBaudRate(CAN_T *tCAN, uint32_t u32BaudRate); +uint32_t CAN_Open(CAN_T *tCAN, uint32_t u32BaudRate, uint32_t u32Mode); +void CAN_Close(CAN_T *tCAN); +void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum); +void CAN_EnableInt(CAN_T *tCAN, uint32_t u32Mask); +void CAN_DisableInt(CAN_T *tCAN, uint32_t u32Mask); +int32_t CAN_Transmit(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T *pCanMsg); +int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T *pCanMsg); +int32_t CAN_SetMultiRxMsg(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32MsgCount, uint32_t u32IDType, uint32_t u32ID); +int32_t CAN_SetRxMsg(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32IDType, uint32_t u32ID); +int32_t CAN_SetRxMsgAndMsk(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32IDType, uint32_t u32ID, uint32_t u32IDMask); +int32_t CAN_SetTxMsg(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T *pCanMsg); +int32_t CAN_TriggerTxMsg(CAN_T *tCAN, uint32_t u32MsgNum); +int32_t CAN_BasicSendMsg(CAN_T *tCAN, STR_CANMSG_T *pCanMsg); +int32_t CAN_BasicReceiveMsg(CAN_T *tCAN, STR_CANMSG_T *pCanMsg); +void CAN_EnterInitMode(CAN_T *tCAN, uint8_t u8Mask); +void CAN_EnterTestMode(CAN_T *tCAN, uint8_t u8TestMask); +void CAN_LeaveTestMode(CAN_T *tCAN); +uint32_t CAN_GetCANBitRate(CAN_T *tCAN); +uint32_t CAN_IsNewDataReceived(CAN_T *tCAN, uint8_t u8MsgObj); +void CAN_LeaveInitMode(CAN_T *tCAN); +int32_t CAN_SetRxMsgObjAndMsk(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8idType, uint32_t u32id, uint32_t u32idmask, uint8_t u8singleOrFifoLast); +int32_t CAN_SetRxMsgObj(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8idType, uint32_t u32id, uint8_t u8singleOrFifoLast); +void CAN_WaitMsg(CAN_T *tCAN); +int32_t CAN_ReadMsgObj(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8Release, STR_CANMSG_T *pCanMsg); + +/*@}*/ /* end of group CAN_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group CAN_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + + + +#endif /*__NU_CAN_H__ */ + +/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_cap.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_cap.h new file mode 100644 index 0000000000..dc06ea7f60 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_cap.h @@ -0,0 +1,316 @@ +/**************************************************************************//** +* @file cap.h +* @version V1.00 +* $Revision: 2 $ +* $Date: 15/06/12 8:48a $ +* @brief N9H30 CAP driver header file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_CAP_H__ +#define __NU_CAP_H__ + +// #include header file +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_CAP_Driver CAP Driver + @{ +*/ + +/** @addtogroup N9H30_CAP_EXPORTED_CONSTANTS CAP Exported Constants + @{ +*/ + +/* Define data type (struct, union? */ +// #define Constant +#include "N9H30.h" +#include "nu_sys.h" + +/*---------------------------------------------------------------------------------------------------------*/ +/* CAP_CTL constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define CAPEN BIT0 /*!< Interrupt enable for VPE operations */ +#define ADDRSW BIT3 /*!< Packet Buffer Address Switch */ +#define PLNEN BIT5 /*!< Planar Output Enable */ +#define PKTEN BIT6 /*!< Packet Output Enable */ +#define SHUTTER BIT16 /*!< Image Capture Interface Automatically Disable The Capture Inteface After A Frame Had Been Captured */ +#define UPDATE BIT20 /*!< Update Register At New Frame */ +#define VPRST BIT24 /*!< Capture Interface Reset */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* CAP_PAR constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define INFMT BIT0 /*!< Sensor Input Data Format */ +#define SENTYPE BIT1 /*!< Sensor Input Type */ +#define INDATORD (BIT2|BIT3) /*!< Sensor Input Data Order */ +#define OUTFMT (BIT4|BIT5) /*!< Image Data Format Output To System Memory */ +#define RANGE BIT6 /*!< Scale Input YUV CCIR601 Color Range To Full Range */ +#define PLNFMT BIT7 /*!< Planar Output YUV Format */ +#define PCLKP BIT8 /*!< Sensor Pixel Clock Polarity */ +#define HSP BIT9 /*!< Sensor Hsync Polarity */ +#define VSP BIT10 /*!< Sensor Vsync Polarity */ +#define COLORCTL (BIT11|BIT12) /*!< Special COLORCTL Processing */ +#define FBB BIT18 /*!< Field By Blank */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* CAP_INT constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define MDIEN BIT20 /*!< Motion Detection Output Finish Interrupt Enable */ +#define ADDRMIEN BIT19 /*!< Address Match Interrupt Enable */ +#define MEIEN BIT17 /*!< System Memory Error Interrupt Enable */ +#define VIEN BIT16 /*!< Video Frame End Interrupt Enable */ +#define MDINTF BIT4 /*!< Motion Detection Output Finish Interrupt */ +#define ADDRMINTF BIT3 /*!< Memory Address Match Interrupt */ +#define MEINTF BIT1 /*!< Bus Master Transfer Error Interrupt */ +#define VINTF BIT0 /*!< Video Frame End Interrupt */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* CAP_MD constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define MDEN BIT0 /*!< Motion Detection Enable */ +#define MDBS BIT8 /*!< Motion Detection Block Size */ +#define MDSM BIT9 /*!< Motion Detection Save Mode */ +#define MDDF (BIT10|BIT11) /*!< Motion Detection Detect Frequency */ +#define MDTHR (BIT16|BIT17|BIT18|BIT19|BIT20) /*!< Motion Detection Differential Threshold */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* CAP_CWSP constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define CWSADDRH (0xFFF<<0) /*!INTEN |= CRPT_INTEN_PRNGIEN_Msk) + +/** + * @brief This macro disables PRNG interrupt. + * @return None + * \hideinitializer + */ +#define PRNG_DISABLE_INT() (CRPT->INTEN &= ~CRPT_INTEN_PRNGIEN_Msk) + +/** + * @brief This macro gets PRNG interrupt flag. + * @return PRNG interrupt flag. + * \hideinitializer + */ +#define PRNG_GET_INT_FLAG() (CRPT->INTSTS & CRPT_INTSTS_PRNGIF_Msk) + +/** + * @brief This macro clears PRNG interrupt flag. + * @return None + * \hideinitializer + */ +#define PRNG_CLR_INT_FLAG() (CRPT->INTSTS = CRPT_INTSTS_PRNGIF_Msk) + +/** + * @brief This macro enables AES interrupt. + * @return None + * \hideinitializer + */ +#define AES_ENABLE_INT() (CRPT->INTEN |= (CRPT_INTEN_AESIEN_Msk|CRPT_INTEN_AESERRIEN_Msk)) + +/** + * @brief This macro disables AES interrupt. + * @return None + * \hideinitializer + */ +#define AES_DISABLE_INT() (CRPT->INTEN &= ~(CRPT_INTEN_AESIEN_Msk|CRPT_INTEN_AESERRIEN_Msk)) + +/** + * @brief This macro gets AES interrupt flag. + * @return AES interrupt flag. + * \hideinitializer + */ +#define AES_GET_INT_FLAG() (CRPT->INTSTS & (CRPT_INTSTS_AESIF_Msk|CRPT_INTSTS_AESERRIF_Msk)) + +/** + * @brief This macro clears AES interrupt flag. + * @return None + * \hideinitializer + */ +#define AES_CLR_INT_FLAG() (CRPT->INTSTS = (CRPT_INTSTS_AESIF_Msk|CRPT_INTSTS_AESERRIF_Msk)) + +/** + * @brief This macro enables AES key protection. + * @return None + * \hideinitializer + */ +#define AES_ENABLE_KEY_PROTECT() (CRPT->AES_CTL |= CRPT_AES_CTL_KEYPRT_Msk) + +/** + * @brief This macro disables AES key protection. + * @return None + * \hideinitializer + */ +#define AES_DISABLE_KEY_PROTECT() (CRPT->AES_CTL = (CRPT->AES_CTL & ~CRPT_AES_CTL_KEYPRT_Msk) | (0x16<INTEN |= (CRPT_INTEN_TDESIEN_Msk|CRPT_INTEN_TDESERRIEN_Msk)) + +/** + * @brief This macro disables TDES interrupt. + * @return None + * \hideinitializer + */ +#define TDES_DISABLE_INT() (CRPT->INTEN &= ~(CRPT_INTEN_TDESIEN_Msk|CRPT_INTEN_TDESERRIEN_Msk)) + +/** + * @brief This macro gets TDES interrupt flag. + * @return TDES interrupt flag. + * \hideinitializer + */ +#define TDES_GET_INT_FLAG() (CRPT->INTSTS & (CRPT_INTSTS_TDESIF_Msk|CRPT_INTSTS_TDESERRIF_Msk)) + +/** + * @brief This macro clears TDES interrupt flag. + * @return None + * \hideinitializer + */ +#define TDES_CLR_INT_FLAG() (CRPT->INTSTS = (CRPT_INTSTS_TDESIF_Msk|CRPT_INTSTS_TDESERRIF_Msk)) + +/** + * @brief This macro enables TDES key protection. + * @return None + * \hideinitializer + */ +#define TDES_ENABLE_KEY_PROTECT() (CRPT->TDES_CTL |= CRPT_TDES_CTL_KEYPRT_Msk) + +/** + * @brief This macro disables TDES key protection. + * @return None + * \hideinitializer + */ +#define TDES_DISABLE_KEY_PROTECT() (CRPT->TDES_CTL = (CRPT->TDES_CTL & ~CRPT_TDES_CTL_KEYPRT_Msk) | (0x16<INTEN |= (CRPT_INTEN_SHAIEN_Msk|CRPT_INTEN_SHAERRIEN_Msk)) + +/** + * @brief This macro disables SHA interrupt. + * @return None + * \hideinitializer + */ +#define SHA_DISABLE_INT() (CRPT->INTEN &= ~(CRPT_INTEN_SHAIEN_Msk|CRPT_INTEN_SHAERRIEN_Msk)) + +/** + * @brief This macro gets SHA interrupt flag. + * @return SHA interrupt flag. + * \hideinitializer + */ +#define SHA_GET_INT_FLAG() (CRPT->INTSTS & (CRPT_INTSTS_SHAIF_Msk|CRPT_INTSTS_SHAERRIF_Msk)) + +/** + * @brief This macro clears SHA interrupt flag. + * @return None + * \hideinitializer + */ +#define SHA_CLR_INT_FLAG() (CRPT->INTSTS = (CRPT_INTSTS_SHAIF_Msk|CRPT_INTSTS_SHAERRIF_Msk)) + + + +/*---------------------------------------------------------------------------------------------------------*/ +/* Functions */ +/*---------------------------------------------------------------------------------------------------------*/ + +void PRNG_Open(uint32_t u32KeySize, uint32_t u32SeedReload, uint32_t u32Seed); +void PRNG_Start(void); +void PRNG_Read(uint32_t u32RandKey[]); +void AES_Open(uint32_t u32Channel, uint32_t u32EncDec, uint32_t u32OpMode, uint32_t u32KeySize, uint32_t u32SwapType); +void AES_Start(int32_t u32Channel, uint32_t u32DMAMode); +void AES_SetKey(uint32_t u32Channel, uint32_t au32Keys[], uint32_t u32KeySize); +void AES_SetInitVect(uint32_t u32Channel, uint32_t au32IV[]); +void AES_SetDMATransfer(uint32_t u32Channel, uint32_t u32SrcAddr, uint32_t u32DstAddr, uint32_t u32TransCnt); +void TDES_Open(uint32_t u32Channel, uint32_t u32EncDec, int32_t Is3DES, int32_t Is3Key, uint32_t u32OpMode, uint32_t u32SwapType); +void TDES_Start(int32_t u32Channel, uint32_t u32DMAMode); +void TDES_SetKey(uint32_t u32Channel, uint32_t au32Keys[3][2]); +void TDES_SetInitVect(uint32_t u32Channel, uint32_t u32IVH, uint32_t u32IVL); +void TDES_SetDMATransfer(uint32_t u32Channel, uint32_t u32SrcAddr, uint32_t u32DstAddr, uint32_t u32TransCnt); +void SHA_Open(uint32_t u32OpMode, uint32_t u32SwapType, int hmac_key_len); +void SHA_Start(uint32_t u32DMAMode); +void SHA_SetDMATransfer(uint32_t u32SrcAddr, uint32_t u32TransCnt); +void SHA_Read(uint32_t u32Digest[]); + + +/*@}*/ /* end of group N9H30_CRYPTO_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_CRYPTO_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif // __NU_CRYPTO_H__ + +/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_emac.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_emac.h new file mode 100644 index 0000000000..f6a5ce86e9 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_emac.h @@ -0,0 +1,396 @@ +/**************************************************************************//** + * @file nu_emac.h + * @version V1.00 + * @brief EMAC driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#ifndef __NU_EMAC_H__ +#define __NU_EMAC_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include "emac_reg.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup EMAC_Driver EMAC Driver + @{ +*/ + +/** @addtogroup EMAC_EXPORTED_CONSTANTS EMAC Exported Constants + @{ +*/ + +#define EMAC_PHY_ADDR 1UL /*!< PHY address, this address is board dependent \hideinitializer */ +#define EMAC_RX_DESC_SIZE 64UL /*!< Number of Rx Descriptors, should be 2 at least \hideinitializer */ +#define EMAC_TX_DESC_SIZE 32UL /*!< Number of Tx Descriptors, should be 2 at least \hideinitializer */ +#define EMAC_CAMENTRY_NB 16UL /*!< Number of CAM \hideinitializer */ +#define EMAC_MAX_PKT_SIZE 1536UL /*!< Number of HDR + EXTRA + VLAN_TAG + PAYLOAD + CRC \hideinitializer */ + +#define EMAC_LINK_DOWN 0UL /*!< Ethernet link is down \hideinitializer */ +#define EMAC_LINK_100F 1UL /*!< Ethernet link is 100Mbps full duplex \hideinitializer */ +#define EMAC_LINK_100H 2UL /*!< Ethernet link is 100Mbps half duplex \hideinitializer */ +#define EMAC_LINK_10F 3UL /*!< Ethernet link is 10Mbps full duplex \hideinitializer */ +#define EMAC_LINK_10H 4UL /*!< Ethernet link is 10Mbps half duplex \hideinitializer */ + +/*@}*/ /* end of group EMAC_EXPORTED_CONSTANTS */ + + +/** Tx/Rx buffer descriptor structure */ +typedef struct +{ + uint32_t u32Status1; /*!< Status word 1 */ + uint32_t u32Data; /*!< Pointer to data buffer */ + uint32_t u32Status2; /*!< Status word 2 */ + uint32_t u32Next; /*!< Pointer to next descriptor */ + uint32_t u32Backup1; /*!< For backup descriptor fields over written by time stamp */ + uint32_t u32Backup2; /*!< For backup descriptor fields over written by time stamp */ +} EMAC_DESCRIPTOR_T; + +/** Tx/Rx buffer structure */ +typedef struct +{ + uint8_t au8Buf[EMAC_MAX_PKT_SIZE]; +} EMAC_FRAME_T; + +typedef struct +{ + EMAC_T *psEmac; + + uint32_t u32TxDescSize; + uint32_t u32RxDescSize; + + EMAC_DESCRIPTOR_T *psRXDescs; + EMAC_FRAME_T *psRXFrames; + EMAC_DESCRIPTOR_T *psTXDescs; + EMAC_FRAME_T *psTXFrames; + + EMAC_DESCRIPTOR_T *psCurrentTxDesc; + EMAC_DESCRIPTOR_T *psNextTxDesc; + EMAC_DESCRIPTOR_T *psCurrentRxDesc; + +} EMAC_MEMMGR_T; + +/** @addtogroup EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions + @{ +*/ + + +/** + * @brief Enable EMAC Tx function + * @param None + * @return None + * \hideinitializer + */ +#define EMAC_ENABLE_TX(EMAC) (EMAC->CTL |= EMAC_CTL_TXON_Msk) + + +/** + * @brief Enable EMAC Rx function + * @param The pointer of the specified EMAC module + * @return None + * \hideinitializer + */ +#define EMAC_ENABLE_RX(EMAC) do{EMAC->CTL |= EMAC_CTL_RXON_Msk; EMAC->RXST = 0;}while(0) + +/** + * @brief Disable EMAC Tx function + * @param The pointer of the specified EMAC module + * @return None + * \hideinitializer + */ +#define EMAC_DISABLE_TX(EMAC) (EMAC->CTL &= ~EMAC_CTL_TXON_Msk) + + +/** + * @brief Disable EMAC Rx function + * @param The pointer of the specified EMAC module + * @return None + * \hideinitializer + */ +#define EMAC_DISABLE_RX(EMAC) (EMAC->CTL &= ~EMAC_CTL_RXON_Msk) + +/** + * @brief Enable EMAC Magic Packet Wakeup function + * @param The pointer of the specified EMAC module + * @return None + * \hideinitializer + */ +#define EMAC_ENABLE_MAGIC_PKT_WAKEUP(EMAC) (EMAC->CTL |= EMAC_CTL_WOLEN_Msk) + +/** + * @brief Disable EMAC Magic Packet Wakeup function + * @param The pointer of the specified EMAC module + * @return None + * \hideinitializer + */ +#define EMAC_DISABLE_MAGIC_PKT_WAKEUP(EMAC) (EMAC->CTL &= ~EMAC_CTL_WOLEN_Msk) + +/** + * @brief Enable EMAC to receive broadcast packets + * @param The pointer of the specified EMAC module + * @return None + * \hideinitializer + */ +#define EMAC_ENABLE_RECV_BCASTPKT(EMAC) (EMAC->CAMCTL |= EMAC_CAMCTL_ABP_Msk) + +/** + * @brief Disable EMAC to receive broadcast packets + * @param The pointer of the specified EMAC module + * @return None + * \hideinitializer + */ +#define EMAC_DISABLE_RECV_BCASTPKT(EMAC) (EMAC->CAMCTL &= ~EMAC_CAMCTL_ABP_Msk) + +/** + * @brief Enable EMAC to receive multicast packets + * @param The pointer of the specified EMAC module + * @return None + * \hideinitializer + */ +#define EMAC_ENABLE_RECV_MCASTPKT(EMAC) (EMAC->CAMCTL |= EMAC_CAMCTL_AMP_Msk) + +/** + * @brief Disable EMAC Magic Packet Wakeup function + * @param The pointer of the specified EMAC module + * @return None + * \hideinitializer + */ +#define EMAC_DISABLE_RECV_MCASTPKT(EMAC) (EMAC->CAMCTL &= ~EMAC_CAMCTL_AMP_Msk) + +/** + * @brief Check if EMAC time stamp alarm interrupt occurred or not + * @param The pointer of the specified EMAC module + * @return If time stamp alarm interrupt occurred or not + * @retval 0 Alarm interrupt does not occur + * @retval 1 Alarm interrupt occurred + * \hideinitializer + */ +#define EMAC_GET_ALARM_FLAG(EMAC) (EMAC->INTSTS & EMAC_INTSTS_TSALMIF_Msk ? 1 : 0) + +/** + * @brief Clear EMAC time stamp alarm interrupt flag + * @param The pointer of the specified EMAC module + * @return None + * \hideinitializer + */ +#define EMAC_CLR_ALARM_FLAG(EMAC) (EMAC->INTSTS = EMAC_INTSTS_TSALMIF_Msk) + +/** + * @brief Trigger EMAC Rx function + * @param The pointer of the specified EMAC module + * @return None + */ +#define EMAC_TRIGGER_RX(EMAC) do{EMAC->RXST = 0UL;}while(0) + +/** + * @brief Trigger EMAC Tx function + * @param The pointer of the specified EMAC module + * @return None + */ +#define EMAC_TRIGGER_TX(EMAC) do{EMAC->TXST = 0UL;}while(0) + +/** + * @brief Enable specified EMAC interrupt + * + * @param[in] EMAC The pointer of the specified EMAC module + * @param[in] u32eIntSel Interrupt type select + * - \ref EMAC_INTEN_RXIEN_Msk : Receive + * - \ref EMAC_INTEN_CRCEIEN_Msk : CRC Error + * - \ref EMAC_INTEN_RXOVIEN_Msk : Receive FIFO Overflow + * - \ref EMAC_INTEN_LPIEN_Msk : Long Packet + * - \ref EMAC_INTEN_RXGDIEN_Msk : Receive Good + * - \ref EMAC_INTEN_ALIEIEN_Msk : Alignment Error + * - \ref EMAC_INTEN_RPIEN_Msk : Runt Packet + * - \ref EMAC_INTEN_MPCOVIEN_Msk : Miss Packet Counter Overrun + * - \ref EMAC_INTEN_MFLEIEN_Msk : Maximum Frame Length Exceed + * - \ref EMAC_INTEN_DENIEN_Msk : DMA Early Notification + * - \ref EMAC_INTEN_RDUIEN_Msk : Receive Descriptor Unavailable + * - \ref EMAC_INTEN_RXBEIEN_Msk : Receive Bus Error + * - \ref EMAC_INTEN_CFRIEN_Msk : Control Frame Receive + * - \ref EMAC_INTEN_WOLIEN_Msk : Wake on LAN Interrupt + * - \ref EMAC_INTEN_TXIEN_Msk : Transmit + * - \ref EMAC_INTEN_TXUDIEN_Msk : Transmit FIFO Underflow + * - \ref EMAC_INTEN_TXCPIEN_Msk : Transmit Completion + * - \ref EMAC_INTEN_EXDEFIEN_Msk : Defer Exceed + * - \ref EMAC_INTEN_NCSIEN_Msk : No Carrier Sense + * - \ref EMAC_INTEN_TXABTIEN_Msk : Transmit Abort + * - \ref EMAC_INTEN_LCIEN_Msk : Late Collision + * - \ref EMAC_INTEN_TDUIEN_Msk : Transmit Descriptor Unavailable + * - \ref EMAC_INTEN_TXBEIEN_Msk : Transmit Bus Error + * - \ref EMAC_INTEN_TSALMIEN_Msk : Time Stamp Alarm + * + * @return None + * + * @details This macro enable specified EMAC interrupt. + * \hideinitializer + */ +#define EMAC_ENABLE_INT(EMAC, u32eIntSel) ((EMAC)->INTEN |= (u32eIntSel)) + +/** + * @brief Disable specified EMAC interrupt + * + * @param[in] emac The pointer of the specified EMAC module + * @param[in] u32eIntSel Interrupt type select + * - \ref EMAC_INTEN_RXIEN_Msk : Receive + * - \ref EMAC_INTEN_CRCEIEN_Msk : CRC Error + * - \ref EMAC_INTEN_RXOVIEN_Msk : Receive FIFO Overflow + * - \ref EMAC_INTEN_LPIEN_Msk : Long Packet + * - \ref EMAC_INTEN_RXGDIEN_Msk : Receive Good + * - \ref EMAC_INTEN_ALIEIEN_Msk : Alignment Error + * - \ref EMAC_INTEN_RPIEN_Msk : Runt Packet + * - \ref EMAC_INTEN_MPCOVIEN_Msk : Miss Packet Counter Overrun + * - \ref EMAC_INTEN_MFLEIEN_Msk : Maximum Frame Length Exceed + * - \ref EMAC_INTEN_DENIEN_Msk : DMA Early Notification + * - \ref EMAC_INTEN_RDUIEN_Msk : Receive Descriptor Unavailable + * - \ref EMAC_INTEN_RXBEIEN_Msk : Receive Bus Error + * - \ref EMAC_INTEN_CFRIEN_Msk : Control Frame Receive + * - \ref EMAC_INTEN_WOLIEN_Msk : Wake on LAN Interrupt + * - \ref EMAC_INTEN_TXIEN_Msk : Transmit + * - \ref EMAC_INTEN_TXUDIEN_Msk : Transmit FIFO Underflow + * - \ref EMAC_INTEN_TXCPIEN_Msk : Transmit Completion + * - \ref EMAC_INTEN_EXDEFIEN_Msk : Defer Exceed + * - \ref EMAC_INTEN_NCSIEN_Msk : No Carrier Sense + * - \ref EMAC_INTEN_TXABTIEN_Msk : Transmit Abort + * - \ref EMAC_INTEN_LCIEN_Msk : Late Collision + * - \ref EMAC_INTEN_TDUIEN_Msk : Transmit Descriptor Unavailable + * - \ref EMAC_INTEN_TXBEIEN_Msk : Transmit Bus Error + * - \ref EMAC_INTEN_TSALMIEN_Msk : Time Stamp Alarm + * + * @return None + * + * @details This macro disable specified EMAC interrupt. + * \hideinitializer + */ +#define EMAC_DISABLE_INT(EMAC, u32eIntSel) ((EMAC)->INTEN &= ~ (u32eIntSel)) + +/** + * @brief Get specified interrupt flag/status + * + * @param[in] emac The pointer of the specified EMAC module + * @param[in] u32eIntTypeFlag Interrupt Type Flag, should be + * - \ref EMAC_INTSTS_RXIF_Msk : Receive + * - \ref EMAC_INTSTS_CRCEIF_Msk : CRC Error + * - \ref EMAC_INTSTS_RXOVIF_Msk : Receive FIFO Overflow + * - \ref EMAC_INTSTS_LPIF_Msk : Long Packet + * - \ref EMAC_INTSTS_RXGDIF_Msk : Receive Good + * - \ref EMAC_INTSTS_ALIEIF_Msk : Alignment Error + * - \ref EMAC_INTSTS_RPIF_Msk : Runt Packet + * - \ref EMAC_INTSTS_MPCOVIF_Msk : Missed Packet Counter + * - \ref EMAC_INTSTS_MFLEIF_Msk : Maximum Frame Length Exceed + * - \ref EMAC_INTSTS_DENIF_Msk : DMA Early Notification + * - \ref EMAC_INTSTS_RDUIF_Msk : Receive Descriptor Unavailable + * - \ref EMAC_INTSTS_RXBEIF_Msk : Receive Bus Error + * - \ref EMAC_INTSTS_CFRIF_Msk : Control Frame Receive + * - \ref EMAC_INTSTS_WOLIF_Msk : Wake on LAN + * - \ref EMAC_INTSTS_TXIF_Msk : Transmit + * - \ref EMAC_INTSTS_TXUDIF_Msk : Transmit FIFO Underflow + * - \ref EMAC_INTSTS_TXCPIF_Msk : Transmit Completion + * - \ref EMAC_INTSTS_EXDEFIF_Msk : Defer Exceed + * - \ref EMAC_INTSTS_NCSIF_Msk : No Carrier Sense + * - \ref EMAC_INTSTS_TXABTIF_Msk : Transmit Abort + * - \ref EMAC_INTSTS_LCIF_Msk : Late Collision + * - \ref EMAC_INTSTS_TDUIF_Msk : Transmit Descriptor Unavailable + * - \ref EMAC_INTSTS_TXBEIF_Msk : Transmit Bus Error + * - \ref EMAC_INTSTS_TSALMIF_Msk : Time Stamp Alarm + * + * @return None + * + * @details This macro get specified interrupt flag or interrupt indicator status. + * \hideinitializer + */ +#define EMAC_GET_INT_FLAG(EMAC, u32eIntTypeFlag) (((EMAC)->INTSTS & (u32eIntTypeFlag))?1:0) + +/** + * @brief Clear specified interrupt flag/status + * + * @param[in] emac The pointer of the specified EMAC module + * @param[in] u32eIntTypeFlag Interrupt Type Flag, should be + * - \ref EMAC_INTSTS_RXIF_Msk : Receive + * - \ref EMAC_INTSTS_CRCEIF_Msk : CRC Error + * - \ref EMAC_INTSTS_RXOVIF_Msk : Receive FIFO Overflow + * - \ref EMAC_INTSTS_LPIF_Msk : Long Packet + * - \ref EMAC_INTSTS_RXGDIF_Msk : Receive Good + * - \ref EMAC_INTSTS_ALIEIF_Msk : Alignment Error + * - \ref EMAC_INTSTS_RPIF_Msk : Runt Packet + * - \ref EMAC_INTSTS_MPCOVIF_Msk : Missed Packet Counter + * - \ref EMAC_INTSTS_MFLEIF_Msk : Maximum Frame Length Exceed + * - \ref EMAC_INTSTS_DENIF_Msk : DMA Early Notification + * - \ref EMAC_INTSTS_RDUIF_Msk : Receive Descriptor Unavailable + * - \ref EMAC_INTSTS_RXBEIF_Msk : Receive Bus Error + * - \ref EMAC_INTSTS_CFRIF_Msk : Control Frame Receive + * - \ref EMAC_INTSTS_WOLIF_Msk : Wake on LAN + * - \ref EMAC_INTSTS_TXIF_Msk : Transmit + * - \ref EMAC_INTSTS_TXUDIF_Msk : Transmit FIFO Underflow + * - \ref EMAC_INTSTS_TXCPIF_Msk : Transmit Completion + * - \ref EMAC_INTSTS_EXDEFIF_Msk : Defer Exceed + * - \ref EMAC_INTSTS_NCSIF_Msk : No Carrier Sense + * - \ref EMAC_INTSTS_TXABTIF_Msk : Transmit Abort + * - \ref EMAC_INTSTS_LCIF_Msk : Late Collision + * - \ref EMAC_INTSTS_TDUIF_Msk : Transmit Descriptor Unavailable + * - \ref EMAC_INTSTS_TXBEIF_Msk : Transmit Bus Error + * - \ref EMAC_INTSTS_TSALMIF_Msk : Time Stamp Alarm + * + * @retval 0 The specified interrupt is not happened. + * 1 The specified interrupt is happened. + * + * @details This macro clear specified interrupt flag or interrupt indicator status. + * \hideinitializer + */ +#define EMAC_CLEAR_INT_FLAG(EMAC, u32eIntTypeFlag) ((EMAC)->INTSTS |= (u32eIntTypeFlag)) +#define EMAC_CLEAR_ALL_INT_FLAG(EMAC) ((EMAC)->INTSTS |= (EMAC)->INTSTS) + + +void EMAC_Open(EMAC_MEMMGR_T *psMemMgr, uint8_t *pu8MacAddr); +void EMAC_Close(EMAC_T *EMAC); +void EMAC_SetMacAddr(EMAC_T *EMAC, uint8_t *pu8MacAddr); +void EMAC_EnableCamEntry(EMAC_T *EMAC, uint32_t u32Entry, uint8_t pu8MacAddr[]); +void EMAC_DisableCamEntry(EMAC_T *EMAC, uint32_t u32Entry); + +uint32_t EMAC_RecvPkt(EMAC_MEMMGR_T *psMemMgr, uint8_t *pu8Data, uint32_t *pu32Size); +uint32_t EMAC_RecvPktTS(EMAC_MEMMGR_T *psMemMgr, uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec); +void EMAC_RecvPktDone(EMAC_MEMMGR_T *psMemMgr); + +uint32_t EMAC_SendPkt(EMAC_MEMMGR_T *psMemMgr, uint8_t *pu8Data, uint32_t u32Size); +uint32_t EMAC_SendPktDone(EMAC_MEMMGR_T *psMemMgr); +uint32_t EMAC_SendPktDoneTS(EMAC_MEMMGR_T *psMemMgr, uint32_t *pu32Sec, uint32_t *pu32Nsec); + +void EMAC_EnableTS(EMAC_T *EMAC, uint32_t u32Sec, uint32_t u32Nsec); +void EMAC_DisableTS(EMAC_T *EMAC); +void EMAC_GetTime(EMAC_T *EMAC, uint32_t *pu32Sec, uint32_t *pu32Nsec); +void EMAC_SetTime(EMAC_T *EMAC, uint32_t u32Sec, uint32_t u32Nsec); +void EMAC_UpdateTime(EMAC_T *EMAC, uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec); +void EMAC_EnableAlarm(EMAC_T *EMAC, uint32_t u32Sec, uint32_t u32Nsec); +void EMAC_DisableAlarm(EMAC_T *EMAC); + +uint32_t EMAC_CheckLinkStatus(EMAC_T *EMAC); + +void EMAC_Reset(EMAC_T *EMAC); +void EMAC_PhyInit(EMAC_T *EMAC); +int32_t EMAC_FillCamEntry(EMAC_T *EMAC, uint8_t pu8MacAddr[]); +uint8_t *EMAC_ClaimFreeTXBuf(EMAC_MEMMGR_T *psMemMgr); +uint32_t EMAC_GetAvailRXBufSize(EMAC_MEMMGR_T *psMemMgr, uint8_t **ppuDataBuf); +uint32_t EMAC_SendPktWoCopy(EMAC_MEMMGR_T *psMemMgr, uint32_t u32Size); +void EMAC_RecvPktDoneWoRxTrigger(EMAC_MEMMGR_T *psMemMgr); + +/*@}*/ /* end of group EMAC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group EMAC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_EMAC_H__ */ + +/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_etimer.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_etimer.h new file mode 100644 index 0000000000..4176a1719b --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_etimer.h @@ -0,0 +1,717 @@ +/**************************************************************************//** + * @file etimer.h + * @brief N9H30 series ETIMER driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_ETIMER_H__ +#define __NU_ETIMER_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "N9H30.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_ETIMER_Driver ETIMER Driver + @{ +*/ + +/** @addtogroup N9H30_ETIMER_EXPORTED_CONSTANTS ETIMER Exported Constants + @{ +*/ + +#define ETIMER_ONESHOT_MODE (0UL) /*!< Timer working in one shot mode */ +#define ETIMER_PERIODIC_MODE (1UL << 4) /*!< Timer working in periodic mode */ +#define ETIMER_TOGGLE_MODE (2UL << 4) /*!< Timer working in toggle mode */ +#define ETIMER_CONTINUOUS_MODE (3UL << 4) /*!< Timer working in continuous mode */ + +#define ETIMER_CAPTURE_FREE_COUNTING_MODE (0UL) /*!< Free counting mode */ +#define ETIMER_CAPTURE_TRIGGER_COUNTING_MODE (1UL << 20) /*!< Trigger counting mode */ +#define ETIMER_CAPTURE_COUNTER_RESET_MODE (1UL << 17) /*!< Counter reset mode */ + +#define ETIMER_CAPTURE_FALLING_EDGE (0UL) /*!< Falling edge trigger timer capture */ +#define ETIMER_CAPTURE_RISING_EDGE (1UL << 18) /*!< Rising edge trigger timer capture */ +#define ETIMER_CAPTURE_FALLING_THEN_RISING_EDGE (2UL << 18) /*!< Falling edge then rising edge trigger timer capture */ +#define ETIMER_CAPTURE_RISING_THEN_FALLING_EDGE (3UL << 18) /*!< Rising edge then falling edge trigger timer capture */ + +#define ETIMER_TIMEOUT_TRIGGER (0UL) /*!< Timer timeout trigger other modules */ +#define ETIMER_CAPTURE_TRIGGER (1UL << 11) /*!< Timer capture trigger other modules */ + +#define ETIMER_COUNTER_RISING_EDGE (1UL << 13) /*!< Counter increase on rising edge */ +#define ETIMER_COUNTER_FALLING_EDGE (0UL) /*!< Counter increase on falling edge */ + +/*@}*/ /* end of group ETIMER_EXPORTED_CONSTANTS */ + +/** @addtogroup N9H30_ETIMER_EXPORTED_FUNCTIONS ETIMER Exported Functions + @{ +*/ + +/** + * @brief This macro is used to set new Timer compared value + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @param[in] u32Value Timer compare value. Valid values are between 2 to 0xFFFFFF + * @return None + * \hideinitializer + */ +#define ETIMER_SET_CMP_VALUE(timer, u32Value) \ + do{\ + if((timer) == 0) {\ + outpw(REG_ETMR0_CMPR, u32Value);\ + } else if((timer) == 1) {\ + outpw(REG_ETMR1_CMPR, u32Value);\ + } else if((timer) == 2) {\ + outpw(REG_ETMR2_CMPR, u32Value);\ + } else {\ + outpw(REG_ETMR3_CMPR, u32Value);\ + }\ + }while(0) + +/** + * @brief This macro is used to set new Timer prescale value + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @param[in] u32Value Timer prescale value. Valid values are between 0 to 0xFF + * @return None + * @note Clock input is divided by (prescale + 1) before it is fed into timer + * \hideinitializer + */ +#define ETIMER_SET_PRESCALE_VALUE(timer, u32Value) \ + do{\ + if((timer) == 0) {\ + outpw(REG_ETMR0_PRECNT, u32Value);\ + } else if((timer) == 1) {\ + outpw(REG_ETMR1_PRECNT, u32Value);\ + } else if((timer) == 2) {\ + outpw(REG_ETMR2_PRECNT, u32Value);\ + } else {\ + outpw(REG_ETMR3_PRECNT, u32Value);\ + }\ + }while(0) + +/** +* @brief Select Timer operating mode +* +* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3. +* @param[in] u32OpMode Operation mode. Possible options are +* - \ref ETIMER_ONESHOT_MODE +* - \ref ETIMER_PERIODIC_MODE +* - \ref ETIMER_TOGGLE_MODE +* - \ref ETIMER_CONTINUOUS_MODE +* +* @return None +* \hideinitializer +*/ +#define ETIMER_SET_OPMODE(timer, u32OpMode) \ + do{\ + if((timer) == 0) {\ + outpw(REG_ETMR0_CTL, (inpw(REG_ETMR0_CTL)&~0x30) | u32OpMode);\ + } else if((timer) == 1) {\ + outpw(REG_ETMR1_CTL, (inpw(REG_ETMR1_CTL)&~0x30) | u32OpMode);\ + } else if((timer) == 2) {\ + outpw(REG_ETMR2_CTL, (inpw(REG_ETMR2_CTL)&~0x30) | u32OpMode);\ + } else {\ + outpw(REG_ETMR3_CTL, (inpw(REG_ETMR3_CTL)&~0x30) | u32OpMode);\ + }\ + }while(0) + +/* + * @brief This macro is used to check if specify Timer is inactive or active + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return timer is activate or inactivate + * @retval 0 Timer 24-bit up counter is inactive + * @retval 1 Timer 24-bit up counter is active + * \hideinitializer + */ +static __inline int ETIMER_Is_Active(UINT timer) +{ + int reg; + + if (timer == 0) + { + reg = inpw(REG_ETMR0_CTL); + } + else if (timer == 1) + { + reg = inpw(REG_ETMR1_CTL); + } + else if (timer == 2) + { + reg = inpw(REG_ETMR2_CTL); + } + else + { + reg = inpw(REG_ETMR3_CTL); + } + return reg & 0x80 ? 1 : 0; +} + +/** + * @brief This function is used to start Timer counting + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_Start(UINT timer) +{ + + if (timer == 0) + { + outpw(REG_ETMR0_CTL, inpw(REG_ETMR0_CTL) | 1); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, inpw(REG_ETMR1_CTL) | 1); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, inpw(REG_ETMR2_CTL) | 1); + } + else + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) | 1); + } +} + +/** + * @brief This function is used to stop Timer counting + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_Stop(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_CTL, inpw(REG_ETMR0_CTL) & ~1); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, inpw(REG_ETMR1_CTL) & ~1); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, inpw(REG_ETMR2_CTL) & ~1); + } + else + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) & ~1); + } +} + +/** + * @brief This function is used to enable the Timer wake-up function + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + * @note To wake the system from power down mode, timer clock source must be ether LXT or LIRC + */ +static __inline void ETIMER_EnableWakeup(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_CTL, inpw(REG_ETMR0_CTL) | 4); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, inpw(REG_ETMR1_CTL) | 4); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, inpw(REG_ETMR2_CTL) | 4); + } + else + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) | 4); + } +} + +/** + * @brief This function is used to disable the Timer wake-up function + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_DisableWakeup(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_CTL, inpw(REG_ETMR0_CTL) & ~4); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, inpw(REG_ETMR1_CTL) & ~4); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, inpw(REG_ETMR2_CTL) & ~4); + } + else + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) & ~4); + } +} + + +/** + * @brief This function is used to enable the capture pin detection de-bounce function. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_EnableCaptureDebounce(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_CTL, inpw(REG_ETMR0_CTL) | 0x400000); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, inpw(REG_ETMR1_CTL) | 0x400000); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, inpw(REG_ETMR2_CTL) | 0x400000); + } + else + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) | 0x400000); + } +} + +/** + * @brief This function is used to disable the capture pin detection de-bounce function. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_DisableCaptureDebounce(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_CTL, inpw(REG_ETMR0_CTL) & ~0x400000); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, inpw(REG_ETMR1_CTL) & ~0x400000); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, inpw(REG_ETMR2_CTL) & ~0x400000); + } + else + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) & ~0x400000); + } +} + + +/** + * @brief This function is used to enable the Timer time-out interrupt function. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_EnableInt(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_IER, inpw(REG_ETMR0_IER) | 1); + } + else if (timer == 1) + { + outpw(REG_ETMR1_IER, inpw(REG_ETMR1_IER) | 1); + } + else if (timer == 2) + { + outpw(REG_ETMR2_IER, inpw(REG_ETMR2_IER) | 1); + } + else + { + outpw(REG_ETMR3_IER, inpw(REG_ETMR3_IER) | 1); + } +} + +/** + * @brief This function is used to disable the Timer time-out interrupt function. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_DisableInt(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_IER, inpw(REG_ETMR0_IER) & ~1); + } + else if (timer == 1) + { + outpw(REG_ETMR1_IER, inpw(REG_ETMR1_IER) & ~1); + } + else if (timer == 2) + { + outpw(REG_ETMR2_IER, inpw(REG_ETMR2_IER) & ~1); + } + else + { + outpw(REG_ETMR3_IER, inpw(REG_ETMR3_IER) & ~1); + } +} + +/** + * @brief This function is used to enable the Timer capture trigger interrupt function. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_EnableCaptureInt(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_IER, inpw(REG_ETMR0_IER) | 2); + } + else if (timer == 1) + { + outpw(REG_ETMR1_IER, inpw(REG_ETMR1_IER) | 2); + } + else if (timer == 2) + { + outpw(REG_ETMR2_IER, inpw(REG_ETMR2_IER) | 2); + } + else + { + outpw(REG_ETMR3_IER, inpw(REG_ETMR3_IER) | 2); + } +} + +/** + * @brief This function is used to disable the Timer capture trigger interrupt function. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_DisableCaptureInt(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_IER, inpw(REG_ETMR0_IER) & ~2); + } + else if (timer == 1) + { + outpw(REG_ETMR1_IER, inpw(REG_ETMR1_IER) & ~2); + } + else if (timer == 2) + { + outpw(REG_ETMR2_IER, inpw(REG_ETMR2_IER) & ~2); + } + else + { + outpw(REG_ETMR3_IER, inpw(REG_ETMR3_IER) & ~2); + } +} + +/** + * @brief This function indicates Timer time-out interrupt occurred or not. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return Timer time-out interrupt occurred or not + * @retval 0 Timer time-out interrupt did not occur + * @retval 1 Timer time-out interrupt occurred + */ +static __inline UINT ETIMER_GetIntFlag(UINT timer) +{ + int reg; + + if (timer == 0) + { + reg = inpw(REG_ETMR0_ISR); + } + else if (timer == 1) + { + reg = inpw(REG_ETMR1_ISR); + } + else if (timer == 2) + { + reg = inpw(REG_ETMR2_ISR); + } + else + { + reg = inpw(REG_ETMR3_ISR); + } + return reg & 1; +} + +/** + * @brief This function clears the Timer time-out interrupt flag. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_ClearIntFlag(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_ISR, 1); + } + else if (timer == 1) + { + outpw(REG_ETMR1_ISR, 1); + } + else if (timer == 2) + { + outpw(REG_ETMR2_ISR, 1); + } + else + { + outpw(REG_ETMR3_ISR, 1); + } +} + +/** + * @brief This function indicates Timer capture interrupt occurred or not. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return Timer capture interrupt occurred or not + * @retval 0 Timer capture interrupt did not occur + * @retval 1 Timer capture interrupt occurred + */ +static __inline UINT ETIMER_GetCaptureIntFlag(UINT timer) +{ + int reg; + + if (timer == 0) + { + reg = inpw(REG_ETMR0_ISR); + } + else if (timer == 1) + { + reg = inpw(REG_ETMR1_ISR); + } + else if (timer == 2) + { + reg = inpw(REG_ETMR2_ISR); + } + else + { + reg = inpw(REG_ETMR3_ISR); + } + return (reg & 2) >> 1; +} + +/** + * @brief This function clears the Timer capture interrupt flag. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_ClearCaptureIntFlag(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_ISR, 2); + } + else if (timer == 1) + { + outpw(REG_ETMR1_ISR, 2); + } + else if (timer == 2) + { + outpw(REG_ETMR2_ISR, 2); + } + else + { + outpw(REG_ETMR3_ISR, 2); + } +} + +/** +* @brief This function gets the Timer capture falling edge flag. +* @param[in] timer ETIMER number. Range from 0 ~ 5 +* @return None +*/ +static __inline UINT8 ETIMER_GetCaptureFallingEdgeFlag(UINT timer) +{ + UINT ret; + + if (timer == 0) + { + ret = inpw(REG_ETMR0_ISR); + } + else if (timer == 1) + { + ret = inpw(REG_ETMR1_ISR); + } + else if (timer == 2) + { + ret = inpw(REG_ETMR2_ISR); + } + else + { + ret = inpw(REG_ETMR3_ISR); + } + return (ret & (1 << 6)) >> 6; +} + +/* + * @brief This function indicates Timer has waked up system or not. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return Timer has waked up system or not + * @retval 0 Timer did not wake up system + * @retval 1 Timer wake up system + */ +static __inline UINT ETIMER_GetWakeupFlag(UINT timer) +{ + int reg; + + if (timer == 0) + { + reg = inpw(REG_ETMR0_ISR); + } + else if (timer == 1) + { + reg = inpw(REG_ETMR1_ISR); + } + else if (timer == 2) + { + reg = inpw(REG_ETMR2_ISR); + } + else + { + reg = inpw(REG_ETMR3_ISR); + } + return (reg & 0x10) >> 4; +} + +/** + * @brief This function clears the Timer wakeup interrupt flag. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +static __inline void ETIMER_ClearWakeupFlag(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_ISR, 0x10); + } + else if (timer == 1) + { + outpw(REG_ETMR1_ISR, 0x10); + } + else if (timer == 2) + { + outpw(REG_ETMR2_ISR, 0x10); + } + else + { + outpw(REG_ETMR3_ISR, 0x10); + } +} + +/** + * @brief This function gets the Timer compare value. + * @param[in] timer ETIMER number. Range from 0 ~ 5 + * @return Timer compare data value + */ +static __inline UINT ETIMER_GetCompareData(UINT timer) +{ + + if (timer == 0) + { + return inpw(REG_ETMR0_CMPR); + } + else if (timer == 1) + { + return inpw(REG_ETMR1_CMPR); + } + else if (timer == 2) + { + return inpw(REG_ETMR2_CMPR); + } + else + { + return inpw(REG_ETMR3_CMPR); + } +} + +/** + * @brief This function gets the Timer capture data. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return Timer capture data value + */ +static __inline UINT ETIMER_GetCaptureData(UINT timer) +{ + + if (timer == 0) + { + return inpw(REG_ETMR0_TCAP); + } + else if (timer == 1) + { + return inpw(REG_ETMR1_TCAP); + } + else if (timer == 2) + { + return inpw(REG_ETMR2_TCAP); + } + else + { + return inpw(REG_ETMR3_TCAP); + } +} + +/** + * @brief This function reports the current timer counter value. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return Timer counter value + */ +static __inline UINT ETIMER_GetCounter(UINT timer) +{ + if (timer == 0) + { + return inpw(REG_ETMR0_DR); + } + else if (timer == 1) + { + return inpw(REG_ETMR1_DR); + } + else if (timer == 2) + { + return inpw(REG_ETMR2_DR); + } + else + { + return inpw(REG_ETMR3_DR); + } +} + +static __inline UINT ETIMER_ClearCounter(UINT timer) +{ + if (timer == 0) + { + return outpw(REG_ETMR0_DR, 0); + } + else if (timer == 1) + { + return outpw(REG_ETMR1_DR, 0); + } + else if (timer == 2) + { + return outpw(REG_ETMR2_DR, 0); + } + else + { + return outpw(REG_ETMR3_DR, 0); + } +} +UINT ETIMER_Open(UINT timer, UINT u32Mode, UINT u32Freq); +void ETIMER_Close(UINT timer); +void ETIMER_Delay(UINT timer, UINT u32Usec); +void ETIMER_EnableCapture(UINT timer, UINT u32CapMode, UINT u32Edge); +void ETIMER_DisableCapture(UINT timer); +UINT ETIMER_GetModuleClock(UINT timer); + +/*@}*/ /* end of group N9H30_ETIMER_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_ETIMER_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_ETIMER_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_fmi.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_fmi.h new file mode 100644 index 0000000000..a0b85078fc --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_fmi.h @@ -0,0 +1,315 @@ +/**************************************************************************//** + * @file fmi.h + * @brief N9H30 FMI eMMC driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include + +#ifndef __NU_FMI_H__ +#define __NU_FMI_H__ + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_FMI_Driver FMI Driver + @{ +*/ + + +/** @addtogroup N9H30_FMI_EXPORTED_CONSTANTS FMI Exported Constants + @{ +*/ + +/** + @addtogroup FMI_CONST FMI Bit Field Definition + Constant Definitions for FMI Controller +@{ */ + +#define FMI_DMACTL_DMAEN_Pos (0) /*!< FMI DMACTL: DMAEN Position */ +#define FMI_DMACTL_DMAEN_Msk (0x1ul << FMI_DMACTL_DMAEN_Pos) /*!< FMI DMACTL: DMAEN Mask */ + +#define FMI_DMACTL_DMARST_Pos (1) /*!< FMI DMACTL: DMARST Position */ +#define FMI_DMACTL_DMARST_Msk (0x1ul << FMI_DMACTL_DMARST_Pos) /*!< FMI DMACTL: DMARST Mask */ + +#define FMI_DMACTL_SGEN_Pos (3) /*!< FMI DMACTL: SGEN Position */ +#define FMI_DMACTL_SGEN_Msk (0x1ul << FMI_DMACTL_SGEN_Pos) /*!< FMI DMACTL: SGEN Mask */ + +#define FMI_DMACTL_DMABUSY_Pos (9) /*!< FMI DMACTL: DMABUSY Position */ +#define FMI_DMACTL_DMABUSY_Msk (0x1ul << FMI_DMACTL_DMABUSY_Pos) /*!< FMI DMACTL: DMABUSY Mask */ + +#define FMI_DMASA_ORDER_Pos (0) /*!< FMI DMASA: ORDER Position */ +#define FMI_DMASA_ORDER_Msk (0x1ul << FMI_DMASA_ORDER_Pos) /*!< FMI DMASA: ORDER Mask */ + +#define FMI_DMASA_DMASA_Pos (1) /*!< FMI DMASA: DMASA Position */ +#define FMI_DMASA_DMASA_Msk (0x7ffffffful << FMI_DMASA_DMASA_Pos) /*!< FMI DMASA: DMASA Mask */ + +#define FMI_DMABCNT_BCNT_Pos (0) /*!< FMI DMABCNT: BCNT Position */ +#define FMI_DMABCNT_BCNT_Msk (0x3fffffful << FMI_DMABCNT_BCNT_Pos) /*!< FMI DMABCNT: BCNT Mask */ + +#define FMI_DMAINTEN_ABORTIEN_Pos (0) /*!< FMI DMAINTEN: ABORTIEN Position */ +#define FMI_DMAINTEN_ABORTIEN_Msk (0x1ul << FMI_DMAINTEN_ABORTIEN_Pos) /*!< FMI DMAINTEN: ABORTIEN Mask */ + +#define FMI_DMAINTEN_WEOTIEN_Pos (1) /*!< FMI DMAINTEN: WEOTIEN Position */ +#define FMI_DMAINTEN_WEOTIEN_Msk (0x1ul << FMI_DMAINTEN_WEOTIEN_Pos) /*!< FMI DMAINTEN: WEOTIEN Mask */ + +#define FMI_DMAINTSTS_ABORTIF_Pos (0) /*!< FMI DMAINTSTS: ABORTIF Position */ +#define FMI_DMAINTSTS_ABORTIF_Msk (0x1ul << FMI_DMAINTSTS_ABORTIF_Pos) /*!< FMI DMAINTSTS: ABORTIF Mask */ + +#define FMI_DMAINTSTS_WEOTIF_Pos (1) /*!< FMI DMAINTSTS: WEOTIF Position */ +#define FMI_DMAINTSTS_WEOTIF_Msk (0x1ul << FMI_DMAINTSTS_WEOTIF_Pos) /*!< FMI DMAINTSTS: WEOTIF Mask */ + +#define FMI_CTL_CTLRST_Pos (0) /*!< FMI CTL: CTLRST Position */ +#define FMI_CTL_CTLRST_Msk (0x1ul << FMI_CTL_CTLRST_Pos) /*!< FMI CTL: CTLRST Mask */ + +#define FMI_CTL_EMMCEN_Pos (1) /*!< FMI CTL: EMMCEN Position */ +#define FMI_CTL_EMMCEN_Msk (0x1ul << FMI_CTL_EMMCEN_Pos) /*!< FMI CTL: EMMCEN Mask */ + +#define FMI_CTL_NANDEN_Pos (1) /*!< FMI CTL: NANDEN Position */ +#define FMI_CTL_NANDEN_Msk (0x1ul << FMI_CTL_NANDEN_Pos) /*!< FMI CTL: NANDEN Mask */ + +#define FMI_INTEN_DTAIEN_Pos (0) /*!< FMI INTEN: DTAIEN Position */ +#define FMI_INTEN_DTAIEN_Msk (0x1ul << FMI_INTEN_DTAIEN_Pos) /*!< FMI INTEN: DTAIEN Mask */ + +#define FMI_INTSTS_DTAIF_Pos (0) /*!< FMI INTSTS: DTAIF Position */ +#define FMI_INTSTS_DTAIF_Msk (0x1ul << FMI_INTSTS_DTAIF_Pos) /*!< FMI INTSTS: DTAIF Mask */ + +#define FMI_EMMCCTL_COEN_Pos (0) /*!< FMI EMMCCTL: COEN Position */ +#define FMI_EMMCCTL_COEN_Msk (0x1ul << FMI_EMMCCTL_COEN_Pos) /*!< FMI EMMCCTL: COEN Mask */ + +#define FMI_EMMCCTL_RIEN_Pos (1) /*!< FMI EMMCCTL: RIEN Position */ +#define FMI_EMMCCTL_RIEN_Msk (0x1ul << FMI_EMMCCTL_RIEN_Pos) /*!< FMI EMMCCTL: RIEN Mask */ + +#define FMI_EMMCCTL_DIEN_Pos (2) /*!< FMI EMMCCTL: DIEN Position */ +#define FMI_EMMCCTL_DIEN_Msk (0x1ul << FMI_EMMCCTL_DIEN_Pos) /*!< FMI EMMCCTL: DIEN Mask */ + +#define FMI_EMMCCTL_DOEN_Pos (3) /*!< FMI EMMCCTL: DOEN Position */ +#define FMI_EMMCCTL_DOEN_Msk (0x1ul << FMI_EMMCCTL_DOEN_Pos) /*!< FMI EMMCCTL: DOEN Mask */ + +#define FMI_EMMCCTL_R2EN_Pos (4) /*!< FMI EMMCCTL: R2EN Position */ +#define FMI_EMMCCTL_R2EN_Msk (0x1ul << FMI_EMMCCTL_R2EN_Pos) /*!< FMI EMMCCTL: R2EN Mask */ + +#define FMI_EMMCCTL_CLK74OEN_Pos (5) /*!< FMI EMMCCTL: CLK74OEN Position */ +#define FMI_EMMCCTL_CLK74OEN_Msk (0x1ul << FMI_EMMCCTL_CLK74OEN_Pos) /*!< FMI EMMCCTL: CLK74OEN Mask */ + +#define FMI_EMMCCTL_CLK8OEN_Pos (6) /*!< FMI EMMCCTL: CLK8OEN Position */ +#define FMI_EMMCCTL_CLK8OEN_Msk (0x1ul << FMI_EMMCCTL_CLK8OEN_Pos) /*!< FMI EMMCCTL: CLK8OEN Mask */ + +#define FMI_EMMCCTL_CLKKEEP0_Pos (7) /*!< FMI EMMCCTL: CLKKEEP0 Position */ +#define FMI_EMMCCTL_CLKKEEP0_Msk (0x1ul << FMI_EMMCCTL_CLKKEEP0_Pos) /*!< FMI EMMCCTL: CLKKEEP0 Mask */ + +#define FMI_EMMCCTL_CMDCODE_Pos (8) /*!< FMI EMMCCTL: CMDCODE Position */ +#define FMI_EMMCCTL_CMDCODE_Msk (0x3ful << FMI_EMMCCTL_CMDCODE_Pos) /*!< FMI EMMCCTL: CMDCODE Mask */ + +#define FMI_EMMCCTL_CTLRST_Pos (14) /*!< FMI EMMCCTL: CTLRST Position */ +#define FMI_EMMCCTL_CTLRST_Msk (0x1ul << FMI_EMMCCTL_CTLRST_Pos) /*!< FMI EMMCCTL: CTLRST Mask */ + +#define FMI_EMMCCTL_DBW_Pos (15) /*!< FMI EMMCCTL: DBW Position */ +#define FMI_EMMCCTL_DBW_Msk (0x1ul << FMI_EMMCCTL_DBW_Pos) /*!< FMI EMMCCTL: DBW Mask */ + +#define FMI_EMMCCTL_BLKCNT_Pos (16) /*!< FMI EMMCCTL: BLKCNT Position */ +#define FMI_EMMCCTL_BLKCNT_Msk (0xfful << FMI_EMMCCTL_BLKCNT_Pos) /*!< FMI EMMCCTL: BLKCNT Mask */ + +#define FMI_EMMCCTL_SDNWR_Pos (24) /*!< FMI EMMCCTL: SDNWR Position */ +#define FMI_EMMCCTL_SDNWR_Msk (0xful << FMI_EMMCCTL_SDNWR_Pos) /*!< FMI EMMCCTL: SDNWR Mask */ + +#define FMI_EMMCCMD_ARGUMENT_Pos (0) /*!< FMI EMMCCMD: ARGUMENT Position */ +#define FMI_EMMCCMD_ARGUMENT_Msk (0xfffffffful << FMI_EMMCCMD_ARGUMENT_Pos) /*!< FMI EMMCCMD: ARGUMENT Mask */ + +#define FMI_EMMCINTEN_BLKDIEN_Pos (0) /*!< FMI EMMCINTEN: BLKDIEN Position */ +#define FMI_EMMCINTEN_BLKDIEN_Msk (0x1ul << FMI_EMMCINTEN_BLKDIEN_Pos) /*!< FMI EMMCINTEN: BLKDIEN Mask */ + +#define FMI_EMMCINTEN_CRCIEN_Pos (1) /*!< FMI EMMCINTEN: CRCIEN Position */ +#define FMI_EMMCINTEN_CRCIEN_Msk (0x1ul << FMI_EMMCINTEN_CRCIEN_Pos) /*!< FMI EMMCINTEN: CRCIEN Mask */ + +#define FMI_EMMCINTEN_RTOIEN_Pos (12) /*!< FMI EMMCINTEN: RTOIEN Position */ +#define FMI_EMMCINTEN_RTOIEN_Msk (0x1ul << FMI_EMMCINTEN_RTOIEN_Pos) /*!< FMI EMMCINTEN: RTOIEN Mask */ + +#define FMI_EMMCINTEN_DITOIEN_Pos (13) /*!< FMI EMMCINTEN: DITOIEN Position */ +#define FMI_EMMCINTEN_DITOIEN_Msk (0x1ul << FMI_EMMCINTEN_DITOIEN_Pos) /*!< FMI EMMCINTEN: DITOIEN Mask */ + +#define FMI_EMMCINTSTS_BLKDIF_Pos (0) /*!< FMI EMMCINTSTS: BLKDIF Position */ +#define FMI_EMMCINTSTS_BLKDIF_Msk (0x1ul << FMI_EMMCINTSTS_BLKDIF_Pos) /*!< FMI EMMCINTSTS: BLKDIF Mask */ + +#define FMI_EMMCINTSTS_CRCIF_Pos (1) /*!< FMI EMMCINTSTS: CRCIF Position */ +#define FMI_EMMCINTSTS_CRCIF_Msk (0x1ul << FMI_EMMCINTSTS_CRCIF_Pos) /*!< FMI EMMCINTSTS: CRCIF Mask */ + +#define FMI_EMMCINTSTS_CRC7_Pos (2) /*!< FMI EMMCINTSTS: CRC7 Position */ +#define FMI_EMMCINTSTS_CRC7_Msk (0x1ul << FMI_EMMCINTSTS_CRC7_Pos) /*!< FMI EMMCINTSTS: CRC7 Mask */ + +#define FMI_EMMCINTSTS_CRC16_Pos (3) /*!< FMI EMMCINTSTS: CRC16 Position */ +#define FMI_EMMCINTSTS_CRC16_Msk (0x1ul << FMI_EMMCINTSTS_CRC16_Pos) /*!< FMI EMMCINTSTS: CRC16 Mask */ + +#define FMI_EMMCINTSTS_CRCSTS_Pos (4) /*!< FMI EMMCINTSTS: CRCSTS Position */ +#define FMI_EMMCINTSTS_CRCSTS_Msk (0x7ul << FMI_EMMCINTSTS_CRCSTS_Pos) /*!< FMI EMMCINTSTS: CRCSTS Mask */ + +#define FMI_EMMCINTSTS_DAT0STS_Pos (7) /*!< FMI EMMCINTSTS: DAT0STS Position */ +#define FMI_EMMCINTSTS_DAT0STS_Msk (0x1ul << FMI_EMMCINTSTS_DAT0STS_Pos) /*!< FMI EMMCINTSTS: DAT0STS Mask */ + +#define FMI_EMMCINTSTS_RTOIF_Pos (12) /*!< FMI EMMCINTSTS: RTOIF Position */ +#define FMI_EMMCINTSTS_RTOIF_Msk (0x1ul << FMI_EMMCINTSTS_RTOIF_Pos) /*!< FMI EMMCINTSTS: RTOIF Mask */ + +#define FMI_EMMCINTSTS_DINTOIF_Pos (13) /*!< FMI EMMCINTSTS: DINTOIF Position */ +#define FMI_EMMCINTSTS_DINTOIF_Msk (0x1ul << FMI_EMMCINTSTS_DINTOIF_Pos) /*!< FMI EMMCINTSTS: DINTOIF Mask */ + +#define FMI_EMMCRESP0_RESPTK0_Pos (0) /*!< FMI EMMCRESP0: RESPTK0 Position */ +#define FMI_EMMCRESP0_RESPTK0_Msk (0xfffffffful << FMI_EMMCRESP0_RESPTK0_Pos) /*!< FMI EMMCRESP0: RESPTK0 Mask */ + +#define FMI_EMMCRESP1_RESPTK1_Pos (0) /*!< FMI EMMCRESP1: RESPTK1 Position */ +#define FMI_EMMCRESP1_RESPTK1_Msk (0xfful << FMI_EMMCRESP1_RESPTK1_Pos) /*!< FMI EMMCRESP1: RESPTK1 Mask */ + +#define FMI_EMMCBLEN_BLKLEN_Pos (0) /*!< FMI EMMCBLEN: BLKLEN Position */ +#define FMI_EMMCBLEN_BLKLEN_Msk (0x7fful << FMI_EMMCBLEN_BLKLEN_Pos) /*!< FMI EMMCBLEN: BLKLEN Mask */ + +#define FMI_EMMCTOUT_TOUT_Pos (0) /*!< FMI EMMCTOUT: TOUT Position */ +#define FMI_EMMCTOUT_TOUT_Msk (0xfffffful << FMI_EMMCTOUT_TOUT_Pos) /*!< FMI EMMCTOUT: TOUT Mask */ + +/**@}*/ /* FMI_CONST */ + +//--- define type of SD card or MMC +#define EMMC_TYPE_UNKNOWN 0 /*!< Card Type - Unknoen \hideinitializer */ +#define EMMC_TYPE_SD_HIGH 1 /*!< Card Type - SDH \hideinitializer */ +#define EMMC_TYPE_SD_LOW 2 /*!< Card Type - SD \hideinitializer */ +#define EMMC_TYPE_MMC 3 /*!< Card Type - MMC \hideinitializer */ +#define EMMC_TYPE_EMMC 4 /*!< Card Type - eMMC \hideinitializer */ + +#define EMMC_ERR_ID 0xFFFF0180 /*!< FMI Error ID \hideinitializer */ +#define EMMC_TIMEOUT (EMMC_ERR_ID|0x01) /*!< FMI Error - Timeout \hideinitializer */ +#define EMMC_NO_MEMORY (EMMC_ERR_ID|0x02) /*!< FMI Error - No Memory \hideinitializer */ +/* EMMC error */ +#define EMMC_NO_CARD (EMMC_ERR_ID|0x10) /*!< FMI Error - No card \hideinitializer */ +#define EMMC_ERR_DEVICE (EMMC_ERR_ID|0x11) /*!< FMI Error - device err \hideinitializer */ +#define EMMC_INIT_TIMEOUT (EMMC_ERR_ID|0x12) /*!< FMI Error - init timeout \hideinitializer */ +#define EMMC_SELECT_ERROR (EMMC_ERR_ID|0x13) /*!< FMI Error - select err \hideinitializer */ +#define EMMC_WRITE_PROTECT (EMMC_ERR_ID|0x14) /*!< FMI Error - write protect \hideinitializer */ +#define EMMC_INIT_ERROR (EMMC_ERR_ID|0x15) /*!< FMI Error - init err \hideinitializer */ +#define EMMC_CRC7_ERROR (EMMC_ERR_ID|0x16) /*!< FMI Error - crc7 err \hideinitializer */ +#define EMMC_CRC16_ERROR (EMMC_ERR_ID|0x17) /*!< FMI Error - crc16 err \hideinitializer */ +#define EMMC_CRC_ERROR (EMMC_ERR_ID|0x18) /*!< FMI Error - crc err \hideinitializer */ +#define EMMC_CMD8_ERROR (EMMC_ERR_ID|0x19) /*!< FMI Error - CMD8 err \hideinitializer */ + +#define SD_FREQ 25000 /*!< Unit: kHz. Output 25MHz to SD \hideinitializer */ +#define SDHC_FREQ 50000 /*!< Unit: kHz. Output 50MHz to SDH \hideinitializer */ +#define MMC_FREQ 20000 /*!< Unit: kHz. Output 20MHz to MMC \hideinitializer */ +#define EMMC_FREQ 26000 /*!< Unit: kHz. Output 26MHz to eMMC \hideinitializer */ + +/*@}*/ /* end of group N9H30_FMI_EXPORTED_CONSTANTS */ + +/** @addtogroup N9H30_FMI_EXPORTED_TYPEDEF FMI Exported Type Defines + @{ +*/ +/** \brief Structure type of Card information. + */ +typedef struct eMMC_info_t +{ + unsigned int CardType; /*!< SDHC, SD, or MMC */ + unsigned int RCA; /*!< relative card address */ + unsigned char IsCardInsert; /*!< card insert state */ + unsigned int totalSectorN; /*!< total sector number */ + unsigned int diskSize; /*!< disk size in Kbytes */ + int sectorSize; /*!< sector size in bytes */ +} EMMC_INFO_T; + +/*@}*/ /* end of group N9H30_FMI_EXPORTED_TYPEDEF */ + +/// @cond HIDDEN_SYMBOLS +extern EMMC_INFO_T eMMC; +extern unsigned char volatile _fmi_eMMCDataReady; + +/// @endcond HIDDEN_SYMBOLS + +/** @addtogroup N9H30_FMI_EXPORTED_FUNCTIONS FMI Exported Functions + @{ +*/ + + +/** + * @brief Enable specified interrupt. + * + * @param[in] u32IntMask Interrupt type mask: + * \ref FMI_EMMCINTEN_BLKDIEN_Msk / \ref FMI_EMMCINTEN_CRCIEN_Msk / + * \ref FMI_EMMCINTEN_RTOIEN_Msk / \ref FMI_EMMCINTEN_DITOIEN_Msk / + * + * @return None. + * \hideinitializer + */ +#define FMI_EMMC_ENABLE_INT(u32IntMask) (outpw(REG_FMI_EMMCINTEN, inpw(REG_FMI_EMMCINTEN)|(u32IntMask))) + +/** + * @brief Disable specified interrupt. + * + * @param[in] u32IntMask Interrupt type mask: + * \ref FMI_EMMCINTEN_BLKDIEN_Msk / \ref FMI_EMMCINTEN_CRCIEN_Msk / + * \ref FMI_EMMCINTEN_RTOIEN_Msk / \ref FMI_EMMCINTEN_DITOIEN_Msk / + * + * @return None. + * \hideinitializer + */ +#define FMI_EMMC_DISABLE_INT(u32IntMask) (outpw(REG_FMI_EMMCINTEN, inpw(REG_FMI_EMMCINTEN) & ~(u32IntMask))) + +/** + * @brief Get specified interrupt flag/status. + * + * @param[in] u32IntMask Interrupt type mask: + * \ref FMI_EMMCINTSTS_BLKDIF_Msk / \ref FMI_EMMCINTSTS_CRCIF_Msk / \ref FMI_EMMCINTSTS_CRC7_Msk / + * \ref FMI_EMMCINTSTS_CRC16_Msk / \ref FMI_EMMCINTSTS_CRCSTS_Msk / \ref FMI_EMMCINTSTS_DAT0STS_Msk / + * \ref FMI_EMMCINTSTS_RTOIF_Msk / \ref FMI_EMMCINTSTS_DINTOIF_Msk / + * + * @return 0 = The specified interrupt is not happened. + * 1 = The specified interrupt is happened. + * \hideinitializer + */ +#define FMI_EMMC_GET_INT_FLAG(u32IntMask) ((inpw(REG_FMI_EMMCINTSTS)&(u32IntMask))?1:0) + + +/** + * @brief Clear specified interrupt flag/status. + * + * @param[in] u32IntMask Interrupt type mask: + * \ref FMI_EMMCINTSTS_BLKDIF_Msk / \ref FMI_EMMCINTSTS_CRCIF_Msk / + * \ref FMI_EMMCINTSTS_RTOIF_Msk / \ref FMI_EMMCINTSTS_DINTOIF_Msk + * + * @return None. + * \hideinitializer + */ +#define FMI_EMMC_CLR_INT_FLAG(u32IntMask) (outpw(REG_FMI_EMMCINTSTS, u32IntMask)) + + +/** + * @brief Check eMMC Card inserted or removed. + * + * @return 1: Card inserted. + * 0: Card removed. + * \hideinitializer + */ +#define FMI_EMMC_IS_CARD_PRESENT() (eMMC.IsCardInsert) + +/** + * @brief Get eMMC Card capacity. + * + * @return eMMC Card capacity. (unit: KByte) + * \hideinitializer + */ +#define FMI_EMMC_GET_CARD_CAPACITY() (eMMC.diskSize) + + +void eMMC_Open(void); +void eMMC_Probe(void); +unsigned int eMMC_Read(unsigned char *pu8BufAddr, unsigned int u32StartSec, unsigned int u32SecCount); +unsigned int eMMC_Write(unsigned char *pu8BufAddr, unsigned int u32StartSec, unsigned int u32SecCount); +void FMI_SetReferenceClock(unsigned int u32Clock); +void eMMC_Open_Disk(void); +void eMMC_Close_Disk(void); + + +/*@}*/ /* end of group N9H30_FMI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_FMI_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#endif //end of __NU_FMI_H__ +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_gpio.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_gpio.h new file mode 100644 index 0000000000..f644ab1229 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_gpio.h @@ -0,0 +1,162 @@ +/**************************************************************************//** +* @file gpio.h +* @version V1.00 +* @brief N9H30 GPIO driver header file +* +* SPDX-License-Identifier: Apache-2.0 +* @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_GPIO_H__ +#define __NU_GPIO_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_GPIO_Driver GPIO Driver + @{ +*/ + +/** @addtogroup N9H30_GPIO_EXPORTED_CONSTANTS GPIO Exported Constants + @{ +*/ + +/*---------------------------------------------------------------------------------------------------------*/ +/* MODE Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +/// @cond HIDDEN_SYMBOLS +#ifndef GPIO_ERR_PORT_BUSY +#define GPIO_ERR_PORT_BUSY -1 +#define GPIO_ERR_UNSUPPORTED -2 +#define GPIO_ERR_BIT_BUSY -3 +#define SUCCESSFUL 0 +#endif +/// @endcond HIDDEN_SYMBOLS + +#define MAX_PORT 10 /*!< GPIO Port Number */ + +#define GPIOA_MASK 0x0000FFFF /*!< GPIO Port A Mask */ +#define GPIOB_MASK 0x0000FFFF /*!< GPIO Port B Mask */ +#define GPIOC_MASK 0x00007FFF /*!< GPIO Port C Mask */ +#define GPIOD_MASK 0x0000FFFF /*!< GPIO Port D Mask */ +#define GPIOE_MASK 0x0000FFFF /*!< GPIO Port E Mask */ +#define GPIOF_MASK 0x0000FFFF /*!< GPIO Port F Mask */ +#define GPIOG_MASK 0x0000FFFF /*!< GPIO Port G Mask */ +#define GPIOH_MASK 0x0000FFFF /*!< GPIO Port H Mask */ +#define GPIOI_MASK 0x0000FFFF /*!< GPIO Port I Mask */ +#define GPIOJ_MASK 0x0000003F /*!< GPIO Port J Mask */ + +/// @cond HIDDEN_SYMBOLS +typedef INT32(*GPIO_CALLBACK)(UINT32 status, UINT32 userData); +typedef INT32(*EINT_CALLBACK)(UINT32 status, UINT32 userData); +/// @endcond HIDDEN_SYMBOLS + +/** \brief Structure type of GPIO_PORT + */ +typedef enum +{ + GPIOA = 0x000, /*!< Port A offset of GPIO base address */ + GPIOB = 0x040, /*!< Port B offset of GPIO base address */ + GPIOC = 0x080, /*!< Port C offset of GPIO base address */ + GPIOD = 0x0C0, /*!< Port D offset of GPIO base address */ + GPIOE = 0x100, /*!< Port E offset of GPIO base address */ + GPIOF = 0x140, /*!< Port F offset of GPIO base address */ + GPIOG = 0x180, /*!< Port G offset of GPIO base address */ + GPIOH = 0x1C0, /*!< Port H offset of GPIO base address */ + GPIOI = 0x200, /*!< Port I offset of GPIO base address */ + GPIOJ = 0x240, /*!< Port J offset of GPIO base address */ +} GPIO_PORT; + +/** \brief Structure type of GPIO_DIR + */ +typedef enum +{ + DIR_INPUT, /*!< GPIO Output mode */ + DIR_OUTPUT /*!< GPIO Input mode */ +} GPIO_DIR; + +/** \brief Structure type of GPIO_PULL + */ +typedef enum +{ + NO_PULL_UP, /*!< GPIO Pull-Up Disable */ + PULL_UP, /*!< GPIO Pull-Up Enable */ + PULL_DOWN /*!< GPIO Pull-Down Enable */ +} GPIO_PULL; + +/** \brief Structure type of GPIO_DRV + */ +typedef enum +{ + DRV_LOW, /*!< GPIO Set to Low */ + DRV_HIGH /*!< GPIO Set to High */ +} GPIO_DRV; + +/** \brief Structure type of GPIO_NIRQ + */ +typedef enum +{ + NIRQ0 = 0, /*!< External interrupt 0 */ + NIRQ1, /*!< External interrupt 1 */ + NIRQ2, /*!< External interrupt 2 */ + NIRQ3, /*!< External interrupt 3 */ + NIRQ4, /*!< External interrupt 4 */ + NIRQ5, /*!< External interrupt 5 */ + NIRQ6, /*!< External interrupt 6 */ + NIRQ7, /*!< External interrupt 7 */ +} GPIO_NIRQ; + +/** \brief Structure type of GPIO_TRIGGER_TYPE + */ +typedef enum +{ + LOW, /*!< Trigger type set low */ + HIGH, /*!< Trigger type set high */ + FALLING, /*!< Trigger type set falling edge */ + RISING, /*!< Trigger type set rising edge */ + BOTH_EDGE /*!< Trigger type set falling edge and rising edge */ +} GPIO_TRIGGER_TYPE; + +/// @cond HIDDEN_SYMBOLS +/// @endcond HIDDEN_SYMBOLS + +/*@}*/ /* end of group N9H30_GPIO_EXPORTED_CONSTANTS */ + + +/** @addtogroup N9H30_GPIO_EXPORTED_FUNCTIONS GPIO Exported Functions + @{ +*/ + +/* General GPIO bit function */ +INT32 GPIO_OpenBit(GPIO_PORT port, UINT32 bit, GPIO_DIR direction, GPIO_PULL pull); +INT32 GPIO_CloseBit(GPIO_PORT port, UINT32 bit); +INT32 GPIO_SetBit(GPIO_PORT port, UINT32 bit); +INT32 GPIO_ClrBit(GPIO_PORT port, UINT32 bit); +INT32 GPIO_ReadBit(GPIO_PORT port, UINT32 bit); +INT32 GPIO_SetBitDir(GPIO_PORT port, UINT32 bit, GPIO_DIR direction); +INT32 GPIO_EnableTriggerType(GPIO_PORT port, UINT32 bit, GPIO_TRIGGER_TYPE triggerType); +INT32 GPIO_DisableTriggerType(GPIO_PORT port, UINT32 bit); + +/* External GPIO interrupt function */ +INT32 GPIO_EnableDebounce(INT32 debounceClkSel); +INT32 GPIO_DisableDebounce(void); + +/*@}*/ /* end of group N9H30_GPIO_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_GPIO_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_GPIO_H__ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_i2c.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_i2c.h new file mode 100644 index 0000000000..ece04bfa83 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_i2c.h @@ -0,0 +1,105 @@ +/**************************************************************************//** +* @file i2c.h +* @brief N9H30 I2C driver header file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_I2C_H__ +#define __NU_I2C_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_I2C_Driver I2C Driver + @{ +*/ + +/** @addtogroup N9H30_I2C_EXPORTED_CONSTANTS I2C Exported Constants + @{ +*/ +/// @cond HIDDEN_SYMBOLS + +/*-----------------------------------------*/ +/* marco, type and constant definitions */ +/*-----------------------------------------*/ +#define I2C_MAX_BUF_LEN 450 + +/*-----------------------------------------*/ +/* global interface variables declarations */ +/*-----------------------------------------*/ +/* + bit map in CMDR +*/ +#define I2C_CMD_START 0x10 +#define I2C_CMD_STOP 0x08 +#define I2C_CMD_READ 0x04 +#define I2C_CMD_WRITE 0x02 +#define I2C_CMD_NACK 0x01 + +/* + for transfer use +*/ +#define I2C_WRITE 0x00 +#define I2C_READ 0x01 + +#define I2C_STATE_NOP 0x00 +#define I2C_STATE_READ 0x01 +#define I2C_STATE_WRITE 0x02 +#define I2C_STATE_PROBE 0x03 + +/* + i2c register offset +*/ +#define I2C_CSR (0x00) /*!< Control and Status Register */ +#define I2C_DIVIDER (0x04) /*!< Clock Prescale Register */ +#define I2C_CMDR (0x08) /*!< Command Register */ +#define I2C_SWR (0x0C) /*!< Software Mode Control Register */ +#define I2C_RxR (0x10) /*!< Data Receive Register */ +#define I2C_TxR (0x14) /*!< Data Transmit Register */ + +/// @endcond HIDDEN_SYMBOLS + +/* + ioctl commands +*/ +#define I2C_IOC_SET_DEV_ADDRESS 0 /*!< Set device slave address */ +#define I2C_IOC_SET_SUB_ADDRESS 1 /*!< Set sub address */ +#define I2C_IOC_SET_SPEED 2 /*!< Set I2C interface speed */ + +/* + error code +*/ +#define I2C_ERR_ID 0xFFFF1100 /*!< I2C library ID */ +#define I2C_ERR_NOERROR (0x00) /*!< No error */ +#define I2C_ERR_LOSTARBITRATION (0x01 | I2C_ERR_ID) /*!< Arbitration lost error */ +#define I2C_ERR_BUSBUSY (0x02 | I2C_ERR_ID) /*!< Bus busy error */ +#define I2C_ERR_NACK (0x03 | I2C_ERR_ID) /*!< data transfer error */ +#define I2C_ERR_SLAVENACK (0x04 | I2C_ERR_ID) /*!< slave not respond after address */ +#define I2C_ERR_NODEV (0x05 | I2C_ERR_ID) /*!< Wrong device */ +#define I2C_ERR_BUSY (0x06 | I2C_ERR_ID) /*!< Device busy */ +#define I2C_ERR_IO (0x07 | I2C_ERR_ID) /*!< Interface not open */ +#define I2C_ERR_NOTTY (0x08 | I2C_ERR_ID) /*!< Command not support */ + +/*@}*/ /* end of group N9H30_I2C_EXPORTED_CONSTANTS */ + +/*@}*/ /* end of group N9H30_I2C_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_I2C_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_i2s.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_i2s.h new file mode 100644 index 0000000000..e7ee11de21 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_i2s.h @@ -0,0 +1,130 @@ +/**************************************************************************//** +* @file i2s.h +* @brief N9H30 I2S driver header file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_I2S_H__ +#define __NU_I2S_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_I2S_Driver I2S Driver + @{ +*/ + +/** @addtogroup N9H30_I2S_EXPORTED_CONSTANTS I2S Exported Constants + @{ +*/ + +#define I2S_ERR_BUSY -1 /*!< Interface is busy */ +#define I2S_ERR_IO -2 /*!< IO contril error */ + +#define I2S_DISABLE 0 /*!< Enable I2S */ +#define I2S_ENABLE 1 /*!< Disable I2S */ + +#define I2S_PLAY 0 /*!< Play I2S audio */ +#define I2S_REC 1 /*!< Reocrd I2S audio */ + +#define PCM_PLAY 0 /*!< Play PCM audio */ +#define PCM_REC 1 /*!< Record PCM audio */ + +#define I2S_SET_PLAY 0 /*!< Start or stop to play */ +#define I2S_START_PLAY 0 /*!< Start to play */ +#define I2S_STOP_PLAY 1 /*!< Stop to play */ + +#define I2S_SET_RECORD 1 /*!< Start or stop to record */ +#define I2S_START_REC 0 /*!< Start to record */ +#define I2S_STOP_REC 1 /*!< Stop to record */ + +#define I2S_SELECT_BLOCK 2 /*!< Select block function */ +#define I2S_BLOCK_I2S 0 /*!< Select I2S function */ +#define I2S_BLOCK_PCM 1 /*!< Select PCM function */ + +#define I2S_SELECT_BIT 3 /*!< Select data bit width */ +#define I2S_BIT_WIDTH_8 0 /*!< 8-bit */ +#define I2S_BIT_WIDTH_16 1 /*!< 16-bit */ +#define I2S_BIT_WIDTH_24 2 /*!< 24-bit */ + +#define I2S_SET_PLAY_DMA_INT_SEL 4 /*!< Select play DMA interrupt request */ +#define I2S_SET_REC_DMA_INT_SEL 5 /*!< Select record DMA interrupt request */ +#define I2S_DMA_INT_END 0 /*!< End of buffer */ +#define I2S_DMA_INT_HALF 1 /*!< Half of buffer */ +#define I2S_DMA_INT_QUARTER 2 /*!< Quarter of buffer */ +#define I2S_DMA_INT_EIGHTH 3 /*!< Eighth of buffer */ + +#define I2S_SET_ZEROCROSS 6 /*!< Enable or disable zero cross function */ +#define I2S_SET_DMACOUNTER 7 /*!< Enable or disable DMA counter function */ + +#define I2S_SET_CHANNEL 8 /*!< Set channel number */ +#define I2S_CHANNEL_P_I2S_ONE 2 /*!< I2S one channel */ +#define I2S_CHANNEL_P_I2S_TWO 3 /*!< I2S two channels */ +#define I2S_CHANNEL_P_PCM_TWO 3 /*!< PCM two slots */ +#define I2S_CHANNEL_P_PCM_TWO_SLOT1 0 /*!< PCM two slots with all slot1 data */ +#define I2S_CHANNEL_P_PCM_TWO_SLOT0 1 /*!< PCM two slots with all slot0 data */ +#define I2S_CHANNEL_P_PCM_ONE_SLOT0 2 /*!< PCM one slot with all slot0 data */ + +#define I2S_CHANNEL_R_I2S_LEFT_PCM_SLOT0 1 /*!< I2S left channel or PCM slot0 */ +#define I2S_CHANNEL_R_I2S_RIGHT_PCM_SLOT1 2 /*!< I2S right channel or PCM slot1 */ +#define I2S_CHANNEL_R_I2S_TWO 3 /*!< I2S two channels */ + +#define I2S_SET_MODE 9 /*!< Select master or slave mode */ +#define I2S_MODE_MASTER 0 /*!< master mode */ +#define I2S_MODE_SLAVE 1 /*!< slave mode */ + +#define I2S_SET_SPLITDATA 10 /*!< Enable or disable split data function */ +#define I2S_SET_DMA_ADDRESS 11 /*!< Set DMA address */ +#define I2S_SET_DMA_LENGTH 12 /*!< Set DMA length */ +#define I2S_GET_DMA_CUR_ADDRESS 13 /*!< Get current DMA address */ + +#define I2S_SET_I2S_FORMAT 14 /*!< Select I2S format */ +#define I2S_FORMAT_I2S 0 /*!< I2S format */ +#define I2S_FORMAT_MSB 1 /*!< MSB foramt */ + +#define I2S_SET_I2S_CALLBACKFUN 15 /*!< Install play or record call-back function */ + +#define I2S_SET_PCMSLOT 16 /*!< Set PCM interface start position of slot */ +#define PCM_SLOT1_IN 0 /*!< Slot-1 in position */ +#define PCM_SLOT1_OUT 1 /*!< Slot-1 out position */ +#define PCM_SLOT2_IN 2 /*!< Slot-2 in position */ +#define PCM_SLOT2_OUT 3 /*!< Slot-2 out position */ + +#define I2S_SET_PCM_FS_PERIOD 17 /*!< Set PCM FS pulse period */ + +/*@}*/ /* end of group N9H30_I2S_EXPORTED_CONSTANTS */ + +/** @addtogroup N9H30_I2S_EXPORTED_FUNCTIONS I2S Exported Functions + @{ +*/ + +int32_t i2sOpen(void); +void i2sClose(void); +void i2sInit(void); +int32_t i2sIoctl(uint32_t cmd, uint32_t arg0, uint32_t arg1); +void i2sSetSampleRate(uint32_t u32SourceClockRate, uint32_t u32SampleRate, uint32_t u32DataBit, uint32_t u32Channel); +void i2sSetMCLKFrequency(uint32_t u32SourceClockRate, uint32_t u32SampleRate); +void i2sSetPCMBCLKFrequency(uint32_t u32SourceClockRate, uint32_t u32Rate); + +/*@}*/ /* end of group N9H30_I2S_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_I2S_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_I2S_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_jpeg.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_jpeg.h new file mode 100644 index 0000000000..4dcb153d41 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_jpeg.h @@ -0,0 +1,398 @@ +/**************************************************************************//** +* @file jpeg.h +* @brief N9H30 JPEG driver header file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_JPEG_H__ +#define __NU_JPEG_H__ + +#include "nu_jpegcodec.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_JPEG_Driver JPEG Driver + @{ +*/ + +/** @addtogroup N9H30_JPEG_EXPORTED_CONSTANTS JPEG Exported Constants + @{ +*/ + + +/// @cond HIDDEN_SYMBOLS +// Define bits mask +#define NVTBIT(start,end) ((0xFFFFFFFFUL >> (31 - start)) & (0xFFFFFFFFUL >>end << end)) +/// @endcond HIDDEN_SYMBOLS + + +//JMCR +#define RESUMEI BIT9 /*!< Resume JPEG Operation for Input On-the-Fly Mode */ +#define RESUMEO BIT8 /*!< Resume JPEG Operation for Output On-the-Fly Mode */ +#define ENC_DEC BIT7 /*!< JPEG Encode/Decode Mode */ +#define WIN_DEC BIT6 /*!< JPEG Window Decode Mode */ +#define PRI BIT5 /*!< Encode Primary Image */ +#define THB BIT4 /*!< Encode Thumbnail Image */ +#define EY422 BIT3 /*!< Encode Image Format */ +#define QT_BUSY BIT2 /*!< Quantization-Table Busy Status (Read-Only) */ +#define ENG_RST BIT1 /*!< Soft Reset JPEG Engine (Except JPEG Control Registers) */ +#define JPG_EN BIT0 /*!< JPEG Engine Operation Control */ + +//JHEADER +#define P_JFIF BIT7 /*!< Primary JPEG Bit-stream Include JFIF Header */ +#define P_HTAB BIT6 /*!< Primary JPEG Bit-stream Include Huffman-Table */ +#define P_QTAB BIT5 /*!< Primary JPEG Bit-stream Include Quantization-Table */ +#define P_DRI BIT4 /*!< Primary JPEG Bit-stream Include Restart Interval */ +#define T_JFIF BIT3 /*!< Thumbnail JPEG Bit-stream Include JFIF Header */ +#define T_HTAB BIT2 /*!< Thumbnail JPEG Bit-stream Include Huffman-Table */ +#define T_QTAB BIT1 /*!< Thumbnail JPEG Bit-stream Include Quantization-Table */ +#define T_DRI BIT0 /*!< Thumbnail JPEG Bit-stream Include Restart Interval */ + +//JITCR +#define Dec_Scatter_Gather BIT18 +#define DEC_OTF BIT17 /*!< Decoder on the fly with VPE */ +#define ARGB8888 BIT16 /*!< ARGB8888 */ +#define PLANAR_ON BIT15 /*!< Packet On */ +#define ORDER BIT14 /*!< Decode Packet Data Order */ +#define RGB_555_565 BIT13 /*!< RGB555 & RGB565 */ +#define ROTATE NVTBIT(12,11) /*!< Encode Image Rotate */ +#define DYUV_MODE NVTBIT(10,8) /*!< Decoded Image YUV Color Format (Read-Only) */ +#define EXIF BIT7 /*!< Encode Quantization-Table & Huffman-Table Header Format Selection */ +#define EY_ONLY BIT6 /*!< Encode Gray-level (Y-component Only) Image */ +#define DHEND BIT5 /*!< Header Decode Complete Stop Enable */ +#define DTHB BIT4 /*!< Decode Thumbnail Image Only */ +#define E3QTAB BIT3 /*!< Numbers of Quantization-Table are Used For Encode */ +#define D3QTAB BIT2 /*!< Numbers of Quantization-Table are Used For Decode (Read-Only) */ +#define ERR_DIS BIT1 /*!< Decode Error Engine Abort */ +#define PDHTAB BIT0 /*!< Programmable Huffman-Table Function For Decode */ + +//JPRIQC +#define P_QADJUST NVTBIT(7,4) /*!< Primary Quantization-Table Adjustment */ +#define P_QVS NVTBIT(3,0) /*!< Primary Quantization-Table Scaling Control */ + +//JTHBQC +#define T_QADJUST NVTBIT(7,4) /*!< Thumbnail Quantization-Table Adjustment */ +#define T_QVS NVTBIT(3,0) /*!< Thumbnail Quantization-Table Scaling Control */ + +//JPRIWH +#define P_HEIGHT NVTBIT(27,16) /*!< Primary Encode Image Height */ +#define P_WIDTH NVTBIT(11,0) /*!< Primary Encode Image Width */ + +//JTHBWH +#define T_HEIGHT NVTBIT(27,16) /*!< Thumbnail Encode Image Height */ +#define T_WIDTH NVTBIT(11,0) /*!< Thumbnail Encode Image Width */ + +//JPRST +#define P_RST NVTBIT(7,0) /*!< Primary Encode Restart Interval Value */ + +//JTRST +#define T_RST NVTBIT(7,0) /*!< Thumbnail Encode Restart Interval Value */ + +//JDECWH +#define DEC_HEIGHT NVTBIT(31,16) /*!< 13-bit Bit Stream Buffer threshold */ +#define DEC_WIDTH NVTBIT(15,0) /*!< 13-bit Header Offset Address */ + +//JINTCR +#define JPG_DOW_INTE BIT28 /*!< Decoding Output Wait Interrupt Enable */ +#define JPG_DOW_INTS BIT24 /*!< Status of Decoding Output Wait */ +#define JPG_WAITI BIT23 /*!< JPEG Input Wait Status (Read-Only) */ +#define JPG_WAITO BIT22 /*!< JPEG Output Wait Status (Read-Only) */ +#define BAbort BIT16 /*!< JPEG Memory Access Error Status (Read-Only) */ +#define CER_INTE BIT15 /*!< Un-complete Capture On-The-Fly Frame Occur Interrupt Enable */ +#define DHE_INTE BIT14 /*!< JPEG Header Decode End Wait Interrupt Enable */ +#define IPW_INTE BIT13 /*!< Input Wait Interrupt Enable */ +#define OPW_INTE BIT12 /*!< Output Wait Interrupt Enable */ +#define ENC_INTE BIT11 /*!< Encode Complete Interrupt Enable */ +#define DEC_INTE BIT10 /*!< Decode Complete Interrupt Enable */ +#define DER_INTE BIT9 /*!< Decode Error Interrupt Enable */ +#define EER_INTE BIT8 /*!< Encode (On-The-Fly) Error Interrupt Enable */ +#define CER_INTS BIT7 /*!< Un-complete Capture On-The-Fly Frame Occur Interrupt Status */ +#define DHE_INTS BIT6 /*!< JPEG Header Decode End Wait Interrupt Status */ +#define IPW_INTS BIT5 /*!< Input Wait Interrupt Status */ +#define OPW_INTS BIT4 /*!< Output Wait Interrupt Status */ +#define ENC_INTS BIT3 /*!< Encode Complete Interrupt Status */ +#define DEC_INTS BIT2 /*!< Decode Complete Interrupt Status */ +#define DER_INTS BIT1 /*!< Decode Error Interrupt Status */ +#define EER_INTS BIT0 /*!< Encode (On-The-Fly) Error Interrupt Status */ + +//JPEG_BSBAD +#define BIST_ST NVTBIT(23,16) /*!< Internal SRAM BIST Status (Read-Only) */ +#define TEST_DOUT NVTBIT(15,8) /*!< Test Data Output (Read-Only) */ +#define TEST_ON BIT7 /*!< Test Enable */ +#define BIST_ON BIT6 /*!< Internal SRAM BIST Mode Enable */ +#define BIST_FINI BIT5 /*!< Internal SRAM BIST Mode Finish (Read-Only) */ +#define BSBAD_BIST_FAIL BIT4 /*!< Internal SRAM BIST Mode Fail (Read-Only) */ +#define TEST_SEL NVTBIT(3,0) /*!< Test Data Selection */ + +//JWINDEC0 +#define MCU_S_Y NVTBIT(24,16) /*!< MCU Start Position Y For Window Decode Mode */ +#define MCU_S_X NVTBIT(8,0) /*!< MCU Start Position X For Window Decode Mode */ + +//JWINDEC1 +#define MCU_E_Y NVTBIT(24,16) /*!< MCU End Position Y For Window Decode Mode */ +#define MCU_E_X NVTBIT(8,0) /*!< MCU End Position X For Window Decode Mode */ + +//JWINDEC2 +#define WD_WIDTH NVTBIT(11,0)) /*!< Image Width (Y-Stride) For Window Decode Mode */ + +//JMACR +#define FLY_SEL NVTBIT(29,24) /*!< Hardware Memory On-the-Fly Access Image Buffer-Size Selection for Encode */ +#define FLY_TYPE NVTBIT(23,22) /*!< Dual/Single buffer on-the fly */ +#define BSF_SEL NVTBIT(17,8) /*!< Memory On-the-Fly Access Bitstream Buffer-Size Selection */ +#define FLY_ON BIT7 /*!< Hardware Memory On-the-Fly Access Mode */ +#define IP_SF_ON BIT3 /*!< Software Memory On-the-Fly Access Mode for Data Input */ +#define OP_SF_ON BIT2 /*!< Software Memory On-the-Fly Access Mode for Data Output */ +#define ENC_MODE NVTBIT(1,0) /*!< JPEG Memory Address Mode Control */ + +//JPSCALU +#define JPSCALU_8X BIT6 /*!< Primary Image Up-Scaling For Encode */ +#define A_JUMP BIT2 /*!< Reserve Buffer Size In JPEG Bit-stream For Software Application */ + +//JPSCALD +#define PSX_ON BIT15 /*!< Primary Image Horizontal Down-Scaling For Encode/Decode */ +#define PS_LPF_ON BIT14 /*!< Primary Image Down-Scaling Low Pass Filter For Decode */ +#define PSCALX_F NVTBIT(12,8) /*!< Primary Image Horizontal Down-Scaling Factor */ +#define PSCALY_F NVTBIT(5,0) /*!< Primary Image Vertical Down-Scaling Factor */ + +//JTSCALD +#define TSX_ON BIT15 /*!< Thumbnail Image Horizontal Down-Scaling For Encode/Decode */ +#define TSCALX_F NVTBIT(14,8) /*!< Thumbnail Image Horizontal Down-Scaling Factor */ +#define TSCALY_F NVTBIT(7,0) /*!< Thumbnail Image Vertical Down-Scaling Factor */ + +//JDBCR +#define DBF_EN BIT7 /*!< Dual Buffering Control */ +#define IP_BUF BIT4 /*!< Input Dual Buffer Control */ + +//JRESERVE +#define RES_SIZE NVTBIT(15,0) /*!< Primary Encode Bit-stream Reserved Size */ + +//JOFFSET +#define OFFSET_SIZE NVTBIT(23,0) /*!< Primary/Thumbnail Starting Address Offset Size */ + +//JFSTRIDE +#define F_STRIDE NVTBIT(23,0) /*!< JPEG Encode Bit-stream Frame Stride */ + +//JYADDR0 +#define Y_IADDR0 NVTBIT(31,0) /*!< JPEG Y Component Frame Buffer-0 Starting Address */ + +//JUADDR0 +#define U_IADDR0 NVTBIT(31,0) /*!< JPEG U Component Frame Buffer-0 Starting Address */ + +//JVADDR0 +#define V_IADDR0 NVTBIT(31,0) /*!< JPEG V Component Frame Buffer-0 Starting Address */ + +//JYADDR1 +#define Y_IADDR1 NVTBIT(31,0) /*!< JPEG Y Component Frame Buffer-1 Starting Address */ + +//JUADDR1 +#define U_IADDR1 NVTBIT(31,0) /*!< JPEG U Component Frame Buffer-1 Starting Address */ + +//JVADDR1 +#define V_IADDR1 NVTBIT(31,0) /*!< JPEG V Component Frame Buffer-1 Starting Address */ + +//JYSTRIDE +#define Y_STRIDE NVTBIT(11,0) /*!< JPEG Y Component Frame Buffer Stride */ + +//JUSTRIDE +#define U_STRIDE NVTBIT(11,0) /*!< JPEG U Component Frame Buffer Stride */ + +//JVSTRIDE +#define V_STRIDE NVTBIT(11,0) /*!< JPEG V Component Frame Buffer Stride */ + +//JIOADDR0 +#define IO_IADDR0 NVTBIT(31,0) /*!< JPEG Bit-stream Frame Buffer-0 Starting Address */ + +//JIOADDR1 +#define IO_IADDR1 NVTBIT(31,0) /*!< JPEG Bit-stream Frame Buffer-1 Starting Address */ + +//JPRI_SIZE +#define PRI_SIZE NVTBIT(23,0) /*!< JPEG Primary Image Encode Bit-stream Size */ + +//JTHB_SIZE +#define THB_SIZE NVTBIT(15,0) /*!< JPEG Thumbnail Image Encode Bit-stream Size */ + +//JUPRAT +#define S_HEIGHT NVTBIT(29,16) /*!< JPEG Image Height Up-Scale Ratio */ +#define S_WIDTH NVTBIT(13,0) /*!< JPEG Image Width Up-Scale Ratio */ + +//JBSFIFO +#define BSFIFO_HT NVTBIT(6,4) /*!< Bit-stream FIFO High-Threshold Control */ +#define BSFIFO_LT NVTBIT(2,0) /*!< Bit-stream FIFO Low-Threshold Control */ + +//JSRCH +#define JSRCH_JSRCH NVTBIT(11,0) /*!< JPEG Encode Source Image Height */ + +/*@}*/ /* end of group N9H30_JPEG_EXPORTED_CONSTANTS */ + +/// @cond HIDDEN_SYMBOLS + +//Define for Interrupt Status +#define JPEG_EER_INTS EER_INTS +#define JPEG_DER_INTS DER_INTS +#define JPEG_DEC_INTS DEC_INTS +#define JPEG_ENC_INTS ENC_INTS +#define JPEG_DHE_INTS DHE_INTS +#define JPEG_IPW_INTS IPW_INTS + +//Define for Scaling +#define JPEG_ENC_UPSCALE_MODE 0 +#define JPEG_DEC_PACKET_DOWNSCALE_MODE 1 +#define JPEG_DEC_PLANAR_DOWNSCALE_MODE 2 +#define JPEG_ENC_PLANAR_PRIMARY_DOWNSCALE_MODE 3 +#define JPEG_ENC_PLANAR_THUMBNAIL_DOWNSCALE_MODE 4 + +//Define for Interrupt Enable +#define JPEG_EER_INTE ERR_INTE +#define JPEG_DER_INTE DER_INTE +#define JPEG_DEC_INTE DEC_INTE +#define JPEG_ENC_INTE ENC_INTE +#define JPEG_DHE_INTE DHE_INTE +#define JPEG_IPW_INTE IPW_INTE + +//Register +#define REG_JMCR JMCR /*!< JPEG Mode Control Register */ +#define REG_JHEADER JHEADER /*!< JPEG Encode Header Control Register */ +#define REG_JITCR JITCR /*!< JPEG Image Type Control Register */ +#define REG_JPRIQC JPRIQC /*!< JPEG Primary Q-Table Control Register */ +#define REG_JTHBQC JTHBQC /*!< JPEG Thumbnail Q-Table Control Register */ +#define REG_JPRIWH JPRIWH /*!< JPEG Encode Primary Width/Height Register */ +#define REG_JTHBWH JTHBWH /*!< JPEG Encode Thumbnail Width/Height Register */ +#define REG_JPRST JPRST /*!< JPEG Encode Primary Restart Interval Register */ +#define REG_JTRST JTRST /*!< JPEG Encode Thumbnail Restart Interval */ +#define REG_JDECWH JDECWH /*!< JPEG Decode Image Width/Height Register */ +#define REG_JINTCR JINTCR /*!< JPEG Interrupt Control and Status Register */ +#define REG_JTEST JTEST /*!< JPEG Test Control Register */ +#define REG_JWINDEC0 JWINDEC0 /*!< JPEG Window Decode Mode Control Register 0 */ +#define REG_JWINDEC1 JWINDEC1 /*!< JPEG Window Decode Mode Control Register 1 */ +#define REG_JWINDEC2 JWINDEC2 /*!< JPEG Window Decode Mode Control Register 2 */ +#define REG_JMACR JMACR /*!< JPEG Memory Address Mode Control Register */ +#define REG_JPSCALU JPSCALU /*!< JPEG Primary Scaling-Up Control Register */ +#define REG_JPSCALD JPSCALD /*!< JPEG Primary Scaling-Down Control Register */ +#define REG_JTSCALD JTSCALD /*!< JPEG Thumbnail Scaling-Down Control Register */ +#define REG_JDBCR JDBCR /*!< JPEG Dual-Buffer Control Register */ +#define REG_JRESERVE JRESERVE /*!< JPEG Encode Primary Bit-stream Reserved Size Register */ +#define REG_JOFFSET JOFFSET /*!< JPEG Offset Between Primary & Thumbnail Register */ +#define REG_JFSTRIDE JFSTRIDE /*!< JPEG Encode Bit-stream Frame Stride Register */ +#define REG_JYADDR0 JYADDR0 /*!< JPEG Y Component Frame Buffer-0 Starting Address Register */ +#define REG_JUADDR0 JUADDR0 /*!< JPEG U Component Frame Buffer-0 Starting Address Register */ +#define REG_JVADDR0 JVADDR0 /*!< JPEG V Component Frame Buffer-0 Starting Address Register */ +#define REG_JYADDR1 JYADDR1 /*!< JPEG Y Component Frame Buffer-1 Starting Address Register */ +#define REG_JUADDR1 JUADDR1 /*!< JPEG U Component Frame Buffer-1 Starting Address Register */ +#define REG_JVADDR1 JVADDR1 /*!< JPEG V Component Frame Buffer-1 Starting Address Register */ +#define REG_JYSTRIDE JYSTRIDE /*!< JPEG Y Component Frame Buffer Stride Register */ +#define REG_JUSTRIDE JUSTRIDE /*!< JPEG U Component Frame Buffer Stride Register */ +#define REG_JVSTRIDE JVSTRIDE /*!< JPEG V Component Frame Buffer Stride Register */ +#define REG_JIOADDR0 JIOADDR0 /*!< JPEG Bit-stream Frame Buffer-0 Starting Address Register */ +#define REG_JIOADDR1 JIOADDR1 /*!< JPEG Bit-stream Frame Buffer-1 Starting Address Register */ +#define REG_JPRI_SIZE JPRI_SIZE /*!< JPEG Encode Primary Image Bit-stream Size Register */ +#define REG_JTHB_SIZE JTHB_SIZE /*!< JPEG Encode Thumbnail Image Bit-stream Size Register */ +#define REG_JUPRAT JUPRAT /*!< JPEG Encode Up-Scale Ratio Register */ +#define REG_JBSFIFO JBSFIFO /*!< JPEG Bit-stream FIFO Control Register */ +#define REG_JSRCH JSRCH /*!< JPEG Encode Source Image Height */ +#define REG_JQTAB0 JQTAB0 /*!< JPEG Quantization-Table 0 Register */ +#define REG_JQTAB1 JQTAB1 /*!< JPEG Quantization-Table 1 Register */ +#define REG_JQTAB2 JQTAB2 /*!< JPEG Quantization-Table 2 Register */ + +//Export functions +#define JPEG_SET_YADDR(u32Address) outp32(REG_JYADDR0, u32Address) +#define JPEG_SET_UADDR(u32Address) outp32(REG_JUADDR0, u32Address) +#define JPEG_SET_VADDR(u32Address) outp32(REG_JVADDR0, u32Address) +#define JPEG_GET_YADDR() inp32(REG_JYADDR0) +#define JPEG_GET_UADDR() inp32(REG_JUADDR0) +#define JPEG_GET_VADDR() inp32(REG_JVADDR0) +#define JPEG_SET_YSTRIDE(u32Stride) outp32(REG_JYSTRIDE, u32Stride) +#define JPEG_SET_USTRIDE(u32Stride) outp32(REG_JUSTRIDE, u32Stride) +#define JPEG_SET_VSTRIDE(u32Stride) outp32(REG_JVSTRIDE, u32Stride) +#define JPEG_GET_YSTRIDE() inp32(REG_JYSTRIDE) +#define JPEG_GET_USTRIDE() inp32(REG_JUSTRIDE) +#define JPEG_GET_VSTRIDE() inp32(REG_JVSTRIDE) +#define JPEG_SET_BITSTREAM_ADDR(u32Address) outp32(REG_JIOADDR0,u32Address) +#define JPEG_GET_BITSTREAM_ADDR() inp32(REG_JIOADDR0) +#define JPEG_SET_ENC_DEC(u8Mode) outp32(REG_JMCR, (inp32(REG_JMCR) & ~ENC_DEC) | (u8Mode << 7)); + +//Encode +#define JPEG_GET_ENC_PRIMARY_BITSTREAM_SIZE() inp32(REG_JPRI_SIZE) +#define JPEG_GET_ENC_THUMBNAIL_BITSTREAM_SIZE() inp32(REG_JTHB_SIZE) +#define JPEG_SET_SOURCE_IMAGE_HEIGHT(u16Size) outp32(REG_JSRCH,u16Size) +#define JPEG_GET_SOURCE_IMAGE_HEIGHT() inp32(REG_JSRCH) +#define JPEG_ENC_ENABLE_UPSCALING() outp32(REG_JPSCALU,inp32(REG_JPSCALU) | JPSCALU_8X) +#define JPEG_ENC_DISABLE_UPSCALING() outp32(REG_JPSCALU,inp32(REG_JPSCALU) & ~JPSCALU_8X) +#define JPEG_ENC_ISENABLE_UPSCALING() ((inp32(REG_JPSCALU) & JPSCALU_8X) >> 6) +#define JPEG_ENC_SET_HEADER_CONTROL(u8Control) outp32(REG_JHEADER, u8Control) +#define JPEG_ENC_GET_HEADER_CONTROL() inp32(REG_JHEADER) +#define JPEG_ENC_SET_RDI_VALUE(u8Value) outp32(REG_JPRST,u8Value) +#define JPEG_ENC_GET_RDI_VALUE() inp32(REG_JPRST) + +//Decode +#define JPEG_DEC_ENABLE_DOWNSCALING() outp32(REG_JPSCALD, PSX_ON) +#define JPEG_DEC_ISENABLE_DOWNSCALING() ((inp32(REG_JPSCALD) & PSX_ON) >> 15) +#define JPEG_DEC_DISABLE_DOWNSCALING() outp32(REG_JPSCALD,~PSX_ON) +#define JPEG_DEC_GET_DECODED_IMAGE_FORMAT() (inp32(REG_JITCR) & DYUV_MODE) +#define JPEG_DEC_ENABLE_LOW_PASS_FILTER() outp32(REG_JPSCALD,inp32(REG_JPSCALD) | PS_LPF_ON) +#define JPEG_DEC_DISABLE_LOW_PASS_FILTER() outp32(REG_JPSCALD,inp32(REG_JPSCALD) & ~PS_LPF_ON) +#define JPEG_DEC_ISENABLE_LOW_PASS_FILTER() ((inp32(REG_JPSCALD) & PS_LPF_ON) >> 14) +#define JPEG_DEC_SET_INPUT_WAIT(u16Size) outp32(REG_JMACR, 0x00400008 | ((u16Size & 0x3FF)<< 8) ); +#define JPEG_DEC_RESUME_INPUT_WAIT() outp32(REG_JMCR,inp32(REG_JMCR) | RESUMEI); +#define JPEG_DEC_DISABLE_WINDOWDECODE() outp32(REG_JMCR, inp32(REG_JMCR) & ~(WIN_DEC)); + +//Interrupt +#define JPEG_INT_ENABLE(u32Intflag) outp32(REG_JINTCR, u32Intflag) +#define JPEG_INT_DISABLE(u32Intflag) outp32(REG_JINTCR, inp32 (REG_JINTCR) & ~(u32Intflag)) +#define JPEG_GET_INT_STATUS() (inp32(REG_JINTCR) & 0x010000FF) +#define JPEG_CLEAR_INT(u32Intflag) outp32(REG_JINTCR, (inp32 (REG_JINTCR) & ~0xFF) | u32Intflag) + +static INT jpegSetEncodeMode(UINT8 u8SourceFormat, UINT16 u16JpegFormat); +static INT jpegSetDecodeMode(UINT32 u8OutputFormat); +static BOOL jpegPollInt(UINT32 u32Intflag); +static VOID jpegEncodeTrigger(void); +static VOID jpegDecodeTrigger(void); +static VOID jpegGetDecodedDimension( + PUINT16 pu16Height, //Decode/Encode Height + PUINT16 pu16Width //Decode/Encode Width +); +static VOID jpegSetDimension( + UINT16 u16Height, //Decode/Encode Height + UINT16 u16Width //Decode/Encode Width +); +static VOID jpegGetDimension( + PUINT16 pu16Height, //Decoded Height from bit stream + PUINT16 pu16Width //Decoded Width from bit stream +); +static INT jpegSetWindowDecode( + UINT16 u16StartMCUX, //Start X MCU + UINT16 u16StartMCUY, //Horizontal Scaling Factor + UINT16 u16EndMCUX, //Vertical Scaling Factor + UINT16 u16EndMCUY, //Horizontal Scaling Factor + UINT32 u32Stride //Decode Output Stride +); +static INT jpegCalScalingFactor( + UINT8 u8Mode, //Up / Down Scaling + UINT16 u16Height, //Original Height + UINT16 u16Width, //Original Width + UINT16 u16ScalingHeight, //Scaled Height + UINT16 u16ScalingWidth, //Scaled Width + PUINT16 pu16RatioH, //Horizontal Ratio + PUINT16 pu16RatioW //Vertical Ratio +); +static INT jpegSetScalingFactor( + UINT8 u8Mode, //Up / Down Scaling + UINT16 u16FactorH, //Vertical Scaling Factor + UINT16 u16FactorW //Horizontal Scaling Factor +); +static VOID jpegGetScalingFactor( + UINT8 u8Mode, //Up / Down Scaling + PUINT16 pu16FactorH, //Vertical Scaling Factor + PUINT16 pu16FactorW //Horizontal Scaling Factor +); +/// @endcond HIDDEN_SYMBOLS + +/*@}*/ /* end of group N9H30_JPEG_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#endif diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_jpegcodec.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_jpegcodec.h new file mode 100644 index 0000000000..c18e6ba9ba --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_jpegcodec.h @@ -0,0 +1,227 @@ +/**************************************************************************//** +* @file jpegcodec.h +* @brief N9H30 JPEG driver header file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_JPEGCODEC_H__ +#define __NU_JPEGCODEC_H__ + +//Include header file +#include "N9H30.h" +#include "nu_sys.h" + + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_JPEG_Driver JPEG Driver + @{ +*/ + + +/** @addtogroup N9H30_JPEG_EXPORTED_CONSTANTS JPEG Exported Constants + @{ +*/ + +#define E_FAIL 0 /*!< JPEG function Error */ +#define E_SUCCESS 1 /*!< JPEG function Success */ +#define E_JPEG_INVALID_PARAM 2 /*!< Input invalid paramater */ +#define E_JPEG_TIMEOUT 3 /*!< JPEG function Time-out */ + + +#define JPEG_ENC_PRIMARY 0 /*!< JPEG encode Primary */ +#define JPEG_ENC_THUMBNAIL 1 /*!< JPEG encode Thumbanil */ + +//Define for Encode input Format +#define JPEG_ENC_SOURCE_PLANAR 0 /*!< JPEG encode input formate is Planar */ +#define JPEG_ENC_SOURCE_PACKET 1 /*!< JPEG encode input formate is Packet */ + +//Define for Decode Output Format + +//(PLANAR_ON | PDHTAB | DHEND) +#define JPEG_DEC_PRIMARY_PLANAR_YUV 0x8021 /*!< JPEG decode output Primary Planar YUV */ +//(PDHTAB | DHEND) +#define JPEG_DEC_PRIMARY_PACKET_YUV422 0x0021 /*!< JPEG decode output Primary Packet YUV422 */ + +//(PDHTAB | DHEND | ORDER) +#define JPEG_DEC_PRIMARY_PACKET_RGB555 0x04021 /*!< JPEG decode output Primary Packet RGB555 */ +//(PDHTAB | DHEND | RGB555_565 | ORDER ) +#define JPEG_DEC_PRIMARY_PACKET_RGB565 0x06021 /*!< JPEG decode output Primary Packet RGB565 */ + +//(PDHTAB | DHEND | ORDER) +#define JPEG_DEC_PRIMARY_PACKET_RGB555R1 0x404021 /*!< JPEG decode output Primary Packet RGB555R1 */ +//(PDHTAB | DHEND | RGB555_565 | ORDER ) +#define JPEG_DEC_PRIMARY_PACKET_RGB565R1 0x406021 /*!< JPEG decode output Primary Packet RGB565R1 */ + +#define JPEG_DEC_PRIMARY_PACKET_RGB565R2 0x806021 /*!< JPEG decode output Primary Packet RGB565R2 */ +//(PDHTAB | DHEND | ORDER) +#define JPEG_DEC_PRIMARY_PACKET_RGB555R2 0x804021 /*!< JPEG decode output Primary Packet RGB555R2 */ + +//(PDHTAB | DHEND | RGB555_565 | ORDER ) +#define JPEG_DEC_PRIMARY_PACKET_RGB888 0x14021 /*!< JPEG decode Primary Packet RGB888 */ +//(PLANAR_ON | DTHB | PDHTAB) +#define JPEG_DEC_THUMBNAIL_PLANAR_YUV 0x8031 /*!< JPEG decode Thumbnail Planar YUV */ +//(DTHB | PDHTAB | DHEND) +#define JPEG_DEC_THUMBNAIL_PACKET_YUV422 0x0031 /*!< JPEG decode Thumbnail Packet YUV422 */ +//(DTHB | PDHTAB | DHEND | ORDER) +#define JPEG_DEC_THUMBNAIL_PACKET_RGB555 0x4031 /*!< JPEG decode Thumbnail Packet RGB555 */ + +//Define for Encode Image Format +#define JPEG_ENC_PRIMARY_YUV420 0xA0 /*!< JPEG encode Primary YUV420 */ +#define JPEG_ENC_PRIMARY_YUV422 0xA8 /*!< JPEG encode Primary YUV422 */ +#define JPEG_ENC_PRIMARY_GRAY 0xA1 /*!< JPEG encode Primary Gray */ +#define JPEG_ENC_THUMBNAIL_YUV420 0x90 /*!< JPEG encode Thumbnail YUV420 */ +#define JPEG_ENC_THUMBNAIL_YUV422 0x98 /*!< JPEG encode Thumbnail YUV422 */ +#define JPEG_ENC_THUMBNAIL_GRAY 0x91 /*!< JPEG encode Thumbnail Gray */ + +//Define for Decode Image Format +#define JPEG_DEC_YUV420 0x000 /*!< JPEG decode image formatr is YUV420 */ +#define JPEG_DEC_YUV422 0x100 /*!< JPEG decode image formatr is YUV422 */ +#define JPEG_DEC_YUV444 0x200 /*!< JPEG decode image formatr is YUV444 */ +#define JPEG_DEC_YUV411 0x300 /*!< JPEG decode image formatr is YUV411 */ +#define JPEG_DEC_GRAY 0x400 /*!< JPEG decode image formatr is Gray */ +#define JPEG_DEC_YUV422T 0x500 /*!< JPEG decode image formatr is YUV422T */ + +//Define for Encode Image Header +/*P_DRI*/ +#define JPEG_ENC_PRIMARY_DRI 0x10 /*!< JPEG encode image header Primary DRI */ +/*P_QTAB*/ +#define JPEG_ENC_PRIMARY_QTAB 0x20 /*!< JPEG encode image header Primary Q Table */ +/*P_HTAB*/ +#define JPEG_ENC_PRIMARY_HTAB 0x40 /*!< JPEG encode image header Primary H Table */ +/*P_JFIF*/ +#define JPEG_ENC_PRIMARY_JFIF 0x80 /*!< JPEG encode image header Primary JFIF */ +/*T_DRI*/ +#define JPEG_ENC_THUMBNAIL_DRI 0x1 /*!< JPEG encode image header Thumbnail DRI */ +/*T_QTAB*/ +#define JPEG_ENC_THUMBNAIL_QTAB 0x2 /*!< JPEG encode image header Thumbnail Q Table */ +/*T_HTAB*/ +#define JPEG_ENC_THUMBNAIL_HTAB 0x4 /*!< JPEG encode image header Thumbnail H Table */ +/*T_JFIF*/ +#define JPEG_ENC_THUMBNAIL_JFIF 0x8 /*!< JPEG encode image header Thumbnail JFIF */ + + +#define JPEG_IOCTL_SET_YADDR 0 /*!< Set Y Component Frame Buffer-0 Starting Address Register */ +#define JPEG_IOCTL_SET_YSTRIDE 1 /*!< Set Y Component Frame Buffer Stride Register */ +#define JPEG_IOCTL_SET_USTRIDE 2 /*!< Set U Component Frame Buffer Stride Register */ +#define JPEG_IOCTL_SET_VSTRIDE 3 /*!< Set V Component Frame Buffer Stride Register */ +#define JPEG_IOCTL_SET_BITSTREAM_ADDR 4 /*!< Set Bit-stream Frame Buffer-0 Starting Address Register */ +#define JPEG_IOCTL_SET_SOURCE_IMAGE_HEIGHT 5 /*!< Set JPEG Bit-stream FIFO Control Register */ +#define JPEG_IOCTL_ENC_SET_HEADER_CONTROL 6 /*!< Set JPEG Encode Header Control Register */ +#define JPEG_IOCTL_SET_DEFAULT_QTAB 7 /*!< Set Default Q Table */ +#define JPEG_IOCTL_SET_DECODE_MODE 8 /*!< Set Decode Mode */ +#define JPEG_IOCTL_SET_ENCODE_MODE 9 /*!< Set Encode Mode */ +#define JPEG_IOCTL_SET_DIMENSION 10 /*!< Set Encode Primary Width/Height */ +#define JPEG_IOCTL_ENCODE_TRIGGER 11 /*!< Encode Trigger */ +#define JPEG_IOCTL_DECODE_TRIGGER 12 /*!< Decode Trigger */ +#define JPEG_IOCTL_WINDOW_DECODE 13 /*!< Window Decode Setting */ +#define JPEG_IOCTL_SET_DECODE_STRIDE 14 /*!< Set Decode Stride */ +#define JPEG_IOCTL_SET_DECODE_DOWNSCALE 15 /*!< Set Decode Downscale */ +#define JPEG_IOCTL_SET_ENCODE_UPSCALE 16 /*!< Set Encode Upscale */ +#define JPEG_IOCTL_SET_HEADERDECODE_CALBACKFUN 17 /*!< Set Header decode call back function */ +#define JPEG_IOCTL_SET_DECINPUTWAIT_CALBACKFUN 18 /*!< Set Decode Input Wait call back function */ +#define JPEG_IOCTL_ADJUST_QTAB 19 /*!< Set Primary or Thumbnail Q Table */ +#define JPEG_IOCTL_ENC_RESERVED_FOR_SOFTWARE 20 /*!< Set Encode Reserved Size */ +#define JPEG_IOCTL_SET_UADDR 21 /*!< Set U Component Frame Buffer-0 Starting Address Register */ +#define JPEG_IOCTL_SET_VADDR 22 /*!< Set V Component Frame Buffer-0 Starting Address Register */ +#define JPEG_IOCTL_SET_ENCODE_PRIMARY_RESTART_INTERVAL 23 /*!< Set Encode Primary restart interval */ +#define JPEG_IOCTL_SET_ENCODE_THUMBNAIL_RESTART_INTERVAL 24 /*!< Set Encode Thumbnail restart interval */ +#define JPEG_IOCTL_GET_ENCODE_PRIMARY_RESTART_INTERVAL 25 /*!< Get Encode Primary restart interval */ +#define JPEG_IOCTL_GET_ENCODE_THUMBNAIL_RESTART_INTERVAL 26 /*!< Get Encode Thumbnail restart interval */ +#define JPEG_IOCTL_SET_THUMBNAIL_DIMENSION 27 /*!< Set Encode Thumbnail Width/Height */ +#define JPEG_IOCTL_SET_ENCODE_SW_OFFSET 28 /*!< Set Offset Between Primary & Thumbnail Register */ +#define JPEG_IOCTL_GET_THUMBNAIL_DIMENSION 29 /*!< Get Thumbnail Width/Height */ +#define JPEG_IOCTL_GET_ENCODE_SW_OFFSET 30 /*!< Get Offset Between Primary & Thumbnail Register */ +#define JPEG_IOCTL_SET_ENCODE_PRIMARY_DOWNSCALE 31 /*!< Set Enciode Primary Downscale */ +#define JPEG_IOCTL_SET_ENCODE_THUMBNAIL_DOWNSCALE 32 /*!< Set Encode Thumbnail Downscale */ +#define JPEG_IOCTL_SET_ENCODE_PRIMARY_ROTATE_RIGHT 33 /*!< Set Encode Primary rotate right */ +#define JPEG_IOCTL_SET_ENCODE_PRIMARY_ROTATE_LEFT 34 /*!< Set Encode Primary rotate left */ +#define JPEG_IOCTL_SET_ENCODE_PRIMARY_ROTATE_NORMAL 35 /*!< Set Encode Primary rotate normal */ +#define JPEG_IOCTL_SET_DECOUTPUTWAIT_CALBACKFUN 36 /*!< Set Decode Output wait call back function */ +#define JPEG_IOCTL_SET_DECOUTPUTWAIT 37 /*!< Set Decode Output wait */ +#define JPEG_IOCTL_GET_DECOUTPUTWAIT_ADDR 38 /*!< Get Decode Output wait address */ +#define JPEG_IOCTL_GET_DECOUTPUTWAIT_SIZE 39 /*!< Get Decode Output wait size */ +#define JPEG_IOCTL_SET_DECODE_COMPLETE_CALBACKFUN 40 /*!< Set Decode complete call back function */ +#define JPEG_IOCTL_SET_ENCODE_COMPLETE_CALBACKFUN 41 /*!< Set Encode complete call back function */ +#define JPEG_IOCTL_SET_DECODE_ERROR_CALBACKFUN 42 /*!< Set Decode Error call back function */ + +typedef BOOL (*PFN_JPEG_HEADERDECODE_CALLBACK)(void); /*!< JPEG Header decode call back function */ +typedef BOOL (*PFN_JPEG_CALLBACK)(void); /*!< JPEG call back function */ +typedef BOOL (*PFN_JPEG_DECWAIT_CALLBACK)(UINT32 u32Address, UINT32 u32Size); /*!< JPEG decode wait call back function */ + +/** \brief Structure type of JPEG encode/decode information + */ +typedef struct +{ + /*decode information*/ + UINT32 yuvformat; /*!< JPEG YUV Format for decode*/ + UINT32 width; /*!< Image Width */ + UINT32 height; /*!< Image High */ + UINT32 jpeg_width; /*!< JPEG decode width*/ + UINT32 jpeg_height; /*!< JPEG decode high*/ + UINT32 stride; /*!< Stride for decode*/ + /*encode information*/ + UINT32 bufferend; /*!< Encode buffer */ + UINT32 image_size[2]; /*!< Image size after encoded*/ +} JPEG_INFO_T; + +/** \brief Structure type of JPEG Window Decode information + */ +typedef struct +{ + UINT16 u16StartMCUX; /*!< Start X MCU */ + UINT16 u16StartMCUY; /*!< Horizontal Scaling Factor */ + UINT16 u16EndMCUX; /*!< Vertical Scaling Factor */ + UINT16 u16EndMCUY; /*!< Horizontal Scaling Factor */ + UINT32 u32Stride; /*!< Decode Output Stride */ +} JPEG_WINDOW_DECODE_T; + +struct nu_jpeg_ioctl +{ + UINT32 arg0; + UINT32 arg1; +}; +typedef struct nu_jpeg_ioctl *nu_jpeg_ioctl_t; + +struct nu_jpeg_qtab +{ + PUINT8 puQTable0; + PUINT8 puQTable1; + PUINT8 puQTable2; + UINT8 u8num; +}; +typedef struct nu_jpeg_qtab *nu_jpeg_qtab_t; + +/*@}*/ /* end of group N9H30_JPEG_EXPORTED_CONSTANTS */ + + +/** @addtogroup N9H30_JPEG_EXPORTED_FUNCTIONS JPEG Exported Functions + @{ +*/ +#define JPEG_IOCTL_SET_QTAB 64 /*!< Set User-defined Q Table */ +#define JPEG_IOCTL_INITIAL_CODEC 65 /*!< Reset Initial internal variables */ +#define JPEG_IOCTL_GET_INFO 66 /*!< Set Decode Error call back function */ +#define JPEG_IOCTL_IS_READY 67 /*!< Check JPEG codec is ready or not */ +#define JPEG_IOCTL_WAITDONE 68 /*!< Wait JPEG action done. */ + +INT jpegSetQTAB(PUINT8 puQTable0, PUINT8 puQTable1, PUINT8 puQTable2, UINT8 u8num); +INT jpegOpen(void); +VOID jpegClose(void); +VOID jpegInit(void); +VOID jpegGetInfo(JPEG_INFO_T *info); +BOOL jpegIsReady(void); +INT jpegWait(void); +VOID jpegIoctl(UINT32 cmd, UINT32 arg0, UINT32 arg1); + +/*@}*/ /* end of group N9H30_JPEG_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_JPEG_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#endif diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h new file mode 100644 index 0000000000..910d708845 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h @@ -0,0 +1,247 @@ +/**************************************************************************//** +* @file lcd.h +* @version V1.00 +* @brief N9H30 LCD driver header file +* +* SPDX-License-Identifier: Apache-2.0 +* @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#ifndef __NU_LCD_H__ +#define __NU_LCD_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_LCD_Driver LCD Driver + @{ +*/ + +/** @addtogroup N9H30_LCD_EXPORTED_CONSTANTS LCD Exported Constants + @{ +*/ +/// @cond HIDDEN_SYMBOLS + +/* bit definition of REG_LCM_DCCS register */ +#define VPOSTB_HC_EN ((UINT32)1<<31) +#define VPOSTB_DISP_ON (1<<25) +#define VPOSTB_ITUEN (1<<15) +#define VPOSTB_OSD_SRC_YUV422 (0<<12) +#define VPOSTB_OSD_SRC_YCBCR422 (1<<12) +#define VPOSTB_OSD_SRC_RGB888 (2<<12) +#define VPOSTB_OSD_SRC_RGB666 (3<<12) +#define VPOSTB_OSD_SRC_RGB565 (4<<12) +#define VPOSTB_OSD_SRC_RGB444_LOW (5<<12) +#define VPOSTB_OSD_SRC_RGB444_HIGH (7<<12) +#define VPOSTB_VA_SRC_YUV422 (0<<8 ) +#define VPOSTB_VA_SRC_YCBCR422 (1<<8 ) +#define VPOSTB_VA_SRC_RGB888 (2<<8 ) +#define VPOSTB_VA_SRC_RGB666 (3<<8 ) +#define VPOSTB_VA_SRC_RGB565 (4<<8 ) +#define VPOSTB_VA_SRC_RGB444_LOW (5<<8 ) +#define VPOSTB_VA_SRC_RGB444_HIGH (7<<8 ) +#define VPOSTB_SINGLE (1<<7 ) +#define VPOSTB_FIELD_INTR (1<<6 ) +#define VPOSTB_CMD_ON (1<<5 ) +#define VPOSTB_DISP_INT_EN (1<<4 ) +#define VPOSTB_DISP_OUT_EN (1<<3 ) +#define VPOSTB_OSD_EN (1<<2 ) +#define VPOSTB_VA_EN (1<<1 ) +#define VPOSTB_ENG_RST (1) + + +/* bit definition of REG_LCM_DEV_CTRL register */ +#define VPOSTB_CMDHIGH (0) +#define VPOSTB_CMDLOW ((UINT32)1<<31) +#define VPOSTB_CM16t18LOW (0) +#define VPOSTB_CM16t18HIGH ((UINT32)1<<30) +#define VPOSTB_CMD8 (0) +#define VPOSTB_CMD16 ((UINT32)1<<29) +#define VPOSTB_IM256K_9or18 (0) +#define VPOSTB_IM256K_8or16 ((UINT32)1<<28) +#define VPOSTB_MPU80 (0) +#define VPOSTB_MPU68 (1<<27) +#define VPOSTB_DATA8or9 (0) +#define VPOSTB_DATA16or18 (1<<26) +#define VPOSTB_COLORTYPE_4K (0) +#define VPOSTB_COLORTYPE_64K (1<<24) +#define VPOSTB_COLORTYPE_256K (2<<24) +#define VPOSTB_COLORTYPE_16M (3<<24) +#define VPOSTB_LACE (1<<23) +#define VPOSTB_VR_LACE (1<<22) +#define VPOSTB_V_POL (1<<21) +#define VPOSTB_H_POL (1<<20) +#define VPOSTB_FAL_D (1<<19) +#define VPOSTB_YUV2CCIR (1<<16) +#define VPOSTB_DEVICE_SYNC_YUV422 (0) +#define VPOSTB_DEVICE_SYNC_UNIPAC (4<<5) +#define VPOSTB_DEVICE_SYNC_EPSON (5<<5) +#define VPOSTB_DEVICE_SYNC_HIGHCOLOR (6<<5) +#define VPOSTB_DEVICE_MPU (7<<5) +#define VPOSTB_SWAP_YUYV (1<<1) + +/* bit definition of REG_LCM_INT_CS register */ +#define VPOSTB_DISP_F_INT ((UINT32)1<<31) +#define VPOSTB_DISP_F_STATUS (1<<30) +#define VPOSTB_UNDERRUN_INT (1<<29) +#define VPOSTB_BUS_ERROR_INT (1<<28) +#define VPOSTB_FLY_ERR (1<<27) +#define VPOSTB_UNDERRUN_EN (1<<1) +#define VPOSTB_DISP_F_EN (1) + +/* bit definition of REG_LCM_VA_FBCTRL register */ +#define VPOSTB_DB_EN ((UINT32)1<<31) +#define VPOSTB_FLY_EN (1<<12) + +/* bit definition of REG_LCM_OSD_OVERLAY register */ +#define VPOSTB_BLI_ON (1<<9) +#define VPOSTB_CKEY_ON (1<<8) + +#define DISPLAY_VIDEO (0) +#define DISPLAY_OSD (1) +#define DISPLAY_SYNTHESIZED (2) + +/// @endcond HIDDEN_SYMBOLS + +#define VA_SRC_YUV422 (0<<8 ) /*!< YUV422 format */ +#define VA_SRC_YCBCR422 (1<<8 ) /*!< YCBCR422 format */ +#define VA_SRC_RGB888 (2<<8 ) /*!< RGB888 format */ +#define VA_SRC_RGB666 (3<<8 ) /*!< RGB666 format */ +#define VA_SRC_RGB565 (4<<8 ) /*!< RGB565 format */ +#define VA_SRC_RGB444_LOW (5<<8 ) /*!< RGB444 low nibble format */ +#define VA_SRC_RGB444_HIGH (7<<8 ) /*!< RGB444 high nibble format */ + +#define OSD_SRC_YUV422 (0<<12) /*!< YUV422 format */ +#define OSD_SRC_YCBCR422 (1<<12) /*!< YCBCR422 format */ +#define OSD_SRC_RGB888 (2<<12) /*!< RGB888 format */ +#define OSD_SRC_RGB666 (3<<12) /*!< RGB666 format */ +#define OSD_SRC_RGB565 (4<<12) /*!< RGB565 format */ +#define OSD_SRC_RGB444_LOW (5<<12) /*!< RGB444 low nibble format */ +#define OSD_SRC_RGB444_HIGH (7<<12) /*!< RGB444 high nibble format */ +#define OSD_SRC_RGB332 (6<<12) /*!< RGB332 format */ + +#define VPOST_DISPLAY_SINGLE 1 /*!< Single display mode */ +#define VPOST_DISPLAY_CONTINUOUS 0 /*!< Continuous display mode */ + +#define VPOSTB_OSD_VUP_1X (0<<16) /*!< OSD vertical scale up 1x */ +#define VPOSTB_OSD_VUP_2X (1<<16) /*!< OSD vertical scale up 2x */ +#define VPOSTB_OSD_VUP_4X (2<<16) /*!< OSD vertical scale up 4x */ + +#define DISPLAY_VIDEO (0) /*!< Display video data */ +#define DISPLAY_OSD (1) /*!< Display OSD data */ +#define DISPLAY_SYNTHESIZED (2) /*!< Display synthesized data */ + +#define VA_SCALE_INTERPOLATION (0) /*!< Scale mode is interpolation */ +#define VA_SCALE_DUPLICATION (1<<15) /*!< Scale mode is duplication */ + +typedef enum va_hcmode_e +{ + HC_MODE0, /*!< 32X32X2bpp 4 color */ + HC_MODE1, /*!< 32X32X2bpp 3 color and 1 transparent */ + HC_MODE2, /*!< 64X64X2bpp 4 color */ + HC_MODE3, /*!< 64X64X2bpp 3 color and 1 transparent */ + HC_MODE4, /*!< 128X128X1bpp 2 color */ + HC_MODE5 /*!< 128X128X1bpp 1 color and 1 transparent */ +} VA_HCMODE_E; + +typedef struct +{ + uint32_t ucVASrcFormat; /*!< User input Display source format */ + uint32_t nScreenWidth; /*!< Driver output,LCD width */ + uint32_t nScreenHeight; /*!< Driver output,LCD height */ + uint32_t nFrameBufferSize; /*!< Driver output,Frame buffer size(malloc by driver) */ + uint8_t ucROT90; /*!< Rotate 90 degree or not */ +} LCDFORMATEX; + +typedef struct +{ + uint32_t ucOSDSrcFormat; /*!< User input, OSD source format */ + uint32_t nXstart; /*!< User input, OSD X axis position */ + uint32_t nYstart; /*!< User input, OSD Y axis position */ + uint32_t nOSDWidth; /*!< User input, OSD width */ + uint32_t nOSDHeight; /*!< User input, OSD height */ + uint32_t nImageWidth; /*!< User input, The width of OSD source image width */ + uint32_t *pFrameBuffer; /*!< User input, The address of OSD source image */ +} OSDFORMATEX; + +#define DIS_PANEL_E50A2V1 0 +#define DIS_PANEL_ILI9341_MPU80 1 +#define DIS_LSA40AT9001 2 +#define DIS_PANEL_FW070TFT 3 +typedef struct +{ + uint32_t u32DevWidth; /*!< Panel width */ + uint32_t u32DevHeight; /*!< Panel height */ + uint32_t u32CmdLow; /*!< MPU command line low indicator */ + uint32_t u32Cmd16t18; /*!< MPU command width */ + uint32_t u32CmdBusWidth; /*!< MPU bus width */ + uint32_t u32DataBusWidth; /*!< Display bus width */ + uint32_t u32MPU_Mode; /*!< MPU mode */ + uint32_t u32DisplayColors; /*!< Display colors */ + uint32_t u32DevType; /*!< Type of display panel */ + uint32_t u32Reg_CRTCSIZE; /*!< CRTCSIZE register value */ + uint32_t u32Reg_CRTCDEND; /*!< CRTCDEND register value */ + uint32_t u32Reg_CRTCHR; /*!< CRTCHR register value */ + uint32_t u32Reg_CRTCHSYNC; /*!< CRTCHSYNC register value */ + uint32_t u32Reg_CRTCVR; /*!< CRTCVR register value */ +} VPOST_T; + +#define LCM_ERR_ID 0xFFFF0400 /*!< LCM library ID */ + +/* error code */ +#define ERR_NULL_BUF (LCM_ERR_ID | 0x04) /*!< error memory location */ +#define ERR_NO_DEVICE (LCM_ERR_ID | 0x05) /*!< error no device */ +#define ERR_BAD_PARAMETER (LCM_ERR_ID | 0x06) /*!< error for bad parameter */ +#define ERR_POWER_STATE (LCM_ERR_ID | 0x07) /*!< error power state control */ +/*@}*/ /* end of group N9H30_LCD_EXPORTED_CONSTANTS */ + +/** @addtogroup N9H30_LCD_EXPORTED_FUNCTIONS LCD Exported Functions + @{ +*/ + +void vpostLCMInit(uint32_t u32DisplayPanelID); +uint8_t *vpostGetFrameBuffer(void); +uint8_t *vpostGetMultiFrameBuffer(uint32_t u32Cnt); +void vpostLCMDeinit(void); +void vpostSetDisplayMode(uint8_t u8DisplayMode); +void vpostSetVASrc(uint32_t u32VASrcType); +void vpostVAStartTrigger(void); +void vpostVAStopTrigger(void); +void vpostVAScalingCtrl(uint8_t u8HIntegral, uint16_t u16HDecimal, uint8_t u8VIntegral, uint16_t u16VDecimal, uint32_t u32Mode); + +void vpostOSDSetColKey(uint8_t u8CKeyColorR, uint8_t u8CKeyColorG, uint8_t u8CKeyColorB); +void vpostOSDSetColMask(uint8_t u8MaskColorR, uint8_t u8MaskColorG, uint8_t u8MaskColorB); +void vpostOSDSetBlinking(uint8_t u8OSDBlinkVcnt); +void vpostOSDDisableBlinking(void); +void vpostSetOSDSrc(uint32_t u32OSDSrcType); +uint8_t *vpostGetOSDBuffer(void); +void vpostOSDEnable(void); +void vpostOSDDisable(void); +void vpostOSDScalingCtrl(uint8_t u8HIntegral, uint16_t u16HDecimal, uint8_t u8VScall); +void vpostOSDSetWindow(uint32_t u32XStart, uint32_t u32YStart, uint32_t u32Width, uint32_t u32Height); +void vpostHCInit(uint32_t *u32CursorBMPBuff, VA_HCMODE_E ucMode); +void vpostHCPosCtrl(uint32_t u32CursorX, uint32_t u32CursorY); +void vpostOSDSetOverlay(uint8_t u8OSDDisplayMatch, uint8_t u8OSDDisplayUnMatch, uint8_t u8OSDSynW); +void vpostMPUWriteAddr(uint16_t uscmd); +void vpostMPUWriteData(uint16_t usdata); +uint32_t vpostMPUReadData(void); +VPOST_T *vpostLCMGetInstance(uint32_t u32DisplayPanelID); + +/*@}*/ /* end of group N9H30_LCD_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_LCD_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_LCD_H__ + + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_pwm.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_pwm.h new file mode 100644 index 0000000000..4282d5099c --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_pwm.h @@ -0,0 +1,238 @@ +/**************************************************************************//** + * @file pwm.h + * @brief N9H30 series PWM driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_PWM_H__ +#define __NU_PWM_H__ +#include "N9H30.h" +#include "nu_sys.h" +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_PWM_Driver PWM Driver + @{ +*/ + +/** @addtogroup N9H30_PWM_EXPORTED_CONSTANTS PWM Exported Constants + @{ +*/ + +#define PWM_OFFSET 0xc ///< each channel has 3 control registers which occupies 12 bytes + +// Timer channel identity information +#define PWM_TIMER_NUM 4 ///< Total PWM channel count +#define PWM_TIMER_MIN 0 ///< Min PWM channel number +#define PWM_TIMER_MAX 3 ///< Max PWM channel number +#define PWM_TIMER0 0 ///< PWM channel 0 +#define PWM_TIMER1 1 ///< PWM channel 1 +#define PWM_TIMER2 2 ///< PWM channel 2 +#define PWM_TIMER3 3 ///< PWM channel 3 + +//ioctl command +#define START_PWMTIMER 0 ///< Start PWM ioctl command +#define STOP_PWMTIMER 1 ///< Stop PWM ioctl command +#define SET_CSR 2 ///< Set CSR ioctl command +#define SET_CP 3 ///< Set CP ioctl command +#define SET_DZI 4 ///< Set dead zone ioctl command +#define SET_INVERTER 5 ///< Set inverter ioctl command +#define SET_MODE 6 ///< Set OP mode ioctl command +#define ENABLE_DZ_GENERATOR 7 ///< Enable dead zone ioctl command +#define DISABLE_DZ_GENERATOR 8 ///< Disable dead zone ioctl command +#define ENABLE_PWMGPIOOUTPUT 9 ///< Enable PWM output ioctl command + +#define PWM_STOP_METHOD1 1 ///< PWM stop method 1 +#define PWM_STOP_METHOD2 2 ///< PWM stop method 2 +//#define PWM_STOP_METHOD3 3 not recommended + +//Timer default value +#define DEFAULT_CSR CSRD16 ///< Default CSR value +#define DEFAULT_CP 255 ///< Default CP value +#define DEFAULT_DZI 50 ///< Default DZI value +#define DEFAULT_CNR 19531 ///< Default CNR value +#define DEFAULT_CMR (19531/4) ///< Default CMR value +#define DEFAULT_MODE PWM_TOGGLE ///< Default OP mode + +// for PWM_PPR +#define DZI_MIN 0 ///< Min DZI value +#define DZI_MAX 255 ///< Max DZI value +#define CP_MIN 0 ///< Min CP value +#define CP_MAX 255 ///< Max CP value + +// for PWM_CSR +#define CSR_MIN 0 ///< Min CSR value +#define CSR_MAX 4 ///< Mac SCR value +#define CSRD2 0x0 ///< Div by 2 +#define CSRD4 0x1 ///< Div by 4 +#define CSRD8 0x2 ///< Div by 8 +#define CSRD16 0x3 ///< Div by 16 +#define CSRD1 0x4 ///< Div by 1 + +// for PWM_PCR +#define PWMDZG_ENABLE 1 ///< Enable PWM dead zone +#define PWMDZG_DISABLE 0 ///< Disable PWM dead zone +#define PWM_ENABLE 1 ///< Enable PWM channel +#define PWM_DISABLE 0 ///< Disable PWM channel +#define PWM_TOGGLE 1 ///< PWM toggle mode +#define PWM_ONESHOT 0 ///< PWM one-shot mode +#define PWM_INVON 1 ///< Enable PWM inverter +#define PWM_INVOFF 0 ///< Disable PWM inverter + +// for PWM_CNR +#define CNR_MIN 0 ///< Min CNR value +#define CNR_MAX 65535 ///< Mac CNR value + +// for PWM_CMR +#define CMR_MIN 0 ///< Min CMR value +#define CMR_MAX 65535 ///< Max CMR value + +// for pin control +#define PWM0_GPA12 0 ///< PWM0 output on GPA12 +#define PWM0_GPB2 1 ///< PWM0 output on GPB2 +#define PWM1_GPA13 4 ///< PWM1 output on GPA13 +#define PWM1_GPB3 5 ///< PWM1 output on GPB3 +#define PWM2_GPA14 7 ///< PWM2 output on GPA14 +#define PWM2_GPH2 9 ///< PWM2 output on GPH2 +#define PWM3_GPA15 10 ///< PWM3 output on GPA15 +#define PWM3_GPH3 12 ///< PWM3 output on GPH3 + +#define PWM_ERR_ID 0xFFFF1300 ///< PWM library ID + +//PWM Error code +#define pwmInvalidTimerChannel (PWM_ERR_ID|1) ///< Invalid channel number +#define pwmInvalidStructLength (PWM_ERR_ID|2) ///< Invalid structure length +#define pwmInvalidIoctlCommand (PWM_ERR_ID|3) ///< Invalid ioctl command +#define pwmInvalidStopMethod (PWM_ERR_ID|4) ///< Invalid stop mode +#define pwmInvalidCPValue (PWM_ERR_ID|5) ///< Invalid CP value +#define pwmInvalidDZIValue (PWM_ERR_ID|6) ///< Invalid DZI value +#define pwmInvalidCSRValue (PWM_ERR_ID|7) ///< Invalid CSR value +#define pwmInvalidDZGStatus (PWM_ERR_ID|8) ///< Invalid DZ status +#define pwmInvalidTimerStatus (PWM_ERR_ID|9) ///< Invalid timer status +#define pwmInvalidInverterValue (PWM_ERR_ID|10) ///< Invalid inverter value +#define pwmInvalidModeStatus (PWM_ERR_ID|11) ///< Invalid OP mode +#define pwmInvalidCNRValue (PWM_ERR_ID|12) ///< Invalid CNR value +#define pwmInvalidCMRValue (PWM_ERR_ID|13) ///< Invalid CMR value +#define pwmTimerNotOpen (PWM_ERR_ID|14) ///< PWM channel not stop +#define pwmTimerBusy (PWM_ERR_ID|15) ///< PWM channel is busy +#define pwmInvalidPin (PWM_ERR_ID|16) ///< Invalid PWM output pin + +/*@}*/ /* end of group N9H30_PWM_EXPORTED_CONSTANTS */ + +/// @cond HIDDEN_SYMBOLS +/** @addtogroup N9H30_PWM_EXPORTED_STRUCTS PWM Exported Structs + @{ +*/ + +typedef union +{ + UINT value; + struct + { + UINT cp0: 8, cp1: 8, dzi0: 8, dzi1: 8; + } field; +} typePPR; + +typedef union +{ + UINT value; + struct + { + UINT csr0: 3, _reserved3: 1, + csr1: 3, _reserved7: 1, + csr2: 3, _reserved11: 1, + csr3: 3, _reserved15: 1, + _reserved16_31: 16; + } field; +} typeCSR; + +typedef union +{ + UINT value; + struct + { + UINT ch0_en: 1, _reserved1: 1, ch0_inverter: 1, ch0_mode: 1, + grpup0_dzen: 1, grpup1_dzen: 1, + _reserved6_7: 2, + ch1_en: 1, _reserved9: 1, ch1_inverter: 1, ch1_mode: 1, + ch2_en: 1, _reserved13: 1, ch2_inverter: 1, ch2_mode: 1, + ch3_en: 1, _reserved17: 1, ch3_inverter: 1, ch3_mode: 1, + _reserved20_31: 12; + } field; +} typePCR; + +typedef union +{ + UINT value; + struct + { + UINT cnr: 16, _reserved16_31: 16; + } field; +} typeCNR; + +typedef union +{ + UINT value; + struct + { + UINT cmr: 16, _reserved16_31: 16; + } field; +} typeCMR; + +// for write operation +typedef union +{ + UINT value; + struct + { + UINT cnr: 16, cmr: 16; + } field; +} typePWMVALUE; + +// for read operation +typedef struct +{ + UINT volatile PDR; + BOOL volatile InterruptFlag; + BOOL _reversed0; + BOOL _reversed1; + BOOL _reversed2; +} typePWMSTATUS; + +/*@}*/ /* end of group N9H30_PWM_EXPORTED_STRUCTS */ +/// @endcond /* HIDDEN_SYMBOLS */ + +/** @addtogroup N9H30_PWM_EXPORTED_FUNCTIONS PWM Exported Functions + @{ +*/ + +// function definition +INT pwmInit(void); +INT pwmExit(void); +INT pwmOpen(const INT nTimerIdentity); +INT pwmClose(const INT nTimerIdentity); +INT pwmRead(const INT nTimerIdentity, PUCHAR pucStatusValue, const UINT uLength); +INT pwmWrite(const INT nTimerIdentity, PUCHAR pucCNRCMRValue, const UINT uLength); +INT pwmIoctl(const INT nTimerIdentity, const UINT uCommand, const UINT uIndication, UINT uValue); + +/*@}*/ /* end of group N9H30_PWM_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_PWM_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_PWM_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_rtc.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_rtc.h new file mode 100644 index 0000000000..6deb571d15 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_rtc.h @@ -0,0 +1,508 @@ +/**************************************************************************//** +* @file RTC.h +* @brief N9H30 RTC driver header file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_RTC_H__ +#define __NU_RTC_H__ + + +/*---------------------------------------------------------------------------------------------------------*/ +/* Includes of system headers */ +/*---------------------------------------------------------------------------------------------------------*/ +#include "N9H30.h" +#include "nu_sys.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_RTC_Driver RTC Driver + @{ +*/ + +/** @addtogroup N9H30_RTC_EXPORTED_CONSTANTS RTC Exported Constants + @{ +*/ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Define Error Code */ +/*---------------------------------------------------------------------------------------------------------*/ +#define E_RTC_SUCCESS 0 /*!< success */ +#define E_RTC_ERR_CALENDAR_VALUE 1 /*!< Wrong Calendar Value */ +#define E_RTC_ERR_TIMESACLE_VALUE 2 /*!< Wrong Time Scale Value */ +#define E_RTC_ERR_TIME_VALUE 3 /*!< Wrong Time Value */ +#define E_RTC_ERR_DWR_VALUE 4 /*!< Wrong Day Value */ +#define E_RTC_ERR_FCR_VALUE 5 /*!< Wrong Compenation value */ +#define E_RTC_ERR_EIO 6 /*!< Initial RTC Failed */ +#define E_RTC_ERR_ENOTTY 7 /*!< Command not support, or parameter incorrect */ +#define E_RTC_ERR_ENODEV 8 /*!< Interface number incorrect */ + +#define RTC_FCR_REFERENCE 32761 /*!< RTC Reference for frequency compensation */ + +#define RTC_INIT_KEY 0xa5eb1357 /*!< RTC Access Key \hideinitializer */ +#define RTC_WRITE_KEY 0xa965 /*!< RTC Access Key \hideinitializer */ + +#define RTC_WAIT_COUNT 0xFFFFFFFF /*!< Initial Time Out Value \hideinitializer */ + +#define RTC_YEAR2000 2000 /*!< RTC Reference \hideinitializer */ + +#define RTC_LEAP_YEAR 1 /*!< RTC leap year \hideinitializer */ + +#define RTC_CLOCK_12 0 /*!< RTC 12 Hour */ +#define RTC_CLOCK_24 1 /*!< RTC 24 Hour */ + +#define RTC_AM 1 /*!< RTC AM \hideinitializer */ +#define RTC_PM 2 /*!< RTC PM \hideinitializer */ + +#define RTC_INIT_ACTIVE_Pos (0) /*!< RTC INIT: ACTIVE Position */ +#define RTC_INIT_ACTIVE_Msk (0x1ul << RTC_INIT_ACTIVE_Pos) /*!< RTC INIT: ACTIVE Mask */ + +#define RTC_INIT_INIT_Pos (0) /*!< RTC INIT: INIT Position */ +#define RTC_INIT_INIT_Msk (0xfffffffful << RTC_INIT_INIT_Pos) /*!< RTC INIT: INIT Mask */ + +#define RTC_RWEN_RWENPASSWD_Pos (0) /*!< RTC RWEN: RWEN Position */ +#define RTC_RWEN_RWENPASSWD_Msk (0xfffful << RTC_RWEN_RWEN_Pos) /*!< RTC RWEN: RWEN Mask */ + +#define RTC_RWEN_RWENF_Pos (16) /*!< RTC RWEN: RWENF Position */ +#define RTC_RWEN_RWENF_Msk (0x1ul << RTC_RWEN_RWENF_Pos) /*!< RTC RWEN: RWENF Mask */ + +#define RTC_FREQADJ_FRACTION_Pos (0) /*!< RTC FREQADJ: FRACTION Position */ +#define RTC_FREQADJ_FRACTION_Msk (0x3ful << RTC_FREQADJ_FRACTION_Pos) /*!< RTC FREQADJ: FRACTION Mask */ + +#define RTC_FREQADJ_INTEGER_Pos (8) /*!< RTC FREQADJ: INTEGER Position */ +#define RTC_FREQADJ_INTEGER_Msk (0xful << RTC_FREQADJ_INTEGER_Pos) /*!< RTC FREQADJ: INTEGER Mask */ + +#define RTC_TIME_SEC_Pos (0) /*!< RTC TIME: SEC Position */ +#define RTC_TIME_SEC_Msk (0xful << RTC_TIME_SEC_Pos) /*!< RTC TIME: SEC Mask */ + +#define RTC_TIME_TENSEC_Pos (4) /*!< RTC TIME: TENSEC Position */ +#define RTC_TIME_TENSEC_Msk (0x7ul << RTC_TIME_TENSEC_Pos) /*!< RTC TIME: TENSEC Mask */ + +#define RTC_TIME_MIN_Pos (8) /*!< RTC TIME: MIN Position */ +#define RTC_TIME_MIN_Msk (0xful << RTC_TIME_MIN_Pos) /*!< RTC TIME: MIN Mask */ + +#define RTC_TIME_TENMIN_Pos (12) /*!< RTC TIME: TENMIN Position */ +#define RTC_TIME_TENMIN_Msk (0x7ul << RTC_TIME_TENMIN_Pos) /*!< RTC TIME: TENMIN Mask */ + +#define RTC_TIME_HR_Pos (16) /*!< RTC TIME: HR Position */ +#define RTC_TIME_HR_Msk (0xful << RTC_TIME_HR_Pos) /*!< RTC TIME: HR Mask */ + +#define RTC_TIME_TENHR_Pos (20) /*!< RTC TIME: TENHR Position */ +#define RTC_TIME_TENHR_Msk (0x3ul << RTC_TIME_TENHR_Pos) /*!< RTC TIME: TENHR Mask */ + +#define RTC_CAL_DAY_Pos (0) /*!< RTC CAL: DAY Position */ +#define RTC_CAL_DAY_Msk (0xful << RTC_CAL_DAY_Pos) /*!< RTC CAL: DAY Mask */ + +#define RTC_CAL_TENDAY_Pos (4) /*!< RTC CAL: TENDAY Position */ +#define RTC_CAL_TENDAY_Msk (0x3ul << RTC_CAL_TENDAY_Pos) /*!< RTC CAL: TENDAY Mask */ + +#define RTC_CAL_MON_Pos (8) /*!< RTC CAL: MON Position */ +#define RTC_CAL_MON_Msk (0xful << RTC_CAL_MON_Pos) /*!< RTC CAL: MON Mask */ + +#define RTC_CAL_TENMON_Pos (12) /*!< RTC CAL: TENMON Position */ +#define RTC_CAL_TENMON_Msk (0x1ul << RTC_CAL_TENMON_Pos) /*!< RTC CAL: TENMON Mask */ + +#define RTC_CAL_YEAR_Pos (16) /*!< RTC CAL: YEAR Position */ +#define RTC_CAL_YEAR_Msk (0xful << RTC_CAL_YEAR_Pos) /*!< RTC CAL: YEAR Mask */ + +#define RTC_CAL_TENYEAR_Pos (20) /*!< RTC CAL: TENYEAR Position */ +#define RTC_CAL_TENYEAR_Msk (0xful << RTC_CAL_TENYEAR_Pos) /*!< RTC CAL: TENYEAR Mask */ + +#define RTC_TIMEFMT_24HEN_Pos (0) /*!< RTC CLKFMT: 24HEN Position */ +#define RTC_TIMEFMT_24HEN_Msk (0x1ul << RTC_CLKFMT_24HEN_Pos) /*!< RTC CLKFMT: 24HEN Mask */ + +#define RTC_WEEKDAY_WEEKDAY_Pos (0) /*!< RTC WEEKDAY: WEEKDAY Position */ +#define RTC_WEEKDAY_WEEKDAY_Msk (0x7ul << RTC_WEEKDAY_WEEKDAY_Pos) /*!< RTC WEEKDAY: WEEKDAY Mask */ + +#define RTC_TALM_SEC_Pos (0) /*!< RTC TALM: SEC Position */ +#define RTC_TALM_SEC_Msk (0xful << RTC_TALM_SEC_Pos) /*!< RTC TALM: SEC Mask */ + +#define RTC_TALM_TENSEC_Pos (4) /*!< RTC TALM: TENSEC Position */ +#define RTC_TALM_TENSEC_Msk (0x7ul << RTC_TALM_TENSEC_Pos) /*!< RTC TALM: TENSEC Mask */ + +#define RTC_TALM_MIN_Pos (8) /*!< RTC TALM: MIN Position */ +#define RTC_TALM_MIN_Msk (0xful << RTC_TALM_MIN_Pos) /*!< RTC TALM: MIN Mask */ + +#define RTC_TALM_TENMIN_Pos (12) /*!< RTC TALM: TENMIN Position */ +#define RTC_TALM_TENMIN_Msk (0x7ul << RTC_TALM_TENMIN_Pos) /*!< RTC TALM: TENMIN Mask */ + +#define RTC_TALM_HR_Pos (16) /*!< RTC TALM: HR Position */ +#define RTC_TALM_HR_Msk (0xful << RTC_TALM_HR_Pos) /*!< RTC TALM: HR Mask */ + +#define RTC_TALM_TENHR_Pos (20) /*!< RTC TALM: TENHR Position */ +#define RTC_TALM_TENHR_Msk (0x3ul << RTC_TALM_TENHR_Pos) /*!< RTC TALM: TENHR Mask */ + +#define RTC_CALM_DAY_Pos (0) /*!< RTC CALM: DAY Position */ +#define RTC_CALM_DAY_Msk (0xful << RTC_CALM_DAY_Pos) /*!< RTC CALM: DAY Mask */ + +#define RTC_CALM_TENDAY_Pos (4) /*!< RTC CALM: TENDAY Position */ +#define RTC_CALM_TENDAY_Msk (0x3ul << RTC_CALM_TENDAY_Pos) /*!< RTC CALM: TENDAY Mask */ + +#define RTC_CALM_MON_Pos (8) /*!< RTC CALM: MON Position */ +#define RTC_CALM_MON_Msk (0xful << RTC_CALM_MON_Pos) /*!< RTC CALM: MON Mask */ + +#define RTC_CALM_TENMON_Pos (12) /*!< RTC CALM: TENMON Position */ +#define RTC_CALM_TENMON_Msk (0x1ul << RTC_CALM_TENMON_Pos) /*!< RTC CALM: TENMON Mask */ + +#define RTC_CALM_YEAR_Pos (16) /*!< RTC CALM: YEAR Position */ +#define RTC_CALM_YEAR_Msk (0xful << RTC_CALM_YEAR_Pos) /*!< RTC CALM: YEAR Mask */ + +#define RTC_CALM_TENYEAR_Pos (20) /*!< RTC CALM: TENYEAR Position */ +#define RTC_CALM_TENYEAR_Msk (0xful << RTC_CALM_TENYEAR_Pos) /*!< RTC CALM: TENYEAR Mask */ + +#define RTC_CALM_WEEKDAY_Pos (24) /*!< RTC CALM: WEEKDAY Position */ +#define RTC_CALM_WEEKDAY_Msk (0x7ul << RTC_CALM_WEEKDAY_Pos) /*!< RTC CALM: WEEKDAY Mask */ + +#define RTC_CALM_DAYALM_MSK_Pos (28) /*!< RTC CALM: DAYALM_MSK Position */ +#define RTC_CALM_DAYALM_MSK_Msk (0x1ul << RTC_CALM_DAYALM_MSK_Pos) /*!< RTC CALM: DAYALM_MSK Mask */ + +#define RTC_CALM_MONALM_MSK_Pos (29) /*!< RTC CALM: MONALM_MSK Position */ +#define RTC_CALM_MONALM_MSK_Msk (0x1ul << RTC_CALM_MONALM_MSK_Pos) /*!< RTC CALM: MONALM_MSK Mask */ + +#define RTC_CALM_YRALM_MSK_Pos (30) /*!< RTC CALM: YRALM_MSK Position */ +#define RTC_CALM_YRALM_MSK_Msk (0x1ul << RTC_CALM_YRALM_MSK_Pos) /*!< RTC CALM: YRALM_MSK Mask */ + +#define RTC_CALM_WKDALM_MSK_Pos (31) /*!< RTC CALM: WKDALM_MSK Position */ +#define RTC_CALM_WKDALM_MSK_Msk (0x1ul << RTC_CALM_WKDALM_MSK_Pos) /*!< RTC CALM: WKDALM_MSK Mask */ + + +#define RTC_LEAPYEAR_LEAPYEAR_Pos (0) /*!< RTC LEAPYEAR: LEAPYEAR Position */ +#define RTC_LEAPYEAR_LEAPYEAR_Msk (0x1ul << RTC_LEAPYEAR_LEAPYEAR_Pos) /*!< RTC LEAPYEAR: LEAPYEAR Mask */ + +#define RTC_INTEN_ALMIEN_Pos (0) /*!< RTC INTEN: ALMIEN Position */ +#define RTC_INTEN_ALMIEN_Msk (0x1ul << RTC_INTEN_ALMIEN_Pos) /*!< RTC INTEN: ALMIEN Mask */ + +#define RTC_INTEN_TICKIEN_Pos (1) /*!< RTC INTEN: TICKIEN Position */ +#define RTC_INTEN_TICKIEN_Msk (0x1ul << RTC_INTEN_TICKIEN_Pos) /*!< RTC INTEN: TICKIEN Mask */ + +#define RTC_INTEN_WAKEUPIEN_Pos (2) /*!< RTC INTEN: WAKEUPIEN Position */ +#define RTC_INTEN_WAKEUPIEN_Msk (0x1ul << RTC_INTEN_WAKEUPIEN_Pos) /*!< RTC INTEN: WAKEUPIEN Mask */ + +#define RTC_INTEN_PWRSWIEN_Pos (3) /*!< RTC INTEN: PWRSWIEN Position */ +#define RTC_INTEN_PWRSWIEN_Msk (0x1ul << RTC_INTEN_PWRSWIEN_Pos) /*!< RTC INTEN: PWRSWIEN Mask */ + +#define RTC_INTEN_RELALMIEN_Pos (4) /*!< RTC INTEN: RELALMIEN Position */ +#define RTC_INTEN_RELALMIEN_Msk (0x1ul << RTC_INTEN_RELALMIEN_Pos) /*!< RTC INTEN: RELALMIEN Mask */ + +#define RTC_INTEN_KEYPRESIEN_Pos (5) /*!< RTC INTEN: KEYPRESIEN Position */ +#define RTC_INTEN_KEYPRESIEN_Msk (0x1ul << RTC_INTEN_KEYPRESIEN_Pos) /*!< RTC INTEN: KEYPRESIEN Mask */ + + +#define RTC_INTSTS_ALMINT_Pos (0) /*!< RTC INTSTS: ALMINT Position */ +#define RTC_INTSTS_ALMINT_Msk (0x1ul << RTC_INTSTS_ALMINT_Pos) /*!< RTC INTSTS: ALMINT Mask */ + +#define RTC_INTSTS_TICKINT_Pos (1) /*!< RTC INTSTS: TICKINT Position */ +#define RTC_INTSTS_TICKINT_Msk (0x1ul << RTC_INTSTS_TICKINT_Pos) /*!< RTC INTSTS: TICKINT Mask */ + +#define RTC_INTSTS_WAKEUPINT_Pos (2) /*!< RTC INTSTS: WAKEUPINT Position */ +#define RTC_INTSTS_WAKEUPINT_Msk (0x1ul << RTC_INTSTS_WAKEUPINT_Pos) /*!< RTC INTSTS: WAKEUPINT Mask */ + +#define RTC_INTSTS_PWRSWINT_Pos (3) /*!< RTC INTSTS: PWRSWINT Position */ +#define RTC_INTSTS_PWRSWINT_Msk (0x1ul << RTC_INTSTS_PWRSWINT_Pos) /*!< RTC INTSTS: PWRSWINT Mask */ + +#define RTC_INTSTS_RELALMINT_Pos (4) /*!< RTC INTSTS: RELALMINT Position */ +#define RTC_INTSTS_RELALMINT_Msk (0x1ul << RTC_INTSTS_RELALMINT_Pos) /*!< RTC INTSTS: RELALMINT Mask */ + +#define RTC_INTSTS_KEYPRESINT_Pos (5) /*!< RTC INTSTS: KEYPRESINT Position */ +#define RTC_INTSTS_KEYPRESINT_Msk (0x1ul << RTC_INTSTS_KEYPRESINT_Pos) /*!< RTC INTSTS: KEYPRESINT Mask */ + +#define RTC_INTSTS_REGWRBUSY_Pos (31) /*!< RTC INTSTS: REGWRBUSY Position */ +#define RTC_INTSTS_REGWRBUSY_Msk (0x1ul << RTC_INTSTS_REGWRBUSY_Pos) /*!< RTC INTSTS: REGWRBUSY Mask */ + + +#define RTC_TICK_TTR_Pos (0) /*!< RTC TICK: TTR Position */ +#define RTC_TICK_TTR_Msk (0x7ul << RTC_TICK_TTR_Pos) /*!< RTC TICK: TTR Mask */ + +#define RTC_PWRCTL_PWR_ON_Pos (0) /*!< RTC PWRCTL: PWR_ON Position */ +#define RTC_PWRCTL_PWR_ON_Msk (0x1ul << RTC_PWRCTL_PWR_ON_Pos) /*!< RTC PWRCTL: PWR_ON Mask */ + +#define RTC_PWRCTL_SW_PCLR_Pos (1) /*!< RTC PWRCTL: SW_PCLR Position */ +#define RTC_PWRCTL_SW_PCLR_Msk (0x1ul << RTC_PWRCTL_SW_PCLR_Pos) /*!< RTC PWRCTL: SW_PCLR Mask */ + +#define RTC_PWRCTL_HW_PCLR_EN_Pos (2) /*!< RTC PWRCTL: HW_PCLR_EN Position */ +#define RTC_PWRCTL_HW_PCLR_EN_Msk (0x1ul << RTC_PWRCTL_HW_PCLR_EN_Pos) /*!< RTC PWRCTL: HW_PCLR_EN Mask */ + +#define RTC_PWRCTL_ALARM_EN_Pos (3) /*!< RTC PWRCTL: ALARM_EN Position */ +#define RTC_PWRCTL_ALARM_EN_Msk (0x1ul << RTC_PWRCTL_ALARM_EN_Pos) /*!< RTC PWRCTL: ALARM_EN Mask */ + +#define RTC_PWRCTL_REL_ALARM_EN_Pos (4) /*!< RTC PWRCTL: REL_ALARM_EN Position */ +#define RTC_PWRCTL_REL_ALARM_EN_Msk (0x1ul << RTC_PWRCTL_REL_ALARM_EN_Pos) /*!< RTC PWRCTL: REL_ALARM_EN Mask */ + +#define RTC_PWRCTL_EDGE_TRIG_Pos (5) /*!< RTC PWRCTL: EDGE_TRIG Position */ +#define RTC_PWRCTL_EDGE_TRIG_Msk (0x1ul << RTC_PWRCTL_EDGE_TRIG_Pos) /*!< RTC PWRCTL: EDGE_TRIG Mask */ + +#define RTC_PWRCTL_TIMEUNITL_Pos (6) /*!< RTC PWRCTL: TIMEUNITL Position */ +#define RTC_PWRCTL_TIMEUNITL_Msk (0x1ul << RTC_PWRCTL_TIMEUNITLPos) /*!< RTC PWRCTL: TIMEUNITL Mask */ + +#define RTC_PWRCTL_PWR_KEY_Pos (7) /*!< RTC PWRCTL: PWR_KEY Position */ +#define RTC_PWRCTL_PWR_KEY_Msk (0x1ul << RTC_PWRCTL_PWR_KEY_Pos) /*!< RTC PWRCTL: PWR_KEY Mask */ + +#define RTC_PWRCTL_PWRON_TIME_Pos (8) /*!< RTC PWRCTL: PWRON_TIME Position */ +#define RTC_PWRCTL_PWRON_TIME_Msk (0xful << RTC_PWRCTL_PWRON_TIME_Pos) /*!< RTC PWRCTL: PWRON_TIME Mask */ + +#define RTC_PWRCTL_PWROFF_TIME_Pos (12) /*!< RTC PWRCTL: PWROFF_TIME Position */ +#define RTC_PWRCTL_PWROFF_TIME_Msk (0xful << RTC_PWRCTL_PWROFF_TIME_Pos) /*!< RTC PWRCTL: PWROFF_TIME Mask */ + +#define RTC_PWRCTL_RELALM_TIME_Pos (16) /*!< RTC PWRCTL: RELALM_TIME Position */ +#define RTC_PWRCTL_RELALM_TIME_Msk (0xffful << RTC_PWRCTL_RELALM_TIME_Pos) /*!< RTC PWRCTL: RELALM_TIME Mask */ + +#define RTC_PWRCTL_ALARM_MODE_Pos (28) /*!< RTC PWRCTL: ALARM_MODE Position */ +#define RTC_PWRCTL_ALARM_MODE_Msk (0x1ul << RTC_PWRCTL_ALARM_MODE_Pos) /*!< RTC PWRCTL: ALARM_MODE Mask */ + + +#define RTC_SPRCTL_SNPDEN_Pos (0) /*!< RTC SPRCTL: SNPDEN Position */ +#define RTC_SPRCTL_SNPDEN_Msk (0x1ul << RTC_SPRCTL_SNPDEN_Pos) /*!< RTC SPRCTL: SNPDEN Mask */ + +#define RTC_SPRCTL_SNPTYPE0_Pos (1) /*!< RTC SPRCTL: SNPTYPE0 Position */ +#define RTC_SPRCTL_SNPTYPE0_Msk (0x1ul << RTC_SPRCTL_SNPTYPE0_Pos) /*!< RTC SPRCTL: SNPTYPE0 Mask */ + +#define RTC_SPRCTL_SPRRWEN_Pos (2) /*!< RTC SPRCTL: SPRRWEN Position */ +#define RTC_SPRCTL_SPRRWEN_Msk (0x1ul << RTC_SPRCTL_SPRRWEN_Pos) /*!< RTC SPRCTL: SPRRWEN Mask */ + +#define RTC_SPRCTL_SNPTYPE1_Pos (3) /*!< RTC SPRCTL: SNPTYPE1 Position */ +#define RTC_SPRCTL_SNPTYPE1_Msk (0x1ul << RTC_SPRCTL_SNPTYPE1_Pos) /*!< RTC SPRCTL: SNPTYPE1 Mask */ + +#define RTC_SPRCTL_SPRCSTS_Pos (5) /*!< RTC SPRCTL: SPRCSTS Position */ +#define RTC_SPRCTL_SPRCSTS_Msk (0x1ul << RTC_SPRCTL_SPRCSTS_Pos) /*!< RTC SPRCTL: SPRCSTS Mask */ + +#define RTC_SPRCTL_SPRRWRDY_Pos (7) /*!< RTC SPRCTL: SPRRWRDY Position */ +#define RTC_SPRCTL_SPRRWRDY_Msk (0x1ul << RTC_SPRCTL_SPRRWRDY_Pos) /*!< RTC SPRCTL: SPRRWRDY Mask */ + +#define RTC_SPR0_SPARE_Pos (0) /*!< RTC SPR0: SPARE Position */ +#define RTC_SPR0_SPARE_Msk (0xfffffffful << RTC_SPR0_SPARE_Pos) /*!< RTC SPR0: SPARE Mask */ + +#define RTC_SPR1_SPARE_Pos (0) /*!< RTC SPR1: SPARE Position */ +#define RTC_SPR1_SPARE_Msk (0xfffffffful << RTC_SPR1_SPARE_Pos) /*!< RTC SPR1: SPARE Mask */ + +#define RTC_SPR2_SPARE_Pos (0) /*!< RTC SPR2: SPARE Position */ +#define RTC_SPR2_SPARE_Msk (0xfffffffful << RTC_SPR2_SPARE_Pos) /*!< RTC SPR2: SPARE Mask */ + +#define RTC_SPR3_SPARE_Pos (0) /*!< RTC SPR3: SPARE Position */ +#define RTC_SPR3_SPARE_Msk (0xfffffffful << RTC_SPR3_SPARE_Pos) /*!< RTC SPR3: SPARE Mask */ + +#define RTC_SPR4_SPARE_Pos (0) /*!< RTC SPR4: SPARE Position */ +#define RTC_SPR4_SPARE_Msk (0xfffffffful << RTC_SPR4_SPARE_Pos) /*!< RTC SPR4: SPARE Mask */ + +#define RTC_SPR5_SPARE_Pos (0) /*!< RTC SPR5: SPARE Position */ +#define RTC_SPR5_SPARE_Msk (0xfffffffful << RTC_SPR5_SPARE_Pos) /*!< RTC SPR5: SPARE Mask */ + +#define RTC_SPR6_SPARE_Pos (0) /*!< RTC SPR6: SPARE Position */ +#define RTC_SPR6_SPARE_Msk (0xfffffffful << RTC_SPR6_SPARE_Pos) /*!< RTC SPR6: SPARE Mask */ + +#define RTC_SPR7_SPARE_Pos (0) /*!< RTC SPR7: SPARE Position */ +#define RTC_SPR7_SPARE_Msk (0xfffffffful << RTC_SPR7_SPARE_Pos) /*!< RTC SPR7: SPARE Mask */ + +#define RTC_SPR8_SPARE_Pos (0) /*!< RTC SPR8: SPARE Position */ +#define RTC_SPR8_SPARE_Msk (0xfffffffful << RTC_SPR8_SPARE_Pos) /*!< RTC SPR8: SPARE Mask */ + +#define RTC_SPR9_SPARE_Pos (0) /*!< RTC SPR9: SPARE Position */ +#define RTC_SPR9_SPARE_Msk (0xfffffffful << RTC_SPR9_SPARE_Pos) /*!< RTC SPR9: SPARE Mask */ + +#define RTC_SPR10_SPARE_Pos (0) /*!< RTC SPR10: SPARE Position */ +#define RTC_SPR10_SPARE_Msk (0xfffffffful << RTC_SPR10_SPARE_Pos) /*!< RTC SPR10: SPARE Mask */ + +#define RTC_SPR11_SPARE_Pos (0) /*!< RTC SPR11: SPARE Position */ +#define RTC_SPR11_SPARE_Msk (0xfffffffful << RTC_SPR11_SPARE_Pos) /*!< RTC SPR11: SPARE Mask */ + +#define RTC_SPR12_SPARE_Pos (0) /*!< RTC SPR12: SPARE Position */ +#define RTC_SPR12_SPARE_Msk (0xfffffffful << RTC_SPR12_SPARE_Pos) /*!< RTC SPR12: SPARE Mask */ + +#define RTC_SPR13_SPARE_Pos (0) /*!< RTC SPR13: SPARE Position */ +#define RTC_SPR13_SPARE_Msk (0xfffffffful << RTC_SPR13_SPARE_Pos) /*!< RTC SPR13: SPARE Mask */ + +#define RTC_SPR14_SPARE_Pos (0) /*!< RTC SPR14: SPARE Position */ +#define RTC_SPR14_SPARE_Msk (0xfffffffful << RTC_SPR14_SPARE_Pos) /*!< RTC SPR14: SPARE Mask */ + +#define RTC_SPR15_SPARE_Pos (0) /*!< RTC SPR15: SPARE Position */ +#define RTC_SPR15_SPARE_Msk (0xfffffffful << RTC_SPR15_SPARE_Pos) /*!< RTC SPR15: SPARE Mask */ + +#define RTC_SPR16_SPARE_Pos (0) /*!< RTC SPR16: SPARE Position */ +#define RTC_SPR16_SPARE_Msk (0xfffffffful << RTC_SPR16_SPARE_Pos) /*!< RTC SPR16: SPARE Mask */ + +#define RTC_SPR17_SPARE_Pos (0) /*!< RTC SPR17: SPARE Position */ +#define RTC_SPR17_SPARE_Msk (0xfffffffful << RTC_SPR17_SPARE_Pos) /*!< RTC SPR17: SPARE Mask */ + +#define RTC_SPR18_SPARE_Pos (0) /*!< RTC SPR18: SPARE Position */ +#define RTC_SPR18_SPARE_Msk (0xfffffffful << RTC_SPR18_SPARE_Pos) /*!< RTC SPR18: SPARE Mask */ + +#define RTC_SPR19_SPARE_Pos (0) /*!< RTC SPR19: SPARE Position */ +#define RTC_SPR19_SPARE_Msk (0xfffffffful << RTC_SPR19_SPARE_Pos) /*!< RTC SPR19: SPARE Mask */ + +/** + * @brief RTC define interrupt source + */ +typedef enum +{ + RTC_ALARM_INT = 0x01, /*!< Alarm interrupt */ + RTC_TICK_INT = 0x02, /*!< Tick interrupt */ + RTC_WAKEUP_INT = 0x04, /*!< Wake-up interrupt */ + RTC_PSWI_INT = 0x08, /*!< Power switch interrupt */ + RTC_RELATIVE_ALARM_INT = 0x10, /*!< Releative Alarm interrupt */ + RTC_KEY_PRESS_INT = 0x20, /*!< Power Key press interrupt */ + RTC_ALL_INT = 0x3F /*!< All interrupt */ +} RTC_INT_SOURCE; + +/** + * @brief Define Ioctl commands + */ +typedef enum +{ + RTC_IOC_IDENTIFY_LEAP_YEAR = 0, /*!< Identify leap year */ + RTC_IOC_SET_TICK_MODE = 1, /*!< Set tick mode */ + RTC_IOC_GET_TICK = 2, /*!< Get tick count */ + RTC_IOC_RESTORE_TICK = 3, /*!< Reset tick count */ + RTC_IOC_ENABLE_INT = 4, /*!< Enable RTC interrupt */ + RTC_IOC_DISABLE_INT = 5, /*!< Disable RTC interrupt */ + RTC_IOC_SET_CURRENT_TIME = 6, /*!< Set current time */ + RTC_IOC_SET_ALAMRM_TIME = 7, /*!< set alarm time */ + RTC_IOC_SET_FREQUENCY = 8, /*!< Set frequency compensation value */ + RTC_IOC_SET_POWER_ON = 9, /*!< Set Power on */ + RTC_IOC_SET_POWER_OFF = 10, /*!< Set Power off*/ + RTC_IOC_SET_POWER_OFF_PERIOD = 11, /*!< Set Power off period */ + RTC_IOC_ENABLE_HW_POWEROFF = 12, /*!< Enable H/W Power off */ + RTC_IOC_DISABLE_HW_POWEROFF = 13, /*!< Disable H/W Power off */ + RTC_IOC_GET_POWERKEY_STATUS = 14, /*!< Get Power key status */ + RTC_IOC_SET_PSWI_CALLBACK = 15, /*!< Set Power switch isr call back function */ + //RTC_IOC_GET_SW_STATUS = 16, + //RTC_IOC_SET_SW_STATUS = 17, + RTC_IOC_SET_RELEATIVE_ALARM = 18, /*!< Set releative alarm */ + //RTC_IOC_SET_POWER_KEY_DELAY = 19, + //RTC_IOC_SET_CLOCK_SOURCE = 20, + //RTC_IOC_GET_CLOCK_SOURCE = 21 +} E_RTC_CMD; + +/** + * @brief RTC define Tick mode + */ +typedef enum +{ + RTC_TICK_1_SEC = 0, /*!< Time tick is 1 second */ + RTC_TICK_1_2_SEC = 1, /*!< Time tick is 1/2 second */ + RTC_TICK_1_4_SEC = 2, /*!< Time tick is 1/4 second */ + RTC_TICK_1_8_SEC = 3, /*!< Time tick is 1/8 second */ + RTC_TICK_1_16_SEC = 4, /*!< Time tick is 1/16 second */ + RTC_TICK_1_32_SEC = 5, /*!< Time tick is 1/32 second */ + RTC_TICK_1_64_SEC = 6, /*!< Time tick is 1/64 second */ + RTC_TICK_1_128_SEC = 7 /*!< Time tick is 1/128 second */ +} RTC_TICK; + +typedef void (PFN_RTC_CALLBACK)(void); /*!< Call back function \hideinitializer */ + +/** + * @brief RTC current/alarm time select + */ +typedef enum +{ + RTC_CURRENT_TIME = 0, /*!< Select current time */ + RTC_ALARM_TIME = 1 /*!< Select alarm time */ +} E_RTC_TIME_SELECT; + +/** + * @brief RTC define Day of week parameter + */ +typedef enum +{ + RTC_SUNDAY = 0, /*!< Sunday */ + RTC_MONDAY = 1, /*!< Monday */ + RTC_TUESDAY = 2, /*!< Tuesday */ + RTC_WEDNESDAY = 3, /*!< Wednesday */ + RTC_THURSDAY = 4, /*!< Thursday */ + RTC_FRIDAY = 5, /*!< Friday */ + RTC_SATURDAY = 6 /*!< Saturday */ +} E_RTC_DWR_PARAMETER; + + +/** + * @brief RTC define Time Data Struct + */ +typedef struct +{ + UINT8 u8cClockDisplay; /*!< 12-Hour, 24-Hour */ + UINT8 u8cAmPm; /*!< Time Scale select 12-hr/24-hr */ + UINT32 u32cSecond; /*!< Second value */ + UINT32 u32cMinute; /*!< Minute value */ + UINT32 u32cHour; /*!< Hour value */ + UINT32 u32cDayOfWeek; /*!< Day of week value */ + UINT32 u32cDay; /*!< Day value */ + UINT32 u32cMonth; /*!< Month value */ + UINT32 u32Year; /*!< Year value */ + UINT32 u32AlarmMaskSecond; /*!< Alarm mask second */ + UINT32 u32AlarmMaskMinute; /*!< Alarm mask minute */ + UINT32 u32AlarmMaskHour; /*!< Alarm mask hour */ + PFN_RTC_CALLBACK *pfnAlarmCallBack; /*!< Alarm ISR call back function */ +} S_RTC_TIME_DATA_T; + + +/** + * @brief RTC define Tick Struct + */ +typedef struct +{ + UINT8 ucMode; /*!< Tick Mode */ + PFN_RTC_CALLBACK *pfnTickCallBack; /*!< Tick ISR call back function */ +} RTC_TICK_T; + +/*@}*/ /* end of group N9H30_RTC_EXPORTED_CONSTANTS */ + +/** @addtogroup N9H30_RTC_EXPORTED_FUNCTIONS RTC Exported Functions + @{ +*/ + +UINT32 RTC_Init(void); +UINT32 RTC_Open(S_RTC_TIME_DATA_T *sPt); +UINT32 RTC_Ioctl(INT32 i32Num, E_RTC_CMD eCmd, UINT32 u32Arg0, UINT32 u32Arg1); +UINT32 RTC_Read(E_RTC_TIME_SELECT eTime, S_RTC_TIME_DATA_T *sPt); +UINT32 RTC_Write(E_RTC_TIME_SELECT eTime, S_RTC_TIME_DATA_T *sPt); +UINT32 RTC_DoFrequencyCompensation(INT32 i32FrequencyX100); +UINT32 RTC_WriteEnable(BOOL bEnable); +UINT32 RTC_Close(void); +void RTC_EnableClock(BOOL bEnable); +VOID RTC_Check(void); + +#define RTC_DisableInt(u32IntFlag) RTC_Ioctl(0, RTC_IOC_DISABLE_INT, u32IntFlag, 0) +#define RTC_EnableInt(u32IntFlag) RTC_Ioctl(0, RTC_IOC_ENABLE_INT, u32IntFlag, 0) +#define RTC_GET_TICK_INT_FLAG() (inp32(REG_RTC_INTSTS)&RTC_TICK_INT) +#define RTC_GET_ALARM_INT_FLAG() (inp32(REG_RTC_INTSTS)&RTC_ALARM_INT) + +static __inline void RTC_CLEAR_TICK_INT_FLAG(void) +{ + RTC_WriteEnable(1); + outp32(REG_RTC_INTSTS, RTC_TICK_INT); + RTC_Check(); +} + +static __inline void RTC_CLEAR_ALARM_INT_FLAG(void) +{ + RTC_WriteEnable(1); + outp32(REG_RTC_INTSTS, RTC_ALARM_INT); + RTC_Check(); +} + + +/*@}*/ /* end of group N9H30_RTC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_RTC_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_RTC_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + + + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_scuart.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_scuart.h new file mode 100644 index 0000000000..58746264ee --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_scuart.h @@ -0,0 +1,335 @@ +/**************************************************************************//** + * @file scuart.h + * @brief N9H30 series Smartcard UART mode (SCUART) driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_SCUART_H__ +#define __NU_SCUART_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_SCUART_Driver SCUART Driver + @{ +*/ + +/** @addtogroup N9H30_SCUART_EXPORTED_CONSTANTS SCUART Exported Constants + @{ +*/ +#define SCUART_CHAR_LEN_5 (0x3ul << 4) /*!< Set SCUART word length to 5 bits */ +#define SCUART_CHAR_LEN_6 (0x2ul << 4) /*!< Set SCUART word length to 6 bits */ +#define SCUART_CHAR_LEN_7 (0x1ul << 4) /*!< Set SCUART word length to 7 bits */ +#define SCUART_CHAR_LEN_8 (0) /*!< Set SCUART word length to 8 bits */ + +#define SCUART_PARITY_NONE (0x00000040) /*!< Set SCUART transfer with no parity */ +#define SCUART_PARITY_ODD (0x00000080) /*!< Set SCUART transfer with odd parity */ +#define SCUART_PARITY_EVEN (0) /*!< Set SCUART transfer with even parity */ + +#define SCUART_STOP_BIT_1 (0x00008000) /*!< Set SCUART transfer with one stop bit */ +#define SCUART_STOP_BIT_2 (0) /*!< Set SCUART transfer with two stop bits */ + +#define SC_STATUS_RXEMPTY_Msk 0x00000002 +#define SC_STATUS_RXFULL_Msk 0x00000004 +#define SC_STATUS_PEF_Msk 0x00000010 +#define SC_STATUS_FEF_Msk 0x00000020 +#define SC_STATUS_BEF_Msk 0x00000040 +#define SC_STATUS_TXEMPTY_Msk 0x00000200 +#define SC_STATUS_TXFULL_Msk 0x00000400 +#define SC_STATUS_TXACT_Msk 0x80000000 + +#define SC_INTEN_RXTOIEN_Msk 0x00000200 +#define SC_INTEN_TERRIEN_Msk 0x00000004 +#define SC_INTEN_TBEIEN_Msk 0x00000002 +#define SC_INTEN_RDAIEN_Msk 0x00000001 + +#define SC_INTSTS_RBTOIF_Msk 0x00000200 +#define SC_INTSTS_TERRIF_Msk 0x00000004 +#define SC_INTSTS_TBEIF_Msk 0x00000002 +#define SC_INTSTS_RDAIF_Msk 0x00000001 + +#define SC_CTL_SCEN_Msk 0x00000001 +#define SC_CTL_NSB_Msk 0x00008000 + +#define SC_UARTCTL_UARTEN_Msk 0x00000001 + +/*@}*/ /* end of group N9H30_SCUART_EXPORTED_CONSTANTS */ + + +/** @addtogroup N9H30_SCUART_EXPORTED_FUNCTIONS SCUART Exported Functions + @{ +*/ + +/* TX Macros */ +/** + * @brief Write Data to Tx data register. + * @param[in] sc Smartcard module number + * @param[in] u8Data Data byte to transmit. + * @return None + * @details By writing data to DAT register, the SC will send out an 8-bit data. + * \hideinitializer + */ +#define SCUART_WRITE(sc, u8Data) \ +do {\ + if(sc == 0)\ + outpw(REG_SC0_DAT, u8Data);\ + else\ + outpw(REG_SC1_DAT, u8Data);\ +}while(0) + +/** + * @brief Get TX FIFO empty flag status from register. + * @param[in] sc Smartcard module number + * @return Transmit FIFO empty status. + * @retval 0 Transmit FIFO is not empty. + * @retval SC_STATUS_TXEMPTY_Msk Transmit FIFO is empty. + * @details When the last byte of TX buffer has been transferred to Transmitter Shift Register, hardware sets TXEMPTY bit (SC_STATUS[9]) high. + * It will be cleared when writing data into DAT (SC_DAT[7:0]). + * \hideinitializer + */ +#define SCUART_GET_TX_EMPTY(sc) (sc == 0 ? (inpw(REG_SC0_STATUS) & SC_STATUS_TXEMPTY_Msk) : (inpw(REG_SC1_STATUS) & SC_STATUS_TXEMPTY_Msk)) + +/** + * @brief Get TX FIFO full flag status from register. + * @param[in] sc Smartcard module number + * @retval 0 Transmit FIFO is not full. + * @retval SC_STATUS_TXFULL_Msk Transmit FIFO is full. + * @details TXFULL(SC_STATUS[10]) is set when TX pointer is equal to 4, otherwise is cleared by hardware. + * \hideinitializer + */ +#define SCUART_GET_TX_FULL(sc) (sc == 0 ? (inpw(REG_SC0_STATUS) & SC_STATUS_TXFULL_Msk) : (inpw(REG_SC1_STATUS) & SC_STATUS_TXFULL_Msk)) + +/** + * @brief Wait specified smartcard port transmission complete. + * @param[in] sc Smartcard module number + * @return None + * @details TXACT (SC_STATUS[31]) is cleared automatically when TX transfer is finished or the last byte transmission has completed. + * @note This macro blocks until transmit complete. + * \hideinitializer + */ +#define SCUART_WAIT_TX_EMPTY(sc)\ +do {\ + if(sc == 0)\ + while(inpw(REG_SC0_STATUS) & SC_STATUS_TXACT_Msk);\ + else\ + while(inpw(REG_SC1_STATUS) & SC_STATUS_TXACT_Msk);\ +}while(0) + +/** + * @brief Check specified smartcard port transmit FIFO is full or not. + * @param[in] sc Smartcard module number + * @retval 0 Transmit FIFO is not full. + * @retval 1 Transmit FIFO is full. + * @details TXFULL(SC_STATUS[10]) indicates TX buffer full or not. + * This is set when TX pointer is equal to 4, otherwise is cleared by hardware. + * \hideinitializer + */ +#define SCUART_IS_TX_FULL(sc) (sc == 0 ? (inpw(REG_SC0_STATUS) & SC_STATUS_TXFULL_Msk ? 1 : 0) : (inpw(REG_SC1_STATUS) & SC_STATUS_TXFULL_Msk ? 1 : 0)) + +/** + * @brief Check specified smartcard port transmission is over. + * @param[in] sc Smartcard module number + * @retval 0 Transmit is not complete. + * @retval 1 Transmit complete. + * @details TXACT (SC_STATUS[31]) is set by hardware when TX transfer is in active and the STOP bit of the last byte has been transmitted. + * \hideinitializer + */ +#define SCUART_IS_TX_EMPTY(sc) (sc == 0 ? (inpw(REG_SC0_STATUS) & SC_STATUS_TXACT_Msk ? 1 : 0) : (inpw(REG_SC1_STATUS) & SC_STATUS_TXACT_Msk ? 1 : 0)) + +/* RX Macros */ + +/** + * @brief Read Rx data register. + * @param[in] sc Smartcard module number + * @return The oldest data byte in RX FIFO. + * @details By reading DAT register, the SC will return an 8-bit received data. + * \hideinitializer + */ +#define SCUART_READ(sc) (sc == 0 ? inpw(REG_SC0_DAT) : inpw(REG_SC1_DAT)) + +/** + * @brief Get RX FIFO empty flag status from register. + * @param[in] sc Smartcard module number + * @retval 0 Receive FIFO is not empty. + * @retval SC_STATUS_RXEMPTY_Msk Receive FIFO is empty. + * @details When the last byte of Rx buffer has been read by CPU, hardware sets RXEMPTY(SC_STATUS[1]) high. + * It will be cleared when SC receives any new data. + * \hideinitializer + */ +#define SCUART_GET_RX_EMPTY(sc) (sc == 0 ? (inpw(REG_SC0_STATUS) & SC_STATUS_RXEMPTY_Msk) : (inpw(REG_SC1_STATUS) & SC_STATUS_RXEMPTY_Msk)) + + +/** + * @brief Get RX FIFO full flag status from register. + * @param[in] sc Smartcard module number + * @retval 0 Receive FIFO is not full. + * @retval SC_STATUS_RXFULL_Msk Receive FIFO is full. + * @details RXFULLF(SC_STATUS[2]) is set when RX pointer is equal to 4, otherwise it is cleared by hardware. + * \hideinitializer + */ +#define SCUART_GET_RX_FULL(sc) (sc == 0 ? (inpw(REG_SC0_STATUS) & SC_STATUS_RXFULL_Msk) : (inpw(REG_SC1_STATUS) & SC_STATUS_RXFULL_Msk)) + +/** + * @brief Check if receive data number in FIFO reach FIFO trigger level or not. + * @param[in] sc Smartcard module number + * @retval 0 The number of bytes in receive FIFO is less than trigger level. + * @retval 1 The number of bytes in receive FIFO equals or larger than trigger level. + * @details RDAIF(SC_INTSTS[0]) is used for received data reaching trigger level RXTRGLV (SC_CTL[7:6]) interrupt status flag. + * @note If receive trigger level is \b not 1 byte, this macro return 0 does not necessary indicates there is no data in FIFO. + * \hideinitializer + */ +#define SCUART_IS_RX_READY(sc) (sc == 0 ? (inpw(REG_SC0_INTSTS) & SC_INTSTS_RDAIF_Msk ? 1 : 0) : (inpw(REG_SC1_INTSTS) & SC_INTSTS_RDAIF_Msk ? 1 : 0)) + +/** + * @brief Check specified smartcard port receive FIFO is full or not. + * @param[in] sc Smartcard module number + * @retval 0 Receive FIFO is not full. + * @retval 1 Receive FIFO is full. + * @details RXFULLF(SC_STATUS[2]) is set when RX pointer is equal to 4, otherwise it is cleared by hardware. + * \hideinitializer + */ +#define SCUART_IS_RX_FULL(sc) (sc == 0 ? (inpw(REG_SC0_STATUS) & SC_STATUS_RXFULL_Msk ? 1 : 0) : (inpw(REG_SC1_STATUS) & SC_STATUS_RXFULL_Msk ? 1 : 0)) + +/* Interrupt Macros */ + +/** + * @brief Enable specified interrupts. + * @param[in] sc Smartcard module number + * @param[in] u32Mask Interrupt masks to enable, a combination of following bits. + * - \ref SC_INTEN_RXTOIEN_Msk + * - \ref SC_INTEN_TERRIEN_Msk + * - \ref SC_INTEN_TBEIEN_Msk + * - \ref SC_INTEN_RDAIEN_Msk + * @return None + * @details The macro is used to enable receiver buffer time-out interrupt, transfer error interrupt, + * transmit buffer empty interrupt or receive data reach trigger level interrupt. + * \hideinitializer + */ +#define SCUART_ENABLE_INT(sc, u32Mask)\ +do {\ + if(sc == 0)\ + outpw(REG_SC0_INTEN, inpw(REG_SC0_INTEN) | (u32Mask));\ + else\ + outpw(REG_SC1_INTEN, inpw(REG_SC1_INTEN) | (u32Mask));\ +}while(0) + +/** + * @brief Disable specified interrupts. + * @param[in] sc Smartcard module number + * @param[in] u32Mask Interrupt masks to disable, a combination of following bits. + * - \ref SC_INTEN_RXTOIEN_Msk + * - \ref SC_INTEN_TERRIEN_Msk + * - \ref SC_INTEN_TBEIEN_Msk + * - \ref SC_INTEN_RDAIEN_Msk + * @return None + * @details The macro is used to disable receiver buffer time-out interrupt, transfer error interrupt, + * transmit buffer empty interrupt or receive data reach trigger level interrupt. + * \hideinitializer + */ +#define SCUART_DISABLE_INT(sc, u32Mask)\ +do {\ + if(sc == 0)\ + outpw(REG_SC0_INTEN, inpw(REG_SC0_INTEN) & ~(u32Mask));\ + else\ + outpw(REG_SC1_INTEN, inpw(REG_SC1_INTEN) & ~(u32Mask));\ +}while(0) + +/** + * @brief Get specified interrupt flag/status. + * @param[in] sc Smartcard module number + * @param[in] u32Type Interrupt flag/status to check, could be one of following value: + * - \ref SC_INTSTS_RBTOIF_Msk + * - \ref SC_INTSTS_TERRIF_Msk + * - \ref SC_INTSTS_TBEIF_Msk + * - \ref SC_INTSTS_RDAIF_Msk + * @return The status of specified interrupt. + * @retval 0 Specified interrupt does not happened. + * @retval 1 Specified interrupt happened. + * @details The macro is used to get receiver buffer time-out interrupt status, transfer error interrupt status, + * transmit buffer empty interrupt status or receive data reach interrupt status. + * \hideinitializer + */ +#define SCUART_GET_INT_FLAG(sc, u32Type) (sc == 0 ? (inpw(REG_SC0_INTSTS) & (u32Type) ? 1 : 0) : (inpw(REG_SC1_INTSTS) & (u32Type) ? 1 : 0)) + +/** + * @brief Clear specified interrupt flag/status. + * @param[in] sc Smartcard module number + * @param[in] u32Type Interrupt flag/status to clear, could be the combination of following values: + * - \ref SC_INTSTS_RBTOIF_Msk + * - \ref SC_INTSTS_TERRIF_Msk + * - \ref SC_INTSTS_TBEIF_Msk + * @return None + * @details The macro is used to clear receiver buffer time-out interrupt flag, transfer error interrupt flag or + * transmit buffer empty interrupt flag. + * \hideinitializer + */ +#define SCUART_CLR_INT_FLAG(sc, u32Type) \ +do {\ + if(sc == 0)\ + outpw(REG_SC0_INTSTS, (u32Type));\ + else\ + outpw(REG_SC1_INTSTS, (u32Type));\ +}while(0) + +/** + * @brief Get receive error flag/status. + * @param[in] sc Smartcard module number + * @return Current receive error status, could one of following errors: + * @retval SC_STATUS_PEF_Msk Parity error. + * @retval SC_STATUS_FEF_Msk Frame error. + * @retval SC_STATUS_BEF_Msk Break error. + * @details The macro is used to get receiver parity error status, receiver frame error status or + * receiver break error status. + * \hideinitializer + */ +#define SCUART_GET_ERR_FLAG(sc) (sc == 0 ? (inpw(REG_SC0_STATUS) & (SC_STATUS_PEF_Msk | SC_STATUS_FEF_Msk | SC_STATUS_BEF_Msk)) : (inpw(REG_SC1_STATUS) & (SC_STATUS_PEF_Msk | SC_STATUS_FEF_Msk | SC_STATUS_BEF_Msk))) + +/** + * @brief Clear specified receive error flag/status. + * @param[in] sc Smartcard module number + * @param[in] u32Mask Receive error flag/status to clear, combination following values: + * - \ref SC_STATUS_PEF_Msk + * - \ref SC_STATUS_FEF_Msk + * - \ref SC_STATUS_BEF_Msk + * @return None + * @details The macro is used to clear receiver parity error flag, receiver frame error flag or + * receiver break error flag. + * \hideinitializer + */ +#define SCUART_CLR_ERR_FLAG(sc, u32Mask)\ +do {\ + if(sc == 0)\ + outpw(REG_SC0_STATUS, (u32Mask));\ + else\ + outpw(REG_SC1_STATUS, (u32Mask));\ +}while(0) + +void SCUART_Close(UINT sc); +UINT SCUART_Open(UINT sc, UINT u32baudrate); +UINT SCUART_Read(UINT sc, char *pu8RxBuf, UINT u32ReadBytes); +UINT SCUART_SetLineConfig(UINT sc, UINT u32Baudrate, UINT u32DataWidth, UINT u32Parity, UINT u32StopBits); +void SCUART_SetTimeoutCnt(UINT sc, UINT u32TOC); +void SCUART_Write(UINT sc, char *pu8TxBuf, UINT u32WriteBytes); + +/*@}*/ /* end of group N9H30_SCUART_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_SCUART_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_SCUART_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_sdh.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_sdh.h new file mode 100644 index 0000000000..2171f2ff71 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_sdh.h @@ -0,0 +1,757 @@ +/**************************************************************************//** + * @file sdh.h + * @brief N9H30 SDH driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include + +#ifndef __NU_SDH_H__ +#define __NU_SDH_H__ + +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +#define TIMER0 0 + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup SDH SD/SDIO Host Controller(SDH) + Memory Mapped Structure for SDH Controller +@{ */ + +typedef struct +{ + + /** + * @var SDH_T::FB + * Offset: 0x00~0x7C Shared Buffer (FIFO) + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |BUFFER |Shared Buffer + * | | |Buffer for DMA transfer + * @var SDH_T::DMACTL + * Offset: 0x400 DMA Control and Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |DMAEN |DMA Engine Enable Bit + * | | |0 = DMA Disabled. + * | | |1 = DMA Enabled. + * | | |If this bit is cleared, DMA will ignore all requests from SD host and force bus master into IDLE state. + * | | |Note: If target abort is occurred, DMAEN will be cleared. + * |[1] |DMARST |Software Engine Reset + * | | |0 = No effect. + * | | |1 = Reset internal state machine and pointers + * | | |The contents of control register will not be cleared + * | | |This bit will auto be cleared after few clock cycles. + * | | |Note: The software reset DMA related registers. + * |[3] |SGEN |Scatter-gather Function Enable Bit + * | | |0 = Scatter-gather function Disabled (DMA will treat the starting address in DMASAR as starting pointer of a single block memory). + * | | |1 = Scatter-gather function Enabled (DMA will treat the starting address in DMASAR as a starting address of Physical Address Descriptor (PAD) table + * | | |The format of these Pads' will be described later). + * |[9] |DMABUSY |DMA Transfer Is in Progress + * | | |This bit indicates if SD Host is granted and doing DMA transfer or not. + * | | |0 = DMA transfer is not in progress. + * | | |1 = DMA transfer is in progress. + * @var SDH_T::DMASA + * Offset: 0x408 DMA Transfer Starting Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ORDER |Determined to the PAD Table Fetching Is in Order or Out of Order + * | | |0 = PAD table is fetched in order. + * | | |1 = PAD table is fetched out of order. + * | | |Note: the bit0 is valid in scatter-gather mode when SGEN = 1. + * |[31:1] |DMASA |DMA Transfer Starting Address + * | | |This field pads 0 as least significant bit indicates a 32-bit starting address of system memory (SRAM) for DMA to retrieve or fill in data. + * | | |If DMA is not in normal mode, this field will be interpreted as a starting address of Physical Address Descriptor (PAD) table. + * | | |Note: Starting address of the SRAM must be word aligned, for example, 0x0000_0000, 0x0000_0004. + * @var SDH_T::DMABCNT + * Offset: 0x40C DMA Transfer Byte Count Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[25:0] |BCNT |DMA Transfer Byte Count (Read Only) + * | | |This field indicates the remained byte count of DMA transfer + * | | |The value of this field is valid only when DMA is busy; otherwise, it is 0. + * @var SDH_T::DMAINTEN + * Offset: 0x410 DMA Interrupt Enable Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ABORTIEN |DMA Read/Write Target Abort Interrupt Enable Bit + * | | |0 = Target abort interrupt generation Disabled during DMA transfer. + * | | |1 = Target abort interrupt generation Enabled during DMA transfer. + * |[1] |WEOTIEN |Wrong EOT Encountered Interrupt Enable Bit + * | | |0 = Interrupt generation Disabled when wrong EOT is encountered. + * | | |1 = Interrupt generation Enabled when wrong EOT is encountered. + * @var SDH_T::DMAINTSTS + * Offset: 0x414 DMA Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ABORTIF |DMA Read/Write Target Abort Interrupt Flag + * | | |0 = No bus ERROR response received. + * | | |1 = Bus ERROR response received. + * | | |Note1: This bit is read only, but can be cleared by writing '1' to it. + * | | |Note2: When DMA's bus master received ERROR response, it means that target abort is happened + * | | |DMA will stop transfer and respond this event and then go to IDLE state + * | | |When target abort occurred or WEOTIF is set, software must reset DMA and SD host, and then transfer those data again. + * |[1] |WEOTIF |Wrong EOT Encountered Interrupt Flag + * | | |When DMA Scatter-Gather function is enabled, and EOT of the descriptor is encountered before DMA transfer finished (that means the total sector count of all PAD is less than the sector count of SD host), this bit will be set. + * | | |0 = No EOT encountered before DMA transfer finished. + * | | |1 = EOT encountered before DMA transfer finished. + * | | |Note: This bit is read only, but can be cleared by writing '1' to it. + * @var SDH_T::GCTL + * Offset: 0x800 Global Control and Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |GCTLRST |Software Engine Reset + * | | |0 = No effect. + * | | |1 = Reset SD host + * | | |The contents of control register will not be cleared + * | | |This bit will auto cleared after reset complete. + * |[1] |SDEN |Secure Digital Functionality Enable Bit + * | | |0 = SD functionality disabled. + * | | |1 = SD functionality enabled. + * @var SDH_T::GINTEN + * Offset: 0x804 Global Interrupt Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |DTAIEN |DMA READ/WRITE Target Abort Interrupt Enable Bit + * | | |0 = DMA READ/WRITE target abort interrupt generation disabled. + * | | |1 = DMA READ/WRITE target abort interrupt generation enabled. + * @var SDH_T::GINTSTS + * Offset: 0x808 Global Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |DTAIF |DMA READ/WRITE Target Abort Interrupt Flag (Read Only) + * | | |This bit indicates DMA received an ERROR response from internal AHB bus during DMA read/write operation + * | | |When Target Abort is occurred, please reset all engine. + * | | |0 = No bus ERROR response received. + * | | |1 = Bus ERROR response received. + * | | |Note: This bit is read only, but can be cleared by writing '1' to it. + * @var SDH_T::CTL + * Offset: 0x820 SD Control and Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |COEN |Command Output Enable Bit + * | | |0 = No effect. (Please use DMARST (SDH_CTL [0]) to clear this bit.) + * | | |1 = Enabled, SD host will output a command to SD card. + * | | |Note: When operation is finished, this bit will be cleared automatically, so don't write 0 to this bit (the controller will be abnormal). + * |[1] |RIEN |Response Input Enable Bit + * | | |0 = No effect. (Please use DMARST (SDH_CTL [0]) to clear this bit.) + * | | |1 = Enabled, SD host will wait to receive a response from SD card. + * | | |Note: When operation is finished, this bit will be cleared automatically, so don't write 0 to this bit (the controller will be abnormal). + * |[2] |DIEN |Data Input Enable Bit + * | | |0 = No effect. (Please use DMARST (SDH_CTL [0]) to clear this bit.) + * | | |1 = Enabled, SD host will wait to receive block data and the CRC16 value from SD card. + * | | |Note: When operation is finished, this bit will be cleared automatically, so don't write 0 to this bit (the controller will be abnormal). + * |[3] |DOEN |Data Output Enable Bit + * | | |0 = No effect. (Please use DMARST (SDH_CTL [0]) to clear this bit.) + * | | |1 = Enabled, SD host will transfer block data and the CRC16 value to SD card. + * | | |Note: When operation is finished, this bit will be cleared automatically, so don't write 0 to this bit (the controller will be abnormal). + * |[4] |R2EN |Response R2 Input Enable Bit + * | | |0 = No effect. (Please use DMARST (SDH_CTL [0]) to clear this bit.) + * | | |1 = Enabled, SD host will wait to receive a response R2 from SD card and store the response data into DMC's flash buffer (exclude CRC7). + * | | |Note: When operation is finished, this bit will be cleared automatically, so don't write 0 to this bit (the controller will be abnormal). + * |[5] |CLK74OEN |Initial 74 Clock Cycles Output Enable Bit + * | | |0 = No effect. (Please use DMARST (SDH_CTL [0]) to clear this bit.) + * | | |1 = Enabled, SD host will output 74 clock cycles to SD card. + * | | |Note: When operation is finished, this bit will be cleared automatically, so don't write 0 to this bit (the controller will be abnormal). + * |[6] |CLK8OEN |Generating 8 Clock Cycles Output Enable Bit + * | | |0 = No effect. (Please use DMARST (SDH_CTL [0]) to clear this bit.) + * | | |1 = Enabled, SD host will output 8 clock cycles. + * | | |Note: When operation is finished, this bit will be cleared automatically, so don't write 0 to this bit (the controller will be abnormal). + * |[7] |CLKKEEP |SD Clock Enable Control + * | | |0 = SD host decided when to output clock and when to disable clock output automatically. + * | | |1 = SD clock always keeps free running. + * |[13:8] |CMDCODE |SD Command Code + * | | |This register contains the SD command code (0x00 - 0x3F). + * |[14] |CTLRST |Software Engine Reset + * | | |0 = No effect. + * | | |1 = Reset the internal state machine and counters + * | | |The contents of control register will not be cleared (but RIEN, DIEN, DOEN and R2_EN will be cleared) + * | | |This bit will be auto cleared after few clock cycles. + * |[15] |DBW |SD Data Bus Width (for 1-bit / 4-bit Selection) + * | | |0 = Data bus width is 1-bit. + * | | |1 = Data bus width is 4-bit. + * |[23:16] |BLKCNT |Block Counts to Be Transferred or Received + * | | |This field contains the block counts for data-in and data-out transfer + * | | |For READ_MULTIPLE_BLOCK and WRITE_MULTIPLE_BLOCK command, software can use this function to accelerate data transfer and improve performance + * | | |Don't fill 0x0 to this field. + * | | |Note: For READ_MULTIPLE_BLOCK and WRITE_MULTIPLE_BLOCK command, the actual total length is BLKCNT * (BLKLEN +1). + * |[27:24] |SDNWR |NWR Parameter for Block Write Operation + * | | |This value indicates the NWR parameter for data block write operation in SD clock counts + * | | |The actual clock cycle will be SDNWR+1. + * @var SDH_T::CMDARG + * Offset: 0x824 SD Command Argument Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |ARGUMENT |SD Command Argument + * | | |This register contains a 32-bit value specifies the argument of SD command from host controller to SD card + * | | |Before trigger COEN (SDH_CTL [0]), software should fill argument in this field. + * @var SDH_T::INTEN + * Offset: 0x828 SD Interrupt Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BLKDIEN |Block Transfer Done Interrupt Enable Bit + * | | |0 = BLKDIF (SDH_INTEN[0]) trigger interrupt Disable. + * | | |1 = BLKDIF (SDH_INTEN[0]) trigger interrupt Enabled. + * |[1] |CRCIEN |CRC7, CRC16 and CRC Status Error Interrupt Enable Bit + * | | |0 = CRCIF (SDH_INTEN[1]) trigger interrupt Disable. + * | | |1 = CRCIF (SDH_INTEN[1]) trigger interrupt Enabled. + * |[8] |CDIEN |SD Card Detection Interrupt Enable Bit + * | | |Enable/Disable interrupts generation of SD controller when card is inserted or removed. + * | | |0 = CDIF (SDH_INTEN[8]) trigger interrupt Disable. + * | | |1 = CDIF (SDH_INTEN[8]) trigger interrupt Enabled. + * |[12] |RTOIEN |Response Time-out Interrupt Enable Bit + * | | |Enable/Disable interrupts generation of SD controller when receiving response or R2 time-out + * | | |Time-out value is specified at TOUT register. + * | | |0 = RTOIF (SDH_INTEN[12]) trigger interrupt Disabled. + * | | |1 = RTOIF (SDH_INTEN[12]) trigger interrupt Enabled. + * |[13] |DITOIEN |Data Input Time-out Interrupt Enable Bit + * | | |Enable/Disable interrupts generation of SD controller when data input time-out + * | | |Time-out value is specified at TOUT register. + * | | |0 = DITOIF (SDH_INTEN[13]) trigger interrupt Disabled. + * | | |1 = DITOIF (SDH_INTEN[13]) trigger interrupt Enabled. + * |[14] |WKIEN |Wake-up Signal Generating Enable Bit + * | | |Enable/Disable wake-up signal generating of SD host when current using SD card issues an interrupt (wake-up) via DAT [1] to host. + * | | |0 = SD Card interrupt to wake-up chip Disabled. + * | | |1 = SD Card interrupt to wake-up chip Enabled. + * |[30] |CDSRC |SD Card Detect Source Selection + * | | |0 = From SD card's DAT3 pin. + * | | |Host need clock to got data on pin DAT3 + * | | |Please make sure CLKKEEP (SDH_CTL[7]) is 1 in order to generate free running clock for DAT3 pin. + * | | |1 = From GPIO pin. + * @var SDH_T::INTSTS + * Offset: 0x82C SD Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BLKDIF |Block Transfer Done Interrupt Flag (Read Only) + * | | |This bit indicates that SD host has finished all data-in or data-out block transfer + * | | |If there is a CRC16 error or incorrect CRC status during multiple block data transfer, the transfer will be broken and this bit will also be set. + * | | |0 = Not finished yet. + * | | |1 = Done. + * | | |Note: This bit is read only, but can be cleared by writing '1' to it. + * |[1] |CRCIF |CRC7, CRC16 and CRC Status Error Interrupt Flag (Read Only) + * | | |This bit indicates that SD host has occurred CRC error during response in, data-in or data-out (CRC status error) transfer + * | | |When CRC error is occurred, software should reset SD engine + * | | |Some response (ex + * | | |R3) doesn't have CRC7 information with it; SD host will still calculate CRC7, get CRC error and set this flag + * | | |In this condition, software should ignore CRC error and clears this bit manually. + * | | |0 = No CRC error is occurred. + * | | |1 = CRC error is occurred. + * | | |Note: This bit is read only, but can be cleared by writing '1' to it. + * |[2] |CRC7 |CRC7 Check Status (Read Only) + * | | |SD host will check CRC7 correctness during each response in + * | | |If that response does not contain CRC7 information (ex + * | | |R3), then software should turn off CRCIEN (SDH_INTEN[1]) and ignore this bit. + * | | |0 = Fault. + * | | |1 = OK. + * |[3] |CRC16 |CRC16 Check Status of Data-in Transfer (Read Only) + * | | |SD host will check CRC16 correctness after data-in transfer. + * | | |0 = Fault. + * | | |1 = OK. + * |[6:4] |CRCSTS |CRC Status Value of Data-out Transfer (Read Only) + * | | |SD host will record CRC status of data-out transfer + * | | |Software could use this value to identify what type of error is during data-out transfer. + * | | |010 = Positive CRC status. + * | | |101 = Negative CRC status. + * | | |111 = SD card programming error occurs. + * |[7] |DAT0STS |DAT0 Pin Status of Current Selected SD Port (Read Only) + * | | |This bit is the DAT0 pin status of current selected SD port. + * |[8] |CDIF |SD Card Detection Interrupt Flag (Read Only) + * | | |This bit indicates that SD card is inserted or removed + * | | |Only when CDIEN (SDH_INTEN[8]) is set to 1, this bit is active. + * | | |0 = No card is inserted or removed. + * | | |1 = There is a card inserted in or removed from SD. + * | | |Note: This bit is read only, but can be cleared by writing '1' to it. + * |[12] |RTOIF |Response Time-out Interrupt Flag (Read Only) + * | | |This bit indicates that SD host counts to time-out value when receiving response or R2 (waiting start bit). + * | | |0 = Not time-out. + * | | |1 = Response time-out. + * | | |Note: This bit is read only, but can be cleared by writing '1' to it. + * |[13] |DITOIF |Data Input Time-out Interrupt Flag (Read Only) + * | | |This bit indicates that SD host counts to time-out value when receiving data (waiting start bit). + * | | |0 = Not time-out. + * | | |1 = Data input time-out. + * | | |Note: This bit is read only, but can be cleared by writing '1' to it. + * |[16] |CDSTS |Card Detect Status of SD (Read Only) + * | | |This bit indicates the card detect pin status of SD, and is used for card detection + * | | |When there is a card inserted in or removed from SD, software should check this bit to confirm if there is really a card insertion or removal. + * | | |If CDSRC (SDH_INTEN[30]) = 0, to select DAT3 for card detection:. + * | | |0 = Card removed. + * | | |1 = Card inserted. + * | | |If CDSRC (SDH_INTEN[30]) = 1, to select GPIO for card detection:. + * | | |0 = Card inserted. + * | | |1 = Card removed. + * |[18] |DAT1STS |DAT1 Pin Status of SD Port (Read Only) + * | | |This bit indicates the DAT1 pin status of SD port. + * @var SDH_T::RESP0 + * Offset: 0x830 SD Receiving Response Token Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |RESPTK0 |SD Receiving Response Token 0 + * | | |SD host controller will receive a response token for getting a reply from SD card when RIEN (SDH_CTL[1]) is set + * | | |This field contains response bit 47-16 of the response token. + * @var SDH_T::RESP1 + * Offset: 0x834 SD Receiving Response Token Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |RESPTK1 |SD Receiving Response Token 1 + * | | |SD host controller will receive a response token for getting a reply from SD card when RIEN (SDH_CTL[1]) is set + * | | |This register contains the bit 15-8 of the response token. + * @var SDH_T::BLEN + * Offset: 0x838 SD Block Length Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[10:0] |BLKLEN |SD BLOCK LENGTH in Byte Unit + * | | |An 11-bit value specifies the SD transfer byte count of a block + * | | |The actual byte count is equal to BLKLEN+1. + * | | |Note: The default SD block length is 512 bytes + * @var SDH_T::TOUT + * Offset: 0x83C SD Response/Data-in Time-out Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:0] |TOUT |SD Response/Data-in Time-out Value + * | | |A 24-bit value specifies the time-out counts of response and data input + * | | |SD host controller will wait start bit of response or data-in until this value reached + * | | |The time period depends on SD engine clock frequency + * | | |Do not write a small number into this field, or you may never get response or data due to time-out. + * | | |Note: Filling 0x0 into this field will disable hardware time-out function. + */ + + __IO uint32_t FB[32]; /*!< Shared Buffer (FIFO) */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE0[224]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t DMACTL; /*!< [0x0400] DMA Control and Status Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE1[1]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t DMASA; /*!< [0x0408] DMA Transfer Starting Address Register */ + __I uint32_t DMABCNT; /*!< [0x040c] DMA Transfer Byte Count Register */ + __IO uint32_t DMAINTEN; /*!< [0x0410] DMA Interrupt Enable Control Register */ + __IO uint32_t DMAINTSTS; /*!< [0x0414] DMA Interrupt Status Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE2[250]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t GCTL; /*!< [0x0800] Global Control and Status Register */ + __IO uint32_t GINTEN; /*!< [0x0804] Global Interrupt Control Register */ + __I uint32_t GINTSTS; /*!< [0x0808] Global Interrupt Status Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE3[5]; + /// @endcond //HIDDEN_SYMBOLS + __IO uint32_t CTL; /*!< [0x0820] SD Control and Status Register */ + __IO uint32_t CMDARG; /*!< [0x0824] SD Command Argument Register */ + __IO uint32_t INTEN; /*!< [0x0828] SD Interrupt Control Register */ + __IO uint32_t INTSTS; /*!< [0x082c] SD Interrupt Status Register */ + __I uint32_t RESP0; /*!< [0x0830] SD Receiving Response Token Register 0 */ + __I uint32_t RESP1; /*!< [0x0834] SD Receiving Response Token Register 1 */ + __IO uint32_t BLEN; /*!< [0x0838] SD Block Length Register */ + __IO uint32_t TOUT; /*!< [0x083c] SD Response/Data-in Time-out Register */ + +} SDH_T; + + +/** + @addtogroup SDH_CONST SDH Bit Field Definition + Constant Definitions for SDH Controller +@{ */ + +#define SDH_DMACTL_DMAEN_Pos (0) /*!< SDH_T::DMACTL: DMAEN Position */ +#define SDH_DMACTL_DMAEN_Msk (0x1ul << SDH_DMACTL_DMAEN_Pos) /*!< SDH_T::DMACTL: DMAEN Mask */ + +#define SDH_DMACTL_DMARST_Pos (1) /*!< SDH_T::DMACTL: DMARST Position */ +#define SDH_DMACTL_DMARST_Msk (0x1ul << SDH_DMACTL_DMARST_Pos) /*!< SDH_T::DMACTL: DMARST Mask */ + +#define SDH_DMACTL_SGEN_Pos (3) /*!< SDH_T::DMACTL: SGEN Position */ +#define SDH_DMACTL_SGEN_Msk (0x1ul << SDH_DMACTL_SGEN_Pos) /*!< SDH_T::DMACTL: SGEN Mask */ + +#define SDH_DMACTL_DMABUSY_Pos (9) /*!< SDH_T::DMACTL: DMABUSY Position */ +#define SDH_DMACTL_DMABUSY_Msk (0x1ul << SDH_DMACTL_DMABUSY_Pos) /*!< SDH_T::DMACTL: DMABUSY Mask */ + +#define SDH_DMASA_ORDER_Pos (0) /*!< SDH_T::DMASA: ORDER Position */ +#define SDH_DMASA_ORDER_Msk (0x1ul << SDH_DMASA_ORDER_Pos) /*!< SDH_T::DMASA: ORDER Mask */ + +#define SDH_DMASA_DMASA_Pos (1) /*!< SDH_T::DMASA: DMASA Position */ +#define SDH_DMASA_DMASA_Msk (0x7ffffffful << SDH_DMASA_DMASA_Pos) /*!< SDH_T::DMASA: DMASA Mask */ + +#define SDH_DMABCNT_BCNT_Pos (0) /*!< SDH_T::DMABCNT: BCNT Position */ +#define SDH_DMABCNT_BCNT_Msk (0x3fffffful << SDH_DMABCNT_BCNT_Pos) /*!< SDH_T::DMABCNT: BCNT Mask */ + +#define SDH_DMAINTEN_ABORTIEN_Pos (0) /*!< SDH_T::DMAINTEN: ABORTIEN Position */ +#define SDH_DMAINTEN_ABORTIEN_Msk (0x1ul << SDH_DMAINTEN_ABORTIEN_Pos) /*!< SDH_T::DMAINTEN: ABORTIEN Mask */ + +#define SDH_DMAINTEN_WEOTIEN_Pos (1) /*!< SDH_T::DMAINTEN: WEOTIEN Position */ +#define SDH_DMAINTEN_WEOTIEN_Msk (0x1ul << SDH_DMAINTEN_WEOTIEN_Pos) /*!< SDH_T::DMAINTEN: WEOTIEN Mask */ + +#define SDH_DMAINTSTS_ABORTIF_Pos (0) /*!< SDH_T::DMAINTSTS: ABORTIF Position */ +#define SDH_DMAINTSTS_ABORTIF_Msk (0x1ul << SDH_DMAINTSTS_ABORTIF_Pos) /*!< SDH_T::DMAINTSTS: ABORTIF Mask */ + +#define SDH_DMAINTSTS_WEOTIF_Pos (1) /*!< SDH_T::DMAINTSTS: WEOTIF Position */ +#define SDH_DMAINTSTS_WEOTIF_Msk (0x1ul << SDH_DMAINTSTS_WEOTIF_Pos) /*!< SDH_T::DMAINTSTS: WEOTIF Mask */ + +#define SDH_GCTL_GCTLRST_Pos (0) /*!< SDH_T::GCTL: GCTLRST Position */ +#define SDH_GCTL_GCTLRST_Msk (0x1ul << SDH_GCTL_GCTLRST_Pos) /*!< SDH_T::GCTL: GCTLRST Mask */ + +#define SDH_GCTL_SDEN_Pos (1) /*!< SDH_T::GCTL: SDEN Position */ +#define SDH_GCTL_SDEN_Msk (0x1ul << SDH_GCTL_SDEN_Pos) /*!< SDH_T::GCTL: SDEN Mask */ + +#define SDH_GINTEN_DTAIEN_Pos (0) /*!< SDH_T::GINTEN: DTAIEN Position */ +#define SDH_GINTEN_DTAIEN_Msk (0x1ul << SDH_GINTEN_DTAIEN_Pos) /*!< SDH_T::GINTEN: DTAIEN Mask */ + +#define SDH_GINTSTS_DTAIF_Pos (0) /*!< SDH_T::GINTSTS: DTAIF Position */ +#define SDH_GINTSTS_DTAIF_Msk (0x1ul << SDH_GINTSTS_DTAIF_Pos) /*!< SDH_T::GINTSTS: DTAIF Mask */ + +#define SDH_CTL_COEN_Pos (0) /*!< SDH_T::CTL: COEN Position */ +#define SDH_CTL_COEN_Msk (0x1ul << SDH_CTL_COEN_Pos) /*!< SDH_T::CTL: COEN Mask */ + +#define SDH_CTL_RIEN_Pos (1) /*!< SDH_T::CTL: RIEN Position */ +#define SDH_CTL_RIEN_Msk (0x1ul << SDH_CTL_RIEN_Pos) /*!< SDH_T::CTL: RIEN Mask */ + +#define SDH_CTL_DIEN_Pos (2) /*!< SDH_T::CTL: DIEN Position */ +#define SDH_CTL_DIEN_Msk (0x1ul << SDH_CTL_DIEN_Pos) /*!< SDH_T::CTL: DIEN Mask */ + +#define SDH_CTL_DOEN_Pos (3) /*!< SDH_T::CTL: DOEN Position */ +#define SDH_CTL_DOEN_Msk (0x1ul << SDH_CTL_DOEN_Pos) /*!< SDH_T::CTL: DOEN Mask */ + +#define SDH_CTL_R2EN_Pos (4) /*!< SDH_T::CTL: R2EN Position */ +#define SDH_CTL_R2EN_Msk (0x1ul << SDH_CTL_R2EN_Pos) /*!< SDH_T::CTL: R2EN Mask */ + +#define SDH_CTL_CLK74OEN_Pos (5) /*!< SDH_T::CTL: CLK74OEN Position */ +#define SDH_CTL_CLK74OEN_Msk (0x1ul << SDH_CTL_CLK74OEN_Pos) /*!< SDH_T::CTL: CLK74OEN Mask */ + +#define SDH_CTL_CLK8OEN_Pos (6) /*!< SDH_T::CTL: CLK8OEN Position */ +#define SDH_CTL_CLK8OEN_Msk (0x1ul << SDH_CTL_CLK8OEN_Pos) /*!< SDH_T::CTL: CLK8OEN Mask */ + +#define SDH_CTL_CLKKEEP_Pos (7) /*!< SDH_T::CTL: CLKKEEP Position */ +#define SDH_CTL_CLKKEEP_Msk (0x1ul << SDH_CTL_CLKKEEP_Pos) /*!< SDH_T::CTL: CLKKEEP Mask */ + +#define SDH_CTL_CMDCODE_Pos (8) /*!< SDH_T::CTL: CMDCODE Position */ +#define SDH_CTL_CMDCODE_Msk (0x3ful << SDH_CTL_CMDCODE_Pos) /*!< SDH_T::CTL: CMDCODE Mask */ + +#define SDH_CTL_CTLRST_Pos (14) /*!< SDH_T::CTL: CTLRST Position */ +#define SDH_CTL_CTLRST_Msk (0x1ul << SDH_CTL_CTLRST_Pos) /*!< SDH_T::CTL: CTLRST Mask */ + +#define SDH_CTL_DBW_Pos (15) /*!< SDH_T::CTL: DBW Position */ +#define SDH_CTL_DBW_Msk (0x1ul << SDH_CTL_DBW_Pos) /*!< SDH_T::CTL: DBW Mask */ + +#define SDH_CTL_BLKCNT_Pos (16) /*!< SDH_T::CTL: BLKCNT Position */ +#define SDH_CTL_BLKCNT_Msk (0xfful << SDH_CTL_BLKCNT_Pos) /*!< SDH_T::CTL: BLKCNT Mask */ + +#define SDH_CTL_SDNWR_Pos (24) /*!< SDH_T::CTL: SDNWR Position */ +#define SDH_CTL_SDNWR_Msk (0xful << SDH_CTL_SDNWR_Pos) /*!< SDH_T::CTL: SDNWR Mask */ + +#define SDH_CTL_SDPORT_Pos (29) /*!< SDH CTL: SDPORT Position */ +#define SDH_CTL_SDPORT_Msk (0x3ul << SDH_CTL_SDPORT_Pos) /*!< SDH CTL: SDPORT Mask */ + +#define SDH_CTL_CLKKEEP1_Pos (31) /*!< SDH CTL: CLKKEEP1 Position */ +#define SDH_CTL_CLKKEEP1_Msk (0x1ul << SDH_CTL_CLKKEEP1_Pos) /*!< SDH CTL: CLKKEEP1 Mask */ + +#define SDH_CMDARG_ARGUMENT_Pos (0) /*!< SDH_T::CMDARG: ARGUMENT Position */ +#define SDH_CMDARG_ARGUMENT_Msk (0xfffffffful << SDH_CMDARG_ARGUMENT_Pos) /*!< SDH_T::CMDARG: ARGUMENT Mask */ + +#define SDH_INTEN_BLKDIEN_Pos (0) /*!< SDH_T::INTEN: BLKDIEN Position */ +#define SDH_INTEN_BLKDIEN_Msk (0x1ul << SDH_INTEN_BLKDIEN_Pos) /*!< SDH_T::INTEN: BLKDIEN Mask */ + +#define SDH_INTEN_CRCIEN_Pos (1) /*!< SDH_T::INTEN: CRCIEN Position */ +#define SDH_INTEN_CRCIEN_Msk (0x1ul << SDH_INTEN_CRCIEN_Pos) /*!< SDH_T::INTEN: CRCIEN Mask */ + +#define SDH_INTEN_CDIEN_Pos (8) /*!< SDH_T::INTEN: CDIEN Position */ +#define SDH_INTEN_CDIEN_Msk (0x1ul << SDH_INTEN_CDIEN_Pos) /*!< SDH_T::INTEN: CDIEN Mask */ + +#define SDH_INTEN_CDIEN1_Pos (9) /*!< SDH INTEN: CDIEN1 Position */ +#define SDH_INTEN_CDIEN1_Msk (0x1ul << SDH_INTEN_CDIEN1_Pos) /*!< SDH INTEN: CDIEN1 Mask */ + +#define SDH_INTEN_SDHOST0IEN_Pos (10) /*!< SDH INTSTS: SDHOST0IEN Position */ +#define SDH_INTEN_SDHOST0IEN_Msk (0x1ul << SDH_INTEN_SDHOST0IEN_Pos) /*!< SDH INTSTS: SDHOST0IEN Mask */ + +#define SDH_INTEN_SDHOST1IEN_Pos (11) /*!< SDH INTSTS: SDHOST1IEN Position */ +#define SDH_INTEN_SDHOST1IEN_Msk (0x1ul << SDH_INTEN_SDHOST1IEN_Pos) /*!< SDH INTSTS: SDHOST1IEN Mask */ + +#define SDH_INTEN_RTOIEN_Pos (12) /*!< SDH INTEN: RTOIEN Position */ +#define SDH_INTEN_RTOIEN_Msk (0x1ul << SDH_INTEN_RTOIEN_Pos) /*!< SDH INTEN: RTOIEN Mask */ + +#define SDH_INTEN_DITOIEN_Pos (13) /*!< SDH_T::INTEN: DITOIEN Position */ +#define SDH_INTEN_DITOIEN_Msk (0x1ul << SDH_INTEN_DITOIEN_Pos) /*!< SDH_T::INTEN: DITOIEN Mask */ + +#define SDH_INTEN_WKIEN_Pos (14) /*!< SDH_T::INTEN: WKIEN Position */ +#define SDH_INTEN_WKIEN_Msk (0x1ul << SDH_INTEN_WKIEN_Pos) /*!< SDH_T::INTEN: WKIEN Mask */ + +#define SDH_INTEN_CDSRC_Pos (30) /*!< SDH_T::INTEN: CDSRC Position */ +#define SDH_INTEN_CDSRC_Msk (0x1ul << SDH_INTEN_CDSRC_Pos) /*!< SDH_T::INTEN: CDSRC Mask */ + +#define SDH_INTEN_CDSRC1_Pos (31) /*!< SDH INTEN: CDSRC1 Position */ +#define SDH_INTEN_CDSRC1_Msk (0x1ul << SDH_INTEN_CDSRC1_Pos) /*!< SDH INTEN: CDSRC1 Mask */ + +#define SDH_INTSTS_BLKDIF_Pos (0) /*!< SDH_T::INTSTS: BLKDIF Position */ +#define SDH_INTSTS_BLKDIF_Msk (0x1ul << SDH_INTSTS_BLKDIF_Pos) /*!< SDH_T::INTSTS: BLKDIF Mask */ + +#define SDH_INTSTS_CRCIF_Pos (1) /*!< SDH_T::INTSTS: CRCIF Position */ +#define SDH_INTSTS_CRCIF_Msk (0x1ul << SDH_INTSTS_CRCIF_Pos) /*!< SDH_T::INTSTS: CRCIF Mask */ + +#define SDH_INTSTS_CRC7_Pos (2) /*!< SDH_T::INTSTS: CRC7 Position */ +#define SDH_INTSTS_CRC7_Msk (0x1ul << SDH_INTSTS_CRC7_Pos) /*!< SDH_T::INTSTS: CRC7 Mask */ + +#define SDH_INTSTS_CRC16_Pos (3) /*!< SDH_T::INTSTS: CRC16 Position */ +#define SDH_INTSTS_CRC16_Msk (0x1ul << SDH_INTSTS_CRC16_Pos) /*!< SDH_T::INTSTS: CRC16 Mask */ + +#define SDH_INTSTS_CRCSTS_Pos (4) /*!< SDH_T::INTSTS: CRCSTS Position */ +#define SDH_INTSTS_CRCSTS_Msk (0x7ul << SDH_INTSTS_CRCSTS_Pos) /*!< SDH_T::INTSTS: CRCSTS Mask */ + +#define SDH_INTSTS_DAT0STS_Pos (7) /*!< SDH_T::INTSTS: DAT0STS Position */ +#define SDH_INTSTS_DAT0STS_Msk (0x1ul << SDH_INTSTS_DAT0STS_Pos) /*!< SDH_T::INTSTS: DAT0STS Mask */ + +#define SDH_INTSTS_CDIF_Pos (8) /*!< SDH_T::INTSTS: CDIF Position */ +#define SDH_INTSTS_CDIF_Msk (0x1ul << SDH_INTSTS_CDIF_Pos) /*!< SDH_T::INTSTS: CDIF Mask */ + +#define SDH_INTSTS_CDIF1_Pos (9) /*!< SDH INTSTS: CDIF1 Position */ +#define SDH_INTSTS_CDIF1_Msk (0x1ul << SDH_INTSTS_CDIF1_Pos) /*!< SDH INTSTS: CDIF1 Mask */ + +#define SDH_INTSTS_SDHOST0IF_Pos (10) /*!< SDH INTSTS: SDHOST0IF Position */ +#define SDH_INTSTS_SDHOST0IF_Msk (0x1ul << SDH_INTSTS_SDHOST0IF_Pos) /*!< SDH INTSTS: SDHOST0IF Mask */ + +#define SDH_INTSTS_SDHOST1IF_Pos (11) /*!< SDH INTSTS: SDHOST1IF Position */ +#define SDH_INTSTS_SDHOST1IF_Msk (0x1ul << SDH_INTSTS_SDHOST1IF_Pos) /*!< SDH INTSTS: SDHOST1IF Mask */ + +#define SDH_INTSTS_RTOIF_Pos (12) /*!< SDH_T::INTSTS: RTOIF Position */ +#define SDH_INTSTS_RTOIF_Msk (0x1ul << SDH_INTSTS_RTOIF_Pos) /*!< SDH_T::INTSTS: RTOIF Mask */ + +#define SDH_INTSTS_DITOIF_Pos (13) /*!< SDH_T::INTSTS: DITOIF Position */ +#define SDH_INTSTS_DITOIF_Msk (0x1ul << SDH_INTSTS_DITOIF_Pos) /*!< SDH_T::INTSTS: DITOIF Mask */ + +#define SDH_INTSTS_CDSTS_Pos (16) /*!< SDH_T::INTSTS: CDSTS Position */ +#define SDH_INTSTS_CDSTS_Msk (0x1ul << SDH_INTSTS_CDSTS_Pos) /*!< SDH_T::INTSTS: CDSTS Mask */ + +#define SDH_INTSTS_CDSTS1_Pos (17) /*!< SDH INTSTS: CDSTS1 Position */ +#define SDH_INTSTS_CDSTS1_Msk (0x1ul << SDH_INTSTS_CDSTS1_Pos) /*!< SDH INTSTS: CDSTS1 Mask */ + +#define SDH_INTSTS_DAT1STS_Pos (18) /*!< SDH_T::INTSTS: DAT1STS Position */ +#define SDH_INTSTS_DAT1STS_Msk (0x1ul << SDH_INTSTS_DAT1STS_Pos) /*!< SDH_T::INTSTS: DAT1STS Mask */ + +#define SDH_RESP0_RESPTK0_Pos (0) /*!< SDH_T::RESP0: RESPTK0 Position */ +#define SDH_RESP0_RESPTK0_Msk (0xfffffffful << SDH_RESP0_RESPTK0_Pos) /*!< SDH_T::RESP0: RESPTK0 Mask */ + +#define SDH_RESP1_RESPTK1_Pos (0) /*!< SDH_T::RESP1: RESPTK1 Position */ +#define SDH_RESP1_RESPTK1_Msk (0xfful << SDH_RESP1_RESPTK1_Pos) /*!< SDH_T::RESP1: RESPTK1 Mask */ + +#define SDH_BLEN_BLKLEN_Pos (0) /*!< SDH_T::BLEN: BLKLEN Position */ +#define SDH_BLEN_BLKLEN_Msk (0x7fful << SDH_BLEN_BLKLEN_Pos) /*!< SDH_T::BLEN: BLKLEN Mask */ + +#define SDH_TOUT_TOUT_Pos (0) /*!< SDH_T::TOUT: TOUT Position */ +#define SDH_TOUT_TOUT_Msk (0xfffffful << SDH_TOUT_TOUT_Pos) /*!< SDH_T::TOUT: TOUT Mask */ + +/**@}*/ /* SDH_CONST */ +/**@}*/ /* end of SDH register group */ +/**@}*/ /* end of REGISTER group */ + +#define SDH0 ((SDH_T *) FMI_BA) +#define SDH1 ((SDH_T *) SDH_BA) + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup SDH_Driver SDH Driver + @{ +*/ + + +/** @addtogroup SDH_EXPORTED_CONSTANTS SDH Exported Constants + @{ +*/ + +#define SDH_ERR_ID 0xFFFF0100ul /*!< SDH error ID \hideinitializer */ + +#define SDH_TIMEOUT (SDH_ERR_ID|0x01ul) /*!< Timeout \hideinitializer */ +#define SDH_NO_MEMORY (SDH_ERR_ID|0x02ul) /*!< OOM \hideinitializer */ + +/*--- define type of SD card or MMC */ +#define SDH_TYPE_UNKNOWN 0ul /*!< Unknown card type \hideinitializer */ +#define SDH_TYPE_SD_HIGH 1ul /*!< SDHC card \hideinitializer */ +#define SDH_TYPE_SD_LOW 2ul /*!< SD card \hideinitializer */ +#define SDH_TYPE_MMC 3ul /*!< MMC card \hideinitializer */ +#define SDH_TYPE_EMMC 4ul /*!< eMMC card \hideinitializer */ + +/* SD error */ +#define SDH_NO_SD_CARD (SDH_ERR_ID|0x10ul) /*!< Card removed \hideinitializer */ +#define SDH_ERR_DEVICE (SDH_ERR_ID|0x11ul) /*!< Device error \hideinitializer */ +#define SDH_INIT_TIMEOUT (SDH_ERR_ID|0x12ul) /*!< Card init timeout \hideinitializer */ +#define SDH_SELECT_ERROR (SDH_ERR_ID|0x13ul) /*!< Card select error \hideinitializer */ +#define SDH_WRITE_PROTECT (SDH_ERR_ID|0x14ul) /*!< Card write protect \hideinitializer */ +#define SDH_INIT_ERROR (SDH_ERR_ID|0x15ul) /*!< Card init error \hideinitializer */ +#define SDH_CRC7_ERROR (SDH_ERR_ID|0x16ul) /*!< CRC 7 error \hideinitializer */ +#define SDH_CRC16_ERROR (SDH_ERR_ID|0x17ul) /*!< CRC 16 error \hideinitializer */ +#define SDH_CRC_ERROR (SDH_ERR_ID|0x18ul) /*!< CRC error \hideinitializer */ +#define SDH_CMD8_ERROR (SDH_ERR_ID|0x19ul) /*!< Command 8 error \hideinitializer */ + +#define MMC_FREQ 20000ul /*!< output 20MHz to MMC \hideinitializer */ +#define SD_FREQ 25000ul /*!< output 25MHz to SD \hideinitializer */ +#define SDHC_FREQ 50000ul /*!< output 50MHz to SDH \hideinitializer */ + +#define SD_PORT0 (1 << 0) /*!< Card select SD0 \hideinitializer */ +#define SD_PORT1 (1 << 2) /*!< Card select SD1 \hideinitializer */ +#define CardDetect_From_GPIO (1ul << 8) /*!< Card detection pin is GPIO \hideinitializer */ +#define CardDetect_From_DAT3 (1ul << 9) /*!< Card detection pin is DAT3 \hideinitializer */ + +/*@}*/ /* end of group N9H30_SDH_EXPORTED_CONSTANTS */ + +/** @addtogroup N9H30_SDH_EXPORTED_TYPEDEF SDH Exported Type Defines + @{ +*/ + +/** \brief Structure type of inserted Card information. + */ +typedef struct SDH_info_t +{ + unsigned char IsCardInsert; /*!< Card insert state */ + unsigned char R3Flag; + unsigned char R7Flag; + unsigned char volatile DataReadyFlag; + unsigned int CardType; /*!< SDHC, SD, or MMC */ + unsigned int RCA; /*!< Relative card address */ + unsigned int totalSectorN; /*!< Total sector number */ + unsigned int diskSize; /*!< Disk size in K bytes */ + int sectorSize; /*!< Sector size in bytes */ + unsigned char *dmabuf; +} SDH_INFO_T; /*!< Structure holds SD card info */ + +/*@}*/ /* end of group N9H30_SDH_EXPORTED_TYPEDEF */ + +/// @cond HIDDEN_SYMBOLS +extern SDH_INFO_T SD0, SD1; + +/// @endcond HIDDEN_SYMBOLS + +/** @addtogroup N9H30_SDH_EXPORTED_FUNCTIONS SDH Exported Functions + @{ +*/ + + +/** + * @brief Enable specified interrupt. + * + * @param[in] u32IntMask Interrupt type mask: + * \ref SDH_INTEN_BLKDIEN_Msk / \ref SDH_INTEN_CRCIEN_Msk / \ref SDH_INTEN_CDIEN0_Msk / \ref SDH_INTEN_CDIEN1_Msk / + * \ref SDH_INTEN_CDSRC0_Msk / \ref SDH_INTEN_CDSRC1_Msk / \ref SDH_INTEN_RTOIEN_Msk / \ref SDH_INTEN_DITOIEN_Msk / + * \ref SDH_INTEN_WKIEN_Msk + * + * @return None. + * \hideinitializer + */ +#define SDH_ENABLE_INT(sdh, u32IntMask) ((sdh)->INTEN |= (u32IntMask)) + +/** + * @brief Disable specified interrupt. + * + * @param[in] sdh Select SDH0 or SDH1. + * @param[in] u32IntMask Interrupt type mask: + * \ref SDH_INTEN_BLKDIEN_Msk / \ref SDH_INTEN_CRCIEN_Msk / \ref SDH_INTEN_CDIEN0_Msk / \ref SDH_INTEN_CDIEN1_Msk / + * \ref SDH_INTEN_SDHOST0IEN_Msk / \ref SDH_INTEN_SDHOST1IEN_Msk / \ref SDH_INTEN_RTOIEN_Msk / \ref SDH_INTEN_DITOIEN_Msk / + * \ref SDH_INTEN_WKIEN_Msk / \ref SDH_INTEN_CDSRC0_Msk / \ref SDH_INTEN_CDSRC1_Msk + * + * @return None. + * \hideinitializer + */ +#define SDH_DISABLE_INT(sdh, u32IntMask) ((sdh)->INTEN &= ~(u32IntMask)) + +/** + * @brief Get specified interrupt flag/status. + * + * @param[in] sdh Select SDH0 or SDH1. + * @param[in] u32IntMask Interrupt type mask: + * \ref SDH_INTSTS_BLKDIF_Msk / \ref SDH_INTSTS_CRCIF_Msk / \ref SDH_INTSTS_CRC7_Msk / + * \ref SDH_INTSTS_CRC16_Msk / \ref SDH_INTSTS_CRCSTS_Msk / \ref SDH_INTSTS_DAT0STS_Msk / \ref SDH_INTSTS_CDIF0_Msk / + * \ref SDH_INTSTS_CDIF1_Msk / \ref SDH_INTSTS_SDHOST0IF_Msk / \ref SDH_INTSTS_SDHOST1IF_Msk / \ref SDH_INTSTS_RTOIF_Msk / + * \ref SDH_INTSTS_DINTOIF_Msk / \ref SDH_INTSTS_CDSTS0_Msk / \ref SDH_INTSTS_CDSTS1_Msk / \ref SDH_INTSTS_DAT1STS_Msk + * + * + * @return 0 = The specified interrupt is not happened. + * 1 = The specified interrupt is happened. + * \hideinitializer + */ +#define SDH_GET_INT_FLAG(sdh, u32IntMask) (((sdh)->INTSTS & (u32IntMask))?1:0) + + +/** + * @brief Clear specified interrupt flag/status. + * + * @param[in] sdh Select SDH0 or SDH1. + * @param[in] u32IntMask Interrupt type mask: + * \ref SDH_INTSTS_BLKDIF_Msk / \ref SDH_INTSTS_CRCIF_Msk / \ref SDH_INTSTS_CDIF0_Msk / + * \ref SDH_INTSTS_CDIF1_Msk / \ref SDH_INTSTS_SDHOST0IF_Msk / \ref SDH_INTSTS_SDHOST1IF_Msk / + * \ref SDH_INTSTS_RTOIF_Msk / \ref SDH_INTSTS_DINTOIF_Msk + * + * + * @return None. + * \hideinitializer + */ +#define SDH_CLR_INT_FLAG(sdh, u32IntMask) ((sdh)->INTSTS = (u32IntMask)) + + +/** + * @brief Check SD Card inserted or removed. + * + * @param[in] sdh Select SDH0 or SDH1. + * + * @return 1: Card inserted. + * 0: Card removed. + * \hideinitializer + */ +#define SDH_IS_CARD_PRESENT(sdh) (((sdh) == SDH0)? SD0.IsCardInsert : SD1.IsCardInsert) + +/** + * @brief Get SD Card capacity. + * + * @param[in] sdh Select SDH0 or SDH1. + * + * @return SD Card capacity. (unit: KByte) + * \hideinitializer + */ +#define SDH_GET_CARD_CAPACITY(sdh) (((sdh) == SDH0)? SD0.diskSize : SD1.diskSize) + + +void SDH_Open(SDH_T *sdh, uint32_t u32CardDetSrc); +uint32_t SDH_Probe(SDH_T *sdh); +uint32_t SDH_Read(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount); +uint32_t SDH_Write(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount); + +uint32_t SDH_CardDetection(SDH_T *sdh); +void SDH_Open_Disk(SDH_T *sdh, uint32_t u32CardDetSrc); +void SDH_Close_Disk(SDH_T *sdh); + + +/*@}*/ /* end of group N9H30_SDH_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_SDH_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#endif //end of __NU_SDH_H__ +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_spi.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_spi.h new file mode 100644 index 0000000000..a453e1dddc --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_spi.h @@ -0,0 +1,121 @@ +/**************************************************************************//** +* @file spi.h +* @brief N9H30 SPI driver header file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#ifndef __NU_SPI_H__ +#define __NU_SPI_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_SPI_Driver SPI Driver + @{ +*/ + +/** @addtogroup N9H30_SPI_EXPORTED_CONSTANTS SPI Exported Constants + @{ +*/ +/// @cond HIDDEN_SYMBOLS + +#define CNTRL 0x00 /*!< Control Register Address */ +#define DIVIDER 0x04 /*!< Divider Register Address */ +#define SSR 0x08 /*!< Slave Select Register Address */ +#define RX0 0x10 /*!< Receive Register 0 Address */ +#define RX1 0x14 /*!< Receive Register 1 Address */ +#define RX2 0x18 /*!< Receive Register 2 Address */ +#define RX3 0x1C /*!< Receive Register 3 Address */ +#define TX0 0x10 /*!< Transfer Register 0 Address */ +#define TX1 0x14 /*!< Transfer Register 1 Address */ +#define TX2 0x18 /*!< Transfer Register 2 Address */ +#define TX3 0x1C /*!< Transfer Register 3 Address */ + +#define SPI_INPUT_CLOCK 75000000 /* Unit: Hz */ +/// @endcond HIDDEN_SYMBOLS + +#define SPI_NUMBER 2 /*!< 2 spi interfaces */ + +#define SPI_NO_ERR 0 /*!< No error */ + +#define SPI_ERR_NODEV -1 /*!< Wrong device id */ +#define SPI_ERR_BUSY -2 /*!< Interface is busy */ +#define SPI_ERR_IO -3 /*!< IO control error for not opened interface */ +#define SPI_ERR_ARG -4 /*!< Wrong argument in IO control */ + +#define SPI_IOC_TRIGGER 0 /*!< Trigger SPI interface */ +#define SPI_IOC_SET_INTERRUPT 1 /*!< Enable/disable interrupt ,arguments could be \ref SPI_DISABLE_INTERRUPT and \ref SPI_ENABLE_INTERRUPT */ +#define SPI_IOC_SET_SPEED 2 /*!< Set SPI clock speed */ +#define SPI_IOC_SET_DUAL_QUAD_MODE 3 /*!< Enable/disable Quad/Dual mode ,arguments could be \ref SPI_DISABLE_DUAL_QUAD, \ref SPI_DUAL_MODE, \ref SPI_QUAD_MODE*/ +#define SPI_IOC_SET_DUAL_QUAD_DIR 4 /*!< Set Quad/Dual mode direction ,arguments could be \ref SPI_DUAL_QUAD_INPUT, \ref SPI_DUAL_QUAD_OUTPUT */ +#define SPI_IOC_SET_LSB_MSB 5 /*!< Set MSB/LSB ,arguments could be \ref SPI_MSB, \ref SPI_LSB */ +#define SPI_IOC_SET_TX_NUM 6 /*!< Set transfer number */ +#define SPI_IOC_SET_TX_BITLEN 7 /*!< Set transfer bit number */ +#define SPI_IOC_SET_MODE 8 /*!< Set SPI mode ,arguments could be \ref SPI_MODE_0, \ref SPI_MODE_1, \ref SPI_MODE_2, \ref SPI_MODE_3 */ +#define SPI_IOC_ENABLE_SS 9 /*!< Enable slave select pin */ +#define SPI_IOC_DISABLE_SS 10 /*!< Disable slave select pin */ +#define SPI_IOC_SET_AUTOSS 11 /*!< Enable/disable auto slave select function ,arguments could be \ref SPI_DISABLE_AUTOSS, \ref SPI_ENABLE_AUTOSS */ +#define SPI_IOC_SET_SS_ACTIVE_LEVEL 12 /*!< Set slave select active level ,arguments could be \ref SPI_SS_ACTIVE_LOW, \ref SPI_SS_ACTIVE_HIGH */ + +#define SPI_DISABLE_INTERRUPT 0 /*!< Disable interrupt */ +#define SPI_ENABLE_INTERRUPT 1 /*!< Enable interrupt */ + +#define SPI_DISABLE_DUAL_QUAD 0 /*!< Disable quad and dual mode */ +#define SPI_DUAL_MODE 1 /*!< Enable dual mode */ +#define SPI_QUAD_MODE 2 /*!< Enable quad mode */ + +#define SPI_DUAL_QUAD_INPUT 0 /*!< Set dual/quad mode io direction to input */ +#define SPI_DUAL_QUAD_OUTPUT 1 /*!< Set dual/quad mode io direction to output */ + +#define SPI_MSB 0 /*!< Enable MSB */ +#define SPI_LSB 1 /*!< Enable LSB */ + +#define SPI_MODE_0 0 /*!< Set to SPI mode 0 */ +#define SPI_MODE_1 1 /*!< Set to SPI mode 1 */ +#define SPI_MODE_2 2 /*!< Set to SPI mode 2 */ +#define SPI_MODE_3 3 /*!< Set to SPI mode 3 */ + +#define SPI_SS_SS0 0 /*!< Select SS0 */ +#define SPI_SS_SS1 1 /*!< Select SS1 */ +#define SPI_SS_BOTH 2 /*!< Select both SS0/SS1 */ + +#define SPI_DISABLE_AUTOSS 0 /*!< Disable auto slave select function */ +#define SPI_ENABLE_AUTOSS 1 /*!< Enable auto slave select function */ + +#define SPI_SS_ACTIVE_LOW 0 /*!< Set active level of slave select to low */ +#define SPI_SS_ACTIVE_HIGH 1 /*!< Set active level of slave select to high */ + +/*@}*/ /* end of group N9H30_SPI_EXPORTED_CONSTANTS */ + +/** @addtogroup N9H30_SPI_EXPORTED_FUNCTIONS SPI Exported Functions + @{ +*/ + +int32_t spiInit(int32_t fd); +int32_t spiIoctl(int32_t fd, uint32_t cmd, uint32_t arg0, uint32_t arg1); +int spiOpen(int32_t fd); +uint8_t spiGetBusyStatus(int32_t fd); +uint32_t spiRead(int32_t fd, uint8_t buff_id); +void spiWrite(int32_t fd, uint8_t buff_id, uint32_t data); +/*@}*/ /* end of group N9H30_SPI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_SPI_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_SPI_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_sys.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_sys.h new file mode 100644 index 0000000000..8a4cea517b --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_sys.h @@ -0,0 +1,373 @@ +/**************************************************************************//** +* @file sys.h +* @brief N9H30 SYS driver header file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_SYS_H__ +#define __NU_SYS_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_SYS_Driver SYS Driver + @{ +*/ + +/** @addtogroup N9H30_SYS_EXPORTED_CONSTANTS SYS Exported Constants + @{ +*/ + +/** + * @details Interrupt Number Definition. + */ +typedef enum IRQn +{ + + /****** N9H30 Specific Interrupt Numbers *****************************************/ + + WDT_IRQn = 1, /*!< Watch Dog Timer Interrupt */ + WWDT_IRQn = 2, /*!< Windowed-WDT Interrupt */ + LVD_IRQn = 3, /*!< Low Voltage Detect Interrupt */ + EINT0_IRQn = 4, /*!< External Interrupt 0 */ + EINT1_IRQn = 5, /*!< External Interrupt 1 */ + EINT2_IRQn = 6, /*!< External Interrupt 2 */ + EINT3_IRQn = 7, /*!< External Interrupt 3 */ + EINT4_IRQn = 8, /*!< External Interrupt 4 */ + EINT5_IRQn = 9, /*!< External Interrupt 5 */ + EINT6_IRQn = 10, /*!< External Interrupt 6 */ + EINT7_IRQn = 11, /*!< External Interrupt 7 */ + ACTL_IRQn = 12, /*!< Audio Controller Interrupt */ + LCD_IRQn = 13, /*!< LCD Controller Interrupt */ + CAP_IRQn = 14, /*!< Sensor Interface Controller Interrupt */ + RTC_IRQn = 15, /*!< Real Time Clock Interrupt */ + TMR0_IRQn = 16, /*!< Timer 0 Interrupt */ + TMR1_IRQn = 17, /*!< Timer 1 Interrupt */ + ADC_IRQn = 18, /*!< ADC Interrupt */ + EMC0_RX_IRQn = 19, /*!< EMC 0 RX Interrupt */ + EMC1_RX_IRQn = 20, /*!< EMC 1 RX Interrupt */ + EMC0_TX_IRQn = 21, /*!< EMC 0 TX Interrupt */ + EMC1_TX_IRQn = 22, /*!< EMC 1 TX Interrupt */ + EHCI_IRQn = 23, /*!< USB 2.0 Host Controller Interrupt */ + OHCI_IRQn = 24, /*!< USB 1.1 Host Controller Interrupt */ + GDMA0_IRQn = 25, /*!< GDMA Channel 0 Interrupt */ + GDMA1_IRQn = 26, /*!< GDMA Channel 1 Interrupt */ + SDH_IRQn = 27, /*!< SD/SDIO Host Interrupt */ + FMI_IRQn = 28, /*!< FMI Interrupt */ + USBD_IRQn = 29, /*!< USB Device Interrupt */ + TMR2_IRQn = 30, /*!< Timer 2 Interrupt */ + TMR3_IRQn = 31, /*!< Timer 3 Interrupt */ + TMR4_IRQn = 32, /*!< Timer 4 Interrupt */ + JPEG_IRQn = 33, /*!< JPEG Engine Interrupt */ + GE2D_IRQn = 34, /*!< 2D Graphic Engine Interrupt */ + CRPT_IRQn = 35, /*!< Cryptographic Accelerator Interrupt */ + UART0_IRQn = 36, /*!< UART 0 Interrupt */ + UART1_IRQn = 37, /*!< UART 1 Interrupt */ + UART2_IRQn = 38, /*!< UART 2 Interrupt */ + UART4_IRQn = 39, /*!< UART 4 Interrupt */ + UART6_IRQn = 40, /*!< UART 6 Interrupt */ + UART8_IRQn = 41, /*!< UART 8 Interrupt */ + UART10_IRQn = 42, /*!< UART 10 Interrupt */ + UART3_IRQn = 43, /*!< UART 3 Interrupt */ + UART5_IRQn = 44, /*!< UART 5 Interrupt */ + UART7_IRQn = 45, /*!< UART 7 Interrupt */ + UART9_IRQn = 46, /*!< UART 9 Interrupt */ + ETMR0_IRQn = 47, /*!< Enhanced Timer 0 Interrupt */ + ETMR1_IRQn = 48, /*!< Enhanced Timer 1 Interrupt */ + ETMR2_IRQn = 49, /*!< Enhanced Timer 2 Interrupt */ + ETMR3_IRQn = 50, /*!< Enhanced Timer 3 Interrupt */ + SPI0_IRQn = 51, /*!< SPI 0 Interrupt */ + SPI1_IRQn = 52, /*!< SPI 1 Interrupt */ + I2C0_IRQn = 53, /*!< I2C 0 Interrupt */ + I2C1_IRQn = 54, /*!< I2C 1 Interrupt */ + SC0_IRQn = 55, /*!< Smart Card 0 Interrupt */ + SC1_IRQn = 56, /*!< Smart Card 1 Interrupt */ + GPIO_IRQn = 57, /*!< GPIO Interrupt */ + CAN0_IRQn = 58, /*!< CAN 0 Interrupt */ + CAN1_IRQn = 59, /*!< CAN 1 Interrupt */ + PWM_IRQn = 60, /*!< PWM Interrupt */ + + /* Renaming for RTT porting */ + IRQ_WDT = 1, /*!< Watch Dog Timer Interrupt */ + IRQ_WWDT = 2, /*!< Windowed-WDT Interrupt */ + IRQ_LVD = 3, /*!< Low Voltage Detect Interrupt */ + IRQ_EINT0 = 4, /*!< External Interrupt 0 */ + IRQ_EINT1 = 5, /*!< External Interrupt 1 */ + IRQ_EINT2 = 6, /*!< External Interrupt 2 */ + IRQ_EINT3 = 7, /*!< External Interrupt 3 */ + IRQ_EINT4 = 8, /*!< External Interrupt 4 */ + IRQ_EINT5 = 9, /*!< External Interrupt 5 */ + IRQ_EINT6 = 10, /*!< External Interrupt 6 */ + IRQ_EINT7 = 11, /*!< External Interrupt 7 */ + IRQ_ACTL = 12, /*!< Audio Controller Interrupt */ + IRQ_LCD = 13, /*!< LCD Controller Interrupt */ + IRQ_CAP = 14, /*!< Sensor Interface Controller Interrupt */ + IRQ_RTC = 15, /*!< Real Time Clock Interrupt */ + IRQ_TMR0 = 16, /*!< Timer 0 Interrupt */ + IRQ_TMR1 = 17, /*!< Timer 1 Interrupt */ + IRQ_ADC = 18, /*!< ADC Interrupt */ + IRQ_EMC0_RX = 19, /*!< EMC 0 RX Interrupt */ + IRQ_EMC1_RX = 20, /*!< EMC 1 RX Interrupt */ + IRQ_EMC0_TX = 21, /*!< EMC 0 TX Interrupt */ + IRQ_EMC1_TX = 22, /*!< EMC 1 TX Interrupt */ + IRQ_EHCI = 23, /*!< USB 2.0 Host Controller Interrupt */ + IRQ_OHCI = 24, /*!< USB 1.1 Host Controller Interrupt */ + IRQ_GDMA0 = 25, /*!< GDMA Channel 0 Interrupt */ + IRQ_GDMA1 = 26, /*!< GDMA Channel 1 Interrupt */ + IRQ_SDH = 27, /*!< SD/SDIO Host Interrupt */ + IRQ_FMI = 28, /*!< FMI Interrupt */ + IRQ_USBD = 29, /*!< USB Device Interrupt */ + IRQ_TMR2 = 30, /*!< Timer 2 Interrupt */ + IRQ_TMR3 = 31, /*!< Timer 3 Interrupt */ + IRQ_TMR4 = 32, /*!< Timer 4 Interrupt */ + IRQ_JPEG = 33, /*!< JPEG Engine Interrupt */ + IRQ_GE2D = 34, /*!< 2D Graphic Engine Interrupt */ + IRQ_CRPT = 35, /*!< Cryptographic Accelerator Interrupt */ + IRQ_UART0 = 36, /*!< UART 0 Interrupt */ + IRQ_UART1 = 37, /*!< UART 1 Interrupt */ + IRQ_UART2 = 38, /*!< UART 2 Interrupt */ + IRQ_UART4 = 39, /*!< UART 4 Interrupt */ + IRQ_UART6 = 40, /*!< UART 6 Interrupt */ + IRQ_UART8 = 41, /*!< UART 8 Interrupt */ + IRQ_UART10 = 42, /*!< UART 10 Interrupt */ + IRQ_UART3 = 43, /*!< UART 3 Interrupt */ + IRQ_UART5 = 44, /*!< UART 5 Interrupt */ + IRQ_UART7 = 45, /*!< UART 7 Interrupt */ + IRQ_UART9 = 46, /*!< UART 9 Interrupt */ + IRQ_ETMR0 = 47, /*!< Enhanced Timer 0 Interrupt */ + IRQ_ETMR1 = 48, /*!< Enhanced Timer 1 Interrupt */ + IRQ_ETMR2 = 49, /*!< Enhanced Timer 2 Interrupt */ + IRQ_ETMR3 = 50, /*!< Enhanced Timer 3 Interrupt */ + IRQ_SPI0 = 51, /*!< SPI 0 Interrupt */ + IRQ_SPI1 = 52, /*!< SPI 1 Interrupt */ + IRQ_I2C0 = 53, /*!< I2C 0 Interrupt */ + IRQ_I2C1 = 54, /*!< I2C 1 Interrupt */ + IRQ_SC0 = 55, /*!< Smart Card 0 Interrupt */ + IRQ_SC1 = 56, /*!< Smart Card 1 Interrupt */ + IRQ_GPIO = 57, /*!< GPIO Interrupt */ + IRQ_CAN0 = 58, /*!< CAN 0 Interrupt */ + IRQ_CAN1 = 59, /*!< CAN 1 Interrupt */ + IRQ_PWM = 60, /*!< PWM Interrupt */ +} +IRQn_Type; + +/* Define constants for use timer in service parameters. */ +#define TIMER0 0 /*!< Select Timer0 */ +#define TIMER1 1 /*!< Select Timer1 */ + +#define ONE_SHOT_MODE 0 /*!< Timer Operation Mode - One Shot */ +#define PERIODIC_MODE 1 /*!< Timer Operation Mode - Periodic */ +#define TOGGLE_MODE 2 /*!< Timer Operation Mode - Toggle */ + +/* The parameters for sysSetInterruptPriorityLevel() and + sysInstallISR() use */ +#define FIQ_LEVEL_0 0 /*!< FIQ Level 0 */ +#define IRQ_LEVEL_1 1 /*!< IRQ Level 1 */ +#define IRQ_LEVEL_2 2 /*!< IRQ Level 2 */ +#define IRQ_LEVEL_3 3 /*!< IRQ Level 3 */ +#define IRQ_LEVEL_4 4 /*!< IRQ Level 4 */ +#define IRQ_LEVEL_5 5 /*!< IRQ Level 5 */ +#define IRQ_LEVEL_6 6 /*!< IRQ Level 6 */ +#define IRQ_LEVEL_7 7 /*!< IRQ Level 7 */ + +#define ONE_HALF_SECS 0 /*!< WDT interval - 1.5s */ +#define FIVE_SECS 1 /*!< WDT interval - 5s */ +#define TEN_SECS 2 /*!< WDT interval - 10s */ +#define TWENTY_SECS 3 /*!< WDT interval - 20s */ + +/* Define constants for use AIC in service parameters. */ +#define SYS_SWI 0 /*!< Exception - SWI */ +#define SYS_D_ABORT 1 /*!< Exception - Data abort */ +#define SYS_I_ABORT 2 /*!< Exception - Instruction abort */ +#define SYS_UNDEFINE 3 /*!< Exception - undefine */ + +/* The parameters for sysSetLocalInterrupt() use */ +#define ENABLE_IRQ 0x7F /*!< Enable I-bit of CP15 */ +#define ENABLE_FIQ 0xBF /*!< Enable F-bit of CP15 */ +#define ENABLE_FIQ_IRQ 0x3F /*!< Enable I-bit and F-bit of CP15 */ +#define DISABLE_IRQ 0x80 /*!< Disable I-bit of CP15 */ +#define DISABLE_FIQ 0x40 /*!< Disable F-bit of CP15 */ +#define DISABLE_FIQ_IRQ 0xC0 /*!< Disable I-bit and F-bit of CP15 */ + +/* Define Cache type */ +#define CACHE_WRITE_BACK 0 /*!< Cache Write-back mode */ +#define CACHE_WRITE_THROUGH 1 /*!< Cache Write-through mode */ +#define CACHE_DISABLE -1 /*!< Cache Disable */ + +/** \brief Structure type of clock source + */ +typedef enum CLKn +{ + + SYS_UPLL = 1, /*!< UPLL clock */ + SYS_APLL = 2, /*!< APLL clock */ + SYS_SYSTEM = 3, /*!< System clock */ + SYS_HCLK1 = 4, /*!< HCLK1 clock */ + SYS_HCLK234 = 5, /*!< HCLK234 clock */ + SYS_PCLK = 6, /*!< PCLK clock */ + SYS_CPU = 7, /*!< CPU clock */ + +} CLK_Type; + + + +/// @cond HIDDEN_SYMBOLS +typedef struct datetime_t +{ + UINT32 year; + UINT32 mon; + UINT32 day; + UINT32 hour; + UINT32 min; + UINT32 sec; +} DateTime_T; + +/* The parameters for sysSetInterruptType() use */ +#define LOW_LEVEL_SENSITIVE 0x00 +#define HIGH_LEVEL_SENSITIVE 0x40 +#define NEGATIVE_EDGE_TRIGGER 0x80 +#define POSITIVE_EDGE_TRIGGER 0xC0 + +/* The parameters for sysSetGlobalInterrupt() use */ +#define ENABLE_ALL_INTERRUPTS 0 +#define DISABLE_ALL_INTERRUPTS 1 + +#define MMU_DIRECT_MAPPING 0 +#define MMU_INVERSE_MAPPING 1 + + +/* Define constants for use Cache in service parameters. */ +#define CACHE_4M 2 +#define CACHE_8M 3 +#define CACHE_16M 4 +#define CACHE_32M 5 +#define I_CACHE 6 +#define D_CACHE 7 +#define I_D_CACHE 8 + + +/** + * @brief Disable register write-protection function + * @param None + * @return None + * @details This function disable register write-protection function. + * To unlock the protected register to allow write access. + */ +static __inline void SYS_UnlockReg(void) +{ + do + { + outpw(0xB00001FC, 0x59UL); + outpw(0xB00001FC, 0x16UL); + outpw(0xB00001FC, 0x88UL); + } + while (inpw(0xB00001FC) == 0UL); +} + +/** + * @brief Enable register write-protection function + * @param None + * @return None + * @details This function is used to enable register write-protection function. + * To lock the protected register to forbid write access. + */ +static __inline void SYS_LockReg(void) +{ + outpw(0xB00001FC, 0); +} + + +/// @endcond HIDDEN_SYMBOLS + +/*@}*/ /* end of group N9H30_SYS_EXPORTED_CONSTANTS */ + + +/** @addtogroup N9H30_SYS_EXPORTED_FUNCTIONS SYS Exported Functions + @{ +*/ + +/* Define system library Timer functions */ +UINT32 sysGetTicks(INT32 nTimeNo); +INT32 sysResetTicks(INT32 nTimeNo); +INT32 sysUpdateTickCount(INT32 nTimeNo, UINT32 uCount); +INT32 sysSetTimerReferenceClock(INT32 nTimeNo, UINT32 uClockRate); +INT32 sysStartTimer(INT32 nTimeNo, UINT32 uTicksPerSecond, INT32 nOpMode); +INT32 sysStopTimer(INT32 nTimeNo); +void sysClearWatchDogTimerCount(void); +void sysClearWatchDogTimerInterruptStatus(void); +void sysDisableWatchDogTimer(void); +void sysDisableWatchDogTimerReset(void); +void sysEnableWatchDogTimer(void); +void sysEnableWatchDogTimerReset(void); +PVOID sysInstallWatchDogTimerISR(INT32 nIntTypeLevel, PVOID pvNewISR); +INT32 sysSetWatchDogTimerInterval(INT32 nWdtInterval); +INT32 sysSetTimerEvent(INT32 nTimeNo, UINT32 uTimeTick, PVOID pvFun); +void sysClearTimerEvent(INT32 nTimeNo, UINT32 uTimeEventNo); +void sysSetLocalTime(DateTime_T ltime); /*!< Set local time \hideinitializer */ +void sysGetCurrentTime(DateTime_T *curTime); /*!< Get current time \hideinitializer */ +void sysDelay(UINT32 uTicks); + +/* Define system library UART functions */ +//INT8 sysGetChar(void); +//INT32 sysInitializeUART(void); +//void sysprintf(PINT8 pcStr, ...); +//void sysPutChar(UINT8 ucCh); +//INT sysIsKbHit(void); + +/* Define system library AIC functions */ +INT32 sysDisableInterrupt(IRQn_Type eIntNo); +INT32 sysEnableInterrupt(IRQn_Type eIntNo); +BOOL sysGetIBitState(void); /*!< Get I bit state \hideinitializer */ +UINT32 sysGetInterruptEnableStatus(void); /*!< Get interrupt enable status \hideinitializer */ +UINT32 sysGetInterruptEnableStatusH(void); /*!< Get interrupt enable status \hideinitializer */ +PVOID sysInstallExceptionHandler(INT32 nExceptType, PVOID pvNewHandler); +PVOID sysInstallFiqHandler(PVOID pvNewISR); +PVOID sysInstallIrqHandler(PVOID pvNewISR); +PVOID sysInstallISR(INT32 nIntTypeLevel, IRQn_Type eIntNo, PVOID pvNewISR); +INT32 sysSetGlobalInterrupt(INT32 nIntState); /*!< Enable/Disable all interrupt \hideinitializer */ +INT32 sysSetInterruptPriorityLevel(IRQn_Type eIntNo, UINT32 uIntLevel); +INT32 sysSetInterruptType(IRQn_Type eIntNo, UINT32 uIntSourceType); /*!< Change interrupt type \hideinitializer */ +INT32 sysSetLocalInterrupt(INT32 nIntState); + + +/* Define system library Cache functions */ +void sysDisableCache(void); +INT32 sysEnableCache(UINT32 uCacheOpMode); +void sysFlushCache(INT32 nCacheType); /*!< flush cache \hideinitializer */ +BOOL sysGetCacheState(void); /*!< get cache state \hideinitializer */ +INT32 sysGetSdramSizebyMB(void); /*!< Get DRAM size \hideinitializer */ +void sysInvalidCache(void); /*!< invalid cache \hideinitializer */ +INT32 sysSetCachePages(UINT32 addr, INT32 size, INT32 cache_mode); /*!< set cache page \hideinitializer */ + +int sysSetMMUMappingMethod(int mode); /*!< MMU mapping \hideinitializer */ + +UINT32 sysGetClock(CLK_Type clk); + +typedef void (*sys_pvFunPtr)(); /* function pointer */ +/// @cond HIDDEN_SYMBOLS +extern sys_pvFunPtr sysIrqHandlerTable[]; +extern BOOL volatile _sys_bIsAICInitial; +/// @endcond +#ifdef __cplusplus +} +#endif + +/*@}*/ /* end of group N9H30_SYS_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_SYS_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#endif //__NU_SYS_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_timer.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_timer.h new file mode 100644 index 0000000000..674cc86eac --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_timer.h @@ -0,0 +1,61 @@ +/**************************************************************************//** + * @file timer.h + * @brief N9H30 series TIMER driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_TIMER_H__ +#define __NU_TIMER_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "N9H30.h" + +#define TIMER_COUNTER_ENABLE (1UL << 30) /*!< Timer counter enable */ +#define TIMER_INTERRUPT_ENABLE (1UL << 29) /*!< Timer interrupt enable */ + +#define TIMER_ONESHOT_MODE (0UL) /*!< Timer working in one shot mode */ +#define TIMER_PERIODIC_MODE (1UL << 27) /*!< Timer working in periodic mode */ +#define TIMER_CONTINUOUS_MODE (3UL << 27) /*!< Timer working in continuous mode */ + +#define TIMER_COUNTER_RESET (1UL << 26) /*!< Timer reset counter */ +#define TIMER_IS_ALIVE (1UL << 25) /*!< Timer is alive */ + +static __inline void TIMER_ClearIntFlag(uint32_t timer) +{ + outpw(REG_TMR_ISR, (1 << timer)); +} + +static __inline uint32_t TIMER_GetIntFlag(uint32_t timer) +{ + return inpw(REG_TMR_ISR) & (1 << timer); +} + +void TIMER_SET_CMP_VALUE(uint32_t timer, uint32_t u32Cmpr); +void TIMER_SET_OPMODE(uint32_t timer, uint32_t u32OpMode); +void TIMER_SET_PRESCALE_VALUE(uint32_t timer, uint32_t u32PreScale); +uint32_t TIMER_GetModuleClock(uint32_t timer); +void TIMER_Start(uint32_t timer); +void TIMER_Stop(uint32_t timer); +void TIMER_ClearCounter(uint32_t timer); +uint32_t TIMER_GetCounter(uint32_t timer); +uint32_t TIMER_GetCompareData(uint32_t timer); +void TIMER_EnableInt(uint32_t timer); +void TIMER_DisableInt(uint32_t timer); +void TIMER_Close(uint32_t timer); +uint32_t TIMER_Open(uint32_t timer, uint32_t u32Mode, uint32_t u32Freq); +__inline void TIMER_ClearIntFlag(uint32_t timer); +__inline uint32_t TIMER_GetIntFlag(uint32_t timer); + +#ifdef __cplusplus +} +#endif + +#endif //__NU_TIMER_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h new file mode 100644 index 0000000000..4f24a2d10d --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h @@ -0,0 +1,773 @@ +/**************************************************************************//** +* @file uart.h +* @version V1.00 +* @brief N9H30 UART driver header file +* +* SPDX-License-Identifier: Apache-2.0 +* @copyright (C) 2015 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_UART_H__ +#define __NU_UART_H__ + +#include "N9H30.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_UART_Driver UART Driver + @{ +*/ + + + +/*-----------------------------------------*/ +/* marco, type and constant definitions */ +/*-----------------------------------------*/ +/// @cond HIDDEN_SYMBOLS +#define UART_NUM 11 + +#define UARTOFFSET 0x100 +/// @endcond HIDDEN_SYMBOLS + +/** @addtogroup N9H30_UART_EXPORTED_CONSTANTS UART Exported Constants + @{ +*/ + +#define UARTWRITESIZE 100 /*!< UART max. write size */ + +#define UARTINTMODE 1 /*!< UART interrupt mode */ +#define UARTPOLLMODE 0 /*!< UART polling mode */ +#define DISABLEALLIER 0 /*!< Disable all interrupt */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART channel number */ +/*---------------------------------------------------------------------------------------------------------*/ +#define ALLCHANNEL 11 /*!< UART ALL channel */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UA_FCR constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ + +#define UART_FCR_RFITL_1BYTE (0x0 << UART_FCR_RFITL_Pos) /*!< UA_FCR setting to set RX FIFO Trigger Level to 1 bit */ +#define UART_FCR_RFITL_4BYTES (0x1 << UART_FCR_RFITL_Pos) /*!< UA_FCR setting to set RX FIFO Trigger Level to 4 bits */ +#define UART_FCR_RFITL_8BYTES (0x2 << UART_FCR_RFITL_Pos) /*!< UA_FCR setting to set RX FIFO Trigger Level to 8 bits */ +#define UART_FCR_RFITL_14BYTES (0x3 << UART_FCR_RFITL_Pos) /*!< UA_FCR setting to set RX FIFO Trigger Level to 14 bits */ +#define UART_FCR_RFITL_30BYTES (0x4 << UART_FCR_RFITL_Pos) /*!< UA_FCR setting to set RX FIFO Trigger Level to 30 bits */ +#define UART_FCR_RFITL_46BYTES (0x5 << UART_FCR_RFITL_Pos) /*!< UA_FCR setting to set RX FIFO Trigger Level to 46 bits */ +#define UART_FCR_RFITL_62BYTES (0x6 << UART_FCR_RFITL_Pos) /*!< UA_FCR setting to set RX FIFO Trigger Level to 62 bits */ + +#define UART_FCR_RTS_TRI_LEV_1BYTE (0x0 << UART_FCR_RTS_TRI_LEV_Pos) /*!< UA_FCR setting to set RTS Trigger Level to 1 bit */ +#define UART_FCR_RTS_TRI_LEV_4BYTES (0x1 << UART_FCR_RTS_TRI_LEV_Pos) /*!< UA_FCR setting to set RTS Trigger Level to 4 bits */ +#define UART_FCR_RTS_TRI_LEV_8BYTES (0x2 << UART_FCR_RTS_TRI_LEV_Pos) /*!< UA_FCR setting to set RTS Trigger Level to 8 bits */ +#define UART_FCR_RTS_TRI_LEV_14BYTES (0x3 << UART_FCR_RTS_TRI_LEV_Pos) /*!< UA_FCR setting to set RTS Trigger Level to 14 bits */ +#define UART_FCR_RTS_TRI_LEV_30BYTES (0x4 << UART_FCR_RTS_TRI_LEV_Pos) /*!< UA_FCR setting to set RTS Trigger Level to 30 bits */ +#define UART_FCR_RTS_TRI_LEV_46BYTES (0x5 << UART_FCR_RTS_TRI_LEV_Pos) /*!< UA_FCR setting to set RTS Trigger Level to 46 bits */ +#define UART_FCR_RTS_TRI_LEV_62BYTES (0x6 << UART_FCR_RTS_TRI_LEV_Pos) /*!< UA_FCR setting to set RTS Trigger Level to 62 bits */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UA_LCR constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_WORD_LEN_5 (0) /*!< UA_LCR setting to set UART word length to 5 bits */ +#define UART_WORD_LEN_6 (1) /*!< UA_LCR setting to set UART word length to 6 bits */ +#define UART_WORD_LEN_7 (2) /*!< UA_LCR setting to set UART word length to 7 bits */ +#define UART_WORD_LEN_8 (3) /*!< UA_LCR setting to set UART word length to 8 bits */ + +#define UART_PARITY_NONE (0x0 << UART_LCR_PBE_Pos) /*!< UA_LCR setting to set UART as no parity */ +#define UART_PARITY_ODD (0x1 << UART_LCR_PBE_Pos) /*!< UA_LCR setting to set UART as odd parity */ +#define UART_PARITY_EVEN (0x3 << UART_LCR_PBE_Pos) /*!< UA_LCR setting to set UART as even parity */ +#define UART_PARITY_STICK (0x8 << UART_LCR_PBE_Pos) /*!< UA_LCR setting to set UART as stick parity */ + +#define UART_STOP_BIT_1 (0x0 << UART_LCR_NSB_Pos) /*!< UA_LCR setting for one stop bit */ +#define UART_STOP_BIT_1_5 (0x1 << UART_LCR_NSB_Pos) /*!< UA_LCR setting for 1.5 stop bit when 5-bit word length */ +#define UART_STOP_BIT_2 (0x1 << UART_LCR_NSB_Pos) /*!< UA_LCR setting for two stop bit when 6, 7, 8-bit word length */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART RTS LEVEL TRIGGER constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_RTS_IS_HIGH_LEV_TRG (0x1 << UART_MCR_LEV_RTS_Pos) /*!< Set RTS is High Level Tigger */ +#define UART_RTS_IS_LOW_LEV_TRG (0x0 << UART_MCR_LEV_RTS_Pos) /*!< Set RTS is Low Level Tigger */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART CTS LEVEL TRIGGER constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_CTS_IS_HIGH_LEV_TRG (0x1 << UART_MSR_LEV_CTS_Pos) /*!< Set CTS is High Level Trigger */ +#define UART_CTS_IS_LOW_LEV_TRG (0x0 << UART_MSR_LEV_CTS_Pos) /*!< Set CTS is Low Level Trigger */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UA_FUNC_SEL constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_FUNC_SEL_UART (0x0 << UART_FUN_SEL_FUN_SEL_Pos) /*!< UA_FUNC_SEL setting to set UART Function (Default) */ +#define UART_FUNC_SEL_LIN (0x1 << UART_FUN_SEL_FUN_SEL_Pos) /*!< UA_FUNC_SEL setting to set LIN Funciton */ +#define UART_FUNC_SEL_IrDA (0x2 << UART_FUN_SEL_FUN_SEL_Pos) /*!< UA_FUNC_SEL setting to set IrDA Function */ +#define UART_FUNC_SEL_RS485 (0x3 << UART_FUN_SEL_FUN_SEL_Pos) /*!< UA_FUNC_SEL setting to set RS485 Function */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UA_LIN_CTL constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_LIN_CTL_LINS_EN (0x1UL << UART_LIN_CTL_LINS_EN_Pos) /*!< UA_LIN_CTL setting to set LIN Slave Mode Enable */ +#define UART_LIN_CTL_LINS_HDET_EN (0x1UL << UART_LIN_CTL_LINS_HDET_EN_Pos) /*!< UA_LIN_CTL setting to set LIN Slave Header Detection Enable */ +#define UART_LIN_CTL_LINS_ARS_EN (0x1UL << UART_LIN_CTL_LINS_ARS_EN_Pos) /*!< UA_LIN_CTL setting to set LIN Slave Automatic Resynchronization Mode Enable */ +#define UART_LIN_CTL_LINS_DUM_EN (0x1UL << UART_LIN_CTL_LINS_DUM_EN_Pos) /*!< UA_LIN_CTL setting to set LIN Slave Divider Update Method Enable */ +#define UART_LIN_CTL_LIN_WAKE_EN (0x1UL << UART_LIN_CTL_LIN_WAKE_EN_Pos) /*!< UA_LIN_CTL setting to set LIN Wake-Up Mode Enable */ +#define UART_LIN_CTL_LIN_SHD (0x1UL << UART_LIN_CTL_LIN_SHD_Pos) /*!< UA_LIN_CTL setting to set LIN TX Send Header Enable */ +#define UART_LIN_CTL_LIN_IDPEN (0x1UL << UART_LIN_CTL_LIN_IDPEN_Pos) /*!< UA_LIN_CTL setting to set LIN ID Parity Enable */ +#define UART_LIN_CTL_LIN_BKDET_ENN (0x1UL << UART_LIN_CTL_LIN_BKDET_EN_Pos) /*!< UA_LIN_CTL setting to set LIN Break Detection Enable */ +#define UART_LIN_CTL_LIN_RX_DIS (0x1UL << UART_LIN_CTL_LIN_RX_DIS_Pos) /*!< UA_LIN_CTL setting to set LIN Receiver Disable */ +#define UART_LIN_CTL_BIT_ERR_EN (0x1UL << UART_LIN_CTL_BIT_ERR_EN_Pos) /*!< UA_LIN_CTL setting to set Bit Error Detect Enable */ +#define UART_LIN_CTL_LIN_BKFL(x) (((x)-1) << UART_LIN_CTL_LIN_BKFL_Pos) /*!< UA_LIN_CTL setting to set LIN Break Field Length, x = 10 ~ 15, default value is 12 */ +#define UART_LIN_CTL_LIN_BS_LEN(x) (((x)-1) << UART_LIN_CTL_LIN_BS_LEN_Pos)/*!< UA_LIN_CTL setting to set LIN Break/Sync Delimiter Length, x = 1 ~ 4 */ +#define UART_LIN_CTL_LIN_HEAD_SEL_BREAK (0x0UL << UART_LIN_CTL_LIN_HEAD_SEL_Pos) /*!< UA_LIN_CTL setting to set LIN Header Select to break field */ +#define UART_LIN_CTL_LIN_HEAD_SEL_BREAK_SYNC (0x1UL << UART_LIN_CTL_LIN_HEAD_SEL_Pos) /*!< UA_LIN_CTL setting to set LIN Header Select to break field and sync field */ +#define UART_LIN_CTL_LIN_HEAD_SEL_BREAK_SYNC_ID (0x2UL << UART_LIN_CTL_LIN_HEAD_SEL_Pos) /*!< UA_LIN_CTL setting to set LIN Header Select to break field, sync field and ID field*/ +#define UART_LIN_CTL_LIN_LIN_PID(x) ((x) << UART_LIN_CTL_LIN_PID_Pos) /*!< UA_LIN_CTL setting to set LIN PID value */ + + +/*---------------------------------------------------------------------------------------------------------*/ +/* BAUD constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_BAUD_MODE0 (0) /*!< Set UART Baudrate Mode is Mode0 */ +#define UART_BAUD_MODE2 (UART_BAUD_DIV_X_EN_Msk | UART_BAUD_DIV_X_ONE_Msk) /*!< Set UART Baudrate Mode is Mode2 */ + +/* UART THR Bit Field Definitions */ +#define UART_THR_THR_Pos 0 /*!< UART THR: THR Position */ +#define UART_THR_THR_Msk (0xFFul << UART_THR_THR_Pos) /*!< UART THR: THR Mask */ + +/* UART RBR Bit Field Definitions */ +#define UART_RBR_RBR_Pos 0 /*!< UART RBR: RBR Posistion */ +#define UART_RBR_RBR_Msk (0xFFul << UART_RBR_RBR_Pos) /*!< UART RBR: RBR Mask */ + +/* UART IER Bit Field Definitions */ +#define UART_IER_DMA_RX_EN_Pos 15 /*!< UART IER: RX DMA Enable Posistion */ +#define UART_IER_DMA_RX_EN_Msk (1ul << UART_IER_DMA_RX_EN_Pos) /*!< UART IER: RX DMA Enable Mask */ + +#define UART_IER_DMA_TX_EN_Pos 14 /*!< UART IER: TX DMA Enable Posistion */ +#define UART_IER_DMA_TX_EN_Msk (1ul << UART_IER_DMA_TX_EN_Pos) /*!< UART IER: TX DMA Enable Mask */ + +#define UART_IER_AUTO_CTS_EN_Pos 13 /*!< UART IER: AUTO_CTS_EN Posistion */ +#define UART_IER_AUTO_CTS_EN_Msk (1ul << UART_IER_AUTO_CTS_EN_Pos) /*!< UART IER: AUTO_CTS_EN Mask */ + +#define UART_IER_AUTO_RTS_EN_Pos 12 /*!< UART IER: AUTO_RTS_EN Posistion */ +#define UART_IER_AUTO_RTS_EN_Msk (1ul << UART_IER_AUTO_RTS_EN_Pos) /*!< UART IER: AUTO_RTS_EN Mask */ + +#define UART_IER_TIME_OUT_EN_Pos 11 /*!< UART IER: TIME_OUT_EN Posistion */ +#define UART_IER_TIME_OUT_EN_Msk (1ul << UART_IER_TIME_OUT_EN_Pos) /*!< UART IER: TIME_OUT_EN Mask */ + +#define UART_IER_LIN_RX_BRK_IEN_Pos 8 /*!< UART IER: LIN_RX_BRK_IEN Posistion */ +#define UART_IER_LIN_RX_BRK_IEN_Msk (1ul << UART_IER_LIN_RX_BRK_IEN_Pos) /*!< UART IER: LIN_RX_BRK_IEN Mask */ + +#define UART_IER_WAKE_EN_Pos 6 /*!< UART IER: WAKE_EN Posistion */ +#define UART_IER_WAKE_EN_Msk (1ul << UART_IER_WAKE_EN_Pos) /*!< UART IER: WAKE_EN Mask */ + +#define UART_IER_BUF_ERR_IEN_Pos 5 /*!< UART IER: BUF_ERR_IEN Posistion */ +#define UART_IER_BUF_ERR_IEN_Msk (1ul << UART_IER_BUF_ERR_IEN_Pos) /*!< UART IER: BUF_ERR_IEN Mask */ + +#define UART_IER_RTO_IEN_Pos 4 /*!< UART IER: RTO_IEN Posistion */ +#define UART_IER_RTO_IEN_Msk (1ul << UART_IER_RTO_IEN_Pos) /*!< UART IER: RTO_IEN Mask */ + +#define UART_IER_MODEM_IEN_Pos 3 /*!< UART IER: MODEM_IEN Posistion */ +#define UART_IER_MODEM_IEN_Msk (1ul << UART_IER_MODEM_IEN_Pos) /*!< UART IER: MODEM_IEN Mask */ + +#define UART_IER_RLS_IEN_Pos 2 /*!< UART IER: RLS_IEN Posistion */ +#define UART_IER_RLS_IEN_Msk (1ul << UART_IER_RLS_IEN_Pos) /*!< UART IER: RLS_IEN Mask */ + +#define UART_IER_THRE_IEN_Pos 1 /*!< UART IER: THRE_IEN Posistion */ +#define UART_IER_THRE_IEN_Msk (1ul << UART_IER_THRE_IEN_Pos) /*!< UART IER: THRE_IEN Mask */ + +#define UART_IER_RDA_IEN_Pos 0 /*!< UART IER: RDA_IEN Position */ +#define UART_IER_RDA_IEN_Msk (1ul << UART_IER_RDA_IEN_Pos) /*!< UART IER: RDA_IEN Mask */ + +/* UART FCR Bit Field Definitions */ +#define UART_FCR_RTS_TRI_LEV_Pos 16 /*!< UART FCR: RTS_TRI_LEV Position */ +#define UART_FCR_RTS_TRI_LEV_Msk (0xFul << UART_FCR_RTS_TRI_LEV_Pos) /*!< UART FCR: RTS_TRI_LEV Mask */ + +#define UART_FCR_RX_DIS_Pos 8 /*!< UART FCR: RX_DIS Position */ +#define UART_FCR_RX_DIS_Msk (1ul << UART_FCR_RX_DIS_Pos) /*!< UART FCR: RX_DIS Mask */ + +#define UART_FCR_RFITL_Pos 4 /*!< UART FCR: RFITL Position */ +#define UART_FCR_RFITL_Msk (0xFul << UART_FCR_RFITL_Pos) /*!< UART FCR: RFITL Mask */ + +#define UART_FCR_TFR_Pos 2 /*!< UART FCR: TFR Position */ +#define UART_FCR_TFR_Msk (1ul << UART_FCR_TFR_Pos) /*!< UART FCR: TFR Mask */ + +#define UART_FCR_RFR_Pos 1 /*!< UART FCR: RFR Position */ +#define UART_FCR_RFR_Msk (1ul << UART_FCR_RFR_Pos) /*!< UART FCR: RFR Mask */ + +/* UART LCR Bit Field Definitions */ +#define UART_LCR_BCB_Pos 6 /*!< UART LCR: BCB Position */ +#define UART_LCR_BCB_Msk (1ul << UART_LCR_BCB_Pos) /*!< UART LCR: BCB Mask */ + +#define UART_LCR_SPE_Pos 5 /*!< UART LCR: SPE Position */ +#define UART_LCR_SPE_Msk (1ul << UART_LCR_SPE_Pos) /*!< UART LCR: SPE Mask */ + +#define UART_LCR_EPE_Pos 4 /*!< UART LCR: EPE Position */ +#define UART_LCR_EPE_Msk (1ul << UART_LCR_EPE_Pos) /*!< UART LCR: EPE Mask */ + +#define UART_LCR_PBE_Pos 3 /*!< UART LCR: PBE Position */ +#define UART_LCR_PBE_Msk (1ul << UART_LCR_PBE_Pos) /*!< UART LCR: PBE Mask */ + +#define UART_LCR_NSB_Pos 2 /*!< UART LCR: NSB Position */ +#define UART_LCR_NSB_Msk (1ul << UART_LCR_NSB_Pos) /*!< UART LCR: NSB Mask */ + +#define UART_LCR_WLS_Pos 0 /*!< UART LCR: WLS Position */ +#define UART_LCR_WLS_Msk (0x3ul << UART_LCR_WLS_Pos) /*!< UART LCR: WLS Mask */ + +/* UART MCR Bit Field Definitions */ +#define UART_MCR_RTS_ST_Pos 13 /*!< UART MCR: RTS_ST Position */ +#define UART_MCR_RTS_ST_Msk (1ul << UART_MCR_RTS_ST_Pos) /*!< UART MCR: RTS_ST Mask */ + +#define UART_MCR_LEV_RTS_Pos 9 /*!< UART MCR: LEV_RTS Position */ +#define UART_MCR_LEV_RTS_Msk (1ul << UART_MCR_LEV_RTS_Pos) /*!< UART MCR: LEV_RTS Mask */ + +#define UART_MCR_RTS_Pos 1 /*!< UART MCR: RTS Position */ +#define UART_MCR_RTS_Msk (1ul << UART_MCR_RTS_Pos) /*!< UART MCR: RTS Mask */ + +/* UART MSR Bit Field Definitions */ +#define UART_MSR_LEV_CTS_Pos 8 /*!< UART MSR: LEV_CTS Position */ +#define UART_MSR_LEV_CTS_Msk (1ul << UART_MSR_LEV_CTS_Pos) /*!< UART MSR: LEV_CTS Mask */ + +#define UART_MSR_CTS_ST_Pos 4 /*!< UART MSR: CTS_ST Position */ +#define UART_MSR_CTS_ST_Msk (1ul << UART_MSR_CTS_ST_Pos) /*!< UART MSR: CTS_ST Mask */ + +#define UART_MSR_DCTSF_Pos 0 /*!< UART MSR: DCTST Position */ +#define UART_MSR_DCTSF_Msk (1ul << UART_MSR_DCTSF_Pos) /*!< UART MSR: DCTST Mask */ + + +/* UART FSR Bit Field Definitions */ +#define UART_FSR_TE_FLAG_Pos 28 /*!< UART FSR: TE_FLAG Position */ +#define UART_FSR_TE_FLAG_Msk (1ul << UART_FSR_TE_FLAG_Pos) /*!< UART FSR: TE_FLAG Mask */ + +#define UART_FSR_TX_OVER_IF_Pos 24 /*!< UART FSR: TX_OVER_IF Position */ +#define UART_FSR_TX_OVER_IF_Msk (1ul << UART_FSR_TX_OVER_IF_Pos) /*!< UART FSR: TX_OVER_IF Mask */ + +#define UART_FSR_TX_FULL_Pos 23 /*!< UART FSR: TX_FULL Position */ +#define UART_FSR_TX_FULL_Msk (1ul << UART_FSR_TX_FULL_Pos) /*!< UART FSR: TX_FULL Mask */ + +#define UART_FSR_TX_EMPTY_Pos 22 /*!< UART FSR: TX_EMPTY Position */ +#define UART_FSR_TX_EMPTY_Msk (1ul << UART_FSR_TX_EMPTY_Pos) /*!< UART FSR: TX_EMPTY Mask */ + +#define UART_FSR_TX_POINTER_Pos 16 /*!< UART FSR: TX_POINTER Position */ +#define UART_FSR_TX_POINTER_Msk (0x3Ful << UART_FSR_TX_POINTER_Pos) /*!< UART FSR: TX_POINTER Mask */ + +#define UART_FSR_RX_FULL_Pos 15 /*!< UART FSR: RX_FULL Position */ +#define UART_FSR_RX_FULL_Msk (1ul << UART_FSR_RX_FULL_Pos) /*!< UART FSR: RX_FULL Mask */ + +#define UART_FSR_RX_EMPTY_Pos 14 /*!< UART FSR: RX_EMPTY Position */ +#define UART_FSR_RX_EMPTY_Msk (1ul << UART_FSR_RX_EMPTY_Pos) /*!< UART FSR: RX_EMPTY Mask */ + +#define UART_FSR_RX_POINTER_Pos 8 /*!< UART FSR: RX_POINTERS Position */ +#define UART_FSR_RX_POINTER_Msk (0x3Ful << UART_FSR_RX_POINTER_Pos) /*!< UART FSR: RX_POINTER Mask */ + +#define UART_FSR_BIF_Pos 6 /*!< UART FSR: BIF Position */ +#define UART_FSR_BIF_Msk (1ul << UART_FSR_BIF_Pos) /*!< UART FSR: BIF Mask */ + +#define UART_FSR_FEF_Pos 5 /*!< UART FSR: FEF Position */ +#define UART_FSR_FEF_Msk (1ul << UART_FSR_FEF_Pos) /*!< UART FSR: FEF Mask */ + +#define UART_FSR_PEF_Pos 4 /*!< UART FSR: PEF Position */ +#define UART_FSR_PEF_Msk (1ul << UART_FSR_PEF_Pos) /*!< UART FSR: PEF Mask */ + +#define UART_FSR_RS485_ADD_DETF_Pos 3 /*!< UART FSR: RS485_ADD_DETF Position */ +#define UART_FSR_RS485_ADD_DETF_Msk (1ul << UART_FSR_RS485_ADD_DETF_Pos) /*!< UART FSR: RS485_ADD_DETF Mask */ + +#define UART_FSR_RX_OVER_IF_Pos 0 /*!< UART FSR: RX_OVER_IF Position */ +#define UART_FSR_RX_OVER_IF_Msk (1ul << UART_FSR_RX_OVER_IF_Pos) /*!< UART FSR: RX_OVER_IF Mask */ + +/* UART ISR Bit Field Definitions */ +#define UART_ISR_LIN_RX_BREAK_INT_Pos 15 /*!< UART ISR: LIN_RX_BREAK_INT Position */ +#define UART_ISR_LIN_RX_BREAK_INT_Msk (1ul << UART_ISR_LIN_RX_BREAK_INT_Pos) /*!< UART ISR: LIN_RX_BREAK_INT Mask */ + +#define UART_ISR_BUF_ERR_INT_Pos 13 /*!< UART ISR: BUF_ERR_INT Position */ +#define UART_ISR_BUF_ERR_INT_Msk (1ul << UART_ISR_BUF_ERR_INT_Pos) /*!< UART ISR: BUF_ERR_INT Mask */ + +#define UART_ISR_TOUT_INT_Pos 12 /*!< UART ISR: TOUT_INT Position */ +#define UART_ISR_TOUT_INT_Msk (1ul << UART_ISR_TOUT_INT_Pos) /*!< UART ISR: TOUT_INT Mask */ + +#define UART_ISR_MODEM_INT_Pos 11 /*!< UART ISR: MODEM_INT Position */ +#define UART_ISR_MODEM_INT_Msk (1ul << UART_ISR_MODEM_INT_Pos) /*!< UART ISR: MODEM_INT Mask */ + +#define UART_ISR_RLS_INT_Pos 10 /*!< UART ISR: RLS_INT Position */ +#define UART_ISR_RLS_INT_Msk (1ul << UART_ISR_RLS_INT_Pos) /*!< UART ISR: RLS_INT Mask */ + +#define UART_ISR_THRE_INT_Pos 9 /*!< UART ISR: THRE_INT Position */ +#define UART_ISR_THRE_INT_Msk (1ul << UART_ISR_THRE_INT_Pos) /*!< UART ISR: THRE_INT Mask */ + +#define UART_ISR_RDA_INT_Pos 8 /*!< UART ISR: RDA_INT Position */ +#define UART_ISR_RDA_INT_Msk (1ul << UART_ISR_RDA_INT_Pos) /*!< UART ISR: RDA_INT Mask */ + +#define UART_ISR_LIN_RX_BREAK_IF_Pos 7 /*!< UART ISR: LIN RX BREAK IF Position */ +#define UART_ISR_LIN_RX_BREAK_IF_Msk (1ul << UART_ISR_LIN_RX_BREAK_IF_Pos) /*!< UART ISR: LIN RX BREAK IF Mask */ + +#define UART_ISR_BUF_ERR_IF_Pos 5 /*!< UART ISR: BUF_ERR_IF Position */ +#define UART_ISR_BUF_ERR_IF_Msk (1ul << UART_ISR_BUF_ERR_IF_Pos) /*!< UART ISR: BUF_ERR_IF Mask */ + +#define UART_ISR_TOUT_IF_Pos 4 /*!< UART ISR: TOUT_IF Position */ +#define UART_ISR_TOUT_IF_Msk (1ul << UART_ISR_TOUT_IF_Pos) /*!< UART ISR: TOUT_IF Mask */ + +#define UART_ISR_MODEM_IF_Pos 3 /*!< UART ISR: MODEM_IF Position */ +#define UART_ISR_MODEM_IF_Msk (1ul << UART_ISR_MODEM_IF_Pos) /*!< UART ISR: MODEM_IF Mask */ + +#define UART_ISR_RLS_IF_Pos 2 /*!< UART ISR: RLS_IF Position */ +#define UART_ISR_RLS_IF_Msk (1ul << UART_ISR_RLS_IF_Pos) /*!< UART ISR: RLS_IF Mask */ + +#define UART_ISR_THRE_IF_Pos 1 /*!< UART ISR: THRE_IF Position */ +#define UART_ISR_THRE_IF_Msk (1ul << UART_ISR_THRE_IF_Pos) /*!< UART ISR: THRE_IF Mask */ + +#define UART_ISR_RDA_IF_Pos 0 /*!< UART ISR: RDA_IF Position */ +#define UART_ISR_RDA_IF_Msk (1ul << UART_ISR_RDA_IF_Pos) /*!< UART ISR: RDA_IF Mask */ + + +/* UART TOR Bit Field Definitions */ +#define UART_TOR_DLY_Pos 8 /*!< UART TOR: DLY Position */ +#define UART_TOR_DLY_Msk (0xFFul << UART_TOR_DLY_Pos) /*!< UART TOR: DLY Mask */ + +#define UART_TOR_TOIC_Pos 0 /*!< UART TOR: TOIC Position */ +#define UART_TOR_TOIC_Msk (0xFFul << UART_TOR_TOIC_Pos) /*!< UART TOR: TOIC Mask */ + +/* UART BAUD Bit Field Definitions */ +#define UART_BAUD_DIV_X_EN_Pos 29 /*!< UART BARD: DIV_X_EN Position */ +#define UART_BAUD_DIV_X_EN_Msk (1ul << UART_BAUD_DIV_X_EN_Pos) /*!< UART BARD: DIV_X_EN Mask */ + +#define UART_BAUD_DIV_X_ONE_Pos 28 /*!< UART BARD: DIV_X_ONE Position */ +#define UART_BAUD_DIV_X_ONE_Msk (1ul << UART_BAUD_DIV_X_ONE_Pos) /*!< UART BARD: DIV_X_ONE Mask */ + +#define UART_BAUD_DIVIDER_X_Pos 24 /*!< UART BARD: DIVIDER_X Position */ +#define UART_BAUD_DIVIDER_X_Msk (0xFul << UART_BAUD_DIVIDER_X_Pos) /*!< UART BARD: DIVIDER_X Mask */ + +#define UART_BAUD_BRD_Pos 0 /*!< UART BARD: BRD Position */ +#define UART_BAUD_BRD_Msk (0xFFFFul << UART_BAUD_BRD_Pos) /*!< UART BARD: BRD Mask */ + +/* UART IRCR Bit Field Definitions */ +#define UART_IRCR_INV_RX_Pos 6 /*!< UART IRCR: INV_RX Position */ +#define UART_IRCR_INV_RX_Msk (1ul << UART_IRCR_INV_RX_Pos) /*!< UART IRCR: INV_RX Mask */ + +#define UART_IRCR_INV_TX_Pos 5 /*!< UART IRCR: INV_TX Position */ +#define UART_IRCR_INV_TX_Msk (1ul << UART_IRCR_INV_TX_Pos) /*!< UART IRCR: INV_TX Mask */ + +#define UART_IRCR_TX_SELECT_Pos 1 /*!< UART IRCR: TX_SELECT Position */ +#define UART_IRCR_TX_SELECT_Msk (1ul << UART_IRCR_TX_SELECT_Pos) /*!< UART IRCR: TX_SELECT Mask */ + +/* UART ALT_CSR Bit Field Definitions */ +#define UART_ALT_CSR_ADDR_MATCH_Pos 24 /*!< UART ALT_CSR: ADDR_MATCH Position */ +#define UART_ALT_CSR_ADDR_MATCH_Msk (0xFFul << UART_ALT_CSR_ADDR_MATCH_Pos) /*!< UART ALT_CSR: ADDR_MATCH Mask */ + +#define UART_ALT_CSR_RS485_ADD_EN_Pos 15 /*!< UART ALT_CSR: RS485_ADD_EN Position */ +#define UART_ALT_CSR_RS485_ADD_EN_Msk (1ul << UART_ALT_CSR_RS485_ADD_EN_Pos) /*!< UART ALT_CSR: RS485_ADD_EN Mask */ + +#define UART_ALT_CSR_RS485_AUD_Pos 10 /*!< UART ALT_CSR: RS485_AUD Position */ +#define UART_ALT_CSR_RS485_AUD_Msk (1ul << UART_ALT_CSR_RS485_AUD_Pos) /*!< UART ALT_CSR: RS485_AUD Mask */ + +#define UART_ALT_CSR_RS485_AAD_Pos 9 /*!< UART ALT_CSR: RS485_AAD Position */ +#define UART_ALT_CSR_RS485_AAD_Msk (1ul << UART_ALT_CSR_RS485_AAD_Pos) /*!< UART ALT_CSR: RS485_AAD Mask */ + +#define UART_ALT_CSR_RS485_NMM_Pos 8 /*!< UART ALT_CSR: RS485_NMM Position */ +#define UART_ALT_CSR_RS485_NMM_Msk (1ul << UART_ALT_CSR_RS485_NMM_Pos) /*!< UART ALT_CSR: RS485_NMM Mask */ + +#define UART_ALT_CSR_LIN_TX_EN_Pos 7 /*!< UART ALT_CSR: LIN TX Break Mode Enable Position */ +#define UART_ALT_CSR_LIN_TX_EN_Msk (1ul << UART_ALT_CSR_LIN_TX_EN_Pos) /*!< UART ALT_CSR: LIN TX Break Mode Enable Mask */ + +#define UART_ALT_CSR_LIN_RX_EN_Pos 6 /*!< UART ALT_CSR: LIN RX Enable Position */ +#define UART_ALT_CSR_LIN_RX_EN_Msk (1ul << UART_ALT_CSR_LIN_RX_EN_Pos) /*!< UART ALT_CSR: LIN RX Enable Mask */ + +#define UART_ALT_CSR_UA_LIN_BKFL_Pos 0 /*!< UART ALT_CSR: UART LIN Break Field Length Position */ +#define UART_ALT_CSR_UA_LIN_BKFL_Msk (0xFul << UART_ALT_CSR_UA_LIN_BKFL_Pos) /*!< UART ALT_CSR: UART LIN Break Field Length Mask */ + +/* UART FUN_SEL Bit Field Definitions */ +#define UART_FUN_SEL_FUN_SEL_Pos 0 /*!< UART FUN_SEL: FUN_SEL Position */ +#define UART_FUN_SEL_FUN_SEL_Msk (0x3ul << UART_FUN_SEL_FUN_SEL_Pos) /*!< UART FUN_SEL: FUN_SEL Mask */ + +/* UART LIN_CTL Bit Field Definitions */ +#define UART_LIN_CTL_LIN_PID_Pos 24 /*!< UART LIN_CTL: LIN_PID Position */ +#define UART_LIN_CTL_LIN_PID_Msk (0xFFul << UART_LIN_CTL_LIN_PID_Pos) /*!< UART LIN_CTL: LIN_PID Mask */ + +#define UART_LIN_CTL_LIN_HEAD_SEL_Pos 22 /*!< UART LIN_CTL: LIN_HEAD_SEL Position */ +#define UART_LIN_CTL_LIN_HEAD_SEL_Msk (0x3ul << UART_LIN_CTL_LIN_HEAD_SEL_Pos) /*!< UART LIN_CTL: LIN_HEAD_SEL Mask */ + +#define UART_LIN_CTL_LIN_BS_LEN_Pos 20 /*!< UART LIN_CTL: LIN_BS_LEN Position */ +#define UART_LIN_CTL_LIN_BS_LEN_Msk (0x3ul << UART_LIN_CTL_LIN_BS_LEN_Pos) /*!< UART LIN_CTL: LIN_BS_LEN Mask */ + +#define UART_LIN_CTL_LIN_BKFL_Pos 16 /*!< UART LIN_CTL: LIN_BKFL Position */ +#define UART_LIN_CTL_LIN_BKFL_Msk (0xFul << UART_LIN_CTL_LIN_BKFL_Pos) /*!< UART LIN_CTL: LIN_BKFL Mask */ + +#define UART_LIN_CTL_BIT_ERR_EN_Pos 12 /*!< UART LIN_CTL: BIT_ERR_EN Position */ +#define UART_LIN_CTL_BIT_ERR_EN_Msk (1ul << UART_LIN_CTL_BIT_ERR_EN_Pos) /*!< UART LIN_CTL: BIT_ERR_EN Mask */ + +#define UART_LIN_CTL_LIN_RX_DIS_Pos 11 /*!< UART LIN_CTL: LIN_RX_DIS Position */ +#define UART_LIN_CTL_LIN_RX_DIS_Msk (1ul << UART_LIN_CTL_LIN_RX_DIS_Pos) /*!< UART LIN_CTL: LIN_RX_DIS Mask */ + +#define UART_LIN_CTL_LIN_BKDET_EN_Pos 10 /*!< UART LIN_CTL: LIN_BKDET_EN Position */ +#define UART_LIN_CTL_LIN_BKDET_EN_Msk (1ul << UART_LIN_CTL_LIN_BKDET_EN_Pos) /*!< UART LIN_CTL: LIN_BKDET_EN Mask */ + +#define UART_LIN_CTL_LIN_IDPEN_Pos 9 /*!< UART LIN_CTL: LIN_IDPEN Position */ +#define UART_LIN_CTL_LIN_IDPEN_Msk (1ul << UART_LIN_CTL_LIN_IDPEN_Pos) /*!< UART LIN_CTL: LIN_IDPEN Mask */ + +#define UART_LIN_CTL_LIN_SHD_Pos 8 /*!< UART LIN_CTL: LIN_SHD Position */ +#define UART_LIN_CTL_LIN_SHD_Msk (1ul << UART_LIN_CTL_LIN_SHD_Pos) /*!< UART LIN_CTL: LIN_SHD Mask */ + +#define UART_LIN_CTL_LIN_WAKE_EN_Pos 4 /*!< UART LIN_CTL: LIN_WAKE_EN Position */ +#define UART_LIN_CTL_LIN_WAKE_EN_Msk (1ul << UART_LIN_CTL_LIN_WAKE_EN_Pos) /*!< UART LIN_CTL: LIN_WAKE_EN Mask */ + +#define UART_LIN_CTL_LINS_DUM_EN_Pos 3 /*!< UART LIN_CTL: LINS_DUM_EN Position */ +#define UART_LIN_CTL_LINS_DUM_EN_Msk (1ul << UART_LIN_CTL_LINS_DUM_EN_Pos) /*!< UART LIN_CTL: LINS_DUM_EN Mask */ + +#define UART_LIN_CTL_LINS_ARS_EN_Pos 2 /*!< UART LIN_CTL: LINS_ARS_EN Position */ +#define UART_LIN_CTL_LINS_ARS_EN_Msk (1ul << UART_LIN_CTL_LINS_ARS_EN_Pos) /*!< UART LIN_CTL: LINS_ARS_EN Mask */ + +#define UART_LIN_CTL_LINS_HDET_EN_Pos 1 /*!< UART LIN_CTL: LINS_HDET_EN Position */ +#define UART_LIN_CTL_LINS_HDET_EN_Msk (1ul << UART_LIN_CTL_LINS_HDET_EN_Pos) /*!< UART LIN_CTL: LINS_HDET_EN Mask */ + +#define UART_LIN_CTL_LINS_EN_Pos 0 /*!< UART LIN_CTL: LINS_EN Position */ +#define UART_LIN_CTL_LINS_EN_Msk (1ul << UART_LIN_CTL_LINS_EN_Pos) /*!< UART LIN_CTL: LINS_EN Mask */ + +/* UART LIN_SR Bit Field Definitions */ +#define UART_LIN_SR_LINS_SYNC_F_Pos 3 /*!< UART LIN_SR: LINS_SYNC_F Position */ +#define UART_LIN_SR_LINS_SYNC_F_Msk (1ul << UART_LIN_SR_LINS_SYNC_F_Pos) /*!< UART LIN_SR: LINS_SYNC_F Mask */ + +#define UART_LIN_SR_LINS_IDPERR_F_Pos 2 /*!< UART LIN_SR: LINS_IDPERR_F Position */ +#define UART_LIN_SR_LINS_IDPERR_F_Msk (1ul << UART_LIN_SR_LINS_IDPERR_F_Pos) /*!< UART LIN_SR: LINS_IDPERR_F Mask */ + +#define UART_LIN_SR_LINS_HERR_F_Pos 1 /*!< UART LIN_SR: LINS_HERR_F Position */ +#define UART_LIN_SR_LINS_HERR_F_Msk (1ul << UART_LIN_SR_LINS_HERR_F_Pos) /*!< UART LIN_SR: LINS_HERR_F Mask */ + +#define UART_LIN_SR_LINS_HDET_F_Pos 0 /*!< UART LIN_SR: LINS_HDET_F Position */ +#define UART_LIN_SR_LINS_HDET_F_Msk (1ul << UART_LIN_SR_LINS_HDET_F_Pos) /*!< UART LIN_SR: LINS_HDET_F Mask */ + +/* UART DEBUG Bit Field Definitions */ +#define UART_DEBUG_ERR_DIVIA_F_Pos 0 /*!< UART DEBUG: ERR_DIVIA_F Position */ +#define UART_DEBUG_ERR_DIVIA_F_Msk (1ul << UART_DEBUG_ERR_DIVIA_F_Pos) /*!< UART DEBUG: ERR_DIVIA_F Mask */ + +#define UART_DEBUG_ERR_HETIME_OUT_F_Pos 1 /*!< UART DEBUG: ERR_HETIME_OUT_F Position */ +#define UART_DEBUG_ERR_HETIME_OUT_F_Msk (1ul << UART_DEBUG_ERR_HETIME_OUT_F_Pos) /*!< UART DEBUG: ERR_HETIME_OUT_F Mask */ + +#define UART_DEBUG_ERR_HEFE_F_Pos 2 /*!< UART DEBUG: ERR_HEFE_F Position */ +#define UART_DEBUG_ERR_HEFE_F_Msk (1ul << UART_DEBUG_ERR_HEFE_F_Pos) /*!< UART DEBUG: ERR_HEFE_F Mask */ + +#define UART_DEBUG_ERR_SYNC_F_Pos 3 /*!< UART DEBUG: ERR_SYNC_F Position */ +#define UART_DEBUG_ERR_SYNC_F_Msk (1ul << UART_DEBUG_ERR_SYNC_F_Pos) /*!< UART DEBUG: ERR_SYNC_F Mask */ + +/* UART SC_CTL Bit Field Definitions */ +#define UART_SC_CTL_RX_ERETRY_Pos 0 /*!< UART SC_CTL: RX_ERETRY Position */ +#define UART_SC_CTL_RX_ERETRY_Msk (7ul << UART_SC_CTL_RX_ERETRY_Pos) /*!< UART SC_CTL: RX_ERETRY Mask */ + +#define UART_SC_CTL_RX_ERETRY_EN_Pos 3 /*!< UART SC_CTL: RX_ERETRY_EN Position */ +#define UART_SC_CTL_RX_ERETRY_EN_Msk (1ul << UART_SC_CTL_RX_ERETRY_EN_Pos) /*!< UART SC_CTL: RX_ERETRY_EN Mask */ + +#define UART_SC_CTL_TX_ERETRY_Pos 4 /*!< UART SC_CTL: TX_ERETRY Position */ +#define UART_SC_CTL_TX_ERETRY_Msk (7ul << UART_SC_CTL_TX_ERETRY_Pos) /*!< UART SC_CTL: TX_ERETRY Mask */ + +#define UART_SC_CTL_TX_ERETRY_EN_Pos 7 /*!< UART SC_CTL: TX_ERETRY_EN Position */ +#define UART_SC_CTL_TX_ERETRY_EN_Msk (1ul << UART_SC_CTL_TX_ERETRY_EN_Pos) /*!< UART SC_CTL: TX_ERETRY_EN Mask */ + +/* UART SC_FSR Bit Field Definitions */ +#define UART_SC_FSR_RX_OVER_ERETRY_Pos 0 /*!< UART SC_FSR: RX_OVER_ERETRY Position */ +#define UART_SC_FSR_RX_OVER_ERETRY_Msk (1ul << UART_SC_FSR_RX_OVER_ERETRY_Pos) /*!< UART SC_FSR: RX_OVER_ERETRY Mask */ + +#define UART_SC_FSR_TX_OVER_ERETRY_Pos 1 /*!< UART SC_FSR: TX_OVER_ERETRY Position */ +#define UART_SC_FSR_TX_OVER_ERETRY_Msk (1ul << UART_SC_FSR_TX_OVER_ERETRY_Pos) /*!< UART SC_FSR: TX_OVER_ERETRY Mask */ + +#define UART_SC_FSR_RX_ERETRY_F_Pos 8 /*!< UART SC_FSR: RX_ERETRY_F Position */ +#define UART_SC_FSR_RX_ERETRY_F_Msk (1ul << UART_SC_FSR_RX_ERETRY_F_Pos) /*!< UART SC_FSR: RX_ERETRY_F Mask */ + +#define UART_SC_FSR_TX_ERETRY_F_Pos 9 /*!< UART SC_FSR: TX_ERETRY_F Position */ +#define UART_SC_FSR_TX_ERETRY_F_Msk (1ul << UART_SC_FSR_TX_ERETRY_F_Pos) /*!< UART SC_FSR: TX_ERETRY_F Mask */ + +/* Enable/Disable IrDA Mode */ +#define ENABLEIrDA 1 /*!< Enable IrDA */ +#define DISABLEIrDA 0 /*!< Disable IrDA */ + +/* define IrDA Direction */ +#define IrDA_TX 0 /*!< Set IrDA Tx direction*/ +#define IrDA_RX 1 /*!< Set IrDA Rx direction*/ + +/* define RTS signal */ +#define UART_RTS_HIGH 1 /*!< Set RTS high*/ +#define UART_RTS_LOW 0 /*!< Set RTS low*/ + +/* define IOCTL command of UART operation mode, interrupt or pooling mode */ +#define UART_IOC_SETTXMODE 1 /*!< Set Tx Mode */ +#define UART_IOC_SETRXMODE 2 /*!< Set Tx Mode */ +#define UART_IOC_GETRECCHARINFO 3 /*!< Get receive character */ +#define UART_IOC_SETUARTPARAMETER 4 /*!< Config UART */ +//#define UART_IOC_PERFORMBLUETOOTH 5 +#define UART_IOC_PERFORMIrDA 6 /*!< Config IrDA */ +#define UART_IOC_GETUARTREGISTERVALUE 7 /*!< Get UART register value*/ +#define UART_IOC_GETERRNO 8 /*!< Get rrror code */ +//#define UART_IOC_SETMODEMLOOPBACK 9 +//#define UART_IOC_GETDSRSTATE 10 +//#define UART_IOC_SETDTRSIGNAL 11 +#define UART_IOC_SETINTERRUPT 12 /*!< Set interrupt */ +#define UART_IOC_SETBREAKCONTROL 13 /*!< Set break */ +#define UART_IOC_GETBIISTATE 14 /*!< Get break status */ +#define UART_IOC_GETCTSSTATE 15 /*!< Get CTS status */ +#define UART_IOC_SETRTSSIGNAL 16 /*!< Set RTS signal */ +#define UART_IOC_SETMODEMINTERRUPT 17 /*!< Set modem interrupt */ +#define UART_IOC_ENABLEHWFLOWCONTROL 18 /*!< Enable H/W flow control */ +#define UART_IOC_DISABLEHWFLOWCONTROL 19 /*!< Disable H/W flow control */ +//#define UART_IOC_ENABLESWFLOWCONTROL 20 /*!< Enable S/W flow control */ +//#define UART_IOC_DISABLESWFLOWCONTROL 21 /*!< Disable S/W flow control */ +//#define UART_IOC_SETUART1FULLMODEM 22 +//#define UART_IOC_SETUART1HIGHSPEED 23 + +#define UART_IOC_FLUSH_TX_BUFFER 24 /*!< Flush Tx buffer */ +#define UART_IOC_FLUSH_RX_BUFFER 25 /*!< Flus Rx buffer */ + +#define UART_IOC_SET_RS485_MODE 26 /*!< Select RS485 Mode */ +#define UART_IOC_SEND_RS485_ADDRESS 27 /*!< Send RS485 Address*/ +#define UART_IOC_SET_RS485_RXOFF 28 /*!< Select RS485 Mode */ +#define UART_IOC_SET_ALTCTL_REG 29 /*!< Set ALT_CTL register */ +#define UART_IOC_GET_ALTCTL_REG 30 /*!< Get ALT_CTL register */ + +#define UART_IOC_SET_LIN_MODE 31 /*!< Select LIN Mode */ + + +/* Enable/Disable Modem interrupt */ +#define UART_ENABLE_MODEM_INT 0 /*!< Enable Modem interrupt */ +#define UART_DISABLE_MODEM_INT 1 /*!< Disable Modem interrupt */ + +/* These error code can get from UART_IOC_GETERRNO */ +#define UART_ERR_PARITY_INVALID -1 /*!< Parity invalid */ +#define UART_ERR_DATA_BITS_INVALID -2 /*!< Data bits invalid */ +#define UART_ERR_STOP_BITS_INVALID -3 /*!< Stop bit invalid */ +#define UART_ERR_TRIGGERLEVEL_INVALID -4 /*!< Trigger level invalid */ +#define UART_ERR_CHANNEL_INVALID -5 /*!< UART channel invalid */ +#define UART_ERR_ALLOC_MEMORY_FAIL -6 /*!< Allocate memory error */ +//#define UART_ERR_CLOCK_SOURCE_INVALID -7 /*!< Clock Source invalid */ +//#define UART_ERR_BAUDRATE_INVALID -8 /*!< Baudrate invalid */ +//#define UART_ERR_CONFIGURE_BT_FAIL -9 +#define UART_ERR_IrDA_COMMAND_INVALID -10 /*!< IrDA mode invalid */ +#define UART_ERR_TX_BUF_NOT_ENOUGH -11 /*!< Tx buffer not enough */ +#define UART_ERR_OPERATE_MODE_INVALID -12 /*!< Operation mode invalid */ +#define UART_ERR_SET_BAUDRATE_FAIL -13 /*!< Set baudrate fail */ + +/* These are the error code actually returns to user application */ +#define UART_ERR_ID 0xFFFF1700 /*!< UART library ID */ +#define UART_ENOTTY (1 | UART_ERR_ID) /*!< Command not support */ +#define UART_ENODEV (2 | UART_ERR_ID) /*!< Interface number out of range */ +#define UART_EIO (3 | UART_ERR_ID) /*!< Read/Write error */ + +/*@}*/ /* end of group N9H30_UART_EXPORTED_CONSTANTS */ + + +/** @addtogroup N9H30_UART_EXPORTED_STRUCTS UART Exported Structs + @{ +*/ + +/// @cond HIDDEN_SYMBOLS +/*----------------------------------------------------*/ +/* Define UART buffer structure */ +/*----------------------------------------------------*/ +typedef struct UART_BUFFER_STRUCT +{ + UINT32 volatile uUartTxHead, uUartTxTail; + UINT32 volatile uUartRxHead, uUartRxTail; + + PUINT8 pucUartTxBuf; + PUINT8 pucUartRxBuf; + PVOID pvUartVector; + BOOL bIsUseUARTTxInt; + BOOL bIsUseUARTRxInt; + BOOL bIsUARTInitial; + + PINT pucUARTFlag; + PINT pucLINFlag; + INT32 volatile nErrno; + +} UART_BUFFER_T; +/// @endcond HIDDEN_SYMBOLS + +/** \brief Structure type of UART data + */ +#if 0 +#define UART0 0 /*!< UART0 channel */ +#define UART1 1 /*!< UART1 channel */ +#define UART2 2 /*!< UART2 channel */ +#define UART3 3 /*!< UART3 channel */ +#define UART4 4 /*!< UART4 channel */ +#define UART5 5 /*!< UART5 channel */ +#define UART6 6 /*!< UART6 channel */ +#define UART7 7 /*!< UART7 channel */ +#define UART8 8 /*!< UART8 channel */ +#define UART9 9 /*!< UART9 channel */ +#define UARTA 10 /*!< UARTA channel */ + +typedef struct UART_STRUCT +{ + UINT32 uFreq; /*!< UART clock frequency */ + UINT32 uBaudRate; /*!< Baudrate */ + UINT8 ucUartNo; /*!< UART Port */ + UINT8 ucDataBits; /*!< Select Data length */ + UINT8 ucStopBits; /*!< Select stop bit length */ + UINT8 ucParity; /*!< Select Parity */ + UINT8 ucRxTriggerLevel; /*!< Select Rx FIFO trigger level */ +} UART_T; +#else + +typedef struct +{ + __IO uint32_t DAT; /*!< [0x0000] UART Receive/Transmit Buffer Register */ + __IO uint32_t INTEN; /*!< [0x0004] UART Interrupt Enable Register */ + __IO uint32_t FIFO; /*!< [0x0008] UART FIFO Control Register */ + __IO uint32_t LINE; /*!< [0x000c] UART Line Control Register */ + __IO uint32_t MODEM; /*!< [0x0010] UART Modem Control Register */ + __IO uint32_t MODEMSTS; /*!< [0x0014] UART Modem Status Register */ + __IO uint32_t FIFOSTS; /*!< [0x0018] UART FIFO Status Register */ + __IO uint32_t INTSTS; /*!< [0x001c] UART Interrupt Status Register */ + __IO uint32_t TOUT; /*!< [0x0020] UART Time-out Register */ + __IO uint32_t BAUD; /*!< [0x0024] UART Baud Rate Divider Register */ + __IO uint32_t IRDA; /*!< [0x0028] UART IrDA Control Register */ + __IO uint32_t ALTCTL; /*!< [0x002c] UART Alternate Control/Status Register */ + __IO uint32_t FUNCSEL; /*!< [0x0030] UART Function Select Register */ + __IO uint32_t LINCTL; /*!< [0x0034] UART LIN Control Register */ + __IO uint32_t LINSTS; /*!< [0x0038] UART LIN Status Register */ +} UART_T; + +#define UART0 ((UART_T *) UART0_BA) /*!< UART0 channel */ +#define UART1 ((UART_T *) UART1_BA) /*!< UART1 channel */ +#define UART2 ((UART_T *) UART2_BA) /*!< UART2 channel */ +#define UART3 ((UART_T *) UART3_BA) /*!< UART3 channel */ +#define UART4 ((UART_T *) UART4_BA) /*!< UART4 channel */ +#define UART5 ((UART_T *) UART5_BA) /*!< UART5 channel */ +#define UART6 ((UART_T *) UART6_BA) /*!< UART6 channel */ +#define UART7 ((UART_T *) UART7_BA) /*!< UART7 channel */ +#define UART8 ((UART_T *) UART8_BA) /*!< UART8 channel */ +#define UART9 ((UART_T *) UART9_BA) /*!< UART9 channel */ +#define UARTA ((UART_T *) UARTA_BA) /*!< UARTA channel */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART_FUNCSEL constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_FIFO_RFITL_Pos (4) /*!< UART_T::FIFO: RFITL Position */ +#define UART_FIFO_RFITL_Msk (0xful << UART_FIFO_RFITL_Pos) /*!< UART_T::FIFO: RFITL Mask */ + +#define UART_FIFO_RTSTRGLV_Pos (16) /*!< UART_T::FIFO: RTSTRGLV Position */ +#define UART_FIFO_RTSTRGLV_Msk (0xful << UART_FIFO_RTSTRGLV_Pos) /*!< UART_T::FIFO: RTSTRGLV Mask */ + +#define UART_FUNCSEL_FUNCSEL_Pos (0) /*!< UART_T::FUNCSEL: FUNCSEL Position */ +#define UART_FUNCSEL_FUNCSEL_Msk (0x3ul << UART_FUNCSEL_FUNCSEL_Pos) /*!< UART_T::FUNCSEL: FUNCSEL Mask */ + +#define UART_FUNCSEL_UART (0x0ul << UART_FUNCSEL_FUNCSEL_Pos) /*!< UART_FUNCSEL setting to set UART Function (Default) \hideinitializer */ +#define UART_FUNCSEL_LIN (0x1ul << UART_FUNCSEL_FUNCSEL_Pos) /*!< UART_FUNCSEL setting to set LIN Function \hideinitializer */ +#define UART_FUNCSEL_IrDA (0x2ul << UART_FUNCSEL_FUNCSEL_Pos) /*!< UART_FUNCSEL setting to set IrDA Function \hideinitializer */ +#define UART_FUNCSEL_RS485 (0x3ul << UART_FUNCSEL_FUNCSEL_Pos) /*!< UART_FUNCSEL setting to set RS485 Function \hideinitializer */ + +#endif + +/** \brief Structure type of UART register + */ +typedef struct UART_REGISTER_STRUCT +{ + UINT32 uUartReg[14][2]; /*!< Store UART register value */ +} UART_REGISTER_T; + +/*@}*/ /* end of group N9H30_UART_EXPORTED_STRUCTS */ + + +/** @addtogroup N9H30_UART_EXPORTED_FUNCTIONS UART Exported Functions + @{ +*/ + +/** + * @brief Calculate UART baudrate mode0 divider + * + * @param[in] u32SrcFreq UART clock frequency + * @param[in] u32BaudRate Baudrate of UART module + * + * @return UART baudrate mode0 divider + * \hideinitializer + * + */ +#define UART_BAUD_MODE0_DIVIDER(u32SrcFreq, u32BaudRate) (((u32SrcFreq + (u32BaudRate*8)) / u32BaudRate >> 4)-2) + +/** + * @brief Calculate UART baudrate mode2 divider + * + * @param[in] u32SrcFreq UART clock frequency + * @param[in] u32BaudRate Baudrate of UART module + * + * @return UART baudrate mode2 divider + * \hideinitializer + */ +#define UART_BAUD_MODE2_DIVIDER(u32SrcFreq, u32BaudRate) (((u32SrcFreq + (u32BaudRate/2)) / u32BaudRate)-2) + + +/** + * @brief Get Rx empty + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 0 Rx FIFO is not empty + * @retval >=1 Rx FIFO is empty + * + * @details This macro get Receiver FIFO empty register value. + * \hideinitializer + */ +#define UART_GET_RX_EMPTY(uart) ((uart)->FIFOSTS & UART_FSR_RX_EMPTY_Msk) + +/** + * @brief Check TX FIFO is full or not + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 1 TX FIFO is full + * @retval 0 TX FIFO is not full + * + * @details This macro check TX FIFO is full or not. + * \hideinitializer + */ +#define UART_IS_TX_FULL(uart) (((uart)->FIFOSTS & UART_FSR_TX_FULL_Msk)>>UART_FSR_TX_FULL_Pos) + +/** + * @brief Write UART data + * + * @param[in] uart The pointer of the specified UART module + * @param[in] u8Data Data byte to transmit. + * + * @return None + * + * @details This macro write Data to Tx data register. + * \hideinitializer + */ +#define UART_WRITE(uart, u8Data) ((uart)->DAT = (u8Data)) + +/** + * @brief Read UART data + * + * @param[in] uart The pointer of the specified UART module + * + * @return The oldest data byte in RX FIFO. + * + * @details This macro read Rx data register. + * \hideinitializer + */ +#define UART_READ(uart) ((uart)->DAT) + +#define UART_ENABLE_INT(uart, u32eIntSel) ((uart)->INTEN |= (u32eIntSel)) +#define UART_DISABLE_INT(uart, u32eIntSel) ((uart)->INTEN &= ~ (u32eIntSel)) + +/*-----------------------------------------*/ +/* interface function declarations */ +/*-----------------------------------------*/ +INT uartOpen(PVOID param); +INT uartInit(void); +INT uartIoctl(INT nNum, UINT32 uCom, UINT32 uArg0, UINT32 uArg1); +INT32 uartRelease(INT nNum); +INT32 uartWrite(INT nNum, PUINT8 pucBuf, UINT32 uLen); +INT32 uartRead(INT nNum, PUINT8 pucBuf, UINT32 uLen); + + +void UART_Open(UART_T *uart, uint32_t u32baudrate); +void UART_Close(UART_T *uart); +void UART_SetLineConfig(UART_T *uart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits); +/*@}*/ /* end of group N9H30_UART_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_UART_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +#endif diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_usbd.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_usbd.h new file mode 100644 index 0000000000..5f8719b45d --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_usbd.h @@ -0,0 +1,937 @@ +/**************************************************************************//** + * @file usbd.h + * @brief N9H30 USBD driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_USBD_H__ +#define __NU_USBD_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_USBD_Driver USBD Driver + @{ +*/ + +/** @addtogroup N9H30_USBD_EXPORTED_CONSTANTS USBD Exported Constants + @{ +*/ +/// @cond HIDDEN_SYMBOLS +#define USBD_MAX_EP 12 + +#define Maximum(a,b) (a)>(b) ? (a) : (b) +#define Minimum(a,b) (a)<(b) ? (a) : (b) + + +#define CEP 0xff /*!< Control Endpoint \hideinitializer */ +#define EPA 0 /*!< Endpoint A \hideinitializer */ +#define EPB 1 /*!< Endpoint B \hideinitializer */ +#define EPC 2 /*!< Endpoint C \hideinitializer */ +#define EPD 3 /*!< Endpoint D \hideinitializer */ +#define EPE 4 /*!< Endpoint E \hideinitializer */ +#define EPF 5 /*!< Endpoint F \hideinitializer */ +#define EPG 6 /*!< Endpoint G \hideinitializer */ +#define EPH 7 /*!< Endpoint H \hideinitializer */ +#define EPI 8 /*!< Endpoint I \hideinitializer */ +#define EPJ 9 /*!< Endpoint J \hideinitializer */ +#define EPK 10 /*!< Endpoint K \hideinitializer */ +#define EPL 11 /*!< Endpoint L \hideinitializer */ + +/* USB Request Type */ +#define REQ_STANDARD 0x00 +#define REQ_CLASS 0x20 +#define REQ_VENDOR 0x40 + +/* USB Standard Request */ +#define GET_STATUS 0x00 +#define CLEAR_FEATURE 0x01 +#define SET_FEATURE 0x03 +#define SET_ADDRESS 0x05 +#define GET_DESCRIPTOR 0x06 +#define SET_DESCRIPTOR 0x07 +#define GET_CONFIGURATION 0x08 +#define SET_CONFIGURATION 0x09 +#define GET_INTERFACE 0x0A +#define SET_INTERFACE 0x0B +#define SYNC_FRAME 0x0C + +/* USB Descriptor Type */ +#define DESC_DEVICE 0x01 +#define DESC_CONFIG 0x02 +#define DESC_STRING 0x03 +#define DESC_INTERFACE 0x04 +#define DESC_ENDPOINT 0x05 +#define DESC_QUALIFIER 0x06 +#define DESC_OTHERSPEED 0x07 +#define DESC_IFPOWER 0x08 +#define DESC_OTG 0x09 + +/* USB HID Descriptor Type */ +#define DESC_HID 0x21 +#define DESC_HID_RPT 0x22 + +/* USB Descriptor Length */ +#define LEN_DEVICE 18 +#define LEN_QUALIFIER 10 +#define LEN_CONFIG 9 +#define LEN_INTERFACE 9 +#define LEN_ENDPOINT 7 +#define LEN_OTG 5 +#define LEN_HID 9 + +/* USB Endpoint Type */ +#define EP_ISO 0x01 +#define EP_BULK 0x02 +#define EP_INT 0x03 + +#define EP_INPUT 0x80 +#define EP_OUTPUT 0x00 + +/* USB Feature Selector */ +#define FEATURE_DEVICE_REMOTE_WAKEUP 0x01 +#define FEATURE_ENDPOINT_HALT 0x00 +/// @endcond HIDDEN_SYMBOLS +/********************* Bit definition of CEPCTL register **********************/ +#define USB_CEPCTL_NAKCLR ((uint32_t)0x00000000) /*!PHYCTL |= (USBD_PHYCTL_PHYEN_Msk|USBD_PHYCTL_DPPUEN_Msk))) /*!PHYCTL &= ~USBD_PHYCTL_DPPUEN_Msk)) /*!PHYCTL |= USBD_PHYCTL_PHYEN_Msk)) /*!PHYCTL &= ~USBD_PHYCTL_PHYEN_Msk)) /*!PHYCTL &= ~USBD_PHYCTL_DPPUEN_Msk)) /*!PHYCTL |= USBD_PHYCTL_DPPUEN_Msk)) /*!FADDR = (addr)) /*!FADDR)) /*!GINTEN = (intr)) /*!BUSINTEN = (intr)) /*!BUSINTSTS) /*!BUSINTSTS = flag) /*!CEPINTEN = (intr)) /*!CEPINTSTS = flag) /*!CEPCTL = flag) /*!CEPTXCNT = size) /*!EP[ep].EPMPS = (size)) /*!EP[ep].EPINTEN = (intr)) /*!EP[ep].EPINTSTS) /*!EP[ep].EPINTSTS = (flag)) /*!DMACNT = len) /*!DMAADDR = addr) /*!DMACTL = (USBD->DMACTL & ~USBD_DMACTL_EPNUM_Msk) | USBD_DMACTL_DMARD_Msk | epnum) /*!DMACTL = (USBD->DMACTL & ~(USBD_DMACTL_EPNUM_Msk | USBD_DMACTL_DMARD_Msk)) | epnum) /*!DMACTL |= USBD_DMACTL_DMAEN_Msk) /*!PHYCTL & USBD_PHYCTL_VBUSDET_Msk)) /*!DMACNT = 0; + USBD->DMACTL = 0x80; + USBD->DMACTL = 0x00; +} +/** + * @brief USBD_SetEpBufAddr, Set Endpoint buffer address + * @param[in] u32Ep Endpoint Number + * @param[in] u32Base Buffer Start Address + * @param[in] u32Len Buffer length + * @retval None. + */ +static __inline void USBD_SetEpBufAddr(uint32_t u32Ep, uint32_t u32Base, uint32_t u32Len) +{ + if (u32Ep == CEP) + { + USBD->CEPBUFSTART = u32Base; + USBD->CEPBUFEND = u32Base + u32Len - 1; + } + else + { + USBD->EP[u32Ep].EPBUFSTART = u32Base; + USBD->EP[u32Ep].EPBUFEND = u32Base + u32Len - 1; + } +} + +/** + * @brief USBD_ConfigEp, Config Endpoint + * @param[in] u32Ep USB endpoint + * @param[in] u32EpNum Endpoint number + * @param[in] u32EpType Endpoint type + * @param[in] u32EpDir Endpoint direction + * @retval None. + */ +static __inline void USBD_ConfigEp(uint32_t u32Ep, uint32_t u32EpNum, uint32_t u32EpType, uint32_t u32EpDir) +{ + if (u32EpType == USB_EP_CFG_TYPE_BULK) + USBD->EP[u32Ep].EPRSPCTL = (USB_EP_RSPCTL_FLUSH | USB_EP_RSPCTL_MODE_AUTO); + else if (u32EpType == USB_EP_CFG_TYPE_INT) + USBD->EP[u32Ep].EPRSPCTL = (USB_EP_RSPCTL_FLUSH | USB_EP_RSPCTL_MODE_MANUAL); + else if (u32EpType == USB_EP_CFG_TYPE_ISO) + USBD->EP[u32Ep].EPRSPCTL = (USB_EP_RSPCTL_FLUSH | USB_EP_RSPCTL_MODE_FLY); + + USBD->EP[u32Ep].EPCFG = (u32EpType | u32EpDir | USB_EP_CFG_VALID | (u32EpNum << 4)); +} + +/** + * @brief Set USB endpoint stall state + * @param[in] u32Ep The USB endpoint ID. + * @return None + * @details Set USB endpoint stall state for the specified endpoint ID. Endpoint will respond STALL token automatically. + */ +static __inline void USBD_SetEpStall(uint32_t u32Ep) +{ + if (u32Ep == CEP) + USBD_SET_CEP_STATE(USB_CEPCTL_STALL); + else + { + USBD->EP[u32Ep].EPRSPCTL = USBD->EP[u32Ep].EPRSPCTL & 0xf7 | USB_EP_RSPCTL_HALT; + } +} + +/** + * @brief Set USB endpoint stall state + * + * @param[in] u32EpNum USB endpoint + * @return None + * + * @details Set USB endpoint stall state, endpoint will return STALL token. + */ +static __inline void USBD_SetStall(uint32_t u32EpNum) +{ + int i; + + if (u32EpNum == 0) + USBD_SET_CEP_STATE(USB_CEPCTL_STALL); + else + { + for (i = 0; i < USBD_MAX_EP; i++) + { + if (((USBD->EP[i].EPCFG & 0xf0) >> 4) == u32EpNum) + { + USBD->EP[i].EPRSPCTL = USBD->EP[i].EPRSPCTL & 0xf7 | USB_EP_RSPCTL_HALT; + } + } + } +} + +/** + * @brief Clear USB endpoint stall state + * @param[in] u32Ep The USB endpoint ID. + * @return None + * @details Clear USB endpoint stall state for the specified endpoint ID. Endpoint will respond ACK/NAK token. + */ +static __inline void USBD_ClearEpStall(uint32_t u32Ep) +{ + USBD->EP[u32Ep].EPRSPCTL = USB_EP_RSPCTL_TOGGLE; +} + +/** + * @brief Clear USB endpoint stall state + * + * @param[in] u32EpNum USB endpoint + * @return None + * + * @details Clear USB endpoint stall state, endpoint will return ACK/NAK token. + */ +static __inline void USBD_ClearStall(uint32_t u32EpNum) +{ + int i; + + for (i = 0; i < USBD_MAX_EP; i++) + { + if (((USBD->EP[i].EPCFG & 0xf0) >> 4) == u32EpNum) + { + USBD->EP[i].EPRSPCTL = USB_EP_RSPCTL_TOGGLE; + } + } +} + +/** + * @brief Get USB endpoint stall state + * @param[in] u32Ep The USB endpoint ID. + * @retval 0 USB endpoint is not stalled. + * @retval Others USB endpoint is stalled. + * @details Get USB endpoint stall state of the specified endpoint ID. + */ +static __inline uint32_t USBD_GetEpStall(uint32_t u32Ep) +{ + return (USBD->EP[u32Ep].EPRSPCTL & USB_EP_RSPCTL_HALT); +} + +/** + * @brief Get USB endpoint stall state + * + * @param[in] u32EpNum USB endpoint + * @retval 0: USB endpoint is not stalled. + * @retval non-0: USB endpoint is stalled. + * + * @details Get USB endpoint stall state. + */ +static __inline uint32_t USBD_GetStall(uint32_t u32EpNum) +{ + int i; + + for (i = 0; i < USBD_MAX_EP; i++) + { + if (((USBD->EP[i].EPCFG & 0xf0) >> 4) == u32EpNum) + { + return (USBD->EP[i].EPRSPCTL & USB_EP_RSPCTL_HALT); + } + } + return 0; +} + + +/*-------------------------------------------------------------------------------------------*/ +typedef void (*VENDOR_REQ)(void); /*!CON & (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); + tCAN->CON = tCAN->CON & ~(CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); + + /* Check interface 1 is available or not */ + if ((tCAN->IF[0ul].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0ul) + { + if (gu8LockCanIf[u32CanNo][0ul] == 0ul) + { + gu8LockCanIf[u32CanNo][0ul] = 1u; + u32FreeIfNo = 0ul; + } + else + { + } + } + else + { + } + + /* Or check interface 2 is available or not */ + if (u32FreeIfNo == 2ul) + { + if ((tCAN->IF[1ul].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0ul) + { + if (gu8LockCanIf[u32CanNo][1ul] == 0ul) + { + gu8LockCanIf[u32CanNo][1ul] = 1u; + u32FreeIfNo = 1ul; + } + else + { + } + } + else + { + } + } + else + { + } + + /* Enable CAN interrupt */ + tCAN->CON |= u32IntMask; + + return u32FreeIfNo; +} + +/** + * @brief Check if any interface is available in a time limitation then lock it for usage. + * @param[in] tCAN The pointer to CAN module base address. + * @retval 0 IF0 is free + * @retval 1 IF1 is free + * @retval 2 No IF is free + * @details Search the first free message interface, starting from 0. If no interface is + * it will try again until time out. If a interface is available, set a flag to + * lock the interface. + */ +static uint32_t LockIF_TL(CAN_T *tCAN) +{ + uint32_t u32Count; + uint32_t u32FreeIfNo; + + for (u32Count = 0ul; u32Count < RETRY_COUNTS; u32Count++) + { + if ((u32FreeIfNo = LockIF(tCAN)) != 2ul) + { + break; + } + else + { + } + } + + return u32FreeIfNo; +} + +/** + * @brief Release locked interface. + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32Info The interface number, 0 or 1. + * @return none + * @details Release the locked interface. + */ +static void ReleaseIF(CAN_T *tCAN, uint32_t u32IfNo) +{ + uint32_t u32IntMask; + uint32_t u32CanNo; + + if (u32IfNo >= 2ul) + { + } + else + { + if (tCAN == CAN0) + u32CanNo = 0ul; +#if defined(CAN1) + else if (tCAN == CAN1) + u32CanNo = 1ul; +#endif +#if defined(CAN2) + else if (tCAN == CAN2) + u32CanNo = 2ul; +#endif +#if defined(CAN3) + else if (tCAN == CAN3) + u32CanNo = 3ul; +#endif + else + return ; + + + /* Disable CAN interrupt */ + u32IntMask = tCAN->CON & (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); + tCAN->CON = tCAN->CON & ~(CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); + + gu8LockCanIf[u32CanNo][u32IfNo] = 0u; + + /* Enable CAN interrupt */ + tCAN->CON |= u32IntMask; + } +} + +static int can_update_spt(int sampl_pt, int tseg, int *tseg1, int *tseg2) +{ + *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000; + if (*tseg2 < TSEG2_MIN) + { + *tseg2 = TSEG2_MIN; + } + else + { + } + + if (*tseg2 > TSEG2_MAX) + { + *tseg2 = TSEG2_MAX; + } + else + { + } + + *tseg1 = tseg - *tseg2; + if (*tseg1 > TSEG1_MAX) + { + *tseg1 = TSEG1_MAX; + *tseg2 = tseg - *tseg1; + } + else + { + } + + return 1000 * (tseg + 1 - *tseg2) / (tseg + 1); +} + +/** @endcond HIDDEN_SYMBOLS */ + +/** + * @brief Enter initialization mode + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u8Mask Following values can be used. + * \ref CAN_CON_DAR_Msk Disable automatic retransmission. + * \ref CAN_CON_EIE_Msk Enable error interrupt. + * \ref CAN_CON_SIE_Msk Enable status interrupt. + * \ref CAN_CON_IE_Msk CAN interrupt. + * @return None + * @details This function is used to set CAN to enter initialization mode and enable access bit timing + * register. After bit timing configuration ready, user must call CAN_LeaveInitMode() + * to leave initialization mode and lock bit timing register to let new configuration + * take effect. + */ +void CAN_EnterInitMode(CAN_T *tCAN, uint8_t u8Mask) +{ + tCAN->CON = u8Mask | (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); +} + + +/** + * @brief Leave initialization mode + * @param[in] tCAN The pointer to CAN module base address. + * @return None + * @details This function is used to set CAN to leave initialization mode to let + * bit timing configuration take effect after configuration ready. + */ +void CAN_LeaveInitMode(CAN_T *tCAN) +{ + tCAN->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk)); + while (tCAN->CON & CAN_CON_INIT_Msk) + { + /* Check INIT bit is released */ + } +} + +/** + * @brief Wait message into message buffer in basic mode. + * @param[in] tCAN The pointer to CAN module base address. + * @return None + * @details This function is used to wait message into message buffer in basic mode. Please notice the + * function is polling NEWDAT bit of MCON register by while loop and it is used in basic mode. + */ +void CAN_WaitMsg(CAN_T *tCAN) +{ + tCAN->STATUS = 0x0ul; /* clr status */ + + while (1) + { + if (tCAN->IF[1].MCON & CAN_IF_MCON_NEWDAT_Msk) /* check new data */ + { + /* New Data IN */ + break; + } + else + { + } + + if (tCAN->STATUS & CAN_STATUS_RXOK_Msk) + { + /* Rx OK */ + } + else + { + } + + if (tCAN->STATUS & CAN_STATUS_LEC_Msk) + { + /* Error */ + } + else + { + } + } +} + +/** + * @brief Get current bit rate + * @param[in] tCAN The pointer to CAN module base address. + * @return Current Bit-Rate (kilo bit per second) + * @details Return current CAN bit rate according to the user bit-timing parameter settings + */ +uint32_t CAN_GetCANBitRate(CAN_T *tCAN) +{ + uint32_t u32Tseg1, u32Tseg2; + uint32_t u32Bpr; + + u32Tseg1 = (tCAN->BTIME & CAN_BTIME_TSEG1_Msk) >> CAN_BTIME_TSEG1_Pos; + u32Tseg2 = (tCAN->BTIME & CAN_BTIME_TSEG2_Msk) >> CAN_BTIME_TSEG2_Pos; + u32Bpr = (tCAN->BTIME & CAN_BTIME_BRP_Msk) | (tCAN->BRPE << 6ul); + + return (CAN_Clock / (u32Bpr + 1ul) / (u32Tseg1 + u32Tseg2 + 3ul)); +} + +/** + * @brief Switch the CAN into test mode. + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u8TestMask Specifies the configuration in test modes + * \ref CAN_TEST_BASIC_Msk Enable basic mode of test mode + * \ref CAN_TEST_SILENT_Msk Enable silent mode of test mode + * \ref CAN_TEST_LBACK_Msk Enable Loop Back Mode of test mode + * \ref CAN_TEST_Tx_Msk Control CAN_TX pin bit field + * @return None + * @details Switch the CAN into test mode. There are four test mode (BASIC/SILENT/LOOPBACK/ + * LOOPBACK combined SILENT/CONTROL_TX_PIN)could be selected. After setting test mode,user + * must call CAN_LeaveInitMode() to let the setting take effect. + */ +void CAN_EnterTestMode(CAN_T *tCAN, uint8_t u8TestMask) +{ + tCAN->CON |= CAN_CON_TEST_Msk; + tCAN->TEST = u8TestMask; +} + + +/** + * @brief Leave the test mode + * @param[in] tCAN The pointer to CAN module base address. + * @return None + * @details This function is used to Leave the test mode (switch into normal mode). + */ +void CAN_LeaveTestMode(CAN_T *tCAN) +{ + tCAN->CON |= CAN_CON_TEST_Msk; + tCAN->TEST &= ~(CAN_TEST_LBACK_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_BASIC_Msk); + tCAN->CON &= (~CAN_CON_TEST_Msk); +} + +/** + * @brief Get the waiting status of a received message. + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u8MsgObj Specifies the Message object number, from 0 to 31. + * @retval non-zero The corresponding message object has a new data bit is set. + * @retval 0 No message object has new data. + * @details This function is used to get the waiting status of a received message. + */ +uint32_t CAN_IsNewDataReceived(CAN_T *tCAN, uint8_t u8MsgObj) +{ + return (u8MsgObj < 16ul ? tCAN->NDAT1 & (1ul << u8MsgObj) : tCAN->NDAT2 & (1ul << (u8MsgObj - 16ul))); +} + + +/** + * @brief Send CAN message in BASIC mode of test mode + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] pCanMsg Pointer to the message structure containing data to transmit. + * @return TRUE: Transmission OK + * FALSE: Check busy flag of interface 0 is timeout + * @details The function is used to send CAN message in BASIC mode of test mode. Before call the API, + * the user should be call CAN_EnterTestMode(CAN_TEST_BASIC) and let CAN controller enter + * basic mode of test mode. Please notice IF1 Registers used as Tx Buffer in basic mode. + */ +int32_t CAN_BasicSendMsg(CAN_T *tCAN, STR_CANMSG_T *pCanMsg) +{ + uint32_t i = 0ul; + int32_t rev = 1l; + + while (tCAN->IF[0].CREQ & CAN_IF_CREQ_BUSY_Msk) + { + } + + tCAN->STATUS &= (~CAN_STATUS_TXOK_Msk); + + if (pCanMsg->IdType == CAN_STD_ID) + { + /* standard ID*/ + tCAN->IF[0].ARB1 = 0ul; + tCAN->IF[0].ARB2 = (((pCanMsg->Id) & 0x7FFul) << 2ul) ; + } + else + { + /* extended ID*/ + tCAN->IF[0].ARB1 = (pCanMsg->Id) & 0xFFFFul; + tCAN->IF[0].ARB2 = ((pCanMsg->Id) & 0x1FFF0000ul) >> 16ul | CAN_IF_ARB2_XTD_Msk; + + } + + if (pCanMsg->FrameType) + { + tCAN->IF[0].ARB2 |= CAN_IF_ARB2_DIR_Msk; + } + else + { + tCAN->IF[0].ARB2 &= (~CAN_IF_ARB2_DIR_Msk); + } + + tCAN->IF[0].MCON = (tCAN->IF[0].MCON & (~CAN_IF_MCON_DLC_Msk)) | pCanMsg->DLC; + tCAN->IF[0].DAT_A1 = (uint16_t)((uint16_t)((uint16_t)pCanMsg->Data[1] << 8) | pCanMsg->Data[0]); + tCAN->IF[0].DAT_A2 = (uint16_t)((uint16_t)((uint16_t)pCanMsg->Data[3] << 8) | pCanMsg->Data[2]); + tCAN->IF[0].DAT_B1 = (uint16_t)((uint16_t)((uint16_t)pCanMsg->Data[5] << 8) | pCanMsg->Data[4]); + tCAN->IF[0].DAT_B2 = (uint16_t)((uint16_t)((uint16_t)pCanMsg->Data[7] << 8) | pCanMsg->Data[6]); + + /* request transmission*/ + tCAN->IF[0].CREQ &= (~CAN_IF_CREQ_BUSY_Msk); + if (tCAN->IF[0].CREQ & CAN_IF_CREQ_BUSY_Msk) + { + /* Cannot clear busy for sending ...*/ + rev = 0l; /* return FALSE */ + } + else + { + tCAN->IF[0].CREQ |= CAN_IF_CREQ_BUSY_Msk; /* sending */ + + for (i = 0ul; i < 0xFFFFFul; i++) + { + if ((tCAN->IF[0].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0ul) + { + break; + } + else + { + } + } + + if (i >= 0xFFFFFul) + { + /* Cannot send out... */ + rev = 0l; /* return FALSE */ + } + else + { + } + } + + return rev; +} + +/** + * @brief Get a message information in BASIC mode. + * + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] pCanMsg Pointer to the message structure where received data is copied. + * + * @return FALSE No any message received. + * TRUE Receive a message success. + * + */ +int32_t CAN_BasicReceiveMsg(CAN_T *tCAN, STR_CANMSG_T *pCanMsg) +{ + int32_t rev = 1l; + + if ((tCAN->IF[1].MCON & CAN_IF_MCON_NEWDAT_Msk) == 0ul) + { + /* In basic mode, receive data always save in IF2 */ + rev = 0; /* return FALSE */ + } + else + { + + tCAN->STATUS &= (~CAN_STATUS_RXOK_Msk); + + tCAN->IF[1].CMASK = CAN_IF_CMASK_ARB_Msk + | CAN_IF_CMASK_CONTROL_Msk + | CAN_IF_CMASK_DATAA_Msk + | CAN_IF_CMASK_DATAB_Msk; + + if ((tCAN->IF[1].ARB2 & CAN_IF_ARB2_XTD_Msk) == 0ul) + { + /* standard ID*/ + pCanMsg->IdType = CAN_STD_ID; + pCanMsg->Id = (tCAN->IF[1].ARB2 >> 2) & 0x07FFul; + + } + else + { + /* extended ID*/ + pCanMsg->IdType = CAN_EXT_ID; + pCanMsg->Id = (tCAN->IF[1].ARB2 & 0x1FFFul) << 16; + pCanMsg->Id |= (uint32_t)tCAN->IF[1].ARB1; + } + + pCanMsg->FrameType = (((tCAN->IF[1].ARB2 & CAN_IF_ARB2_DIR_Msk) >> CAN_IF_ARB2_DIR_Pos)) ? 0ul : 1ul; + + pCanMsg->DLC = (uint8_t)(tCAN->IF[1].MCON & CAN_IF_MCON_DLC_Msk); + pCanMsg->Data[0] = (uint8_t)(tCAN->IF[1].DAT_A1 & CAN_IF_DAT_A1_DATA0_Msk); + pCanMsg->Data[1] = (uint8_t)((tCAN->IF[1].DAT_A1 & CAN_IF_DAT_A1_DATA1_Msk) >> CAN_IF_DAT_A1_DATA1_Pos); + pCanMsg->Data[2] = (uint8_t)(tCAN->IF[1].DAT_A2 & CAN_IF_DAT_A2_DATA2_Msk); + pCanMsg->Data[3] = (uint8_t)((tCAN->IF[1].DAT_A2 & CAN_IF_DAT_A2_DATA3_Msk) >> CAN_IF_DAT_A2_DATA3_Pos); + pCanMsg->Data[4] = (uint8_t)(tCAN->IF[1].DAT_B1 & CAN_IF_DAT_B1_DATA4_Msk); + pCanMsg->Data[5] = (uint8_t)((tCAN->IF[1].DAT_B1 & CAN_IF_DAT_B1_DATA5_Msk) >> CAN_IF_DAT_B1_DATA5_Pos); + pCanMsg->Data[6] = (uint8_t)(tCAN->IF[1].DAT_B2 & CAN_IF_DAT_B2_DATA6_Msk); + pCanMsg->Data[7] = (uint8_t)((tCAN->IF[1].DAT_B2 & CAN_IF_DAT_B2_DATA7_Msk) >> CAN_IF_DAT_B2_DATA7_Pos); + } + + return rev; +} + +/** + * @brief Set Rx message object, include ID mask. + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u8MsgObj Specifies the Message object number, from 0 to 31. + * @param[in] u8idType Specifies the identifier type of the frames that will be transmitted + * This parameter can be one of the following values: + * \ref CAN_STD_ID (standard ID, 11-bit) + * \ref CAN_EXT_ID (extended ID, 29-bit) + * @param[in] u32id Specifies the identifier used for acceptance filtering. + * @param[in] u32idmask Specifies the identifier mask used for acceptance filtering. + * @param[in] u8singleOrFifoLast Specifies the end-of-buffer indicator. + * This parameter can be one of the following values: + * TRUE: for a single receive object or a FIFO receive object that is the last one of the FIFO. + * FALSE: for a FIFO receive object that is not the last one. + * @retval TRUE SUCCESS + * @retval FALSE No useful interface + * @details The function is used to configure a receive message object. + */ +int32_t CAN_SetRxMsgObjAndMsk(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8idType, uint32_t u32id, uint32_t u32idmask, uint8_t u8singleOrFifoLast) +{ + int32_t rev = 1l; + uint32_t u32MsgIfNum; + + /* Get and lock a free interface */ + if ((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul) + { + rev = 0; /* return FALSE */ + } + else + { + /* Command Setting */ + tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_WRRD_Msk | CAN_IF_CMASK_MASK_Msk | CAN_IF_CMASK_ARB_Msk | + CAN_IF_CMASK_CONTROL_Msk | CAN_IF_CMASK_DATAA_Msk | CAN_IF_CMASK_DATAB_Msk; + + if (u8idType == CAN_STD_ID) /* According STD/EXT ID format,Configure Mask and Arbitration register */ + { + tCAN->IF[u32MsgIfNum].ARB1 = 0ul; + tCAN->IF[u32MsgIfNum].ARB2 = CAN_IF_ARB2_MSGVAL_Msk | (u32id & 0x7FFul) << 2; + } + else + { + tCAN->IF[u32MsgIfNum].ARB1 = u32id & 0xFFFFul; + tCAN->IF[u32MsgIfNum].ARB2 = CAN_IF_ARB2_MSGVAL_Msk | CAN_IF_ARB2_XTD_Msk | (u32id & 0x1FFF0000ul) >> 16; + } + + tCAN->IF[u32MsgIfNum].MASK1 = (u32idmask & 0xFFFFul); + tCAN->IF[u32MsgIfNum].MASK2 = (u32idmask >> 16) & 0xFFFFul; + + /* tCAN->IF[u32MsgIfNum].MCON |= CAN_IF_MCON_UMASK_Msk | CAN_IF_MCON_RXIE_Msk; */ + tCAN->IF[u32MsgIfNum].MCON = CAN_IF_MCON_UMASK_Msk | CAN_IF_MCON_RXIE_Msk; + if (u8singleOrFifoLast) + { + tCAN->IF[u32MsgIfNum].MCON |= CAN_IF_MCON_EOB_Msk; + } + else + { + tCAN->IF[u32MsgIfNum].MCON &= (~CAN_IF_MCON_EOB_Msk); + } + + tCAN->IF[u32MsgIfNum].DAT_A1 = 0ul; + tCAN->IF[u32MsgIfNum].DAT_A2 = 0ul; + tCAN->IF[u32MsgIfNum].DAT_B1 = 0ul; + tCAN->IF[u32MsgIfNum].DAT_B2 = 0ul; + + tCAN->IF[u32MsgIfNum].CREQ = 1ul + u8MsgObj; + ReleaseIF(tCAN, u32MsgIfNum); + } + + return rev; +} + +/** + * @brief Set Rx message object + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u8MsgObj Specifies the Message object number, from 0 to 31. + * @param[in] u8idType Specifies the identifier type of the frames that will be transmitted + * This parameter can be one of the following values: + * \ref CAN_STD_ID (standard ID, 11-bit) + * \ref CAN_EXT_ID (extended ID, 29-bit) + * @param[in] u32id Specifies the identifier used for acceptance filtering. + * @param[in] u8singleOrFifoLast Specifies the end-of-buffer indicator. + * This parameter can be one of the following values: + * TRUE: for a single receive object or a FIFO receive object that is the last one of the FIFO. + * FALSE: for a FIFO receive object that is not the last one. + * @retval TRUE SUCCESS + * @retval FALSE No useful interface + * @details The function is used to configure a receive message object. + */ +int32_t CAN_SetRxMsgObj(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8idType, uint32_t u32id, uint8_t u8singleOrFifoLast) +{ + int32_t rev = 1l; + uint32_t u32MsgIfNum; + + /* Get and lock a free interface */ + if ((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul) + { + rev = 0; /* return FALSE */ + } + else + { + /* Command Setting */ + tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_WRRD_Msk | CAN_IF_CMASK_MASK_Msk | CAN_IF_CMASK_ARB_Msk | + CAN_IF_CMASK_CONTROL_Msk | CAN_IF_CMASK_DATAA_Msk | CAN_IF_CMASK_DATAB_Msk; + + if (u8idType == CAN_STD_ID) /* According STD/EXT ID format,Configure Mask and Arbitration register */ + { + tCAN->IF[u32MsgIfNum].ARB1 = 0ul; + tCAN->IF[u32MsgIfNum].ARB2 = CAN_IF_ARB2_MSGVAL_Msk | (u32id & 0x7FFul) << 2; + } + else + { + tCAN->IF[u32MsgIfNum].ARB1 = u32id & 0xFFFFul; + tCAN->IF[u32MsgIfNum].ARB2 = CAN_IF_ARB2_MSGVAL_Msk | CAN_IF_ARB2_XTD_Msk | (u32id & 0x1FFF0000ul) >> 16; + } + + /* tCAN->IF[u8MsgIfNum].MCON |= CAN_IF_MCON_UMASK_Msk | CAN_IF_MCON_RXIE_Msk; */ + tCAN->IF[u32MsgIfNum].MCON = CAN_IF_MCON_UMASK_Msk | CAN_IF_MCON_RXIE_Msk; + if (u8singleOrFifoLast) + { + tCAN->IF[u32MsgIfNum].MCON |= CAN_IF_MCON_EOB_Msk; + } + else + { + tCAN->IF[u32MsgIfNum].MCON &= (~CAN_IF_MCON_EOB_Msk); + } + + tCAN->IF[u32MsgIfNum].DAT_A1 = 0ul; + tCAN->IF[u32MsgIfNum].DAT_A2 = 0ul; + tCAN->IF[u32MsgIfNum].DAT_B1 = 0ul; + tCAN->IF[u32MsgIfNum].DAT_B2 = 0ul; + + tCAN->IF[u32MsgIfNum].CREQ = 1ul + u8MsgObj; + ReleaseIF(tCAN, u32MsgIfNum); + } + + return rev; +} + +/** + * @brief Gets the message + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u8MsgObj Specifies the Message object number, from 0 to 31. + * @param[in] u8Release Specifies the message release indicator. + * This parameter can be one of the following values: + * TRUE: the message object is released when getting the data. + * FALSE:the message object is not released. + * @param[in] pCanMsg Pointer to the message structure where received data is copied. + * @retval TRUE Success + * @retval FALSE No any message received + * @details Gets the message, if received. + */ +int32_t CAN_ReadMsgObj(CAN_T *tCAN, uint8_t u8MsgObj, uint8_t u8Release, STR_CANMSG_T *pCanMsg) +{ + int32_t rev = 1l; + uint32_t u32MsgIfNum; + + if (!CAN_IsNewDataReceived(tCAN, u8MsgObj)) + { + rev = 0; /* return FALSE */ + } + else + { + /* Get and lock a free interface */ + if ((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul) + { + rev = 0; /* return FALSE */ + } + else + { + tCAN->STATUS &= (~CAN_STATUS_RXOK_Msk); + + /* read the message contents*/ + tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_MASK_Msk + | CAN_IF_CMASK_ARB_Msk + | CAN_IF_CMASK_CONTROL_Msk + | CAN_IF_CMASK_CLRINTPND_Msk + | (u8Release ? CAN_IF_CMASK_TXRQSTNEWDAT_Msk : 0ul) + | CAN_IF_CMASK_DATAA_Msk + | CAN_IF_CMASK_DATAB_Msk; + + tCAN->IF[u32MsgIfNum].CREQ = 1ul + u8MsgObj; + + while (tCAN->IF[u32MsgIfNum].CREQ & CAN_IF_CREQ_BUSY_Msk) + { + /*Wait*/ + } + + if ((tCAN->IF[u32MsgIfNum].ARB2 & CAN_IF_ARB2_XTD_Msk) == 0ul) + { + /* standard ID*/ + pCanMsg->IdType = CAN_STD_ID; + pCanMsg->Id = (tCAN->IF[u32MsgIfNum].ARB2 & CAN_IF_ARB2_ID_Msk) >> 2ul; + } + else + { + /* extended ID*/ + pCanMsg->IdType = CAN_EXT_ID; + pCanMsg->Id = (((tCAN->IF[u32MsgIfNum].ARB2) & 0x1FFFul) << 16) | tCAN->IF[u32MsgIfNum].ARB1; + } + + pCanMsg->DLC = (uint8_t)(tCAN->IF[u32MsgIfNum].MCON & CAN_IF_MCON_DLC_Msk); + pCanMsg->Data[0] = (uint8_t)(tCAN->IF[u32MsgIfNum].DAT_A1 & CAN_IF_DAT_A1_DATA0_Msk); + pCanMsg->Data[1] = (uint8_t)((tCAN->IF[u32MsgIfNum].DAT_A1 & CAN_IF_DAT_A1_DATA1_Msk) >> CAN_IF_DAT_A1_DATA1_Pos); + pCanMsg->Data[2] = (uint8_t)(tCAN->IF[u32MsgIfNum].DAT_A2 & CAN_IF_DAT_A2_DATA2_Msk); + pCanMsg->Data[3] = (uint8_t)((tCAN->IF[u32MsgIfNum].DAT_A2 & CAN_IF_DAT_A2_DATA3_Msk) >> CAN_IF_DAT_A2_DATA3_Pos); + pCanMsg->Data[4] = (uint8_t)(tCAN->IF[u32MsgIfNum].DAT_B1 & CAN_IF_DAT_B1_DATA4_Msk); + pCanMsg->Data[5] = (uint8_t)((tCAN->IF[u32MsgIfNum].DAT_B1 & CAN_IF_DAT_B1_DATA5_Msk) >> CAN_IF_DAT_B1_DATA5_Pos); + pCanMsg->Data[6] = (uint8_t)(tCAN->IF[u32MsgIfNum].DAT_B2 & CAN_IF_DAT_B2_DATA6_Msk); + pCanMsg->Data[7] = (uint8_t)((tCAN->IF[u32MsgIfNum].DAT_B2 & CAN_IF_DAT_B2_DATA7_Msk) >> CAN_IF_DAT_B2_DATA7_Pos); + + ReleaseIF(tCAN, u32MsgIfNum); + } + } + + return rev; +} + + +/** + * @brief Set bus baud-rate. + * + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32BaudRate The target CAN baud-rate. The range of u32BaudRate is 1~1000KHz. + * + * @return u32CurrentBitRate Real baud-rate value. + * + * @details The function is used to set bus timing parameter according current clock and target baud-rate. + */ +uint32_t CAN_SetBaudRate(CAN_T *tCAN, uint32_t u32BaudRate) +{ + long rate; + long best_error = 1000000000, error = 0; + int best_tseg = 0, best_brp = 0, brp = 0; + int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0; + int spt_error = 1000, spt = 0, sampl_pt; + uint64_t clock_freq = (uint64_t)0, u64PCLK_DIV = (uint64_t)1; + uint32_t sjw = (uint32_t)1; + + CAN_EnterInitMode(tCAN, (uint8_t)0); + + CAN_Clock = sysGetClock(SYS_PCLK) * 1000000; + + clock_freq = CAN_Clock / u64PCLK_DIV; + + if (u32BaudRate >= (uint32_t)1000000) + { + u32BaudRate = (uint32_t)1000000; + } + + /* Use CIA recommended sample points */ + if (u32BaudRate > (uint32_t)800000) + { + sampl_pt = (int)750; + } + else if (u32BaudRate > (uint32_t)500000) + { + sampl_pt = (int)800; + } + else + { + sampl_pt = (int)875; + } + + /* tseg even = round down, odd = round up */ + for (tseg = (TSEG1_MAX + TSEG2_MAX) * 2ul + 1ul; tseg >= (TSEG1_MIN + TSEG2_MIN) * 2ul; tseg--) + { + tsegall = 1ul + tseg / 2ul; + /* Compute all possible tseg choices (tseg=tseg1+tseg2) */ + brp = clock_freq / (tsegall * u32BaudRate) + tseg % 2; + /* chose brp step which is possible in system */ + brp = (brp / BRP_INC) * BRP_INC; + + if ((brp < BRP_MIN) || (brp > BRP_MAX)) + { + continue; + } + rate = clock_freq / (brp * tsegall); + + error = u32BaudRate - rate; + + /* tseg brp biterror */ + if (error < 0) + { + error = -error; + } + if (error > best_error) + { + continue; + } + best_error = error; + if (error == 0) + { + spt = can_update_spt(sampl_pt, tseg / 2, &tseg1, &tseg2); + error = sampl_pt - spt; + if (error < 0) + { + error = -error; + } + if (error > spt_error) + { + continue; + } + spt_error = error; + } + best_tseg = tseg / 2; + best_brp = brp; + + if (error == 0) + { + break; + } + } + + spt = can_update_spt(sampl_pt, best_tseg, &tseg1, &tseg2); + + /* check for sjw user settings */ + /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */ + if (sjw > SJW_MAX) + { + sjw = SJW_MAX; + } + /* bt->sjw must not be higher than tseg2 */ + if (tseg2 < sjw) + { + sjw = tseg2; + } + + /* real bit-rate */ + u32BaudRate = clock_freq / (best_brp * (tseg1 + tseg2 + 1)); + + tCAN->BTIME = ((uint32_t)(tseg2 - 1ul) << CAN_BTIME_TSEG2_Pos) | ((uint32_t)(tseg1 - 1ul) << CAN_BTIME_TSEG1_Pos) | + ((uint32_t)(best_brp - 1ul) & CAN_BTIME_BRP_Msk) | (sjw << CAN_BTIME_SJW_Pos); + tCAN->BRPE = ((uint32_t)(best_brp - 1ul) >> 6) & 0x0Ful; + + /* printf("\n bitrate = %d \n", CAN_GetCANBitRate(tCAN)); */ + + CAN_LeaveInitMode(tCAN); + + return u32BaudRate; +} + +/** + * @brief The function is used to disable all CAN interrupt. + * + * @param[in] tCAN The pointer to CAN module base address. + * + * @return None + * + * @details No Status Change Interrupt and Error Status Interrupt will be generated. + */ +void CAN_Close(CAN_T *tCAN) +{ + CAN_DisableInt(tCAN, (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)); +} + +/** + * @brief Set CAN operation mode and target baud-rate. + * + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32BaudRate The target CAN baud-rate. The range of u32BaudRate is 1~1000KHz. + * @param[in] u32Mode The CAN operation mode. Valid values are: + * - \ref CAN_NORMAL_MODE Normal operation. + * - \ref CAN_BASIC_MODE Basic mode. + * @return u32CurrentBitRate Real baud-rate value. + * + * @details Set bus timing parameter according current clock and target baud-rate. + * In Basic mode, IF1 Registers used as Tx Buffer, IF2 Registers used as Rx Buffer. + */ +uint32_t CAN_Open(CAN_T *tCAN, uint32_t u32BaudRate, uint32_t u32Mode) +{ + uint32_t u32CurrentBitRate; + + u32CurrentBitRate = CAN_SetBaudRate(tCAN, u32BaudRate); + + if (u32Mode == CAN_BASIC_MODE) + { + CAN_EnterTestMode(tCAN, (uint8_t)CAN_TEST_BASIC_Msk); + } + else + { + } + + return u32CurrentBitRate; +} + +/** + * @brief The function is used to configure a transmit object. + * + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31. + * @param[in] pCanMsg Pointer to the message structure where received data is copied. + * + * @retval FALSE No useful interface. + * @retval TRUE Config message object success. + * + * @details The two sets of interface registers (IF1 and IF2) control the software access to the Message RAM. + * They buffer the data to be transferred to and from the RAM, avoiding conflicts between software accesses and message reception/transmission. + */ +int32_t CAN_SetTxMsg(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T *pCanMsg) +{ + int32_t rev = 1l; + uint32_t u32MsgIfNum; + + if ((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul) + { + rev = 0; /* return FALSE */ + } + else + { + /* update the contents needed for transmission*/ + tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_WRRD_Msk | CAN_IF_CMASK_MASK_Msk | CAN_IF_CMASK_ARB_Msk | + CAN_IF_CMASK_CONTROL_Msk | CAN_IF_CMASK_DATAA_Msk | CAN_IF_CMASK_DATAB_Msk; + + if (pCanMsg->IdType == CAN_STD_ID) + { + /* standard ID*/ + tCAN->IF[u32MsgIfNum].ARB1 = 0ul; + tCAN->IF[u32MsgIfNum].ARB2 = (((pCanMsg->Id) & 0x7FFul) << 2) | CAN_IF_ARB2_DIR_Msk | CAN_IF_ARB2_MSGVAL_Msk; + } + else + { + /* extended ID*/ + tCAN->IF[u32MsgIfNum].ARB1 = (pCanMsg->Id) & 0xFFFFul; + tCAN->IF[u32MsgIfNum].ARB2 = ((pCanMsg->Id) & 0x1FFF0000ul) >> 16 | + CAN_IF_ARB2_DIR_Msk | CAN_IF_ARB2_XTD_Msk | CAN_IF_ARB2_MSGVAL_Msk; + } + + if (pCanMsg->FrameType) + { + tCAN->IF[u32MsgIfNum].ARB2 |= CAN_IF_ARB2_DIR_Msk; + } + else + { + tCAN->IF[u32MsgIfNum].ARB2 &= (~CAN_IF_ARB2_DIR_Msk); + } + + tCAN->IF[u32MsgIfNum].DAT_A1 = (uint16_t)((uint16_t)(((uint16_t)pCanMsg->Data[1] << 8)) | pCanMsg->Data[0]); + tCAN->IF[u32MsgIfNum].DAT_A2 = (uint16_t)((uint16_t)(((uint16_t)pCanMsg->Data[3] << 8)) | pCanMsg->Data[2]); + tCAN->IF[u32MsgIfNum].DAT_B1 = (uint16_t)((uint16_t)(((uint16_t)pCanMsg->Data[5] << 8)) | pCanMsg->Data[4]); + tCAN->IF[u32MsgIfNum].DAT_B2 = (uint16_t)((uint16_t)(((uint16_t)pCanMsg->Data[7] << 8)) | pCanMsg->Data[6]); + + tCAN->IF[u32MsgIfNum].MCON = CAN_IF_MCON_NEWDAT_Msk | pCanMsg->DLC | CAN_IF_MCON_TXIE_Msk | CAN_IF_MCON_EOB_Msk; + tCAN->IF[u32MsgIfNum].CREQ = 1ul + u32MsgNum; + + ReleaseIF(tCAN, u32MsgIfNum); + } + + return rev; +} + +/** + * @brief Set transmit request bit. + * + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31. + * + * @return TRUE: Start transmit message. + * + * @details If a transmission is requested by programming bit TxRqst/NewDat (IFn_CMASK[2]), the TxRqst (IFn_MCON[8]) will be ignored. + */ +int32_t CAN_TriggerTxMsg(CAN_T *tCAN, uint32_t u32MsgNum) +{ + int32_t rev = 1l; + uint32_t u32MsgIfNum; + + if ((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul) + { + rev = 0; /* return FALSE */ + } + else + { + tCAN->STATUS &= (~CAN_STATUS_TXOK_Msk); + + /* read the message contents*/ + tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_CLRINTPND_Msk + | CAN_IF_CMASK_TXRQSTNEWDAT_Msk; + + tCAN->IF[u32MsgIfNum].CREQ = 1ul + u32MsgNum; + + while (tCAN->IF[u32MsgIfNum].CREQ & CAN_IF_CREQ_BUSY_Msk) + { + /*Wait*/ + } + tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_WRRD_Msk | CAN_IF_CMASK_TXRQSTNEWDAT_Msk; + tCAN->IF[u32MsgIfNum].CREQ = 1ul + u32MsgNum; + + ReleaseIF(tCAN, u32MsgIfNum); + } + + return rev; +} + +/** + * @brief Enable CAN interrupt. + * + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32Mask Interrupt Mask. Valid values are: + * - \ref CAN_CON_IE_Msk Module interrupt enable. + * - \ref CAN_CON_SIE_Msk Status change interrupt enable. + * - \ref CAN_CON_EIE_Msk Error interrupt enable. + * + * @return None + * + * @details The application software has two possibilities to follow the source of a message interrupt. + * First, it can follow the IntId in the Interrupt Register and second it can poll the Interrupt Pending Register. + */ +void CAN_EnableInt(CAN_T *tCAN, uint32_t u32Mask) +{ + tCAN->CON = (tCAN->CON & ~(CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)) | + (u32Mask & (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)); +} + +/** + * @brief Disable CAN interrupt. + * + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32Mask Interrupt Mask. (CAN_CON_IE_Msk / CAN_CON_SIE_Msk / CAN_CON_EIE_Msk). + * + * @return None + * + * @details The interrupt remains active until the Interrupt Register is back to value zero (the cause of the interrupt is reset) or until IE is reset. + */ +void CAN_DisableInt(CAN_T *tCAN, uint32_t u32Mask) +{ + tCAN->CON = tCAN->CON & ~((u32Mask & (CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk))); +} + + +/** + * @brief The function is used to configure a receive message object. + * + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31. + * @param[in] u32IDType Specifies the identifier type of the frames that will be transmitted. Valid values are: + * - \ref CAN_STD_ID The 11-bit identifier. + * - \ref CAN_EXT_ID The 29-bit identifier. + * @param[in] u32ID Specifies the identifier used for acceptance filtering. + * + * @retval FALSE No useful interface. + * @retval TRUE Configure a receive message object success. + * + * @details If the RxIE bit (CAN_IFn_MCON[10]) is set, the IntPnd bit (CAN_IFn_MCON[13]) + * will be set when a received Data Frame is accepted and stored in the Message Object. + */ +int32_t CAN_SetRxMsg(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32IDType, uint32_t u32ID) +{ + int32_t rev = (int32_t)TRUE; + uint32_t u32TimeOutCount = 0ul; + + while (CAN_SetRxMsgObj(tCAN, (uint8_t)u32MsgNum, (uint8_t)u32IDType, u32ID, (uint8_t)TRUE) == (int32_t)FALSE) + { + if (++u32TimeOutCount >= RETRY_COUNTS) + { + rev = (int32_t)(FALSE); /* return FALSE */ + break; + } + else + { + } + } + + return rev; +} + +/** + * @brief The function is used to configure a receive message object. + * + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31. + * @param[in] u32IDType Specifies the identifier type of the frames that will be transmitted. Valid values are: + * - \ref CAN_STD_ID The 11-bit identifier. + * - \ref CAN_EXT_ID The 29-bit identifier. + * @param[in] u32ID Specifies the identifier used for acceptance filtering. + * @param[in] u32IDMask Specifies the identifier mask used for acceptance filtering. + * + * @retval FALSE No useful interface. + * @retval TRUE Configure a receive message object success. + * + * @details If the RxIE bit (CAN_IFn_MCON[10]) is set, the IntPnd bit (CAN_IFn_MCON[13]) + * will be set when a received Data Frame is accepted and stored in the Message Object. + */ +int32_t CAN_SetRxMsgAndMsk(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32IDType, uint32_t u32ID, uint32_t u32IDMask) +{ + int32_t rev = (int32_t)TRUE; + uint32_t u32TimeOutCount = 0ul; + + while (CAN_SetRxMsgObjAndMsk(tCAN, (uint8_t)u32MsgNum, (uint8_t)u32IDType, u32ID, u32IDMask, (uint8_t)TRUE) == (int32_t)FALSE) + { + if (++u32TimeOutCount >= RETRY_COUNTS) + { + rev = (int32_t)FALSE; + break; + } + else + { + } + } + + return rev; +} + +/** + * @brief The function is used to configure several receive message objects. + * + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32MsgNum The starting MSG RAM number(0 ~ 31). + * @param[in] u32MsgCount the number of MSG RAM of the FIFO. + * @param[in] u32IDType Specifies the identifier type of the frames that will be transmitted. Valid values are: + * - \ref CAN_STD_ID The 11-bit identifier. + * - \ref CAN_EXT_ID The 29-bit identifier. + * @param[in] u32ID Specifies the identifier used for acceptance filtering. + * + * @retval FALSE No useful interface. + * @retval TRUE Configure receive message objects success. + * + * @details The Interface Registers avoid conflict between the CPU accesses to the Message RAM and CAN message reception + * and transmission by buffering the data to be transferred. + */ +int32_t CAN_SetMultiRxMsg(CAN_T *tCAN, uint32_t u32MsgNum, uint32_t u32MsgCount, uint32_t u32IDType, uint32_t u32ID) +{ + int32_t rev = (int32_t)TRUE; + uint32_t i; + uint32_t u32TimeOutCount; + uint32_t u32EOB_Flag = 0ul; + + for (i = 1ul; i <= u32MsgCount; i++) + { + u32TimeOutCount = 0ul; + + u32MsgNum += (i - 1ul); + + if (i == u32MsgCount) + { + u32EOB_Flag = 1ul; + } + else + { + } + + while (CAN_SetRxMsgObj(tCAN, (uint8_t)u32MsgNum, (uint8_t)u32IDType, u32ID, (uint8_t)u32EOB_Flag) == (int32_t)FALSE) + { + if (++u32TimeOutCount >= RETRY_COUNTS) + { + rev = (int32_t)FALSE; + break; + } + else + { + } + } + } + + return rev; +} + + +/** + * @brief Send CAN message. + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31. + * @param[in] pCanMsg Pointer to the message structure where received data is copied. + * + * @retval FALSE 1. When operation in basic mode: Transmit message time out. \n + * 2. When operation in normal mode: No useful interface. \n + * @retval TRUE Transmit Message success. + * + * @details The receive/transmit priority for the Message Objects is attached to the message number. + * Message Object 1 has the highest priority, while Message Object 32 has the lowest priority. + */ +int32_t CAN_Transmit(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T *pCanMsg) +{ + int32_t rev = (int32_t)TRUE; + uint32_t u32Tmp; + + u32Tmp = (tCAN->TEST & CAN_TEST_BASIC_Msk); + + if ((tCAN->CON & CAN_CON_TEST_Msk) && u32Tmp) + { + rev = CAN_BasicSendMsg(tCAN, pCanMsg); + } + else + { + if (CAN_SetTxMsg(tCAN, u32MsgNum, pCanMsg) == FALSE) + { + rev = (int32_t)FALSE; + } + else + { + CAN_TriggerTxMsg(tCAN, u32MsgNum); + } + } + + return rev; +} + + +/** + * @brief Gets the message, if received. + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31. + * @param[in] pCanMsg Pointer to the message structure where received data is copied. + * + * @retval FALSE No any message received. + * @retval TRUE Receive Message success. + * + * @details The Interface Registers avoid conflict between the CPU accesses to the Message RAM and CAN message reception + * and transmission by buffering the data to be transferred. + */ +int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T *pCanMsg) +{ + int32_t rev = (int32_t)TRUE; + uint32_t u32Tmp; + + u32Tmp = (tCAN->TEST & CAN_TEST_BASIC_Msk); + + if ((tCAN->CON & CAN_CON_TEST_Msk) && u32Tmp) + { + rev = CAN_BasicReceiveMsg(tCAN, pCanMsg); + } + else + { + rev = CAN_ReadMsgObj(tCAN, (uint8_t)u32MsgNum, (uint8_t)TRUE, pCanMsg); + } + + return rev; +} + +/** + * @brief Clear interrupt pending bit. + * @param[in] tCAN The pointer to CAN module base address. + * @param[in] u32MsgNum Specifies the Message object number, from 0 to 31. + * + * @return None + * + * @details An interrupt remains pending until the application software has cleared it. + */ +void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum) +{ + uint32_t u32MsgIfNum; + + if ((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul) + { + u32MsgIfNum = 0ul; + } + else + { + } + + tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_CLRINTPND_Msk | CAN_IF_CMASK_TXRQSTNEWDAT_Msk; + tCAN->IF[u32MsgIfNum].CREQ = 1ul + u32MsgNum; + + ReleaseIF(tCAN, u32MsgIfNum); +} + + +/*@}*/ /* end of group CAN_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group CAN_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_cap.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_cap.c new file mode 100644 index 0000000000..69bea7c7a4 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_cap.c @@ -0,0 +1,1520 @@ +/**************************************************************************//** +* @file cap.c +* @version V1.00 +* @brief N9H30 CAP driver source file +* +* SPDX-License-Identifier: Apache-2.0 +* @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include +#include +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_cap.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_CAP_Driver CAP Driver + @{ +*/ + +/** @addtogroup N9H30_CAP_EXPORTED_FUNCTIONS CAP Exported Functions + @{ +*/ + +/// @cond HIDDEN_SYMBOLS +PFN_CAP_CALLBACK(pfnCAP_IntHandlerTable)[4] = {0}; +/// @endcond HIDDEN_SYMBOLS + +/** + * @brief CAP interrupt Handler + * + * @param None + * + * @return None + * + * @details Driver internal use API to process the interrupt of CAP + * As interrupt occurrence, the register call back function will be executed + */ +static UINT32 u32EscapeFrame = 0; +//static UINT32 g_u32DeviceType = 0; +static void CAP_IntHandler(void) +{ + UINT32 u32CapInt; + UINT32 uBuf = 0; + + if ((inp32(REG_CLK_HCLKEN) & (0x1 << 26)) == (0x1 << 26)) /* CMOS sensor interface controller clock enabled */ + { + u32CapInt = inp32(REG_CAP_INT); + if ((u32CapInt & (VIEN | VINTF)) == (VIEN | VINTF)) + { + if (pfnCAP_IntHandlerTable[0] != 0) + pfnCAP_IntHandlerTable[0](uBuf, uBuf, u32EscapeFrame); + outp32(REG_CAP_INT, (u32CapInt & ~(MDINTF | ADDRMINTF | MEINTF))); /* Clear Frame end interrupt */ + u32EscapeFrame = u32EscapeFrame + 1; + } + else if ((u32CapInt & (ADDRMIEN | ADDRMINTF)) == (ADDRMIEN | ADDRMINTF)) + { + if (pfnCAP_IntHandlerTable[1] != 0) + pfnCAP_IntHandlerTable[1](uBuf, uBuf, u32EscapeFrame); + outp32(REG_CAP_INT, (u32CapInt & ~(MDINTF | VINTF | MEINTF))); /* Clear Address match interrupt */ + } + else if ((u32CapInt & (MEIEN | MEINTF)) == (MEIEN | MEINTF)) + { + if (pfnCAP_IntHandlerTable[2] != 0) + pfnCAP_IntHandlerTable[2](uBuf, uBuf, u32EscapeFrame); + outp32(REG_CAP_INT, (u32CapInt & ~(MDINTF | VINTF | ADDRMINTF))); /* Clear Memory error interrupt */ + } + else if ((u32CapInt & (MDIEN | MDINTF)) == (MDIEN | MDINTF)) + { + if (pfnCAP_IntHandlerTable[3] != 0) + pfnCAP_IntHandlerTable[3](uBuf, uBuf, u32EscapeFrame); + outp32(REG_CAP_INT, (u32CapInt & ~(VINTF | MEINTF | ADDRMINTF))); /* Clear Memory error interrupt */ + } + } +} + +/** + * @brief Set Inital Frame + * + * @return None + * + * @details If enable interrupt, there is internal counter that records how many frames have pass. + * Set the internal counters to zero. The internal counter may be not a constant + */ +void CAP_SetInitFrame(void) +{ + u32EscapeFrame = 0; +} + +/** + * @brief Get Inital Frame + * + * @retval >0 Internal counters + * + * @details If enable interrupt, there is internal counter that records how many frames have pass. + * Get the internal counters. The internal counter may be not a constant + */ +UINT32 CAP_GetSkipFrame(void) +{ + return u32EscapeFrame; +} + +/** + * @brief CAP Initial + * + * @param[in] bIsEnableSnrClock Enable/Disable sensor clock + * 1 : Enable + * 0 : Disable + * @param[in] eSnrSrc Set CAP clock source. Including : + * - \ref eCAP_SNR_APLL + * - \ref eCAP_SNR_UPLL + * @param[in] u32SensorFreqKHz Specify the sensor clock + * + * @return None + * + * @details To Initial sensor source clock and frequency for CAP interface + */ +void CAP_Init(BOOL bIsEnableSnrClock, E_CAP_SNR_SRC eSnrSrc, UINT32 u32SensorFreqKHz/*KHz unit*/) +{ + UINT32 u32PllClock, u32SenDiv;// u32ExtFreq; + UINT32 u32Div0, u32Div1; + UINT32 u32SenSrc; + volatile UINT32 u32Divider; + + /* MFP_GPI_L : I3=SEN_CLK0, I4=SEN_PCLK, I5=SEN_HSYNC, I6=SEN_VSYNC, I7=SEN_FIFLD*/ + outpw(REG_SYS_GPI_MFPL, (inpw(REG_SYS_GPI_MFPL) & (0x00000FFF)) | 0x33333000); + + /* MFP_GPI_H : SEN_PDATA[0~7]*/ + outpw(REG_SYS_GPI_MFPH, (inpw(REG_SYS_GPI_MFPH) & (0xFFFFFFFF)) | 0x33333333); + + u32SensorFreqKHz = u32SensorFreqKHz * 1000; + switch (eSnrSrc) + { + case eCAP_SNR_APLL: + u32PllClock = sysGetClock(SYS_APLL) * 1000000; + u32SenSrc = 0x2 << 19; //APLL for sensor clock + break; + case eCAP_SNR_UPLL: + u32PllClock = sysGetClock(SYS_UPLL) * 1000000; + u32SenSrc = 0x3 << 19; //UPLL for sensor clock + break; + } + + + u32SenDiv = u32PllClock / (u32SensorFreqKHz); + if (u32PllClock % u32SensorFreqKHz != 0) u32SenDiv = u32SenDiv + 1; + for (u32Div1 = 1; u32Div1 <= 16; u32Div1 = u32Div1 + 1) + { + for (u32Div0 = 1; u32Div0 <= 8; u32Div0 = u32Div0 + 1) + if (u32SenDiv == u32Div0 * u32Div1) break; + if (u32Div0 >= 9) continue; + if (u32SenDiv == u32Div0 * u32Div1) break; + } + //sysprintf("Div0 and Div1 = %d, %d ", u32Div0, u32Div1); + u32Div0 = u32Div0 - 1; + u32Div1 = u32Div1 - 1; + + if (bIsEnableSnrClock) + { + outp32(REG_CLK_HCLKEN, inp32(REG_CLK_HCLKEN) | (1 << 27)); /* CMOS Sensor Reference Clock Output Enable */ + outp32(REG_CLK_HCLKEN, inp32(REG_CLK_HCLKEN) | (1 << 26)); /* CMOS Sensor Interface Controller Clock Enable */ + } + else + { + outp32(REG_CLK_HCLKEN, inp32(REG_CLK_HCLKEN) & ~(1 << 27)); /* CMOS Sensor Reference Clock Output Disabled */ + outp32(REG_CLK_HCLKEN, inp32(REG_CLK_HCLKEN) & ~(1 << 26)); /* CMOS Sensor Interface Controller Clock Disabled */ + } + u32Divider = u32SenSrc | ((u32Div0 << 16) | (u32Div1 << 24)) ; + //sysprintf("Sensor Divider = 0x%08x\n", u32Divider); + + outp32(REG_CLK_DIVCTL3, (inp32(REG_CLK_DIVCTL3) & ~((0x3 << 19) | (0x7 << 16) | (0xF << 24))) | u32Divider); + + +} + +/** + * @brief CAP Open + * + * @param[in] u32SensorFreqKHz Specify the sensor clock + * + * @retval 0 Success + * @retval <0 Error code + * + * @details Initialize the CAP engine. Register a call back for driver internal using + */ +INT32 CAP_Open(UINT32 u32SensorFreqKHz) +{ + + UINT32 u32PllClock;// u32ExtFreq; + UINT32 u32SenDiv; + UINT32 u32Div0, u32Div1; + UINT32 u32SenSrc; + volatile UINT32 u32Divider; + + u32SensorFreqKHz = u32SensorFreqKHz * 1000; + + outp32(REG_CLK_PMCON, inpw(REG_CLK_PMCON) | (0x1 << 4)) ; /* Sensor clock keep on high level */ + outp32(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) | (0x1 << 26)); /* CMOS sensor interface controller clock enable */ + outp32(REG_SYS_AHBIPRST, inp32(REG_SYS_AHBIPRST) | (1 << 10)); /* Video capture (CMOS sensor interface) reset enable. */ + outp32(REG_SYS_AHBIPRST, inp32(REG_SYS_AHBIPRST) & ~(1 << 10)); /* Video capture (CMOS sensor interface) reset disable */ + + switch ((inpw(REG_CLK_DIVCTL3) >> 19) & 0x3) + { + case eCAP_SNR_APLL: + u32PllClock = sysGetClock(SYS_APLL) * 1000000; + u32SenSrc = 0x2 << 19; //APLL for sensor clock + break; + case eCAP_SNR_UPLL: + u32PllClock = sysGetClock(SYS_UPLL) * 1000000; + u32SenSrc = 0x3 << 19; //APLL for sensor clock + break; + } + + u32SenDiv = u32PllClock / (u32SensorFreqKHz); + if (u32PllClock % u32SensorFreqKHz != 0) + u32SenDiv = u32SenDiv + 1; + for (u32Div1 = 1; u32Div1 <= 16; u32Div1 = u32Div1 + 1) + { + for (u32Div0 = 1; u32Div0 <= 8; u32Div0 = u32Div0 + 1) + { + if (u32SenDiv == u32Div0 * u32Div1) + break; + } + if (u32Div0 >= 9) continue; + if (u32SenDiv == u32Div0 * u32Div1) + break; + } + //sysprintf("Div0 and Div1 = %d, %d ", u32Div0, u32Div1); + u32Div0 = u32Div0 - 1; + u32Div1 = u32Div1 - 1; + u32Divider = u32SenSrc | ((u32Div0 << 16) | (u32Div1 << 24)) ; + //sysprintf("Sensor Divider = 0x%08x\n", u32Divider); + + outp32(REG_CLK_DIVCTL3, (inp32(REG_CLK_DIVCTL3) & ~((0x3 << 19) | (0x7 << 16) | (0xF << 24))) | u32Divider); + + sysInstallISR(IRQ_LEVEL_1, CAP_IRQn, (PVOID)CAP_IntHandler); + sysEnableInterrupt(CAP_IRQn); + + return Successful; +} + + +/** + * @brief videoIn Reset + * + * @return None + * + * @details Capture interface reset. + */ +void CAP_Reset(void) +{ + outp32(REG_CAP_CTL, inp32(REG_CAP_CTL) | (VPRST)); + outp32(REG_CAP_CTL, inp32(REG_CAP_CTL) & (~VPRST)); +} + +/** + * @brief videoIn Close + * + * @return None + * + * @details Disable pin function,engine clock and interrupt + */ +void CAP_Close(void) +{ + // 1. Disable IP's interrupt + sysDisableInterrupt(CAP_IRQn); + // 2. Disable IPs clock + outp32(REG_CLK_HCLKEN, inp32(REG_CLK_HCLKEN) & ~(0x1 << 25)); + CAP_Reset(); + outp32(REG_CLK_HCLKEN, inp32(REG_CLK_HCLKEN) & ~(0x1 << 26)); + // 3. Disable Capture pin function +} + +/** + * @brief Configure packet frame buffer. + * + * @param[in] bFrameSwitch Software mode buffer select + * 0: Packet buffer 0 + * 1: Packet buffer 1 + * @return None + * + * @details This function set packet frame buffer control + */ +void CAP_SetPacketFrameBufferControl(BOOL bFrameSwitch) +{ + UINT32 u32Ctl; + u32Ctl = inp32(REG_CAP_CTL) & ~(ADDRSW); + outp32(REG_CAP_CTL, u32Ctl | (bFrameSwitch ? ADDRSW : 0)); +} + +/** +* @brief Get packet frame buffer. + * + * @param pbFrameSwitch Software mode buffer select + * 0: Packet buffer 0 + * 1: Packet buffer 1 + * @return None + * + * @details This function get packet frame buffer control + */ +void CAP_GetPacketFrameBufferControl(PBOOL pbFrameSwitch) +{ + UINT32 u32Ctl = inp32(REG_CAP_CTL); + *pbFrameSwitch = (u32Ctl & ADDRSW) >> 3; +} + +/** +* @brief Configure callback function + * + * @param[in] eIntType Set interrupt type. Including : + * - \ref eCAP_MDINTF + * - \ref eCAP_ADDRMINTF + * - \ref eCAP_MEINTF + * - \ref eCAP_VINTF + * @param[in] pfnCallback Set Callback function. + * The callbakc function : + * void (*PFN_CAP_CALLBACK)(UINT8 u8PacketBufID,UINT8 u8PlanarBufID, UINT8 u8FrameRate); + * @param[in] pfnOldCallback Set Old callback function + * The callbakc function : + * void *(*PFN_CAP_CALLBACK)(UINT8 u8PacketBufID,UINT8 u8PlanarBufID, UINT8 u8FrameRate); + * @retval 0 Success + * @retval <0 Error code + * + * @details This function configure callback function and set trigger level + */ +INT32 CAP_InstallCallback(E_CAP_INT_TYPE eIntType, PFN_CAP_CALLBACK pfnCallback, PFN_CAP_CALLBACK *pfnOldCallback) +{ + if (eIntType == eCAP_VINTF) + { + *pfnOldCallback = pfnCAP_IntHandlerTable[0]; + pfnCAP_IntHandlerTable[0] = (PFN_CAP_CALLBACK)(pfnCallback); + } + else if (eIntType == eCAP_ADDRMINTF) + { + *pfnOldCallback = pfnCAP_IntHandlerTable[1]; + pfnCAP_IntHandlerTable[1] = (PFN_CAP_CALLBACK)(pfnCallback); + } + else if (eIntType == eCAP_MEINTF) + { + *pfnOldCallback = pfnCAP_IntHandlerTable[2]; + pfnCAP_IntHandlerTable[2] = (PFN_CAP_CALLBACK)(pfnCallback); + } + else if (eIntType == eCAP_MDINTF) + { + *pfnOldCallback = pfnCAP_IntHandlerTable[3]; + pfnCAP_IntHandlerTable[3] = (PFN_CAP_CALLBACK)(pfnCallback); + } + else + return E_CAP_INVALID_INT; + return Successful; +} + +/** + * @brief Enable videoIn interrupt. + * + * @param[in] eIntType Interrupt type. Incuding: + * - \ref eCAP_MDINTF + * - \ref eCAP_ADDRMINTF + * - \ref eCAP_MEINTF + * - \ref eCAP_VINTF + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to enable videoIn interrupt. + */ +INT32 CAP_EnableInt(E_CAP_INT_TYPE eIntType) +{ + switch (eIntType) + { + case eCAP_MDINTF: + case eCAP_ADDRMINTF: + case eCAP_MEINTF: + case eCAP_VINTF: + outp32(REG_CAP_INT, inp32(REG_CAP_INT) | eIntType); + break; + default: + return E_CAP_INVALID_INT; + } + return Successful; +} + +/** + * @brief Disable videoIn interrupt + * + * @param[in] eIntType Interrupt type. Incuding: + * - \ref eCAP_MDINTF + * - \ref eCAP_ADDRMINTF + * - \ref eCAP_MEINTF + * - \ref eCAP_VINTF + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to disable videoIn interrupt. + */ +INT32 CAP_DisableInt(E_CAP_INT_TYPE eIntType) +{ + switch (eIntType) + { + case eCAP_MDINTF: + case eCAP_ADDRMINTF: + case eCAP_MEINTF: + case eCAP_VINTF: + outp32(REG_CAP_INT, inp32(REG_CAP_INT) & ~eIntType); + break; + default: + return E_CAP_INVALID_INT; + } + return Successful; +} + +/** + * @brief Check videoIn interrupt + * + * @param[in] eIntType Interrupt type. Incuding: + * - \ref eCAP_MDINTF + * - \ref eCAP_ADDRMINTF + * - \ref eCAP_MEINTF + * - \ref eCAP_VINTF + * @retval 1 Enable + * @retval 0 Disable + * + * @details This function is used to check videoIn interrupt. + */ +BOOL CAP_IsIntEnabled(E_CAP_INT_TYPE eIntType) +{ + UINT32 u32IntEnable = inp32(REG_CAP_INT); + switch (eIntType) + { + case eCAP_MDINTF: + u32IntEnable = u32IntEnable & eCAP_MDINTF; + break; + case eCAP_ADDRMINTF: + u32IntEnable = u32IntEnable & eCAP_ADDRMINTF; + break; + case eCAP_MEINTF: + u32IntEnable = u32IntEnable & eCAP_MEINTF; + break; + case eCAP_VINTF: + u32IntEnable = u32IntEnable & eCAP_VINTF; + break; + } + return (u32IntEnable ? TRUE : FALSE); +} + +/** + * @brief Clear videoIn interrupt flag. + * + * @param[in] eIntType Interrupt type. Incuding: + * - \ref eCAP_MDINTF + * - \ref eCAP_ADDRMINTF + * - \ref eCAP_MEINTF + * - \ref eCAP_VINTF + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to clear videoIn interrupt flag. + */ +INT32 CAP_ClearInt(E_CAP_INT_TYPE eIntType) +{ + UINT32 u32IntChannel = eIntType >> 16; + switch (eIntType) + { + case eCAP_MDINTF: + outp32(REG_CAP_INT, (inp32(REG_CAP_INT) & ~((eCAP_ADDRMINTF | eCAP_MEINTF | eCAP_VINTF) >> 16)) | + u32IntChannel); + break; + case eCAP_ADDRMINTF: + outp32(REG_CAP_INT, (inp32(REG_CAP_INT) & ~((eCAP_MDINTF | eCAP_MEINTF | eCAP_VINTF) >> 16)) | + u32IntChannel); + break; + case eCAP_MEINTF: + outp32(REG_CAP_INT, (inp32(REG_CAP_INT) & ~((eCAP_MDINTF | eCAP_ADDRMINTF | eCAP_VINTF) >> 16)) | + u32IntChannel); + break; + case eCAP_VINTF: + outp32(REG_CAP_INT, (inp32(REG_CAP_INT) & ~((eCAP_MDINTF | eCAP_MEINTF | eCAP_ADDRMINTF) >> 16)) | + u32IntChannel); + break; + default: + return E_CAP_INVALID_INT; + } + return Successful; + + +} + +/** + * @brief Polling videoIn interrupt flag. + * + * @param[in] eIntType Interrupt type. Incuding: + * - \ref eCAP_MDINTF + * - \ref eCAP_ADDRMINTF + * - \ref eCAP_MEINTF + * - \ref eCAP_VINTF + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to poll videoIn interrupt flag. + */ +BOOL CAP_PollInt(E_CAP_INT_TYPE eIntType) +{ + UINT32 u32IntStatus = inp32(REG_CAP_INT); + switch (eIntType) + { + case eCAP_MDINTF: + u32IntStatus = u32IntStatus & (eCAP_MDINTF >> 16); + break; + case eCAP_ADDRMINTF: + u32IntStatus = u32IntStatus & (eCAP_ADDRMINTF >> 16); + break; + case eCAP_MEINTF: + u32IntStatus = u32IntStatus & (eCAP_MEINTF >> 16); + break; + case eCAP_VINTF: + u32IntStatus = u32IntStatus & (eCAP_VINTF >> 16); + break; + } + return (u32IntStatus ? TRUE : FALSE); +} + +/** + * @brief Enable engine clock and turn on the pipe. + * + * @param[in] bEngEnable Enable engine clock. + * 1 : Enable engine clock. + * 0 : Disable engine clock. + * @param[in] ePipeEnable Enable pipe type. Incuding: + * - \ref eCAP_BOTH_PIPE_DISABLE + * - \ref eCAP_PLANAR + * - \ref eCAP_PACKET + * - \ref eCAP_BOTH_PIPE_ENABLE + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to enable engine clock and pipe type. + */ +void CAP_SetPipeEnable( + BOOL bEngEnable, + E_CAP_PIPE ePipeEnable +) +{ + outp32(REG_CAP_CTL, (inp32(REG_CAP_CTL) & ~(CAPEN | PKTEN | PLNEN)) + | (((bEngEnable ? CAPEN : 0x0)) + // | ((ePipeEnable & ~(PKTEN | PLNEN))<<5)) ); + | ((ePipeEnable & 0x03) << 5))); +} // DrvVideoIn_SetPipeEnable + +/** + * @brief Get engine clock and pipe type. + * + * @param[out] pbEngEnable Enable engine clock. + * 1 : Enable engine clock. + * 0 : Disable engine clock. + * @param[out] pePipeEnable Pipe type. Incuding: + * - \ref eCAP_BOTH_PIPE_DISABLE + * - \ref eCAP_PLANAR + * - \ref eCAP_PACKET + * - \ref eCAP_BOTH_PIPE_ENABLE + * @return None + * + * @details This function is used to get engin clock and pipe type. + */ +void CAP_GetPipeEnable(PBOOL pbEngEnable, E_CAP_PIPE *pePipeEnable) +{ + UINT32 u32Temp = inp32(REG_CAP_CTL); + + *pbEngEnable = (u32Temp & CAPEN) ? TRUE : FALSE; + *pePipeEnable = (E_CAP_PIPE)((u32Temp & (PKTEN | PLNEN)) >> 5); +} // DrvVideoIn_GetPipeEnable + + +/** + * @brief Set Shadow(Update) Register + * + * @details This function is used to reload frame buffer address after + * setting shoaw(update) register. + */ +void CAP_SetShadowRegister(void) +{ + outp32(REG_CAP_CTL, inp32(REG_CAP_CTL) | UPDATE); +} // DrvVideoIn_SetShadowRegister + + +/** + * @brief Set sensor polarity. + * + * @param[in] bVsync Sensor Vsync Polarity. + * 1 : High Active + * 0 : Low Active + * @param[in] bHsync Sensor Hsync Polarity. + * 1 : High Active + * 0 : Low Active + * @param[in] bPixelClk Sensor Vsync Polarity. + * 1 : Falling Edge + * 0 : Rising Edig + * @return None + * + * @details This function is used to set sensor polarity. + */ +void CAP_SetSensorPolarity(BOOL bVsync, BOOL bHsync, BOOL bPixelClk) +{ + UINT32 u32Polarity, u32RegVal; + u32RegVal = inp32(REG_CAP_PAR); + //sysprintf("Enter Register addr = 0x%x\n", (REG_CAP_PAR)); + //sysprintf("Enter Register value = 0x%x\n", u32RegVal); + u32Polarity = (((bVsync ? VSP : 0x0) | (bHsync ? HSP : 0x0)) | (bPixelClk ? PCLKP : 0x0)); + u32RegVal = (inp32(REG_CAP_PAR) & ~(VSP | HSP | PCLKP)) ; + //sysprintf("REG_VPEPAR = 0x%x", (u32RegVal | u32Polarity)); + outp32((REG_CAP_PAR), (u32RegVal | u32Polarity)); +} + +/** + * @brief Get sensor polarity. + * + * @param[out] pbVsync Sensor Vsync Polarity. + * 1 : High Active + * 0 : Low Active + * @param[out] pbHsync Sensor Hsync Polarity. + * 1 : High Active + * 0 : Low Active + * @param[out] pbPixelClk Sensor Vsync Polarity. + * 1 : Falling Edge + * 0 : Rising Edig + * @return None + * + * @details This function is used to get sensor polarity. + */ +void CAP_GetSensorPolarity(PBOOL pbVsync, PBOOL pbHsync, PBOOL pbPixelClk) +{ + UINT32 u32Temp = inp32(REG_CAP_PAR); + + *pbVsync = (u32Temp & VSP) ? TRUE : FALSE; + *pbHsync = (u32Temp & HSP) ? TRUE : FALSE; + *pbPixelClk = (u32Temp & PCLKP) ? TRUE : FALSE; +} + +/** + * @brief Set data format and order. + * + * @param[in] eInputOrder Data order for input format.Including : + * - \ref eCAP_IN_UYVY = Y0 U0 Y1 V0 + * - \ref eCAP_IN_YUYV = Y0 V0 Y1 U0 + * - \ref eCAP_IN_VYUY = U0 Y0 V0 Y1 + * - \ref eCAP_IN_YVYU = V0 Y0 U0 Y1 + * @param[in] eInputFormat Input data format.Including : + * - \ref eCAP_IN_YUV422 + * - \ref eCAP_IN_RGB565 + * @param[in] eOutputFormat Sensor Vsync Polarity.Including : + * - \ref eCAP_OUT_YUV422 = YCbCr422 + * - \ref eCAP_OUT_ONLY_Y = only output Y + * - \ref eCAP_OUT_RGB555 = rgb555 + * - \ref eCAP_OUT_RGB565 = rgb565 + * @return None + * + * @details This function is used to set data format and order. + */ +void CAP_SetDataFormatAndOrder(E_CAP_ORDER eInputOrder, E_CAP_IN_FORMAT eInputFormat, E_CAP_OUT_FORMAT eOutputFormat) +{ + outp32((REG_CAP_PAR), (inp32(REG_CAP_PAR) & ~(OUTFMT | INDATORD | INFMT)) + | ((((eInputOrder << 2) & INDATORD) + | (eInputFormat & INFMT)) + | ((eOutputFormat << 4) & OUTFMT))); +} // DrvVideoIn_SetDataFormatAndOrder + +/** + * @brief Get data format and order. + * + * @param[out] peInputOrder Data order for input format.Including : + * - \ref eCAP_IN_UYVY + * - \ref eCAP_IN_YUYV + * - \ref eCAP_IN_VYUY + * - \ref eCAP_IN_YVYU + * @param[out] peInputFormat Input data format.Including : + * - \ref eCAP_IN_YUV422 + * - \ref eCAP_IN_RGB565 + * @param[out] peOutputFormat Sensor Vsync Polarity.Including : + * - \ref eCAP_OUT_YUV422 = YCbCr422 + * - \ref eCAP_OUT_ONLY_Y = only output Y + * - \ref eCAP_OUT_RGB555 = rgb555 + * - \ref eCAP_OUT_RGB565 = rgb565 + * @return None + * + * @details This function is used to get data format and order. + */ +void CAP_GetDataFormatAndOrder(E_CAP_ORDER *peInputOrder, E_CAP_IN_FORMAT *peInputFormat, E_CAP_OUT_FORMAT *peOutputFormat) +{ + UINT32 u32Temp = inp32(REG_CAP_PAR); + + *peInputOrder = (E_CAP_ORDER)((u32Temp & INDATORD) >> 2); + *peInputFormat = (E_CAP_IN_FORMAT)(u32Temp & INFMT); + *peOutputFormat = (E_CAP_OUT_FORMAT)((u32Temp & OUTFMT) >> 4); +} + +/** + * @brief Set planar format. + * + * @param[in] ePlanarFmt Data order for input format.Including : + * - \ref eCAP_PLANAR_YUV422 + * - \ref eCAP_PLANAR_YUV420 + * @return None + * + * @details This function is used to set planar format. + */ +void CAP_SetPlanarFormat(E_CAP_PLANAR_FORMAT ePlanarFmt) +{ + switch (ePlanarFmt) + { + case eCAP_PLANAR_YUV422: + outp32((REG_CAP_PAR), (inp32(REG_CAP_PAR) & ~(PLNFMT))); + break; + case eCAP_PLANAR_YUV420: + outp32((REG_CAP_PAR), ((inp32(REG_CAP_PAR) | (PLNFMT)))); + break; + } +} + +/** + * @brief Get planar format. + * + * @retval - \ref eCAP_PLANAR_YUV422 : Planar format is YUV420. + * @retval - \ref eCAP_PLANAR_YUV420 : Planar format is YUV422. + * + * @details This function is used to get planar format. + */ +BOOL CAP_GetPlanarFormat(void) +{ + return ((inp32(REG_CAP_PAR) & PLNFMT) >> 7); +} + +/** + * @brief Set motion detection parameter. + * + * @param[in] bEnable Enable Motion Detection.Including : + * 0 : Disable motion detection. + * 1 : Enable motion detection. + * @param[in] bBlockSize Motion Detection Block Size.Including : + * 0 : Block size is set to 16x16. + * 1 : Block size is set to 8x8. + * @param[in] bSaveMode Motion Detection Save Mode.Including : + * 0 : 1 bit DIFF + 7 Y Differential. + * 1 : 1 bit DIFF only. + * @return None + * + * @details This function is used to set motion detection parameter. + */ +void CAP_SetMotionDet(BOOL bEnable, BOOL bBlockSize, BOOL bSaveMode) +{ + outp32(REG_CAP_MD, (inp32(REG_CAP_MD) & ~(MDSM | MDBS | MDEN)) | + (((bEnable ? MDEN : 0) | (bBlockSize ? MDBS : 0)) | + (bSaveMode ? MDSM : 0))); +} + +/** + * @brief Get motion detection parameter. + * + * @param[out] pbEnable Enable Motion Detection.Including : + * 0 : Disable motion detection. + * 1 : Enable motion detection. + * @param[out] pbBlockSize Motion Detection Block Size.Including : + * 0 : Block size is set to 16x16. + * 1 : Block size is set to 8x8. + * @param[out] pbSaveMode Motion Detection Save Mode.Including : + * 0 : 1 bit DIFF + 7 Y Differential. + * 1 : 1 bit DIFF only. + * @return None + * + * @details This function is used to get motion detection parameter. + */ +void CAP_GetMotionDet(PBOOL pbEnable, PBOOL pbBlockSize, PBOOL pbSaveMode) +{ + UINT32 u32RegData = inp32(REG_CAP_MD); + *pbEnable = (u32RegData & MDEN); + *pbBlockSize = (u32RegData & MDBS) >> 8; + *pbSaveMode = (u32RegData & MDSM) >> 9; +} + +/** + * @brief Set motion detection parameter externtion. + * + * @param[in] u32DetFreq Motion Detection frequency.Including : + * 0 : Each frame + * 1 : Every 2 frame + * 2 : Every 3 frame + * 3 : Every 4 frame + * @param[in] u32Threshold Motion detection threshold.It should be 0~31. + * + * @param[in] u32OutBuffer Motion Detection Output Address Register.(Word Alignment) + * + * @param[in] u32LumBuffer Motion Detection Temp Y Output Address Register.(Word Alignment) + * + * @return None + * + * @details This function is used to set motion detection parameter externtion. + */ +void CAP_SetMotionDetEx(UINT32 u32DetFreq, UINT32 u32Threshold, UINT32 u32OutBuffer, UINT32 u32LumBuffer) +{ + outp32(REG_CAP_MD, (inp32(REG_CAP_MD) & ~MDDF) | ((u32DetFreq << 10) & MDDF)); + outp32(REG_CAP_MD, (inp32(REG_CAP_MD) & ~MDTHR) | ((u32Threshold << 16) & MDTHR)); + outp32(REG_CAP_MDADDR, u32OutBuffer); + outp32(REG_CAP_MDYADDR, u32LumBuffer); +} + +/** + * @brief Get motion detection parameter externtion. + * + * @param[out] pu32DetFreq Motion Detection frequency.Including : + * 0 : Each frame + * 1 : Every 2 frame + * 2 : Every 3 frame + * 3 : Every 4 frame + * @param[out] pu32Threshold Motion detection threshold.It should be 0~31. + * + * @param[out] pu32OutBuffer Motion Detection Output Address Register.(Word Alignment) + * + * @param[out] pu32LumBuffer Motion Detection Temp Y Output Address Register.(Word Alignment) + * + * @return None + * + * @details This function is used to get motion detection parameter externtion. + */ +void CAP_GetMotionDetEx(PUINT32 pu32DetFreq, PUINT32 pu32Threshold, PUINT32 pu32OutBuffer, PUINT32 pu32LumBuffer) +{ + UINT32 u32RegData; + u32RegData = inp32(REG_CAP_MD); + *pu32DetFreq = u32RegData & MDDF; + *pu32Threshold = u32RegData & MDTHR; + *pu32OutBuffer = inp32(REG_CAP_MDADDR); + *pu32LumBuffer = inp32(REG_CAP_MDYADDR); +} + +/** + * @brief Set motion detection frequency. + * + * @param[in] u32DetFreq Motion Detection frequency.Including : + * 0 : Each frame + * 1 : Every 2 frame + * 2 : Every 3 frame + * 3 : Every 4 frame + * @return None + * + * @details This function is used to set motion detection frequency. + */ +void CAP_SetMotionDetFreq(UINT32 u32DetFreq) +{ + outp32(REG_CAP_MD, (inp32(REG_CAP_MD) & ~MDDF) | + ((u32DetFreq << 10) & MDDF)); +} + +/** + * @brief Get motion detection frequency. + * + * @param[out] pu32DetFreq Motion Detection frequency.Including : + * 0 : Each frame + * 1 : Every 2 frame + * 2 : Every 3 frame + * 3 : Every 4 frame + * @return None + * + * @details This function is used to get motion detection frequency. + */ +void CAP_GetMotionDetFreq(PUINT32 pu32DetFreq) +{ + UINT32 u32RegData; + u32RegData = inp32(REG_CAP_MD); + *pu32DetFreq = u32RegData & MDDF; +} + +/** + * @brief Set One shutte or continuous mode. + * + * @param[in] bIsOneSutterMode Enable One shutte.Including : + * 1 : Enable One shutte mode. + * 0 : Disable One shutte mode. + * @return None + * + * @details This function is used to set one shutte or continuous mode. + * Image capture interface automatically disable the capture + * inteface after a frame bad been captured. + */ +void CAP_SetOperationMode(BOOL bIsOneSutterMode) +{ + outp32(REG_CAP_CTL, (inp32(REG_CAP_CTL) & ~SHUTTER) | + ((bIsOneSutterMode << 16) & SHUTTER)); +} // DrvVideoIn_SetOperationMode + +/** + * @brief Get One shutte or continuous mode. + * + * @retval 1 : Disable one shutte mode + * @retval 0 : Enable one shutte mode + * + * @details This function is used to get one shutte or continuous mode. + * Image capture interface automatically disable the capture + * inteface after a frame bad been captured. + */ +BOOL CAP_GetOperationMode(void) +{ + return ((inp32(REG_CAP_CTL) & SHUTTER) ? TRUE : FALSE); +} // DrvVideoIn_GetOperationMode + + +/** + * @brief Get packet/planar processed data count. + * + * @param[in] ePipe Pipe type. Including : + * - \ref eCAP_PACKET + * - \ref eCAP_PLANAR + * + * @return Get current packet/planar processed data count. + * + * @details This function is used to get packet/planar processed data count. + */ +UINT32 CAP_GetProcessedDataCount(E_CAP_PIPE ePipe) +{ + if (ePipe == eCAP_PACKET) + return inp32(REG_CAP_CURADDRP); /* Packet pipe */ + else if (ePipe == eCAP_PLANAR) + return inp32(REG_CAP_CURADDRY); /* Planar pipe */ + else + return 0; +} + + +/** + * @brief Set cropping window vertical/horizontal starting address. + * + * @param[in] u32VerticalStart Cropping window vertical starting address. + * @param[in] u32HorizontalStart Cropping window horizontal starting address. + * + * @return None. + * + * @details This function is used to set cropping window vertical/horizontal starting address. + */ +void CAP_SetCropWinStartAddr(UINT32 u32VerticalStart, UINT32 u32HorizontalStart) +{ + outp32(REG_CAP_CWSP, (inp32(REG_CAP_CWSP) & ~(CWSADDRV | CWSADDRH)) //(Y|X) + | ((u32VerticalStart << 16) + | u32HorizontalStart)); +} + + +/** + * @brief Get cropping window vertical/horizontal starting address. + * + * @param[out] pu32VerticalStart Cropping window vertical starting address. + * @param[out] pu32HorizontalStart Cropping window horizontal starting address. + * + * @return None. + * + * @details This function is used to get cropping window vertical/horizontal starting address. + */ +void CAP_GetCropWinStartAddr(PUINT32 pu32VerticalStart, PUINT32 pu32HorizontalStart) +{ + UINT32 u32Temp = inp32(REG_CAP_CWSP); + + *pu32VerticalStart = (u32Temp & CWSADDRV) >> 16; + *pu32HorizontalStart = u32Temp & CWSADDRH; +} + +/** + * @brief Set cropping window size. + * + * @param[in] u32Width Cropping window width. + * @param[in] u32Height Cropping window heigh. + * + * @return None. + * + * @details This function is used to set cropping window size. + */ +void CAP_SetCropWinSize(UINT32 u32Height, UINT32 u32Width) +{ + outp32(REG_CAP_CWS, (inp32(REG_CAP_CWS) & ~(CWH | CWW)) + | ((u32Height << 16) + | u32Width)); +} + + +/** + * @brief Get cropping window size. + * + * @param[out] pu32Width Cropping window width. + * @param[out] pu32Height Cropping window heigh. + * + * @return None. + * + * @details This function is used to get cropping window size. + */ +void CAP_GetCropWinSize(PUINT32 pu32Height, PUINT32 pu32Width) +{ + UINT32 u32Temp = inp32(REG_CAP_CWS); + + *pu32Height = (u32Temp & CWH) >> 16; + *pu32Width = u32Temp & CWW; +} + +/** + * @brief Set packet/planar scaling vertical factor. + * + * @param[in] ePipe Pipe type.Including. + * - \ref eCAP_PACKET. + * - \ref eCAP_PLANAR. + * @param[in] u16Numerator Scaling Vertical Factor N. + * @param[in] u16Denominator Scaling Vertical Factor M. + * + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to set packet/planar scaling vertical factor. + * The output image width will be equal to the image width * N/M. + * Note: The value of N must be equal to or less than M + */ +INT32 CAP_SetVerticalScaleFactor(E_CAP_PIPE ePipe, UINT16 u16Numerator, UINT16 u16Denominator) +{ + UINT8 u8NumeratorL = u16Numerator & 0xFF, u8NumeratorH = u16Numerator >> 8; + UINT8 u8DenominatorL = u16Denominator & 0xFF, u8DenominatorH = u16Denominator >> 8; + if (ePipe == eCAP_PACKET) + { + outp32(REG_CAP_PKTSL, (inp32(REG_CAP_PKTSL) & ~(PKTSVNL | PKTSVML)) + | ((u8NumeratorL << 24) + | (u8DenominatorL << 16))); + outp32(REG_CAP_PKTSM, (inp32(REG_CAP_PKTSM) & ~(PKTSHMH | PKTSVMH)) + | ((u8NumeratorH << 24) + | (u8DenominatorH << 16))); + } + else if (ePipe == eCAP_PLANAR) + { + outp32(REG_CAP_PLNSL, (inp32(REG_CAP_PLNSL) & ~(PKTSVNL | PKTSVML)) + | ((u8NumeratorL << 24) + | (u8DenominatorL << 16))); + outp32(REG_CAP_PLNSM, (inp32(REG_CAP_PLNSM) & ~(PKTSHMH | PKTSVMH)) + | ((u8NumeratorH << 24) + | (u8DenominatorH << 16))); + } + else + return E_CAP_INVALID_PIPE; + return Successful; +} + +/** + * @brief Get packet/planar scaling vertical factor. + * + * @param[in] ePipe Pipe type.Including. + * - \ref eCAP_PACKET. + * - \ref eCAP_PLANAR. + * @param[out] pu16Numerator Scaling Vertical Factor N. + * @param[out] pu16Denominator Scaling Vertical Factor M. + * + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to get packet/planar scaling vertical factor. + * The output image width will be equal to the image width * N/M. + * Note: The value of N must be equal to or less than M + */ +INT32 DrvCAP_GetVerticalScaleFactor(E_CAP_PIPE ePipe, PUINT16 pu16Numerator, PUINT16 pu16Denominator) +{ + UINT32 u32Temp1, u32Temp2; + if (ePipe == eCAP_PACKET) + { + u32Temp1 = inp32(REG_CAP_PKTSL); + u32Temp2 = inp32(REG_CAP_PKTSM); + } + else if (ePipe == eCAP_PLANAR) + { + u32Temp1 = inp32(REG_CAP_PLNSL); + u32Temp2 = inp32(REG_CAP_PLNSM); + } + else + return E_CAP_INVALID_PIPE; + *pu16Numerator = ((u32Temp1 & PKTSVNL) >> 24) | (((u32Temp2 & PKTSHMH) >> 24) << 8); + *pu16Denominator = (u32Temp1 & PKTSVML) >> 16 | (((u32Temp2 & PKTSVMH) >> 16) << 8); + return Successful; +} + +/** + * @brief Set packet/planar scaling horizontal factor. + * + * @param[in] bPipe Pipe type.Including. + * - \ref eCAP_PACKET. + * - \ref eCAP_PLANAR. + * @param[in] u16Numerator Scaling Horizontal Factor N. + * @param[in] u16Denominator Scaling Horizontal Factor M. + * + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to set packet/planar scaling horizontal factor. + * The output image width will be equal to the image width * N/M. + * Note: The value of N must be equal to or less than M + */ +INT32 CAP_SetHorizontalScaleFactor(E_CAP_PIPE bPipe, UINT16 u16Numerator, UINT16 u16Denominator) +{ + UINT8 u8NumeratorL = u16Numerator & 0xFF, u8NumeratorH = u16Numerator >> 8; + UINT8 u8DenominatorL = u16Denominator & 0xFF, u8DenominatorH = u16Denominator >> 8; + if (bPipe == eCAP_PACKET) + { + outp32(REG_CAP_PKTSL, (inp32(REG_CAP_PKTSL) & ~(PKTSHNL | PKTSHML)) + | ((u8NumeratorL << 8) + | u8DenominatorL)); + outp32(REG_CAP_PKTSM, (inp32(REG_CAP_PKTSM) & ~(PKTSHNH | PKTSHMH)) + | ((u8NumeratorH << 8) + | u8DenominatorH)); + } + else if (bPipe == eCAP_PLANAR) + { + outp32(REG_CAP_PLNSL, (inp32(REG_CAP_PLNSL) & ~(PKTSHNL | PKTSHML)) + | ((u8NumeratorL << 8) + | u8DenominatorL)); + outp32(REG_CAP_PLNSM, (inp32(REG_CAP_PLNSM) & ~(PKTSHNH | PKTSHMH)) + | ((u8NumeratorH << 8) + | u8DenominatorH)); + } + else + return E_CAP_INVALID_PIPE; + return Successful; +} + +/** + * @brief Get packet/planar scaling horizontal factor. + * + * @param[in] bPipe Pipe type.Including. + * - \ref eCAP_PACKET. + * - \ref eCAP_PLANAR. + * @param[out] pu16Numerator Scaling Horizontal Factor N. + * @param[out] pu16Denominator Scaling Horizontal Factor M. + * + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to get packet/planar scaling horizontal factor. + * The output image width will be equal to the image width * N/M. + * Note: The value of N must be equal to or less than M. + */ +INT32 CAP_GetHorizontalScaleFactor(E_CAP_PIPE bPipe, PUINT16 pu16Numerator, PUINT16 pu16Denominator) +{ + UINT32 u32Temp1, u32Temp2; + if (bPipe == eCAP_PACKET) + { + u32Temp1 = inp32(REG_CAP_PKTSL); + u32Temp2 = inp32(REG_CAP_PKTSM); + } + else if (bPipe == eCAP_PLANAR) + { + u32Temp1 = inp32(REG_CAP_PLNSL); + u32Temp2 = inp32(REG_CAP_PLNSM); + } + else + return E_CAP_INVALID_PIPE; + *pu16Numerator = ((u32Temp1 & PKTSHNL) >> 8) | (u32Temp2 & PKTSHNH); + *pu16Denominator = (u32Temp1 & PKTSHML) | ((u32Temp2 & PKTSHMH) << 8); + return Successful; +} + +/** + * @brief Set scaling frame rate factor. + * + * @param[in] u8Numerator Scaling Frame Rate Factor N. + * @param[in] u8Denominator Scaling Frame Rate Factor M. + * + * @return None. + * + * @details This function is used to set scaling frame rate factor.. + * The output image frame rate will be equal to input image frame rate * (N/M). + * Note: The value of N must be equal to or less than M. + */ +void DrvCAP_SetFrameRateScaleFactor(UINT8 u8Numerator, UINT8 u8Denominator) +{ + outp32(REG_CAP_FRCTL, (inp32(REG_CAP_FRCTL) & ~(FRN | FRM)) + | (((u8Numerator << 8) & FRN) + | (u8Denominator & FRM))); +} // DrvVideoIn_SetFrameRateScaleFactor + +/** + * @brief Get scaling frame rate factor. + * + * @param[out] pu8Numerator Scaling Frame Rate Factor N. + * @param[out] pu8Denominator Scaling Frame Rate Factor M. + * + * @return None. + * + * @details This function is used to get scaling frame rate factor.. + * The output image frame rate will be equal to input image frame rate * (N/M). + * Note: The value of N must be equal to or less than M. + */ +void DrvCAP_GetFrameRateScaleFactor(PUINT8 pu8Numerator, PUINT8 pu8Denominator) +{ + UINT32 u32Temp = inp32(REG_CAP_FRCTL); + + *pu8Numerator = (u32Temp & FRN) >> 8; + *pu8Denominator = u32Temp & FRM; +} + +/** + * @brief Set address match + * + * @param[in] u32AddressMatch Compare Memory Base Address.It should be 0~0xFFFFFFFF. + * + * @return None. + * + * @details This function is used to set compare memory base address. + */ +void DrvCAP_SetAddressMatch(UINT32 u32AddressMatch) +{ + outp32(REG_CAP_CMPADDR, u32AddressMatch); +} + +/** + * @brief Get address match + * + * @param[out] pu32AddressMatch Compare Memory Base Address.It should be 0~0xFFFFFFFF. + * + * @return None. + * + * @details This function is used to get compare memory base address. + */ +void CAP_GetAddressMatch(PUINT32 pu32AddressMatch) +{ + *pu32AddressMatch = inp32(REG_CAP_CMPADDR); +} + +/** + * @brief Set frame output pixel stride width. + * + * @param[in] u32PacketStride Packet frame output pixel stride width.It should be 0~0x3FFF. + * @param[in] u32PlanarStride Planar frame output pixel stride width.It should be 0~0x3FFF. + * + * @return None. + * + * @details This function is used to set frame output pixel stride width. + */ +void CAP_SetStride(UINT32 u32PacketStride, UINT32 u32PlanarStride) +{ + outp32(REG_CAP_STRIDE, ((u32PlanarStride << 16) & PLNSTRIDE) | + (u32PacketStride & PKTSTRIDE)); +} + +/** + * @brief Get frame output pixel stride width. + * + * @param[out] pu32PacketStride Packet frame output pixel stride width.It should be 0~0x3FFF. + * @param[out] pu32PlanarStride Planar frame output pixel stride width.It should be 0~0x3FFF. + * + * @return None. + * + * @details This function is used to get frame output pixel stride width. + */ +void CAP_GetStride(PUINT32 pu32PacketStride, PUINT32 pu32PlanarStride) +{ + UINT32 u32Tmp = inp32(REG_CAP_STRIDE); + *pu32PlanarStride = (u32Tmp & PLNSTRIDE) >> 16; + *pu32PacketStride = u32Tmp & PKTSTRIDE; +} + +/** + * @brief Set system memory packet/planar base address. + * + * @param[in] ePipe Pipe type.Including: + * - \ref eCAP_PACKET + * - \ref eCAP_PLANAR + * + * @param[in] eBuf Packet/Planar buffer address. + * - \ref eCAP_BUF0 : + * Packet : Packet base address 0 + * Planar : Planar Y base address + * - \ref eCAP_BUF1 + * Packet : Packet base address 1 + * Planar : Planar U base address + * - \ref eCAP_BUF2 + * Packet : None. + * Planar : Planar V base address + * + * @param[in] u32BaseStartAddr System Memory Base Address.It should be 0~0xFFFFFFFF. + * + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to set system memory packet/planar base address. + */ +INT32 CAP_SetBaseStartAddress(E_CAP_PIPE ePipe, E_CAP_BUFFER eBuf, UINT32 u32BaseStartAddr) +{ + if (ePipe == eCAP_PACKET) + { + if (eBuf > eCAP_BUF1) + return E_CAP_INVALID_BUF; + outp32(REG_CAP_PKTBA0 + eBuf * 4, u32BaseStartAddr); + } + else if (ePipe == eCAP_PLANAR) + { + if (eBuf > eCAP_BUF2) + return E_CAP_INVALID_BUF; + outp32(REG_CAP_YBA + eBuf * 4, u32BaseStartAddr); + } + else + return E_CAP_INVALID_PIPE; + return Successful; +} + +/** + * @brief Get system memory packet/planar base address. + * + * @param[in] ePipe Pipe type.Including: + * - \ref eCAP_PACKET + * - \ref eCAP_PLANAR + * + * @param[in] eBuf Packet/Planar buffer address. + * - \ref eCAP_BUF0 : + * Packet : Packet base address 0 + * Planar : Planar Y base address + * - \ref eCAP_BUF1 + * Packet : Packet base address 1 + * Planar : Planar U base address + * - \ref eCAP_BUF2 + * Packet : None. + * Planar : Planar V base address + * + * @param[out] pu32BaseStartAddr System Memory Base Address.It should be 0~0xFFFFFFFF. + * + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to get system memory packet/planar base address. + */ +INT32 CAP_GetBaseStartAddress(E_CAP_PIPE ePipe, E_CAP_BUFFER eBuf, PUINT32 pu32BaseStartAddr) +{ + if (ePipe == eCAP_PACKET) + { + if (eBuf > eCAP_BUF1) + return E_CAP_INVALID_BUF; + *pu32BaseStartAddr = inp32(REG_CAP_PKTBA0 + eBuf * 4); + } + else if (ePipe == eCAP_PLANAR) + { + if (eBuf > eCAP_BUF2) + return E_CAP_INVALID_BUF; + *pu32BaseStartAddr = inp32(REG_CAP_YBA + eBuf * 4); + } + else + return E_CAP_INVALID_PIPE; + return Successful; +} + +/** + * @brief Set standard CCIR656. + * + * @param[in] bIsStandard Standard CCIR656. + * - 1 : Standard CCIR656 mode. + * - 0 : Non-Standard CCIR656 mode. (OV7725 or Hynix 702) + * @return None. + * + * @details This function is used to set standard CCIR65/non-standard CCIR65. + */ +void CAP_SetStandardCCIR656(BOOL bIsStandard) +{ + if (bIsStandard == TRUE) + outp32(REG_CAP_PAR, inp32(REG_CAP_PAR) & ~FBB); // Standard + else + outp32(REG_CAP_PAR, inp32(REG_CAP_PAR) | FBB); // Non-Standard +} + +/** + * @brief Set color effect + * + * @param[in] eColorMode Available as following. + * - \ref eCAP_CEF_NORMAL : Normal Color. + * - \ref eCAP_CEF_SEPIA : Sepia effect, + * corresponding U,V component value is set at register - \ref REG_CAP_SEPIA. + * - \ref eCAP_CEF_NEGATIVE : Negative picture. + * - \ref eCAP_CEF_POSTERIZE : Posterize image, + * the Y, U, V components posterizing factor are set at register - \ref REG_CAP_POSTERIZE. + * + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to set color effect. + */ +INT32 CAP_SetColorEffect(E_CAP_CEF eColorMode) +{ + if (eColorMode > eCAP_CEF_POSTERIZE) + return E_CAP_INVALID_COLOR_MODE; + outp32(REG_CAP_PAR, (inp32(REG_CAP_PAR) & ~COLORCTL) | + (eColorMode << 11)); + return Successful; +} + +/** + * @brief Get color effect + * + * @param[out] peColorMode Available as following. + * - \ref eCAP_CEF_NORMAL : Normal Color. + * - \ref eCAP_CEF_SEPIA : Sepia effect, + * corresponding U,V component value is set at register - \ref REG_CAP_SEPIA. + * - \ref eCAP_CEF_NEGATIVE : Negative picture. + * - \ref eCAP_CEF_POSTERIZE : Posterize image, + * the Y, U, V components posterizing factor are set at register - \ref REG_CAP_POSTERIZE. + * + * @return None. + * + * @details This function is used to get color effect. + */ +void DrvCAP_GetColorEffect(E_CAP_CEF *peColorMode) +{ + UINT32 u32Tmp = inp32(REG_CAP_PAR); + *peColorMode = (E_CAP_CEF)((u32Tmp & COLORCTL) >> 11); +} + +/** + * @brief Set color effect parameter + * + * @param[in] u8YComp The constant Y component.If eColorMode is set to + * eCAP_CEF_SEPIA : the constant Y component in - \ref REG_CAP_SEPIA. + * eCAP_CEF_POSTERIZE : the constant Y component in - \ref REG_CAP_POSTERIZE. + * @param[in] u8UComp The constant U component. + * eCAP_CEF_SEPIA : the constant U component in - \ref REG_CAP_SEPIA. + * eCAP_CEF_POSTERIZE : the constant U component in - \ref REG_CAP_POSTERIZE. + * @param[in] u8VComp The constant V component. + * eCAP_CEF_SEPIA : the constant V component in - \ref REG_CAP_SEPIA. + * eCAP_CEF_POSTERIZE : the constant V component in - \ref REG_CAP_POSTERIZE. + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to set color effect parameter. + */ +INT32 CAP_SetColorEffectParameter(UINT8 u8YComp, UINT8 u8UComp, UINT8 u8VComp) +{ + UINT32 u32Tmp = inp32(REG_CAP_PAR); + UINT32 u32ColorMode = (u32Tmp & COLORCTL) >> 11; + if (u32ColorMode == eCAP_CEF_SEPIA) + { + outp32(REG_CAP_SEPIA, (((UINT32)u8UComp << 8) | u8VComp)); + } + else if (u32ColorMode == eCAP_CEF_POSTERIZE) + { + outp32(REG_CAP_POSTERIZE, (((UINT32)u8YComp << 16) | ((UINT32)u8UComp << 8) | u8VComp)); + } + else + { + return E_CAP_WRONG_COLOR_PARAMETER; + } + return Successful; +} + +/** + * @brief Get color effect parameter + * + * @param[out] pu8YComp The constant Y component.If eColorMode is set to + * eCAP_CEF_SEPIA : the constant Y component in - \ref REG_CAP_SEPIA. + * eCAP_CEF_POSTERIZE : the constant Y component in - \ref REG_CAP_POSTERIZE. + * @param[out] pu8UComp The constant U component. + * eCAP_CEF_SEPIA : the constant U component in - \ref REG_CAP_SEPIA. + * eCAP_CEF_POSTERIZE : the constant U component in - \ref REG_CAP_POSTERIZE. + * @param[out] pu8VComp The constant V component. + * eCAP_CEF_SEPIA : the constant V component in - \ref REG_CAP_SEPIA. + * eCAP_CEF_POSTERIZE : the constant V component in - \ref REG_CAP_POSTERIZE. + * @retval 0 Success + * @retval <0 Error code + * + * @details This function is used to get color effect parameter. + */ +INT32 CAP_GetColorEffectParameter(PUINT8 pu8YComp, PUINT8 pu8UComp, PUINT8 pu8VComp) +{ + UINT32 u32Tmp = inp32(REG_CAP_PAR); + UINT32 u32ColorMode = (u32Tmp & COLORCTL) >> 11; + if (u32ColorMode == eCAP_CEF_SEPIA) + { + u32Tmp = inp32(REG_CAP_SEPIA); + *pu8UComp = (u32Tmp & 0xFF00) >> 8; + *pu8VComp = u32Tmp & 0xFF; + } + else if (u32ColorMode == eCAP_CEF_POSTERIZE) + { + u32Tmp = inp32(REG_CAP_POSTERIZE); + *pu8YComp = (u32Tmp & 0xFF0000) >> 16; + *pu8UComp = (u32Tmp & 0xFF00) >> 8; + *pu8VComp = u32Tmp & 0xFF; + } + else + { + return E_CAP_WRONG_COLOR_PARAMETER; + } + return Successful; +} + +/// @cond HIDDEN_SYMBOLS +CAPDEV_T CAP = +{ + CAP_Init, // void (*Init)(BOOL bIsEnableSnrClock, E_CAP_SNR_SRC eSnrSrc, UINT32 u32SensorFreqKHz, E_CAP_DEV_TYPE eDevType): + CAP_Open, // INT32 (*Open)(UINT32 u32SensorFreqKHz); + CAP_Close, // void (*Close)(void); + CAP_SetPipeEnable, // void (*SetPipeEnable)(BOOL bEngEnable, E_CAP_PIPE ePipeEnable); + CAP_SetPlanarFormat, // void (*SetPlanarFormat)(E_CAP_PLANAR_FORMAT ePlanarFmt); + CAP_SetCropWinSize, // void (*SetCropWinSize)(UINT32 u32height, UINT32 u32width); + CAP_SetCropWinStartAddr, // void (*SetCropWinStartAddr)(UINT32 u32VerticalStart, UINT32 u32HorizontalStart); + CAP_SetStride, // void (*SetStride)(UINT32 u16packetstride, UINT32 u32planarstride); + CAP_GetStride, // void (*GetStride)(PUINT32 pu32PacketStride, PUINT32 pu32PlanarStride); + CAP_EnableInt, // INT32 (*EnableInt)(E_CAP_INT_TYPE eIntType); + CAP_DisableInt, // INT32 (*DisableInt)(E_CAP_INT_TYPE eIntType); + CAP_InstallCallback, // INT32 (*InstallCallback)(E_CAP_INT_TYPE eIntType, PFN_CAP_CALLBACK pfnCallback, PFN_CAP_CALLBACK *pfnOldCallback); + CAP_SetBaseStartAddress, // INT32 (*SetBaseStartAddress(E_CAP_PIPE ePipe, E_CAP_BUFFER eBuf, UINT32 u32BaseStartAddr); + CAP_SetOperationMode, // void (*SetOperationMode(BOOL bIsOneSutterMode); + CAP_GetOperationMode, // BOOL (*GetOperationMode)(void); + CAP_SetPacketFrameBufferControl, // void (*videoIn1_SetPacketFrameBufferControl)(BOOL bFrameSwitch, BOOL bFrameBufferSel); + CAP_SetSensorPolarity, // void (*videoIn1_SetSensorPolarity)(BOOL bVsync, BOOL bHsync, BOOL bPixelClk); + CAP_SetColorEffectParameter, // INT32 (*SetColorEffectParameter)(UINT8 u8YComp, UINT8 u8UComp, UINT8 u8VComp); + CAP_SetDataFormatAndOrder, // void (*SetDataFormatAndOrder)(E_CAP_ORDER eInputOrder, E_CAP_IN_FORMAT eInputFormat, E_CAP_OUT_FORMAT eOutputFormat) + CAP_SetMotionDet, // void (*SetMotionDet)(BOOL bEnable, BOOL bBlockSize,BOOL bSaveMode); + CAP_SetMotionDetEx, // void (*SetMotionDetEx)(UINT32 u32Threshold, UINT32 u32OutBuffer, UINT32 u32LumBuffer); + CAP_SetStandardCCIR656, // void (*SetStandardCcir656)(BOOL); + CAP_SetShadowRegister // void (*SetShadowRegister)(void); +}; +/// @endcond HIDDEN_SYMBOLS + +/*@}*/ /* end of group N9H30_CAP_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_CAP_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_crypto.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_crypto.c new file mode 100644 index 0000000000..498b333e62 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_crypto.c @@ -0,0 +1,394 @@ +/**************************************************************************//** + * @file crypto.c + * @version V1.10 + * $Revision: 3 $ + * $Date: 15/06/12 9:42a $ + * @brief Cryptographic Accelerator driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include +#include +#include "N9H30.h" +#include "nu_crypto.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_CRYPTO_Driver CRYPTO Driver + @{ +*/ + + +/** @addtogroup N9H30_CRYPTO_EXPORTED_FUNCTIONS CRYPTO Exported Functions + @{ +*/ + +/// @cond HIDDEN_SYMBOLS + +static uint32_t g_AES_CTL[4]; +static uint32_t g_TDES_CTL[4]; + +/// @endcond HIDDEN_SYMBOLS + +/** + * @brief Open PRNG function + * @param[in] u32KeySize is PRNG key size, including: + * - \ref PRNG_KEY_SIZE_64 + * - \ref PRNG_KEY_SIZE_128 + * - \ref PRNG_KEY_SIZE_192 + * - \ref PRNG_KEY_SIZE_256 + * @param[in] u32SeedReload is PRNG seed reload or not, including: + * - \ref PRNG_SEED_CONT + * - \ref PRNG_SEED_RELOAD + * @param[in] u32Seed The new seed. Only valid when u32SeedReload is PRNG_SEED_RELOAD. + * @return None + */ +void PRNG_Open(uint32_t u32KeySize, uint32_t u32SeedReload, uint32_t u32Seed) +{ + if (u32SeedReload) + CRPT->PRNG_SEED = u32Seed; + + CRPT->PRNG_CTL = (u32KeySize << CRPT_PRNG_CTL_KEYSZ_Pos) | + (u32SeedReload << CRPT_PRNG_CTL_SEEDRLD_Pos); +} + +/** + * @brief Start to generate one PRNG key. + * @return None + */ +void PRNG_Start(void) +{ + CRPT->PRNG_CTL |= CRPT_PRNG_CTL_START_Msk; +} + +/** + * @brief Read the PRNG key. + * @param[out] u32RandKey The key buffer to store newly generated PRNG key. + * @return None + */ +void PRNG_Read(uint32_t u32RandKey[]) +{ + uint32_t i, wcnt; + + wcnt = (((CRPT->PRNG_CTL & CRPT_PRNG_CTL_KEYSZ_Msk) >> CRPT_PRNG_CTL_KEYSZ_Pos) + 1U) * 2U; + + for (i = 0U; i < wcnt; i++) + { + u32RandKey[i] = CRPT->PRNG_KEY[i]; + } + + CRPT->PRNG_CTL &= ~CRPT_PRNG_CTL_SEEDRLD_Msk; +} + + +/** + * @brief Open AES encrypt/decrypt function. + * @param[in] u32Channel AES channel. Must be 0~3. + * @param[in] u32EncDec 1: AES encode; 0: AES decode + * @param[in] u32OpMode AES operation mode, including: + * - \ref AES_MODE_ECB + * - \ref AES_MODE_CBC + * - \ref AES_MODE_CFB + * - \ref AES_MODE_OFB + * - \ref AES_MODE_CTR + * - \ref AES_MODE_CBC_CS1 + * - \ref AES_MODE_CBC_CS2 + * - \ref AES_MODE_CBC_CS3 + * @param[in] u32KeySize is AES key size, including: + * - \ref AES_KEY_SIZE_128 + * - \ref AES_KEY_SIZE_192 + * - \ref AES_KEY_SIZE_256 + * @param[in] u32SwapType is AES input/output data swap control, including: + * - \ref AES_NO_SWAP + * - \ref AES_OUT_SWAP + * - \ref AES_IN_SWAP + * - \ref AES_IN_OUT_SWAP + * @return None + */ +void AES_Open(uint32_t u32Channel, uint32_t u32EncDec, + uint32_t u32OpMode, uint32_t u32KeySize, uint32_t u32SwapType) +{ + CRPT->AES_CTL = (u32Channel << CRPT_AES_CTL_CHANNEL_Pos) | + (u32EncDec << CRPT_AES_CTL_ENCRPT_Pos) | + (u32OpMode << CRPT_AES_CTL_OPMODE_Pos) | + (u32KeySize << CRPT_AES_CTL_KEYSZ_Pos) | + (u32SwapType << CRPT_AES_CTL_OUTSWAP_Pos); + g_AES_CTL[u32Channel] = CRPT->AES_CTL; +} + +/** + * @brief Start AES encrypt/decrypt + * @param[in] u32Channel AES channel. Must be 0~3. + * @param[in] u32DMAMode AES DMA control, including: + * - \ref CRYPTO_DMA_ONE_SHOT One shop AES encrypt/decrypt. + * - \ref CRYPTO_DMA_CONTINUE Continuous AES encrypt/decrypt. + * - \ref CRYPTO_DMA_LAST Last AES encrypt/decrypt of a series of AES_Start. + * @return None + */ +void AES_Start(int32_t u32Channel, uint32_t u32DMAMode) +{ + CRPT->AES_CTL = g_AES_CTL[u32Channel]; + CRPT->AES_CTL |= CRPT_AES_CTL_START_Msk | (u32DMAMode << CRPT_AES_CTL_DMALAST_Pos); +} + +/** + * @brief Set AES keys + * @param[in] u32Channel AES channel. Must be 0~3. + * @param[in] au32Keys An word array contains AES keys. + * @param[in] u32KeySize is AES key size, including: + * - \ref AES_KEY_SIZE_128 + * - \ref AES_KEY_SIZE_192 + * - \ref AES_KEY_SIZE_256 + * @return None + */ +void AES_SetKey(uint32_t u32Channel, uint32_t au32Keys[], uint32_t u32KeySize) +{ + int i, wcnt; + uint32_t *key_ptr; + + key_ptr = (uint32_t *)((uint32_t)&CRPT->AES0_KEY0 + (u32Channel * 0x3C)); + wcnt = 4 + u32KeySize * 2; + for (i = 0; i < wcnt; i++, key_ptr++) + *key_ptr = au32Keys[i]; +} + +/** + * @brief Set AES initial vectors + * @param[in] u32Channel AES channel. Must be 0~3. + * @param[in] au32IV A four entry word array contains AES initial vectors. + * @return None + */ +void AES_SetInitVect(uint32_t u32Channel, uint32_t au32IV[]) +{ + int i; + uint32_t *key_ptr; + + key_ptr = (uint32_t *)((uint32_t)&CRPT->AES0_IV0 + (u32Channel * 0x3C)); + for (i = 0; i < 4; i++, key_ptr++) + *key_ptr = au32IV[i]; +} + +/** + * @brief Set AES DMA transfer configuration. + * @param[in] u32Channel AES channel. Must be 0~3. + * @param[in] u32SrcAddr AES DMA source address + * @param[in] u32DstAddr AES DMA destination address + * @param[in] u32TransCnt AES DMA transfer byte count + * @return None + */ +void AES_SetDMATransfer(uint32_t u32Channel, uint32_t u32SrcAddr, + uint32_t u32DstAddr, uint32_t u32TransCnt) +{ + *(uint32_t *)((uint32_t)&CRPT->AES0_SADDR + (u32Channel * 0x3C)) = u32SrcAddr; + *(uint32_t *)((uint32_t)&CRPT->AES0_DADDR + (u32Channel * 0x3C)) = u32DstAddr; + *(uint32_t *)((uint32_t)&CRPT->AES0_CNT + (u32Channel * 0x3C)) = u32TransCnt; +} + +/** + * @brief Open TDES encrypt/decrypt function. + * @param[in] u32Channel TDES channel. Must be 0~3. + * @param[in] u32EncDec 1: TDES encode; 0: TDES decode + * @param[in] u32OpMode TDES operation mode, including: + * - \ref TDES_MODE_ECB + * - \ref TDES_MODE_CBC + * - \ref TDES_MODE_CFB + * - \ref TDES_MODE_OFB + * - \ref TDES_MODE_CTR + * @param[in] u32SwapType is TDES input/output data swap control and word swap control, including: + * - \ref TDES_NO_SWAP + * - \ref TDES_WHL_SWAP + * - \ref TDES_OUT_SWAP + * - \ref TDES_OUT_WHL_SWAP + * - \ref TDES_IN_SWAP + * - \ref TDES_IN_WHL_SWAP + * - \ref TDES_IN_OUT_SWAP + * - \ref TDES_IN_OUT_WHL_SWAP + * @return None + */ +void TDES_Open(uint32_t u32Channel, uint32_t u32EncDec, int32_t Is3DES, int32_t Is3Key, + uint32_t u32OpMode, uint32_t u32SwapType) +{ + g_TDES_CTL[u32Channel] = (u32Channel << CRPT_TDES_CTL_CHANNEL_Pos) | + (u32EncDec << CRPT_TDES_CTL_ENCRPT_Pos) | + u32OpMode | (u32SwapType << CRPT_TDES_CTL_BLKSWAP_Pos); + if (Is3DES) + { + g_TDES_CTL[u32Channel] |= CRPT_TDES_CTL_TMODE_Msk; + } + if (Is3Key) + { + g_TDES_CTL[u32Channel] |= CRPT_TDES_CTL_3KEYS_Msk; + } +} + +/** + * @brief Start TDES encrypt/decrypt + * @param[in] u32Channel TDES channel. Must be 0~3. + * @param[in] u32DMAMode TDES DMA control, including: + * - \ref CRYPTO_DMA_ONE_SHOT One shop TDES encrypt/decrypt. + * - \ref CRYPTO_DMA_CONTINUE Continuous TDES encrypt/decrypt. + * - \ref CRYPTO_DMA_LAST Last TDES encrypt/decrypt of a series of TDES_Start. + * @return None + */ +void TDES_Start(int32_t u32Channel, uint32_t u32DMAMode) +{ + g_TDES_CTL[u32Channel] |= CRPT_TDES_CTL_START_Msk | (u32DMAMode << CRPT_TDES_CTL_DMALAST_Pos); + CRPT->TDES_CTL = g_TDES_CTL[u32Channel]; +} + +/** + * @brief Set TDES keys + * @param[in] u32Channel TDES channel. Must be 0~3. + * @param[in] au8Keys The TDES keys. + * @return None + */ +void TDES_SetKey(uint32_t u32Channel, uint32_t au32Keys[3][2]) +{ + int i; + uint32_t *pu32TKey; + + pu32TKey = (uint32_t *)((uint32_t)&CRPT->TDES0_KEY1H + (0x40 * u32Channel)); + for (i = 0; i < 3; i++) + { + *pu32TKey = au32Keys[i][0]; /* TDESn_KEYxH */ + pu32TKey++; + *pu32TKey = au32Keys[i][1]; /* TDESn_KEYxL */ + pu32TKey++; + } +} + +/** + * @brief Set TDES initial vectors + * @param[in] u32Channel TDES channel. Must be 0~3. + * @param[in] u32IVH TDES initial vector high word. + * @param[in] u32IVL TDES initial vector low word. + * @return None + */ +void TDES_SetInitVect(uint32_t u32Channel, uint32_t u32IVH, uint32_t u32IVL) +{ + *(uint32_t *)((uint32_t)&CRPT->TDES0_IVH + 0x40 * u32Channel) = u32IVH; + *(uint32_t *)((uint32_t)&CRPT->TDES0_IVL + 0x40 * u32Channel) = u32IVL; +} + +/** + * @brief Set TDES DMA transfer configuration. + * @param[in] u32Channel TDES channel. Must be 0~3. + * @param[in] u32SrcAddr TDES DMA source address + * @param[in] u32DstAddr TDES DMA destination address + * @param[in] u32TransCnt TDES DMA transfer byte count + * @return None + */ +void TDES_SetDMATransfer(uint32_t u32Channel, uint32_t u32SrcAddr, + uint32_t u32DstAddr, uint32_t u32TransCnt) +{ + *(uint32_t *)((uint32_t)&CRPT->TDES0_SADDR + (u32Channel * 0x40)) = u32SrcAddr; + *(uint32_t *)((uint32_t)&CRPT->TDES0_DADDR + (u32Channel * 0x40)) = u32DstAddr; + *(uint32_t *)((uint32_t)&CRPT->TDES0_CNT + (u32Channel * 0x40)) = u32TransCnt; +} + +/** + * @brief Open SHA encrypt function. + * @param[in] u32OpMode SHA operation mode, including: + * - \ref SHA_MODE_SHA1 + * - \ref SHA_MODE_SHA224 + * - \ref SHA_MODE_SHA256 + * - \ref SHA_MODE_SHA384 + * - \ref SHA_MODE_SHA512 + * @param[in] u32SwapType is SHA input/output data swap control, including: + * - \ref SHA_NO_SWAP + * - \ref SHA_OUT_SWAP + * - \ref SHA_IN_SWAP + * - \ref SHA_IN_OUT_SWAP + * @param[in] hmac_key_len The length of HMAC key if HMAC is employed. + * If HMAC is not used, just give hmac_key_len a zero value. + * @return None + */ +void SHA_Open(uint32_t u32OpMode, uint32_t u32SwapType, int hmac_key_len) +{ + CRPT->HMAC_CTL = (u32OpMode << CRPT_HMAC_CTL_OPMODE_Pos) | + (u32SwapType << CRPT_HMAC_CTL_OUTSWAP_Pos); + + if (hmac_key_len > 0) + { + CRPT->HMAC_KEYCNT = hmac_key_len; + CRPT->HMAC_CTL |= CRPT_HMAC_CTL_HMACEN_Msk; + } +} + + +/** + * @brief Start SHA encrypt + * @param[in] u32DMAMode TDES DMA control, including: + * - \ref CRYPTO_DMA_ONE_SHOT One shop SHA encrypt. + * - \ref CRYPTO_DMA_CONTINUE Continuous SHA encrypt. + * - \ref CRYPTO_DMA_LAST Last SHA encrypt of a series of SHA_Start. + * @return None + */ +void SHA_Start(uint32_t u32DMAMode) +{ + CRPT->HMAC_CTL &= ~(0x7 << CRPT_HMAC_CTL_DMALAST_Pos); + CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk | (u32DMAMode << CRPT_HMAC_CTL_DMALAST_Pos); +} + +/** + * @brief Set SHA DMA transfer + * @param[in] u32SrcAddr SHA DMA source address + * @param[in] u32TransCnt SHA DMA transfer byte count + * @return None + */ +void SHA_SetDMATransfer(uint32_t u32SrcAddr, uint32_t u32TransCnt) +{ + CRPT->HMAC_SADDR = u32SrcAddr; + CRPT->HMAC_DMACNT = u32TransCnt; +} + +/** + * @brief Read the SHA digest. + * @param[out] u32Digest The SHA encrypt output digest. + * @return None + */ +void SHA_Read(uint32_t u32Digest[]) +{ + uint32_t i, wcnt; + + i = (CRPT->HMAC_CTL & CRPT_HMAC_CTL_OPMODE_Msk) >> CRPT_HMAC_CTL_OPMODE_Pos; + if (i == SHA_MODE_SHA1) + { + wcnt = 5UL; + } + else if (i == SHA_MODE_SHA224) + { + wcnt = 7UL; + } + else if (i == SHA_MODE_SHA256) + { + wcnt = 8UL; + } + else if (i == SHA_MODE_SHA384) + { + wcnt = 12UL; + } + else + { + /* SHA_MODE_SHA512 */ + wcnt = 16UL; + } + + for (i = 0; i < wcnt; i++) + u32Digest[i] = *(uint32_t *)((uint32_t) & (CRPT->HMAC_DGST0) + (i * 4)); +} + + +/*@}*/ /* end of group N9H30_CRYPTO_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_CRYPTO_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_emac.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_emac.c new file mode 100644 index 0000000000..703c686311 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_emac.c @@ -0,0 +1,1158 @@ +/**************************************************************************//** + * @file emac.c + * @version V1.00 + * @brief M480 EMAC driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include +#include +#include "NuMicro.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup EMAC_Driver EMAC Driver + @{ +*/ + + +/* Below are structure, definitions, static variables used locally by EMAC driver and does not want to parse by doxygen unless HIDDEN_SYMBOLS is defined */ +/** @cond HIDDEN_SYMBOLS */ + +/** @addtogroup EMAC_EXPORTED_CONSTANTS EMAC Exported Constants + @{ +*/ + +/* PHY Register Description */ +#define PHY_CNTL_REG 0x00UL /*!< PHY control register address */ +#define PHY_STATUS_REG 0x01UL /*!< PHY status register address */ +#define PHY_ID1_REG 0x02UL /*!< PHY ID1 register */ +#define PHY_ID2_REG 0x03UL /*!< PHY ID2 register */ +#define PHY_ANA_REG 0x04UL /*!< PHY auto-negotiation advertisement register */ +#define PHY_ANLPA_REG 0x05UL /*!< PHY auto-negotiation link partner availability register */ +#define PHY_ANE_REG 0x06UL /*!< PHY auto-negotiation expansion register */ + +/* PHY Control Register */ +#define PHY_CNTL_RESET_PHY (1UL << 15UL) +#define PHY_CNTL_DR_100MB (1UL << 13UL) +#define PHY_CNTL_ENABLE_AN (1UL << 12UL) +#define PHY_CNTL_POWER_DOWN (1UL << 11UL) +#define PHY_CNTL_RESTART_AN (1UL << 9UL) +#define PHY_CNTL_FULLDUPLEX (1UL << 8UL) + +/* PHY Status Register */ +#define PHY_STATUS_AN_COMPLETE (1UL << 5UL) +#define PHY_STATUS_LINK_VALID (1UL << 2UL) + +/* PHY Auto-negotiation Advertisement Register */ +#define PHY_ANA_DR100_TX_FULL (1UL << 8UL) +#define PHY_ANA_DR100_TX_HALF (1UL << 7UL) +#define PHY_ANA_DR10_TX_FULL (1UL << 6UL) +#define PHY_ANA_DR10_TX_HALF (1UL << 5UL) +#define PHY_ANA_IEEE_802_3_CSMA_CD (1UL << 0UL) + +/* PHY Auto-negotiation Link Partner Advertisement Register */ +#define PHY_ANLPA_DR100_TX_FULL (1UL << 8UL) +#define PHY_ANLPA_DR100_TX_HALF (1UL << 7UL) +#define PHY_ANLPA_DR10_TX_FULL (1UL << 6UL) +#define PHY_ANLPA_DR10_TX_HALF (1UL << 5UL) + +/* EMAC Tx/Rx descriptor's owner bit */ +#define EMAC_DESC_OWN_EMAC 0x80000000UL /*!< Set owner to EMAC */ +#define EMAC_DESC_OWN_CPU 0x00000000UL /*!< Set owner to CPU */ + +/* Rx Frame Descriptor Status */ +#define EMAC_RXFD_RTSAS 0x0080UL /*!< Time Stamp Available */ +#define EMAC_RXFD_RP 0x0040UL /*!< Runt Packet */ +#define EMAC_RXFD_ALIE 0x0020UL /*!< Alignment Error */ +#define EMAC_RXFD_RXGD 0x0010UL /*!< Receiving Good packet received */ +#define EMAC_RXFD_PTLE 0x0008UL /*!< Packet Too Long Error */ +#define EMAC_RXFD_CRCE 0x0002UL /*!< CRC Error */ +#define EMAC_RXFD_RXINTR 0x0001UL /*!< Interrupt on receive */ + +/* Tx Frame Descriptor's Control bits */ +#define EMAC_TXFD_TTSEN 0x08UL /*!< Tx time stamp enable */ +#define EMAC_TXFD_INTEN 0x04UL /*!< Tx interrupt enable */ +#define EMAC_TXFD_CRCAPP 0x02UL /*!< Append CRC */ +#define EMAC_TXFD_PADEN 0x01UL /*!< Padding mode enable */ + +/* Tx Frame Descriptor Status */ +#define EMAC_TXFD_TXINTR 0x0001UL /*!< Interrupt on Transmit */ +#define EMAC_TXFD_DEF 0x0002UL /*!< Transmit deferred */ +#define EMAC_TXFD_TXCP 0x0008UL /*!< Transmission Completion */ +#define EMAC_TXFD_EXDEF 0x0010UL /*!< Exceed Deferral */ +#define EMAC_TXFD_NCS 0x0020UL /*!< No Carrier Sense Error */ +#define EMAC_TXFD_TXABT 0x0040UL /*!< Transmission Abort */ +#define EMAC_TXFD_LC 0x0080UL /*!< Late Collision */ +#define EMAC_TXFD_TXHA 0x0100UL /*!< Transmission halted */ +#define EMAC_TXFD_PAU 0x0200UL /*!< Paused */ +#define EMAC_TXFD_SQE 0x0400UL /*!< SQE error */ +#define EMAC_TXFD_TTSAS 0x0800UL /*!< Time Stamp available */ + +/*@}*/ /* end of group EMAC_EXPORTED_CONSTANTS */ + +/** @addtogroup EMAC_EXPORTED_TYPEDEF EMAC Exported Type Defines + @{ +*/ + +/*@}*/ /* end of group EMAC_EXPORTED_TYPEDEF */ + +/* local variables */ +static uint32_t s_u32EnableTs = 0UL; + +static void EMAC_MdioWrite(EMAC_T *EMAC, uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data); +static uint32_t EMAC_MdioRead(EMAC_T *EMAC, uint32_t u32Reg, uint32_t u32Addr); + +static uint32_t EMAC_Subsec2Nsec(uint32_t subsec); +static uint32_t EMAC_Nsec2Subsec(uint32_t nsec); +static void EMAC_TxDescInit(EMAC_MEMMGR_T *psMemMgr); +static void EMAC_RxDescInit(EMAC_MEMMGR_T *psMemMgr); + +/** @addtogroup EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions + @{ +*/ + + +/** + * @brief Write PHY register + * @param[in] u32Reg PHY register number + * @param[in] u32Addr PHY address, this address is board dependent + * @param[in] u32Data data to write to PHY register + * @return None + */ +static void EMAC_MdioWrite(EMAC_T *EMAC, uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data) +{ + /* Set data register */ + EMAC->MIIMDAT = u32Data ; + /* Set PHY address, PHY register address, busy bit and write bit */ + EMAC->MIIMCTL = u32Reg | (u32Addr << 8) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk; + + /* Wait write complete by polling busy bit. */ + while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) + { + ; + } + +} + +/** + * @brief Read PHY register + * @param[in] u32Reg PHY register number + * @param[in] u32Addr PHY address, this address is board dependent + * @return Value read from PHY register + */ +static uint32_t EMAC_MdioRead(EMAC_T *EMAC, uint32_t u32Reg, uint32_t u32Addr) +{ + /* Set PHY address, PHY register address, busy bit */ + EMAC->MIIMCTL = u32Reg | (u32Addr << EMAC_MIIMCTL_PHYADDR_Pos) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk; + + /* Wait read complete by polling busy bit */ + while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) + { + ; + } + + /* Get return data */ + return EMAC->MIIMDAT; +} + +void EMAC_Reset(EMAC_T *EMAC) +{ + /* Reset MAC */ + EMAC->CTL = 0x1000000; +} + +/** + * @brief Initialize PHY chip, check for the auto-negotiation result. + * @param None + * @return None + */ +void EMAC_PhyInit(EMAC_T *EMAC) +{ + uint32_t reg; + uint32_t i = 0UL; + + /* Reset Phy Chip */ + EMAC_MdioWrite(EMAC, PHY_CNTL_REG, EMAC_PHY_ADDR, PHY_CNTL_RESET_PHY); + + /* Wait until reset complete */ + while (1) + { + reg = EMAC_MdioRead(EMAC, PHY_CNTL_REG, EMAC_PHY_ADDR) ; + + if ((reg & PHY_CNTL_RESET_PHY) == 0UL) + { + break; + } + } + + while (!(EMAC_MdioRead(EMAC, PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID)) + { + if (i++ > 10000UL) /* Cable not connected */ + { + EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk; + EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk; + break; + } + } + + if (i <= 10000UL) + { + /* Configure auto negotiation capability */ + EMAC_MdioWrite(EMAC, PHY_ANA_REG, EMAC_PHY_ADDR, PHY_ANA_DR100_TX_FULL | + PHY_ANA_DR100_TX_HALF | + PHY_ANA_DR10_TX_FULL | + PHY_ANA_DR10_TX_HALF | + PHY_ANA_IEEE_802_3_CSMA_CD); + /* Restart auto negotiation */ + EMAC_MdioWrite(EMAC, PHY_CNTL_REG, EMAC_PHY_ADDR, EMAC_MdioRead(EMAC, PHY_CNTL_REG, EMAC_PHY_ADDR) | PHY_CNTL_RESTART_AN); + + /* Wait for auto-negotiation complete */ + while (!(EMAC_MdioRead(EMAC, PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_AN_COMPLETE)) + { + ; + } + + /* Check link valid again. Some PHYs needs to check result after link valid bit set */ + while (!(EMAC_MdioRead(EMAC, PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID)) + { + ; + } + + /* Check link partner capability */ + reg = EMAC_MdioRead(EMAC, PHY_ANLPA_REG, EMAC_PHY_ADDR) ; + + if (reg & PHY_ANLPA_DR100_TX_FULL) + { + EMAC->CTL |= EMAC_CTL_OPMODE_Msk; + EMAC->CTL |= EMAC_CTL_FUDUP_Msk; + } + else if (reg & PHY_ANLPA_DR100_TX_HALF) + { + EMAC->CTL |= EMAC_CTL_OPMODE_Msk; + EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk; + } + else if (reg & PHY_ANLPA_DR10_TX_FULL) + { + EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk; + EMAC->CTL |= EMAC_CTL_FUDUP_Msk; + } + else + { + EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk; + EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk; + } + } +} + +/** + * @brief Initial EMAC Tx descriptors and get Tx descriptor base address + * @param EMAC_MEMMGR_T pointer + * @return None + */ +static void EMAC_TxDescInit(EMAC_MEMMGR_T *psMemMgr) +{ + uint32_t i; + + /* Get Frame descriptor's base address. */ + psMemMgr->psNextTxDesc = psMemMgr->psCurrentTxDesc = (EMAC_DESCRIPTOR_T *)((uint32_t)&psMemMgr->psTXDescs[0] | BIT31); + + for (i = 0UL; i < psMemMgr->u32TxDescSize; i++) + { + + if (s_u32EnableTs) + { + psMemMgr->psTXDescs[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN; + } + else + { + psMemMgr->psTXDescs[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN | EMAC_TXFD_TTSEN; + } + + psMemMgr->psTXDescs[i].u32Data = (uint32_t)& psMemMgr->psTXFrames[i] | BIT31; + psMemMgr->psTXDescs[i].u32Status2 = 0UL; + psMemMgr->psTXDescs[i].u32Next = (uint32_t)(&psMemMgr->psTXDescs[(i + 1UL) % EMAC_TX_DESC_SIZE]) | BIT31; + psMemMgr->psTXDescs[i].u32Backup1 = psMemMgr->psTXDescs[i].u32Data; + psMemMgr->psTXDescs[i].u32Backup2 = psMemMgr->psTXDescs[i].u32Next; + } + psMemMgr->psEmac->TXDSA = (uint32_t)psMemMgr->psCurrentTxDesc; +} + + +/** + * @brief Initial EMAC Rx descriptors and get Rx descriptor base address + * @param EMAC_MEMMGR_T pointer + * @return None + */ +static void EMAC_RxDescInit(EMAC_MEMMGR_T *psMemMgr) +{ + + uint32_t i; + + /* Get Frame descriptor's base address. */ + psMemMgr->psCurrentRxDesc = (EMAC_DESCRIPTOR_T *)((uint32_t)&psMemMgr->psRXDescs[0] | BIT31); + + for (i = 0UL; i < psMemMgr->u32RxDescSize; i++) + { + psMemMgr->psRXDescs[i].u32Status1 = EMAC_DESC_OWN_EMAC; + psMemMgr->psRXDescs[i].u32Data = (uint32_t)&psMemMgr->psRXFrames[i] | BIT31; + psMemMgr->psRXDescs[i].u32Status2 = 0UL; + psMemMgr->psRXDescs[i].u32Next = (uint32_t)(&psMemMgr->psRXDescs[(i + 1UL) % EMAC_RX_DESC_SIZE]) | BIT31; + psMemMgr->psRXDescs[i].u32Backup1 = psMemMgr->psRXDescs[i].u32Data; + psMemMgr->psRXDescs[i].u32Backup2 = psMemMgr->psRXDescs[i].u32Next; + } + psMemMgr->psEmac->RXDSA = (uint32_t)psMemMgr->psCurrentRxDesc; +} + +/** + * @brief Convert subsecond value to nano second + * @param[in] subsec Subsecond value to be convert + * @return Nano second + */ +static uint32_t EMAC_Subsec2Nsec(uint32_t subsec) +{ + /* 2^31 subsec == 10^9 ns */ + uint64_t i; + i = 1000000000ull * (uint64_t)subsec; + i >>= 31; + return ((uint32_t)i); +} + +/** + * @brief Convert nano second to subsecond value + * @param[in] nsec Nano second to be convert + * @return Subsecond + */ +static uint32_t EMAC_Nsec2Subsec(uint32_t nsec) +{ + /* 10^9 ns = 2^31 subsec */ + uint64_t i; + i = (1ull << 31) * nsec; + i /= 1000000000ull; + return ((uint32_t)i); +} + + +/*@}*/ /* end of group EMAC_EXPORTED_FUNCTIONS */ + + + +/** @endcond HIDDEN_SYMBOLS */ + + +/** @addtogroup EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions + @{ +*/ + + +/** + * @brief Initialize EMAC interface, including descriptors, MAC address, and PHY. + * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address + * @return None + * @note This API configures EMAC to receive all broadcast and multicast packets, but could configure to other settings with + * \ref EMAC_ENABLE_RECV_BCASTPKT, \ref EMAC_DISABLE_RECV_BCASTPKT, \ref EMAC_ENABLE_RECV_MCASTPKT, and \ref EMAC_DISABLE_RECV_MCASTPKT + * @note Receive(RX) and transmit(TX) are not enabled yet, application must call \ref EMAC_ENABLE_RX and \ref EMAC_ENABLE_TX to + * enable receive and transmit function. + */ +void EMAC_Open(EMAC_MEMMGR_T *psMemMgr, uint8_t *pu8MacAddr) +{ + EMAC_T *EMAC = psMemMgr->psEmac; + + /* Enable transmit and receive descriptor */ + EMAC_TxDescInit(psMemMgr); + EMAC_RxDescInit(psMemMgr); + + /* Set the CAM Control register and the MAC address value */ + EMAC_SetMacAddr(EMAC, pu8MacAddr); + + /* Configure the MAC interrupt enable register. */ + EMAC->INTEN = EMAC_INTEN_RXIEN_Msk | + EMAC_INTEN_TXIEN_Msk | + EMAC_INTEN_RXGDIEN_Msk | + EMAC_INTEN_TXCPIEN_Msk | + EMAC_INTEN_RXBEIEN_Msk | + EMAC_INTEN_TXBEIEN_Msk | + EMAC_INTEN_RDUIEN_Msk | + EMAC_INTEN_TSALMIEN_Msk | + EMAC_INTEN_WOLIEN_Msk; + + /* Configure the MAC control register. */ + EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | + EMAC_CTL_RMIIEN_Msk; + + /* Accept packets for us and all broadcast and multicast packets */ + EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk | + EMAC_CAMCTL_AMP_Msk | + EMAC_CAMCTL_ABP_Msk; + + /* Limit the max receive frame length */ + EMAC->MRFL = EMAC_MAX_PKT_SIZE; +} + +/** + * @brief This function stop all receive and transmit activity and disable MAC interface + * @param None + * @return None + */ + +void EMAC_Close(EMAC_T *EMAC) +{ + EMAC->CTL |= EMAC_CTL_RST_Msk; + + while (EMAC->CTL & EMAC_CTL_RST_Msk) {} +} + +/** + * @brief Set the device MAC address + * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address + * @return None + */ +void EMAC_SetMacAddr(EMAC_T *EMAC, uint8_t *pu8MacAddr) +{ + EMAC_EnableCamEntry(EMAC, 0UL, pu8MacAddr); +} + +/** + * @brief Fill a CAM entry for MAC address comparison. + * @param[in] u32Entry MAC entry to fill. Entry 0 is used to store device MAC address, do not overwrite the setting in it. + * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address + * @return None + */ +void EMAC_EnableCamEntry(EMAC_T *EMAC, uint32_t u32Entry, uint8_t pu8MacAddr[]) +{ + uint32_t u32Lsw, u32Msw; + uint32_t reg; + u32Lsw = (uint32_t)(((uint32_t)pu8MacAddr[4] << 24) | + ((uint32_t)pu8MacAddr[5] << 16)); + u32Msw = (uint32_t)(((uint32_t)pu8MacAddr[0] << 24) | + ((uint32_t)pu8MacAddr[1] << 16) | + ((uint32_t)pu8MacAddr[2] << 8) | + (uint32_t)pu8MacAddr[3]); + + reg = (uint32_t)&EMAC->CAM0M + u32Entry * 2UL * 4UL; + *(uint32_t volatile *)reg = u32Msw; + reg = (uint32_t)&EMAC->CAM0L + u32Entry * 2UL * 4UL; + *(uint32_t volatile *)reg = u32Lsw; + + EMAC->CAMEN |= (1UL << u32Entry); +} + +/** + * @brief Disable a specified CAM entry + * @param[in] u32Entry CAM entry to be disabled + * @return None + */ +void EMAC_DisableCamEntry(EMAC_T *EMAC, uint32_t u32Entry) +{ + EMAC->CAMEN &= ~(1UL << u32Entry); +} + + +/** + * @brief Receive an Ethernet packet + * @param[in] pu8Data Pointer to a buffer to store received packet (4 byte CRC removed) + * @param[in] pu32Size Received packet size (without 4 byte CRC). + * @return Packet receive success or not + * @retval 0 No packet available for receive + * @retval 1 A packet is received + * @note Return 0 doesn't guarantee the packet will be sent and received successfully. + */ +uint32_t EMAC_RecvPkt(EMAC_MEMMGR_T *psMemMgr, uint8_t *pu8Data, uint32_t *pu32Size) +{ + uint32_t reg; + uint32_t u32Count = 0UL; + EMAC_T *EMAC = psMemMgr->psEmac; + + /* Clear Rx interrupt flags */ + reg = EMAC->INTSTS; + EMAC->INTSTS = reg & 0xFFFFUL; /* Clear all RX related interrupt status */ + + if (reg & EMAC_INTSTS_RXBEIF_Msk) + { + /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */ + while (1) {} + } + else + { + /* Get Rx Frame Descriptor */ + EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)psMemMgr->psCurrentRxDesc; + + /* If we reach last recv Rx descriptor, leave the loop */ + if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) /* ownership=CPU */ + { + uint32_t status = desc->u32Status1 >> 16; + + /* If Rx frame is good, process received frame */ + if (status & EMAC_RXFD_RXGD) + { + /* lower 16 bit in descriptor status1 stores the Rx packet length */ + *pu32Size = desc->u32Status1 & 0xFFFFUL; + memcpy(pu8Data, (uint8_t *)desc->u32Data, *pu32Size); + u32Count = 1UL; + } + else + { + /* Save Error status if necessary */ + if (status & EMAC_RXFD_RP) {} + + if (status & EMAC_RXFD_ALIE) {} + + if (status & EMAC_RXFD_PTLE) {} + + if (status & EMAC_RXFD_CRCE) {} + } + } + } + + return (u32Count); +} + +/** + * @brief Receive an Ethernet packet and the time stamp while it's received + * @param[out] pu8Data Pointer to a buffer to store received packet (4 byte CRC removed) + * @param[out] pu32Size Received packet size (without 4 byte CRC). + * @param[out] pu32Sec Second value while packet received + * @param[out] pu32Nsec Nano second value while packet received + * @return Packet receive success or not + * @retval 0 No packet available for receive + * @retval 1 A packet is received + * @note Return 0 doesn't guarantee the packet will be sent and received successfully. + * @note Largest Ethernet packet is 1514 bytes after stripped CRC, application must give + * a buffer large enough to store such packet + */ +uint32_t EMAC_RecvPktTS(EMAC_MEMMGR_T *psMemMgr, uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec) +{ + EMAC_T *EMAC = psMemMgr->psEmac; + uint32_t reg; + uint32_t u32Count = 0UL; + + /* Clear Rx interrupt flags */ + reg = EMAC->INTSTS; + EMAC->INTSTS = reg & 0xFFFFUL; /* Clear all Rx related interrupt status */ + + if (reg & EMAC_INTSTS_RXBEIF_Msk) + { + /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */ + while (1) {} + } + else + { + /* Get Rx Frame Descriptor */ + EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)psMemMgr->psCurrentRxDesc; + + /* If we reach last recv Rx descriptor, leave the loop */ + if (EMAC->CRXDSA != (uint32_t)desc) + { + if ((desc->u32Status1 | EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) /* ownership=CPU */ + { + + uint32_t status = desc->u32Status1 >> 16; + + /* If Rx frame is good, process received frame */ + if (status & EMAC_RXFD_RXGD) + { + /* lower 16 bit in descriptor status1 stores the Rx packet length */ + *pu32Size = desc->u32Status1 & 0xFFFFUL; + memcpy(pu8Data, (uint8_t *)desc->u32Data, *pu32Size); + + *pu32Sec = desc->u32Next; /* second stores in descriptor's NEXT field */ + *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); /* Sub nano second store in DATA field */ + + u32Count = 1UL; + } + else + { + /* Save Error status if necessary */ + if (status & EMAC_RXFD_RP) {} + + if (status & EMAC_RXFD_ALIE) {} + + if (status & EMAC_RXFD_PTLE) {} + + if (status & EMAC_RXFD_CRCE) {} + } + } + } + } + + return (u32Count); +} + +/** + * @brief Clean up process after a packet is received + * @param None + * @return None + * @details EMAC Rx interrupt service routine \b must call this API to release the resource use by receive process + * @note Application can only call this function once every time \ref EMAC_RecvPkt or \ref EMAC_RecvPktTS returns 1 + */ +void EMAC_RecvPktDone(EMAC_MEMMGR_T *psMemMgr) +{ + EMAC_T *EMAC = psMemMgr->psEmac; + /* Get Rx Frame Descriptor */ + EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)psMemMgr->psCurrentRxDesc; + + /* Restore descriptor link list and data pointer they will be overwrite if time stamp enabled */ + desc->u32Data = desc->u32Backup1; + desc->u32Next = desc->u32Backup2; + + /* Change ownership to DMA for next use */ + desc->u32Status1 |= EMAC_DESC_OWN_EMAC; + + /* Get Next Frame Descriptor pointer to process */ + desc = (EMAC_DESCRIPTOR_T *)desc->u32Next; + + /* Save last processed Rx descriptor */ + psMemMgr->psCurrentRxDesc = desc; + + EMAC_TRIGGER_RX(EMAC); +} + + +/** + * @brief Send an Ethernet packet + * @param[in] pu8Data Pointer to a buffer holds the packet to transmit + * @param[in] u32Size Packet size (without 4 byte CRC). + * @return Packet transmit success or not + * @retval 0 Transmit failed due to descriptor unavailable. + * @retval 1 Packet is copied to descriptor and triggered to transmit. + * @note Return 1 doesn't guarantee the packet will be sent and received successfully. + */ +uint32_t EMAC_SendPkt(EMAC_MEMMGR_T *psMemMgr, uint8_t *pu8Data, uint32_t u32Size) +{ + EMAC_T *EMAC = psMemMgr->psEmac; + + /* Get Tx frame descriptor & data pointer */ + EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)psMemMgr->psNextTxDesc; + uint32_t status = desc->u32Status1; + uint32_t ret = 0UL; + + /* Check descriptor ownership */ + if ((status & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) + { + memcpy((uint8_t *)desc->u32Data, pu8Data, u32Size); + + /* Set Tx descriptor transmit byte count */ + desc->u32Status2 = u32Size; + + /* Change descriptor ownership to EMAC */ + desc->u32Status1 |= EMAC_DESC_OWN_EMAC; + + /* Get next Tx descriptor */ + psMemMgr->psNextTxDesc = (EMAC_DESCRIPTOR_T *)(desc->u32Next); + + /* Trigger EMAC to send the packet */ + EMAC_TRIGGER_TX(EMAC); + ret = 1UL; + } + + return (ret); +} + + +/** + * @brief Clean up process after packet(s) are sent + * @param None + * @return Number of packet sent between two function calls + * @details EMAC Tx interrupt service routine \b must call this API or \ref EMAC_SendPktDoneTS to + * release the resource use by transmit process + */ +uint32_t EMAC_SendPktDone(EMAC_MEMMGR_T *psMemMgr) +{ + EMAC_T *EMAC = psMemMgr->psEmac; + + uint32_t status, reg; + uint32_t last_tx_desc; + uint32_t u32Count = 0UL; + + reg = EMAC->INTSTS; + /* Clear Tx interrupt flags */ + EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk); + + + if (reg & EMAC_INTSTS_TXBEIF_Msk) + { + /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */ + while (1) {} + } + else + { + /* Get our first descriptor to process */ + EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)psMemMgr->psCurrentTxDesc; + + /* Process the descriptor(s). */ + last_tx_desc = EMAC->CTXDSA ; + + do + { + /* Descriptor ownership is still EMAC, so this packet haven't been send. */ + if (desc->u32Status1 & EMAC_DESC_OWN_EMAC) + { + break; + } + + /* Get Tx status stored in descriptor */ + status = desc->u32Status2 >> 16UL; + + if (status & EMAC_TXFD_TXCP) + { + u32Count++; + } + else + { + /* Do nothing here on error. */ + if (status & EMAC_TXFD_TXABT) {} + + if (status & EMAC_TXFD_DEF) {} + + if (status & EMAC_TXFD_PAU) {} + + if (status & EMAC_TXFD_EXDEF) {} + + if (status & EMAC_TXFD_NCS) {} + + if (status & EMAC_TXFD_SQE) {} + + if (status & EMAC_TXFD_LC) {} + + if (status & EMAC_TXFD_TXHA) {} + } + + /* restore descriptor link list and data pointer they will be overwrite if time stamp enabled */ + desc->u32Data = desc->u32Backup1; + desc->u32Next = desc->u32Backup2; + /* go to next descriptor in link */ + desc = (EMAC_DESCRIPTOR_T *)desc->u32Next; + } + while (last_tx_desc != (uint32_t)desc); /* If we reach last sent Tx descriptor, leave the loop */ + + /* Save last processed Tx descriptor */ + psMemMgr->psCurrentTxDesc = (EMAC_DESCRIPTOR_T *)desc; + } + + return (u32Count); +} + +/** + * @brief Clean up process after a packet is sent, and get the time stamp while packet is sent + * @param[in] pu32Sec Second value while packet sent + * @param[in] pu32Nsec Nano second value while packet sent + * @return If a packet sent successfully + * @retval 0 No packet sent successfully, and the value in *pu32Sec and *pu32Nsec are meaningless + * @retval 1 A packet sent successfully, and the value in *pu32Sec and *pu32Nsec is the time stamp while packet sent + * @details EMAC Tx interrupt service routine \b must call this API or \ref EMAC_SendPktDone to + * release the resource use by transmit process + */ +uint32_t EMAC_SendPktDoneTS(EMAC_MEMMGR_T *psMemMgr, uint32_t *pu32Sec, uint32_t *pu32Nsec) +{ + EMAC_T *EMAC = psMemMgr->psEmac; + uint32_t reg; + uint32_t u32Count = 0UL; + + reg = EMAC->INTSTS; + /* Clear Tx interrupt flags */ + EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk); + + + if (reg & EMAC_INTSTS_TXBEIF_Msk) + { + /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */ + while (1) {} + } + else + { + /* Process the descriptor. + Get our first descriptor to process */ + EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)psMemMgr->psCurrentTxDesc; + + /* Descriptor ownership is still EMAC, so this packet haven't been send. */ + if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) + { + /* Get Tx status stored in descriptor */ + uint32_t status = desc->u32Status2 >> 16UL; + + if (status & EMAC_TXFD_TXCP) + { + u32Count = 1UL; + *pu32Sec = desc->u32Next; /* second stores in descriptor's NEXT field */ + *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); /* Sub nano second store in DATA field */ + } + else + { + /* Do nothing here on error. */ + if (status & EMAC_TXFD_TXABT) {} + + if (status & EMAC_TXFD_DEF) {} + + if (status & EMAC_TXFD_PAU) {} + + if (status & EMAC_TXFD_EXDEF) {} + + if (status & EMAC_TXFD_NCS) {} + + if (status & EMAC_TXFD_SQE) {} + + if (status & EMAC_TXFD_LC) {} + + if (status & EMAC_TXFD_TXHA) {} + } + + /* restore descriptor link list and data pointer they will be overwrite if time stamp enabled */ + desc->u32Data = desc->u32Backup1; + desc->u32Next = desc->u32Backup2; + /* go to next descriptor in link */ + desc = (EMAC_DESCRIPTOR_T *)desc->u32Next; + + /* Save last processed Tx descriptor */ + psMemMgr->psCurrentTxDesc = desc; + } + } + + return (u32Count); +} + +/** + * @brief Enable IEEE1588 time stamp function and set current time + * @param[in] u32Sec Second value + * @param[in] u32Nsec Nano second value + * @return None + */ +void EMAC_EnableTS(EMAC_T *EMAC, uint32_t u32Sec, uint32_t u32Nsec) +{ +#if 0 + double f; + uint32_t reg; + EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk; + EMAC->UPDSEC = u32Sec; /* Assume current time is 0 sec + 0 nano sec */ + EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec); + + /* PTP source clock is 160MHz (Real chip using PLL). Each tick is 6.25ns + Assume we want to set each tick to 100ns. + Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7 + Addend register = 2^32 * tick_freq / (160MHz), where tick_freq = (2^31 / 215) MHz + From above equation, addend register = 2^63 / (160M * 215) ~= 268121280 = 0xFFB34C0 + So: + EMAC->TSIR = 0xD7; + EMAC->TSAR = 0x1E70C600; */ + f = (100.0 * 2147483648.0) / (1000000000.0) + 0.5; + EMAC->TSINC = (reg = (uint32_t)f); + f = (double)9223372036854775808.0 / ((double)(CLK_GetHCLKFreq()) * (double)reg); + EMAC->TSADDEND = (uint32_t)f; + EMAC->TSCTL |= (EMAC_TSCTL_TSUPDATE_Msk | EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk); /* Fine update */ +#endif +} + +/** + * @brief Disable IEEE1588 time stamp function + * @param None + * @return None + */ +void EMAC_DisableTS(EMAC_T *EMAC) +{ +#if 0 + EMAC->TSCTL = 0UL; +#endif +} + +/** + * @brief Get current time stamp + * @param[out] pu32Sec Current second value + * @param[out] pu32Nsec Current nano second value + * @return None + */ +void EMAC_GetTime(EMAC_T *EMAC, uint32_t *pu32Sec, uint32_t *pu32Nsec) +{ + /* Must read TSLSR firstly. Hardware will preserve TSMSR value at the time TSLSR read. */ + *pu32Nsec = EMAC_Subsec2Nsec(EMAC->TSSUBSEC); + *pu32Sec = EMAC->TSSEC; +} + +/** + * @brief Set current time stamp + * @param[in] u32Sec Second value + * @param[in] u32Nsec Nano second value + * @return None + */ +void EMAC_SetTime(EMAC_T *EMAC, uint32_t u32Sec, uint32_t u32Nsec) +{ + /* Disable time stamp counter before update time value (clear EMAC_TSCTL_TSIEN_Msk) */ + EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk; + EMAC->UPDSEC = u32Sec; + EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec); + EMAC->TSCTL |= (EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk); + +} + +/** + * @brief Enable alarm function and set alarm time + * @param[in] u32Sec Second value to trigger alarm + * @param[in] u32Nsec Nano second value to trigger alarm + * @return None + */ +void EMAC_EnableAlarm(EMAC_T *EMAC, uint32_t u32Sec, uint32_t u32Nsec) +{ + + EMAC->ALMSEC = u32Sec; + EMAC->ALMSUBSEC = EMAC_Nsec2Subsec(u32Nsec); + EMAC->TSCTL |= EMAC_TSCTL_TSALMEN_Msk; + +} + +/** + * @brief Disable alarm function + * @param None + * @return None + */ +void EMAC_DisableAlarm(EMAC_T *EMAC) +{ + + EMAC->TSCTL &= ~EMAC_TSCTL_TSALMEN_Msk; + +} + +/** + * @brief Add a offset to current time + * @param[in] u32Neg Offset is negative value (u32Neg == 1) or positive value (u32Neg == 0). + * @param[in] u32Sec Second value to add to current time + * @param[in] u32Nsec Nano second value to add to current time + * @return None + */ +void EMAC_UpdateTime(EMAC_T *EMAC, uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec) +{ + EMAC->UPDSEC = u32Sec; + EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec); + + if (u32Neg) + { + EMAC->UPDSUBSEC |= BIT31; /* Set bit 31 indicates this is a negative value */ + } + + EMAC->TSCTL |= EMAC_TSCTL_TSUPDATE_Msk; + +} + +/** + * @brief Check Ethernet link status + * @param None + * @return Current link status, could be one of following value. + * - \ref EMAC_LINK_DOWN + * - \ref EMAC_LINK_100F + * - \ref EMAC_LINK_100H + * - \ref EMAC_LINK_10F + * - \ref EMAC_LINK_10H + * @note This API should be called regularly to sync EMAC setting with real connection status + */ +uint32_t EMAC_CheckLinkStatus(EMAC_T *EMAC) +{ + uint32_t reg, ret = EMAC_LINK_DOWN; + + /* Check link valid again */ + if (EMAC_MdioRead(EMAC, PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID) + { + /* Check link partner capability */ + reg = EMAC_MdioRead(EMAC, PHY_ANLPA_REG, EMAC_PHY_ADDR) ; + + if (reg & PHY_ANLPA_DR100_TX_FULL) + { + EMAC->CTL |= EMAC_CTL_OPMODE_Msk; + EMAC->CTL |= EMAC_CTL_FUDUP_Msk; + ret = EMAC_LINK_100F; + } + else if (reg & PHY_ANLPA_DR100_TX_HALF) + { + EMAC->CTL |= EMAC_CTL_OPMODE_Msk; + EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk; + ret = EMAC_LINK_100H; + } + else if (reg & PHY_ANLPA_DR10_TX_FULL) + { + EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk; + EMAC->CTL |= EMAC_CTL_FUDUP_Msk; + ret = EMAC_LINK_10F; + } + else + { + EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk; + EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk; + ret = EMAC_LINK_10H; + } + } + + return ret; +} + +/** + * @brief Fill a MAC address to list and enable. + * @param A MAC address + * @return The CAM index + * @retval -1 Failed to fill the MAC address. + * @retval 0~(EMAC_CAMENTRY_NB-1) The index number of entry location. + */ +int32_t EMAC_FillCamEntry(EMAC_T *EMAC, uint8_t pu8MacAddr[]) +{ + uint32_t *EMAC_CAMxM; + uint32_t *EMAC_CAMxL; + int32_t index; + uint8_t mac[6]; + + for (index = 0; index < EMAC_CAMENTRY_NB; index ++) + { + EMAC_CAMxM = (uint32_t *)((uint32_t)&EMAC->CAM0M + (index * 8)); + EMAC_CAMxL = (uint32_t *)((uint32_t)&EMAC->CAM0L + (index * 8)); + + mac[0] = (*EMAC_CAMxM >> 24) & 0xff; + mac[1] = (*EMAC_CAMxM >> 16) & 0xff; + mac[2] = (*EMAC_CAMxM >> 8) & 0xff; + mac[3] = (*EMAC_CAMxM) & 0xff; + mac[4] = (*EMAC_CAMxL >> 24) & 0xff; + mac[5] = (*EMAC_CAMxL >> 16) & 0xff; + + if (memcmp(mac, pu8MacAddr, sizeof(mac)) == 0) + { + goto exit_emac_fillcamentry; + } + + if (*EMAC_CAMxM == 0 && *EMAC_CAMxL == 0) + { + break; + } + } + + if (index < EMAC_CAMENTRY_NB) + { + EMAC_EnableCamEntry(EMAC, index, pu8MacAddr); + goto exit_emac_fillcamentry; + } + + return -1; + +exit_emac_fillcamentry: + + return index; +} + +/** + * @brief Send an Ethernet packet + * @param[in] u32Size Packet size (without 4 byte CRC). + * @return Packet transmit success or not + * @retval 0 Transmit failed due to descriptor unavailable. + * @retval 1 Triggered to transmit. + * @note Return 1 doesn't guarantee the packet will be sent and received successfully. + */ +uint32_t EMAC_SendPktWoCopy(EMAC_MEMMGR_T *psMemMgr, uint32_t u32Size) +{ + EMAC_T *EMAC = psMemMgr->psEmac; + + /* Get Tx frame descriptor & data pointer */ + EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)psMemMgr->psNextTxDesc; + uint32_t status = desc->u32Status1; + uint32_t ret = 0UL; + + /* Check descriptor ownership */ + if ((status & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) + { + /* Set Tx descriptor transmit byte count */ + desc->u32Status2 = u32Size; + + /* Change descriptor ownership to EMAC */ + desc->u32Status1 |= EMAC_DESC_OWN_EMAC; + + /* Get next Tx descriptor */ + psMemMgr->psNextTxDesc = (EMAC_DESCRIPTOR_T *)(desc->u32Next); + + /* Trigger EMAC to send the packet */ + EMAC_TRIGGER_TX(EMAC); + ret = 1UL; + } + + return (ret); +} + +/** + * @brief Get avaiable TX buffer address + * @param None + * @return An avaiable TX buffer. + * @note This API should be called before EMAC_SendPkt_WoCopy calling. Caller will do data-copy. + */ +uint8_t *EMAC_ClaimFreeTXBuf(EMAC_MEMMGR_T *psMemMgr) +{ + EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)psMemMgr->psNextTxDesc; + + if (desc->u32Status1 & EMAC_DESC_OWN_EMAC) + { + return (NULL); + } + else + { + return (uint8_t *)desc->u32Data; + } +} + +/** + * @brief Get data length of avaiable RX buffer. + * @param None + * @return An data length of avaiable RX buffer. + * @note This API should be called before EMAC_RecvPktDone_WoTrigger calling. Caller will do data-copy. + */ +uint32_t EMAC_GetAvailRXBufSize(EMAC_MEMMGR_T *psMemMgr, uint8_t **ppuDataBuf) +{ + EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)psMemMgr->psCurrentRxDesc; + + if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) /* ownership=CPU */ + { + uint32_t status = desc->u32Status1 >> 16; + + /* It is good and no CRC error. */ + if ((status & EMAC_RXFD_RXGD) && !(status & EMAC_RXFD_CRCE)) + { + *ppuDataBuf = (uint8_t *)desc->u32Data; + return desc->u32Status1 & 0xFFFFUL; + } + else + { + // Drop it + EMAC_RecvPktDone(psMemMgr); + } + } + + return 0; +} + + +/** + * @brief Clean up process after a packet is received. + * @param None + * @return None + * @details Caller must call the function to release the resource. + * @note Application can only call this function once every time \ref EMAC_RecvPkt or \ref EMAC_RecvPktTS returns 1 + * @note This function is without doing EMAC_TRIGGER_RX. + */ +void EMAC_RecvPktDoneWoRxTrigger(EMAC_MEMMGR_T *psMemMgr) +{ + /* Get Rx Frame Descriptor */ + EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)psMemMgr->psCurrentRxDesc; + + /* Restore descriptor link list and data pointer they will be overwrite if time stamp enabled */ + desc->u32Data = desc->u32Backup1; + desc->u32Next = desc->u32Backup2; + + /* Change ownership to DMA for next use */ + desc->u32Status1 |= EMAC_DESC_OWN_EMAC; + + /* Get Next Frame Descriptor pointer to process */ + desc = (EMAC_DESCRIPTOR_T *)desc->u32Next; + + /* Save last processed Rx descriptor */ + psMemMgr->psCurrentRxDesc = desc; +} + + +/*@}*/ /* end of group EMAC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group EMAC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_etimer.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_etimer.c new file mode 100644 index 0000000000..f34db44f6f --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_etimer.c @@ -0,0 +1,341 @@ +/**************************************************************************//** + * @file etimer.c + * @brief N9H30 series ETIMER driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "N9H30.h" +#include "nu_sys.h" + +/// @cond HIDDEN_SYMBOLS +/** + * @brief This API is used to get the clock frequency of Timer + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return Timer clock frequency + * @note This API cannot return correct clock rate if timer source is external clock input. + */ +UINT ETIMER_GetModuleClock(UINT timer) +{ + UINT src; + + src = (inpw(REG_CLK_DIVCTL8) >> (16 + timer * 4)) & 0x3; + + if (src == 0) + return 12000000; + else if (src == 1) + return (sysGetClock(SYS_PCLK) * 1000000); + else if (src == 2) + return (sysGetClock(SYS_PCLK) * 1000000 / 4096); + else + return 32768; + +} + +/// @endcond /* HIDDEN_SYMBOLS */ + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_ETIMER_Driver ETIMER Driver + @{ +*/ + + +/** @addtogroup N9H30_ETIMER_EXPORTED_FUNCTIONS ETIMER Exported Functions + @{ +*/ + +/** + * @brief This API is used to configure timer to operate in specified mode + * and frequency. If timer cannot work in target frequency, a closest + * frequency will be chose and returned. + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @param[in] u32Mode Operation mode. Possible options are + * - \ref ETIMER_ONESHOT_MODE + * - \ref ETIMER_PERIODIC_MODE + * - \ref ETIMER_TOGGLE_MODE + * - \ref ETIMER_CONTINUOUS_MODE + * @param[in] u32Freq Target working frequency + * @return Real Timer working frequency + * @note After calling this API, Timer is \b NOT running yet. But could start timer running be calling + * \ref ETIMER_Start macro or program registers directly + */ +UINT ETIMER_Open(UINT timer, UINT u32Mode, UINT u32Freq) +{ + UINT u32Clk = ETIMER_GetModuleClock(timer); + UINT u32Cmpr = 0, u32Prescale = 0; + + // Fastest possible timer working freq is u32Clk / 2. While cmpr = 2, pre-scale = 0 + if (u32Freq > (u32Clk / 2)) + { + u32Cmpr = 2; + } + else + { + if (u32Clk >= 0x4000000) + { + u32Prescale = 7; // real prescaler value is 8 + u32Clk >>= 3; + } + else if (u32Clk >= 0x2000000) + { + u32Prescale = 3; // real prescaler value is 4 + u32Clk >>= 2; + } + else if (u32Clk >= 0x1000000) + { + u32Prescale = 1; // real prescaler value is 2 + u32Clk >>= 1; + } + u32Cmpr = u32Clk / u32Freq; + } + + if (timer == 0) + { + outpw(REG_ETMR0_CMPR, u32Cmpr); + outpw(REG_ETMR0_PRECNT, u32Prescale); + outpw(REG_ETMR0_CTL, 1 | u32Mode); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CMPR, u32Cmpr); + outpw(REG_ETMR1_PRECNT, u32Prescale); + outpw(REG_ETMR1_CTL, 1 | u32Mode); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CMPR, u32Cmpr); + outpw(REG_ETMR2_PRECNT, u32Prescale); + outpw(REG_ETMR2_CTL, 1 | u32Mode); + } + else + { + outpw(REG_ETMR3_CMPR, u32Cmpr); + outpw(REG_ETMR3_PRECNT, u32Prescale); + outpw(REG_ETMR3_CTL, 1 | u32Mode); + } + + return (u32Clk / (u32Cmpr * (u32Prescale + 1))); +} + +/** + * @brief This API stops Timer counting and disable the Timer interrupt function + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +void ETIMER_Close(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_CTL, 0); + outpw(REG_ETMR0_IER, 0); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, 0); + outpw(REG_ETMR1_IER, 0); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, 0); + outpw(REG_ETMR2_IER, 0); + } + else + { + outpw(REG_ETMR3_CTL, 0); + outpw(REG_ETMR3_IER, 0); + } +} + +/** + * @brief This API is used to create a delay loop for u32usec micro seconds + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @param[in] u32Usec Delay period in micro seconds with 10 usec every step. Valid values are between 10~1000000 (10 micro second ~ 1 second) + * @return None + * @note This API overwrites the register setting of the timer used to count the delay time. + * @note This API use polling mode. So there is no need to enable interrupt for the timer module used to generate delay + */ +void ETIMER_Delay(UINT timer, UINT u32Usec) +{ + UINT u32Clk = ETIMER_GetModuleClock(timer); + UINT u32Prescale = 0, delay = 300000000 / u32Clk; + float fCmpr; + + // Clear current timer configuration + if (timer == 0) + { + outpw(REG_ETMR0_CTL, 0); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, 0); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, 0); + } + else + { + outpw(REG_ETMR3_CTL, 0); + } + + if (u32Clk == 10000) // min delay is 100us if timer clock source is LIRC 10k + { + u32Usec = ((u32Usec + 99) / 100) * 100; + } + else // 10 usec every step + { + u32Usec = ((u32Usec + 9) / 10) * 10; + } + + if (u32Clk >= 0x4000000) + { + u32Prescale = 7; // real prescaler value is 8 + u32Clk >>= 3; + } + else if (u32Clk >= 0x2000000) + { + u32Prescale = 3; // real prescaler value is 4 + u32Clk >>= 2; + } + else if (u32Clk >= 0x1000000) + { + u32Prescale = 1; // real prescaler value is 2 + u32Clk >>= 1; + } + + // u32Usec * u32Clk might overflow if using UINT + fCmpr = ((float)u32Usec * (float)u32Clk) / 1000000.0; + + if (timer == 0) + { + outpw(REG_ETMR0_CMPR, (UINT)fCmpr); + outpw(REG_ETMR0_PRECNT, u32Prescale); + outpw(REG_ETMR0_CTL, 1); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CMPR, (UINT)fCmpr); + outpw(REG_ETMR1_PRECNT, u32Prescale); + outpw(REG_ETMR1_CTL, 1); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CMPR, (UINT)fCmpr); + outpw(REG_ETMR2_PRECNT, u32Prescale); + outpw(REG_ETMR2_CTL, 1); + } + else + { + outpw(REG_ETMR3_CMPR, (UINT)fCmpr); + outpw(REG_ETMR3_PRECNT, u32Prescale); + outpw(REG_ETMR3_CTL, 1); + } + + // When system clock is faster than timer clock, it is possible timer active bit cannot set in time while we check it. + // And the while loop below return immediately, so put a tiny delay here allowing timer start counting and raise active flag. + for (; delay > 0; delay--) + { +#if defined (__GNUC__) && !(__CC_ARM) + __asm__ __volatile__ + ( + "nop \n" + ); +#else + __asm + { + NOP + } +#endif + } + + if (timer == 0) + { + while (inpw(REG_ETMR0_CTL) & 0x80); + } + else if (timer == 1) + { + while (inpw(REG_ETMR1_CTL) & 0x80); + } + else if (timer == 2) + { + while (inpw(REG_ETMR2_CTL) & 0x80); + } + else + { + while (inpw(REG_ETMR3_CTL) & 0x80); + } +} + +/** + * @brief This API is used to enable timer capture function with specified mode and capture edge + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @param[in] u32CapMode Timer capture mode. Could be + * - \ref ETIMER_CAPTURE_FREE_COUNTING_MODE + * - \ref ETIMER_CAPTURE_TRIGGER_COUNTING_MODE + * - \ref ETIMER_CAPTURE_COUNTER_RESET_MODE + * @param[in] u32Edge Timer capture edge. Possible values are + * - \ref ETIMER_CAPTURE_FALLING_EDGE + * - \ref ETIMER_CAPTURE_RISING_EDGE + * - \ref ETIMER_CAPTURE_FALLING_THEN_RISING_EDGE + * - \ref ETIMER_CAPTURE_RISING_THEN_FALLING_EDGE + * @return None + * @note Timer frequency should be configured separately by using \ref ETIMER_Open API, or program registers directly + */ +void ETIMER_EnableCapture(UINT timer, UINT u32CapMode, UINT u32Edge) +{ + if (timer == 0) + { + outpw(REG_ETMR0_CTL, (inpw(REG_ETMR0_CTL) & ~0x1E0000) | u32CapMode | u32Edge | 0x10000); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, (inpw(REG_ETMR1_CTL) & ~0x1E0000) | u32CapMode | u32Edge | 0x10000); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, (inpw(REG_ETMR2_CTL) & ~0x1E0000) | u32CapMode | u32Edge | 0x10000); + } + else + { + outpw(REG_ETMR3_CTL, (inpw(REG_ETMR3_CTL) & ~0x1E0000) | u32CapMode | u32Edge | 0x10000); + } +} + +/** + * @brief This API is used to disable the Timer capture function + * @param[in] timer ETIMER number. Range from 0 ~ 3 + * @return None + */ +void ETIMER_DisableCapture(UINT timer) +{ + if (timer == 0) + { + outpw(REG_ETMR0_CTL, inpw(REG_ETMR0_CTL) & ~0x10000); + } + else if (timer == 1) + { + outpw(REG_ETMR1_CTL, inpw(REG_ETMR1_CTL) & ~0x10000); + } + else if (timer == 2) + { + outpw(REG_ETMR2_CTL, inpw(REG_ETMR2_CTL) & ~0x10000); + } + else + { + outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) & ~0x10000); + } + +} + + +/*@}*/ /* end of group N9H30_ETIMER_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_ETIMER_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_fmi.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_fmi.c new file mode 100644 index 0000000000..3f80d5fbb2 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_fmi.c @@ -0,0 +1,920 @@ +/**************************************************************************//** + * @file fmi.c + * @brief N9H30 FMI eMMC driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include +#include +#include +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_fmi.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_FMI_Driver FMI Driver + @{ +*/ + + +/** @addtogroup N9H30_FMI_EXPORTED_FUNCTIONS FMI Exported Functions + @{ +*/ +/// @cond HIDDEN_SYMBOLS + +#define FMI_BLOCK_SIZE 512 + +// global variables +// For response R3 (such as ACMD41, CRC-7 is invalid; but FMI controller will still +// calculate CRC-7 and get an error result, software should ignore this error and clear INTSTS [CRC_IF] flag +// _fmi_uR3_CMD is the flag for it. 1 means software should ignore CRC-7 error +unsigned int _fmi_uR3_CMD = 0; +unsigned int _fmi_uR7_CMD = 0; +unsigned char volatile _fmi_eMMCDataReady = FALSE; + +unsigned char *_fmi_peMMCBuffer; +unsigned int gFMIReferenceClock; + +#ifdef __ICCARM__ + #pragma data_alignment = 4096 + unsigned char _fmi_uceMMCBuffer[512]; +#else + unsigned char _fmi_uceMMCBuffer[512] __attribute__((aligned(4096))); +#endif + +int emmc_ok = 0; + +unsigned char peMMC_offset = 0; + +EMMC_INFO_T eMMC; + +void eMMC_CheckRB() +{ + while (1) + { + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk); + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk); + if (inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_DAT0STS_Msk) + break; + } +} + + +int eMMC_Command(EMMC_INFO_T *pSD, unsigned char ucCmd, unsigned int uArg) +{ + volatile int buf; + + outpw(REG_FMI_EMMCCMD, uArg); + buf = (inpw(REG_FMI_EMMCCTL) & (~FMI_EMMCCTL_CMDCODE_Msk)) | (ucCmd << 8) | (FMI_EMMCCTL_COEN_Msk); + outpw(REG_FMI_EMMCCTL, buf); + + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_COEN_Msk) + { + if (pSD->IsCardInsert == FALSE) + return EMMC_NO_CARD; + } + return 0; +} + + +int eMMC_CmdAndRsp(EMMC_INFO_T *pSD, unsigned char ucCmd, unsigned int uArg, int ntickCount) +{ + volatile int buf; + + outpw(REG_FMI_EMMCCMD, uArg); + buf = (inpw(REG_FMI_EMMCCTL) & (~FMI_EMMCCTL_CMDCODE_Msk)) | (ucCmd << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk); + outpw(REG_FMI_EMMCCTL, buf); + + if (ntickCount > 0) + { + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_RIEN_Msk) + { + if (ntickCount-- == 0) + { + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CTLRST_Msk); // reset SD engine + return 2; + } + if (pSD->IsCardInsert == FALSE) + return EMMC_NO_CARD; + } + } + else + { + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_RIEN_Msk) + { + if (pSD->IsCardInsert == FALSE) + return EMMC_NO_CARD; + } + } + + if (_fmi_uR7_CMD) + { + if (((inpw(REG_FMI_EMMCRESP1) & 0xff) != 0x55) && ((inpw(REG_FMI_EMMCRESP0) & 0xf) != 0x01)) + { + _fmi_uR7_CMD = 0; + return EMMC_CMD8_ERROR; + } + } + + if (!_fmi_uR3_CMD) + { + if (inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC7_Msk) // check CRC7 + return 0; + else + return EMMC_CRC7_ERROR; + } + else // ignore CRC error for R3 case + { + _fmi_uR3_CMD = 0; + outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_CRCIF_Msk); + return 0; + } +} + +int eMMC_Swap32(int val) +{ + int buf; + + buf = val; + val <<= 24; + val |= (buf << 8) & 0xff0000; + val |= (buf >> 8) & 0xff00; + val |= (buf >> 24) & 0xff; + return val; +} + +// Get 16 bytes CID or CSD +int eMMC_CmdAndRsp2(EMMC_INFO_T *pSD, unsigned char ucCmd, unsigned int uArg, unsigned int *puR2ptr) +{ + unsigned int i, buf; + unsigned int tmpBuf[5]; + + outpw(REG_FMI_EMMCCMD, uArg); + buf = (inpw(REG_FMI_EMMCCTL) & (~FMI_EMMCCTL_CMDCODE_Msk)) | (ucCmd << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_R2EN_Msk); + outpw(REG_FMI_EMMCCTL, buf); + + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_R2EN_Msk) + { + if (pSD->IsCardInsert == FALSE) + return EMMC_NO_CARD; + } + + if (inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC7_Msk) + { + for (i = 0; i < 5; i++) + tmpBuf[i] = eMMC_Swap32(*(int *)(FMI_BA + i * 4)); + for (i = 0; i < 4; i++) + *puR2ptr++ = ((tmpBuf[i] & 0x00ffffff) << 8) | ((tmpBuf[i + 1] & 0xff000000) >> 24); + return 0; + } + else + return EMMC_CRC7_ERROR; +} + + +int eMMC_CmdAndRspDataIn(EMMC_INFO_T *pSD, unsigned char ucCmd, unsigned int uArg) +{ + volatile int buf; + + outpw(REG_FMI_EMMCCMD, uArg); + buf = (inpw(REG_FMI_EMMCCTL) & (~FMI_EMMCCTL_CMDCODE_Msk)) | (ucCmd << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk | FMI_EMMCCTL_DIEN_Msk); + outpw(REG_FMI_EMMCCTL, buf); + + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_RIEN_Msk) + { + if (pSD->IsCardInsert == FALSE) + return EMMC_NO_CARD; + } + + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_DIEN_Msk) + { + if (pSD->IsCardInsert == FALSE) + return EMMC_NO_CARD; + } + + if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC7_Msk)) // check CRC7 + { + return EMMC_CRC7_ERROR; + } + + if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC16_Msk)) // check CRC16 + { + return EMMC_CRC16_ERROR; + } + return 0; +} + +// there are 3 bits for divider N0, maximum is 8 +#define EMMC_CLK_DIV0_MAX 8 +// there are 8 bits for divider N1, maximum is 256 +#define EMMC_CLK_DIV1_MAX 256 + +void eMMC_Set_clock(unsigned int clock_khz) +{ + UINT32 rate, div0, div1, i; + + //--- calculate the rate that 2 divider have to divide + // _fmi_uFMIReferenceClock is the input clock with unit KHz like as APLL/UPLL and + if (clock_khz > gFMIReferenceClock) + { + //sysprintf("ERROR: wrong eMMC clock %dKHz since it is faster than input clock %dKHz !\n", clock_khz, gFMIReferenceClock); + return; + } + rate = gFMIReferenceClock / clock_khz; + // choose slower clock if system clock cannot divisible by wanted clock + if (gFMIReferenceClock % clock_khz != 0) + rate++; + + if (rate > (EMMC_CLK_DIV0_MAX * EMMC_CLK_DIV1_MAX)) // the maximum divider for EMMC_CLK is (EMMC_CLK_DIV0_MAX * EMMC_CLK_DIV1_MAX) + { + //sysprintf("ERROR: wrong SD clock %dKHz since it is slower than input clock %dKHz/%d !\n", clock_khz, gFMIReferenceClock, EMMC_CLK_DIV0_MAX * EMMC_CLK_DIV1_MAX); + return; + } + + //--- choose a suitable value for first divider + for (div0 = EMMC_CLK_DIV0_MAX; div0 > 0; div0--) // choose the maximum value if can exact division + { + if (rate % div0 == 0) + break; + } + if (div0 == 0) // cannot exact division + { + // if rate <= EMMC_CLK_DIV1_MAX, set div0 to 1 since div1 can exactly divide input clock + div0 = (rate <= EMMC_CLK_DIV1_MAX) ? 1 : EMMC_CLK_DIV0_MAX; + } + + //--- calculate the second divider + div1 = rate / div0; + div1 &= 0xFF; + + //sysprintf("Set_clock(): wanted clock=%d, rate=%d, div0=%d, div1=%d\n", clock_khz, rate, div0, div1); + + //--- setup register + outpw(REG_CLK_DIVCTL3, (inpw(REG_CLK_DIVCTL3) & ~0x18) | (0x3 << 3)); + outpw(REG_CLK_DIVCTL3, (inpw(REG_CLK_DIVCTL3) & ~0x7) | (div0 - 1)); + outpw(REG_CLK_DIVCTL3, (inpw(REG_CLK_DIVCTL3) & ~0xff00) | ((div1 - 1) << 8)); + for (i = 0; i < 1000; i++); // waiting for clock become stable + return; +} + +// Initial +int eMMC_Init(EMMC_INFO_T *pSD) +{ + int volatile i, status; + unsigned int resp; + unsigned int CIDBuffer[4]; + unsigned int volatile u32CmdTimeOut; + + // set the clock to 300KHz + eMMC_Set_clock(300); + + // power ON 74 clock + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK74OEN_Msk); + + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK74OEN_Msk); + + eMMC_Command(pSD, 0, 0); // reset all cards + for (i = 0x1000; i > 0; i--); + + // initial SDHC + _fmi_uR7_CMD = 1; + u32CmdTimeOut = 5000; + + i = eMMC_CmdAndRsp(pSD, 8, 0x00000155, u32CmdTimeOut); + if (i == 0) + { + // SD 2.0 + eMMC_CmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut); + _fmi_uR3_CMD = 1; + eMMC_CmdAndRsp(pSD, 41, 0x40ff8000, u32CmdTimeOut); // 2.7v-3.6v + resp = inpw(REG_FMI_EMMCRESP0); + + while (!(resp & 0x00800000)) // check if card is ready + { + eMMC_CmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut); + _fmi_uR3_CMD = 1; + eMMC_CmdAndRsp(pSD, 41, 0x40ff8000, u32CmdTimeOut); // 3.0v-3.4v + resp = inpw(REG_FMI_EMMCRESP0); + } + if (resp & 0x00400000) + pSD->CardType = EMMC_TYPE_SD_HIGH; + else + pSD->CardType = EMMC_TYPE_SD_LOW; + } + else + { + // SD 1.1 + eMMC_Command(pSD, 0, 0); // reset all cards + for (i = 0x100; i > 0; i--); + + i = eMMC_CmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut); + if (i == 2) // MMC memory + { + + eMMC_Command(pSD, 0, 0); // reset + for (i = 0x100; i > 0; i--); + + _fmi_uR3_CMD = 1; + + if (eMMC_CmdAndRsp(pSD, 1, 0x40ff8000, u32CmdTimeOut) != 2) // eMMC memory + { + resp = inpw(REG_FMI_EMMCRESP0); + while (!(resp & 0x00800000)) // check if card is ready + { + _fmi_uR3_CMD = 1; + + eMMC_CmdAndRsp(pSD, 1, 0x40ff8000, u32CmdTimeOut); // high voltage + resp = inpw(REG_FMI_EMMCRESP0); + } + + if (resp & 0x00400000) + pSD->CardType = EMMC_TYPE_EMMC; + else + pSD->CardType = EMMC_TYPE_MMC; + } + else + { + pSD->CardType = EMMC_TYPE_UNKNOWN; + return EMMC_ERR_DEVICE; + } + } + else if (i == 0) // SD Memory + { + _fmi_uR3_CMD = 1; + eMMC_CmdAndRsp(pSD, 41, 0x00ff8000, u32CmdTimeOut); // 3.0v-3.4v + resp = inpw(REG_FMI_EMMCRESP0); + while (!(resp & 0x00800000)) // check if card is ready + { + eMMC_CmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut); + _fmi_uR3_CMD = 1; + eMMC_CmdAndRsp(pSD, 41, 0x00ff8000, u32CmdTimeOut); // 3.0v-3.4v + resp = inpw(REG_FMI_EMMCRESP0); + } + pSD->CardType = EMMC_TYPE_SD_LOW; + } + else + { + pSD->CardType = EMMC_TYPE_UNKNOWN; + return EMMC_INIT_ERROR; + } + } + + // CMD2, CMD3 + if (pSD->CardType != EMMC_TYPE_UNKNOWN) + { + eMMC_CmdAndRsp2(pSD, 2, 0x00, CIDBuffer); + if ((pSD->CardType == EMMC_TYPE_MMC) || (pSD->CardType == EMMC_TYPE_EMMC)) + { + if ((status = eMMC_CmdAndRsp(pSD, 3, 0x10000, 0)) != 0) // set RCA + return status; + pSD->RCA = 0x10000; + } + else + { + if ((status = eMMC_CmdAndRsp(pSD, 3, 0x00, 0)) != 0) // get RCA + return status; + else + pSD->RCA = (inpw(REG_FMI_EMMCRESP0) << 8) & 0xffff0000; + } + } + +#if 0 + if (pSD->CardType == EMMC_TYPE_SD_HIGH) + sysprintf("This is high capacity SD memory card\n"); + if (pSD->CardType == EMMC_TYPE_SD_LOW) + sysprintf("This is standard capacity SD memory card\n"); + if (pSD->CardType == EMMC_TYPE_EMMC) + sysprintf("This is eMMC memory card\n"); +#endif + return 0; +} + + +int eMMC_SwitchToHighSpeed(EMMC_INFO_T *pSD) +{ + int volatile status = 0; + unsigned short current_comsumption, busy_status0; + + outpw(REG_FMI_DMASA, (unsigned int)_fmi_peMMCBuffer); // set DMA transfer starting address + outpw(REG_FMI_EMMCBLEN, 63); // 512 bit + + if ((status = eMMC_CmdAndRspDataIn(pSD, 6, 0x00ffff01)) != 0) + return 1; + + current_comsumption = _fmi_peMMCBuffer[0] << 8 | _fmi_peMMCBuffer[1]; + if (!current_comsumption) + return 1; + + busy_status0 = _fmi_peMMCBuffer[28] << 8 | _fmi_peMMCBuffer[29]; + + if (!busy_status0) // function ready + { + outpw(REG_FMI_DMASA, (unsigned int)_fmi_peMMCBuffer); // set DMA transfer starting address + outpw(REG_FMI_EMMCBLEN, 63); // 512 bit + + if ((status = eMMC_CmdAndRspDataIn(pSD, 6, 0x80ffff01)) != 0) + return 1; + + // function change timing: 8 clocks + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk); + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk); + + current_comsumption = _fmi_peMMCBuffer[0] << 8 | _fmi_peMMCBuffer[1]; + if (!current_comsumption) + return 1; + + return 0; + } + else + return 1; +} + + +int eMMC_SelectCardType(EMMC_INFO_T *pSD) +{ + int volatile status = 0; + //unsigned int arg; + + if ((status = eMMC_CmdAndRsp(pSD, 7, pSD->RCA, 0)) != 0) + return status; + + eMMC_CheckRB(); + + // if SD card set 4bit + if (pSD->CardType == EMMC_TYPE_SD_HIGH) + { + _fmi_peMMCBuffer = (unsigned char *)((unsigned int)_fmi_uceMMCBuffer); + outpw(REG_FMI_DMASA, (unsigned int)_fmi_peMMCBuffer); // set DMA transfer starting address + outpw(REG_FMI_EMMCBLEN, 0x07); // 64 bit + + if ((status = eMMC_CmdAndRsp(pSD, 55, pSD->RCA, 0)) != 0) + return status; + if ((status = eMMC_CmdAndRspDataIn(pSD, 51, 0x00)) != 0) + return status; + + if ((_fmi_uceMMCBuffer[0] & 0xf) == 0x2) + { + status = eMMC_SwitchToHighSpeed(pSD); + if (status == 0) + { + /* divider */ + eMMC_Set_clock(SDHC_FREQ); + } + } + + if ((status = eMMC_CmdAndRsp(pSD, 55, pSD->RCA, 0)) != 0) + return status; + if ((status = eMMC_CmdAndRsp(pSD, 6, 0x02, 0)) != 0) // set bus width + return status; + + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_DBW_Msk); + } + else if (pSD->CardType == EMMC_TYPE_SD_LOW) + { + _fmi_peMMCBuffer = (unsigned char *)((unsigned int)_fmi_uceMMCBuffer); + outpw(REG_FMI_DMASA, (unsigned int) _fmi_peMMCBuffer); // set DMA transfer starting address + outpw(REG_FMI_EMMCBLEN, 0x07); // 64 bit + + if ((status = eMMC_CmdAndRsp(pSD, 55, pSD->RCA, 0)) != 0) + return status; + if ((status = eMMC_CmdAndRspDataIn(pSD, 51, 0x00)) != 0) + return status; + + // set data bus width. ACMD6 for SD card, SDCR_DBW for host. + if ((status = eMMC_CmdAndRsp(pSD, 55, pSD->RCA, 0)) != 0) + return status; + + if ((status = eMMC_CmdAndRsp(pSD, 6, 0x02, 0)) != 0) // set bus width + return status; + + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_DBW_Msk); + } + else if (pSD->CardType == EMMC_TYPE_MMC) + { + + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) & ~FMI_EMMCCTL_DBW_Msk); + + } + else if (pSD->CardType == EMMC_TYPE_EMMC) + { + + //--- sent CMD6 to MMC card to set bus width to 4 bits mode, skymedi only support 1-bit + // set CMD6 argument Access field to 3, Index to 183, Value to 1 (4-bit mode) +// arg = (3 << 24) | (183 << 16) | (1 << 8); +// if ((status = eMMC_CmdAndRsp(pSD, 6, arg, 0)) != 0) +// return status; +// eMMC_CheckRB(); + +// outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL)| FMI_EMMCCTL_DBW_Msk); + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) & ~FMI_EMMCCTL_DBW_Msk); + } + + if ((status = eMMC_CmdAndRsp(pSD, 16, FMI_BLOCK_SIZE, 0)) != 0) // set block length + return status; + outpw(REG_FMI_EMMCBLEN, FMI_BLOCK_SIZE - 1); // set the block size + + eMMC_Command(pSD, 7, 0); + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk); + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk); + + outpw(REG_FMI_EMMCINTEN, inpw(REG_FMI_EMMCINTEN) | FMI_EMMCINTEN_BLKDIEN_Msk); + + return 0; +} + +void eMMC_Get_info(EMMC_INFO_T *pSD) +{ + unsigned int R_LEN, C_Size, MULT, size; + unsigned int Buffer[4]; + unsigned char *ptr; + + eMMC_CmdAndRsp2(pSD, 9, pSD->RCA, Buffer); + + if ((pSD->CardType == EMMC_TYPE_MMC) || (pSD->CardType == EMMC_TYPE_EMMC)) + { + // for MMC/eMMC card + if ((Buffer[0] & 0xc0000000) == 0xc0000000) + { + // CSD_STRUCTURE [127:126] is 3 + // CSD version depend on EXT_CSD register in eMMC v4.4 for card size > 2GB + eMMC_CmdAndRsp(pSD, 7, pSD->RCA, 0); + + ptr = (unsigned char *)((unsigned int)_fmi_uceMMCBuffer); + outpw(REG_FMI_DMASA, (unsigned int)ptr); // set DMA transfer starting address + outpw(REG_FMI_EMMCBLEN, 511); // read 512 bytes for EXT_CSD + + if (eMMC_CmdAndRspDataIn(pSD, 8, 0x00) != 0) + return; + + eMMC_Command(pSD, 7, 0); + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk); + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk); + + pSD->totalSectorN = (*(unsigned int *)(ptr + 212)); + pSD->diskSize = pSD->totalSectorN / 2; + } + else + { + // CSD version v1.0/1.1/1.2 in eMMC v4.4 spec for card size <= 2GB + R_LEN = (Buffer[1] & 0x000f0000) >> 16; + C_Size = ((Buffer[1] & 0x000003ff) << 2) | ((Buffer[2] & 0xc0000000) >> 30); + MULT = (Buffer[2] & 0x00038000) >> 15; + size = (C_Size + 1) * (1 << (MULT + 2)) * (1 << R_LEN); + + pSD->diskSize = size / 1024; + pSD->totalSectorN = size / 512; + } + } + else + { + if (Buffer[0] & 0xc0000000) + { + C_Size = ((Buffer[1] & 0x0000003f) << 16) | ((Buffer[2] & 0xffff0000) >> 16); + size = (C_Size + 1) * 512; // Kbytes + + pSD->diskSize = size; + pSD->totalSectorN = size << 1; + } + else + { + R_LEN = (Buffer[1] & 0x000f0000) >> 16; + C_Size = ((Buffer[1] & 0x000003ff) << 2) | ((Buffer[2] & 0xc0000000) >> 30); + MULT = (Buffer[2] & 0x00038000) >> 15; + size = (C_Size + 1) * (1 << (MULT + 2)) * (1 << R_LEN); + + pSD->diskSize = size / 1024; + pSD->totalSectorN = size / 512; + } + } + pSD->sectorSize = 512; + //sysprintf("The size is %d KB\n", pSD->diskSize); +} + +/// @endcond HIDDEN_SYMBOLS + +/** + * @brief This function use to tell FMI eMMC engine clock. + * + * @param[in] u32Clock Set current eMMC engine clock + * + * @return None + */ +void FMI_SetReferenceClock(unsigned int u32Clock) +{ + gFMIReferenceClock = u32Clock; // kHz +} + +/** + * @brief This function use to reset FMI eMMC function. + * + * @return None + */ +void eMMC_Open(void) +{ + // enable DMAC + outpw(REG_FMI_DMACTL, FMI_DMACTL_DMARST_Msk); + while (inpw(REG_FMI_DMACTL) & FMI_DMACTL_DMARST_Msk); + + outpw(REG_FMI_DMACTL, FMI_DMACTL_DMAEN_Msk); + + //Reset Global + outpw(REG_FMI_CTL, FMI_CTL_CTLRST_Msk); + while (inpw(REG_FMI_CTL) & FMI_CTL_CTLRST_Msk); + + // enable eMMC + outpw(REG_FMI_CTL, FMI_CTL_EMMCEN_Msk); + + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CTLRST_Msk); + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CTLRST_Msk); + + memset(&eMMC, 0, sizeof(EMMC_INFO_T)); + eMMC.IsCardInsert = 1; +} + +/** + * @brief This function use to initial eMMC card. + * + * @return None + */ +void eMMC_Probe(void) +{ + // Disable FMI interrupt + outpw(REG_FMI_INTEN, 0); + + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) & ~(FMI_EMMCCTL_SDNWR_Msk | FMI_EMMCCTL_BLKCNT_Msk | FMI_EMMCCTL_DBW_Msk)); + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | (0x09 << FMI_EMMCCTL_SDNWR_Pos) | (0x01 << FMI_EMMCCTL_BLKCNT_Pos)); + + if (eMMC_Init(&eMMC) < 0) + return; + + /* divider */ + if ((eMMC.CardType == EMMC_TYPE_MMC) || (eMMC.CardType == EMMC_TYPE_EMMC)) + eMMC_Set_clock(MMC_FREQ); + else + eMMC_Set_clock(SD_FREQ); + + eMMC_Get_info(&eMMC); + + if (eMMC_SelectCardType(&eMMC)) + return; + + emmc_ok = 1; +} + +/** + * @brief This function use to read data from eMMC card. + * + * @param[out] pu8BufAddr The buffer to receive the data from eMMC card. + * @param[in] u32StartSec The start read sector address. + * @param[in] u32SecCount The the read sector number of data + * + * @return None + */ +unsigned int eMMC_Read(unsigned char *pu8BufAddr, unsigned int u32StartSec, unsigned int u32SecCount) +{ + char volatile bIsSendCmd = FALSE; + unsigned int volatile reg; + int volatile i, loop, status; + unsigned int blksize = FMI_BLOCK_SIZE; + + EMMC_INFO_T *pSD; + pSD = &eMMC; + + //--- check input parameters + if (u32SecCount == 0) + return EMMC_SELECT_ERROR; + + if ((status = eMMC_CmdAndRsp(pSD, 7, pSD->RCA, 0)) != 0) + return status; + eMMC_CheckRB(); + + outpw(REG_FMI_EMMCBLEN, blksize - 1); // the actual byte count is equal to (BLEN+1) + + if ((pSD->CardType == EMMC_TYPE_SD_HIGH) || (pSD->CardType == EMMC_TYPE_EMMC)) + outpw(REG_FMI_EMMCCMD, u32StartSec); + else + outpw(REG_FMI_EMMCCMD, u32StartSec * blksize); + + outpw(REG_FMI_DMASA, (unsigned int)pu8BufAddr); + + loop = u32SecCount / 255; + for (i = 0; i < loop; i++) + { + _fmi_eMMCDataReady = FALSE; + + reg = inpw(REG_FMI_EMMCCTL) & ~FMI_EMMCCTL_CMDCODE_Msk; + reg = reg | 0xff0000; + if (bIsSendCmd == FALSE) + { + outpw(REG_FMI_EMMCCTL, reg | (18 << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk | FMI_EMMCCTL_DIEN_Msk)); + bIsSendCmd = TRUE; + } + else + outpw(REG_FMI_EMMCCTL, reg | FMI_EMMCCTL_DIEN_Msk); + + while (!_fmi_eMMCDataReady) + { +// if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_BLKDIF_Msk) && (!(inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_DIEN_Msk))) { +// outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_BLKDIF_Msk); +// break; +// } + if (pSD->IsCardInsert == FALSE) + return EMMC_NO_CARD; + } + + if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC7_Msk)) // check CRC7 + { + return EMMC_CRC7_ERROR; + } + + if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC16_Msk)) // check CRC16 + { + return EMMC_CRC16_ERROR; + } + } + + loop = u32SecCount % 255; + if (loop != 0) + { + _fmi_eMMCDataReady = FALSE; + + reg = inpw(REG_FMI_EMMCCTL) & (~FMI_EMMCCTL_CMDCODE_Msk); + reg = reg & (~FMI_EMMCCTL_BLKCNT_Msk); + reg |= (loop << 16); + + if (bIsSendCmd == FALSE) + { + outpw(REG_FMI_EMMCCTL, reg | (18 << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk | FMI_EMMCCTL_DIEN_Msk)); + bIsSendCmd = TRUE; + } + else + outpw(REG_FMI_EMMCCTL, reg | FMI_EMMCCTL_DIEN_Msk); + + while (!_fmi_eMMCDataReady) + { +// if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_BLKDIF_Msk) && (!(inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_DIEN_Msk))) { +// outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_BLKDIF_Msk); +// break; +// } + if (pSD->IsCardInsert == FALSE) + return EMMC_NO_CARD; + } + + if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC7_Msk)) // check CRC7 + { + return EMMC_CRC7_ERROR; + } + + if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC16_Msk)) // check CRC16 + { + return EMMC_CRC16_ERROR; + } + } + + if (eMMC_CmdAndRsp(pSD, 12, 0, 0)) // stop command + { + //sysprintf("stop command fail !!\n"); + return EMMC_CRC7_ERROR; + } + eMMC_CheckRB(); + + eMMC_Command(pSD, 7, 0); + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk); + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk); + + return 0; +} + + +/** + * @brief This function use to write data to eMMC card. + * + * @param[in] pu8BufAddr The buffer to send the data to SD card. + * @param[in] u32StartSec The start write sector address. + * @param[in] u32SecCount The the write sector number of data. + * + * @return - \ref EMMC_SELECT_ERROR u32SecCount is zero. + * - \ref EMMC_NO_CARD SD card be removed. + * - \ref EMMC_CRC_ERROR CRC error happen. + * - \ref EMMC_CRC7_ERROR CRC7 error happen. + * - \ref Successful Write data to eMMC card success. + */ +unsigned int eMMC_Write(unsigned char *pu8BufAddr, unsigned int u32StartSec, unsigned int u32SecCount) +{ + char volatile bIsSendCmd = FALSE; + unsigned int volatile reg; + int volatile i, loop, status; + + EMMC_INFO_T *pSD; + pSD = &eMMC; + + //--- check input parameters + if (u32SecCount == 0) + return EMMC_SELECT_ERROR; + + if ((status = eMMC_CmdAndRsp(pSD, 7, pSD->RCA, 0)) != 0) + return status; + + eMMC_CheckRB(); + + // According to SD Spec v2.0/ eMMC v4.4, the write CMD block size MUST be 512, and the start address MUST be 512*n. + outpw(REG_FMI_EMMCBLEN, FMI_BLOCK_SIZE - 1); // set the block size + + if ((pSD->CardType == EMMC_TYPE_SD_HIGH) || (pSD->CardType == EMMC_TYPE_EMMC)) + outpw(REG_FMI_EMMCCMD, u32StartSec); + else + outpw(REG_FMI_EMMCCMD, u32StartSec * FMI_BLOCK_SIZE); // set start address for CMD + + outpw(REG_FMI_DMASA, (unsigned int)pu8BufAddr); + loop = u32SecCount / 255; // the maximum block count is 0xFF=255 + for (i = 0; i < loop; i++) + { + _fmi_eMMCDataReady = FALSE; + + reg = inpw(REG_FMI_EMMCCTL) & 0xff00c080; + reg = reg | 0xff0000; + if (!bIsSendCmd) + { + outpw(REG_FMI_EMMCCTL, reg | (25 << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk | FMI_EMMCCTL_DOEN_Msk)); + bIsSendCmd = TRUE; + } + else + outpw(REG_FMI_EMMCCTL, reg | FMI_EMMCCTL_DOEN_Msk); + + while (!_fmi_eMMCDataReady) + { +// if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_BLKDIF_Msk) && (!(inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_DOEN_Msk))) { +// outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_BLKDIF_Msk); +// break; +// } + if (pSD->IsCardInsert == FALSE) + return EMMC_NO_CARD; + } + + if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRCIF_Msk) != 0) // check CRC + { + outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_CRCIF_Msk); + return EMMC_CRC_ERROR; + } + } + + loop = u32SecCount % 255; + if (loop != 0) + { + _fmi_eMMCDataReady = FALSE; + + reg = (inpw(REG_FMI_EMMCCTL) & 0xff00c080) | (loop << 16); + if (!bIsSendCmd) + { + outpw(REG_FMI_EMMCCTL, reg | (25 << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk | FMI_EMMCCTL_DOEN_Msk)); + bIsSendCmd = TRUE; + } + else + outpw(REG_FMI_EMMCCTL, reg | FMI_EMMCCTL_DOEN_Msk); + + while (!_fmi_eMMCDataReady) + { +// if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_BLKDIF_Msk) && (!(inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_DOEN_Msk))) { +// outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_BLKDIF_Msk); +// break; +// } + if (pSD->IsCardInsert == FALSE) + return EMMC_NO_CARD; + } + + if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRCIF_Msk) != 0) // check CRC + { + outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_CRCIF_Msk); + return EMMC_CRC_ERROR; + } + } + outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_CRCIF_Msk); + + if (eMMC_CmdAndRsp(pSD, 12, 0, 0)) // stop command + { + return EMMC_CRC7_ERROR; + } + eMMC_CheckRB(); + + eMMC_Command(pSD, 7, 0); + outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk); + while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk); + + return 0; +} + + +/*@}*/ /* end of group N9H30_FMI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_FMI_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_gpio.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_gpio.c new file mode 100644 index 0000000000..3d4fd76105 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_gpio.c @@ -0,0 +1,500 @@ +/**************************************************************************//** +* @file gpio.c +* @version V1.00 +* @brief N9H30 GPIO driver source file +* +* SPDX-License-Identifier: Apache-2.0 +* @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_gpio.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_GPIO_Driver GPIO Driver + @{ +*/ + +/** @addtogroup N9H30_GPIO_EXPORTED_FUNCTIONS GPIO Exported Functions + @{ +*/ + +/** + * @brief Set GPIO Port + * + * @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ + * @param[in] bitMap GPIO port. It could be \ref BIT0 \ref BIT1, ... or \ref BIT31 + * + * @retval <0 Fail + * @retval 0 Success + * + * @details This function is used to set GPIO port output data. + */ +INT32 GPIO_Set(GPIO_PORT port, UINT32 bitMap) +{ + INT32 offset; + INT32 reg; + + offset = (INT32)port; + + reg = inpw(REG_GPIOA_DATAOUT + offset); + reg = reg | bitMap; + outpw(REG_GPIOA_DATAOUT + offset, reg); + + return SUCCESSFUL; +} + +/** +* @brief Clear GPIO port OUT Data +* +* @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ +* @param[in] bitMap GPIO port data. It could be 0x00 ~ 0xFF. +* +* @retval <0 Fail +* @retval 0 Success +* +* @details Clear GPIO port output data to 0. +*/ +INT32 GPIO_Clr(GPIO_PORT port, UINT32 bitMap) +{ + INT32 offset; + INT32 reg; + + offset = (INT32)port; + + reg = inpw(REG_GPIOA_DATAOUT + offset); + reg = reg & (~bitMap); + outpw(REG_GPIOA_DATAOUT + offset, reg); + + return SUCCESSFUL; +} + + + +/** + * @brief Open GPIO bit + * + * @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ + * @param[in] bit GPIO pin. It could be \ref BIT0 \ref BIT1, ... or \ref BIT31 + * @param[in] direction GPIO direction. It could be \ref DIR_INPUT or \ref DIR_OUTPUT + * @param[in] pull GPIO pull-up. It could be \ref NO_PULL_UP or \ref PULL_UP + * + * @retval <0 Fail + * @retval 0 Success + * + * @details This function is used to open gpio pin. + */ +INT32 GPIO_OpenBit(GPIO_PORT port, UINT32 bit, GPIO_DIR direction, GPIO_PULL pull) +{ + UINT32 reg; + UINT32 mask; + INT32 offset; + + offset = (INT32)port; + + mask = (UINT32)bit; + + reg = inpw(REG_GPIOA_DIR + offset); + reg = reg & (~mask); + + if (direction == DIR_OUTPUT) + { + reg = reg | mask; + } + + outpw(REG_GPIOA_DIR + offset, reg); + + reg = inpw(REG_GPIOA_PUEN + offset); + reg = reg & (~mask); + + if (pull == PULL_UP) + { + reg = reg | mask; + outpw(REG_GPIOA_PUEN + offset, reg); + } + else if (pull == PULL_DOWN) + { + reg = reg | mask; + outpw(REG_GPIOA_PDEN + offset, reg); + } + else + { + outpw(REG_GPIOA_PUEN + offset, reg); + outpw(REG_GPIOA_PDEN + offset, reg); + } + + return SUCCESSFUL; +} + +/** +* @brief Set GPIO pin OUT Data +* +* @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ +* @param[in] bit GPIO pin. It could be \ref BIT0 \ref BIT1, ... or \ref BIT31 +* +* @retval <0 Fail +* @retval 0 Success +* +* @details Set the Data into specified GPIO pin. +*/ +INT32 GPIO_CloseBit(GPIO_PORT port, UINT32 bit) +{ + UINT32 reg; + UINT32 mask; + INT32 offset; + + offset = (INT32)port; + mask = (UINT32)bit; + + reg = inpw(REG_GPIOA_DIR + offset); + reg = reg & (~mask); + outpw(REG_GPIOA_DIR + offset, reg); + + reg = inpw(REG_GPIOA_PUEN + offset); + reg = reg & (~mask); + outpw(REG_GPIOA_PUEN + offset, reg); + + return SUCCESSFUL; +} + + +/** + * @brief Set GPIO pin OUT Data + * + * @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ + * @param[in] bit GPIO pin. It could be \ref BIT0 \ref BIT1, ... or \ref BIT31 + * + * @retval <0 Fail + * @retval 0 Success + * + * @details Set the Data into specified GPIO pin. + */ +INT32 GPIO_SetBit(GPIO_PORT port, UINT32 bit) +{ + UINT32 bitMap; + INT32 offset; + INT32 reg; + + offset = (INT32)port; + bitMap = (UINT32)bit; + + reg = inpw(REG_GPIOA_DATAOUT + offset); + reg = reg | bitMap; + outpw(REG_GPIOA_DATAOUT + offset, reg); + + return SUCCESSFUL; +} + +/** +* @brief Clear GPIO port Interrupt Flag +* +* @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ +* @param[in] bitMap GPIO port data. It could be 0x00 ~ 0xFF. +* +* @retval <0 Fail +* @retval 0 Success +* +* @details Clear the interrupt status of specified GPIO port. +*/ +INT32 GPIO_ClrISR(GPIO_PORT port, UINT32 bitMap) +{ + INT32 offset; + + offset = (INT32)port; + + outpw(REG_GPIOA_ISR + offset, bitMap); + + return SUCCESSFUL; +} + +/** + * @brief Clear GPIO Pin Interrupt Flag + * + * @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ + * @param[in] bit GPIO pin. It could be \ref BIT0 \ref BIT1, ... or \ref BIT31 + * + * @retval <0 Fail + * @retval 0 Success + * + * @details Clear the interrupt status of specified GPIO pin. + */ +INT32 GPIO_ClrISRBit(GPIO_PORT port, UINT32 bit) +{ + UINT32 bitMap; + INT32 offset; + + offset = (INT32)port; + bitMap = (UINT32)bit; + + outpw(REG_GPIOA_ISR + offset, bitMap); + + return SUCCESSFUL; +} + +/** +* @brief Clear GPIO pin OUT Data +* +* @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ +* @param[in] bit GPIO pin. It could be \ref BIT0 \ref BIT1, ... or \ref BIT31 +* +* @retval <0 Fail +* @retval 0 Success +* +* @details Set the Data into specified GPIO pin. +*/ +INT32 GPIO_ClrBit(GPIO_PORT port, UINT32 bit) +{ + UINT32 bitMap; + INT32 offset; + INT32 reg; + + offset = (INT32)port; + bitMap = (UINT32)bit; + + reg = inpw(REG_GPIOA_DATAOUT + offset); + reg = reg & (~bitMap); + outpw(REG_GPIOA_DATAOUT + offset, reg); + + return SUCCESSFUL; +} + +/** +* @brief Read GPIO pin In Data +* +* @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ +* @param[in] bit GPIO pin. It could be \ref BIT0 \ref BIT1, ... or \ref BIT31 +* +* @retval 1/0 GPIO pin input data. +* +* @details Read the In Data from GPIO pin. +*/ +INT32 GPIO_ReadBit(GPIO_PORT port, UINT32 bit) +{ + UINT32 reg; + UINT32 bitMap; + INT32 offset; + + offset = (INT32)port; + bitMap = (UINT32)bit; + + reg = inpw(REG_GPIOA_DATAIN + offset); + + return ((reg & bitMap) ? 1 : 0); +} + +/** +* @brief Set GPIO pin direction +* +* @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ +* @param[in] bit GPIO pin. It could be \ref BIT0 \ref BIT1, ... or \ref BIT31 +* @param[in] direction GPIO direction. It could be \ref DIR_INPUT, \ref DIR_OUTPUT. +* +* @retval <0 Fail +* @retval 0 Success +* +* @details Set the GPIO direction into specified GPIO pin. +*/ +INT32 GPIO_SetBitDir(GPIO_PORT port, UINT32 bit, GPIO_DIR direction) +{ + UINT32 reg; + UINT32 bitMap; + INT32 offset; + + offset = (INT32)port; + bitMap = (UINT32)bit; + + reg = inpw(REG_GPIOA_DIR + offset); + reg = reg & (~bitMap); + + if (direction == DIR_OUTPUT) + { + reg = reg | bitMap; + } + + outpw(REG_GPIOA_DIR + offset, reg); + + return SUCCESSFUL; +} + +/** + * @brief Enable GPIO trigger type. + * + * @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ + * @param[in] bitMap GPIO port. It could be \ref BIT0 \ref BIT1, ... or \ref BIT31 + * @param[in] triggerType The triggerType of specified GPIO pin. It could be \n + * \ref RISING, \ref FALLING, \ref BOTH_EDGE, \ref HIGH, \ref LOW. + * + * @retval <0 Fail + * @retval 0 Success + * + * @details This function is used to enable trigger type. + */ +INT32 GPIO_EnableTriggerType(GPIO_PORT port, UINT32 bitMap, GPIO_TRIGGER_TYPE triggerType) +{ + UINT32 reg; + INT32 offset; + + offset = (INT32)port; + + switch (triggerType) + { + case LOW: + reg = inpw(REG_GPIOA_IMD + offset); + outpw(REG_GPIOA_IMD + offset, reg | bitMap); + + reg = inpw(REG_GPIOA_IREN + offset); + outpw(REG_GPIOA_IREN + offset, reg & ~bitMap); + + reg = inpw(REG_GPIOA_IFEN + offset); + outpw(REG_GPIOA_IFEN + offset, reg | bitMap); + break; + case HIGH: + reg = inpw(REG_GPIOA_IMD + offset); + outpw(REG_GPIOA_IMD + offset, reg | bitMap); + + reg = inpw(REG_GPIOA_IREN + offset); + outpw(REG_GPIOA_IREN + offset, reg | bitMap); + + reg = inpw(REG_GPIOA_IFEN + offset); + outpw(REG_GPIOA_IFEN + offset, reg & ~bitMap); + break; + case FALLING: + reg = inpw(REG_GPIOA_IMD + offset); + outpw(REG_GPIOA_IMD + offset, reg & ~bitMap); + + reg = inpw(REG_GPIOA_IREN + offset); + outpw(REG_GPIOA_IREN + offset, reg & ~bitMap); + + reg = inpw(REG_GPIOA_IFEN + offset); + outpw(REG_GPIOA_IFEN + offset, reg | bitMap); + break; + case RISING: + reg = inpw(REG_GPIOA_IMD + offset); + outpw(REG_GPIOA_IMD + offset, reg & ~bitMap); + + reg = inpw(REG_GPIOA_IREN + offset); + outpw(REG_GPIOA_IREN + offset, reg | bitMap); + + reg = inpw(REG_GPIOA_IFEN + offset); + outpw(REG_GPIOA_IFEN + offset, reg & ~bitMap); + break; + case BOTH_EDGE: + reg = inpw(REG_GPIOA_IMD + offset); + outpw(REG_GPIOA_IMD + offset, reg & ~bitMap); + + reg = inpw(REG_GPIOA_IREN + offset); + outpw(REG_GPIOA_IREN + offset, reg | bitMap); + + reg = inpw(REG_GPIOA_IFEN + offset); + outpw(REG_GPIOA_IFEN + offset, reg | bitMap); + break; + } + return SUCCESSFUL; +} + +/** + * @brief Disable GPIO trigger type. + * + * @param[in] port GPIO port. It could be \ref GPIOA, \ref GPIOB, ... or \ref GPIOJ + * @param[in] bitMap GPIO port. It could be \ref BIT0 \ref BIT1, ... or \ref BIT31 + * + * @retval <0 Fail + * @retval 0 Success + * + * @details This function is used to disable trigger type. + */ +INT32 GPIO_DisableTriggerType(GPIO_PORT port, UINT32 bitMap) +{ + UINT32 reg; + INT32 offset; + + offset = (INT32)port; + + reg = inpw(REG_GPIOA_IMD + offset); + outpw(REG_GPIOA_IMD + offset, reg & ~bitMap); + + reg = inpw(REG_GPIOA_IREN + offset); + outpw(REG_GPIOA_IREN + offset, reg & ~bitMap); + + reg = inpw(REG_GPIOA_IFEN + offset); + outpw(REG_GPIOA_IFEN + offset, reg & ~bitMap); + + return SUCCESSFUL; +} + +/** + * @brief Enable GPIO De-bounce Function + * + * @param[in] debounceClkSel The de-bounce sampling cycle selection. It could be 0~0xF. \n + * 0 = Sample interrupt input once per 1 clocks. \n + * 1 = Sample interrupt input once per 2 clocks. \n + * 2 = Sample interrupt input once per 4 clocks. \n + * 3 = Sample interrupt input once per 8 clocks. \n + * 4 = Sample interrupt input once per 16 clocks. \n + * 5 = Sample interrupt input once per 32 clocks. \n + * 6 = Sample interrupt input once per 64 clocks. \n + * 7 = Sample interrupt input once per 128 clocks. \n + * 8 = Sample interrupt input once per 256 clocks. \n + * 9 = Sample interrupt input once per 2*256 clocks. \n + * 10 = Sample interrupt input once per 4*256 clocks. \n + * 11 = Sample interrupt input once per 8*256 clocks. \n + * 12 = Sample interrupt input once per 16*256 clocks. \n + * 13 = Sample interrupt input once per 32*256 clocks. \n + * 14 = Sample interrupt input once per 64*256 clocks. \n + * 15 = Sample interrupt input once per 128*256 clocks + * + * @retval <0 Fail + * @retval 0 Success + * + * @details Enable the interrupt de-bounce function of specified GPIO. + */ +INT32 GPIO_EnableDebounce(INT32 debounceClkSel) +{ + UINT32 reg; + + reg = inpw(REG_GPIO_DBNCECON); + + /* Setting the debounce timing */ + reg = ((reg & ~0xf) | debounceClkSel); + + /* Enable the debounce function */ + reg = reg | 0x20; + outpw(REG_GPIO_DBNCECON, reg); + + return SUCCESSFUL; +} + +/** + * @brief Disable GPIO De-bounce Function. + * + * @retval <0 Fail + * @retval 0 Success + * + * @details Disable the interrupt de-bounce function of specified GPIO. + */ +INT32 GPIO_DisableDebounce(void) +{ + UINT32 reg; + + reg = inpw(REG_GPIO_DBNCECON); + + /* Setting the debounce timing */ + reg = ((reg & ~0xf)); + + /* Enable the debounce function */ + reg = reg | 0x20; + outpw(REG_GPIO_DBNCECON, reg); + + return SUCCESSFUL; +} + +/*@}*/ /* end of group N9H30_GPIO_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_GPIO_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_i2s.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_i2s.c new file mode 100644 index 0000000000..f538703526 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_i2s.c @@ -0,0 +1,461 @@ +/**************************************************************************//** +* @file i2s.c +* @brief N9H30 I2S driver source file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include +#include +#include + +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_i2s.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_I2S_Driver I2S Driver + @{ +*/ + +/** @addtogroup N9H30_I2S_EXPORTED_CONSTANTS I2S Exported Constants + @{ +*/ + +/// @cond HIDDEN_SYMBOLS + +typedef uint32_t (AU_CB_FUNC_T)(uint32_t); + +static AU_CB_FUNC_T *g_fnPlayCallBack; +static AU_CB_FUNC_T *g_fnRecCallBack; +static uint8_t i2sOpened = 0; + +/// @endcond /* HIDDEN_SYMBOLS */ + +/*@}*/ /* end of group N9H30_I2S_EXPORTED_CONSTANTS */ + +/** @addtogroup N9H30_I2S_EXPORTED_FUNCTIONS I2S Exported Functions + @{ +*/ + +/// @cond HIDDEN_SYMBOLS +/** + * @brief Start to play + * @param None + * @return None + */ +static void i2sStartPlay(void) +{ + /* start playing */ + //sysprintf("IIS start playing...\n"); + + outpw(REG_ACTL_PSR, 0x1); + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) | (1 << 5)); +} + +/** + * @brief Stop to play + * @param None + * @return None + */ +static void i2sStopPlay(void) +{ + //sysprintf("IIS stop playing\n"); + + /* stop playing */ + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) & ~(1 << 5)); +} + +/** + * @brief Start to record + * @param None + * @return None + */ +static void i2sStartRecord(void) +{ + /* start recording */ + //sysprintf("IIS start recording...\n"); + + outpw(REG_ACTL_RSR, 0x1); + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) | (1 << 6)); +} + +/** + * @brief Stop to record + * @param None + * @return None + */ +static void i2sStopRecord(void) +{ + //sysprintf("I2S stop recording\n"); + + /* stop recording */ + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) & ~(1 << 6)); +} + +/** + * @brief Delay function + * @param None + * @return None + */ +static void Delay(int nCnt) +{ + int volatile loop; + for (loop = 0; loop < nCnt * 10; loop++); +} + +/** + * @brief Interrupt service routine for i2s + * @param None + * @return None + */ +static void i2sISR(void) +{ + uint8_t u8SN; + + if (inpw(REG_ACTL_CON) & (1 << 10)) + { + outpw(REG_ACTL_CON, inpw(REG_ACTL_CON) | (1 << 10)); //Clear TX INT + + if (inpw(REG_ACTL_PSR) & (1 << 4)) + { + outpw(REG_ACTL_PSR, (1 << 4)); + //sysprintf("\ndebug:DMA_COUNTER_IRQ occur"); + } + + if (inpw(REG_ACTL_PSR) & (1 << 3)) + { + outpw(REG_ACTL_PSR, (1 << 3)); + //sysprintf("\ndebug:DMA_DATA_ZERO_IRQ occur"); + } + + if (inpw(REG_ACTL_PSR) & 0x1) + { + outpw(REG_ACTL_PSR, 0x1); + u8SN = (inpw(REG_ACTL_PSR) >> 5) & 0x7; + g_fnPlayCallBack(u8SN); + } + } + + if (inpw(REG_ACTL_CON) & (1 << 11)) + { + outpw(REG_ACTL_CON, inpw(REG_ACTL_CON) | (1 << 11)); //Clear RX INT + + if (inpw(REG_ACTL_RSR) & 0x1) + { + outpw(REG_ACTL_RSR, 0x1); + u8SN = (inpw(REG_ACTL_RSR) >> 5) & 0x7; + g_fnRecCallBack(u8SN); + } + } +} +/// @endcond /* HIDDEN_SYMBOLS */ + +/** + * @brief Open i2s interface + * @return open status + * @retval I2S_ERR_BUSY error. + * @retval 0 success. + */ +int32_t i2sOpen(void) +{ + if (i2sOpened) + return I2S_ERR_BUSY; + + /* reset audio interface */ + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) | (1 << 16)); + Delay(100); + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) & ~(1 << 16)); + Delay(100); + + /* reset IIS interface */ + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) | 0x1); + Delay(100); + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) & ~0x1); + Delay(100); + + outpw(REG_ACTL_CON, inpw(REG_ACTL_CON) | (1 << 21) | (1 << 20)); + + i2sOpened = 1; + + return 0; +} + +/** + * @brief Close i2s interface + * @return None + */ +void i2sClose(void) +{ + // reset some variables + i2sOpened = 0; + g_fnPlayCallBack = NULL; + g_fnRecCallBack = NULL; + + // reset i2s interface + outpw(REG_SYS_AHBIPRST, inpw(REG_SYS_AHBIPRST) | (1 << 8)); + outpw(REG_SYS_AHBIPRST, inpw(REG_SYS_AHBIPRST) & ~(1 << 8)); +} + +/** + * @brief Initialize i2s interface and setup interrupt + * @return None + */ +void i2sInit(void) +{ + // enable i2s engine clock + outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) | (1 << 24)); + + // enable interrupt and set ISR + sysSetInterruptType(ACTL_IRQn, HIGH_LEVEL_SENSITIVE); + sysInstallISR(IRQ_LEVEL_1, ACTL_IRQn, (PVOID)i2sISR); + sysEnableInterrupt(ACTL_IRQn); + sysSetLocalInterrupt(ENABLE_IRQ); +} + +/** + * @brief IO control for i2s interface + * @param[in] cmd Command for io control, value could be + * - \ref I2S_SET_PLAY + * - \ref I2S_SET_RECORD + * - \ref I2S_SELECT_BLOCK + * - \ref I2S_SELECT_BIT + * - \ref I2S_SET_PLAY_DMA_INT_SEL + * - \ref I2S_SET_REC_DMA_INT_SEL + * - \ref I2S_SET_ZEROCROSS + * - \ref I2S_SET_DMACOUNTER + * - \ref I2S_SET_CHANNEL + * - \ref I2S_SET_MODE + * - \ref I2S_SET_SPLITDATA + * - \ref I2S_SET_DMA_ADDRESS + * - \ref I2S_SET_DMA_LENGTH + * - \ref I2S_GET_DMA_CUR_ADDRESS + * - \ref I2S_SET_I2S_FORMAT + * - \ref I2S_SET_I2S_CALLBACKFUN + * - \ref I2S_SET_PCMSLOT + * @param[in] arg0 argument 0 for io control + * @param[in] arg1 argument 1 for io control + * @retval I2S_ERR_IO Command error. + * @retval 0 success. + */ +int32_t i2sIoctl(uint32_t cmd, uint32_t arg0, uint32_t arg1) +{ + uint32_t *buf; + AU_CB_FUNC_T *ptr; + + switch (cmd) + { + // #define I2S_START_PLAY 0 + // #define I2S_STOP_PLAY 1 + case I2S_SET_PLAY: + if (arg0 == I2S_START_PLAY) + i2sStartPlay(); + else + i2sStopPlay(); + break; + // #define I2S_START_REC 0 + // #define I2S_STOP_REC 1 + case I2S_SET_RECORD: + if (arg0 == I2S_START_REC) + i2sStartRecord(); + else + i2sStopRecord(); + break; + // #define I2S_BLOCK_I2S 0 + // #define I2S_BLOCK_PCM 1 + case I2S_SELECT_BLOCK: + if (arg0 == I2S_BLOCK_I2S) + outpw(REG_ACTL_CON, (inpw(REG_ACTL_CON) & ~0x3) | 0x1); + else + outpw(REG_ACTL_CON, (inpw(REG_ACTL_CON) & ~0x3) | 0x2); + break; + // #define I2S_BIT_WIDTH_8 0 + // #define I2S_BIT_WIDTH_16 1 + // #define I2S_BIT_WIDTH_24 2 + case I2S_SELECT_BIT: + outpw(REG_ACTL_CON, (inpw(REG_ACTL_CON) & ~0x300) | (arg0 << 8)); + break; + // #define I2S_DMA_INT_END 0 + // #define I2S_DMA_INT_HALF 1 + // #define I2S_DMA_INT_QUARTER 2 + // #define I2S_DMA_INT_EIGTH 3 + case I2S_SET_PLAY_DMA_INT_SEL: + outpw(REG_ACTL_CON, (inpw(REG_ACTL_CON) & ~0x3000) | (arg0 << 12)); + break; + + case I2S_SET_REC_DMA_INT_SEL: + outpw(REG_ACTL_CON, (inpw(REG_ACTL_CON) & ~0xc000) | (arg0 << 14)); + break; + + case I2S_SET_ZEROCROSS: + if (arg0 == I2S_ENABLE) + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) | 0x8); + else + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) & ~0x8); + break; + + case I2S_SET_DMACOUNTER: + if (arg0 == I2S_ENABLE) + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) | 0x10); + else + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) & ~0x10); + break; + // #define I2S_CHANNEL_I2S_ONE 2 + // #define I2S_CHANNEL_I2S_TWO 3 + // #define I2S_CHANNEL_PCM_TWO 3 + // #define I2S_CHANNEL_PCM_TWO_SLOT1 0 + // #define I2S_CHANNEL_PCM_TWO_SLOT0 1 + // #define I2S_CHANNEL_PCM_ONE_SLOT0 2 + case I2S_SET_CHANNEL: + if (arg0 == I2S_PLAY) + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) & ~(0x3 << 12) | (arg1 << 12)); + else + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) & ~(0x3 << 14) | (arg1 << 14)); + break; + // #define I2S_MODE_MASTER 0 + // #define I2S_MODE_SLAVE 1 + case I2S_SET_MODE: + if (arg0 == I2S_MODE_MASTER) + outpw(REG_ACTL_I2SCON, inpw(REG_ACTL_I2SCON) & ~(0x1 << 20)); + else + outpw(REG_ACTL_I2SCON, inpw(REG_ACTL_I2SCON) | (0x1 << 20)); + break; + + case I2S_SET_SPLITDATA: + if (arg0 == I2S_ENABLE) + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) | (0x1 << 20)); + else + outpw(REG_ACTL_RESET, inpw(REG_ACTL_RESET) & ~(0x1 << 20)); + break; + + case I2S_SET_DMA_ADDRESS: + if (arg0 == I2S_PLAY) + outpw(REG_ACTL_PDESB, arg1 | 0x80000000); + else if (arg0 == I2S_REC) + outpw(REG_ACTL_RDESB, arg1 | 0x80000000); + else if (arg0 == PCM_PLAY) + outpw(REG_ACTL_PDESB2, arg1 | 0x80000000); + else + outpw(REG_ACTL_RDESB2, arg1 | 0x80000000); + break; + + case I2S_SET_DMA_LENGTH: + if (arg0 == I2S_PLAY) + outpw(REG_ACTL_PDES_LENGTH, arg1); + else + outpw(REG_ACTL_RDES_LENGTH, arg1); + break; + + case I2S_GET_DMA_CUR_ADDRESS: + buf = (uint32_t *)arg0; + if (arg0 == I2S_PLAY) + *buf = inpw(REG_ACTL_PDESC); + else + *buf = inpw(REG_ACTL_RDESC); + break; + + // #define I2S_FORMAT_I2S 0 + // #define I2S_FORMAT_MSB 1 + case I2S_SET_I2S_FORMAT: + if (arg0 == I2S_FORMAT_I2S) + outpw(REG_ACTL_I2SCON, inpw(REG_ACTL_I2SCON) & ~ 0x8); + else + outpw(REG_ACTL_I2SCON, inpw(REG_ACTL_I2SCON) | 0x8); + break; + + case I2S_SET_I2S_CALLBACKFUN: + ptr = (AU_CB_FUNC_T *)arg1; + if (arg0 == I2S_PLAY) + g_fnPlayCallBack = ptr; + else + g_fnRecCallBack = ptr; + break; + // #define PCM_SLOT1_IN 0 + // #define PCM_SLOT1_OUT 1 + // #define PCM_SLOT2_IN 2 + // #define PCM_SLOT2_OUT 3 + case I2S_SET_PCMSLOT: + if (arg0 == PCM_SLOT1_IN) + outpw(REG_ACTL_PCMS1ST, (inpw(REG_ACTL_PCMS1ST) & ~0x3ff) | (arg1 & 0x3ff)); + else if (arg0 == PCM_SLOT1_OUT) + outpw(REG_ACTL_PCMS1ST, (inpw(REG_ACTL_PCMS1ST) & ~0x3ff0000) | ((arg1 & 0x3ff) << 16)); + else if (arg0 == PCM_SLOT2_IN) + outpw(REG_ACTL_PCMS2ST, (inpw(REG_ACTL_PCMS2ST) & ~0x3ff) | (arg1 & 0x3ff)); + else + outpw(REG_ACTL_PCMS2ST, (inpw(REG_ACTL_PCMS2ST) & ~0x3ff0000) | ((arg1 & 0x3ff) << 16)); + break; + + case I2S_SET_PCM_FS_PERIOD: + outpw(REG_ACTL_PCMCON, (inpw(REG_ACTL_PCMCON) & ~0x03FF0000 | (((arg0 - 1) & 0x3ff) << 16))); + break; + + default: + return I2S_ERR_IO; + } + return 0; +} + +/** + * @brief Configure sampling rate for audio + * @param[in] u32SourceClockRate source speed to i2s interface + * @param[in] u32SampleRate sampling rate + * @param[in] u32DataBit data width + * @param[in] u32Channel channel number + * @return None + */ +void i2sSetSampleRate(uint32_t u32SourceClockRate, uint32_t u32SampleRate, uint32_t u32DataBit, uint32_t u32Channel) +{ + uint32_t u32BCLKDiv; + uint32_t u32MCLK, u32MCLKDiv; + + u32MCLK = (u32SampleRate * 256); + u32MCLKDiv = u32SourceClockRate / u32MCLK; + outpw(REG_ACTL_I2SCON, (inpw(REG_ACTL_I2SCON) & ~0x000F0000) | (u32MCLKDiv - 1) << 16); + + u32BCLKDiv = u32MCLK / (u32SampleRate * u32DataBit * u32Channel); + u32BCLKDiv = u32BCLKDiv / 2 - 1; + outpw(REG_ACTL_I2SCON, (inpw(REG_ACTL_I2SCON) & ~0xF0) | u32BCLKDiv << 5); +} + +/** + * @brief Configure MCLK frequency (master mode) + * @param[in] u32SourceClockRate source clock rate + * @param[in] u32SampleRate sampling rate + * @return None + */ +void i2sSetMCLKFrequency(uint32_t u32SourceClockRate, uint32_t u32SampleRate) +{ + uint32_t u32MCLK, u32MCLKDiv; + + u32MCLK = (u32SampleRate * 256); + u32MCLKDiv = u32SourceClockRate / u32MCLK; + outpw(REG_ACTL_I2SCON, (inpw(REG_ACTL_I2SCON) & ~0x000F0000) | (u32MCLKDiv - 1) << 16); +} + +/** + * @brief Configure PCM BCLK frequency (master mode) + * @param[in] u32SourceClockRate source clock rate + * @param[in] u32Rate target rate + * @return None + */ +void i2sSetPCMBCLKFrequency(uint32_t u32SourceClockRate, uint32_t u32Rate) +{ + uint32_t u32BCLKDiv; + + u32BCLKDiv = (u32SourceClockRate / (2 * u32Rate)) - 1; + outpw(REG_ACTL_PCMCON, (inpw(REG_ACTL_PCMCON) & ~0x0000FF00) | (u32BCLKDiv << 8)); +} + + +/*@}*/ /* end of group N9H30_I2S_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_I2S_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c new file mode 100644 index 0000000000..138641f002 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c @@ -0,0 +1,764 @@ +/**************************************************************************//** +* @file lcd.c +* @brief N9H30 LCD driver source file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include +#include +#include +#include + +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_lcd.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_LCD_Driver LCD Driver + @{ +*/ + +/** @addtogroup N9H30_LCD_EXPORTED_CONSTANTS LCD Exported Constants + @{ +*/ + +/// @cond HIDDEN_SYMBOLS + +/* LCD attributes */ +static VPOST_T DEF_E50A2V1 = +{ + 800, /*!< Panel width */ + 480, /*!< Panel height */ + 0, /*!< MPU command line low indicator */ + 0, /*!< MPU command width */ + 0, /*!< MPU bus width */ + VPOSTB_DATA16or18, /*!< Display bus width */ + 0, /*!< MPU mode */ + VPOSTB_COLORTYPE_64K, /*!< Display colors */ + VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */ + 0x020d03a0, /*!< CRTCSIZE register value */ + 0x01e00320, /*!< CRTCDEND register value */ + 0x03250321, /*!< CRTCHR register value */ + 0x03780348, /*!< CRTCHSYNC register value */ + 0x01f001ed /*!< CRTCVR register value */ +}; + +static VPOST_T DEF_ILI9341_MPU80 = +{ + 240, /*!< Panel width */ + 320, /*!< Panel height */ + VPOSTB_CMDLOW, /*!< MPU command line low indicator */ + VPOSTB_CM16t18HIGH, /*!< MPU command width */ + VPOSTB_CMD8, /*!< MPU bus width */ + VPOSTB_DATA16or18, /*!< Display bus width */ + VPOSTB_MPU80, /*!< MPU mode */ + VPOSTB_COLORTYPE_64K, /*!< Display colors */ + VPOSTB_DEVICE_MPU, /*!< Type of display panel */ + 0x01600100, /*!< CRTCSIZE register value */ + 0x014000F0, /*!< CRTCDEND register value */ + 0x00FA00F5, /*!< CRTCHR register value */ + 0x00FC00FA, /*!< CRTCHSYNC register value */ + 0x01500145 /*!< CRTCVR register value */ +}; + +static VPOST_T DEF_LSA40AT9001 = +{ + 800, /*!< Panel width */ + 600, /*!< Panel height */ + 0, /*!< MPU command line low indicator */ + 0, /*!< MPU command width */ + 0, /*!< MPU bus width */ + VPOSTB_DATA16or18, /*!< Display bus width */ + 0, /*!< MPU mode */ + VPOSTB_COLORTYPE_64K, /*!< Display colors */ + VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */ + 0x02800425, /*!< CRTCSIZE register value */ + 0x02580320, /*!< CRTCDEND register value */ + 0x032F032A, /*!< CRTCHR register value */ + 0x0334032A, /*!< CRTCHSYNC register value */ + 0x026C0262 /*!< CRTCVR register value */ +}; + + +static VPOST_T DEF_FW070TFT = +{ + 800, /*!< Panel width */ + 480, /*!< Panel height */ + 0, /*!< MPU command line low indicator */ + 0, /*!< MPU command width */ + 0, /*!< MPU bus width */ + VPOSTB_DATA16or18, /*!< Display bus width */ + 0, /*!< MPU mode */ + VPOSTB_COLORTYPE_16M, /*!< Display colors */ + VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */ + 0x020d0420, /*!< CRTCSIZE register value */ + 0x01e00320, /*!< CRTCDEND register value */ + 0x033e0339, /*!< CRTCHR register value */ + 0x040c03f8, /*!< CRTCHSYNC register value */ + 0x020001f6 /*!< CRTCVR register value */ +}; + +/* LCD build-in support list */ +static VPOST_T *DisplayDevList[4] = {&DEF_E50A2V1, &DEF_ILI9341_MPU80, &DEF_LSA40AT9001, &DEF_FW070TFT}; +static VPOST_T curDisplayDev; +static OSDFORMATEX curOSDDev = {0}; +static LCDFORMATEX curVADev = {0}; + +/// @endcond /* HIDDEN_SYMBOLS */ + +/*@}*/ /* end of group N9H30_I2C_EXPORTED_CONSTANTS */ + +/** @addtogroup N9H30_LCD_EXPORTED_FUNCTIONS LCD Exported Functions + @{ +*/ +/// @cond HIDDEN_SYMBOLS + +/* For align 32 */ +static uint32_t shift_pointer(uint32_t ptr, uint32_t align) +{ + uint32_t alignedPTR; + uint32_t remain; + + //printf("pointer position is %x\n",ptr); + if ((ptr % align) != 0) + { + remain = ptr % align; + alignedPTR = ptr + (align - remain); + return alignedPTR; + } + return ptr; +} + +/// @endcond /* HIDDEN_SYMBOLS */ + +/** + * @brief Configure attributes of LCD panel,install interrupt handler and enable LCD engine clock + * @param[in] u32DisplayPanelID is panel id to configure. + * @return none + */ +void vpostLCMInit(uint32_t u32DisplayPanelID) +{ + // enable lcd engine clock + outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) | (1 << 25)); + + memset((void *)&curDisplayDev, 0, sizeof(curDisplayDev)); + memcpy((void *)&curDisplayDev, DisplayDevList[u32DisplayPanelID], sizeof(curDisplayDev)); + + outpw(REG_LCM_DEV_CTRL, curDisplayDev.u32CmdLow + | curDisplayDev.u32Cmd16t18 + | curDisplayDev.u32CmdBusWidth + | curDisplayDev.u32DataBusWidth + | curDisplayDev.u32MPU_Mode + | curDisplayDev.u32DisplayColors + | curDisplayDev.u32DevType); + + outpw(REG_LCM_CRTC_SIZE, curDisplayDev.u32Reg_CRTCSIZE); + outpw(REG_LCM_CRTC_DEND, curDisplayDev.u32Reg_CRTCDEND); + outpw(REG_LCM_CRTC_HR, curDisplayDev.u32Reg_CRTCHR); + outpw(REG_LCM_CRTC_HSYNC, curDisplayDev.u32Reg_CRTCHSYNC); + outpw(REG_LCM_CRTC_VR, curDisplayDev.u32Reg_CRTCVR); + +} + +/** + * @brief Query LCM capacity and configuration by ID + * @param[in] u32DisplayPanelID is panel id to configure. + * @return LCM instance + */ +VPOST_T *vpostLCMGetInstance(uint32_t u32DisplayPanelID) +{ + if (u32DisplayPanelID > (sizeof(DisplayDevList) / sizeof(VPOST_T *))) + return NULL; + + return DisplayDevList[u32DisplayPanelID]; +} + +/** + * @brief Disable LCD engine + * @param none + * @return none + */ +void vpostLCMDeinit(void) +{ + // disable lcd engine clock + outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) & ~(1 << 25)); + + //sysDisableInterrupt(LCD_IRQn); +} + +/** + * @brief Get the pointer of frame buffer + * @param none + * @return pointer of frame buffer + * @retval NULL fail. + * @note before calling this function, display width, height and source format must be set first. + */ +uint8_t *vpostGetFrameBuffer(void) +{ + uint8_t *u8BufPtr; + uint8_t u32BytePerPixel; + + if ((curDisplayDev.u32DevWidth == 0) || (curDisplayDev.u32DevHeight == 0)) + return NULL; + + switch (curVADev.ucVASrcFormat) + { + case VA_SRC_YUV422: + case VA_SRC_YCBCR422: + case VA_SRC_RGB565: + u32BytePerPixel = 2; + break; + + case VA_SRC_RGB666: + case VA_SRC_RGB888: + u32BytePerPixel = 4; + break; + + default: + u32BytePerPixel = 2; + } + + u8BufPtr = (uint8_t *)malloc((curDisplayDev.u32DevWidth * curDisplayDev.u32DevHeight * u32BytePerPixel) + 32); + if (u8BufPtr == NULL) + return NULL; + u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32); + + outpw(REG_LCM_VA_BADDR0, (uint32_t)((uint32_t)u8BufPtr | 0x80000000)); + outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~(1 << 30) & ~VPOSTB_DB_EN); + + return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000); +} + + +/** + * @brief Get the pointer of frame buffer + * @param[in] u32Cnt is the frame buffer count to allocate. Min value is 1. + * @return pointer of frame buffer + * @retval NULL fail. + * @note before calling this function, display width, height and source format must be set first. + */ +uint8_t *vpostGetMultiFrameBuffer(uint32_t u32Cnt) +{ + uint8_t *u8BufPtr; + uint8_t u32BytePerPixel; + + if ((curDisplayDev.u32DevWidth == 0) || (curDisplayDev.u32DevHeight == 0) || (u32Cnt == 0)) + return NULL; + + switch (curVADev.ucVASrcFormat) + { + case VA_SRC_YUV422: + case VA_SRC_YCBCR422: + case VA_SRC_RGB565: + u32BytePerPixel = 2; + break; + + case VA_SRC_RGB666: + case VA_SRC_RGB888: + u32BytePerPixel = 4; + break; + + default: + u32BytePerPixel = 2; + } + + u8BufPtr = (uint8_t *)malloc((curDisplayDev.u32DevWidth * curDisplayDev.u32DevHeight * u32BytePerPixel) * u32Cnt + 32); + if (u8BufPtr == NULL) + return NULL; + u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32); + + outpw(REG_LCM_VA_BADDR0, (uint32_t)((uint32_t)u8BufPtr | 0x80000000)); + outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~(1 << 30) & ~VPOSTB_DB_EN); + + return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000); +} + +/** + * @brief Set active display window + * @param[in] u16StartY is y start position + * @param[in] u16EndY is y end position + * @param[in] u8BGColorR is background R color + * @param[in] u8BGColorG is background G color + * @param[in] u8BGColorB is background B color + * @return none + */ +void vpostSetActiveWindow(uint16_t u16StartY, uint16_t u16EndY, uint8_t u8BGColorR, uint8_t u8BGColorG, uint8_t u8BGColorB) +{ + outpw(REG_LCM_VA_WIN, (u16StartY << 16) | u16EndY); + outpw(REG_LCM_VA_STUFF, (u8BGColorR << 16) | (u8BGColorG << 8) | u8BGColorB); +} + +/** + * @brief Configure LCD display mode + * @param[in] u8DisplayMode is display mode, value could be + * - \ref VPOST_DISPLAY_SINGLE + * - \ref VPOST_DISPLAY_CONTINUOUS + * @return none + */ +void vpostSetDisplayMode(uint8_t u8DisplayMode) +{ + if (u8DisplayMode == 0) + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(1 << 7)); //clear setting + else + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | (u8DisplayMode) << 7); +} + +/** + * @brief Configure display attributes of video interface, + * @param[in] u32VASrcType is display type, value could be + * - \ref VA_SRC_YUV422 + * - \ref VA_SRC_YCBCR422 + * - \ref VA_SRC_RGB888 + * - \ref VA_SRC_RGB666 + * - \ref VA_SRC_RGB565 + * - \ref VA_SRC_RGB444_LOW + * - \ref VA_SRC_RGB444_HIGH + * @return none + */ +void vpostSetVASrc(uint32_t u32VASrcType) +{ + uint32_t u32BytePerPixel, VA_FF, VA_Sride; + + curVADev.ucVASrcFormat = u32VASrcType; + + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 8)); + if (u32VASrcType != 0) + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | u32VASrcType); + else + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 8)); + + if ((u32VASrcType == VA_SRC_RGB888) || (u32VASrcType == VA_SRC_RGB666)) + outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | (curDisplayDev.u32DevWidth << 16) | curDisplayDev.u32DevWidth); + else + outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | ((curDisplayDev.u32DevWidth / 2) << 16) | (curDisplayDev.u32DevWidth / 2)); + + switch (u32VASrcType) + { + case VA_SRC_YUV422: + case VA_SRC_YCBCR422: + case VA_SRC_RGB565: + u32BytePerPixel = 2; + break; + + case VA_SRC_RGB666: + case VA_SRC_RGB888: + u32BytePerPixel = 4; + break; + + default: + u32BytePerPixel = 2; + } + + /* set video stream frame buffer control */ + VA_FF = curDisplayDev.u32DevWidth * u32BytePerPixel / 4; + VA_Sride = curDisplayDev.u32DevWidth * u32BytePerPixel / 4; + outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | (VA_FF << 16) | VA_Sride); +} + +/** + * @brief Start to display + * @param none + * @return none + */ +void vpostVAStartTrigger(void) +{ + if ((inpw(REG_LCM_DCCS) & VPOSTB_SINGLE) == VPOSTB_SINGLE) + while ((inpw(REG_LCM_DCCS) & VPOSTB_VA_EN) == VPOSTB_VA_EN); //wait VA_EN low + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_DISP_OUT_EN); //display_out-enable + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_VA_EN); //va-enable +} + +/** + * @brief Stop to display + * @param none + * @return none + */ +void vpostVAStopTrigger(void) +{ + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(VPOSTB_DISP_OUT_EN | VPOSTB_VA_EN)); //OSD disable +} + +/** + * @brief Configure LCD scaling attribute + * @param[in] u8HIntegral is horizontal integral + * @param[in] u16HDecimal is horizontal decimal + * @param[in] u8VIntegral is vertical integral + * @param[in] u16VDecimal is vertical decimal + * @param[in] u32Mode is scale mode, value could be + * - \ref VA_SCALE_INTERPOLATION + * - \ref VA_SCALE_DUPLICATION + * @return none + */ +void vpostVAScalingCtrl(uint8_t u8HIntegral, uint16_t u16HDecimal, uint8_t u8VIntegral, uint16_t u16VDecimal, uint32_t u32Mode) +{ + outpw(REG_LCM_VA_SCALE, ((((uint32_t)u8VIntegral << 10) + ((uint32_t)ceil((double)1024 / 10)*u16VDecimal)) << 16) + | (((uint32_t)u8HIntegral << 10) + ((uint32_t)ceil((double)1024 / 10)*u16HDecimal)) | u32Mode); +} + +/** + * @brief Set OSD color key + * @param[in] u8CKeyColorR is color key R color + * @param[in] u8CKeyColorG is color key G color + * @param[in] u8CKeyColorB is color key B color + * @return none + */ +void vpostOSDSetColKey(uint8_t u8CKeyColorR, uint8_t u8CKeyColorG, uint8_t u8CKeyColorB) +{ + outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~(VPOSTB_BLI_ON | VPOSTB_CKEY_ON)); //blinking disable, color-key disable + outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | VPOSTB_CKEY_ON);//color-key enable + outpw(REG_LCM_OSD_CKEY, ((uint32_t)(u8CKeyColorR << 16) | (uint32_t)(u8CKeyColorG << 8) | u8CKeyColorB)); +} + +/** + * @brief Set OSD color mask, OSD data only will be displayed if the mask bit is set as 1. + * @param[in] u8MaskColorR is color key R color + * @param[in] u8MaskColorG is color key G color + * @param[in] u8MaskColorB is color key B color + * @return none + */ +void vpostOSDSetColMask(uint8_t u8MaskColorR, uint8_t u8MaskColorG, uint8_t u8MaskColorB) +{ + outpw(REG_LCM_OSD_CMASK, ((u8MaskColorR << 16) | (u8MaskColorG << 8) | u8MaskColorB)); +} + +/** + * @brief Set OSD blinking function + * @param[in] u8OSDBlinkVcnt is blinking cycle time, unit is VSync + * @return none + */ +void vpostOSDSetBlinking(uint8_t u8OSDBlinkVcnt) +{ + outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~(VPOSTB_BLI_ON | VPOSTB_CKEY_ON)); //blinking disable, color-key disable + outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | VPOSTB_BLI_ON); + outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | ((uint32_t)(u8OSDBlinkVcnt) << 16)); +} + +/** + * @brief Disable OSD blinking function + * @param none + * @return none + */ +void vpostOSDDisableBlinking(void) +{ + outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~ VPOSTB_BLI_ON); +} + +/** + * @brief Configure display attributes of OSD + * @param[in] u32OSDSrcType is display type, value could be + * - \ref OSD_SRC_YUV422 + * - \ref OSD_SRC_YCBCR422 + * - \ref OSD_SRC_RGB888 + * - \ref OSD_SRC_RGB666 + * - \ref OSD_SRC_RGB565 + * - \ref OSD_SRC_RGB444_LOW + * - \ref OSD_SRC_RGB444_HIGH + * - \ref OSD_SRC_RGB332 + * @return none + */ +void vpostSetOSDSrc(uint32_t u32OSDSrcType) +{ + uint32_t u32BytePerPixel, VA_FF, VA_Sride; + + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 12) | u32OSDSrcType); + curOSDDev.ucOSDSrcFormat = u32OSDSrcType; + + switch (u32OSDSrcType) + { + case OSD_SRC_YUV422: + case OSD_SRC_YCBCR422: + case OSD_SRC_RGB565: + u32BytePerPixel = 2; + break; + + case OSD_SRC_RGB666: + case OSD_SRC_RGB888: + u32BytePerPixel = 4; + break; + + default: + u32BytePerPixel = 2; + } + + /* set video stream frame buffer control */ + VA_FF = curOSDDev.nOSDWidth * u32BytePerPixel / 4; + VA_Sride = curOSDDev.nOSDWidth * u32BytePerPixel / 4; + outpw(REG_LCM_OSD_FBCTRL, inpw(REG_LCM_OSD_FBCTRL) & ~0x7ff07ff | (VA_FF << 16) | VA_Sride); +} + +/** + * @brief Get the pointer of OSD frame buffer + * @param none + * @return pointer of OSD frame buffer + * @retval NULL fail. + * @note Must call \ref vpostOSDSetWindow and \ref vpostSetOSDSrc before calling this function + */ +uint8_t *vpostGetOSDBuffer(void) +{ + uint32_t u32BytePerPixel; + uint8_t *u8BufPtr; + + if ((curOSDDev.nOSDWidth == 0) || (curOSDDev.nOSDHeight == 0)) + { + return NULL; + } + + switch (curOSDDev.ucOSDSrcFormat) + { + case OSD_SRC_YUV422: + case OSD_SRC_YCBCR422: + case OSD_SRC_RGB565: + u32BytePerPixel = 2; + break; + + case OSD_SRC_RGB666: + case OSD_SRC_RGB888: + u32BytePerPixel = 4; + break; + + default: + u32BytePerPixel = 2; + } + + u8BufPtr = (uint8_t *)malloc((curOSDDev.nOSDWidth * curOSDDev.nOSDHeight * u32BytePerPixel) + 32); + if (u8BufPtr == NULL) + return NULL; + u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32); + + outpw(REG_LCM_OSD_BADDR, (uint32_t)((uint32_t)u8BufPtr | 0x80000000)); + + return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000); +} + +/** + * @brief Enable OSD function + * @param none + * @return none + */ +void vpostOSDEnable(void) +{ + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_OSD_EN); //OSD enable +} + +/** + * @brief Disable OSD function + * @param none + * @return none + */ +void vpostOSDDisable(void) +{ + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~VPOSTB_OSD_EN); //OSD disable +} + +/** + * @brief Configure OSD scaling attribute + * @param[in] u8HIntegral is horizontal integral + * @param[in] u16HDecimal is horizontal decimal + * @param[in] u8VScall is scale mode, value could be + * - \ref VPOSTB_OSD_VUP_1X + * - \ref VPOSTB_OSD_VUP_2X + * - \ref VPOSTB_OSD_VUP_4X + * @return none + */ +void vpostOSDScalingCtrl(uint8_t u8HIntegral, uint16_t u16HDecimal, uint8_t u8VScall) +{ + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & 0xfff0ffff); //clear OSD scaling setting + if (u8VScall != 0) + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | (u8VScall << 16)); + outpw(REG_LCM_OSD_SCALE, ((uint32_t)u8HIntegral << 10) | ((uint32_t)ceil((double)1024 / 10 * u16HDecimal)) << 6); +} + +/** + * @brief Set OSD display window, including start position, width and height. + * @param[in] u32XStart is X start position + * @param[in] u32YStart is Y start position + * @param[in] u32Width is OSD display width + * @param[in] u32Height is OSD display height + * @return none + */ +void vpostOSDSetWindow(uint32_t u32XStart, uint32_t u32YStart, uint32_t u32Width, uint32_t u32Height) +{ + outpw(REG_LCM_OSD_WINS, ((u32YStart + 1) << 16) | (u32XStart + 1)); + outpw(REG_LCM_OSD_WINE, ((u32YStart + u32Height) << 16) | (u32XStart + u32Width)); + + curOSDDev.nOSDWidth = u32Width; + curOSDDev.nOSDHeight = u32Height; +} + +/** + * @brief Initialize hardware cursor function + * @param[in] u32CursorBMPBuff is pointer of hardware cursor image + * @param[in] ucMode is hardware cursor mode, value could be + * - \ref HC_MODE0 + * - \ref HC_MODE1 + * - \ref HC_MODE2 + * - \ref HC_MODE3 + * - \ref HC_MODE4 + * - \ref HC_MODE5 + * @return none + */ +void vpostHCInit(uint32_t *u32CursorBMPBuff, VA_HCMODE_E ucMode) +{ + int bpp = 2; + int BlockWidth = 32; + int bpw = 32; + + outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x003f3f00 | (0x00 << 8) | (0x00 << 16)); //set TIP + if (ucMode == HC_MODE0) + { + bpp = 2; + BlockWidth = 32; + outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7); //set mode 0 32X32X2bpp 4 color + + } + else if (ucMode == HC_MODE1) + { + bpp = 2; + BlockWidth = 32; + outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x1); //set mode 1 32X32X2bpp 3 color and 1 transparent + } + else if (ucMode == HC_MODE2) + { + bpp = 2; + BlockWidth = 64; + outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x2); //set mode 2 64X64X2bpp 4 color + } + else if (ucMode == HC_MODE3) + { + bpp = 2; + BlockWidth = 64; + outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x3); //set mode 3 64X64X2bpp 3 color and 1 transparent + } + else if (ucMode == HC_MODE4) + { + bpp = 1; + BlockWidth = 128; + outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x4); //set mode 4 128X128X1bpp 2 color + } + else if (ucMode == HC_MODE5) + { + bpp = 1; + BlockWidth = 128; + outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x5); //set mode 5 128X128X1bpp 1 color and 1 transparent + } + + outpw(REG_LCM_HC_WBCTRL, ((bpp * BlockWidth / bpw) << 16) | (bpp * BlockWidth / bpw)); + outpw(REG_LCM_HC_BADDR, (uint32_t)u32CursorBMPBuff); + outpw(REG_LCM_HC_COLOR0, 0x00ff0000); // RED color + outpw(REG_LCM_HC_COLOR1, 0x0000ff00); // GREEN color + outpw(REG_LCM_HC_COLOR2, 0x000000ff); // BLUE color + outpw(REG_LCM_HC_COLOR3, 0x00ffff00); // YELLOW color + outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_HC_EN); +} + +/** + * @brief Set the position of hardware cursor + * @param[in] u32CursorX is X position + * @param[in] u32CursorY is Y position + * @return none + */ +void vpostHCPosCtrl(uint32_t u32CursorX, uint32_t u32CursorY) +{ + outpw(REG_LCM_HC_POS, (u32CursorY << 16) | u32CursorX); //set Cursor position +} + +/** + * @brief Set OSD overlay condition + * @param[in] u8OSDDisplayMatch is display method when mask bit is matched, value could be + * - \ref DISPLAY_VIDEO + * - \ref DISPLAY_OSD + * - \ref DISPLAY_SYNTHESIZED + * @param[in] u8OSDDisplayUnMatch is display method when mask bit is unmatched + * - \ref DISPLAY_VIDEO + * - \ref DISPLAY_OSD + * - \ref DISPLAY_SYNTHESIZED + * @param[in] u8OSDSynW is synthesis video weighting, based on match condition + * @return none + */ +void vpostOSDSetOverlay(uint8_t u8OSDDisplayMatch, uint8_t u8OSDDisplayUnMatch, uint8_t u8OSDSynW) +{ + /* clear OCR0 and OCR1 */ + outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & 0xfffffff0); + + /* match condition */ + if (u8OSDDisplayMatch != 0) + { + outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDDisplayMatch << 2)); + } + + /* unmatch condition */ + if (u8OSDDisplayUnMatch != 0) + { + outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDDisplayUnMatch)); + } + + /* synthesized weight */ + if (u8OSDDisplayMatch == DISPLAY_SYNTHESIZED || u8OSDDisplayUnMatch == DISPLAY_SYNTHESIZED) + { + outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDSynW << 4)); + } +} + +/** + * @brief Write MPU command + * @param[in] uscmd MPU command code + * @return none + */ +void vpostMPUWriteAddr(uint16_t uscmd) +{ + outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 30)); //RS=0 + outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 29)); //w + + outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON + outpw(REG_LCM_MPU_CMD, (inpw(REG_LCM_MPU_CMD) & 0xffff0000 | uscmd)); + while (inpw(REG_LCM_MPU_CMD) & (1UL << 31)); + outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF +} + +/** + * @brief Write MPU data + * @param[in] usdata MPU data + * @return none + */ +void vpostMPUWriteData(uint16_t usdata) +{ + outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 30)); //RS=1 + outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 29)); //w + outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON + outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & 0xffff0000 | usdata); + while (inpw(REG_LCM_MPU_CMD) & (1UL << 31)); + outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF +} + +/** + * @brief Read MPU data + * @param none + * @return MPU data + */ +uint32_t vpostMPUReadData(void) +{ + uint32_t udata; + + outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 30)); //RS=1 + outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON + outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 29)); //r + while (inpw(REG_LCM_MPU_CMD) & (1UL << 31)); + udata = inpw(REG_LCM_MPU_CMD) & 0xffff; + outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF + + return udata; +} + +/*@}*/ /* end of group N9H30_LCD_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_LCD_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_pwm.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_pwm.c new file mode 100644 index 0000000000..a4e11b69f1 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_pwm.c @@ -0,0 +1,1117 @@ +/**************************************************************************//** + * @file pwm.c + * @brief N9H30 series PWM driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_pwm.h" +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_PWM_Driver PWM Driver + @{ +*/ + + +/** @addtogroup N9H30_PWM_EXPORTED_FUNCTIONS PWM Exported Functions + @{ +*/ + +//Internal function definition +/// @cond HIDDEN_SYMBOLS + +void pwmISR(PVOID pvParam); + + +static INT pwmInitGPIO(const INT nTimerIdentity, const INT nValue); +static INT pwmInitTimer(const INT nTimerIdentity); +static INT pwmStartTimer(const INT nTimerIdentity); +static INT pwmStopTimer(const INT nTimerIdentity, const INT nMethod); +// Register operation +static INT pwmSetCP(const INT nTimerIdentity, const INT nValue); +static INT pwmSetDZI(const INT nTimerIdentity, const INT nValue); +static INT pwmSetCSR(const INT nTimerIdentity, const INT nValue); +static INT pwmSetDZGenerator(const INT nTimerIdentity, const INT nStatus); +static INT pwmSetTimerState(const INT nTimerIdentity, const INT nStatus); +static INT pwmSetInverter(const INT nTimerIdentity, const INT nStatus); +static INT pwmSetMode(const INT nTimerIdentity, const INT nStatus); +static INT pwmSetCNR(const INT nTimerIdentity, const INT nValue); +static INT pwmSetCMR(const INT nTimerIdentity, const INT nValue); +static UINT pwmGetPDR(const INT nTimerIdentity); +static INT pwmSetPIER(const INT nTimerIdentity, const INT value); +static INT pwmCleanPIIR(const INT nTimerIdentity); + +//Global variable +static BOOL bPWMIRQFlag = FALSE; //IRQ enable flag, set after PWM IRQ enable +static BOOL bPWMTimerOpenStatus[PWM_TIMER_NUM]; //timer flag which set after open(for disable IRQ decision) +static BOOL bPWMTimerStartStatus[PWM_TIMER_NUM]; //timer flag which set after Start count(to avoid incorrectly stop procedure) +static BOOL bPWMTimerMode[PWM_TIMER_NUM]; //PWM timer toggle/one shot mode +static BOOL volatile bPWMIntFlag[PWM_TIMER_NUM]; //interrupt flag which set by ISR +/// @endcond /* HIDDEN_SYMBOLS */ + + +/** + * @brief The init function of PWM device driver + */ +INT pwmInit(void) +{ + UINT temp; + // Enable PWM clock + temp = inpw(REG_CLK_PCLKEN1); + temp = temp | 0x8000000; + outpw(REG_CLK_PCLKEN1, temp); + + sysInstallISR(IRQ_LEVEL_1, PWM_IRQn, (PVOID)pwmISR); + sysSetLocalInterrupt(ENABLE_IRQ); // Enable CPSR I bit + + return 0; +} + +/** + * @brief The exit function of PWM device driver + */ +INT pwmExit(void) +{ + return 0; +} + +/** + * @brief The open function of PWM device driver + * @param[in] nTimerIdentity PWM Timer channel identity + * @retval Successful PWM successfully opened + * @retval pwmTimerBusy PWM timer already open + * @retval pwmInvalidTimerChannel PWM Timer channel number error + */ +INT pwmOpen(const INT nTimerIdentity) +{ + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// nTimerIdentity value error + } + if (bPWMTimerOpenStatus[nTimerIdentity] == TRUE) + { + return pwmTimerBusy; + } + if (bPWMIRQFlag == FALSE) + { + + sysEnableInterrupt(PWM_IRQn); + + bPWMIRQFlag = TRUE; + } + bPWMTimerOpenStatus[nTimerIdentity] = TRUE; + + // Set PWM timer default value(CSR->PPR->PCR->CMR->CNR) + pwmInitTimer(nTimerIdentity); + + //Enable PIER + pwmSetPIER(nTimerIdentity, PWM_ENABLE); + + //Reset PIIR + pwmCleanPIIR(nTimerIdentity); + + //Reset PWM timer start count flag + bPWMTimerStartStatus[nTimerIdentity] = FALSE; + + return Successful; + +} + +/** + * @brief The close function of PWM device driver + * @param[in] nTimerIdentity PWM Timer channel identity + * @retval Successful PWM successfully closed + * @retval pwmTimerNotOpen PWM timer not open + * @retval pwmInvalidTimerChannel PWM Timer channel number error + */ +INT pwmClose(const INT nTimerIdentity) +{ + INT nLoop; + BOOL uAllTimerClose = TRUE; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// nTimerIdentity value error + } + if (bPWMTimerOpenStatus[nTimerIdentity] == FALSE) + { + return pwmTimerNotOpen; + } + bPWMTimerOpenStatus[nTimerIdentity] = FALSE; + //Check if all timer stop, IRQ can be disable + for (nLoop = PWM_TIMER_MIN; nLoop < PWM_TIMER_NUM; nLoop++) + { + if (bPWMTimerOpenStatus[nLoop] == TRUE) + { + uAllTimerClose = FALSE; + } + } + //All timer stop, disable IRQs + if (uAllTimerClose == TRUE) + { + + sysDisableInterrupt(PWM_IRQn); + bPWMIRQFlag = FALSE; + } + + pwmSetPIER(nTimerIdentity, PWM_DISABLE); + pwmCleanPIIR(nTimerIdentity); + + + return Successful; + +} + +/** + * @brief The read function of PWM device driver + * @param[in] nTimerIdentity PWM Timer channel identity + * @param[out] pucStatusValue The point of typePWMSTATUS + * @param[in] uLength The length of typePWMSTATUS + * @retval Successful Read PWM value successfully + * @retval pwmTimerNotOpen PWM timer not open + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval pwmInvalidStructLength Struct length error(struct type error) + */ +INT pwmRead(const INT nTimerIdentity, PUCHAR pucStatusValue, const UINT uLength) +{ + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// nTimerIdentity value error + } + if (bPWMTimerOpenStatus[nTimerIdentity] == FALSE) + { + return pwmTimerNotOpen; + } + if (uLength != sizeof(typePWMSTATUS)) + { + return pwmInvalidStructLength;// Struct length error(struct type error) + } + if (sizeof(*((typePWMSTATUS *)pucStatusValue)) != sizeof(typePWMSTATUS)) + { + return pwmInvalidStructLength;// Struct length error(struct type error) + } + ((typePWMSTATUS *)pucStatusValue)->PDR = pwmGetPDR(nTimerIdentity); + if (bPWMIntFlag[nTimerIdentity] == TRUE) + { + bPWMIntFlag[nTimerIdentity] = FALSE; + ((typePWMSTATUS *)pucStatusValue)->InterruptFlag = TRUE; + } + else + { + ((typePWMSTATUS *)pucStatusValue)->InterruptFlag = FALSE; + } + + return Successful; + +} + +/** + * @brief The write function of PWM device driver + * @param[in] nTimerIdentity PWM Timer channel identity + * @param[in] pucCNRCMRValue The value of CNR and CMR + * @param[in] uLength For future usage + * @retval Successful Write PWM setting successfully + * @retval pwmTimerNotOpen PWM timer not open + * @retval pwmInvalidTimerChannel PWM Timer channel number error + */ +INT pwmWrite(const INT nTimerIdentity, PUCHAR pucCNRCMRValue, const UINT uLength) +{ + typePWMVALUE pwmvalue; + INT nStatus; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// nTimerIdentity value error + } + if (bPWMTimerOpenStatus[nTimerIdentity] == FALSE) + { + return pwmTimerNotOpen; + } + if (uLength != sizeof(typePWMVALUE)) + { + return pwmInvalidStructLength;// Struct length error(struct type error) + } + pwmvalue.value = ((typePWMVALUE *)pucCNRCMRValue)->value; + nStatus = pwmSetCNR(nTimerIdentity, pwmvalue.field.cnr); + + if (nStatus != Successful) + { + return nStatus; + } + nStatus = pwmSetCMR(nTimerIdentity, pwmvalue.field.cmr); + + if (nStatus != Successful) + { + return nStatus; + } + return Successful; + +} + +/** + * @brief The ioctl function of PWM device driver + * @param[in] nTimerIdentity PWM Timer channel identity + * @param[in] uCommand Ioctl command which indicates different operation + * @param[in] uIndication Not use in PWM + * @param[in] uValue The value which use with uCommand + * @retval Successful PWM ioctl execute successfully + * @retval pwmTimerNotOpen PWM timer not open + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval pwmInvalidIoctlCommand Ioctl command error + * @retval Others Error according to different uCommand + */ +INT pwmIoctl(const INT nTimerIdentity, const UINT uCommand, const UINT uIndication, UINT uValue) +{ + INT nStatus; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// nTimerIdentity value error + } + if (bPWMTimerOpenStatus[nTimerIdentity] == FALSE) + { + return pwmTimerNotOpen; + } + switch (uCommand) + { + case START_PWMTIMER: + { + nStatus = pwmStartTimer(nTimerIdentity); + break; + } + case STOP_PWMTIMER: + { + // default stop method is 2 + nStatus = pwmStopTimer(nTimerIdentity, PWM_STOP_METHOD2); + break; + } + case SET_CSR: + { + nStatus = pwmSetCSR(nTimerIdentity, uValue); + break; + } + case SET_CP: + { + nStatus = pwmSetCP(nTimerIdentity, uValue); + break; + } + case SET_DZI: + { + nStatus = pwmSetDZI(nTimerIdentity, uValue); + break; + } + case SET_INVERTER: + { + nStatus = pwmSetInverter(nTimerIdentity, uValue); + break; + } + case SET_MODE: + { + nStatus = pwmSetMode(nTimerIdentity, uValue); + break; + } + case ENABLE_DZ_GENERATOR: + { + nStatus = pwmSetDZGenerator(nTimerIdentity, PWM_ENABLE); + break; + } + case DISABLE_DZ_GENERATOR: + { + nStatus = pwmSetDZGenerator(nTimerIdentity, PWM_DISABLE); + break; + } + case ENABLE_PWMGPIOOUTPUT: + { + nStatus = pwmInitGPIO(nTimerIdentity, uValue); + break; + } + default: + { + return pwmInvalidIoctlCommand; + } + } + return nStatus; +} + + +/// @cond HIDDEN_SYMBOLS + +/** + * @brief The interrupt service routines of PWM + * @param[in] pvParam IRQ Parameter(not use in PWM) + */ +VOID pwmISR(PVOID pvParam) +{ + INT i; + + UINT32 uRegisterValue = 0; + uRegisterValue = inpw(REG_PWM_PIIR);// Get PIIR value + for (i = 0; i < PWM_TIMER_NUM ; i++) + { + if (uRegisterValue & (1 << i)) + { + bPWMIntFlag[i] = 1; + outpw(REG_PWM_PIIR, (1 << i)); + } + } +} + +/** + * @brief This function set corresponding GPIO as PWM function according to the + * parameter nTimerIdentity + * @param[in] nTimerIdentity Timer channel number + * @retval Successful PWM init GPIO successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval pwmInvalidPin PWM output pin setting error + */ +static INT pwmInitGPIO(const INT nTimerIdentity, const INT nValue) +{ + UINT temp = 0; + + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + + if (nTimerIdentity == PWM_TIMER0) + { + if (nValue == PWM0_GPA12) + { + temp = inpw(REG_SYS_GPA_MFPH); + temp = (temp & ~0x000F0000) | 0xD0000; + outpw(REG_SYS_GPA_MFPH, temp); + } + else if (nValue == PWM0_GPB2) + { + temp = inpw(REG_SYS_GPB_MFPL); + temp = (temp & ~0xF00) | 0xD00; + outpw(REG_SYS_GPB_MFPL, temp); + } + else + return pwmInvalidPin; + } + else if (nTimerIdentity == PWM_TIMER1) + { + if (nValue == PWM1_GPA13) + { + temp = inpw(REG_SYS_GPA_MFPH); + temp = (temp & ~0x00F00000) | 0xD00000; + outpw(REG_SYS_GPA_MFPH, temp); + } + else if (nValue == PWM1_GPB3) + { + temp = inpw(REG_SYS_GPB_MFPL); + temp = (temp & ~0xF000) | 0xD000; + outpw(REG_SYS_GPB_MFPL, temp); + } + else + return pwmInvalidPin; + } + else if (nTimerIdentity == PWM_TIMER2) + { + if (nValue == PWM2_GPA14) + { + temp = inpw(REG_SYS_GPA_MFPH); + temp = (temp & ~0x0F000000) | 0xD000000; + outpw(REG_SYS_GPA_MFPH, temp); + } + else if (nValue == PWM2_GPH2) + { + temp = inpw(REG_SYS_GPH_MFPL); + temp = (temp & ~0xF00) | 0xD00; + outpw(REG_SYS_GPH_MFPL, temp); + } + else + return pwmInvalidPin; + } + else + { + if (nValue == PWM3_GPA15) + { + temp = inpw(REG_SYS_GPA_MFPH); + temp = (temp & ~0xF0000000) | 0xD0000000; + outpw(REG_SYS_GPA_MFPH, temp); + } + else if (nValue == PWM3_GPH3) + { + temp = inpw(REG_SYS_GPH_MFPL); + temp = (temp & ~0xF000) | 0xD000; + outpw(REG_SYS_GPH_MFPL, temp); + } + else + return pwmInvalidPin; + } + + return Successful; +} + + +/** + * @brief This function initiates PWM timer n and set the default setting to CSR, + * PPR, PCR, CNR, CMR + * @param[in] nTimerIdentity Timer channel number + * @retval Successful PWM init timer successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + */ +static INT pwmInitTimer(const INT nTimerIdentity) +{ + typePPR PWMPPR; + INT nStatus; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// nTimerIdentity value error + } + + //Set CSR + nStatus = pwmSetCSR(nTimerIdentity, DEFAULT_CSR); + + if (nStatus != Successful) + { + return nStatus; + } + + //Set PPR + PWMPPR.value = (UINT)inpw(REG_PWM_PPR); + switch (nTimerIdentity) + { + case PWM_TIMER0: + { + if (PWMPPR.field.cp0 == 0) + { + pwmSetCP(nTimerIdentity, DEFAULT_CP); + } + break; + } + case PWM_TIMER1: + { + if (PWMPPR.field.cp0 == 0) + { + pwmSetCP(nTimerIdentity, DEFAULT_CP); + } + break; + } + case PWM_TIMER2: + { + if (PWMPPR.field.cp1 == 0) + { + pwmSetCP(nTimerIdentity, DEFAULT_CP); + } + break; + } + case PWM_TIMER3: + { + if (PWMPPR.field.cp1 == 0) + { + pwmSetCP(nTimerIdentity, DEFAULT_CP); + } + break; + } + } + + //Set PCR + nStatus = pwmSetMode(nTimerIdentity, DEFAULT_MODE); + + if (nStatus != Successful) + { + return nStatus; + } + bPWMTimerMode[nTimerIdentity] = DEFAULT_MODE; + + //Set CMR + nStatus = pwmSetCMR(nTimerIdentity, DEFAULT_CMR); + + if (nStatus != Successful) + { + return nStatus; + } + + //Set CNR + nStatus = pwmSetCNR(nTimerIdentity, DEFAULT_CNR); + + if (nStatus != Successful) + { + return nStatus; + } + + return Successful; + +} + + +/** + * @brief This function starts PWM timer according to the parameter + * @param[in] nTimerIdentity Timer channel number + * @retval Successful PWM start timer successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + */ +static INT pwmStartTimer(const INT nTimerIdentity) +{ + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + pwmSetTimerState(nTimerIdentity, PWM_ENABLE); + if (bPWMTimerMode[nTimerIdentity] == PWM_TOGGLE) + { + bPWMTimerStartStatus[nTimerIdentity] = TRUE; + } + + return Successful; +} + +/** + * @brief This function stops PWM timer n using method 1, 2, or 3 according to the + * parameter nTimerIdentity and nStatus + * @param[in] nTimerIdentity Timer channel number + * @param[in] nMethod Stop PWM timer method + * @retval Successful PWM stop timer successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval pwmInvalidStopMethod Stop method error + */ +static INT pwmStopTimer(const INT nTimerIdentity, INT nMethod) +{ + typeCNR PWMCNR; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + // Timer_num value error + return pwmInvalidTimerChannel; + } + //Can't stop before open PWM timer + if (bPWMTimerOpenStatus[nTimerIdentity] == FALSE) + { + return Successful; + } + // one shot mode didn't need stop procedure + if (bPWMTimerMode[nTimerIdentity] == PWM_ONESHOT) + { + return Successful; + } + // Timer stop already, no need to stop again + if (bPWMTimerStartStatus[nTimerIdentity] == FALSE) + { + return Successful; + } + + // Set CNR as 0 + PWMCNR.field.cnr = 0; + outpw(REG_PWM_CNR0 + (PWM_OFFSET * nTimerIdentity), PWMCNR.value); + + switch (nMethod) + { + case PWM_STOP_METHOD1: + { + while (1) + { + if (pwmGetPDR(nTimerIdentity) == 0) // Wait PDR reach to 0 + { + pwmSetTimerState(nTimerIdentity, PWM_DISABLE);// Disable pwm timer + bPWMIntFlag[nTimerIdentity] = FALSE; + bPWMTimerStartStatus[nTimerIdentity] = FALSE; + break; + } + } + break; + } + case PWM_STOP_METHOD2: + { + while (1) + { + if (bPWMIntFlag[nTimerIdentity] == TRUE) // Wait interrupt happen + { + pwmSetTimerState(nTimerIdentity, PWM_DISABLE);// Disable pwm timer + bPWMIntFlag[nTimerIdentity] = FALSE; + bPWMTimerStartStatus[nTimerIdentity] = FALSE; + break; + } + } + break; + } + /*case PWM_STOP_METHOD3: + { + pwmSetPCRState(nTimerIdentity, PWM_DISABLE);// Disable pwm timer + bPWMIntFlag[nTimerIdentity] = FALSE; + bPWMTimerStartStatus[nTimerIdentity] = FALSE; + break; + }*/ + default: + { + return pwmInvalidStopMethod;// Stop method value error + } + } + + return Successful; +} + +/** + * @brief This function set CPn value according to the parameter nTimerIdentity and nValue + * @param[in] nTimerIdentity Timer channel number + * @param[in] nValue The value which want to set in CSRn + * @retval Successful Set CPn successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval pwmInvalidCPValue PWM_PPR CPn value out of range + */ +static INT pwmSetCP(const INT nTimerIdentity, const INT nValue) +{ + typePPR PWMPPR; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + if (nValue < CP_MIN || nValue > CP_MAX) + { + return pwmInvalidCPValue;// CP value error + } + PWMPPR.value = (UINT)inpw(REG_PWM_PPR); + switch (nTimerIdentity) + { + case PWM_TIMER0: + { + PWMPPR.field.cp0 = nValue; + break; + } + case PWM_TIMER1: + { + PWMPPR.field.cp0 = nValue; + break; + } + case PWM_TIMER2: + { + PWMPPR.field.cp1 = nValue; + break; + } + case PWM_TIMER3: + { + PWMPPR.field.cp1 = nValue; + break; + } + } + outpw(REG_PWM_PPR, PWMPPR.value); + + return Successful; +} + +/** + * @brief This function set DZIn value according to the parameter nTimerIdentity and nValue + * @param[in] nTimerIdentity Timer channel number + * @param[in] nValue The value which want to set in DZIn + * @retval Successful Set DZIn successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval pwmInvalidDZIValue PWM_PPR DZIn value out of range + */ +static INT pwmSetDZI(const INT nTimerIdentity, const INT nValue) +{ + typePPR PWMPPR; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + if (nValue < DZI_MIN || nValue > DZI_MAX) + { + return pwmInvalidDZIValue;// CSR value error + } + PWMPPR.value = (UINT)inpw(REG_PWM_PPR); + switch (nTimerIdentity) + { + case PWM_TIMER0: + { + PWMPPR.field.dzi0 = nValue; + break; + } + case PWM_TIMER1: + { + PWMPPR.field.dzi0 = nValue; + break; + } + case PWM_TIMER2: + { + PWMPPR.field.dzi1 = nValue; + break; + } + case PWM_TIMER3: + { + PWMPPR.field.dzi1 = nValue; + break; + } + } + outpw(REG_PWM_PPR, PWMPPR.value); + + return Successful; +} + +/** + * @brief This function set CSRn value according to the parameter nTimerIdentity and nValue + * @param[in] nTimerIdentity Timer channel number + * @param[in] nValue The value which want to set in CSRn + * @retval Successful Set CSRn successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + */ +static INT pwmSetCSR(const INT nTimerIdentity, const INT nValue) +{ + typeCSR PWMCSR; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + if (nValue < CSR_MIN || nValue > CSR_MAX) + { + return pwmInvalidCSRValue;// CSR value error + } + PWMCSR.value = (UINT)inpw(REG_PWM_CSR); + switch (nTimerIdentity) + { + case PWM_TIMER0: + { + PWMCSR.field.csr0 = nValue; + break; + } + case PWM_TIMER1: + { + PWMCSR.field.csr1 = nValue; + break; + } + case PWM_TIMER2: + { + PWMCSR.field.csr2 = nValue; + break; + } + case PWM_TIMER3: + { + PWMCSR.field.csr3 = nValue; + break; + } + } + outpw(REG_PWM_CSR, PWMCSR.value); + + return Successful; +} + +/** + * @brief This function enable/disable PWM channel n dead zone function according to the + * parameter nTimerIdentity and nStatus + * @param[in] nTimerIdentity Timer channel number + * @param[in] nStatus PWMDZG_ENABLE/PWMDZG_DISABLE + * @retval Successful Set dead zone successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval pwmInvalidDZGStatus PWM Dead-Zone Generator enable/disable status error + */ +static INT pwmSetDZGenerator(const INT nTimerIdentity, INT nStatus) +{ + typePCR PWMPCR; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + if (nStatus != PWMDZG_ENABLE && nStatus != PWMDZG_DISABLE) + { + return pwmInvalidDZGStatus;// PCR inverter value error + } + PWMPCR.value = (UINT)inpw(REG_PWM_PCR); + switch (nTimerIdentity) + { + case PWM_TIMER0: + { + PWMPCR.field.grpup0_dzen = nStatus; + break; + } + case PWM_TIMER1: + { + PWMPCR.field.grpup0_dzen = nStatus; + break; + } + case PWM_TIMER2: + { + PWMPCR.field.grpup1_dzen = nStatus; + break; + } + case PWM_TIMER3: + { + PWMPCR.field.grpup1_dzen = nStatus; + break; + } + } + outpw(REG_PWM_PCR, PWMPCR.value); + + return Successful; +} + +/** + * @brief This function set PWM channel n enable/disable according to the + * parameter nTimerIdentity and nStatus + * @param[in] nTimerIdentity Timer channel number + * @param[in] nStatus PWM_ENABLE/PWMDISABLE + * @retval Successful Set channel enable/disable successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + */ +static INT pwmSetTimerState(const INT nTimerIdentity, INT nStatus) +{ + typePCR PWMPCR; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + if (nStatus != PWM_ENABLE && nStatus != PWM_DISABLE) + { + return pwmInvalidTimerStatus; + } + PWMPCR.value = (UINT)inpw(REG_PWM_PCR); + switch (nTimerIdentity) + { + case PWM_TIMER0: + { + PWMPCR.field.ch0_en = nStatus; + break; + } + case PWM_TIMER1: + { + PWMPCR.field.ch1_en = nStatus; + break; + } + case PWM_TIMER2: + { + PWMPCR.field.ch2_en = nStatus; + break; + } + case PWM_TIMER3: + { + PWMPCR.field.ch3_en = nStatus; + break; + } + } + outpw(REG_PWM_PCR, PWMPCR.value); + + return Successful; +} + + +/** + * @brief This function set PWM channel n inverter on/off according to the + * parameter nTimerIdentity and nStatus + * @param[in] nTimerIdentity Timer channel number + * @param[in] nStatus PWM_ENABLE/PWM_DISABLE + * @retval Successful Set inverter successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval pwmInvalidInverterValue Inverter value error + */ +static INT pwmSetInverter(const INT nTimerIdentity, INT nStatus) +{ + typePCR PWMPCR; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + if (nStatus != PWM_INVON && nStatus != PWM_INVOFF) + { + return pwmInvalidInverterValue;// PCR inverter value error + } + PWMPCR.value = (UINT)inpw(REG_PWM_PCR); + switch (nTimerIdentity) + { + case PWM_TIMER0: + { + PWMPCR.field.ch0_inverter = nStatus; + break; + } + case PWM_TIMER1: + { + PWMPCR.field.ch1_inverter = nStatus; + break; + } + case PWM_TIMER2: + { + PWMPCR.field.ch2_inverter = nStatus; + break; + } + case PWM_TIMER3: + { + PWMPCR.field.ch3_inverter = nStatus; + break; + } + } + outpw(REG_PWM_PCR, PWMPCR.value); + + return Successful; +} + +/** + * @brief This function set PWM channel n toggle/one shot mode according to the + * parameter nTimerIdentity and nStatus + * @param[in] nTimerIdentity Timer channel number + * @param[in] nStatus PWM_TOGGLE/PWM_ONESHOT + * @retval Successful Set operation mode successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval pwmInvalidModeStatus Operating mode error + */ +static INT pwmSetMode(const INT nTimerIdentity, INT nStatus) +{ + typePCR PWMPCR; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + if (nStatus != PWM_TOGGLE && nStatus != PWM_ONESHOT) + { + return pwmInvalidModeStatus;// PCR inverter value error + } + PWMPCR.value = (UINT)inpw(REG_PWM_PCR); + switch (nTimerIdentity) + { + case PWM_TIMER0: + { + PWMPCR.field.ch0_mode = nStatus; + break; + } + case PWM_TIMER1: + { + PWMPCR.field.ch1_mode = nStatus; + break; + } + case PWM_TIMER2: + { + PWMPCR.field.ch2_mode = nStatus; + break; + } + case PWM_TIMER3: + { + PWMPCR.field.ch3_mode = nStatus; + break; + } + } + outpw(REG_PWM_PCR, PWMPCR.value); + bPWMTimerMode[nTimerIdentity] = nStatus; + + return Successful; +} + + +/** + * @brief This function set PWM_CNRn value according to the parameter nTimerIdentity and nValue + * @param[in] nTimerIdentity Timer channel number + * @param[in] nValue CNR value + * @retval Successful Set CNR successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval pwmInvalidCNRValue Invalid CNR value + */ +static INT pwmSetCNR(const INT nTimerIdentity, INT nValue) +{ + typeCNR PWMCNR; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + if (nValue < CNR_MIN || nValue > CNR_MAX) + { + return pwmInvalidCNRValue;// PCR inverter value error + } + PWMCNR.field.cnr = nValue; + outpw(REG_PWM_CNR0 + (PWM_OFFSET * nTimerIdentity), PWMCNR.value); + + return Successful; +} + +/** + * @brief This function set PWM_CMRn value according to the parameter nTimerIdentity and nValue + * @param[in] nTimerIdentity Timer channel number + * @param[in] nValue CMR value + * @retval Successful Set CMR successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval pwmInvalidCMRValue Invalid CMR value + */ +static INT pwmSetCMR(const INT nTimerIdentity, INT nValue) +{ + typeCMR PWMCMR; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + if (nValue < CMR_MIN || nValue > CMR_MAX) + { + return pwmInvalidCMRValue;// CMR value error + } + PWMCMR.field.cmr = nValue; + outpw(REG_PWM_CMR0 + (PWM_OFFSET * nTimerIdentity), PWMCMR.value); + + return Successful; +} + +/** + * @brief This function return the PDR value of PWM timer n + * @param[in] nTimerIdentity Timer channel number + * @retval pwmInvalidTimerChannel PWM Timer channel number error + * @retval Others Current PDR value + */ +static UINT pwmGetPDR(const INT nTimerIdentity) +{ + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + else + { + return (UINT)inpw(REG_PWM_PDR0 + (PWM_OFFSET * nTimerIdentity)); // Return PDR value + } +} + +/** + * @brief This function set the PIERn bit of PWM timer n as 1 or 0 according to the + * parameter nTimerIdentity and nValue + * @param[in] nTimerIdentity Timer channel number + * @param[in] nValue PWM_ENABLE/PWM_DISABLE + * @retval Successful Set PIER successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + */ +static INT pwmSetPIER(const INT nTimerIdentity, INT nValue) +{ + UINT uRegisterValue = 0;; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// Timer_num value error + } + else + { + uRegisterValue = (UINT)inpw(REG_PWM_PIER); + if (nValue == PWM_ENABLE) + { + uRegisterValue = uRegisterValue | (1 << nTimerIdentity); // Set PIER + } + else + { + uRegisterValue = uRegisterValue & (0 << nTimerIdentity); // Clear PIER + } + outpw(REG_PWM_PIER, uRegisterValue);// Write value to PIER + + return Successful; + } +} + + +/** + * @brief This function clear PIIRn bit according to the parameter nTimerIdentity + * @param[in] nTimerIdentity Timer channel number + * @retval Successful Clear PIIR successfully + * @retval pwmInvalidTimerChannel PWM Timer channel number error + */ +static INT pwmCleanPIIR(const INT nTimerIdentity) +{ + UINT uRegisterValue = 0; + if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX) + { + return pwmInvalidTimerChannel;// nTimerIdentity value error + } + uRegisterValue = (UINT)inpw(REG_PWM_PIIR); + uRegisterValue = uRegisterValue & ~(1 << nTimerIdentity); + outpw(REG_PWM_PIIR, uRegisterValue); + + return Successful; +} + +/// @endcond /* HIDDEN_SYMBOLS */ + +/*@}*/ /* end of group N9H30_PWM_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_PWM_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_rtc.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_rtc.c new file mode 100644 index 0000000000..4ec0cdf506 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_rtc.c @@ -0,0 +1,1153 @@ +/**************************************************************************//** +* @file RTC.c +* @brief N9H30 RTC driver source file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include +#include +#include +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_rtc.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_RTC_Driver RTC Driver + @{ +*/ + +/** @addtogroup N9H30_RTC_EXPORTED_FUNCTIONS RTC Exported Functions + @{ +*/ + +/// @cond HIDDEN_SYMBOLS + +static CHAR g_chHourMode = 0; +static BOOL volatile g_bIsEnableTickInt = FALSE; +static BOOL volatile g_bIsEnableAlarmInt = FALSE; + +static UINT32 volatile g_u32Reg, g_u32Reg1, g_u32hiYear, g_u32loYear, g_u32hiMonth, g_u32loMonth, g_u32hiDay, g_u32loDay; +static UINT32 volatile g_u32hiHour, g_u32loHour, g_u32hiMin, g_u32loMin, g_u32hiSec, g_u32loSec; +UINT32 volatile i, Wait; + +VOID RTC_Check(void) +{ + i = 0; + + Wait = inp32(REG_RTC_INTSTS) & RTC_INTSTS_REGWRBUSY_Msk; + + while (Wait == RTC_INTSTS_REGWRBUSY_Msk) + { + + Wait = inp32(REG_RTC_INTSTS) & RTC_INTSTS_REGWRBUSY_Msk; + + i++; + + if (i > RTC_WAIT_COUNT) + { + break; + } + } +} + +/// @endcond HIDDEN_SYMBOLS + +/** + * @brief Set 32k Frequency Compensation Data + * + * @param[in] i32FrequencyX100 Specify the RTC clock X100, ex: 3277365 means 32773.65. + * + * @return E_RTC_ERR_FCR_VALUE Wrong Compensation VALUE + * E_RTC_SUCCESS Success + * + * @details This API is used to compensate the 32 kHz frequency by current LXT frequency for RTC application. + */ +UINT32 RTC_DoFrequencyCompensation(INT32 i32FrequencyX100) +{ + INT32 i32RegInt, i32RegFra; + UINT32 u32Reg; + + /* Compute integer and fraction for RTC FCR register */ + i32RegInt = (i32FrequencyX100 / 100) - RTC_FCR_REFERENCE; + i32RegFra = (((i32FrequencyX100 % 100)) * 60) / 100; + + /* Judge Integer part is reasonable */ + if ((i32RegInt < 0) | (i32RegInt > 15)) + { + return E_RTC_ERR_FCR_VALUE; + } + + u32Reg = (uint32_t)((i32RegInt << 8) | i32RegFra); + + RTC_WriteEnable(1); + outp32(REG_RTC_FREQADJ, u32Reg); + RTC_Check(); + + return E_RTC_SUCCESS; +} + +/** + * @brief RTC access register enable + * + * @param[in] bEnable 1: Enable access register + * 0: Disable access register + * + * @retval E_RTC_ERR_EIO Time-out error + * @retval E_RTC_SUCCESS Success + * + */ +UINT32 RTC_WriteEnable(BOOL bEnable) +{ + INT32 volatile i32i; + + RTC_Check(); + + if (bEnable) + { + outp32(REG_RTC_RWEN, RTC_WRITE_KEY); + RTC_Check(); + + for (i32i = 0 ; i32i < RTC_WAIT_COUNT ; i32i++) + { + /*-------------------------------------------------------------------------------------------------*/ + /* check RTC_RWEN[16] to find out RTC write enable */ + /*-------------------------------------------------------------------------------------------------*/ + if (inp32(REG_RTC_RWEN) & 0x10000) + { + break; + } + } + + if (i32i == RTC_WAIT_COUNT) + { + //sysprintf ("\nRTC: 3, set write enable FAILED!\n"); + + return E_RTC_ERR_EIO; + } + } + else + { + for (i32i = 0 ; i32i < RTC_WAIT_COUNT ; i32i++) + { + if (inp32(REG_RTC_RWEN) == 0) + { + break; + } + } + } + + return E_RTC_SUCCESS; +} + +/** + * @brief Initial RTC and install ISR + * @retval E_RTC_ERR_EIO Initial RTC time-out + * @retval E_RTC_SUCCESS Success + * + */ +UINT32 RTC_Init(void) +{ + INT32 i32i; + + /*-----------------------------------------------------------------------------------------------------*/ + /* When RTC is power on, write 0xa5eb1357 to RTC_INIR to reset all logic. */ + /*-----------------------------------------------------------------------------------------------------*/ + + outp32(REG_RTC_INIT, RTC_INIT_KEY); + RTC_Check(); + + for (i32i = 0 ; i32i < RTC_WAIT_COUNT ; i32i++) + { + if (inp32(REG_RTC_INIT) & 0x01) + { + /* Check RTC_INIR[0] to find out RTC reset signal */ + break; + } + } + + if (i32i == RTC_WAIT_COUNT) + { + return E_RTC_ERR_EIO; + } + + /*-----------------------------------------------------------------------------------------------------*/ + /* Install RTC ISR */ + /*-----------------------------------------------------------------------------------------------------*/ + + outp32(REG_RTC_RWEN, RTC_WRITE_KEY); + RTC_Check(); + + for (i32i = 0 ; i32i < RTC_WAIT_COUNT ; i32i++) + { + /*-------------------------------------------------------------------------------------------------*/ + /* check RTC_RWEN[16] to find out RTC write enable */ + /*-------------------------------------------------------------------------------------------------*/ + if (inp32(REG_RTC_RWEN) & 0x10000) + { + break; + } + } + + if (i32i == RTC_WAIT_COUNT) + { + return E_RTC_ERR_EIO; + } + + return E_RTC_SUCCESS; +} + +/** + * @brief Set Current Timer + * + * @param[in] *sPt Specify the time property and current time. It includes: + * - u8cClockDisplay: \ref RTC_CLOCK_12 / \ref RTC_CLOCK_24 + * - u8cAmPm: \ref RTC_AM / \ref RTC_PM + * - u32cSecond: Second value + * - u32cMinute: Minute value + * - u32cHour: Hour value + * - u32cDayOfWeek: Day of week + * - u32cDay: Day value + * - u32cMonth: Month value + * - u32Year: Year value + * - u32AlarmMaskSecond: Mask second alarm + * - u32AlarmMaskMinute: Mask minute alarm + * - u32AlarmMaskHour: Mask hour alarm + * - *pfnAlarmCallBack: Call back function + * + * @retval E_RTC_ERR_EIO Initial RTC time-out + * @retval E_RTC_SUCCESS Success + * + */ +UINT32 RTC_Open(S_RTC_TIME_DATA_T *sPt) +{ + UINT32 volatile u32Reg; + + /*-----------------------------------------------------------------------------------------------------*/ + /* DO BASIC JUDGEMENT TO Check RTC time data value is reasonable or not. */ + /*-----------------------------------------------------------------------------------------------------*/ + if (((sPt->u32Year - RTC_YEAR2000) > 99) | + ((sPt->u32cMonth == 0) || (sPt->u32cMonth > 12)) | + ((sPt->u32cDay == 0) || (sPt->u32cDay > 31))) + { + return E_RTC_ERR_CALENDAR_VALUE; + } + + if (sPt->u8cClockDisplay == RTC_CLOCK_12) + { + if ((sPt->u32cHour == 0) || (sPt->u32cHour > 12)) + { + return E_RTC_ERR_TIMESACLE_VALUE ; + } + } + else if (sPt->u8cClockDisplay == RTC_CLOCK_24) + { + if (sPt->u32cHour > 23) + { + return E_RTC_ERR_TIMESACLE_VALUE ; + } + } + else + { + return E_RTC_ERR_TIMESACLE_VALUE ; + } + + if ((sPt->u32cMinute > 59) | + (sPt->u32cSecond > 59) | + (sPt->u32cSecond > 59)) + { + return E_RTC_ERR_TIME_VALUE ; + } + if (sPt->u32cDayOfWeek > 6) + { + return E_RTC_ERR_DWR_VALUE ; + } + + /*-----------------------------------------------------------------------------------------------------*/ + /* Second, set RTC time data. */ + /*-----------------------------------------------------------------------------------------------------*/ + if (sPt->u8cClockDisplay == RTC_CLOCK_12) + { + g_chHourMode = RTC_CLOCK_12; + + RTC_WriteEnable(1); + outp32(REG_RTC_TIMEFMT, RTC_CLOCK_12); + RTC_Check(); + + /*-------------------------------------------------------------------------------------------------*/ + /* important, range of 12-hour PM mode is 21 upto 32 */ + /*-------------------------------------------------------------------------------------------------*/ + if (sPt->u8cAmPm == RTC_PM) + sPt->u32cHour += 20; + } + else /* RTC_CLOCK_24 */ + { + g_chHourMode = RTC_CLOCK_24; + + RTC_WriteEnable(1); + outp32(REG_RTC_TIMEFMT, RTC_CLOCK_24); + RTC_Check(); + } + + + g_u32hiHour = sPt->u32cHour / 10; + g_u32loHour = sPt->u32cHour % 10; + g_u32hiMin = sPt->u32cMinute / 10; + g_u32loMin = sPt->u32cMinute % 10; + g_u32hiSec = sPt->u32cSecond / 10; + g_u32loSec = sPt->u32cSecond % 10; + u32Reg = (g_u32hiHour << 20); + u32Reg |= (g_u32loHour << 16); + u32Reg |= (g_u32hiMin << 12); + u32Reg |= (g_u32loMin << 8); + u32Reg |= (g_u32hiSec << 4); + u32Reg |= g_u32loSec; + g_u32Reg = u32Reg; + + RTC_WriteEnable(1); + outp32(REG_RTC_TIME, (UINT32)g_u32Reg); + RTC_Check(); + + if (sPt->u8cClockDisplay == RTC_CLOCK_12) + { + if (sPt->u8cAmPm == RTC_PM) + sPt->u32cHour -= 20; + } + + g_u32hiYear = (sPt->u32Year - RTC_YEAR2000) / 10; + g_u32loYear = (sPt->u32Year - RTC_YEAR2000) % 10; + g_u32hiMonth = sPt->u32cMonth / 10; + g_u32loMonth = sPt->u32cMonth % 10; + g_u32hiDay = sPt->u32cDay / 10; + g_u32loDay = sPt->u32cDay % 10; + u32Reg = (g_u32hiYear << 20); + u32Reg |= (g_u32loYear << 16); + u32Reg |= (g_u32hiMonth << 12); + u32Reg |= (g_u32loMonth << 8); + u32Reg |= (g_u32hiDay << 4); + u32Reg |= g_u32loDay; + g_u32Reg = u32Reg; + + RTC_WriteEnable(1); + outp32(REG_RTC_CAL, (UINT32)g_u32Reg); + RTC_Check(); + + RTC_WriteEnable(1); + outp32(REG_RTC_WEEKDAY, (UINT32)sPt->u32cDayOfWeek); + RTC_Check(); + + return E_RTC_SUCCESS; +} + + +/** + * @brief Read current date/time or alarm date/time from RTC + * + * @param[in] eTime \ref RTC_CURRENT_TIME / \ref RTC_ALARM_TIME + * @param[out] *sPt Specify the time property and current time. It includes: + * - u8cClockDisplay: \ref RTC_CLOCK_12 / \ref RTC_CLOCK_24 + * - u8cAmPm: \ref RTC_AM / \ref RTC_PM + * - u32cSecond: Second value + * - u32cMinute: Minute value + * - u32cHour: Hour value + * - u32cDayOfWeek: Day of week + * - u32cDay: Day value + * - u32cMonth: Month value + * - u32Year: Year value + * - u32AlarmMaskSecond: Mask second alarm + * - u32AlarmMaskMinute: Mask minute alarm + * - u32AlarmMaskHour: Mask hour alarm + * - *pfnAlarmCallBack: Call back function + * + * @retval E_RTC_ERR_ENOTTY Wrong select time + * @retval E_RTC_SUCCESS Success + * + */ +UINT32 RTC_Read(E_RTC_TIME_SELECT eTime, S_RTC_TIME_DATA_T *sPt) +{ + UINT32 u32Tmp; + + sPt->u8cClockDisplay = inp32(REG_RTC_TIMEFMT); /* 12/24-hour */ + sPt->u32cDayOfWeek = inp32(REG_RTC_WEEKDAY); /* Day of week */ + + switch (eTime) + { + case RTC_CURRENT_TIME: + { + g_u32Reg = inp32(REG_RTC_CAL); + g_u32Reg1 = inp32(REG_RTC_TIME); + break; + } + case RTC_ALARM_TIME: + { + g_u32Reg = inp32(REG_RTC_CALM); + g_u32Reg1 = inp32(REG_RTC_TALM); + break; + } + default: + { + return E_RTC_ERR_ENOTTY; + } + } + + g_u32hiYear = (g_u32Reg & 0xF00000) >> 20; + g_u32loYear = (g_u32Reg & 0xF0000) >> 16; + g_u32hiMonth = (g_u32Reg & 0x1000) >> 12; + g_u32loMonth = (g_u32Reg & 0xF00) >> 8; + g_u32hiDay = (g_u32Reg & 0x30) >> 4; + g_u32loDay = g_u32Reg & 0xF; + + u32Tmp = (g_u32hiYear * 10); + u32Tmp += g_u32loYear; + sPt->u32Year = u32Tmp + RTC_YEAR2000; + + u32Tmp = (g_u32hiMonth * 10); + sPt->u32cMonth = u32Tmp + g_u32loMonth; + + u32Tmp = (g_u32hiDay * 10); + sPt->u32cDay = u32Tmp + g_u32loDay; + + g_u32hiHour = (g_u32Reg1 & 0x300000) >> 20; + g_u32loHour = (g_u32Reg1 & 0xF0000) >> 16; + g_u32hiMin = (g_u32Reg1 & 0x7000) >> 12; + g_u32loMin = (g_u32Reg1 & 0xF00) >> 8; + g_u32hiSec = (g_u32Reg1 & 0x70) >> 4; + g_u32loSec = g_u32Reg1 & 0xF; + + if (sPt->u8cClockDisplay == RTC_CLOCK_12) + { + u32Tmp = (g_u32hiHour * 10); + u32Tmp += g_u32loHour; + sPt->u32cHour = u32Tmp; /* AM: 1~12. PM: 21~32. */ + + if (eTime == RTC_CURRENT_TIME) + { + if (sPt->u32cHour >= 21) + { + sPt->u8cAmPm = RTC_PM; + sPt->u32cHour -= 20; + } + else + { + sPt->u8cAmPm = RTC_AM; + } + } + else + { + if (sPt->u32cHour < 12) + { + if (sPt->u32cHour == 0) + sPt->u32cHour = 12; + sPt->u8cAmPm = RTC_AM; + } + else + { + sPt->u32cHour -= 12; + sPt->u8cAmPm = RTC_PM; + } + } + + u32Tmp = (g_u32hiMin * 10); + u32Tmp += g_u32loMin; + sPt->u32cMinute = u32Tmp; + + u32Tmp = (g_u32hiSec * 10); + u32Tmp += g_u32loSec; + sPt->u32cSecond = u32Tmp; + + } + else + { + /* RTC_CLOCK_24 */ + u32Tmp = (g_u32hiHour * 10); + u32Tmp += g_u32loHour; + sPt->u32cHour = u32Tmp; + + u32Tmp = (g_u32hiMin * 10); + u32Tmp += g_u32loMin; + sPt->u32cMinute = u32Tmp; + + u32Tmp = (g_u32hiSec * 10); + u32Tmp += g_u32loSec; + sPt->u32cSecond = u32Tmp; + } + + return E_RTC_SUCCESS; + +} + + +/** + * @brief Write current date/time or alarm date/time from RTC + * + * @param[in] eTime \ref RTC_CURRENT_TIME / \ref RTC_ALARM_TIME + * @param[in] *sPt Specify the time property and current time. It includes: + * - u8cClockDisplay: \ref RTC_CLOCK_12 / \ref RTC_CLOCK_24 + * - u8cAmPm: \ref RTC_AM / \ref RTC_PM + * - u32cSecond: Second value + * - u32cMinute: Minute value + * - u32cHour: Hour value + * - u32cDayOfWeek: Day of week + * - u32cDay: Day value + * - u32cMonth: Month value + * - u32Year: Year value + * - u32AlarmMaskSecond: Mask second alarm + * - u32AlarmMaskMinute: Mask minute alarm + * - u32AlarmMaskHour: Mask hour alarm + * - *pfnAlarmCallBack: Call back function + * + * @retval E_RTC_ERR_ENOTTY Wrong select time + * @retval E_RTC_ERR_CALENDAR_VALUE Wrong calender value + * @retval E_RTC_ERR_TIME_VALUE Wrong time value + * @retval E_RTC_ERR_DWR_VALUE Wrong day of week value + * @retval E_RTC_SUCCESS Success + * + */ +UINT32 RTC_Write(E_RTC_TIME_SELECT eTime, S_RTC_TIME_DATA_T *sPt) +{ + UINT32 u32Reg; + + /*-----------------------------------------------------------------------------------------------------*/ + /* Check RTC time data value is reasonable or not. */ + /*-----------------------------------------------------------------------------------------------------*/ + if (((sPt->u32Year - RTC_YEAR2000) > 99) | + ((sPt->u32cMonth == 0) || (sPt->u32cMonth > 12)) | + ((sPt->u32cDay == 0) || (sPt->u32cDay > 31))) + { + return E_RTC_ERR_CALENDAR_VALUE; + } + + if ((sPt->u32Year - RTC_YEAR2000) > 99) + { + return E_RTC_ERR_CALENDAR_VALUE; + } + + if ((sPt->u32cMonth == 0) || (sPt->u32cMonth > 12)) + { + return E_RTC_ERR_CALENDAR_VALUE; + } + + if ((sPt->u32cDay == 0) || (sPt->u32cDay > 31)) + { + return E_RTC_ERR_CALENDAR_VALUE; + } + + if (sPt->u8cClockDisplay == RTC_CLOCK_12) + { + if ((sPt->u32cHour == 0) || (sPt->u32cHour > 12)) + { + return E_RTC_ERR_TIME_VALUE; + } + } + else if (sPt->u8cClockDisplay == RTC_CLOCK_24) + { + if (sPt->u32cHour > 23) + { + return E_RTC_ERR_TIME_VALUE; + } + } + else + { + return E_RTC_ERR_TIME_VALUE; + } + + if (sPt->u32cMinute > 59) + { + return E_RTC_ERR_TIME_VALUE; + } + + if (sPt->u32cSecond > 59) + { + return E_RTC_ERR_TIME_VALUE; + } + + if (sPt->u32cDayOfWeek > 6) + { + return E_RTC_ERR_DWR_VALUE; + } + + switch (eTime) + { + + case RTC_CURRENT_TIME: + { + /*---------------------------------------------------------------------------------------------*/ + /* Second, set RTC time data. */ + /*---------------------------------------------------------------------------------------------*/ + + if (sPt->u8cClockDisplay == RTC_CLOCK_12) + { + g_chHourMode = RTC_CLOCK_12; + + RTC_WriteEnable(1); + outp32(REG_RTC_TIMEFMT, RTC_CLOCK_12); + RTC_Check(); + + /*-----------------------------------------------------------------------------------------*/ + /* important, range of 12-hour PM mode is 21 upto 32 */ + /*-----------------------------------------------------------------------------------------*/ + if (sPt->u8cAmPm == RTC_PM) + { + sPt->u32cHour += 20; + } + } + else /* RTC_CLOCK_24 */ + { + g_chHourMode = RTC_CLOCK_24; + + RTC_WriteEnable(1); + outp32(REG_RTC_TIMEFMT, RTC_CLOCK_24); + RTC_Check(); + + } + + g_u32hiHour = sPt->u32cHour / 10; + g_u32loHour = sPt->u32cHour % 10; + g_u32hiMin = sPt->u32cMinute / 10; + g_u32loMin = sPt->u32cMinute % 10; + g_u32hiSec = sPt->u32cSecond / 10; + g_u32loSec = sPt->u32cSecond % 10; + + u32Reg = (g_u32hiHour << 20); + u32Reg |= (g_u32loHour << 16); + u32Reg |= (g_u32hiMin << 12); + u32Reg |= (g_u32loMin << 8); + u32Reg |= (g_u32hiSec << 4); + u32Reg |= g_u32loSec; + g_u32Reg = u32Reg; + + RTC_WriteEnable(1); + outp32(REG_RTC_TIME, (UINT32)g_u32Reg); + RTC_Check(); + + g_u32hiYear = (sPt->u32Year - RTC_YEAR2000) / 10; + g_u32loYear = (sPt->u32Year - RTC_YEAR2000) % 10; + g_u32hiMonth = sPt->u32cMonth / 10; + g_u32loMonth = sPt->u32cMonth % 10; + g_u32hiDay = sPt->u32cDay / 10; + g_u32loDay = sPt->u32cDay % 10; + + u32Reg = (g_u32hiYear << 20); + u32Reg |= (g_u32loYear << 16); + u32Reg |= (g_u32hiMonth << 12); + u32Reg |= (g_u32loMonth << 8); + u32Reg |= (g_u32hiDay << 4); + u32Reg |= g_u32loDay; + g_u32Reg = u32Reg; + + RTC_WriteEnable(1); + outp32(REG_RTC_CAL, (UINT32)g_u32Reg); + RTC_Check(); + + RTC_WriteEnable(1); + outp32(REG_RTC_WEEKDAY, (UINT32) sPt->u32cDayOfWeek); + RTC_Check(); + + if (sPt->u8cClockDisplay == RTC_CLOCK_12) + { + if (sPt->u8cAmPm == RTC_PM) + { + sPt->u32cHour -= 20; + } + } + + return E_RTC_SUCCESS; + + } + case RTC_ALARM_TIME: + { + RTC_WriteEnable(1); + outp32(REG_RTC_PWRCTL, inp32(REG_RTC_PWRCTL) & ~RTC_PWRCTL_ALARM_EN_Msk); + RTC_Check(); + + /*---------------------------------------------------------------------------------------------*/ + /* Second, set alarm time data. */ + /*---------------------------------------------------------------------------------------------*/ + g_u32hiYear = (sPt->u32Year - RTC_YEAR2000) / 10; + g_u32loYear = (sPt->u32Year - RTC_YEAR2000) % 10; + g_u32hiMonth = sPt->u32cMonth / 10; + g_u32loMonth = sPt->u32cMonth % 10; + g_u32hiDay = sPt->u32cDay / 10; + g_u32loDay = sPt->u32cDay % 10; + + //u32Reg = ((sPt->u32AlarmMaskDayOfWeek & 0x1) << 31); + u32Reg = ((sPt->u32cDayOfWeek & 0x7) << 24); + //u32Reg|= ((sPt->u32AlarmMaskYear & 0x1) << 30); + u32Reg |= (g_u32hiYear << 20); + u32Reg |= (g_u32loYear << 16); + //u32Reg|= ((sPt->u32AlarmMaskMonth & 0x1) << 29); + u32Reg |= (g_u32hiMonth << 12); + u32Reg |= (g_u32loMonth << 8); + //u32Reg|= ((sPt->u32AlarmMaskDay & 0x1) << 28); + u32Reg |= (g_u32hiDay << 4); + u32Reg |= g_u32loDay; + + g_u32Reg = u32Reg; + + RTC_WriteEnable(1); + outp32(REG_RTC_CALM, (UINT32)g_u32Reg); + RTC_Check(); + + + if (g_chHourMode == RTC_CLOCK_12) + { + if (sPt->u8cAmPm == RTC_PM) /* important, range of 12-hour PM mode is 21 upto 32 */ + { + sPt->u32cHour += 20; + } + } + g_u32hiHour = sPt->u32cHour / 10; + g_u32loHour = sPt->u32cHour % 10; + g_u32hiMin = sPt->u32cMinute / 10; + g_u32loMin = sPt->u32cMinute % 10; + g_u32hiSec = sPt->u32cSecond / 10; + g_u32loSec = sPt->u32cSecond % 10; + + u32Reg = ((sPt->u32AlarmMaskHour & 0x1) << 30); + u32Reg |= (g_u32hiHour << 20); + u32Reg |= (g_u32loHour << 16); + u32Reg |= ((sPt->u32AlarmMaskMinute & 0x1) << 29); + u32Reg |= (g_u32hiMin << 12); + u32Reg |= (g_u32loMin << 8); + u32Reg |= ((sPt->u32AlarmMaskSecond & 0x1) << 28); + u32Reg |= (g_u32hiSec << 4); + u32Reg |= g_u32loSec; + + g_u32Reg = u32Reg; + + RTC_WriteEnable(1); + outp32(REG_RTC_TALM, (UINT32)g_u32Reg); + RTC_Check(); + + if (sPt->u8cClockDisplay == RTC_CLOCK_12) + { + if (sPt->u8cAmPm == RTC_PM) + { + sPt->u32cHour -= 20; + } + } + /*---------------------------------------------------------------------------------------------*/ + /* Finally, enable alarm interrupt. */ + /*---------------------------------------------------------------------------------------------*/ + + RTC_Ioctl(0, RTC_IOC_ENABLE_INT, RTC_ALARM_INT, 0); + + RTC_WriteEnable(1); + outp32(REG_RTC_PWRCTL, inp32(REG_RTC_PWRCTL) | RTC_PWRCTL_ALARM_EN_Msk); + RTC_Check(); + + return E_RTC_SUCCESS; + } + default: + { + return E_RTC_ERR_ENOTTY; + } + } + +} + + +/** + * @brief Support some commands for application. + * + * @param[in] i32Num Interface number. always set 0 + * @param[in] eCmd Command + * @param[in] u32Arg0 Arguments for the command + * @param[in] u32Arg1 Arguments for the command. + * + * @retval E_RTC_ERR_ENOTTY Wrong command or argument + * @retval E_RTC_ERR_ENODEV Interface number incorrect + * @retval E_RTC_SUCCESS Success + * + */ +UINT32 RTC_Ioctl(INT32 i32Num, E_RTC_CMD eCmd, UINT32 u32Arg0, UINT32 u32Arg1) +{ + INT32 i32Ret; + UINT32 u32Reg; + RTC_TICK_T *ptick; + UINT32 u32Tmp; + + if (i32Num != 0) + return E_RTC_ERR_ENODEV; + + switch (eCmd) + { + + case RTC_IOC_IDENTIFY_LEAP_YEAR: + { + u32Reg = inp32(REG_RTC_LEAPYEAR); + if (u32Reg & 0x01) + { + *(PUINT32)u32Arg0 = RTC_LEAP_YEAR; + } + else + { + *(PUINT32)u32Arg0 = 0; + } + break; + } + case RTC_IOC_SET_TICK_MODE: + { + ptick = (RTC_TICK_T *) u32Arg0; + + if (g_bIsEnableTickInt == TRUE) + { + RTC_Ioctl(0, RTC_IOC_DISABLE_INT, RTC_TICK_INT, 0); + g_bIsEnableTickInt = TRUE; + } + + if (ptick->ucMode > RTC_TICK_1_128_SEC) /*Tick mode 0 to 7 */ + { + return E_RTC_ERR_ENOTTY ; + } + + RTC_WriteEnable(1); + outp32(REG_RTC_TICK, ptick->ucMode); + RTC_Check(); + + /*---------------------------------------------------------------------------------------------*/ + /* Reset tick interrupt status if program enable tick interrupt before. */ + /*---------------------------------------------------------------------------------------------*/ + if (g_bIsEnableTickInt == TRUE) + { + + RTC_Ioctl(0, RTC_IOC_ENABLE_INT, RTC_TICK_INT, 0); + + return E_RTC_SUCCESS; + } + break; + } + + case RTC_IOC_GET_TICK: + { + break; + } + + case RTC_IOC_RESTORE_TICK: + { + break; + } + + case RTC_IOC_ENABLE_INT: + { + + switch ((RTC_INT_SOURCE)u32Arg0) + { + + case RTC_TICK_INT: + { + g_bIsEnableTickInt = TRUE; + u32Tmp = inp32(REG_RTC_INTEN) | RTC_TICK_INT; + break; + } + case RTC_ALARM_INT: + { + g_bIsEnableAlarmInt = TRUE; + + RTC_WriteEnable(1); + u32Tmp = inp32(REG_RTC_PWRCTL) | RTC_PWRCTL_ALARM_EN_Msk; + + outp32(REG_RTC_PWRCTL, u32Tmp); + outp32(REG_RTC_INTEN, inp32(REG_RTC_INTEN) | RTC_INTEN_ALMIEN_Msk); + + RTC_Check(); + + u32Tmp = inp32(REG_RTC_INTEN) | RTC_ALARM_INT; + + break; + } + case RTC_RELATIVE_ALARM_INT: + { + g_bIsEnableAlarmInt = TRUE; + + RTC_WriteEnable(1); + u32Tmp = inp32(REG_RTC_PWRCTL) | RTC_PWRCTL_REL_ALARM_EN_Msk; + + outp32(REG_RTC_PWRCTL, u32Tmp); + RTC_Check(); + + u32Tmp = inp32(REG_RTC_INTEN) | RTC_RELATIVE_ALARM_INT; + break; + } + case RTC_PSWI_INT: + { + g_bIsEnableAlarmInt = TRUE; + u32Tmp = inp32(REG_RTC_INTEN) | RTC_PSWI_INT; + break; + } + default: + { + return E_RTC_ERR_ENOTTY; + + } + } + + RTC_WriteEnable(1); + outp32(REG_RTC_INTEN, u32Tmp); + RTC_Check(); + + break; + } + case RTC_IOC_DISABLE_INT: + { + + switch ((RTC_INT_SOURCE)u32Arg0) + { + case RTC_TICK_INT: + { + g_bIsEnableTickInt = FALSE; + + RTC_WriteEnable(1); + u32Tmp = inp32(REG_RTC_INTEN) & (~RTC_TICK_INT); + + outp32(REG_RTC_INTEN, u32Tmp); + + outp32(REG_RTC_INTSTS, RTC_TICK_INT); + RTC_Check(); + + break; + } + case RTC_ALARM_INT: + { + g_bIsEnableAlarmInt = FALSE; + + RTC_WriteEnable(1); + u32Tmp = inp32(REG_RTC_INTEN) & (~RTC_ALARM_INT); + + outp32(REG_RTC_INTEN, u32Tmp); + RTC_Check(); + + RTC_WriteEnable(1); + u32Tmp = inp32(REG_RTC_PWRCTL) & ~RTC_PWRCTL_ALARM_EN_Msk; + + outp32(REG_RTC_PWRCTL, u32Tmp); + RTC_Check(); + + outp32(REG_RTC_INTSTS, RTC_ALARM_INT); + + break; + } + case RTC_RELATIVE_ALARM_INT: + { + g_bIsEnableAlarmInt = FALSE; + + RTC_WriteEnable(1); + u32Tmp = inp32(REG_RTC_INTEN) & (~RTC_RELATIVE_ALARM_INT); + + outp32(REG_RTC_INTEN, u32Tmp); + RTC_Check(); + + RTC_WriteEnable(1); + u32Tmp = inp32(REG_RTC_PWRCTL) & ~RTC_PWRCTL_REL_ALARM_EN_Msk; + + outp32(REG_RTC_PWRCTL, u32Tmp); + RTC_Check(); + + outp32(REG_RTC_INTSTS, RTC_RELATIVE_ALARM_INT); + + break; + } + case RTC_PSWI_INT: + { + g_bIsEnableAlarmInt = FALSE; + + RTC_WriteEnable(1); + u32Tmp = inp32(REG_RTC_INTEN) & (~RTC_PSWI_INT); + + outp32(REG_RTC_INTEN, u32Tmp); + RTC_Check(); + + outp32(REG_RTC_INTSTS, RTC_PSWI_INT); + + break; + } + + case RTC_ALL_INT: + { + g_bIsEnableTickInt = FALSE; + g_bIsEnableAlarmInt = FALSE; + + RTC_WriteEnable(1); + outp32(REG_RTC_INTEN, 0); + outp32(REG_RTC_INTSTS, RTC_ALL_INT); + RTC_Check(); + + break; + } + default: + { + return E_RTC_ERR_ENOTTY; + } + } + + + break; + } + + case RTC_IOC_SET_FREQUENCY: + { + i32Ret = RTC_DoFrequencyCompensation(u32Arg0) ; + if (i32Ret != 0) + { + return E_RTC_ERR_ENOTTY; + } + break; + } + case RTC_IOC_SET_POWER_ON: + { + RTC_WriteEnable(1); + u32Tmp = inp32(REG_RTC_PWRCTL) | 0x01; + + outp32(REG_RTC_PWRCTL, u32Tmp); + RTC_Check(); + + while ((inp32(REG_RTC_PWRCTL) & 0x01) != 0x1); + + break; + } + case RTC_IOC_SET_POWER_OFF: + { + RTC_WriteEnable(1); + outp32(REG_RTC_PWRCTL, (inp32(REG_RTC_PWRCTL) & ~0x01) | 2); + RTC_Check(); + + while (1); + + //break; + } + case RTC_IOC_SET_POWER_OFF_PERIOD: + { + if (u32Arg0 < 4) u32Arg0 = 4; + + u32Arg0 = u32Arg0 - 4; + + RTC_WriteEnable(1); + outp32(REG_RTC_PWRCTL, (inp32(REG_RTC_PWRCTL) & ~0xF000) | ((u32Arg0 & 0xF) << 12)); + RTC_Check(); + + break; + } + case RTC_IOC_ENABLE_HW_POWEROFF: + { + RTC_WriteEnable(1); + outp32(REG_RTC_PWRCTL, (inp32(REG_RTC_PWRCTL) | 0x04)); + RTC_Check(); + + break; + } + case RTC_IOC_DISABLE_HW_POWEROFF: + { + RTC_WriteEnable(1); + outp32(REG_RTC_PWRCTL, (inp32(REG_RTC_PWRCTL) & ~0x04)); + RTC_Check(); + + break; + } + case RTC_IOC_SET_PSWI_CALLBACK: + { + + RTC_Ioctl(0, RTC_IOC_ENABLE_INT, RTC_PSWI_INT, 0); + + break; + } + case RTC_IOC_GET_POWERKEY_STATUS: + { + RTC_WriteEnable(1); + if (inp32(REG_RTC_PWRCTL) & 0x80) + *(PUINT32)u32Arg0 = 1; + else + *(PUINT32)u32Arg0 = 0; + + break; + } + case RTC_IOC_SET_RELEATIVE_ALARM: + { + g_bIsEnableAlarmInt = TRUE; + + RTC_WriteEnable(1); + outp32(REG_RTC_PWRCTL, (inp32(REG_RTC_PWRCTL) & ~0xFFF0010)); + RTC_Check(); + + RTC_WriteEnable(1); + u32Tmp = (inp32(REG_RTC_PWRCTL) & ~0xFFF0000) | ((u32Arg0 & 0xFFF) << 16) | RTC_PWRCTL_REL_ALARM_EN_Msk; + + outp32(REG_RTC_PWRCTL, u32Tmp); + RTC_Check(); + + g_bIsEnableAlarmInt = TRUE; + + RTC_WriteEnable(1); + u32Tmp = inp32(REG_RTC_INTEN) | RTC_RELATIVE_ALARM_INT; + + outp32(REG_RTC_INTEN, u32Tmp); + RTC_Check(); + + break; + + } + + default: + { + return E_RTC_ERR_ENOTTY; + } + } + + return E_RTC_SUCCESS; +} + +/** + * @brief Disable AIC channel of RTC and both tick and alarm interrupt. + * + * @param[in] None + * + * @retval E_RTC_SUCCESS Success + * + */ +UINT32 RTC_Close(void) +{ + + g_bIsEnableTickInt = FALSE; + + sysDisableInterrupt(RTC_IRQn); + + + RTC_Ioctl(0, RTC_IOC_DISABLE_INT, RTC_ALL_INT, 0); + + + return E_RTC_SUCCESS; +} + +/** + * @brief Enable RTC clock. + * + * @param[in] bEnable 1: Enable \n + * 2: Disable + * + * @return None + * + */ +void RTC_EnableClock(BOOL bEnable) +{ + if (bEnable) + outp32(REG_CLK_PCLKEN0, inp32(REG_CLK_PCLKEN0) | (1 << 2)); + else + outp32(REG_CLK_PCLKEN0, inp32(REG_CLK_PCLKEN0) & ~(1 << 2)); + +} + + + +/*@}*/ /* end of group N9H30_RTC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_RTC_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_scuart.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_scuart.c new file mode 100644 index 0000000000..6656e0fe0e --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_scuart.c @@ -0,0 +1,246 @@ +/**************************************************************************//** + * @file scuart.c + * @brief N9H30 series Smartcard UART mode (SCUART) driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "N9H30.h" +#include "nu_scuart.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_SCUART_Driver SCUART Driver + @{ +*/ + + +/** @addtogroup N9H30_SCUART_EXPORTED_FUNCTIONS SCUART Exported Functions + @{ +*/ + +/** + * @brief Disable smartcard uart interface. + * @param sc Smartcard module number + * @return None + * @details The function is used to disable smartcard interface UART mode. + */ +void SCUART_Close(UINT sc) +{ + if (sc == 0) + { + outpw(REG_SC0_INTEN, 0); + outpw(REG_SC0_UARTCTL, 0); + outpw(REG_SC0_CTL, 0); + } + else + { + outpw(REG_SC1_INTEN, 0); + outpw(REG_SC1_UARTCTL, 0); + outpw(REG_SC1_CTL, 0); + } +} + +/// @cond HIDDEN_SYMBOLS +/** + * @brief This function returns module clock of specified SC interface + * @param[in] sc Smartcard module number + * @return Module clock of specified SC interface + */ +static uint32_t SCUART_GetClock(UINT sc) +{ + uint32_t u32Div; + + if (sc == 0) + u32Div = ((inpw(REG_CLK_DIVCTL6) >> 24) & 0xF) + 1; + else + u32Div = ((inpw(REG_CLK_DIVCTL6) >> 28) & 0xF) + 1; + + return 12000000 / u32Div; +} +/// @endcond HIDDEN_SYMBOLS + +/** + * @brief Enable smartcard uart interface. + * @param[in] sc Smartcard module number + * @param[in] u32baudrate Target baudrate of smartcard module. + * @return Actual baudrate of smartcard mode. + * @details This function use to enable smartcard module UART mode and set baudrate. + * @note This function configures character width to 8 bits, 1 stop bit, and no parity. + * And can use \ref SCUART_SetLineConfig function to update these settings. + */ +UINT SCUART_Open(UINT sc, UINT u32baudrate) +{ + uint32_t u32Clk = SCUART_GetClock(sc), u32Div; + + // Calculate divider for target baudrate + u32Div = (u32Clk + (u32baudrate >> 1) - 1) / u32baudrate - 1; + + if (sc == 0) + { + outpw(REG_SC0_CTL, SC_CTL_SCEN_Msk | SC_CTL_NSB_Msk); // Enable smartcard interface and stop bit = 1 + outpw(REG_SC0_UARTCTL, SCUART_CHAR_LEN_8 | SCUART_PARITY_NONE | SC_UARTCTL_UARTEN_Msk); // Enable UART mode, disable parity and 8 bit per character + outpw(REG_SC0_ETUCTL, u32Div); + } + else + { + outpw(REG_SC1_CTL, SC_CTL_SCEN_Msk | SC_CTL_NSB_Msk); // Enable smartcard interface and stop bit = 1 + outpw(REG_SC1_UARTCTL, SCUART_CHAR_LEN_8 | SCUART_PARITY_NONE | SC_UARTCTL_UARTEN_Msk); // Enable UART mode, disable parity and 8 bit per character + outpw(REG_SC1_ETUCTL, u32Div); + } + + return (u32Clk / (u32Div + 1)); +} + +/** + * @brief Read data from smartcard UART interface. + * @param[in] sc Smartcard module number + * @param[in] pu8RxBuf The buffer to store receive the data. + * @param[in] u32ReadBytes Target number of characters to receive. + * @return Actual character number reads to buffer. + * @details The function is used to read Rx data from RX FIFO. + * @note This function does not block and return immediately if there's no data available. + */ +UINT SCUART_Read(UINT sc, char *pu8RxBuf, UINT u32ReadBytes) +{ + uint32_t u32Count; + + if (sc == 0) + { + for (u32Count = 0; u32Count < u32ReadBytes; u32Count++) + { + if (inpw(REG_SC0_STATUS) & SC_STATUS_RXEMPTY_Msk) // no data available + { + break; + } + pu8RxBuf[u32Count] = inpw(REG_SC0_DAT); // get data from FIFO + } + } + else + { + for (u32Count = 0; u32Count < u32ReadBytes; u32Count++) + { + if (inpw(REG_SC1_STATUS) & SC_STATUS_RXEMPTY_Msk) // no data available + { + break; + } + pu8RxBuf[u32Count] = inpw(REG_SC1_DAT); // get data from FIFO + } + + } + + return u32Count; +} + +/** + * @brief This function use to config smartcard UART mode line setting. + * @param[in] sc Smartcard module number + * @param[in] u32Baudrate Target baudrate of smartcard module. If this value is 0, UART baudrate will not change. + * @param[in] u32DataWidth The data length, could be: + * - \ref SCUART_CHAR_LEN_5 + * - \ref SCUART_CHAR_LEN_6 + * - \ref SCUART_CHAR_LEN_7 + * - \ref SCUART_CHAR_LEN_8 + * @param[in] u32Parity The parity setting, could be: + * - \ref SCUART_PARITY_NONE + * - \ref SCUART_PARITY_ODD + * - \ref SCUART_PARITY_EVEN + * @param[in] u32StopBits The stop bit length, could be: + * - \ref SCUART_STOP_BIT_1 + * - \ref SCUART_STOP_BIT_2 + * @return Actual baudrate of smartcard. + * @details Smartcard UART mode is operated in LIN data frame. + */ +UINT SCUART_SetLineConfig(UINT sc, UINT u32Baudrate, UINT u32DataWidth, UINT u32Parity, UINT u32StopBits) +{ + + uint32_t u32Clk = SCUART_GetClock(sc), u32Div; + + if (u32Baudrate == 0) // keep original baudrate setting + { + u32Div = (sc == 0) ? inpw(REG_SC0_ETUCTL) & 0xFFF : inpw(REG_SC1_ETUCTL) & 0xFFF; + } + else + { + // Calculate divider for target baudrate + u32Div = (u32Clk + (u32Baudrate >> 1) - 1) / u32Baudrate - 1; + if (sc == 0) + outpw(REG_SC0_ETUCTL, u32Div); + else + outpw(REG_SC1_ETUCTL, u32Div); + } + + if (sc == 0) + { + outpw(REG_SC0_CTL, u32StopBits | SC_CTL_SCEN_Msk); // Set stop bit + outpw(REG_SC0_UARTCTL, u32Parity | u32DataWidth | SC_UARTCTL_UARTEN_Msk); // Set character width and parity + } + else + { + outpw(REG_SC1_CTL, u32StopBits | SC_CTL_SCEN_Msk); // Set stop bit + outpw(REG_SC1_UARTCTL, u32Parity | u32DataWidth | SC_UARTCTL_UARTEN_Msk); // Set character width and parity + } + return (u32Clk / (u32Div + 1)); +} + +/** + * @brief This function use to set receive timeout count. + * @param[in] sc Smartcard module number + * @param[in] u32TOC Rx timeout counter, using baudrate as counter unit. Valid range are 0~0x1FF, + * set this value to 0 will disable timeout counter. + * @return None + * @details The time-out counter resets and starts counting whenever the RX buffer received a + * new data word. Once the counter decrease to 1 and no new data is received or CPU + * does not read any data from FIFO, a receiver time-out interrupt will be generated. + */ +void SCUART_SetTimeoutCnt(UINT sc, UINT u32TOC) +{ + if (sc == 0) + outpw(REG_SC0_RXTOUT, u32TOC); + else + outpw(REG_SC1_RXTOUT, u32TOC); +} + + +/** + * @brief Write data to smartcard UART interface. + * @param[in] sc Smartcard module number + * @param[in] pu8TxBuf The buffer containing data to send to transmit FIFO. + * @param[in] u32WriteBytes Number of data to send. + * @return None + * @details This function is to write data into transmit FIFO to send data out. + * @note This function blocks until all data write into FIFO. + */ +void SCUART_Write(UINT sc, char *pu8TxBuf, UINT u32WriteBytes) +{ + uint32_t u32Count; + + if (sc == 0) + { + for (u32Count = 0; u32Count != u32WriteBytes; u32Count++) + { + while (inpw(REG_SC0_STATUS) & SC_STATUS_TXFULL_Msk); // Wait 'til FIFO not full + outpw(REG_SC0_DAT, pu8TxBuf[u32Count]); // Write 1 byte to FIFO + } + } + else + { + for (u32Count = 0; u32Count != u32WriteBytes; u32Count++) + { + while (inpw(REG_SC0_STATUS) & SC_STATUS_TXFULL_Msk); // Wait 'til FIFO not full + outpw(REG_SC1_DAT, pu8TxBuf[u32Count]); // Write 1 byte to FIFO + } + } +} + + +/*@}*/ /* end of group N9H30_SCUART_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_SCUART_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sdh.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sdh.c new file mode 100644 index 0000000000..3d0306b43f --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sdh.c @@ -0,0 +1,1193 @@ +/**************************************************************************//** + * @file sdh.c + * @brief N9H30 SDH driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include +#include +#include +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_sdh.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_SDH_Driver SDH Driver + @{ +*/ + + +/** @addtogroup N9H30_SDH_EXPORTED_FUNCTIONS SDH Exported Functions + @{ +*/ +#define SDH_BLOCK_SIZE 512ul + +/** @cond HIDDEN_SYMBOLS */ + +/* global variables */ +/* For response R3 (such as ACMD41, CRC-7 is invalid; but SD controller will still */ +/* calculate CRC-7 and get an error result, software should ignore this error and clear SDISR [CRC_IF] flag */ +/* _sd_uR3_CMD is the flag for it. 1 means software should ignore CRC-7 error */ + +#ifdef __ICCARM__ + #pragma data_alignment = 32 + static uint8_t _SDH0_ucSDHCBuffer[512]; + static uint8_t _SDH1_ucSDHCBuffer[512]; +#else + static uint8_t _SDH0_ucSDHCBuffer[512] __attribute__((aligned(32))); + static uint8_t _SDH1_ucSDHCBuffer[512] __attribute__((aligned(32))); +#endif + +SDH_INFO_T SD0, SD1; + +void SDH_CheckRB(SDH_T *sdh) +{ + while (1) + { + sdh->CTL |= SDH_CTL_CLK8OEN_Msk; + while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk) + { + } + if ((sdh->INTSTS & SDH_INTSTS_DAT0STS_Msk) == SDH_INTSTS_DAT0STS_Msk) + { + break; + } + } +} + + +uint32_t SDH_SDCommand(SDH_T *sdh, uint32_t ucCmd, uint32_t uArg) +{ + volatile uint32_t buf, val = 0ul; + SDH_INFO_T *pSD; + + if (sdh == SDH0) + { + pSD = &SD0; + } + else + { + pSD = &SD1; + } + + sdh->CMDARG = uArg; + buf = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (ucCmd << 8ul) | (SDH_CTL_COEN_Msk); + sdh->CTL = buf; + + while ((sdh->CTL & SDH_CTL_COEN_Msk) == SDH_CTL_COEN_Msk) + { + if (pSD->IsCardInsert == 0ul) + { + val = SDH_NO_SD_CARD; + } + } + return val; +} + + +uint32_t SDH_SDCmdAndRsp(SDH_T *sdh, uint32_t ucCmd, uint32_t uArg, uint32_t ntickCount) +{ + volatile uint32_t buf; + SDH_INFO_T *pSD; + + if (sdh == SDH0) + { + pSD = &SD0; + } + else + { + pSD = &SD1; + } + + sdh->CMDARG = uArg; + buf = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (ucCmd << 8ul) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk); + sdh->CTL = buf; + + if (ntickCount > 0ul) + { + while ((sdh->CTL & SDH_CTL_RIEN_Msk) == SDH_CTL_RIEN_Msk) + { + if (ntickCount-- == 0ul) + { + sdh->CTL |= SDH_CTL_CTLRST_Msk; /* reset SD engine */ + return 2ul; + } + if (pSD->IsCardInsert == FALSE) + { + return SDH_NO_SD_CARD; + } + } + } + else + { + while ((sdh->CTL & SDH_CTL_RIEN_Msk) == SDH_CTL_RIEN_Msk) + { + if (pSD->IsCardInsert == FALSE) + { + return SDH_NO_SD_CARD; + } + } + } + + if (pSD->R7Flag) + { + uint32_t tmp0 = 0ul, tmp1 = 0ul; + tmp1 = sdh->RESP1 & 0xfful; + tmp0 = sdh->RESP0 & 0xful; + if ((tmp1 != 0x55ul) && (tmp0 != 0x01ul)) + { + pSD->R7Flag = 0ul; + return SDH_CMD8_ERROR; + } + } + + if (!pSD->R3Flag) + { + if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) == SDH_INTSTS_CRC7_Msk) /* check CRC7 */ + { + return Successful; + } + else + { + return SDH_CRC7_ERROR; + } + } + else + { + /* ignore CRC error for R3 case */ + pSD->R3Flag = 0ul; + sdh->INTSTS = SDH_INTSTS_CRCIF_Msk; + return Successful; + } +} + + +uint32_t SDH_Swap32(uint32_t val) +{ + uint32_t buf; + + buf = val; + val <<= 24; + val |= (buf << 8) & 0xff0000ul; + val |= (buf >> 8) & 0xff00ul; + val |= (buf >> 24) & 0xfful; + return val; +} + +/* Get 16 bytes CID or CSD */ +uint32_t SDH_SDCmdAndRsp2(SDH_T *sdh, uint32_t ucCmd, uint32_t uArg, uint32_t puR2ptr[]) +{ + uint32_t i, buf; + uint32_t tmpBuf[5]; + SDH_INFO_T *pSD; + + if (sdh == SDH0) + { + pSD = &SD0; + } + else + { + pSD = &SD1; + } + + sdh->CMDARG = uArg; + buf = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (ucCmd << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_R2EN_Msk); + sdh->CTL = buf; + + while ((sdh->CTL & SDH_CTL_R2EN_Msk) == SDH_CTL_R2EN_Msk) + { + if (pSD->IsCardInsert == FALSE) + { + return SDH_NO_SD_CARD; + } + } + + if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) == SDH_INTSTS_CRC7_Msk) + { + for (i = 0ul; i < 5ul; i++) + { + tmpBuf[i] = SDH_Swap32(sdh->FB[i]); + } + for (i = 0ul; i < 4ul; i++) + { + puR2ptr[i] = ((tmpBuf[i] & 0x00fffffful) << 8) | ((tmpBuf[i + 1ul] & 0xff000000ul) >> 24); + } + } + else + { + return SDH_CRC7_ERROR; + } + return Successful; +} + + +uint32_t SDH_SDCmdAndRspDataIn(SDH_T *sdh, uint32_t ucCmd, uint32_t uArg) +{ + volatile uint32_t buf; + SDH_INFO_T *pSD; + + if (sdh == SDH0) + { + pSD = &SD0; + } + else + { + pSD = &SD1; + } + + sdh->CMDARG = uArg; + buf = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (ucCmd << 8ul) | + (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk); + + sdh->CTL = buf; + + while ((sdh->CTL & SDH_CTL_RIEN_Msk) == SDH_CTL_RIEN_Msk) + { + if (pSD->IsCardInsert == FALSE) + { + return SDH_NO_SD_CARD; + } + } + + while ((sdh->CTL & SDH_CTL_DIEN_Msk) == SDH_CTL_DIEN_Msk) + { + if (pSD->IsCardInsert == FALSE) + { + return SDH_NO_SD_CARD; + } + } + + if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) != SDH_INTSTS_CRC7_Msk) + { + /* check CRC7 */ + return SDH_CRC7_ERROR; + } + + if ((sdh->INTSTS & SDH_INTSTS_CRC16_Msk) != SDH_INTSTS_CRC16_Msk) + { + /* check CRC16 */ + return SDH_CRC16_ERROR; + } + return 0ul; +} + +/* there are 8 bits for divider0, maximum is 256 */ +#define SDH_CLK_DIV0_MAX 256ul + +void SDH_Set_clock(SDH_T *sdh, uint32_t sd_clock_khz) +{ + UINT32 div; + uint32_t SDH_ReferenceClock; + + if (sd_clock_khz <= 2000) + { + SDH_ReferenceClock = 12000; + if (sdh == SDH0) + { + outpw(REG_CLK_DIVCTL9, (inpw(REG_CLK_DIVCTL9) & ~0x18) | (0x0 << 3)); // SD clock from XIN [4:3] + } + else + { + //fixme outpw(REG_CLK_DIVCTL9, (inpw(REG_CLK_DIVCTL9) & ~0x18) | (0x0 << 3)); // SD clock from XIN [4:3] + } + } + else + { + SDH_ReferenceClock = 300000; + if (sdh == SDH0) + { + outpw(REG_CLK_DIVCTL9, (inpw(REG_CLK_DIVCTL9) & ~0x18) | (0x3 << 3)); // SD clock from UPLL [4:3] + } + else + { + //fixme outpw(REG_CLK_DIVCTL9, (inpw(REG_CLK_DIVCTL9) & ~0x18) | (0x3 << 3)); // SD clock from UPLL [4:3] + } + } + div = (SDH_ReferenceClock / sd_clock_khz) - 1; + + if (div >= SDH_CLK_DIV0_MAX) + { + div = 0xff; + } + outpw(REG_CLK_DIVCTL9, (inpw(REG_CLK_DIVCTL9) & ~0xff00) | ((div) << 8)); // SD clock divided by CLKDIV3[SD_N] [15:8] +} + +uint32_t SDH_CardDetection(SDH_T *sdh) +{ + uint32_t i, val = TRUE; + SDH_INFO_T *pSD; + + if (sdh == SDH0) + { + pSD = &SD0; + } + else + { + pSD = &SD1; + } + + + if ((sdh->INTEN & SDH_INTEN_CDSRC_Msk) == SDH_INTEN_CDSRC_Msk) /* Card detect pin from GPIO */ + { + if ((sdh->INTSTS & SDH_INTSTS_CDSTS_Msk) == SDH_INTSTS_CDSTS_Msk) /* Card remove */ + { + pSD->IsCardInsert = (uint8_t)FALSE; + val = FALSE; + } + else + { + pSD->IsCardInsert = (uint8_t)TRUE; + } + } + else if ((sdh->INTEN & SDH_INTEN_CDSRC_Msk) != SDH_INTEN_CDSRC_Msk) + { + sdh->CTL |= SDH_CTL_CLKKEEP_Msk; + for (i = 0ul; i < 5000ul; i++) + { + } + + if ((sdh->INTSTS & SDH_INTSTS_CDSTS_Msk) == SDH_INTSTS_CDSTS_Msk) /* Card insert */ + { + pSD->IsCardInsert = (uint8_t)TRUE; + } + else + { + pSD->IsCardInsert = (uint8_t)FALSE; + val = FALSE; + } + + sdh->CTL &= ~SDH_CTL_CLKKEEP_Msk; + } + + return val; +} + +uint32_t SDH_Init(SDH_T *sdh) +{ + uint32_t volatile i, status; + uint32_t resp; + uint32_t CIDBuffer[4]; + uint32_t volatile u32CmdTimeOut; + SDH_INFO_T *pSD; + + if (sdh == SDH0) + { + pSD = &SD0; + } + else + { + pSD = &SD1; + } + + /* set the clock to 300KHz */ + SDH_Set_clock(sdh, 300ul); + + /* power ON 74 clock */ + sdh->CTL |= SDH_CTL_CLK74OEN_Msk; + + while ((sdh->CTL & SDH_CTL_CLK74OEN_Msk) == SDH_CTL_CLK74OEN_Msk) + { + if (pSD->IsCardInsert == FALSE) + { + return SDH_NO_SD_CARD; + } + } + + SDH_SDCommand(sdh, 0ul, 0ul); /* reset all cards */ + for (i = 0x1000ul; i > 0ul; i--) + { + } + + /* initial SDHC */ + pSD->R7Flag = 1ul; + u32CmdTimeOut = 0xFFFFFul; + + i = SDH_SDCmdAndRsp(sdh, 8ul, 0x00000155ul, u32CmdTimeOut); + if (i == Successful) + { + /* SD 2.0 */ + SDH_SDCmdAndRsp(sdh, 55ul, 0x00ul, u32CmdTimeOut); + pSD->R3Flag = 1ul; + SDH_SDCmdAndRsp(sdh, 41ul, 0x40ff8000ul, u32CmdTimeOut); /* 2.7v-3.6v */ + resp = sdh->RESP0; + + while ((resp & 0x00800000ul) != 0x00800000ul) /* check if card is ready */ + { + SDH_SDCmdAndRsp(sdh, 55ul, 0x00ul, u32CmdTimeOut); + pSD->R3Flag = 1ul; + SDH_SDCmdAndRsp(sdh, 41ul, 0x40ff8000ul, u32CmdTimeOut); /* 3.0v-3.4v */ + resp = sdh->RESP0; + } + if ((resp & 0x00400000ul) == 0x00400000ul) + { + pSD->CardType = SDH_TYPE_SD_HIGH; + } + else + { + pSD->CardType = SDH_TYPE_SD_LOW; + } + } + else + { + /* SD 1.1 */ + SDH_SDCommand(sdh, 0ul, 0ul); /* reset all cards */ + for (i = 0x100ul; i > 0ul; i--) + { + } + + i = SDH_SDCmdAndRsp(sdh, 55ul, 0x00ul, u32CmdTimeOut); + if (i == 2ul) /* MMC memory */ + { + + SDH_SDCommand(sdh, 0ul, 0ul); /* reset */ + for (i = 0x100ul; i > 0ul; i--) + { + } + + pSD->R3Flag = 1ul; + + if (SDH_SDCmdAndRsp(sdh, 1ul, 0x40ff8000ul, u32CmdTimeOut) != 2ul) /* eMMC memory */ + { + resp = sdh->RESP0; + while ((resp & 0x00800000ul) != 0x00800000ul) + { + /* check if card is ready */ + pSD->R3Flag = 1ul; + + SDH_SDCmdAndRsp(sdh, 1ul, 0x40ff8000ul, u32CmdTimeOut); /* high voltage */ + resp = sdh->RESP0; + } + + if ((resp & 0x00400000ul) == 0x00400000ul) + { + pSD->CardType = SDH_TYPE_EMMC; + } + else + { + pSD->CardType = SDH_TYPE_MMC; + } + } + else + { + pSD->CardType = SDH_TYPE_UNKNOWN; + return SDH_ERR_DEVICE; + } + } + else if (i == 0ul) /* SD Memory */ + { + pSD->R3Flag = 1ul; + SDH_SDCmdAndRsp(sdh, 41ul, 0x00ff8000ul, u32CmdTimeOut); /* 3.0v-3.4v */ + resp = sdh->RESP0; + while ((resp & 0x00800000ul) != 0x00800000ul) /* check if card is ready */ + { + SDH_SDCmdAndRsp(sdh, 55ul, 0x00ul, u32CmdTimeOut); + pSD->R3Flag = 1ul; + SDH_SDCmdAndRsp(sdh, 41ul, 0x00ff8000ul, u32CmdTimeOut); /* 3.0v-3.4v */ + resp = sdh->RESP0; + } + pSD->CardType = SDH_TYPE_SD_LOW; + } + else + { + pSD->CardType = SDH_TYPE_UNKNOWN; + return SDH_INIT_ERROR; + } + } + + if (pSD->CardType != SDH_TYPE_UNKNOWN) + { + SDH_SDCmdAndRsp2(sdh, 2ul, 0x00ul, CIDBuffer); + if ((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC)) + { + if ((status = SDH_SDCmdAndRsp(sdh, 3ul, 0x10000ul, 0ul)) != Successful) /* set RCA */ + { + return status; + } + pSD->RCA = 0x10000ul; + } + else + { + if ((status = SDH_SDCmdAndRsp(sdh, 3ul, 0x00ul, 0ul)) != Successful) /* get RCA */ + { + return status; + } + else + { + pSD->RCA = (sdh->RESP0 << 8) & 0xffff0000; + } + } + } + return Successful; +} + + +uint32_t SDH_SwitchToHighSpeed(SDH_T *sdh, SDH_INFO_T *pSD) +{ + uint32_t volatile status = 0ul; + uint16_t current_comsumption, busy_status0; + + sdh->DMASA = (uint32_t)pSD->dmabuf; + sdh->BLEN = 63ul; + + if ((status = SDH_SDCmdAndRspDataIn(sdh, 6ul, 0x00ffff01ul)) != Successful) + { + return Fail; + } + + current_comsumption = (uint16_t)(*pSD->dmabuf) << 8; + current_comsumption |= (uint16_t)(*(pSD->dmabuf + 1)); + if (!current_comsumption) + { + return Fail; + } + + busy_status0 = (uint16_t)(*(pSD->dmabuf + 28)) << 8; + busy_status0 |= (uint16_t)(*(pSD->dmabuf + 29)); + + if (!busy_status0) /* function ready */ + { + sdh->DMASA = (uint32_t)pSD->dmabuf; + sdh->BLEN = 63ul; /* 512 bit */ + + if ((status = SDH_SDCmdAndRspDataIn(sdh, 6ul, 0x80ffff01ul)) != Successful) + { + return Fail; + } + + /* function change timing: 8 clocks */ + sdh->CTL |= SDH_CTL_CLK8OEN_Msk; + while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk) + { + } + + current_comsumption = (uint16_t)(*pSD->dmabuf) << 8; + current_comsumption |= (uint16_t)(*(pSD->dmabuf + 1)); + if (!current_comsumption) + { + return Fail; + } + + return Successful; + } + else + { + return Fail; + } +} + + +uint32_t SDH_SelectCardType(SDH_T *sdh) +{ + uint32_t volatile status = 0ul; + uint32_t param; + SDH_INFO_T *pSD; + + if (sdh == SDH0) + { + pSD = &SD0; + } + else + { + pSD = &SD1; + } + + if ((status = SDH_SDCmdAndRsp(sdh, 7ul, pSD->RCA, 0ul)) != Successful) + { + return status; + } + + SDH_CheckRB(sdh); + + /* if SD card set 4bit */ + if (pSD->CardType == SDH_TYPE_SD_HIGH) + { + sdh->DMASA = (uint32_t)pSD->dmabuf; + sdh->BLEN = 0x07ul; /* 64 bit */ + sdh->DMACTL |= SDH_DMACTL_DMARST_Msk; + while ((sdh->DMACTL & SDH_DMACTL_DMARST_Msk) == 0x2); + + if ((status = SDH_SDCmdAndRsp(sdh, 55ul, pSD->RCA, 0ul)) != Successful) + { + return status; + } + if ((status = SDH_SDCmdAndRspDataIn(sdh, 51ul, 0x00ul)) != Successful) + { + return status; + } + + if ((*pSD->dmabuf & 0xful) == 0x2ul) + { + status = SDH_SwitchToHighSpeed(sdh, pSD); + if (status == Successful) + { + /* divider */ + SDH_Set_clock(sdh, SDHC_FREQ); + } + } + + if ((status = SDH_SDCmdAndRsp(sdh, 55ul, pSD->RCA, 0ul)) != Successful) + { + return status; + } + if ((status = SDH_SDCmdAndRsp(sdh, 6ul, 0x02ul, 0ul)) != Successful) /* set bus width */ + { + return status; + } + + sdh->CTL |= SDH_CTL_DBW_Msk; + } + else if (pSD->CardType == SDH_TYPE_SD_LOW) + { + sdh->DMASA = (uint32_t)pSD->dmabuf;; + sdh->BLEN = 0x07ul; + + if ((status = SDH_SDCmdAndRsp(sdh, 55ul, pSD->RCA, 0ul)) != Successful) + { + return status; + } + if ((status = SDH_SDCmdAndRspDataIn(sdh, 51ul, 0x00ul)) != Successful) + { + return status; + } + + /* set data bus width. ACMD6 for SD card, SDCR_DBW for host. */ + if ((status = SDH_SDCmdAndRsp(sdh, 55ul, pSD->RCA, 0ul)) != Successful) + { + return status; + } + + if ((status = SDH_SDCmdAndRsp(sdh, 6ul, 0x02ul, 0ul)) != Successful) + { + return status; + } + + sdh->CTL |= SDH_CTL_DBW_Msk; + } + else if ((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC)) + { + + if (pSD->CardType == SDH_TYPE_MMC) + { + sdh->CTL &= ~SDH_CTL_DBW_Msk; + } + + /*--- sent CMD6 to MMC card to set bus width to 4 bits mode */ + /* set CMD6 argument Access field to 3, Index to 183, Value to 1 (4-bit mode) */ + param = (3ul << 24) | (183ul << 16) | (1ul << 8); + if ((status = SDH_SDCmdAndRsp(sdh, 6ul, param, 0ul)) != Successful) + { + return status; + } + SDH_CheckRB(sdh); + + sdh->CTL |= SDH_CTL_DBW_Msk; /* set bus width to 4-bit mode for SD host controller */ + + } + + if ((status = SDH_SDCmdAndRsp(sdh, 16ul, SDH_BLOCK_SIZE, 0ul)) != Successful) + { + return status; + } + sdh->BLEN = SDH_BLOCK_SIZE - 1ul; + + SDH_SDCommand(sdh, 7ul, 0ul); + sdh->CTL |= SDH_CTL_CLK8OEN_Msk; + while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk) + { + } + + sdh->INTEN |= SDH_INTEN_BLKDIEN_Msk; + + return Successful; +} + +void SDH_Get_SD_info(SDH_T *sdh) +{ + unsigned int R_LEN, C_Size, MULT, size; + uint32_t Buffer[4]; + //unsigned char *ptr; + SDH_INFO_T *pSD; + + if (sdh == SDH0) + { + pSD = &SD0; + } + else + { + pSD = &SD1; + } + + SDH_SDCmdAndRsp2(sdh, 9ul, pSD->RCA, Buffer); + + if ((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC)) + { + /* for MMC/eMMC card */ + if ((Buffer[0] & 0xc0000000) == 0xc0000000) + { + /* CSD_STRUCTURE [127:126] is 3 */ + /* CSD version depend on EXT_CSD register in eMMC v4.4 for card size > 2GB */ + SDH_SDCmdAndRsp(sdh, 7ul, pSD->RCA, 0ul); + + //ptr = (uint8_t *)((uint32_t)_SDH_ucSDHCBuffer ); + sdh->DMASA = (uint32_t)pSD->dmabuf;; + sdh->BLEN = 511ul; /* read 512 bytes for EXT_CSD */ + + if (SDH_SDCmdAndRspDataIn(sdh, 8ul, 0x00ul) == Successful) + { + SDH_SDCommand(sdh, 7ul, 0ul); + sdh->CTL |= SDH_CTL_CLK8OEN_Msk; + while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk) + { + } + + pSD->totalSectorN = (uint32_t)(*(pSD->dmabuf + 215)) << 24; + pSD->totalSectorN |= (uint32_t)(*(pSD->dmabuf + 214)) << 16; + pSD->totalSectorN |= (uint32_t)(*(pSD->dmabuf + 213)) << 8; + pSD->totalSectorN |= (uint32_t)(*(pSD->dmabuf + 212)); + pSD->diskSize = pSD->totalSectorN / 2ul; + } + } + else + { + /* CSD version v1.0/1.1/1.2 in eMMC v4.4 spec for card size <= 2GB */ + R_LEN = (Buffer[1] & 0x000f0000ul) >> 16; + C_Size = ((Buffer[1] & 0x000003fful) << 2) | ((Buffer[2] & 0xc0000000ul) >> 30); + MULT = (Buffer[2] & 0x00038000ul) >> 15; + size = (C_Size + 1ul) * (1ul << (MULT + 2ul)) * (1ul << R_LEN); + + pSD->diskSize = size / 1024ul; + pSD->totalSectorN = size / 512ul; + } + } + else + { + if ((Buffer[0] & 0xc0000000) != 0x0ul) + { + C_Size = ((Buffer[1] & 0x0000003ful) << 16) | ((Buffer[2] & 0xffff0000ul) >> 16); + size = (C_Size + 1ul) * 512ul; /* Kbytes */ + + pSD->diskSize = size; + pSD->totalSectorN = size << 1; + } + else + { + R_LEN = (Buffer[1] & 0x000f0000ul) >> 16; + C_Size = ((Buffer[1] & 0x000003fful) << 2) | ((Buffer[2] & 0xc0000000ul) >> 30); + MULT = (Buffer[2] & 0x00038000ul) >> 15; + size = (C_Size + 1ul) * (1ul << (MULT + 2ul)) * (1ul << R_LEN); + + pSD->diskSize = size / 1024ul; + pSD->totalSectorN = size / 512ul; + } + } + pSD->sectorSize = (int)512; +// printf("The size is %d KB\n", pSD->diskSize); +} + +/** @endcond HIDDEN_SYMBOLS */ + + +/** + * @brief This function use to reset SD function and select card detection source and pin. + * + * @param[in] sdh Select SDH0 or SDH1. + * @param[in] u32CardDetSrc Select card detection pin from GPIO or DAT3 pin. ( \ref CardDetect_From_GPIO / \ref CardDetect_From_DAT3) + * + * @return None + */ +void SDH_Open(SDH_T *sdh, uint32_t u32CardDetSrc) +{ + volatile int i; + sdh->DMACTL = SDH_DMACTL_DMARST_Msk; + while ((sdh->DMACTL & SDH_DMACTL_DMARST_Msk) == SDH_DMACTL_DMARST_Msk) + { + } + + sdh->DMACTL = SDH_DMACTL_DMAEN_Msk; + + sdh->GCTL = SDH_GCTL_GCTLRST_Msk | SDH_GCTL_SDEN_Msk; + while ((sdh->GCTL & SDH_GCTL_GCTLRST_Msk) == SDH_GCTL_GCTLRST_Msk) + { + } + + if (sdh == SDH0) + { + memset(&SD0, 0, sizeof(SDH_INFO_T)); + SD0.dmabuf = (unsigned char *)((uint32_t)_SDH0_ucSDHCBuffer | 0x80000000); + } + else if (sdh == SDH1) + { + memset(&SD1, 0, sizeof(SDH_INFO_T)); + SD1.dmabuf = (unsigned char *)((uint32_t)_SDH1_ucSDHCBuffer | 0x80000000); + } + else + { + } + + sdh->GCTL = SDH_GCTL_SDEN_Msk; + + if ((u32CardDetSrc & CardDetect_From_DAT3) == CardDetect_From_DAT3) + { + sdh->INTEN &= ~SDH_INTEN_CDSRC_Msk; + } + else + { + sdh->INTEN |= SDH_INTEN_CDSRC_Msk; + } + for (i = 0; i < 0x100; i++); + sdh->INTSTS = SDH_INTSTS_CDIF_Msk; + sdh->INTEN |= SDH_INTEN_CDIEN_Msk; + + sdh->CTL |= SDH_CTL_CTLRST_Msk; + while ((sdh->CTL & SDH_CTL_CTLRST_Msk) == SDH_CTL_CTLRST_Msk) + { + } +} + +/** + * @brief This function use to initial SD card. + * + * @param[in] sdh Select SDH0 or SDH1. + * + * @return None + * + * @details This function is used to initial SD card. + * SD initial state needs 400KHz clock output, driver will use HIRC for SD initial clock source. + * And then switch back to the user's setting. + */ +uint32_t SDH_Probe(SDH_T *sdh) +{ + uint32_t val; + + sdh->GINTEN = 0ul; + sdh->CTL &= ~SDH_CTL_SDNWR_Msk; + sdh->CTL |= 0x09ul << SDH_CTL_SDNWR_Pos; /* set SDNWR = 9 */ + sdh->CTL &= ~SDH_CTL_BLKCNT_Msk; + sdh->CTL |= 0x01ul << SDH_CTL_BLKCNT_Pos; /* set BLKCNT = 1 */ + sdh->CTL &= ~SDH_CTL_DBW_Msk; /* SD 1-bit data bus */ + + if (!(SDH_CardDetection(sdh))) + { + return SDH_NO_SD_CARD; + } + + if ((val = SDH_Init(sdh)) != 0ul) + { + return val; + } + + /* divider */ + if ((SD0.CardType == SDH_TYPE_MMC) || (SD1.CardType == SDH_TYPE_MMC)) + { + SDH_Set_clock(sdh, MMC_FREQ); + } + else + { + SDH_Set_clock(sdh, SD_FREQ); + } + SDH_Get_SD_info(sdh); + + if ((val = SDH_SelectCardType(sdh)) != 0ul) + { + return val; + } + + return 0ul; +} + +/** + * @brief This function use to read data from SD card. + * + * @param[in] sdh Select SDH0 or SDH1. + * @param[out] pu8BufAddr The buffer to receive the data from SD card. + * @param[in] u32StartSec The start read sector address. + * @param[in] u32SecCount The the read sector number of data + * + * @return None + */ +uint32_t SDH_Read(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount) +{ + uint32_t volatile bIsSendCmd = FALSE, buf; + uint32_t volatile reg; + uint32_t volatile i, loop, status; + uint32_t blksize = SDH_BLOCK_SIZE; + + SDH_INFO_T *pSD; + if (sdh == SDH0) + { + pSD = &SD0; + } + else + { + pSD = &SD1; + } + + if (u32SecCount == 0ul) + { + return SDH_SELECT_ERROR; + } + + if ((status = SDH_SDCmdAndRsp(sdh, 7ul, pSD->RCA, 0ul)) != Successful) + { + return status; + } + SDH_CheckRB(sdh); + + sdh->BLEN = blksize - 1ul; /* the actual byte count is equal to (SDBLEN+1) */ + + if ((pSD->CardType == SDH_TYPE_SD_HIGH) || (pSD->CardType == SDH_TYPE_EMMC)) + { + sdh->CMDARG = u32StartSec; + } + else + { + sdh->CMDARG = u32StartSec * blksize; + } + + sdh->DMASA = (uint32_t)pu8BufAddr; + + loop = u32SecCount / 255ul; + for (i = 0ul; i < loop; i++) + { + pSD->DataReadyFlag = (uint8_t)FALSE; + reg = sdh->CTL & ~SDH_CTL_CMDCODE_Msk; + reg = reg | 0xff0000ul; /* set BLK_CNT to 255 */ + if (bIsSendCmd == FALSE) + { + sdh->CTL = reg | (18ul << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk); + bIsSendCmd = TRUE; + } + else + { + sdh->CTL = reg | SDH_CTL_DIEN_Msk; + } + + while (!pSD->DataReadyFlag) + { + if (pSD->DataReadyFlag) + { + break; + } + if (pSD->IsCardInsert == FALSE) + { + return SDH_NO_SD_CARD; + } + } + + if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) != SDH_INTSTS_CRC7_Msk) /* check CRC7 */ + { + return SDH_CRC7_ERROR; + } + + if ((sdh->INTSTS & SDH_INTSTS_CRC16_Msk) != SDH_INTSTS_CRC16_Msk) /* check CRC16 */ + { + return SDH_CRC16_ERROR; + } + } + + loop = u32SecCount % 255ul; + if (loop != 0ul) + { + pSD->DataReadyFlag = (uint8_t)FALSE; + reg = sdh->CTL & (~SDH_CTL_CMDCODE_Msk); + reg = reg & (~SDH_CTL_BLKCNT_Msk); + reg |= (loop << 16); /* setup SDCR_BLKCNT */ + + if (bIsSendCmd == FALSE) + { + sdh->CTL = reg | (18ul << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk); + bIsSendCmd = TRUE; + } + else + { + sdh->CTL = reg | SDH_CTL_DIEN_Msk; + } + + while (!pSD->DataReadyFlag) + { + if (pSD->IsCardInsert == FALSE) + { + return SDH_NO_SD_CARD; + } + } + + if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) != SDH_INTSTS_CRC7_Msk) /* check CRC7 */ + { + return SDH_CRC7_ERROR; + } + + if ((sdh->INTSTS & SDH_INTSTS_CRC16_Msk) != SDH_INTSTS_CRC16_Msk) /* check CRC16 */ + { + return SDH_CRC16_ERROR; + } + } + + if (SDH_SDCmdAndRsp(sdh, 12ul, 0ul, 0ul)) /* stop command */ + { + return SDH_CRC7_ERROR; + } + SDH_CheckRB(sdh); + + SDH_SDCommand(sdh, 7ul, 0ul); + sdh->CTL |= SDH_CTL_CLK8OEN_Msk; + while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk) + { + } + + return Successful; +} + + +/** + * @brief This function use to write data to SD card. + * + * @param[in] sdh Select SDH0 or SDH1. + * @param[in] pu8BufAddr The buffer to send the data to SD card. + * @param[in] u32StartSec The start write sector address. + * @param[in] u32SecCount The the write sector number of data. + * + * @return \ref SDH_SELECT_ERROR : u32SecCount is zero. \n + * \ref SDH_NO_SD_CARD : SD card be removed. \n + * \ref SDH_CRC_ERROR : CRC error happen. \n + * \ref SDH_CRC7_ERROR : CRC7 error happen. \n + * \ref Successful : Write data to SD card success. + */ +uint32_t SDH_Write(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount) +{ + uint32_t volatile bIsSendCmd = FALSE; + uint32_t volatile reg; + uint32_t volatile i, loop, status; + + SDH_INFO_T *pSD; + + if (sdh == SDH0) + { + pSD = &SD0; + } + else + { + pSD = &SD1; + } + + if (u32SecCount == 0ul) + { + return SDH_SELECT_ERROR; + } + + if ((status = SDH_SDCmdAndRsp(sdh, 7ul, pSD->RCA, 0ul)) != Successful) + { + return status; + } + + SDH_CheckRB(sdh); + + /* According to SD Spec v2.0, the write CMD block size MUST be 512, and the start address MUST be 512*n. */ + sdh->BLEN = SDH_BLOCK_SIZE - 1ul; + + if ((pSD->CardType == SDH_TYPE_SD_HIGH) || (pSD->CardType == SDH_TYPE_EMMC)) + { + sdh->CMDARG = u32StartSec; + } + else + { + sdh->CMDARG = u32StartSec * SDH_BLOCK_SIZE; /* set start address for SD CMD */ + } + + sdh->DMASA = (uint32_t)pu8BufAddr; + loop = u32SecCount / 255ul; /* the maximum block count is 0xFF=255 for register SDCR[BLK_CNT] */ + for (i = 0ul; i < loop; i++) + { + pSD->DataReadyFlag = (uint8_t)FALSE; + reg = sdh->CTL & 0xff00c080; + reg = reg | 0xff0000ul; /* set BLK_CNT to 0xFF=255 */ + if (!bIsSendCmd) + { + sdh->CTL = reg | (25ul << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk); + bIsSendCmd = TRUE; + } + else + { + sdh->CTL = reg | SDH_CTL_DOEN_Msk; + } + + while (!pSD->DataReadyFlag) + { + if (pSD->IsCardInsert == FALSE) + { + return SDH_NO_SD_CARD; + } + } + + if ((sdh->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0ul) + { + sdh->INTSTS = SDH_INTSTS_CRCIF_Msk; + return SDH_CRC_ERROR; + } + } + + loop = u32SecCount % 255ul; + if (loop != 0ul) + { + pSD->DataReadyFlag = (uint8_t)FALSE; + reg = (sdh->CTL & 0xff00c080) | (loop << 16); + if (!bIsSendCmd) + { + sdh->CTL = reg | (25ul << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk); + bIsSendCmd = TRUE; + } + else + { + sdh->CTL = reg | SDH_CTL_DOEN_Msk; + } + + while (!pSD->DataReadyFlag) + { + if (pSD->IsCardInsert == FALSE) + { + return SDH_NO_SD_CARD; + } + } + + if ((sdh->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0ul) + { + sdh->INTSTS = SDH_INTSTS_CRCIF_Msk; + return SDH_CRC_ERROR; + } + } + sdh->INTSTS = SDH_INTSTS_CRCIF_Msk; + + if (SDH_SDCmdAndRsp(sdh, 12ul, 0ul, 0ul)) /* stop command */ + { + return SDH_CRC7_ERROR; + } + SDH_CheckRB(sdh); + + SDH_SDCommand(sdh, 7ul, 0ul); + sdh->CTL |= SDH_CTL_CLK8OEN_Msk; + while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk) + { + } + + return Successful; +} + +/*@}*/ /* end of group N9H30_SD_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_SD_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + + + + + + + + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_spi.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_spi.c new file mode 100644 index 0000000000..3f631238fa --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_spi.c @@ -0,0 +1,336 @@ +/**************************************************************************//** +* @file spi.c +* @brief N9H30 SPI driver source file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +/* Header files */ +#include +#include + +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_spi.h" +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_SPI_Driver SPI Driver + @{ +*/ + +/** @addtogroup N9H30_SPI_EXPORTED_CONSTANTS SPI Exported Constants + @{ +*/ +/// @cond HIDDEN_SYMBOLS + +#define spi_out(dev, byte, addr) outpw((dev)->base + addr, byte) +#define spi_in(dev, addr) inpw((dev)->base + addr) + +typedef struct +{ + uint32_t base; /* spi bus number */ + uint8_t openflag; + uint8_t intflag; +} spi_dev; + +/// @endcond HIDDEN_SYMBOLS +/*@}*/ /* end of group N9H30_EMAC_EXPORTED_CONSTANTS */ + +/** @addtogroup N9H30_SPI_EXPORTED_FUNCTIONS SPI Exported Functions + @{ +*/ +/// @cond HIDDEN_SYMBOLS + +static spi_dev spi_device[SPI_NUMBER]; + +#if 0 +/** + * @brief SPI-0 Interrupt handler + * @param None + * @return None + */ +static void spi0ISR(void) +{ + // clear interrupt flag + outpw(REG_SPI0_CNTRL, spi_in((spi_dev *)((uint32_t)&spi_device[0]), CNTRL) | 0x1 << 16); + spi_device[0].intflag = 1; +} + +/** + * @brief SPI-1 Interrupt handler + * @param None + * @return None + */ +static void spi1ISR(void) +{ + // clear interrupt flag + outpw(REG_SPI1_CNTRL, spi_in((spi_dev *)((uint32_t)&spi_device[1]), CNTRL) | 0x1 << 16); + spi_device[1].intflag = 1; +} +#endif + +/** + * @brief Set SPI divider + * @param[in] dev pointer to spi interface structure + * @param[in] speed desire spi speed + * @return speed set actually + */ +static uint32_t spiSetSpeed(spi_dev *dev, uint32_t speed) +{ + uint16_t div = (uint16_t)(SPI_INPUT_CLOCK / (2 * speed)) - 1; + + spi_out(dev, div, DIVIDER); + return (SPI_INPUT_CLOCK / (2 * (div + 1))); +} + +/// @endcond /* HIDDEN_SYMBOLS */ + +/** + * @brief Initialize spi interface and install interrupt callback function + * @return always 0. + * @retval 0 Success. + */ +int32_t spiInit(int32_t fd) +{ +#if 0 + if (fd == 0) + { + sysInstallISR(IRQ_LEVEL_1, SPI0_IRQn, (PVOID)spi0ISR); + sysEnableInterrupt(SPI0_IRQn); + memset((void *)&spi_device[0], 0, sizeof(spi_dev)); + } + else + { + sysInstallISR(IRQ_LEVEL_1, SPI1_IRQn, (PVOID)spi1ISR); + sysEnableInterrupt(SPI1_IRQn); + memset((void *)&spi_device[1], 0, sizeof(spi_dev)); + } + + sysSetLocalInterrupt(ENABLE_IRQ); +#endif + + return (0); +} + +/** + * @brief Support some spi driver commands for application. + * @param[in] fd is interface number. + * @param[in] cmd is command. + * @param[in] arg0 is the first argument of command. + * @param[in] arg1 is the second argument of command. + * @return command status. + * @retval 0 Success otherwise fail. Fail value could be + * - \ref SPI_ERR_NODEV + * - \ref SPI_ERR_IO + * - \ref SPI_ERR_ARG + */ +int32_t spiIoctl(int32_t fd, uint32_t cmd, uint32_t arg0, uint32_t arg1) +{ + spi_dev *dev; + + if (fd != 0 && fd != 1) + return (SPI_ERR_NODEV); + + dev = (spi_dev *)((uint32_t)&spi_device[fd]); + if (dev->openflag == 0) + return (SPI_ERR_IO); + + switch (cmd) + { + case SPI_IOC_TRIGGER: + dev->intflag = 0; + spi_out(dev, spi_in(dev, CNTRL) | 0x1, CNTRL); + break; + +#if 0 + case SPI_IOC_SET_INTERRUPT: + if (arg0 == SPI_ENABLE_INTERRUPT) + spi_out(dev, spi_in(dev, CNTRL) | (0x1 << 17), CNTRL); + else + spi_out(dev, spi_in(dev, CNTRL) & ~(0x1 << 17), CNTRL); + break; +#endif + + case SPI_IOC_SET_SPEED: + return spiSetSpeed(dev, (uint32_t)arg0); + + case SPI_IOC_SET_DUAL_QUAD_MODE: + if (arg0 == SPI_DISABLE_DUAL_QUAD) + { + spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 21)), CNTRL); + break; + } + + if (arg0 == SPI_DUAL_MODE) + spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 21)) | (0x1 << 22), CNTRL); + else + spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 21)) | (0x1 << 21), CNTRL); + break; + + case SPI_IOC_SET_DUAL_QUAD_DIR: + if (arg0 == SPI_DUAL_QUAD_INPUT) + spi_out(dev, spi_in(dev, CNTRL) & ~(0x1 << 20), CNTRL); + else + spi_out(dev, spi_in(dev, CNTRL) | (0x1 << 20), CNTRL); + break; + + case SPI_IOC_SET_LSB_MSB: + if (arg0 == SPI_MSB) + spi_out(dev, spi_in(dev, CNTRL) & ~(0x1 << 10), CNTRL); + else + spi_out(dev, spi_in(dev, CNTRL) | (0x1 << 10), CNTRL); + break; + + case SPI_IOC_SET_TX_NUM: + if (arg0 < 4) + spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 8)) | (arg0 << 8), CNTRL); + else + return SPI_ERR_ARG; + break; + + case SPI_IOC_SET_TX_BITLEN: + if (arg0 < 32) + spi_out(dev, (spi_in(dev, CNTRL) & ~(0x1f << 3)) | (arg0 << 3), CNTRL); + else + return SPI_ERR_ARG; + break; + + case SPI_IOC_SET_MODE: + if (arg0 > SPI_MODE_3) + return SPI_ERR_ARG; + + if (arg0 == SPI_MODE_0) + spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3 << 1) | (1UL << 31))) | (1 << 2), CNTRL); + else if (arg0 == SPI_MODE_1) + spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3 << 1) | (1UL << 31))) | (1 << 1), CNTRL); + else if (arg0 == SPI_MODE_2) + spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3 << 1) | (1UL << 31))) | ((1UL << 31) | (1 << 2)), CNTRL); + else + spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3 << 1) | (1UL << 31))) | ((1UL << 31) | (1 << 1)), CNTRL); + break; + + case SPI_IOC_ENABLE_SS: + if (arg0 == SPI_SS_SS0) + spi_out(dev, (spi_in(dev, SSR) & ~(0x3)) | 0x1, SSR); + else if (arg0 == SPI_SS_SS1) + spi_out(dev, (spi_in(dev, SSR) & ~(0x3)) | 0x2, SSR); + else if (arg0 == SPI_SS_BOTH) + spi_out(dev, (spi_in(dev, SSR) & ~(0x3)) | 0x3, SSR); + else + return SPI_ERR_ARG; + break; + + case SPI_IOC_DISABLE_SS: + if (arg0 == SPI_SS_SS0) + spi_out(dev, (spi_in(dev, SSR) & ~(0x1)), SSR); + else if (arg0 == SPI_SS_SS1) + spi_out(dev, (spi_in(dev, SSR) & ~(0x2)), SSR); + else if (arg0 == SPI_SS_BOTH) + spi_out(dev, (spi_in(dev, SSR) & ~(0x3)), SSR); + else + return SPI_ERR_ARG; + break; + + case SPI_IOC_SET_AUTOSS: + if (arg0 == SPI_DISABLE_AUTOSS) + spi_out(dev, spi_in(dev, SSR) & ~(0x1 << 3), SSR); + else + spi_out(dev, spi_in(dev, SSR) | (0x1 << 3), SSR); + break; + + case SPI_IOC_SET_SS_ACTIVE_LEVEL: + if (arg0 == SPI_SS_ACTIVE_LOW) + spi_out(dev, spi_in(dev, SSR) & ~(0x1 << 2), SSR); + else + spi_out(dev, spi_in(dev, SSR) | (0x1 << 2), SSR); + default: + break; + } + + return 0; +} + +/** + * @brief Open spi interface and initialize some variables + * @param[in] fd is interface number. + * @return always 0 + * @retval 0 success. + */ +int spiOpen(int32_t fd) +{ + spi_dev *dev; + + if ((uint32_t)fd >= SPI_NUMBER) + return SPI_ERR_NODEV; + + dev = (spi_dev *)((uint32_t)&spi_device[fd]); + + if (dev->openflag != 0) /* a card slot can open only once */ + return (SPI_ERR_BUSY); + + memset(dev, 0, sizeof(spi_dev)); + dev->base = ((uint32_t)fd) ? SPI1_BA : SPI0_BA; + dev->openflag = 1; + dev->intflag = 0; + + return 0; +} + +/** + * @brief Get busy status of spi interface + * @param[in] fd is interface number. + * @return busy or not + * @retval 0 not busy. + * @retval 1 busy. + */ +uint8_t spiGetBusyStatus(int32_t fd) +{ + spi_dev *dev; + + dev = (spi_dev *)((uint32_t)&spi_device[fd]); + + if (spi_in(dev, CNTRL) & (0x1 << 17)) + return (!dev->intflag); + else + return ((spi_in(dev, CNTRL) & 0x1) == 0x1 ? 1 : 0); +} + +/** + * @brief Read data form spi interface + * @param[in] fd is interface number. + * @param[in] buff_id is buffer number. If transfer number is 4, application needs read 4 times (buff_id is from 0 to 3) from buffer. + * @return data + */ +uint32_t spiRead(int32_t fd, uint8_t buff_id) +{ + spi_dev *dev; + + dev = (spi_dev *)((uint32_t)&spi_device[fd]); + return spi_in(dev, (RX0 + 4 * buff_id)); +} + +/** + * @brief Write data to spi interface + * @param[in] fd is interface number. + * @param[in] buff_id is buffer number. If transfer number is 4, application needs write 4 times (buff_id is from 0 to 3) to buffer. + * @param[in] data is data to be written. + * @return none + */ +void spiWrite(int32_t fd, uint8_t buff_id, uint32_t data) +{ + spi_dev *dev; + + dev = (spi_dev *)((uint32_t)&spi_device[fd]); + spi_out(dev, data, (TX0 + 4 * buff_id)); +} + +/*@}*/ /* end of group N9H30_SPI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_SPI_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sys.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sys.c new file mode 100644 index 0000000000..ef3772b025 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sys.c @@ -0,0 +1,675 @@ +/**************************************************************************//** +* @file sys.c +* @brief N9H30 SYS driver source file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include "N9H30.h" +#include "nu_sys.h" + +/// @cond HIDDEN_SYMBOLS + +#define SYS_MIN_INT_SOURCE 1 +#define SYS_MAX_INT_SOURCE 62 +#define SYS_NUM_OF_AICREG 16 + +/* Global variables */ +BOOL volatile _sys_bIsAICInitial = FALSE; + +/* declaration the function prototype */ +extern void SYS_Interrupt_Shell(void); + +/* Interrupt Handler Table */ +//typedef void (*sys_pvFunPtr)(); /* function pointer */ +sys_pvFunPtr sysIrqHandlerTable[] = { 0, /* 0 */ + SYS_Interrupt_Shell, /* 1 */ + SYS_Interrupt_Shell, /* 2 */ + SYS_Interrupt_Shell, /* 3 */ + SYS_Interrupt_Shell, /* 4 */ + SYS_Interrupt_Shell, /* 5 */ + SYS_Interrupt_Shell, /* 6 */ + SYS_Interrupt_Shell, /* 7 */ + SYS_Interrupt_Shell, /* 8 */ + SYS_Interrupt_Shell, /* 9 */ + SYS_Interrupt_Shell, /* 10 */ + SYS_Interrupt_Shell, /* 11 */ + SYS_Interrupt_Shell, /* 12 */ + SYS_Interrupt_Shell, /* 13 */ + SYS_Interrupt_Shell, /* 14 */ + SYS_Interrupt_Shell, /* 15 */ + SYS_Interrupt_Shell, /* 16 */ + SYS_Interrupt_Shell, /* 17 */ + SYS_Interrupt_Shell, /* 18 */ + SYS_Interrupt_Shell, /* 19 */ + SYS_Interrupt_Shell, /* 20 */ + SYS_Interrupt_Shell, /* 21 */ + SYS_Interrupt_Shell, /* 22 */ + SYS_Interrupt_Shell, /* 23 */ + SYS_Interrupt_Shell, /* 24 */ + SYS_Interrupt_Shell, /* 25 */ + SYS_Interrupt_Shell, /* 26 */ + SYS_Interrupt_Shell, /* 27 */ + SYS_Interrupt_Shell, /* 28 */ + SYS_Interrupt_Shell, /* 29 */ + SYS_Interrupt_Shell, /* 30 */ + SYS_Interrupt_Shell, /* 31 */ + SYS_Interrupt_Shell, /* 32 */ + SYS_Interrupt_Shell, /* 33 */ + SYS_Interrupt_Shell, /* 34 */ + SYS_Interrupt_Shell, /* 35 */ + SYS_Interrupt_Shell, /* 36 */ + SYS_Interrupt_Shell, /* 37 */ + SYS_Interrupt_Shell, /* 38 */ + SYS_Interrupt_Shell, /* 39 */ + SYS_Interrupt_Shell, /* 40 */ + SYS_Interrupt_Shell, /* 41 */ + SYS_Interrupt_Shell, /* 42 */ + SYS_Interrupt_Shell, /* 43 */ + SYS_Interrupt_Shell, /* 44 */ + SYS_Interrupt_Shell, /* 45 */ + SYS_Interrupt_Shell, /* 46 */ + SYS_Interrupt_Shell, /* 47 */ + SYS_Interrupt_Shell, /* 48 */ + SYS_Interrupt_Shell, /* 49 */ + SYS_Interrupt_Shell, /* 50 */ + SYS_Interrupt_Shell, /* 51 */ + SYS_Interrupt_Shell, /* 52 */ + SYS_Interrupt_Shell, /* 53 */ + SYS_Interrupt_Shell, /* 54 */ + SYS_Interrupt_Shell, /* 55 */ + SYS_Interrupt_Shell, /* 56 */ + SYS_Interrupt_Shell, /* 57 */ + SYS_Interrupt_Shell, /* 58 */ + SYS_Interrupt_Shell, /* 59 */ + SYS_Interrupt_Shell, /* 60 */ + SYS_Interrupt_Shell /* 61 */ + }; + +sys_pvFunPtr sysFiqHandlerTable[] = { 0, + SYS_Interrupt_Shell, /* 1 */ + SYS_Interrupt_Shell, /* 2 */ + SYS_Interrupt_Shell, /* 3 */ + SYS_Interrupt_Shell, /* 4 */ + SYS_Interrupt_Shell, /* 5 */ + SYS_Interrupt_Shell, /* 6 */ + SYS_Interrupt_Shell, /* 7 */ + SYS_Interrupt_Shell, /* 8 */ + SYS_Interrupt_Shell, /* 9 */ + SYS_Interrupt_Shell, /* 10 */ + SYS_Interrupt_Shell, /* 11 */ + SYS_Interrupt_Shell, /* 12 */ + SYS_Interrupt_Shell, /* 13 */ + SYS_Interrupt_Shell, /* 14 */ + SYS_Interrupt_Shell, /* 15 */ + SYS_Interrupt_Shell, /* 16 */ + SYS_Interrupt_Shell, /* 17 */ + SYS_Interrupt_Shell, /* 18 */ + SYS_Interrupt_Shell, /* 19 */ + SYS_Interrupt_Shell, /* 20 */ + SYS_Interrupt_Shell, /* 21 */ + SYS_Interrupt_Shell, /* 22 */ + SYS_Interrupt_Shell, /* 23 */ + SYS_Interrupt_Shell, /* 24 */ + SYS_Interrupt_Shell, /* 25 */ + SYS_Interrupt_Shell, /* 26 */ + SYS_Interrupt_Shell, /* 27 */ + SYS_Interrupt_Shell, /* 28 */ + SYS_Interrupt_Shell, /* 29 */ + SYS_Interrupt_Shell, /* 30 */ + SYS_Interrupt_Shell, /* 31 */ + SYS_Interrupt_Shell, /* 32 */ + SYS_Interrupt_Shell, /* 33 */ + SYS_Interrupt_Shell, /* 34 */ + SYS_Interrupt_Shell, /* 35 */ + SYS_Interrupt_Shell, /* 36 */ + SYS_Interrupt_Shell, /* 37 */ + SYS_Interrupt_Shell, /* 38 */ + SYS_Interrupt_Shell, /* 39 */ + SYS_Interrupt_Shell, /* 40 */ + SYS_Interrupt_Shell, /* 41 */ + SYS_Interrupt_Shell, /* 42 */ + SYS_Interrupt_Shell, /* 43 */ + SYS_Interrupt_Shell, /* 44 */ + SYS_Interrupt_Shell, /* 45 */ + SYS_Interrupt_Shell, /* 46 */ + SYS_Interrupt_Shell, /* 47 */ + SYS_Interrupt_Shell, /* 48 */ + SYS_Interrupt_Shell, /* 49 */ + SYS_Interrupt_Shell, /* 50 */ + SYS_Interrupt_Shell, /* 51 */ + SYS_Interrupt_Shell, /* 52 */ + SYS_Interrupt_Shell, /* 53 */ + SYS_Interrupt_Shell, /* 54 */ + SYS_Interrupt_Shell, /* 55 */ + SYS_Interrupt_Shell, /* 56 */ + SYS_Interrupt_Shell, /* 57 */ + SYS_Interrupt_Shell, /* 58 */ + SYS_Interrupt_Shell, /* 59 */ + SYS_Interrupt_Shell, /* 60 */ + SYS_Interrupt_Shell /* 61 */ + }; + +/* Interrupt Handler */ +#if defined ( __GNUC__ ) && !(__CC_ARM) + static void __attribute__((interrupt("IRQ"))) sysIrqHandler(void) +#else + __irq void sysIrqHandler() +#endif +{ + UINT32 volatile _mIPER, _mISNR; + + _mIPER = (inpw(REG_AIC_IPER) >> 2) & 0x3f; + _mISNR = inpw(REG_AIC_ISNR); + if (_mIPER != 0) + { + if (_mISNR != 0) + (*sysIrqHandlerTable[_mIPER])(); + outpw(REG_AIC_EOSCR, 1); + } +} + +#if defined ( __GNUC__ ) && !(__CC_ARM) + static void __attribute__((interrupt("FIQ"))) sysFiqHandler(void) +#else + __irq void sysFiqHandler() +#endif +{ + UINT32 volatile _mIPER, _mISNR; + + _mIPER = (inpw(REG_AIC_IPER) >> 2) & 0x3f; + _mISNR = inpw(REG_AIC_ISNR); + if (_mIPER != 0) + { + if (_mISNR != 0) + (*sysFiqHandlerTable[_mIPER])(); + outpw(REG_AIC_EOSCR, 1); + } +} + +void SYS_Interrupt_Shell() +{ + //sysprintf("ISR not found! ISNR=%d\n", inpw(REG_AIC_ISNR)); +} + +void sysInitializeAIC() +{ + *(unsigned int volatile *)0x38 = (unsigned int)sysIrqHandler; + + *(unsigned int volatile *)0x3C = (unsigned int)sysFiqHandler; +} +/// @endcond HIDDEN_SYMBOLS + + +/* Interrupt library functions */ +/** + * @brief system AIC - disable interrupt + * + * @param[in] eIntNo Select interrupt source. \ref IRQn_Type + * + * @return 0 + */ +INT32 sysDisableInterrupt(IRQn_Type eIntNo) +{ + if ((eIntNo > SYS_MAX_INT_SOURCE) || (eIntNo < SYS_MIN_INT_SOURCE)) + return 1; + + if (eIntNo < 32) + outpw(REG_AIC_MDCR, (1 << eIntNo)); + else + outpw(REG_AIC_MDCRH, (1 << (eIntNo - 32))); + + return 0; +} + + +/** + * @brief system AIC - enable interrupt + * + * @param[in] eIntNo Select interrupt source. \ref IRQn_Type + * + * @return 0 + */ +INT32 sysEnableInterrupt(IRQn_Type eIntNo) +{ + if ((eIntNo > SYS_MAX_INT_SOURCE) || (eIntNo < SYS_MIN_INT_SOURCE)) + return 1; + + if (eIntNo < 32) + outpw(REG_AIC_MECR, (1 << eIntNo)); + else + outpw(REG_AIC_MECRH, (1 << (eIntNo - 32))); + + return 0; +} + + +/** + * @brief system AIC - install exception handler + * + * @param[in] nExceptType exception type. ( \ref SYS_SWI / \ref SYS_D_ABORT / \ref SYS_I_ABORT / \ref SYS_UNDEFINE) + * @param[in] pvNewHandler own exception handler + * + * @return old handler + */ +PVOID sysInstallExceptionHandler(INT32 nExceptType, PVOID pvNewHandler) +{ + PVOID _mOldVect = NULL; + + switch (nExceptType) + { + case SYS_SWI: + _mOldVect = *(PVOID volatile *)0x28; + *(PVOID volatile *)0x28 = pvNewHandler; + break; + + case SYS_D_ABORT: + _mOldVect = *(PVOID volatile *)0x30; + *(PVOID volatile *)0x30 = pvNewHandler; + break; + + case SYS_I_ABORT: + _mOldVect = *(PVOID volatile *)0x2C; + *(PVOID volatile *)0x2C = pvNewHandler; + break; + + case SYS_UNDEFINE: + _mOldVect = *(PVOID volatile *)0x24; + *(PVOID volatile *)0x24 = pvNewHandler; + break; + + default: + ; + } + return _mOldVect; +} + +/** + * @brief system AIC - install FIQ handler + * + * @param[in] pvNewISR own fiq handler + * + * @return old handler + */ +PVOID sysInstallFiqHandler(PVOID pvNewISR) +{ + PVOID _mOldVect; + + _mOldVect = *(PVOID volatile *)0x3C; + *(PVOID volatile *)0x3C = pvNewISR; + return _mOldVect; +} + +/** + * @brief system AIC - install IRQ handler + * + * @param[in] pvNewISR own irq handler + * + * @return old handler + */ +PVOID sysInstallIrqHandler(PVOID pvNewISR) +{ + PVOID _mOldVect; + + _mOldVect = *(PVOID volatile *)0x38; + *(PVOID volatile *)0x38 = pvNewISR; + return _mOldVect; +} + + +/** + * @brief system AIC - install Own IRQ service routine + * + * @param[in] nIntTypeLevel Interrupt Level. ( \ref FIQ_LEVEL_0 / \ref IRQ_LEVEL_1 / \ref IRQ_LEVEL_2 / \ref IRQ_LEVEL_3 / + * \ref IRQ_LEVEL_4 / \ref IRQ_LEVEL_5 / \ref IRQ_LEVEL_6 / \ref IRQ_LEVEL_7 ) + * @param[in] eIntNo Interrupt number. \ref IRQn_Type + * @param[in] pvNewISR own irq handler + * + * @return old handler + */ +PVOID sysInstallISR(INT32 nIntTypeLevel, IRQn_Type eIntNo, PVOID pvNewISR) +{ + PVOID _mOldVect; + UINT32 _mRegAddr/*, _mRegValue*/; + INT shift; + + if (!_sys_bIsAICInitial) + { + sysInitializeAIC(); + _sys_bIsAICInitial = TRUE; + } + + _mRegAddr = REG_AIC_SCR1 + ((eIntNo / 4) * 4); + shift = (eIntNo % 4) * 8; + nIntTypeLevel &= 0xff; + outpw(_mRegAddr, (inpw(_mRegAddr) & ~(0x07 << shift)) | (nIntTypeLevel << shift)); + + if ((nIntTypeLevel & 0x7) == FIQ_LEVEL_0) + { + _mOldVect = (PVOID) sysFiqHandlerTable[eIntNo]; + sysFiqHandlerTable[eIntNo] = (sys_pvFunPtr)pvNewISR; + } + else + { + _mOldVect = (PVOID) sysIrqHandlerTable[eIntNo]; + sysIrqHandlerTable[eIntNo] = (sys_pvFunPtr)pvNewISR; + } + return _mOldVect; +} + + +INT32 sysSetGlobalInterrupt(INT32 nIntState) +{ + switch (nIntState) + { + case ENABLE_ALL_INTERRUPTS: + outpw(REG_AIC_MECR, 0xFFFFFFFF); + outpw(REG_AIC_MECRH, 0xFFFFFFFF); + break; + + case DISABLE_ALL_INTERRUPTS: + outpw(REG_AIC_MDCR, 0xFFFFFFFF); + outpw(REG_AIC_MDCRH, 0xFFFFFFFF); + break; + + default: + ; + } + return 0; +} + + +/** + * @brief system AIC - Change interrupt level + * + * @param[in] eIntNo Interrupt number. \ref IRQn_Type + * @param[in] uIntLevel Interrupt Level. ( \ref FIQ_LEVEL_0 / \ref IRQ_LEVEL_1 / \ref IRQ_LEVEL_2 / \ref IRQ_LEVEL_3 / + * \ref IRQ_LEVEL_4 / \ref IRQ_LEVEL_5 / \ref IRQ_LEVEL_6 / \ref IRQ_LEVEL_7 ) + * + * @return 0 + */ +INT32 sysSetInterruptPriorityLevel(IRQn_Type eIntNo, UINT32 uIntLevel) +{ + UINT32 _mRegAddr; + INT shift; + + if ((eIntNo > SYS_MAX_INT_SOURCE) || (eIntNo < SYS_MIN_INT_SOURCE)) + return 1; + + _mRegAddr = REG_AIC_SCR1 + ((eIntNo / 4) * 4); + shift = (eIntNo % 4) * 8; + uIntLevel &= 0x7; + outpw(_mRegAddr, (inpw(_mRegAddr) & ~(0x07 << shift)) | (uIntLevel << shift)); + + return 0; +} + + +INT32 sysSetInterruptType(IRQn_Type eIntNo, UINT32 uIntSourceType) +{ + UINT32 _mRegAddr; + INT shift; + + if ((eIntNo > SYS_MAX_INT_SOURCE) || (eIntNo < SYS_MIN_INT_SOURCE)) + return 1; + + _mRegAddr = REG_AIC_SCR1 + ((eIntNo / 4) * 4); + shift = (eIntNo % 4) * 8; + uIntSourceType &= 0xC0; + outpw(_mRegAddr, (inpw(_mRegAddr) & ~(0xC0 << shift)) | (uIntSourceType << shift)); + + return 0; +} + + +/** + * @brief system AIC - Set CP15 Interrupt Type + * + * @param[in] nIntState Interrupt state. ( \ref ENABLE_IRQ / \ref ENABLE_FIQ / \ref ENABLE_FIQ_IRQ / + * \ref DISABLE_IRQ / \ref DISABLE_FIQ / \ref DISABLE_FIQ_IRQ) + * + * @return 0 + */ +INT32 sysSetLocalInterrupt(INT32 nIntState) +{ +#if defined ( __GNUC__ ) && !(__CC_ARM) + +# else + INT32 temp; +#endif + + switch (nIntState) + { + case ENABLE_IRQ: + case ENABLE_FIQ: + case ENABLE_FIQ_IRQ: +#if defined ( __GNUC__ ) && !(__CC_ARM) + asm + ( + "mrs r0, CPSR \n" + "bic r0, r0, #0x80 \n" + "msr CPSR_c, r0 \n" + ); +#else + __asm + { + MRS temp, CPSR + AND temp, temp, nIntState + MSR CPSR_c, temp + } +#endif + break; + case DISABLE_IRQ: + case DISABLE_FIQ: + case DISABLE_FIQ_IRQ: +#if defined ( __GNUC__ ) && !(__CC_ARM) + asm + ( + "MRS r0, CPSR \n" + "ORR r0, r0, #0x80 \n" + "MSR CPSR_c, r0 \n" + ); +#else + __asm + { + MRS temp, CPSR + ORR temp, temp, nIntState + MSR CPSR_c, temp + } +#endif + break; + + default: + ; + } + return 0; +} + +UINT32 sysGetInterruptEnableStatus(void) +{ + return (inpw(REG_AIC_IMR)); +} + + +UINT32 sysGetInterruptEnableStatusH(void) +{ + return (inpw(REG_AIC_IMRH)); +} + +/// @cond HIDDEN_SYMBOLS +BOOL sysGetIBitState() +{ + INT32 temp; + +#if defined ( __GNUC__ ) && !(__CC_ARM) + asm + ( + "MRS %0, CPSR \n" + :"=r"(temp) : : + ); +#else + __asm + { + MRS temp, CPSR + } +#endif + + if (temp & 0x80) + return FALSE; + else + return TRUE; +} + +INT32 sysGetPLL(UINT32 reg) +{ + UINT32 N, M, P; + + N = ((inpw(reg) & 0x007F) >> 0) + 1; + M = ((inpw(reg) & 0x1F80) >> 7) + 1; + P = ((inpw(reg) & 0xE000) >> 13) + 1; + + return (12 * N / (M * P)); /* 12MHz HXT */ +} +/// @endcond HIDDEN_SYMBOLS + +/** + * @brief system Timer - install WDT interrupt handler + * + * @param[in] clk clock source. \ref CLK_Type + * + * @return MHz + */ +UINT32 sysGetClock(CLK_Type clk) +{ + UINT32 src, divS, divN, reg, div; + + switch (clk) + { + case SYS_UPLL: + return sysGetPLL(REG_CLK_UPLLCON); + + case SYS_APLL: + return sysGetPLL(REG_CLK_APLLCON); + + case SYS_SYSTEM: + { + reg = inpw(REG_CLK_DIVCTL0); + switch (reg & 0x18) + { + case 0x0: + src = 12; /* HXT */ + break; + case 0x10: + src = sysGetPLL(REG_CLK_APLLCON); + break; + case 0x18: + src = sysGetPLL(REG_CLK_UPLLCON); + break; + default: + return 0; + } + divS = (reg & 0x7) + 1; + divN = ((reg & 0xf00) >> 8) + 1; + return (src / divS / divN); + } + + case SYS_HCLK1: + { + reg = inpw(REG_CLK_DIVCTL0); + switch (reg & 0x18) + { + case 0x0: + src = 12; /* HXT */ + break; + case 0x10: + src = sysGetPLL(REG_CLK_APLLCON); + break; + case 0x18: + src = sysGetPLL(REG_CLK_UPLLCON); + break; + default: + return 0; + } + divS = (reg & 0x7) + 1; + divN = ((reg & 0xf00) >> 8) + 1; + return (src / divS / divN / 2); + } + + case SYS_HCLK234: + { + reg = inpw(REG_CLK_DIVCTL0); + switch (reg & 0x18) + { + case 0x0: + src = 12; /* HXT */ + break; + case 0x10: + src = sysGetPLL(REG_CLK_APLLCON); + break; + case 0x18: + src = sysGetPLL(REG_CLK_UPLLCON); + break; + default: + return 0; + } + divS = (reg & 0x7) + 1; + divN = ((reg & 0xf00) >> 8) + 1; + div = ((reg & 0xf00000) >> 20) + 1; + return (src / divS / divN / 2 / div); + } + + case SYS_PCLK: + { + reg = inpw(REG_CLK_DIVCTL0); + switch (reg & 0x18) + { + case 0x0: + src = 12; /* HXT */ + break; + case 0x10: + src = sysGetPLL(REG_CLK_APLLCON); + break; + case 0x18: + src = sysGetPLL(REG_CLK_UPLLCON); + break; + default: + return 0; + } + divS = (reg & 0x7) + 1; + divN = ((reg & 0xf00) >> 8) + 1; + div = ((reg & 0xf000000) >> 24) + 1; + return (src / divS / divN / 2 / div); + } + case SYS_CPU: + { + reg = inpw(REG_CLK_DIVCTL0); + switch (reg & 0x18) + { + case 0x0: + src = 12; /* HXT */ + break; + case 0x10: + src = sysGetPLL(REG_CLK_APLLCON); + break; + case 0x18: + src = sysGetPLL(REG_CLK_UPLLCON); + break; + default: + return 0; + } + divS = (reg & 0x7) + 1; + divN = ((reg & 0xf00) >> 8) + 1; + div = ((reg & 0xf0000) >> 16) + 1; + return (src / divS / divN / div); + } + + default: + ; + } + return 0; +} + + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_timer.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_timer.c new file mode 100644 index 0000000000..a5931660a4 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_timer.c @@ -0,0 +1,146 @@ +/**************************************************************************//** + * @file timer.c + * @brief N9H30 series TIMER driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_timer.h" + +void TIMER_SET_CMP_VALUE(uint32_t timer, uint32_t u32Cmpr) +{ + uint32_t u32TmrCMPROffset; + + u32TmrCMPROffset = REG_TMR0_CMPR + timer * 0x10; + + outpw(u32TmrCMPROffset, u32Cmpr); +} + +void TIMER_SET_OPMODE(uint32_t timer, uint32_t u32OpMode) +{ + uint32_t u32TmrCSROffset; + + u32TmrCSROffset = REG_TMR0_CSR + timer * 0x10; + + outpw(u32TmrCSROffset, (inpw(u32TmrCSROffset) & ~(0x3UL << 27)) | u32OpMode); +} + +void TIMER_SET_PRESCALE_VALUE(uint32_t timer, uint32_t u32PreScale) +{ + uint32_t u32TmrCSROffset; + + u32TmrCSROffset = REG_TMR0_CSR + timer * 0x10; + + outpw(u32TmrCSROffset, (inpw(u32TmrCSROffset) & ~(0xFFUL)) | u32PreScale); +} + +uint32_t TIMER_GetModuleClock(uint32_t timer) +{ + return 12000000; +} + +void TIMER_Start(uint32_t timer) +{ + uint32_t u32TmrCSROffset; + + u32TmrCSROffset = REG_TMR0_CSR + timer * 0x10; + + outpw(u32TmrCSROffset, inpw(u32TmrCSROffset) | TIMER_COUNTER_ENABLE); +} + +void TIMER_Stop(uint32_t timer) +{ + uint32_t u32TmrCSROffset; + + u32TmrCSROffset = REG_TMR0_CSR + timer * 0x10; + + outpw(u32TmrCSROffset, inpw(u32TmrCSROffset) & ~TIMER_COUNTER_ENABLE); +} + +void TIMER_ClearCounter(uint32_t timer) +{ + uint32_t u32TmrCSROffset; + + u32TmrCSROffset = REG_TMR0_CSR + timer * 0x10; + + outpw(u32TmrCSROffset, inpw(u32TmrCSROffset) | TIMER_COUNTER_RESET); +} + +uint32_t TIMER_GetCounter(uint32_t timer) +{ + uint32_t u32TmrDROffset; + + u32TmrDROffset = REG_TMR0_DR + timer * 0x10; + + return inpw(u32TmrDROffset); +} + +uint32_t TIMER_GetCompareData(uint32_t timer) +{ + uint32_t u32TmrCMPROffset; + + u32TmrCMPROffset = REG_TMR0_CMPR + timer * 0x10; + + return inpw(u32TmrCMPROffset); +} + +void TIMER_EnableInt(uint32_t timer) +{ + uint32_t u32TmrCSROffset; + + u32TmrCSROffset = REG_TMR0_CSR + timer * 0x10; + + outpw(u32TmrCSROffset, inpw(u32TmrCSROffset) | TIMER_INTERRUPT_ENABLE); +} + +void TIMER_DisableInt(uint32_t timer) +{ + uint32_t u32TmrCSROffset; + + u32TmrCSROffset = REG_TMR0_CSR + timer * 0x10; + + outpw(u32TmrCSROffset, inpw(u32TmrCSROffset) & ~TIMER_INTERRUPT_ENABLE); +} + +void TIMER_Close(uint32_t timer) +{ + uint32_t u32TmrCSROffset; + + u32TmrCSROffset = REG_TMR0_CSR + timer * 0x10; + + outpw(u32TmrCSROffset, 0); +} + +uint32_t TIMER_Open(uint32_t timer, uint32_t u32Mode, uint32_t u32Freq) +{ + uint32_t u32Clk = TIMER_GetModuleClock(timer); + uint32_t u32Cmpr = 0, u32Prescale = 0; + uint32_t u32TmrOffset = 0; + + // Fastest possible timer working freq is u32Clk / 2. While cmpr = 2, pre-scale = 0 + if (u32Freq > (u32Clk / 2)) + { + u32Cmpr = 2; + } + else + { + /* Clock source is only XIN. */ + u32Cmpr = u32Clk / u32Freq; + } + + u32TmrOffset = timer * 0x10; + + TIMER_Close(timer); /* disable timer */ + TIMER_DisableInt(timer); /* clear for safety */ + + outpw(REG_TMR0_CMPR + u32TmrOffset, u32Cmpr); + outpw(REG_TMR0_CSR + u32TmrOffset, u32Mode | u32Prescale); + + return (u32Clk / (u32Cmpr * (u32Prescale + 1))); +} + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_uart.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_uart.c new file mode 100644 index 0000000000..9122b80d63 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_uart.c @@ -0,0 +1,2200 @@ +/**************************************************************************//** +* @file uart.c +* @version V1.00 +* @brief N9H30 UART driver source file +* +* SPDX-License-Identifier: Apache-2.0 +* @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#if 0 +#include +#include +#include +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_uart.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_UART_Driver UART Driver + @{ +*/ + +/** @addtogroup N9H30_UART_EXPORTED_CONSTANTS UART Exported Constants + @{ +*/ + +/*@}*/ /* end of group N9H30_UART_EXPORTED_CONSTANTS */ + +/// @cond HIDDEN_SYMBOLS + +/*-----------------------------------------*/ +/* marco, type and constant definitions */ +/*-----------------------------------------*/ +/* + Define debug level +*/ +//#define UART_DEBUG +//#define UART_FLOWCONTROL_DEBUG +//#define UART1_DEBUG +//#define UART2_DEBUG + +#ifdef UART_DEBUG + #define UDEBUG sysprintf +#else + #define UDEBUG(...) +#endif /* UART_DEBUG */ + +#ifdef UART_FLOWCONTROL_DEBUG + #define FDEBUG sysprintf +#else + #define FDEBUG(...) +#endif /* UART_FLOWCONTROL_DEBUG */ + +#ifdef UART1_DEBUG + #define U1DEBUG sysprintf +#else + #define U1DEBUG(...) +#endif /* UART1_DEBUG */ + +#ifdef UART2_DEBUG + #define U2DEBUG sysprintf +#else + #define U2DEBUG(...) +#endif /* UART1_DEBUG */ + +/*-----------------------------------------*/ +/* global file scope (static) variables */ +/*-----------------------------------------*/ +static UART_BUFFER_T UART_DEV[UART_NUM]; + +static UINT32 UARTTXBUFSIZE[UART_NUM] = {500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500}; /* UART0~10 Tx buffer size */ +static UINT32 UARTRXBUFSIZE[UART_NUM] = {500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500}; /* UART0~10 Rx buffer size */ + + +/* + UART flag declarations. +*/ +static volatile CHAR _uart_cDSRState0 = 0; /* set 1, state change */ +static volatile CHAR _uart_cDSRState1 = 0; /* set 1, state change */ +static volatile CHAR _uart_cDSRState2 = 0; /* set 1, state change */ +static volatile CHAR _uart_cDSRState3 = 0; /* set 1, state change */ +static volatile CHAR _uart_cDSRState4 = 0; /* set 1, state change */ +static volatile CHAR _uart_cDSRState5 = 0; /* set 1, state change */ +static volatile CHAR _uart_cDSRState6 = 0; /* set 1, state change */ +static volatile CHAR _uart_cDSRState7 = 0; /* set 1, state change */ +static volatile CHAR _uart_cDSRState8 = 0; /* set 1, state change */ +static volatile CHAR _uart_cDSRState9 = 0; /* set 1, state change */ +static volatile CHAR _uart_cDSRState10 = 0; /* set 1, state change */ +static volatile CHAR _uart_cBIIState_0 = 0; /* set 1, UART channel 0 break interrupt occur */ +static volatile CHAR _uart_cBIIState_1 = 0; /* set 1, UART channel 1 break interrupt occur */ +static volatile CHAR _uart_cBIIState_2 = 0; /* set 1, UART channel 2 break interrupt occur */ +static volatile CHAR _uart_cBIIState_3 = 0; /* set 1, UART channel 3 break interrupt occur */ +static volatile CHAR _uart_cBIIState_4 = 0; /* set 1, UART channel 4 break interrupt occur */ +static volatile CHAR _uart_cBIIState_5 = 0; /* set 1, UART channel 0 break interrupt occur */ +static volatile CHAR _uart_cBIIState_6 = 0; /* set 1, UART channel 1 break interrupt occur */ +static volatile CHAR _uart_cBIIState_7 = 0; /* set 1, UART channel 2 break interrupt occur */ +static volatile CHAR _uart_cBIIState_8 = 0; /* set 1, UART channel 3 break interrupt occur */ +static volatile CHAR _uart_cBIIState_9 = 0; /* set 1, UART channel 4 break interrupt occur */ +static volatile CHAR _uart_cBIIState_10 = 0; /* set 1, UART channel 4 break interrupt occur */ +static volatile CHAR _uart_cCTSState0 = 0; /* set 1, state change */ +static volatile CHAR _uart_cCTSState1 = 0; /* set 1, state change */ +static volatile CHAR _uart_cCTSState2 = 0; /* set 1, state change */ +static volatile CHAR _uart_cCTSState3 = 0; /* set 1, state change */ +static volatile CHAR _uart_cCTSState4 = 0; /* set 1, state change */ +static volatile CHAR _uart_cCTSState5 = 0; /* set 1, state change */ +static volatile CHAR _uart_cCTSState6 = 0; /* set 1, state change */ +static volatile CHAR _uart_cCTSState7 = 0; /* set 1, state change */ +static volatile CHAR _uart_cCTSState8 = 0; /* set 1, state change */ +static volatile CHAR _uart_cCTSState9 = 0; /* set 1, state change */ +static volatile CHAR _uart_cCTSState10 = 0; /* set 1, state change */ + +/* + Define flow control flags & parameters. +*/ +#define HWFLOWCONTROL 1 +#define SWFLOWCONTROL 2 +static volatile CHAR _uart_cFlowControlMode = 0; /* default no flow control */ +static volatile CHAR _uart_cHWTXStopped = 0; /* Use for H/W flow control. Set 1, stop TX. Set 0, start TX. */ +static volatile CHAR _uart_cHWRXStopped = 0; /* Use for H/W flow control. Set 1, stop RX. Set 0, start RX. */ +static volatile CHAR _uart_cSWTXStopped = 0; /* Use for S/W flow control. Set 1, rec Xoff. Set 0, rec Xon. */ +static volatile CHAR _uart_cSWRXStopped = 0; /* Use for S/W flow control. Set 1, send Xoff. Set 0, send Xon. */ +//static INT _uart_nMaxRxBuf = 0; /* used in uartReceiveChars() */ +//static INT _uart_nMinRxBuf = 0; /* used in uartReadRxBuf() */ + + +/*-----------------------------------------*/ +/* prototypes of static functions */ +/*-----------------------------------------*/ +static UINT32 _uartTxBufGetNextOne(INT nNum, UINT32 uPointer); +static UINT32 _uartRxBufGetNextOne(INT nNum, UINT32 uPointer); +static void _uartEnableInterrupt(INT nNum, UINT32 uVal); +static void _uartDisableInterrupt(INT nNum, UINT32 uVal); +static void _uartReceiveChars(INT nNum); +static void _uartTransmitChars(INT nNum); +static void _uartCheckModemStatus(INT nNum); +static INT _uartSetBaudRate(INT nNum, UART_T *val); +static void _uartInstallISR(UINT8 ucNum); +static BOOL _uartBUFSpaceAlloc(INT nNum); +static BOOL _uartCheckTxBufSpace(INT nNum, UINT32 uHead, UINT32 uTail, UINT32 uLen); +static INT32 _uartReadRxBuf(INT nNum, PUINT8 pucBuf, UINT32 uLen); +static void _uartWriteTxBuf(INT nNum, PUINT8 pucBuf, UINT32 uLen); +static INT _uartConfigureUART(PVOID pvParam); +static INT _uartPerformIrDA(INT nNum, UINT32 uCmd, UINT32 uCmd1); +static INT _uartGetRegisterValue(INT nNum, PVOID pvReg); + + +void RS485_HANDLE(INT nNum) +{ + UINT32 volatile uRegISR, uRegFSR, uRegALT_CSR; + + uRegISR = inpw(REG_UART0_ISR + (nNum * UARTOFFSET)); + uRegFSR = inpw(REG_UART0_FSR + (nNum * UARTOFFSET)); + + if ((uRegISR & UART_ISR_RLS_IF_Msk) && (uRegISR & UART_ISR_RDA_IF_Msk)) /* RLS INT & RDA INT */ //For RS485 Detect Address + { + if (uRegFSR & UART_FSR_RS485_ADD_DETF_Msk) /* ADD_IF, RS485 mode */ + { + _uartReceiveChars(nNum); + outpw((REG_UART0_FSR + (nNum * UARTOFFSET)), UART_FSR_RS485_ADD_DETF_Msk); /* clear ADD_IF flag */ + } + } + else if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) /* Rx Ready or Time-out INT*/ + { + /* Handle received data */ + _uartReceiveChars(nNum); + } + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART0_FSR + (nNum * UARTOFFSET)); + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_0 = 1; + } +} + +void uart0ISR(void) +{ + UINT32 volatile uRegISR, uRegFSR; + + uRegISR = inpw(REG_UART0_ISR) & 0xff; + + if (uRegISR & UART_ISR_THRE_IF_Msk) /* TX empty interrupt, check LSR 4 kinds of error further */ + _uartTransmitChars(UART0); + + if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) /* Received Data Available interrupt */ + _uartReceiveChars(UART0); + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART0_FSR); + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_0 = 1; + } + +} + +void uart1ISR(void) +{ + UINT32 volatile uRegISR, uRegFSR, uRegMSR, uRegFUN_SEL; + + uRegISR = inpw(REG_UART1_ISR) & 0xff; + uRegFUN_SEL = inpw(REG_UART1_FUN_SEL); + + if (uRegISR & UART_ISR_THRE_IF_Msk) /* TX empty interrupt, check LSR 4 kinds of error further */ + _uartTransmitChars(UART1); + + if (uRegFUN_SEL == 0x3) + { + RS485_HANDLE(UART1); + } + else + { + if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) /* Received Data Available interrupt */ + _uartReceiveChars(UART1); + + if (uRegISR & UART_ISR_MODEM_IF_Msk) + { + if (_uart_cFlowControlMode == 0) + { + uRegMSR = inpw(REG_UART1_MSR); + + if (uRegMSR & 0x01) + _uart_cCTSState1 = 1; + } + else + _uartCheckModemStatus(UART1); /* H/W flow control */ + } + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART1_FSR); + U1DEBUG("U1 Irpt_RLS [0x%x]!\n", uRegFSR); + + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_1 = 1; + + if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + U1DEBUG("U1 OEI!\n"); + } + } +} + +void uart2ISR(void) +{ + UINT32 volatile uRegISR, uRegFSR, uRegMSR, uRegFUN_SEL; + + uRegISR = inpw(REG_UART2_ISR) & 0xff; + uRegFUN_SEL = inpw(REG_UART2_FUN_SEL); + + if (uRegISR & UART_ISR_THRE_IF_Msk) /* TX empty interrupt, check LSR 4 kinds of error further */ + _uartTransmitChars(UART2); + + if (uRegFUN_SEL == 0x3) + { + RS485_HANDLE(UART2); + } + else + { + if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) /* Received Data Available interrupt */ + _uartReceiveChars(UART2); + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART2_FSR); + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_2 = 1; + } + + if (uRegISR & UART_ISR_MODEM_IF_Msk) + { + if (_uart_cFlowControlMode == 0) + { + uRegMSR = inpw(REG_UART2_MSR); + + if (uRegMSR & 0x01) + _uart_cCTSState2 = 1; + } + else + _uartCheckModemStatus(UART2); /* H/W flow control */ + } + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART2_FSR); + U1DEBUG("U2 Irpt_RLS [0x%x]!\n", uRegFSR); + + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_2 = 1; + + if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + U1DEBUG("U2 OEI!\n"); + } + } +} + +void uart3ISR(void) +{ + UINT32 volatile uRegISR, uRegFSR, uRegMSR, uRegFUN_SEL; + + uRegISR = inpw(REG_UART3_ISR) & 0xff; + uRegFUN_SEL = inpw(REG_UART3_FUN_SEL); + + if (uRegISR & UART_ISR_THRE_IF_Msk) /* TX empty interrupt, check LSR 4 kinds of error further */ + _uartTransmitChars(UART3); + + if (uRegFUN_SEL == 0x3) + { + RS485_HANDLE(UART3); + } + else + { + if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) + _uartReceiveChars(UART3); + + if (uRegISR & UART_ISR_MODEM_IF_Msk) + { + if (_uart_cFlowControlMode == 0) + { + uRegMSR = inpw(REG_UART3_MSR); + + if (uRegMSR & 0x01) + _uart_cCTSState3 = 1; + } + else + _uartCheckModemStatus(UART3); /* H/W flow control */ + } + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART3_FSR); + U1DEBUG("U3 Irpt_RLS [0x%x]!\n", uRegFSR); + + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_3 = 1; + + if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + U1DEBUG("U3 OEI!\n"); + } + } + +} + +void uart4ISR(void) +{ + UINT32 volatile uRegISR, uRegFSR, uRegMSR, uRegFUN_SEL; + + uRegISR = inpw(REG_UART4_ISR) & 0xff; + uRegFUN_SEL = inpw(REG_UART4_FUN_SEL); + + if (uRegISR & UART_ISR_THRE_IF_Msk) /* TX empty interrupt, check LSR 4 kinds of error further */ + _uartTransmitChars(UART4); + + if (uRegFUN_SEL == 0x3) + { + RS485_HANDLE(UART4); + } + else + { + if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) /* Received Data Available interrupt */ + _uartReceiveChars(UART4); + + if (uRegISR & UART_ISR_MODEM_IF_Msk) + { + if (_uart_cFlowControlMode == 0) + { + uRegMSR = inpw(REG_UART4_MSR); + + if (uRegMSR & 0x01) + _uart_cCTSState4 = 1; + } + else + _uartCheckModemStatus(UART4); /* H/W flow control */ + } + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART4_FSR); + U1DEBUG("U4 Irpt_RLS [0x%x]!\n", uRegFSR); + + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_4 = 1; + + if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + U1DEBUG("U4 OEI!\n"); + } + } + +} + +void uart5ISR(void) +{ + UINT32 volatile uRegISR, uRegFSR, uRegMSR, uRegFUN_SEL; + + uRegISR = inpw(REG_UART5_ISR) & 0xff; + uRegFUN_SEL = inpw(REG_UART5_FUN_SEL); + + if (uRegISR & UART_ISR_THRE_IF_Msk) /* TX empty interrupt, check LSR 4 kinds of error further */ + _uartTransmitChars(UART5); + + if (uRegFUN_SEL == 0x3) + { + RS485_HANDLE(UART5); + } + else + { + if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) /* Received Data Available interrupt */ + _uartReceiveChars(UART5); + + if (uRegISR & UART_ISR_MODEM_IF_Msk) + { + if (_uart_cFlowControlMode == 0) + { + uRegMSR = inpw(REG_UART5_MSR); + + if (uRegMSR & 0x01) + _uart_cCTSState5 = 1; + } + else + _uartCheckModemStatus(UART5); /* H/W flow control */ + } + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART5_FSR); + U1DEBUG("U5 Irpt_RLS [0x%x]!\n", uRegFSR); + + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_5 = 1; + + if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + U1DEBUG("U5 OEI!\n"); + } + } + +} + +void uart6ISR(void) +{ + UINT32 volatile uRegISR, uRegFSR, uRegMSR, uRegFUN_SEL; + + uRegISR = inpw(REG_UART6_ISR) & 0xff; + uRegFUN_SEL = inpw(REG_UART6_FUN_SEL); + + if (uRegISR & UART_ISR_THRE_IF_Msk) /* TX empty interrupt, check LSR 4 kinds of error further */ + _uartTransmitChars(UART6); + + if (uRegFUN_SEL == 0x3) + { + RS485_HANDLE(UART6); + } + else + { + if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) /* Received Data Available interrupt */ + _uartReceiveChars(UART6); + + if (uRegISR & UART_ISR_MODEM_IF_Msk) + { + if (_uart_cFlowControlMode == 0) + { + uRegMSR = inpw(REG_UART6_MSR); + + if (uRegMSR & 0x01) + _uart_cCTSState6 = 1; + } + else + _uartCheckModemStatus(UART6); /* H/W flow control */ + } + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART6_FSR); + U1DEBUG("U6 Irpt_RLS [0x%x]!\n", uRegFSR); + + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_6 = 1; + + if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + U1DEBUG("U6 OEI!\n"); + } + } + +} + +void uart7ISR(void) +{ + UINT32 volatile uRegISR, uRegFSR, uRegMSR, uRegFUN_SEL; + + uRegISR = inpw(REG_UART7_ISR) & 0xff; + uRegFUN_SEL = inpw(REG_UART7_FUN_SEL); + + if (uRegISR & UART_ISR_THRE_IF_Msk) /* TX empty interrupt, check LSR 4 kinds of error further */ + _uartTransmitChars(UART7); + + if (uRegFUN_SEL == 0x3) + { + RS485_HANDLE(UART7); + } + else + { + if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) /* Received Data Available interrupt */ + _uartReceiveChars(UART7); + + if (uRegISR & UART_ISR_MODEM_IF_Msk) + { + if (_uart_cFlowControlMode == 0) + { + uRegMSR = inpw(REG_UART7_MSR); + + if (uRegMSR & 0x01) + _uart_cCTSState7 = 1; + } + else + _uartCheckModemStatus(UART7); /* H/W flow control */ + } + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART7_FSR); + U1DEBUG("U7 Irpt_RLS [0x%x]!\n", uRegFSR); + + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_7 = 1; + + if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + U1DEBUG("U7 OEI!\n"); + } + } + +} + +void uart8ISR(void) +{ + UINT32 volatile uRegISR, uRegFSR, uRegMSR, uRegFUN_SEL; + + uRegISR = inpw(REG_UART8_ISR) & 0xff; + uRegFUN_SEL = inpw(REG_UART8_FUN_SEL); + + if (uRegISR & UART_ISR_THRE_IF_Msk) /* TX empty interrupt, check LSR 4 kinds of error further */ + _uartTransmitChars(UART8); + + if (uRegFUN_SEL == 0x3) + { + RS485_HANDLE(UART8); + } + else + { + if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) /* Received Data Available interrupt */ + _uartReceiveChars(UART8); + + if (uRegISR & UART_ISR_MODEM_IF_Msk) + { + if (_uart_cFlowControlMode == 0) + { + uRegMSR = inpw(REG_UART8_MSR); + + if (uRegMSR & 0x01) + _uart_cCTSState8 = 1; + } + else + _uartCheckModemStatus(UART8); /* H/W flow control */ + } + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART8_FSR); + U1DEBUG("U8 Irpt_RLS [0x%x]!\n", uRegFSR); + + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_8 = 1; + + if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + U1DEBUG("U8 OEI!\n"); + } + } + +} + +void uart9ISR(void) +{ + UINT32 volatile uRegISR, uRegFSR, uRegMSR, uRegFUN_SEL; + + uRegISR = inpw(REG_UART9_ISR) & 0xff; + uRegFUN_SEL = inpw(REG_UART9_FUN_SEL); + + if (uRegISR & UART_ISR_THRE_IF_Msk) /* TX empty interrupt, check LSR 4 kinds of error further */ + _uartTransmitChars(UART9); + + if (uRegFUN_SEL == 0x3) + { + RS485_HANDLE(UART9); + } + else + { + if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) /* Received Data Available interrupt */ + _uartReceiveChars(UART9); + + if (uRegISR & UART_ISR_MODEM_IF_Msk) + { + if (_uart_cFlowControlMode == 0) + { + uRegMSR = inpw(REG_UART9_MSR); + + if (uRegMSR & 0x01) + _uart_cCTSState9 = 1; + } + else + _uartCheckModemStatus(UART9); /* H/W flow control */ + } + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UART9_FSR); + U1DEBUG("U9 Irpt_RLS [0x%x]!\n", uRegFSR); + + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_9 = 1; + + if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + U1DEBUG("U9 OEI!\n"); + } + } + +} + +void uart10ISR(void) +{ + UINT32 volatile uRegISR, uRegFSR, uRegMSR, uRegFUN_SEL; + + uRegISR = inpw(REG_UARTA_ISR) & 0xff; + uRegFUN_SEL = inpw(REG_UARTA_FUN_SEL); + + if (uRegISR & UART_ISR_THRE_IF_Msk) /* TX empty interrupt, check LSR 4 kinds of error further */ + _uartTransmitChars(UARTA); + + if (uRegFUN_SEL == 0x3) + { + RS485_HANDLE(UARTA); + } + else + { + if (uRegISR & (UART_ISR_RDA_IF_Msk | UART_ISR_TOUT_IF_Msk)) /* Received Data Available interrupt */ + _uartReceiveChars(UARTA); + + if (uRegISR & UART_ISR_MODEM_IF_Msk) + { + if (_uart_cFlowControlMode == 0) + { + uRegMSR = inpw(REG_UARTA_MSR); + + if (uRegMSR & 0x01) + _uart_cCTSState10 = 1; + } + else + _uartCheckModemStatus(UARTA); /* H/W flow control */ + } + + if (uRegISR & UART_ISR_RLS_IF_Msk) + { + uRegFSR = inpw(REG_UARTA_FSR); + U1DEBUG("U10 Irpt_RLS [0x%x]!\n", uRegFSR); + + if (uRegFSR & UART_FSR_BIF_Msk) + _uart_cBIIState_10 = 1; + + if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + U1DEBUG("U10 OEI!\n"); + } + } + +} + +static UINT32 _uartTxBufGetNextOne(INT nNum, UINT32 uPointer) +{ + if ((uPointer + 1) == UARTTXBUFSIZE[nNum]) + return (UINT32)NULL; + else + return (uPointer + 1); +} + +static UINT32 _uartRxBufGetNextOne(INT nNum, UINT32 uPointer) +{ + if ((uPointer + 1) == UARTRXBUFSIZE[nNum]) + return (UINT32)NULL; + else + return (uPointer + 1); +} + +static void _uartEnableInterrupt(INT nNum, UINT32 uVal) +{ + UINT32 uReg = 0; + + uReg = inpw(REG_UART0_IER + (nNum * UARTOFFSET)); + uReg |= uVal; + outpw(REG_UART0_IER + (nNum * UARTOFFSET), uReg); +} + +static void _uartDisableInterrupt(INT nNum, UINT32 uVal) +{ + UINT32 uReg = 0; + + if (uVal == DISABLEALLIER) + outpw(REG_UART0_IER + (nNum * UARTOFFSET), 0); + else + { + uReg = inpw(REG_UART0_IER + (nNum * UARTOFFSET)); + uReg &= ~uVal; + outpw(REG_UART0_IER + (nNum * UARTOFFSET), uReg); + } +} + +static void _uartReceiveChars(INT nNum) +{ + //UINT32 volatile uRegLSR, uBuf = 0; + UINT32 volatile uRegFSR, uRegALT_CSR, uRegFUN_SEL, uRegFCR, uRegLINSR, uRegISR; + UINT32 volatile uBuf = 0; + UINT32 volatile uOffset = nNum * UARTOFFSET; + INT nMaxCount = 256; + UCHAR ucChar; + + UART_BUFFER_T *dev; + + dev = (UART_BUFFER_T *) &UART_DEV[nNum]; + + //uRegFSR = inpw(REG_UART0_FSR+(nNum * UARTOFFSET)); + uRegFUN_SEL = inpw(REG_UART0_FUN_SEL + uOffset); + + do + { + uRegFSR = inpw(REG_UART0_FSR + uOffset); + uRegLINSR = inpw(REG_UART0_LIN_SR + uOffset); + uRegISR = inpw(REG_UART0_ISR + uOffset); + ucChar = inpb(REG_UART0_RBR + uOffset); + + if ((uRegFSR & UART_FSR_RS485_ADD_DETF_Msk) && (uRegFUN_SEL == 0x3)) + { + uRegALT_CSR = inpw(REG_UART0_ALT_CSR + (nNum * UARTOFFSET)); + uRegFCR = inpw(REG_UART0_FCR + (nNum * UARTOFFSET)); + if (uRegALT_CSR & UART_ALT_CSR_RS485_NMM_Msk) + { + if (ucChar == (uRegALT_CSR >> UART_ALT_CSR_ADDR_MATCH_Pos)) + { + uRegFCR &= ~UART_FCR_RX_DIS_Msk; /* Enable RS485 RX */ + outpw((REG_UART0_FCR + (nNum * UARTOFFSET)), uRegFCR); + } + else + { + uRegFCR |= UART_FCR_RX_DIS_Msk; /* Disable RS485 RX */ + uRegFCR |= UART_FCR_RFR_Msk; /* Clear data from RX FIFO */ + outpw((REG_UART0_FCR + (nNum * UARTOFFSET)), uRegFCR); + break; + } + } + } + + + uBuf = _uartRxBufGetNextOne(nNum, dev->uUartRxTail); + if (uBuf == dev->uUartRxHead) /* Rx buffer full */ + { + //ucChar = inpb(REG_UART0_RBR+(nNum * UARTOFFSET)); + + if (_uart_cHWRXStopped) + U1DEBUG("[%d] buf full!\n", nNum); + + break; + } + + //ucChar = inpb(REG_UART0_RBR+(nNum * UARTOFFSET)); + + dev->pucUartRxBuf[dev->uUartRxTail] = ucChar; + + /* Check LSR for BII, FEI, PEI, OEI */ + dev->pucUARTFlag[dev->uUartRxTail] = 0; + + if (uRegFSR & UART_FSR_BIF_Msk) + { + dev->pucUARTFlag[dev->uUartRxTail] = UART_FSR_BIF_Msk; + U1DEBUG("BIF!\n"); + } + else if (uRegFSR & UART_FSR_FEF_Msk) + { + dev->pucUARTFlag[dev->uUartRxTail] = UART_FSR_FEF_Msk; + U1DEBUG("FEF!\n"); + } + else if (uRegFSR & UART_FSR_PEF_Msk) + { + dev->pucUARTFlag[dev->uUartRxTail] = UART_FSR_PEF_Msk; + U1DEBUG("PEF!\n"); + } + else if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + { + dev->pucUARTFlag[dev->uUartRxTail] = UART_FSR_RX_OVER_IF_Msk; + U1DEBUG("OVER_IF!\n"); + } + else if (uRegFSR & UART_FSR_RS485_ADD_DETF_Msk) + { + dev->pucUARTFlag[dev->uUartRxTail] = UART_FSR_RS485_ADD_DETF_Msk; + U1DEBUG("RS485_ADD_DET_IF!\n"); + } + + if (uRegFUN_SEL == 0x1) + { + if (uRegISR & UART_ISR_LIN_RX_BREAK_IF_Msk) + { + dev->pucLINFlag[dev->uUartRxTail] = uRegLINSR; + + // Clear ISR and LIN Status + outpw(REG_UART0_ISR, UART_ISR_LIN_RX_BREAK_IF_Msk); + outpw(REG_UART0_LIN_SR, 0x30F); + } + } + + dev->uUartRxTail = _uartRxBufGetNextOne(nNum, dev->uUartRxTail); + + /* overrun error is special case, H/W ignore the character */ + if (uRegFSR & UART_FSR_RX_OVER_IF_Msk) + { + dev->pucUARTFlag[dev->uUartRxTail] = UART_FSR_RX_OVER_IF_Msk; + dev->uUartRxTail = _uartRxBufGetNextOne(nNum, dev->uUartRxTail); + } + + uRegFSR = inpw(REG_UART0_FSR + (nNum * UARTOFFSET)); + } + while ((!(uRegFSR & UART_FSR_RX_EMPTY_Msk)) && (nMaxCount-- > 0)); + +} + +static void _uartTransmitChars(INT nNum) +{ + UINT32 volatile i; + + UART_BUFFER_T *dev; + + dev = (UART_BUFFER_T *) &UART_DEV[nNum]; + + if (dev->uUartTxHead != dev->uUartTxTail) /* buffer is not empty */ + { + for (i = 0; i < 8; i++) + { + outpw(REG_UART0_THR + (nNum * UARTOFFSET), dev->pucUartTxBuf[dev->uUartTxHead]); + dev->uUartTxHead = _uartTxBufGetNextOne(nNum, dev->uUartTxHead); + + if (dev->uUartTxHead == dev->uUartTxTail) /* buffer empty */ + { + _uartDisableInterrupt(nNum, UART_IER_THRE_IEN_Msk); + break; + } + } + } +} + +/* + Call by uart1ISR(). +*/ +static void _uartCheckModemStatus(INT nNum) +{ + UINT32 volatile uRegMSR; + UINT32 uOffset = nNum * UARTOFFSET; + + UART_BUFFER_T *dev; + + dev = (UART_BUFFER_T *) &UART_DEV[nNum]; + + FDEBUG("\n Modem INT\n"); + uRegMSR = inpw(REG_UART0_MSR + uOffset); + if (_uart_cHWTXStopped) + { + if (!(uRegMSR & 0x10)) /* CTS high, external signal is low */ + { + _uart_cHWTXStopped = 0; + FDEBUG("H/W flow control ...\n"); + + /* 2007.11.12 modify, PT23 HHWu */ + if (dev->uUartTxHead != dev->uUartTxTail) /* buffer is not empty */ + { + _uartEnableInterrupt(nNum, UART_IER_THRE_IEN_Msk); /* enable TX empty interrupt */ + FDEBUG("buf not empty, TX continued\n"); + } + } + } + else + { + if (!(uRegMSR & 0x10)) /* CTS low, external signal is high */ + { + _uart_cHWTXStopped = 1; + _uartDisableInterrupt(nNum, UART_IER_THRE_IEN_Msk); /* disable TX empty interrupt */ + FDEBUG("H/W flow control, TX stopped\n"); + } + } +} + +static INT _uartSetBaudRate(INT nNum, UART_T *val) +{ + UINT32 u32Reg; + UINT32 uOffset = nNum * UARTOFFSET; + UINT32 u32Baud_Div; + UINT32 u32Clk = val->uFreq; + UINT32 u32baudrate = val->uBaudRate; + + //if (val->uFreq > 200000000) /* Max frequency 200MHz */ + // return -1; + + u32Baud_Div = UART_BAUD_MODE2_DIVIDER(u32Clk, u32baudrate); + + if (u32Baud_Div > 0xFFFF) + u32Reg = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER(u32Clk, u32baudrate)); + else + u32Reg = (UART_BAUD_MODE2 | u32Baud_Div); + + outpw(REG_UART0_BAUD + uOffset, u32Reg); + + return 0; +} + +static void _uartInstallISR(UINT8 ucNum) +{ + UART_BUFFER_T *dev; + + IRQn_Type IRQ; + + dev = (UART_BUFFER_T *) &UART_DEV[ucNum]; + + if (ucNum == UART0) + { + IRQ = UART0_IRQn; + dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)uart0ISR); + } + else if (ucNum == UART1) + { + IRQ = UART1_IRQn; + dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)uart1ISR); + } + else if (ucNum == UART2) + { + IRQ = UART2_IRQn; + dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)uart2ISR); + } + else if (ucNum == UART3) + { + IRQ = UART3_IRQn; + dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)uart3ISR); + } + else if (ucNum == UART4) + { + IRQ = UART4_IRQn; + dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)uart4ISR); + } + else if (ucNum == UART5) + { + IRQ = UART5_IRQn; + dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)uart5ISR); + } + else if (ucNum == UART6) + { + IRQ = UART6_IRQn; + dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)uart6ISR); + } + else if (ucNum == UART7) + { + IRQ = UART7_IRQn; + dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)uart7ISR); + } + else if (ucNum == UART8) + { + IRQ = UART8_IRQn; + dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)uart8ISR); + } + else if (ucNum == UART9) + { + IRQ = UART9_IRQn; + dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)uart9ISR); + } + else if (ucNum == UARTA) + { + IRQ = UART10_IRQn; + dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)uart10ISR); + } + else + { + return; + } + + //dev->pvUartVector = sysInstallISR((IRQ_LEVEL_1 | HIGH_LEVEL_SENSITIVE), IRQ, (PVOID)pvNewISR); + sysSetLocalInterrupt(ENABLE_IRQ); /* enable CPSR I bit */ + sysEnableInterrupt(IRQ); + //DrvUART_EnableInt(TEST_PORT,(DRVUART_RLSINT|DRVUART_THREINT|DRVUART_RDAINT)); + + +} + +static BOOL _uartBUFSpaceAlloc(INT nNum) +{ + UART_BUFFER_T *dev; + + dev = (UART_BUFFER_T *) &UART_DEV[nNum]; + + /* Memory allocate Tx buffer */ + dev->pucUartTxBuf = (PUINT8) malloc(UARTTXBUFSIZE[nNum] * sizeof(UINT8)); + if (dev->pucUartTxBuf == NULL) + return FALSE; + + /* Memory allocate Rx buffer */ + dev->pucUartRxBuf = (PUINT8) malloc(UARTRXBUFSIZE[nNum] * sizeof(UINT8)); + if (dev->pucUartRxBuf == NULL) + { + free(dev->pucUartTxBuf); + return FALSE; + } + + /* Memory allocate Rx character flag */ + dev->pucUARTFlag = (PINT) malloc(UARTRXBUFSIZE[nNum] * sizeof(INT)); + if (dev->pucUARTFlag == NULL) + { + free(dev->pucUartTxBuf); + free(dev->pucUartRxBuf); + return FALSE; + } + + /* initial memory */ + memset(dev->pucUartTxBuf, 0, UARTTXBUFSIZE[nNum] * sizeof(UINT8)); + memset(dev->pucUartRxBuf, 0, UARTRXBUFSIZE[nNum] * sizeof(UINT8)); + memset(dev->pucUARTFlag, 0, UARTRXBUFSIZE[nNum] * sizeof(INT)); + + /* inital struct UART_BUFFER_STRUCT, uUartTxHead, uUartTxTail, uUartRxHead, uUartRxTail */ + dev->uUartTxHead = dev->uUartTxTail = (UINT32)NULL; + dev->uUartRxHead = dev->uUartRxTail = (UINT32)NULL; + + return TRUE; +} + +static BOOL _uartCheckTxBufSpace(INT nNum, UINT32 uHead, UINT32 uTail, UINT32 uLen) +{ + UINT32 uBuf; + + uBuf = _uartTxBufGetNextOne(nNum, uTail); + if (uBuf == uHead) /* Tx buffer full */ + return FALSE; + + if (uHead == uTail) /* Tx buffer empty */ + return TRUE; + + if (uTail > uHead) + { + if (uLen >= (UARTTXBUFSIZE[nNum] - (uTail - uHead))) /* 2007.10.29 fix pointer bug, PT23 HHWu */ + return FALSE; /* Tx buffer space isn't enough */ + else + return TRUE; + } + else + { + /* case: uTail < uHead */ + if (uLen >= (uHead - uTail)) /* 2007.10.29 fix pointer bug, PT23 HHWu */ + return FALSE; /* Tx buffer space isn't enough */ + else + return TRUE; + } + + //return TRUE; +} + +static INT32 _uartReadRxBuf(INT nNum, PUINT8 pucBuf, UINT32 uLen) +{ + UINT32 i; + UINT32 uOffset = nNum * UARTOFFSET; + UART_BUFFER_T *dev; + + dev = (UART_BUFFER_T *) &UART_DEV[nNum]; + + if (dev->bIsUseUARTRxInt == TRUE) + { + + // disable Rx interrupt ... + + if (dev->uUartRxHead == dev->uUartRxTail) + return 0; + + for (i = uLen ; i > 0 ; i--) + { + *pucBuf++ = dev->pucUartRxBuf[dev->uUartRxHead]; + dev->uUartRxHead = _uartRxBufGetNextOne(nNum, dev->uUartRxHead); + + if (dev->uUartRxHead == dev->uUartRxTail) + break; + } + + uLen = uLen - i + 1; + } + else /* pooling mode */ + { + for (i = 0 ; i < uLen; i++) + { + while (!(inpw(REG_UART0_FSR + uOffset) & UART_FSR_RX_EMPTY_Msk)); + *pucBuf++ = inpb(REG_UART0_RBR + uOffset); + } + } + + return (uLen); +} + +static void _uartWriteTxBuf(INT nNum, PUINT8 pucBuf, UINT32 uLen) +{ + UINT32 i; + UINT32 uOffset = nNum * UARTOFFSET; + UART_BUFFER_T *dev; + + dev = (UART_BUFFER_T *) &UART_DEV[nNum]; + + /* Check interrupt or polling mode first */ + if (dev->bIsUseUARTTxInt == TRUE) + { + while (uLen--) + { + dev->pucUartTxBuf[dev->uUartTxTail] = *pucBuf++; + dev->uUartTxTail = _uartTxBufGetNextOne(nNum, dev->uUartTxTail); + } + + if (!(inpw(REG_UART0_IER + uOffset) & UART_IER_THRE_IEN_Msk)) /* Enable Tx empty interrupt */ + _uartEnableInterrupt(nNum, UART_IER_THRE_IEN_Msk); + } + else /* pooling mode */ + { + for (i = 0 ; i < uLen ; i++) + { + /* Wait until the transmitter buffer is empty */ + while (!(inpw(REG_UART0_FSR + uOffset) & UART_FSR_TE_FLAG_Msk)); + outpw(REG_UART0_THR + uOffset, *pucBuf++); + } + } +} + +static INT _uartConfigureUART(PVOID pvParam) +{ + INT retval; + BOOL bIsMemoryAllocOk; + UINT32 u32Reg; + UINT32 uOffset; + UINT32 uNum = 0; + + UART_T *param = (UART_T *) pvParam; + + uOffset = param->ucUartNo * UARTOFFSET; + uNum = param->ucUartNo; + + /* Check UART channel */ + if (uNum > UARTA) + return UART_ERR_CHANNEL_INVALID; + + /* Check the supplied parity */ + if ((param->ucParity != NU_PARITY_NONE) && + (param->ucParity != NU_PARITY_EVEN) && + (param->ucParity != NU_PARITY_ODD) && + (param->ucParity != (NU_PARITY_ODD | NU_PARITY_STICK)) && + (param->ucParity != (NU_PARITY_EVEN | NU_PARITY_STICK))) + return UART_ERR_PARITY_INVALID; + + /* Check the supplied number of data bits */ + if ((param->ucDataBits != NU_DATA_BITS_5) && + (param->ucDataBits != NU_DATA_BITS_6) && + (param->ucDataBits != NU_DATA_BITS_7) && + (param->ucDataBits != NU_DATA_BITS_8)) + return UART_ERR_DATA_BITS_INVALID; + + /* Check the supplied number of stop bits */ + if ((param->ucStopBits != NU_STOP_BITS_1) && + (param->ucStopBits != NU_STOP_BITS_2)) + return UART_ERR_STOP_BITS_INVALID; + + /* Check the supplied number of trigger level bytes */ + if ((param -> ucUartNo == UART1) || (param -> ucUartNo == UART2) || (param -> ucUartNo == UART4) || + (param -> ucUartNo == UART6) || (param -> ucUartNo == UART8) || (param -> ucUartNo == UARTA)) + { + /* UART1,2,4,6,8,A */ + if ((param->ucRxTriggerLevel != UART_FCR_RFITL_1BYTE) && + (param->ucRxTriggerLevel != UART_FCR_RFITL_4BYTES) && + (param->ucRxTriggerLevel != UART_FCR_RFITL_8BYTES) && + (param->ucRxTriggerLevel != UART_FCR_RFITL_14BYTES) && + (param->ucRxTriggerLevel != UART_FCR_RFITL_30BYTES) && + (param->ucRxTriggerLevel != UART_FCR_RFITL_46BYTES) && + (param->ucRxTriggerLevel != UART_FCR_RFITL_62BYTES)) + return UART_ERR_TRIGGERLEVEL_INVALID; + } + else + { + /* UART0,3,5,7,9 */ + if ((param->ucRxTriggerLevel != UART_FCR_RFITL_1BYTE) && + (param->ucRxTriggerLevel != UART_FCR_RFITL_4BYTES) && + (param->ucRxTriggerLevel != UART_FCR_RFITL_8BYTES) && + (param->ucRxTriggerLevel != UART_FCR_RFITL_30BYTES)) + return UART_ERR_TRIGGERLEVEL_INVALID; + } + + /* Enable UART clock */ + if (param->ucUartNo < ALLCHANNEL) + { + outpw(REG_CLK_PCLKEN0, inpw(REG_CLK_PCLKEN0) | (1 << (16 + param->ucUartNo))); + } + + /* Reset TX/RX FIFOs */ + u32Reg = inpw(REG_UART0_FCR + uOffset); + outpw(REG_UART0_FCR + uOffset, (u32Reg | (0x03 << 1))); + + /* Setup baud rate */ + retval = _uartSetBaudRate(param->ucUartNo, param); + if (retval < 0) + return UART_ERR_SET_BAUDRATE_FAIL; + + /* Setup parity, data bits, and stop bits */ + outpw(REG_UART0_LCR + uOffset, (param->ucParity | param->ucDataBits | param->ucStopBits)); + + /* Setup Rx time out value */ + outpw(REG_UART0_TOR + uOffset, 0x80 + 0x20); + + /* Setup FIFO trigger level */ + outpw(REG_UART0_FCR + uOffset, param->ucRxTriggerLevel); + + /* only exec once unless call uartClose() */ + if (UART_DEV[param->ucUartNo].bIsUARTInitial == FALSE) + { + /* Configure GPIO function */ + //_uartConfigureGPIO(param->ucUartNo); + + /* Allocate Tx, Rx buffer */ + bIsMemoryAllocOk = _uartBUFSpaceAlloc(param->ucUartNo); + if (bIsMemoryAllocOk == FALSE) + return UART_ERR_ALLOC_MEMORY_FAIL; + + /* Hook UART interrupt service routine */ + _uartInstallISR(param->ucUartNo); + + /* Enable Rx interrupt */ + if (UART_DEV[param->ucUartNo].bIsUseUARTRxInt == TRUE) + _uartEnableInterrupt(param->ucUartNo, UART_IER_RDA_IEN_Msk); + + } + + UART_DEV[param->ucUartNo].bIsUARTInitial = TRUE; /* it's important to set TRUE */ + return 0; +} + +static INT _uartPerformIrDA(INT nNum, UINT32 uCmd, UINT32 uCmd1) /* UART2 only */ +{ + UINT32 uOffset = nNum * UARTOFFSET; + UINT32 baud; + + switch (uCmd) + { + case ENABLEIrDA: + //_uart_bIsPerformIrDA = TRUE; + + baud = inpw(REG_UART0_BAUD + uOffset); + baud = baud & (0x0000ffff); + baud = baud + 2; + baud = baud / 16; + baud = baud - 2; + + outpw(REG_UART0_BAUD + uOffset, baud); + + if (uCmd1 == IrDA_TX) + outpw(REG_UART0_IRCR + uOffset, UART_IRCR_TX_SELECT_Msk); + else if (uCmd1 == IrDA_RX) + outpw(REG_UART0_IRCR + uOffset, 0x0); + else + return UART_ERR_IrDA_COMMAND_INVALID; + + outpw(REG_UART0_FUN_SEL + uOffset, 0x2); // Select IrDA mode + + break; + + case DISABLEIrDA: + //_uart_bIsPerformIrDA = FALSE; + outpw(REG_UART0_IRCR + uOffset, 0x40); /* Set default value, INV_TX set 0, INV_RX set 1 */ + outpw(REG_UART0_FUN_SEL + uOffset, 0x0); // Select UART mode + break; + + default: + return UART_ERR_IrDA_COMMAND_INVALID; + } + + return 0; +} + +/* + Remark: + 1. LCR & LSR aren't support yet. +*/ +static INT _uartGetRegisterValue(INT nNum, PVOID pvReg) +{ + INT nCnt = 0; + UINT32 uOffset = nNum * UARTOFFSET; + + UART_REGISTER_T *reg = (UART_REGISTER_T *) pvReg; + + memset(reg, 0, sizeof(UART_REGISTER_T)); + + /* Read IER */ + reg->uUartReg[nCnt][0] = REG_UART0_IER + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_IER + uOffset); + + /* Read FCR */ + reg->uUartReg[nCnt][0] = REG_UART0_FCR + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_FCR + uOffset); + + /* Read LCR */ + reg->uUartReg[nCnt][0] = REG_UART0_LCR + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_LCR + uOffset); + + /* Read MCR, MSR */ + reg->uUartReg[nCnt][0] = REG_UART0_MCR + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_MCR + uOffset); + reg->uUartReg[nCnt][0] = REG_UART0_MSR + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_MSR + uOffset); + + /* Read FSR */ + reg->uUartReg[nCnt][0] = REG_UART0_FSR + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_FSR + uOffset); + + /* Read ISR */ + reg->uUartReg[nCnt][0] = REG_UART0_ISR + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_ISR + uOffset); + + /* Read TOR */ + reg->uUartReg[nCnt][0] = REG_UART0_TOR + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_TOR + uOffset); + + /* Read BAUD */ + reg->uUartReg[nCnt][0] = REG_UART0_BAUD + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_BAUD + uOffset); + + /* Read IRCR */ + reg->uUartReg[nCnt][0] = REG_UART0_IRCR + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_IRCR + uOffset); + + /* Read ALT_CSR */ + reg->uUartReg[nCnt][0] = REG_UART0_ALT_CSR + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_ALT_CSR + uOffset); + + /* Read FUN_SEL */ + reg->uUartReg[nCnt][0] = REG_UART0_FUN_SEL + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_FUN_SEL + uOffset); + + /* Read LIN_CTL */ + reg->uUartReg[nCnt][0] = REG_UART0_LIN_CTL + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_LIN_CTL + uOffset); + + /* Read LIN_SR */ + reg->uUartReg[nCnt][0] = REG_UART0_LIN_SR + uOffset; + reg->uUartReg[nCnt++][1] = inpw(REG_UART0_LIN_SR + uOffset); + + return (nCnt); +} + +/// @endcond HIDDEN_SYMBOLS + +/** @addtogroup N9H30_UART_EXPORTED_FUNCTIONS UART Exported Functions + @{ +*/ + +/** + * @brief The function is used to initial device struct parameters. + * + * @return 0 + */ +INT uartInit(void) +{ + INT i; + + /* Initial UART_BUFFER_T struct */ + for (i = 0; i < UART_NUM ; i++) + UART_DEV[i].bIsUARTInitial = FALSE; + + for (i = 0; i < UART_NUM ; i++) + UART_DEV[i].bIsUseUARTTxInt = TRUE; + + for (i = 0; i < UART_NUM ; i++) + UART_DEV[i].bIsUseUARTRxInt = TRUE; + + return 0; +} + +/** + * @brief The function is used to config UART channel. + * + * @param[in] uart: UART Port. ( UART0 / UART1 / UART2 / UART3 / UART 4 /UART 5 / + * UART6 / UART7 / UART8 / UART9 / UARTA ) + * + * @return UART_EIO: UART config Fail + * Successful: UART config success + */ +INT uartOpen(PVOID uart) +{ + INT nValue = 0; + UART_T *dev = (UART_T *) uart; + + if ((nValue = _uartConfigureUART(uart)) < 0) + { + if (nValue != UART_ERR_CHANNEL_INVALID) + UART_DEV[dev->ucUartNo].nErrno = nValue; + + return UART_EIO; + } + else + UART_DEV[dev->ucUartNo].nErrno = 0; + + return Successful; +} + +/** + * @brief The function is used to read RX FIFO returned data or RX driver buffer. + * + * @param[in] nNum: UART Port. ( UART0 / UART1 / UART2 / UART3 / UART 4 /UART 5 / + * UART6 / UART7 / UART8 / UART9 / UARTA ) + * @param[out] pucBuf: The buffer to receive. + * + * @param[in] uLen: The the read bytes number of data. + * + * @return UART_EIO: UART read Fail + * DataLength: Receive byte count + */ +INT32 uartRead(INT nNum, PUINT8 pucBuf, UINT32 uLen) +{ + UART_BUFFER_T *dev; + INT32 DataLength; + + //if((nNum < UART0) || (nNum > UART4)) + // return UART_ENODEV; + + dev = (UART_BUFFER_T *) &UART_DEV[nNum]; + + /* Check UART initial status */ + if (dev->bIsUARTInitial == FALSE) + return UART_EIO; + + /* Check uLen value */ + if ((uLen > UARTRXBUFSIZE[nNum]) || (uLen == 0)) + return UART_EIO; + + DataLength = _uartReadRxBuf(nNum, pucBuf, uLen); + + return (DataLength); + +} + + +/** + * @brief The function is used to write data to TX FIFO directly or TX driver buffer. + * + * @param[in] nNum: UART channel. ( UART0 / UART1 / UART2 / UART3 / UART 4 /UART 5 / + * UART6 / UART7 / UART8 / UART9 / UARTA ) + * @param[out] pucBuf: Transmit buffer pointer. + * + * @param[in] uLen: Transmit buffer length. + * + * @return UART_EIO: UART transmit Fail + * uLen: write length on success + */ +INT32 uartWrite(INT nNum, PUINT8 pucBuf, UINT32 uLen) +{ + BOOL bIsTxBufEnough; + + UART_BUFFER_T *dev; + + //if((nNum < UART0) || (nNum > UART4)) + // return UART_ENODEV; + + dev = (UART_BUFFER_T *) &UART_DEV[nNum]; + dev->nErrno = 0; + + /* Check UART initial status */ + if (dev->bIsUARTInitial == FALSE) + return UART_EIO; + + /* Check uLen value */ + if ((uLen > UARTWRITESIZE) || (uLen == 0)) + return UART_EIO; + + /* Check UART Tx buffer */ + if (dev->bIsUseUARTTxInt == TRUE) + { + bIsTxBufEnough = _uartCheckTxBufSpace(nNum, dev->uUartTxHead, dev->uUartTxTail, uLen); + if (bIsTxBufEnough == FALSE) + { + //sysprintf("Tx buf not enough\n"); + dev->nErrno = UART_ERR_TX_BUF_NOT_ENOUGH; + return UART_EIO; + } + } + + /* Move data to UART Tx buffer then transmit */ + _uartWriteTxBuf(nNum, pucBuf, uLen); + + return (uLen); +} + +/** + * @brief Support some UART driver commands for application. + * + * @param[in] nNum: UART channel. ( UART0 / UART1 / UART2 / UART3 / UART 4 /UART 5 / + * UART6 / UART7 / UART8 / UART9 / UARTA ) + * + * @param[in] uCmd: Command. + * + * @param[in] uArg0: Arguments for the command. + * + * @param[in] uArg1: Arguments for the command. + * + * @return UART_ENODEV: UART channel out of range + * UART_EIO: No activated or argument error or configure UART fail + * Successful: Success + */ +INT uartIoctl(INT nNum, UINT32 uCmd, UINT32 uArg0, UINT32 uArg1) +{ + INT32 retval; + UINT32 uReg; + UINT32 uOffset = nNum * UARTOFFSET; + + UART_BUFFER_T *dev; + + if ((nNum < UART0) || (nNum > UARTA)) + return UART_ENODEV; + + dev = (UART_BUFFER_T *) &UART_DEV[nNum]; + + /* Check UART initial status */ + if (dev->bIsUARTInitial == FALSE) + { + if ((uCmd != UART_IOC_GETERRNO) && + (uCmd != UART_IOC_GETUARTREGISTERVALUE)) + return UART_EIO; + } + + switch (uCmd) + { + case UART_IOC_SETTXMODE: + if (uArg0 == UARTINTMODE) + dev->bIsUseUARTTxInt = TRUE; + else if (uArg0 == UARTPOLLMODE) + dev->bIsUseUARTTxInt = FALSE; + else + { + dev->nErrno = UART_ERR_OPERATE_MODE_INVALID; + return UART_EIO; + } + + break; + + case UART_IOC_SETRXMODE: + if (uArg0 == UARTINTMODE) + { + dev->bIsUseUARTRxInt = TRUE; + _uartEnableInterrupt(nNum, UART_IER_RDA_IEN_Msk); + } + else if (uArg0 == UARTPOLLMODE) + { + dev->bIsUseUARTRxInt = FALSE; + _uartDisableInterrupt(nNum, UART_IER_RDA_IEN_Msk); + } + else + { + dev->nErrno = UART_ERR_OPERATE_MODE_INVALID; + return UART_EIO; + } + + break; + + case UART_IOC_GETRECCHARINFO: // ..... not test yet + memcpy((PVOID) uArg0, (PVOID) dev, sizeof(struct UART_BUFFER_STRUCT)); + break; + + case UART_IOC_SETUARTPARAMETER: // ..... not test yet + if ((retval = _uartConfigureUART((PVOID) uArg0)) < 0) + { + dev->nErrno = retval; + return UART_EIO; + } + + break; + + case UART_IOC_PERFORMIrDA: + + if ((retval = _uartPerformIrDA(nNum, uArg0, uArg1)) < 0) + { + dev->nErrno = retval; + return UART_EIO; + } + + break; + + case UART_IOC_GETUARTREGISTERVALUE: + return (_uartGetRegisterValue(nNum, (PVOID) uArg0)); + //break; + + case UART_IOC_GETERRNO: + *(PUINT32)uArg0 = dev->nErrno; + break; + + case UART_IOC_SETMODEMINTERRUPT: + + if (uArg0 == UART_ENABLE_MODEM_INT) + _uartEnableInterrupt(nNum, UART_IER_MODEM_IEN_Msk); + else if (uArg0 == UART_DISABLE_MODEM_INT) + _uartDisableInterrupt(nNum, UART_IER_MODEM_IEN_Msk); + else + return UART_EIO; + + break; + + case UART_IOC_GETCTSSTATE: + + if (nNum == UART1) + { + *(PUINT32)uArg0 = _uart_cCTSState1; /* CTS state */ + _uart_cCTSState1 = 0; + } + else if (nNum == UART2) + { + *(PUINT32)uArg0 = _uart_cCTSState2; /* CTS state */ + _uart_cCTSState2 = 0; + } + else if (nNum == UART3) + { + *(PUINT32)uArg0 = _uart_cCTSState3; /* CTS state */ + _uart_cCTSState3 = 0; + } + else if (nNum == UART4) + { + *(PUINT32)uArg0 = _uart_cCTSState4; /* CTS state */ + _uart_cCTSState4 = 0; + } + else if (nNum == UART5) + { + *(PUINT32)uArg0 = _uart_cCTSState5; /* CTS state */ + _uart_cCTSState5 = 0; + } + else if (nNum == UART6) + { + *(PUINT32)uArg0 = _uart_cCTSState6; /* CTS state */ + _uart_cCTSState6 = 0; + } + else if (nNum == UART7) + { + *(PUINT32)uArg0 = _uart_cCTSState7; /* CTS state */ + _uart_cCTSState7 = 0; + } + else if (nNum == UART8) + { + *(PUINT32)uArg0 = _uart_cCTSState8; /* CTS state */ + _uart_cCTSState8 = 0; + } + else if (nNum == UART9) + { + *(PUINT32)uArg0 = _uart_cCTSState9; /* CTS state */ + _uart_cCTSState9 = 0; + } + else if (nNum == UARTA) + { + *(PUINT32)uArg0 = _uart_cCTSState10; /* CTS state */ + _uart_cCTSState10 = 0; + } + + *(PUINT32)uArg1 = (inpw(REG_UART0_MSR + uOffset) & (1 << 4)) >> 4; /* get CTS# value */ + + break; + + case UART_IOC_SETRTSSIGNAL: + + if (uArg0 == UART_RTS_HIGH) /* set RTS signal high */ + outpw(REG_UART0_MCR + uOffset, inpw(REG_UART0_MCR + uOffset) & ~0x02); + else if (uArg0 == UART_RTS_LOW) /* set RTS signal low */ + outpw(REG_UART0_MCR + uOffset, inpw(REG_UART0_MCR + uOffset) | 0x02); + else + return UART_EIO; + + break; + + case UART_IOC_SETINTERRUPT: + if (uArg0 == 1) /* enable interrupt */ + _uartEnableInterrupt(nNum, uArg1); + else if (uArg0 == 0) /* disable interrupt */ + _uartDisableInterrupt(nNum, uArg1); + else + return UART_EIO; + + break; + + case UART_IOC_SETBREAKCONTROL: + uReg = inpw(REG_UART0_LCR + uOffset); + if (uArg0 == 1) /* set break contorl bit */ + { + uReg |= UART_LCR_BCB_Msk; + outpw(REG_UART0_LCR + uOffset, uReg); + } + else if (uArg0 == 0) /* clear break contorl bit */ + { + uReg &= ~UART_LCR_BCB_Msk; + outpw(REG_UART0_LCR + uOffset, uReg); + } + else + return UART_EIO; + + break; + + case UART_IOC_GETBIISTATE: + switch (nNum) + { + case UART0: + *(PUINT32)uArg0 = _uart_cBIIState_0; + break; + case UART1: + *(PUINT32)uArg0 = _uart_cBIIState_1; + break; + case UART2: + *(PUINT32)uArg0 = _uart_cBIIState_2; + break; + case UART3: + *(PUINT32)uArg0 = _uart_cBIIState_3; + break; + case UART4: + *(PUINT32)uArg0 = _uart_cBIIState_4; + break; + case UART5: + *(PUINT32)uArg0 = _uart_cBIIState_5; + break; + case UART6: + *(PUINT32)uArg0 = _uart_cBIIState_6; + break; + case UART7: + *(PUINT32)uArg0 = _uart_cBIIState_7; + break; + case UART8: + *(PUINT32)uArg0 = _uart_cBIIState_8; + break; + case UART9: + *(PUINT32)uArg0 = _uart_cBIIState_9; + break; + case UARTA: + *(PUINT32)uArg0 = _uart_cBIIState_10; + break; + + default: + break; + } + break; + + /* H/W S/W flow control function */ + case UART_IOC_ENABLEHWFLOWCONTROL: + + /* H/W & S/W are alternative */ + if (_uart_cFlowControlMode == SWFLOWCONTROL) + return UART_EIO; + + _uart_cFlowControlMode = HWFLOWCONTROL; + + /* Implement H/W flow control on TX & RX interrupt mode. */ + //dev->bIsUseUARTTxInt = TRUE; + //dev->bIsUseUARTRxInt = TRUE; + _uartEnableInterrupt(nNum, UART_IER_RDA_IEN_Msk); + + /* + Set up RTS mechanism. + In uartReceiveChars(), if uRecCnt >= _uart_nMaxRxBuf then set RTS high to stop RX. + In uartReadRxBuf(), if uRecCnt <= _uart_nMinRxBuf then set RTS low to re-start RX. + */ + //_uart_nMaxRxBuf = (UARTRXBUFSIZE[nNum] * 3) / 4; + //_uart_nMinRxBuf = UARTRXBUFSIZE[nNum] / 2; + //FDEBUG("max[%d] min[%d]\n", _uart_nMaxRxBuf, _uart_nMinRxBuf); + + /* Set RTS high level trigger */ + outpw(REG_UART0_MCR + uOffset, (inpw(REG_UART0_MCR + uOffset) | UART_RTS_IS_HIGH_LEV_TRG)); + /* Set RTS high level trigger */ + outpw(REG_UART0_MSR + uOffset, (inpw(REG_UART0_MSR + uOffset) | UART_CTS_IS_HIGH_LEV_TRG)); + + /* Set Auto CTS/RTS */ + outpw(REG_UART0_IER + uOffset, inpw(REG_UART0_IER + uOffset) | (0x3 << 12)); + + /* Enable MODEM status interrupt */ + //_uartEnableInterrupt(nNum, UART_IER_MODEM_IEN_Msk); + + /* + Maintain H/W flow control flag by read Modem Status Register. + If CTS high, stop TX. + If CTS low, start TX. + */ + //if( inpw(REG_UART0_MSR+uOffset) & 0x10 ) /* CTS external signal is low */ + // _uart_cHWTXStopped = 0; /* TX started */ + //else /* CTS external signal is high */ + // _uart_cHWTXStopped = 1; /* TX stopped */ + + /* Set RTS as logic 0, RX re-start */ + //outpb(REG_UART0_MCR+uOffset, inpb(REG_UART0_MCR+uOffset) | 0x02); /* set RTS signal low */ + //_uart_cHWRXStopped = 0; // RX started + break; + + case UART_IOC_DISABLEHWFLOWCONTROL: + + /* Disable MODEM status interrupt */ + _uartDisableInterrupt(nNum, UART_IER_MODEM_IEN_Msk); + _uart_cFlowControlMode = 0; + _uart_cHWTXStopped = 0; + _uart_cHWRXStopped = 0; + break; + + case UART_IOC_FLUSH_TX_BUFFER: + dev->uUartTxTail = 0; + dev->uUartTxHead = 0; + break; + + case UART_IOC_FLUSH_RX_BUFFER: + dev->uUartRxTail = 0; + dev->uUartRxHead = 0; + break; + + case UART_IOC_SET_RS485_MODE: + outpw((REG_UART0_FUN_SEL + uOffset), 0x3); + outpw((REG_UART0_MCR + uOffset), 0x0); + outpw((REG_UART0_LCR + uOffset), (UART_LCR_SPE_Msk | UART_LCR_EPE_Msk | UART_LCR_PBE_Msk | (0x3 << UART_LCR_WLS_Pos))); + outpw((REG_UART0_ALT_CSR + uOffset), uArg0 | (uArg1 << UART_ALT_CSR_ADDR_MATCH_Pos)); + break; + + case UART_IOC_SEND_RS485_ADDRESS: + + while (!((inpw(REG_UART0_FSR + uOffset)) & UART_FSR_TE_FLAG_Msk)); + uReg = inpw(REG_UART0_LCR + uOffset); + outpw((REG_UART0_LCR + uOffset), (UART_LCR_SPE_Msk | UART_LCR_PBE_Msk | (0x3 << UART_LCR_WLS_Pos))); + outpw((REG_UART0_THR + uOffset), uArg0); + while (!((inpw(REG_UART0_FSR + uOffset)) & UART_FSR_TE_FLAG_Msk)); + + outpw((REG_UART0_LCR + uOffset), uReg); + + break; + + case UART_IOC_SET_RS485_RXOFF: + uReg = inpw(REG_UART0_FCR + uOffset); + if (uArg0 == 1) + uReg |= UART_FCR_RX_DIS_Msk; + else + uReg &= ~UART_FCR_RX_DIS_Msk; + + outpw((REG_UART0_FCR + uOffset), uReg); + + break; + + case UART_IOC_SET_ALTCTL_REG: + + outpw((REG_UART0_ALT_CSR + uOffset), uArg0); + + break; + + case UART_IOC_GET_ALTCTL_REG: + + *(PUINT32)uArg0 = inpw(REG_UART0_ALT_CSR + uOffset); + + break; + + case UART_IOC_SET_LIN_MODE: + + outpw((REG_UART0_FUN_SEL + uOffset), 0x1); // Select LIN function + + /* Select LIN function setting : Tx enable, Rx enable and break field length */ + uReg = inpw(REG_UART0_ALT_CSR + uOffset); + uReg &= ~(UART_ALT_CSR_LIN_TX_EN_Msk | UART_ALT_CSR_LIN_RX_EN_Msk | UART_ALT_CSR_UA_LIN_BKFL_Msk); + uReg |= (uArg0 | (uArg1 << UART_ALT_CSR_UA_LIN_BKFL_Pos)); + outpw((REG_UART0_ALT_CSR + uOffset), uReg); + + break; + + default: + return UART_ENOTTY; + } + + return Successful; +} + +/** + * @brief Release memory resource, disable interrupt. + * + * @param[in] nNum: UART channel. ( UART0 / UART1 / UART2 / UART3 / UART 4 /UART 5 / + * UART6 / UART7 / UART8 / UART9 / UARTA ) + * + * @return UART_ENODEV: UART channel out of range + * UART_EIO: No activated + * Successful: Success + */ +INT32 uartRelease(INT nNum) +{ + UART_BUFFER_T *dev; + + if ((nNum < UART0) || (nNum > UARTA)) + return UART_ENODEV; + + dev = (UART_BUFFER_T *) &UART_DEV[nNum]; + + /* Check UART initial status */ + if (dev->bIsUARTInitial == FALSE) + return UART_EIO; + + /* Disable all interrupt of the specific UART */ + _uartDisableInterrupt(nNum, DISABLEALLIER); + + /* Free memory */ + free(dev->pucUartTxBuf); + free(dev->pucUartRxBuf); + free(dev->pucUARTFlag); + + /* Initial parameter */ + dev->bIsUARTInitial = FALSE; /* it's important */ + + return Successful; +} + +/*@}*/ /* end of group N9H30_UART_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_UART_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ +#else +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_uart.h" + +/** + * @brief Open and set UART function + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] u32baudrate The baudrate of UART module. + * + * @return None + * + * @details This function use to enable UART function and set baud-rate. + */ +void UART_Open(UART_T *uart, uint32_t u32baudrate) +{ + uint32_t u32UartClkSrcSel = 0ul, u32UartClkDivNum = 0ul; + //uint32_t u32ClkTbl[4] = {XIN, LXT, ACLK, UCLK}; + uint32_t u32ClkTbl[4] = {12000000, 0, 75000000, 150000000}; + uint32_t u32Baud_Div = 0ul; + + if ((uint32_t)uart == UART0_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL4) & (0x3ul << 3)) >> 3; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL4) & (0x7ul << 5)) >> 5; + } + else if ((uint32_t)uart == UART1_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL4) & (0x3ul << 11)) >> 11; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL4) & (0x7ul << 13)) >> 13; + } + else if ((uint32_t)uart == UART2_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL4) & (0x3ul << 19)) >> 19; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL4) & (0x7ul << 21)) >> 21; + } + else if ((uint32_t)uart == UART3_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL4) & (0x3ul << 27)) >> 27; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL4) & (0x7ul << 29)) >> 29; + } + else if ((uint32_t)uart == UART4_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL5) & (0x3ul << 3)) >> 3; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL5) & (0x7ul << 5)) >> 5; + } + else if ((uint32_t)uart == UART5_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL5) & (0x3ul << 11)) >> 11; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL5) & (0x7ul << 13)) >> 13; + } + else if ((uint32_t)uart == UART6_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL5) & (0x3ul << 19)) >> 19; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL5) & (0x7ul << 21)) >> 21; + } + else if ((uint32_t)uart == UART7_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL5) & (0x3ul << 27)) >> 27; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL5) & (0x7ul << 29)) >> 29; + } + else if ((uint32_t)uart == UART8_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL6) & (0x3ul << 3)) >> 3; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL6) & (0x7ul << 5)) >> 5; + } + else if ((uint32_t)uart == UART9_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL6) & (0x3ul << 11)) >> 11; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL6) & (0x7ul << 13)) >> 13; + } + else if ((uint32_t)uart == UARTA_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL6) & (0x3ul << 19)) >> 19; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL6) & (0x7ul << 21)) >> 21; + } + + /* Select UART function */ + uart->FUNCSEL = UART_FUNCSEL_UART; + + /* Set UART line configuration */ + uart->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1; + + /* Set UART Rx and RTS trigger level */ + uart->FIFO &= ~(UART_FIFO_RFITL_Msk | UART_FIFO_RTSTRGLV_Msk); + + /* Get PLL clock frequency if UART clock source selection is PLL */ + if (u32UartClkSrcSel == 2ul) // ACLK + { + //u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq(); + } + + if (u32UartClkSrcSel == 3ul) // PCLK + { + //u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq(); + } + + /* Set UART baud rate */ + if (u32baudrate != 0ul) + { + u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate); + + if (u32Baud_Div > 0xFFFFul) + { + uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate)); + } + else + { + uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div); + } + } +} + +void UART_Close(UART_T *uart) +{ + uart->INTEN = 0ul; +} + +/** + * @brief Set UART line configuration + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] u32baudrate The register value of baudrate of UART module. + * If u32baudrate = 0, UART baudrate will not change. + * @param[in] u32data_width The data length of UART module. + * - \ref UART_WORD_LEN_5 + * - \ref UART_WORD_LEN_6 + * - \ref UART_WORD_LEN_7 + * - \ref UART_WORD_LEN_8 + * @param[in] u32parity The parity setting (none/odd/even/mark/space) of UART module. + * - \ref UART_PARITY_NONE + * - \ref UART_PARITY_ODD + * - \ref UART_PARITY_EVEN + * - \ref UART_PARITY_MARK + * - \ref UART_PARITY_SPACE + * @param[in] u32stop_bits The stop bit length (1/1.5/2 bit) of UART module. + * - \ref UART_STOP_BIT_1 + * - \ref UART_STOP_BIT_1_5 + * - \ref UART_STOP_BIT_2 + * + * @return None + * + * @details This function use to config UART line setting. + */ +void UART_SetLineConfig(UART_T *uart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits) +{ + uint32_t u32UartClkSrcSel = 0ul, u32UartClkDivNum = 0ul; + //uint32_t u32ClkTbl[4] = {XIN, LXT, ACLK, UCLK}; + uint32_t u32ClkTbl[4] = {12000000, 32768, 75000000, 150000000}; + uint32_t u32Baud_Div = 0ul; + + + if ((uint32_t)uart == UART0_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL4) & (0x3ul << 3)) >> 3; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL4) & (0x7ul << 5)) >> 5; + } + else if ((uint32_t)uart == UART1_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL4) & (0x3ul << 11)) >> 11; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL4) & (0x7ul << 13)) >> 13; + } + else if ((uint32_t)uart == UART2_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL4) & (0x3ul << 19)) >> 19; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL4) & (0x7ul << 21)) >> 21; + } + else if ((uint32_t)uart == UART3_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL4) & (0x3ul << 27)) >> 27; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL4) & (0x7ul << 29)) >> 29; + } + else if ((uint32_t)uart == UART4_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL5) & (0x3ul << 3)) >> 3; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL5) & (0x7ul << 5)) >> 5; + } + else if ((uint32_t)uart == UART5_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL5) & (0x3ul << 11)) >> 11; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL5) & (0x7ul << 13)) >> 13; + } + else if ((uint32_t)uart == UART6_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL5) & (0x3ul << 19)) >> 19; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL5) & (0x7ul << 21)) >> 21; + } + else if ((uint32_t)uart == UART7_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL5) & (0x3ul << 27)) >> 27; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL5) & (0x7ul << 29)) >> 29; + } + else if ((uint32_t)uart == UART8_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL6) & (0x3ul << 3)) >> 3; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL6) & (0x7ul << 5)) >> 5; + } + else if ((uint32_t)uart == UART9_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL6) & (0x3ul << 11)) >> 11; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL6) & (0x7ul << 13)) >> 13; + } + else if ((uint32_t)uart == UARTA_BA) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (inp32(REG_CLK_DIVCTL6) & (0x3ul << 19)) >> 19; + /* Get UART clock divider number */ + u32UartClkDivNum = (inp32(REG_CLK_DIVCTL6) & (0x7ul << 21)) >> 21; + } + + /* Get PLL clock frequency if UART clock source selection is PLL */ + if (u32UartClkSrcSel == 2ul) // ACLK + { + //u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq(); + } + + if (u32UartClkSrcSel == 3ul) // PCLK + { + //u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq(); + } + + /* Set UART baud rate */ + if (u32baudrate != 0ul) + { + u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate); + + if (u32Baud_Div > 0xFFFFul) + { + uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate)); + } + else + { + uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div); + } + } + + /* Set UART line configuration */ + uart->LINE = u32data_width | u32parity | u32stop_bits; +} +#endif + + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_usbd.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_usbd.c new file mode 100644 index 0000000000..1ed8a1670a --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_usbd.c @@ -0,0 +1,619 @@ +/**************************************************************************//** + * @file usbd.c + * @brief N9H30 USBD driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "N9H30.h" +#include "nu_usbd.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_USBD_Driver USBD Driver + @{ +*/ + + +/** @addtogroup N9H30_USBD_EXPORTED_FUNCTIONS USBD Exported Functions + @{ +*/ +/*--------------------------------------------------------------------------*/ +/// @cond HIDDEN_SYMBOLS + +/*!< Global variables for Control Pipe */ +S_USBD_CMD_T gUsbCmd; +S_USBD_INFO_T *g_usbd_sInfo; + +VENDOR_REQ g_usbd_pfnVendorRequest = 0; +CLASS_REQ g_usbd_pfnClassRequest = 0; +SET_INTERFACE_REQ g_usbd_pfnSetInterface = 0; +uint32_t g_u32EpStallLock = 0; /*!< Bit map flag to lock specified EP when SET_FEATURE */ + +static uint8_t *g_usbd_CtrlInPointer = 0; +static uint32_t g_usbd_CtrlMaxPktSize = 64; +static uint8_t g_usbd_UsbConfig = 0; +static uint8_t g_usbd_UsbAltInterface = 0; +static uint8_t g_usbd_EnableTestMode = 0; +static uint8_t g_usbd_TestSelector = 0; + +#ifdef __ICCARM__ + #pragma data_alignment=4 + static uint8_t g_usbd_buf[12]; +#else + static uint8_t g_usbd_buf[12] __attribute__((aligned(4))); +#endif + + +uint8_t volatile g_usbd_Configured = 0; +uint8_t g_usbd_CtrlZero = 0; +uint8_t g_usbd_UsbAddr = 0; +uint8_t g_usbd_ShortPacket = 0; +uint32_t volatile g_usbd_DmaDone = 0; +uint32_t g_usbd_CtrlInSize = 0; +/// @endcond HIDDEN_SYMBOLS + +/** + * @brief USBD Initial + * + * @param[in] param Descriptor + * @param[in] pfnClassReq Class Request Callback Function + * @param[in] pfnSetInterface SetInterface Request Callback Function + * + * @return None + * + * @details This function is used to initial USBD. + */ +void USBD_Open(S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface) +{ + /* Select Vbus detect pin -> GPH0 */ + outpw(REG_SYS_GPH_MFPL, (inpw(REG_SYS_GPH_MFPL) & ~0xf) | 0x7); + /* Enable USB device clock */ + outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) | 0x80000); + + g_usbd_sInfo = param; + g_usbd_pfnClassRequest = pfnClassReq; + g_usbd_pfnSetInterface = pfnSetInterface; + + /* get EP0 maximum packet size */ + g_usbd_CtrlMaxPktSize = g_usbd_sInfo->gu8DevDesc[7]; + + /* Initial USB engine */ + /* Enable PHY */ + USBD_ENABLE_PHY(); + /* wait PHY clock ready */ + while (1) + { + USBD->EP[EPA].EPMPS = 0x20; + if (USBD->EP[EPA].EPMPS == 0x20) + break; + } + /* Force SE0, and then clear it to connect*/ + USBD_SET_SE0(); +} + +/** + * @brief USBD Start + * + * @return None + * + * @details This function is used to start transfer + */ +void USBD_Start(void) +{ + USBD_CLR_SE0(); +} + +/** + * @brief Process Setup Packet + * + * @return None + * + * @details This function is used to process Setup packet. + */ +void USBD_ProcessSetupPacket(void) +{ + // Setup packet process + gUsbCmd.bmRequestType = (uint8_t)(USBD->SETUP1_0 & 0xff); + gUsbCmd.bRequest = (int8_t)(USBD->SETUP1_0 >> 8) & 0xff; + gUsbCmd.wValue = (uint16_t)USBD->SETUP3_2; + gUsbCmd.wIndex = (uint16_t)USBD->SETUP5_4; + gUsbCmd.wLength = (uint16_t)USBD->SETUP7_6; + + /* USB device request in setup packet: offset 0, D[6..5]: 0=Standard, 1=Class, 2=Vendor, 3=Reserved */ + switch (gUsbCmd.bmRequestType & 0x60) + { + case REQ_STANDARD: // Standard + { + USBD_StandardRequest(); + break; + } + case REQ_CLASS: // Class + { + if (g_usbd_pfnClassRequest != NULL) + { + g_usbd_pfnClassRequest(); + } + break; + } + case REQ_VENDOR: // Vendor + { + if (g_usbd_pfnVendorRequest != NULL) + { + g_usbd_pfnVendorRequest(); + } + break; + } + default: // reserved + { + /* Setup error, stall the device */ + USBD_SET_CEP_STATE(USBD_CEPCTL_STALLEN_Msk); + break; + } + } +} + +/** + * @brief Get Descriptor request + * + * @return None + * + * @details This function is used to process GetDescriptor request. + */ +int USBD_GetDescriptor(void) +{ + uint32_t u32Len; + + u32Len = gUsbCmd.wLength; + g_usbd_CtrlZero = 0; + + switch ((gUsbCmd.wValue & 0xff00) >> 8) + { + // Get Device Descriptor + case DESC_DEVICE: + { + u32Len = Minimum(u32Len, LEN_DEVICE); + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len); + break; + } + // Get Configuration Descriptor + case DESC_CONFIG: + { + uint32_t u32TotalLen; + + u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3]; + u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8); + + u32Len = Minimum(u32Len, u32TotalLen); + if ((u32Len % g_usbd_CtrlMaxPktSize) == 0) + g_usbd_CtrlZero = 1; + + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len); + break; + } + // Get Qualifier Descriptor + case DESC_QUALIFIER: + { + u32Len = Minimum(u32Len, LEN_QUALIFIER); + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8QualDesc, u32Len); + break; + } + // Get Other Speed Descriptor - Full speed + case DESC_OTHERSPEED: + { + uint32_t u32TotalLen; + + u32TotalLen = g_usbd_sInfo->gu8OtherConfigDesc[3]; + u32TotalLen = g_usbd_sInfo->gu8OtherConfigDesc[2] + (u32TotalLen << 8); + + u32Len = Minimum(u32Len, u32TotalLen); + if ((u32Len % g_usbd_CtrlMaxPktSize) == 0) + g_usbd_CtrlZero = 1; + + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8OtherConfigDesc, u32Len); + break; + } + // Get HID Descriptor + case DESC_HID: + { + u32Len = Minimum(u32Len, LEN_HID); + USBD_MemCopy(g_usbd_buf, (uint8_t *)&g_usbd_sInfo->gu8ConfigDesc[LEN_CONFIG + LEN_INTERFACE], u32Len); + USBD_PrepareCtrlIn(g_usbd_buf, u32Len); + break; + } + // Get Report Descriptor + case DESC_HID_RPT: + { + if ((u32Len % g_usbd_CtrlMaxPktSize) == 0) + g_usbd_CtrlZero = 1; + + u32Len = Minimum(u32Len, g_usbd_sInfo->gu32HidReportSize[gUsbCmd.wIndex & 0xff]); + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8HidReportDesc[gUsbCmd.wIndex & 0xff], u32Len); + break; + } + // Get String Descriptor + case DESC_STRING: + { + // Get String Descriptor + if ((gUsbCmd.wValue & 0xff) < 4) + { + u32Len = Minimum(u32Len, g_usbd_sInfo->gu8StringDesc[gUsbCmd.wValue & 0xff][0]); + if ((u32Len % g_usbd_CtrlMaxPktSize) == 0) + g_usbd_CtrlZero = 1; + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8StringDesc[gUsbCmd.wValue & 0xff], u32Len); + } + else + { + USBD_SET_CEP_STATE(USBD_CEPCTL_STALLEN_Msk); + return 1; + } + break; + } + default: + // Not support. Reply STALL. + USBD_SET_CEP_STATE(USBD_CEPCTL_STALLEN_Msk); + return 1; + } + return 0; +} + + +/** + * @brief Process USB standard request + * + * @return None + * + * @details This function is used to process USB Standard Request. + */ +void USBD_StandardRequest(void) +{ + /* clear global variables for new request */ + g_usbd_CtrlInPointer = 0; + g_usbd_CtrlInSize = 0; + + if (gUsbCmd.bmRequestType & 0x80) /* request data transfer direction */ + { + // Device to host + switch (gUsbCmd.bRequest) + { + case GET_CONFIGURATION: + { + // Return current configuration setting + USBD_PrepareCtrlIn((uint8_t *)&g_usbd_UsbConfig, 1); + + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_INTKIEN_Msk); + break; + } + case GET_DESCRIPTOR: + { + if (!USBD_GetDescriptor()) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_INTKIEN_Msk); + } + break; + } + case GET_INTERFACE: + { + // Return current interface setting + USBD_PrepareCtrlIn((uint8_t *)&g_usbd_UsbAltInterface, 1); + + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_INTKIEN_Msk); + break; + } + case GET_STATUS: + { + // Device + if (gUsbCmd.bmRequestType == 0x80) + { + if (g_usbd_sInfo->gu8ConfigDesc[7] & 0x40) + g_usbd_buf[0] = 1; // Self-Powered + else + g_usbd_buf[0] = 0; // bus-Powered + } + // Interface + else if (gUsbCmd.bmRequestType == 0x81) + g_usbd_buf[0] = 0; + // Endpoint + else if (gUsbCmd.bmRequestType == 0x82) + { + uint8_t ep = gUsbCmd.wIndex & 0xF; + g_usbd_buf[0] = USBD_GetStall(ep) ? 1 : 0; + } + g_usbd_buf[1] = 0; + USBD_PrepareCtrlIn(g_usbd_buf, 2); + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_INTKIEN_Msk); + break; + } + default: + { + /* Setup error, stall the device */ + USBD_SET_CEP_STATE(USBD_CEPCTL_STALLEN_Msk); + break; + } + } + } + else + { + // Host to device + switch (gUsbCmd.bRequest) + { + case CLEAR_FEATURE: + { + if ((gUsbCmd.wValue & 0xff) == FEATURE_ENDPOINT_HALT) + { + + int32_t epNum, i; + + /* EP number stall is not allow to be clear in MSC class "Error Recovery Test". + a flag: g_u32EpStallLock is added to support it */ + epNum = gUsbCmd.wIndex & 0xF; + for (i = 0; i < USBD_MAX_EP; i++) + { + if ((((USBD->EP[i].EPCFG & 0xf0) >> 4) == epNum) && ((g_u32EpStallLock & (1 << i)) == 0)) + { + USBD->EP[i].EPRSPCTL = (USBD->EP[i].EPRSPCTL & 0xef) | USB_EP_RSPCTL_TOGGLE; + } + } + } + /* Status stage */ + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk); + USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_STSDONEIEN_Msk); + break; + } + case SET_ADDRESS: + { + g_usbd_UsbAddr = (uint8_t)gUsbCmd.wValue; + + // DATA IN for end of setup + /* Status Stage */ + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk); + USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_STSDONEIEN_Msk); + break; + } + case SET_CONFIGURATION: + { + g_usbd_UsbConfig = (uint8_t)gUsbCmd.wValue; + g_usbd_Configured = 1; + // DATA IN for end of setup + /* Status stage */ + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk); + USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_STSDONEIEN_Msk); + break; + } + case SET_FEATURE: + { + if ((gUsbCmd.wValue & 0x3) == 2) /* TEST_MODE*/ + { + g_usbd_EnableTestMode = 1; + g_usbd_TestSelector = gUsbCmd.wIndex >> 8; + } + /* Status stage */ + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk); + USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_STSDONEIEN_Msk); + break; + } + case SET_INTERFACE: + { + g_usbd_UsbAltInterface = (uint8_t)gUsbCmd.wValue; + if (g_usbd_pfnSetInterface != NULL) + g_usbd_pfnSetInterface(g_usbd_UsbAltInterface); + /* Status stage */ + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk); + USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_STSDONEIEN_Msk); + break; + } + default: + { + /* Setup error, stall the device */ + USBD_SET_CEP_STATE(USBD_CEPCTL_STALLEN_Msk); + break; + } + } + } +} + +#define TEST_J 0x01 /*!< TEST J \hideinitializer */ +#define TEST_K 0x02 /*!< TEST K \hideinitializer */ +#define TEST_SE0_NAK 0x03 /*!< TEST SE0 \hideinitializer */ +#define TEST_PACKET 0x04 /*!< TEST Packet \hideinitializer */ +#define TEST_FORCE_ENABLE 0x05 /*!< TEST Force enable \hideinitializer */ + + +/** + * @brief Update Device State + * + * @return None + * + * @details This function is used to update Device state when Setup packet complete + */ +void USBD_UpdateDeviceState(void) +{ + switch (gUsbCmd.bRequest) + { + case SET_ADDRESS: + { + USBD_SET_ADDR(g_usbd_UsbAddr); + break; + } + case SET_CONFIGURATION: + { + if (g_usbd_UsbConfig == 0) + { + int volatile i; + /* Reset PID DATA0 */ + for (i = 0; i < USBD_MAX_EP; i++) + { + if (USBD->EP[i].EPCFG & 0x1) + { + USBD->EP[i].EPRSPCTL = USB_EP_RSPCTL_TOGGLE; + } + } + } + break; + } + case SET_FEATURE: + { + if (gUsbCmd.wValue == FEATURE_ENDPOINT_HALT) + USBD_SetStall(gUsbCmd.wIndex & 0xF); + else if (g_usbd_EnableTestMode) + { + g_usbd_EnableTestMode = 0; + if (g_usbd_TestSelector == TEST_J) + USBD->TEST = TEST_J; + else if (g_usbd_TestSelector == TEST_K) + USBD->TEST = TEST_K; + else if (g_usbd_TestSelector == TEST_SE0_NAK) + USBD->TEST = TEST_SE0_NAK; + else if (g_usbd_TestSelector == TEST_PACKET) + USBD->TEST = TEST_PACKET; + else if (g_usbd_TestSelector == TEST_FORCE_ENABLE) + USBD->TEST = TEST_FORCE_ENABLE; + } + break; + } + case CLEAR_FEATURE: + { + if (gUsbCmd.wValue == FEATURE_ENDPOINT_HALT) + USBD_ClearStall(gUsbCmd.wIndex & 0xF); + break; + } + default: + ; + } +} + + +/** + * @brief Prepare Control IN transaction + * + * @param[in] pu8Buf Control IN data pointer + * @param[in] u32Size IN transfer size + * + * @return None + * + * @details This function is used to prepare Control IN transfer + */ +void USBD_PrepareCtrlIn(uint8_t *pu8Buf, uint32_t u32Size) +{ + g_usbd_CtrlInPointer = pu8Buf; + g_usbd_CtrlInSize = u32Size; +} + + + +/** + * @brief Start Control IN transfer + * + * @return None + * + * @details This function is used to start Control IN + */ +void USBD_CtrlIn(void) +{ + int volatile i; + uint32_t volatile count; + + // Process remained data + if (g_usbd_CtrlInSize >= g_usbd_CtrlMaxPktSize) + { + // Data size > MXPLD + for (i = 0; i < (g_usbd_CtrlMaxPktSize >> 2); i++, g_usbd_CtrlInPointer += 4) + USBD->cep.CEPDAT = *(uint32_t *)g_usbd_CtrlInPointer; + USBD_START_CEP_IN(g_usbd_CtrlMaxPktSize); + g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize; + } + else + { + // Data size <= MXPLD + for (i = 0; i < (g_usbd_CtrlInSize >> 2); i++, g_usbd_CtrlInPointer += 4) + USBD->cep.CEPDAT = *(uint32_t *)g_usbd_CtrlInPointer; + + count = g_usbd_CtrlInSize % 4; + for (i = 0; i < count; i++) + USBD->cep.CEPDAT_BYTE = *(uint8_t *)(g_usbd_CtrlInPointer + i); + + USBD_START_CEP_IN(g_usbd_CtrlInSize); + g_usbd_CtrlInPointer = 0; + g_usbd_CtrlInSize = 0; + } +} + +/** + * @brief Start Control OUT transaction + * + * @param[in] pu8Buf Control OUT data pointer + * @param[in] u32Size OUT transfer size + * + * @return None + * + * @details This function is used to start Control OUT transfer + */ +void USBD_CtrlOut(uint8_t *pu8Buf, uint32_t u32Size) +{ + int volatile i; + + while (1) + { + if (USBD->CEPINTSTS & USBD_CEPINTSTS_RXPKIF_Msk) + { + for (i = 0; i < u32Size; i++) + *(uint8_t *)(pu8Buf + i) = USBD->cep.CEPDAT_BYTE; + USBD->CEPINTSTS = USBD_CEPINTSTS_RXPKIF_Msk; + break; + } + } +} + +/** + * @brief Clear all software flags + * + * @return None + * + * @details This function is used to clear all software control flag + */ +void USBD_SwReset(void) +{ + // Reset all variables for protocol + g_usbd_UsbAddr = 0; + g_usbd_DmaDone = 0; + g_usbd_ShortPacket = 0; + g_usbd_Configured = 0; + + // Reset USB device address + USBD_SET_ADDR(0); +} + +/** + * @brief USBD Set Vendor Request + * + * @param[in] pfnVendorReq Vendor Request Callback Function + * + * @return None + * + * @details This function is used to set USBD vendor request callback function + */ +void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq) +{ + g_usbd_pfnVendorRequest = pfnVendorReq; +} + + +/*@}*/ /* end of group N9H30_USBD_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_USBD_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_wdt.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_wdt.c new file mode 100644 index 0000000000..70bb6f5a67 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_wdt.c @@ -0,0 +1,66 @@ +/**************************************************************************//** + * @file wdt.c + * @brief NUC980 series WDT driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "nu_wdt.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup WDT_Driver WDT Driver + @{ +*/ + +/** @addtogroup WDT_EXPORTED_FUNCTIONS WDT Exported Functions + @{ +*/ + +/** + * @brief Initialize WDT and start counting + * + * @param[in] u32TimeoutInterval Time-out interval period of WDT module. Valid values are: + * - \ref WDT_TIMEOUT_2POW4 + * - \ref WDT_TIMEOUT_2POW6 + * - \ref WDT_TIMEOUT_2POW8 + * - \ref WDT_TIMEOUT_2POW10 + * - \ref WDT_TIMEOUT_2POW12 + * - \ref WDT_TIMEOUT_2POW14 + * - \ref WDT_TIMEOUT_2POW16 + * - \ref WDT_TIMEOUT_2POW18 + * @param[in] u32ResetDelay Configure WDT time-out reset delay period. Valid values are: + * - \ref WDT_RESET_DELAY_1026CLK + * - \ref WDT_RESET_DELAY_130CLK + * - \ref WDT_RESET_DELAY_18CLK + * - \ref WDT_RESET_DELAY_3CLK + * @param[in] u32EnableReset Enable WDT time-out reset system function. Valid values are TRUE and FALSE. + * @param[in] u32EnableWakeup Enable WDT time-out wake-up system function. Valid values are TRUE and FALSE. + * + * @return None + * + * @details This function makes WDT module start counting with different time-out interval, reset delay period and choose to \n + * enable or disable WDT time-out reset system or wake-up system. + * @note Please make sure that Register Write-Protection Function has been disabled before using this function. + */ +void WDT_Open(UINT32 u32TimeoutInterval, + UINT32 u32ResetDelay, + UINT32 u32EnableReset, + UINT32 u32EnableWakeup) +{ + + outpw(REG_WDT_ALTCTL, u32ResetDelay); + outpw(REG_WDT_CTL, u32TimeoutInterval | 0x80 | + (u32EnableReset << 1) | + (u32EnableWakeup << 4)); + return; +} + +/*@}*/ /* end of group WDT_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group WDT_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_wwdt.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_wwdt.c new file mode 100644 index 0000000000..56eafed69d --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_wwdt.c @@ -0,0 +1,72 @@ +/**************************************************************************//** + * @file wwdt.c + * @brief N9H30 WWDT driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "N9H30.h" +#include "nu_sys.h" +#include "nu_wwdt.h" + +/** @addtogroup N9H30_Device_Driver N9H30 Device Driver + @{ +*/ + +/** @addtogroup N9H30_WWDT_Driver WWDT Driver + @{ +*/ + + +/** @addtogroup N9H30_WWDT_EXPORTED_FUNCTIONS WWDT Exported Functions + @{ +*/ + + +/** + * @brief This function make WWDT module start counting with different counter period and compared window value + * @param[in] u32PreScale Prescale period for the WWDT counter period. Valid values are: + * - \ref WWDT_PRESCALER_1 + * - \ref WWDT_PRESCALER_2 + * - \ref WWDT_PRESCALER_4 + * - \ref WWDT_PRESCALER_8 + * - \ref WWDT_PRESCALER_16 + * - \ref WWDT_PRESCALER_32 + * - \ref WWDT_PRESCALER_64 + * - \ref WWDT_PRESCALER_128 + * - \ref WWDT_PRESCALER_192 + * - \ref WWDT_PRESCALER_256 + * - \ref WWDT_PRESCALER_384 + * - \ref WWDT_PRESCALER_512 + * - \ref WWDT_PRESCALER_768 + * - \ref WWDT_PRESCALER_1024 + * - \ref WWDT_PRESCALER_1536 + * - \ref WWDT_PRESCALER_2048 + * @param[in] u32CmpValue Window compared value. Valid values are between 0x0 to 0x3F + * @param[in] u32EnableInt Enable WWDT interrupt or not. Valid values are \ref TRUE and \ref FALSE + * @return None + * @note Application can call this function can only once after boot up + */ +void WWDT_Open(UINT u32PreScale, UINT u32CmpValue, UINT u32EnableInt) +{ + UINT reg; + reg = u32PreScale | + (u32CmpValue << 16) | + 0x1 | // enable + (u32EnableInt ? 0x2 : 0); + outpw(REG_WWDT_CTL, reg); + + return; +} + + + + +/*@}*/ /* end of group N9H30_WWDT_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group N9H30_WWDT_Driver */ + +/*@}*/ /* end of group N9H30_Device_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/README.md b/bsp/nuvoton/libraries/n9h30/README.md new file mode 100644 index 0000000000..a0e0561d75 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/README.md @@ -0,0 +1,32 @@ +# N9H30 Series + +## Supported drivers + +| Peripheral | rt_device_class_type | Device name | +| ------ | ---- | :------: | +| ADC | RT_Device_Class_Miscellaneous (ADC) | ***adc*** | +| ADC_TOUCH | RT_Device_Class_Touch | ***adc_touch*** | +| CAN | RT_Device_Class_CAN | ***can[0-1]*** | +| CRYPTO | RT_Device_Class_Miscellaneous (HW Crypto) | ***hwcryto*** | +| EMAC | RT_Device_Class_NetIf | ***e[0-1]*** | +| ETIMER | RT_Device_Class_Timer | ***etimer[0-3]*** | +| ETIMER_CAPTURE | RT_Device_Class_Miscellaneous(inputcapture) | ***etmr[0-3]i0*** | +| GE2D | N/A | ***N/A*** | +| GPIO | RT_Device_Class_Miscellaneous (Pin) | ***gpio*** | +| I2C | RT_Device_Class_I2CBUS | ***i2c[0-1]*** | +| I2S | RT_Device_Class_Sound | ***sound0*** | +| JPEGCODEC | N/A | ***N/A*** | +| PWM | RT_Device_Class_Miscellaneous (PWM) | ***pwm0*** | +| QSPI | RT_Device_Class_SPIBUS | ***qspi[0-1]*** | +| RTC | RT_Device_Class_RTC | ***rtc*** | +| SC (UART function) | RT_Device_Class_Char | ***scuart[0-1]*** | +| SDH | RT_Device_Class_Block | ***sdh[0-1]*** | +| SOFTI2C | RT_Device_Class_I2CBUS | ***softi2c[0-1]*** | +| SYS | N/A | ***N/A*** | +| SYSTICK | N/A | ***N/A*** | +| TIMER | RT_Device_Class_Timer | ***timer[0-3]*** | +| UART | RT_Device_Class_Char | ***uart[0-9]*** | +| USBD | RT_Device_Class_USBDevice | ***usbd*** | +| USBHOST | RT_Device_Class_USBHost | ***usbh*** | +| VPOST | RT_Device_Class_Graphic | ***lcd,osd*** | +| WDT | RT_Device_Class_Miscellaneous (Watchdog) | ***wdt*** | diff --git a/bsp/nuvoton/libraries/n9h30/SConscript b/bsp/nuvoton/libraries/n9h30/SConscript new file mode 100644 index 0000000000..c7ef7659ec --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/SConscript @@ -0,0 +1,14 @@ +# for module compiling +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/SConscript b/bsp/nuvoton/libraries/n9h30/UsbHostLib/SConscript new file mode 100644 index 0000000000..6bcad4b630 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/SConscript @@ -0,0 +1,12 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +group = [] +if GetDepend('BSP_USING_HSUSBH') or GetDepend('BSP_USING_USBH'): + src = Glob('*src/*.c') + Glob('src/*.cpp') + CPPPATH = [cwd + '/inc'] + group = DefineGroup('n9h30_usbhostlib', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/config.h b/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/config.h new file mode 100644 index 0000000000..be7c96dade --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/config.h @@ -0,0 +1,1524 @@ +/**************************************************************************//** + * @file config.h + * @version V1.00 + * @brief This header file defines the configuration of USB Host library. + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ + +#ifndef _USBH_CONFIG_H_ +#define _USBH_CONFIG_H_ + + +/// @cond HIDDEN_SYMBOLS + +#include +#include "N9H30.h" +#include "nu_sys.h" +#include "drv_sys.h" + + +/*----------------------------------------------------------------------------------------*/ +/* Hardware settings */ +/*----------------------------------------------------------------------------------------*/ +#define HCLK_MHZ 300 /* used for loop-delay. must be larger than + true HCLK clock MHz */ + +#define NON_CACHE_MASK (0x80000000) + +#define ENABLE_OHCI_IRQ() rt_hw_interrupt_umask(IRQ_OHCI) +#define DISABLE_OHCI_IRQ() rt_hw_interrupt_mask(IRQ_OHCI) +#define IS_OHCI_IRQ_ENABLED() ((inpw(REG_AIC_IMR)>>OHCI_IRQn) & 0x1) +#define ENABLE_EHCI_IRQ() rt_hw_interrupt_umask(IRQ_EHCI) +#define DISABLE_EHCI_IRQ() rt_hw_interrupt_mask(IRQ_EHCI) +#define IS_EHCI_IRQ_ENABLED() ((inpw(REG_AIC_IMR)>>EHCI_IRQn) & 0x1) + +#define ENABLE_OHCI /* Enable OHCI host controller */ +#define ENABLE_EHCI /* Enable EHCI host controller */ + +#define EHCI_PORT_CNT 2 /* Number of EHCI roothub ports */ +#define OHCI_PORT_CNT 2 /* Number of OHCI roothub ports */ +//#define OHCI_PER_PORT_POWER /* OHCI root hub per port powered */ + +#define OHCI_ISO_DELAY 4 /* preserved number frames while scheduling + OHCI isochronous transfer */ + +#define EHCI_ISO_DELAY 2 /* preserved number of frames while + scheduling EHCI isochronous transfer */ + +#define EHCI_ISO_RCLM_RANGE 32 /* When inspecting activated iTD/siTD, + unconditionally reclaim iTD/isTD scheduled + in just elapsed EHCI_ISO_RCLM_RANGE ms. */ + +#define MAX_DESC_BUFF_SIZE 4096 /* To hold the configuration descriptor, USB + core will allocate a buffer with this size + for each connected device. USB core does + not release it until device disconnected. */ + +/*----------------------------------------------------------------------------------------*/ +/* Memory allocation settings */ +/*----------------------------------------------------------------------------------------*/ + +#define STATIC_MEMORY_ALLOC 0 /* pre-allocate static memory blocks. No dynamic memory aloocation. + But the maximum number of connected devices and transfers are + limited. */ + +#define MAX_UDEV_DRIVER 8 /*!< Maximum number of registered drivers */ +#define MAX_ALT_PER_IFACE 12 /*!< maximum number of alternative interfaces per interface */ +#define MAX_EP_PER_IFACE 8 /*!< maximum number of endpoints per interface */ +#define MAX_HUB_DEVICE 8 /*!< Maximum number of hub devices */ + +/* Host controller hardware transfer descriptors memory pool. ED/TD/ITD of OHCI and QH/QTD of EHCI + are all allocated from this pool. Allocated unit size is determined by MEM_POOL_UNIT_SIZE. + May allocate one or more units depend on hardware descriptor type. */ + +#define MEM_POOL_UNIT_SIZE 128 /*!< A fixed hard coding setting. Do not change it! */ +#define MEM_POOL_UNIT_NUM 256 /*!< Increase this or heap size if memory allocate failed. */ + +/*----------------------------------------------------------------------------------------*/ +/* Re-defined staff for various compiler */ +/*----------------------------------------------------------------------------------------*/ +#ifdef __ICCARM__ + #define __inline inline +#endif + + +/*----------------------------------------------------------------------------------------*/ +/* Debug settings */ +/*----------------------------------------------------------------------------------------*/ +#define ENABLE_ERROR_MSG /* enable debug messages */ +#define ENABLE_DEBUG_MSG /* enable debug messages */ +//#define ENABLE_VERBOSE_DEBUG /* verbos debug messages */ +//#define DUMP_DESCRIPTOR /* dump descriptors */ + +#ifdef ENABLE_ERROR_MSG + #define USB_error rt_kprintf +#else + #define USB_error(...) +#endif + +#ifdef ENABLE_DEBUG_MSG + #define USB_debug rt_kprintf + #ifdef ENABLE_VERBOSE_DEBUG + #define USB_vdebug rt_kprintf + #else + #define USB_vdebug(...) + #endif +#else + #define USB_debug(...) + #define USB_vdebug(...) +#endif + + +#define __I volatile const /*!< Defines 'read only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + + +//typedef unsigned int uint32_t; +//typedef unsigned short uint16_t; +//typedef unsigned char uint8_t; + + + +/*---------------------- USB Host Controller -------------------------*/ +/** + @addtogroup USBH USB Host Controller(USBH) + Memory Mapped Structure for USBH Controller +@{ */ + +typedef struct +{ + + /** + * @var USBH_T::HcRevision + * Offset: 0x00 Host Controller Revision Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |REV |Revision Number + * | | |Indicates the Open HCI Specification revision number implemented by the Hardware + * | | |Host Controller supports 1.1 specification. + * | | |(X.Y = XYh). + * @var USBH_T::HcControl + * Offset: 0x04 Host Controller Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |CBSR |Control Bulk Service Ratio + * | | |This specifies the service ratio between Control and Bulk EDs + * | | |Before processing any of the non-periodic lists, HC must compare the ratio specified with its internal count on how many nonempty Control EDs have been processed, in determining whether to continue serving another Control ED or switching to Bulk EDs + * | | |The internal count will be retained when crossing the frame boundary + * | | |In case of reset, HCD is responsible for restoring this + * | | |Value. + * | | |00 = Number of Control EDs over Bulk EDs served is 1:1. + * | | |01 = Number of Control EDs over Bulk EDs served is 2:1. + * | | |10 = Number of Control EDs over Bulk EDs served is 3:1. + * | | |11 = Number of Control EDs over Bulk EDs served is 4:1. + * |[2] |PLE |Periodic List Enable Bit + * | | |When set, this bit enables processing of the Periodic (interrupt and isochronous) list + * | | |The Host Controller checks this bit prior to attempting any periodic transfers in a frame. + * | | |0 = Processing of the Periodic (Interrupt and Isochronous) list after next SOF (Start-Of-Frame) Disabled. + * | | |1 = Processing of the Periodic (Interrupt and Isochronous) list in the next frame Enabled. + * | | |Note: To enable the processing of the Isochronous list, user has to set both PLE and IE (HcControl[3]) high. + * |[3] |IE |Isochronous List Enable Bit + * | | |Both ISOEn and PLE (HcControl[2]) high enables Host Controller to process the Isochronous list + * | | |Either ISOEn or PLE (HcControl[2]) is low disables Host Controller to process the Isochronous list. + * | | |0 = Processing of the Isochronous list after next SOF (Start-Of-Frame) Disabled. + * | | |1 = Processing of the Isochronous list in the next frame Enabled, if the PLE (HcControl[2]) is high, too. + * |[4] |CLE |Control List Enable Bit + * | | |0 = Processing of the Control list after next SOF (Start-Of-Frame) Disabled. + * | | |1 = Processing of the Control list in the next frame Enabled. + * |[5] |BLE |Bulk List Enable Bit + * | | |0 = Processing of the Bulk list after next SOF (Start-Of-Frame) Disabled. + * | | |1 = Processing of the Bulk list in the next frame Enabled. + * |[7:6] |HCFS |Host Controller Functional State + * | | |This field sets the Host Controller state + * | | |The Controller may force a state change from USBSUSPEND to USBRESUME after detecting resume signaling from a downstream port + * | | |States are: + * | | |00 = USBSUSPEND. + * | | |01 = USBOPERATIONAL. + * | | |10 = USBRESUME. + * | | |11 = USBRESET. + * @var USBH_T::HcCommandStatus + * Offset: 0x08 Host Controller Command Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |HCR |Host Controller Reset + * | | |This bit is set to initiate the software reset of Host Controller + * | | |This bit is cleared by the Host Controller, upon completed of the reset operation. + * | | |This bit, when set, didn't reset the Root Hub and no subsequent reset signaling be asserted to its downstream ports. + * | | |0 = Host Controller is not in software reset state. + * | | |1 = Host Controller is in software reset state. + * |[1] |CLF |Control List Filled + * | | |Set high to indicate there is an active TD on the Control List + * | | |It may be set by either software or the Host Controller and cleared by the Host Controller each time it begins processing the head of the Control List. + * | | |0 = No active TD found or Host Controller begins to process the head of the Control list. + * | | |1 = An active TD added or found on the Control list. + * |[2] |BLF |Bulk List Filled + * | | |Set high to indicate there is an active TD on the Bulk list + * | | |This bit may be set by either software or the Host Controller and cleared by the Host Controller each time it begins processing the head of the Bulk list. + * | | |0 = No active TD found or Host Controller begins to process the head of the Bulk list. + * | | |1 = An active TD added or found on the Bulk list. + * |[17:16] |SOC |Schedule Overrun Count + * | | |These bits are incremented on each scheduling overrun error + * | | |It is initialized to 00b and wraps around at 11b + * | | |This will be incremented when a scheduling overrun is detected even if SO (HcInterruptStatus[0]) has already been set. + * @var USBH_T::HcInterruptStatus + * Offset: 0x0C Host Controller Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SO |Scheduling Overrun + * | | |Set when the List Processor determines a Schedule Overrun has occurred. + * | | |0 = Schedule Overrun didn't occur. + * | | |1 = Schedule Overrun has occurred. + * |[1] |WDH |Write Back Done Head + * | | |Set after the Host Controller has written HcDoneHead to HccaDoneHead + * | | |Further updates of the HccaDoneHead will not occur until this bit has been cleared. + * | | |0 =.Host Controller didn't update HccaDoneHead. + * | | |1 =.Host Controller has written HcDoneHead to HccaDoneHead. + * |[2] |SF |Start of Frame + * | | |Set when the Frame Management functional block signals a 'Start of Frame' event + * | | |Host Control generates a SOF token at the same time. + * | | |0 =.Not the start of a frame. + * | | |1 =.Indicate the start of a frame and Host Controller generates a SOF token. + * |[3] |RD |Resume Detected + * | | |Set when Host Controller detects resume signaling on a downstream port. + * | | |0 = No resume signaling detected on a downstream port. + * | | |1 = Resume signaling detected on a downstream port. + * |[5] |FNO |Frame Number Overflow + * | | |This bit is set when bit 15 of Frame Number changes from 1 to 0 or from 0 to 1. + * | | |0 = The bit 15 of Frame Number didn't change. + * | | |1 = The bit 15 of Frame Number changes from 1 to 0 or from 0 to 1. + * |[6] |RHSC |Root Hub Status Change + * | | |This bit is set when the content of HcRhStatus or the content of HcRhPortStatus register has changed. + * | | |0 = The content of HcRhStatus and the content of HcRhPortStatus register didn't change. + * | | |1 = The content of HcRhStatus or the content of HcRhPortStatus register has changed. + * @var USBH_T::HcInterruptEnable + * Offset: 0x10 Host Controller Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SO |Scheduling Overrun Enable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to SO (HcInterruptStatus[0]) Enabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to SO (HcInterruptStatus[0]) Disabled. + * | | |1 = Interrupt generation due to SO (HcInterruptStatus[0]) Enabled. + * |[1] |WDH |Write Back Done Head Enable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to WDH (HcInterruptStatus[1]) Enabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to WDH (HcInterruptStatus[1]) Disabled. + * | | |1 = Interrupt generation due to WDH (HcInterruptStatus[1]) Enabled. + * |[2] |SF |Start of Frame Enable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to SF (HcInterruptStatus[2]) Enabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to SF (HcInterruptStatus[2]) Disabled. + * | | |1 = Interrupt generation due to SF (HcInterruptStatus[2]) Enabled. + * |[3] |RD |Resume Detected Enable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to RD (HcInterruptStatus[3]) Enabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to RD (HcInterruptStatus[3]) Disabled. + * | | |1 = Interrupt generation due to RD (HcInterruptStatus[3]) Enabled. + * |[5] |FNO |Frame Number Overflow Enable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to FNO (HcInterruptStatus[5]) Enabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to FNO (HcInterruptStatus[5]) Disabled. + * | | |1 = Interrupt generation due to FNO (HcInterruptStatus[5]) Enabled. + * |[6] |RHSC |Root Hub Status Change Enable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to RHSC (HcInterruptStatus[6]) Enabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to RHSC (HcInterruptStatus[6]) Disabled. + * | | |1 = Interrupt generation due to RHSC (HcInterruptStatus[6]) Enabled. + * |[31] |MIE |Master Interrupt Enable Bit + * | | |This bit is a global interrupt enable + * | | |A write of '1' allows interrupts to be enabled via the specific enable bits listed above. + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to RHSC (HcInterruptStatus[6]), FNO (HcInterruptStatus[5]), RD (HcInterruptStatus[3]), SF (HcInterruptStatus[2]), WDH (HcInterruptStatus[1]) or SO (HcInterruptStatus[0]) Enabled if the corresponding bit in HcInterruptEnable is high. + * | | |Read Operation: + * | | |0 = Interrupt generation due to RHSC (HcInterruptStatus[6]), FNO (HcInterruptStatus[5]), RD (HcInterruptStatus[3]), SF (HcInterruptStatus[2]), WDH (HcInterruptStatus[1]) or SO (HcInterruptStatus[0]) Disabled even if the corresponding bit in HcInterruptEnable is high. + * | | |1 = Interrupt generation due to RHSC (HcInterruptStatus[6]), FNO (HcInterruptStatus[5]), RD (HcInterruptStatus[3]), SF (HcInterruptStatus[2]), WDH (HcInterruptStatus[1]) or SO (HcInterruptStatus[0]) Enabled if the corresponding bit in HcInterruptEnable is high. + * @var USBH_T::HcInterruptDisable + * Offset: 0x14 Host Controller Interrupt Disable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SO |Scheduling Overrun Disable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to SO (HcInterruptStatus[0]) Disabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to SO (HcInterruptStatus[0]) Disabled. + * | | |1 = Interrupt generation due to SO (HcInterruptStatus[0]) Enabled. + * |[1] |WDH |Write Back Done Head Disable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to WDH (HcInterruptStatus[1]) Disabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to WDH (HcInterruptStatus[1]) Disabled. + * | | |1 = Interrupt generation due to WDH (HcInterruptStatus[1]) Enabled. + * |[2] |SF |Start of Frame Disable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to SF (HcInterruptStatus[2]) Disabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to SF (HcInterruptStatus[2]) Disabled. + * | | |1 = Interrupt generation due to SF (HcInterruptStatus[2]) Enabled. + * |[3] |RD |Resume Detected Disable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to RD (HcInterruptStatus[3]) Disabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to RD (HcInterruptStatus[3]) Disabled. + * | | |1 = Interrupt generation due to RD (HcInterruptStatus[3]) Enabled. + * |[5] |FNO |Frame Number Overflow Disable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to FNO (HcInterruptStatus[5]) Disabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to FNO (HcInterruptStatus[5]) Disabled. + * | | |1 = Interrupt generation due to FNO (HcInterruptStatus[5]) Enabled. + * |[6] |RHSC |Root Hub Status Change Disable Bit + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to RHSC (HcInterruptStatus[6]) Disabled. + * | | |Read Operation: + * | | |0 = Interrupt generation due to RHSC (HcInterruptStatus[6]) Disabled. + * | | |1 = Interrupt generation due to RHSC (HcInterruptStatus[6]) Enabled. + * |[31] |MIE |Master Interrupt Disable Bit + * | | |Global interrupt disable. Writing '1' to disable all interrupts. + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Interrupt generation due to RHSC (HcInterruptStatus[6]), FNO (HcInterruptStatus[5]), RD (HcInterruptStatus[3]), SF (HcInterruptStatus[2]), WDH (HcInterruptStatus[1]) or SO (HcInterruptStatus[0]) Disabled if the corresponding bit in HcInterruptEnable is high. + * | | |Read Operation: + * | | |0 = Interrupt generation due to RHSC (HcInterruptStatus[6]), FNO (HcInterruptStatus[5]), RD (HcInterruptStatus[3]), SF (HcInterruptStatus[2]), WDH (HcInterruptStatus[1]) or SO (HcInterruptStatus[0]) Disabled even if the corresponding bit in HcInterruptEnable is high. + * | | |1 = Interrupt generation due to RHSC (HcInterruptStatus[6]), FNO (HcInterruptStatus[5]), RD (HcInterruptStatus[3]), SF (HcInterruptStatus[2]), WDH (HcInterruptStatus[1]) or SO (HcInterruptStatus[0]) Enabled if the corresponding bit in HcInterruptEnable is high. + * @var USBH_T::HcHCCA + * Offset: 0x18 Host Controller Communication Area Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:8] |HCCA |Host Controller Communication Area + * | | |Pointer to indicate base address of the Host Controller Communication Area (HCCA). + * @var USBH_T::HcPeriodCurrentED + * Offset: 0x1C Host Controller Period Current ED Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:4] |PCED |Periodic Current ED + * | | |Pointer to indicate physical address of the current Isochronous or Interrupt Endpoint Descriptor. + * @var USBH_T::HcControlHeadED + * Offset: 0x20 Host Controller Control Head ED Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:4] |CHED |Control Head ED + * | | |Pointer to indicate physical address of the first Endpoint Descriptor of the Control list. + * @var USBH_T::HcControlCurrentED + * Offset: 0x24 Host Controller Control Current ED Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:4] |CCED |Control Current Head ED + * | | |Pointer to indicate the physical address of the current Endpoint Descriptor of the Control list. + * @var USBH_T::HcBulkHeadED + * Offset: 0x28 Host Controller Bulk Head ED Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:4] |BHED |Bulk Head ED + * | | |Pointer to indicate the physical address of the first Endpoint Descriptor of the Bulk list. + * @var USBH_T::HcBulkCurrentED + * Offset: 0x2C Host Controller Bulk Current ED Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:4] |BCED |Bulk Current Head ED + * | | |Pointer to indicate the physical address of the current endpoint of the Bulk list. + * @var USBH_T::HcDoneHead + * Offset: 0x30 Host Controller Done Head Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:4] |DH |Done Head + * | | |Pointer to indicate the physical address of the last completed Transfer Descriptor that was added to the Done queue. + * @var USBH_T::HcFmInterval + * Offset: 0x34 Host Controller Frame Interval Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[13:0] |FI |Frame Interval + * | | |This field specifies the length of a frame as (bit times - 1) + * | | |For 12,000 bit times in a frame, a value of 11,999 is stored here. + * |[30:16] |FSMPS |FS Largest Data Packet + * | | |This field specifies a value that is loaded into the Largest Data Packet Counter at the beginning of each frame. + * |[31] |FIT |Frame Interval Toggle + * | | |This bit is toggled by Host Controller Driver when it loads a new value into FI (HcFmInterval[13:0]). + * | | |0 = Host Controller Driver didn't load new value into FI (HcFmInterval[13:0]). + * | | |1 = Host Controller Driver loads a new value into FI (HcFmInterval[13:0]). + * @var USBH_T::HcFmRemaining + * Offset: 0x38 Host Controller Frame Remaining Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[13:0] |FR |Frame Remaining + * | | |When the Host Controller is in the USBOPERATIONAL state, this 14-bit field decrements each 12 MHz clock period + * | | |When the count reaches 0, (end of frame) the counter reloads with Frame Interval + * | | |In addition, the counter loads when the Host Controller transitions into USBOPERATIONAL. + * |[31] |FRT |Frame Remaining Toggle + * | | |This bit is loaded from the FIT (HcFmInterval[31]) whenever FR (HcFmRemaining[13:0]) reaches 0. + * @var USBH_T::HcFmNumber + * Offset: 0x3C Host Controller Frame Number Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |FN |Frame Number + * | | |This 16-bit incrementing counter field is incremented coincident with the re-load of FR (HcFmRemaining[13:0]) + * | | |The count rolls over from 'FFFFh' to '0h.' + * @var USBH_T::HcPeriodicStart + * Offset: 0x40 Host Controller Periodic Start Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[13:0] |PS |Periodic Start + * | | |This field contains a value used by the List Processor to determine where in a frame the Periodic List processing must begin. + * @var USBH_T::HcLSThreshold + * Offset: 0x44 Host Controller Low-speed Threshold Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[11:0] |LST |Low-speed Threshold + * | | |This field contains a value which is compared to the FR (HcFmRemaining[13:0]) field prior to initiating a Low-speed transaction + * | | |The transaction is started only if FR (HcFmRemaining[13:0]) >= this field + * | | |The value is calculated by Host Controller Driver with the consideration of transmission and setup overhead. + * @var USBH_T::HcRhDescriptorA + * Offset: 0x48 Host Controller Root Hub Descriptor A Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |NDP |Number Downstream Ports + * | | |USB host control supports two downstream ports and only one port is available in this series of chip. + * |[8] |PSM |Power Switching Mode + * | | |This bit is used to specify how the power switching of the Root Hub ports is controlled. + * | | |0 = Global Switching. + * | | |1 = Individual Switching. + * |[11] |OCPM |over Current Protection Mode + * | | |This bit describes how the over current status for the Root Hub ports reported + * | | |This bit is only valid when NOCP (HcRhDescriptorA[12]) is cleared. + * | | |0 = Global Over current. + * | | |1 = Individual Over current. + * |[12] |NOCP |No over Current Protection + * | | |This bit describes how the over current status for the Root Hub ports reported. + * | | |0 = Over current status is reported. + * | | |1 = Over current status is not reported. + * @var USBH_T::HcRhDescriptorB + * Offset: 0x4C Host Controller Root Hub Descriptor B Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:16] |PPCM |Port Power Control Mask + * | | |Global power switching + * | | |This field is only valid if PowerSwitchingMode is set (individual port switching) + * | | |When set, the port only responds to individual port power switching commands (Set/ClearPortPower) + * | | |When cleared, the port only responds to global power switching commands (Set/ClearGlobalPower). + * | | |0 = Port power controlled by global power switching. + * | | |1 = Port power controlled by port power switching. + * | | |Note: PPCM[15:2] and PPCM[0] are reserved. + * @var USBH_T::HcRhStatus + * Offset: 0x50 Host Controller Root Hub Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |LPS |Clear Global Power + * | | |In global power mode (PSM (HcRhDescriptorA[8]) = 0), this bit is written to one to clear all ports' power. + * | | |This bit always read as zero. + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Clear global power. + * |[1] |OCI |over Current Indicator + * | | |This bit reflects the state of the over current status pin + * | | |This field is only valid if NOCP (HcRhDesA[12]) and OCPM (HcRhDesA[11]) are cleared. + * | | |0 = No over current condition. + * | | |1 = Over current condition. + * |[15] |DRWE |Device Remote Wakeup Enable Bit + * | | |This bit controls if port's Connect Status Change as a remote wake-up event. + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Connect Status Change as a remote wake-up event Enabled. + * | | |Read Operation: + * | | |0 = Connect Status Change as a remote wake-up event Disabled. + * | | |1 = Connect Status Change as a remote wake-up event Enabled. + * |[16] |LPSC |Set Global Power + * | | |In global power mode (PSM (HcRhDescriptorA[8]) = 0), this bit is written to one to enable power to all ports. + * | | |This bit always read as zero. + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Set global power. + * |[17] |OCIC |over Current Indicator Change + * | | |This bit is set by hardware when a change has occurred in OCI (HcRhStatus[1]). + * | | |Write 1 to clear this bit to zero. + * | | |0 = OCI (HcRhStatus[1]) didn't change. + * | | |1 = OCI (HcRhStatus[1]) change. + * |[31] |CRWE |Clear Remote Wake-up Enable Bit + * | | |This bit is use to clear DRWE (HcRhStatus[15]). + * | | |This bit always read as zero. + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Clear DRWE (HcRhStatus[15]). + * @var USBH_T::HcRhPortStatus[2] + * Offset: 0x54 Host Controller Root Hub Port Status + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CCS |CurrentConnectStatus (Read) or ClearPortEnable Bit (Write) + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Clear port enable. + * | | |Read Operation: + * | | |0 = No device connected. + * | | |1 = Device connected. + * |[1] |PES |Port Enable Status + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Set port enable. + * | | |Read Operation: + * | | |0 = Port Disabled. + * | | |1 = Port Enabled. + * |[2] |PSS |Port Suspend Status + * | | |This bit indicates the port is suspended + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Set port suspend. + * | | |Read Operation: + * | | |0 = Port is not suspended. + * | | |1 = Port is selectively suspended. + * |[3] |POCI |Port over Current Indicator (Read) or Clear Port Suspend (Write) + * | | |This bit reflects the state of the over current status pin dedicated to this port + * | | |This field is only valid if NOCP (HcRhDescriptorA[12]) is cleared and OCPM (HcRhDescriptorA[11]) is set. + * | | |This bit is also used to initiate the selective result sequence for the port. + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Clear port suspend. + * | | |Read Operation: + * | | |0 = No over current condition. + * | | |1 = Over current condition. + * |[4] |PRS |Port Reset Status + * | | |This bit reflects the reset state of the port. + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Set port reset. + * | | |Read Operation + * | | |0 = Port reset signal is not active. + * | | |1 = Port reset signal is active. + * |[8] |PPS |Port Power Status + * | | |This bit reflects the power state of the port regardless of the power switching mode. + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Port Power Enabled. + * | | |Read Operation: + * | | |0 = Port power is Disabled. + * | | |1 = Port power is Enabled. + * |[9] |LSDA |Low Speed Device Attached (Read) or Clear Port Power (Write) + * | | |This bit defines the speed (and bud idle) of the attached device + * | | |It is only valid when CCS (HcRhPortStatus1[0]) is set. + * | | |This bit is also used to clear port power. + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Clear PPS (HcRhPortStatus1[8]). + * | | |Read Operation: + * | | |0 = Full Speed device. + * | | |1 = Low-speed device. + * |[16] |CSC |Connect Status Change + * | | |This bit indicates connect or disconnect event has been detected (CCS (HcRhPortStatus1[0]) changed). + * | | |Write 1 to clear this bit to zero. + * | | |0 = No connect/disconnect event (CCS (HcRhPortStatus1[0]) didn't change). + * | | |1 = Hardware detection of connect/disconnect event (CCS (HcRhPortStatus1[0]) changed). + * |[17] |PESC |Port Enable Status Change + * | | |This bit indicates that the port has been disabled (PES (HcRhPortStatus1[1]) cleared) due to a hardware event. + * | | |Write 1 to clear this bit to zero. + * | | |0 = PES (HcRhPortStatus1[1]) didn't change. + * | | |1 = PES (HcRhPortStatus1[1]) changed. + * |[18] |PSSC |Port Suspend Status Change + * | | |This bit indicates the completion of the selective resume sequence for the port. + * | | |Write 1 to clear this bit to zero. + * | | |0 = Port resume is not completed. + * | | |1 = Port resume completed. + * |[19] |OCIC |Port over Current Indicator Change + * | | |This bit is set when POCI (HcRhPortStatus1[3]) changes. + * | | |Write 1 to clear this bit to zero. + * | | |0 = POCI (HcRhPortStatus1[3]) didn't change. + * | | |1 = POCI (HcRhPortStatus1[3]) changes. + * |[20] |PRSC |Port Reset Status Change + * | | |This bit indicates that the port reset signal has completed. + * | | |Write 1 to clear this bit to zero. + * | | |0 = Port reset is not complete. + * | | |1 = Port reset is complete. + * @var USBH_T::HcPhyControl + * Offset: 0x200 Host Controller PHY Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[27] |STBYEN |USB Transceiver Standby Enable Bit + * | | |This bit controls if USB transceiver could enter the standby mode to reduce power consumption. + * | | |0 = The USB transceiver would never enter the standby mode. + * | | |1 = The USB transceiver will enter standby mode while port is in power off state (port power is inactive). + * @var USBH_T::HcMiscControl + * Offset: 0x204 Host Controller Miscellaneous Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |ABORT |AHB Bus ERROR Response + * | | |This bit indicates there is an ERROR response received in AHB bus. + * | | |0 = No ERROR response received. + * | | |1 = ERROR response received. + * |[3] |OCAL |over Current Active Low + * | | |This bit controls the polarity of over current flag from external power IC. + * | | |0 = Over current flag is high active. + * | | |1 = Over current flag is low active. + * |[16] |DPRT1 |Disable Port 1 + * | | |This bit controls if the connection between USB host controller and transceiver of port 1 is disabled + * | | |If the connection is disabled, the USB host controller will not recognize any event of USB bus. + * | | |Set this bit high, the transceiver of port 1 will also be forced into the standby mode no matter what USB host controller operation is. + * | | |0 = The connection between USB host controller and transceiver of port 1 Enabled. + * | | |1 = The connection between USB host controller and transceiver of port 1 Disabled and the transceiver of port 1 will also be forced into the standby mode. + */ + __I uint32_t HcRevision; /*!< [0x0000] Host Controller Revision Register */ + __IO uint32_t HcControl; /*!< [0x0004] Host Controller Control Register */ + __IO uint32_t HcCommandStatus; /*!< [0x0008] Host Controller Command Status Register */ + __IO uint32_t HcInterruptStatus; /*!< [0x000c] Host Controller Interrupt Status Register */ + __IO uint32_t HcInterruptEnable; /*!< [0x0010] Host Controller Interrupt Enable Register */ + __IO uint32_t HcInterruptDisable; /*!< [0x0014] Host Controller Interrupt Disable Register */ + __IO uint32_t HcHCCA; /*!< [0x0018] Host Controller Communication Area Register */ + __IO uint32_t HcPeriodCurrentED; /*!< [0x001c] Host Controller Period Current ED Register */ + __IO uint32_t HcControlHeadED; /*!< [0x0020] Host Controller Control Head ED Register */ + __IO uint32_t HcControlCurrentED; /*!< [0x0024] Host Controller Control Current ED Register */ + __IO uint32_t HcBulkHeadED; /*!< [0x0028] Host Controller Bulk Head ED Register */ + __IO uint32_t HcBulkCurrentED; /*!< [0x002c] Host Controller Bulk Current ED Register */ + __IO uint32_t HcDoneHead; /*!< [0x0030] Host Controller Done Head Register */ + __IO uint32_t HcFmInterval; /*!< [0x0034] Host Controller Frame Interval Register */ + __I uint32_t HcFmRemaining; /*!< [0x0038] Host Controller Frame Remaining Register */ + __I uint32_t HcFmNumber; /*!< [0x003c] Host Controller Frame Number Register */ + __IO uint32_t HcPeriodicStart; /*!< [0x0040] Host Controller Periodic Start Register */ + __IO uint32_t HcLSThreshold; /*!< [0x0044] Host Controller Low-speed Threshold Register */ + __IO uint32_t HcRhDescriptorA; /*!< [0x0048] Host Controller Root Hub Descriptor A Register */ + __IO uint32_t HcRhDescriptorB; /*!< [0x004c] Host Controller Root Hub Descriptor B Register */ + __IO uint32_t HcRhStatus; /*!< [0x0050] Host Controller Root Hub Status Register */ + __IO uint32_t HcRhPortStatus[2]; /*!< [0x0054] Host Controller Root Hub Port Status [1] */ + __I uint32_t RESERVE0[105]; + __IO uint32_t HcPhyControl; /*!< [0x0200] Host Controller PHY Control Register */ + __IO uint32_t HcMiscControl; /*!< [0x0204] Host Controller Miscellaneous Control Register */ + +} USBH_T; + +/** + @addtogroup USBH_CONST USBH Bit Field Definition + Constant Definitions for USBH Controller +@{ */ + +#define USBH_HcRevision_REV_Pos (0) /*!< USBH_T::HcRevision: REV Position */ +#define USBH_HcRevision_REV_Msk (0xfful << USBH_HcRevision_REV_Pos) /*!< USBH_T::HcRevision: REV Mask */ + +#define USBH_HcControl_CBSR_Pos (0) /*!< USBH_T::HcControl: CBSR Position */ +#define USBH_HcControl_CBSR_Msk (0x3ul << USBH_HcControl_CBSR_Pos) /*!< USBH_T::HcControl: CBSR Mask */ + +#define USBH_HcControl_PLE_Pos (2) /*!< USBH_T::HcControl: PLE Position */ +#define USBH_HcControl_PLE_Msk (0x1ul << USBH_HcControl_PLE_Pos) /*!< USBH_T::HcControl: PLE Mask */ + +#define USBH_HcControl_IE_Pos (3) /*!< USBH_T::HcControl: IE Position */ +#define USBH_HcControl_IE_Msk (0x1ul << USBH_HcControl_IE_Pos) /*!< USBH_T::HcControl: IE Mask */ + +#define USBH_HcControl_CLE_Pos (4) /*!< USBH_T::HcControl: CLE Position */ +#define USBH_HcControl_CLE_Msk (0x1ul << USBH_HcControl_CLE_Pos) /*!< USBH_T::HcControl: CLE Mask */ + +#define USBH_HcControl_BLE_Pos (5) /*!< USBH_T::HcControl: BLE Position */ +#define USBH_HcControl_BLE_Msk (0x1ul << USBH_HcControl_BLE_Pos) /*!< USBH_T::HcControl: BLE Mask */ + +#define USBH_HcControl_HCFS_Pos (6) /*!< USBH_T::HcControl: HCFS Position */ +#define USBH_HcControl_HCFS_Msk (0x3ul << USBH_HcControl_HCFS_Pos) /*!< USBH_T::HcControl: HCFS Mask */ + +#define USBH_HcCommandStatus_HCR_Pos (0) /*!< USBH_T::HcCommandStatus: HCR Position */ +#define USBH_HcCommandStatus_HCR_Msk (0x1ul << USBH_HcCommandStatus_HCR_Pos) /*!< USBH_T::HcCommandStatus: HCR Mask */ + +#define USBH_HcCommandStatus_CLF_Pos (1) /*!< USBH_T::HcCommandStatus: CLF Position */ +#define USBH_HcCommandStatus_CLF_Msk (0x1ul << USBH_HcCommandStatus_CLF_Pos) /*!< USBH_T::HcCommandStatus: CLF Mask */ + +#define USBH_HcCommandStatus_BLF_Pos (2) /*!< USBH_T::HcCommandStatus: BLF Position */ +#define USBH_HcCommandStatus_BLF_Msk (0x1ul << USBH_HcCommandStatus_BLF_Pos) /*!< USBH_T::HcCommandStatus: BLF Mask */ + +#define USBH_HcCommandStatus_SOC_Pos (16) /*!< USBH_T::HcCommandStatus: SOC Position */ +#define USBH_HcCommandStatus_SOC_Msk (0x3ul << USBH_HcCommandStatus_SOC_Pos) /*!< USBH_T::HcCommandStatus: SOC Mask */ + +#define USBH_HcInterruptStatus_SO_Pos (0) /*!< USBH_T::HcInterruptStatus: SO Position */ +#define USBH_HcInterruptStatus_SO_Msk (0x1ul << USBH_HcInterruptStatus_SO_Pos) /*!< USBH_T::HcInterruptStatus: SO Mask */ + +#define USBH_HcInterruptStatus_WDH_Pos (1) /*!< USBH_T::HcInterruptStatus: WDH Position*/ +#define USBH_HcInterruptStatus_WDH_Msk (0x1ul << USBH_HcInterruptStatus_WDH_Pos) /*!< USBH_T::HcInterruptStatus: WDH Mask */ + +#define USBH_HcInterruptStatus_SF_Pos (2) /*!< USBH_T::HcInterruptStatus: SF Position */ +#define USBH_HcInterruptStatus_SF_Msk (0x1ul << USBH_HcInterruptStatus_SF_Pos) /*!< USBH_T::HcInterruptStatus: SF Mask */ + +#define USBH_HcInterruptStatus_RD_Pos (3) /*!< USBH_T::HcInterruptStatus: RD Position */ +#define USBH_HcInterruptStatus_RD_Msk (0x1ul << USBH_HcInterruptStatus_RD_Pos) /*!< USBH_T::HcInterruptStatus: RD Mask */ + +#define USBH_HcInterruptStatus_FNO_Pos (5) /*!< USBH_T::HcInterruptStatus: FNO Position*/ +#define USBH_HcInterruptStatus_FNO_Msk (0x1ul << USBH_HcInterruptStatus_FNO_Pos) /*!< USBH_T::HcInterruptStatus: FNO Mask */ + +#define USBH_HcInterruptStatus_RHSC_Pos (6) /*!< USBH_T::HcInterruptStatus: RHSC Position*/ +#define USBH_HcInterruptStatus_RHSC_Msk (0x1ul << USBH_HcInterruptStatus_RHSC_Pos) /*!< USBH_T::HcInterruptStatus: RHSC Mask */ + +#define USBH_HcInterruptEnable_SO_Pos (0) /*!< USBH_T::HcInterruptEnable: SO Position */ +#define USBH_HcInterruptEnable_SO_Msk (0x1ul << USBH_HcInterruptEnable_SO_Pos) /*!< USBH_T::HcInterruptEnable: SO Mask */ + +#define USBH_HcInterruptEnable_WDH_Pos (1) /*!< USBH_T::HcInterruptEnable: WDH Position*/ +#define USBH_HcInterruptEnable_WDH_Msk (0x1ul << USBH_HcInterruptEnable_WDH_Pos) /*!< USBH_T::HcInterruptEnable: WDH Mask */ + +#define USBH_HcInterruptEnable_SF_Pos (2) /*!< USBH_T::HcInterruptEnable: SF Position */ +#define USBH_HcInterruptEnable_SF_Msk (0x1ul << USBH_HcInterruptEnable_SF_Pos) /*!< USBH_T::HcInterruptEnable: SF Mask */ + +#define USBH_HcInterruptEnable_RD_Pos (3) /*!< USBH_T::HcInterruptEnable: RD Position */ +#define USBH_HcInterruptEnable_RD_Msk (0x1ul << USBH_HcInterruptEnable_RD_Pos) /*!< USBH_T::HcInterruptEnable: RD Mask */ + +#define USBH_HcInterruptEnable_FNO_Pos (5) /*!< USBH_T::HcInterruptEnable: FNO Position*/ +#define USBH_HcInterruptEnable_FNO_Msk (0x1ul << USBH_HcInterruptEnable_FNO_Pos) /*!< USBH_T::HcInterruptEnable: FNO Mask */ + +#define USBH_HcInterruptEnable_RHSC_Pos (6) /*!< USBH_T::HcInterruptEnable: RHSC Position*/ +#define USBH_HcInterruptEnable_RHSC_Msk (0x1ul << USBH_HcInterruptEnable_RHSC_Pos) /*!< USBH_T::HcInterruptEnable: RHSC Mask */ + +#define USBH_HcInterruptEnable_MIE_Pos (31) /*!< USBH_T::HcInterruptEnable: MIE Position*/ +#define USBH_HcInterruptEnable_MIE_Msk (0x1ul << USBH_HcInterruptEnable_MIE_Pos) /*!< USBH_T::HcInterruptEnable: MIE Mask */ + +#define USBH_HcInterruptDisable_SO_Pos (0) /*!< USBH_T::HcInterruptDisable: SO Position*/ +#define USBH_HcInterruptDisable_SO_Msk (0x1ul << USBH_HcInterruptDisable_SO_Pos) /*!< USBH_T::HcInterruptDisable: SO Mask */ + +#define USBH_HcInterruptDisable_WDH_Pos (1) /*!< USBH_T::HcInterruptDisable: WDH Position*/ +#define USBH_HcInterruptDisable_WDH_Msk (0x1ul << USBH_HcInterruptDisable_WDH_Pos) /*!< USBH_T::HcInterruptDisable: WDH Mask */ + +#define USBH_HcInterruptDisable_SF_Pos (2) /*!< USBH_T::HcInterruptDisable: SF Position*/ +#define USBH_HcInterruptDisable_SF_Msk (0x1ul << USBH_HcInterruptDisable_SF_Pos) /*!< USBH_T::HcInterruptDisable: SF Mask */ + +#define USBH_HcInterruptDisable_RD_Pos (3) /*!< USBH_T::HcInterruptDisable: RD Position*/ +#define USBH_HcInterruptDisable_RD_Msk (0x1ul << USBH_HcInterruptDisable_RD_Pos) /*!< USBH_T::HcInterruptDisable: RD Mask */ + +#define USBH_HcInterruptDisable_FNO_Pos (5) /*!< USBH_T::HcInterruptDisable: FNO Position*/ +#define USBH_HcInterruptDisable_FNO_Msk (0x1ul << USBH_HcInterruptDisable_FNO_Pos) /*!< USBH_T::HcInterruptDisable: FNO Mask */ + +#define USBH_HcInterruptDisable_RHSC_Pos (6) /*!< USBH_T::HcInterruptDisable: RHSC Position*/ +#define USBH_HcInterruptDisable_RHSC_Msk (0x1ul << USBH_HcInterruptDisable_RHSC_Pos) /*!< USBH_T::HcInterruptDisable: RHSC Mask */ + +#define USBH_HcInterruptDisable_MIE_Pos (31) /*!< USBH_T::HcInterruptDisable: MIE Position*/ +#define USBH_HcInterruptDisable_MIE_Msk (0x1ul << USBH_HcInterruptDisable_MIE_Pos) /*!< USBH_T::HcInterruptDisable: MIE Mask */ + +#define USBH_HcHCCA_HCCA_Pos (8) /*!< USBH_T::HcHCCA: HCCA Position */ +#define USBH_HcHCCA_HCCA_Msk (0xfffffful << USBH_HcHCCA_HCCA_Pos) /*!< USBH_T::HcHCCA: HCCA Mask */ + +#define USBH_HcPeriodCurrentED_PCED_Pos (4) /*!< USBH_T::HcPeriodCurrentED: PCED Position*/ +#define USBH_HcPeriodCurrentED_PCED_Msk (0xffffffful << USBH_HcPeriodCurrentED_PCED_Pos) /*!< USBH_T::HcPeriodCurrentED: PCED Mask */ + +#define USBH_HcControlHeadED_CHED_Pos (4) /*!< USBH_T::HcControlHeadED: CHED Position */ +#define USBH_HcControlHeadED_CHED_Msk (0xffffffful << USBH_HcControlHeadED_CHED_Pos) /*!< USBH_T::HcControlHeadED: CHED Mask */ + +#define USBH_HcControlCurrentED_CCED_Pos (4) /*!< USBH_T::HcControlCurrentED: CCED Position*/ +#define USBH_HcControlCurrentED_CCED_Msk (0xffffffful << USBH_HcControlCurrentED_CCED_Pos) /*!< USBH_T::HcControlCurrentED: CCED Mask */ + +#define USBH_HcBulkHeadED_BHED_Pos (4) /*!< USBH_T::HcBulkHeadED: BHED Position */ +#define USBH_HcBulkHeadED_BHED_Msk (0xffffffful << USBH_HcBulkHeadED_BHED_Pos) /*!< USBH_T::HcBulkHeadED: BHED Mask */ + +#define USBH_HcBulkCurrentED_BCED_Pos (4) /*!< USBH_T::HcBulkCurrentED: BCED Position */ +#define USBH_HcBulkCurrentED_BCED_Msk (0xffffffful << USBH_HcBulkCurrentED_BCED_Pos) /*!< USBH_T::HcBulkCurrentED: BCED Mask */ + +#define USBH_HcDoneHead_DH_Pos (4) /*!< USBH_T::HcDoneHead: DH Position */ +#define USBH_HcDoneHead_DH_Msk (0xffffffful << USBH_HcDoneHead_DH_Pos) /*!< USBH_T::HcDoneHead: DH Mask */ + +#define USBH_HcFmInterval_FI_Pos (0) /*!< USBH_T::HcFmInterval: FI Position */ +#define USBH_HcFmInterval_FI_Msk (0x3ffful << USBH_HcFmInterval_FI_Pos) /*!< USBH_T::HcFmInterval: FI Mask */ + +#define USBH_HcFmInterval_FSMPS_Pos (16) /*!< USBH_T::HcFmInterval: FSMPS Position */ +#define USBH_HcFmInterval_FSMPS_Msk (0x7ffful << USBH_HcFmInterval_FSMPS_Pos) /*!< USBH_T::HcFmInterval: FSMPS Mask */ + +#define USBH_HcFmInterval_FIT_Pos (31) /*!< USBH_T::HcFmInterval: FIT Position */ +#define USBH_HcFmInterval_FIT_Msk (0x1ul << USBH_HcFmInterval_FIT_Pos) /*!< USBH_T::HcFmInterval: FIT Mask */ + +#define USBH_HcFmRemaining_FR_Pos (0) /*!< USBH_T::HcFmRemaining: FR Position */ +#define USBH_HcFmRemaining_FR_Msk (0x3ffful << USBH_HcFmRemaining_FR_Pos) /*!< USBH_T::HcFmRemaining: FR Mask */ + +#define USBH_HcFmRemaining_FRT_Pos (31) /*!< USBH_T::HcFmRemaining: FRT Position */ +#define USBH_HcFmRemaining_FRT_Msk (0x1ul << USBH_HcFmRemaining_FRT_Pos) /*!< USBH_T::HcFmRemaining: FRT Mask */ + +#define USBH_HcFmNumber_FN_Pos (0) /*!< USBH_T::HcFmNumber: FN Position */ +#define USBH_HcFmNumber_FN_Msk (0xfffful << USBH_HcFmNumber_FN_Pos) /*!< USBH_T::HcFmNumber: FN Mask */ + +#define USBH_HcPeriodicStart_PS_Pos (0) /*!< USBH_T::HcPeriodicStart: PS Position */ +#define USBH_HcPeriodicStart_PS_Msk (0x3ffful << USBH_HcPeriodicStart_PS_Pos) /*!< USBH_T::HcPeriodicStart: PS Mask */ + +#define USBH_HcLSThreshold_LST_Pos (0) /*!< USBH_T::HcLSThreshold: LST Position */ +#define USBH_HcLSThreshold_LST_Msk (0xffful << USBH_HcLSThreshold_LST_Pos) /*!< USBH_T::HcLSThreshold: LST Mask */ + +#define USBH_HcRhDescriptorA_NDP_Pos (0) /*!< USBH_T::HcRhDescriptorA: NDP Position */ +#define USBH_HcRhDescriptorA_NDP_Msk (0xfful << USBH_HcRhDescriptorA_NDP_Pos) /*!< USBH_T::HcRhDescriptorA: NDP Mask */ + +#define USBH_HcRhDescriptorA_PSM_Pos (8) /*!< USBH_T::HcRhDescriptorA: PSM Position */ +#define USBH_HcRhDescriptorA_PSM_Msk (0x1ul << USBH_HcRhDescriptorA_PSM_Pos) /*!< USBH_T::HcRhDescriptorA: PSM Mask */ + +#define USBH_HcRhDescriptorA_OCPM_Pos (11) /*!< USBH_T::HcRhDescriptorA: OCPM Position */ +#define USBH_HcRhDescriptorA_OCPM_Msk (0x1ul << USBH_HcRhDescriptorA_OCPM_Pos) /*!< USBH_T::HcRhDescriptorA: OCPM Mask */ + +#define USBH_HcRhDescriptorA_NOCP_Pos (12) /*!< USBH_T::HcRhDescriptorA: NOCP Position */ +#define USBH_HcRhDescriptorA_NOCP_Msk (0x1ul << USBH_HcRhDescriptorA_NOCP_Pos) /*!< USBH_T::HcRhDescriptorA: NOCP Mask */ + +#define USBH_HcRhDescriptorB_PPCM_Pos (16) /*!< USBH_T::HcRhDescriptorB: PPCM Position */ +#define USBH_HcRhDescriptorB_PPCM_Msk (0xfffful << USBH_HcRhDescriptorB_PPCM_Pos) /*!< USBH_T::HcRhDescriptorB: PPCM Mask */ + +#define USBH_HcRhStatus_LPS_Pos (0) /*!< USBH_T::HcRhStatus: LPS Position */ +#define USBH_HcRhStatus_LPS_Msk (0x1ul << USBH_HcRhStatus_LPS_Pos) /*!< USBH_T::HcRhStatus: LPS Mask */ + +#define USBH_HcRhStatus_OCI_Pos (1) /*!< USBH_T::HcRhStatus: OCI Position */ +#define USBH_HcRhStatus_OCI_Msk (0x1ul << USBH_HcRhStatus_OCI_Pos) /*!< USBH_T::HcRhStatus: OCI Mask */ + +#define USBH_HcRhStatus_DRWE_Pos (15) /*!< USBH_T::HcRhStatus: DRWE Position */ +#define USBH_HcRhStatus_DRWE_Msk (0x1ul << USBH_HcRhStatus_DRWE_Pos) /*!< USBH_T::HcRhStatus: DRWE Mask */ + +#define USBH_HcRhStatus_LPSC_Pos (16) /*!< USBH_T::HcRhStatus: LPSC Position */ +#define USBH_HcRhStatus_LPSC_Msk (0x1ul << USBH_HcRhStatus_LPSC_Pos) /*!< USBH_T::HcRhStatus: LPSC Mask */ + +#define USBH_HcRhStatus_OCIC_Pos (17) /*!< USBH_T::HcRhStatus: OCIC Position */ +#define USBH_HcRhStatus_OCIC_Msk (0x1ul << USBH_HcRhStatus_OCIC_Pos) /*!< USBH_T::HcRhStatus: OCIC Mask */ + +#define USBH_HcRhStatus_CRWE_Pos (31) /*!< USBH_T::HcRhStatus: CRWE Position */ +#define USBH_HcRhStatus_CRWE_Msk (0x1ul << USBH_HcRhStatus_CRWE_Pos) /*!< USBH_T::HcRhStatus: CRWE Mask */ + +#define USBH_HcRhPortStatus_CCS_Pos (0) /*!< USBH_T::HcRhPortStatus1: CCS Position */ +#define USBH_HcRhPortStatus_CCS_Msk (0x1ul << USBH_HcRhPortStatus_CCS_Pos) /*!< USBH_T::HcRhPortStatus1: CCS Mask */ + +#define USBH_HcRhPortStatus_PES_Pos (1) /*!< USBH_T::HcRhPortStatus1: PES Position */ +#define USBH_HcRhPortStatus_PES_Msk (0x1ul << USBH_HcRhPortStatus_PES_Pos) /*!< USBH_T::HcRhPortStatus1: PES Mask */ + +#define USBH_HcRhPortStatus_PSS_Pos (2) /*!< USBH_T::HcRhPortStatus1: PSS Position */ +#define USBH_HcRhPortStatus_PSS_Msk (0x1ul << USBH_HcRhPortStatus_PSS_Pos) /*!< USBH_T::HcRhPortStatus1: PSS Mask */ + +#define USBH_HcRhPortStatus_POCI_Pos (3) /*!< USBH_T::HcRhPortStatus1: POCI Position */ +#define USBH_HcRhPortStatus_POCI_Msk (0x1ul << USBH_HcRhPortStatus_POCI_Pos) /*!< USBH_T::HcRhPortStatus1: POCI Mask */ + +#define USBH_HcRhPortStatus_PRS_Pos (4) /*!< USBH_T::HcRhPortStatus1: PRS Position */ +#define USBH_HcRhPortStatus_PRS_Msk (0x1ul << USBH_HcRhPortStatus_PRS_Pos) /*!< USBH_T::HcRhPortStatus1: PRS Mask */ + +#define USBH_HcRhPortStatus_PPS_Pos (8) /*!< USBH_T::HcRhPortStatus1: PPS Position */ +#define USBH_HcRhPortStatus_PPS_Msk (0x1ul << USBH_HcRhPortStatus_PPS_Pos) /*!< USBH_T::HcRhPortStatus1: PPS Mask */ + +#define USBH_HcRhPortStatus_LSDA_Pos (9) /*!< USBH_T::HcRhPortStatus1: LSDA Position */ +#define USBH_HcRhPortStatus_LSDA_Msk (0x1ul << USBH_HcRhPortStatus_LSDA_Pos) /*!< USBH_T::HcRhPortStatus1: LSDA Mask */ + +#define USBH_HcRhPortStatus_CSC_Pos (16) /*!< USBH_T::HcRhPortStatus1: CSC Position */ +#define USBH_HcRhPortStatus_CSC_Msk (0x1ul << USBH_HcRhPortStatus_CSC_Pos) /*!< USBH_T::HcRhPortStatus1: CSC Mask */ + +#define USBH_HcRhPortStatus_PESC_Pos (17) /*!< USBH_T::HcRhPortStatus1: PESC Position */ +#define USBH_HcRhPortStatus_PESC_Msk (0x1ul << USBH_HcRhPortStatus_PESC_Pos) /*!< USBH_T::HcRhPortStatus1: PESC Mask */ + +#define USBH_HcRhPortStatus_PSSC_Pos (18) /*!< USBH_T::HcRhPortStatus1: PSSC Position */ +#define USBH_HcRhPortStatus_PSSC_Msk (0x1ul << USBH_HcRhPortStatus_PSSC_Pos) /*!< USBH_T::HcRhPortStatus1: PSSC Mask */ + +#define USBH_HcRhPortStatus_OCIC_Pos (19) /*!< USBH_T::HcRhPortStatus1: OCIC Position */ +#define USBH_HcRhPortStatus_OCIC_Msk (0x1ul << USBH_HcRhPortStatus_OCIC_Pos) /*!< USBH_T::HcRhPortStatus1: OCIC Mask */ + +#define USBH_HcRhPortStatus_PRSC_Pos (20) /*!< USBH_T::HcRhPortStatus1: PRSC Position */ +#define USBH_HcRhPortStatus_PRSC_Msk (0x1ul << USBH_HcRhPortStatus_PRSC_Pos) /*!< USBH_T::HcRhPortStatus1: PRSC Mask */ + +#define USBH_HcPhyControl_STBYEN_Pos (27) /*!< USBH_T::HcPhyControl: STBYEN Position */ +#define USBH_HcPhyControl_STBYEN_Msk (0x1ul << USBH_HcPhyControl_STBYEN_Pos) /*!< USBH_T::HcPhyControl: STBYEN Mask */ + +#define USBH_HcMiscControl_ABORT_Pos (1) /*!< USBH_T::HcMiscControl: ABORT Position */ +#define USBH_HcMiscControl_ABORT_Msk (0x1ul << USBH_HcMiscControl_ABORT_Pos) /*!< USBH_T::HcMiscControl: ABORT Mask */ + +#define USBH_HcMiscControl_OCAL_Pos (3) /*!< USBH_T::HcMiscControl: OCAL Position */ +#define USBH_HcMiscControl_OCAL_Msk (0x1ul << USBH_HcMiscControl_OCAL_Pos) /*!< USBH_T::HcMiscControl: OCAL Mask */ + +#define USBH_HcMiscControl_DPRT1_Pos (16) /*!< USBH_T::HcMiscControl: DPRT1 Position */ +#define USBH_HcMiscControl_DPRT1_Msk (0x1ul << USBH_HcMiscControl_DPRT1_Pos) /*!< USBH_T::HcMiscControl: DPRT1 Mask */ + +/**@}*/ /* USBH_CONST */ +/**@}*/ /* end of USBH register group */ + + +/*---------------------- HSUSBH HSUSB Host Controller -------------------------*/ +/** + @addtogroup HSUSBH High Speed USB Host Controller (HSUSBH) + Memory Mapped Structure for HSUSBH Controller +@{ */ + +typedef struct +{ + + + /** + * @var HSUSBH_T::EHCVNR + * Offset: 0x00 EHCI Version Number Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |CRLEN |Capability Registers Length + * | | |This register is used as an offset to add to register base to find the beginning of the Operational Register Space. + * |[31:16] |VERSION |Host Controller Interface Version Number + * | | |This is a two-byte register containing a BCD encoding of the EHCI revision number supported by this host controller + * | | |The most significant byte of this register represents a major revision and the least significant byte is the minor revision. + * @var HSUSBH_T::EHCSPR + * Offset: 0x04 EHCI Structural Parameters Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |N_PORTS |Number of Physical Downstream Ports + * | | |This field specifies the number of physical downstream ports implemented on this host controller + * | | |The value of this field determines how many port registers are addressable in the Operational Register Space (see Table 2-8) + * | | |Valid values are in the range of 1H to FH. + * | | |A zero in this field is undefined. + * |[4] |PPC |Port Power Control + * | | |This field indicates whether the host controller implementation includes port power control + * | | |A one in this bit indicates the ports have port power switches + * | | |A zero in this bit indicates the port do not have port power stitches + * | | |The value of this field affects the functionality of the Port Power field in each port status and control register. + * |[11:8] |N_PCC |Number of Ports Per Companion Controller + * | | |This field indicates the number of ports supported per companion host controller + * | | |It is used to indicate the port routing configuration to system software. + * | | |For example, if N_PORTS has a value of 6 and N_CC has a value of 2 then N_PCC could have a value of 3 + * | | |The convention is that the first N_PCC ports are assumed to be routed to companion controller 1, the next N_PCC ports to companion controller 2, etc + * | | |In the previous example, the N_PCC could have been 4, where the first 4 are routed to companion controller 1 and the last two are routed to companion controller 2. + * | | |The number in this field must be consistent with N_PORTS and N_CC. + * |[15:12] |N_CC |Number of Companion Controller + * | | |This field indicates the number of companion controllers associated with this USB 2.0 host controller. + * | | |A zero in this field indicates there are no companion host controllers + * | | |Port-ownership hand-off is not supported + * | | |Only high-speed devices are supported on the host controller root ports. + * | | |A value larger than zero in this field indicates there are companion USB 1.1 host controller(s) + * | | |Port-ownership hand-offs are supported + * | | |High, Full- and Low-speed devices are supported on the host controller root ports. + * @var HSUSBH_T::EHCCPR + * Offset: 0x08 EHCI Capability Parameters Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |AC64 |64-bit Addressing Capability + * | | |0 = Data structure using 32-bit address memory pointers. + * |[1] |PFLF |Programmable Frame List Flag + * | | |0 = System software must use a frame list length of 1024 elements with this EHCI host controller. + * |[2] |ASPC |Asynchronous Schedule Park Capability + * | | |0 = This EHCI host controller doesn't support park feature of high-speed queue heads in the Asynchronous Schedule. + * |[7:4] |IST |Isochronous Scheduling Threshold + * | | |This field indicates, relative to the current position of the executing host controller, where software can reliably update the isochronous schedule. + * | | |When bit [7] is zero, the value of the least significant 3 bits indicates the number of micro-frames a host controller can hold a set of isochronous data structures (one or more) before flushing the state. + * |[15:8] |EECP |EHCI Extended Capabilities Pointer (EECP) + * | | |0 = No extended capabilities are implemented. + * @var HSUSBH_T::UCMDR + * Offset: 0x20 USB Command Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RUN |Run/Stop (R/W) + * | | |When set to a 1, the Host Controller proceeds with execution of the schedule + * | | |The Host Controller continues execution as long as this bit is set to a 1 + * | | |When this bit is set to 0, the Host Controller completes the current and any actively pipelined transactions on the USB and then halts + * | | |The Host Controller must halt within 16 micro-frames after software clears the Run bit + * | | |The HC Halted bit in the status register indicates when the Host Controller has finished its pending pipelined transactions and has entered the stopped state + * | | |Software must not write a one to this field unless the host controller is in the Halted state (i.e. + * | | |HCHalted in the USBSTS register is a one) + * | | |Doing so will yield undefined results. + * | | |0 = Stop. + * | | |1 = Run. + * |[1] |HCRST |Host Controller Reset (HCRESET) (R/W) + * | | |This control bit is used by software to reset the host controller + * | | |The effects of this on Root Hub registers are similar to a Chip Hardware Reset. + * | | |When software writes a one to this bit, the Host Controller resets its internal pipelines, timers, counters, state machines, etc + * | | |to their initial value + * | | |Any transaction currently in progress on USB is immediately terminated + * | | |A USB reset is not driven on downstream ports. + * | | |All operational registers, including port registers and port state machines are set to their initial values + * | | |Port ownership reverts to the companion host controller(s), with the side effects + * | | |Software must reinitialize the host controller in order to return the host controller to an operational state. + * | | |This bit is set to zero by the Host Controller when the reset process is complete + * | | |Software cannot terminate the reset process early by writing a zero to this register. + * | | |Software should not set this bit to a one when the HCHalted bit in the USBSTS register is a zero + * | | |Attempting to reset an actively running host controller will result in undefined behavior. + * |[3:2] |FLSZ |Frame List Size (R/W or RO) + * | | |This field is R/W only if Programmable Frame List Flag in the HCCPARAMS registers is set to a one + * | | |This field specifies the size of the frame list + * | | |The size the frame list controls which bits in the Frame Index Register should be used for the Frame List Current index + * | | |Values mean: + * | | |00 = 1024 elements (4096 bytes) Default value. + * | | |01 = 512 elements (2048 bytes). + * | | |10 = 256 elements (1024 bytes) u2013 for resource-constrained environment. + * | | |11 = Reserved. + * |[4] |PSEN |Periodic Schedule Enable (R/W) + * | | |This bit controls whether the host controller skips processing the Periodic Schedule. Values mean: + * | | |0 = Do not process the Periodic Schedule. + * | | |1 = Use the PERIODICLISTBASE register to access the Periodic Schedule. + * |[5] |ASEN |Asynchronous Schedule Enable (R/W) + * | | |This bit controls whether the host controller skips processing the Asynchronous Schedule. Values mean: + * | | |0 = Do not process the Asynchronous Schedule. + * | | |1 = Use the ASYNCLISTADDR register to access the Asynchronous Schedule. + * |[6] |IAAD |Interrupt on Asynchronous Advance Doorbell (R/W) + * | | |This bit is used as a doorbell by software to tell the host controller to issue an interrupt the next time it advances asynchronous schedule + * | | |Software must write a 1 to this bit to ring the doorbell. + * | | |When the host controller has evicted all appropriate cached schedule state, it sets the Interrupt on Asynchronous Advance status bit in the USBSTS register + * | | |If the Interrupt on Asynchronous Advance Enable bit in the USBINTR register is a one then the host controller will assert an interrupt at the next interrupt threshold. + * | | |The host controller sets this bit to a zero after it has set the Interrupt on Asynchronous Advance status bit in the USBSTS register to a one. + * | | |Software should not write a one to this bit when the asynchronous schedule is disabled + * | | |Doing so will yield undefined results. + * |[23:16] |ITC |Interrupt Threshold Control (R/W) + * | | |This field is used by system software to select the maximum rate at which the host controller will issue interrupts + * | | |The only valid values are defined below + * | | |If software writes an invalid value to this register, the results are undefined + * | | |Value Maximum Interrupt Interval + * | | |0x00 = Reserved. + * | | |0x01 = 1 micro-frame. + * | | |0x02 = 2 micro-frames. + * | | |0x04 = 4 micro-frames. + * | | |0x08 = 8 micro-frames (default, equates to 1 ms). + * | | |0x10 = 16 micro-frames (2 ms). + * | | |0x20 = 32 micro-frames (4 ms). + * | | |0x40 = 64 micro-frames (8 ms). + * | | |Any other value in this register yields undefined results. + * | | |Software modifications to this bit while HCHalted bit is equal to zero results in undefined behavior. + * @var HSUSBH_T::USTSR + * Offset: 0x24 USB Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |USBINT |USB Interrupt (USBINT) (R/WC) + * | | |The Host Controller sets this bit to 1 on the completion of a USB transaction, which results in the retirement of a Transfer Descriptor that had its IOC bit set. + * | | |The Host Controller also sets this bit to 1 when a short packet is detected (actual number of bytes received was less than the expected number of bytes). + * |[1] |UERRINT |USB Error Interrupt (USBERRINT) (R/WC) + * | | |The Host Controller sets this bit to 1 when completion of a USB transaction results in an error condition (e.g., error counter underflow) + * | | |If the TD on which the error interrupt occurred also had its IOC bit set, both this bit and USBINT bit are set. + * |[2] |PCD |Port Change Detect (R/WC) + * | | |The Host Controller sets this bit to a one when any port for which the Port Owner bit is set to zero has a change bit transition from a zero to a one or a Force Port Resume bit transition from a zero to a one as a result of a J-K transition detected on a suspended port + * | | |This bit will also be set as a result of the Connect Status Change being set to a one after system software has relinquished ownership of a connected port by writing a one to a port's Port Owner bit. + * | | |This bit is allowed to be maintained in the Auxiliary power well + * | | |Alternatively, it is also acceptable that on a D3 to D0 transition of the EHCI HC device, this bit is loaded with the OR of all of the PORTSC change bits (including: Force port resume, over-current change, enable/disable change and connect status change). + * |[3] |FLR |Frame List Rollover (R/WC) + * | | |The Host Controller sets this bit to a one when the Frame List Index rolls over from its maximum value to zero + * | | |The exact value at which the rollover occurs depends on the frame list size + * | | |For example, if the frame list size (as programmed in the Frame List Size field of the USBCMD register) is 1024, the Frame Index Register rolls over every time FRINDEX[13] toggles + * | | |Similarly, if the size is 512, the Host Controller sets this bit to a one every time FRINDEX[12] toggles. + * |[4] |HSERR |Host System Error (R/WC) + * | | |The Host Controller sets this bit to 1 when a serious error occurs during a host system access involving the Host Controller module. + * |[5] |IAA |Interrupt on Asynchronous Advance (R/WC) + * | | |System software can force the host controller to issue an interrupt the next time the host controller advances the asynchronous schedule by writing a one to the Interrupt on Asynchronous Advance Doorbell bit in the USBCMD register + * | | |This status bit indicates the assertion of that interrupt source. + * |[12] |HCHalted |HCHalted (RO) + * | | |This bit is a zero whenever the Run/Stop bit is a one + * | | |The Host Controller sets this bit to one after it has stopped executing as a result of the Run/Stop bit being set to 0, either by software or by the Host Controller hardware (e.g. + * | | |internal error). + * |[13] |RECLA |Reclamation (RO) + * | | |This is a read-only status bit, which is used to detect an empty asynchronous schedule. + * |[14] |PSS |Periodic Schedule Status (RO) + * | | |The bit reports the current real status of the Periodic Schedule + * | | |If this bit is a zero then the status of the Periodic Schedule is disabled + * | | |If this bit is a one then the status of the Periodic Schedule is enabled + * | | |The Host Controller is not required to immediately disable or enable the Periodic Schedule when software transitions the Periodic Schedule Enable bit in the USBCMD register + * | | |When this bit and the Periodic Schedule Enable bit are the same value, the Periodic Schedule is either enabled (1) or disabled (0). + * |[15] |ASS |Asynchronous Schedule Status (RO) + * | | |The bit reports the current real status of the Asynchronous Schedule + * | | |If this bit is a zero then the status of them Asynchronous Schedule is disabled + * | | |If this bit is a one then the status of the Asynchronous Schedule is enabled + * | | |The Host Controller is not required to immediately disable or enable the Asynchronous Schedule when software transitions the Asynchronous Schedule Enable bit in the USBCMD register + * | | |When this bit and the Asynchronous Schedule Enable bit are the same value, the Asynchronous Schedule is either enabled (1) or disabled (0). + * @var HSUSBH_T::UIENR + * Offset: 0x28 USB Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |USBIEN |USB Interrupt Enable or Disable Bit + * | | |When this bit is a one, and the USBINT bit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold + * | | |The interrupt is acknowledged by software clearing the USBINT bit. + * | | |0 = USB interrupt Disabled. + * | | |1 = USB interrupt Enabled. + * |[1] |UERRIEN |USB Error Interrupt Enable or Disable Bit + * | | |When this bit is a one, and the USBERRINT bit in the USBSTS register is a one, the host t controller will issue an interrupt at the next interrupt threshold + * | | |The interrupt is acknowledged by software clearing the USBERRINT bit. + * | | |0 = USB Error interrupt Disabled. + * | | |1 = USB Error interrupt Enabled. + * |[2] |PCIEN |Port Change Interrupt Enable or Disable Bit + * | | |When this bit is a one, and the Port Change Detect bit in the USBSTS register is a one, the host controller will issue an interrupt + * | | |The interrupt is acknowledged by software clearing the Port Change Detect bit. + * | | |0 = Port Change interrupt Disabled. + * | | |1 = Port Change interrupt Enabled. + * |[3] |FLREN |Frame List Rollover Enable or Disable Bit + * | | |When this bit is a one, and the Frame List Rollover bit in the USBSTS register is a one, the host controller will issue an interrupt + * | | |The interrupt is acknowledged by software clearing the Frame List Rollover bit. + * | | |0 = Frame List Rollover interrupt Disabled. + * | | |1 = Frame List Rollover interrupt Enabled. + * |[4] |HSERREN |Host System Error Enable or Disable Bit + * | | |When this bit is a one, and the Host System Error Status bit in the USBSTS register is a one, the host controller will issue an interrupt + * | | |The interrupt is acknowledged by software clearing the Host System Error bit. + * | | |0 = Host System Error interrupt Disabled. + * | | |1 = Host System Error interrupt Enabled. + * |[5] |IAAEN |Interrupt on Asynchronous Advance Enable or Disable Bit + * | | |When this bit is a one, and the Interrupt on Asynchronous Advance bit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold + * | | |The interrupt is acknowledged by software clearing the Interrupt on Asynchronous Advance bit. + * | | |0 = Interrupt on Asynchronous Advance Disabled. + * | | |1 = Interrupt on Asynchronous Advance Enabled. + * @var HSUSBH_T::UFINDR + * Offset: 0x2C USB Frame Index Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[13:0] |FI |Frame Index + * | | |The value in this register increment at the end of each time frame (e.g. + * | | |micro-frame) + * | | |Bits [N:3] are used for the Frame List current index + * | | |This means that each location of the frame list is accessed 8 times (frames or micro-frames) before moving to the next index + * | | |The following illustrates values of N based on the value of the Frame List Size field in the USBCMD register. + * | | |FLSZ (UCMDR[3:2] Number Elements N + * | | |0x0 1024 12 + * | | |0x1 512 11 + * | | |0x2 256 10 + * | | |0x3 Reserved + * @var HSUSBH_T::UPFLBAR + * Offset: 0x34 USB Periodic Frame List Base Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:12] |BADDR |Base Address + * | | |These bits correspond to memory address signals [31:12], respectively. + * @var HSUSBH_T::UCALAR + * Offset: 0x38 USB Current Asynchronous List Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:5] |LPL |Link Pointer Low (LPL) + * | | |These bits correspond to memory address signals [31:5], respectively + * | | |This field may only reference a Queue Head (QH). + * @var HSUSBH_T::UASSTR + * Offset: 0x3C USB Asynchronous Schedule Sleep Timer Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[11:0] |ASSTMR |Asynchronous Schedule Sleep Timer + * | | |This field defines the AsyncSchedSleepTime of EHCI spec. + * | | |The asynchronous schedule sleep timer is used to control how often the host controller fetches asynchronous schedule list from system memory while the asynchronous schedule is empty. + * | | |The default value of this timer is 12'hBD6 + * | | |Because this timer is implemented in UTMI clock (30MHz) domain, the default sleeping time will be about 100us. + * @var HSUSBH_T::UCFGR + * Offset: 0x60 USB Configure Flag Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CF |Configure Flag (CF) + * | | |Host software sets this bit as the last action in its process of configuring the Host Controller + * | | |This bit controls the default port-routing control logic + * | | |Bit values and side-effects are listed below. + * | | |0 = Port routing control logic default-routes each port to an implementation dependent classic host controller. + * | | |1 = Port routing control logic default-routes all ports to this host controller. + * @var HSUSBH_T::UPSCR[2] + * Offset: 0x64~0x68 USB Port 0~1 Status and Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CCS |Current Connect Status (RO) + * | | |This value reflects the current state of the port, and may not correspond directly to the event that caused the Connect Status Change bit (Bit 1) to be set. + * | | |This field is zero if Port Power is zero. + * | | |0 = No device is present. + * | | |1 = Device is present on port. + * |[1] |CSC |Connect Status Change (R/W) + * | | |Indicates a change has occurred in the port's Current Connect Status + * | | |The host controller sets this bit for all changes to the port device connect status, even if system software has not cleared an existing connect status change + * | | |For example, the insertion status changes twice before system software has cleared the changed condition, hub hardware will be "setting" an already-set bit (i.e., the bit will remain set).Software sets this bit to 0 by writing a 1 to it. + * | | |This field is zero if Port Power is zero. + * | | |0 = No change. + * | | |1 = Change in Current Connect Status. + * |[2] |PE |Port Enabled/Disabled (R/W) + * | | |Ports can only be enabled by the host controller as a part of the reset and enable + * | | |Software cannot enable a port by writing a one to this field + * | | |The host controller will only set this bit to a one when the reset sequence determines that the attached device is a high-speed device. + * | | |Ports can be disabled by either a fault condition (disconnect event or other fault condition) or by host software + * | | |Note that the bit status does not change until the port state actually changes + * | | |There may be a delay in disabling or enabling a port due to other host controller and bus events. + * | | |When the port is disabled (0b) downstream propagation of data is blocked on this port, except for reset. + * | | |This field is zero if Port Power is zero. + * | | |0 = Port Disabled. + * | | |1 = Port Enabled. + * |[3] |PEC |Port Enable/Disable Change (R/WC) + * | | |For the root hub, this bit gets set to a one only when a port is disabled due to the appropriate conditions existing at the EOF2 point (See Chapter 11 of the USB Specification for the definition of a Port Error) + * | | |Software clears this bit by writing a 1 to it. + * | | |This field is zero if Port Power is zero. + * | | |0 = No change. + * | | |1 = Port enabled/disabled status has changed. + * |[4] |OCA |Over-current Active (RO) + * | | |This bit will automatically transition from a one to a zero when the over current condition is removed. + * | | |0 = This port does not have an over-current condition. + * | | |1 = This port currently has an over-current condition. + * |[5] |OCC |Over-current Change (R/WC) + * | | |1 = This bit gets set to a one when there is a change to Over-current Active + * | | |Software clears this bit by writing a one to this bit position. + * |[6] |FPR |Force Port Resume (R/W) + * | | |This functionality defined for manipulating this bit depends on the value of the Suspend bit + * | | |For example, if the port is not suspended (Suspend and Enabled bits are a one) and software transitions this bit to a one, then the effects on the bus are undefined. + * | | |Software sets this bit to a 1 to drive resume signaling + * | | |The Host Controller sets this bit to a 1 if a J-to-K transition is detected while the port is in the Suspend state + * | | |When this bit transitions to a one because a J-to-K transition is detected, the Port Change Detect bit in the USBSTS register is also set to a one + * | | |If software sets this bit to a one, the host controller must not set the Port Change Detect bit. + * | | |Note that when the EHCI controller owns the port, the resume sequence follows the defined sequence documented in the USB Specification Revision 2.0 + * | | |The resume signaling (Full-speed 'K') is driven on the port as long as this bit remains a one + * | | |Software must appropriately time the Resume and set this bit to a zero when the appropriate amount of time has elapsed + * | | |Writing a zero (from one) causes the port to return to high-speed mode (forcing the bus below the port into a high-speed idle) + * | | |This bit will remain a one until the port has switched to the high-speed idle + * | | |The host controller must complete this transition within 2 milliseconds of software setting this bit to a zero. + * | | |This field is zero if Port Power is zero. + * | | |0 = No resume (K-state) detected/driven on port. + * | | |1 = Resume detected/driven on port. + * |[7] |SUSPEND |Suspend (R/W) + * | | |Port Enabled Bit and Suspend bit of this register define the port states as follows: + * | | |Port enable is 0 and suspend is 0 = Disable. + * | | |Port enable is 0 and suspend is 1 = Disable. + * | | |Port enable is 1 and suspend is 0 = Enable. + * | | |Port enable is 1 and suspend is 1 = Suspend. + * | | |When in suspend state, downstream propagation of data is blocked on this port, except for port reset + * | | |The blocking occurs at the end of the current transaction, if a transaction was in progress when this bit was written to 1 + * | | |In the suspend state, the port is sensitive to resume detection + * | | |Note that the bit status does not change until the port is suspended and that there may be a delay in suspending a port if there is a transaction currently in progress on the USB. + * | | |A write of zero to this bit is ignored by the host controller + * | | |The host controller will unconditionally set this bit to a zero when: + * | | |Software sets the Force Port Resume bit to a zero (from a one). + * | | |Software sets the Port Reset bit to a one (from a zero). + * | | |If host software sets this bit to a one when the port is not enabled (i.e. + * | | |Port enabled bit is a zero) the results are undefined. + * | | |This field is zero if Port Power is zero. + * | | |0 = Port not in suspend state. + * | | |1 = Port in suspend state. + * |[8] |PRST |Port Reset (R/W) + * | | |When software writes a one to this bit (from a zero), the bus reset sequence as defined in the USB Specification Revision 2.0 is started + * | | |Software writes a zero to this bit to terminate the bus reset sequence + * | | |Software must keep this bit at a one long enough to ensure the reset sequence, as specified in the USB Specification Revision 2.0, completes + * | | |Note: when software writes this bit to a one, it must also write a zero to the Port Enable bit. + * | | |Note that when software writes a zero to this bit there may be a delay before the bit status changes to a zero + * | | |The bit status will not read as a zero until after the reset has completed + * | | |If the port is in high-speed mode after reset is complete, the host controller will automatically enable this port (e.g. + * | | |set the Port Enable bit to a one) + * | | |A host controller must terminate the reset and stabilize the state of the port within 2 milliseconds of software transitioning this bit from a one to a zero + * | | |For example: if the port detects that the attached device is high-speed during reset, then the host controller must have the port in the enabled state within 2ms of software writing this bit to a zero. + * | | |The HCHalted bit in the USBSTS register should be a zero before software attempts to use this bit + * | | |The host controller may hold Port Reset asserted to a one when the HCHalted bit is a one. + * | | |This field is zero if Port Power is zero. + * | | |0 = Port is not in Reset. + * | | |1 = Port is in Reset. + * |[11:10] |LSTS |Line Status (RO) + * | | |These bits reflect the current logical levels of the D+ (bit 11) and D- (bit 10) signal lines + * | | |These bits are used for detection of low-speed USB devices prior to the port reset and enable sequence + * | | |This field is valid only when the port enable bit is zero and the current connect status bit is set to a one. + * | | |The encoding of the bits are: + * | | |Bits[11:10] USB State Interpretation + * | | |00 = SE0 Not Low-speed device, perform EHCI reset. + * | | |01 = K-state Low-speed device, release ownership of port. + * | | |10 = J-state Not Low-speed device, perform EHCI reset. + * | | |11 = Undefined Not Low-speed device, perform EHCI reset. + * | | |This value of this field is undefined if Port Power is zero. + * |[12] |PP |Port Power (PP) + * | | |Host controller has port power control switches + * | | |This bit represents the Current setting of the switch (0 = off, 1 = on) + * | | |When power is not available on a port (i.e. + * | | |PP equals a 0), the port is nonfunctional and will not report attaches, detaches, etc. + * | | |When an over-current condition is detected on a powered port and PPC is a one, the PP bit in each affected port may be transitioned by the host controller from a 1 to 0 (removing power from the port). + * |[13] |PO |Port Owner (R/W) + * | | |This bit unconditionally goes to a 0b when the Configured bit in the CONFIGFLAG register makes a 0 to 1 transition + * | | |This bit unconditionally goes to 1 whenever the Configured bit is zero. + * | | |System software uses this field to release ownership of the port to a selected host controller (in the event that the attached device is not a high-speed device) + * | | |Software writes a one to this bit when the attached device is not a high-speed device + * | | |A one in this bit means that a companion host controller owns and controls the port. + * |[19:16] |PTC |Port Test Control (R/W) + * | | |When this field is zero, the port is NOT operating in a test mode + * | | |A non-zero value indicates that it is operating in test mode and the specific test mode is indicated by the specific value + * | | |The encoding of the test mode bits are (0x6 ~ 0xF are reserved): + * | | |Bits Test Mode + * | | |0x0 = Test mode not enabled. + * | | |0x1 = Test J_STATE. + * | | |0x2 = Test K_STATE. + * | | |0x3 = Test SE0_NAK. + * | | |0x4 = Test Packet. + * | | |0x5 = Test FORCE_ENABLE. + * @var HSUSBH_T::USBPCR0 + * Offset: 0xC4 USB PHY 0 Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8] |SUSPEND |Suspend Assertion + * | | |This bit controls the suspend mode of USB PHY 0. + * | | |While PHY was suspended, all circuits of PHY were powered down and outputs are tri-state. + * | | |This bit is 1'b0 in default + * | | |This means the USB PHY 0 is suspended in default + * | | |It is necessary to set this bit 1'b1 to make USB PHY 0 leave suspend mode before doing configuration of USB host. + * | | |0 = USB PHY 0 was suspended. + * | | |1 = USB PHY 0 was not suspended. + * |[11] |CLKVALID |UTMI Clock Valid + * | | |This bit is a flag to indicate if the UTMI clock from USB 2.0 PHY is ready + * | | |S/W program must prevent to write other control registers before this UTMI clock valid flag is active. + * | | |0 = UTMI clock is not valid. + * | | |1 = UTMI clock is valid. + * @var HSUSBH_T::USBPCR1 + * Offset: 0xC8 USB PHY 1 Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8] |SUSPEND |Suspend Assertion + * | | |This bit controls the suspend mode of USB PHY 1. + * | | |While PHY was suspended, all circuits of PHY were powered down and outputs are tri-state. + * | | |This bit is 1'b0 in default + * | | |This means the USB PHY 0 is suspended in default + * | | |It is necessary to set this bit 1'b1 to make USB PHY 0 leave suspend mode before doing configuration of USB host. + * | | |0 = USB PHY 1 was suspended. + * | | |1 = USB PHY 1 was not suspended. + */ + __I uint32_t EHCVNR; /*!< [0x0000] EHCI Version Number Register */ + __I uint32_t EHCSPR; /*!< [0x0004] EHCI Structural Parameters Register */ + __I uint32_t EHCCPR; /*!< [0x0008] EHCI Capability Parameters Register */ + __I uint32_t RESERVE0[5]; + __IO uint32_t UCMDR; /*!< [0x0020] USB Command Register */ + __IO uint32_t USTSR; /*!< [0x0024] USB Status Register */ + __IO uint32_t UIENR; /*!< [0x0028] USB Interrupt Enable Register */ + __IO uint32_t UFINDR; /*!< [0x002c] USB Frame Index Register */ + __I uint32_t RESERVE1[1]; + __IO uint32_t UPFLBAR; /*!< [0x0034] USB Periodic Frame List Base Address Register */ + __IO uint32_t UCALAR; /*!< [0x0038] USB Current Asynchronous List Address Register */ + __IO uint32_t UASSTR; /*!< [0x003c] USB Asynchronous Schedule Sleep Timer Register */ + __I uint32_t RESERVE2[8]; + __IO uint32_t UCFGR; /*!< [0x0060] USB Configure Flag Register */ + __IO uint32_t UPSCR[2]; /*!< [0x0064] ~ [0x0068] USB Port 0 & 1 Status and Control Register */ + __I uint32_t RESERVE3[22]; + __IO uint32_t USBPCR0; /*!< [0x00c4] USB PHY 0 Control Register */ + __IO uint32_t USBPCR1; /*!< [0x00c8] USB PHY 1 Control Register */ + +} HSUSBH_T; + +/** + @addtogroup HSUSBH_CONST HSUSBH Bit Field Definition + Constant Definitions for HSUSBH Controller +@{ */ + +#define HSUSBH_EHCVNR_CRLEN_Pos (0) /*!< HSUSBH_T::EHCVNR: CRLEN Position */ +#define HSUSBH_EHCVNR_CRLEN_Msk (0xfful << HSUSBH_EHCVNR_CRLEN_Pos) /*!< HSUSBH_T::EHCVNR: CRLEN Mask */ + +#define HSUSBH_EHCVNR_VERSION_Pos (16) /*!< HSUSBH_T::EHCVNR: VERSION Position */ +#define HSUSBH_EHCVNR_VERSION_Msk (0xfffful << HSUSBH_EHCVNR_VERSION_Pos) /*!< HSUSBH_T::EHCVNR: VERSION Mask */ + +#define HSUSBH_EHCSPR_N_PORTS_Pos (0) /*!< HSUSBH_T::EHCSPR: N_PORTS Position */ +#define HSUSBH_EHCSPR_N_PORTS_Msk (0xful << HSUSBH_EHCSPR_N_PORTS_Pos) /*!< HSUSBH_T::EHCSPR: N_PORTS Mask */ + +#define HSUSBH_EHCSPR_PPC_Pos (4) /*!< HSUSBH_T::EHCSPR: PPC Position */ +#define HSUSBH_EHCSPR_PPC_Msk (0x1ul << HSUSBH_EHCSPR_PPC_Pos) /*!< HSUSBH_T::EHCSPR: PPC Mask */ + +#define HSUSBH_EHCSPR_N_PCC_Pos (8) /*!< HSUSBH_T::EHCSPR: N_PCC Position */ +#define HSUSBH_EHCSPR_N_PCC_Msk (0xful << HSUSBH_EHCSPR_N_PCC_Pos) /*!< HSUSBH_T::EHCSPR: N_PCC Mask */ + +#define HSUSBH_EHCSPR_N_CC_Pos (12) /*!< HSUSBH_T::EHCSPR: N_CC Position */ +#define HSUSBH_EHCSPR_N_CC_Msk (0xful << HSUSBH_EHCSPR_N_CC_Pos) /*!< HSUSBH_T::EHCSPR: N_CC Mask */ + +#define HSUSBH_EHCCPR_AC64_Pos (0) /*!< HSUSBH_T::EHCCPR: AC64 Position */ +#define HSUSBH_EHCCPR_AC64_Msk (0x1ul << HSUSBH_EHCCPR_AC64_Pos) /*!< HSUSBH_T::EHCCPR: AC64 Mask */ + +#define HSUSBH_EHCCPR_PFLF_Pos (1) /*!< HSUSBH_T::EHCCPR: PFLF Position */ +#define HSUSBH_EHCCPR_PFLF_Msk (0x1ul << HSUSBH_EHCCPR_PFLF_Pos) /*!< HSUSBH_T::EHCCPR: PFLF Mask */ + +#define HSUSBH_EHCCPR_ASPC_Pos (2) /*!< HSUSBH_T::EHCCPR: ASPC Position */ +#define HSUSBH_EHCCPR_ASPC_Msk (0x1ul << HSUSBH_EHCCPR_ASPC_Pos) /*!< HSUSBH_T::EHCCPR: ASPC Mask */ + +#define HSUSBH_EHCCPR_IST_Pos (4) /*!< HSUSBH_T::EHCCPR: IST Position */ +#define HSUSBH_EHCCPR_IST_Msk (0xful << HSUSBH_EHCCPR_IST_Pos) /*!< HSUSBH_T::EHCCPR: IST Mask */ + +#define HSUSBH_EHCCPR_EECP_Pos (8) /*!< HSUSBH_T::EHCCPR: EECP Position */ +#define HSUSBH_EHCCPR_EECP_Msk (0xfful << HSUSBH_EHCCPR_EECP_Pos) /*!< HSUSBH_T::EHCCPR: EECP Mask */ + +#define HSUSBH_UCMDR_RUN_Pos (0) /*!< HSUSBH_T::UCMDR: RUN Position */ +#define HSUSBH_UCMDR_RUN_Msk (0x1ul << HSUSBH_UCMDR_RUN_Pos) /*!< HSUSBH_T::UCMDR: RUN Mask */ + +#define HSUSBH_UCMDR_HCRST_Pos (1) /*!< HSUSBH_T::UCMDR: HCRST Position */ +#define HSUSBH_UCMDR_HCRST_Msk (0x1ul << HSUSBH_UCMDR_HCRST_Pos) /*!< HSUSBH_T::UCMDR: HCRST Mask */ + +#define HSUSBH_UCMDR_FLSZ_Pos (2) /*!< HSUSBH_T::UCMDR: FLSZ Position */ +#define HSUSBH_UCMDR_FLSZ_Msk (0x3ul << HSUSBH_UCMDR_FLSZ_Pos) /*!< HSUSBH_T::UCMDR: FLSZ Mask */ + +#define HSUSBH_UCMDR_PSEN_Pos (4) /*!< HSUSBH_T::UCMDR: PSEN Position */ +#define HSUSBH_UCMDR_PSEN_Msk (0x1ul << HSUSBH_UCMDR_PSEN_Pos) /*!< HSUSBH_T::UCMDR: PSEN Mask */ + +#define HSUSBH_UCMDR_ASEN_Pos (5) /*!< HSUSBH_T::UCMDR: ASEN Position */ +#define HSUSBH_UCMDR_ASEN_Msk (0x1ul << HSUSBH_UCMDR_ASEN_Pos) /*!< HSUSBH_T::UCMDR: ASEN Mask */ + +#define HSUSBH_UCMDR_IAAD_Pos (6) /*!< HSUSBH_T::UCMDR: IAAD Position */ +#define HSUSBH_UCMDR_IAAD_Msk (0x1ul << HSUSBH_UCMDR_IAAD_Pos) /*!< HSUSBH_T::UCMDR: IAAD Mask */ + +#define HSUSBH_UCMDR_ITC_Pos (16) /*!< HSUSBH_T::UCMDR: ITC Position */ +#define HSUSBH_UCMDR_ITC_Msk (0xfful << HSUSBH_UCMDR_ITC_Pos) /*!< HSUSBH_T::UCMDR: ITC Mask */ + +#define HSUSBH_USTSR_USBINT_Pos (0) /*!< HSUSBH_T::USTSR: USBINT Position */ +#define HSUSBH_USTSR_USBINT_Msk (0x1ul << HSUSBH_USTSR_USBINT_Pos) /*!< HSUSBH_T::USTSR: USBINT Mask */ + +#define HSUSBH_USTSR_UERRINT_Pos (1) /*!< HSUSBH_T::USTSR: UERRINT Position */ +#define HSUSBH_USTSR_UERRINT_Msk (0x1ul << HSUSBH_USTSR_UERRINT_Pos) /*!< HSUSBH_T::USTSR: UERRINT Mask */ + +#define HSUSBH_USTSR_PCD_Pos (2) /*!< HSUSBH_T::USTSR: PCD Position */ +#define HSUSBH_USTSR_PCD_Msk (0x1ul << HSUSBH_USTSR_PCD_Pos) /*!< HSUSBH_T::USTSR: PCD Mask */ + +#define HSUSBH_USTSR_FLR_Pos (3) /*!< HSUSBH_T::USTSR: FLR Position */ +#define HSUSBH_USTSR_FLR_Msk (0x1ul << HSUSBH_USTSR_FLR_Pos) /*!< HSUSBH_T::USTSR: FLR Mask */ + +#define HSUSBH_USTSR_HSERR_Pos (4) /*!< HSUSBH_T::USTSR: HSERR Position */ +#define HSUSBH_USTSR_HSERR_Msk (0x1ul << HSUSBH_USTSR_HSERR_Pos) /*!< HSUSBH_T::USTSR: HSERR Mask */ + +#define HSUSBH_USTSR_IAA_Pos (5) /*!< HSUSBH_T::USTSR: IAA Position */ +#define HSUSBH_USTSR_IAA_Msk (0x1ul << HSUSBH_USTSR_IAA_Pos) /*!< HSUSBH_T::USTSR: IAA Mask */ + +#define HSUSBH_USTSR_HCHalted_Pos (12) /*!< HSUSBH_T::USTSR: HCHalted Position */ +#define HSUSBH_USTSR_HCHalted_Msk (0x1ul << HSUSBH_USTSR_HCHalted_Pos) /*!< HSUSBH_T::USTSR: HCHalted Mask */ + +#define HSUSBH_USTSR_RECLA_Pos (13) /*!< HSUSBH_T::USTSR: RECLA Position */ +#define HSUSBH_USTSR_RECLA_Msk (0x1ul << HSUSBH_USTSR_RECLA_Pos) /*!< HSUSBH_T::USTSR: RECLA Mask */ + +#define HSUSBH_USTSR_PSS_Pos (14) /*!< HSUSBH_T::USTSR: PSS Position */ +#define HSUSBH_USTSR_PSS_Msk (0x1ul << HSUSBH_USTSR_PSS_Pos) /*!< HSUSBH_T::USTSR: PSS Mask */ + +#define HSUSBH_USTSR_ASS_Pos (15) /*!< HSUSBH_T::USTSR: ASS Position */ +#define HSUSBH_USTSR_ASS_Msk (0x1ul << HSUSBH_USTSR_ASS_Pos) /*!< HSUSBH_T::USTSR: ASS Mask */ + +#define HSUSBH_UIENR_USBIEN_Pos (0) /*!< HSUSBH_T::UIENR: USBIEN Position */ +#define HSUSBH_UIENR_USBIEN_Msk (0x1ul << HSUSBH_UIENR_USBIEN_Pos) /*!< HSUSBH_T::UIENR: USBIEN Mask */ + +#define HSUSBH_UIENR_UERRIEN_Pos (1) /*!< HSUSBH_T::UIENR: UERRIEN Position */ +#define HSUSBH_UIENR_UERRIEN_Msk (0x1ul << HSUSBH_UIENR_UERRIEN_Pos) /*!< HSUSBH_T::UIENR: UERRIEN Mask */ + +#define HSUSBH_UIENR_PCIEN_Pos (2) /*!< HSUSBH_T::UIENR: PCIEN Position */ +#define HSUSBH_UIENR_PCIEN_Msk (0x1ul << HSUSBH_UIENR_PCIEN_Pos) /*!< HSUSBH_T::UIENR: PCIEN Mask */ + +#define HSUSBH_UIENR_FLREN_Pos (3) /*!< HSUSBH_T::UIENR: FLREN Position */ +#define HSUSBH_UIENR_FLREN_Msk (0x1ul << HSUSBH_UIENR_FLREN_Pos) /*!< HSUSBH_T::UIENR: FLREN Mask */ + +#define HSUSBH_UIENR_HSERREN_Pos (4) /*!< HSUSBH_T::UIENR: HSERREN Position */ +#define HSUSBH_UIENR_HSERREN_Msk (0x1ul << HSUSBH_UIENR_HSERREN_Pos) /*!< HSUSBH_T::UIENR: HSERREN Mask */ + +#define HSUSBH_UIENR_IAAEN_Pos (5) /*!< HSUSBH_T::UIENR: IAAEN Position */ +#define HSUSBH_UIENR_IAAEN_Msk (0x1ul << HSUSBH_UIENR_IAAEN_Pos) /*!< HSUSBH_T::UIENR: IAAEN Mask */ + +#define HSUSBH_UFINDR_FI_Pos (0) /*!< HSUSBH_T::UFINDR: FI Position */ +#define HSUSBH_UFINDR_FI_Msk (0x3ffful << HSUSBH_UFINDR_FI_Pos) /*!< HSUSBH_T::UFINDR: FI Mask */ + +#define HSUSBH_UPFLBAR_BADDR_Pos (12) /*!< HSUSBH_T::UPFLBAR: BADDR Position */ +#define HSUSBH_UPFLBAR_BADDR_Msk (0xffffful << HSUSBH_UPFLBAR_BADDR_Pos) /*!< HSUSBH_T::UPFLBAR: BADDR Mask */ + +#define HSUSBH_UCALAR_LPL_Pos (5) /*!< HSUSBH_T::UCALAR: LPL Position */ +#define HSUSBH_UCALAR_LPL_Msk (0x7fffffful << HSUSBH_UCALAR_LPL_Pos) /*!< HSUSBH_T::UCALAR: LPL Mask */ + +#define HSUSBH_UASSTR_ASSTMR_Pos (0) /*!< HSUSBH_T::UASSTR: ASSTMR Position */ +#define HSUSBH_UASSTR_ASSTMR_Msk (0xffful << HSUSBH_UASSTR_ASSTMR_Pos) /*!< HSUSBH_T::UASSTR: ASSTMR Mask */ + +#define HSUSBH_UCFGR_CF_Pos (0) /*!< HSUSBH_T::UCFGR: CF Position */ +#define HSUSBH_UCFGR_CF_Msk (0x1ul << HSUSBH_UCFGR_CF_Pos) /*!< HSUSBH_T::UCFGR: CF Mask */ + +#define HSUSBH_UPSCR_CCS_Pos (0) /*!< HSUSBH_T::UPSCR[2]: CCS Position */ +#define HSUSBH_UPSCR_CCS_Msk (0x1ul << HSUSBH_UPSCR_CCS_Pos) /*!< HSUSBH_T::UPSCR[2]: CCS Mask */ + +#define HSUSBH_UPSCR_CSC_Pos (1) /*!< HSUSBH_T::UPSCR[2]: CSC Position */ +#define HSUSBH_UPSCR_CSC_Msk (0x1ul << HSUSBH_UPSCR_CSC_Pos) /*!< HSUSBH_T::UPSCR[2]: CSC Mask */ + +#define HSUSBH_UPSCR_PE_Pos (2) /*!< HSUSBH_T::UPSCR[2]: PE Position */ +#define HSUSBH_UPSCR_PE_Msk (0x1ul << HSUSBH_UPSCR_PE_Pos) /*!< HSUSBH_T::UPSCR[2]: PE Mask */ + +#define HSUSBH_UPSCR_PEC_Pos (3) /*!< HSUSBH_T::UPSCR[2]: PEC Position */ +#define HSUSBH_UPSCR_PEC_Msk (0x1ul << HSUSBH_UPSCR_PEC_Pos) /*!< HSUSBH_T::UPSCR[2]: PEC Mask */ + +#define HSUSBH_UPSCR_OCA_Pos (4) /*!< HSUSBH_T::UPSCR[2]: OCA Position */ +#define HSUSBH_UPSCR_OCA_Msk (0x1ul << HSUSBH_UPSCR_OCA_Pos) /*!< HSUSBH_T::UPSCR[2]: OCA Mask */ + +#define HSUSBH_UPSCR_OCC_Pos (5) /*!< HSUSBH_T::UPSCR[2]: OCC Position */ +#define HSUSBH_UPSCR_OCC_Msk (0x1ul << HSUSBH_UPSCR_OCC_Pos) /*!< HSUSBH_T::UPSCR[2]: OCC Mask */ + +#define HSUSBH_UPSCR_FPR_Pos (6) /*!< HSUSBH_T::UPSCR[2]: FPR Position */ +#define HSUSBH_UPSCR_FPR_Msk (0x1ul << HSUSBH_UPSCR_FPR_Pos) /*!< HSUSBH_T::UPSCR[2]: FPR Mask */ + +#define HSUSBH_UPSCR_SUSPEND_Pos (7) /*!< HSUSBH_T::UPSCR[2]: SUSPEND Position */ +#define HSUSBH_UPSCR_SUSPEND_Msk (0x1ul << HSUSBH_UPSCR_SUSPEND_Pos) /*!< HSUSBH_T::UPSCR[2]: SUSPEND Mask */ + +#define HSUSBH_UPSCR_PRST_Pos (8) /*!< HSUSBH_T::UPSCR[2]: PRST Position */ +#define HSUSBH_UPSCR_PRST_Msk (0x1ul << HSUSBH_UPSCR_PRST_Pos) /*!< HSUSBH_T::UPSCR[2]: PRST Mask */ + +#define HSUSBH_UPSCR_LSTS_Pos (10) /*!< HSUSBH_T::UPSCR[2]: LSTS Position */ +#define HSUSBH_UPSCR_LSTS_Msk (0x3ul << HSUSBH_UPSCR_LSTS_Pos) /*!< HSUSBH_T::UPSCR[2]: LSTS Mask */ + +#define HSUSBH_UPSCR_PP_Pos (12) /*!< HSUSBH_T::UPSCR[2]: PP Position */ +#define HSUSBH_UPSCR_PP_Msk (0x1ul << HSUSBH_UPSCR_PP_Pos) /*!< HSUSBH_T::UPSCR[2]: PP Mask */ + +#define HSUSBH_UPSCR_PO_Pos (13) /*!< HSUSBH_T::UPSCR[2]: PO Position */ +#define HSUSBH_UPSCR_PO_Msk (0x1ul << HSUSBH_UPSCR_PO_Pos) /*!< HSUSBH_T::UPSCR[2]: PO Mask */ + +#define HSUSBH_UPSCR_PTC_Pos (16) /*!< HSUSBH_T::UPSCR[2]: PTC Position */ +#define HSUSBH_UPSCR_PTC_Msk (0xful << HSUSBH_UPSCR_PTC_Pos) /*!< HSUSBH_T::UPSCR[2]: PTC Mask */ + +#define HSUSBH_USBPCR0_SUSPEND_Pos (8) /*!< HSUSBH_T::USBPCR0: SUSPEND Position */ +#define HSUSBH_USBPCR0_SUSPEND_Msk (0x1ul << HSUSBH_USBPCR0_SUSPEND_Pos) /*!< HSUSBH_T::USBPCR0: SUSPEND Mask */ + +#define HSUSBH_USBPCR0_CLKVALID_Pos (11) /*!< HSUSBH_T::USBPCR0: CLKVALID Position */ +#define HSUSBH_USBPCR0_CLKVALID_Msk (0x1ul << HSUSBH_USBPCR0_CLKVALID_Pos) /*!< HSUSBH_T::USBPCR0: CLKVALID Mask */ + +#define HSUSBH_USBPCR1_SUSPEND_Pos (8) /*!< HSUSBH_T::USBPCR1: SUSPEND Position */ +#define HSUSBH_USBPCR1_SUSPEND_Msk (0x1ul << HSUSBH_USBPCR1_SUSPEND_Pos) /*!< HSUSBH_T::USBPCR1: SUSPEND Mask */ + +/**@}*/ /* HSUSBH_CONST */ +/**@}*/ /* end of HSUSBH register group */ + +#define USBH ((USBH_T *)0xB0007000) +#define HSUSBH ((HSUSBH_T *)0xB0005000) + + +/// @endcond /*HIDDEN_SYMBOLS*/ + +#endif /* _USBH_CONFIG_H_ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/ehci.h b/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/ehci.h new file mode 100644 index 0000000000..4d09ed9b8f --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/ehci.h @@ -0,0 +1,279 @@ +/**************************************************************************//** + * @file ehci.h + * @version V1.00 + * @brief USB EHCI host controller driver header file. + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2017 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ + +#ifndef _USBH_EHCI_H_ +#define _USBH_EHCI_H_ + +/// @cond HIDDEN_SYMBOLS + +struct utr_t; +struct udev_t; +struct qh_t; +struct iso_ep_t; +struct ep_info_t; + +/*----------------------------------------------------------------------------------------*/ +/* Periodic Frame List Size (256, 512, or 1024) */ +/*----------------------------------------------------------------------------------------*/ +#define FL_SIZE 1024 /* frame list size can be 256, 512, or 1024 */ +#define NUM_IQH 11 /* depends on FL_SIZE, 256:9, 512:10, 1024:11 */ + + +/*----------------------------------------------------------------------------------------*/ +/* Interrupt Threshold Control (1, 2, 4, 6, .. 64) */ +/*----------------------------------------------------------------------------------------*/ +#define UCMDR_INT_THR_CTRL (0x1< of QH */ +} qTD_T; + + +#define QTD_LIST_END 0x1 /* Indicate the terminate of qTD list. */ +#define QTD_PTR(x) ((qTD_T *)((uint32_t)(x) & ~0x1F)) + +/* + * Status: qTD Token[7:0] + */ +#define QTD_STS_PS_OUT (0<<0) /* directs the HC to issue an OUT PID */ +#define QTD_STS_PS_PING (1<<0) /* directs the HC to issue an PING PID */ +#define QTD_STS_SPLIT_STRAT (0<<1) /* directs the HC to issue an Start split */ +#define QTD_STS_SPLIT_COMPLETE (1<<1) /* directs the HC to issue an Complete split */ +#define QTD_STS_MISS_MF (1<<2) /* miss a required complete-split transaction */ +#define QTD_STS_XactErr (1<<3) /* Transaction Error occurred */ +#define QTD_STS_BABBLE (1<<4) /* Babble Detected */ +#define QTD_STS_DATA_BUFF_ERR (1<<5) /* Data Buffer Error */ +#define QTD_STS_HALT (1<<6) /* Halted */ +#define QTD_STS_ACTIVE (1<<7) /* Active */ + +/* + * PID: qTD Token[9:8] + */ +#define QTD_PID_Msk (0x3<<8) +#define QTD_PID_OUT (0<<8) /* generates token (E1H) */ +#define QTD_PID_IN (1<<8) /* generates token (69H) */ +#define QTD_PID_SETUP (2<<8) /* generates token (2DH) */ + +#define QTD_ERR_COUNTER (3<<10) /* Token[11:10] */ +#define QTD_IOC (1<<15) /* Token[15] - Interrupt On Complete */ +#define QTD_TODO_LEN_Pos 16 /* Token[31:16] - Total Bytes to Transfer */ +#define QTD_TODO_LEN(x) (((x)>>16) & 0x7FFF) +#define QTD_DT (1UL<<31) /* Token[31] - Data Toggle */ + +/*----------------------------------------------------------------------------------------*/ +/* Queue Head (QH) */ +/*----------------------------------------------------------------------------------------*/ +typedef struct qh_t +{ + /* OHCI spec. Endpoint descriptor */ + uint32_t HLink; /* Queue Head Horizontal Link Pointer */ + uint32_t Chrst; /* Endpoint Characteristics: QH DWord 1 */ + uint32_t Cap; /* Endpoint Capabilities: QH DWord 2 */ + uint32_t Curr_qTD; /* Current qTD Pointer */ + /* + * The followings are qTD Transfer Overlay + */ + uint32_t OL_Next_qTD; /* Next qTD Pointer */ + uint32_t OL_Alt_Next_qTD; /* Alternate Next qTD Pointer */ + uint32_t OL_Token; /* qTD Token */ + uint32_t OL_Bptr[5]; /* qTD Buffer Page Pointer List */ + /* + * The following members are used by USB Host libary. + */ + qTD_T *qtd_list; /* currently linked qTD transfers */ + qTD_T *done_list; /* currently linked qTD transfers */ + struct qh_t *next; /* point to the next QH in remove list */ +} QH_T; + +/* HLink[0] T field of "Queue Head Horizontal Link Pointer" */ +#define QH_HLNK_END 0x1 + +/* + * HLink[2:1] Typ field of "Queue Head Horizontal Link Pointer" + */ +#define QH_HLNK_ITD(x) (((uint32_t)(x) & ~0x1F) | 0x0) +#define QH_HLNK_QH(x) (((uint32_t)(x) & ~0x1F) | 0x2) +#define QH_HLNK_SITD(x) (((uint32_t)(x) & ~0x1F) | 0x4) +#define QH_HLNK_FSTN(x) (((uint32_t)(x) & ~0x1F) | 0x6) +#define QH_PTR(x) ((QH_T *)((uint32_t)(x) & ~0x1F)) + +/* + * Bit fields of "Endpoint Characteristics" + */ +#define QH_NAK_RL (4L<<28) /* Chrst[31:28] - NAK Count Reload */ +#define QH_CTRL_EP_FLAG (1<<27) /* Chrst[27] - Control Endpoint Flag */ +#define QH_RCLM_LIST_HEAD (1<<15) /* Chrst[15] - Head of Reclamation List Flag */ +#define QH_DTC (1<<14) /* Chrst[14] - Data Toggle Control */ +#define QH_EPS_FULL (0<<12) /* Chrst[13:12] - Endpoint Speed (Full) */ +#define QH_EPS_LOW (1<<12) /* Chrst[13:12] - Endpoint Speed (Low) */ +#define QH_EPS_HIGH (2<<12) /* Chrst[13:12] - Endpoint Speed (High) */ +#define QH_I_NEXT (1<<7) /* Chrst[7] - Inactivate on Next Transaction */ + +/* + * Bit fields of "Endpoint Capabilities" + */ +#define QH_MULT_Pos 30 /* Cap[31:30] - High-Bandwidth Pipe Multiplier */ +#define QH_HUB_PORT_Pos 23 /* Cap[29:23] - Hub Port Number */ +#define QH_HUB_ADDR_Pos 16 /* Cap[22:16] - Hub Addr */ +#define QH_C_MASK_Msk 0xFF00 /* Cap[15:8] - uFrame C-mask */ +#define QH_S_MASK_Msk 0x00FF /* Cap[7:0] - uFrame S-mask */ + + +/*----------------------------------------------------------------------------------------*/ +/* Isochronous (High-Speed) Transfer Descriptor (iTD) */ +/*----------------------------------------------------------------------------------------*/ +typedef struct itd_t +{ + uint32_t Next_Link; /* Next Link Pointer */ + uint32_t Transaction[8]; /* Transaction Status and Control */ + uint32_t Bptr[7]; /* Buffer Page Pointer List */ + /* + * The following members are used by USB Host libary. + */ + struct iso_ep_t *iso_ep; /* associated isochronous information block */ + struct utr_t *utr; /* associated UTR */ + uint32_t buff_base; /* buffer base address */ + uint8_t fidx; /* iTD's first index to UTR iso frames */ + uint8_t trans_mask; /* mask of activated transactions in iTD */ + uint32_t sched_frnidx; /* scheduled frame index */ + struct itd_t *next; /* used by software to maintain iTD list */ +} iTD_T; + +/* + * Next_Link[2:1] Typ field of "Next Schedule Element Pointer" Typ field + */ +#define ITD_HLNK_ITD(x) (((uint32_t)(x) & ~0x1F) | 0x0) +#define ITD_HLNK_QH(x) (((uint32_t)(x) & ~0x1F) | 0x2) +#define ITD_HLNK_SITD(x) (((uint32_t)(x) & ~0x1F) | 0x4) +#define ITD_HLNK_FSTN(x) (((uint32_t)(x) & ~0x1F) | 0x6) +#define ITD_PTR(x) ((iTD_T *)((uint32_t)(x) & ~0x1F)) + +/* + * Transaction[8] + */ +#define ITD_STATUS(x) (((x)>>28)&0xF) +#define ITD_STATUS_ACTIVE (0x80000000UL) /* Active */ +#define ITD_STATUS_BUFF_ERR (0x40000000UL) /* Data Buffer Error */ +#define ITD_STATUS_BABBLE (0x20000000UL) /* Babble Detected */ +#define ITD_STATUS_XACT_ERR (0x10000000UL) /* Transcation Error */ + +#define ITD_XLEN_Pos 16 +#define ITD_XFER_LEN(x) (((x)>>16)&0xFFF) +#define ITD_IOC (1<<15) +#define ITD_PG_Pos 12 +#define ITD_XFER_OFF_Msk 0xFFF + +/* + * Bptr[7] + */ +#define ITD_BUFF_PAGE_Pos 12 +/* Bptr[0] */ +#define ITD_EP_NUM_Pos 8 +#define ITD_EP_NUM(itd) (((itd)->Bptr[0]>>8)&0xF) +#define ITD_DEV_ADDR_Pos 0 +#define ITD_DEV_ADDR(itd) ((itd)->Bptr[0]&0x7F) +/* Bptr[1] */ +#define ITD_DIR_IN (1<<11) +#define ITD_DIR_OUT (0<<11) +#define ITD_MAX_PKTSZ_Pos 0 +#define ITD_MAX_PKTSZ(itd) ((itd)->Bptr[1]&0x7FF) + +/*----------------------------------------------------------------------------------------*/ +/* Split Isochronous (Full-Speed) Transfer Descriptor (siTD) */ +/*----------------------------------------------------------------------------------------*/ +typedef struct sitd_t +{ + uint32_t Next_Link; /* Next Link Pointer */ + uint32_t Chrst; /* Endpoint and Transaction Translator Characteristics */ + uint32_t Sched; /* Micro-frame Schedule Control */ + uint32_t StsCtrl; /* siTD Transfer Status and Control */ + uint32_t Bptr[2]; /* Buffer Page Pointer List */ + uint32_t BackLink; /* siTD Back Link Pointer */ + /* + * The following members are used by USB Host libary. + */ + struct iso_ep_t *iso_ep; /* associated isochronous information block */ + struct utr_t *utr; /* associated UTR */ + uint8_t fidx; /* iTD's first index to UTR iso frames */ + uint32_t sched_frnidx; /* scheduled frame index */ + struct sitd_t *next; /* used by software to maintain siTD list */ +} siTD_T; + +#define SITD_LIST_END 0x1 /* Indicate the terminate of siTD list. */ + +#define SITD_XFER_IO_Msk (1UL<<31) +#define SITD_XFER_IN (1UL<<31) +#define SITD_XFER_OUT (0UL<<31) + +#define SITD_PORT_NUM_Pos 24 +#define SITD_HUB_ADDR_Pos 16 +#define SITD_EP_NUM_Pos 8 +#define SITD_DEV_ADDR_Pos 0 + +#define SITD_IOC (1UL<<31) +#define SITD_XFER_CNT_Pos 16 +#define SITD_XFER_CNT_Msk (0x3FF<>28) & 0x0F) +#define TD_CC_SET(td, cc) (td) = ((td) & 0x0FFFFFFF) | (((cc) & 0x0F) << 28) +#define TD_T_DATA0 0x02000000 +#define TD_T_DATA1 0x03000000 +#define TD_R 0x00040000 +#define TD_DP 0x00180000 +#define TD_DP_IN 0x00100000 +#define TD_DP_OUT 0x00080000 +#define MAXPSW 8 +/* steel TD reserved bits to keep driver data */ +#define TD_TYPE_Msk (0x3<<16) +#define TD_TYPE_CTRL (0x0<<16) +#define TD_TYPE_BULK (0x1<<16) +#define TD_TYPE_INT (0x2<<16) +#define TD_TYPE_ISO (0x3<<16) +#define TD_CTRL_Msk (0x7<<15) +#define TD_CTRL_DATA (1<<15) + + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined in the OHCI spec. that the host controller is + * told the base address of. It must be 256-byte aligned. + */ +typedef struct +{ + uint32_t int_table[32]; /* Interrupt ED table */ + uint16_t frame_no; /* current frame number */ + uint16_t pad1; /* set to 0 on each frame_no change */ + uint32_t done_head; /* info returned for an interrupt */ + uint8_t reserved_for_hc[116]; +} HCCA_T; + + +/// @endcond + +#endif /* _USBH_OHCI_H_ */ diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usb.h b/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usb.h new file mode 100644 index 0000000000..4f99d4e6c9 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usb.h @@ -0,0 +1,394 @@ +/**************************************************************************//** + * @file usb.h + * @version V1.00 + * @brief USB Host library header file. + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2017 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ + +#ifndef _USBH_H_ +#define _USBH_H_ + +#include "config.h" +#include "usbh_lib.h" +#include "ehci.h" +#include "ohci.h" + +/// @cond HIDDEN_SYMBOLS + +struct utr_t; +struct udev_t; +struct hub_dev_t; +struct iface_t; +struct ep_info_t; + +/*----------------------------------------------------------------------------------*/ +/* USB device request setup packet */ +/*----------------------------------------------------------------------------------*/ +typedef struct __attribute__((__packed__)) +{ + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} +DEV_REQ_T; + +/* + * bmRequestType[7] - Data transfer direction + */ +#define REQ_TYPE_OUT 0x00 +#define REQ_TYPE_IN 0x80 +/* + * bmRequestType[6:5] - Type + */ +#define REQ_TYPE_STD_DEV 0x00 +#define REQ_TYPE_CLASS_DEV 0x20 +#define REQ_TYPE_VENDOR_DEV 0x40 +/* + * bmRequestType[4:0] - Recipient + */ +#define REQ_TYPE_TO_DEV 0x00 +#define REQ_TYPE_TO_IFACE 0x01 +#define REQ_TYPE_TO_EP 0x02 +#define REQ_TYPE_TO_OTHER 0x03 +/* + * Standard Requests + */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_SET_INTERFACE 0x0B +/* + * Descriptor Types + */ +#define USB_DT_STANDARD 0x00 +#define USB_DT_CLASS 0x20 +#define USB_DT_VENDOR 0x40 + +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIGURATION 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 +#define USB_DT_DEVICE_QUALIFIER 0x06 +#define USB_DT_OTHER_SPEED_CONF 0x07 +#define USB_DT_IFACE_POWER 0x08 + + + +/*----------------------------------------------------------------------------------*/ +/* USB standard descriptors */ +/*----------------------------------------------------------------------------------*/ + +/* Descriptor header */ +typedef struct __attribute__((__packed__)) +{ + uint8_t bLength; + uint8_t bDescriptorType; +} +DESC_HDR_T; + +/*----------------------------------------------------------------------------------*/ +/* USB device descriptor */ +/*----------------------------------------------------------------------------------*/ +typedef struct __attribute__((__packed__)) /*!< device descriptor structure */ +{ + uint8_t bLength; /*!< Length of device descriptor */ + uint8_t bDescriptorType; /*!< Device descriptor type */ + uint16_t bcdUSB; /*!< USB version number */ + uint8_t bDeviceClass; /*!< Device class code */ + uint8_t bDeviceSubClass; /*!< Device subclass code */ + uint8_t bDeviceProtocol; /*!< Device protocol code */ + uint8_t bMaxPacketSize0; /*!< Maximum packet size of control endpoint*/ + uint16_t idVendor; /*!< Vendor ID */ + uint16_t idProduct; /*!< Product ID */ + uint16_t bcdDevice; /*!< Device ID */ + uint8_t iManufacturer; /*!< Manufacture description string ID */ + uint8_t iProduct; /*!< Product description string ID */ + uint8_t iSerialNumber; /*!< Serial number description string ID */ + uint8_t bNumConfigurations; /*!< Total number of configurations */ +} +DESC_DEV_T; /*!< device descriptor structure */ + +/* + * Configuration Descriptor + */ +typedef struct __attribute__((__packed__)) usb_config_descriptor /*!< Configuration descriptor structure */ +{ + uint8_t bLength; /*!< Length of configuration descriptor */ + uint8_t bDescriptorType; /*!< Descriptor type */ + uint16_t wTotalLength; /*!< Total length of this configuration */ + uint8_t bNumInterfaces; /*!< Total number of interfaces */ + uint8_t bConfigurationValue; /*!< Configuration descriptor number */ + uint8_t iConfiguration; /*!< String descriptor ID */ + uint8_t bmAttributes; /*!< Configuration characteristics */ + uint8_t MaxPower; /*!< Maximum power consumption */ +} DESC_CONF_T; /*!< Configuration descriptor structure */ + +/* + * Interface Descriptor + */ +typedef struct __attribute__((__packed__))usb_interface_descriptor /*!< Interface descriptor structure */ +{ + uint8_t bLength; /*!< Length of interface descriptor */ + uint8_t bDescriptorType; /*!< Descriptor type */ + uint8_t bInterfaceNumber; /*!< Interface number */ + uint8_t bAlternateSetting; /*!< Alternate setting number */ + uint8_t bNumEndpoints; /*!< Number of endpoints */ + uint8_t bInterfaceClass; /*!< Interface class code */ + uint8_t bInterfaceSubClass; /*!< Interface subclass code */ + uint8_t bInterfaceProtocol; /*!< Interface protocol code */ + uint8_t iInterface; /*!< Interface ID */ +} DESC_IF_T; /*!< Interface descriptor structure */ + +/* + * Endpoint Descriptor + */ +typedef struct __attribute__((__packed__)) usb_endpoint_descriptor /*!< Endpoint descriptor structure */ +{ + uint8_t bLength; /*!< Length of endpoint descriptor */ + uint8_t bDescriptorType; /*!< Descriptor type */ + uint8_t bEndpointAddress; /*!< Endpoint address */ + uint8_t bmAttributes; /*!< Endpoint attribute */ + uint16_t wMaxPacketSize; /*!< Maximum packet size */ + uint8_t bInterval; /*!< Synchronous transfer interval */ + uint8_t bRefresh; /*!< Refresh */ + uint8_t bSynchAddress; /*!< Sync address */ +} DESC_EP_T; /*!< Endpoint descriptor structure */ + +/* + * Endpoint descriptor bEndpointAddress[7] - direction + */ +#define EP_ADDR_DIR_MASK 0x80 +#define EP_ADDR_DIR_IN 0x80 +#define EP_ADDR_DIR_OUT 0x00 + +/* + * Endpoint descriptor bmAttributes[1:0] - transfer type + */ +#define EP_ATTR_TT_MASK 0x03 +#define EP_ATTR_TT_CTRL 0x00 +#define EP_ATTR_TT_ISO 0x01 +#define EP_ATTR_TT_BULK 0x02 +#define EP_ATTR_TT_INT 0x03 + + +/*----------------------------------------------------------------------------------*/ +/* USB Host controller driver */ +/*----------------------------------------------------------------------------------*/ +typedef struct +{ + int (*init)(void); + void (*shutdown)(void); + void (*suspend)(void); + void (*resume)(void); + int (*ctrl_xfer)(struct utr_t *utr); + int (*bulk_xfer)(struct utr_t *utr); + int (*int_xfer)(struct utr_t *utr); + int (*iso_xfer)(struct utr_t *utr); + int (*quit_xfer)(struct utr_t *utr, struct ep_info_t *ep); + + /* root hub support */ + int (*rthub_port_reset)(int port); + int (*rthub_polling)(void); +} HC_DRV_T; + + +/*----------------------------------------------------------------------------------*/ +/* USB device driver */ +/*----------------------------------------------------------------------------------*/ +typedef struct +{ + int (*probe)(struct iface_t *iface); + void (*disconnect)(struct iface_t *iface); + void (*suspend)(struct iface_t *iface); + void (*resume)(struct iface_t *iface); +} UDEV_DRV_T; + + +/*----------------------------------------------------------------------------------*/ +/* USB device */ +/*----------------------------------------------------------------------------------*/ + +typedef enum +{ + SPEED_LOW, + SPEED_FULL, + SPEED_HIGH +} SPEED_E; + +typedef struct ep_info_t +{ + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint8_t bInterval; + uint8_t bToggle; + uint16_t wMaxPacketSize; + void *hw_pipe; /*!< point to the HC assocaied endpoint \hideinitializer */ +} EP_INFO_T; + +typedef struct udev_t +{ + DESC_DEV_T descriptor; /*!< Device descriptor. \hideinitializer */ + struct hub_dev_t *parent; /*!< parent hub device \hideinitializer */ + uint8_t port_num; /*!< The hub port this device connected on \hideinitializer */ + uint8_t dev_num; /*!< device number \hideinitializer */ + int8_t cur_conf; /*!< Currentll selected configuration \hideinitializer */ + SPEED_E speed; /*!< device speed (low/full/high) \hideinitializer */ + /* + * The followings are lightweight USB stack internal used . + */ + uint8_t *cfd_buff; /*!< Configuration descriptor buffer. \hideinitializer */ + EP_INFO_T ep0; /*!< Endpoint 0 \hideinitializer */ + HC_DRV_T *hc_driver; /*!< host controller driver \hideinitializer */ + struct iface_t *iface_list; /*!< Working interface list \hideinitializer */ + struct udev_t *next; /*!< link for global usb device list \hideinitializer */ +} UDEV_T; + +typedef struct alt_iface_t +{ + DESC_IF_T *ifd; /*!< point to the location of this alternative interface descriptor in UDEV_T->cfd_buff */ + EP_INFO_T ep[MAX_EP_PER_IFACE]; /*!< endpoints of this alternative interface */ +} ALT_IFACE_T; + +typedef struct iface_t +{ + UDEV_T *udev; /*!< USB device \hideinitializer */ + uint8_t if_num; /*!< Interface number \hideinitializer */ + uint8_t num_alt; /*!< Number of alternative interface \hideinitializer */ + ALT_IFACE_T *aif; /*!< Point to the active alternative interface */ + ALT_IFACE_T alt[MAX_ALT_PER_IFACE]; /*!< List of alternative interface \hideinitializer */ + UDEV_DRV_T *driver; /*!< Interface associated driver \hideinitializer */ + void *context; /*!< Reference to device context \hideinitializer */ + struct iface_t *next; /*!< Point to next interface of the same device. Started from UDEV_T->iface_list \hideinitializer */ +} IFACE_T; + + +/*----------------------------------------------------------------------------------*/ +/* URB (USB Request Block) */ +/*----------------------------------------------------------------------------------*/ + +#define IF_PER_UTR 8 /* number of frames per UTR isochronous transfer (DO NOT modify it!) */ + +typedef void (*FUNC_UTR_T)(struct utr_t *); + +typedef struct utr_t +{ + UDEV_T *udev; /*!< point to associated USB device \hideinitializer */ + DEV_REQ_T setup; /*!< buffer for setup packet \hideinitializer */ + EP_INFO_T *ep; /*!< associated endpoint \hideinitializer */ + uint8_t *buff; /*!< transfer buffer \hideinitializer */ + uint8_t bIsTransferDone; /*!< tansfer done? \hideinitializer */ + uint32_t data_len; /*!< length of data to be transferred \hideinitializer */ + uint32_t xfer_len; /*!< length of transferred data \hideinitializer */ + uint8_t bIsoNewSched; /*!< New schedule isochronous transfer \hideinitializer */ + uint16_t iso_sf; /*!< Isochronous start frame number \hideinitializer */ + uint16_t iso_xlen[IF_PER_UTR]; /*!< transfer length of isochronous frames \hideinitializer */ + uint8_t *iso_buff[IF_PER_UTR]; /*!< transfer buffer address of isochronous frames \hideinitializer */ + int iso_status[IF_PER_UTR]; /*!< transfer status of isochronous frames \hideinitializer */ + int td_cnt; /*!< number of transfer descriptors \hideinitializer */ + int status; /*!< return status \hideinitializer */ + int interval; /*!< interrupt/isochronous interval \hideinitializer */ + void *context; /*!< point to deivce proprietary data area \hideinitializer */ + FUNC_UTR_T func; /*!< tansfer done call-back function \hideinitializer */ + struct utr_t *next; /* point to the next UTR of the same endpoint. \hideinitializer */ +} UTR_T; + + +/*----------------------------------------------------------------------------------*/ +/* Global variables */ +/*----------------------------------------------------------------------------------*/ +extern USBH_T *_ohci; +extern HSUSBH_T *_ehci; + +extern HC_DRV_T ohci_driver; +extern HC_DRV_T ehci_driver; + +extern UDEV_T *g_udev_list; + +extern volatile int _IsInUsbInterrupt; + +/*----------------------------------------------------------------------------------*/ +/* USB stack exported functions */ +/*----------------------------------------------------------------------------------*/ +extern void usbh_delay_ms(int msec); + +extern void dump_ohci_regs(void); +extern void dump_ohci_ports(void); +extern void dump_ohci_int_table(void); +extern void dump_ehci_regs(void); +extern void dump_ehci_qtd(qTD_T *qtd); +extern void dump_ehci_asynclist(void); +extern void dump_ehci_period_frame_list_simple(void); +extern void usbh_dump_buff_bytes(uint8_t *buff, int nSize); +extern void usbh_dump_interface_descriptor(DESC_IF_T *if_desc); +extern void usbh_dump_endpoint_descriptor(DESC_EP_T *ep_desc); +extern void usbh_dump_iface(IFACE_T *iface); +extern void usbh_dump_ep_info(EP_INFO_T *ep); + +/* + * Memory management functions + */ +extern void USB_InitializeMemoryPool(void); +extern void *USB_malloc(int wanted_size, int boundary); +extern void USB_free(void *); +extern int USB_available_memory(void); +extern int USB_allocated_memory(void); +extern void usbh_memory_init(void); +extern uint32_t usbh_memory_used(void); +extern void *usbh_alloc_mem(int size); +extern void usbh_free_mem(void *p, int size); +extern int alloc_dev_address(void); +extern void free_dev_address(int dev_addr); +extern UDEV_T *alloc_device(void); +extern void free_device(UDEV_T *udev); +extern UTR_T *alloc_utr(UDEV_T *udev); +extern void free_utr(UTR_T *utr); +extern ED_T *alloc_ohci_ED(void); +extern void free_ohci_ED(ED_T *ed); +extern TD_T *alloc_ohci_TD(UTR_T *utr); +extern void free_ohci_TD(TD_T *td); +extern QH_T *alloc_ehci_QH(void); +extern void free_ehci_QH(QH_T *qh); +extern qTD_T *alloc_ehci_qTD(UTR_T *utr); +extern void free_ehci_qTD(qTD_T *qtd); +extern iTD_T *alloc_ehci_iTD(void); +extern void free_ehci_iTD(iTD_T *itd); +extern siTD_T *alloc_ehci_siTD(void); +extern void free_ehci_siTD(siTD_T *sitd); + + +extern void usbh_hub_init(void); +extern int usbh_connect_device(UDEV_T *); +extern void usbh_disconnect_device(UDEV_T *); +extern int usbh_register_driver(UDEV_DRV_T *driver); +extern EP_INFO_T *usbh_iface_find_ep(IFACE_T *iface, uint8_t ep_addr, uint8_t dir_type); +extern int usbh_reset_device(UDEV_T *); +extern int usbh_reset_port(UDEV_T *); + +/* + * USB Standard Request functions + */ +extern int usbh_get_device_descriptor(UDEV_T *udev, DESC_DEV_T *desc_buff); +extern int usbh_get_config_descriptor(UDEV_T *udev, uint8_t *desc_buff, int buff_len); +extern int usbh_set_configuration(UDEV_T *udev, uint8_t conf_val); +extern int usbh_set_interface(IFACE_T *iface, uint16_t alt_setting); +extern int usbh_clear_halt(UDEV_T *udev, uint16_t ep_addr); + +extern int usbh_ctrl_xfer(UDEV_T *udev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t *buff, uint32_t *xfer_len, uint32_t timeout); +extern int usbh_bulk_xfer(UTR_T *utr); +extern int usbh_int_xfer(UTR_T *utr); +extern int usbh_iso_xfer(UTR_T *utr); +extern int usbh_quit_utr(UTR_T *utr); +extern int usbh_quit_xfer(UDEV_T *udev, EP_INFO_T *ep); + + +/// @endcond HIDDEN_SYMBOLS + +#endif /* _USBH_H_ */ diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usbh_lib.h b/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usbh_lib.h new file mode 100644 index 0000000000..ecf336e474 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usbh_lib.h @@ -0,0 +1,188 @@ +/**************************************************************************//** + * @file usbh_lib.h + * @version V1.10 + * $Revision: 4 $ + * $Date: 15/06/10 2:06p $ + * @brief USB Host library exported header file. + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2017 Nuvoton Technology Corp. All rights reserved. + ******************************************************************************/ +#ifndef _USBH_LIB_H_ +#define _USBH_LIB_H_ + +#include "N9H30.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup Library Library + @{ +*/ + +/** @addtogroup USBH_Library USB Host Library + @{ +*/ + +/** @addtogroup USBH_EXPORTED_CONSTANTS USB Host Exported Constants + @{ +*/ + +#define USBH_OK 0 /*!< No error. */ +#define USBH_ERR_MEMORY_OUT -10 /*!< Out of memory. */ +#define USBH_ERR_IF_ALT_LIMIT -11 /*!< Number of alternative interface > MAX_ALT_PER_IFACE */ +#define USBH_ERR_IF_EP_LIMIT -15 /*!< Number of endpoints > MAX_EP_PER_IFACE */ +#define USBH_ERR_NOT_SUPPORTED -101 /*!< Device/Class/Transfer not supported */ +#define USBH_ERR_NOT_MATCHED -103 /*!< Not macthed */ +#define USBH_ERR_NOT_EXPECTED -104 /*!< Unknown or unexpected */ +#define USBH_ERR_INVALID_PARAM -105 /*!< Invalid parameter */ +#define USBH_ERR_NOT_FOUND -106 /*!< Device or interface not found */ +#define USBH_ERR_EP_NOT_FOUND -107 /*!< Endpoint not found */ +#define USBH_ERR_DESCRIPTOR -137 /*!< Failed to parse USB descriptors */ +#define USBH_ERR_SET_DEV_ADDR -139 /*!< Failed to set device address */ +#define USBH_ERR_SET_CONFIG -151 /*!< Failed to set device configuration */ + +#define USBH_ERR_TRANSFER -201 /*!< USB transfer error */ +#define USBH_ERR_TIMEOUT -203 /*!< USB transfer time-out */ +#define USBH_ERR_ABORT -205 /*!< USB transfer aborted due to disconnect or reset */ +#define USBH_ERR_PORT_RESET -255 /*!< Hub port reset failed */ +#define USBH_ERR_SCH_OVERRUN -257 /*!< USB isochronous schedule overrun */ +#define USBH_ERR_DISCONNECTED -259 /*!< USB device was disconnected */ + +#define USBH_ERR_TRANSACTION -271 /*!< USB transaction timeout, CRC, Bad PID, etc. */ +#define USBH_ERR_BABBLE_DETECTED -272 /*!< A babble is detected during the transaction */ +#define USBH_ERR_DATA_BUFF -274 /*!< Data buffer overrun or underrun */ + +#define USBH_ERR_CC_NO_ERR -280 /*!< OHCI CC code - no error */ +#define USBH_ERR_CRC -281 /*!< USB trasfer CRC error */ +#define USBH_ERR_BIT_STUFF -282 /*!< USB transfer bit stuffing error */ +#define USBH_ERR_DATA_TOGGLE -283 /*!< USB trasfer data toggle error */ +#define USBH_ERR_STALL -284 /*!< USB trasfer STALL error */ +#define USBH_ERR_DEV_NO_RESP -285 /*!< USB trasfer device no response error */ +#define USBH_ERR_PID_CHECK -286 /*!< USB trasfer PID check failure */ +#define USBH_ERR_UNEXPECT_PID -287 /*!< USB trasfer unexpected PID error */ +#define USBH_ERR_DATA_OVERRUN -288 /*!< USB trasfer data overrun error */ +#define USBH_ERR_DATA_UNDERRUN -289 /*!< USB trasfer data underrun error */ +#define USBH_ERR_BUFF_OVERRUN -292 /*!< USB trasfer buffer overrun error */ +#define USBH_ERR_BUFF_UNDERRUN -293 /*!< USB trasfer buffer underrun error */ +#define USBH_ERR_NOT_ACCESS0 -294 /*!< USB trasfer not accessed error */ +#define USBH_ERR_NOT_ACCESS1 -295 /*!< USB trasfer not accessed error */ + +#define USBH_ERR_OHCI_INIT -301 /*!< Failed to initialize OHIC controller. */ +#define USBH_ERR_OHCI_EP_BUSY -303 /*!< The endpoint is under transfer. */ + +#define USBH_ERR_EHCI_INIT -501 /*!< Failed to initialize EHCI controller. */ +#define USBH_ERR_EHCI_QH_BUSY -503 /*!< the Queue Head is busy. */ + +#define UMAS_OK 0 /*!< No error. */ +#define UMAS_ERR_NO_DEVICE -1031 /*!< No Mass Stroage Device found. */ +#define UMAS_ERR_IO -1033 /*!< Device read/write failed. */ +#define UMAS_ERR_INIT_DEVICE -1035 /*!< failed to init MSC device */ +#define UMAS_ERR_CMD_STATUS -1037 /*!< SCSI command status failed */ +#define UMAS_ERR_IVALID_PARM -1038 /*!< Invalid parameter. */ +#define UMAS_ERR_DRIVE_NOT_FOUND -1039 /*!< drive not found */ + +#define HID_RET_OK 0 /*!< Return with no errors. */ +#define HID_RET_DEV_NOT_FOUND -1081 /*!< HID device not found or removed. */ +#define HID_RET_IO_ERR -1082 /*!< USB transfer failed. */ +#define HID_RET_INVALID_PARAMETER -1083 /*!< Invalid parameter. */ +#define HID_RET_OUT_OF_MEMORY -1084 /*!< Out of memory. */ +#define HID_RET_NOT_SUPPORTED -1085 /*!< Function not supported. */ +#define HID_RET_EP_NOT_FOUND -1086 /*!< Endpoint not found. */ +#define HID_RET_PARSING -1087 /*!< Failed to parse HID descriptor */ +#define HID_RET_XFER_IS_RUNNING -1089 /*!< The transfer has been enabled. */ +#define HID_RET_REPORT_NOT_FOUND -1090 /*!< The transfer has been enabled. */ + +#define UAC_RET_OK 0 /*!< Return with no errors. */ +#define UAC_RET_DEV_NOT_FOUND -2001 /*!< Audio Class device not found or removed. */ +#define UAC_RET_FUNC_NOT_FOUND -2002 /*!< Audio device has no this function. */ +#define UAC_RET_IO_ERR -2003 /*!< USB transfer failed. */ +#define UAC_RET_DATA_LEN -2004 /*!< Unexpected transfer length */ +#define UAC_RET_INVALID -2005 /*!< Invalid parameter or usage. */ +#define UAC_RET_OUT_OF_MEMORY -2007 /*!< Out of memory. */ +#define UAC_RET_DRV_NOT_SUPPORTED -2009 /*!< Function not supported by this UAC driver. */ +#define UAC_RET_DEV_NOT_SUPPORTED -2011 /*!< Function not supported by the UAC device. */ +#define UAC_RET_PARSER -2013 /*!< Failed to parse UAC descriptor */ +#define UAC_RET_IS_STREAMING -2015 /*!< Audio pipe is on streaming. */ + + +/*@}*/ /* end of group USBH_EXPORTED_CONSTANTS */ + + +/** @addtogroup USBH_EXPORTED_TYPEDEF USB Host Typedef + @{ +*/ +struct udev_t; +typedef void (CONN_FUNC)(struct udev_t *udev, int param); + +struct line_coding_t; +struct cdc_dev_t; +typedef void (CDC_CB_FUNC)(struct cdc_dev_t *cdev, uint8_t *rdata, int data_len); + +struct usbhid_dev; +typedef void (HID_IR_FUNC)(struct usbhid_dev *hdev, uint16_t ep_addr, int status, uint8_t *rdata, uint32_t data_len); /*!< interrupt in callback function \hideinitializer */ +typedef void (HID_IW_FUNC)(struct usbhid_dev *hdev, uint16_t ep_addr, int status, uint8_t *wbuff, uint32_t *data_len); /*!< interrupt out callback function \hideinitializer */ + +struct uac_dev_t; +typedef int (UAC_CB_FUNC)(struct uac_dev_t *dev, uint8_t *data, int len); /*!< audio in callback function \hideinitializer */ + +/*@}*/ /* end of group USBH_EXPORTED_STRUCT */ + + + +/** @addtogroup USBH_EXPORTED_FUNCTIONS USB Host Exported Functions + @{ +*/ + +/*------------------------------------------------------------------*/ +/* */ +/* USB Core Library APIs */ +/* */ +/*------------------------------------------------------------------*/ +extern void usbh_core_init(void); +extern int usbh_polling_root_hubs(void); +extern void usbh_install_conn_callback(CONN_FUNC *conn_func, CONN_FUNC *disconn_func); +extern void usbh_suspend(void); +extern void usbh_resume(void); +extern struct udev_t *usbh_find_device(char *hub_id, int port); + +/** + * @brief A function return current tick count. + * @return Current tick. + * @details User application must provide this function to return current tick. + * The tick should increase by 1 for every 10 ms. + */ +extern uint32_t usbh_get_ticks(void); /* This function must be provided by user application. */ +extern uint32_t usbh_tick_from_millisecond(uint32_t msec); /* This function must be provided by user application. */ + + +/// @cond HIDDEN_SYMBOLS + +extern void dump_ohci_regs(void); +extern void dump_ehci_regs(void); +extern void dump_ohci_ports(void); +extern void dump_ehci_ports(void); +extern uint32_t usbh_memory_used(void); + +/// @endcond HIDDEN_SYMBOLS + + +/*@}*/ /* end of group USBH_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group USBH_Library */ + +/*@}*/ /* end of group LIBRARY */ + +#ifdef __cplusplus +} +#endif + +#endif /* _USBH_LIB_H_ */ + +/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/ + + + diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci.c b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci.c new file mode 100644 index 0000000000..dbcda52196 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci.c @@ -0,0 +1,1288 @@ +/**************************************************************************//** + * @file ehci.c + * @version V1.10 + * $Revision: 11 $ + * $Date: 14/10/03 1:54p $ + * @brief USB Host library EHCI (USB 2.0) host controller driver. + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2017 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include +#include +#include + +#include "usb.h" +#include "hub.h" + + +/// @cond HIDDEN_SYMBOLS + +static QH_T *_H_qh; /* head of reclamation list */ +static qTD_T *_ghost_qtd; /* used as a terminator qTD */ +static QH_T *qh_remove_list; + +extern ISO_EP_T *iso_ep_list; /* list of activated isochronous pipes */ +extern int ehci_iso_xfer(UTR_T *utr); /* EHCI isochronous transfer function */ +extern int ehci_quit_iso_xfer(UTR_T *utr, EP_INFO_T *ep); + +uint32_t _PFList_mem[FL_SIZE] __attribute__((aligned(4096)));/* Periodic frame list (Keil) */ + +uint32_t *_PFList; + + +QH_T *_Iqh[NUM_IQH]; + + +#ifdef ENABLE_ERROR_MSG +void dump_ehci_regs() +{ + USB_debug("Dump HSUSBH(EHCI) registers:\n"); + USB_debug(" UCMDR = 0x%x\n", _ehci->UCMDR); + USB_debug(" USTSR = 0x%x\n", _ehci->USTSR); + USB_debug(" UIENR = 0x%x\n", _ehci->UIENR); + USB_debug(" UFINDR = 0x%x\n", _ehci->UFINDR); + USB_debug(" UPFLBAR = 0x%x\n", _ehci->UPFLBAR); + USB_debug(" UCALAR = 0x%x\n", _ehci->UCALAR); + USB_debug(" UASSTR = 0x%x\n", _ehci->UASSTR); + USB_debug(" UCFGR = 0x%x\n", _ehci->UCFGR); + USB_debug(" UPSCR = 0x%x\n", _ehci->UPSCR[0]); + USB_debug(" PHYCTL0 = 0x%x\n", _ehci->USBPCR0); + USB_debug(" PHYCTL1 = 0x%x\n", _ehci->USBPCR1); +} + +void dump_ehci_ports() +{ + USB_debug("_ehci port0=0x%x, port1=0x%x\n", _ehci->UPSCR[0], _ehci->UPSCR[1]); +} + +void dump_ehci_qtd(qTD_T *qtd) +{ + USB_debug(" [qTD] - 0x%08x\n", (int)qtd); + USB_debug(" 0x%08x (Next qtd Pointer)\n", qtd->Next_qTD); + USB_debug(" 0x%08x (Alternate Next qtd Pointer)\n", qtd->Alt_Next_qTD); + USB_debug(" 0x%08x (qtd Token) PID: %s, Bytes: %d, IOC: %d\n", qtd->Token, (((qtd->Token >> 8) & 0x3) == 0) ? "OUT" : ((((qtd->Token >> 8) & 0x3) == 1) ? "IN" : "SETUP"), (qtd->Token >> 16) & 0x7FFF, (qtd->Token >> 15) & 0x1); + USB_debug(" 0x%08x (Buffer Pointer (page 0))\n", qtd->Bptr[0]); + //USB_debug(" 0x%08x (Buffer Pointer (page 1))\n", qtd->Bptr[1]); + //USB_debug(" 0x%08x (Buffer Pointer (page 2))\n", qtd->Bptr[2]); + //USB_debug(" 0x%08x (Buffer Pointer (page 3))\n", qtd->Bptr[3]); + //USB_debug(" 0x%08x (Buffer Pointer (page 4))\n", qtd->Bptr[4]); + USB_debug("\n"); +} + +void dump_ehci_asynclist(void) +{ + QH_T *qh = _H_qh; + qTD_T *qtd; + + USB_debug(">>> Dump EHCI Asynchronous List <<<\n"); + do + { + USB_debug("[QH] - 0x%08x\n", (int)qh); + USB_debug(" 0x%08x (Queue Head Horizontal Link Pointer, Queue Head DWord 0)\n", qh->HLink); + USB_debug(" 0x%08x (Endpoint Characteristics) DevAddr: %d, EP: 0x%x, PktSz: %d, Speed: %s\n", qh->Chrst, qh->Chrst & 0x7F, (qh->Chrst >> 8) & 0xF, (qh->Chrst >> 16) & 0x7FF, ((qh->Chrst >> 12) & 0x3 == 0) ? "Full" : (((qh->Chrst >> 12) & 0x3 == 1) ? "Low" : "High")); + USB_debug(" 0x%08x (Endpoint Capabilities: Queue Head DWord 2)\n", qh->Cap); + USB_debug(" 0x%08x (Current qtd Pointer)\n", qh->Curr_qTD); + USB_debug(" --- Overlay Area ---\n"); + USB_debug(" 0x%08x (Next qtd Pointer)\n", qh->OL_Next_qTD); + USB_debug(" 0x%08x (Alternate Next qtd Pointer)\n", qh->OL_Alt_Next_qTD); + USB_debug(" 0x%08x (qtd Token)\n", qh->OL_Token); + USB_debug(" 0x%08x (Buffer Pointer (page 0))\n", qh->OL_Bptr[0]); + USB_debug("\n"); + + qtd = QTD_PTR(qh->Curr_qTD); + while (qtd != NULL) + { + dump_ehci_qtd(qtd); + qtd = QTD_PTR(qtd->Next_qTD); + } + qh = QH_PTR(qh->HLink); + } + while (qh != _H_qh); +} + +void dump_ehci_asynclist_simple(void) +{ + QH_T *qh = _H_qh; + + USB_debug(">>> EHCI Asynchronous List <<<\n"); + USB_debug("[QH] => "); + do + { + USB_debug("0x%08x ", (int)qh); + qh = QH_PTR(qh->HLink); + } + while (qh != _H_qh); + USB_debug("\n"); +} + +void dump_ehci_period_frame_list_simple(void) +{ + QH_T *qh = _Iqh[NUM_IQH - 1]; + + USB_debug(">>> EHCI period frame list simple <<<\n"); + USB_debug("[FList] => "); + do + { + USB_debug("0x%08x ", (int)qh); + qh = QH_PTR(qh->HLink); + } + while (qh != NULL); + USB_debug("\n"); +} + +void dump_ehci_period_frame_list() +{ + int i; + QH_T *qh; + + for (i = 0; i < FL_SIZE; i++) + { + USB_debug("!%02d: ", i); + qh = QH_PTR(_PFList[i]);; + while (qh != NULL) + { + // USB_debug("0x%x (0x%x) => ", (int)qh, qh->HLink); + USB_debug("0x%x => ", (int)qh); + qh = QH_PTR(qh->HLink); + } + USB_debug("0\n"); + } +} + +#endif /* ENABLE_ERROR_MSG */ + +static void init_periodic_frame_list() +{ + QH_T *qh_p; + int i, idx, interval; + + _PFList = (uint32_t *)((uint32_t)_PFList_mem | NON_CACHE_MASK); + memset(_PFList, 0, sizeof(_PFList_mem)); + + iso_ep_list = NULL; + + for (i = NUM_IQH - 1; i >= 0; i--) /* interval = i^2 */ + { + _Iqh[i] = alloc_ehci_QH(); + + _Iqh[i]->HLink = QH_HLNK_END; + _Iqh[i]->Curr_qTD = (uint32_t)_ghost_qtd; + _Iqh[i]->OL_Next_qTD = QTD_LIST_END; + _Iqh[i]->OL_Alt_Next_qTD = (uint32_t)_ghost_qtd; + _Iqh[i]->OL_Token = QTD_STS_HALT; + + interval = 0x1 << i; + + for (idx = interval - 1; idx < FL_SIZE; idx += interval) + { + if (_PFList[idx] == 0) /* is empty list, insert directly */ + { + _PFList[idx] = QH_HLNK_QH(_Iqh[i]); + } + else + { + qh_p = QH_PTR(_PFList[idx]); + + while (1) + { + if (qh_p == _Iqh[i]) + break; /* already chained by previous visit */ + + if (qh_p->HLink == QH_HLNK_END) /* reach end of list? */ + { + qh_p->HLink = QH_HLNK_QH(_Iqh[i]); + break; + } + qh_p = QH_PTR(qh_p->HLink); + } + } + } + } +} + +static QH_T *get_int_tree_head_node(int interval) +{ + int i; + + interval /= 8; /* each frame list entry for 8 micro-frame */ + + for (i = 0; i < NUM_IQH - 1; i++) + { + interval >>= 1; + if (interval == 0) + return _Iqh[i]; + } + return _Iqh[NUM_IQH - 1]; +} + +static int make_int_s_mask(int bInterval) +{ + int order, interval; + + interval = 1; + while (bInterval > 1) + { + interval *= 2; + bInterval--; + } + + if (interval < 2) + return 0xFF; /* interval 1 */ + if (interval < 4) + return 0x55; /* interval 2 */ + if (interval < 8) + return 0x22; /* interval 4 */ + for (order = 0; (interval > 1); order++) + { + interval >>= 1; + } + return (0x1 << (order % 8)); +} + +static int ehci_init(void) +{ + int timeout = 250 * 1000; /* EHCI reset time-out 250 ms */ + + /*------------------------------------------------------------------------------------*/ + /* Reset EHCI host controller */ + /*------------------------------------------------------------------------------------*/ + _ehci->UCMDR = HSUSBH_UCMDR_HCRST_Msk; + while ((_ehci->UCMDR & HSUSBH_UCMDR_HCRST_Msk) && (timeout > 0)) + { + usbh_delay_ms(1); + timeout -= 1000; + } + if (_ehci->UCMDR & HSUSBH_UCMDR_HCRST_Msk) + return USBH_ERR_EHCI_INIT; + + _ehci->UCMDR = UCMDR_INT_THR_CTRL | HSUSBH_UCMDR_RUN_Msk; + + _ghost_qtd = alloc_ehci_qTD(NULL); + _ghost_qtd->Token = 0x11197B7F; //QTD_STS_HALT; visit_qtd() will not remove a qTD with this mark. It represents a qhost qTD. + + /*------------------------------------------------------------------------------------*/ + /* Initialize asynchronous list */ + /*------------------------------------------------------------------------------------*/ + qh_remove_list = NULL; + + /* Create the QH list head with H-bit 1 */ + _H_qh = alloc_ehci_QH(); + _H_qh->HLink = QH_HLNK_QH(_H_qh); /* circular link to itself, the only one QH */ + _H_qh->Chrst = QH_RCLM_LIST_HEAD; /* it's the head of reclamation list */ + _H_qh->Curr_qTD = (uint32_t)_ghost_qtd; + _H_qh->OL_Next_qTD = QTD_LIST_END; + _H_qh->OL_Alt_Next_qTD = (uint32_t)_ghost_qtd; + _H_qh->OL_Token = QTD_STS_HALT; + _ehci->UCALAR = (uint32_t)_H_qh; + + /*------------------------------------------------------------------------------------*/ + /* Initialize periodic list */ + /*------------------------------------------------------------------------------------*/ + if (FL_SIZE == 256) + _ehci->UCMDR |= (0x2 << HSUSBH_UCMDR_FLSZ_Pos); + else if (FL_SIZE == 512) + _ehci->UCMDR |= (0x1 << HSUSBH_UCMDR_FLSZ_Pos); + else if (FL_SIZE == 1024) + _ehci->UCMDR |= (0x0 << HSUSBH_UCMDR_FLSZ_Pos); + else + return USBH_ERR_EHCI_INIT; /* Invalid FL_SIZE setting! */ + + /*------------------------------------------------------------------------------------*/ + /* start run */ + /*------------------------------------------------------------------------------------*/ + + _ehci->UCFGR = 0x1; /* enable port routing to EHCI */ + _ehci->UIENR = HSUSBH_UIENR_USBIEN_Msk | HSUSBH_UIENR_UERRIEN_Msk | HSUSBH_UIENR_HSERREN_Msk | HSUSBH_UIENR_IAAEN_Msk; + + usbh_delay_ms(1); /* delay 1 ms */ + + _ehci->UPSCR[0] = HSUSBH_UPSCR_PP_Msk; /* enable port 1 port power */ + _ehci->UPSCR[1] = HSUSBH_UPSCR_PP_Msk; /* enable port 2 port power */ + + init_periodic_frame_list(); + + _ehci->UPFLBAR = (uint32_t)_PFList; + usbh_delay_ms(10); /* delay 10 ms */ + + return 0; +} + +static void ehci_suspend(void) +{ + if (_ehci->UPSCR[0] & 0x1) + _ehci->UPSCR[0] |= HSUSBH_UPSCR_SUSPEND_Msk; +} + +static void ehci_resume(void) +{ + if (_ehci->UPSCR[0] & 0x1) + _ehci->UPSCR[0] = (HSUSBH->UPSCR[0] & ~HSUSBH_UPSCR_SUSPEND_Msk) | HSUSBH_UPSCR_FPR_Msk; +} + +static void ehci_shutdown(void) +{ + ehci_suspend(); +} + +static void move_qh_to_remove_list(QH_T *qh) +{ + QH_T *q; + + // USB_debug("move_qh_to_remove_list - 0x%x (0x%x)\n", (int)qh, qh->Chrst); + + /* check if this ED found in ed_remove_list */ + q = qh_remove_list; + while (q) + { + if (q == qh) /* This QH found in qh_remove_list. */ + { + return; /* Do nothing, return... */ + } + q = q->next; + } + + DISABLE_EHCI_IRQ(); + + /*------------------------------------------------------------------------------------*/ + /* Search asynchronous frame list and remove qh if found in list. */ + /*------------------------------------------------------------------------------------*/ + q = _H_qh; /* find and remove it from asynchronous list */ + while (QH_PTR(q->HLink) != _H_qh) + { + if (QH_PTR(q->HLink) == qh) + { + /* q's next QH is qh, found... */ + q->HLink = qh->HLink; /* remove qh from list */ + + qh->next = qh_remove_list; /* add qh to qh_remove_list */ + qh_remove_list = qh; + _ehci->UCMDR |= HSUSBH_UCMDR_IAAD_Msk; /* trigger IAA interrupt */ + ENABLE_EHCI_IRQ(); + return; /* done */ + } + q = QH_PTR(q->HLink); /* advance to next QH in asynchronous list */ + } + + /*------------------------------------------------------------------------------------*/ + /* Search periodic frame list and remove qh if found in list. */ + /*------------------------------------------------------------------------------------*/ + q = _Iqh[NUM_IQH - 1]; + while (q->HLink != QH_HLNK_END) + { + if (QH_PTR(q->HLink) == qh) + { + /* q's next QH is qh, found... */ + q->HLink = qh->HLink; /* remove qh from list */ + + qh->next = qh_remove_list; /* add qh to qh_remove_list */ + qh_remove_list = qh; + _ehci->UCMDR |= HSUSBH_UCMDR_IAAD_Msk; /* trigger IAA interrupt */ + ENABLE_EHCI_IRQ(); + return; /* done */ + } + q = QH_PTR(q->HLink); /* advance to next QH in asynchronous list */ + } + ENABLE_EHCI_IRQ(); +} + +static void append_to_qtd_list_of_QH(QH_T *qh, qTD_T *qtd) +{ + qTD_T *q; + + if (qh->qtd_list == NULL) + { + qh->qtd_list = qtd; + } + else + { + q = qh->qtd_list; + while (q->next != NULL) + { + q = q->next; + } + q->next = qtd; + } +} + +/* + * If ep==NULL, it's a control endpoint QH. + */ +static void write_qh(UDEV_T *udev, EP_INFO_T *ep, QH_T *qh) +{ + uint32_t chrst, cap; + + /*------------------------------------------------------------------------------------*/ + /* Write QH DWord 1 - Endpoint Characteristics */ + /*------------------------------------------------------------------------------------*/ + if (ep == NULL) /* is control endpoint? */ + { + if (udev->descriptor.bMaxPacketSize0 == 0) + { + if (udev->speed == SPEED_LOW) /* give a default maximum packet size */ + udev->descriptor.bMaxPacketSize0 = 8; + else + udev->descriptor.bMaxPacketSize0 = 64; + } + chrst = QH_DTC | QH_NAK_RL | (udev->descriptor.bMaxPacketSize0 << 16); + if (udev->speed != SPEED_HIGH) + chrst |= QH_CTRL_EP_FLAG; /* non-high-speed control endpoint */ + } + else /* not a control endpoint */ + { + chrst = QH_NAK_RL | (ep->wMaxPacketSize << 16); + chrst |= ((ep->bEndpointAddress & 0xf) << 8); /* Endpoint Address */ + } + + if (udev->speed == SPEED_LOW) + chrst |= QH_EPS_LOW; + else if (udev->speed == SPEED_FULL) + chrst |= QH_EPS_FULL; + else + chrst |= QH_EPS_HIGH; + + chrst |= udev->dev_num; + + qh->Chrst = chrst; + + /*------------------------------------------------------------------------------------*/ + /* Write QH DWord 2 - Endpoint Capabilities */ + /*------------------------------------------------------------------------------------*/ + if (udev->speed == SPEED_HIGH) + { + cap = 0; + } + else + { + /* + * Backtrace device tree until the USB 2.0 hub found + */ + HUB_DEV_T *hub; + int port_num; + + port_num = udev->port_num; + hub = udev->parent; + + while ((hub != NULL) && (hub->iface->udev->speed != SPEED_HIGH)) + { + port_num = hub->iface->udev->port_num; + hub = hub->iface->udev->parent; + } + + cap = (port_num << QH_HUB_PORT_Pos) | + (hub->iface->udev->dev_num << QH_HUB_ADDR_Pos); + } + + qh->Cap = cap; +} + +static void write_qtd_bptr(qTD_T *qtd, uint32_t buff_addr, int xfer_len) +{ + int i; + + qtd->xfer_len = xfer_len; + qtd->Bptr[0] = buff_addr; + + buff_addr = (buff_addr + 0x1000) & ~0xFFF; + + for (i = 1; i < 5; i++) + { + qtd->Bptr[i] = buff_addr; + buff_addr += 0x1000; + } +} + +static int ehci_ctrl_xfer(UTR_T *utr) +{ + UDEV_T *udev; + QH_T *qh; + qTD_T *qtd_setup, *qtd_data, *qtd_status; + uint32_t token; + int is_new_qh = 0; + + udev = utr->udev; + + if (utr->data_len > 0) + { + if (((uint32_t)utr->buff + utr->data_len) > (((uint32_t)utr->buff & ~0xFFF) + 0x5000)) + return USBH_ERR_BUFF_OVERRUN; + } + + /*------------------------------------------------------------------------------------*/ + /* Allocate and link QH */ + /*------------------------------------------------------------------------------------*/ + if (udev->ep0.hw_pipe != NULL) + { + qh = (QH_T *)udev->ep0.hw_pipe; + if (qh->qtd_list) + return USBH_ERR_EHCI_QH_BUSY; + } + else + { + qh = alloc_ehci_QH(); + if (qh == NULL) + return USBH_ERR_MEMORY_OUT; + + udev->ep0.hw_pipe = (void *)qh; /* driver can find QH from EP */ + is_new_qh = 1; + } + write_qh(udev, NULL, qh); + utr->ep = &udev->ep0; /* driver can find EP from UTR */ + + /*------------------------------------------------------------------------------------*/ + /* Allocate qTDs */ + /*------------------------------------------------------------------------------------*/ + qtd_setup = alloc_ehci_qTD(utr); /* allocate qTD for SETUP */ + + if (utr->data_len > 0) + qtd_data = alloc_ehci_qTD(utr); /* allocate qTD for DATA */ + else + qtd_data = NULL; + + qtd_status = alloc_ehci_qTD(utr); /* allocate qTD for USTSR */ + + if (qtd_status == NULL) /* out of memory? */ + { + if (qtd_setup) + free_ehci_qTD(qtd_setup); /* free memory */ + if (qtd_data) + free_ehci_qTD(qtd_data); /* free memory */ + return USBH_ERR_MEMORY_OUT; /* out of memory */ + } + + //USB_debug("qh=0x%x, qtd_setup=0x%x, qtd_data=0x%x, qtd_status=0x%x\n", (int)qh, (int)qtd_setup, (int)qtd_data, (int)qtd_status); + + /*------------------------------------------------------------------------------------*/ + /* prepare SETUP stage qTD */ + /*------------------------------------------------------------------------------------*/ + qtd_setup->qh = qh; + //qtd_setup->utr = utr; + write_qtd_bptr(qtd_setup, (uint32_t)&utr->setup, 8); + append_to_qtd_list_of_QH(qh, qtd_setup); + qtd_setup->Token = (8 << 16) | QTD_ERR_COUNTER | QTD_PID_SETUP | QTD_STS_ACTIVE; + + /*------------------------------------------------------------------------------------*/ + /* prepare DATA stage qTD */ + /*------------------------------------------------------------------------------------*/ + if (utr->data_len > 0) + { + qtd_setup->Next_qTD = (uint32_t)qtd_data; + qtd_data->Next_qTD = (uint32_t)qtd_status; + + if ((utr->setup.bmRequestType & 0x80) == REQ_TYPE_OUT) + token = QTD_ERR_COUNTER | QTD_PID_OUT | QTD_STS_ACTIVE; + else + token = QTD_ERR_COUNTER | QTD_PID_IN | QTD_STS_ACTIVE; + + qtd_data->qh = qh; + //qtd_data->utr = utr; + write_qtd_bptr(qtd_data, (uint32_t)utr->buff, utr->data_len); + append_to_qtd_list_of_QH(qh, qtd_data); + qtd_data->Token = QTD_DT | (utr->data_len << 16) | token; + } + else + { + qtd_setup->Next_qTD = (uint32_t)qtd_status; + } + + /*------------------------------------------------------------------------------------*/ + /* prepare USTSR stage qTD */ + /*------------------------------------------------------------------------------------*/ + qtd_status->Next_qTD = (uint32_t)_ghost_qtd; + qtd_status->Alt_Next_qTD = QTD_LIST_END; + + if ((utr->setup.bmRequestType & 0x80) == REQ_TYPE_OUT) + token = QTD_ERR_COUNTER | QTD_PID_IN | QTD_STS_ACTIVE; + else + token = QTD_ERR_COUNTER | QTD_PID_OUT | QTD_STS_ACTIVE; + + qtd_status->qh = qh; + //qtd_status->utr = utr; + append_to_qtd_list_of_QH(qh, qtd_status); + qtd_status->Token = QTD_DT | QTD_IOC | token; + + /*------------------------------------------------------------------------------------*/ + /* Update QH overlay */ + /*------------------------------------------------------------------------------------*/ + qh->Curr_qTD = 0; + qh->OL_Next_qTD = (uint32_t)qtd_setup; + qh->OL_Alt_Next_qTD = QTD_LIST_END; + qh->OL_Token = 0; + + /*------------------------------------------------------------------------------------*/ + /* Link QH and start asynchronous transfer */ + /*------------------------------------------------------------------------------------*/ + if (is_new_qh) + { + qh->HLink = _H_qh->HLink; + _H_qh->HLink = QH_HLNK_QH(qh); + } + + /* Start transfer */ + _ehci->UCMDR |= HSUSBH_UCMDR_ASEN_Msk; /* start asynchronous transfer */ + return 0; +} + +static int ehci_bulk_xfer(UTR_T *utr) +{ + UDEV_T *udev; + EP_INFO_T *ep = utr->ep; + QH_T *qh; + qTD_T *qtd, *qtd_pre; + uint32_t data_len, xfer_len; + uint8_t *buff; + uint32_t token; + int is_new_qh = 0; + + //USB_debug("Bulk XFER =>\n"); + // dump_ehci_asynclist_simple(); + + udev = utr->udev; + + if (ep->hw_pipe != NULL) + { + qh = (QH_T *)ep->hw_pipe ; + if (qh->qtd_list) + { + return USBH_ERR_EHCI_QH_BUSY; + } + } + else + { + qh = alloc_ehci_QH(); + if (qh == NULL) + return USBH_ERR_MEMORY_OUT; + is_new_qh = 1; + write_qh(udev, ep, qh); + ep->hw_pipe = (void *)qh; /* associate QH with endpoint */ + } + + /*------------------------------------------------------------------------------------*/ + /* Prepare qTDs */ + /*------------------------------------------------------------------------------------*/ + data_len = utr->data_len; + buff = utr->buff; + qtd_pre = NULL; + + while (data_len > 0) + { + qtd = alloc_ehci_qTD(utr); + if (qtd == NULL) /* failed to allocate a qTD */ + { + qtd = qh->qtd_list; + while (qtd != NULL) + { + qtd_pre = qtd; + qtd = qtd->next; + free_ehci_qTD(qtd_pre); + } + if (is_new_qh) + { + free_ehci_QH(qh); + ep->hw_pipe = NULL; + } + return USBH_ERR_MEMORY_OUT; + } + + if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_OUT) + token = QTD_ERR_COUNTER | QTD_PID_OUT | QTD_STS_ACTIVE; + else + token = QTD_ERR_COUNTER | QTD_PID_IN | QTD_STS_ACTIVE; + + if (data_len > 0x4000) /* force maximum x'fer length 16K per qTD */ + xfer_len = 0x4000; + else + xfer_len = data_len; /* remaining data length < 4K */ + + qtd->qh = qh; + qtd->Next_qTD = (uint32_t)_ghost_qtd; + qtd->Alt_Next_qTD = QTD_LIST_END; //(uint32_t)_ghost_qtd; + write_qtd_bptr(qtd, (uint32_t)buff, xfer_len); + append_to_qtd_list_of_QH(qh, qtd); + qtd->Token = (xfer_len << 16) | token; + + buff += xfer_len; /* advanced buffer pointer */ + data_len -= xfer_len; + + if (data_len == 0) /* is this the latest qTD? */ + { + qtd->Token |= QTD_IOC; /* ask to raise an interrupt on the last qTD */ + qtd->Next_qTD = (uint32_t)_ghost_qtd; /* qTD list end */ + } + + if (qtd_pre != NULL) + qtd_pre->Next_qTD = (uint32_t)qtd; + qtd_pre = qtd; + } + + //USB_debug("utr=0x%x, qh=0x%x, qtd=0x%x\n", (int)utr, (int)qh, (int)qh->qtd_list); + + qtd = qh->qtd_list; + + qh->OL_Next_qTD = (uint32_t)qtd; + + /*------------------------------------------------------------------------------------*/ + /* Link QH and start asynchronous transfer */ + /*------------------------------------------------------------------------------------*/ + if (is_new_qh) + { + memcpy(&(qh->OL_Bptr[0]), &(qtd->Bptr[0]), 20); + qh->Curr_qTD = (uint32_t)qtd; + + qh->OL_Token = 0; //qtd->Token; + + if (utr->ep->bToggle) + qh->OL_Token |= QTD_DT; + + qh->HLink = _H_qh->HLink; + _H_qh->HLink = QH_HLNK_QH(qh); + } + + /* Start transfer */ + _ehci->UCMDR |= HSUSBH_UCMDR_ASEN_Msk; /* start asynchronous transfer */ + + return 0; +} + +static int ehci_int_xfer(UTR_T *utr) +{ + UDEV_T *udev = utr->udev; + EP_INFO_T *ep = utr->ep; + QH_T *qh, *iqh; + qTD_T *qtd; + uint32_t token; + int8_t is_new_qh = 0; + + if (ep->hw_pipe != NULL) + { + qh = (QH_T *)ep->hw_pipe ; + if (qh->qtd_list) + return USBH_ERR_EHCI_QH_BUSY; + } + else + { + qh = alloc_ehci_QH(); + if (qh == NULL) + return USBH_ERR_MEMORY_OUT; + is_new_qh = 1; + write_qh(udev, ep, qh); + qh->Chrst &= ~0xF0000000; + + if (udev->speed == SPEED_HIGH) + { + qh->Cap = (0x1 << QH_MULT_Pos) | (qh->Cap & 0xff) | make_int_s_mask(ep->bInterval); + } + else + { + qh->Cap = (0x1 << QH_MULT_Pos) | (qh->Cap & ~(QH_C_MASK_Msk | QH_S_MASK_Msk)) | 0x7802; + } + ep->hw_pipe = (void *)qh; /* associate QH with endpoint */ + } + + /*------------------------------------------------------------------------------------*/ + /* Prepare qTD */ + /*------------------------------------------------------------------------------------*/ + qtd = alloc_ehci_qTD(utr); + if (qtd == NULL) /* failed to allocate a qTD */ + { + if (is_new_qh) + { + free_ehci_QH(qh); + ep->hw_pipe = NULL; + } + return USBH_ERR_MEMORY_OUT; + } + + if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_OUT) + token = QTD_ERR_COUNTER | QTD_PID_OUT | QTD_STS_ACTIVE; + else + token = QTD_ERR_COUNTER | QTD_PID_IN | QTD_STS_ACTIVE; + + qtd->qh = qh; + qtd->Next_qTD = QTD_LIST_END; //(uint32_t)_ghost_qtd; + qtd->Alt_Next_qTD = QTD_LIST_END; //(uint32_t)_ghost_qtd; + write_qtd_bptr(qtd, (uint32_t)utr->buff, utr->data_len); + append_to_qtd_list_of_QH(qh, qtd); + qtd->Token = QTD_IOC | (utr->data_len << 16) | token; + + DISABLE_EHCI_IRQ(); + + USB_debug("ehci_int_xfer - qh: 0x%x, 0x%x, 0x%x, qtd: 0x%x\n", (int)qh, (int)qh->Chrst, (int)qh->Cap, (int)qtd); + + qh->OL_Next_qTD = (uint32_t)qtd; + + if (is_new_qh) + { + memcpy(&(qh->OL_Bptr[0]), &(qtd->Bptr[0]), 20); + qh->Curr_qTD = (uint32_t)qtd; + qh->OL_Token = qtd->Token; + + if (udev->speed == SPEED_HIGH) /* get head node of this interval */ + iqh = get_int_tree_head_node(ep->bInterval); + else + iqh = get_int_tree_head_node(ep->bInterval * 8); + qh->HLink = iqh->HLink; /* Add to list of the same interval */ + iqh->HLink = QH_HLNK_QH(qh); + } + + ENABLE_EHCI_IRQ(); + + _ehci->UCMDR |= HSUSBH_UCMDR_PSEN_Msk; /* periodic list enable */ + return 0; +} + +/* + * Quit current trasnfer via UTR or hardware EP. + */ +static int ehci_quit_xfer(UTR_T *utr, EP_INFO_T *ep) +{ + QH_T *qh; + + // USB_debug("ehci_quit_xfer - utr: 0x%x, ep: 0x%x\n", (int)utr, (int)ep); + + DISABLE_EHCI_IRQ(); + if (ehci_quit_iso_xfer(utr, ep) == 0) + { + ENABLE_EHCI_IRQ(); + return 0; + } + ENABLE_EHCI_IRQ(); + + if (utr != NULL) + { + if (utr->ep == NULL) + return USBH_ERR_NOT_FOUND; + + qh = (QH_T *)(utr->ep->hw_pipe); + + if (!qh) + return USBH_ERR_NOT_FOUND; + + /* add the QH to remove list, it will be removed on the next IAAD interrupt */ + move_qh_to_remove_list(qh); + utr->ep->hw_pipe = NULL; + } + + if ((ep != NULL) && (ep->hw_pipe != NULL)) + { + qh = (QH_T *)(ep->hw_pipe); + /* add the QH to remove list, it will be removed on the next IAAD interrupt */ + move_qh_to_remove_list(qh); + ep->hw_pipe = NULL; + } + usbh_delay_ms(2); + + return 0; +} + +static int visit_qtd(qTD_T *qtd) +{ + if ((qtd->Token == 0x11197B7F) || (qtd->Token == 0x1197B7F)) + return 0; /* A Dummy qTD or qTD on writing, don't touch it. */ + + // USB_debug("Visit qtd 0x%x - 0x%x\n", (int)qtd, qtd->Token); + + if ((qtd->Token & QTD_STS_ACTIVE) == 0) + { + if (qtd->Token & (QTD_STS_HALT | QTD_STS_DATA_BUFF_ERR | QTD_STS_BABBLE | QTD_STS_XactErr | QTD_STS_MISS_MF)) + { + USB_error("qTD 0x%x error token=0x%x! 0x%x\n", (int)qtd, qtd->Token, qtd->Bptr[0]); + if (qtd->utr->status == 0) + qtd->utr->status = USBH_ERR_TRANSACTION; + } + else + { + if ((qtd->Token & QTD_PID_Msk) != QTD_PID_SETUP) + { + qtd->utr->xfer_len += qtd->xfer_len - QTD_TODO_LEN(qtd->Token); + // USB_debug("0x%x utr->xfer_len += %d\n", qtd->Token, qtd->xfer_len - QTD_TODO_LEN(qtd->Token)); + } + } + return 1; + } + return 0; +} + +static void scan_asynchronous_list() +{ + QH_T *qh, *qh_tmp; + qTD_T *q_pre, *qtd, *qtd_tmp; + UTR_T *utr; + + qh = QH_PTR(_H_qh->HLink); + while (qh != _H_qh) + { + // USB_debug("Scan qh=0x%x, 0x%x\n", (int)qh, qh->OL_Token); + + utr = NULL; + qtd = qh->qtd_list; + while (qtd != NULL) + { + if (visit_qtd(qtd)) /* if TRUE, reclaim this qtd */ + { + /* qTD is completed, will remove it */ + utr = qtd->utr; + if (qtd == qh->qtd_list) + qh->qtd_list = qtd->next; /* unlink the qTD from qtd_list */ + else + q_pre->next = qtd->next; /* unlink the qTD from qtd_list */ + + qtd_tmp = qtd; /* remember this qTD for freeing later */ + qtd = qtd->next; /* advance to the next qTD */ + + qtd_tmp->next = qh->done_list; /* push this qTD to QH's done list */ + qh->done_list = qtd_tmp; + } + else + { + q_pre = qtd; /* remember this qTD as a preceder */ + qtd = qtd->next; /* advance to next qTD */ + } + } + + qh_tmp = qh; + qh = QH_PTR(qh->HLink); /* advance to the next QH */ + + /* If all TDs are done, call-back to requester and then remove this QH. */ + if ((qh_tmp->qtd_list == NULL) && utr) + { + // printf("T %d [%d]\n", (qh_tmp->Chrst>>8)&0xf, (qh_tmp->OL_Token&QTD_DT) ? 1 : 0); + if (qh_tmp->OL_Token & QTD_DT) + utr->ep->bToggle = 1; + else + utr->ep->bToggle = 0; + + utr->bIsTransferDone = 1; + if (utr->func) + utr->func(utr); + + _ehci->UCMDR |= HSUSBH_UCMDR_IAAD_Msk; /* trigger IAA to reclaim done_list */ + } + } +} + +static void scan_periodic_frame_list() +{ + QH_T *qh; + qTD_T *qtd; + UTR_T *utr; + + /*------------------------------------------------------------------------------------*/ + /* Scan interrupt frame list */ + /*------------------------------------------------------------------------------------*/ + qh = _Iqh[NUM_IQH - 1]; + while (qh != NULL) + { + qtd = qh->qtd_list; /* There's only one qTD in list at most. */ + + if (qtd == NULL) + { + /* empty QH */ + qh = QH_PTR(qh->HLink); /* advance to the next QH */ + continue; + } + + if (visit_qtd(qtd)) /* if TRUE, reclaim this qtd */ + { + qtd->next = qh->done_list; /* push qTD into the done list */ + qh->done_list = qtd; + qh->qtd_list = NULL; /* qtd_list becomes empty */ + } + + qtd = qh->done_list; + + /* If all TDs are done, call-back to requester and then remove this QH. */ + if ((qtd != NULL) && (qh->qtd_list == NULL)) + { + utr = qtd->utr; + + if (qh->OL_Token & QTD_DT) + utr->ep->bToggle = 1; + else + utr->ep->bToggle = 0; + + utr->bIsTransferDone = 1; + if (utr->func) + utr->func(utr); + + _ehci->UCMDR |= HSUSBH_UCMDR_IAAD_Msk; /* trigger IAA to reclaim done_list */ + } + + qh = QH_PTR(qh->HLink); /* advance to the next QH */ + } + + /*------------------------------------------------------------------------------------*/ + /* Scan isochronous frame list */ + /*------------------------------------------------------------------------------------*/ + + scan_isochronous_list(); +} + +void iaad_remove_qh() +{ + QH_T *qh; + qTD_T *qtd; + UTR_T *utr; + + /*------------------------------------------------------------------------------------*/ + /* Remove all QHs in qh_remove_list... */ + /*------------------------------------------------------------------------------------*/ + while (qh_remove_list != NULL) + { + qh = qh_remove_list; + qh_remove_list = qh->next; + + // USB_debug("iaad_remove_qh - remove QH 0x%x\n", (int)qh); + + while (qh->done_list) /* we can free the qTDs now */ + { + qtd = qh->done_list; + qh->done_list = qtd->next; + free_ehci_qTD(qtd); + } + + if (qh->qtd_list != NULL) /* still have incomplete qTDs? */ + { + utr = qh->qtd_list->utr; + while (qh->qtd_list) + { + qtd = qh->qtd_list; + qh->qtd_list = qtd->next; + free_ehci_qTD(qtd); + } + utr->status = USBH_ERR_ABORT; + utr->bIsTransferDone = 1; + if (utr->func) + utr->func(utr); /* call back */ + } + free_ehci_QH(qh); /* free the QH */ + } + + /*------------------------------------------------------------------------------------*/ + /* Free all qTD in done_list of each asynchronous QH */ + /*------------------------------------------------------------------------------------*/ + qh = QH_PTR(_H_qh->HLink); + while (qh != _H_qh) + { + while (qh->done_list) /* we can free the qTDs now */ + { + qtd = qh->done_list; + qh->done_list = qtd->next; + free_ehci_qTD(qtd); + } + qh = QH_PTR(qh->HLink); /* advance to the next QH */ + } + + /*------------------------------------------------------------------------------------*/ + /* Free all qTD in done_list of each QH of periodic frame list */ + /*------------------------------------------------------------------------------------*/ + qh = _Iqh[NUM_IQH - 1]; + while (qh != NULL) + { + while (qh->done_list) /* we can free the qTDs now */ + { + qtd = qh->done_list; + qh->done_list = qtd->next; + free_ehci_qTD(qtd); + } + qh = QH_PTR(qh->HLink); /* advance to the next QH */ + } +} + +//void EHCI_IRQHandler(void) +void nu_ehci_isr(int vector, void *param) +{ + uint32_t intsts; + + intsts = _ehci->USTSR; + _ehci->USTSR = intsts; /* clear interrupt status */ + + //USB_debug("ehci int_sts = 0x%x\n", intsts); + + if (intsts & HSUSBH_USTSR_UERRINT_Msk) + { + USB_error("Transfer error!\n"); + } + + if (intsts & HSUSBH_USTSR_USBINT_Msk) + { + /* some transfers completed, travel asynchronous */ + /* and periodic lists to find and reclaim them. */ + scan_asynchronous_list(); + + scan_periodic_frame_list(); + } + + if (intsts & HSUSBH_USTSR_IAA_Msk) + { + iaad_remove_qh(); + } +} + +static UDEV_T *ehci_find_device_by_port(int port) +{ + UDEV_T *udev; + + udev = g_udev_list; + while (udev != NULL) + { + if ((udev->parent == NULL) && (udev->port_num == port) && (udev->speed == SPEED_HIGH)) + return udev; + udev = udev->next; + } + return NULL; +} + +static int ehci_rh_port_reset(int port) +{ + int retry; + int reset_time; + uint32_t t0; + + reset_time = usbh_tick_from_millisecond(PORT_RESET_TIME_MS); + + for (retry = 0; retry < PORT_RESET_RETRY; retry++) + { + _ehci->UPSCR[port] = (_ehci->UPSCR[port] | HSUSBH_UPSCR_PRST_Msk) & ~HSUSBH_UPSCR_PE_Msk; + + t0 = usbh_get_ticks(); + while (usbh_get_ticks() - t0 < (reset_time) + 1) ; /* wait at least 50 ms */ + + _ehci->UPSCR[port] &= ~HSUSBH_UPSCR_PRST_Msk; + + t0 = usbh_get_ticks(); + while (usbh_get_ticks() - t0 < (reset_time) + 1) + { + if (!(_ehci->UPSCR[port] & HSUSBH_UPSCR_CCS_Msk) || + ((_ehci->UPSCR[port] & (HSUSBH_UPSCR_CCS_Msk | HSUSBH_UPSCR_PE_Msk)) == (HSUSBH_UPSCR_CCS_Msk | HSUSBH_UPSCR_PE_Msk))) + goto port_reset_done; + } + reset_time += PORT_RESET_RETRY_INC_MS; + } + + USB_debug("EHCI port %d - port reset failed!\n", port + 1); + return USBH_ERR_PORT_RESET; + +port_reset_done: + if ((_ehci->UPSCR[port] & HSUSBH_UPSCR_CCS_Msk) == 0) /* check again if device disconnected */ + { + _ehci->UPSCR[port] |= HSUSBH_UPSCR_CSC_Msk; /* clear CSC */ + return USBH_ERR_DISCONNECTED; + } + _ehci->UPSCR[port] |= HSUSBH_UPSCR_PEC_Msk; /* clear port enable change status */ + return USBH_OK; /* port reset success */ +} + +static int ehci_rh_polling(void) +{ + UDEV_T *udev; + int ret, change = 0; + int port; + int connect_status, t0, debounce_tick; + + for (port = 0; port < EHCI_PORT_CNT; port++) + { + if (!(_ehci->UPSCR[port] & HSUSBH_UPSCR_CSC_Msk)) + continue; + + change = 1; + USB_debug("EHCI port%d status change: 0x%x\n", port + 1, _ehci->UPSCR[port]); + + /*--------------------------------------------------------------------------------*/ + /* Disconnect the devices attached to this port. */ + /*--------------------------------------------------------------------------------*/ + while (1) + { + udev = ehci_find_device_by_port(port + 1); + if (udev == NULL) + break; + usbh_disconnect_device(udev); + } + + /*--------------------------------------------------------------------------------*/ + /* Port de-bounce */ + /*--------------------------------------------------------------------------------*/ + t0 = usbh_get_ticks(); + debounce_tick = usbh_tick_from_millisecond(HUB_DEBOUNCE_TIME); + connect_status = _ehci->UPSCR[port] & HSUSBH_UPSCR_CCS_Msk; + while (usbh_get_ticks() - t0 < debounce_tick) + { + if (connect_status != (_ehci->UPSCR[port] & HSUSBH_UPSCR_CCS_Msk)) + { + /* reset stable time counting */ + t0 = usbh_get_ticks(); + connect_status = _ehci->UPSCR[port] & HSUSBH_UPSCR_CCS_Msk; + } + } + + _ehci->UPSCR[port] |= HSUSBH_UPSCR_CSC_Msk; /* clear connect status change bit */ + + if (connect_status == HSUSBH_UPSCR_CCS_Msk) + { + /*----------------------------------------------------------------------------*/ + /* A new device connected. */ + /*----------------------------------------------------------------------------*/ + if (ehci_rh_port_reset(port) != USBH_OK) + { + /* port reset failed, maybe an USB 1.1 device */ + _ehci->UPSCR[port] |= HSUSBH_UPSCR_PO_Msk; /* change port owner to OHCI */ + _ehci->UPSCR[port] |= HSUSBH_UPSCR_CSC_Msk; /* clear all status change bits */ + return 0; + } + + /* + * Port reset success. Start to enumerate this new device. + */ + udev = alloc_device(); + if (udev == NULL) + return 0; /* out-of-memory, do nothing... */ + + udev->parent = NULL; + udev->port_num = port + 1; + udev->speed = SPEED_HIGH; + udev->hc_driver = &ehci_driver; + + ret = usbh_connect_device(udev); + if (ret < 0) + { + USB_error("connect_device error! [%d]\n", ret); + free_device(udev); + } + } + else + { + /* Device disconnected */ + while (1) + { + udev = ehci_find_device_by_port(port + 1); + if (udev == NULL) + break; + usbh_disconnect_device(udev); + } + } + } + return change; +} + + +HC_DRV_T ehci_driver = +{ + ehci_init, /* init */ + ehci_shutdown, /* shutdown */ + ehci_suspend, /* suspend */ + ehci_resume, /* resume */ + ehci_ctrl_xfer, /* ctrl_xfer */ + ehci_bulk_xfer, /* bulk_xfer */ + ehci_int_xfer, /* int_xfer */ + ehci_iso_xfer, /* iso_xfer */ + ehci_quit_xfer, /* quit_xfer */ + ehci_rh_port_reset, /* rthub_port_reset */ + ehci_rh_polling /* rthub_polling */ +}; + + +/// @endcond HIDDEN_SYMBOLS + +/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci_iso.c b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci_iso.c new file mode 100644 index 0000000000..3ba835d4d8 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci_iso.c @@ -0,0 +1,918 @@ +/**************************************************************************//** + * @file ehci_iso.c + * @version V1.10 + * $Revision: 11 $ + * $Date: 14/10/03 1:54p $ + * @brief USB EHCI isochornous transfer driver. + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2017 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include +#include +#include + +#include "N9H30.h" + +#include "usb.h" +#include "hub.h" + + +/// @cond HIDDEN_SYMBOLS + +uint32_t g_flr_cnt; /* frame list rollover counter */ + +ISO_EP_T *iso_ep_list; /* list of activated isochronous pipes */ + +extern uint32_t *_PFList; /* Periodic frame list */ + +static const uint16_t sitd_OUT_Smask [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f }; + +static int ehci_iso_split_xfer(UTR_T *utr, ISO_EP_T *iso_ep); + +/* + * Inspect the iTD can be reclaimed or not. If yes, collect the transaction results. + * Return: 1 - reclaimed + * 0 - not completed + */ +static int review_itd(iTD_T *itd) +{ + UTR_T *utr; + uint32_t frnidx = itd->sched_frnidx; + uint32_t now_frame = (_ehci->UFINDR >> 3) & 0x3FF; + int i, fidx; + + // printf("R - %d %d, 0x%x\n", now_frame, frnidx, itd->Transaction[0]); + + if (now_frame == frnidx) + { + for (i = 0; i < 8; i++) + { + if (itd->Transaction[i] & ITD_STATUS_ACTIVE) + return 0; /* have any not completed frames */ + } + } + else if (now_frame > frnidx) + { + if ((now_frame - frnidx) > EHCI_ISO_RCLM_RANGE) + return 0; /* don't touch it */ + } + else + { + if (now_frame + FL_SIZE - frnidx > EHCI_ISO_RCLM_RANGE) + return 0; /* don't touch it */ + } + + /* + * Reclaim this iTD + */ + utr = itd->utr; + fidx = itd->fidx; + for (i = 0; i < 8; i++) + { + if (!(itd->trans_mask & (0x1 << i))) + continue; /* not scheduled micro-frame */ + + if (ITD_STATUS(itd->Transaction[i])) + { + if (itd->Transaction[i] & ITD_STATUS_ACTIVE) + { + utr->iso_status[fidx] = USBH_ERR_NOT_ACCESS0; + utr->status = USBH_ERR_NOT_ACCESS0; + } + else if (itd->Transaction[i] & ITD_STATUS_BABBLE) + { + utr->iso_status[fidx] = USBH_ERR_BABBLE_DETECTED; + utr->status = USBH_ERR_TRANSFER; + } + else if (itd->Transaction[i] & ITD_STATUS_BUFF_ERR) + { + utr->iso_status[fidx] = USBH_ERR_DATA_BUFF; + utr->status = USBH_ERR_TRANSFER; + } + else + { + utr->iso_status[fidx] = USBH_ERR_TRANSACTION; + utr->status = USBH_ERR_TRANSFER; + } + } + else + { + utr->iso_status[fidx] = 0; + utr->iso_xlen[fidx] = ITD_XFER_LEN(itd->Transaction[i]); + } + fidx++; + } + utr->td_cnt--; + + if (utr->td_cnt == 0) /* All iTD of this UTR done */ + { + utr->bIsTransferDone = 1; + if (utr->func) + utr->func(utr); + } + + return 1; /* to be reclaimed */ +} + +/* + * Inspect the siTD can be reclaimed or not. If yes, collect the transaction results. + * Return: 1 - reclaimed + * 0 - not completed + */ +static int review_sitd(siTD_T *sitd) +{ + UTR_T *utr; + uint32_t frnidx = sitd->sched_frnidx; + uint32_t now_frame = (_ehci->UFINDR >> 3) & 0x3FF; + int fidx; + uint32_t TotalBytesToTransfer; + + if (now_frame == frnidx) + { + if (SITD_STATUS(sitd->StsCtrl) == SITD_STATUS_ACTIVE) + return 0; + } + else if (now_frame > frnidx) + { + if ((now_frame - frnidx) > EHCI_ISO_RCLM_RANGE) + return 0; /* don't touch it */ + } + else + { + if (now_frame + FL_SIZE - frnidx > EHCI_ISO_RCLM_RANGE) + return 0; /* don't touch it */ + } + + /* + * Reclaim this siTD + */ + utr = sitd->utr; + fidx = sitd->fidx; + + if (SITD_STATUS(sitd->StsCtrl)) + { + if (sitd->StsCtrl & SITD_STATUS_ACTIVE) + { + utr->iso_status[fidx] = USBH_ERR_NOT_ACCESS0; + } + else if (sitd->StsCtrl & SITD_BABBLE_DETECTED) + { + utr->iso_status[fidx] = USBH_ERR_BABBLE_DETECTED; + utr->status = USBH_ERR_TRANSFER; + } + else if (sitd->StsCtrl & SITD_STATUS_BUFF_ERR) + { + utr->iso_status[fidx] = USBH_ERR_DATA_BUFF; + utr->status = USBH_ERR_TRANSFER; + } + else + { + utr->iso_status[fidx] = USBH_ERR_TRANSACTION; + utr->status = USBH_ERR_TRANSFER; + } + } + else + { + TotalBytesToTransfer = (sitd->StsCtrl & SITD_XFER_CNT_Msk) >> SITD_XFER_CNT_Pos; + utr->iso_xlen[fidx] = utr->iso_xlen[fidx] - TotalBytesToTransfer; + utr->iso_status[fidx] = 0; + } + utr->td_cnt--; + + if (utr->td_cnt == 0) /* All iTD of this UTR done */ + { + utr->bIsTransferDone = 1; + if (utr->func) + utr->func(utr); + } + return 1; /* to be reclaimed */ +} + +/* + * Some iTD/siTD may be scheduled but not serviced due to time missed. + * This function scan several earlier frames and drop unserviced iTD/siTD if found. + */ +void scan_isochronous_list(void) +{ + ISO_EP_T *iso_ep = iso_ep_list; + iTD_T *itd, *itd_pre, *p; + siTD_T *sitd, *sitd_pre, *sp; + uint32_t frnidx; + + DISABLE_EHCI_IRQ(); + + while (iso_ep != NULL) /* Search all activated iso endpoints */ + { + /*--------------------------------------------------------------------------------*/ + /* Scan all iTDs */ + /*--------------------------------------------------------------------------------*/ + itd = iso_ep->itd_list; /* get the first iTD from iso_ep's iTD list */ + itd_pre = NULL; + while (itd != NULL) /* traverse all iTDs of itd list */ + { + if (review_itd(itd)) /* inspect and reclaim iTD */ + { + /*------------------------------------------------------------------------*/ + /* Remove this iTD from period frame list */ + /*------------------------------------------------------------------------*/ + frnidx = itd->sched_frnidx; + if (_PFList[frnidx] == ITD_HLNK_ITD(itd)) + { + /* is the first entry, just change to next */ + _PFList[frnidx] = itd->Next_Link; + } + else + { + p = ITD_PTR(_PFList[frnidx]); /* find the preceding iTD */ + while ((ITD_PTR(p->Next_Link) != itd) && (p != NULL)) + { + p = ITD_PTR(p->Next_Link); + } + + if (p == NULL) /* link list out of control! */ + { + USB_error("An iTD lost refernece to periodic frame list! 0x%x -> %d\n", (int)itd, frnidx); + } + else /* remove iTD from list */ + { + p->Next_Link = itd->Next_Link; + } + } + + /*------------------------------------------------------------------------*/ + /* Remove this iTD from iso_ep's iTD list */ + /*------------------------------------------------------------------------*/ + if (itd_pre == NULL) + { + iso_ep->itd_list = itd->next; + } + else + { + itd_pre->next = itd->next; + } + p = itd->next; + free_ehci_iTD(itd); + itd = p; + } + else + { + itd_pre = itd; + itd = itd->next; /* traverse to the next iTD of iTD list */ + } + } + + /*--------------------------------------------------------------------------------*/ + /* Scan all siTDs */ + /*--------------------------------------------------------------------------------*/ + sitd = iso_ep->sitd_list; /* get the first siTD from iso_ep's siTD list */ + sitd_pre = NULL; + while (sitd != NULL) /* traverse all siTDs of sitd list */ + { + if (review_sitd(sitd)) /* inspect and reclaim siTD */ + { + /*------------------------------------------------------------------------*/ + /* Remove this siTD from period frame list */ + /*------------------------------------------------------------------------*/ + frnidx = sitd->sched_frnidx; + if (_PFList[frnidx] == SITD_HLNK_SITD(sitd)) + { + /* is the first entry, just change to next */ + _PFList[frnidx] = sitd->Next_Link; + } + else + { + sp = SITD_PTR(_PFList[frnidx]); /* find the preceding siTD */ + while ((SITD_PTR(sp->Next_Link) != sitd) && (sp != NULL)) + { + sp = SITD_PTR(sp->Next_Link); + } + + if (sp == NULL) /* link list out of control! */ + { + USB_error("An siTD lost reference to periodic frame list! 0x%x -> %d\n", (int)sitd, frnidx); + } + else /* remove iTD from list */ + { + sp->Next_Link = sitd->Next_Link; + } + } + + /*------------------------------------------------------------------------*/ + /* Remove this siTD from iso_ep's siTD list */ + /*------------------------------------------------------------------------*/ + if (sitd_pre == NULL) + { + iso_ep->sitd_list = sitd->next; + } + else + { + sitd_pre->next = sitd->next; + } + sp = sitd->next; + free_ehci_siTD(sitd); + sitd = sp; + } + else + { + sitd_pre = sitd; + sitd = sitd->next; /* traverse to the next siTD of siTD list */ + } + } + + iso_ep = iso_ep->next; + } + + ENABLE_EHCI_IRQ(); +} + + +static void write_itd_info(UTR_T *utr, iTD_T *itd) +{ + UDEV_T *udev = utr->udev; + EP_INFO_T *ep = utr->ep; /* reference to isochronous endpoint */ + uint32_t buff_page_addr; + int i; + + buff_page_addr = itd->buff_base & 0xFFFFF000; /* 4K page */ + + for (i = 0; i < 7; i++) + { + itd->Bptr[i] = buff_page_addr + (0x1000 * i); + } + /* EndPtr R Device Address */ + itd->Bptr[0] |= (udev->dev_num) | ((ep->bEndpointAddress & 0xF) << ITD_EP_NUM_Pos); + itd->Bptr[1] |= ep->wMaxPacketSize; /* Maximum Packet Size */ + + if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN) /* I/O */ + itd->Bptr[1] |= ITD_DIR_IN; + else + itd->Bptr[1] |= ITD_DIR_OUT; + + itd->Bptr[2] |= (ep->wMaxPacketSize + 1023) / 1024; /* Mult */ +} + +static void write_itd_micro_frame(UTR_T *utr, int fidx, iTD_T *itd, int mf) +{ + uint32_t buff_addr; + + buff_addr = (uint32_t)(utr->iso_buff[fidx]); /* xfer buffer start address of this frame */ + + itd->Transaction[mf] = ITD_STATUS_ACTIVE | /* Status */ + ((utr->iso_xlen[fidx] & 0xFFF) << ITD_XLEN_Pos) | /* Transaction Length */ + ((buff_addr & 0xFFFFF000) - (itd->buff_base & 0xFFFFF000)) | /* PG */ + (buff_addr & 0xFFF); /* Transaction offset */ +} + + +static void remove_iso_ep_from_list(ISO_EP_T *iso_ep) +{ + ISO_EP_T *p; + + if (iso_ep_list == iso_ep) + { + iso_ep_list = iso_ep->next; /* it's the first entry, remove it */ + return; + } + + p = iso_ep_list; /* find the previous entry of iso_ep */ + while (p->next != NULL) + { + if (p->next == iso_ep) + { + break; + } + p = p->next; + } + + if (p->next == NULL) + { + return; /* not found */ + } + p->next = iso_ep->next; /* remove iso_ep from list */ +} + + +static __inline void add_itd_to_iso_ep(ISO_EP_T *iso_ep, iTD_T *itd) +{ + iTD_T *p; + + itd->next = NULL; + + if (iso_ep->itd_list == NULL) + { + iso_ep->itd_list = itd; + return; + } + + /* + * Find the tail entry of iso_ep->itd_list + */ + p = iso_ep->itd_list; + while (p->next != NULL) + { + p = p->next; + } + p->next = itd; +} + +int ehci_iso_xfer(UTR_T *utr) +{ + EP_INFO_T *ep = utr->ep; /* reference to isochronous endpoint */ + ISO_EP_T *iso_ep; /* software iso endpoint descriptor */ + iTD_T *itd, *itd_next, *itd_list = NULL; + int i, itd_cnt; + int trans_mask; /* bit mask of used xfer in an iTD */ + int fidx; /* index to the 8 iso frames of UTR */ + int interval; /* frame interval of iTD */ + + if (ep->hw_pipe != NULL) + { + iso_ep = (ISO_EP_T *)ep->hw_pipe; /* get reference of the isochronous endpoint */ + + if (utr->bIsoNewSched) + iso_ep->next_frame = (((_ehci->UFINDR + (EHCI_ISO_DELAY * 8)) & HSUSBH_UFINDR_FI_Msk) >> 3) & 0x3FF; + } + else + { + /* first time transfer of this iso endpoint */ + iso_ep = usbh_alloc_mem(sizeof(*iso_ep)); + if (iso_ep == NULL) + return USBH_ERR_MEMORY_OUT; + + memset(iso_ep, 0, sizeof(*iso_ep)); + iso_ep->ep = ep; + iso_ep->next_frame = (((_ehci->UFINDR + (EHCI_ISO_DELAY * 8)) & HSUSBH_UFINDR_FI_Msk) >> 3) & 0x3FF; + + ep->hw_pipe = iso_ep; + + /* + * Add this iso_ep into iso_ep_list + */ + DISABLE_EHCI_IRQ(); + iso_ep->next = iso_ep_list; + iso_ep_list = iso_ep; + ENABLE_EHCI_IRQ(); + } + + if (utr->udev->speed == SPEED_FULL) + return ehci_iso_split_xfer(utr, iso_ep); + + /*------------------------------------------------------------------------------------*/ + /* Allocate iTDs */ + /*------------------------------------------------------------------------------------*/ + + if (ep->bInterval < 2) /* transfer interval is 1 micro-frame */ + { + trans_mask = 0xFF; + itd_cnt = 1; /* required 1 iTD for one UTR */ + interval = 1; /* iTD frame interval of this endpoint */ + } + else if (ep->bInterval < 4) /* transfer interval is 2 micro-frames */ + { + trans_mask = 0x55; + itd_cnt = 2; /* required 2 iTDs for one UTR */ + interval = 1; /* iTD frame interval of this endpoint */ + } + else if (ep->bInterval < 8) /* transfer interval is 4 micro-frames */ + { + trans_mask = 0x44; + itd_cnt = 4; /* required 4 iTDs for one UTR */ + interval = 1; /* iTD frame interval of this endpoint */ + } + else if (ep->bInterval < 16) /* transfer interval is 8 micro-frames */ + { + trans_mask = 0x08; /* there's 1 transfer in one iTD */ + itd_cnt = 8; /* required 8 iTDs for one UTR */ + interval = 1; /* iTD frame interval of this endpoint */ + } + else if (ep->bInterval < 32) /* transfer interval is 16 micro-frames */ + { + trans_mask = 0x10; /* there's 1 transfer in one iTD */ + itd_cnt = 8; /* required 8 iTDs for one UTR */ + interval = 2; /* iTD frame interval of this endpoint */ + } + else if (ep->bInterval < 64) /* transfer interval is 32 micro-frames */ + { + trans_mask = 0x02; /* there's 1 transfer in one iTD */ + itd_cnt = 8; /* required 8 iTDs for one UTR */ + interval = 4; /* iTD frame interval of this endpoint */ + } + else /* transfer interval is 64 micro-frames */ + { + trans_mask = 0x04; /* there's 1 transfer in one iTD */ + itd_cnt = 8; /* required 8 iTDs for one UTR */ + interval = 8; /* iTD frame interval of this endpoint */ + } + + for (i = 0; i < itd_cnt; i++) /* allocate all iTDs required by UTR */ + { + itd = alloc_ehci_iTD(); + if (itd == NULL) + goto malloc_failed; + + if (itd_list == NULL) /* link all iTDs */ + { + itd_list = itd; + } + else + { + itd->next = itd_list; + itd_list = itd; + } + } + + utr->td_cnt = itd_cnt; + + /*------------------------------------------------------------------------------------*/ + /* Fill and link all iTDs */ + /*------------------------------------------------------------------------------------*/ + + utr->iso_sf = iso_ep->next_frame; + fidx = 0; /* index to UTR iso frmes (total IF_PER_UTR) */ + + for (itd = itd_list; (itd != NULL);) + { + if (fidx >= IF_PER_UTR) /* unlikely */ + { + USB_error("EHCI driver ITD bug!?\n"); + goto malloc_failed; + } + + itd->utr = utr; + itd->fidx = fidx; /* index to UTR's n'th IF_PER_UTR frame */ + itd->buff_base = (uint32_t)(utr->iso_buff[fidx]); /* iTD buffer base is buffer of the first UTR iso frame serviced by this iTD */ + itd->trans_mask = trans_mask; + + write_itd_info(utr, itd); + + for (i = 0; i < 8; i++) /* settle xfer into micro-frames */ + { + if (!(trans_mask & (0x1 << i))) + { + itd->Transaction[i] = 0; /* not accesed */ + continue; /* not scheduled micro-frame */ + } + + write_itd_micro_frame(utr, fidx, itd, i); + + fidx++; /* preceed to next UTR iso frame */ + + if (fidx == IF_PER_UTR) /* is the last scheduled micro-frame? */ + { + /* raise interrupt on completed */ + itd->Transaction[i] |= ITD_IOC; + break; + } + } + + itd_next = itd->next; /* remember the next itd */ + + // USB_debug("Link iTD 0x%x, %d\n", (int)itd, iso_ep->next_frame); + /* + * Link iTD to period frame list + */ + DISABLE_EHCI_IRQ(); + itd->sched_frnidx = iso_ep->next_frame; /* remember it for reclamation scan */ + add_itd_to_iso_ep(iso_ep, itd); /* add to software itd list */ + itd->Next_Link = _PFList[itd->sched_frnidx]; /* keep the next link */ + _PFList[itd->sched_frnidx] = ITD_HLNK_ITD(itd); + iso_ep->next_frame = (iso_ep->next_frame + interval) % FL_SIZE; + ENABLE_EHCI_IRQ(); + + itd = itd_next; + } + + _ehci->UCMDR |= HSUSBH_UCMDR_PSEN_Msk; /* periodic list enable */ + return 0; + +malloc_failed: + + while (itd_list != NULL) + { + itd = itd_list; + itd_list = itd->next; + free_ehci_iTD(itd); + } + return USBH_ERR_MEMORY_OUT; +} + +static __inline void add_sitd_to_iso_ep(ISO_EP_T *iso_ep, siTD_T *sitd) +{ + siTD_T *p; + + sitd->next = NULL; + + if (iso_ep->sitd_list == NULL) + { + iso_ep->sitd_list = sitd; + return; + } + + /* + * Find the tail entry of iso_ep->itd_list + */ + p = iso_ep->sitd_list; + while (p->next != NULL) + { + p = p->next; + } + p->next = sitd; +} + +static void write_sitd_info(UTR_T *utr, siTD_T *sitd) +{ + UDEV_T *udev = utr->udev; + EP_INFO_T *ep = utr->ep; /* reference to isochronous endpoint */ + uint32_t buff_page_addr; + int xlen = utr->iso_xlen[sitd->fidx]; + int scnt; + + sitd->Chrst = (udev->port_num << SITD_PORT_NUM_Pos) | + (udev->parent->iface->udev->dev_num << SITD_HUB_ADDR_Pos) | + ((ep->bEndpointAddress & 0xF) << SITD_EP_NUM_Pos) | + (udev->dev_num << SITD_DEV_ADDR_Pos); + + buff_page_addr = ((uint32_t)utr->iso_buff[sitd->fidx]) & 0xFFFFF000; + sitd->Bptr[0] = (uint32_t)(utr->iso_buff[sitd->fidx]); + sitd->Bptr[1] = buff_page_addr + 0x1000; + + scnt = (xlen + 187) / 188; + + if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN) /* I/O */ + { + sitd->Chrst |= SITD_XFER_IN; + sitd->Sched = (1 << (scnt + 2)) - 1; + sitd->Sched = (sitd->Sched << 10) | 0x1; + //sitd->Sched <<= 1; + } + else + { + sitd->Chrst |= SITD_XFER_OUT; + sitd->Sched = sitd_OUT_Smask[scnt - 1]; + if (scnt > 1) + { + sitd->Bptr[1] |= (0x1 << 3); /* Transaction position (TP) 01b: Begin */ + } + sitd->Bptr[1] |= scnt; /* Transaction count (T-Count) */ + } + + if (sitd->fidx == IF_PER_UTR) + { + sitd->Sched |= SITD_IOC; + } + + sitd->StsCtrl = (xlen << SITD_XFER_CNT_Pos) | SITD_STATUS_ACTIVE; + + sitd->BackLink = SITD_LIST_END; +} + + +static void ehci_sitd_adjust_schedule(siTD_T *sitd) +{ + siTD_T *hlink = (siTD_T *)_PFList[sitd->sched_frnidx]; + uint32_t uframe_mask = 0x00; + + while (hlink && !HLINK_IS_TERMINATED(hlink) && HLINK_IS_SITD(hlink)) + { + hlink = SITD_PTR(hlink); + if (hlink != sitd) + { + if ((hlink->Chrst & SITD_XFER_IO_Msk) == SITD_XFER_IN) + { + uframe_mask |= (hlink->Sched & 0xFF); /* mark micro-frames used by IN S-mask */ + uframe_mask |= ((hlink->Sched >> 8) & 0xFF); /* mark micro-frames used by IN C-mask */ + } + else + { + uframe_mask |= (hlink->Sched & 0xFF); /* mark micro-frames used by OUT S-mask */ + } + } + hlink = SITD_PTR(hlink->Next_Link); + } + + uframe_mask = uframe_mask | (uframe_mask << 8); /* mark both S-mask and C-mask */ + + if (uframe_mask) + { + /* + * Shift afterward one micro-frame until no conflicts. + */ + while (1) + { + if (sitd->Sched & uframe_mask) + { + sitd->Sched = (sitd->Sched & 0xFFFF0000) | ((sitd->Sched << 1) & 0xFFFF); + } + else + { + break; /* no conflit, done. */ + } + } + } +} + + +static int ehci_iso_split_xfer(UTR_T *utr, ISO_EP_T *iso_ep) +{ + EP_INFO_T *ep = utr->ep; /* reference to isochronous endpoint */ + siTD_T *sitd, *sitd_next, *sitd_list = NULL; + int i; + int fidx; /* index to the 8 iso frames of UTR */ + + if (utr->udev->parent == NULL) + { + USB_error("siso xfer - parent lost!\n"); + return USBH_ERR_INVALID_PARAM; + } + + /*------------------------------------------------------------------------------------*/ + /* Allocate siTDs */ + /*------------------------------------------------------------------------------------*/ + for (i = 0; i < IF_PER_UTR; i++) /* allocate all siTDs required by UTR */ + { + sitd = alloc_ehci_siTD(); + if (sitd == NULL) + goto malloc_failed; + + if (sitd_list == NULL) /* link all siTDs */ + { + sitd_list = sitd; + } + else + { + sitd->next = sitd_list; + sitd_list = sitd; + } + } + + utr->td_cnt = IF_PER_UTR; + + /*------------------------------------------------------------------------------------*/ + /* Fill and link all siTDs */ + /*------------------------------------------------------------------------------------*/ + + utr->iso_sf = iso_ep->next_frame; + fidx = 0; /* index to UTR iso frmes (total IF_PER_UTR) */ + + for (sitd = sitd_list; (sitd != NULL); fidx++) + { + if (fidx >= IF_PER_UTR) /* unlikely */ + { + USB_error("EHCI driver siTD bug!?\n"); + goto malloc_failed; + } + + sitd->utr = utr; + sitd->fidx = fidx; /* index to UTR's n'th IF_PER_UTR frame */ + + write_sitd_info(utr, sitd); + + sitd_next = sitd->next; /* remember the next itd */ + + // USB_debug("Link iTD 0x%x, %d\n", (int)itd, iso_ep->next_frame); + /* + * Link iTD to period frame list + */ + sitd->sched_frnidx = iso_ep->next_frame; /* remember it for reclamation scan */ + DISABLE_EHCI_IRQ(); + ehci_sitd_adjust_schedule(sitd); + add_sitd_to_iso_ep(iso_ep, sitd); /* add to software itd list */ + sitd->Next_Link = _PFList[sitd->sched_frnidx];/* keep the next link */ + _PFList[sitd->sched_frnidx] = SITD_HLNK_SITD(sitd); + iso_ep->next_frame = (iso_ep->next_frame + ep->bInterval) % FL_SIZE; + ENABLE_EHCI_IRQ(); + + sitd = sitd_next; + } + + _ehci->UCMDR |= HSUSBH_UCMDR_PSEN_Msk; /* periodic list enable */ + return 0; + +malloc_failed: + + while (sitd_list != NULL) + { + sitd = sitd_list; + sitd_list = sitd->next; + free_ehci_siTD(sitd); + } + return USBH_ERR_MEMORY_OUT; +} + +/* + * If it's an isochronous endpoint, quit current transfer via UTR or hardware EP. + */ +int ehci_quit_iso_xfer(UTR_T *utr, EP_INFO_T *ep) +{ + ISO_EP_T *iso_ep; + iTD_T *itd, *itd_next, *p; + uint32_t frnidx; + uint32_t now_frame; + + if (ep == NULL) + { + if (utr == NULL) + return USBH_ERR_NOT_FOUND; + + if (utr->ep == NULL) + return USBH_ERR_NOT_FOUND; + + ep = utr->ep; + } + + if ((ep->bmAttributes & EP_ATTR_TT_MASK) != EP_ATTR_TT_ISO) + return USBH_ERR_NOT_FOUND; /* not isochronous endpoint */ + + /*------------------------------------------------------------------------------------*/ + /* It's an iso endpoint. Remove it as required. */ + /*------------------------------------------------------------------------------------*/ + iso_ep = iso_ep_list; + while (iso_ep != NULL) /* Search all activated iso endpoints */ + { + if (iso_ep->ep == ep) + break; + iso_ep = iso_ep->next; + } + if (iso_ep == NULL) + return 0; /* should have been removed */ + + itd = iso_ep->itd_list; /* get the first iTD from iso_ep's iTD list */ + + while (itd != NULL) /* traverse all iTDs of itd list */ + { + itd_next = itd->next; /* remember the next iTD */ + utr = itd->utr; + + /*--------------------------------------------------------------------------------*/ + /* Remove this iTD from period frame list */ + /*--------------------------------------------------------------------------------*/ + frnidx = itd->sched_frnidx; + + /* + * Prevent to race with Host Controller. If the iTD to be removed is located in + * current or next frame, wait until HC passed through it. + */ + while (1) + { + now_frame = (_ehci->UFINDR >> 3) & 0x3FF; + if ((now_frame == frnidx) || (((now_frame + 1) % 1024) == frnidx)) + continue; + break; + } + + if (_PFList[frnidx] == ITD_HLNK_ITD(itd)) + { + /* is the first entry, just change to next */ + _PFList[frnidx] = itd->Next_Link; + } + else + { + p = ITD_PTR(_PFList[frnidx]); /* find the preceding iTD */ + while ((ITD_PTR(p->Next_Link) != itd) && (p != NULL)) + { + p = ITD_PTR(p->Next_Link); + } + + if (p == NULL) /* link list out of control! */ + { + USB_error("ehci_quit_iso_xfer - An iTD lost reference to periodic frame list! 0x%x on %d\n", (int)itd, frnidx); + } + else /* remove iTD from list */ + { + p->Next_Link = itd->Next_Link; + } + } + + utr->td_cnt--; + + if (utr->td_cnt == 0) /* All iTD of this UTR done */ + { + utr->bIsTransferDone = 1; + if (utr->func) + utr->func(utr); + utr->status = USBH_ERR_ABORT; + } + free_ehci_iTD(itd); + itd = itd_next; + } + + /* + * Remove iso_ep from iso_ep_list + */ + remove_iso_ep_from_list(iso_ep); + usbh_free_mem(iso_ep, sizeof(*iso_ep)); /* free this iso_ep */ + ep->hw_pipe = NULL; + + if (iso_ep_list == NULL) + _ehci->UCMDR &= ~HSUSBH_UCMDR_PSEN_Msk; + + return 0; +} + + +/// @endcond HIDDEN_SYMBOLS + +/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/mem_alloc.c b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/mem_alloc.c new file mode 100644 index 0000000000..1ad3cabcb1 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/mem_alloc.c @@ -0,0 +1,540 @@ +/**************************************************************************//** + * @file mem_alloc.c + * @version V1.10 + * $Revision: 11 $ + * $Date: 14/10/03 1:54p $ + * @brief USB host library memory allocation functions. + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include +#include +#include + +#include "usb.h" + + +/// @cond HIDDEN_SYMBOLS + +//#define MEM_DEBUG + +#ifdef MEM_DEBUG + #define mem_debug rt_kprintf +#else + #define mem_debug(...) +#endif + +#ifdef __ICCARM__ + #pragma data_alignment=1024 + uint8_t _mem_pool_buff[MEM_POOL_UNIT_NUM][MEM_POOL_UNIT_SIZE]; +#else + uint8_t _mem_pool_buff[MEM_POOL_UNIT_NUM][MEM_POOL_UNIT_SIZE] __attribute__((aligned(1024))); +#endif + +static uint8_t *_mem_pool[MEM_POOL_UNIT_NUM]; +static uint8_t _unit_used[MEM_POOL_UNIT_NUM]; + +static volatile int _usbh_mem_used; +static volatile int _usbh_max_mem_used; +static volatile int _mem_pool_used; + + +UDEV_T *g_udev_list; + +uint8_t _dev_addr_pool[128]; +static volatile int _device_addr; + +static int _sidx = 0;; + +/*--------------------------------------------------------------------------*/ +/* Memory alloc/free recording */ +/*--------------------------------------------------------------------------*/ + +void usbh_memory_init(void) +{ + int i; + + if (sizeof(TD_T) > MEM_POOL_UNIT_SIZE) + { + USB_error("TD_T - MEM_POOL_UNIT_SIZE too small!\n"); + while (1); + } + + if (sizeof(ED_T) > MEM_POOL_UNIT_SIZE) + { + USB_error("ED_T - MEM_POOL_UNIT_SIZE too small!\n"); + while (1); + } + + for (i = 0; i < MEM_POOL_UNIT_NUM; i++) + { + _unit_used[i] = 0; + _mem_pool[i] = (uint8_t *)((uint32_t)&_mem_pool_buff[i] | NON_CACHE_MASK); + } + + _usbh_mem_used = 0L; + _usbh_max_mem_used = 0L; + + _mem_pool_used = 0; + _sidx = 0; + + g_udev_list = NULL; + + memset(_dev_addr_pool, 0, sizeof(_dev_addr_pool)); + _device_addr = 1; + + USB_InitializeMemoryPool(); +} + +uint32_t usbh_memory_used(void) +{ + mem_debug("USB static memory: %d/%d, heap used: %d\n", _mem_pool_used, MEM_POOL_UNIT_NUM, _usbh_mem_used); + return _usbh_mem_used; +} + +static void memory_counter(int size) +{ + _usbh_mem_used += size; + if (_usbh_mem_used > _usbh_max_mem_used) + _usbh_max_mem_used = _usbh_mem_used; +} + +void *usbh_alloc_mem(int size) +{ + void *p; + + p = USB_malloc(size, 16); + if (p == NULL) + { + USB_error("usbh_alloc_mem failed! %d\n", size); + return NULL; + } + + memset(p, 0, size); + memory_counter(size); + return p; +} + +void usbh_free_mem(void *p, int size) +{ + USB_free(p); + memory_counter(0 - size); +} + + +/*--------------------------------------------------------------------------*/ +/* USB device allocate/free */ +/*--------------------------------------------------------------------------*/ + +UDEV_T *alloc_device(void) +{ + UDEV_T *udev; + + udev = (UDEV_T *)USB_malloc(sizeof(*udev), 16); + if (udev == NULL) + { + USB_error("alloc_device failed!\n"); + return NULL; + } + + memset(udev, 0, sizeof(*udev)); + memory_counter(sizeof(*udev)); + udev->cur_conf = -1; /* must! used to identify the first SET CONFIGURATION */ + udev->next = g_udev_list; /* chain to global device list */ + g_udev_list = udev; + return udev; +} + +void free_device(UDEV_T *udev) +{ + UDEV_T *d; + + if (udev == NULL) + return; + + if (udev->cfd_buff != NULL) + usbh_free_mem(udev->cfd_buff, MAX_DESC_BUFF_SIZE); + + /* + * Remove it from the global device list + */ + if (g_udev_list == udev) + { + g_udev_list = g_udev_list->next; + } + else + { + d = g_udev_list; + while (d != NULL) + { + if (d->next == udev) + { + d->next = udev->next; + break; + } + d = d->next; + } + } + USB_free(udev); + memory_counter(-sizeof(*udev)); +} + +int alloc_dev_address(void) +{ + _device_addr++; + + if (_device_addr >= 128) + _device_addr = 1; + + while (1) + { + if (_dev_addr_pool[_device_addr] == 0) + { + _dev_addr_pool[_device_addr] = 1; + return _device_addr; + } + _device_addr++; + if (_device_addr >= 128) + _device_addr = 1; + } +} + +void free_dev_address(int dev_addr) +{ + if (dev_addr < 128) + _dev_addr_pool[dev_addr] = 0; +} + +/*--------------------------------------------------------------------------*/ +/* UTR (USB Transfer Request) allocate/free */ +/*--------------------------------------------------------------------------*/ + +UTR_T *alloc_utr(UDEV_T *udev) +{ +#if 0 + UTR_T *utr, *utr_noncache; + + utr = (UTR_T *)USB_malloc(sizeof(*utr), 16); + if (utr == NULL) + { + USB_error("alloc_utr failed!\n"); + return NULL; + } + + utr_noncache = (UTR_T *)((uint32_t)utr | NONCACHEABLE); + + memory_counter(sizeof(*utr)); + memset(utr_noncache, 0, sizeof(*utr)); + utr_noncache->udev = udev; + mem_debug("[ALLOC] [UTR] - 0x%x\n", (int)utr_noncache); + return utr_noncache; +#else + UTR_T *utr; + + utr = (UTR_T *)USB_malloc(sizeof(*utr), 16); + if (utr == NULL) + { + USB_error("alloc_utr failed!\n"); + return NULL; + } + + memory_counter(sizeof(*utr)); + memset(utr, 0, sizeof(*utr)); + utr->udev = udev; + mem_debug("[ALLOC] [UTR] - 0x%x\n", (int)utr_noncache); + return utr; +#endif +} + +void free_utr(UTR_T *utr) +{ + if (utr == NULL) + return; + + mem_debug("[FREE] [UTR] - 0x%x\n", (int)utr); + +#if 0 + if ((uint32_t)utr & NONCACHEABLE) + utr = (UTR_T *)((uint32_t)utr & ~NONCACHEABLE); +#endif + + USB_free(utr); + memory_counter(0 - (int)sizeof(*utr)); +} + +/*--------------------------------------------------------------------------*/ +/* OHCI ED allocate/free */ +/*--------------------------------------------------------------------------*/ + +ED_T *alloc_ohci_ED(void) +{ + int i; + ED_T *ed; + + for (i = 0; i < MEM_POOL_UNIT_NUM; i++) + { + if (_unit_used[i] == 0) + { + _unit_used[i] = 1; + _mem_pool_used++; + ed = (ED_T *)_mem_pool[i]; + memset(ed, 0, sizeof(*ed)); + mem_debug("[ALLOC] [ED] - 0x%x\n", (int)ed); + return ed; + } + } + USB_error("alloc_ohci_ED failed!\n"); + return NULL; +} + +void free_ohci_ED(ED_T *ed) +{ + int i; + + for (i = 0; i < MEM_POOL_UNIT_NUM; i++) + { + if ((uint32_t)_mem_pool[i] == (uint32_t)ed) + { + mem_debug("[FREE] [ED] - 0x%x\n", (int)ed); + _unit_used[i] = 0; + _mem_pool_used--; + return; + } + } + USB_debug("free_ohci_ED - not found! (ignored in case of multiple UTR)\n"); +} + +/*--------------------------------------------------------------------------*/ +/* OHCI TD allocate/free */ +/*--------------------------------------------------------------------------*/ +TD_T *alloc_ohci_TD(UTR_T *utr) +{ + int i; + TD_T *td; + + for (i = 0; i < MEM_POOL_UNIT_NUM; i++) + { + if (_unit_used[i] == 0) + { + _unit_used[i] = 1; + _mem_pool_used++; + td = (TD_T *)_mem_pool[i]; + + memset(td, 0, sizeof(*td)); + td->utr = utr; + mem_debug("[ALLOC] [TD] - 0x%x\n", (int)td); + return td; + } + } + USB_error("alloc_ohci_TD failed!\n"); + return NULL; +} + +void free_ohci_TD(TD_T *td) +{ + int i; + + for (i = 0; i < MEM_POOL_UNIT_NUM; i++) + { + if ((uint32_t)_mem_pool[i] == (uint32_t)td) + { + mem_debug("[FREE] [TD] - 0x%x\n", (int)td); + _unit_used[i] = 0; + _mem_pool_used--; + return; + } + } + USB_error("free_ohci_TD - not found!\n"); +} + +/*--------------------------------------------------------------------------*/ +/* EHCI QH allocate/free */ +/*--------------------------------------------------------------------------*/ +QH_T *alloc_ehci_QH(void) +{ + int i; + QH_T *qh = NULL; + + for (i = (_sidx + 1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i + 1) % MEM_POOL_UNIT_NUM) + { + if (_unit_used[i] == 0) + { + _unit_used[i] = 1; + _sidx = i; + _mem_pool_used++; + qh = (QH_T *)_mem_pool[i]; + memset(qh, 0, sizeof(*qh)); + mem_debug("[ALLOC] [QH] - 0x%x\n", (int)qh); + break; + } + } + if (qh == NULL) + { + USB_error("alloc_ehci_QH failed!\n"); + return NULL; + } + qh->Curr_qTD = QTD_LIST_END; + qh->OL_Next_qTD = QTD_LIST_END; + qh->OL_Alt_Next_qTD = QTD_LIST_END; + qh->OL_Token = QTD_STS_HALT; + return qh; +} + +void free_ehci_QH(QH_T *qh) +{ + int i; + + for (i = 0; i < MEM_POOL_UNIT_NUM; i++) + { + if ((uint32_t)_mem_pool[i] == (uint32_t)qh) + { + mem_debug("[FREE] [QH] - 0x%x\n", (int)qh); + _unit_used[i] = 0; + _mem_pool_used--; + return; + } + } + USB_debug("free_ehci_QH - not found! (ignored in case of multiple UTR)\n"); +} + +/*--------------------------------------------------------------------------*/ +/* EHCI qTD allocate/free */ +/*--------------------------------------------------------------------------*/ +qTD_T *alloc_ehci_qTD(UTR_T *utr) +{ + int i; + qTD_T *qtd; + + for (i = (_sidx + 1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i + 1) % MEM_POOL_UNIT_NUM) + { + if (_unit_used[i] == 0) + { + _unit_used[i] = 1; + _sidx = i; + _mem_pool_used++; + qtd = (qTD_T *)_mem_pool[i]; + + memset(qtd, 0, sizeof(*qtd)); + qtd->Next_qTD = QTD_LIST_END; + qtd->Alt_Next_qTD = QTD_LIST_END; + qtd->Token = 0x1197B7F; // QTD_STS_HALT; visit_qtd() will not remove a qTD with this mark. It means the qTD still not ready for transfer. + qtd->utr = utr; + mem_debug("[ALLOC] [qTD] - 0x%x\n", (int)qtd); + return qtd; + } + } + USB_error("alloc_ehci_qTD failed!\n"); + return NULL; +} + +void free_ehci_qTD(qTD_T *qtd) +{ + int i; + + for (i = 0; i < MEM_POOL_UNIT_NUM; i++) + { + if ((uint32_t)_mem_pool[i] == (uint32_t)qtd) + { + mem_debug("[FREE] [qTD] - 0x%x\n", (int)qtd); + _unit_used[i] = 0; + _mem_pool_used--; + return; + } + } + USB_error("free_ehci_qTD 0x%x - not found!\n", (int)qtd); +} + +/*--------------------------------------------------------------------------*/ +/* EHCI iTD allocate/free */ +/*--------------------------------------------------------------------------*/ +iTD_T *alloc_ehci_iTD(void) +{ + int i; + iTD_T *itd; + + for (i = (_sidx + 1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i + 1) % MEM_POOL_UNIT_NUM) + { + if (i + 2 >= MEM_POOL_UNIT_NUM) + continue; + + if ((_unit_used[i] == 0) && (_unit_used[i + 1] == 0)) + { + _unit_used[i] = _unit_used[i + 1] = 1; + _sidx = i + 1; + _mem_pool_used += 2; + itd = (iTD_T *)_mem_pool[i]; + memset(itd, 0, sizeof(*itd)); + mem_debug("[ALLOC] [iTD] - 0x%x\n", (int)itd); + return itd; + } + } + USB_error("alloc_ehci_iTD failed!\n"); + return NULL; +} + +void free_ehci_iTD(iTD_T *itd) +{ + int i; + + for (i = 0; i + 1 < MEM_POOL_UNIT_NUM; i++) + { + if ((uint32_t)_mem_pool[i] == (uint32_t)itd) + { + mem_debug("[FREE] [iTD] - 0x%x\n", (int)itd); + _unit_used[i] = _unit_used[i + 1] = 0; + _mem_pool_used -= 2; + return; + } + } + USB_error("free_ehci_iTD 0x%x - not found!\n", (int)itd); +} + +/*--------------------------------------------------------------------------*/ +/* EHCI iTD allocate/free */ +/*--------------------------------------------------------------------------*/ +siTD_T *alloc_ehci_siTD(void) +{ + int i; + siTD_T *sitd; + + for (i = (_sidx + 1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i + 1) % MEM_POOL_UNIT_NUM) + { + if (_unit_used[i] == 0) + { + _unit_used[i] = 1; + _sidx = i; + _mem_pool_used ++; + sitd = (siTD_T *)_mem_pool[i]; + memset(sitd, 0, sizeof(*sitd)); + mem_debug("[ALLOC] [siTD] - 0x%x\n", (int)sitd); + return sitd; + } + } + USB_error("alloc_ehci_siTD failed!\n"); + return NULL; +} + +void free_ehci_siTD(siTD_T *sitd) +{ + int i; + + for (i = 0; i < MEM_POOL_UNIT_NUM; i++) + { + if ((uint32_t)_mem_pool[i] == (uint32_t)sitd) + { + mem_debug("[FREE] [siTD] - 0x%x\n", (int)sitd); + _unit_used[i] = 0; + _mem_pool_used--; + return; + } + } + USB_error("free_ehci_siTD 0x%x - not found!\n", (int)sitd); +} + +/// @endcond HIDDEN_SYMBOLS + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ohci.c b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ohci.c new file mode 100644 index 0000000000..7b9e82b257 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ohci.c @@ -0,0 +1,1301 @@ +/**************************************************************************//** + * @file ohci.c + * @version V1.10 + * $Revision: 11 $ + * $Date: 14/10/03 1:54p $ + * @brief USB Host library OHCI (USB 1.1) host controller driver. + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2017 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include +#include +#include + +#include "N9H30.h" + +#include "usb.h" +#include "hub.h" +#include "ohci.h" + +/// @cond HIDDEN_SYMBOLS + +//#define TD_debug rt_kprintf +#define TD_debug(...) + +//#define ED_debug rt_kprintf +#define ED_debug(...) + +uint8_t _hcca_mem[256] __attribute__((aligned(256))); + +HCCA_T *_hcca; + +ED_T *_Ied[6]; + + +static ED_T *ed_remove_list; + +static void add_to_ED_remove_list(ED_T *ed) +{ + ED_T *p; + + ED_debug("add_to_ED_remove_list - 0x%x (0x%x)\n", (int)ed, ed->Info); + DISABLE_OHCI_IRQ(); + + /* check if this ED found in ed_remove_list */ + p = ed_remove_list; + while (p) + { + if (p == ed) + { + ENABLE_OHCI_IRQ(); /* This ED found in ed_remove_list */ + return; /* do nothing */ + } + p = p->next; + } + + ed->Info |= ED_SKIP; /* ask OHCI controller skip this ED */ + ed->next = ed_remove_list; + ed_remove_list = ed; /* insert to the head of ed_remove_list */ + ENABLE_OHCI_IRQ(); + _ohci->HcInterruptStatus = USBH_HcInterruptStatus_SF_Msk; + _ohci->HcInterruptEnable |= USBH_HcInterruptEnable_SF_Msk; + usbh_delay_ms(2); /* Full speed wait 2 ms is enough */ +} + +static int ohci_reset(void) +{ + volatile int t0; + + /* Disable HC interrupts */ + _ohci->HcInterruptDisable = USBH_HcInterruptDisable_MIE_Msk; + + /* HC Reset requires max 10 ms delay */ + _ohci->HcControl = 0; + _ohci->HcCommandStatus = USBH_HcCommandStatus_HCR_Msk; + + usbh_delay_ms(10); + + /* Check if OHCI reset completed? */ + if ((USBH->HcCommandStatus & USBH_HcCommandStatus_HCR_Msk) != 0) + { + USB_error("Error! - USB OHCI reset timed out!\n"); + return -1; + } + + USBH->HcRhStatus = USBH_HcRhStatus_OCI_Msk | USBH_HcRhStatus_LPS_Msk; + + USBH->HcControl = HCFS_RESET; + + usbh_delay_ms(10); + + /* Check if OHCI reset completed? */ + if ((USBH->HcCommandStatus & USBH_HcCommandStatus_HCR_Msk) != 0) + { + USB_error("Error! - USB HC reset timed out!\n"); + return -1; + } + return 0; +} + +static void init_hcca_int_table() +{ + ED_T *ed_p; + int i, idx, interval; + + memset(_hcca->int_table, 0, sizeof(_hcca->int_table)); + + for (i = 5; i >= 0; i--) /* interval = i^2 */ + { + _Ied[i] = alloc_ohci_ED(); + _Ied[i]->Info = ED_SKIP; + + interval = 0x1 << i; + + for (idx = interval - 1; idx < 32; idx += interval) + { + if (_hcca->int_table[idx] == 0) /* is empty list, insert directly */ + { + _hcca->int_table[idx] = (uint32_t)_Ied[i]; + } + else + { + ed_p = (ED_T *)_hcca->int_table[idx]; + + while (1) + { + if (ed_p == _Ied[i]) + break; /* already chained by previous visit */ + + if (ed_p->NextED == 0) /* reach end of list? */ + { + ed_p->NextED = (uint32_t)_Ied[i]; + break; + } + ed_p = (ED_T *)ed_p->NextED; + } + } + } + } +} + +static ED_T *get_int_tree_head_node(int interval) +{ + int i; + + for (i = 0; i < 5; i++) + { + interval >>= 1; + if (interval == 0) + return _Ied[i]; + } + return _Ied[5]; /* for interval >= 32 */ +} + +static int get_ohci_interval(int interval) +{ + int i, bInterval = 1; + + for (i = 0; i < 5; i++) + { + interval >>= 1; + if (interval == 0) + return bInterval; + bInterval *= 2; + } + return 32; /* for interval >= 32 */ +} + + +static int ohci_init(void) +{ + uint32_t fminterval; + volatile int i; + + _hcca = (HCCA_T *)((uint32_t)_hcca_mem | NON_CACHE_MASK); + + if (ohci_reset() < 0) + return -1; + + ed_remove_list = NULL; + + init_hcca_int_table(); + + /* Tell the controller where the control and bulk lists are + * The lists are empty now. */ + _ohci->HcControlHeadED = 0; /* control ED list head */ + _ohci->HcBulkHeadED = 0; /* bulk ED list head */ + + _ohci->HcHCCA = (uint32_t)_hcca; /* HCCA area */ + + /* periodic start 90% of frame interval */ + fminterval = 0x2edf; /* 11,999 */ + _ohci->HcPeriodicStart = (fminterval * 9) / 10; + + /* set FSLargestDataPacket, 10,104 for 0x2edf frame interval */ + fminterval |= ((((fminterval - 210) * 6) / 7) << 16); + _ohci->HcFmInterval = fminterval; + + _ohci->HcLSThreshold = 0x628; + + /* start controller operations */ + _ohci->HcControl = HCFS_OPER | (0x3 << USBH_HcControl_CBSR_Pos); + +#ifdef OHCI_PER_PORT_POWER + _ohci->HcRhDescriptorB = 0x60000; + for (i = 0; i < OHCI_PORT_CNT; i++) + _ohci->HcRhPortStatus[i] = USBH_HcRhPortStatus_PPS_Msk; +#else + _ohci->HcRhDescriptorA = (USBH->HcRhDescriptorA | (1 << 9)) & ~USBH_HcRhDescriptorA_PSM_Msk; + _ohci->HcRhStatus = USBH_HcRhStatus_LPSC_Msk; +#endif + + _ohci->HcInterruptEnable = USBH_HcInterruptEnable_MIE_Msk | USBH_HcInterruptEnable_WDH_Msk | USBH_HcInterruptEnable_SF_Msk; + + /* POTPGT delay is bits 24-31, in 20 ms units. */ + usbh_delay_ms(20); + return 0; +} + +static void ohci_suspend(void) +{ + int i; + + for (i = 0; i < OHCI_PORT_CNT; i++) + { + /* set port suspend if connected */ + if (_ohci->HcRhPortStatus[i] & 0x1) + _ohci->HcRhPortStatus[i] = 0x4; + } + + /* enable Device Remote Wakeup */ + _ohci->HcRhStatus |= USBH_HcRhStatus_DRWE_Msk; + + /* enable USBH RHSC interrupt for system wakeup */ + _ohci->HcInterruptEnable |= USBH_HcInterruptEnable_RHSC_Msk | USBH_HcInterruptEnable_RD_Msk; + + /* set Host Controller enter suspend state */ + _ohci->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (3 << USBH_HcControl_HCFS_Pos); +} + +static void ohci_resume(void) +{ + int i; + + _ohci->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (1 << USBH_HcControl_HCFS_Pos); + _ohci->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (2 << USBH_HcControl_HCFS_Pos); + + for (i = 0; i < OHCI_PORT_CNT; i++) + { + if (_ohci->HcRhPortStatus[i] & 0x4) + _ohci->HcRhPortStatus[i] = 0x8; + } +} + +static void ohci_shutdown(void) +{ + ohci_suspend(); + DISABLE_OHCI_IRQ(); +#ifndef OHCI_PER_PORT_POWER + _ohci->HcRhStatus = USBH_HcRhStatus_LPS_Msk; +#endif +} + + +/* + * Quit current trasnfer via UTR or hardware EP. + */ +static int ohci_quit_xfer(UTR_T *utr, EP_INFO_T *ep) +{ + ED_T *ed; + + if (utr != NULL) + { + if (utr->ep == NULL) + return USBH_ERR_NOT_FOUND; + + ed = (ED_T *)(utr->ep->hw_pipe); + + if (!ed) + return USBH_ERR_NOT_FOUND; + + /* add the endpoint to remove list, it will be removed on the next start of frame */ + add_to_ED_remove_list(ed); + utr->ep->hw_pipe = NULL; + } + + if ((ep != NULL) && (ep->hw_pipe != NULL)) + { + ed = (ED_T *)(ep->hw_pipe); + /* add the endpoint to remove list, it will be removed on the next start of frame */ + add_to_ED_remove_list(ed); + ep->hw_pipe = NULL; + } + + return 0; +} + +uint32_t ed_make_info(UDEV_T *udev, EP_INFO_T *ep) +{ + uint32_t info; + + if (ep == NULL) /* is a control endpoint */ + { + /* control endpoint direction is from TD */ + if (udev->descriptor.bMaxPacketSize0 == 0) /* is 0 if device descriptor still not obtained. */ + { + if (udev->speed == SPEED_LOW) /* give a default maximum packet size */ + udev->descriptor.bMaxPacketSize0 = 8; + else + udev->descriptor.bMaxPacketSize0 = 64; + } + info = (udev->descriptor.bMaxPacketSize0 << 16) /* Control endpoint Maximum Packet Size from device descriptor */ + | ED_DIR_BY_TD /* Direction (Get direction From TD) */ + | ED_FORMAT_GENERAL /* General format */ + | (0 << ED_CTRL_EN_Pos); /* Endpoint address 0 */ + } + else /* Other endpoint direction is from endpoint descriptor */ + { + info = (ep->wMaxPacketSize << 16); /* Maximum Packet Size from endpoint */ + + info |= ((ep->bEndpointAddress & 0xf) << ED_CTRL_EN_Pos); /* Endpoint Number */ + + if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN) + info |= ED_DIR_IN; + else + info |= ED_DIR_OUT; + + if ((ep->bmAttributes & EP_ATTR_TT_MASK) == EP_ATTR_TT_ISO) + info |= ED_FORMAT_ISO; + else + info |= ED_FORMAT_GENERAL; + } + + info |= ((udev->speed == SPEED_LOW) ? ED_SPEED_LOW : ED_SPEED_FULL); /* Speed */ + info |= (udev->dev_num); /* Function Address */ + + return info; +} + +static void write_td(TD_T *td, uint32_t info, uint8_t *buff, uint32_t data_len) +{ + td->Info = info; + td->CBP = (uint32_t)((!buff || !data_len) ? 0 : buff); + td->BE = (uint32_t)((!buff || !data_len) ? 0 : (uint32_t)buff + data_len - 1); + td->buff_start = td->CBP; + // TD_debug("TD [0x%x]: 0x%x, 0x%x, 0x%x\n", (int)td, td->Info, td->CBP, td->BE); +} + +static int ohci_ctrl_xfer(UTR_T *utr) +{ + UDEV_T *udev; + ED_T *ed; + TD_T *td_setup, *td_data, *td_status; + uint32_t info; + + udev = utr->udev; + + /*------------------------------------------------------------------------------------*/ + /* Allocate ED and TDs */ + /*------------------------------------------------------------------------------------*/ + td_setup = alloc_ohci_TD(utr); + + if (utr->data_len > 0) + td_data = alloc_ohci_TD(utr); + else + td_data = NULL; + + td_status = alloc_ohci_TD(utr); + + if (td_status == NULL) + { + free_ohci_TD(td_setup); + if (utr->data_len > 0) + free_ohci_TD(td_data); + return USBH_ERR_MEMORY_OUT; + } + + /* Check if there's any transfer pending on this endpoint... */ + if (udev->ep0.hw_pipe == NULL) + { + ed = alloc_ohci_ED(); + if (ed == NULL) + { + free_ohci_TD(td_setup); + free_ohci_TD(td_status); + if (utr->data_len > 0) + free_ohci_TD(td_data); + return USBH_ERR_MEMORY_OUT; + } + } + else + ed = (ED_T *)udev->ep0.hw_pipe; + + /*------------------------------------------------------------------------------------*/ + /* prepare SETUP stage TD */ + /*------------------------------------------------------------------------------------*/ + info = TD_CC | TD_T_DATA0 | TD_TYPE_CTRL; + write_td(td_setup, info, (uint8_t *)&utr->setup, 8); + td_setup->ed = ed; + + /*------------------------------------------------------------------------------------*/ + /* prepare DATA stage TD */ + /*------------------------------------------------------------------------------------*/ + if (utr->data_len > 0) + { + if ((utr->setup.bmRequestType & 0x80) == REQ_TYPE_OUT) + info = (TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 | TD_TYPE_CTRL | TD_CTRL_DATA); + else + info = (TD_CC | TD_R | TD_DP_IN | TD_T_DATA1 | TD_TYPE_CTRL | TD_CTRL_DATA); + + write_td(td_data, info, utr->buff, utr->data_len); + td_data->ed = ed; + td_setup->NextTD = (uint32_t)td_data; + td_setup->next = td_data; + td_data->NextTD = (uint32_t)td_status; + td_data->next = td_status; + } + else + { + td_setup->NextTD = (uint32_t)td_status; + td_setup->next = td_status; + } + + /*------------------------------------------------------------------------------------*/ + /* prepare STATUS stage TD */ + /*------------------------------------------------------------------------------------*/ + ed->Info = ed_make_info(udev, NULL); + if ((utr->setup.bmRequestType & 0x80) == REQ_TYPE_OUT) + info = (TD_CC | TD_DP_IN | TD_T_DATA1 | TD_TYPE_CTRL); + else + info = (TD_CC | TD_DP_OUT | TD_T_DATA1 | TD_TYPE_CTRL); + + write_td(td_status, info, NULL, 0); + td_status->ed = ed; + td_status->NextTD = 0; + td_status->next = 0; + + /*------------------------------------------------------------------------------------*/ + /* prepare ED */ + /*------------------------------------------------------------------------------------*/ + ed->TailP = 0; + ed->HeadP = (uint32_t)td_setup; + ed->Info = ed_make_info(udev, NULL); + ed->NextED = 0; + + //TD_debug("TD SETUP [0x%x]: 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td_setup, td_setup->Info, td_setup->CBP, td_setup->BE, td_setup->NextTD); + //if (td_data) + // TD_debug("TD DATA [0x%x]: 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td_data, td_data->Info, td_data->CBP, td_data->BE, td_data->NextTD); + //TD_debug("TD STATUS [0x%x]: 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td_status, td_status->Info, td_status->CBP, td_status->BE, td_status->NextTD); + ED_debug("Xfer ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED); + + if (utr->data_len > 0) + utr->td_cnt = 3; + else + utr->td_cnt = 2; + + utr->ep = &udev->ep0; /* driver can find EP from UTR */ + udev->ep0.hw_pipe = (void *)ed; /* driver can find ED from EP */ + + /*------------------------------------------------------------------------------------*/ + /* Start transfer */ + /*------------------------------------------------------------------------------------*/ + DISABLE_OHCI_IRQ(); + _ohci->HcControlHeadED = (uint32_t)ed; /* Link ED to OHCI */ + _ohci->HcControl |= USBH_HcControl_CLE_Msk; /* enable control list */ + ENABLE_OHCI_IRQ(); + _ohci->HcCommandStatus = USBH_HcCommandStatus_CLF_Msk; /* start Control list */ + + return 0; +} + +static int ohci_bulk_xfer(UTR_T *utr) +{ + UDEV_T *udev = utr->udev; + EP_INFO_T *ep = utr->ep; + ED_T *ed; + TD_T *td, *td_p, *td_list = NULL; + uint32_t info; + uint32_t data_len, xfer_len; + int8_t bIsNewED = 0; + uint8_t *buff; + + /*------------------------------------------------------------------------------------*/ + /* Check if there's uncompleted transfer on this endpoint... */ + /* Prepare ED */ + /*------------------------------------------------------------------------------------*/ + info = ed_make_info(udev, ep); + + /* Check if there's any transfer pending on this endpoint... */ + ed = (ED_T *)_ohci->HcBulkHeadED; /* get the head of bulk endpoint list */ + while (ed != NULL) + { + if (ed->Info == info) /* have transfer of this EP not completed? */ + { + if ((ed->HeadP & 0xFFFFFFF0) != (ed->TailP & 0xFFFFFFF0)) + return USBH_ERR_OHCI_EP_BUSY; /* endpoint is busy */ + else + break; /* ED already there... */ + } + ed = (ED_T *)ed->NextED; + } + + if (ed == NULL) + { + bIsNewED = 1; + ed = alloc_ohci_ED(); /* allocate an Endpoint Descriptor */ + if (ed == NULL) + return USBH_ERR_MEMORY_OUT; + ed->Info = info; + ed->HeadP = 0; + ED_debug("Link BULK ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED); + } + + ep->hw_pipe = (void *)ed; + + /*------------------------------------------------------------------------------------*/ + /* Prepare TDs */ + /*------------------------------------------------------------------------------------*/ + utr->td_cnt = 0; + data_len = utr->data_len; + buff = utr->buff; + + do + { + if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_OUT) + info = (TD_CC | TD_R | TD_DP_OUT | TD_TYPE_BULK); + else + info = (TD_CC | TD_R | TD_DP_IN | TD_TYPE_BULK); + + info &= ~(1 << 25); /* Data toggle from ED toggleCarry bit */ + + if (data_len > 4096) /* maximum transfer length is 4K for each TD */ + xfer_len = 4096; + else + xfer_len = data_len; /* remaining data length < 4K */ + + td = alloc_ohci_TD(utr); /* allocate a TD */ + if (td == NULL) + goto mem_out; + /* fill this TD */ + write_td(td, info, buff, xfer_len); + td->ed = ed; + + utr->td_cnt++; /* increase TD count, for recalim counter */ + + buff += xfer_len; /* advanced buffer pointer */ + data_len -= xfer_len; + + /* chain to end of TD list */ + if (td_list == NULL) + { + td_list = td; + } + else + { + td_p = td_list; + while (td_p->NextTD != 0) + td_p = (TD_T *)td_p->NextTD; + td_p->NextTD = (uint32_t)td; + } + + } + while (data_len > 0); + + /*------------------------------------------------------------------------------------*/ + /* Start transfer */ + /*------------------------------------------------------------------------------------*/ + utr->status = 0; + DISABLE_OHCI_IRQ(); + ed->HeadP = (ed->HeadP & 0x2) | (uint32_t)td_list; /* keep toggleCarry bit */ + if (bIsNewED) + { + ed->HeadP = (uint32_t)td_list; + /* Link ED to OHCI Bulk List */ + ed->NextED = _ohci->HcBulkHeadED; + _ohci->HcBulkHeadED = (uint32_t)ed; + } + ENABLE_OHCI_IRQ(); + _ohci->HcControl |= USBH_HcControl_BLE_Msk; /* enable bulk list */ + _ohci->HcCommandStatus = USBH_HcCommandStatus_BLF_Msk; /* start bulk list */ + + return 0; + +mem_out: + while (td_list != NULL) + { + td = td_list; + td_list = (TD_T *)td_list->NextTD; + free_ohci_TD(td); + } + free_ohci_ED(ed); + return USBH_ERR_MEMORY_OUT; +} + +static int ohci_int_xfer(UTR_T *utr) +{ + UDEV_T *udev = utr->udev; + EP_INFO_T *ep = utr->ep; + ED_T *ed, *ied; + TD_T *td, *td_new; + uint32_t info; + int8_t bIsNewED = 0; + + if (utr->data_len > 64) /* USB 1.1 interrupt transfer maximum packet size is 64 */ + return USBH_ERR_INVALID_PARAM; + + td_new = alloc_ohci_TD(utr); /* allocate a TD for dummy TD */ + if (td_new == NULL) + return USBH_ERR_MEMORY_OUT; + + ied = get_int_tree_head_node(ep->bInterval); /* get head node of this interval */ + + /*------------------------------------------------------------------------------------*/ + /* Find if this ED was already in the list */ + /*------------------------------------------------------------------------------------*/ + info = ed_make_info(udev, ep); + ed = ied; + while (ed != NULL) + { + if (ed->Info == info) + break; /* Endpoint found */ + ed = (ED_T *)ed->NextED; + } + + if (ed == NULL) /* ED not found, create it */ + { + bIsNewED = 1; + ed = alloc_ohci_ED(); /* allocate an Endpoint Descriptor */ + if (ed == NULL) + return USBH_ERR_MEMORY_OUT; + ed->Info = info; + ed->HeadP = 0; + ed->bInterval = ep->bInterval; + + td = alloc_ohci_TD(NULL); /* allocate the initial dummy TD for ED */ + if (td == NULL) + { + free_ohci_ED(ed); + free_ohci_TD(td_new); + return USBH_ERR_MEMORY_OUT; + } + ed->HeadP = (uint32_t)td; /* Let both HeadP and TailP point to dummy TD */ + ed->TailP = ed->HeadP; + } + else + { + td = (TD_T *)(ed->TailP & ~0xf); /* TailP always point to the dummy TD */ + } + ep->hw_pipe = (void *)ed; + + /*------------------------------------------------------------------------------------*/ + /* Prepare TD */ + /*------------------------------------------------------------------------------------*/ + if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_OUT) + info = (TD_CC | TD_R | TD_DP_OUT | TD_TYPE_INT); + else + info = (TD_CC | TD_R | TD_DP_IN | TD_TYPE_INT); + + /* Keep data toggle */ + info = (info & ~(1 << 25)) | (td->Info & (1 << 25)); + + /* fill this TD */ + write_td(td, info, utr->buff, utr->data_len); + td->ed = ed; + td->NextTD = (uint32_t)td_new; + td->utr = utr; + utr->td_cnt = 1; /* increase TD count, for recalim counter */ + utr->status = 0; + + /*------------------------------------------------------------------------------------*/ + /* Hook ED and TD list to HCCA interrupt table */ + /*------------------------------------------------------------------------------------*/ + DISABLE_OHCI_IRQ(); + + ed->TailP = (uint32_t)td_new; + if (bIsNewED) + { + /* Add to list of the same interval */ + ed->NextED = ied->NextED; + ied->NextED = (uint32_t)ed; + } + + ENABLE_OHCI_IRQ(); + + //printf("Link INT ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED); + + _ohci->HcControl |= USBH_HcControl_PLE_Msk; /* periodic list enable */ + return 0; +} + +static int ohci_iso_xfer(UTR_T *utr) +{ + UDEV_T *udev = utr->udev; + EP_INFO_T *ep = utr->ep; + ED_T *ed, *ied; + TD_T *td, *td_list, *last_td; + int i; + uint32_t info; + uint32_t buff_addr; + int8_t bIsNewED = 0; + + ied = get_int_tree_head_node(ep->bInterval); /* get head node of this interval */ + + /*------------------------------------------------------------------------------------*/ + /* Find if this ED was already in the list */ + /*------------------------------------------------------------------------------------*/ + info = ed_make_info(udev, ep); + ed = ied; + while (ed != NULL) + { + if (ed->Info == info) + break; /* Endpoint found */ + ed = (ED_T *)ed->NextED; + } + + if (ed == NULL) /* ED not found, create it */ + { + bIsNewED = 1; + ed = alloc_ohci_ED(); /* allocate an Endpoint Descriptor */ + if (ed == NULL) + return USBH_ERR_MEMORY_OUT; + ed->Info = info; + ed->HeadP = 0; + ed->bInterval = ep->bInterval; + } + else + + ep->hw_pipe = (void *)ed; + + /*------------------------------------------------------------------------------------*/ + /* Prepare TDs */ + /*------------------------------------------------------------------------------------*/ + if (utr->bIsoNewSched) /* Is the starting of isochronous streaming? */ + ed->next_sf = _hcca->frame_no + OHCI_ISO_DELAY; + + utr->td_cnt = 0; + utr->iso_sf = ed->next_sf; + + last_td = NULL; + td_list = NULL; + + for (i = 0; i < IF_PER_UTR; i++) + { + utr->iso_status[i] = USBH_ERR_NOT_ACCESS1; + + td = alloc_ohci_TD(utr); /* allocate a TD */ + if (td == NULL) + goto mem_out; + /* fill this TD */ + buff_addr = (uint32_t)(utr->iso_buff[i]); + td->Info = (TD_CC | TD_TYPE_ISO) | ed->next_sf; + ed->next_sf += get_ohci_interval(ed->bInterval); + td->CBP = buff_addr & ~0xFFF; + td->BE = buff_addr + utr->iso_xlen[i] - 1; + td->PSW[0] = 0xE000 | (buff_addr & 0xFFF); + + td->ed = ed; + utr->td_cnt++; /* increase TD count, for recalim counter */ + + /* chain to end of TD list */ + if (td_list == NULL) + td_list = td; + else + last_td->NextTD = (uint32_t)td; + + last_td = td; + }; + + /*------------------------------------------------------------------------------------*/ + /* Hook ED and TD list to HCCA interrupt table */ + /*------------------------------------------------------------------------------------*/ + utr->status = 0; + DISABLE_OHCI_IRQ(); + + if ((ed->HeadP & ~0x3) == 0) + ed->HeadP = (ed->HeadP & 0x2) | (uint32_t)td_list; /* keep toggleCarry bit */ + else + { + /* find the tail of TDs under this ED */ + td = (TD_T *)(ed->HeadP & ~0x3); + while (td->NextTD != 0) + { + td = (TD_T *)td->NextTD; + } + td->NextTD = (uint32_t)td_list; + } + + if (bIsNewED) + { + /* Add to list of the same interval */ + ed->NextED = ied->NextED; + ied->NextED = (uint32_t)ed; + } + + ENABLE_OHCI_IRQ(); + ED_debug("Link ISO ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED); + _ohci->HcControl |= USBH_HcControl_PLE_Msk | USBH_HcControl_IE_Msk; /* enable periodic list and isochronous transfer */ + + return 0; + +mem_out: + while (td_list != NULL) + { + td = td_list; + td_list = (TD_T *)td_list->NextTD; + free_ohci_TD(td); + } + free_ohci_ED(ed); + return USBH_ERR_MEMORY_OUT; +} + +static UDEV_T *ohci_find_device_by_port(int port) +{ + UDEV_T *udev; + + udev = g_udev_list; + while (udev != NULL) + { + if ((udev->parent == NULL) && (udev->port_num == port) && + ((udev->speed == SPEED_LOW) || (udev->speed == SPEED_FULL))) + return udev; + udev = udev->next; + } + return NULL; +} + +static int ohci_rh_port_reset(int port) +{ + int retry; + int reset_time; + uint32_t t0; + + reset_time = usbh_tick_from_millisecond(PORT_RESET_TIME_MS); + + for (retry = 0; retry < PORT_RESET_RETRY; retry++) + { + _ohci->HcRhPortStatus[port] = USBH_HcRhPortStatus_PRS_Msk; + + t0 = usbh_get_ticks(); + while (usbh_get_ticks() - t0 < (reset_time) + 1) + { + /* + * If device is disconnected or port enabled, we can stop port reset. + */ + if (((_ohci->HcRhPortStatus[port] & USBH_HcRhPortStatus_CCS_Msk) == 0) || + ((_ohci->HcRhPortStatus[port] & (USBH_HcRhPortStatus_PES_Msk | USBH_HcRhPortStatus_CCS_Msk)) == (USBH_HcRhPortStatus_PES_Msk | USBH_HcRhPortStatus_CCS_Msk))) + goto port_reset_done; + } + reset_time += PORT_RESET_RETRY_INC_MS; + } + + USB_debug("OHCI port %d - port reset failed!\n", port + 1); + return USBH_ERR_PORT_RESET; + +port_reset_done: + if ((_ohci->HcRhPortStatus[port] & USBH_HcRhPortStatus_CCS_Msk) == 0) /* check again if device disconnected */ + { + _ohci->HcRhPortStatus[port] = USBH_HcRhPortStatus_CSC_Msk; /* clear CSC */ + return USBH_ERR_DISCONNECTED; + } + return USBH_OK; /* port reset success */ +} + +static int ohci_rh_polling(void) +{ + int i, change = 0; + UDEV_T *udev; + int ret; + + for (i = 0; i < OHCI_PORT_CNT; i++) + { + /* clear unwanted port change status */ + _ohci->HcRhPortStatus[i] = USBH_HcRhPortStatus_OCIC_Msk | USBH_HcRhPortStatus_PRSC_Msk | + USBH_HcRhPortStatus_PSSC_Msk | USBH_HcRhPortStatus_PESC_Msk; + + if ((_ohci->HcRhPortStatus[i] & USBH_HcRhPortStatus_CSC_Msk) == 0) + continue; + rt_kprintf("OHCI port%d status change: 0x%x\n", i + 1, _ohci->HcRhPortStatus[i]); + + /*--------------------------------------------------------------------------------*/ + /* connect status change */ + /*--------------------------------------------------------------------------------*/ + + _ohci->HcRhPortStatus[i] = USBH_HcRhPortStatus_CSC_Msk; /* clear CSC */ + + if (_ohci->HcRhPortStatus[i] & USBH_HcRhPortStatus_CCS_Msk) + { + /*----------------------------------------------------------------------------*/ + /* First of all, check if there's any previously connected device. */ + /*----------------------------------------------------------------------------*/ + while (1) + { + udev = ohci_find_device_by_port(i + 1); + if (udev == NULL) + break; + usbh_disconnect_device(udev); + } + + rt_kprintf("OHCI connect device.\n"); + + if (ohci_rh_port_reset(i) != USBH_OK) + continue; + + /* + * Port reset success... + */ + udev = alloc_device(); + if (udev == NULL) + continue; + + udev->parent = NULL; + udev->port_num = i + 1; + if (_ohci->HcRhPortStatus[i] & USBH_HcRhPortStatus_LSDA_Msk) + udev->speed = SPEED_LOW; + else + udev->speed = SPEED_FULL; + udev->hc_driver = &ohci_driver; + + ret = usbh_connect_device(udev); + if (ret < 0) + { + USB_error("connect_device error! [%d]\n", ret); + free_device(udev); + } + + change = 1; + } + else + { + /* + * Device disconnected + */ + rt_kprintf("OHCI disconnect device.\n"); + while (1) + { + udev = ohci_find_device_by_port(i + 1); + if (udev == NULL) + break; + usbh_disconnect_device(udev); + } + change = 1; + } + } + return change; +} + +void td_done(TD_T *td) +{ + UTR_T *utr = td->utr; + uint32_t info; + int cc; + + info = td->Info; + + TD_debug("td_done: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td, td->Info, td->CBP, td->NextTD, td->BE); + + /* ISO ... drivers see per-TD length/status */ + if ((info & TD_TYPE_Msk) == TD_TYPE_ISO) + { + uint16_t sf; + int idx; + + sf = info & 0xFFFF; + idx = ((sf + 0x10000 - utr->iso_sf) & 0xFFFF) / get_ohci_interval(td->ed->bInterval); + if (idx >= IF_PER_UTR) + { + USB_error("ISO invalid index!! %d, %d\n", sf, utr->iso_sf); + goto td_out; + } + + cc = (td->PSW[0] >> 12) & 0xF; + if (cc == 0xF) /* this frame was not transferred */ + { + USB_debug("ISO F %d N/A!\n", sf); + utr->iso_status[idx] = USBH_ERR_SCH_OVERRUN; + goto td_out; + } + if ((cc != 0) && (cc != CC_DATA_UNDERRUN)) + { + utr->iso_status[idx] = USBH_ERR_CC_NO_ERR - cc; + goto td_out; + } + utr->iso_status[idx] = 0; + utr->iso_xlen[idx] = td->PSW[0] & 0x7FF; + } + else + { + cc = TD_CC_GET(info); + + /* short packet is fine */ + if ((cc != CC_NOERROR) && (cc != CC_DATA_UNDERRUN)) + { + USB_error("TD error, CC = 0x%x\n", cc); + if (cc == CC_STALL) + utr->status = USBH_ERR_STALL; + else + utr->status = USBH_ERR_TRANSFER; + } + + switch (info & TD_TYPE_Msk) + { + case TD_TYPE_CTRL: + if (info & TD_CTRL_DATA) + { + if (td->CBP == 0) + utr->xfer_len += td->BE - td->buff_start + 1; + else + utr->xfer_len += td->CBP - td->buff_start; + } + break; + + case TD_TYPE_BULK: + case TD_TYPE_INT: + if (td->CBP == 0) + utr->xfer_len += td->BE - td->buff_start + 1; + else + utr->xfer_len += td->CBP - td->buff_start; + break; + } + } + +td_out: + + utr->td_cnt--; + + /* If all TDs are done, call-back to requester. */ + if (utr->td_cnt == 0) + { + utr->bIsTransferDone = 1; + if (utr->func) + utr->func(utr); + } +} + +/* in IRQ context */ +static void remove_ed() +{ + ED_T *ed, *ed_p, *ied; + TD_T *td, *td_next; + UTR_T *utr; + int found; + + while (ed_remove_list != NULL) + { + ED_debug("Remove ED: 0x%x, %d\n", (int)ed_remove_list, ed_remove_list->bInterval); + ed_p = ed_remove_list; + found = 0; + + /*--------------------------------------------------------------------------------*/ + /* Remove endpoint from Control List if found */ + /*--------------------------------------------------------------------------------*/ + if ((ed_p->Info & ED_EP_ADDR_Msk) == 0) + { + if (_ohci->HcControlHeadED == (uint32_t)ed_p) + { + _ohci->HcControlHeadED = (uint32_t)ed_p->NextED; + found = 1; + } + else + { + ed = (ED_T *)_ohci->HcControlHeadED; + while (ed != NULL) + { + if (ed->NextED == (uint32_t)ed_p) + { + ed->NextED = ed_p->NextED; + found = 1; + } + ed = (ED_T *)ed->NextED; + } + } + } + + /*--------------------------------------------------------------------------------*/ + /* Remove INT or ISO endpoint from HCCA interrupt table */ + /*--------------------------------------------------------------------------------*/ + else if (ed_p->bInterval > 0) + { + ied = get_int_tree_head_node(ed_p->bInterval); + + ed = ied; + while (ed != NULL) + { + if (ed->NextED == (uint32_t)ed_p) + { + ed->NextED = ed_p->NextED; + found = 1; + break; + } + ed = (ED_T *)ed->NextED; + } + } + + /*--------------------------------------------------------------------------------*/ + /* Remove endpoint from Bulk List if found */ + /*--------------------------------------------------------------------------------*/ + else + { + if (_ohci->HcBulkHeadED == (uint32_t)ed_p) + { + ed = (ED_T *)ed_p; + _ohci->HcBulkHeadED = ed_p->NextED; + found = 1; + } + else + { + ed = (ED_T *)_ohci->HcBulkHeadED; + while (ed != NULL) + { + if (ed->NextED == (uint32_t)ed_p) + { + ed->NextED = ed_p->NextED; + found = 1; + } + ed = (ED_T *)ed->NextED; + } + } + } + + /*--------------------------------------------------------------------------------*/ + /* Remove and free all TDs under this endpoint */ + /*--------------------------------------------------------------------------------*/ + if (found) + { + td = (TD_T *)(ed_p->HeadP & ~0x3); + if (td != NULL) + { + while (td != NULL) + { + utr = td->utr; + td_next = (TD_T *)td->NextTD; + free_ohci_TD(td); + td = td_next; + + utr->td_cnt--; + if (utr->td_cnt == 0) + { + utr->status = USBH_ERR_ABORT; + utr->bIsTransferDone = 1; + if (utr->func) + utr->func(utr); + } + } + } + } + + /* + * Done. Remove this ED from [ed_remove_list] and free it. + */ + ed_remove_list = ed_p->next; + free_ohci_ED(ed_p); + } +} + + +//static irqreturn_t ohci_irq (struct usb_hcd *hcd) +//void OHCI_IRQHandler(void) +void nu_ohci_isr(int vector, void *param) +{ + TD_T *td, *td_prev, *td_next; + uint32_t int_sts; + + //if ( nu_sys_usb0_role() != USB0_ID_HOST ) return; + + int_sts = _ohci->HcInterruptStatus; + + //USB_debug("ohci int_sts = 0x%x\n", int_sts); + + if ((_ohci->HcInterruptEnable & USBH_HcInterruptEnable_SF_Msk) && + (int_sts & USBH_HcInterruptStatus_SF_Msk)) + { + int_sts &= ~USBH_HcInterruptStatus_SF_Msk; + + _ohci->HcInterruptDisable = USBH_HcInterruptDisable_SF_Msk; + remove_ed(); + _ohci->HcInterruptStatus = USBH_HcInterruptStatus_SF_Msk; + } + + if (int_sts & USBH_HcInterruptStatus_WDH_Msk) + { + int_sts &= ~USBH_HcInterruptStatus_WDH_Msk; + /* + * reverse done list + */ + td = (TD_T *)(_hcca->done_head & TD_ADDR_MASK); + _hcca->done_head = 0; + td_prev = NULL; + _ohci->HcInterruptStatus = USBH_HcInterruptStatus_WDH_Msk; + + while (td != NULL) + { + //TD_debug("Done list TD 0x%x => 0x%x\n", (int)td, (int)td->NextTD); + td_next = (TD_T *)(td->NextTD & TD_ADDR_MASK); + td->NextTD = (uint32_t)td_prev; + td_prev = td; + td = td_next; + } + td = td_prev; /* first TD of the reversed done list */ + + /* + * reclaim TDs + */ + while (td != NULL) + { + TD_debug("Reclaim TD 0x%x, next 0x%x\n", (int)td, td->NextTD); + td_next = (TD_T *)td->NextTD; + td_done(td); + free_ohci_TD(td); + td = td_next; + } + } + + if (int_sts & USBH_HcInterruptStatus_RHSC_Msk) + { + _ohci->HcInterruptDisable = USBH_HcInterruptDisable_RHSC_Msk; + } + + _ohci->HcInterruptStatus = int_sts; +} + +#ifdef ENABLE_DEBUG_MSG + +void dump_ohci_int_table() +{ + int i; + ED_T *ed; + + for (i = 0; i < 32; i++) +// for (i = 0; i < 1; i++) + + { + USB_debug("%02d: ", i); + + ed = (ED_T *)_hcca->int_table[i]; + + while (ed != NULL) + { + USB_debug("0x%x (0x%x) => ", (int)ed, ed->HeadP); + ed = (ED_T *)ed->NextED; + } + rt_kprintf("0\n"); + } +} + +void dump_ohci_regs() +{ + USB_debug("Dump OCHI registers:\n"); + USB_debug(" HcRevision = 0x%x\n", _ohci->HcRevision); + USB_debug(" HcControl = 0x%x\n", _ohci->HcControl); + USB_debug(" HcCommandStatus = 0x%x\n", _ohci->HcCommandStatus); + USB_debug(" HcInterruptStatus = 0x%x\n", _ohci->HcInterruptStatus); + USB_debug(" HcInterruptEnable = 0x%x\n", _ohci->HcInterruptEnable); + USB_debug(" HcInterruptDisable = 0x%x\n", _ohci->HcInterruptDisable); + USB_debug(" HcHCCA = 0x%x\n", _ohci->HcHCCA); + USB_debug(" HcPeriodCurrentED = 0x%x\n", _ohci->HcPeriodCurrentED); + USB_debug(" HcControlHeadED = 0x%x\n", _ohci->HcControlHeadED); + USB_debug(" HcControlCurrentED = 0x%x\n", _ohci->HcControlCurrentED); + USB_debug(" HcBulkHeadED = 0x%x\n", _ohci->HcBulkHeadED); + USB_debug(" HcBulkCurrentED = 0x%x\n", _ohci->HcBulkCurrentED); + USB_debug(" HcDoneHead = 0x%x\n", _ohci->HcDoneHead); + USB_debug(" HcFmInterval = 0x%x\n", _ohci->HcFmInterval); + USB_debug(" HcFmRemaining = 0x%x\n", _ohci->HcFmRemaining); + USB_debug(" HcFmNumber = 0x%x\n", _ohci->HcFmNumber); + USB_debug(" HcPeriodicStart = 0x%x\n", _ohci->HcPeriodicStart); + USB_debug(" HcLSThreshold = 0x%x\n", _ohci->HcLSThreshold); + USB_debug(" HcRhDescriptorA = 0x%x\n", _ohci->HcRhDescriptorA); + USB_debug(" HcRhDescriptorB = 0x%x\n", _ohci->HcRhDescriptorB); + USB_debug(" HcRhStatus = 0x%x\n", _ohci->HcRhStatus); + USB_debug(" HcRhPortStatus0 = 0x%x\n", _ohci->HcRhPortStatus[0]); + USB_debug(" HcRhPortStatus1 = 0x%x\n", _ohci->HcRhPortStatus[1]); + USB_debug(" HcPhyControl = 0x%x\n", _ohci->HcPhyControl); + USB_debug(" HcMiscControl = 0x%x\n", _ohci->HcMiscControl); +} + +void dump_ohci_ports() +{ + USB_debug("_ohci port0=0x%x, port1=0x%x\n", _ohci->HcRhPortStatus[0], _ohci->HcRhPortStatus[1]); +} + +#endif // ENABLE_DEBUG_MSG + +HC_DRV_T ohci_driver = +{ + ohci_init, /* init */ + ohci_shutdown, /* shutdown */ + ohci_suspend, /* suspend */ + ohci_resume, /* resume */ + ohci_ctrl_xfer, /* ctrl_xfer */ + ohci_bulk_xfer, /* bulk_xfer */ + ohci_int_xfer, /* int_xfer */ + ohci_iso_xfer, /* iso_xfer */ + ohci_quit_xfer, /* quit_xfer */ + ohci_rh_port_reset, /* rthub_port_reset */ + ohci_rh_polling /* rthub_polling */ +}; + +/// @endcond HIDDEN_SYMBOLS + +/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/support.c b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/support.c new file mode 100644 index 0000000000..5006034c50 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/support.c @@ -0,0 +1,324 @@ +/**************************************************************************//** + * @file support.c + * @version V1.10 + * $Revision: 11 $ + * $Date: 14/10/03 1:54p $ + * @brief Functions to support USB host driver. + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include +#include +#include + +#include "usb.h" + +/// @cond HIDDEN_SYMBOLS + + +#define USB_MEMORY_POOL_SIZE (32*1024) +#define USB_MEM_BLOCK_SIZE 128 + +#define BOUNDARY_WORD 4 + + +static uint32_t _FreeMemorySize; +uint32_t _AllocatedMemorySize; + + +#define USB_MEM_ALLOC_MAGIC 0x19685788 /* magic number in leading block */ + +typedef struct USB_mhdr +{ + uint32_t flag; /* 0:free, 1:allocated, 0x3:first block */ + uint32_t bcnt; /* if allocated, the block count of allocated memory block */ + uint32_t magic; + uint32_t reserved; +} USB_MHDR_T; + +uint8_t _USBMemoryPool[USB_MEMORY_POOL_SIZE] __attribute__((aligned(USB_MEM_BLOCK_SIZE))); + + +static USB_MHDR_T *_pCurrent; +uint32_t *_USB_pCurrent = (uint32_t *) &_pCurrent; + +static uint32_t _MemoryPoolBase, _MemoryPoolEnd; + + +void USB_InitializeMemoryPool() +{ + _MemoryPoolBase = (UINT32)&_USBMemoryPool[0] | NON_CACHE_MASK; + _MemoryPoolEnd = _MemoryPoolBase + USB_MEMORY_POOL_SIZE; + _FreeMemorySize = _MemoryPoolEnd - _MemoryPoolBase; + _AllocatedMemorySize = 0; + _pCurrent = (USB_MHDR_T *)_MemoryPoolBase; + memset((char *)_MemoryPoolBase, 0, _FreeMemorySize); +} + + +int USB_available_memory() +{ + return _FreeMemorySize; +} + + +int USB_allocated_memory() +{ + return _AllocatedMemorySize; +} + + +void *USB_malloc(INT wanted_size, INT boundary) +{ + USB_MHDR_T *pPrimitivePos = _pCurrent; + USB_MHDR_T *pFound; + INT found_size = -1; + INT i, block_count; + INT wrap = 0; + int disable_ohci_irq, disable_ehci_irq; + + if (IS_OHCI_IRQ_ENABLED()) + disable_ohci_irq = 1; + else + disable_ohci_irq = 0; + + if (IS_EHCI_IRQ_ENABLED()) + disable_ehci_irq = 1; + else + disable_ehci_irq = 0; + + if (disable_ohci_irq) + DISABLE_OHCI_IRQ(); + if (disable_ehci_irq) + DISABLE_EHCI_IRQ(); + + if (wanted_size >= _FreeMemorySize) + { + rt_kprintf("USB_malloc - want=%d, free=%d\n", wanted_size, _FreeMemorySize); + if (disable_ohci_irq) + ENABLE_OHCI_IRQ(); + if (disable_ehci_irq) + ENABLE_EHCI_IRQ(); + return NULL; + } + + if ((UINT32)_pCurrent >= _MemoryPoolEnd) + _pCurrent = (USB_MHDR_T *)_MemoryPoolBase; /* wrapped */ + + do + { + if (_pCurrent->flag) /* is not a free block */ + { + if (_pCurrent->magic != USB_MEM_ALLOC_MAGIC) + { + rt_kprintf("\nUSB_malloc - incorrect magic number! C:%x F:%x, wanted:%d, Base:0x%x, End:0x%x\n", (UINT32)_pCurrent, _FreeMemorySize, wanted_size, (UINT32)_MemoryPoolBase, (UINT32)_MemoryPoolEnd); + if (disable_ohci_irq) + ENABLE_OHCI_IRQ(); + if (disable_ehci_irq) + ENABLE_EHCI_IRQ(); + return NULL; + } + + if (_pCurrent->flag == 0x3) + _pCurrent = (USB_MHDR_T *)((UINT32)_pCurrent + _pCurrent->bcnt * USB_MEM_BLOCK_SIZE); + else + { + rt_kprintf("USB_malloc warning - not the first block!\n"); + _pCurrent = (USB_MHDR_T *)((UINT32)_pCurrent + USB_MEM_BLOCK_SIZE); + } + + if ((UINT32)_pCurrent > _MemoryPoolEnd) + rt_kprintf("USB_malloc - behind limit!!\n"); + + if ((UINT32)_pCurrent == _MemoryPoolEnd) + { + //rt_kprintf("USB_alloc - warp!!\n"); + wrap = 1; + _pCurrent = (USB_MHDR_T *)_MemoryPoolBase; /* wrapped */ + } + + found_size = -1; /* reset the accumlator */ + } + else /* is a free block */ + { + if (found_size == -1) /* the leading block */ + { + pFound = _pCurrent; + block_count = 1; + + if (boundary > BOUNDARY_WORD) + found_size = 0; /* not use the data area of the leading block */ + else + found_size = USB_MEM_BLOCK_SIZE - sizeof(USB_MHDR_T); + + /* check boundary - + * If boundary > BOUNDARY_WORD, the start of next block should + * be the beginning address of allocated memory. Thus, we check + * the boundary of the next block. The leading block will be + * used as a header only. + */ + if ((boundary > BOUNDARY_WORD) && + ((((UINT32)_pCurrent) + USB_MEM_BLOCK_SIZE >= _MemoryPoolEnd) || + ((((UINT32)_pCurrent) + USB_MEM_BLOCK_SIZE) % boundary != 0))) + found_size = -1; /* violate boundary, reset the accumlator */ + } + else /* not the leading block */ + { + found_size += USB_MEM_BLOCK_SIZE; + block_count++; + } + + if (found_size >= wanted_size) + { + pFound->bcnt = block_count; + pFound->magic = USB_MEM_ALLOC_MAGIC; + _FreeMemorySize -= block_count * USB_MEM_BLOCK_SIZE; + _AllocatedMemorySize += block_count * USB_MEM_BLOCK_SIZE; + _pCurrent = pFound; + for (i = 0; i < block_count; i++) + { + _pCurrent->flag = 1; /* allocate block */ + _pCurrent = (USB_MHDR_T *)((UINT32)_pCurrent + USB_MEM_BLOCK_SIZE); + } + pFound->flag = 0x3; + + if (boundary > BOUNDARY_WORD) + { + if (disable_ohci_irq) + ENABLE_OHCI_IRQ(); + if (disable_ehci_irq) + ENABLE_EHCI_IRQ(); + //rt_kprintf("- 0x%x, %d\n", (int)pFound, wanted_size); + return (void *)((UINT32)pFound + USB_MEM_BLOCK_SIZE); + } + else + { + //USB_debug("USB_malloc(%d,%d):%x\tsize:%d, C:0x%x, %d\n", wanted_size, boundary, (UINT32)pFound + sizeof(USB_MHDR_T), block_count * USB_MEM_BLOCK_SIZE, _pCurrent, block_count); + if (disable_ohci_irq) + ENABLE_OHCI_IRQ(); + if (disable_ehci_irq) + ENABLE_EHCI_IRQ(); + //rt_kprintf("- 0x%x, %d\n", (int)pFound, wanted_size); + return (void *)((UINT32)pFound + sizeof(USB_MHDR_T)); + } + } + + /* advance to the next block */ + _pCurrent = (USB_MHDR_T *)((UINT32)_pCurrent + USB_MEM_BLOCK_SIZE); + if ((UINT32)_pCurrent >= _MemoryPoolEnd) + { + wrap = 1; + _pCurrent = (USB_MHDR_T *)_MemoryPoolBase; /* wrapped */ + found_size = -1; /* reset accumlator */ + } + } + } + while ((wrap == 0) || (_pCurrent < pPrimitivePos)); + + rt_kprintf("USB_malloc - No free memory!\n"); + if (disable_ohci_irq) + ENABLE_OHCI_IRQ(); + if (disable_ehci_irq) + ENABLE_EHCI_IRQ(); + return NULL; +} + + +void USB_free(void *alloc_addr) +{ + USB_MHDR_T *pMblk; + UINT32 addr = (UINT32)alloc_addr; + INT i, count; + int disable_ohci_irq, disable_ehci_irq; + + if (IS_OHCI_IRQ_ENABLED()) + disable_ohci_irq = 1; + else + disable_ohci_irq = 0; + + if (IS_EHCI_IRQ_ENABLED()) + disable_ehci_irq = 1; + else + disable_ehci_irq = 0; + + //rt_kprintf("USB_free: 0x%x\n", (int)alloc_addr); + + if ((addr < _MemoryPoolBase) || (addr >= _MemoryPoolEnd)) + { + if (addr) + { + rt_kprintf("[%s]Wrong!!\n", __func__); + //free(alloc_addr); + } + return; + } + + if (disable_ohci_irq) + DISABLE_OHCI_IRQ(); + if (disable_ehci_irq) + DISABLE_EHCI_IRQ(); + + //rt_kprintf("USB_free:%x\n", (INT)addr+USB_MEM_BLOCK_SIZE); + + /* get the leading block address */ + if (addr % USB_MEM_BLOCK_SIZE == 0) + addr -= USB_MEM_BLOCK_SIZE; + else + addr -= sizeof(USB_MHDR_T); + + if (addr % USB_MEM_BLOCK_SIZE != 0) + { + rt_kprintf("USB_free fatal error on address: %x!!\n", (UINT32)alloc_addr); + if (disable_ohci_irq) + ENABLE_OHCI_IRQ(); + if (disable_ehci_irq) + ENABLE_EHCI_IRQ(); + return; + } + + pMblk = (USB_MHDR_T *)addr; + if (pMblk->flag == 0) + { + rt_kprintf("USB_free(), warning - try to free a free block: %x\n", (UINT32)alloc_addr); + if (disable_ohci_irq) + ENABLE_OHCI_IRQ(); + if (disable_ehci_irq) + ENABLE_EHCI_IRQ(); + return; + } + if (pMblk->magic != USB_MEM_ALLOC_MAGIC) + { + rt_kprintf("USB_free(), warning - try to free an unknow block at address:%x.\n", addr); + if (disable_ohci_irq) + ENABLE_OHCI_IRQ(); + if (disable_ehci_irq) + ENABLE_EHCI_IRQ(); + return; + } + + //_pCurrent = pMblk; + + //rt_kprintf("+ 0x%x, %d\n", (int)pMblk, pMblk->bcnt); + + count = pMblk->bcnt; + for (i = 0; i < count; i++) + { + pMblk->flag = 0; /* release block */ + pMblk = (USB_MHDR_T *)((UINT32)pMblk + USB_MEM_BLOCK_SIZE); + } + + _FreeMemorySize += count * USB_MEM_BLOCK_SIZE; + _AllocatedMemorySize -= count * USB_MEM_BLOCK_SIZE; + if (disable_ohci_irq) + ENABLE_OHCI_IRQ(); + if (disable_ehci_irq) + ENABLE_EHCI_IRQ(); + return; +} + + +/// @endcond HIDDEN_SYMBOLS + diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/usb_core.c b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/usb_core.c new file mode 100644 index 0000000000..7bb6c30bbe --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/usb_core.c @@ -0,0 +1,312 @@ +/**************************************************************************//** + * @file usb_core.c + * @version V1.10 + * $Revision: 11 $ + * $Date: 14/10/03 1:54p $ + * @brief USB Host library core. + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include +#include +#include + +#include "usb.h" +#include "hub.h" + + +/// @cond HIDDEN_SYMBOLS + +USBH_T *_ohci; +HSUSBH_T *_ehci; + +static UDEV_DRV_T *_drivers[MAX_UDEV_DRIVER]; + +static CONN_FUNC *g_conn_func, *g_disconn_func; + + +//extern void EHCI_IRQHandler(void); +//extern void OHCI_IRQHandler(void); +extern void nu_ohci_isr(int vector, void *param); +extern void nu_ehci_isr(int vector, void *param); + + +/// @endcond HIDDEN_SYMBOLS + + +/** + * @brief Initialize NUC980 USB Host controller and USB stack. + * + * @return None. + */ +void usbh_core_init() +{ + DISABLE_EHCI_IRQ(); + DISABLE_OHCI_IRQ(); + + _ohci = USBH; + _ehci = HSUSBH; + + memset(_drivers, 0, sizeof(_drivers)); + + g_conn_func = NULL; + g_disconn_func = NULL; + +// usbh_hub_init(); + + _ehci->USBPCR0 = 0x160; /* enable PHY 0 */ + _ehci->USBPCR1 = 0x520; /* enable PHY 1 */ + usbh_memory_init(); + + //_ohci->HcMiscControl |= USBH_HcMiscControl_OCAL_Msk; /* Over-current active low */ + _ohci->HcMiscControl &= ~USBH_HcMiscControl_OCAL_Msk; /* Over-current active high */ + +#ifdef ENABLE_OHCI + //sysInstallISR(IRQ_LEVEL_1, IRQ_OHCI, (PVOID)OHCI_IRQHandler); + rt_hw_interrupt_install(IRQ_OHCI, nu_ohci_isr, NULL, "ohci"); + rt_hw_interrupt_set_priority(IRQ_OHCI, IRQ_LEVEL_1); + + ohci_driver.init(); + ENABLE_OHCI_IRQ(); +#endif + +#ifdef ENABLE_EHCI + //sysInstallISR(IRQ_LEVEL_1, IRQ_EHCI, (PVOID)EHCI_IRQHandler); + rt_hw_interrupt_install(IRQ_EHCI, nu_ehci_isr, NULL, "ehci"); + rt_hw_interrupt_set_priority(IRQ_EHCI, IRQ_LEVEL_1); + + ehci_driver.init(); + ENABLE_EHCI_IRQ(); +#endif +} + + +/** + * @brief Let USB stack polls all root hubs. If there's any hub port + * change found, USB stack will manage the hub events in this function call. + * In this function, USB stack enumerates newly connected devices and remove staff + * of disconnected devices. User's application should periodically invoke this + * function. + * @return There's hub port change or not. + * @retval 0 No any hub port status changes found. + * @retval 1 There's hub port status changes. + */ +int usbh_polling_root_hubs(void) +{ + int ret, change = 0; + +#ifdef ENABLE_EHCI + do + { + ret = ehci_driver.rthub_polling(); + if (ret) + change = 1; + } + while (ret == 1); + + // scan_isochronous_list(); + +#endif + +#ifdef ENABLE_OHCI + do + { + ret = ohci_driver.rthub_polling(); + if (ret) + change = 1; + } + while (ret == 1); +#endif + + return change; +} + +/** + * @brief Force to quit an endpoint transfer. + * @param[in] udev The USB device. + * @param[in] ep The endpoint to be quit. + * @retval 0 Transfer success + * @retval < 0 Failed. Refer to error code definitions. + */ +int usbh_quit_xfer(UDEV_T *udev, EP_INFO_T *ep) +{ + return udev->hc_driver->quit_xfer(NULL, ep); +} + + +int usbh_connect_device(UDEV_T *udev) +{ + usbh_delay_ms(100); /* initially, give 100 ms delay */ + + if (g_conn_func) + g_conn_func(udev, 0); + + return 0; +} + + +void usbh_disconnect_device(UDEV_T *udev) +{ + USB_debug("disconnect device...\n"); + + if (g_disconn_func) + g_disconn_func(udev, 0); + + +#if 1 //CHECK: Maybe create a new API to quit_xfer and free udev for application + usbh_quit_xfer(udev, &(udev->ep0)); /* Quit control transfer if hw_pipe is not NULL. */ + + /* remove device from global device list */ +// free_dev_address(udev->dev_num); + free_device(udev); + +// usbh_memory_used(); +#endif +} + +/** + * @brief Install device connect and disconnect callback function. + * + * @param[in] conn_func Device connect callback function. + * @param[in] disconn_func Device disconnect callback function. + * @return None. + */ +void usbh_install_conn_callback(CONN_FUNC *conn_func, CONN_FUNC *disconn_func) +{ + g_conn_func = conn_func; + g_disconn_func = disconn_func; +} + +int usbh_reset_port(UDEV_T *udev) +{ + if (udev->parent == NULL) + { + if (udev->hc_driver) + return udev->hc_driver->rthub_port_reset(udev->port_num - 1); + else + return USBH_ERR_NOT_FOUND; + } + else + { + return udev->parent->port_reset(udev->parent, udev->port_num); + } +} + + +/** + * @brief Force to quit an UTR transfer. + * @param[in] utr The UTR transfer to be quit. + * @retval 0 Transfer success + * @retval < 0 Failed. Refer to error code definitions. + */ +int usbh_quit_utr(UTR_T *utr) +{ + if (!utr || !utr->udev) + return USBH_ERR_NOT_FOUND; + + return utr->udev->hc_driver->quit_xfer(utr, NULL); +} + + +/** + * @brief Execute an USB request in control transfer. This function returns after the request + * was done or aborted. + * @param[in] udev The target USB device. + * @param[in] bmRequestType Characteristics of request + * @param[in] bRequest Specific request + * @param[in] wValue Word-sized field that varies according to request + * @param[in] wIndex Word-sized field that varies according to request + * @param[in] wLength Number of bytes to transfer if there is a Data stage + * @param[in] buff Data buffer used in data stage + * @param[out] xfer_len Transmitted/received length of data + * @param[in] timeout Time-out limit (in 10ms - timer tick) of this transfer + * @retval 0 Transfer success + * @retval < 0 Transfer failed. Refer to error code definitions. + */ +int usbh_ctrl_xfer(UDEV_T *udev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + uint16_t wLength, uint8_t *buff, uint32_t *xfer_len, uint32_t timeout) +{ + UTR_T *utr; + uint32_t t0, timeout_tick; + int status; + + *xfer_len = 0; + + //if (check_device(udev)) + // return USBH_ERR_INVALID_PARAM; + + utr = alloc_utr(udev); + if (utr == NULL) + return USBH_ERR_MEMORY_OUT; + + utr->setup.bmRequestType = bmRequestType; + utr->setup.bRequest = bRequest; + utr->setup.wValue = wValue; + utr->setup.wIndex = wIndex; + utr->setup.wLength = wLength; + + utr->buff = buff; + utr->data_len = wLength; + utr->bIsTransferDone = 0; + status = udev->hc_driver->ctrl_xfer(utr); + if (status < 0) + { + udev->ep0.hw_pipe = NULL; + free_utr(utr); + return status; + } + + timeout_tick = usbh_tick_from_millisecond(timeout); + t0 = usbh_get_ticks(); + while (utr->bIsTransferDone == 0) + { + if (usbh_get_ticks() - t0 > timeout_tick) + { + usbh_quit_utr(utr); + free_utr(utr); + udev->ep0.hw_pipe = NULL; + return USBH_ERR_TIMEOUT; + } + } + + status = utr->status; + + if (status == 0) + { + *xfer_len = utr->xfer_len; + } + free_utr(utr); + + return status; +} + +/** + * @brief Execute a bulk transfer request. This function will return immediately after + * issued the bulk transfer. USB stack will later call back utr->func() once the bulk + * transfer was done or aborted. + * @param[in] utr The bulk transfer request. + * @retval 0 Transfer success + * @retval < 0 Failed. Refer to error code definitions. + */ +int usbh_bulk_xfer(UTR_T *utr) +{ + return utr->udev->hc_driver->bulk_xfer(utr); +} + +/** + * @brief Execute an interrupt transfer request. This function will return immediately after + * issued the interrupt transfer. USB stack will later call back utr->func() once the + * interrupt transfer was done or aborted. + * @param[in] utr The interrupt transfer request. + * @retval 0 Transfer success + * @retval < 0 Failed. Refer to error code definitions. + */ +int usbh_int_xfer(UTR_T *utr) +{ + return utr->udev->hc_driver->int_xfer(utr); +} + + diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig new file mode 100644 index 0000000000..97b1a58f24 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig @@ -0,0 +1,500 @@ +config SOC_SERIES_N9H30 + bool + select ARCH_ARM_ARM9 + select SOC_FAMILY_NUMICRO + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + + config BSP_USE_STDDRIVER_SOURCE + bool "Build StdDriver source" + default n + + config BSP_USING_MMU + bool "Enable MMU" + default y + + config BSP_USING_GPIO + bool "Enable General Purpose I/O(GPIO)" + select RT_USING_PIN + default y + + menuconfig BSP_USING_CLK + bool "Enable Clock Controller(CLK)" + select RT_USING_PM + select BSP_USING_TMR + default y + help + Choose this option if you need CLK/PM function. + Notice: Enable the option will hold timer3 resource + + if BSP_USING_CLK + config NU_CLK_INVOKE_WKTMR + bool "Enable SPD1 and DPD mode wakeup timer. (About 6.6 Secs)" + default y + endif + + menuconfig BSP_USING_EMAC + bool "Enable Ethernet MAC Controller(EMAC)" + select RT_USING_LWIP + select RT_USING_NETDEV + + if BSP_USING_EMAC + config BSP_USING_EMAC0 + bool "Enable EMAC0" + + config BSP_USING_EMAC1 + bool "Enable EMAC1" + endif + + menuconfig BSP_USING_RTC + bool "Enable Real Time Clock(RTC)" + select RT_USING_RTC + + config NU_RTC_SUPPORT_IO_RW + bool "Support device RW entry" + depends on BSP_USING_RTC && RT_USING_RTC + + config NU_RTC_SUPPORT_MSH_CMD + bool "Support module shell command" + depends on BSP_USING_RTC && RT_USING_RTC + + menuconfig BSP_USING_ADC + bool "Enable Analog-to-Digital Converter(ADC)" + select RT_USING_ADC + + if BSP_USING_ADC + config BSP_USING_ADC_TOUCH + bool "Enable ADC Touching function" + select RT_USING_TOUCH + default y + endif + + menuconfig BSP_USING_ETMR + bool "Enable Enhance Timer Controller(ETIMER)" + + if BSP_USING_ETMR + + config BSP_USING_ETIMER + bool + + config BSP_USING_ETIMER_CAPTURE + bool + + config BSP_USING_ETMR0 + bool "Enable ETIMER0" + depends on BSP_USING_ETMR + + if BSP_USING_ETMR0 + choice + prompt "Select ETIMER0 function mode" + + config BSP_USING_ETIMER0 + select BSP_USING_ETIMER + select RT_USING_HWTIMER + bool "ETIMER" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_ETIMER0_CAPTURE + select BSP_USING_ETIMER_CAPTURE + select RT_USING_INPUT_CAPTURE + bool "ETIMER CAPTURE" + help + Choose this option if you need CAPTURE function mode. + + endchoice + endif + + config BSP_USING_ETMR1 + bool "Enable ETIMER1" + depends on BSP_USING_ETMR + + if BSP_USING_ETMR1 + choice + prompt "Select ETIMER1 function mode" + + config BSP_USING_ETIMER1 + select BSP_USING_ETIMER + select RT_USING_HWTIMER + bool "ETIMER" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_ETIMER1_CAPTURE + select BSP_USING_ETIMER_CAPTURE + select RT_USING_INPUT_CAPTURE + bool "ETIMER CAPTURE" + help + Choose this option if you need CAPTURE function mode. + endchoice + endif + + config BSP_USING_ETMR2 + bool "Enable ETIMER2" + depends on BSP_USING_ETMR + + if BSP_USING_ETMR2 + choice + prompt "Select ETIMER2 function mode" + + config BSP_USING_ETIMER2 + select BSP_USING_ETIMER + select RT_USING_HWTIMER + bool "ETIMER" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_ETIMER2_CAPTURE + select BSP_USING_ETIMER_CAPTURE + select RT_USING_INPUT_CAPTURE + bool "ETIMER CAPTURE" + help + Choose this option if you need CAPTURE function mode. + endchoice + endif + + config BSP_USING_ETMR3 + bool "Enable ETIMER3" + depends on BSP_USING_ETMR + + if BSP_USING_ETMR3 + choice + prompt "Select ETIMER3 function mode" + + config BSP_USING_ETIMER3 + select BSP_USING_ETIMER + select RT_USING_HWTIMER + bool "ETIMER" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_ETIMER3_CAPTURE + select BSP_USING_ETIMER_CAPTURE + select RT_USING_INPUT_CAPTURE + bool "ETIMER CAPTURE" + help + Choose this option if you need CAPTURE function mode. + endchoice + endif + + endif + + menuconfig BSP_USING_TMR + bool "Enable Timer Controller(TIMER)" + + if BSP_USING_TMR + + config BSP_USING_TIMER + bool + + config BSP_USING_TIMER0 + select BSP_USING_TIMER + select RT_USING_HWTIMER + bool "TIMER0" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_TIMER1 + select BSP_USING_TIMER + select RT_USING_HWTIMER + bool "TIMER1" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_TIMER2 + select BSP_USING_TIMER + select RT_USING_HWTIMER + bool "TIMER2" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_TIMER3 + select BSP_USING_TIMER + select RT_USING_HWTIMER + bool "TIMER3" + help + Choose this option if you need TIMER function mode. + + endif + + menuconfig BSP_USING_UART + bool "Enable Universal Asynchronous Receiver/Transmitters(UART)" + select RT_USING_SERIAL + + if BSP_USING_UART + config BSP_USING_UART0 + bool "Enable UART0" + + config BSP_USING_UART1 + bool "Enable UART1" + + config BSP_USING_UART2 + bool "Enable UART2" + + config BSP_USING_UART3 + bool "Enable UART3" + + config BSP_USING_UART4 + bool "Enable UART4" + + config BSP_USING_UART5 + bool "Enable UART5" + + config BSP_USING_UART6 + bool "Enable UART6" + + config BSP_USING_UART7 + bool "Enable UART7" + + config BSP_USING_UART8 + bool "Enable UART8" + + config BSP_USING_UART9 + bool "Enable UART9" + + config BSP_USING_UART10 + bool "Enable UART10" + + endif + + menuconfig BSP_USING_I2C + bool "Enable I2C Serial Interface Controller(I2C)" + select RT_USING_I2C + + if BSP_USING_I2C + config BSP_USING_I2C0 + bool "Enable I2C0" + + config BSP_USING_I2C1 + bool "Enable I2C1" + endif + + menuconfig BSP_USING_SDH + bool "Enable Secure Digital Host Controller(SDH)" + select RT_USING_DFS + + if BSP_USING_SDH + config BSP_USING_SDH0 + bool "Enable SDH0" + + config BSP_USING_SDH1 + bool "Enable SDH1" + + config NU_SDH_HOTPLUG + bool "Using HOTPLUG" + default y + + config NU_SDH_MOUNT_ON_ROOT + bool "Mount on root" + + endif + + menuconfig BSP_USING_CAN + bool "Enable Controller Area Network(CAN)" + select RT_USING_CAN + + if BSP_USING_CAN + config BSP_USING_CAN0 + bool "Enable CAN0" + + config BSP_USING_CAN1 + bool "Enable CAN1" + endif + + menuconfig BSP_USING_PWM + bool "Enable PWM Generator (PWM)" + select RT_USING_PWM + + if BSP_USING_PWM + config BSP_USING_PWM0 + select RT_USING_PWM + bool "Enable PWM0" + help + Choose this option if you need PWM function mode. + endif + + menuconfig BSP_USING_QSPI + bool "Enable Quad Serial Peripheral Interface(QSPI)" + select RT_USING_SPI + + if BSP_USING_QSPI + choice + prompt "Select QSPI0 function mode" + config BSP_USING_QSPI0_NONE + bool "NONE" + help + Choose this option if you need not QSPI0. + + config BSP_USING_QSPI0 + bool "Enable QSPI0" + help + Choose this option if you need QSPI function mode. + endchoice + + choice + prompt "Select QSPI1 function mode" + config BSP_USING_QSPI1_NONE + bool "NONE" + help + Choose this option if you need not QSPI1. + + config BSP_USING_QSPI1 + bool "Enable QSPI1" + help + Choose this option if you need QSPI function mode. + endchoice + + endif + + config BSP_USING_I2S + bool "Enable I2S Controller(I2S)" + select RT_USING_AUDIO + + if BSP_USING_I2S + config NU_I2S_DMA_FIFO_SIZE + int "DMA Buffer size of capture and playback" + range 2048 4096 + default 2048 + endif + + menuconfig BSP_USING_SCUART + bool "Enable Smart Card Host Interface - UART(SCUART)" + + if BSP_USING_SCUART + config BSP_USING_SCUART0 + bool "Enable SCUART0" + + config BSP_USING_SCUART1 + bool "Enable SCUART1" + endif + + menuconfig BSP_USING_CRYPTO + bool "Enable Cryptographic Accelerator(CRYPTO)" + select RT_USING_HWCRYPTO + select RT_HWCRYPTO_USING_AES + select RT_HWCRYPTO_USING_AES_ECB + select RT_HWCRYPTO_USING_AES_CBC + select RT_HWCRYPTO_USING_AES_CFB + select RT_HWCRYPTO_USING_AES_CTR + select RT_HWCRYPTO_USING_AES_CFB + select RT_HWCRYPTO_USING_AES_OFB + select RT_HWCRYPTO_USING_SHA1 + select RT_HWCRYPTO_USING_SHA2 + select RT_HWCRYPTO_USING_SHA2_224 + select RT_HWCRYPTO_USING_SHA2_256 + select RT_HWCRYPTO_USING_SHA2_384 + select RT_HWCRYPTO_USING_SHA2_512 + select RT_HWCRYPTO_USING_RNG + + if BSP_USING_CRYPTO + config NU_PRNG_USE_SEED + bool "Use specified seed value." + help + Specify the seed value to PRNG. + + if NU_PRNG_USE_SEED + config NU_PRNG_SEED_VALUE + hex "Enter seed value" + range 0 0xFFFFFFFF + default 0 + endif + endif + + menuconfig BSP_USING_SOFT_I2C + bool "Enable SOFT I2C" + + if BSP_USING_SOFT_I2C + config BSP_USING_SOFT_I2C0 + bool "Enable SOFT I2C0" + select RT_USING_I2C + select RT_USING_I2C_BITOPS + default n + + if BSP_USING_SOFT_I2C0 + config BSP_SOFT_I2C0_SCL_PIN + hex "Specify the pin index of SCL of SOFT I2C0" + range 0 0x7F + default 0x18 + + config BSP_SOFT_I2C0_SDA_PIN + hex "Specify the pin index of SDA of SOFT I2C0" + range 0 0x7F + default 0x17 + endif + + config BSP_USING_SOFT_I2C1 + bool "Enable SOFT I2C1" + select RT_USING_I2C + select RT_USING_I2C_BITOPS + default n + + if BSP_USING_SOFT_I2C1 + config BSP_SOFT_I2C1_SCL_PIN + hex "Specify the pin index of SCL of SOFT I2C1" + range 0 0x7F + default 0x0B + + config BSP_SOFT_I2C1_SDA_PIN + hex "Specify the pin index of SDA of SOFT I2C1" + range 0 0x7F + default 0x0A + endif + endif + + config BSP_USING_WDT + bool "Enable Watchdog Timer(WDT)" + select RT_USING_WDT + default y + + config BSP_USING_EBI + bool "Enable External Bus Interface(EBI)" + default n + + config BSP_USING_VPOST + bool "Enable LCD Display engine(VPOST)" + default y + + if BSP_USING_VPOST + choice + prompt "Select Supported LCM panel" + default LCM_USING_FW070TFT + config LCM_USING_E50A2V1 + bool "LCM_E50A2V1(800x480x2)" + + config LCM_USING_LSA40AT9001 + bool "LCM_LSA40AT9001(800x600x2)" + + config LCM_USING_FW070TFT + bool "LCM_FW070TFT(800x480x4)" + + endchoice + + config VPOST_USING_LCD_IDX + int + default 0 if LCM_USING_E50A2V1 + + default 2 if LCM_USING_LSA40AT9001 + default 3 if LCM_USING_FW070TFT + + config LCM_USING_BPP + int + default 2 if LCM_USING_E50A2V1 + + default 2 if LCM_USING_LSA40AT9001 + default 4 if LCM_USING_FW070TFT + + config BSP_USING_VPOST_OSD + bool "Enable VPOST OSD layer" + default n + + endif + + config BSP_USING_USBD + bool "Enable USB Device Controller(USBD)" + select RT_USING_USB_DEVICE + + config BSP_USING_USBH + bool "Enable USB Host Controller(USBH)" + select RT_USING_USB_HOST + select RT_USBH_MSTORAGE diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/SConscript b/bsp/nuvoton/libraries/n9h30/rtt_port/SConscript new file mode 100644 index 0000000000..e1b907cc3c --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/SConscript @@ -0,0 +1,14 @@ +# RT-Thread building script for component + +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +CPPPATH = [cwd] +group = [] + +# USB driver constrain +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c new file mode 100644 index 0000000000..5ce1c64276 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c @@ -0,0 +1,728 @@ +/**************************************************************************//** +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_ADC) + +#include +#include "NuMicro.h" +#include "drv_sys.h" +#include "nu_bitutil.h" +#include "drv_adc.h" + +/* Private define ---------------------------------------------------------------*/ +#define DEF_ADC_TOUCH_SMPL_TICK 40 + +/* Private Typedef --------------------------------------------------------------*/ +struct nu_adc +{ + struct rt_adc_device dev; + char *name; + uint32_t OpFreqKHz; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + int chn_num; + uint32_t chn_mask; + rt_sem_t m_psSem; + + rt_touch_t psRtTouch; + rt_timer_t psRtTouchMenuTimer; + + nu_adc_cb m_isr[eAdc_ISR_CNT]; + nu_adc_cb m_wkisr[eAdc_WKISR_CNT]; + + rt_mq_t m_pmqTouchXYZ; +}; +typedef struct nu_adc *nu_adc_t; + +struct nu_adc_touch_data +{ + uint16_t u16X; + uint16_t u16Y; + uint16_t u16Z0; + uint16_t u16Z1; +}; +typedef struct nu_adc_touch_data *nu_adc_touch_data_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled); +static rt_err_t nu_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value); +static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args); + +/* Public functions ------------------------------------------------------------*/ +int rt_hw_adc_init(void); + +/* Private variables ------------------------------------------------------------*/ + +static struct nu_adc g_sNuADC = +{ + .name = "adc", + .OpFreqKHz = 4000, /* 1000 <= OpFreqKHz <= 4000 */ + .chn_num = 8, + .irqn = IRQ_ADC, + .rstidx = ADCRST, + .clkidx = ADCCKEN, + .chn_mask = 0 +}; + +static void nu_adc_isr(int vector, void *param) +{ + rt_int32_t isr, wkisr; + nu_adc_t psNuAdc = (nu_adc_t)param; + rt_int32_t irqidx; + + isr = inpw(REG_ADC_ISR); + wkisr = inpw(REG_ADC_WKISR); + + while ((irqidx = nu_ctz(isr)) < eAdc_ISR_CNT) + { + uint32_t u32IsrBitMask = 1 << irqidx ; + + if (psNuAdc->m_isr[irqidx].cbfunc != RT_NULL) + { + //rt_kprintf("[%s] %d %x\n", __func__, irqidx, psNuAdc->m_isr[irqidx].cbfunc); + psNuAdc->m_isr[irqidx].cbfunc(isr, psNuAdc->m_isr[irqidx].private_data); + } + + /* Clear sent bit */ + outpw(REG_ADC_ISR, u32IsrBitMask); + isr &= ~(u32IsrBitMask); + } //while + + while ((irqidx = nu_ctz(wkisr)) < eAdc_WKISR_CNT) + { + uint32_t u32IsrBitMask = 1 << irqidx ; + + if (psNuAdc->m_wkisr[irqidx].cbfunc != RT_NULL) + { + psNuAdc->m_wkisr[irqidx].cbfunc(wkisr, psNuAdc->m_wkisr[irqidx].private_data); + } + + /* Clear sent bit */ + outpw(REG_ADC_WKISR, u32IsrBitMask); + wkisr &= ~(u32IsrBitMask); + } //while +} + +static rt_err_t _nu_adc_init(rt_device_t dev) +{ + uint32_t div; + nu_adc_t psNuAdc = (nu_adc_t)dev; + + /* ADC Engine Clock is set to freq Khz */ + if (psNuAdc->OpFreqKHz > 4000) psNuAdc->OpFreqKHz = 4000; + if (psNuAdc->OpFreqKHz < 1000) psNuAdc->OpFreqKHz = 1000; + + div = 12000 / psNuAdc->OpFreqKHz; + + outpw(REG_CLK_DIVCTL7, inpw(REG_CLK_DIVCTL7) & ~((0x3 << 19) | (0x7 << 16) | (0xFFul << 24))); + outpw(REG_CLK_DIVCTL7, (0 << 19) | (0 << 16) | ((div - 1) << 24)); + + /* Install interrupt service routine */ + rt_hw_interrupt_install(psNuAdc->irqn, nu_adc_isr, (void *)psNuAdc, psNuAdc->name); + + return RT_EOK; +} + +void nu_adc_touch_detect(rt_bool_t bStartDetect) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + + if (bStartDetect) + { + /* Start detect PenDown */ + _nu_adc_control((rt_device_t)psNuAdc, PEPOWER_ON, RT_NULL); + } + else + { + /* Stop detect PenDown */ + _nu_adc_control((rt_device_t)psNuAdc, PEPOWER_OFF, RT_NULL); + } +} + +static int32_t AdcMenuStartCallback(uint32_t status, uint32_t userData) +{ + static struct nu_adc_touch_data point; + static rt_bool_t bDrop = RT_FALSE; + static uint16_t u16LastZ0 = 0xfffful; + + nu_adc_t psNuAdc = (nu_adc_t)userData; + + if (psNuAdc->psRtTouch != RT_NULL) + { + uint32_t value; + + value = inpw(REG_ADC_XYDATA); + point.u16X = (uint16_t)(value & 0x0ffful); + point.u16Y = (uint16_t)((value >> 16) & 0x0ffful); + + value = inpw(REG_ADC_ZDATA); + point.u16Z0 = (uint16_t)(value & 0x0ffful); + point.u16Z1 = (uint16_t)((value >> 16) & 0x0ffful); + + /* Trigger next or not. */ + if (point.u16Z0 == 0) + { + /* Stop sampling procedure. */ + rt_timer_stop(g_sNuADC.psRtTouchMenuTimer); + + /* Re-start pendown detection */ + nu_adc_touch_detect(RT_TRUE); + + bDrop = RT_TRUE; + } + else + { + bDrop = RT_FALSE; + } + + /* Notify upper layer. */ + if ((!bDrop || (u16LastZ0 != 0)) && rt_mq_send(psNuAdc->m_pmqTouchXYZ, (const void *)&point, sizeof(struct nu_adc_touch_data)) == RT_EOK) + { + rt_hw_touch_isr(psNuAdc->psRtTouch); + } + + u16LastZ0 = point.u16Z0; + } + else + { + rt_err_t result = rt_sem_release(psNuAdc->m_psSem); + RT_ASSERT(result == RT_EOK); + } + + return 0; +} + + +static int32_t PenDownCallback(uint32_t status, uint32_t userData) +{ + nu_adc_touch_detect(RT_FALSE); + + rt_timer_start(g_sNuADC.psRtTouchMenuTimer); + + return 0; +} + +int32_t nu_adc_read_touch_xyz(uint16_t *bufX, uint16_t *bufY, uint16_t *bufZ0, uint16_t *bufZ1, int32_t dataCnt) +{ + int i; + struct nu_adc_touch_data value; + + for (i = 0 ; i < dataCnt; i++) + { + if (rt_mq_recv(g_sNuADC.m_pmqTouchXYZ, (void *)&value, sizeof(struct nu_adc_touch_data), 0) == -RT_ETIMEOUT) + break; + + bufX[i] = value.u16X; + bufY[i] = value.u16Y; + bufZ0[i] = value.u16Z0; + bufZ1[i] = value.u16Z1; + } + return i; +} + +static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args) +{ + rt_err_t ret = RT_EINVAL ; + nu_adc_t psNuAdc = (nu_adc_t)dev; + + nu_adc_cb_t psAdcCb = (nu_adc_cb_t)args; + + switch (cmd) + { + case START_MST: /* Menu Start Conversion */ + { + /* Enable interrupt */ + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_MIEN); + + /* Start conversion */ + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_MST); + + /* Wait it done */ + ret = rt_sem_take(psNuAdc->m_psSem, RT_WAITING_FOREVER); + RT_ASSERT(ret == RT_EOK); + + /* Get data: valid data is 12-bit */ + if (args != RT_NULL) + *((uint32_t *)args) = inpw(REG_ADC_DATA) & 0x00000FFF; + } + break; + + /* case START_MST_POLLING: Not supported. */ + + case VBPOWER_ON: /* Enable ADC Internal Bandgap Power */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_VBGEN); + } + break; + + case VBPOWER_OFF: /* Disable ADC Internal Bandgap Power */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_VBGEN); + } + break; + + case KPPOWER_ON: /* Enable ADC Keypad Power */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_PWKPEN); + } + break; + + case KPPOWER_OFF: /* Disable ADC Keypad Power */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_PWKPEN); + } + break; + + case PEPOWER_ON: /* Enable Pen Power */ + { + int retry = 100; + uint32_t treg = inpw(REG_ADC_IER); + outpw(REG_ADC_IER, treg & ~(ADC_IER_PEDEIEN | ADC_IER_PEUEIEN)); + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_PEDEEN); + do + { + outpw(REG_ADC_ISR, ADC_ISR_PEDEF | ADC_ISR_PEUEF); + rt_thread_mdelay(1); + if (retry-- == 0) + break; + } + while (inpw(REG_ADC_ISR) & (ADC_ISR_PEDEF | ADC_ISR_PEUEF)); + outpw(REG_ADC_IER, treg); + } + break; + + case PEPOWER_OFF: /* Disable Pen Power */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_PEDEEN); + } + break; + + case KPPRESS_ON: /* Enable Keypad press event */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_KPEF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPEIEN); + } + break; + + case KPPRESS_OFF: /* Disable Keypad press event */ + { + outpw(REG_ADC_IER, inpw(REG_ADC_IER & ~ADC_IER_KPEIEN)); + } + break; + + case KPUP_ON: /* Enable Keypad up event */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_KPUEF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPUEIEN); + } + break; + + case KPUP_OFF: /* Disable Keypad up event */ + { + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_KPUEIEN); + } + break; + + case PEDEF_ON: /* Enable Pen Down Event */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_PEDEF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_PEDEIEN); + } + break; + + case PEDEF_OFF: /* Disable Pen Down Event */ + { + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_PEDEIEN); + } + break; + + case WKP_ON: /* Enable Keypad Press Wake Up */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_wkisr[eAdc_WKPEF], psAdcCb, sizeof(nu_adc_cb)); + } + + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WKPEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_WKPIEN); + outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) | (1 << 26)); + } + break; + + case WKP_OFF: /* Disable Keypad Press Wake Up */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WKPEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_WKPIEN); + outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) & ~(1 << 26)); + } + break; + + case WKT_ON: /* Enable Touch Wake Up */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_wkisr[eAdc_WPEDEF], psAdcCb, sizeof(nu_adc_cb)); + } + + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WKTEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_WKTIEN); + outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) | (1 << 26)); + } + break; + + case WKT_OFF: /* Disable Touch Wake Up */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WKTEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_WKTIEN); + outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) & ~(1 << 26)); + } + break; + + case SWITCH_5WIRE_ON: /* Wire Mode Switch to 5-Wire */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WMSWCH); + } + break; + + case SWITCH_5WIRE_OFF: /* Wire Mode Switch to 4-Wire */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WMSWCH); + } + break; + + case T_ON: /* Enable Touch detection function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_TEN); + } + break; + + case T_OFF: /* Disable Touch detection function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_TEN); + } + break; + + case TAVG_ON: /* Enable Touch Mean average for X and Y function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_DISTMAVEN); + } + break; + + case TAVG_OFF: /* Disable Touch Mean average for X and Y function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_DISTMAVEN); + } + break; + + case Z_ON: /* Enable Press measure function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_ZEN); + } + break; + + case Z_OFF: /* Disable Press measure function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_ZEN); + rt_mq_control(psNuAdc->m_pmqTouchXYZ, RT_IPC_CMD_RESET, RT_NULL); + } + break; + + case TZAVG_ON: /* Enable Pressure Mean average for Z1 and Z2 function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_DISZMAVEN); + } + break; + + case TZAVG_OFF: /* Disable Pressure Mean average for Z1 and Z2 function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_DISZMAVEN); + } + break; + + case NAC_ON: /* Enable Normal AD Conversion */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_NACEN | ADC_CONF_REFSEL_AVDD33); + } + break; + + case NAC_OFF: /* Disable Normal AD Conversion */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_NACEN); + } + break; + + case VBAT_ON: /* Enable Voltage Battery Conversion */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_VBF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_VBATEN); + } + break; + + case VBAT_OFF: /* Disable Voltage Battery */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_VBATEN); + } + break; + + case KPCONV_ON: /* Enable Keypad conversion function */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_KPCF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_KPCEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPEIEN); + } + break; + + case KPCONV_OFF: /* Disable Keypad conversion function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_KPCEN); + } + break; + + case SWITCH_CH: + { + int chn = (int)args; + if (chn >= psNuAdc->chn_num) + { + return -ret; + } + outpw(REG_ADC_CONF, (inpw(REG_ADC_CONF) & ~ADC_CONF_CHSEL_Msk) | (chn << ADC_CONF_CHSEL_Pos)); + } + break; + + default: + return -(ret); + } + + return RT_EOK; +} + +void nu_adc_touch_start_conv(void) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + _nu_adc_control((rt_device_t)psNuAdc, START_MST, RT_NULL); +} + +rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + nu_adc_cb sNuAdcCb; + + rt_adc_enable((rt_adc_device_t)psNuAdc, 4); + rt_adc_enable((rt_adc_device_t)psNuAdc, 5); + rt_adc_enable((rt_adc_device_t)psNuAdc, 6); + rt_adc_enable((rt_adc_device_t)psNuAdc, 7); + + outpw(REG_ADC_CONF, (inpw(REG_ADC_CONF) & ~(0xfful << 24)) | 0xfful << 24); + + /* Register touch device. */ + psNuAdc->psRtTouch = psRtTouch; + + /* Enable TouchXY. */ + _nu_adc_control((rt_device_t)psNuAdc, T_ON, RT_NULL); + + /* Enable TouchZZ. */ + _nu_adc_control((rt_device_t)psNuAdc, Z_ON, RT_NULL); + + /* Register PenDown callback. */ + sNuAdcCb.cbfunc = PenDownCallback; + sNuAdcCb.private_data = (rt_uint32_t)psRtTouch; + _nu_adc_control((rt_device_t)psNuAdc, PEDEF_ON, (void *)&sNuAdcCb); + + nu_adc_touch_detect(RT_TRUE); + + return RT_EOK; +} + +rt_err_t nu_adc_touch_disable(void) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + + nu_adc_touch_detect(RT_FALSE); + + _nu_adc_control((rt_device_t)psNuAdc, T_OFF, RT_NULL); + _nu_adc_control((rt_device_t)psNuAdc, Z_OFF, RT_NULL); + _nu_adc_control((rt_device_t)psNuAdc, PEDEF_OFF, RT_NULL); + + rt_adc_disable((rt_adc_device_t)psNuAdc, 4); + rt_adc_disable((rt_adc_device_t)psNuAdc, 5); + rt_adc_disable((rt_adc_device_t)psNuAdc, 6); + rt_adc_disable((rt_adc_device_t)psNuAdc, 7); + + return RT_EOK; +} + +static rt_err_t _nu_adc_open(rt_device_t dev, rt_uint16_t oflag) +{ + nu_adc_t psNuAdc = (nu_adc_t)dev; + + /* Enable ADC engine clock */ + nu_sys_ipclk_enable(psNuAdc->clkidx); + + /* Reset the ADC IP */ + nu_sys_ip_reset(psNuAdc->rstidx); + + /* Enable ADC Power */ + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_ADEN); + + /* Enable ADC to high speed mode */ + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_HSPEED); + + /* Enable interrupt */ + rt_hw_interrupt_umask(psNuAdc->irqn); + + /* Enable Normal AD Conversion */ + _nu_adc_control(dev, NAC_ON, RT_NULL); + + return RT_EOK; +} + +static rt_err_t _nu_adc_close(rt_device_t dev) +{ + nu_adc_t psNuAdc = (nu_adc_t)dev; + + /* Disable Normal AD Conversion */ + _nu_adc_control(dev, NAC_OFF, RT_NULL); + + /* Disable interrupt */ + rt_hw_interrupt_mask(psNuAdc->irqn); + + /* Disable ADC Power */ + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_ADEN); + + /* Disable ADC engine clock */ + nu_sys_ipclk_disable(psNuAdc->clkidx); + + return RT_EOK; +} + +static const struct rt_adc_ops nu_adc_ops = +{ + nu_adc_enabled, + nu_adc_convert, +}; + +/* nu_adc_enabled - Enable ADC clock and wait for ready */ +static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) +{ + nu_adc_t psNuADC = (nu_adc_t)device; + RT_ASSERT(device != RT_NULL); + + if (channel >= psNuADC->chn_num) + return -(RT_EINVAL); + + if (enabled) + { + psNuADC->chn_mask |= (1 << channel); + } + else + { + psNuADC->chn_mask &= ~(1 << channel); + } + + if (psNuADC->chn_mask > 0 && ((rt_device_t)device)->ref_count == 0) + { + _nu_adc_open((rt_device_t)device, 0); + ((rt_device_t)device)->ref_count = 1; + } + else if ((psNuADC->chn_mask == 0) && ((rt_device_t)device)->ref_count == 1) + { + _nu_adc_close((rt_device_t)device); + ((rt_device_t)device)->ref_count = 0; + } + return RT_EOK; +} + +static rt_err_t nu_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) +{ + rt_err_t ret = RT_EOK; + nu_adc_t psNuAdc = (nu_adc_t)device; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(value != RT_NULL); + + if (channel >= psNuAdc->chn_num) + { + ret = RT_EINVAL; + goto exit_nu_adc_convert; + } + else if ((ret = _nu_adc_control((rt_device_t)device, SWITCH_CH, (void *)channel)) != RT_EOK) + { + goto exit_nu_adc_convert; + } + else if ((ret = _nu_adc_control((rt_device_t)device, START_MST, (void *)value)) != RT_EOK) + { + goto exit_nu_adc_convert; + } + +exit_nu_adc_convert: + + return (-ret) ; +} + +static void nu_adc_touch_smpl(void *p) +{ + /* Enable interrupt */ + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_MIEN); + + /* Start conversion */ + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_MST); +} + + +int rt_hw_adc_init(void) +{ + rt_err_t result = RT_ERROR; + rt_device_t psDev = &g_sNuADC.dev.parent; + + result = rt_hw_adc_register(&g_sNuADC.dev, g_sNuADC.name, &nu_adc_ops, &g_sNuADC); + RT_ASSERT(result == RT_EOK); + + result = _nu_adc_init(psDev); + RT_ASSERT(result == RT_EOK); + + g_sNuADC.m_psSem = rt_sem_create("adc_mst_sem", 0, RT_IPC_FLAG_FIFO); + RT_ASSERT(g_sNuADC.m_psSem != RT_NULL); + + g_sNuADC.m_pmqTouchXYZ = rt_mq_create("ADC_TOUCH_XYZ", sizeof(struct nu_adc_touch_data), TOUCH_MQ_LENGTH, RT_IPC_FLAG_FIFO); + RT_ASSERT(g_sNuADC.m_pmqTouchXYZ != RT_NULL); + + g_sNuADC.psRtTouchMenuTimer = rt_timer_create("TOUCH_SMPL_TIMER", nu_adc_touch_smpl, (void *)&g_sNuADC, DEF_ADC_TOUCH_SMPL_TICK, RT_TIMER_FLAG_PERIODIC); + RT_ASSERT(g_sNuADC.psRtTouchMenuTimer != RT_NULL); + + rt_memset(&g_sNuADC.m_isr, 0, sizeof(g_sNuADC.m_isr)); + rt_memset(&g_sNuADC.m_wkisr, 0, sizeof(g_sNuADC.m_wkisr)); + + g_sNuADC.m_isr[eAdc_MF].cbfunc = AdcMenuStartCallback; + g_sNuADC.m_isr[eAdc_MF].private_data = (UINT32)&g_sNuADC; + + return (int)result; +} +INIT_BOARD_EXPORT(rt_hw_adc_init); + +#endif //#if defined(BSP_USING_ADC) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h new file mode 100644 index 0000000000..2269f1f35c --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h @@ -0,0 +1,64 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-4-7 Wayne First version +* +******************************************************************************/ + +#ifndef __DRV_ADC_H__ +#define __DRV_ADC_H__ + +#include +#include "nu_adc.h" +#include "touch.h" + +#define TOUCH_MQ_LENGTH 128 + +typedef enum +{ + eAdc_MF, //0 + eAdc_KPEF, //1 + eAdc_PEDEF, //2 + eAdc_KPUEF, //3 + eAdc_PEUEF, //4 + eAdc_TF = 8, //8 + eAdc_ZF, //9 + eAdc_NACF, //10 + eAdc_VBF, //11 + eAdc_KPCF, //12 + eAdc_SELFTF, //13 + eAdc_INTKP = 16, //16 + eAdc_INTTC, //17 + eAdc_ISR_CNT //18 +} E_ADC_ISR_EVENT; + +typedef enum +{ + eAdc_WKPEF, + eAdc_WPEDEF, + eAdc_WKISR_CNT +} E_ADC_WKISR_EVENT; + +typedef struct +{ + ADC_CALLBACK cbfunc; + uint32_t private_data; +} nu_adc_cb; + +typedef nu_adc_cb *nu_adc_cb_t; + +int32_t nu_adc_read_touch_xyz(uint16_t *bufX, uint16_t *bufY, uint16_t *bufZ0, uint16_t *bufZ1, int32_t dataCnt); +rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch); +rt_err_t nu_adc_touch_disable(void); +void nu_adc_touch_detect(rt_bool_t bStartDetect); +void nu_adc_touch_start_conv(void); + +void nu_adc_touch_update_caldata(int *psi32NewValue); +void nu_adc_touch_reset_caldata(int *psi32NewValue); + +#endif /* __DRV_ADC_H__ */ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c new file mode 100644 index 0000000000..cefdb168ab --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c @@ -0,0 +1,274 @@ +/**************************************************************************//** +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-04-20 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_ADC_TOUCH) + +#include "NuMicro.h" +#include +#include "drv_adc.h" +#include "touch.h" + +typedef struct +{ + struct rt_touch_device dev; + rt_uint32_t x_range; + rt_uint32_t y_range; +} nu_adc_touch; +typedef nu_adc_touch *nu_adc_touch_t; + +static nu_adc_touch s_NuAdcTouch = {0}; + +#define DEF_CALDATA_LENGTH 7 +static int cal_data_a[DEF_CALDATA_LENGTH] = { 13230, -66, -1161952, -85, 8600, -1636996, 65536 }; +static const int cal_zero[DEF_CALDATA_LENGTH] = { 1, 0, 0, 0, 1, 0, 1 }; + +static void nu_adc_touch_cal(int *sumx, int *sumy) +{ + int xtemp, ytemp; + + xtemp = *sumx; + ytemp = *sumy; + *sumx = (cal_data_a[2] + + cal_data_a[0] * xtemp + + cal_data_a[1] * ytemp) / cal_data_a[6]; + *sumy = (cal_data_a[5] + + cal_data_a[3] * xtemp + + cal_data_a[4] * ytemp) / cal_data_a[6]; +} + +static rt_size_t nu_adc_touch_readpoint(struct rt_touch_device *device, void *buf, rt_size_t read_num) +{ + static int last_report_x = 0, last_report_y = 0; + struct rt_touch_data *pPoint = (struct rt_touch_data *)buf; + nu_adc_touch_t psNuAdcTouch = (nu_adc_touch_t)device; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(buf != RT_NULL); + + int i; + + for (i = 0; i < read_num; i++) + { + int bufZ0 = 0, bufZ1 = 0; + int sumx = 0, sumy = 0; + pPoint[i].timestamp = rt_touch_get_ts(); + pPoint[i].track_id = 0; + + if (nu_adc_read_touch_xyz((uint16_t *)&sumx, (uint16_t *)&sumy, (uint16_t *)&bufZ0, (uint16_t *)&bufZ1, 1) != 1) + break; + + if (bufZ0 == 0) + { + /* Workaround: In this case, x, y values are unstable. so, report last point's coordinate.*/ + pPoint[i].event = RT_TOUCH_EVENT_UP; + pPoint[i].x_coordinate = last_report_x; + pPoint[i].y_coordinate = last_report_y; + } + else + { + nu_adc_touch_cal(&sumx, &sumy); + pPoint[i].event = RT_TOUCH_EVENT_DOWN; + pPoint[i].x_coordinate = sumx; + pPoint[i].y_coordinate = sumy; + last_report_x = sumx; + last_report_y = sumy; + } + + bufZ0 = bufZ0 >> 3; + + pPoint[i].width = (bufZ0 > 255) ? 255 : bufZ0; + + //Limit max x, y coordinate if value is over its range. + pPoint[i].x_coordinate = (pPoint[i].x_coordinate > psNuAdcTouch->x_range) ? psNuAdcTouch->x_range : pPoint[i].x_coordinate; + pPoint[i].y_coordinate = (pPoint[i].y_coordinate > psNuAdcTouch->y_range) ? psNuAdcTouch->y_range : pPoint[i].y_coordinate; + } + return (rt_size_t)i; +} + +static rt_err_t nu_adc_touch_control(struct rt_touch_device *device, int cmd, void *data) +{ + nu_adc_touch_t psNuAdcTouch = (nu_adc_touch_t)device; + RT_ASSERT(psNuAdcTouch != RT_NULL); + + switch (cmd) + { + case RT_TOUCH_CTRL_SET_X_RANGE: /* set x range */ + psNuAdcTouch->x_range = *((rt_int32_t *)data); + break; + + case RT_TOUCH_CTRL_SET_Y_RANGE: /* set y range */ + psNuAdcTouch->y_range = *((rt_int32_t *)data); + break; + + case RT_TOUCH_CTRL_ENABLE_INT: /* enable pen_down interrupt */ + nu_adc_touch_detect(RT_TRUE); + break; + + case RT_TOUCH_CTRL_DISABLE_INT: /* disable pen_down interrupt */ + nu_adc_touch_detect(RT_FALSE); + break; + + case RT_TOUCH_CTRL_POWER_ON: /* Touch Power On */ + return nu_adc_touch_enable(device); + + case RT_TOUCH_CTRL_POWER_OFF: /* Touch Power Off */ + return nu_adc_touch_disable(); + + default: + return -RT_ERROR; + } + return RT_EOK; +} + +static struct rt_touch_ops touch_ops = +{ + .touch_readpoint = nu_adc_touch_readpoint, + .touch_control = nu_adc_touch_control, +}; + +void nu_adc_touch_update_caldata(int *psi32NewValue) +{ + rt_memcpy(&cal_data_a[0], &psi32NewValue[0], sizeof(cal_data_a)); +} + +void nu_adc_touch_reset_caldata(int *psi32NewValue) +{ + rt_memcpy(&cal_data_a[0], &cal_zero[0], sizeof(cal_data_a)); +} + +int rt_hw_adc_touch_init(void) +{ + /* Register touch device */ + s_NuAdcTouch.dev.info.type = RT_TOUCH_TYPE_RESISTANCE; + s_NuAdcTouch.dev.info.vendor = RT_TOUCH_VENDOR_UNKNOWN; + s_NuAdcTouch.dev.info.point_num = 1; + s_NuAdcTouch.dev.info.range_x = 800; + s_NuAdcTouch.dev.info.range_x = 480; + + s_NuAdcTouch.dev.ops = &touch_ops; + + return (int)rt_hw_touch_register(&s_NuAdcTouch.dev, "adc_touch", RT_DEVICE_FLAG_INT_RX, RT_NULL); +} +INIT_DEVICE_EXPORT(rt_hw_adc_touch_init); + + +static rt_thread_t adc_touch_thread = RT_NULL; +static rt_sem_t adc_touch_sem = RT_NULL; +static int adc_touch_worker_run = 0; +static rt_err_t adc_touch_rx_callback(rt_device_t dev, rt_size_t size) +{ + rt_sem_release(adc_touch_sem); + return 0; +} + +static void adc_touch_entry(void *parameter) +{ + struct rt_touch_data touch_point; + + rt_err_t result; + rt_device_t pdev = &s_NuAdcTouch.dev.parent; + + int max_range; + + adc_touch_sem = rt_sem_create("adc_touch_sem", 0, RT_IPC_FLAG_FIFO); + RT_ASSERT(adc_touch_sem != RT_NULL); + + result = rt_device_open(pdev, RT_DEVICE_FLAG_INT_RX); + RT_ASSERT(result == RT_EOK); + + result = rt_device_set_rx_indicate(pdev, adc_touch_rx_callback); + RT_ASSERT(result == RT_EOK); + + max_range = 800; + result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_X_RANGE, (void *)&max_range); + RT_ASSERT(result == RT_EOK); + + max_range = 480; + result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_Y_RANGE, (void *)&max_range); + RT_ASSERT(result == RT_EOK); + + // nu_adc_touch_reset_caldata(int *psi32NewValue); + // nu_adc_touch_update_caldata(int *psi32NewValue); + + result = rt_device_control(pdev, RT_TOUCH_CTRL_POWER_ON, RT_NULL); + RT_ASSERT(result == RT_EOK); + + while (adc_touch_worker_run) + { + if ((-RT_ETIMEOUT == rt_sem_take(adc_touch_sem, rt_tick_from_millisecond(100)))) + continue; + + rt_memset(&touch_point, 0, sizeof(struct rt_touch_data)); + + if (rt_device_read(pdev, 0, &touch_point, s_NuAdcTouch.dev.info.point_num) == s_NuAdcTouch.dev.info.point_num) + { + if (touch_point.event == RT_TOUCH_EVENT_DOWN + || touch_point.event == RT_TOUCH_EVENT_UP + || touch_point.event == RT_TOUCH_EVENT_MOVE) + { +#if defined(PKG_USING_LITTLEVGL2RTT) + extern void littlevgl2rtt_send_input_event(rt_int16_t x, rt_int16_t y, rt_uint8_t state); + littlevgl2rtt_send_input_event(touch_point.x_coordinate, touch_point.y_coordinate, touch_point.event); +#endif +#if defined(PKG_USING_NUEMWIN) + extern void nuemwin_send_input_event(rt_int16_t x, rt_int16_t y, rt_uint8_t state); + nuemwin_send_input_event(touch_point.x_coordinate, touch_point.y_coordinate, touch_point.event); +#endif + rt_kprintf("[%d-%d] id=%d width=%d x=%d y=%d\n", + touch_point.timestamp, + touch_point.event, + touch_point.track_id, + touch_point.width, + touch_point.x_coordinate, + touch_point.y_coordinate); + } + } + } + + result = rt_device_control(pdev, RT_TOUCH_CTRL_POWER_OFF, RT_NULL); + RT_ASSERT(result == RT_EOK); + + result = rt_device_close(pdev); + RT_ASSERT(result == RT_EOK); +} + + +/* Support "nu_touch_start" command line in msh mode */ +static rt_err_t nu_touch_start(int argc, char **argv) +{ + if (adc_touch_thread == RT_NULL) + { + adc_touch_thread = rt_thread_create("adc_touch_thread", + adc_touch_entry, + RT_NULL, + 1024, + 25, + 5); + adc_touch_worker_run = 1; + if (adc_touch_thread != RT_NULL) + rt_thread_startup(adc_touch_thread); + } + return 0; +} +MSH_CMD_EXPORT(nu_touch_start, e.g: start adc touch); + +/* Support "nu_touch_stop" command line in msh mode */ +static rt_err_t nu_touch_stop(int argc, char **argv) +{ + adc_touch_worker_run = 0; + adc_touch_thread = RT_NULL; + return 0; +} +MSH_CMD_EXPORT(nu_touch_stop, e.g: stop adc touch); + +#endif //#if defined(BSP_USING_ADC_TOUCH) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c new file mode 100644 index 0000000000..a4da2879cf --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c @@ -0,0 +1,544 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_CAN) + +#include +#include +#include "NuMicro.h" +#include + +/* Private Define ---------------------------------------------------------------*/ +#define RX_MSG_ID_INDEX 16 +#define IS_CAN_STDID(STDID) ((STDID) <= 0x7FFU) +#define IS_CAN_EXTID(EXTID) ((EXTID) <= 0x1FFFFFFFU) +#define IS_CAN_DLC(DLC) ((DLC) <= 8U) + +/* Default config for serial_configure structure */ +#define NU_CAN_CONFIG_DEFAULT \ +{ \ + CAN1MBaud, /* 1M bits/s */ \ + RT_CANMSG_BOX_SZ, /* message box max size */ \ + RT_CANSND_BOX_NUM, /* message box number */ \ + RT_CAN_MODE_NORMAL, /* Normal mode */ \ + 0, /* privmode */ \ + 0, /* reserved */ \ + 100, /* Timeout Tick */ \ +} + +enum +{ + CAN_START = -1, +#if defined(BSP_USING_CAN0) + CAN0_IDX, +#endif +#if defined(BSP_USING_CAN1) + CAN1_IDX, +#endif + CAN_CNT, +}; + +/* Private Typedef --------------------------------------------------------------*/ +struct nu_can +{ + struct rt_can_device dev; + char *name; + CAN_T *base; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; +}; +typedef struct nu_can *nu_can_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg); +static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg); +static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno); +static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno); +static void nu_can_isr(int vector, void *param); + +static struct nu_can nu_can_arr[] = +{ +#if defined(BSP_USING_CAN0) + { + .name = "can0", + .base = CAN0, + .irqn = IRQ_CAN0, + .rstidx = CAN0RST, + .clkidx = CAN0CKEN, + }, +#endif +#if defined(BSP_USING_CAN1) + { + .name = "can1", + .base = CAN1, + .irqn = IRQ_CAN1, + .rstidx = CAN1RST, + .clkidx = CAN1CKEN, + }, +#endif +}; /* struct nu_can */ + +/* Public functions ------------------------------------------------------------*/ + +/* Private variables ------------------------------------------------------------*/ +static const struct rt_can_ops nu_can_ops = +{ + .configure = nu_can_configure, + .control = nu_can_control, + .sendmsg = nu_can_sendmsg, + .recvmsg = nu_can_recvmsg, +}; + +static const struct can_configure nu_can_default_config = NU_CAN_CONFIG_DEFAULT; + +/* Interrupt Handle Function ----------------------------------------------------*/ +static void nu_can_isr(int vector, void *param) +{ + uint32_t u32IIDRstatus; + nu_can_t psNuCAN = (nu_can_t)param; + + /* Get base address of CAN register */ + CAN_T *base = psNuCAN->base; + + /* Get interrupt event */ + u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base); + + if (u32IIDRstatus == 0x00008000) /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + { + /**************************/ + /* Status Change interrupt*/ + /**************************/ + if (base->STATUS & CAN_STATUS_TXOK_Msk) + { + base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ + //rt_kprintf("%s: TX\n", psNuCAN->name) ; +#ifndef RT_CAN_USING_HDR + /* Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); +#endif + } + + if (base->STATUS & CAN_STATUS_RXOK_Msk) + { + base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ + //rt_kprintf("%s: RX\n", psNuCAN->name) ; +#ifndef RT_CAN_USING_HDR + /* Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); +#endif + } + + /**************************/ + /* Error Status interrupt */ + /**************************/ + if (base->STATUS & CAN_STATUS_EWARN_Msk) + { + rt_kprintf("%s: EWARN\n", psNuCAN->name) ; + } + + if (base->STATUS & CAN_STATUS_BOFF_Msk) + { + rt_kprintf("%s: BUSOFF\n", psNuCAN->name) ; + + /* Do Init to release busoff pin */ + base->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); + base->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk)); + while (base->CON & CAN_CON_INIT_Msk); + } + + if (base->STATUS & CAN_STATUS_LEC_Msk) + { + rt_kprintf("[%s] Last Error Code %03x\n", psNuCAN->name, base->STATUS & CAN_STATUS_LEC_Msk) ; + } + + } +#ifdef RT_CAN_USING_HDR + /*IntId: 0x0001-0x0020, Number of Message Object which caused the interrupt.*/ + else if (u32IIDRstatus > 0 && u32IIDRstatus <= 32) + { + /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ + if (u32IIDRstatus <= RX_MSG_ID_INDEX) + { + //rt_kprintf("[%s-Tx]IntId = %d\n", psNuCAN->name, u32IIDRstatus); + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + } + else /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + { + //rt_kprintf("[%s-Rx]IntId = %d\n", psNuCAN->name, u32IIDRstatus); + rt_hw_can_isr(&psNuCAN->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); + } + CAN_CLR_INT_PENDING_BIT(base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ + } +#endif + +} + + +static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg) +{ + nu_can_t psNuCAN = (nu_can_t)can; + + RT_ASSERT(can != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + /* Get base address of CAN register */ + CAN_T *base = psNuCAN->base; + + RT_ASSERT(base != RT_NULL); + + switch (cfg->mode) + { + /* CAN default Normal mode */ + case RT_CAN_MODE_NORMAL: + can->config.mode = CAN_NORMAL_MODE; + break; + case RT_CAN_MODE_LISEN: + can->config.mode = RT_CAN_MODE_LISEN; + break; + case RT_CAN_MODE_LOOPBACK: + can->config.mode = RT_CAN_MODE_LOOPBACK; + break; + case RT_CAN_MODE_LOOPBACKANLISEN: + can->config.mode = RT_CAN_MODE_LOOPBACKANLISEN; + break; + default: + rt_kprintf("Unsupported Operating mode"); + goto exit_nu_can_configure; + } + + nu_sys_ip_reset(psNuCAN->rstidx); + + /*Set the CAN Bit Rate and Operating mode*/ + if (CAN_Open(base, can->config.baud_rate, can->config.mode) < 1) + return -(RT_ERROR); + + + switch (cfg->mode) + { + /* CAN default Normal mode */ + case RT_CAN_MODE_NORMAL: +#ifdef RT_CAN_USING_HDR + CAN_LeaveTestMode(base); +#else + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk); +#endif + break; + case RT_CAN_MODE_LISEN: + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk); + break; + case RT_CAN_MODE_LOOPBACK: + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_LBACK_Msk); + break; + case RT_CAN_MODE_LOOPBACKANLISEN: + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); + break; + default: + rt_kprintf("Unsupported Operating mode"); + goto exit_nu_can_configure; + } + + + return RT_EOK; + +exit_nu_can_configure: + + CAN_Close(base); + + return -(RT_ERROR); +} + +static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) +{ + rt_uint32_t argval; + nu_can_t psNuCAN = (nu_can_t)can; + +#ifdef RT_CAN_USING_HDR + struct rt_can_filter_config *filter_cfg; +#endif + /* Get base address of CAN register */ + CAN_T *base = psNuCAN->base; + + RT_ASSERT(base != RT_NULL); + /* Check baud rate */ + RT_ASSERT(can->config.baud_rate != 0); + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + argval = (rt_uint32_t) arg; + if ((argval == RT_DEVICE_FLAG_INT_RX) || (argval == RT_DEVICE_FLAG_INT_TX)) + { + /* Disable NVIC interrupt. */ + rt_hw_interrupt_mask(psNuCAN->irqn); + + /* Disable Status Change Interrupt */ + CAN_DisableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); + + } + else if (argval == RT_DEVICE_CAN_INT_ERR) + { + /* Disable interrupt. */ + rt_hw_interrupt_mask(psNuCAN->irqn); + + /* Disable Error Interrupt */ + CAN_DisableInt(base, CAN_CON_EIE_Msk); + } + break; + + case RT_DEVICE_CTRL_SET_INT: + argval = (rt_uint32_t) arg; + if (argval == RT_DEVICE_FLAG_INT_RX || (argval == RT_DEVICE_FLAG_INT_TX)) + { + /* Enable Status Change Interrupt */ + CAN_EnableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); + + /* Enable interrupt. */ + rt_hw_interrupt_umask(psNuCAN->irqn); + } + else if (argval == RT_DEVICE_CAN_INT_ERR) + { + /* Enable Error Status and Status Change Interrupt */ + CAN_EnableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); + + /* Enable interrupt. */ + rt_hw_interrupt_umask(psNuCAN->irqn); + } + break; + +#ifdef RT_CAN_USING_HDR + case RT_CAN_CMD_SET_FILTER: + filter_cfg = (struct rt_can_filter_config *)arg; + + for (int i = 0; i < filter_cfg->count; i++) + { + + /*set the filter message object*/ + if (filter_cfg->items[i].mode == 1) + { + if (CAN_SetRxMsgObjAndMsk(base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) + { + return -(RT_ERROR); + } + } + else + { + /*set the filter message object*/ + if (CAN_SetRxMsgAndMsk(base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) + { + return -(RT_ERROR); + } + } + } + break; +#endif + + case RT_CAN_CMD_SET_MODE: + argval = (rt_uint32_t) arg; + if (argval != RT_CAN_MODE_NORMAL && argval != RT_CAN_MODE_LISEN && + argval != RT_CAN_MODE_LOOPBACK && argval != RT_CAN_MODE_LOOPBACKANLISEN) + { + return -(RT_ERROR); + } + if (argval != can->config.mode) + { + can->config.mode = argval; + return nu_can_configure(can, &can->config); + } + break; + + case RT_CAN_CMD_SET_BAUD: + argval = (rt_uint32_t) arg; + if (argval != CAN1MBaud && argval != CAN800kBaud && argval != CAN500kBaud && argval != CAN250kBaud && + argval != CAN125kBaud && argval != CAN100kBaud && argval != CAN50kBaud && argval != CAN20kBaud && argval != CAN10kBaud) + { + return -(RT_ERROR); + } + if (argval != can->config.baud_rate) + { + can->config.baud_rate = argval; + return nu_can_configure(can, &can->config); + } + break; + + case RT_CAN_CMD_SET_PRIV: + argval = (rt_uint32_t) arg; + if (argval != RT_CAN_MODE_PRIV && argval != RT_CAN_MODE_NOPRIV) + { + return -(RT_ERROR); + } + if (argval != can->config.privmode) + { + can->config.privmode = argval; + return nu_can_configure(can, &can->config); + } + break; + + case RT_CAN_CMD_GET_STATUS: + { + rt_uint32_t errtype; + errtype = base->ERR; + /*Receive Error Counter*/ + can->status.rcverrcnt = (errtype >> 8); + /*Transmit Error Counter*/ + can->status.snderrcnt = ((errtype >> 24) & 0xFF); + can->status.lasterrtype = CAN_GET_INT_STATUS(base) & 0x8000; + /*status error code*/ + can->status.errcode = CAN_GET_INT_STATUS(base) & 0x07; + rt_memcpy(arg, &can->status, sizeof(can->status)); + } + break; + + default: + return -(RT_EINVAL); + + } + + return RT_EOK; +} + +static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno) +{ + STR_CANMSG_T tMsg; + struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + + /* Get base address of CAN register */ + CAN_T *base = ((nu_can_t)can)->base; + + RT_ASSERT(base != RT_NULL); + RT_ASSERT(buf != RT_NULL); + + /* Check the parameters */ + RT_ASSERT(IS_CAN_DLC(pmsg->len)); + + /* Standard ID (11 bits)*/ + if (pmsg->ide == RT_CAN_STDID) + { + tMsg.IdType = CAN_STD_ID; + RT_ASSERT(IS_CAN_STDID(pmsg->id)) + tMsg.Id = pmsg->id ; + } + else + { + /* Extended ID (29 bits)*/ + tMsg.IdType = CAN_EXT_ID; + RT_ASSERT(IS_CAN_EXTID(pmsg->id)); + tMsg.Id = pmsg->id ; + } + + if (pmsg->rtr == RT_CAN_DTR) + { + /* Data frame */ + tMsg.FrameType = CAN_DATA_FRAME; + } + else + { + /* Remote frame */ + tMsg.FrameType = CAN_REMOTE_FRAME; + } + tMsg.DLC = pmsg->len; + rt_memcpy(tMsg.Data, pmsg->data, pmsg->len); + + if (CAN_Transmit(base, MSG(boxno), &tMsg) == FALSE) // Configure Msg RAM and send the Msg in the RAM + { + return -(RT_ERROR); + } + + return RT_EOK; +} +static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno) +{ + STR_CANMSG_T tMsg; + struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + /* Get base address of CAN register */ + CAN_T *base = ((nu_can_t)can)->base; + + RT_ASSERT(base != RT_NULL); + RT_ASSERT(buf != RT_NULL); + + /* get data */ + if (CAN_Receive(base, boxno, &tMsg) == FALSE) + { + rt_kprintf("No available RX Msg.\n"); + return -(RT_ERROR); + } + +#ifdef RT_CAN_USING_HDR + /* Hardware filter messages are valid */ + pmsg->hdr = boxno - RX_MSG_ID_INDEX; + can->hdr[pmsg->hdr].connected = 1; +#endif + + /* Standard ID (11 bits)*/ + if (tMsg.IdType == CAN_STD_ID) + { + pmsg->ide = RT_CAN_STDID; + pmsg->id = tMsg.Id; + } + else /* Extended ID (29 bits)*/ + { + pmsg->ide = RT_CAN_EXTID; + pmsg->id = tMsg.Id; + } + + if (tMsg.FrameType == CAN_DATA_FRAME) + { + /* Data frame */ + pmsg->rtr = RT_CAN_DTR; + } + else + { + /* Remote frame */ + pmsg->rtr = RT_CAN_RTR; + } + + pmsg->len = tMsg.DLC ; + + rt_memcpy(pmsg->data, tMsg.Data, pmsg->len); + + return RT_EOK; +} + +/** + * Hardware CAN Initialization + */ +static int rt_hw_can_init(void) +{ + int i; + rt_err_t ret = RT_EOK; + + for (i = (CAN_START + 1); i < CAN_CNT; i++) + { + nu_can_arr[i].dev.config = nu_can_default_config; + +#ifdef RT_CAN_USING_HDR + nu_can_arr[i].dev.config.maxhdr = RT_CANMSG_BOX_SZ; +#endif + + /* Register CAN ISR */ + rt_hw_interrupt_install(nu_can_arr[i].irqn, nu_can_isr, &nu_can_arr[i], nu_can_arr[i].name); + + /* Enable IP engine clock */ + nu_sys_ipclk_enable(nu_can_arr[i].clkidx); + + /* Register can device */ + ret = rt_hw_can_register(&nu_can_arr[i].dev, nu_can_arr[i].name, &nu_can_ops, NULL); + RT_ASSERT(ret == RT_EOK); + } + + return (int)ret; +} +INIT_DEVICE_EXPORT(rt_hw_can_init); + +#endif //#if defined(BSP_USING_CAN) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.c new file mode 100644 index 0000000000..b96c9b7b04 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.c @@ -0,0 +1,78 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-11-11 Wayne First version +* +******************************************************************************/ + +#include +#include +#include "board.h" +#include "drv_uart.h" +#include "drv_sys.h" + +#if defined(BSP_USING_MMU) +static struct mem_desc hw_mem_desc[] = +{ + { 0x00000000, 0xFFFFFFFF, 0x00000000, RW_NCNB }, /* None cached for 4G memory */ + { 0x00000000, BOARD_SDRAM_SIZE - 1, 0x00000000, RW_CB }, /* 64M cached DDR memory */ + { BIT31, (BIT31 | BOARD_SDRAM_SIZE) - 1, BIT31, RW_NCNB }, /* Shadow DDR Map */ + { 0x3C000000, 0x3C00E000 - 1, 0x3C000000, RW_NCNB }, /* 56K SRAM memory */ + { 0xBC000000, 0xBC00E000 - 1, 0xBC000000, RW_NCNB } /* 56K Shadow memory */ +}; +#endif + +/** + * This function will initial M487 board. + */ +RT_WEAK void rt_hw_board_init(void) +{ + /* initialize base clock */ + nu_clock_base_init(); + + /* initialize peripheral pin function */ + nu_pin_init(); + +#if defined(BSP_USING_MMU) + /* initialize mmu */ + rt_hw_mmu_init(&hw_mem_desc[0], sizeof(hw_mem_desc) / sizeof(hw_mem_desc[0])); +#else + /* disable I/D cache */ + mmu_disable_dcache(); + mmu_disable_icache(); + mmu_disable(); + mmu_invalidate_tlb(); +#endif + + /* initialize hardware interrupt */ + rt_hw_interrupt_init(); + + /* initialize systick */ + rt_hw_systick_init(); + +#ifdef RT_USING_HEAP + /* init memory system */ + rt_system_heap_init((void *)BOARD_HEAP_START, (void *)BOARD_HEAP_END); +#endif + + /* initialize uart */ + rt_hw_uart_init(); + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_HEAP + /* Dump heap information */ + rt_kprintf("Heap: Begin@%08x, END@%08x, SIZE:%d\n", BOARD_HEAP_START, BOARD_HEAP_END, (rt_uint32_t)BOARD_HEAP_END - (rt_uint32_t)BOARD_HEAP_START); +#endif +} diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.h b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.h new file mode 100644 index 0000000000..f971f871c1 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.h @@ -0,0 +1,20 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#ifndef __DRV_COMMON_H__ +#define __DRV_COMMON_H__ + +#include + +void nu_clock_base_dump(void); + +#endif /* __DRV_UART_H__ */ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_crypto.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_crypto.c new file mode 100644 index 0000000000..83f62e49cc --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_crypto.c @@ -0,0 +1,996 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-4-22 Wayne First version +* +******************************************************************************/ + +#include + +#if (defined(BSP_USING_CRYPTO) && defined(RT_USING_HWCRYPTO)) + +#include +#include +#include +#include "NuMicro.h" +#include "drv_sys.h" +#include + +/* Private typedef --------------------------------------------------------------*/ +#define CACHE_LINE_SIZE 32 + +typedef struct +{ + uint8_t *pu8SHATempBuf; + uint32_t u32SHATempBufLen; + uint32_t u32DMAMode; + uint32_t u32BlockSize; +} S_SHA_CONTEXT; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx); +static void nu_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx); +static rt_err_t nu_hwcrypto_clone(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src); +static void nu_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx); + +/* Private variables ------------------------------------------------------------*/ +static const struct rt_hwcrypto_ops nu_hwcrypto_ops = +{ + .create = nu_hwcrypto_create, + .destroy = nu_hwcrypto_destroy, + .copy = nu_hwcrypto_clone, + .reset = nu_hwcrypto_reset, +}; + +/* Crypto engine operation ------------------------------------------------------------*/ + +#define NU_HWCRYPTO_DES_3KEYS 1 +#define NU_HWCRYPTO_DES_NO3KEYS 0 +#define NU_HWCRYPTO_AES_NAME "nu_AES" +#define NU_HWCRYPTO_TDES_NAME "nu_TDES" +#define NU_HWCRYPTO_SHA_NAME "nu_SHA" +#define NU_HWCRYPTO_PRNG_NAME "nu_PRNG" + +static struct rt_mutex s_AES_mutex; +static struct rt_mutex s_TDES_mutex; +static struct rt_mutex s_SHA_mutex; + +static struct rt_mutex s_PRNG_mutex; + +//Crypto engine IRQ handler +static void nu_crypto_isr(int vector, void *param) +{ + if (TDES_GET_INT_FLAG()) + { + TDES_CLR_INT_FLAG(); + } +} + +static rt_err_t nu_aes_crypt_run( + rt_bool_t bEncrypt, + uint32_t u32OpMode, + uint8_t *pu8Key, + uint32_t u32KeySize, + uint8_t *pu8IV, + uint8_t *pu8InData, + uint8_t *pu8OutData, + uint32_t u32DataLen +) +{ + uint32_t au32SwapKey[8]; + uint32_t au32SwapIV[4]; + rt_err_t result; + + au32SwapKey[0] = nu_get32_be(&pu8Key[0]); + au32SwapKey[1] = nu_get32_be(&pu8Key[4]); + au32SwapKey[2] = nu_get32_be(&pu8Key[8]); + au32SwapKey[3] = nu_get32_be(&pu8Key[12]); + + if ((u32KeySize == AES_KEY_SIZE_192) || (u32KeySize == AES_KEY_SIZE_256)) + { + au32SwapKey[4] = nu_get32_be(&pu8Key[16]); + au32SwapKey[5] = nu_get32_be(&pu8Key[20]); + } + + if (u32KeySize == AES_KEY_SIZE_256) + { + au32SwapKey[6] = nu_get32_be(&pu8Key[24]); + au32SwapKey[7] = nu_get32_be(&pu8Key[28]); + } + + au32SwapIV[0] = nu_get32_be(&pu8IV[0]); + au32SwapIV[1] = nu_get32_be(&pu8IV[4]); + au32SwapIV[2] = nu_get32_be(&pu8IV[8]); + au32SwapIV[3] = nu_get32_be(&pu8IV[12]); + + result = rt_mutex_take(&s_AES_mutex, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + //Using Channel 0 + AES_Open(0, bEncrypt, u32OpMode, u32KeySize, AES_IN_OUT_SWAP); + AES_SetKey(0, (uint32_t *)au32SwapKey, u32KeySize); + AES_SetInitVect(0, (uint32_t *)au32SwapIV); + + //Setup AES DMA + AES_SetDMATransfer(0, (uint32_t)pu8InData, (uint32_t)pu8OutData, u32DataLen); +#if defined(BSP_USING_MMU) + /* Writeback data in dcache to memory before transferring. */ + { + /* Flush Src buffer into memory. */ + if (pu8InData) + mmu_clean_invalidated_dcache((uint32_t)pu8InData, u32DataLen); + + /* Flush Dst buffer into memory. */ + if (pu8OutData) + mmu_clean_invalidated_dcache((uint32_t)pu8OutData, u32DataLen); + } +#endif + + /* Clear AES interrupt status */ + AES_CLR_INT_FLAG(); + + /* Start AES encryption/decryption */ + AES_Start(0, CRYPTO_DMA_ONE_SHOT); + + /* Wait done */ + while (!(CRPT->INTSTS & CRPT_INTEN_AESIEN_Msk)) {}; + + if ((u32DataLen % 16) && (CRPT->AES_STS & (CRPT_AES_STS_OUTBUFEMPTY_Msk | CRPT_AES_STS_INBUFEMPTY_Msk))) + rt_kprintf("AES WARNING - AES Data length(%d) is not enough. -> %d \n", u32DataLen, RT_ALIGN(u32DataLen, 16)); + else if (CRPT->INTSTS & (CRPT_INTSTS_AESERRIF_Msk) || (CRPT->AES_STS & (CRPT_AES_STS_BUSERR_Msk | CRPT_AES_STS_CNTERR_Msk))) + rt_kprintf("AES ERROR - CRPT->INTSTS-%08x, CRPT->AES_STS-%08x\n", CRPT->INTSTS, CRPT->AES_STS); + + /* Clear AES interrupt status */ + AES_CLR_INT_FLAG(); + + result = rt_mutex_release(&s_AES_mutex); + RT_ASSERT(result == RT_EOK); + + return RT_EOK; +} + +static void nu_prng_open(uint32_t u32Seed) +{ + rt_err_t result; + + result = rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + //Open PRNG 64 bits. But always return 32 bits + PRNG_Open(PRNG_KEY_SIZE_64, PRNG_SEED_RELOAD, u32Seed); + + result = rt_mutex_release(&s_PRNG_mutex); + RT_ASSERT(result == RT_EOK); +} + +static rt_uint32_t nu_prng_run(void) +{ + uint32_t au32RNGValue[2]; + rt_err_t result; + static uint32_t s_u32PRNG_Counter = 0; + result = rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + +#if !defined(NU_PRNG_USE_SEED) + nu_prng_open(rt_tick_get() + s_u32PRNG_Counter++); +#endif + + PRNG_Start(); + while ((CRPT->PRNG_CTL & CRPT_PRNG_CTL_BUSY_Msk)) {}; + + /* Clear PRNG interrupt status */ + PRNG_CLR_INT_FLAG(); + + PRNG_Read(&au32RNGValue[0]); + + result = rt_mutex_release(&s_PRNG_mutex); + RT_ASSERT(result == RT_EOK); + + return au32RNGValue[0]; +} + +static rt_err_t nu_aes_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hwcrypto_symmetric_info *symmetric_info) +{ + uint32_t u32AESOpMode; + uint32_t u32AESKeySize; + unsigned char *in, *out; + unsigned char in_align_flag = 0; + unsigned char out_align_flag = 0; + unsigned char iv_temp[16]; + RT_ASSERT(symmetric_ctx != RT_NULL); + RT_ASSERT(symmetric_info != RT_NULL); + + if ((symmetric_info->length % 4) != 0) + { + return -RT_EINVAL; + } + + //Checking key length + if (symmetric_ctx->key_bitlen == 128) + { + u32AESKeySize = AES_KEY_SIZE_128; + } + else if (symmetric_ctx->key_bitlen == 192) + { + u32AESKeySize = AES_KEY_SIZE_192; + } + else if (symmetric_ctx->key_bitlen == 256) + { + u32AESKeySize = AES_KEY_SIZE_256; + } + else + { + return -RT_EINVAL; + } + + //Select AES operation mode + switch (symmetric_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK)) + { + case HWCRYPTO_TYPE_AES_ECB: + u32AESOpMode = AES_MODE_ECB; + break; + case HWCRYPTO_TYPE_AES_CBC: + u32AESOpMode = AES_MODE_CBC; + break; + case HWCRYPTO_TYPE_AES_CFB: + u32AESOpMode = AES_MODE_CFB; + break; + case HWCRYPTO_TYPE_AES_OFB: + u32AESOpMode = AES_MODE_OFB; + break; + case HWCRYPTO_TYPE_AES_CTR: + u32AESOpMode = AES_MODE_CTR; + break; + default : + return -RT_ERROR; + } + + in = (unsigned char *)symmetric_info->in; + out = (unsigned char *)symmetric_info->out; + + //Checking in/out data buffer address not alignment + if (((rt_uint32_t)in % CACHE_LINE_SIZE) != 0) + { + in = rt_malloc_align(symmetric_info->length, CACHE_LINE_SIZE); + if (in == RT_NULL) + { + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, symmetric_info->length); + return -RT_ENOMEM; + } + + rt_memcpy(in, symmetric_info->in, symmetric_info->length); + in_align_flag = 1; + } + + if (((rt_uint32_t)out % CACHE_LINE_SIZE) != 0) + { + out = rt_malloc_align(symmetric_info->length, CACHE_LINE_SIZE); + if (out == RT_NULL) + { + if (in_align_flag) + rt_free_align(in); + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, symmetric_info->length); + return -RT_ENOMEM; + } + + out_align_flag = 1; + } + + if ((u32AESOpMode == AES_MODE_CBC) && (symmetric_info->mode == HWCRYPTO_MODE_DECRYPT)) + { + uint32_t loop; + + loop = (symmetric_info->length - 1) / 16; + rt_memcpy(iv_temp, in + (loop * 16), 16); + } + + nu_aes_crypt_run(symmetric_info->mode == HWCRYPTO_MODE_ENCRYPT ? TRUE : FALSE, u32AESOpMode, symmetric_ctx->key, u32AESKeySize, symmetric_ctx->iv, in, out, symmetric_info->length); + + if (u32AESOpMode == AES_MODE_CBC) + { + if (symmetric_info->mode == HWCRYPTO_MODE_DECRYPT) + { + rt_memcpy(symmetric_ctx->iv, iv_temp, 16); + } + else + { + uint32_t loop; + + loop = (symmetric_info->length - 1) / 16; + rt_memcpy(symmetric_ctx->iv, out + (loop * 16), 16); + } + } + + if (out_align_flag) + { + rt_memcpy(symmetric_info->out, out, symmetric_info->length); + rt_free_align(out); + } + + if (in_align_flag) + { + rt_free_align(in); + } + + return RT_EOK; +} + +static rt_err_t nu_des_crypt_run( + rt_bool_t bEncrypt, + uint32_t u32OpMode, + uint8_t *pu8Key, + uint32_t u32KeySize, + uint8_t *pu8IV, + uint8_t *pu8InData, + uint8_t *pu8OutData, + uint32_t u32DataLen +) +{ + rt_err_t result; + + uint32_t au32SwapKey[3][2]; + uint32_t au32SwapIV[2]; + + au32SwapKey[0][0] = nu_get32_be(&pu8Key[0]); + au32SwapKey[0][1] = nu_get32_be(&pu8Key[4]); + au32SwapKey[1][0] = nu_get32_be(&pu8Key[8]); + au32SwapKey[1][1] = nu_get32_be(&pu8Key[12]); + + if (u32KeySize == NU_HWCRYPTO_DES_3KEYS) + { + au32SwapKey[2][0] = nu_get32_be(&pu8Key[16]); + au32SwapKey[2][1] = nu_get32_be(&pu8Key[20]); + } + + au32SwapIV[0] = nu_get32_be(&pu8IV[0]); + au32SwapIV[1] = nu_get32_be(&pu8IV[4]); + + result = rt_mutex_take(&s_TDES_mutex, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + //Using Channel 0 + TDES_Open(0, bEncrypt, (u32OpMode & CRPT_TDES_CTL_TMODE_Msk), u32KeySize, u32OpMode, TDES_IN_OUT_WHL_SWAP); + TDES_SetKey(0, au32SwapKey); + TDES_SetInitVect(0, au32SwapIV[0], au32SwapIV[1]); + + //Setup TDES DMA + TDES_SetDMATransfer(0, (uint32_t)pu8InData, (uint32_t)pu8OutData, u32DataLen); + +#if defined(BSP_USING_MMU) + /* Writeback data in dcache to memory before transferring. */ + { + /* Flush Src buffer into memory. */ + if (pu8InData) + mmu_clean_invalidated_dcache((uint32_t)pu8InData, u32DataLen); + + /* Flush Dst buffer into memory. */ + if (pu8OutData) + mmu_clean_invalidated_dcache((uint32_t)pu8OutData, u32DataLen); + } +#endif + + TDES_CLR_INT_FLAG(); + + //Start TDES encryption/decryption + TDES_Start(0, CRYPTO_DMA_ONE_SHOT); + + /* Wait done */ + while (!(CRPT->INTSTS & CRPT_INTEN_TDESIEN_Msk)) {}; + + if ((u32DataLen % 16) && (CRPT->TDES_STS & (CRPT_TDES_STS_OUTBUFEMPTY_Msk | CRPT_TDES_STS_INBUFEMPTY_Msk))) + rt_kprintf("TDES WARNING - TDES Data length(%d) is not enough. -> %d \n", u32DataLen, RT_ALIGN(u32DataLen, 16)); + else if (CRPT->INTSTS & (CRPT_INTSTS_TDESERRIF_Msk) || (CRPT->TDES_STS & (CRPT_TDES_STS_BUSERR_Msk))) + rt_kprintf("AES ERROR - CRPT->INTSTS-%08x, CRPT->AES_STS-%08x\n", CRPT->INTSTS, CRPT->AES_STS); + + /* Clear TDES interrupt status */ + TDES_CLR_INT_FLAG(); + + result = rt_mutex_release(&s_TDES_mutex); + RT_ASSERT(result == RT_EOK); + + return RT_EOK; +} + +static rt_err_t nu_des_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hwcrypto_symmetric_info *symmetric_info) +{ + uint32_t u32DESOpMode; + uint32_t u32DESKeySize; + unsigned char *in, *out; + unsigned char in_align_flag = 0; + unsigned char out_align_flag = 0; + + if ((symmetric_info->length % 8) != 0) + { + return -RT_EINVAL; + } + + //Checking key length + if (symmetric_ctx->key_bitlen == 128 || symmetric_ctx->key_bitlen == 64) + { + u32DESKeySize = NU_HWCRYPTO_DES_NO3KEYS; + } + else if (symmetric_ctx->key_bitlen == 192) + { + u32DESKeySize = NU_HWCRYPTO_DES_3KEYS; + } + else + { + return -RT_EINVAL; + } + + //Select DES operation mode + switch (symmetric_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK)) + { + case HWCRYPTO_TYPE_DES_ECB: + u32DESOpMode = DES_MODE_ECB; + break; + case HWCRYPTO_TYPE_DES_CBC: + u32DESOpMode = DES_MODE_CBC; + break; + case HWCRYPTO_TYPE_3DES_ECB: + u32DESOpMode = TDES_MODE_ECB; + break; + case HWCRYPTO_TYPE_3DES_CBC: + u32DESOpMode = TDES_MODE_CBC; + break; + default : + return -RT_ERROR; + } + + in = (unsigned char *)symmetric_info->in; + out = (unsigned char *)symmetric_info->out; + + //Checking in/out data buffer address not alignment or out of SRAM + if (((rt_uint32_t)in % CACHE_LINE_SIZE) != 0) + { + in = rt_malloc_align(symmetric_info->length, CACHE_LINE_SIZE); + if (in == RT_NULL) + { + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, symmetric_info->length); + return -RT_ENOMEM; + } + + rt_memcpy(in, symmetric_info->in, symmetric_info->length); + in_align_flag = 1; + } + + if (((rt_uint32_t)out % CACHE_LINE_SIZE) != 0) + { + out = rt_malloc_align(symmetric_info->length, CACHE_LINE_SIZE); + if (out == RT_NULL) + { + if (in_align_flag) + rt_free_align(in); + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, symmetric_info->length); + return -RT_ENOMEM; + } + + out_align_flag = 1; + } + + nu_des_crypt_run(symmetric_info->mode == HWCRYPTO_MODE_ENCRYPT ? TRUE : FALSE, u32DESOpMode, symmetric_ctx->key, u32DESKeySize, symmetric_ctx->iv, in, out, symmetric_info->length); + + if (out_align_flag) + { + rt_memcpy(symmetric_info->out, out, symmetric_info->length); + rt_free_align(out); + } + + if (in_align_flag) + { + rt_free_align(in); + } + + return RT_EOK; +} + +static void SHABlockUpdate(uint32_t u32OpMode, uint32_t u32SrcAddr, uint32_t u32Len, uint32_t u32Mode) +{ + SHA_Open(u32OpMode, SHA_IN_OUT_SWAP, 0); + + //Setup SHA DMA + SHA_SetDMATransfer(u32SrcAddr, u32Len); + + if (u32Mode == CRYPTO_DMA_FIRST) + { + u32Mode = CRYPTO_DMA_CONTINUE; + } + +#if defined(BSP_USING_MMU) + /* Writeback data in dcache to memory before transferring. */ + { + /* Flush Src buffer into memory. */ + if (u32SrcAddr) + mmu_clean_invalidated_dcache(u32SrcAddr, u32Len); + } +#endif + + //Start SHA + SHA_CLR_INT_FLAG(); + + SHA_Start(u32Mode); + + /* Wait done */ + while (!(CRPT->INTSTS & CRPT_INTSTS_SHAIF_Msk)) {}; + + if (CRPT->INTSTS & (CRPT_INTSTS_SHAERRIF_Msk) || (CRPT->HMAC_STS & (CRPT_HMAC_STS_DMAERR_Msk))) + rt_kprintf("SHA ERROR - CRPT->INTSTS-%08x, CRPT->HMAC_STS-%08x\n", CRPT->INTSTS, CRPT->HMAC_STS); + + /* Clear SHA interrupt status */ + SHA_CLR_INT_FLAG(); +} + +static rt_err_t nu_sha_hash_run( + S_SHA_CONTEXT *psSHACtx, + uint32_t u32OpMode, + uint8_t *pu8InData, + uint32_t u32DataLen +) +{ + rt_err_t result; + + RT_ASSERT(psSHACtx != RT_NULL); + RT_ASSERT(pu8InData != RT_NULL); + + result = rt_mutex_take(&s_SHA_mutex, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + uint8_t *pu8SrcAddr = (uint8_t *)pu8InData; + uint32_t u32CopyLen = 0; + + while ((psSHACtx->u32SHATempBufLen + u32DataLen) > psSHACtx->u32BlockSize) + { + if (psSHACtx->pu8SHATempBuf) + { + if (psSHACtx->u32SHATempBufLen == psSHACtx->u32BlockSize) + { + //Trigger SHA block update + SHABlockUpdate(u32OpMode, (uint32_t)psSHACtx->pu8SHATempBuf, psSHACtx->u32BlockSize, psSHACtx->u32DMAMode); + + psSHACtx->u32DMAMode = CRYPTO_DMA_CONTINUE; + //free SHATempBuff + rt_free_align(psSHACtx->pu8SHATempBuf); + psSHACtx->pu8SHATempBuf = NULL; + psSHACtx->u32SHATempBufLen = 0; + continue; + } + else + { + u32CopyLen = psSHACtx->u32BlockSize - psSHACtx->u32SHATempBufLen; + if (u32DataLen < u32CopyLen) + u32CopyLen = u32DataLen; + rt_memcpy(psSHACtx->pu8SHATempBuf + psSHACtx->u32SHATempBufLen, pu8SrcAddr, u32CopyLen); + psSHACtx->u32SHATempBufLen += u32CopyLen; + pu8SrcAddr += u32CopyLen; + u32DataLen -= u32CopyLen; + continue; + } + } + + if ((uint32_t) pu8SrcAddr & (CACHE_LINE_SIZE - 1)) //address not aligned 32 + { + psSHACtx->pu8SHATempBuf = rt_malloc_align(psSHACtx->u32BlockSize, CACHE_LINE_SIZE); + + if (psSHACtx->pu8SHATempBuf == RT_NULL) + { + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize); + result = rt_mutex_release(&s_SHA_mutex); + RT_ASSERT(result == RT_EOK); + return -RT_ENOMEM; + } + + rt_memcpy(psSHACtx->pu8SHATempBuf, pu8SrcAddr, psSHACtx->u32BlockSize); + psSHACtx->u32SHATempBufLen = psSHACtx->u32BlockSize; + pu8SrcAddr += psSHACtx->u32BlockSize; + u32DataLen -= psSHACtx->u32BlockSize; + continue; + } + + //Trigger SHA block update + SHABlockUpdate(u32OpMode, (uint32_t)pu8SrcAddr, psSHACtx->u32BlockSize, psSHACtx->u32DMAMode); + + psSHACtx->u32DMAMode = CRYPTO_DMA_CONTINUE; + + pu8SrcAddr += psSHACtx->u32BlockSize; + u32DataLen -= psSHACtx->u32BlockSize; + } + + if (u32DataLen) + { + if (psSHACtx->pu8SHATempBuf == NULL) + { + psSHACtx->pu8SHATempBuf = rt_malloc_align(psSHACtx->u32BlockSize, CACHE_LINE_SIZE); + + if (psSHACtx->pu8SHATempBuf == RT_NULL) + { + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize); + result = rt_mutex_release(&s_SHA_mutex); + RT_ASSERT(result == RT_EOK); + return -RT_ENOMEM; + } + + psSHACtx->u32SHATempBufLen = 0; + } + + rt_memcpy(psSHACtx->pu8SHATempBuf, pu8SrcAddr, u32DataLen); + psSHACtx->u32SHATempBufLen += u32DataLen; + } + + result = rt_mutex_release(&s_SHA_mutex); + RT_ASSERT(result == RT_EOK); + + return RT_EOK; +} + +static rt_err_t nu_sha_update(struct hwcrypto_hash *hash_ctx, const rt_uint8_t *in, rt_size_t length) +{ + uint32_t u32SHAOpMode; + unsigned char *nu_in; + unsigned char in_align_flag = 0; + RT_ASSERT(hash_ctx != RT_NULL); + RT_ASSERT(in != RT_NULL); + + //Select SHA operation mode + switch (hash_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK)) + { + case HWCRYPTO_TYPE_SHA1: + u32SHAOpMode = SHA_MODE_SHA1; + break; + case HWCRYPTO_TYPE_SHA224: + u32SHAOpMode = SHA_MODE_SHA224; + break; + case HWCRYPTO_TYPE_SHA256: + u32SHAOpMode = SHA_MODE_SHA256; + break; + case HWCRYPTO_TYPE_SHA384: + u32SHAOpMode = SHA_MODE_SHA384; + break; + case HWCRYPTO_TYPE_SHA512: + u32SHAOpMode = SHA_MODE_SHA512; + break; + default : + return -RT_ERROR; + } + + nu_in = (unsigned char *)in; + + //Checking in data buffer address not alignment + if (((rt_uint32_t)nu_in % CACHE_LINE_SIZE) != 0) + { + nu_in = rt_malloc_align(length, CACHE_LINE_SIZE); + if (nu_in == RT_NULL) + { + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, length); + return -RT_ENOMEM; + } + + rt_memcpy(nu_in, in, length); + in_align_flag = 1; + } + + nu_sha_hash_run(hash_ctx->parent.contex, u32SHAOpMode, nu_in, length); + + if (in_align_flag) + { + rt_free_align(nu_in); + } + + return RT_EOK; +} + +static rt_err_t nu_sha_finish(struct hwcrypto_hash *hash_ctx, rt_uint8_t *out, rt_size_t length) +{ + unsigned char *nu_out; + unsigned char out_align_flag = 0; + uint32_t u32SHAOpMode; + S_SHA_CONTEXT *psSHACtx = RT_NULL; + RT_ASSERT(hash_ctx != RT_NULL); + RT_ASSERT(out != RT_NULL); + + psSHACtx = hash_ctx->parent.contex; + + //Check SHA Hash value buffer length + switch (hash_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK)) + { + case HWCRYPTO_TYPE_SHA1: + u32SHAOpMode = SHA_MODE_SHA1; + if (length < 5UL) + { + return -RT_EINVAL; + } + break; + case HWCRYPTO_TYPE_SHA224: + u32SHAOpMode = SHA_MODE_SHA224; + if (length < 7UL) + { + return -RT_EINVAL; + } + break; + case HWCRYPTO_TYPE_SHA256: + u32SHAOpMode = SHA_MODE_SHA256; + if (length < 8UL) + { + return -RT_EINVAL; + } + break; + case HWCRYPTO_TYPE_SHA384: + u32SHAOpMode = SHA_MODE_SHA384; + if (length < 12UL) + { + return -RT_EINVAL; + } + break; + case HWCRYPTO_TYPE_SHA512: + u32SHAOpMode = SHA_MODE_SHA512; + if (length < 16UL) + { + return -RT_EINVAL; + } + break; + default : + return -RT_ERROR; + } + + nu_out = (unsigned char *)out; + + //Checking out data buffer address alignment or not + if (((rt_uint32_t)nu_out % CACHE_LINE_SIZE) != 0) + { + nu_out = rt_malloc_align(length, CACHE_LINE_SIZE); + if (nu_out == RT_NULL) + { + LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, length); + return -RT_ENOMEM; + } + + out_align_flag = 1; + } + + if (psSHACtx->pu8SHATempBuf) + { + if (psSHACtx->u32DMAMode == CRYPTO_DMA_FIRST) + SHABlockUpdate(u32SHAOpMode, (uint32_t)psSHACtx->pu8SHATempBuf, psSHACtx->u32SHATempBufLen, CRYPTO_DMA_ONE_SHOT); + else + SHABlockUpdate(u32SHAOpMode, (uint32_t)psSHACtx->pu8SHATempBuf, psSHACtx->u32SHATempBufLen, CRYPTO_DMA_LAST); + + //free SHATempBuf + rt_free_align(psSHACtx->pu8SHATempBuf); + psSHACtx->pu8SHATempBuf = RT_NULL; + psSHACtx->u32SHATempBufLen = 0; + } + else + { + SHABlockUpdate(u32SHAOpMode, (uint32_t)NULL, 0, CRYPTO_DMA_LAST); + } + + SHA_Read((uint32_t *)nu_out); + + if (out_align_flag) + { + rt_memcpy(out, nu_out, length); + rt_free_align(nu_out); + } + + return RT_EOK; +} + +static rt_uint32_t nu_prng_rand(struct hwcrypto_rng *ctx) +{ + return nu_prng_run(); +} + +static const struct hwcrypto_symmetric_ops nu_aes_ops = +{ + .crypt = nu_aes_crypt, +}; + +static const struct hwcrypto_symmetric_ops nu_des_ops = +{ + .crypt = nu_des_crypt, +}; + +static const struct hwcrypto_hash_ops nu_sha_ops = +{ + .update = nu_sha_update, + .finish = nu_sha_finish, +}; + +static const struct hwcrypto_rng_ops nu_rng_ops = +{ + .update = nu_prng_rand, +}; + +/* Register crypto interface ----------------------------------------------------------*/ +static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) +{ + rt_err_t res = RT_EOK; + RT_ASSERT(ctx != RT_NULL); + + switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK) + { + + case HWCRYPTO_TYPE_AES: + { + ctx->contex = RT_NULL; + //Setup AES operation + ((struct hwcrypto_symmetric *)ctx)->ops = &nu_aes_ops; + break; + } + + case HWCRYPTO_TYPE_DES: + { + ctx->contex = RT_NULL; + //Setup DES operation + ((struct hwcrypto_symmetric *)ctx)->ops = &nu_des_ops; + break; + } + + case HWCRYPTO_TYPE_3DES: + { + ctx->contex = RT_NULL; + //Setup 3DES operation + ((struct hwcrypto_symmetric *)ctx)->ops = &nu_des_ops; + break; + } + + + case HWCRYPTO_TYPE_SHA1: + { + ctx->contex = rt_malloc(sizeof(S_SHA_CONTEXT)); + + if (ctx->contex == RT_NULL) + return -RT_ERROR; + + rt_memset(ctx->contex, 0, sizeof(S_SHA_CONTEXT)); + //Setup SHA1 operation + ((struct hwcrypto_hash *)ctx)->ops = &nu_sha_ops; + break; + } + + case HWCRYPTO_TYPE_SHA2: + { + ctx->contex = rt_malloc(sizeof(S_SHA_CONTEXT)); + + if (ctx->contex == RT_NULL) + return -RT_ERROR; + + rt_memset(ctx->contex, 0, sizeof(S_SHA_CONTEXT)); + //Setup SHA2 operation + ((struct hwcrypto_hash *)ctx)->ops = &nu_sha_ops; + break; + } + + case HWCRYPTO_TYPE_RNG: + { + ctx->contex = RT_NULL; + ((struct hwcrypto_rng *)ctx)->ops = &nu_rng_ops; +#if defined(NU_PRNG_USE_SEED) + nu_prng_open(NU_PRNG_SEED_VALUE); +#endif + break; + } + + default: + res = -RT_ERROR; + break; + } + + return res; +} + +static void nu_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx) +{ + RT_ASSERT(ctx != RT_NULL); + + if (ctx->contex) + rt_free(ctx->contex); +} + +static rt_err_t nu_hwcrypto_clone(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) +{ + rt_err_t res = RT_EOK; + RT_ASSERT(des != RT_NULL); + RT_ASSERT(src != RT_NULL); + + if (des->contex && src->contex) + { + rt_memcpy(des->contex, src->contex, sizeof(struct rt_hwcrypto_ctx)); + } + else + return -RT_EINVAL; + return res; +} + +static void nu_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx) +{ + switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK) + { + case HWCRYPTO_TYPE_RNG: + { +#if defined(NU_PRNG_USE_SEED) + nu_prng_open(NU_PRNG_SEED_VALUE); +#else + nu_prng_open(rt_tick_get()); +#endif + break; + } + case HWCRYPTO_TYPE_SHA1: + case HWCRYPTO_TYPE_SHA2: + { + S_SHA_CONTEXT *psSHACtx = (S_SHA_CONTEXT *)ctx->contex; + + if (psSHACtx->pu8SHATempBuf) + { + rt_free_align(psSHACtx->pu8SHATempBuf); + } + + psSHACtx->pu8SHATempBuf = RT_NULL; + psSHACtx->u32SHATempBufLen = 0; + psSHACtx->u32DMAMode = CRYPTO_DMA_FIRST; + + if ((ctx->type == HWCRYPTO_TYPE_SHA384) || (ctx->type == HWCRYPTO_TYPE_SHA512)) + { + psSHACtx->u32BlockSize = 128; + } + else + { + psSHACtx->u32BlockSize = 64; + } + break; + } + + default: + break; + } +} + +/* Init and register nu_hwcrypto_dev */ + +int nu_hwcrypto_device_init(void) +{ + rt_err_t result; + static struct rt_hwcrypto_device nu_hwcrypto_dev; + + nu_hwcrypto_dev.ops = &nu_hwcrypto_ops; + nu_hwcrypto_dev.id = 0; + nu_hwcrypto_dev.user_data = &nu_hwcrypto_dev; + + nu_sys_ipclk_enable(CRYPTOCKEN); + nu_sys_ip_reset(CRYPTORST); + + /* init cipher mutex */ +#if defined(RT_HWCRYPTO_USING_AES) + result = rt_mutex_init(&s_AES_mutex, NU_HWCRYPTO_AES_NAME, RT_IPC_FLAG_PRIO); + RT_ASSERT(result == RT_EOK); + AES_ENABLE_INT(); +#endif + +#if defined(RT_HWCRYPTO_USING_SHA1) || defined(RT_HWCRYPTO_USING_SHA2) + result = rt_mutex_init(&s_SHA_mutex, NU_HWCRYPTO_SHA_NAME, RT_IPC_FLAG_PRIO); + RT_ASSERT(result == RT_EOK); + SHA_ENABLE_INT(); +#endif + +#if defined(RT_HWCRYPTO_USING_RNG) + result = rt_mutex_init(&s_PRNG_mutex, NU_HWCRYPTO_PRNG_NAME, RT_IPC_FLAG_PRIO); + RT_ASSERT(result == RT_EOK); + PRNG_ENABLE_INT(); +#endif + + /* register hwcrypto operation */ + result = rt_hwcrypto_register(&nu_hwcrypto_dev, RT_HWCRYPTO_DEFAULT_NAME); + RT_ASSERT(result == RT_EOK); + + /* Enable Crypto engine interrupt */ + rt_hw_interrupt_install(IRQ_CRPT, nu_crypto_isr, RT_NULL, "crypto"); + + return 0; +} +INIT_DEVICE_EXPORT(nu_hwcrypto_device_init); + +#endif //#if (defined(BSP_USING_CRYPTO) && defined(RT_USING_HWCRYPTO)) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_emac.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_emac.c new file mode 100644 index 0000000000..0ff6857fd0 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_emac.c @@ -0,0 +1,621 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_EMAC) + +#if defined(RT_USING_LWIP) + +#include +#include "NuMicro.h" +#include +#include +#include +#include "lwipopts.h" + +#include "drv_sys.h" + +/* Private define ---------------------------------------------------------------*/ +// RT_DEV_NAME_PREFIX e + +#define NU_EMAC_DEBUG +#if defined(NU_EMAC_DEBUG) + //#define NU_EMAC_RX_DUMP + //#define NU_EMAC_TX_DUMP + #define NU_EMAC_TRACE rt_kprintf +#else + #define NU_EMAC_TRACE(...) +#endif + +#define NU_EMAC_TID_STACK_SIZE 1024 + +/* Private typedef --------------------------------------------------------------*/ +struct nu_emac +{ + struct eth_device eth; + char *name; + EMAC_MEMMGR_T memmgr; + IRQn_Type irqn_tx; + IRQn_Type irqn_rx; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + rt_thread_t link_monitor; + rt_uint8_t mac_addr[6]; + struct rt_semaphore eth_sem; +}; +typedef struct nu_emac *nu_emac_t; + +enum +{ + EMAC_START = -1, +#if defined(BSP_USING_EMAC0) + EMAC0_IDX, +#endif +#if defined(BSP_USING_EMAC1) + EMAC1_IDX, +#endif + EMAC_CNT +}; + +/* Private functions ------------------------------------------------------------*/ +#if defined(NU_EMAC_RX_DUMP) || defined(NU_EMAC_TX_DUMP) + static void nu_emac_pkt_dump(const char *msg, const struct pbuf *p); +#endif +#if LWIP_IPV4 && LWIP_IGMP + static err_t nu_igmp_mac_filter(struct netif *netif, const ip4_addr_t *ip4_addr, enum netif_mac_filter_action action); +#endif +static void nu_emac_halt(nu_emac_t); +static void nu_emac_reinit(nu_emac_t); +static void link_monitor(void *param); +static rt_err_t nu_emac_init(rt_device_t dev); + +static rt_err_t nu_emac_open(rt_device_t dev, rt_uint16_t oflag); +static rt_err_t nu_emac_close(rt_device_t dev); +static rt_size_t nu_emac_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size); +static rt_size_t nu_emac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size); +static rt_err_t nu_emac_control(rt_device_t dev, int cmd, void *args); +static rt_err_t nu_emac_tx(rt_device_t dev, struct pbuf *p); +static struct pbuf *nu_emac_rx(rt_device_t dev); +static void rt_hw_nu_emac_assign_macaddr(nu_emac_t psNuEMAC); +static int rt_hw_nu_emac_init(void); +static void *nu_emac_memcpy(void *dest, void *src, unsigned int count); +static void nu_emac_tx_isr(int vector, void *param); +static void nu_emac_rx_isr(int vector, void *param); + +/* Public functions -------------------------------------------------------------*/ + +/* Private variables ------------------------------------------------------------*/ +static struct nu_emac nu_emac_arr[] = +{ +#if defined(BSP_USING_EMAC0) + { + .name = "e0", + .memmgr.psEmac = (EMAC_T *)EMC0_BA, + .irqn_tx = IRQ_EMC0_TX, + .irqn_rx = IRQ_EMC0_RX, + .rstidx = EMAC0RST, + .clkidx = EMAC0CKEN, + }, +#endif +#if defined(BSP_USING_EMAC1) + { + .name = "e1", + .memmgr.psEmac = (EMAC_T *)EMC1_BA, + .irqn_tx = IRQ_EMC1_TX, + .irqn_rx = IRQ_EMC1_RX, + .rstidx = EMAC1RST, + .clkidx = EMAC1CKEN, + }, +#endif +}; + +#if defined(NU_EMAC_RX_DUMP) || defined(NU_EMAC_TX_DUMP) +static void nu_emac_pkt_dump(const char *msg, const struct pbuf *p) +{ + rt_uint32_t i; + rt_uint8_t *ptr = p->payload; + + NU_EMAC_TRACE("%s %d byte\n", msg, p->tot_len); + + for (i = 0; i < p->tot_len; i++) + { + if ((i % 8) == 0) + { + NU_EMAC_TRACE(" "); + } + if ((i % 16) == 0) + { + NU_EMAC_TRACE("\r\n"); + } + NU_EMAC_TRACE("%02x ", *ptr); + ptr++; + } + NU_EMAC_TRACE("\n\n"); +} +#endif /* dump */ + +static void nu_emac_halt(nu_emac_t psNuEmac) +{ + EMAC_T *EMAC = psNuEmac->memmgr.psEmac; + EMAC_DISABLE_RX(EMAC); + EMAC_DISABLE_TX(EMAC); +} + +static void *nu_emac_memcpy(void *dest, void *src, unsigned int count) +{ + return memcpy(dest, src, count); +} + +static void nu_emac_reinit(nu_emac_t psNuEmac) +{ + rt_uint32_t EMAC_CAMxM[EMAC_CAMENTRY_NB]; + rt_uint32_t EMAC_CAMxL[EMAC_CAMENTRY_NB]; + rt_uint32_t EMAC_CAMEN; + EMAC_T *EMAC = psNuEmac->memmgr.psEmac; + + // Backup MAC address. + EMAC_CAMEN = EMAC->CAMEN; + for (rt_uint8_t index = 0 ; index < EMAC_CAMENTRY_NB; index ++) + { + rt_uint32_t *CAMxM = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0M + (index * 8)); + rt_uint32_t *CAMxL = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0L + (index * 8)); + + EMAC_CAMxM[index] = *CAMxM; + EMAC_CAMxL[index] = *CAMxL; + } + + nu_emac_halt(psNuEmac); + EMAC_Close(EMAC); + EMAC_Open(&psNuEmac->memmgr, (uint8_t *)&psNuEmac->mac_addr[0]); + EMAC_ENABLE_TX(EMAC); + EMAC_ENABLE_RX(EMAC); + + // Restore MAC address. + for (rt_uint8_t index = 0 ; index < EMAC_CAMENTRY_NB; index ++) + { + rt_uint32_t *CAMxM = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0M + (index * 8)); + rt_uint32_t *CAMxL = (rt_uint32_t *)((rt_uint32_t)&EMAC->CAM0L + (index * 8)); + + *CAMxM = EMAC_CAMxM[index]; + *CAMxL = EMAC_CAMxL[index]; + } + EMAC->CAMEN = EMAC_CAMEN; +} + +#if LWIP_IPV4 && LWIP_IGMP +static err_t nu_igmp_mac_filter(struct netif *netif, const ip4_addr_t *ip4_addr, enum netif_mac_filter_action action) +{ + nu_emac_t psNuEmac = (nu_emac_t)netif->state; + rt_uint8_t mac[6]; + int32_t ret = 0; + const uint8_t *p = (const uint8_t *)ip4_addr; + + mac[0] = 0x01; + mac[1] = 0x00; + mac[2] = 0x5E; + mac[3] = *(p + 1) & 0x7F; + mac[4] = *(p + 2); + mac[5] = *(p + 3); + + ret = EMAC_FillCamEntry(psNuEmac->memmgr.psEmac, (uint8_t *)&mac[0]); + if (ret >= 0) + { + NU_EMAC_TRACE("%s %s %s ", __FUNCTION__, (action == NETIF_ADD_MAC_FILTER) ? "add" : "del", ip4addr_ntoa(ip4_addr)); + NU_EMAC_TRACE("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + + return (ret >= 0) ? RT_EOK : -(RT_ERROR); +} +#endif /* LWIP_IPV4 && LWIP_IGMP */ + +static void link_monitor(void *param) +{ + nu_emac_t psNuEmac = (nu_emac_t)param; + EMAC_T *EMAC = psNuEmac->memmgr.psEmac; + uint32_t LinkStatus_Last = EMAC_LINK_DOWN; + + EMAC_PhyInit(EMAC); + + while (1) + { + uint32_t LinkStatus_Current = EMAC_CheckLinkStatus(EMAC); + /* linkchange */ + if (LinkStatus_Last != LinkStatus_Current) + { + + switch (LinkStatus_Current) + { + case EMAC_LINK_DOWN: + NU_EMAC_TRACE("[%s] Link status: Down\n", psNuEmac->name); + break; + + case EMAC_LINK_100F: + NU_EMAC_TRACE("[%s] Link status: 100F\n", psNuEmac->name); + break; + + case EMAC_LINK_100H: + NU_EMAC_TRACE("[%s] Link status: 100H\n", psNuEmac->name); + break; + + case EMAC_LINK_10F: + NU_EMAC_TRACE("[%s] Link status: 10F\n", psNuEmac->name); + break; + + case EMAC_LINK_10H: + NU_EMAC_TRACE("[%s] Link status: 10H\n", psNuEmac->name); + break; + } /* switch( LinkStatus_Current ) */ + + /* Send link status to upper layer. */ + if (LinkStatus_Current == EMAC_LINK_DOWN) + { + eth_device_linkchange(&psNuEmac->eth, RT_FALSE); + } + else + { + eth_device_linkchange(&psNuEmac->eth, RT_TRUE); + } + LinkStatus_Last = LinkStatus_Current; + + } /* if ( LinkStatus_Last != LinkStatus_Current ) */ + + rt_thread_delay(RT_TICK_PER_SECOND); + + } /* while(1) */ + +} + +static void nu_memmgr_init(EMAC_MEMMGR_T *psMemMgr) +{ + psMemMgr->u32TxDescSize = EMAC_TX_DESC_SIZE; + psMemMgr->u32RxDescSize = EMAC_RX_DESC_SIZE; + + psMemMgr->psTXDescs = (EMAC_DESCRIPTOR_T *) rt_malloc_align(sizeof(EMAC_DESCRIPTOR_T) * psMemMgr->u32TxDescSize, 32); + RT_ASSERT(psMemMgr->psTXDescs != RT_NULL); + + psMemMgr->psRXDescs = (EMAC_DESCRIPTOR_T *) rt_malloc_align(sizeof(EMAC_DESCRIPTOR_T) * psMemMgr->u32RxDescSize, 32); + RT_ASSERT(psMemMgr->psRXDescs != RT_NULL); + + psMemMgr->psTXFrames = (EMAC_FRAME_T *) rt_malloc_align(sizeof(EMAC_FRAME_T) * psMemMgr->u32TxDescSize, 32); + RT_ASSERT(psMemMgr->psTXFrames != RT_NULL); + + psMemMgr->psRXFrames = (EMAC_FRAME_T *) rt_malloc_align(sizeof(EMAC_FRAME_T) * psMemMgr->u32RxDescSize, 32); + RT_ASSERT(psMemMgr->psRXFrames != RT_NULL); +} + +static rt_err_t nu_emac_init(rt_device_t dev) +{ + nu_emac_t psNuEmac = (nu_emac_t)dev; + EMAC_T *EMAC = psNuEmac->memmgr.psEmac; + char szTmp[16]; + rt_err_t ret = RT_EOK; + + nu_memmgr_init(&psNuEmac->memmgr); + + snprintf(szTmp, sizeof(szTmp), "%sphy", psNuEmac->name); + + ret = rt_sem_init(&psNuEmac->eth_sem, "eth_sem", 0, RT_IPC_FLAG_FIFO); + RT_ASSERT(ret == RT_EOK); + + EMAC_Reset(EMAC); + + EMAC_Close(EMAC); + EMAC_Open(&psNuEmac->memmgr, (uint8_t *)&psNuEmac->mac_addr[0]); + +#if defined(BSP_USING_MMU) + mmu_clean_invalidated_dcache((uint32_t)psNuEmac->memmgr.psTXDescs, sizeof(EMAC_DESCRIPTOR_T)*psNuEmac->memmgr.u32TxDescSize); + mmu_clean_invalidated_dcache((uint32_t)psNuEmac->memmgr.psRXDescs, sizeof(EMAC_DESCRIPTOR_T)*psNuEmac->memmgr.u32RxDescSize); +#endif + + EMAC_ENABLE_RX(EMAC); + EMAC_ENABLE_TX(EMAC); + + EMAC_TRIGGER_RX(EMAC); + +#if defined(LWIP_IPV4) && defined(LWIP_IGMP) + netif_set_igmp_mac_filter(psNuEmac->eth.netif, nu_igmp_mac_filter); +#endif /* LWIP_IPV4 && LWIP_IGMP */ + + psNuEmac->link_monitor = rt_thread_create((const char *)szTmp, + link_monitor, + (void *)psNuEmac, + NU_EMAC_TID_STACK_SIZE, + RT_THREAD_PRIORITY_MAX - 2, + 10); + RT_ASSERT(psNuEmac->link_monitor != RT_NULL); + + ret = rt_thread_startup(psNuEmac->link_monitor); + RT_ASSERT(ret == RT_EOK); + + return RT_EOK; +} + +static rt_err_t nu_emac_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t nu_emac_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_size_t nu_emac_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_size_t nu_emac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_err_t nu_emac_control(rt_device_t dev, int cmd, void *args) +{ + nu_emac_t psNuEMAC = (nu_emac_t)dev; + switch (cmd) + { + case NIOCTL_GADDR: + /* Get MAC address */ + if (args) + rt_memcpy(args, &psNuEMAC->mac_addr[0], 6); + else + return -RT_ERROR; + + break; + default : + break; + } + + return RT_EOK; +} + +static rt_err_t nu_emac_tx(rt_device_t dev, struct pbuf *p) +{ + nu_emac_t psNuEmac = (nu_emac_t)dev; + EMAC_T *EMAC = psNuEmac->memmgr.psEmac; + struct pbuf *q; + rt_uint32_t offset = 0; + rt_uint8_t *buf; + + buf = (rt_uint8_t *)EMAC_ClaimFreeTXBuf(&psNuEmac->memmgr); + /* Get free TX buffer */ + if (buf == RT_NULL) + { + rt_err_t result; + + result = rt_sem_control(&psNuEmac->eth_sem, RT_IPC_CMD_RESET, 0); + RT_ASSERT(result != RT_EOK); + + EMAC_CLEAR_INT_FLAG(EMAC, EMAC_INTSTS_TXCPIF_Msk); + EMAC_ENABLE_INT(EMAC, EMAC_INTEN_TXCPIEN_Msk); + + do + { + result = rt_sem_take(&psNuEmac->eth_sem, 10); + buf = (rt_uint8_t *)EMAC_ClaimFreeTXBuf(&psNuEmac->memmgr); + } + while (buf == RT_NULL); + } + + for (q = p; q != NULL; q = q->next) + { + rt_uint8_t *ptr; + rt_uint32_t len; + + len = q->len; + ptr = q->payload; + + nu_emac_memcpy(&buf[offset], ptr, len); + + offset += len; + } + +#if defined(NU_EMAC_TX_DUMP) + nu_emac_pkt_dump("TX dump", p); +#endif + + /* Return SUCCESS? */ +#if defined(BSP_USING_MMU) + mmu_clean_invalidated_dcache((uint32_t)psNuEmac->memmgr.psCurrentTxDesc, sizeof(EMAC_DESCRIPTOR_T)); +#endif + return (EMAC_SendPktWoCopy(&psNuEmac->memmgr, offset) == 1) ? RT_EOK : RT_ERROR; +} + +static struct pbuf *nu_emac_rx(rt_device_t dev) +{ + nu_emac_t psNuEmac = (nu_emac_t)dev; + struct pbuf *p = RT_NULL; + uint8_t *pu8DataBuf = NULL; + unsigned int avaialbe_size; + EMAC_T *EMAC = psNuEmac->memmgr.psEmac; + + /* Check available data. */ +#if defined(BSP_USING_MMU) + mmu_clean_invalidated_dcache((uint32_t)psNuEmac->memmgr.psCurrentRxDesc, sizeof(EMAC_DESCRIPTOR_T)); +#endif + if ((avaialbe_size = EMAC_GetAvailRXBufSize(&psNuEmac->memmgr, &pu8DataBuf)) > 0) + { + /* Allocate RX packet buffer. */ + p = pbuf_alloc(PBUF_RAW, avaialbe_size, PBUF_RAM); + if (p != RT_NULL) + { + RT_ASSERT(p->next == RT_NULL); + + nu_emac_memcpy((void *)p->payload, (void *)pu8DataBuf, avaialbe_size); + +#if defined(NU_EMAC_RX_DUMP) + nu_emac_pkt_dump("RX dump", p); +#endif + } + else + { + NU_EMAC_TRACE("Can't allocate memory for RX packet.(%d)\n", avaialbe_size); + } + + /* Update RX descriptor */ + EMAC_RecvPktDoneWoRxTrigger(&psNuEmac->memmgr); + } + else /* If it hasn't RX packet, it will enable interrupt. */ + { + /* No available RX packet, we enable RXGD/RDUIEN interrupts. */ + if (!(EMAC->INTEN & EMAC_INTEN_RDUIEN_Msk)) + { + EMAC_CLEAR_INT_FLAG(EMAC, (EMAC_INTSTS_RDUIF_Msk | EMAC_INTSTS_RXGDIF_Msk)); + EMAC_ENABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk)); + } + else + { + EMAC_CLEAR_INT_FLAG(EMAC, EMAC_INTSTS_RXGDIF_Msk); + EMAC_ENABLE_INT(EMAC, EMAC_INTEN_RXGDIEN_Msk); + } + EMAC_TRIGGER_RX(EMAC); + } + + return p; +} + +static void nu_emac_rx_isr(int vector, void *param) +{ + nu_emac_t psNuEmac = (nu_emac_t)param; + EMAC_T *EMAC = psNuEmac->memmgr.psEmac; + + unsigned int status = EMAC->INTSTS & 0xFFFF; + + /* No RX descriptor available, we need to get data from RX pool */ + if (EMAC_GET_INT_FLAG(EMAC, EMAC_INTSTS_RDUIF_Msk)) + { + EMAC_DISABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk)); + eth_device_ready(&psNuEmac->eth); + } + /* A good packet ready. */ + else if (EMAC_GET_INT_FLAG(EMAC, EMAC_INTSTS_RXGDIF_Msk)) + { + EMAC_DISABLE_INT(EMAC, EMAC_INTEN_RXGDIEN_Msk); + eth_device_ready(&psNuEmac->eth); + } + + /* Receive Bus Error Interrupt */ + if (EMAC_GET_INT_FLAG(EMAC, EMAC_INTSTS_RXBEIF_Msk)) + { + NU_EMAC_TRACE("Reinit Rx EMAC\n"); + EMAC_CLEAR_INT_FLAG(EMAC, EMAC_INTSTS_RXBEIF_Msk); + nu_emac_reinit(psNuEmac); + } + + EMAC->INTSTS = status; +} + +static void nu_emac_tx_isr(int vector, void *param) +{ + nu_emac_t psNuEmac = (nu_emac_t)param; + EMAC_T *EMAC = psNuEmac->memmgr.psEmac; + rt_err_t result = RT_EOK; + + unsigned int status = EMAC->INTSTS & 0xFFFF0000; + + /* Wake-up suspended process to send */ + if (EMAC_GET_INT_FLAG(EMAC, EMAC_INTSTS_TXCPIF_Msk)) + { + EMAC_DISABLE_INT(EMAC, EMAC_INTEN_TXCPIEN_Msk); + + result = rt_sem_release(&psNuEmac->eth_sem); + RT_ASSERT(result == RT_EOK); + } + + if (EMAC_GET_INT_FLAG(EMAC, EMAC_INTSTS_TXBEIF_Msk)) + { + NU_EMAC_TRACE("Reinit Tx EMAC\n"); + nu_emac_reinit(psNuEmac); + } + else + EMAC_SendPktDone(&psNuEmac->memmgr); + + EMAC->INTSTS = status; +} + +static void rt_hw_nu_emac_assign_macaddr(nu_emac_t psNuEMAC) +{ + static rt_uint32_t value = 0x94539453; + + /* Assign MAC address */ + psNuEMAC->mac_addr[0] = 0x82; + psNuEMAC->mac_addr[1] = 0x06; + psNuEMAC->mac_addr[2] = 0x21; + psNuEMAC->mac_addr[3] = (value >> 16) & 0xff; + psNuEMAC->mac_addr[4] = (value >> 8) & 0xff; + psNuEMAC->mac_addr[5] = (value) & 0xff; + + NU_EMAC_TRACE("MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", \ + psNuEMAC->mac_addr[0], \ + psNuEMAC->mac_addr[1], \ + psNuEMAC->mac_addr[2], \ + psNuEMAC->mac_addr[3], \ + psNuEMAC->mac_addr[4], \ + psNuEMAC->mac_addr[5]); + value++; +} + +static int rt_hw_nu_emac_init(void) +{ + int i; + rt_err_t ret = RT_EOK; + char szTmp[32]; + + /* MDC CLK divider */ + outpw(REG_CLK_DIVCTL8, (inpw(REG_CLK_DIVCTL8) & ~0xFF) | 0xA0); + + for (i = (EMAC_START + 1); i < EMAC_CNT; i++) + { + nu_emac_t psNuEMAC = (nu_emac_t)&nu_emac_arr[i]; + + nu_sys_ipclk_enable(psNuEMAC->clkidx); + + nu_sys_ip_reset(psNuEMAC->rstidx); + + rt_hw_nu_emac_assign_macaddr(psNuEMAC); + + /* Register member functions */ + psNuEMAC->eth.parent.init = nu_emac_init; + psNuEMAC->eth.parent.open = nu_emac_open; + psNuEMAC->eth.parent.close = nu_emac_close; + psNuEMAC->eth.parent.read = nu_emac_read; + psNuEMAC->eth.parent.write = nu_emac_write; + psNuEMAC->eth.parent.control = nu_emac_control; + psNuEMAC->eth.parent.user_data = psNuEMAC; + psNuEMAC->eth.eth_rx = nu_emac_rx; + psNuEMAC->eth.eth_tx = nu_emac_tx; + + snprintf(szTmp, sizeof(szTmp), "%s_tx", psNuEMAC->name); + rt_hw_interrupt_install(psNuEMAC->irqn_tx, nu_emac_tx_isr, (void *)psNuEMAC, szTmp); + rt_hw_interrupt_umask(psNuEMAC->irqn_tx); + + snprintf(szTmp, sizeof(szTmp), "%s_rx", psNuEMAC->name); + rt_hw_interrupt_install(psNuEMAC->irqn_rx, nu_emac_rx_isr, (void *)psNuEMAC, szTmp); + rt_hw_interrupt_umask(psNuEMAC->irqn_rx); + + /* Register eth device */ + ret = eth_device_init(&psNuEMAC->eth, psNuEMAC->name); + RT_ASSERT(ret == RT_EOK); + } + + return 0; +} + +INIT_APP_EXPORT(rt_hw_nu_emac_init); + +#endif /* #if defined( RT_USING_LWIP ) */ + +#endif /* #if defined( BSP_USING_EMAC ) */ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_etimer.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_etimer.c new file mode 100644 index 0000000000..7c3b1578e4 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_etimer.c @@ -0,0 +1,283 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-3 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_ETIMER) && defined(RT_USING_HWTIMER) + +#include +#include "NuMicro.h" +#include + +/* Private define ---------------------------------------------------------------*/ +#define NU_TIMER_DEVICE(etimer) (nu_etimer_t)(etimer) + +enum +{ + ETIMER_START = -1, +#if defined(BSP_USING_ETIMER0) + ETIMER0_IDX, +#endif +#if defined(BSP_USING_ETIMER1) + ETIMER1_IDX, +#endif +#if defined(BSP_USING_ETIMER2) + ETIMER2_IDX, +#endif +#if defined(BSP_USING_ETIMER3) + ETIMER3_IDX, +#endif + ETIMER_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ +struct nu_etimer +{ + rt_hwtimer_t parent; + char *name; + uint32_t idx; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; +}; +typedef struct nu_etimer *nu_etimer_t; + +/* Private functions ------------------------------------------------------------*/ +static void nu_etimer_init(rt_hwtimer_t *timer, rt_uint32_t state); +static rt_err_t nu_etimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode); +static void nu_etimer_stop(rt_hwtimer_t *timer); +static rt_uint32_t nu_etimer_count_get(rt_hwtimer_t *timer); +static rt_err_t nu_etimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args); + +/* Public functions -------------------------------------------------------------*/ + + +/* Private variables ------------------------------------------------------------*/ +static struct nu_etimer nu_etimer_arr [] = +{ +#if defined(BSP_USING_ETIMER0) + { + .name = "etmr0", + .idx = 0, + .irqn = IRQ_ETMR0, + .rstidx = ETIMER0RST, + .clkidx = ETIMER0CKEN, + }, +#endif +#if defined(BSP_USING_ETIMER1) + { + .name = "etmr1", + .idx = 1, + .irqn = IRQ_ETMR1, + .rstidx = ETIMER1RST, + .clkidx = ETIMER1CKEN, + }, +#endif +#if defined(BSP_USING_ETIMER2) + { + .name = "etmr2", + .idx = 2, + .irqn = IRQ_ETMR2, + .rstidx = ETIMER2RST, + .clkidx = ETIMER2CKEN, + }, +#endif +#if defined(BSP_USING_ETIMER3) + { + .name = "etmr3", + .idx = 3, + .irqn = IRQ_ETMR3, + .rstidx = ETIMER3RST, + .clkidx = ETIMER3CKEN, + }, +#endif +}; + +static struct rt_hwtimer_info nu_etimer_info = +{ + 12000000, /* maximum count frequency */ + 46875, /* minimum count frequency */ + 0xFFFFFF, /* the maximum counter value */ + HWTIMER_CNTMODE_UP, /* Increment or Decreasing count mode */ +}; + +static struct rt_hwtimer_ops nu_etimer_ops = +{ + nu_etimer_init, + nu_etimer_start, + nu_etimer_stop, + nu_etimer_count_get, + nu_etimer_control +}; + +/* Functions define ------------------------------------------------------------*/ +static void nu_etimer_init(rt_hwtimer_t *timer, rt_uint32_t state) +{ + nu_etimer_t psNuETmr = NU_TIMER_DEVICE(timer); + RT_ASSERT(psNuETmr != RT_NULL); + + if (1 == state) + { + uint32_t timer_clk; + struct rt_hwtimer_info *info = &nu_etimer_info; + + timer_clk = ETIMER_GetModuleClock(psNuETmr->idx); + info->maxfreq = timer_clk; + info->minfreq = timer_clk / 256; + ETIMER_Open(psNuETmr->idx, ETIMER_ONESHOT_MODE, 1); + ETIMER_EnableInt(psNuETmr->idx); + rt_hw_interrupt_umask(psNuETmr->irqn); + } + else + { + rt_hw_interrupt_mask(psNuETmr->irqn); + ETIMER_DisableInt(psNuETmr->idx); + ETIMER_Close(psNuETmr->idx); + } +} + +static rt_err_t nu_etimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode) +{ + rt_err_t ret = RT_EINVAL; + rt_uint32_t u32OpMode; + + nu_etimer_t psNuETmr = NU_TIMER_DEVICE(timer); + RT_ASSERT(psNuETmr != RT_NULL); + + if (cnt <= 1 || cnt > 0xFFFFFF) + { + goto exit_nu_etimer_start; + } + + switch (opmode) + { + case HWTIMER_MODE_PERIOD: + u32OpMode = ETIMER_PERIODIC_MODE; + break; + + case HWTIMER_MODE_ONESHOT: + u32OpMode = ETIMER_ONESHOT_MODE; + break; + + default: + goto exit_nu_etimer_start; + } + + ETIMER_SET_CMP_VALUE(psNuETmr->idx, cnt); + ETIMER_SET_OPMODE(psNuETmr->idx, u32OpMode); + ETIMER_EnableInt(psNuETmr->idx); + rt_hw_interrupt_umask(psNuETmr->irqn); + + ETIMER_Start(psNuETmr->idx); + + ret = RT_EOK; + +exit_nu_etimer_start: + + return -(ret); +} + +static void nu_etimer_stop(rt_hwtimer_t *timer) +{ + nu_etimer_t psNuETmr = NU_TIMER_DEVICE(timer); + RT_ASSERT(psNuETmr != RT_NULL); + + rt_hw_interrupt_mask(psNuETmr->irqn); + ETIMER_DisableInt(psNuETmr->idx); + ETIMER_Stop(psNuETmr->idx); + ETIMER_ClearCounter(psNuETmr->idx); +} + +static rt_uint32_t nu_etimer_count_get(rt_hwtimer_t *timer) +{ + nu_etimer_t psNuETmr = NU_TIMER_DEVICE(timer); + RT_ASSERT(psNuETmr != RT_NULL); + + return ETIMER_GetCounter(psNuETmr->idx); +} + +static rt_err_t nu_etimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args) +{ + rt_err_t ret = RT_EOK; + nu_etimer_t psNuETmr = NU_TIMER_DEVICE(timer); + RT_ASSERT(psNuETmr != RT_NULL); + + switch (cmd) + { + case HWTIMER_CTRL_FREQ_SET: + { + uint32_t clk; + uint32_t pre; + + clk = ETIMER_GetModuleClock(psNuETmr->idx); + pre = clk / *((uint32_t *)args) - 1; + ETIMER_SET_PRESCALE_VALUE(psNuETmr->idx, pre); + *((uint32_t *)args) = clk / (pre + 1) ; + } + break; + + case HWTIMER_CTRL_STOP: + ETIMER_Stop(psNuETmr->idx); + break; + + default: + ret = RT_EINVAL; + break; + } + + return -(ret); +} + +/** + * All UART interrupt service routine + */ +static void nu_etimer_isr(int vector, void *param) +{ + nu_etimer_t psNuETmr = NU_TIMER_DEVICE(param); + RT_ASSERT(psNuETmr != RT_NULL); + + if (ETIMER_GetIntFlag(psNuETmr->idx)) + { + ETIMER_ClearIntFlag(psNuETmr->idx); + rt_device_hwtimer_isr(&psNuETmr->parent); + } +} + +int rt_hw_etimer_init(void) +{ + int i; + rt_err_t ret = RT_EOK; + for (i = (ETIMER_START + 1); i < ETIMER_CNT; i++) + { + nu_sys_ipclk_enable(nu_etimer_arr[i].clkidx); + + nu_sys_ip_reset(nu_etimer_arr[i].rstidx); + + /* Register Etimer information. */ + nu_etimer_arr[i].parent.info = &nu_etimer_info; + + /* Register Etimer operation. */ + nu_etimer_arr[i].parent.ops = &nu_etimer_ops; + + /* Register Etimer interrupt service routine. */ + rt_hw_interrupt_install(nu_etimer_arr[i].irqn, nu_etimer_isr, &nu_etimer_arr[i], nu_etimer_arr[i].name); + + /* Register RT hwtimer device. */ + ret = rt_device_hwtimer_register(&nu_etimer_arr[i].parent, nu_etimer_arr[i].name, &nu_etimer_arr[i]); + RT_ASSERT(ret == RT_EOK); + } + return 0; +} + +INIT_BOARD_EXPORT(rt_hw_etimer_init); + +#endif //#if defined(BSP_USING_ETIMER) && defined(RT_USING_HWTIMER) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_etimer_capture.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_etimer_capture.c new file mode 100644 index 0000000000..93184c689f --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_etimer_capture.c @@ -0,0 +1,226 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-1-28 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_TIMER_CAPTURE) + +#include +#include "NuMicro.h" +#include + +/* Private define ---------------------------------------------------------------*/ + +/* Timer prescale setting. Since it will affect the pulse width of measure, it is recommended to set to 2. */ +#define PSC_DIV (2) + +#define NU_TCAP_DEVICE(etimer) (nu_capture_t*)(etimer) +enum +{ + TCAP_START = -1, +#if defined(BSP_USING_ETIMER0_CAPTURE) + TCAP0_IDX, +#endif +#if defined(BSP_USING_ETIMER1_CAPTURE) + TCAP1_IDX, +#endif +#if defined(BSP_USING_ETIMER2_CAPTURE) + TCAP2_IDX, +#endif +#if defined(BSP_USING_ETIMER3_CAPTURE) + TCAP3_IDX, +#endif + TCAP_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ +typedef struct _timer +{ + struct rt_inputcapture_device parent; + char *name; + uint32_t idx; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + + uint32_t u32CurrentCnt; +} nu_capture_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us); + +/* Public functions -------------------------------------------------------------*/ + +/* Private variables ------------------------------------------------------------*/ +static nu_capture_t nu_etcap_arr [] = +{ +#if defined(BSP_USING_ETIMER0_CAPTURE) + { + .name = "etmr0i0", + .idx = 0, + .irqn = IRQ_ETMR0, + .rstidx = ETIMER0RST, + .clkidx = ETIMER0CKEN, + }, +#endif +#if defined(BSP_USING_ETIMER1_CAPTURE) + { + .name = "etmr1i0", + .idx = 1, + .irqn = IRQ_ETMR1, + .rstidx = ETIMER1RST, + .clkidx = ETIMER1CKEN, + }, +#endif +#if defined(BSP_USING_ETIMER2_CAPTURE) + { + .name = "etmr2i0", + .idx = 2, + .irqn = IRQ_ETMR2, + .rstidx = ETIMER2RST, + .clkidx = ETIMER2CKEN, + }, +#endif +#if defined(BSP_USING_ETIMER3_CAPTURE) + { + .name = "etmr3i0", + .idx = 3, + .irqn = IRQ_ETMR3, + .rstidx = ETIMER3RST, + .clkidx = ETIMER3CKEN, + }, +#endif +}; + +static struct rt_inputcapture_ops nu_capture_ops = +{ + .init = nu_capture_init, + .open = nu_capture_open, + .close = nu_capture_close, + .get_pulsewidth = nu_capture_get_pulsewidth, +}; + +/* Functions define ------------------------------------------------------------*/ +static void nu_tcap_isr(int vector, void *param) +{ + nu_capture_t *psNuTCap = NU_TCAP_DEVICE(param); + + RT_ASSERT(psNuTCap != RT_NULL); + + ETIMER_ClearCaptureIntFlag(psNuTCap->idx); + + /* Report caputring data and level. */ + psNuTCap->u32CurrentCnt = ETIMER_GetCaptureData(psNuTCap->idx); + rt_hw_inputcapture_isr(&psNuTCap->parent, ETIMER_GetCaptureFallingEdgeFlag(psNuTCap->idx)); +} + +static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us) +{ + nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture); + + RT_ASSERT(inputcapture != RT_NULL); + RT_ASSERT(pulsewidth_us != RT_NULL); + + *pulsewidth_us = psNuTCap->u32CurrentCnt / PSC_DIV; + + return RT_EOK; +} + +static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture) +{ + nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture); + + RT_ASSERT(inputcapture != RT_NULL); + + nu_sys_ipclk_enable(psNuTCap->clkidx); + nu_sys_ip_reset(psNuTCap->rstidx); + + return RT_EOK; +} + +static uint8_t cal_time_prescale(nu_capture_t *psNuTCap) +{ + uint32_t u32Clk = ETIMER_GetModuleClock(psNuTCap->idx); + + /* 1 tick = 1/PSC_DIV us */ + return (u32Clk / 1000000 / PSC_DIV) - 1; +} + +static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture) +{ + nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture); + + RT_ASSERT(inputcapture != RT_NULL); + + /* Enable Timer Interrupt */ + rt_hw_interrupt_umask(psNuTCap->irqn); + + /* Clear counter before openning. */ + ETIMER_ClearCounter(psNuTCap->idx); + + ETIMER_Open(psNuTCap->idx, ETIMER_CONTINUOUS_MODE, 1); + + ETIMER_SET_PRESCALE_VALUE(psNuTCap->idx, cal_time_prescale(psNuTCap)); + + ETIMER_SET_CMP_VALUE(psNuTCap->idx, 0xFFFFFF); + + ETIMER_EnableCapture(psNuTCap->idx, ETIMER_CAPTURE_COUNTER_RESET_MODE, ETIMER_CAPTURE_RISING_THEN_FALLING_EDGE); + + ETIMER_EnableCaptureInt(psNuTCap->idx); + + ETIMER_Start(psNuTCap->idx); + + return RT_EOK; +} + +static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture) +{ + nu_capture_t *psNuTCap = NU_TCAP_DEVICE(inputcapture); + + RT_ASSERT(inputcapture != RT_NULL); + + ETIMER_Stop(psNuTCap->idx); + + ETIMER_DisableCaptureInt(psNuTCap->idx); + + ETIMER_Close(psNuTCap->idx); + + rt_hw_interrupt_mask(psNuTCap->irqn); + + return RT_EOK; +} + +/* Init and register timer capture */ +static int nu_etimer_capture_device_init(void) +{ + int i; + + for (i = (TCAP_START + 1); i < TCAP_CNT; i++) + { + /* Register operations */ + nu_etcap_arr[i].parent.ops = &nu_capture_ops; + + /* Install ISR */ + rt_hw_interrupt_install(nu_etcap_arr[i].irqn, nu_tcap_isr, &nu_etcap_arr[i], nu_etcap_arr[i].name); + + /* Register inputcapture device */ + rt_device_inputcapture_register(&nu_etcap_arr[i].parent, nu_etcap_arr[i].name, &nu_etcap_arr[i]); + } + + return 0; +} +INIT_DEVICE_EXPORT(nu_etimer_capture_device_init); + +#endif //#if defined(BSP_USING_ETIMER_CAPTURE) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_ge2d.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_ge2d.c new file mode 100644 index 0000000000..1b1522fcbf --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_ge2d.c @@ -0,0 +1,3470 @@ +/**************************************************************************//** +* @file 2d.c +* @brief N9H30 GE2D driver source file +* +* @note +* SPDX-License-Identifier: Apache-2.0 +* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "rtthread.h" + +#include "NuMicro.h" +#include + +//#define DEBUG +//#define DEF_COND_WAIT 1 + +static unsigned int GFX_BPP; +static unsigned int GFX_WIDTH; +static unsigned int GFX_HEIGHT; + +#if defined ( __GNUC__ ) && !(__CC_ARM) + __attribute__((aligned(32))) static void *GFX_START_ADDR = NULL; + __attribute__((aligned(32))) static void *GFX_PAT_ADDR = NULL; +#else + static __align(32) void *GFX_START_ADDR = NULL; + static __align(32) void *GFX_PAT_ADDR = NULL; +#endif + +#define PN 1 // Quadrant 1 +#define NN 2 // Quadrant 2 +#define NP 3 // Quadrant 3 +#define PP 4 // Quadrant 4 + +#define ABS(x) (((x)>0)?(x):-(x)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +/* octant code of line drawing */ + +#define XpYpXl (0<<1) // XY octant position is 1~3 in Control register +#define XpYpYl (1<<1) +#define XpYmXl (2<<1) +#define XpYmYl (3<<1) +#define XmYpXl (4<<1) +#define XmYpYl (5<<1) +#define XmYmXl (6<<1) +#define XmYmYl (7<<1) + +static MONOPATTERN MonoPatternData[6] = +{ + {0x00000000, 0xff000000}, // HS_HORIZONTAL + {0x08080808, 0x08080808}, // HS_VERTICAL + {0x80402010, 0x08040201}, // HS_FDIAGONAL + {0x01020408, 0x10204080}, // HS_BDIAGONAL + {0x08080808, 0xff080808}, // HS_CROSS + {0x81422418, 0x18244281} // HS_DIAGCROSS +}; + +static char _DrawMode = MODE_OPAQUE; +static UINT32 _ColorKey = COLOR_KEY; +static UINT32 _ColorKeyMask = 0xFFFFFF; + +static BOOL _EnableAlpha = FALSE; +static int _AlphaKs, _AlphaKd; +static BOOL _ClipEnable = FALSE; +static BOOL _OutsideClip = FALSE; +static UINT32 _ClipTL, _ClipBR; +static int _PatternType; + +static unsigned char FontData8[256][8] = +{ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //0 + {0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E}, //1 + {0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E}, //2 + {0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00}, //3 + {0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00}, //4 + {0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x92, 0x10, 0x7C}, //5 + {0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C}, //6 + {0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00}, //7 + {0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF}, //8 + {0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00}, //9 + {0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF}, //10 + {0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78}, //11 + {0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18}, //12 + {0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0}, //13 + {0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0}, //14 + {0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99}, //15 + {0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00}, //16 + {0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00}, //17 + {0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18}, //18 + {0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00}, //19 + {0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00}, //20 + {0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0x86, 0xFC}, //21 + {0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00}, //22 + {0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF}, //23 + {0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00}, //24 + {0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00}, //25 + {0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00}, //26 + {0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00}, //27 + {0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00}, //28 + {0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00}, //29 + {0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00}, //30 + {0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00}, //31 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //32 + {0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, //33 + {0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00}, //34 + {0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00}, //35 + {0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00}, //36 + {0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00}, //37 + {0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00}, //38 + {0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, //39 + {0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00}, //40 + {0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00}, //41 + {0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, //42 + {0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00}, //43 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30}, //44 + {0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00}, //45 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00}, //46 + {0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00}, //47 + {0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00}, //48 + {0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00}, //49 + {0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00}, //50 + {0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00}, //51 + {0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00}, //52 + {0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00}, //53 + {0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00}, //54 + {0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00}, //55 + {0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00}, //56 + {0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00}, //57 + {0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00}, //58 + {0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30}, //59 + {0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00}, //60 + {0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00}, //61 + {0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00}, //62 + {0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00}, //63 + {0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00}, //64 + {0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00}, //65 + {0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00}, //66 + {0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00}, //67 + {0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00}, //68 + {0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00}, //69 + {0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00}, //70 + {0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3A, 0x00}, //71 + {0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00}, //72 + {0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00}, //73 + {0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00}, //74 + {0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00}, //75 + {0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00}, //76 + {0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00}, //77 + {0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00}, //78 + {0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00}, //79 + {0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00}, //80 + {0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0x7C, 0x0E, 0x00}, //81 + {0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00}, //82 + {0x7C, 0xC6, 0xE0, 0x78, 0x0E, 0xC6, 0x7C, 0x00}, //83 + {0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00}, //84 + {0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00}, //85 + {0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00}, //86 + {0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00}, //87 + {0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00}, //88 + {0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00}, //89 + {0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00}, //90 + {0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00}, //91 + {0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00}, //92 + {0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00}, //93 + {0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00}, //94 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, //95 + {0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, //96 + {0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00}, //97 + {0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00}, //98 + {0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00}, //99 + {0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00}, //100 + {0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00}, //101 + {0x38, 0x6C, 0x64, 0xF0, 0x60, 0x60, 0xF0, 0x00}, //102 + {0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8}, //103 + {0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00}, //104 + {0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00}, //105 + {0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78}, //106 + {0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00}, //107 + {0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00}, //108 + {0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xD6, 0x00}, //109 + {0x00, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00}, //110 + {0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00}, //111 + {0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0}, //112 + {0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E}, //113 + {0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00}, //114 + {0x00, 0x00, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00}, //115 + {0x10, 0x30, 0xFC, 0x30, 0x30, 0x34, 0x18, 0x00}, //116 + {0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00}, //117 + {0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00}, //118 + {0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00}, //119 + {0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00}, //120 + {0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8}, //121 + {0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00}, //122 + {0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00}, //123 + {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, //124 + {0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00}, //125 + {0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //126 + {0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00}, //127 + {0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x0C, 0x06, 0x7C}, //128 + {0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00}, //129 + {0x1C, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00}, //130 + {0x7E, 0x81, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0x00}, //131 + {0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00}, //132 + {0xE0, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00}, //133 + {0x30, 0x30, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00}, //134 + {0x00, 0x00, 0x7C, 0xC6, 0xC0, 0x78, 0x0C, 0x38}, //135 + {0x7E, 0x81, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00}, //136 + {0xCC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00}, //137 + {0xE0, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00}, //138 + {0xCC, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00}, //139 + {0x7C, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00}, //140 + {0xE0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00}, //141 + {0xC6, 0x10, 0x7C, 0xC6, 0xFE, 0xC6, 0xC6, 0x00}, //142 + {0x30, 0x30, 0x00, 0x78, 0xCC, 0xFC, 0xCC, 0x00}, //143 + {0x1C, 0x00, 0xFC, 0x60, 0x78, 0x60, 0xFC, 0x00}, //144 + {0x00, 0x00, 0x7F, 0x0C, 0x7F, 0xCC, 0x7F, 0x00}, //145 + {0x3E, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCE, 0x00}, //146 + {0x78, 0x84, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00}, //147 + {0x00, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00}, //148 + {0x00, 0xE0, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00}, //149 + {0x78, 0x84, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00}, //150 + {0x00, 0xE0, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00}, //151 + {0x00, 0xCC, 0x00, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8}, //152 + {0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00}, //153 + {0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00}, //154 + {0x18, 0x18, 0x7E, 0xC0, 0xC0, 0x7E, 0x18, 0x18}, //155 + {0x38, 0x6C, 0x64, 0xF0, 0x60, 0xE6, 0xFC, 0x00}, //156 + {0xCC, 0xCC, 0x78, 0x30, 0xFC, 0x30, 0xFC, 0x30}, //157 + {0xF8, 0xCC, 0xCC, 0xFA, 0xC6, 0xCF, 0xC6, 0xC3}, //158 + {0x0E, 0x1B, 0x18, 0x3C, 0x18, 0x18, 0xD8, 0x70}, //159 + {0x1C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00}, //160 + {0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00}, //161 + {0x00, 0x1C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00}, //162 + {0x00, 0x1C, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00}, //163 + {0x00, 0xF8, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0x00}, //164 + {0xFC, 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00}, //165 + {0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00}, //166 + {0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00}, //167 + {0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3C, 0x00}, //168 + {0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x00, 0x00}, //169 + {0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x00, 0x00}, //170 + {0xC6, 0xCC, 0xD8, 0x36, 0x6B, 0xC2, 0x84, 0x0F}, //171 + {0xC3, 0xC6, 0xCC, 0xDB, 0x37, 0x6D, 0xCF, 0x03}, //172 + {0x18, 0x00, 0x18, 0x18, 0x3C, 0x3C, 0x18, 0x00}, //173 + {0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00}, //174 + {0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00}, //175 + {0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88}, //176 + {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA}, //177 + {0xDB, 0xF6, 0xDB, 0x6F, 0xDB, 0x7E, 0xD7, 0xED}, //178 + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //179 + {0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18}, //180 + {0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18}, //181 + {0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36}, //182 + {0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36}, //183 + {0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18}, //184 + {0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36}, //185 + {0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //186 + {0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36}, //187 + {0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00}, //188 + {0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00}, //189 + {0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00}, //190 + {0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18}, //191 + {0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00}, //192 + {0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00}, //193 + {0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18}, //194 + {0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18}, //195 + {0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00}, //196 + {0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18}, //197 + {0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18}, //198 + {0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36}, //199 + {0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00}, //200 + {0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36}, //201 + {0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00}, //202 + {0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36}, //203 + {0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36}, //204 + {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00}, //205 + {0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36}, //206 + {0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00}, //207 + {0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00}, //208 + {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18}, //209 + {0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36}, //210 + {0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00}, //211 + {0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00}, //212 + {0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18}, //213 + {0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36}, //214 + {0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36}, //215 + {0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18}, //216 + {0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00}, //217 + {0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18}, //218 + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //219 + {0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, //220 + {0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0}, //221 + {0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F}, //222 + {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, //223 + {0x00, 0x00, 0x76, 0xDC, 0xC8, 0xDC, 0x76, 0x00}, //224 + {0x00, 0x78, 0xCC, 0xF8, 0xCC, 0xF8, 0xC0, 0xC0}, //225 + {0x00, 0xFC, 0xCC, 0xC0, 0xC0, 0xC0, 0xC0, 0x00}, //226 + {0x00, 0x00, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x00}, //227 + {0xFC, 0xCC, 0x60, 0x30, 0x60, 0xCC, 0xFC, 0x00}, //228 + {0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0x70, 0x00}, //229 + {0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0}, //230 + {0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x00}, //231 + {0xFC, 0x30, 0x78, 0xCC, 0xCC, 0x78, 0x30, 0xFC}, //232 + {0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x6C, 0x38, 0x00}, //233 + {0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x6C, 0xEE, 0x00}, //234 + {0x1C, 0x30, 0x18, 0x7C, 0xCC, 0xCC, 0x78, 0x00}, //235 + {0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x00, 0x00}, //236 + {0x06, 0x0C, 0x7E, 0xDB, 0xDB, 0x7E, 0x60, 0xC0}, //237 + {0x38, 0x60, 0xC0, 0xF8, 0xC0, 0x60, 0x38, 0x00}, //238 + {0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x00}, //239 + {0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00}, //240 + {0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00}, //241 + {0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xFC, 0x00}, //242 + {0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xFC, 0x00}, //243 + {0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18}, //244 + {0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70}, //245 + {0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00}, //246 + {0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00}, //247 + {0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00}, //248 + {0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00}, //249 + {0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00}, //250 + {0x0F, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C}, //251 + {0x58, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00}, //252 + {0x70, 0x98, 0x30, 0x60, 0xF8, 0x00, 0x00, 0x00}, //253 + {0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00}, //254 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} //255 +}; + +static unsigned char FontData16[256][16] = +{ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //0 + {0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00}, //1 + {0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00}, //2 + {0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, //3 + {0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, //4 + {0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x99, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00}, //5 + {0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00}, //6 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //7 + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //8 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00}, //9 + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //10 + {0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00}, //11 + {0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, //12 + {0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00}, //13 + {0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00}, //14 + {0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, //15 + {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00}, //16 + {0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00}, //17 + {0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00}, //18 + {0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, //19 + {0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00}, //20 + {0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00}, //21 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00}, //22 + {0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00}, //23 + {0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, //24 + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00}, //25 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //26 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //27 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //28 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6C, 0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //29 + {0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00}, //30 + {0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, //31 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //32 + {0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, //33 + {0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //34 + {0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00}, //35 + {0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, 0x00}, //36 + {0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, 0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00}, //37 + {0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //38 + {0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //39 + {0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00}, //40 + {0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00}, //41 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //42 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //43 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00}, //44 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //45 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, //46 + {0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00}, //47 + {0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xCE, 0xD6, 0xD6, 0xE6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //48 + {0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00}, //49 + {0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00}, //50 + {0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //51 + {0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00}, //52 + {0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x0E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //53 + {0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //54 + {0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00}, //55 + {0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //56 + {0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00}, //57 + {0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, //58 + {0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00}, //59 + {0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00}, //60 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //61 + {0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00}, //62 + {0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, //63 + {0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00}, //64 + {0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00}, //65 + {0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00}, //66 + {0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00}, //67 + {0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00}, //68 + {0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00}, //69 + {0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00}, //70 + {0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE, 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00}, //71 + {0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00}, //72 + {0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00}, //73 + {0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00}, //74 + {0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00}, //75 + {0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00}, //76 + {0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00}, //77 + {0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00}, //78 + {0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00}, //79 + {0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00}, //80 + {0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00}, //81 + {0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00}, //82 + {0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //83 + {0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00}, //84 + {0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //85 + {0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00}, //86 + {0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00}, //87 + {0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x6C, 0x38, 0x38, 0x6C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00}, //88 + {0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00}, //89 + {0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00}, //90 + {0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00}, //91 + {0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00}, //92 + {0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00}, //93 + {0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //94 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00}, //95 + {0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //96 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //97 + {0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0xDC, 0x00, 0x00, 0x00, 0x00}, //98 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //99 + {0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //100 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //101 + {0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00}, //102 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00}, //103 + {0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00}, //104 + {0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00}, //105 + {0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00}, //106 + {0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00}, //107 + {0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00}, //108 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00}, //109 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, //110 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //111 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00}, //112 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00}, //113 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00}, //114 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //115 + {0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, //116 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //117 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00}, //118 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00}, //119 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00}, //120 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00}, //121 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00}, //122 + {0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00}, //123 + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, //124 + {0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00}, //125 + {0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //126 + {0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00}, //127 + {0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x0C, 0x06, 0x7C, 0x00, 0x00}, //128 + {0x00, 0x00, 0xCC, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //129 + {0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //130 + {0x00, 0x10, 0x38, 0x6C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //131 + {0x00, 0x00, 0xCC, 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //132 + {0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //133 + {0x00, 0x38, 0x6C, 0x38, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //134 + {0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x66, 0x3C, 0x0C, 0x06, 0x3C, 0x00, 0x00, 0x00}, //135 + {0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //136 + {0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //137 + {0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //138 + {0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00}, //139 + {0x00, 0x18, 0x3C, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00}, //140 + {0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00}, //141 + {0x00, 0xC6, 0xC6, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00}, //142 + {0x38, 0x6C, 0x38, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00}, //143 + {0x18, 0x30, 0x60, 0x00, 0xFE, 0x66, 0x60, 0x7C, 0x60, 0x60, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00}, //144 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x76, 0x36, 0x7E, 0xD8, 0xD8, 0x6E, 0x00, 0x00, 0x00, 0x00}, //145 + {0x00, 0x00, 0x3E, 0x6C, 0xCC, 0xCC, 0xFE, 0xCC, 0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00, 0x00, 0x00}, //146 + {0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //147 + {0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //148 + {0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //149 + {0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //150 + {0x00, 0x60, 0x30, 0x18, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //151 + {0x00, 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00}, //152 + {0x00, 0xC6, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00}, //153 + {0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //154 + {0x00, 0x18, 0x18, 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, //155 + {0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xE6, 0xFC, 0x00, 0x00, 0x00, 0x00}, //156 + {0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, //157 + {0x00, 0xF8, 0xCC, 0xCC, 0xF8, 0xC4, 0xCC, 0xDE, 0xCC, 0xCC, 0xCC, 0xC6, 0x00, 0x00, 0x00, 0x00}, //158 + {0x00, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0x70, 0x00, 0x00}, //159 + {0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //160 + {0x00, 0x0C, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00}, //161 + {0x00, 0x18, 0x30, 0x60, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //162 + {0x00, 0x18, 0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00}, //163 + {0x00, 0x00, 0x76, 0xDC, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, //164 + {0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00}, //165 + {0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //166 + {0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //167 + {0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xC0, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00}, //168 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00}, //169 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, //170 + {0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x60, 0xCE, 0x93, 0x06, 0x0C, 0x1F, 0x00, 0x00}, //171 + {0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xCE, 0x9A, 0x3F, 0x06, 0x0F, 0x00, 0x00}, //172 + {0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00}, //173 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //174 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //175 + {0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44}, //176 + {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA}, //177 + {0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77}, //178 + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //179 + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //180 + {0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //181 + {0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //182 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //183 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //184 + {0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //185 + {0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //186 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //187 + {0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //188 + {0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //189 + {0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //190 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //191 + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //192 + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //193 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //194 + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //195 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //196 + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //197 + {0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //198 + {0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //199 + {0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //200 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //201 + {0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //202 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //203 + {0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //204 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //205 + {0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //206 + {0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //207 + {0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //208 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //209 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //210 + {0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //211 + {0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //212 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //213 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //214 + {0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}, //215 + {0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //216 + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //217 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //218 + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //219 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //220 + {0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0}, //221 + {0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F}, //222 + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //223 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0xD8, 0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00}, //224 + {0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xC6, 0xFC, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0, 0xC0, 0x00, 0x00}, //225 + {0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00}, //226 + {0x00, 0x00, 0x00, 0x00, 0x80, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00}, //227 + {0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00}, //228 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00}, //229 + {0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00}, //230 + {0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, //231 + {0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00}, //232 + {0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00}, //233 + {0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x6C, 0x6C, 0x6C, 0xEE, 0x00, 0x00, 0x00, 0x00}, //234 + {0x00, 0x00, 0x1E, 0x30, 0x18, 0x0C, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00}, //235 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //236 + {0x00, 0x00, 0x00, 0x03, 0x06, 0x7E, 0xCF, 0xDB, 0xF3, 0x7E, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00}, //237 + {0x00, 0x00, 0x1C, 0x30, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00, 0x00}, //238 + {0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00}, //239 + {0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00}, //240 + {0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00}, //241 + {0x00, 0x00, 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00}, //242 + {0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00}, //243 + {0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, //244 + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00}, //245 + {0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, //246 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //247 + {0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //248 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //249 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //250 + {0x00, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00}, //251 + {0x00, 0xD8, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //252 + {0x00, 0x70, 0x98, 0x30, 0x60, 0xC8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //253 + {0x00, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00}, //254 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} //255 +}; + +struct nu_ge2d +{ + char *name; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + + rt_mutex_t lock; +#if defined(DEF_COND_WAIT) + rt_sem_t signal; +#endif +}; +typedef struct nu_ge2d *nu_ge2d_t; + +static struct nu_ge2d g_sNuGe2d = +{ + .name = "GE2D", + .irqn = IRQ_GE2D, + .rstidx = GE2DRST, + .clkidx = GE2DCKEN +}; + +#define NU_GE2D_LOCK() { \ + rt_err_t result = rt_mutex_take(g_sNuGe2d.lock, RT_WAITING_FOREVER); \ + RT_ASSERT(result == RT_EOK); \ + } + +#define NU_GE2D_UNLOCK() { \ + rt_err_t result = rt_mutex_release(g_sNuGe2d.lock); \ + RT_ASSERT(result == RT_EOK); \ + } + +#if defined(DEF_COND_WAIT) +#define NU_GE2D_COND_WAIT() { \ + rt_err_t result = rt_sem_take(g_sNuGe2d.signal, RT_WAITING_FOREVER); \ + RT_ASSERT(result == RT_EOK); \ + } + +#define NU_GE2D_SIGNAL() { \ + rt_err_t result = rt_sem_release(g_sNuGe2d.signal); \ + RT_ASSERT(result == RT_EOK); \ + } +/* Interrupt Service Routine for GE2D */ +static void nu_ge2d_isr(int vector, void *param) +{ + /* Clear interrupt status. */ + outpw(REG_GE2D_INTSTS, 1); + + /* Signal condition-waiting to resume caller. */ + NU_GE2D_SIGNAL(); +} +#else +#define NU_GE2D_COND_WAIT() { \ + while ((inpw(REG_GE2D_INTSTS) & 0x01) == 0); \ + outpw(REG_GE2D_INTSTS, 1); \ + } +#define NU_GE2D_SIGNAL() +#endif + + +static unsigned long make_color(int color) +{ + UINT32 r, g, b; + + if (GFX_BPP == 8) + { + r = (color & 0x00e00000) >> 16; // 3 bits + g = (color & 0x0000e000) >> 11; // 3 bits + b = (color & 0x000000c0) >> 6; // 2 bits + return (r | g | b); + } + else if (GFX_BPP == 16) + { + r = (color & 0x00f80000) >> 8; // 5 bits + g = (color & 0x0000fc00) >> 5; // 6 bits + b = (color & 0x000000f8) >> 3; // 5 bits + return (r | g | b); + } + else return (UINT32)color; +} +/// @endcond /* HIDDEN_SYMBOLS */ + +/** + * @brief Clear the on screen buffer with a specified color. + * @param[in] color clear with this color. + * @return none + */ +void ge2dClearScreen(int color) +{ + UINT32 cmd32; + UINT32 color32, dest_pitch, dest_dimension; + + color32 = make_color(color); + + cmd32 = 0xcc430040; + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_BGCOLR, color32); // fill with background color + + dest_pitch = GFX_WIDTH << 16; // pitch in pixels + outpw(REG_GE2D_SDPITCH, dest_pitch); + + outpw(REG_GE2D_DSTSPA, 0); // starts from (0,0) + + dest_dimension = GFX_HEIGHT << 16 | GFX_WIDTH; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Set output data mask. + * @param[in] mask is mask value + * @return none + */ +void ge2dSetWriteMask(int mask) +{ + outpw(REG_GE2D_WRPLNMSK, make_color(mask)); +} + +/** + * @brief Set source origin starting address. + * @param[in] ptr pointer of start address + * @return none + */ +void ge2dSetSourceOriginStarting(void *ptr) +{ + outpw(REG_GE2D_XYSORG, (int)ptr); +} + +/** + * @brief Set destination origin starting address. + * @param[in] ptr pointer of start address + * @return none + */ +void ge2dSetDestinationOriginStarting(void *ptr) +{ + outpw(REG_GE2D_XYDORG, (int)ptr); +} + + +/** + * @brief Reset graphics engine. + * @param none + * @return none + */ +void ge2dReset(void) +{ + outpw(REG_GE2D_MISCTL, 0x40); // FIFO reset + outpw(REG_GE2D_MISCTL, 0x00); + + outpw(REG_GE2D_MISCTL, 0x80); // Engine reset + outpw(REG_GE2D_MISCTL, 0x00); +} + +/** + * @brief Graphics engine initialization. + * @param[in] bpp bit per pixel + * @param[in] width is width of display memory + * @param[in] height is height of display memory + * @param[in] destination is pointer of destination buffer address + * @return none + */ +void ge2dInit(int bpp, int width, int height, void *destination) +{ + UINT32 data32; + + if (destination == NULL) + return; + + NU_GE2D_LOCK(); + + ge2dReset(); + + GFX_WIDTH = width; + GFX_HEIGHT = height; + + _DrawMode = MODE_TRANSPARENT; + _ColorKey = COLOR_KEY; + _ColorKeyMask = 0xFFFFFF; + + GFX_START_ADDR = (void *)destination; + + if (GFX_BPP != bpp) + { + GFX_BPP = bpp; + if (GFX_PAT_ADDR != NULL) + { + rt_free_align(GFX_PAT_ADDR); + GFX_PAT_ADDR = RT_NULL; + } + if (GFX_PAT_ADDR == NULL) + { + uint32_t u32Size = (8 * 8 * (GFX_BPP / 8)) * 2; + GFX_PAT_ADDR = (void *)rt_malloc_align(u32Size, u32Size); + RT_ASSERT(GFX_PAT_ADDR != RT_NULL); + sysprintf("[%s] Allocated %d@0x%08x.\n", __func__, u32Size, GFX_PAT_ADDR); + } + } + + +#ifdef DEBUG + sysprintf("[%s]\n", __func__); + sysprintf("screen width = %d\n", GFX_WIDTH); + sysprintf("screen height = %d\n", GFX_HEIGHT); + sysprintf("screen bpp = %d\n", GFX_BPP); + sysprintf("destination = 0x%x\n", destination); +#endif + + outpw(REG_GE2D_INTSTS, 1); // clear interrupt + outpw(REG_GE2D_PATSA, (unsigned int)GFX_PAT_ADDR); + outpw(REG_GE2D_CTL, 0); // disable interrupt + outpw(REG_GE2D_XYDORG, (unsigned int)GFX_START_ADDR); + outpw(REG_GE2D_XYSORG, (unsigned int)GFX_START_ADDR); + + outpw(REG_GE2D_WRPLNMSK, 0x00ffffff); // write plane mask + + data32 = GE_BPP_8; // default is 8 bpp + + if (GFX_BPP == 16) + { + data32 |= GE_BPP_16; + } + else if (GFX_BPP == 32) + { + data32 |= GE_BPP_32; + } + + outpw(REG_GE2D_MISCTL, data32); +} + +/** + * @brief Reset FIFO of graphics engine. + * @param none + * @return none + */ +void ge2dResetFIFO(void) +{ + UINT32 temp32; + + temp32 = inpw(REG_GE2D_MISCTL); + temp32 |= 0x00000040; + outpw(REG_GE2D_MISCTL, temp32); + temp32 &= 0xffffffbf; + outpw(REG_GE2D_MISCTL, temp32); +} + +/** + * @brief Set BitBlt drawing mode. + * @param[in] opt is drawing mode + * @param[in] ckey is value of color key + * @param[in] mask is value of color mask + * @return none + */ +void ge2dBitblt_SetDrawMode(int opt, int ckey, int mask) +{ + if (opt == MODE_TRANSPARENT) + { + _DrawMode = MODE_TRANSPARENT; + + _ColorKey = make_color(ckey); + _ColorKeyMask = make_color(mask); + + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + else if (opt == MODE_DEST_TRANSPARENT) + { + _DrawMode = MODE_DEST_TRANSPARENT; + + _ColorKey = make_color(ckey); + _ColorKeyMask = make_color(mask); + + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + else + { + _DrawMode = MODE_OPAQUE; // default is OPAQUE + } +} + +/** + * @brief Set alpha blending programming. + * @param[in] opt is selection for enable or disable + * @param[in] ks is value of alpha blending factor Ks + * @param[in] kd is value of alpha blending factor Kd + * @return none + */ +int ge2dBitblt_SetAlphaMode(int opt, int ks, int kd) +{ + if (ks + kd > 255) + return -1; + + if (opt == 1) + { + _EnableAlpha = TRUE; + _AlphaKs = ks; + _AlphaKd = kd; + } + else + { + _EnableAlpha = FALSE; + } + + return 0; +} + +/** + * @brief Screen-to-Screen BitBlt with SRCCOPY ROP operation. + * @param[in] srcx is source x position + * @param[in] srcy is source y position + * @param[in] destx is destination x position + * @param[in] desty is destination y position + * @param[in] width is display width + * @param[in] height is display width + * @return none + */ +void ge2dBitblt_ScreenToScreen(int srcx, int srcy, int destx, int desty, int width, int height) +{ + UINT32 cmd32, pitch, dest_start, src_start, dimension; + UINT32 data32, alpha; + +#ifdef DEBUG + sysprintf("screen_to_screen_blt():\n"); + sysprintf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty); + sysprintf("width=%d height=%d\n", width, height); +#endif + + cmd32 = 0xcc430000; + + outpw(REG_GE2D_CTL, cmd32); + + if (srcx > destx) //+X + { + if (srcy > desty) //+Y + { + } + else //-Y + { + cmd32 |= 0x08; + srcy = srcy + height - 1; + desty = desty + height - 1; + } + } + else //-X + { + if (srcy > desty) //+Y + { + cmd32 |= 0x04; // 010 + srcx = srcx + width - 1; + destx = destx + width - 1; + } + else //-Y + { + cmd32 |= 0xc; // 110 + srcx = srcx + width - 1; + destx = destx + width - 1; + srcy = srcy + height - 1; + desty = desty + height - 1; + } + } + +#ifdef DEBUG + sysprintf("new srcx=%d srcy=%d\n", srcx, srcy); + sysprintf("new destx=%d desty=%d\n", destx, desty); +#endif + + outpw(REG_GE2D_CTL, cmd32); + + pitch = GFX_WIDTH << 16 | GFX_WIDTH; + outpw(REG_GE2D_SDPITCH, pitch); + + src_start = srcy << 16 | srcx; + outpw(REG_GE2D_SRCSPA, src_start); + + dest_start = desty << 16 | destx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dimension); + + // + // force to use the same starting address + // + outpw(REG_GE2D_XYSORG, (int)GFX_START_ADDR); + outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR); //smf + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + if (_DrawMode == MODE_TRANSPARENT) + { + cmd32 |= 0x00008000; // color transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + else if (_DrawMode == MODE_DEST_TRANSPARENT) + { + cmd32 |= 0x00009000; // destination pixels control transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + + if (_EnableAlpha) + { + cmd32 |= 0x00200000; + outpw(REG_GE2D_CTL, cmd32); + + data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff; + alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd); + data32 |= (alpha << 16); + + outpw(REG_GE2D_MISCTL, data32); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Screen-to-Screen BitBlt with ROP option. + * @param[in] srcx is source x position + * @param[in] srcy is source y position + * @param[in] destx is destination x position + * @param[in] desty is destination y position + * @param[in] width is display width + * @param[in] height is display width + * @param[in] rop is rop option + * @return none + */ +void ge2dBitblt_ScreenToScreenRop(int srcx, int srcy, int destx, int desty, int width, int height, int rop) +{ + UINT32 cmd32, pitch, dest_start, src_start, dimension; + UINT32 data32, alpha; + +#ifdef DEBUG + sysprintf("screen_to_screen_rop_blt():\n"); + sysprintf("ROP=0x%x\n", rop); + sysprintf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty); + sysprintf("width=%d height=%d\n", width, height); +#endif + + cmd32 = 0x00430000 | (rop << 24); + + if (_PatternType == TYPE_MONO) + { + cmd32 |= 0x00000010; // default is TYPE_COLOR + } + + outpw(REG_GE2D_CTL, cmd32); + + if (srcx > destx) //+X + { + if (srcy > desty) //+Y + { + } + else //-Y + { + cmd32 |= 0x08; + srcy = srcy + height - 1; + desty = desty + height - 1; + } + } + else //-X + { + if (srcy > desty) //+Y + { + cmd32 |= 0x04; // 010 + srcx = srcx + width - 1; + destx = destx + width - 1; + } + else //-Y + { + cmd32 |= 0xc; // 110 + srcx = srcx + width - 1; + destx = destx + width - 1; + srcy = srcy + height - 1; + desty = desty + height - 1; + } + } + +#ifdef DEBUG + sysprintf("new srcx=%d srcy=%d\n", srcx, srcy); + sysprintf("new destx=%d desty=%d\n", destx, desty); +#endif + + outpw(REG_GE2D_CTL, cmd32); + + pitch = GFX_WIDTH << 16 | GFX_WIDTH; // pitch in pixel + outpw(REG_GE2D_SDPITCH, pitch); + + src_start = srcy << 16 | srcx; + outpw(REG_GE2D_SRCSPA, src_start); + + dest_start = desty << 16 | destx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dimension); + + // + // force to use the same starting address + // + outpw(REG_GE2D_XYSORG, (int)GFX_START_ADDR); + outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR); //smf + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + if (_DrawMode == MODE_TRANSPARENT) + { + cmd32 |= 0x00008000; // color transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + else if (_DrawMode == MODE_DEST_TRANSPARENT) + { + cmd32 |= 0x00009000; + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + + if (_EnableAlpha) + { + cmd32 |= 0x00200000; + outpw(REG_GE2D_CTL, cmd32); + + data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff; + alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd); + data32 |= (alpha << 16); + + outpw(REG_GE2D_MISCTL, data32); + } + + if ((rop == 0x00) || (rop == 0xff)) + { + cmd32 = (cmd32 & 0xffff0fff) | 0x00009000; + outpw(REG_GE2D_CTL, cmd32); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Source to destination BitBlt with SRCCOPY ROP operation. + * @param[in] srcx is source x position + * @param[in] srcy is source y position + * @param[in] destx is destination x position + * @param[in] desty is destination y position + * @param[in] width is display width + * @param[in] height is display width + * @param[in] srcpitch is source pixel pitch + * @param[in] destpitch is destination pixel pitch + * @return none + * @note before calling this function, it would set the source and destination origin starting place + */ +void ge2dBitblt_SourceToDestination(int srcx, int srcy, int destx, int desty, int width, int height, int srcpitch, int destpitch) +{ + UINT32 cmd32, pitch, dest_start, src_start, dimension; + UINT32 data32, alpha; + +#ifdef DEBUG + sysprintf("source_to_destination_blt():\n"); + sysprintf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty); + sysprintf("width=%d height=%d\n", width, height); +#endif + + cmd32 = 0xcc430000; + + outpw(REG_GE2D_CTL, cmd32); + + if (srcx > destx) //+X + { + if (srcy > desty) //+Y + { + } + else //-Y + { + cmd32 |= 0x08; + srcy = srcy + height - 1; + desty = desty + height - 1; + } + } + else //-X + { + if (srcy > desty) //+Y + { + cmd32 |= 0x04; // 010 + srcx = srcx + width - 1; + destx = destx + width - 1; + } + else //-Y + { + cmd32 |= 0xc; // 110 + srcx = srcx + width - 1; + destx = destx + width - 1; + srcy = srcy + height - 1; + desty = desty + height - 1; + } + } + +#ifdef DEBUG + sysprintf("new srcx=%d srcy=%d\n", srcx, srcy); + sysprintf("new destx=%d desty=%d\n", destx, desty); +#endif + + outpw(REG_GE2D_CTL, cmd32); + + pitch = destpitch << 16 | srcpitch; // pitch in pixel, back | GFX_WIDTH ?? + outpw(REG_GE2D_SDPITCH, pitch); + + src_start = srcy << 16 | srcx; + outpw(REG_GE2D_SRCSPA, src_start); + + dest_start = desty << 16 | destx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dimension); + + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + if (_DrawMode == MODE_TRANSPARENT) + { + cmd32 |= 0x00008000; // color transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + else if (_DrawMode == MODE_DEST_TRANSPARENT) + { + cmd32 |= 0x00009000; // destination pixels control transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + + if (_EnableAlpha) + { + cmd32 |= 0x00200000; + outpw(REG_GE2D_CTL, cmd32); + + data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff; + alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd); + data32 |= (alpha << 16); + + outpw(REG_GE2D_MISCTL, data32); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Set the clip rectangle. (top-left to down-right). + * @param[in] x1 is top-left x position + * @param[in] y1 is top-left y position + * @param[in] x2 is down-right x position + * @param[in] y2 is down-right y position + * @return none + */ +void ge2dClip_SetClip(int x1, int y1, int x2, int y2) +{ + +#ifdef DEBUG + sysprintf("set_clip(): (%d,%d)-(%d,%d)\n", x1, y1, x2, y2); +#endif + + if ((x1 >= 0) && (y1 >= 0) && (x2 >= 0) && (y2 >= 0)) + { + if ((x2 > x1) && (y2 > y1)) + { + _ClipEnable = TRUE; + /* hardware clipper not includes last pixel */ + x2++; + y2++; + _ClipTL = (UINT32)((y1 << 16) | x1); + _ClipBR = (UINT32)((y2 << 16) | x2); + } + else + { + _ClipEnable = FALSE; + } + } + else + { + _ClipEnable = FALSE; + } +} + +/** + * @brief Set the clip to inside clip or outside clip. + * @param[in] opt is option for setting clip inside or outside, value could be + * - \ref MODE_INSIDE_CLIP + * - \ref MODE_OUTSIDE_CLIP + * @return none + */ +void ge2dClip_SetClipMode(int opt) +{ + _OutsideClip = (opt == 0) ? FALSE : TRUE; + + if (_OutsideClip) + { +#ifdef DEBUG + sysprintf("set_clip_mode(): OUTSIDE\n"); +#endif + } + else + { +#ifdef DEBUG + sysprintf("set_clip_mode(): INSIDE\n"); +#endif + } +} + +/** + * @brief Draw an one-pixel rectangle frame. + * @param[in] x1 is top-left x position + * @param[in] y1 is top-left y position + * @param[in] x2 is down-right x position + * @param[in] y2 is down-right y position + * @param[in] color is color of this rectangle + * @param[in] opt is draw option, value could be + * - 0: rectangle + * - 1: diagonal + * @return none + */ +void ge2dDrawFrame(int x1, int y1, int x2, int y2, int color, int opt) +{ + UINT32 dest_pitch, dest_start, dest_dimension; + UINT32 color32; + +#ifdef DEBUG + sysprintf("draw_frame():\n"); + sysprintf("(%d,%d)-(%d,%d)\n", x1, y1, x2, y2); + sysprintf("color=0x%x opt=%d\n", color, opt); +#endif + + /* + ** The opt==1 case must be specially handled. + */ + + if (opt == 0) + { + outpw(REG_GE2D_CTL, 0xcccb0000); // rectangle + } + else + { + outpw(REG_GE2D_CTL, 0xcccf0000); // diagonal + } + +#ifdef DEBUG + sysprintf("(%d,%d)-(%d,%d)\n", x1, y1, x2, y2); +#endif + + color32 = make_color(color); + outpw(REG_GE2D_FGCOLR, color32); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = y1 << 16 | x1; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = (y2 - y1) << 16 | (x2 - x1); + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + outpw(REG_GE2D_MISCTL, inpw(REG_GE2D_MISCTL)); // address caculation + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Draw an solid rectangle line. + * @param[in] x1 is top-left x position + * @param[in] y1 is top-left y position + * @param[in] x2 is down-right x position + * @param[in] y2 is down-right y position + * @param[in] color is color of this line + * @return none + */ +void ge2dLine_DrawSolidLine(int x1, int y1, int x2, int y2, int color) +{ + int abs_X, abs_Y, min, max; + UINT32 step_constant, initial_error, direction_code; + UINT32 cmd32, dest_pitch, dest_start; + +#ifdef DEBUG + sysprintf("draw_solid_line():\n"); + sysprintf("(%d,%d)-(%d,%d)\n", x1, y1, x2, y2); + sysprintf("color=0x%x\n", color); +#endif + + abs_X = ABS(x2 - x1); //absolute value + abs_Y = ABS(y2 - y1); //absolute value + if (abs_X > abs_Y) // X major + { + max = abs_X; + min = abs_Y; + + step_constant = (((UINT32)(2 * (min - max))) << 16) | (UINT32)(2 * min); + initial_error = (((UINT32)(2 * (min) - max)) << 16) | (UINT32)(max); + + if (x2 > x1) // +X direction + { + if (y2 > y1) // +Y direction + direction_code = XpYpXl; + else // -Y direction + direction_code = XpYmXl; + } + else // -X direction + { + if (y2 > y1) // +Y direction + direction_code = XmYpXl; + else // -Y direction + direction_code = XmYmXl; + } + } + else // Y major + { + max = abs_Y; + min = abs_X; + + step_constant = (((UINT32)(2 * (min - max))) << 16) | (UINT32)(2 * min); + initial_error = (((UINT32)(2 * (min) - max)) << 16) | (UINT32)(max); + + if (x2 > x1) // +X direction + { + if (y2 > y1) // +Y direction + direction_code = XpYpYl; + else // -Y direction + direction_code = XpYmYl; + } + else // -X direction + { + if (y2 > y1) // +Y direction + direction_code = XmYpYl; + else // -Y direction + direction_code = XmYmYl; + } + } + + outpw(REG_GE2D_BETSC, step_constant); + outpw(REG_GE2D_BIEPC, initial_error); + + cmd32 = 0x008b0000 | direction_code; + + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_BGCOLR, make_color(color)); + outpw(REG_GE2D_FGCOLR, make_color(color)); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR); + + dest_start = y1 << 16 | x1; + outpw(REG_GE2D_DSTSPA, dest_start); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Draw an solid rectangle line with assigned RGB565 color + * @param[in] x1 is top-left x position + * @param[in] y1 is top-left y position + * @param[in] x2 is down-right x position + * @param[in] y2 is down-right y position + * @param[in] color is color of this line + * @return none + */ +void ge2dLine_DrawSolidLine_RGB565(int x1, int y1, int x2, int y2, int color) +{ + int abs_X, abs_Y, min, max; + UINT32 step_constant, initial_error, direction_code; + UINT32 cmd32, dest_pitch, dest_start; + +#ifdef DEBUG + sysprintf("draw_solid_line():\n"); + sysprintf("(%d,%d)-(%d,%d)\n", x1, y1, x2, y2); + sysprintf("color=0x%x\n", color); +#endif + + abs_X = ABS(x2 - x1); //absolute value + abs_Y = ABS(y2 - y1); //absolute value + if (abs_X > abs_Y) // X major + { + max = abs_X; + min = abs_Y; + + step_constant = (((UINT32)(2 * (min - max))) << 16) | (UINT32)(2 * min); + initial_error = (((UINT32)(2 * (min) - max)) << 16) | (UINT32)(max); + + if (x2 > x1) // +X direction + { + if (y2 > y1) // +Y direction + direction_code = XpYpXl; + else // -Y direction + direction_code = XpYmXl; + } + else // -X direction + { + if (y2 > y1) // +Y direction + direction_code = XmYpXl; + else // -Y direction + direction_code = XmYmXl; + } + } + else // Y major + { + max = abs_Y; + min = abs_X; + + step_constant = (((UINT32)(2 * (min - max))) << 16) | (UINT32)(2 * min); + initial_error = (((UINT32)(2 * (min) - max)) << 16) | (UINT32)(max); + + if (x2 > x1) // +X direction + { + if (y2 > y1) // +Y direction + direction_code = XpYpYl; + else // -Y direction + direction_code = XpYmYl; + } + else // -X direction + { + if (y2 > y1) // +Y direction + direction_code = XmYpYl; + else // -Y direction + direction_code = XmYmYl; + } + } + + outpw(REG_GE2D_BETSC, step_constant); + outpw(REG_GE2D_BIEPC, initial_error); + + cmd32 = 0x008b0000 | direction_code; + + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_BGCOLR, color); + outpw(REG_GE2D_FGCOLR, color); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR); + + dest_start = y1 << 16 | x1; + outpw(REG_GE2D_DSTSPA, dest_start); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + + +/** + * @brief Draw a styled line. + * @param[in] x1 is top-left x position + * @param[in] y1 is top-left y position + * @param[in] x2 is down-right x position + * @param[in] y2 is down-right y position + * @param[in] style is style of line pattern + * @param[in] fgcolor is color of foreground + * @param[in] bkcolor is color of background + * @param[in] draw_mode is transparent is enable or not + * @return none + */ +void ge2dLine_DrawStyledLine(int x1, int y1, int x2, int y2, int style, int fgcolor, int bkcolor, int draw_mode) +{ + int abs_X, abs_Y, min, max; + UINT32 step_constant, initial_error, direction_code; + UINT32 cmd32, dest_pitch, dest_start; + UINT32 temp32, line_control_code; + + abs_X = ABS(x2 - x1); + abs_Y = ABS(y2 - y1); + if (abs_X > abs_Y) // X major + { + max = abs_X; + min = abs_Y; + + step_constant = (((UINT32)(2 * (min - max))) << 16) | (UINT32)(2 * min); + initial_error = (((UINT32)(2 * min - max)) << 16) | (UINT32)(max); + + if (x2 > x1) // +X direction + { + if (y2 > y1) // +Y direction + direction_code = XpYpXl; + else // -Y direction + direction_code = XpYmXl; + } + else // -X direction + { + if (y2 > y1) // +Y direction + direction_code = XmYpXl; + else // -Y direction + direction_code = XmYmXl; + } + } + else // Y major + { + max = abs_Y; + min = abs_X; + + step_constant = (((UINT32)(2 * (min - max))) << 16) | (UINT32)(2 * min); + initial_error = (((UINT32)(2 * min - max)) << 16) | (UINT32)(max); + + if (x2 > x1) // +X direction + { + if (y2 > y1) // +Y direction + direction_code = XpYpYl; + else // -Y direction + direction_code = XpYmYl; + } + else // -X direction + { + if (y2 > y1) // +Y direction + direction_code = XmYpYl; + else // -Y direction + direction_code = XmYmYl; + } + } + + outpw(REG_GE2D_BETSC, step_constant); + outpw(REG_GE2D_BIEPC, initial_error); + + cmd32 = 0x009b0000 | direction_code; // styled line + if (draw_mode == MODE_TRANSPARENT) + { + cmd32 |= 0x00008000; // default is MODE_OPAQUE + } + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_BGCOLR, make_color(bkcolor)); + outpw(REG_GE2D_FGCOLR, make_color(fgcolor)); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR); + + dest_start = y1 << 16 | x1; + outpw(REG_GE2D_DSTSPA, dest_start); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + line_control_code = style; + temp32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff; + temp32 = (line_control_code << 16) | temp32; + + outpw(REG_GE2D_MISCTL, temp32); // address caculation + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Draw a styled line using RGB565 color + * @param[in] x1 is top-left x position + * @param[in] y1 is top-left y position + * @param[in] x2 is down-right x position + * @param[in] y2 is down-right y position + * @param[in] style is style of line pattern + * @param[in] fgcolor is color of foreground + * @param[in] bkcolor is color of background + * @param[in] draw_mode is transparent is enable or not + * @return none + */ +void ge2dLine_DrawStyledLine_RGB565(int x1, int y1, int x2, int y2, int style, int fgcolor, int bkcolor, int draw_mode) +{ + int abs_X, abs_Y, min, max; + UINT32 step_constant, initial_error, direction_code; + UINT32 cmd32, dest_pitch, dest_start; + UINT32 temp32, line_control_code; + + abs_X = ABS(x2 - x1); + abs_Y = ABS(y2 - y1); + if (abs_X > abs_Y) // X major + { + max = abs_X; + min = abs_Y; + + step_constant = (((UINT32)(2 * (min - max))) << 16) | (UINT32)(2 * min); + initial_error = (((UINT32)(2 * min - max)) << 16) | (UINT32)(max); + + if (x2 > x1) // +X direction + { + if (y2 > y1) // +Y direction + direction_code = XpYpXl; + else // -Y direction + direction_code = XpYmXl; + } + else // -X direction + { + if (y2 > y1) // +Y direction + direction_code = XmYpXl; + else // -Y direction + direction_code = XmYmXl; + } + } + else // Y major + { + max = abs_Y; + min = abs_X; + + step_constant = (((UINT32)(2 * (min - max))) << 16) | (UINT32)(2 * min); + initial_error = (((UINT32)(2 * min - max)) << 16) | (UINT32)(max); + + if (x2 > x1) // +X direction + { + if (y2 > y1) // +Y direction + direction_code = XpYpYl; + else // -Y direction + direction_code = XpYmYl; + } + else // -X direction + { + if (y2 > y1) // +Y direction + direction_code = XmYpYl; + else // -Y direction + direction_code = XmYmYl; + } + } + + outpw(REG_GE2D_BETSC, step_constant); + outpw(REG_GE2D_BIEPC, initial_error); + + cmd32 = 0x009b0000 | direction_code; // styled line + if (draw_mode == MODE_TRANSPARENT) + { + cmd32 |= 0x00008000; // default is MODE_OPAQUE + } + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_BGCOLR, bkcolor); + outpw(REG_GE2D_FGCOLR, fgcolor); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR); + + dest_start = y1 << 16 | x1; + outpw(REG_GE2D_DSTSPA, dest_start); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + line_control_code = style; + temp32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff; + temp32 = (line_control_code << 16) | temp32; + + outpw(REG_GE2D_MISCTL, temp32); // address caculation + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Rectangle solid color fill with foreground color. + * @param[in] dx x position + * @param[in] dy y position + * @param[in] width is display width + * @param[in] height is display height + * @param[in] color is color of foreground + * @return none + */ +void ge2dFill_Solid(int dx, int dy, int width, int height, int color) +{ + UINT32 cmd32, color32; + UINT32 dest_start, dest_pitch, dest_dimension; + +#ifdef DEBUG + sysprintf("solid_fill() begin\n"); + sysprintf("(%d,%d)-(%d,%d)\n", dx, dy, dx + width - 1, dy + height - 1); + sysprintf("color=0x%x\n", color); +#endif + + color32 = make_color(color); + cmd32 = 0xcc430060; + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_FGCOLR, color32); // fill with foreground color + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = dy << 16 | dx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Rectangle solid color fill with RGB565 color. + * @param[in] dx x position + * @param[in] dy y position + * @param[in] width is display width + * @param[in] height is display height + * @param[in] color is RGB565 color of foreground + * @return none + */ +void ge2dFill_Solid_RGB565(int dx, int dy, int width, int height, int color) +{ + UINT32 cmd32; + UINT32 dest_start, dest_pitch, dest_dimension; + +#ifdef DEBUG + sysprintf("solid_fill()\n"); + sysprintf("(%d,%d)-(%d,%d)\n", dx, dy, dx + width - 1, dy + height - 1); + sysprintf("color=0x%x\n", color); +#endif + + cmd32 = 0xcc430060; + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_FGCOLR, color); // fill with foreground color + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = dy << 16 | dx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Rectangle solid color fill with background color. + * @param[in] dx x position + * @param[in] dy y position + * @param[in] width is display width + * @param[in] height is display height + * @param[in] color is color of background + * @return none + */ +void ge2dFill_SolidBackground(int dx, int dy, int width, int height, int color) +{ + UINT32 cmd32, color32; + UINT32 dest_start, dest_pitch, dest_dimension; + +#ifdef DEBUG + sysprintf("solid_fill_back()\n"); + sysprintf("(%d,%d)-(%d,%d)\n", dx, dy, dx + width - 1, dy + height - 1); + sysprintf("color=0x%x\n", color); +#endif + + color32 = make_color(color); + + cmd32 = 0xcc430040; + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_BGCOLR, color32); // fill with foreground color + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = dy << 16 | dx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Rectangle fill with 8x8 color pattern. + * @param[in] dx x position + * @param[in] dy y position + * @param[in] width is display width + * @param[in] height is display height + * @return none + * @note The color pattern data is stored in the off-screen buffer. + */ +void ge2dFill_ColorPattern(int dx, int dy, int width, int height) +{ + UINT32 cmd32; + UINT32 dest_start, dest_pitch, dest_dimension; + +#ifdef DEBUG + sysprintf("color_pattern_fill()\n"); + sysprintf("(%d,%d)-(%d,%d)\n", dx, dy, dx + width - 1, dy + height - 1); + sysprintf("pattern offset (%d,%d)\n", dx % 8, dy % 8); +#endif + + cmd32 = 0xf0430000; + outpw(REG_GE2D_CTL, cmd32); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = dy << 16 | dx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Rectangle fill with 8x8 mono pattern. + * @param[in] dx x position + * @param[in] dy y position + * @param[in] width is display width + * @param[in] height is display height + * @param[in] opt is transparent is enable or not + * @return none + */ +void ge2dFill_MonoPattern(int dx, int dy, int width, int height, int opt) +{ + UINT32 cmd32; + UINT32 dest_start, dest_pitch, dest_dimension; + +#ifdef DEBUG + sysprintf("mono_pattern_fill()\n"); + sysprintf("(%d,%d)-(%d,%d)\n", dx, dy, dx + width - 1, dy + height - 1); +#endif + + cmd32 = 0xf0430010; + if (opt == MODE_TRANSPARENT) + { + cmd32 |= 0x00006000; + } + outpw(REG_GE2D_CTL, cmd32); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = dy << 16 | dx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Rectangle fill with 8x8 color pattern. + * @param[in] sx x position + * @param[in] sy y position + * @param[in] width is display width + * @param[in] height is display height + * @param[in] rop is ROP operation code + * @return none + */ +void ge2dFill_ColorPatternROP(int sx, int sy, int width, int height, int rop) +{ + UINT32 cmd32; + UINT32 dest_start, dest_pitch, dest_dimension; + +#ifdef DEBUG + sysprintf("color_pattern_fill()\n"); + sysprintf("(%d,%d)-(%d,%d)\n", sx, sy, sx + width - 1, sy + height - 1); + sysprintf("pattern offset (%d,%d)\n", sx % 8, sy % 8); +#endif + + cmd32 = 0x00430000 | (rop << 24); + outpw(REG_GE2D_CTL, cmd32); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = sy << 16 | sx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Rectangle fill with 8x8 mono pattern. + * @param[in] sx x position + * @param[in] sy y position + * @param[in] width is display width + * @param[in] height is display height + * @param[in] opt is transparent is enable or not + * @param[in] rop is ROP operation code + * @return none + */ +void ge2dFill_MonoPatternROP(int sx, int sy, int width, int height, int rop, int opt) +{ + UINT32 cmd32; + UINT32 dest_start, dest_pitch, dest_dimension; + +#ifdef DEBUG + sysprintf("mono_pattern_fill()\n"); + sysprintf("(%d,%d)-(%d,%d)\n", sx, sy, sx + width - 1, sy + height - 1); +#endif + + cmd32 = 0x00430010 | (rop << 24); + if (opt == MODE_TRANSPARENT) + { + cmd32 |= 0x00006000; + } + outpw(REG_GE2D_CTL, cmd32); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = sy << 16 | sx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief TileBLT function. + * @param[in] srcx source x position + * @param[in] srcy source y position + * @param[in] destx destination x position + * @param[in] desty destination y position + * @param[in] width is display width + * @param[in] height is display height + * @param[in] x_count is tile count for x-axis + * @param[in] y_count is tile count for y-axis + * @return none + */ +void ge2dFill_TileBlt(int srcx, int srcy, int destx, int desty, int width, int height, int x_count, int y_count) +{ + UINT32 cmd32, pitch, dest_start, src_start, dimension; + UINT32 tile_ctl; + +#ifdef DEBUG + sysprintf("tile_blt_image()\n"); + sysprintf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty); + sysprintf("width=%d height=%d\n", width, height); + sysprintf("%dx%d grids\n", x_count, y_count); +#endif + + if (x_count > 0) x_count--; + if (y_count > 0) y_count--; + + cmd32 = 0xcc430400; // b10 is the tile control + + outpw(REG_GE2D_CTL, cmd32); + + pitch = GFX_WIDTH << 16 | GFX_WIDTH; // pitch in pixel + outpw(REG_GE2D_SDPITCH, pitch); + + src_start = srcy << 16 | srcx; // redundancy ?? + outpw(REG_GE2D_SRCSPA, src_start); // redundancy ?? + + dest_start = desty << 16 | destx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dimension); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + tile_ctl = (y_count << 8) | (x_count); + outpw(REG_GE2D_TCNTVHSF, tile_ctl); + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Host-to-Screen BitBlt with SRCCOPY (through data port) + * @param[in] x x position + * @param[in] y y position + * @param[in] width is display width + * @param[in] height is display height + * @param[in] buf is pointer of HostBLT data + * @return none + */ +void ge2dHostBlt_Write(int x, int y, int width, int height, void *buf) +{ + UINT32 cmd32, dest_pitch, dest_start, dest_dimension; + int transfer_count, i, j; + UINT32 *ptr32, data32; + +#ifdef DEBUG + sysprintf("host_write_blt()\n"); + sysprintf("(%d,%d)-(%d,%d)\n", x, y, x + width - 1, y + height - 1); + sysprintf("width=%d height=%d\n", width, height); +#endif + + cmd32 = 0xcc430020; + + outpw(REG_GE2D_CTL, cmd32); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = y << 16 | x; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + outpw(REG_GE2D_TRG, 1); + + ptr32 = (UINT32 *)buf; + for (i = 0; i < height; i++) // 120 + { + transfer_count = (width * (GFX_BPP / 8) + 3) / 4; // 4-byte count + + while (transfer_count >= 8) + { + while ((inpw(REG_GE2D_MISCTL) & 0x00000800) == 0); // check empty + for (j = 0; j < 8; j++) + { + data32 = *ptr32++; + outpw(REG_GE2D_GEHBDW0, data32); + } + transfer_count -= 8; + } + + if (transfer_count > 0) + { + while ((inpw(REG_GE2D_MISCTL) & 0x00000800) == 0); // check empty + for (j = 0; j < transfer_count; j++) + { + data32 = *ptr32++; + outpw(REG_GE2D_GEHBDW0, data32); + } + } + } + + while ((inpw(REG_GE2D_INTSTS) & 0x01) == 0); // wait for command complete + outpw(REG_GE2D_INTSTS, 1); // clear interrupt status +} + +/** + * @brief Screen-to-Host BitBlt with SRCCOPY (through data port). + * @param[in] x x position + * @param[in] y y position + * @param[in] width is display width + * @param[in] height is display height + * @param[in] buf is pointer of HostBLT data + * @return none + */ +void ge2dHostBlt_Read(int x, int y, int width, int height, void *buf) +{ + UINT32 cmd32, dest_pitch, dest_start, dest_dimension; + int transfer_count, i, j; + UINT32 *ptr32; + +#ifdef DEBUG + sysprintf("host_read_blt()\n"); + sysprintf("(%d,%d)-(%d,%d)\n", x, y, x + width - 1, y + height - 1); + sysprintf("width=%d height=%d\n", width, height); +#endif + + cmd32 = 0xcc430001; + + outpw(REG_GE2D_CTL, cmd32); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = y << 16 | x; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + outpw(REG_GE2D_TRG, 1); + + ptr32 = (UINT32 *)buf; + for (i = 0; i < height; i++) + { + transfer_count = (width * (GFX_BPP / 8) + 3) / 4; // 4-byte count + + while (transfer_count >= 8) + { + while ((inpw(REG_GE2D_MISCTL) & 0x00000400) == 0); + for (j = 0; j < 8; j++) + { + *ptr32++ = inpw(REG_GE2D_GEHBDW0); + } + transfer_count -= 8; + } + + if (transfer_count > 0) + { + while (((inpw(REG_GE2D_MISCTL) & 0x0000f000) >> 12) != transfer_count); + for (j = 0; j < transfer_count; j++) + { + *ptr32++ = inpw(REG_GE2D_GEHBDW0); + } + } + } + + while ((inpw(REG_GE2D_INTSTS) & 0x01) == 0); // wait for command complete + + outpw(REG_GE2D_INTSTS, 1); // clear interrupt status +} + +/** + * @brief Host-to-Screen SpriteBlt with SRCCOPY. + * @param[in] x x position + * @param[in] y y position + * @param[in] width is display width + * @param[in] height is display height + * @param[in] buf is pointer of HostBLT data + * @return none + */ +void ge2dHostBlt_Sprite(int x, int y, int width, int height, void *buf) +{ + UINT32 cmd32, dest_pitch, dest_start, dest_dimension; + int transfer_count, i, j; + UINT32 *ptr32, data32, alpha; + +#ifdef DEBUG + sysprintf("host_sprite_blt()\n"); + sysprintf("(%d,%d)-(%d,%d)\n", x, y, x + width - 1, y + height - 1); +#endif + + cmd32 = 0xcc430020; + + outpw(REG_GE2D_CTL, cmd32); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = y << 16 | x; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + if (_DrawMode == MODE_TRANSPARENT) + { + cmd32 |= 0x00008000; // color transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + else if (_DrawMode == MODE_DEST_TRANSPARENT) + { + cmd32 |= 0x00009000; + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + + if (_EnableAlpha) + { + cmd32 |= 0x00200000; + outpw(REG_GE2D_CTL, cmd32); + + data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff; + alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd); + data32 |= (alpha << 16); + + outpw(REG_GE2D_MISCTL, data32); + } + + outpw(REG_GE2D_TRG, 1); + + ptr32 = (UINT32 *)buf; + for (i = 0; i < height; i++) + { + transfer_count = width * (GFX_BPP / 8) / 4; // 4-byte count + + while (transfer_count > 8) + { + while ((inpw(REG_GE2D_MISCTL) & 0x00000800) == 0); // check empty + for (j = 0; j < 8; j++) + { + data32 = *ptr32++; + outpw(REG_GE2D_GEHBDW0, data32); + } + transfer_count -= 8; + } + + if (transfer_count > 0) + { + while ((inpw(REG_GE2D_MISCTL) & 0x00000800) == 0); // check empty + for (j = 0; j < transfer_count; j++) + { + data32 = *ptr32++; + outpw(REG_GE2D_GEHBDW0, data32); + } + } + } + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Captured the specified photo data from display memory, then displayed on display memory by rotation angle + * @param[in] srcx source x position + * @param[in] srcy source y position + * @param[in] destx destination x position + * @param[in] desty destination y position + * @param[in] width is display width + * @param[in] height is display height + * @param[in] ctl is drawing direction + * @return none + */ +void ge2dRotation(int srcx, int srcy, int destx, int desty, int width, int height, int ctl) +{ + UINT32 cmd32, dest_start, src_start, dimension, pitch; + void *tmpscreen, *orig_dest_start00; + + tmpscreen = (void *)rt_malloc(width * height * GFX_BPP / 8); + +#ifdef DEBUG + sysprintf("rotation_image()\n"); + sysprintf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty); + sysprintf("width=%d height=%d\n", width, height); +#endif + + rt_memset(tmpscreen, 0, width * height * GFX_BPP / 8); + + orig_dest_start00 = (void *)inpw(REG_GE2D_XYDORG); + outpw(REG_GE2D_XYDORG, (int)tmpscreen); //captured photo to another position + outpw(REG_GE2D_XYSORG, (int)GFX_START_ADDR); + + ge2dBitblt_SourceToDestination(srcx, srcy, 0, 0, width, height, GFX_WIDTH, width); + + src_start = dest_start = dimension = cmd32 = pitch = 0; + + outpw(REG_GE2D_XYDORG, (int)orig_dest_start00); + outpw(REG_GE2D_XYSORG, (int)tmpscreen); + + pitch = GFX_WIDTH << 16 | width; + outpw(REG_GE2D_SDPITCH, pitch); + + src_start = 0 << 16 | 0; // captured photo at (0,0) position + outpw(REG_GE2D_SRCSPA, src_start); + + dest_start = desty << 16 | destx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dimension); + + cmd32 = 0xcc030000 | (ctl << 1); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + /* set rotation reference point xy register, then nothing happened */ + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + rt_free(tmpscreen); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief OffScreen-to-OnScreen SpriteBlt with SRCCOPY. + * @param[in] destx destination x position + * @param[in] desty destination y position + * @param[in] sprite_width is sprite width + * @param[in] sprite_height is sprite height + * @param[in] buf is pointer of origin data + * @return none + */ +void ge2dSpriteBlt_Screen(int destx, int desty, int sprite_width, int sprite_height, void *buf) +{ + UINT32 cmd32, pitch, dest_start, src_start, dimension; + UINT32 data32, alpha; + +#ifdef DEBUG + sysprintf("screen_sprite_blt():\n"); + sysprintf("buf=%08x, x=%d y=%d width=%d height=%d\n", buf, destx, desty, sprite_width, sprite_height); +#endif + + cmd32 = 0xcc430000; + + outpw(REG_GE2D_CTL, cmd32); + + pitch = GFX_WIDTH << 16 | sprite_width; // pitch in pixel + outpw(REG_GE2D_SDPITCH, pitch); + + src_start = 0; // start from (0,0) of sprite + outpw(REG_GE2D_SRCSPA, src_start); + + dest_start = desty << 16 | destx; + outpw(REG_GE2D_DSTSPA, dest_start); + + dimension = sprite_height << 16 | sprite_width; + outpw(REG_GE2D_RTGLSZ, dimension); + + outpw(REG_GE2D_XYSORG, (UINT32)buf); + outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + + if (_DrawMode == MODE_TRANSPARENT) + { + cmd32 |= 0x00008000; // color transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + else if (_DrawMode == MODE_DEST_TRANSPARENT) + { + cmd32 |= 0x00009000; // destination pixels control transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + + + if (_EnableAlpha) + { + cmd32 |= 0x00200000; + outpw(REG_GE2D_CTL, cmd32); + + data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff; + alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd); + data32 |= (alpha << 16); + + outpw(REG_GE2D_MISCTL, data32); + } + + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief OffScreen-to-OnScreen SpriteBlt with SRCCOPY. + * @param[in] x x position + * @param[in] y y position + * @param[in] sprite_sx sprite x position + * @param[in] sprite_sy sprite y position + * @param[in] width is width + * @param[in] height is height + * @param[in] sprite_width is sprite width + * @param[in] sprite_height is sprite height + * @param[in] buf is pointer of origin data + * @return none + * @note The sprite starting address can be programmed. + */ +void ge2dSpriteBltx_Screen(int x, int y, int sprite_sx, int sprite_sy, int width, int height, int sprite_width, int sprite_height, void *buf) +{ + UINT32 cmd32, pitch, dest_start, src_start, dimension; + UINT32 data32, alpha; + +#ifdef DEBUG + sysprintf("screen_sprite_bltx(): (%d,%d)\n", x, y); + sysprintf("sprite width=%d height=%d\n", sprite_width, sprite_height); + sysprintf("x=%d y=%d width=%d height=%d\n", sprite_sx, sprite_sy, width, height); +#endif + + cmd32 = 0xcc430000; + + outpw(REG_GE2D_CTL, cmd32); + + pitch = GFX_WIDTH << 16 | sprite_width; // pitch in pixel + outpw(REG_GE2D_SDPITCH, pitch); + + outpw(REG_GE2D_XYSORG, (UINT32)buf); + outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR); + + src_start = sprite_sy << 16 | sprite_sx; + outpw(REG_GE2D_SRCSPA, src_start); + + dest_start = y << 16 | x; + outpw(REG_GE2D_DSTSPA, dest_start); + + dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dimension); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + if (_DrawMode == MODE_TRANSPARENT) + { + cmd32 |= 0x00008000; // color transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + else if (_DrawMode == MODE_DEST_TRANSPARENT) + { + cmd32 |= 0x00009000; // destination pixels control transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + + if (_EnableAlpha) + { + cmd32 |= 0x00200000; + outpw(REG_GE2D_CTL, cmd32); + + data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff; + alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd); + data32 |= (alpha << 16); + + outpw(REG_GE2D_MISCTL, data32); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief OffScreen-to-OnScreen SpriteBlt with ROP. + * @param[in] x x position + * @param[in] y y position + * @param[in] sprite_width is sprite width + * @param[in] sprite_height is sprite height + * @param[in] buf is pointer of origin data + * @param[in] rop is ROP operation code + * @return none + * @note The sprite always starts from (0,0) for the BLT. + */ +void ge2dSpriteBlt_ScreenRop(int x, int y, int sprite_width, int sprite_height, void *buf, int rop) +{ + UINT32 cmd32, pitch, dest_start, src_start, dimension; + UINT32 data32, alpha; + +#ifdef DEBUG + sysprintf("screen_sprite_rop_blt():\n"); + sysprintf("x=%d y=%d width=%d height=%d\n", x, y, sprite_width, sprite_height); + sysprintf("rop=0x%x\n", rop); +#endif + + cmd32 = 0x00430000 | (rop << 24); + + if (_PatternType == TYPE_MONO) + { + cmd32 |= 0x00000010; // default is TYPE_COLOR + } + + outpw(REG_GE2D_CTL, cmd32); + + pitch = GFX_WIDTH << 16 | sprite_width; // pitch in pixel + outpw(REG_GE2D_SDPITCH, pitch); + + src_start = 0; // start from (0,0) of sprite + outpw(REG_GE2D_SRCSPA, src_start); + + dest_start = y << 16 | x; + outpw(REG_GE2D_DSTSPA, dest_start); + + dimension = sprite_height << 16 | sprite_width; + outpw(REG_GE2D_RTGLSZ, dimension); + + outpw(REG_GE2D_XYSORG, (UINT32)buf); + outpw(REG_GE2D_XYDORG, (int) GFX_START_ADDR); //smf + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + if (_DrawMode == MODE_TRANSPARENT) + { + cmd32 |= 0x00008000; // color transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + else if (_DrawMode == MODE_DEST_TRANSPARENT) + { + cmd32 |= 0x00009000; // destination pixels control transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + + if (_EnableAlpha) + { + cmd32 |= 0x00200000; + outpw(REG_GE2D_CTL, cmd32); + + data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff; + alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd); + data32 |= (alpha << 16); + + outpw(REG_GE2D_MISCTL, data32); + } + + if ((rop == 0x00) || (rop == 0xff)) + { + cmd32 = (cmd32 & 0xffff0fff) | 0x00009000; + outpw(REG_GE2D_CTL, cmd32); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief OffScreen-to-OnScreen SpriteBlt with ROP. + * @param[in] x x position + * @param[in] y y position + * @param[in] sprite_sx sprite x position + * @param[in] sprite_sy sprite y position + * @param[in] width is width + * @param[in] height is height + * @param[in] sprite_width is sprite width + * @param[in] sprite_height is sprite height + * @param[in] buf is pointer of origin data + * @param[in] rop is ROP operation code + * @return none + * @note The sprite always starts from (0,0) for the BLT. + */ +void ge2dSpriteBltx_ScreenRop(int x, int y, int sprite_sx, int sprite_sy, int width, int height, int sprite_width, int sprite_height, void *buf, int rop) +{ + UINT32 cmd32, pitch, dest_start, src_start, dimension; + UINT32 data32, alpha; + +#ifdef DEBUG + sysprintf("screen_sprite_rop_bltx():\n"); + sysprintf("x=%d y=%d width=%d height=%d\n", x, y, sprite_width, sprite_height); + sysprintf("rop=0x%x\n", rop); +#endif + + cmd32 = 0x00430000 | (rop << 24); + + if (_PatternType == TYPE_MONO) + { + cmd32 |= 0x00000010; // default is TYPE_COLOR + } + + outpw(REG_GE2D_CTL, cmd32); + + pitch = GFX_WIDTH << 16 | sprite_width; // pitch in pixel + outpw(REG_GE2D_SDPITCH, pitch); + + src_start = sprite_sy << 16 | sprite_sx; + outpw(REG_GE2D_SRCSPA, src_start); + + dest_start = y << 16 | x; + outpw(REG_GE2D_DSTSPA, dest_start); + + dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dimension); + + outpw(REG_GE2D_XYSORG, (UINT32)buf); + outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR); //smf + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + if (_DrawMode == MODE_TRANSPARENT) + { + cmd32 |= 0x00008000; // color transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + else if (_DrawMode == MODE_DEST_TRANSPARENT) + { + cmd32 |= 0x00009000; // destination pixels control transparency + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_TRNSCOLR, _ColorKey); + outpw(REG_GE2D_TCMSK, _ColorKeyMask); + } + + if (_EnableAlpha) + { + cmd32 |= 0x00200000; + outpw(REG_GE2D_CTL, cmd32); + + data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff; + alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd); + data32 |= (alpha << 16); + + outpw(REG_GE2D_MISCTL, data32); + } + + if ((rop == 0x00) || (rop == 0xff)) + { + cmd32 = (cmd32 & 0xffff0fff) | 0x00009000; + outpw(REG_GE2D_CTL, cmd32); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief OffScreen-to-OnScreen TextBLT. + * @param[in] x x position + * @param[in] y y position + * @param[in] width is width + * @param[in] height is height + * @param[in] fore_color is color of foreground + * @param[in] back_color is color of background + * @param[in] opt is transparent is enable or not + * @param[in] buf is pointer of origin data + * @return none + * @note Fetch the monochrome source data from off-screen memory to the desired destination area + */ +void ge2dColorExpansionBlt(int x, int y, int width, int height, int fore_color, int back_color, int opt, void *buf) +{ + UINT32 cmd32, dest_pitch, src_pitch, pitch, dest_start, dest_dimension; + UINT32 fore_color32, back_color32; + + fore_color32 = make_color(fore_color); + back_color32 = make_color(back_color); + + cmd32 = 0xcc430080; + if (opt == MODE_TRANSPARENT) + { + cmd32 |= 0x00004000; // mono transparency + } + + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_FGCOLR, fore_color32); + outpw(REG_GE2D_BGCOLR, back_color32); + + dest_pitch = GFX_WIDTH; // pitch in pixels + src_pitch = width; // pitch in pixels + + pitch = (dest_pitch << 16) | src_pitch; + outpw(REG_GE2D_SDPITCH, pitch); + + outpw(REG_GE2D_XYSORG, (int)buf); + outpw(REG_GE2D_SRCSPA, 0); // always start from (0,0) + + dest_start = y << 16 | x; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + if (_ClipEnable) + { + cmd32 |= 0x00000200; + if (_OutsideClip) + { + cmd32 |= 0x00000100; + } + outpw(REG_GE2D_CTL, cmd32); + outpw(REG_GE2D_CLPBTL, _ClipTL); + outpw(REG_GE2D_CLPBBR, _ClipBR); + } + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Host-to-Screen TextBLT through data port. + * @param[in] x x position + * @param[in] y y position + * @param[in] width is width + * @param[in] height is height + * @param[in] fore_color is color of foreground + * @param[in] back_color is color of background + * @param[in] opt is transparent is enable or not + * @param[in] buf is pointer of origin data + * @return none + */ +void ge2dHostColorExpansionBlt(int x, int y, int width, int height, int fore_color, int back_color, int opt, void *buf) +{ + UINT32 cmd32, dest_pitch, dest_start, dest_dimension; + UINT32 fore_color32, back_color32; + UINT32 *ptr32, data32; + int transfer_count, i, j; + + fore_color32 = make_color(fore_color); + back_color32 = make_color(back_color); + + cmd32 = 0xcc4300a0; + if (opt == MODE_TRANSPARENT) + { + cmd32 |= 0x00004000; // mono transparency + } + + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_FGCOLR, fore_color32); + outpw(REG_GE2D_BGCOLR, back_color32); + + dest_pitch = GFX_WIDTH << 16; // pitch in pixel + outpw(REG_GE2D_SDPITCH, dest_pitch); + + dest_start = y << 16 | x; + outpw(REG_GE2D_DSTSPA, dest_start); + outpw(REG_GE2D_SRCSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + outpw(REG_GE2D_TRG, 1); + + ptr32 = (UINT32 *)buf; + for (i = 0; i < height; i++) + { + transfer_count = (width + 31) / 32; // 32 pixels unit + + while (transfer_count > 8) + { + while ((inpw(REG_GE2D_MISCTL) & 0x00000800) == 0); // check empty + for (j = 0; j < 8; j++) + { + data32 = *ptr32++; + outpw(REG_GE2D_GEHBDW0, data32); + } + transfer_count -= 8; + } + + if (transfer_count > 0) + { + while ((inpw(REG_GE2D_MISCTL) & 0x00000800) == 0); // check empty + for (j = 0; j < transfer_count; j++) + { + data32 = *ptr32++; + outpw(REG_GE2D_GEHBDW0, data32); + } + } + } + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Set the 8x8 mono pattern for following BitBLT functions. + * @param[in] opt is index for build-in pattern + * @param[in] fore_color is color of foreground + * @param[in] back_color is color of background + * @return none + */ +void ge2dInitMonoPattern(int opt, int fore_color, int back_color) +{ + UINT32 color32; + + /* + ** If hardware pattern definition is a little different from software. + ** Need to do the BYTE swap before programming the pattern registers. + */ + + outpw(REG_GE2D_PTNA, MonoPatternData[opt].PatternA); + outpw(REG_GE2D_PTNB, MonoPatternData[opt].PatternB); + + color32 = make_color(fore_color); + outpw(REG_GE2D_FGCOLR, color32); + + color32 = make_color(back_color); + outpw(REG_GE2D_BGCOLR, color32); + + _PatternType = TYPE_MONO; +} + +/** + * @brief Set the 8x8 mono pattern for following BitBLT functions. + * @param[in] PatternA is pattern A + * @param[in] PatternB is pattern B + * @param[in] fore_color is color of foreground + * @param[in] back_color is color of background + * @return none + */ +void ge2dInitMonoInputPattern(UINT32 PatternA, UINT32 PatternB, int fore_color, int back_color) +{ + UINT32 color32; + + /* + ** If hardware pattern definition is a little different from software. + ** Need to do the BYTE swap before programming the pattern registers. + */ + + outpw(REG_GE2D_PTNA, PatternA); + outpw(REG_GE2D_PTNB, PatternB); + + color32 = make_color(fore_color); + outpw(REG_GE2D_FGCOLR, color32); + + color32 = make_color(back_color); + outpw(REG_GE2D_BGCOLR, color32); + + _PatternType = TYPE_MONO; +} + +/** + * @brief Set the 8x8 color pattern for following BitBLT functions. + * @param[in] patformat is format of pattern, value could be + * - \ref RGB888 + * - \ref RGB565 + * - \ref RGB332 + * @param[in] patdata is pointer of input pattern image + * @return none + * @note This function transfers those forms: + * RGB888 to RGB565 or RGB332 + * RGB565 to RGB332 or RGB888 + * RGB332 to RGB565 or RGB888 + */ +void ge2dInitColorPattern(int patformat, void *patdata) +{ + UINT8 *ptr_pat; + UINT8 *ptr8, r8, g8, b8; + UINT16 *ptr16, r16, g16, b16, g16_1, g16_2; + UINT32 *ptr32, r32, g32, b32, g32_1, g32_2; + int idx; + + ptr_pat = (UINT8 *)patdata; + if (patformat == RGB888) + { + if (GFX_BPP == 8) + { + ptr8 = (UINT8 *)GFX_PAT_ADDR; + for (idx = 0; idx < 64; idx++) + { + b8 = (UINT8)(*ptr_pat++) & 0xc0; // 2 bits + g8 = (UINT8)(*ptr_pat++) & 0xe0; // 3 bits + r8 = (UINT8)(*ptr_pat++) & 0xe0; // 3 bits + ptr_pat++; + *ptr8++ = r8 | (g8 >> 3) | (b8 >> 6); + } + } + else if (GFX_BPP == 16) + { + ptr16 = (UINT16 *)GFX_PAT_ADDR; + for (idx = 0; idx < 64; idx++) + { + b16 = (UINT16)(*ptr_pat++) & 0x000f8; // 5 bits + g16 = (UINT16)(*ptr_pat++) & 0x000fc; // 6 bits + r16 = (UINT16)(*ptr_pat++) & 0x000f8; // 5 bits + ptr_pat++; + *ptr16++ = (r16 << 8) | (g16 << 3) | (b16 >> 3); + } + } + else if (GFX_BPP == 32) + { + ptr32 = (UINT32 *)GFX_PAT_ADDR; + for (idx = 0; idx < 64; idx++) + { + b32 = (UINT32)(*ptr_pat++); + g32 = (UINT32)(*ptr_pat++); + r32 = (UINT32)(*ptr_pat++); + ptr_pat++; + *ptr32++ = (r32 << 16) | (g32 << 8) | b32; + } + } + } + else if (patformat == RGB565) + { + if (GFX_BPP == 8) + { + ptr8 = (UINT8 *)GFX_PAT_ADDR; + + for (idx = 0; idx < 64; idx++) + { + b8 = (UINT8)(*ptr_pat++) & 0x00018; // 2 bits + g8 = (UINT8)(*ptr_pat) & 0x00007; // 3 bits + r8 = (UINT8)(*ptr_pat++) & 0x000e0; // 3bits + *ptr8++ = r8 | (g8 << 2) | (b8 >> 3); + } + } + else if (GFX_BPP == 16) + { + ptr16 = (UINT16 *)GFX_PAT_ADDR; + + for (idx = 0; idx < 64; idx++) + { + *ptr16++ = (*ptr_pat) | (*(ptr_pat + 1)) << 8; + ptr_pat += 2; + } + } + else if (GFX_BPP == 32) + { + ptr32 = (UINT32 *)GFX_PAT_ADDR; + + for (idx = 0; idx < 64; idx++) + { + b32 = (UINT8)(*ptr_pat) & 0x1f; // 5 bits + g32_1 = (UINT8)(*ptr_pat++) & 0xe0; // front 3 bits + g32_2 = (UINT8)(*ptr_pat) & 0x07; // back 3 bits + g32 = ((g32_1 >> 5) | (g32_2 << 3)) << 2; + r32 = (UINT8)(*ptr_pat++) & 0xf8; // 5 bits + *ptr32++ = 0 << 24 | (r32 << 16) | (g32 << 8) | (b32 << 3); + } + } + } + else if (patformat == RGB332) + { + if (GFX_BPP == 8) + { + ptr8 = (UINT8 *)GFX_PAT_ADDR; + + for (idx = 0; idx < 64; idx++) + { + *ptr8++ = *ptr_pat; + ptr_pat++; + } + } + else if (GFX_BPP == 16) + { + ptr16 = (UINT16 *)GFX_PAT_ADDR; + + for (idx = 0; idx < 64; idx++) + { + r16 = (UINT8)(*ptr_pat) & 0xe0; // 3 bits + g16_1 = (UINT8)(*ptr_pat) & 0x10; + g16_2 = (UINT8)(*ptr_pat) & 0x0c; + g16 = (g16_1 >> 2) | (g16_2 >> 2); + b16 = (UINT8)(*ptr_pat++) & 0x3; // 2 bits + *ptr16++ = (r16 << 8) | (g16 << 8) | (b16 << 3); + } + } + else if (GFX_BPP == 32) + { + ptr32 = (UINT32 *)GFX_PAT_ADDR; + + for (idx = 0; idx < 64; idx++) + { + r32 = (UINT8)(*ptr_pat) & 0xe0; // 3 bits + g32 = (UINT8)(*ptr_pat) & 0x1c; // 3 bits + b32 = (UINT8)(*ptr_pat++) & 0x3; // 2 bits + *ptr32++ = 0 << 24 | (r32 << 15) | (g32 << 11) | (b32 << 6); + } + } + } + + _PatternType = TYPE_COLOR; +} + +/** + * @brief Display font character. + * @param[in] x x position + * @param[in] y y position + * @param[in] asc_code is ascii code + * @param[in] fore_color is color of foreground + * @param[in] back_color is color of background + * @param[in] draw_mode is transparent is enable or not + * @param[in] font_id is selection of 8x8 or 8x16 font + * @return none + */ +void ge2dFont_PutChar(int x, int y, char asc_code, int fore_color, int back_color, int draw_mode, int font_id) +{ + int cmd32, dest_pitch, src_pitch, pitch, dest_start, dest_dimension; + UINT32 width, height; + UINT32 fore_color32, back_color32; + UINT8 *fptr; + UINT8 *temp_buf[32 * 32], *ptr8; + int idx; + + fore_color32 = make_color(fore_color); + back_color32 = make_color(back_color); + + cmd32 = 0xcc430080; + + if (draw_mode == MODE_TRANSPARENT) + { + cmd32 |= 0x00004000; // mono transparency + } + + outpw(REG_GE2D_CTL, cmd32); + + outpw(REG_GE2D_FGCOLR, fore_color32); + outpw(REG_GE2D_BGCOLR, back_color32); + + if (font_id == F8x16) + { + fptr = (UINT8 *)&FontData16[asc_code][0]; + src_pitch = 32; + width = 32; + height = 16; + + ptr8 = (UINT8 *)&temp_buf[0]; + for (idx = 0; idx < 16; idx++) + { + *ptr8++ = *fptr++; + *ptr8++ = 0; + *ptr8++ = 0; + *ptr8++ = 0; + } + fptr = (UINT8 *)&temp_buf[0]; + } + else /* F8x8 */ + { + fptr = (UINT8 *)&FontData8[asc_code][0]; + src_pitch = 32; + width = 32; + height = 8; + ptr8 = (UINT8 *)&temp_buf[0]; + for (idx = 0; idx < 8; idx++) + { + *ptr8++ = *fptr++; + *ptr8++ = 0; + *ptr8++ = 0; + *ptr8++ = 0; + } + fptr = (UINT8 *)&temp_buf[0]; + } + + dest_pitch = GFX_WIDTH; // pitch in pixels + + pitch = (dest_pitch << 16) | src_pitch; + outpw(REG_GE2D_SDPITCH, pitch); + + outpw(REG_GE2D_XYSORG, (int)fptr); + outpw(REG_GE2D_SRCSPA, 0); // always start from (0,0) + + dest_start = y << 16 | x; + outpw(REG_GE2D_DSTSPA, dest_start); + + dest_dimension = height << 16 | width; + outpw(REG_GE2D_RTGLSZ, dest_dimension); + + outpw(REG_GE2D_TRG, 1); + + NU_GE2D_COND_WAIT(); + + NU_GE2D_UNLOCK(); +} + +/** + * @brief Display font string. + * @param[in] x x position + * @param[in] y y position + * @param[in] str is pointer of display string + * @param[in] fore_color is color of foreground + * @param[in] back_color is color of background + * @param[in] draw_mode is transparent is enable or not + * @param[in] font_id is selection of 8x8 or 8x16 font + * @return none + */ +void ge2dFont_PutString(int x, int y, char *str, int fore_color, int back_color, int draw_mode, int font_id) +{ + char *ptr; + int idx, sx; + + ptr = str; + sx = x; + for (idx = 0; idx < rt_strlen(str); idx++) + { + ge2dFont_PutChar(sx, y, *ptr++, fore_color, back_color, draw_mode, font_id); + sx += 8; //char width + } +} + +/** + * Hardware GE2D Initialization + */ +int rt_hw_ge2d_init(void) +{ + g_sNuGe2d.lock = rt_mutex_create("ge2d_lock", RT_IPC_FLAG_PRIO); + RT_ASSERT(g_sNuGe2d.lock != RT_NULL); + +#if defined(DEF_COND_WAIT) + rt_kprintf("with_cond_wait\n"); + g_sNuGe2d.signal = rt_sem_create("ge2d_wait", 0, RT_IPC_FLAG_FIFO); + RT_ASSERT(g_sNuGe2d.signal != RT_NULL); + + /* Install ISR & Respond the IRQ */ + rt_hw_interrupt_install(g_sNuGe2d.irqn, nu_ge2d_isr, &g_sNuGe2d, g_sNuGe2d.name); + rt_hw_interrupt_umask(g_sNuGe2d.irqn); +#endif + + /* Enable GE2D engine clock */ + nu_sys_ipclk_enable(GE2DCKEN); + + return 0; +} + +INIT_DEVICE_EXPORT(rt_hw_ge2d_init); diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_gpio.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_gpio.c new file mode 100644 index 0000000000..a6623653c6 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_gpio.c @@ -0,0 +1,388 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#include + +#if (defined(BSP_USING_GPIO) && defined(RT_USING_PIN)) + +#include +#include +#include "NuMicro.h" +#include +#include +#include +#include + +#define LOG_TAG "drv.gpio" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include + +/* Private define ---------------------------------------------------------------*/ + +#define PORT_OFFSET 0x40 +#define IRQ_MAX_NUM 16 //Max support 32 +#define GPIO_PIN_MAX 16 + +/* Private functions ------------------------------------------------------------*/ + +static void nu_gpio_mode(struct rt_device *device, rt_base_t pin, rt_base_t mode); +static void nu_gpio_write(struct rt_device *device, rt_base_t pin, rt_base_t value); +static int nu_gpio_read(struct rt_device *device, rt_base_t pin); +static rt_err_t nu_gpio_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args); +static rt_err_t nu_gpio_detach_irq(struct rt_device *device, rt_int32_t pin); +static rt_err_t nu_gpio_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled); +static rt_base_t nu_gpio_pin_get(const char *name); + +/* Private variables ------------------------------------------------------------*/ +static struct rt_pin_irq_hdr pin_irq_hdr_tab[IRQ_MAX_NUM]; +static struct rt_pin_ops nu_gpio_ops = +{ + nu_gpio_mode, + nu_gpio_write, + nu_gpio_read, + nu_gpio_attach_irq, + nu_gpio_detach_irq, + nu_gpio_irq_enable, + nu_gpio_pin_get, +}; + +static rt_uint32_t g_u32PinIrqMask = 0x0; + +static uint32_t au32PinMaskTbl[] = {GPIOA_MASK, GPIOB_MASK, GPIOC_MASK, GPIOD_MASK, GPIOE_MASK, GPIOF_MASK, GPIOG_MASK, GPIOH_MASK, GPIOI_MASK, GPIOJ_MASK}; + +/* Functions define ------------------------------------------------------------*/ + +static rt_err_t nu_port_check(rt_int32_t pin) +{ + if (NU_GET_PORT(pin) >= NU_PORT_CNT) + { + LOG_E("Over port group. %04x", pin); + return -(RT_ERROR); + } + + if (!(au32PinMaskTbl[NU_GET_PORT(pin)] & NU_GET_PIN_MASK(NU_GET_PINS(pin)))) + { + LOG_E("Over port-pin group. %04x", pin); + return -(RT_ERROR); + } + + return RT_EOK; +} + +static rt_int32_t nu_find_irqindex(rt_uint32_t pin_index) +{ + rt_int32_t irqindex; + rt_int32_t u32PinIrqStatus = g_u32PinIrqMask; + + // Find index of pin is attached in pool. + while ((irqindex = nu_ctz(u32PinIrqStatus)) < IRQ_MAX_NUM) // Count Trailing Zeros ==> Find First One + { + if (pin_irq_hdr_tab[irqindex].pin == pin_index) + return irqindex; + + u32PinIrqStatus &= ~(1 << irqindex); + } + + return -(RT_ERROR); +} + +static void pin_irq_hdr(rt_uint32_t irq_status, rt_uint32_t port_index) +{ + rt_int32_t irqindex, i; + rt_int32_t pinindex = port_index * GPIO_PIN_MAX ; + + while ((i = nu_ctz(irq_status)) < GPIO_PIN_MAX)// Count Trailing Zeros ==> Find First One + { + int pin_mask = (1 << i); + irqindex = nu_find_irqindex(pinindex + i); + if (irqindex != -(RT_ERROR)) + { + if (pin_irq_hdr_tab[irqindex].hdr) + { + pin_irq_hdr_tab[irqindex].hdr(pin_irq_hdr_tab[irqindex].args); + } + } + // Clear the served bit. + irq_status &= ~pin_mask; + } +} + +static rt_base_t nu_gpio_pin_get(const char *name) +{ + /* Get pin number by name,such as PA.0, PF12 */ + if ((name[2] == '\0') || ((name[2] == '.') && (name[3] == '\0'))) + return -(RT_EINVAL); + + long number; + + if ((name[2] == '.')) + number = atol(&name[3]); + else + number = atol(&name[2]); + + if (number > 15) + return -(RT_EINVAL); + + if (name[1] >= 'A' && name[1] <= 'J') + return ((name[1] - 'A') * 0x10) + number; + + if (name[1] >= 'a' && name[1] <= 'i') + return ((name[1] - 'a') * 0x10) + number; + + return -(RT_EINVAL); +} + +static void nu_gpio_mode(struct rt_device *device, rt_base_t pin, rt_base_t mode) +{ + GPIO_PORT PORT; + + if (nu_port_check(pin)) + return; + + PORT = (GPIO_PORT)(GPIOA + (NU_GET_PORT(pin) * PORT_OFFSET)); + + switch (mode) + { + case PIN_MODE_INPUT_PULLUP: + GPIO_OpenBit(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), DIR_INPUT, PULL_UP); + break; + + case PIN_MODE_INPUT_PULLDOWN: + GPIO_OpenBit(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), DIR_INPUT, PULL_DOWN); + break; + + case PIN_MODE_OUTPUT: + GPIO_OpenBit(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), DIR_OUTPUT, NO_PULL_UP); + break; + + case PIN_MODE_INPUT: + GPIO_OpenBit(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), DIR_INPUT, NO_PULL_UP); + break; + + case PIN_MODE_OUTPUT_OD: + default: + LOG_E("Open-drian is not supportted."); + break; + } +} + +static void nu_gpio_write(struct rt_device *device, rt_base_t pin, rt_base_t value) +{ + GPIO_PORT PORT; + + if (nu_port_check(pin)) + return; + + PORT = (GPIO_PORT)(GPIOA + (NU_GET_PORT(pin) * PORT_OFFSET)); + + if (value) + GPIO_SetBit(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin))); + else + GPIO_ClrBit(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin))); +} + +static int nu_gpio_read(struct rt_device *device, rt_base_t pin) +{ + GPIO_PORT PORT; + + if (nu_port_check(pin)) + return PIN_LOW; + + PORT = (GPIO_PORT)(GPIOA + (NU_GET_PORT(pin) * PORT_OFFSET)); + + return GPIO_ReadBit(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin))); +} + +static rt_err_t nu_gpio_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args) +{ + rt_base_t level; + rt_int32_t irqindex; + + if (nu_port_check(pin)) + return -(RT_ERROR); + + level = rt_hw_interrupt_disable(); + + /* Find index of pin is attached in pool. */ + if ((irqindex = nu_find_irqindex(pin)) >= 0) + goto exit_nu_gpio_attach_irq; + + /* Find available index of pin in pool. */ + if ((irqindex = nu_cto(g_u32PinIrqMask)) < IRQ_MAX_NUM) // Count Trailing Ones ==> Find First Zero + goto exit_nu_gpio_attach_irq; + + rt_hw_interrupt_enable(level); + + return -(RT_EBUSY); + +exit_nu_gpio_attach_irq: + + pin_irq_hdr_tab[irqindex].pin = pin; + pin_irq_hdr_tab[irqindex].hdr = hdr; + pin_irq_hdr_tab[irqindex].mode = mode; + pin_irq_hdr_tab[irqindex].args = args; + + g_u32PinIrqMask |= (1 << irqindex); + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +static rt_err_t nu_gpio_detach_irq(struct rt_device *device, rt_int32_t pin) +{ + rt_base_t level; + rt_int32_t irqindex; + rt_int32_t u32PinIrqStatus; + + if (nu_port_check(pin)) + return -(RT_ERROR); + + level = rt_hw_interrupt_disable(); + + u32PinIrqStatus = g_u32PinIrqMask; + + // Find index of pin is attached in pool. + while ((irqindex = nu_ctz(u32PinIrqStatus)) < IRQ_MAX_NUM)// Count Trailing Zeros ==> Find First One + { + if (pin_irq_hdr_tab[irqindex].pin == pin) + { + pin_irq_hdr_tab[irqindex].pin = PIN_IRQ_PIN_NONE; + pin_irq_hdr_tab[irqindex].hdr = RT_NULL; + pin_irq_hdr_tab[irqindex].mode = PIN_IRQ_MODE_RISING; + pin_irq_hdr_tab[irqindex].args = RT_NULL; + g_u32PinIrqMask &= ~(1 << irqindex); + break; + } + u32PinIrqStatus &= ~(1 << irqindex); + } + + rt_hw_interrupt_enable(level); + return RT_EOK; +} + +static void nu_gpio_isr(int vector, void *param) +{ + int i; + rt_uint32_t u32IntStatus_Port; + + u32IntStatus_Port = inpw(REG_GPIO_ISR) | ~((1 << MAX_PORT) - 1); + while ((i = nu_ctz(u32IntStatus_Port)) < MAX_PORT)// Count Trailing Zeros ==> Find First One + { + int port_mask = (1 << i); + rt_uint32_t u32IntStatus_Pins = inpw(REG_GPIOA_ISR + PORT_OFFSET * i); + + /* Invoke pins status and port number */ + pin_irq_hdr(u32IntStatus_Pins, i); + + /* Clear Interrupt flag. */ + outpw(REG_GPIOA_ISR + PORT_OFFSET * i, u32IntStatus_Pins); + + /* Clear the served bit. */ + u32IntStatus_Port &= ~port_mask; + } + + /* Clear interrupt */ + outpw(REG_AIC_SCCRH, IRQ_GPIO - 1); +} + +static rt_err_t nu_gpio_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) +{ + GPIO_PORT PORT; + GPIO_TRIGGER_TYPE triggerType; + + rt_base_t level; + rt_int32_t irqindex; + rt_err_t ret = RT_EOK; + + if (nu_port_check(pin)) + return -(RT_ERROR); + + level = rt_hw_interrupt_disable(); + + irqindex = nu_find_irqindex(pin); + if (irqindex == -(RT_ERROR)) + { + ret = RT_ERROR; + goto exit_nu_gpio_irq_enable; + } + + PORT = (GPIO_PORT)(GPIOA + (NU_GET_PORT(pin) * PORT_OFFSET)); + + if (enabled == PIN_IRQ_ENABLE) + { + switch (pin_irq_hdr_tab[irqindex].mode) + { + case PIN_IRQ_MODE_RISING: + triggerType = RISING; + break; + + case PIN_IRQ_MODE_FALLING: + triggerType = FALLING; + break; + + case PIN_IRQ_MODE_RISING_FALLING: + triggerType = BOTH_EDGE; + break; + + case PIN_IRQ_MODE_HIGH_LEVEL: + triggerType = HIGH; + break; + + case PIN_IRQ_MODE_LOW_LEVEL: + triggerType = LOW; + break; + + default: + goto exit_nu_gpio_irq_enable; + } + GPIO_EnableTriggerType(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), triggerType); + } + else + { + GPIO_DisableTriggerType(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin))); + } + +exit_nu_gpio_irq_enable: + + rt_hw_interrupt_enable(level); + return -(ret); +} + +int rt_hw_gpio_init(void) +{ + char szTmp[16]; + rt_int32_t irqindex; + + for (irqindex = 0; irqindex < IRQ_MAX_NUM ; irqindex++) + { + pin_irq_hdr_tab[irqindex].pin = PIN_IRQ_PIN_NONE; + pin_irq_hdr_tab[irqindex].hdr = RT_NULL; + pin_irq_hdr_tab[irqindex].mode = PIN_IRQ_MODE_RISING; + pin_irq_hdr_tab[irqindex].args = RT_NULL; + } + + nu_sys_ipclk_enable(GPIOCKEN); + + snprintf(szTmp, sizeof(szTmp), "gpio"); + rt_hw_interrupt_install(IRQ_GPIO, nu_gpio_isr, RT_NULL, szTmp); + rt_hw_interrupt_set_type(IRQ_GPIO, HIGH_LEVEL_SENSITIVE); + rt_hw_interrupt_umask(IRQ_GPIO); + + return rt_device_pin_register("gpio", &nu_gpio_ops, RT_NULL); +} + +INIT_BOARD_EXPORT(rt_hw_gpio_init); + +#endif //#if (defined(BSP_USING_GPIO) && defined(RT_USING_PIN)) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_gpio.h b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_gpio.h new file mode 100644 index 0000000000..c8f232e491 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_gpio.h @@ -0,0 +1,36 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-2-7 YCHuang12 First version +* +******************************************************************************/ + +#ifndef __DRV_GPIO_H__ +#define __DRV_GPIO_H__ + +typedef enum +{ + NU_PA, + NU_PB, + NU_PC, + NU_PD, + NU_PE, + NU_PF, + NU_PG, + NU_PH, + NU_PI, + NU_PJ, + NU_PORT_CNT, +} nu_gpio_port; + +#define NU_GET_PININDEX(port, pin) ((port)*16+(pin)) +#define NU_GET_PINS(rt_pin_index) ((rt_pin_index) & 0x0000000F) +#define NU_GET_PORT(rt_pin_index) (((rt_pin_index)>>4) & 0x0000000F) +#define NU_GET_PIN_MASK(nu_gpio_pin) (1 << (nu_gpio_pin)) + +#endif //__DRV_GPIO_H__ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c new file mode 100644 index 0000000000..0b4fbaabf1 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c @@ -0,0 +1,520 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-04-20 Wayne First version +******************************************************************************/ + + +#include + +#if defined( BSP_USING_I2C) + +#include +#include "NuMicro.h" +//#include +#include + +/* Private define ---------------------------------------------------------------*/ +#define LOG_TAG "drv.i2c" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_ERROR +#define DBG_COLOR +#include + +#define I2C_REG_WRITE(dev, addr, byte) outpw(dev->base + addr, byte) +#define I2C_REG_READ(dev, addr) inpw(dev->base + addr) + +#define I2C_DISABLE(dev) I2C_REG_WRITE(dev, I2C_CSR, 0x00) /* Disable i2c core and interrupt */ +#define I2C_ENABLE(dev) I2C_REG_WRITE(dev, I2C_CSR, 0x3) /* Enable i2c core and interrupt */ +#define I2C_ISBUSFREE(dev) (((I2C_REG_READ(dev, I2C_SWR) & 0x18) == 0x18 && (I2C_REG_READ(dev, I2C_CSR) & 0x0400) == 0) ? 1 : 0) + +enum +{ + I2C_START = -1, +#if defined(BSP_USING_I2C0) + I2C0_IDX, +#endif +#if defined(BSP_USING_I2C1) + I2C1_IDX, +#endif + I2C_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ +typedef struct +{ + int32_t base; /* i2c bus number */ + int32_t state; + int32_t addr; + uint32_t last_error; + int32_t bNackValid; + + uint32_t subaddr; + int32_t subaddr_len; + + uint8_t buffer[I2C_MAX_BUF_LEN]; + uint32_t pos, len; + +} nu_i2c_dev; +typedef nu_i2c_dev *nu_i2c_dev_t; + +typedef struct +{ + struct rt_i2c_bus_device parent; + char *name; + + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + + struct rt_i2c_msg *cur_i2c_msg; + + nu_i2c_dev dev; +} nu_i2c_bus ; +typedef nu_i2c_bus *nu_i2c_bus_t; +/* Private variables ------------------------------------------------------------*/ + +static nu_i2c_bus nu_i2c_arr [ ] = +{ +#if defined(BSP_USING_I2C0) + { + .dev = + { + .base = I2C0_BA, + }, + .name = "i2c0", + .irqn = IRQ_I2C0, + .rstidx = I2C0RST, + .clkidx = I2C0CKEN, + }, +#endif +#if defined(BSP_USING_I2C1) + { + .dev = + { + .base = I2C1_BA, + }, + .name = "i2c1", + .irqn = IRQ_I2C1, + .rstidx = I2C1RST, + .clkidx = I2C1CKEN, + }, +#endif +}; + +/* Private functions ------------------------------------------------------------*/ +/** + * @brief Set i2c interface speed + * @param[in] dev i2c device structure pointer + * @param[in] sp i2c speed + * @return always 0 + */ +static int32_t nu_i2c_set_speed(nu_i2c_dev_t psNuI2cDev, int32_t sp) +{ + uint32_t d; + + if (sp != 100 && sp != 400) + return (I2C_ERR_NOTTY); + + d = (sysGetClock(SYS_PCLK) * 1000) / (sp * 5) - 1; + + I2C_REG_WRITE(psNuI2cDev, I2C_DIVIDER, d & 0xffff); + + return 0; +} + +/** + * @brief Configure i2c command + * @param[in] dev i2c device structure pointer + * @param[in] cmd command + * @return None + */ +static void nu_i2c_command(nu_i2c_dev_t psNuI2cDev, int32_t cmd) +{ + psNuI2cDev->bNackValid = (cmd & I2C_CMD_WRITE) ? 1 : 0; + I2C_REG_WRITE(psNuI2cDev, I2C_CMDR, cmd); +} + +/** + * @brief Configure slave address data + * @param[in] dev i2c device structure pointer + * @param[in] mode could be write or read + * @return None + */ +static void nu_i2c_calculate_address(nu_i2c_dev_t psNuI2cDev, int32_t mode) +{ + int32_t i; + uint32_t subaddr = psNuI2cDev->subaddr; + + psNuI2cDev->buffer[0] = (((psNuI2cDev->addr << 1) & 0xfe) | I2C_WRITE) & 0xff; + + for (i = psNuI2cDev->subaddr_len; i > 0; i--) + { + psNuI2cDev->buffer[i] = subaddr & 0xff; + subaddr >>= 8; + } + + if (mode == I2C_STATE_READ) + { + i = psNuI2cDev->subaddr_len + 1; + psNuI2cDev->buffer[i] = (((psNuI2cDev->addr << 1) & 0xfe)) | I2C_READ; + } +} + +/** + * @brief Reset some variables + * @param[in] dev i2c device structure pointer + * @return None + */ +static void nu_i2c_reset(nu_i2c_dev_t psNuI2cDev) +{ + psNuI2cDev->addr = -1; + psNuI2cDev->last_error = 0; + psNuI2cDev->subaddr = 0; + psNuI2cDev->subaddr_len = 0; +} + +static void nu_i2c_isr(int vector, void *param) +{ + nu_i2c_bus_t psNuI2CBus = (nu_i2c_bus_t)param; + nu_i2c_dev_t psNuI2CDev = (nu_i2c_dev_t)&psNuI2CBus->dev; + struct rt_i2c_msg *pmsg = psNuI2CBus->cur_i2c_msg; + uint32_t msg_flag = pmsg->flags; + + uint32_t csr, val; + + csr = I2C_REG_READ(psNuI2CDev, I2C_CSR); + csr |= 0x04; + + /* Clear interrupt flag */ + I2C_REG_WRITE(psNuI2CDev, I2C_CSR, csr); + + if (psNuI2CDev->state == I2C_STATE_NOP) + return; + + /* NACK only valid in WRITE */ + if ((csr & 0x800) && psNuI2CDev->bNackValid && !(msg_flag & RT_I2C_IGNORE_NACK)) + { + rt_kprintf("I2C W/ NACK\n"); + psNuI2CDev->last_error = I2C_ERR_NACK; + nu_i2c_command(psNuI2CDev, I2C_CMD_STOP); + psNuI2CDev->state = I2C_STATE_NOP; + } + /* Arbitration lost */ + else if (csr & 0x200) + { + rt_kprintf("Arbitration lost\n"); + psNuI2CDev->last_error = I2C_ERR_LOSTARBITRATION; + psNuI2CDev->state = I2C_STATE_NOP; + } + /* Transmit complete */ + else if (!(csr & 0x100)) + { + /* Send address state */ + if (psNuI2CDev->pos < psNuI2CDev->subaddr_len + 1) + { + val = psNuI2CDev->buffer[psNuI2CDev->pos++] & 0xff; + I2C_REG_WRITE(psNuI2CDev, I2C_TxR, val); + nu_i2c_command(psNuI2CDev, I2C_CMD_WRITE); + } + else if (psNuI2CDev->state == I2C_STATE_READ) + { + /* Sub-address send over, begin restart a read command */ + if (psNuI2CDev->pos == psNuI2CDev->subaddr_len + 1) + { + val = psNuI2CDev->buffer[psNuI2CDev->pos++]; + I2C_REG_WRITE(psNuI2CDev, I2C_TxR, val); + nu_i2c_command(psNuI2CDev, I2C_CMD_START | I2C_CMD_WRITE); + } + else + { + psNuI2CDev->buffer[psNuI2CDev->pos++] = I2C_REG_READ(psNuI2CDev, I2C_RxR) & 0xff; + if (psNuI2CDev->pos < psNuI2CDev->len) + { + /* Last character */ + if (psNuI2CDev->pos == psNuI2CDev->len - 1) + nu_i2c_command(psNuI2CDev, I2C_CMD_READ | I2C_CMD_STOP | I2C_CMD_NACK); + else + nu_i2c_command(psNuI2CDev, I2C_CMD_READ); + } + else + { + psNuI2CDev->state = I2C_STATE_NOP; + } + } + } + /* Write data */ + else if (psNuI2CDev->state == I2C_STATE_WRITE) + { + + if (psNuI2CDev->pos < psNuI2CDev->len) + { + val = psNuI2CDev->buffer[psNuI2CDev->pos]; + + I2C_REG_WRITE(psNuI2CDev, I2C_TxR, val); + + /* Last character */ + if (psNuI2CDev->pos == psNuI2CDev->len - 1) + nu_i2c_command(psNuI2CDev, I2C_CMD_WRITE | I2C_CMD_STOP); + else + nu_i2c_command(psNuI2CDev, I2C_CMD_WRITE); + + psNuI2CDev->pos ++; + } + else + { + psNuI2CDev->state = I2C_STATE_NOP; + } + } + } +} + + + +/** + * @brief Read data from I2C slave. + * @param[in] psNuI2cDev is interface structure pointer. + * @param[in] pmsg is pointer of rt i2c message structure. + * @return read status. + * @retval >0 length when success. + * @retval I2C_ERR_BUSY Interface busy. + * @retval I2C_ERR_IO Interface not opened. + * @retval I2C_ERR_NODEV No such device. + * @retval I2C_ERR_NACK Slave returns an erroneous ACK. + * @retval I2C_ERR_LOSTARBITRATION arbitration lost happen. + */ +static int32_t nu_i2c_read(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) +{ + uint8_t *buf = pmsg->buf; + uint32_t len = pmsg->len; + + if (len > I2C_MAX_BUF_LEN - 10) + len = I2C_MAX_BUF_LEN - 10; + + psNuI2cDev->state = I2C_STATE_READ; + psNuI2cDev->pos = 1; + + /* Current ISR design will get one garbage byte */ + /* plus 1 unused char */ + psNuI2cDev->len = psNuI2cDev->subaddr_len + 1 + len + 2; + psNuI2cDev->last_error = 0; + + /* Get slave address */ + nu_i2c_calculate_address(psNuI2cDev, I2C_STATE_READ); + + /* Enable I2C-EN */ + I2C_ENABLE(psNuI2cDev); + + /* Send first byte to transfer the message. */ + I2C_REG_WRITE(psNuI2cDev, I2C_TxR, psNuI2cDev->buffer[0] & 0xff); + + if (!I2C_ISBUSFREE(psNuI2cDev)) + return (I2C_ERR_BUSY); + + nu_i2c_command(psNuI2cDev, I2C_CMD_START | I2C_CMD_WRITE); + + while (psNuI2cDev->state != I2C_STATE_NOP); + + /* Disable I2C-EN */ + I2C_DISABLE(psNuI2cDev); + + if (psNuI2cDev->last_error) + return (psNuI2cDev->last_error); + + rt_memcpy(buf, psNuI2cDev->buffer + psNuI2cDev->subaddr_len + 3, len); + + psNuI2cDev->subaddr += len; + + return len; +} + +/** + * @brief Write data from I2C slave. + * @param[in] psNuI2cDev is interface structure pointer. + * @param[in] pmsg is pointer of rt i2c message structure. + * @return write status. + * @retval >0 length when success. + * @retval I2C_ERR_BUSY Interface busy. + * @retval I2C_ERR_IO Interface not opened. + * @retval I2C_ERR_NODEV No such device. + * @retval I2C_ERR_NACK Slave returns an erroneous ACK. + * @retval I2C_ERR_LOSTARBITRATION arbitration lost happen. + */ +static int32_t nu_i2c_write(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) +{ + uint8_t *buf = pmsg->buf; + uint32_t len = pmsg->len; + + if (len > I2C_MAX_BUF_LEN - 10) + len = I2C_MAX_BUF_LEN - 10; + + rt_memcpy(psNuI2cDev->buffer + psNuI2cDev->subaddr_len + 1, buf, len); + + psNuI2cDev->state = I2C_STATE_WRITE; + psNuI2cDev->pos = 1; + psNuI2cDev->len = psNuI2cDev->subaddr_len + 1 + len; + psNuI2cDev->last_error = 0; + + /* Get slave address */ + nu_i2c_calculate_address(psNuI2cDev, I2C_STATE_WRITE); + + /* Enable I2C-EN */ + I2C_ENABLE(psNuI2cDev); + + /* Send first byte to transfer the message. */ + I2C_REG_WRITE(psNuI2cDev, I2C_TxR, psNuI2cDev->buffer[0] & 0xff); + + if (!I2C_ISBUSFREE(psNuI2cDev)) + return (I2C_ERR_BUSY); + + nu_i2c_command(psNuI2cDev, I2C_CMD_START | I2C_CMD_WRITE); + + while (psNuI2cDev->state != I2C_STATE_NOP); + + /* Disable I2C-EN */ + I2C_DISABLE(psNuI2cDev); + + if (psNuI2cDev->last_error) + return (psNuI2cDev->last_error); + + psNuI2cDev->subaddr += len; + + return len; +} + +/** + * @brief Support some I2C driver commands for application. + * @param[in] psNuI2cDev is interface structure pointer. + * @param[in] cmd is command. + * @param[in] arg0 is the first argument of command. + * @param[in] arg1 is the second argument of command. + * @return command status. + * @retval 0 Success. + * @retval I2C_ERR_IO Interface not opened. + * @retval I2C_ERR_NODEV No such device. + * @retval I2C_ERR_NOTTY Command not support, or parameter error. + */ +static int32_t nu_i2c_ioctl(nu_i2c_dev_t psNuI2cDev, uint32_t cmd, uint32_t arg0, uint32_t arg1) +{ + switch (cmd) + { + case I2C_IOC_SET_DEV_ADDRESS: + + psNuI2cDev->addr = arg0; + break; + + case I2C_IOC_SET_SPEED: + + return (nu_i2c_set_speed(psNuI2cDev, (int32_t)arg0)); + + case I2C_IOC_SET_SUB_ADDRESS: + + if (arg1 > 4) + { + return (I2C_ERR_NOTTY); + } + + psNuI2cDev->subaddr = arg0; + psNuI2cDev->subaddr_len = arg1; + break; + + default: + return (I2C_ERR_NOTTY); + } + + return (0); +} + +static rt_size_t nu_i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + nu_i2c_bus_t psNuI2cBus; + nu_i2c_dev_t psNuI2cDev; + rt_size_t i; + rt_err_t ret; + struct rt_i2c_msg *pmsg; + + RT_ASSERT(bus != RT_NULL); + psNuI2cBus = (nu_i2c_bus_t) bus; + psNuI2cDev = &psNuI2cBus->dev; + + for (i = 0; i < num; i++) + { + if (!I2C_ISBUSFREE(psNuI2cDev)) + break; + + pmsg = psNuI2cBus->cur_i2c_msg = &msgs[i]; + + /* Not support 10bit. */ + if ((pmsg->flags & RT_I2C_ADDR_10BIT) + || (pmsg->len == 0)) + break; + + /* Set device address */ + nu_i2c_reset(psNuI2cDev); + nu_i2c_ioctl(psNuI2cDev, I2C_IOC_SET_DEV_ADDRESS, pmsg->addr, 0); + + if (pmsg->flags & RT_I2C_RD) + { + ret = nu_i2c_read(psNuI2cDev, pmsg); + } + else + { + ret = nu_i2c_write(psNuI2cDev, pmsg); + } + + + if (ret != pmsg->len) break; + } + + return i; +} + +static const struct rt_i2c_bus_device_ops nu_i2c_ops = +{ + .master_xfer = nu_i2c_mst_xfer, + .slave_xfer = NULL, + .i2c_bus_control = NULL, +}; + + +/* Public functions -------------------------------------------------------------*/ +int rt_hw_i2c_init(void) +{ + int i; + rt_err_t ret = RT_EOK; + + for (i = (I2C_START + 1); i < I2C_CNT; i++) + { + nu_i2c_dev_t psNuI2cDev = &nu_i2c_arr[i].dev; + + ret = rt_i2c_bus_device_register(&nu_i2c_arr[i].parent, nu_i2c_arr[i].name); + RT_ASSERT(RT_EOK == ret); + + nu_i2c_arr[i].parent.ops = &nu_i2c_ops; + + /* Enable I2C engine clock and reset. */ + nu_sys_ipclk_enable(nu_i2c_arr[i].clkidx); + nu_sys_ip_reset(nu_i2c_arr[i].rstidx); + + nu_i2c_ioctl(psNuI2cDev, I2C_IOC_SET_SPEED, 100, 0); + + /* Register ISR and Respond IRQ. */ + rt_hw_interrupt_install(nu_i2c_arr[i].irqn, nu_i2c_isr, &nu_i2c_arr[i], nu_i2c_arr[i].name); + rt_hw_interrupt_umask(nu_i2c_arr[i].irqn); + } + + return 0; +} + +INIT_DEVICE_EXPORT(rt_hw_i2c_init); + +#endif /* BSP_USING_I2C */ + diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2s.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2s.c new file mode 100644 index 0000000000..f11ea2e25f --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2s.c @@ -0,0 +1,630 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne Lin First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_I2S) + +#include +#include +#include "NuMicro.h" + +/* Private define ---------------------------------------------------------------*/ +#define DBG_ENABLE +#define DBG_LEVEL DBG_LOG +#define DBG_SECTION_NAME "i2s" +#define DBG_COLOR +#include + +#define I2S_RSR_R_DMA_RIA_IRQ_Pos (0) +#define I2S_RSR_R_DMA_RIA_IRQ_Msk (1<audio); + } + } + + if (u32RegAudCtl & I2S_GLBCON_R_DMA_IRQ_Msk) + { + volatile uint32_t u32RegRecordStatus = inpw(REG_ACTL_RSR); + + outpw(REG_ACTL_CON, u32RegAudCtl | I2S_GLBCON_R_DMA_IRQ_Msk); //Clear RX INT + + /* Record DMA Reach Indicative Address Interrupt Request Bit */ + /* 0 = Record DMA address does not reach the indicative address by R_DMA_IRQ_SEL */ + /* 1 = Record DMA address does reach the indicative address by R_DMA_IRQ_SEL */ + /* Note: This bit is readable, and can only be cleared by writing '1' to it. */ + if (u32RegRecordStatus & I2S_RSR_R_DMA_RIA_IRQ_Msk) + { + nu_i2s_dai_t psNuI2sDai = &psNuI2s->i2s_dais[NU_I2S_DAI_CAPTURE]; + + /* + Record DMA Reach Indicative Address Section Number Bit (Read Only) + R_DMA_IRQ_SEL (I2S_GLBCON[15:14]) = 01, R_DMA_RIA_SN[2:0]= 1, 0. + R_DMA_IRQ_SEL (I2S_GLBCON[15:14]) = 10, R_DMA_RIA_SN[2:0]= 1, 2, 3, 0. + R_DMA_IRQ_SEL (I2S_GLBCON[15:14]) = 11, R_DMA_RIA_SN[2:0]= 1, 2, 3, 4, 5, 6, 7, 0. + */ + uint8_t u8FifoBlockIdx = (u32RegRecordStatus & I2S_RSR_R_DMA_RIA_SN_Msk) >> I2S_RSR_R_DMA_RIA_SN_Pos; + + rt_uint8_t *pbuf = (uint8_t *)((uint32_t)&psNuI2sDai->fifo[u8FifoBlockIdx * NU_I2S_DMA_BUF_BLOCK_SIZE] | NONCACHEABLE); + + /* Clear Record status of DMA reach indicate address interrupt. */ + outpw(REG_ACTL_RSR, I2S_RSR_R_DMA_RIA_IRQ_Msk); + + /* Report upper layer. */ + rt_audio_rx_done(&psNuI2s->audio, pbuf, NU_I2S_DMA_BUF_BLOCK_SIZE); + } + } + +} + +static rt_bool_t nu_i2s_capacity_check(struct rt_audio_configure *pconfig) +{ + switch (pconfig->samplebits) + { + case 8: + case 16: + case 24: + break; + default: + goto exit_nu_i2s_capacity_check; + } + + switch (pconfig->channels) + { + case 1: + case 2: + break; + default: + goto exit_nu_i2s_capacity_check; + } + + return RT_TRUE; + +exit_nu_i2s_capacity_check: + + return RT_FALSE; +} + +static rt_err_t nu_i2s_dai_setup(nu_i2s_t psNuI2s, struct rt_audio_configure *pconfig) +{ + rt_err_t result = RT_EOK; + nu_acodec_ops_t pNuACodecOps = RT_NULL; + RT_ASSERT(psNuI2s->AcodecOps != RT_NULL); + pNuACodecOps = psNuI2s->AcodecOps; + + /* Open I2S */ + if (nu_i2s_capacity_check(pconfig) == RT_TRUE) + { + /* Reset audio codec */ + if (pNuACodecOps->nu_acodec_reset) + result = pNuACodecOps->nu_acodec_reset(); + + if (result != RT_EOK) + goto exit_nu_i2s_dai_setup; + + /* Setup audio codec */ + if (pNuACodecOps->nu_acodec_init) + result = pNuACodecOps->nu_acodec_init(); + + if (!pNuACodecOps->nu_acodec_init || result != RT_EOK) + goto exit_nu_i2s_dai_setup; + + /* Setup acodec samplerate/samplebit/channel */ + if (pNuACodecOps->nu_acodec_dsp_control) + result = pNuACodecOps->nu_acodec_dsp_control(pconfig); + + if (!pNuACodecOps->nu_acodec_dsp_control || result != RT_EOK) + goto exit_nu_i2s_dai_setup; + + /* Open I2S */ + if (i2sOpen() != 0) + goto exit_nu_i2s_dai_setup; + + /* Select I2S function */ + i2sIoctl(I2S_SELECT_BLOCK, I2S_BLOCK_I2S, 0); + + /* Select Data width */ + i2sIoctl(I2S_SELECT_BIT, ((pconfig->samplebits / 8) - 1), 0); + + if (pconfig->channels > 1) + { + /* Set to stereo */ + i2sIoctl(I2S_SET_CHANNEL, I2S_PLAY, I2S_CHANNEL_P_I2S_TWO); + i2sIoctl(I2S_SET_CHANNEL, I2S_REC, I2S_CHANNEL_R_I2S_TWO); + } + else + { + /* Set to mono */ + i2sIoctl(I2S_SET_CHANNEL, I2S_PLAY, I2S_CHANNEL_P_I2S_ONE); + i2sIoctl(I2S_SET_CHANNEL, I2S_REC, I2S_CHANNEL_R_I2S_LEFT_PCM_SLOT0); + } + + /* Set DMA interrupt selection to half of DMA buffer */ + switch (NU_I2S_DMA_BUF_BLOCK_NUMBER) + { + case 2: + i2sIoctl(I2S_SET_PLAY_DMA_INT_SEL, I2S_DMA_INT_HALF, 0); + i2sIoctl(I2S_SET_REC_DMA_INT_SEL, I2S_DMA_INT_HALF, 0); + break; + case 4: + i2sIoctl(I2S_SET_PLAY_DMA_INT_SEL, I2S_DMA_INT_QUARTER, 0); + i2sIoctl(I2S_SET_REC_DMA_INT_SEL, I2S_DMA_INT_QUARTER, 0); + break; + case 8: + i2sIoctl(I2S_SET_PLAY_DMA_INT_SEL, I2S_DMA_INT_EIGHTH, 0); + i2sIoctl(I2S_SET_REC_DMA_INT_SEL, I2S_DMA_INT_EIGHTH, 0); + break; + default: + RT_ASSERT(0); + break; + } + + /* Set DMA buffer address */ + i2sIoctl(I2S_SET_DMA_ADDRESS, I2S_PLAY, (uint32_t)&psNuI2s->i2s_dais[NU_I2S_DAI_PLAYBACK].fifo[0]); + i2sIoctl(I2S_SET_DMA_ADDRESS, I2S_REC, (uint32_t)&psNuI2s->i2s_dais[NU_I2S_DAI_CAPTURE].fifo[0]); + + /* Set DMA buffer length */ + i2sIoctl(I2S_SET_DMA_LENGTH, I2S_PLAY, NU_I2S_DMA_FIFO_SIZE); + i2sIoctl(I2S_SET_DMA_LENGTH, I2S_REC, NU_I2S_DMA_FIFO_SIZE); + + /* Select I2S format */ + i2sIoctl(I2S_SET_I2S_FORMAT, I2S_FORMAT_I2S, 0); + + if (psNuI2s->AcodecOps->role == NU_ACODEC_ROLE_MASTER) + { + if (pconfig->samplerate % 11025) + { + // 12.288MHz ==> APLL=98.4MHz / 8 = 12.3MHz + // APLL is 98.4MHz + /* + FB_DV = 0x28 -> N=FB_DV+1 -> N=41 + IN_DV = 0 -> M=IN_DV+1 -> M=1 + OUT_DV = 4 -> P=4+1 -> P=5 + Fpllout = 12MHz * N / (M*P) -> Fpllout = 12MHz * 41 / (5*1) = 98.4 MHz + */ + outpw(REG_CLK_APLLCON, 0xC0008028); + + // Select APLL as I2S source and divider is (7+1) + outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0x001f0000) | (0x2 << 19) | (0x7 << 24)); + + // Set sampleing rate, data width, channel + i2sSetSampleRate(12300000, pconfig->samplerate, pconfig->samplebits, pconfig->channels); + } + else + { + // 11.2896MHz ==> APLL=90MHz / 8 = 11.25MHz + // APLL is 90MHz + /* + FB_DV = 0x2D -> N=FB_DV+1 -> N=45 + IN_DV = 0 -> M=IN_DV+1 -> M=1 + OUT_DV = 5 -> P=5+1 -> P=6 + Fpllout = 12MHz * N / (M*P) -> Fpllout = 12MHz * 45 / (6*1) = 90 MHz + */ + outpw(REG_CLK_APLLCON, 0xC000A02D); + + // Select APLL as I2S source and divider is (7+1) + outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0x001f0000) | (0x2 << 19) | (0x7 << 24)); + + // Set sampleing rate, data width, channel + i2sSetSampleRate(11250000, pconfig->samplerate, pconfig->samplebits, pconfig->channels); + } + // Set as master + i2sIoctl(I2S_SET_MODE, I2S_MODE_MASTER, 0); + } + else + { + // Set as slave, source clock is XIN (12MHz) + i2sIoctl(I2S_SET_MODE, I2S_MODE_SLAVE, 0); + } + + LOG_I("Open I2S."); + + /* Set unmute */ + if (pNuACodecOps->nu_acodec_mixer_control) + pNuACodecOps->nu_acodec_mixer_control(AUDIO_MIXER_MUTE, RT_FALSE); + } + else + result = -RT_EINVAL; + +exit_nu_i2s_dai_setup: + + return result; +} + +static rt_err_t nu_i2s_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps) +{ + rt_err_t result = RT_EOK; + nu_i2s_t psNuI2s; + nu_acodec_ops_t pNuACodecOps = RT_NULL; + + RT_ASSERT(audio != RT_NULL); + RT_ASSERT(caps != RT_NULL); + + psNuI2s = (nu_i2s_t)audio; + + RT_ASSERT(psNuI2s->AcodecOps != RT_NULL); + + pNuACodecOps = psNuI2s->AcodecOps; + + switch (caps->main_type) + { + case AUDIO_TYPE_QUERY: + switch (caps->sub_type) + { + case AUDIO_TYPE_QUERY: + caps->udata.mask = AUDIO_TYPE_INPUT | AUDIO_TYPE_OUTPUT | AUDIO_TYPE_MIXER; + break; + default: + result = -RT_ERROR; + break; + } // switch (caps->sub_type) + break; + + case AUDIO_TYPE_MIXER: + + if (pNuACodecOps->nu_acodec_mixer_query) + { + switch (caps->sub_type) + { + case AUDIO_MIXER_QUERY: + return pNuACodecOps->nu_acodec_mixer_query(AUDIO_MIXER_QUERY, &caps->udata.mask); + + default: + return pNuACodecOps->nu_acodec_mixer_query(caps->sub_type, (rt_uint32_t *)&caps->udata.value); + } // switch (caps->sub_type) + + } // if (pNuACodecOps->nu_acodec_mixer_query) + + result = -RT_ERROR; + break; + + case AUDIO_TYPE_INPUT: + case AUDIO_TYPE_OUTPUT: + + switch (caps->sub_type) + { + case AUDIO_DSP_PARAM: + caps->udata.config.channels = psNuI2s->config.channels; + caps->udata.config.samplebits = psNuI2s->config.samplebits; + caps->udata.config.samplerate = psNuI2s->config.samplerate; + break; + case AUDIO_DSP_SAMPLERATE: + caps->udata.config.samplerate = psNuI2s->config.samplerate; + break; + case AUDIO_DSP_CHANNELS: + caps->udata.config.channels = psNuI2s->config.channels; + break; + case AUDIO_DSP_SAMPLEBITS: + caps->udata.config.samplebits = psNuI2s->config.samplebits; + break; + default: + result = -RT_ERROR; + break; + } // switch (caps->sub_type) + break; + + default: + result = -RT_ERROR; + break; + + } // switch (caps->main_type) + + return result; +} + +static rt_err_t nu_i2s_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps) +{ + rt_err_t result = RT_EOK; + nu_i2s_t psNuI2s; + nu_acodec_ops_t pNuACodecOps = RT_NULL; + int stream = -1; + + RT_ASSERT(audio != RT_NULL); + RT_ASSERT(caps != RT_NULL); + + psNuI2s = (nu_i2s_t)audio; + + RT_ASSERT(psNuI2s->AcodecOps != RT_NULL); + pNuACodecOps = psNuI2s->AcodecOps; + + switch (caps->main_type) + { + case AUDIO_TYPE_MIXER: + if (psNuI2s->AcodecOps->nu_acodec_mixer_control) + psNuI2s->AcodecOps->nu_acodec_mixer_control(caps->sub_type, caps->udata.value); + break; + + + case AUDIO_TYPE_INPUT: + stream = AUDIO_STREAM_RECORD; + case AUDIO_TYPE_OUTPUT: + { + rt_bool_t bNeedReset = RT_FALSE; + + if (stream < 0) + stream = AUDIO_STREAM_REPLAY; + + switch (caps->sub_type) + { + case AUDIO_DSP_PARAM: + if (rt_memcmp(&psNuI2s->config, &caps->udata.config, sizeof(struct rt_audio_configure)) != 0) + { + rt_memcpy(&psNuI2s->config, &caps->udata.config, sizeof(struct rt_audio_configure)); + bNeedReset = RT_TRUE; + } + break; + case AUDIO_DSP_SAMPLEBITS: + if (psNuI2s->config.samplerate != caps->udata.config.samplebits) + { + psNuI2s->config.samplerate = caps->udata.config.samplebits; + bNeedReset = RT_TRUE; + } + break; + case AUDIO_DSP_CHANNELS: + if (psNuI2s->config.channels != caps->udata.config.channels) + { + pNuACodecOps->config.channels = caps->udata.config.channels; + bNeedReset = RT_TRUE; + } + break; + case AUDIO_DSP_SAMPLERATE: + if (psNuI2s->config.samplerate != caps->udata.config.samplerate) + { + psNuI2s->config.samplerate = caps->udata.config.samplerate; + bNeedReset = RT_TRUE; + } + break; + default: + result = -RT_ERROR; + break; + } // switch (caps->sub_type) + + if (bNeedReset) + { + return nu_i2s_start(audio, stream); + } + } + break; + default: + result = -RT_ERROR; + break; + } // switch (caps->main_type) + + return result; +} + +static rt_err_t nu_i2s_init(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + nu_i2s_t psNuI2s; + + RT_ASSERT(audio != RT_NULL); + + psNuI2s = (nu_i2s_t)audio; + + /* Enable IP engine clock */ + nu_sys_ipclk_enable(psNuI2s->clkidx); + + /* Reset IP engine */ + nu_sys_ip_reset(psNuI2s->rstidx); + + /* Enable interrupt */ + rt_hw_interrupt_umask(psNuI2s->irqn); + + return -(result); +} + +static rt_err_t nu_i2s_start(struct rt_audio_device *audio, int stream) +{ + nu_i2s_t psNuI2s; + + RT_ASSERT(audio != RT_NULL); + + psNuI2s = (nu_i2s_t)audio; + + /* Restart all: I2S and codec. */ + nu_i2s_stop(audio, stream); + if (nu_i2s_dai_setup(psNuI2s, &psNuI2s->config) != RT_EOK) + return -RT_ERROR; + + switch (stream) + { + case AUDIO_STREAM_REPLAY: + { + i2sIoctl(I2S_SET_PLAY, I2S_START_PLAY, 0); + + LOG_I("Start replay."); + } + break; + + case AUDIO_STREAM_RECORD: + { + i2sIoctl(I2S_SET_RECORD, I2S_START_REC, 0); + + LOG_I("Start record."); + } + break; + + default: + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t nu_i2s_stop(struct rt_audio_device *audio, int stream) +{ + nu_i2s_t psNuI2s; + nu_i2s_dai_t psNuI2sDai = RT_NULL; + + RT_ASSERT(audio != RT_NULL); + + psNuI2s = (nu_i2s_t)audio; + + switch (stream) + { + case AUDIO_STREAM_REPLAY: + psNuI2sDai = &psNuI2s->i2s_dais[NU_I2S_DAI_PLAYBACK]; + + i2sIoctl(I2S_SET_PLAY, I2S_STOP_PLAY, 0); + + LOG_I("Stop replay."); + break; + + case AUDIO_STREAM_RECORD: + psNuI2sDai = &psNuI2s->i2s_dais[NU_I2S_DAI_CAPTURE]; + + i2sIoctl(I2S_SET_RECORD, I2S_STOP_REC, 0); + + LOG_I("Stop record."); + break; + + default: + return -RT_EINVAL; + } + + /* Close I2S if record and playback path. */ + if (!((inpw(REG_ACTL_RESET)&I2S_RESET_PLAY_Msk) || (inpw(REG_ACTL_RESET)&I2S_RESET_RECORD_Msk))) + { + i2sClose(); + LOG_I("Close I2S."); + } + + /* Silence */ + rt_memset((void *)psNuI2sDai->fifo, 0, NU_I2S_DMA_FIFO_SIZE); + + return RT_EOK; +} + +static void nu_i2s_buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info) +{ + nu_i2s_t psNuI2s; + + RT_ASSERT(audio != RT_NULL); + RT_ASSERT(info != RT_NULL); + + psNuI2s = (nu_i2s_t)audio; + + /* Define it a NONCACHEABLE address. */ + info->buffer = (rt_uint8_t *)((uint32_t)psNuI2s->i2s_dais[NU_I2S_DAI_PLAYBACK].fifo | NONCACHEABLE) ; + info->total_size = NU_I2S_DMA_FIFO_SIZE; + info->block_size = NU_I2S_DMA_BUF_BLOCK_SIZE; + info->block_count = NU_I2S_DMA_BUF_BLOCK_NUMBER; + + return; +} + +static struct rt_audio_ops nu_i2s_audio_ops = +{ + .getcaps = nu_i2s_getcaps, + .configure = nu_i2s_configure, + + .init = nu_i2s_init, + .start = nu_i2s_start, + .stop = nu_i2s_stop, + .transmit = RT_NULL, + .buffer_info = nu_i2s_buffer_info +}; + +int rt_hw_i2s_init(void) +{ + int i = 0; + nu_i2s_dai_t psNuI2sDai; + + for (i = 0; i < NU_I2S_DAI_CNT; i++) + { + psNuI2sDai = &g_nu_i2s_dev.i2s_dais[i]; + + /* Allocate playback and record FIFO buffer. */ + psNuI2sDai->fifo = (uint8_t *)rt_malloc_align(NU_I2S_DMA_FIFO_SIZE, 32); + RT_ASSERT(psNuI2sDai->fifo != RT_NULL); + + rt_memset(psNuI2sDai->fifo, 0, NU_I2S_DMA_FIFO_SIZE); + } + + /* Register ops of audio device */ + g_nu_i2s_dev.audio.ops = &nu_i2s_audio_ops; + + /* Register device, RW: it is with replay and record functions. */ + rt_audio_register(&g_nu_i2s_dev.audio, g_nu_i2s_dev.name, RT_DEVICE_FLAG_RDWR, &g_nu_i2s_dev); + + /* Register I2S ISR */ + rt_hw_interrupt_install(g_nu_i2s_dev.irqn, nu_i2s_isr, &g_nu_i2s_dev, g_nu_i2s_dev.name); + + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_i2s_init); +#endif //#if defined(BSP_USING_I2S) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2s.h b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2s.h new file mode 100644 index 0000000000..2b4c877acb --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2s.h @@ -0,0 +1,98 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#ifndef __DRV_I2S_H__ +#define __DRV_I2S_H__ + +#include +#include +#include "NuMicro.h" + +#if !defined(NU_I2S_DMA_FIFO_SIZE) + #define NU_I2S_DMA_FIFO_SIZE (2048) +#endif + +#if !defined(NU_I2S_DMA_BUF_BLOCK_NUMBER) + #define NU_I2S_DMA_BUF_BLOCK_NUMBER (2) +#endif + +#if ( (NU_I2S_DMA_FIFO_SIZE % NU_I2S_DMA_BUF_BLOCK_NUMBER) != 0 ) + #error "Please give an aligned definition" +#endif +#if ( NU_I2S_DMA_FIFO_SIZE < 2048 ) + #warning "DMA FIFO too small, miss voice?" +#endif + +#define NU_I2S_DMA_BUF_BLOCK_SIZE (NU_I2S_DMA_FIFO_SIZE/NU_I2S_DMA_BUF_BLOCK_NUMBER) + +#if ( NU_I2S_DMA_BUF_BLOCK_SIZE > RT_AUDIO_RECORD_PIPE_SIZE ) + #error "Specified I2S DMA buffer size is small than PIPE size in RT driver." + #error "You should enlarge RT_AUDIO_RECORD_PIPE_SIZE. " +#endif + +typedef enum +{ + NU_I2S_DAI_PLAYBACK, + NU_I2S_DAI_CAPTURE, + NU_I2S_DAI_CNT +} E_NU_I2S_DAI; + +typedef enum +{ + NU_ACODEC_ROLE_MASTER, + NU_ACODEC_ROLE_SLAVE, +} E_NU_ACODEC_ROLE; + +typedef struct +{ + char *name; + + E_NU_ACODEC_ROLE role; + + struct rt_audio_configure config; + + rt_err_t (*nu_acodec_init)(void); + + rt_err_t (*nu_acodec_reset)(void); + + rt_err_t (*nu_acodec_dsp_control)(struct rt_audio_configure *config); + + rt_err_t (*nu_acodec_mixer_control)(rt_uint32_t ui32Item, rt_uint32_t ui32Value); + + rt_err_t (*nu_acodec_mixer_query)(rt_uint32_t ui32Item, rt_uint32_t *ui32Value); + +} nu_acodec_ops; + +typedef nu_acodec_ops *nu_acodec_ops_t; + +struct nu_i2s_dai +{ + rt_uint8_t *fifo; +}; +typedef struct nu_i2s_dai *nu_i2s_dai_t; + +struct nu_i2s +{ + struct rt_audio_device audio; + struct rt_audio_configure config; + + char *name; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + + struct nu_i2s_dai i2s_dais[NU_I2S_DAI_CNT]; + nu_acodec_ops_t AcodecOps; +}; +typedef struct nu_i2s *nu_i2s_t; + +#endif // __DRV_I2S_H___ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_jpegcodec.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_jpegcodec.c new file mode 100644 index 0000000000..16ae07f5d1 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_jpegcodec.c @@ -0,0 +1,1412 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-4-16 Wayne First version +* +******************************************************************************/ + +#include "rtthread.h" + +#include "NuMicro.h" +#include "nu_jpeg.h" +#include "drv_sys.h" + +struct nu_jpeg +{ + struct rt_device dev; + char *name; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + + struct rt_mutex lock; +}; +typedef struct nu_jpeg *nu_jpeg_t; + +static BOOL volatile g_bWait = FALSE, g_jpegError = FALSE, g_bScale = FALSE, g_OutputWait = FALSE, g_InputWait = FALSE, g_u32WindowDec = FALSE, g_bEncThumbnailDownScale = FALSE, g_bEncPrimaryDownScale = FALSE; +static UINT32 volatile g_u32Stride, g_u32ScaleWidth, g_u32ScaleHeight, g_u32OpMode, g_u32EncRotate = 0; +static UINT32 volatile g_u32BufferCount, g_u32DecInputWaitAddr; +static UINT16 volatile g_u16BufferSize, g_u16ReserveSize; +static UINT32 volatile g_u32OutputFormat, g_u32windowSizeX, g_u32windowSizeY; + + +static PFN_JPEG_CALLBACK pfnJpegDecodeComplete = NULL; +static PFN_JPEG_CALLBACK pfnJpegDecodeError = NULL; +static PFN_JPEG_CALLBACK pfnJpegEncodeComplete = NULL; +static PFN_JPEG_HEADERDECODE_CALLBACK pfnJpegHeaderDecode = NULL; +static PFN_JPEG_DECWAIT_CALLBACK pfnJpegDecInputWait = NULL; +static PFN_JPEG_DECWAIT_CALLBACK pfnJpegDecOutputWait = NULL; + +static JPEG_INFO_T jpegInfo; + +/* Default Quantization-Table 0 ~ 2 */ +static UINT8 g_au8QTable0[64] = { 0x06, 0x04, 0x04, 0x05, 0x04, 0x04, 0x06, 0x05, + 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x08, 0x0E, + 0x09, 0x08, 0x08, 0x08, 0x08, 0x11, 0x0C, 0x0D, + 0x0A, 0x0E, 0x14, 0x11, 0x15, 0x14, 0x13, 0x11, + 0x13, 0x13, 0x16, 0x18, 0x1F, 0x1A, 0x16, 0x17, + 0x1D, 0x17, 0x13, 0x13, 0x1B, 0x25, 0x1B, 0x1D, + 0x20, 0x21, 0x23, 0x23, 0x23, 0x15, 0x1A, 0x26, + 0x29, 0x26, 0x22, 0x28, 0x1F, 0x22, 0x23, 0x21 + }, + g_au8QTable1[64] = { 0x06, 0x06, 0x06, 0x08, 0x07, 0x08, 0x10, 0x09, + 0x09, 0x10, 0x21, 0x16, 0x13, 0x16, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 + }; + + +static struct nu_jpeg g_sNuJpeg = +{ + .name = "jpegcodec", + .irqn = JPEG_IRQn, + .rstidx = JPEGRST, + .clkidx = JPEGCKEN +}; + +/* Interrupt Service Routine for H/W JPEG CODEC */ +static void nu_jpeg_isr(int vector, void *param) +{ + UINT32 u32interruptStatus; + + /* Get the interrupt status */ + u32interruptStatus = JPEG_GET_INT_STATUS(); + + /* It's Header Decode Complete Interrupt */ + if (u32interruptStatus & DHE_INTS) + { + UINT32 u32YuvFormat; + UINT16 u16Height, u16Width, UVHeight, UVWidth; + UINT16 u16WidthTmp, u16HeightTmp; + /* Get the JPEG format */ + u32YuvFormat = JPEG_DEC_GET_DECODED_IMAGE_FORMAT(); + + /* Get the decoded image dimension */ + jpegGetDecodedDimension(&u16Height, &u16Width); + + jpegInfo.jpeg_width = u16Width; + jpegInfo.jpeg_height = u16Height; + jpegInfo.yuvformat = u32YuvFormat; + + if (pfnJpegHeaderDecode != NULL) + { + if (!pfnJpegHeaderDecode()) + { + jpegInit(); + g_bWait = FALSE; + return; + } + } + + if (g_bScale) + { + UINT16 u16RatioH, u16RatioW; + + if (jpegCalScalingFactor( + g_u32OpMode, //Up / Down Scaling + u16Height, //Original Height + u16Width, //Original Width + g_u32ScaleHeight, //Scaled Height + g_u32ScaleWidth, //Scaled Width + &u16RatioH, //Horizontal Ratio + &u16RatioW //Vertical Ratio + ) != E_SUCCESS) + { + g_bWait = FALSE; + g_jpegError = TRUE; + } + else + { + jpegSetScalingFactor(g_u32OpMode, u16RatioH, u16RatioW); + u16Width = g_u32ScaleWidth; + u16Height = g_u32ScaleHeight; + } + } + else + { + + if (u32YuvFormat == JPEG_DEC_YUV411) + { + /* 32-pixel alignment for YUV411 raw data */ + if (u16Width % 32) + u16Width = (u16Width & 0xFFFFFFE0) + 32; + } + else if ((u32YuvFormat == JPEG_DEC_YUV444) || (u32YuvFormat == JPEG_DEC_YUV422T)) + { + /* 8-pixel alignment for YUV444 raw data */ + if (u16Width % 8) + u16Width = (u16Width & 0xFFFFFFF8) + 8; + } + else + { + /* 16-pixel alignment for YUV422 or YUV420 raw data */ + if (u16Width % 16) + u16Width = (u16Width & 0xFFFFFFF0) + 16; + } + } + + if (g_u32Stride >= u16Width) + { + jpegInfo.stride = g_u32Stride; + g_u32Stride = g_u32Stride - u16Width; + JPEG_SET_YSTRIDE(g_u32Stride); + u16Width = jpegInfo.stride; + } + else + { + g_u32Stride = 0; + JPEG_SET_YSTRIDE(0); + jpegInfo.stride = 0; + } + + if (g_u32OutputFormat == JPEG_DEC_PRIMARY_PLANAR_YUV || g_u32OutputFormat == JPEG_DEC_THUMBNAIL_PLANAR_YUV) + { + if (g_u32WindowDec) + { + u16WidthTmp = u16Width; + u16HeightTmp = u16Height; + + u16Width = g_u32windowSizeX; + u16Height = g_u32windowSizeY; + } + + if (u32YuvFormat == JPEG_DEC_YUV411) + { + /* For YUV411 raw data */ + UVWidth = u16Width / 4; + } + else if ((u32YuvFormat == JPEG_DEC_YUV444) || (u32YuvFormat == JPEG_DEC_YUV422T)) + { + /* For YUV444 raw data */ + UVWidth = u16Width; + } + /* Set the U-component and V-componente width for YUV422 or YUV420 raw data */ + else if (u16Width % 2) + UVWidth = u16Width / 2 + 1; + else + UVWidth = u16Width / 2; + + + /* Sets the height of U and V for YUV420 image */ + if (u32YuvFormat == JPEG_DEC_YUV420) + { + /* 16-pixel alignment for YUV422 or YUV420 raw data */ + if (u16Height % 16) + u16Height = (u16Height & 0xFFFFFFF0) + 16; + UVHeight = u16Height / 2; + } + else if (u32YuvFormat == JPEG_DEC_YUV422) + { + /* 8-pixel alignment for YUV444 raw data */ + if (u16Height % 8) + u16Height = (u16Height & 0xFFFFFFF8) + 8; + UVHeight = u16Height; + } + else if (u32YuvFormat == JPEG_DEC_YUV444) + { + /* 8-pixel alignment for YUV444 raw data */ + if (u16Height % 8) + u16Height = (u16Height & 0xFFFFFFF8) + 8; + UVHeight = u16Height; + } + else if (u32YuvFormat == JPEG_DEC_YUV411) + { + /* 8-pixel alignment for YUV411 raw data */ + if (u16Height % 8) + u16Height = (u16Height & 0xFFFFFFF8) + 8; + UVHeight = u16Height; + } + else if (u32YuvFormat == JPEG_DEC_YUV422T) + { + /* 16-pixel alignment for YUV422 or YUV420 raw data */ + if (u16Height % 16) + u16Height = (u16Height & 0xFFFFFFF0) + 16; + UVHeight = u16Height / 2; + } + else + { + /* 8-pixel alignment for raw data */ + if (u16Height % 8) + u16Height = (u16Height & 0xFFFFFFF8) + 8; + UVHeight = u16Height; + } + + JPEG_SET_UADDR(JPEG_GET_YADDR() + u16Width * u16Height); + JPEG_SET_VADDR(JPEG_GET_UADDR() + UVWidth * UVHeight); + + if (u32YuvFormat == JPEG_DEC_GRAY) + jpegInfo.image_size[0] = u16Width * u16Height; + else + jpegInfo.image_size[0] = u16Width * u16Height + 2 * UVWidth * UVHeight; + + if (g_u32WindowDec) + { + u16Width = u16WidthTmp; + u16Height = u16HeightTmp; + } + } + else + { + if (g_u32WindowDec) + { + u16WidthTmp = u16Width; + u16HeightTmp = u16Height; + + u16Width = g_u32windowSizeX; + u16Height = g_u32windowSizeY; + } + + if (jpegInfo.stride) + jpegInfo.image_size[0] = jpegInfo.stride * u16Height; + else + jpegInfo.image_size[0] = u16Width * u16Height; + + if (g_u32OutputFormat == JPEG_DEC_PRIMARY_PACKET_RGB888) + jpegInfo.image_size[0] = 4 * jpegInfo.image_size[0]; + else + jpegInfo.image_size[0] = 2 * jpegInfo.image_size[0]; + + if (g_u32WindowDec) + { + u16Width = u16WidthTmp; + u16Height = u16HeightTmp; + } + + } + + /* Set the image dimension */ + jpegSetDimension(u16Height, u16Width); + + + outp32(JITCR, inp32(JITCR) | Dec_Scatter_Gather); + + /* Clear interrupt status */ + JPEG_CLEAR_INT(DHE_INTS); + } + /* It's Decode Output Wait Interrupt */ + else if (u32interruptStatus & JPG_DOW_INTS) + { + if (pfnJpegDecOutputWait != NULL) + { + pfnJpegDecOutputWait(inp32(JYADDR0), inp32(JDOWFBS)); + } + JPEG_CLEAR_INT(JPG_DOW_INTS); + + outp32(JITCR, inp32(JITCR) | Dec_Scatter_Gather); + + } + /* It's Encode Complete Interrupt */ + else if (u32interruptStatus & ENC_INTS) + { + /* Get the Encode Bit stream length */ + jpegInfo.image_size[0] = JPEG_GET_ENC_PRIMARY_BITSTREAM_SIZE(); + jpegInfo.image_size[1] = JPEG_GET_ENC_THUMBNAIL_BITSTREAM_SIZE(); + /* Clear interrupt status */ + JPEG_CLEAR_INT(ENC_INTS); + + g_bWait = FALSE; + + if (pfnJpegEncodeComplete != NULL) + pfnJpegEncodeComplete(); + } + /* It's Decode Complete Interrupt */ + else if (u32interruptStatus & DEC_INTS) + { + UINT16 imageWidth, imageHeight; + + /* Get the image dimension */ + jpegGetDimension(&imageHeight, &imageWidth); + + if (g_u32Stride != 0) + { + imageWidth = imageWidth - g_u32Stride; + } + + jpegInfo.width = imageWidth; + jpegInfo.height = imageHeight; + + /* Clear interrupt status */ + JPEG_CLEAR_INT(DEC_INTS); + JPEG_CLEAR_INT(JPG_DOW_INTS); + + g_bWait = FALSE; + + if (pfnJpegDecodeComplete != NULL) + pfnJpegDecodeComplete(); + } + /* It's Decode Error Interrupt */ + else if (u32interruptStatus & DER_INTS) + { + /* Clear interrupt status */ + JPEG_CLEAR_INT(DER_INTS); + + g_bWait = FALSE; + g_jpegError = TRUE; + + if (pfnJpegDecodeError != NULL) + pfnJpegDecodeError(); + } + else if (u32interruptStatus & IPW_INTS) + { + /* Clear interrupt status */ + JPEG_CLEAR_INT(IPW_INTS); + + JPEG_DEC_RESUME_INPUT_WAIT(); + + if (pfnJpegDecInputWait != NULL) + { + if (!pfnJpegDecInputWait((g_u32DecInputWaitAddr + (g_u32BufferCount % 2) * g_u16BufferSize), g_u16BufferSize)) + { + jpegInit(); + g_bWait = FALSE; + return; + } + g_u32BufferCount++; + } + else + while (1); + + } + +} + +static INT jpegAdjustQTAB(UINT8 u8Mode, UINT8 u8Qadjust, UINT8 u8Qscaling) +{ + UINT32 u32Addr; + if (u8Mode == JPEG_ENC_PRIMARY) + u32Addr = REG_JPRIQC; + else if (u8Mode == JPEG_ENC_THUMBNAIL) + u32Addr = REG_JTHBQC; + else + return E_JPEG_INVALID_PARAM; + + outp32(u32Addr, ((u8Qadjust & 0xF) << 4) | (u8Qscaling & 0xF)); + return E_SUCCESS; +} + + +#if 0 +//Poll the interrupt status and get if the interrupt is generated +static BOOL jpegPollInt(UINT32 u32Intflag) +{ + if (JPEG_GET_INT_STATUS() & u32Intflag) + return 1; + else + return 0; +} + + +static UINT32 jpegPower(UINT32 u32Index, UINT32 u32Exp) +{ + if (u32Exp == 0) + return 1; + else + { + UINT32 u32Idx; + for (u32Idx = 1; u32Idx < u32Exp; u32Idx = u32Idx + 1) + { + u32Index = 2 * u32Index; + } + } + return u32Index; +} + +static VOID jpegGetScalingFactor( + UINT8 u8Mode, //Up / Down Scaling + PUINT16 pu16FactorH, //Vertical Scaling Factor + PUINT16 pu16FactorW //Horizontal Scaling Factor +) +{ + if (u8Mode == JPEG_DEC_PLANAR_DOWNSCALE_MODE) + { + *pu16FactorH = inp32(REG_JPSCALD) & 0x3F; + *pu16FactorW = (inp32(REG_JPSCALD) >> 8) & 0x1F; + } + else + { + *pu16FactorH = (inp32(REG_JUPRAT) >> 16) & 0x3FFF; + *pu16FactorW = inp32(REG_JUPRAT) & 0x3FFF; + } +} +#endif + +static INT jpegSetEncodeMode(UINT8 u8SourceFormat, UINT16 u16JpegFormat) +{ + UINT8 u8Gray = 0; + switch (u16JpegFormat) + { + case JPEG_ENC_PRIMARY_YUV420: + case JPEG_ENC_PRIMARY_YUV422: + case JPEG_ENC_THUMBNAIL_YUV420: + case JPEG_ENC_THUMBNAIL_YUV422: + case (JPEG_ENC_PRIMARY_YUV420 | JPEG_ENC_THUMBNAIL_YUV420): + case (JPEG_ENC_PRIMARY_YUV422 | JPEG_ENC_THUMBNAIL_YUV422): + outp32(REG_JMCR, (inp32(REG_JMCR) & WIN_DEC) | u16JpegFormat); + u8Gray = 0; + break; + case JPEG_ENC_PRIMARY_GRAY: + case JPEG_ENC_THUMBNAIL_GRAY: + case (JPEG_ENC_PRIMARY_GRAY | JPEG_ENC_THUMBNAIL_GRAY): + if (u8SourceFormat == JPEG_ENC_SOURCE_PACKET) + return E_JPEG_INVALID_PARAM; + else + { + if (u16JpegFormat == (JPEG_ENC_PRIMARY_GRAY | JPEG_ENC_THUMBNAIL_GRAY)) + outp32(REG_JMCR, 0xB0); + else + outp32(REG_JMCR, 0xA0); + } + u8Gray = EY_ONLY; + break; + default: + return E_JPEG_INVALID_PARAM; + } + g_u32OpMode = JPEG_ENC_UPSCALE_MODE; + + if (g_bEncPrimaryDownScale) + g_u32OpMode = JPEG_ENC_PLANAR_PRIMARY_DOWNSCALE_MODE; + + if (g_bEncThumbnailDownScale) + g_u32OpMode = JPEG_ENC_PLANAR_THUMBNAIL_DOWNSCALE_MODE; + + if (u8SourceFormat == JPEG_ENC_SOURCE_PLANAR) + outp32(REG_JITCR, (inp32(REG_JITCR) & (0x8 | ROTATE)) | PLANAR_ON | u8Gray); + else if (u8SourceFormat == JPEG_ENC_SOURCE_PACKET) + outp32(REG_JITCR, inp32(REG_JITCR) & ~(PLANAR_ON | ROTATE)); + else + return E_JPEG_INVALID_PARAM; + + return E_SUCCESS; +} + +static INT jpegSetDecodeMode(UINT32 u32OutputFormat) +{ + switch (u32OutputFormat) + { + case JPEG_DEC_PRIMARY_PLANAR_YUV: + case JPEG_DEC_PRIMARY_PACKET_YUV422: + case JPEG_DEC_PRIMARY_PACKET_RGB555: + case JPEG_DEC_PRIMARY_PACKET_RGB555R1: + case JPEG_DEC_PRIMARY_PACKET_RGB555R2: + case JPEG_DEC_THUMBNAIL_PLANAR_YUV: + case JPEG_DEC_THUMBNAIL_PACKET_YUV422: + case JPEG_DEC_THUMBNAIL_PACKET_RGB555: + case JPEG_DEC_PRIMARY_PACKET_RGB565: + case JPEG_DEC_PRIMARY_PACKET_RGB565R1: + case JPEG_DEC_PRIMARY_PACKET_RGB565R2: + case JPEG_DEC_PRIMARY_PACKET_RGB888: + outp32(REG_JITCR, u32OutputFormat); + outp32(REG_JMCR, inp32(REG_JMCR) & ~ENC_DEC); + g_u32OpMode = JPEG_DEC_PACKET_DOWNSCALE_MODE; + g_u32OutputFormat = u32OutputFormat; + if (u32OutputFormat == JPEG_DEC_PRIMARY_PLANAR_YUV || u32OutputFormat == JPEG_DEC_THUMBNAIL_PLANAR_YUV) + g_u32OpMode = JPEG_DEC_PLANAR_DOWNSCALE_MODE; + break; + default: + return E_JPEG_INVALID_PARAM; + } + return E_SUCCESS; +} + +static VOID jpegDecodeTrigger(void) +{ + g_bWait = TRUE; + g_jpegError = FALSE; + + rt_memset(&jpegInfo, 0, sizeof(jpegInfo)); + + /* Decode Complete /Decode Header End/Decode Error Interrupt Enable and clear the Decode Complete /Decode Header End/Decode Error Interrupt */ + if (g_InputWait) + { + g_u32BufferCount = 0; + g_u32DecInputWaitAddr = JPEG_GET_BITSTREAM_ADDR(); + if (g_OutputWait) + JPEG_INT_ENABLE(DEC_INTE | DER_INTE | DHE_INTE | IPW_INTE | JPG_DOW_INTE); + else + JPEG_INT_ENABLE(DEC_INTE | DER_INTE | DHE_INTE | IPW_INTE); + } + else if (g_OutputWait) + { + JPEG_INT_ENABLE(DEC_INTE | DER_INTE | DHE_INTE | JPG_DOW_INTE); + } + else + JPEG_INT_ENABLE(DEC_INTE | DER_INTE | DHE_INTE); + + + + JPEG_CLEAR_INT(DEC_INTS | JPEG_DER_INTS | JPEG_DHE_INTS | JPEG_IPW_INTS | JPG_DOW_INTS); + + outp32(REG_JMCR, JPG_EN | inp32(REG_JMCR)); + outp32(REG_JMCR, ~JPG_EN & inp32(REG_JMCR)); +} + +static VOID jpegEncodeTrigger(void) +{ + g_bWait = TRUE; + g_jpegError = FALSE; + + g_u32OpMode = JPEG_ENC_UPSCALE_MODE; + + if (g_bEncPrimaryDownScale) + g_u32OpMode = JPEG_ENC_PLANAR_PRIMARY_DOWNSCALE_MODE; + + if (g_bEncThumbnailDownScale) + g_u32OpMode = JPEG_ENC_PLANAR_THUMBNAIL_DOWNSCALE_MODE; + + rt_memset(&jpegInfo, 0, sizeof(jpegInfo)); + + if (g_u32EncRotate != 0) + { + UINT16 u16Height, u16Width; + + if (((inp32(REG_JITCR) & (PLANAR_ON | EY_ONLY)) != (PLANAR_ON)) && ((inp32(REG_JMCR) & EY422) != 0)) + { + g_jpegError = TRUE; + g_bWait = FALSE; + return; + } + jpegGetDimension(&u16Width, &u16Height); + + if (g_u32EncRotate == JPEG_IOCTL_SET_ENCODE_PRIMARY_ROTATE_LEFT) + { + JPEG_SET_YADDR((JPEG_GET_YADDR() + (u16Width - 1))); + JPEG_SET_UADDR((JPEG_GET_UADDR() + (u16Width / 2 - 1))); + JPEG_SET_VADDR((JPEG_GET_VADDR() + (u16Width / 2 - 1))); + } + else + { + JPEG_SET_YADDR((JPEG_GET_YADDR() + ((u16Height - 1) * u16Width))); + u16Width = JPEG_GET_USTRIDE(); + JPEG_SET_UADDR((JPEG_GET_UADDR() + ((u16Height - 2) * u16Width / 2))); + JPEG_SET_VADDR((JPEG_GET_VADDR() + ((u16Height - 2) * u16Width / 2))); + + } + } + + if (g_bScale) + { + UINT16 u16Height, u16Width, u16ratioH, u16ratioW; + + if (g_u32EncRotate != 0) + jpegGetDimension(&u16Width, &u16Height); + else + jpegGetDimension(&u16Height, &u16Width); + + if (jpegCalScalingFactor( + g_u32OpMode, //Up / Down Scaling + u16Height, //Original Height + u16Width, //Original Width + g_u32ScaleHeight, //Scaled Height + g_u32ScaleWidth, //Scaled Width + &u16ratioH, //Horizontal Ratio + &u16ratioW //Vertical Ratio + ) != E_SUCCESS) + { + g_jpegError = TRUE; + g_bWait = FALSE; + return; + } + else + { + jpegSetScalingFactor(g_u32OpMode, u16ratioH, u16ratioW); + if (g_bEncThumbnailDownScale) + outp32(REG_JTHBWH, ((g_u32ScaleHeight & 0x1FFF) << 16) | (g_u32ScaleWidth & 0x1FFF)); + else + { + if (g_u32EncRotate != 0) + jpegSetDimension(g_u32ScaleWidth, g_u32ScaleHeight); + else + jpegSetDimension(g_u32ScaleHeight, g_u32ScaleWidth); + } + } + } + + /* Encode Complete Interrupt Enable and clear the Encode Complete Interrupt */ + JPEG_INT_ENABLE(ENC_INTE); + JPEG_CLEAR_INT(ENC_INTS); + + outp32(REG_JMCR, JPG_EN | inp32(REG_JMCR)); + outp32(REG_JMCR, ~JPG_EN & inp32(REG_JMCR)); +} + +static INT jpegCalScalingFactor( + UINT8 u8Mode, //Up / Down Scaling + UINT16 u16Height, //Original Height + UINT16 u16Width, //Original Width + UINT16 u16ScalingHeight, //Scaled Height + UINT16 u16ScalingWidth, //Scaled Width + PUINT16 pu16RatioH, //Horizontal Ratio + PUINT16 pu16RatioW //Vertical Ratio +) +{ + if (u8Mode == JPEG_ENC_UPSCALE_MODE) + { + if (u16ScalingHeight < u16Height || u16ScalingWidth < u16Width) + return E_JPEG_INVALID_PARAM; + + *pu16RatioW = (UINT32)((float)(u16ScalingWidth - 1) / (float)(u16Width - 2) * 1024); + *pu16RatioH = (UINT32)((float)(u16ScalingHeight - 1) / (float)(u16Height - 2) * 1024); + + } + else if (u8Mode == JPEG_DEC_PACKET_DOWNSCALE_MODE) + { + if (u16ScalingHeight > u16Height || u16ScalingWidth > u16Width) + return E_JPEG_INVALID_PARAM; + + *pu16RatioW = (UINT32)(((float)(u16ScalingWidth) / (u16Width - 1) * 8192)); + + if (*pu16RatioW > 8192) + *pu16RatioW = 8192; + + *pu16RatioH = (UINT32)((float)(u16ScalingHeight) / (u16Height - 1) * 8192); + + if (*pu16RatioH > 8192) + *pu16RatioH = 8192; + + } + else if (u8Mode == JPEG_DEC_PLANAR_DOWNSCALE_MODE || u8Mode == JPEG_ENC_PLANAR_PRIMARY_DOWNSCALE_MODE || u8Mode == JPEG_ENC_PLANAR_THUMBNAIL_DOWNSCALE_MODE) + { + UINT16 u16RatioW, u16RatioH; + if (u16ScalingHeight > u16Height || u16ScalingWidth > u16Width) + return E_JPEG_INVALID_PARAM; + if (u16Height % u16ScalingHeight) + return E_JPEG_INVALID_PARAM; + if (u16Width % u16ScalingWidth) + return E_JPEG_INVALID_PARAM; + + u16RatioW = u16Width / u16ScalingWidth; + + u16RatioW = u16RatioW / 2 - 1; + + if ((u16RatioW != 0) && (u16RatioW != 1) && (u16RatioW != 3)) + return E_JPEG_INVALID_PARAM; + + u16RatioH = u16Height / u16ScalingHeight - 1; + + if ((u16RatioH != 0) && (u16RatioH != 1) && (u16RatioH != 3) && (u16RatioH != 7)) + return E_JPEG_INVALID_PARAM; + + *pu16RatioW = u16RatioW; + *pu16RatioH = u16RatioH; + } + else + return E_JPEG_INVALID_PARAM; + + return E_SUCCESS; + +} + +static INT jpegSetScalingFactor( + UINT8 u8Mode, //Up / Down Scaling + UINT16 u16FactorH, //Vertical Scaling Factor + UINT16 u16FactorW //Horizontal Scaling Factor +) +{ + if (u8Mode == JPEG_ENC_UPSCALE_MODE) + { + JPEG_DEC_DISABLE_DOWNSCALING(); + JPEG_ENC_ENABLE_UPSCALING(); + } + else if (u8Mode == JPEG_DEC_PACKET_DOWNSCALE_MODE || u8Mode == JPEG_DEC_PLANAR_DOWNSCALE_MODE || u8Mode == JPEG_ENC_PLANAR_PRIMARY_DOWNSCALE_MODE) + { + JPEG_DEC_ENABLE_DOWNSCALING(); + JPEG_ENC_DISABLE_UPSCALING(); + } + else if (u8Mode == JPEG_ENC_PLANAR_THUMBNAIL_DOWNSCALE_MODE) + { + outp32(REG_JTSCALD, TSX_ON); + } + + if (u8Mode == JPEG_DEC_PLANAR_DOWNSCALE_MODE || u8Mode == JPEG_ENC_PLANAR_PRIMARY_DOWNSCALE_MODE) + outp32(REG_JPSCALD, (inp32(REG_JPSCALD) & ~(PSCALX_F | PSCALY_F)) | ((u16FactorW & 0x1F) << 8) | (u16FactorH & 0x1F)); + + else if (u8Mode == JPEG_ENC_PLANAR_THUMBNAIL_DOWNSCALE_MODE) + outp32(REG_JTSCALD, (inp32(REG_JTSCALD) & ~(TSCALX_F | TSCALY_F)) | ((u16FactorW & 0x1F) << 8) | (u16FactorH & 0x1F)); + else + { + outp32(REG_JPSCALD, inp32(REG_JPSCALD) & ~(PSCALX_F | PSCALY_F)); + outp32(REG_JUPRAT, ((u16FactorH & 0x3FFF) << 16) | (u16FactorW & 0x3FFF)); + } + return E_SUCCESS; +} + +static VOID jpegGetDecodedDimension( + PUINT16 pu16Height, //Decode/Encode Height + PUINT16 pu16Width //Decode/Encode Width +) +{ + *pu16Width = inp32(REG_JDECWH) & 0x0000FFFF; + *pu16Height = inp32(REG_JDECWH) >> 16; +} + + +static VOID jpegSetDimension( + UINT16 u16Height, //Decode/Encode Height + UINT16 u16Width //Decode/Encode Width +) +{ + outp32(REG_JPRIWH, ((u16Height & 0x1FFF) << 16) | (u16Width & 0x1FFF)); +} + +static VOID jpegGetDimension( + PUINT16 pu16Height, //Decoded Height from bit stream + PUINT16 pu16Width //Decoded Width from bit stream +) +{ + *pu16Height = inp32(REG_JPRIWH) >> 16; + *pu16Width = inp32(REG_JPRIWH) & 0x1FFF; +} + +static INT jpegSetWindowDecode( + UINT16 u16StartMCUX, //Start X MCU + UINT16 u16StartMCUY, //Horizontal Scaling Factor + UINT16 u16EndMCUX, //Vertical Scaling Factor + UINT16 u16EndMCUY, //Horizontal Scaling Factor + UINT32 u32Stride //Decode Output Stride +) +{ + if (u16StartMCUX >= u16EndMCUX || u16StartMCUY >= u16EndMCUY) + return E_JPEG_INVALID_PARAM; + + outp32(REG_JWINDEC0, u16StartMCUY << 16 | u16StartMCUX); + outp32(REG_JWINDEC1, u16EndMCUY << 16 | u16EndMCUX); + outp32(REG_JWINDEC2, u32Stride); + outp32(REG_JMCR, WIN_DEC); + //sysprintf("\tJWINDEC0 0x%X\n", inp32(REG_JWINDEC0)); + //sysprintf("\tJWINDEC1 0x%X\n", inp32(REG_JWINDEC1)); + //sysprintf("\tJWINDEC2 0x%X\n", inp32(REG_JWINDEC2)); + return E_SUCCESS; +} + +/** + * @brief The function is used to set JPEG Q Table. + * + * @param[in] puQTable0: Q Table 0 + * @param[in] puQTable1: Q Table 1 + * @param[in] puQTable2: Q Table 2 + * @param[in] u8num: Q Table number + * + * @return E_JPEG_TIMEOUT: Time-out \n + * E_SUCCESS: success + */ +static INT _jpegSetQTAB(PUINT8 puQTable0, PUINT8 puQTable1, PUINT8 puQTable2, UINT8 u8num) +{ + UINT32 u32value; + UINT32 u32TimeOut; + int i; + + u32TimeOut = 0xFFFFFF; + for (i = 0; i < 64; i = i + 4) + { + while ((inp32(REG_JMCR) & QT_BUSY) & u32TimeOut) + u32TimeOut--; + + if (!u32TimeOut) + return E_JPEG_TIMEOUT; + + u32value = puQTable0[i] | (puQTable0[i + 1] << 8) | (puQTable0[i + 2] << 16) | (puQTable0[i + 3] << 24); + outp32((REG_JQTAB0 + i), u32value); + } + + u32TimeOut = 0xFFFFFF; + for (i = 0; i < 64; i = i + 4) + { + while ((inp32(REG_JMCR) & QT_BUSY) & u32TimeOut) + u32TimeOut--; + + if (!u32TimeOut) + return E_JPEG_TIMEOUT; + + u32value = puQTable1[i] | (puQTable1[i + 1] << 8) | (puQTable1[i + 2] << 16) | (puQTable1[i + 3] << 24); + outp32((REG_JQTAB1 + i), u32value); + } + + if (u8num < 3) + return E_SUCCESS; + + outp32(JITCR, inp32(JITCR) | 0x8); + + u32TimeOut = 0xFFFFFF; + + for (i = 0; i < 64; i = i + 4) + { + while ((inp32(REG_JMCR) & QT_BUSY) & u32TimeOut) + u32TimeOut--; + + if (!u32TimeOut) + return E_JPEG_TIMEOUT; + + u32value = puQTable2[i] | (puQTable2[i + 1] << 8) | (puQTable2[i + 2] << 16) | (puQTable2[i + 3] << 24); + outp32((REG_JQTAB2 + i), u32value); + } + + u32TimeOut = 0xFFFFFF; + while ((inp32(REG_JMCR) & QT_BUSY) & u32TimeOut) + u32TimeOut--; + + if (!u32TimeOut) + return E_JPEG_TIMEOUT; + else + return E_SUCCESS; + +} + +INT jpegSetQTAB(PUINT8 puQTable0, PUINT8 puQTable1, PUINT8 puQTable2, UINT8 u8num) +{ + INT ret = 0; + struct nu_jpeg_ioctl sNuJpegIoctl = {0}; + struct nu_jpeg_qtab sNuJpegQTab = {0}; + + sNuJpegQTab.puQTable0 = puQTable0; + sNuJpegQTab.puQTable1 = puQTable1; + sNuJpegQTab.puQTable2 = puQTable2; + sNuJpegQTab.u8num = u8num; + + sNuJpegIoctl.arg0 = (UINT32)&sNuJpegQTab; + sNuJpegIoctl.arg1 = (UINT32)&ret; + + rt_device_control(&g_sNuJpeg.dev, JPEG_IOCTL_SET_QTAB, (void *)&sNuJpegIoctl); + + return ret; +} + +/// @endcond HIDDEN_SYMBOLS + + +/** @addtogroup N9H30_JPEG_EXPORTED_FUNCTIONS JPEG Exported Functions + @{ +*/ + +/** + * @brief The function is used to initial device parameters and register. + * + * @return 0 + */ +static VOID _jpegInit(void) +{ + /* Set the default values of the JPEG registers */ + g_bScale = FALSE; + g_u32Stride = 0; + g_u32BufferCount = 0; + g_u16ReserveSize = 0; + g_u32WindowDec = FALSE; + g_u32windowSizeX = 0; + g_u32windowSizeY = 0; + g_InputWait = FALSE; + g_bEncThumbnailDownScale = FALSE; + g_bEncPrimaryDownScale = FALSE; + g_OutputWait = FALSE; + g_u32EncRotate = 0; + pfnJpegHeaderDecode = NULL; + pfnJpegDecInputWait = NULL; + pfnJpegDecOutputWait = NULL; + outp32(REG_JPRIQC, 0x000000F4); + outp32(REG_JTHBQC, 0x000000F4); + outp32(REG_JPRST, 0x00000004); + outp32(REG_JTRST, 0x00000004); + outp32(REG_JITCR, 0x00000000); + outp32(REG_JINTCR, 0x00000000); + outp32(JDOWFBS, 0xFFFFFFFF); + + // Disable the Primary Up-scaling & Scaling-down + outp32(REG_JPSCALU, 0x00000000); + outp32(REG_JPSCALD, 0x00000000); + + // Reset JUPRAT and JSRCH + outp32(REG_JUPRAT, 0x00000000); + outp32(REG_JSRCH, 0x00000FFF); + //------------------------------------------- + + /* Reset JPEG (JMCR [1]) */ + outp32(REG_JMCR, 0x00000002); + outp32(REG_JMCR, 0x00000000); + outp32(REG_JMACR, 0x00400000); //Can't use single buffer +} + +VOID jpegInit(void) +{ + rt_device_control(&g_sNuJpeg.dev, JPEG_IOCTL_INITIAL_CODEC, (void *)RT_NULL); +} + +/** + * @brief The function is used to check JPEG engine not busy. + * + * @return TRUE: JPEG engine busy \n + * FALSE: JPEG engine not busy + */ +static BOOL _jpegIsReady(void) +{ + if (g_bWait == FALSE) + return TRUE; + else + return FALSE; +} + +BOOL jpegIsReady(void) +{ + UINT32 u32IsReady = 0; + struct nu_jpeg_ioctl sNuJpegIoctl = {0}; + + sNuJpegIoctl.arg0 = (UINT32)&u32IsReady; + + rt_device_control(&g_sNuJpeg.dev, JPEG_IOCTL_IS_READY, (void *)&sNuJpegIoctl); + + return (BOOL)u32IsReady; +} +/** + * @brief The function is used to get JPEG information. + * + * @param[out] *info: JPEG encode/decode information. + * + * @return 0 + */ +static VOID _jpegGetInfo(JPEG_INFO_T *info) +{ + rt_memcpy(info, &jpegInfo, sizeof(JPEG_INFO_T)); +} + +VOID jpegGetInfo(JPEG_INFO_T *info) +{ + struct nu_jpeg_ioctl sNuJpegIoctl = {0}; + + sNuJpegIoctl.arg0 = (UINT32)info; + + rt_device_control(&g_sNuJpeg.dev, JPEG_IOCTL_GET_INFO, (void *)&sNuJpegIoctl); +} + +/** + * @brief The function is used to wait JPEG engine, until JPEG engine not busy. + * + * @return E_SUCCESS: JPEG engine encode/decode complete \n + * FALSE: JPEG engine error + */ +static INT _jpegWait(void) +{ + while (1) + { + if (g_bWait == FALSE) + break; + } + + if (g_jpegError) + return E_FAIL; + + return E_SUCCESS; +} + +INT jpegWait(void) +{ + INT ret = 0; + struct nu_jpeg_ioctl sNuJpegIoctl; + + sNuJpegIoctl.arg0 = (UINT32)&ret; + sNuJpegIoctl.arg1 = 0; + + rt_device_control(&g_sNuJpeg.dev, JPEG_IOCTL_WAITDONE, (void *)&sNuJpegIoctl); + + return ret; +} + +/** + * @brief The function is used to config and reset JPEG IP. + * + * @return E_SUCCESS: success + */ +INT jpegOpen(void) +{ + return (rt_device_open(&g_sNuJpeg.dev, RT_DEVICE_FLAG_RDWR) == RT_EOK) ? E_SUCCESS : E_FAIL; +} + +/** + * @brief Support some JPEG driver commands for application. + * + * @param[in] cmd: Command. + * + * @param[in] arg0: Arguments for the command. + * + * @param[in] arg1: Arguments for the command. + * + * @return 0 + * + */ +VOID jpegIoctl(UINT32 cmd, UINT32 arg0, UINT32 arg1) +{ + struct nu_jpeg_ioctl sNuJpegIoctl; + + sNuJpegIoctl.arg0 = arg0; + sNuJpegIoctl.arg1 = arg1; + + rt_device_control(&g_sNuJpeg.dev, cmd, (void *)&sNuJpegIoctl); +} + +/** + * @brief JPEG function close. + * + * @return 0 + * + */ +VOID jpegClose(void) +{ + rt_device_close(&g_sNuJpeg.dev); +} + +static rt_err_t nu_jpeg_init(rt_device_t dev) +{ + UINT32 u32JPGDiv = 0; + UINT32 u32JPGSource; + UINT32 u32HclkHz; + nu_jpeg_t psNuJpeg = (nu_jpeg_t)dev; + + RT_ASSERT(dev != RT_NULL); + + /* Set JPEG engine clock */ + u32HclkHz = sysGetClock(SYS_HCLK234) * 1000000; + u32JPGSource = u32HclkHz / (((inp32(REG_CLK_DIVCTL3) & 0xf0000000) >> 28) + 1); + + if (u32JPGSource > 75000000) + { + if (u32JPGSource % 75000000) + { + u32JPGDiv = (u32JPGSource / 75000000); + } + else + u32JPGDiv = (u32JPGSource / 75000000) - 1; + } + outp32(REG_CLK_DIVCTL3, (inp32(REG_CLK_DIVCTL3) & ~(0xf0000000)) | ((u32JPGDiv & 0xf) << 28)); + + rt_kprintf("JPEG Engine clock frequency is %d MHz\n", u32JPGSource / (u32JPGDiv + 1) / 1000000); + + /* Register ISR and Response JPEG Interrupt. */ + rt_hw_interrupt_install(psNuJpeg->irqn, nu_jpeg_isr, (void *)psNuJpeg, psNuJpeg->name); + rt_hw_interrupt_umask(psNuJpeg->irqn); + + return RT_EOK; +} + +static rt_err_t nu_jpeg_open(rt_device_t dev, rt_uint16_t oflag) +{ + rt_err_t result; + nu_jpeg_t psNuJpeg = (nu_jpeg_t)dev; + + result = rt_mutex_take(&psNuJpeg->lock, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + /* Enable JPEG engine clock */ + nu_sys_ipclk_enable(psNuJpeg->clkidx); + + /* Reset JPEG codec and internal variables. */ + nu_sys_ip_reset(psNuJpeg->rstidx); + jpegInit(); + + result = rt_mutex_release(&psNuJpeg->lock); + RT_ASSERT(result == RT_EOK); + + return RT_EOK; +} + +static rt_err_t nu_jpeg_close(rt_device_t dev) +{ + rt_err_t result; + nu_jpeg_t psNuJpeg = (nu_jpeg_t)dev; + + RT_ASSERT(dev != RT_NULL); + + result = rt_mutex_take(&psNuJpeg->lock, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + /* Reset JPEG (JMCR [1]) */ + outp32(REG_JMCR, 0x00000002); + outp32(REG_JMCR, 0x00000000); + + /* Disable JPEG engine clock */ + nu_sys_ipclk_disable(psNuJpeg->clkidx); + + result = rt_mutex_release(&psNuJpeg->lock); + RT_ASSERT(result == RT_EOK); + + return RT_EOK; +} + +static rt_err_t nu_jpeg_control(rt_device_t dev, int cmd, void *args) +{ + JPEG_WINDOW_DECODE_T *winDecode; + PUINT32 pu32Tmp; + UINT32 arg0 = 0, arg1 = 0; + rt_err_t result; + nu_jpeg_t psNuJpeg = (nu_jpeg_t)dev; + + nu_jpeg_ioctl_t psNuJpegIoctl = (nu_jpeg_ioctl_t)args; + + RT_ASSERT(dev != RT_NULL); + + result = rt_mutex_take(&psNuJpeg->lock, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + if (psNuJpegIoctl != RT_NULL) + { + arg0 = psNuJpegIoctl->arg0; + arg1 = psNuJpegIoctl->arg1; + } + + switch (cmd) + { + case JPEG_IOCTL_SET_YADDR: + JPEG_SET_YADDR(arg0); + break; + case JPEG_IOCTL_SET_UADDR: + JPEG_SET_UADDR(arg0); + break; + case JPEG_IOCTL_SET_VADDR: + JPEG_SET_VADDR(arg0); + break; + case JPEG_IOCTL_SET_YSTRIDE: + JPEG_SET_YSTRIDE(arg0); + break; + case JPEG_IOCTL_SET_USTRIDE: + JPEG_SET_USTRIDE(arg0); + break; + case JPEG_IOCTL_SET_VSTRIDE: + JPEG_SET_VSTRIDE(arg0); + break; + case JPEG_IOCTL_SET_BITSTREAM_ADDR: + JPEG_SET_BITSTREAM_ADDR(arg0); + break; + case JPEG_IOCTL_SET_SOURCE_IMAGE_HEIGHT: + JPEG_SET_SOURCE_IMAGE_HEIGHT(arg0); + break; + case JPEG_IOCTL_ENC_SET_HEADER_CONTROL: + JPEG_ENC_SET_HEADER_CONTROL(arg0); + break; + case JPEG_IOCTL_SET_DEFAULT_QTAB: + jpegSetQTAB(g_au8QTable0, g_au8QTable1, 0, 2); + break; + case JPEG_IOCTL_SET_DECODE_MODE: + jpegSetDecodeMode(arg0); + break; + case JPEG_IOCTL_SET_ENCODE_MODE: + jpegSetEncodeMode(arg0, arg1); + break; + case JPEG_IOCTL_SET_DIMENSION: + jpegSetDimension(arg0, arg1); + break; + case JPEG_IOCTL_ENCODE_TRIGGER: + jpegEncodeTrigger(); + if (g_u16ReserveSize != 0) + { + UINT32 u32Addr = JPEG_GET_BITSTREAM_ADDR(); + outp8(u32Addr + 2, 0xFF); + outp8(u32Addr + 3, 0xE0); + outp8(u32Addr + 4, ((g_u16ReserveSize - 4) & 0xFF00) >> 8); + outp8(u32Addr + 5, (g_u16ReserveSize - 4) & 0xFF); + } + break; + case JPEG_IOCTL_DECODE_TRIGGER: + jpegDecodeTrigger(); + break; + case JPEG_IOCTL_WINDOW_DECODE: + winDecode = (JPEG_WINDOW_DECODE_T *)arg0; + jpegSetWindowDecode(winDecode->u16StartMCUX, winDecode->u16StartMCUY, + winDecode->u16EndMCUX, winDecode->u16EndMCUY, winDecode->u32Stride); + g_u32WindowDec = TRUE; + g_u32windowSizeX = winDecode->u32Stride; + g_u32windowSizeY = 16 * (winDecode->u16EndMCUY - winDecode->u16StartMCUY + 1); + + break; + case JPEG_IOCTL_SET_DECODE_STRIDE: + g_u32Stride = arg0; + break; + case JPEG_IOCTL_SET_DECODE_DOWNSCALE: + g_bScale = TRUE; + g_u32ScaleWidth = arg1; + g_u32ScaleHeight = arg0; + break; + case JPEG_IOCTL_SET_ENCODE_UPSCALE: + g_bScale = TRUE; + g_u32ScaleWidth = arg1; + g_u32ScaleHeight = arg0; + break; + case JPEG_IOCTL_SET_HEADERDECODE_CALBACKFUN: + pfnJpegHeaderDecode = (PFN_JPEG_HEADERDECODE_CALLBACK) arg0; + break; + case JPEG_IOCTL_SET_DECINPUTWAIT_CALBACKFUN: + g_InputWait = TRUE; + pfnJpegDecInputWait = (PFN_JPEG_DECWAIT_CALLBACK) arg0; + JPEG_DEC_SET_INPUT_WAIT(((UINT16) arg1 / 2048)); + g_u16BufferSize = arg1 / 2; + break; + case JPEG_IOCTL_ADJUST_QTAB: + jpegAdjustQTAB(arg0, ((arg1 & 0xFF00) >> 4), (arg1 & 0xFF)); + break; + case JPEG_IOCTL_ENC_RESERVED_FOR_SOFTWARE: + if (arg0 > 0) + { + UINT32 u32Tmp; + + u32Tmp = arg0 + 4; + if (u32Tmp % 2) + u32Tmp++; + if ((u32Tmp % 4) == 0) + u32Tmp += 2; + if (u32Tmp >= 0xFFFF) + u32Tmp = 65534; + + outp32(REG_JPSCALU, inp32(REG_JPSCALU) | A_JUMP); + outp32(JRESERVE, u32Tmp); + g_u16ReserveSize = u32Tmp; + } + break; + case JPEG_IOCTL_SET_ENCODE_PRIMARY_RESTART_INTERVAL: + outp32(REG_JPRST, arg0); + break; + case JPEG_IOCTL_SET_ENCODE_THUMBNAIL_RESTART_INTERVAL: + outp32(REG_JTRST, arg0); + break; + case JPEG_IOCTL_GET_ENCODE_PRIMARY_RESTART_INTERVAL: + pu32Tmp = (PUINT32) arg0; + *pu32Tmp = inp32(REG_JPRST); + break; + case JPEG_IOCTL_GET_ENCODE_THUMBNAIL_RESTART_INTERVAL: + pu32Tmp = (PUINT32) arg0; + *pu32Tmp = inp32(REG_JTRST); + break; + + case JPEG_IOCTL_SET_THUMBNAIL_DIMENSION: + outp32(REG_JTHBWH, ((arg0 & 0x1FFF) << 16) | (arg1 & 0x1FFF)); + break; + case JPEG_IOCTL_SET_ENCODE_SW_OFFSET: + outp32(REG_JOFFSET, arg0); + break; + case JPEG_IOCTL_GET_THUMBNAIL_DIMENSION: + pu32Tmp = (PUINT32) arg0; + *pu32Tmp = inp32(REG_JTHBWH) >> 16; + pu32Tmp = (PUINT32) arg1; + *pu32Tmp = inp32(REG_JTHBWH) & 0x1FFF; + break; + case JPEG_IOCTL_GET_ENCODE_SW_OFFSET: + pu32Tmp = (PUINT32) arg0; + *pu32Tmp = inp32(REG_JOFFSET); + break; + case JPEG_IOCTL_SET_ENCODE_PRIMARY_DOWNSCALE: + g_bScale = TRUE; + g_bEncPrimaryDownScale = TRUE; + g_u32ScaleWidth = arg1; + g_u32ScaleHeight = arg0; + break; + case JPEG_IOCTL_SET_ENCODE_THUMBNAIL_DOWNSCALE: + g_bScale = TRUE; + g_bEncThumbnailDownScale = TRUE; + g_u32ScaleWidth = arg1; + g_u32ScaleHeight = arg0; + break; + case JPEG_IOCTL_SET_ENCODE_PRIMARY_ROTATE_RIGHT: + g_u32EncRotate = JPEG_IOCTL_SET_ENCODE_PRIMARY_ROTATE_RIGHT; + outp32(REG_JITCR, (inp32(REG_JITCR) & ~ROTATE) | ROTATE); + break; + case JPEG_IOCTL_SET_ENCODE_PRIMARY_ROTATE_LEFT: + g_u32EncRotate = JPEG_IOCTL_SET_ENCODE_PRIMARY_ROTATE_LEFT; + outp32(REG_JITCR, (inp32(REG_JITCR) & ~ROTATE) | 0x1000); + break; + case JPEG_IOCTL_SET_ENCODE_PRIMARY_ROTATE_NORMAL: + g_u32EncRotate = 0; + outp32(REG_JITCR, (inp32(REG_JITCR) & ~ROTATE)); + break; + case JPEG_IOCTL_SET_DECOUTPUTWAIT_CALBACKFUN: + pfnJpegDecOutputWait = (PFN_JPEG_DECWAIT_CALLBACK) arg0; + break; + case JPEG_IOCTL_SET_DECOUTPUTWAIT: + outp32(JYADDR0, arg0); + outp32(JDOWFBS, arg1); + g_OutputWait = TRUE; + break; + case JPEG_IOCTL_GET_DECOUTPUTWAIT_ADDR: + pu32Tmp = (PUINT32) arg0; + *pu32Tmp = inp32(JYADDR0); + break; + case JPEG_IOCTL_GET_DECOUTPUTWAIT_SIZE: + pu32Tmp = (PUINT32) arg0; + *pu32Tmp = inp32(JDOWFBS); + break; + case JPEG_IOCTL_SET_DECODE_COMPLETE_CALBACKFUN: + pfnJpegDecodeComplete = (PFN_JPEG_CALLBACK) arg0; + break; + case JPEG_IOCTL_SET_ENCODE_COMPLETE_CALBACKFUN: + pfnJpegEncodeComplete = (PFN_JPEG_CALLBACK) arg0; + break; + case JPEG_IOCTL_SET_DECODE_ERROR_CALBACKFUN: + pfnJpegDecodeError = (PFN_JPEG_CALLBACK) arg0; + break; + + /* Extended IOCTL command */ + case JPEG_IOCTL_SET_QTAB: + { + nu_jpeg_qtab_t psJpegQtab = (nu_jpeg_qtab_t)arg0; + INT *pi32ret = (INT *)arg1; + *pi32ret = _jpegSetQTAB(psJpegQtab->puQTable0, psJpegQtab->puQTable1, psJpegQtab->puQTable2, psJpegQtab->u8num); + } + break; + case JPEG_IOCTL_INITIAL_CODEC: + _jpegInit(); + break; + case JPEG_IOCTL_GET_INFO: + _jpegGetInfo((JPEG_INFO_T *)arg0); + break; + case JPEG_IOCTL_IS_READY: + { + UINT32 *pu32ret = (UINT32 *)arg0; + *pu32ret = _jpegIsReady(); + + } + break; + case JPEG_IOCTL_WAITDONE: + { + INT *pi32ret = (INT *)arg0; + *pi32ret = _jpegWait(); + } + break; + + default: + break; + } + + result = rt_mutex_release(&psNuJpeg->lock); + RT_ASSERT(result == RT_EOK); + + return RT_EOK; +} + +/* Hardward JPEG codec init */ +static int rt_hw_jpeg_init(void) +{ + rt_err_t ret = RT_EOK; + + /* Register sdcard device */ + g_sNuJpeg.dev.type = RT_Device_Class_Miscellaneous; + g_sNuJpeg.dev.init = nu_jpeg_init; + g_sNuJpeg.dev.open = nu_jpeg_open; + g_sNuJpeg.dev.close = nu_jpeg_close; + g_sNuJpeg.dev.read = RT_NULL; + g_sNuJpeg.dev.write = RT_NULL; + g_sNuJpeg.dev.control = nu_jpeg_control; + + /* Private */ + g_sNuJpeg.dev.user_data = (void *)&g_sNuJpeg; + + ret = rt_mutex_init(&g_sNuJpeg.lock, "jpeg_lock", RT_IPC_FLAG_PRIO); + RT_ASSERT(ret == RT_EOK); + + /* Only support single opening. */ + ret = rt_device_register(&g_sNuJpeg.dev, g_sNuJpeg.name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); + RT_ASSERT(ret == RT_EOK); + + return (int)ret; +} +INIT_DEVICE_EXPORT(rt_hw_jpeg_init); diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_pwm.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_pwm.c new file mode 100644 index 0000000000..ce77b21aa8 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_pwm.c @@ -0,0 +1,293 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-1 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_PWM) + +#define LOG_TAG "drv.pwm" +#define DBG_ENABLE +#define DBG_SECTION_NAME "drv.pwm" +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include + +#include +#include +#include +#include "NuMicro.h" +#include "drv_sys.h" + +enum +{ + PWM_START = -1, +#if defined(BSP_USING_PWM0) + PWM0_IDX, +#endif + PWM_CNT +}; + +#define NU_PWM_BA_DISTANCE 0 +#define NU_PWM_CHANNEL_NUM 4 + +struct nu_pwm +{ + struct rt_device_pwm dev; + char *name; + uint32_t base_addr; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; +}; + +typedef struct nu_pwm *nu_pwm_t; + +static struct nu_pwm nu_pwm_arr [] = +{ +#if defined(BSP_USING_PWM0) + { + .name = "pwm0", + .base_addr = PWM_BA, + .rstidx = PWMRST, + .clkidx = PWMCKEN, + }, +#endif + +}; /* pwm nu_pwm */ + +static rt_err_t nu_pwm_control(struct rt_device_pwm *device, int cmd, void *arg); + +static struct rt_pwm_ops nu_pwm_ops = +{ + .control = nu_pwm_control +}; + +static rt_err_t nu_pwm_enable(struct rt_device_pwm *device, struct rt_pwm_configuration *config, rt_bool_t enable) +{ + nu_pwm_t psNuPWM = (nu_pwm_t)device; + + rt_err_t result = RT_EOK; + rt_uint32_t ch = config->channel; + + if (enable == RT_TRUE) + { + uint32_t u32RegAdrrPCR = psNuPWM->base_addr + 0x8; + uint32_t u32PCRChAlign = (!ch) ? 0x9 : (0x9 << (4 + ch * 4)); + + /* Period and enable channel. */ + outpw(u32RegAdrrPCR, inpw(u32RegAdrrPCR) | u32PCRChAlign); + } + else + { + uint32_t u32RegAdrrPCR = psNuPWM->base_addr + 0x8; + uint32_t u32PCRChAlign = (!ch) ? 0x1 : (0x1 << (4 + ch * 4)); + + outpw(u32RegAdrrPCR, inpw(u32RegAdrrPCR) & ~u32PCRChAlign); + } + + return result; +} + +static rt_err_t nu_pwm_get(struct rt_device_pwm *device, struct rt_pwm_configuration *config) +{ + nu_pwm_t psNuPWM = (nu_pwm_t)device; + uint32_t u32RegAdrrPPR = psNuPWM->base_addr; + uint32_t u32RegAdrrCSR = psNuPWM->base_addr + 0x04; + uint32_t u32RegAdrrCNR = psNuPWM->base_addr + 0xC + (config->channel * 0xC); + uint32_t u32RegAdrrCMR = psNuPWM->base_addr + 0x10 + (config->channel * 0xC); + uint32_t u32PWMSrcClk = sysGetClock(SYS_PCLK) * 1000000; + uint32_t u32CMR, u32CNR; + double douDutyCycle; /* unit:% */ + uint32_t u32PWMOutClk; /* unit:Hz */ + uint32_t u32Prescale, u32Divider; + + u32CNR = inpw(u32RegAdrrCNR) + 1; + u32CMR = inpw(u32RegAdrrCMR) + 1; + u32Prescale = ((inpw(u32RegAdrrPPR) & (0xff << ((config->channel >> 1) * 8))) >> ((config->channel >> 1) * 8)) + 1; + u32Divider = (inpw(u32RegAdrrCSR) & (0x7 << (4 * config->channel))) >> (4 * config->channel); + + /* Re-convert register to real value */ + if (u32Divider == 4) + u32Divider = 1; + else if (u32Divider == 0) + u32Divider = 2; + else if (u32Divider == 1) + u32Divider = 4; + else if (u32Divider == 2) + u32Divider = 8; + else // 3 + u32Divider = 16; + + douDutyCycle = (double)u32CMR / u32CNR; + + u32PWMOutClk = u32PWMSrcClk / (u32Prescale * u32Divider * u32CNR); + + config->period = 1000000000 / u32PWMOutClk; /* In ns. */ + config->pulse = douDutyCycle * config->period; + + LOG_I("%s %d %d %d\n", ((nu_pwm_t)device)->name, config->channel, config->period, config->pulse); + + return RT_EOK; +} + +uint32_t nu_pwm_config(uint32_t u32PwmBaseAddr, uint32_t u32ChannelNum, uint32_t u32Frequency, uint32_t u32PulseInHz) +{ + uint32_t i; + uint8_t u8Divider = 1, u8Prescale = 0xFF; + uint16_t u16CNR = 0xFFFF; + uint16_t u16CMR = 0xFFFF; + uint32_t u32RegAdrrPPR = u32PwmBaseAddr; + uint32_t u32RegAdrrCSR = u32PwmBaseAddr + 0x04; + uint32_t u32RegAdrrCNR = u32PwmBaseAddr + 0xC + (u32ChannelNum * 0xC); + uint32_t u32RegAdrrCMR = u32PwmBaseAddr + 0x10 + (u32ChannelNum * 0xC); + uint32_t u32PWMSrcClk = sysGetClock(SYS_PCLK) * 1000000; + uint32_t u32PWMOutClk = 0; + + if (u32Frequency > u32PWMSrcClk) + return 0; + + /* + PWM_Freq = PCLK2 / (Prescale+1) / (Clock Divider) / (CNR+1) + PCLK / PWM_Freq = (Prescale+1) * (Clock Divider) * (CNR+1) + PCLK / PWM_Freq / (Clock Divider) = (Prescale+1) * (CNR+1) + */ + + /* clk divider could only be 1, 2, 4, 8, 16 */ + for (; u8Divider < 17; u8Divider <<= 1) + { + i = (u32PWMSrcClk / u32Frequency) / u8Divider; + + /* If target value is larger than CNR * prescale, need to use a larger divider */ + if (i > (0x10000 * 0x100)) + continue; + + /* CNR = 0xFFFF + 1, get a prescaler that CNR value is below 0xFFFF */ + u8Prescale = (i + 0xFFFF) / 0x10000; + + /* u8Prescale must at least be 2, otherwise the output stop */ + if (u8Prescale < 2) + u8Prescale = 2; + + i /= u8Prescale; + if (i < 0x10000) + { + if (i == 1) + u16CNR = 1; // Too fast, and PWM cannot generate expected frequency... + else + u16CNR = i; + + break; + } + } + + u32PWMOutClk = u32PWMSrcClk / (u8Prescale * u8Divider * u16CNR); + + /* For fill into registers. */ + u8Prescale -= 1; + u16CNR -= 1; + + /* Convert to real register value */ + if (u8Divider == 1) + u8Divider = 4; + else if (u8Divider == 2) + u8Divider = 0; + else if (u8Divider == 4) + u8Divider = 1; + else if (u8Divider == 8) + u8Divider = 2; + else // 16 + u8Divider = 3; + + /* Every two channels share a prescaler */ + outpw(u32RegAdrrPPR, (inpw(u32RegAdrrPPR) & ~(0xff << ((u32ChannelNum >> 1) * 8))) | (u8Prescale << ((u32ChannelNum >> 1) * 8))); + + /* Update CLKSEL in specified channel in CSR field. */ + outpw(u32RegAdrrCSR, inpw(u32RegAdrrCSR) & ~(0x7 << (4 * u32ChannelNum)) | (u8Divider << (4 * u32ChannelNum))); + + u16CMR = u32Frequency * (u16CNR + 1) / u32PulseInHz; + + outpw(u32RegAdrrCMR, (u16CMR == 0) ? 0 : u16CMR - 1); + outpw(u32RegAdrrCNR, u16CNR); + + return (u32PWMOutClk); +} + +static rt_err_t nu_pwm_set(struct rt_device_pwm *device, struct rt_pwm_configuration *config) +{ + nu_pwm_t psNuPWM = (nu_pwm_t)device; + rt_err_t result = RT_EINVAL; + rt_uint32_t u32FreqInHz; /* unit:Hz */ + rt_uint32_t u32PulseInHz; /* unit:% */ + + if (config->period < 1000 || !config->period || !config->pulse) + goto exit_nu_pwm_set; + + /* Calculate frequency, Unit is in us. */ + u32FreqInHz = (1000000000) / config->period; + u32PulseInHz = (1000000000) / config->pulse; + + nu_pwm_config(psNuPWM->base_addr, config->channel, u32FreqInHz, u32PulseInHz); + + result = RT_EOK; + +exit_nu_pwm_set: + + return -(result); +} + +static rt_err_t nu_pwm_control(struct rt_device_pwm *device, int cmd, void *arg) +{ + struct rt_pwm_configuration *config = (struct rt_pwm_configuration *)arg; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(config != RT_NULL); + + if (config->channel > NU_PWM_CHANNEL_NUM) + return -(RT_EINVAL); + + switch (cmd) + { + case PWM_CMD_ENABLE: + return nu_pwm_enable(device, config, RT_TRUE); + case PWM_CMD_DISABLE: + return nu_pwm_enable(device, config, RT_FALSE); + case PWM_CMD_SET: + return nu_pwm_set(device, config); + case PWM_CMD_GET: + return nu_pwm_get(device, config); + default: + break; + } + + return -(RT_ERROR); +} + +int rt_hw_pwm_init(void) +{ + rt_err_t ret; + int i; + + for (i = (PWM_START + 1); i < PWM_CNT; i++) + { + nu_sys_ipclk_enable(nu_pwm_arr[i].clkidx); + + nu_sys_ip_reset(nu_pwm_arr[i].rstidx); + + ret = rt_device_pwm_register(&nu_pwm_arr[i].dev, nu_pwm_arr[i].name, &nu_pwm_ops, RT_NULL); + RT_ASSERT(ret == RT_EOK); + } + + return 0; +} + +INIT_DEVICE_EXPORT(rt_hw_pwm_init); + +#endif diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.c new file mode 100644 index 0000000000..1cbcbc58a1 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.c @@ -0,0 +1,557 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-2-11 Wayne First version +* +******************************************************************************/ +#include + +#if defined(BSP_USING_QSPI) + +#include +#include "NuMicro.h" +#include +#include +#include + +#define LOG_TAG "drv.qspi" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include + +#include +#include +#include + +/* Private define ---------------------------------------------------------------*/ + +/* fsclk = fpclk / ((div+1)*2), but div=1 is suggested. */ +#define DEF_SPI_MAX_SPEED (SPI_INPUT_CLOCK/((1)*2)) + +enum +{ + QSPI_START = -1, +#if defined(BSP_USING_QSPI0) + QSPI0_IDX, +#endif +#if defined(BSP_USING_QSPI1) + QSPI1_IDX, +#endif + QSPI_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ +struct nu_qspi +{ + struct rt_spi_bus dev; + char *name; + uint32_t idx; + + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + uint32_t dummy; + + struct rt_qspi_configuration configuration; +}; +typedef struct nu_qspi *nu_qspi_t; + +/* Private functions ------------------------------------------------------------*/ +static void nu_qspi_transmission_with_poll(struct nu_qspi *spi_bus, + uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word); +static int nu_qspi_register_bus(struct nu_qspi *spi_bus, const char *name); +static rt_uint32_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message); +static rt_err_t nu_qspi_bus_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration); + +/* Public functions -------------------------------------------------------------*/ + +/* Private variables ------------------------------------------------------------*/ +static struct rt_spi_ops nu_qspi_poll_ops = +{ + .configure = nu_qspi_bus_configure, + .xfer = nu_qspi_bus_xfer, +}; + +static struct nu_qspi nu_qspi_arr [] = +{ +#if defined(BSP_USING_QSPI0) + { + .name = "qspi0", + .idx = 0, + .rstidx = SPI0RST, + .clkidx = SPI0CKEN, + }, +#endif +#if defined(BSP_USING_QSPI1) + { + .name = "qspi1", + .idx = 1, + .rstidx = SPI1RST, + .clkidx = SPI1CKEN, + }, +#endif +}; /* nu_qspi */ + +static rt_err_t nu_qspi_bus_configure(struct rt_spi_device *device, + struct rt_spi_configuration *configuration) +{ + struct nu_qspi *qspi_bus; + uint32_t u32SPIMode; + uint32_t u32SPISpeed; + rt_err_t ret = RT_EOK; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + qspi_bus = (struct nu_qspi *) device->bus; + + /* Check mode */ + switch (configuration->mode & RT_SPI_MODE_3) + { + case RT_SPI_MODE_0: + u32SPIMode = SPI_MODE_0; + break; + case RT_SPI_MODE_1: + u32SPIMode = SPI_MODE_1; + break; + case RT_SPI_MODE_2: + u32SPIMode = SPI_MODE_2; + break; + case RT_SPI_MODE_3: + u32SPIMode = SPI_MODE_3; + break; + default: + ret = RT_EIO; + goto exit_nu_qspi_bus_configure; + } + + /* Check data width */ + if (!(configuration->data_width == 8 || + configuration->data_width == 16 || + configuration->data_width == 24 || + configuration->data_width == 32)) + { + ret = RT_EINVAL; + goto exit_nu_qspi_bus_configure; + } + + /* Need to initialize new configuration? */ + if (rt_memcmp(configuration, &qspi_bus->configuration, sizeof(*configuration)) != 0) + { + rt_memcpy(&qspi_bus->configuration, configuration, sizeof(*configuration)); + + /* Set mode */ + spiIoctl(qspi_bus->idx, SPI_IOC_SET_MODE, (uint32_t)u32SPIMode, 0); + + /* Set data width */ + spiIoctl(qspi_bus->idx, SPI_IOC_SET_TX_BITLEN, (uint32_t)configuration->data_width, 0); + + /* Set speed */ + u32SPISpeed = configuration->max_hz; + if (u32SPISpeed > DEF_SPI_MAX_SPEED) + u32SPISpeed = DEF_SPI_MAX_SPEED; + + u32SPISpeed = spiIoctl(qspi_bus->idx, SPI_IOC_SET_SPEED, u32SPISpeed, 0); + LOG_I("Actual=%dHz, Prefer=%dHz", u32SPISpeed, configuration->max_hz); + + /* Disable auto-select */ + spiIoctl(qspi_bus->idx, SPI_IOC_SET_AUTOSS, SPI_DISABLE_AUTOSS, 0); + + if (configuration->mode & RT_SPI_CS_HIGH) + { + /* Set CS pin to LOW */ + spiIoctl(qspi_bus->idx, SPI_IOC_SET_SS_ACTIVE_LEVEL, SPI_SS_ACTIVE_HIGH, 0); + } + else + { + /* Set CS pin to HIGH */ + spiIoctl(qspi_bus->idx, SPI_IOC_SET_SS_ACTIVE_LEVEL, SPI_SS_ACTIVE_LOW, 0); + } + + if (configuration->mode & RT_SPI_MSB) + { + /* Set sequence to MSB first */ + spiIoctl(qspi_bus->idx, SPI_IOC_SET_LSB_MSB, SPI_MSB, 0); + } + else + { + /* Set sequence to LSB first */ + spiIoctl(qspi_bus->idx, SPI_IOC_SET_LSB_MSB, SPI_LSB, 0); + } + } + +exit_nu_qspi_bus_configure: + + return -(ret); +} + +static int nu_qspi_read(uint32_t idx, uint32_t buf_id, uint8_t *recv_addr, uint8_t bytes_per_word) +{ + uint32_t val; + + // Read data from SPI RX FIFO + switch (bytes_per_word) + { + case 4: + val = spiRead(idx, buf_id); + nu_set32_le(recv_addr, val); + break; + case 3: + val = spiRead(idx, buf_id); + nu_set24_le(recv_addr, val); + break; + case 2: + val = spiRead(idx, buf_id); + nu_set16_le(recv_addr, val); + break; + case 1: + *recv_addr = spiRead(idx, buf_id); + break; + default: + LOG_E("Data length is not supported.\n"); + return 0; + } + return bytes_per_word; +} + +static int nu_qspi_write(uint32_t idx, uint32_t buf_id, const uint8_t *send_addr, uint8_t bytes_per_word) +{ + // Input data to SPI TX + switch (bytes_per_word) + { + case 4: + spiWrite(idx, buf_id, nu_get32_le(send_addr)); + break; + case 3: + spiWrite(idx, buf_id, nu_get24_le(send_addr)); + break; + case 2: + spiWrite(idx, buf_id, nu_get16_le(send_addr)); + break; + case 1: + spiWrite(idx, buf_id, *((uint8_t *)send_addr)); + break; + default: + LOG_E("Data length is not supported.\n"); + return 0; + } + return bytes_per_word; +} + +/** + * @brief SPI bus polling + * @param dev : The pointer of the specified SPI module. + * @param send_addr : Source address + * @param recv_addr : Destination address + * @param length : Data length + */ +static void nu_qspi_transmission_with_poll(struct nu_qspi *spi_bus, + uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word) +{ + uint32_t idx = spi_bus->idx; + int trans_num = length / bytes_per_word; + + while (trans_num > 0) + { + int i; + + uint32_t u32TxNum = (trans_num > 4) ? 4 : trans_num; + + for (i = 0; i < u32TxNum; i++) + { + /* Write TX data into TX-buffer */ + if ((send_addr != RT_NULL)) + { + send_addr += nu_qspi_write(idx, i, (const uint8_t *)send_addr, bytes_per_word); + } + else /* read-only */ + { + spi_bus->dummy = 0; + nu_qspi_write(idx, i, (const uint8_t *)&spi_bus->dummy, bytes_per_word); + } + } + + /* Set TX transacation number */ + spiIoctl(idx, SPI_IOC_SET_TX_NUM, u32TxNum - 1, 0); + + /* Trigger SPI communication. */ + spiIoctl(idx, SPI_IOC_TRIGGER, 0, 0); + + /* Wait it done. */ + while (spiGetBusyStatus(idx)) {}; + + /* Read data from RX-buffer */ + if ((recv_addr != RT_NULL)) + { + for (i = 0; i < u32TxNum; i++) + { + recv_addr += nu_qspi_read(idx, i, recv_addr, bytes_per_word); + } + } + + trans_num -= u32TxNum; + } +} + +void nu_qspi_transfer(struct nu_qspi *spi_bus, uint8_t *tx, uint8_t *rx, int length, uint8_t bytes_per_word) +{ + RT_ASSERT(spi_bus != RT_NULL); + nu_qspi_transmission_with_poll(spi_bus, tx, rx, length, bytes_per_word); +} + +static int nu_qspi_mode_config(struct nu_qspi *spi_bus, rt_uint8_t *tx, rt_uint8_t *rx, int qspi_lines) +{ + uint32_t idx = spi_bus->idx; + if (qspi_lines > 1) + { + if (tx) + { + switch (qspi_lines) + { + case 2: + spiIoctl(idx, SPI_IOC_SET_DUAL_QUAD_MODE, SPI_DUAL_MODE, 0); + break; + case 4: + spiIoctl(idx, SPI_IOC_SET_DUAL_QUAD_MODE, SPI_QUAD_MODE, 0); + break; + default: + LOG_E("Data line is not supported.\n"); + return -1; + } + spiIoctl(idx, SPI_IOC_SET_DUAL_QUAD_DIR, SPI_DUAL_QUAD_OUTPUT, 0); + } + else if (rx) + { + switch (qspi_lines) + { + case 2: + spiIoctl(idx, SPI_IOC_SET_DUAL_QUAD_MODE, SPI_DUAL_MODE, 0); + break; + case 4: + spiIoctl(idx, SPI_IOC_SET_DUAL_QUAD_MODE, SPI_QUAD_MODE, 0); + break; + default: + LOG_E("Data line is not supported.\n"); + return -1; + } + spiIoctl(idx, SPI_IOC_SET_DUAL_QUAD_DIR, SPI_DUAL_QUAD_INPUT, 0); + } + } + else + { + spiIoctl(idx, SPI_IOC_SET_DUAL_QUAD_MODE, SPI_DISABLE_DUAL_QUAD, 0); + } + return qspi_lines; +} + +static rt_uint32_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + struct nu_qspi *spi_bus; + struct rt_qspi_configuration *qspi_configuration; + struct rt_qspi_message *qspi_message; + rt_uint8_t u8last = 1; + rt_uint8_t bytes_per_word; + uint32_t idx; + rt_uint32_t u32len = 0; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(message != RT_NULL); + + spi_bus = (struct nu_qspi *) device->bus; + idx = spi_bus->idx; + qspi_configuration = &spi_bus->configuration; + + bytes_per_word = qspi_configuration->parent.data_width / 8; + + if (message->cs_take && !(qspi_configuration->parent.mode & RT_SPI_NO_CS)) + { + /* /CS: active */ + /* We just use CS0 only. if you need CS1, please use pin controlling before sending message. */ + spiIoctl(idx, SPI_IOC_ENABLE_SS, SPI_SS_SS0, 0); + } + + qspi_message = (struct rt_qspi_message *)message; + + /* Command + Address + Dummy + Data */ + /* Command stage */ + if (qspi_message->instruction.content != 0) + { + u8last = nu_qspi_mode_config(spi_bus, (rt_uint8_t *) &qspi_message->instruction.content, RT_NULL, qspi_message->instruction.qspi_lines); + nu_qspi_transfer((struct nu_qspi *)spi_bus, + (rt_uint8_t *) &qspi_message->instruction.content, + RT_NULL, + 1, + 1); + } + + /* Address stage */ + if (qspi_message->address.size > 0) + { + rt_uint32_t u32ReversedAddr = 0; + rt_uint32_t u32AddrNumOfByte = qspi_message->address.size / 8; + switch (u32AddrNumOfByte) + { + case 1: + u32ReversedAddr = (qspi_message->address.content & 0xff); + break; + case 2: + nu_set16_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content); + break; + case 3: + nu_set24_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content); + break; + case 4: + nu_set32_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content); + break; + default: + RT_ASSERT(0); + break; + } + u8last = nu_qspi_mode_config(spi_bus, (rt_uint8_t *)&u32ReversedAddr, RT_NULL, qspi_message->address.qspi_lines); + nu_qspi_transfer((struct nu_qspi *)spi_bus, + (rt_uint8_t *) &u32ReversedAddr, + RT_NULL, + u32AddrNumOfByte, + 1); + } + + /* alternate_bytes stage */ + if ((qspi_message->alternate_bytes.size > 0) && (qspi_message->alternate_bytes.size <= 4)) + { + rt_uint32_t u32AlternateByte = 0; + rt_uint32_t u32NumOfByte = qspi_message->alternate_bytes.size / 8; + switch (u32NumOfByte) + { + case 1: + u32AlternateByte = (qspi_message->alternate_bytes.content & 0xff); + break; + case 2: + nu_set16_be((rt_uint8_t *)&u32AlternateByte, qspi_message->alternate_bytes.content); + break; + case 3: + nu_set24_be((rt_uint8_t *)&u32AlternateByte, qspi_message->alternate_bytes.content); + break; + case 4: + nu_set32_be((rt_uint8_t *)&u32AlternateByte, qspi_message->alternate_bytes.content); + break; + default: + RT_ASSERT(0); + break; + } + u8last = nu_qspi_mode_config(spi_bus, (rt_uint8_t *)&u32AlternateByte, RT_NULL, qspi_message->alternate_bytes.qspi_lines); + nu_qspi_transfer((struct nu_qspi *)spi_bus, + (rt_uint8_t *) &u32AlternateByte, + RT_NULL, + u32NumOfByte, + 1); + } + + /* Dummy_cycles stage */ + if (qspi_message->dummy_cycles > 0) + { + spi_bus->dummy = 0x00; + + u8last = nu_qspi_mode_config(spi_bus, (rt_uint8_t *) &spi_bus->dummy, RT_NULL, u8last); + nu_qspi_transfer((struct nu_qspi *)spi_bus, + (rt_uint8_t *) &spi_bus->dummy, + RT_NULL, + qspi_message->dummy_cycles / (8 / u8last), + 1); + } + + if (message->length > 0) + { + /* Data stage */ + nu_qspi_mode_config(spi_bus, (rt_uint8_t *) message->send_buf, (rt_uint8_t *) message->recv_buf, qspi_message->qspi_data_lines); + nu_qspi_transfer((struct nu_qspi *)spi_bus, + (rt_uint8_t *) message->send_buf, + (rt_uint8_t *) message->recv_buf, + message->length, + bytes_per_word); + u32len = message->length; + } + else + { + u32len = 1; + } + + if (message->cs_release && !(qspi_configuration->parent.mode & RT_SPI_NO_CS)) + { + /* /CS: deactive */ + /* We just use CS0 only. if you need CS1, please use pin controlling before sending message. */ + spiIoctl(idx, SPI_IOC_DISABLE_SS, SPI_SS_SS0, 0); + } + + return u32len; +} + +static int nu_qspi_register_bus(struct nu_qspi *spi_bus, const char *name) +{ + return rt_qspi_bus_register(&spi_bus->dev, name, &nu_qspi_poll_ops); +} + +/** + * Hardware SPI Initial + */ +static int rt_hw_qspi_init(void) +{ + int i; + + for (i = (QSPI_START + 1); i < QSPI_CNT; i++) + { + nu_sys_ipclk_enable(nu_qspi_arr[i].clkidx); + + nu_sys_ip_reset(nu_qspi_arr[i].rstidx); + + spiOpen(nu_qspi_arr[i].idx); + + nu_qspi_register_bus(&nu_qspi_arr[i], nu_qspi_arr[i].name); + } + + return 0; +} + +INIT_DEVICE_EXPORT(rt_hw_qspi_init); + +rt_err_t nu_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!\n"); + 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; +} + +#endif //#if defined(BSP_USING_SPI) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.h b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.h new file mode 100644 index 0000000000..c6b13d7db0 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.h @@ -0,0 +1,20 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-2-7 Wayne First version +* +******************************************************************************/ + +#ifndef __DRV_QSPI_H__ +#define __DRV_QSPI_H__ + +#include + +rt_err_t nu_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)()); + +#endif // __DRV_QSPI_H___ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_rtc.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_rtc.c new file mode 100644 index 0000000000..917cb64b50 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_rtc.c @@ -0,0 +1,386 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-04-12 Wayne First version +* +******************************************************************************/ +#include + +#if defined (BSP_USING_RTC) + +#include +#include +#include "NuMicro.h" +#include + +/* Private define ---------------------------------------------------------------*/ + +/* convert the real year and month value to the format of struct tm. */ +#define CONV_TO_TM_YEAR(year) ((year) - 1900) +#define CONV_TO_TM_MON(mon) ((mon) - 1) + +/* convert the tm_year and tm_mon from struct tm to the real value. */ +#define CONV_FROM_TM_YEAR(tm_year) ((tm_year) + 1900) +#define CONV_FROM_TM_MON(tm_mon) ((tm_mon) + 1) + +/* rtc date upper bound reaches the year of 2099. */ +#define RTC_TM_UPPER_BOUND \ +{ .tm_year = CONV_TO_TM_YEAR(2099), \ + .tm_mon = CONV_TO_TM_MON(12), \ + .tm_mday = 31, \ + .tm_hour = 23, \ + .tm_min = 59, \ + .tm_sec = 59, \ +} + +/* rtc date lower bound reaches the year of 2000. */ +#define RTC_TM_LOWER_BOUND \ +{ .tm_year = CONV_TO_TM_YEAR(2000), \ + .tm_mon = CONV_TO_TM_MON(1), \ + .tm_mday = 1, \ + .tm_hour = 0, \ + .tm_min = 0, \ + .tm_sec = 0, \ +} + +/* Private typedef --------------------------------------------------------------*/ + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_rtc_control(rt_device_t dev, int cmd, void *args); + +#if defined (NU_RTC_SUPPORT_IO_RW) + static rt_size_t nu_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size); + static rt_size_t nu_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size); +#endif + +static rt_err_t nu_rtc_is_date_valid(const time_t *const t); +static void nu_rtc_init(void); + +#if defined(RT_USING_ALARM) + static void nu_rtc_alarm_reset(void); + static void nu_rtc_isr(int vector, void *param); +#endif + +/* Public functions -------------------------------------------------------------*/ +#if defined (NU_RTC_SUPPORT_MSH_CMD) + extern rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day); + extern rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second); +#endif + +/* Private variables ------------------------------------------------------------*/ +static struct rt_device device_rtc; + + +static void nu_rtc_init(void) +{ + S_RTC_TIME_DATA_T sInitTime = {0}; + + nu_sys_ipclk_enable(RTCCKEN); + + /* Time Setting */ + sInitTime.u32Year = 2015; + sInitTime.u32cMonth = 5; + sInitTime.u32cDay = 25; + sInitTime.u32cHour = 13; + sInitTime.u32cMinute = 30; + sInitTime.u32cSecond = 0; + sInitTime.u32cDayOfWeek = RTC_TUESDAY; + sInitTime.u8cClockDisplay = RTC_CLOCK_24; + + /* hw rtc initialise */ + if (RTC_Init() != E_RTC_SUCCESS) + rt_kprintf("[%s] failure!!\n", __func__); + + /* Initialization the RTC timer */ + if (RTC_Open(&sInitTime) != E_RTC_SUCCESS) + rt_kprintf("Open Fail!!\n"); + + /* Do RTC Calibration */ + RTC_Ioctl(0, RTC_IOC_SET_FREQUENCY, 0, 0); + + RTC_DisableInt(RTC_TICK_INT); + RTC_DisableInt(RTC_ALARM_INT); + +#if defined(RT_USING_ALARM) + + nu_rtc_alarm_reset(); + + rt_hw_interrupt_install(IRQ_RTC, nu_rtc_isr, &device_rtc, "rtc"); + rt_hw_interrupt_umask(IRQ_RTC); + +#endif +} + + +#if defined(RT_USING_ALARM) +/* Reset alarm settings to avoid the unwanted values remain in rtc registers. */ +static void nu_rtc_alarm_reset(void) +{ + S_RTC_TIME_DATA_T alarm = {0}; + + /* Reset alarm time and calendar. */ + alarm.u32Year = RTC_YEAR2000; + alarm.u32cMonth = 1; + alarm.u32cDay = 1; + alarm.u8cClockDisplay = RTC_CLOCK_24; + + RTC_Write(RTC_ALARM_TIME, &alarm); + + /* Clear alarm flag for safe */ + RTC_CLEAR_ALARM_INT_FLAG(); +} +#endif + + +/* rtc device driver initialise. */ +int rt_hw_rtc_init(void) +{ + rt_err_t ret; + + nu_rtc_init(); + + /* register rtc device IO operations */ + device_rtc.type = RT_Device_Class_RTC; + device_rtc.init = NULL; + device_rtc.open = NULL; + device_rtc.close = NULL; + device_rtc.control = nu_rtc_control; + +#if defined (NU_RTC_SUPPORT_IO_RW) + device_rtc.read = nu_rtc_read; + device_rtc.write = nu_rtc_write; +#else + device_rtc.read = NULL; + device_rtc.write = NULL; +#endif + + device_rtc.user_data = RT_NULL; + device_rtc.rx_indicate = RT_NULL; + device_rtc.tx_complete = RT_NULL; + + ret = rt_device_register(&device_rtc, "rtc", RT_DEVICE_FLAG_RDWR); + + return (int)ret; +} +INIT_BOARD_EXPORT(rt_hw_rtc_init); + + +#if defined (NU_RTC_SUPPORT_IO_RW) +/* Register rt-thread device.read() entry. */ +static rt_size_t nu_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + (void) pos; + nu_rtc_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, buffer); + + return size; +} +#endif + + +#if defined (NU_RTC_SUPPORT_IO_RW) +/* Register rt-thread device.write() entry. */ +static rt_size_t nu_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + (void) pos; + nu_rtc_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, (void *)buffer); + + return size; +} +#endif + + +static rt_err_t nu_rtc_is_date_valid(const time_t *const t) +{ + static struct tm tm_upper = RTC_TM_UPPER_BOUND; + static struct tm tm_lower = RTC_TM_LOWER_BOUND; + static time_t t_upper, t_lower; + static rt_bool_t initialised = RT_FALSE; + + if (!initialised) + { + t_upper = timegm((struct tm *)&tm_upper); + t_lower = timegm((struct tm *)&tm_lower); + initialised = RT_TRUE; + } + + /* check the date is supported by rtc. */ + if ((*t > t_upper) || (*t < t_lower)) + return -(RT_EINVAL); + + return RT_EOK; +} + + +/* Register rt-thread device.control() entry. */ +static rt_err_t nu_rtc_control(rt_device_t dev, int cmd, void *args) +{ + struct tm tm_out, *tm_in; + time_t *time; + S_RTC_TIME_DATA_T hw_time = {0}; + +#if defined(RT_USING_ALARM) + + struct rt_rtc_wkalarm *wkalarm; + S_RTC_TIME_DATA_T hw_alarm = {0}; +#endif + + if ((dev == NULL) || (args == NULL)) + return -(RT_EINVAL); + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + + time = (time_t *)args; + + if (RTC_Read(RTC_CURRENT_TIME, &hw_time) != E_RTC_SUCCESS) + return -(RT_ERROR); + + tm_out.tm_year = CONV_TO_TM_YEAR(hw_time.u32Year); + tm_out.tm_mon = CONV_TO_TM_MON(hw_time.u32cMonth); + tm_out.tm_mday = hw_time.u32cDay; + tm_out.tm_hour = hw_time.u32cHour; + tm_out.tm_min = hw_time.u32cMinute; + tm_out.tm_sec = hw_time.u32cSecond; + tm_out.tm_wday = hw_time.u32cDayOfWeek; + *time = timegm(&tm_out); + + break; + + case RT_DEVICE_CTRL_RTC_SET_TIME: + + time = (time_t *) args; + tm_in = gmtime(time); + + if (nu_rtc_is_date_valid(time) != RT_EOK) + return -(RT_ERROR); + + hw_time.u32Year = CONV_FROM_TM_YEAR(tm_in->tm_year); + hw_time.u32cMonth = CONV_FROM_TM_MON(tm_in->tm_mon); + hw_time.u32cDay = tm_in->tm_mday; + hw_time.u32cHour = tm_in->tm_hour; + hw_time.u32cMinute = tm_in->tm_min; + hw_time.u32cSecond = tm_in->tm_sec; + hw_time.u32cDayOfWeek = tm_in->tm_wday; + hw_time.u8cClockDisplay = RTC_CLOCK_24; + hw_time.u8cAmPm = 0; + + if (RTC_Write(RTC_CURRENT_TIME, &hw_time) != E_RTC_SUCCESS) + return -(RT_ERROR); + + break; + +#if defined(RT_USING_ALARM) + case RT_DEVICE_CTRL_RTC_GET_ALARM: + + wkalarm = (struct rt_rtc_wkalarm *) args; + if (RTC_Read(RTC_ALARM_TIME, &hw_alarm) != E_RTC_SUCCESS) + return -(RT_ERROR); + + wkalarm->tm_hour = hw_alarm.u32cHour; + wkalarm->tm_min = hw_alarm.u32cMinute; + wkalarm->tm_sec = hw_alarm.u32cSecond; + break; + + case RT_DEVICE_CTRL_RTC_SET_ALARM: + + wkalarm = (struct rt_rtc_wkalarm *) args; + + /* Readback current ALARM time from RTC register for avoiding wrong parameter when next RTC_Write. */ + if (RTC_Read(RTC_CURRENT_TIME, &hw_alarm) != E_RTC_SUCCESS) + return -(RT_ERROR); + + hw_alarm.u32AlarmMaskHour = 0; + hw_alarm.u32AlarmMaskMinute = 0; + hw_alarm.u32AlarmMaskSecond = 0; + + hw_alarm.u32cHour = wkalarm->tm_hour; + hw_alarm.u32cMinute = wkalarm->tm_min; + hw_alarm.u32cSecond = wkalarm->tm_sec; + + if (RTC_Write(RTC_ALARM_TIME, &hw_alarm) != E_RTC_SUCCESS) + return -(RT_ERROR); + + break; + + default: + return -(RT_EINVAL); +#endif + } + + return RT_EOK; +} + + +#if defined (NU_RTC_SUPPORT_MSH_CMD) + +/* Support "rtc_det_date" command line in msh mode */ +static rt_err_t msh_rtc_set_date(int argc, char **argv) +{ + rt_uint32_t index, len, arg[3]; + + rt_memset(arg, 0, sizeof(arg)); + len = (argc >= 4) ? 4 : argc; + + /* The date information stored in argv is represented by the following order : + argv[0,1,2,3] = [cmd, year, month, day] */ + for (index = 0; index < (len - 1); index ++) + { + arg[index] = atol(argv[index + 1]); + } + + return set_date(arg[0], arg[1], arg[2]); +} +MSH_CMD_EXPORT_ALIAS(msh_rtc_set_date, rtc_set_date, e.g: rtc_set_date 2020 1 20); +#endif + + +#if defined (NU_RTC_SUPPORT_MSH_CMD) + +/* Support "rtc_det_time" command line in msh mode */ +static rt_err_t msh_rtc_set_time(int argc, char **argv) +{ + rt_uint32_t index, len, arg[3]; + + rt_memset(arg, 0, sizeof(arg)); + len = (argc >= 4) ? 4 : argc; + + /* The time information stored in argv is represented by the following order : + argv[0,1,2,3] = [cmd, hour, minute, second] */ + for (index = 0; index < (len - 1); index ++) + { + arg[index] = atol(argv[index + 1]); + } + + return set_time(arg[0], arg[1], arg[2]); +} +MSH_CMD_EXPORT_ALIAS(msh_rtc_set_time, rtc_set_time, e.g: rtc_set_time 18 30 00); +#endif + +#if defined(RT_USING_ALARM) +/* rtc interrupt entry */ +static void nu_rtc_isr(int vector, void *param) +{ + if (RTC_GET_TICK_INT_FLAG()) + { + RTC_CLEAR_TICK_INT_FLAG(); + } + + if (RTC_GET_ALARM_INT_FLAG()) + { + RTC_CLEAR_ALARM_INT_FLAG(); + + /* Send an alarm event to notify rt-thread alarm service. */ + rt_alarm_update(&device_rtc, (rt_uint32_t)NULL); + } + +} +#endif + +#endif /* BSP_USING_RTC */ + diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_scuart.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_scuart.c new file mode 100644 index 0000000000..ddf9f5f045 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_scuart.c @@ -0,0 +1,333 @@ +/**************************************************************************//** + * + * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-12-1 Wayne First version + * + ******************************************************************************/ + +#include + +#if defined(BSP_USING_SCUART) + +#include "NuMicro.h" +#include +#include +#include + +/* Private definition + * ---------------------------------------------------------------*/ +#define LOG_TAG "drv.scuart" +#define DBG_ENABLE +#define DBG_SECTION_NAME "drv.scuart" +#define DBG_LEVEL DBG_ERROR +#define DBG_COLOR +#include + +enum +{ + SCUART_START = -1, +#if defined(BSP_USING_SCUART0) + SCUART0_IDX, +#endif +#if defined(BSP_USING_SCUART1) + SCUART1_IDX, +#endif + SCUART_CNT +}; + +/* Private typedef + * --------------------------------------------------------------*/ +struct nu_scuart +{ + rt_serial_t dev; + char *name; + uint32_t idx; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; +}; +typedef struct nu_scuart *nu_scuart_t; + +/* Private functions + * ------------------------------------------------------------*/ +static rt_err_t nu_scuart_configure(struct rt_serial_device *serial, + struct serial_configure *cfg); +static rt_err_t nu_scuart_control(struct rt_serial_device *serial, int cmd, + void *arg); +static int nu_scuart_send(struct rt_serial_device *serial, char c); +static int nu_scuart_receive(struct rt_serial_device *serial); +static void nu_scuart_isr(int vector, void *param); + +static const struct rt_uart_ops nu_scuart_ops = +{ + .configure = nu_scuart_configure, + .control = nu_scuart_control, + .putc = nu_scuart_send, + .getc = nu_scuart_receive, + .dma_transmit = RT_NULL /* not support DMA mode */ +}; + +static const struct serial_configure nu_scuart_default_config = + RT_SERIAL_CONFIG_DEFAULT; + +static struct nu_scuart nu_scuart_arr[] = +{ +#if defined(BSP_USING_SCUART0) + { + .name = "scuart0", + .idx = 0, + .irqn = IRQ_SC0, + .rstidx = SMC0RST, + .clkidx = SMC0CKEN, + }, +#endif + +#if defined(BSP_USING_SCUART1) + { + .name = "scuart1", + .idx = 1, + .irqn = IRQ_SC1, + .rstidx = SMC1RST, + .clkidx = SMC1CKEN, + }, +#endif +}; /* scuart nu_scuart */ + +/** + * All SCUART interrupt service routine + */ +static void nu_scuart_isr(int vector, void *param) +{ + nu_scuart_t psNuSCUart = (nu_scuart_t)param; + + /* Handle RX event */ + if (SCUART_GET_INT_FLAG(psNuSCUart->idx, SC_INTSTS_RBTOIF_Msk) || + SCUART_GET_INT_FLAG(psNuSCUart->idx, SC_INTSTS_RDAIF_Msk)) + { + rt_hw_serial_isr(&psNuSCUart->dev, RT_SERIAL_EVENT_RX_IND); + + // RDA is the only interrupt enabled in this driver, this status bit + // automatically cleared after Rx FIFO empty. So no need to clear interrupt + // status here. + SCUART_CLR_INT_FLAG(psNuSCUart->idx, SC_INTSTS_RBTOIF_Msk); + } +} + +/** + * Configure scuart port + */ +static rt_err_t nu_scuart_configure(struct rt_serial_device *serial, + struct serial_configure *cfg) +{ + rt_err_t ret = RT_EOK; + uint32_t scuart_word_len = 0; + uint32_t scuart_stop_bit = 0; + uint32_t scuart_parity = 0; + nu_scuart_t psNuSCUart = (nu_scuart_t)serial; + RT_ASSERT(psNuSCUart != RT_NULL); + + /* Check baud rate */ RT_ASSERT(cfg->baud_rate != 0); + + RT_ASSERT(cfg->baud_rate != 0); + + /* Check word len */ + switch (cfg->data_bits) + { + case DATA_BITS_5: + scuart_word_len = SCUART_CHAR_LEN_5; + break; + + case DATA_BITS_6: + scuart_word_len = SCUART_CHAR_LEN_6; + break; + + case DATA_BITS_7: + scuart_word_len = SCUART_CHAR_LEN_7; + break; + + case DATA_BITS_8: + scuart_word_len = SCUART_CHAR_LEN_8; + break; + + default: + LOG_E("Unsupported data length"); + ret = RT_EINVAL; + goto exit_nu_scuart_configure; + } + + /* Check stop bit */ + switch (cfg->stop_bits) + { + case STOP_BITS_1: + scuart_stop_bit = SCUART_STOP_BIT_1; + break; + + case STOP_BITS_2: + scuart_stop_bit = SCUART_STOP_BIT_2; + break; + + default: + LOG_E("Unsupported stop bit"); + ret = RT_EINVAL; + goto exit_nu_scuart_configure; + } + + /* Check parity */ + switch (cfg->parity) + { + case PARITY_NONE: + scuart_parity = SCUART_PARITY_NONE; + break; + + case PARITY_ODD: + scuart_parity = SCUART_PARITY_ODD; + break; + + case PARITY_EVEN: + scuart_parity = SCUART_PARITY_EVEN; + break; + + default: + LOG_E("Unsupported parity"); + ret = RT_EINVAL; + goto exit_nu_scuart_configure; + } + + nu_sys_ip_reset(psNuSCUart->rstidx); + + /* Open SCUART and set SCUART baud rate */ + SCUART_Open(psNuSCUart->idx, cfg->baud_rate); + + /* Set line configuration. */ + SCUART_SetLineConfig(psNuSCUart->idx, 0, scuart_word_len, scuart_parity, + scuart_stop_bit); + + /* Enable interrupt. */ + rt_hw_interrupt_umask(psNuSCUart->irqn); + +exit_nu_scuart_configure: + + if (ret != RT_EOK) + SCUART_Close(psNuSCUart->idx); + + return -(ret); +} + +/** + * SCUART interrupt control + */ +static rt_err_t nu_scuart_control(struct rt_serial_device *serial, int cmd, + void *arg) +{ + rt_err_t result = RT_EOK; + rt_uint32_t flag; + rt_ubase_t ctrl_arg = (rt_ubase_t)arg; + nu_scuart_t psNuSCUart = (nu_scuart_t)serial; + RT_ASSERT(psNuSCUart != RT_NULL); + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) /* Disable INT-RX */ + { + flag = SC_INTEN_RDAIEN_Msk | SC_INTEN_RXTOIEN_Msk; + SCUART_DISABLE_INT(psNuSCUart->idx, flag); + } + break; + + case RT_DEVICE_CTRL_SET_INT: + + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) /* Enable INT-RX */ + { + flag = SC_INTEN_RDAIEN_Msk | SC_INTEN_RXTOIEN_Msk; + SCUART_ENABLE_INT(psNuSCUart->idx, flag); + } + break; + + case RT_DEVICE_CTRL_CLOSE: + + /* Disable interrupt. */ + rt_hw_interrupt_mask(psNuSCUart->irqn); + + /* Close SCUART port */ + SCUART_Close(psNuSCUart->idx); + + break; + + default: + + result = -RT_EINVAL; + break; + } + return result; +} + +/** + * SCUART put char + */ +static int nu_scuart_send(struct rt_serial_device *serial, char c) +{ + nu_scuart_t psNuSCUart = (nu_scuart_t)serial; + RT_ASSERT(psNuSCUart != RT_NULL); + + /* Waiting if TX-FIFO is full. */ + while (SCUART_IS_TX_FULL(psNuSCUart->idx)) ; + + /* Put char into TX-FIFO */ + SCUART_WRITE(psNuSCUart->idx, c); + + return 1; +} + +/** + * SCUART get char + */ +static int nu_scuart_receive(struct rt_serial_device *serial) +{ + nu_scuart_t psNuSCUart = (nu_scuart_t)serial; + RT_ASSERT(psNuSCUart != RT_NULL); + + /* Return failure if RX-FIFO is empty. */ + if (SCUART_GET_RX_EMPTY(psNuSCUart->idx)) + { + return -1; + } + + /* Get char from RX-FIFO */ + return SCUART_READ(psNuSCUart->idx); +} + +/** + * Hardware SCUART Initialization + */ +static int rt_hw_scuart_init(void) +{ + int i; + rt_uint32_t flag; + rt_err_t ret = RT_EOK; + + for (i = (SCUART_START + 1); i < SCUART_CNT; i++) + { + flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX; + + nu_scuart_arr[i].dev.ops = &nu_scuart_ops; + nu_scuart_arr[i].dev.config = nu_scuart_default_config; + + rt_hw_interrupt_install(nu_scuart_arr[i].irqn, nu_scuart_isr, &nu_scuart_arr[i], nu_scuart_arr[i].name); + + nu_sys_ipclk_enable(nu_scuart_arr[i].clkidx); + + ret = rt_hw_serial_register(&nu_scuart_arr[i].dev, nu_scuart_arr[i].name, flag, NULL); + RT_ASSERT(ret == RT_EOK); + } + + return (int)ret; +} +INIT_DEVICE_EXPORT(rt_hw_scuart_init); +#endif //#if defined(BSP_USING_SCUART) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c new file mode 100644 index 0000000000..1f44e5d6c1 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c @@ -0,0 +1,642 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_SDH) + +#include +#include +#include "NuMicro.h" +#include + +#if defined(RT_USING_DFS) + #include + #include +#endif + +/* Private define ---------------------------------------------------------------*/ + +#if defined(NU_SDH_MOUNT_ON_ROOT) + + #if !defined(NU_SDH_MOUNTPOINT_SDH0) + #define NU_SDH_MOUNTPOINT_SDH0 "/" + #endif + + #if !defined(NU_SDH_MOUNTPOINT_SDH1) + #define NU_SDH_MOUNTPOINT_SDH1 NU_SDH_MOUNTPOINT_SDH0"/sd1" + #endif + +#else + + #if !defined(NU_SDH_MOUNTPOINT_ROOT) + #define NU_SDH_MOUNTPOINT_ROOT "/mnt" + #endif + +#endif + +#if !defined(NU_SDH_MOUNTPOINT_SDH0) + #define NU_SDH_MOUNTPOINT_SDH0 NU_SDH_MOUNTPOINT_ROOT"/sd0" +#endif + +#if !defined(NU_SDH_MOUNTPOINT_SDH1) + #define NU_SDH_MOUNTPOINT_SDH1 NU_SDH_MOUNTPOINT_ROOT"/sd1" +#endif + +enum +{ + SDH_START = -1, +#if defined(BSP_USING_SDH0) + SDH0_IDX, +#endif +#if defined(BSP_USING_SDH1) + SDH1_IDX, +#endif + SDH_CNT +}; + +#define SDH_BLOCK_SIZE 512ul + +#if defined(NU_SDH_HOTPLUG) + #define NU_SDH_TID_STACK_SIZE 1024 +#endif + +#if defined(NU_SDH_HOTPLUG) +enum +{ + NU_SDH_CARD_DETECTED_SD0 = (1 << 0), + NU_SDH_CARD_DETECTED_SD1 = (1 << 1), + NU_SDH_CARD_EVENT_ALL = (NU_SDH_CARD_DETECTED_SD0 | NU_SDH_CARD_DETECTED_SD1) +}; +#endif + +/* Private typedef --------------------------------------------------------------*/ +struct nu_sdh +{ + struct rt_device dev; + char *name; +#if defined(NU_SDH_HOTPLUG) + char *mounted_point; +#endif + SDH_T *base; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + + uint32_t is_card_inserted; + SDH_INFO_T *info; + struct rt_semaphore lock; + uint8_t *pbuf; +}; +typedef struct nu_sdh *nu_sdh_t; + +#if defined(NU_SDH_HOTPLUG) + static struct rt_thread sdh_tid; + static rt_uint8_t sdh_stack[NU_SDH_TID_STACK_SIZE]; +#endif + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_sdh_init(rt_device_t dev); +static rt_err_t nu_sdh_open(rt_device_t dev, rt_uint16_t oflag); +static rt_err_t nu_sdh_close(rt_device_t dev); +static rt_size_t nu_sdh_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t blk_nb); +static rt_err_t nu_sdh_control(rt_device_t dev, int cmd, void *args); +static int rt_hw_sdh_init(void); + +#if defined(NU_SDH_HOTPLUG) + static rt_bool_t nu_sdh_hotplug_is_mounted(const char *mounting_path); + static void sdh_hotplugger(void *param); + static rt_err_t nu_sdh_hotplug_mount(nu_sdh_t sdh); + static rt_err_t nu_sdh_hotplug_unmount(nu_sdh_t sdh); +#endif + +/* Public functions -------------------------------------------------------------*/ + + +/* Private variables ------------------------------------------------------------*/ +static struct nu_sdh nu_sdh_arr [] = +{ +#if defined(BSP_USING_SDH0) + { + .name = "sdh0", +#if defined(NU_SDH_HOTPLUG) + .mounted_point = NU_SDH_MOUNTPOINT_SDH0, +#endif + .irqn = IRQ_FMI, + .base = SDH0, + .rstidx = FMIRST, + .clkidx = EMMCCKEN, + .info = &SD0, + }, +#endif +#if defined(BSP_USING_SDH1) + { + .name = "sdh1", +#if defined(NU_SDH_HOTPLUG) + .mounted_point = NU_SDH_MOUNTPOINT_SDH1, +#endif + .irqn = IRQ_SDH, + .base = SDH1, + .rstidx = SDIORST, + .clkidx = SDHCKEN, + .info = &SD1, + }, +#endif +}; /* struct nu_sdh nu_sdh_arr [] */ +static struct rt_event sdh_event; + +static void SDH_IRQHandler(int vector, void *param) +{ + nu_sdh_t sdh = (nu_sdh_t)param; + SDH_T *sdh_base = sdh->base; + unsigned int volatile isr; + SDH_INFO_T *pSD = sdh->info; + + // FMI data abort interrupt + if (sdh_base->GINTSTS & SDH_GINTSTS_DTAIF_Msk) + { + /* ResetAllEngine() */ + sdh_base->GCTL |= SDH_GCTL_GCTLRST_Msk; + } + + //----- SD interrupt status + isr = sdh_base->INTSTS; + if (isr & SDH_INTSTS_BLKDIF_Msk) + { + // block down + pSD->DataReadyFlag = TRUE; + SDH_CLR_INT_FLAG(sdh_base, SDH_INTSTS_BLKDIF_Msk); + } + + if (isr & SDH_INTSTS_CDIF_Msk) // card detect + { +#if defined(NU_SDH_HOTPLUG) + if (sdh->base == SDH0) + rt_event_send(&sdh_event, NU_SDH_CARD_DETECTED_SD0); + else if (sdh->base == SDH1) + rt_event_send(&sdh_event, NU_SDH_CARD_DETECTED_SD1); +#endif + /* Clear CDIF interrupt flag */ + SDH_CLR_INT_FLAG(sdh_base, SDH_INTSTS_CDIF_Msk); + } + + // CRC error interrupt + if (isr & SDH_INTSTS_CRCIF_Msk) + { + if (!(isr & SDH_INTSTS_CRC16_Msk)) + { + /* CRC_16 error */ + // TODO: handle CRC 16 error + } + else if (!(isr & SDH_INTSTS_CRC7_Msk)) + { + if (!pSD->R3Flag) + { + /* CRC_7 error */ + // TODO: handle CRC 7 error + } + } + /* Clear CRCIF interrupt flag */ + SDH_CLR_INT_FLAG(sdh_base, SDH_INTSTS_CRCIF_Msk); + } + + /* Data-in timeout */ + if (isr & SDH_INTSTS_DITOIF_Msk) + { + sdh_base->INTSTS |= SDH_INTSTS_DITOIF_Msk; + } + + /* Response-in timeout interrupt */ + if (isr & SDH_INTSTS_RTOIF_Msk) + { + sdh_base->INTSTS |= SDH_INTSTS_RTOIF_Msk; + } +} + +/* RT-Thread Device Driver Interface */ +static rt_err_t nu_sdh_init(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_err_t nu_sdh_open(rt_device_t dev, rt_uint16_t oflag) +{ + nu_sdh_t sdh = (nu_sdh_t)dev; + + RT_ASSERT(dev != RT_NULL); + + return (SDH_Probe(sdh->base) == 0) ? RT_EOK : -(RT_ERROR); +} + +static rt_err_t nu_sdh_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_size_t nu_sdh_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t blk_nb) +{ + rt_err_t result = RT_ERROR; + rt_uint32_t ret = 0; + nu_sdh_t sdh = (nu_sdh_t)dev; + + RT_ASSERT(dev != RT_NULL); + RT_ASSERT(buffer != RT_NULL); + + result = rt_sem_take(&sdh->lock, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + /* Check alignment. */ + if (((uint32_t)buffer & 0x03) != 0) + { + /* Non-aligned. */ + uint32_t i; + uint8_t *copy_buffer = (uint8_t *)buffer; + + sdh->pbuf = rt_malloc(SDH_BLOCK_SIZE); + if (sdh->pbuf == RT_NULL) + goto exit_nu_sdh_read; + + for (i = 0; i < blk_nb; i++) + { + /* Read to temp buffer from specified sector. */ + ret = SDH_Read(sdh->base, (uint8_t *)((uint32_t)&sdh->pbuf[0] | NONCACHEABLE), pos, 1); + if (ret != Successful) + goto exit_nu_sdh_read; + + /* Move to user's buffer */ + memcpy((void *)copy_buffer, (void *)&sdh->pbuf[0], SDH_BLOCK_SIZE); + + pos ++; + copy_buffer += SDH_BLOCK_SIZE; + } + } + else + { +#if defined(BSP_USING_MMU) + mmu_clean_invalidated_dcache((rt_uint32_t)buffer, SDH_BLOCK_SIZE * blk_nb); +#endif + + /* Read to user's buffer from specified sector. */ + ret = SDH_Read(sdh->base, (uint8_t *)((uint32_t)buffer | NONCACHEABLE), pos, blk_nb); + } + +exit_nu_sdh_read: + + if (sdh->pbuf) + { + rt_free(sdh->pbuf); + sdh->pbuf = RT_NULL; + } + + result = rt_sem_release(&sdh->lock); + RT_ASSERT(result == RT_EOK); + + if (ret == Successful) + return blk_nb; + + rt_kprintf("Read failed: %d, buffer 0x%08x\n", ret, buffer); + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_size_t nu_sdh_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t blk_nb) +{ + rt_err_t result = RT_ERROR; + rt_uint32_t ret = 0; + nu_sdh_t sdh = (nu_sdh_t)dev; + + RT_ASSERT(dev != RT_NULL); + RT_ASSERT(buffer != RT_NULL); + + result = rt_sem_take(&sdh->lock, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + /* Check alignment. */ + if (((uint32_t)buffer & 0x03) != 0) + { + /* Non-aligned. */ + uint32_t i; + uint8_t *copy_buffer = (uint8_t *)buffer; + + sdh->pbuf = rt_malloc(SDH_BLOCK_SIZE); + if (sdh->pbuf == RT_NULL) + goto exit_nu_sdh_write; + + for (i = 0; i < blk_nb; i++) + { +#if defined(BSP_USING_MMU) + mmu_clean_invalidated_dcache((rt_uint32_t)copy_buffer, SDH_BLOCK_SIZE); +#endif + + memcpy((void *)&sdh->pbuf[0], copy_buffer, SDH_BLOCK_SIZE); + + ret = SDH_Write(sdh->base, (uint8_t *)((uint32_t)&sdh->pbuf[0] | NONCACHEABLE), pos, 1); + if (ret != Successful) + goto exit_nu_sdh_write; + + pos++; + copy_buffer += SDH_BLOCK_SIZE; + } + } + else + { +#if defined(BSP_USING_MMU) + mmu_clean_invalidated_dcache((rt_uint32_t)buffer, SDH_BLOCK_SIZE * blk_nb); +#endif + + /* Write to device directly. */ + ret = SDH_Write(sdh->base, (uint8_t *)((uint32_t)buffer | NONCACHEABLE), pos, blk_nb); + } + +exit_nu_sdh_write: + + if (sdh->pbuf) + { + rt_free(sdh->pbuf); + sdh->pbuf = RT_NULL; + } + + result = rt_sem_release(&sdh->lock); + RT_ASSERT(result == RT_EOK); + + if (ret == Successful) return blk_nb; + + rt_kprintf("write failed: %d, buffer 0x%08x\n", ret, buffer); + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_err_t nu_sdh_control(rt_device_t dev, int cmd, void *args) +{ + nu_sdh_t sdh = (nu_sdh_t)dev; + + RT_ASSERT(dev != RT_NULL); + + if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) + { + SDH_INFO_T *sdh_info = sdh->info; + + struct rt_device_blk_geometry *geometry; + + geometry = (struct rt_device_blk_geometry *)args; + if (geometry == RT_NULL) return -RT_ERROR; + + geometry->bytes_per_sector = sdh_info->sectorSize; + geometry->block_size = sdh_info->sectorSize; + geometry->sector_count = sdh_info->totalSectorN; + } + + return RT_EOK; +} + + +static int rt_hw_sdh_init(void) +{ + int i; + rt_err_t ret = RT_EOK; + rt_uint32_t flags = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE; + + ret = rt_event_init(&sdh_event, "sdh_event", RT_IPC_FLAG_FIFO); + RT_ASSERT(ret == RT_EOK); + + for (i = (SDH_START + 1); i < SDH_CNT; i++) + { + /* Register sdcard device */ + nu_sdh_arr[i].dev.type = RT_Device_Class_Block; + nu_sdh_arr[i].dev.init = nu_sdh_init; + nu_sdh_arr[i].dev.open = nu_sdh_open; + nu_sdh_arr[i].dev.close = nu_sdh_close; + nu_sdh_arr[i].dev.read = nu_sdh_read; + nu_sdh_arr[i].dev.write = nu_sdh_write; + nu_sdh_arr[i].dev.control = nu_sdh_control; + + /* Private */ + nu_sdh_arr[i].dev.user_data = (void *)&nu_sdh_arr[i]; + + ret = rt_sem_init(&nu_sdh_arr[i].lock, "sdhlock", 1, RT_IPC_FLAG_FIFO); + RT_ASSERT(ret == RT_EOK); + + rt_hw_interrupt_install(nu_sdh_arr[i].irqn, SDH_IRQHandler, (void *)&nu_sdh_arr[i], nu_sdh_arr[i].name); + rt_hw_interrupt_umask(nu_sdh_arr[i].irqn); + + nu_sys_ipclk_enable(nu_sdh_arr[i].clkidx); + + nu_sys_ip_reset(nu_sdh_arr[i].rstidx); + + nu_sdh_arr[i].pbuf = RT_NULL; + + ret = rt_device_register(&nu_sdh_arr[i].dev, nu_sdh_arr[i].name, flags); + RT_ASSERT(ret == RT_EOK); + } + + return (int)ret; +} +INIT_BOARD_EXPORT(rt_hw_sdh_init); + +#if defined(NU_SDH_HOTPLUG) +static rt_bool_t nu_sdh_hotplug_is_mounted(const char *mounting_path) +{ + rt_bool_t ret = RT_FALSE; + +#if defined(RT_USING_DFS) + + struct dfs_filesystem *psFS = dfs_filesystem_lookup(mounting_path); + if (psFS == RT_NULL) + { + goto exit_nu_sdh_hotplug_is_mounted; + } + else if (!rt_memcmp(psFS->path, mounting_path, rt_strlen(mounting_path))) + { + ret = RT_TRUE; + } + else + { + ret = RT_FALSE; + } + +exit_nu_sdh_hotplug_is_mounted: + +#endif + + return ret; +} +static rt_err_t nu_sdh_hotplug_mount(nu_sdh_t sdh) +{ + rt_err_t ret = RT_ERROR; + +#if defined(RT_USING_DFS) + DIR *t; + + if (nu_sdh_hotplug_is_mounted(sdh->mounted_point) == RT_TRUE) + { + ret = RT_EOK; + goto exit_nu_sdh_hotplug_mount; + } + + /* Check the SD folder path is valid. */ + if ((t = opendir(sdh->mounted_point)) != RT_NULL) + { + closedir(t); + } +#if !defined(NU_SDH_MOUNT_ON_ROOT) + else + { + + /* Check the ROOT path is valid. */ + if ((t = opendir(NU_SDH_MOUNTPOINT_ROOT)) != RT_NULL) + { + closedir(t); + } + else if ((ret = mkdir(NU_SDH_MOUNTPOINT_ROOT, 0)) != RT_EOK) + { + rt_kprintf("Failed to mkdir %s\n", NU_SDH_MOUNTPOINT_ROOT); + goto exit_nu_sdh_hotplug_mount; + } + + if ((ret = mkdir(sdh->mounted_point, 0)) != RT_EOK) + { + rt_kprintf("Failed to mkdir %s\n", sdh->mounted_point); + goto exit_nu_sdh_hotplug_mount; + } + + } //else +#endif + + if ((ret = dfs_mount(sdh->name, sdh->mounted_point, "elm", 0, 0)) == 0) + { + rt_kprintf("Mounted %s on %s\n", sdh->name, sdh->mounted_point); + } + else + { + rt_kprintf("Failed to mount %s on %s\n", sdh->name, sdh->mounted_point); + ret = RT_ERROR; + } + +exit_nu_sdh_hotplug_mount: + +#endif + return -(ret); +} + +static rt_err_t nu_sdh_hotplug_unmount(nu_sdh_t sdh) +{ + rt_err_t ret = RT_ERROR; + +#if defined(RT_USING_DFS) + if (nu_sdh_hotplug_is_mounted(sdh->mounted_point) == RT_FALSE) + { + ret = RT_EOK; + goto exit_nu_sdh_hotplug_unmount; + } + + ret = dfs_unmount(sdh->mounted_point); + if (ret != RT_EOK) + { + rt_kprintf("Failed to unmount %s.\n", sdh->mounted_point); + } + else + { + rt_kprintf("Succeed to unmount %s.\n", sdh->mounted_point); + ret = RT_EOK; + } + +exit_nu_sdh_hotplug_unmount: + +#endif + + return -(ret); +} + +static void nu_card_detector(nu_sdh_t sdh) +{ + SDH_T *sdh_base = sdh->base; + unsigned int volatile isr = sdh_base->INTSTS; + if (isr & SDH_INTSTS_CDSTS_Msk) + { + /* Card removed */ + sdh->info->IsCardInsert = FALSE; // SDISR_CD_Card = 1 means card remove for GPIO mode + rt_memset((void *)sdh->info, 0, sizeof(SDH_INFO_T)); + nu_sdh_hotplug_unmount(sdh); + } + else + { + SDH_Open(sdh_base, CardDetect_From_GPIO); + if (!SDH_Probe(sdh_base)) + { + /* Card inserted */ + nu_sdh_hotplug_mount(sdh); + } + } +} + +static void sdh_hotplugger(void *param) +{ + rt_uint32_t e; + int i; + + for (i = (SDH_START + 1); i < SDH_CNT; i++) + { + /* Try to detect SD card on selected port. */ + SDH_Open(nu_sdh_arr[i].base, CardDetect_From_GPIO); + if (!SDH_Probe(nu_sdh_arr[i].base) && + SDH_IS_CARD_PRESENT(nu_sdh_arr[i].base)) + { + nu_sdh_hotplug_mount(&nu_sdh_arr[i]); + } + } + + while (1) + { + if (rt_event_recv(&sdh_event, (NU_SDH_CARD_EVENT_ALL), + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + RT_WAITING_FOREVER, &e) == RT_EOK) + { + /* Debounce */ + rt_thread_mdelay(200); + switch (e) + { +#if defined(BSP_USING_SDH0) + case NU_SDH_CARD_DETECTED_SD0: + nu_card_detector(&nu_sdh_arr[SDH0_IDX]); + break; +#endif +#if defined(BSP_USING_SDH1) + case NU_SDH_CARD_DETECTED_SD1: + nu_card_detector(&nu_sdh_arr[SDH1_IDX]); + break; +#endif + default: + break; + + } //switch(e) + + } //if + + } /* while(1) */ +} + +int mnt_init_sdcard_hotplug(void) +{ + rt_err_t ret = RT_EOK; + + ret = rt_thread_init(&sdh_tid, "hotplug", sdh_hotplugger, NULL, sdh_stack, sizeof(sdh_stack), RT_THREAD_PRIORITY_MAX - 2, 10); + RT_ASSERT(ret == RT_EOK); + + ret = rt_thread_startup(&sdh_tid); + RT_ASSERT(ret == RT_EOK); + + return 0; +} +INIT_ENV_EXPORT(mnt_init_sdcard_hotplug); +#endif + +#endif //#if defined(BSP_USING_SDH) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_softi2c.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_softi2c.c new file mode 100644 index 0000000000..8defbe38eb --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_softi2c.c @@ -0,0 +1,238 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#include + +#if (defined(BSP_USING_SOFT_I2C) && defined(RT_USING_I2C_BITOPS) && defined(RT_USING_I2C) && defined(RT_USING_PIN)) + +#include +#include +#include +#include "NuMicro.h" +#include "drv_sys.h" + +/* Private define ---------------------------------------------------------------*/ +#define LOG_TAG "drv.softi2c" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_INFO +#include + +#ifdef BSP_USING_SOFT_I2C0 +#define NU_SOFT_I2C0_BUS_CONFIG \ + { \ + .scl = BSP_SOFT_I2C0_SCL_PIN, \ + .sda = BSP_SOFT_I2C0_SDA_PIN, \ + .bus_name = "softi2c0", \ + } +#endif + +#ifdef BSP_USING_SOFT_I2C1 +#define NU_SOFT_I2C1_BUS_CONFIG \ + { \ + .scl = BSP_SOFT_I2C1_SCL_PIN, \ + .sda = BSP_SOFT_I2C1_SDA_PIN, \ + .bus_name = "softi2c1", \ + } +#endif + +#if (!defined(BSP_USING_SOFT_I2C0) && !defined(BSP_USING_SOFT_I2C1)) + #error "Please define at least one BSP_USING_SOFT_I2Cx" + /* this driver can be disabled at menuconfig ? RT-Thread Components ? Device Drivers */ +#endif + +/* Private typedef --------------------------------------------------------------*/ +/* soft i2c config class */ +struct nu_soft_i2c_config +{ + rt_uint8_t scl; + rt_uint8_t sda; + const char *bus_name; +}; +/* soft i2c driver class */ +struct nu_soft_i2c +{ + struct rt_i2c_bit_ops ops; + struct rt_i2c_bus_device soft_i2c_bus; +}; + +/* Private functions ------------------------------------------------------------*/ +static void nu_soft_i2c_udelay(rt_uint32_t us); +static void nu_soft_i2c_set_sda(void *data, rt_int32_t state); +static void nu_soft_i2c_set_scl(void *data, rt_int32_t state); +static rt_int32_t nu_soft_i2c_get_sda(void *data); +static rt_int32_t nu_soft_i2c_get_scl(void *data); + +/* Private variables ------------------------------------------------------------*/ +static const struct nu_soft_i2c_config nu_soft_i2c_cfg[] = +{ +#ifdef BSP_USING_SOFT_I2C0 + NU_SOFT_I2C0_BUS_CONFIG, +#endif +#ifdef BSP_USING_SOFT_I2C1 + NU_SOFT_I2C1_BUS_CONFIG, +#endif +}; + +static struct nu_soft_i2c nu_soft_i2c_obj[sizeof(nu_soft_i2c_cfg) / sizeof(nu_soft_i2c_cfg[0])]; + +static const struct rt_i2c_bit_ops nu_soft_i2c_bit_ops = +{ + .data = RT_NULL, + .set_sda = nu_soft_i2c_set_sda, + .set_scl = nu_soft_i2c_set_scl, + .get_sda = nu_soft_i2c_get_sda, + .get_scl = nu_soft_i2c_get_scl, + .udelay = nu_soft_i2c_udelay, + .delay_us = 1, + .timeout = 100 +}; + +/* Functions define ------------------------------------------------------------*/ + +/** + * The time delay function. + * + * @param microseconds. + */ +static void nu_soft_i2c_udelay(rt_uint32_t us) +{ + rt_hw_us_delay(us); +} + +/** + * This function initializes the soft i2c pin. + * + * @param soft i2c config class. + */ +static void nu_soft_i2c_gpio_init(const struct nu_soft_i2c_config *cfg) +{ + rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT); + rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT); + + rt_pin_write(cfg->scl, PIN_HIGH); + rt_pin_write(cfg->sda, PIN_HIGH); +} + +/** + * if i2c is locked, this function will unlock it + * + * @param soft i2c config class + * + * @return RT_EOK indicates successful unlock. + */ +static rt_err_t nu_soft_i2c_bus_unlock(const struct nu_soft_i2c_config *cfg) +{ + rt_int32_t i = 0; + + rt_pin_mode(cfg->sda, PIN_MODE_INPUT); + rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT); + + if (PIN_LOW == rt_pin_read(cfg->sda)) + { + while (i++ < 9) + { + rt_pin_write(cfg->scl, PIN_HIGH); + nu_soft_i2c_udelay(100); + rt_pin_write(cfg->scl, PIN_LOW); + nu_soft_i2c_udelay(100); + } + } + if (PIN_LOW == rt_pin_read(cfg->sda)) + { + return -RT_ERROR; + } + + return RT_EOK; +} + +/** + * This function sets the sda pin. + * + * @param soft i2c config class. + * @param The sda pin state. + */ +static void nu_soft_i2c_set_sda(void *data, rt_int32_t state) +{ + struct nu_soft_i2c_config *cfg = (struct nu_soft_i2c_config *)data; + + rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT); + rt_pin_write(cfg->sda, state ? PIN_HIGH : PIN_LOW); +} + +/** + * This function sets the scl pin. + * + * @param soft i2c config class. + * @param The scl pin state. + */ +static void nu_soft_i2c_set_scl(void *data, rt_int32_t state) +{ + struct nu_soft_i2c_config *cfg = (struct nu_soft_i2c_config *)data; + + rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT); + rt_pin_write(cfg->scl, state ? PIN_HIGH : PIN_LOW); +} + +/** + * This function gets the sda pin state. + * + * @param The sda pin state. + */ +static rt_int32_t nu_soft_i2c_get_sda(void *data) +{ + struct nu_soft_i2c_config *cfg = (struct nu_soft_i2c_config *)data; + + rt_pin_mode(cfg->sda, PIN_MODE_INPUT); + return rt_pin_read(cfg->sda); +} + +/** + * This function gets the scl pin state. + * + * @param The scl pin state. + */ +static rt_int32_t nu_soft_i2c_get_scl(void *data) +{ + struct nu_soft_i2c_config *cfg = (struct nu_soft_i2c_config *)data; + + rt_pin_mode(cfg->scl, PIN_MODE_INPUT); + return rt_pin_read(cfg->scl); +} + +/* Soft I2C initialization function */ +int rt_soft_i2c_init(void) +{ + rt_size_t obj_num = sizeof(nu_soft_i2c_obj) / sizeof(struct nu_soft_i2c); + rt_err_t result; + + for (int i = 0; i < obj_num; i++) + { + nu_soft_i2c_obj[i].ops = nu_soft_i2c_bit_ops; + nu_soft_i2c_obj[i].ops.data = (void *)&nu_soft_i2c_cfg[i]; + nu_soft_i2c_obj[i].soft_i2c_bus.priv = &nu_soft_i2c_obj[i].ops; + nu_soft_i2c_gpio_init(&nu_soft_i2c_cfg[i]); + result = rt_i2c_bit_add_bus(&nu_soft_i2c_obj[i].soft_i2c_bus, nu_soft_i2c_cfg[i].bus_name); + RT_ASSERT(result == RT_EOK); + nu_soft_i2c_bus_unlock(&nu_soft_i2c_cfg[i]); + + LOG_I("software simulation %s init done, pin scl: %d, pin sda %d", + nu_soft_i2c_cfg[i].bus_name, + nu_soft_i2c_cfg[i].scl, + nu_soft_i2c_cfg[i].sda); + } + + return 0; +} +INIT_DEVICE_EXPORT(rt_soft_i2c_init); + +#endif //#if (defined(BSP_USING_SOFT_I2C) && defined(RT_USING_I2C_BITOPS) && defined(RT_USING_I2C) && defined(RT_USING_PIN)) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sys.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sys.c new file mode 100644 index 0000000000..43b0c2cfb8 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sys.c @@ -0,0 +1,330 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-11-11 Wayne First version +* +******************************************************************************/ + +#include +#include +#include "NuMicro.h" +#include "drv_sys.h" + +#define SYS_MIN_INT_SOURCE 1 +#define SYS_MAX_INT_SOURCE 62 +#define SYS_NUM_OF_AICREG 16 +#define INT_IRQ 0x00 +#define INT_FIQ 0x01 + +extern rt_uint32_t rt_interrupt_nest; + +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; + +struct rt_irq_desc irq_desc[SYS_MAX_INT_SOURCE + 1]; + +void rt_hw_interrupt_dummy_handler(int vector, void *param) +{ + rt_kprintf("Unhandled interrupt %d occurred!!!\n", vector); + RT_ASSERT(0); +} + +void rt_hw_interrupt_set_priority(int vector, int IntTypeLevel) +{ + sysSetInterruptPriorityLevel((IRQn_Type)vector, (UINT32)IntTypeLevel); +} + +void rt_interrupt_dispatch(rt_uint32_t fiq_irq) +{ + rt_isr_handler_t isr_func; + rt_uint32_t volatile _mIPER, _mISNR; + void *param; + + /* Get irq number */ + _mIPER = (inpw(REG_AIC_IPER) >> 2) & 0x3f; + _mISNR = inpw(REG_AIC_ISNR) & 0x3f; + if ((_mIPER != _mISNR) || _mISNR == 0) + return; + + /* Get interrupt service routine */ + isr_func = irq_desc[_mISNR].handler; + param = irq_desc[_mISNR].param; + +#ifdef RT_USING_INTERRUPT_INFO + irq_desc[_mISNR].counter ++; +#endif + + /* Turn to interrupt service routine */ + isr_func(_mISNR, param); + + /* Handled the ISR. */ + outpw(REG_AIC_EOSCR, 1); +} + +void rt_hw_interrupt_init(void) +{ + int i; + + *((volatile unsigned int *)REG_AIC_ISR) = 0xFFFFFFFF; // disable all interrupt channel + *((volatile unsigned int *)REG_AIC_ISRH) = 0xFFFFFFFF; // disable all interrupt channel + + /* init interrupt nest, and context in thread sp */ + rt_interrupt_nest = 0; + rt_interrupt_from_thread = 0; + rt_interrupt_to_thread = 0; + rt_thread_switch_interrupt_flag = 0; + + for (i = SYS_MIN_INT_SOURCE; i <= SYS_MAX_INT_SOURCE; i++) + { + rt_hw_interrupt_install(i, rt_hw_interrupt_dummy_handler, RT_NULL, (char *)"dummy"); + rt_hw_interrupt_mask(i); + } +} + +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if (vector > SYS_MAX_INT_SOURCE) + return RT_NULL; + + /* Set default priority IRQ_LEVEL_7 */ + rt_hw_interrupt_set_priority(vector, IRQ_LEVEL_7); + + old_handler = irq_desc[vector].handler; + if (handler != RT_NULL) + { + irq_desc[vector].handler = (rt_isr_handler_t)handler; + irq_desc[vector].param = param; +#ifdef RT_USING_INTERRUPT_INFO + rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name); + irq_desc[vector].counter = 0; +#endif + } + + return old_handler; +} + +/* Disable interrupt */ +void rt_hw_interrupt_mask(int vector) +{ + sysDisableInterrupt((IRQn_Type)vector); +} + +void rt_hw_interrupt_umask(int vector) +{ + sysEnableInterrupt((IRQn_Type)vector); +} + +/* TYPE + * #define LOW_LEVEL_SENSITIVE 0x00 + * #define HIGH_LEVEL_SENSITIVE 0x40 + * #define NEGATIVE_EDGE_TRIGGER 0x80 + * #define POSITIVE_EDGE_TRIGGER 0xC0 + */ +void rt_hw_interrupt_set_type(int vector, int type) +{ + sysSetInterruptType((IRQn_Type)vector, (UINT32) type); +} + +void rt_low_level_init(void) +{ + /* Unlock write-protect */ + SYS_UnlockReg(); + + /* Close WDT first, to avoid WDT timer is enabled IBR timeout reset. */ + WDT_Close(); + + /* Lock write-protect */ + SYS_LockReg(); +} + +void nu_clock_base_init(void) +{ + nu_sys_ipclk_enable(CPUCKEN); + nu_sys_ipclk_enable(HCLKCKEN); + nu_sys_ipclk_enable(HCLK1CKEN); + nu_sys_ipclk_enable(HCLK3CKEN); + nu_sys_ipclk_enable(HCLK4CKEN); + nu_sys_ipclk_enable(PCLKCKEN); + nu_sys_ipclk_enable(SRAMCKEN); + nu_sys_ipclk_enable(DDRCKEN); +} + +void machine_reset(void) +{ + rt_kprintf("machine_reset...\n"); + rt_hw_interrupt_disable(); + + /* Unlock */ + SYS_UnlockReg(); + + nu_sys_ip_reset(CHIPRST); + + while (1); +} + +void machine_shutdown(void) +{ + rt_kprintf("machine_shutdown...\n"); + rt_hw_interrupt_disable(); + + /* Unlock */ + SYS_UnlockReg(); + + while (1); +} + + +void nu_sys_ip_reset(E_SYS_IPRST eIPRstIdx) +{ + uint32_t volatile u32IPRSTRegAddr; + uint32_t u32IPRSTRegBit; + rt_uint32_t level; + + if (eIPRstIdx >= SYS_IPRST_CNT) + return; + + u32IPRSTRegAddr = REG_SYS_AHBIPRST + (4ul * (eIPRstIdx / 32)); + u32IPRSTRegBit = eIPRstIdx % 32; + + /* Enter critical section */ + level = rt_hw_interrupt_disable(); + + /* Unlock write-protect */ + SYS_UnlockReg(); + + /* Enable IP reset */ + outpw(u32IPRSTRegAddr, inpw(u32IPRSTRegAddr) | (1 << u32IPRSTRegBit)); + + /* Disable IP reset */ + outpw(u32IPRSTRegAddr, inpw(u32IPRSTRegAddr) & ~(1 << u32IPRSTRegBit)); + + /* Wait it done. */ + while (inpw(u32IPRSTRegAddr) & (1 << u32IPRSTRegBit)) {} + + /* Lock write protect */ + SYS_LockReg(); + + /* Leave critical section */ + rt_hw_interrupt_enable(level); +} + +static void _nu_sys_ipclk(E_SYS_IPCLK eIPClkIdx, uint32_t bEnable) +{ + uint32_t volatile u32IPCLKRegAddr; + uint32_t u32IPCLKRegBit; + rt_uint32_t level; + + if (eIPClkIdx >= SYS_IPCLK_CNT) + return; + + u32IPCLKRegAddr = REG_CLK_HCLKEN + (4ul * (eIPClkIdx / 32)); + u32IPCLKRegBit = eIPClkIdx % 32; + + /* Enter critical section */ + level = rt_hw_interrupt_disable(); + + if (bEnable) + { + /* Enable IP CLK */ + outpw(u32IPCLKRegAddr, inpw(u32IPCLKRegAddr) | (1 << u32IPCLKRegBit)); + } + else + { + /* Disable IP CLK */ + outpw(u32IPCLKRegAddr, inpw(u32IPCLKRegAddr) & ~(1 << u32IPCLKRegBit)); + } + + /* Leave critical section */ + rt_hw_interrupt_enable(level); +} + + +void nu_sys_ipclk_enable(E_SYS_IPCLK eIPClkIdx) +{ + _nu_sys_ipclk(eIPClkIdx, 1); +} + +void nu_sys_ipclk_disable(E_SYS_IPCLK eIPClkIdx) +{ + _nu_sys_ipclk(eIPClkIdx, 0); +} + +E_SYS_USB0_ID nu_sys_usb0_role(void) +{ + /* Check Role on USB0 dual-role port. */ + /* + [17] USB0_IDS + USB0_ID Status + 0 = USB port 0 used as a USB device port. + 1 = USB port 0 used as a USB host port. + */ + return ((inpw(REG_SYS_MISCISR) & (1 << 17)) > 0) ? USB0_ID_HOST : USB0_ID_DEVICE; +} + +#ifdef RT_USING_FINSH + +#include +FINSH_FUNCTION_EXPORT_ALIAS(rt_hw_cpu_reset, reset, restart the system); + +#ifdef FINSH_USING_MSH +int cmd_reset(int argc, char **argv) +{ + rt_hw_cpu_reset(); + return 0; +} + +int cmd_shutdown(int argc, char **argv) +{ + rt_hw_cpu_shutdown(); + return 0; +} + +FINSH_FUNCTION_EXPORT_ALIAS(cmd_reset, __cmd_reset, restart the system.); +FINSH_FUNCTION_EXPORT_ALIAS(cmd_shutdown, __cmd_shutdown, shutdown the system.); + +int nu_clocks(int argc, char **argv) +{ + rt_kprintf("SYS_UPLL = %d MHz\n", sysGetClock(SYS_UPLL)); + rt_kprintf("SYS_APLL = %d MHz\n", sysGetClock(SYS_APLL)); + rt_kprintf("SYS_SYSTEM = %d MHz\n", sysGetClock(SYS_SYSTEM)); + rt_kprintf("SYS_HCLK1 = %d MHz\n", sysGetClock(SYS_HCLK1)); + rt_kprintf("SYS_HCLK234 = %d MHz\n", sysGetClock(SYS_HCLK234)); + rt_kprintf("SYS_PCLK = %d MHz\n", sysGetClock(SYS_PCLK)); + rt_kprintf("SYS_CPU = %d MHz\n", sysGetClock(SYS_CPU)); + + rt_kprintf("CLK_HCLKEN = %08X\n", inpw(REG_CLK_HCLKEN)); + rt_kprintf("CLK_PCLKEN0 = %08X\n", inpw(REG_CLK_PCLKEN0)); + rt_kprintf("CLK_PCLKEN1 = %08X\n", inpw(REG_CLK_PCLKEN1)); + + return 0; +} +MSH_CMD_EXPORT(nu_clocks, Get all system clocks); + +#ifdef RT_USING_INTERRUPT_INFO +int list_interrupt(int argc, char **argv) +{ + int i; + + for (i = SYS_MIN_INT_SOURCE; i <= SYS_MAX_INT_SOURCE; i++) + { + if (irq_desc[i].handler != rt_hw_interrupt_dummy_handler) + { + rt_kprintf("[%d] %s: %d\n", i, irq_desc[i].name, irq_desc[i].counter); + } + } + + return 0; +} +MSH_CMD_EXPORT(list_interrupt, list registered interrupts); +#endif + +#endif + +#endif diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sys.h b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sys.h new file mode 100644 index 0000000000..621a476e6d --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sys.h @@ -0,0 +1,281 @@ +#ifndef __PLAT_INTERRUPT_H__ +#define __PLAT_INTERRUPT_H__ + +#include "rthw.h" +#include + +#if defined(BSP_USING_MMU) + #include "mmu.h" + #define NONCACHEABLE BIT31 +#else + #define NONCACHEABLE 0 +#endif + +#define sysprintf rt_kprintf + +typedef enum +{ + SYS_IPRST_NA = -1, + + /* SYS_AHBIPRST, SYS_BA + 0x060 */ + CHIPRST, + AHBIPRST_Reserved_1, + CPURST, + GDMARST, + AHBIPRST_Reserved_4, + AHBIPRST_Reserved_5, + AHBIPRST_Reserved_6, + AHBIPRST_Reserved_7, + + I2SRST, + LCDRST, + CAPRST, + AHBIPRST_Reserved_11, + AHBIPRST_Reserved_12, + AHBIPRST_Reserved_13, + AHBIPRST_Reserved_14, + AHBIPRST_Reserved_15, + + EMAC0RST, + EMAC1RST, + USBHRST, + USBDRST, + FMIRST, + GE2DRST, + JPEGRST, + CRYPTORST, + + SDIORST, + AHBIPRST_Reserved_25, + AHBIPRST_Reserved_26, + AHBIPRST_Reserved_27, + AHBIPRST_Reserved_28, + AHBIPRST_Reserved_29, + AHBIPRST_Reserved_30, + AHBIPRST_Reserved_31, + + /* SYS_APBIPRST0, SYS_BA + 0x064 */ + APBIPRST0_Reserved_0, + APBIPRST0_Reserved_1, + APBIPRST0_Reserved_2, + GPIORST, + ETIMER0RST, + ETIMER1RST, + ETIMER2RST, + ETIMER3RST, + + TIMER0RST, + TIMER1RST, + TIMER2RST, + TIMER3RST, + TIMER4RST, + APBIPRST0_Reserved_13, + APBIPRST0_Reserved_14, + APBIPRST0_Reserved_15, + + UART0RST, + UART1RST, + UART2RST, + UART3RST, + UART4RST, + UART5RST, + UART6RST, + UART7RST, + + UART8RST, + UART9RST, + UART10RST, + APBIPRST0_Reserved_27, + APBIPRST0_Reserved_28, + APBIPRST0_Reserved_29, + APBIPRST0_Reserved_30, + APBIPRST0_Reserved_31, + + /* SYS_APBIPRST1, SYS_BA + 0x068 */ + I2C0RST, + I2C1RST, + APBIPRST1_Reserved_2, + APBIPRST1_Reserved_3, + SPI0RST, + SPI1RST, + APBIPRST1_Reserved_6, + APBIPRST1_Reserved_7, + + CAN0RST, + CAN1RST, + APBIPRST1_Reserved_10, + APBIPRST1_Reserved_11, + SMC0RST, + SMC1RST, + APBIPRST1_Reserved_14, + APBIPRST1_Reserved_15, + + APBIPRST1_Reserved_16, + APBIPRST1_Reserved_17, + APBIPRST1_Reserved_18, + APBIPRST1_Reserved_19, + APBIPRST1_Reserved_20, + APBIPRST1_Reserved_21, + APBIPRST1_Reserved_22, + APBIPRST1_Reserved_23, + + ADCRST, + APBIPRST1_Reserved_25, + MTPCRST, + PWMRST, + APBIPRST1_Reserved_28, + APBIPRST1_Reserved_29, + APBIPRST1_Reserved_30, + APBIPRST1_Reserved_31, + + SYS_IPRST_CNT + +} E_SYS_IPRST; + +typedef enum +{ + SYS_IPCLK_NA = -1, + + /* CLK_HCLKEN, CLK_BA + 0x010 */ + CPUCKEN, + HCLKCKEN, + HCLK1CKEN, + HCLK3CKEN, + HCLK4CKEN, + PCLKCKEN, + HCLKEN_Reserved_6, + TICCKEN, + + SRAMCKEN, + EBICKEN, + DDRCKEN, + HCLKEN_Reserved_11, + GDMACKEN, + HCLKEN_Reserved_13, + HCLKEN_Reserved_14, + CKOCKEN, + + EMAC0CKEN, + EMAC1CKEN, + USBHCKEN, + USBDCKEN, + FMICKEN, + NANDCKEN, + EMMCCKEN, + CRYPTOCKEN, + + I2SCKEN, + LCDCKEN, + CAPCKEN, + SENSORCKEN, + GE2DCKEN, + JPEGCKEN, + SDHCKEN, + HCLKEN_Reserved_31, + + CLK_HCLKEN_END, + + /* CLK_BA+0x014 */ + + /* CLK_PCLKEN0 CLK_BA+0x018 */ + CLK_PCLKEN0_BEGIN = CLK_HCLKEN_END + 32, + + WDTCKEN = CLK_PCLKEN0_BEGIN, + WWDTCKEN, + RTCCKEN, + GPIOCKEN, + ETIMER0CKEN, + ETIMER1CKEN, + ETIMER2CKEN, + ETIMER3CKEN, + + TIMER0CKEN, + TIMER1CKEN, + TIMER2CKEN, + TIMER3CKEN, + TIMER4CKEN, + PCLKEN0_Reserved_14, + PCLKEN0_Reserved_15, + PCLKEN0_Reserved_16, + + UART0CKEN, + UART1CKEN, + UART2CKEN, + UART3CKEN, + UART4CKEN, + UART5CKEN, + UART6CKEN, + UART7CKEN, + + UART8CKEN, + UART9CKEN, + UART10CKEN, + PCLKEN0_Reserved_27, + PCLKEN0_Reserved_28, + PCLKEN0_Reserved_29, + PCLKEN0_Reserved_30, + PCLKEN0_Reserved_31, + + /* CLK_PCLKEN1, CLK_BA + 0x01C */ + I2C0CKEN, + I2C1CKEN, + PCLKEN1_Reserved_2, + PCLKEN1_Reserved_3, + SPI0CKEN, + SPI1CKEN, + PCLKEN1_Reserved_6, + PCLKEN1_Reserved_7, + + CAN0CKEN, + CAN1CKEN, + PCLKEN1_Reserved_10, + PCLKEN1_Reserved_11, + SMC0CKEN, + SMC1CKEN, + PCLKEN1_Reserved_14, + PCLKEN1_Reserved_15, + + PCLKEN1_Reserved_16, + PCLKEN1_Reserved_17, + PCLKEN1_Reserved_18, + PCLKEN1_Reserved_19, + PCLKEN1_Reserved_20, + PCLKEN1_Reserved_21, + PCLKEN1_Reserved_22, + PCLKEN1_Reserved_23, + + ADCCKEN, + PCLKEN1_Reserved_25, + MTPCCKEN, + PWMCKEN, + PCLKEN1_Reserved_28, + PCLKEN1_Reserved_29, + PCLKEN1_Reserved_30, + PCLKEN1_Reserved_31, + + SYS_IPCLK_CNT + +} E_SYS_IPCLK; + +typedef enum +{ + USB0_ID_DEVICE, + USB0_ID_HOST, + USB0_ID_CNT +} E_SYS_USB0_ID; + +void rt_hw_interrupt_init(void); +void rt_hw_interrupt_set_priority(int vector, int priority); +void rt_hw_interrupt_set_type(int vector, int type); +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name); + +void rt_hw_systick_init(void); +void nu_clock_base_init(void); + +void nu_systick_udelay(uint32_t delay_us); +void nu_sys_ip_reset(E_SYS_IPRST eIPRstIdx); +void nu_sys_ipclk_enable(E_SYS_IPCLK eIPClkIdx); +void nu_sys_ipclk_disable(E_SYS_IPCLK eIPClkIdx); +E_SYS_USB0_ID nu_sys_usb0_role(void); + +#endif diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_systick.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_systick.c new file mode 100644 index 0000000000..8587be6ba3 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_systick.c @@ -0,0 +1,92 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-11-11 Wayne First version +* +******************************************************************************/ + +#include "rtthread.h" +#include "NuMicro.h" +#include "drv_sys.h" +#include "nu_timer.h" + +#define USE_TIMER 4 + +/* Concatenate */ +#define _CONCAT2_(x, y) x##y +#define _CONCAT3_(x, y, z) x##y##z +#define CONCAT2(x, y) _CONCAT2_(x, y) +#define CONCAT3(x, y, z) _CONCAT3_(x,y,z) + +/* Concatenate the macros of timer instance for driver usage. */ +#define SYSTICK_IRQ CONCAT2(IRQ_TMR, USE_TIMER ) + +#define SYSTICK_CLKEN CONCAT3(TIMER, USE_TIMER, CKEN) + +#define SYSTICK_RST CONCAT3(TIMER, USE_TIMER, RST) + +static void nu_systick_isr(int vector, void *param) +{ + rt_tick_increase(); + TIMER_ClearIntFlag(USE_TIMER); +} + +void rt_hw_systick_init(void) +{ + nu_sys_ipclk_enable(SYSTICK_CLKEN); + + nu_sys_ip_reset(SYSTICK_RST); + + // Set timer frequency + TIMER_Open(USE_TIMER, TIMER_PERIODIC_MODE, RT_TICK_PER_SECOND); + + // Enable timer interrupt + TIMER_EnableInt(USE_TIMER); + + rt_hw_interrupt_install(SYSTICK_IRQ, nu_systick_isr, RT_NULL, "systick"); + rt_hw_interrupt_set_priority(SYSTICK_IRQ, IRQ_LEVEL_1); + rt_hw_interrupt_umask(SYSTICK_IRQ); + + TIMER_Start(USE_TIMER); +} /* rt_hw_systick_init */ + +void rt_hw_us_delay(rt_uint32_t us) +{ + rt_uint32_t ticks; + rt_uint32_t told, tnow, tcnt = 0; + rt_uint32_t cmp = TIMER_GetCompareData(USE_TIMER); + + ticks = us * cmp / (1000000 / RT_TICK_PER_SECOND); + told = TIMER_GetCounter(USE_TIMER); + while (1) + { + /* Timer counter is increment. */ + tnow = TIMER_GetCounter(USE_TIMER); + if (tnow != told) + { + /* 0 -- old === now -------- cmp */ + if (tnow > told) + { + tcnt += tnow - told; + } + else + { + /* 0 == now --- old ======== cmp */ + tcnt += cmp - told + tnow; + } + told = tnow; + + /* Timeout */ + if (tcnt >= ticks) + { + break; + } + } + } + +} /* rt_hw_us_delay */ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_timer.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_timer.c new file mode 100644 index 0000000000..946da8a6f1 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_timer.c @@ -0,0 +1,285 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-3 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_TIMER) && defined(RT_USING_HWTIMER) + +#include +#include "NuMicro.h" +#include +#include "nu_timer.h" + +/* Private define ---------------------------------------------------------------*/ +#define NU_TIMER_DEVICE(timer) (nu_timer_t)(timer) + +enum +{ + TIMER_START = -1, +#if defined(BSP_USING_TIMER0) + TIMER0_IDX, +#endif +#if defined(BSP_USING_TIMER1) + TIMER1_IDX, +#endif +#if defined(BSP_USING_TIMER2) + TIMER2_IDX, +#endif +#if defined(BSP_USING_TIMER3) + TIMER3_IDX, +#endif + /* BSP_USING_TIMER4 is reserved for Systick usage. */ + TIMER_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ +struct nu_timer +{ + rt_hwtimer_t parent; + char *name; + uint32_t idx; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; +}; +typedef struct nu_timer *nu_timer_t; + +/* Private functions ------------------------------------------------------------*/ +static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state); +static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode); +static void nu_timer_stop(rt_hwtimer_t *timer); +static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer); +static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args); + +/* Public functions -------------------------------------------------------------*/ + + +/* Private variables ------------------------------------------------------------*/ +static struct nu_timer nu_timer_arr [] = +{ +#if defined(BSP_USING_TIMER0) + { + .name = "timer0", + .idx = 0, + .irqn = IRQ_TMR0, + .rstidx = TIMER0RST, + .clkidx = TIMER0CKEN, + }, +#endif +#if defined(BSP_USING_TIMER1) + { + .name = "timer1", + .idx = 1, + .irqn = IRQ_TMR1, + .rstidx = TIMER1RST, + .clkidx = TIMER1CKEN, + }, +#endif +#if defined(BSP_USING_TIMER2) + { + .name = "timer2", + .idx = 2, + .irqn = IRQ_TMR2, + .rstidx = TIMER2RST, + .clkidx = TIMER2CKEN, + }, +#endif +#if defined(BSP_USING_TIMER3) + { + .name = "timer3", + .idx = 3, + .irqn = IRQ_TMR3, + .rstidx = TIMER3RST, + .clkidx = TIMER3CKEN, + }, +#endif + /* BSP_USING_TIMER4 is reserved for Systick usage. */ +}; + +static struct rt_hwtimer_info nu_timer_info = +{ + 12000000, /* maximum count frequency */ + 46875, /* minimum count frequency */ + 0xFFFFFF, /* the maximum counter value */ + HWTIMER_CNTMODE_UP, /* Increment or Decreasing count mode */ +}; + +static struct rt_hwtimer_ops nu_timer_ops = +{ + nu_timer_init, + nu_timer_start, + nu_timer_stop, + nu_timer_count_get, + nu_timer_control +}; + +/* Functions define ------------------------------------------------------------*/ +static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state) +{ + nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer); + RT_ASSERT(psNuTmr != RT_NULL); + + if (1 == state) + { + uint32_t timer_clk; + struct rt_hwtimer_info *info = &nu_timer_info; + + timer_clk = TIMER_GetModuleClock(psNuTmr->idx); + info->maxfreq = timer_clk; + info->minfreq = timer_clk / 256; + TIMER_Open(psNuTmr->idx, TIMER_ONESHOT_MODE, 1); + TIMER_EnableInt(psNuTmr->idx); + rt_hw_interrupt_umask(psNuTmr->irqn); + } + else + { + rt_hw_interrupt_mask(psNuTmr->irqn); + TIMER_DisableInt(psNuTmr->idx); + TIMER_Close(psNuTmr->idx); + } +} + +static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode) +{ + rt_err_t ret = RT_EINVAL; + rt_uint32_t u32OpMode; + + nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer); + RT_ASSERT(psNuTmr != RT_NULL); + + if (cnt <= 1 || cnt > 0xFFFFFF) + { + goto exit_nu_timer_start; + } + + switch (opmode) + { + case HWTIMER_MODE_PERIOD: + u32OpMode = TIMER_PERIODIC_MODE; + break; + + case HWTIMER_MODE_ONESHOT: + u32OpMode = TIMER_ONESHOT_MODE; + break; + + default: + goto exit_nu_timer_start; + } + + TIMER_SET_CMP_VALUE(psNuTmr->idx, cnt); + TIMER_SET_OPMODE(psNuTmr->idx, u32OpMode); + TIMER_EnableInt(psNuTmr->idx); + rt_hw_interrupt_umask(psNuTmr->irqn); + + TIMER_Start(psNuTmr->idx); + + ret = RT_EOK; + +exit_nu_timer_start: + + return -(ret); +} + +static void nu_timer_stop(rt_hwtimer_t *timer) +{ + nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer); + RT_ASSERT(psNuTmr != RT_NULL); + + rt_hw_interrupt_mask(psNuTmr->irqn); + TIMER_DisableInt(psNuTmr->idx); + TIMER_Stop(psNuTmr->idx); + TIMER_ClearCounter(psNuTmr->idx); +} + +static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer) +{ + nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer); + RT_ASSERT(psNuTmr != RT_NULL); + + return TIMER_GetCounter(psNuTmr->idx); +} + +static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args) +{ + rt_err_t ret = RT_EOK; + nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer); + RT_ASSERT(psNuTmr != RT_NULL); + + switch (cmd) + { + case HWTIMER_CTRL_FREQ_SET: + { + uint32_t clk; + uint32_t pre; + + clk = TIMER_GetModuleClock(psNuTmr->idx); + pre = clk / *((uint32_t *)args) - 1; + TIMER_SET_PRESCALE_VALUE(psNuTmr->idx, pre); + *((uint32_t *)args) = clk / (pre + 1) ; + } + break; + + case HWTIMER_CTRL_STOP: + TIMER_Stop(psNuTmr->idx); + break; + + default: + ret = RT_EINVAL; + break; + } + + return -(ret); +} + +/** + * All UART interrupt service routine + */ +static void nu_timer_isr(int vector, void *param) +{ + nu_timer_t psNuTmr = NU_TIMER_DEVICE(param); + RT_ASSERT(psNuTmr != RT_NULL); + + if (TIMER_GetIntFlag(psNuTmr->idx)) + { + TIMER_ClearIntFlag(psNuTmr->idx); + rt_device_hwtimer_isr(&psNuTmr->parent); + } +} + +int rt_hw_timer_init(void) +{ + int i; + rt_err_t ret = RT_EOK; + for (i = (TIMER_START + 1); i < TIMER_CNT; i++) + { + nu_sys_ipclk_enable(nu_timer_arr[i].clkidx); + + nu_sys_ip_reset(nu_timer_arr[i].rstidx); + + /* Register Etimer information. */ + nu_timer_arr[i].parent.info = &nu_timer_info; + + /* Register Etimer operation. */ + nu_timer_arr[i].parent.ops = &nu_timer_ops; + + /* Register Etimer interrupt service routine. */ + rt_hw_interrupt_install(nu_timer_arr[i].irqn, nu_timer_isr, &nu_timer_arr[i], nu_timer_arr[i].name); + + /* Register RT hwtimer device. */ + ret = rt_device_hwtimer_register(&nu_timer_arr[i].parent, nu_timer_arr[i].name, &nu_timer_arr[i]); + RT_ASSERT(ret == RT_EOK); + } + return 0; +} +INIT_BOARD_EXPORT(rt_hw_timer_init); + +#endif //#if defined(BSP_USING_TIMER) && defined(RT_USING_HWTIMER) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_uart.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_uart.c new file mode 100644 index 0000000000..ca7a03e8e3 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_uart.c @@ -0,0 +1,482 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-1-11 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_UART) + +#include +#include +#include "NuMicro.h" +#include +#include + + +/* Private define ---------------------------------------------------------------*/ +enum +{ + UART_START = -1, +#if defined(BSP_USING_UART0) + UART0_IDX, +#endif +#if defined(BSP_USING_UART1) + UART1_IDX, +#endif +#if defined(BSP_USING_UART2) + UART2_IDX, +#endif +#if defined(BSP_USING_UART3) + UART3_IDX, +#endif +#if defined(BSP_USING_UART4) + UART4_IDX, +#endif +#if defined(BSP_USING_UART5) + UART5_IDX, +#endif +#if defined(BSP_USING_UART6) + UART6_IDX, +#endif +#if defined(BSP_USING_UART7) + UART7_IDX, +#endif +#if defined(BSP_USING_UART8) + UART8_IDX, +#endif +#if defined(BSP_USING_UART9) + UART9_IDX, +#endif +#if defined(BSP_USING_UART10) + UART10_IDX, +#endif + UART_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ +struct nu_uart +{ + rt_serial_t dev; + char *name; + UART_T *uart_base; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; +}; +typedef struct nu_uart *nu_uart_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg); +static rt_err_t nu_uart_control(struct rt_serial_device *serial, int cmd, void *arg); +static int nu_uart_send(struct rt_serial_device *serial, char c); +static int nu_uart_receive(struct rt_serial_device *serial); + +/* Public functions ------------------------------------------------------------*/ + +/* Private variables ------------------------------------------------------------*/ + +static const struct rt_uart_ops nu_uart_ops = +{ + .configure = nu_uart_configure, + .control = nu_uart_control, + .putc = nu_uart_send, + .getc = nu_uart_receive, + .dma_transmit = RT_NULL +}; + +static const struct serial_configure nu_uart_default_config = + RT_SERIAL_CONFIG_DEFAULT; + +static struct nu_uart nu_uart_arr [] = +{ +#if defined(BSP_USING_UART0) + { + .name = "uart0", + .uart_base = UART0, + .irqn = IRQ_UART0, + .rstidx = UART0RST, + .clkidx = UART0CKEN, + }, +#endif + +#if defined(BSP_USING_UART1) + { + .name = "uart1", + .uart_base = UART1, + .irqn = IRQ_UART1, + .rstidx = UART1RST, + .clkidx = UART1CKEN, + }, +#endif + +#if defined(BSP_USING_UART2) + { + .name = "uart2", + .uart_base = UART2, + .irqn = IRQ_UART2, + .rstidx = UART2RST, + .clkidx = UART2CKEN, + }, +#endif + +#if defined(BSP_USING_UART3) + { + .name = "uart3", + .uart_base = UART3, + .irqn = IRQ_UART3, + .rstidx = UART3RST, + .clkidx = UART3CKEN, + }, +#endif + +#if defined(BSP_USING_UART4) + { + .name = "uart4", + .uart_base = UART4, + .irqn = IRQ_UART4, + .rstidx = UART4RST, + .clkidx = UART4CKEN, + }, +#endif + +#if defined(BSP_USING_UART5) + { + .name = "uart5", + .uart_base = UART5, + .irqn = IRQ_UART5, + .rstidx = UART5RST, + .clkidx = UART5CKEN, + }, +#endif + +#if defined(BSP_USING_UART6) + { + .name = "uart6", + .uart_base = UART6, + .irqn = IRQ_UART6, + .rstidx = UART6RST, + .clkidx = UART6CKEN, + }, +#endif + +#if defined(BSP_USING_UART7) + { + .name = "uart7", + .uart_base = UART7, + .irqn = IRQ_UART7, + .rstidx = UART7RST, + .clkidx = UART7CKEN, + }, +#endif + +#if defined(BSP_USING_UART8) + { + .name = "uart8", + .uart_base = UART8, + .irqn = IRQ_UART8, + .rstidx = UART8RST, + .clkidx = UART8CKEN, + }, +#endif + +#if defined(BSP_USING_UART9) + { + .name = "uart9", + .uart_base = UART9, + .irqn = IRQ_UART9, + .rstidx = UART9RST, + .clkidx = UART9CKEN, + }, +#endif + +#if defined(BSP_USING_UART10) + { + .name = "uart10", + .uart_base = UARTA, + .irqn = IRQ_UART10, + .rstidx = UART10RST, + .clkidx = UART10CKEN, + }, +#endif + +}; /* uart nu_uart */ + +/** + * All UART interrupt service routine + */ +static void nu_uart_isr(int vector, void *param) +{ + /* Get base address of uart register */ + nu_uart_t serial = (nu_uart_t)param; + UART_T *uart_base = ((nu_uart_t)serial)->uart_base; + + /* Get interrupt event */ + uint32_t u32IntSts = uart_base->INTSTS; + uint32_t u32FIFOSts = uart_base->FIFOSTS; + + /* Handle RX event */ + if (u32IntSts & (UART_ISR_RDA_INT_Msk | UART_ISR_TOUT_INT_Msk)) + { + rt_hw_serial_isr(&serial->dev, RT_SERIAL_EVENT_RX_IND); + } + uart_base->INTSTS = u32IntSts; + uart_base->FIFOSTS = u32FIFOSts; +} + +/** + * Set RS-485 AUD mode + */ +void nu_uart_set_rs485aud(struct rt_serial_device *serial, rt_bool_t bRTSActiveLowLevel) +{ + UART_T *uart_base; + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uart register */ + uart_base = ((nu_uart_t)serial)->uart_base; + + /* Set RTS as RS-485 phy direction controlling ping. */ + uart_base->FUNCSEL = UART_FUNCSEL_RS485; + + /* Set RS585 configuration */ + uart_base->ALTCTL &= ~(UART_ALT_CSR_RS485_NMM_Msk | UART_ALT_CSR_RS485_AAD_Msk | UART_ALT_CSR_RS485_AUD_Msk | UART_ALT_CSR_RS485_ADD_EN_Msk); + uart_base->ALTCTL |= UART_ALT_CSR_RS485_AUD_Msk; + + if (bRTSActiveLowLevel) + { + /* Set direction pin as active-high. */ + uart_base->MODEM &= ~UART_MCR_LEV_RTS_Msk; + } + else + { + /* Set direction pin as active-low. */ + uart_base->MODEM |= UART_MCR_LEV_RTS_Msk; + } + + rt_kprintf("Set %s to RS-485 AUD function mode. ActiveLowLevel-%s\n", ((nu_uart_t)serial)->name, bRTSActiveLowLevel ? "YES" : "NO"); +} + +/** + * Configure uart port + */ +static rt_err_t nu_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + rt_err_t ret = RT_EOK; + uint32_t uart_word_len = 0; + uint32_t uart_stop_bit = 0; + uint32_t uart_parity = 0; + + /* Get base address of uart register */ + UART_T *uart_base = ((nu_uart_t)serial)->uart_base; + + /* Check baudrate */ + RT_ASSERT(cfg->baud_rate != 0); + + /* Check word len */ + switch (cfg->data_bits) + { + case DATA_BITS_5: + uart_word_len = UART_WORD_LEN_5; + break; + + case DATA_BITS_6: + uart_word_len = UART_WORD_LEN_6; + break; + + case DATA_BITS_7: + uart_word_len = UART_WORD_LEN_7; + break; + + case DATA_BITS_8: + uart_word_len = UART_WORD_LEN_8; + break; + + default: + rt_kprintf("Unsupported data length"); + ret = RT_EINVAL; + goto exit_nu_uart_configure; + } + + /* Check stop bit */ + switch (cfg->stop_bits) + { + case STOP_BITS_1: + uart_stop_bit = UART_STOP_BIT_1; + break; + + case STOP_BITS_2: + uart_stop_bit = UART_STOP_BIT_2; + break; + + default: + rt_kprintf("Unsupported stop bit"); + ret = RT_EINVAL; + goto exit_nu_uart_configure; + } + + /* Check parity */ + switch (cfg->parity) + { + case PARITY_NONE: + uart_parity = UART_PARITY_NONE; + break; + + case PARITY_ODD: + uart_parity = UART_PARITY_ODD; + break; + + case PARITY_EVEN: + uart_parity = UART_PARITY_EVEN; + break; + + default: + rt_kprintf("Unsupported parity"); + ret = RT_EINVAL; + goto exit_nu_uart_configure; + } + + nu_sys_ip_reset(((nu_uart_t)serial)->rstidx); + + /* Open Uart and set UART Baudrate */ + UART_Open(uart_base, cfg->baud_rate); + + /* Set line configuration. */ + UART_SetLineConfig(uart_base, 0, uart_word_len, uart_parity, uart_stop_bit); + + /* Enable interrupt. */ + rt_hw_interrupt_umask(((nu_uart_t)serial)->irqn); + +exit_nu_uart_configure: + + if (ret != RT_EOK) + UART_Close(uart_base); + + return -(ret); +} + +/** + * Uart interrupt control + */ +static rt_err_t nu_uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + nu_uart_t psNuUart = (nu_uart_t)serial; + rt_err_t result = RT_EOK; + rt_uint32_t flag; + rt_ubase_t ctrl_arg = (rt_ubase_t)arg; + + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uart register */ + UART_T *uart_base = psNuUart->uart_base; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) /* Disable INT-RX */ + { + flag = UART_IER_RDA_IEN_Msk | UART_IER_RTO_IEN_Msk | UART_IER_TIME_OUT_EN_Msk; + UART_DISABLE_INT(uart_base, flag); + } + else if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) /* Disable DMA-RX */ + { + /* Disable Receive Line interrupt & Stop DMA RX transfer. */ + } + break; + + case RT_DEVICE_CTRL_SET_INT: + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) /* Enable INT-RX */ + { + flag = UART_IER_RDA_IEN_Msk | UART_IER_RTO_IEN_Msk | UART_IER_TIME_OUT_EN_Msk; + UART_ENABLE_INT(uart_base, flag); + } + break; + + case RT_DEVICE_CTRL_CLOSE: + /* Disable interrupt. */ + rt_hw_interrupt_mask(psNuUart->irqn); + + /* Close UART port */ + UART_Close(uart_base); + + break; + + default: + result = -RT_EINVAL; + break; + + } + return result; +} + +/** + * Uart put char + */ +static int nu_uart_send(struct rt_serial_device *serial, char c) +{ + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uart register */ + UART_T *uart_base = ((nu_uart_t)serial)->uart_base; + + /* Waiting if TX-FIFO is full. */ + while (UART_IS_TX_FULL(uart_base)); + + /* Put char into TX-FIFO */ + UART_WRITE(uart_base, c); + + return 1; +} + +/** + * Uart get char + */ +static int nu_uart_receive(struct rt_serial_device *serial) +{ + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uart register */ + UART_T *uart_base = ((nu_uart_t)serial)->uart_base; + + /* Return failure if RX-FIFO is empty. */ + if (UART_GET_RX_EMPTY(uart_base)) + { + return -1; + } + + /* Get char from RX-FIFO */ + return UART_READ(uart_base); +} + +/** + * Hardware UART Initialization + */ +rt_err_t rt_hw_uart_init(void) +{ + int i; + rt_uint32_t flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX; + rt_err_t ret = RT_EOK; + + for (i = (UART_START + 1); i < UART_CNT; i++) + { + nu_uart_arr[i].dev.ops = &nu_uart_ops; + nu_uart_arr[i].dev.config = nu_uart_default_config; + + rt_hw_interrupt_install(nu_uart_arr[i].irqn, nu_uart_isr, &nu_uart_arr[i], nu_uart_arr[i].name); + + nu_sys_ipclk_enable(nu_uart_arr[i].clkidx); + + ret = rt_hw_serial_register(&nu_uart_arr[i].dev, nu_uart_arr[i].name, flag, NULL); + RT_ASSERT(ret == RT_EOK); + } + + return ret; +} + +#endif //#if defined(BSP_USING_UART) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_uart.h b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_uart.h new file mode 100644 index 0000000000..cda8e7fb85 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_uart.h @@ -0,0 +1,21 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-2-7 Wayne First version +* +******************************************************************************/ + +#ifndef __DRV_UART_H__ +#define __DRV_UART_H__ + +#include + +rt_err_t rt_hw_uart_init(void); +void nu_uart_set_rs485aud(struct rt_serial_device *serial, rt_bool_t bRTSActiveLowLevel); + +#endif /* __DRV_UART_H__ */ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbd.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbd.c new file mode 100644 index 0000000000..876c6d96c2 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbd.c @@ -0,0 +1,932 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-03-16 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_USBD) + +#include +#include +#include +#include "NuMicro.h" +#include +#include "drv_sys.h" + +#define LOG_TAG "drv.usbd" +//#define DBG_ENABLE +#define DBG_SECTION_NAME "drv.usbd" +//#define DBG_LEVEL DBG_ERROR +#define DBG_COLOR +#include + +/* Private define ---------------------------------------------------------------*/ +#define ENABLE_FULL_SPEED_MODE_ONLY 0 /* 0: default hi-speed mode; 1: full-speed mode only */ + +/* Define EP maximum packet size */ + +#define CEP_MAX_PKT_SIZE 64 +#define CEP_OTHER_MAX_PKT_SIZE 64 + +#define EPA_MAX_PKT_SIZE 512 +#define EPA_OTHER_MAX_PKT_SIZE 64 + +#define EPB_MAX_PKT_SIZE 512 +#define EPB_OTHER_MAX_PKT_SIZE 64 + +#define EPC_MAX_PKT_SIZE 64 +#define EPC_OTHER_MAX_PKT_SIZE 64 + +#define EPD_MAX_PKT_SIZE 64 +#define EPD_OTHER_MAX_PKT_SIZE 64 + +#define EPE_MAX_PKT_SIZE 512 +#define EPE_OTHER_MAX_PKT_SIZE 64 + +#define EPF_MAX_PKT_SIZE 512 +#define EPF_OTHER_MAX_PKT_SIZE 64 + +#define EPG_MAX_PKT_SIZE 64 +#define EPG_OTHER_MAX_PKT_SIZE 64 + +#define EPH_MAX_PKT_SIZE 64 +#define EPH_OTHER_MAX_PKT_SIZE 64 + +#define EPI_MAX_PKT_SIZE 512 +#define EPI_OTHER_MAX_PKT_SIZE 64 + +#define EPJ_MAX_PKT_SIZE 512 +#define EPJ_OTHER_MAX_PKT_SIZE 64 + +#define EPK_MAX_PKT_SIZE 64 +#define EPK_OTHER_MAX_PKT_SIZE 64 + +#define EPL_MAX_PKT_SIZE 64 +#define EPL_OTHER_MAX_PKT_SIZE 64 + +#define CEP_BUF_BASE 0 +#define CEP_BUF_LEN CEP_MAX_PKT_SIZE + +#define EPA_BUF_BASE (CEP_BUF_BASE + CEP_BUF_LEN) +#define EPA_BUF_LEN EPA_MAX_PKT_SIZE + +#define EPB_BUF_BASE (EPA_BUF_BASE + EPA_BUF_LEN) +#define EPB_BUF_LEN EPB_MAX_PKT_SIZE + +#define EPC_BUF_BASE (EPB_BUF_BASE + EPB_BUF_LEN) +#define EPC_BUF_LEN EPC_MAX_PKT_SIZE + +#define EPD_BUF_BASE (EPC_BUF_BASE + EPC_BUF_LEN) +#define EPD_BUF_LEN EPD_MAX_PKT_SIZE + +#define EPE_BUF_BASE (EPD_BUF_BASE + EPD_BUF_LEN) +#define EPE_BUF_LEN EPE_MAX_PKT_SIZE + +#define EPF_BUF_BASE (EPE_BUF_BASE + EPE_BUF_LEN) +#define EPF_BUF_LEN EPF_MAX_PKT_SIZE + +#define EPG_BUF_BASE (EPF_BUF_BASE + EPF_BUF_LEN) +#define EPG_BUF_LEN EPG_MAX_PKT_SIZE + +#define EPH_BUF_BASE (EPG_BUF_BASE + EPG_BUF_LEN) +#define EPH_BUF_LEN EPH_MAX_PKT_SIZE + +#define EPI_BUF_BASE (EPH_BUF_BASE + EPH_BUF_LEN) +#define EPI_BUF_LEN EPI_MAX_PKT_SIZE + +#define EPJ_BUF_BASE (EPI_BUF_BASE + EPI_BUF_LEN) +#define EPJ_BUF_LEN EPJ_MAX_PKT_SIZE + +#define EPK_BUF_BASE (EPJ_BUF_BASE + EPJ_BUF_LEN) +#define EPK_BUF_LEN EPK_MAX_PKT_SIZE + +#define EPL_BUF_BASE (EPK_BUF_BASE + EPK_BUF_LEN) +#define EPL_BUF_LEN EPL_MAX_PKT_SIZE + + +#define EPADR_SW2HW(address) ((address & USB_EPNO_MASK) - 1) /* for non-control endpoint */ +#define EPADR_HW2SW(address) ((address & USB_EPNO_MASK) + 1) /* for non-control endpoint */ + +/* Private typedef --------------------------------------------------------------*/ +typedef struct _nu_usbd_t +{ + USBD_T *base; /* REG base */ + char *name; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + uint8_t address_tmp; /* Keep assigned address for flow control */ + uint8_t plugging_status; /* For debounce, 0: Unplug, 1: plug-in */ +} nu_usbd_t; + + +typedef struct +{ + + uint32_t u32BufferBase; + uint32_t u32BufferLength; + + uint32_t u32OtherMaxPktSize; + +} S_EP_CXT; + + +/* Private variables ------------------------------------------------------------*/ + +static nu_usbd_t nu_usbd = +{ + .base = USBD, + .name = "usbd", + .irqn = IRQ_USBD, + .rstidx = USBDRST, + .clkidx = USBDCKEN, + .address_tmp = 0, + .plugging_status = 0, +}; + +static struct udcd _rt_obj_udc; + +static S_EP_CXT _ep_cxt_pool[] = +{ + { EPA_BUF_BASE, EPA_BUF_LEN, EPA_OTHER_MAX_PKT_SIZE}, //EPA + { EPB_BUF_BASE, EPB_BUF_LEN, EPB_OTHER_MAX_PKT_SIZE}, //EPB + { EPC_BUF_BASE, EPC_BUF_LEN, EPC_OTHER_MAX_PKT_SIZE}, //EPC + { EPD_BUF_BASE, EPD_BUF_LEN, EPD_OTHER_MAX_PKT_SIZE}, //EPD + { EPE_BUF_BASE, EPE_BUF_LEN, EPE_OTHER_MAX_PKT_SIZE}, //EPE + { EPF_BUF_BASE, EPF_BUF_LEN, EPF_OTHER_MAX_PKT_SIZE}, //EPF + { EPG_BUF_BASE, EPG_BUF_LEN, EPG_OTHER_MAX_PKT_SIZE}, //EPG + { EPH_BUF_BASE, EPH_BUF_LEN, EPH_OTHER_MAX_PKT_SIZE}, //EPH + { EPI_BUF_BASE, EPI_BUF_LEN, EPI_OTHER_MAX_PKT_SIZE}, //EPI + { EPJ_BUF_BASE, EPJ_BUF_LEN, EPJ_OTHER_MAX_PKT_SIZE}, //EPJ + { EPK_BUF_BASE, EPK_BUF_LEN, EPK_OTHER_MAX_PKT_SIZE}, //EPK + { EPL_BUF_BASE, EPL_BUF_LEN, EPL_OTHER_MAX_PKT_SIZE} //EPL +}; + +static struct ep_id _ep_pool[] = +{ + {0x0, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, CEP_MAX_PKT_SIZE, ID_ASSIGNED }, + + {EPADR_HW2SW(EPA), USB_EP_ATTR_BULK, USB_DIR_IN, EPA_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EPB), USB_EP_ATTR_BULK, USB_DIR_OUT, EPB_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EPC), USB_EP_ATTR_INT, USB_DIR_IN, EPC_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EPD), USB_EP_ATTR_INT, USB_DIR_OUT, EPD_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EPE), USB_EP_ATTR_BULK, USB_DIR_IN, EPE_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EPF), USB_EP_ATTR_BULK, USB_DIR_OUT, EPF_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EPG), USB_EP_ATTR_INT, USB_DIR_IN, EPG_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EPH), USB_EP_ATTR_INT, USB_DIR_OUT, EPH_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EPI), USB_EP_ATTR_BULK, USB_DIR_IN, EPE_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EPJ), USB_EP_ATTR_BULK, USB_DIR_OUT, EPF_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EPK), USB_EP_ATTR_INT, USB_DIR_IN, EPG_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EPL), USB_EP_ATTR_INT, USB_DIR_OUT, EPH_MAX_PKT_SIZE, ID_UNASSIGNED}, + + {0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED }, +}; + + +static void _nu_ep_partition_set(int isHighSpeed) +{ + int i; + + for (i = 0; i < USBD_MAX_EP; i++) + { + uint32_t u32NuEPTypeDef = 0x0; + uint32_t u32NuEPDirDef = 0x0; + + if (_ep_pool[i + 1].type == USB_EP_ATTR_BULK) + u32NuEPTypeDef = USB_EP_CFG_TYPE_BULK; + else if (_ep_pool[i + 1].type == USB_EP_ATTR_INT) + u32NuEPTypeDef = USB_EP_CFG_TYPE_INT; + else + continue; + + if (_ep_pool[i + 1].dir == USB_DIR_IN) + u32NuEPDirDef = USB_EP_CFG_DIR_IN; + else if (_ep_pool[i + 1].dir == USB_DIR_OUT) + u32NuEPDirDef = USB_EP_CFG_DIR_OUT; + else + continue; + + USBD_SetEpBufAddr(i, _ep_cxt_pool[i].u32BufferBase, _ep_cxt_pool[i].u32BufferLength); + if (isHighSpeed) + USBD_SET_MAX_PAYLOAD(i, _ep_cxt_pool[i].u32BufferLength); + else + USBD_SET_MAX_PAYLOAD(i, _ep_cxt_pool[i].u32OtherMaxPktSize); + + USBD_ConfigEp(i, EPADR_HW2SW(i), u32NuEPTypeDef, u32NuEPDirDef); + + if (u32NuEPDirDef == USB_EP_CFG_DIR_OUT) + USBD_ENABLE_EP_INT(i, USBD_EPINTEN_RXPKIEN_Msk); + + } //for + +} + +static void _nu_ep_partition(void) +{ + /* Configure USB controller */ + /* Enable USB BUS, CEP and EPA ~ EPH global interrupt */ + USBD_ENABLE_USB_INT(USBD_GINTEN_USBIE_Msk + | USBD_GINTEN_CEPIE_Msk + | USBD_GINTEN_EPAIE_Msk + | USBD_GINTEN_EPBIE_Msk + | USBD_GINTEN_EPCIE_Msk + | USBD_GINTEN_EPDIE_Msk + | USBD_GINTEN_EPEIE_Msk + | USBD_GINTEN_EPFIE_Msk + | USBD_GINTEN_EPGIE_Msk + | USBD_GINTEN_EPHIE_Msk + | USBD_GINTEN_EPIIE_Msk + | USBD_GINTEN_EPJIE_Msk + | USBD_GINTEN_EPKIE_Msk + | USBD_GINTEN_EPLIE_Msk); + + /* Enable BUS interrupt */ + USBD_ENABLE_BUS_INT(USBD_BUSINTEN_DMADONEIEN_Msk + | USBD_BUSINTEN_RESUMEIEN_Msk + | USBD_BUSINTEN_RSTIEN_Msk + | USBD_BUSINTEN_VBUSDETIEN_Msk); + /* Reset Address to 0 */ + USBD_SET_ADDR(0); + + /*****************************************************/ + /* Control endpoint */ + USBD_SetEpBufAddr(CEP, CEP_BUF_BASE, CEP_BUF_LEN); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk + | USBD_CEPINTEN_STSDONEIEN_Msk); + + _nu_ep_partition_set(1); +} + +static void NU_SetupStageCallback(nu_usbd_t *nu_udc) +{ + struct urequest setup_packet; + + /* Setup packet process */ + setup_packet.request_type = (uint8_t)(nu_udc->base->SETUP1_0 & 0xfful); + setup_packet.bRequest = (uint8_t)((nu_udc->base->SETUP1_0 >> 8) & 0xfful); + setup_packet.wValue = (uint16_t) nu_udc->base->SETUP3_2; + setup_packet.wIndex = (uint16_t) nu_udc->base->SETUP5_4; + setup_packet.wLength = (uint16_t) nu_udc->base->SETUP7_6; + + rt_usbd_ep0_setup_handler(&_rt_obj_udc, (struct urequest *)&setup_packet); +} + +__STATIC_INLINE void nu_udc_enable(void) +{ + USBD_ENABLE_USB(); +} + +__STATIC_INLINE void nu_udc_disable(void) +{ + int i; + + USBD_ENABLE_CEP_INT(0); + USBD_CLR_CEP_INT_FLAG(0xffff); + + USBD_SET_CEP_STATE(inpw(REG_USBD_CEPCTL) | USB_CEPCTL_FLUSH); + + for (i = 0; i < USBD_MAX_EP; i++) + USBD->EP[i].EPRSPCTL = USB_EP_RSPCTL_FLUSH | USB_EP_RSPCTL_TOGGLE; + + USBD_DISABLE_USB(); +} + + +static rt_err_t _ep_set_stall(rt_uint8_t address) +{ + + if (address & USB_EPNO_MASK) + { + USBD_SetEpStall(EPADR_SW2HW(address)); + } + else + { + /* Not support. Reply STALL. */ + USBD_SET_CEP_STATE(USBD_CEPCTL_STALLEN_Msk); + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPPKIF_Msk); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk); + } + return RT_EOK; +} + +static rt_err_t _ep_clear_stall(rt_uint8_t address) +{ + if (address & USB_EPNO_MASK) + { + USBD_ClearEpStall(EPADR_SW2HW(address)); + } + + return RT_EOK; +} + + +static rt_err_t _set_address(rt_uint8_t address) +{ + if (0 != address) + { + nu_usbd.address_tmp = address; + } + + return RT_EOK; +} + +static rt_err_t _set_config(rt_uint8_t address) +{ + return RT_EOK; +} + +static rt_err_t _ep_enable(uep_t ep) +{ + RT_ASSERT(ep != RT_NULL); + RT_ASSERT(ep->ep_desc != RT_NULL); + + USBD->EP[EPADR_SW2HW(ep->ep_desc->bEndpointAddress)].EPRSPCTL = USB_EP_RSPCTL_TOGGLE; + USBD->EP[EPADR_SW2HW(ep->ep_desc->bEndpointAddress)].EPCFG |= USB_EP_CFG_VALID; + + return RT_EOK; +} + +static rt_err_t _ep_disable(uep_t ep) +{ + RT_ASSERT(ep != RT_NULL); + RT_ASSERT(ep->ep_desc != RT_NULL); + USBD->EP[EPADR_SW2HW(ep->ep_desc->bEndpointAddress)].EPCFG &= ~USB_EP_CFG_VALID; + + return RT_EOK; +} + +static rt_err_t _ep0_send_status(void) +{ + /* Status Stage */ + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk + | USBD_CEPINTSTS_SETUPPKIF_Msk); + + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_STSDONEIEN_Msk); + + USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); + + return RT_EOK; +} + +__STATIC_INLINE void nu_buffer_cpy(rt_uint8_t address, void *buffer, rt_size_t size) +{ + rt_uint32_t i, cnt; + rt_uint32_t *_buf_word; + rt_uint8_t *_buf_byte; + + _buf_word = (rt_uint32_t *)buffer; + cnt = size >> 2; + _buf_byte = (rt_uint8_t *)((rt_uint8_t *)buffer + (cnt * 4)); + + if ((address & USB_EPNO_MASK)) //EPs + { + if (address & USB_DIR_IN) //IN + { + /* Non-control endpoint IN*/ + for (i = 0; i < cnt; i++) + { + USBD->EP[EPADR_SW2HW(address)].ep.EPDAT = _buf_word[i]; + } + + for (i = 0ul; i < (size % 4ul); i++) + USBD->EP[EPADR_SW2HW(address)].ep.EPDAT_BYTE = _buf_byte[i]; + } + else //OUT + { + for (i = 0; i < cnt; i++) + { + _buf_word[i] = USBD->EP[EPADR_SW2HW(address)].ep.EPDAT; + } + + for (i = 0ul; i < (size % 4ul); i++) + _buf_byte[i] = USBD->EP[EPADR_SW2HW(address)].ep.EPDAT_BYTE; + } + } + else //Control + { + if (address & USB_DIR_IN) //IN + { + for (i = 0; i < cnt; i++) + { + USBD->cep.CEPDAT = _buf_word[i]; + } + + for (i = 0ul; i < (size % 4ul); i++) + USBD->cep.CEPDAT_BYTE = _buf_byte[i]; + + } + else //OUT + { + for (i = 0; i < cnt; i++) + { + _buf_word[i] = USBD->cep.CEPDAT; + } + + for (i = 0ul; i < (size % 4ul); i++) + _buf_byte[i] = USBD->cep.CEPDAT_BYTE; + } + } +} + +static rt_size_t _ep_read(rt_uint8_t address, void *buffer) +{ + rt_size_t size = 0; + + RT_ASSERT(!(address & USB_DIR_IN)); + + if ((address & USB_EPNO_MASK)) + { + RT_ASSERT(buffer != RT_NULL); + size = USBD->EP[EPADR_SW2HW(address)].EPDATCNT & 0xffff; + nu_buffer_cpy(address, buffer, size); + } + else //control transfer + { + + size = USBD->CEPRXCNT & 0xffff; + if (size) + { + RT_ASSERT(_rt_obj_udc.stage == STAGE_DOUT); + nu_buffer_cpy(address, buffer, size); + } + + _ep0_send_status(); + } + + return size; +} + +static rt_size_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size) +{ + RT_ASSERT(!(address & USB_DIR_IN)); + + if ((address & USB_EPNO_MASK)) + { + USBD_ENABLE_EP_INT(EPADR_SW2HW(address), + USBD_EPINTEN_RXPKIEN_Msk); + } + else //control transfer + { + if (size) + { + RT_ASSERT(_rt_obj_udc.stage == STAGE_DOUT); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_OUTTKIEN_Msk); + } + else + { + + RT_ASSERT(_rt_obj_udc.stage == STAGE_STATUS_OUT); + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPPKIF_Msk + | USBD_CEPINTSTS_STSDONEIF_Msk); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk + | USBD_CEPINTEN_STSDONEIEN_Msk); + USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); + } + + } + + return size; +} + +static rt_size_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size) +{ + + RT_ASSERT((address & USB_DIR_IN)); + + if (!(address & USB_EPNO_MASK)) //control transfer + { + if (size) + { + nu_buffer_cpy(address, buffer, size); + USBD_START_CEP_IN(size); + } + else//zero length + { + USBD_SET_CEP_STATE(USB_CEPCTL_ZEROLEN); + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk + | USBD_CEPINTSTS_SETUPPKIF_Msk); + + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk + | USBD_CEPINTEN_STSDONEIEN_Msk); + } + + if (_rt_obj_udc.stage == STAGE_DIN) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_TXPKIF_Msk); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_TXPKIEN_Msk); + } + else if (_rt_obj_udc.stage == STAGE_DOUT) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_RXPKIF_Msk); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_RXPKIEN_Msk); + } + } + else + { + /* Non-control endpoint IN*/ + nu_buffer_cpy(address, buffer, size); + USBD->EP[EPADR_SW2HW(address)].EPRSPCTL = USB_EP_RSPCTL_SHORTTXEN; // packet end + USBD->EP[EPADR_SW2HW(address)].EPTXCNT = size; + + if ((USBD->EP[EPADR_SW2HW(address)].EPCFG & USBD_EPCFG_EPTYPE_Msk) == USB_EP_CFG_TYPE_INT) + { + USBD_ENABLE_EP_INT(EPADR_SW2HW(address), USBD_EPINTEN_INTKIEN_Msk); //for interrupt transfer timing + } + else + { + USBD_ENABLE_EP_INT(EPADR_SW2HW(address), USBD_EPINTEN_TXPKIEN_Msk); //for bulk transfer timing + } + } + + return size; +} + +static rt_err_t _suspend(void) +{ + return RT_EOK; +} + +static rt_err_t _wakeup(void) +{ + return RT_EOK; +} + +static void nu_usbd_isr(int vector, void *param) +{ + __IO rt_uint32_t IrqStL, IrqSt; + int i; + int IrqStAllEP; + + /* Igrone event if role is USBH*/ + if (nu_sys_usb0_role() != USB0_ID_DEVICE) return; + + IrqStL = USBD->GINTSTS & USBD->GINTEN; /* get interrupt status */ + + if (!IrqStL) return; + + /* USB interrupt */ + if (IrqStL & USBD_GINTSTS_USBIF_Msk) + { + IrqSt = USBD->BUSINTSTS & USBD->BUSINTEN; + + if (IrqSt & USBD_BUSINTSTS_SOFIF_Msk) + { + USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_SOFIF_Msk); + rt_usbd_sof_handler(&_rt_obj_udc); + } + if (IrqSt & USBD_BUSINTSTS_RSTIF_Msk) + { + /* Reset USB device address */ + USBD_SET_ADDR(0ul); + + USBD_ResetDMA(); + for (i = 0; i < USBD_MAX_EP; i++) + USBD->EP[i].EPRSPCTL = USBD_EPRSPCTL_FLUSH_Msk; + + if (USBD->OPER & 0x04) /* high speed */ + { + LOG_I("-High Speed-"); + _nu_ep_partition_set(1); + } + else /* full speed */ + { + LOG_I("-Full Speed-"); + _nu_ep_partition_set(0); + } + + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk); + USBD_ENABLE_BUS_INT(USBD_BUSINTEN_RSTIEN_Msk + | USBD_BUSINTEN_RESUMEIEN_Msk + | USBD_BUSINTEN_SUSPENDIEN_Msk + | USBD_BUSINTEN_VBUSDETIEN_Msk); + USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_RSTIF_Msk); + USBD_CLR_CEP_INT_FLAG(0x1ffc); + + for (i = 0ul; i < USBD_MAX_EP; i++) + { + if ((USBD->EP[i].EPCFG & 0x1ul) == 0x1ul) + { + USBD->EP[i].EPRSPCTL = USB_EP_RSPCTL_TOGGLE; + } + } + rt_usbd_reset_handler(&_rt_obj_udc); + USBD_ENABLE_USB(); + } + + if (IrqSt & USBD_BUSINTSTS_RESUMEIF_Msk) + { + LOG_I("-Resume-"); + USBD_ENABLE_BUS_INT(USBD_BUSINTEN_RSTIEN_Msk | USBD_BUSINTEN_SUSPENDIEN_Msk); + USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_RESUMEIF_Msk); + } + + if (IrqSt & USBD_BUSINTSTS_SUSPENDIF_Msk) + { + LOG_I("-Suspend-"); + USBD_ENABLE_BUS_INT(USBD_BUSINTEN_RSTIEN_Msk | USBD_BUSINTEN_RESUMEIEN_Msk | USBD_BUSINTEN_VBUSDETIEN_Msk); + USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_SUSPENDIF_Msk); + } + + if (IrqSt & USBD_BUSINTSTS_HISPDIF_Msk) + { + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk); + USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_HISPDIF_Msk); + } + + if (IrqSt & USBD_BUSINTSTS_DMADONEIF_Msk) + { + USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_DMADONEIF_Msk); + + if (!(USBD->DMACTL & USBD_DMACTL_DMARD_Msk)) + { + USBD_ENABLE_EP_INT(EPD, USBD_EPINTEN_RXPKIEN_Msk); + } + } + + if (IrqSt & USBD_BUSINTSTS_PHYCLKVLDIF_Msk) + { + USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_PHYCLKVLDIF_Msk); + } + + if (IrqSt & USBD_BUSINTSTS_VBUSDETIF_Msk) + { + if (USBD_IS_ATTACHED()) + { + if (!nu_usbd.plugging_status) + { + LOG_I("PLUG IN"); + /* USB Plug In */ + nu_udc_enable(); + rt_usbd_connect_handler(&_rt_obj_udc); + nu_usbd.plugging_status = 1; + } + } + else + { + if (nu_usbd.plugging_status) + { + LOG_I("Un-Plug"); + /* USB Un-plug */ + nu_udc_disable(); + rt_usbd_disconnect_handler(&_rt_obj_udc); + nu_usbd.plugging_status = 0; + } + } + USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_VBUSDETIF_Msk); + } + } //if (IrqStL & USBD_GINTSTS_USBIF_Msk) + + /* Control Transfer */ + if (IrqStL & USBD_GINTSTS_CEPIF_Msk) + { + IrqSt = USBD->CEPINTSTS & USBD->CEPINTEN; + + if (IrqSt & USBD_CEPINTSTS_SETUPTKIF_Msk) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPTKIF_Msk); + return; + } + + if (IrqSt & USBD_CEPINTSTS_SETUPPKIF_Msk) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPPKIF_Msk); + NU_SetupStageCallback(&nu_usbd); + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk + | USBD_CEPINTSTS_RXPKIF_Msk + | USBD_CEPINTSTS_STSDONEIF_Msk); + return; + } + + if (IrqSt & USBD_CEPINTSTS_OUTTKIF_Msk) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_OUTTKIF_Msk); + rt_usbd_ep0_out_handler(&_rt_obj_udc, 0); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_RXPKIEN_Msk); + return; + } + + if (IrqSt & USBD_CEPINTSTS_INTKIF_Msk) + { + USBD_ENABLE_CEP_INT(0); + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk); + rt_usbd_ep0_in_handler(&_rt_obj_udc); + return; + } + + if (IrqSt & USBD_CEPINTSTS_PINGIF_Msk) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_PINGIF_Msk); + return; + } + + if (IrqSt & USBD_CEPINTSTS_TXPKIF_Msk) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_TXPKIF_Msk + | USBD_CEPINTSTS_SETUPPKIF_Msk + | USBD_CEPINTSTS_STSDONEIF_Msk); + + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_INTKIEN_Msk + | USBD_CEPINTEN_SETUPPKIEN_Msk + | USBD_CEPINTEN_STSDONEIEN_Msk); + + USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); + return; + } + + if (IrqSt & USBD_CEPINTSTS_RXPKIF_Msk) + { + + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPPKIF_Msk + | USBD_CEPINTSTS_STSDONEIF_Msk + | USBD_CEPINTSTS_RXPKIF_Msk); + USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk + | USBD_CEPINTEN_STSDONEIEN_Msk + | USBD_CEPINTEN_RXPKIEN_Msk); + return; + } + + if (IrqSt & USBD_CEPINTSTS_NAKIF_Msk) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_NAKIF_Msk); + return; + } + + if (IrqSt & USBD_CEPINTSTS_STALLIF_Msk) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STALLIF_Msk); + return; + } + + if (IrqSt & USBD_CEPINTSTS_ERRIF_Msk) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_ERRIF_Msk); + return; + } + + if (IrqSt & USBD_CEPINTSTS_STSDONEIF_Msk) + { + + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk | USBD_CEPINTSTS_SETUPPKIF_Msk); + USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk); + + if ((USBD_GET_ADDR() == 0) + && ((uint8_t)((nu_usbd.base->SETUP1_0 >> 8) & 0xfful) == SET_ADDRESS)) + { + USBD_SET_ADDR(nu_usbd.address_tmp); + LOG_I("SET ADDR: 0x%02x", nu_usbd.address_tmp); + nu_usbd.address_tmp = 0; + + } + return; + } + + if (IrqSt & USBD_CEPINTSTS_BUFFULLIF_Msk) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_BUFFULLIF_Msk); + return; + } + + if (IrqSt & USBD_CEPINTSTS_BUFEMPTYIF_Msk) + { + USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_BUFEMPTYIF_Msk); + return; + } + + } //if (IrqStL & USBD_GINTSTS_CEPIF_Msk) + + // For End-points + IrqStAllEP = (IrqStL >> USBD_GINTSTS_EPAIF_Pos) & ((1 << USBD_MAX_EP) - 1); + + // Find the position of first '1' in allch_sts. + while ((i = nu_ctz(IrqStAllEP)) != 32) + { + IrqSt = USBD->EP[i].EPINTSTS & USBD->EP[i].EPINTEN; + + if (_ep_pool[i + 1].dir == USB_DIR_IN) + USBD_ENABLE_EP_INT(i, 0); + + USBD_CLR_EP_INT_FLAG(i, IrqSt); + + rt_usbd_ep_in_handler(&_rt_obj_udc, _ep_pool[i + 1].dir | EPADR_HW2SW(i), 0); + + IrqStAllEP &= ~(1 << i); + } +} + +static rt_err_t _init(rt_device_t device) +{ + nu_sys_ipclk_enable(nu_usbd.clkidx); + + nu_sys_ip_reset(nu_usbd.rstidx); + + rt_hw_us_delay(1000); + + /* USBD Open */ + USBD_ENABLE_USB(); + + while (1) + { + USBD->EP[EPA].EPMPS = 0x20ul; + if (USBD->EP[EPA].EPMPS == 0x20ul) + { + break; + } + } + + /* Force SE0 */ + USBD_SET_SE0(); + + _nu_ep_partition(); + +#if ENABLE_FULL_SPEED_MODE_ONLY + USBD->OPER &= ~USBD_OPER_HISPDEN_Msk; +#else + USBD->OPER |= USBD_OPER_HISPDEN_Msk; +#endif + + /* Install USBD interrupt */ + rt_hw_interrupt_install(nu_usbd.irqn, nu_usbd_isr, &nu_usbd, nu_usbd.name); + rt_hw_interrupt_set_priority(nu_usbd.irqn, IRQ_LEVEL_1); + + /* Enable USBD interrupt */ + rt_hw_interrupt_umask(nu_usbd.irqn); + + /* Start transaction */ + USBD_CLR_SE0(); + + /* Get currect cable status */ + nu_usbd.plugging_status = USBD_IS_ATTACHED() >> USBD_PHYCTL_VBUSDET_Pos; + + return RT_EOK; +} + +const static struct udcd_ops _udc_ops = +{ + _set_address, + _set_config, + _ep_set_stall, + _ep_clear_stall, + _ep_enable, + _ep_disable, + _ep_read_prepare, + _ep_read, + _ep_write, + _ep0_send_status, + _suspend, + _wakeup, +}; + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops _ops = +{ + _init, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, +}; +#endif + +int nu_usbd_register(void) +{ + rt_err_t result = RT_EOK; + + rt_memset((void *)&_rt_obj_udc, 0, sizeof(struct udcd)); + _rt_obj_udc.parent.type = RT_Device_Class_USBDevice; + +#ifdef RT_USING_DEVICE_OPS + _rt_obj_udc.parent.ops = &_ops; +#else + _rt_obj_udc.parent.init = _init; +#endif + + _rt_obj_udc.parent.user_data = &nu_usbd; + _rt_obj_udc.ops = &_udc_ops; + + /* Register endpoint information */ + _rt_obj_udc.ep_pool = _ep_pool; + _rt_obj_udc.ep0.id = &_ep_pool[0]; + +#if ENABLE_FULL_SPEED_MODE_ONLY + _rt_obj_udc.device_is_hs = RT_FALSE; /* Enable Full-speed only */ +#else + _rt_obj_udc.device_is_hs = RT_TRUE; /* Support Hi-Speed */ +#endif + + result = rt_device_register((rt_device_t)&_rt_obj_udc, nu_usbd.name, 0); + RT_ASSERT(result == RT_EOK); + + return rt_usb_device_init(); +} +INIT_DEVICE_EXPORT(nu_usbd_register); +#endif diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c new file mode 100644 index 0000000000..cd6f837c88 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c @@ -0,0 +1,893 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-30 Wayne First version +* +******************************************************************************/ +#include + +#if defined(BSP_USING_USBH) + +#include +#include +#include "NuMicro.h" + +#include "usb.h" +#include "usbh_lib.h" + +#if !defined(NU_USBHOST_HUB_POLLING_INTERVAL) + #define NU_USBHOST_HUB_POLLING_INTERVAL (100) +#endif + +#define NU_MAX_USBH_PORT 2 //2* USB2.0 port +#define NU_MAX_USBH_PIPE 16 +#define NU_USBH_THREAD_STACK_SIZE 2048 + +#define NU_MAX_USBH_HUB_PORT_DEV USB_HUB_PORT_NUM + +/* Private typedef --------------------------------------------------------------*/ +typedef struct nu_port_dev +{ + rt_bool_t bRHParent; + UDEV_T *pUDev; + EP_INFO_T *apsEPInfo[NU_MAX_USBH_PIPE]; + struct urequest asSetupReq[NU_MAX_USBH_PIPE]; + struct rt_completion utr_completion; + int port_num; + rt_bool_t bEnumDone; +#if defined(BSP_USING_MMU) + void *asPipePktBuf[NU_MAX_USBH_PIPE]; +#endif +} S_NU_PORT_DEV; + + +typedef struct nu_port_ctrl +{ + S_NU_PORT_DEV sRHPortDev; + S_NU_PORT_DEV asHubPortDev[NU_MAX_USBH_HUB_PORT_DEV]; +} S_NU_RH_PORT_CTRL; + + +struct nu_usbh_dev +{ + struct uhcd uhcd; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + rt_thread_t polling_thread; + S_NU_RH_PORT_CTRL asPortCtrl[NU_MAX_USBH_PORT]; +}; + +/* Private variables ------------------------------------------------------------*/ +static struct nu_usbh_dev s_sUSBHDev = +{ + .rstidx = USBHRST, + .clkidx = USBHCKEN, +}; + +static S_NU_RH_PORT_CTRL * +GetRHPortControlFromPipe( + upipe_t pipe) +{ + uinst_t inst; + int port; + if (pipe->inst->parent_hub->is_roothub) + { + //case: device ---> root hub + inst = pipe->inst; + port = inst->port; + } + else + { + //case: device ---> hub ---> root hub + inst = pipe->inst->parent_hub->self; + port = inst->port; + } + + if (port > NU_MAX_USBH_PORT) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_open_pipe ERROR: port index over NU_MAX_USBH_PORT\n")); + return RT_NULL; + } + + return &s_sUSBHDev.asPortCtrl[port - 1];; +} + +static S_NU_PORT_DEV * +GetPortDevFromPipe( + upipe_t pipe) +{ + S_NU_RH_PORT_CTRL *psRHPortCtrl = GetRHPortControlFromPipe(pipe); + int i; + + if (psRHPortCtrl == RT_NULL) + return RT_NULL; + + if (pipe->inst->parent_hub->is_roothub) + { + //case: device ---> root hub + return &psRHPortCtrl->sRHPortDev; + } + + //case: device ---> hub ---> root hub + for (i = 0 ; i < NU_MAX_USBH_HUB_PORT_DEV; i ++) + { + if (psRHPortCtrl->asHubPortDev[i].port_num == pipe->inst->port) + break; + } + + if (i >= NU_MAX_USBH_HUB_PORT_DEV) + return RT_NULL; + + return &psRHPortCtrl->asHubPortDev[i]; +} + +static rt_err_t nu_reset_port(rt_uint8_t port) +{ + S_NU_RH_PORT_CTRL *psPortCtrl; + + if (port > NU_MAX_USBH_PORT) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("%s ERROR: port index over NU_MAX_USBH_PORT\n", __func__)); + return RT_EIO; + } + + psPortCtrl = &s_sUSBHDev.asPortCtrl[port - 1]; + if (psPortCtrl->sRHPortDev.pUDev == NULL) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("%s ERROR: udev not found\n", __func__)); + return RT_EIO; + } + + usbh_reset_port(psPortCtrl->sRHPortDev.pUDev); + + return RT_EOK; +} + +static EP_INFO_T *GetFreePipe( + S_NU_RH_PORT_CTRL *psPortCtrl, + S_NU_PORT_DEV *psPortDev, + rt_uint8_t *pu8PipeIndex) +{ + if (psPortCtrl != NULL) + { + int i; + /* Find free Pipe */ + for (i = 0; i < NU_MAX_USBH_PIPE; i ++) + { + if (psPortDev->apsEPInfo[i] == NULL) + break; + } + + if (i < NU_MAX_USBH_PIPE) + { + EP_INFO_T *psEPInfo = rt_malloc(sizeof(EP_INFO_T)); + if (psEPInfo != RT_NULL) + { + psPortDev->apsEPInfo[i] = psEPInfo; + *pu8PipeIndex = i; + return psEPInfo; + } + } + } + return RT_NULL; +} + +static void FreePipe( + S_NU_RH_PORT_CTRL *psPortCtrl, + S_NU_PORT_DEV *psPortDev, + rt_uint8_t u8PipeIndex) +{ + if ((psPortCtrl != RT_NULL) && + (u8PipeIndex < NU_MAX_USBH_PIPE) && + (psPortDev->apsEPInfo[u8PipeIndex] != RT_NULL)) + { + rt_free(psPortDev->apsEPInfo[u8PipeIndex]); + psPortDev->apsEPInfo[u8PipeIndex] = RT_NULL; + } +} + +static S_NU_PORT_DEV * +AllocateNewUDev( + S_NU_RH_PORT_CTRL *psRHPortCtrl) +{ + if (psRHPortCtrl != RT_NULL) + { + int i; + /* Find free Dev */ + for (i = 0 ; i < NU_MAX_USBH_HUB_PORT_DEV; i ++) + { + if (psRHPortCtrl->asHubPortDev[i].pUDev == NULL) + break; + } + + if (i < NU_MAX_USBH_HUB_PORT_DEV) + { + psRHPortCtrl->asHubPortDev[i].pUDev = alloc_device(); + if (psRHPortCtrl->asHubPortDev[i].pUDev == NULL) + { + return RT_NULL; + } + else + { + return &psRHPortCtrl->asHubPortDev[i]; + } + } + } + return RT_NULL; +} + +static rt_err_t nu_open_pipe(upipe_t pipe) +{ + S_NU_RH_PORT_CTRL *psPortCtrl; + S_NU_PORT_DEV *psPortDev; + + psPortCtrl = GetRHPortControlFromPipe(pipe); + if (psPortCtrl == RT_NULL) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("%s ERROR: RHPort not found\n", __func__)); + goto exit_nu_open_pipe; + } + + if (psPortCtrl->sRHPortDev.pUDev == NULL) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("%s ERROR: udev not found\n", __func__)); + goto exit_nu_open_pipe; + } + + psPortDev = GetPortDevFromPipe(pipe); + + if ((psPortDev == NULL) || (psPortDev->pUDev == NULL)) + { + //allocate new dev for hub device + psPortDev = AllocateNewUDev(psPortCtrl); + + if (psPortDev == RT_NULL) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_open_pipe ERROR: udev allocate failed\n")); + goto exit_nu_open_pipe; + } + + if (pipe->inst->speed) + { + psPortDev->pUDev->speed = SPEED_FULL; + } + else + { + psPortDev->pUDev->speed = SPEED_HIGH; + } + + psPortDev->pUDev->parent = NULL; + psPortDev->pUDev->hc_driver = psPortCtrl->sRHPortDev.pUDev->hc_driver; + psPortDev->port_num = pipe->inst->port; + psPortDev->pUDev->port_num = pipe->inst->port; + psPortDev->bEnumDone = FALSE; + } + + //For ep0 control transfer + if ((pipe->ep.bEndpointAddress & 0x7F) == 0) + { + pipe->pipe_index = 0; + } + else + { + int pksz; + EP_INFO_T *psEPInfo = GetFreePipe(psPortCtrl, psPortDev, &pipe->pipe_index); + if (psEPInfo == RT_NULL) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("%s ERROR: get free pipe failed\n", __func__)); + goto exit_nu_open_pipe; + } + + psEPInfo->bEndpointAddress = pipe->ep.bEndpointAddress; + psEPInfo->bmAttributes = pipe->ep.bmAttributes; + + pksz = pipe->ep.wMaxPacketSize; + pksz = (pksz & 0x07ff) * (1 + ((pksz >> 11) & 3)); + psEPInfo->wMaxPacketSize = pksz; + + psEPInfo->bInterval = pipe->ep.bInterval; + psEPInfo->hw_pipe = NULL; + psEPInfo->bToggle = 0; + } + +#if defined(BSP_USING_MMU) + if (!psPortDev->asPipePktBuf[pipe->pipe_index]) + { + psPortDev->asPipePktBuf[pipe->pipe_index] = rt_malloc_align(512ul, CACHE_LINE_SIZE); + RT_ASSERT(psPortDev->asPipePktBuf[pipe->pipe_index] != RT_NULL); + } +#endif + + return RT_EOK; + +exit_nu_open_pipe: + + return -RT_ERROR; +} + +static rt_err_t nu_close_pipe(upipe_t pipe) +{ + S_NU_RH_PORT_CTRL *psPortCtrl; + S_NU_PORT_DEV *psPortDev; + + psPortCtrl = GetRHPortControlFromPipe(pipe); + if (psPortCtrl == RT_NULL) + { + return RT_EIO; + } + + psPortDev = GetPortDevFromPipe(pipe); + + //For ep0 control transfer + if ((pipe->ep.bEndpointAddress & 0x7F) == 0) + { + if ((psPortDev) && (psPortDev->bRHParent == FALSE) && (psPortDev->bEnumDone == TRUE)) + { + if (psPortDev->pUDev) + { + int i; + for (i = 0; i < NU_MAX_USBH_PIPE; i++) + { + if (psPortDev->apsEPInfo[i] != NULL) + { + usbh_quit_xfer(psPortDev->pUDev, psPortDev->apsEPInfo[i]); + } + } + + free_device(psPortDev->pUDev); + psPortDev->pUDev = NULL; + } + } + } + + if (psPortDev != NULL) + { +#if defined(BSP_USING_MMU) + if (psPortDev->asPipePktBuf[pipe->pipe_index]) + { + rt_free_align(psPortDev->asPipePktBuf[pipe->pipe_index]); + psPortDev->asPipePktBuf[pipe->pipe_index] = RT_NULL; + } +#endif + + FreePipe(psPortCtrl, psPortDev, pipe->pipe_index); + } + return RT_EOK; +} + +static int nu_ctrl_xfer( + S_NU_PORT_DEV *psPortDev, + struct urequest *psSetup, + void *buffer, + int timeouts) +{ + uint32_t xfer_len = 0; + int ret; + + ret = usbh_ctrl_xfer(psPortDev->pUDev, psSetup->request_type, psSetup->bRequest, psSetup->wValue, psSetup->wIndex, psSetup->wLength, buffer, &xfer_len, timeouts * 10); + if (ret < 0) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_ctrl_xfer ERROR: xfer failed %d\n", ret)); + return ret; + } + + if (xfer_len != psSetup->wLength) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_ctrl_xfer ERROR: xfer length %d %d\n", psSetup->wLength, xfer_len)); + } + + if ((psSetup->bRequest == USB_REQ_SET_ADDRESS) && ((psSetup->request_type & 0x60) == REQ_TYPE_STD_DEV)) + psPortDev->pUDev->dev_num = psSetup->wValue; + + if ((psSetup->bRequest == USB_REQ_SET_CONFIGURATION) && ((psSetup->request_type & 0x60) == REQ_TYPE_STD_DEV)) + { + psPortDev->pUDev->cur_conf = psSetup->wValue; + psPortDev->bEnumDone = TRUE; + } + + return xfer_len; +} + +static int nu_bulk_xfer( + S_NU_PORT_DEV *psPortDev, + UTR_T *psUTR, + int timeouts) +{ + int ret; + + ret = usbh_bulk_xfer(psUTR); + + if (ret < 0) + return ret; + + //wait transfer done + rt_completion_wait(&(psPortDev->utr_completion), timeouts); + return 0; +} + +static int nu_int_xfer( + upipe_t pipe, + S_NU_PORT_DEV *psPortDev, + UTR_T *psUTR, + int timeouts) +{ + int ret; + int retry = 3; + + while (retry > 0) + { + ret = usbh_int_xfer(psUTR); + if (ret == 0) + break; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_int_xfer ERROR: failed to submit interrupt request\n")); + rt_thread_delay((pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) > 0 ? (pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) : 1); + retry --; + } + + if (ret < 0) + return ret; + + return 0; +} + +static void xfer_done_cb(UTR_T *psUTR) +{ + S_NU_PORT_DEV *psPortDev = (S_NU_PORT_DEV *)psUTR->context; + + //transfer done, signal utr_completion + rt_completion_done(&(psPortDev->utr_completion)); +} + +static void int_xfer_done_cb(UTR_T *psUTR) +{ + upipe_t pipe = (upipe_t)psUTR->context; + + if (psUTR->status != 0) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("Interrupt xfer failed %d\n", psUTR->status)); + goto exit_int_xfer_done_cb; + } + + if (pipe->callback != RT_NULL) + { + struct uhost_msg msg; + msg.type = USB_MSG_CALLBACK; + msg.content.cb.function = pipe->callback; + msg.content.cb.context = pipe; + rt_usbh_event_signal(&msg); + } + +exit_int_xfer_done_cb: + + free_utr(psUTR); +} + +static int nu_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts) +{ + S_NU_RH_PORT_CTRL *psPortCtrl; + S_NU_PORT_DEV *psPortDev; + UTR_T *psUTR = NULL; + int i32XferLen = -1; + + void *buffer_nonch = buffer; + + psPortCtrl = GetRHPortControlFromPipe(pipe); + if (psPortCtrl == RT_NULL) + { + goto exit_nu_pipe_xfer; + } + + psPortDev = GetPortDevFromPipe(pipe); + if (psPortDev->pUDev == NULL) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: udev not found\n")); + goto exit_nu_pipe_xfer; + } + +#if defined(BSP_USING_MMU) + if (buffer_nonch && nbytes) + { + buffer_nonch = psPortDev->asPipePktBuf[pipe->pipe_index]; + rt_memcpy(buffer_nonch, buffer, nbytes); + mmu_clean_invalidated_dcache((uint32_t)buffer_nonch, nbytes); + } +#endif + + //ctrl xfer + if (pipe->ep.bmAttributes == USB_EP_ATTR_CONTROL) + { + int ret; + if (token == USBH_PID_SETUP) + { + struct urequest *psSetup = (struct urequest *)buffer_nonch; + RT_ASSERT(buffer_nonch != RT_NULL); + + /* Read data from USB device. */ + if (psSetup->request_type & USB_REQ_TYPE_DIR_IN) + { + //Store setup request + rt_memcpy(&psPortCtrl->asHubPortDev->asSetupReq[pipe->pipe_index], psSetup, sizeof(struct urequest)); + } + else + { + /* Write data to USB device. */ + //Trigger USBHostLib Ctril_Xfer + ret = nu_ctrl_xfer(psPortDev, psSetup, NULL, timeouts); + if (ret != psSetup->wLength) + goto exit_nu_pipe_xfer; + } + } + else + { + //token == USBH_PID_DATA + if (buffer_nonch && ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN)) + { + /* Read data from USB device. */ + //Trigger USBHostLib Ctril_Xfer + ret = nu_ctrl_xfer(psPortDev, &psPortCtrl->asHubPortDev->asSetupReq[pipe->pipe_index], buffer_nonch, timeouts); + if (ret != nbytes) + goto exit_nu_pipe_xfer; + } + else + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("%d == USBH_PID_DATA, nil buf-%d \n", token, nbytes)); + } + + } //else + i32XferLen = nbytes; + goto exit_nu_pipe_xfer; + } // if ( pipe->ep.bmAttributes == USB_EP_ATTR_CONTROL ) + else + { + + psUTR = alloc_utr(psPortDev->pUDev); + + if (!psUTR) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: unable alloc UTR\n")); + goto exit_nu_pipe_xfer; + } + + psUTR->ep = psPortDev->apsEPInfo[pipe->pipe_index]; + psUTR->buff = buffer_nonch; + psUTR->data_len = nbytes; + psUTR->xfer_len = 0; + psUTR->func = xfer_done_cb; + psUTR->context = psPortDev; + psUTR->bIsTransferDone = 0; + psUTR->status = 0; + + //others xfer + rt_completion_init(&(psPortDev->utr_completion)); + + if (pipe->ep.bmAttributes == USB_EP_ATTR_BULK) + { + if (nu_bulk_xfer(psPortDev, psUTR, timeouts) < 0) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: bulk transfer failed\n")); + goto exit_nu_pipe_xfer; + } + } + else if (pipe->ep.bmAttributes == USB_EP_ATTR_INT) + { + psUTR->func = int_xfer_done_cb; + psUTR->context = pipe; + + if (nu_int_xfer(pipe, psPortDev, psUTR, timeouts) < 0) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: int transfer failed\n")); + //goto exit_nu_pipe_xfer; + } + else + { + i32XferLen = nbytes; + } + return i32XferLen; + } + else if (pipe->ep.bmAttributes == USB_EP_ATTR_ISOC) + { + //TODO: ISO transfer + RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: isoc transfer not support\n")); + goto exit_nu_pipe_xfer; + } + + } //else + + if (psUTR->bIsTransferDone == 0) + { + //Timeout + RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: timeout\n")); + pipe->status = UPIPE_STATUS_ERROR; + usbh_quit_utr(psUTR); + } + else + { + // Transfer Done. Get status + if (psUTR->status == 0) + { + pipe->status = UPIPE_STATUS_OK; + } + else if (psUTR->status == USBH_ERR_STALL) + { + pipe->status = UPIPE_STATUS_STALL; + } + else + { + pipe->status = UPIPE_STATUS_ERROR; + } + } + + i32XferLen = psUTR->xfer_len; + + //Call callback + if (pipe->callback != RT_NULL) + { + struct uhost_msg msg; + msg.type = USB_MSG_CALLBACK; + msg.content.cb.function = pipe->callback; + msg.content.cb.context = pipe->user_data; + rt_usbh_event_signal(&msg); + } + + if (pipe->status != UPIPE_STATUS_OK) + goto exit_nu_pipe_xfer; + +exit_nu_pipe_xfer: + +#if defined(BSP_USING_MMU) + if ((nbytes) && + (buffer_nonch != buffer)) + { + mmu_invalidate_dcache((uint32_t)buffer_nonch, nbytes); + rt_memcpy(buffer, buffer_nonch, nbytes); + } +#endif + + if (psUTR) + free_utr(psUTR); + + return i32XferLen; +} + +/* Polling USB root hub status task */ +static void nu_usbh_rh_thread_entry(void *parameter) +{ + while (1) + { + usbh_polling_root_hubs(); + rt_thread_mdelay(NU_USBHOST_HUB_POLLING_INTERVAL); + } +} + +static void nu_hcd_connect_callback( + struct udev_t *udev, + int param) +{ + int i; + int port_index; + S_NU_RH_PORT_CTRL *psPortCtrl; + + /* Igrone event if role is USBD*/ + if (nu_sys_usb0_role() == USB0_ID_HOST) + { + SYS_UnlockReg(); + outpw(REG_SYS_MISCFCR, (inpw(REG_SYS_MISCFCR) | (1 << 11))); /* Set USRHDSEN as 1; USB host/device role selection decided by USBID (SYS_PWRON[16]) */ + outpw(REG_SYS_PWRON, (inpw(REG_SYS_PWRON) | (1 << 16))); /* Set USB port 0 used for Host */ + SYS_LockReg(); + } + + for (i = 0; i < NU_MAX_USBH_PORT; i++) + { + psPortCtrl = &s_sUSBHDev.asPortCtrl[i]; + if (psPortCtrl->sRHPortDev.pUDev == NULL) + break; + } + + if (i >= NU_MAX_USBH_PORT) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("ERROR: port connect slot is full\n")); + return; + } + + port_index = i + 1; + psPortCtrl->sRHPortDev.pUDev = udev; + psPortCtrl->sRHPortDev.bRHParent = TRUE; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb connected\n")); + + if (udev->speed == SPEED_HIGH) + rt_usbh_root_hub_connect_handler(&s_sUSBHDev.uhcd, port_index, RT_TRUE); + else + rt_usbh_root_hub_connect_handler(&s_sUSBHDev.uhcd, port_index, RT_FALSE); +} + +static void nu_hcd_disconnect_callback( + struct udev_t *udev, + int param) +{ + int i; + int port_index; + S_NU_RH_PORT_CTRL *psPortCtrl; + + for (i = 0; i < NU_MAX_USBH_PORT; i++) + { + psPortCtrl = &s_sUSBHDev.asPortCtrl[i]; + if (psPortCtrl->sRHPortDev.pUDev == udev) + break; + } + + if (i >= NU_MAX_USBH_PORT) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("ERROR: udev not found\n")); + return; + } + + port_index = i + 1; + + for (i = 0; i < NU_MAX_USBH_PIPE; i++) + { + if (psPortCtrl->sRHPortDev.apsEPInfo[i] != NULL) + { + usbh_quit_xfer(psPortCtrl->sRHPortDev.pUDev, psPortCtrl->sRHPortDev.apsEPInfo[i]); + } + } + + psPortCtrl->sRHPortDev.pUDev = NULL; + + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb disconnect\n")); + + rt_usbh_root_hub_disconnect_handler(&s_sUSBHDev.uhcd, port_index); + + if (nu_sys_usb0_role() != USB0_ID_HOST) + { + SYS_UnlockReg(); + outpw(REG_SYS_MISCFCR, (inpw(REG_SYS_MISCFCR) & (~(1 << 11)))); + outpw(REG_SYS_PWRON, (inpw(REG_SYS_PWRON) & (~(1 << 16)))); + SYS_LockReg(); + } + +} + + +/* USB host operations -----------------------------------------------------------*/ +static struct uhcd_ops nu_uhcd_ops = +{ + nu_reset_port, + nu_pipe_xfer, + nu_open_pipe, + nu_close_pipe, +}; + +static rt_err_t nu_hcd_init(rt_device_t device) +{ + struct nu_usbh_dev *pNuUSBHDev = (struct nu_usbh_dev *)device; + usbh_core_init(); + + //install connect/disconnect callback + usbh_install_conn_callback(nu_hcd_connect_callback, nu_hcd_disconnect_callback); + usbh_polling_root_hubs(); + + //create thread for polling usbh port status + /* create usb hub thread */ + pNuUSBHDev->polling_thread = rt_thread_create("usbh_drv", nu_usbh_rh_thread_entry, RT_NULL, + NU_USBH_THREAD_STACK_SIZE, 8, 20); + RT_ASSERT(pNuUSBHDev->polling_thread != RT_NULL); + + /* startup usb host thread */ + rt_thread_startup(pNuUSBHDev->polling_thread); + + return RT_EOK; +} + +/* global function for USB host library -----------------------------*/ +uint32_t usbh_get_ticks(void) +{ + return rt_tick_get(); +} + +void usbh_delay_ms(int msec) +{ + rt_thread_mdelay(msec); +} + +uint32_t usbh_tick_from_millisecond(uint32_t msec) +{ + return rt_tick_from_millisecond(msec); +} + +#if defined(RT_USING_PM) + +/* device pm suspend() entry. */ +static int usbhost_pm_suspend(const struct rt_device *device, rt_uint8_t mode) +{ + rt_err_t result; + + struct nu_usbh_dev *pNuUSBHDev = (struct nu_usbh_dev *)device; + + RT_ASSERT(pNuUSBHDev != RT_NULL); + switch (mode) + { + case PM_SLEEP_MODE_LIGHT: + case PM_SLEEP_MODE_DEEP: + + pNuUSBHDev->polling_thread->stat = RT_THREAD_READY; + result = rt_thread_suspend(pNuUSBHDev->polling_thread); + RT_ASSERT(result == RT_EOK); + + break; + + default: + break; + } + + return (int)RT_EOK; +} + +/* device pm resume() entry. */ +static void usbhost_pm_resume(const struct rt_device *device, rt_uint8_t mode) +{ + rt_err_t result; + struct nu_usbh_dev *pNuUSBHDev = (struct nu_usbh_dev *)device; + RT_ASSERT(pNuUSBHDev != RT_NULL); + + switch (mode) + { + case PM_SLEEP_MODE_LIGHT: + case PM_SLEEP_MODE_DEEP: + result = rt_thread_resume(pNuUSBHDev->polling_thread); + RT_ASSERT(result == RT_EOK); + break; + + default: + break; + } +} + +static struct rt_device_pm_ops device_pm_ops = +{ + .suspend = usbhost_pm_suspend, + .resume = usbhost_pm_resume, + .frequency_change = RT_NULL +}; +#endif + +int nu_usbh_register(void) +{ + rt_err_t res; + uhcd_t psUHCD; + + psUHCD = (uhcd_t)&s_sUSBHDev.uhcd; + + psUHCD->parent.type = RT_Device_Class_USBHost; + psUHCD->parent.init = nu_hcd_init; + psUHCD->parent.user_data = &s_sUSBHDev; + + psUHCD->ops = &nu_uhcd_ops; + psUHCD->num_ports = NU_MAX_USBH_PORT; + + res = rt_device_register(&psUHCD->parent, "usbh", RT_DEVICE_FLAG_DEACTIVATE); + RT_ASSERT(res == RT_EOK); + + nu_sys_ipclk_enable(s_sUSBHDev.clkidx); + nu_sys_ip_reset(s_sUSBHDev.rstidx); + + + /*initialize the usb host function */ + res = rt_usb_host_init(); + RT_ASSERT(res == RT_EOK); + +#if defined(RT_USING_PM) + rt_pm_device_register(&psUHCD->parent, &device_pm_ops); +#endif + + return 0; +} +INIT_DEVICE_EXPORT(nu_usbh_register); + +#endif diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c new file mode 100644 index 0000000000..50c45ee915 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c @@ -0,0 +1,352 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-4-13 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_VPOST) + +#include +#include +#include +#include "NuMicro.h" +#include + +/* Private typedef --------------------------------------------------------------*/ + +typedef enum +{ + eVpost_LCD, +#if defined(BSP_USING_VPOST_OSD) + eVpost_OSD, +#endif + eVpost_Cnt +} E_VPOST_LAYER; + +struct nu_vpost +{ + struct rt_device dev; + char *name; + E_VPOST_LAYER layer; + IRQn_Type irqn; + E_SYS_IPRST rstidx; + E_SYS_IPCLK clkidx; + struct rt_device_graphic_info info; +}; +typedef struct nu_vpost *nu_vpost_t; + +static struct nu_vpost nu_fbdev[eVpost_Cnt] = +{ + { + .name = "lcd", + .layer = eVpost_LCD, + .irqn = IRQ_LCD, + .rstidx = LCDRST, + .clkidx = LCDCKEN, + } +#if defined(BSP_USING_VPOST_OSD) + , { + .name = "osd", + .layer = eVpost_OSD, + .irqn = (IRQn_Type) - 1, + .rstidx = SYS_IPRST_NA, + .clkidx = SYS_IPCLK_NA, + } +#endif +}; + +static rt_err_t vpost_layer_open(rt_device_t dev, rt_uint16_t oflag) +{ + nu_vpost_t psVpost = (nu_vpost_t)dev; + RT_ASSERT(psVpost != RT_NULL); + + switch (psVpost->layer) + { + case eVpost_LCD: + vpostVAStartTrigger(); + break; + +#if defined(BSP_USING_VPOST_OSD) + case eVpost_OSD: + vpostVAStartTrigger(); + + /* Set scale to 1:1 */ + vpostOSDScalingCtrl(1, 0, 0); + +#if (LCM_USING_BPP==4) + vpostOSDSetColMask(0xff, 0xff, 0xff); +#else + vpostOSDSetColMask(0x1f, 0x3f, 0x1f); +#endif + + /* Enable color key function */ + vpostOSDSetColKey(0, 0, 0); + + /* Configure overlay function of OSD to display OSD image */ + vpostOSDSetOverlay(DISPLAY_OSD, DISPLAY_OSD, 0); + + vpostOSDEnable(); + break; +#endif + + default: + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t vpost_layer_close(rt_device_t dev) +{ + nu_vpost_t psVpost = (nu_vpost_t)dev; + RT_ASSERT(psVpost != RT_NULL); + + switch (psVpost->layer) + { + case eVpost_LCD: +#if defined(BSP_USING_VPOST_OSD) + if (nu_fbdev[eVpost_OSD].dev.ref_count == 0) +#endif + vpostVAStopTrigger(); + break; + +#if defined(BSP_USING_VPOST_OSD) + case eVpost_OSD: + vpostOSDDisable(); + if (nu_fbdev[eVpost_LCD].dev.ref_count == 0) + { + /* Also stop displaying */ + vpostVAStopTrigger(); + } + break; +#endif + + default: + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t vpost_layer_control(rt_device_t dev, int cmd, void *args) +{ + nu_vpost_t psVpost = (nu_vpost_t)dev; + RT_ASSERT(psVpost != RT_NULL); + + switch (cmd) + { + case RTGRAPHIC_CTRL_GET_INFO: + { + struct rt_device_graphic_info *info = (struct rt_device_graphic_info *) args; + RT_ASSERT(info != RT_NULL); + rt_memcpy(args, (void *)&psVpost->info, sizeof(struct rt_device_graphic_info)); + } + break; + + default: + break; + } + + return RT_EOK; +} + +static rt_err_t vpost_layer_init(rt_device_t dev) +{ + nu_vpost_t psVpost = (nu_vpost_t)dev; + RT_ASSERT(psVpost != RT_NULL); + + /* Enable VPOST engine clock. */ + nu_sys_ipclk_enable(LCDCKEN); + + return RT_EOK; +} + +int rt_hw_vpost_init(void) +{ + int i = -1; + rt_err_t ret; + + VPOST_T *psVpostLcmInst = vpostLCMGetInstance(VPOST_USING_LCD_IDX); + RT_ASSERT(psVpostLcmInst != RT_NULL); + +#if (LCM_USING_BPP==4 ) + /* LCD clock is selected from UPLL and divide to 30MHz */ + outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0x918); +#else + /* LCD clock is selected from UPLL and divide to 20MHz */ + outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0xE18); +#endif + + /* Initial LCM */ + vpostLCMInit(VPOST_USING_LCD_IDX); + + /* Set scale to 1:1 */ + vpostVAScalingCtrl(1, 0, 1, 0, VA_SCALE_INTERPOLATION); + + for (i = eVpost_LCD; i < eVpost_Cnt; i++) + { + nu_vpost_t psVpost = &nu_fbdev[i]; + rt_memset((void *)&psVpost->info, 0, sizeof(struct rt_device_graphic_info)); + + /* Register VPOST information */ + psVpost->info.bits_per_pixel = LCM_USING_BPP * 8; + psVpost->info.pixel_format = (LCM_USING_BPP == 4) ? RTGRAPHIC_PIXEL_FORMAT_ARGB888 : RTGRAPHIC_PIXEL_FORMAT_RGB565; + psVpost->info.pitch = psVpostLcmInst->u32DevWidth * LCM_USING_BPP; + psVpost->info.width = psVpostLcmInst->u32DevWidth; + psVpost->info.height = psVpostLcmInst->u32DevHeight; + + /* Get pointer of video frame buffer */ + /* Set display color depth */ + /* Note: before get pointer of frame buffer, must set display color depth first */ + if (psVpost->layer == eVpost_LCD) + { +#if (LCM_USING_BPP==4) + vpostSetVASrc(VA_SRC_RGB888); +#else + vpostSetVASrc(VA_SRC_RGB565); +#endif + psVpost->info.framebuffer = (rt_uint8_t *)vpostGetFrameBuffer(); + } +#if defined(BSP_USING_VPOST_OSD) + else if (psVpost->layer == eVpost_OSD) + { + vpostOSDSetWindow(0, 0, psVpost->info.width, psVpost->info.height); + +#if (LCM_USING_BPP==4) + vpostSetOSDSrc(OSD_SRC_RGB888); +#else + vpostSetOSDSrc(OSD_SRC_RGB565); +#endif + psVpost->info.framebuffer = (rt_uint8_t *)vpostGetOSDBuffer(); + } +#endif + + if (psVpost->info.framebuffer == NULL) + { + rt_kprintf("Fail to get VRAM buffer.\n"); + RT_ASSERT(0); + } + + /* Register member functions of lcd device */ + psVpost->dev.type = RT_Device_Class_Graphic; + psVpost->dev.init = vpost_layer_init; + psVpost->dev.open = vpost_layer_open; + psVpost->dev.close = vpost_layer_close; + psVpost->dev.control = vpost_layer_control; + + /* register graphic device driver */ + ret = rt_device_register(&psVpost->dev, psVpost->name, RT_DEVICE_FLAG_RDWR); + RT_ASSERT(ret == RT_EOK); + + rt_kprintf("%s's fbmem at 0x%08x.\n", psVpost->name, psVpost->info.framebuffer); + } + + /* For saving memory bandwidth. */ + vpostLCMDeinit(); + + return (int)ret; +} +INIT_DEVICE_EXPORT(rt_hw_vpost_init); + + +/* Support "vpost_set_osd_colkey" command line in msh mode */ +static rt_err_t vpost_set_osd_colkey(int argc, char **argv) +{ + rt_uint32_t index, len, arg[4]; + + rt_memset(arg, 0, sizeof(arg)); + len = (argc >= 4) ? 4 : argc; + + for (index = 0; index < (len - 1); index ++) + { + arg[index] = atol(argv[index + 1]); + } + + /* Enable color key function */ + vpostOSDSetColKey(arg[0], arg[1], arg[2]); + + /* Configure overlay function of OSD to display VIDEO image */ + vpostOSDSetOverlay(DISPLAY_VIDEO, DISPLAY_OSD, 0); + + return 0; +} +MSH_CMD_EXPORT(vpost_set_osd_colkey, e.g: vpost_set_osd_colkey R G B); + +/* Support "vpost_show_layer" command line in msh mode */ +static rt_err_t vpost_show_layer(int argc, char **argv) +{ + rt_uint32_t index, len, arg[2]; + nu_vpost_t psVpostLayer; + + rt_memset(arg, 0, sizeof(arg)); + len = (argc >= 2) ? 2 : argc; + + for (index = 0; index < (len - 1); index ++) + { + arg[index] = atol(argv[index + 1]); + } + psVpostLayer = &nu_fbdev[arg[0]]; + + return rt_device_open(&psVpostLayer->dev, RT_DEVICE_FLAG_RDWR); +} +MSH_CMD_EXPORT(vpost_show_layer, e.g: vpost_show_layer layer); + +/* Support "vpost_hide_layer" command line in msh mode */ +static rt_err_t vpost_hide_layer(int argc, char **argv) +{ + rt_uint32_t index, len, arg[2]; + nu_vpost_t psVpostLayer; + + rt_memset(arg, 0, sizeof(arg)); + len = (argc >= 2) ? 2 : argc; + + for (index = 0; index < (len - 1); index ++) + { + arg[index] = atol(argv[index + 1]); + } + psVpostLayer = &nu_fbdev[arg[0]]; + + return rt_device_close(&psVpostLayer->dev); +} +MSH_CMD_EXPORT(vpost_hide_layer, e.g: vpost_hide_layer layer); + +/* Support "vpost_fill_color" command line in msh mode */ +static rt_err_t vpost_fill_color(int argc, char **argv) +{ + rt_uint32_t index, len, arg[5]; + nu_vpost_t psVpostLayer; + + rt_memset(arg, 0, sizeof(arg)); + len = (argc >= 5) ? 5 : argc; + + for (index = 0; index < (len - 1); index ++) + { + arg[index] = atol(argv[index + 1]); + } + + psVpostLayer = &nu_fbdev[arg[0]]; + + if (psVpostLayer->info.framebuffer != RT_NULL) + { + int i; + uint32_t fill_num = psVpostLayer->info.height * psVpostLayer->info.width; + uint32_t *fbmem_start = (uint32_t *)psVpostLayer->info.framebuffer; + uint32_t color = (arg[1] << 16) | (arg[2] << 8) | arg[3] ; + for (i = 0; i < fill_num; i++) + { + rt_memcpy((void *)&fbmem_start[i], &color, (psVpostLayer->info.bits_per_pixel / 8)); + } + } + return 0; +} +MSH_CMD_EXPORT(vpost_fill_color, e.g: vpost_fill_color layer R G B); + +#endif /* if defined(BSP_USING_VPOST) */ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_wdt.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_wdt.c new file mode 100644 index 0000000000..cc77bd2b30 --- /dev/null +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_wdt.c @@ -0,0 +1,283 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-12-12 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_WDT) + +#include +#include +#include +#include "NuMicro.h" +#include + +/* Private define ---------------------------------------------------------------*/ + +/* Pick a suitable wdt timeout interval, it is a trade-off between the + consideration of timeout accuracy and the system performance. The MIN_CYCLES + parameter is a numerical value of the toutsel setting, and it must be set to + a correct one which matches to the literal meaning of MIN_TOUTSEL. */ +#define MIN_TOUTSEL (WDT_TIMEOUT_2POW10) +#define MIN_CYCLES (1024) + + +/* Macros to convert the value between the timeout interval and the soft time iterations. */ +#define ROUND_TO_INTEGER(value) ((int)(((value) * 10 + 5) / 10)) +#define CONV_SEC_TO_IT(hz, secs) (ROUND_TO_INTEGER((float)((secs) * (hz)) / (float)(MIN_CYCLES))) +#define CONV_IT_TO_SEC(hz, iterations) (ROUND_TO_INTEGER((float)((iterations) * (MIN_CYCLES)) / (float)(hz))) + + +/* Private typedef --------------------------------------------------------------*/ +struct soft_time_handle +{ + int clock_hz; + int wanted_sec; + int report_sec; + int left_iterations; + int full_iterations; + rt_bool_t expired; + rt_bool_t feed_dog; +}; + +typedef volatile struct soft_time_handle soft_time_handle_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t wdt_init(rt_watchdog_t *dev); +static rt_err_t wdt_control(rt_watchdog_t *dev, int cmd, void *args); +static uint32_t wdt_get_working_hz(void); +static void soft_time_init(soft_time_handle_t *const soft_time); +static void soft_time_setup(uint32_t wanted_sec, uint32_t hz, soft_time_handle_t *const soft_time); +static void soft_time_feed_dog(soft_time_handle_t *const soft_time); +static void nu_wdt_isr(int vector, void *param); + +/* Public functions -------------------------------------------------------------*/ + +/* Private variables ------------------------------------------------------------*/ +static struct soft_time_handle soft_time; +static struct rt_watchdog_device device_wdt; +static struct rt_watchdog_ops ops_wdt = +{ + .init = wdt_init, + .control = wdt_control, +}; + +static void hw_wdt_init(void) +{ + nu_sys_ipclk_enable(WDTCKEN); + + rt_hw_interrupt_install(IRQ_WDT, nu_wdt_isr, &device_wdt, "wdt"); + rt_hw_interrupt_umask(IRQ_WDT); +} + + +/* wdt device driver initialize. */ +int rt_hw_wdt_init(void) +{ + rt_err_t ret; + + hw_wdt_init(); + + device_wdt.ops = &ops_wdt; + ret = rt_hw_watchdog_register(&device_wdt, "wdt", RT_DEVICE_FLAG_RDWR, RT_NULL); + + return (int)ret; +} +INIT_BOARD_EXPORT(rt_hw_wdt_init); + + +/* Register rt-thread device.init() entry. */ +static rt_err_t wdt_init(rt_watchdog_t *dev) +{ + soft_time_init(&soft_time); + + return RT_EOK; +} + + +static uint32_t wdt_get_working_hz(void) +{ + static uint32_t u32ClkTbl[4] = {12000000, 12000000 / 128, 0, 32768}; + uint32_t u32WDT_S = (inpw(REG_CLK_DIVCTL8) & (0x3 << 8)) >> 8; + uint32_t clk = 0; + + switch (u32WDT_S) + { + case 0: // XIN Hz + case 1: // XIN/128 Hz + case 3: // 32.768 Hz + clk = u32ClkTbl[u32WDT_S]; + break; + + case 2: // PCLK/4096 Hz + clk = sysGetClock(SYS_PCLK) * 1000000 / 4096; + break; + + default: + break; + } + + return clk; +} + + + +static void soft_time_init(soft_time_handle_t *const soft_time) +{ + rt_memset((void *)soft_time, 0, sizeof(struct soft_time_handle)); + +} + + +static void soft_time_setup(uint32_t wanted_sec, uint32_t hz, soft_time_handle_t *const soft_time) +{ + rt_base_t level = rt_hw_interrupt_disable(); + + soft_time->expired = RT_FALSE; + soft_time->feed_dog = RT_FALSE; + soft_time->wanted_sec = wanted_sec; + soft_time->full_iterations = CONV_SEC_TO_IT(hz, wanted_sec); + soft_time->left_iterations = soft_time->full_iterations; + soft_time->report_sec = CONV_IT_TO_SEC(hz, soft_time->full_iterations); + soft_time->clock_hz = hz; + + rt_hw_interrupt_enable(level); +} + + +static void soft_time_feed_dog(soft_time_handle_t *const soft_time) +{ + soft_time->feed_dog = RT_TRUE; +} + + +/* Register rt-thread device.control() entry. */ +static rt_err_t wdt_control(rt_watchdog_t *dev, int cmd, void *args) +{ + uint32_t wanted_sec, hz; + uint32_t *buf; + rt_err_t ret = RT_EOK; + + if (dev == NULL) + return -(RT_EINVAL); + + hz = wdt_get_working_hz(); + + SYS_UnlockReg(); + + switch (cmd) + { + case RT_DEVICE_CTRL_WDT_GET_TIMEOUT: + + if (args == RT_NULL) + { + ret = RT_EINVAL; + break; + } + + buf = (uint32_t *)args; + *buf = soft_time.report_sec; + break; + + case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: + + wanted_sec = *((uint32_t *)args); + + if (wanted_sec == 0) + { + ret = RT_EINVAL; + break; + } + + soft_time_setup(wanted_sec, hz, &soft_time); + break; + + case RT_DEVICE_CTRL_WDT_GET_TIMELEFT: + + if (args == RT_NULL) + { + ret = RT_EINVAL; + break; + } + + buf = (uint32_t *)args; + *buf = CONV_IT_TO_SEC(hz, soft_time.left_iterations); + break; + + case RT_DEVICE_CTRL_WDT_KEEPALIVE: + + /* Make a mark that the application has fed the watchdog. */ + soft_time_feed_dog(&soft_time); + break; + + case RT_DEVICE_CTRL_WDT_START: + + WDT_RESET_COUNTER(); + WDT_Open(MIN_TOUTSEL, WDT_RESET_DELAY_1026CLK, TRUE, TRUE); + WDT_EnableInt(); + break; + + case RT_DEVICE_CTRL_WDT_STOP: + + WDT_Close(); + break; + + default: + ret = RT_ERROR; + } + + SYS_LockReg(); + + return -(ret); +} + + +/* wdt interrupt entry */ +static void nu_wdt_isr(int vector, void *param) +{ + /* Clear wdt interrupt flag */ + if (WDT_GET_TIMEOUT_INT_FLAG()) + { + WDT_CLEAR_TIMEOUT_INT_FLAG(); + } + + SYS_UnlockReg(); + + /* The soft time has not reached the configured timeout yet. Clear the wdt counter + any way to prevent the system from hardware wdt reset. */ + if (soft_time.left_iterations-- > 0) + { + WDT_RESET_COUNTER(); + } + + /* The soft time reaches the configured timeout boundary. Clear the wdt + counter if he application has fed the dog at least once until now. */ + else + { + if ((soft_time.feed_dog) && (!soft_time.expired)) + { + WDT_RESET_COUNTER(); + soft_time.feed_dog = RT_FALSE; + soft_time.left_iterations = soft_time.full_iterations; + } + else + { + /* Application does not feed the dog in time. */ + soft_time.expired = RT_TRUE; + } + } + + SYS_LockReg(); +} + +#endif /* BSP_USING_WDT */ + + From 74f6a0ba7d0f3a2573d5ae5ad9a9abe83afcbaa9 Mon Sep 17 00:00:00 2001 From: greedyhao Date: Thu, 13 May 2021 10:22:09 +0800 Subject: [PATCH 057/255] [bluetrum] Fix the cache mechanism --- bsp/bluetrum/ab32vg1-ab-prougen/board/board.c | 26 +++++++++++++--- bsp/bluetrum/ab32vg1-ab-prougen/link.lds | 20 +++++------- .../hal_libraries/ab32vg1_hal/libhal.a | Bin 0 -> 33546 bytes .../hal_libraries/bmsis/source/startup.S | 29 ++++++++++-------- 4 files changed, 46 insertions(+), 29 deletions(-) create mode 100644 bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/libhal.a diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/board/board.c b/bsp/bluetrum/ab32vg1-ab-prougen/board/board.c index f10ea4a6c8..4fc392d008 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/board/board.c +++ b/bsp/bluetrum/ab32vg1-ab-prougen/board/board.c @@ -19,14 +19,13 @@ void rt_soft_isr(int vector, void *param); void cpu_irq_comm(void); void set_cpu_irq_comm(void (*irq_hook)(void)); void load_cache(); +void os_cache_init(void); void sys_error_hook(uint8_t err_no); -typedef void (*os_cache_setfunc_func)(void *load_cache_func, void *io_read); typedef void (*spiflash_init_func)(uint8_t sf_read, uint8_t dummy); -#define os_cache_setfunc ((os_cache_setfunc_func) 0x84024) - static struct rt_mutex mutex_spiflash = {0}; +static struct rt_mutex mutex_cache = {0}; extern volatile rt_uint8_t rt_interrupt_nest; extern uint32_t __heap_start, __heap_end; @@ -148,8 +147,9 @@ void rt_hw_us_delay(rt_uint32_t us) RT_SECTION(".irq.cache") void cache_init(void) { - os_cache_setfunc(load_cache, NULL); + os_cache_init(); rt_mutex_init(&mutex_spiflash, "flash_mutex", RT_IPC_FLAG_FIFO); + rt_mutex_init(&mutex_cache, "cache_mutex", RT_IPC_FLAG_FIFO); } RT_SECTION(".irq.cache") @@ -170,6 +170,24 @@ void os_spiflash_unlock(void) } } +RT_SECTION(".irq.cache") +void os_cache_lock(void) +{ + // if (rt_thread_self()->stat == RT_THREAD_RUNNING) { + if ((rt_thread_self() != RT_NULL) && (rt_interrupt_nest == 0)) { + rt_mutex_take(&mutex_cache, RT_WAITING_FOREVER); + } +} + +RT_SECTION(".irq.cache") +void os_cache_unlock(void) +{ + // if (rt_thread_self()->stat == RT_THREAD_RUNNING) { + if ((rt_thread_self() != RT_NULL) && (rt_interrupt_nest == 0)) { + rt_mutex_release(&mutex_cache); + } +} + RT_SECTION(".irq.err.str") static const char stack_info[] = "thread sp=0x%x name=%s"; diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/link.lds b/bsp/bluetrum/ab32vg1-ab-prougen/link.lds index d785c3d92c..82e8906080 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/link.lds +++ b/bsp/bluetrum/ab32vg1-ab-prougen/link.lds @@ -43,7 +43,7 @@ SECTIONS . = ALIGN(4); PROVIDE(__ctors_start__ = .); KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) + KEEP (*(.init_array*)) PROVIDE(__ctors_end__ = .); . = ALIGN(4); @@ -73,21 +73,17 @@ SECTIONS .comm __comm_vma : { . = ALIGN(4); KEEP(*(.vector)) + *(.irq.cache) *(.irq*) - /*applications**.o (.text .rodata)*/ - *hal_libraries*ab32vg1_hal**.o (.text .rodata) - *(.text.unlikely) - *(.text.startup) - *hal_drivers**.o (.rodata) - *audio*drv_sound.o (.rodata) - *system_ab32vgx.o (.rodata) - EXCLUDE_FILE(*lib_a**.o *cp-demangle.o *cp-demangle.o - *src*mem.o *src*memheap.o *dfs**.o *components.o *drivers*sdio**.o *cmd.o *msh_file.o - *drv_sdio.o *drv_wdt.o) *(.rodata.str1.4) - EXCLUDE_FILE(*lib_a**.o *unwind*.o) *(.srodata) + *components*src**.o (.text* .rodata*) + *ab32vg1_hal**.o (.text* .rodata*) + *drv_gpio.o (.text* .rodata*) + *drv_usart.o (.rodata*) + EXCLUDE_FILE(*lib_a**.o *unwind*.o) *(.srodata*) *(.rela*) *(.data*) *(.sdata*) + *(.com_text*) } > comm AT > flash .bss (NOLOAD): diff --git a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/libhal.a b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/libhal.a new file mode 100644 index 0000000000000000000000000000000000000000..97474b1370514216fc3e263d1da5d912795bb505 GIT binary patch literal 33546 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 F{|C$je8d0% literal 0 HcmV?d00001 diff --git a/bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S b/bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S index 3245135038..175ea15797 100644 --- a/bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S +++ b/bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S @@ -9,6 +9,8 @@ .global _start .section .reset, "ax" _start: + la tp, _tp + la gp, _gp //load comm la a0, __comm_vma @@ -25,7 +27,7 @@ _start: la a0, __irq_stack_start //Stack清成0x23 li a1, 0x23 la a2, __irq_stack_size - call memset + call 0x84040 la ra, __irq_stack lui a5, 0x1 sw zero, -1920(a5) @@ -35,7 +37,7 @@ _start: la a0, __bss_start li a1, 0 la a2, __bss_size - call memset + call 0x84040 call cache_init @@ -56,32 +58,33 @@ __exception: .org 0x40 jal x0, low_prio_irq - mret .org 0x80 #define METHOD 1 #if METHOD == 1 addi sp, sp, -6*4 - lw a0, PICEN(zero) + # lw a0, PICEN(zero) lw a1, EPC(zero) lw a2, EPICCON(zero) - sw a0, 3*4(sp) + # sw a0, 3*4(sp) sw a1, 4*4(sp) sw a2, 5*4(sp) - andi a0, a0, 1 - sw a0, PICEN(zero) + # andi a0, a0, 1 + # sw a0, PICEN(zero) + li a2, 0 + sw a2, EPICCON(zero) la a0, 0f sw a0, EPC(zero) - j 0x84020 + j isr_cache 0: sw a0, 0(sp) sw a1, 4(sp) sw a2, 8(sp) - lw a0, 3*4(sp) + # lw a0, 3*4(sp) lw a1, 4*4(sp) lw a2, 5*4(sp) - sw a0, PICEN(zero) + # sw a0, PICEN(zero) sw a1, EPC(zero) sw a2, EPICCON(zero) @@ -90,9 +93,6 @@ __exception: lw a2, 8(sp) addi sp, sp, 6*4 mret - .align 4 -1: .word 0, 0 - j 0x84020 #endif .global cpu_irq_comm @@ -102,3 +102,6 @@ cpu_irq_comm: j cpu_irq_comm_do ret + + .global _tp + .set _tp, 0x84800 From 3e65ce5d037b44e760bfe4927800f42f660855b3 Mon Sep 17 00:00:00 2001 From: greedyhao Date: Thu, 13 May 2021 10:22:45 +0800 Subject: [PATCH 058/255] [bluetrum] add fmrx support --- bsp/bluetrum/ab32vg1-ab-prougen/.config | 17 +++++++- bsp/bluetrum/ab32vg1-ab-prougen/README.md | 2 +- .../board/ports/audio/drv_sound.c | 38 ++++++++-------- bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h | 6 ++- .../ab32vg1_hal/include/api_fmrx.h | 43 +++++++++++++++++++ 5 files changed, 85 insertions(+), 21 deletions(-) create mode 100644 bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/api_fmrx.h diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/.config b/bsp/bluetrum/ab32vg1-ab-prougen/.config index 9c2fe998a6..097f9df54c 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/.config +++ b/bsp/bluetrum/ab32vg1-ab-prougen/.config @@ -74,7 +74,7 @@ CONFIG_RT_USING_DEVICE_OPS=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=128 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x40003 +CONFIG_RT_VER_NUM=0x40004 # CONFIG_RT_USING_CPU_FFS is not set # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set @@ -160,6 +160,7 @@ CONFIG_RT_USING_PIN=y CONFIG_RT_USING_LIBC=y # CONFIG_RT_USING_PTHREADS is not set # CONFIG_RT_USING_MODULE is not set +CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # # Network @@ -197,6 +198,11 @@ CONFIG_RT_USING_LIBC=y # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + # # RT-Thread online packages # @@ -309,9 +315,11 @@ CONFIG_RT_USING_LIBC=y # 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 @@ -349,6 +357,10 @@ CONFIG_RT_USING_LIBC=y # 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 @@ -396,6 +408,7 @@ CONFIG_RT_USING_LIBC=y # CONFIG_PKG_USING_QFPLIB_M3 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 @@ -463,6 +476,7 @@ CONFIG_RT_USING_LIBC=y # 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 @@ -490,6 +504,7 @@ CONFIG_RT_USING_LIBC=y # 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 diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/README.md b/bsp/bluetrum/ab32vg1-ab-prougen/README.md index 8950f880aa..5eb229a223 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/README.md +++ b/bsp/bluetrum/ab32vg1-ab-prougen/README.md @@ -48,7 +48,7 @@ ab32vg1-prougen 是 中科蓝讯(Bluetrum) 推出的一款基于 RISC-V 内核 | FLASH | 即将支持 | 对接 FAL | | TIMER | 支持 | | | PWM | 支持 | LPWM 的 G1 G2 G3 之间是互斥的,只能三选一 | -| FM receive | 即将支持 | | +| FM receive | 支持 | | | USB Device | 暂不支持 | | | USB Host | 暂不支持 | | diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c b/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c index d250a3fc94..e2ba236512 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c +++ b/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c @@ -13,8 +13,9 @@ #define DBG_LVL DBG_INFO #include -#define SAI_AUDIO_FREQUENCY_44K ((uint32_t)44100u) #define SAI_AUDIO_FREQUENCY_48K ((uint32_t)48000u) +#define SAI_AUDIO_FREQUENCY_44K ((uint32_t)44100u) +#define SAI_AUDIO_FREQUENCY_38K ((uint32_t)38000u) #define TX_FIFO_SIZE (1024) struct sound_device @@ -22,10 +23,11 @@ struct sound_device struct rt_audio_device audio; struct rt_audio_configure replay_config; rt_sem_t semaphore; - rt_thread_t thread; + rt_thread_t thread; rt_uint8_t *tx_fifo; rt_uint8_t *rx_fifo; rt_uint8_t volume; + rt_uint8_t dma_to_aubuf; }; static struct sound_device snd_dev = {0}; @@ -120,16 +122,15 @@ void audio_sem_pend(void) void saia_frequency_set(uint32_t frequency) { + DACDIGCON0 &= ~(0xf << 2); if (frequency == SAI_AUDIO_FREQUENCY_48K) { - DACDIGCON0 |= BIT(1); - DACDIGCON0 &= ~(0xf << 2); - DACDIGCON0 |= BIT(6); + DACDIGCON0 |= (0 << 2); } else if (frequency == SAI_AUDIO_FREQUENCY_44K) { - DACDIGCON0 &= ~BIT(1); - DACDIGCON0 &= ~(0xf << 2); - DACDIGCON0 |= BIT(1); - DACDIGCON0 |= BIT(6); + DACDIGCON0 |= (1 << 2); + } else if (frequency == SAI_AUDIO_FREQUENCY_38K) { + DACDIGCON0 |= (2 << 2); } + DACDIGCON0 |= BIT(6); } void saia_channels_set(uint8_t channels) @@ -271,6 +272,10 @@ static rt_err_t sound_configure(struct rt_audio_device *audio, struct rt_audio_c break; } + case AUDIO_MIXER_EXTEND: + snd_dev->dma_to_aubuf = caps->udata.value; + break; + default: result = -RT_ERROR; break; @@ -349,6 +354,7 @@ static rt_err_t sound_init(struct rt_audio_device *audio) /* set default params */ saia_frequency_set(snd_dev->replay_config.samplerate); saia_channels_set(snd_dev->replay_config.channels); + saia_volume_set(snd_dev->volume); return RT_EOK; } @@ -368,9 +374,7 @@ static rt_err_t sound_start(struct rt_audio_device *audio, int stream) AUBUFSIZE |= (TX_FIFO_SIZE / 8) << 16; AUBUFSTARTADDR = DMA_ADR(snd_dev->rx_fifo); - DACDIGCON0 = BIT(0) | BIT(10); // (0x01<<2) - DACVOLCON = 0x7fff; // -60DB - DACVOLCON |= BIT(20); + DACDIGCON0 |= BIT(0) | BIT(10); // (0x01<<2) AUBUFCON |= BIT(1); } @@ -380,13 +384,11 @@ static rt_err_t sound_start(struct rt_audio_device *audio, int stream) static rt_err_t sound_stop(struct rt_audio_device *audio, int stream) { - struct sound_device *snd_dev = RT_NULL; - RT_ASSERT(audio != RT_NULL); - snd_dev = (struct sound_device *)audio->parent.user_data; if (stream == AUDIO_STREAM_REPLAY) { + DACDIGCON0 = 0; AUBUFCON &= ~BIT(4); LOG_D("close sound device"); } @@ -463,7 +465,7 @@ static void audio_thread_entry(void *parameter) { while (1) { - if (snd_dev.audio.replay->activated == RT_TRUE) { + if ((snd_dev.dma_to_aubuf == RT_FALSE) && (snd_dev.audio.replay->activated == RT_TRUE)) { rt_audio_tx_complete(&snd_dev.audio); } else { rt_thread_mdelay(50); @@ -506,7 +508,7 @@ static int rt_hw_sound_init(void) RT_NULL, 1024, 20, // must equal or lower than tshell priority - 5 + 1 ); if (snd_dev.thread != RT_NULL) @@ -516,7 +518,7 @@ static int rt_hw_sound_init(void) /* init default configuration */ { - snd_dev.replay_config.samplerate = 48000; + snd_dev.replay_config.samplerate = SAI_AUDIO_FREQUENCY_48K; snd_dev.replay_config.channels = 2; snd_dev.replay_config.samplebits = 16; snd_dev.volume = 55; diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h b/bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h index 6defaad7dc..7451b8f1c0 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h +++ b/bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h @@ -46,7 +46,7 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40003 +#define RT_VER_NUM 0x40004 /* RT-Thread Components */ @@ -90,6 +90,7 @@ /* POSIX layer and C standard library */ #define RT_USING_LIBC +#define RT_LIBC_FIXED_TIMEZONE 8 /* Network */ @@ -111,6 +112,9 @@ /* Utilities */ +/* RT-Thread Utestcases */ + + /* RT-Thread online packages */ /* IoT - internet of things */ diff --git a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/api_fmrx.h b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/api_fmrx.h new file mode 100644 index 0000000000..03e61039fe --- /dev/null +++ b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/api_fmrx.h @@ -0,0 +1,43 @@ +#ifndef FMRX_H__ +#define FMRX_H__ + +/** + * @brief Synchronize between FMRX and DAC + * + * @param buf_size Size of audio buffer. + */ +void fmrx_dac_sync(uint32_t buf_size); + +/** + * @brief FMRX power on. + * + * @param val Make it zero now. + */ +void fmrx_power_on(uint32_t val); + +/** + * @brief FMRX power off. + * + */ +void fmrx_power_off(void); + +/** + * @brief FMRX digital start. + * + */ +void fmrx_digital_start(void); + +/** + * @brief FMRX digital stop. + * + */ +void fmrx_digital_stop(void); + +/** + * @brief FMRX dma to aubuf enable. + * + * @param enable RT_TRUE or RT_FALSE. + */ +void fmrx_dma_to_aubuf(uint8_t enable); + +#endif From 21beba79133e0d834ae0a5dab2edbbb6b20f5920 Mon Sep 17 00:00:00 2001 From: ZHU Hao Date: Thu, 13 May 2021 11:58:09 +0800 Subject: [PATCH 059/255] Update api_fmrx.h --- .../hal_libraries/ab32vg1_hal/include/api_fmrx.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/api_fmrx.h b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/api_fmrx.h index 03e61039fe..2638060591 100644 --- a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/api_fmrx.h +++ b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/api_fmrx.h @@ -3,39 +3,39 @@ /** * @brief Synchronize between FMRX and DAC - * + * * @param buf_size Size of audio buffer. */ void fmrx_dac_sync(uint32_t buf_size); /** * @brief FMRX power on. - * + * * @param val Make it zero now. */ void fmrx_power_on(uint32_t val); /** * @brief FMRX power off. - * + * */ void fmrx_power_off(void); /** * @brief FMRX digital start. - * + * */ void fmrx_digital_start(void); /** * @brief FMRX digital stop. - * + * */ void fmrx_digital_stop(void); /** * @brief FMRX dma to aubuf enable. - * + * * @param enable RT_TRUE or RT_FALSE. */ void fmrx_dma_to_aubuf(uint8_t enable); From 329fc480cee74a2c1e13eac48a1f28559a2faa08 Mon Sep 17 00:00:00 2001 From: Meco Jianting Man <920369182@qq.com> Date: Thu, 13 May 2021 12:05:30 +0800 Subject: [PATCH 060/255] revert automac.h --- bsp/qemu-vexpress-a9/drivers/automac.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bsp/qemu-vexpress-a9/drivers/automac.h b/bsp/qemu-vexpress-a9/drivers/automac.h index 567b1f82fb..7c4ca08fbc 100644 --- a/bsp/qemu-vexpress-a9/drivers/automac.h +++ b/bsp/qemu-vexpress-a9/drivers/automac.h @@ -8,8 +8,8 @@ #define AUTOMAC0 0x52 #define AUTOMAC1 0x54 #define AUTOMAC2 0x00 -#define AUTOMAC3 0x78 -#define AUTOMAC4 0xe7 -#define AUTOMAC5 0x23 +#define AUTOMAC3 0xa0 +#define AUTOMAC4 0x0e +#define AUTOMAC5 0xe4 #endif From d205721462ca448b8710098f83118620ef2399e9 Mon Sep 17 00:00:00 2001 From: Wang-Huachen Date: Thu, 13 May 2021 16:33:40 +0800 Subject: [PATCH 061/255] add ethernet driver for zynqmp-r5-axu4ev --- bsp/zynqmp-r5-axu4ev/.config | 209 ++- bsp/zynqmp-r5-axu4ev/README.md | 20 +- bsp/zynqmp-r5-axu4ev/README_zh.md | 9 +- bsp/zynqmp-r5-axu4ev/drivers/Kconfig | 13 + .../drivers/Zynq_HAL_Driver/SConscript | 3 + .../Zynq_HAL_Driver/emacps_v3_11/SConscript | 15 + .../Zynq_HAL_Driver/emacps_v3_11/xemacps.c | 480 +++++++ .../Zynq_HAL_Driver/emacps_v3_11/xemacps.h | 836 ++++++++++++ .../Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h | 762 +++++++++++ .../emacps_v3_11/xemacps_bdring.c | 1076 +++++++++++++++ .../emacps_v3_11/xemacps_bdring.h | 215 +++ .../emacps_v3_11/xemacps_control.c | 1133 ++++++++++++++++ .../Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c | 32 + .../Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c | 97 ++ .../Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h | 646 +++++++++ .../emacps_v3_11/xemacps_intr.c | 242 ++++ .../emacps_v3_11/xemacps_sinit.c | 71 + .../drivers/Zynq_HAL_Driver/sleep.h | 2 +- .../Zynq_HAL_Driver/xemacpsif/SConscript | 15 + .../xemacpsif/netif/xadapter.h | 94 ++ .../xemacpsif/netif/xemacpsif.h | 163 +++ .../Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h | 54 + .../xemacpsif/netif/xtopology.h | 58 + .../Zynq_HAL_Driver/xemacpsif/xadapter.c | 432 +++++++ .../xemacpsif/xemac_ieee_reg.h | 101 ++ .../Zynq_HAL_Driver/xemacpsif/xemacpsif.c | 759 +++++++++++ .../Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c | 873 +++++++++++++ .../Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c | 276 ++++ .../Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.h | 49 + .../xemacpsif/xemacpsif_physpeed.c | 1152 +++++++++++++++++ .../Zynq_HAL_Driver/xemacpsif/xlwipconfig.h | 44 + .../Zynq_HAL_Driver/xemacpsif/xpqueue.c | 93 ++ .../Zynq_HAL_Driver/xemacpsif/xtopology_g.c | 15 + .../drivers/Zynq_HAL_Driver/xil_types.h | 3 + bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c | 349 +++++ bsp/zynqmp-r5-axu4ev/drivers/drv_eth.h | 13 + bsp/zynqmp-r5-axu4ev/rtconfig.h | 87 +- libcpu/arm/zynqmp-r5/cache.c | 297 ++++- libcpu/arm/zynqmp-r5/start_gcc.S | 4 + libcpu/arm/zynqmp-r5/xil_mmu.h | 54 + libcpu/arm/zynqmp-r5/xil_mpu.c | 637 +++++++++ libcpu/arm/zynqmp-r5/xil_mpu.h | 129 ++ 42 files changed, 11554 insertions(+), 58 deletions(-) create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/SConscript create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/SConscript create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.h create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xlwipconfig.h create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c create mode 100644 bsp/zynqmp-r5-axu4ev/drivers/drv_eth.h create mode 100644 libcpu/arm/zynqmp-r5/xil_mmu.h create mode 100644 libcpu/arm/zynqmp-r5/xil_mpu.c create mode 100644 libcpu/arm/zynqmp-r5/xil_mpu.h diff --git a/bsp/zynqmp-r5-axu4ev/.config b/bsp/zynqmp-r5-axu4ev/.config index 629096a979..1f215d3c25 100644 --- a/bsp/zynqmp-r5-axu4ev/.config +++ b/bsp/zynqmp-r5-axu4ev/.config @@ -23,6 +23,12 @@ CONFIG_IDLE_THREAD_STACK_SIZE=512 CONFIG_RT_USING_TIMER_SOFT=y CONFIG_RT_TIMER_THREAD_PRIO=4 CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 + +# +# 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 is not set # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -52,8 +58,9 @@ CONFIG_RT_USING_MESSAGEQUEUE=y CONFIG_RT_USING_MEMPOOL=y # CONFIG_RT_USING_MEMHEAP is not set # CONFIG_RT_USING_NOHEAP is not set -CONFIG_RT_USING_SMALL_MEM=y -# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_SMALL_MEM is not set +CONFIG_RT_USING_SLAB=y +# CONFIG_RT_USING_USERHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set CONFIG_RT_USING_HEAP=y @@ -66,7 +73,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=128 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x40003 +CONFIG_RT_VER_NUM=0x40004 # CONFIG_RT_USING_CPU_FFS is not set # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set @@ -123,6 +130,11 @@ CONFIG_RT_DFS_ELM_WORD_ACCESS=y # 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 @@ -131,15 +143,16 @@ CONFIG_RT_DFS_ELM_REENTRANT=y CONFIG_RT_USING_DFS_DEVFS=y # CONFIG_RT_USING_DFS_ROMFS is not set # CONFIG_RT_USING_DFS_RAMFS is not set -# CONFIG_RT_USING_DFS_UFFS is not set -# CONFIG_RT_USING_DFS_JFFS2 is not set +# 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_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 CONFIG_RT_USING_SERIAL=y CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=64 @@ -147,6 +160,7 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 # 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=y # CONFIG_RT_USING_ADC is not set # CONFIG_RT_USING_DAC is not set @@ -172,11 +186,6 @@ CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_USB_HOST is not set # CONFIG_RT_USING_USB_DEVICE is not set -# -# Using RapidIO -# -# CONFIG_RT_USING_RAPIDIO is not set - # # POSIX layer and C standard library # @@ -188,6 +197,7 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -196,22 +206,91 @@ CONFIG_RT_USING_POSIX=y # # Socket abstraction layer # -# CONFIG_RT_USING_SAL is not set +CONFIG_RT_USING_SAL=y +CONFIG_SAL_INTERNET_CHECK=y + +# +# protocol stack implement +# +CONFIG_SAL_USING_LWIP=y +CONFIG_SAL_USING_POSIX=y # # Network interface device # -# CONFIG_RT_USING_NETDEV is not set +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 is not set +CONFIG_RT_USING_LWIP=y +# CONFIG_RT_USING_LWIP141 is not set +CONFIG_RT_USING_LWIP202=y +# CONFIG_RT_USING_LWIP212 is not set +# CONFIG_RT_USING_LWIP_IPV6 is not set +CONFIG_RT_LWIP_MEM_ALIGNMENT=32 +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=y +CONFIG_IP_SOF_BROADCAST=1 +CONFIG_IP_SOF_BROADCAST_RECV=1 + +# +# Static IPv4 Address +# +CONFIG_RT_LWIP_IPADDR="192.168.1.30" +CONFIG_RT_LWIP_GWADDR="192.168.1.1" +CONFIG_RT_LWIP_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=256 +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=2048 +# 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) @@ -225,6 +304,11 @@ CONFIG_RT_USING_POSIX=y # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + # # RT-Thread online packages # @@ -292,8 +376,6 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_LIBRWS is not set # CONFIG_PKG_USING_TCPSERVER is not set # CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set # CONFIG_PKG_USING_DLT645 is not set # CONFIG_PKG_USING_QXWZ is not set # CONFIG_PKG_USING_SMTP_CLIENT is not set @@ -307,6 +389,13 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -332,8 +421,11 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -345,6 +437,8 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -357,6 +451,22 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -364,7 +474,6 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_GUIENGINE is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set -# CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set # CONFIG_PKG_USING_FLASHDB is not set @@ -374,6 +483,9 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -388,11 +500,21 @@ CONFIG_RT_USING_POSIX=y # 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_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# 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 +# 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 @@ -401,6 +523,7 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -449,6 +572,30 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -458,6 +605,7 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -479,19 +627,24 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_HELLO is not set # CONFIG_PKG_USING_VI is not set # CONFIG_PKG_USING_KI is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_ELAPACK is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set # CONFIG_PKG_USING_VT100 is not set -# CONFIG_PKG_USING_TETRIS is not set -# CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set + +# +# 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_TENSORFLOWLITEMICRO 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_SOC_ZYNQMP_R5=y # @@ -510,6 +663,16 @@ CONFIG_BSP_USING_UART0=y CONFIG_BSP_USING_SDIO=y CONFIG_BSP_USING_SD0=y +# +# Please set RT_LWIP_PBUF_NUM is at least 256 if Enable Ethernet! +# + +# +# Please set RT_LWIP_MEM_ALIGNMENT is at 32 if Enable Ethernet! +# +CONFIG_BSP_USING_ETH=y +CONFIG_RT_LWIP_PBUF_POOL_BUFSIZE=1700 + # # Board extended module Drivers # diff --git a/bsp/zynqmp-r5-axu4ev/README.md b/bsp/zynqmp-r5-axu4ev/README.md index a67c9c86ee..8b8cfe2b7b 100644 --- a/bsp/zynqmp-r5-axu4ev/README.md +++ b/bsp/zynqmp-r5-axu4ev/README.md @@ -35,6 +35,7 @@ Each peripheral supporting condition for this BSP is as follows: | UART | Support | UART0 | | TIMER | Support | TTC0 provides system clock | | EMMC | Support | SD0 Controller | +| EMAC | Support | e0 Net Interface | ## Execution Instruction @@ -99,14 +100,31 @@ msh /> This BSP enables EMMC driver and DFS file system by default. If you need to use a file system, you can format and mount it by yourself. +This BSP is enabled and configured with net interface driver and LwIP protocol stack by default, and note the following configuration: + +1. Note that `RT_LWIP_PBUF_NUM` is set to at least 256 + +2. Note that `RT_ LWIP_ MEM_ Alignment` is set to 32. If the version other than lwip 2.0.2 in RTT is used, the `MEM_ALIGNMENT` in `lwipopts.h` needs to be modified manually because the macro is not used in other versions. + ## BSP Migration If you need to ported the BSP to another development board of Xilinx Zynq UltraScale+ MPSOC development platform, it is also convenient. The main modifications are as follows: -1. Memory: `psu_r5_ddr_0_MEM_0` in `zynqmp-r5.ld` (if DDR memory is less than 2G) +1. Memory: `psu_r5_ddr_0_MEM_0` in `zynqmp-r5.ld` and `HEAP_END` in `board.h ` (if DDR memory is less than 2G) 2. Main Frequency: `XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ` in `zynqmp-r5.h` 3. Pin and Frequency of Serial Port: `rxmio`, `txmio` and `XPAR_PSU_UART_0_UART_CLK_FREQ_HZ` in `drv_uart.c` 4. Timer Frequency: `XPAR_PSU_TTC_0_TTC_CLK_FREQ_HZ` in `drv_timer.c` 5. SD Controller: Block device driver initialization in `drv_sdcard.c` +6. Net interface: If the PHY chip used is not in the range of driver support, it may be necessary to realize the rate identification function of the corresponding chip in `xemacpsif_physpeed.c`. You can refer to the corresponding tutorial of Alinx. The parameter macro definition in `xparameters.h` does not need to be modified manually. You can directly copy the `xparameters.h` file of the development board generated in Xilinx Vitis. + +## Attention + +-None + +## Contact + +Maintainer: + +- [Wang Huachen](https://github.com/Wang-Huachen/) \ No newline at end of file diff --git a/bsp/zynqmp-r5-axu4ev/README_zh.md b/bsp/zynqmp-r5-axu4ev/README_zh.md index 2735f9a353..f3c9582dd7 100644 --- a/bsp/zynqmp-r5-axu4ev/README_zh.md +++ b/bsp/zynqmp-r5-axu4ev/README_zh.md @@ -32,6 +32,7 @@ AXU4EV-E 开发板是 芯驿电子科技(上海)有限公司 推出的一款 | UART | 支持 | UART0 | | TIMER | 支持 | TTC0提供系统时钟 | | EMMC | 支持 | SD0控制器 | +| EMAC | 支持 | e0网卡 | ## 使用说明 @@ -107,16 +108,22 @@ msh /> 此 BSP 默认开启了 EMMC 驱动和 DFS 文件系统,如果需要使用文件系统可以自行格式化并挂载。 +此 BSP 默认开启并配置了网卡驱动及lwip协议栈,相关配置需要注意如下几点: + +1. 注意将`RT_LWIP_PBUF_NUM`至少设置为256 +2. 注意将`RT_LWIP_MEM_ALIGNMENT`设置为32。若使用RTT中lwip 2.0.2以外的版本时,由于其他版本未使用该宏,需要手动修改`lwipopts.h`中的`MEM_ALIGNMENT`宏。 + ## 板级移植 如果需要将BSP移植到其他 XILINX Zynq UltraScale+ MPSoCs 开发平台的开发板上也比较方便,主要修改的地方有以下几点: -1. 内存: 如果 DDR memory 小于 2G,需要修改`zynqmp-r5.ld`链接文件中的`psu_r5_ddr_0_MEM_0` +1. 内存: 如果 DDR memory 小于 2G,需要修改`zynqmp-r5.ld`链接文件中的`psu_r5_ddr_0_MEM_0` 以及`board.h`中的`HEAP_END` 2. 主频: `xparameters.h`中的`XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ` 3. 串口引脚和频率:`drv_uart.c`中的`rxmio`, `txmio` 和`xparameters.h`中的`XPAR_PSU_UART_0_UART_CLK_FREQ_HZ` 4. 定时器频率:`xparameters.h`中的`XPAR_PSU_TTC_0_TTC_CLK_FREQ_HZ` 5. SD控制器:`drv_sdcard.c`中的块设备驱动初始化 +6. 网卡驱动:若使用的PHY芯片不在驱动支持范围内,可能需要在`xemacpsif_physpeed.c`中实现相应芯片的速率识别函数,可参考ALINX的相应教程。 以上需要修改的`xparameters.h`中的参数宏定义不需要手动修改,可以直接将Xilinx Vitis中产生的开发板的`xparameters.h`文件复制过来即可。 diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Kconfig b/bsp/zynqmp-r5-axu4ev/drivers/Kconfig index fd16c490f9..5461f7ecf5 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Kconfig +++ b/bsp/zynqmp-r5-axu4ev/drivers/Kconfig @@ -24,6 +24,19 @@ menu "Hardware Drivers Config" bool "Enable SD0 EMMC" default y endif + comment "Please set RT_LWIP_PBUF_NUM is at least 256 if Enable Ethernet!" + comment "Please set RT_LWIP_MEM_ALIGNMENT is at 32 if Enable Ethernet!" + menuconfig BSP_USING_ETH + bool "Enable Ethernet" + default n + select RT_USING_NETDEV + select RT_USING_LWIP + if BSP_USING_ETH + config RT_LWIP_PBUF_POOL_BUFSIZE + int "The size of each pbuf in the pbuf pool" + range 1500 2000 + default 1700 + endif endmenu diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/SConscript b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/SConscript index 03f0e5d26d..58a8169357 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/SConscript +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/SConscript @@ -11,6 +11,9 @@ if GetDepend('BSP_USING_SDIO'): objs = objs + SConscript('sdps_v3_9/SConscript') if GetDepend('RT_USING_PIN'): objs = objs + SConscript('gpiops_v3_7/SConscript') +if GetDepend('BSP_USING_ETH'): + objs = objs + SConscript('emacps_v3_11/SConscript') + objs = objs + SConscript('xemacpsif/SConscript') objs = objs + group diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/SConscript b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/SConscript new file mode 100644 index 0000000000..8e5fc7069e --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/SConscript @@ -0,0 +1,15 @@ +import rtconfig +from building import * + +# get current directory +cwd = GetCurrentDir() +CPPPATH = [cwd] + +# The set of source files associated with this SConscript file. + +src = Glob('*.c') +path = cwd + +group = DefineGroup('ZYNQMP_HAL', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') \ No newline at end of file diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c new file mode 100644 index 0000000000..fb4a6483e9 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c @@ -0,0 +1,480 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps.c +* @addtogroup emacps_v3_11 +* @{ +* +* The XEmacPs driver. Functions in this file are the minimum required functions +* for this driver. See xemacps.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 2.1  srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification and
+*		      64-bit changes.
+* 3.00 kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.0  hk   02/20/15 Added support for jumbo frames. Increase AHB burst.
+*                    Disable extended mode. Perform all 64 bit changes under
+*                    check for arch64.
+* 3.1  hk   08/10/15 Update upper 32 bit tx and rx queue ptr registers
+* 3.5  hk   08/14/17 Update cache coherency information of the interface in
+*                    its config structure.
+* 3.8  hk   09/17/18 Cleanup stale comments.
+* 3.8  mus  11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
+* 3.10 hk   05/16/19 Clear status registers properly in reset
+* 3.11 sd   02/14/20 Add clock support
+*
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xemacps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +void XEmacPs_StubHandler(void); /* Default handler routine */ + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* Initialize a specific XEmacPs instance/driver. The initialization entails: +* - Initialize fields of the XEmacPs instance structure +* - Reset hardware and apply default options +* - Configure the DMA channels +* +* The PHY is setup independently from the device. Use the MII or whatever other +* interface may be present for setup. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param CfgPtr is the device configuration structure containing required +* hardware build data. +* @param EffectiveAddress is the base address of the device. If address +* translation is not utilized, this parameter can be passed in using +* CfgPtr->Config.BaseAddress to specify the physical base address. +* +* @return +* - XST_SUCCESS if initialization was successful +* +******************************************************************************/ +LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr, + UINTPTR EffectiveAddress) +{ + /* Verify arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + + /* Set device base address and ID */ + InstancePtr->Config.DeviceId = CfgPtr->DeviceId; + InstancePtr->Config.BaseAddress = EffectiveAddress; + InstancePtr->Config.IsCacheCoherent = CfgPtr->IsCacheCoherent; +#if defined (XCLOCKING) + InstancePtr->Config.RefClk = CfgPtr->RefClk; +#endif + + /* Set callbacks to an initial stub routine */ + InstancePtr->SendHandler = ((XEmacPs_Handler)((void*)XEmacPs_StubHandler)); + InstancePtr->RecvHandler = ((XEmacPs_Handler)(void*)XEmacPs_StubHandler); + InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void*)XEmacPs_StubHandler); + + /* Reset the hardware and set default options */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + XEmacPs_Reset(InstancePtr); + + return (LONG)(XST_SUCCESS); +} + + +/*****************************************************************************/ +/** +* Start the Ethernet controller as follows: +* - Enable transmitter if XTE_TRANSMIT_ENABLE_OPTION is set +* - Enable receiver if XTE_RECEIVER_ENABLE_OPTION is set +* - Start the SG DMA send and receive channels and enable the device +* interrupt +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return N/A +* +* @note +* Hardware is configured with scatter-gather DMA, the driver expects to start +* the scatter-gather channels and expects that the user has previously set up +* the buffer descriptor lists. +* +* This function makes use of internal resources that are shared between the +* Start, Stop, and Set/ClearOptions functions. So if one task might be setting +* device options while another is trying to start the device, the user is +* required to provide protection of this shared data (typically using a +* semaphore). +* +* This function must not be preempted by an interrupt that may service the +* device. +* +******************************************************************************/ +void XEmacPs_Start(XEmacPs *InstancePtr) +{ + u32 Reg; + + /* Assert bad arguments and conditions */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + +#if defined (XCLOCKING) + if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) { + Xil_ClockEnable(InstancePtr->Config.RefClk); + } +#endif + + /* Start DMA */ + /* When starting the DMA channels, both transmit and receive sides + * need an initialized BD list. + */ + if (InstancePtr->Version == 2) { + Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0); + Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXQBASE_OFFSET, + InstancePtr->RxBdRing.BaseBdAddr); + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXQBASE_OFFSET, + InstancePtr->TxBdRing.BaseBdAddr); + } + + /* clear any existed int status */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, + XEMACPS_IXR_ALL_MASK); + + /* Enable transmitter if not already enabled */ + if ((InstancePtr->Options & (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION)!=0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + if ((!(Reg & XEMACPS_NWCTRL_TXEN_MASK))==TRUE) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, + Reg | (u32)XEMACPS_NWCTRL_TXEN_MASK); + } + } + + /* Enable receiver if not already enabled */ + if ((InstancePtr->Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + if ((!(Reg & XEMACPS_NWCTRL_RXEN_MASK))==TRUE) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, + Reg | (u32)XEMACPS_NWCTRL_RXEN_MASK); + } + } + + /* Enable TX and RX interrupts */ + XEmacPs_IntEnable(InstancePtr, (XEMACPS_IXR_TX_ERR_MASK | + XEMACPS_IXR_RX_ERR_MASK | (u32)XEMACPS_IXR_FRAMERX_MASK | + (u32)XEMACPS_IXR_TXCOMPL_MASK)); + + /* Enable TX Q1 Interrupts */ + if (InstancePtr->Version > 2) + XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK); + + /* Mark as started */ + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; + + return; +} + + +/*****************************************************************************/ +/** +* Gracefully stop the Ethernet MAC as follows: +* - Disable all interrupts from this device +* - Stop DMA channels +* - Disable the tansmitter and receiver +* +* Device options currently in effect are not changed. +* +* This function will disable all interrupts. Default interrupts settings that +* had been enabled will be restored when XEmacPs_Start() is called. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @note +* This function makes use of internal resources that are shared between the +* Start, Stop, SetOptions, and ClearOptions functions. So if one task might be +* setting device options while another is trying to start the device, the user +* is required to provide protection of this shared data (typically using a +* semaphore). +* +* Stopping the DMA channels causes this function to block until the DMA +* operation is complete. +* +******************************************************************************/ +void XEmacPs_Stop(XEmacPs *InstancePtr) +{ + u32 Reg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Disable all interrupts */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET, + XEMACPS_IXR_ALL_MASK); + + /* Disable the receiver & transmitter */ + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); + Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + + /* Mark as stopped */ + InstancePtr->IsStarted = 0U; +#if defined (XCLOCKING) + Xil_ClockDisable(InstancePtr->Config.RefClk); +#endif +} + + +/*****************************************************************************/ +/** +* Perform a graceful reset of the Ethernet MAC. Resets the DMA channels, the +* transmitter, and the receiver. +* +* Steps to reset +* - Stops transmit and receive channels +* - Stops DMA +* - Configure transmit and receive buffer size to default +* - Clear transmit and receive status register and counters +* - Clear all interrupt sources +* - Clear phy (if there is any previously detected) address +* - Clear MAC addresses (1-4) as well as Type IDs and hash value +* +* All options are placed in their default state. Any frames in the +* descriptor lists will remain in the lists. The side effect of doing +* this is that after a reset and following a restart of the device, frames +* were in the list before the reset may be transmitted or received. +* +* The upper layer software is responsible for re-configuring (if necessary) +* and restarting the MAC after the reset. Note also that driver statistics +* are not cleared on reset. It is up to the upper layer software to clear the +* statistics if needed. +* +* When a reset is required, the driver notifies the upper layer software of +* this need through the ErrorHandler callback and specific status codes. +* The upper layer software is responsible for calling this Reset function +* and then re-configuring the device. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +******************************************************************************/ +void XEmacPs_Reset(XEmacPs *InstancePtr) +{ + u32 Reg; + u8 i; + s8 EmacPs_zero_MAC[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Stop the device and reset hardware */ + XEmacPs_Stop(InstancePtr); + InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS; + + InstancePtr->Version = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, 0xFC); + + InstancePtr->Version = (InstancePtr->Version >> 16) & 0xFFF; + + InstancePtr->MaxMtuSize = XEMACPS_MTU; + InstancePtr->MaxFrameSize = XEMACPS_MTU + XEMACPS_HDR_SIZE + + XEMACPS_TRL_SIZE; + InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + + XEMACPS_HDR_VLAN_SIZE; + InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK; + + /* Setup hardware with default values */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, + (XEMACPS_NWCTRL_STATCLR_MASK | + XEMACPS_NWCTRL_MDEN_MASK) & + (u32)(~XEMACPS_NWCTRL_LOOPEN_MASK)); + + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + Reg &= XEMACPS_NWCFG_MDCCLKDIV_MASK; + + Reg = Reg | (u32)XEMACPS_NWCFG_100_MASK | + (u32)XEMACPS_NWCFG_FDEN_MASK | + (u32)XEMACPS_NWCFG_UCASTHASHEN_MASK; + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, Reg); + if (InstancePtr->Version > 2) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET, + (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET) | + XEMACPS_NWCFG_DWIDTH_64_MASK)); + } + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, + (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) + + (((((u32)XEMACPS_RX_BUF_SIZE % + (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << + (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & + (u32)(XEMACPS_DMACR_RXBUF_MASK)) | + (u32)XEMACPS_DMACR_RXSIZE_MASK | + (u32)XEMACPS_DMACR_TXSIZE_MASK); + + + if (InstancePtr->Version > 2) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, + (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET) | +#if defined(__aarch64__) || defined(__arch64__) + (u32)XEMACPS_DMACR_ADDR_WIDTH_64 | +#endif + (u32)XEMACPS_DMACR_INCR16_AHB_BURST)); + } + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET, XEMACPS_SR_ALL_MASK); + + XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_SEND); + if (InstancePtr->Version > 2) + XEmacPs_SetQueuePtr(InstancePtr, 0, 0x01U, (u16)XEMACPS_SEND); + XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_RECV); + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXSR_OFFSET, XEMACPS_SR_ALL_MASK); + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET, + XEMACPS_IXR_ALL_MASK); + + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_ISR_OFFSET); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, + Reg); + + XEmacPs_ClearHash(InstancePtr); + + for (i = 1U; i < 5U; i++) { + (void)XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i); + (void)XEmacPs_SetTypeIdCheck(InstancePtr, 0x00000000U, i); + } + + /* clear all counters */ + for (i = 0U; i < (u8)((XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4U); + i++) { + (void)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_OCTTXL_OFFSET + (u32)(((u32)i) * ((u32)4))); + } + + /* Disable the receiver */ + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + + /* Sync default options with hardware but leave receiver and + * transmitter disabled. They get enabled with XEmacPs_Start() if + * XEMACPS_TRANSMITTER_ENABLE_OPTION and + * XEMACPS_RECEIVER_ENABLE_OPTION are set. + */ + (void)XEmacPs_SetOptions(InstancePtr, InstancePtr->Options & + ~((u32)XEMACPS_TRANSMITTER_ENABLE_OPTION | + (u32)XEMACPS_RECEIVER_ENABLE_OPTION)); + + (void)XEmacPs_ClearOptions(InstancePtr, ~InstancePtr->Options); +} + + +/******************************************************************************/ +/** + * This is a stub for the asynchronous callbacks. The stub is here in case the + * upper layer forgot to set the handler(s). On initialization, all handlers are + * set to this callback. It is considered an error for this handler to be + * invoked. + * + ******************************************************************************/ +void XEmacPs_StubHandler(void) +{ + Xil_AssertVoidAlways(); +} + +/*****************************************************************************/ +/** +* This function sets the start address of the transmit/receive buffer queue. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param QPtr is the address of the Queue to be written +* @param QueueNum is the Buffer Queue Index +* @param Direction indicates Transmit/Receive +* +* @note +* The buffer queue addresses has to be set before starting the transfer, so +* this function has to be called in prior to XEmacPs_Start() +* +******************************************************************************/ +void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum, + u16 Direction) +{ + /* Assert bad arguments and conditions */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* If already started, then there is nothing to do */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + return; + } + + if (QueueNum == 0x00U) { + if (Direction == XEMACPS_SEND) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXQBASE_OFFSET, + (QPtr & ULONG64_LO_MASK)); + } else { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXQBASE_OFFSET, + (QPtr & ULONG64_LO_MASK)); + } + } + else { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXQ1BASE_OFFSET, + (QPtr & ULONG64_LO_MASK)); + } +#ifdef __aarch64__ + if (Direction == XEMACPS_SEND) { + /* Set the MSB of TX Queue start address */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_MSBBUF_TXQBASE_OFFSET, + (u32)((QPtr & ULONG64_HI_MASK) >> 32U)); + } else { + /* Set the MSB of RX Queue start address */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_MSBBUF_RXQBASE_OFFSET, + (u32)((QPtr & ULONG64_HI_MASK) >> 32U)); + } +#endif +} +/** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h new file mode 100644 index 0000000000..d3c5b6349f --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h @@ -0,0 +1,836 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** + * + * @file xemacps.h +* @addtogroup emacps_v3_11 +* @{ +* @details + * + * The Xilinx Embedded Processor Block Ethernet driver. + * + * For a full description of XEMACPS features, please see the hardware spec. + * This driver supports the following features: + * - Memory mapped access to host interface registers + * - Statistics counter registers for RMON/MIB + * - API for interrupt driven frame transfers for hardware configured DMA + * - Virtual memory support + * - Unicast, broadcast, and multicast receive address filtering + * - Full and half duplex operation + * - Automatic PAD & FCS insertion and stripping + * - Flow control + * - Support up to four 48bit addresses + * - Address checking for four specific 48bit addresses + * - VLAN frame support + * - Pause frame support + * - Large frame support up to 1536 bytes + * - Checksum offload + * + * Driver Description + * + * The device driver enables higher layer software (e.g., an application) to + * communicate to the XEmacPs. The driver handles transmission and reception + * of Ethernet frames, as well as configuration and control. No pre or post + * processing of frame data is performed. The driver does not validate the + * contents of an incoming frame in addition to what has already occurred in + * hardware. + * A single device driver can support multiple devices even when those devices + * have significantly different configurations. + * + * Initialization & Configuration + * + * The XEmacPs_Config structure is used by the driver to configure itself. + * This configuration structure is typically created by the tool-chain based + * on hardware build properties. + * + * The driver instance can be initialized in + * + * - XEmacPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddress): Uses a + * configuration structure provided by the caller. If running in a system + * with address translation, the provided virtual memory base address + * replaces the physical address present in the configuration structure. + * + * The device supports DMA only as current development plan. No FIFO mode is + * supported. The driver expects to start the DMA channels and expects that + * the user has set up the buffer descriptor lists. + * + * Interrupts and Asynchronous Callbacks + * + * The driver has no dependencies on the interrupt controller. When an + * interrupt occurs, the handler will perform a small amount of + * housekeeping work, determine the source of the interrupt, and call the + * appropriate callback function. All callbacks are registered by the user + * level application. + * + * Virtual Memory + * + * All virtual to physical memory mappings must occur prior to accessing the + * driver API. + * + * For DMA transactions, user buffers supplied to the driver must be in terms + * of their physical address. + * + * DMA + * + * The DMA engine uses buffer descriptors (BDs) to describe Ethernet frames. + * These BDs are typically chained together into a list the hardware follows + * when transferring data in and out of the packet buffers. Each BD describes + * a memory region containing either a full or partial Ethernet packet. + * + * Interrupt coalescing is not supported from this built-in DMA engine. + * + * This API requires the user to understand how the DMA operates. The + * following paragraphs provide some explanation, but the user is encouraged + * to read documentation in xemacps_bdring.h as well as study example code + * that accompanies this driver. + * + * The API is designed to get BDs to and from the DMA engine in the most + * efficient means possible. The first step is to establish a memory region + * to contain all BDs for a specific channel. This is done with + * XEmacPs_BdRingCreate(). This function sets up a BD ring that hardware will + * follow as BDs are processed. The ring will consist of a user defined number + * of BDs which will all be partially initialized. For example on the transmit + * channel, the driver will initialize all BDs' so that they are configured + * for transmit. The more fields that can be permanently setup at + * initialization, then the fewer accesses will be needed to each BD while + * the DMA engine is in operation resulting in better throughput and CPU + * utilization. The best case initialization would require the user to set + * only a frame buffer address and length prior to submitting the BD to the + * engine. + * + * BDs move through the engine with the help of functions + * XEmacPs_BdRingAlloc(), XEmacPs_BdRingToHw(), XEmacPs_BdRingFromHw(), + * and XEmacPs_BdRingFree(). + * All these functions handle BDs that are in place. That is, there are no + * copies of BDs kept anywhere and any BD the user interacts with is an actual + * BD from the same ring hardware accesses. + * + * BDs in the ring go through a series of states as follows: + * 1. Idle. The driver controls BDs in this state. + * 2. The user has data to transfer. XEmacPs_BdRingAlloc() is called to + * reserve BD(s). Once allocated, the user may setup the BD(s) with + * frame buffer address, length, and other attributes. The user controls + * BDs in this state. + * 3. The user submits BDs to the DMA engine with XEmacPs_BdRingToHw. BDs + * in this state are either waiting to be processed by hardware, are in + * process, or have been processed. The DMA engine controls BDs in this + * state. + * 4. Processed BDs are retrieved with XEmacEpv_BdRingFromHw() by the + * user. Once retrieved, the user can examine each BD for the outcome of + * the DMA transfer. The user controls BDs in this state. After examining + * the BDs the user calls XEmacPs_BdRingFree() which places the BDs back + * into state 1. + * + * Each of the four BD accessor functions operate on a set of BDs. A set is + * defined as a segment of the BD ring consisting of one or more BDs. The user + * views the set as a pointer to the first BD along with the number of BDs for + * that set. The set can be navigated by using macros XEmacPs_BdNext(). The + * user must exercise extreme caution when changing BDs in a set as there is + * nothing to prevent doing a mBdNext past the end of the set and modifying a + * BD out of bounds. + * + * XEmacPs_BdRingAlloc() + XEmacPs_BdRingToHw(), as well as + * XEmacPs_BdRingFromHw() + XEmacPs_BdRingFree() are designed to be used in + * tandem. The same BD set retrieved with BdRingAlloc should be the same one + * provided to hardware with BdRingToHw. Same goes with BdRingFromHw and + * BdRIngFree. + * + * Alignment & Data Cache Restrictions + * + * Due to the design of the hardware, all RX buffers, BDs need to be 4-byte + * aligned. Please reference xemacps_bd.h for cache related macros. + * + * DMA Tx: + * + * - If frame buffers exist in cached memory, then they must be flushed + * prior to committing them to hardware. + * + * DMA Rx: + * + * - If frame buffers exist in cached memory, then the cache must be + * invalidated for the memory region containing the frame prior to data + * access + * + * Both cache invalidate/flush are taken care of in driver code. + * + * Buffer Copying + * + * The driver is designed for a zero-copy buffer scheme. That is, the driver + * will not copy buffers. This avoids potential throughput bottlenecks within + * the driver. If byte copying is required, then the transfer will take longer + * to complete. + * + * Checksum Offloading + * + * The Embedded Processor Block Ethernet can be configured to perform IP, TCP + * and UDP checksum offloading in both receive and transmit directions. + * + * IP packets contain a 16-bit checksum field, which is the 16-bit 1s + * complement of the 1s complement sum of all 16-bit words in the header. + * TCP and UDP packets contain a 16-bit checksum field, which is the 16-bit + * 1s complement of the 1s complement sum of all 16-bit words in the header, + * the data and a conceptual pseudo header. + * + * To calculate these checksums in software requires each byte of the packet + * to be read. For TCP and UDP this can use a large amount of processing power. + * Offloading the checksum calculation to hardware can result in significant + * performance improvements. + * + * The transmit checksum offload is only available to use DMA in packet buffer + * mode. This is because the complete frame to be transmitted must be read + * into the packet buffer memory before the checksum can be calculated and + * written to the header at the beginning of the frame. + * + * For IP, TCP or UDP receive checksum offload to be useful, the operating + * system containing the protocol stack must be aware that this offload is + * available so that it can make use of the fact that the hardware has verified + * the checksum. + * + * When receive checksum offloading is enabled in the hardware, the IP header + * checksum is checked, where the packet meets the following criteria: + * + * 1. If present, the VLAN header must be four octets long and the CFI bit + * must not be set. + * 2. Encapsulation must be RFC 894 Ethernet Type Encoding or RFC 1042 SNAP + * encoding. + * 3. IP v4 packet. + * 4. IP header is of a valid length. + * 5. Good IP header checksum. + * 6. No IP fragmentation. + * 7. TCP or UDP packet. + * + * When an IP, TCP or UDP frame is received, the receive buffer descriptor + * gives an indication if the hardware was able to verify the checksums. + * There is also an indication if the frame had SNAP encapsulation. These + * indication bits will replace the type ID match indication bits when the + * receive checksum offload is enabled. + * + * If any of the checksums are verified incorrect by the hardware, the packet + * is discarded and the appropriate statistics counter incremented. + * + * PHY Interfaces + * + * RGMII 1.3 is the only interface supported. + * + * Asserts + * + * Asserts are used within all Xilinx drivers to enforce constraints on + * parameters. Asserts can be turned off on a system-wide basis by defining, + * at compile time, the NDEBUG identifier. By default, asserts are turned on + * and it is recommended that users leave asserts on during development. For + * deployment use -DNDEBUG compiler switch to remove assert code. + * + * @note + * + * Xilinx drivers are typically composed of two parts, one is the driver + * and the other is the adapter. The driver is independent of OS and processor + * and is intended to be highly portable. The adapter is OS-specific and + * facilitates communication between the driver and an OS. + * This driver is intended to be RTOS and processor independent. Any needs for + * dynamic memory management, threads or thread mutual exclusion, or cache + * control must be satisfied bythe layer above this driver. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wsy  01/10/10 First release
+ * 1.00a asa  11/21/11 The function XEmacPs_BdRingFromHwTx in file
+ *		       xemacps_bdring.c is modified. Earlier it was checking for
+ *		       "BdLimit"(passed argument) number of BDs for finding out
+ *		       which BDs are successfully processed. Now one more check
+ *		       is added. It looks for BDs till the current BD pointer
+ *		       reaches HwTail. By doing this processing time is saved.
+ * 1.00a asa  01/24/12 The function XEmacPs_BdRingFromHwTx in file
+ *		       xemacps_bdring.c is modified. Now start of packet is
+ *		       searched for returning the number of BDs processed.
+ * 1.02a asa  11/05/12 Added a new API for deleting an entry from the HASH
+ *		       registers. Added a new API to set the bust length.
+ *		       Added some new hash-defines.
+ * 1.03a asa  01/23/12 Fix for CR #692702 which updates error handling for
+ *		       Rx errors. Under heavy Rx traffic, there will be a large
+ *		       number of errors related to receive buffer not available.
+ *		       Because of a HW bug (SI #692601), under such heavy errors,
+ *		       the Rx data path can become unresponsive. To reduce the
+ *		       probabilities for hitting this HW bug, the SW writes to
+ *		       bit 18 to flush a packet from Rx DPRAM immediately. The
+ *		       changes for it are done in the function
+ *		       XEmacPs_IntrHandler.
+ * 1.05a asa  09/23/13 Cache operations on BDs are not required and hence
+ *		       removed. It is expected that all BDs are allocated in
+ *		       from uncached area.
+ * 1.06a asa  11/02/13 Changed the value for XEMACPS_RXBUF_LEN_MASK from 0x3fff
+ *				to 0x1fff. This fixes the CR#744902.
+ *			  Made changes in example file xemacps_example.h to fix compilation
+ *			  issues with iarcc compiler.
+ * 2.0   adk  10/12/13 Updated as per the New Tcl API's
+ * 2.1   adk  11/08/14 Fixed the CR#811288. Changes are made in the driver tcl file.
+ * 2.1   bss  09/08/14 Modified driver tcl to fix CR#820349 to export phy
+ *		       address in xparameters.h when GMII to RGMII converter
+ *		       is present in hw.
+ * 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification and 64-bit
+ *		       changes.
+ * 2.2   adk  29/10/14 Fixed CR#827686 when PCS/PMA core is configured with
+ *                    1000BASE-X mode export proper values to the xparameters.h
+ *                    file. Changes are made in the driver tcl file.
+ * 3.0   adk  08/1/15  Don't include gem in peripheral test when gem is
+ *                    configured with PCS/PMA Core. Changes are made in the
+ *		       test app tcl(CR:827686).
+ * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+ * 3.0   hk   03/18/15 Added support for jumbo frames. Increase AHB burst.
+ *                     Disable extended mode. Perform all 64 bit changes under
+ *                     check for arch64.
+ *                     Remove "used bit set" from TX error interrupt masks.
+ * 3.1   hk   07/27/15 Do not call error handler with '0' error code when
+ *                     there is no error. CR# 869403
+ *            08/10/15 Update upper 32 bit tx and rx queue ptr registers.
+ * 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
+ * 3.4   ms   01/23/17 Modified xil_printf statement in main function for all
+ *                     examples to ensure that "Successfully ran" and "Failed"
+ *                     strings are available in all examples. This is a fix
+ *                     for CR-965028.
+ *       ms   03/17/17 Modified text file in examples folder for doxygen
+ *                     generation.
+ *       ms   04/05/17 Added tabspace for return statements in functions of
+ *                     xemacps_ieee1588_example.c for proper documentation
+ *                     while generating doxygen.
+ * 3.5   hk   08/14/17 Update cache coherency information of the interface in
+ *                     its config structure.
+ * 3.6   rb   09/08/17 HwCnt variable (in XEmacPs_BdRing structure) is
+ *		       changed to volatile.
+ *		       Add API XEmacPs_BdRingPtrReset() to reset pointers
+ * 3.8   hk   07/19/18 Fixed CPP, GCC and doxygen warnings - CR-1006327
+ *	 hk   09/17/18 Fix PTP interrupt masks and cleanup comments.
+ * 3.9   hk   01/23/19 Add RX watermark support
+ * 3.11  sd   02/14/20 Add clock support
+ *
+ * 
+ * + ****************************************************************************/ + +#ifndef XEMACPS_H /* prevent circular inclusions */ +#define XEMACPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xemacps_hw.h" +#include "xemacps_bd.h" +#include "xemacps_bdring.h" +#if defined (XCLOCKING) +#include "xil_clocking.h" +#endif + +/************************** Constant Definitions ****************************/ + +/* + * Device information + */ +#define XEMACPS_DEVICE_NAME "xemacps" +#define XEMACPS_DEVICE_DESC "Xilinx PS 10/100/1000 MAC" + + +/** @name Configuration options + * + * Device configuration options. See the XEmacPs_SetOptions(), + * XEmacPs_ClearOptions() and XEmacPs_GetOptions() for information on how to + * use options. + * + * The default state of the options are noted and are what the device and + * driver will be set to after calling XEmacPs_Reset() or + * XEmacPs_Initialize(). + * + * @{ + */ + +#define XEMACPS_PROMISC_OPTION 0x00000001U +/**< Accept all incoming packets. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_FRAME1536_OPTION 0x00000002U +/**< Frame larger than 1516 support for Tx & Rx. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_VLAN_OPTION 0x00000004U +/**< VLAN Rx & Tx frame support. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_FLOW_CONTROL_OPTION 0x00000010U +/**< Enable recognition of flow control frames on Rx + * This option defaults to enabled (set) */ + +#define XEMACPS_FCS_STRIP_OPTION 0x00000020U +/**< Strip FCS and PAD from incoming frames. Note: PAD from VLAN frames is not + * stripped. + * This option defaults to enabled (set) */ + +#define XEMACPS_FCS_INSERT_OPTION 0x00000040U +/**< Generate FCS field and add PAD automatically for outgoing frames. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_LENTYPE_ERR_OPTION 0x00000080U +/**< Enable Length/Type error checking for incoming frames. When this option is + * set, the MAC will filter frames that have a mismatched type/length field + * and if XEMACPS_REPORT_RXERR_OPTION is set, the user is notified when these + * types of frames are encountered. When this option is cleared, the MAC will + * allow these types of frames to be received. + * + * This option defaults to disabled (cleared) */ + +#define XEMACPS_TRANSMITTER_ENABLE_OPTION 0x00000100U +/**< Enable the transmitter. + * This option defaults to enabled (set) */ + +#define XEMACPS_RECEIVER_ENABLE_OPTION 0x00000200U +/**< Enable the receiver + * This option defaults to enabled (set) */ + +#define XEMACPS_BROADCAST_OPTION 0x00000400U +/**< Allow reception of the broadcast address + * This option defaults to enabled (set) */ + +#define XEMACPS_MULTICAST_OPTION 0x00000800U +/**< Allows reception of multicast addresses programmed into hash + * This option defaults to disabled (clear) */ + +#define XEMACPS_RX_CHKSUM_ENABLE_OPTION 0x00001000U +/**< Enable the RX checksum offload + * This option defaults to enabled (set) */ + +#define XEMACPS_TX_CHKSUM_ENABLE_OPTION 0x00002000U +/**< Enable the TX checksum offload + * This option defaults to enabled (set) */ + +#define XEMACPS_JUMBO_ENABLE_OPTION 0x00004000U +#define XEMACPS_SGMII_ENABLE_OPTION 0x00008000U + +#define XEMACPS_DEFAULT_OPTIONS \ + ((u32)XEMACPS_FLOW_CONTROL_OPTION | \ + (u32)XEMACPS_FCS_INSERT_OPTION | \ + (u32)XEMACPS_FCS_STRIP_OPTION | \ + (u32)XEMACPS_BROADCAST_OPTION | \ + (u32)XEMACPS_LENTYPE_ERR_OPTION | \ + (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION | \ + (u32)XEMACPS_RECEIVER_ENABLE_OPTION | \ + (u32)XEMACPS_RX_CHKSUM_ENABLE_OPTION | \ + (u32)XEMACPS_TX_CHKSUM_ENABLE_OPTION) + +/**< Default options set when device is initialized or reset */ +/*@}*/ + +/** @name Callback identifiers + * + * These constants are used as parameters to XEmacPs_SetHandler() + * @{ + */ +#define XEMACPS_HANDLER_DMASEND 1U +#define XEMACPS_HANDLER_DMARECV 2U +#define XEMACPS_HANDLER_ERROR 3U +/*@}*/ + +/* Constants to determine the configuration of the hardware device. They are + * used to allow the driver to verify it can operate with the hardware. + */ +#define XEMACPS_MDIO_DIV_DFT MDC_DIV_32 /**< Default MDIO clock divisor */ + +/* The next few constants help upper layers determine the size of memory + * pools used for Ethernet buffers and descriptor lists. + */ +#define XEMACPS_MAC_ADDR_SIZE 6U /* size of Ethernet header */ + +#define XEMACPS_MTU 1500U /* max MTU size of Ethernet frame */ +#define XEMACPS_MTU_JUMBO 10240U /* max MTU size of jumbo frame */ +#define XEMACPS_HDR_SIZE 14U /* size of Ethernet header */ +#define XEMACPS_HDR_VLAN_SIZE 18U /* size of Ethernet header with VLAN */ +#define XEMACPS_TRL_SIZE 4U /* size of Ethernet trailer (FCS) */ +#define XEMACPS_MAX_FRAME_SIZE (XEMACPS_MTU + XEMACPS_HDR_SIZE + \ + XEMACPS_TRL_SIZE) +#define XEMACPS_MAX_VLAN_FRAME_SIZE (XEMACPS_MTU + XEMACPS_HDR_SIZE + \ + XEMACPS_HDR_VLAN_SIZE + XEMACPS_TRL_SIZE) +#define XEMACPS_MAX_VLAN_FRAME_SIZE_JUMBO (XEMACPS_MTU_JUMBO + XEMACPS_HDR_SIZE + \ + XEMACPS_HDR_VLAN_SIZE + XEMACPS_TRL_SIZE) + +/* DMACR Bust length hash defines */ + +#define XEMACPS_SINGLE_BURST 0x00000001 +#define XEMACPS_4BYTE_BURST 0x00000004 +#define XEMACPS_8BYTE_BURST 0x00000008 +#define XEMACPS_16BYTE_BURST 0x00000010 + + +/**************************** Type Definitions ******************************/ +/** @name Typedefs for callback functions + * + * These callbacks are invoked in interrupt context. + * @{ + */ +/** + * Callback invoked when frame(s) have been sent or received in interrupt + * driven DMA mode. To set the send callback, invoke XEmacPs_SetHandler(). + * + * @param CallBackRef is user data assigned when the callback was set. + * + * @note + * See xemacps_hw.h for bitmasks definitions and the device hardware spec for + * further information on their meaning. + * + */ +typedef void (*XEmacPs_Handler) (void *CallBackRef); + +/** + * Callback when an asynchronous error occurs. To set this callback, invoke + * XEmacPs_SetHandler() with XEMACPS_HANDLER_ERROR in the HandlerType + * parameter. + * + * @param CallBackRef is user data assigned when the callback was set. + * @param Direction defines either receive or transmit error(s) has occurred. + * @param ErrorWord definition varies with Direction + * + */ +typedef void (*XEmacPs_ErrHandler) (void *CallBackRef, u8 Direction, + u32 ErrorWord); + +/*@}*/ + +/** + * This typedef contains configuration information for a device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddress;/**< Physical base address of IPIF registers */ + u8 IsCacheCoherent; /**< Applicable only to A53 in EL1 mode; + * describes whether Cache Coherent or not */ +#if defined (XCLOCKING) + u32 RefClk; /**< Input clock */ +#endif +} XEmacPs_Config; + + +/** + * The XEmacPs driver instance data. The user is required to allocate a + * structure of this type for every XEmacPs device in the system. A pointer + * to a structure of this type is then passed to the driver API functions. + */ +typedef struct XEmacPs_Instance { + XEmacPs_Config Config; /* Hardware configuration */ + u32 IsStarted; /* Device is currently started */ + u32 IsReady; /* Device is initialized and ready */ + u32 Options; /* Current options word */ + + XEmacPs_BdRing TxBdRing; /* Transmit BD ring */ + XEmacPs_BdRing RxBdRing; /* Receive BD ring */ + + XEmacPs_Handler SendHandler; + XEmacPs_Handler RecvHandler; + void *SendRef; + void *RecvRef; + + XEmacPs_ErrHandler ErrorHandler; + void *ErrorRef; + u32 Version; + u32 RxBufMask; + u32 MaxMtuSize; + u32 MaxFrameSize; + u32 MaxVlanFrameSize; + +} XEmacPs; + + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* Retrieve the Tx ring object. This object can be used in the various Ring +* API functions. +* +* @param InstancePtr is the DMA channel to operate on. +* +* @return TxBdRing attribute +* +* @note +* C-style signature: +* XEmacPs_BdRing XEmacPs_GetTxRing(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_GetTxRing(InstancePtr) ((InstancePtr)->TxBdRing) + +/****************************************************************************/ +/** +* Retrieve the Rx ring object. This object can be used in the various Ring +* API functions. +* +* @param InstancePtr is the DMA channel to operate on. +* +* @return RxBdRing attribute +* +* @note +* C-style signature: +* XEmacPs_BdRing XEmacPs_GetRxRing(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_GetRxRing(InstancePtr) ((InstancePtr)->RxBdRing) + +/****************************************************************************/ +/** +* +* Enable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to enable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntEnable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntEnable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_IER_OFFSET, \ + ((Mask) & XEMACPS_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* Disable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to disable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntDisable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntDisable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_IDR_OFFSET, \ + ((Mask) & XEMACPS_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* Enable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to enable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntQ1Enable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntQ1Enable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_INTQ1_IER_OFFSET, \ + ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* Disable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to disable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntDisable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntQ1Disable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_INTQ1_IDR_OFFSET, \ + ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* This macro triggers trasmit circuit to send data currently in TX buffer(s). +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return +* +* @note +* +* Signature: void XEmacPs_Transmit(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_Transmit(InstancePtr) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_NWCTRL_OFFSET, \ + (XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK)) + +/****************************************************************************/ +/** +* +* This macro determines if the device is configured with checksum offloading +* on the receive channel +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return +* +* Boolean TRUE if the device is configured with checksum offloading, or +* FALSE otherwise. +* +* @note +* +* Signature: u32 XEmacPs_IsRxCsum(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_IsRxCsum(InstancePtr) \ + ((XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_NWCFG_OFFSET) & XEMACPS_NWCFG_RXCHKSUMEN_MASK) != 0U \ + ? TRUE : FALSE) + +/****************************************************************************/ +/** +* +* This macro determines if the device is configured with checksum offloading +* on the transmit channel +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return +* +* Boolean TRUE if the device is configured with checksum offloading, or +* FALSE otherwise. +* +* @note +* +* Signature: u32 XEmacPs_IsTxCsum(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_IsTxCsum(InstancePtr) \ + ((XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_DMACR_OFFSET) & XEMACPS_DMACR_TCPCKSUM_MASK) != 0U \ + ? TRUE : FALSE) + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* This macro sets RX watermark register. +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* @param High is the non-zero RX high watermark value. When SRAM fill level +* is above this, a pause frame will be sent. +* @param Low is the non-zero RX low watermark value. When SRAM fill level +* is below this, a zero length pause frame will be sent IF the last +* pause frame sent was non-zero. +* +* @return None +* +* @note +* +* Signature: void XEmacPs_SetRXWatermark(XEmacPs *InstancePtr, u16 High, +* u16 Low) +* +*****************************************************************************/ +#define XEmacPs_SetRXWatermark(InstancePtr, High, Low) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_RXWATERMARK_OFFSET, \ + (High & XEMACPS_RXWM_HIGH_MASK) | \ + ((Low << XEMACPS_RXWM_LOW_SHFT_MSK) & XEMACPS_RXWM_LOW_MASK) |) + +/****************************************************************************/ +/** +* +* This macro gets RX watermark register. +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return RX watermark register value +* +* @note +* +* Signature: void XEmacPs_GetRXWatermark(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_GetRXWatermark(InstancePtr) \ + XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_RXWATERMARK_OFFSET) +/* + * Initialization functions in xemacps.c + */ +LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config *CfgPtr, + UINTPTR EffectiveAddress); +void XEmacPs_Start(XEmacPs *InstancePtr); +void XEmacPs_Stop(XEmacPs *InstancePtr); +void XEmacPs_Reset(XEmacPs *InstancePtr); +void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum, + u16 Direction); + +/* + * Lookup configuration in xemacps_sinit.c + */ +XEmacPs_Config *XEmacPs_LookupConfig(u16 DeviceId); + +/* + * Interrupt-related functions in xemacps_intr.c + * DMA only and FIFO is not supported. This DMA does not support coalescing. + */ +LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType, + void *FuncPointer, void *CallBackRef); +void XEmacPs_IntrHandler(void *XEmacPsPtr); + +/* + * MAC configuration/control functions in XEmacPs_control.c + */ +LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options); +LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options); +u32 XEmacPs_GetOptions(XEmacPs *InstancePtr); + +LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index); +LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr); +void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index); + +LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr); +void XEmacPs_ClearHash(XEmacPs *InstancePtr); +void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr); + +void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, + XEmacPs_MdcDiv Divisor); +void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed); +u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr); +LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, + u32 RegisterNum, u16 *PhyDataPtr); +LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress, + u32 RegisterNum, u16 PhyData); +LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index); + +LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr); +void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h new file mode 100644 index 0000000000..a757322615 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h @@ -0,0 +1,762 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xemacps_bd.h +* @addtogroup emacps_v3_11 +* @{ + * + * This header provides operations to manage buffer descriptors in support + * of scatter-gather DMA. + * + * The API exported by this header defines abstracted macros that allow the + * user to read/write specific BD fields. + * + * Buffer Descriptors + * + * A buffer descriptor (BD) defines a DMA transaction. The macros defined by + * this header file allow access to most fields within a BD to tailor a DMA + * transaction according to user and hardware requirements. See the hardware + * IP DMA spec for more information on BD fields and how they affect transfers. + * + * The XEmacPs_Bd structure defines a BD. The organization of this structure + * is driven mainly by the hardware for use in scatter-gather DMA transfers. + * + * Performance + * + * Limiting I/O to BDs can improve overall performance of the DMA channel. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wsy  01/10/10 First release
+ * 2.1   srt  07/15/14 Add support for Zynq Ultrascale MP GEM specification
+ *                     and 64-bit changes.
+ * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+ * 3.0   hk   02/20/15 Added support for jumbo frames.
+ *                     Disable extended mode. Perform all 64 bit changes under
+ *                     check for arch64.
+ * 3.2   hk   11/18/15 Change BD typedef and number of words.
+ * 3.8   hk   08/18/18 Remove duplicate definition of XEmacPs_BdSetLength
+ * 3.8   mus  11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
+ *
+ * 
+ * + * *************************************************************************** + */ + +#ifndef XEMACPS_BD_H /* prevent circular inclusions */ +#define XEMACPS_BD_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ +#ifdef __aarch64__ +/* Minimum BD alignment */ +#define XEMACPS_DMABD_MINIMUM_ALIGNMENT 64U +#define XEMACPS_BD_NUM_WORDS 4U +#else +/* Minimum BD alignment */ +#define XEMACPS_DMABD_MINIMUM_ALIGNMENT 4U +#define XEMACPS_BD_NUM_WORDS 2U +#endif + +/** + * The XEmacPs_Bd is the type for buffer descriptors (BDs). + */ +typedef u32 XEmacPs_Bd[XEMACPS_BD_NUM_WORDS]; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * Zero out BD fields + * + * @param BdPtr is the BD pointer to operate on + * + * @return Nothing + * + * @note + * C-style signature: + * void XEmacPs_BdClear(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClear(BdPtr) \ + memset((BdPtr), 0, sizeof(XEmacPs_Bd)) + +/****************************************************************************/ +/** +* +* Read the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to read +* @param Offset is the word offset to be read +* +* @return The 32-bit value of the field +* +* @note +* C-style signature: +* u32 XEmacPs_BdRead(UINTPTR BaseAddress, UINTPTR Offset) +* +*****************************************************************************/ +#define XEmacPs_BdRead(BaseAddress, Offset) \ + (*(u32 *)((UINTPTR)((void*)(BaseAddress)) + (u32)(Offset))) + +/****************************************************************************/ +/** +* +* Write the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to write +* @param Offset is the word offset to be written +* @param Data is the 32-bit value to write to the field +* +* @return None. +* +* @note +* C-style signature: +* void XEmacPs_BdWrite(UINTPTR BaseAddress, UINTPTR Offset, UINTPTR Data) +* +*****************************************************************************/ +#define XEmacPs_BdWrite(BaseAddress, Offset, Data) \ + (*(u32 *)((UINTPTR)(void*)(BaseAddress) + (u32)(Offset)) = (u32)(Data)) + +/*****************************************************************************/ +/** + * Set the BD's Address field (word 0). + * + * @param BdPtr is the BD pointer to operate on + * @param Addr is the value to write to BD's status field. + * + * @note : + * + * C-style signature: + * void XEmacPs_BdSetAddressTx(XEmacPs_Bd* BdPtr, UINTPTR Addr) + * + *****************************************************************************/ +#if defined(__aarch64__) || defined(__arch64__) +#define XEmacPs_BdSetAddressTx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + (u32)((Addr) & ULONG64_LO_MASK)); \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET, \ + (u32)(((Addr) & ULONG64_HI_MASK) >> 32U)); +#else +#define XEmacPs_BdSetAddressTx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, (u32)(Addr)) +#endif + +/*****************************************************************************/ +/** + * Set the BD's Address field (word 0). + * + * @param BdPtr is the BD pointer to operate on + * @param Addr is the value to write to BD's status field. + * + * @note : Due to some bits are mixed within receive BD's address field, + * read-modify-write is performed. + * + * C-style signature: + * void XEmacPs_BdSetAddressRx(XEmacPs_Bd* BdPtr, UINTPTR Addr) + * + *****************************************************************************/ +#ifdef __aarch64__ +#define XEmacPs_BdSetAddressRx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + ~XEMACPS_RXBUF_ADD_MASK) | ((u32)((Addr) & ULONG64_LO_MASK)))); \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET, \ + (u32)(((Addr) & ULONG64_HI_MASK) >> 32U)); +#else +#define XEmacPs_BdSetAddressRx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + ~XEMACPS_RXBUF_ADD_MASK) | (UINTPTR)(Addr))) +#endif + +/*****************************************************************************/ +/** + * Set the BD's Status field (word 1). + * + * @param BdPtr is the BD pointer to operate on + * @param Data is the value to write to BD's status field. + * + * @note + * C-style signature: + * void XEmacPs_BdSetStatus(XEmacPs_Bd* BdPtr, UINTPTR Data) + * + *****************************************************************************/ +#define XEmacPs_BdSetStatus(BdPtr, Data) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | (Data)) + + +/*****************************************************************************/ +/** + * Retrieve the BD's Packet DMA transfer status word (word 1). + * + * @param BdPtr is the BD pointer to operate on + * + * @return Status word + * + * @note + * C-style signature: + * u32 XEmacPs_BdGetStatus(XEmacPs_Bd* BdPtr) + * + * Due to the BD bit layout differences in transmit and receive. User's + * caution is required. + *****************************************************************************/ +#define XEmacPs_BdGetStatus(BdPtr) \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) + + +/*****************************************************************************/ +/** + * Get the address (bits 0..31) of the BD's buffer address (word 0) + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetBufAddr(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#if defined(__aarch64__) || defined(__arch64__) +#define XEmacPs_BdGetBufAddr(BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) | \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET)) << 32U) +#else +#define XEmacPs_BdGetBufAddr(BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET)) +#endif + +/*****************************************************************************/ +/** + * Set transfer length in bytes for the given BD. The length must be set each + * time a BD is submitted to hardware. + * + * @param BdPtr is the BD pointer to operate on + * @param LenBytes is the number of bytes to transfer. + * + * @note + * C-style signature: + * void XEmacPs_BdSetLength(XEmacPs_Bd* BdPtr, u32 LenBytes) + * + *****************************************************************************/ +#define XEmacPs_BdSetLength(BdPtr, LenBytes) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_LEN_MASK) | (LenBytes))) + + +/*****************************************************************************/ +/** + * Retrieve the BD length field. + * + * For Tx channels, the returned value is the same as that written with + * XEmacPs_BdSetLength(). + * + * For Rx channels, the returned value is the size of the received packet. + * + * @param BdPtr is the BD pointer to operate on + * + * @return Length field processed by hardware or set by + * XEmacPs_BdSetLength(). + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetLength(XEmacPs_Bd* BdPtr) + * XEAMCPS_RXBUF_LEN_MASK is same as XEMACPS_TXBUF_LEN_MASK. + * + *****************************************************************************/ +#define XEmacPs_BdGetLength(BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_LEN_MASK) + +/*****************************************************************************/ +/** + * Retrieve the RX frame size. + * + * The returned value is the size of the received packet. + * This API supports jumbo frame sizes if enabled. + * + * @param InstancePtr is the pointer to XEmacps instance + * + * @param BdPtr is the BD pointer to operate on + * + * @return Length field processed by hardware or set by + * XEmacPs_BdSetLength(). + * + * @note + * C-style signature: + * UINTPTR XEmacPs_GetRxFrameSize(XEmacPs* InstancePtr, XEmacPs_Bd* BdPtr) + * RxBufMask is dependent on whether jumbo is enabled or not. + * + *****************************************************************************/ +#define XEmacPs_GetRxFrameSize(InstancePtr, BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + (InstancePtr)->RxBufMask) + +/*****************************************************************************/ +/** + * Test whether the given BD has been marked as the last BD of a packet. + * + * @param BdPtr is the BD pointer to operate on + * + * @return TRUE if BD represents the "Last" BD of a packet, FALSE otherwise + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsLast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsLast(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_EOF_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Tell the DMA engine that the given transmit BD marks the end of the current + * packet to be processed. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetLast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdSetLast(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_LAST_MASK)) + + +/*****************************************************************************/ +/** + * Tell the DMA engine that the current packet does not end with the given + * BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdClearLast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearLast(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_LAST_MASK)) + + +/*****************************************************************************/ +/** + * Set this bit to mark the last descriptor in the receive buffer descriptor + * list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetRxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +/*#define XEmacPs_BdSetRxWrap(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) | \ + XEMACPS_RXBUF_WRAP_MASK)) +*/ + +/*****************************************************************************/ +/** + * Determine the wrap bit of the receive BD which indicates end of the + * BD list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * u8 XEmacPs_BdIsRxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxWrap(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + XEMACPS_RXBUF_WRAP_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Sets this bit to mark the last descriptor in the transmit buffer + * descriptor list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetTxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +/*#define XEmacPs_BdSetTxWrap(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_WRAP_MASK)) +*/ + +/*****************************************************************************/ +/** + * Determine the wrap bit of the transmit BD which indicates end of the + * BD list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * u8 XEmacPs_BdGetTxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxWrap(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_WRAP_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/* + * Must clear this bit to enable the MAC to write data to the receive + * buffer. Hardware sets this bit once it has successfully written a frame to + * memory. Once set, software has to clear the bit before the buffer can be + * used again. This macro clear the new bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdClearRxNew(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearRxNew(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + ~XEMACPS_RXBUF_NEW_MASK)) + + +/*****************************************************************************/ +/** + * Determine the new bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxNew(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxNew(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + XEMACPS_RXBUF_NEW_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Software sets this bit to disable the buffer to be read by the hardware. + * Hardware sets this bit for the first buffer of a frame once it has been + * successfully transmitted. This macro sets this bit of transmit BD to avoid + * confusion. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetTxUsed(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdSetTxUsed(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_USED_MASK)) + + +/*****************************************************************************/ +/** + * Software clears this bit to enable the buffer to be read by the hardware. + * Hardware sets this bit for the first buffer of a frame once it has been + * successfully transmitted. This macro clears this bit of transmit BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdClearTxUsed(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearTxUsed(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_USED_MASK)) + + +/*****************************************************************************/ +/** + * Determine the used bit of the transmit BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxUsed(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxUsed(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_USED_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if a frame fails to be transmitted due to too many retries. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxRetry(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxRetry(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_RETRY_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if a frame fails to be transmitted due to data can not be + * feteched in time or buffers are exhausted. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxUrun(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxUrun(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_URUN_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if a frame fails to be transmitted due to buffer is exhausted + * mid-frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxExh(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxExh(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_EXH_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Sets this bit, no CRC will be appended to the current frame. This control + * bit must be set for the first buffer in a frame and will be ignored for + * the subsequent buffers of a frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * This bit must be clear when using the transmit checksum generation offload, + * otherwise checksum generation and substitution will not occur. + * + * C-style signature: + * UINTPTR XEmacPs_BdSetTxNoCRC(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdSetTxNoCRC(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_NOCRC_MASK)) + + +/*****************************************************************************/ +/** + * Clear this bit, CRC will be appended to the current frame. This control + * bit must be set for the first buffer in a frame and will be ignored for + * the subsequent buffers of a frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * This bit must be clear when using the transmit checksum generation offload, + * otherwise checksum generation and substitution will not occur. + * + * C-style signature: + * UINTPTR XEmacPs_BdClearTxNoCRC(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearTxNoCRC(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_NOCRC_MASK)) + + +/*****************************************************************************/ +/** + * Determine the broadcast bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxBcast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxBcast(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_BCAST_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the multicast hash bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxMultiHash(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxMultiHash(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_MULTIHASH_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the unicast hash bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxUniHash(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxUniHash(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_UNIHASH_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if the received frame is a VLAN Tagged frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxVlan(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxVlan(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_VLAN_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if the received frame has Type ID of 8100h and null VLAN + * identifier(Priority tag). + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxPri(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxPri(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_PRI_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if the received frame's Concatenation Format Indicator (CFI) of + * the frames VLANTCI field was set. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxCFI(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxCFI(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_CFI_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the End Of Frame (EOF) bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetRxEOF(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxEOF(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_EOF_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the Start Of Frame (SOF) bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetRxSOF(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxSOF(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_SOF_MASK)!=0U ? TRUE : FALSE) + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c new file mode 100644 index 0000000000..1225aca42d --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c @@ -0,0 +1,1076 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_bdring.c +* @addtogroup emacps_v3_11 +* @{ +* +* This file implements buffer descriptor ring related functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 1.00a asa  11/21/11 The function XEmacPs_BdRingFromHwTx is modified.
+*		      Earlier it used to search in "BdLimit" number of BDs to
+*		      know which BDs are processed. Now one more check is
+*		      added. It looks for BDs till the current BD pointer
+*		      reaches HwTail. By doing this processing time is saved.
+* 1.00a asa  01/24/12 The function XEmacPs_BdRingFromHwTx in file
+*		      xemacps_bdring.c is modified. Now start of packet is
+*		      searched for returning the number of BDs processed.
+* 1.05a asa  09/23/13 Cache operations on BDs are not required and hence
+*		      removed. It is expected that all BDs are allocated in
+*		      from uncached area. Fix for CR #663885.
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp architecture.
+* 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.6   rb   09/08/17 Add XEmacPs_BdRingPtrReset() API to reset BD ring
+* 		      pointers
+*
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xil_cache.h" +#include "xemacps_hw.h" +#include "xemacps_bd.h" +#include "xemacps_bdring.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************************************************************** + * Compute the virtual address of a descriptor from its physical address + * + * @param BdPtr is the physical address of the BD + * + * @returns Virtual address of BdPtr + * + * @note Assume BdPtr is always a valid BD in the ring + ****************************************************************************/ +#define XEMACPS_PHYS_TO_VIRT(BdPtr) \ + ((UINTPTR)(BdPtr) + (RingPtr->BaseBdAddr - RingPtr->PhysBaseAddr)) + +/**************************************************************************** + * Compute the physical address of a descriptor from its virtual address + * + * @param BdPtr is the physical address of the BD + * + * @returns Physical address of BdPtr + * + * @note Assume BdPtr is always a valid BD in the ring + ****************************************************************************/ +#define XEMACPS_VIRT_TO_PHYS(BdPtr) \ + ((UINTPTR)(BdPtr) - (RingPtr->BaseBdAddr - RingPtr->PhysBaseAddr)) + +/**************************************************************************** + * Move the BdPtr argument ahead an arbitrary number of BDs wrapping around + * to the beginning of the ring if needed. + * + * We know if a wrapaound should occur if the new BdPtr is greater than + * the high address in the ring OR if the new BdPtr crosses over the + * 0xFFFFFFFF to 0 boundary. The latter test is a valid one since we do not + * allow a BD space to span this boundary. + * + * @param RingPtr is the ring BdPtr appears in + * @param BdPtr on input is the starting BD position and on output is the + * final BD position + * @param NumBd is the number of BD spaces to increment + * + ****************************************************************************/ +#define XEMACPS_RING_SEEKAHEAD(RingPtr, BdPtr, NumBd) \ + { \ + UINTPTR Addr = (UINTPTR)(void *)(BdPtr); \ + \ + Addr += ((RingPtr)->Separation * (NumBd)); \ + if ((Addr > (RingPtr)->HighBdAddr) || ((UINTPTR)(void *)(BdPtr) > Addr)) \ + { \ + Addr -= (RingPtr)->Length; \ + } \ + \ + (BdPtr) = (XEmacPs_Bd*)(void *)Addr; \ + } + +/**************************************************************************** + * Move the BdPtr argument backwards an arbitrary number of BDs wrapping + * around to the end of the ring if needed. + * + * We know if a wrapaound should occur if the new BdPtr is less than + * the base address in the ring OR if the new BdPtr crosses over the + * 0xFFFFFFFF to 0 boundary. The latter test is a valid one since we do not + * allow a BD space to span this boundary. + * + * @param RingPtr is the ring BdPtr appears in + * @param BdPtr on input is the starting BD position and on output is the + * final BD position + * @param NumBd is the number of BD spaces to increment + * + ****************************************************************************/ +#define XEMACPS_RING_SEEKBACK(RingPtr, BdPtr, NumBd) \ + { \ + UINTPTR Addr = (UINTPTR)(void *)(BdPtr); \ + \ + Addr -= ((RingPtr)->Separation * (NumBd)); \ + if ((Addr < (RingPtr)->BaseBdAddr) || ((UINTPTR)(void*)(BdPtr) < Addr)) \ + { \ + Addr += (RingPtr)->Length; \ + } \ + \ + (BdPtr) = (XEmacPs_Bd*)(void*)Addr; \ + } + + +/************************** Function Prototypes ******************************/ + +static void XEmacPs_BdSetRxWrap(UINTPTR BdPtr); +static void XEmacPs_BdSetTxWrap(UINTPTR BdPtr); + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** + * Using a memory segment allocated by the caller, create and setup the BD list + * for the given DMA channel. + * + * @param RingPtr is the instance to be worked on. + * @param PhysAddr is the physical base address of user memory region. + * @param VirtAddr is the virtual base address of the user memory region. If + * address translation is not being utilized, then VirtAddr should be + * equivalent to PhysAddr. + * @param Alignment governs the byte alignment of individual BDs. This function + * will enforce a minimum alignment of 4 bytes with no maximum as long + * as it is specified as a power of 2. + * @param BdCount is the number of BDs to setup in the user memory region. It + * is assumed the region is large enough to contain the BDs. + * + * @return + * + * - XST_SUCCESS if initialization was successful + * - XST_NO_FEATURE if the provided instance is a non DMA type + * channel. + * - XST_INVALID_PARAM under any of the following conditions: + * 1) PhysAddr and/or VirtAddr are not aligned to the given Alignment + * parameter. + * 2) Alignment parameter does not meet minimum requirements or is not a + * power of 2 value. + * 3) BdCount is 0. + * - XST_DMA_SG_LIST_ERROR if the memory segment containing the list spans + * over address 0x00000000 in virtual address space. + * + * @note + * Make sure to pass in the right alignment value. + *****************************************************************************/ +LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr, + UINTPTR VirtAddr, u32 Alignment, u32 BdCount) +{ + u32 i; + UINTPTR BdVirtAddr; + UINTPTR BdPhyAddr; + UINTPTR VirtAddrLoc = VirtAddr; + + /* In case there is a failure prior to creating list, make sure the + * following attributes are 0 to prevent calls to other functions + * from doing anything. + */ + RingPtr->AllCnt = 0U; + RingPtr->FreeCnt = 0U; + RingPtr->HwCnt = 0U; + RingPtr->PreCnt = 0U; + RingPtr->PostCnt = 0U; + + /* Make sure Alignment parameter meets minimum requirements */ + if (Alignment < (u32)XEMACPS_DMABD_MINIMUM_ALIGNMENT) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Make sure Alignment is a power of 2 */ + if (((Alignment - 0x00000001U) & Alignment)!=0x00000000U) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Make sure PhysAddr and VirtAddr are on same Alignment */ + if (((PhysAddr % Alignment)!=(u32)0) || ((VirtAddrLoc % Alignment)!=(u32)0)) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Is BdCount reasonable? */ + if (BdCount == 0x00000000U) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Figure out how many bytes will be between the start of adjacent BDs */ + RingPtr->Separation = ((u32)sizeof(XEmacPs_Bd)); + + /* Must make sure the ring doesn't span address 0x00000000. If it does, + * then the next/prev BD traversal macros will fail. + */ + if (VirtAddrLoc > ((VirtAddrLoc + (RingPtr->Separation * BdCount)) - (u32)1)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + /* Initial ring setup: + * - Clear the entire space + * - Setup each BD's BDA field with the physical address of the next BD + */ + (void)memset((void *) VirtAddrLoc, 0, (RingPtr->Separation * BdCount)); + + BdVirtAddr = VirtAddrLoc; + BdPhyAddr = PhysAddr + RingPtr->Separation; + for (i = 1U; i < BdCount; i++) { + BdVirtAddr += RingPtr->Separation; + BdPhyAddr += RingPtr->Separation; + } + + /* Setup and initialize pointers and counters */ + RingPtr->RunState = (u32)(XST_DMA_SG_IS_STOPPED); + RingPtr->BaseBdAddr = VirtAddrLoc; + RingPtr->PhysBaseAddr = PhysAddr; + RingPtr->HighBdAddr = BdVirtAddr; + RingPtr->Length = + ((RingPtr->HighBdAddr - RingPtr->BaseBdAddr) + RingPtr->Separation); + RingPtr->AllCnt = (u32)BdCount; + RingPtr->FreeCnt = (u32)BdCount; + RingPtr->FreeHead = (XEmacPs_Bd *)(void *)VirtAddrLoc; + RingPtr->PreHead = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->HwHead = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->HwTail = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->PostHead = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->BdaRestart = (XEmacPs_Bd *)(void *)PhysAddr; + + return (LONG)(XST_SUCCESS); +} + + +/*****************************************************************************/ +/** + * Clone the given BD into every BD in the list. + * every field of the source BD is replicated in every BD of the list. + * + * This function can be called only when all BDs are in the free group such as + * they are immediately after initialization with XEmacPs_BdRingCreate(). + * This prevents modification of BDs while they are in use by hardware or the + * user. + * + * @param RingPtr is the pointer of BD ring instance to be worked on. + * @param SrcBdPtr is the source BD template to be cloned into the list. This + * BD will be modified. + * @param Direction is either XEMACPS_SEND or XEMACPS_RECV that indicates + * which direction. + * + * @return + * - XST_SUCCESS if the list was modified. + * - XST_DMA_SG_NO_LIST if a list has not been created. + * - XST_DMA_SG_LIST_ERROR if some of the BDs in this channel are under + * hardware or user control. + * - XST_DEVICE_IS_STARTED if the DMA channel has not been stopped. + * + *****************************************************************************/ +LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr, + u8 Direction) +{ + u32 i; + UINTPTR CurBd; + + /* Can't do this function if there isn't a ring */ + if (RingPtr->AllCnt == 0x00000000U) { + return (LONG)(XST_DMA_SG_NO_LIST); + } + + /* Can't do this function with the channel running */ + if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) { + return (LONG)(XST_DEVICE_IS_STARTED); + } + + /* Can't do this function with some of the BDs in use */ + if (RingPtr->FreeCnt != RingPtr->AllCnt) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Starting from the top of the ring, save BD.Next, overwrite the entire + * BD with the template, then restore BD.Next + */ + CurBd = RingPtr->BaseBdAddr; + for (i = 0U; i < RingPtr->AllCnt; i++) { + memcpy((void *)CurBd, SrcBdPtr, sizeof(XEmacPs_Bd)); + CurBd += RingPtr->Separation; + } + + CurBd -= RingPtr->Separation; + + if (Direction == XEMACPS_RECV) { + XEmacPs_BdSetRxWrap(CurBd); + } + else { + XEmacPs_BdSetTxWrap(CurBd); + } + + return (LONG)(XST_SUCCESS); +} + + +/*****************************************************************************/ +/** + * Reserve locations in the BD list. The set of returned BDs may be modified + * in preparation for future DMA transaction(s). Once the BDs are ready to be + * submitted to hardware, the user must call XEmacPs_BdRingToHw() in the same + * order which they were allocated here. Example: + * + *
+ *        NumBd = 2,
+ *        Status = XEmacPs_BdRingAlloc(MyRingPtr, NumBd, &MyBdSet),
+ *
+ *        if (Status != XST_SUCCESS)
+ *        {
+ *            *Not enough BDs available for the request*
+ *        }
+ *
+ *        CurBd = MyBdSet,
+ *        for (i=0; i
+ *
+ * A more advanced use of this function may allocate multiple sets of BDs.
+ * They must be allocated and given to hardware in the correct sequence:
+ * 
+ *        * Legal *
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
+ *
+ *        * Legal *
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2),
+ *
+ *        * Not legal *
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
+ * 
+ * + * Use the API defined in xemacps_bd.h to modify individual BDs. Traversal + * of the BD set can be done using XEmacPs_BdRingNext() and + * XEmacPs_BdRingPrev(). + * + * @param RingPtr is a pointer to the BD ring instance to be worked on. + * @param NumBd is the number of BDs to allocate + * @param BdSetPtr is an output parameter, it points to the first BD available + * for modification. + * + * @return + * - XST_SUCCESS if the requested number of BDs was returned in the BdSetPtr + * parameter. + * - XST_FAILURE if there were not enough free BDs to satisfy the request. + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + * @note Do not modify more BDs than the number requested with the NumBd + * parameter. Doing so will lead to data corruption and system + * instability. + * + *****************************************************************************/ +LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd ** BdSetPtr) +{ + LONG Status; + /* Enough free BDs available for the request? */ + if (RingPtr->FreeCnt < NumBd) { + Status = (LONG)(XST_FAILURE); + } else { + /* Set the return argument and move FreeHead forward */ + *BdSetPtr = RingPtr->FreeHead; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->FreeHead, NumBd); + RingPtr->FreeCnt -= NumBd; + RingPtr->PreCnt += NumBd; + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + +/*****************************************************************************/ +/** + * Fully or partially undo an XEmacPs_BdRingAlloc() operation. Use this + * function if all the BDs allocated by XEmacPs_BdRingAlloc() could not be + * transferred to hardware with XEmacPs_BdRingToHw(). + * + * This function helps out in situations when an unrelated error occurs after + * BDs have been allocated but before they have been given to hardware. + * An example of this type of error would be an OS running out of resources. + * + * This function is not the same as XEmacPs_BdRingFree(). The Free function + * returns BDs to the free list after they have been processed by hardware, + * while UnAlloc returns them before being processed by hardware. + * + * There are two scenarios where this function can be used. Full UnAlloc or + * Partial UnAlloc. A Full UnAlloc means all the BDs Alloc'd will be returned: + * + *
+ *    Status = XEmacPs_BdRingAlloc(MyRingPtr, 10, &BdPtr),
+ *        ...
+ *    if (Error)
+ *    {
+ *        Status = XEmacPs_BdRingUnAlloc(MyRingPtr, 10, &BdPtr),
+ *    }
+ * 
+ * + * A partial UnAlloc means some of the BDs Alloc'd will be returned: + * + *
+ *    Status = XEmacPs_BdRingAlloc(MyRingPtr, 10, &BdPtr),
+ *    BdsLeft = 10,
+ *    CurBdPtr = BdPtr,
+ *
+ *    while (BdsLeft)
+ *    {
+ *       if (Error)
+ *       {
+ *          Status = XEmacPs_BdRingUnAlloc(MyRingPtr, BdsLeft, CurBdPtr),
+ *       }
+ *
+ *       CurBdPtr = XEmacPs_BdRingNext(MyRingPtr, CurBdPtr),
+ *       BdsLeft--,
+ *    }
+ * 
+ * + * A partial UnAlloc must include the last BD in the list that was Alloc'd. + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param NumBd is the number of BDs to allocate + * @param BdSetPtr is an output parameter, it points to the first BD available + * for modification. + * + * @return + * - XST_SUCCESS if the BDs were unallocated. + * - XST_FAILURE if NumBd parameter was greater that the number of BDs in + * the preprocessing state. + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr) +{ + LONG Status; + (void) BdSetPtr; + Xil_AssertNonvoid(RingPtr != NULL); + Xil_AssertNonvoid(BdSetPtr != NULL); + + /* Enough BDs in the free state for the request? */ + if (RingPtr->PreCnt < NumBd) { + Status = (LONG)(XST_FAILURE); + } else { + /* Set the return argument and move FreeHead backward */ + XEMACPS_RING_SEEKBACK(RingPtr, (RingPtr->FreeHead), NumBd); + RingPtr->FreeCnt += NumBd; + RingPtr->PreCnt -= NumBd; + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + + +/*****************************************************************************/ +/** + * Enqueue a set of BDs to hardware that were previously allocated by + * XEmacPs_BdRingAlloc(). Once this function returns, the argument BD set goes + * under hardware control. Any changes made to these BDs after this point will + * corrupt the BD list leading to data corruption and system instability. + * + * The set will be rejected if the last BD of the set does not mark the end of + * a packet (see XEmacPs_BdSetLast()). + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param NumBd is the number of BDs in the set. + * @param BdSetPtr is the first BD of the set to commit to hardware. + * + * @return + * - XST_SUCCESS if the set of BDs was accepted and enqueued to hardware. + * - XST_FAILURE if the set of BDs was rejected because the last BD of the set + * did not have its "last" bit set. + * - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with + * XEmacPs_BdRingAlloc(). + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr) +{ + XEmacPs_Bd *CurBdPtr; + u32 i; + LONG Status; + /* if no bds to process, simply return. */ + if (0U == NumBd){ + Status = (LONG)(XST_SUCCESS); + } else { + /* Make sure we are in sync with XEmacPs_BdRingAlloc() */ + if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) { + Status = (LONG)(XST_DMA_SG_LIST_ERROR); + } else { + CurBdPtr = BdSetPtr; + for (i = 0U; i < NumBd; i++) { + CurBdPtr = (XEmacPs_Bd *)((void *)XEmacPs_BdRingNext(RingPtr, CurBdPtr)); + } + /* Adjust ring pointers & counters */ + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd); + RingPtr->PreCnt -= NumBd; + RingPtr->HwTail = CurBdPtr; + RingPtr->HwCnt += NumBd; + + Status = (LONG)(XST_SUCCESS); + } + } + return Status; +} + + +/*****************************************************************************/ +/** + * Returns a set of BD(s) that have been processed by hardware. The returned + * BDs may be examined to determine the outcome of the DMA transaction(s). + * Once the BDs have been examined, the user must call XEmacPs_BdRingFree() + * in the same order which they were retrieved here. Example: + * + *
+ *        NumBd = XEmacPs_BdRingFromHwTx(MyRingPtr, MaxBd, &MyBdSet),
+ *        if (NumBd == 0)
+ *        {
+ *           * hardware has nothing ready for us yet*
+ *        }
+ *
+ *        CurBd = MyBdSet,
+ *        for (i=0; i
+ *
+ * A more advanced use of this function may allocate multiple sets of BDs.
+ * They must be retrieved from hardware and freed in the correct sequence:
+ * 
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *
+ *        * Not legal *
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ * 
+ * + * If hardware has only partially completed a packet spanning multiple BDs, + * then none of the BDs for that packet will be included in the results. + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param BdLimit is the maximum number of BDs to return in the set. + * @param BdSetPtr is an output parameter, it points to the first BD available + * for examination. + * + * @return + * The number of BDs processed by hardware. A value of 0 indicates that no + * data is available. No more than BdLimit BDs will be returned. + * + * @note Treat BDs returned by this function as read-only. + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, + XEmacPs_Bd ** BdSetPtr) +{ + XEmacPs_Bd *CurBdPtr; + u32 BdStr = 0U; + u32 BdCount; + u32 BdPartialCount; + u32 Sop = 0U; + u32 Status; + u32 BdLimitLoc = BdLimit; + CurBdPtr = RingPtr->HwHead; + BdCount = 0U; + BdPartialCount = 0U; + + /* If no BDs in work group, then there's nothing to search */ + if (RingPtr->HwCnt == 0x00000000U) { + *BdSetPtr = NULL; + Status = 0U; + } else { + + if (BdLimitLoc > RingPtr->HwCnt){ + BdLimitLoc = RingPtr->HwCnt; + } + /* Starting at HwHead, keep moving forward in the list until: + * - A BD is encountered with its new/used bit set which means + * hardware has not completed processing of that BD. + * - RingPtr->HwTail is reached and RingPtr->HwCnt is reached. + * - The number of requested BDs has been processed + */ + while (BdCount < BdLimitLoc) { + /* Read the status */ + if(CurBdPtr != NULL){ + BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET); + } + + if ((Sop == 0x00000000U) && ((BdStr & XEMACPS_TXBUF_USED_MASK)!=0x00000000U)){ + Sop = 1U; + } + if (Sop == 0x00000001U) { + BdCount++; + BdPartialCount++; + } + + /* hardware has processed this BD so check the "last" bit. + * If it is clear, then there are more BDs for the current + * packet. Keep a count of these partial packet BDs. + */ + if ((Sop == 0x00000001U) && ((BdStr & XEMACPS_TXBUF_LAST_MASK)!=0x00000000U)) { + Sop = 0U; + BdPartialCount = 0U; + } + + /* Move on to next BD in work group */ + CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); + } + + /* Subtract off any partial packet BDs found */ + BdCount -= BdPartialCount; + + /* If BdCount is non-zero then BDs were found to return. Set return + * parameters, update pointers and counters, return success + */ + if (BdCount > 0x00000000U) { + *BdSetPtr = RingPtr->HwHead; + RingPtr->HwCnt -= BdCount; + RingPtr->PostCnt += BdCount; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); + Status = (BdCount); + } else { + *BdSetPtr = NULL; + Status = 0U; + } + } + return Status; +} + + +/*****************************************************************************/ +/** + * Returns a set of BD(s) that have been processed by hardware. The returned + * BDs may be examined to determine the outcome of the DMA transaction(s). + * Once the BDs have been examined, the user must call XEmacPs_BdRingFree() + * in the same order which they were retrieved here. Example: + * + *
+ *        NumBd = XEmacPs_BdRingFromHwRx(MyRingPtr, MaxBd, &MyBdSet),
+ *
+ *        if (NumBd == 0)
+ *        {
+ *           *hardware has nothing ready for us yet*
+ *        }
+ *
+ *        CurBd = MyBdSet,
+ *        for (i=0; i
+ *
+ * A more advanced use of this function may allocate multiple sets of BDs.
+ * They must be retrieved from hardware and freed in the correct sequence:
+ * 
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *
+ *        * Not legal *
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ * 
+ * + * If hardware has only partially completed a packet spanning multiple BDs, + * then none of the BDs for that packet will be included in the results. + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param BdLimit is the maximum number of BDs to return in the set. + * @param BdSetPtr is an output parameter, it points to the first BD available + * for examination. + * + * @return + * The number of BDs processed by hardware. A value of 0 indicates that no + * data is available. No more than BdLimit BDs will be returned. + * + * @note Treat BDs returned by this function as read-only. + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, + XEmacPs_Bd ** BdSetPtr) +{ + XEmacPs_Bd *CurBdPtr; + u32 BdStr = 0U; + u32 BdCount; + u32 BdPartialCount; + u32 Status; + + CurBdPtr = RingPtr->HwHead; + BdCount = 0U; + BdPartialCount = 0U; + + /* If no BDs in work group, then there's nothing to search */ + if (RingPtr->HwCnt == 0x00000000U) { + *BdSetPtr = NULL; + Status = 0U; + } else { + + /* Starting at HwHead, keep moving forward in the list until: + * - A BD is encountered with its new/used bit set which means + * hardware has completed processing of that BD. + * - RingPtr->HwTail is reached and RingPtr->HwCnt is reached. + * - The number of requested BDs has been processed + */ + while (BdCount < BdLimit) { + + /* Read the status */ + if(CurBdPtr!=NULL){ + BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET); + } + if ((!(XEmacPs_BdIsRxNew(CurBdPtr)))==TRUE) { + break; + } + + BdCount++; + + /* hardware has processed this BD so check the "last" bit. If + * it is clear, then there are more BDs for the current packet. + * Keep a count of these partial packet BDs. + */ + if ((BdStr & XEMACPS_RXBUF_EOF_MASK)!=0x00000000U) { + BdPartialCount = 0U; + } else { + BdPartialCount++; + } + + /* Move on to next BD in work group */ + CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); + } + + /* Subtract off any partial packet BDs found */ + BdCount -= BdPartialCount; + + /* If BdCount is non-zero then BDs were found to return. Set return + * parameters, update pointers and counters, return success + */ + if (BdCount > 0x00000000U) { + *BdSetPtr = RingPtr->HwHead; + RingPtr->HwCnt -= BdCount; + RingPtr->PostCnt += BdCount; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); + Status = (BdCount); + } + else { + *BdSetPtr = NULL; + Status = 0U; + } +} + return Status; +} + + +/*****************************************************************************/ +/** + * Frees a set of BDs that had been previously retrieved with + * XEmacPs_BdRingFromHw(). + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param NumBd is the number of BDs to free. + * @param BdSetPtr is the head of a list of BDs returned by + * XEmacPs_BdRingFromHw(). + * + * @return + * - XST_SUCCESS if the set of BDs was freed. + * - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with + * XEmacPs_BdRingFromHw(). + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr) +{ + LONG Status; + /* if no bds to process, simply return. */ + if (0x00000000U == NumBd){ + Status = (LONG)(XST_SUCCESS); + } else { + /* Make sure we are in sync with XEmacPs_BdRingFromHw() */ + if ((RingPtr->PostCnt < NumBd) || (RingPtr->PostHead != BdSetPtr)) { + Status = (LONG)(XST_DMA_SG_LIST_ERROR); + } else { + /* Update pointers and counters */ + RingPtr->FreeCnt += NumBd; + RingPtr->PostCnt -= NumBd; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PostHead, NumBd); + Status = (LONG)(XST_SUCCESS); + } + } + return Status; +} + + +/*****************************************************************************/ +/** + * Check the internal data structures of the BD ring for the provided channel. + * The following checks are made: + * + * - Is the BD ring linked correctly in physical address space. + * - Do the internal pointers point to BDs in the ring. + * - Do the internal counters add up. + * + * The channel should be stopped prior to calling this function. + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param Direction is either XEMACPS_SEND or XEMACPS_RECV that indicates + * which direction. + * + * @return + * - XST_SUCCESS if the set of BDs was freed. + * - XST_DMA_SG_NO_LIST if the list has not been created. + * - XST_IS_STARTED if the channel is not stopped. + * - XST_DMA_SG_LIST_ERROR if a problem is found with the internal data + * structures. If this value is returned, the channel should be reset to + * avoid data corruption or system instability. + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +LONG XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction) +{ + UINTPTR AddrV, AddrP; + u32 i; + + if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Is the list created */ + if (RingPtr->AllCnt == 0x00000000U) { + return (LONG)(XST_DMA_SG_NO_LIST); + } + + /* Can't check if channel is running */ + if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) { + return (LONG)(XST_IS_STARTED); + } + + /* RunState doesn't make sense */ + if (RingPtr->RunState != (u32)XST_DMA_SG_IS_STOPPED) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + /* Verify internal pointers point to correct memory space */ + AddrV = (UINTPTR) RingPtr->FreeHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + AddrV = (UINTPTR) RingPtr->PreHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + AddrV = (UINTPTR) RingPtr->HwHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + AddrV = (UINTPTR) RingPtr->HwTail; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + AddrV = (UINTPTR) RingPtr->PostHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + /* Verify internal counters add up */ + if ((RingPtr->HwCnt + RingPtr->PreCnt + RingPtr->FreeCnt + + RingPtr->PostCnt) != RingPtr->AllCnt) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + /* Verify BDs are linked correctly */ + AddrV = RingPtr->BaseBdAddr; + AddrP = RingPtr->PhysBaseAddr + RingPtr->Separation; + + for (i = 1U; i < RingPtr->AllCnt; i++) { + /* Check BDA for this BD. It should point to next physical addr */ + if (XEmacPs_BdRead(AddrV, XEMACPS_BD_ADDR_OFFSET) != AddrP) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + /* Move on to next BD */ + AddrV += RingPtr->Separation; + AddrP += RingPtr->Separation; + } + + /* Last BD should have wrap bit set */ + if (XEMACPS_SEND == Direction) { + if ((!XEmacPs_BdIsTxWrap(AddrV))==TRUE) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + } + else { /* XEMACPS_RECV */ + if ((!XEmacPs_BdIsRxWrap(AddrV))==TRUE) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + } + + /* No problems found */ + return (LONG)(XST_SUCCESS); +} + +/*****************************************************************************/ +/** + * Set this bit to mark the last descriptor in the receive buffer descriptor + * list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetRxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +static void XEmacPs_BdSetRxWrap(UINTPTR BdPtr) +{ + u32 DataValueRx; + u32 *TempPtr; + + BdPtr += (u32)(XEMACPS_BD_ADDR_OFFSET); + TempPtr = (u32 *)BdPtr; + if(TempPtr != NULL) { + DataValueRx = *TempPtr; + DataValueRx |= XEMACPS_RXBUF_WRAP_MASK; + *TempPtr = DataValueRx; + } +} + +/*****************************************************************************/ +/** + * Sets this bit to mark the last descriptor in the transmit buffer + * descriptor list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetTxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +static void XEmacPs_BdSetTxWrap(UINTPTR BdPtr) +{ + u32 DataValueTx; + u32 *TempPtr; + + BdPtr += (u32)(XEMACPS_BD_STAT_OFFSET); + TempPtr = (u32 *)BdPtr; + if(TempPtr != NULL) { + DataValueTx = *TempPtr; + DataValueTx |= XEMACPS_TXBUF_WRAP_MASK; + *TempPtr = DataValueTx; + } +} + +/*****************************************************************************/ +/** + * Reset BD ring head and tail pointers. + * + * @param RingPtr is the instance to be worked on. + * @param virtaddrloc is the virtual base address of the user memory region. + * + * @note + * Should be called after XEmacPs_Stop() + * + * @note + * C-style signature: + * void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc) + * + *****************************************************************************/ +void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc) +{ + RingPtr->FreeHead = virtaddrloc; + RingPtr->PreHead = virtaddrloc; + RingPtr->HwHead = virtaddrloc; + RingPtr->HwTail = virtaddrloc; + RingPtr->PostHead = virtaddrloc; +} + +/** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h new file mode 100644 index 0000000000..9d7331d6d9 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h @@ -0,0 +1,215 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_bdring.h +* @addtogroup emacps_v3_11 +* @{ +* +* The Xiline EmacPs Buffer Descriptor ring driver. This is part of EmacPs +* DMA functionalities. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp architecture.
+* 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.6   rb   09/08/17 HwCnt variable (in XEmacPs_BdRing structure) is
+*		      changed to volatile.
+*
+* 
+* +******************************************************************************/ + +#ifndef XEMACPS_BDRING_H /* prevent curcular inclusions */ +#define XEMACPS_BDRING_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/**************************** Type Definitions *******************************/ + +/** This is an internal structure used to maintain the DMA list */ +typedef struct { + UINTPTR PhysBaseAddr;/**< Physical address of 1st BD in list */ + UINTPTR BaseBdAddr; /**< Virtual address of 1st BD in list */ + UINTPTR HighBdAddr; /**< Virtual address of last BD in the list */ + u32 Length; /**< Total size of ring in bytes */ + u32 RunState; /**< Flag to indicate DMA is started */ + u32 Separation; /**< Number of bytes between the starting address + of adjacent BDs */ + XEmacPs_Bd *FreeHead; + /**< First BD in the free group */ + XEmacPs_Bd *PreHead;/**< First BD in the pre-work group */ + XEmacPs_Bd *HwHead; /**< First BD in the work group */ + XEmacPs_Bd *HwTail; /**< Last BD in the work group */ + XEmacPs_Bd *PostHead; + /**< First BD in the post-work group */ + XEmacPs_Bd *BdaRestart; + /**< BDA to load when channel is started */ + + volatile u32 HwCnt; /**< Number of BDs in work group */ + u32 PreCnt; /**< Number of BDs in pre-work group */ + u32 FreeCnt; /**< Number of allocatable BDs in the free group */ + u32 PostCnt; /**< Number of BDs in post-work group */ + u32 AllCnt; /**< Total Number of BDs for channel */ +} XEmacPs_BdRing; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* Use this macro at initialization time to determine how many BDs will fit +* in a BD list within the given memory constraints. +* +* The results of this macro can be provided to XEmacPs_BdRingCreate(). +* +* @param Alignment specifies what byte alignment the BDs must fall on and +* must be a power of 2 to get an accurate calculation (32, 64, 128,...) +* @param Bytes is the number of bytes to be used to store BDs. +* +* @return Number of BDs that can fit in the given memory area +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingCntCalc(u32 Alignment, u32 Bytes) +* +******************************************************************************/ +#define XEmacPs_BdRingCntCalc(Alignment, Bytes) \ + (u32)((Bytes) / (sizeof(XEmacPs_Bd))) + +/*****************************************************************************/ +/** +* Use this macro at initialization time to determine how many bytes of memory +* is required to contain a given number of BDs at a given alignment. +* +* @param Alignment specifies what byte alignment the BDs must fall on. This +* parameter must be a power of 2 to get an accurate calculation (32, 64, +* 128,...) +* @param NumBd is the number of BDs to calculate memory size requirements for +* +* @return The number of bytes of memory required to create a BD list with the +* given memory constraints. +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingMemCalc(u32 Alignment, u32 NumBd) +* +******************************************************************************/ +#define XEmacPs_BdRingMemCalc(Alignment, NumBd) \ + (u32)(sizeof(XEmacPs_Bd) * (NumBd)) + +/****************************************************************************/ +/** +* Return the total number of BDs allocated by this channel with +* XEmacPs_BdRingCreate(). +* +* @param RingPtr is the DMA channel to operate on. +* +* @return The total number of BDs allocated for this channel. +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingGetCnt(XEmacPs_BdRing* RingPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingGetCnt(RingPtr) ((RingPtr)->AllCnt) + +/****************************************************************************/ +/** +* Return the number of BDs allocatable with XEmacPs_BdRingAlloc() for pre- +* processing. +* +* @param RingPtr is the DMA channel to operate on. +* +* @return The number of BDs currently allocatable. +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingGetFreeCnt(XEmacPs_BdRing* RingPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingGetFreeCnt(RingPtr) ((RingPtr)->FreeCnt) + +/****************************************************************************/ +/** +* Return the next BD from BdPtr in a list. +* +* @param RingPtr is the DMA channel to operate on. +* @param BdPtr is the BD to operate on. +* +* @return The next BD in the list relative to the BdPtr parameter. +* +* @note +* C-style signature: +* XEmacPs_Bd *XEmacPs_BdRingNext(XEmacPs_BdRing* RingPtr, +* XEmacPs_Bd *BdPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingNext(RingPtr, BdPtr) \ + (((UINTPTR)((void *)(BdPtr)) >= (RingPtr)->HighBdAddr) ? \ + (XEmacPs_Bd*)((void*)(RingPtr)->BaseBdAddr) : \ + (XEmacPs_Bd*)((UINTPTR)((void *)(BdPtr)) + (RingPtr)->Separation)) + +/****************************************************************************/ +/** +* Return the previous BD from BdPtr in the list. +* +* @param RingPtr is the DMA channel to operate on. +* @param BdPtr is the BD to operate on +* +* @return The previous BD in the list relative to the BdPtr parameter. +* +* @note +* C-style signature: +* XEmacPs_Bd *XEmacPs_BdRingPrev(XEmacPs_BdRing* RingPtr, +* XEmacPs_Bd *BdPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingPrev(RingPtr, BdPtr) \ + (((UINTPTR)(BdPtr) <= (RingPtr)->BaseBdAddr) ? \ + (XEmacPs_Bd*)(RingPtr)->HighBdAddr : \ + (XEmacPs_Bd*)((UINTPTR)(BdPtr) - (RingPtr)->Separation)) + +/************************** Function Prototypes ******************************/ + +/* + * Scatter gather DMA related functions in xemacps_bdring.c + */ +LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr, + UINTPTR VirtAddr, u32 Alignment, u32 BdCount); +LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr, + u8 Direction); +LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd ** BdSetPtr); +LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr); +LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr); +LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr); +u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, + XEmacPs_Bd ** BdSetPtr); +u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, + XEmacPs_Bd ** BdSetPtr); +LONG XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction); + +void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc); + +#ifdef __cplusplus +} +#endif + + +#endif /* end of protection macros */ +/** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c new file mode 100644 index 0000000000..b9620c208b --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c @@ -0,0 +1,1133 @@ +/****************************************************************************** +* Copyright (C) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xemacps_control.c +* @addtogroup emacps_v3_11 +* @{ + * + * Functions in this file implement general purpose command and control related + * functionality. See xemacps.h for a detailed description of the driver. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wsy  01/10/10 First release
+ * 1.02a asa  11/05/12 Added a new API for deleting an entry from the HASH
+ *					   register. Added a new API for setting the BURST length
+ *					   in DMACR register.
+ * 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp architecture.
+ * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+ * 3.0   hk   02/20/15 Added support for jumbo frames.
+ * 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
+ * 
+ *****************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xemacps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** + * Set the MAC address for this driver/device. The address is a 48-bit value. + * The device must be stopped before calling this function. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param AddressPtr is a pointer to a 6-byte MAC address. + * @param Index is a index to which MAC (1-4) address. + * + * @return + * - XST_SUCCESS if the MAC address was set successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * + *****************************************************************************/ +LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index) +{ + u32 MacAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 IndexLoc = Index; + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Aptr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U)); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } + else{ + /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ + IndexLoc--; + + /* Set the MAC bits [31:0] in BOT */ + MacAddr = *(Aptr); + MacAddr |= ((u32)(*(Aptr+1)) << 8U); + MacAddr |= ((u32)(*(Aptr+2)) << 16U); + MacAddr |= ((u32)(*(Aptr+3)) << 24U); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr); + + /* There are reserved bits in TOP so don't affect them */ + MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8))); + + MacAddr &= (u32)(~XEMACPS_LADDR_MACH_MASK); + + /* Set MAC bits [47:32] in TOP */ + MacAddr |= (u32)(*(Aptr+4)); + MacAddr |= (u32)(*(Aptr+5)) << 8U; + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr); + + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + + +/*****************************************************************************/ +/** + * Get the MAC address for this driver/device. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param AddressPtr is an output parameter, and is a pointer to a buffer into + * which the current MAC address will be copied. + * @param Index is a index to which MAC (1-4) address. + * + *****************************************************************************/ +void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index) +{ + u32 MacAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 IndexLoc = Index; + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Aptr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U)); + + /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ + IndexLoc--; + + MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8))); + *Aptr = (u8) MacAddr; + *(Aptr+1) = (u8) (MacAddr >> 8U); + *(Aptr+2) = (u8) (MacAddr >> 16U); + *(Aptr+3) = (u8) (MacAddr >> 24U); + + /* Read MAC bits [47:32] in TOP */ + MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8))); + *(Aptr+4) = (u8) MacAddr; + *(Aptr+5) = (u8) (MacAddr >> 8U); +} + + +/*****************************************************************************/ +/** + * Set 48-bit MAC addresses in hash table. + * The device must be stopped before calling this function. + * + * The hash address register is 64 bits long and takes up two locations in + * the memory map. The least significant bits are stored in hash register + * bottom and the most significant bits in hash register top. + * + * The unicast hash enable and the multicast hash enable bits in the network + * configuration register enable the reception of hash matched frames. The + * destination address is reduced to a 6 bit index into the 64 bit hash + * register using the following hash function. The hash function is an XOR + * of every sixth bit of the destination address. + * + *
+ * hash_index[05] = da[05]^da[11]^da[17]^da[23]^da[29]^da[35]^da[41]^da[47]
+ * hash_index[04] = da[04]^da[10]^da[16]^da[22]^da[28]^da[34]^da[40]^da[46]
+ * hash_index[03] = da[03]^da[09]^da[15]^da[21]^da[27]^da[33]^da[39]^da[45]
+ * hash_index[02] = da[02]^da[08]^da[14]^da[20]^da[26]^da[32]^da[38]^da[44]
+ * hash_index[01] = da[01]^da[07]^da[13]^da[19]^da[25]^da[31]^da[37]^da[43]
+ * hash_index[00] = da[00]^da[06]^da[12]^da[18]^da[24]^da[30]^da[36]^da[42]
+ * 
+ * + * da[0] represents the least significant bit of the first byte received, + * that is, the multicast/unicast indicator, and da[47] represents the most + * significant bit of the last byte received. + * + * If the hash index points to a bit that is set in the hash register then + * the frame will be matched according to whether the frame is multicast + * or unicast. + * + * A multicast match will be signaled if the multicast hash enable bit is + * set, da[0] is logic 1 and the hash index points to a bit set in the hash + * register. + * + * A unicast match will be signaled if the unicast hash enable bit is set, + * da[0] is logic 0 and the hash index points to a bit set in the hash + * register. + * + * To receive all multicast frames, the hash register should be set with + * all ones and the multicast hash enable bit should be set in the network + * configuration register. + * + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param AddressPtr is a pointer to a 6-byte MAC address. + * + * @return + * - XST_SUCCESS if the HASH MAC address was set successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet + * requirement after calculation + * + * @note + * Having Aptr be unsigned type prevents the following operations from sign + * extending. + *****************************************************************************/ +LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr) +{ + u32 HashAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8; + u32 Result; + LONG Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(AddressPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + Temp1 = (*(Aptr+0)) & 0x3FU; + Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); + + Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x3U) << 4U); + Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); + Temp5 = (*(Aptr+3)) & 0x3FU; + Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); + Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); + Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); + + Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ + (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8); + + if (Result >= (u32)XEMACPS_MAX_HASH_BITS) { + Status = (LONG)(XST_INVALID_PARAM); + } else { + + if (Result < (u32)32) { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET); + HashAddr |= (u32)(0x00000001U << Result); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET, HashAddr); + } else { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET); + HashAddr |= (u32)(0x00000001U << (u32)(Result - (u32)32)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET, HashAddr); + } + Status = (LONG)(XST_SUCCESS); + } + } + return Status; +} + +/*****************************************************************************/ +/** + * Delete 48-bit MAC addresses in hash table. + * The device must be stopped before calling this function. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param AddressPtr is a pointer to a 6-byte MAC address. + * + * @return + * - XST_SUCCESS if the HASH MAC address was deleted successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet + * requirement after calculation + * + * @note + * Having Aptr be unsigned type prevents the following operations from sign + * extending. + *****************************************************************************/ +LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr) +{ + u32 HashAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8; + u32 Result; + LONG Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Aptr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + Temp1 = (*(Aptr+0)) & 0x3FU; + Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); + Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x03U) << 4U); + Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); + Temp5 = (*(Aptr+3)) & 0x3FU; + Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); + Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); + Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); + + Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ + (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8); + + if (Result >= (u32)(XEMACPS_MAX_HASH_BITS)) { + Status = (LONG)(XST_INVALID_PARAM); + } else { + if (Result < (u32)32) { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET); + HashAddr &= (u32)(~(0x00000001U << Result)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET, HashAddr); + } else { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET); + HashAddr &= (u32)(~(0x00000001U << (u32)(Result - (u32)32))); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET, HashAddr); + } + Status = (LONG)(XST_SUCCESS); + } + } + return Status; +} +/*****************************************************************************/ +/** + * Clear the Hash registers for the mac address pointed by AddressPtr. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * + *****************************************************************************/ +void XEmacPs_ClearHash(XEmacPs *InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET, 0x0U); + + /* write bits [63:32] in TOP */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET, 0x0U); +} + + +/*****************************************************************************/ +/** + * Get the Hash address for this driver/device. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param AddressPtr is an output parameter, and is a pointer to a buffer into + * which the current HASH MAC address will be copied. + * + *****************************************************************************/ +void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr) +{ + u32 *Aptr = (u32 *)(void *)AddressPtr; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(AddressPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + *(Aptr+0) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET); + + /* Read Hash bits [63:32] in TOP */ + *(Aptr+1) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET); +} + + +/*****************************************************************************/ +/** + * Set the Type ID match for this driver/device. The register is a 32-bit + * value. The device must be stopped before calling this function. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param Id_Check is type ID to be configured. + * @param Index is a index to which Type ID (1-4). + * + * @return + * - XST_SUCCESS if the MAC address was set successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * + *****************************************************************************/ +LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index) +{ + u8 IndexLoc = Index; + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_TYPE_ID) && (IndexLoc > 0x00U)); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + + /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ + IndexLoc--; + + /* Set the ID bits in MATCHx register */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_MATCH1_OFFSET + ((u32)IndexLoc * (u32)4)), Id_Check); + + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + +/*****************************************************************************/ +/** + * Set options for the driver/device. The driver should be stopped with + * XEmacPs_Stop() before changing options. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param Options are the options to set. Multiple options can be set by OR'ing + * XTE_*_OPTIONS constants together. Options not specified are not + * affected. + * + * @return + * - XST_SUCCESS if the options were set successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * + * @note + * See xemacps.h for a description of the available options. + * + *****************************************************************************/ +LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options) +{ + u32 Reg; /* Generic register contents */ + u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ + u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + + /* Many of these options will change the NET_CONFIG registers. + * To reduce the amount of IO to the device, group these options here + * and change them all at once. + */ + + /* Grab current register contents */ + RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + RegNewNetCfg = RegNetCfg; + + /* + * It is configured to max 1536. + */ + if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { + RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK); + } + + /* Turn on VLAN packet only, only VLAN tagged will be accepted */ + if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK; + } + + /* Turn on FCS stripping on receive packets */ + if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK; + } + + /* Turn on length/type field checking on receive packets */ + if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_LENERRDSCRD_MASK; + } + + /* Turn on flow control */ + if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK; + } + + /* Turn on promiscuous frame filtering (all frames are received) */ + if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK; + } + + /* Allow broadcast address reception */ + if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_BCASTDI_MASK); + } + + /* Allow multicast address filtering */ + if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK; + } + + /* enable RX checksum offload */ + if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK; + } + + /* Enable jumbo frames */ + if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) && + (InstancePtr->Version > 2)) { + RegNewNetCfg |= XEMACPS_NWCFG_JUMBO_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_JUMBOMAXLEN_OFFSET, XEMACPS_RX_BUF_SIZE_JUMBO); + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg &= ~XEMACPS_DMACR_RXBUF_MASK; + Reg |= (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO / (u32)XEMACPS_RX_BUF_UNIT) + + (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO % + (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << + (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & + (u32)(XEMACPS_DMACR_RXBUF_MASK)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + InstancePtr->MaxMtuSize = XEMACPS_MTU_JUMBO; + InstancePtr->MaxFrameSize = XEMACPS_MTU_JUMBO + + XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; + InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + + XEMACPS_HDR_VLAN_SIZE; + InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_JUMBO_MASK; + } + + if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) && + (InstancePtr->Version > 2)) { + RegNewNetCfg |= (XEMACPS_NWCFG_SGMIIEN_MASK | + XEMACPS_NWCFG_PCSSEL_MASK); + } + + /* Officially change the NET_CONFIG registers if it needs to be + * modified. + */ + if (RegNetCfg != RegNewNetCfg) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, RegNewNetCfg); + } + + /* Enable TX checksum offload */ + if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg |= XEMACPS_DMACR_TCPCKSUM_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + } + + /* Enable transmitter */ + if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg |= XEMACPS_NWCTRL_TXEN_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } + + /* Enable receiver */ + if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg |= XEMACPS_NWCTRL_RXEN_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } + + /* The remaining options not handled here are managed elsewhere in the + * driver. No register modifications are needed at this time. Reflecting + * the option in InstancePtr->Options is good enough for now. + */ + + /* Set options word to its new value */ + InstancePtr->Options |= Options; + + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + + +/*****************************************************************************/ +/** + * Clear options for the driver/device + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param Options are the options to clear. Multiple options can be cleared by + * OR'ing XEMACPS_*_OPTIONS constants together. Options not specified + * are not affected. + * + * @return + * - XST_SUCCESS if the options were set successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * + * @note + * See xemacps.h for a description of the available options. + * + *****************************************************************************/ +LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options) +{ + u32 Reg; /* Generic */ + u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ + u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + + /* Many of these options will change the NET_CONFIG registers. + * To reduce the amount of IO to the device, group these options here + * and change them all at once. + */ + + /* Grab current register contents */ + RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + RegNewNetCfg = RegNetCfg; + + /* There is only RX configuration!? + * It is configured in two different length, up to 1536 and 10240 bytes + */ + if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_1536RXEN_MASK); + } + + /* Turn off VLAN packet only */ + if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_NVLANDISC_MASK); + } + + /* Turn off FCS stripping on receive packets */ + if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_FCSREM_MASK); + } + + /* Turn off length/type field checking on receive packets */ + if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_LENERRDSCRD_MASK); + } + + /* Turn off flow control */ + if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_PAUSEEN_MASK); + } + + /* Turn off promiscuous frame filtering (all frames are received) */ + if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_COPYALLEN_MASK); + } + + /* Disallow broadcast address filtering => broadcast reception */ + if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK; + } + + /* Disallow multicast address filtering */ + if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_MCASTHASHEN_MASK); + } + + /* Disable RX checksum offload */ + if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_RXCHKSUMEN_MASK); + } + + /* Disable jumbo frames */ + if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) && + (InstancePtr->Version > 2)) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_JUMBO_MASK); + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg &= ~XEMACPS_DMACR_RXBUF_MASK; + Reg |= (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) + + (((((u32)XEMACPS_RX_BUF_SIZE % + (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << + (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & + (u32)(XEMACPS_DMACR_RXBUF_MASK)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + InstancePtr->MaxMtuSize = XEMACPS_MTU; + InstancePtr->MaxFrameSize = XEMACPS_MTU + + XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; + InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + + XEMACPS_HDR_VLAN_SIZE; + InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK; + } + + if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) && + (InstancePtr->Version > 2)) { + RegNewNetCfg &= (u32)(~(XEMACPS_NWCFG_SGMIIEN_MASK | + XEMACPS_NWCFG_PCSSEL_MASK)); + } + + /* Officially change the NET_CONFIG registers if it needs to be + * modified. + */ + if (RegNetCfg != RegNewNetCfg) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, RegNewNetCfg); + } + + /* Disable TX checksum offload */ + if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg &= (u32)(~XEMACPS_DMACR_TCPCKSUM_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + } + + /* Disable transmitter */ + if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } + + /* Disable receiver */ + if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } + + /* The remaining options not handled here are managed elsewhere in the + * driver. No register modifications are needed at this time. Reflecting + * option in InstancePtr->Options is good enough for now. + */ + + /* Set options word to its new value */ + InstancePtr->Options &= ~Options; + + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + + +/*****************************************************************************/ +/** + * Get current option settings + * + * @param InstancePtr is a pointer to the instance to be worked on. + * + * @return + * A bitmask of XTE_*_OPTION constants. Any bit set to 1 is to be interpreted + * as a set option. + * + * @note + * See xemacps.h for a description of the available options. + * + *****************************************************************************/ +u32 XEmacPs_GetOptions(XEmacPs *InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + return (InstancePtr->Options); +} + + +/*****************************************************************************/ +/** + * Send a pause packet + * + * @param InstancePtr is a pointer to the instance to be worked on. + * + * @return + * - XST_SUCCESS if pause frame transmission was initiated + * - XST_DEVICE_IS_STOPPED if the device has not been started. + * + *****************************************************************************/ +LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr) +{ + u32 Reg; + LONG Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Make sure device is ready for this operation */ + if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STOPPED); + } else { + /* Send flow control frame */ + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg |= XEMACPS_NWCTRL_PAUSETX_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + +/*****************************************************************************/ +/** + * XEmacPs_GetOperatingSpeed gets the current operating link speed. This may + * be the value set by XEmacPs_SetOperatingSpeed() or a hardware default. + * + * @param InstancePtr references the TEMAC channel on which to operate. + * + * @return XEmacPs_GetOperatingSpeed returns the link speed in units of + * megabits per second. + * + * @note + * + *****************************************************************************/ +u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr) +{ + u32 Reg; + u16 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + + if ((Reg & XEMACPS_NWCFG_1000_MASK) != 0x00000000U) { + Status = (u16)(1000); + } else { + if ((Reg & XEMACPS_NWCFG_100_MASK) != 0x00000000U) { + Status = (u16)(100); + } else { + Status = (u16)(10); + } + } + return Status; +} + + +/*****************************************************************************/ +/** + * XEmacPs_SetOperatingSpeed sets the current operating link speed. For any + * traffic to be passed, this speed must match the current MII/GMII/SGMII/RGMII + * link speed. + * + * @param InstancePtr references the TEMAC channel on which to operate. + * @param Speed is the speed to set in units of Mbps. Valid values are 10, 100, + * or 1000. XEmacPs_SetOperatingSpeed ignores invalid values. + * + * @note + * + *****************************************************************************/ +void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed) +{ + u32 Reg; + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Speed == (u16)10) || (Speed == (u16)100) || (Speed == (u16)1000)); + + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + Reg &= (u32)(~(XEMACPS_NWCFG_1000_MASK | XEMACPS_NWCFG_100_MASK)); + + switch (Speed) { + case (u16)10: + break; + + case (u16)100: + Reg |= XEMACPS_NWCFG_100_MASK; + break; + + case (u16)1000: + Reg |= XEMACPS_NWCFG_1000_MASK; + break; + } + + /* Set register and return */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, Reg); +} + + +/*****************************************************************************/ +/** + * Set the MDIO clock divisor. + * + * Calculating the divisor: + * + *
+ *              f[HOSTCLK]
+ *   f[MDC] = -----------------
+ *            (1 + Divisor) * 2
+ * 
+ * + * where f[HOSTCLK] is the bus clock frequency in MHz, and f[MDC] is the + * MDIO clock frequency in MHz to the PHY. Typically, f[MDC] should not + * exceed 2.5 MHz. Some PHYs can tolerate faster speeds which means faster + * access. Here is the table to show values to generate MDC, + * + *
+ * 000 : divide pclk by   8 (pclk up to  20 MHz)
+ * 001 : divide pclk by  16 (pclk up to  40 MHz)
+ * 010 : divide pclk by  32 (pclk up to  80 MHz)
+ * 011 : divide pclk by  48 (pclk up to 120 MHz)
+ * 100 : divide pclk by  64 (pclk up to 160 MHz)
+ * 101 : divide pclk by  96 (pclk up to 240 MHz)
+ * 110 : divide pclk by 128 (pclk up to 320 MHz)
+ * 111 : divide pclk by 224 (pclk up to 540 MHz)
+ * 
+ * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param Divisor is the divisor to set. Range is 0b000 to 0b111. + * + *****************************************************************************/ +void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor) +{ + u32 Reg; + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Divisor <= (XEmacPs_MdcDiv)0x7); /* only last three bits are valid */ + + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + /* clear these three bits, could be done with mask */ + Reg &= (u32)(~XEMACPS_NWCFG_MDCCLKDIV_MASK); + + Reg |= ((u32)Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK); + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, Reg); +} + + +/*****************************************************************************/ +/** +* Read the current value of the PHY register indicated by the PhyAddress and +* the RegisterNum parameters. The MAC provides the driver with the ability to +* talk to a PHY that adheres to the Media Independent Interface (MII) as +* defined in the IEEE 802.3 standard. +* +* Prior to PHY access with this function, the user should have setup the MDIO +* clock with XEmacPs_SetMdioDivisor(). +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* @param PhyAddress is the address of the PHY to be read (supports multiple +* PHYs) +* @param RegisterNum is the register number, 0-31, of the specific PHY register +* to read +* @param PhyDataPtr is an output parameter, and points to a 16-bit buffer into +* which the current value of the register will be copied. +* +* @return +* +* - XST_SUCCESS if the PHY was read from successfully +* - XST_EMAC_MII_BUSY if there is another PHY operation in progress +* +* @note +* +* This function is not thread-safe. The user must provide mutually exclusive +* access to this function if there are to be multiple threads that can call it. +* +* There is the possibility that this function will not return if the hardware +* is broken (i.e., it never sets the status bit indicating that the read is +* done). If this is of concern to the user, the user should provide a mechanism +* suitable to their needs for recovery. +* +* For the duration of this function, all host interface reads and writes are +* blocked to the current XEmacPs instance. +* +******************************************************************************/ +LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, + u32 RegisterNum, u16 *PhyDataPtr) +{ + u32 Mgtcr; + volatile u32 Ipisr; + u32 IpReadTemp; + LONG Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Make sure no other PHY operation is currently in progress */ + if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET) & + XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) { + Status = (LONG)(XST_EMAC_MII_BUSY); + } else { + + /* Construct Mgtcr mask for the operation */ + Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK | + (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) | + (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK); + + /* Write Mgtcr and wait for completion */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_PHYMNTNC_OFFSET, Mgtcr); + + do { + Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET); + IpReadTemp = Ipisr; + } while ((IpReadTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U); + + /* Read data */ + *PhyDataPtr = (u16)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_PHYMNTNC_OFFSET); + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + + +/*****************************************************************************/ +/** +* Write data to the specified PHY register. The Ethernet driver does not +* require the device to be stopped before writing to the PHY. Although it is +* probably a good idea to stop the device, it is the responsibility of the +* application to deem this necessary. The MAC provides the driver with the +* ability to talk to a PHY that adheres to the Media Independent Interface +* (MII) as defined in the IEEE 802.3 standard. +* +* Prior to PHY access with this function, the user should have setup the MDIO +* clock with XEmacPs_SetMdioDivisor(). +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* @param PhyAddress is the address of the PHY to be written (supports multiple +* PHYs) +* @param RegisterNum is the register number, 0-31, of the specific PHY register +* to write +* @param PhyData is the 16-bit value that will be written to the register +* +* @return +* +* - XST_SUCCESS if the PHY was written to successfully. Since there is no error +* status from the MAC on a write, the user should read the PHY to verify the +* write was successful. +* - XST_EMAC_MII_BUSY if there is another PHY operation in progress +* +* @note +* +* This function is not thread-safe. The user must provide mutually exclusive +* access to this function if there are to be multiple threads that can call it. +* +* There is the possibility that this function will not return if the hardware +* is broken (i.e., it never sets the status bit indicating that the write is +* done). If this is of concern to the user, the user should provide a mechanism +* suitable to their needs for recovery. +* +* For the duration of this function, all host interface reads and writes are +* blocked to the current XEmacPs instance. +* +******************************************************************************/ +LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress, + u32 RegisterNum, u16 PhyData) +{ + u32 Mgtcr; + volatile u32 Ipisr; + u32 IpWriteTemp; + LONG Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Make sure no other PHY operation is currently in progress */ + if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET) & + XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) { + Status = (LONG)(XST_EMAC_MII_BUSY); + } else { + /* Construct Mgtcr mask for the operation */ + Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK | + (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) | + (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK) | (u32)PhyData; + + /* Write Mgtcr and wait for completion */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_PHYMNTNC_OFFSET, Mgtcr); + + do { + Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET); + IpWriteTemp = Ipisr; + } while ((IpWriteTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U); + + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + +/*****************************************************************************/ +/** +* API to update the Burst length in the DMACR register. +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* @param BLength is the length in bytes for the dma burst. +* +* @return None +* +******************************************************************************/ +void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength) +{ + u32 Reg; + u32 RegUpdateVal = 0; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((BLength == XEMACPS_SINGLE_BURST) || + (BLength == XEMACPS_4BYTE_BURST) || + (BLength == XEMACPS_8BYTE_BURST) || + (BLength == XEMACPS_16BYTE_BURST)); + + switch (BLength) { + case XEMACPS_SINGLE_BURST: + RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST; + break; + + case XEMACPS_4BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST; + break; + + case XEMACPS_8BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST; + break; + + case XEMACPS_16BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST; + break; + } + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + + Reg &= (u32)(~XEMACPS_DMACR_BLENGTH_MASK); + Reg |= RegUpdateVal; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, + Reg); +} +/** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c new file mode 100644 index 0000000000..7f725231af --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c @@ -0,0 +1,32 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: 2020.1 +* DO NOT EDIT. +* +* Copyright (C) 2010-2021 Xilinx, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xemacps.h" + +/* +* The configuration table for devices +*/ + +XEmacPs_Config XEmacPs_ConfigTable[XPAR_XEMACPS_NUM_INSTANCES] = +{ + { + XPAR_PSU_ETHERNET_3_DEVICE_ID, + XPAR_PSU_ETHERNET_3_BASEADDR, + XPAR_PSU_ETHERNET_3_IS_CACHE_COHERENT + } +}; + + diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c new file mode 100644 index 0000000000..3fa614b553 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c @@ -0,0 +1,97 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_hw.c +* @addtogroup emacps_v3_11 +* @{ +* +* This file contains the implementation of the ethernet interface reset sequence +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.05a kpc  28/06/13 First release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xemacps_hw.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* This function perform the reset sequence to the given emacps interface by +* configuring the appropriate control bits in the emacps specific registers. +* the emacps reset sequence involves the following steps +* Disable all the interuupts +* Clear the status registers +* Disable Rx and Tx engines +* Update the Tx and Rx descriptor queue registers with reset values +* Update the other relevant control registers with reset value +* +* @param BaseAddr of the interface +* +* @return N/A +* +* @note +* This function will not modify the slcr registers that are relevant for +* emacps controller +******************************************************************************/ +void XEmacPs_ResetHw(u32 BaseAddr) +{ + u32 RegVal; + + /* Disable the interrupts */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_IDR_OFFSET,0x0U); + + /* Stop transmission,disable loopback and Stop tx and Rx engines */ + RegVal = XEmacPs_ReadReg(BaseAddr,XEMACPS_NWCTRL_OFFSET); + RegVal &= ~((u32)XEMACPS_NWCTRL_TXEN_MASK| + (u32)XEMACPS_NWCTRL_RXEN_MASK| + (u32)XEMACPS_NWCTRL_HALTTX_MASK| + (u32)XEMACPS_NWCTRL_LOOPEN_MASK); + /* Clear the statistic registers, flush the packets in DPRAM*/ + RegVal |= (XEMACPS_NWCTRL_STATCLR_MASK| + XEMACPS_NWCTRL_FLUSH_DPRAM_MASK); + XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCTRL_OFFSET,RegVal); + /* Clear the interrupt status */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_ISR_OFFSET,XEMACPS_IXR_ALL_MASK); + /* Clear the tx status */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_TXSR_OFFSET,(XEMACPS_TXSR_ERROR_MASK| + (u32)XEMACPS_TXSR_TXCOMPL_MASK| + (u32)XEMACPS_TXSR_TXGO_MASK)); + /* Clear the rx status */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_RXSR_OFFSET, + XEMACPS_RXSR_FRAMERX_MASK); + /* Clear the tx base address */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_TXQBASE_OFFSET,0x0U); + /* Clear the rx base address */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_RXQBASE_OFFSET,0x0U); + /* Update the network config register with reset value */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCFG_OFFSET,XEMACPS_NWCFG_RESET_MASK); + /* Update the hash address registers with reset value */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHL_OFFSET,0x0U); + XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHH_OFFSET,0x0U); +} +/** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h new file mode 100644 index 0000000000..362acfdb7f --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h @@ -0,0 +1,646 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_hw.h +* @addtogroup emacps_v3_11 +* @{ +* +* This header file contains identifiers and low-level driver functions (or +* macros) that can be used to access the PS Ethernet MAC (XEmacPs) device. +* High-level driver functions are defined in xemacps.h. +* +* @note +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release.
+* 1.02a asa  11/05/12 Added hash defines for DMACR burst length configuration.
+* 1.05a kpc  28/06/13 Added XEmacPs_ResetHw function prototype
+* 1.06a asa  11/02/13 Changed the value for XEMACPS_RXBUF_LEN_MASK from 0x3fff
+*					  to 0x1fff. This fixes the CR#744902.
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification.
+* 3.0   kvn  12/16/14 Changed name of XEMACPS_NWCFG_LENGTHERRDSCRD_MASK to
+*					  XEMACPS_NWCFG_LENERRDSCRD_MASK as it exceeds 31 characters.
+* 3.0  kpc   1/23/15  Corrected the extended descriptor macro values.
+* 3.0  kvn   02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.0  hk   03/18/15 Added support for jumbo frames.
+*                    Remove "used bit set" from TX error interrupt masks.
+* 3.1  hk   08/10/15 Update upper 32 bit tx and rx queue ptr register offsets.
+* 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
+* 3.8  hk   09/17/18 Fix PTP interrupt masks.
+* 3.9  hk   01/23/19 Add RX watermark support
+* 3.10 hk   05/16/19 Clear status registers properly in reset
+* 
+* +******************************************************************************/ + +#ifndef XEMACPS_HW_H /* prevent circular inclusions */ +#define XEMACPS_HW_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +#define XEMACPS_MAX_MAC_ADDR 4U /**< Maxmum number of mac address + supported */ +#define XEMACPS_MAX_TYPE_ID 4U /**< Maxmum number of type id supported */ + +#ifdef __aarch64__ +#define XEMACPS_BD_ALIGNMENT 64U /**< Minimum buffer descriptor alignment + on the local bus */ +#else + +#define XEMACPS_BD_ALIGNMENT 4U /**< Minimum buffer descriptor alignment + on the local bus */ +#endif +#define XEMACPS_RX_BUF_ALIGNMENT 4U /**< Minimum buffer alignment when using + options that impose alignment + restrictions on the buffer data on + the local bus */ + +/** @name Direction identifiers + * + * These are used by several functions and callbacks that need + * to specify whether an operation specifies a send or receive channel. + * @{ + */ +#define XEMACPS_SEND 1U /**< send direction */ +#define XEMACPS_RECV 2U /**< receive direction */ +/*@}*/ + +/** @name MDC clock division + * currently supporting 8, 16, 32, 48, 64, 96, 128, 224. + * @{ + */ +typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, + MDC_DIV_64, MDC_DIV_96, MDC_DIV_128, MDC_DIV_224 +} XEmacPs_MdcDiv; + +/*@}*/ + +#define XEMACPS_RX_BUF_SIZE 1536U /**< Specify the receive buffer size in + bytes, 64, 128, ... 10240 */ +#define XEMACPS_RX_BUF_SIZE_JUMBO 10240U + +#define XEMACPS_RX_BUF_UNIT 64U /**< Number of receive buffer bytes as a + unit, this is HW setup */ + +#define XEMACPS_MAX_RXBD 128U /**< Size of RX buffer descriptor queues */ +#define XEMACPS_MAX_TXBD 128U /**< Size of TX buffer descriptor queues */ + +#define XEMACPS_MAX_HASH_BITS 64U /**< Maximum value for hash bits. 2**6 */ + +/* Register offset definitions. Unless otherwise noted, register access is + * 32 bit. Names are self explained here. + */ + +#define XEMACPS_NWCTRL_OFFSET 0x00000000U /**< Network Control reg */ +#define XEMACPS_NWCFG_OFFSET 0x00000004U /**< Network Config reg */ +#define XEMACPS_NWSR_OFFSET 0x00000008U /**< Network Status reg */ + +#define XEMACPS_DMACR_OFFSET 0x00000010U /**< DMA Control reg */ +#define XEMACPS_TXSR_OFFSET 0x00000014U /**< TX Status reg */ +#define XEMACPS_RXQBASE_OFFSET 0x00000018U /**< RX Q Base address reg */ +#define XEMACPS_TXQBASE_OFFSET 0x0000001CU /**< TX Q Base address reg */ +#define XEMACPS_RXSR_OFFSET 0x00000020U /**< RX Status reg */ + +#define XEMACPS_ISR_OFFSET 0x00000024U /**< Interrupt Status reg */ +#define XEMACPS_IER_OFFSET 0x00000028U /**< Interrupt Enable reg */ +#define XEMACPS_IDR_OFFSET 0x0000002CU /**< Interrupt Disable reg */ +#define XEMACPS_IMR_OFFSET 0x00000030U /**< Interrupt Mask reg */ + +#define XEMACPS_PHYMNTNC_OFFSET 0x00000034U /**< Phy Maintaince reg */ +#define XEMACPS_RXPAUSE_OFFSET 0x00000038U /**< RX Pause Time reg */ +#define XEMACPS_TXPAUSE_OFFSET 0x0000003CU /**< TX Pause Time reg */ + +#define XEMACPS_JUMBOMAXLEN_OFFSET 0x00000048U /**< Jumbo max length reg */ + +#define XEMACPS_RXWATERMARK_OFFSET 0x0000007CU /**< RX watermark reg */ + +#define XEMACPS_HASHL_OFFSET 0x00000080U /**< Hash Low address reg */ +#define XEMACPS_HASHH_OFFSET 0x00000084U /**< Hash High address reg */ + +#define XEMACPS_LADDR1L_OFFSET 0x00000088U /**< Specific1 addr low reg */ +#define XEMACPS_LADDR1H_OFFSET 0x0000008CU /**< Specific1 addr high reg */ +#define XEMACPS_LADDR2L_OFFSET 0x00000090U /**< Specific2 addr low reg */ +#define XEMACPS_LADDR2H_OFFSET 0x00000094U /**< Specific2 addr high reg */ +#define XEMACPS_LADDR3L_OFFSET 0x00000098U /**< Specific3 addr low reg */ +#define XEMACPS_LADDR3H_OFFSET 0x0000009CU /**< Specific3 addr high reg */ +#define XEMACPS_LADDR4L_OFFSET 0x000000A0U /**< Specific4 addr low reg */ +#define XEMACPS_LADDR4H_OFFSET 0x000000A4U /**< Specific4 addr high reg */ + +#define XEMACPS_MATCH1_OFFSET 0x000000A8U /**< Type ID1 Match reg */ +#define XEMACPS_MATCH2_OFFSET 0x000000ACU /**< Type ID2 Match reg */ +#define XEMACPS_MATCH3_OFFSET 0x000000B0U /**< Type ID3 Match reg */ +#define XEMACPS_MATCH4_OFFSET 0x000000B4U /**< Type ID4 Match reg */ + +#define XEMACPS_STRETCH_OFFSET 0x000000BCU /**< IPG Stretch reg */ + +#define XEMACPS_OCTTXL_OFFSET 0x00000100U /**< Octects transmitted Low + reg */ +#define XEMACPS_OCTTXH_OFFSET 0x00000104U /**< Octects transmitted High + reg */ + +#define XEMACPS_TXCNT_OFFSET 0x00000108U /**< Error-free Frmaes + transmitted counter */ +#define XEMACPS_TXBCCNT_OFFSET 0x0000010CU /**< Error-free Broadcast + Frames counter*/ +#define XEMACPS_TXMCCNT_OFFSET 0x00000110U /**< Error-free Multicast + Frame counter */ +#define XEMACPS_TXPAUSECNT_OFFSET 0x00000114U /**< Pause Frames Transmitted + Counter */ +#define XEMACPS_TX64CNT_OFFSET 0x00000118U /**< Error-free 64 byte Frames + Transmitted counter */ +#define XEMACPS_TX65CNT_OFFSET 0x0000011CU /**< Error-free 65-127 byte + Frames Transmitted + counter */ +#define XEMACPS_TX128CNT_OFFSET 0x00000120U /**< Error-free 128-255 byte + Frames Transmitted + counter*/ +#define XEMACPS_TX256CNT_OFFSET 0x00000124U /**< Error-free 256-511 byte + Frames transmitted + counter */ +#define XEMACPS_TX512CNT_OFFSET 0x00000128U /**< Error-free 512-1023 byte + Frames transmitted + counter */ +#define XEMACPS_TX1024CNT_OFFSET 0x0000012CU /**< Error-free 1024-1518 byte + Frames transmitted + counter */ +#define XEMACPS_TX1519CNT_OFFSET 0x00000130U /**< Error-free larger than + 1519 byte Frames + transmitted counter */ +#define XEMACPS_TXURUNCNT_OFFSET 0x00000134U /**< TX under run error + counter */ + +#define XEMACPS_SNGLCOLLCNT_OFFSET 0x00000138U /**< Single Collision Frame + Counter */ +#define XEMACPS_MULTICOLLCNT_OFFSET 0x0000013CU /**< Multiple Collision Frame + Counter */ +#define XEMACPS_EXCESSCOLLCNT_OFFSET 0x00000140U /**< Excessive Collision Frame + Counter */ +#define XEMACPS_LATECOLLCNT_OFFSET 0x00000144U /**< Late Collision Frame + Counter */ +#define XEMACPS_TXDEFERCNT_OFFSET 0x00000148U /**< Deferred Transmission + Frame Counter */ +#define XEMACPS_TXCSENSECNT_OFFSET 0x0000014CU /**< Transmit Carrier Sense + Error Counter */ + +#define XEMACPS_OCTRXL_OFFSET 0x00000150U /**< Octects Received register + Low */ +#define XEMACPS_OCTRXH_OFFSET 0x00000154U /**< Octects Received register + High */ + +#define XEMACPS_RXCNT_OFFSET 0x00000158U /**< Error-free Frames + Received Counter */ +#define XEMACPS_RXBROADCNT_OFFSET 0x0000015CU /**< Error-free Broadcast + Frames Received Counter */ +#define XEMACPS_RXMULTICNT_OFFSET 0x00000160U /**< Error-free Multicast + Frames Received Counter */ +#define XEMACPS_RXPAUSECNT_OFFSET 0x00000164U /**< Pause Frames + Received Counter */ +#define XEMACPS_RX64CNT_OFFSET 0x00000168U /**< Error-free 64 byte Frames + Received Counter */ +#define XEMACPS_RX65CNT_OFFSET 0x0000016CU /**< Error-free 65-127 byte + Frames Received Counter */ +#define XEMACPS_RX128CNT_OFFSET 0x00000170U /**< Error-free 128-255 byte + Frames Received Counter */ +#define XEMACPS_RX256CNT_OFFSET 0x00000174U /**< Error-free 256-512 byte + Frames Received Counter */ +#define XEMACPS_RX512CNT_OFFSET 0x00000178U /**< Error-free 512-1023 byte + Frames Received Counter */ +#define XEMACPS_RX1024CNT_OFFSET 0x0000017CU /**< Error-free 1024-1518 byte + Frames Received Counter */ +#define XEMACPS_RX1519CNT_OFFSET 0x00000180U /**< Error-free 1519-max byte + Frames Received Counter */ +#define XEMACPS_RXUNDRCNT_OFFSET 0x00000184U /**< Undersize Frames Received + Counter */ +#define XEMACPS_RXOVRCNT_OFFSET 0x00000188U /**< Oversize Frames Received + Counter */ +#define XEMACPS_RXJABCNT_OFFSET 0x0000018CU /**< Jabbers Received + Counter */ +#define XEMACPS_RXFCSCNT_OFFSET 0x00000190U /**< Frame Check Sequence + Error Counter */ +#define XEMACPS_RXLENGTHCNT_OFFSET 0x00000194U /**< Length Field Error + Counter */ +#define XEMACPS_RXSYMBCNT_OFFSET 0x00000198U /**< Symbol Error Counter */ +#define XEMACPS_RXALIGNCNT_OFFSET 0x0000019CU /**< Alignment Error Counter */ +#define XEMACPS_RXRESERRCNT_OFFSET 0x000001A0U /**< Receive Resource Error + Counter */ +#define XEMACPS_RXORCNT_OFFSET 0x000001A4U /**< Receive Overrun Counter */ +#define XEMACPS_RXIPCCNT_OFFSET 0x000001A8U /**< IP header Checksum Error + Counter */ +#define XEMACPS_RXTCPCCNT_OFFSET 0x000001ACU /**< TCP Checksum Error + Counter */ +#define XEMACPS_RXUDPCCNT_OFFSET 0x000001B0U /**< UDP Checksum Error + Counter */ +#define XEMACPS_LAST_OFFSET 0x000001B4U /**< Last statistic counter + offset, for clearing */ + +#define XEMACPS_1588_SEC_OFFSET 0x000001D0U /**< 1588 second counter */ +#define XEMACPS_1588_NANOSEC_OFFSET 0x000001D4U /**< 1588 nanosecond counter */ +#define XEMACPS_1588_ADJ_OFFSET 0x000001D8U /**< 1588 nanosecond + adjustment counter */ +#define XEMACPS_1588_INC_OFFSET 0x000001DCU /**< 1588 nanosecond + increment counter */ +#define XEMACPS_PTP_TXSEC_OFFSET 0x000001E0U /**< 1588 PTP transmit second + counter */ +#define XEMACPS_PTP_TXNANOSEC_OFFSET 0x000001E4U /**< 1588 PTP transmit + nanosecond counter */ +#define XEMACPS_PTP_RXSEC_OFFSET 0x000001E8U /**< 1588 PTP receive second + counter */ +#define XEMACPS_PTP_RXNANOSEC_OFFSET 0x000001ECU /**< 1588 PTP receive + nanosecond counter */ +#define XEMACPS_PTPP_TXSEC_OFFSET 0x000001F0U /**< 1588 PTP peer transmit + second counter */ +#define XEMACPS_PTPP_TXNANOSEC_OFFSET 0x000001F4U /**< 1588 PTP peer transmit + nanosecond counter */ +#define XEMACPS_PTPP_RXSEC_OFFSET 0x000001F8U /**< 1588 PTP peer receive + second counter */ +#define XEMACPS_PTPP_RXNANOSEC_OFFSET 0x000001FCU /**< 1588 PTP peer receive + nanosecond counter */ + +#define XEMACPS_INTQ1_STS_OFFSET 0x00000400U /**< Interrupt Q1 Status + reg */ +#define XEMACPS_TXQ1BASE_OFFSET 0x00000440U /**< TX Q1 Base address + reg */ +#define XEMACPS_RXQ1BASE_OFFSET 0x00000480U /**< RX Q1 Base address + reg */ +#define XEMACPS_MSBBUF_TXQBASE_OFFSET 0x000004C8U /**< MSB Buffer TX Q Base + reg */ +#define XEMACPS_MSBBUF_RXQBASE_OFFSET 0x000004D4U /**< MSB Buffer RX Q Base + reg */ +#define XEMACPS_INTQ1_IER_OFFSET 0x00000600U /**< Interrupt Q1 Enable + reg */ +#define XEMACPS_INTQ1_IDR_OFFSET 0x00000620U /**< Interrupt Q1 Disable + reg */ +#define XEMACPS_INTQ1_IMR_OFFSET 0x00000640U /**< Interrupt Q1 Mask + reg */ + +/* Define some bit positions for registers. */ + +/** @name network control register bit definitions + * @{ + */ +#define XEMACPS_NWCTRL_FLUSH_DPRAM_MASK 0x00040000U /**< Flush a packet from + Rx SRAM */ +#define XEMACPS_NWCTRL_ZEROPAUSETX_MASK 0x00000800U /**< Transmit zero quantum + pause frame */ +#define XEMACPS_NWCTRL_PAUSETX_MASK 0x00000800U /**< Transmit pause frame */ +#define XEMACPS_NWCTRL_HALTTX_MASK 0x00000400U /**< Halt transmission + after current frame */ +#define XEMACPS_NWCTRL_STARTTX_MASK 0x00000200U /**< Start tx (tx_go) */ + +#define XEMACPS_NWCTRL_STATWEN_MASK 0x00000080U /**< Enable writing to + stat counters */ +#define XEMACPS_NWCTRL_STATINC_MASK 0x00000040U /**< Increment statistic + registers */ +#define XEMACPS_NWCTRL_STATCLR_MASK 0x00000020U /**< Clear statistic + registers */ +#define XEMACPS_NWCTRL_MDEN_MASK 0x00000010U /**< Enable MDIO port */ +#define XEMACPS_NWCTRL_TXEN_MASK 0x00000008U /**< Enable transmit */ +#define XEMACPS_NWCTRL_RXEN_MASK 0x00000004U /**< Enable receive */ +#define XEMACPS_NWCTRL_LOOPEN_MASK 0x00000002U /**< local loopback */ +/*@}*/ + +/** @name network configuration register bit definitions + * @{ + */ +#define XEMACPS_NWCFG_BADPREAMBEN_MASK 0x20000000U /**< disable rejection of + non-standard preamble */ +#define XEMACPS_NWCFG_IPDSTRETCH_MASK 0x10000000U /**< enable transmit IPG */ +#define XEMACPS_NWCFG_SGMIIEN_MASK 0x08000000U /**< SGMII Enable */ +#define XEMACPS_NWCFG_FCSIGNORE_MASK 0x04000000U /**< disable rejection of + FCS error */ +#define XEMACPS_NWCFG_HDRXEN_MASK 0x02000000U /**< RX half duplex */ +#define XEMACPS_NWCFG_RXCHKSUMEN_MASK 0x01000000U /**< enable RX checksum + offload */ +#define XEMACPS_NWCFG_PAUSECOPYDI_MASK 0x00800000U /**< Do not copy pause + Frames to memory */ +#define XEMACPS_NWCFG_DWIDTH_64_MASK 0x00200000U /**< 64 bit Data bus width */ +#define XEMACPS_NWCFG_MDC_SHIFT_MASK 18U /**< shift bits for MDC */ +#define XEMACPS_NWCFG_MDCCLKDIV_MASK 0x001C0000U /**< MDC Mask PCLK divisor */ +#define XEMACPS_NWCFG_FCSREM_MASK 0x00020000U /**< Discard FCS from + received frames */ +#define XEMACPS_NWCFG_LENERRDSCRD_MASK 0x00010000U +/**< RX length error discard */ +#define XEMACPS_NWCFG_RXOFFS_MASK 0x0000C000U /**< RX buffer offset */ +#define XEMACPS_NWCFG_PAUSEEN_MASK 0x00002000U /**< Enable pause RX */ +#define XEMACPS_NWCFG_RETRYTESTEN_MASK 0x00001000U /**< Retry test */ +#define XEMACPS_NWCFG_XTADDMACHEN_MASK 0x00000200U +/**< External address match enable */ +#define XEMACPS_NWCFG_PCSSEL_MASK 0x00000800U /**< PCS Select */ +#define XEMACPS_NWCFG_1000_MASK 0x00000400U /**< 1000 Mbps */ +#define XEMACPS_NWCFG_1536RXEN_MASK 0x00000100U /**< Enable 1536 byte + frames reception */ +#define XEMACPS_NWCFG_UCASTHASHEN_MASK 0x00000080U /**< Receive unicast hash + frames */ +#define XEMACPS_NWCFG_MCASTHASHEN_MASK 0x00000040U /**< Receive multicast hash + frames */ +#define XEMACPS_NWCFG_BCASTDI_MASK 0x00000020U /**< Do not receive + broadcast frames */ +#define XEMACPS_NWCFG_COPYALLEN_MASK 0x00000010U /**< Copy all frames */ +#define XEMACPS_NWCFG_JUMBO_MASK 0x00000008U /**< Jumbo frames */ +#define XEMACPS_NWCFG_NVLANDISC_MASK 0x00000004U /**< Receive only VLAN + frames */ +#define XEMACPS_NWCFG_FDEN_MASK 0x00000002U/**< full duplex */ +#define XEMACPS_NWCFG_100_MASK 0x00000001U /**< 100 Mbps */ +#define XEMACPS_NWCFG_RESET_MASK 0x00080000U/**< reset value */ +/*@}*/ + +/** @name network status register bit definitaions + * @{ + */ +#define XEMACPS_NWSR_MDIOIDLE_MASK 0x00000004U /**< PHY management idle */ +#define XEMACPS_NWSR_MDIO_MASK 0x00000002U /**< Status of mdio_in */ +/*@}*/ + + +/** @name MAC address register word 1 mask + * @{ + */ +#define XEMACPS_LADDR_MACH_MASK 0x0000FFFFU /**< Address bits[47:32] + bit[31:0] are in BOTTOM */ +/*@}*/ + + +/** @name DMA control register bit definitions + * @{ + */ +#define XEMACPS_DMACR_ADDR_WIDTH_64 0x40000000U /**< 64 bit address bus */ +#define XEMACPS_DMACR_TXEXTEND_MASK 0x20000000U /**< Tx Extended desc mode */ +#define XEMACPS_DMACR_RXEXTEND_MASK 0x10000000U /**< Rx Extended desc mode */ +#define XEMACPS_DMACR_RXBUF_MASK 0x00FF0000U /**< Mask bit for RX buffer + size */ +#define XEMACPS_DMACR_RXBUF_SHIFT 16U /**< Shift bit for RX buffer + size */ +#define XEMACPS_DMACR_TCPCKSUM_MASK 0x00000800U /**< enable/disable TX + checksum offload */ +#define XEMACPS_DMACR_TXSIZE_MASK 0x00000400U /**< TX buffer memory size */ +#define XEMACPS_DMACR_RXSIZE_MASK 0x00000300U /**< RX buffer memory size */ +#define XEMACPS_DMACR_ENDIAN_MASK 0x00000080U /**< endian configuration */ +#define XEMACPS_DMACR_BLENGTH_MASK 0x0000001FU /**< buffer burst length */ +#define XEMACPS_DMACR_SINGLE_AHB_BURST 0x00000001U /**< single AHB bursts */ +#define XEMACPS_DMACR_INCR4_AHB_BURST 0x00000004U /**< 4 bytes AHB bursts */ +#define XEMACPS_DMACR_INCR8_AHB_BURST 0x00000008U /**< 8 bytes AHB bursts */ +#define XEMACPS_DMACR_INCR16_AHB_BURST 0x00000010U /**< 16 bytes AHB bursts */ +/*@}*/ + +/** @name transmit status register bit definitions + * @{ + */ +#define XEMACPS_TXSR_HRESPNOK_MASK 0x00000100U /**< Transmit hresp not OK */ +#define XEMACPS_TXSR_URUN_MASK 0x00000040U /**< Transmit underrun */ +#define XEMACPS_TXSR_TXCOMPL_MASK 0x00000020U /**< Transmit completed OK */ +#define XEMACPS_TXSR_BUFEXH_MASK 0x00000010U /**< Transmit buffs exhausted + mid frame */ +#define XEMACPS_TXSR_TXGO_MASK 0x00000008U /**< Status of go flag */ +#define XEMACPS_TXSR_RXOVR_MASK 0x00000004U /**< Retry limit exceeded */ +#define XEMACPS_TXSR_FRAMERX_MASK 0x00000002U /**< Collision tx frame */ +#define XEMACPS_TXSR_USEDREAD_MASK 0x00000001U /**< TX buffer used bit set */ + +#define XEMACPS_TXSR_ERROR_MASK ((u32)XEMACPS_TXSR_HRESPNOK_MASK | \ + (u32)XEMACPS_TXSR_URUN_MASK | \ + (u32)XEMACPS_TXSR_BUFEXH_MASK | \ + (u32)XEMACPS_TXSR_RXOVR_MASK | \ + (u32)XEMACPS_TXSR_FRAMERX_MASK | \ + (u32)XEMACPS_TXSR_USEDREAD_MASK) +/*@}*/ + +/** + * @name receive status register bit definitions + * @{ + */ +#define XEMACPS_RXSR_HRESPNOK_MASK 0x00000008U /**< Receive hresp not OK */ +#define XEMACPS_RXSR_RXOVR_MASK 0x00000004U /**< Receive overrun */ +#define XEMACPS_RXSR_FRAMERX_MASK 0x00000002U /**< Frame received OK */ +#define XEMACPS_RXSR_BUFFNA_MASK 0x00000001U /**< RX buffer used bit set */ + +#define XEMACPS_RXSR_ERROR_MASK ((u32)XEMACPS_RXSR_HRESPNOK_MASK | \ + (u32)XEMACPS_RXSR_RXOVR_MASK | \ + (u32)XEMACPS_RXSR_BUFFNA_MASK) + +#define XEMACPS_SR_ALL_MASK 0xFFFFFFFFU /**< Mask for full register */ + +/*@}*/ + +/** + * @name Interrupt Q1 status register bit definitions + * @{ + */ +#define XEMACPS_INTQ1SR_TXCOMPL_MASK 0x00000080U /**< Transmit completed OK */ +#define XEMACPS_INTQ1SR_TXERR_MASK 0x00000040U /**< Transmit AMBA Error */ + +#define XEMACPS_INTQ1_IXR_ALL_MASK ((u32)XEMACPS_INTQ1SR_TXCOMPL_MASK | \ + (u32)XEMACPS_INTQ1SR_TXERR_MASK) + +/*@}*/ + +/** + * @name interrupts bit definitions + * Bits definitions are same in XEMACPS_ISR_OFFSET, + * XEMACPS_IER_OFFSET, XEMACPS_IDR_OFFSET, and XEMACPS_IMR_OFFSET + * @{ + */ +#define XEMACPS_IXR_PTPPSTX_MASK 0x02000000U /**< PTP Pdelay_resp TXed */ +#define XEMACPS_IXR_PTPPDRTX_MASK 0x01000000U /**< PTP Pdelay_req TXed */ +#define XEMACPS_IXR_PTPPSRX_MASK 0x00800000U /**< PTP Pdelay_resp RXed */ +#define XEMACPS_IXR_PTPPDRRX_MASK 0x00400000U /**< PTP Pdelay_req RXed */ + +#define XEMACPS_IXR_PTPSTX_MASK 0x00200000U /**< PTP Sync TXed */ +#define XEMACPS_IXR_PTPDRTX_MASK 0x00100000U /**< PTP Delay_req TXed */ +#define XEMACPS_IXR_PTPSRX_MASK 0x00080000U /**< PTP Sync RXed */ +#define XEMACPS_IXR_PTPDRRX_MASK 0x00040000U /**< PTP Delay_req RXed */ + +#define XEMACPS_IXR_PAUSETX_MASK 0x00004000U /**< Pause frame transmitted */ +#define XEMACPS_IXR_PAUSEZERO_MASK 0x00002000U /**< Pause time has reached + zero */ +#define XEMACPS_IXR_PAUSENZERO_MASK 0x00001000U /**< Pause frame received */ +#define XEMACPS_IXR_HRESPNOK_MASK 0x00000800U /**< hresp not ok */ +#define XEMACPS_IXR_RXOVR_MASK 0x00000400U /**< Receive overrun occurred */ +#define XEMACPS_IXR_TXCOMPL_MASK 0x00000080U /**< Frame transmitted ok */ +#define XEMACPS_IXR_TXEXH_MASK 0x00000040U /**< Transmit err occurred or + no buffers*/ +#define XEMACPS_IXR_RETRY_MASK 0x00000020U /**< Retry limit exceeded */ +#define XEMACPS_IXR_URUN_MASK 0x00000010U /**< Transmit underrun */ +#define XEMACPS_IXR_TXUSED_MASK 0x00000008U /**< Tx buffer used bit read */ +#define XEMACPS_IXR_RXUSED_MASK 0x00000004U /**< Rx buffer used bit read */ +#define XEMACPS_IXR_FRAMERX_MASK 0x00000002U /**< Frame received ok */ +#define XEMACPS_IXR_MGMNT_MASK 0x00000001U /**< PHY management complete */ +#define XEMACPS_IXR_ALL_MASK 0x00007FFFU /**< Everything! */ + +#define XEMACPS_IXR_TX_ERR_MASK ((u32)XEMACPS_IXR_TXEXH_MASK | \ + (u32)XEMACPS_IXR_RETRY_MASK | \ + (u32)XEMACPS_IXR_URUN_MASK) + + +#define XEMACPS_IXR_RX_ERR_MASK ((u32)XEMACPS_IXR_HRESPNOK_MASK | \ + (u32)XEMACPS_IXR_RXUSED_MASK | \ + (u32)XEMACPS_IXR_RXOVR_MASK) + +/*@}*/ + +/** @name PHY Maintenance bit definitions + * @{ + */ +#define XEMACPS_PHYMNTNC_OP_MASK 0x40020000U /**< operation mask bits */ +#define XEMACPS_PHYMNTNC_OP_R_MASK 0x20000000U /**< read operation */ +#define XEMACPS_PHYMNTNC_OP_W_MASK 0x10000000U /**< write operation */ +#define XEMACPS_PHYMNTNC_ADDR_MASK 0x0F800000U /**< Address bits */ +#define XEMACPS_PHYMNTNC_REG_MASK 0x007C0000U /**< register bits */ +#define XEMACPS_PHYMNTNC_DATA_MASK 0x00000FFFU /**< data bits */ +#define XEMACPS_PHYMNTNC_PHAD_SHFT_MSK 23U /**< Shift bits for PHYAD */ +#define XEMACPS_PHYMNTNC_PREG_SHFT_MSK 18U /**< Shift bits for PHREG */ +/*@}*/ + +/** @name RX watermark bit definitions + * @{ + */ +#define XEMACPS_RXWM_HIGH_MASK 0x0000FFFFU /**< RXWM high mask */ +#define XEMACPS_RXWM_LOW_MASK 0xFFFF0000U /**< RXWM low mask */ +#define XEMACPS_RXWM_LOW_SHFT_MSK 16U /**< Shift for RXWM low */ +/*@}*/ + +/* Transmit buffer descriptor status words offset + * @{ + */ +#define XEMACPS_BD_ADDR_OFFSET 0x00000000U /**< word 0/addr of BDs */ +#define XEMACPS_BD_STAT_OFFSET 0x00000004U /**< word 1/status of BDs */ +#define XEMACPS_BD_ADDR_HI_OFFSET 0x00000008U /**< word 2/addr of BDs */ + +/* + * @} + */ + +/* Transmit buffer descriptor status words bit positions. + * Transmit buffer descriptor consists of two 32-bit registers, + * the first - word0 contains a 32-bit address pointing to the location of + * the transmit data. + * The following register - word1, consists of various information to control + * the XEmacPs transmit process. After transmit, this is updated with status + * information, whether the frame was transmitted OK or why it had failed. + * @{ + */ +#define XEMACPS_TXBUF_USED_MASK 0x80000000U /**< Used bit. */ +#define XEMACPS_TXBUF_WRAP_MASK 0x40000000U /**< Wrap bit, last descriptor */ +#define XEMACPS_TXBUF_RETRY_MASK 0x20000000U /**< Retry limit exceeded */ +#define XEMACPS_TXBUF_URUN_MASK 0x10000000U /**< Transmit underrun occurred */ +#define XEMACPS_TXBUF_EXH_MASK 0x08000000U /**< Buffers exhausted */ +#define XEMACPS_TXBUF_TCP_MASK 0x04000000U /**< Late collision. */ +#define XEMACPS_TXBUF_NOCRC_MASK 0x00010000U /**< No CRC */ +#define XEMACPS_TXBUF_LAST_MASK 0x00008000U /**< Last buffer */ +#define XEMACPS_TXBUF_LEN_MASK 0x00003FFFU /**< Mask for length field */ +/* + * @} + */ + +/* Receive buffer descriptor status words bit positions. + * Receive buffer descriptor consists of two 32-bit registers, + * the first - word0 contains a 32-bit word aligned address pointing to the + * address of the buffer. The lower two bits make up the wrap bit indicating + * the last descriptor and the ownership bit to indicate it has been used by + * the XEmacPs. + * The following register - word1, contains status information regarding why + * the frame was received (the filter match condition) as well as other + * useful info. + * @{ + */ +#define XEMACPS_RXBUF_BCAST_MASK 0x80000000U /**< Broadcast frame */ +#define XEMACPS_RXBUF_MULTIHASH_MASK 0x40000000U /**< Multicast hashed frame */ +#define XEMACPS_RXBUF_UNIHASH_MASK 0x20000000U /**< Unicast hashed frame */ +#define XEMACPS_RXBUF_EXH_MASK 0x08000000U /**< buffer exhausted */ +#define XEMACPS_RXBUF_AMATCH_MASK 0x06000000U /**< Specific address + matched */ +#define XEMACPS_RXBUF_IDFOUND_MASK 0x01000000U /**< Type ID matched */ +#define XEMACPS_RXBUF_IDMATCH_MASK 0x00C00000U /**< ID matched mask */ +#define XEMACPS_RXBUF_VLAN_MASK 0x00200000U /**< VLAN tagged */ +#define XEMACPS_RXBUF_PRI_MASK 0x00100000U /**< Priority tagged */ +#define XEMACPS_RXBUF_VPRI_MASK 0x000E0000U /**< Vlan priority */ +#define XEMACPS_RXBUF_CFI_MASK 0x00010000U /**< CFI frame */ +#define XEMACPS_RXBUF_EOF_MASK 0x00008000U /**< End of frame. */ +#define XEMACPS_RXBUF_SOF_MASK 0x00004000U /**< Start of frame. */ +#define XEMACPS_RXBUF_LEN_MASK 0x00001FFFU /**< Mask for length field */ +#define XEMACPS_RXBUF_LEN_JUMBO_MASK 0x00003FFFU /**< Mask for jumbo length */ + +#define XEMACPS_RXBUF_WRAP_MASK 0x00000002U /**< Wrap bit, last BD */ +#define XEMACPS_RXBUF_NEW_MASK 0x00000001U /**< Used bit.. */ +#define XEMACPS_RXBUF_ADD_MASK 0xFFFFFFFCU /**< Mask for address */ +/* + * @} + */ + +/* + * Define appropriate I/O access method to memory mapped I/O or other + * interface if necessary. + */ + +#define XEmacPs_In32 Xil_In32 +#define XEmacPs_Out32 Xil_Out32 + + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddress 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 +* C-style signature: +* u32 XEmacPs_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XEmacPs_ReadReg(BaseAddress, RegOffset) \ + XEmacPs_In32((BaseAddress) + (u32)(RegOffset)) + + +/****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddress 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 +* C-style signature: +* void XEmacPs_WriteReg(u32 BaseAddress, u32 RegOffset, +* u32 Data) +* +*****************************************************************************/ +#define XEmacPs_WriteReg(BaseAddress, RegOffset, Data) \ + XEmacPs_Out32((BaseAddress) + (u32)(RegOffset), (u32)(Data)) + +/************************** Function Prototypes *****************************/ +/* + * Perform reset operation to the emacps interface + */ +void XEmacPs_ResetHw(u32 BaseAddr); + +#ifdef __cplusplus + } +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c new file mode 100644 index 0000000000..cd9335ace6 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c @@ -0,0 +1,242 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_intr.c +* @addtogroup emacps_v3_11 +* @{ +* +* Functions in this file implement general purpose interrupt processing related +* functionality. See xemacps.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 1.03a asa  01/24/13 Fix for CR #692702 which updates error handling for
+*		      Rx errors. Under heavy Rx traffic, there will be a large
+*		      number of errors related to receive buffer not available.
+*		      Because of a HW bug (SI #692601), under such heavy errors,
+*		      the Rx data path can become unresponsive. To reduce the
+*		      probabilities for hitting this HW bug, the SW writes to
+*		      bit 18 to flush a packet from Rx DPRAM immediately. The
+*		      changes for it are done in the function
+*		      XEmacPs_IntrHandler.
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification
+*		       and 64-bit changes.
+* 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1   hk   07/27/15 Do not call error handler with '0' error code when
+*                     there is no error. CR# 869403
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xemacps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** + * Install an asynchronous handler function for the given HandlerType: + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param HandlerType indicates what interrupt handler type is. + * XEMACPS_HANDLER_DMASEND, XEMACPS_HANDLER_DMARECV and + * XEMACPS_HANDLER_ERROR. + * @param FuncPointer is the pointer to the callback function + * @param CallBackRef is the upper layer callback reference passed back when + * when the callback function is invoked. + * + * @return + * + * None. + * + * @note + * There is no assert on the CallBackRef since the driver doesn't know what + * it is. + * + *****************************************************************************/ +LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType, + void *FuncPointer, void *CallBackRef) +{ + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(FuncPointer != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + switch (HandlerType) { + case XEMACPS_HANDLER_DMASEND: + Status = (LONG)(XST_SUCCESS); + InstancePtr->SendHandler = ((XEmacPs_Handler)(void *)FuncPointer); + InstancePtr->SendRef = CallBackRef; + break; + case XEMACPS_HANDLER_DMARECV: + Status = (LONG)(XST_SUCCESS); + InstancePtr->RecvHandler = ((XEmacPs_Handler)(void *)FuncPointer); + InstancePtr->RecvRef = CallBackRef; + break; + case XEMACPS_HANDLER_ERROR: + Status = (LONG)(XST_SUCCESS); + InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void *)FuncPointer); + InstancePtr->ErrorRef = CallBackRef; + break; + default: + Status = (LONG)(XST_INVALID_PARAM); + break; + } + return Status; +} + +/*****************************************************************************/ +/** +* Master interrupt handler for EMAC driver. This routine will query the +* status of the device, bump statistics, and invoke user callbacks. +* +* This routine must be connected to an interrupt controller using OS/BSP +* specific methods. +* +* @param XEmacPsPtr is a pointer to the XEMACPS instance that has caused the +* interrupt. +* +******************************************************************************/ +void XEmacPs_IntrHandler(void *XEmacPsPtr) +{ + u32 RegISR; + u32 RegSR; + u32 RegCtrl; + u32 RegQ1ISR = 0U; + XEmacPs *InstancePtr = (XEmacPs *) XEmacPsPtr; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* This ISR will try to handle as many interrupts as it can in a single + * call. However, in most of the places where the user's error handler + * is called, this ISR exits because it is expected that the user will + * reset the device in nearly all instances. + */ + RegISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_ISR_OFFSET); + + /* Read Transmit Q1 ISR */ + + if (InstancePtr->Version > 2) + RegQ1ISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_INTQ1_STS_OFFSET); + + /* Clear the interrupt status register */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, + RegISR); + + /* Receive complete interrupt */ + if ((RegISR & XEMACPS_IXR_FRAMERX_MASK) != 0x00000000U) { + /* Clear RX status register RX complete indication but preserve + * error bits if there is any */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXSR_OFFSET, + ((u32)XEMACPS_RXSR_FRAMERX_MASK | + (u32)XEMACPS_RXSR_BUFFNA_MASK)); + InstancePtr->RecvHandler(InstancePtr->RecvRef); + } + + /* Transmit Q1 complete interrupt */ + if ((InstancePtr->Version > 2) && + ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) { + /* Clear TX status register TX complete indication but preserve + * error bits if there is any */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_INTQ1_STS_OFFSET, + XEMACPS_INTQ1SR_TXCOMPL_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET, + ((u32)XEMACPS_TXSR_TXCOMPL_MASK | + (u32)XEMACPS_TXSR_USEDREAD_MASK)); + InstancePtr->SendHandler(InstancePtr->SendRef); + } + + /* Transmit complete interrupt */ + if ((RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U) { + /* Clear TX status register TX complete indication but preserve + * error bits if there is any */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET, + ((u32)XEMACPS_TXSR_TXCOMPL_MASK | + (u32)XEMACPS_TXSR_USEDREAD_MASK)); + InstancePtr->SendHandler(InstancePtr->SendRef); + } + + /* Receive error conditions interrupt */ + if ((RegISR & XEMACPS_IXR_RX_ERR_MASK) != 0x00000000U) { + /* Clear RX status register */ + RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXSR_OFFSET); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXSR_OFFSET, RegSR); + + /* Fix for CR # 692702. Write to bit 18 of net_ctrl + * register to flush a packet out of Rx SRAM upon + * an error for receive buffer not available. */ + if ((RegISR & XEMACPS_IXR_RXUSED_MASK) != 0x00000000U) { + RegCtrl = + XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + RegCtrl |= (u32)XEMACPS_NWCTRL_FLUSH_DPRAM_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, RegCtrl); + } + + if(RegSR != 0) { + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, + XEMACPS_RECV, RegSR); + } + } + + /* When XEMACPS_IXR_TXCOMPL_MASK is flagged, XEMACPS_IXR_TXUSED_MASK + * will be asserted the same time. + * Have to distinguish this bit to handle the real error condition. + */ + /* Transmit Q1 error conditions interrupt */ + if ((InstancePtr->Version > 2) && + ((RegQ1ISR & XEMACPS_INTQ1SR_TXERR_MASK) != 0x00000000U) && + ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) { + /* Clear Interrupt Q1 status register */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_INTQ1_STS_OFFSET, RegQ1ISR); + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, + RegQ1ISR); + } + + /* Transmit error conditions interrupt */ + if (((RegISR & XEMACPS_IXR_TX_ERR_MASK) != 0x00000000U) && + (!(RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U)) { + /* Clear TX status register */ + RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET, RegSR); + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, + RegSR); + } + +} +/** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c new file mode 100644 index 0000000000..a16201e939 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c @@ -0,0 +1,71 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_sinit.c +* @addtogroup emacps_v3_11 +* @{ +* +* This file contains lookup method by device ID when success, it returns +* pointer to config table to be used to initialize the device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 New
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xemacps.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/*************************** Variable Definitions *****************************/ +extern XEmacPs_Config XEmacPs_ConfigTable[XPAR_XEMACPS_NUM_INSTANCES]; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return +* A pointer to the configuration table entry corresponding to the given +* device ID, or NULL if no match is found. +* +******************************************************************************/ +XEmacPs_Config *XEmacPs_LookupConfig(u16 DeviceId) +{ + XEmacPs_Config *CfgPtr = NULL; + u32 i; + + for (i = 0U; i < (u32)XPAR_XEMACPS_NUM_INSTANCES; i++) { + if (XEmacPs_ConfigTable[i].DeviceId == DeviceId) { + CfgPtr = &XEmacPs_ConfigTable[i]; + break; + } + } + + return (XEmacPs_Config *)(CfgPtr); +} +/** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h index b49a864dc6..eca569e5b4 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h @@ -21,7 +21,7 @@ static inline void usleep(unsigned long useconds) static inline void sleep(unsigned int seconds) { - rt_thread_delay(seconds); + rt_thread_delay(seconds*RT_TICK_PER_SECOND); } #ifdef __cplusplus diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/SConscript b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/SConscript new file mode 100644 index 0000000000..8e5fc7069e --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/SConscript @@ -0,0 +1,15 @@ +import rtconfig +from building import * + +# get current directory +cwd = GetCurrentDir() +CPPPATH = [cwd] + +# The set of source files associated with this SConscript file. + +src = Glob('*.c') +path = cwd + +group = DefineGroup('ZYNQMP_HAL', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') \ No newline at end of file diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h new file mode 100644 index 0000000000..aaff03e647 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2007 - 2019 Xilinx, Inc. + * Copyright (C) 2021 WangHuachen. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __XADAPTER_H_ +#define __XADAPTER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwipopts.h" + +#if !NO_SYS +#ifdef OS_IS_XILKERNEL +#include "xmk.h" +#endif +#include "lwip/sys.h" +#endif + +#include "lwip/netif.h" +#include "lwip/ip.h" + +#include "netif/xtopology.h" +#include + +struct xemac_s { + enum xemac_types type; + int topology_index; + void *state; +#if 0 + sys_sem_t sem_rx_data_available; +#else + struct eth_device *rt_eth_device; +#endif +#if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5) + TimerHandle_t xTimer; +#endif +}; + +enum ethernet_link_status { + ETH_LINK_UNDEFINED = 0, + ETH_LINK_UP, + ETH_LINK_DOWN, + ETH_LINK_NEGOTIATING +}; + +void eth_link_detect(struct netif *netif); +void lwip_raw_init(); +int xemacif_input(struct netif *netif); +void xemacif_input_thread(struct netif *netif); +struct netif * xemac_add(struct netif *netif, + ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw, + unsigned char *mac_ethernet_address, + unsigned mac_baseaddr); +#if defined (__arm__) || defined (__aarch64__) +void xemacpsif_resetrx_on_no_rxdata(struct netif *netif); +#endif + +/* global lwip debug variable used for debugging */ +extern int lwip_runtime_debug; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h new file mode 100644 index 0000000000..796cdd7f66 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2010 - 2019 Xilinx, Inc. + * Copyright (C) 2021 WangHuachen. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __NETIF_XEMACPSIF_H__ +#define __NETIF_XEMACPSIF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xlwipconfig.h" +#include "lwip/netif.h" +#include "netif/etharp.h" +#include "lwip/sys.h" +#include "netif/xadapter.h" + +#include "xstatus.h" +#include "sleep.h" +#include "xparameters.h" +#include "xparameters_ps.h" /* defines XPAR values */ +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +// #include "xil_exception.h" +// #include "xpseudo_asm.h" +#include "xpseudo_asm_gcc.h" +#include "xil_cache.h" +#include "xil_printf.h" +// #include "xscugic.h" +#include "xemacps.h" /* defines XEmacPs API */ + +#include "netif/xpqueue.h" +#include "xlwipconfig.h" + +#if EL1_NONSECURE +#include "xil_smc.h" +#endif + +#define ZYNQ_EMACPS_0_BASEADDR 0xE000B000 +#define ZYNQ_EMACPS_1_BASEADDR 0xE000C000 + +#define ZYNQMP_EMACPS_0_BASEADDR 0xFF0B0000 +#define ZYNQMP_EMACPS_1_BASEADDR 0xFF0C0000 +#define ZYNQMP_EMACPS_2_BASEADDR 0xFF0D0000 +#define ZYNQMP_EMACPS_3_BASEADDR 0xFF0E0000 + +#define CRL_APB_GEM0_REF_CTRL 0xFF5E0050 +#define CRL_APB_GEM1_REF_CTRL 0xFF5E0054 +#define CRL_APB_GEM2_REF_CTRL 0xFF5E0058 +#define CRL_APB_GEM3_REF_CTRL 0xFF5E005C + +#define CRL_APB_GEM_DIV0_MASK 0x00003F00 +#define CRL_APB_GEM_DIV0_SHIFT 8 +#define CRL_APB_GEM_DIV1_MASK 0x003F0000 +#define CRL_APB_GEM_DIV1_SHIFT 16 + +#define VERSAL_EMACPS_0_BASEADDR 0xFF0C0000 +#define VERSAL_EMACPS_1_BASEADDR 0xFF0D0000 + +#define VERSAL_CRL_GEM0_REF_CTRL 0xFF5E0118 +#define VERSAL_CRL_GEM1_REF_CTRL 0xFF5E011C + +#define VERSAL_CRL_GEM_DIV_MASK 0x0003FF00 +#define VERSAL_CRL_APB_GEM_DIV_SHIFT 8 + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (__MICROBLAZE__) +#if defined (USE_JUMBO_FRAMES) +#define ZYNQMP_USE_JUMBO +#endif +#endif + +#define GEM_VERSION_ZYNQMP 7 +#define GEM_VERSION_VERSAL 0x107 + +#define MAX_FRAME_SIZE_JUMBO (XEMACPS_MTU_JUMBO + XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE) + +void xemacpsif_setmac(u32_t index, u8_t *addr); +u8_t* xemacpsif_getmac(u32_t index); +err_t xemacpsif_init(struct netif *netif); +s32_t xemacpsif_input(struct netif *netif); + +/* xaxiemacif_hw.c */ +void xemacps_error_handler(XEmacPs * Temac); + +/* structure within each netif, encapsulating all information required for + * using a particular temac instance + */ +typedef struct { + XEmacPs emacps; + + /* queue to store overflow packets */ + pq_queue_t *recv_q; + pq_queue_t *send_q; + + /* pointers to memory holding buffer descriptors (used only with SDMA) */ + void *rx_bdspace; + void *tx_bdspace; + + unsigned int last_rx_frms_cntr; + +} xemacpsif_s; + +extern xemacpsif_s xemacpsif; + +s32_t is_tx_space_available(xemacpsif_s *emac); + +/* xemacpsif_dma.c */ + +void process_sent_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *txring); +u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr); +void detect_phy(XEmacPs *xemacpsp); +void emacps_send_handler(void *arg); +XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p); +void emacps_recv_handler(void *arg); +void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord); +void setup_rx_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *rxring); +void HandleTxErrors(struct xemac_s *xemac); +void HandleEmacPsError(struct xemac_s *xemac); +XEmacPs_Config *xemacps_lookup_config(unsigned mac_base); +void init_emacps(xemacpsif_s *xemacps, struct netif *netif); +void setup_isr (struct xemac_s *xemac); +XStatus init_dma(struct xemac_s *xemac); +void start_emacps (xemacpsif_s *xemacps); +void free_txrx_pbufs(xemacpsif_s *xemacpsif); +void free_onlytx_pbufs(xemacpsif_s *xemacpsif); +void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif); +void clean_dma_txdescs(struct xemac_s *xemac); +void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif); +void reset_dma(struct xemac_s *xemac); + +#ifdef __cplusplus +} +#endif + +#endif /* __NETIF_XAXIEMACIF_H__ */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h new file mode 100644 index 0000000000..132f02fb38 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007 - 2019 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __LWIP_PBUF_QUEUE_H_ +#define __LWIP_PBUF_QUEUE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define PQ_QUEUE_SIZE 4096 + +typedef struct { + void *data[PQ_QUEUE_SIZE]; + int head, tail, len; +} pq_queue_t; + +pq_queue_t* pq_create_queue(); +int pq_enqueue(pq_queue_t *q, void *p); +void* pq_dequeue(pq_queue_t *q); +int pq_qlength(pq_queue_t *q); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h new file mode 100644 index 0000000000..f3474cba7c --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007 - 2019 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __XTOPOLOGY_H_ +#define __XTOPOLOGY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps }; + +struct xtopology_t { + unsigned emac_baseaddr; + enum xemac_types emac_type; + unsigned intc_baseaddr; + unsigned intc_emac_intr; /* valid only for xemac_type_xps_emaclite */ + unsigned scugic_baseaddr; /* valid only for Zynq */ + unsigned scugic_emac_intr; /* valid only for GEM */ +}; + +extern int xtopology_n_emacs; +extern struct xtopology_t xtopology[]; + +int xtopology_find_index(unsigned base); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c new file mode 100644 index 0000000000..a9ed329d58 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2007 - 2019 Xilinx, Inc. + * Copyright (C) 2021 WangHuachen. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwipopts.h" +#include "xlwipconfig.h" +#include "xemac_ieee_reg.h" + +#if !NO_SYS +#ifdef OS_IS_XILKERNEL +#include "xmk.h" +#include "sys/process.h" +#endif +#endif + +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/ip.h" +#include "lwip/tcp.h" +#include "lwip/udp.h" +#include "lwip/priv/tcp_priv.h" + +#include "netif/etharp.h" +#include "netif/xadapter.h" + +#ifdef XLWIP_CONFIG_INCLUDE_EMACLITE +#include "netif/xemacliteif.h" +#endif + +#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET +#include "netif/xaxiemacif.h" +#endif + +#ifdef XLWIP_CONFIG_INCLUDE_GEM +#include "netif/xemacpsif.h" +#endif + +#if !NO_SYS +#include "lwip/tcpip.h" +#endif + +#ifdef OS_IS_FREERTOS +#define THREAD_STACKSIZE 256 +#define LINK_DETECT_THREAD_INTERVAL 1000 /* one second */ + +void link_detect_thread(void *p); +#endif + +/* global lwip debug variable used for debugging */ +int lwip_runtime_debug = 0; + +enum ethernet_link_status eth_link_status = ETH_LINK_UNDEFINED; +u32_t phyaddrforemac; + +void +lwip_raw_init() +{ + ip_init(); /* Doesn't do much, it should be called to handle future changes. */ +#if LWIP_UDP + udp_init(); /* Clears the UDP PCB list. */ +#endif +#if LWIP_TCP + tcp_init(); /* Clears the TCP PCB list and clears some internal TCP timers. */ + /* Note: you must call tcp_fasttmr() and tcp_slowtmr() at the */ + /* predefined regular intervals after this initialization. */ +#endif +} + +static enum xemac_types +find_mac_type(unsigned base) +{ + int i; + + for (i = 0; i < xtopology_n_emacs; i++) { + if (xtopology[i].emac_baseaddr == base) + return xtopology[i].emac_type; + } + + return xemac_type_unknown; +} + +int +xtopology_find_index(unsigned base) +{ + int i; + + for (i = 0; i < xtopology_n_emacs; i++) { + if (xtopology[i].emac_baseaddr == base) + return i; + } + + return -1; +} + +/* + * xemac_add: this is a wrapper around lwIP's netif_add function. + * The objective is to provide portability between the different Xilinx MAC's + * This function can be used to add both xps_ethernetlite and xps_ll_temac + * based interfaces + */ +struct netif * +xemac_add(struct netif *netif, + ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw, + unsigned char *mac_ethernet_address, + unsigned mac_baseaddr) +{ + int i; + +#ifdef OS_IS_FREERTOS + /* Start thread to detect link periodically for Hot Plug autodetect */ + sys_thread_new("link_detect_thread", link_detect_thread, netif, + THREAD_STACKSIZE, tskIDLE_PRIORITY); +#endif + + /* set mac address */ + netif->hwaddr_len = 6; + for (i = 0; i < 6; i++) + netif->hwaddr[i] = mac_ethernet_address[i]; + + /* initialize based on MAC type */ + switch (find_mac_type(mac_baseaddr)) { + case xemac_type_xps_emaclite: +#ifdef XLWIP_CONFIG_INCLUDE_EMACLITE + return netif_add(netif, ipaddr, netmask, gw, + (void*)(UINTPTR)mac_baseaddr, + xemacliteif_init, +#if NO_SYS + ethernet_input +#else + tcpip_input +#endif + ); +#else + return NULL; +#endif + case xemac_type_axi_ethernet: +#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET + return netif_add(netif, ipaddr, netmask, gw, + (void*)(UINTPTR)mac_baseaddr, + xaxiemacif_init, +#if NO_SYS + ethernet_input +#else + tcpip_input +#endif + ); +#else + return NULL; +#endif +#if defined (__arm__) || defined (__aarch64__) + case xemac_type_emacps: +#ifdef XLWIP_CONFIG_INCLUDE_GEM + return netif_add(netif, ipaddr, netmask, gw, + (void*)(UINTPTR)mac_baseaddr, + xemacpsif_init, +#if NO_SYS + ethernet_input +#else + tcpip_input +#endif + + ); +#endif +#endif + default: + xil_printf("unable to determine type of EMAC with baseaddress 0x%08x\r\n", + mac_baseaddr); + return NULL; + } +} + +#if 0 +/* + * The input thread calls lwIP to process any received packets. + * This thread waits until a packet is received (sem_rx_data_available), + * and then calls xemacif_input which processes 1 packet at a time. + */ +void +xemacif_input_thread(struct netif *netif) +{ + struct xemac_s *emac = (struct xemac_s *)netif->state; + while (1) { + /* sleep until there are packets to process + * This semaphore is set by the packet receive interrupt + * routine. + */ + sys_sem_wait(&emac->sem_rx_data_available); + + /* move all received packets to lwIP */ + xemacif_input(netif); + } +} +#endif + +int +xemacif_input(struct netif *netif) +{ + struct xemac_s *emac = (struct xemac_s *)netif->state; + + int n_packets = 0; + + switch (emac->type) { + case xemac_type_xps_emaclite: +#ifdef XLWIP_CONFIG_INCLUDE_EMACLITE + n_packets = xemacliteif_input(netif); + break; +#else + // print("incorrect configuration: xps_ethernetlite drivers not present?"); + while(1); + return 0; +#endif + case xemac_type_axi_ethernet: +#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET + n_packets = xaxiemacif_input(netif); + break; +#else + // print("incorrect configuration: axi_ethernet drivers not present?"); + while(1); + return 0; +#endif +#if defined (__arm__) || defined (__aarch64__) + case xemac_type_emacps: +#ifdef XLWIP_CONFIG_INCLUDE_GEM + n_packets = xemacpsif_input(netif); + break; +#else + xil_printf("incorrect configuration: ps7_ethernet drivers not present?\r\n"); + while(1); + return 0; +#endif +#endif + default: + // print("incorrect configuration: unknown temac type"); + while(1); + return 0; + } + + return n_packets; +} + +#if defined(XLWIP_CONFIG_INCLUDE_GEM) +u32_t phy_link_detect(XEmacPs *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_LINK_STATUS) + return 1; + return 0; +} +#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET) +static u32_t phy_link_detect(XAxiEthernet *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_LINK_STATUS) + return 1; + return 0; +} +#elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE) +static u32_t phy_link_detect(XEmacLite *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_LINK_STATUS) + return 1; + return 0; +} +#endif + +#if defined(XLWIP_CONFIG_INCLUDE_GEM) +u32_t phy_autoneg_status(XEmacPs *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) + return 1; + return 0; +} +#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET) +static u32_t phy_autoneg_status(XAxiEthernet *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) + return 1; + return 0; +} +#elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE) +static u32_t phy_autoneg_status(XEmacLite *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) + return 1; + return 0; +} +#endif + +void eth_link_detect(struct netif *netif) +{ + u32_t link_speed, phy_link_status; + struct xemac_s *xemac = (struct xemac_s *)(netif->state); + +#if defined(XLWIP_CONFIG_INCLUDE_GEM) + xemacpsif_s *xemacs = (xemacpsif_s *)(xemac->state); + XEmacPs *xemacp = &xemacs->emacps; +#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET) + xaxiemacif_s *xemacs = (xaxiemacif_s *)(xemac->state); + XAxiEthernet *xemacp = &xemacs->axi_ethernet; +#elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE) + xemacliteif_s *xemacs = (xemacliteif_s *)(xemac->state); + XEmacLite *xemacp = xemacs->instance; +#endif + + if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) || + (eth_link_status == ETH_LINK_UNDEFINED)) + return; + + phy_link_status = phy_link_detect(xemacp, phyaddrforemac); + + if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status)) + eth_link_status = ETH_LINK_DOWN; + + switch (eth_link_status) { + case ETH_LINK_UNDEFINED: + case ETH_LINK_UP: + return; + case ETH_LINK_DOWN: + netif_set_link_down(netif); + eth_link_status = ETH_LINK_NEGOTIATING; + xil_printf("Ethernet Link down\r\n"); + break; + case ETH_LINK_NEGOTIATING: + if (phy_link_status && + phy_autoneg_status(xemacp, phyaddrforemac)) { + + /* Initiate Phy setup to get link speed */ +#if defined(XLWIP_CONFIG_INCLUDE_GEM) + link_speed = phy_setup_emacps(xemacp, + phyaddrforemac); + XEmacPs_SetOperatingSpeed(xemacp, link_speed); +#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET) + link_speed = phy_setup_axiemac(xemacp); + XAxiEthernet_SetOperatingSpeed(xemacp, + link_speed); +#endif + netif_set_link_up(netif); + eth_link_status = ETH_LINK_UP; + xil_printf("Ethernet Link up\r\n"); + } + break; + } +} + +#ifdef OS_IS_FREERTOS +void link_detect_thread(void *p) +{ + struct netif *netif = (struct netif *) p; + + while (1) { + /* Call eth_link_detect() every second to detect Ethernet link + * change. + */ + eth_link_detect(netif); + vTaskDelay(LINK_DETECT_THREAD_INTERVAL / portTICK_RATE_MS); + } +} +#endif diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h new file mode 100644 index 0000000000..4c240a9b7c --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2018 - 2019 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __XEMAC_IEEE_REGS_H_ +#define __XEMAC_IEEE_REGS_H_ + +/* Advertisement control register. */ +#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ +#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */ +#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ +#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */ +#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ +#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */ +#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ +#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */ +#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ + + +#define ADVERTISE_100_AND_10 (ADVERTISE_10FULL | ADVERTISE_100FULL | \ + ADVERTISE_10HALF | ADVERTISE_100HALF) +#define ADVERTISE_100 (ADVERTISE_100FULL | ADVERTISE_100HALF) +#define ADVERTISE_10 (ADVERTISE_10FULL | ADVERTISE_10HALF) + +#define ADVERTISE_1000 0x0300 + + +#define IEEE_CONTROL_REG_OFFSET 0 +#define IEEE_STATUS_REG_OFFSET 1 +#define IEEE_AUTONEGO_ADVERTISE_REG 4 +#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5 +#define IEEE_PARTNER_ABILITIES_2_REG_OFFSET 8 +#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10 +#define IEEE_1000_ADVERTISE_REG_OFFSET 9 +#define IEEE_MMD_ACCESS_CONTROL_REG 13 +#define IEEE_MMD_ACCESS_ADDRESS_DATA_REG 14 +#define IEEE_COPPER_SPECIFIC_CONTROL_REG 16 +#define IEEE_SPECIFIC_STATUS_REG 17 +#define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19 +#define IEEE_EXT_PHY_SPECIFIC_CONTROL_REG 20 +#define IEEE_CONTROL_REG_MAC 21 +#define IEEE_PAGE_ADDRESS_REGISTER 22 + +#define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040 +#define IEEE_CTRL_LINKSPEED_MASK 0x0040 +#define IEEE_CTRL_LINKSPEED_1000M 0x0040 +#define IEEE_CTRL_LINKSPEED_100M 0x2000 +#define IEEE_CTRL_LINKSPEED_10M 0x0000 +#define IEEE_CTRL_FULL_DUPLEX 0x100 +#define IEEE_CTRL_RESET_MASK 0x8000 +#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000 +#define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008 +#define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020 +#define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200 +#define IEEE_STAT_LINK_STATUS 0x0004 +#define IEEE_STAT_1GBPS_EXTENSIONS 0x0100 +#define IEEE_AN1_ABILITY_MASK 0x1FE0 +#define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00 +#define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380 +#define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060 +#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK 0x0030 + +#define IEEE_SPEED_MASK 0xC000 +#define IEEE_SPEED_1000 0x8000 +#define IEEE_SPEED_100 0x4000 + +#define IEEE_ASYMMETRIC_PAUSE_MASK 0x0800 +#define IEEE_PAUSE_MASK 0x0400 +#define IEEE_AUTONEG_ERROR_MASK 0x8000 + +#define IEEE_MMD_ACCESS_CTRL_DEVAD_MASK 0x1F +#define IEEE_MMD_ACCESS_CTRL_PIDEVAD_MASK 0x801F +#define IEEE_MMD_ACCESS_CTRL_NOPIDEVAD_MASK 0x401F + +#endif /* __XEMAC_IEEE_REGS_H_ */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c new file mode 100644 index 0000000000..d2aeaba3da --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c @@ -0,0 +1,759 @@ +/* + * Copyright (C) 2010 - 2019 Xilinx, Inc. + * Copyright (C) 2021 WangHuachen. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include +#include + +#include +#include "lwipopts.h" +#include "xlwipconfig.h" +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/stats.h" +#include "lwip/igmp.h" + +#include "netif/etharp.h" +#include "netif/xemacpsif.h" +#include "netif/xadapter.h" +#include "netif/xpqueue.h" +#include "xparameters.h" +// #include "xscugic.h" +#include "xemacps.h" + +#if LWIP_IPV6 +#include "lwip/ethip6.h" +#endif + +#ifdef SYS_ARCH_DECL_PROTECT +#undef SYS_ARCH_DECL_PROTECT +#endif +#define SYS_ARCH_DECL_PROTECT(lev) rt_base_t lev; + +#ifdef SYS_ARCH_PROTECT +#undef SYS_ARCH_PROTECT +#endif +#define SYS_ARCH_PROTECT(lev) lev = rt_hw_interrupt_disable(); + +#ifdef SYS_ARCH_UNPROTECT +#undef SYS_ARCH_UNPROTECT +#endif +#define SYS_ARCH_UNPROTECT(lev) rt_hw_interrupt_enable(lev); + +/* Define those to better describe your network interface. */ +#define IFNAME0 't' +#define IFNAME1 'e' + +#if LWIP_IGMP +static err_t xemacpsif_mac_filter_update (struct netif *netif, + ip_addr_t *group, u8_t action); + +static u8_t xemacps_mcast_entry_mask = 0; +#endif + +#if LWIP_IPV6 && LWIP_IPV6_MLD +static err_t xemacpsif_mld6_mac_filter_update (struct netif *netif, + ip_addr_t *group, u8_t action); + +static u8_t xemacps_mld6_mcast_entry_mask; +#endif + +XEmacPs_Config *mac_config; +struct netif *NetIf; + +#if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5) +int32_t lExpireCounter = 0; +#define RESETRXTIMEOUT 10 +#endif + +/* + * this function is always called with interrupts off + * this function also assumes that there are available BD's + */ +err_t _unbuffered_low_level_output(xemacpsif_s *xemacpsif, + struct pbuf *p) +{ + XStatus status = 0; + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + status = emacps_sgsend(xemacpsif, p); + if (status != XST_SUCCESS) { +#if LINK_STATS + lwip_stats.link.drop++; +#endif + } + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + +#if LINK_STATS + lwip_stats.link.xmit++; +#endif /* LINK_STATS */ + + return ERR_OK; + +} + +/* + * low_level_output(): + * + * Should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + */ + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ + SYS_ARCH_DECL_PROTECT(lev); + err_t err; + s32_t freecnt; + XEmacPs_BdRing *txring; + + struct xemac_s *xemac = (struct xemac_s *)(netif->state); + xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); + + SYS_ARCH_PROTECT(lev); + + /* check if space is available to send */ + freecnt = is_tx_space_available(xemacpsif); + if (freecnt <= 5) { + txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps)); + process_sent_bds(xemacpsif, txring); + } + + if (is_tx_space_available(xemacpsif)) { + _unbuffered_low_level_output(xemacpsif, p); + err = ERR_OK; + } else { +#if LINK_STATS + lwip_stats.link.drop++; +#endif + rt_kprintf("pack dropped, no space\r\n"); + err = ERR_MEM; + } + + SYS_ARCH_UNPROTECT(lev); + return err; +} + +/* + * low_level_input(): + * + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + */ +static struct pbuf * low_level_input(struct netif *netif) +{ + struct xemac_s *xemac = (struct xemac_s *)(netif->state); + xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); + struct pbuf *p; + + /* see if there is data to process */ + if (pq_qlength(xemacpsif->recv_q) == 0) + return NULL; + + /* return one packet from receive q */ + p = (struct pbuf *)pq_dequeue(xemacpsif->recv_q); + return p; +} + +/* + * xemacpsif_output(): + * + * This function is called by the TCP/IP stack when an IP packet + * should be sent. It calls the function called low_level_output() to + * do the actual transmission of the packet. + * + */ + +static err_t xemacpsif_output(struct netif *netif, struct pbuf *p, + const ip_addr_t *ipaddr) +{ + /* resolve hardware address, then send (or queue) packet */ + return etharp_output(netif, p, ipaddr); +} + +/* + * xemacpsif_input(): + * + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. + * + * Returns the number of packets read (max 1 packet on success, + * 0 if there are no packets) + * + */ + +s32_t xemacpsif_input(struct netif *netif) +{ + struct eth_hdr *ethhdr; + struct pbuf *p; + SYS_ARCH_DECL_PROTECT(lev); + +#ifdef OS_IS_FREERTOS + while (1) +#endif + { + /* move received packet into a new pbuf */ + SYS_ARCH_PROTECT(lev); + p = low_level_input(netif); + SYS_ARCH_UNPROTECT(lev); + + /* no packet could be read, silently ignore this */ + if (p == NULL) { + return 0; + } + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = p->payload; + + #if LINK_STATS + lwip_stats.link.recv++; + #endif /* LINK_STATS */ + + switch (htons(ethhdr->type)) { + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_ARP: + #if LWIP_IPV6 + /*IPv6 Packet?*/ + case ETHTYPE_IPV6: + #endif + #if PPPOE_SUPPORT + /* PPPoE packet? */ + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: + #endif /* PPPOE_SUPPORT */ + /* full packet send to tcpip_thread to process */ + if (netif->input(p, netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_input: IP input error\r\n")); + pbuf_free(p); + p = NULL; + } + break; + + default: + pbuf_free(p); + p = NULL; + break; + } + } + + return 1; +} + + +#if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5) +void vTimerCallback( TimerHandle_t pxTimer ) +{ + /* Do something if the pxTimer parameter is NULL */ + configASSERT(pxTimer); + + lExpireCounter++; + /* If the timer has expired 100 times then reset RX */ + if(lExpireCounter >= RESETRXTIMEOUT) { + lExpireCounter = 0; + xemacpsif_resetrx_on_no_rxdata(NetIf); + } +} + #endif + +static err_t low_level_init(struct netif *netif) +{ + UINTPTR mac_address = (UINTPTR)(netif->state); + struct xemac_s *xemac; + xemacpsif_s *xemacpsif; + u32 dmacrreg; + + s32_t status = XST_SUCCESS; + + NetIf = netif; + + xemacpsif = mem_malloc(sizeof *xemacpsif); + if (xemacpsif == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n")); + return ERR_MEM; + } + + xemac = mem_malloc(sizeof *xemac); + if (xemac == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n")); + return ERR_MEM; + } + + xemac->state = (void *)xemacpsif; + xemac->topology_index = xtopology_find_index(mac_address); + xemac->type = xemac_type_emacps; + + xemacpsif->send_q = NULL; + xemacpsif->recv_q = pq_create_queue(); + if (!xemacpsif->recv_q) + return ERR_MEM; + + /* maximum transfer unit */ +#ifdef ZYNQMP_USE_JUMBO + netif->mtu = XEMACPS_MTU_JUMBO - XEMACPS_HDR_SIZE; +#else + netif->mtu = XEMACPS_MTU - XEMACPS_HDR_SIZE; +#endif + +#if LWIP_IGMP + netif->igmp_mac_filter = xemacpsif_mac_filter_update; +#endif + +#if LWIP_IPV6 && LWIP_IPV6_MLD + netif->mld_mac_filter = xemacpsif_mld6_mac_filter_update; +#endif + + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | + NETIF_FLAG_LINK_UP; + +#if LWIP_IPV6 && LWIP_IPV6_MLD + netif->flags |= NETIF_FLAG_MLD6; +#endif + +#if LWIP_IGMP + netif->flags |= NETIF_FLAG_IGMP; +#endif + +#if 0 + sys_sem_new(&xemac->sem_rx_data_available, 0); +#endif + /* obtain config of this emac */ + mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)(UINTPTR)netif->state); + +#if EL1_NONSECURE + /* Request device to indicate that this library is using it */ + if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) { + Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_0, 1, 0, 100, 1, 0, 0); + } + if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) { + Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_1, 1, 0, 100, 1, 0, 0); + } +#endif + + status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config, + mac_config->BaseAddress); + if (status != XST_SUCCESS) { + xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__); + } + + /* initialize the mac */ + init_emacps(xemacpsif, netif); + + dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + dmacrreg = dmacrreg | (0x00000010); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_DMACR_OFFSET, dmacrreg); + +#if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5) + /* Freertos tick is 10ms by default; set period to the same */ + xemac->xTimer = xTimerCreate("Timer", 10, pdTRUE, ( void * ) 1, vTimerCallback); + if (xemac->xTimer == NULL) { + xil_printf("In %s:Timer creation failed....\r\n", __func__); + } else { + if(xTimerStart(xemac->xTimer, 0) != pdPASS) { + xil_printf("In %s:Timer start failed....\r\n", __func__); + } + } +#endif + setup_isr(xemac); + init_dma(xemac); + start_emacps(xemacpsif); + + /* replace the state in netif (currently the emac baseaddress) + * with the mac instance pointer. + */ + netif->state = (void *)xemac; + + return ERR_OK; +} + +void HandleEmacPsError(struct xemac_s *xemac) +{ + xemacpsif_s *xemacpsif; + s32_t status = XST_SUCCESS; + u32 dmacrreg; + + SYS_ARCH_DECL_PROTECT(lev); + SYS_ARCH_PROTECT(lev); + + xemacpsif = (xemacpsif_s *)(xemac->state); + free_txrx_pbufs(xemacpsif); + status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config, + mac_config->BaseAddress); + if (status != XST_SUCCESS) { + xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__); + } + /* initialize the mac */ + init_emacps_on_error(xemacpsif, NetIf); + dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + dmacrreg = dmacrreg | (0x01000000); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_DMACR_OFFSET, dmacrreg); + setup_isr(xemac); + init_dma(xemac); + start_emacps(xemacpsif); + + SYS_ARCH_UNPROTECT(lev); +} + +void HandleTxErrors(struct xemac_s *xemac) +{ + xemacpsif_s *xemacpsif; + u32 netctrlreg; + + SYS_ARCH_DECL_PROTECT(lev); + SYS_ARCH_PROTECT(lev); + xemacpsif = (xemacpsif_s *)(xemac->state); + netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, netctrlreg); + free_onlytx_pbufs(xemacpsif); + + clean_dma_txdescs(xemac); + netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, netctrlreg); + SYS_ARCH_UNPROTECT(lev); +} + +#if LWIP_IPV6 && LWIP_IPV6_MLD +static u8_t xemacpsif_ip6_addr_ismulticast(ip6_addr_t* ip_addr) +{ + if(ip6_addr_ismulticast_linklocal(ip_addr)|| + ip6_addr_ismulticast_iflocal(ip_addr) || + ip6_addr_ismulticast_adminlocal(ip_addr)|| + ip6_addr_ismulticast_sitelocal(ip_addr) || + ip6_addr_ismulticast_orglocal(ip_addr) || + ip6_addr_ismulticast_global(ip_addr)) { + /*Return TRUE if IPv6 is Multicast type*/ + return TRUE; + } else { + return FALSE; + } +} + +static void xemacpsif_mld6_mac_hash_update (struct netif *netif, u8_t *ip_addr, + u8_t action) +{ + u8_t multicast_mac_addr[6]; + struct xemac_s *xemac = (struct xemac_s *) (netif->state); + xemacpsif_s *xemacpsif = (xemacpsif_s *) (xemac->state); + XEmacPs_BdRing *txring; + txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps)); + + multicast_mac_addr[0] = LL_IP6_MULTICAST_ADDR_0; + multicast_mac_addr[1] = LL_IP6_MULTICAST_ADDR_1; + multicast_mac_addr[2] = ip_addr[12]; + multicast_mac_addr[3] = ip_addr[13]; + multicast_mac_addr[4] = ip_addr[14]; + multicast_mac_addr[5] = ip_addr[15]; + + /* Wait till all sent packets are acknowledged from HW */ + while(txring->HwCnt); + + SYS_ARCH_DECL_PROTECT(lev); + + SYS_ARCH_PROTECT(lev); + + /* Stop Ethernet */ + XEmacPs_Stop(&xemacpsif->emacps); + + if (action == NETIF_ADD_MAC_FILTER) { + /* Set Mulitcast mac address in hash table */ + XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr); + + } else if (action == NETIF_DEL_MAC_FILTER) { + /* Remove Mulitcast mac address in hash table */ + XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr); + } + + /* Reset DMA */ + reset_dma(xemac); + + /* Start Ethernet */ + XEmacPs_Start(&xemacpsif->emacps); + + SYS_ARCH_UNPROTECT(lev); +} + +static err_t xemacpsif_mld6_mac_filter_update (struct netif *netif, ip_addr_t *group, + u8_t action) +{ + u8_t temp_mask; + unsigned int i; + u8_t * ip_addr = (u8_t *) group; + + if(!(xemacpsif_ip6_addr_ismulticast((ip6_addr_t*) ip_addr))) { + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: The requested MAC address is not a multicast address.\r\n", __func__)); LWIP_DEBUGF(NETIF_DEBUG, + ("Multicast address add operation failure !!\r\n")); + return ERR_ARG; + } + if (action == NETIF_ADD_MAC_FILTER) { + for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) { + temp_mask = (0x01) << i; + if ((xemacps_mld6_mcast_entry_mask & temp_mask) == temp_mask) { + continue; + } + xemacps_mld6_mcast_entry_mask |= temp_mask; + + /* Update mac address in hash table */ + xemacpsif_mld6_mac_hash_update(netif, ip_addr, action); + + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: Multicast MAC address successfully added.\r\n", __func__)); + + return ERR_OK; + } + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: No multicast address registers left.\r\n", __func__)); + LWIP_DEBUGF(NETIF_DEBUG, + ("Multicast MAC address add operation failure !!\r\n")); + return ERR_MEM; + } else if (action == NETIF_DEL_MAC_FILTER) { + for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) { + temp_mask = (0x01) << i; + if ((xemacps_mld6_mcast_entry_mask & temp_mask) != temp_mask) { + continue; + } + xemacps_mld6_mcast_entry_mask &= (~temp_mask); + + /* Update mac address in hash table */ + xemacpsif_mld6_mac_hash_update(netif, ip_addr, action); + + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: Multicast MAC address successfully removed.\r\n", __func__)); + + return ERR_OK; + } + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: No multicast address registers present with\r\n", __func__)); + LWIP_DEBUGF(NETIF_DEBUG, + ("the requested Multicast MAC address.\r\n")); + LWIP_DEBUGF(NETIF_DEBUG, + ("Multicast MAC address removal failure!!.\r\n")); + return ERR_MEM; + } + return ERR_ARG; +} +#endif + +#if LWIP_IGMP +static void xemacpsif_mac_hash_update (struct netif *netif, u8_t *ip_addr, + u8_t action) +{ + u8_t multicast_mac_addr[6]; + struct xemac_s *xemac = (struct xemac_s *) (netif->state); + xemacpsif_s *xemacpsif = (xemacpsif_s *) (xemac->state); + XEmacPs_BdRing *txring; + txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps)); + + multicast_mac_addr[0] = 0x01; + multicast_mac_addr[1] = 0x00; + multicast_mac_addr[2] = 0x5E; + multicast_mac_addr[3] = ip_addr[1] & 0x7F; + multicast_mac_addr[4] = ip_addr[2]; + multicast_mac_addr[5] = ip_addr[3]; + + /* Wait till all sent packets are acknowledged from HW */ + while(txring->HwCnt); + + SYS_ARCH_DECL_PROTECT(lev); + + SYS_ARCH_PROTECT(lev); + + /* Stop Ethernet */ + XEmacPs_Stop(&xemacpsif->emacps); + + if (action == IGMP_ADD_MAC_FILTER) { + /* Set Mulitcast mac address in hash table */ + XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr); + + } else if (action == IGMP_DEL_MAC_FILTER) { + /* Remove Mulitcast mac address in hash table */ + XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr); + } + + /* Reset DMA */ + reset_dma(xemac); + + /* Start Ethernet */ + XEmacPs_Start(&xemacpsif->emacps); + + SYS_ARCH_UNPROTECT(lev); +} + +static err_t xemacpsif_mac_filter_update (struct netif *netif, ip_addr_t *group, + u8_t action) +{ + u8_t temp_mask; + unsigned int i; + u8_t * ip_addr = (u8_t *) group; + + if ((ip_addr[0] < 224) && (ip_addr[0] > 239)) { + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: The requested MAC address is not a multicast address.\r\n", __func__)); + LWIP_DEBUGF(NETIF_DEBUG, + ("Multicast address add operation failure !!\r\n")); + + return ERR_ARG; + } + + if (action == IGMP_ADD_MAC_FILTER) { + + for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) { + temp_mask = (0x01) << i; + if ((xemacps_mcast_entry_mask & temp_mask) == temp_mask) { + continue; + } + xemacps_mcast_entry_mask |= temp_mask; + + /* Update mac address in hash table */ + xemacpsif_mac_hash_update(netif, ip_addr, action); + + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: Multicast MAC address successfully added.\r\n", __func__)); + + return ERR_OK; + } + if (i == XEMACPS_MAX_MAC_ADDR) { + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: No multicast address registers left.\r\n", __func__)); + LWIP_DEBUGF(NETIF_DEBUG, + ("Multicast MAC address add operation failure !!\r\n")); + + return ERR_MEM; + } + } else if (action == IGMP_DEL_MAC_FILTER) { + for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) { + temp_mask = (0x01) << i; + if ((xemacps_mcast_entry_mask & temp_mask) != temp_mask) { + continue; + } + xemacps_mcast_entry_mask &= (~temp_mask); + + /* Update mac address in hash table */ + xemacpsif_mac_hash_update(netif, ip_addr, action); + + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: Multicast MAC address successfully removed.\r\n", __func__)); + + return ERR_OK; + } + if (i == XEMACPS_MAX_MAC_ADDR) { + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: No multicast address registers present with\r\n", __func__)); + LWIP_DEBUGF(NETIF_DEBUG, + ("the requested Multicast MAC address.\r\n")); + LWIP_DEBUGF(NETIF_DEBUG, + ("Multicast MAC address removal failure!!.\r\n")); + + return ERR_MEM; + } + } + return ERR_OK; +} +#endif + +/* + * xemacpsif_init(): + * + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + */ + +err_t xemacpsif_init(struct netif *netif) +{ +#if LWIP_SNMP + /* ifType ethernetCsmacd(6) @see RFC1213 */ + netif->link_type = 6; + /* your link speed here */ + netif->link_speed = ; + netif->ts = 0; + netif->ifinoctets = 0; + netif->ifinucastpkts = 0; + netif->ifinnucastpkts = 0; + netif->ifindiscards = 0; + netif->ifoutoctets = 0; + netif->ifoutucastpkts = 0; + netif->ifoutnucastpkts = 0; + netif->ifoutdiscards = 0; +#endif + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + netif->output = xemacpsif_output; + netif->linkoutput = low_level_output; +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif + + low_level_init(netif); + return ERR_OK; +} + +/* + * xemacpsif_resetrx_on_no_rxdata(): + * + * Should be called by the user at regular intervals, typically + * from a timer (100 msecond). This is to provide a SW workaround + * for the HW bug (SI #692601). Please refer to the function header + * for the function resetrx_on_no_rxdata in xemacpsif_dma.c to + * know more about the SI. + * + */ + +void xemacpsif_resetrx_on_no_rxdata(struct netif *netif) +{ + struct xemac_s *xemac = (struct xemac_s *)(netif->state); + xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); + + resetrx_on_no_rxdata(xemacpsif); +} diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c new file mode 100644 index 0000000000..e52f6da6bb --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c @@ -0,0 +1,873 @@ +/* + * Copyright (C) 2010 - 2019 Xilinx, Inc. + * Copyright (C) 2021 WangHuachen. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwipopts.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/inet_chksum.h" + +#include "netif/xadapter.h" +#include "netif/xemacpsif.h" +#include "xstatus.h" + +#include "xlwipconfig.h" +#include "xparameters.h" +#include "xparameters_ps.h" +// #include "xil_exception.h" +#include "xil_mmu.h" +#if defined (ARMR5) +#include "xreg_cortexr5.h" +#endif +#ifdef CONFIG_XTRACE +#include "xtrace.h" +#endif +#ifdef OS_IS_FREERTOS +#include "FreeRTOS.h" +#include "semphr.h" +#include "timers.h" +#endif + +#include + +#define INTC_BASE_ADDR XPAR_SCUGIC_0_CPU_BASEADDR +#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_0_DIST_BASEADDR + +/* Byte alignment of BDs */ +#define BD_ALIGNMENT (XEMACPS_DMABD_MINIMUM_ALIGNMENT*2) + +/* A max of 4 different ethernet interfaces are supported */ +static UINTPTR tx_pbufs_storage[4*XLWIP_CONFIG_N_TX_DESC]; +static UINTPTR rx_pbufs_storage[4*XLWIP_CONFIG_N_RX_DESC]; + +static s32_t emac_intr_num; + +/****************************************************************************** + * Each BD is of 8 bytes of size and the BDs (BD chain) need to be put + * at uncached memory location. If they are not put at uncached + * locations, the user needs to flush or invalidate for each BD/packet. + * However, the flush or invalidate can happen over a cache line which can + * span multiple BDs. This means a flush or invalidate of one BD can actually + * flush/invalidate multiple BDs adjacent to the targeted BD.Assuming that + * the user and hardware both update the BD fields, this operation from user + * can potentially overwrite the updates done by hardware or user. + * To avoid this, it is always safe to put the BD chains for Rx and tx side + * at uncached memory location. + * + * The Xilinx standalone BSP for Cortex A9 implements only primary page tables. + * Each table entry corresponds to 1 MB of address map. This means, if a memory + * region has to be made uncached, the minimum granularity will be of 1 MB. + * + * The implementation below allocates a 1 MB of u8 array aligned to 1 MB. + * This ensures that this array is put at 1 MB aligned memory (e.g. 0x1200000) + * and accupies memory of 1 MB. The init_dma function then changes 1 MB of this + * region to make it uncached (strongly ordered). + * This increases the bss section of the program significantly and can be a + * wastage of memory. The reason beings, BDs will hardly occupy few KBs of + * memory and the rest of 1 MB of memory will be unused. + * + * If a program uses other peripherals that have DMAs/bus masters and need + * uncached memory, they may also end of following the same approach. This + * definitely aggravates the memory wastage issue. To avoid all this, the user + * can create a new 1 MB section in the linker script and reserve it for such + * use cases that need uncached memory location. They can then have their own + * memory allocation logic in their application that allocates uncached memory + * from this 1 MB location. For such a case, changes need to be done in this + * file and appropriate uncached memory allocated through other means can be + * used. + * + * The present implementation here allocates 1 MB of uncached memory. It + * reserves of 64 KB of memory for each BD chain. 64 KB of memory means 8192 of + * BDs for each BD chain which is more than enough for any application. + * Assuming that both emac0 and emac1 are present, 256 KB of memory is allocated + * for BDs. The rest 768 KB of memory is just unused. + *********************************************************************************/ + +#if defined __aarch64__ +u8_t bd_space[0x200000] __attribute__ ((aligned (0x200000))); +#else +u8_t bd_space[0x100000] __attribute__ ((aligned (0x100000))); +#endif +static volatile u32_t bd_space_index = 0; +static volatile u32_t bd_space_attr_set = 0; + +#ifdef OS_IS_FREERTOS +long xInsideISR = 0; +#endif + +#define XEMACPS_BD_TO_INDEX(ringptr, bdptr) \ + (((UINTPTR)bdptr - (UINTPTR)(ringptr)->BaseBdAddr) / (ringptr)->Separation) + + +s32_t is_tx_space_available(xemacpsif_s *emac) +{ + XEmacPs_BdRing *txring; + s32_t freecnt = 0; + + txring = &(XEmacPs_GetTxRing(&emac->emacps)); + + /* tx space is available as long as there are valid BD's */ + freecnt = XEmacPs_BdRingGetFreeCnt(txring); + return freecnt; +} + + +static inline +u32_t get_base_index_txpbufsstorage (xemacpsif_s *xemacpsif) +{ + u32_t index; +#ifdef XPAR_XEMACPS_0_BASEADDR + if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) { + index = 0; + } +#endif +#ifdef XPAR_XEMACPS_1_BASEADDR + if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_1_BASEADDR) { + index = XLWIP_CONFIG_N_TX_DESC; + } +#endif +#ifdef XPAR_XEMACPS_2_BASEADDR + if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_2_BASEADDR) { + index = 2 * XLWIP_CONFIG_N_TX_DESC; + } +#endif +#ifdef XPAR_XEMACPS_3_BASEADDR + if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_3_BASEADDR) { + index = 3 * XLWIP_CONFIG_N_TX_DESC; + } +#endif + return index; +} + +static inline +u32_t get_base_index_rxpbufsstorage (xemacpsif_s *xemacpsif) +{ + u32_t index; +#ifdef XPAR_XEMACPS_0_BASEADDR + if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) { + index = 0; + } +#endif +#ifdef XPAR_XEMACPS_1_BASEADDR + if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_1_BASEADDR) { + index = XLWIP_CONFIG_N_RX_DESC; + } +#endif +#ifdef XPAR_XEMACPS_2_BASEADDR + if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_2_BASEADDR) { + index = 2 * XLWIP_CONFIG_N_RX_DESC; + } +#endif +#ifdef XPAR_XEMACPS_3_BASEADDR + if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_3_BASEADDR) { + index = 3 * XLWIP_CONFIG_N_RX_DESC; + } +#endif + return index; +} + +void process_sent_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *txring) +{ + XEmacPs_Bd *txbdset; + XEmacPs_Bd *curbdpntr; + s32_t n_bds; + XStatus status; + s32_t n_pbufs_freed = 0; + u32_t bdindex; + struct pbuf *p; + u32 *temp; + u32_t index; + + index = get_base_index_txpbufsstorage (xemacpsif); + + while (1) { + /* obtain processed BD's */ + n_bds = XEmacPs_BdRingFromHwTx(txring, + XLWIP_CONFIG_N_TX_DESC, &txbdset); + if (n_bds == 0) { + return; + } + /* free the processed BD's */ + n_pbufs_freed = n_bds; + curbdpntr = txbdset; + while (n_pbufs_freed > 0) { + bdindex = XEMACPS_BD_TO_INDEX(txring, curbdpntr); + temp = (u32 *)curbdpntr; + *temp = 0; + temp++; + if (bdindex == (XLWIP_CONFIG_N_TX_DESC - 1)) { + *temp = 0xC0000000; + } else { + *temp = 0x80000000; + } + dsb(); + p = (struct pbuf *)tx_pbufs_storage[index + bdindex]; + if (p != NULL) { + pbuf_free(p); + } + tx_pbufs_storage[index + bdindex] = 0; + curbdpntr = XEmacPs_BdRingNext(txring, curbdpntr); + n_pbufs_freed--; + dsb(); + } + + status = XEmacPs_BdRingFree(txring, n_bds, txbdset); + if (status != XST_SUCCESS) { + LWIP_DEBUGF(NETIF_DEBUG, ("Failure while freeing in Tx Done ISR\r\n")); + } + } + return; +} + +void emacps_send_handler(void *arg) +{ + struct xemac_s *xemac; + xemacpsif_s *xemacpsif; + XEmacPs_BdRing *txringptr; + u32_t regval; +#ifdef OS_IS_FREERTOS + xInsideISR++; +#endif + xemac = (struct xemac_s *)(arg); + xemacpsif = (xemacpsif_s *)(xemac->state); + txringptr = &(XEmacPs_GetTxRing(&xemacpsif->emacps)); + regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_TXSR_OFFSET); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,XEMACPS_TXSR_OFFSET, regval); + + /* If Transmit done interrupt is asserted, process completed BD's */ + /* Since RT-Thread does not support freeing memory in interrupts, comment it out */ + // process_sent_bds(xemacpsif, txringptr); +#ifdef OS_IS_FREERTOS + xInsideISR--; +#endif +} + +XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p) +{ + struct pbuf *q; + s32_t n_pbufs; + XEmacPs_Bd *txbdset, *txbd, *last_txbd = NULL; + XEmacPs_Bd *temp_txbd; + XStatus status; + XEmacPs_BdRing *txring; + u32_t bdindex; + u32_t lev; + u32_t index; + u32_t max_fr_size; + + lev = mfcpsr(); + mtcpsr(lev | 0x000000C0); + + txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps)); + + index = get_base_index_txpbufsstorage (xemacpsif); + + /* first count the number of pbufs */ + for (q = p, n_pbufs = 0; q != NULL; q = q->next) + n_pbufs++; + + /* obtain as many BD's */ + status = XEmacPs_BdRingAlloc(txring, n_pbufs, &txbdset); + if (status != XST_SUCCESS) { + mtcpsr(lev); + LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error allocating TxBD\r\n")); + return XST_FAILURE; + } + + for(q = p, txbd = txbdset; q != NULL; q = q->next) { + bdindex = XEMACPS_BD_TO_INDEX(txring, txbd); + if (tx_pbufs_storage[index + bdindex] != 0) { + mtcpsr(lev); + LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n")); + return XST_FAILURE; + } + + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + if (xemacpsif->emacps.Config.IsCacheCoherent == 0) { + Xil_DCacheFlushRange((UINTPTR)q->payload, (UINTPTR)q->len); + } + + XEmacPs_BdSetAddressTx(txbd, (UINTPTR)q->payload); + +#ifdef ZYNQMP_USE_JUMBO + max_fr_size = MAX_FRAME_SIZE_JUMBO - 18; +#else + max_fr_size = XEMACPS_MAX_FRAME_SIZE - 18; +#endif + if (q->len > max_fr_size) + XEmacPs_BdSetLength(txbd, max_fr_size & 0x3FFF); + else + XEmacPs_BdSetLength(txbd, q->len & 0x3FFF); + + tx_pbufs_storage[index + bdindex] = (UINTPTR)q; + + pbuf_ref(q); + last_txbd = txbd; + XEmacPs_BdClearLast(txbd); + txbd = XEmacPs_BdRingNext(txring, txbd); + } + XEmacPs_BdSetLast(last_txbd); + /* For fragmented packets, remember the 1st BD allocated for the 1st + packet fragment. The used bit for this BD should be cleared at the end + after clearing out used bits for other fragments. For packets without + just remember the allocated BD. */ + temp_txbd = txbdset; + txbd = txbdset; + txbd = XEmacPs_BdRingNext(txring, txbd); + q = p->next; + for(; q != NULL; q = q->next) { + XEmacPs_BdClearTxUsed(txbd); + dsb(); + txbd = XEmacPs_BdRingNext(txring, txbd); + } + XEmacPs_BdClearTxUsed(temp_txbd); + dsb(); + + status = XEmacPs_BdRingToHw(txring, n_pbufs, txbdset); + if (status != XST_SUCCESS) { + mtcpsr(lev); + LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error submitting TxBD\r\n")); + return XST_FAILURE; + } + /* Start transmit */ + XEmacPs_WriteReg((xemacpsif->emacps).Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, + (XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK)); + + mtcpsr(lev); + return status; +} + +void setup_rx_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *rxring) +{ + XEmacPs_Bd *rxbd; + XStatus status; + struct pbuf *p; + u32_t freebds; + u32_t bdindex; + u32 *temp; + u32_t index; + + index = get_base_index_rxpbufsstorage (xemacpsif); + + freebds = XEmacPs_BdRingGetFreeCnt (rxring); + while (freebds > 0) { + freebds--; +#ifdef ZYNQMP_USE_JUMBO + p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL); +#else + p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL); +#endif + if (!p) { +#if LINK_STATS + lwip_stats.link.memerr++; + lwip_stats.link.drop++; +#endif + rt_kprintf("unable to alloc pbuf in recv_handler\r\n"); + return; + } + status = XEmacPs_BdRingAlloc(rxring, 1, &rxbd); + if (status != XST_SUCCESS) { + LWIP_DEBUGF(NETIF_DEBUG, ("setup_rx_bds: Error allocating RxBD\r\n")); + pbuf_free(p); + return; + } + status = XEmacPs_BdRingToHw(rxring, 1, rxbd); + if (status != XST_SUCCESS) { + LWIP_DEBUGF(NETIF_DEBUG, ("Error committing RxBD to hardware: ")); + if (status == XST_DMA_SG_LIST_ERROR) { + LWIP_DEBUGF(NETIF_DEBUG, ("XST_DMA_SG_LIST_ERROR: this function was called out of sequence with XEmacPs_BdRingAlloc()\r\n")); + } + else { + LWIP_DEBUGF(NETIF_DEBUG, ("set of BDs was rejected because the first BD did not have its start-of-packet bit set, or the last BD did not have its end-of-packet bit set, or any one of the BD set has 0 as length value\r\n")); + } + + pbuf_free(p); + XEmacPs_BdRingUnAlloc(rxring, 1, rxbd); + return; + } +#ifdef ZYNQMP_USE_JUMBO + if (xemacpsif->emacps.Config.IsCacheCoherent == 0) { + Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO); + } +#else + if (xemacpsif->emacps.Config.IsCacheCoherent == 0) { + Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE); + } +#endif + bdindex = XEMACPS_BD_TO_INDEX(rxring, rxbd); + temp = (u32 *)rxbd; + if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) { + *temp = 0x00000002; + } else { + *temp = 0; + } + temp++; + *temp = 0; + dsb(); + + XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload); + rx_pbufs_storage[index + bdindex] = (UINTPTR)p; + } +} + +void emacps_recv_handler(void *arg) +{ + struct pbuf *p; + XEmacPs_Bd *rxbdset, *curbdptr; + struct xemac_s *xemac; + xemacpsif_s *xemacpsif; + XEmacPs_BdRing *rxring; + volatile s32_t bd_processed; + s32_t rx_bytes, k; + u32_t bdindex; + u32_t regval; + u32_t index; + u32_t gigeversion; + + xemac = (struct xemac_s *)(arg); + xemacpsif = (xemacpsif_s *)(xemac->state); + rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps); + +#ifdef OS_IS_FREERTOS + xInsideISR++; +#endif + + gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF; + index = get_base_index_rxpbufsstorage (xemacpsif); + /* + * If Reception done interrupt is asserted, call RX call back function + * to handle the processed BDs and then raise the according flag. + */ + regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET, regval); + if (gigeversion <= 2) { + resetrx_on_no_rxdata(xemacpsif); + } + + while(1) { + + bd_processed = XEmacPs_BdRingFromHwRx(rxring, XLWIP_CONFIG_N_RX_DESC, &rxbdset); + if (bd_processed <= 0) { + break; + } + for (k = 0, curbdptr=rxbdset; k < bd_processed; k++) { + + bdindex = XEMACPS_BD_TO_INDEX(rxring, curbdptr); + p = (struct pbuf *)rx_pbufs_storage[index + bdindex]; + /* + * Adjust the buffer size to the actual number of bytes received. + */ +#ifdef ZYNQMP_USE_JUMBO + rx_bytes = XEmacPs_GetRxFrameSize(&xemacpsif->emacps, curbdptr); +#else + rx_bytes = XEmacPs_BdGetLength(curbdptr); +#endif + pbuf_realloc(p, rx_bytes); + /* Invalidate RX frame before queuing to handle + * L1 cache prefetch conditions on any architecture. + */ + Xil_DCacheInvalidateRange((UINTPTR)p->payload, rx_bytes); + /* store it in the receive queue, + * where it'll be processed by a different handler + */ + if (pq_enqueue(xemacpsif->recv_q, (void*)p) < 0) { +#if LINK_STATS + lwip_stats.link.memerr++; + lwip_stats.link.drop++; +#endif + pbuf_free(p); + } + curbdptr = XEmacPs_BdRingNext( rxring, curbdptr); + } + /* free up the BD's */ + XEmacPs_BdRingFree(rxring, bd_processed, rxbdset); + setup_rx_bds(xemacpsif, rxring); +#if 0 + sys_sem_signal(&xemac->sem_rx_data_available); +#else + eth_device_ready(xemac->rt_eth_device); +#endif + } + +#ifdef OS_IS_FREERTOS + xInsideISR--; +#endif + return; +} + +void clean_dma_txdescs(struct xemac_s *xemac) +{ + XEmacPs_Bd bdtemplate; + XEmacPs_BdRing *txringptr; + xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); + + txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps); + + XEmacPs_BdClear(&bdtemplate); + XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK); + + /* + * Create the TxBD ring + */ + XEmacPs_BdRingCreate(txringptr, (UINTPTR) xemacpsif->tx_bdspace, + (UINTPTR) xemacpsif->tx_bdspace, BD_ALIGNMENT, + XLWIP_CONFIG_N_TX_DESC); + XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND); +} + +XStatus init_dma(struct xemac_s *xemac) +{ + XEmacPs_Bd bdtemplate; + XEmacPs_BdRing *rxringptr, *txringptr; + XEmacPs_Bd *rxbd; + struct pbuf *p; + XStatus status; + s32_t i; + u32_t bdindex; + volatile UINTPTR tempaddress; + u32_t index; + u32_t gigeversion; + XEmacPs_Bd *bdtxterminate; + XEmacPs_Bd *bdrxterminate; + u32 *temp; + + xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); + struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index]; + + index = get_base_index_rxpbufsstorage (xemacpsif); + gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF; + /* + * The BDs need to be allocated in uncached memory. Hence the 1 MB + * address range allocated for Bd_Space is made uncached + * by setting appropriate attributes in the translation table. + * The Bd_Space is aligned to 1MB and has a size of 1 MB. This ensures + * a reserved uncached area used only for BDs. + */ + if (bd_space_attr_set == 0) { +#if defined (ARMR5) + Xil_SetTlbAttributes((s32_t)bd_space, STRONG_ORDERD_SHARED | PRIV_RW_USER_RW); // addr, attr +#else +#if defined __aarch64__ + Xil_SetTlbAttributes((u64)bd_space, NORM_NONCACHE | INNER_SHAREABLE); +#else + Xil_SetTlbAttributes((s32_t)bd_space, DEVICE_MEMORY); // addr, attr +#endif +#endif + bd_space_attr_set = 1; + } + + rxringptr = &XEmacPs_GetRxRing(&xemacpsif->emacps); + txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps); + LWIP_DEBUGF(NETIF_DEBUG, ("rxringptr: 0x%08x\r\n", rxringptr)); + LWIP_DEBUGF(NETIF_DEBUG, ("txringptr: 0x%08x\r\n", txringptr)); + + /* Allocate 64k for Rx and Tx bds each to take care of extreme cases */ + tempaddress = (UINTPTR)&(bd_space[bd_space_index]); + xemacpsif->rx_bdspace = (void *)tempaddress; + bd_space_index += 0x10000; + tempaddress = (UINTPTR)&(bd_space[bd_space_index]); + xemacpsif->tx_bdspace = (void *)tempaddress; + bd_space_index += 0x10000; + if (gigeversion > 2) { + tempaddress = (UINTPTR)&(bd_space[bd_space_index]); + bdrxterminate = (XEmacPs_Bd *)tempaddress; + bd_space_index += 0x10000; + tempaddress = (UINTPTR)&(bd_space[bd_space_index]); + bdtxterminate = (XEmacPs_Bd *)tempaddress; + bd_space_index += 0x10000; + } + + LWIP_DEBUGF(NETIF_DEBUG, ("rx_bdspace: %p \r\n", xemacpsif->rx_bdspace)); + LWIP_DEBUGF(NETIF_DEBUG, ("tx_bdspace: %p \r\n", xemacpsif->tx_bdspace)); + + if (!xemacpsif->rx_bdspace || !xemacpsif->tx_bdspace) { + xil_printf("%s@%d: Error: Unable to allocate memory for TX/RX buffer descriptors", + __FILE__, __LINE__); + return ERR_IF; + } + + /* + * Setup RxBD space. + * + * Setup a BD template for the Rx channel. This template will be copied to + * every RxBD. We will not have to explicitly set these again. + */ + XEmacPs_BdClear(&bdtemplate); + + /* + * Create the RxBD ring + */ + + status = XEmacPs_BdRingCreate(rxringptr, (UINTPTR) xemacpsif->rx_bdspace, + (UINTPTR) xemacpsif->rx_bdspace, BD_ALIGNMENT, + XLWIP_CONFIG_N_RX_DESC); + + if (status != XST_SUCCESS) { + LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space\r\n")); + return ERR_IF; + } + + status = XEmacPs_BdRingClone(rxringptr, &bdtemplate, XEMACPS_RECV); + if (status != XST_SUCCESS) { + LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space\r\n")); + return ERR_IF; + } + + XEmacPs_BdClear(&bdtemplate); + XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK); + /* + * Create the TxBD ring + */ + status = XEmacPs_BdRingCreate(txringptr, (UINTPTR) xemacpsif->tx_bdspace, + (UINTPTR) xemacpsif->tx_bdspace, BD_ALIGNMENT, + XLWIP_CONFIG_N_TX_DESC); + + if (status != XST_SUCCESS) { + return ERR_IF; + } + + /* We reuse the bd template, as the same one will work for both rx and tx. */ + status = XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND); + if (status != XST_SUCCESS) { + return ERR_IF; + } + + /* + * Allocate RX descriptors, 1 RxBD at a time. + */ + for (i = 0; i < XLWIP_CONFIG_N_RX_DESC; i++) { +#ifdef ZYNQMP_USE_JUMBO + p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL); +#else + p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL); +#endif + if (!p) { +#if LINK_STATS + lwip_stats.link.memerr++; + lwip_stats.link.drop++; +#endif + rt_kprintf("unable to alloc pbuf in init_dma\r\n"); + return ERR_IF; + } + status = XEmacPs_BdRingAlloc(rxringptr, 1, &rxbd); + if (status != XST_SUCCESS) { + LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n")); + pbuf_free(p); + return ERR_IF; + } + /* Enqueue to HW */ + status = XEmacPs_BdRingToHw(rxringptr, 1, rxbd); + if (status != XST_SUCCESS) { + LWIP_DEBUGF(NETIF_DEBUG, ("Error: committing RxBD to HW\r\n")); + pbuf_free(p); + XEmacPs_BdRingUnAlloc(rxringptr, 1, rxbd); + return ERR_IF; + } + + bdindex = XEMACPS_BD_TO_INDEX(rxringptr, rxbd); + temp = (u32 *)rxbd; + *temp = 0; + if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) { + *temp = 0x00000002; + } + temp++; + *temp = 0; + dsb(); +#ifdef ZYNQMP_USE_JUMBO + if (xemacpsif->emacps.Config.IsCacheCoherent == 0) { + Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO); + } +#else + if (xemacpsif->emacps.Config.IsCacheCoherent == 0) { + Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE); + } +#endif + XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload); + + rx_pbufs_storage[index + bdindex] = (UINTPTR)p; + } + XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.RxBdRing.BaseBdAddr, 0, XEMACPS_RECV); + if (gigeversion > 2) { + XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 1, XEMACPS_SEND); + }else { + XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 0, XEMACPS_SEND); + } + if (gigeversion > 2) + { + /* + * This version of GEM supports priority queuing and the current + * driver is using tx priority queue 1 and normal rx queue for + * packet transmit and receive. The below code ensure that the + * other queue pointers are parked to known state for avoiding + * the controller to malfunction by fetching the descriptors + * from these queues. + */ + XEmacPs_BdClear(bdrxterminate); + XEmacPs_BdSetAddressRx(bdrxterminate, (XEMACPS_RXBUF_NEW_MASK | + XEMACPS_RXBUF_WRAP_MASK)); + XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_RXQ1BASE_OFFSET), + (UINTPTR)bdrxterminate); + XEmacPs_BdClear(bdtxterminate); + XEmacPs_BdSetStatus(bdtxterminate, (XEMACPS_TXBUF_USED_MASK | + XEMACPS_TXBUF_WRAP_MASK)); + XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_TXQBASE_OFFSET), + (UINTPTR)bdtxterminate); + } + + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + // XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr, + // (Xil_ExceptionHandler)XEmacPs_IntrHandler, + // (void *)&xemacpsif->emacps); + /* + * Enable the interrupt for emacps. + */ + // XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, (u32) xtopologyp->scugic_emac_intr); + emac_intr_num = (u32) xtopologyp->scugic_emac_intr; + return 0; +} + +/* + * resetrx_on_no_rxdata(): + * + * It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata + * called by the user. + * The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic. + * Under heavy Rx traffic because of the HW bug there are times when the Rx path + * becomes unresponsive. The workaround for it is to check for the Rx path for + * traffic (by reading the stats registers regularly). If the stats register + * does not increment for sometime (proving no Rx traffic), the function resets + * the Rx data path. + * + */ + +void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif) +{ + u32_t regctrl; + u32_t tempcntr; + u32_t gigeversion; + + gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF; + if (gigeversion == 2) { + tempcntr = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET); + if ((!tempcntr) && (!(xemacpsif->last_rx_frms_cntr))) { + regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, regctrl); + regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET); + regctrl |= (XEMACPS_NWCTRL_RXEN_MASK); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl); + } + xemacpsif->last_rx_frms_cntr = tempcntr; + } +} + +void free_txrx_pbufs(xemacpsif_s *xemacpsif) +{ + s32_t index; + s32_t index1; + struct pbuf *p; + + index1 = get_base_index_txpbufsstorage (xemacpsif); + + for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) { + if (tx_pbufs_storage[index] != 0) { + p = (struct pbuf *)tx_pbufs_storage[index]; + pbuf_free(p); + tx_pbufs_storage[index] = 0; + } + } + + for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) { + p = (struct pbuf *)rx_pbufs_storage[index]; + pbuf_free(p); + + } +} + +void free_onlytx_pbufs(xemacpsif_s *xemacpsif) +{ + s32_t index; + s32_t index1; + struct pbuf *p; + + index1 = get_base_index_txpbufsstorage (xemacpsif); + for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) { + if (tx_pbufs_storage[index] != 0) { + p = (struct pbuf *)tx_pbufs_storage[index]; + pbuf_free(p); + tx_pbufs_storage[index] = 0; + } + } +} + +/* reset Tx and Rx DMA pointers after XEmacPs_Stop */ +void reset_dma(struct xemac_s *xemac) +{ + u8 txqueuenum; + u32_t gigeversion; + xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); + XEmacPs_BdRing *txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps); + XEmacPs_BdRing *rxringptr = &XEmacPs_GetRxRing(&xemacpsif->emacps); + + XEmacPs_BdRingPtrReset(txringptr, xemacpsif->tx_bdspace); + XEmacPs_BdRingPtrReset(rxringptr, xemacpsif->rx_bdspace); + + gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF; + if (gigeversion > 2) { + txqueuenum = 1; + } else { + txqueuenum = 0; + } + + XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.RxBdRing.BaseBdAddr, 0, XEMACPS_RECV); + XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, txqueuenum, XEMACPS_SEND); +} + +void emac_disable_intr(void) +{ + // XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, emac_intr_num); + rt_hw_interrupt_mask(emac_intr_num); +} + +void emac_enable_intr(void) +{ + // XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, emac_intr_num); + rt_hw_interrupt_umask(emac_intr_num); +} diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c new file mode 100644 index 0000000000..a1bef1faa1 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2010 - 2019 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "netif/xemacpsif.h" +#include "lwipopts.h" + +#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \ + XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1 +#define PCM_PMA_CORE_PRESENT +#else +#undef PCM_PMA_CORE_PRESENT +#endif + +u32_t link_speed = 100; +extern XEmacPs_Config XEmacPs_ConfigTable[]; +extern u32_t phymapemac0[32]; +extern u32_t phymapemac1[32]; +extern u32_t phyaddrforemac; +extern enum ethernet_link_status eth_link_status; + +#ifdef OS_IS_FREERTOS +extern long xInsideISR; +#endif + +XEmacPs_Config *xemacps_lookup_config(unsigned mac_base) +{ + XEmacPs_Config *cfgptr = NULL; + s32_t i; + + for (i = 0; i < XPAR_XEMACPS_NUM_INSTANCES; i++) { + if (XEmacPs_ConfigTable[i].BaseAddress == mac_base) { + cfgptr = &XEmacPs_ConfigTable[i]; + break; + } + } + + return (cfgptr); +} + +void init_emacps(xemacpsif_s *xemacps, struct netif *netif) +{ + XEmacPs *xemacpsp; + s32_t status = XST_SUCCESS; + u32_t i; + u32_t phyfoundforemac0 = FALSE; + u32_t phyfoundforemac1 = FALSE; + + xemacpsp = &xemacps->emacps; + +#ifdef ZYNQMP_USE_JUMBO + XEmacPs_SetOptions(xemacpsp, XEMACPS_JUMBO_ENABLE_OPTION); +#endif + +#ifdef LWIP_IGMP + XEmacPs_SetOptions(xemacpsp, XEMACPS_MULTICAST_OPTION); +#endif + + /* set mac address */ + status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1); + if (status != XST_SUCCESS) { + xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__); + } + + XEmacPs_SetMdioDivisor(xemacpsp, MDC_DIV_224); + +/* Please refer to file header comments for the file xemacpsif_physpeed.c + * to know more about the PHY programming sequence. + * For PCS PMA core, phy_setup_emacps is called with the predefined PHY address + * exposed through xaparemeters.h + * For RGMII case, assuming multiple PHYs can be present on the MDIO bus, + * detect_phy is called to get the addresses of the PHY present on + * a particular MDIO bus (emac0 or emac1). This address map is populated + * in phymapemac0 or phymapemac1. + * phy_setup_emacps is then called for each PHY present on the MDIO bus. + */ +#ifdef PCM_PMA_CORE_PRESENT +#ifdef XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT + link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_1000BASEX_PHYADDR); +#elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT + link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_SGMII_PHYADDR); +#endif +#else + detect_phy(xemacpsp); + for (i = 31; i > 0; i--) { + if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) { + if (phymapemac0[i] == TRUE) { + link_speed = phy_setup_emacps(xemacpsp, i); + phyfoundforemac0 = TRUE; + phyaddrforemac = i; + } + } else { + if (phymapemac1[i] == TRUE) { + link_speed = phy_setup_emacps(xemacpsp, i); + phyfoundforemac1 = TRUE; + phyaddrforemac = i; + } + } + } + /* If no PHY was detected, use broadcast PHY address of 0 */ + if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) { + if (phyfoundforemac0 == FALSE) + link_speed = phy_setup_emacps(xemacpsp, 0); + } else { + if (phyfoundforemac1 == FALSE) + link_speed = phy_setup_emacps(xemacpsp, 0); + } +#endif + + if (link_speed == XST_FAILURE) { + eth_link_status = ETH_LINK_DOWN; + xil_printf("Phy setup failure %s \n\r",__func__); + return; + } else { + eth_link_status = ETH_LINK_UP; + } + + XEmacPs_SetOperatingSpeed(xemacpsp, link_speed); + /* Setting the operating speed of the MAC needs a delay. */ + { + volatile s32_t wait; + for (wait=0; wait < 20000; wait++); + } +} + +void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif) +{ + XEmacPs *xemacpsp; + s32_t status = XST_SUCCESS; + + xemacpsp = &xemacps->emacps; + + /* set mac address */ + status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1); + if (status != XST_SUCCESS) { + xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__); + } + + XEmacPs_SetOperatingSpeed(xemacpsp, link_speed); + + /* Setting the operating speed of the MAC needs a delay. */ + { + volatile s32_t wait; + for (wait=0; wait < 20000; wait++); + } +} + +void setup_isr (struct xemac_s *xemac) +{ + xemacpsif_s *xemacpsif; + + xemacpsif = (xemacpsif_s *)(xemac->state); + /* + * Setup callbacks + */ + XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND, + (void *) emacps_send_handler, + (void *) xemac); + + XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV, + (void *) emacps_recv_handler, + (void *) xemac); + + XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR, + (void *) emacps_error_handler, + (void *) xemac); +} + +void start_emacps (xemacpsif_s *xemacps) +{ + /* start the temac */ + XEmacPs_Start(&xemacps->emacps); +} + +void restart_emacps_transmitter (xemacpsif_s *xemacps) { + u32_t Reg; + Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg = Reg & (~XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + + Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg = Reg | (XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); +} + +void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord) +{ + struct xemac_s *xemac; + xemacpsif_s *xemacpsif; + XEmacPs_BdRing *rxring; + XEmacPs_BdRing *txring; +#ifdef OS_IS_FREERTOS + xInsideISR++; +#endif + + xemac = (struct xemac_s *)(arg); + xemacpsif = (xemacpsif_s *)(xemac->state); + rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps); + txring = &XEmacPs_GetTxRing(&xemacpsif->emacps); + + if (ErrorWord != 0) { + switch (Direction) { + case XEMACPS_RECV: + if (ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK) { + LWIP_DEBUGF(NETIF_DEBUG, ("Receive DMA error\r\n")); + HandleEmacPsError(xemac); + } + if (ErrorWord & XEMACPS_RXSR_RXOVR_MASK) { + LWIP_DEBUGF(NETIF_DEBUG, ("Receive over run\r\n")); + emacps_recv_handler(arg); + setup_rx_bds(xemacpsif, rxring); + } + if (ErrorWord & XEMACPS_RXSR_BUFFNA_MASK) { + LWIP_DEBUGF(NETIF_DEBUG, ("Receive buffer not available\r\n")); + emacps_recv_handler(arg); + setup_rx_bds(xemacpsif, rxring); + } + break; + case XEMACPS_SEND: + if (ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK) { + LWIP_DEBUGF(NETIF_DEBUG, ("Transmit DMA error\r\n")); + HandleEmacPsError(xemac); + } + if (ErrorWord & XEMACPS_TXSR_URUN_MASK) { + LWIP_DEBUGF(NETIF_DEBUG, ("Transmit under run\r\n")); + HandleTxErrors(xemac); + } + if (ErrorWord & XEMACPS_TXSR_BUFEXH_MASK) { + LWIP_DEBUGF(NETIF_DEBUG, ("Transmit buffer exhausted\r\n")); + HandleTxErrors(xemac); + } + if (ErrorWord & XEMACPS_TXSR_RXOVR_MASK) { + LWIP_DEBUGF(NETIF_DEBUG, ("Transmit retry excessed limits\r\n")); + HandleTxErrors(xemac); + } + if (ErrorWord & XEMACPS_TXSR_FRAMERX_MASK) { + LWIP_DEBUGF(NETIF_DEBUG, ("Transmit collision\r\n")); + // process_sent_bds(xemacpsif, txring); + } + break; + } + } +#ifdef OS_IS_FREERTOS + xInsideISR--; +#endif +} diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.h new file mode 100644 index 0000000000..64f7771494 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 - 2019 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __XEMACPSIF_HW_H_ +#define __XEMACPSIF_HW_H_ + +#include "netif/xemacpsif.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +XEmacPs_Config * lookup_config(unsigned mac_base); + +void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c new file mode 100644 index 0000000000..9113e3fecb --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c @@ -0,0 +1,1152 @@ +/* + * Copyright (C) 2010 - 2019 Xilinx, Inc. + * Copyright (C) 2021 WangHuachen. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +/***************************************************************************** +* This file xemacpsif_physpeed.c implements functionalities to: +* - Detect the available PHYs connected to a MAC +* - Negotiate speed +* - Configure speed +* - Configure the SLCR registers for the negotiated speed +* +* In a typical use case, users of the APIs implemented in this file need to +* do the following. +* - Call the API detect_phy. It probes for the available PHYs connected to a MAC. +* The MACs can be Emac0 (XPAR_XEMACPS_0_BASEADDR, 0xE000B000) or Emac1 +* (XPAR_XEMACPS_0_BASEADDR, 0xE000C000). It populates an array to notify +* about the detected PHYs. The array phymapemac0 is used for Emac0 and +* phymapemac1 is for Emac1. +* - The users need to parse the corresponding arrays, phymapemac0 or phymapemac1 +* to know the available PHYs for a MAC. The users then need to call +* phy_setup_emacps to setup the PHYs for proper speed setting. The API +* phy_setup_emacps should be called with the PHY address for which the speed +* needs to be negotiated or configured. In a specific use case, if 2 PHYs are +* connected to Emac0 with addresses of 7 and 11, then users get these address +* details from phymapemac0 (after calling detect_phy) and then call +* phy_setup_emacps twice, with ab address of 7 and 11. +* - Points to note: The MAC can operate at only one speed. If a MAC is connected +* to multiple PHYs, then all PHYs must negotiate and configured for the same +* speed. +* - This file implements static functions to set proper SLCR clocks. As stated +* above, all PHYs connected to a PHY must operate at same speed and the SLCR +* clock will be setup accordingly. +* +* This file implements the following PHY types. +* - The standard RGMII. +* - It provides support for GMII to RGMII converter Xilinx IP. This Xilinx IP +* sits on the MDIO bus with a predefined PHY address. This IP exposes register +* that needs to be programmed with the negotiated speed. +* For example, in a typical design, the Emac0 or Emac1 exposes GMII interface. +* The user can then use the Xilinx IP that converts GMII to RGMII. +* The external PHY (most typically Marvell 88E1116R) negotiates for speed +* with the remote PHY. The implementation in this file then programs the +* Xilinx IP with this negotiated speed. The Xilinx IP has a predefined IP +* address exposed through xparameters.h +* - The SGMII and 1000 BaseX PHY interfaces. +* If the PHY interface is SGMII or 1000 BaseX a separate "get_IEEE_phy_speed" +* is used which is different from standard RGMII "get_IEEE_phy_speed". +* The 1000 BaseX always operates at 1000 Mbps. The SGMII interface can +* negotiate speed accordingly. +* For SGMII or 1000 BaseX interfaces, the detect_phy should not be called. +* The phy addresses for these interfaces are fixed at the design time. +* +* Point to note: +* A MAC can not be connected to PHYs where there is a mix between +* SGMII or 1000 Basex or GMII/MII/RGMII. +* In a typical multiple PHY designs, it is expected that the PHYs connected +* will be RGMII or GMII. +* +* The users can choose not to negotiate speed from lwip settings GUI. +* If they opt to choose a particular PHY speed, then the PHY will hard code +* the speed to operate only at the corresponding speed. It will not advertise +* any other speeds. It is users responsibility to ensure that the remote PHY +* supports the speed programmed through the lwip gui. +* +* The following combination of MDIO/PHY are supported: +* - Multiple PHYs connected to the MDIO bus of a MAC. If Emac0 MDIO is connected +* to single/multiple PHYs, it is supported. Similarly Emac1 MDIO connected to +* single/multiple PHYs is supported. +* - A design where both the interfaces are present and are connected to their own +* MDIO bus is supported. +* +* The following MDIO/PHY setup is not supported: +* - A design has both the MACs present. MDIO bus is available only for one MAC +* (Emac0 or Emac1). This MDIO bus has multiple PHYs available for both the +* MACs. The negotiated speed for PHYs sitting on the MDIO bus of one MAC will +* not be see for the other MAC and hence the speed/SLCR settings of the other +* MAC cannot be programmed. Hence this kind of design will not work for +* this implementation. +* +********************************************************************************/ + +#include "netif/xemacpsif.h" +#include "lwipopts.h" +#include "xparameters_ps.h" +#include "xparameters.h" +#include "xemac_ieee_reg.h" + +#if defined (__aarch64__) +#include "bspconfig.h" +#include "xil_smc.h" +#endif + +#define CONFIG_LINKSPEED_AUTODETECT 1 + +#define PHY_DETECT_REG 1 +#define PHY_IDENTIFIER_1_REG 2 +#define PHY_IDENTIFIER_2_REG 3 +#define PHY_DETECT_MASK 0x1808 +#define PHY_MARVELL_IDENTIFIER 0x0141 +#define PHY_TI_IDENTIFIER 0x2000 +#define PHY_REALTEK_IDENTIFIER 0x001c +#define PHY_XILINX_PCS_PMA_ID1 0x0174 +#define PHY_XILINX_PCS_PMA_ID2 0x0C00 + +#define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140 +#define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100 +#define XEMACPS_GMII2RGMII_SPEED10_FD 0x100 +#define XEMACPS_GMII2RGMII_REG_NUM 0x10 + +#define PHY_REGCR 0x0D +#define PHY_ADDAR 0x0E +#define PHY_RGMIIDCTL 0x86 +#define PHY_RGMIICTL 0x32 +#define PHY_STS 0x11 +#define PHY_TI_CR 0x10 +#define PHY_TI_CFG4 0x31 + +#define MICREL_PHY_IDENTIFIER 0x22 +#define MICREL_PHY_KSZ9031_MODEL 0x220 + +#define PHY_REGCR_ADDR 0x001F +#define PHY_REGCR_DATA 0x401F +#define PHY_TI_CRVAL 0x5048 +#define PHY_TI_CFG4RESVDBIT7 0x80 + +/* Frequency setting */ +#define SLCR_LOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x4) +#define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8) +#define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140) +#define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144) +#define SLCR_GEM_SRCSEL_EMIO 0x40 +#define SLCR_LOCK_KEY_VALUE 0x767B +#define SLCR_UNLOCK_KEY_VALUE 0xDF0D +#define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214) +#define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF + +#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \ + XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1 +#define PCM_PMA_CORE_PRESENT +#else +#undef PCM_PMA_CORE_PRESENT +#endif + +#ifdef PCM_PMA_CORE_PRESENT +#define IEEE_CTRL_RESET 0x9140 +#define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF +#endif + +u32_t phymapemac0[32]; +u32_t phymapemac1[32]; + +#if defined (PCM_PMA_CORE_PRESENT) || defined (CONFIG_LINKSPEED_AUTODETECT) +static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr); +#endif +static void SetUpSLCRDivisors(u32_t mac_baseaddr, s32_t speed); +#if defined (CONFIG_LINKSPEED1000) || defined (CONFIG_LINKSPEED100) \ + || defined (CONFIG_LINKSPEED10) +static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed); +#endif + +#ifdef PCM_PMA_CORE_PRESENT +u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr) +{ + u32_t link_speed; + u16_t regval; + u16_t phy_id; + + if(phy_addr == 0) { + for (phy_addr = 31; phy_addr > 0; phy_addr--) { + XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG, + &phy_id); + + if (phy_id == PHY_XILINX_PCS_PMA_ID1) { + XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_2_REG, + &phy_id); + if (phy_id == PHY_XILINX_PCS_PMA_ID2) { + /* Found a valid PHY address */ + LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n", + phy_addr)); + break; + } + } + } + } + + link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr); + if (link_speed == 1000) + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000); + else if (link_speed == 100) + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100); + else + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10); + + xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed); + return link_speed; +} + +static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) +{ + u16_t temp; + u16_t control; + u16_t status; + u16_t partner_capabilities; + + xil_printf("Start PHY autonegotiation \r\n"); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE; + control |= IEEE_STAT_AUTONEGOTIATE_RESTART; + control &= IEEE_CTRL_ISOLATE_DISABLE; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { + sleep(1); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, + &status); + } + xil_printf("autonegotiation complete \r\n"); + +#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 1); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp); + if ((temp & 0x0020) == 0x0020) { + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + return 1000; + } + else { + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + xil_printf("Link error, temp = %x\r\n", temp); + return 0; + } +#elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1 + xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n"); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp); + while(!(temp & 0x8000)) { + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp); + } + if((temp & 0x0C00) == 0x0800) { + return 1000; + } + else if((temp & 0x0C00) == 0x0400) { + return 100; + } + else if((temp & 0x0C00) == 0x0000) { + return 10; + } else { + xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Defaulting to Speed = 10 Mbps\r\n"); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &temp); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, 0x0100); + return 10; + } +#endif + +} + +#else /*PCM_PMA_CORE_PRESENT not defined, GMII/RGMII case*/ +void detect_phy(XEmacPs *xemacpsp) +{ + u16_t phy_reg; + u32_t phy_addr; + u32_t emacnum; + + if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) + emacnum = 0; + else + emacnum = 1; + for (phy_addr = 31; phy_addr > 0; phy_addr--) { + XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG, + &phy_reg); + + if ((phy_reg != 0xFFFF) && + ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { + /* Found a valid PHY address */ + LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n", + phy_addr)); + if (emacnum == 0) + phymapemac0[phy_addr] = TRUE; + else + phymapemac1[phy_addr] = TRUE; + + XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG, + &phy_reg); + if ((phy_reg != PHY_MARVELL_IDENTIFIER) && + (phy_reg != PHY_TI_IDENTIFIER) && + (phy_reg != PHY_REALTEK_IDENTIFIER)) { + xil_printf("WARNING: Not a Marvell or TI or Realtek Ethernet PHY. Please verify the initialization sequence\r\n"); + } + } + } +} + +u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr) +{ + u32_t link_speed; + u32_t conv_present = 0; + u32_t convspeeddupsetting = 0; + u32_t convphyaddr = 0; + +#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR + convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR; + conv_present = 1; +#endif +#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR + convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR; + conv_present = 1; +#endif + +#ifdef CONFIG_LINKSPEED_AUTODETECT + link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr); + if (link_speed == 1000) { + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000); + convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD; + } else if (link_speed == 100) { + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100); + convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD; + } else if (link_speed != XST_FAILURE){ + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10); + convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD; + } else { + xil_printf("Phy setup error \r\n"); + return XST_FAILURE; + } +#elif defined(CONFIG_LINKSPEED1000) + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000); + link_speed = 1000; + configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed); + convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD; + sleep(1); +#elif defined(CONFIG_LINKSPEED100) + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100); + link_speed = 100; + configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed); + convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD; + sleep(1); +#elif defined(CONFIG_LINKSPEED10) + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10); + link_speed = 10; + configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed); + convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD; + sleep(1); +#endif + if (conv_present) { + XEmacPs_PhyWrite(xemacpsp, convphyaddr, + XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting); + } + + xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed); + return link_speed; +} + +#if defined CONFIG_LINKSPEED_AUTODETECT +static u32_t get_phy_speed_ksz9031(XEmacPs *xemacpsp, u32_t phy_addr) +{ + static int phy_init_flag = 0; + u16_t temp; + u16_t control; + u16_t status; + u16_t status_speed; + u32_t timeout_counter = 0; + + xil_printf("Start PHY autonegotiation \r\n"); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control); + control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); + control |= IEEE_ASYMMETRIC_PAUSE_MASK; + control |= IEEE_PAUSE_MASK; + control |= ADVERTISE_100; + control |= ADVERTISE_10; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + &control); + control |= ADVERTISE_1000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + control); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, &control); + + control |= (7 << 12); /* max number of gigabit attempts */ + control |= (1 << 11); /* enable downshift */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, + control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE; + control |= IEEE_STAT_AUTONEGOTIATE_RESTART; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_RESET_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + while (1) { + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + if (control & IEEE_CTRL_RESET_MASK) + continue; + else + break; + } + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); + + while (!(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)) { + sleep(1); + XEmacPs_PhyRead(xemacpsp, phy_addr, + IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp); + timeout_counter++; + if ((phy_init_flag == 0) && (timeout_counter > 1)) + { + phy_init_flag = 1; + return XST_FAILURE; + } + if (timeout_counter == 30) { + xil_printf("Auto negotiation error \r\n"); + return XST_FAILURE; + } + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + } + xil_printf("autonegotiation complete \r\n"); + + XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1f, &status_speed); + + if ((status_speed & 0x40) == 0x40) /* 1000Mbps */ + return 1000; + else if ((status_speed & 0x20) == 0x20) /* 100Mbps */ + return 100; + else if ((status_speed & 0x10) == 0x10) /* 10Mbps */ + return 10; + else + return 0; + return XST_SUCCESS; +} + +static u32_t get_TI_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) +{ + u16_t control; + u16_t status; + u16_t status_speed; + u32_t timeout_counter = 0; + u32_t phyregtemp; + int i; + u32_t RetStatus; + static int phy_init_flag = 0; + + xil_printf("Start PHY autonegotiation \r\n"); + + XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, (u16_t *)&phyregtemp); + phyregtemp |= 0x4000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, phyregtemp); + RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, (u16_t *)&phyregtemp); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error during sw reset \n\r"); + return XST_FAILURE; + } + + XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp); + phyregtemp |= 0x8000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, phyregtemp); + + /* + * Delay + */ + for(i=0;i<1000000000;i++); + + RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error during reset \n\r"); + return XST_FAILURE; + } + + /* FIFO depth */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_TI_CR, PHY_TI_CRVAL); + RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_TI_CR, (u16_t *)&phyregtemp); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error writing to 0x10 \n\r"); + return XST_FAILURE; + } + + /* TX/RX tuning */ + /* Write to PHY_RGMIIDCTL */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA); + RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xA8); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error in tuning"); + return XST_FAILURE; + } + + /* Read PHY_RGMIIDCTL */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA); + RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error in tuning"); + return XST_FAILURE; + } + + /* Write PHY_RGMIICTL */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA); + RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xD3); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error in tuning"); + return XST_FAILURE; + } + + /* Read PHY_RGMIICTL */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA); + RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp); + if (RetStatus != XST_SUCCESS) { + xil_printf("Error in tuning"); + return XST_FAILURE; + } + + /* SW workaround for unstable link when RX_CTRL is not STRAP MODE 3 or 4 */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA); + RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp); + phyregtemp &= ~(PHY_TI_CFG4RESVDBIT7); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4); + XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA); + RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, phyregtemp); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); + control |= IEEE_ASYMMETRIC_PAUSE_MASK; + control |= IEEE_PAUSE_MASK; + control |= ADVERTISE_100; + control |= ADVERTISE_10; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + &control); + control |= ADVERTISE_1000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE; + control |= IEEE_STAT_AUTONEGOTIATE_RESTART; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); + + while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { + sleep(1); + timeout_counter++; + if ((phy_init_flag == 0) && (timeout_counter > 1)) + { + phy_init_flag = 1; + return XST_FAILURE; + } + if (timeout_counter == 30) { + xil_printf("Auto negotiation error \r\n"); + return XST_FAILURE; + } + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + } + xil_printf("autonegotiation complete \r\n"); + + XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_STS, &status_speed); + if ((status_speed & 0xC000) == 0x8000) { + return 1000; + } else if ((status_speed & 0xC000) == 0x4000) { + return 100; + } else { + return 10; + } + + return XST_SUCCESS; +} + +static u32_t get_Marvell_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) +{ + u16_t temp; + u16_t control; + u16_t status; + u16_t status_speed; + u32_t timeout_counter = 0; + u32_t temp_speed; + static int phy_init_flag = 0; + + xil_printf("Start PHY autonegotiation \r\n"); + + XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control); + control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); + control |= IEEE_ASYMMETRIC_PAUSE_MASK; + control |= IEEE_PAUSE_MASK; + control |= ADVERTISE_100; + control |= ADVERTISE_10; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + &control); + control |= ADVERTISE_1000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + control); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, + &control); + control |= (7 << 12); /* max number of gigabit attempts */ + control |= (1 << 11); /* enable downshift */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, + control); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE; + control |= IEEE_STAT_AUTONEGOTIATE_RESTART; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_RESET_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + while (1) { + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + if (control & IEEE_CTRL_RESET_MASK) + continue; + else + break; + } + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); + + while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { + sleep(1); + XEmacPs_PhyRead(xemacpsp, phy_addr, + IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp); + timeout_counter++; + if ((phy_init_flag == 0) && (timeout_counter > 1)) + { + phy_init_flag = 1; + return XST_FAILURE; + } + if (timeout_counter == 30) { + xil_printf("Auto negotiation error \r\n"); + return XST_FAILURE; + } + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + } + xil_printf("autonegotiation complete \r\n"); + + XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG, + &status_speed); + if (status_speed & 0x400) { + temp_speed = status_speed & IEEE_SPEED_MASK; + + if (temp_speed == IEEE_SPEED_1000) + return 1000; + else if(temp_speed == IEEE_SPEED_100) + return 100; + else + return 10; + } + + return XST_SUCCESS; +} + +static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) +{ + u16_t control; + u16_t status; + u16_t status_speed; + u32_t timeout_counter = 0; + u32_t temp_speed; + static int phy_init_flag = 0; + + xil_printf("Start PHY autonegotiation \r\n"); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); + control |= IEEE_ASYMMETRIC_PAUSE_MASK; + control |= IEEE_PAUSE_MASK; + control |= ADVERTISE_100; + control |= ADVERTISE_10; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + &control); + control |= ADVERTISE_1000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE; + control |= IEEE_STAT_AUTONEGOTIATE_RESTART; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_RESET_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + while (1) { + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + if (control & IEEE_CTRL_RESET_MASK) + continue; + else + break; + } + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); + + while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { + sleep(1); + timeout_counter++; + if ((phy_init_flag == 0) && (timeout_counter > 1)) + { + phy_init_flag = 1; + return XST_FAILURE; + } + if (timeout_counter == 30) { + xil_printf("Auto negotiation error \r\n"); + return XST_FAILURE; + } + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + } + xil_printf("autonegotiation complete \r\n"); + + XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG, + &status_speed); + if (status_speed & 0x400) { + temp_speed = status_speed & IEEE_SPEED_MASK; + + if (temp_speed == IEEE_SPEED_1000) + return 1000; + else if(temp_speed == IEEE_SPEED_100) + return 100; + else + return 10; + } + + return XST_FAILURE; +} + +static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) +{ + u16_t phy_identity; + u32_t RetStatus; + + XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG, + &phy_identity); + if(phy_identity == MICREL_PHY_IDENTIFIER){ + RetStatus = get_phy_speed_ksz9031(xemacpsp, phy_addr); + } else if (phy_identity == PHY_TI_IDENTIFIER) { + RetStatus = get_TI_phy_speed(xemacpsp, phy_addr); + } else if (phy_identity == PHY_REALTEK_IDENTIFIER) { + RetStatus = get_Realtek_phy_speed(xemacpsp, phy_addr); + } else { + RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr); + } + + return RetStatus; +} +#endif + +#if defined (CONFIG_LINKSPEED1000) || defined (CONFIG_LINKSPEED100) \ + || defined (CONFIG_LINKSPEED10) +static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed) +{ + u16_t control; + u16_t autonereg; + + XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control); + control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg |= IEEE_ASYMMETRIC_PAUSE_MASK; + autonereg |= IEEE_PAUSE_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control &= ~IEEE_CTRL_LINKSPEED_1000M; + control &= ~IEEE_CTRL_LINKSPEED_100M; + control &= ~IEEE_CTRL_LINKSPEED_10M; + + if (speed == 1000) { + control |= IEEE_CTRL_LINKSPEED_1000M; + + /* Don't advertise PHY speed of 100 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg &= (~ADVERTISE_100); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + + /* Don't advertise PHY speed of 10 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg &= (~ADVERTISE_10); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + + /* Advertise PHY speed of 1000 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg); + autonereg |= ADVERTISE_1000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg); + } + + else if (speed == 100) { + control |= IEEE_CTRL_LINKSPEED_100M; + + /* Don't advertise PHY speed of 1000 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg); + autonereg &= (~ADVERTISE_1000); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg); + + /* Don't advertise PHY speed of 10 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg &= (~ADVERTISE_10); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + + /* Advertise PHY speed of 100 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg |= ADVERTISE_100; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + } + + else if (speed == 10) { + control |= IEEE_CTRL_LINKSPEED_10M; + + /* Don't advertise PHY speed of 1000 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg); + autonereg &= (~ADVERTISE_1000); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg); + + /* Don't advertise PHY speed of 100 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg &= (~ADVERTISE_100); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + + /* Advertise PHY speed of 10 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg |= ADVERTISE_10; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + } + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, + control | IEEE_CTRL_RESET_MASK); + { + volatile s32_t wait; + for (wait=0; wait < 100000; wait++); + } + return 0; +} +#endif +#endif /*PCM_PMA_CORE_PRESENT*/ + +static void SetUpSLCRDivisors(u32_t mac_baseaddr, s32_t speed) +{ + volatile u32_t slcrBaseAddress; + u32_t SlcrDiv0 = 0; + u32_t SlcrDiv1 = 0; + u32_t SlcrTxClkCntrl; + u32_t gigeversion; + volatile u32_t CrlApbBaseAddr; + u32_t CrlApbDiv0 = 0; + u32_t CrlApbDiv1 = 0; + u32_t CrlApbGemCtrl; +#if EL1_NONSECURE + u32_t ClkId; +#endif + + gigeversion = ((Xil_In32(mac_baseaddr + 0xFC)) >> 16) & 0xFFF; + if (gigeversion == 2) { + + *(volatile u32_t *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE; + + if (mac_baseaddr == ZYNQ_EMACPS_0_BASEADDR) { + slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR; + } else { + slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR; + } + + if((*(volatile u32_t *)(UINTPTR)(slcrBaseAddress)) & + SLCR_GEM_SRCSEL_EMIO) { + return; + } + + if (speed == 1000) { + if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) { +#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1; +#endif + } else { +#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1; +#endif + } + } else if (speed == 100) { + if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) { +#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1; +#endif + } else { +#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1; +#endif + } + } else { + if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) { +#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1; +#endif + } else { +#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1; +#endif + } + } + + if (SlcrDiv0 != 0 && SlcrDiv1 != 0) { + SlcrTxClkCntrl = *(volatile u32_t *)(UINTPTR)(slcrBaseAddress); + SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK; + SlcrTxClkCntrl |= (SlcrDiv1 << 20); + SlcrTxClkCntrl |= (SlcrDiv0 << 8); + *(volatile u32_t *)(UINTPTR)(slcrBaseAddress) = SlcrTxClkCntrl; + *(volatile u32_t *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE; + } else { + xil_printf("Clock Divisors incorrect - Please check\r\n"); + } + } else if (gigeversion == GEM_VERSION_ZYNQMP) { + /* Setup divisors in CRL_APB for Zynq Ultrascale+ MPSoC */ + if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) { + CrlApbBaseAddr = CRL_APB_GEM0_REF_CTRL; + } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) { + CrlApbBaseAddr = CRL_APB_GEM1_REF_CTRL; + } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) { + CrlApbBaseAddr = CRL_APB_GEM2_REF_CTRL; + } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) { + CrlApbBaseAddr = CRL_APB_GEM3_REF_CTRL; + } + + if (speed == 1000) { + if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1; +#endif + } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1; +#endif + } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV1; +#endif + } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV1; +#endif + } + } else if (speed == 100) { + if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV1; +#endif + } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV1; +#endif + } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV1; +#endif + } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV1; +#endif + } + } else { + if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV1; +#endif + } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV1; +#endif + } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV1; +#endif + } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) { +#ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0 + CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0; + CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV1; +#endif + } + } + + if (CrlApbDiv0 != 0 && CrlApbDiv1 != 0) { + #if EL1_NONSECURE + XSmc_OutVar RegRead; + RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr), + 0, 0, 0, 0, 0, 0); + CrlApbGemCtrl = RegRead.Arg0 >> 32; + #else + CrlApbGemCtrl = *(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr); + #endif + CrlApbGemCtrl &= ~CRL_APB_GEM_DIV0_MASK; + CrlApbGemCtrl |= CrlApbDiv0 << CRL_APB_GEM_DIV0_SHIFT; + CrlApbGemCtrl &= ~CRL_APB_GEM_DIV1_MASK; + CrlApbGemCtrl |= CrlApbDiv1 << CRL_APB_GEM_DIV1_SHIFT; + #if EL1_NONSECURE + Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(CrlApbBaseAddr) | ((u64)(0xFFFFFFFF) << 32), + (u64)CrlApbGemCtrl, 0, 0, 0, 0, 0); + do { + RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr), + 0, 0, 0, 0, 0, 0); + } while((RegRead.Arg0 >> 32) != CrlApbGemCtrl); + #else + *(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr) = CrlApbGemCtrl; + #endif + } else { + xil_printf("Clock Divisors incorrect - Please check\r\n"); + } + } else if (gigeversion == GEM_VERSION_VERSAL) { + /* Setup divisors in CRL for Versal */ + if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) { + CrlApbBaseAddr = VERSAL_CRL_GEM0_REF_CTRL; +#if EL1_NONSECURE + ClkId = CLK_GEM0_REF; +#endif + } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) { + CrlApbBaseAddr = VERSAL_CRL_GEM1_REF_CTRL; +#if EL1_NONSECURE + ClkId = CLK_GEM1_REF; +#endif + } + + if (speed == 1000) { + if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) { +#ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 + CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0; +#endif + } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) { +#ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0 + CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0; +#endif + } + } else if (speed == 100) { + if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) { +#ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 + CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0; +#endif + } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) { +#ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0 + CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0; +#endif + } + } else { + if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) { +#ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0 + CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0; +#endif + } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) { +#ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0 + CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0; +#endif + } + } + + if (CrlApbDiv0 != 0) { +#if EL1_NONSECURE + Xil_Smc(PM_SET_DIVIDER_SMC_FID, (((u64)CrlApbDiv0 << 32) | ClkId), 0, 0, 0, 0, 0, 0); +#else + CrlApbGemCtrl = Xil_In32((UINTPTR)CrlApbBaseAddr); + CrlApbGemCtrl &= ~VERSAL_CRL_GEM_DIV_MASK; + CrlApbGemCtrl |= CrlApbDiv0 << VERSAL_CRL_APB_GEM_DIV_SHIFT; + + Xil_Out32((UINTPTR)CrlApbBaseAddr, CrlApbGemCtrl); +#endif + } else { + xil_printf("Clock Divisors incorrect - Please check\r\n"); + } + } + + return; +} diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xlwipconfig.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xlwipconfig.h new file mode 100644 index 0000000000..fd114dd5fb --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xlwipconfig.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. + * Copyright (C) 2007 - 2018 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __XLWIPCONFIG_H_ +#define __XLWIPCONFIG_H_ + + +/* This is a generated file - do not edit */ + +#define XLWIP_CONFIG_INCLUDE_GEM 1 +#define XLWIP_CONFIG_EMAC_NUMBER 0 +#define XLWIP_CONFIG_N_TX_DESC 64 +#define XLWIP_CONFIG_N_RX_DESC 64 + +#endif diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c new file mode 100644 index 0000000000..b5a773e29b --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2007 - 2019 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include + +#include "netif/xpqueue.h" +#include "xil_printf.h" + +#define NUM_QUEUES 2 + +pq_queue_t pq_queue[NUM_QUEUES]; + +pq_queue_t * +pq_create_queue() +{ + static int i; + pq_queue_t *q = NULL; + + if (i >= NUM_QUEUES) { + xil_printf("ERR: Max Queues allocated\n\r"); + return q; + } + + q = &pq_queue[i++]; + + if (!q) + return q; + + q->head = q->tail = q->len = 0; + + return q; +} + +int +pq_enqueue(pq_queue_t *q, void *p) +{ + if (q->len == PQ_QUEUE_SIZE) + return -1; + + q->data[q->head] = p; + q->head = (q->head + 1)%PQ_QUEUE_SIZE; + q->len++; + + return 0; +} + +void* +pq_dequeue(pq_queue_t *q) +{ + int ptail; + + if (q->len == 0) + return NULL; + + ptail = q->tail; + q->tail = (q->tail + 1)%PQ_QUEUE_SIZE; + q->len--; + + return q->data[ptail]; +} + +int +pq_qlength(pq_queue_t *q) +{ + return q->len; +} diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c new file mode 100644 index 0000000000..9d6fb85f03 --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c @@ -0,0 +1,15 @@ +#include "netif/xtopology.h" +#include "xparameters.h" + +struct xtopology_t xtopology[] = { + { + 0xFF0E0000, + xemac_type_emacps, + 0x0, + 0x0, + 0xF8F00100, + XPAR_XEMACPS_3_INTR, + }, +}; + +int xtopology_n_emacs = 1; diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h index 3970866971..107f0bd724 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h @@ -54,6 +54,9 @@ typedef long LONG; typedef unsigned long ULONG; #endif +#define ULONG64_HI_MASK 0xFFFFFFFF00000000U +#define ULONG64_LO_MASK ~ULONG64_HI_MASK + /** @{ */ /** * This data type defines an interrupt handler for a device. diff --git a/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c b/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c new file mode 100644 index 0000000000..758fc138df --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2021, WangHuachen + * + * SPDX-License-Identifier: MIT + * + * Change Logs: + * Date Author Notes + * 2021-5-10 WangHuachen the first version + */ + + +#include "board.h" +#include +#include "lwipopts.h" +#include "lwip/opt.h" +#include "drv_eth.h" +#include "lwip/netif.h" +#include "netif/xadapter.h" +#include "netif/xemacpsif.h" +#include "xparameters.h" +#include "xemacps.h" + +#define DBG_TAG "drv.emac" +#define DBG_LEVEL DBG_INFO +#include + +#define MAC_BASE_ADDR XPAR_PSU_ETHERNET_3_BASEADDR +#define MAX_ADDR_LEN 6 + +struct rt_zynqmp_eth +{ + /* inherit from ethernet device */ + struct eth_device parent; + + /* interface address info, hw address */ + rt_uint8_t dev_addr[MAX_ADDR_LEN]; + + struct xemac_s *xemac; +}; + +static struct rt_zynqmp_eth zynqmp_eth_device; +extern XEmacPs_Config *mac_config; +extern struct netif *NetIf; + +static void rt_hw_eth_isr(int irqno, void *param) +{ + struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)param; + xemacpsif_s *xemacpsif = (xemacpsif_s *)eth_dev->xemac->state; + XEmacPs_IntrHandler(&xemacpsif->emacps); +} + +extern enum ethernet_link_status eth_link_status; +extern u32_t phy_link_detect(XEmacPs *xemacp, u32_t phy_addr); +extern u32_t phy_autoneg_status(XEmacPs *xemacp, u32_t phy_addr); +extern u32_t phyaddrforemac; + +void rt_zynqmp_eth_link_detect(struct rt_zynqmp_eth *eth_dev) +{ + u32_t link_speed, phy_link_status; + struct xemac_s *xemac = eth_dev->xemac; + xemacpsif_s *xemacs = (xemacpsif_s *)(xemac->state); + XEmacPs *xemacp = &xemacs->emacps; + + if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) || + (eth_link_status == ETH_LINK_UNDEFINED)) + return; + + phy_link_status = phy_link_detect(xemacp, phyaddrforemac); + + if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status)) + eth_link_status = ETH_LINK_DOWN; + + switch (eth_link_status) { + case ETH_LINK_UNDEFINED: + case ETH_LINK_UP: + return; + case ETH_LINK_DOWN: + eth_device_linkchange(&zynqmp_eth_device.parent, RT_FALSE); + eth_link_status = ETH_LINK_NEGOTIATING; + LOG_D("Ethernet Link down"); + break; + case ETH_LINK_NEGOTIATING: + if (phy_link_status && + phy_autoneg_status(xemacp, phyaddrforemac)) { + + /* Initiate Phy setup to get link speed */ + link_speed = phy_setup_emacps(xemacp, + phyaddrforemac); + XEmacPs_SetOperatingSpeed(xemacp, link_speed); + + eth_device_linkchange(&zynqmp_eth_device.parent, RT_TRUE); + eth_link_status = ETH_LINK_UP; + LOG_D("Ethernet Link up"); + } + break; + } +} + +static void phy_monitor_thread(void *parameter) +{ + struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)parameter; + + while (1) + { + rt_zynqmp_eth_link_detect(eth_dev); + rt_thread_delay(RT_TICK_PER_SECOND); + } +} + +static rt_err_t rt_zynqmp_eth_init(rt_device_t dev) +{ + struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data; + struct netif *netif = eth_dev->parent.netif; + struct xemac_s *xemac; + xemacpsif_s *xemacpsif; + u32 dmacrreg; + s32_t status = XST_SUCCESS; + struct xtopology_t *xtopologyp; + + if (eth_dev->xemac != RT_NULL) + { + LOG_W("rt_zynqmp_eth_init: device has been initialized"); + return -RT_ERROR; + } + + NetIf = netif; + + xemacpsif = rt_malloc(sizeof *xemacpsif); + if (xemacpsif == NULL) + { + LOG_E("rt_zynqmp_eth_init: out of memory"); + return -RT_ENOMEM; + } + + xemac = rt_malloc(sizeof *xemac); + if (xemac == NULL) + { + LOG_E("rt_zynqmp_eth_init: out of memory"); + return -RT_ENOMEM; + } + + xemac->state = (void *)xemacpsif; + xemac->topology_index = xtopology_find_index(MAC_BASE_ADDR); + xemac->type = xemac_type_emacps; + xemac->rt_eth_device = ð_dev->parent; + + xemacpsif->send_q = NULL; + xemacpsif->recv_q = pq_create_queue(); + if (!xemacpsif->recv_q) + return -RT_ENOMEM; + + eth_dev->xemac = xemac; + + /* obtain config of this emac */ + mac_config = (XEmacPs_Config *)xemacps_lookup_config(MAC_BASE_ADDR); + + status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config, + mac_config->BaseAddress); + if (status != XST_SUCCESS) + { + LOG_W("In %s:EmacPs Configuration Failed....", __func__); + return -RT_ERROR; + } + + /* initialize the mac */ + init_emacps(xemacpsif, netif); + + dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + dmacrreg = dmacrreg | (0x00000010); + XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, + XEMACPS_DMACR_OFFSET, dmacrreg); + + setup_isr(xemac); + init_dma(xemac); + + xtopologyp = &xtopology[xemac->topology_index]; + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + rt_hw_interrupt_install(xtopologyp->scugic_emac_intr, rt_hw_eth_isr, (void *)eth_dev, "eth"); + /* + * Enable the interrupt for emacps. + */ + rt_hw_interrupt_umask(xtopologyp->scugic_emac_intr); + + start_emacps(xemacpsif); + + if (eth_link_status == ETH_LINK_UP) + eth_device_linkchange(ð_dev->parent, RT_TRUE); + + rt_thread_t tid; + tid = rt_thread_create("phylnk", + phy_monitor_thread, + eth_dev, + 1024, + RT_THREAD_PRIORITY_MAX - 2, + 2); + if (tid != RT_NULL) + rt_thread_startup(tid); + else + return -RT_ERROR; + + return RT_EOK; +} + +static rt_err_t rt_zynqmp_eth_open(rt_device_t dev, rt_uint16_t oflag) +{ + LOG_D("emac open"); + return RT_EOK; +} + +static rt_err_t rt_zynqmp_eth_close(rt_device_t dev) +{ + LOG_D("emac close"); + return RT_EOK; +} + +static rt_size_t rt_zynqmp_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + LOG_D("emac read"); + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_size_t rt_zynqmp_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + LOG_D("emac write"); + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_err_t rt_zynqmp_eth_control(rt_device_t dev, int cmd, void *args) +{ + struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data; + switch (cmd) + { + case NIOCTL_GADDR: + /* get mac address */ + if (args) rt_memcpy(args, eth_dev->dev_addr, 6); + else return -RT_ERROR; + break; + + default : + break; + } + + return RT_EOK; +} + +extern err_t _unbuffered_low_level_output(xemacpsif_s *xemacpsif, struct pbuf *p); +rt_err_t rt_zynqmp_eth_tx(rt_device_t dev, struct pbuf *p) +{ + rt_base_t lev; + rt_err_t err; + XEmacPs_BdRing *txring; + + struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data; + struct xemac_s *xemac = eth_dev->xemac; + xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); + + lev = rt_hw_interrupt_disable(); + + txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps)); + process_sent_bds(xemacpsif, txring); + + if (is_tx_space_available(xemacpsif)) + { + _unbuffered_low_level_output(xemacpsif, p); + err = RT_EOK; + } + else + { +#if LINK_STATS + lwip_stats.link.drop++; +#endif + LOG_D("pack dropped, no space"); + err = -RT_ENOMEM; + } + + rt_hw_interrupt_enable(lev); + + return err; +} + +struct pbuf *rt_zynqmp_eth_rx(rt_device_t dev) +{ + rt_base_t lev; + struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data; + struct xemac_s *xemac = eth_dev->xemac; + xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); + struct pbuf *p; + + lev = rt_hw_interrupt_disable(); + + /* see if there is data to process */ + if (pq_qlength(xemacpsif->recv_q) == 0) + return NULL; + + /* return one packet from receive q */ + p = (struct pbuf *)pq_dequeue(xemacpsif->recv_q); + + rt_hw_interrupt_enable(lev); + + return p; +} + +static int rt_hw_zynqmp_eth_init(void) +{ + rt_err_t state = RT_EOK; + + zynqmp_eth_device.xemac = RT_NULL; + + zynqmp_eth_device.dev_addr[0] = 0x00; + zynqmp_eth_device.dev_addr[1] = 0x0A; + zynqmp_eth_device.dev_addr[2] = 0x35; + zynqmp_eth_device.dev_addr[3] = 0x00; + zynqmp_eth_device.dev_addr[4] = 0x01; + zynqmp_eth_device.dev_addr[5] = 0x02; + + zynqmp_eth_device.parent.parent.init = rt_zynqmp_eth_init; + zynqmp_eth_device.parent.parent.open = rt_zynqmp_eth_open; + zynqmp_eth_device.parent.parent.close = rt_zynqmp_eth_close; + zynqmp_eth_device.parent.parent.read = rt_zynqmp_eth_read; + zynqmp_eth_device.parent.parent.write = rt_zynqmp_eth_write; + zynqmp_eth_device.parent.parent.control = rt_zynqmp_eth_control; + zynqmp_eth_device.parent.parent.user_data = &zynqmp_eth_device; + + zynqmp_eth_device.parent.eth_rx = rt_zynqmp_eth_rx; + zynqmp_eth_device.parent.eth_tx = rt_zynqmp_eth_tx; + + /* register eth device */ + state = eth_device_init(&(zynqmp_eth_device.parent), "e0"); + if (RT_EOK == state) + { + LOG_D("emac device init success"); + } + else + { + LOG_E("emac device init faild: %d", state); + state = -RT_ERROR; + return state; + } + + return state; +} +INIT_DEVICE_EXPORT(rt_hw_zynqmp_eth_init); \ No newline at end of file diff --git a/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.h b/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.h new file mode 100644 index 0000000000..3d1a5d37cf --- /dev/null +++ b/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.h @@ -0,0 +1,13 @@ +#ifndef __DRV_ETH_H__ +#define __DRV_ETH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/zynqmp-r5-axu4ev/rtconfig.h b/bsp/zynqmp-r5-axu4ev/rtconfig.h index 95d92ea09d..03ced833bc 100644 --- a/bsp/zynqmp-r5-axu4ev/rtconfig.h +++ b/bsp/zynqmp-r5-axu4ev/rtconfig.h @@ -19,6 +19,9 @@ #define RT_USING_TIMER_SOFT #define RT_TIMER_THREAD_PRIO 4 #define RT_TIMER_THREAD_STACK_SIZE 512 + +/* kservice optimization */ + #define RT_DEBUG /* Inter-Thread communication */ @@ -32,7 +35,7 @@ /* Memory Management */ #define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM +#define RT_USING_SLAB #define RT_USING_HEAP /* Kernel Device Object */ @@ -41,7 +44,7 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40003 +#define RT_VER_NUM 0x40004 /* RT-Thread Components */ @@ -83,6 +86,8 @@ #define RT_DFS_ELM_WORD_ACCESS #define RT_DFS_ELM_USE_LFN_3 #define RT_DFS_ELM_USE_LFN 3 +#define RT_DFS_ELM_LFN_UNICODE_0 +#define RT_DFS_ELM_LFN_UNICODE 0 #define RT_DFS_ELM_MAX_LFN 255 #define RT_DFS_ELM_DRIVES 2 #define RT_DFS_ELM_MAX_SECTOR_SIZE 512 @@ -93,6 +98,9 @@ #define RT_USING_DEVICE_IPC #define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 #define RT_USING_SERIAL #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 @@ -101,24 +109,77 @@ /* Using USB */ -/* Using RapidIO */ - - /* POSIX layer and C standard library */ #define RT_USING_LIBC #define RT_USING_POSIX +#define RT_LIBC_FIXED_TIMEZONE 8 /* Network */ /* Socket abstraction layer */ +#define RT_USING_SAL +#define SAL_INTERNET_CHECK + +/* protocol stack implement */ + +#define SAL_USING_LWIP +#define SAL_USING_POSIX /* Network interface device */ +#define RT_USING_NETDEV +#define NETDEV_USING_IFCONFIG +#define NETDEV_USING_PING +#define NETDEV_USING_NETSTAT +#define NETDEV_USING_AUTO_DEFAULT +#define NETDEV_IPV4 1 +#define NETDEV_IPV6 0 /* light weight TCP/IP stack */ +#define RT_USING_LWIP +#define RT_USING_LWIP202 +#define RT_LWIP_MEM_ALIGNMENT 32 +#define RT_LWIP_IGMP +#define RT_LWIP_ICMP +#define RT_LWIP_DNS +#define RT_LWIP_DHCP +#define IP_SOF_BROADCAST 1 +#define IP_SOF_BROADCAST_RECV 1 + +/* Static IPv4 Address */ + +#define RT_LWIP_IPADDR "192.168.1.30" +#define RT_LWIP_GWADDR "192.168.1.1" +#define RT_LWIP_MSKADDR "255.255.255.0" +#define RT_LWIP_UDP +#define RT_LWIP_TCP +#define RT_LWIP_RAW +#define RT_MEMP_NUM_NETCONN 8 +#define RT_LWIP_PBUF_NUM 256 +#define RT_LWIP_RAW_PCB_NUM 4 +#define RT_LWIP_UDP_PCB_NUM 4 +#define RT_LWIP_TCP_PCB_NUM 4 +#define RT_LWIP_TCP_SEG_NUM 40 +#define RT_LWIP_TCP_SND_BUF 8196 +#define RT_LWIP_TCP_WND 8196 +#define RT_LWIP_TCPTHREAD_PRIORITY 10 +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 +#define RT_LWIP_TCPTHREAD_STACKSIZE 2048 +#define RT_LWIP_ETHTHREAD_PRIORITY 12 +#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define SO_REUSE 1 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_RCVBUF 1 +#define LWIP_SO_LINGER 0 +#define LWIP_NETIF_LOOPBACK 0 +#define RT_LWIP_USING_PING /* AT commands */ @@ -129,6 +190,9 @@ /* Utilities */ +/* RT-Thread Utestcases */ + + /* RT-Thread online packages */ /* IoT - internet of things */ @@ -166,11 +230,17 @@ /* peripheral libraries and drivers */ +/* AI packages */ + + /* miscellaneous packages */ /* samples: kernel and components samples */ + +/* entertainment: terminal games and other interesting software packages */ + #define SOC_ZYNQMP_R5 /* Hardware Drivers Config */ @@ -184,6 +254,13 @@ #define BSP_USING_SDIO #define BSP_USING_SD0 +/* Please set RT_LWIP_PBUF_NUM is at least 256 if Enable Ethernet! */ + +/* Please set RT_LWIP_MEM_ALIGNMENT is at 32 if Enable Ethernet! */ + +#define BSP_USING_ETH +#define RT_LWIP_PBUF_POOL_BUFSIZE 1700 + /* Board extended module Drivers */ diff --git a/libcpu/arm/zynqmp-r5/cache.c b/libcpu/arm/zynqmp-r5/cache.c index d6e7cd2d6d..ed0efa4824 100644 --- a/libcpu/arm/zynqmp-r5/cache.c +++ b/libcpu/arm/zynqmp-r5/cache.c @@ -1,11 +1,13 @@ /* * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2014 - 2020 Xilinx, Inc. All rights reserved. + * Copyright (c) 2021 WangHuachen. All rights reserved. + * SPDX-License-Identifier: MIT * * Change Logs: * Date Author Notes * 2020-03-19 WangHuachen first version + * 2021-05-10 WangHuachen add more functions */ #include #include @@ -44,41 +46,85 @@ typedef rt_uint32_t u32; XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)) #endif +void Xil_DCacheEnable(void); +void Xil_DCacheDisable(void); +void Xil_DCacheInvalidate(void); +void Xil_DCacheInvalidateRange(INTPTR adr, u32 len); +void Xil_DCacheFlush(void); +void Xil_DCacheFlushRange(INTPTR adr, u32 len); +void Xil_DCacheInvalidateLine(INTPTR adr); +void Xil_DCacheFlushLine(INTPTR adr); +void Xil_DCacheStoreLine(INTPTR adr); +void Xil_ICacheEnable(void); +void Xil_ICacheDisable(void); +void Xil_ICacheInvalidate(void); +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len); +void Xil_ICacheInvalidateLine(INTPTR adr); -void Xil_ICacheInvalidateRange(INTPTR adr, u32 len) +void Xil_DCacheEnable(void) +{ + register u32 CtrlReg; + + /* enable caches only if they are disabled */ +#if defined (__GNUC__) + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL,CtrlReg); +#endif + if ((CtrlReg & XREG_CP15_CONTROL_C_BIT)==0x00000000U) { + /* invalidate the Data cache */ + Xil_DCacheInvalidate(); + + /* enable the Data cache */ + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + } +} + +void Xil_DCacheDisable(void) +{ + register u32 CtrlReg; + + /* clean and invalidate the Data cache */ + Xil_DCacheFlush(); + + /* disable the Data cache */ +#if defined (__GNUC__) + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL,CtrlReg); +#endif + + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +void Xil_DCacheInvalidate(void) { - u32 LocalAddr = adr; - const u32 cacheline = 32U; - u32 end; u32 currmask; currmask = mfcpsr(); mtcpsr(currmask | IRQ_FIQ_MASK); - if (len != 0x00000000U) { - /* Back the starting address up to the start of a cache line - * perform cache operations until adr+len - */ - end = LocalAddr + len; - LocalAddr = LocalAddr & ~(cacheline - 1U); - /* Select cache L0 I-cache in CSSR */ - mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); +#if 0 + stack_end = (u32 )&_stack_end; + stack_start = (u32 )&__undef_stack; + stack_size = stack_start-stack_end; - while (LocalAddr < end) { + /* Flush stack memory to save return address */ + Xil_DCacheFlushRange(stack_end, stack_size); +#endif + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); - /* Invalidate L1 I-cache line */ - asm_inval_ic_line_mva_pou(LocalAddr); + /*invalidate all D cache*/ + mtcp(XREG_CP15_INVAL_DC_ALL, 0); - LocalAddr += cacheline; - } - } - - /* Wait for invalidate to complete */ - dsb(); mtcpsr(currmask); } -void Xil_DCacheFlushLine(INTPTR adr) +void Xil_DCacheInvalidateLine(INTPTR adr) { u32 currmask; @@ -86,11 +132,11 @@ void Xil_DCacheFlushLine(INTPTR adr) mtcpsr(currmask | IRQ_FIQ_MASK); mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); + mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F))); - mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F))); - - /* Wait for flush to complete */ + /* Wait for invalidate to complete */ dsb(); + mtcpsr(currmask); } @@ -135,6 +181,79 @@ void Xil_DCacheInvalidateRange(INTPTR adr, u32 len) mtcpsr(currmask); } +void Xil_DCacheFlush(void) +{ + register u32 CsidReg, C7Reg; + u32 CacheSize, LineSize, NumWays; + u32 Way, WayIndex, Set, SetIndex, NumSet; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + /* Select cache level 0 and D cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); + +#if defined (__GNUC__) + CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_CACHE_SIZE_ID,CsidReg); +#endif + /* Determine Cache Size */ + + CacheSize = (CsidReg >> 13U) & 0x000001FFU; + CacheSize += 0x00000001U; + CacheSize *= (u32)128; /* to get number of bytes */ + + /* Number of Ways */ + NumWays = (CsidReg & 0x000003ffU) >> 3U; + NumWays += 0x00000001U; + + /* Get the cacheline size, way size, index size from csidr */ + LineSize = (CsidReg & 0x00000007U) + 0x00000004U; + + NumSet = CacheSize/NumWays; + NumSet /= (0x00000001U << LineSize); + + Way = 0U; + Set = 0U; + + /* Invalidate all the cachelines */ + for (WayIndex = 0U; WayIndex < NumWays; WayIndex++) { + for (SetIndex = 0U; SetIndex < NumSet; SetIndex++) { + C7Reg = Way | Set; + /* Flush by Set/Way */ + asm_clean_inval_dc_line_sw(C7Reg); + + Set += (0x00000001U << LineSize); + } + Set = 0U; + Way += 0x40000000U; + } + + /* Wait for flush to complete */ + dsb(); + mtcpsr(currmask); + + mtcpsr(currmask); +} + +void Xil_DCacheFlushLine(INTPTR adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); + + mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F))); + + /* Wait for flush to complete */ + dsb(); + mtcpsr(currmask); +} + void Xil_DCacheFlushRange(INTPTR adr, u32 len) { u32 LocalAddr = adr; @@ -163,6 +282,130 @@ void Xil_DCacheFlushRange(INTPTR adr, u32 len) mtcpsr(currmask); } +void Xil_DCacheStoreLine(INTPTR adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); + mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1F))); + + /* Wait for store to complete */ + dsb(); + isb(); + + mtcpsr(currmask); +} + +void Xil_ICacheEnable(void) +{ + register u32 CtrlReg; + + /* enable caches only if they are disabled */ +#if defined (__GNUC__) + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#endif + if ((CtrlReg & XREG_CP15_CONTROL_I_BIT)==0x00000000U) { + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0); + + /* enable the instruction cache */ + CtrlReg |= (XREG_CP15_CONTROL_I_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + } +} + +void Xil_ICacheDisable(void) +{ + register u32 CtrlReg; + + dsb(); + + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0); + + /* disable the instruction cache */ +#if defined (__GNUC__) + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL,CtrlReg); +#endif + + CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +void Xil_ICacheInvalidate(void) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1); + + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0); + + /* Wait for invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + +void Xil_ICacheInvalidateLine(INTPTR adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1); + mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1F))); + + /* Wait for invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + if (len != 0x00000000U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Select cache L0 I-cache in CSSR */ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); + + while (LocalAddr < end) { + + /* Invalidate L1 I-cache line */ + asm_inval_ic_line_mva_pou(LocalAddr); + + LocalAddr += cacheline; + } + } + + /* Wait for invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + void rt_hw_cpu_icache_ops(int ops, void *addr, int size) { if (ops == RT_HW_CACHE_INVALIDATE) diff --git a/libcpu/arm/zynqmp-r5/start_gcc.S b/libcpu/arm/zynqmp-r5/start_gcc.S index faea0022be..7e99c9e82b 100644 --- a/libcpu/arm/zynqmp-r5/start_gcc.S +++ b/libcpu/arm/zynqmp-r5/start_gcc.S @@ -6,6 +6,9 @@ * Change Logs: * Date Author Notes * 2020-03-19 WangHuachen first version + * 2021-05-11 WangHuachen Added call to Xil_InitializeExistingMPURegConfig to + * initialize the MPU configuration table with the MPU + * configurations already set in Init_Mpu function. */ .equ Mode_USR, 0x10 @@ -234,6 +237,7 @@ ctor_loop: b ctor_loop ctor_end: + bl Xil_InitializeExistingMPURegConfig /* Initialize MPU config */ /* start RT-Thread Kernel */ ldr pc, _entry diff --git a/libcpu/arm/zynqmp-r5/xil_mmu.h b/libcpu/arm/zynqmp-r5/xil_mmu.h new file mode 100644 index 0000000000..99e019c6f5 --- /dev/null +++ b/libcpu/arm/zynqmp-r5/xil_mmu.h @@ -0,0 +1,54 @@ +/****************************************************************************** +* Copyright (c) 2015 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xil_mmu.h +* This file only includes xil_mpu.h which contains Xil_SetTlbAttributes API +* defined for MPU in R5. R5 does not have mmu and for usage of similar API +* the file has been created. +* +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 5.0    pkp  2/12/15 Initial version
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef XIL_MMU_H +#define XIL_MMU_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_mpu.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_MMU_H */ diff --git a/libcpu/arm/zynqmp-r5/xil_mpu.c b/libcpu/arm/zynqmp-r5/xil_mpu.c new file mode 100644 index 0000000000..7115bbb0a6 --- /dev/null +++ b/libcpu/arm/zynqmp-r5/xil_mpu.c @@ -0,0 +1,637 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. All rights reserved. +* Copyright (C) 2021 WangHuachen. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +* +* +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_mpu.c +* +* This file provides APIs for enabling/disabling MPU and setting the memory +* attributes for sections, in the MPU translation table. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 5.00  pkp  02/10/14 Initial version
+* 6.2   mus  01/27/17 Updated to support IAR compiler
+* 6.4   asa  08/16/17 Added many APIs for MPU access to make MPU usage
+*                       user-friendly. The APIs added are: Xil_UpdateMPUConfig,
+*                       Xil_GetMPUConfig, Xil_GetNumOfFreeRegions,
+*                       Xil_GetNextMPURegion, Xil_DisableMPURegionByRegNum,
+*                       Xil_GetMPUFreeRegMask, Xil_SetMPURegionByRegNum, and
+*                       Xil_InitializeExistingMPURegConfig.
+*                       Added a new array of structure of type XMpuConfig to
+*                       represent the MPU configuration table.
+* 6.8  aru  07/02/18 Returned the pointer instead of address
+*            of that pointer in Xil_MemMap().
+* 
+* +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_cache.h" +#include "xpseudo_asm_gcc.h" +#include "xil_types.h" +#include "xil_mpu.h" +// #include "xdebug.h" +#include "xreg_cortexr5.h" +#include "xstatus.h" + +#include +#define DBG_TAG "xil_mpu" +#define DBG_LVL DBG_INFO +#include + +extern void Xil_DCacheFlush(void); +extern void Xil_ICacheInvalidate(void); +extern void Xil_DCacheDisable(void); +extern void Xil_ICacheDisable(void); +extern void Xil_DCacheEnable(void); +extern void Xil_ICacheEnable(void); + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ +#define MPU_REGION_SIZE_MIN 0x20 +/************************** Variable Definitions *****************************/ + +static const struct { + u64 size; + unsigned int encoding; +}region_size[] = { + { 0x20, REGION_32B }, + { 0x40, REGION_64B }, + { 0x80, REGION_128B }, + { 0x100, REGION_256B }, + { 0x200, REGION_512B }, + { 0x400, REGION_1K }, + { 0x800, REGION_2K }, + { 0x1000, REGION_4K }, + { 0x2000, REGION_8K }, + { 0x4000, REGION_16K }, + { 0x8000, REGION_32K }, + { 0x10000, REGION_64K }, + { 0x20000, REGION_128K }, + { 0x40000, REGION_256K }, + { 0x80000, REGION_512K }, + { 0x100000, REGION_1M }, + { 0x200000, REGION_2M }, + { 0x400000, REGION_4M }, + { 0x800000, REGION_8M }, + { 0x1000000, REGION_16M }, + { 0x2000000, REGION_32M }, + { 0x4000000, REGION_64M }, + { 0x8000000, REGION_128M }, + { 0x10000000, REGION_256M }, + { 0x20000000, REGION_512M }, + { 0x40000000, REGION_1G }, + { 0x80000000, REGION_2G }, + { 0x100000000, REGION_4G }, +}; + +XMpu_Config Mpu_Config; + +/************************** Function Prototypes ******************************/ +void Xil_InitializeExistingMPURegConfig(void); +/*****************************************************************************/ +/** +* @brief This function sets the memory attributes for a section covering +* 1MB, of memory in the translation table. +* +* @param Addr: 32-bit address for which memory attributes need to be set. +* @param attrib: Attribute for the given memory region. +* @return None. +* +* +******************************************************************************/ +void Xil_SetTlbAttributes(INTPTR addr, u32 attrib) +{ + INTPTR Localaddr = addr; + Localaddr &= (~(0xFFFFFU)); + /* Setting the MPU region with given attribute with 1MB size */ + Xil_SetMPURegion(Localaddr, 0x100000, attrib); +} + +/*****************************************************************************/ +/** +* @brief Set the memory attributes for a section of memory in the +* translation table. +* +* @param Addr: 32-bit address for which memory attributes need to be set.. +* @param size: size is the size of the region. +* @param attrib: Attribute for the given memory region. +* @return None. +* +* +******************************************************************************/ +u32 Xil_SetMPURegion(INTPTR addr, u64 size, u32 attrib) +{ + u32 Regionsize = 0; + INTPTR Localaddr = addr; + u32 NextAvailableMemRegion; + unsigned int i; + + NextAvailableMemRegion = Xil_GetNextMPURegion(); + if (NextAvailableMemRegion == 0xFF) { + LOG_E("No regions available\r\n"); + return XST_FAILURE; + } + + Xil_DCacheFlush(); + Xil_ICacheInvalidate(); + + mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,NextAvailableMemRegion); + isb(); + + /* Lookup the size. */ + for (i = 0; i < sizeof region_size / sizeof region_size[0]; i++) { + if (size <= region_size[i].size) { + Regionsize = region_size[i].encoding; + break; + } + } + + Localaddr &= ~(region_size[i].size - 1); + + Regionsize <<= 1; + Regionsize |= REGION_EN; + dsb(); + mtcp(XREG_CP15_MPU_REG_BASEADDR, Localaddr); /* Set base address of a region */ + mtcp(XREG_CP15_MPU_REG_ACCESS_CTRL, attrib); /* Set the control attribute */ + mtcp(XREG_CP15_MPU_REG_SIZE_EN, Regionsize); /* set the region size and enable it*/ + dsb(); + isb(); + Xil_UpdateMPUConfig(NextAvailableMemRegion, Localaddr, Regionsize, attrib); + return XST_SUCCESS; +} +/*****************************************************************************/ +/** +* @brief Enable MPU for Cortex R5 processor. This function invalidates I +* cache and flush the D Caches, and then enables the MPU. +* +* +* @param None. +* @return None. +* +******************************************************************************/ +void Xil_EnableMPU(void) +{ + u32 CtrlReg, Reg; + s32 DCacheStatus=0, ICacheStatus=0; + /* enable caches only if they are disabled */ +#if defined (__GNUC__) + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL,CtrlReg); +#endif + if ((CtrlReg & XREG_CP15_CONTROL_C_BIT) != 0x00000000U) { + DCacheStatus=1; + } + if ((CtrlReg & XREG_CP15_CONTROL_I_BIT) != 0x00000000U) { + ICacheStatus=1; + } + + if(DCacheStatus != 0) { + Xil_DCacheDisable(); + } + if(ICacheStatus != 0){ + Xil_ICacheDisable(); + } +#if defined (__GNUC__) + Reg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL,Reg); +#endif + Reg |= 0x00000001U; + dsb(); + mtcp(XREG_CP15_SYS_CONTROL, Reg); + isb(); + /* enable caches only if they are disabled in routine*/ + if(DCacheStatus != 0) { + Xil_DCacheEnable(); + } + if(ICacheStatus != 0) { + Xil_ICacheEnable(); + } +} + +/*****************************************************************************/ +/** +* @brief Disable MPU for Cortex R5 processors. This function invalidates I +* cache and flush the D Caches, and then disabes the MPU. +* +* @param None. +* +* @return None. +* +******************************************************************************/ +void Xil_DisableMPU(void) +{ + u32 CtrlReg, Reg; + s32 DCacheStatus=0, ICacheStatus=0; + /* enable caches only if they are disabled */ + +#if defined (__GNUC__) + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL,CtrlReg); +#endif + if ((CtrlReg & XREG_CP15_CONTROL_C_BIT) != 0x00000000U) { + DCacheStatus=1; + } + if ((CtrlReg & XREG_CP15_CONTROL_I_BIT) != 0x00000000U) { + ICacheStatus=1; + } + + if(DCacheStatus != 0) { + Xil_DCacheDisable(); + } + if(ICacheStatus != 0){ + Xil_ICacheDisable(); + } + + mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0); +#if defined (__GNUC__) + Reg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL,Reg); +#endif + Reg &= ~(0x00000001U); + dsb(); + mtcp(XREG_CP15_SYS_CONTROL, Reg); + isb(); + /* enable caches only if they are disabled in routine*/ + if(DCacheStatus != 0) { + Xil_DCacheEnable(); + } + if(ICacheStatus != 0) { + Xil_ICacheEnable(); + } +} + +/*****************************************************************************/ +/** +* @brief Update the MPU configuration for the requested region number in +* the global MPU configuration table. +* +* @param reg_num: The requested region number to be updated information for. +* @param address: 32 bit address for start of the region. +* @param size: Requested size of the region. +* @param attrib: Attribute for the corresponding region. +* @return XST_FAILURE: When the requested region number if 16 or more. +* XST_SUCCESS: When the MPU configuration table is updated. +* +* +******************************************************************************/ +u32 Xil_UpdateMPUConfig(u32 reg_num, INTPTR address, u32 size, u32 attrib) +{ + u32 ReturnVal = XST_SUCCESS; + u32 Tempsize = size; + u32 Index; + + if (reg_num >= MAX_POSSIBLE_MPU_REGS) { + LOG_E("Invalid region number\r\n"); + ReturnVal = XST_FAILURE; + goto exit; + } + + if (size & REGION_EN) { + Mpu_Config[reg_num].RegionStatus = MPU_REG_ENABLED; + Mpu_Config[reg_num].BaseAddress = address; + Tempsize &= (~REGION_EN); + Tempsize >>= 1; + /* Lookup the size. */ + for (Index = 0; Index < + sizeof region_size / sizeof region_size[0]; Index++) { + if (Tempsize <= region_size[Index].encoding) { + Mpu_Config[reg_num].Size = region_size[Index].size; + break; + } + } + Mpu_Config[reg_num].Attribute = attrib; + } else { + Mpu_Config[reg_num].RegionStatus = 0U; + Mpu_Config[reg_num].BaseAddress = 0U; + Mpu_Config[reg_num].Size = 0U; + Mpu_Config[reg_num].Attribute = 0U; + } + +exit: + return ReturnVal; +} + +/*****************************************************************************/ +/** +* @brief The MPU configuration table is passed to the caller. +* +* @param mpuconfig: This is of type XMpu_Config which is an array of +* 16 entries of type structure representing the MPU config table +* @return none +* +* +******************************************************************************/ +void Xil_GetMPUConfig (XMpu_Config mpuconfig) { + u32 Index = 0U; + + while (Index < MAX_POSSIBLE_MPU_REGS) { + mpuconfig[Index].RegionStatus = Mpu_Config[Index].RegionStatus; + mpuconfig[Index].BaseAddress = Mpu_Config[Index].BaseAddress; + mpuconfig[Index].Attribute = Mpu_Config[Index].Attribute; + mpuconfig[Index].Size = Mpu_Config[Index].Size; + Index++; + } +} + +/*****************************************************************************/ +/** +* @brief Returns the total number of free MPU regions available. +* +* @param none +* @return Number of free regions available to users +* +* +******************************************************************************/ +u32 Xil_GetNumOfFreeRegions (void) { + u32 Index = 0U; + int NumofFreeRegs = 0U; + + while (Index < MAX_POSSIBLE_MPU_REGS) { + if (MPU_REG_DISABLED == Mpu_Config[Index].RegionStatus) { + NumofFreeRegs++; + } + Index++; + } + return NumofFreeRegs; +} + +/*****************************************************************************/ +/** +* @brief Returns the total number of free MPU regions available in the form +* of a mask. A bit of 1 in the returned 16 bit value represents the +* corresponding region number to be available. +* For example, if this function returns 0xC0000, this would mean, the +* regions 14 and 15 are available to users. +* +* @param none +* @return The free region mask as a 16 bit value +* +* +******************************************************************************/ +u16 Xil_GetMPUFreeRegMask (void) { + u32 Index = 0U; + u16 FreeRegMask = 0U; + + while (Index < MAX_POSSIBLE_MPU_REGS) { + if (MPU_REG_DISABLED == Mpu_Config[Index].RegionStatus) { + FreeRegMask |= (1U << Index); + } + Index++; + } + return FreeRegMask; +} + +/*****************************************************************************/ +/** +* @brief Disables the corresponding region number as passed by the user. +* +* @param reg_num: The region number to be disabled +* @return XST_SUCCESS: If the region could be disabled successfully +* XST_FAILURE: If the requested region number is 16 or more. +* +* +******************************************************************************/ +u32 Xil_DisableMPURegionByRegNum (u32 reg_num) { + u32 Temp = 0U; + u32 ReturnVal = XST_FAILURE; + + if (reg_num >= 16U) { + LOG_E("Invalid region number\r\n"); + goto exit1; + } + Xil_DCacheFlush(); + Xil_ICacheInvalidate(); + + mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,reg_num); +#if defined (__GNUC__) + Temp = mfcp(XREG_CP15_MPU_REG_SIZE_EN); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_MPU_REG_SIZE_EN,Temp); +#endif + Temp &= (~REGION_EN); + dsb(); + mtcp(XREG_CP15_MPU_REG_SIZE_EN,Temp); + dsb(); + isb(); + Xil_UpdateMPUConfig(reg_num, 0U, 0U, 0U); + ReturnVal = XST_SUCCESS; + +exit1: + return ReturnVal; +} + +/*****************************************************************************/ +/** +* @brief Enables the corresponding region number as passed by the user. +* +* @param reg_num: The region number to be enabled +* @param address: 32 bit address for start of the region. +* @param size: Requested size of the region. +* @param attrib: Attribute for the corresponding region. +* @return XST_SUCCESS: If the region could be created successfully +* XST_FAILURE: If the requested region number is 16 or more. +* +* +******************************************************************************/ +u32 Xil_SetMPURegionByRegNum (u32 reg_num, INTPTR addr, u64 size, u32 attrib) +{ + u32 ReturnVal = XST_SUCCESS; + INTPTR Localaddr = addr; + u32 Regionsize = 0; + u32 Index; + + if (reg_num >= 16U) { + LOG_E("Invalid region number\r\n"); + ReturnVal = XST_FAILURE; + goto exit2; + } + + if (Mpu_Config[reg_num].RegionStatus == MPU_REG_ENABLED) { + LOG_E("Region already enabled\r\n"); + ReturnVal = XST_FAILURE; + goto exit2; + } + + Xil_DCacheFlush(); + Xil_ICacheInvalidate(); + mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,reg_num); + isb(); + + /* Lookup the size. */ + for (Index = 0; Index < + sizeof region_size / sizeof region_size[0]; Index++) { + if (size <= region_size[Index].size) { + Regionsize = region_size[Index].encoding; + break; + } + } + + Localaddr &= ~(region_size[Index].size - 1); + Regionsize <<= 1; + Regionsize |= REGION_EN; + dsb(); + mtcp(XREG_CP15_MPU_REG_BASEADDR, Localaddr); + mtcp(XREG_CP15_MPU_REG_ACCESS_CTRL, attrib); + mtcp(XREG_CP15_MPU_REG_SIZE_EN, Regionsize); + dsb(); + isb(); + Xil_UpdateMPUConfig(reg_num, Localaddr, Regionsize, attrib); +exit2: + return ReturnVal; + +} + +/*****************************************************************************/ +/** +* @brief Initializes the MPU configuration table that are setup in the +* R5 boot code in the Init_Mpu function called before C main. +* +* @param none +* @return none +* +* +******************************************************************************/ +void Xil_InitializeExistingMPURegConfig(void) +{ + u32 Index = 0U; + u32 Index1 = 0U; + u32 MPURegSize; + INTPTR MPURegBA; + u32 MPURegAttrib; + u32 Tempsize; + + while (Index < MAX_POSSIBLE_MPU_REGS) { + mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,Index); +#if defined (__GNUC__) + MPURegSize = mfcp(XREG_CP15_MPU_REG_SIZE_EN); + MPURegBA = mfcp(XREG_CP15_MPU_REG_BASEADDR); + MPURegAttrib = mfcp(XREG_CP15_MPU_REG_ACCESS_CTRL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_MPU_REG_SIZE_EN,MPURegSize); + mfcp(XREG_CP15_MPU_REG_BASEADDR, MPURegBA); + mfcp(XREG_CP15_MPU_REG_ACCESS_CTRL, MPURegAttrib); +#endif + if (MPURegSize & REGION_EN) { + Mpu_Config[Index].RegionStatus = MPU_REG_ENABLED; + Mpu_Config[Index].BaseAddress = MPURegBA; + Mpu_Config[Index].Attribute = MPURegAttrib; + Tempsize = MPURegSize & (~REGION_EN); + Tempsize >>= 1; + for (Index1 = 0; Index1 < + (sizeof (region_size) / sizeof (region_size[0])); Index1++) { + if (Tempsize <= region_size[Index1].encoding) { + Mpu_Config[Index].Size = region_size[Index1].size; + break; + } + } + } + Index++; + } +} + +/*****************************************************************************/ +/** +* @brief Returns the next available free MPU region +* +* @param none +* @return The free MPU region available +* +* +******************************************************************************/ +u32 Xil_GetNextMPURegion(void) +{ + u32 Index = 0U; + u32 NextAvailableReg = 0xFF; + while (Index < MAX_POSSIBLE_MPU_REGS) { + if (Mpu_Config[Index].RegionStatus != MPU_REG_ENABLED) { + NextAvailableReg = Index; + break; + } + Index++; + } + return NextAvailableReg; +} + +/*****************************************************************************/ +/** +* @brief Memory mapping for Cortex r5. +* +* @param Physaddr is base physical address at which to start mapping. +* NULL in Physaddr masks possible mapping errors. +* @param size of region to be mapped. +* @param flags used to set translation table. +* +* @return Physaddr on success, NULL on error. Ambiguous if Physaddr==NULL +* +* @note: u32overflow() is defined for readability and (for __GNUC__) to +* - force the type of the check to be the same as the first argument +* - hide the otherwise unused third argument of the builtin +* - improve safety by choosing the explicit _uadd_ version. +* Consider __builtin_add_overflow_p() when available. +* Use an alternative (less optimal?) for compilers w/o the builtin. +* +******************************************************************************/ +#ifdef __GNUC__ +#define u32overflow(a, b) ({typeof(a) s; __builtin_uadd_overflow(a, b, &s); }) +#else +#define u32overflow(a, b) ((a) > ((a) + (b))) +#endif /* __GNUC__ */ +void *Xil_MemMap(UINTPTR Physaddr, size_t size, u32 flags) +{ + size_t Regionsize = MPU_REGION_SIZE_MIN; + UINTPTR Basephysaddr = 0, end = Physaddr + size; + + if (!flags) + return (void *)Physaddr; + if (u32overflow(Physaddr, size)) + return NULL; + for ( ; Regionsize != 0; Regionsize <<= 1) { + if (Regionsize >= size) { + Basephysaddr = Physaddr & ~(Regionsize - 1); + if (u32overflow(Basephysaddr, Regionsize)) + break; + if ((Basephysaddr + Regionsize) >= end) + return Xil_SetMPURegion(Basephysaddr, + Regionsize, flags) == XST_SUCCESS ? + (void *)Physaddr : NULL; + } + } + return NULL; +} diff --git a/libcpu/arm/zynqmp-r5/xil_mpu.h b/libcpu/arm/zynqmp-r5/xil_mpu.h new file mode 100644 index 0000000000..1afa6f76f7 --- /dev/null +++ b/libcpu/arm/zynqmp-r5/xil_mpu.h @@ -0,0 +1,129 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +* +* +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil_mmu.h +* +* @addtogroup r5_mpu_apis Cortex R5 Processor MPU specific APIs +* +* MPU functions provides access to MPU operations such as enable MPU, disable +* MPU and set attribute for section of memory. +* Boot code invokes Init_MPU function to configure the MPU. A total of 10 MPU +* regions are allocated with another 6 being free for users. Overview of the +* memory attributes for different MPU regions is as given below, +* +*| | Memory Range | Attributes of MPURegion | +*|-----------------------|-------------------------|-----------------------------| +*| DDR | 0x00000000 - 0x7FFFFFFF | Normal write-back Cacheable | +*| PL | 0x80000000 - 0xBFFFFFFF | Strongly Ordered | +*| QSPI | 0xC0000000 - 0xDFFFFFFF | Device Memory | +*| PCIe | 0xE0000000 - 0xEFFFFFFF | Device Memory | +*| STM_CORESIGHT | 0xF8000000 - 0xF8FFFFFF | Device Memory | +*| RPU_R5_GIC | 0xF9000000 - 0xF90FFFFF | Device memory | +*| FPS | 0xFD000000 - 0xFDFFFFFF | Device Memory | +*| LPS | 0xFE000000 - 0xFFFFFFFF | Device Memory | +*| OCM | 0xFFFC0000 - 0xFFFFFFFF | Normal write-back Cacheable | +* +* +* @note +* For a system where DDR is less than 2GB, region after DDR and before PL is +* marked as undefined in translation table. Memory range 0xFE000000-0xFEFFFFFF is +* allocated for upper LPS slaves, where as memory region 0xFF000000-0xFFFFFFFF is +* allocated for lower LPS slaves. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 5.00  pkp  02/10/14 Initial version
+* 6.4   asa  08/16/17 Added many APIs for MPU access to make MPU usage
+*                       user-friendly. The APIs added are: Xil_UpdateMPUConfig,
+*                       Xil_GetMPUConfig, Xil_GetNumOfFreeRegions,
+*                       Xil_GetNextMPURegion, Xil_DisableMPURegionByRegNum,
+*                       Xil_GetMPUFreeRegMask, Xil_SetMPURegionByRegNum, and
+*                       Xil_InitializeExistingMPURegConfig.
+*                       Added a new array of structure of type XMpuConfig to
+*                       represent the MPU configuration table.
+* 
+* + +* +* +******************************************************************************/ + +#ifndef XIL_MPU_H +#define XIL_MPU_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +#include "xil_types.h" +/***************************** Include Files *********************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +#define MPU_REG_DISABLED 0U +#define MPU_REG_ENABLED 1U +#define MAX_POSSIBLE_MPU_REGS 16U +/**************************** Type Definitions *******************************/ +struct XMpuConfig{ + u32 RegionStatus; /* Enabled or disabled */ + INTPTR BaseAddress;/* MPU region base address */ + u64 Size; /* MPU region size address */ + u32 Attribute; /* MPU region size attribute */ +}; + +typedef struct XMpuConfig XMpu_Config[MAX_POSSIBLE_MPU_REGS]; + +extern XMpu_Config Mpu_Config; +/************************** Constant Definitions *****************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib); +void Xil_EnableMPU(void); +void Xil_DisableMPU(void); +u32 Xil_SetMPURegion(INTPTR addr, u64 size, u32 attrib); +u32 Xil_UpdateMPUConfig(u32 reg_num, INTPTR address, u32 size, u32 attrib); +void Xil_GetMPUConfig (XMpu_Config mpuconfig); +u32 Xil_GetNumOfFreeRegions (void); +u32 Xil_GetNextMPURegion(void); +u32 Xil_DisableMPURegionByRegNum (u32 reg_num); +u16 Xil_GetMPUFreeRegMask (void); +u32 Xil_SetMPURegionByRegNum (u32 reg_num, INTPTR addr, u64 size, u32 attrib); +void* Xil_MemMap(UINTPTR Physaddr, size_t size, u32 flags); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_MPU_H */ +/** +* @} End of "addtogroup r5_mpu_apis". +*/ From 4ae3a3a7f06942fd07c8d299339893a4bb8eed07 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Thu, 13 May 2021 18:47:12 +0800 Subject: [PATCH 062/255] Update NK-N9H30 description. --- bsp/nuvoton/README.md | 6 +++--- bsp/nuvoton/nk-n9h30/README.md | 19 ++++++++----------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/bsp/nuvoton/README.md b/bsp/nuvoton/README.md index 1bd95a9edc..ec049a5546 100644 --- a/bsp/nuvoton/README.md +++ b/bsp/nuvoton/README.md @@ -1,11 +1,11 @@ -Nuvoton BSP descriptions +# Nuvoton BSP Description Current supported BSP shown in below table: | **BSP Folder** | **Board Name** | -|:------------------------- |:-------------------------- | +| ------------------------- | -------------------------- | | [numaker-iot-m487](numaker-iot-m487) | Nuvoton NuMaker-IoT-M487 | | [numaker-pfm-m487](numaker-pfm-m487) | Nuvoton NuMaker-PFM-M487 | | [nk-980iot](nk-980iot) | Nuvoton NK-980IOT | | [numaker-m2354](numaker-m2354) | Nuvoton NuMaker-M2354 | | [nk-rtu980](nk-rtu980) | Nuvoton NK-RTU980 | -| [nk-n9h30](nk-n9h30) | Nuvoton NK-N9H30 | \ No newline at end of file +| [nk-n9h30](nk-n9h30) | Nuvoton NK-N9H30 | diff --git a/bsp/nuvoton/nk-n9h30/README.md b/bsp/nuvoton/nk-n9h30/README.md index 5dc4a7aec6..b4225cb68d 100644 --- a/bsp/nuvoton/nk-n9h30/README.md +++ b/bsp/nuvoton/nk-n9h30/README.md @@ -4,11 +4,10 @@ Nuvoton offers the emWin platform which is embedded with Nuvoton N9H MPU, it pro [![NK-N9H30](https://i.imgur.com/B04MCCf.png "NK-N9H30")](https://i.imgur.com/B04MCCf.png "NK-N9H30") -### 1.1 MCU specification - +### 1.1 MPU specification | | Features | | -- | -- | -| Part NO. | N9H30F61IEC (LQFP216 pin MCP package with DDR (64 MB) | +| Part NO. | N9H30F61IEC(or N9H30F63IEC) (LQFP216 pin MCP package with DDR (64 MB) | | CPU ARCH. | 32-bit ARM926EJ-S | | Operation frequency | 300 MHz | | Embedded SDRAM size | Built-in 64MB | @@ -19,8 +18,9 @@ Nuvoton offers the emWin platform which is embedded with Nuvoton N9H MPU, it pro | Extern storage | 32MB SPI-NOR Flash | | SD card slot | SD | -### 1.2 Interface +**Notice: Please remember to select corresponding Part NO in NuWriter.** +### 1.2 Interface | Interface | | -- | | Two RJ45 Ethernet | @@ -30,12 +30,13 @@ Nuvoton offers the emWin platform which is embedded with Nuvoton N9H MPU, it pro | An ICE connector | ### 1.3 On-board devices - | Device | Description | Driver supporting status | | -- | -- | -- | |Ethernet PHY | IP101GR | Supported | -|Keypad | | Supported | +|Keypad | K[1, 6] | Supported | |LEDs | | Supported | +|TFT-LCD panel | 7" inch 24b RGB | Supported | +|Touch panel | 7" inch resistive | Supported | |Audio Codec | NAU8822, Supports MIC and earphone | Supported | |USB Device | VCOM + MStorage | Supported | |USB Host | MStorage | Supported | @@ -43,7 +44,6 @@ Nuvoton offers the emWin platform which is embedded with Nuvoton N9H MPU, it pro ## 2. Supported compiler Support GCC, MDK4 and MDK5 IDE/compilers. More information of these compiler version as following: - | IDE/Compiler | Tested version | | ---------- | ---------------------------- | | MDK5 | 5.26.2 | @@ -88,7 +88,7 @@ You can use Tera Term terminate emulator (or other software) to type commands of ## 5. Demo -* Run NUemWin2RTT on NK-N9H30 +* Run NUemWin on NK-N9H30 ```bash \ | / @@ -106,7 +106,6 @@ msh /> nuemwin_stop [![NUemWin2RTT on NK-N9H30](https://img.youtube.com/vi/TAfkOKpySQk/0.jpg)](https://www.youtube.com/watch?v=TAfkOKpySQk) - * Run LittlevGL2RTT on NK-N9H30 **Please check out modified version with GE2D accelerating from [HERE](https://github.com/wosayttn/LittlevGL2RTT).** @@ -123,8 +122,6 @@ msh /> lv_demo ``` - - [![LvGL2RTT on NK-N9H30](https://img.youtube.com/vi/djz0jAKrfjs/0.jpg)](https://www.youtube.com/watch?v=djz0jAKrfjs) ## 6. Purchase From 74064e8cc731ca0dc17c26284e8203988d38a858 Mon Sep 17 00:00:00 2001 From: Meco Jianting Man <920369182@qq.com> Date: Fri, 14 May 2021 10:03:38 +0800 Subject: [PATCH 063/255] =?UTF-8?q?[bug][bsp][stm32f407-explorer]=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8Dsdcard=E9=A9=B1=E5=8A=A8=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=B7=A5=E7=A8=8B=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/stm32f407-atk-explorer/board/SConscript | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsp/stm32/stm32f407-atk-explorer/board/SConscript b/bsp/stm32/stm32f407-atk-explorer/board/SConscript index c366e1d7a0..e97905718f 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/SConscript +++ b/bsp/stm32/stm32f407-atk-explorer/board/SConscript @@ -19,7 +19,7 @@ if GetDepend(['BSP_USING_SPI_FLASH']): src += Glob('ports/spi_flash_init.c') if GetDepend(['BSP_USING_SDCARD']): - src += Glob('ports/sdcard_port.c') + src += Glob('ports/drv_sdcard.c') if GetDepend(['BSP_USING_SRAM']): src += Glob('ports/drv_sram.c') @@ -40,4 +40,4 @@ elif rtconfig.CROSS_TOOL == 'iar': CPPDEFINES = ['STM32F407xx'] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) -Return('group') \ No newline at end of file +Return('group') From 71a5385a97172891403923f6eed3211f8e93c8a4 Mon Sep 17 00:00:00 2001 From: Meco Jianting Man <920369182@qq.com> Date: Fri, 14 May 2021 10:06:27 +0800 Subject: [PATCH 064/255] =?UTF-8?q?[sconscript]=20application=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=A4=B9=E5=A2=9E=E5=8A=A0=E5=B7=A5=E7=A8=8B=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E8=B7=AF=E5=BE=84=E5=90=91=E4=B8=8B=E6=89=AB=E6=8F=8F?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户在加入自己的工程文件夹时,只要该文件内含有Sconscript,就可以被自动探测到,无需手动修改application下的sconscript手动添加。 --- bsp/stm32/stm32f407-atk-explorer/applications/SConscript | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bsp/stm32/stm32f407-atk-explorer/applications/SConscript b/bsp/stm32/stm32f407-atk-explorer/applications/SConscript index 6f66f7ab73..d229539fc7 100644 --- a/bsp/stm32/stm32f407-atk-explorer/applications/SConscript +++ b/bsp/stm32/stm32f407-atk-explorer/applications/SConscript @@ -1,4 +1,5 @@ import rtconfig +import os from building import * cwd = GetCurrentDir() @@ -9,4 +10,10 @@ main.c group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) +list = os.listdir(cwd) +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + group = group + SConscript(os.path.join(d, 'SConscript')) + Return('group') From cc32e7aa4dc016494a396c6ffb163f54928f1014 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Fri, 14 May 2021 11:53:46 +0800 Subject: [PATCH 065/255] Follow coding-style and formatting. --- .../libraries/m2354/CMSIS/Include/arm_math.h | 9936 ++++++++--------- .../m2354/CMSIS/Include/cmsis_compiler.h | 425 +- .../m2354/CMSIS/Include/core_armv8mbl.h | 934 +- .../m2354/CMSIS/Include/core_armv8mml.h | 1412 +-- .../libraries/m2354/CMSIS/Include/core_cm0.h | 382 +- .../m2354/CMSIS/Include/core_cm0plus.h | 416 +- .../libraries/m2354/CMSIS/Include/core_cm3.h | 754 +- .../libraries/m2354/CMSIS/Include/core_cm33.h | 1404 +-- .../libraries/m2354/CMSIS/Include/core_cm4.h | 898 +- .../libraries/m2354/CMSIS/Include/mpu_armv7.h | 67 +- .../m2354/CMSIS/Include/tz_context.h | 36 +- .../libraries/m2354/USBHostLib/inc/config.h | 30 +- .../libraries/m2354/USBHostLib/inc/usbh_lib.h | 10 +- .../libraries/m2354/USBHostLib/src/usb_core.c | 16 +- .../m480/CMSIS/Include/arm_common_tables.h | 8 +- .../m480/CMSIS/Include/arm_const_structs.h | 62 +- .../m480/CMSIS/Include/cmsis_armcc_V6.h | 730 +- .../Device/Nuvoton/M480/Include/sys_reg.h | 6 +- .../libraries/m480/StdDriver/inc/nu_clk.h | 10 +- .../libraries/m480/StdDriver/inc/nu_trng.h | 4 +- .../libraries/m480/StdDriver/src/nu_crypto.c | 46 +- .../libraries/m480/USBHostLib/inc/config.h | 36 +- .../libraries/m480/USBHostLib/inc/usbh_lib.h | 4 +- .../libraries/m480/USBHostLib/src/ehci.c | 50 +- .../libraries/m480/USBHostLib/src/usb_core.c | 10 +- .../m480/rtt_port/drv_epwm_capture.c | 2 +- .../libraries/n9h30/Driver/Source/nu_cap.c | 2 +- .../libraries/n9h30/UsbHostLib/inc/usbh_lib.h | 2 +- .../libraries/nuc980/Driver/Include/nu_pwm.h | 2 +- .../libraries/nuc980/Driver/Include/nu_wwdt.h | 34 +- .../nuc980/Driver/Source/nu_crypto.c | 22 +- .../nuc980/UsbHostLib/inc/usbh_lib.h | 2 +- .../board/NuClockConfig/nutool_clkcfg.h | 2 +- .../board/NuClockConfig/nutool_modclkcfg.c | 8 +- .../board/NuClockConfig/nutool_modclkcfg.h | 2 +- .../board/NuPinConfig/nutool_pincfg.c | 34 +- .../board/NuPinConfig/nutool_pincfg.h | 2 +- .../board/NuPinConfig/nutool_pincfg.c | 2 +- .../board/NuPinConfig/nutool_pincfg.h | 2 +- 39 files changed, 8912 insertions(+), 8892 deletions(-) diff --git a/bsp/nuvoton/libraries/m2354/CMSIS/Include/arm_math.h b/bsp/nuvoton/libraries/m2354/CMSIS/Include/arm_math.h index 6d75401896..a489ab614d 100644 --- a/bsp/nuvoton/libraries/m2354/CMSIS/Include/arm_math.h +++ b/bsp/nuvoton/libraries/m2354/CMSIS/Include/arm_math.h @@ -81,7 +81,7 @@ * ARM_MATH_CM0 or ARM_MATH_CM0PLUS depending on the target processor in the application. * For ARMv8M cores define pre processor MACRO ARM_MATH_ARMV8MBL or ARM_MATH_ARMV8MML. * Set Pre processor MACRO __DSP_PRESENT if ARMv8M Mainline core supports DSP instructions. - * + * * * Examples * -------- @@ -299,10 +299,10 @@ #elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) #elif defined ( __GNUC__ ) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wsign-conversion" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wunused-parameter" + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" + #pragma GCC diagnostic ignored "-Wunused-parameter" #elif defined ( __ICCARM__ ) @@ -313,36 +313,36 @@ #elif defined ( __TASKING__ ) #else - #error Unknown compiler + #error Unknown compiler #endif #define __CMSIS_GENERIC /* disable NVIC and Systick functions */ #if defined(ARM_MATH_CM7) - #include "core_cm7.h" - #define ARM_MATH_DSP -#elif defined (ARM_MATH_CM4) - #include "core_cm4.h" - #define ARM_MATH_DSP -#elif defined (ARM_MATH_CM3) - #include "core_cm3.h" -#elif defined (ARM_MATH_CM0) - #include "core_cm0.h" - #define ARM_MATH_CM0_FAMILY -#elif defined (ARM_MATH_CM0PLUS) - #include "core_cm0plus.h" - #define ARM_MATH_CM0_FAMILY -#elif defined (ARM_MATH_ARMV8MBL) - #include "core_armv8mbl.h" - #define ARM_MATH_CM0_FAMILY -#elif defined (ARM_MATH_ARMV8MML) - #include "core_armv8mml.h" - #if (defined (__DSP_PRESENT) && (__DSP_PRESENT == 1)) + #include "core_cm7.h" #define ARM_MATH_DSP - #endif +#elif defined (ARM_MATH_CM4) + #include "core_cm4.h" + #define ARM_MATH_DSP +#elif defined (ARM_MATH_CM3) + #include "core_cm3.h" +#elif defined (ARM_MATH_CM0) + #include "core_cm0.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_CM0PLUS) + #include "core_cm0plus.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_ARMV8MBL) + #include "core_armv8mbl.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_ARMV8MML) + #include "core_armv8mml.h" + #if (defined (__DSP_PRESENT) && (__DSP_PRESENT == 1)) + #define ARM_MATH_DSP + #endif #else - #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS, ARM_MATH_CM0, ARM_MATH_ARMV8MBL, ARM_MATH_ARMV8MML" + #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS, ARM_MATH_CM0, ARM_MATH_ARMV8MBL, ARM_MATH_ARMV8MML" #endif #undef __CMSIS_GENERIC /* enable NVIC and Systick functions */ @@ -354,20 +354,20 @@ extern "C" #endif - /** - * @brief Macros required for reciprocal calculation in Normalized LMS - */ +/** + * @brief Macros required for reciprocal calculation in Normalized LMS + */ #define DELTA_Q31 (0x100) #define DELTA_Q15 0x5 #define INDEX_MASK 0x0000003F #ifndef PI - #define PI 3.14159265358979f +#define PI 3.14159265358979f #endif - /** - * @brief Macros required for SINE and COSINE Fast math approximations - */ +/** + * @brief Macros required for SINE and COSINE Fast math approximations + */ #define FAST_MATH_TABLE_SIZE 512 #define FAST_MATH_Q31_SHIFT (32 - 10) @@ -376,32 +376,32 @@ extern "C" #define TABLE_SPACING_Q31 0x400000 #define TABLE_SPACING_Q15 0x80 - /** - * @brief Macros required for SINE and COSINE Controller functions - */ - /* 1.31(q31) Fixed value of 2/360 */ - /* -1 to +1 is divided into 360 values so total spacing is (2/360) */ +/** + * @brief Macros required for SINE and COSINE Controller functions + */ +/* 1.31(q31) Fixed value of 2/360 */ +/* -1 to +1 is divided into 360 values so total spacing is (2/360) */ #define INPUT_SPACING 0xB60B61 - /** - * @brief Macro for Unaligned Support - */ +/** + * @brief Macro for Unaligned Support + */ #ifndef UNALIGNED_SUPPORT_DISABLE - #define ALIGN4 +#define ALIGN4 #else - #if defined (__GNUC__) - #define ALIGN4 __attribute__((aligned(4))) - #else - #define ALIGN4 __align(4) - #endif +#if defined (__GNUC__) +#define ALIGN4 __attribute__((aligned(4))) +#else +#define ALIGN4 __align(4) +#endif #endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */ - /** - * @brief Error status returned by some functions in the library. - */ +/** + * @brief Error status returned by some functions in the library. + */ - typedef enum - { +typedef enum +{ ARM_MATH_SUCCESS = 0, /**< No error */ ARM_MATH_ARGUMENT_ERROR = -1, /**< One or more arguments are incorrect */ ARM_MATH_LENGTH_ERROR = -2, /**< Length of data buffer is incorrect */ @@ -409,78 +409,78 @@ extern "C" ARM_MATH_NANINF = -4, /**< Not-a-number (NaN) or infinity is generated */ ARM_MATH_SINGULAR = -5, /**< Generated by matrix inversion if the input matrix is singular and cannot be inverted. */ ARM_MATH_TEST_FAILURE = -6 /**< Test Failed */ - } arm_status; +} arm_status; - /** - * @brief 8-bit fractional data type in 1.7 format. - */ - typedef int8_t q7_t; +/** + * @brief 8-bit fractional data type in 1.7 format. + */ +typedef int8_t q7_t; - /** - * @brief 16-bit fractional data type in 1.15 format. - */ - typedef int16_t q15_t; +/** + * @brief 16-bit fractional data type in 1.15 format. + */ +typedef int16_t q15_t; - /** - * @brief 32-bit fractional data type in 1.31 format. - */ - typedef int32_t q31_t; +/** + * @brief 32-bit fractional data type in 1.31 format. + */ +typedef int32_t q31_t; - /** - * @brief 64-bit fractional data type in 1.63 format. - */ - typedef int64_t q63_t; +/** + * @brief 64-bit fractional data type in 1.63 format. + */ +typedef int64_t q63_t; - /** - * @brief 32-bit floating-point type definition. - */ - typedef float float32_t; +/** + * @brief 32-bit floating-point type definition. + */ +typedef float float32_t; - /** - * @brief 64-bit floating-point type definition. - */ - typedef double float64_t; +/** + * @brief 64-bit floating-point type definition. + */ +typedef double float64_t; - /** - * @brief definition to read/write two 16 bit values. - */ +/** + * @brief definition to read/write two 16 bit values. + */ #if defined ( __CC_ARM ) - #define __SIMD32_TYPE int32_t __packed - #define CMSIS_UNUSED __attribute__((unused)) - #define CMSIS_INLINE __attribute__((always_inline)) +#define __SIMD32_TYPE int32_t __packed +#define CMSIS_UNUSED __attribute__((unused)) +#define CMSIS_INLINE __attribute__((always_inline)) #elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) - #define __SIMD32_TYPE int32_t - #define CMSIS_UNUSED __attribute__((unused)) - #define CMSIS_INLINE __attribute__((always_inline)) +#define __SIMD32_TYPE int32_t +#define CMSIS_UNUSED __attribute__((unused)) +#define CMSIS_INLINE __attribute__((always_inline)) #elif defined ( __GNUC__ ) - #define __SIMD32_TYPE int32_t - #define CMSIS_UNUSED __attribute__((unused)) - #define CMSIS_INLINE __attribute__((always_inline)) +#define __SIMD32_TYPE int32_t +#define CMSIS_UNUSED __attribute__((unused)) +#define CMSIS_INLINE __attribute__((always_inline)) #elif defined ( __ICCARM__ ) - #define __SIMD32_TYPE int32_t __packed - #define CMSIS_UNUSED - #define CMSIS_INLINE +#define __SIMD32_TYPE int32_t __packed +#define CMSIS_UNUSED +#define CMSIS_INLINE #elif defined ( __TI_ARM__ ) - #define __SIMD32_TYPE int32_t - #define CMSIS_UNUSED __attribute__((unused)) - #define CMSIS_INLINE +#define __SIMD32_TYPE int32_t +#define CMSIS_UNUSED __attribute__((unused)) +#define CMSIS_INLINE #elif defined ( __CSMC__ ) - #define __SIMD32_TYPE int32_t - #define CMSIS_UNUSED - #define CMSIS_INLINE +#define __SIMD32_TYPE int32_t +#define CMSIS_UNUSED +#define CMSIS_INLINE #elif defined ( __TASKING__ ) - #define __SIMD32_TYPE __unaligned int32_t - #define CMSIS_UNUSED - #define CMSIS_INLINE +#define __SIMD32_TYPE __unaligned int32_t +#define CMSIS_UNUSED +#define CMSIS_INLINE #else - #error Unknown compiler +#error Unknown compiler #endif #define __SIMD32(addr) (*(__SIMD32_TYPE **) & (addr)) @@ -490,9 +490,9 @@ extern "C" /* #if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ #if !defined (ARM_MATH_DSP) - /** - * @brief definition to pack two 16 bit values. - */ +/** + * @brief definition to pack two 16 bit values. + */ #define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \ (((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) ) #define __PKHTB(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0xFFFF0000) | \ @@ -501,9 +501,9 @@ extern "C" /* #endif // defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ #endif /* !defined (ARM_MATH_DSP) */ - /** - * @brief definition to pack four 8 bit values. - */ +/** +* @brief definition to pack four 8 bit values. +*/ #ifndef ARM_MATH_BIG_ENDIAN #define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v0) << 0) & (int32_t)0x000000FF) | \ @@ -520,57 +520,57 @@ extern "C" #endif - /** - * @brief Clips Q63 to Q31 values. - */ - CMSIS_INLINE __STATIC_INLINE q31_t clip_q63_to_q31( - q63_t x) - { - return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? - ((0x7FFFFFFF ^ ((q31_t) (x >> 63)))) : (q31_t) x; - } +/** + * @brief Clips Q63 to Q31 values. + */ +CMSIS_INLINE __STATIC_INLINE q31_t clip_q63_to_q31( + q63_t x) +{ + return ((q31_t)(x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFFFFFF ^ ((q31_t)(x >> 63)))) : (q31_t) x; +} - /** - * @brief Clips Q63 to Q15 values. - */ - CMSIS_INLINE __STATIC_INLINE q15_t clip_q63_to_q15( - q63_t x) - { - return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? - ((0x7FFF ^ ((q15_t) (x >> 63)))) : (q15_t) (x >> 15); - } +/** + * @brief Clips Q63 to Q15 values. + */ +CMSIS_INLINE __STATIC_INLINE q15_t clip_q63_to_q15( + q63_t x) +{ + return ((q31_t)(x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFF ^ ((q15_t)(x >> 63)))) : (q15_t)(x >> 15); +} - /** - * @brief Clips Q31 to Q7 values. - */ - CMSIS_INLINE __STATIC_INLINE q7_t clip_q31_to_q7( - q31_t x) - { - return ((q31_t) (x >> 24) != ((q31_t) x >> 23)) ? - ((0x7F ^ ((q7_t) (x >> 31)))) : (q7_t) x; - } +/** + * @brief Clips Q31 to Q7 values. + */ +CMSIS_INLINE __STATIC_INLINE q7_t clip_q31_to_q7( + q31_t x) +{ + return ((q31_t)(x >> 24) != ((q31_t) x >> 23)) ? + ((0x7F ^ ((q7_t)(x >> 31)))) : (q7_t) x; +} - /** - * @brief Clips Q31 to Q15 values. - */ - CMSIS_INLINE __STATIC_INLINE q15_t clip_q31_to_q15( - q31_t x) - { - return ((q31_t) (x >> 16) != ((q31_t) x >> 15)) ? - ((0x7FFF ^ ((q15_t) (x >> 31)))) : (q15_t) x; - } +/** + * @brief Clips Q31 to Q15 values. + */ +CMSIS_INLINE __STATIC_INLINE q15_t clip_q31_to_q15( + q31_t x) +{ + return ((q31_t)(x >> 16) != ((q31_t) x >> 15)) ? + ((0x7FFF ^ ((q15_t)(x >> 31)))) : (q15_t) x; +} - /** - * @brief Multiplies 32 X 64 and returns 32 bit result in 2.30 format. - */ +/** + * @brief Multiplies 32 X 64 and returns 32 bit result in 2.30 format. + */ - CMSIS_INLINE __STATIC_INLINE q63_t mult32x64( - q63_t x, - q31_t y) - { - return ((((q63_t) (x & 0x00000000FFFFFFFF) * y) >> 32) + - (((q63_t) (x >> 32) * y))); - } +CMSIS_INLINE __STATIC_INLINE q63_t mult32x64( + q63_t x, + q31_t y) +{ + return ((((q63_t)(x & 0x00000000FFFFFFFF) * y) >> 32) + + (((q63_t)(x >> 32) * y))); +} /* #if defined (ARM_MATH_CM0_FAMILY) && defined ( __CC_ARM ) @@ -579,34 +579,34 @@ extern "C" */ /* note: function can be removed when all toolchain support __CLZ for Cortex-M0 */ #if defined (ARM_MATH_CM0_FAMILY) && ((defined (__ICCARM__)) ) - CMSIS_INLINE __STATIC_INLINE uint32_t __CLZ( - q31_t data); +CMSIS_INLINE __STATIC_INLINE uint32_t __CLZ( + q31_t data); - CMSIS_INLINE __STATIC_INLINE uint32_t __CLZ( - q31_t data) - { +CMSIS_INLINE __STATIC_INLINE uint32_t __CLZ( + q31_t data) +{ uint32_t count = 0; uint32_t mask = 0x80000000; while ((data & mask) == 0) { - count += 1u; - mask = mask >> 1u; + count += 1u; + mask = mask >> 1u; } return (count); - } +} #endif - /** - * @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type. - */ +/** + * @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type. + */ - CMSIS_INLINE __STATIC_INLINE uint32_t arm_recip_q31( - q31_t in, - q31_t * dst, - q31_t * pRecipTable) - { +CMSIS_INLINE __STATIC_INLINE uint32_t arm_recip_q31( + q31_t in, + q31_t *dst, + q31_t *pRecipTable) +{ q31_t out; uint32_t tempVal; uint32_t index, i; @@ -614,11 +614,11 @@ extern "C" if (in > 0) { - signBits = ((uint32_t) (__CLZ( in) - 1)); + signBits = ((uint32_t)(__CLZ(in) - 1)); } else { - signBits = ((uint32_t) (__CLZ(-in) - 1)); + signBits = ((uint32_t)(__CLZ(-in) - 1)); } /* Convert input sample to 1.31 format */ @@ -635,11 +635,11 @@ extern "C" /* running approximation for two iterations */ for (i = 0u; i < 2u; i++) { - tempVal = (uint32_t) (((q63_t) in * out) >> 31); - tempVal = 0x7FFFFFFFu - tempVal; - /* 1.31 with exp 1 */ - /* out = (q31_t) (((q63_t) out * tempVal) >> 30); */ - out = clip_q63_to_q31(((q63_t) out * tempVal) >> 30); + tempVal = (uint32_t)(((q63_t) in * out) >> 31); + tempVal = 0x7FFFFFFFu - tempVal; + /* 1.31 with exp 1 */ + /* out = (q31_t) (((q63_t) out * tempVal) >> 30); */ + out = clip_q63_to_q31(((q63_t) out * tempVal) >> 30); } /* write output */ @@ -647,17 +647,17 @@ extern "C" /* return num of signbits of out = 1/in value */ return (signBits + 1u); - } +} - /** - * @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type. - */ - CMSIS_INLINE __STATIC_INLINE uint32_t arm_recip_q15( - q15_t in, - q15_t * dst, - q15_t * pRecipTable) - { +/** + * @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type. + */ +CMSIS_INLINE __STATIC_INLINE uint32_t arm_recip_q15( + q15_t in, + q15_t *dst, + q15_t *pRecipTable) +{ q15_t out = 0; uint32_t tempVal = 0; uint32_t index = 0, i = 0; @@ -665,11 +665,11 @@ extern "C" if (in > 0) { - signBits = ((uint32_t)(__CLZ( in) - 17)); + signBits = ((uint32_t)(__CLZ(in) - 17)); } else { - signBits = ((uint32_t)(__CLZ(-in) - 17)); + signBits = ((uint32_t)(__CLZ(-in) - 17)); } /* Convert input sample to 1.15 format */ @@ -686,11 +686,11 @@ extern "C" /* running approximation for two iterations */ for (i = 0u; i < 2u; i++) { - tempVal = (uint32_t) (((q31_t) in * out) >> 15); - tempVal = 0x7FFFu - tempVal; - /* 1.15 with exp 1 */ - out = (q15_t) (((q31_t) out * tempVal) >> 14); - /* out = clip_q31_to_q15(((q31_t) out * tempVal) >> 14); */ + tempVal = (uint32_t)(((q31_t) in * out) >> 15); + tempVal = 0x7FFFu - tempVal; + /* 1.15 with exp 1 */ + out = (q15_t)(((q31_t) out * tempVal) >> 14); + /* out = clip_q31_to_q15(((q31_t) out * tempVal) >> 14); */ } /* write output */ @@ -698,1125 +698,1125 @@ extern "C" /* return num of signbits of out = 1/in value */ return (signBits + 1); - } +} - /* - * @brief C custom defined intrinisic function for only M0 processors - */ +/* + * @brief C custom defined intrinisic function for only M0 processors + */ #if defined(ARM_MATH_CM0_FAMILY) - CMSIS_INLINE __STATIC_INLINE q31_t __SSAT( - q31_t x, - uint32_t y) - { +CMSIS_INLINE __STATIC_INLINE q31_t __SSAT( + q31_t x, + uint32_t y) +{ int32_t posMax, negMin; uint32_t i; posMax = 1; for (i = 0; i < (y - 1); i++) { - posMax = posMax * 2; + posMax = posMax * 2; } if (x > 0) { - posMax = (posMax - 1); + posMax = (posMax - 1); - if (x > posMax) - { - x = posMax; - } + if (x > posMax) + { + x = posMax; + } } else { - negMin = -posMax; + negMin = -posMax; - if (x < negMin) - { - x = negMin; - } + if (x < negMin) + { + x = negMin; + } } return (x); - } +} #endif /* end of ARM_MATH_CM0_FAMILY */ - /* - * @brief C custom defined intrinsic function for M3 and M0 processors - */ +/* + * @brief C custom defined intrinsic function for M3 and M0 processors + */ /* #if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ #if !defined (ARM_MATH_DSP) - /* - * @brief C custom defined QADD8 for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __QADD8( - uint32_t x, - uint32_t y) - { +/* + * @brief C custom defined QADD8 for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __QADD8( + uint32_t x, + uint32_t y) +{ q31_t r, s, t, u; r = __SSAT(((((q31_t)x << 24) >> 24) + (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; s = __SSAT(((((q31_t)x << 16) >> 24) + (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; t = __SSAT(((((q31_t)x << 8) >> 24) + (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; - u = __SSAT(((((q31_t)x ) >> 24) + (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x) >> 24) + (((q31_t)y) >> 24)), 8) & (int32_t)0x000000FF; - return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); - } + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} - /* - * @brief C custom defined QSUB8 for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __QSUB8( - uint32_t x, - uint32_t y) - { +/* + * @brief C custom defined QSUB8 for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __QSUB8( + uint32_t x, + uint32_t y) +{ q31_t r, s, t, u; r = __SSAT(((((q31_t)x << 24) >> 24) - (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; s = __SSAT(((((q31_t)x << 16) >> 24) - (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; t = __SSAT(((((q31_t)x << 8) >> 24) - (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; - u = __SSAT(((((q31_t)x ) >> 24) - (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x) >> 24) - (((q31_t)y) >> 24)), 8) & (int32_t)0x000000FF; - return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); - } + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} - /* - * @brief C custom defined QADD16 for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __QADD16( - uint32_t x, - uint32_t y) - { -/* q31_t r, s; without initialisation 'arm_offset_q15 test' fails but 'intrinsic' tests pass! for armCC */ +/* + * @brief C custom defined QADD16 for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __QADD16( + uint32_t x, + uint32_t y) +{ + /* q31_t r, s; without initialisation 'arm_offset_q15 test' fails but 'intrinsic' tests pass! for armCC */ q31_t r = 0, s = 0; r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; - s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x) >> 16) + (((q31_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; - return ((uint32_t)((s << 16) | (r ))); - } + return ((uint32_t)((s << 16) | (r))); +} - /* - * @brief C custom defined SHADD16 for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SHADD16( - uint32_t x, - uint32_t y) - { +/* + * @brief C custom defined SHADD16 for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SHADD16( + uint32_t x, + uint32_t y) +{ q31_t r, s; r = (((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; - s = (((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x) >> 16) + (((q31_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; - return ((uint32_t)((s << 16) | (r ))); - } + return ((uint32_t)((s << 16) | (r))); +} - /* - * @brief C custom defined QSUB16 for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __QSUB16( - uint32_t x, - uint32_t y) - { +/* + * @brief C custom defined QSUB16 for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __QSUB16( + uint32_t x, + uint32_t y) +{ q31_t r, s; r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; - s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x) >> 16) - (((q31_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; - return ((uint32_t)((s << 16) | (r ))); - } + return ((uint32_t)((s << 16) | (r))); +} - /* - * @brief C custom defined SHSUB16 for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SHSUB16( - uint32_t x, - uint32_t y) - { +/* + * @brief C custom defined SHSUB16 for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SHSUB16( + uint32_t x, + uint32_t y) +{ q31_t r, s; r = (((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; - s = (((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x) >> 16) - (((q31_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; - return ((uint32_t)((s << 16) | (r ))); - } + return ((uint32_t)((s << 16) | (r))); +} - /* - * @brief C custom defined QASX for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __QASX( - uint32_t x, - uint32_t y) - { +/* + * @brief C custom defined QASX for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __QASX( + uint32_t x, + uint32_t y) +{ q31_t r, s; - r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; - s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; - return ((uint32_t)((s << 16) | (r ))); - } + return ((uint32_t)((s << 16) | (r))); +} - /* - * @brief C custom defined SHASX for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SHASX( - uint32_t x, - uint32_t y) - { +/* + * @brief C custom defined SHASX for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SHASX( + uint32_t x, + uint32_t y) +{ q31_t r, s; - r = (((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; - s = (((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; - return ((uint32_t)((s << 16) | (r ))); - } + return ((uint32_t)((s << 16) | (r))); +} - /* - * @brief C custom defined QSAX for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __QSAX( - uint32_t x, - uint32_t y) - { +/* + * @brief C custom defined QSAX for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __QSAX( + uint32_t x, + uint32_t y) +{ q31_t r, s; - r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; - s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; - return ((uint32_t)((s << 16) | (r ))); - } + return ((uint32_t)((s << 16) | (r))); +} - /* - * @brief C custom defined SHSAX for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SHSAX( - uint32_t x, - uint32_t y) - { +/* + * @brief C custom defined SHSAX for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SHSAX( + uint32_t x, + uint32_t y) +{ q31_t r, s; - r = (((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; - s = (((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; - return ((uint32_t)((s << 16) | (r ))); - } + return ((uint32_t)((s << 16) | (r))); +} - /* - * @brief C custom defined SMUSDX for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SMUSDX( - uint32_t x, - uint32_t y) - { - return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - - ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); - } +/* + * @brief C custom defined SMUSDX for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SMUSDX( + uint32_t x, + uint32_t y) +{ + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y) >> 16)) - + ((((q31_t)x) >> 16) * (((q31_t)y << 16) >> 16)))); +} - /* - * @brief C custom defined SMUADX for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SMUADX( - uint32_t x, - uint32_t y) - { - return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + - ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); - } +/* + * @brief C custom defined SMUADX for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SMUADX( + uint32_t x, + uint32_t y) +{ + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y) >> 16)) + + ((((q31_t)x) >> 16) * (((q31_t)y << 16) >> 16)))); +} - /* - * @brief C custom defined QADD for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE int32_t __QADD( - int32_t x, - int32_t y) - { +/* + * @brief C custom defined QADD for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE int32_t __QADD( + int32_t x, + int32_t y) +{ return ((int32_t)(clip_q63_to_q31((q63_t)x + (q31_t)y))); - } +} - /* - * @brief C custom defined QSUB for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE int32_t __QSUB( - int32_t x, - int32_t y) - { +/* + * @brief C custom defined QSUB for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE int32_t __QSUB( + int32_t x, + int32_t y) +{ return ((int32_t)(clip_q63_to_q31((q63_t)x - (q31_t)y))); - } +} - /* - * @brief C custom defined SMLAD for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SMLAD( - uint32_t x, - uint32_t y, - uint32_t sum) - { +/* + * @brief C custom defined SMLAD for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SMLAD( + uint32_t x, + uint32_t y, + uint32_t sum) +{ return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + - ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + - ( ((q31_t)sum ) ) )); - } + ((((q31_t)x) >> 16) * (((q31_t)y) >> 16)) + + (((q31_t)sum)))); +} - /* - * @brief C custom defined SMLADX for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SMLADX( - uint32_t x, - uint32_t y, - uint32_t sum) - { - return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + - ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + - ( ((q31_t)sum ) ) )); - } +/* + * @brief C custom defined SMLADX for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SMLADX( + uint32_t x, + uint32_t y, + uint32_t sum) +{ + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y) >> 16)) + + ((((q31_t)x) >> 16) * (((q31_t)y << 16) >> 16)) + + (((q31_t)sum)))); +} - /* - * @brief C custom defined SMLSDX for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SMLSDX( - uint32_t x, - uint32_t y, - uint32_t sum) - { - return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - - ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + - ( ((q31_t)sum ) ) )); - } +/* + * @brief C custom defined SMLSDX for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SMLSDX( + uint32_t x, + uint32_t y, + uint32_t sum) +{ + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y) >> 16)) - + ((((q31_t)x) >> 16) * (((q31_t)y << 16) >> 16)) + + (((q31_t)sum)))); +} - /* - * @brief C custom defined SMLALD for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint64_t __SMLALD( - uint32_t x, - uint32_t y, - uint64_t sum) - { -/* return (sum + ((q15_t) (x >> 16) * (q15_t) (y >> 16)) + ((q15_t) x * (q15_t) y)); */ +/* + * @brief C custom defined SMLALD for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint64_t __SMLALD( + uint32_t x, + uint32_t y, + uint64_t sum) +{ + /* return (sum + ((q15_t) (x >> 16) * (q15_t) (y >> 16)) + ((q15_t) x * (q15_t) y)); */ return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + - ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + - ( ((q63_t)sum ) ) )); - } + ((((q31_t)x) >> 16) * (((q31_t)y) >> 16)) + + (((q63_t)sum)))); +} - /* - * @brief C custom defined SMLALDX for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint64_t __SMLALDX( - uint32_t x, - uint32_t y, - uint64_t sum) - { -/* return (sum + ((q15_t) (x >> 16) * (q15_t) y)) + ((q15_t) x * (q15_t) (y >> 16)); */ - return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + - ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + - ( ((q63_t)sum ) ) )); - } +/* + * @brief C custom defined SMLALDX for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint64_t __SMLALDX( + uint32_t x, + uint32_t y, + uint64_t sum) +{ + /* return (sum + ((q15_t) (x >> 16) * (q15_t) y)) + ((q15_t) x * (q15_t) (y >> 16)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y) >> 16)) + + ((((q31_t)x) >> 16) * (((q31_t)y << 16) >> 16)) + + (((q63_t)sum)))); +} - /* - * @brief C custom defined SMUAD for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SMUAD( - uint32_t x, - uint32_t y) - { +/* + * @brief C custom defined SMUAD for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SMUAD( + uint32_t x, + uint32_t y) +{ return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + - ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); - } + ((((q31_t)x) >> 16) * (((q31_t)y) >> 16)))); +} - /* - * @brief C custom defined SMUSD for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SMUSD( - uint32_t x, - uint32_t y) - { +/* + * @brief C custom defined SMUSD for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SMUSD( + uint32_t x, + uint32_t y) +{ return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) - - ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); - } + ((((q31_t)x) >> 16) * (((q31_t)y) >> 16)))); +} - /* - * @brief C custom defined SXTB16 for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __SXTB16( - uint32_t x) - { +/* + * @brief C custom defined SXTB16 for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __SXTB16( + uint32_t x) +{ return ((uint32_t)(((((q31_t)x << 24) >> 24) & (q31_t)0x0000FFFF) | - ((((q31_t)x << 8) >> 8) & (q31_t)0xFFFF0000) )); - } + ((((q31_t)x << 8) >> 8) & (q31_t)0xFFFF0000))); +} - /* - * @brief C custom defined SMMLA for M3 and M0 processors - */ - CMSIS_INLINE __STATIC_INLINE int32_t __SMMLA( - int32_t x, - int32_t y, - int32_t sum) - { - return (sum + (int32_t) (((int64_t) x * y) >> 32)); - } +/* + * @brief C custom defined SMMLA for M3 and M0 processors + */ +CMSIS_INLINE __STATIC_INLINE int32_t __SMMLA( + int32_t x, + int32_t y, + int32_t sum) +{ + return (sum + (int32_t)(((int64_t) x * y) >> 32)); +} #if 0 - /* - * @brief C custom defined PKHBT for unavailable DSP extension - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __PKHBT( - uint32_t x, - uint32_t y, - uint32_t leftshift) - { - return ( ((x ) & 0x0000FFFFUL) | - ((y << leftshift) & 0xFFFF0000UL) ); - } +/* + * @brief C custom defined PKHBT for unavailable DSP extension + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __PKHBT( + uint32_t x, + uint32_t y, + uint32_t leftshift) +{ + return (((x) & 0x0000FFFFUL) | + ((y << leftshift) & 0xFFFF0000UL)); +} - /* - * @brief C custom defined PKHTB for unavailable DSP extension - */ - CMSIS_INLINE __STATIC_INLINE uint32_t __PKHTB( - uint32_t x, - uint32_t y, - uint32_t rightshift) - { - return ( ((x ) & 0xFFFF0000UL) | - ((y >> rightshift) & 0x0000FFFFUL) ); - } +/* + * @brief C custom defined PKHTB for unavailable DSP extension + */ +CMSIS_INLINE __STATIC_INLINE uint32_t __PKHTB( + uint32_t x, + uint32_t y, + uint32_t rightshift) +{ + return (((x) & 0xFFFF0000UL) | + ((y >> rightshift) & 0x0000FFFFUL)); +} #endif /* #endif // defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ #endif /* !defined (ARM_MATH_DSP) */ - /** - * @brief Instance structure for the Q7 FIR filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q7 FIR filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of filter coefficients in the filter. */ q7_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ - } arm_fir_instance_q7; +} arm_fir_instance_q7; - /** - * @brief Instance structure for the Q15 FIR filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 FIR filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of filter coefficients in the filter. */ q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ - } arm_fir_instance_q15; +} arm_fir_instance_q15; - /** - * @brief Instance structure for the Q31 FIR filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 FIR filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of filter coefficients in the filter. */ q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ - } arm_fir_instance_q31; +} arm_fir_instance_q31; - /** - * @brief Instance structure for the floating-point FIR filter. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point FIR filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of filter coefficients in the filter. */ float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ - } arm_fir_instance_f32; +} arm_fir_instance_f32; - /** - * @brief Processing function for the Q7 FIR filter. - * @param[in] S points to an instance of the Q7 FIR filter structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_fir_q7( - const arm_fir_instance_q7 * S, - q7_t * pSrc, - q7_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q7 FIR filter. + * @param[in] S points to an instance of the Q7 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_fir_q7( + const arm_fir_instance_q7 *S, + q7_t *pSrc, + q7_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the Q7 FIR filter. - * @param[in,out] S points to an instance of the Q7 FIR structure. - * @param[in] numTaps Number of filter coefficients in the filter. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] blockSize number of samples that are processed. - */ - void arm_fir_init_q7( - arm_fir_instance_q7 * S, - uint16_t numTaps, - q7_t * pCoeffs, - q7_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the Q7 FIR filter. + * @param[in,out] S points to an instance of the Q7 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed. + */ +void arm_fir_init_q7( + arm_fir_instance_q7 *S, + uint16_t numTaps, + q7_t *pCoeffs, + q7_t *pState, + uint32_t blockSize); - /** - * @brief Processing function for the Q15 FIR filter. - * @param[in] S points to an instance of the Q15 FIR structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_fir_q15( - const arm_fir_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q15 FIR filter. + * @param[in] S points to an instance of the Q15 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_fir_q15( + const arm_fir_instance_q15 *S, + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); - /** - * @brief Processing function for the fast Q15 FIR filter for Cortex-M3 and Cortex-M4. - * @param[in] S points to an instance of the Q15 FIR filter structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_fir_fast_q15( - const arm_fir_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the fast Q15 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_fir_fast_q15( + const arm_fir_instance_q15 *S, + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the Q15 FIR filter. - * @param[in,out] S points to an instance of the Q15 FIR filter structure. - * @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] blockSize number of samples that are processed at a time. - * @return The function returns ARM_MATH_SUCCESS if initialization was successful or ARM_MATH_ARGUMENT_ERROR if - * numTaps is not a supported value. - */ - arm_status arm_fir_init_q15( - arm_fir_instance_q15 * S, - uint16_t numTaps, - q15_t * pCoeffs, - q15_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the Q15 FIR filter. + * @param[in,out] S points to an instance of the Q15 FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + * @return The function returns ARM_MATH_SUCCESS if initialization was successful or ARM_MATH_ARGUMENT_ERROR if + * numTaps is not a supported value. + */ +arm_status arm_fir_init_q15( + arm_fir_instance_q15 *S, + uint16_t numTaps, + q15_t *pCoeffs, + q15_t *pState, + uint32_t blockSize); - /** - * @brief Processing function for the Q31 FIR filter. - * @param[in] S points to an instance of the Q31 FIR filter structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_fir_q31( - const arm_fir_instance_q31 * S, - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q31 FIR filter. + * @param[in] S points to an instance of the Q31 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_fir_q31( + const arm_fir_instance_q31 *S, + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @brief Processing function for the fast Q31 FIR filter for Cortex-M3 and Cortex-M4. - * @param[in] S points to an instance of the Q31 FIR structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_fir_fast_q31( - const arm_fir_instance_q31 * S, - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the fast Q31 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_fir_fast_q31( + const arm_fir_instance_q31 *S, + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the Q31 FIR filter. - * @param[in,out] S points to an instance of the Q31 FIR structure. - * @param[in] numTaps Number of filter coefficients in the filter. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] blockSize number of samples that are processed at a time. - */ - void arm_fir_init_q31( - arm_fir_instance_q31 * S, - uint16_t numTaps, - q31_t * pCoeffs, - q31_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the Q31 FIR filter. + * @param[in,out] S points to an instance of the Q31 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ +void arm_fir_init_q31( + arm_fir_instance_q31 *S, + uint16_t numTaps, + q31_t *pCoeffs, + q31_t *pState, + uint32_t blockSize); - /** - * @brief Processing function for the floating-point FIR filter. - * @param[in] S points to an instance of the floating-point FIR structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_fir_f32( - const arm_fir_instance_f32 * S, - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the floating-point FIR filter. + * @param[in] S points to an instance of the floating-point FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_fir_f32( + const arm_fir_instance_f32 *S, + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the floating-point FIR filter. - * @param[in,out] S points to an instance of the floating-point FIR filter structure. - * @param[in] numTaps Number of filter coefficients in the filter. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] blockSize number of samples that are processed at a time. - */ - void arm_fir_init_f32( - arm_fir_instance_f32 * S, - uint16_t numTaps, - float32_t * pCoeffs, - float32_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the floating-point FIR filter. + * @param[in,out] S points to an instance of the floating-point FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ +void arm_fir_init_f32( + arm_fir_instance_f32 *S, + uint16_t numTaps, + float32_t *pCoeffs, + float32_t *pState, + uint32_t blockSize); - /** - * @brief Instance structure for the Q15 Biquad cascade filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 Biquad cascade filter. + */ +typedef struct +{ int8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ q15_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ q15_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ int8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ - } arm_biquad_casd_df1_inst_q15; +} arm_biquad_casd_df1_inst_q15; - /** - * @brief Instance structure for the Q31 Biquad cascade filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 Biquad cascade filter. + */ +typedef struct +{ uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ q31_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ q31_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ uint8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ - } arm_biquad_casd_df1_inst_q31; +} arm_biquad_casd_df1_inst_q31; - /** - * @brief Instance structure for the floating-point Biquad cascade filter. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point Biquad cascade filter. + */ +typedef struct +{ uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ float32_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ float32_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ - } arm_biquad_casd_df1_inst_f32; +} arm_biquad_casd_df1_inst_f32; - /** - * @brief Processing function for the Q15 Biquad cascade filter. - * @param[in] S points to an instance of the Q15 Biquad cascade structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_biquad_cascade_df1_q15( - const arm_biquad_casd_df1_inst_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q15 Biquad cascade filter. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_biquad_cascade_df1_q15( + const arm_biquad_casd_df1_inst_q15 *S, + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the Q15 Biquad cascade filter. - * @param[in,out] S points to an instance of the Q15 Biquad cascade structure. - * @param[in] numStages number of 2nd order stages in the filter. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format - */ - void arm_biquad_cascade_df1_init_q15( - arm_biquad_casd_df1_inst_q15 * S, - uint8_t numStages, - q15_t * pCoeffs, - q15_t * pState, - int8_t postShift); +/** + * @brief Initialization function for the Q15 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ +void arm_biquad_cascade_df1_init_q15( + arm_biquad_casd_df1_inst_q15 *S, + uint8_t numStages, + q15_t *pCoeffs, + q15_t *pState, + int8_t postShift); - /** - * @brief Fast but less precise processing function for the Q15 Biquad cascade filter for Cortex-M3 and Cortex-M4. - * @param[in] S points to an instance of the Q15 Biquad cascade structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_biquad_cascade_df1_fast_q15( - const arm_biquad_casd_df1_inst_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Fast but less precise processing function for the Q15 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_biquad_cascade_df1_fast_q15( + const arm_biquad_casd_df1_inst_q15 *S, + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); - /** - * @brief Processing function for the Q31 Biquad cascade filter - * @param[in] S points to an instance of the Q31 Biquad cascade structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_biquad_cascade_df1_q31( - const arm_biquad_casd_df1_inst_q31 * S, - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q31 Biquad cascade filter + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_biquad_cascade_df1_q31( + const arm_biquad_casd_df1_inst_q31 *S, + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @brief Fast but less precise processing function for the Q31 Biquad cascade filter for Cortex-M3 and Cortex-M4. - * @param[in] S points to an instance of the Q31 Biquad cascade structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_biquad_cascade_df1_fast_q31( - const arm_biquad_casd_df1_inst_q31 * S, - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Fast but less precise processing function for the Q31 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_biquad_cascade_df1_fast_q31( + const arm_biquad_casd_df1_inst_q31 *S, + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the Q31 Biquad cascade filter. - * @param[in,out] S points to an instance of the Q31 Biquad cascade structure. - * @param[in] numStages number of 2nd order stages in the filter. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format - */ - void arm_biquad_cascade_df1_init_q31( - arm_biquad_casd_df1_inst_q31 * S, - uint8_t numStages, - q31_t * pCoeffs, - q31_t * pState, - int8_t postShift); +/** + * @brief Initialization function for the Q31 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ +void arm_biquad_cascade_df1_init_q31( + arm_biquad_casd_df1_inst_q31 *S, + uint8_t numStages, + q31_t *pCoeffs, + q31_t *pState, + int8_t postShift); - /** - * @brief Processing function for the floating-point Biquad cascade filter. - * @param[in] S points to an instance of the floating-point Biquad cascade structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_biquad_cascade_df1_f32( - const arm_biquad_casd_df1_inst_f32 * S, - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the floating-point Biquad cascade filter. + * @param[in] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_biquad_cascade_df1_f32( + const arm_biquad_casd_df1_inst_f32 *S, + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the floating-point Biquad cascade filter. - * @param[in,out] S points to an instance of the floating-point Biquad cascade structure. - * @param[in] numStages number of 2nd order stages in the filter. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - */ - void arm_biquad_cascade_df1_init_f32( - arm_biquad_casd_df1_inst_f32 * S, - uint8_t numStages, - float32_t * pCoeffs, - float32_t * pState); +/** + * @brief Initialization function for the floating-point Biquad cascade filter. + * @param[in,out] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ +void arm_biquad_cascade_df1_init_f32( + arm_biquad_casd_df1_inst_f32 *S, + uint8_t numStages, + float32_t *pCoeffs, + float32_t *pState); - /** - * @brief Instance structure for the floating-point matrix structure. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point matrix structure. + */ +typedef struct +{ uint16_t numRows; /**< number of rows of the matrix. */ uint16_t numCols; /**< number of columns of the matrix. */ float32_t *pData; /**< points to the data of the matrix. */ - } arm_matrix_instance_f32; +} arm_matrix_instance_f32; - /** - * @brief Instance structure for the floating-point matrix structure. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point matrix structure. + */ +typedef struct +{ uint16_t numRows; /**< number of rows of the matrix. */ uint16_t numCols; /**< number of columns of the matrix. */ float64_t *pData; /**< points to the data of the matrix. */ - } arm_matrix_instance_f64; +} arm_matrix_instance_f64; - /** - * @brief Instance structure for the Q15 matrix structure. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 matrix structure. + */ +typedef struct +{ uint16_t numRows; /**< number of rows of the matrix. */ uint16_t numCols; /**< number of columns of the matrix. */ q15_t *pData; /**< points to the data of the matrix. */ - } arm_matrix_instance_q15; +} arm_matrix_instance_q15; - /** - * @brief Instance structure for the Q31 matrix structure. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 matrix structure. + */ +typedef struct +{ uint16_t numRows; /**< number of rows of the matrix. */ uint16_t numCols; /**< number of columns of the matrix. */ q31_t *pData; /**< points to the data of the matrix. */ - } arm_matrix_instance_q31; +} arm_matrix_instance_q31; - /** - * @brief Floating-point matrix addition. - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_add_f32( - const arm_matrix_instance_f32 * pSrcA, - const arm_matrix_instance_f32 * pSrcB, - arm_matrix_instance_f32 * pDst); +/** + * @brief Floating-point matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_add_f32( + const arm_matrix_instance_f32 *pSrcA, + const arm_matrix_instance_f32 *pSrcB, + arm_matrix_instance_f32 *pDst); - /** - * @brief Q15 matrix addition. - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_add_q15( - const arm_matrix_instance_q15 * pSrcA, - const arm_matrix_instance_q15 * pSrcB, - arm_matrix_instance_q15 * pDst); +/** + * @brief Q15 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_add_q15( + const arm_matrix_instance_q15 *pSrcA, + const arm_matrix_instance_q15 *pSrcB, + arm_matrix_instance_q15 *pDst); - /** - * @brief Q31 matrix addition. - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_add_q31( - const arm_matrix_instance_q31 * pSrcA, - const arm_matrix_instance_q31 * pSrcB, - arm_matrix_instance_q31 * pDst); +/** + * @brief Q31 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_add_q31( + const arm_matrix_instance_q31 *pSrcA, + const arm_matrix_instance_q31 *pSrcB, + arm_matrix_instance_q31 *pDst); - /** - * @brief Floating-point, complex, matrix multiplication. - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_cmplx_mult_f32( - const arm_matrix_instance_f32 * pSrcA, - const arm_matrix_instance_f32 * pSrcB, - arm_matrix_instance_f32 * pDst); +/** + * @brief Floating-point, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_cmplx_mult_f32( + const arm_matrix_instance_f32 *pSrcA, + const arm_matrix_instance_f32 *pSrcB, + arm_matrix_instance_f32 *pDst); - /** - * @brief Q15, complex, matrix multiplication. - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_cmplx_mult_q15( - const arm_matrix_instance_q15 * pSrcA, - const arm_matrix_instance_q15 * pSrcB, - arm_matrix_instance_q15 * pDst, - q15_t * pScratch); +/** + * @brief Q15, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_cmplx_mult_q15( + const arm_matrix_instance_q15 *pSrcA, + const arm_matrix_instance_q15 *pSrcB, + arm_matrix_instance_q15 *pDst, + q15_t *pScratch); - /** - * @brief Q31, complex, matrix multiplication. - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_cmplx_mult_q31( - const arm_matrix_instance_q31 * pSrcA, - const arm_matrix_instance_q31 * pSrcB, - arm_matrix_instance_q31 * pDst); +/** + * @brief Q31, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_cmplx_mult_q31( + const arm_matrix_instance_q31 *pSrcA, + const arm_matrix_instance_q31 *pSrcB, + arm_matrix_instance_q31 *pDst); - /** - * @brief Floating-point matrix transpose. - * @param[in] pSrc points to the input matrix - * @param[out] pDst points to the output matrix - * @return The function returns either ARM_MATH_SIZE_MISMATCH - * or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_trans_f32( - const arm_matrix_instance_f32 * pSrc, - arm_matrix_instance_f32 * pDst); +/** + * @brief Floating-point matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_trans_f32( + const arm_matrix_instance_f32 *pSrc, + arm_matrix_instance_f32 *pDst); - /** - * @brief Q15 matrix transpose. - * @param[in] pSrc points to the input matrix - * @param[out] pDst points to the output matrix - * @return The function returns either ARM_MATH_SIZE_MISMATCH - * or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_trans_q15( - const arm_matrix_instance_q15 * pSrc, - arm_matrix_instance_q15 * pDst); +/** + * @brief Q15 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_trans_q15( + const arm_matrix_instance_q15 *pSrc, + arm_matrix_instance_q15 *pDst); - /** - * @brief Q31 matrix transpose. - * @param[in] pSrc points to the input matrix - * @param[out] pDst points to the output matrix - * @return The function returns either ARM_MATH_SIZE_MISMATCH - * or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_trans_q31( - const arm_matrix_instance_q31 * pSrc, - arm_matrix_instance_q31 * pDst); +/** + * @brief Q31 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_trans_q31( + const arm_matrix_instance_q31 *pSrc, + arm_matrix_instance_q31 *pDst); - /** - * @brief Floating-point matrix multiplication - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_mult_f32( - const arm_matrix_instance_f32 * pSrcA, - const arm_matrix_instance_f32 * pSrcB, - arm_matrix_instance_f32 * pDst); +/** + * @brief Floating-point matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_mult_f32( + const arm_matrix_instance_f32 *pSrcA, + const arm_matrix_instance_f32 *pSrcB, + arm_matrix_instance_f32 *pDst); - /** - * @brief Q15 matrix multiplication - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @param[in] pState points to the array for storing intermediate results - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_mult_q15( - const arm_matrix_instance_q15 * pSrcA, - const arm_matrix_instance_q15 * pSrcB, - arm_matrix_instance_q15 * pDst, - q15_t * pState); +/** + * @brief Q15 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_mult_q15( + const arm_matrix_instance_q15 *pSrcA, + const arm_matrix_instance_q15 *pSrcB, + arm_matrix_instance_q15 *pDst, + q15_t *pState); - /** - * @brief Q15 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @param[in] pState points to the array for storing intermediate results - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_mult_fast_q15( - const arm_matrix_instance_q15 * pSrcA, - const arm_matrix_instance_q15 * pSrcB, - arm_matrix_instance_q15 * pDst, - q15_t * pState); +/** + * @brief Q15 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_mult_fast_q15( + const arm_matrix_instance_q15 *pSrcA, + const arm_matrix_instance_q15 *pSrcB, + arm_matrix_instance_q15 *pDst, + q15_t *pState); - /** - * @brief Q31 matrix multiplication - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_mult_q31( - const arm_matrix_instance_q31 * pSrcA, - const arm_matrix_instance_q31 * pSrcB, - arm_matrix_instance_q31 * pDst); +/** + * @brief Q31 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_mult_q31( + const arm_matrix_instance_q31 *pSrcA, + const arm_matrix_instance_q31 *pSrcB, + arm_matrix_instance_q31 *pDst); - /** - * @brief Q31 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_mult_fast_q31( - const arm_matrix_instance_q31 * pSrcA, - const arm_matrix_instance_q31 * pSrcB, - arm_matrix_instance_q31 * pDst); +/** + * @brief Q31 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_mult_fast_q31( + const arm_matrix_instance_q31 *pSrcA, + const arm_matrix_instance_q31 *pSrcB, + arm_matrix_instance_q31 *pDst); - /** - * @brief Floating-point matrix subtraction - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_sub_f32( - const arm_matrix_instance_f32 * pSrcA, - const arm_matrix_instance_f32 * pSrcB, - arm_matrix_instance_f32 * pDst); +/** + * @brief Floating-point matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_sub_f32( + const arm_matrix_instance_f32 *pSrcA, + const arm_matrix_instance_f32 *pSrcB, + arm_matrix_instance_f32 *pDst); - /** - * @brief Q15 matrix subtraction - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_sub_q15( - const arm_matrix_instance_q15 * pSrcA, - const arm_matrix_instance_q15 * pSrcB, - arm_matrix_instance_q15 * pDst); +/** + * @brief Q15 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_sub_q15( + const arm_matrix_instance_q15 *pSrcA, + const arm_matrix_instance_q15 *pSrcB, + arm_matrix_instance_q15 *pDst); - /** - * @brief Q31 matrix subtraction - * @param[in] pSrcA points to the first input matrix structure - * @param[in] pSrcB points to the second input matrix structure - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_sub_q31( - const arm_matrix_instance_q31 * pSrcA, - const arm_matrix_instance_q31 * pSrcB, - arm_matrix_instance_q31 * pDst); +/** + * @brief Q31 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_sub_q31( + const arm_matrix_instance_q31 *pSrcA, + const arm_matrix_instance_q31 *pSrcB, + arm_matrix_instance_q31 *pDst); - /** - * @brief Floating-point matrix scaling. - * @param[in] pSrc points to the input matrix - * @param[in] scale scale factor - * @param[out] pDst points to the output matrix - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_scale_f32( - const arm_matrix_instance_f32 * pSrc, - float32_t scale, - arm_matrix_instance_f32 * pDst); +/** + * @brief Floating-point matrix scaling. + * @param[in] pSrc points to the input matrix + * @param[in] scale scale factor + * @param[out] pDst points to the output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_scale_f32( + const arm_matrix_instance_f32 *pSrc, + float32_t scale, + arm_matrix_instance_f32 *pDst); - /** - * @brief Q15 matrix scaling. - * @param[in] pSrc points to input matrix - * @param[in] scaleFract fractional portion of the scale factor - * @param[in] shift number of bits to shift the result by - * @param[out] pDst points to output matrix - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_scale_q15( - const arm_matrix_instance_q15 * pSrc, - q15_t scaleFract, - int32_t shift, - arm_matrix_instance_q15 * pDst); +/** + * @brief Q15 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_scale_q15( + const arm_matrix_instance_q15 *pSrc, + q15_t scaleFract, + int32_t shift, + arm_matrix_instance_q15 *pDst); - /** - * @brief Q31 matrix scaling. - * @param[in] pSrc points to input matrix - * @param[in] scaleFract fractional portion of the scale factor - * @param[in] shift number of bits to shift the result by - * @param[out] pDst points to output matrix structure - * @return The function returns either - * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. - */ - arm_status arm_mat_scale_q31( - const arm_matrix_instance_q31 * pSrc, - q31_t scaleFract, - int32_t shift, - arm_matrix_instance_q31 * pDst); +/** + * @brief Q31 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ +arm_status arm_mat_scale_q31( + const arm_matrix_instance_q31 *pSrc, + q31_t scaleFract, + int32_t shift, + arm_matrix_instance_q31 *pDst); - /** - * @brief Q31 matrix initialization. - * @param[in,out] S points to an instance of the floating-point matrix structure. - * @param[in] nRows number of rows in the matrix. - * @param[in] nColumns number of columns in the matrix. - * @param[in] pData points to the matrix data array. - */ - void arm_mat_init_q31( - arm_matrix_instance_q31 * S, - uint16_t nRows, - uint16_t nColumns, - q31_t * pData); +/** + * @brief Q31 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ +void arm_mat_init_q31( + arm_matrix_instance_q31 *S, + uint16_t nRows, + uint16_t nColumns, + q31_t *pData); - /** - * @brief Q15 matrix initialization. - * @param[in,out] S points to an instance of the floating-point matrix structure. - * @param[in] nRows number of rows in the matrix. - * @param[in] nColumns number of columns in the matrix. - * @param[in] pData points to the matrix data array. - */ - void arm_mat_init_q15( - arm_matrix_instance_q15 * S, - uint16_t nRows, - uint16_t nColumns, - q15_t * pData); +/** + * @brief Q15 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ +void arm_mat_init_q15( + arm_matrix_instance_q15 *S, + uint16_t nRows, + uint16_t nColumns, + q15_t *pData); - /** - * @brief Floating-point matrix initialization. - * @param[in,out] S points to an instance of the floating-point matrix structure. - * @param[in] nRows number of rows in the matrix. - * @param[in] nColumns number of columns in the matrix. - * @param[in] pData points to the matrix data array. - */ - void arm_mat_init_f32( - arm_matrix_instance_f32 * S, - uint16_t nRows, - uint16_t nColumns, - float32_t * pData); +/** + * @brief Floating-point matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ +void arm_mat_init_f32( + arm_matrix_instance_f32 *S, + uint16_t nRows, + uint16_t nColumns, + float32_t *pData); - /** - * @brief Instance structure for the Q15 PID Control. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 PID Control. + */ +typedef struct +{ q15_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ #if !defined (ARM_MATH_DSP) q15_t A1; @@ -1828,13 +1828,13 @@ extern "C" q15_t Kp; /**< The proportional gain. */ q15_t Ki; /**< The integral gain. */ q15_t Kd; /**< The derivative gain. */ - } arm_pid_instance_q15; +} arm_pid_instance_q15; - /** - * @brief Instance structure for the Q31 PID Control. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 PID Control. + */ +typedef struct +{ q31_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ q31_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ q31_t A2; /**< The derived gain, A2 = Kd . */ @@ -1842,13 +1842,13 @@ extern "C" q31_t Kp; /**< The proportional gain. */ q31_t Ki; /**< The integral gain. */ q31_t Kd; /**< The derivative gain. */ - } arm_pid_instance_q31; +} arm_pid_instance_q31; - /** - * @brief Instance structure for the floating-point PID Control. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point PID Control. + */ +typedef struct +{ float32_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ float32_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ float32_t A2; /**< The derived gain, A2 = Kd . */ @@ -1856,178 +1856,178 @@ extern "C" float32_t Kp; /**< The proportional gain. */ float32_t Ki; /**< The integral gain. */ float32_t Kd; /**< The derivative gain. */ - } arm_pid_instance_f32; +} arm_pid_instance_f32; - /** - * @brief Initialization function for the floating-point PID Control. - * @param[in,out] S points to an instance of the PID structure. - * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. - */ - void arm_pid_init_f32( - arm_pid_instance_f32 * S, - int32_t resetStateFlag); +/** + * @brief Initialization function for the floating-point PID Control. + * @param[in,out] S points to an instance of the PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ +void arm_pid_init_f32( + arm_pid_instance_f32 *S, + int32_t resetStateFlag); - /** - * @brief Reset function for the floating-point PID Control. - * @param[in,out] S is an instance of the floating-point PID Control structure - */ - void arm_pid_reset_f32( - arm_pid_instance_f32 * S); +/** + * @brief Reset function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + */ +void arm_pid_reset_f32( + arm_pid_instance_f32 *S); - /** - * @brief Initialization function for the Q31 PID Control. - * @param[in,out] S points to an instance of the Q15 PID structure. - * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. - */ - void arm_pid_init_q31( - arm_pid_instance_q31 * S, - int32_t resetStateFlag); +/** + * @brief Initialization function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ +void arm_pid_init_q31( + arm_pid_instance_q31 *S, + int32_t resetStateFlag); - /** - * @brief Reset function for the Q31 PID Control. - * @param[in,out] S points to an instance of the Q31 PID Control structure - */ +/** + * @brief Reset function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + */ - void arm_pid_reset_q31( - arm_pid_instance_q31 * S); +void arm_pid_reset_q31( + arm_pid_instance_q31 *S); - /** - * @brief Initialization function for the Q15 PID Control. - * @param[in,out] S points to an instance of the Q15 PID structure. - * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. - */ - void arm_pid_init_q15( - arm_pid_instance_q15 * S, - int32_t resetStateFlag); +/** + * @brief Initialization function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ +void arm_pid_init_q15( + arm_pid_instance_q15 *S, + int32_t resetStateFlag); - /** - * @brief Reset function for the Q15 PID Control. - * @param[in,out] S points to an instance of the q15 PID Control structure - */ - void arm_pid_reset_q15( - arm_pid_instance_q15 * S); +/** + * @brief Reset function for the Q15 PID Control. + * @param[in,out] S points to an instance of the q15 PID Control structure + */ +void arm_pid_reset_q15( + arm_pid_instance_q15 *S); - /** - * @brief Instance structure for the floating-point Linear Interpolate function. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point Linear Interpolate function. + */ +typedef struct +{ uint32_t nValues; /**< nValues */ float32_t x1; /**< x1 */ float32_t xSpacing; /**< xSpacing */ float32_t *pYData; /**< pointer to the table of Y values */ - } arm_linear_interp_instance_f32; +} arm_linear_interp_instance_f32; - /** - * @brief Instance structure for the floating-point bilinear interpolation function. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point bilinear interpolation function. + */ +typedef struct +{ uint16_t numRows; /**< number of rows in the data table. */ uint16_t numCols; /**< number of columns in the data table. */ float32_t *pData; /**< points to the data table. */ - } arm_bilinear_interp_instance_f32; +} arm_bilinear_interp_instance_f32; - /** - * @brief Instance structure for the Q31 bilinear interpolation function. - */ - typedef struct - { +/** +* @brief Instance structure for the Q31 bilinear interpolation function. +*/ +typedef struct +{ uint16_t numRows; /**< number of rows in the data table. */ uint16_t numCols; /**< number of columns in the data table. */ q31_t *pData; /**< points to the data table. */ - } arm_bilinear_interp_instance_q31; +} arm_bilinear_interp_instance_q31; - /** - * @brief Instance structure for the Q15 bilinear interpolation function. - */ - typedef struct - { +/** +* @brief Instance structure for the Q15 bilinear interpolation function. +*/ +typedef struct +{ uint16_t numRows; /**< number of rows in the data table. */ uint16_t numCols; /**< number of columns in the data table. */ q15_t *pData; /**< points to the data table. */ - } arm_bilinear_interp_instance_q15; +} arm_bilinear_interp_instance_q15; - /** - * @brief Instance structure for the Q15 bilinear interpolation function. - */ - typedef struct - { +/** +* @brief Instance structure for the Q15 bilinear interpolation function. +*/ +typedef struct +{ uint16_t numRows; /**< number of rows in the data table. */ uint16_t numCols; /**< number of columns in the data table. */ q7_t *pData; /**< points to the data table. */ - } arm_bilinear_interp_instance_q7; +} arm_bilinear_interp_instance_q7; - /** - * @brief Q7 vector multiplication. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_mult_q7( - q7_t * pSrcA, - q7_t * pSrcB, - q7_t * pDst, - uint32_t blockSize); +/** + * @brief Q7 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_mult_q7( + q7_t *pSrcA, + q7_t *pSrcB, + q7_t *pDst, + uint32_t blockSize); - /** - * @brief Q15 vector multiplication. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_mult_q15( - q15_t * pSrcA, - q15_t * pSrcB, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Q15 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_mult_q15( + q15_t *pSrcA, + q15_t *pSrcB, + q15_t *pDst, + uint32_t blockSize); - /** - * @brief Q31 vector multiplication. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_mult_q31( - q31_t * pSrcA, - q31_t * pSrcB, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Q31 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_mult_q31( + q31_t *pSrcA, + q31_t *pSrcB, + q31_t *pDst, + uint32_t blockSize); - /** - * @brief Floating-point vector multiplication. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_mult_f32( - float32_t * pSrcA, - float32_t * pSrcB, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Floating-point vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_mult_f32( + float32_t *pSrcA, + float32_t *pSrcB, + float32_t *pDst, + uint32_t blockSize); - /** - * @brief Instance structure for the Q15 CFFT/CIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ +typedef struct +{ uint16_t fftLen; /**< length of the FFT. */ uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ @@ -2035,26 +2035,26 @@ extern "C" uint16_t *pBitRevTable; /**< points to the bit reversal table. */ uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ - } arm_cfft_radix2_instance_q15; +} arm_cfft_radix2_instance_q15; /* Deprecated */ - arm_status arm_cfft_radix2_init_q15( - arm_cfft_radix2_instance_q15 * S, - uint16_t fftLen, - uint8_t ifftFlag, - uint8_t bitReverseFlag); +arm_status arm_cfft_radix2_init_q15( + arm_cfft_radix2_instance_q15 *S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); /* Deprecated */ - void arm_cfft_radix2_q15( - const arm_cfft_radix2_instance_q15 * S, - q15_t * pSrc); +void arm_cfft_radix2_q15( + const arm_cfft_radix2_instance_q15 *S, + q15_t *pSrc); - /** - * @brief Instance structure for the Q15 CFFT/CIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ +typedef struct +{ uint16_t fftLen; /**< length of the FFT. */ uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ @@ -2062,25 +2062,25 @@ extern "C" uint16_t *pBitRevTable; /**< points to the bit reversal table. */ uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ - } arm_cfft_radix4_instance_q15; +} arm_cfft_radix4_instance_q15; /* Deprecated */ - arm_status arm_cfft_radix4_init_q15( - arm_cfft_radix4_instance_q15 * S, - uint16_t fftLen, - uint8_t ifftFlag, - uint8_t bitReverseFlag); +arm_status arm_cfft_radix4_init_q15( + arm_cfft_radix4_instance_q15 *S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); /* Deprecated */ - void arm_cfft_radix4_q15( - const arm_cfft_radix4_instance_q15 * S, - q15_t * pSrc); +void arm_cfft_radix4_q15( + const arm_cfft_radix4_instance_q15 *S, + q15_t *pSrc); - /** - * @brief Instance structure for the Radix-2 Q31 CFFT/CIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the Radix-2 Q31 CFFT/CIFFT function. + */ +typedef struct +{ uint16_t fftLen; /**< length of the FFT. */ uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ @@ -2088,25 +2088,25 @@ extern "C" uint16_t *pBitRevTable; /**< points to the bit reversal table. */ uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ - } arm_cfft_radix2_instance_q31; +} arm_cfft_radix2_instance_q31; /* Deprecated */ - arm_status arm_cfft_radix2_init_q31( - arm_cfft_radix2_instance_q31 * S, - uint16_t fftLen, - uint8_t ifftFlag, - uint8_t bitReverseFlag); +arm_status arm_cfft_radix2_init_q31( + arm_cfft_radix2_instance_q31 *S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); /* Deprecated */ - void arm_cfft_radix2_q31( - const arm_cfft_radix2_instance_q31 * S, - q31_t * pSrc); +void arm_cfft_radix2_q31( + const arm_cfft_radix2_instance_q31 *S, + q31_t *pSrc); - /** - * @brief Instance structure for the Q31 CFFT/CIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 CFFT/CIFFT function. + */ +typedef struct +{ uint16_t fftLen; /**< length of the FFT. */ uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ @@ -2114,25 +2114,25 @@ extern "C" uint16_t *pBitRevTable; /**< points to the bit reversal table. */ uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ - } arm_cfft_radix4_instance_q31; +} arm_cfft_radix4_instance_q31; /* Deprecated */ - void arm_cfft_radix4_q31( - const arm_cfft_radix4_instance_q31 * S, - q31_t * pSrc); +void arm_cfft_radix4_q31( + const arm_cfft_radix4_instance_q31 *S, + q31_t *pSrc); /* Deprecated */ - arm_status arm_cfft_radix4_init_q31( - arm_cfft_radix4_instance_q31 * S, - uint16_t fftLen, - uint8_t ifftFlag, - uint8_t bitReverseFlag); +arm_status arm_cfft_radix4_init_q31( + arm_cfft_radix4_instance_q31 *S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); - /** - * @brief Instance structure for the floating-point CFFT/CIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ +typedef struct +{ uint16_t fftLen; /**< length of the FFT. */ uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ @@ -2141,25 +2141,25 @@ extern "C" uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ float32_t onebyfftLen; /**< value of 1/fftLen. */ - } arm_cfft_radix2_instance_f32; +} arm_cfft_radix2_instance_f32; /* Deprecated */ - arm_status arm_cfft_radix2_init_f32( - arm_cfft_radix2_instance_f32 * S, - uint16_t fftLen, - uint8_t ifftFlag, - uint8_t bitReverseFlag); +arm_status arm_cfft_radix2_init_f32( + arm_cfft_radix2_instance_f32 *S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); /* Deprecated */ - void arm_cfft_radix2_f32( - const arm_cfft_radix2_instance_f32 * S, - float32_t * pSrc); +void arm_cfft_radix2_f32( + const arm_cfft_radix2_instance_f32 *S, + float32_t *pSrc); - /** - * @brief Instance structure for the floating-point CFFT/CIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ +typedef struct +{ uint16_t fftLen; /**< length of the FFT. */ uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ @@ -2168,76 +2168,76 @@ extern "C" uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ float32_t onebyfftLen; /**< value of 1/fftLen. */ - } arm_cfft_radix4_instance_f32; +} arm_cfft_radix4_instance_f32; /* Deprecated */ - arm_status arm_cfft_radix4_init_f32( - arm_cfft_radix4_instance_f32 * S, - uint16_t fftLen, - uint8_t ifftFlag, - uint8_t bitReverseFlag); +arm_status arm_cfft_radix4_init_f32( + arm_cfft_radix4_instance_f32 *S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); /* Deprecated */ - void arm_cfft_radix4_f32( - const arm_cfft_radix4_instance_f32 * S, - float32_t * pSrc); +void arm_cfft_radix4_f32( + const arm_cfft_radix4_instance_f32 *S, + float32_t *pSrc); - /** - * @brief Instance structure for the fixed-point CFFT/CIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ +typedef struct +{ uint16_t fftLen; /**< length of the FFT. */ const q15_t *pTwiddle; /**< points to the Twiddle factor table. */ const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ uint16_t bitRevLength; /**< bit reversal table length. */ - } arm_cfft_instance_q15; +} arm_cfft_instance_q15; void arm_cfft_q15( - const arm_cfft_instance_q15 * S, - q15_t * p1, + const arm_cfft_instance_q15 *S, + q15_t *p1, uint8_t ifftFlag, uint8_t bitReverseFlag); - /** - * @brief Instance structure for the fixed-point CFFT/CIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ +typedef struct +{ uint16_t fftLen; /**< length of the FFT. */ const q31_t *pTwiddle; /**< points to the Twiddle factor table. */ const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ uint16_t bitRevLength; /**< bit reversal table length. */ - } arm_cfft_instance_q31; +} arm_cfft_instance_q31; void arm_cfft_q31( - const arm_cfft_instance_q31 * S, - q31_t * p1, + const arm_cfft_instance_q31 *S, + q31_t *p1, uint8_t ifftFlag, uint8_t bitReverseFlag); - /** - * @brief Instance structure for the floating-point CFFT/CIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ +typedef struct +{ uint16_t fftLen; /**< length of the FFT. */ const float32_t *pTwiddle; /**< points to the Twiddle factor table. */ const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ uint16_t bitRevLength; /**< bit reversal table length. */ - } arm_cfft_instance_f32; +} arm_cfft_instance_f32; - void arm_cfft_f32( - const arm_cfft_instance_f32 * S, - float32_t * p1, - uint8_t ifftFlag, - uint8_t bitReverseFlag); +void arm_cfft_f32( + const arm_cfft_instance_f32 *S, + float32_t *p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); - /** - * @brief Instance structure for the Q15 RFFT/RIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 RFFT/RIFFT function. + */ +typedef struct +{ uint32_t fftLenReal; /**< length of the real FFT. */ uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ @@ -2245,24 +2245,24 @@ void arm_cfft_q31( q15_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ q15_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ const arm_cfft_instance_q15 *pCfft; /**< points to the complex FFT instance. */ - } arm_rfft_instance_q15; +} arm_rfft_instance_q15; - arm_status arm_rfft_init_q15( - arm_rfft_instance_q15 * S, - uint32_t fftLenReal, - uint32_t ifftFlagR, - uint32_t bitReverseFlag); +arm_status arm_rfft_init_q15( + arm_rfft_instance_q15 *S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); - void arm_rfft_q15( - const arm_rfft_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst); +void arm_rfft_q15( + const arm_rfft_instance_q15 *S, + q15_t *pSrc, + q15_t *pDst); - /** - * @brief Instance structure for the Q31 RFFT/RIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 RFFT/RIFFT function. + */ +typedef struct +{ uint32_t fftLenReal; /**< length of the real FFT. */ uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ @@ -2270,24 +2270,24 @@ void arm_cfft_q31( q31_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ q31_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ const arm_cfft_instance_q31 *pCfft; /**< points to the complex FFT instance. */ - } arm_rfft_instance_q31; +} arm_rfft_instance_q31; - arm_status arm_rfft_init_q31( - arm_rfft_instance_q31 * S, - uint32_t fftLenReal, - uint32_t ifftFlagR, - uint32_t bitReverseFlag); +arm_status arm_rfft_init_q31( + arm_rfft_instance_q31 *S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); - void arm_rfft_q31( - const arm_rfft_instance_q31 * S, - q31_t * pSrc, - q31_t * pDst); +void arm_rfft_q31( + const arm_rfft_instance_q31 *S, + q31_t *pSrc, + q31_t *pDst); - /** - * @brief Instance structure for the floating-point RFFT/RIFFT function. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ +typedef struct +{ uint32_t fftLenReal; /**< length of the real FFT. */ uint16_t fftLenBy2; /**< length of the complex FFT. */ uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ @@ -2296,44 +2296,44 @@ void arm_cfft_q31( float32_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ float32_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ - } arm_rfft_instance_f32; +} arm_rfft_instance_f32; - arm_status arm_rfft_init_f32( - arm_rfft_instance_f32 * S, - arm_cfft_radix4_instance_f32 * S_CFFT, - uint32_t fftLenReal, - uint32_t ifftFlagR, - uint32_t bitReverseFlag); +arm_status arm_rfft_init_f32( + arm_rfft_instance_f32 *S, + arm_cfft_radix4_instance_f32 *S_CFFT, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); - void arm_rfft_f32( - const arm_rfft_instance_f32 * S, - float32_t * pSrc, - float32_t * pDst); +void arm_rfft_f32( + const arm_rfft_instance_f32 *S, + float32_t *pSrc, + float32_t *pDst); - /** - * @brief Instance structure for the floating-point RFFT/RIFFT function. - */ +/** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ typedef struct - { +{ arm_cfft_instance_f32 Sint; /**< Internal CFFT structure. */ uint16_t fftLenRFFT; /**< length of the real sequence */ - float32_t * pTwiddleRFFT; /**< Twiddle factors real stage */ - } arm_rfft_fast_instance_f32 ; + float32_t *pTwiddleRFFT; /**< Twiddle factors real stage */ +} arm_rfft_fast_instance_f32 ; -arm_status arm_rfft_fast_init_f32 ( - arm_rfft_fast_instance_f32 * S, - uint16_t fftLen); +arm_status arm_rfft_fast_init_f32( + arm_rfft_fast_instance_f32 *S, + uint16_t fftLen); void arm_rfft_fast_f32( - arm_rfft_fast_instance_f32 * S, - float32_t * p, float32_t * pOut, - uint8_t ifftFlag); + arm_rfft_fast_instance_f32 *S, + float32_t *p, float32_t *pOut, + uint8_t ifftFlag); - /** - * @brief Instance structure for the floating-point DCT4/IDCT4 function. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point DCT4/IDCT4 function. + */ +typedef struct +{ uint16_t N; /**< length of the DCT4. */ uint16_t Nby2; /**< half of the length of the DCT4. */ float32_t normalize; /**< normalizing factor. */ @@ -2341,45 +2341,45 @@ void arm_rfft_fast_f32( float32_t *pCosFactor; /**< points to the cosFactor table. */ arm_rfft_instance_f32 *pRfft; /**< points to the real FFT instance. */ arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ - } arm_dct4_instance_f32; +} arm_dct4_instance_f32; - /** - * @brief Initialization function for the floating-point DCT4/IDCT4. - * @param[in,out] S points to an instance of floating-point DCT4/IDCT4 structure. - * @param[in] S_RFFT points to an instance of floating-point RFFT/RIFFT structure. - * @param[in] S_CFFT points to an instance of floating-point CFFT/CIFFT structure. - * @param[in] N length of the DCT4. - * @param[in] Nby2 half of the length of the DCT4. - * @param[in] normalize normalizing factor. - * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if fftLenReal is not a supported transform length. - */ - arm_status arm_dct4_init_f32( - arm_dct4_instance_f32 * S, - arm_rfft_instance_f32 * S_RFFT, - arm_cfft_radix4_instance_f32 * S_CFFT, - uint16_t N, - uint16_t Nby2, - float32_t normalize); +/** + * @brief Initialization function for the floating-point DCT4/IDCT4. + * @param[in,out] S points to an instance of floating-point DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of floating-point RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of floating-point CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if fftLenReal is not a supported transform length. + */ +arm_status arm_dct4_init_f32( + arm_dct4_instance_f32 *S, + arm_rfft_instance_f32 *S_RFFT, + arm_cfft_radix4_instance_f32 *S_CFFT, + uint16_t N, + uint16_t Nby2, + float32_t normalize); - /** - * @brief Processing function for the floating-point DCT4/IDCT4. - * @param[in] S points to an instance of the floating-point DCT4/IDCT4 structure. - * @param[in] pState points to state buffer. - * @param[in,out] pInlineBuffer points to the in-place input and output buffer. - */ - void arm_dct4_f32( - const arm_dct4_instance_f32 * S, - float32_t * pState, - float32_t * pInlineBuffer); +/** + * @brief Processing function for the floating-point DCT4/IDCT4. + * @param[in] S points to an instance of the floating-point DCT4/IDCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ +void arm_dct4_f32( + const arm_dct4_instance_f32 *S, + float32_t *pState, + float32_t *pInlineBuffer); - /** - * @brief Instance structure for the Q31 DCT4/IDCT4 function. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 DCT4/IDCT4 function. + */ +typedef struct +{ uint16_t N; /**< length of the DCT4. */ uint16_t Nby2; /**< half of the length of the DCT4. */ q31_t normalize; /**< normalizing factor. */ @@ -2387,45 +2387,45 @@ void arm_rfft_fast_f32( q31_t *pCosFactor; /**< points to the cosFactor table. */ arm_rfft_instance_q31 *pRfft; /**< points to the real FFT instance. */ arm_cfft_radix4_instance_q31 *pCfft; /**< points to the complex FFT instance. */ - } arm_dct4_instance_q31; +} arm_dct4_instance_q31; - /** - * @brief Initialization function for the Q31 DCT4/IDCT4. - * @param[in,out] S points to an instance of Q31 DCT4/IDCT4 structure. - * @param[in] S_RFFT points to an instance of Q31 RFFT/RIFFT structure - * @param[in] S_CFFT points to an instance of Q31 CFFT/CIFFT structure - * @param[in] N length of the DCT4. - * @param[in] Nby2 half of the length of the DCT4. - * @param[in] normalize normalizing factor. - * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. - */ - arm_status arm_dct4_init_q31( - arm_dct4_instance_q31 * S, - arm_rfft_instance_q31 * S_RFFT, - arm_cfft_radix4_instance_q31 * S_CFFT, - uint16_t N, - uint16_t Nby2, - q31_t normalize); +/** + * @brief Initialization function for the Q31 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q31 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q31 RFFT/RIFFT structure + * @param[in] S_CFFT points to an instance of Q31 CFFT/CIFFT structure + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ +arm_status arm_dct4_init_q31( + arm_dct4_instance_q31 *S, + arm_rfft_instance_q31 *S_RFFT, + arm_cfft_radix4_instance_q31 *S_CFFT, + uint16_t N, + uint16_t Nby2, + q31_t normalize); - /** - * @brief Processing function for the Q31 DCT4/IDCT4. - * @param[in] S points to an instance of the Q31 DCT4 structure. - * @param[in] pState points to state buffer. - * @param[in,out] pInlineBuffer points to the in-place input and output buffer. - */ - void arm_dct4_q31( - const arm_dct4_instance_q31 * S, - q31_t * pState, - q31_t * pInlineBuffer); +/** + * @brief Processing function for the Q31 DCT4/IDCT4. + * @param[in] S points to an instance of the Q31 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ +void arm_dct4_q31( + const arm_dct4_instance_q31 *S, + q31_t *pState, + q31_t *pInlineBuffer); - /** - * @brief Instance structure for the Q15 DCT4/IDCT4 function. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 DCT4/IDCT4 function. + */ +typedef struct +{ uint16_t N; /**< length of the DCT4. */ uint16_t Nby2; /**< half of the length of the DCT4. */ q15_t normalize; /**< normalizing factor. */ @@ -2433,558 +2433,558 @@ void arm_rfft_fast_f32( q15_t *pCosFactor; /**< points to the cosFactor table. */ arm_rfft_instance_q15 *pRfft; /**< points to the real FFT instance. */ arm_cfft_radix4_instance_q15 *pCfft; /**< points to the complex FFT instance. */ - } arm_dct4_instance_q15; - - - /** - * @brief Initialization function for the Q15 DCT4/IDCT4. - * @param[in,out] S points to an instance of Q15 DCT4/IDCT4 structure. - * @param[in] S_RFFT points to an instance of Q15 RFFT/RIFFT structure. - * @param[in] S_CFFT points to an instance of Q15 CFFT/CIFFT structure. - * @param[in] N length of the DCT4. - * @param[in] Nby2 half of the length of the DCT4. - * @param[in] normalize normalizing factor. - * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. - */ - arm_status arm_dct4_init_q15( - arm_dct4_instance_q15 * S, - arm_rfft_instance_q15 * S_RFFT, - arm_cfft_radix4_instance_q15 * S_CFFT, - uint16_t N, - uint16_t Nby2, - q15_t normalize); - - - /** - * @brief Processing function for the Q15 DCT4/IDCT4. - * @param[in] S points to an instance of the Q15 DCT4 structure. - * @param[in] pState points to state buffer. - * @param[in,out] pInlineBuffer points to the in-place input and output buffer. - */ - void arm_dct4_q15( - const arm_dct4_instance_q15 * S, - q15_t * pState, - q15_t * pInlineBuffer); - - - /** - * @brief Floating-point vector addition. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_add_f32( - float32_t * pSrcA, - float32_t * pSrcB, - float32_t * pDst, - uint32_t blockSize); - - - /** - * @brief Q7 vector addition. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_add_q7( - q7_t * pSrcA, - q7_t * pSrcB, - q7_t * pDst, - uint32_t blockSize); - - - /** - * @brief Q15 vector addition. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_add_q15( - q15_t * pSrcA, - q15_t * pSrcB, - q15_t * pDst, - uint32_t blockSize); - - - /** - * @brief Q31 vector addition. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_add_q31( - q31_t * pSrcA, - q31_t * pSrcB, - q31_t * pDst, - uint32_t blockSize); - - - /** - * @brief Floating-point vector subtraction. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_sub_f32( - float32_t * pSrcA, - float32_t * pSrcB, - float32_t * pDst, - uint32_t blockSize); - - - /** - * @brief Q7 vector subtraction. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_sub_q7( - q7_t * pSrcA, - q7_t * pSrcB, - q7_t * pDst, - uint32_t blockSize); - - - /** - * @brief Q15 vector subtraction. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_sub_q15( - q15_t * pSrcA, - q15_t * pSrcB, - q15_t * pDst, - uint32_t blockSize); - - - /** - * @brief Q31 vector subtraction. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in each vector - */ - void arm_sub_q31( - q31_t * pSrcA, - q31_t * pSrcB, - q31_t * pDst, - uint32_t blockSize); - - - /** - * @brief Multiplies a floating-point vector by a scalar. - * @param[in] pSrc points to the input vector - * @param[in] scale scale factor to be applied - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_scale_f32( - float32_t * pSrc, - float32_t scale, - float32_t * pDst, - uint32_t blockSize); - - - /** - * @brief Multiplies a Q7 vector by a scalar. - * @param[in] pSrc points to the input vector - * @param[in] scaleFract fractional portion of the scale value - * @param[in] shift number of bits to shift the result by - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_scale_q7( - q7_t * pSrc, - q7_t scaleFract, - int8_t shift, - q7_t * pDst, - uint32_t blockSize); - - - /** - * @brief Multiplies a Q15 vector by a scalar. - * @param[in] pSrc points to the input vector - * @param[in] scaleFract fractional portion of the scale value - * @param[in] shift number of bits to shift the result by - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_scale_q15( - q15_t * pSrc, - q15_t scaleFract, - int8_t shift, - q15_t * pDst, - uint32_t blockSize); - - - /** - * @brief Multiplies a Q31 vector by a scalar. - * @param[in] pSrc points to the input vector - * @param[in] scaleFract fractional portion of the scale value - * @param[in] shift number of bits to shift the result by - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_scale_q31( - q31_t * pSrc, - q31_t scaleFract, - int8_t shift, - q31_t * pDst, - uint32_t blockSize); - - - /** - * @brief Q7 vector absolute value. - * @param[in] pSrc points to the input buffer - * @param[out] pDst points to the output buffer - * @param[in] blockSize number of samples in each vector - */ - void arm_abs_q7( - q7_t * pSrc, - q7_t * pDst, - uint32_t blockSize); - - - /** - * @brief Floating-point vector absolute value. - * @param[in] pSrc points to the input buffer - * @param[out] pDst points to the output buffer - * @param[in] blockSize number of samples in each vector - */ - void arm_abs_f32( - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize); - - - /** - * @brief Q15 vector absolute value. - * @param[in] pSrc points to the input buffer - * @param[out] pDst points to the output buffer - * @param[in] blockSize number of samples in each vector - */ - void arm_abs_q15( - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); - - - /** - * @brief Q31 vector absolute value. - * @param[in] pSrc points to the input buffer - * @param[out] pDst points to the output buffer - * @param[in] blockSize number of samples in each vector - */ - void arm_abs_q31( - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); - - - /** - * @brief Dot product of floating-point vectors. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[in] blockSize number of samples in each vector - * @param[out] result output result returned here - */ - void arm_dot_prod_f32( - float32_t * pSrcA, - float32_t * pSrcB, - uint32_t blockSize, - float32_t * result); - - - /** - * @brief Dot product of Q7 vectors. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[in] blockSize number of samples in each vector - * @param[out] result output result returned here - */ - void arm_dot_prod_q7( - q7_t * pSrcA, - q7_t * pSrcB, - uint32_t blockSize, - q31_t * result); - - - /** - * @brief Dot product of Q15 vectors. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[in] blockSize number of samples in each vector - * @param[out] result output result returned here - */ - void arm_dot_prod_q15( - q15_t * pSrcA, - q15_t * pSrcB, - uint32_t blockSize, - q63_t * result); - - - /** - * @brief Dot product of Q31 vectors. - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[in] blockSize number of samples in each vector - * @param[out] result output result returned here - */ - void arm_dot_prod_q31( - q31_t * pSrcA, - q31_t * pSrcB, - uint32_t blockSize, - q63_t * result); - - - /** - * @brief Shifts the elements of a Q7 vector a specified number of bits. - * @param[in] pSrc points to the input vector - * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_shift_q7( - q7_t * pSrc, - int8_t shiftBits, - q7_t * pDst, - uint32_t blockSize); - - - /** - * @brief Shifts the elements of a Q15 vector a specified number of bits. - * @param[in] pSrc points to the input vector - * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_shift_q15( - q15_t * pSrc, - int8_t shiftBits, - q15_t * pDst, - uint32_t blockSize); - - - /** - * @brief Shifts the elements of a Q31 vector a specified number of bits. - * @param[in] pSrc points to the input vector - * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_shift_q31( - q31_t * pSrc, - int8_t shiftBits, - q31_t * pDst, - uint32_t blockSize); - - - /** - * @brief Adds a constant offset to a floating-point vector. - * @param[in] pSrc points to the input vector - * @param[in] offset is the offset to be added - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_offset_f32( - float32_t * pSrc, - float32_t offset, - float32_t * pDst, - uint32_t blockSize); - - - /** - * @brief Adds a constant offset to a Q7 vector. - * @param[in] pSrc points to the input vector - * @param[in] offset is the offset to be added - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_offset_q7( - q7_t * pSrc, - q7_t offset, - q7_t * pDst, - uint32_t blockSize); - - - /** - * @brief Adds a constant offset to a Q15 vector. - * @param[in] pSrc points to the input vector - * @param[in] offset is the offset to be added - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_offset_q15( - q15_t * pSrc, - q15_t offset, - q15_t * pDst, - uint32_t blockSize); - - - /** - * @brief Adds a constant offset to a Q31 vector. - * @param[in] pSrc points to the input vector - * @param[in] offset is the offset to be added - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_offset_q31( - q31_t * pSrc, - q31_t offset, - q31_t * pDst, - uint32_t blockSize); - - - /** - * @brief Negates the elements of a floating-point vector. - * @param[in] pSrc points to the input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_negate_f32( - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize); - - - /** - * @brief Negates the elements of a Q7 vector. - * @param[in] pSrc points to the input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_negate_q7( - q7_t * pSrc, - q7_t * pDst, - uint32_t blockSize); - - - /** - * @brief Negates the elements of a Q15 vector. - * @param[in] pSrc points to the input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_negate_q15( - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); - - - /** - * @brief Negates the elements of a Q31 vector. - * @param[in] pSrc points to the input vector - * @param[out] pDst points to the output vector - * @param[in] blockSize number of samples in the vector - */ - void arm_negate_q31( - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); - - - /** - * @brief Copies the elements of a floating-point vector. - * @param[in] pSrc input pointer - * @param[out] pDst output pointer - * @param[in] blockSize number of samples to process - */ - void arm_copy_f32( - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize); - - - /** - * @brief Copies the elements of a Q7 vector. - * @param[in] pSrc input pointer - * @param[out] pDst output pointer - * @param[in] blockSize number of samples to process - */ - void arm_copy_q7( - q7_t * pSrc, - q7_t * pDst, - uint32_t blockSize); - - - /** - * @brief Copies the elements of a Q15 vector. - * @param[in] pSrc input pointer - * @param[out] pDst output pointer - * @param[in] blockSize number of samples to process - */ - void arm_copy_q15( - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); - - - /** - * @brief Copies the elements of a Q31 vector. - * @param[in] pSrc input pointer - * @param[out] pDst output pointer - * @param[in] blockSize number of samples to process - */ - void arm_copy_q31( - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); - - - /** - * @brief Fills a constant value into a floating-point vector. - * @param[in] value input value to be filled - * @param[out] pDst output pointer - * @param[in] blockSize number of samples to process - */ - void arm_fill_f32( - float32_t value, - float32_t * pDst, - uint32_t blockSize); - - - /** - * @brief Fills a constant value into a Q7 vector. - * @param[in] value input value to be filled - * @param[out] pDst output pointer - * @param[in] blockSize number of samples to process - */ - void arm_fill_q7( - q7_t value, - q7_t * pDst, - uint32_t blockSize); - - - /** - * @brief Fills a constant value into a Q15 vector. - * @param[in] value input value to be filled - * @param[out] pDst output pointer - * @param[in] blockSize number of samples to process - */ - void arm_fill_q15( - q15_t value, - q15_t * pDst, - uint32_t blockSize); - - - /** - * @brief Fills a constant value into a Q31 vector. - * @param[in] value input value to be filled - * @param[out] pDst output pointer - * @param[in] blockSize number of samples to process - */ - void arm_fill_q31( - q31_t value, - q31_t * pDst, - uint32_t blockSize); +} arm_dct4_instance_q15; + + +/** + * @brief Initialization function for the Q15 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q15 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q15 RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of Q15 CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ +arm_status arm_dct4_init_q15( + arm_dct4_instance_q15 *S, + arm_rfft_instance_q15 *S_RFFT, + arm_cfft_radix4_instance_q15 *S_CFFT, + uint16_t N, + uint16_t Nby2, + q15_t normalize); + + +/** + * @brief Processing function for the Q15 DCT4/IDCT4. + * @param[in] S points to an instance of the Q15 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ +void arm_dct4_q15( + const arm_dct4_instance_q15 *S, + q15_t *pState, + q15_t *pInlineBuffer); + + +/** + * @brief Floating-point vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_add_f32( + float32_t *pSrcA, + float32_t *pSrcB, + float32_t *pDst, + uint32_t blockSize); + + +/** + * @brief Q7 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_add_q7( + q7_t *pSrcA, + q7_t *pSrcB, + q7_t *pDst, + uint32_t blockSize); + + +/** + * @brief Q15 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_add_q15( + q15_t *pSrcA, + q15_t *pSrcB, + q15_t *pDst, + uint32_t blockSize); + + +/** + * @brief Q31 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_add_q31( + q31_t *pSrcA, + q31_t *pSrcB, + q31_t *pDst, + uint32_t blockSize); + + +/** + * @brief Floating-point vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_sub_f32( + float32_t *pSrcA, + float32_t *pSrcB, + float32_t *pDst, + uint32_t blockSize); + + +/** + * @brief Q7 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_sub_q7( + q7_t *pSrcA, + q7_t *pSrcB, + q7_t *pDst, + uint32_t blockSize); + + +/** + * @brief Q15 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_sub_q15( + q15_t *pSrcA, + q15_t *pSrcB, + q15_t *pDst, + uint32_t blockSize); + + +/** + * @brief Q31 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ +void arm_sub_q31( + q31_t *pSrcA, + q31_t *pSrcB, + q31_t *pDst, + uint32_t blockSize); + + +/** + * @brief Multiplies a floating-point vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scale scale factor to be applied + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_scale_f32( + float32_t *pSrc, + float32_t scale, + float32_t *pDst, + uint32_t blockSize); + + +/** + * @brief Multiplies a Q7 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_scale_q7( + q7_t *pSrc, + q7_t scaleFract, + int8_t shift, + q7_t *pDst, + uint32_t blockSize); + + +/** + * @brief Multiplies a Q15 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_scale_q15( + q15_t *pSrc, + q15_t scaleFract, + int8_t shift, + q15_t *pDst, + uint32_t blockSize); + + +/** + * @brief Multiplies a Q31 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_scale_q31( + q31_t *pSrc, + q31_t scaleFract, + int8_t shift, + q31_t *pDst, + uint32_t blockSize); + + +/** + * @brief Q7 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ +void arm_abs_q7( + q7_t *pSrc, + q7_t *pDst, + uint32_t blockSize); + + +/** + * @brief Floating-point vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ +void arm_abs_f32( + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); + + +/** + * @brief Q15 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ +void arm_abs_q15( + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); + + +/** + * @brief Q31 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ +void arm_abs_q31( + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); + + +/** + * @brief Dot product of floating-point vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ +void arm_dot_prod_f32( + float32_t *pSrcA, + float32_t *pSrcB, + uint32_t blockSize, + float32_t *result); + + +/** + * @brief Dot product of Q7 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ +void arm_dot_prod_q7( + q7_t *pSrcA, + q7_t *pSrcB, + uint32_t blockSize, + q31_t *result); + + +/** + * @brief Dot product of Q15 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ +void arm_dot_prod_q15( + q15_t *pSrcA, + q15_t *pSrcB, + uint32_t blockSize, + q63_t *result); + + +/** + * @brief Dot product of Q31 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ +void arm_dot_prod_q31( + q31_t *pSrcA, + q31_t *pSrcB, + uint32_t blockSize, + q63_t *result); + + +/** + * @brief Shifts the elements of a Q7 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_shift_q7( + q7_t *pSrc, + int8_t shiftBits, + q7_t *pDst, + uint32_t blockSize); + + +/** + * @brief Shifts the elements of a Q15 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_shift_q15( + q15_t *pSrc, + int8_t shiftBits, + q15_t *pDst, + uint32_t blockSize); + + +/** + * @brief Shifts the elements of a Q31 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_shift_q31( + q31_t *pSrc, + int8_t shiftBits, + q31_t *pDst, + uint32_t blockSize); + + +/** + * @brief Adds a constant offset to a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_offset_f32( + float32_t *pSrc, + float32_t offset, + float32_t *pDst, + uint32_t blockSize); + + +/** + * @brief Adds a constant offset to a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_offset_q7( + q7_t *pSrc, + q7_t offset, + q7_t *pDst, + uint32_t blockSize); + + +/** + * @brief Adds a constant offset to a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_offset_q15( + q15_t *pSrc, + q15_t offset, + q15_t *pDst, + uint32_t blockSize); + + +/** + * @brief Adds a constant offset to a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_offset_q31( + q31_t *pSrc, + q31_t offset, + q31_t *pDst, + uint32_t blockSize); + + +/** + * @brief Negates the elements of a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_negate_f32( + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); + + +/** + * @brief Negates the elements of a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_negate_q7( + q7_t *pSrc, + q7_t *pDst, + uint32_t blockSize); + + +/** + * @brief Negates the elements of a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_negate_q15( + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); + + +/** + * @brief Negates the elements of a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ +void arm_negate_q31( + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); + + +/** + * @brief Copies the elements of a floating-point vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ +void arm_copy_f32( + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); + + +/** + * @brief Copies the elements of a Q7 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ +void arm_copy_q7( + q7_t *pSrc, + q7_t *pDst, + uint32_t blockSize); + + +/** + * @brief Copies the elements of a Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ +void arm_copy_q15( + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); + + +/** + * @brief Copies the elements of a Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ +void arm_copy_q31( + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); + + +/** + * @brief Fills a constant value into a floating-point vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ +void arm_fill_f32( + float32_t value, + float32_t *pDst, + uint32_t blockSize); + + +/** + * @brief Fills a constant value into a Q7 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ +void arm_fill_q7( + q7_t value, + q7_t *pDst, + uint32_t blockSize); + + +/** + * @brief Fills a constant value into a Q15 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ +void arm_fill_q15( + q15_t value, + q15_t *pDst, + uint32_t blockSize); + + +/** + * @brief Fills a constant value into a Q31 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ +void arm_fill_q31( + q31_t value, + q31_t *pDst, + uint32_t blockSize); /** @@ -2995,32 +2995,32 @@ void arm_rfft_fast_f32( * @param[in] srcBLen length of the second input sequence. * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. */ - void arm_conv_f32( - float32_t * pSrcA, - uint32_t srcALen, - float32_t * pSrcB, - uint32_t srcBLen, - float32_t * pDst); +void arm_conv_f32( + float32_t *pSrcA, + uint32_t srcALen, + float32_t *pSrcB, + uint32_t srcBLen, + float32_t *pDst); - /** - * @brief Convolution of Q15 sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. - * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. - * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). - */ - void arm_conv_opt_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst, - q15_t * pScratch1, - q15_t * pScratch2); +/** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ +void arm_conv_opt_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst, + q15_t *pScratch1, + q15_t *pScratch2); /** @@ -3031,296 +3031,296 @@ void arm_rfft_fast_f32( * @param[in] srcBLen length of the second input sequence. * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. */ - void arm_conv_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst); +void arm_conv_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst); - /** - * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. - */ - void arm_conv_fast_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst); +/** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ +void arm_conv_fast_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst); - /** - * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. - * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. - * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). - */ - void arm_conv_fast_opt_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst, - q15_t * pScratch1, - q15_t * pScratch2); +/** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ +void arm_conv_fast_opt_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst, + q15_t *pScratch1, + q15_t *pScratch2); - /** - * @brief Convolution of Q31 sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. - */ - void arm_conv_q31( - q31_t * pSrcA, - uint32_t srcALen, - q31_t * pSrcB, - uint32_t srcBLen, - q31_t * pDst); +/** + * @brief Convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ +void arm_conv_q31( + q31_t *pSrcA, + uint32_t srcALen, + q31_t *pSrcB, + uint32_t srcBLen, + q31_t *pDst); - /** - * @brief Convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. - */ - void arm_conv_fast_q31( - q31_t * pSrcA, - uint32_t srcALen, - q31_t * pSrcB, - uint32_t srcBLen, - q31_t * pDst); +/** + * @brief Convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ +void arm_conv_fast_q31( + q31_t *pSrcA, + uint32_t srcALen, + q31_t *pSrcB, + uint32_t srcBLen, + q31_t *pDst); - /** - * @brief Convolution of Q7 sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. - * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. - * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). - */ - void arm_conv_opt_q7( - q7_t * pSrcA, - uint32_t srcALen, - q7_t * pSrcB, - uint32_t srcBLen, - q7_t * pDst, - q15_t * pScratch1, - q15_t * pScratch2); +/** +* @brief Convolution of Q7 sequences. +* @param[in] pSrcA points to the first input sequence. +* @param[in] srcALen length of the first input sequence. +* @param[in] pSrcB points to the second input sequence. +* @param[in] srcBLen length of the second input sequence. +* @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. +* @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. +* @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). +*/ +void arm_conv_opt_q7( + q7_t *pSrcA, + uint32_t srcALen, + q7_t *pSrcB, + uint32_t srcBLen, + q7_t *pDst, + q15_t *pScratch1, + q15_t *pScratch2); - /** - * @brief Convolution of Q7 sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. - */ - void arm_conv_q7( - q7_t * pSrcA, - uint32_t srcALen, - q7_t * pSrcB, - uint32_t srcBLen, - q7_t * pDst); +/** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ +void arm_conv_q7( + q7_t *pSrcA, + uint32_t srcALen, + q7_t *pSrcB, + uint32_t srcBLen, + q7_t *pDst); - /** - * @brief Partial convolution of floating-point sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data - * @param[in] firstIndex is the first output sample to start with. - * @param[in] numPoints is the number of output points to be computed. - * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. - */ - arm_status arm_conv_partial_f32( - float32_t * pSrcA, - uint32_t srcALen, - float32_t * pSrcB, - uint32_t srcBLen, - float32_t * pDst, - uint32_t firstIndex, - uint32_t numPoints); +/** + * @brief Partial convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ +arm_status arm_conv_partial_f32( + float32_t *pSrcA, + uint32_t srcALen, + float32_t *pSrcB, + uint32_t srcBLen, + float32_t *pDst, + uint32_t firstIndex, + uint32_t numPoints); - /** - * @brief Partial convolution of Q15 sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data - * @param[in] firstIndex is the first output sample to start with. - * @param[in] numPoints is the number of output points to be computed. - * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. - * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). - * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. - */ - arm_status arm_conv_partial_opt_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst, - uint32_t firstIndex, - uint32_t numPoints, - q15_t * pScratch1, - q15_t * pScratch2); +/** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ +arm_status arm_conv_partial_opt_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t *pScratch1, + q15_t *pScratch2); - /** - * @brief Partial convolution of Q15 sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data - * @param[in] firstIndex is the first output sample to start with. - * @param[in] numPoints is the number of output points to be computed. - * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. - */ - arm_status arm_conv_partial_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst, - uint32_t firstIndex, - uint32_t numPoints); +/** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ +arm_status arm_conv_partial_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst, + uint32_t firstIndex, + uint32_t numPoints); - /** - * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data - * @param[in] firstIndex is the first output sample to start with. - * @param[in] numPoints is the number of output points to be computed. - * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. - */ - arm_status arm_conv_partial_fast_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst, - uint32_t firstIndex, - uint32_t numPoints); +/** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ +arm_status arm_conv_partial_fast_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst, + uint32_t firstIndex, + uint32_t numPoints); - /** - * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data - * @param[in] firstIndex is the first output sample to start with. - * @param[in] numPoints is the number of output points to be computed. - * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. - * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). - * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. - */ - arm_status arm_conv_partial_fast_opt_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst, - uint32_t firstIndex, - uint32_t numPoints, - q15_t * pScratch1, - q15_t * pScratch2); +/** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ +arm_status arm_conv_partial_fast_opt_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t *pScratch1, + q15_t *pScratch2); - /** - * @brief Partial convolution of Q31 sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data - * @param[in] firstIndex is the first output sample to start with. - * @param[in] numPoints is the number of output points to be computed. - * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. - */ - arm_status arm_conv_partial_q31( - q31_t * pSrcA, - uint32_t srcALen, - q31_t * pSrcB, - uint32_t srcBLen, - q31_t * pDst, - uint32_t firstIndex, - uint32_t numPoints); +/** + * @brief Partial convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ +arm_status arm_conv_partial_q31( + q31_t *pSrcA, + uint32_t srcALen, + q31_t *pSrcB, + uint32_t srcBLen, + q31_t *pDst, + uint32_t firstIndex, + uint32_t numPoints); - /** - * @brief Partial convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data - * @param[in] firstIndex is the first output sample to start with. - * @param[in] numPoints is the number of output points to be computed. - * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. - */ - arm_status arm_conv_partial_fast_q31( - q31_t * pSrcA, - uint32_t srcALen, - q31_t * pSrcB, - uint32_t srcBLen, - q31_t * pDst, - uint32_t firstIndex, - uint32_t numPoints); +/** + * @brief Partial convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ +arm_status arm_conv_partial_fast_q31( + q31_t *pSrcA, + uint32_t srcALen, + q31_t *pSrcB, + uint32_t srcBLen, + q31_t *pDst, + uint32_t firstIndex, + uint32_t numPoints); - /** - * @brief Partial convolution of Q7 sequences - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data - * @param[in] firstIndex is the first output sample to start with. - * @param[in] numPoints is the number of output points to be computed. - * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. - * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). - * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. - */ - arm_status arm_conv_partial_opt_q7( - q7_t * pSrcA, - uint32_t srcALen, - q7_t * pSrcB, - uint32_t srcBLen, - q7_t * pDst, - uint32_t firstIndex, - uint32_t numPoints, - q15_t * pScratch1, - q15_t * pScratch2); +/** + * @brief Partial convolution of Q7 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ +arm_status arm_conv_partial_opt_q7( + q7_t *pSrcA, + uint32_t srcALen, + q7_t *pSrcB, + uint32_t srcBLen, + q7_t *pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t *pScratch1, + q15_t *pScratch2); /** @@ -3334,555 +3334,555 @@ void arm_rfft_fast_f32( * @param[in] numPoints is the number of output points to be computed. * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. */ - arm_status arm_conv_partial_q7( - q7_t * pSrcA, - uint32_t srcALen, - q7_t * pSrcB, - uint32_t srcBLen, - q7_t * pDst, - uint32_t firstIndex, - uint32_t numPoints); +arm_status arm_conv_partial_q7( + q7_t *pSrcA, + uint32_t srcALen, + q7_t *pSrcB, + uint32_t srcBLen, + q7_t *pDst, + uint32_t firstIndex, + uint32_t numPoints); - /** - * @brief Instance structure for the Q15 FIR decimator. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 FIR decimator. + */ +typedef struct +{ uint8_t M; /**< decimation factor. */ uint16_t numTaps; /**< number of coefficients in the filter. */ q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ - } arm_fir_decimate_instance_q15; +} arm_fir_decimate_instance_q15; - /** - * @brief Instance structure for the Q31 FIR decimator. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 FIR decimator. + */ +typedef struct +{ uint8_t M; /**< decimation factor. */ uint16_t numTaps; /**< number of coefficients in the filter. */ q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ - } arm_fir_decimate_instance_q31; +} arm_fir_decimate_instance_q31; - /** - * @brief Instance structure for the floating-point FIR decimator. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point FIR decimator. + */ +typedef struct +{ uint8_t M; /**< decimation factor. */ uint16_t numTaps; /**< number of coefficients in the filter. */ float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ - } arm_fir_decimate_instance_f32; +} arm_fir_decimate_instance_f32; - /** - * @brief Processing function for the floating-point FIR decimator. - * @param[in] S points to an instance of the floating-point FIR decimator structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_decimate_f32( - const arm_fir_decimate_instance_f32 * S, - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the floating-point FIR decimator. + * @param[in] S points to an instance of the floating-point FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_decimate_f32( + const arm_fir_decimate_instance_f32 *S, + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the floating-point FIR decimator. - * @param[in,out] S points to an instance of the floating-point FIR decimator structure. - * @param[in] numTaps number of coefficients in the filter. - * @param[in] M decimation factor. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] blockSize number of input samples to process per call. - * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if - * blockSize is not a multiple of M. - */ - arm_status arm_fir_decimate_init_f32( - arm_fir_decimate_instance_f32 * S, - uint16_t numTaps, - uint8_t M, - float32_t * pCoeffs, - float32_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the floating-point FIR decimator. + * @param[in,out] S points to an instance of the floating-point FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ +arm_status arm_fir_decimate_init_f32( + arm_fir_decimate_instance_f32 *S, + uint16_t numTaps, + uint8_t M, + float32_t *pCoeffs, + float32_t *pState, + uint32_t blockSize); - /** - * @brief Processing function for the Q15 FIR decimator. - * @param[in] S points to an instance of the Q15 FIR decimator structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_decimate_q15( - const arm_fir_decimate_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q15 FIR decimator. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_decimate_q15( + const arm_fir_decimate_instance_q15 *S, + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); - /** - * @brief Processing function for the Q15 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. - * @param[in] S points to an instance of the Q15 FIR decimator structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_decimate_fast_q15( - const arm_fir_decimate_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q15 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_decimate_fast_q15( + const arm_fir_decimate_instance_q15 *S, + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the Q15 FIR decimator. - * @param[in,out] S points to an instance of the Q15 FIR decimator structure. - * @param[in] numTaps number of coefficients in the filter. - * @param[in] M decimation factor. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] blockSize number of input samples to process per call. - * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if - * blockSize is not a multiple of M. - */ - arm_status arm_fir_decimate_init_q15( - arm_fir_decimate_instance_q15 * S, - uint16_t numTaps, - uint8_t M, - q15_t * pCoeffs, - q15_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the Q15 FIR decimator. + * @param[in,out] S points to an instance of the Q15 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ +arm_status arm_fir_decimate_init_q15( + arm_fir_decimate_instance_q15 *S, + uint16_t numTaps, + uint8_t M, + q15_t *pCoeffs, + q15_t *pState, + uint32_t blockSize); - /** - * @brief Processing function for the Q31 FIR decimator. - * @param[in] S points to an instance of the Q31 FIR decimator structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_decimate_q31( - const arm_fir_decimate_instance_q31 * S, - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q31 FIR decimator. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_decimate_q31( + const arm_fir_decimate_instance_q31 *S, + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @brief Processing function for the Q31 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. - * @param[in] S points to an instance of the Q31 FIR decimator structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_decimate_fast_q31( - arm_fir_decimate_instance_q31 * S, - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q31 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_decimate_fast_q31( + arm_fir_decimate_instance_q31 *S, + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the Q31 FIR decimator. - * @param[in,out] S points to an instance of the Q31 FIR decimator structure. - * @param[in] numTaps number of coefficients in the filter. - * @param[in] M decimation factor. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] blockSize number of input samples to process per call. - * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if - * blockSize is not a multiple of M. - */ - arm_status arm_fir_decimate_init_q31( - arm_fir_decimate_instance_q31 * S, - uint16_t numTaps, - uint8_t M, - q31_t * pCoeffs, - q31_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the Q31 FIR decimator. + * @param[in,out] S points to an instance of the Q31 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ +arm_status arm_fir_decimate_init_q31( + arm_fir_decimate_instance_q31 *S, + uint16_t numTaps, + uint8_t M, + q31_t *pCoeffs, + q31_t *pState, + uint32_t blockSize); - /** - * @brief Instance structure for the Q15 FIR interpolator. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 FIR interpolator. + */ +typedef struct +{ uint8_t L; /**< upsample factor. */ uint16_t phaseLength; /**< length of each polyphase filter component. */ q15_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ q15_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ - } arm_fir_interpolate_instance_q15; +} arm_fir_interpolate_instance_q15; - /** - * @brief Instance structure for the Q31 FIR interpolator. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 FIR interpolator. + */ +typedef struct +{ uint8_t L; /**< upsample factor. */ uint16_t phaseLength; /**< length of each polyphase filter component. */ q31_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ q31_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ - } arm_fir_interpolate_instance_q31; +} arm_fir_interpolate_instance_q31; - /** - * @brief Instance structure for the floating-point FIR interpolator. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point FIR interpolator. + */ +typedef struct +{ uint8_t L; /**< upsample factor. */ uint16_t phaseLength; /**< length of each polyphase filter component. */ float32_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ float32_t *pState; /**< points to the state variable array. The array is of length phaseLength+numTaps-1. */ - } arm_fir_interpolate_instance_f32; +} arm_fir_interpolate_instance_f32; - /** - * @brief Processing function for the Q15 FIR interpolator. - * @param[in] S points to an instance of the Q15 FIR interpolator structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_interpolate_q15( - const arm_fir_interpolate_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q15 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_interpolate_q15( + const arm_fir_interpolate_instance_q15 *S, + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the Q15 FIR interpolator. - * @param[in,out] S points to an instance of the Q15 FIR interpolator structure. - * @param[in] L upsample factor. - * @param[in] numTaps number of filter coefficients in the filter. - * @param[in] pCoeffs points to the filter coefficient buffer. - * @param[in] pState points to the state buffer. - * @param[in] blockSize number of input samples to process per call. - * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if - * the filter length numTaps is not a multiple of the interpolation factor L. - */ - arm_status arm_fir_interpolate_init_q15( - arm_fir_interpolate_instance_q15 * S, - uint8_t L, - uint16_t numTaps, - q15_t * pCoeffs, - q15_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the Q15 FIR interpolator. + * @param[in,out] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ +arm_status arm_fir_interpolate_init_q15( + arm_fir_interpolate_instance_q15 *S, + uint8_t L, + uint16_t numTaps, + q15_t *pCoeffs, + q15_t *pState, + uint32_t blockSize); - /** - * @brief Processing function for the Q31 FIR interpolator. - * @param[in] S points to an instance of the Q15 FIR interpolator structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_interpolate_q31( - const arm_fir_interpolate_instance_q31 * S, - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q31 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_interpolate_q31( + const arm_fir_interpolate_instance_q31 *S, + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the Q31 FIR interpolator. - * @param[in,out] S points to an instance of the Q31 FIR interpolator structure. - * @param[in] L upsample factor. - * @param[in] numTaps number of filter coefficients in the filter. - * @param[in] pCoeffs points to the filter coefficient buffer. - * @param[in] pState points to the state buffer. - * @param[in] blockSize number of input samples to process per call. - * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if - * the filter length numTaps is not a multiple of the interpolation factor L. - */ - arm_status arm_fir_interpolate_init_q31( - arm_fir_interpolate_instance_q31 * S, - uint8_t L, - uint16_t numTaps, - q31_t * pCoeffs, - q31_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the Q31 FIR interpolator. + * @param[in,out] S points to an instance of the Q31 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ +arm_status arm_fir_interpolate_init_q31( + arm_fir_interpolate_instance_q31 *S, + uint8_t L, + uint16_t numTaps, + q31_t *pCoeffs, + q31_t *pState, + uint32_t blockSize); - /** - * @brief Processing function for the floating-point FIR interpolator. - * @param[in] S points to an instance of the floating-point FIR interpolator structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_interpolate_f32( - const arm_fir_interpolate_instance_f32 * S, - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the floating-point FIR interpolator. + * @param[in] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_interpolate_f32( + const arm_fir_interpolate_instance_f32 *S, + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the floating-point FIR interpolator. - * @param[in,out] S points to an instance of the floating-point FIR interpolator structure. - * @param[in] L upsample factor. - * @param[in] numTaps number of filter coefficients in the filter. - * @param[in] pCoeffs points to the filter coefficient buffer. - * @param[in] pState points to the state buffer. - * @param[in] blockSize number of input samples to process per call. - * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if - * the filter length numTaps is not a multiple of the interpolation factor L. - */ - arm_status arm_fir_interpolate_init_f32( - arm_fir_interpolate_instance_f32 * S, - uint8_t L, - uint16_t numTaps, - float32_t * pCoeffs, - float32_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the floating-point FIR interpolator. + * @param[in,out] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ +arm_status arm_fir_interpolate_init_f32( + arm_fir_interpolate_instance_f32 *S, + uint8_t L, + uint16_t numTaps, + float32_t *pCoeffs, + float32_t *pState, + uint32_t blockSize); - /** - * @brief Instance structure for the high precision Q31 Biquad cascade filter. - */ - typedef struct - { +/** + * @brief Instance structure for the high precision Q31 Biquad cascade filter. + */ +typedef struct +{ uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ q63_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ q31_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ uint8_t postShift; /**< additional shift, in bits, applied to each output sample. */ - } arm_biquad_cas_df1_32x64_ins_q31; +} arm_biquad_cas_df1_32x64_ins_q31; - /** - * @param[in] S points to an instance of the high precision Q31 Biquad cascade filter structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] blockSize number of samples to process. - */ - void arm_biquad_cas_df1_32x64_q31( - const arm_biquad_cas_df1_32x64_ins_q31 * S, - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @param[in] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ +void arm_biquad_cas_df1_32x64_q31( + const arm_biquad_cas_df1_32x64_ins_q31 *S, + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @param[in,out] S points to an instance of the high precision Q31 Biquad cascade filter structure. - * @param[in] numStages number of 2nd order stages in the filter. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] postShift shift to be applied to the output. Varies according to the coefficients format - */ - void arm_biquad_cas_df1_32x64_init_q31( - arm_biquad_cas_df1_32x64_ins_q31 * S, - uint8_t numStages, - q31_t * pCoeffs, - q63_t * pState, - uint8_t postShift); +/** + * @param[in,out] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift shift to be applied to the output. Varies according to the coefficients format + */ +void arm_biquad_cas_df1_32x64_init_q31( + arm_biquad_cas_df1_32x64_ins_q31 *S, + uint8_t numStages, + q31_t *pCoeffs, + q63_t *pState, + uint8_t postShift); - /** - * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ +typedef struct +{ uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ float32_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ - } arm_biquad_cascade_df2T_instance_f32; +} arm_biquad_cascade_df2T_instance_f32; - /** - * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ +typedef struct +{ uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ float32_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ - } arm_biquad_cascade_stereo_df2T_instance_f32; +} arm_biquad_cascade_stereo_df2T_instance_f32; - /** - * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ +typedef struct +{ uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ float64_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ float64_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ - } arm_biquad_cascade_df2T_instance_f64; +} arm_biquad_cascade_df2T_instance_f64; - /** - * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. - * @param[in] S points to an instance of the filter data structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] blockSize number of samples to process. - */ - void arm_biquad_cascade_df2T_f32( - const arm_biquad_cascade_df2T_instance_f32 * S, - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ +void arm_biquad_cascade_df2T_f32( + const arm_biquad_cascade_df2T_instance_f32 *S, + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); - /** - * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. 2 channels - * @param[in] S points to an instance of the filter data structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] blockSize number of samples to process. - */ - void arm_biquad_cascade_stereo_df2T_f32( - const arm_biquad_cascade_stereo_df2T_instance_f32 * S, - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. 2 channels + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ +void arm_biquad_cascade_stereo_df2T_f32( + const arm_biquad_cascade_stereo_df2T_instance_f32 *S, + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); - /** - * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. - * @param[in] S points to an instance of the filter data structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] blockSize number of samples to process. - */ - void arm_biquad_cascade_df2T_f64( - const arm_biquad_cascade_df2T_instance_f64 * S, - float64_t * pSrc, - float64_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ +void arm_biquad_cascade_df2T_f64( + const arm_biquad_cascade_df2T_instance_f64 *S, + float64_t *pSrc, + float64_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. - * @param[in,out] S points to an instance of the filter data structure. - * @param[in] numStages number of 2nd order stages in the filter. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - */ - void arm_biquad_cascade_df2T_init_f32( - arm_biquad_cascade_df2T_instance_f32 * S, - uint8_t numStages, - float32_t * pCoeffs, - float32_t * pState); +/** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ +void arm_biquad_cascade_df2T_init_f32( + arm_biquad_cascade_df2T_instance_f32 *S, + uint8_t numStages, + float32_t *pCoeffs, + float32_t *pState); - /** - * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. - * @param[in,out] S points to an instance of the filter data structure. - * @param[in] numStages number of 2nd order stages in the filter. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - */ - void arm_biquad_cascade_stereo_df2T_init_f32( - arm_biquad_cascade_stereo_df2T_instance_f32 * S, - uint8_t numStages, - float32_t * pCoeffs, - float32_t * pState); +/** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ +void arm_biquad_cascade_stereo_df2T_init_f32( + arm_biquad_cascade_stereo_df2T_instance_f32 *S, + uint8_t numStages, + float32_t *pCoeffs, + float32_t *pState); - /** - * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. - * @param[in,out] S points to an instance of the filter data structure. - * @param[in] numStages number of 2nd order stages in the filter. - * @param[in] pCoeffs points to the filter coefficients. - * @param[in] pState points to the state buffer. - */ - void arm_biquad_cascade_df2T_init_f64( - arm_biquad_cascade_df2T_instance_f64 * S, - uint8_t numStages, - float64_t * pCoeffs, - float64_t * pState); +/** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ +void arm_biquad_cascade_df2T_init_f64( + arm_biquad_cascade_df2T_instance_f64 *S, + uint8_t numStages, + float64_t *pCoeffs, + float64_t *pState); - /** - * @brief Instance structure for the Q15 FIR lattice filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 FIR lattice filter. + */ +typedef struct +{ uint16_t numStages; /**< number of filter stages. */ q15_t *pState; /**< points to the state variable array. The array is of length numStages. */ q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ - } arm_fir_lattice_instance_q15; +} arm_fir_lattice_instance_q15; - /** - * @brief Instance structure for the Q31 FIR lattice filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 FIR lattice filter. + */ +typedef struct +{ uint16_t numStages; /**< number of filter stages. */ q31_t *pState; /**< points to the state variable array. The array is of length numStages. */ q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ - } arm_fir_lattice_instance_q31; +} arm_fir_lattice_instance_q31; - /** - * @brief Instance structure for the floating-point FIR lattice filter. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point FIR lattice filter. + */ +typedef struct +{ uint16_t numStages; /**< number of filter stages. */ float32_t *pState; /**< points to the state variable array. The array is of length numStages. */ float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ - } arm_fir_lattice_instance_f32; +} arm_fir_lattice_instance_f32; - /** - * @brief Initialization function for the Q15 FIR lattice filter. - * @param[in] S points to an instance of the Q15 FIR lattice structure. - * @param[in] numStages number of filter stages. - * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. - * @param[in] pState points to the state buffer. The array is of length numStages. - */ - void arm_fir_lattice_init_q15( - arm_fir_lattice_instance_q15 * S, - uint16_t numStages, - q15_t * pCoeffs, - q15_t * pState); +/** + * @brief Initialization function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ +void arm_fir_lattice_init_q15( + arm_fir_lattice_instance_q15 *S, + uint16_t numStages, + q15_t *pCoeffs, + q15_t *pState); - /** - * @brief Processing function for the Q15 FIR lattice filter. - * @param[in] S points to an instance of the Q15 FIR lattice structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_fir_lattice_q15( - const arm_fir_lattice_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_fir_lattice_q15( + const arm_fir_lattice_instance_q15 *S, + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the Q31 FIR lattice filter. - * @param[in] S points to an instance of the Q31 FIR lattice structure. - * @param[in] numStages number of filter stages. - * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. - * @param[in] pState points to the state buffer. The array is of length numStages. - */ - void arm_fir_lattice_init_q31( - arm_fir_lattice_instance_q31 * S, - uint16_t numStages, - q31_t * pCoeffs, - q31_t * pState); +/** + * @brief Initialization function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ +void arm_fir_lattice_init_q31( + arm_fir_lattice_instance_q31 *S, + uint16_t numStages, + q31_t *pCoeffs, + q31_t *pState); - /** - * @brief Processing function for the Q31 FIR lattice filter. - * @param[in] S points to an instance of the Q31 FIR lattice structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] blockSize number of samples to process. - */ - void arm_fir_lattice_q31( - const arm_fir_lattice_instance_q31 * S, - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ +void arm_fir_lattice_q31( + const arm_fir_lattice_instance_q31 *S, + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); /** @@ -3892,137 +3892,137 @@ void arm_rfft_fast_f32( * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. * @param[in] pState points to the state buffer. The array is of length numStages. */ - void arm_fir_lattice_init_f32( - arm_fir_lattice_instance_f32 * S, - uint16_t numStages, - float32_t * pCoeffs, - float32_t * pState); +void arm_fir_lattice_init_f32( + arm_fir_lattice_instance_f32 *S, + uint16_t numStages, + float32_t *pCoeffs, + float32_t *pState); - /** - * @brief Processing function for the floating-point FIR lattice filter. - * @param[in] S points to an instance of the floating-point FIR lattice structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] blockSize number of samples to process. - */ - void arm_fir_lattice_f32( - const arm_fir_lattice_instance_f32 * S, - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ +void arm_fir_lattice_f32( + const arm_fir_lattice_instance_f32 *S, + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); - /** - * @brief Instance structure for the Q15 IIR lattice filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 IIR lattice filter. + */ +typedef struct +{ uint16_t numStages; /**< number of stages in the filter. */ q15_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ q15_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ q15_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ - } arm_iir_lattice_instance_q15; +} arm_iir_lattice_instance_q15; - /** - * @brief Instance structure for the Q31 IIR lattice filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 IIR lattice filter. + */ +typedef struct +{ uint16_t numStages; /**< number of stages in the filter. */ q31_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ q31_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ q31_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ - } arm_iir_lattice_instance_q31; +} arm_iir_lattice_instance_q31; - /** - * @brief Instance structure for the floating-point IIR lattice filter. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point IIR lattice filter. + */ +typedef struct +{ uint16_t numStages; /**< number of stages in the filter. */ float32_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ float32_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ float32_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ - } arm_iir_lattice_instance_f32; +} arm_iir_lattice_instance_f32; - /** - * @brief Processing function for the floating-point IIR lattice filter. - * @param[in] S points to an instance of the floating-point IIR lattice structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_iir_lattice_f32( - const arm_iir_lattice_instance_f32 * S, - float32_t * pSrc, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_iir_lattice_f32( + const arm_iir_lattice_instance_f32 *S, + float32_t *pSrc, + float32_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the floating-point IIR lattice filter. - * @param[in] S points to an instance of the floating-point IIR lattice structure. - * @param[in] numStages number of stages in the filter. - * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. - * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. - * @param[in] pState points to the state buffer. The array is of length numStages+blockSize-1. - * @param[in] blockSize number of samples to process. - */ - void arm_iir_lattice_init_f32( - arm_iir_lattice_instance_f32 * S, - uint16_t numStages, - float32_t * pkCoeffs, - float32_t * pvCoeffs, - float32_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize-1. + * @param[in] blockSize number of samples to process. + */ +void arm_iir_lattice_init_f32( + arm_iir_lattice_instance_f32 *S, + uint16_t numStages, + float32_t *pkCoeffs, + float32_t *pvCoeffs, + float32_t *pState, + uint32_t blockSize); - /** - * @brief Processing function for the Q31 IIR lattice filter. - * @param[in] S points to an instance of the Q31 IIR lattice structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_iir_lattice_q31( - const arm_iir_lattice_instance_q31 * S, - q31_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_iir_lattice_q31( + const arm_iir_lattice_instance_q31 *S, + q31_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @brief Initialization function for the Q31 IIR lattice filter. - * @param[in] S points to an instance of the Q31 IIR lattice structure. - * @param[in] numStages number of stages in the filter. - * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. - * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. - * @param[in] pState points to the state buffer. The array is of length numStages+blockSize. - * @param[in] blockSize number of samples to process. - */ - void arm_iir_lattice_init_q31( - arm_iir_lattice_instance_q31 * S, - uint16_t numStages, - q31_t * pkCoeffs, - q31_t * pvCoeffs, - q31_t * pState, - uint32_t blockSize); +/** + * @brief Initialization function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process. + */ +void arm_iir_lattice_init_q31( + arm_iir_lattice_instance_q31 *S, + uint16_t numStages, + q31_t *pkCoeffs, + q31_t *pvCoeffs, + q31_t *pState, + uint32_t blockSize); - /** - * @brief Processing function for the Q15 IIR lattice filter. - * @param[in] S points to an instance of the Q15 IIR lattice structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data. - * @param[in] blockSize number of samples to process. - */ - void arm_iir_lattice_q15( - const arm_iir_lattice_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Processing function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the Q15 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ +void arm_iir_lattice_q15( + const arm_iir_lattice_instance_q15 *S, + q15_t *pSrc, + q15_t *pDst, + uint32_t blockSize); /** @@ -4034,220 +4034,220 @@ void arm_rfft_fast_f32( * @param[in] pState points to state buffer. The array is of length numStages+blockSize. * @param[in] blockSize number of samples to process per call. */ - void arm_iir_lattice_init_q15( - arm_iir_lattice_instance_q15 * S, - uint16_t numStages, - q15_t * pkCoeffs, - q15_t * pvCoeffs, - q15_t * pState, - uint32_t blockSize); +void arm_iir_lattice_init_q15( + arm_iir_lattice_instance_q15 *S, + uint16_t numStages, + q15_t *pkCoeffs, + q15_t *pvCoeffs, + q15_t *pState, + uint32_t blockSize); - /** - * @brief Instance structure for the floating-point LMS filter. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point LMS filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of coefficients in the filter. */ float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ float32_t mu; /**< step size that controls filter coefficient updates. */ - } arm_lms_instance_f32; +} arm_lms_instance_f32; - /** - * @brief Processing function for floating-point LMS filter. - * @param[in] S points to an instance of the floating-point LMS filter structure. - * @param[in] pSrc points to the block of input data. - * @param[in] pRef points to the block of reference data. - * @param[out] pOut points to the block of output data. - * @param[out] pErr points to the block of error data. - * @param[in] blockSize number of samples to process. - */ - void arm_lms_f32( - const arm_lms_instance_f32 * S, - float32_t * pSrc, - float32_t * pRef, - float32_t * pOut, - float32_t * pErr, - uint32_t blockSize); +/** + * @brief Processing function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ +void arm_lms_f32( + const arm_lms_instance_f32 *S, + float32_t *pSrc, + float32_t *pRef, + float32_t *pOut, + float32_t *pErr, + uint32_t blockSize); - /** - * @brief Initialization function for floating-point LMS filter. - * @param[in] S points to an instance of the floating-point LMS filter structure. - * @param[in] numTaps number of filter coefficients. - * @param[in] pCoeffs points to the coefficient buffer. - * @param[in] pState points to state buffer. - * @param[in] mu step size that controls filter coefficient updates. - * @param[in] blockSize number of samples to process. - */ - void arm_lms_init_f32( - arm_lms_instance_f32 * S, - uint16_t numTaps, - float32_t * pCoeffs, - float32_t * pState, - float32_t mu, - uint32_t blockSize); +/** + * @brief Initialization function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ +void arm_lms_init_f32( + arm_lms_instance_f32 *S, + uint16_t numTaps, + float32_t *pCoeffs, + float32_t *pState, + float32_t mu, + uint32_t blockSize); - /** - * @brief Instance structure for the Q15 LMS filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 LMS filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of coefficients in the filter. */ q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ q15_t mu; /**< step size that controls filter coefficient updates. */ uint32_t postShift; /**< bit shift applied to coefficients. */ - } arm_lms_instance_q15; +} arm_lms_instance_q15; - /** - * @brief Initialization function for the Q15 LMS filter. - * @param[in] S points to an instance of the Q15 LMS filter structure. - * @param[in] numTaps number of filter coefficients. - * @param[in] pCoeffs points to the coefficient buffer. - * @param[in] pState points to the state buffer. - * @param[in] mu step size that controls filter coefficient updates. - * @param[in] blockSize number of samples to process. - * @param[in] postShift bit shift applied to coefficients. - */ - void arm_lms_init_q15( - arm_lms_instance_q15 * S, - uint16_t numTaps, - q15_t * pCoeffs, - q15_t * pState, - q15_t mu, - uint32_t blockSize, - uint32_t postShift); +/** + * @brief Initialization function for the Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ +void arm_lms_init_q15( + arm_lms_instance_q15 *S, + uint16_t numTaps, + q15_t *pCoeffs, + q15_t *pState, + q15_t mu, + uint32_t blockSize, + uint32_t postShift); - /** - * @brief Processing function for Q15 LMS filter. - * @param[in] S points to an instance of the Q15 LMS filter structure. - * @param[in] pSrc points to the block of input data. - * @param[in] pRef points to the block of reference data. - * @param[out] pOut points to the block of output data. - * @param[out] pErr points to the block of error data. - * @param[in] blockSize number of samples to process. - */ - void arm_lms_q15( - const arm_lms_instance_q15 * S, - q15_t * pSrc, - q15_t * pRef, - q15_t * pOut, - q15_t * pErr, - uint32_t blockSize); +/** + * @brief Processing function for Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ +void arm_lms_q15( + const arm_lms_instance_q15 *S, + q15_t *pSrc, + q15_t *pRef, + q15_t *pOut, + q15_t *pErr, + uint32_t blockSize); - /** - * @brief Instance structure for the Q31 LMS filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 LMS filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of coefficients in the filter. */ q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ q31_t mu; /**< step size that controls filter coefficient updates. */ uint32_t postShift; /**< bit shift applied to coefficients. */ - } arm_lms_instance_q31; +} arm_lms_instance_q31; - /** - * @brief Processing function for Q31 LMS filter. - * @param[in] S points to an instance of the Q15 LMS filter structure. - * @param[in] pSrc points to the block of input data. - * @param[in] pRef points to the block of reference data. - * @param[out] pOut points to the block of output data. - * @param[out] pErr points to the block of error data. - * @param[in] blockSize number of samples to process. - */ - void arm_lms_q31( - const arm_lms_instance_q31 * S, - q31_t * pSrc, - q31_t * pRef, - q31_t * pOut, - q31_t * pErr, - uint32_t blockSize); +/** + * @brief Processing function for Q31 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ +void arm_lms_q31( + const arm_lms_instance_q31 *S, + q31_t *pSrc, + q31_t *pRef, + q31_t *pOut, + q31_t *pErr, + uint32_t blockSize); - /** - * @brief Initialization function for Q31 LMS filter. - * @param[in] S points to an instance of the Q31 LMS filter structure. - * @param[in] numTaps number of filter coefficients. - * @param[in] pCoeffs points to coefficient buffer. - * @param[in] pState points to state buffer. - * @param[in] mu step size that controls filter coefficient updates. - * @param[in] blockSize number of samples to process. - * @param[in] postShift bit shift applied to coefficients. - */ - void arm_lms_init_q31( - arm_lms_instance_q31 * S, - uint16_t numTaps, - q31_t * pCoeffs, - q31_t * pState, - q31_t mu, - uint32_t blockSize, - uint32_t postShift); +/** + * @brief Initialization function for Q31 LMS filter. + * @param[in] S points to an instance of the Q31 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ +void arm_lms_init_q31( + arm_lms_instance_q31 *S, + uint16_t numTaps, + q31_t *pCoeffs, + q31_t *pState, + q31_t mu, + uint32_t blockSize, + uint32_t postShift); - /** - * @brief Instance structure for the floating-point normalized LMS filter. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point normalized LMS filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of coefficients in the filter. */ float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ float32_t mu; /**< step size that control filter coefficient updates. */ float32_t energy; /**< saves previous frame energy. */ float32_t x0; /**< saves previous input sample. */ - } arm_lms_norm_instance_f32; +} arm_lms_norm_instance_f32; - /** - * @brief Processing function for floating-point normalized LMS filter. - * @param[in] S points to an instance of the floating-point normalized LMS filter structure. - * @param[in] pSrc points to the block of input data. - * @param[in] pRef points to the block of reference data. - * @param[out] pOut points to the block of output data. - * @param[out] pErr points to the block of error data. - * @param[in] blockSize number of samples to process. - */ - void arm_lms_norm_f32( - arm_lms_norm_instance_f32 * S, - float32_t * pSrc, - float32_t * pRef, - float32_t * pOut, - float32_t * pErr, - uint32_t blockSize); +/** + * @brief Processing function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ +void arm_lms_norm_f32( + arm_lms_norm_instance_f32 *S, + float32_t *pSrc, + float32_t *pRef, + float32_t *pOut, + float32_t *pErr, + uint32_t blockSize); - /** - * @brief Initialization function for floating-point normalized LMS filter. - * @param[in] S points to an instance of the floating-point LMS filter structure. - * @param[in] numTaps number of filter coefficients. - * @param[in] pCoeffs points to coefficient buffer. - * @param[in] pState points to state buffer. - * @param[in] mu step size that controls filter coefficient updates. - * @param[in] blockSize number of samples to process. - */ - void arm_lms_norm_init_f32( - arm_lms_norm_instance_f32 * S, - uint16_t numTaps, - float32_t * pCoeffs, - float32_t * pState, - float32_t mu, - uint32_t blockSize); +/** + * @brief Initialization function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ +void arm_lms_norm_init_f32( + arm_lms_norm_instance_f32 *S, + uint16_t numTaps, + float32_t *pCoeffs, + float32_t *pState, + float32_t mu, + uint32_t blockSize); - /** - * @brief Instance structure for the Q31 normalized LMS filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 normalized LMS filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of coefficients in the filter. */ q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ @@ -4256,52 +4256,52 @@ void arm_rfft_fast_f32( q31_t *recipTable; /**< points to the reciprocal initial value table. */ q31_t energy; /**< saves previous frame energy. */ q31_t x0; /**< saves previous input sample. */ - } arm_lms_norm_instance_q31; +} arm_lms_norm_instance_q31; - /** - * @brief Processing function for Q31 normalized LMS filter. - * @param[in] S points to an instance of the Q31 normalized LMS filter structure. - * @param[in] pSrc points to the block of input data. - * @param[in] pRef points to the block of reference data. - * @param[out] pOut points to the block of output data. - * @param[out] pErr points to the block of error data. - * @param[in] blockSize number of samples to process. - */ - void arm_lms_norm_q31( - arm_lms_norm_instance_q31 * S, - q31_t * pSrc, - q31_t * pRef, - q31_t * pOut, - q31_t * pErr, - uint32_t blockSize); +/** + * @brief Processing function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ +void arm_lms_norm_q31( + arm_lms_norm_instance_q31 *S, + q31_t *pSrc, + q31_t *pRef, + q31_t *pOut, + q31_t *pErr, + uint32_t blockSize); - /** - * @brief Initialization function for Q31 normalized LMS filter. - * @param[in] S points to an instance of the Q31 normalized LMS filter structure. - * @param[in] numTaps number of filter coefficients. - * @param[in] pCoeffs points to coefficient buffer. - * @param[in] pState points to state buffer. - * @param[in] mu step size that controls filter coefficient updates. - * @param[in] blockSize number of samples to process. - * @param[in] postShift bit shift applied to coefficients. - */ - void arm_lms_norm_init_q31( - arm_lms_norm_instance_q31 * S, - uint16_t numTaps, - q31_t * pCoeffs, - q31_t * pState, - q31_t mu, - uint32_t blockSize, - uint8_t postShift); +/** + * @brief Initialization function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ +void arm_lms_norm_init_q31( + arm_lms_norm_instance_q31 *S, + uint16_t numTaps, + q31_t *pCoeffs, + q31_t *pState, + q31_t mu, + uint32_t blockSize, + uint8_t postShift); - /** - * @brief Instance structure for the Q15 normalized LMS filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 normalized LMS filter. + */ +typedef struct +{ uint16_t numTaps; /**< Number of coefficients in the filter. */ q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ @@ -4310,578 +4310,578 @@ void arm_rfft_fast_f32( q15_t *recipTable; /**< Points to the reciprocal initial value table. */ q15_t energy; /**< saves previous frame energy. */ q15_t x0; /**< saves previous input sample. */ - } arm_lms_norm_instance_q15; +} arm_lms_norm_instance_q15; - /** - * @brief Processing function for Q15 normalized LMS filter. - * @param[in] S points to an instance of the Q15 normalized LMS filter structure. - * @param[in] pSrc points to the block of input data. - * @param[in] pRef points to the block of reference data. - * @param[out] pOut points to the block of output data. - * @param[out] pErr points to the block of error data. - * @param[in] blockSize number of samples to process. - */ - void arm_lms_norm_q15( - arm_lms_norm_instance_q15 * S, - q15_t * pSrc, - q15_t * pRef, - q15_t * pOut, - q15_t * pErr, - uint32_t blockSize); +/** + * @brief Processing function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ +void arm_lms_norm_q15( + arm_lms_norm_instance_q15 *S, + q15_t *pSrc, + q15_t *pRef, + q15_t *pOut, + q15_t *pErr, + uint32_t blockSize); - /** - * @brief Initialization function for Q15 normalized LMS filter. - * @param[in] S points to an instance of the Q15 normalized LMS filter structure. - * @param[in] numTaps number of filter coefficients. - * @param[in] pCoeffs points to coefficient buffer. - * @param[in] pState points to state buffer. - * @param[in] mu step size that controls filter coefficient updates. - * @param[in] blockSize number of samples to process. - * @param[in] postShift bit shift applied to coefficients. - */ - void arm_lms_norm_init_q15( - arm_lms_norm_instance_q15 * S, - uint16_t numTaps, - q15_t * pCoeffs, - q15_t * pState, - q15_t mu, - uint32_t blockSize, - uint8_t postShift); +/** + * @brief Initialization function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ +void arm_lms_norm_init_q15( + arm_lms_norm_instance_q15 *S, + uint16_t numTaps, + q15_t *pCoeffs, + q15_t *pState, + q15_t mu, + uint32_t blockSize, + uint8_t postShift); - /** - * @brief Correlation of floating-point sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. - */ - void arm_correlate_f32( - float32_t * pSrcA, - uint32_t srcALen, - float32_t * pSrcB, - uint32_t srcBLen, - float32_t * pDst); +/** + * @brief Correlation of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ +void arm_correlate_f32( + float32_t *pSrcA, + uint32_t srcALen, + float32_t *pSrcB, + uint32_t srcBLen, + float32_t *pDst); - /** - * @brief Correlation of Q15 sequences - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. - * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. - */ - void arm_correlate_opt_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst, - q15_t * pScratch); +/** +* @brief Correlation of Q15 sequences +* @param[in] pSrcA points to the first input sequence. +* @param[in] srcALen length of the first input sequence. +* @param[in] pSrcB points to the second input sequence. +* @param[in] srcBLen length of the second input sequence. +* @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. +* @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. +*/ +void arm_correlate_opt_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst, + q15_t *pScratch); - /** - * @brief Correlation of Q15 sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. - */ +/** + * @brief Correlation of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ - void arm_correlate_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst); +void arm_correlate_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst); - /** - * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. - */ +/** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ - void arm_correlate_fast_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst); +void arm_correlate_fast_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst); - /** - * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. - * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. - */ - void arm_correlate_fast_opt_q15( - q15_t * pSrcA, - uint32_t srcALen, - q15_t * pSrcB, - uint32_t srcBLen, - q15_t * pDst, - q15_t * pScratch); +/** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ +void arm_correlate_fast_opt_q15( + q15_t *pSrcA, + uint32_t srcALen, + q15_t *pSrcB, + uint32_t srcBLen, + q15_t *pDst, + q15_t *pScratch); - /** - * @brief Correlation of Q31 sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. - */ - void arm_correlate_q31( - q31_t * pSrcA, - uint32_t srcALen, - q31_t * pSrcB, - uint32_t srcBLen, - q31_t * pDst); +/** + * @brief Correlation of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ +void arm_correlate_q31( + q31_t *pSrcA, + uint32_t srcALen, + q31_t *pSrcB, + uint32_t srcBLen, + q31_t *pDst); - /** - * @brief Correlation of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. - */ - void arm_correlate_fast_q31( - q31_t * pSrcA, - uint32_t srcALen, - q31_t * pSrcB, - uint32_t srcBLen, - q31_t * pDst); +/** + * @brief Correlation of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ +void arm_correlate_fast_q31( + q31_t *pSrcA, + uint32_t srcALen, + q31_t *pSrcB, + uint32_t srcBLen, + q31_t *pDst); - /** - * @brief Correlation of Q7 sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. - * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. - * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). - */ - void arm_correlate_opt_q7( - q7_t * pSrcA, - uint32_t srcALen, - q7_t * pSrcB, - uint32_t srcBLen, - q7_t * pDst, - q15_t * pScratch1, - q15_t * pScratch2); +/** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ +void arm_correlate_opt_q7( + q7_t *pSrcA, + uint32_t srcALen, + q7_t *pSrcB, + uint32_t srcBLen, + q7_t *pDst, + q15_t *pScratch1, + q15_t *pScratch2); - /** - * @brief Correlation of Q7 sequences. - * @param[in] pSrcA points to the first input sequence. - * @param[in] srcALen length of the first input sequence. - * @param[in] pSrcB points to the second input sequence. - * @param[in] srcBLen length of the second input sequence. - * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. - */ - void arm_correlate_q7( - q7_t * pSrcA, - uint32_t srcALen, - q7_t * pSrcB, - uint32_t srcBLen, - q7_t * pDst); +/** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ +void arm_correlate_q7( + q7_t *pSrcA, + uint32_t srcALen, + q7_t *pSrcB, + uint32_t srcBLen, + q7_t *pDst); - /** - * @brief Instance structure for the floating-point sparse FIR filter. - */ - typedef struct - { +/** + * @brief Instance structure for the floating-point sparse FIR filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of coefficients in the filter. */ uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ float32_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ - } arm_fir_sparse_instance_f32; +} arm_fir_sparse_instance_f32; - /** - * @brief Instance structure for the Q31 sparse FIR filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q31 sparse FIR filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of coefficients in the filter. */ uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ q31_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ - } arm_fir_sparse_instance_q31; +} arm_fir_sparse_instance_q31; - /** - * @brief Instance structure for the Q15 sparse FIR filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q15 sparse FIR filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of coefficients in the filter. */ uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ q15_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ - } arm_fir_sparse_instance_q15; +} arm_fir_sparse_instance_q15; - /** - * @brief Instance structure for the Q7 sparse FIR filter. - */ - typedef struct - { +/** + * @brief Instance structure for the Q7 sparse FIR filter. + */ +typedef struct +{ uint16_t numTaps; /**< number of coefficients in the filter. */ uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ q7_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ - } arm_fir_sparse_instance_q7; +} arm_fir_sparse_instance_q7; - /** - * @brief Processing function for the floating-point sparse FIR filter. - * @param[in] S points to an instance of the floating-point sparse FIR structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] pScratchIn points to a temporary buffer of size blockSize. - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_sparse_f32( - arm_fir_sparse_instance_f32 * S, - float32_t * pSrc, - float32_t * pDst, - float32_t * pScratchIn, - uint32_t blockSize); +/** + * @brief Processing function for the floating-point sparse FIR filter. + * @param[in] S points to an instance of the floating-point sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_sparse_f32( + arm_fir_sparse_instance_f32 *S, + float32_t *pSrc, + float32_t *pDst, + float32_t *pScratchIn, + uint32_t blockSize); - /** - * @brief Initialization function for the floating-point sparse FIR filter. - * @param[in,out] S points to an instance of the floating-point sparse FIR structure. - * @param[in] numTaps number of nonzero coefficients in the filter. - * @param[in] pCoeffs points to the array of filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] pTapDelay points to the array of offset times. - * @param[in] maxDelay maximum offset time supported. - * @param[in] blockSize number of samples that will be processed per block. - */ - void arm_fir_sparse_init_f32( - arm_fir_sparse_instance_f32 * S, - uint16_t numTaps, - float32_t * pCoeffs, - float32_t * pState, - int32_t * pTapDelay, - uint16_t maxDelay, - uint32_t blockSize); +/** + * @brief Initialization function for the floating-point sparse FIR filter. + * @param[in,out] S points to an instance of the floating-point sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ +void arm_fir_sparse_init_f32( + arm_fir_sparse_instance_f32 *S, + uint16_t numTaps, + float32_t *pCoeffs, + float32_t *pState, + int32_t *pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); - /** - * @brief Processing function for the Q31 sparse FIR filter. - * @param[in] S points to an instance of the Q31 sparse FIR structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] pScratchIn points to a temporary buffer of size blockSize. - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_sparse_q31( - arm_fir_sparse_instance_q31 * S, - q31_t * pSrc, - q31_t * pDst, - q31_t * pScratchIn, - uint32_t blockSize); +/** + * @brief Processing function for the Q31 sparse FIR filter. + * @param[in] S points to an instance of the Q31 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_sparse_q31( + arm_fir_sparse_instance_q31 *S, + q31_t *pSrc, + q31_t *pDst, + q31_t *pScratchIn, + uint32_t blockSize); - /** - * @brief Initialization function for the Q31 sparse FIR filter. - * @param[in,out] S points to an instance of the Q31 sparse FIR structure. - * @param[in] numTaps number of nonzero coefficients in the filter. - * @param[in] pCoeffs points to the array of filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] pTapDelay points to the array of offset times. - * @param[in] maxDelay maximum offset time supported. - * @param[in] blockSize number of samples that will be processed per block. - */ - void arm_fir_sparse_init_q31( - arm_fir_sparse_instance_q31 * S, - uint16_t numTaps, - q31_t * pCoeffs, - q31_t * pState, - int32_t * pTapDelay, - uint16_t maxDelay, - uint32_t blockSize); +/** + * @brief Initialization function for the Q31 sparse FIR filter. + * @param[in,out] S points to an instance of the Q31 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ +void arm_fir_sparse_init_q31( + arm_fir_sparse_instance_q31 *S, + uint16_t numTaps, + q31_t *pCoeffs, + q31_t *pState, + int32_t *pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); - /** - * @brief Processing function for the Q15 sparse FIR filter. - * @param[in] S points to an instance of the Q15 sparse FIR structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] pScratchIn points to a temporary buffer of size blockSize. - * @param[in] pScratchOut points to a temporary buffer of size blockSize. - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_sparse_q15( - arm_fir_sparse_instance_q15 * S, - q15_t * pSrc, - q15_t * pDst, - q15_t * pScratchIn, - q31_t * pScratchOut, - uint32_t blockSize); +/** + * @brief Processing function for the Q15 sparse FIR filter. + * @param[in] S points to an instance of the Q15 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_sparse_q15( + arm_fir_sparse_instance_q15 *S, + q15_t *pSrc, + q15_t *pDst, + q15_t *pScratchIn, + q31_t *pScratchOut, + uint32_t blockSize); - /** - * @brief Initialization function for the Q15 sparse FIR filter. - * @param[in,out] S points to an instance of the Q15 sparse FIR structure. - * @param[in] numTaps number of nonzero coefficients in the filter. - * @param[in] pCoeffs points to the array of filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] pTapDelay points to the array of offset times. - * @param[in] maxDelay maximum offset time supported. - * @param[in] blockSize number of samples that will be processed per block. - */ - void arm_fir_sparse_init_q15( - arm_fir_sparse_instance_q15 * S, - uint16_t numTaps, - q15_t * pCoeffs, - q15_t * pState, - int32_t * pTapDelay, - uint16_t maxDelay, - uint32_t blockSize); +/** + * @brief Initialization function for the Q15 sparse FIR filter. + * @param[in,out] S points to an instance of the Q15 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ +void arm_fir_sparse_init_q15( + arm_fir_sparse_instance_q15 *S, + uint16_t numTaps, + q15_t *pCoeffs, + q15_t *pState, + int32_t *pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); - /** - * @brief Processing function for the Q7 sparse FIR filter. - * @param[in] S points to an instance of the Q7 sparse FIR structure. - * @param[in] pSrc points to the block of input data. - * @param[out] pDst points to the block of output data - * @param[in] pScratchIn points to a temporary buffer of size blockSize. - * @param[in] pScratchOut points to a temporary buffer of size blockSize. - * @param[in] blockSize number of input samples to process per call. - */ - void arm_fir_sparse_q7( - arm_fir_sparse_instance_q7 * S, - q7_t * pSrc, - q7_t * pDst, - q7_t * pScratchIn, - q31_t * pScratchOut, - uint32_t blockSize); +/** + * @brief Processing function for the Q7 sparse FIR filter. + * @param[in] S points to an instance of the Q7 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ +void arm_fir_sparse_q7( + arm_fir_sparse_instance_q7 *S, + q7_t *pSrc, + q7_t *pDst, + q7_t *pScratchIn, + q31_t *pScratchOut, + uint32_t blockSize); - /** - * @brief Initialization function for the Q7 sparse FIR filter. - * @param[in,out] S points to an instance of the Q7 sparse FIR structure. - * @param[in] numTaps number of nonzero coefficients in the filter. - * @param[in] pCoeffs points to the array of filter coefficients. - * @param[in] pState points to the state buffer. - * @param[in] pTapDelay points to the array of offset times. - * @param[in] maxDelay maximum offset time supported. - * @param[in] blockSize number of samples that will be processed per block. - */ - void arm_fir_sparse_init_q7( - arm_fir_sparse_instance_q7 * S, - uint16_t numTaps, - q7_t * pCoeffs, - q7_t * pState, - int32_t * pTapDelay, - uint16_t maxDelay, - uint32_t blockSize); +/** + * @brief Initialization function for the Q7 sparse FIR filter. + * @param[in,out] S points to an instance of the Q7 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ +void arm_fir_sparse_init_q7( + arm_fir_sparse_instance_q7 *S, + uint16_t numTaps, + q7_t *pCoeffs, + q7_t *pState, + int32_t *pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); - /** - * @brief Floating-point sin_cos function. - * @param[in] theta input value in degrees - * @param[out] pSinVal points to the processed sine output. - * @param[out] pCosVal points to the processed cos output. - */ - void arm_sin_cos_f32( - float32_t theta, - float32_t * pSinVal, - float32_t * pCosVal); +/** + * @brief Floating-point sin_cos function. + * @param[in] theta input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cos output. + */ +void arm_sin_cos_f32( + float32_t theta, + float32_t *pSinVal, + float32_t *pCosVal); - /** - * @brief Q31 sin_cos function. - * @param[in] theta scaled input value in degrees - * @param[out] pSinVal points to the processed sine output. - * @param[out] pCosVal points to the processed cosine output. - */ - void arm_sin_cos_q31( - q31_t theta, - q31_t * pSinVal, - q31_t * pCosVal); +/** + * @brief Q31 sin_cos function. + * @param[in] theta scaled input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cosine output. + */ +void arm_sin_cos_q31( + q31_t theta, + q31_t *pSinVal, + q31_t *pCosVal); - /** - * @brief Floating-point complex conjugate. - * @param[in] pSrc points to the input vector - * @param[out] pDst points to the output vector - * @param[in] numSamples number of complex samples in each vector - */ - void arm_cmplx_conj_f32( - float32_t * pSrc, - float32_t * pDst, - uint32_t numSamples); +/** + * @brief Floating-point complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ +void arm_cmplx_conj_f32( + float32_t *pSrc, + float32_t *pDst, + uint32_t numSamples); - /** - * @brief Q31 complex conjugate. - * @param[in] pSrc points to the input vector - * @param[out] pDst points to the output vector - * @param[in] numSamples number of complex samples in each vector - */ - void arm_cmplx_conj_q31( - q31_t * pSrc, - q31_t * pDst, - uint32_t numSamples); +/** + * @brief Q31 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ +void arm_cmplx_conj_q31( + q31_t *pSrc, + q31_t *pDst, + uint32_t numSamples); - /** - * @brief Q15 complex conjugate. - * @param[in] pSrc points to the input vector - * @param[out] pDst points to the output vector - * @param[in] numSamples number of complex samples in each vector - */ - void arm_cmplx_conj_q15( - q15_t * pSrc, - q15_t * pDst, - uint32_t numSamples); +/** + * @brief Q15 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ +void arm_cmplx_conj_q15( + q15_t *pSrc, + q15_t *pDst, + uint32_t numSamples); - /** - * @brief Floating-point complex magnitude squared - * @param[in] pSrc points to the complex input vector - * @param[out] pDst points to the real output vector - * @param[in] numSamples number of complex samples in the input vector - */ - void arm_cmplx_mag_squared_f32( - float32_t * pSrc, - float32_t * pDst, - uint32_t numSamples); +/** + * @brief Floating-point complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ +void arm_cmplx_mag_squared_f32( + float32_t *pSrc, + float32_t *pDst, + uint32_t numSamples); - /** - * @brief Q31 complex magnitude squared - * @param[in] pSrc points to the complex input vector - * @param[out] pDst points to the real output vector - * @param[in] numSamples number of complex samples in the input vector - */ - void arm_cmplx_mag_squared_q31( - q31_t * pSrc, - q31_t * pDst, - uint32_t numSamples); +/** + * @brief Q31 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ +void arm_cmplx_mag_squared_q31( + q31_t *pSrc, + q31_t *pDst, + uint32_t numSamples); - /** - * @brief Q15 complex magnitude squared - * @param[in] pSrc points to the complex input vector - * @param[out] pDst points to the real output vector - * @param[in] numSamples number of complex samples in the input vector - */ - void arm_cmplx_mag_squared_q15( - q15_t * pSrc, - q15_t * pDst, - uint32_t numSamples); +/** + * @brief Q15 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ +void arm_cmplx_mag_squared_q15( + q15_t *pSrc, + q15_t *pDst, + uint32_t numSamples); - /** - * @ingroup groupController - */ +/** + * @ingroup groupController + */ - /** - * @defgroup PID PID Motor Control - * - * A Proportional Integral Derivative (PID) controller is a generic feedback control - * loop mechanism widely used in industrial control systems. - * A PID controller is the most commonly used type of feedback controller. - * - * This set of functions implements (PID) controllers - * for Q15, Q31, and floating-point data types. The functions operate on a single sample - * of data and each call to the function returns a single processed value. - * S points to an instance of the PID control data structure. in - * is the input sample value. The functions return the output value. - * - * \par Algorithm: - *
-   *    y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]
-   *    A0 = Kp + Ki + Kd
-   *    A1 = (-Kp ) - (2 * Kd )
-   *    A2 = Kd  
- * - * \par - * where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant - * - * \par - * \image html PID.gif "Proportional Integral Derivative Controller" - * - * \par - * The PID controller calculates an "error" value as the difference between - * the measured output and the reference input. - * The controller attempts to minimize the error by adjusting the process control inputs. - * The proportional value determines the reaction to the current error, - * the integral value determines the reaction based on the sum of recent errors, - * and the derivative value determines the reaction based on the rate at which the error has been changing. - * - * \par Instance Structure - * The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure. - * A separate instance structure must be defined for each PID Controller. - * There are separate instance structure declarations for each of the 3 supported data types. - * - * \par Reset Functions - * There is also an associated reset function for each data type which clears the state array. - * - * \par Initialization Functions - * There is also an associated initialization function for each data type. - * The initialization function performs the following operations: - * - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains. - * - Zeros out the values in the state buffer. - * - * \par - * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function. - * - * \par Fixed-Point Behavior - * Care must be taken when using the fixed-point versions of the PID Controller functions. - * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. - * Refer to the function specific documentation below for usage guidelines. - */ +/** + * @defgroup PID PID Motor Control + * + * A Proportional Integral Derivative (PID) controller is a generic feedback control + * loop mechanism widely used in industrial control systems. + * A PID controller is the most commonly used type of feedback controller. + * + * This set of functions implements (PID) controllers + * for Q15, Q31, and floating-point data types. The functions operate on a single sample + * of data and each call to the function returns a single processed value. + * S points to an instance of the PID control data structure. in + * is the input sample value. The functions return the output value. + * + * \par Algorithm: + *
+ *    y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]
+ *    A0 = Kp + Ki + Kd
+ *    A1 = (-Kp ) - (2 * Kd )
+ *    A2 = Kd  
+ * + * \par + * where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant + * + * \par + * \image html PID.gif "Proportional Integral Derivative Controller" + * + * \par + * The PID controller calculates an "error" value as the difference between + * the measured output and the reference input. + * The controller attempts to minimize the error by adjusting the process control inputs. + * The proportional value determines the reaction to the current error, + * the integral value determines the reaction based on the sum of recent errors, + * and the derivative value determines the reaction based on the rate at which the error has been changing. + * + * \par Instance Structure + * The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure. + * A separate instance structure must be defined for each PID Controller. + * There are separate instance structure declarations for each of the 3 supported data types. + * + * \par Reset Functions + * There is also an associated reset function for each data type which clears the state array. + * + * \par Initialization Functions + * There is also an associated initialization function for each data type. + * The initialization function performs the following operations: + * - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains. + * - Zeros out the values in the state buffer. + * + * \par + * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function. + * + * \par Fixed-Point Behavior + * Care must be taken when using the fixed-point versions of the PID Controller functions. + * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ - /** - * @addtogroup PID - * @{ - */ +/** + * @addtogroup PID + * @{ + */ - /** - * @brief Process function for the floating-point PID Control. - * @param[in,out] S is an instance of the floating-point PID Control structure - * @param[in] in input sample to process - * @return out processed output sample. - */ - CMSIS_INLINE __STATIC_INLINE float32_t arm_pid_f32( - arm_pid_instance_f32 * S, - float32_t in) - { +/** + * @brief Process function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + */ +CMSIS_INLINE __STATIC_INLINE float32_t arm_pid_f32( + arm_pid_instance_f32 *S, + float32_t in) +{ float32_t out; /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2] */ out = (S->A0 * in) + - (S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]); + (S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]); /* Update state */ S->state[1] = S->state[0]; @@ -4891,26 +4891,26 @@ void arm_rfft_fast_f32( /* return to application */ return (out); - } +} - /** - * @brief Process function for the Q31 PID Control. - * @param[in,out] S points to an instance of the Q31 PID Control structure - * @param[in] in input sample to process - * @return out processed output sample. - * - * Scaling and Overflow Behavior: - * \par - * The function is implemented using an internal 64-bit accumulator. - * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. - * Thus, if the accumulator result overflows it wraps around rather than clip. - * In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions. - * After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format. - */ - CMSIS_INLINE __STATIC_INLINE q31_t arm_pid_q31( - arm_pid_instance_q31 * S, - q31_t in) - { +/** + * @brief Process function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 64-bit accumulator. + * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. + * Thus, if the accumulator result overflows it wraps around rather than clip. + * In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions. + * After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format. + */ +CMSIS_INLINE __STATIC_INLINE q31_t arm_pid_q31( + arm_pid_instance_q31 *S, + q31_t in) +{ q63_t acc; q31_t out; @@ -4924,7 +4924,7 @@ void arm_rfft_fast_f32( acc += (q63_t) S->A2 * S->state[1]; /* convert output to 1.31 format to add y[n-1] */ - out = (q31_t) (acc >> 31u); + out = (q31_t)(acc >> 31u); /* out += y[n-1] */ out += S->state[2]; @@ -4936,28 +4936,28 @@ void arm_rfft_fast_f32( /* return to application */ return (out); - } +} - /** - * @brief Process function for the Q15 PID Control. - * @param[in,out] S points to an instance of the Q15 PID Control structure - * @param[in] in input sample to process - * @return out processed output sample. - * - * Scaling and Overflow Behavior: - * \par - * The function is implemented using a 64-bit internal accumulator. - * Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result. - * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. - * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. - * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. - * Lastly, the accumulator is saturated to yield a result in 1.15 format. - */ - CMSIS_INLINE __STATIC_INLINE q15_t arm_pid_q15( - arm_pid_instance_q15 * S, - q15_t in) - { +/** + * @brief Process function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using a 64-bit internal accumulator. + * Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result. + * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. + * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. + * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. + * Lastly, the accumulator is saturated to yield a result in 1.15 format. + */ +CMSIS_INLINE __STATIC_INLINE q15_t arm_pid_q15( + arm_pid_instance_q15 *S, + q15_t in) +{ q63_t acc; q15_t out; @@ -4971,7 +4971,7 @@ void arm_rfft_fast_f32( /* acc += A1 * x[n-1] + A2 * x[n-2] */ vstate = __SIMD32_CONST(S->state); - acc = (q63_t)__SMLALD((uint32_t)S->A1, (uint32_t)*vstate, (uint64_t)acc); + acc = (q63_t)__SMLALD((uint32_t)S->A1, (uint32_t) * vstate, (uint64_t)acc); #else /* acc = A0 * x[n] */ acc = ((q31_t) S->A0) * in; @@ -4985,7 +4985,7 @@ void arm_rfft_fast_f32( acc += (q31_t) S->state[2] << 15; /* saturate the output */ - out = (q15_t) (__SSAT((acc >> 15), 16)); + out = (q15_t)(__SSAT((acc >> 15), 16)); /* Update state */ S->state[1] = S->state[0]; @@ -4994,527 +4994,527 @@ void arm_rfft_fast_f32( /* return to application */ return (out); - } +} - /** - * @} end of PID group - */ +/** + * @} end of PID group + */ - /** - * @brief Floating-point matrix inverse. - * @param[in] src points to the instance of the input floating-point matrix structure. - * @param[out] dst points to the instance of the output floating-point matrix structure. - * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. - * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. - */ - arm_status arm_mat_inverse_f32( - const arm_matrix_instance_f32 * src, - arm_matrix_instance_f32 * dst); +/** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ +arm_status arm_mat_inverse_f32( + const arm_matrix_instance_f32 *src, + arm_matrix_instance_f32 *dst); - /** - * @brief Floating-point matrix inverse. - * @param[in] src points to the instance of the input floating-point matrix structure. - * @param[out] dst points to the instance of the output floating-point matrix structure. - * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. - * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. - */ - arm_status arm_mat_inverse_f64( - const arm_matrix_instance_f64 * src, - arm_matrix_instance_f64 * dst); +/** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ +arm_status arm_mat_inverse_f64( + const arm_matrix_instance_f64 *src, + arm_matrix_instance_f64 *dst); - /** - * @ingroup groupController - */ +/** + * @ingroup groupController + */ - /** - * @defgroup clarke Vector Clarke Transform - * Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector. - * Generally the Clarke transform uses three-phase currents Ia, Ib and Ic to calculate currents - * in the two-phase orthogonal stator axis Ialpha and Ibeta. - * When Ialpha is superposed with Ia as shown in the figure below - * \image html clarke.gif Stator current space vector and its components in (a,b). - * and Ia + Ib + Ic = 0, in this condition Ialpha and Ibeta - * can be calculated using only Ia and Ib. - * - * The function operates on a single sample of data and each call to the function returns the processed output. - * The library provides separate functions for Q31 and floating-point data types. - * \par Algorithm - * \image html clarkeFormula.gif - * where Ia and Ib are the instantaneous stator phases and - * pIalpha and pIbeta are the two coordinates of time invariant vector. - * \par Fixed-Point Behavior - * Care must be taken when using the Q31 version of the Clarke transform. - * In particular, the overflow and saturation behavior of the accumulator used must be considered. - * Refer to the function specific documentation below for usage guidelines. - */ +/** + * @defgroup clarke Vector Clarke Transform + * Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector. + * Generally the Clarke transform uses three-phase currents Ia, Ib and Ic to calculate currents + * in the two-phase orthogonal stator axis Ialpha and Ibeta. + * When Ialpha is superposed with Ia as shown in the figure below + * \image html clarke.gif Stator current space vector and its components in (a,b). + * and Ia + Ib + Ic = 0, in this condition Ialpha and Ibeta + * can be calculated using only Ia and Ib. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeFormula.gif + * where Ia and Ib are the instantaneous stator phases and + * pIalpha and pIbeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ - /** - * @addtogroup clarke - * @{ - */ +/** + * @addtogroup clarke + * @{ + */ - /** - * - * @brief Floating-point Clarke transform - * @param[in] Ia input three-phase coordinate a - * @param[in] Ib input three-phase coordinate b - * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha - * @param[out] pIbeta points to output two-phase orthogonal vector axis beta - */ - CMSIS_INLINE __STATIC_INLINE void arm_clarke_f32( - float32_t Ia, - float32_t Ib, - float32_t * pIalpha, - float32_t * pIbeta) - { +/** + * + * @brief Floating-point Clarke transform + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + */ +CMSIS_INLINE __STATIC_INLINE void arm_clarke_f32( + float32_t Ia, + float32_t Ib, + float32_t *pIalpha, + float32_t *pIbeta) +{ /* Calculate pIalpha using the equation, pIalpha = Ia */ *pIalpha = Ia; /* Calculate pIbeta using the equation, pIbeta = (1/sqrt(3)) * Ia + (2/sqrt(3)) * Ib */ *pIbeta = ((float32_t) 0.57735026919 * Ia + (float32_t) 1.15470053838 * Ib); - } +} - /** - * @brief Clarke transform for Q31 version - * @param[in] Ia input three-phase coordinate a - * @param[in] Ib input three-phase coordinate b - * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha - * @param[out] pIbeta points to output two-phase orthogonal vector axis beta - * - * Scaling and Overflow Behavior: - * \par - * The function is implemented using an internal 32-bit accumulator. - * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. - * There is saturation on the addition, hence there is no risk of overflow. - */ - CMSIS_INLINE __STATIC_INLINE void arm_clarke_q31( - q31_t Ia, - q31_t Ib, - q31_t * pIalpha, - q31_t * pIbeta) - { +/** + * @brief Clarke transform for Q31 version + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ +CMSIS_INLINE __STATIC_INLINE void arm_clarke_q31( + q31_t Ia, + q31_t Ib, + q31_t *pIalpha, + q31_t *pIbeta) +{ q31_t product1, product2; /* Temporary variables used to store intermediate results */ /* Calculating pIalpha from Ia by equation pIalpha = Ia */ *pIalpha = Ia; /* Intermediate product is calculated by (1/(sqrt(3)) * Ia) */ - product1 = (q31_t) (((q63_t) Ia * 0x24F34E8B) >> 30); + product1 = (q31_t)(((q63_t) Ia * 0x24F34E8B) >> 30); /* Intermediate product is calculated by (2/sqrt(3) * Ib) */ - product2 = (q31_t) (((q63_t) Ib * 0x49E69D16) >> 30); + product2 = (q31_t)(((q63_t) Ib * 0x49E69D16) >> 30); /* pIbeta is calculated by adding the intermediate products */ *pIbeta = __QADD(product1, product2); - } +} - /** - * @} end of clarke group - */ +/** + * @} end of clarke group + */ - /** - * @brief Converts the elements of the Q7 vector to Q31 vector. - * @param[in] pSrc input pointer - * @param[out] pDst output pointer - * @param[in] blockSize number of samples to process - */ - void arm_q7_to_q31( - q7_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the Q7 vector to Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ +void arm_q7_to_q31( + q7_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @ingroup groupController - */ +/** + * @ingroup groupController + */ - /** - * @defgroup inv_clarke Vector Inverse Clarke Transform - * Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases. - * - * The function operates on a single sample of data and each call to the function returns the processed output. - * The library provides separate functions for Q31 and floating-point data types. - * \par Algorithm - * \image html clarkeInvFormula.gif - * where pIa and pIb are the instantaneous stator phases and - * Ialpha and Ibeta are the two coordinates of time invariant vector. - * \par Fixed-Point Behavior - * Care must be taken when using the Q31 version of the Clarke transform. - * In particular, the overflow and saturation behavior of the accumulator used must be considered. - * Refer to the function specific documentation below for usage guidelines. - */ +/** + * @defgroup inv_clarke Vector Inverse Clarke Transform + * Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeInvFormula.gif + * where pIa and pIb are the instantaneous stator phases and + * Ialpha and Ibeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ - /** - * @addtogroup inv_clarke - * @{ - */ +/** + * @addtogroup inv_clarke + * @{ + */ - /** - * @brief Floating-point Inverse Clarke transform - * @param[in] Ialpha input two-phase orthogonal vector axis alpha - * @param[in] Ibeta input two-phase orthogonal vector axis beta - * @param[out] pIa points to output three-phase coordinate a - * @param[out] pIb points to output three-phase coordinate b - */ - CMSIS_INLINE __STATIC_INLINE void arm_inv_clarke_f32( - float32_t Ialpha, - float32_t Ibeta, - float32_t * pIa, - float32_t * pIb) - { +/** +* @brief Floating-point Inverse Clarke transform +* @param[in] Ialpha input two-phase orthogonal vector axis alpha +* @param[in] Ibeta input two-phase orthogonal vector axis beta +* @param[out] pIa points to output three-phase coordinate a +* @param[out] pIb points to output three-phase coordinate b +*/ +CMSIS_INLINE __STATIC_INLINE void arm_inv_clarke_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t *pIa, + float32_t *pIb) +{ /* Calculating pIa from Ialpha by equation pIa = Ialpha */ *pIa = Ialpha; /* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */ *pIb = -0.5f * Ialpha + 0.8660254039f * Ibeta; - } +} - /** - * @brief Inverse Clarke transform for Q31 version - * @param[in] Ialpha input two-phase orthogonal vector axis alpha - * @param[in] Ibeta input two-phase orthogonal vector axis beta - * @param[out] pIa points to output three-phase coordinate a - * @param[out] pIb points to output three-phase coordinate b - * - * Scaling and Overflow Behavior: - * \par - * The function is implemented using an internal 32-bit accumulator. - * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. - * There is saturation on the subtraction, hence there is no risk of overflow. - */ - CMSIS_INLINE __STATIC_INLINE void arm_inv_clarke_q31( - q31_t Ialpha, - q31_t Ibeta, - q31_t * pIa, - q31_t * pIb) - { +/** + * @brief Inverse Clarke transform for Q31 version + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the subtraction, hence there is no risk of overflow. + */ +CMSIS_INLINE __STATIC_INLINE void arm_inv_clarke_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t *pIa, + q31_t *pIb) +{ q31_t product1, product2; /* Temporary variables used to store intermediate results */ /* Calculating pIa from Ialpha by equation pIa = Ialpha */ *pIa = Ialpha; /* Intermediate product is calculated by (1/(2*sqrt(3)) * Ia) */ - product1 = (q31_t) (((q63_t) (Ialpha) * (0x40000000)) >> 31); + product1 = (q31_t)(((q63_t)(Ialpha) * (0x40000000)) >> 31); /* Intermediate product is calculated by (1/sqrt(3) * pIb) */ - product2 = (q31_t) (((q63_t) (Ibeta) * (0x6ED9EBA1)) >> 31); + product2 = (q31_t)(((q63_t)(Ibeta) * (0x6ED9EBA1)) >> 31); /* pIb is calculated by subtracting the products */ *pIb = __QSUB(product2, product1); - } +} - /** - * @} end of inv_clarke group - */ +/** + * @} end of inv_clarke group + */ - /** - * @brief Converts the elements of the Q7 vector to Q15 vector. - * @param[in] pSrc input pointer - * @param[out] pDst output pointer - * @param[in] blockSize number of samples to process - */ - void arm_q7_to_q15( - q7_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the Q7 vector to Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ +void arm_q7_to_q15( + q7_t *pSrc, + q15_t *pDst, + uint32_t blockSize); - /** - * @ingroup groupController - */ +/** + * @ingroup groupController + */ - /** - * @defgroup park Vector Park Transform - * - * Forward Park transform converts the input two-coordinate vector to flux and torque components. - * The Park transform can be used to realize the transformation of the Ialpha and the Ibeta currents - * from the stationary to the moving reference frame and control the spatial relationship between - * the stator vector current and rotor flux vector. - * If we consider the d axis aligned with the rotor flux, the diagram below shows the - * current vector and the relationship from the two reference frames: - * \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame" - * - * The function operates on a single sample of data and each call to the function returns the processed output. - * The library provides separate functions for Q31 and floating-point data types. - * \par Algorithm - * \image html parkFormula.gif - * where Ialpha and Ibeta are the stator vector components, - * pId and pIq are rotor vector components and cosVal and sinVal are the - * cosine and sine values of theta (rotor flux position). - * \par Fixed-Point Behavior - * Care must be taken when using the Q31 version of the Park transform. - * In particular, the overflow and saturation behavior of the accumulator used must be considered. - * Refer to the function specific documentation below for usage guidelines. - */ +/** + * @defgroup park Vector Park Transform + * + * Forward Park transform converts the input two-coordinate vector to flux and torque components. + * The Park transform can be used to realize the transformation of the Ialpha and the Ibeta currents + * from the stationary to the moving reference frame and control the spatial relationship between + * the stator vector current and rotor flux vector. + * If we consider the d axis aligned with the rotor flux, the diagram below shows the + * current vector and the relationship from the two reference frames: + * \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame" + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkFormula.gif + * where Ialpha and Ibeta are the stator vector components, + * pId and pIq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ - /** - * @addtogroup park - * @{ - */ +/** + * @addtogroup park + * @{ + */ - /** - * @brief Floating-point Park transform - * @param[in] Ialpha input two-phase vector coordinate alpha - * @param[in] Ibeta input two-phase vector coordinate beta - * @param[out] pId points to output rotor reference frame d - * @param[out] pIq points to output rotor reference frame q - * @param[in] sinVal sine value of rotation angle theta - * @param[in] cosVal cosine value of rotation angle theta - * - * The function implements the forward Park transform. - * - */ - CMSIS_INLINE __STATIC_INLINE void arm_park_f32( - float32_t Ialpha, - float32_t Ibeta, - float32_t * pId, - float32_t * pIq, - float32_t sinVal, - float32_t cosVal) - { +/** + * @brief Floating-point Park transform + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * The function implements the forward Park transform. + * + */ +CMSIS_INLINE __STATIC_INLINE void arm_park_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t *pId, + float32_t *pIq, + float32_t sinVal, + float32_t cosVal) +{ /* Calculate pId using the equation, pId = Ialpha * cosVal + Ibeta * sinVal */ *pId = Ialpha * cosVal + Ibeta * sinVal; /* Calculate pIq using the equation, pIq = - Ialpha * sinVal + Ibeta * cosVal */ *pIq = -Ialpha * sinVal + Ibeta * cosVal; - } +} - /** - * @brief Park transform for Q31 version - * @param[in] Ialpha input two-phase vector coordinate alpha - * @param[in] Ibeta input two-phase vector coordinate beta - * @param[out] pId points to output rotor reference frame d - * @param[out] pIq points to output rotor reference frame q - * @param[in] sinVal sine value of rotation angle theta - * @param[in] cosVal cosine value of rotation angle theta - * - * Scaling and Overflow Behavior: - * \par - * The function is implemented using an internal 32-bit accumulator. - * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. - * There is saturation on the addition and subtraction, hence there is no risk of overflow. - */ - CMSIS_INLINE __STATIC_INLINE void arm_park_q31( - q31_t Ialpha, - q31_t Ibeta, - q31_t * pId, - q31_t * pIq, - q31_t sinVal, - q31_t cosVal) - { +/** + * @brief Park transform for Q31 version + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition and subtraction, hence there is no risk of overflow. + */ +CMSIS_INLINE __STATIC_INLINE void arm_park_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t *pId, + q31_t *pIq, + q31_t sinVal, + q31_t cosVal) +{ q31_t product1, product2; /* Temporary variables used to store intermediate results */ q31_t product3, product4; /* Temporary variables used to store intermediate results */ /* Intermediate product is calculated by (Ialpha * cosVal) */ - product1 = (q31_t) (((q63_t) (Ialpha) * (cosVal)) >> 31); + product1 = (q31_t)(((q63_t)(Ialpha) * (cosVal)) >> 31); /* Intermediate product is calculated by (Ibeta * sinVal) */ - product2 = (q31_t) (((q63_t) (Ibeta) * (sinVal)) >> 31); + product2 = (q31_t)(((q63_t)(Ibeta) * (sinVal)) >> 31); /* Intermediate product is calculated by (Ialpha * sinVal) */ - product3 = (q31_t) (((q63_t) (Ialpha) * (sinVal)) >> 31); + product3 = (q31_t)(((q63_t)(Ialpha) * (sinVal)) >> 31); /* Intermediate product is calculated by (Ibeta * cosVal) */ - product4 = (q31_t) (((q63_t) (Ibeta) * (cosVal)) >> 31); + product4 = (q31_t)(((q63_t)(Ibeta) * (cosVal)) >> 31); /* Calculate pId by adding the two intermediate products 1 and 2 */ *pId = __QADD(product1, product2); /* Calculate pIq by subtracting the two intermediate products 3 from 4 */ *pIq = __QSUB(product4, product3); - } +} - /** - * @} end of park group - */ +/** + * @} end of park group + */ - /** - * @brief Converts the elements of the Q7 vector to floating-point vector. - * @param[in] pSrc is input pointer - * @param[out] pDst is output pointer - * @param[in] blockSize is the number of samples to process - */ - void arm_q7_to_float( - q7_t * pSrc, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the Q7 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ +void arm_q7_to_float( + q7_t *pSrc, + float32_t *pDst, + uint32_t blockSize); - /** - * @ingroup groupController - */ +/** + * @ingroup groupController + */ - /** - * @defgroup inv_park Vector Inverse Park transform - * Inverse Park transform converts the input flux and torque components to two-coordinate vector. - * - * The function operates on a single sample of data and each call to the function returns the processed output. - * The library provides separate functions for Q31 and floating-point data types. - * \par Algorithm - * \image html parkInvFormula.gif - * where pIalpha and pIbeta are the stator vector components, - * Id and Iq are rotor vector components and cosVal and sinVal are the - * cosine and sine values of theta (rotor flux position). - * \par Fixed-Point Behavior - * Care must be taken when using the Q31 version of the Park transform. - * In particular, the overflow and saturation behavior of the accumulator used must be considered. - * Refer to the function specific documentation below for usage guidelines. - */ +/** + * @defgroup inv_park Vector Inverse Park transform + * Inverse Park transform converts the input flux and torque components to two-coordinate vector. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkInvFormula.gif + * where pIalpha and pIbeta are the stator vector components, + * Id and Iq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ - /** - * @addtogroup inv_park - * @{ - */ +/** + * @addtogroup inv_park + * @{ + */ - /** - * @brief Floating-point Inverse Park transform - * @param[in] Id input coordinate of rotor reference frame d - * @param[in] Iq input coordinate of rotor reference frame q - * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha - * @param[out] pIbeta points to output two-phase orthogonal vector axis beta - * @param[in] sinVal sine value of rotation angle theta - * @param[in] cosVal cosine value of rotation angle theta - */ - CMSIS_INLINE __STATIC_INLINE void arm_inv_park_f32( - float32_t Id, - float32_t Iq, - float32_t * pIalpha, - float32_t * pIbeta, - float32_t sinVal, - float32_t cosVal) - { +/** +* @brief Floating-point Inverse Park transform +* @param[in] Id input coordinate of rotor reference frame d +* @param[in] Iq input coordinate of rotor reference frame q +* @param[out] pIalpha points to output two-phase orthogonal vector axis alpha +* @param[out] pIbeta points to output two-phase orthogonal vector axis beta +* @param[in] sinVal sine value of rotation angle theta +* @param[in] cosVal cosine value of rotation angle theta +*/ +CMSIS_INLINE __STATIC_INLINE void arm_inv_park_f32( + float32_t Id, + float32_t Iq, + float32_t *pIalpha, + float32_t *pIbeta, + float32_t sinVal, + float32_t cosVal) +{ /* Calculate pIalpha using the equation, pIalpha = Id * cosVal - Iq * sinVal */ *pIalpha = Id * cosVal - Iq * sinVal; /* Calculate pIbeta using the equation, pIbeta = Id * sinVal + Iq * cosVal */ *pIbeta = Id * sinVal + Iq * cosVal; - } +} - /** - * @brief Inverse Park transform for Q31 version - * @param[in] Id input coordinate of rotor reference frame d - * @param[in] Iq input coordinate of rotor reference frame q - * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha - * @param[out] pIbeta points to output two-phase orthogonal vector axis beta - * @param[in] sinVal sine value of rotation angle theta - * @param[in] cosVal cosine value of rotation angle theta - * - * Scaling and Overflow Behavior: - * \par - * The function is implemented using an internal 32-bit accumulator. - * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. - * There is saturation on the addition, hence there is no risk of overflow. - */ - CMSIS_INLINE __STATIC_INLINE void arm_inv_park_q31( - q31_t Id, - q31_t Iq, - q31_t * pIalpha, - q31_t * pIbeta, - q31_t sinVal, - q31_t cosVal) - { +/** + * @brief Inverse Park transform for Q31 version + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ +CMSIS_INLINE __STATIC_INLINE void arm_inv_park_q31( + q31_t Id, + q31_t Iq, + q31_t *pIalpha, + q31_t *pIbeta, + q31_t sinVal, + q31_t cosVal) +{ q31_t product1, product2; /* Temporary variables used to store intermediate results */ q31_t product3, product4; /* Temporary variables used to store intermediate results */ /* Intermediate product is calculated by (Id * cosVal) */ - product1 = (q31_t) (((q63_t) (Id) * (cosVal)) >> 31); + product1 = (q31_t)(((q63_t)(Id) * (cosVal)) >> 31); /* Intermediate product is calculated by (Iq * sinVal) */ - product2 = (q31_t) (((q63_t) (Iq) * (sinVal)) >> 31); + product2 = (q31_t)(((q63_t)(Iq) * (sinVal)) >> 31); /* Intermediate product is calculated by (Id * sinVal) */ - product3 = (q31_t) (((q63_t) (Id) * (sinVal)) >> 31); + product3 = (q31_t)(((q63_t)(Id) * (sinVal)) >> 31); /* Intermediate product is calculated by (Iq * cosVal) */ - product4 = (q31_t) (((q63_t) (Iq) * (cosVal)) >> 31); + product4 = (q31_t)(((q63_t)(Iq) * (cosVal)) >> 31); /* Calculate pIalpha by using the two intermediate products 1 and 2 */ *pIalpha = __QSUB(product1, product2); /* Calculate pIbeta by using the two intermediate products 3 and 4 */ *pIbeta = __QADD(product4, product3); - } +} - /** - * @} end of Inverse park group - */ +/** + * @} end of Inverse park group + */ - /** - * @brief Converts the elements of the Q31 vector to floating-point vector. - * @param[in] pSrc is input pointer - * @param[out] pDst is output pointer - * @param[in] blockSize is the number of samples to process - */ - void arm_q31_to_float( - q31_t * pSrc, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the Q31 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ +void arm_q31_to_float( + q31_t *pSrc, + float32_t *pDst, + uint32_t blockSize); - /** - * @ingroup groupInterpolation - */ +/** + * @ingroup groupInterpolation + */ - /** - * @defgroup LinearInterpolate Linear Interpolation - * - * Linear interpolation is a method of curve fitting using linear polynomials. - * Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line - * - * \par - * \image html LinearInterp.gif "Linear interpolation" - * - * \par - * A Linear Interpolate function calculates an output value(y), for the input(x) - * using linear interpolation of the input values x0, x1( nearest input values) and the output values y0 and y1(nearest output values) - * - * \par Algorithm: - *
-   *       y = y0 + (x - x0) * ((y1 - y0)/(x1-x0))
-   *       where x0, x1 are nearest values of input x
-   *             y0, y1 are nearest values to output y
-   * 
- * - * \par - * This set of functions implements Linear interpolation process - * for Q7, Q15, Q31, and floating-point data types. The functions operate on a single - * sample of data and each call to the function returns a single processed value. - * S points to an instance of the Linear Interpolate function data structure. - * x is the input sample value. The functions returns the output value. - * - * \par - * if x is outside of the table boundary, Linear interpolation returns first value of the table - * if x is below input range and returns last value of table if x is above range. - */ +/** + * @defgroup LinearInterpolate Linear Interpolation + * + * Linear interpolation is a method of curve fitting using linear polynomials. + * Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line + * + * \par + * \image html LinearInterp.gif "Linear interpolation" + * + * \par + * A Linear Interpolate function calculates an output value(y), for the input(x) + * using linear interpolation of the input values x0, x1( nearest input values) and the output values y0 and y1(nearest output values) + * + * \par Algorithm: + *
+ *       y = y0 + (x - x0) * ((y1 - y0)/(x1-x0))
+ *       where x0, x1 are nearest values of input x
+ *             y0, y1 are nearest values to output y
+ * 
+ * + * \par + * This set of functions implements Linear interpolation process + * for Q7, Q15, Q31, and floating-point data types. The functions operate on a single + * sample of data and each call to the function returns a single processed value. + * S points to an instance of the Linear Interpolate function data structure. + * x is the input sample value. The functions returns the output value. + * + * \par + * if x is outside of the table boundary, Linear interpolation returns first value of the table + * if x is below input range and returns last value of table if x is above range. + */ - /** - * @addtogroup LinearInterpolate - * @{ - */ +/** + * @addtogroup LinearInterpolate + * @{ + */ - /** - * @brief Process function for the floating-point Linear Interpolation Function. - * @param[in,out] S is an instance of the floating-point Linear Interpolation structure - * @param[in] x input sample to process - * @return y processed output sample. - * - */ - CMSIS_INLINE __STATIC_INLINE float32_t arm_linear_interp_f32( - arm_linear_interp_instance_f32 * S, - float32_t x) - { +/** + * @brief Process function for the floating-point Linear Interpolation Function. + * @param[in,out] S is an instance of the floating-point Linear Interpolation structure + * @param[in] x input sample to process + * @return y processed output sample. + * + */ +CMSIS_INLINE __STATIC_INLINE float32_t arm_linear_interp_f32( + arm_linear_interp_instance_f32 *S, + float32_t x) +{ float32_t y; float32_t x0, x1; /* Nearest input values */ float32_t y0, y1; /* Nearest output values */ @@ -5523,56 +5523,56 @@ void arm_rfft_fast_f32( float32_t *pYData = S->pYData; /* pointer to output table */ /* Calculation of index */ - i = (int32_t) ((x - S->x1) / xSpacing); + i = (int32_t)((x - S->x1) / xSpacing); if (i < 0) { - /* Iniatilize output for below specified range as least output value of table */ - y = pYData[0]; + /* Iniatilize output for below specified range as least output value of table */ + y = pYData[0]; } else if ((uint32_t)i >= S->nValues) { - /* Iniatilize output for above specified range as last output value of table */ - y = pYData[S->nValues - 1]; + /* Iniatilize output for above specified range as last output value of table */ + y = pYData[S->nValues - 1]; } else { - /* Calculation of nearest input values */ - x0 = S->x1 + i * xSpacing; - x1 = S->x1 + (i + 1) * xSpacing; + /* Calculation of nearest input values */ + x0 = S->x1 + i * xSpacing; + x1 = S->x1 + (i + 1) * xSpacing; - /* Read of nearest output values */ - y0 = pYData[i]; - y1 = pYData[i + 1]; + /* Read of nearest output values */ + y0 = pYData[i]; + y1 = pYData[i + 1]; - /* Calculation of output */ - y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0)); + /* Calculation of output */ + y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0)); } /* returns output value */ return (y); - } +} - /** - * - * @brief Process function for the Q31 Linear Interpolation Function. - * @param[in] pYData pointer to Q31 Linear Interpolation table - * @param[in] x input sample to process - * @param[in] nValues number of table values - * @return y processed output sample. - * - * \par - * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. - * This function can support maximum of table size 2^12. - * - */ - CMSIS_INLINE __STATIC_INLINE q31_t arm_linear_interp_q31( - q31_t * pYData, - q31_t x, - uint32_t nValues) - { +/** +* +* @brief Process function for the Q31 Linear Interpolation Function. +* @param[in] pYData pointer to Q31 Linear Interpolation table +* @param[in] x input sample to process +* @param[in] nValues number of table values +* @return y processed output sample. +* +* \par +* Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. +* This function can support maximum of table size 2^12. +* +*/ +CMSIS_INLINE __STATIC_INLINE q31_t arm_linear_interp_q31( + q31_t *pYData, + q31_t x, + uint32_t nValues) +{ q31_t y; /* output */ q31_t y0, y1; /* Nearest output values */ q31_t fract; /* fractional part */ @@ -5585,52 +5585,52 @@ void arm_rfft_fast_f32( if (index >= (int32_t)(nValues - 1)) { - return (pYData[nValues - 1]); + return (pYData[nValues - 1]); } else if (index < 0) { - return (pYData[0]); + return (pYData[0]); } else { - /* 20 bits for the fractional part */ - /* shift left by 11 to keep fract in 1.31 format */ - fract = (x & 0x000FFFFF) << 11; + /* 20 bits for the fractional part */ + /* shift left by 11 to keep fract in 1.31 format */ + fract = (x & 0x000FFFFF) << 11; - /* Read two nearest output values from the index in 1.31(q31) format */ - y0 = pYData[index]; - y1 = pYData[index + 1]; + /* Read two nearest output values from the index in 1.31(q31) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; - /* Calculation of y0 * (1-fract) and y is in 2.30 format */ - y = ((q31_t) ((q63_t) y0 * (0x7FFFFFFF - fract) >> 32)); + /* Calculation of y0 * (1-fract) and y is in 2.30 format */ + y = ((q31_t)((q63_t) y0 * (0x7FFFFFFF - fract) >> 32)); - /* Calculation of y0 * (1-fract) + y1 *fract and y is in 2.30 format */ - y += ((q31_t) (((q63_t) y1 * fract) >> 32)); + /* Calculation of y0 * (1-fract) + y1 *fract and y is in 2.30 format */ + y += ((q31_t)(((q63_t) y1 * fract) >> 32)); - /* Convert y to 1.31 format */ - return (y << 1u); + /* Convert y to 1.31 format */ + return (y << 1u); } - } +} - /** - * - * @brief Process function for the Q15 Linear Interpolation Function. - * @param[in] pYData pointer to Q15 Linear Interpolation table - * @param[in] x input sample to process - * @param[in] nValues number of table values - * @return y processed output sample. - * - * \par - * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. - * This function can support maximum of table size 2^12. - * - */ - CMSIS_INLINE __STATIC_INLINE q15_t arm_linear_interp_q15( - q15_t * pYData, - q31_t x, - uint32_t nValues) - { +/** + * + * @brief Process function for the Q15 Linear Interpolation Function. + * @param[in] pYData pointer to Q15 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ +CMSIS_INLINE __STATIC_INLINE q15_t arm_linear_interp_q15( + q15_t *pYData, + q31_t x, + uint32_t nValues) +{ q63_t y; /* output */ q15_t y0, y1; /* Nearest output values */ q31_t fract; /* fractional part */ @@ -5643,51 +5643,51 @@ void arm_rfft_fast_f32( if (index >= (int32_t)(nValues - 1)) { - return (pYData[nValues - 1]); + return (pYData[nValues - 1]); } else if (index < 0) { - return (pYData[0]); + return (pYData[0]); } else { - /* 20 bits for the fractional part */ - /* fract is in 12.20 format */ - fract = (x & 0x000FFFFF); + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); - /* Read two nearest output values from the index */ - y0 = pYData[index]; - y1 = pYData[index + 1]; + /* Read two nearest output values from the index */ + y0 = pYData[index]; + y1 = pYData[index + 1]; - /* Calculation of y0 * (1-fract) and y is in 13.35 format */ - y = ((q63_t) y0 * (0xFFFFF - fract)); + /* Calculation of y0 * (1-fract) and y is in 13.35 format */ + y = ((q63_t) y0 * (0xFFFFF - fract)); - /* Calculation of (y0 * (1-fract) + y1 * fract) and y is in 13.35 format */ - y += ((q63_t) y1 * (fract)); + /* Calculation of (y0 * (1-fract) + y1 * fract) and y is in 13.35 format */ + y += ((q63_t) y1 * (fract)); - /* convert y to 1.15 format */ - return (q15_t) (y >> 20); + /* convert y to 1.15 format */ + return (q15_t)(y >> 20); } - } +} - /** - * - * @brief Process function for the Q7 Linear Interpolation Function. - * @param[in] pYData pointer to Q7 Linear Interpolation table - * @param[in] x input sample to process - * @param[in] nValues number of table values - * @return y processed output sample. - * - * \par - * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. - * This function can support maximum of table size 2^12. - */ - CMSIS_INLINE __STATIC_INLINE q7_t arm_linear_interp_q7( - q7_t * pYData, - q31_t x, - uint32_t nValues) - { +/** + * + * @brief Process function for the Q7 Linear Interpolation Function. + * @param[in] pYData pointer to Q7 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + */ +CMSIS_INLINE __STATIC_INLINE q7_t arm_linear_interp_q7( + q7_t *pYData, + q31_t x, + uint32_t nValues) +{ q31_t y; /* output */ q7_t y0, y1; /* Nearest output values */ q31_t fract; /* fractional part */ @@ -5698,200 +5698,200 @@ void arm_rfft_fast_f32( /* Index value calculation */ if (x < 0) { - return (pYData[0]); + return (pYData[0]); } index = (x >> 20) & 0xfff; if (index >= (nValues - 1)) { - return (pYData[nValues - 1]); + return (pYData[nValues - 1]); } else { - /* 20 bits for the fractional part */ - /* fract is in 12.20 format */ - fract = (x & 0x000FFFFF); + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); - /* Read two nearest output values from the index and are in 1.7(q7) format */ - y0 = pYData[index]; - y1 = pYData[index + 1]; + /* Read two nearest output values from the index and are in 1.7(q7) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; - /* Calculation of y0 * (1-fract ) and y is in 13.27(q27) format */ - y = ((y0 * (0xFFFFF - fract))); + /* Calculation of y0 * (1-fract ) and y is in 13.27(q27) format */ + y = ((y0 * (0xFFFFF - fract))); - /* Calculation of y1 * fract + y0 * (1-fract) and y is in 13.27(q27) format */ - y += (y1 * fract); + /* Calculation of y1 * fract + y0 * (1-fract) and y is in 13.27(q27) format */ + y += (y1 * fract); - /* convert y to 1.7(q7) format */ - return (q7_t) (y >> 20); - } - } + /* convert y to 1.7(q7) format */ + return (q7_t)(y >> 20); + } +} - /** - * @} end of LinearInterpolate group - */ +/** + * @} end of LinearInterpolate group + */ - /** - * @brief Fast approximation to the trigonometric sine function for floating-point data. - * @param[in] x input value in radians. - * @return sin(x). - */ - float32_t arm_sin_f32( - float32_t x); +/** + * @brief Fast approximation to the trigonometric sine function for floating-point data. + * @param[in] x input value in radians. + * @return sin(x). + */ +float32_t arm_sin_f32( + float32_t x); - /** - * @brief Fast approximation to the trigonometric sine function for Q31 data. - * @param[in] x Scaled input value in radians. - * @return sin(x). - */ - q31_t arm_sin_q31( - q31_t x); +/** + * @brief Fast approximation to the trigonometric sine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ +q31_t arm_sin_q31( + q31_t x); - /** - * @brief Fast approximation to the trigonometric sine function for Q15 data. - * @param[in] x Scaled input value in radians. - * @return sin(x). - */ - q15_t arm_sin_q15( - q15_t x); +/** + * @brief Fast approximation to the trigonometric sine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ +q15_t arm_sin_q15( + q15_t x); - /** - * @brief Fast approximation to the trigonometric cosine function for floating-point data. - * @param[in] x input value in radians. - * @return cos(x). - */ - float32_t arm_cos_f32( - float32_t x); +/** + * @brief Fast approximation to the trigonometric cosine function for floating-point data. + * @param[in] x input value in radians. + * @return cos(x). + */ +float32_t arm_cos_f32( + float32_t x); - /** - * @brief Fast approximation to the trigonometric cosine function for Q31 data. - * @param[in] x Scaled input value in radians. - * @return cos(x). - */ - q31_t arm_cos_q31( - q31_t x); +/** + * @brief Fast approximation to the trigonometric cosine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ +q31_t arm_cos_q31( + q31_t x); - /** - * @brief Fast approximation to the trigonometric cosine function for Q15 data. - * @param[in] x Scaled input value in radians. - * @return cos(x). - */ - q15_t arm_cos_q15( - q15_t x); +/** + * @brief Fast approximation to the trigonometric cosine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ +q15_t arm_cos_q15( + q15_t x); - /** - * @ingroup groupFastMath - */ +/** + * @ingroup groupFastMath + */ - /** - * @defgroup SQRT Square Root - * - * Computes the square root of a number. - * There are separate functions for Q15, Q31, and floating-point data types. - * The square root function is computed using the Newton-Raphson algorithm. - * This is an iterative algorithm of the form: - *
-   *      x1 = x0 - f(x0)/f'(x0)
-   * 
- * where x1 is the current estimate, - * x0 is the previous estimate, and - * f'(x0) is the derivative of f() evaluated at x0. - * For the square root function, the algorithm reduces to: - *
-   *     x0 = in/2                         [initial guess]
-   *     x1 = 1/2 * ( x0 + in / x0)        [each iteration]
-   * 
- */ +/** + * @defgroup SQRT Square Root + * + * Computes the square root of a number. + * There are separate functions for Q15, Q31, and floating-point data types. + * The square root function is computed using the Newton-Raphson algorithm. + * This is an iterative algorithm of the form: + *
+ *      x1 = x0 - f(x0)/f'(x0)
+ * 
+ * where x1 is the current estimate, + * x0 is the previous estimate, and + * f'(x0) is the derivative of f() evaluated at x0. + * For the square root function, the algorithm reduces to: + *
+ *     x0 = in/2                         [initial guess]
+ *     x1 = 1/2 * ( x0 + in / x0)        [each iteration]
+ * 
+ */ - /** - * @addtogroup SQRT - * @{ - */ +/** + * @addtogroup SQRT + * @{ + */ - /** - * @brief Floating-point square root function. - * @param[in] in input value. - * @param[out] pOut square root of input value. - * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if - * in is negative value and returns zero output for negative values. - */ - CMSIS_INLINE __STATIC_INLINE arm_status arm_sqrt_f32( - float32_t in, - float32_t * pOut) - { +/** + * @brief Floating-point square root function. + * @param[in] in input value. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ +CMSIS_INLINE __STATIC_INLINE arm_status arm_sqrt_f32( + float32_t in, + float32_t *pOut) +{ if (in >= 0.0f) { #if (__FPU_USED == 1) && defined ( __CC_ARM ) - *pOut = __sqrtf(in); + *pOut = __sqrtf(in); #elif (__FPU_USED == 1) && (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) - *pOut = __builtin_sqrtf(in); + *pOut = __builtin_sqrtf(in); #elif (__FPU_USED == 1) && defined(__GNUC__) - *pOut = __builtin_sqrtf(in); + *pOut = __builtin_sqrtf(in); #elif (__FPU_USED == 1) && defined ( __ICCARM__ ) && (__VER__ >= 6040000) - __ASM("VSQRT.F32 %0,%1" : "=t"(*pOut) : "t"(in)); + __ASM("VSQRT.F32 %0,%1" : "=t"(*pOut) : "t"(in)); #else - *pOut = sqrtf(in); + *pOut = sqrtf(in); #endif - return (ARM_MATH_SUCCESS); + return (ARM_MATH_SUCCESS); } else { - *pOut = 0.0f; - return (ARM_MATH_ARGUMENT_ERROR); + *pOut = 0.0f; + return (ARM_MATH_ARGUMENT_ERROR); } - } +} - /** - * @brief Q31 square root function. - * @param[in] in input value. The range of the input value is [0 +1) or 0x00000000 to 0x7FFFFFFF. - * @param[out] pOut square root of input value. - * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if - * in is negative value and returns zero output for negative values. - */ - arm_status arm_sqrt_q31( - q31_t in, - q31_t * pOut); +/** + * @brief Q31 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x00000000 to 0x7FFFFFFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ +arm_status arm_sqrt_q31( + q31_t in, + q31_t *pOut); - /** - * @brief Q15 square root function. - * @param[in] in input value. The range of the input value is [0 +1) or 0x0000 to 0x7FFF. - * @param[out] pOut square root of input value. - * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if - * in is negative value and returns zero output for negative values. - */ - arm_status arm_sqrt_q15( - q15_t in, - q15_t * pOut); +/** + * @brief Q15 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x0000 to 0x7FFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ +arm_status arm_sqrt_q15( + q15_t in, + q15_t *pOut); - /** - * @} end of SQRT group - */ +/** + * @} end of SQRT group + */ - /** - * @brief floating-point Circular write function. - */ - CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_f32( - int32_t * circBuffer, - int32_t L, - uint16_t * writeOffset, - int32_t bufferInc, - const int32_t * src, - int32_t srcInc, - uint32_t blockSize) - { +/** + * @brief floating-point Circular write function. + */ +CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_f32( + int32_t *circBuffer, + int32_t L, + uint16_t *writeOffset, + int32_t bufferInc, + const int32_t *src, + int32_t srcInc, + uint32_t blockSize) +{ uint32_t i = 0u; int32_t wOffset; @@ -5904,94 +5904,94 @@ void arm_rfft_fast_f32( while (i > 0u) { - /* copy the input sample to the circular buffer */ - circBuffer[wOffset] = *src; + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; - /* Update the input pointer */ - src += srcInc; + /* Update the input pointer */ + src += srcInc; - /* Circularly update wOffset. Watch out for positive and negative value */ - wOffset += bufferInc; - if (wOffset >= L) - wOffset -= L; + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; - /* Decrement the loop counter */ - i--; + /* Decrement the loop counter */ + i--; } /* Update the index pointer */ *writeOffset = (uint16_t)wOffset; - } +} - /** - * @brief floating-point Circular Read function. - */ - CMSIS_INLINE __STATIC_INLINE void arm_circularRead_f32( - int32_t * circBuffer, - int32_t L, - int32_t * readOffset, - int32_t bufferInc, - int32_t * dst, - int32_t * dst_base, - int32_t dst_length, - int32_t dstInc, - uint32_t blockSize) - { +/** + * @brief floating-point Circular Read function. + */ +CMSIS_INLINE __STATIC_INLINE void arm_circularRead_f32( + int32_t *circBuffer, + int32_t L, + int32_t *readOffset, + int32_t bufferInc, + int32_t *dst, + int32_t *dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) +{ uint32_t i = 0u; int32_t rOffset, dst_end; /* Copy the value of Index pointer that points * to the current location from where the input samples to be read */ rOffset = *readOffset; - dst_end = (int32_t) (dst_base + dst_length); + dst_end = (int32_t)(dst_base + dst_length); /* Loop over the blockSize */ i = blockSize; while (i > 0u) { - /* copy the sample from the circular buffer to the destination buffer */ - *dst = circBuffer[rOffset]; + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; - /* Update the input pointer */ - dst += dstInc; + /* Update the input pointer */ + dst += dstInc; - if (dst == (int32_t *) dst_end) - { - dst = dst_base; - } + if (dst == (int32_t *) dst_end) + { + dst = dst_base; + } - /* Circularly update rOffset. Watch out for positive and negative value */ - rOffset += bufferInc; + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; - if (rOffset >= L) - { - rOffset -= L; - } + if (rOffset >= L) + { + rOffset -= L; + } - /* Decrement the loop counter */ - i--; + /* Decrement the loop counter */ + i--; } /* Update the index pointer */ *readOffset = rOffset; - } +} - /** - * @brief Q15 Circular write function. - */ - CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_q15( - q15_t * circBuffer, - int32_t L, - uint16_t * writeOffset, - int32_t bufferInc, - const q15_t * src, - int32_t srcInc, - uint32_t blockSize) - { +/** + * @brief Q15 Circular write function. + */ +CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_q15( + q15_t *circBuffer, + int32_t L, + uint16_t *writeOffset, + int32_t bufferInc, + const q15_t *src, + int32_t srcInc, + uint32_t blockSize) +{ uint32_t i = 0u; int32_t wOffset; @@ -6004,40 +6004,40 @@ void arm_rfft_fast_f32( while (i > 0u) { - /* copy the input sample to the circular buffer */ - circBuffer[wOffset] = *src; + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; - /* Update the input pointer */ - src += srcInc; + /* Update the input pointer */ + src += srcInc; - /* Circularly update wOffset. Watch out for positive and negative value */ - wOffset += bufferInc; - if (wOffset >= L) - wOffset -= L; + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; - /* Decrement the loop counter */ - i--; + /* Decrement the loop counter */ + i--; } /* Update the index pointer */ *writeOffset = (uint16_t)wOffset; - } +} - /** - * @brief Q15 Circular Read function. - */ - CMSIS_INLINE __STATIC_INLINE void arm_circularRead_q15( - q15_t * circBuffer, - int32_t L, - int32_t * readOffset, - int32_t bufferInc, - q15_t * dst, - q15_t * dst_base, - int32_t dst_length, - int32_t dstInc, - uint32_t blockSize) - { +/** + * @brief Q15 Circular Read function. + */ +CMSIS_INLINE __STATIC_INLINE void arm_circularRead_q15( + q15_t *circBuffer, + int32_t L, + int32_t *readOffset, + int32_t bufferInc, + q15_t *dst, + q15_t *dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) +{ uint32_t i = 0; int32_t rOffset, dst_end; @@ -6045,53 +6045,53 @@ void arm_rfft_fast_f32( * to the current location from where the input samples to be read */ rOffset = *readOffset; - dst_end = (int32_t) (dst_base + dst_length); + dst_end = (int32_t)(dst_base + dst_length); /* Loop over the blockSize */ i = blockSize; while (i > 0u) { - /* copy the sample from the circular buffer to the destination buffer */ - *dst = circBuffer[rOffset]; + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; - /* Update the input pointer */ - dst += dstInc; + /* Update the input pointer */ + dst += dstInc; - if (dst == (q15_t *) dst_end) - { - dst = dst_base; - } + if (dst == (q15_t *) dst_end) + { + dst = dst_base; + } - /* Circularly update wOffset. Watch out for positive and negative value */ - rOffset += bufferInc; + /* Circularly update wOffset. Watch out for positive and negative value */ + rOffset += bufferInc; - if (rOffset >= L) - { - rOffset -= L; - } + if (rOffset >= L) + { + rOffset -= L; + } - /* Decrement the loop counter */ - i--; + /* Decrement the loop counter */ + i--; } /* Update the index pointer */ *readOffset = rOffset; - } +} - /** - * @brief Q7 Circular write function. - */ - CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_q7( - q7_t * circBuffer, - int32_t L, - uint16_t * writeOffset, - int32_t bufferInc, - const q7_t * src, - int32_t srcInc, - uint32_t blockSize) - { +/** + * @brief Q7 Circular write function. + */ +CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_q7( + q7_t *circBuffer, + int32_t L, + uint16_t *writeOffset, + int32_t bufferInc, + const q7_t *src, + int32_t srcInc, + uint32_t blockSize) +{ uint32_t i = 0u; int32_t wOffset; @@ -6104,40 +6104,40 @@ void arm_rfft_fast_f32( while (i > 0u) { - /* copy the input sample to the circular buffer */ - circBuffer[wOffset] = *src; + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; - /* Update the input pointer */ - src += srcInc; + /* Update the input pointer */ + src += srcInc; - /* Circularly update wOffset. Watch out for positive and negative value */ - wOffset += bufferInc; - if (wOffset >= L) - wOffset -= L; + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; - /* Decrement the loop counter */ - i--; + /* Decrement the loop counter */ + i--; } /* Update the index pointer */ *writeOffset = (uint16_t)wOffset; - } +} - /** - * @brief Q7 Circular Read function. - */ - CMSIS_INLINE __STATIC_INLINE void arm_circularRead_q7( - q7_t * circBuffer, - int32_t L, - int32_t * readOffset, - int32_t bufferInc, - q7_t * dst, - q7_t * dst_base, - int32_t dst_length, - int32_t dstInc, - uint32_t blockSize) - { +/** + * @brief Q7 Circular Read function. + */ +CMSIS_INLINE __STATIC_INLINE void arm_circularRead_q7( + q7_t *circBuffer, + int32_t L, + int32_t *readOffset, + int32_t bufferInc, + q7_t *dst, + q7_t *dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) +{ uint32_t i = 0; int32_t rOffset, dst_end; @@ -6145,425 +6145,425 @@ void arm_rfft_fast_f32( * to the current location from where the input samples to be read */ rOffset = *readOffset; - dst_end = (int32_t) (dst_base + dst_length); + dst_end = (int32_t)(dst_base + dst_length); /* Loop over the blockSize */ i = blockSize; while (i > 0u) { - /* copy the sample from the circular buffer to the destination buffer */ - *dst = circBuffer[rOffset]; + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; - /* Update the input pointer */ - dst += dstInc; + /* Update the input pointer */ + dst += dstInc; - if (dst == (q7_t *) dst_end) - { - dst = dst_base; - } + if (dst == (q7_t *) dst_end) + { + dst = dst_base; + } - /* Circularly update rOffset. Watch out for positive and negative value */ - rOffset += bufferInc; + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; - if (rOffset >= L) - { - rOffset -= L; - } + if (rOffset >= L) + { + rOffset -= L; + } - /* Decrement the loop counter */ - i--; + /* Decrement the loop counter */ + i--; } /* Update the index pointer */ *readOffset = rOffset; - } +} - /** - * @brief Sum of the squares of the elements of a Q31 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_power_q31( - q31_t * pSrc, - uint32_t blockSize, - q63_t * pResult); +/** + * @brief Sum of the squares of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_power_q31( + q31_t *pSrc, + uint32_t blockSize, + q63_t *pResult); - /** - * @brief Sum of the squares of the elements of a floating-point vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_power_f32( - float32_t * pSrc, - uint32_t blockSize, - float32_t * pResult); +/** + * @brief Sum of the squares of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_power_f32( + float32_t *pSrc, + uint32_t blockSize, + float32_t *pResult); - /** - * @brief Sum of the squares of the elements of a Q15 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_power_q15( - q15_t * pSrc, - uint32_t blockSize, - q63_t * pResult); +/** + * @brief Sum of the squares of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_power_q15( + q15_t *pSrc, + uint32_t blockSize, + q63_t *pResult); - /** - * @brief Sum of the squares of the elements of a Q7 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_power_q7( - q7_t * pSrc, - uint32_t blockSize, - q31_t * pResult); +/** + * @brief Sum of the squares of the elements of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_power_q7( + q7_t *pSrc, + uint32_t blockSize, + q31_t *pResult); - /** - * @brief Mean value of a Q7 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_mean_q7( - q7_t * pSrc, - uint32_t blockSize, - q7_t * pResult); +/** + * @brief Mean value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_mean_q7( + q7_t *pSrc, + uint32_t blockSize, + q7_t *pResult); - /** - * @brief Mean value of a Q15 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_mean_q15( - q15_t * pSrc, - uint32_t blockSize, - q15_t * pResult); +/** + * @brief Mean value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_mean_q15( + q15_t *pSrc, + uint32_t blockSize, + q15_t *pResult); - /** - * @brief Mean value of a Q31 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_mean_q31( - q31_t * pSrc, - uint32_t blockSize, - q31_t * pResult); +/** + * @brief Mean value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_mean_q31( + q31_t *pSrc, + uint32_t blockSize, + q31_t *pResult); - /** - * @brief Mean value of a floating-point vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_mean_f32( - float32_t * pSrc, - uint32_t blockSize, - float32_t * pResult); +/** + * @brief Mean value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_mean_f32( + float32_t *pSrc, + uint32_t blockSize, + float32_t *pResult); - /** - * @brief Variance of the elements of a floating-point vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_var_f32( - float32_t * pSrc, - uint32_t blockSize, - float32_t * pResult); +/** + * @brief Variance of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_var_f32( + float32_t *pSrc, + uint32_t blockSize, + float32_t *pResult); - /** - * @brief Variance of the elements of a Q31 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_var_q31( - q31_t * pSrc, - uint32_t blockSize, - q31_t * pResult); +/** + * @brief Variance of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_var_q31( + q31_t *pSrc, + uint32_t blockSize, + q31_t *pResult); - /** - * @brief Variance of the elements of a Q15 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_var_q15( - q15_t * pSrc, - uint32_t blockSize, - q15_t * pResult); +/** + * @brief Variance of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_var_q15( + q15_t *pSrc, + uint32_t blockSize, + q15_t *pResult); - /** - * @brief Root Mean Square of the elements of a floating-point vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_rms_f32( - float32_t * pSrc, - uint32_t blockSize, - float32_t * pResult); +/** + * @brief Root Mean Square of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_rms_f32( + float32_t *pSrc, + uint32_t blockSize, + float32_t *pResult); - /** - * @brief Root Mean Square of the elements of a Q31 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_rms_q31( - q31_t * pSrc, - uint32_t blockSize, - q31_t * pResult); +/** + * @brief Root Mean Square of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_rms_q31( + q31_t *pSrc, + uint32_t blockSize, + q31_t *pResult); - /** - * @brief Root Mean Square of the elements of a Q15 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_rms_q15( - q15_t * pSrc, - uint32_t blockSize, - q15_t * pResult); +/** + * @brief Root Mean Square of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_rms_q15( + q15_t *pSrc, + uint32_t blockSize, + q15_t *pResult); - /** - * @brief Standard deviation of the elements of a floating-point vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_std_f32( - float32_t * pSrc, - uint32_t blockSize, - float32_t * pResult); +/** + * @brief Standard deviation of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_std_f32( + float32_t *pSrc, + uint32_t blockSize, + float32_t *pResult); - /** - * @brief Standard deviation of the elements of a Q31 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_std_q31( - q31_t * pSrc, - uint32_t blockSize, - q31_t * pResult); +/** + * @brief Standard deviation of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_std_q31( + q31_t *pSrc, + uint32_t blockSize, + q31_t *pResult); - /** - * @brief Standard deviation of the elements of a Q15 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output value. - */ - void arm_std_q15( - q15_t * pSrc, - uint32_t blockSize, - q15_t * pResult); +/** + * @brief Standard deviation of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ +void arm_std_q15( + q15_t *pSrc, + uint32_t blockSize, + q15_t *pResult); - /** - * @brief Floating-point complex magnitude - * @param[in] pSrc points to the complex input vector - * @param[out] pDst points to the real output vector - * @param[in] numSamples number of complex samples in the input vector - */ - void arm_cmplx_mag_f32( - float32_t * pSrc, - float32_t * pDst, - uint32_t numSamples); +/** + * @brief Floating-point complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ +void arm_cmplx_mag_f32( + float32_t *pSrc, + float32_t *pDst, + uint32_t numSamples); - /** - * @brief Q31 complex magnitude - * @param[in] pSrc points to the complex input vector - * @param[out] pDst points to the real output vector - * @param[in] numSamples number of complex samples in the input vector - */ - void arm_cmplx_mag_q31( - q31_t * pSrc, - q31_t * pDst, - uint32_t numSamples); +/** + * @brief Q31 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ +void arm_cmplx_mag_q31( + q31_t *pSrc, + q31_t *pDst, + uint32_t numSamples); - /** - * @brief Q15 complex magnitude - * @param[in] pSrc points to the complex input vector - * @param[out] pDst points to the real output vector - * @param[in] numSamples number of complex samples in the input vector - */ - void arm_cmplx_mag_q15( - q15_t * pSrc, - q15_t * pDst, - uint32_t numSamples); +/** + * @brief Q15 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ +void arm_cmplx_mag_q15( + q15_t *pSrc, + q15_t *pDst, + uint32_t numSamples); - /** - * @brief Q15 complex dot product - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[in] numSamples number of complex samples in each vector - * @param[out] realResult real part of the result returned here - * @param[out] imagResult imaginary part of the result returned here - */ - void arm_cmplx_dot_prod_q15( - q15_t * pSrcA, - q15_t * pSrcB, - uint32_t numSamples, - q31_t * realResult, - q31_t * imagResult); +/** + * @brief Q15 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ +void arm_cmplx_dot_prod_q15( + q15_t *pSrcA, + q15_t *pSrcB, + uint32_t numSamples, + q31_t *realResult, + q31_t *imagResult); - /** - * @brief Q31 complex dot product - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[in] numSamples number of complex samples in each vector - * @param[out] realResult real part of the result returned here - * @param[out] imagResult imaginary part of the result returned here - */ - void arm_cmplx_dot_prod_q31( - q31_t * pSrcA, - q31_t * pSrcB, - uint32_t numSamples, - q63_t * realResult, - q63_t * imagResult); +/** + * @brief Q31 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ +void arm_cmplx_dot_prod_q31( + q31_t *pSrcA, + q31_t *pSrcB, + uint32_t numSamples, + q63_t *realResult, + q63_t *imagResult); - /** - * @brief Floating-point complex dot product - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[in] numSamples number of complex samples in each vector - * @param[out] realResult real part of the result returned here - * @param[out] imagResult imaginary part of the result returned here - */ - void arm_cmplx_dot_prod_f32( - float32_t * pSrcA, - float32_t * pSrcB, - uint32_t numSamples, - float32_t * realResult, - float32_t * imagResult); +/** + * @brief Floating-point complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ +void arm_cmplx_dot_prod_f32( + float32_t *pSrcA, + float32_t *pSrcB, + uint32_t numSamples, + float32_t *realResult, + float32_t *imagResult); - /** - * @brief Q15 complex-by-real multiplication - * @param[in] pSrcCmplx points to the complex input vector - * @param[in] pSrcReal points to the real input vector - * @param[out] pCmplxDst points to the complex output vector - * @param[in] numSamples number of samples in each vector - */ - void arm_cmplx_mult_real_q15( - q15_t * pSrcCmplx, - q15_t * pSrcReal, - q15_t * pCmplxDst, - uint32_t numSamples); +/** + * @brief Q15 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ +void arm_cmplx_mult_real_q15( + q15_t *pSrcCmplx, + q15_t *pSrcReal, + q15_t *pCmplxDst, + uint32_t numSamples); - /** - * @brief Q31 complex-by-real multiplication - * @param[in] pSrcCmplx points to the complex input vector - * @param[in] pSrcReal points to the real input vector - * @param[out] pCmplxDst points to the complex output vector - * @param[in] numSamples number of samples in each vector - */ - void arm_cmplx_mult_real_q31( - q31_t * pSrcCmplx, - q31_t * pSrcReal, - q31_t * pCmplxDst, - uint32_t numSamples); +/** + * @brief Q31 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ +void arm_cmplx_mult_real_q31( + q31_t *pSrcCmplx, + q31_t *pSrcReal, + q31_t *pCmplxDst, + uint32_t numSamples); - /** - * @brief Floating-point complex-by-real multiplication - * @param[in] pSrcCmplx points to the complex input vector - * @param[in] pSrcReal points to the real input vector - * @param[out] pCmplxDst points to the complex output vector - * @param[in] numSamples number of samples in each vector - */ - void arm_cmplx_mult_real_f32( - float32_t * pSrcCmplx, - float32_t * pSrcReal, - float32_t * pCmplxDst, - uint32_t numSamples); +/** + * @brief Floating-point complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ +void arm_cmplx_mult_real_f32( + float32_t *pSrcCmplx, + float32_t *pSrcReal, + float32_t *pCmplxDst, + uint32_t numSamples); - /** - * @brief Minimum value of a Q7 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] result is output pointer - * @param[in] index is the array index of the minimum value in the input buffer. - */ - void arm_min_q7( - q7_t * pSrc, - uint32_t blockSize, - q7_t * result, - uint32_t * index); +/** + * @brief Minimum value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] result is output pointer + * @param[in] index is the array index of the minimum value in the input buffer. + */ +void arm_min_q7( + q7_t *pSrc, + uint32_t blockSize, + q7_t *result, + uint32_t *index); - /** - * @brief Minimum value of a Q15 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output pointer - * @param[in] pIndex is the array index of the minimum value in the input buffer. - */ - void arm_min_q15( - q15_t * pSrc, - uint32_t blockSize, - q15_t * pResult, - uint32_t * pIndex); +/** + * @brief Minimum value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[in] pIndex is the array index of the minimum value in the input buffer. + */ +void arm_min_q15( + q15_t *pSrc, + uint32_t blockSize, + q15_t *pResult, + uint32_t *pIndex); - /** - * @brief Minimum value of a Q31 vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output pointer - * @param[out] pIndex is the array index of the minimum value in the input buffer. - */ - void arm_min_q31( - q31_t * pSrc, - uint32_t blockSize, - q31_t * pResult, - uint32_t * pIndex); +/** + * @brief Minimum value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ +void arm_min_q31( + q31_t *pSrc, + uint32_t blockSize, + q31_t *pResult, + uint32_t *pIndex); - /** - * @brief Minimum value of a floating-point vector. - * @param[in] pSrc is input pointer - * @param[in] blockSize is the number of samples to process - * @param[out] pResult is output pointer - * @param[out] pIndex is the array index of the minimum value in the input buffer. - */ - void arm_min_f32( - float32_t * pSrc, - uint32_t blockSize, - float32_t * pResult, - uint32_t * pIndex); +/** + * @brief Minimum value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ +void arm_min_f32( + float32_t *pSrc, + uint32_t blockSize, + float32_t *pResult, + uint32_t *pIndex); /** @@ -6573,11 +6573,11 @@ void arm_rfft_fast_f32( * @param[out] pResult maximum value returned here * @param[out] pIndex index of maximum value returned here */ - void arm_max_q7( - q7_t * pSrc, - uint32_t blockSize, - q7_t * pResult, - uint32_t * pIndex); +void arm_max_q7( + q7_t *pSrc, + uint32_t blockSize, + q7_t *pResult, + uint32_t *pIndex); /** @@ -6587,11 +6587,11 @@ void arm_rfft_fast_f32( * @param[out] pResult maximum value returned here * @param[out] pIndex index of maximum value returned here */ - void arm_max_q15( - q15_t * pSrc, - uint32_t blockSize, - q15_t * pResult, - uint32_t * pIndex); +void arm_max_q15( + q15_t *pSrc, + uint32_t blockSize, + q15_t *pResult, + uint32_t *pIndex); /** @@ -6601,11 +6601,11 @@ void arm_rfft_fast_f32( * @param[out] pResult maximum value returned here * @param[out] pIndex index of maximum value returned here */ - void arm_max_q31( - q31_t * pSrc, - uint32_t blockSize, - q31_t * pResult, - uint32_t * pIndex); +void arm_max_q31( + q31_t *pSrc, + uint32_t blockSize, + q31_t *pResult, + uint32_t *pIndex); /** @@ -6615,226 +6615,226 @@ void arm_rfft_fast_f32( * @param[out] pResult maximum value returned here * @param[out] pIndex index of maximum value returned here */ - void arm_max_f32( - float32_t * pSrc, - uint32_t blockSize, - float32_t * pResult, - uint32_t * pIndex); +void arm_max_f32( + float32_t *pSrc, + uint32_t blockSize, + float32_t *pResult, + uint32_t *pIndex); - /** - * @brief Q15 complex-by-complex multiplication - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] numSamples number of complex samples in each vector - */ - void arm_cmplx_mult_cmplx_q15( - q15_t * pSrcA, - q15_t * pSrcB, - q15_t * pDst, - uint32_t numSamples); +/** + * @brief Q15 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ +void arm_cmplx_mult_cmplx_q15( + q15_t *pSrcA, + q15_t *pSrcB, + q15_t *pDst, + uint32_t numSamples); - /** - * @brief Q31 complex-by-complex multiplication - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] numSamples number of complex samples in each vector - */ - void arm_cmplx_mult_cmplx_q31( - q31_t * pSrcA, - q31_t * pSrcB, - q31_t * pDst, - uint32_t numSamples); +/** + * @brief Q31 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ +void arm_cmplx_mult_cmplx_q31( + q31_t *pSrcA, + q31_t *pSrcB, + q31_t *pDst, + uint32_t numSamples); - /** - * @brief Floating-point complex-by-complex multiplication - * @param[in] pSrcA points to the first input vector - * @param[in] pSrcB points to the second input vector - * @param[out] pDst points to the output vector - * @param[in] numSamples number of complex samples in each vector - */ - void arm_cmplx_mult_cmplx_f32( - float32_t * pSrcA, - float32_t * pSrcB, - float32_t * pDst, - uint32_t numSamples); +/** + * @brief Floating-point complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ +void arm_cmplx_mult_cmplx_f32( + float32_t *pSrcA, + float32_t *pSrcB, + float32_t *pDst, + uint32_t numSamples); - /** - * @brief Converts the elements of the floating-point vector to Q31 vector. - * @param[in] pSrc points to the floating-point input vector - * @param[out] pDst points to the Q31 output vector - * @param[in] blockSize length of the input vector - */ - void arm_float_to_q31( - float32_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the floating-point vector to Q31 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q31 output vector + * @param[in] blockSize length of the input vector + */ +void arm_float_to_q31( + float32_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @brief Converts the elements of the floating-point vector to Q15 vector. - * @param[in] pSrc points to the floating-point input vector - * @param[out] pDst points to the Q15 output vector - * @param[in] blockSize length of the input vector - */ - void arm_float_to_q15( - float32_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the floating-point vector to Q15 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q15 output vector + * @param[in] blockSize length of the input vector + */ +void arm_float_to_q15( + float32_t *pSrc, + q15_t *pDst, + uint32_t blockSize); - /** - * @brief Converts the elements of the floating-point vector to Q7 vector. - * @param[in] pSrc points to the floating-point input vector - * @param[out] pDst points to the Q7 output vector - * @param[in] blockSize length of the input vector - */ - void arm_float_to_q7( - float32_t * pSrc, - q7_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the floating-point vector to Q7 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q7 output vector + * @param[in] blockSize length of the input vector + */ +void arm_float_to_q7( + float32_t *pSrc, + q7_t *pDst, + uint32_t blockSize); - /** - * @brief Converts the elements of the Q31 vector to Q15 vector. - * @param[in] pSrc is input pointer - * @param[out] pDst is output pointer - * @param[in] blockSize is the number of samples to process - */ - void arm_q31_to_q15( - q31_t * pSrc, - q15_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the Q31 vector to Q15 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ +void arm_q31_to_q15( + q31_t *pSrc, + q15_t *pDst, + uint32_t blockSize); - /** - * @brief Converts the elements of the Q31 vector to Q7 vector. - * @param[in] pSrc is input pointer - * @param[out] pDst is output pointer - * @param[in] blockSize is the number of samples to process - */ - void arm_q31_to_q7( - q31_t * pSrc, - q7_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the Q31 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ +void arm_q31_to_q7( + q31_t *pSrc, + q7_t *pDst, + uint32_t blockSize); - /** - * @brief Converts the elements of the Q15 vector to floating-point vector. - * @param[in] pSrc is input pointer - * @param[out] pDst is output pointer - * @param[in] blockSize is the number of samples to process - */ - void arm_q15_to_float( - q15_t * pSrc, - float32_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the Q15 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ +void arm_q15_to_float( + q15_t *pSrc, + float32_t *pDst, + uint32_t blockSize); - /** - * @brief Converts the elements of the Q15 vector to Q31 vector. - * @param[in] pSrc is input pointer - * @param[out] pDst is output pointer - * @param[in] blockSize is the number of samples to process - */ - void arm_q15_to_q31( - q15_t * pSrc, - q31_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the Q15 vector to Q31 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ +void arm_q15_to_q31( + q15_t *pSrc, + q31_t *pDst, + uint32_t blockSize); - /** - * @brief Converts the elements of the Q15 vector to Q7 vector. - * @param[in] pSrc is input pointer - * @param[out] pDst is output pointer - * @param[in] blockSize is the number of samples to process - */ - void arm_q15_to_q7( - q15_t * pSrc, - q7_t * pDst, - uint32_t blockSize); +/** + * @brief Converts the elements of the Q15 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ +void arm_q15_to_q7( + q15_t *pSrc, + q7_t *pDst, + uint32_t blockSize); - /** - * @ingroup groupInterpolation - */ +/** + * @ingroup groupInterpolation + */ - /** - * @defgroup BilinearInterpolate Bilinear Interpolation - * - * Bilinear interpolation is an extension of linear interpolation applied to a two dimensional grid. - * The underlying function f(x, y) is sampled on a regular grid and the interpolation process - * determines values between the grid points. - * Bilinear interpolation is equivalent to two step linear interpolation, first in the x-dimension and then in the y-dimension. - * Bilinear interpolation is often used in image processing to rescale images. - * The CMSIS DSP library provides bilinear interpolation functions for Q7, Q15, Q31, and floating-point data types. - * - * Algorithm - * \par - * The instance structure used by the bilinear interpolation functions describes a two dimensional data table. - * For floating-point, the instance structure is defined as: - *
-   *   typedef struct
-   *   {
-   *     uint16_t numRows;
-   *     uint16_t numCols;
-   *     float32_t *pData;
-   * } arm_bilinear_interp_instance_f32;
-   * 
- * - * \par - * where numRows specifies the number of rows in the table; - * numCols specifies the number of columns in the table; - * and pData points to an array of size numRows*numCols values. - * The data table pTable is organized in row order and the supplied data values fall on integer indexes. - * That is, table element (x,y) is located at pTable[x + y*numCols] where x and y are integers. - * - * \par - * Let (x, y) specify the desired interpolation point. Then define: - *
-   *     XF = floor(x)
-   *     YF = floor(y)
-   * 
- * \par - * The interpolated output point is computed as: - *
-   *  f(x, y) = f(XF, YF) * (1-(x-XF)) * (1-(y-YF))
-   *           + f(XF+1, YF) * (x-XF)*(1-(y-YF))
-   *           + f(XF, YF+1) * (1-(x-XF))*(y-YF)
-   *           + f(XF+1, YF+1) * (x-XF)*(y-YF)
-   * 
- * Note that the coordinates (x, y) contain integer and fractional components. - * The integer components specify which portion of the table to use while the - * fractional components control the interpolation processor. - * - * \par - * if (x,y) are outside of the table boundary, Bilinear interpolation returns zero output. - */ +/** + * @defgroup BilinearInterpolate Bilinear Interpolation + * + * Bilinear interpolation is an extension of linear interpolation applied to a two dimensional grid. + * The underlying function f(x, y) is sampled on a regular grid and the interpolation process + * determines values between the grid points. + * Bilinear interpolation is equivalent to two step linear interpolation, first in the x-dimension and then in the y-dimension. + * Bilinear interpolation is often used in image processing to rescale images. + * The CMSIS DSP library provides bilinear interpolation functions for Q7, Q15, Q31, and floating-point data types. + * + * Algorithm + * \par + * The instance structure used by the bilinear interpolation functions describes a two dimensional data table. + * For floating-point, the instance structure is defined as: + *
+ *   typedef struct
+ *   {
+ *     uint16_t numRows;
+ *     uint16_t numCols;
+ *     float32_t *pData;
+ * } arm_bilinear_interp_instance_f32;
+ * 
+ * + * \par + * where numRows specifies the number of rows in the table; + * numCols specifies the number of columns in the table; + * and pData points to an array of size numRows*numCols values. + * The data table pTable is organized in row order and the supplied data values fall on integer indexes. + * That is, table element (x,y) is located at pTable[x + y*numCols] where x and y are integers. + * + * \par + * Let (x, y) specify the desired interpolation point. Then define: + *
+ *     XF = floor(x)
+ *     YF = floor(y)
+ * 
+ * \par + * The interpolated output point is computed as: + *
+ *  f(x, y) = f(XF, YF) * (1-(x-XF)) * (1-(y-YF))
+ *           + f(XF+1, YF) * (x-XF)*(1-(y-YF))
+ *           + f(XF, YF+1) * (1-(x-XF))*(y-YF)
+ *           + f(XF+1, YF+1) * (x-XF)*(y-YF)
+ * 
+ * Note that the coordinates (x, y) contain integer and fractional components. + * The integer components specify which portion of the table to use while the + * fractional components control the interpolation processor. + * + * \par + * if (x,y) are outside of the table boundary, Bilinear interpolation returns zero output. + */ - /** - * @addtogroup BilinearInterpolate - * @{ - */ +/** + * @addtogroup BilinearInterpolate + * @{ + */ - /** - * - * @brief Floating-point bilinear interpolation. - * @param[in,out] S points to an instance of the interpolation structure. - * @param[in] X interpolation coordinate. - * @param[in] Y interpolation coordinate. - * @return out interpolated value. - */ - CMSIS_INLINE __STATIC_INLINE float32_t arm_bilinear_interp_f32( - const arm_bilinear_interp_instance_f32 * S, - float32_t X, - float32_t Y) - { +/** +* +* @brief Floating-point bilinear interpolation. +* @param[in,out] S points to an instance of the interpolation structure. +* @param[in] X interpolation coordinate. +* @param[in] Y interpolation coordinate. +* @return out interpolated value. +*/ +CMSIS_INLINE __STATIC_INLINE float32_t arm_bilinear_interp_f32( + const arm_bilinear_interp_instance_f32 *S, + float32_t X, + float32_t Y) +{ float32_t out; float32_t f00, f01, f10, f11; float32_t *pData = S->pData; @@ -6849,7 +6849,7 @@ void arm_rfft_fast_f32( /* Returns zero output when values are outside table boundary */ if (xIndex < 0 || xIndex > (S->numRows - 1) || yIndex < 0 || yIndex > (S->numCols - 1)) { - return (0); + return (0); } /* Calculation of index for two nearest points in X-direction */ @@ -6885,22 +6885,22 @@ void arm_rfft_fast_f32( /* return to application */ return (out); - } +} - /** - * - * @brief Q31 bilinear interpolation. - * @param[in,out] S points to an instance of the interpolation structure. - * @param[in] X interpolation coordinate in 12.20 format. - * @param[in] Y interpolation coordinate in 12.20 format. - * @return out interpolated value. - */ - CMSIS_INLINE __STATIC_INLINE q31_t arm_bilinear_interp_q31( - arm_bilinear_interp_instance_q31 * S, - q31_t X, - q31_t Y) - { +/** +* +* @brief Q31 bilinear interpolation. +* @param[in,out] S points to an instance of the interpolation structure. +* @param[in] X interpolation coordinate in 12.20 format. +* @param[in] Y interpolation coordinate in 12.20 format. +* @return out interpolated value. +*/ +CMSIS_INLINE __STATIC_INLINE q31_t arm_bilinear_interp_q31( + arm_bilinear_interp_instance_q31 *S, + q31_t X, + q31_t Y) +{ q31_t out; /* Temporary output */ q31_t acc = 0; /* output */ q31_t xfract, yfract; /* X, Y fractional parts */ @@ -6923,7 +6923,7 @@ void arm_rfft_fast_f32( /* Returns zero output when values are outside table boundary */ if (rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) { - return (0); + return (0); } /* 20 bits for the fractional part */ @@ -6943,38 +6943,38 @@ void arm_rfft_fast_f32( y2 = pYData[(rI) + (int32_t)nCols * (cI + 1) + 1]; /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 3.29(q29) format */ - out = ((q31_t) (((q63_t) x1 * (0x7FFFFFFF - xfract)) >> 32)); - acc = ((q31_t) (((q63_t) out * (0x7FFFFFFF - yfract)) >> 32)); + out = ((q31_t)(((q63_t) x1 * (0x7FFFFFFF - xfract)) >> 32)); + acc = ((q31_t)(((q63_t) out * (0x7FFFFFFF - yfract)) >> 32)); /* x2 * (xfract) * (1-yfract) in 3.29(q29) and adding to acc */ - out = ((q31_t) ((q63_t) x2 * (0x7FFFFFFF - yfract) >> 32)); - acc += ((q31_t) ((q63_t) out * (xfract) >> 32)); + out = ((q31_t)((q63_t) x2 * (0x7FFFFFFF - yfract) >> 32)); + acc += ((q31_t)((q63_t) out * (xfract) >> 32)); /* y1 * (1 - xfract) * (yfract) in 3.29(q29) and adding to acc */ - out = ((q31_t) ((q63_t) y1 * (0x7FFFFFFF - xfract) >> 32)); - acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + out = ((q31_t)((q63_t) y1 * (0x7FFFFFFF - xfract) >> 32)); + acc += ((q31_t)((q63_t) out * (yfract) >> 32)); /* y2 * (xfract) * (yfract) in 3.29(q29) and adding to acc */ - out = ((q31_t) ((q63_t) y2 * (xfract) >> 32)); - acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + out = ((q31_t)((q63_t) y2 * (xfract) >> 32)); + acc += ((q31_t)((q63_t) out * (yfract) >> 32)); /* Convert acc to 1.31(q31) format */ return ((q31_t)(acc << 2)); - } +} - /** - * @brief Q15 bilinear interpolation. - * @param[in,out] S points to an instance of the interpolation structure. - * @param[in] X interpolation coordinate in 12.20 format. - * @param[in] Y interpolation coordinate in 12.20 format. - * @return out interpolated value. - */ - CMSIS_INLINE __STATIC_INLINE q15_t arm_bilinear_interp_q15( - arm_bilinear_interp_instance_q15 * S, - q31_t X, - q31_t Y) - { +/** +* @brief Q15 bilinear interpolation. +* @param[in,out] S points to an instance of the interpolation structure. +* @param[in] X interpolation coordinate in 12.20 format. +* @param[in] Y interpolation coordinate in 12.20 format. +* @return out interpolated value. +*/ +CMSIS_INLINE __STATIC_INLINE q15_t arm_bilinear_interp_q15( + arm_bilinear_interp_instance_q15 *S, + q31_t X, + q31_t Y) +{ q63_t acc = 0; /* output */ q31_t out; /* Temporary output */ q15_t x1, x2, y1, y2; /* Nearest output values */ @@ -6997,7 +6997,7 @@ void arm_rfft_fast_f32( /* Returns zero output when values are outside table boundary */ if (rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) { - return (0); + return (0); } /* 20 bits for the fractional part */ @@ -7020,39 +7020,39 @@ void arm_rfft_fast_f32( /* x1 is in 1.15(q15), xfract in 12.20 format and out is in 13.35 format */ /* convert 13.35 to 13.31 by right shifting and out is in 1.31 */ - out = (q31_t) (((q63_t) x1 * (0xFFFFF - xfract)) >> 4u); + out = (q31_t)(((q63_t) x1 * (0xFFFFF - xfract)) >> 4u); acc = ((q63_t) out * (0xFFFFF - yfract)); /* x2 * (xfract) * (1-yfract) in 1.51 and adding to acc */ - out = (q31_t) (((q63_t) x2 * (0xFFFFF - yfract)) >> 4u); + out = (q31_t)(((q63_t) x2 * (0xFFFFF - yfract)) >> 4u); acc += ((q63_t) out * (xfract)); /* y1 * (1 - xfract) * (yfract) in 1.51 and adding to acc */ - out = (q31_t) (((q63_t) y1 * (0xFFFFF - xfract)) >> 4u); + out = (q31_t)(((q63_t) y1 * (0xFFFFF - xfract)) >> 4u); acc += ((q63_t) out * (yfract)); /* y2 * (xfract) * (yfract) in 1.51 and adding to acc */ - out = (q31_t) (((q63_t) y2 * (xfract)) >> 4u); + out = (q31_t)(((q63_t) y2 * (xfract)) >> 4u); acc += ((q63_t) out * (yfract)); /* acc is in 13.51 format and down shift acc by 36 times */ /* Convert out to 1.15 format */ return ((q15_t)(acc >> 36)); - } +} - /** - * @brief Q7 bilinear interpolation. - * @param[in,out] S points to an instance of the interpolation structure. - * @param[in] X interpolation coordinate in 12.20 format. - * @param[in] Y interpolation coordinate in 12.20 format. - * @return out interpolated value. - */ - CMSIS_INLINE __STATIC_INLINE q7_t arm_bilinear_interp_q7( - arm_bilinear_interp_instance_q7 * S, - q31_t X, - q31_t Y) - { +/** +* @brief Q7 bilinear interpolation. +* @param[in,out] S points to an instance of the interpolation structure. +* @param[in] X interpolation coordinate in 12.20 format. +* @param[in] Y interpolation coordinate in 12.20 format. +* @return out interpolated value. +*/ +CMSIS_INLINE __STATIC_INLINE q7_t arm_bilinear_interp_q7( + arm_bilinear_interp_instance_q7 *S, + q31_t X, + q31_t Y) +{ q63_t acc = 0; /* output */ q31_t out; /* Temporary output */ q31_t xfract, yfract; /* X, Y fractional parts */ @@ -7075,7 +7075,7 @@ void arm_rfft_fast_f32( /* Returns zero output when values are outside table boundary */ if (rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) { - return (0); + return (0); } /* 20 bits for the fractional part */ @@ -7112,11 +7112,11 @@ void arm_rfft_fast_f32( /* acc in 16.47 format and down shift by 40 to convert to 1.7 format */ return ((q7_t)(acc >> 40)); - } +} - /** - * @} end of BilinearInterpolate group - */ +/** + * @} end of BilinearInterpolate group + */ /* SMMLAR */ @@ -7145,82 +7145,82 @@ void arm_rfft_fast_f32( #if defined ( __CC_ARM ) - /* Enter low optimization region - place directly above function definition */ - #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) - #define LOW_OPTIMIZATION_ENTER \ +/* Enter low optimization region - place directly above function definition */ +#if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) +#define LOW_OPTIMIZATION_ENTER \ _Pragma ("push") \ _Pragma ("O1") - #else - #define LOW_OPTIMIZATION_ENTER - #endif +#else +#define LOW_OPTIMIZATION_ENTER +#endif - /* Exit low optimization region - place directly after end of function definition */ - #if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) - #define LOW_OPTIMIZATION_EXIT \ +/* Exit low optimization region - place directly after end of function definition */ +#if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) +#define LOW_OPTIMIZATION_EXIT \ _Pragma ("pop") - #else - #define LOW_OPTIMIZATION_EXIT - #endif +#else +#define LOW_OPTIMIZATION_EXIT +#endif - /* Enter low optimization region - place directly above function definition */ - #define IAR_ONLY_LOW_OPTIMIZATION_ENTER +/* Enter low optimization region - place directly above function definition */ +#define IAR_ONLY_LOW_OPTIMIZATION_ENTER - /* Exit low optimization region - place directly after end of function definition */ - #define IAR_ONLY_LOW_OPTIMIZATION_EXIT +/* Exit low optimization region - place directly after end of function definition */ +#define IAR_ONLY_LOW_OPTIMIZATION_EXIT #elif defined (__ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) - #define LOW_OPTIMIZATION_ENTER - #define LOW_OPTIMIZATION_EXIT - #define IAR_ONLY_LOW_OPTIMIZATION_ENTER - #define IAR_ONLY_LOW_OPTIMIZATION_EXIT +#define LOW_OPTIMIZATION_ENTER +#define LOW_OPTIMIZATION_EXIT +#define IAR_ONLY_LOW_OPTIMIZATION_ENTER +#define IAR_ONLY_LOW_OPTIMIZATION_EXIT #elif defined ( __GNUC__ ) - #define LOW_OPTIMIZATION_ENTER \ +#define LOW_OPTIMIZATION_ENTER \ __attribute__(( optimize("-O1") )) - #define LOW_OPTIMIZATION_EXIT - #define IAR_ONLY_LOW_OPTIMIZATION_ENTER - #define IAR_ONLY_LOW_OPTIMIZATION_EXIT +#define LOW_OPTIMIZATION_EXIT +#define IAR_ONLY_LOW_OPTIMIZATION_ENTER +#define IAR_ONLY_LOW_OPTIMIZATION_EXIT #elif defined ( __ICCARM__ ) - /* Enter low optimization region - place directly above function definition */ - #if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) - #define LOW_OPTIMIZATION_ENTER \ +/* Enter low optimization region - place directly above function definition */ +#if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) +#define LOW_OPTIMIZATION_ENTER \ _Pragma ("optimize=low") - #else - #define LOW_OPTIMIZATION_ENTER - #endif +#else +#define LOW_OPTIMIZATION_ENTER +#endif - /* Exit low optimization region - place directly after end of function definition */ - #define LOW_OPTIMIZATION_EXIT +/* Exit low optimization region - place directly after end of function definition */ +#define LOW_OPTIMIZATION_EXIT - /* Enter low optimization region - place directly above function definition */ - #if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) - #define IAR_ONLY_LOW_OPTIMIZATION_ENTER \ +/* Enter low optimization region - place directly above function definition */ +#if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) +#define IAR_ONLY_LOW_OPTIMIZATION_ENTER \ _Pragma ("optimize=low") - #else - #define IAR_ONLY_LOW_OPTIMIZATION_ENTER - #endif +#else +#define IAR_ONLY_LOW_OPTIMIZATION_ENTER +#endif - /* Exit low optimization region - place directly after end of function definition */ - #define IAR_ONLY_LOW_OPTIMIZATION_EXIT +/* Exit low optimization region - place directly after end of function definition */ +#define IAR_ONLY_LOW_OPTIMIZATION_EXIT #elif defined ( __TI_ARM__ ) - #define LOW_OPTIMIZATION_ENTER - #define LOW_OPTIMIZATION_EXIT - #define IAR_ONLY_LOW_OPTIMIZATION_ENTER - #define IAR_ONLY_LOW_OPTIMIZATION_EXIT +#define LOW_OPTIMIZATION_ENTER +#define LOW_OPTIMIZATION_EXIT +#define IAR_ONLY_LOW_OPTIMIZATION_ENTER +#define IAR_ONLY_LOW_OPTIMIZATION_EXIT #elif defined ( __CSMC__ ) - #define LOW_OPTIMIZATION_ENTER - #define LOW_OPTIMIZATION_EXIT - #define IAR_ONLY_LOW_OPTIMIZATION_ENTER - #define IAR_ONLY_LOW_OPTIMIZATION_EXIT +#define LOW_OPTIMIZATION_ENTER +#define LOW_OPTIMIZATION_EXIT +#define IAR_ONLY_LOW_OPTIMIZATION_ENTER +#define IAR_ONLY_LOW_OPTIMIZATION_EXIT #elif defined ( __TASKING__ ) - #define LOW_OPTIMIZATION_ENTER - #define LOW_OPTIMIZATION_EXIT - #define IAR_ONLY_LOW_OPTIMIZATION_ENTER - #define IAR_ONLY_LOW_OPTIMIZATION_EXIT +#define LOW_OPTIMIZATION_ENTER +#define LOW_OPTIMIZATION_EXIT +#define IAR_ONLY_LOW_OPTIMIZATION_ENTER +#define IAR_ONLY_LOW_OPTIMIZATION_EXIT #endif @@ -7235,7 +7235,7 @@ void arm_rfft_fast_f32( #elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) #elif defined ( __GNUC__ ) -#pragma GCC diagnostic pop + #pragma GCC diagnostic pop #elif defined ( __ICCARM__ ) @@ -7246,7 +7246,7 @@ void arm_rfft_fast_f32( #elif defined ( __TASKING__ ) #else - #error Unknown compiler + #error Unknown compiler #endif #endif /* _ARM_MATH_H */ diff --git a/bsp/nuvoton/libraries/m2354/CMSIS/Include/cmsis_compiler.h b/bsp/nuvoton/libraries/m2354/CMSIS/Include/cmsis_compiler.h index 147c8089df..971380b7d1 100644 --- a/bsp/nuvoton/libraries/m2354/CMSIS/Include/cmsis_compiler.h +++ b/bsp/nuvoton/libraries/m2354/CMSIS/Include/cmsis_compiler.h @@ -31,21 +31,21 @@ * ARM Compiler 4/5 */ #if defined ( __CC_ARM ) - #include "cmsis_armcc.h" +#include "cmsis_armcc.h" /* * ARM Compiler 6 (armclang) */ #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #include "cmsis_armclang.h" +#include "cmsis_armclang.h" /* * GNU Compiler */ #elif defined ( __GNUC__ ) - #include "cmsis_gcc.h" +#include "cmsis_gcc.h" /* @@ -54,298 +54,313 @@ #elif defined ( __ICCARM__ ) - #ifndef __ASM +#ifndef __ASM #define __ASM __asm - #endif - #ifndef __INLINE +#endif +#ifndef __INLINE #define __INLINE inline - #endif - #ifndef __STATIC_INLINE +#endif +#ifndef __STATIC_INLINE #define __STATIC_INLINE static inline - #endif +#endif - #include +#include - /* CMSIS compiler control architecture macros */ - #if (__CORE__ == __ARM6M__) || (__CORE__ == __ARM6SM__) +/* CMSIS compiler control architecture macros */ +#if (__CORE__ == __ARM6M__) || (__CORE__ == __ARM6SM__) #ifndef __ARM_ARCH_6M__ - #define __ARM_ARCH_6M__ 1 + #define __ARM_ARCH_6M__ 1 #endif - #elif (__CORE__ == __ARM7M__) +#elif (__CORE__ == __ARM7M__) #ifndef __ARM_ARCH_7M__ - #define __ARM_ARCH_7M__ 1 + #define __ARM_ARCH_7M__ 1 #endif - #elif (__CORE__ == __ARM7EM__) +#elif (__CORE__ == __ARM7EM__) #ifndef __ARM_ARCH_7EM__ - #define __ARM_ARCH_7EM__ 1 + #define __ARM_ARCH_7EM__ 1 #endif - #endif +#endif - #ifndef __NO_RETURN +#ifndef __NO_RETURN #define __NO_RETURN __noreturn - #endif - #ifndef __USED +#endif +#ifndef __USED #define __USED __root - #endif - #ifndef __WEAK +#endif +#ifndef __WEAK #define __WEAK __weak - #endif - #ifndef __PACKED +#endif +#ifndef __PACKED #define __PACKED __packed - #endif - #ifndef __PACKED_STRUCT +#endif +#ifndef __PACKED_STRUCT #define __PACKED_STRUCT __packed struct - #endif - #ifndef __PACKED_UNION +#endif +#ifndef __PACKED_UNION #define __PACKED_UNION __packed union - #endif - #ifndef __UNALIGNED_UINT32 /* deprecated */ - __packed struct T_UINT32 { uint32_t v; }; - #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) - #endif - #ifndef __UNALIGNED_UINT16_WRITE - __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; - #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT16_READ - __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; - #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) - #endif - #ifndef __UNALIGNED_UINT32_WRITE - __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; - #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT32_READ - __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; - #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) - #endif - #ifndef __ALIGNED +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ +__packed struct T_UINT32 +{ + uint32_t v; +}; +#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE +__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; +#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ +__PACKED_STRUCT T_UINT16_READ { uint16_t v; }; +#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE +__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; +#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ +__PACKED_STRUCT T_UINT32_READ { uint32_t v; }; +#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED //#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. #define __ALIGNED(x) - #endif - #ifndef __RESTRICT +#endif +#ifndef __RESTRICT //#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. #define __RESTRICT - #endif +#endif - // Workaround for missing __CLZ intrinsic in - // various versions of the IAR compilers. - // __IAR_FEATURE_CLZ__ should be defined by - // the compiler that supports __CLZ internally. - #if (defined (__ARM_ARCH_6M__)) && (__ARM_ARCH_6M__ == 1) && (!defined (__IAR_FEATURE_CLZ__)) - __STATIC_INLINE uint32_t __CLZ(uint32_t data) +// Workaround for missing __CLZ intrinsic in +// various versions of the IAR compilers. +// __IAR_FEATURE_CLZ__ should be defined by +// the compiler that supports __CLZ internally. +#if (defined (__ARM_ARCH_6M__)) && (__ARM_ARCH_6M__ == 1) && (!defined (__IAR_FEATURE_CLZ__)) +__STATIC_INLINE uint32_t __CLZ(uint32_t data) +{ + if (data == 0u) + { + return 32u; + } + + uint32_t count = 0; + uint32_t mask = 0x80000000; + + while ((data & mask) == 0) { - if (data == 0u) { return 32u; } - - uint32_t count = 0; - uint32_t mask = 0x80000000; - - while ((data & mask) == 0) - { count += 1u; mask = mask >> 1u; - } - - return (count); } - #endif + + return (count); +} +#endif /* * TI ARM Compiler */ #elif defined ( __TI_ARM__ ) - #include +#include - #ifndef __ASM +#ifndef __ASM #define __ASM __asm - #endif - #ifndef __INLINE +#endif +#ifndef __INLINE #define __INLINE inline - #endif - #ifndef __STATIC_INLINE +#endif +#ifndef __STATIC_INLINE #define __STATIC_INLINE static inline - #endif - #ifndef __NO_RETURN +#endif +#ifndef __NO_RETURN #define __NO_RETURN __attribute__((noreturn)) - #endif - #ifndef __USED +#endif +#ifndef __USED #define __USED __attribute__((used)) - #endif - #ifndef __WEAK +#endif +#ifndef __WEAK #define __WEAK __attribute__((weak)) - #endif - #ifndef __PACKED +#endif +#ifndef __PACKED #define __PACKED __attribute__((packed)) - #endif - #ifndef __PACKED_STRUCT +#endif +#ifndef __PACKED_STRUCT #define __PACKED_STRUCT struct __attribute__((packed)) - #endif - #ifndef __PACKED_UNION +#endif +#ifndef __PACKED_UNION #define __PACKED_UNION union __attribute__((packed)) - #endif - #ifndef __UNALIGNED_UINT32 /* deprecated */ - struct __attribute__((packed)) T_UINT32 { uint32_t v; }; - #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) - #endif - #ifndef __UNALIGNED_UINT16_WRITE - __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; - #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT16_READ - __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; - #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) - #endif - #ifndef __UNALIGNED_UINT32_WRITE - __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; - #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT32_READ - __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; - #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) - #endif - #ifndef __ALIGNED +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ +struct __attribute__((packed)) T_UINT32 +{ + uint32_t v; +}; +#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE +__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; +#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ +__PACKED_STRUCT T_UINT16_READ { uint16_t v; }; +#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE +__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; +#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ +__PACKED_STRUCT T_UINT32_READ { uint32_t v; }; +#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED #define __ALIGNED(x) __attribute__((aligned(x))) - #endif - #ifndef __RESTRICT +#endif +#ifndef __RESTRICT #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. #define __RESTRICT - #endif +#endif /* * TASKING Compiler */ #elif defined ( __TASKING__ ) - /* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all intrinsics, - * Including the CMSIS ones. - */ +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ - #ifndef __ASM +#ifndef __ASM #define __ASM __asm - #endif - #ifndef __INLINE +#endif +#ifndef __INLINE #define __INLINE inline - #endif - #ifndef __STATIC_INLINE +#endif +#ifndef __STATIC_INLINE #define __STATIC_INLINE static inline - #endif - #ifndef __NO_RETURN +#endif +#ifndef __NO_RETURN #define __NO_RETURN __attribute__((noreturn)) - #endif - #ifndef __USED +#endif +#ifndef __USED #define __USED __attribute__((used)) - #endif - #ifndef __WEAK +#endif +#ifndef __WEAK #define __WEAK __attribute__((weak)) - #endif - #ifndef __PACKED +#endif +#ifndef __PACKED #define __PACKED __packed__ - #endif - #ifndef __PACKED_STRUCT +#endif +#ifndef __PACKED_STRUCT #define __PACKED_STRUCT struct __packed__ - #endif - #ifndef __PACKED_UNION +#endif +#ifndef __PACKED_UNION #define __PACKED_UNION union __packed__ - #endif - #ifndef __UNALIGNED_UINT32 /* deprecated */ - struct __packed__ T_UINT32 { uint32_t v; }; - #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) - #endif - #ifndef __UNALIGNED_UINT16_WRITE - __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; - #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT16_READ - __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; - #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) - #endif - #ifndef __UNALIGNED_UINT32_WRITE - __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; - #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT32_READ - __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; - #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) - #endif - #ifndef __ALIGNED +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ +struct __packed__ T_UINT32 +{ + uint32_t v; +}; +#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE +__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; +#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ +__PACKED_STRUCT T_UINT16_READ { uint16_t v; }; +#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE +__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; +#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ +__PACKED_STRUCT T_UINT32_READ { uint32_t v; }; +#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED #define __ALIGNED(x) __align(x) - #endif - #ifndef __RESTRICT +#endif +#ifndef __RESTRICT #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. #define __RESTRICT - #endif +#endif /* * COSMIC Compiler */ #elif defined ( __CSMC__ ) - #include +#include - #ifndef __ASM +#ifndef __ASM #define __ASM _asm - #endif - #ifndef __INLINE +#endif +#ifndef __INLINE #define __INLINE inline - #endif - #ifndef __STATIC_INLINE +#endif +#ifndef __STATIC_INLINE #define __STATIC_INLINE static inline - #endif - #ifndef __NO_RETURN +#endif +#ifndef __NO_RETURN // NO RETURN is automatically detected hence no warning here #define __NO_RETURN - #endif - #ifndef __USED +#endif +#ifndef __USED #warning No compiler specific solution for __USED. __USED is ignored. #define __USED - #endif - #ifndef __WEAK +#endif +#ifndef __WEAK #define __WEAK __weak - #endif - #ifndef __PACKED +#endif +#ifndef __PACKED #define __PACKED @packed - #endif - #ifndef __PACKED_STRUCT +#endif +#ifndef __PACKED_STRUCT #define __PACKED_STRUCT @packed struct - #endif - #ifndef __PACKED_UNION +#endif +#ifndef __PACKED_UNION #define __PACKED_UNION @packed union - #endif - #ifndef __UNALIGNED_UINT32 /* deprecated */ - @packed struct T_UINT32 { uint32_t v; }; - #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) - #endif - #ifndef __UNALIGNED_UINT16_WRITE - __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; - #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT16_READ - __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; - #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) - #endif - #ifndef __UNALIGNED_UINT32_WRITE - __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; - #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT32_READ - __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; - #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) - #endif - #ifndef __ALIGNED +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ +@packed struct T_UINT32 +{ + uint32_t v; +}; +#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE +__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; +#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ +__PACKED_STRUCT T_UINT16_READ { uint16_t v; }; +#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE +__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; +#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ +__PACKED_STRUCT T_UINT32_READ { uint32_t v; }; +#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. #define __ALIGNED(x) - #endif - #ifndef __RESTRICT +#endif +#ifndef __RESTRICT #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. #define __RESTRICT - #endif +#endif #else - #error Unknown compiler. +#error Unknown compiler. #endif diff --git a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_armv8mbl.h b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_armv8mbl.h index 13003e1cd6..f37a244eda 100644 --- a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_armv8mbl.h +++ b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_armv8mbl.h @@ -23,9 +23,9 @@ */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ + #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang system_header /* treat file as system include file */ + #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_ARMV8MBL_H_GENERIC @@ -34,7 +34,7 @@ #include #ifdef __cplusplus - extern "C" { +extern "C" { #endif /** @@ -59,7 +59,7 @@ \ingroup Cortex_ARMv8MBL @{ */ - + #include "cmsis_version.h" /* CMSIS definitions */ @@ -76,39 +76,39 @@ #define __FPU_USED 0U #if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __TARGET_FPU_VFP +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __ARM_PCS_VFP +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __ARMVFP__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __TI_ARM__ ) - #if defined __TI_VFP_SUPPORT__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __TI_VFP_SUPPORT__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __FPU_VFP__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __CSMC__ ) - #if ( __CSMC__ & 0x400U) - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if ( __CSMC__ & 0x400U) +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #endif @@ -127,55 +127,55 @@ #define __CORE_ARMV8MBL_H_DEPENDANT #ifdef __cplusplus - extern "C" { +extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES - #ifndef __ARMv8MBL_REV - #define __ARMv8MBL_REV 0x0000U - #warning "__ARMv8MBL_REV not defined in device header file; using default!" - #endif +#ifndef __ARMv8MBL_REV +#define __ARMv8MBL_REV 0x0000U +#warning "__ARMv8MBL_REV not defined in device header file; using default!" +#endif - #ifndef __FPU_PRESENT - #define __FPU_PRESENT 0U - #warning "__FPU_PRESENT not defined in device header file; using default!" - #endif +#ifndef __FPU_PRESENT +#define __FPU_PRESENT 0U +#warning "__FPU_PRESENT not defined in device header file; using default!" +#endif - #ifndef __MPU_PRESENT - #define __MPU_PRESENT 0U - #warning "__MPU_PRESENT not defined in device header file; using default!" - #endif +#ifndef __MPU_PRESENT +#define __MPU_PRESENT 0U +#warning "__MPU_PRESENT not defined in device header file; using default!" +#endif - #ifndef __SAUREGION_PRESENT - #define __SAUREGION_PRESENT 0U - #warning "__SAUREGION_PRESENT not defined in device header file; using default!" - #endif +#ifndef __SAUREGION_PRESENT +#define __SAUREGION_PRESENT 0U +#warning "__SAUREGION_PRESENT not defined in device header file; using default!" +#endif - #ifndef __VTOR_PRESENT - #define __VTOR_PRESENT 0U - #warning "__VTOR_PRESENT not defined in device header file; using default!" - #endif +#ifndef __VTOR_PRESENT +#define __VTOR_PRESENT 0U +#warning "__VTOR_PRESENT not defined in device header file; using default!" +#endif - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 2U - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif +#ifndef __NVIC_PRIO_BITS +#define __NVIC_PRIO_BITS 2U +#warning "__NVIC_PRIO_BITS not defined in device header file; using default!" +#endif - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0U - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 0U +#warning "__Vendor_SysTickConfig not defined in device header file; using default!" +#endif - #ifndef __ETM_PRESENT - #define __ETM_PRESENT 0U - #warning "__ETM_PRESENT not defined in device header file; using default!" - #endif +#ifndef __ETM_PRESENT +#define __ETM_PRESENT 0U +#warning "__ETM_PRESENT not defined in device header file; using default!" +#endif - #ifndef __MTB_PRESENT - #define __MTB_PRESENT 0U - #warning "__MTB_PRESENT not defined in device header file; using default!" - #endif +#ifndef __MTB_PRESENT +#define __MTB_PRESENT 0U +#warning "__MTB_PRESENT not defined in device header file; using default!" +#endif #endif @@ -188,9 +188,9 @@ \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ +#define __I volatile /*!< Defines 'read only' permissions */ #else - #define __I volatile const /*!< Defines 'read only' permissions */ +#define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ @@ -232,15 +232,15 @@ */ typedef union { - struct - { - uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t _reserved0: 28; /*!< bit: 0..27 Reserved */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ @@ -262,12 +262,12 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ @@ -280,18 +280,18 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 15; /*!< bit: 9..23 Reserved */ + uint32_t T: 1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1: 3; /*!< bit: 25..27 Reserved */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ @@ -319,13 +319,13 @@ typedef union */ typedef union { - struct - { - uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ - uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t nPRIV: 1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL: 1; /*!< bit: 1 Stack-pointer select */ + uint32_t _reserved1: 30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ @@ -350,19 +350,19 @@ typedef union */ typedef struct { - __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[16U]; - __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[16U]; - __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[16U]; - __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[16U]; - __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ - uint32_t RESERVED4[16U]; - __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ - uint32_t RESERVED5[16U]; - __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ } NVIC_Type; /*@} end of group CMSIS_NVIC */ @@ -380,19 +380,19 @@ typedef struct */ typedef struct { - __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) - __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ #else - uint32_t RESERVED0; + uint32_t RESERVED0; #endif - __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - uint32_t RESERVED1; - __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ - __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ } SCB_Type; /* SCB CPUID Register Definitions */ @@ -554,10 +554,10 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ @@ -606,72 +606,72 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ - uint32_t RESERVED0[6U]; - __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ - __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ - uint32_t RESERVED1[1U]; - __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ - uint32_t RESERVED2[1U]; - __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ - uint32_t RESERVED3[1U]; - __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ - uint32_t RESERVED4[1U]; - __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ - uint32_t RESERVED5[1U]; - __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ - uint32_t RESERVED6[1U]; - __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ - uint32_t RESERVED7[1U]; - __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ - uint32_t RESERVED8[1U]; - __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ - uint32_t RESERVED9[1U]; - __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ - uint32_t RESERVED10[1U]; - __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ - uint32_t RESERVED11[1U]; - __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ - uint32_t RESERVED12[1U]; - __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ - uint32_t RESERVED13[1U]; - __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ - uint32_t RESERVED14[1U]; - __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ - uint32_t RESERVED15[1U]; - __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ - uint32_t RESERVED16[1U]; - __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ - uint32_t RESERVED17[1U]; - __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ - uint32_t RESERVED18[1U]; - __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ - uint32_t RESERVED19[1U]; - __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ - uint32_t RESERVED20[1U]; - __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ - uint32_t RESERVED21[1U]; - __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ - uint32_t RESERVED22[1U]; - __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ - uint32_t RESERVED23[1U]; - __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ - uint32_t RESERVED24[1U]; - __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ - uint32_t RESERVED25[1U]; - __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ - uint32_t RESERVED26[1U]; - __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ - uint32_t RESERVED27[1U]; - __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ - uint32_t RESERVED28[1U]; - __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ - uint32_t RESERVED29[1U]; - __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ - uint32_t RESERVED30[1U]; - __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ - uint32_t RESERVED31[1U]; - __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + uint32_t RESERVED0[6U]; + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ } DWT_Type; /* DWT Control Register Definitions */ @@ -721,30 +721,30 @@ typedef struct */ typedef struct { - __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ - __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ - uint32_t RESERVED0[2U]; - __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ - uint32_t RESERVED1[55U]; - __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ - uint32_t RESERVED2[131U]; - __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ - __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ - __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ - uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ - __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ - __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ - uint32_t RESERVED4[1U]; - __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ - __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ - __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ - uint32_t RESERVED5[39U]; - __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ - __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ - uint32_t RESERVED7[8U]; - __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ - __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ @@ -877,14 +877,14 @@ typedef struct */ typedef struct { - __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ - uint32_t RESERVED0[7U]; - __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ - __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + uint32_t RESERVED0[7U]; + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ } MPU_Type; /* MPU Type Register Definitions */ @@ -977,12 +977,12 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ - __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ - __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ #endif } SAU_Type; @@ -1034,13 +1034,13 @@ typedef struct */ typedef struct { - __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ - __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ - __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ - __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ - uint32_t RESERVED4[1U]; - __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ - __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ @@ -1157,48 +1157,48 @@ typedef struct */ /* Memory mapping of Core Hardware */ - #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ - #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ - #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ - #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ - #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ - #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ - #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ - #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ - #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ - #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ - #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ - #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ - #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ - #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ - #endif - - #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) - #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ - #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ - #endif +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ +#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) - #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ - #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ - #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ - #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ - #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ +#define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ +#define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ +#endif - #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ - #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ - #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ - #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ +#define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ +#define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ +#define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ +#define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ - #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ - #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ - #endif +#define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ +#define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ +#define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ +#define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +#define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ +#define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ +#endif #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} */ @@ -1227,33 +1227,33 @@ typedef struct */ #ifdef CMSIS_NVIC_VIRTUAL - #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE - #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" - #endif - #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE +#define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" +#endif +#include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else /*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for ARMv8-M Baseline */ /*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for ARMv8-M Baseline */ - #define NVIC_EnableIRQ __NVIC_EnableIRQ - #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ - #define NVIC_DisableIRQ __NVIC_DisableIRQ - #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ - #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ - #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ - #define NVIC_GetActive __NVIC_GetActive - #define NVIC_SetPriority __NVIC_SetPriority - #define NVIC_GetPriority __NVIC_GetPriority - #define NVIC_SystemReset __NVIC_SystemReset +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_GetActive __NVIC_GetActive +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority +#define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL - #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE - #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" - #endif - #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" +#endif +#include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else - #define NVIC_SetVector __NVIC_SetVector - #define NVIC_GetVector __NVIC_GetVector +#define NVIC_SetVector __NVIC_SetVector +#define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 @@ -1274,10 +1274,10 @@ typedef struct */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1291,14 +1291,14 @@ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1310,12 +1310,12 @@ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - __DSB(); - __ISB(); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } @@ -1329,14 +1329,14 @@ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1348,10 +1348,10 @@ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1363,10 +1363,10 @@ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1380,14 +1380,14 @@ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1402,14 +1402,14 @@ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1423,15 +1423,15 @@ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); - return((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); + return ((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1445,15 +1445,15 @@ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); - return((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); + return ((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ @@ -1469,16 +1469,16 @@ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | - (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); - } - else - { - SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | - (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } } @@ -1494,14 +1494,14 @@ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn)) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return ((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn)) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } } @@ -1518,11 +1518,11 @@ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) - uint32_t *vectors = (uint32_t *)SCB->VTOR; + uint32_t *vectors = (uint32_t *)SCB->VTOR; #else - uint32_t *vectors = (uint32_t *)0x0U; + uint32_t *vectors = (uint32_t *)0x0U; #endif - vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } @@ -1537,11 +1537,11 @@ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) - uint32_t *vectors = (uint32_t *)SCB->VTOR; + uint32_t *vectors = (uint32_t *)SCB->VTOR; #else - uint32_t *vectors = (uint32_t *)0x0U; + uint32_t *vectors = (uint32_t *)0x0U; #endif - return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } @@ -1551,16 +1551,16 @@ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SystemReset(void) { - __DSB(); /* Ensure all outstanding memory accesses included + __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ - SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - SCB_AIRCR_SYSRESETREQ_Msk); - __DSB(); /* Ensure completion of memory access */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ - for(;;) /* wait until reset */ - { - __NOP(); - } + for (;;) /* wait until reset */ + { + __NOP(); + } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) @@ -1572,10 +1572,10 @@ __STATIC_INLINE void __NVIC_SystemReset(void) */ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1589,14 +1589,14 @@ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1608,10 +1608,10 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1625,10 +1625,10 @@ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } } @@ -1640,10 +1640,10 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1655,10 +1655,10 @@ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1672,14 +1672,14 @@ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC_NS->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1694,16 +1694,16 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | - (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); - } - else - { - SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | - (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } } @@ -1718,14 +1718,14 @@ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) __STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn)) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return ((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn)) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } } #endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ @@ -1774,7 +1774,7 @@ __STATIC_INLINE uint32_t SCB_GetFPUType(void) */ __STATIC_INLINE void TZ_SAU_Enable(void) { - SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); } @@ -1818,18 +1818,18 @@ __STATIC_INLINE void TZ_SAU_Disable(void) */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } - SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) @@ -1847,18 +1847,18 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) */ __STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) { - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } - SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ diff --git a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_armv8mml.h b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_armv8mml.h index 5c4d6f6ee1..060d81e323 100644 --- a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_armv8mml.h +++ b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_armv8mml.h @@ -23,9 +23,9 @@ */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ + #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang system_header /* treat file as system include file */ + #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_ARMV8MML_H_GENERIC @@ -34,7 +34,7 @@ #include #ifdef __cplusplus - extern "C" { +extern "C" { #endif /** @@ -61,7 +61,7 @@ */ #include "cmsis_version.h" - + /* CMSIS ARMv8MML definitions */ #define __ARMv8MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __ARMv8MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ @@ -74,88 +74,88 @@ For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. */ #if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __TARGET_FPU_VFP +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __ARM_PCS_VFP +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __ARMVFP__ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __TI_ARM__ ) - #if defined __TI_VFP_SUPPORT__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __TI_VFP_SUPPORT__ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __FPU_VFP__ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __CSMC__ ) - #if ( __CSMC__ & 0x400U) - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if ( __CSMC__ & 0x400U) +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #endif @@ -174,45 +174,45 @@ #define __CORE_ARMV8MML_H_DEPENDANT #ifdef __cplusplus - extern "C" { +extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES - #ifndef __ARMv8MML_REV - #define __ARMv8MML_REV 0x0000U - #warning "__ARMv8MML_REV not defined in device header file; using default!" - #endif +#ifndef __ARMv8MML_REV +#define __ARMv8MML_REV 0x0000U +#warning "__ARMv8MML_REV not defined in device header file; using default!" +#endif - #ifndef __FPU_PRESENT - #define __FPU_PRESENT 0U - #warning "__FPU_PRESENT not defined in device header file; using default!" - #endif +#ifndef __FPU_PRESENT +#define __FPU_PRESENT 0U +#warning "__FPU_PRESENT not defined in device header file; using default!" +#endif - #ifndef __MPU_PRESENT - #define __MPU_PRESENT 0U - #warning "__MPU_PRESENT not defined in device header file; using default!" - #endif +#ifndef __MPU_PRESENT +#define __MPU_PRESENT 0U +#warning "__MPU_PRESENT not defined in device header file; using default!" +#endif - #ifndef __SAUREGION_PRESENT - #define __SAUREGION_PRESENT 0U - #warning "__SAUREGION_PRESENT not defined in device header file; using default!" - #endif +#ifndef __SAUREGION_PRESENT +#define __SAUREGION_PRESENT 0U +#warning "__SAUREGION_PRESENT not defined in device header file; using default!" +#endif - #ifndef __DSP_PRESENT - #define __DSP_PRESENT 0U - #warning "__DSP_PRESENT not defined in device header file; using default!" - #endif +#ifndef __DSP_PRESENT +#define __DSP_PRESENT 0U +#warning "__DSP_PRESENT not defined in device header file; using default!" +#endif - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 3U - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif +#ifndef __NVIC_PRIO_BITS +#define __NVIC_PRIO_BITS 3U +#warning "__NVIC_PRIO_BITS not defined in device header file; using default!" +#endif - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0U - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 0U +#warning "__Vendor_SysTickConfig not defined in device header file; using default!" +#endif #endif /* IO definitions (access restrictions to peripheral registers) */ @@ -224,9 +224,9 @@ \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ +#define __I volatile /*!< Defines 'read only' permissions */ #else - #define __I volatile const /*!< Defines 'read only' permissions */ +#define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ @@ -269,18 +269,18 @@ */ typedef union { - struct - { - uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t _reserved0: 16; /*!< bit: 0..15 Reserved */ + uint32_t GE: 4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1: 7; /*!< bit: 20..26 Reserved */ + uint32_t Q: 1; /*!< bit: 27 Saturation condition flag */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ @@ -308,12 +308,12 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ @@ -326,21 +326,21 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 7; /*!< bit: 9..15 Reserved */ + uint32_t GE: 4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1: 4; /*!< bit: 20..23 Reserved */ + uint32_t T: 1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT: 2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q: 1; /*!< bit: 27 Saturation condition flag */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ @@ -377,15 +377,15 @@ typedef union */ typedef union { - struct - { - uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ - uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ - uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ - uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t nPRIV: 1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL: 1; /*!< bit: 1 Stack-pointer select */ + uint32_t FPCA: 1; /*!< bit: 2 Floating-point context active */ + uint32_t SFPA: 1; /*!< bit: 3 Secure floating-point active */ + uint32_t _reserved1: 28; /*!< bit: 4..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ @@ -416,21 +416,21 @@ typedef union */ typedef struct { - __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[16U]; - __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[16U]; - __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[16U]; - __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[16U]; - __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ - uint32_t RESERVED4[16U]; - __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ - uint32_t RESERVED5[16U]; - __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ - uint32_t RESERVED6[580U]; - __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED6[580U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ @@ -452,56 +452,56 @@ typedef struct */ typedef struct { - __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ - __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ - __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ - __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ - __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ - __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ - __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ - __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ - __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ - __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ - __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ - __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ - __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ - __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ - __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ - __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ - __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ - __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ - __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ - __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ - uint32_t RESERVED3[92U]; - __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ - uint32_t RESERVED4[15U]; - __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ - __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ - __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ - uint32_t RESERVED5[1U]; - __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ - uint32_t RESERVED6[1U]; - __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ - __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ - __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ - __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ - __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ - __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ - __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ - __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ - uint32_t RESERVED7[6U]; - __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ - __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ - __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ - __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ - __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ - uint32_t RESERVED8[1U]; - __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ + uint32_t RESERVED3[92U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ } SCB_Type; /* SCB CPUID Register Definitions */ @@ -961,10 +961,10 @@ typedef struct */ typedef struct { - uint32_t RESERVED0[1U]; - __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ - __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ - __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ } SCnSCB_Type; /* Interrupt Controller Type Register Definitions */ @@ -986,10 +986,10 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ @@ -1038,40 +1038,40 @@ typedef struct */ typedef struct { - __OM union - { - __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ - __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ - __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ - } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ - uint32_t RESERVED0[864U]; - __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ - uint32_t RESERVED1[15U]; - __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ - uint32_t RESERVED2[15U]; - __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29U]; - __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ - uint32_t RESERVED4[43U]; - __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ - __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ - uint32_t RESERVED5[1U]; - __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ - uint32_t RESERVED6[4U]; - __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ - __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ - __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ - __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ - __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ - __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ - __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ - __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ - __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ - __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ - __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ - __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ + uint32_t RESERVED6[4U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Stimulus Port Register Definitions */ @@ -1153,81 +1153,81 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ - __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ - __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ - __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ - __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ - __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ - __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ - __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ - __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ - uint32_t RESERVED1[1U]; - __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ - uint32_t RESERVED2[1U]; - __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ - uint32_t RESERVED3[1U]; - __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ - uint32_t RESERVED4[1U]; - __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ - uint32_t RESERVED5[1U]; - __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ - uint32_t RESERVED6[1U]; - __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ - uint32_t RESERVED7[1U]; - __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ - uint32_t RESERVED8[1U]; - __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ - uint32_t RESERVED9[1U]; - __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ - uint32_t RESERVED10[1U]; - __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ - uint32_t RESERVED11[1U]; - __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ - uint32_t RESERVED12[1U]; - __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ - uint32_t RESERVED13[1U]; - __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ - uint32_t RESERVED14[1U]; - __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ - uint32_t RESERVED15[1U]; - __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ - uint32_t RESERVED16[1U]; - __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ - uint32_t RESERVED17[1U]; - __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ - uint32_t RESERVED18[1U]; - __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ - uint32_t RESERVED19[1U]; - __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ - uint32_t RESERVED20[1U]; - __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ - uint32_t RESERVED21[1U]; - __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ - uint32_t RESERVED22[1U]; - __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ - uint32_t RESERVED23[1U]; - __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ - uint32_t RESERVED24[1U]; - __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ - uint32_t RESERVED25[1U]; - __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ - uint32_t RESERVED26[1U]; - __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ - uint32_t RESERVED27[1U]; - __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ - uint32_t RESERVED28[1U]; - __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ - uint32_t RESERVED29[1U]; - __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ - uint32_t RESERVED30[1U]; - __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ - uint32_t RESERVED31[1U]; - __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ - uint32_t RESERVED32[934U]; - __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ - uint32_t RESERVED33[1U]; - __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + uint32_t RESERVED32[934U]; + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ + uint32_t RESERVED33[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ } DWT_Type; /* DWT Control Register Definitions */ @@ -1339,30 +1339,30 @@ typedef struct */ typedef struct { - __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ - __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ - uint32_t RESERVED0[2U]; - __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ - uint32_t RESERVED1[55U]; - __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ - uint32_t RESERVED2[131U]; - __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ - __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ - __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ - uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ - __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ - __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ - uint32_t RESERVED4[1U]; - __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ - __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ - __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ - uint32_t RESERVED5[39U]; - __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ - __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ - uint32_t RESERVED7[8U]; - __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ - __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ @@ -1495,20 +1495,20 @@ typedef struct */ typedef struct { - __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ - __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ - __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ - __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ - __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ - __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ - __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ - uint32_t RESERVED0[1]; - __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ - __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ + __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ + __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ + __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ + uint32_t RESERVED0[1]; + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ } MPU_Type; /* MPU Type Register Definitions */ @@ -1601,17 +1601,17 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ - __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ - __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ #else - uint32_t RESERVED0[3]; + uint32_t RESERVED0[3]; #endif - __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ - __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ + __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ + __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ } SAU_Type; /* SAU Control Register Definitions */ @@ -1687,12 +1687,12 @@ typedef struct */ typedef struct { - uint32_t RESERVED0[1U]; - __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ - __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ - __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ - __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ - __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ } FPU_Type; /* Floating-Point Context Control Register Definitions */ @@ -1817,13 +1817,13 @@ typedef struct */ typedef struct { - __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ - __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ - __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ - __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ - uint32_t RESERVED4[1U]; - __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ - __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ @@ -1973,57 +1973,57 @@ typedef struct */ /* Memory mapping of Core Hardware */ - #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ - #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ - #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ - #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ - #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ - #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ - #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ - #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ - #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ - #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ - #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ - #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ - #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ - #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ - #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ - #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ - #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ - #endif - - #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) - #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ - #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ - #endif - - #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ - #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ +#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) - #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ - #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ - #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ - #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ - #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ +#define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ +#define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ +#endif - #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ - #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ - #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ - #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ - #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ - #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ - #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ - #endif +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ +#define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ +#define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ +#define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ +#define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ - #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ - #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ +#define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ +#define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ +#define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ +#define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ +#define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +#define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ +#define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ +#endif + +#define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ +#define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} */ @@ -2053,33 +2053,33 @@ typedef struct */ #ifdef CMSIS_NVIC_VIRTUAL - #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE - #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" - #endif - #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE +#define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" +#endif +#include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else - #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping - #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping - #define NVIC_EnableIRQ __NVIC_EnableIRQ - #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ - #define NVIC_DisableIRQ __NVIC_DisableIRQ - #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ - #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ - #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ - #define NVIC_GetActive __NVIC_GetActive - #define NVIC_SetPriority __NVIC_SetPriority - #define NVIC_GetPriority __NVIC_GetPriority - #define NVIC_SystemReset __NVIC_SystemReset +#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping +#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_GetActive __NVIC_GetActive +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority +#define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL - #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE - #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" - #endif - #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" +#endif +#include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else - #define NVIC_SetVector __NVIC_SetVector - #define NVIC_GetVector __NVIC_GetVector +#define NVIC_SetVector __NVIC_SetVector +#define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 @@ -2097,15 +2097,15 @@ typedef struct */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - reg_value = SCB->AIRCR; /* read old register configuration */ - reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ - SCB->AIRCR = reg_value; + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; } @@ -2116,7 +2116,7 @@ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { - return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } @@ -2128,10 +2128,10 @@ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2145,14 +2145,14 @@ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2164,12 +2164,12 @@ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - __DSB(); - __ISB(); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } @@ -2183,14 +2183,14 @@ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2202,10 +2202,10 @@ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2217,10 +2217,10 @@ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2234,14 +2234,14 @@ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2256,14 +2256,14 @@ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2277,15 +2277,15 @@ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); - return((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); + return ((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2299,15 +2299,15 @@ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); - return((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); + return ((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ @@ -2323,14 +2323,14 @@ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->IPR[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } - else - { - SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } } @@ -2346,14 +2346,14 @@ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return(((uint32_t)NVIC->IPR[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return(((uint32_t)SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); - } + if ((int32_t)(IRQn) >= 0) + { + return (((uint32_t)NVIC->IPR[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return (((uint32_t)SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] >> (8U - __NVIC_PRIO_BITS))); + } } @@ -2368,19 +2368,19 @@ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ -__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +__STATIC_INLINE uint32_t NVIC_EncodePriority(uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - return ( - ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | - ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) - ); + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits)) - 1UL))) + ); } @@ -2395,17 +2395,17 @@ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t P \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ -__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +__STATIC_INLINE void NVIC_DecodePriority(uint32_t Priority, uint32_t PriorityGroup, uint32_t *const pPreemptPriority, uint32_t *const pSubPriority) { - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); - *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority) & (uint32_t)((1UL << (SubPriorityBits)) - 1UL); } @@ -2420,8 +2420,8 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { - uint32_t *vectors = (uint32_t *)SCB->VTOR; - vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } @@ -2435,8 +2435,8 @@ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { - uint32_t *vectors = (uint32_t *)SCB->VTOR; - return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } @@ -2446,17 +2446,17 @@ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SystemReset(void) { - __DSB(); /* Ensure all outstanding memory accesses included + __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ - SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | - SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ - __DSB(); /* Ensure completion of memory access */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ - for(;;) /* wait until reset */ - { - __NOP(); - } + for (;;) /* wait until reset */ + { + __NOP(); + } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) @@ -2471,15 +2471,15 @@ __STATIC_INLINE void __NVIC_SystemReset(void) */ __STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) { - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - reg_value = SCB_NS->AIRCR; /* read old register configuration */ - reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ - SCB_NS->AIRCR = reg_value; + reg_value = SCB_NS->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U)); /* Insert write key and priorty group */ + SCB_NS->AIRCR = reg_value; } @@ -2490,7 +2490,7 @@ __STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) { - return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); + return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } @@ -2502,10 +2502,10 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) */ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2519,14 +2519,14 @@ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2538,10 +2538,10 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2555,14 +2555,14 @@ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2574,10 +2574,10 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2589,10 +2589,10 @@ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2606,14 +2606,14 @@ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC_NS->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2628,14 +2628,14 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->IPR[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } - else - { - SCB_NS->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB_NS->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } } @@ -2650,14 +2650,14 @@ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) __STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return(((uint32_t)NVIC_NS->IPR[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return(((uint32_t)SCB_NS->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); - } + if ((int32_t)(IRQn) >= 0) + { + return (((uint32_t)NVIC_NS->IPR[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return (((uint32_t)SCB_NS->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] >> (8U - __NVIC_PRIO_BITS))); + } } #endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ @@ -2682,21 +2682,21 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { - uint32_t mvfr0; + uint32_t mvfr0; - mvfr0 = FPU->MVFR0; - if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) - { - return 2U; /* Double + Single precision FPU */ - } - else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) - { - return 1U; /* Single precision FPU */ - } - else - { - return 0U; /* No FPU */ - } + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } } @@ -2720,7 +2720,7 @@ __STATIC_INLINE uint32_t SCB_GetFPUType(void) */ __STATIC_INLINE void TZ_SAU_Enable(void) { - SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); } @@ -2764,18 +2764,18 @@ __STATIC_INLINE void TZ_SAU_Disable(void) */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } - SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) @@ -2793,18 +2793,18 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) */ __STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) { - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } - SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ @@ -2834,18 +2834,18 @@ extern volatile int32_t ITM_RxBuffer; /*!< External \param [in] ch Character to transmit. \returns Character to transmit. */ -__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +__STATIC_INLINE uint32_t ITM_SendChar(uint32_t ch) { - if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ - ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ - { - while (ITM->PORT[0U].u32 == 0UL) + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL) != 0UL)) /* ITM Port #0 enabled */ { - __NOP(); + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; } - ITM->PORT[0U].u8 = (uint8_t)ch; - } - return (ch); + return (ch); } @@ -2855,17 +2855,17 @@ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) \return Received character. \return -1 No character pending. */ -__STATIC_INLINE int32_t ITM_ReceiveChar (void) +__STATIC_INLINE int32_t ITM_ReceiveChar(void) { - int32_t ch = -1; /* no character available */ + int32_t ch = -1; /* no character available */ - if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) - { - ch = ITM_RxBuffer; - ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ - } + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } - return (ch); + return (ch); } @@ -2875,17 +2875,17 @@ __STATIC_INLINE int32_t ITM_ReceiveChar (void) \return 0 No character available. \return 1 Character available. */ -__STATIC_INLINE int32_t ITM_CheckChar (void) +__STATIC_INLINE int32_t ITM_CheckChar(void) { - if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) - { - return (0); /* no character available */ - } - else - { - return (1); /* character available */ - } + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } } /*@} end of CMSIS_core_DebugFunctions */ diff --git a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm0.h b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm0.h index 2f63b68610..f78676fbb4 100644 --- a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm0.h +++ b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm0.h @@ -23,9 +23,9 @@ */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ + #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang system_header /* treat file as system include file */ + #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM0_H_GENERIC @@ -34,7 +34,7 @@ #include #ifdef __cplusplus - extern "C" { +extern "C" { #endif /** @@ -61,7 +61,7 @@ */ #include "cmsis_version.h" - + /* CMSIS CM0 definitions */ #define __CM0_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM0_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ @@ -76,39 +76,39 @@ #define __FPU_USED 0U #if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __TARGET_FPU_VFP +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __ARM_PCS_VFP +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __ARMVFP__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __TI_ARM__ ) - #if defined __TI_VFP_SUPPORT__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __TI_VFP_SUPPORT__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __FPU_VFP__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __CSMC__ ) - #if ( __CSMC__ & 0x400U) - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if ( __CSMC__ & 0x400U) +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #endif @@ -127,25 +127,25 @@ #define __CORE_CM0_H_DEPENDANT #ifdef __cplusplus - extern "C" { +extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES - #ifndef __CM0_REV - #define __CM0_REV 0x0000U - #warning "__CM0_REV not defined in device header file; using default!" - #endif +#ifndef __CM0_REV +#define __CM0_REV 0x0000U +#warning "__CM0_REV not defined in device header file; using default!" +#endif - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 2U - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif +#ifndef __NVIC_PRIO_BITS +#define __NVIC_PRIO_BITS 2U +#warning "__NVIC_PRIO_BITS not defined in device header file; using default!" +#endif - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0U - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 0U +#warning "__Vendor_SysTickConfig not defined in device header file; using default!" +#endif #endif /* IO definitions (access restrictions to peripheral registers) */ @@ -157,9 +157,9 @@ \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ +#define __I volatile /*!< Defines 'read only' permissions */ #else - #define __I volatile const /*!< Defines 'read only' permissions */ +#define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ @@ -198,15 +198,15 @@ */ typedef union { - struct - { - uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t _reserved0: 28; /*!< bit: 0..27 Reserved */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ @@ -228,12 +228,12 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ @@ -246,18 +246,18 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 15; /*!< bit: 9..23 Reserved */ + uint32_t T: 1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1: 3; /*!< bit: 25..27 Reserved */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ @@ -285,13 +285,13 @@ typedef union */ typedef union { - struct - { - uint32_t _reserved0:1; /*!< bit: 0 Reserved */ - uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ - uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t _reserved0: 1; /*!< bit: 0 Reserved */ + uint32_t SPSEL: 1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1: 30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ @@ -313,16 +313,16 @@ typedef union */ typedef struct { - __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[31U]; - __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[31U]; - __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[31U]; - __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[31U]; - uint32_t RESERVED4[64U]; - __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ } NVIC_Type; /*@} end of group CMSIS_NVIC */ @@ -340,15 +340,15 @@ typedef struct */ typedef struct { - __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ - uint32_t RESERVED0; - __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - uint32_t RESERVED1; - __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ - __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + uint32_t RESERVED0; + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ } SCB_Type; /* SCB CPUID Register Definitions */ @@ -447,10 +447,10 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ @@ -567,33 +567,33 @@ typedef struct */ #ifdef CMSIS_NVIC_VIRTUAL - #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE - #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" - #endif - #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE +#define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" +#endif +#include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else /*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for Cortex-M0 */ /*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for Cortex-M0 */ - #define NVIC_EnableIRQ __NVIC_EnableIRQ - #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ - #define NVIC_DisableIRQ __NVIC_DisableIRQ - #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ - #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ - #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ /*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0 */ - #define NVIC_SetPriority __NVIC_SetPriority - #define NVIC_GetPriority __NVIC_GetPriority - #define NVIC_SystemReset __NVIC_SystemReset +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority +#define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL - #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE - #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" - #endif - #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" +#endif +#include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else - #define NVIC_SetVector __NVIC_SetVector - #define NVIC_GetVector __NVIC_GetVector +#define NVIC_SetVector __NVIC_SetVector +#define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 @@ -614,10 +614,10 @@ typedef struct */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -631,14 +631,14 @@ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -650,12 +650,12 @@ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - __DSB(); - __ISB(); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } @@ -669,14 +669,14 @@ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -688,10 +688,10 @@ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -703,10 +703,10 @@ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -721,16 +721,16 @@ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | - (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); - } - else - { - SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | - (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } } @@ -746,14 +746,14 @@ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn)) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return ((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn)) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } } @@ -768,8 +768,8 @@ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { - uint32_t *vectors = (uint32_t *)0x0U; - vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + uint32_t *vectors = (uint32_t *)0x0U; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } @@ -783,8 +783,8 @@ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { - uint32_t *vectors = (uint32_t *)0x0U; - return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; + uint32_t *vectors = (uint32_t *)0x0U; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } @@ -794,16 +794,16 @@ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SystemReset(void) { - __DSB(); /* Ensure all outstanding memory accesses included + __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ - SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - SCB_AIRCR_SYSRESETREQ_Msk); - __DSB(); /* Ensure completion of memory access */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ - for(;;) /* wait until reset */ - { - __NOP(); - } + for (;;) /* wait until reset */ + { + __NOP(); + } } /*@} end of CMSIS_Core_NVICFunctions */ @@ -858,18 +858,18 @@ __STATIC_INLINE uint32_t SCB_GetFPUType(void) */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } - SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ } #endif diff --git a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm0plus.h b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm0plus.h index 5c6135802b..d301f0437a 100644 --- a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm0plus.h +++ b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm0plus.h @@ -23,9 +23,9 @@ */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ + #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang system_header /* treat file as system include file */ + #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM0PLUS_H_GENERIC @@ -34,7 +34,7 @@ #include #ifdef __cplusplus - extern "C" { +extern "C" { #endif /** @@ -61,7 +61,7 @@ */ #include "cmsis_version.h" - + /* CMSIS CM0+ definitions */ #define __CM0PLUS_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM0PLUS_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ @@ -76,39 +76,39 @@ #define __FPU_USED 0U #if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __TARGET_FPU_VFP +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __ARM_PCS_VFP +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __ARMVFP__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __TI_ARM__ ) - #if defined __TI_VFP_SUPPORT__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __TI_VFP_SUPPORT__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __FPU_VFP__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __CSMC__ ) - #if ( __CSMC__ & 0x400U) - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if ( __CSMC__ & 0x400U) +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #endif @@ -127,35 +127,35 @@ #define __CORE_CM0PLUS_H_DEPENDANT #ifdef __cplusplus - extern "C" { +extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES - #ifndef __CM0PLUS_REV - #define __CM0PLUS_REV 0x0000U - #warning "__CM0PLUS_REV not defined in device header file; using default!" - #endif +#ifndef __CM0PLUS_REV +#define __CM0PLUS_REV 0x0000U +#warning "__CM0PLUS_REV not defined in device header file; using default!" +#endif - #ifndef __MPU_PRESENT - #define __MPU_PRESENT 0U - #warning "__MPU_PRESENT not defined in device header file; using default!" - #endif +#ifndef __MPU_PRESENT +#define __MPU_PRESENT 0U +#warning "__MPU_PRESENT not defined in device header file; using default!" +#endif - #ifndef __VTOR_PRESENT - #define __VTOR_PRESENT 0U - #warning "__VTOR_PRESENT not defined in device header file; using default!" - #endif +#ifndef __VTOR_PRESENT +#define __VTOR_PRESENT 0U +#warning "__VTOR_PRESENT not defined in device header file; using default!" +#endif - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 2U - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif +#ifndef __NVIC_PRIO_BITS +#define __NVIC_PRIO_BITS 2U +#warning "__NVIC_PRIO_BITS not defined in device header file; using default!" +#endif - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0U - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 0U +#warning "__Vendor_SysTickConfig not defined in device header file; using default!" +#endif #endif /* IO definitions (access restrictions to peripheral registers) */ @@ -167,9 +167,9 @@ \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ +#define __I volatile /*!< Defines 'read only' permissions */ #else - #define __I volatile const /*!< Defines 'read only' permissions */ +#define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ @@ -209,15 +209,15 @@ */ typedef union { - struct - { - uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t _reserved0: 28; /*!< bit: 0..27 Reserved */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ @@ -239,12 +239,12 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ @@ -257,18 +257,18 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 15; /*!< bit: 9..23 Reserved */ + uint32_t T: 1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1: 3; /*!< bit: 25..27 Reserved */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ @@ -296,13 +296,13 @@ typedef union */ typedef union { - struct - { - uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ - uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t nPRIV: 1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL: 1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1: 30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ @@ -327,16 +327,16 @@ typedef union */ typedef struct { - __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[31U]; - __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[31U]; - __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[31U]; - __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[31U]; - uint32_t RESERVED4[64U]; - __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ } NVIC_Type; /*@} end of group CMSIS_NVIC */ @@ -354,19 +354,19 @@ typedef struct */ typedef struct { - __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) - __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ #else - uint32_t RESERVED0; + uint32_t RESERVED0; #endif - __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - uint32_t RESERVED1; - __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ - __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ } SCB_Type; /* SCB CPUID Register Definitions */ @@ -471,10 +471,10 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ @@ -523,11 +523,11 @@ typedef struct */ typedef struct { - __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ } MPU_Type; /* MPU Type Register Definitions */ @@ -653,8 +653,8 @@ typedef struct #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ +#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif /*@} */ @@ -683,33 +683,33 @@ typedef struct */ #ifdef CMSIS_NVIC_VIRTUAL - #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE - #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" - #endif - #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE +#define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" +#endif +#include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else /*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for Cortex-M0+ */ /*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for Cortex-M0+ */ - #define NVIC_EnableIRQ __NVIC_EnableIRQ - #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ - #define NVIC_DisableIRQ __NVIC_DisableIRQ - #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ - #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ - #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ /*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0+ */ - #define NVIC_SetPriority __NVIC_SetPriority - #define NVIC_GetPriority __NVIC_GetPriority - #define NVIC_SystemReset __NVIC_SystemReset +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority +#define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL - #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE - #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" - #endif - #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" +#endif +#include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else - #define NVIC_SetVector __NVIC_SetVector - #define NVIC_GetVector __NVIC_GetVector +#define NVIC_SetVector __NVIC_SetVector +#define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 @@ -730,10 +730,10 @@ typedef struct */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -747,14 +747,14 @@ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -766,12 +766,12 @@ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - __DSB(); - __ISB(); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } @@ -785,14 +785,14 @@ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -804,10 +804,10 @@ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -819,10 +819,10 @@ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -837,16 +837,16 @@ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | - (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); - } - else - { - SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | - (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } } @@ -862,14 +862,14 @@ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn)) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return ((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn)) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } } @@ -886,11 +886,11 @@ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) - uint32_t *vectors = (uint32_t *)SCB->VTOR; + uint32_t *vectors = (uint32_t *)SCB->VTOR; #else uint32_t *vectors = (uint32_t *)0x0U; #endif - vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } @@ -905,11 +905,11 @@ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) - uint32_t *vectors = (uint32_t *)SCB->VTOR; + uint32_t *vectors = (uint32_t *)SCB->VTOR; #else - uint32_t *vectors = (uint32_t *)0x0U; + uint32_t *vectors = (uint32_t *)0x0U; #endif - return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } @@ -920,16 +920,16 @@ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SystemReset(void) { - __DSB(); /* Ensure all outstanding memory accesses included + __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ - SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - SCB_AIRCR_SYSRESETREQ_Msk); - __DSB(); /* Ensure completion of memory access */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ - for(;;) /* wait until reset */ - { - __NOP(); - } + for (;;) /* wait until reset */ + { + __NOP(); + } } /*@} end of CMSIS_Core_NVICFunctions */ @@ -991,18 +991,18 @@ __STATIC_INLINE uint32_t SCB_GetFPUType(void) */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } - SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ } #endif diff --git a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm3.h b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm3.h index 3c1f01f497..d2761ceb16 100644 --- a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm3.h +++ b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm3.h @@ -23,9 +23,9 @@ */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ + #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang system_header /* treat file as system include file */ + #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM3_H_GENERIC @@ -34,7 +34,7 @@ #include #ifdef __cplusplus - extern "C" { +extern "C" { #endif /** @@ -61,7 +61,7 @@ */ #include "cmsis_version.h" - + /* CMSIS CM3 definitions */ #define __CM3_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM3_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ @@ -76,39 +76,39 @@ #define __FPU_USED 0U #if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __TARGET_FPU_VFP +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __ARM_PCS_VFP +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __ARMVFP__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __TI_ARM__ ) - #if defined __TI_VFP_SUPPORT__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __TI_VFP_SUPPORT__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if defined __FPU_VFP__ +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #elif defined ( __CSMC__ ) - #if ( __CSMC__ & 0x400U) - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif +#if ( __CSMC__ & 0x400U) +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif #endif @@ -127,30 +127,30 @@ #define __CORE_CM3_H_DEPENDANT #ifdef __cplusplus - extern "C" { +extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES - #ifndef __CM3_REV - #define __CM3_REV 0x0200U - #warning "__CM3_REV not defined in device header file; using default!" - #endif +#ifndef __CM3_REV +#define __CM3_REV 0x0200U +#warning "__CM3_REV not defined in device header file; using default!" +#endif - #ifndef __MPU_PRESENT - #define __MPU_PRESENT 0U - #warning "__MPU_PRESENT not defined in device header file; using default!" - #endif +#ifndef __MPU_PRESENT +#define __MPU_PRESENT 0U +#warning "__MPU_PRESENT not defined in device header file; using default!" +#endif - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 3U - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif +#ifndef __NVIC_PRIO_BITS +#define __NVIC_PRIO_BITS 3U +#warning "__NVIC_PRIO_BITS not defined in device header file; using default!" +#endif - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0U - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 0U +#warning "__Vendor_SysTickConfig not defined in device header file; using default!" +#endif #endif /* IO definitions (access restrictions to peripheral registers) */ @@ -162,9 +162,9 @@ \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ +#define __I volatile /*!< Defines 'read only' permissions */ #else - #define __I volatile const /*!< Defines 'read only' permissions */ +#define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ @@ -205,16 +205,16 @@ */ typedef union { - struct - { - uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t _reserved0: 27; /*!< bit: 0..26 Reserved */ + uint32_t Q: 1; /*!< bit: 27 Saturation condition flag */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ @@ -239,12 +239,12 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ @@ -257,21 +257,21 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:1; /*!< bit: 9 Reserved */ - uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ - uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit */ - uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1: 6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t _reserved1: 8; /*!< bit: 16..23 Reserved */ + uint32_t T: 1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2: 2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q: 1; /*!< bit: 27 Saturation condition flag */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ @@ -308,13 +308,13 @@ typedef union */ typedef union { - struct - { - uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ - uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t nPRIV: 1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL: 1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1: 30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ @@ -339,19 +339,19 @@ typedef union */ typedef struct { - __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[24U]; - __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[24U]; - __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[24U]; - __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[24U]; - __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ - uint32_t RESERVED4[56U]; - __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ - uint32_t RESERVED5[644U]; - __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ @@ -373,27 +373,27 @@ typedef struct */ typedef struct { - __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ - __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ - __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ - __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ - __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ - __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ - __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ - __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ - __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ - __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ - __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ - __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ - __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ - __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ - uint32_t RESERVED0[5U]; - __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ } SCB_Type; /* SCB CPUID Register Definitions */ @@ -654,12 +654,12 @@ typedef struct */ typedef struct { - uint32_t RESERVED0[1U]; - __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ #if defined (__CM3_REV) && (__CM3_REV >= 0x200U) - __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ #else - uint32_t RESERVED1[1U]; + uint32_t RESERVED1[1U]; #endif } SCnSCB_Type; @@ -693,10 +693,10 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ @@ -745,38 +745,38 @@ typedef struct */ typedef struct { - __OM union - { - __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ - __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ - __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ - } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ - uint32_t RESERVED0[864U]; - __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ - uint32_t RESERVED1[15U]; - __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ - uint32_t RESERVED2[15U]; - __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29U]; - __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ - uint32_t RESERVED4[43U]; - __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ - __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ - uint32_t RESERVED5[6U]; - __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ - __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ - __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ - __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ - __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ - __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ - __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ - __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ - __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ - __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ - __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ - __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Trace Privilege Register Definitions */ @@ -848,29 +848,29 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ - __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ - __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ - __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ - __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ - __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ - __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ - __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ - __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ - __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ - __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ - uint32_t RESERVED0[1U]; - __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ - __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ - __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ - uint32_t RESERVED1[1U]; - __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ - __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ - __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ - uint32_t RESERVED2[1U]; - __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ - __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ - __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ } DWT_Type; /* DWT Control Register Definitions */ @@ -995,30 +995,30 @@ typedef struct */ typedef struct { - __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ - __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ - uint32_t RESERVED0[2U]; - __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ - uint32_t RESERVED1[55U]; - __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ - uint32_t RESERVED2[131U]; - __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ - __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ - __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ - uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ - __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ - __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ - uint32_t RESERVED4[1U]; - __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ - __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ - __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ - uint32_t RESERVED5[39U]; - __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ - __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ - uint32_t RESERVED7[8U]; - __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ - __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ @@ -1151,17 +1151,17 @@ typedef struct */ typedef struct { - __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ - __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ - __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ - __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ - __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ - __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ - __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ } MPU_Type; /* MPU Type Register Definitions */ @@ -1245,10 +1245,10 @@ typedef struct */ typedef struct { - __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ - __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ - __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ - __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ @@ -1391,8 +1391,8 @@ typedef struct #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ +#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif /*@} */ @@ -1422,33 +1422,33 @@ typedef struct */ #ifdef CMSIS_NVIC_VIRTUAL - #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE - #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" - #endif - #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE +#define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" +#endif +#include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else - #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping - #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping - #define NVIC_EnableIRQ __NVIC_EnableIRQ - #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ - #define NVIC_DisableIRQ __NVIC_DisableIRQ - #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ - #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ - #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ - #define NVIC_GetActive __NVIC_GetActive - #define NVIC_SetPriority __NVIC_SetPriority - #define NVIC_GetPriority __NVIC_GetPriority - #define NVIC_SystemReset __NVIC_SystemReset +#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping +#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_GetActive __NVIC_GetActive +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority +#define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL - #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE - #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" - #endif - #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" +#endif +#include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else - #define NVIC_SetVector __NVIC_SetVector - #define NVIC_GetVector __NVIC_GetVector +#define NVIC_SetVector __NVIC_SetVector +#define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 @@ -1466,15 +1466,15 @@ typedef struct */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - reg_value = SCB->AIRCR; /* read old register configuration */ - reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ - SCB->AIRCR = reg_value; + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; } @@ -1485,7 +1485,7 @@ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { - return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } @@ -1497,10 +1497,10 @@ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1514,14 +1514,14 @@ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1533,12 +1533,12 @@ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - __DSB(); - __ISB(); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } @@ -1552,14 +1552,14 @@ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1571,10 +1571,10 @@ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1586,10 +1586,10 @@ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1603,14 +1603,14 @@ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1625,14 +1625,14 @@ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } - else - { - SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } } @@ -1648,14 +1648,14 @@ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); - } + if ((int32_t)(IRQn) >= 0) + { + return (((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return (((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] >> (8U - __NVIC_PRIO_BITS))); + } } @@ -1670,19 +1670,19 @@ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ -__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +__STATIC_INLINE uint32_t NVIC_EncodePriority(uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - return ( - ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | - ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) - ); + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits)) - 1UL))) + ); } @@ -1697,17 +1697,17 @@ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t P \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ -__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +__STATIC_INLINE void NVIC_DecodePriority(uint32_t Priority, uint32_t PriorityGroup, uint32_t *const pPreemptPriority, uint32_t *const pSubPriority) { - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); - *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority) & (uint32_t)((1UL << (SubPriorityBits)) - 1UL); } @@ -1722,8 +1722,8 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { - uint32_t *vectors = (uint32_t *)SCB->VTOR; - vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } @@ -1737,8 +1737,8 @@ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { - uint32_t *vectors = (uint32_t *)SCB->VTOR; - return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } @@ -1748,17 +1748,17 @@ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SystemReset(void) { - __DSB(); /* Ensure all outstanding memory accesses included + __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ - SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | - SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ - __DSB(); /* Ensure completion of memory access */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ - for(;;) /* wait until reset */ - { - __NOP(); - } + for (;;) /* wait until reset */ + { + __NOP(); + } } /*@} end of CMSIS_Core_NVICFunctions */ @@ -1820,18 +1820,18 @@ __STATIC_INLINE uint32_t SCB_GetFPUType(void) */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } - SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ } #endif @@ -1860,18 +1860,18 @@ extern volatile int32_t ITM_RxBuffer; /*!< External \param [in] ch Character to transmit. \returns Character to transmit. */ -__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +__STATIC_INLINE uint32_t ITM_SendChar(uint32_t ch) { - if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ - ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ - { - while (ITM->PORT[0U].u32 == 0UL) + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL) != 0UL)) /* ITM Port #0 enabled */ { - __NOP(); + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; } - ITM->PORT[0U].u8 = (uint8_t)ch; - } - return (ch); + return (ch); } @@ -1881,17 +1881,17 @@ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) \return Received character. \return -1 No character pending. */ -__STATIC_INLINE int32_t ITM_ReceiveChar (void) +__STATIC_INLINE int32_t ITM_ReceiveChar(void) { - int32_t ch = -1; /* no character available */ + int32_t ch = -1; /* no character available */ - if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) - { - ch = ITM_RxBuffer; - ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ - } + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } - return (ch); + return (ch); } @@ -1901,17 +1901,17 @@ __STATIC_INLINE int32_t ITM_ReceiveChar (void) \return 0 No character available. \return 1 Character available. */ -__STATIC_INLINE int32_t ITM_CheckChar (void) +__STATIC_INLINE int32_t ITM_CheckChar(void) { - if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) - { - return (0); /* no character available */ - } - else - { - return (1); /* character available */ - } + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } } /*@} end of CMSIS_core_DebugFunctions */ diff --git a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm33.h b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm33.h index fab2f9a118..9753b3e993 100644 --- a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm33.h +++ b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm33.h @@ -23,9 +23,9 @@ */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ + #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang system_header /* treat file as system include file */ + #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM33_H_GENERIC @@ -34,7 +34,7 @@ #include #ifdef __cplusplus - extern "C" { +extern "C" { #endif /** @@ -61,7 +61,7 @@ */ #include "cmsis_version.h" - + /* CMSIS CM33 definitions */ #define __CM33_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM33_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ @@ -74,88 +74,88 @@ For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. */ #if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __TARGET_FPU_VFP +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __ARM_PCS_VFP +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __ARMVFP__ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __TI_ARM__ ) - #if defined __TI_VFP_SUPPORT__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __TI_VFP_SUPPORT__ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __FPU_VFP__ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __CSMC__ ) - #if ( __CSMC__ & 0x400U) - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if ( __CSMC__ & 0x400U) +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #endif @@ -174,45 +174,45 @@ #define __CORE_CM33_H_DEPENDANT #ifdef __cplusplus - extern "C" { +extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES - #ifndef __CM33_REV - #define __CM33_REV 0x0000U - #warning "__CM33_REV not defined in device header file; using default!" - #endif +#ifndef __CM33_REV +#define __CM33_REV 0x0000U +#warning "__CM33_REV not defined in device header file; using default!" +#endif - #ifndef __FPU_PRESENT - #define __FPU_PRESENT 0U - #warning "__FPU_PRESENT not defined in device header file; using default!" - #endif +#ifndef __FPU_PRESENT +#define __FPU_PRESENT 0U +#warning "__FPU_PRESENT not defined in device header file; using default!" +#endif - #ifndef __MPU_PRESENT - #define __MPU_PRESENT 0U - #warning "__MPU_PRESENT not defined in device header file; using default!" - #endif +#ifndef __MPU_PRESENT +#define __MPU_PRESENT 0U +#warning "__MPU_PRESENT not defined in device header file; using default!" +#endif - #ifndef __SAUREGION_PRESENT - #define __SAUREGION_PRESENT 0U - #warning "__SAUREGION_PRESENT not defined in device header file; using default!" - #endif +#ifndef __SAUREGION_PRESENT +#define __SAUREGION_PRESENT 0U +#warning "__SAUREGION_PRESENT not defined in device header file; using default!" +#endif - #ifndef __DSP_PRESENT - #define __DSP_PRESENT 0U - #warning "__DSP_PRESENT not defined in device header file; using default!" - #endif +#ifndef __DSP_PRESENT +#define __DSP_PRESENT 0U +#warning "__DSP_PRESENT not defined in device header file; using default!" +#endif - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 3U - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif +#ifndef __NVIC_PRIO_BITS +#define __NVIC_PRIO_BITS 3U +#warning "__NVIC_PRIO_BITS not defined in device header file; using default!" +#endif - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0U - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 0U +#warning "__Vendor_SysTickConfig not defined in device header file; using default!" +#endif #endif /* IO definitions (access restrictions to peripheral registers) */ @@ -224,9 +224,9 @@ \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ +#define __I volatile /*!< Defines 'read only' permissions */ #else - #define __I volatile const /*!< Defines 'read only' permissions */ +#define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ @@ -269,18 +269,18 @@ */ typedef union { - struct - { - uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t _reserved0: 16; /*!< bit: 0..15 Reserved */ + uint32_t GE: 4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1: 7; /*!< bit: 20..26 Reserved */ + uint32_t Q: 1; /*!< bit: 27 Saturation condition flag */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ @@ -308,12 +308,12 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ @@ -326,21 +326,21 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 7; /*!< bit: 9..15 Reserved */ + uint32_t GE: 4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1: 4; /*!< bit: 20..23 Reserved */ + uint32_t T: 1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT: 2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q: 1; /*!< bit: 27 Saturation condition flag */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ @@ -377,15 +377,15 @@ typedef union */ typedef union { - struct - { - uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ - uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ - uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ - uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t nPRIV: 1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL: 1; /*!< bit: 1 Stack-pointer select */ + uint32_t FPCA: 1; /*!< bit: 2 Floating-point context active */ + uint32_t SFPA: 1; /*!< bit: 3 Secure floating-point active */ + uint32_t _reserved1: 28; /*!< bit: 4..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ @@ -416,21 +416,21 @@ typedef union */ typedef struct { - __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[16U]; - __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[16U]; - __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[16U]; - __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[16U]; - __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ - uint32_t RESERVED4[16U]; - __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ - uint32_t RESERVED5[16U]; - __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ - uint32_t RESERVED6[580U]; - __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED6[580U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ @@ -452,56 +452,56 @@ typedef struct */ typedef struct { - __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ - __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ - __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ - __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ - __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ - __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ - __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ - __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ - __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ - __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ - __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ - __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ - __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ - __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ - __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ - __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ - __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ - __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ - __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ - __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ - uint32_t RESERVED3[92U]; - __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ - uint32_t RESERVED4[15U]; - __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ - __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ - __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ - uint32_t RESERVED5[1U]; - __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ - uint32_t RESERVED6[1U]; - __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ - __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ - __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ - __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ - __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ - __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ - __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ - __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ - uint32_t RESERVED7[6U]; - __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ - __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ - __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ - __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ - __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ - uint32_t RESERVED8[1U]; - __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ + uint32_t RESERVED3[92U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ } SCB_Type; /* SCB CPUID Register Definitions */ @@ -961,10 +961,10 @@ typedef struct */ typedef struct { - uint32_t RESERVED0[1U]; - __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ - __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ - __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ } SCnSCB_Type; /* Interrupt Controller Type Register Definitions */ @@ -986,10 +986,10 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ @@ -1038,40 +1038,40 @@ typedef struct */ typedef struct { - __OM union - { - __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ - __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ - __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ - } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ - uint32_t RESERVED0[864U]; - __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ - uint32_t RESERVED1[15U]; - __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ - uint32_t RESERVED2[15U]; - __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29U]; - __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ - uint32_t RESERVED4[43U]; - __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ - __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ - uint32_t RESERVED5[1U]; - __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ - uint32_t RESERVED6[4U]; - __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ - __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ - __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ - __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ - __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ - __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ - __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ - __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ - __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ - __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ - __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ - __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ + uint32_t RESERVED6[4U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Stimulus Port Register Definitions */ @@ -1153,81 +1153,81 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ - __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ - __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ - __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ - __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ - __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ - __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ - __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ - __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ - uint32_t RESERVED1[1U]; - __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ - uint32_t RESERVED2[1U]; - __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ - uint32_t RESERVED3[1U]; - __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ - uint32_t RESERVED4[1U]; - __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ - uint32_t RESERVED5[1U]; - __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ - uint32_t RESERVED6[1U]; - __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ - uint32_t RESERVED7[1U]; - __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ - uint32_t RESERVED8[1U]; - __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ - uint32_t RESERVED9[1U]; - __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ - uint32_t RESERVED10[1U]; - __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ - uint32_t RESERVED11[1U]; - __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ - uint32_t RESERVED12[1U]; - __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ - uint32_t RESERVED13[1U]; - __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ - uint32_t RESERVED14[1U]; - __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ - uint32_t RESERVED15[1U]; - __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ - uint32_t RESERVED16[1U]; - __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ - uint32_t RESERVED17[1U]; - __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ - uint32_t RESERVED18[1U]; - __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ - uint32_t RESERVED19[1U]; - __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ - uint32_t RESERVED20[1U]; - __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ - uint32_t RESERVED21[1U]; - __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ - uint32_t RESERVED22[1U]; - __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ - uint32_t RESERVED23[1U]; - __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ - uint32_t RESERVED24[1U]; - __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ - uint32_t RESERVED25[1U]; - __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ - uint32_t RESERVED26[1U]; - __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ - uint32_t RESERVED27[1U]; - __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ - uint32_t RESERVED28[1U]; - __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ - uint32_t RESERVED29[1U]; - __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ - uint32_t RESERVED30[1U]; - __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ - uint32_t RESERVED31[1U]; - __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ - uint32_t RESERVED32[934U]; - __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ - uint32_t RESERVED33[1U]; - __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + uint32_t RESERVED32[934U]; + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ + uint32_t RESERVED33[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ } DWT_Type; /* DWT Control Register Definitions */ @@ -1339,30 +1339,30 @@ typedef struct */ typedef struct { - __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ - __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ - uint32_t RESERVED0[2U]; - __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ - uint32_t RESERVED1[55U]; - __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ - uint32_t RESERVED2[131U]; - __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ - __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ - __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ - uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ - __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ - __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ - uint32_t RESERVED4[1U]; - __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ - __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ - __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ - uint32_t RESERVED5[39U]; - __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ - __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ - uint32_t RESERVED7[8U]; - __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ - __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ @@ -1495,20 +1495,20 @@ typedef struct */ typedef struct { - __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ - __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ - __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ - __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ - __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ - __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ - __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ - uint32_t RESERVED0[1]; - __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ - __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ + __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ + __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ + __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ + uint32_t RESERVED0[1]; + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ } MPU_Type; /* MPU Type Register Definitions */ @@ -1601,17 +1601,17 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ - __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ - __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ #else - uint32_t RESERVED0[3]; + uint32_t RESERVED0[3]; #endif - __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ - __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ + __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ + __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ } SAU_Type; /* SAU Control Register Definitions */ @@ -1687,12 +1687,12 @@ typedef struct */ typedef struct { - uint32_t RESERVED0[1U]; - __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ - __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ - __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ - __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ - __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ } FPU_Type; /* Floating-Point Context Control Register Definitions */ @@ -1817,13 +1817,13 @@ typedef struct */ typedef struct { - __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ - __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ - __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ - __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ - uint32_t RESERVED4[1U]; - __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ - __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ @@ -1973,57 +1973,57 @@ typedef struct */ /* Memory mapping of Core Hardware */ - #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ - #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ - #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ - #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ - #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ - #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ - #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ - #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ - #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ - #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ - #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ - #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ - #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ - #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ - #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ - #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ - #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ - #endif - - #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) - #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ - #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ - #endif - - #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ - #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ +#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) - #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ - #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ - #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ - #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ - #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ +#define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ +#define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ +#endif - #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ - #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ - #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ - #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ - #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ - #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ - #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ - #endif +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ +#define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ +#define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ +#define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ +#define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ - #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ - #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ +#define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ +#define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ +#define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ +#define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ +#define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +#define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ +#define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ +#endif + +#define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ +#define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} */ @@ -2053,33 +2053,33 @@ typedef struct */ #ifdef CMSIS_NVIC_VIRTUAL - #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE - #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" - #endif - #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE +#define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" +#endif +#include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else - #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping - #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping - #define NVIC_EnableIRQ __NVIC_EnableIRQ - #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ - #define NVIC_DisableIRQ __NVIC_DisableIRQ - #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ - #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ - #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ - #define NVIC_GetActive __NVIC_GetActive - #define NVIC_SetPriority __NVIC_SetPriority - #define NVIC_GetPriority __NVIC_GetPriority - #define NVIC_SystemReset __NVIC_SystemReset +#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping +#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_GetActive __NVIC_GetActive +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority +#define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL - #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE - #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" - #endif - #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" +#endif +#include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else - #define NVIC_SetVector __NVIC_SetVector - #define NVIC_GetVector __NVIC_GetVector +#define NVIC_SetVector __NVIC_SetVector +#define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 @@ -2097,15 +2097,15 @@ typedef struct */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - reg_value = SCB->AIRCR; /* read old register configuration */ - reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ - SCB->AIRCR = reg_value; + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; } @@ -2116,7 +2116,7 @@ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { - return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } @@ -2128,10 +2128,10 @@ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2145,14 +2145,14 @@ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2164,12 +2164,12 @@ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - __DSB(); - __ISB(); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } @@ -2183,14 +2183,14 @@ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2202,10 +2202,10 @@ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2217,10 +2217,10 @@ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2234,14 +2234,14 @@ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2256,14 +2256,14 @@ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2277,15 +2277,15 @@ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); - return((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); + return ((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2299,15 +2299,15 @@ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); - return((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); + return ((uint32_t)(((NVIC->ITNS[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ @@ -2323,14 +2323,14 @@ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->IPR[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } - else - { - SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } } @@ -2346,14 +2346,14 @@ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return(((uint32_t)NVIC->IPR[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return(((uint32_t)SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); - } + if ((int32_t)(IRQn) >= 0) + { + return (((uint32_t)NVIC->IPR[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return (((uint32_t)SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] >> (8U - __NVIC_PRIO_BITS))); + } } @@ -2368,19 +2368,19 @@ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ -__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +__STATIC_INLINE uint32_t NVIC_EncodePriority(uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - return ( - ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | - ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) - ); + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits)) - 1UL))) + ); } @@ -2395,17 +2395,17 @@ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t P \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ -__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +__STATIC_INLINE void NVIC_DecodePriority(uint32_t Priority, uint32_t PriorityGroup, uint32_t *const pPreemptPriority, uint32_t *const pSubPriority) { - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); - *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority) & (uint32_t)((1UL << (SubPriorityBits)) - 1UL); } @@ -2420,8 +2420,8 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { - uint32_t *vectors = (uint32_t *)SCB->VTOR; - vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } @@ -2435,8 +2435,8 @@ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { - uint32_t *vectors = (uint32_t *)SCB->VTOR; - return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } @@ -2446,17 +2446,17 @@ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SystemReset(void) { - __DSB(); /* Ensure all outstanding memory accesses included + __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ - SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | - SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ - __DSB(); /* Ensure completion of memory access */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ - for(;;) /* wait until reset */ - { - __NOP(); - } + for (;;) /* wait until reset */ + { + __NOP(); + } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) @@ -2471,15 +2471,15 @@ __STATIC_INLINE void __NVIC_SystemReset(void) */ __STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) { - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - reg_value = SCB_NS->AIRCR; /* read old register configuration */ - reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ - SCB_NS->AIRCR = reg_value; + reg_value = SCB_NS->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U)); /* Insert write key and priorty group */ + SCB_NS->AIRCR = reg_value; } @@ -2490,7 +2490,7 @@ __STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) { - return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); + return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } @@ -2502,10 +2502,10 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) */ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2519,14 +2519,14 @@ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC_NS->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2538,10 +2538,10 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2555,10 +2555,10 @@ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } } @@ -2570,10 +2570,10 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2585,10 +2585,10 @@ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -2602,14 +2602,14 @@ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC_NS->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -2624,14 +2624,14 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) */ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) >= 0) - { - NVIC_NS->IPR[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } - else - { - SCB_NS->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB_NS->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } } @@ -2646,14 +2646,14 @@ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) __STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return(((uint32_t)NVIC_NS->IPR[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return(((uint32_t)SCB_NS->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); - } + if ((int32_t)(IRQn) >= 0) + { + return (((uint32_t)NVIC_NS->IPR[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return (((uint32_t)SCB_NS->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] >> (8U - __NVIC_PRIO_BITS))); + } } #endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ @@ -2678,21 +2678,21 @@ __STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { - uint32_t mvfr0; + uint32_t mvfr0; - mvfr0 = FPU->MVFR0; - if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) - { - return 2U; /* Double + Single precision FPU */ - } - else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) - { - return 1U; /* Single precision FPU */ - } - else - { - return 0U; /* No FPU */ - } + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } } @@ -2716,7 +2716,7 @@ __STATIC_INLINE uint32_t SCB_GetFPUType(void) */ __STATIC_INLINE void TZ_SAU_Enable(void) { - SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); } @@ -2760,18 +2760,18 @@ __STATIC_INLINE void TZ_SAU_Disable(void) */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } - SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) @@ -2789,18 +2789,18 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) */ __STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) { - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } - SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ @@ -2830,18 +2830,18 @@ extern volatile int32_t ITM_RxBuffer; /*!< External \param [in] ch Character to transmit. \returns Character to transmit. */ -__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +__STATIC_INLINE uint32_t ITM_SendChar(uint32_t ch) { - if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ - ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ - { - while (ITM->PORT[0U].u32 == 0UL) + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL) != 0UL)) /* ITM Port #0 enabled */ { - __NOP(); + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; } - ITM->PORT[0U].u8 = (uint8_t)ch; - } - return (ch); + return (ch); } @@ -2851,17 +2851,17 @@ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) \return Received character. \return -1 No character pending. */ -__STATIC_INLINE int32_t ITM_ReceiveChar (void) +__STATIC_INLINE int32_t ITM_ReceiveChar(void) { - int32_t ch = -1; /* no character available */ + int32_t ch = -1; /* no character available */ - if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) - { - ch = ITM_RxBuffer; - ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ - } + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } - return (ch); + return (ch); } @@ -2871,17 +2871,17 @@ __STATIC_INLINE int32_t ITM_ReceiveChar (void) \return 0 No character available. \return 1 Character available. */ -__STATIC_INLINE int32_t ITM_CheckChar (void) +__STATIC_INLINE int32_t ITM_CheckChar(void) { - if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) - { - return (0); /* no character available */ - } - else - { - return (1); /* character available */ - } + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } } /*@} end of CMSIS_core_DebugFunctions */ diff --git a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm4.h b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm4.h index ad3bc27d58..56e9e82b92 100644 --- a/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm4.h +++ b/bsp/nuvoton/libraries/m2354/CMSIS/Include/core_cm4.h @@ -23,9 +23,9 @@ */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ + #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang system_header /* treat file as system include file */ + #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM4_H_GENERIC @@ -34,7 +34,7 @@ #include #ifdef __cplusplus - extern "C" { +extern "C" { #endif /** @@ -61,7 +61,7 @@ */ #include "cmsis_version.h" - + /* CMSIS CM4 definitions */ #define __CM4_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM4_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ @@ -74,88 +74,88 @@ For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. */ #if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __TARGET_FPU_VFP +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __ARM_PCS_VFP +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __ARMVFP__ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __TI_ARM__ ) - #if defined __TI_VFP_SUPPORT__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __TI_VFP_SUPPORT__ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if defined __FPU_VFP__ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #elif defined ( __CSMC__ ) - #if ( __CSMC__ & 0x400U) - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif +#if ( __CSMC__ & 0x400U) +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) +#define __FPU_USED 1U +#else +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#define __FPU_USED 0U +#endif +#else +#define __FPU_USED 0U +#endif #endif @@ -174,35 +174,35 @@ #define __CORE_CM4_H_DEPENDANT #ifdef __cplusplus - extern "C" { +extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES - #ifndef __CM4_REV - #define __CM4_REV 0x0000U - #warning "__CM4_REV not defined in device header file; using default!" - #endif +#ifndef __CM4_REV +#define __CM4_REV 0x0000U +#warning "__CM4_REV not defined in device header file; using default!" +#endif - #ifndef __FPU_PRESENT - #define __FPU_PRESENT 0U - #warning "__FPU_PRESENT not defined in device header file; using default!" - #endif +#ifndef __FPU_PRESENT +#define __FPU_PRESENT 0U +#warning "__FPU_PRESENT not defined in device header file; using default!" +#endif - #ifndef __MPU_PRESENT - #define __MPU_PRESENT 0U - #warning "__MPU_PRESENT not defined in device header file; using default!" - #endif +#ifndef __MPU_PRESENT +#define __MPU_PRESENT 0U +#warning "__MPU_PRESENT not defined in device header file; using default!" +#endif - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 3U - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif +#ifndef __NVIC_PRIO_BITS +#define __NVIC_PRIO_BITS 3U +#warning "__NVIC_PRIO_BITS not defined in device header file; using default!" +#endif - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0U - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 0U +#warning "__Vendor_SysTickConfig not defined in device header file; using default!" +#endif #endif /* IO definitions (access restrictions to peripheral registers) */ @@ -214,9 +214,9 @@ \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ +#define __I volatile /*!< Defines 'read only' permissions */ #else - #define __I volatile const /*!< Defines 'read only' permissions */ +#define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ @@ -258,18 +258,18 @@ */ typedef union { - struct - { - uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t _reserved0: 16; /*!< bit: 0..15 Reserved */ + uint32_t GE: 4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1: 7; /*!< bit: 20..26 Reserved */ + uint32_t Q: 1; /*!< bit: 27 Saturation condition flag */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ @@ -297,12 +297,12 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ @@ -315,22 +315,22 @@ typedef union */ typedef union { - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:1; /*!< bit: 9 Reserved */ - uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit */ - uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0: 1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1: 6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t GE: 4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1: 4; /*!< bit: 20..23 Reserved */ + uint32_t T: 1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2: 2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q: 1; /*!< bit: 27 Saturation condition flag */ + uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ + uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ @@ -370,14 +370,14 @@ typedef union */ typedef union { - struct - { - uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ - uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ - uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ + struct + { + uint32_t nPRIV: 1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL: 1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA: 1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0: 29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ @@ -405,19 +405,19 @@ typedef union */ typedef struct { - __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[24U]; - __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[24U]; - __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[24U]; - __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[24U]; - __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ - uint32_t RESERVED4[56U]; - __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ - uint32_t RESERVED5[644U]; - __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ @@ -439,27 +439,27 @@ typedef struct */ typedef struct { - __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ - __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ - __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ - __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ - __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ - __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ - __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ - __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ - __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ - __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ - __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ - __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ - __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ - __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ - uint32_t RESERVED0[5U]; - __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ } SCB_Type; /* SCB CPUID Register Definitions */ @@ -718,9 +718,9 @@ typedef struct */ typedef struct { - uint32_t RESERVED0[1U]; - __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ - __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ } SCnSCB_Type; /* Interrupt Controller Type Register Definitions */ @@ -758,10 +758,10 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ @@ -810,38 +810,38 @@ typedef struct */ typedef struct { - __OM union - { - __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ - __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ - __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ - } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ - uint32_t RESERVED0[864U]; - __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ - uint32_t RESERVED1[15U]; - __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ - uint32_t RESERVED2[15U]; - __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29U]; - __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ - uint32_t RESERVED4[43U]; - __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ - __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ - uint32_t RESERVED5[6U]; - __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ - __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ - __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ - __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ - __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ - __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ - __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ - __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ - __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ - __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ - __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ - __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Trace Privilege Register Definitions */ @@ -913,29 +913,29 @@ typedef struct */ typedef struct { - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ - __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ - __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ - __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ - __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ - __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ - __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ - __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ - __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ - __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ - __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ - uint32_t RESERVED0[1U]; - __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ - __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ - __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ - uint32_t RESERVED1[1U]; - __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ - __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ - __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ - uint32_t RESERVED2[1U]; - __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ - __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ - __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ } DWT_Type; /* DWT Control Register Definitions */ @@ -1060,30 +1060,30 @@ typedef struct */ typedef struct { - __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ - __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ - uint32_t RESERVED0[2U]; - __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ - uint32_t RESERVED1[55U]; - __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ - uint32_t RESERVED2[131U]; - __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ - __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ - __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ - uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ - __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ - __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ - uint32_t RESERVED4[1U]; - __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ - __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ - __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ - uint32_t RESERVED5[39U]; - __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ - __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ - uint32_t RESERVED7[8U]; - __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ - __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ @@ -1216,17 +1216,17 @@ typedef struct */ typedef struct { - __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ - __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ - __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ - __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ - __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ - __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ - __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ } MPU_Type; /* MPU Type Register Definitions */ @@ -1310,12 +1310,12 @@ typedef struct */ typedef struct { - uint32_t RESERVED0[1U]; - __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ - __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ - __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ - __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ - __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ } FPU_Type; /* Floating-Point Context Control Register Definitions */ @@ -1416,10 +1416,10 @@ typedef struct */ typedef struct { - __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ - __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ - __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ - __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ @@ -1562,8 +1562,8 @@ typedef struct #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ +#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ @@ -1596,33 +1596,33 @@ typedef struct */ #ifdef CMSIS_NVIC_VIRTUAL - #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE - #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" - #endif - #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE +#define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" +#endif +#include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else - #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping - #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping - #define NVIC_EnableIRQ __NVIC_EnableIRQ - #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ - #define NVIC_DisableIRQ __NVIC_DisableIRQ - #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ - #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ - #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ - #define NVIC_GetActive __NVIC_GetActive - #define NVIC_SetPriority __NVIC_SetPriority - #define NVIC_GetPriority __NVIC_GetPriority - #define NVIC_SystemReset __NVIC_SystemReset +#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping +#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_GetActive __NVIC_GetActive +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority +#define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL - #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE - #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" - #endif - #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" +#endif +#include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else - #define NVIC_SetVector __NVIC_SetVector - #define NVIC_GetVector __NVIC_GetVector +#define NVIC_SetVector __NVIC_SetVector +#define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 @@ -1640,15 +1640,15 @@ typedef struct */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - reg_value = SCB->AIRCR; /* read old register configuration */ - reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ - SCB->AIRCR = reg_value; + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; } @@ -1659,7 +1659,7 @@ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { - return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } @@ -1671,10 +1671,10 @@ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1688,14 +1688,14 @@ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1707,12 +1707,12 @@ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - __DSB(); - __ISB(); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } @@ -1726,14 +1726,14 @@ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1745,10 +1745,10 @@ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1760,10 +1760,10 @@ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + } } @@ -1777,14 +1777,14 @@ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } + if ((int32_t)(IRQn) >= 0) + { + return ((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return (0U); + } } @@ -1799,14 +1799,14 @@ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) >= 0) - { - NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } - else - { - SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } } @@ -1822,14 +1822,14 @@ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) >= 0) - { - return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); - } + if ((int32_t)(IRQn) >= 0) + { + return (((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return (((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL) - 4UL] >> (8U - __NVIC_PRIO_BITS))); + } } @@ -1844,19 +1844,19 @@ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ -__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +__STATIC_INLINE uint32_t NVIC_EncodePriority(uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - return ( - ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | - ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) - ); + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits)) - 1UL))) + ); } @@ -1871,17 +1871,17 @@ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t P \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ -__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +__STATIC_INLINE void NVIC_DecodePriority(uint32_t Priority, uint32_t PriorityGroup, uint32_t *const pPreemptPriority, uint32_t *const pSubPriority) { - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); - *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority) & (uint32_t)((1UL << (SubPriorityBits)) - 1UL); } @@ -1896,8 +1896,8 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { - uint32_t *vectors = (uint32_t *)SCB->VTOR; - vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } @@ -1911,8 +1911,8 @@ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { - uint32_t *vectors = (uint32_t *)SCB->VTOR; - return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } @@ -1922,17 +1922,17 @@ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) */ __STATIC_INLINE void __NVIC_SystemReset(void) { - __DSB(); /* Ensure all outstanding memory accesses included + __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ - SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | - SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ - __DSB(); /* Ensure completion of memory access */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ - for(;;) /* wait until reset */ - { - __NOP(); - } + for (;;) /* wait until reset */ + { + __NOP(); + } } /*@} end of CMSIS_Core_NVICFunctions */ @@ -1964,17 +1964,17 @@ __STATIC_INLINE void __NVIC_SystemReset(void) */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { - uint32_t mvfr0; + uint32_t mvfr0; - mvfr0 = FPU->MVFR0; - if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) - { - return 1U; /* Single precision FPU */ - } - else - { - return 0U; /* No FPU */ - } + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } } @@ -2005,18 +2005,18 @@ __STATIC_INLINE uint32_t SCB_GetFPUType(void) */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } - SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ } #endif @@ -2045,18 +2045,18 @@ extern volatile int32_t ITM_RxBuffer; /*!< External \param [in] ch Character to transmit. \returns Character to transmit. */ -__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +__STATIC_INLINE uint32_t ITM_SendChar(uint32_t ch) { - if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ - ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ - { - while (ITM->PORT[0U].u32 == 0UL) + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL) != 0UL)) /* ITM Port #0 enabled */ { - __NOP(); + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; } - ITM->PORT[0U].u8 = (uint8_t)ch; - } - return (ch); + return (ch); } @@ -2066,17 +2066,17 @@ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) \return Received character. \return -1 No character pending. */ -__STATIC_INLINE int32_t ITM_ReceiveChar (void) +__STATIC_INLINE int32_t ITM_ReceiveChar(void) { - int32_t ch = -1; /* no character available */ + int32_t ch = -1; /* no character available */ - if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) - { - ch = ITM_RxBuffer; - ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ - } + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } - return (ch); + return (ch); } @@ -2086,17 +2086,17 @@ __STATIC_INLINE int32_t ITM_ReceiveChar (void) \return 0 No character available. \return 1 Character available. */ -__STATIC_INLINE int32_t ITM_CheckChar (void) +__STATIC_INLINE int32_t ITM_CheckChar(void) { - if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) - { - return (0); /* no character available */ - } - else - { - return (1); /* character available */ - } + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } } /*@} end of CMSIS_core_DebugFunctions */ diff --git a/bsp/nuvoton/libraries/m2354/CMSIS/Include/mpu_armv7.h b/bsp/nuvoton/libraries/m2354/CMSIS/Include/mpu_armv7.h index fb1a339bec..d678faa98d 100644 --- a/bsp/nuvoton/libraries/m2354/CMSIS/Include/mpu_armv7.h +++ b/bsp/nuvoton/libraries/m2354/CMSIS/Include/mpu_armv7.h @@ -21,7 +21,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #ifndef ARM_MPU_ARMV7_H #define ARM_MPU_ARMV7_H @@ -54,7 +54,7 @@ #define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) #define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) -#define ARM_MPU_AP_NONE 0u +#define ARM_MPU_AP_NONE 0u #define ARM_MPU_AP_PRIV 1u #define ARM_MPU_AP_URO 2u #define ARM_MPU_AP_FULL 3u @@ -70,7 +70,7 @@ /** * MPU Region Attribut and Size Register Value -* +* * \param DisableExec Instruction access disable bit, 1= disable instruction fetches. * \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. * \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. @@ -79,7 +79,7 @@ * \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. * \param SubRegionDisable Sub-region disable field. * \param Size Region size of the region to be configured, for example 4K, 8K. -*/ +*/ #define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ ((DisableExec << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ ((AccessPermission << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ @@ -95,21 +95,22 @@ /** * Struct for a single MPU Region */ -typedef struct _ARM_MPU_Region_t { - uint32_t RBAR; //!< The region base address register value (RBAR) - uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR +typedef struct _ARM_MPU_Region_t +{ + uint32_t RBAR; //!< The region base address register value (RBAR) + uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR } ARM_MPU_Region_t; - + /** Enable the MPU. * \param MPU_Control Default access permissions for unconfigured regions. */ __STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) { - __DSB(); - __ISB(); - MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; + __DSB(); + __ISB(); + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; #ifdef SCB_SHCSR_MEMFAULTENA_Msk - SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; #endif } @@ -117,12 +118,12 @@ __STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) */ __STATIC_INLINE void ARM_MPU_Disable() { - __DSB(); - __ISB(); + __DSB(); + __ISB(); #ifdef SCB_SHCSR_MEMFAULTENA_Msk - SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; #endif - MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; + MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; } /** Clear and disable the given MPU region. @@ -130,30 +131,30 @@ __STATIC_INLINE void ARM_MPU_Disable() */ __STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) { - MPU->RNR = rnr; - MPU->RASR = 0u; + MPU->RNR = rnr; + MPU->RASR = 0u; } /** Configure an MPU region. * \param rbar Value for RBAR register. * \param rsar Value for RSAR register. -*/ +*/ __STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) { - MPU->RBAR = rbar; - MPU->RASR = rasr; + MPU->RBAR = rbar; + MPU->RASR = rasr; } /** Configure the given MPU region. * \param rnr Region number to be configured. * \param rbar Value for RBAR register. * \param rsar Value for RSAR register. -*/ +*/ __STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) { - MPU->RNR = rnr; - MPU->RBAR = rbar; - MPU->RASR = rasr; + MPU->RNR = rnr; + MPU->RBAR = rbar; + MPU->RASR = rasr; } /** Memcopy with strictly ordered memory access, e.g. for register targets. @@ -161,22 +162,22 @@ __STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t r * \param src Source data is copied from. * \param len Amount of data words to be copied. */ -__STATIC_INLINE void orderedCpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) +__STATIC_INLINE void orderedCpy(volatile uint32_t *dst, const uint32_t *__RESTRICT src, uint32_t len) { - uint32_t i; - for (i = 0u; i < len; ++i) - { - dst[i] = src[i]; - } + uint32_t i; + for (i = 0u; i < len; ++i) + { + dst[i] = src[i]; + } } /** Load the given number of MPU regions from a table. * \param table Pointer to the MPU configuration table. * \param cnt Amount of regions to be configured. */ -__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) +__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const *table, uint32_t cnt) { - orderedCpy(&(MPU->RBAR), &(table->RBAR), cnt*sizeof(ARM_MPU_Region_t)/4u); + orderedCpy(&(MPU->RBAR), &(table->RBAR), cnt * sizeof(ARM_MPU_Region_t) / 4u); } #endif diff --git a/bsp/nuvoton/libraries/m2354/CMSIS/Include/tz_context.h b/bsp/nuvoton/libraries/m2354/CMSIS/Include/tz_context.h index 0784d26cac..ecc24c079f 100644 --- a/bsp/nuvoton/libraries/m2354/CMSIS/Include/tz_context.h +++ b/bsp/nuvoton/libraries/m2354/CMSIS/Include/tz_context.h @@ -26,44 +26,44 @@ * Version 1.0 * Initial Release *---------------------------------------------------------------------------*/ - + #ifndef TZ_CONTEXT_H #define TZ_CONTEXT_H - + #include - + #ifndef TZ_MODULEID_T -#define TZ_MODULEID_T -/// \details Data type that identifies secure software modules called by a process. -typedef uint32_t TZ_ModuleId_t; + #define TZ_MODULEID_T + /// \details Data type that identifies secure software modules called by a process. + typedef uint32_t TZ_ModuleId_t; #endif - + /// \details TZ Memory ID identifies an allocated memory slot. typedef uint32_t TZ_MemoryId_t; - + /// Initialize secure context memory system /// \return execution status (1: success, 0: error) -uint32_t TZ_InitContextSystem_S (void); - +uint32_t TZ_InitContextSystem_S(void); + /// Allocate context memory for calling secure software modules in TrustZone /// \param[in] module identifies software modules called from non-secure mode /// \return value != 0 id TrustZone memory slot identifier /// \return value 0 no memory available or internal error -TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module); - +TZ_MemoryId_t TZ_AllocModuleContext_S(TZ_ModuleId_t module); + /// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S /// \param[in] id TrustZone memory slot identifier /// \return execution status (1: success, 0: error) -uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id); - +uint32_t TZ_FreeModuleContext_S(TZ_MemoryId_t id); + /// Load secure context (called on RTOS thread context switch) /// \param[in] id TrustZone memory slot identifier /// \return execution status (1: success, 0: error) -uint32_t TZ_LoadContext_S (TZ_MemoryId_t id); - +uint32_t TZ_LoadContext_S(TZ_MemoryId_t id); + /// Store secure context (called on RTOS thread context switch) /// \param[in] id TrustZone memory slot identifier /// \return execution status (1: success, 0: error) -uint32_t TZ_StoreContext_S (TZ_MemoryId_t id); - +uint32_t TZ_StoreContext_S(TZ_MemoryId_t id); + #endif // TZ_CONTEXT_H diff --git a/bsp/nuvoton/libraries/m2354/USBHostLib/inc/config.h b/bsp/nuvoton/libraries/m2354/USBHostLib/inc/config.h index 46a876e17b..47ca7d9d2a 100644 --- a/bsp/nuvoton/libraries/m2354/USBHostLib/inc/config.h +++ b/bsp/nuvoton/libraries/m2354/USBHostLib/inc/config.h @@ -17,7 +17,7 @@ /*----------------------------------------------------------------------------------------*/ /* Hardware settings */ /*----------------------------------------------------------------------------------------*/ -#define HCLK_MHZ 192 /* used for loop-delay. must be larger than +#define HCLK_MHZ 192 /* used for loop-delay. must be larger than true HCLK clock MHz */ #define ENABLE_OHCI_IRQ() NVIC_EnableIRQ(USBH_IRQn) @@ -25,12 +25,12 @@ #define ENABLE_OHCI /* Enable OHCI host controller */ -#define OHCI_ISO_DELAY 4 /* preserved number frames while scheduling +#define OHCI_ISO_DELAY 4 /* preserved number frames while scheduling OHCI isochronous transfer */ -#define MAX_DESC_BUFF_SIZE 512 /* To hold the configuration descriptor, USB +#define MAX_DESC_BUFF_SIZE 512 /* To hold the configuration descriptor, USB core will allocate a buffer with this size - for each connected device. USB core does + for each connected device. USB core does not release it until device disconnected. */ /*----------------------------------------------------------------------------------------*/ @@ -57,7 +57,7 @@ /* Re-defined staff for various compiler */ /*----------------------------------------------------------------------------------------*/ #ifdef __ICCARM__ -#define __inline inline + #define __inline inline #endif @@ -70,21 +70,21 @@ //#define DUMP_DESCRIPTOR /* dump descriptors */ #ifdef ENABLE_ERROR_MSG -#define USB_error rt_kprintf + #define USB_error rt_kprintf #else -#define USB_error(...) + #define USB_error(...) #endif #ifdef ENABLE_DEBUG_MSG -#define USB_debug rt_kprintf -#ifdef ENABLE_VERBOSE_DEBUG -#define USB_vdebug rt_kprintf + #define USB_debug rt_kprintf + #ifdef ENABLE_VERBOSE_DEBUG + #define USB_vdebug rt_kprintf + #else + #define USB_vdebug(...) + #endif #else -#define USB_vdebug(...) -#endif -#else -#define USB_debug(...) -#define USB_vdebug(...) + #define USB_debug(...) + #define USB_vdebug(...) #endif diff --git a/bsp/nuvoton/libraries/m2354/USBHostLib/inc/usbh_lib.h b/bsp/nuvoton/libraries/m2354/USBHostLib/inc/usbh_lib.h index e76eebdfe2..9597e14ba8 100644 --- a/bsp/nuvoton/libraries/m2354/USBHostLib/inc/usbh_lib.h +++ b/bsp/nuvoton/libraries/m2354/USBHostLib/inc/usbh_lib.h @@ -51,7 +51,7 @@ extern "C" #define USBH_ERR_DISCONNECTED -259 /*!< USB device was disconnected */ #define USBH_ERR_TRANSACTION -271 /*!< USB transaction timeout, CRC, Bad PID, etc. */ -#define USBH_ERR_BABBLE_DETECTED -272 /*!< A babble is detected during the transaction */ +#define USBH_ERR_BABBLE_DETECTED -272 /*!< A 'babble' is detected during the transaction */ #define USBH_ERR_DATA_BUFF -274 /*!< Data buffer overrun or underrun */ #define USBH_ERR_CC_NO_ERR -280 /*!< OHCI CC code - no error */ @@ -145,7 +145,7 @@ extern int usbh_polling_root_hubs(void); extern void usbh_install_conn_callback(CONN_FUNC *conn_func, CONN_FUNC *disconn_func); extern void usbh_suspend(void); extern void usbh_resume(void); -extern struct udev_t * usbh_find_device(char *hub_id, int port); +extern struct udev_t *usbh_find_device(char *hub_id, int port); /** * @brief A function return current tick count. * @return Current tick. @@ -161,7 +161,7 @@ extern uint32_t usbh_tick_from_millisecond(uint32_t msec); /* This function mu /* */ /*------------------------------------------------------------------*/ extern void usbh_cdc_init(void); -extern struct cdc_dev_t * usbh_cdc_get_device_list(void); +extern struct cdc_dev_t *usbh_cdc_get_device_list(void); /// @cond HIDDEN_SYMBOLS extern int32_t usbh_cdc_get_line_coding(struct cdc_dev_t *cdev, struct line_coding_t *line_code); extern int32_t usbh_cdc_set_line_coding(struct cdc_dev_t *cdev, struct line_coding_t *line_code); @@ -178,7 +178,7 @@ extern int32_t usbh_cdc_send_data(struct cdc_dev_t *cdev, uint8_t *buff, int bu /* */ /*------------------------------------------------------------------*/ extern void usbh_hid_init(void); -extern struct usbhid_dev * usbh_hid_get_device_list(void); +extern struct usbhid_dev *usbh_hid_get_device_list(void); extern int32_t usbh_hid_get_report_descriptor(struct usbhid_dev *hdev, uint8_t *desc_buf, int buf_max_len); extern int32_t usbh_hid_get_report(struct usbhid_dev *hdev, int rtp_typ, int rtp_id, uint8_t *data, int len); extern int32_t usbh_hid_set_report(struct usbhid_dev *hdev, int rtp_typ, int rtp_id, uint8_t *data, int len); @@ -211,7 +211,7 @@ extern int usbh_umas_reset_disk(int drv_no); /*------------------------------------------------------------------*/ extern void usbh_uac_init(void); extern int usbh_uac_open(struct uac_dev_t *audev); -extern struct uac_dev_t * usbh_uac_get_device_list(void); +extern struct uac_dev_t *usbh_uac_get_device_list(void); extern int usbh_uac_get_channel_number(struct uac_dev_t *audev, uint8_t target); extern int usbh_uac_get_bit_resolution(struct uac_dev_t *audev, uint8_t target, uint8_t *byte_cnt); extern int usbh_uac_get_sampling_rate(struct uac_dev_t *audev, uint8_t target, uint32_t *srate_list, int max_cnt, uint8_t *type); diff --git a/bsp/nuvoton/libraries/m2354/USBHostLib/src/usb_core.c b/bsp/nuvoton/libraries/m2354/USBHostLib/src/usb_core.c index fa11e1d357..b72f8d6ab8 100644 --- a/bsp/nuvoton/libraries/m2354/USBHostLib/src/usb_core.c +++ b/bsp/nuvoton/libraries/m2354/USBHostLib/src/usb_core.c @@ -22,7 +22,7 @@ USBH_T *_ohci; -static UDEV_DRV_T * _drivers[MAX_UDEV_DRIVER]; +static UDEV_DRV_T *_drivers[MAX_UDEV_DRIVER]; static CONN_FUNC *g_conn_func, *g_disconn_func; /// @endcond HIDDEN_SYMBOLS @@ -34,7 +34,7 @@ static CONN_FUNC *g_conn_func, *g_disconn_func; */ void usbh_core_init() { - if((__PC() & NS_OFFSET) == NS_OFFSET) + if ((__PC() & NS_OFFSET) == NS_OFFSET) { _ohci = USBH_NS; } @@ -50,7 +50,7 @@ void usbh_core_init() g_conn_func = NULL; g_disconn_func = NULL; - // usbh_hub_init(); +// usbh_hub_init(); usbh_memory_init(); @@ -111,7 +111,7 @@ int usbh_connect_device(UDEV_T *udev) if (g_conn_func) g_conn_func(udev, 0); - + return 0; } @@ -123,8 +123,8 @@ void usbh_disconnect_device(UDEV_T *udev) if (g_disconn_func) g_disconn_func(udev, 0); - -#if 1 //CHECK: Maybe create a new API to quit_xfer and free udev for application + +#if 1 //CHECK: Maybe create a new API to quit_xfer and free udev for application usbh_quit_xfer(udev, &(udev->ep0)); /* Quit control transfer if hw_pipe is not NULL. */ /* remove device from global device list */ @@ -153,7 +153,7 @@ int usbh_reset_port(UDEV_T *udev) if (udev->parent == NULL) { if (udev->hc_driver) - return udev->hc_driver->rthub_port_reset(udev->port_num-1); + return udev->hc_driver->rthub_port_reset(udev->port_num - 1); else return USBH_ERR_NOT_FOUND; } @@ -171,7 +171,7 @@ int usbh_reset_port(UDEV_T *udev) */ int usbh_quit_utr(UTR_T *utr) { - if(!utr || !utr->udev) + if (!utr || !utr->udev) return USBH_ERR_NOT_FOUND; return utr->udev->hc_driver->quit_xfer(utr, NULL); diff --git a/bsp/nuvoton/libraries/m480/CMSIS/Include/arm_common_tables.h b/bsp/nuvoton/libraries/m480/CMSIS/Include/arm_common_tables.h index 8742a56991..03153851b8 100644 --- a/bsp/nuvoton/libraries/m480/CMSIS/Include/arm_common_tables.h +++ b/bsp/nuvoton/libraries/m480/CMSIS/Include/arm_common_tables.h @@ -2,12 +2,12 @@ * Copyright (C) 2010-2014 ARM Limited. All rights reserved. * * $Date: 19. October 2015 -* $Revision: V.1.4.5 a +* $Revision: V.1.4.5 a * -* Project: CMSIS DSP Library -* Title: arm_common_tables.h +* Project: CMSIS DSP Library +* Title: arm_common_tables.h * -* Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions +* Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions * * Target Processor: Cortex-M4/Cortex-M3 * diff --git a/bsp/nuvoton/libraries/m480/CMSIS/Include/arm_const_structs.h b/bsp/nuvoton/libraries/m480/CMSIS/Include/arm_const_structs.h index 726d06eb69..4d02617344 100644 --- a/bsp/nuvoton/libraries/m480/CMSIS/Include/arm_const_structs.h +++ b/bsp/nuvoton/libraries/m480/CMSIS/Include/arm_const_structs.h @@ -2,12 +2,12 @@ * Copyright (C) 2010-2014 ARM Limited. All rights reserved. * * $Date: 19. March 2015 -* $Revision: V.1.4.5 +* $Revision: V.1.4.5 * -* Project: CMSIS DSP Library -* Title: arm_const_structs.h +* Project: CMSIS DSP Library +* Title: arm_const_structs.h * -* Description: This file has constant structs that are initialized for +* Description: This file has constant structs that are initialized for * user convenience. For example, some can be given as * arguments to the arm_cfft_f32() function. * @@ -46,34 +46,34 @@ #include "arm_math.h" #include "arm_common_tables.h" - extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16; - extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32; - extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64; - extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128; - extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256; - extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512; - extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024; - extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048; - extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096; +extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16; +extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32; +extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64; +extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128; +extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256; +extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512; +extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024; +extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048; +extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096; - extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len16; - extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len32; - extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len64; - extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len128; - extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len256; - extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len512; - extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024; - extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048; - extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096; +extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len16; +extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len32; +extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len64; +extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len128; +extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len256; +extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len512; +extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024; +extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048; +extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096; - extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len16; - extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len32; - extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len64; - extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len128; - extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len256; - extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len512; - extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024; - extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048; - extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096; +extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len16; +extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len32; +extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len64; +extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len128; +extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len256; +extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len512; +extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024; +extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048; +extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096; #endif diff --git a/bsp/nuvoton/libraries/m480/CMSIS/Include/cmsis_armcc_V6.h b/bsp/nuvoton/libraries/m480/CMSIS/Include/cmsis_armcc_V6.h index cd13240ce3..6d8f998d84 100644 --- a/bsp/nuvoton/libraries/m480/CMSIS/Include/cmsis_armcc_V6.h +++ b/bsp/nuvoton/libraries/m480/CMSIS/Include/cmsis_armcc_V6.h @@ -49,7 +49,7 @@ */ __attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) { - __ASM volatile ("cpsie i" : : : "memory"); + __ASM volatile("cpsie i" : : : "memory"); } @@ -60,7 +60,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) */ __attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) { - __ASM volatile ("cpsid i" : : : "memory"); + __ASM volatile("cpsid i" : : : "memory"); } @@ -71,10 +71,10 @@ __attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, control" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, control" : "=r"(result)); + return (result); } @@ -86,10 +86,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_CONTROL_NS(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, control_ns" : "=r"(result)); + return (result); } #endif @@ -101,7 +101,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_CONTROL_NS(void */ __attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t control) { - __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ASM volatile("MSR control, %0" : : "r"(control) : "memory"); } @@ -113,7 +113,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t contr */ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_CONTROL_NS(uint32_t control) { - __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ASM volatile("MSR control_ns, %0" : : "r"(control) : "memory"); } #endif @@ -125,10 +125,10 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_CONTROL_NS(uint32_t */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, ipsr" : "=r"(result)); + return (result); } @@ -140,10 +140,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_IPSR_NS(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, ipsr_ns" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, ipsr_ns" : "=r"(result)); + return (result); } #endif @@ -155,10 +155,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_IPSR_NS(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, apsr" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, apsr" : "=r"(result)); + return (result); } @@ -170,10 +170,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_APSR_NS(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, apsr_ns" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, apsr_ns" : "=r"(result)); + return (result); } #endif @@ -185,10 +185,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_APSR_NS(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, xpsr" : "=r"(result)); + return (result); } @@ -200,10 +200,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_xPSR_NS(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, xpsr_ns" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, xpsr_ns" : "=r"(result)); + return (result); } #endif @@ -215,10 +215,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_xPSR_NS(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSP(void) { - register uint32_t result; + register uint32_t result; - __ASM volatile ("MRS %0, psp" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, psp" : "=r"(result)); + return (result); } @@ -230,10 +230,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSP(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSP_NS(void) { - register uint32_t result; + register uint32_t result; - __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, psp_ns" : "=r"(result)); + return (result); } #endif @@ -245,7 +245,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSP_NS(void) */ __attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) { - __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : "sp"); + __ASM volatile("MSR psp, %0" : : "r"(topOfProcStack) : "sp"); } @@ -257,7 +257,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProc */ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) { - __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : "sp"); + __ASM volatile("MSR psp_ns, %0" : : "r"(topOfProcStack) : "sp"); } #endif @@ -269,10 +269,10 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSP_NS(uint32_t top */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSP(void) { - register uint32_t result; + register uint32_t result; - __ASM volatile ("MRS %0, msp" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, msp" : "=r"(result)); + return (result); } @@ -284,10 +284,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSP(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSP_NS(void) { - register uint32_t result; + register uint32_t result; - __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, msp_ns" : "=r"(result)); + return (result); } #endif @@ -299,7 +299,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSP_NS(void) */ __attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) { - __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : "sp"); + __ASM volatile("MSR msp, %0" : : "r"(topOfMainStack) : "sp"); } @@ -311,7 +311,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMain */ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) { - __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : "sp"); + __ASM volatile("MSR msp_ns, %0" : : "r"(topOfMainStack) : "sp"); } #endif @@ -323,10 +323,10 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSP_NS(uint32_t top */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, primask" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, primask" : "=r"(result)); + return (result); } @@ -338,10 +338,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PRIMASK_NS(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, primask_ns" : "=r"(result)); + return (result); } #endif @@ -353,7 +353,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PRIMASK_NS(void */ __attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) { - __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); + __ASM volatile("MSR primask, %0" : : "r"(priMask) : "memory"); } @@ -365,7 +365,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMa */ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) { - __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); + __ASM volatile("MSR primask_ns, %0" : : "r"(priMask) : "memory"); } #endif @@ -379,7 +379,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PRIMASK_NS(uint32_t */ __attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void) { - __ASM volatile ("cpsie f" : : : "memory"); + __ASM volatile("cpsie f" : : : "memory"); } @@ -390,7 +390,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void) */ __attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void) { - __ASM volatile ("cpsid f" : : : "memory"); + __ASM volatile("cpsid f" : : : "memory"); } @@ -401,10 +401,10 @@ __attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, basepri" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, basepri" : "=r"(result)); + return (result); } @@ -416,10 +416,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_BASEPRI_NS(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, basepri_ns" : "=r"(result)); + return (result); } #endif @@ -431,7 +431,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_BASEPRI_NS(void */ __attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value) { - __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); + __ASM volatile("MSR basepri, %0" : : "r"(value) : "memory"); } @@ -443,7 +443,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value */ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_NS(uint32_t value) { - __ASM volatile ("MSR basepri_ns, %0" : : "r" (value) : "memory"); + __ASM volatile("MSR basepri_ns, %0" : : "r"(value) : "memory"); } #endif @@ -456,7 +456,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_NS(uint32_t */ __attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) { - __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); + __ASM volatile("MSR basepri_max, %0" : : "r"(value) : "memory"); } @@ -464,12 +464,12 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t v /** \brief Set Base Priority with condition (non_secure) \details Assigns the given value to the non-secure Base Priority register when in secure state only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. + or the new value increases the BASEPRI priority level. \param [in] basePri Base Priority value to set */ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_MAX_NS(uint32_t value) { - __ASM volatile ("MSR basepri_max_ns, %0" : : "r" (value) : "memory"); + __ASM volatile("MSR basepri_max_ns, %0" : : "r"(value) : "memory"); } #endif @@ -481,10 +481,10 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_MAX_NS(uint */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, faultmask" : "=r"(result)); + return (result); } @@ -496,10 +496,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FAULTMASK_NS(void) { - uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, faultmask_ns" : "=r"(result)); + return (result); } #endif @@ -511,7 +511,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FAULTMASK_NS(vo */ __attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) { - __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); + __ASM volatile("MSR faultmask, %0" : : "r"(faultMask) : "memory"); } @@ -523,7 +523,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t fau */ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) { - __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); + __ASM volatile("MSR faultmask_ns, %0" : : "r"(faultMask) : "memory"); } #endif @@ -540,10 +540,10 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FAULTMASK_NS(uint32 */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSPLIM(void) { - register uint32_t result; + register uint32_t result; - __ASM volatile ("MRS %0, psplim" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, psplim" : "=r"(result)); + return (result); } @@ -555,10 +555,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSPLIM(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSPLIM_NS(void) { - register uint32_t result; + register uint32_t result; - __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, psplim_ns" : "=r"(result)); + return (result); } #endif @@ -570,7 +570,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSPLIM_NS(void) */ __attribute__((always_inline)) __STATIC_INLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) { - __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); + __ASM volatile("MSR psplim, %0" : : "r"(ProcStackPtrLimit)); } @@ -582,7 +582,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_PSPLIM(uint32_t ProcSt */ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) { - __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); + __ASM volatile("MSR psplim_ns, %0\n" : : "r"(ProcStackPtrLimit)); } #endif @@ -594,11 +594,11 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSPLIM_NS(uint32_t */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSPLIM(void) { - register uint32_t result; + register uint32_t result; - __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + __ASM volatile("MRS %0, msplim" : "=r"(result)); - return(result); + return (result); } @@ -610,10 +610,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSPLIM(void) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSPLIM_NS(void) { - register uint32_t result; + register uint32_t result; - __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); - return(result); + __ASM volatile("MRS %0, msplim_ns" : "=r"(result)); + return (result); } #endif @@ -625,7 +625,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSPLIM_NS(void) */ __attribute__((always_inline)) __STATIC_INLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) { - __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); + __ASM volatile("MSR msplim, %0" : : "r"(MainStackPtrLimit)); } @@ -637,7 +637,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_MSPLIM(uint32_t MainSt */ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) { - __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); + __ASM volatile("MSR msplim_ns, %0" : : "r"(MainStackPtrLimit)); } #endif @@ -656,14 +656,14 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSPLIM_NS(uint32_t __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) { #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - uint32_t result; + uint32_t result; - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); - __ASM volatile (""); - return(result); + __ASM volatile(""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile("VMRS %0, fpscr" : "=r"(result)); + __ASM volatile(""); + return (result); #else - return(0); + return (0); #endif } #endif @@ -677,14 +677,14 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FPSCR_NS(void) { #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - uint32_t result; + uint32_t result; - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMRS %0, fpscr_ns" : "=r" (result) ); - __ASM volatile (""); - return(result); + __ASM volatile(""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile("VMRS %0, fpscr_ns" : "=r"(result)); + __ASM volatile(""); + return (result); #else - return(0); + return (0); #endif } #endif @@ -700,9 +700,9 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FPSCR_NS(void) __attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) { #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); - __ASM volatile (""); + __ASM volatile(""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile("VMSR fpscr, %0" : : "r"(fpscr) : "vfpcc"); + __ASM volatile(""); #endif } #endif @@ -716,9 +716,9 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t fpscr) { #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMSR fpscr_ns, %0" : : "r" (fpscr) : "vfpcc"); - __ASM volatile (""); + __ASM volatile(""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile("VMSR fpscr_ns, %0" : : "r"(fpscr) : "vfpcc"); + __ASM volatile(""); #endif } #endif @@ -740,11 +740,11 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t f * For thumb1, use low register (r0-r7), specified by constraint "l" * Otherwise, use general registers, specified by constraint "r" */ #if defined (__thumb__) && !defined (__thumb2__) -#define __CMSIS_GCC_OUT_REG(r) "=l" (r) -#define __CMSIS_GCC_USE_REG(r) "l" (r) + #define __CMSIS_GCC_OUT_REG(r) "=l" (r) + #define __CMSIS_GCC_USE_REG(r) "l" (r) #else -#define __CMSIS_GCC_OUT_REG(r) "=r" (r) -#define __CMSIS_GCC_USE_REG(r) "r" (r) + #define __CMSIS_GCC_OUT_REG(r) "=r" (r) + #define __CMSIS_GCC_USE_REG(r) "r" (r) #endif /** @@ -818,10 +818,10 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t f #if 0 __attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) { - uint32_t result; + uint32_t result; - __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); + __ASM volatile("rev16 %0, %1" : __CMSIS_GCC_OUT_REG(result) : __CMSIS_GCC_USE_REG(value)); + return (result); } #endif @@ -832,13 +832,13 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) \param [in] value Value to reverse \return Reversed value */ - /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ +/* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ __attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) { - int32_t result; + int32_t result; - __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); + __ASM volatile("revsh %0, %1" : __CMSIS_GCC_OUT_REG(result) : __CMSIS_GCC_USE_REG(value)); + return (result); } @@ -851,7 +851,7 @@ __attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) { - return (op1 >> op2) | (op1 << (32U - op2)); + return (op1 >> op2) | (op1 << (32U - op2)); } @@ -871,26 +871,26 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint \param [in] value Value to reverse \return Reversed value */ - /* ToDo: ARMCC_V6: check if __builtin_arm_rbit is supported */ +/* ToDo: ARMCC_V6: check if __builtin_arm_rbit is supported */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) { - uint32_t result; + uint32_t result; #if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ - __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + __ASM volatile("rbit %0, %1" : "=r"(result) : "r"(value)); #else - int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ - result = value; /* r will be reversed bits of v; first get LSB of v */ - for (value >>= 1U; value; value >>= 1U) - { - result <<= 1U; - result |= value & 1U; - s--; - } - result <<= s; /* shift when v's highest bits are zero */ + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ #endif - return(result); + return (result); } @@ -1015,10 +1015,10 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) { - uint32_t result; + uint32_t result; - __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); + __ASM volatile("rrx %0, %1" : __CMSIS_GCC_OUT_REG(result) : __CMSIS_GCC_USE_REG(value)); + return (result); } @@ -1032,8 +1032,8 @@ __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t { uint32_t result; - __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint8_t) result); /* Add explicit type cast here */ + __ASM volatile("ldrbt %0, %1" : "=r"(result) : "Q"(*ptr)); + return ((uint8_t) result); /* Add explicit type cast here */ } @@ -1047,8 +1047,8 @@ __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_ { uint32_t result; - __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint16_t) result); /* Add explicit type cast here */ + __ASM volatile("ldrht %0, %1" : "=r"(result) : "Q"(*ptr)); + return ((uint16_t) result); /* Add explicit type cast here */ } @@ -1062,8 +1062,8 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t { uint32_t result; - __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return(result); + __ASM volatile("ldrt %0, %1" : "=r"(result) : "Q"(*ptr)); + return (result); } @@ -1075,7 +1075,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t */ __attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) { - __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile("strbt %1, %0" : "=Q"(*ptr) : "r"((uint32_t)value)); } @@ -1087,7 +1087,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volat */ __attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) { - __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile("strht %1, %0" : "=Q"(*ptr) : "r"((uint32_t)value)); } @@ -1099,7 +1099,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, vola */ __attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *ptr) { - __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); + __ASM volatile("strt %1, %0" : "=Q"(*ptr) : "r"(value)); } #endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ @@ -1117,8 +1117,8 @@ __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDAB(volatile uint8_t * { uint32_t result; - __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint8_t) result); + __ASM volatile("ldab %0, %1" : "=r"(result) : "Q"(*ptr)); + return ((uint8_t) result); } @@ -1132,8 +1132,8 @@ __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDAH(volatile uint16_t { uint32_t result; - __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint16_t) result); + __ASM volatile("ldah %0, %1" : "=r"(result) : "Q"(*ptr)); + return ((uint16_t) result); } @@ -1147,8 +1147,8 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDA(volatile uint32_t { uint32_t result; - __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); - return(result); + __ASM volatile("lda %0, %1" : "=r"(result) : "Q"(*ptr)); + return (result); } @@ -1160,7 +1160,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDA(volatile uint32_t */ __attribute__((always_inline)) __STATIC_INLINE void __STLB(uint8_t value, volatile uint8_t *ptr) { - __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile("stlb %1, %0" : "=Q"(*ptr) : "r"((uint32_t)value)); } @@ -1172,7 +1172,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __STLB(uint8_t value, volati */ __attribute__((always_inline)) __STATIC_INLINE void __STLH(uint16_t value, volatile uint16_t *ptr) { - __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile("stlh %1, %0" : "=Q"(*ptr) : "r"((uint32_t)value)); } @@ -1184,7 +1184,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __STLH(uint16_t value, volat */ __attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volatile uint32_t *ptr) { - __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile("stl %1, %0" : "=Q"(*ptr) : "r"((uint32_t)value)); } @@ -1262,308 +1262,308 @@ __attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volati __attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("sadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("qadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("shadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uqadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uhadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("ssub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("qsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("shsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("usub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uqsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uhsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("sadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("qadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("shadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uqadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uhadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("ssub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("qsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("shsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("usub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uqsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uhsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("sasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("qasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("shasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uqasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uhasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("ssax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("qsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("shsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("usax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uqsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uhsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("usad8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) { - uint32_t result; + uint32_t result; - __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); + __ASM volatile("usada8 %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); + return (result); } #define __SSAT16(ARG1,ARG2) \ @@ -1582,190 +1582,194 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, u __attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) { - uint32_t result; + uint32_t result; - __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); - return(result); + __ASM volatile("uxtb16 %0, %1" : "=r"(result) : "r"(op1)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("uxtab16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) { - uint32_t result; + uint32_t result; - __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); - return(result); + __ASM volatile("sxtb16 %0, %1" : "=r"(result) : "r"(op1)); + return (result); } __attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("sxtab16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("smuad %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("smuadx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD(uint32_t op1, uint32_t op2, uint32_t op3) { - uint32_t result; + uint32_t result; - __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); + __ASM volatile("smlad %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); + return (result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX(uint32_t op1, uint32_t op2, uint32_t op3) { - uint32_t result; + uint32_t result; - __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); + __ASM volatile("smladx %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); + return (result); } -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALD(uint32_t op1, uint32_t op2, uint64_t acc) { - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; + union llreg_u + { + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); + __ASM volatile("smlald %0, %1, %2, %3" : "=r"(llr.w32[0]), "=r"(llr.w32[1]): "r"(op1), "r"(op2), "0"(llr.w32[0]), "1"(llr.w32[1])); #else /* Big endian */ - __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); + __ASM volatile("smlald %0, %1, %2, %3" : "=r"(llr.w32[1]), "=r"(llr.w32[0]): "r"(op1), "r"(op2), "0"(llr.w32[1]), "1"(llr.w32[0])); #endif - return(llr.w64); + return (llr.w64); } -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALDX(uint32_t op1, uint32_t op2, uint64_t acc) { - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; + union llreg_u + { + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); + __ASM volatile("smlaldx %0, %1, %2, %3" : "=r"(llr.w32[0]), "=r"(llr.w32[1]): "r"(op1), "r"(op2), "0"(llr.w32[0]), "1"(llr.w32[1])); #else /* Big endian */ - __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); + __ASM volatile("smlaldx %0, %1, %2, %3" : "=r"(llr.w32[1]), "=r"(llr.w32[0]): "r"(op1), "r"(op2), "0"(llr.w32[1]), "1"(llr.w32[0])); #endif - return(llr.w64); + return (llr.w64); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("smusd %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("smusdx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD(uint32_t op1, uint32_t op2, uint32_t op3) { - uint32_t result; + uint32_t result; - __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); + __ASM volatile("smlsd %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); + return (result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX(uint32_t op1, uint32_t op2, uint32_t op3) { - uint32_t result; + uint32_t result; - __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); - return(result); + __ASM volatile("smlsdx %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); + return (result); } -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLD(uint32_t op1, uint32_t op2, uint64_t acc) { - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; + union llreg_u + { + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); + __ASM volatile("smlsld %0, %1, %2, %3" : "=r"(llr.w32[0]), "=r"(llr.w32[1]): "r"(op1), "r"(op2), "0"(llr.w32[0]), "1"(llr.w32[1])); #else /* Big endian */ - __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); + __ASM volatile("smlsld %0, %1, %2, %3" : "=r"(llr.w32[1]), "=r"(llr.w32[0]): "r"(op1), "r"(op2), "0"(llr.w32[1]), "1"(llr.w32[0])); #endif - return(llr.w64); + return (llr.w64); } -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLDX(uint32_t op1, uint32_t op2, uint64_t acc) { - union llreg_u{ - uint32_t w32[2]; - uint64_t w64; - } llr; - llr.w64 = acc; + union llreg_u + { + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ - __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); + __ASM volatile("smlsldx %0, %1, %2, %3" : "=r"(llr.w32[0]), "=r"(llr.w32[1]): "r"(op1), "r"(op2), "0"(llr.w32[0]), "1"(llr.w32[1])); #else /* Big endian */ - __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); + __ASM volatile("smlsldx %0, %1, %2, %3" : "=r"(llr.w32[1]), "=r"(llr.w32[0]): "r"(op1), "r"(op2), "0"(llr.w32[1]), "1"(llr.w32[0])); #endif - return(llr.w64); + return (llr.w64); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL(uint32_t op1, uint32_t op2) { - uint32_t result; + uint32_t result; - __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("sel %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } -__attribute__((always_inline)) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +__attribute__((always_inline)) __STATIC_INLINE int32_t __QADD(int32_t op1, int32_t op2) { - int32_t result; + int32_t result; - __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("qadd %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } -__attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +__attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB(int32_t op1, int32_t op2) { - int32_t result; + int32_t result; - __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); - return(result); + __ASM volatile("qsub %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); } #define __PKHBT(ARG1,ARG2,ARG3) \ @@ -1785,12 +1789,12 @@ __attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB( int32_t op1, in __RES; \ }) -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMMLA(int32_t op1, int32_t op2, int32_t op3) { - int32_t result; + int32_t result; - __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); - return(result); + __ASM volatile("smmla %0, %1, %2, %3" : "=r"(result): "r"(op1), "r"(op2), "r"(op3)); + return (result); } #endif /* (__ARM_FEATURE_DSP == 1U) */ diff --git a/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/sys_reg.h b/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/sys_reg.h index 2bf3288d24..b9bde8aa15 100644 --- a/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/sys_reg.h +++ b/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/sys_reg.h @@ -10,7 +10,7 @@ #define __SYS_REG_H__ #if defined ( __CC_ARM ) -#pragma anon_unions + #pragma anon_unions #endif /** @@ -3339,7 +3339,7 @@ typedef struct #define SYS_HIRCTCTL_CESTOPEN_Msk (0x1ul << SYS_HIRCTCTL_CESTOPEN_Pos) /*!< SYS_T::HIRCTCTL: CESTOPEN Mask */ #define SYS_HIRCTCTL_BOUNDEN_Pos (9) /*!< SYS_T::HIRCTCTL: BOUNDEN Position */ -#define SYS_HIRCTCTL_BOUNDEN_Msk (0x1ul << SYS_HIRCTCTL_BOUNDEN_Pos) /*!< SYS_T::HIRCTCTL: BOUNDEN Mask */ +#define SYS_HIRCTCTL_BOUNDEN_Msk (0x1ul << SYS_HIRCTCTL_BOUNDEN_Pos) /*!< SYS_T::HIRCTCTL: BOUNDEN Mask */ #define SYS_HIRCTCTL_REFCKSEL_Pos (10) /*!< SYS_T::HIRCTCTL: REFCKSEL Position */ #define SYS_HIRCTCTL_REFCKSEL_Msk (0x1ul << SYS_HIRCTCTL_REFCKSEL_Pos) /*!< SYS_T::HIRCTCTL: REFCKSEL Mask */ @@ -3656,7 +3656,7 @@ typedef struct /**@}*/ /* end of REGISTER group */ #if defined ( __CC_ARM ) -#pragma no_anon_unions + #pragma no_anon_unions #endif #endif /* __SYS_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m480/StdDriver/inc/nu_clk.h b/bsp/nuvoton/libraries/m480/StdDriver/inc/nu_clk.h index 9dc88b552d..a95a3f3618 100644 --- a/bsp/nuvoton/libraries/m480/StdDriver/inc/nu_clk.h +++ b/bsp/nuvoton/libraries/m480/StdDriver/inc/nu_clk.h @@ -298,7 +298,7 @@ extern "C" #define CLK_PCLKDIV_PCLK1DIV4 (0x2UL << CLK_PCLKDIV_APB1DIV_Pos) /*!< PCLKDIV Setting for PCLK1 = 1/4 HCLK \hideinitializer */ #define CLK_PCLKDIV_PCLK1DIV8 (0x3UL << CLK_PCLKDIV_APB1DIV_Pos) /*!< PCLKDIV Setting for PCLK1 = 1/8 HCLK \hideinitializer */ #define CLK_PCLKDIV_PCLK1DIV16 (0x4UL << CLK_PCLKDIV_APB1DIV_Pos) /*!< PCLKDIV Setting for PCLK1 = 1/16 HCLK \hideinitializer */ -// +// #define CLK_PCLKDIV_APB0DIV_DIV1 (0x0UL << CLK_PCLKDIV_APB0DIV_Pos) /*!< PCLKDIV Setting for PCLK0 = HCLK \hideinitializer */ #define CLK_PCLKDIV_APB0DIV_DIV2 (0x1UL << CLK_PCLKDIV_APB0DIV_Pos) /*!< PCLKDIV Setting for PCLK0 = 1/2 HCLK \hideinitializer */ #define CLK_PCLKDIV_APB0DIV_DIV4 (0x2UL << CLK_PCLKDIV_APB0DIV_Pos) /*!< PCLKDIV Setting for PCLK0 = 1/4 HCLK \hideinitializer */ @@ -617,7 +617,7 @@ __STATIC_INLINE void CLK_SysTickDelay(uint32_t us) SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; /* Waiting for down-count to zero */ - while((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0UL) + while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0UL) { } @@ -642,7 +642,7 @@ __STATIC_INLINE void CLK_SysTickLongDelay(uint32_t us) do { - if(us > delay) + if (us > delay) { us -= delay; } @@ -657,13 +657,13 @@ __STATIC_INLINE void CLK_SysTickLongDelay(uint32_t us) SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; /* Waiting for down-count to zero */ - while((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0UL); + while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0UL); /* Disable SysTick counter */ SysTick->CTRL = 0UL; } - while(us > 0UL); + while (us > 0UL); } diff --git a/bsp/nuvoton/libraries/m480/StdDriver/inc/nu_trng.h b/bsp/nuvoton/libraries/m480/StdDriver/inc/nu_trng.h index 6a062241a9..cf8a7ea283 100644 --- a/bsp/nuvoton/libraries/m480/StdDriver/inc/nu_trng.h +++ b/bsp/nuvoton/libraries/m480/StdDriver/inc/nu_trng.h @@ -32,8 +32,8 @@ extern "C" /*----------------------------------------------------------------------------------------------*/ /** - * @brief Let TRNG engine know the currrent PCLK frequency. The CLKPSC is the peripheral - * clock frequency range for the selected value , the CLKPSC setting must be higher + * @brief Let TRNG engine know the currrent PCLK frequency. The CLKPSC is the peripheral + * clock frequency range for the selected value , the CLKPSC setting must be higher * than or equal to the actual peripheral clock frequency (for correct random generation). * @param clkpsc 0: PCLK is 80~100 MHz * 1: PCLK is 60~80 MHz diff --git a/bsp/nuvoton/libraries/m480/StdDriver/src/nu_crypto.c b/bsp/nuvoton/libraries/m480/StdDriver/src/nu_crypto.c index fd4bfe884a..03afc5fde3 100644 --- a/bsp/nuvoton/libraries/m480/StdDriver/src/nu_crypto.c +++ b/bsp/nuvoton/libraries/m480/StdDriver/src/nu_crypto.c @@ -16,9 +16,9 @@ #define ENABLE_DEBUG 0 #if ENABLE_DEBUG -#define CRPT_DBGMSG printf + #define CRPT_DBGMSG printf #else -#define CRPT_DBGMSG(...) do { } while (0) /* disable debug */ + #define CRPT_DBGMSG(...) do { } while (0) /* disable debug */ #endif /** @endcond HIDDEN_SYMBOLS */ @@ -75,8 +75,8 @@ void PRNG_Open(CRPT_T *crpt, uint32_t u32KeySize, uint32_t u32SeedReload, uint32 crpt->PRNG_SEED = u32Seed; } - crpt->PRNG_CTL = (u32KeySize << CRPT_PRNG_CTL_KEYSZ_Pos) | - (u32SeedReload << CRPT_PRNG_CTL_SEEDRLD_Pos); + crpt->PRNG_CTL = (u32KeySize << CRPT_PRNG_CTL_KEYSZ_Pos) | + (u32SeedReload << CRPT_PRNG_CTL_SEEDRLD_Pos); } /** @@ -178,7 +178,7 @@ void AES_SetKey(CRPT_T *crpt, uint32_t u32Channel, uint32_t au32Keys[], uint32_t uint32_t i, wcnt, key_reg_addr; key_reg_addr = (uint32_t)&crpt->AES0_KEY[0] + (u32Channel * 0x3CUL); - wcnt = 4UL + u32KeySize*2UL; + wcnt = 4UL + u32KeySize * 2UL; for (i = 0U; i < wcnt; i++) { @@ -379,9 +379,9 @@ void SHA_Open(CRPT_T *crpt, uint32_t u32OpMode, uint32_t u32SwapType, uint32_t h crpt->HMAC_KEYCNT = hmac_key_len; if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0) - crpt->HMAC_CTL |= (1<<4); /* M480MD HMACEN is CRYPTO_HMAC_CTL[4] */ + crpt->HMAC_CTL |= (1 << 4); /* M480MD HMACEN is CRYPTO_HMAC_CTL[4] */ else - crpt->HMAC_CTL |= (1<<11); /* M480LD HMACEN is CRYPTO_HMAC_CTL[11] */ + crpt->HMAC_CTL |= (1 << 11); /* M480LD HMACEN is CRYPTO_HMAC_CTL[11] */ } } @@ -447,7 +447,7 @@ void SHA_Read(CRPT_T *crpt, uint32_t u32Digest[]) wcnt = 16UL; } - reg_addr = (uint32_t)&(crpt->HMAC_DGST[0]); + reg_addr = (uint32_t) & (crpt->HMAC_DGST[0]); for (i = 0UL; i < wcnt; i++) { u32Digest[i] = inpw(reg_addr); @@ -887,7 +887,7 @@ const ECC_CURVE _Curve[] = static ECC_CURVE *pCurve; static ECC_CURVE Curve_Copy; -static ECC_CURVE * get_curve(E_ECC_CURVE ecc_curve); +static ECC_CURVE *get_curve(E_ECC_CURVE ecc_curve); static int32_t ecc_init_curve(CRPT_T *crpt, E_ECC_CURVE ecc_curve); static void run_ecc_codec(CRPT_T *crpt, uint32_t mode); @@ -990,7 +990,7 @@ static void Hex2RegEx(char input[], uint32_t volatile reg[], int shift) */ static char get_Nth_nibble_char(uint32_t val32, uint32_t idx) { - return hex_char_tbl[ (val32 >> (idx * 4U)) & 0xfU ]; + return hex_char_tbl[(val32 >> (idx * 4U)) & 0xfU ]; } @@ -1012,7 +1012,7 @@ static void Reg2Hex(int32_t count, uint32_t volatile reg[], char output[]) } } -static ECC_CURVE * get_curve(E_ECC_CURVE ecc_curve) +static ECC_CURVE *get_curve(E_ECC_CURVE ecc_curve) { uint32_t i; ECC_CURVE *ret = NULL; @@ -1108,7 +1108,7 @@ static int ecc_strcmp(char *s1, char *s2) while (*s1 == '0') s1++; while (*s2 == '0') s2++; - for ( ; *s1 || *s2; s1++, s2++) + for (; *s1 || *s2; s1++, s2++) { if ((*s1 >= 'A') && (*s1 <= 'Z')) c1 = *s1 + 32; @@ -1502,7 +1502,7 @@ int32_t ECC_GenerateSignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *messag Reg2Hex(pCurve->Echar, temp_result1, R); /* - * 4. Compute s = k ? 1 (e + d r)(mod n). If s = 0, go to step 2 + * 4. Compute s = k ? 1 } (e + d } r)(mod n). If s = 0, go to step 2 * (1) Write the curve order to N registers according * (2) Write 0x1 to Y1 registers * (3) Write the random integer k to X1 registers according @@ -1732,7 +1732,7 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, #endif /* - * 4. Compute u1 = e w (mod n) and u2 = r w (mod n) + * 4. Compute u1 = e } w (mod n) and u2 = r } w (mod n) * (1) Write the curve order and curve length to N ,M registers * (2) Write e, w to X1, Y1 registers * (3) Set ECCOP(CRPT_ECC_CTL[10:9]) to 01 @@ -1814,7 +1814,7 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, #endif /* - * 5. Compute X (x1, y1) = u1 * G + u2 * Q + * 5. Compute X・ (x1・, y1・) = u1 * G + u2 * Q * (1) Write the curve parameter A, B, N, and curve length M to corresponding registers * (2) Write the point G(x, y) to X1, Y1 registers * (3) Write u1 to K registers @@ -1833,17 +1833,17 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, * (16) Set ECCOP(CRPT_ECC_CTL[10:9]) to 10 * (17) Set START(CRPT_ECC_CTL[0]) to 1 * (18) Wait for BUSY(CRPT_ECC_STS[0]) be cleared - * (19) Read X1, Y1 registers to get X(x1, y1) + * (19) Read X1, Y1 registers to get X・(x1・, y1・) * (20) Write the curve order and curve length to N ,M registers - * (21) Write x1 to X1 registers + * (21) Write x1・ to X1 registers * (22) Write 0x0 to Y1 registers * (23) Set ECCOP(CRPT_ECC_CTL[10:9]) to 01 * (24) Set MOPOP(CRPT_ECC_CTL[12:11]) to 10 * (25) Set START(CRPT_ECC_CTL[0]) to 1 * (26) Wait for BUSY(CRPT_ECC_STS[0]) be cleared - * (27) Read X1 registers to get x1 (mod n) + * (27) Read X1 registers to get x1・ (mod n) * - * 6. The signature is valid if x1 = r, otherwise it is invalid + * 6. The signature is valid if x1・ = r, otherwise it is invalid */ /* @@ -1927,7 +1927,7 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, run_ecc_codec(crpt, ECCOP_POINT_ADD); - /* (19) Read X1, Y1 registers to get X(x1, y1) */ + /* (19) Read X1, Y1 registers to get X・(x1・, y1・) */ for (i = 0; i < 18; i++) { temp_x[i] = crpt->ECC_X1[i]; @@ -1949,7 +1949,7 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, Hex2Reg(pCurve->Eorder, crpt->ECC_N); /* - * (21) Write x1 to X1 registers + * (21) Write x1・ to X1 registers * (22) Write 0x0 to Y1 registers */ for (i = 0; i < 18; i++) @@ -1967,11 +1967,11 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, run_ecc_codec(crpt, ECCOP_MODULE | MODOP_ADD); - /* (27) Read X1 registers to get x1 (mod n) */ + /* (27) Read X1 registers to get x1・ (mod n) */ Reg2Hex(pCurve->Echar, crpt->ECC_X1, temp_hex_str); CRPT_DBGMSG("5-(27) x1' (mod n) = %s\n", temp_hex_str); - /* 6. The signature is valid if x1 = r, otherwise it is invalid */ + /* 6. The signature is valid if x1・ = r, otherwise it is invalid */ /* Compare with test pattern to check if r is correct or not */ if (ecc_strcmp(temp_hex_str, R) != 0) diff --git a/bsp/nuvoton/libraries/m480/USBHostLib/inc/config.h b/bsp/nuvoton/libraries/m480/USBHostLib/inc/config.h index 0dab057ac3..1534e645d2 100644 --- a/bsp/nuvoton/libraries/m480/USBHostLib/inc/config.h +++ b/bsp/nuvoton/libraries/m480/USBHostLib/inc/config.h @@ -18,7 +18,7 @@ /*----------------------------------------------------------------------------------------*/ /* Hardware settings */ /*----------------------------------------------------------------------------------------*/ -#define HCLK_MHZ 192 /* used for loop-delay. must be larger than +#define HCLK_MHZ 192 /* used for loop-delay. must be larger than true HCLK clock MHz */ #define ENABLE_OHCI_IRQ() NVIC_EnableIRQ(USBH_IRQn) @@ -29,26 +29,26 @@ #define ENABLE_OHCI /* Enable OHCI host controller */ #if defined(BSP_USING_HSUSBH) -#define ENABLE_EHCI /* Enable EHCI host controller */ + #define ENABLE_EHCI /* Enable EHCI host controller */ #endif #define EHCI_PORT_CNT 1 /* Number of EHCI roothub ports */ #define OHCI_PORT_CNT 2 /* Number of OHCI roothub ports */ #define OHCI_PER_PORT_POWER /* OHCI root hub per port powered */ -#define OHCI_ISO_DELAY 4 /* preserved number frames while scheduling +#define OHCI_ISO_DELAY 4 /* preserved number frames while scheduling OHCI isochronous transfer */ -#define EHCI_ISO_DELAY 2 /* preserved number of frames while +#define EHCI_ISO_DELAY 2 /* preserved number of frames while scheduling EHCI isochronous transfer */ -#define EHCI_ISO_RCLM_RANGE 32 /* When inspecting activated iTD/siTD, +#define EHCI_ISO_RCLM_RANGE 32 /* When inspecting activated iTD/siTD, unconditionally reclaim iTD/isTD scheduled in just elapsed EHCI_ISO_RCLM_RANGE ms. */ -#define MAX_DESC_BUFF_SIZE 512 /* To hold the configuration descriptor, USB +#define MAX_DESC_BUFF_SIZE 512 /* To hold the configuration descriptor, USB core will allocate a buffer with this size - for each connected device. USB core does + for each connected device. USB core does not release it until device disconnected. */ /*----------------------------------------------------------------------------------------*/ @@ -75,7 +75,7 @@ /* Re-defined staff for various compiler */ /*----------------------------------------------------------------------------------------*/ #ifdef __ICCARM__ -#define __inline inline + #define __inline inline #endif @@ -88,21 +88,21 @@ //#define DUMP_DESCRIPTOR /* dump descriptors */ #ifdef ENABLE_ERROR_MSG -#define USB_error rt_kprintf + #define USB_error rt_kprintf #else -#define USB_error(...) + #define USB_error(...) #endif #ifdef ENABLE_DEBUG_MSG -#define USB_debug rt_kprintf -#ifdef ENABLE_VERBOSE_DEBUG -#define USB_vdebug rt_kprintf + #define USB_debug rt_kprintf + #ifdef ENABLE_VERBOSE_DEBUG + #define USB_vdebug rt_kprintf + #else + #define USB_vdebug(...) + #endif #else -#define USB_vdebug(...) -#endif -#else -#define USB_debug(...) -#define USB_vdebug(...) + #define USB_debug(...) + #define USB_vdebug(...) #endif diff --git a/bsp/nuvoton/libraries/m480/USBHostLib/inc/usbh_lib.h b/bsp/nuvoton/libraries/m480/USBHostLib/inc/usbh_lib.h index 01d00171ee..a4b86c9df6 100644 --- a/bsp/nuvoton/libraries/m480/USBHostLib/inc/usbh_lib.h +++ b/bsp/nuvoton/libraries/m480/USBHostLib/inc/usbh_lib.h @@ -51,7 +51,7 @@ extern "C" #define USBH_ERR_DISCONNECTED -259 /*!< USB device was disconnected */ #define USBH_ERR_TRANSACTION -271 /*!< USB transaction timeout, CRC, Bad PID, etc. */ -#define USBH_ERR_BABBLE_DETECTED -272 /*!< A babble is detected during the transaction */ +#define USBH_ERR_BABBLE_DETECTED -272 /*!< A 'babble' is detected during the transaction */ #define USBH_ERR_DATA_BUFF -274 /*!< Data buffer overrun or underrun */ #define USBH_ERR_CC_NO_ERR -280 /*!< OHCI CC code - no error */ @@ -145,7 +145,7 @@ extern int usbh_polling_root_hubs(void); extern void usbh_install_conn_callback(CONN_FUNC *conn_func, CONN_FUNC *disconn_func); extern void usbh_suspend(void); extern void usbh_resume(void); -extern struct udev_t * usbh_find_device(char *hub_id, int port); +extern struct udev_t *usbh_find_device(char *hub_id, int port); /** * @brief A function return current tick count. diff --git a/bsp/nuvoton/libraries/m480/USBHostLib/src/ehci.c b/bsp/nuvoton/libraries/m480/USBHostLib/src/ehci.c index 9138c237a4..c373ef32e9 100644 --- a/bsp/nuvoton/libraries/m480/USBHostLib/src/ehci.c +++ b/bsp/nuvoton/libraries/m480/USBHostLib/src/ehci.c @@ -29,13 +29,13 @@ extern int ehci_iso_xfer(UTR_T *utr); /* EHCI isochronous transfer functio extern int ehci_quit_iso_xfer(UTR_T *utr, EP_INFO_T *ep); #ifdef __ICCARM__ -#pragma data_alignment=4096 -uint32_t _PFList[FL_SIZE]; /* Periodic frame list (IAR) */ + #pragma data_alignment=4096 + uint32_t _PFList[FL_SIZE]; /* Periodic frame list (IAR) */ #else -uint32_t _PFList[FL_SIZE] __attribute__((aligned(4096))); /* Periodic frame list */ + uint32_t _PFList[FL_SIZE] __attribute__((aligned(4096))); /* Periodic frame list */ #endif -QH_T * _Iqh[NUM_IQH]; +QH_T *_Iqh[NUM_IQH]; #ifdef ENABLE_ERROR_MSG @@ -65,7 +65,7 @@ void dump_ehci_qtd(qTD_T *qtd) USB_debug(" [qTD] - 0x%08x\n", (int)qtd); USB_debug(" 0x%08x (Next qtd Pointer)\n", qtd->Next_qTD); USB_debug(" 0x%08x (Alternate Next qtd Pointer)\n", qtd->Alt_Next_qTD); - USB_debug(" 0x%08x (qtd Token) PID: %s, Bytes: %d, IOC: %d\n", qtd->Token, (((qtd->Token>>8)&0x3)==0) ? "OUT" : ((((qtd->Token>>8)&0x3)==1) ? "IN" : "SETUP"), (qtd->Token>>16)&0x7FFF, (qtd->Token>>15)&0x1); + USB_debug(" 0x%08x (qtd Token) PID: %s, Bytes: %d, IOC: %d\n", qtd->Token, (((qtd->Token >> 8) & 0x3) == 0) ? "OUT" : ((((qtd->Token >> 8) & 0x3) == 1) ? "IN" : "SETUP"), (qtd->Token >> 16) & 0x7FFF, (qtd->Token >> 15) & 0x1); USB_debug(" 0x%08x (Buffer Pointer (page 0))\n", qtd->Bptr[0]); //USB_debug(" 0x%08x (Buffer Pointer (page 1))\n", qtd->Bptr[1]); //USB_debug(" 0x%08x (Buffer Pointer (page 2))\n", qtd->Bptr[2]); @@ -84,7 +84,7 @@ void dump_ehci_asynclist(void) { USB_debug("[QH] - 0x%08x\n", (int)qh); USB_debug(" 0x%08x (Queue Head Horizontal Link Pointer, Queue Head DWord 0)\n", qh->HLink); - USB_debug(" 0x%08x (Endpoint Characteristics) DevAddr: %d, EP: 0x%x, PktSz: %d, Speed: %s\n", qh->Chrst, qh->Chrst&0x7F, (qh->Chrst>>8)&0xF, (qh->Chrst>>16)&0x7FF, ((qh->Chrst>>12)&0x3 == 0) ? "Full" : (((qh->Chrst>>12)&0x3 == 1) ? "Low" : "High")); + USB_debug(" 0x%08x (Endpoint Characteristics) DevAddr: %d, EP: 0x%x, PktSz: %d, Speed: %s\n", qh->Chrst, qh->Chrst & 0x7F, (qh->Chrst >> 8) & 0xF, (qh->Chrst >> 16) & 0x7FF, ((qh->Chrst >> 12) & 0x3 == 0) ? "Full" : (((qh->Chrst >> 12) & 0x3 == 1) ? "Low" : "High")); USB_debug(" 0x%08x (Endpoint Capabilities: Queue Head DWord 2)\n", qh->Cap); USB_debug(" 0x%08x (Current qtd Pointer)\n", qh->Curr_qTD); USB_debug(" --- Overlay Area ---\n"); @@ -122,7 +122,7 @@ void dump_ehci_asynclist_simple(void) void dump_ehci_period_frame_list_simple(void) { - QH_T *qh = _Iqh[NUM_IQH-1]; + QH_T *qh = _Iqh[NUM_IQH - 1]; USB_debug(">>> EHCI period frame list simple <<<\n"); USB_debug("[FList] => "); @@ -165,7 +165,7 @@ static void init_periodic_frame_list() iso_ep_list = NULL; - for (i = NUM_IQH-1; i >= 0; i--) /* interval = i^2 */ + for (i = NUM_IQH - 1; i >= 0; i--) /* interval = i^2 */ { _Iqh[i] = alloc_ehci_QH(); @@ -204,19 +204,19 @@ static void init_periodic_frame_list() } } -static QH_T * get_int_tree_head_node(int interval) +static QH_T *get_int_tree_head_node(int interval) { int i; interval /= 8; /* each frame list entry for 8 micro-frame */ - for (i = 0; i < NUM_IQH-1; i++) + for (i = 0; i < NUM_IQH - 1; i++) { interval >>= 1; if (interval == 0) return _Iqh[i]; } - return _Iqh[NUM_IQH-1]; + return _Iqh[NUM_IQH - 1]; } static int make_int_s_mask(int bInterval) @@ -245,7 +245,7 @@ static int make_int_s_mask(int bInterval) static int ehci_init(void) { - int timeout = 250*1000; /* EHCI reset time-out 250 ms */ + int timeout = 250 * 1000; /* EHCI reset time-out 250 ms */ /*------------------------------------------------------------------------------------*/ /* Reset EHCI host controller */ @@ -283,11 +283,11 @@ static int ehci_init(void) /* Initialize periodic list */ /*------------------------------------------------------------------------------------*/ if (FL_SIZE == 256) - _ehci->UCMDR |= (0x2<UCMDR |= (0x2 << HSUSBH_UCMDR_FLSZ_Pos); else if (FL_SIZE == 512) - _ehci->UCMDR |= (0x1<UCMDR |= (0x1 << HSUSBH_UCMDR_FLSZ_Pos); else if (FL_SIZE == 1024) - _ehci->UCMDR |= (0x0<UCMDR |= (0x0 << HSUSBH_UCMDR_FLSZ_Pos); else return USBH_ERR_EHCI_INIT; /* Invalid FL_SIZE setting! */ @@ -371,7 +371,7 @@ static void move_qh_to_remove_list(QH_T *qh) /*------------------------------------------------------------------------------------*/ /* Search periodic frame list and remove qh if found in list. */ /*------------------------------------------------------------------------------------*/ - q = _Iqh[NUM_IQH-1]; + q = _Iqh[NUM_IQH - 1]; while (q->HLink != QH_HLNK_END) { if (QH_PTR(q->HLink) == qh) @@ -508,7 +508,7 @@ static int ehci_ctrl_xfer(UTR_T *utr) if (utr->data_len > 0) { - if (((uint32_t)utr->buff + utr->data_len) > (((uint32_t)utr->buff & ~0xFFF)+0x5000)) + if (((uint32_t)utr->buff + utr->data_len) > (((uint32_t)utr->buff & ~0xFFF) + 0x5000)) return USBH_ERR_BUFF_OVERRUN; } @@ -918,7 +918,7 @@ static int visit_qtd(qTD_T *qtd) static void scan_asynchronous_list() { QH_T *qh, *qh_tmp; - qTD_T *q_pre=NULL, *qtd, *qtd_tmp; + qTD_T *q_pre = NULL, *qtd, *qtd_tmp; UTR_T *utr; qh = QH_PTR(_H_qh->HLink); @@ -982,7 +982,7 @@ static void scan_periodic_frame_list() /*------------------------------------------------------------------------------------*/ /* Scan interrupt frame list */ /*------------------------------------------------------------------------------------*/ - qh = _Iqh[NUM_IQH-1]; + qh = _Iqh[NUM_IQH - 1]; while (qh != NULL) { qtd = qh->qtd_list; @@ -1095,7 +1095,7 @@ void iaad_remove_qh() /*------------------------------------------------------------------------------------*/ /* Free all qTD in done_list of each QH of periodic frame list */ /*------------------------------------------------------------------------------------*/ - qh = _Iqh[NUM_IQH-1]; + qh = _Iqh[NUM_IQH - 1]; while (qh != NULL) { while (qh->done_list) /* we can free the qTDs now */ @@ -1138,7 +1138,7 @@ void EHCI_IRQHandler(void) } } -static UDEV_T * ehci_find_device_by_port(int port) +static UDEV_T *ehci_find_device_by_port(int port) { UDEV_T *udev; @@ -1165,12 +1165,12 @@ static int ehci_rh_port_reset(int port) _ehci->UPSCR[port] = (_ehci->UPSCR[port] | HSUSBH_UPSCR_PRST_Msk) & ~HSUSBH_UPSCR_PE_Msk; t0 = usbh_get_ticks(); - while (usbh_get_ticks() - t0 < (reset_time)+1) ; /* wait at least 50 ms */ + while (usbh_get_ticks() - t0 < (reset_time) + 1) ; /* wait at least 50 ms */ _ehci->UPSCR[port] &= ~HSUSBH_UPSCR_PRST_Msk; t0 = usbh_get_ticks(); - while (usbh_get_ticks() - t0 < (reset_time)+1) + while (usbh_get_ticks() - t0 < (reset_time) + 1) { if (!(_ehci->UPSCR[port] & HSUSBH_UPSCR_CCS_Msk) || ((_ehci->UPSCR[port] & (HSUSBH_UPSCR_CCS_Msk | HSUSBH_UPSCR_PE_Msk)) == (HSUSBH_UPSCR_CCS_Msk | HSUSBH_UPSCR_PE_Msk))) @@ -1179,7 +1179,7 @@ static int ehci_rh_port_reset(int port) reset_time += PORT_RESET_RETRY_INC_MS; } - USB_debug("EHCI port %d - port reset failed!\n", port+1); + USB_debug("EHCI port %d - port reset failed!\n", port + 1); return USBH_ERR_PORT_RESET; port_reset_done: @@ -1222,7 +1222,7 @@ static int ehci_rh_polling(void) /* Port de-bounce */ /*--------------------------------------------------------------------------------*/ t0 = usbh_get_ticks(); - debounce_tick = usbh_tick_from_millisecond(HUB_DEBOUNCE_TIME); + debounce_tick = usbh_tick_from_millisecond(HUB_DEBOUNCE_TIME); connect_status = _ehci->UPSCR[0] & HSUSBH_UPSCR_CCS_Msk; while (usbh_get_ticks() - t0 < debounce_tick) { diff --git a/bsp/nuvoton/libraries/m480/USBHostLib/src/usb_core.c b/bsp/nuvoton/libraries/m480/USBHostLib/src/usb_core.c index eed2e5ae2b..475b768a7a 100644 --- a/bsp/nuvoton/libraries/m480/USBHostLib/src/usb_core.c +++ b/bsp/nuvoton/libraries/m480/USBHostLib/src/usb_core.c @@ -22,7 +22,7 @@ USBH_T *_ohci; HSUSBH_T *_ehci; -static UDEV_DRV_T * _drivers[MAX_UDEV_DRIVER]; +static UDEV_DRV_T *_drivers[MAX_UDEV_DRIVER]; static CONN_FUNC *g_conn_func, *g_disconn_func; /** @@ -130,7 +130,7 @@ int usbh_connect_device(UDEV_T *udev) if (g_conn_func) g_conn_func(udev, 0); - + return 0; } @@ -142,8 +142,8 @@ void usbh_disconnect_device(UDEV_T *udev) if (g_disconn_func) g_disconn_func(udev, 0); - -#if 1 //CHECK: Maybe create a new API to quit_xfer and free udev for application + +#if 1 //CHECK: Maybe create a new API to quit_xfer and free udev for application usbh_quit_xfer(udev, &(udev->ep0)); /* Quit control transfer if hw_pipe is not NULL. */ /* remove device from global device list */ @@ -172,7 +172,7 @@ int usbh_reset_port(UDEV_T *udev) if (udev->parent == NULL) { if (udev->hc_driver) - return udev->hc_driver->rthub_port_reset(udev->port_num-1); + return udev->hc_driver->rthub_port_reset(udev->port_num - 1); else return USBH_ERR_NOT_FOUND; } diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_epwm_capture.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_epwm_capture.c index 8dcfb92cd7..87c9ca2abf 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_epwm_capture.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_epwm_capture.c @@ -484,7 +484,7 @@ int nu_epwm_capture_device_init(void) } } -#endif //#if (BSP_USING_EPWM0_CAPTURE_CHMSK!=0) +#endif //#if (BSP_USING_EPWM0_CAPTURE_CHMSK!=0) #if (BSP_USING_EPWM1_CAPTURE_CHMSK!=0) for (int i = 0; i < EPWM_CHANNEL_NUM; i++) { diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_cap.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_cap.c index 69bea7c7a4..0fe3d87424 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_cap.c +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_cap.c @@ -267,7 +267,7 @@ void CAP_Close(void) { // 1. Disable IP's interrupt sysDisableInterrupt(CAP_IRQn); - // 2. Disable IPs clock + // 2. Disable IP's clock outp32(REG_CLK_HCLKEN, inp32(REG_CLK_HCLKEN) & ~(0x1 << 25)); CAP_Reset(); outp32(REG_CLK_HCLKEN, inp32(REG_CLK_HCLKEN) & ~(0x1 << 26)); diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usbh_lib.h b/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usbh_lib.h index ecf336e474..29b4868f9d 100644 --- a/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usbh_lib.h +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/inc/usbh_lib.h @@ -53,7 +53,7 @@ extern "C" #define USBH_ERR_DISCONNECTED -259 /*!< USB device was disconnected */ #define USBH_ERR_TRANSACTION -271 /*!< USB transaction timeout, CRC, Bad PID, etc. */ -#define USBH_ERR_BABBLE_DETECTED -272 /*!< A babble is detected during the transaction */ +#define USBH_ERR_BABBLE_DETECTED -272 /*!< A 'babble' is detected during the transaction */ #define USBH_ERR_DATA_BUFF -274 /*!< Data buffer overrun or underrun */ #define USBH_ERR_CC_NO_ERR -280 /*!< OHCI CC code - no error */ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pwm.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pwm.h index 4283ee32eb..b1431a1856 100644 --- a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pwm.h +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_pwm.h @@ -46,7 +46,7 @@ extern "C" #define PWM1_TIMER3 7 ///< PWM1 channel 3 //ioctl command -#define START_PWMTIMER 0 ///< Start PWM ioctl command +#define START_PWMTIMER 0 ///< Start PWM ioctl command #define STOP_PWMTIMER 1 ///< Stop PWM ioctl command #define SET_CSR 2 ///< Set CSR ioctl command #define SET_CP 3 ///< Set CP ioctl command diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_wwdt.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_wwdt.h index 0f0dd66b9a..65084471cb 100644 --- a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_wwdt.h +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_wwdt.h @@ -25,24 +25,24 @@ extern "C" /** @addtogroup WWDT_EXPORTED_CONSTANTS WWDT Exported Constants @{ */ -#define WWDT_PRESCALER_1 (0UL << 8) ///< WWDT setting prescaler to 1 \hideinitializer -#define WWDT_PRESCALER_2 (1UL << 8) ///< WWDT setting prescaler to 2 \hideinitializer -#define WWDT_PRESCALER_4 (2UL << 8) ///< WWDT setting prescaler to 4 \hideinitializer -#define WWDT_PRESCALER_8 (3UL << 8) ///< WWDT setting prescaler to 8 \hideinitializer -#define WWDT_PRESCALER_16 (4UL << 8) ///< WWDT setting prescaler to 16 \hideinitializer -#define WWDT_PRESCALER_32 (5UL << 8) ///< WWDT setting prescaler to 32 \hideinitializer -#define WWDT_PRESCALER_64 (6UL << 8) ///< WWDT setting prescaler to 64 \hideinitializer -#define WWDT_PRESCALER_128 (7UL << 8) ///< WWDT setting prescaler to 128 \hideinitializer -#define WWDT_PRESCALER_192 (8UL << 8) ///< WWDT setting prescaler to 192 \hideinitializer -#define WWDT_PRESCALER_256 (9UL << 8) ///< WWDT setting prescaler to 256 \hideinitializer -#define WWDT_PRESCALER_384 (0xAUL << 8) ///< WWDT setting prescaler to 384 \hideinitializer -#define WWDT_PRESCALER_512 (0xBUL << 8) ///< WWDT setting prescaler to 512 \hideinitializer -#define WWDT_PRESCALER_768 (0xCUL << 8) ///< WWDT setting prescaler to 768 \hideinitializer -#define WWDT_PRESCALER_1024 (0xDUL << 8) ///< WWDT setting prescaler to 1024 \hideinitializer -#define WWDT_PRESCALER_1536 (0xEUL << 8) ///< WWDT setting prescaler to 1536 \hideinitializer -#define WWDT_PRESCALER_2048 (0xFUL << 8) ///< WWDT setting prescaler to 2048 \hideinitializer +#define WWDT_PRESCALER_1 (0UL << 8) ///< WWDT setting prescaler to 1 \hideinitializer +#define WWDT_PRESCALER_2 (1UL << 8) ///< WWDT setting prescaler to 2 \hideinitializer +#define WWDT_PRESCALER_4 (2UL << 8) ///< WWDT setting prescaler to 4 \hideinitializer +#define WWDT_PRESCALER_8 (3UL << 8) ///< WWDT setting prescaler to 8 \hideinitializer +#define WWDT_PRESCALER_16 (4UL << 8) ///< WWDT setting prescaler to 16 \hideinitializer +#define WWDT_PRESCALER_32 (5UL << 8) ///< WWDT setting prescaler to 32 \hideinitializer +#define WWDT_PRESCALER_64 (6UL << 8) ///< WWDT setting prescaler to 64 \hideinitializer +#define WWDT_PRESCALER_128 (7UL << 8) ///< WWDT setting prescaler to 128 \hideinitializer +#define WWDT_PRESCALER_192 (8UL << 8) ///< WWDT setting prescaler to 192 \hideinitializer +#define WWDT_PRESCALER_256 (9UL << 8) ///< WWDT setting prescaler to 256 \hideinitializer +#define WWDT_PRESCALER_384 (0xAUL << 8) ///< WWDT setting prescaler to 384 \hideinitializer +#define WWDT_PRESCALER_512 (0xBUL << 8) ///< WWDT setting prescaler to 512 \hideinitializer +#define WWDT_PRESCALER_768 (0xCUL << 8) ///< WWDT setting prescaler to 768 \hideinitializer +#define WWDT_PRESCALER_1024 (0xDUL << 8) ///< WWDT setting prescaler to 1024 \hideinitializer +#define WWDT_PRESCALER_1536 (0xEUL << 8) ///< WWDT setting prescaler to 1536 \hideinitializer +#define WWDT_PRESCALER_2048 (0xFUL << 8) ///< WWDT setting prescaler to 2048 \hideinitializer -#define WWDT_RELOAD_WORD (0x00005AA5) ///< Fill this value to RLD register to reload WWDT counter \hideinitializer +#define WWDT_RELOAD_WORD (0x00005AA5) ///< Fill this value to RLD register to reload WWDT counter \hideinitializer /*@}*/ /* end of group WWDT_EXPORTED_CONSTANTS */ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c index b9564346f8..b74f774bd8 100644 --- a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_crypto.c @@ -1372,7 +1372,7 @@ int32_t ECC_GenerateSignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *messag Reg2Hex(pCurve->Echar, temp_result1, R); /* - * 4. Compute s = k ? 1 (e + d r)(mod n). If s = 0, go to step 2 + * 4. Compute s = k ? 1 * (e + d * r)(mod n). If s = 0, go to step 2 * (1) Write the curve order to N registers according * (2) Write 0x1 to Y1 registers * (3) Write the random integer k to X1 registers according @@ -1602,7 +1602,7 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, #endif /* - * 4. Compute u1 = e w (mod n) and u2 = r w (mod n) + * 4. Compute u1 = e * w (mod n) and u2 = r * w (mod n) * (1) Write the curve order and curve length to N ,M registers * (2) Write e, w to X1, Y1 registers * (3) Set ECCOP(CRPT_ECC_CTL[10:9]) to 01 @@ -1684,7 +1684,7 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, #endif /* - * 5. Compute X (x1, y1) = u1 * G + u2 * Q + * 5. Compute X' (x1' y1') = u1 * G + u2 * Q * (1) Write the curve parameter A, B, N, and curve length M to corresponding registers * (2) Write the point G(x, y) to X1, Y1 registers * (3) Write u1 to K registers @@ -1703,17 +1703,17 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, * (16) Set ECCOP(CRPT_ECC_CTL[10:9]) to 10 * (17) Set START(CRPT_ECC_CTL[0]) to 1 * (18) Wait for BUSY(CRPT_ECC_STS[0]) be cleared - * (19) Read X1, Y1 registers to get X(x1, y1) + * (19) Read X1, Y1 registers to get X('x1', y1') * (20) Write the curve order and curve length to N ,M registers - * (21) Write x1 to X1 registers + * (21) Write x1' to X1 registers * (22) Write 0x0 to Y1 registers * (23) Set ECCOP(CRPT_ECC_CTL[10:9]) to 01 * (24) Set MOPOP(CRPT_ECC_CTL[12:11]) to 10 * (25) Set START(CRPT_ECC_CTL[0]) to 1 * (26) Wait for BUSY(CRPT_ECC_STS[0]) be cleared - * (27) Read X1 registers to get x1 (mod n) + * (27) Read X1 registers to get x1' (mod n) * - * 6. The signature is valid if x1 = r, otherwise it is invalid + * 6. The signature is valid if x1' = r, otherwise it is invalid */ /* @@ -1797,7 +1797,7 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, run_ecc_codec(crpt, ECCOP_POINT_ADD); - /* (19) Read X1, Y1 registers to get X(x1, y1) */ + /* (19) Read X1, Y1 registers to get X'(x1' y1') */ for (i = 0; i < 18; i++) { temp_x[i] = crpt->ECC_X1[i]; @@ -1819,7 +1819,7 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, Hex2Reg(pCurve->Eorder, crpt->ECC_N); /* - * (21) Write x1 to X1 registers + * (21) Write x1' to X1 registers * (22) Write 0x0 to Y1 registers */ for (i = 0; i < 18; i++) @@ -1837,11 +1837,11 @@ int32_t ECC_VerifySignature(CRPT_T *crpt, E_ECC_CURVE ecc_curve, char *message, run_ecc_codec(crpt, ECCOP_MODULE | MODOP_ADD); - /* (27) Read X1 registers to get x1 (mod n) */ + /* (27) Read X1 registers to get x1' (mod n) */ Reg2Hex(pCurve->Echar, crpt->ECC_X1, temp_hex_str); CRPT_DBGMSG("5-(27) x1' (mod n) = %s\n", temp_hex_str); - /* 6. The signature is valid if x1 = r, otherwise it is invalid */ + /* 6. The signature is valid if x1' = r, otherwise it is invalid */ /* Compare with test pattern to check if r is correct or not */ if (ecc_strcmp(temp_hex_str, R) != 0) diff --git a/bsp/nuvoton/libraries/nuc980/UsbHostLib/inc/usbh_lib.h b/bsp/nuvoton/libraries/nuc980/UsbHostLib/inc/usbh_lib.h index fd14a96cec..f7a88d6e94 100644 --- a/bsp/nuvoton/libraries/nuc980/UsbHostLib/inc/usbh_lib.h +++ b/bsp/nuvoton/libraries/nuc980/UsbHostLib/inc/usbh_lib.h @@ -53,7 +53,7 @@ extern "C" #define USBH_ERR_DISCONNECTED -259 /*!< USB device was disconnected */ #define USBH_ERR_TRANSACTION -271 /*!< USB transaction timeout, CRC, Bad PID, etc. */ -#define USBH_ERR_BABBLE_DETECTED -272 /*!< A babble is detected during the transaction */ +#define USBH_ERR_BABBLE_DETECTED -272 /*!< A 'babble' is detected during the transaction */ #define USBH_ERR_DATA_BUFF -274 /*!< Data buffer overrun or underrun */ #define USBH_ERR_CC_NO_ERR -280 /*!< OHCI CC code - no error */ diff --git a/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_clkcfg.h b/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_clkcfg.h index 757323f65d..c4ffd553e3 100644 --- a/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_clkcfg.h +++ b/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_clkcfg.h @@ -1,7 +1,7 @@ /**************************************************************************** * @file nutool_clkcfg.h * @version V1.05 - * @Date 2020/11/11-11:43:32 + * @Date 2020/11/11-11:43:32 * @brief NuMicro generated code file * * SPDX-License-Identifier: Apache-2.0 diff --git a/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_modclkcfg.c b/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_modclkcfg.c index ea2c7a2f3a..b0bf9c80e4 100644 --- a/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_modclkcfg.c +++ b/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_modclkcfg.c @@ -1,7 +1,7 @@ /**************************************************************************** * @file nutool_modclkcfg.c * @version V1.05 - * @Date 2020/11/11-11:43:32 + * @Date 2020/11/11-11:43:32 * @brief NuMicro generated code file * * SPDX-License-Identifier: Apache-2.0 @@ -1160,14 +1160,14 @@ void nutool_modclkcfg_init_base(void) { /* LXT source from external LXT */ CLK_EnableModuleClock(RTC_MODULE); - RTC->LXTCTL &= ~(RTC_LXTCTL_LIRC32KEN_Msk|RTC_LXTCTL_C32KSEL_Msk); + RTC->LXTCTL &= ~(RTC_LXTCTL_LIRC32KEN_Msk | RTC_LXTCTL_C32KSEL_Msk); CLK_DisableModuleClock(RTC_MODULE); /* Enable clock source */ - CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk|CLK_PWRCTL_LXTEN_Msk|CLK_PWRCTL_HXTEN_Msk|CLK_PWRCTL_HIRC48EN_Msk|CLK_PWRCTL_MIRCEN_Msk); + CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk | CLK_PWRCTL_LXTEN_Msk | CLK_PWRCTL_HXTEN_Msk | CLK_PWRCTL_HIRC48EN_Msk | CLK_PWRCTL_MIRCEN_Msk); /* Waiting for clock source ready */ - CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk|CLK_STATUS_LXTSTB_Msk|CLK_STATUS_HXTSTB_Msk|CLK_STATUS_HIRC48STB_Msk|CLK_STATUS_MIRCSTB_Msk); + CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk | CLK_STATUS_LXTSTB_Msk | CLK_STATUS_HXTSTB_Msk | CLK_STATUS_HIRC48STB_Msk | CLK_STATUS_MIRCSTB_Msk); /* Disable PLL first to avoid unstable when setting PLL */ CLK_DisablePLL(); diff --git a/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_modclkcfg.h b/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_modclkcfg.h index 704cd6adc1..b374392a06 100644 --- a/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_modclkcfg.h +++ b/bsp/nuvoton/numaker-m2354/board/NuClockConfig/nutool_modclkcfg.h @@ -1,7 +1,7 @@ /**************************************************************************** * @file nutool_modclkcfg.h * @version V1.05 - * @Date 2020/11/11-11:43:32 + * @Date 2020/11/11-11:43:32 * @brief NuMicro generated code file * * SPDX-License-Identifier: Apache-2.0 diff --git a/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.c b/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.c index 55d8c8c99c..f64be93443 100644 --- a/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.c +++ b/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.c @@ -1,7 +1,7 @@ /**************************************************************************** * @file nutool_pincfg.c * @version V1.21 - * @Date 2020/11/11-12:06:36 + * @Date 2020/11/11-12:06:36 * @brief NuMicro generated code file * * Copyright (C) 2013-2020 Nuvoton Technology Corp. All rights reserved. @@ -318,44 +318,44 @@ void pincfg_init_slcd(void) SEG 33~36 : PH.7, PH.6, PH.5, PH.4 SEG 37~39 : PG.4, PG.3, PG.2 */ - + /* COM 0~5 */ - SYS->GPC_MFPL = (SYS->GPC_MFPL & - ~(SYS_GPC_MFPL_PC0MFP_Msk | SYS_GPC_MFPL_PC1MFP_Msk | SYS_GPC_MFPL_PC2MFP_Msk | SYS_GPC_MFPL_PC3MFP_Msk | - SYS_GPC_MFPL_PC4MFP_Msk | SYS_GPC_MFPL_PC5MFP_Msk)) | + SYS->GPC_MFPL = (SYS->GPC_MFPL & + ~(SYS_GPC_MFPL_PC0MFP_Msk | SYS_GPC_MFPL_PC1MFP_Msk | SYS_GPC_MFPL_PC2MFP_Msk | SYS_GPC_MFPL_PC3MFP_Msk | + SYS_GPC_MFPL_PC4MFP_Msk | SYS_GPC_MFPL_PC5MFP_Msk)) | (LCD_COM0_PC0 | LCD_COM1_PC1 | LCD_COM2_PC2 | LCD_COM3_PC3 | LCD_COM4_PC4 | LCD_COM5_PC5); /* COM 6~7 */ SYS->GPD_MFPH = (SYS->GPD_MFPH & ~(SYS_GPD_MFPH_PD8MFP_Msk | SYS_GPD_MFPH_PD9MFP_Msk)) | (LCD_COM6_PD8 | LCD_COM7_PD9); - + /* SEG 0 */ SYS->GPD_MFPH = (SYS->GPD_MFPH & ~SYS_GPD_MFPH_PD14MFP_Msk) | LCD_SEG0_PD14; /* SEG 1~4 */ SYS->GPH_MFPH = (SYS->GPH_MFPH & ~(SYS_GPH_MFPH_PH11MFP_Msk | SYS_GPH_MFPH_PH10MFP_Msk | SYS_GPH_MFPH_PH9MFP_Msk | SYS_GPH_MFPH_PH8MFP_Msk)) | (LCD_SEG1_PH11 | LCD_SEG2_PH10 | LCD_SEG3_PH9 | LCD_SEG4_PH8); /* SEG 5~12 */ - SYS->GPE_MFPL = (SYS->GPE_MFPL & - ~(SYS_GPE_MFPL_PE0MFP_Msk | SYS_GPE_MFPL_PE1MFP_Msk | SYS_GPE_MFPL_PE2MFP_Msk | SYS_GPE_MFPL_PE3MFP_Msk | - SYS_GPE_MFPL_PE4MFP_Msk | SYS_GPE_MFPL_PE5MFP_Msk | SYS_GPE_MFPL_PE6MFP_Msk | SYS_GPE_MFPL_PE7MFP_Msk)) | + SYS->GPE_MFPL = (SYS->GPE_MFPL & + ~(SYS_GPE_MFPL_PE0MFP_Msk | SYS_GPE_MFPL_PE1MFP_Msk | SYS_GPE_MFPL_PE2MFP_Msk | SYS_GPE_MFPL_PE3MFP_Msk | + SYS_GPE_MFPL_PE4MFP_Msk | SYS_GPE_MFPL_PE5MFP_Msk | SYS_GPE_MFPL_PE6MFP_Msk | SYS_GPE_MFPL_PE7MFP_Msk)) | (LCD_SEG5_PE0 | LCD_SEG6_PE1 | LCD_SEG7_PE2 | LCD_SEG8_PE3 | LCD_SEG9_PE4 | LCD_SEG10_PE5 | LCD_SEG11_PE6 | LCD_SEG12_PE7); /* SEG 13~14 */ SYS->GPD_MFPL = (SYS->GPD_MFPL & ~(SYS_GPD_MFPL_PD6MFP_Msk | SYS_GPD_MFPL_PD7MFP_Msk)) | (LCD_SEG13_PD6 | LCD_SEG14_PD7); /* SEG 15~21 */ - SYS->GPG_MFPH = (SYS->GPG_MFPH & - ~(SYS_GPG_MFPH_PG15MFP_Msk | SYS_GPG_MFPH_PG14MFP_Msk | SYS_GPG_MFPH_PG13MFP_Msk | SYS_GPG_MFPH_PG12MFP_Msk | - SYS_GPG_MFPH_PG11MFP_Msk | SYS_GPG_MFPH_PG10MFP_Msk | SYS_GPG_MFPH_PG9MFP_Msk)) | + SYS->GPG_MFPH = (SYS->GPG_MFPH & + ~(SYS_GPG_MFPH_PG15MFP_Msk | SYS_GPG_MFPH_PG14MFP_Msk | SYS_GPG_MFPH_PG13MFP_Msk | SYS_GPG_MFPH_PG12MFP_Msk | + SYS_GPG_MFPH_PG11MFP_Msk | SYS_GPG_MFPH_PG10MFP_Msk | SYS_GPG_MFPH_PG9MFP_Msk)) | (LCD_SEG15_PG15 | LCD_SEG16_PG14 | LCD_SEG17_PG13 | LCD_SEG18_PG12 | LCD_SEG19_PG11 | LCD_SEG20_PG10 | LCD_SEG21_PG9); /* SEG 22~23 */ SYS->GPE_MFPH = (SYS->GPE_MFPH & ~(SYS_GPE_MFPH_PE15MFP_Msk | SYS_GPE_MFPH_PE14MFP_Msk)) | (LCD_SEG22_PE15 | LCD_SEG23_PE14); /* SEG 24~29 */ - SYS->GPA_MFPL = (SYS->GPA_MFPL & - ~(SYS_GPA_MFPL_PA0MFP_Msk | SYS_GPA_MFPL_PA1MFP_Msk | SYS_GPA_MFPL_PA2MFP_Msk | SYS_GPA_MFPL_PA3MFP_Msk | - SYS_GPA_MFPL_PA4MFP_Msk | SYS_GPA_MFPL_PA5MFP_Msk)) | - (LCD_SEG24_PA0 | LCD_SEG25_PA1 | LCD_SEG26_PA2 | LCD_SEG27_PA3 | LCD_SEG28_PA4 |LCD_SEG29_PA5); + SYS->GPA_MFPL = (SYS->GPA_MFPL & + ~(SYS_GPA_MFPL_PA0MFP_Msk | SYS_GPA_MFPL_PA1MFP_Msk | SYS_GPA_MFPL_PA2MFP_Msk | SYS_GPA_MFPL_PA3MFP_Msk | + SYS_GPA_MFPL_PA4MFP_Msk | SYS_GPA_MFPL_PA5MFP_Msk)) | + (LCD_SEG24_PA0 | LCD_SEG25_PA1 | LCD_SEG26_PA2 | LCD_SEG27_PA3 | LCD_SEG28_PA4 | LCD_SEG29_PA5); /* SEG 30~32 */ - SYS->GPE_MFPH = (SYS->GPE_MFPH & ~(SYS_GPE_MFPH_PE10MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE8MFP_Msk)) | + SYS->GPE_MFPH = (SYS->GPE_MFPH & ~(SYS_GPE_MFPH_PE10MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE8MFP_Msk)) | (LCD_SEG30_PE10 | LCD_SEG31_PE9 | LCD_SEG32_PE8); /* SEG 33~36 */ SYS->GPH_MFPL = (SYS->GPH_MFPL & ~(SYS_GPH_MFPL_PH7MFP_Msk | SYS_GPH_MFPL_PH6MFP_Msk | SYS_GPH_MFPL_PH5MFP_Msk | SYS_GPH_MFPL_PH4MFP_Msk)) | diff --git a/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.h b/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.h index c3222715fc..5c5125bdbb 100644 --- a/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.h +++ b/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.h @@ -1,7 +1,7 @@ /**************************************************************************** * @file nutool_pincfg.h * @version V1.21 - * @Date 2020/11/11-12:06:36 + * @Date 2020/11/11-12:06:36 * @brief NuMicro generated code file * * Copyright (C) 2013-2020 Nuvoton Technology Corp. All rights reserved. diff --git a/bsp/nuvoton/numaker-pfm-m487/board/NuPinConfig/nutool_pincfg.c b/bsp/nuvoton/numaker-pfm-m487/board/NuPinConfig/nutool_pincfg.c index 5f9cd205b8..2675139697 100644 --- a/bsp/nuvoton/numaker-pfm-m487/board/NuPinConfig/nutool_pincfg.c +++ b/bsp/nuvoton/numaker-pfm-m487/board/NuPinConfig/nutool_pincfg.c @@ -1,7 +1,7 @@ /**************************************************************************** * @file nutool_pincfg.c * @version V1.20 - * @Date 2020/05/27-17:17:14 + * @Date 2020/05/27-17:17:14 * @brief NuMicro generated code file * * SPDX-License-Identifier: Apache-2.0 diff --git a/bsp/nuvoton/numaker-pfm-m487/board/NuPinConfig/nutool_pincfg.h b/bsp/nuvoton/numaker-pfm-m487/board/NuPinConfig/nutool_pincfg.h index 3f24e8cd48..ab1531c1d8 100644 --- a/bsp/nuvoton/numaker-pfm-m487/board/NuPinConfig/nutool_pincfg.h +++ b/bsp/nuvoton/numaker-pfm-m487/board/NuPinConfig/nutool_pincfg.h @@ -1,7 +1,7 @@ /**************************************************************************** * @file nutool_pincfg.h * @version V1.20 - * @Date 2020/05/27-17:17:14 + * @Date 2020/05/27-17:17:14 * @brief NuMicro generated code file * * SPDX-License-Identifier: Apache-2.0 From 8da49ff98420f4da21a96e152a00429d92ecf068 Mon Sep 17 00:00:00 2001 From: ZHU Hao Date: Fri, 14 May 2021 11:59:30 +0800 Subject: [PATCH 066/255] Update startup.S --- .../libraries/hal_libraries/bmsis/source/startup.S | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S b/bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S index 175ea15797..8ea645316e 100644 --- a/bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S +++ b/bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S @@ -6,6 +6,7 @@ #include "ab32vg1.h" +.set _memcpy, 0x84044 .global _start .section .reset, "ax" _start: @@ -16,18 +17,18 @@ _start: la a0, __comm_vma la a1, __comm_lma la a2, __comm_size - call 0x84044 + call _memcpy //load ram1 la a0, __ram1_vma la a1, __ram1_lma la a2, __ram1_size - call 0x84044 + call _memcpy la a0, __irq_stack_start //Stack清成0x23 li a1, 0x23 la a2, __irq_stack_size - call 0x84040 + call rt_memset la ra, __irq_stack lui a5, 0x1 sw zero, -1920(a5) @@ -37,7 +38,7 @@ _start: la a0, __bss_start li a1, 0 la a2, __bss_size - call 0x84040 + call rt_memset call cache_init From 97b6f10a4507079b62713ea2023401432a1871cc Mon Sep 17 00:00:00 2001 From: Wang-Huachen Date: Fri, 14 May 2021 14:22:23 +0800 Subject: [PATCH 067/255] format files in zynqmp-r5-axu4ev bsp --- .../Zynq_HAL_Driver/emacps_v3_11/xemacps.c | 234 +-- .../Zynq_HAL_Driver/emacps_v3_11/xemacps.h | 78 +- .../emacps_v3_11/xemacps_bdring.c | 450 ++--- .../emacps_v3_11/xemacps_bdring.h | 38 +- .../emacps_v3_11/xemacps_control.c | 692 +++---- .../Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c | 10 +- .../Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c | 42 +- .../Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h | 82 +- .../emacps_v3_11/xemacps_intr.c | 128 +- .../emacps_v3_11/xemacps_sinit.c | 14 +- .../Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c | 490 ++--- .../Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h | 82 +- .../Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c | 8 +- .../Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c | 14 +- .../Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h | 24 +- .../gpiops_v3_7/xgpiops_intr.c | 590 +++--- .../gpiops_v3_7/xgpiops_selftest.c | 44 +- .../gpiops_v3_7/xgpiops_sinit.c | 24 +- .../drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c | 306 +-- .../drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h | 160 +- .../Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c | 1268 ++++++------ .../Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c | 40 +- .../Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c | 1726 ++++++++--------- .../Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h | 1276 ++++++------ .../Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c | 544 +++--- .../Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c | 20 +- .../drivers/Zynq_HAL_Driver/sleep.h | 10 +- .../xemacpsif/netif/xadapter.h | 32 +- .../xemacpsif/netif/xemacpsif.h | 52 +- .../Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h | 12 +- .../xemacpsif/netif/xtopology.h | 12 +- .../Zynq_HAL_Driver/xemacpsif/xadapter.c | 290 +-- .../xemacpsif/xemac_ieee_reg.h | 2 +- .../Zynq_HAL_Driver/xemacpsif/xemacpsif.c | 582 +++--- .../Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c | 778 ++++---- .../Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c | 226 +-- .../xemacpsif/xemacpsif_physpeed.c | 1214 ++++++------ .../Zynq_HAL_Driver/xemacpsif/xpqueue.c | 50 +- .../Zynq_HAL_Driver/xemacpsif/xtopology_g.c | 12 +- .../drivers/Zynq_HAL_Driver/xil_io.h | 60 +- .../drivers/Zynq_HAL_Driver/xil_types.h | 14 +- .../drivers/Zynq_HAL_Driver/xparameters.h | 18 +- .../drivers/Zynq_HAL_Driver/xparameters_ps.h | 276 +-- .../drivers/Zynq_HAL_Driver/xplatform_info.h | 14 +- .../drivers/Zynq_HAL_Driver/xstatus.h | 48 +- bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c | 6 +- bsp/zynqmp-r5-axu4ev/drivers/drv_timer.c | 4 +- bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h | 10 +- 48 files changed, 6053 insertions(+), 6053 deletions(-) diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c index fb4a6483e9..8142b7072b 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c @@ -81,27 +81,27 @@ LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr, UINTPTR EffectiveAddress) { /* Verify arguments */ - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(CfgPtr != NULL); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); /* Set device base address and ID */ - InstancePtr->Config.DeviceId = CfgPtr->DeviceId; - InstancePtr->Config.BaseAddress = EffectiveAddress; - InstancePtr->Config.IsCacheCoherent = CfgPtr->IsCacheCoherent; + InstancePtr->Config.DeviceId = CfgPtr->DeviceId; + InstancePtr->Config.BaseAddress = EffectiveAddress; + InstancePtr->Config.IsCacheCoherent = CfgPtr->IsCacheCoherent; #if defined (XCLOCKING) - InstancePtr->Config.RefClk = CfgPtr->RefClk; + InstancePtr->Config.RefClk = CfgPtr->RefClk; #endif /* Set callbacks to an initial stub routine */ - InstancePtr->SendHandler = ((XEmacPs_Handler)((void*)XEmacPs_StubHandler)); - InstancePtr->RecvHandler = ((XEmacPs_Handler)(void*)XEmacPs_StubHandler); - InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void*)XEmacPs_StubHandler); + InstancePtr->SendHandler = ((XEmacPs_Handler)((void*)XEmacPs_StubHandler)); + InstancePtr->RecvHandler = ((XEmacPs_Handler)(void*)XEmacPs_StubHandler); + InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void*)XEmacPs_StubHandler); /* Reset the hardware and set default options */ - InstancePtr->IsReady = XIL_COMPONENT_IS_READY; - XEmacPs_Reset(InstancePtr); + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + XEmacPs_Reset(InstancePtr); - return (LONG)(XST_SUCCESS); + return (LONG)(XST_SUCCESS); } @@ -134,15 +134,15 @@ LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr, ******************************************************************************/ void XEmacPs_Start(XEmacPs *InstancePtr) { - u32 Reg; + u32 Reg; /* Assert bad arguments and conditions */ - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); #if defined (XCLOCKING) - if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) { - Xil_ClockEnable(InstancePtr->Config.RefClk); + if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) { + Xil_ClockEnable(InstancePtr->Config.RefClk); } #endif @@ -150,39 +150,39 @@ void XEmacPs_Start(XEmacPs *InstancePtr) /* When starting the DMA channels, both transmit and receive sides * need an initialized BD list. */ - if (InstancePtr->Version == 2) { - Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0); - Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + if (InstancePtr->Version == 2) { + Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0); + Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_RXQBASE_OFFSET, InstancePtr->RxBdRing.BaseBdAddr); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_TXQBASE_OFFSET, InstancePtr->TxBdRing.BaseBdAddr); } /* clear any existed int status */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, XEMACPS_IXR_ALL_MASK); /* Enable transmitter if not already enabled */ - if ((InstancePtr->Options & (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION)!=0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - if ((!(Reg & XEMACPS_NWCTRL_TXEN_MASK))==TRUE) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + if ((InstancePtr->Options & (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION)!=0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + if ((!(Reg & XEMACPS_NWCTRL_TXEN_MASK))==TRUE) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, Reg | (u32)XEMACPS_NWCTRL_TXEN_MASK); } } /* Enable receiver if not already enabled */ - if ((InstancePtr->Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - if ((!(Reg & XEMACPS_NWCTRL_RXEN_MASK))==TRUE) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + if ((InstancePtr->Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + if ((!(Reg & XEMACPS_NWCTRL_RXEN_MASK))==TRUE) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, Reg | (u32)XEMACPS_NWCTRL_RXEN_MASK); } @@ -190,17 +190,17 @@ void XEmacPs_Start(XEmacPs *InstancePtr) /* Enable TX and RX interrupts */ XEmacPs_IntEnable(InstancePtr, (XEMACPS_IXR_TX_ERR_MASK | - XEMACPS_IXR_RX_ERR_MASK | (u32)XEMACPS_IXR_FRAMERX_MASK | + XEMACPS_IXR_RX_ERR_MASK | (u32)XEMACPS_IXR_FRAMERX_MASK | (u32)XEMACPS_IXR_TXCOMPL_MASK)); /* Enable TX Q1 Interrupts */ - if (InstancePtr->Version > 2) - XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK); + if (InstancePtr->Version > 2) + XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK); /* Mark as started */ - InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; - return; + return; } @@ -231,27 +231,27 @@ void XEmacPs_Start(XEmacPs *InstancePtr) ******************************************************************************/ void XEmacPs_Stop(XEmacPs *InstancePtr) { - u32 Reg; + u32 Reg; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); /* Disable all interrupts */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET, XEMACPS_IXR_ALL_MASK); /* Disable the receiver & transmitter */ - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); - Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); + Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, Reg); /* Mark as stopped */ - InstancePtr->IsStarted = 0U; + InstancePtr->IsStarted = 0U; #if defined (XCLOCKING) - Xil_ClockDisable(InstancePtr->Config.RefClk); + Xil_ClockDisable(InstancePtr->Config.RefClk); #endif } @@ -290,53 +290,53 @@ void XEmacPs_Stop(XEmacPs *InstancePtr) ******************************************************************************/ void XEmacPs_Reset(XEmacPs *InstancePtr) { - u32 Reg; - u8 i; - s8 EmacPs_zero_MAC[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + u32 Reg; + u8 i; + s8 EmacPs_zero_MAC[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); /* Stop the device and reset hardware */ - XEmacPs_Stop(InstancePtr); - InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS; + XEmacPs_Stop(InstancePtr); + InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS; - InstancePtr->Version = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, 0xFC); + InstancePtr->Version = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, 0xFC); - InstancePtr->Version = (InstancePtr->Version >> 16) & 0xFFF; + InstancePtr->Version = (InstancePtr->Version >> 16) & 0xFFF; - InstancePtr->MaxMtuSize = XEMACPS_MTU; - InstancePtr->MaxFrameSize = XEMACPS_MTU + XEMACPS_HDR_SIZE + - XEMACPS_TRL_SIZE; - InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + - XEMACPS_HDR_VLAN_SIZE; - InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK; + InstancePtr->MaxMtuSize = XEMACPS_MTU; + InstancePtr->MaxFrameSize = XEMACPS_MTU + XEMACPS_HDR_SIZE + + XEMACPS_TRL_SIZE; + InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + + XEMACPS_HDR_VLAN_SIZE; + InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK; /* Setup hardware with default values */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, (XEMACPS_NWCTRL_STATCLR_MASK | - XEMACPS_NWCTRL_MDEN_MASK) & + XEMACPS_NWCTRL_MDEN_MASK) & (u32)(~XEMACPS_NWCTRL_LOOPEN_MASK)); - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET); - Reg &= XEMACPS_NWCFG_MDCCLKDIV_MASK; + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + Reg &= XEMACPS_NWCFG_MDCCLKDIV_MASK; - Reg = Reg | (u32)XEMACPS_NWCFG_100_MASK | + Reg = Reg | (u32)XEMACPS_NWCFG_100_MASK | (u32)XEMACPS_NWCFG_FDEN_MASK | (u32)XEMACPS_NWCFG_UCASTHASHEN_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET, Reg); - if (InstancePtr->Version > 2) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, Reg); + if (InstancePtr->Version > 2) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET, (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET) | - XEMACPS_NWCFG_DWIDTH_64_MASK)); + XEMACPS_NWCFG_DWIDTH_64_MASK)); } - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) + (((((u32)XEMACPS_RX_BUF_SIZE % (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << @@ -346,8 +346,8 @@ void XEmacPs_Reset(XEmacPs *InstancePtr) (u32)XEMACPS_DMACR_TXSIZE_MASK); - if (InstancePtr->Version > 2) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, + if (InstancePtr->Version > 2) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET) | #if defined(__aarch64__) || defined(__arch64__) (u32)XEMACPS_DMACR_ADDR_WIDTH_64 | @@ -355,44 +355,44 @@ void XEmacPs_Reset(XEmacPs *InstancePtr) (u32)XEMACPS_DMACR_INCR16_AHB_BURST)); } - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_TXSR_OFFSET, XEMACPS_SR_ALL_MASK); - XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_SEND); - if (InstancePtr->Version > 2) - XEmacPs_SetQueuePtr(InstancePtr, 0, 0x01U, (u16)XEMACPS_SEND); - XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_RECV); + XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_SEND); + if (InstancePtr->Version > 2) + XEmacPs_SetQueuePtr(InstancePtr, 0, 0x01U, (u16)XEMACPS_SEND); + XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_RECV); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_RXSR_OFFSET, XEMACPS_SR_ALL_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET, XEMACPS_IXR_ALL_MASK); - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_ISR_OFFSET); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_ISR_OFFSET); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, Reg); - XEmacPs_ClearHash(InstancePtr); + XEmacPs_ClearHash(InstancePtr); - for (i = 1U; i < 5U; i++) { + for (i = 1U; i < 5U; i++) { (void)XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i); (void)XEmacPs_SetTypeIdCheck(InstancePtr, 0x00000000U, i); } /* clear all counters */ - for (i = 0U; i < (u8)((XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4U); + for (i = 0U; i < (u8)((XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4U); i++) { (void)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_OCTTXL_OFFSET + (u32)(((u32)i) * ((u32)4))); } /* Disable the receiver */ - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, Reg); /* Sync default options with hardware but leave receiver and @@ -418,17 +418,17 @@ void XEmacPs_Reset(XEmacPs *InstancePtr) ******************************************************************************/ void XEmacPs_StubHandler(void) { - Xil_AssertVoidAlways(); + Xil_AssertVoidAlways(); } /*****************************************************************************/ /** * This function sets the start address of the transmit/receive buffer queue. * -* @param InstancePtr is a pointer to the instance to be worked on. -* @param QPtr is the address of the Queue to be written -* @param QueueNum is the Buffer Queue Index -* @param Direction indicates Transmit/Receive +* @param InstancePtr is a pointer to the instance to be worked on. +* @param QPtr is the address of the Queue to be written +* @param QueueNum is the Buffer Queue Index +* @param Direction indicates Transmit/Receive * * @note * The buffer queue addresses has to be set before starting the transfer, so @@ -439,40 +439,40 @@ void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum, u16 Direction) { /* Assert bad arguments and conditions */ - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); /* If already started, then there is nothing to do */ if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { return; } - if (QueueNum == 0x00U) { - if (Direction == XEMACPS_SEND) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_TXQBASE_OFFSET, + if (QueueNum == 0x00U) { + if (Direction == XEMACPS_SEND) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXQBASE_OFFSET, (QPtr & ULONG64_LO_MASK)); } else { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_RXQBASE_OFFSET, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXQBASE_OFFSET, (QPtr & ULONG64_LO_MASK)); } } else { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_TXQ1BASE_OFFSET, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXQ1BASE_OFFSET, (QPtr & ULONG64_LO_MASK)); } #ifdef __aarch64__ - if (Direction == XEMACPS_SEND) { + if (Direction == XEMACPS_SEND) { /* Set the MSB of TX Queue start address */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_MSBBUF_TXQBASE_OFFSET, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_MSBBUF_TXQBASE_OFFSET, (u32)((QPtr & ULONG64_HI_MASK) >> 32U)); } else { /* Set the MSB of RX Queue start address */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_MSBBUF_RXQBASE_OFFSET, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_MSBBUF_RXQBASE_OFFSET, (u32)((QPtr & ULONG64_HI_MASK) >> 32U)); } #endif diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h index d3c5b6349f..cfb387a371 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h @@ -265,7 +265,7 @@ * removed. It is expected that all BDs are allocated in * from uncached area. * 1.06a asa 11/02/13 Changed the value for XEMACPS_RXBUF_LEN_MASK from 0x3fff - * to 0x1fff. This fixes the CR#744902. + * to 0x1fff. This fixes the CR#744902. * Made changes in example file xemacps_example.h to fix compilation * issues with iarcc compiler. * 2.0 adk 10/12/13 Updated as per the New Tcl API's @@ -412,8 +412,8 @@ extern "C" { /**< Enable the TX checksum offload * This option defaults to enabled (set) */ -#define XEMACPS_JUMBO_ENABLE_OPTION 0x00004000U -#define XEMACPS_SGMII_ENABLE_OPTION 0x00008000U +#define XEMACPS_JUMBO_ENABLE_OPTION 0x00004000U +#define XEMACPS_SGMII_ENABLE_OPTION 0x00008000U #define XEMACPS_DEFAULT_OPTIONS \ ((u32)XEMACPS_FLOW_CONTROL_OPTION | \ @@ -463,10 +463,10 @@ extern "C" { /* DMACR Bust length hash defines */ -#define XEMACPS_SINGLE_BURST 0x00000001 -#define XEMACPS_4BYTE_BURST 0x00000004 -#define XEMACPS_8BYTE_BURST 0x00000008 -#define XEMACPS_16BYTE_BURST 0x00000010 +#define XEMACPS_SINGLE_BURST 0x00000001 +#define XEMACPS_4BYTE_BURST 0x00000004 +#define XEMACPS_8BYTE_BURST 0x00000008 +#define XEMACPS_16BYTE_BURST 0x00000010 /**************************** Type Definitions ******************************/ @@ -507,12 +507,12 @@ typedef void (*XEmacPs_ErrHandler) (void *CallBackRef, u8 Direction, * This typedef contains configuration information for a device. */ typedef struct { - u16 DeviceId; /**< Unique ID of device */ - UINTPTR BaseAddress;/**< Physical base address of IPIF registers */ - u8 IsCacheCoherent; /**< Applicable only to A53 in EL1 mode; + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddress;/**< Physical base address of IPIF registers */ + u8 IsCacheCoherent; /**< Applicable only to A53 in EL1 mode; * describes whether Cache Coherent or not */ #if defined (XCLOCKING) - u32 RefClk; /**< Input clock */ + u32 RefClk; /**< Input clock */ #endif } XEmacPs_Config; @@ -523,26 +523,26 @@ typedef struct { * to a structure of this type is then passed to the driver API functions. */ typedef struct XEmacPs_Instance { - XEmacPs_Config Config; /* Hardware configuration */ - u32 IsStarted; /* Device is currently started */ - u32 IsReady; /* Device is initialized and ready */ - u32 Options; /* Current options word */ + XEmacPs_Config Config; /* Hardware configuration */ + u32 IsStarted; /* Device is currently started */ + u32 IsReady; /* Device is initialized and ready */ + u32 Options; /* Current options word */ - XEmacPs_BdRing TxBdRing; /* Transmit BD ring */ - XEmacPs_BdRing RxBdRing; /* Receive BD ring */ + XEmacPs_BdRing TxBdRing; /* Transmit BD ring */ + XEmacPs_BdRing RxBdRing; /* Receive BD ring */ - XEmacPs_Handler SendHandler; - XEmacPs_Handler RecvHandler; - void *SendRef; - void *RecvRef; + XEmacPs_Handler SendHandler; + XEmacPs_Handler RecvHandler; + void *SendRef; + void *RecvRef; - XEmacPs_ErrHandler ErrorHandler; - void *ErrorRef; - u32 Version; - u32 RxBufMask; - u32 MaxMtuSize; - u32 MaxFrameSize; - u32 MaxVlanFrameSize; + XEmacPs_ErrHandler ErrorHandler; + void *ErrorRef; + u32 Version; + u32 RxBufMask; + u32 MaxMtuSize; + u32 MaxFrameSize; + u32 MaxVlanFrameSize; } XEmacPs; @@ -598,8 +598,8 @@ typedef struct XEmacPs_Instance { * *****************************************************************************/ #define XEmacPs_IntEnable(InstancePtr, Mask) \ - XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ - XEMACPS_IER_OFFSET, \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_IER_OFFSET, \ ((Mask) & XEMACPS_IXR_ALL_MASK)); /****************************************************************************/ @@ -619,8 +619,8 @@ typedef struct XEmacPs_Instance { * *****************************************************************************/ #define XEmacPs_IntDisable(InstancePtr, Mask) \ - XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ - XEMACPS_IDR_OFFSET, \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_IDR_OFFSET, \ ((Mask) & XEMACPS_IXR_ALL_MASK)); /****************************************************************************/ @@ -640,8 +640,8 @@ typedef struct XEmacPs_Instance { * *****************************************************************************/ #define XEmacPs_IntQ1Enable(InstancePtr, Mask) \ - XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ - XEMACPS_INTQ1_IER_OFFSET, \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_INTQ1_IER_OFFSET, \ ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); /****************************************************************************/ @@ -661,8 +661,8 @@ typedef struct XEmacPs_Instance { * *****************************************************************************/ #define XEmacPs_IntQ1Disable(InstancePtr, Mask) \ - XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ - XEMACPS_INTQ1_IDR_OFFSET, \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_INTQ1_IDR_OFFSET, \ ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); /****************************************************************************/ @@ -750,7 +750,7 @@ typedef struct XEmacPs_Instance { * @note * * Signature: void XEmacPs_SetRXWatermark(XEmacPs *InstancePtr, u16 High, -* u16 Low) +* u16 Low) * *****************************************************************************/ #define XEmacPs_SetRXWatermark(InstancePtr, High, Low) \ @@ -797,7 +797,7 @@ XEmacPs_Config *XEmacPs_LookupConfig(u16 DeviceId); * DMA only and FIFO is not supported. This DMA does not support coalescing. */ LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType, - void *FuncPointer, void *CallBackRef); + void *FuncPointer, void *CallBackRef); void XEmacPs_IntrHandler(void *XEmacPsPtr); /* @@ -816,7 +816,7 @@ void XEmacPs_ClearHash(XEmacPs *InstancePtr); void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr); void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, - XEmacPs_MdcDiv Divisor); + XEmacPs_MdcDiv Divisor); void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed); u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr); LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c index 1225aca42d..dad6ac0c84 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c @@ -176,49 +176,49 @@ static void XEmacPs_BdSetTxWrap(UINTPTR BdPtr); LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr, UINTPTR VirtAddr, u32 Alignment, u32 BdCount) { - u32 i; - UINTPTR BdVirtAddr; - UINTPTR BdPhyAddr; - UINTPTR VirtAddrLoc = VirtAddr; + u32 i; + UINTPTR BdVirtAddr; + UINTPTR BdPhyAddr; + UINTPTR VirtAddrLoc = VirtAddr; /* In case there is a failure prior to creating list, make sure the * following attributes are 0 to prevent calls to other functions * from doing anything. */ - RingPtr->AllCnt = 0U; - RingPtr->FreeCnt = 0U; - RingPtr->HwCnt = 0U; - RingPtr->PreCnt = 0U; - RingPtr->PostCnt = 0U; + RingPtr->AllCnt = 0U; + RingPtr->FreeCnt = 0U; + RingPtr->HwCnt = 0U; + RingPtr->PreCnt = 0U; + RingPtr->PostCnt = 0U; /* Make sure Alignment parameter meets minimum requirements */ - if (Alignment < (u32)XEMACPS_DMABD_MINIMUM_ALIGNMENT) { - return (LONG)(XST_INVALID_PARAM); + if (Alignment < (u32)XEMACPS_DMABD_MINIMUM_ALIGNMENT) { + return (LONG)(XST_INVALID_PARAM); } /* Make sure Alignment is a power of 2 */ - if (((Alignment - 0x00000001U) & Alignment)!=0x00000000U) { - return (LONG)(XST_INVALID_PARAM); + if (((Alignment - 0x00000001U) & Alignment)!=0x00000000U) { + return (LONG)(XST_INVALID_PARAM); } /* Make sure PhysAddr and VirtAddr are on same Alignment */ - if (((PhysAddr % Alignment)!=(u32)0) || ((VirtAddrLoc % Alignment)!=(u32)0)) { - return (LONG)(XST_INVALID_PARAM); + if (((PhysAddr % Alignment)!=(u32)0) || ((VirtAddrLoc % Alignment)!=(u32)0)) { + return (LONG)(XST_INVALID_PARAM); } /* Is BdCount reasonable? */ - if (BdCount == 0x00000000U) { - return (LONG)(XST_INVALID_PARAM); + if (BdCount == 0x00000000U) { + return (LONG)(XST_INVALID_PARAM); } /* Figure out how many bytes will be between the start of adjacent BDs */ - RingPtr->Separation = ((u32)sizeof(XEmacPs_Bd)); + RingPtr->Separation = ((u32)sizeof(XEmacPs_Bd)); /* Must make sure the ring doesn't span address 0x00000000. If it does, * then the next/prev BD traversal macros will fail. */ - if (VirtAddrLoc > ((VirtAddrLoc + (RingPtr->Separation * BdCount)) - (u32)1)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + if (VirtAddrLoc > ((VirtAddrLoc + (RingPtr->Separation * BdCount)) - (u32)1)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); } /* Initial ring setup: @@ -227,30 +227,30 @@ LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr, */ (void)memset((void *) VirtAddrLoc, 0, (RingPtr->Separation * BdCount)); - BdVirtAddr = VirtAddrLoc; - BdPhyAddr = PhysAddr + RingPtr->Separation; - for (i = 1U; i < BdCount; i++) { - BdVirtAddr += RingPtr->Separation; - BdPhyAddr += RingPtr->Separation; + BdVirtAddr = VirtAddrLoc; + BdPhyAddr = PhysAddr + RingPtr->Separation; + for (i = 1U; i < BdCount; i++) { + BdVirtAddr += RingPtr->Separation; + BdPhyAddr += RingPtr->Separation; } /* Setup and initialize pointers and counters */ - RingPtr->RunState = (u32)(XST_DMA_SG_IS_STOPPED); - RingPtr->BaseBdAddr = VirtAddrLoc; - RingPtr->PhysBaseAddr = PhysAddr; - RingPtr->HighBdAddr = BdVirtAddr; - RingPtr->Length = + RingPtr->RunState = (u32)(XST_DMA_SG_IS_STOPPED); + RingPtr->BaseBdAddr = VirtAddrLoc; + RingPtr->PhysBaseAddr = PhysAddr; + RingPtr->HighBdAddr = BdVirtAddr; + RingPtr->Length = ((RingPtr->HighBdAddr - RingPtr->BaseBdAddr) + RingPtr->Separation); - RingPtr->AllCnt = (u32)BdCount; - RingPtr->FreeCnt = (u32)BdCount; - RingPtr->FreeHead = (XEmacPs_Bd *)(void *)VirtAddrLoc; - RingPtr->PreHead = (XEmacPs_Bd *)VirtAddrLoc; - RingPtr->HwHead = (XEmacPs_Bd *)VirtAddrLoc; - RingPtr->HwTail = (XEmacPs_Bd *)VirtAddrLoc; - RingPtr->PostHead = (XEmacPs_Bd *)VirtAddrLoc; - RingPtr->BdaRestart = (XEmacPs_Bd *)(void *)PhysAddr; + RingPtr->AllCnt = (u32)BdCount; + RingPtr->FreeCnt = (u32)BdCount; + RingPtr->FreeHead = (XEmacPs_Bd *)(void *)VirtAddrLoc; + RingPtr->PreHead = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->HwHead = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->HwTail = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->PostHead = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->BdaRestart = (XEmacPs_Bd *)(void *)PhysAddr; - return (LONG)(XST_SUCCESS); + return (LONG)(XST_SUCCESS); } @@ -281,47 +281,47 @@ LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr, LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr, u8 Direction) { - u32 i; - UINTPTR CurBd; + u32 i; + UINTPTR CurBd; /* Can't do this function if there isn't a ring */ - if (RingPtr->AllCnt == 0x00000000U) { - return (LONG)(XST_DMA_SG_NO_LIST); + if (RingPtr->AllCnt == 0x00000000U) { + return (LONG)(XST_DMA_SG_NO_LIST); } /* Can't do this function with the channel running */ - if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) { - return (LONG)(XST_DEVICE_IS_STARTED); + if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) { + return (LONG)(XST_DEVICE_IS_STARTED); } /* Can't do this function with some of the BDs in use */ - if (RingPtr->FreeCnt != RingPtr->AllCnt) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + if (RingPtr->FreeCnt != RingPtr->AllCnt) { + return (LONG)(XST_DMA_SG_LIST_ERROR); } - if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) { - return (LONG)(XST_INVALID_PARAM); + if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) { + return (LONG)(XST_INVALID_PARAM); } /* Starting from the top of the ring, save BD.Next, overwrite the entire * BD with the template, then restore BD.Next */ - CurBd = RingPtr->BaseBdAddr; - for (i = 0U; i < RingPtr->AllCnt; i++) { - memcpy((void *)CurBd, SrcBdPtr, sizeof(XEmacPs_Bd)); - CurBd += RingPtr->Separation; + CurBd = RingPtr->BaseBdAddr; + for (i = 0U; i < RingPtr->AllCnt; i++) { + memcpy((void *)CurBd, SrcBdPtr, sizeof(XEmacPs_Bd)); + CurBd += RingPtr->Separation; } - CurBd -= RingPtr->Separation; + CurBd -= RingPtr->Separation; - if (Direction == XEMACPS_RECV) { - XEmacPs_BdSetRxWrap(CurBd); + if (Direction == XEMACPS_RECV) { + XEmacPs_BdSetRxWrap(CurBd); } - else { - XEmacPs_BdSetTxWrap(CurBd); + else { + XEmacPs_BdSetTxWrap(CurBd); } - return (LONG)(XST_SUCCESS); + return (LONG)(XST_SUCCESS); } @@ -400,19 +400,19 @@ LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr, LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, XEmacPs_Bd ** BdSetPtr) { - LONG Status; + LONG Status; /* Enough free BDs available for the request? */ - if (RingPtr->FreeCnt < NumBd) { - Status = (LONG)(XST_FAILURE); + if (RingPtr->FreeCnt < NumBd) { + Status = (LONG)(XST_FAILURE); } else { /* Set the return argument and move FreeHead forward */ *BdSetPtr = RingPtr->FreeHead; - XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->FreeHead, NumBd); - RingPtr->FreeCnt -= NumBd; - RingPtr->PreCnt += NumBd; - Status = (LONG)(XST_SUCCESS); + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->FreeHead, NumBd); + RingPtr->FreeCnt -= NumBd; + RingPtr->PreCnt += NumBd; + Status = (LONG)(XST_SUCCESS); } - return Status; + return Status; } /*****************************************************************************/ @@ -480,22 +480,22 @@ LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, XEmacPs_Bd * BdSetPtr) { - LONG Status; + LONG Status; (void) BdSetPtr; - Xil_AssertNonvoid(RingPtr != NULL); - Xil_AssertNonvoid(BdSetPtr != NULL); + Xil_AssertNonvoid(RingPtr != NULL); + Xil_AssertNonvoid(BdSetPtr != NULL); /* Enough BDs in the free state for the request? */ - if (RingPtr->PreCnt < NumBd) { - Status = (LONG)(XST_FAILURE); + if (RingPtr->PreCnt < NumBd) { + Status = (LONG)(XST_FAILURE); } else { /* Set the return argument and move FreeHead backward */ - XEMACPS_RING_SEEKBACK(RingPtr, (RingPtr->FreeHead), NumBd); - RingPtr->FreeCnt += NumBd; - RingPtr->PreCnt -= NumBd; - Status = (LONG)(XST_SUCCESS); + XEMACPS_RING_SEEKBACK(RingPtr, (RingPtr->FreeHead), NumBd); + RingPtr->FreeCnt += NumBd; + RingPtr->PreCnt -= NumBd; + Status = (LONG)(XST_SUCCESS); } - return Status; + return Status; } @@ -526,33 +526,33 @@ LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, * *****************************************************************************/ LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd * BdSetPtr) + XEmacPs_Bd * BdSetPtr) { - XEmacPs_Bd *CurBdPtr; - u32 i; - LONG Status; + XEmacPs_Bd *CurBdPtr; + u32 i; + LONG Status; /* if no bds to process, simply return. */ - if (0U == NumBd){ - Status = (LONG)(XST_SUCCESS); + if (0U == NumBd){ + Status = (LONG)(XST_SUCCESS); } else { /* Make sure we are in sync with XEmacPs_BdRingAlloc() */ - if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) { - Status = (LONG)(XST_DMA_SG_LIST_ERROR); + if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) { + Status = (LONG)(XST_DMA_SG_LIST_ERROR); } else { - CurBdPtr = BdSetPtr; - for (i = 0U; i < NumBd; i++) { - CurBdPtr = (XEmacPs_Bd *)((void *)XEmacPs_BdRingNext(RingPtr, CurBdPtr)); + CurBdPtr = BdSetPtr; + for (i = 0U; i < NumBd; i++) { + CurBdPtr = (XEmacPs_Bd *)((void *)XEmacPs_BdRingNext(RingPtr, CurBdPtr)); } /* Adjust ring pointers & counters */ - XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd); - RingPtr->PreCnt -= NumBd; - RingPtr->HwTail = CurBdPtr; - RingPtr->HwCnt += NumBd; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd); + RingPtr->PreCnt -= NumBd; + RingPtr->HwTail = CurBdPtr; + RingPtr->HwCnt += NumBd; - Status = (LONG)(XST_SUCCESS); + Status = (LONG)(XST_SUCCESS); } } - return Status; + return Status; } @@ -625,25 +625,25 @@ LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd, u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, XEmacPs_Bd ** BdSetPtr) { - XEmacPs_Bd *CurBdPtr; - u32 BdStr = 0U; - u32 BdCount; - u32 BdPartialCount; - u32 Sop = 0U; - u32 Status; - u32 BdLimitLoc = BdLimit; - CurBdPtr = RingPtr->HwHead; - BdCount = 0U; - BdPartialCount = 0U; + XEmacPs_Bd *CurBdPtr; + u32 BdStr = 0U; + u32 BdCount; + u32 BdPartialCount; + u32 Sop = 0U; + u32 Status; + u32 BdLimitLoc = BdLimit; + CurBdPtr = RingPtr->HwHead; + BdCount = 0U; + BdPartialCount = 0U; /* If no BDs in work group, then there's nothing to search */ - if (RingPtr->HwCnt == 0x00000000U) { + if (RingPtr->HwCnt == 0x00000000U) { *BdSetPtr = NULL; - Status = 0U; + Status = 0U; } else { - if (BdLimitLoc > RingPtr->HwCnt){ - BdLimitLoc = RingPtr->HwCnt; + if (BdLimitLoc > RingPtr->HwCnt){ + BdLimitLoc = RingPtr->HwCnt; } /* Starting at HwHead, keep moving forward in the list until: * - A BD is encountered with its new/used bit set which means @@ -651,31 +651,31 @@ u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, * - RingPtr->HwTail is reached and RingPtr->HwCnt is reached. * - The number of requested BDs has been processed */ - while (BdCount < BdLimitLoc) { + while (BdCount < BdLimitLoc) { /* Read the status */ - if(CurBdPtr != NULL){ - BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET); + if(CurBdPtr != NULL){ + BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET); } - if ((Sop == 0x00000000U) && ((BdStr & XEMACPS_TXBUF_USED_MASK)!=0x00000000U)){ - Sop = 1U; + if ((Sop == 0x00000000U) && ((BdStr & XEMACPS_TXBUF_USED_MASK)!=0x00000000U)){ + Sop = 1U; } - if (Sop == 0x00000001U) { - BdCount++; - BdPartialCount++; + if (Sop == 0x00000001U) { + BdCount++; + BdPartialCount++; } /* hardware has processed this BD so check the "last" bit. * If it is clear, then there are more BDs for the current * packet. Keep a count of these partial packet BDs. */ - if ((Sop == 0x00000001U) && ((BdStr & XEMACPS_TXBUF_LAST_MASK)!=0x00000000U)) { - Sop = 0U; - BdPartialCount = 0U; + if ((Sop == 0x00000001U) && ((BdStr & XEMACPS_TXBUF_LAST_MASK)!=0x00000000U)) { + Sop = 0U; + BdPartialCount = 0U; } /* Move on to next BD in work group */ - CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); + CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); } /* Subtract off any partial packet BDs found */ @@ -684,18 +684,18 @@ u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, /* If BdCount is non-zero then BDs were found to return. Set return * parameters, update pointers and counters, return success */ - if (BdCount > 0x00000000U) { + if (BdCount > 0x00000000U) { *BdSetPtr = RingPtr->HwHead; - RingPtr->HwCnt -= BdCount; - RingPtr->PostCnt += BdCount; - XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); - Status = (BdCount); + RingPtr->HwCnt -= BdCount; + RingPtr->PostCnt += BdCount; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); + Status = (BdCount); } else { *BdSetPtr = NULL; - Status = 0U; + Status = 0U; } } - return Status; + return Status; } @@ -769,20 +769,20 @@ u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, XEmacPs_Bd ** BdSetPtr) { - XEmacPs_Bd *CurBdPtr; - u32 BdStr = 0U; - u32 BdCount; - u32 BdPartialCount; - u32 Status; + XEmacPs_Bd *CurBdPtr; + u32 BdStr = 0U; + u32 BdCount; + u32 BdPartialCount; + u32 Status; - CurBdPtr = RingPtr->HwHead; - BdCount = 0U; - BdPartialCount = 0U; + CurBdPtr = RingPtr->HwHead; + BdCount = 0U; + BdPartialCount = 0U; /* If no BDs in work group, then there's nothing to search */ - if (RingPtr->HwCnt == 0x00000000U) { + if (RingPtr->HwCnt == 0x00000000U) { *BdSetPtr = NULL; - Status = 0U; + Status = 0U; } else { /* Starting at HwHead, keep moving forward in the list until: @@ -791,51 +791,51 @@ u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, * - RingPtr->HwTail is reached and RingPtr->HwCnt is reached. * - The number of requested BDs has been processed */ - while (BdCount < BdLimit) { + while (BdCount < BdLimit) { /* Read the status */ - if(CurBdPtr!=NULL){ - BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET); + if(CurBdPtr!=NULL){ + BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET); } - if ((!(XEmacPs_BdIsRxNew(CurBdPtr)))==TRUE) { - break; + if ((!(XEmacPs_BdIsRxNew(CurBdPtr)))==TRUE) { + break; } - BdCount++; + BdCount++; /* hardware has processed this BD so check the "last" bit. If * it is clear, then there are more BDs for the current packet. * Keep a count of these partial packet BDs. */ - if ((BdStr & XEMACPS_RXBUF_EOF_MASK)!=0x00000000U) { - BdPartialCount = 0U; + if ((BdStr & XEMACPS_RXBUF_EOF_MASK)!=0x00000000U) { + BdPartialCount = 0U; } else { - BdPartialCount++; + BdPartialCount++; } /* Move on to next BD in work group */ - CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); + CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); } /* Subtract off any partial packet BDs found */ - BdCount -= BdPartialCount; + BdCount -= BdPartialCount; /* If BdCount is non-zero then BDs were found to return. Set return * parameters, update pointers and counters, return success */ - if (BdCount > 0x00000000U) { + if (BdCount > 0x00000000U) { *BdSetPtr = RingPtr->HwHead; - RingPtr->HwCnt -= BdCount; - RingPtr->PostCnt += BdCount; - XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); - Status = (BdCount); + RingPtr->HwCnt -= BdCount; + RingPtr->PostCnt += BdCount; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); + Status = (BdCount); } - else { + else { *BdSetPtr = NULL; - Status = 0U; + Status = 0U; } } - return Status; + return Status; } @@ -860,25 +860,25 @@ u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, * *****************************************************************************/ LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd * BdSetPtr) + XEmacPs_Bd * BdSetPtr) { - LONG Status; + LONG Status; /* if no bds to process, simply return. */ - if (0x00000000U == NumBd){ - Status = (LONG)(XST_SUCCESS); + if (0x00000000U == NumBd){ + Status = (LONG)(XST_SUCCESS); } else { /* Make sure we are in sync with XEmacPs_BdRingFromHw() */ - if ((RingPtr->PostCnt < NumBd) || (RingPtr->PostHead != BdSetPtr)) { - Status = (LONG)(XST_DMA_SG_LIST_ERROR); + if ((RingPtr->PostCnt < NumBd) || (RingPtr->PostHead != BdSetPtr)) { + Status = (LONG)(XST_DMA_SG_LIST_ERROR); } else { /* Update pointers and counters */ - RingPtr->FreeCnt += NumBd; - RingPtr->PostCnt -= NumBd; - XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PostHead, NumBd); - Status = (LONG)(XST_SUCCESS); + RingPtr->FreeCnt += NumBd; + RingPtr->PostCnt -= NumBd; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PostHead, NumBd); + Status = (LONG)(XST_SUCCESS); } } - return Status; + return Status; } @@ -912,89 +912,89 @@ LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd, *****************************************************************************/ LONG XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction) { - UINTPTR AddrV, AddrP; - u32 i; + UINTPTR AddrV, AddrP; + u32 i; - if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) { - return (LONG)(XST_INVALID_PARAM); + if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) { + return (LONG)(XST_INVALID_PARAM); } /* Is the list created */ - if (RingPtr->AllCnt == 0x00000000U) { - return (LONG)(XST_DMA_SG_NO_LIST); + if (RingPtr->AllCnt == 0x00000000U) { + return (LONG)(XST_DMA_SG_NO_LIST); } /* Can't check if channel is running */ - if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) { - return (LONG)(XST_IS_STARTED); + if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) { + return (LONG)(XST_IS_STARTED); } /* RunState doesn't make sense */ - if (RingPtr->RunState != (u32)XST_DMA_SG_IS_STOPPED) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + if (RingPtr->RunState != (u32)XST_DMA_SG_IS_STOPPED) { + return (LONG)(XST_DMA_SG_LIST_ERROR); } /* Verify internal pointers point to correct memory space */ - AddrV = (UINTPTR) RingPtr->FreeHead; - if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + AddrV = (UINTPTR) RingPtr->FreeHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); } - AddrV = (UINTPTR) RingPtr->PreHead; - if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + AddrV = (UINTPTR) RingPtr->PreHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); } - AddrV = (UINTPTR) RingPtr->HwHead; - if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + AddrV = (UINTPTR) RingPtr->HwHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); } - AddrV = (UINTPTR) RingPtr->HwTail; - if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + AddrV = (UINTPTR) RingPtr->HwTail; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); } - AddrV = (UINTPTR) RingPtr->PostHead; - if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + AddrV = (UINTPTR) RingPtr->PostHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); } /* Verify internal counters add up */ - if ((RingPtr->HwCnt + RingPtr->PreCnt + RingPtr->FreeCnt + + if ((RingPtr->HwCnt + RingPtr->PreCnt + RingPtr->FreeCnt + RingPtr->PostCnt) != RingPtr->AllCnt) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + return (LONG)(XST_DMA_SG_LIST_ERROR); } /* Verify BDs are linked correctly */ - AddrV = RingPtr->BaseBdAddr; - AddrP = RingPtr->PhysBaseAddr + RingPtr->Separation; + AddrV = RingPtr->BaseBdAddr; + AddrP = RingPtr->PhysBaseAddr + RingPtr->Separation; - for (i = 1U; i < RingPtr->AllCnt; i++) { + for (i = 1U; i < RingPtr->AllCnt; i++) { /* Check BDA for this BD. It should point to next physical addr */ - if (XEmacPs_BdRead(AddrV, XEMACPS_BD_ADDR_OFFSET) != AddrP) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + if (XEmacPs_BdRead(AddrV, XEMACPS_BD_ADDR_OFFSET) != AddrP) { + return (LONG)(XST_DMA_SG_LIST_ERROR); } /* Move on to next BD */ - AddrV += RingPtr->Separation; - AddrP += RingPtr->Separation; + AddrV += RingPtr->Separation; + AddrP += RingPtr->Separation; } /* Last BD should have wrap bit set */ - if (XEMACPS_SEND == Direction) { - if ((!XEmacPs_BdIsTxWrap(AddrV))==TRUE) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + if (XEMACPS_SEND == Direction) { + if ((!XEmacPs_BdIsTxWrap(AddrV))==TRUE) { + return (LONG)(XST_DMA_SG_LIST_ERROR); } } - else { /* XEMACPS_RECV */ - if ((!XEmacPs_BdIsRxWrap(AddrV))==TRUE) { - return (LONG)(XST_DMA_SG_LIST_ERROR); + else { /* XEMACPS_RECV */ + if ((!XEmacPs_BdIsRxWrap(AddrV))==TRUE) { + return (LONG)(XST_DMA_SG_LIST_ERROR); } } /* No problems found */ - return (LONG)(XST_SUCCESS); + return (LONG)(XST_SUCCESS); } /*****************************************************************************/ @@ -1012,13 +1012,13 @@ LONG XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction) static void XEmacPs_BdSetRxWrap(UINTPTR BdPtr) { u32 DataValueRx; - u32 *TempPtr; + u32 *TempPtr; - BdPtr += (u32)(XEMACPS_BD_ADDR_OFFSET); - TempPtr = (u32 *)BdPtr; - if(TempPtr != NULL) { - DataValueRx = *TempPtr; - DataValueRx |= XEMACPS_RXBUF_WRAP_MASK; + BdPtr += (u32)(XEMACPS_BD_ADDR_OFFSET); + TempPtr = (u32 *)BdPtr; + if(TempPtr != NULL) { + DataValueRx = *TempPtr; + DataValueRx |= XEMACPS_RXBUF_WRAP_MASK; *TempPtr = DataValueRx; } } @@ -1038,13 +1038,13 @@ static void XEmacPs_BdSetRxWrap(UINTPTR BdPtr) static void XEmacPs_BdSetTxWrap(UINTPTR BdPtr) { u32 DataValueTx; - u32 *TempPtr; + u32 *TempPtr; - BdPtr += (u32)(XEMACPS_BD_STAT_OFFSET); - TempPtr = (u32 *)BdPtr; - if(TempPtr != NULL) { - DataValueTx = *TempPtr; - DataValueTx |= XEMACPS_TXBUF_WRAP_MASK; + BdPtr += (u32)(XEMACPS_BD_STAT_OFFSET); + TempPtr = (u32 *)BdPtr; + if(TempPtr != NULL) { + DataValueTx = *TempPtr; + DataValueTx |= XEMACPS_TXBUF_WRAP_MASK; *TempPtr = DataValueTx; } } @@ -1066,11 +1066,11 @@ static void XEmacPs_BdSetTxWrap(UINTPTR BdPtr) *****************************************************************************/ void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc) { - RingPtr->FreeHead = virtaddrloc; - RingPtr->PreHead = virtaddrloc; - RingPtr->HwHead = virtaddrloc; - RingPtr->HwTail = virtaddrloc; - RingPtr->PostHead = virtaddrloc; + RingPtr->FreeHead = virtaddrloc; + RingPtr->PreHead = virtaddrloc; + RingPtr->HwHead = virtaddrloc; + RingPtr->HwTail = virtaddrloc; + RingPtr->PostHead = virtaddrloc; } /** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h index 9d7331d6d9..e454ecb3e1 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h @@ -40,28 +40,28 @@ extern "C" { /** This is an internal structure used to maintain the DMA list */ typedef struct { - UINTPTR PhysBaseAddr;/**< Physical address of 1st BD in list */ - UINTPTR BaseBdAddr; /**< Virtual address of 1st BD in list */ - UINTPTR HighBdAddr; /**< Virtual address of last BD in the list */ - u32 Length; /**< Total size of ring in bytes */ - u32 RunState; /**< Flag to indicate DMA is started */ - u32 Separation; /**< Number of bytes between the starting address + UINTPTR PhysBaseAddr;/**< Physical address of 1st BD in list */ + UINTPTR BaseBdAddr; /**< Virtual address of 1st BD in list */ + UINTPTR HighBdAddr; /**< Virtual address of last BD in the list */ + u32 Length; /**< Total size of ring in bytes */ + u32 RunState; /**< Flag to indicate DMA is started */ + u32 Separation; /**< Number of bytes between the starting address of adjacent BDs */ - XEmacPs_Bd *FreeHead; + XEmacPs_Bd *FreeHead; /**< First BD in the free group */ - XEmacPs_Bd *PreHead;/**< First BD in the pre-work group */ - XEmacPs_Bd *HwHead; /**< First BD in the work group */ - XEmacPs_Bd *HwTail; /**< Last BD in the work group */ - XEmacPs_Bd *PostHead; + XEmacPs_Bd *PreHead;/**< First BD in the pre-work group */ + XEmacPs_Bd *HwHead; /**< First BD in the work group */ + XEmacPs_Bd *HwTail; /**< Last BD in the work group */ + XEmacPs_Bd *PostHead; /**< First BD in the post-work group */ - XEmacPs_Bd *BdaRestart; + XEmacPs_Bd *BdaRestart; /**< BDA to load when channel is started */ - volatile u32 HwCnt; /**< Number of BDs in work group */ - u32 PreCnt; /**< Number of BDs in pre-work group */ - u32 FreeCnt; /**< Number of allocatable BDs in the free group */ - u32 PostCnt; /**< Number of BDs in post-work group */ - u32 AllCnt; /**< Total Number of BDs for channel */ + volatile u32 HwCnt; /**< Number of BDs in work group */ + u32 PreCnt; /**< Number of BDs in pre-work group */ + u32 FreeCnt; /**< Number of allocatable BDs in the free group */ + u32 PostCnt; /**< Number of BDs in post-work group */ + u32 AllCnt; /**< Total Number of BDs for channel */ } XEmacPs_BdRing; @@ -195,9 +195,9 @@ LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, XEmacPs_Bd * BdSetPtr); LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd * BdSetPtr); + XEmacPs_Bd * BdSetPtr); LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd * BdSetPtr); + XEmacPs_Bd * BdSetPtr); u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, XEmacPs_Bd ** BdSetPtr); u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c index b9620c208b..cb45bc7f10 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c @@ -64,47 +64,47 @@ *****************************************************************************/ LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index) { - u32 MacAddr; - u8 *Aptr = (u8 *)(void *)AddressPtr; - u8 IndexLoc = Index; - LONG Status; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(Aptr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U)); + u32 MacAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 IndexLoc = Index; + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Aptr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U)); /* Be sure device has been stopped */ - if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); } - else{ + else{ /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ - IndexLoc--; + IndexLoc--; /* Set the MAC bits [31:0] in BOT */ - MacAddr = *(Aptr); - MacAddr |= ((u32)(*(Aptr+1)) << 8U); - MacAddr |= ((u32)(*(Aptr+2)) << 16U); - MacAddr |= ((u32)(*(Aptr+3)) << 24U); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + MacAddr = *(Aptr); + MacAddr |= ((u32)(*(Aptr+1)) << 8U); + MacAddr |= ((u32)(*(Aptr+2)) << 16U); + MacAddr |= ((u32)(*(Aptr+3)) << 24U); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr); /* There are reserved bits in TOP so don't affect them */ - MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8))); - MacAddr &= (u32)(~XEMACPS_LADDR_MACH_MASK); + MacAddr &= (u32)(~XEMACPS_LADDR_MACH_MASK); /* Set MAC bits [47:32] in TOP */ - MacAddr |= (u32)(*(Aptr+4)); - MacAddr |= (u32)(*(Aptr+5)) << 8U; + MacAddr |= (u32)(*(Aptr+4)); + MacAddr |= (u32)(*(Aptr+5)) << 8U; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr); - Status = (LONG)(XST_SUCCESS); + Status = (LONG)(XST_SUCCESS); } - return Status; + return Status; } @@ -120,18 +120,18 @@ LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index) *****************************************************************************/ void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index) { - u32 MacAddr; - u8 *Aptr = (u8 *)(void *)AddressPtr; - u8 IndexLoc = Index; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(Aptr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - Xil_AssertVoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U)); + u32 MacAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 IndexLoc = Index; + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Aptr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U)); /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ - IndexLoc--; + IndexLoc--; - MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8))); *Aptr = (u8) MacAddr; *(Aptr+1) = (u8) (MacAddr >> 8U); @@ -139,7 +139,7 @@ void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index) *(Aptr+3) = (u8) (MacAddr >> 24U); /* Read MAC bits [47:32] in TOP */ - MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8))); *(Aptr+4) = (u8) MacAddr; *(Aptr+5) = (u8) (MacAddr >> 8U); @@ -206,54 +206,54 @@ void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index) *****************************************************************************/ LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr) { - u32 HashAddr; - u8 *Aptr = (u8 *)(void *)AddressPtr; - u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8; - u32 Result; - LONG Status; + u32 HashAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8; + u32 Result; + LONG Status; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(AddressPtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(AddressPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); /* Be sure device has been stopped */ - if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); } else { - Temp1 = (*(Aptr+0)) & 0x3FU; - Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); + Temp1 = (*(Aptr+0)) & 0x3FU; + Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); - Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x3U) << 4U); - Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); - Temp5 = (*(Aptr+3)) & 0x3FU; - Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); - Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); - Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); + Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x3U) << 4U); + Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); + Temp5 = (*(Aptr+3)) & 0x3FU; + Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); + Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); + Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); - Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ + Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8); - if (Result >= (u32)XEMACPS_MAX_HASH_BITS) { - Status = (LONG)(XST_INVALID_PARAM); + if (Result >= (u32)XEMACPS_MAX_HASH_BITS) { + Status = (LONG)(XST_INVALID_PARAM); } else { - if (Result < (u32)32) { - HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHL_OFFSET); - HashAddr |= (u32)(0x00000001U << Result); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHL_OFFSET, HashAddr); + if (Result < (u32)32) { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET); + HashAddr |= (u32)(0x00000001U << Result); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET, HashAddr); } else { - HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHH_OFFSET); - HashAddr |= (u32)(0x00000001U << (u32)(Result - (u32)32)); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHH_OFFSET, HashAddr); + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET); + HashAddr |= (u32)(0x00000001U << (u32)(Result - (u32)32)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET, HashAddr); } - Status = (LONG)(XST_SUCCESS); + Status = (LONG)(XST_SUCCESS); } } - return Status; + return Status; } /*****************************************************************************/ @@ -276,52 +276,52 @@ LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr) *****************************************************************************/ LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr) { - u32 HashAddr; - u8 *Aptr = (u8 *)(void *)AddressPtr; - u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8; - u32 Result; - LONG Status; + u32 HashAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8; + u32 Result; + LONG Status; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(Aptr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Aptr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); /* Be sure device has been stopped */ - if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); } else { - Temp1 = (*(Aptr+0)) & 0x3FU; - Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); - Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x03U) << 4U); - Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); - Temp5 = (*(Aptr+3)) & 0x3FU; - Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); - Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); - Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); + Temp1 = (*(Aptr+0)) & 0x3FU; + Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); + Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x03U) << 4U); + Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); + Temp5 = (*(Aptr+3)) & 0x3FU; + Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); + Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); + Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); - Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ + Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8); - if (Result >= (u32)(XEMACPS_MAX_HASH_BITS)) { - Status = (LONG)(XST_INVALID_PARAM); + if (Result >= (u32)(XEMACPS_MAX_HASH_BITS)) { + Status = (LONG)(XST_INVALID_PARAM); } else { - if (Result < (u32)32) { - HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHL_OFFSET); - HashAddr &= (u32)(~(0x00000001U << Result)); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHL_OFFSET, HashAddr); + if (Result < (u32)32) { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET); + HashAddr &= (u32)(~(0x00000001U << Result)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET, HashAddr); } else { - HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHH_OFFSET); - HashAddr &= (u32)(~(0x00000001U << (u32)(Result - (u32)32))); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHH_OFFSET, HashAddr); + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET); + HashAddr &= (u32)(~(0x00000001U << (u32)(Result - (u32)32))); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET, HashAddr); } - Status = (LONG)(XST_SUCCESS); + Status = (LONG)(XST_SUCCESS); } } - return Status; + return Status; } /*****************************************************************************/ /** @@ -332,14 +332,14 @@ LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr) *****************************************************************************/ void XEmacPs_ClearHash(XEmacPs *InstancePtr) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_HASHL_OFFSET, 0x0U); /* write bits [63:32] in TOP */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_HASHH_OFFSET, 0x0U); } @@ -355,11 +355,11 @@ void XEmacPs_ClearHash(XEmacPs *InstancePtr) *****************************************************************************/ void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr) { - u32 *Aptr = (u32 *)(void *)AddressPtr; + u32 *Aptr = (u32 *)(void *)AddressPtr; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(AddressPtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(AddressPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); *(Aptr+0) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_HASHL_OFFSET); @@ -386,27 +386,27 @@ void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr) *****************************************************************************/ LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index) { - u8 IndexLoc = Index; - LONG Status; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_TYPE_ID) && (IndexLoc > 0x00U)); + u8 IndexLoc = Index; + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_TYPE_ID) && (IndexLoc > 0x00U)); /* Be sure device has been stopped */ - if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); } else { /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ - IndexLoc--; + IndexLoc--; /* Set the ID bits in MATCHx register */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, ((u32)XEMACPS_MATCH1_OFFSET + ((u32)IndexLoc * (u32)4)), Id_Check); - Status = (LONG)(XST_SUCCESS); + Status = (LONG)(XST_SUCCESS); } - return Status; + return Status; } /*****************************************************************************/ @@ -429,16 +429,16 @@ LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index) *****************************************************************************/ LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options) { - u32 Reg; /* Generic register contents */ - u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ - u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ - LONG Status; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + u32 Reg; /* Generic register contents */ + u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ + u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); /* Be sure device has been stopped */ - if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); } else { /* Many of these options will change the NET_CONFIG registers. @@ -447,119 +447,119 @@ LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options) */ /* Grab current register contents */ - RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET); - RegNewNetCfg = RegNetCfg; + RegNewNetCfg = RegNetCfg; /* * It is configured to max 1536. */ - if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { - RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK); + if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { + RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK); } /* Turn on VLAN packet only, only VLAN tagged will be accepted */ - if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK; + if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK; } /* Turn on FCS stripping on receive packets */ - if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK; + if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK; } /* Turn on length/type field checking on receive packets */ - if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_LENERRDSCRD_MASK; + if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_LENERRDSCRD_MASK; } /* Turn on flow control */ - if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK; + if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK; } /* Turn on promiscuous frame filtering (all frames are received) */ - if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK; + if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK; } /* Allow broadcast address reception */ - if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_BCASTDI_MASK); + if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_BCASTDI_MASK); } /* Allow multicast address filtering */ - if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK; + if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK; } /* enable RX checksum offload */ - if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK; + if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK; } /* Enable jumbo frames */ - if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) && + if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) && (InstancePtr->Version > 2)) { - RegNewNetCfg |= XEMACPS_NWCFG_JUMBO_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_JUMBOMAXLEN_OFFSET, XEMACPS_RX_BUF_SIZE_JUMBO); - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + RegNewNetCfg |= XEMACPS_NWCFG_JUMBO_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_JUMBOMAXLEN_OFFSET, XEMACPS_RX_BUF_SIZE_JUMBO); + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET); - Reg &= ~XEMACPS_DMACR_RXBUF_MASK; - Reg |= (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO / (u32)XEMACPS_RX_BUF_UNIT) + + Reg &= ~XEMACPS_DMACR_RXBUF_MASK; + Reg |= (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO / (u32)XEMACPS_RX_BUF_UNIT) + (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO % (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & (u32)(XEMACPS_DMACR_RXBUF_MASK)); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET, Reg); - InstancePtr->MaxMtuSize = XEMACPS_MTU_JUMBO; - InstancePtr->MaxFrameSize = XEMACPS_MTU_JUMBO + - XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; - InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + - XEMACPS_HDR_VLAN_SIZE; - InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_JUMBO_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + InstancePtr->MaxMtuSize = XEMACPS_MTU_JUMBO; + InstancePtr->MaxFrameSize = XEMACPS_MTU_JUMBO + + XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; + InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + + XEMACPS_HDR_VLAN_SIZE; + InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_JUMBO_MASK; } - if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) && + if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) && (InstancePtr->Version > 2)) { - RegNewNetCfg |= (XEMACPS_NWCFG_SGMIIEN_MASK | - XEMACPS_NWCFG_PCSSEL_MASK); + RegNewNetCfg |= (XEMACPS_NWCFG_SGMIIEN_MASK | + XEMACPS_NWCFG_PCSSEL_MASK); } /* Officially change the NET_CONFIG registers if it needs to be * modified. */ - if (RegNetCfg != RegNewNetCfg) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + if (RegNetCfg != RegNewNetCfg) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET, RegNewNetCfg); } /* Enable TX checksum offload */ - if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET); - Reg |= XEMACPS_DMACR_TCPCKSUM_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg |= XEMACPS_DMACR_TCPCKSUM_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, Reg); } /* Enable transmitter */ - if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - Reg |= XEMACPS_NWCTRL_TXEN_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg |= XEMACPS_NWCTRL_TXEN_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, Reg); } /* Enable receiver */ - if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - Reg |= XEMACPS_NWCTRL_RXEN_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg |= XEMACPS_NWCTRL_RXEN_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, Reg); } @@ -569,11 +569,11 @@ LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options) */ /* Set options word to its new value */ - InstancePtr->Options |= Options; + InstancePtr->Options |= Options; - Status = (LONG)(XST_SUCCESS); + Status = (LONG)(XST_SUCCESS); } - return Status; + return Status; } @@ -596,16 +596,16 @@ LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options) *****************************************************************************/ LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options) { - u32 Reg; /* Generic */ - u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ - u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ - LONG Status; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + u32 Reg; /* Generic */ + u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ + u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); /* Be sure device has been stopped */ - if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); } else { /* Many of these options will change the NET_CONFIG registers. @@ -614,117 +614,117 @@ LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options) */ /* Grab current register contents */ - RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET); - RegNewNetCfg = RegNetCfg; + RegNewNetCfg = RegNetCfg; /* There is only RX configuration!? * It is configured in two different length, up to 1536 and 10240 bytes */ - if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_1536RXEN_MASK); + if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_1536RXEN_MASK); } /* Turn off VLAN packet only */ - if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_NVLANDISC_MASK); + if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_NVLANDISC_MASK); } /* Turn off FCS stripping on receive packets */ - if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_FCSREM_MASK); + if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_FCSREM_MASK); } /* Turn off length/type field checking on receive packets */ - if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_LENERRDSCRD_MASK); + if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_LENERRDSCRD_MASK); } /* Turn off flow control */ - if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_PAUSEEN_MASK); + if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_PAUSEEN_MASK); } /* Turn off promiscuous frame filtering (all frames are received) */ - if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_COPYALLEN_MASK); + if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_COPYALLEN_MASK); } /* Disallow broadcast address filtering => broadcast reception */ - if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK; + if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK; } /* Disallow multicast address filtering */ - if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_MCASTHASHEN_MASK); + if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_MCASTHASHEN_MASK); } /* Disable RX checksum offload */ - if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_RXCHKSUMEN_MASK); + if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_RXCHKSUMEN_MASK); } /* Disable jumbo frames */ - if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) && + if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) && (InstancePtr->Version > 2)) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_JUMBO_MASK); - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_JUMBO_MASK); + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET); - Reg &= ~XEMACPS_DMACR_RXBUF_MASK; - Reg |= (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) + + Reg &= ~XEMACPS_DMACR_RXBUF_MASK; + Reg |= (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) + (((((u32)XEMACPS_RX_BUF_SIZE % (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & (u32)(XEMACPS_DMACR_RXBUF_MASK)); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET, Reg); - InstancePtr->MaxMtuSize = XEMACPS_MTU; - InstancePtr->MaxFrameSize = XEMACPS_MTU + - XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; - InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + - XEMACPS_HDR_VLAN_SIZE; - InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + InstancePtr->MaxMtuSize = XEMACPS_MTU; + InstancePtr->MaxFrameSize = XEMACPS_MTU + + XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; + InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + + XEMACPS_HDR_VLAN_SIZE; + InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK; } - if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) && + if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) && (InstancePtr->Version > 2)) { - RegNewNetCfg &= (u32)(~(XEMACPS_NWCFG_SGMIIEN_MASK | - XEMACPS_NWCFG_PCSSEL_MASK)); + RegNewNetCfg &= (u32)(~(XEMACPS_NWCFG_SGMIIEN_MASK | + XEMACPS_NWCFG_PCSSEL_MASK)); } /* Officially change the NET_CONFIG registers if it needs to be * modified. */ - if (RegNetCfg != RegNewNetCfg) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + if (RegNetCfg != RegNewNetCfg) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET, RegNewNetCfg); } /* Disable TX checksum offload */ - if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET); - Reg &= (u32)(~XEMACPS_DMACR_TCPCKSUM_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg &= (u32)(~XEMACPS_DMACR_TCPCKSUM_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, Reg); } /* Disable transmitter */ - if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, Reg); } /* Disable receiver */ - if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, Reg); } @@ -734,11 +734,11 @@ LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options) */ /* Set options word to its new value */ - InstancePtr->Options &= ~Options; + InstancePtr->Options &= ~Options; - Status = (LONG)(XST_SUCCESS); + Status = (LONG)(XST_SUCCESS); } - return Status; + return Status; } @@ -758,10 +758,10 @@ LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options) *****************************************************************************/ u32 XEmacPs_GetOptions(XEmacPs *InstancePtr) { - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - return (InstancePtr->Options); + return (InstancePtr->Options); } @@ -778,25 +778,25 @@ u32 XEmacPs_GetOptions(XEmacPs *InstancePtr) *****************************************************************************/ LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr) { - u32 Reg; - LONG Status; + u32 Reg; + LONG Status; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); /* Make sure device is ready for this operation */ - if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STOPPED); + if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STOPPED); } else { /* Send flow control frame */ - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - Reg |= XEMACPS_NWCTRL_PAUSETX_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg |= XEMACPS_NWCTRL_PAUSETX_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, Reg); - Status = (LONG)(XST_SUCCESS); + Status = (LONG)(XST_SUCCESS); } - return Status; + return Status; } /*****************************************************************************/ @@ -814,25 +814,25 @@ LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr) *****************************************************************************/ u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr) { - u32 Reg; - u16 Status; + u32 Reg; + u16 Status; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET); + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); - if ((Reg & XEMACPS_NWCFG_1000_MASK) != 0x00000000U) { - Status = (u16)(1000); + if ((Reg & XEMACPS_NWCFG_1000_MASK) != 0x00000000U) { + Status = (u16)(1000); } else { - if ((Reg & XEMACPS_NWCFG_100_MASK) != 0x00000000U) { - Status = (u16)(100); + if ((Reg & XEMACPS_NWCFG_100_MASK) != 0x00000000U) { + Status = (u16)(100); } else { - Status = (u16)(10); + Status = (u16)(10); } } - return Status; + return Status; } @@ -853,15 +853,15 @@ void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed) { u32 Reg; Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); Xil_AssertVoid((Speed == (u16)10) || (Speed == (u16)100) || (Speed == (u16)1000)); Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET); - Reg &= (u32)(~(XEMACPS_NWCFG_1000_MASK | XEMACPS_NWCFG_100_MASK)); + XEMACPS_NWCFG_OFFSET); + Reg &= (u32)(~(XEMACPS_NWCFG_1000_MASK | XEMACPS_NWCFG_100_MASK)); - switch (Speed) { - case (u16)10: + switch (Speed) { + case (u16)10: break; case (u16)100: @@ -913,19 +913,19 @@ void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed) *****************************************************************************/ void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor) { - u32 Reg; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Divisor <= (XEmacPs_MdcDiv)0x7); /* only last three bits are valid */ + u32 Reg; + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Divisor <= (XEmacPs_MdcDiv)0x7); /* only last three bits are valid */ - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET); + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); /* clear these three bits, could be done with mask */ - Reg &= (u32)(~XEMACPS_NWCFG_MDCCLKDIV_MASK); + Reg &= (u32)(~XEMACPS_NWCFG_MDCCLKDIV_MASK); - Reg |= ((u32)Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK); + Reg |= ((u32)Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET, Reg); } @@ -970,41 +970,41 @@ void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor) LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, u32 RegisterNum, u16 *PhyDataPtr) { - u32 Mgtcr; - volatile u32 Ipisr; - u32 IpReadTemp; - LONG Status; + u32 Mgtcr; + volatile u32 Ipisr; + u32 IpReadTemp; + LONG Status; - Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr != NULL); /* Make sure no other PHY operation is currently in progress */ - if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWSR_OFFSET) & + if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET) & XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) { - Status = (LONG)(XST_EMAC_MII_BUSY); + Status = (LONG)(XST_EMAC_MII_BUSY); } else { /* Construct Mgtcr mask for the operation */ - Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK | + Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK | (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) | (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK); /* Write Mgtcr and wait for completion */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_PHYMNTNC_OFFSET, Mgtcr); - do { - Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + do { + Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWSR_OFFSET); - IpReadTemp = Ipisr; + IpReadTemp = Ipisr; } while ((IpReadTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U); /* Read data */ *PhyDataPtr = (u16)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_PHYMNTNC_OFFSET); - Status = (LONG)(XST_SUCCESS); + XEMACPS_PHYMNTNC_OFFSET); + Status = (LONG)(XST_SUCCESS); } - return Status; + return Status; } @@ -1051,37 +1051,37 @@ LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress, u32 RegisterNum, u16 PhyData) { - u32 Mgtcr; - volatile u32 Ipisr; - u32 IpWriteTemp; - LONG Status; + u32 Mgtcr; + volatile u32 Ipisr; + u32 IpWriteTemp; + LONG Status; - Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr != NULL); /* Make sure no other PHY operation is currently in progress */ - if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWSR_OFFSET) & + if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET) & XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) { - Status = (LONG)(XST_EMAC_MII_BUSY); + Status = (LONG)(XST_EMAC_MII_BUSY); } else { /* Construct Mgtcr mask for the operation */ - Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK | + Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK | (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) | (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK) | (u32)PhyData; /* Write Mgtcr and wait for completion */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_PHYMNTNC_OFFSET, Mgtcr); - do { - Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + do { + Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWSR_OFFSET); - IpWriteTemp = Ipisr; + IpWriteTemp = Ipisr; } while ((IpWriteTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U); - Status = (LONG)(XST_SUCCESS); + Status = (LONG)(XST_SUCCESS); } - return Status; + return Status; } /*****************************************************************************/ @@ -1096,38 +1096,38 @@ LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress, ******************************************************************************/ void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength) { - u32 Reg; - u32 RegUpdateVal = 0; + u32 Reg; + u32 RegUpdateVal = 0; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid((BLength == XEMACPS_SINGLE_BURST) || + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((BLength == XEMACPS_SINGLE_BURST) || (BLength == XEMACPS_4BYTE_BURST) || (BLength == XEMACPS_8BYTE_BURST) || (BLength == XEMACPS_16BYTE_BURST)); - switch (BLength) { - case XEMACPS_SINGLE_BURST: - RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST; - break; + switch (BLength) { + case XEMACPS_SINGLE_BURST: + RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST; + break; - case XEMACPS_4BYTE_BURST: - RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST; - break; + case XEMACPS_4BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST; + break; - case XEMACPS_8BYTE_BURST: - RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST; - break; + case XEMACPS_8BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST; + break; - case XEMACPS_16BYTE_BURST: - RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST; - break; + case XEMACPS_16BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST; + break; } - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET); + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); - Reg &= (u32)(~XEMACPS_DMACR_BLENGTH_MASK); - Reg |= RegUpdateVal; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, - Reg); + Reg &= (u32)(~XEMACPS_DMACR_BLENGTH_MASK); + Reg |= RegUpdateVal; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, + Reg); } /** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c index 7f725231af..c3d94f4d59 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c @@ -6,9 +6,9 @@ * DO NOT EDIT. * * Copyright (C) 2010-2021 Xilinx, Inc. All Rights Reserved. -* SPDX-License-Identifier: MIT +* SPDX-License-Identifier: MIT -* +* * Description: Driver configuration * *******************************************************************/ @@ -23,9 +23,9 @@ XEmacPs_Config XEmacPs_ConfigTable[XPAR_XEMACPS_NUM_INSTANCES] = { { - XPAR_PSU_ETHERNET_3_DEVICE_ID, - XPAR_PSU_ETHERNET_3_BASEADDR, - XPAR_PSU_ETHERNET_3_IS_CACHE_COHERENT + XPAR_PSU_ETHERNET_3_DEVICE_ID, + XPAR_PSU_ETHERNET_3_BASEADDR, + XPAR_PSU_ETHERNET_3_IS_CACHE_COHERENT } }; diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c index 3fa614b553..6e72317e16 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c @@ -44,11 +44,11 @@ * This function perform the reset sequence to the given emacps interface by * configuring the appropriate control bits in the emacps specific registers. * the emacps reset sequence involves the following steps -* Disable all the interuupts -* Clear the status registers -* Disable Rx and Tx engines -* Update the Tx and Rx descriptor queue registers with reset values -* Update the other relevant control registers with reset value +* Disable all the interuupts +* Clear the status registers +* Disable Rx and Tx engines +* Update the Tx and Rx descriptor queue registers with reset values +* Update the other relevant control registers with reset value * * @param BaseAddr of the interface * @@ -60,38 +60,38 @@ ******************************************************************************/ void XEmacPs_ResetHw(u32 BaseAddr) { - u32 RegVal; + u32 RegVal; /* Disable the interrupts */ - XEmacPs_WriteReg(BaseAddr,XEMACPS_IDR_OFFSET,0x0U); + XEmacPs_WriteReg(BaseAddr,XEMACPS_IDR_OFFSET,0x0U); /* Stop transmission,disable loopback and Stop tx and Rx engines */ - RegVal = XEmacPs_ReadReg(BaseAddr,XEMACPS_NWCTRL_OFFSET); - RegVal &= ~((u32)XEMACPS_NWCTRL_TXEN_MASK| + RegVal = XEmacPs_ReadReg(BaseAddr,XEMACPS_NWCTRL_OFFSET); + RegVal &= ~((u32)XEMACPS_NWCTRL_TXEN_MASK| (u32)XEMACPS_NWCTRL_RXEN_MASK| (u32)XEMACPS_NWCTRL_HALTTX_MASK| (u32)XEMACPS_NWCTRL_LOOPEN_MASK); /* Clear the statistic registers, flush the packets in DPRAM*/ - RegVal |= (XEMACPS_NWCTRL_STATCLR_MASK| - XEMACPS_NWCTRL_FLUSH_DPRAM_MASK); - XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCTRL_OFFSET,RegVal); + RegVal |= (XEMACPS_NWCTRL_STATCLR_MASK| + XEMACPS_NWCTRL_FLUSH_DPRAM_MASK); + XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCTRL_OFFSET,RegVal); /* Clear the interrupt status */ - XEmacPs_WriteReg(BaseAddr,XEMACPS_ISR_OFFSET,XEMACPS_IXR_ALL_MASK); + XEmacPs_WriteReg(BaseAddr,XEMACPS_ISR_OFFSET,XEMACPS_IXR_ALL_MASK); /* Clear the tx status */ - XEmacPs_WriteReg(BaseAddr,XEMACPS_TXSR_OFFSET,(XEMACPS_TXSR_ERROR_MASK| + XEmacPs_WriteReg(BaseAddr,XEMACPS_TXSR_OFFSET,(XEMACPS_TXSR_ERROR_MASK| (u32)XEMACPS_TXSR_TXCOMPL_MASK| (u32)XEMACPS_TXSR_TXGO_MASK)); /* Clear the rx status */ - XEmacPs_WriteReg(BaseAddr,XEMACPS_RXSR_OFFSET, - XEMACPS_RXSR_FRAMERX_MASK); + XEmacPs_WriteReg(BaseAddr,XEMACPS_RXSR_OFFSET, + XEMACPS_RXSR_FRAMERX_MASK); /* Clear the tx base address */ - XEmacPs_WriteReg(BaseAddr,XEMACPS_TXQBASE_OFFSET,0x0U); + XEmacPs_WriteReg(BaseAddr,XEMACPS_TXQBASE_OFFSET,0x0U); /* Clear the rx base address */ - XEmacPs_WriteReg(BaseAddr,XEMACPS_RXQBASE_OFFSET,0x0U); + XEmacPs_WriteReg(BaseAddr,XEMACPS_RXQBASE_OFFSET,0x0U); /* Update the network config register with reset value */ - XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCFG_OFFSET,XEMACPS_NWCFG_RESET_MASK); + XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCFG_OFFSET,XEMACPS_NWCFG_RESET_MASK); /* Update the hash address registers with reset value */ - XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHL_OFFSET,0x0U); - XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHH_OFFSET,0x0U); + XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHL_OFFSET,0x0U); + XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHH_OFFSET,0x0U); } /** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h index 362acfdb7f..a8ea3a8315 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h @@ -89,7 +89,7 @@ extern "C" { * @{ */ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, - MDC_DIV_64, MDC_DIV_96, MDC_DIV_128, MDC_DIV_224 + MDC_DIV_64, MDC_DIV_96, MDC_DIV_128, MDC_DIV_224 } XEmacPs_MdcDiv; /*@}*/ @@ -276,29 +276,29 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, nanosecond counter */ #define XEMACPS_INTQ1_STS_OFFSET 0x00000400U /**< Interrupt Q1 Status - reg */ + reg */ #define XEMACPS_TXQ1BASE_OFFSET 0x00000440U /**< TX Q1 Base address - reg */ + reg */ #define XEMACPS_RXQ1BASE_OFFSET 0x00000480U /**< RX Q1 Base address - reg */ + reg */ #define XEMACPS_MSBBUF_TXQBASE_OFFSET 0x000004C8U /**< MSB Buffer TX Q Base - reg */ + reg */ #define XEMACPS_MSBBUF_RXQBASE_OFFSET 0x000004D4U /**< MSB Buffer RX Q Base - reg */ + reg */ #define XEMACPS_INTQ1_IER_OFFSET 0x00000600U /**< Interrupt Q1 Enable - reg */ + reg */ #define XEMACPS_INTQ1_IDR_OFFSET 0x00000620U /**< Interrupt Q1 Disable - reg */ + reg */ #define XEMACPS_INTQ1_IMR_OFFSET 0x00000640U /**< Interrupt Q1 Mask - reg */ + reg */ /* Define some bit positions for registers. */ /** @name network control register bit definitions * @{ */ -#define XEMACPS_NWCTRL_FLUSH_DPRAM_MASK 0x00040000U /**< Flush a packet from - Rx SRAM */ +#define XEMACPS_NWCTRL_FLUSH_DPRAM_MASK 0x00040000U /**< Flush a packet from + Rx SRAM */ #define XEMACPS_NWCTRL_ZEROPAUSETX_MASK 0x00000800U /**< Transmit zero quantum pause frame */ #define XEMACPS_NWCTRL_PAUSETX_MASK 0x00000800U /**< Transmit pause frame */ @@ -382,23 +382,23 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, /** @name DMA control register bit definitions * @{ */ -#define XEMACPS_DMACR_ADDR_WIDTH_64 0x40000000U /**< 64 bit address bus */ -#define XEMACPS_DMACR_TXEXTEND_MASK 0x20000000U /**< Tx Extended desc mode */ -#define XEMACPS_DMACR_RXEXTEND_MASK 0x10000000U /**< Rx Extended desc mode */ -#define XEMACPS_DMACR_RXBUF_MASK 0x00FF0000U /**< Mask bit for RX buffer - size */ -#define XEMACPS_DMACR_RXBUF_SHIFT 16U /**< Shift bit for RX buffer - size */ -#define XEMACPS_DMACR_TCPCKSUM_MASK 0x00000800U /**< enable/disable TX +#define XEMACPS_DMACR_ADDR_WIDTH_64 0x40000000U /**< 64 bit address bus */ +#define XEMACPS_DMACR_TXEXTEND_MASK 0x20000000U /**< Tx Extended desc mode */ +#define XEMACPS_DMACR_RXEXTEND_MASK 0x10000000U /**< Rx Extended desc mode */ +#define XEMACPS_DMACR_RXBUF_MASK 0x00FF0000U /**< Mask bit for RX buffer + size */ +#define XEMACPS_DMACR_RXBUF_SHIFT 16U /**< Shift bit for RX buffer + size */ +#define XEMACPS_DMACR_TCPCKSUM_MASK 0x00000800U /**< enable/disable TX checksum offload */ -#define XEMACPS_DMACR_TXSIZE_MASK 0x00000400U /**< TX buffer memory size */ -#define XEMACPS_DMACR_RXSIZE_MASK 0x00000300U /**< RX buffer memory size */ -#define XEMACPS_DMACR_ENDIAN_MASK 0x00000080U /**< endian configuration */ -#define XEMACPS_DMACR_BLENGTH_MASK 0x0000001FU /**< buffer burst length */ -#define XEMACPS_DMACR_SINGLE_AHB_BURST 0x00000001U /**< single AHB bursts */ -#define XEMACPS_DMACR_INCR4_AHB_BURST 0x00000004U /**< 4 bytes AHB bursts */ -#define XEMACPS_DMACR_INCR8_AHB_BURST 0x00000008U /**< 8 bytes AHB bursts */ -#define XEMACPS_DMACR_INCR16_AHB_BURST 0x00000010U /**< 16 bytes AHB bursts */ +#define XEMACPS_DMACR_TXSIZE_MASK 0x00000400U /**< TX buffer memory size */ +#define XEMACPS_DMACR_RXSIZE_MASK 0x00000300U /**< RX buffer memory size */ +#define XEMACPS_DMACR_ENDIAN_MASK 0x00000080U /**< endian configuration */ +#define XEMACPS_DMACR_BLENGTH_MASK 0x0000001FU /**< buffer burst length */ +#define XEMACPS_DMACR_SINGLE_AHB_BURST 0x00000001U /**< single AHB bursts */ +#define XEMACPS_DMACR_INCR4_AHB_BURST 0x00000004U /**< 4 bytes AHB bursts */ +#define XEMACPS_DMACR_INCR8_AHB_BURST 0x00000008U /**< 8 bytes AHB bursts */ +#define XEMACPS_DMACR_INCR16_AHB_BURST 0x00000010U /**< 16 bytes AHB bursts */ /*@}*/ /** @name transmit status register bit definitions @@ -435,7 +435,7 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, (u32)XEMACPS_RXSR_RXOVR_MASK | \ (u32)XEMACPS_RXSR_BUFFNA_MASK) -#define XEMACPS_SR_ALL_MASK 0xFFFFFFFFU /**< Mask for full register */ +#define XEMACPS_SR_ALL_MASK 0xFFFFFFFFU /**< Mask for full register */ /*@}*/ @@ -443,8 +443,8 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, * @name Interrupt Q1 status register bit definitions * @{ */ -#define XEMACPS_INTQ1SR_TXCOMPL_MASK 0x00000080U /**< Transmit completed OK */ -#define XEMACPS_INTQ1SR_TXERR_MASK 0x00000040U /**< Transmit AMBA Error */ +#define XEMACPS_INTQ1SR_TXCOMPL_MASK 0x00000080U /**< Transmit completed OK */ +#define XEMACPS_INTQ1SR_TXERR_MASK 0x00000040U /**< Transmit AMBA Error */ #define XEMACPS_INTQ1_IXR_ALL_MASK ((u32)XEMACPS_INTQ1SR_TXCOMPL_MASK | \ (u32)XEMACPS_INTQ1SR_TXERR_MASK) @@ -457,15 +457,15 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, * XEMACPS_IER_OFFSET, XEMACPS_IDR_OFFSET, and XEMACPS_IMR_OFFSET * @{ */ -#define XEMACPS_IXR_PTPPSTX_MASK 0x02000000U /**< PTP Pdelay_resp TXed */ -#define XEMACPS_IXR_PTPPDRTX_MASK 0x01000000U /**< PTP Pdelay_req TXed */ -#define XEMACPS_IXR_PTPPSRX_MASK 0x00800000U /**< PTP Pdelay_resp RXed */ -#define XEMACPS_IXR_PTPPDRRX_MASK 0x00400000U /**< PTP Pdelay_req RXed */ +#define XEMACPS_IXR_PTPPSTX_MASK 0x02000000U /**< PTP Pdelay_resp TXed */ +#define XEMACPS_IXR_PTPPDRTX_MASK 0x01000000U /**< PTP Pdelay_req TXed */ +#define XEMACPS_IXR_PTPPSRX_MASK 0x00800000U /**< PTP Pdelay_resp RXed */ +#define XEMACPS_IXR_PTPPDRRX_MASK 0x00400000U /**< PTP Pdelay_req RXed */ -#define XEMACPS_IXR_PTPSTX_MASK 0x00200000U /**< PTP Sync TXed */ -#define XEMACPS_IXR_PTPDRTX_MASK 0x00100000U /**< PTP Delay_req TXed */ -#define XEMACPS_IXR_PTPSRX_MASK 0x00080000U /**< PTP Sync RXed */ -#define XEMACPS_IXR_PTPDRRX_MASK 0x00040000U /**< PTP Delay_req RXed */ +#define XEMACPS_IXR_PTPSTX_MASK 0x00200000U /**< PTP Sync TXed */ +#define XEMACPS_IXR_PTPDRTX_MASK 0x00100000U /**< PTP Delay_req TXed */ +#define XEMACPS_IXR_PTPSRX_MASK 0x00080000U /**< PTP Sync RXed */ +#define XEMACPS_IXR_PTPDRRX_MASK 0x00040000U /**< PTP Delay_req RXed */ #define XEMACPS_IXR_PAUSETX_MASK 0x00004000U /**< Pause frame transmitted */ #define XEMACPS_IXR_PAUSEZERO_MASK 0x00002000U /**< Pause time has reached @@ -511,9 +511,9 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, /** @name RX watermark bit definitions * @{ */ -#define XEMACPS_RXWM_HIGH_MASK 0x0000FFFFU /**< RXWM high mask */ -#define XEMACPS_RXWM_LOW_MASK 0xFFFF0000U /**< RXWM low mask */ -#define XEMACPS_RXWM_LOW_SHFT_MSK 16U /**< Shift for RXWM low */ +#define XEMACPS_RXWM_HIGH_MASK 0x0000FFFFU /**< RXWM high mask */ +#define XEMACPS_RXWM_LOW_MASK 0xFFFF0000U /**< RXWM low mask */ +#define XEMACPS_RXWM_LOW_SHFT_MSK 16U /**< Shift for RXWM low */ /*@}*/ /* Transmit buffer descriptor status words offset diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c index cd9335ace6..f1af7b8613 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c @@ -77,34 +77,34 @@ * *****************************************************************************/ LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType, - void *FuncPointer, void *CallBackRef) + void *FuncPointer, void *CallBackRef) { - LONG Status; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(FuncPointer != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(FuncPointer != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - switch (HandlerType) { - case XEMACPS_HANDLER_DMASEND: - Status = (LONG)(XST_SUCCESS); - InstancePtr->SendHandler = ((XEmacPs_Handler)(void *)FuncPointer); - InstancePtr->SendRef = CallBackRef; - break; - case XEMACPS_HANDLER_DMARECV: - Status = (LONG)(XST_SUCCESS); - InstancePtr->RecvHandler = ((XEmacPs_Handler)(void *)FuncPointer); - InstancePtr->RecvRef = CallBackRef; - break; - case XEMACPS_HANDLER_ERROR: - Status = (LONG)(XST_SUCCESS); - InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void *)FuncPointer); - InstancePtr->ErrorRef = CallBackRef; - break; - default: - Status = (LONG)(XST_INVALID_PARAM); - break; + switch (HandlerType) { + case XEMACPS_HANDLER_DMASEND: + Status = (LONG)(XST_SUCCESS); + InstancePtr->SendHandler = ((XEmacPs_Handler)(void *)FuncPointer); + InstancePtr->SendRef = CallBackRef; + break; + case XEMACPS_HANDLER_DMARECV: + Status = (LONG)(XST_SUCCESS); + InstancePtr->RecvHandler = ((XEmacPs_Handler)(void *)FuncPointer); + InstancePtr->RecvRef = CallBackRef; + break; + case XEMACPS_HANDLER_ERROR: + Status = (LONG)(XST_SUCCESS); + InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void *)FuncPointer); + InstancePtr->ErrorRef = CallBackRef; + break; + default: + Status = (LONG)(XST_INVALID_PARAM); + break; } - return Status; + return Status; } /*****************************************************************************/ @@ -121,93 +121,93 @@ LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType, ******************************************************************************/ void XEmacPs_IntrHandler(void *XEmacPsPtr) { - u32 RegISR; - u32 RegSR; - u32 RegCtrl; - u32 RegQ1ISR = 0U; - XEmacPs *InstancePtr = (XEmacPs *) XEmacPsPtr; + u32 RegISR; + u32 RegSR; + u32 RegCtrl; + u32 RegQ1ISR = 0U; + XEmacPs *InstancePtr = (XEmacPs *) XEmacPsPtr; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); /* This ISR will try to handle as many interrupts as it can in a single * call. However, in most of the places where the user's error handler * is called, this ISR exits because it is expected that the user will * reset the device in nearly all instances. */ - RegISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + RegISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET); /* Read Transmit Q1 ISR */ - if (InstancePtr->Version > 2) - RegQ1ISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + if (InstancePtr->Version > 2) + RegQ1ISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_INTQ1_STS_OFFSET); /* Clear the interrupt status register */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, RegISR); /* Receive complete interrupt */ - if ((RegISR & XEMACPS_IXR_FRAMERX_MASK) != 0x00000000U) { + if ((RegISR & XEMACPS_IXR_FRAMERX_MASK) != 0x00000000U) { /* Clear RX status register RX complete indication but preserve * error bits if there is any */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_RXSR_OFFSET, ((u32)XEMACPS_RXSR_FRAMERX_MASK | (u32)XEMACPS_RXSR_BUFFNA_MASK)); - InstancePtr->RecvHandler(InstancePtr->RecvRef); + InstancePtr->RecvHandler(InstancePtr->RecvRef); } /* Transmit Q1 complete interrupt */ - if ((InstancePtr->Version > 2) && + if ((InstancePtr->Version > 2) && ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) { /* Clear TX status register TX complete indication but preserve * error bits if there is any */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_INTQ1_STS_OFFSET, XEMACPS_INTQ1SR_TXCOMPL_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_TXSR_OFFSET, ((u32)XEMACPS_TXSR_TXCOMPL_MASK | (u32)XEMACPS_TXSR_USEDREAD_MASK)); - InstancePtr->SendHandler(InstancePtr->SendRef); + InstancePtr->SendHandler(InstancePtr->SendRef); } /* Transmit complete interrupt */ - if ((RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U) { + if ((RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U) { /* Clear TX status register TX complete indication but preserve * error bits if there is any */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_TXSR_OFFSET, ((u32)XEMACPS_TXSR_TXCOMPL_MASK | (u32)XEMACPS_TXSR_USEDREAD_MASK)); - InstancePtr->SendHandler(InstancePtr->SendRef); + InstancePtr->SendHandler(InstancePtr->SendRef); } /* Receive error conditions interrupt */ - if ((RegISR & XEMACPS_IXR_RX_ERR_MASK) != 0x00000000U) { + if ((RegISR & XEMACPS_IXR_RX_ERR_MASK) != 0x00000000U) { /* Clear RX status register */ - RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_RXSR_OFFSET); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_RXSR_OFFSET, RegSR); /* Fix for CR # 692702. Write to bit 18 of net_ctrl * register to flush a packet out of Rx SRAM upon * an error for receive buffer not available. */ - if ((RegISR & XEMACPS_IXR_RXUSED_MASK) != 0x00000000U) { - RegCtrl = - XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - RegCtrl |= (u32)XEMACPS_NWCTRL_FLUSH_DPRAM_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, RegCtrl); + if ((RegISR & XEMACPS_IXR_RXUSED_MASK) != 0x00000000U) { + RegCtrl = + XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + RegCtrl |= (u32)XEMACPS_NWCTRL_FLUSH_DPRAM_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, RegCtrl); } - if(RegSR != 0) { - InstancePtr->ErrorHandler(InstancePtr->ErrorRef, - XEMACPS_RECV, RegSR); + if(RegSR != 0) { + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, + XEMACPS_RECV, RegSR); } } @@ -220,9 +220,9 @@ void XEmacPs_IntrHandler(void *XEmacPsPtr) ((RegQ1ISR & XEMACPS_INTQ1SR_TXERR_MASK) != 0x00000000U) && ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) { /* Clear Interrupt Q1 status register */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_INTQ1_STS_OFFSET, RegQ1ISR); - InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, RegQ1ISR); } @@ -230,11 +230,11 @@ void XEmacPs_IntrHandler(void *XEmacPsPtr) if (((RegISR & XEMACPS_IXR_TX_ERR_MASK) != 0x00000000U) && (!(RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U)) { /* Clear TX status register */ - RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_TXSR_OFFSET); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_TXSR_OFFSET, RegSR); - InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, RegSR); } diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c index a16201e939..9f0781d531 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c @@ -56,16 +56,16 @@ extern XEmacPs_Config XEmacPs_ConfigTable[XPAR_XEMACPS_NUM_INSTANCES]; ******************************************************************************/ XEmacPs_Config *XEmacPs_LookupConfig(u16 DeviceId) { - XEmacPs_Config *CfgPtr = NULL; - u32 i; + XEmacPs_Config *CfgPtr = NULL; + u32 i; - for (i = 0U; i < (u32)XPAR_XEMACPS_NUM_INSTANCES; i++) { - if (XEmacPs_ConfigTable[i].DeviceId == DeviceId) { - CfgPtr = &XEmacPs_ConfigTable[i]; - break; + for (i = 0U; i < (u32)XPAR_XEMACPS_NUM_INSTANCES; i++) { + if (XEmacPs_ConfigTable[i].DeviceId == DeviceId) { + CfgPtr = &XEmacPs_ConfigTable[i]; + break; } } - return (XEmacPs_Config *)(CfgPtr); + return (XEmacPs_Config *)(CfgPtr); } /** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c index 7a318e3819..f0f43a1299 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c @@ -25,7 +25,7 @@ * for output pins on all banks during initialization. * 2.1 hk 04/29/14 Use Input data register DATA_RO for read. CR# 771667. * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. -* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980. +* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980. * 3.1 aru 07/13/18 Resolved doxygen reported warnings. CR# 1006331. * 3.4 aru 08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751 * 3.5 sne 03/01/19 Fixes violations according to MISRAC-2012 @@ -61,50 +61,50 @@ extern void StubHandler(void *CallBackRef, u32 Bank, u32 Status); * All members of the XGpioPs instance structure are initialized and * StubHandlers are assigned to the Bank Status Handlers. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param ConfigPtr points to the XGpioPs device configuration structure. -* @param EffectiveAddr is the device base address in the virtual memory -* address space. If the address translation is not used then the -* physical address should be passed. -* Unexpected errors may occur if the address mapping is changed -* after this function is invoked. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param ConfigPtr points to the XGpioPs device configuration structure. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. If the address translation is not used then the +* physical address should be passed. +* Unexpected errors may occur if the address mapping is changed +* after this function is invoked. * -* @return XST_SUCCESS always. +* @return XST_SUCCESS always. * -* @note None. +* @note None. * ******************************************************************************/ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, - u32 EffectiveAddr) + u32 EffectiveAddr) { - s32 Status = XST_SUCCESS; - u8 i; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(ConfigPtr != NULL); - Xil_AssertNonvoid(EffectiveAddr != (u32)0); + s32 Status = XST_SUCCESS; + u8 i; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + Xil_AssertNonvoid(EffectiveAddr != (u32)0); /* * Set some default values for instance data, don't indicate the device * is ready to use until everything has been initialized successfully. */ - InstancePtr->IsReady = 0U; - InstancePtr->GpioConfig.BaseAddr = EffectiveAddr; - InstancePtr->GpioConfig.DeviceId = ConfigPtr->DeviceId; - InstancePtr->Handler = (XGpioPs_Handler)StubHandler; - InstancePtr->Platform = XGetPlatform_Info(); + InstancePtr->IsReady = 0U; + InstancePtr->GpioConfig.BaseAddr = EffectiveAddr; + InstancePtr->GpioConfig.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Handler = (XGpioPs_Handler)StubHandler; + InstancePtr->Platform = XGetPlatform_Info(); /* Initialize the Bank data based on platform */ - if (InstancePtr->Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + if (InstancePtr->Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { /* - * Max pins in the ZynqMP GPIO device - * 0 - 25, Bank 0 - * 26 - 51, Bank 1 - * 52 - 77, Bank 2 - * 78 - 109, Bank 3 - * 110 - 141, Bank 4 - * 142 - 173, Bank 5 + * Max pins in the ZynqMP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 */ - InstancePtr->MaxPinNum = (u32)174; - InstancePtr->MaxBanks = (u8)6; + InstancePtr->MaxPinNum = (u32)174; + InstancePtr->MaxBanks = (u8)6; } else if (InstancePtr->Platform == (u32)XPLAT_VERSAL) { @@ -131,21 +131,21 @@ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, } else { /* - * Max pins in the GPIO device - * 0 - 31, Bank 0 - * 32 - 53, Bank 1 - * 54 - 85, Bank 2 - * 86 - 117, Bank 3 + * Max pins in the GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 */ - InstancePtr->MaxPinNum = (u32)118; - InstancePtr->MaxBanks = (u8)4; + InstancePtr->MaxPinNum = (u32)118; + InstancePtr->MaxBanks = (u8)4; } /* * By default, interrupts are not masked in GPIO. Disable * interrupts for all pins in all the 4 banks. */ - for (i=(u8)0U;iMaxBanks;i++) { + for (i=(u8)0U;iMaxBanks;i++) { if (InstancePtr->Platform == XPLAT_VERSAL){ if(InstancePtr->PmcGpio == (u32)FALSE) { @@ -171,16 +171,16 @@ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, } else { - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); } } /* Indicate the component is now ready to use. */ - InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; - return Status; + return Status; } /****************************************************************************/ @@ -188,20 +188,20 @@ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, * * Read the Data register of the specified GPIO bank. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * -* @return Current value of the Data register. +* @return Current value of the Data register. * -* @note This function is used for reading the state of all the GPIO pins -* of specified bank. +* @note This function is used for reading the state of all the GPIO pins +* of specified bank. * *****************************************************************************/ u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank) { - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { @@ -211,7 +211,7 @@ u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank) } #endif - return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + XGPIOPS_DATA_RO_OFFSET); } @@ -221,33 +221,33 @@ u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank) * * Read Data from the specified pin. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Pin is the pin number for which the data has to be read. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. -* See xgpiops.h for the mapping of the pin numbers in the banks. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the data has to be read. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* See xgpiops.h for the mapping of the pin numbers in the banks. * -* @return Current value of the Pin (0 or 1). +* @return Current value of the Pin (0 or 1). * -* @note This function is used for reading the state of the specified -* GPIO pin. +* @note This function is used for reading the state of the specified +* GPIO pin. * *****************************************************************************/ u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin) { - u8 Bank; - u8 PinNumber; + u8 Bank; + u8 PinNumber; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + XGPIOPS_DATA_RO_OFFSET) >> (u32)PinNumber) & (u32)1; @@ -258,21 +258,21 @@ u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin) * * Write to the Data register of the specified GPIO bank. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. -* @param Data is the value to be written to the Data register. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Data is the value to be written to the Data register. * -* @return None. +* @return None. * -* @note This function is used for writing to all the GPIO pins of -* the bank. The previous state of the pins is not maintained. +* @note This function is used for writing to all the GPIO pins of +* the bank. The previous state of the pins is not maintained. * *****************************************************************************/ void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { @@ -282,7 +282,7 @@ void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data) } #endif - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + XGPIOPS_DATA_OFFSET, Data); } @@ -292,52 +292,52 @@ void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data) * * Write data to the specified pin. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Pin is the pin number to which the Data is to be written. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. -* @param Data is the data to be written to the specified pin (0 or 1). +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param Data is the data to be written to the specified pin (0 or 1). * -* @return None. +* @return None. * -* @note This function does a masked write to the specified pin of -* the specified GPIO bank. The previous state of other pins -* is maintained. +* @note This function does a masked write to the specified pin of +* the specified GPIO bank. The previous state of other pins +* is maintained. * *****************************************************************************/ void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data) { - u32 RegOffset; - u32 Value; - u8 Bank; - u8 PinNumber; - u32 DataVar = Data; + u32 RegOffset; + u32 Value; + u8 Bank; + u8 PinNumber; + u32 DataVar = Data; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - if (PinNumber > 15U) { + if (PinNumber > 15U) { /* There are only 16 data bits in bit maskable register. */ - PinNumber -= (u8)16; - RegOffset = XGPIOPS_DATA_MSW_OFFSET; + PinNumber -= (u8)16; + RegOffset = XGPIOPS_DATA_MSW_OFFSET; } else { - RegOffset = XGPIOPS_DATA_LSW_OFFSET; + RegOffset = XGPIOPS_DATA_LSW_OFFSET; } /* * Get the 32 bit value to be written to the Mask/Data register where * the upper 16 bits is the mask and lower 16 bits is the data. */ - DataVar &= (u32)0x01; - Value = ~((u32)1 << (PinNumber + 16U)) & ((DataVar << PinNumber) | 0xFFFF0000U); - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + DataVar &= (u32)0x01; + Value = ~((u32)1 << (PinNumber + 16U)) & ((DataVar << PinNumber) | 0xFFFF0000U); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) + RegOffset, Value); @@ -350,24 +350,24 @@ void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data) * * Set the Direction of the pins of the specified GPIO Bank. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. -* @param Direction is the 32 bit mask of the Pin direction to be set for -* all the pins in the Bank. Bits with 0 are set to Input mode, -* bits with 1 are set to Output Mode. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Direction is the 32 bit mask of the Pin direction to be set for +* all the pins in the Bank. Bits with 0 are set to Input mode, +* bits with 1 are set to Output Mode. * -* @return None. +* @return None. * -* @note This function is used for setting the direction of all the pins -* in the specified bank. The previous state of the pins is -* not maintained. +* @note This function is used for setting the direction of all the pins +* in the specified bank. The previous state of the pins is +* not maintained. * *****************************************************************************/ void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { @@ -377,7 +377,7 @@ void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction) } #endif - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_DIRM_OFFSET, Direction); } @@ -387,43 +387,43 @@ void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction) * * Set the Direction of the specified pin. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Pin is the pin number to which the Data is to be written. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. -* @param Direction is the direction to be set for the specified pin. -* Valid values are 0 for Input Direction, 1 for Output Direction. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param Direction is the direction to be set for the specified pin. +* Valid values are 0 for Input Direction, 1 for Output Direction. * -* @return None. +* @return None. * *****************************************************************************/ void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction) { - u8 Bank; - u8 PinNumber; - u32 DirModeReg; + u8 Bank; + u8 PinNumber; + u32 DirModeReg; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); - Xil_AssertVoid(Direction <= (u32)1); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(Direction <= (u32)1); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - DirModeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + DirModeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_DIRM_OFFSET); - if (Direction!=(u32)0) { /* Output Direction */ - DirModeReg |= ((u32)1 << (u32)PinNumber); + if (Direction!=(u32)0) { /* Output Direction */ + DirModeReg |= ((u32)1 << (u32)PinNumber); } else { /* Input Direction */ - DirModeReg &= ~ ((u32)1 << (u32)PinNumber); + DirModeReg &= ~ ((u32)1 << (u32)PinNumber); } - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_DIRM_OFFSET, DirModeReg); } @@ -433,20 +433,20 @@ void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction) * * Get the Direction of the pins of the specified GPIO Bank. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * -* @return Returns a 32 bit mask of the Direction register. Bits with 0 are -* in Input mode, bits with 1 are in Output Mode. +* @return Returns a 32 bit mask of the Direction register. Bits with 0 are +* in Input mode, bits with 1 are in Output Mode. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank) { - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { @@ -456,9 +456,9 @@ u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank) } #endif - return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_DIRM_OFFSET); + XGPIOPS_DIRM_OFFSET); } /****************************************************************************/ @@ -466,35 +466,35 @@ u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank) * * Get the Direction of the specified pin. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Pin is the pin number for which the Direction is to be -* retrieved. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the Direction is to be +* retrieved. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * -* @return Direction of the specified pin. +* @return Direction of the specified pin. * - 0 for Input Direction * - 1 for Output Direction * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin) { - u8 Bank; - u8 PinNumber; + u8 Bank; + u8 PinNumber; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_DIRM_OFFSET) >> (u32)PinNumber) & (u32)1; } @@ -504,24 +504,24 @@ u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin) * * Set the Output Enable of the pins of the specified GPIO Bank. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. -* @param OpEnable is the 32 bit mask of the Output Enables to be set for -* all the pins in the Bank. The Output Enable of bits with 0 are -* disabled, the Output Enable of bits with 1 are enabled. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param OpEnable is the 32 bit mask of the Output Enables to be set for +* all the pins in the Bank. The Output Enable of bits with 0 are +* disabled, the Output Enable of bits with 1 are enabled. * -* @return None. +* @return None. * -* @note This function is used for setting the Output Enables of all the -* pins in the specified bank. The previous state of the Output -* Enables is not maintained. +* @note This function is used for setting the Output Enables of all the +* pins in the specified bank. The previous state of the Output +* Enables is not maintained. * *****************************************************************************/ void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { @@ -531,7 +531,7 @@ void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable) } #endif - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_OUTEN_OFFSET, OpEnable); } @@ -541,48 +541,48 @@ void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable) * * Set the Output Enable of the specified pin. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Pin is the pin number to which the Data is to be written. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. -* @param OpEnable specifies whether the Output Enable for the specified -* pin should be enabled. -* Valid values are 0 for Disabling Output Enable, -* 1 for Enabling Output Enable. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param OpEnable specifies whether the Output Enable for the specified +* pin should be enabled. +* Valid values are 0 for Disabling Output Enable, +* 1 for Enabling Output Enable. * -* @return None. +* @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable) { - u8 Bank; - u8 PinNumber; - u32 OpEnableReg; + u8 Bank; + u8 PinNumber; + u32 OpEnableReg; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); - Xil_AssertVoid(OpEnable <= (u32)1); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(OpEnable <= (u32)1); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - OpEnableReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + OpEnableReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_OUTEN_OFFSET); - if (OpEnable != (u32)0) { /* Enable Output Enable */ - OpEnableReg |= ((u32)1 << (u32)PinNumber); + if (OpEnable != (u32)0) { /* Enable Output Enable */ + OpEnableReg |= ((u32)1 << (u32)PinNumber); } else { /* Disable Output Enable */ - OpEnableReg &= ~ ((u32)1 << (u32)PinNumber); + OpEnableReg &= ~ ((u32)1 << (u32)PinNumber); } - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_OUTEN_OFFSET, OpEnableReg); } @@ -591,21 +591,21 @@ void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnabl * * Get the Output Enable status of the pins of the specified GPIO Bank. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * -* @return Returns a a 32 bit mask of the Output Enable register. -* Bits with 0 are in Disabled state, bits with 1 are in -* Enabled State. +* @return Returns a a 32 bit mask of the Output Enable register. +* Bits with 0 are in Disabled state, bits with 1 are in +* Enabled State. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank) { - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { @@ -615,9 +615,9 @@ u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank) } #endif - return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_OUTEN_OFFSET); + XGPIOPS_OUTEN_OFFSET); } /****************************************************************************/ @@ -625,35 +625,35 @@ u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank) * * Get the Output Enable status of the specified pin. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Pin is the pin number for which the Output Enable status is to -* be retrieved. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the Output Enable status is to +* be retrieved. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * -* @return Output Enable of the specified pin. +* @return Output Enable of the specified pin. * - 0 if Output Enable is disabled for this pin * - 1 if Output Enable is enabled for this pin * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin) { - u8 Bank; - u8 PinNumber; + u8 Bank; + u8 PinNumber; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_OUTEN_OFFSET) >> (u32)PinNumber) & (u32)1; } @@ -664,14 +664,14 @@ u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin) * Get the Bank number and the Pin number in the Bank, for the given PinNumber * in the GPIO device. * -* @param PinNumber is the Pin number in the GPIO device. -* @param BankNumber returns the Bank in which this GPIO pin is present. -* Valid values are 0 to XGPIOPS_MAX_BANKS - 1. -* @param PinNumberInBank returns the Pin Number within the Bank. +* @param PinNumber is the Pin number in the GPIO device. +* @param BankNumber returns the Bank in which this GPIO pin is present. +* Valid values are 0 to XGPIOPS_MAX_BANKS - 1. +* @param PinNumberInBank returns the Pin Number within the Bank. * -* @return None. +* @return None. * -* @note None. +* @note None. * *****************************************************************************/ #ifdef versal @@ -680,29 +680,29 @@ void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber, u8 *BankNumber, void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank) #endif { - u32 XGpioPsPinTable[6] = {0}; + u32 XGpioPsPinTable[6] = {0}; #ifdef versal u8 i=(u8)0; #endif - u32 Platform = XGetPlatform_Info(); + u32 Platform = XGetPlatform_Info(); - if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { /* * This structure defines the mapping of the pin numbers to the banks when * the driver APIs are used for working on the individual pins. */ - XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ - XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */ - XGpioPsPinTable[2] = (u32)77; /* 52 - 77, Bank 2 */ - XGpioPsPinTable[3] = (u32)109; /* 78 - 109, Bank 3 */ - XGpioPsPinTable[4] = (u32)141; /* 110 - 141, Bank 4 */ - XGpioPsPinTable[5] = (u32)173; /* 142 - 173 Bank 5 */ + XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ + XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */ + XGpioPsPinTable[2] = (u32)77; /* 52 - 77, Bank 2 */ + XGpioPsPinTable[3] = (u32)109; /* 78 - 109, Bank 3 */ + XGpioPsPinTable[4] = (u32)141; /* 110 - 141, Bank 4 */ + XGpioPsPinTable[5] = (u32)173; /* 142 - 173 Bank 5 */ *BankNumber = 0U; - while (*BankNumber < XGPIOPS_SIX) { - if (PinNumber <= XGpioPsPinTable[*BankNumber]) { - break; + while (*BankNumber < XGPIOPS_SIX) { + if (PinNumber <= XGpioPsPinTable[*BankNumber]) { + break; } (*BankNumber)++; } @@ -760,20 +760,20 @@ void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank) } #endif else { - XGpioPsPinTable[0] = (u32)31; /* 0 - 31, Bank 0 */ - XGpioPsPinTable[1] = (u32)53; /* 32 - 53, Bank 1 */ - XGpioPsPinTable[2] = (u32)85; /* 54 - 85, Bank 2 */ - XGpioPsPinTable[3] = (u32)117; /* 86 - 117 Bank 3 */ + XGpioPsPinTable[0] = (u32)31; /* 0 - 31, Bank 0 */ + XGpioPsPinTable[1] = (u32)53; /* 32 - 53, Bank 1 */ + XGpioPsPinTable[2] = (u32)85; /* 54 - 85, Bank 2 */ + XGpioPsPinTable[3] = (u32)117; /* 86 - 117 Bank 3 */ *BankNumber = 0U; - while (*BankNumber < XGPIOPS_FOUR) { - if (PinNumber <= XGpioPsPinTable[*BankNumber]) { - break; + while (*BankNumber < XGPIOPS_FOUR) { + if (PinNumber <= XGpioPsPinTable[*BankNumber]) { + break; } (*BankNumber)++; } } - if (*BankNumber == (u8)0) { + if (*BankNumber == (u8)0) { *PinNumberInBank = PinNumber; } diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h index b030e60686..4f5374297c 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h @@ -67,10 +67,10 @@ * for output pins on all banks during initialization. * 1.02a hk 08/22/13 Added low level reset API * 2.1 hk 04/29/14 Use Input data register DATA_RO for read. CR# 771667. -* 2.2 sk 10/13/14 Used Pin number in Bank instead of pin number +* 2.2 sk 10/13/14 Used Pin number in Bank instead of pin number * passed to APIs. CR# 822636 * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. -* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980. +* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980. * ms 03/17/17 Added readme.txt file in examples folder for doxygen * generation. * ms 04/05/17 Added tabspace for return statements in functions of @@ -89,9 +89,9 @@ * 3.5 sne 03/14/19 Added Versal support. * 3.6 mus 04/05/19 Replaced XPLAT_versal macro with XPLAT_VERSAL, to be in * sync with standalone BSP -* 3.6 sne 06/12/19 Fixed IAR compiler warning. +* 3.6 sne 06/12/19 Fixed IAR compiler warning. * 3.6 sne 08/14/19 Added interrupt handler support on versal. -* 3.7 sne 12/04/19 Reverted versal examples support. +* 3.7 sne 12/04/19 Reverted versal examples support. * *
* @@ -116,43 +116,43 @@ extern "C" { * The following constants define the interrupt types that can be set for each * GPIO pin. */ -#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0x00U /**< Interrupt on Rising edge */ -#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 0x01U /**< Interrupt Falling edge */ -#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 0x02U /**< Interrupt on both edges */ -#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 0x03U /**< Interrupt on high level */ -#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 0x04U /**< Interrupt on low level */ +#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0x00U /**< Interrupt on Rising edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 0x01U /**< Interrupt Falling edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 0x02U /**< Interrupt on both edges */ +#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 0x03U /**< Interrupt on high level */ +#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 0x04U /**< Interrupt on low level */ /*@}*/ #define XGPIOPS_BANK_MAX_PINS (u32)32 /**< Max pins in a GPIO bank */ -#define XGPIOPS_BANK0 0x00U /**< GPIO Bank 0 */ -#define XGPIOPS_BANK1 0x01U /**< GPIO Bank 1 */ -#define XGPIOPS_BANK2 0x02U /**< GPIO Bank 2 */ -#define XGPIOPS_BANK3 0x03U /**< GPIO Bank 3 */ +#define XGPIOPS_BANK0 0x00U /**< GPIO Bank 0 */ +#define XGPIOPS_BANK1 0x01U /**< GPIO Bank 1 */ +#define XGPIOPS_BANK2 0x02U /**< GPIO Bank 2 */ +#define XGPIOPS_BANK3 0x03U /**< GPIO Bank 3 */ #ifdef XPAR_PSU_GPIO_0_BASEADDR -#define XGPIOPS_BANK4 0x04U /**< GPIO Bank 4 */ -#define XGPIOPS_BANK5 0x05U /**< GPIO Bank 5 */ +#define XGPIOPS_BANK4 0x04U /**< GPIO Bank 4 */ +#define XGPIOPS_BANK5 0x05U /**< GPIO Bank 5 */ #endif -#define XGPIOPS_MAX_BANKS_ZYNQMP 0x06U /**< Max banks in a - * Zynq Ultrascale+ MP GPIO device +#define XGPIOPS_MAX_BANKS_ZYNQMP 0x06U /**< Max banks in a + * Zynq Ultrascale+ MP GPIO device */ -#define XGPIOPS_MAX_BANKS 0x04U /**< Max banks in a Zynq GPIO device */ +#define XGPIOPS_MAX_BANKS 0x04U /**< Max banks in a Zynq GPIO device */ #define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP (u32)174 /**< Max pins in the - * Zynq Ultrascale+ MP GPIO device + * Zynq Ultrascale+ MP GPIO device * 0 - 25, Bank 0 * 26 - 51, Bank 1 - * 52 - 77, Bank 2 - * 78 - 109, Bank 3 - * 110 - 141, Bank 4 - * 142 - 173, Bank 5 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 */ #define XGPIOPS_DEVICE_MAX_PIN_NUM (u32)118 /**< Max pins in the Zynq GPIO device * 0 - 31, Bank 0 * 32 - 53, Bank 1 - * 54 - 85, Bank 2 - * 86 - 117, Bank 3 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 */ /**************************** Type Definitions *******************************/ @@ -165,13 +165,13 @@ extern "C" { * driven mode. The handler executes in an interrupt context such that minimal * processing should be performed. * - * @param CallBackRef is a callback reference passed in by the upper layer - * when setting the callback functions for a GPIO bank. It is - * passed back to the upper layer when the callback is invoked. Its - * type is not important to the driver component, so it is a void - * pointer. - * @param Bank is the bank for which the interrupt status has changed. - * @param Status is the Interrupt status of the GPIO bank. + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the callback functions for a GPIO bank. It is + * passed back to the upper layer when the callback is invoked. Its + * type is not important to the driver component, so it is a void + * pointer. + * @param Bank is the bank for which the interrupt status has changed. + * @param Status is the Interrupt status of the GPIO bank. * *****************************************************************************/ typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status); @@ -180,8 +180,8 @@ typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status); * This typedef contains configuration information for a device. */ typedef struct { - u16 DeviceId; /**< Unique ID of device */ - u32 BaseAddr; /**< Register base address */ + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Register base address */ } XGpioPs_Config; /** @@ -190,13 +190,13 @@ typedef struct { * to a variable of this type is then passed to the driver API functions. */ typedef struct { - XGpioPs_Config GpioConfig; /**< Device configuration */ - u32 IsReady; /**< Device is initialized and ready */ - XGpioPs_Handler Handler; /**< Status handlers for all banks */ - void *CallBackRef; /**< Callback ref for bank handlers */ - u32 Platform; /**< Platform data */ - u32 MaxPinNum; /**< Max pins in the GPIO device */ - u8 MaxBanks; /**< Max banks in a GPIO device */ + XGpioPs_Config GpioConfig; /**< Device configuration */ + u32 IsReady; /**< Device is initialized and ready */ + XGpioPs_Handler Handler; /**< Status handlers for all banks */ + void *CallBackRef; /**< Callback ref for bank handlers */ + u32 Platform; /**< Platform data */ + u32 MaxPinNum; /**< Max pins in the GPIO device */ + u8 MaxBanks; /**< Max banks in a GPIO device */ u32 PmcGpio; /**< Flag for accessing PS GPIO for versal*/ } XGpioPs; diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c index 43f53df958..71c225084d 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c @@ -6,9 +6,9 @@ * DO NOT EDIT. * * Copyright (C) 2010-2020 Xilinx, Inc. All Rights Reserved. -* SPDX-License-Identifier: MIT +* SPDX-License-Identifier: MIT -* +* * Description: Driver configuration * *******************************************************************/ @@ -23,8 +23,8 @@ XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES] = { { - XPAR_PSU_GPIO_0_DEVICE_ID, - XPAR_PSU_GPIO_0_BASEADDR + XPAR_PSU_GPIO_0_DEVICE_ID, + XPAR_PSU_GPIO_0_BASEADDR } }; diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c index 86ed7e868e..38fee0848b 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c @@ -19,7 +19,7 @@ * ----- ---- -------- ----------------------------------------------- * 1.02a hk 08/22/13 First Release * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. -* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980. +* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980. * 3.5 sne 03/01/19 Fixes violations according to MISRAC-2012 * in safety mode and modified the code such as * Use of mixed mode arithmetic,Declared the pointer param @@ -52,19 +52,19 @@ * This function resets the GPIO module by writing reset values to * all registers * -* @param Base address of GPIO module +* @param Base address of GPIO module * -* @return None +* @return None * -* @note None. +* @note None. * ******************************************************************************/ void XGpioPs_ResetHw(u32 BaseAddress) { - u32 BankCount; - u32 Platform,MaxBanks; + u32 BankCount; + u32 Platform,MaxBanks; - Platform = XGetPlatform_Info(); + Platform = XGetPlatform_Info(); if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { MaxBanks = (u32)6; } diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h index bb22e2d59f..ba23e13882 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h @@ -23,7 +23,7 @@ * 1.02a hk 08/22/13 Added low level reset API function prototype and * related constant definitions * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. -* 3.1 kvn 04/13/15 Corrected reset values of banks. +* 3.1 kvn 04/13/15 Corrected reset values of banks. * 3.5 sne 03/14/19 Added versal support. *
* @@ -106,33 +106,33 @@ extern "C" { * * This macro reads the given register. * -* @param BaseAddr is the base address of the device. -* @param RegOffset is the register offset to be read. +* @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 +* @return The 32-bit value of the register * -* @note None. +* @note None. * *****************************************************************************/ #define XGpioPs_ReadReg(BaseAddr, RegOffset) \ - Xil_In32((BaseAddr) + (u32)(RegOffset)) + Xil_In32((BaseAddr) + (u32)(RegOffset)) /****************************************************************************/ /** * * This macro writes to the given register. * -* @param BaseAddr is the base address of the device. -* @param RegOffset is the offset of the register to be written. -* @param Data is the 32-bit value to write to the register. +* @param BaseAddr is the base address of the device. +* @param RegOffset is the offset of the register to be written. +* @param Data is the 32-bit value to write to the register. * -* @return None. +* @return None. * -* @note None. +* @note None. * *****************************************************************************/ #define XGpioPs_WriteReg(BaseAddr, RegOffset, Data) \ - Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) + Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) /************************** Function Prototypes ******************************/ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_intr.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_intr.c index c70de1aec6..43c8435c33 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_intr.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_intr.c @@ -18,10 +18,10 @@ * Ver Who Date Changes * ----- ---- -------- ----------------------------------------------- * 1.00a sv 01/18/10 First Release -* 2.2 sk 10/13/14 Used Pin number in Bank instead of pin number +* 2.2 sk 10/13/14 Used Pin number in Bank instead of pin number * passed to API's. CR# 822636 * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. -* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980. +* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980. * 3.1 aru 07/13/18 Ressolved doxygen reported warnings. CR# 1006331. * 3.4 aru 08/09/18 Ressolved cppcheck warnings. * 3.4 aru 08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751 @@ -32,7 +32,7 @@ * Literal value requires a U suffix. * 3.5 sne 03/14/19 Added Versal support. * 3.5 sne 03/20/19 Fixed multiple interrupts problem CR#1024556. -* 3.6 sne 06/12/19 Fixed IAR compiler warning. +* 3.6 sne 06/12/19 Fixed IAR compiler warning. * 3.6 sne 08/14/19 Added interrupt handler support on versal. * *
@@ -61,22 +61,22 @@ void StubHandler(const void *CallBackRef, u32 Bank, u32 Status); * This function enables the interrupts for the specified pins in the specified * bank. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. -* @param Mask is the bit mask of the pins for which interrupts are to -* be enabled. Bit positions of 1 will be enabled. Bit positions -* of 0 will keep the previous setting. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Mask is the bit mask of the pins for which interrupts are to +* be enabled. Bit positions of 1 will be enabled. Bit positions +* of 0 will keep the previous setting. * -* @return None. +* @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { @@ -86,7 +86,7 @@ void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) } #endif - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTEN_OFFSET, Mask); } @@ -96,34 +96,34 @@ void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) * * This function enables the interrupt for the specified pin. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Pin is the pin number for which the interrupt is to be enabled. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt is to be enabled. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * -* @return None. +* @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin) { - u8 Bank; - u8 PinNumber; - u32 IntrReg; + u8 Bank; + u8 PinNumber; + u32 IntrReg; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - IntrReg = ((u32)1 << (u32)PinNumber); - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + IntrReg = ((u32)1 << (u32)PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTEN_OFFSET, IntrReg); } @@ -134,23 +134,23 @@ void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin) * This function disables the interrupts for the specified pins in the specified * bank. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. -* @param Mask is the bit mask of the pins for which interrupts are -* to be disabled. Bit positions of 1 will be disabled. Bit -* positions of 0 will keep the previous setting. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Mask is the bit mask of the pins for which interrupts are +* to be disabled. Bit positions of 1 will be disabled. Bit +* positions of 0 will keep the previous setting. * -* @return None. +* @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Bank < InstancePtr->MaxBanks); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { Xil_AssertVoid(Bank != XGPIOPS_TWO); @@ -159,7 +159,7 @@ void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) } #endif - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTDIS_OFFSET, Mask); } @@ -169,34 +169,34 @@ void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) * * This function disables the interrupts for the specified pin. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Pin is the pin number for which the interrupt is to be disabled. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt is to be disabled. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * -* @return None. +* @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin) { - u8 Bank; - u8 PinNumber; - u32 IntrReg; + u8 Bank; + u8 PinNumber; + u32 IntrReg; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - IntrReg = ((u32)1 << (u32)PinNumber); - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + IntrReg = ((u32)1 << (u32)PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTDIS_OFFSET, IntrReg); } @@ -206,24 +206,24 @@ void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin) * * This function returns the interrupt enable status for a bank. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * -* @return Enabled interrupt(s) in a 32-bit format. Bit positions with 1 -* indicate that the interrupt for that pin is enabled, bit -* positions with 0 indicate that the interrupt for that pin is -* disabled. +* @return Enabled interrupt(s) in a 32-bit format. Bit positions with 1 +* indicate that the interrupt for that pin is enabled, bit +* positions with 0 indicate that the interrupt for that pin is +* disabled. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank) { - u32 IntrMask; + u32 IntrMask; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { @@ -233,10 +233,10 @@ u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank) } #endif - IntrMask = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + IntrMask = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTMASK_OFFSET); - return (~IntrMask); + return (~IntrMask); } /****************************************************************************/ @@ -244,40 +244,40 @@ u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank) * * This function returns whether interrupts are enabled for the specified pin. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Pin is the pin number for which the interrupt enable status -* is to be known. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt enable status +* is to be known. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * * @return * - TRUE if the interrupt is enabled. * - FALSE if the interrupt is disabled. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin) { - u8 Bank; - u8 PinNumber; - u32 IntrReg; + u8 Bank; + u8 PinNumber; + u32 IntrReg; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTMASK_OFFSET); - return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? FALSE : TRUE); + return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? FALSE : TRUE); } /****************************************************************************/ @@ -285,19 +285,19 @@ u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin) * * This function returns interrupt status read from Interrupt Status Register. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * -* @return The value read from Interrupt Status Register. +* @return The value read from Interrupt Status Register. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank) { - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { @@ -307,9 +307,9 @@ u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank) } #endif - return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTSTS_OFFSET); + XGPIOPS_INTSTS_OFFSET); } /****************************************************************************/ @@ -317,40 +317,40 @@ u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank) * * This function returns interrupt enable status of the specified pin. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Pin is the pin number for which the interrupt enable status -* is to be known. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt enable status +* is to be known. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * * @return * - TRUE if the interrupt has occurred. * - FALSE if the interrupt has not occurred. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin) { - u8 Bank; - u8 PinNumber; - u32 IntrReg; + u8 Bank; + u8 PinNumber; + u32 IntrReg; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTSTS_OFFSET); - return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? TRUE : FALSE); + return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? TRUE : FALSE); } /****************************************************************************/ @@ -360,21 +360,21 @@ u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin) * function should be called after the software has serviced the interrupts * that are pending. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. -* @param Mask is the mask of the interrupts to be cleared. Bit positions -* of 1 will be cleared. Bit positions of 0 will not change the -* previous interrupt status. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param Mask is the mask of the interrupts to be cleared. Bit positions +* of 1 will be cleared. Bit positions of 0 will not change the +* previous interrupt status. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Bank < InstancePtr->MaxBanks); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { Xil_AssertVoid(Bank != XGPIOPS_TWO); @@ -384,7 +384,7 @@ void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) #endif /* Clear the currently pending interrupts. */ - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTSTS_OFFSET, Mask); } @@ -395,37 +395,37 @@ void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) * This function clears the specified pending interrupt. This function should be * called after the software has serviced the interrupts that are pending. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param Pin is the pin number for which the interrupt status is to be -* cleared. Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt status is to be +* cleared. Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin) { - u8 Bank; - u8 PinNumber; - u32 IntrReg; + u8 Bank; + u8 PinNumber; + u32 IntrReg; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif /* Clear the specified pending interrupts. */ - IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTSTS_OFFSET); - IntrReg &= ((u32)1 << PinNumber); - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + IntrReg &= ((u32)1 << PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTSTS_OFFSET, IntrReg); } @@ -436,34 +436,34 @@ void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin) * This function is used for setting the Interrupt Type, Interrupt Polarity and * Interrupt On Any for the specified GPIO Bank pins. * -* @param InstancePtr is a pointer to an XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. -* @param IntrType is the 32 bit mask of the interrupt type. -* 0 means Level Sensitive and 1 means Edge Sensitive. -* @param IntrPolarity is the 32 bit mask of the interrupt polarity. -* 0 means Active Low or Falling Edge and 1 means Active High or -* Rising Edge. -* @param IntrOnAny is the 32 bit mask of the interrupt trigger for -* edge triggered interrupts. 0 means trigger on single edge using -* the configured interrupt polarity and 1 means trigger on both -* edges. +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param IntrType is the 32 bit mask of the interrupt type. +* 0 means Level Sensitive and 1 means Edge Sensitive. +* @param IntrPolarity is the 32 bit mask of the interrupt polarity. +* 0 means Active Low or Falling Edge and 1 means Active High or +* Rising Edge. +* @param IntrOnAny is the 32 bit mask of the interrupt trigger for +* edge triggered interrupts. 0 means trigger on single edge using +* the configured interrupt polarity and 1 means trigger on both +* edges. * -* @return None. +* @return None. * -* @note This function is used for setting the interrupt related -* properties of all the pins in the specified bank. The previous -* state of the pins is not maintained. -* To change the Interrupt properties of a single GPIO pin, use the -* function XGpioPs_SetPinIntrType(). +* @note This function is used for setting the interrupt related +* properties of all the pins in the specified bank. The previous +* state of the pins is not maintained. +* To change the Interrupt properties of a single GPIO pin, use the +* function XGpioPs_SetPinIntrType(). * *****************************************************************************/ void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, u32 IntrPolarity, u32 IntrOnAny) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Bank < InstancePtr->MaxBanks); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { Xil_AssertVoid(Bank != XGPIOPS_TWO); @@ -472,15 +472,15 @@ void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, } #endif - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET, IntrType); - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTPOL_OFFSET, IntrPolarity); - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTANY_OFFSET, IntrOnAny); } @@ -491,31 +491,31 @@ void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, * This function is used for getting the Interrupt Type, Interrupt Polarity and * Interrupt On Any for the specified GPIO Bank pins. * -* @param InstancePtr is a pointer to an XGpioPs instance. -* @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. -* @param IntrType returns the 32 bit mask of the interrupt type. -* 0 means Level Sensitive and 1 means Edge Sensitive. -* @param IntrPolarity returns the 32 bit mask of the interrupt -* polarity. 0 means Active Low or Falling Edge and 1 means -* Active High or Rising Edge. -* @param IntrOnAny returns the 32 bit mask of the interrupt trigger for -* edge triggered interrupts. 0 means trigger on single edge using -* the configured interrupt polarity and 1 means trigger on both -* edges. +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* @param IntrType returns the 32 bit mask of the interrupt type. +* 0 means Level Sensitive and 1 means Edge Sensitive. +* @param IntrPolarity returns the 32 bit mask of the interrupt +* polarity. 0 means Active Low or Falling Edge and 1 means +* Active High or Rising Edge. +* @param IntrOnAny returns the 32 bit mask of the interrupt trigger for +* edge triggered interrupts. 0 means trigger on single edge using +* the configured interrupt polarity and 1 means trigger on both +* edges. * -* @return None. +* @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, u32 *IntrPolarity, u32 *IntrOnAny) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Bank < InstancePtr->MaxBanks); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); #ifdef versal if(InstancePtr->PmcGpio == TRUE) { Xil_AssertVoid(Bank != XGPIOPS_TWO); @@ -542,86 +542,86 @@ void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, * * This function is used for setting the IRQ Type of a single GPIO pin. * -* @param InstancePtr is a pointer to an XGpioPs instance. -* @param Pin is the pin number whose IRQ type is to be set. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. -* @param IrqType is the IRQ type for GPIO Pin. Use XGPIOPS_IRQ_TYPE_* -* defined in xgpiops.h to specify the IRQ type. +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Pin is the pin number whose IRQ type is to be set. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param IrqType is the IRQ type for GPIO Pin. Use XGPIOPS_IRQ_TYPE_* +* defined in xgpiops.h to specify the IRQ type. * -* @return None. +* @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType) { - u32 IntrTypeReg; - u32 IntrPolReg; - u32 IntrOnAnyReg; - u8 Bank; - u8 PinNumber; + u32 IntrTypeReg; + u32 IntrPolReg; + u32 IntrOnAnyReg; + u8 Bank; + u8 PinNumber; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); - Xil_AssertVoid(IrqType <= XGPIOPS_IRQ_TYPE_LEVEL_LOW); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(IrqType <= XGPIOPS_IRQ_TYPE_LEVEL_LOW); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - IntrTypeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + IntrTypeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET); - IntrPolReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + IntrPolReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTPOL_OFFSET); - IntrOnAnyReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + IntrOnAnyReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTANY_OFFSET); + XGPIOPS_INTANY_OFFSET); - switch (IrqType) { - case XGPIOPS_IRQ_TYPE_EDGE_RISING: - IntrTypeReg |= ((u32)1 << (u32)PinNumber); - IntrPolReg |= ((u32)1 << (u32)PinNumber); - IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); - break; - case XGPIOPS_IRQ_TYPE_EDGE_FALLING: - IntrTypeReg |= ((u32)1 << (u32)PinNumber); - IntrPolReg &= ~((u32)1 << (u32)PinNumber); - IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); - break; - case XGPIOPS_IRQ_TYPE_EDGE_BOTH: - IntrTypeReg |= ((u32)1 << (u32)PinNumber); - IntrOnAnyReg |= ((u32)1 << (u32)PinNumber); - break; - case XGPIOPS_IRQ_TYPE_LEVEL_HIGH: - IntrTypeReg &= ~((u32)1 << (u32)PinNumber); - IntrPolReg |= ((u32)1 << (u32)PinNumber); - break; - case XGPIOPS_IRQ_TYPE_LEVEL_LOW: - IntrTypeReg &= ~((u32)1 << (u32)PinNumber); - IntrPolReg &= ~((u32)1 << (u32)PinNumber); - break; - default: + switch (IrqType) { + case XGPIOPS_IRQ_TYPE_EDGE_RISING: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrPolReg |= ((u32)1 << (u32)PinNumber); + IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_EDGE_FALLING: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrPolReg &= ~((u32)1 << (u32)PinNumber); + IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_EDGE_BOTH: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrOnAnyReg |= ((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_LEVEL_HIGH: + IntrTypeReg &= ~((u32)1 << (u32)PinNumber); + IntrPolReg |= ((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_LEVEL_LOW: + IntrTypeReg &= ~((u32)1 << (u32)PinNumber); + IntrPolReg &= ~((u32)1 << (u32)PinNumber); + break; + default: /**< Default statement is added for MISRA C compliance. */ - break; + break; } - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET, IntrTypeReg); - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTPOL_OFFSET, IntrPolReg); - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTANY_OFFSET, IntrOnAnyReg); } @@ -631,72 +631,72 @@ void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType) * * This function returns the IRQ Type of a given GPIO pin. * -* @param InstancePtr is a pointer to an XGpioPs instance. -* @param Pin is the pin number whose IRQ type is to be obtained. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Pin is the pin number whose IRQ type is to be obtained. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * -* @return None. +* @return None. * -* @note Use XGPIOPS_IRQ_TYPE_* defined in xgpiops.h for the IRQ type -* returned by this function. +* @note Use XGPIOPS_IRQ_TYPE_* defined in xgpiops.h for the IRQ type +* returned by this function. * *****************************************************************************/ u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin) { - u32 IntrType; - u32 IntrPol; - u32 IntrOnAny; - u8 Bank; - u8 PinNumber; - u8 IrqType; + u32 IntrType; + u32 IntrPol; + u32 IntrOnAny; + u8 Bank; + u8 PinNumber; + u8 IrqType; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); /* Get the Bank number and Pin number within the bank. */ #ifdef versal - XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else - XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET) & ((u32)1 << PinNumber); - if (IntrType == ((u32)1 << PinNumber)) { + if (IntrType == ((u32)1 << PinNumber)) { - IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTANY_OFFSET) & ((u32)1 << PinNumber); - IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); - if (IntrOnAny == ((u32)1 << PinNumber)) { - IrqType = XGPIOPS_IRQ_TYPE_EDGE_BOTH; + if (IntrOnAny == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_BOTH; } else if (IntrPol == ((u32)1 << PinNumber)) { - IrqType = XGPIOPS_IRQ_TYPE_EDGE_RISING; + IrqType = XGPIOPS_IRQ_TYPE_EDGE_RISING; } else { - IrqType = XGPIOPS_IRQ_TYPE_EDGE_FALLING; + IrqType = XGPIOPS_IRQ_TYPE_EDGE_FALLING; } } else { - IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); - if (IntrPol == ((u32)1 << PinNumber)) { - IrqType = XGPIOPS_IRQ_TYPE_LEVEL_HIGH; + if (IntrPol == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_LEVEL_HIGH; } else { - IrqType = XGPIOPS_IRQ_TYPE_LEVEL_LOW; + IrqType = XGPIOPS_IRQ_TYPE_LEVEL_LOW; } } - return IrqType; + return IrqType; } /*****************************************************************************/ @@ -705,28 +705,28 @@ u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin) * This function sets the status callback function. The callback function is * called by the XGpioPs_IntrHandler when an interrupt occurs. * -* @param InstancePtr is a pointer to the XGpioPs instance. -* @param CallBackRef is the upper layer callback reference passed back -* when the callback function is invoked. -* @param FuncPointer is the pointer to the callback function. +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param FuncPointer is the pointer to the callback function. * * -* @return None. +* @return None. * -* @note The handler is called within interrupt context, so it should do -* its work quickly and queue potentially time-consuming work to a -* task-level thread. +* @note The handler is called within interrupt context, so it should do +* its work quickly and queue potentially time-consuming work to a +* task-level thread. * ******************************************************************************/ void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, XGpioPs_Handler FuncPointer) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(FuncPointer != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPointer != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - InstancePtr->Handler = FuncPointer; - InstancePtr->CallBackRef = CallBackRef; + InstancePtr->Handler = FuncPointer; + InstancePtr->CallBackRef = CallBackRef; } /*****************************************************************************/ @@ -738,42 +738,42 @@ void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, * handler set by the function XGpioPs_SetBankHandler(). The callback is called * when an interrupt * -* @param InstancePtr is a pointer to the XGpioPs instance. +* @param InstancePtr is a pointer to the XGpioPs instance. * -* @return None. +* @return None. * -* @note This function does not save and restore the processor context -* such that the user must provide this processing. +* @note This function does not save and restore the processor context +* such that the user must provide this processing. * ******************************************************************************/ void XGpioPs_IntrHandler(const XGpioPs *InstancePtr) { - u8 Bank; - u32 IntrStatus; - u32 IntrEnabled; + u8 Bank; + u32 IntrStatus; + u32 IntrEnabled; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - for (Bank = 0U; Bank < InstancePtr->MaxBanks; Bank++) { + for (Bank = 0U; Bank < InstancePtr->MaxBanks; Bank++) { #ifdef versal - if(InstancePtr->PmcGpio == TRUE) { - if(Bank == XGPIOPS_TWO) { - continue; + if(InstancePtr->PmcGpio == TRUE) { + if(Bank == XGPIOPS_TWO) { + continue; } } else { - if((Bank == XGPIOPS_ONE) || (Bank == XGPIOPS_TWO)) { - continue; + if((Bank == XGPIOPS_ONE) || (Bank == XGPIOPS_TWO)) { + continue; } } #endif - IntrStatus = XGpioPs_IntrGetStatus(InstancePtr, Bank); - IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr,Bank); - if ((IntrStatus & IntrEnabled) != (u32)0) { - XGpioPs_IntrClear(InstancePtr, Bank, + IntrStatus = XGpioPs_IntrGetStatus(InstancePtr, Bank); + IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr,Bank); + if ((IntrStatus & IntrEnabled) != (u32)0) { + XGpioPs_IntrClear(InstancePtr, Bank, (IntrStatus & IntrEnabled)); - InstancePtr->Handler(InstancePtr-> - CallBackRef, Bank, + InstancePtr->Handler(InstancePtr-> + CallBackRef, Bank, (IntrStatus & IntrEnabled)); } } @@ -785,13 +785,13 @@ void XGpioPs_IntrHandler(const XGpioPs *InstancePtr) * This is a stub for the status callback. The stub is here in case the upper * layers do not set the handler. * -* @param CallBackRef is a pointer to the upper layer callback reference -* @param Bank is the GPIO Bank in which an interrupt occurred. -* @param Status is the Interrupt status of the GPIO bank. +* @param CallBackRef is a pointer to the upper layer callback reference +* @param Bank is the GPIO Bank in which an interrupt occurred. +* @param Status is the Interrupt status of the GPIO bank. * -* @return None. +* @return None. * -* @note None. +* @note None. * ******************************************************************************/ void StubHandler(const void *CallBackRef, u32 Bank, u32 Status) @@ -800,6 +800,6 @@ void StubHandler(const void *CallBackRef, u32 Bank, u32 Status) (void) Bank; (void) Status; - Xil_AssertVoidAlways(); + Xil_AssertVoidAlways(); } /** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_selftest.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_selftest.c index 6f5fcf799a..6ba43424e3 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_selftest.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_selftest.c @@ -52,7 +52,7 @@ * This function runs a self-test on the GPIO driver/device. This function * does a register read/write test on some of the Interrupt Registers. * -* @param InstancePtr is a pointer to the XGpioPs instance. +* @param InstancePtr is a pointer to the XGpioPs instance. * * @return * - XST_SUCCESS if the self-test passed. @@ -62,51 +62,51 @@ ******************************************************************************/ s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr) { - s32 Status = XST_SUCCESS; - u32 IntrEnabled; - u32 CurrentIntrType = 0U; - u32 CurrentIntrPolarity = 0U; - u32 CurrentIntrOnAny = 0U; - u32 IntrType = 0U; - u32 IntrPolarity = 0U; - u32 IntrOnAny = 0U; - u32 IntrTestValue = 0x22U; + s32 Status = XST_SUCCESS; + u32 IntrEnabled; + u32 CurrentIntrType = 0U; + u32 CurrentIntrPolarity = 0U; + u32 CurrentIntrOnAny = 0U; + u32 IntrType = 0U; + u32 IntrPolarity = 0U; + u32 IntrOnAny = 0U; + u32 IntrTestValue = 0x22U; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* Disable the Interrupts for Bank 0 . */ - IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr, XGPIOPS_BANK0); - XGpioPs_IntrDisable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); + IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr, XGPIOPS_BANK0); + XGpioPs_IntrDisable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); /* * Get the Current Interrupt properties for Bank 0. * Set them to a known value, read it back and compare. */ - XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &CurrentIntrType, + XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &CurrentIntrType, &CurrentIntrPolarity, &CurrentIntrOnAny); - XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, IntrTestValue, + XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, IntrTestValue, IntrTestValue, IntrTestValue); - XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &IntrType, + XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &IntrType, &IntrPolarity, &IntrOnAny); - if ((IntrType != IntrTestValue) && (IntrPolarity != IntrTestValue) && + if ((IntrType != IntrTestValue) && (IntrPolarity != IntrTestValue) && (IntrOnAny != IntrTestValue)) { - Status = XST_FAILURE; + Status = XST_FAILURE; } /* * Restore the contents of all the interrupt registers modified in this * test. */ - XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, CurrentIntrType, + XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, CurrentIntrType, CurrentIntrPolarity, CurrentIntrOnAny); - XGpioPs_IntrEnable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); + XGpioPs_IntrEnable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); - return Status; + return Status; } /** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_sinit.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_sinit.c index bfc08a6aed..713e11f53f 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_sinit.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_sinit.c @@ -13,7 +13,7 @@ * This file contains the implementation of the XGpioPs driver's static * initialization functionality. * -* @note None. +* @note None. * *
 *
@@ -50,26 +50,26 @@ extern XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES];
 * ID. The table XGpioPs_ConfigTable[] contains the configuration information
 * for each device in the system.
 *
-* @param	DeviceId is the unique device ID of the device being looked up.
+* @param    DeviceId is the unique device ID of the device being looked up.
 *
-* @return	A pointer to the configuration table entry corresponding to the
-*		given device ID, or NULL if no match is found.
+* @return    A pointer to the configuration table entry corresponding to the
+*	    given device ID, or NULL if no match is found.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId)
 {
-	XGpioPs_Config *CfgPtr = NULL;
-	u32 Index;
+    XGpioPs_Config *CfgPtr = NULL;
+    u32 Index;
 
-	for (Index = 0U; Index < (u32)XPAR_XGPIOPS_NUM_INSTANCES; Index++) {
-		if (XGpioPs_ConfigTable[Index].DeviceId == DeviceId) {
-			CfgPtr = &XGpioPs_ConfigTable[Index];
-			break;
+    for (Index = 0U; Index < (u32)XPAR_XGPIOPS_NUM_INSTANCES; Index++) {
+	    if (XGpioPs_ConfigTable[Index].DeviceId == DeviceId) {
+		    CfgPtr = &XGpioPs_ConfigTable[Index];
+		    break;
 		}
 	}
 
-	return (XGpioPs_Config *)CfgPtr;
+    return (XGpioPs_Config *)CfgPtr;
 }
 /** @} */
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c
index d6542b0674..f1237ca86c 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c
@@ -24,14 +24,14 @@
 * 2.2   hk     07/28/14 Make changes to enable use of data cache.
 * 2.3   sk     09/23/14 Send command for relative card address
 *                       when re-initialization is done.CR# 819614.
-*						Use XSdPs_Change_ClkFreq API whenever changing
-*						clock.CR# 816586.
-* 2.4	sk	   12/04/14 Added support for micro SD without
-* 						WP/CD. CR# 810655.
-*						Checked for DAT Inhibit mask instead of CMD
-* 						Inhibit mask in Cmd Transfer API.
-*						Added Support for SD Card v1.0
-* 2.5 	sg	   07/09/15 Added SD 3.0 features
+*					    Use XSdPs_Change_ClkFreq API whenever changing
+*					    clock.CR# 816586.
+* 2.4    sk	   12/04/14 Added support for micro SD without
+* 					    WP/CD. CR# 810655.
+*					    Checked for DAT Inhibit mask instead of CMD
+* 					    Inhibit mask in Cmd Transfer API.
+*					    Added Support for SD Card v1.0
+* 2.5     sg	   07/09/15 Added SD 3.0 features
 *       kvn    07/15/15 Modified the code according to MISRAC-2012.
 * 2.6   sk     10/12/15 Added support for SD card v1.0 CR# 840601.
 * 2.7   sk     11/24/15 Considered the slot type befoe checking CD/WP pins.
@@ -102,96 +102,96 @@
 * Initializes a specific XSdPs instance such that the driver is ready to use.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	ConfigPtr is a reference to a structure containing information
-*		about a specific SD device. This function initializes an
-*		InstancePtr object for a specific device specified by the
-*		contents of Config.
-* @param	EffectiveAddr is the device base address in the virtual memory
-*		address space. The caller is responsible for keeping the address
-*		mapping from EffectiveAddr to the device physical base address
-*		unchanged once this function is invoked. Unexpected errors may
-*		occur if the address mapping changes after this function is
-*		called. If address translation is not used, use
-*		ConfigPtr->Config.BaseAddress for this device.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    ConfigPtr is a reference to a structure containing information
+*	    about a specific SD device. This function initializes an
+*	    InstancePtr object for a specific device specified by the
+*	    contents of Config.
+* @param    EffectiveAddr is the device base address in the virtual memory
+*	    address space. The caller is responsible for keeping the address
+*	    mapping from EffectiveAddr to the device physical base address
+*	    unchanged once this function is invoked. Unexpected errors may
+*	    occur if the address mapping changes after this function is
+*	    called. If address translation is not used, use
+*	    ConfigPtr->Config.BaseAddress for this device.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_DEVICE_IS_STARTED if the device is already started.
-*		It must be stopped to re-initialize.
+*	    It must be stopped to re-initialize.
 *
-* @note		This function initializes the host controller.
-*		Initial clock of 400KHz is set.
-*		Voltage of 3.3V is selected as that is supported by host.
-*		Interrupts status is enabled and signal disabled by default.
-*		Default data direction is card to host and
-*		32 bit ADMA2 is selected. Default Block size is 512 bytes.
+* @note	    This function initializes the host controller.
+*	    Initial clock of 400KHz is set.
+*	    Voltage of 3.3V is selected as that is supported by host.
+*	    Interrupts status is enabled and signal disabled by default.
+*	    Default data direction is card to host and
+*	    32 bit ADMA2 is selected. Default Block size is 512 bytes.
 *
 ******************************************************************************/
 s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
-				u32 EffectiveAddr)
+			    u32 EffectiveAddr)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(ConfigPtr != NULL);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(ConfigPtr != NULL);
 
 #if defined  (XCLOCKING)
-	InstancePtr->Config.RefClk = ConfigPtr->RefClk;
-	Xil_ClockEnable(InstancePtr->Config.RefClk);
+    InstancePtr->Config.RefClk = ConfigPtr->RefClk;
+    Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 	/* If this API is getting called twice, return value accordingly */
-	if (InstancePtr->IsReady == XIL_COMPONENT_IS_READY) {
-		Status = (s32)XST_DEVICE_IS_STARTED;
-		goto RETURN_PATH ;
+    if (InstancePtr->IsReady == XIL_COMPONENT_IS_READY) {
+	    Status = (s32)XST_DEVICE_IS_STARTED;
+	    goto RETURN_PATH ;
 	}
 
 	/* Set some default values. */
-	InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
-	InstancePtr->Config.BaseAddress = EffectiveAddr;
-	InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
-	InstancePtr->Config.CardDetect =  ConfigPtr->CardDetect;
-	InstancePtr->Config.WriteProtect =  ConfigPtr->WriteProtect;
-	InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
-	InstancePtr->Config.BankNumber = ConfigPtr->BankNumber;
-	InstancePtr->Config.HasEMIO = ConfigPtr->HasEMIO;
-	InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
-	InstancePtr->SectorCount = 0U;
-	InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
-	InstancePtr->OTapDelay = 0U;
-	InstancePtr->ITapDelay = 0U;
-	InstancePtr->Dma64BitAddr = 0U;
-	InstancePtr->SlcrBaseAddr = XPS_SYS_CTRL_BASEADDR;
+    InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
+    InstancePtr->Config.BaseAddress = EffectiveAddr;
+    InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
+    InstancePtr->Config.CardDetect =  ConfigPtr->CardDetect;
+    InstancePtr->Config.WriteProtect =  ConfigPtr->WriteProtect;
+    InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
+    InstancePtr->Config.BankNumber = ConfigPtr->BankNumber;
+    InstancePtr->Config.HasEMIO = ConfigPtr->HasEMIO;
+    InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
+    InstancePtr->SectorCount = 0U;
+    InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
+    InstancePtr->OTapDelay = 0U;
+    InstancePtr->ITapDelay = 0U;
+    InstancePtr->Dma64BitAddr = 0U;
+    InstancePtr->SlcrBaseAddr = XPS_SYS_CTRL_BASEADDR;
 
 	/* Host Controller version is read. */
-	InstancePtr->HC_Version =
+    InstancePtr->HC_Version =
 			(u8)(XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK);
+		    XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK);
 
 	/*
 	 * Read capabilities register and update it in Instance pointer.
 	 * It is sufficient to read this once on power on.
 	 */
-	InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-						XSDPS_CAPS_OFFSET);
+    InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+					    XSDPS_CAPS_OFFSET);
 
 	/* Reset the SD bus lines */
-	Status = XSdPs_ResetConfig(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    Status = XSdPs_ResetConfig(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
 	/* Configure the SD Host Controller */
-	XSdPs_HostConfig(InstancePtr);
+    XSdPs_HostConfig(InstancePtr);
 
-	InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
+    InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
-	Xil_ClockDisable(InstancePtr->Config.RefClk);
+    Xil_ClockDisable(InstancePtr->Config.RefClk);
 #endif
-	return Status;
+    return Status;
 
 }
 
@@ -202,69 +202,69 @@ RETURN_PATH:
 * Initialize Card with Identification mode sequence
 *
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
 * 		- XST_FAILURE if failure - could be because
-* 			a) SD is already initialized
-* 			b) There is no card inserted
-* 			c) One of the steps (commands) in the
+* 		    a) SD is already initialized
+* 		    b) There is no card inserted
+* 		    c) One of the steps (commands) in the
 *			   initialization cycle failed
 *
 *
 ******************************************************************************/
 s32 XSdPs_CardInitialize(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
 	/* Default settings */
-	InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
-	InstancePtr->CardType = XSDPS_CARD_SD;
-	InstancePtr->Switch1v8 = 0U;
-	InstancePtr->BusSpeed = XSDPS_CLK_400_KHZ;
+    InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
+    InstancePtr->CardType = XSDPS_CARD_SD;
+    InstancePtr->Switch1v8 = 0U;
+    InstancePtr->BusSpeed = XSDPS_CLK_400_KHZ;
 
 #if defined  (XCLOCKING)
-	Xil_ClockEnable(InstancePtr->Config.RefClk);
+    Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
 	/* Change the clock frequency to 400 KHz */
-	Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
 	/* Identify the Card whether it is SD, MMC or eMMC */
-	Status = XSdPs_IdentifyCard(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_IdentifyCard(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Initialize the identified card */
-	if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		Status = XSdPs_SdCardInitialize(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+	    Status = XSdPs_SdCardInitialize(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	} else {
-		Status = XSdPs_MmcCardInitialize(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_MmcCardInitialize(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
-	Xil_ClockDisable(InstancePtr->Config.RefClk);
+    Xil_ClockDisable(InstancePtr->Config.RefClk);
 #endif
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -272,48 +272,48 @@ RETURN_PATH:
 * @brief
 * This function performs SD read in polled mode.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Arg is the address passed by the user that is to be sent as
-* 		argument along with the command.
-* @param	BlkCnt - Block count passed by the user.
-* @param	Buff - Pointer to the data buffer for a DMA transfer.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Arg is the address passed by the user that is to be sent as
+* 	    argument along with the command.
+* @param    BlkCnt - Block count passed by the user.
+* @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
 * 		- XST_FAILURE if failure - could be because another transfer
-* 		is in progress or command or data inhibit is set
+* 	    is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
 #if defined  (XCLOCKING)
-	Xil_ClockEnable(InstancePtr->Config.RefClk);
+    Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
 	/* Setup the Read Transfer */
-	Status = XSdPs_SetupTransfer(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_SetupTransfer(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Read from the card */
-	Status = XSdPs_Read(InstancePtr, Arg, BlkCnt, Buff);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Read(InstancePtr, Arg, BlkCnt, Buff);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
-	Xil_ClockDisable(InstancePtr->Config.RefClk);
+    Xil_ClockDisable(InstancePtr->Config.RefClk);
 #endif
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -321,48 +321,48 @@ RETURN_PATH:
 * @brief
 * This function performs SD write in polled mode.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Arg is the address passed by the user that is to be sent as
-* 		argument along with the command.
-* @param	BlkCnt - Block count passed by the user.
-* @param	Buff - Pointer to the data buffer for a DMA transfer.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Arg is the address passed by the user that is to be sent as
+* 	    argument along with the command.
+* @param    BlkCnt - Block count passed by the user.
+* @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
 * 		- XST_FAILURE if failure - could be because another transfer
-* 		is in progress or command or data inhibit is set
+* 	    is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
 #if defined  (XCLOCKING)
-	Xil_ClockEnable(InstancePtr->Config.RefClk);
+    Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
 	/* Setup the Write Transfer */
-	Status = XSdPs_SetupTransfer(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_SetupTransfer(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Write to the card */
-	Status = XSdPs_Write(InstancePtr, Arg, BlkCnt, Buff);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Write(InstancePtr, Arg, BlkCnt, Buff);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
-	Xil_ClockDisable(InstancePtr->Config.RefClk);
+    Xil_ClockDisable(InstancePtr->Config.RefClk);
 #endif
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -372,49 +372,49 @@ RETURN_PATH:
 * API to idle the SDIO Interface
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
-* @return	None
+* @return    None
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 s32 XSdPs_Idle(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
 #if defined  (XCLOCKING)
-	Xil_ClockEnable(InstancePtr->Config.RefClk);
+    Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
 	/* Check if the bus is idle */
-	Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK
+    Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK
 										| XSDPS_PSR_INHIBIT_DAT_MASK
 										| XSDPS_PSR_DAT_ACTIVE_MASK);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
 	/* Disable the Bus Power */
-	XSdPs_DisableBusPower(InstancePtr);
+    XSdPs_DisableBusPower(InstancePtr);
 
 	/* Reset Command and Data Lines */
-	Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
-	Xil_ClockDisable(InstancePtr->Config.RefClk);
+    Xil_ClockDisable(InstancePtr->Config.RefClk);
 #endif
-	return Status;
+    return Status;
 }
 /** @} */
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h
index 075b751bf0..3fe8bb64e8 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h
@@ -83,14 +83,14 @@
 * 2.2   hk     07/28/14 Make changes to enable use of data cache.
 * 2.3   sk     09/23/14 Send command for relative card address
 *                       when re-initialization is done.CR# 819614.
-*						Use XSdPs_Change_ClkFreq API whenever changing
-*						clock.CR# 816586.
-* 2.4	sk	   12/04/14 Added support for micro SD without
-* 						WP/CD. CR# 810655.
-*						Checked for DAT Inhibit mask instead of CMD
-* 						Inhibit mask in Cmd Transfer API.
-*						Added Support for SD Card v1.0
-* 2.5 	sg		07/09/15 Added SD 3.0 features
+*					    Use XSdPs_Change_ClkFreq API whenever changing
+*					    clock.CR# 816586.
+* 2.4    sk	   12/04/14 Added support for micro SD without
+* 					    WP/CD. CR# 810655.
+*					    Checked for DAT Inhibit mask instead of CMD
+* 					    Inhibit mask in Cmd Transfer API.
+*					    Added Support for SD Card v1.0
+* 2.5     sg	    07/09/15 Added SD 3.0 features
 *       kvn     07/15/15 Modified the code according to MISRAC-2012.
 * 2.6   sk     10/12/15 Added support for SD card v1.0 CR# 840601.
 * 2.7   sk     11/24/15 Considered the slot type befoe checking CD/WP pins.
@@ -119,7 +119,7 @@
 *       vns    02/09/17 Added ARMA53_32 support for ZynqMP CR#968397
 *       sk     03/20/17 Add support for EL1 non-secure mode.
 * 3.3   mn     05/17/17 Add support for 64bit DMA addressing
-* 	mn     08/07/17 Modify driver to support 64-bit DMA in arm64 only
+*     mn     08/07/17 Modify driver to support 64-bit DMA in arm64 only
 *       mn     08/17/17 Enabled CCI support for A53 by adding cache coherency
 *                       information.
 *       mn     09/06/17 Resolved compilation errors with IAR toolchain
@@ -155,38 +155,38 @@ extern "C" {
 
 /************************** Constant Definitions *****************************/
 
-#define XSDPS_CT_ERROR	0x2L	/**< Command timeout flag */
-#define MAX_TUNING_COUNT	40U		/**< Maximum Tuning count */
-#define MAX_TIMEOUT		0x1FFFFFFFU		/**< Maximum Timeout */
-#define XSDPS_CMD8_VOL_PATTERN	0x1AAU
-#define XSDPS_RESPOCR_READY	0x80000000U
-#define XSDPS_ACMD41_HCS	0x40000000U
-#define XSDPS_ACMD41_3V3	0x00300000U
-#define XSDPS_CMD1_HIGH_VOL	0x00FF8000U
-#define XSDPS_CMD1_DUAL_VOL	0x00FF8010U
-#define HIGH_SPEED_SUPPORT	0x2U
-#define UHS_SDR12_SUPPORT	0x1U
-#define UHS_SDR25_SUPPORT	0x2U
-#define UHS_SDR50_SUPPORT	0x4U
-#define UHS_SDR104_SUPPORT	0x8U
-#define UHS_DDR50_SUPPORT	0x10U
-#define WIDTH_4_BIT_SUPPORT	0x4U
-#define SD_CLK_25_MHZ		25000000U
-#define SD_CLK_19_MHZ		19000000U
-#define SD_CLK_26_MHZ		26000000U
-#define EXT_CSD_DEVICE_TYPE_BYTE	196U
-#define EXT_CSD_SEC_COUNT_BYTE1		212U
-#define EXT_CSD_SEC_COUNT_BYTE2		213U
-#define EXT_CSD_SEC_COUNT_BYTE3		214U
-#define EXT_CSD_SEC_COUNT_BYTE4		215U
-#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED			0x2U
-#define EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED	0x4U
-#define EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED	0x8U
-#define EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200		0x10U
-#define EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200		0x20U
-#define CSD_SPEC_VER_3		0x3U
-#define SCR_SPEC_VER_3		0x80U
-#define ADDRESS_BEYOND_32BIT	0x100000000U
+#define XSDPS_CT_ERROR    0x2L	/**< Command timeout flag */
+#define MAX_TUNING_COUNT    40U		/**< Maximum Tuning count */
+#define MAX_TIMEOUT	    0x1FFFFFFFU		/**< Maximum Timeout */
+#define XSDPS_CMD8_VOL_PATTERN    0x1AAU
+#define XSDPS_RESPOCR_READY    0x80000000U
+#define XSDPS_ACMD41_HCS    0x40000000U
+#define XSDPS_ACMD41_3V3    0x00300000U
+#define XSDPS_CMD1_HIGH_VOL    0x00FF8000U
+#define XSDPS_CMD1_DUAL_VOL    0x00FF8010U
+#define HIGH_SPEED_SUPPORT    0x2U
+#define UHS_SDR12_SUPPORT    0x1U
+#define UHS_SDR25_SUPPORT    0x2U
+#define UHS_SDR50_SUPPORT    0x4U
+#define UHS_SDR104_SUPPORT    0x8U
+#define UHS_DDR50_SUPPORT    0x10U
+#define WIDTH_4_BIT_SUPPORT    0x4U
+#define SD_CLK_25_MHZ	    25000000U
+#define SD_CLK_19_MHZ	    19000000U
+#define SD_CLK_26_MHZ	    26000000U
+#define EXT_CSD_DEVICE_TYPE_BYTE    196U
+#define EXT_CSD_SEC_COUNT_BYTE1	    212U
+#define EXT_CSD_SEC_COUNT_BYTE2	    213U
+#define EXT_CSD_SEC_COUNT_BYTE3	    214U
+#define EXT_CSD_SEC_COUNT_BYTE4	    215U
+#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED		    0x2U
+#define EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED    0x4U
+#define EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED    0x8U
+#define EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200	    0x10U
+#define EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200	    0x20U
+#define CSD_SPEC_VER_3	    0x3U
+#define SCR_SPEC_VER_3	    0x80U
+#define ADDRESS_BEYOND_32BIT    0x100000000U
 
 /**************************** Type Definitions *******************************/
 
@@ -196,25 +196,25 @@ typedef void (*XSdPs_ConfigTap) (u32 Bank, u32 DeviceId, u32 CardType);
  * This typedef contains configuration information for the device.
  */
 typedef struct {
-	u16 DeviceId;			/**< Unique ID  of device */
-	u32 BaseAddress;		/**< Base address of the device */
-	u32 InputClockHz;		/**< Input clock frequency */
-	u32 CardDetect;			/**< Card Detect */
-	u32 WriteProtect;			/**< Write Protect */
-	u32 BusWidth;			/**< Bus Width */
-	u32 BankNumber;			/**< MIO Bank selection for SD */
-	u32 HasEMIO;			/**< If SD is connected to EMIO */
-	u8 IsCacheCoherent; 		/**< If SD is Cache Coherent or not */
+    u16 DeviceId;			/**< Unique ID  of device */
+    u32 BaseAddress;		/**< Base address of the device */
+    u32 InputClockHz;		/**< Input clock frequency */
+    u32 CardDetect;			/**< Card Detect */
+    u32 WriteProtect;			/**< Write Protect */
+    u32 BusWidth;			/**< Bus Width */
+    u32 BankNumber;			/**< MIO Bank selection for SD */
+    u32 HasEMIO;			/**< If SD is connected to EMIO */
+    u8 IsCacheCoherent; 		/**< If SD is Cache Coherent or not */
 #if defined  (XCLOCKING)
-	u32 RefClk;			/**< Input clocks */
+    u32 RefClk;			/**< Input clocks */
 #endif
 } XSdPs_Config;
 
 /* ADMA2 32-Bit descriptor table */
 typedef struct {
-	u16 Attribute;		/**< Attributes of descriptor */
-	u16 Length;		/**< Length of current dma transfer */
-	u32 Address;		/**< Address of current dma transfer */
+    u16 Attribute;		/**< Attributes of descriptor */
+    u16 Length;		/**< Length of current dma transfer */
+    u32 Address;		/**< Address of current dma transfer */
 #ifdef __ICCARM__
 #pragma data_alignment = 32
 } XSdPs_Adma2Descriptor32;
@@ -224,9 +224,9 @@ typedef struct {
 
 /* ADMA2 64-Bit descriptor table */
 typedef struct {
-	u16 Attribute;		/**< Attributes of descriptor */
-	u16 Length;		/**< Length of current dma transfer */
-	u64 Address;		/**< Address of current dma transfer */
+    u16 Attribute;		/**< Attributes of descriptor */
+    u16 Length;		/**< Length of current dma transfer */
+    u64 Address;		/**< Address of current dma transfer */
 #ifdef __ICCARM__
 #pragma data_alignment = 32
 } XSdPs_Adma2Descriptor64;
@@ -240,28 +240,28 @@ typedef struct {
  * to a variable of this type is then passed to the driver API functions.
  */
 typedef struct {
-	XSdPs_Config Config;	/**< Configuration structure */
-	u32 IsReady;		/**< Device is initialized and ready */
-	u32 Host_Caps;		/**< Capabilities of host controller */
-	u32 Host_CapsExt;	/**< Extended Capabilities */
-	u32 HCS;		/**< High capacity support in card */
-	u8  CardType;		/**< Type of card - SD/MMC/eMMC */
-	u8  Card_Version;	/**< Card version */
-	u8  HC_Version;		/**< Host controller version */
-	u8  BusWidth;		/**< Current operating bus width */
-	u32 BusSpeed;		/**< Current operating bus speed */
-	u8  Switch1v8;		/**< 1.8V Switch support */
-	u32 CardID[4];		/**< Card ID Register */
-	u32 RelCardAddr;	/**< Relative Card Address */
-	u32 CardSpecData[4];	/**< Card Specific Data Register */
-	u32 SectorCount;		/**< Sector Count */
-	u32 SdCardConfig;	/**< Sd Card Configuration Register */
-	u32 Mode;			/**< Bus Speed Mode */
-	u32 OTapDelay;		/**< Output Tap Delay */
-	u32 ITapDelay;		/**< Input Tap Delay */
-	u64 Dma64BitAddr;	/**< 64 Bit DMA Address */
-	u16 TransferMode;	/**< Transfer Mode */
-	u32 SlcrBaseAddr;	/**< SLCR base address*/
+    XSdPs_Config Config;	/**< Configuration structure */
+    u32 IsReady;		/**< Device is initialized and ready */
+    u32 Host_Caps;		/**< Capabilities of host controller */
+    u32 Host_CapsExt;	/**< Extended Capabilities */
+    u32 HCS;		/**< High capacity support in card */
+    u8  CardType;		/**< Type of card - SD/MMC/eMMC */
+    u8  Card_Version;	/**< Card version */
+    u8  HC_Version;		/**< Host controller version */
+    u8  BusWidth;		/**< Current operating bus width */
+    u32 BusSpeed;		/**< Current operating bus speed */
+    u8  Switch1v8;		/**< 1.8V Switch support */
+    u32 CardID[4];		/**< Card ID Register */
+    u32 RelCardAddr;	/**< Relative Card Address */
+    u32 CardSpecData[4];	/**< Card Specific Data Register */
+    u32 SectorCount;		/**< Sector Count */
+    u32 SdCardConfig;	/**< Sd Card Configuration Register */
+    u32 Mode;			/**< Bus Speed Mode */
+    u32 OTapDelay;		/**< Output Tap Delay */
+    u32 ITapDelay;		/**< Input Tap Delay */
+    u64 Dma64BitAddr;	/**< 64 Bit DMA Address */
+    u16 TransferMode;	/**< Transfer Mode */
+    u32 SlcrBaseAddr;	/**< SLCR base address*/
 } XSdPs;
 
 /***************** Macros (Inline Functions) Definitions *********************/
@@ -269,7 +269,7 @@ typedef struct {
 /************************** Function Prototypes ******************************/
 XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId);
 s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
-				u32 EffectiveAddr);
+			    u32 EffectiveAddr);
 s32 XSdPs_CardInitialize(XSdPs *InstancePtr);
 s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff);
 s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff);
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c
index 9de30bd1e5..d6430a9a00 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c
@@ -41,58 +41,58 @@
 * @brief
 * This function performs SD read in polled mode.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Arg is the address passed by the user that is to be sent as
-* 		argument along with the command.
-* @param	BlkCnt - Block count passed by the user.
-* @param	Buff - Pointer to the data buffer for a DMA transfer.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Arg is the address passed by the user that is to be sent as
+* 	    argument along with the command.
+* @param    BlkCnt - Block count passed by the user.
+* @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
 * 		- XST_FAILURE if failure - could be because another transfer
-* 		is in progress or command or data inhibit is set
+* 	    is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_Read(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
 {
-	s32 Status;
-	u16 BlkSize;
+    s32 Status;
+    u16 BlkSize;
 
-	BlkSize = XSDPS_BLK_SIZE_512_MASK;
+    BlkSize = XSDPS_BLK_SIZE_512_MASK;
 
-	XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, Buff);
+    XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, Buff);
 
-	if (BlkCnt == 1U) {
+    if (BlkCnt == 1U) {
 		/* Send single block read command */
-		Status = XSdPs_CmdTransfer(InstancePtr, CMD17, Arg, BlkCnt);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_CmdTransfer(InstancePtr, CMD17, Arg, BlkCnt);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	} else {
 		/* Send multiple blocks read command */
-		Status = XSdPs_CmdTransfer(InstancePtr, CMD18, Arg, BlkCnt);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_CmdTransfer(InstancePtr, CMD18, Arg, BlkCnt);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
 	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheInvalidateRange((INTPTR)Buff,
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+	    Xil_DCacheInvalidateRange((INTPTR)Buff,
 				(INTPTR)BlkCnt * BlkSize);
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -100,53 +100,53 @@ RETURN_PATH:
 * @brief
 * This function performs SD write in polled mode.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Arg is the address passed by the user that is to be sent as
-* 		argument along with the command.
-* @param	BlkCnt - Block count passed by the user.
-* @param	Buff - Pointer to the data buffer for a DMA transfer.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Arg is the address passed by the user that is to be sent as
+* 	    argument along with the command.
+* @param    BlkCnt - Block count passed by the user.
+* @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
 * 		- XST_FAILURE if failure - could be because another transfer
-* 		is in progress or command or data inhibit is set
+* 	    is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_Write(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
 {
-	s32 Status;
-	u16 BlkSize;
+    s32 Status;
+    u16 BlkSize;
 
-	BlkSize = XSDPS_BLK_SIZE_512_MASK;
+    BlkSize = XSDPS_BLK_SIZE_512_MASK;
 
-	XSdPs_SetupWriteDma(InstancePtr, BlkCnt, BlkSize, Buff);
+    XSdPs_SetupWriteDma(InstancePtr, BlkCnt, BlkSize, Buff);
 
-	if (BlkCnt == 1U) {
+    if (BlkCnt == 1U) {
 		/* Send single block write command */
-		Status = XSdPs_CmdTransfer(InstancePtr, CMD24, Arg, BlkCnt);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_CmdTransfer(InstancePtr, CMD24, Arg, BlkCnt);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	} else {
 		/* Send multiple blocks write command */
-		Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
 	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+	    return Status;
 }
 /*****************************************************************************/
 /**
@@ -155,55 +155,55 @@ s32 XSdPs_Write(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
 * Identify type of card using CMD0 + CMD1 sequence
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
 ******************************************************************************/
 s32 XSdPs_IdentifyCard(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
-	if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
+    if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
 			((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
 			== XSDPS_CAPS_EMB_SLOT)) {
-		InstancePtr->CardType = XSDPS_CHIP_EMMC;
-		Status = XST_SUCCESS;
-		goto RETURN_PATH;
+	    InstancePtr->CardType = XSDPS_CHIP_EMMC;
+	    Status = XST_SUCCESS;
+	    goto RETURN_PATH;
 	}
 
 	/* 74 CLK delay after card is powered up, before the first command. */
-	usleep(XSDPS_INIT_DELAY);
+    usleep(XSDPS_INIT_DELAY);
 
 	/* CMD0 no response expected */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0U, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0U, 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Host High Capacity support & High voltage window */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
-			XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);
-	if (Status != XST_SUCCESS) {
-		InstancePtr->CardType = XSDPS_CARD_SD;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
+		    XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);
+    if (Status != XST_SUCCESS) {
+	    InstancePtr->CardType = XSDPS_CARD_SD;
 	} else {
-		InstancePtr->CardType = XSDPS_CARD_MMC;
+	    InstancePtr->CardType = XSDPS_CARD_MMC;
 	}
 
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
 
-	Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_CMD_LINE_MASK);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_CMD_LINE_MASK);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -212,50 +212,50 @@ RETURN_PATH:
 * SD initialization is done in this function
 *
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
 * 		- XST_FAILURE if failure - could be because
-* 			a) SD is already initialized
-* 			b) There is no card inserted
-* 			c) One of the steps (commands) in the
+* 		    a) SD is already initialized
+* 		    b) There is no card inserted
+* 		    c) One of the steps (commands) in the
 			   initialization cycle failed
 *
-* @note		This function initializes the SD card by following its
-*		initialization and identification state diagram.
-*		CMD0 is sent to reset card.
-*		CMD8 and ACDM41 are sent to identify voltage and
-*		high capacity support
-*		CMD2 and CMD3 are sent to obtain Card ID and
-*		Relative card address respectively.
-*		CMD9 is sent to read the card specific data.
+* @note	    This function initializes the SD card by following its
+*	    initialization and identification state diagram.
+*	    CMD0 is sent to reset card.
+*	    CMD8 and ACDM41 are sent to identify voltage and
+*	    high capacity support
+*	    CMD2 and CMD3 are sent to obtain Card ID and
+*	    Relative card address respectively.
+*	    CMD9 is sent to read the card specific data.
 *
 ******************************************************************************/
 s32 XSdPs_SdCardInitialize(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
 #ifndef UHS_MODE_ENABLE
-	InstancePtr->Config.BusWidth = XSDPS_WIDTH_4;
+    InstancePtr->Config.BusWidth = XSDPS_WIDTH_4;
 #endif
 
-	Status = XSdPs_SdCardEnum(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_SdCardEnum(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XSdPs_SdModeInit(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_SdModeInit(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 
 }
 
@@ -265,66 +265,66 @@ RETURN_PATH:
 * Mmc initialization is done in this function
 *
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
 * 		- XST_FAILURE if failure - could be because
-* 			a) MMC is already initialized
-* 			b) There is no card inserted
-* 			c) One of the steps (commands) in the initialization
+* 		    a) MMC is already initialized
+* 		    b) There is no card inserted
+* 		    c) One of the steps (commands) in the initialization
 *			   cycle failed
-* @note 	This function initializes the SD card by following its
-*		initialization and identification state diagram.
-*		CMD0 is sent to reset card.
-*		CMD1 sent to identify voltage and high capacity support
-*		CMD2 and CMD3 are sent to obtain Card ID and
-*		Relative card address respectively.
-*		CMD9 is sent to read the card specific data.
+* @note     This function initializes the SD card by following its
+*	    initialization and identification state diagram.
+*	    CMD0 is sent to reset card.
+*	    CMD1 sent to identify voltage and high capacity support
+*	    CMD2 and CMD3 are sent to obtain Card ID and
+*	    Relative card address respectively.
+*	    CMD9 is sent to read the card specific data.
 *
 ******************************************************************************/
 s32 XSdPs_MmcCardInitialize(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
-	Status = XSdPs_MmcCardEnum(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_MmcCardEnum(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	if (((InstancePtr->CardType == XSDPS_CARD_MMC) &&
+    if (((InstancePtr->CardType == XSDPS_CARD_MMC) &&
 				(InstancePtr->Card_Version > CSD_SPEC_VER_3)) &&
 				(InstancePtr->HC_Version == XSDPS_HC_SPEC_V2)) {
-		Status = XSdPs_MmcModeInit(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_MmcModeInit(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	} else if (InstancePtr->CardType == XSDPS_CHIP_EMMC) {
-		Status = XSdPs_EmmcModeInit(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_EmmcModeInit(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	} else {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 
 	}
 
-	if (InstancePtr->Mode != XSDPS_DDR52_MODE) {
-		Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+    if (InstancePtr->Mode != XSDPS_DDR52_MODE) {
+	    Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -332,40 +332,40 @@ RETURN_PATH:
 * @brief
 * This function checks if the card is present or not.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_CheckCardDetect(XSdPs *InstancePtr)
 {
-	u32 PresentStateReg;
-	s32 Status;
+    u32 PresentStateReg;
+    s32 Status;
 
-	if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
+    if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
 				((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
 				== XSDPS_CAPS_EMB_SLOT)) {
-		Status = XST_SUCCESS;
-		goto RETURN_PATH;
+	    Status = XST_SUCCESS;
+	    goto RETURN_PATH;
 	}
 
-	if(InstancePtr->Config.CardDetect != 0U) {
+    if(InstancePtr->Config.CardDetect != 0U) {
 		/*
 		 * Check the present state register to make sure
 		 * card is inserted and detected by host controller
 		 */
-		PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-				XSDPS_PRES_STATE_OFFSET);
-		if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U)	{
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+			    XSDPS_PRES_STATE_OFFSET);
+	    if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U)	{
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -373,22 +373,22 @@ RETURN_PATH:
 * @brief
 * This function sends CMD0 to reset the card.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_CardReset(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
 	/* CMD0 no response expected */
-	Status = XSdPs_CmdTransfer(InstancePtr, (u32)CMD0, 0U, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdPs_CmdTransfer(InstancePtr, (u32)CMD0, 0U, 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -396,47 +396,47 @@ s32 XSdPs_CardReset(XSdPs *InstancePtr)
 * @brief
 * This function sends command to get the card interface details.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_CardIfCond(XSdPs *InstancePtr)
 {
-	u32 RespOCR;
-	s32 Status;
+    u32 RespOCR;
+    s32 Status;
 
 	/*
 	 * CMD8; response expected
 	 * 0x1AA - Supply Voltage 2.7 - 3.6V and AA is pattern
 	 */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD8,
-			XSDPS_CMD8_VOL_PATTERN, 0U);
-	if ((Status != XST_SUCCESS) && (Status != XSDPS_CT_ERROR)) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD8,
+		    XSDPS_CMD8_VOL_PATTERN, 0U);
+    if ((Status != XST_SUCCESS) && (Status != XSDPS_CT_ERROR)) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	if (Status == XSDPS_CT_ERROR) {
-		Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_CMD_LINE_MASK);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH ;
+    if (Status == XSDPS_CT_ERROR) {
+	    Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_CMD_LINE_MASK);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH ;
 		}
 	}
 
-	RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-						XSDPS_RESP0_OFFSET);
-	if (RespOCR != XSDPS_CMD8_VOL_PATTERN) {
-		InstancePtr->Card_Version = XSDPS_SD_VER_1_0;
+    RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+					    XSDPS_RESP0_OFFSET);
+    if (RespOCR != XSDPS_CMD8_VOL_PATTERN) {
+	    InstancePtr->Card_Version = XSDPS_SD_VER_1_0;
 	} else {
-		InstancePtr->Card_Version = XSDPS_SD_VER_2_0;
+	    InstancePtr->Card_Version = XSDPS_SD_VER_2_0;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -444,68 +444,68 @@ RETURN_PATH:
 * @brief
 * This function sends command to get the card operating condition.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_CardOpCond(XSdPs *InstancePtr)
 {
-	u32 RespOCR;
-	s32 Status;
-	u32 Arg;
+    u32 RespOCR;
+    s32 Status;
+    u32 Arg;
 
 	/* Send ACMD41 while card is still busy with power up */
-	do {
-		if (InstancePtr->CardType == XSDPS_CARD_SD) {
-			Status = XSdPs_CmdTransfer(InstancePtr, CMD55, 0U, 0U);
-			if (Status != XST_SUCCESS) {
-				Status = XST_FAILURE;
-				goto RETURN_PATH;
+    do {
+	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+		    Status = XSdPs_CmdTransfer(InstancePtr, CMD55, 0U, 0U);
+		    if (Status != XST_SUCCESS) {
+			    Status = XST_FAILURE;
+			    goto RETURN_PATH;
 			}
 
-			Arg = XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3 | (0x1FFU << 15U);
-			if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
+		    Arg = XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3 | (0x1FFU << 15U);
+		    if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
 				(InstancePtr->Config.BusWidth == XSDPS_WIDTH_8)) {
-				Arg |= XSDPS_OCR_S18;
+			    Arg |= XSDPS_OCR_S18;
 			}
 
 			/* 0x40300000 - Host High Capacity support & 3.3V window */
-			Status = XSdPs_CmdTransfer(InstancePtr, ACMD41,
-					Arg, 0U);
+		    Status = XSdPs_CmdTransfer(InstancePtr, ACMD41,
+				    Arg, 0U);
 		} else {
 			/* Send CMD1 while card is still busy with power up */
-			Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
-					XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);
+		    Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
+				    XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);
 		}
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 
 		/* Response with card capacity */
-		RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-				XSDPS_RESP0_OFFSET);
+	    RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+			    XSDPS_RESP0_OFFSET);
 	} while ((RespOCR & XSDPS_RESPOCR_READY) == 0U);
 
 	/* Update HCS support flag based on card capacity response */
-	if ((RespOCR & XSDPS_ACMD41_HCS) != 0U) {
-		InstancePtr->HCS = 1U;
+    if ((RespOCR & XSDPS_ACMD41_HCS) != 0U) {
+	    InstancePtr->HCS = 1U;
 	}
 
-	if ((RespOCR & XSDPS_OCR_S18) != 0U) {
-		InstancePtr->Switch1v8 = 1U;
-		Status = XSdPs_Switch_Voltage(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+    if ((RespOCR & XSDPS_OCR_S18) != 0U) {
+	    InstancePtr->Switch1v8 = 1U;
+	    Status = XSdPs_Switch_Voltage(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -513,65 +513,65 @@ RETURN_PATH:
 * @brief
 * This function is used to get the card ID.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_GetCardId(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
 	/* CMD2 for Card ID */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0U, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0U, 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	InstancePtr->CardID[0] =
-			XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_RESP0_OFFSET);
-	InstancePtr->CardID[1] =
-			XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_RESP1_OFFSET);
-	InstancePtr->CardID[2] =
-			XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_RESP2_OFFSET);
-	InstancePtr->CardID[3] =
-			XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_RESP3_OFFSET);
+    InstancePtr->CardID[0] =
+		    XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_RESP0_OFFSET);
+    InstancePtr->CardID[1] =
+		    XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_RESP1_OFFSET);
+    InstancePtr->CardID[2] =
+		    XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_RESP2_OFFSET);
+    InstancePtr->CardID[3] =
+		    XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_RESP3_OFFSET);
 
-	if(InstancePtr->CardType == XSDPS_CARD_SD) {
-		do {
-			Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0U, 0U);
-			if (Status != XST_SUCCESS) {
-				Status = XST_FAILURE;
-				goto RETURN_PATH;
+    if(InstancePtr->CardType == XSDPS_CARD_SD) {
+	    do {
+		    Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0U, 0U);
+		    if (Status != XST_SUCCESS) {
+			    Status = XST_FAILURE;
+			    goto RETURN_PATH;
 			}
 
 			/*
 			 * Relative card address is stored as the upper 16 bits
 			 * This is to avoid shifting when sending commands
 			 */
-			InstancePtr->RelCardAddr =
-					XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-						XSDPS_RESP0_OFFSET) & 0xFFFF0000U;
+		    InstancePtr->RelCardAddr =
+				    XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+					    XSDPS_RESP0_OFFSET) & 0xFFFF0000U;
 		} while (InstancePtr->RelCardAddr == 0U);
 	} else {
 		/* Set relative card address */
-		InstancePtr->RelCardAddr = 0x12340000U;
-		Status = XSdPs_CmdTransfer(InstancePtr, CMD3, (InstancePtr->RelCardAddr), 0U);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    InstancePtr->RelCardAddr = 0x12340000U;
+	    Status = XSdPs_CmdTransfer(InstancePtr, CMD3, (InstancePtr->RelCardAddr), 0U);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -579,64 +579,64 @@ RETURN_PATH:
 * @brief
 * This function is used to get the CSD register from the card.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_GetCsd(XSdPs *InstancePtr)
 {
-	s32 Status;
-	u32 CSD[4];
-	u32 BlkLen;
-	u32 DeviceSize;
-	u32 Mult;
+    s32 Status;
+    u32 CSD[4];
+    u32 BlkLen;
+    u32 DeviceSize;
+    u32 Mult;
 
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/*
 	 * Card specific data is read.
 	 * Currently not used for any operation.
 	 */
-	CSD[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-			XSDPS_RESP0_OFFSET);
-	CSD[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-			XSDPS_RESP1_OFFSET);
-	CSD[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-			XSDPS_RESP2_OFFSET);
-	CSD[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-			XSDPS_RESP3_OFFSET);
+    CSD[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+		    XSDPS_RESP0_OFFSET);
+    CSD[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+		    XSDPS_RESP1_OFFSET);
+    CSD[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+		    XSDPS_RESP2_OFFSET);
+    CSD[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+		    XSDPS_RESP3_OFFSET);
 
-	if (InstancePtr->CardType != XSDPS_CARD_SD) {
-		InstancePtr->Card_Version = (u8)((u32)(CSD[3] & CSD_SPEC_VER_MASK) >>18U);
-		Status = XST_SUCCESS;
-		goto RETURN_PATH;
+    if (InstancePtr->CardType != XSDPS_CARD_SD) {
+	    InstancePtr->Card_Version = (u8)((u32)(CSD[3] & CSD_SPEC_VER_MASK) >>18U);
+	    Status = XST_SUCCESS;
+	    goto RETURN_PATH;
 	}
 
-	if (((CSD[3] & CSD_STRUCT_MASK) >> 22U) == 0U) {
-		BlkLen = 1U << ((u32)(CSD[2] & READ_BLK_LEN_MASK) >> 8U);
-		Mult = 1U << ((u32)((CSD[1] & C_SIZE_MULT_MASK) >> 7U) + 2U);
-		DeviceSize = (CSD[1] & C_SIZE_LOWER_MASK) >> 22U;
-		DeviceSize |= (CSD[2] & C_SIZE_UPPER_MASK) << 10U;
-		DeviceSize = (DeviceSize + 1U) * Mult;
-		DeviceSize =  DeviceSize * BlkLen;
-		InstancePtr->SectorCount = (DeviceSize/XSDPS_BLK_SIZE_512_MASK);
+    if (((CSD[3] & CSD_STRUCT_MASK) >> 22U) == 0U) {
+	    BlkLen = 1U << ((u32)(CSD[2] & READ_BLK_LEN_MASK) >> 8U);
+	    Mult = 1U << ((u32)((CSD[1] & C_SIZE_MULT_MASK) >> 7U) + 2U);
+	    DeviceSize = (CSD[1] & C_SIZE_LOWER_MASK) >> 22U;
+	    DeviceSize |= (CSD[2] & C_SIZE_UPPER_MASK) << 10U;
+	    DeviceSize = (DeviceSize + 1U) * Mult;
+	    DeviceSize =  DeviceSize * BlkLen;
+	    InstancePtr->SectorCount = (DeviceSize/XSDPS_BLK_SIZE_512_MASK);
 	} else if (((CSD[3] & CSD_STRUCT_MASK) >> 22U) == 1U) {
-		InstancePtr->SectorCount = (((CSD[1] & CSD_V2_C_SIZE_MASK) >> 8U) +
-										1U) * 1024U;
+	    InstancePtr->SectorCount = (((CSD[1] & CSD_V2_C_SIZE_MASK) >> 8U) +
+									    1U) * 1024U;
 	} else {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -644,46 +644,46 @@ RETURN_PATH:
 * @brief
 * This function is used to set the card voltage to 1.8V.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_CardSetVoltage18(XSdPs *InstancePtr)
 {
-	s32 Status;
-	u16 CtrlReg;
-	u16 ClockReg;
+    s32 Status;
+    u16 CtrlReg;
+    u16 ClockReg;
 
 	/* Stop the clock */
-	CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_CLK_CTRL_OFFSET);
-	CtrlReg &= ~(XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_CLK_EN_MASK);
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,
-			CtrlReg);
+    CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_CLK_CTRL_OFFSET);
+    CtrlReg &= ~(XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_CLK_EN_MASK);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,
+		    CtrlReg);
 
 	/* Check for 1.8V signal enable bit is cleared by Host */
-	Status = XSdPs_SetVoltage18(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_SetVoltage18(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				XSDPS_CLK_CTRL_OFFSET);
+    ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+			    XSDPS_CLK_CTRL_OFFSET);
 	/* Enable the clock in the controller */
-	Status = XSdPs_EnableClock(InstancePtr, ClockReg);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdPs_EnableClock(InstancePtr, ClockReg);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
 	/* Wait for 1mSec */
 	(void)usleep(1000U);
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -691,27 +691,27 @@ RETURN_PATH:
 * @brief
 * This function is used to do initial Reset Configuration.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_ResetConfig(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
-	XSdPs_DisableBusPower(InstancePtr);
+    XSdPs_DisableBusPower(InstancePtr);
 
-	Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
-	XSdPs_EnableBusPower(InstancePtr);
+    XSdPs_EnableBusPower(InstancePtr);
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -719,29 +719,29 @@ RETURN_PATH:
 * @brief
 * This function is used to do initial Host Configuration.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 void XSdPs_HostConfig(XSdPs *InstancePtr)
 {
-	XSdPs_ConfigPower(InstancePtr);
+    XSdPs_ConfigPower(InstancePtr);
 
-	XSdPs_ConfigDma(InstancePtr);
+    XSdPs_ConfigDma(InstancePtr);
 
-	XSdPs_ConfigInterrupt(InstancePtr);
+    XSdPs_ConfigInterrupt(InstancePtr);
 
 	/*
 	 * Transfer mode register - default value
 	 * DMA enabled, block count enabled, data direction card to host(read)
 	 */
-	InstancePtr->TransferMode = XSDPS_TM_DMA_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK |
-			XSDPS_TM_DAT_DIR_SEL_MASK;
+    InstancePtr->TransferMode = XSDPS_TM_DMA_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK |
+		    XSDPS_TM_DAT_DIR_SEL_MASK;
 
 	/* Set block size to 512 by default */
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK);
 }
 
 /*****************************************************************************/
@@ -749,36 +749,36 @@ void XSdPs_HostConfig(XSdPs *InstancePtr)
 * @brief
 * This function checks for Reset Done bits to be cleared after a reset assert.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Value is the bits to be checked to be cleared.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Value is the bits to be checked to be cleared.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_CheckResetDone(XSdPs *InstancePtr, u8 Value)
 {
-	u32 Timeout = 1000000U;
-	u32 ReadReg;
-	s32 Status;
+    u32 Timeout = 1000000U;
+    u32 ReadReg;
+    s32 Status;
 
 	/* Proceed with initialization only after reset is complete */
-	do {
-		ReadReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
-				XSDPS_SW_RST_OFFSET);
-		Timeout = Timeout - 1U;
-		usleep(1);
+    do {
+	    ReadReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
+			    XSDPS_SW_RST_OFFSET);
+	    Timeout = Timeout - 1U;
+	    usleep(1);
 	} while (((ReadReg & Value) != 0U)
 			&& (Timeout != 0U));
 
-	if (Timeout == 0U) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    if (Timeout == 0U) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -786,41 +786,41 @@ RETURN_PATH:
 * @brief
 * This function is used to setup the voltage switch.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_SetupVoltageSwitch(XSdPs *InstancePtr)
 {
-	u32 Timeout = 10000;
-	s32 Status;
-	u32 ReadReg;
+    u32 Timeout = 10000;
+    s32 Status;
+    u32 ReadReg;
 
 	/* Send switch voltage command */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD11, 0U, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD11, 0U, 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Wait for CMD and DATA line to go low */
-	do {
-		ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-				XSDPS_PRES_STATE_OFFSET);
-		Timeout = Timeout - 1;
-		usleep(1);
+    do {
+	    ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+			    XSDPS_PRES_STATE_OFFSET);
+	    Timeout = Timeout - 1;
+	    usleep(1);
 	} while (((ReadReg & (XSDPS_PSR_CMD_SG_LVL_MASK |
-			XSDPS_PSR_DAT30_SG_LVL_MASK)) != 0U)
+		    XSDPS_PSR_DAT30_SG_LVL_MASK)) != 0U)
 			&& (Timeout != 0U));
 
-	if (Timeout == 0U) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    if (Timeout == 0U) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -828,37 +828,37 @@ RETURN_PATH:
 * @brief
 * This function is used to check if the Cmd and Dat buses are high.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_CheckBusHigh(XSdPs *InstancePtr)
 {
-	u32 Timeout = 10000;
-	s32 Status;
-	u32 ReadReg;
+    u32 Timeout = 10000;
+    s32 Status;
+    u32 ReadReg;
 
 	/* Wait for CMD and DATA line to go high */
-	Timeout = MAX_TIMEOUT;
-	do {
-		ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-				XSDPS_PRES_STATE_OFFSET);
-		Timeout = Timeout - 1;
-		usleep(1);
+    Timeout = MAX_TIMEOUT;
+    do {
+	    ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+			    XSDPS_PRES_STATE_OFFSET);
+	    Timeout = Timeout - 1;
+	    usleep(1);
 	} while (((ReadReg & (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK))
 			!= (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK))
 			&& (Timeout != 0U));
 
-	if (Timeout == 0U) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    if (Timeout == 0U) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -870,40 +870,40 @@ RETURN_PATH:
 * supported bus speed.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	ReadBuff contains the response for CMD6
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    ReadBuff contains the response for CMD6
 *
-* @return	None.
+* @return    None.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 void XSdPs_Identify_UhsMode(XSdPs *InstancePtr, u8 *ReadBuff)
 {
-	if (((ReadBuff[13] & UHS_SDR104_SUPPORT) != 0U) &&
+    if (((ReadBuff[13] & UHS_SDR104_SUPPORT) != 0U) &&
 		(InstancePtr->Config.InputClockHz >= XSDPS_SD_INPUT_MAX_CLK)) {
-		InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR104;
-		if (InstancePtr->Config.BankNumber == 2U) {
-			InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2;
+	    InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR104;
+	    if (InstancePtr->Config.BankNumber == 2U) {
+		    InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2;
 		} else {
-			InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0;
+		    InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0;
 		}
 	} else if (((ReadBuff[13] & UHS_SDR50_SUPPORT) != 0U) &&
 		(InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR50_MAX_CLK)) {
-		InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR50;
-		InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD50;
+	    InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR50;
+	    InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD50;
 	} else if (((ReadBuff[13] & UHS_DDR50_SUPPORT) != 0U) &&
 		(InstancePtr->Config.InputClockHz >= XSDPS_SD_DDR50_MAX_CLK)) {
-		InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_DDR50;
-		InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_DDR50;
-		InstancePtr->ITapDelay = SD_ITAPDLYSEL_SD_DDR50;
+	    InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_DDR50;
+	    InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_DDR50;
+	    InstancePtr->ITapDelay = SD_ITAPDLYSEL_SD_DDR50;
 	} else if (((ReadBuff[13] & UHS_SDR25_SUPPORT) != 0U) &&
 		(InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR25_MAX_CLK)) {
-		InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR25;
-		InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD;
-		InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
+	    InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR25;
+	    InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD;
+	    InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
 	} else {
-		InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR12;
+	    InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR12;
 	}
 }
 
@@ -914,31 +914,31 @@ void XSdPs_Identify_UhsMode(XSdPs *InstancePtr, u8 *ReadBuff)
 * API to set Tap Delay w.r.t speed modes
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
-* @return	None
+* @return    None
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 void XSdPs_SetTapDelay(XSdPs *InstancePtr)
 {
-	if ((InstancePtr->Mode == XSDPS_DEFAULT_SPEED_MODE) ||
+    if ((InstancePtr->Mode == XSDPS_DEFAULT_SPEED_MODE) ||
 		(InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR12)) {
-		return;
+	    return;
 	}
 
 #ifndef versal
 	/* Issue DLL Reset */
-	XSdPs_DllRstCtrl(InstancePtr, 1U);
+    XSdPs_DllRstCtrl(InstancePtr, 1U);
 #endif
 
 	/* Configure the Tap Delay Registers */
-	XSdPs_ConfigTapDelay(InstancePtr);
+    XSdPs_ConfigTapDelay(InstancePtr);
 
 #ifndef versal
 	/* Release the DLL out of reset */
-	XSdPs_DllRstCtrl(InstancePtr, 0U);
+    XSdPs_DllRstCtrl(InstancePtr, 0U);
 #endif
 }
 
@@ -947,57 +947,57 @@ void XSdPs_SetTapDelay(XSdPs *InstancePtr)
 * @brief
 * This function is used to change the SD Bus Speed.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_Change_SdBusSpeed(XSdPs *InstancePtr)
 {
-	s32 Status;
-	u32 Arg;
-	u16 BlkCnt;
-	u16 BlkSize;
-	u16 CtrlReg;
-	u8 ReadBuff[64] = {0U};
+    s32 Status;
+    u32 Arg;
+    u16 BlkCnt;
+    u16 BlkSize;
+    u16 CtrlReg;
+    u8 ReadBuff[64] = {0U};
 
-	Status = XSdPs_CalcBusSpeed(InstancePtr, &Arg);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CalcBusSpeed(InstancePtr, &Arg);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
-	BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
+    BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
+    BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
 
-	XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
+    XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
 
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, BlkCnt);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, BlkCnt);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	if (InstancePtr->Switch1v8 != 0U) {
+    if (InstancePtr->Switch1v8 != 0U) {
 		/* Set UHS mode in controller */
-		CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				XSDPS_HOST_CTRL2_OFFSET);
-		CtrlReg &= (u16)(~XSDPS_HC2_UHS_MODE_MASK);
-		XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-						XSDPS_HOST_CTRL2_OFFSET,
-						CtrlReg | InstancePtr->Mode);
+	    CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+			    XSDPS_HOST_CTRL2_OFFSET);
+	    CtrlReg &= (u16)(~XSDPS_HC2_UHS_MODE_MASK);
+	    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+					    XSDPS_HOST_CTRL2_OFFSET,
+					    CtrlReg | InstancePtr->Mode);
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -1005,38 +1005,38 @@ RETURN_PATH:
 * @brief
 * This function is used to change the eMMC bus speed.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_Change_MmcBusSpeed(XSdPs *InstancePtr)
 {
-	s32 Status;
-	u32 Arg;
+    s32 Status;
+    u32 Arg;
 
-	Status = XSdPs_CalcBusSpeed(InstancePtr, &Arg);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CalcBusSpeed(InstancePtr, &Arg);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -1044,29 +1044,29 @@ RETURN_PATH:
 * @brief
 * This function is used to do the Auto tuning.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_AutoTuning(XSdPs *InstancePtr)
 {
-	s32 Status;
-	u16 BlkSize;
-	u8 TuningCount;
+    s32 Status;
+    u16 BlkSize;
+    u8 TuningCount;
 
-	BlkSize = XSDPS_TUNING_CMD_BLKSIZE;
-	if(InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH)
+    BlkSize = XSDPS_TUNING_CMD_BLKSIZE;
+    if(InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH)
 	{
-		BlkSize = BlkSize*2U;
+	    BlkSize = BlkSize*2U;
 	}
-	BlkSize &= XSDPS_BLK_SIZE_MASK;
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
-			BlkSize);
+    BlkSize &= XSDPS_BLK_SIZE_MASK;
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
+		    BlkSize);
 
-	InstancePtr->TransferMode = XSDPS_TM_DAT_DIR_SEL_MASK;
+    InstancePtr->TransferMode = XSDPS_TM_DAT_DIR_SEL_MASK;
 
-	XSdPs_SetExecTuning(InstancePtr);
+    XSdPs_SetExecTuning(InstancePtr);
 	/*
 	 * workaround which can work for 1.0/2.0 silicon for auto tuning.
 	 * This can be revisited for 3.0 silicon if necessary.
@@ -1074,38 +1074,38 @@ s32 XSdPs_AutoTuning(XSdPs *InstancePtr)
 	/* Wait for ~60 clock cycles to reset the tap values */
 	(void)usleep(1U);
 
-	for (TuningCount = 0U; TuningCount < MAX_TUNING_COUNT; TuningCount++) {
+    for (TuningCount = 0U; TuningCount < MAX_TUNING_COUNT; TuningCount++) {
 
-		if (InstancePtr->CardType == XSDPS_CARD_SD) {
-			Status = XSdPs_CmdTransfer(InstancePtr, CMD19, 0U, 1U);
+	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+		    Status = XSdPs_CmdTransfer(InstancePtr, CMD19, 0U, 1U);
 		} else {
-			Status = XSdPs_CmdTransfer(InstancePtr, CMD21, 0U, 1U);
+		    Status = XSdPs_CmdTransfer(InstancePtr, CMD21, 0U, 1U);
 		}
 
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 
-		if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_EXEC_TNG_MASK) == 0U) {
-			break;
+	    if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+			    XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_EXEC_TNG_MASK) == 0U) {
+		    break;
 		}
 	}
 
-	if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_SAMP_CLK_SEL_MASK) == 0U) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_SAMP_CLK_SEL_MASK) == 0U) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Wait for ~12 clock cycles to synchronize the new tap values */
 	(void)usleep(1U);
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -1115,21 +1115,21 @@ RETURN_PATH:
 * API to setup ADMA2 descriptor table
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	BlkCnt - block count.
-* @param	Buff pointer to data buffer.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    BlkCnt - block count.
+* @param    Buff pointer to data buffer.
 *
-* @return	None
+* @return    None
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
 {
-	if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-		XSdPs_Setup64ADMA2DescTbl(InstancePtr, BlkCnt, Buff);
+    if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
+	    XSdPs_Setup64ADMA2DescTbl(InstancePtr, BlkCnt, Buff);
 	} else {
-		XSdPs_Setup32ADMA2DescTbl(InstancePtr, BlkCnt, Buff);
+	    XSdPs_Setup32ADMA2DescTbl(InstancePtr, BlkCnt, Buff);
 	}
 }
 
@@ -1140,73 +1140,73 @@ void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
 * API to setup ADMA2 descriptor table for 64 Bit DMA
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	BlkCnt - block count.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    BlkCnt - block count.
 *
-* @return	None
+* @return    None
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 void XSdPs_SetupADMA2DescTbl64Bit(XSdPs *InstancePtr, u32 BlkCnt)
 {
 #ifdef __ICCARM__
 #pragma data_alignment = 32
-	static XSdPs_Adma2Descriptor64 Adma2_DescrTbl[32];
+    static XSdPs_Adma2Descriptor64 Adma2_DescrTbl[32];
 #else
-	static XSdPs_Adma2Descriptor64 Adma2_DescrTbl[32] __attribute__ ((aligned(32)));
+    static XSdPs_Adma2Descriptor64 Adma2_DescrTbl[32] __attribute__ ((aligned(32)));
 #endif
-	u32 TotalDescLines;
-	u64 DescNum;
-	u32 BlkSize;
+    u32 TotalDescLines;
+    u64 DescNum;
+    u32 BlkSize;
 
 	/* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */
-	BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_BLK_SIZE_OFFSET) &
-					XSDPS_BLK_SIZE_MASK;
+    BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+				    XSDPS_BLK_SIZE_OFFSET) &
+				    XSDPS_BLK_SIZE_MASK;
 
-	if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
+    if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
 
-		TotalDescLines = 1U;
+	    TotalDescLines = 1U;
 
 	} else {
 
-		TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
-		if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
-			TotalDescLines += 1U;
+	    TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
+	    if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
+		    TotalDescLines += 1U;
 		}
 
 	}
 
-	for (DescNum = 0U; DescNum < (TotalDescLines-1); DescNum++) {
-		Adma2_DescrTbl[DescNum].Address =
-				InstancePtr->Dma64BitAddr +
+    for (DescNum = 0U; DescNum < (TotalDescLines-1); DescNum++) {
+	    Adma2_DescrTbl[DescNum].Address =
+			    InstancePtr->Dma64BitAddr +
 				(DescNum*XSDPS_DESC_MAX_LENGTH);
-		Adma2_DescrTbl[DescNum].Attribute =
-				XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
-		Adma2_DescrTbl[DescNum].Length = 0U;
+	    Adma2_DescrTbl[DescNum].Attribute =
+			    XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
+	    Adma2_DescrTbl[DescNum].Length = 0U;
 	}
 
-	Adma2_DescrTbl[TotalDescLines-1].Address =
-				InstancePtr->Dma64BitAddr +
+    Adma2_DescrTbl[TotalDescLines-1].Address =
+			    InstancePtr->Dma64BitAddr +
 				(DescNum*XSDPS_DESC_MAX_LENGTH);
 
-	Adma2_DescrTbl[TotalDescLines-1].Attribute =
-			XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
+    Adma2_DescrTbl[TotalDescLines-1].Attribute =
+		    XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
 
-	Adma2_DescrTbl[TotalDescLines-1].Length =
+    Adma2_DescrTbl[TotalDescLines-1].Length =
 			(u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH));
 
-	XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
+    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
 			(u32)((UINTPTR)&(Adma2_DescrTbl[0]) & (u32)~0x0));
 
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
-			sizeof(XSdPs_Adma2Descriptor64) * 32U);
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+	    Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
+		    sizeof(XSdPs_Adma2Descriptor64) * 32U);
 	}
 
 	/* Clear the 64-Bit Address variable */
-	InstancePtr->Dma64BitAddr = 0U;
+    InstancePtr->Dma64BitAddr = 0U;
 
 }
 
@@ -1217,42 +1217,42 @@ void XSdPs_SetupADMA2DescTbl64Bit(XSdPs *InstancePtr, u32 BlkCnt)
 * API to reset the DLL
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
-* @return	None
+* @return    None
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 s32 XSdPs_DllReset(XSdPs *InstancePtr)
 {
-	u32 ClockReg;
-	s32 Status;
+    u32 ClockReg;
+    s32 Status;
 
 	/* Disable clock */
-	ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_CLK_CTRL_OFFSET);
-	ClockReg &= ~XSDPS_CC_SD_CLK_EN_MASK;
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_CLK_CTRL_OFFSET, (u16)ClockReg);
+    ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_CLK_CTRL_OFFSET);
+    ClockReg &= ~XSDPS_CC_SD_CLK_EN_MASK;
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_CLK_CTRL_OFFSET, (u16)ClockReg);
 
 	/* Issue DLL Reset to load zero tap values */
-	XSdPs_DllRstCtrl(InstancePtr, 1U);
+    XSdPs_DllRstCtrl(InstancePtr, 1U);
 
 	/* Wait for 2 micro seconds */
 	(void)usleep(2U);
 
-	XSdPs_DllRstCtrl(InstancePtr, 0U);
+    XSdPs_DllRstCtrl(InstancePtr, 0U);
 
-	ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				XSDPS_CLK_CTRL_OFFSET);
+    ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+			    XSDPS_CLK_CTRL_OFFSET);
 	/* Enable the clock in the controller */
-	Status = XSdPs_EnableClock(InstancePtr, ClockReg);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdPs_EnableClock(InstancePtr, ClockReg);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -1260,40 +1260,40 @@ s32 XSdPs_DllReset(XSdPs *InstancePtr)
 * @brief
 * This function is used to identify the eMMC speed mode.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	ExtCsd is the extended CSD register from the card
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    ExtCsd is the extended CSD register from the card
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 void XSdPs_IdentifyEmmcMode(XSdPs *InstancePtr, const u8 *ExtCsd)
 {
-	if (InstancePtr->BusWidth < XSDPS_4_BIT_WIDTH) {
-		InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
+    if (InstancePtr->BusWidth < XSDPS_4_BIT_WIDTH) {
+	    InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
 	} else {
 		/* Check for card supported speed */
-		if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
+	    if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
 				(EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 |
-				EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200)) != 0U) {
-			InstancePtr->Mode = XSDPS_HS200_MODE;
-			if (InstancePtr->Config.BankNumber == 2U) {
-				InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2;
+			    EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200)) != 0U) {
+		    InstancePtr->Mode = XSDPS_HS200_MODE;
+		    if (InstancePtr->Config.BankNumber == 2U) {
+			    InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2;
 			} else {
-				InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0;
+			    InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0;
 			}
 		} else if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
 				(EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED |
-				EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED)) != 0U) {
-			InstancePtr->Mode = XSDPS_DDR52_MODE;
-			InstancePtr->OTapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
-			InstancePtr->ITapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
+			    EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED)) != 0U) {
+		    InstancePtr->Mode = XSDPS_DDR52_MODE;
+		    InstancePtr->OTapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
+		    InstancePtr->ITapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
 		} else if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
-				EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) {
-			InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
-			InstancePtr->OTapDelay = SD_OTAPDLYSEL_EMMC_HSD;
-			InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
+			    EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) {
+		    InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
+		    InstancePtr->OTapDelay = SD_OTAPDLYSEL_EMMC_HSD;
+		    InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
 		} else {
-			InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
+		    InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
 		}
 	}
 }
@@ -1303,39 +1303,39 @@ void XSdPs_IdentifyEmmcMode(XSdPs *InstancePtr, const u8 *ExtCsd)
 * @brief
 * This function is used to check the eMMC timing.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	ExtCsd is the extended CSD register from the card
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    ExtCsd is the extended CSD register from the card
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_CheckEmmcTiming(XSdPs *InstancePtr, u8 *ExtCsd)
 {
-	s32 Status;
+    s32 Status;
 
-	Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	if (InstancePtr->Mode == XSDPS_HS200_MODE) {
-		if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HS200) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+    if (InstancePtr->Mode == XSDPS_HS200_MODE) {
+	    if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HS200) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	} else if ((InstancePtr->Mode == XSDPS_HIGH_SPEED_MODE) ||
 			(InstancePtr->Mode == XSDPS_DDR52_MODE)) {
-		if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	} else {
-		Status = XST_FAILURE;
+	    Status = XST_FAILURE;
 	}
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -1343,38 +1343,38 @@ RETURN_PATH:
 * @brief
 * This function is used to set the clock to the passed frequency.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	SelFreq is the selected frequency
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    SelFreq is the selected frequency
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_SetClock(XSdPs *InstancePtr, u32 SelFreq)
 {
-	u16 ClockReg;
-	s32 Status;
+    u16 ClockReg;
+    s32 Status;
 
 	/* Disable clock */
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_CLK_CTRL_OFFSET, 0U);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_CLK_CTRL_OFFSET, 0U);
 
 	/* If selected frequency is zero, return from here */
-	if (SelFreq == 0U) {
-		Status = XST_SUCCESS;
-		goto RETURN_PATH ;
+    if (SelFreq == 0U) {
+	    Status = XST_SUCCESS;
+	    goto RETURN_PATH ;
 	}
 
 	/* Calculate the clock */
-	ClockReg = XSdPs_CalcClock(InstancePtr, SelFreq);
+    ClockReg = XSdPs_CalcClock(InstancePtr, SelFreq);
 
 	/* Enable the clock in the controller */
-	Status = XSdPs_EnableClock(InstancePtr, ClockReg);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdPs_EnableClock(InstancePtr, ClockReg);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -1382,7 +1382,7 @@ RETURN_PATH:
 * @brief
 * This function checks if the voltage is set to 1.8V or not.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
 * 		- XST_SUCCESS if voltage is 1.8V
@@ -1391,18 +1391,18 @@ RETURN_PATH:
 ******************************************************************************/
 s32 XSdPs_CheckVoltage18(XSdPs *InstancePtr)
 {
-	u32 Status;
+    u32 Status;
 
-	if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_1V8_EN_MASK) == 0U) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_1V8_EN_MASK) == 0U) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -1410,48 +1410,48 @@ RETURN_PATH:
 * @brief
 * This function initializes the command sequence.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Arg is the address passed by the user that is to be sent as
-* 		argument along with the command.
-* @param	BlkCnt - Block count passed by the user.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Arg is the address passed by the user that is to be sent as
+* 	    argument along with the command.
+* @param    BlkCnt - Block count passed by the user.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_SetupCmd(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt)
 {
-	s32 Status;
+    s32 Status;
 
 	/*
 	 * Check the command inhibit to make sure no other
 	 * command transfer is in progress
 	 */
-	Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
 	/* Write block count register */
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_BLK_CNT_OFFSET, (u16)BlkCnt);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_BLK_CNT_OFFSET, (u16)BlkCnt);
 
-	XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			XSDPS_TIMEOUT_CTRL_OFFSET, 0xEU);
+    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+		    XSDPS_TIMEOUT_CTRL_OFFSET, 0xEU);
 
 	/* Write argument register */
-	XSdPs_WriteReg(InstancePtr->Config.BaseAddress,
-			XSDPS_ARGMT_OFFSET, Arg);
+    XSdPs_WriteReg(InstancePtr->Config.BaseAddress,
+		    XSDPS_ARGMT_OFFSET, Arg);
 
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -1459,8 +1459,8 @@ RETURN_PATH:
 * @brief
 * This function initiates the Cmd transfer to SD card.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Cmd is the command to be sent
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Cmd is the command to be sent
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
@@ -1469,41 +1469,41 @@ RETURN_PATH:
 ******************************************************************************/
 s32 XSdPs_SendCmd(XSdPs *InstancePtr, u32 Cmd)
 {
-	u32 PresentStateReg;
-	u32 CommandReg;
-	s32 Status;
+    u32 PresentStateReg;
+    u32 CommandReg;
+    s32 Status;
 
 	/* Command register is set to trigger transfer of command */
-	CommandReg = XSdPs_FrameCmd(InstancePtr, Cmd);
+    CommandReg = XSdPs_FrameCmd(InstancePtr, Cmd);
 
 	/*
 	 * Mask to avoid writing to reserved bits 31-30
 	 * This is necessary because 0x8000 is used  by this software to
 	 * distinguish between ACMD and CMD of same number
 	 */
-	CommandReg = CommandReg & 0x3FFFU;
+    CommandReg = CommandReg & 0x3FFFU;
 
 	/*
 	 * Check for data inhibit in case of command using DAT lines.
 	 * For Tuning Commands DAT lines check can be ignored.
 	 */
-	if ((Cmd != CMD21) && (Cmd != CMD19)) {
-		PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-				XSDPS_PRES_STATE_OFFSET);
-		if (((PresentStateReg & XSDPS_PSR_INHIBIT_DAT_MASK) != 0U) &&
+    if ((Cmd != CMD21) && (Cmd != CMD19)) {
+	    PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+			    XSDPS_PRES_STATE_OFFSET);
+	    if (((PresentStateReg & XSDPS_PSR_INHIBIT_DAT_MASK) != 0U) &&
 				((CommandReg & XSDPS_DAT_PRESENT_SEL_MASK) != 0U)) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET,
+    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET,
 			(CommandReg << 16) | InstancePtr->TransferMode);
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 
 }
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c
index 17956382b0..f3c01598f0 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c
@@ -6,9 +6,9 @@
 * DO NOT EDIT.
 *
 * Copyright (C) 2010-2020 Xilinx, Inc. All Rights Reserved.
-* SPDX-License-Identifier: MIT 
+* SPDX-License-Identifier: MIT
 
-* 
+*
 * Description: Driver configuration
 *
 *******************************************************************/
@@ -23,26 +23,26 @@
 XSdPs_Config XSdPs_ConfigTable[XPAR_XSDPS_NUM_INSTANCES] =
 {
 	{
-		XPAR_PSU_SD_0_DEVICE_ID,
-		XPAR_PSU_SD_0_BASEADDR,
-		XPAR_PSU_SD_0_SDIO_CLK_FREQ_HZ,
-		XPAR_PSU_SD_0_HAS_CD,
-		XPAR_PSU_SD_0_HAS_WP,
-		XPAR_PSU_SD_0_BUS_WIDTH,
-		XPAR_PSU_SD_0_MIO_BANK,
-		XPAR_PSU_SD_0_HAS_EMIO,
-		XPAR_PSU_SD_0_IS_CACHE_COHERENT
+	    XPAR_PSU_SD_0_DEVICE_ID,
+	    XPAR_PSU_SD_0_BASEADDR,
+	    XPAR_PSU_SD_0_SDIO_CLK_FREQ_HZ,
+	    XPAR_PSU_SD_0_HAS_CD,
+	    XPAR_PSU_SD_0_HAS_WP,
+	    XPAR_PSU_SD_0_BUS_WIDTH,
+	    XPAR_PSU_SD_0_MIO_BANK,
+	    XPAR_PSU_SD_0_HAS_EMIO,
+	    XPAR_PSU_SD_0_IS_CACHE_COHERENT
 	},
 	{
-		XPAR_PSU_SD_1_DEVICE_ID,
-		XPAR_PSU_SD_1_BASEADDR,
-		XPAR_PSU_SD_1_SDIO_CLK_FREQ_HZ,
-		XPAR_PSU_SD_1_HAS_CD,
-		XPAR_PSU_SD_1_HAS_WP,
-		XPAR_PSU_SD_1_BUS_WIDTH,
-		XPAR_PSU_SD_1_MIO_BANK,
-		XPAR_PSU_SD_1_HAS_EMIO,
-		XPAR_PSU_SD_1_IS_CACHE_COHERENT
+	    XPAR_PSU_SD_1_DEVICE_ID,
+	    XPAR_PSU_SD_1_BASEADDR,
+	    XPAR_PSU_SD_1_SDIO_CLK_FREQ_HZ,
+	    XPAR_PSU_SD_1_HAS_CD,
+	    XPAR_PSU_SD_1_HAS_WP,
+	    XPAR_PSU_SD_1_BUS_WIDTH,
+	    XPAR_PSU_SD_1_MIO_BANK,
+	    XPAR_PSU_SD_1_HAS_EMIO,
+	    XPAR_PSU_SD_1_IS_CACHE_COHERENT
 	}
 };
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c
index 25b5bc54cc..cdfa65d125 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c
@@ -40,7 +40,7 @@
 void XSdps_Smc(XSdPs *InstancePtr, u32 RegOffset, u32 Mask, u32 Val)
 {
 	(void)Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(InstancePtr->SlcrBaseAddr +
-			RegOffset) | ((u64)Mask << 32),
+		    RegOffset) | ((u64)Mask << 32),
 			(u64)Val, 0, 0, 0, 0, 0);
 }
 #endif
@@ -52,35 +52,35 @@ void XSdps_Smc(XSdPs *InstancePtr, u32 RegOffset, u32 Mask, u32 Val)
 * Switches the SD card voltage from 3v3 to 1v8
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
 ******************************************************************************/
 s32 XSdPs_Switch_Voltage(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
 	/* Setup the voltage switching sequence */
-	Status = XSdPs_SetupVoltageSwitch(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_SetupVoltageSwitch(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Set the card voltage to 1.8V */
-	Status = XSdPs_CardSetVoltage18(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CardSetVoltage18(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Check if the bus is high */
-	Status = XSdPs_CheckBusHigh(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdPs_CheckBusHigh(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -88,7 +88,7 @@ RETURN_PATH:
 * @brief
 * This function initiates the transfer to or from SD card.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
@@ -97,38 +97,38 @@ RETURN_PATH:
 ******************************************************************************/
 s32 XSdPs_SetupTransfer(XSdPs *InstancePtr)
 {
-	u32 PresentStateReg;
-	s32 Status;
+    u32 PresentStateReg;
+    s32 Status;
 
-	if ((InstancePtr->HC_Version != XSDPS_HC_SPEC_V3) ||
+    if ((InstancePtr->HC_Version != XSDPS_HC_SPEC_V3) ||
 				((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
 				!= XSDPS_CAPS_EMB_SLOT)) {
-		if(InstancePtr->Config.CardDetect != 0U) {
+	    if(InstancePtr->Config.CardDetect != 0U) {
 			/* Check status to ensure card is initialized */
-			PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-					XSDPS_PRES_STATE_OFFSET);
-			if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) {
-				Status = XST_FAILURE;
-				goto RETURN_PATH;
+		    PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+				    XSDPS_PRES_STATE_OFFSET);
+		    if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) {
+			    Status = XST_FAILURE;
+			    goto RETURN_PATH;
 			}
 		}
 	}
 
 	/* Set block size to 512 if not already set */
-	if(XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-			XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {
-		Status = XSdPs_SetBlkSize(InstancePtr,
-			XSDPS_BLK_SIZE_512_MASK);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+    if(XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+		    XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {
+	    Status = XSdPs_SetBlkSize(InstancePtr,
+		    XSDPS_BLK_SIZE_512_MASK);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 
 }
 
@@ -137,8 +137,8 @@ RETURN_PATH:
 * @brief
 * This function resets the SD card.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Value is the type of reset
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Value is the type of reset
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
@@ -147,20 +147,20 @@ RETURN_PATH:
 ******************************************************************************/
 s32 XSdPs_Reset(XSdPs *InstancePtr, u8 Value)
 {
-	s32 Status;
+    s32 Status;
 
 	/* "Software reset for all" is initiated */
-	XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET,
-			Value);
+    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET,
+		    Value);
 
-	Status = XSdPs_CheckResetDone(InstancePtr, Value);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    Status = XSdPs_CheckResetDone(InstancePtr, Value);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+	    return Status;
 }
 
 /*****************************************************************************/
@@ -168,20 +168,20 @@ s32 XSdPs_Reset(XSdPs *InstancePtr, u8 Value)
 * @brief
 * This function sets bit to start execution of tuning.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 void XSdPs_SetExecTuning(XSdPs *InstancePtr)
 {
-	u16 CtrlReg;
+    u16 CtrlReg;
 
-	CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				XSDPS_HOST_CTRL2_OFFSET);
-	CtrlReg |= XSDPS_HC2_EXEC_TNG_MASK;
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-				XSDPS_HOST_CTRL2_OFFSET, CtrlReg);
+    CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+			    XSDPS_HOST_CTRL2_OFFSET);
+    CtrlReg |= XSDPS_HC2_EXEC_TNG_MASK;
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+			    XSDPS_HOST_CTRL2_OFFSET, CtrlReg);
 }
 
 /*****************************************************************************/
@@ -189,7 +189,7 @@ void XSdPs_SetExecTuning(XSdPs *InstancePtr)
 * @brief
 * This function does SD mode initialization.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
 * 		- XST_SUCCESS if initialization is successful
@@ -198,59 +198,59 @@ void XSdPs_SetExecTuning(XSdPs *InstancePtr)
 ******************************************************************************/
 s32 XSdPs_SdModeInit(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 #ifdef __ICCARM__
 #pragma data_alignment = 32
-	static u8 SCR[8] = { 0U };
+    static u8 SCR[8] = { 0U };
 #else
-	static u8 SCR[8] __attribute__ ((aligned(32))) = { 0U };
+    static u8 SCR[8] __attribute__ ((aligned(32))) = { 0U };
 #endif
-	u8 ReadBuff[64] = { 0U };
+    u8 ReadBuff[64] = { 0U };
 
-	Status = XSdPs_Get_BusWidth(InstancePtr, SCR);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Get_BusWidth(InstancePtr, SCR);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	if ((SCR[1] & WIDTH_4_BIT_SUPPORT) != 0U) {
-		InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
-		Status = XSdPs_Change_BusWidth(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+    if ((SCR[1] & WIDTH_4_BIT_SUPPORT) != 0U) {
+	    InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
+	    Status = XSdPs_Change_BusWidth(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
 	/* Get speed supported by device */
-	Status = XSdPs_Get_BusSpeed(InstancePtr, ReadBuff);
-	if (Status != XST_SUCCESS) {
-		goto RETURN_PATH;
+    Status = XSdPs_Get_BusSpeed(InstancePtr, ReadBuff);
+    if (Status != XST_SUCCESS) {
+	    goto RETURN_PATH;
 	}
 
-	if (((SCR[2] & SCR_SPEC_VER_3) != 0U) &&
+    if (((SCR[2] & SCR_SPEC_VER_3) != 0U) &&
 		(ReadBuff[13] >= UHS_SDR50_SUPPORT) &&
 		(InstancePtr->Config.BusWidth == XSDPS_WIDTH_8) &&
 		(InstancePtr->Switch1v8 == 0U)) {
 
-		InstancePtr->Switch1v8 = 1U;
+	    InstancePtr->Switch1v8 = 1U;
 
-		Status = XSdPs_CardSetVoltage18(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_CardSetVoltage18(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	if (InstancePtr->Switch1v8 != 0U) {
+    if (InstancePtr->Switch1v8 != 0U) {
 
 		/* Identify the UHS mode supported by card */
-		XSdPs_Identify_UhsMode(InstancePtr, ReadBuff);
+	    XSdPs_Identify_UhsMode(InstancePtr, ReadBuff);
 
-		Status = XSdPs_Change_BusSpeed(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_Change_BusSpeed(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	} else {
 		/*
@@ -258,32 +258,32 @@ s32 XSdPs_SdModeInit(XSdPs *InstancePtr)
 		 * indicates that the Physical Layer Specification Version
 		 * is 1.10 or later. So for SD v1.0 cmd6 is not supported.
 		 */
-		if (SCR[0] != 0U) {
+	    if (SCR[0] != 0U) {
 			/* Check for high speed support */
-			if (((ReadBuff[13] & HIGH_SPEED_SUPPORT) != 0U) &&
+		    if (((ReadBuff[13] & HIGH_SPEED_SUPPORT) != 0U) &&
 					(InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH)) {
-				InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
-				InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD;
-				InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
-				Status = XSdPs_Change_BusSpeed(InstancePtr);
-				if (Status != XST_SUCCESS) {
-					Status = XST_FAILURE;
-					goto RETURN_PATH;
+			    InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
+			    InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD;
+			    InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
+			    Status = XSdPs_Change_BusSpeed(InstancePtr);
+			    if (Status != XST_SUCCESS) {
+				    Status = XST_FAILURE;
+				    goto RETURN_PATH;
 				}
 			}
 		}
 	}
 
-	Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -291,7 +291,7 @@ RETURN_PATH:
 * @brief
 * This function does MMC mode initialization.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
 * 		- XST_SUCCESS if initialization is successful
@@ -300,58 +300,58 @@ RETURN_PATH:
 ******************************************************************************/
 s32 XSdPs_MmcModeInit(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 #ifdef __ICCARM__
 #pragma data_alignment = 32
-	static u8 ExtCsd[512];
+    static u8 ExtCsd[512];
 #else
-	static u8 ExtCsd[512] __attribute__ ((aligned(32)));
+    static u8 ExtCsd[512] __attribute__ ((aligned(32)));
 #endif
 
-	InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
-	Status = XSdPs_Change_BusWidth(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
+    Status = XSdPs_Change_BusWidth(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	InstancePtr->SectorCount = ((u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE4]) << 24;
-	InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE3] << 16;
-	InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE2] << 8;
-	InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE1];
+    InstancePtr->SectorCount = ((u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE4]) << 24;
+    InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE3] << 16;
+    InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE2] << 8;
+    InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE1];
 
-	if (((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
-			EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) &&
+    if (((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
+		    EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) &&
 			(InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH)) {
-		InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
-		Status = XSdPs_Change_BusSpeed(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
+	    Status = XSdPs_Change_BusSpeed(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 
-		Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 
-		if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -359,7 +359,7 @@ RETURN_PATH:
 * @brief
 * This function does eMMC mode initialization.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
 * 		- XST_SUCCESS if initialization is successful
@@ -368,74 +368,74 @@ RETURN_PATH:
 ******************************************************************************/
 s32 XSdPs_EmmcModeInit(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
 #ifdef __ICCARM__
 #pragma data_alignment = 32
-	static u8 ExtCsd[512];
+    static u8 ExtCsd[512];
 #else
-	static u8 ExtCsd[512] __attribute__ ((aligned(32)));
+    static u8 ExtCsd[512] __attribute__ ((aligned(32)));
 #endif
 
-	if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
+    if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
 			(InstancePtr->Config.BusWidth == XSDPS_WIDTH_8)) {
 		/* in case of eMMC data width 8-bit */
-		InstancePtr->BusWidth = XSDPS_8_BIT_WIDTH;
+	    InstancePtr->BusWidth = XSDPS_8_BIT_WIDTH;
 	} else if (InstancePtr->Config.BusWidth == XSDPS_WIDTH_4) {
 		/* in case of eMMC data width 4-bit */
-		InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
+	    InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
 	} else {
 		/* in case of eMMC data width 1-bit */
-		InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
+	    InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
 	}
 
-	Status = XSdPs_Change_BusWidth(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Change_BusWidth(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Get Extended CSD */
-	Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	InstancePtr->SectorCount = ((u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE4]) << 24;
-	InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE3] << 16;
-	InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE2] << 8;
-	InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE1];
+    InstancePtr->SectorCount = ((u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE4]) << 24;
+    InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE3] << 16;
+    InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE2] << 8;
+    InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE1];
 
-	XSdPs_IdentifyEmmcMode(InstancePtr, ExtCsd);
+    XSdPs_IdentifyEmmcMode(InstancePtr, ExtCsd);
 
-	if (InstancePtr->Mode != XSDPS_DEFAULT_SPEED_MODE) {
-		Status = XSdPs_Change_BusSpeed(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+    if (InstancePtr->Mode != XSDPS_DEFAULT_SPEED_MODE) {
+	    Status = XSdPs_Change_BusSpeed(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 
-		Status = XSdPs_CheckEmmcTiming(InstancePtr, ExtCsd);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_CheckEmmcTiming(InstancePtr, ExtCsd);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
 	/* Enable Rst_n_Fun bit if it is disabled */
-	if(ExtCsd[EXT_CSD_RST_N_FUN_BYTE] == EXT_CSD_RST_N_FUN_TEMP_DIS) {
-		Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, XSDPS_MMC_RST_FUN_EN_ARG);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+    if(ExtCsd[EXT_CSD_RST_N_FUN_BYTE] == EXT_CSD_RST_N_FUN_TEMP_DIS) {
+	    Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, XSDPS_MMC_RST_FUN_EN_ARG);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -443,20 +443,20 @@ RETURN_PATH:
 * @brief
 * This function disables the bus power.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 void XSdPs_DisableBusPower(XSdPs *InstancePtr)
 {
 	/* Disable SD bus power and issue eMMC HW reset */
-	if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-				XSDPS_POWER_CTRL_OFFSET, XSDPS_PC_EMMC_HW_RST_MASK);
+    if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
+	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+			    XSDPS_POWER_CTRL_OFFSET, XSDPS_PC_EMMC_HW_RST_MASK);
 	} else {
-		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-				XSDPS_POWER_CTRL_OFFSET, 0x0);
+	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+			    XSDPS_POWER_CTRL_OFFSET, 0x0);
 	}
 
 	/* 1ms delay to poweroff card */
@@ -468,27 +468,27 @@ void XSdPs_DisableBusPower(XSdPs *InstancePtr)
 * @brief
 * This function enables the bus power.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 void XSdPs_EnableBusPower(XSdPs *InstancePtr)
 {
 	/* Select voltage and enable bus power. */
-	if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-				XSDPS_POWER_CTRL_OFFSET,
+    if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
+	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+			    XSDPS_POWER_CTRL_OFFSET,
 				(XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK) &
 				~XSDPS_PC_EMMC_HW_RST_MASK);
 	} else {
-		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-				XSDPS_POWER_CTRL_OFFSET,
-				XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK);
+	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+			    XSDPS_POWER_CTRL_OFFSET,
+			    XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK);
 	}
 
 	/* 0.2ms Delay after bus power on*/
-	usleep(200);
+    usleep(200);
 }
 
 /*****************************************************************************/
@@ -496,55 +496,55 @@ void XSdPs_EnableBusPower(XSdPs *InstancePtr)
 * @brief
 * This function enumerates the SD card.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_SdCardEnum(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
 	/* Check if the card is present */
-	Status = XSdPs_CheckCardDetect(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CheckCardDetect(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Reset the SD card */
-	Status = XSdPs_CardReset(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CardReset(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Get the card interface condition */
-	Status = XSdPs_CardIfCond(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CardIfCond(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Get the card operating condition */
-	Status = XSdPs_CardOpCond(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CardOpCond(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Get the card ID */
-	Status = XSdPs_GetCardId(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_GetCardId(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Get the CSD register */
-	Status = XSdPs_GetCsd(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_GetCsd(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Change clock to default clock 25MHz */
@@ -553,35 +553,35 @@ s32 XSdPs_SdCardEnum(XSdPs *InstancePtr)
 	 * The reason for this is SD requires a voltage level shifter.
 	 * This limitation applies to ZynqMPSoC.
 	 */
-	if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-		InstancePtr->BusSpeed = SD_CLK_19_MHZ;
+    if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
+	    InstancePtr->BusSpeed = SD_CLK_19_MHZ;
 	} else {
-		InstancePtr->BusSpeed = SD_CLK_25_MHZ;
+	    InstancePtr->BusSpeed = SD_CLK_25_MHZ;
 	}
-	Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Select the card to transition to transfer state */
-	Status = XSdPs_Select_Card(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Select_Card(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Pull-up disconnected during data transfer */
-	Status = XSdPs_Pullup(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Pullup(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+	    return Status;
 }
 
 /*****************************************************************************/
@@ -589,69 +589,69 @@ s32 XSdPs_SdCardEnum(XSdPs *InstancePtr)
 * @brief
 * This function enumerates the MMC card.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_MmcCardEnum(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
 	/* Check if the card is preset */
-	Status = XSdPs_CheckCardDetect(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CheckCardDetect(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Reset the card */
-	Status = XSdPs_CardReset(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CardReset(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Get the card operating condition */
-	Status = XSdPs_CardOpCond(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CardOpCond(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Get the card ID */
-	Status = XSdPs_GetCardId(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_GetCardId(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Get the CSD register */
-	Status = XSdPs_GetCsd(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_GetCsd(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Change clock to default clock 26MHz */
-	InstancePtr->BusSpeed = SD_CLK_26_MHZ;
-	Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    InstancePtr->BusSpeed = SD_CLK_26_MHZ;
+    Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Send select card command to transition to transfer state */
-	Status = XSdPs_Select_Card(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Select_Card(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -659,46 +659,46 @@ RETURN_PATH:
 * @brief
 * This function performs SD tuning.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
 #ifndef versal
 	/* Issue DLL Reset to load new SDHC tuned tap values */
-	Status = XSdPs_DllReset(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_DllReset(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 #endif
 
 	/* Perform the auto tuning */
-	Status = XSdPs_AutoTuning(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_AutoTuning(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 #ifndef versal
 	/* Issue DLL Reset to load new SDHC tuned tap values */
-	Status = XSdPs_DllReset(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_DllReset(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 #endif
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 
 }
 
@@ -707,8 +707,8 @@ RETURN_PATH:
 * @brief
 * This function is used to enable the clock.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	ClockReg is the clock value to be set.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    ClockReg is the clock value to be set.
 *
 * @return
 * 		- XST_SUCCESS if success
@@ -717,37 +717,37 @@ RETURN_PATH:
 ******************************************************************************/
 s32 XSdPs_EnableClock(XSdPs *InstancePtr, u16 ClockReg)
 {
-	u32 Timeout = 150000U;
-	s32 Status;
-	u16 ReadReg;
+    u32 Timeout = 150000U;
+    s32 Status;
+    u16 ReadReg;
 
-	ClockReg |= (u16)XSDPS_CC_INT_CLK_EN_MASK;
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_CLK_CTRL_OFFSET, ClockReg);
+    ClockReg |= (u16)XSDPS_CC_INT_CLK_EN_MASK;
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_CLK_CTRL_OFFSET, ClockReg);
 
 	/* Wait for 150ms for internal clock to stabilize */
-	do {
-		ReadReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				XSDPS_CLK_CTRL_OFFSET);
-		Timeout = Timeout - 1U;
-		usleep(1);
+    do {
+	    ReadReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+			    XSDPS_CLK_CTRL_OFFSET);
+	    Timeout = Timeout - 1U;
+	    usleep(1);
 	} while (((ReadReg & XSDPS_CC_INT_CLK_STABLE_MASK) == 0U)
 				&& (Timeout != 0U));
 
-	if (Timeout == 0U) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    if (Timeout == 0U) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
 	/* Enable SD clock */
-	ClockReg |= XSDPS_CC_SD_CLK_EN_MASK;
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_CLK_CTRL_OFFSET, ClockReg);
+    ClockReg |= XSDPS_CC_SD_CLK_EN_MASK;
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_CLK_CTRL_OFFSET, ClockReg);
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -755,9 +755,9 @@ RETURN_PATH:
 * @brief
 * This function is used to calculate the bus speed.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Arg is the argument to be sent along with the command.
-* 		This could be address or any other information
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Arg is the argument to be sent along with the command.
+* 	    This could be address or any other information
 *
 * @return
 * 		- XST_SUCCESS if success
@@ -766,59 +766,59 @@ RETURN_PATH:
 ******************************************************************************/
 s32 XSdPs_CalcBusSpeed(XSdPs *InstancePtr, u32 *Arg)
 {
-	s32 Status = XST_SUCCESS;
+    s32 Status = XST_SUCCESS;
 
-	if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		switch (InstancePtr->Mode) {
-		case XSDPS_UHS_SPEED_MODE_SDR12:
+    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+	    switch (InstancePtr->Mode) {
+	    case XSDPS_UHS_SPEED_MODE_SDR12:
 			*Arg = XSDPS_SWITCH_CMD_SDR12_SET;
-			InstancePtr->BusSpeed = XSDPS_SD_SDR12_MAX_CLK;
-			break;
-		case XSDPS_UHS_SPEED_MODE_SDR25:
+		    InstancePtr->BusSpeed = XSDPS_SD_SDR12_MAX_CLK;
+		    break;
+	    case XSDPS_UHS_SPEED_MODE_SDR25:
 			*Arg = XSDPS_SWITCH_CMD_SDR25_SET;
-			InstancePtr->BusSpeed = XSDPS_SD_SDR25_MAX_CLK;
-			break;
-		case XSDPS_UHS_SPEED_MODE_SDR50:
+		    InstancePtr->BusSpeed = XSDPS_SD_SDR25_MAX_CLK;
+		    break;
+	    case XSDPS_UHS_SPEED_MODE_SDR50:
 			*Arg = XSDPS_SWITCH_CMD_SDR50_SET;
-			InstancePtr->BusSpeed = XSDPS_SD_SDR50_MAX_CLK;
-			break;
-		case XSDPS_UHS_SPEED_MODE_SDR104:
+		    InstancePtr->BusSpeed = XSDPS_SD_SDR50_MAX_CLK;
+		    break;
+	    case XSDPS_UHS_SPEED_MODE_SDR104:
 			*Arg = XSDPS_SWITCH_CMD_SDR104_SET;
-			InstancePtr->BusSpeed = XSDPS_SD_SDR104_MAX_CLK;
-			break;
-		case XSDPS_UHS_SPEED_MODE_DDR50:
+		    InstancePtr->BusSpeed = XSDPS_SD_SDR104_MAX_CLK;
+		    break;
+	    case XSDPS_UHS_SPEED_MODE_DDR50:
 			*Arg = XSDPS_SWITCH_CMD_DDR50_SET;
-			InstancePtr->BusSpeed = XSDPS_SD_DDR50_MAX_CLK;
-			break;
-		case XSDPS_HIGH_SPEED_MODE:
+		    InstancePtr->BusSpeed = XSDPS_SD_DDR50_MAX_CLK;
+		    break;
+	    case XSDPS_HIGH_SPEED_MODE:
 			*Arg = XSDPS_SWITCH_CMD_HS_SET;
-			InstancePtr->BusSpeed = XSDPS_CLK_50_MHZ;
-			break;
-		default:
-			Status = XST_FAILURE;
-			break;
+		    InstancePtr->BusSpeed = XSDPS_CLK_50_MHZ;
+		    break;
+	    default:
+		    Status = XST_FAILURE;
+		    break;
 		}
 	} else {
-		switch (InstancePtr->Mode) {
-		case XSDPS_HS200_MODE:
+	    switch (InstancePtr->Mode) {
+	    case XSDPS_HS200_MODE:
 			*Arg = XSDPS_MMC_HS200_ARG;
-			InstancePtr->BusSpeed = XSDPS_MMC_HS200_MAX_CLK;
-			break;
-		case XSDPS_DDR52_MODE:
+		    InstancePtr->BusSpeed = XSDPS_MMC_HS200_MAX_CLK;
+		    break;
+	    case XSDPS_DDR52_MODE:
 			*Arg = XSDPS_MMC_HIGH_SPEED_ARG;
-			InstancePtr->BusSpeed = XSDPS_MMC_DDR_MAX_CLK;
-			break;
-		case XSDPS_HIGH_SPEED_MODE:
+		    InstancePtr->BusSpeed = XSDPS_MMC_DDR_MAX_CLK;
+		    break;
+	    case XSDPS_HIGH_SPEED_MODE:
 			*Arg = XSDPS_MMC_HIGH_SPEED_ARG;
-			InstancePtr->BusSpeed = XSDPS_MMC_HSD_MAX_CLK;
-			break;
-		default:
-			Status = XST_FAILURE;
-			break;
+		    InstancePtr->BusSpeed = XSDPS_MMC_HSD_MAX_CLK;
+		    break;
+	    default:
+		    Status = XST_FAILURE;
+		    break;
 		}
 	}
 
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -826,41 +826,41 @@ s32 XSdPs_CalcBusSpeed(XSdPs *InstancePtr, u32 *Arg)
 * @brief
 * This function is used to do the DMA transfer to or from SD card.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	BlkCnt - Block count passed by the user.
-* @param	BlkSize - Block size passed by the user.
-* @param	Buff - Pointer to the data buffer for a DMA transfer.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    BlkCnt - Block count passed by the user.
+* @param    BlkSize - Block size passed by the user.
+* @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
 * 		- XST_FAILURE if failure - could be because another transfer
-* 			is in progress or command or data inhibit is set
+* 		    is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 void XSdPs_SetupReadDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, u8 *Buff)
 {
-	BlkSize &= XSDPS_BLK_SIZE_MASK;
+    BlkSize &= XSDPS_BLK_SIZE_MASK;
 
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_BLK_SIZE_OFFSET, BlkSize);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_BLK_SIZE_OFFSET, BlkSize);
 
-	if (InstancePtr->Dma64BitAddr >= ADDRESS_BEYOND_32BIT) {
-		XSdPs_SetupADMA2DescTbl64Bit(InstancePtr, BlkCnt);
+    if (InstancePtr->Dma64BitAddr >= ADDRESS_BEYOND_32BIT) {
+	    XSdPs_SetupADMA2DescTbl64Bit(InstancePtr, BlkCnt);
 	} else {
-		XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
-		if (InstancePtr->Config.IsCacheCoherent == 0U) {
-			Xil_DCacheInvalidateRange((INTPTR)Buff,
+	    XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
+	    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+		    Xil_DCacheInvalidateRange((INTPTR)Buff,
 				(INTPTR)BlkCnt * BlkSize);
 		}
 	}
 
-	if (BlkCnt == 1U) {
-		InstancePtr->TransferMode = XSDPS_TM_BLK_CNT_EN_MASK |
-			XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK;
+    if (BlkCnt == 1U) {
+	    InstancePtr->TransferMode = XSDPS_TM_BLK_CNT_EN_MASK |
+		    XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK;
 	} else {
-		InstancePtr->TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK |
-			XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DAT_DIR_SEL_MASK |
-			XSDPS_TM_DMA_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK;
+	    InstancePtr->TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK |
+		    XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DAT_DIR_SEL_MASK |
+		    XSDPS_TM_DMA_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK;
 	}
 }
 
@@ -869,41 +869,41 @@ void XSdPs_SetupReadDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, u8 *Buff)
 * @brief
 * This function is used to do the DMA transfer to or from SD card.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	BlkCnt - Block count passed by the user.
-* @param	BlkSize - Block size passed by the user.
-* @param	Buff - Pointer to the data buffer for a DMA transfer.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    BlkCnt - Block count passed by the user.
+* @param    BlkSize - Block size passed by the user.
+* @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
 * 		- XST_FAILURE if failure - could be because another transfer
-* 			is in progress or command or data inhibit is set
+* 		    is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 void XSdPs_SetupWriteDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, const u8 *Buff)
 {
-	BlkSize &= XSDPS_BLK_SIZE_MASK;
+    BlkSize &= XSDPS_BLK_SIZE_MASK;
 
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_BLK_SIZE_OFFSET, BlkSize);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_BLK_SIZE_OFFSET, BlkSize);
 
-	if (InstancePtr->Dma64BitAddr >= ADDRESS_BEYOND_32BIT) {
-		XSdPs_SetupADMA2DescTbl64Bit(InstancePtr, BlkCnt);
+    if (InstancePtr->Dma64BitAddr >= ADDRESS_BEYOND_32BIT) {
+	    XSdPs_SetupADMA2DescTbl64Bit(InstancePtr, BlkCnt);
 	} else {
-		XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
-		if (InstancePtr->Config.IsCacheCoherent == 0U) {
-			Xil_DCacheFlushRange((INTPTR)Buff,
+	    XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
+	    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+		    Xil_DCacheFlushRange((INTPTR)Buff,
 				(INTPTR)BlkCnt * BlkSize);
 		}
 	}
 
-	if (BlkCnt == 1U) {
-		InstancePtr->TransferMode = XSDPS_TM_BLK_CNT_EN_MASK |
-			XSDPS_TM_DMA_EN_MASK;
+    if (BlkCnt == 1U) {
+	    InstancePtr->TransferMode = XSDPS_TM_BLK_CNT_EN_MASK |
+		    XSDPS_TM_DMA_EN_MASK;
 	} else {
-		InstancePtr->TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK |
-			XSDPS_TM_BLK_CNT_EN_MASK |
-			XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK;
+	    InstancePtr->TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK |
+		    XSDPS_TM_BLK_CNT_EN_MASK |
+		    XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK;
 	}
 }
 
@@ -914,64 +914,64 @@ void XSdPs_SetupWriteDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, const u8 *
 * API to setup ADMA2 descriptor table for 32-bit DMA
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	BlkCnt - block count.
-* @param	Buff pointer to data buffer.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    BlkCnt - block count.
+* @param    Buff pointer to data buffer.
 *
-* @return	None
+* @return    None
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 void XSdPs_Setup32ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
 {
 #ifdef __ICCARM__
 #pragma data_alignment = 32
-	static XSdPs_Adma2Descriptor32 Adma2_DescrTbl[32];
+    static XSdPs_Adma2Descriptor32 Adma2_DescrTbl[32];
 #else
-	static XSdPs_Adma2Descriptor32 Adma2_DescrTbl[32] __attribute__ ((aligned(32)));
+    static XSdPs_Adma2Descriptor32 Adma2_DescrTbl[32] __attribute__ ((aligned(32)));
 #endif
-	u32 TotalDescLines;
-	u64 DescNum;
-	u32 BlkSize;
+    u32 TotalDescLines;
+    u64 DescNum;
+    u32 BlkSize;
 
 	/* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */
-	BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_BLK_SIZE_OFFSET) &
-					XSDPS_BLK_SIZE_MASK;
+    BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+				    XSDPS_BLK_SIZE_OFFSET) &
+				    XSDPS_BLK_SIZE_MASK;
 
-	if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
-		TotalDescLines = 1U;
+    if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
+	    TotalDescLines = 1U;
 	} else {
-		TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
-		if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
-			TotalDescLines += 1U;
+	    TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
+	    if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
+		    TotalDescLines += 1U;
 		}
 	}
 
-	for (DescNum = 0U; DescNum < (TotalDescLines-1); DescNum++) {
-		Adma2_DescrTbl[DescNum].Address =
+    for (DescNum = 0U; DescNum < (TotalDescLines-1); DescNum++) {
+	    Adma2_DescrTbl[DescNum].Address =
 				(u32)((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
-		Adma2_DescrTbl[DescNum].Attribute =
-				XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
-		Adma2_DescrTbl[DescNum].Length = 0U;
+	    Adma2_DescrTbl[DescNum].Attribute =
+			    XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
+	    Adma2_DescrTbl[DescNum].Length = 0U;
 	}
 
-	Adma2_DescrTbl[TotalDescLines-1].Address =
+    Adma2_DescrTbl[TotalDescLines-1].Address =
 			(u32)((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
 
-	Adma2_DescrTbl[TotalDescLines-1].Attribute =
-			XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
+    Adma2_DescrTbl[TotalDescLines-1].Attribute =
+		    XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
 
-	Adma2_DescrTbl[TotalDescLines-1].Length =
+    Adma2_DescrTbl[TotalDescLines-1].Length =
 			(u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH));
 
-	XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
+    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
 			(u32)((UINTPTR)&(Adma2_DescrTbl[0]) & (u32)~0x0));
 
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
-			sizeof(XSdPs_Adma2Descriptor32) * 32U);
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+	    Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
+		    sizeof(XSdPs_Adma2Descriptor32) * 32U);
 	}
 }
 
@@ -982,69 +982,69 @@ void XSdPs_Setup32ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
 * API to setup ADMA2 descriptor table for 64-bit DMA
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	BlkCnt - block count.
-* @param	Buff pointer to data buffer.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    BlkCnt - block count.
+* @param    Buff pointer to data buffer.
 *
-* @return	None
+* @return    None
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 void XSdPs_Setup64ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
 {
 #ifdef __ICCARM__
 #pragma data_alignment = 32
-	static XSdPs_Adma2Descriptor64 Adma2_DescrTbl[32];
+    static XSdPs_Adma2Descriptor64 Adma2_DescrTbl[32];
 #else
-	static XSdPs_Adma2Descriptor64 Adma2_DescrTbl[32] __attribute__ ((aligned(32)));
+    static XSdPs_Adma2Descriptor64 Adma2_DescrTbl[32] __attribute__ ((aligned(32)));
 #endif
-	u32 TotalDescLines;
-	u64 DescNum;
-	u32 BlkSize;
+    u32 TotalDescLines;
+    u64 DescNum;
+    u32 BlkSize;
 
 	/* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */
-	BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_BLK_SIZE_OFFSET) &
-					XSDPS_BLK_SIZE_MASK;
+    BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+				    XSDPS_BLK_SIZE_OFFSET) &
+				    XSDPS_BLK_SIZE_MASK;
 
-	if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
-		TotalDescLines = 1U;
+    if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
+	    TotalDescLines = 1U;
 	} else {
-		TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
-		if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
-			TotalDescLines += 1U;
+	    TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
+	    if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
+		    TotalDescLines += 1U;
 		}
 	}
 
-	for (DescNum = 0U; DescNum < (TotalDescLines-1); DescNum++) {
-		Adma2_DescrTbl[DescNum].Address =
+    for (DescNum = 0U; DescNum < (TotalDescLines-1); DescNum++) {
+	    Adma2_DescrTbl[DescNum].Address =
 				((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
-		Adma2_DescrTbl[DescNum].Attribute =
-				XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
-		Adma2_DescrTbl[DescNum].Length = 0U;
+	    Adma2_DescrTbl[DescNum].Attribute =
+			    XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
+	    Adma2_DescrTbl[DescNum].Length = 0U;
 	}
 
-	Adma2_DescrTbl[TotalDescLines-1].Address =
+    Adma2_DescrTbl[TotalDescLines-1].Address =
 			(u64)((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
 
-	Adma2_DescrTbl[TotalDescLines-1].Attribute =
-			XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
+    Adma2_DescrTbl[TotalDescLines-1].Attribute =
+		    XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
 
-	Adma2_DescrTbl[TotalDescLines-1].Length =
+    Adma2_DescrTbl[TotalDescLines-1].Length =
 			(u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH));
 
 #if defined(__aarch64__) || defined(__arch64__)
-	XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_EXT_OFFSET,
+    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_EXT_OFFSET,
 			(u32)((UINTPTR)(Adma2_DescrTbl)>>32U));
 #endif
 
-	XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
+    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
 			(u32)((UINTPTR)&(Adma2_DescrTbl[0]) & (u32)~0x0));
 
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
-			sizeof(XSdPs_Adma2Descriptor64) * 32U);
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+	    Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
+		    sizeof(XSdPs_Adma2Descriptor64) * 32U);
 	}
 }
 
@@ -1053,40 +1053,40 @@ void XSdPs_Setup64ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
 * @brief
 * This function is used calculate the clock divisor value.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	SelFreq is the selected frequency
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    SelFreq is the selected frequency
 *
-* @return	Clock divisor value
+* @return    Clock divisor value
 *
 ******************************************************************************/
 u32 XSdPs_CalcClock(XSdPs *InstancePtr, u32 SelFreq)
 {
-	u16 ClockVal = 0U;
-	u16 DivCnt;
-	u16 Divisor = 0U;
+    u16 ClockVal = 0U;
+    u16 DivCnt;
+    u16 Divisor = 0U;
 
-	if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
+    if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
 		/* Calculate divisor */
-		for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_EXT_MAX_DIV_CNT; DivCnt++) {
-			if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
-				Divisor = DivCnt >> 1;
-				break;
+	    for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_EXT_MAX_DIV_CNT; DivCnt++) {
+		    if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
+			    Divisor = DivCnt >> 1;
+			    break;
 			}
 		}
 	} else {
 		/* Calculate divisor */
-		for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_MAX_DIV_CNT; DivCnt <<= 1U) {
-			if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
-				Divisor = DivCnt / 2U;
-				break;
+	    for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_MAX_DIV_CNT; DivCnt <<= 1U) {
+		    if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
+			    Divisor = DivCnt / 2U;
+			    break;
 			}
 		}
 	}
 
-	ClockVal |= (Divisor & XSDPS_CC_SDCLK_FREQ_SEL_MASK) << XSDPS_CC_DIV_SHIFT;
-	ClockVal |= ((Divisor >> 8U) & XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK) << XSDPS_CC_EXT_DIV_SHIFT;
+    ClockVal |= (Divisor & XSDPS_CC_SDCLK_FREQ_SEL_MASK) << XSDPS_CC_DIV_SHIFT;
+    ClockVal |= ((Divisor >> 8U) & XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK) << XSDPS_CC_EXT_DIV_SHIFT;
 
-	return ClockVal;
+    return ClockVal;
 }
 
 /*****************************************************************************/
@@ -1096,35 +1096,35 @@ u32 XSdPs_CalcClock(XSdPs *InstancePtr, u32 SelFreq)
 * API to Set or Reset the DLL
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	EnRst is a flag indicating whether to Assert or De-assert Reset.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    EnRst is a flag indicating whether to Assert or De-assert Reset.
 *
-* @return	None
+* @return    None
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst)
 {
-	u32 DeviceId;
-	u32 DllCtrl;
+    u32 DeviceId;
+    u32 DllCtrl;
 
-	DeviceId = InstancePtr->Config.DeviceId;
+    DeviceId = InstancePtr->Config.DeviceId;
 #ifdef versal
 #ifdef XPAR_PSV_PMC_SD_0_DEVICE_ID
-	if (DeviceId == 0U) {
+    if (DeviceId == 0U) {
 #if EL1_NONSECURE && defined (__aarch64__)
 		(void)DllCtrl;
 
-		XSdps_Smc(InstancePtr, SD0_DLL_CTRL, SD_DLL_RST, (EnRst == 1U) ? SD0_DLL_RST : 0U);
+	    XSdps_Smc(InstancePtr, SD0_DLL_CTRL, SD_DLL_RST, (EnRst == 1U) ? SD0_DLL_RST : 0U);
 #else /* EL1_NONSECURE && defined (__aarch64__) */
-		DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD0_DLL_CTRL);
-		if (EnRst == 1U) {
-			DllCtrl |= SD_DLL_RST;
+	    DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD0_DLL_CTRL);
+	    if (EnRst == 1U) {
+		    DllCtrl |= SD_DLL_RST;
 		} else {
-			DllCtrl &= ~SD_DLL_RST;
+		    DllCtrl &= ~SD_DLL_RST;
 		}
-		XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD0_DLL_CTRL, DllCtrl);
+	    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD0_DLL_CTRL, DllCtrl);
 #endif /* EL1_NONSECURE && defined (__aarch64__) */
 	} else {
 #endif /* XPAR_PSV_PMC_SD_0_DEVICE_ID */
@@ -1132,15 +1132,15 @@ void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst)
 #if EL1_NONSECURE && defined (__aarch64__)
 		(void)DllCtrl;
 
-		XSdps_Smc(InstancePtr, SD1_DLL_CTRL, SD_DLL_RST, (EnRst == 1U) ? SD_DLL_RST : 0U);
+	    XSdps_Smc(InstancePtr, SD1_DLL_CTRL, SD_DLL_RST, (EnRst == 1U) ? SD_DLL_RST : 0U);
 #else
-		DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD1_DLL_CTRL);
-		if (EnRst == 1U) {
-			DllCtrl |= SD_DLL_RST;
+	    DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD1_DLL_CTRL);
+	    if (EnRst == 1U) {
+		    DllCtrl |= SD_DLL_RST;
 		} else {
-			DllCtrl &= ~SD_DLL_RST;
+		    DllCtrl &= ~SD_DLL_RST;
 		}
-		XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD1_DLL_CTRL, DllCtrl);
+	    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD1_DLL_CTRL, DllCtrl);
 #endif
 #ifdef XPAR_PSV_PMC_SD_0_DEVICE_ID
 	}
@@ -1148,19 +1148,19 @@ void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst)
 #else /* versal */
 
 #ifdef XPAR_PSU_SD_0_DEVICE_ID
-	if (DeviceId == 0U) {
+    if (DeviceId == 0U) {
 #if EL1_NONSECURE && defined (__aarch64__)
 		(void)DllCtrl;
 
-		XSdps_Smc(InstancePtr, SD_DLL_CTRL, SD0_DLL_RST, (EnRst == 1U) ? SD0_DLL_RST : 0U);
+	    XSdps_Smc(InstancePtr, SD_DLL_CTRL, SD0_DLL_RST, (EnRst == 1U) ? SD0_DLL_RST : 0U);
 #else
-		DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL);
-		if (EnRst == 1U) {
-			DllCtrl |= SD0_DLL_RST;
+	    DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL);
+	    if (EnRst == 1U) {
+		    DllCtrl |= SD0_DLL_RST;
 		} else {
-			DllCtrl &= ~SD0_DLL_RST;
+		    DllCtrl &= ~SD0_DLL_RST;
 		}
-		XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL, DllCtrl);
+	    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL, DllCtrl);
 #endif
 	} else {
 #endif /* XPAR_PSU_SD_0_DEVICE_ID */
@@ -1168,15 +1168,15 @@ void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst)
 #if EL1_NONSECURE && defined (__aarch64__)
 		(void)DllCtrl;
 
-		XSdps_Smc(InstancePtr, SD_DLL_CTRL, SD1_DLL_RST, (EnRst == 1U) ? SD1_DLL_RST : 0U);
+	    XSdps_Smc(InstancePtr, SD_DLL_CTRL, SD1_DLL_RST, (EnRst == 1U) ? SD1_DLL_RST : 0U);
 #else
-		DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL);
-		if (EnRst == 1U) {
-			DllCtrl |= SD1_DLL_RST;
+	    DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL);
+	    if (EnRst == 1U) {
+		    DllCtrl |= SD1_DLL_RST;
 		} else {
-			DllCtrl &= ~SD1_DLL_RST;
+		    DllCtrl &= ~SD1_DLL_RST;
 		}
-		XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL, DllCtrl);
+	    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL, DllCtrl);
 #endif
 #ifdef XPAR_PSU_SD_0_DEVICE_ID
 	}
@@ -1191,115 +1191,115 @@ void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst)
 * Function to configure the Tap Delays.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
-* @return	None
+* @return    None
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 void XSdPs_ConfigTapDelay(XSdPs *InstancePtr)
 {
-	u32 DeviceId;
-	u32 TapDelay;
-	u32 ITapDelay;
-	u32 OTapDelay;
+    u32 DeviceId;
+    u32 TapDelay;
+    u32 ITapDelay;
+    u32 OTapDelay;
 
-	DeviceId = InstancePtr->Config.DeviceId ;
-	TapDelay = 0U;
-	ITapDelay = InstancePtr->ITapDelay;
-	OTapDelay = InstancePtr->OTapDelay;
+    DeviceId = InstancePtr->Config.DeviceId ;
+    TapDelay = 0U;
+    ITapDelay = InstancePtr->ITapDelay;
+    OTapDelay = InstancePtr->OTapDelay;
 
 #ifdef versal
 	(void) DeviceId;
-	if (ITapDelay) {
-		TapDelay = SD_ITAPCHGWIN;
-		XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
+    if (ITapDelay) {
+	    TapDelay = SD_ITAPCHGWIN;
+	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
 		/* Program the ITAPDLY */
-		TapDelay |= SD_ITAPDLYENA;
-		XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
-		TapDelay |= ITapDelay;
-		XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
-		TapDelay &= ~SD_ITAPCHGWIN;
-		XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
+	    TapDelay |= SD_ITAPDLYENA;
+	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
+	    TapDelay |= ITapDelay;
+	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
+	    TapDelay &= ~SD_ITAPCHGWIN;
+	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
 	}
-	if (OTapDelay) {
+    if (OTapDelay) {
 		/* Program the OTAPDLY */
-		TapDelay = SD_OTAPDLYENA;
-		XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_OTAPDLY, TapDelay);
-		TapDelay |= OTapDelay;
-		XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_OTAPDLY, TapDelay);
+	    TapDelay = SD_OTAPDLYENA;
+	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_OTAPDLY, TapDelay);
+	    TapDelay |= OTapDelay;
+	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_OTAPDLY, TapDelay);
 	}
 #else
 #ifdef XPAR_PSU_SD_0_DEVICE_ID
-	if (DeviceId == 0U) {
+    if (DeviceId == 0U) {
 #if EL1_NONSECURE && defined (__aarch64__)
 		(void)TapDelay;
-		if (ITapDelay) {
-			XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPCHGWIN, SD0_ITAPCHGWIN);
-			XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPDLYENA, SD0_ITAPDLYENA);
-			XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPDLY_SEL_MASK, ITapDelay);
-			XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPCHGWIN, 0U);
+	    if (ITapDelay) {
+		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPCHGWIN, SD0_ITAPCHGWIN);
+		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPDLYENA, SD0_ITAPDLYENA);
+		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPDLY_SEL_MASK, ITapDelay);
+		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPCHGWIN, 0U);
 		}
-		if (OTapDelay) {
-			XSdps_Smc(InstancePtr, SD_OTAPDLY, SD0_OTAPDLY_SEL_MASK, OTapDelay);
+	    if (OTapDelay) {
+		    XSdps_Smc(InstancePtr, SD_OTAPDLY, SD0_OTAPDLY_SEL_MASK, OTapDelay);
 		}
 #else
-		if (ITapDelay) {
-			TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY);
-			TapDelay |= SD0_ITAPCHGWIN;
-			XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+	    if (ITapDelay) {
+		    TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY);
+		    TapDelay |= SD0_ITAPCHGWIN;
+		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
 			/* Program the ITAPDLY */
-			TapDelay |= SD0_ITAPDLYENA;
-			XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-			TapDelay |= ITapDelay;
-			XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-			TapDelay &= ~SD0_ITAPCHGWIN;
-			XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+		    TapDelay |= SD0_ITAPDLYENA;
+		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+		    TapDelay |= ITapDelay;
+		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+		    TapDelay &= ~SD0_ITAPCHGWIN;
+		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
 		}
-		if (OTapDelay) {
+	    if (OTapDelay) {
 			/* Program the OTAPDLY */
-			TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY);
-			TapDelay &= ~SD0_OTAPDLY_SEL_MASK;
-			TapDelay |= OTapDelay;
-			XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay);
+		    TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY);
+		    TapDelay &= ~SD0_OTAPDLY_SEL_MASK;
+		    TapDelay |= OTapDelay;
+		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay);
 		}
 #endif
 	} else {
 #endif
 		(void) DeviceId;
-		ITapDelay = ITapDelay << 16U;
-		OTapDelay = OTapDelay << 16U;
+	    ITapDelay = ITapDelay << 16U;
+	    OTapDelay = OTapDelay << 16U;
 #if EL1_NONSECURE && defined (__aarch64__)
 		(void)TapDelay;
-		if (ITapDelay) {
-			XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPCHGWIN, SD1_ITAPCHGWIN);
-			XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPDLYENA, SD1_ITAPDLYENA);
-			XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPDLY_SEL_MASK, ITapDelay);
-			XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPCHGWIN, 0U);
+	    if (ITapDelay) {
+		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPCHGWIN, SD1_ITAPCHGWIN);
+		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPDLYENA, SD1_ITAPDLYENA);
+		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPDLY_SEL_MASK, ITapDelay);
+		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPCHGWIN, 0U);
 		}
-		if (OTapDelay) {
-			XSdps_Smc(InstancePtr, SD_OTAPDLY, SD1_OTAPDLY_SEL_MASK, OTapDelay);
+	    if (OTapDelay) {
+		    XSdps_Smc(InstancePtr, SD_OTAPDLY, SD1_OTAPDLY_SEL_MASK, OTapDelay);
 		}
 #else
-		if (ITapDelay) {
-			TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY);
-			TapDelay |= SD1_ITAPCHGWIN;
-			XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+	    if (ITapDelay) {
+		    TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY);
+		    TapDelay |= SD1_ITAPCHGWIN;
+		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
 			/* Program the ITAPDLY */
-			TapDelay |= SD1_ITAPDLYENA;
-			XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-			TapDelay |= ITapDelay;
-			XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-			TapDelay &= ~SD1_ITAPCHGWIN;
-			XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+		    TapDelay |= SD1_ITAPDLYENA;
+		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+		    TapDelay |= ITapDelay;
+		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+		    TapDelay &= ~SD1_ITAPCHGWIN;
+		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
 		}
-		if (OTapDelay) {
+	    if (OTapDelay) {
 			/* Program the OTAPDLY */
-			TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY);
-			TapDelay &= ~SD1_OTAPDLY_SEL_MASK;
-			TapDelay |= OTapDelay;
-			XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay);
+		    TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY);
+		    TapDelay &= ~SD1_OTAPDLY_SEL_MASK;
+		    TapDelay |= OTapDelay;
+		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay);
 		}
 #endif
 #ifdef XPAR_PSU_SD_0_DEVICE_ID
@@ -1313,7 +1313,7 @@ void XSdPs_ConfigTapDelay(XSdPs *InstancePtr)
 * @brief
 * This function is used to set voltage to 1.8V.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
 * 		- XST_SUCCESS if successful
@@ -1322,26 +1322,26 @@ void XSdPs_ConfigTapDelay(XSdPs *InstancePtr)
 ******************************************************************************/
 s32 XSdPs_SetVoltage18(XSdPs *InstancePtr)
 {
-	s32 Status;
-	u16 CtrlReg;
+    s32 Status;
+    u16 CtrlReg;
 
 	/* Enabling 1.8V in controller */
-	CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_HOST_CTRL2_OFFSET);
-	CtrlReg |= XSDPS_HC2_1V8_EN_MASK;
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_HOST_CTRL2_OFFSET,
-			CtrlReg);
+    CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_HOST_CTRL2_OFFSET);
+    CtrlReg |= XSDPS_HC2_1V8_EN_MASK;
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_HOST_CTRL2_OFFSET,
+		    CtrlReg);
 
 	/* Wait minimum 5mSec */
 	(void)usleep(5000U);
 
 	/* Check for 1.8V signal enable bit is cleared by Host */
-	Status = XSdPs_CheckVoltage18(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdPs_CheckVoltage18(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -1349,29 +1349,29 @@ s32 XSdPs_SetVoltage18(XSdPs *InstancePtr)
 * @brief
 * This function is used configure the Power Level.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 void XSdPs_ConfigPower(XSdPs *InstancePtr)
 {
-	u8 PowerLevel;
+    u8 PowerLevel;
 
-	if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V3_MASK) != 0U) {
-		PowerLevel = XSDPS_PC_BUS_VSEL_3V3_MASK;
+    if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V3_MASK) != 0U) {
+	    PowerLevel = XSDPS_PC_BUS_VSEL_3V3_MASK;
 	} else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V0_MASK) != 0U) {
-		PowerLevel = XSDPS_PC_BUS_VSEL_3V0_MASK;
+	    PowerLevel = XSDPS_PC_BUS_VSEL_3V0_MASK;
 	} else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_1V8_MASK) != 0U) {
-		PowerLevel = XSDPS_PC_BUS_VSEL_1V8_MASK;
+	    PowerLevel = XSDPS_PC_BUS_VSEL_1V8_MASK;
 	} else {
-		PowerLevel = 0U;
+	    PowerLevel = 0U;
 	}
 
 	/* Select voltage based on capability and enable bus power. */
-	XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			XSDPS_POWER_CTRL_OFFSET,
-			PowerLevel | XSDPS_PC_BUS_PWR_MASK);
+    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+		    XSDPS_POWER_CTRL_OFFSET,
+		    PowerLevel | XSDPS_PC_BUS_PWR_MASK);
 }
 
 /*****************************************************************************/
@@ -1379,23 +1379,23 @@ void XSdPs_ConfigPower(XSdPs *InstancePtr)
 * @brief
 * This function is used configure the DMA.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 void XSdPs_ConfigDma(XSdPs *InstancePtr)
 {
-	if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
+    if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
 		/* Enable ADMA2 in 64bit mode. */
-		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-				XSDPS_HOST_CTRL1_OFFSET,
-				XSDPS_HC_DMA_ADMA2_64_MASK);
+	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+			    XSDPS_HOST_CTRL1_OFFSET,
+			    XSDPS_HC_DMA_ADMA2_64_MASK);
 	} else {
 		/* Enable ADMA2 in 32bit mode. */
-		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-				XSDPS_HOST_CTRL1_OFFSET,
-				XSDPS_HC_DMA_ADMA2_32_MASK);
+	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+			    XSDPS_HOST_CTRL1_OFFSET,
+			    XSDPS_HC_DMA_ADMA2_32_MASK);
 	}
 }
 
@@ -1404,27 +1404,27 @@ void XSdPs_ConfigDma(XSdPs *InstancePtr)
 * @brief
 * This function is used configure the Interrupts.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 void XSdPs_ConfigInterrupt(XSdPs *InstancePtr)
 {
 	/* Enable all interrupt status except card interrupt initially */
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_NORM_INTR_STS_EN_OFFSET,
-			XSDPS_NORM_INTR_ALL_MASK & (~XSDPS_INTR_CARD_MASK));
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_NORM_INTR_STS_EN_OFFSET,
+		    XSDPS_NORM_INTR_ALL_MASK & (~XSDPS_INTR_CARD_MASK));
 
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_ERR_INTR_STS_EN_OFFSET,
-			XSDPS_ERROR_INTR_ALL_MASK);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_ERR_INTR_STS_EN_OFFSET,
+		    XSDPS_ERROR_INTR_ALL_MASK);
 
 	/* Disable all interrupt signals by default. */
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_NORM_INTR_SIG_EN_OFFSET, 0x0U);
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_ERR_INTR_SIG_EN_OFFSET, 0x0U);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_NORM_INTR_SIG_EN_OFFSET, 0x0U);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_ERR_INTR_SIG_EN_OFFSET, 0x0U);
 
 }
 
@@ -1432,73 +1432,73 @@ void XSdPs_ConfigInterrupt(XSdPs *InstancePtr)
 /**
 * This function does SD command generation.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Cmd is the command to be sent.
-* @param	Arg is the argument to be sent along with the command.
-* 		This could be address or any other information
-* @param	BlkCnt - Block count passed by the user.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Cmd is the command to be sent.
+* @param    Arg is the argument to be sent along with the command.
+* 	    This could be address or any other information
+* @param    BlkCnt - Block count passed by the user.
 *
 * @return
 * 		- XST_SUCCESS if initialization was successful
 * 		- XST_FAILURE if failure - could be because another transfer
-* 			is in progress or command or data inhibit is set
+* 		    is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt)
 {
-	u32 Timeout = 10000000U;
-	u32 StatusReg;
-	s32 Status;
+    u32 Timeout = 10000000U;
+    u32 StatusReg;
+    s32 Status;
 
-	Status = XSdPs_SetupCmd(InstancePtr, Arg, BlkCnt);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_SetupCmd(InstancePtr, Arg, BlkCnt);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XSdPs_SendCmd(InstancePtr, Cmd);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_SendCmd(InstancePtr, Cmd);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Polling for response for now */
-	do {
-		StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_NORM_INTR_STS_OFFSET);
-		if ((Cmd == CMD21) || (Cmd == CMD19)) {
-			if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_NORM_INTR_STS_OFFSET) & XSDPS_INTR_BRR_MASK) != 0U){
-				XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_BRR_MASK);
-				break;
+    do {
+	    StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+				    XSDPS_NORM_INTR_STS_OFFSET);
+	    if ((Cmd == CMD21) || (Cmd == CMD19)) {
+		    if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+				    XSDPS_NORM_INTR_STS_OFFSET) & XSDPS_INTR_BRR_MASK) != 0U){
+			    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+				    XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_BRR_MASK);
+			    break;
 			}
 		}
 
-		if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
-			Status = (s32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-									XSDPS_ERR_INTR_STS_OFFSET);
-			if (((u32)Status & ~XSDPS_INTR_ERR_CT_MASK) == 0U) {
-				Status = XSDPS_CT_ERROR;
+	    if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
+		    Status = (s32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+								    XSDPS_ERR_INTR_STS_OFFSET);
+		    if (((u32)Status & ~XSDPS_INTR_ERR_CT_MASK) == 0U) {
+			    Status = XSDPS_CT_ERROR;
 			}
 			 /* Write to clear error bits */
-			XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_ERR_INTR_STS_OFFSET,
-					XSDPS_ERROR_INTR_ALL_MASK);
-			goto RETURN_PATH;
+		    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+				    XSDPS_ERR_INTR_STS_OFFSET,
+				    XSDPS_ERROR_INTR_ALL_MASK);
+		    goto RETURN_PATH;
 		}
-		Timeout = Timeout - 1U;
+	    Timeout = Timeout - 1U;
 	} while (((StatusReg & XSDPS_INTR_CC_MASK) == 0U)
 				&& (Timeout != 0U));
 	/* Write to clear bit */
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_NORM_INTR_STS_OFFSET,
-			XSDPS_INTR_CC_MASK);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_NORM_INTR_STS_OFFSET,
+		    XSDPS_INTR_CC_MASK);
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-		return Status;
+	    return Status;
 
 }
 
@@ -1506,50 +1506,50 @@ RETURN_PATH:
 /**
 * This function is used to check if the transfer is completed successfully.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdps_CheckTransferDone(XSdPs *InstancePtr)
 {
-	u32 Timeout = 5000000U;
-	u16 StatusReg;
-	s32 Status;
+    u32 Timeout = 5000000U;
+    u16 StatusReg;
+    s32 Status;
 
 	/*
 	 * Check for transfer complete
 	 * Polling for response for now
 	 */
-	do {
-		StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_NORM_INTR_STS_OFFSET);
-		if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
+    do {
+	    StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+				    XSDPS_NORM_INTR_STS_OFFSET);
+	    if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
 			/* Write to clear error bits */
-			XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_ERR_INTR_STS_OFFSET,
-					XSDPS_ERROR_INTR_ALL_MASK);
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+		    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+				    XSDPS_ERR_INTR_STS_OFFSET,
+				    XSDPS_ERROR_INTR_ALL_MASK);
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
-		Timeout = Timeout - 1U;
-		usleep(1);
+	    Timeout = Timeout - 1U;
+	    usleep(1);
 	} while (((StatusReg & XSDPS_INTR_TC_MASK) == 0U)
 			&& (Timeout != 0U));
 
-	if (Timeout == 0U) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    if (Timeout == 0U) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
 	/* Write to clear bit */
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+		    XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -1557,42 +1557,42 @@ RETURN_PATH:
 * @brief
 * This function is used to check if the CMD/DATA bus is idle or not.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Value is to selct Cmd bus or Dat bus
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Value is to selct Cmd bus or Dat bus
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_CheckBusIdle(XSdPs *InstancePtr, u32 Value)
 {
-	u32 Timeout = 10000000U;
-	u32 PresentStateReg;
-	u32 StatusReg;
-	s32 Status;
+    u32 Timeout = 10000000U;
+    u32 PresentStateReg;
+    u32 StatusReg;
+    s32 Status;
 
-	PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-			XSDPS_PRES_STATE_OFFSET);
+    PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+		    XSDPS_PRES_STATE_OFFSET);
 	/* Check for Card Present */
-	if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) != 0U) {
+    if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) != 0U) {
 		/* Check for SD idle */
-		do {
-			StatusReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-					XSDPS_PRES_STATE_OFFSET);
-			Timeout = Timeout - 1;
-			usleep(1);
+	    do {
+		    StatusReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+				    XSDPS_PRES_STATE_OFFSET);
+		    Timeout = Timeout - 1;
+		    usleep(1);
 		} while (((StatusReg & Value) != 0U)
 				&& (Timeout != 0U));
 	}
 
-	if (Timeout == 0U) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    if (Timeout == 0U) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -1604,198 +1604,198 @@ RETURN_PATH:
 * This value is already shifted to be upper 16 bits and can be directly
 * OR'ed with transfer mode register value.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Cmd is the Command to be sent.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Cmd is the Command to be sent.
 *
-* @return	Command register value complete with response type and
-* 		data, CRC and index related flags.
+* @return    Command register value complete with response type and
+* 	    data, CRC and index related flags.
 *
 ******************************************************************************/
 u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd)
 {
-	u32 RetVal;
+    u32 RetVal;
 
-	RetVal = Cmd;
+    RetVal = Cmd;
 #if 0
-	switch(Cmd) {
-	case CMD0:
-		RetVal |= RESP_NONE;
-		break;
-	case CMD1:
-		RetVal |= RESP_R3;
-		break;
-	case CMD2:
-		RetVal |= RESP_R2;
-		break;
-	case CMD3:
-		if (InstancePtr->CardType == XSDPS_CARD_SD) {
-			RetVal |= RESP_R6;
+    switch(Cmd) {
+    case CMD0:
+	    RetVal |= RESP_NONE;
+	    break;
+    case CMD1:
+	    RetVal |= RESP_R3;
+	    break;
+    case CMD2:
+	    RetVal |= RESP_R2;
+	    break;
+    case CMD3:
+	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+		    RetVal |= RESP_R6;
 		} else {
-			RetVal |= RESP_R1;
+		    RetVal |= RESP_R1;
 		}
-		break;
-	case CMD4:
-		RetVal |= RESP_NONE;
-		break;
-	case CMD5:
-		RetVal |= RESP_R1B;
-		break;
-	case CMD6:
-		if (InstancePtr->CardType == XSDPS_CARD_SD) {
-			RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+	    break;
+    case CMD4:
+	    RetVal |= RESP_NONE;
+	    break;
+    case CMD5:
+	    RetVal |= RESP_R1B;
+	    break;
+    case CMD6:
+	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+		    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
 		} else {
-			RetVal |= RESP_R1B;
+		    RetVal |= RESP_R1B;
 		}
-		break;
-	case ACMD6:
-		RetVal |= RESP_R1;
-		break;
-	case CMD7:
-		RetVal |= RESP_R1;
-		break;
-	case CMD8:
-		if (InstancePtr->CardType == XSDPS_CARD_SD) {
-			RetVal |= RESP_R1;
+	    break;
+    case ACMD6:
+	    RetVal |= RESP_R1;
+	    break;
+    case CMD7:
+	    RetVal |= RESP_R1;
+	    break;
+    case CMD8:
+	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+		    RetVal |= RESP_R1;
 		} else {
-			RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+		    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
 		}
-		break;
-	case CMD9:
-		RetVal |= RESP_R2;
-		break;
-	case CMD11:
-	case CMD10:
-	case CMD12:
-		RetVal |= RESP_R1;
-		break;
-	case ACMD13:
-		RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		break;
-	case CMD16:
-		RetVal |= RESP_R1;
-		break;
-	case CMD17:
-	case CMD18:
-	case CMD19:
-	case CMD21:
-		RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		break;
-	case CMD23:
-	case ACMD23:
-	case CMD24:
-	case CMD25:
-		RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		break;
-	case ACMD41:
-		RetVal |= RESP_R3;
-		break;
-	case ACMD42:
-		RetVal |= RESP_R1;
-		break;
-	case ACMD51:
-		RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		break;
-	case CMD52:
-	case CMD55:
-		RetVal |= RESP_R1;
-		break;
-	case CMD58:
-		break;
-	default :
-		RetVal |= Cmd;
-		break;
+	    break;
+    case CMD9:
+	    RetVal |= RESP_R2;
+	    break;
+    case CMD11:
+    case CMD10:
+    case CMD12:
+	    RetVal |= RESP_R1;
+	    break;
+    case ACMD13:
+	    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+	    break;
+    case CMD16:
+	    RetVal |= RESP_R1;
+	    break;
+    case CMD17:
+    case CMD18:
+    case CMD19:
+    case CMD21:
+	    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+	    break;
+    case CMD23:
+    case ACMD23:
+    case CMD24:
+    case CMD25:
+	    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+	    break;
+    case ACMD41:
+	    RetVal |= RESP_R3;
+	    break;
+    case ACMD42:
+	    RetVal |= RESP_R1;
+	    break;
+    case ACMD51:
+	    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+	    break;
+    case CMD52:
+    case CMD55:
+	    RetVal |= RESP_R1;
+	    break;
+    case CMD58:
+	    break;
+    default :
+	    RetVal |= Cmd;
+	    break;
 	}
 #else
-	switch(Cmd) {
-	case CMD0:
-		RetVal |= XSDPS_RESP_NONE;
-		break;
-	case CMD1:
-		RetVal |= XSDPS_RESP_R3;
-		break;
-	case CMD2:
-		RetVal |= XSDPS_RESP_R2;
-		break;
-	case CMD3:
-		if (InstancePtr->CardType == XSDPS_CARD_SD) {
-			RetVal |= XSDPS_RESP_R6;
+    switch(Cmd) {
+    case CMD0:
+	    RetVal |= XSDPS_RESP_NONE;
+	    break;
+    case CMD1:
+	    RetVal |= XSDPS_RESP_R3;
+	    break;
+    case CMD2:
+	    RetVal |= XSDPS_RESP_R2;
+	    break;
+    case CMD3:
+	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+		    RetVal |= XSDPS_RESP_R6;
 		} else {
-			RetVal |= XSDPS_RESP_R1;
+		    RetVal |= XSDPS_RESP_R1;
 		}
-		break;
-	case CMD4:
-		RetVal |= XSDPS_RESP_NONE;
-		break;
-	case CMD5:
-		RetVal |= XSDPS_RESP_R1B;
-		break;
-	case CMD6:
-		if (InstancePtr->CardType == XSDPS_CARD_SD) {
-			RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+	    break;
+    case CMD4:
+	    RetVal |= XSDPS_RESP_NONE;
+	    break;
+    case CMD5:
+	    RetVal |= XSDPS_RESP_R1B;
+	    break;
+    case CMD6:
+	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+		    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
 		} else {
-			RetVal |= XSDPS_RESP_R1B;
+		    RetVal |= XSDPS_RESP_R1B;
 		}
-		break;
-	case ACMD6:
-		RetVal |= XSDPS_RESP_R1;
-		break;
-	case CMD7:
-		RetVal |= XSDPS_RESP_R1;
-		break;
-	case CMD8:
-		if (InstancePtr->CardType == XSDPS_CARD_SD) {
-			RetVal |= XSDPS_RESP_R1;
+	    break;
+    case ACMD6:
+	    RetVal |= XSDPS_RESP_R1;
+	    break;
+    case CMD7:
+	    RetVal |= XSDPS_RESP_R1;
+	    break;
+    case CMD8:
+	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+		    RetVal |= XSDPS_RESP_R1;
 		} else {
-			RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+		    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
 		}
-		break;
-	case CMD9:
-		RetVal |= XSDPS_RESP_R2;
-		break;
-	case CMD11:
-	case CMD10:
-	case CMD12:
-		RetVal |= XSDPS_RESP_R1;
-		break;
-	case ACMD13:
-		RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		break;
-	case CMD16:
-		RetVal |= XSDPS_RESP_R1;
-		break;
-	case CMD17:
-	case CMD18:
-	case CMD19:
-	case CMD21:
-		RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		break;
-	case CMD23:
-	case ACMD23:
-	case CMD24:
-	case CMD25:
-		RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		break;
-	case ACMD41:
-		RetVal |= XSDPS_RESP_R3;
-		break;
-	case ACMD42:
-		RetVal |= XSDPS_RESP_R1;
-		break;
-	case ACMD51:
-		RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		break;
-	case CMD52:
-	case CMD55:
-		RetVal |= XSDPS_RESP_R1;
-		break;
-	case CMD58:
-		break;
-	default :
-		RetVal |= Cmd;
-		break;
+	    break;
+    case CMD9:
+	    RetVal |= XSDPS_RESP_R2;
+	    break;
+    case CMD11:
+    case CMD10:
+    case CMD12:
+	    RetVal |= XSDPS_RESP_R1;
+	    break;
+    case ACMD13:
+	    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+	    break;
+    case CMD16:
+	    RetVal |= XSDPS_RESP_R1;
+	    break;
+    case CMD17:
+    case CMD18:
+    case CMD19:
+    case CMD21:
+	    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+	    break;
+    case CMD23:
+    case ACMD23:
+    case CMD24:
+    case CMD25:
+	    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+	    break;
+    case ACMD41:
+	    RetVal |= XSDPS_RESP_R3;
+	    break;
+    case ACMD42:
+	    RetVal |= XSDPS_RESP_R1;
+	    break;
+    case ACMD51:
+	    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+	    break;
+    case CMD52:
+    case CMD55:
+	    RetVal |= XSDPS_RESP_R1;
+	    break;
+    case CMD58:
+	    break;
+    default :
+	    RetVal |= Cmd;
+	    break;
 	}
 #endif
-	return RetVal;
+    return RetVal;
 }
 
 /** @} */
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h
index 7ddb221c77..21582fdee2 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h
@@ -20,7 +20,7 @@
 * Ver   Who    Date     Changes
 * ----- ---    -------- -----------------------------------------------
 * 1.00a hk/sg  10/17/13 Initial release
-* 2.5 	sg	   07/09/15 Added SD 3.0 features
+* 2.5     sg	   07/09/15 Added SD 3.0 features
 *       kvn    07/15/15 Modified the code according to MISRAC-2012.
 * 2.7   sk     12/10/15 Added support for MMC cards.
 *       sk     03/02/16 Configured the Tap Delay values for eMMC HS200 mode.
@@ -67,126 +67,126 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_SDMA_SYS_ADDR_OFFSET	0x00U	/**< SDMA System Address
-							Register */
-#define XSDPS_SDMA_SYS_ADDR_LO_OFFSET	XSDPS_SDMA_SYS_ADDR_OFFSET
+#define XSDPS_SDMA_SYS_ADDR_OFFSET    0x00U	/**< SDMA System Address
+						    Register */
+#define XSDPS_SDMA_SYS_ADDR_LO_OFFSET    XSDPS_SDMA_SYS_ADDR_OFFSET
 						/**< SDMA System Address
-							Low Register */
-#define XSDPS_ARGMT2_LO_OFFSET		0x00U	/**< Argument2 Low Register */
-#define XSDPS_SDMA_SYS_ADDR_HI_OFFSET	0x02U	/**< SDMA System Address
-							High Register */
-#define XSDPS_ARGMT2_HI_OFFSET		0x02U	/**< Argument2 High Register */
+						    Low Register */
+#define XSDPS_ARGMT2_LO_OFFSET	    0x00U	/**< Argument2 Low Register */
+#define XSDPS_SDMA_SYS_ADDR_HI_OFFSET    0x02U	/**< SDMA System Address
+						    High Register */
+#define XSDPS_ARGMT2_HI_OFFSET	    0x02U	/**< Argument2 High Register */
 
-#define XSDPS_BLK_SIZE_OFFSET		0x04U	/**< Block Size Register */
-#define XSDPS_BLK_CNT_OFFSET		0x06U	/**< Block Count Register */
-#define XSDPS_ARGMT_OFFSET		0x08U	/**< Argument Register */
-#define XSDPS_ARGMT1_LO_OFFSET		XSDPS_ARGMT_OFFSET
+#define XSDPS_BLK_SIZE_OFFSET	    0x04U	/**< Block Size Register */
+#define XSDPS_BLK_CNT_OFFSET	    0x06U	/**< Block Count Register */
+#define XSDPS_ARGMT_OFFSET	    0x08U	/**< Argument Register */
+#define XSDPS_ARGMT1_LO_OFFSET	    XSDPS_ARGMT_OFFSET
 						/**< Argument1 Register */
-#define XSDPS_ARGMT1_HI_OFFSET		0x0AU	/**< Argument1 Register */
+#define XSDPS_ARGMT1_HI_OFFSET	    0x0AU	/**< Argument1 Register */
 
-#define XSDPS_XFER_MODE_OFFSET		0x0CU	/**< Transfer Mode Register */
-#define XSDPS_CMD_OFFSET		0x0EU	/**< Command Register */
-#define XSDPS_RESP0_OFFSET		0x10U	/**< Response0 Register */
-#define XSDPS_RESP1_OFFSET		0x14U	/**< Response1 Register */
-#define XSDPS_RESP2_OFFSET		0x18U	/**< Response2 Register */
-#define XSDPS_RESP3_OFFSET		0x1CU	/**< Response3 Register */
-#define XSDPS_BUF_DAT_PORT_OFFSET	0x20U	/**< Buffer Data Port */
-#define XSDPS_PRES_STATE_OFFSET		0x24U	/**< Present State */
-#define XSDPS_HOST_CTRL1_OFFSET		0x28U	/**< Host Control 1 */
-#define XSDPS_POWER_CTRL_OFFSET		0x29U	/**< Power Control */
-#define XSDPS_BLK_GAP_CTRL_OFFSET	0x2AU	/**< Block Gap Control */
-#define XSDPS_WAKE_UP_CTRL_OFFSET	0x2BU	/**< Wake Up Control */
-#define XSDPS_CLK_CTRL_OFFSET		0x2CU	/**< Clock Control */
-#define XSDPS_TIMEOUT_CTRL_OFFSET	0x2EU	/**< Timeout Control */
-#define XSDPS_SW_RST_OFFSET		0x2FU	/**< Software Reset */
-#define XSDPS_NORM_INTR_STS_OFFSET 	0x30U	/**< Normal Interrupt
-							Status Register */
-#define XSDPS_ERR_INTR_STS_OFFSET 	0x32U	/**< Error Interrupt
-							Status Register */
-#define XSDPS_NORM_INTR_STS_EN_OFFSET	0x34U	/**< Normal Interrupt
-						Status Enable Register */
-#define XSDPS_ERR_INTR_STS_EN_OFFSET	0x36U	/**< Error Interrupt
-						Status Enable Register */
-#define XSDPS_NORM_INTR_SIG_EN_OFFSET	0x38U	/**< Normal Interrupt
-						Signal Enable Register */
-#define XSDPS_ERR_INTR_SIG_EN_OFFSET	0x3AU	/**< Error Interrupt
-						Signal Enable Register */
+#define XSDPS_XFER_MODE_OFFSET	    0x0CU	/**< Transfer Mode Register */
+#define XSDPS_CMD_OFFSET	    0x0EU	/**< Command Register */
+#define XSDPS_RESP0_OFFSET	    0x10U	/**< Response0 Register */
+#define XSDPS_RESP1_OFFSET	    0x14U	/**< Response1 Register */
+#define XSDPS_RESP2_OFFSET	    0x18U	/**< Response2 Register */
+#define XSDPS_RESP3_OFFSET	    0x1CU	/**< Response3 Register */
+#define XSDPS_BUF_DAT_PORT_OFFSET    0x20U	/**< Buffer Data Port */
+#define XSDPS_PRES_STATE_OFFSET	    0x24U	/**< Present State */
+#define XSDPS_HOST_CTRL1_OFFSET	    0x28U	/**< Host Control 1 */
+#define XSDPS_POWER_CTRL_OFFSET	    0x29U	/**< Power Control */
+#define XSDPS_BLK_GAP_CTRL_OFFSET    0x2AU	/**< Block Gap Control */
+#define XSDPS_WAKE_UP_CTRL_OFFSET    0x2BU	/**< Wake Up Control */
+#define XSDPS_CLK_CTRL_OFFSET	    0x2CU	/**< Clock Control */
+#define XSDPS_TIMEOUT_CTRL_OFFSET    0x2EU	/**< Timeout Control */
+#define XSDPS_SW_RST_OFFSET	    0x2FU	/**< Software Reset */
+#define XSDPS_NORM_INTR_STS_OFFSET     0x30U	/**< Normal Interrupt
+						    Status Register */
+#define XSDPS_ERR_INTR_STS_OFFSET     0x32U	/**< Error Interrupt
+						    Status Register */
+#define XSDPS_NORM_INTR_STS_EN_OFFSET    0x34U	/**< Normal Interrupt
+					    Status Enable Register */
+#define XSDPS_ERR_INTR_STS_EN_OFFSET    0x36U	/**< Error Interrupt
+					    Status Enable Register */
+#define XSDPS_NORM_INTR_SIG_EN_OFFSET    0x38U	/**< Normal Interrupt
+					    Signal Enable Register */
+#define XSDPS_ERR_INTR_SIG_EN_OFFSET    0x3AU	/**< Error Interrupt
+					    Signal Enable Register */
 
-#define XSDPS_AUTO_CMD12_ERR_STS_OFFSET	0x3CU	/**< Auto CMD12 Error Status
-							Register */
-#define XSDPS_HOST_CTRL2_OFFSET		0x3EU	/**< Host Control2 Register */
-#define XSDPS_CAPS_OFFSET 		0x40U	/**< Capabilities Register */
-#define XSDPS_CAPS_EXT_OFFSET 		0x44U	/**< Capabilities Extended */
-#define XSDPS_MAX_CURR_CAPS_OFFSET	0x48U	/**< Maximum Current
-						Capabilities Register */
-#define XSDPS_MAX_CURR_CAPS_EXT_OFFSET	0x4CU	/**< Maximum Current
-						Capabilities Ext Register */
-#define XSDPS_FE_ERR_INT_STS_OFFSET	0x52U	/**< Force Event for
-						Error Interrupt Status */
-#define XSDPS_FE_AUTO_CMD12_EIS_OFFSET	0x50U	/**< Auto CM12 Error Interrupt
-							Status Register */
-#define XSDPS_ADMA_ERR_STS_OFFSET	0x54U	/**< ADMA Error Status
-							Register */
-#define XSDPS_ADMA_SAR_OFFSET		0x58U	/**< ADMA System Address
-							Register */
-#define XSDPS_ADMA_SAR_EXT_OFFSET	0x5CU	/**< ADMA System Address
-							Extended Register */
-#define XSDPS_PRE_VAL_1_OFFSET		0x60U	/**< Preset Value Register */
-#define XSDPS_PRE_VAL_2_OFFSET		0x64U	/**< Preset Value Register */
-#define XSDPS_PRE_VAL_3_OFFSET		0x68U	/**< Preset Value Register */
-#define XSDPS_PRE_VAL_4_OFFSET		0x6CU	/**< Preset Value Register */
-#define XSDPS_BOOT_TOUT_CTRL_OFFSET	0x70U	/**< Boot timeout control
-							register */
+#define XSDPS_AUTO_CMD12_ERR_STS_OFFSET    0x3CU	/**< Auto CMD12 Error Status
+						    Register */
+#define XSDPS_HOST_CTRL2_OFFSET	    0x3EU	/**< Host Control2 Register */
+#define XSDPS_CAPS_OFFSET 	    0x40U	/**< Capabilities Register */
+#define XSDPS_CAPS_EXT_OFFSET 	    0x44U	/**< Capabilities Extended */
+#define XSDPS_MAX_CURR_CAPS_OFFSET    0x48U	/**< Maximum Current
+					    Capabilities Register */
+#define XSDPS_MAX_CURR_CAPS_EXT_OFFSET    0x4CU	/**< Maximum Current
+					    Capabilities Ext Register */
+#define XSDPS_FE_ERR_INT_STS_OFFSET    0x52U	/**< Force Event for
+					    Error Interrupt Status */
+#define XSDPS_FE_AUTO_CMD12_EIS_OFFSET    0x50U	/**< Auto CM12 Error Interrupt
+						    Status Register */
+#define XSDPS_ADMA_ERR_STS_OFFSET    0x54U	/**< ADMA Error Status
+						    Register */
+#define XSDPS_ADMA_SAR_OFFSET	    0x58U	/**< ADMA System Address
+						    Register */
+#define XSDPS_ADMA_SAR_EXT_OFFSET    0x5CU	/**< ADMA System Address
+						    Extended Register */
+#define XSDPS_PRE_VAL_1_OFFSET	    0x60U	/**< Preset Value Register */
+#define XSDPS_PRE_VAL_2_OFFSET	    0x64U	/**< Preset Value Register */
+#define XSDPS_PRE_VAL_3_OFFSET	    0x68U	/**< Preset Value Register */
+#define XSDPS_PRE_VAL_4_OFFSET	    0x6CU	/**< Preset Value Register */
+#define XSDPS_BOOT_TOUT_CTRL_OFFSET    0x70U	/**< Boot timeout control
+						    register */
 
-#define XSDPS_SHARED_BUS_CTRL_OFFSET	0xE0U	/**< Shared Bus Control
-							Register */
-#define XSDPS_SLOT_INTR_STS_OFFSET	0xFCU	/**< Slot Interrupt Status
-							Register */
-#define XSDPS_HOST_CTRL_VER_OFFSET	0xFEU	/**< Host Controller Version
-							Register */
+#define XSDPS_SHARED_BUS_CTRL_OFFSET    0xE0U	/**< Shared Bus Control
+						    Register */
+#define XSDPS_SLOT_INTR_STS_OFFSET    0xFCU	/**< Slot Interrupt Status
+						    Register */
+#define XSDPS_HOST_CTRL_VER_OFFSET    0xFEU	/**< Host Controller Version
+						    Register */
 
 /* @} */
 
 /** @name Control Register - Host control, Power control,
- * 			Block Gap control and Wakeup control
+ * 		    Block Gap control and Wakeup control
  *
  * This register contains bits for various configuration options of
  * the SD host controller. Read/Write apart from the reserved bits.
  * @{
  */
 
-#define XSDPS_HC_LED_MASK		0x00000001U /**< LED Control */
-#define XSDPS_HC_WIDTH_MASK		0x00000002U /**< Bus width */
-#define XSDPS_HC_BUS_WIDTH_4		0x00000002U
-#define XSDPS_HC_SPEED_MASK		0x00000004U /**< High Speed */
-#define XSDPS_HC_DMA_MASK		0x00000018U /**< DMA Mode Select */
-#define XSDPS_HC_DMA_SDMA_MASK		0x00000000U /**< SDMA Mode */
-#define XSDPS_HC_DMA_ADMA1_MASK		0x00000008U /**< ADMA1 Mode */
-#define XSDPS_HC_DMA_ADMA2_32_MASK	0x00000010U /**< ADMA2 Mode - 32 bit */
-#define XSDPS_HC_DMA_ADMA2_64_MASK	0x00000018U /**< ADMA2 Mode - 64 bit */
-#define XSDPS_HC_EXT_BUS_WIDTH		0x00000020U /**< Bus width - 8 bit */
-#define XSDPS_HC_CARD_DET_TL_MASK	0x00000040U /**< Card Detect Tst Lvl */
-#define XSDPS_HC_CARD_DET_SD_MASK	0x00000080U /**< Card Detect Sig Det */
+#define XSDPS_HC_LED_MASK	    0x00000001U /**< LED Control */
+#define XSDPS_HC_WIDTH_MASK	    0x00000002U /**< Bus width */
+#define XSDPS_HC_BUS_WIDTH_4	    0x00000002U
+#define XSDPS_HC_SPEED_MASK	    0x00000004U /**< High Speed */
+#define XSDPS_HC_DMA_MASK	    0x00000018U /**< DMA Mode Select */
+#define XSDPS_HC_DMA_SDMA_MASK	    0x00000000U /**< SDMA Mode */
+#define XSDPS_HC_DMA_ADMA1_MASK	    0x00000008U /**< ADMA1 Mode */
+#define XSDPS_HC_DMA_ADMA2_32_MASK    0x00000010U /**< ADMA2 Mode - 32 bit */
+#define XSDPS_HC_DMA_ADMA2_64_MASK    0x00000018U /**< ADMA2 Mode - 64 bit */
+#define XSDPS_HC_EXT_BUS_WIDTH	    0x00000020U /**< Bus width - 8 bit */
+#define XSDPS_HC_CARD_DET_TL_MASK    0x00000040U /**< Card Detect Tst Lvl */
+#define XSDPS_HC_CARD_DET_SD_MASK    0x00000080U /**< Card Detect Sig Det */
 
-#define XSDPS_PC_BUS_PWR_MASK		0x00000001U /**< Bus Power Control */
-#define XSDPS_PC_BUS_VSEL_MASK		0x0000000EU /**< Bus Voltage Select */
-#define XSDPS_PC_BUS_VSEL_3V3_MASK	0x0000000EU /**< Bus Voltage 3.3V */
-#define XSDPS_PC_BUS_VSEL_3V0_MASK	0x0000000CU /**< Bus Voltage 3.0V */
-#define XSDPS_PC_BUS_VSEL_1V8_MASK	0x0000000AU /**< Bus Voltage 1.8V */
-#define XSDPS_PC_EMMC_HW_RST_MASK	0x00000010U /**< HW reset for eMMC */
+#define XSDPS_PC_BUS_PWR_MASK	    0x00000001U /**< Bus Power Control */
+#define XSDPS_PC_BUS_VSEL_MASK	    0x0000000EU /**< Bus Voltage Select */
+#define XSDPS_PC_BUS_VSEL_3V3_MASK    0x0000000EU /**< Bus Voltage 3.3V */
+#define XSDPS_PC_BUS_VSEL_3V0_MASK    0x0000000CU /**< Bus Voltage 3.0V */
+#define XSDPS_PC_BUS_VSEL_1V8_MASK    0x0000000AU /**< Bus Voltage 1.8V */
+#define XSDPS_PC_EMMC_HW_RST_MASK    0x00000010U /**< HW reset for eMMC */
 
-#define XSDPS_BGC_STP_REQ_MASK		0x00000001U /**< Block Gap Stop Req */
-#define XSDPS_BGC_CNT_REQ_MASK		0x00000002U /**< Block Gap Cont Req */
-#define XSDPS_BGC_RWC_MASK		0x00000004U /**< Block Gap Rd Wait */
-#define XSDPS_BGC_INTR_MASK		0x00000008U /**< Block Gap Intr */
-#define XSDPS_BGC_SPI_MODE_MASK		0x00000010U /**< Block Gap SPI Mode */
-#define XSDPS_BGC_BOOT_EN_MASK		0x00000020U /**< Block Gap Boot Enb */
-#define XSDPS_BGC_ALT_BOOT_EN_MASK	0x00000040U /**< Block Gap Alt BootEn */
-#define XSDPS_BGC_BOOT_ACK_MASK		0x00000080U /**< Block Gap Boot Ack */
+#define XSDPS_BGC_STP_REQ_MASK	    0x00000001U /**< Block Gap Stop Req */
+#define XSDPS_BGC_CNT_REQ_MASK	    0x00000002U /**< Block Gap Cont Req */
+#define XSDPS_BGC_RWC_MASK	    0x00000004U /**< Block Gap Rd Wait */
+#define XSDPS_BGC_INTR_MASK	    0x00000008U /**< Block Gap Intr */
+#define XSDPS_BGC_SPI_MODE_MASK	    0x00000010U /**< Block Gap SPI Mode */
+#define XSDPS_BGC_BOOT_EN_MASK	    0x00000020U /**< Block Gap Boot Enb */
+#define XSDPS_BGC_ALT_BOOT_EN_MASK    0x00000040U /**< Block Gap Alt BootEn */
+#define XSDPS_BGC_BOOT_ACK_MASK	    0x00000080U /**< Block Gap Boot Ack */
 
-#define XSDPS_WC_WUP_ON_INTR_MASK	0x00000001U /**< Wakeup Card Intr */
-#define XSDPS_WC_WUP_ON_INSRT_MASK	0x00000002U /**< Wakeup Card Insert */
-#define XSDPS_WC_WUP_ON_REM_MASK	0x00000004U /**< Wakeup Card Removal */
+#define XSDPS_WC_WUP_ON_INTR_MASK    0x00000001U /**< Wakeup Card Intr */
+#define XSDPS_WC_WUP_ON_INSRT_MASK    0x00000002U /**< Wakeup Card Insert */
+#define XSDPS_WC_WUP_ON_REM_MASK    0x00000004U /**< Wakeup Card Removal */
 
 /* @} */
 
@@ -198,33 +198,33 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_CC_INT_CLK_EN_MASK		0x00000001U
-#define XSDPS_CC_INT_CLK_STABLE_MASK	0x00000002U
-#define XSDPS_CC_SD_CLK_EN_MASK			0x00000004U
-#define XSDPS_CC_SD_CLK_GEN_SEL_MASK		0x00000020U
-#define XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK	0x00000003U
-#define XSDPS_CC_SDCLK_FREQ_SEL_MASK		0x000000FFU
-#define XSDPS_CC_SDCLK_FREQ_D256_MASK		0x00008000U
-#define XSDPS_CC_SDCLK_FREQ_D128_MASK		0x00004000U
-#define XSDPS_CC_SDCLK_FREQ_D64_MASK		0x00002000U
-#define XSDPS_CC_SDCLK_FREQ_D32_MASK		0x00001000U
-#define XSDPS_CC_SDCLK_FREQ_D16_MASK		0x00000800U
-#define XSDPS_CC_SDCLK_FREQ_D8_MASK		0x00000400U
-#define XSDPS_CC_SDCLK_FREQ_D4_MASK		0x00000200U
-#define XSDPS_CC_SDCLK_FREQ_D2_MASK		0x00000100U
-#define XSDPS_CC_SDCLK_FREQ_BASE_MASK	0x00000000U
-#define XSDPS_CC_MAX_DIV_CNT			256U
-#define XSDPS_CC_EXT_MAX_DIV_CNT		2046U
-#define XSDPS_CC_EXT_DIV_SHIFT			6U
+#define XSDPS_CC_INT_CLK_EN_MASK	    0x00000001U
+#define XSDPS_CC_INT_CLK_STABLE_MASK    0x00000002U
+#define XSDPS_CC_SD_CLK_EN_MASK		    0x00000004U
+#define XSDPS_CC_SD_CLK_GEN_SEL_MASK	    0x00000020U
+#define XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK    0x00000003U
+#define XSDPS_CC_SDCLK_FREQ_SEL_MASK	    0x000000FFU
+#define XSDPS_CC_SDCLK_FREQ_D256_MASK	    0x00008000U
+#define XSDPS_CC_SDCLK_FREQ_D128_MASK	    0x00004000U
+#define XSDPS_CC_SDCLK_FREQ_D64_MASK	    0x00002000U
+#define XSDPS_CC_SDCLK_FREQ_D32_MASK	    0x00001000U
+#define XSDPS_CC_SDCLK_FREQ_D16_MASK	    0x00000800U
+#define XSDPS_CC_SDCLK_FREQ_D8_MASK	    0x00000400U
+#define XSDPS_CC_SDCLK_FREQ_D4_MASK	    0x00000200U
+#define XSDPS_CC_SDCLK_FREQ_D2_MASK	    0x00000100U
+#define XSDPS_CC_SDCLK_FREQ_BASE_MASK    0x00000000U
+#define XSDPS_CC_MAX_DIV_CNT		    256U
+#define XSDPS_CC_EXT_MAX_DIV_CNT	    2046U
+#define XSDPS_CC_EXT_DIV_SHIFT		    6U
 
-#define XSDPS_TC_CNTR_VAL_MASK			0x0000000FU
+#define XSDPS_TC_CNTR_VAL_MASK		    0x0000000FU
 
-#define XSDPS_SWRST_ALL_MASK			0x00000001U
-#define XSDPS_SWRST_CMD_LINE_MASK		0x00000002U
-#define XSDPS_SWRST_DAT_LINE_MASK		0x00000004U
+#define XSDPS_SWRST_ALL_MASK		    0x00000001U
+#define XSDPS_SWRST_CMD_LINE_MASK	    0x00000002U
+#define XSDPS_SWRST_DAT_LINE_MASK	    0x00000004U
 
-#define XSDPS_CC_MAX_NUM_OF_DIV		9U
-#define XSDPS_CC_DIV_SHIFT		8U
+#define XSDPS_CC_MAX_NUM_OF_DIV	    9U
+#define XSDPS_CC_DIV_SHIFT	    8U
 
 /* @} */
 
@@ -251,42 +251,42 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_INTR_CC_MASK		0x00000001U /**< Command Complete */
-#define XSDPS_INTR_TC_MASK		0x00000002U /**< Transfer Complete */
-#define XSDPS_INTR_BGE_MASK		0x00000004U /**< Block Gap Event */
-#define XSDPS_INTR_DMA_MASK		0x00000008U /**< DMA Interrupt */
-#define XSDPS_INTR_BWR_MASK		0x00000010U /**< Buffer Write Ready */
-#define XSDPS_INTR_BRR_MASK		0x00000020U /**< Buffer Read Ready */
-#define XSDPS_INTR_CARD_INSRT_MASK	0x00000040U /**< Card Insert */
-#define XSDPS_INTR_CARD_REM_MASK	0x00000080U /**< Card Remove */
-#define XSDPS_INTR_CARD_MASK		0x00000100U /**< Card Interrupt */
-#define XSDPS_INTR_INT_A_MASK		0x00000200U /**< INT A Interrupt */
-#define XSDPS_INTR_INT_B_MASK		0x00000400U /**< INT B Interrupt */
-#define XSDPS_INTR_INT_C_MASK		0x00000800U /**< INT C Interrupt */
-#define XSDPS_INTR_RE_TUNING_MASK	0x00001000U /**< Re-Tuning Interrupt */
-#define XSDPS_INTR_BOOT_ACK_RECV_MASK	0x00002000U /**< Boot Ack Recv
-							Interrupt */
-#define XSDPS_INTR_BOOT_TERM_MASK	0x00004000U /**< Boot Terminate
-							Interrupt */
-#define XSDPS_INTR_ERR_MASK		0x00008000U /**< Error Interrupt */
-#define XSDPS_NORM_INTR_ALL_MASK	0x0000FFFFU
+#define XSDPS_INTR_CC_MASK	    0x00000001U /**< Command Complete */
+#define XSDPS_INTR_TC_MASK	    0x00000002U /**< Transfer Complete */
+#define XSDPS_INTR_BGE_MASK	    0x00000004U /**< Block Gap Event */
+#define XSDPS_INTR_DMA_MASK	    0x00000008U /**< DMA Interrupt */
+#define XSDPS_INTR_BWR_MASK	    0x00000010U /**< Buffer Write Ready */
+#define XSDPS_INTR_BRR_MASK	    0x00000020U /**< Buffer Read Ready */
+#define XSDPS_INTR_CARD_INSRT_MASK    0x00000040U /**< Card Insert */
+#define XSDPS_INTR_CARD_REM_MASK    0x00000080U /**< Card Remove */
+#define XSDPS_INTR_CARD_MASK	    0x00000100U /**< Card Interrupt */
+#define XSDPS_INTR_INT_A_MASK	    0x00000200U /**< INT A Interrupt */
+#define XSDPS_INTR_INT_B_MASK	    0x00000400U /**< INT B Interrupt */
+#define XSDPS_INTR_INT_C_MASK	    0x00000800U /**< INT C Interrupt */
+#define XSDPS_INTR_RE_TUNING_MASK    0x00001000U /**< Re-Tuning Interrupt */
+#define XSDPS_INTR_BOOT_ACK_RECV_MASK    0x00002000U /**< Boot Ack Recv
+						    Interrupt */
+#define XSDPS_INTR_BOOT_TERM_MASK    0x00004000U /**< Boot Terminate
+						    Interrupt */
+#define XSDPS_INTR_ERR_MASK	    0x00008000U /**< Error Interrupt */
+#define XSDPS_NORM_INTR_ALL_MASK    0x0000FFFFU
 
-#define XSDPS_INTR_ERR_CT_MASK		0x00000001U /**< Command Timeout
-							Error */
-#define XSDPS_INTR_ERR_CCRC_MASK	0x00000002U /**< Command CRC Error */
-#define XSDPS_INTR_ERR_CEB_MASK		0x00000004U /**< Command End Bit
-							Error */
-#define XSDPS_INTR_ERR_CI_MASK		0x00000008U /**< Command Index Error */
-#define XSDPS_INTR_ERR_DT_MASK		0x00000010U /**< Data Timeout Error */
-#define XSDPS_INTR_ERR_DCRC_MASK	0x00000020U /**< Data CRC Error */
-#define XSDPS_INTR_ERR_DEB_MASK		0x00000040U /**< Data End Bit Error */
-#define XSDPS_INTR_ERR_CUR_LMT_MASK	0x00000080U /**< Current Limit Error */
-#define XSDPS_INTR_ERR_AUTO_CMD12_MASK	0x00000100U /**< Auto CMD12 Error */
-#define XSDPS_INTR_ERR_ADMA_MASK	0x00000200U /**< ADMA Error */
-#define XSDPS_INTR_ERR_TR_MASK		0x00001000U /**< Tuning Error */
-#define XSDPS_INTR_VEND_SPF_ERR_MASK	0x0000E000U /**< Vendor Specific
-							Error */
-#define XSDPS_ERROR_INTR_ALL_MASK	0x0000F3FFU /**< Mask for error bits */
+#define XSDPS_INTR_ERR_CT_MASK	    0x00000001U /**< Command Timeout
+						    Error */
+#define XSDPS_INTR_ERR_CCRC_MASK    0x00000002U /**< Command CRC Error */
+#define XSDPS_INTR_ERR_CEB_MASK	    0x00000004U /**< Command End Bit
+						    Error */
+#define XSDPS_INTR_ERR_CI_MASK	    0x00000008U /**< Command Index Error */
+#define XSDPS_INTR_ERR_DT_MASK	    0x00000010U /**< Data Timeout Error */
+#define XSDPS_INTR_ERR_DCRC_MASK    0x00000020U /**< Data CRC Error */
+#define XSDPS_INTR_ERR_DEB_MASK	    0x00000040U /**< Data End Bit Error */
+#define XSDPS_INTR_ERR_CUR_LMT_MASK    0x00000080U /**< Current Limit Error */
+#define XSDPS_INTR_ERR_AUTO_CMD12_MASK    0x00000100U /**< Auto CMD12 Error */
+#define XSDPS_INTR_ERR_ADMA_MASK    0x00000200U /**< ADMA Error */
+#define XSDPS_INTR_ERR_TR_MASK	    0x00001000U /**< Tuning Error */
+#define XSDPS_INTR_VEND_SPF_ERR_MASK    0x0000E000U /**< Vendor Specific
+						    Error */
+#define XSDPS_ERROR_INTR_ALL_MASK    0x0000F3FFU /**< Mask for error bits */
 /* @} */
 
 /** @name Block Size and Block Count Register
@@ -297,12 +297,12 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_BLK_SIZE_MASK		0x00000FFFU /**< Transfer Block Size */
-#define XSDPS_SDMA_BUFF_SIZE_MASK	0x00007000U /**< Host SDMA Buffer Size */
-#define XSDPS_BLK_SIZE_1024		0x400U
-#define XSDPS_BLK_SIZE_2048		0x800U
-#define XSDPS_BLK_CNT_MASK		0x0000FFFFU /**< Block Count for
-								Current Transfer */
+#define XSDPS_BLK_SIZE_MASK	    0x00000FFFU /**< Transfer Block Size */
+#define XSDPS_SDMA_BUFF_SIZE_MASK    0x00007000U /**< Host SDMA Buffer Size */
+#define XSDPS_BLK_SIZE_1024	    0x400U
+#define XSDPS_BLK_SIZE_2048	    0x800U
+#define XSDPS_BLK_CNT_MASK	    0x0000FFFFU /**< Block Count for
+							    Current Transfer */
 
 /* @} */
 
@@ -314,35 +314,35 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_TM_DMA_EN_MASK		0x00000001U /**< DMA Enable */
-#define XSDPS_TM_BLK_CNT_EN_MASK	0x00000002U /**< Block Count Enable */
-#define XSDPS_TM_AUTO_CMD12_EN_MASK	0x00000004U /**< Auto CMD12 Enable */
-#define XSDPS_TM_DAT_DIR_SEL_MASK	0x00000010U /**< Data Transfer
-							Direction Select */
-#define XSDPS_TM_MUL_SIN_BLK_SEL_MASK	0x00000020U /**< Multi/Single
-							Block Select */
+#define XSDPS_TM_DMA_EN_MASK	    0x00000001U /**< DMA Enable */
+#define XSDPS_TM_BLK_CNT_EN_MASK    0x00000002U /**< Block Count Enable */
+#define XSDPS_TM_AUTO_CMD12_EN_MASK    0x00000004U /**< Auto CMD12 Enable */
+#define XSDPS_TM_DAT_DIR_SEL_MASK    0x00000010U /**< Data Transfer
+						    Direction Select */
+#define XSDPS_TM_MUL_SIN_BLK_SEL_MASK    0x00000020U /**< Multi/Single
+						    Block Select */
 
-#define XSDPS_CMD_RESP_SEL_MASK		0x00000003U /**< Response Type
-							Select */
-#define XSDPS_CMD_RESP_NONE_MASK	0x00000000U /**< No Response */
-#define XSDPS_CMD_RESP_L136_MASK	0x00000001U /**< Response length 138 */
-#define XSDPS_CMD_RESP_L48_MASK		0x00000002U /**< Response length 48 */
-#define XSDPS_CMD_RESP_L48_BSY_CHK_MASK	0x00000003U /**< Response length 48 &
-							check busy after
-							response */
-#define XSDPS_CMD_CRC_CHK_EN_MASK	0x00000008U /**< Command CRC Check
-							Enable */
-#define XSDPS_CMD_INX_CHK_EN_MASK	0x00000010U /**< Command Index Check
-							Enable */
-#define XSDPS_DAT_PRESENT_SEL_MASK	0x00000020U /**< Data Present Select */
-#define XSDPS_CMD_TYPE_MASK		0x000000C0U /**< Command Type */
-#define XSDPS_CMD_TYPE_NORM_MASK	0x00000000U /**< CMD Type - Normal */
-#define XSDPS_CMD_TYPE_SUSPEND_MASK	0x00000040U /**< CMD Type - Suspend */
-#define XSDPS_CMD_TYPE_RESUME_MASK	0x00000080U /**< CMD Type - Resume */
-#define XSDPS_CMD_TYPE_ABORT_MASK	0x000000C0U /**< CMD Type - Abort */
-#define XSDPS_CMD_MASK			0x00003F00U /**< Command Index Mask -
-							Set to CMD0-63,
-							AMCD0-63 */
+#define XSDPS_CMD_RESP_SEL_MASK	    0x00000003U /**< Response Type
+						    Select */
+#define XSDPS_CMD_RESP_NONE_MASK    0x00000000U /**< No Response */
+#define XSDPS_CMD_RESP_L136_MASK    0x00000001U /**< Response length 138 */
+#define XSDPS_CMD_RESP_L48_MASK	    0x00000002U /**< Response length 48 */
+#define XSDPS_CMD_RESP_L48_BSY_CHK_MASK    0x00000003U /**< Response length 48 &
+						    check busy after
+						    response */
+#define XSDPS_CMD_CRC_CHK_EN_MASK    0x00000008U /**< Command CRC Check
+						    Enable */
+#define XSDPS_CMD_INX_CHK_EN_MASK    0x00000010U /**< Command Index Check
+						    Enable */
+#define XSDPS_DAT_PRESENT_SEL_MASK    0x00000020U /**< Data Present Select */
+#define XSDPS_CMD_TYPE_MASK	    0x000000C0U /**< Command Type */
+#define XSDPS_CMD_TYPE_NORM_MASK    0x00000000U /**< CMD Type - Normal */
+#define XSDPS_CMD_TYPE_SUSPEND_MASK    0x00000040U /**< CMD Type - Suspend */
+#define XSDPS_CMD_TYPE_RESUME_MASK    0x00000080U /**< CMD Type - Resume */
+#define XSDPS_CMD_TYPE_ABORT_MASK    0x000000C0U /**< CMD Type - Abort */
+#define XSDPS_CMD_MASK		    0x00003F00U /**< Command Index Mask -
+						    Set to CMD0-63,
+						    AMCD0-63 */
 
 /* @} */
 
@@ -353,16 +353,16 @@ extern "C" {
  * Read Only
  * @{
  */
-#define XSDPS_AUTO_CMD12_NT_EX_MASK	0x0001U /**< Auto CMD12 Not
-							executed */
-#define XSDPS_AUTO_CMD_TOUT_MASK	0x0002U /**< Auto CMD Timeout
-							Error */
-#define XSDPS_AUTO_CMD_CRC_MASK		0x0004U /**< Auto CMD CRC Error */
-#define XSDPS_AUTO_CMD_EB_MASK		0x0008U /**< Auto CMD End Bit
-							Error */
-#define XSDPS_AUTO_CMD_IND_MASK		0x0010U /**< Auto CMD Index Error */
-#define XSDPS_AUTO_CMD_CNI_ERR_MASK	0x0080U /**< Command not issued by
-							Auto CMD12 Error */
+#define XSDPS_AUTO_CMD12_NT_EX_MASK    0x0001U /**< Auto CMD12 Not
+						    executed */
+#define XSDPS_AUTO_CMD_TOUT_MASK    0x0002U /**< Auto CMD Timeout
+						    Error */
+#define XSDPS_AUTO_CMD_CRC_MASK	    0x0004U /**< Auto CMD CRC Error */
+#define XSDPS_AUTO_CMD_EB_MASK	    0x0008U /**< Auto CMD End Bit
+						    Error */
+#define XSDPS_AUTO_CMD_IND_MASK	    0x0010U /**< Auto CMD Index Error */
+#define XSDPS_AUTO_CMD_CNI_ERR_MASK    0x0080U /**< Command not issued by
+						    Auto CMD12 Error */
 /* @} */
 
 /** @name Host Control2 Register
@@ -371,25 +371,25 @@ extern "C" {
  * Read Write
  * @{
  */
-#define XSDPS_HC2_UHS_MODE_MASK		0x0007U /**< UHS Mode select bits */
-#define XSDPS_HC2_UHS_MODE_SDR12_MASK	0x0000U /**< SDR12 UHS Mode */
-#define XSDPS_HC2_UHS_MODE_SDR25_MASK	0x0001U /**< SDR25 UHS Mode */
-#define XSDPS_HC2_UHS_MODE_SDR50_MASK	0x0002U /**< SDR50 UHS Mode */
-#define XSDPS_HC2_UHS_MODE_SDR104_MASK	0x0003U /**< SDR104 UHS Mode */
-#define XSDPS_HC2_UHS_MODE_DDR50_MASK	0x0004U /**< DDR50 UHS Mode */
-#define XSDPS_HC2_1V8_EN_MASK		0x0008U /**< 1.8V Signal Enable */
-#define XSDPS_HC2_DRV_STR_SEL_MASK	0x0030U /**< Driver Strength
-							Selection */
-#define XSDPS_HC2_DRV_STR_B_MASK	0x0000U /**< Driver Strength B */
-#define XSDPS_HC2_DRV_STR_A_MASK	0x0010U /**< Driver Strength A */
-#define XSDPS_HC2_DRV_STR_C_MASK	0x0020U /**< Driver Strength C */
-#define XSDPS_HC2_DRV_STR_D_MASK	0x0030U /**< Driver Strength D */
-#define XSDPS_HC2_EXEC_TNG_MASK		0x0040U /**< Execute Tuning */
-#define XSDPS_HC2_SAMP_CLK_SEL_MASK	0x0080U /**< Sampling Clock
-							Selection */
-#define XSDPS_HC2_ASYNC_INTR_EN_MASK	0x4000U /**< Asynchronous Interrupt
-							Enable */
-#define XSDPS_HC2_PRE_VAL_EN_MASK	0x8000U /**< Preset Value Enable */
+#define XSDPS_HC2_UHS_MODE_MASK	    0x0007U /**< UHS Mode select bits */
+#define XSDPS_HC2_UHS_MODE_SDR12_MASK    0x0000U /**< SDR12 UHS Mode */
+#define XSDPS_HC2_UHS_MODE_SDR25_MASK    0x0001U /**< SDR25 UHS Mode */
+#define XSDPS_HC2_UHS_MODE_SDR50_MASK    0x0002U /**< SDR50 UHS Mode */
+#define XSDPS_HC2_UHS_MODE_SDR104_MASK    0x0003U /**< SDR104 UHS Mode */
+#define XSDPS_HC2_UHS_MODE_DDR50_MASK    0x0004U /**< DDR50 UHS Mode */
+#define XSDPS_HC2_1V8_EN_MASK	    0x0008U /**< 1.8V Signal Enable */
+#define XSDPS_HC2_DRV_STR_SEL_MASK    0x0030U /**< Driver Strength
+						    Selection */
+#define XSDPS_HC2_DRV_STR_B_MASK    0x0000U /**< Driver Strength B */
+#define XSDPS_HC2_DRV_STR_A_MASK    0x0010U /**< Driver Strength A */
+#define XSDPS_HC2_DRV_STR_C_MASK    0x0020U /**< Driver Strength C */
+#define XSDPS_HC2_DRV_STR_D_MASK    0x0030U /**< Driver Strength D */
+#define XSDPS_HC2_EXEC_TNG_MASK	    0x0040U /**< Execute Tuning */
+#define XSDPS_HC2_SAMP_CLK_SEL_MASK    0x0080U /**< Sampling Clock
+						    Selection */
+#define XSDPS_HC2_ASYNC_INTR_EN_MASK    0x4000U /**< Asynchronous Interrupt
+						    Enable */
+#define XSDPS_HC2_PRE_VAL_EN_MASK    0x8000U /**< Preset Value Enable */
 
 /* @} */
 
@@ -401,63 +401,63 @@ extern "C" {
  * Read Only
  * @{
  */
-#define XSDPS_CAP_TOUT_CLK_FREQ_MASK	0x0000003FU /**< Timeout clock freq
-							select */
-#define XSDPS_CAP_TOUT_CLK_UNIT_MASK	0x00000080U /**< Timeout clock unit -
-							MHz/KHz */
-#define XSDPS_CAP_MAX_BLK_LEN_MASK	0x00030000U /**< Max block length */
-#define XSDPS_CAP_MAX_BLK_LEN_512B_MASK	0x00000000U /**< Max block 512 bytes */
-#define XSDPS_CAP_MAX_BL_LN_1024_MASK	0x00010000U /**< Max block 1024 bytes */
-#define XSDPS_CAP_MAX_BL_LN_2048_MASK	0x00020000U /**< Max block 2048 bytes */
-#define XSDPS_CAP_MAX_BL_LN_4096_MASK	0x00030000U /**< Max block 4096 bytes */
+#define XSDPS_CAP_TOUT_CLK_FREQ_MASK    0x0000003FU /**< Timeout clock freq
+						    select */
+#define XSDPS_CAP_TOUT_CLK_UNIT_MASK    0x00000080U /**< Timeout clock unit -
+						    MHz/KHz */
+#define XSDPS_CAP_MAX_BLK_LEN_MASK    0x00030000U /**< Max block length */
+#define XSDPS_CAP_MAX_BLK_LEN_512B_MASK    0x00000000U /**< Max block 512 bytes */
+#define XSDPS_CAP_MAX_BL_LN_1024_MASK    0x00010000U /**< Max block 1024 bytes */
+#define XSDPS_CAP_MAX_BL_LN_2048_MASK    0x00020000U /**< Max block 2048 bytes */
+#define XSDPS_CAP_MAX_BL_LN_4096_MASK    0x00030000U /**< Max block 4096 bytes */
 
-#define XSDPS_CAP_EXT_MEDIA_BUS_MASK	0x00040000U /**< Extended media bus */
-#define XSDPS_CAP_ADMA2_MASK		0x00080000U /**< ADMA2 support */
-#define XSDPS_CAP_HIGH_SPEED_MASK	0x00200000U /**< High speed support */
-#define XSDPS_CAP_SDMA_MASK		0x00400000U /**< SDMA support */
-#define XSDPS_CAP_SUSP_RESUME_MASK	0x00800000U /**< Suspend/Resume
-							support */
-#define XSDPS_CAP_VOLT_3V3_MASK		0x01000000U /**< 3.3V support */
-#define XSDPS_CAP_VOLT_3V0_MASK		0x02000000U /**< 3.0V support */
-#define XSDPS_CAP_VOLT_1V8_MASK		0x04000000U /**< 1.8V support */
+#define XSDPS_CAP_EXT_MEDIA_BUS_MASK    0x00040000U /**< Extended media bus */
+#define XSDPS_CAP_ADMA2_MASK	    0x00080000U /**< ADMA2 support */
+#define XSDPS_CAP_HIGH_SPEED_MASK    0x00200000U /**< High speed support */
+#define XSDPS_CAP_SDMA_MASK	    0x00400000U /**< SDMA support */
+#define XSDPS_CAP_SUSP_RESUME_MASK    0x00800000U /**< Suspend/Resume
+						    support */
+#define XSDPS_CAP_VOLT_3V3_MASK	    0x01000000U /**< 3.3V support */
+#define XSDPS_CAP_VOLT_3V0_MASK	    0x02000000U /**< 3.0V support */
+#define XSDPS_CAP_VOLT_1V8_MASK	    0x04000000U /**< 1.8V support */
 
-#define XSDPS_CAP_SYS_BUS_64_MASK	0x10000000U /**< 64 bit system bus
-							support */
+#define XSDPS_CAP_SYS_BUS_64_MASK    0x10000000U /**< 64 bit system bus
+						    support */
 /* Spec 2.0 */
-#define XSDPS_CAP_INTR_MODE_MASK	0x08000000U /**< Interrupt mode
-							support */
-#define XSDPS_CAP_SPI_MODE_MASK		0x20000000U /**< SPI mode */
-#define XSDPS_CAP_SPI_BLOCK_MODE_MASK	0x40000000U /**< SPI block mode */
+#define XSDPS_CAP_INTR_MODE_MASK    0x08000000U /**< Interrupt mode
+						    support */
+#define XSDPS_CAP_SPI_MODE_MASK	    0x20000000U /**< SPI mode */
+#define XSDPS_CAP_SPI_BLOCK_MODE_MASK    0x40000000U /**< SPI block mode */
 
 
 /* Spec 3.0 */
-#define XSDPS_CAPS_ASYNC_INTR_MASK	0x20000000U /**< Async Interrupt
-							support */
-#define XSDPS_CAPS_SLOT_TYPE_MASK	0xC0000000U /**< Slot Type */
-#define XSDPS_CAPS_REM_CARD			0x00000000U /**< Removable Slot */
-#define XSDPS_CAPS_EMB_SLOT			0x40000000U /**< Embedded Slot */
-#define XSDPS_CAPS_SHR_BUS			0x80000000U /**< Shared Bus Slot */
+#define XSDPS_CAPS_ASYNC_INTR_MASK    0x20000000U /**< Async Interrupt
+						    support */
+#define XSDPS_CAPS_SLOT_TYPE_MASK    0xC0000000U /**< Slot Type */
+#define XSDPS_CAPS_REM_CARD		    0x00000000U /**< Removable Slot */
+#define XSDPS_CAPS_EMB_SLOT		    0x40000000U /**< Embedded Slot */
+#define XSDPS_CAPS_SHR_BUS		    0x80000000U /**< Shared Bus Slot */
 
-#define XSDPS_ECAPS_SDR50_MASK		0x00000001U /**< SDR50 Mode support */
-#define XSDPS_ECAPS_SDR104_MASK		0x00000002U /**< SDR104 Mode support */
-#define XSDPS_ECAPS_DDR50_MASK		0x00000004U /**< DDR50 Mode support */
-#define XSDPS_ECAPS_DRV_TYPE_A_MASK	0x00000010U /**< DriverType A support */
-#define XSDPS_ECAPS_DRV_TYPE_C_MASK	0x00000020U /**< DriverType C support */
-#define XSDPS_ECAPS_DRV_TYPE_D_MASK	0x00000040U /**< DriverType D support */
-#define XSDPS_ECAPS_TMR_CNT_MASK	0x00000F00U /**< Timer Count for
-							Re-tuning */
-#define XSDPS_ECAPS_USE_TNG_SDR50_MASK	0x00002000U /**< SDR50 Mode needs
-							tuning */
-#define XSDPS_ECAPS_RE_TNG_MODES_MASK	0x0000C000U /**< Re-tuning modes
-							support */
-#define XSDPS_ECAPS_RE_TNG_MODE1_MASK	0x00000000U /**< Re-tuning mode 1 */
-#define XSDPS_ECAPS_RE_TNG_MODE2_MASK	0x00004000U /**< Re-tuning mode 2 */
-#define XSDPS_ECAPS_RE_TNG_MODE3_MASK	0x00008000U /**< Re-tuning mode 3 */
-#define XSDPS_ECAPS_CLK_MULT_MASK	0x00FF0000U /**< Clock Multiplier value
-							for Programmable clock
-							mode */
-#define XSDPS_ECAPS_SPI_MODE_MASK	0x01000000U /**< SPI mode */
-#define XSDPS_ECAPS_SPI_BLK_MODE_MASK	0x02000000U /**< SPI block mode */
+#define XSDPS_ECAPS_SDR50_MASK	    0x00000001U /**< SDR50 Mode support */
+#define XSDPS_ECAPS_SDR104_MASK	    0x00000002U /**< SDR104 Mode support */
+#define XSDPS_ECAPS_DDR50_MASK	    0x00000004U /**< DDR50 Mode support */
+#define XSDPS_ECAPS_DRV_TYPE_A_MASK    0x00000010U /**< DriverType A support */
+#define XSDPS_ECAPS_DRV_TYPE_C_MASK    0x00000020U /**< DriverType C support */
+#define XSDPS_ECAPS_DRV_TYPE_D_MASK    0x00000040U /**< DriverType D support */
+#define XSDPS_ECAPS_TMR_CNT_MASK    0x00000F00U /**< Timer Count for
+						    Re-tuning */
+#define XSDPS_ECAPS_USE_TNG_SDR50_MASK    0x00002000U /**< SDR50 Mode needs
+						    tuning */
+#define XSDPS_ECAPS_RE_TNG_MODES_MASK    0x0000C000U /**< Re-tuning modes
+						    support */
+#define XSDPS_ECAPS_RE_TNG_MODE1_MASK    0x00000000U /**< Re-tuning mode 1 */
+#define XSDPS_ECAPS_RE_TNG_MODE2_MASK    0x00004000U /**< Re-tuning mode 2 */
+#define XSDPS_ECAPS_RE_TNG_MODE3_MASK    0x00008000U /**< Re-tuning mode 3 */
+#define XSDPS_ECAPS_CLK_MULT_MASK    0x00FF0000U /**< Clock Multiplier value
+						    for Programmable clock
+						    mode */
+#define XSDPS_ECAPS_SPI_MODE_MASK    0x01000000U /**< SPI mode */
+#define XSDPS_ECAPS_SPI_BLK_MODE_MASK    0x02000000U /**< SPI block mode */
 
 /* @} */
 
@@ -468,22 +468,22 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_PSR_INHIBIT_CMD_MASK	0x00000001U /**< Command inhibit - CMD */
-#define XSDPS_PSR_INHIBIT_DAT_MASK	0x00000002U /**< Command Inhibit - DAT */
-#define XSDPS_PSR_DAT_ACTIVE_MASK	0x00000004U /**< DAT line active */
-#define XSDPS_PSR_RE_TUNING_REQ_MASK	0x00000008U /**< Re-tuning request */
-#define XSDPS_PSR_WR_ACTIVE_MASK	0x00000100U /**< Write transfer active */
-#define XSDPS_PSR_RD_ACTIVE_MASK	0x00000200U /**< Read transfer active */
-#define XSDPS_PSR_BUFF_WR_EN_MASK	0x00000400U /**< Buffer write enable */
-#define XSDPS_PSR_BUFF_RD_EN_MASK	0x00000800U /**< Buffer read enable */
-#define XSDPS_PSR_CARD_INSRT_MASK	0x00010000U /**< Card inserted */
-#define XSDPS_PSR_CARD_STABLE_MASK	0x00020000U /**< Card state stable */
-#define XSDPS_PSR_CARD_DPL_MASK		0x00040000U /**< Card detect pin level */
-#define XSDPS_PSR_WPS_PL_MASK		0x00080000U /**< Write protect switch
-								pin level */
-#define XSDPS_PSR_DAT30_SG_LVL_MASK	0x00F00000U /**< Data 3:0 signal lvl */
-#define XSDPS_PSR_CMD_SG_LVL_MASK	0x01000000U /**< Cmd Line signal lvl */
-#define XSDPS_PSR_DAT74_SG_LVL_MASK	0x1E000000U /**< Data 7:4 signal lvl */
+#define XSDPS_PSR_INHIBIT_CMD_MASK    0x00000001U /**< Command inhibit - CMD */
+#define XSDPS_PSR_INHIBIT_DAT_MASK    0x00000002U /**< Command Inhibit - DAT */
+#define XSDPS_PSR_DAT_ACTIVE_MASK    0x00000004U /**< DAT line active */
+#define XSDPS_PSR_RE_TUNING_REQ_MASK    0x00000008U /**< Re-tuning request */
+#define XSDPS_PSR_WR_ACTIVE_MASK    0x00000100U /**< Write transfer active */
+#define XSDPS_PSR_RD_ACTIVE_MASK    0x00000200U /**< Read transfer active */
+#define XSDPS_PSR_BUFF_WR_EN_MASK    0x00000400U /**< Buffer write enable */
+#define XSDPS_PSR_BUFF_RD_EN_MASK    0x00000800U /**< Buffer read enable */
+#define XSDPS_PSR_CARD_INSRT_MASK    0x00010000U /**< Card inserted */
+#define XSDPS_PSR_CARD_STABLE_MASK    0x00020000U /**< Card state stable */
+#define XSDPS_PSR_CARD_DPL_MASK	    0x00040000U /**< Card detect pin level */
+#define XSDPS_PSR_WPS_PL_MASK	    0x00080000U /**< Write protect switch
+							    pin level */
+#define XSDPS_PSR_DAT30_SG_LVL_MASK    0x00F00000U /**< Data 3:0 signal lvl */
+#define XSDPS_PSR_CMD_SG_LVL_MASK    0x01000000U /**< Cmd Line signal lvl */
+#define XSDPS_PSR_DAT74_SG_LVL_MASK    0x1E000000U /**< Data 7:4 signal lvl */
 
 /* @} */
 
@@ -494,12 +494,12 @@ extern "C" {
  * Read Only
  * @{
  */
-#define XSDPS_MAX_CUR_CAPS_1V8_MASK	0x00000F00U /**< Maximum Current
-							Capability at 1.8V */
-#define XSDPS_MAX_CUR_CAPS_3V0_MASK	0x000000F0U /**< Maximum Current
-							Capability at 3.0V */
-#define XSDPS_MAX_CUR_CAPS_3V3_MASK	0x0000000FU /**< Maximum Current
-							Capability at 3.3V */
+#define XSDPS_MAX_CUR_CAPS_1V8_MASK    0x00000F00U /**< Maximum Current
+						    Capability at 1.8V */
+#define XSDPS_MAX_CUR_CAPS_3V0_MASK    0x000000F0U /**< Maximum Current
+						    Capability at 3.0V */
+#define XSDPS_MAX_CUR_CAPS_3V3_MASK    0x0000000FU /**< Maximum Current
+						    Capability at 3.3V */
 /* @} */
 
 
@@ -510,16 +510,16 @@ extern "C" {
  * Write Only
  * @{
  */
-#define XSDPS_FE_AUTO_CMD12_NT_EX_MASK	0x0001U /**< Auto CMD12 Not
-							executed */
-#define XSDPS_FE_AUTO_CMD_TOUT_MASK	0x0002U /**< Auto CMD Timeout
-							Error */
-#define XSDPS_FE_AUTO_CMD_CRC_MASK	0x0004U /**< Auto CMD CRC Error */
-#define XSDPS_FE_AUTO_CMD_EB_MASK	0x0008U /**< Auto CMD End Bit
-							Error */
-#define XSDPS_FE_AUTO_CMD_IND_MASK	0x0010U /**< Auto CMD Index Error */
-#define XSDPS_FE_AUTO_CMD_CNI_ERR_MASK	0x0080U /**< Command not issued by
-							Auto CMD12 Error */
+#define XSDPS_FE_AUTO_CMD12_NT_EX_MASK    0x0001U /**< Auto CMD12 Not
+						    executed */
+#define XSDPS_FE_AUTO_CMD_TOUT_MASK    0x0002U /**< Auto CMD Timeout
+						    Error */
+#define XSDPS_FE_AUTO_CMD_CRC_MASK    0x0004U /**< Auto CMD CRC Error */
+#define XSDPS_FE_AUTO_CMD_EB_MASK    0x0008U /**< Auto CMD End Bit
+						    Error */
+#define XSDPS_FE_AUTO_CMD_IND_MASK    0x0010U /**< Auto CMD Index Error */
+#define XSDPS_FE_AUTO_CMD_CNI_ERR_MASK    0x0080U /**< Command not issued by
+						    Auto CMD12 Error */
 /* @} */
 
 
@@ -531,21 +531,21 @@ extern "C" {
  * Write Only
  * @{
  */
-#define XSDPS_FE_INTR_ERR_CT_MASK	0x0001U /**< Command Timeout
-							Error */
-#define XSDPS_FE_INTR_ERR_CCRC_MASK	0x0002U /**< Command CRC Error */
-#define XSDPS_FE_INTR_ERR_CEB_MASK	0x0004U /**< Command End Bit
-							Error */
-#define XSDPS_FE_INTR_ERR_CI_MASK	0x0008U /**< Command Index Error */
-#define XSDPS_FE_INTR_ERR_DT_MASK	0x0010U /**< Data Timeout Error */
-#define XSDPS_FE_INTR_ERR_DCRC_MASK	0x0020U /**< Data CRC Error */
-#define XSDPS_FE_INTR_ERR_DEB_MASK	0x0040U /**< Data End Bit Error */
-#define XSDPS_FE_INTR_ERR_CUR_LMT_MASK	0x0080U /**< Current Limit Error */
-#define XSDPS_FE_INTR_ERR_AUTO_CMD_MASK	0x0100U /**< Auto CMD Error */
-#define XSDPS_FE_INTR_ERR_ADMA_MASK	0x0200U /**< ADMA Error */
-#define XSDPS_FE_INTR_ERR_TR_MASK	0x1000U /**< Target Response */
-#define XSDPS_FE_INTR_VEND_SPF_ERR_MASK	0xE000U /**< Vendor Specific
-							Error */
+#define XSDPS_FE_INTR_ERR_CT_MASK    0x0001U /**< Command Timeout
+						    Error */
+#define XSDPS_FE_INTR_ERR_CCRC_MASK    0x0002U /**< Command CRC Error */
+#define XSDPS_FE_INTR_ERR_CEB_MASK    0x0004U /**< Command End Bit
+						    Error */
+#define XSDPS_FE_INTR_ERR_CI_MASK    0x0008U /**< Command Index Error */
+#define XSDPS_FE_INTR_ERR_DT_MASK    0x0010U /**< Data Timeout Error */
+#define XSDPS_FE_INTR_ERR_DCRC_MASK    0x0020U /**< Data CRC Error */
+#define XSDPS_FE_INTR_ERR_DEB_MASK    0x0040U /**< Data End Bit Error */
+#define XSDPS_FE_INTR_ERR_CUR_LMT_MASK    0x0080U /**< Current Limit Error */
+#define XSDPS_FE_INTR_ERR_AUTO_CMD_MASK    0x0100U /**< Auto CMD Error */
+#define XSDPS_FE_INTR_ERR_ADMA_MASK    0x0200U /**< ADMA Error */
+#define XSDPS_FE_INTR_ERR_TR_MASK    0x1000U /**< Target Response */
+#define XSDPS_FE_INTR_VEND_SPF_ERR_MASK    0xE000U /**< Vendor Specific
+						    Error */
 
 /* @} */
 
@@ -556,15 +556,15 @@ extern "C" {
  * Read Only
  * @{
  */
-#define XSDPS_ADMA_ERR_MM_LEN_MASK	0x04U /**< ADMA Length Mismatch
-							Error */
-#define XSDPS_ADMA_ERR_STATE_MASK	0x03U /**< ADMA Error State */
-#define XSDPS_ADMA_ERR_STATE_STOP_MASK	0x00U /**< ADMA Error State
-							STOP */
-#define XSDPS_ADMA_ERR_STATE_FDS_MASK	0x01U /**< ADMA Error State
-							FDS */
-#define XSDPS_ADMA_ERR_STATE_TFR_MASK	0x03U /**< ADMA Error State
-							TFR */
+#define XSDPS_ADMA_ERR_MM_LEN_MASK    0x04U /**< ADMA Length Mismatch
+						    Error */
+#define XSDPS_ADMA_ERR_STATE_MASK    0x03U /**< ADMA Error State */
+#define XSDPS_ADMA_ERR_STATE_STOP_MASK    0x00U /**< ADMA Error State
+						    STOP */
+#define XSDPS_ADMA_ERR_STATE_FDS_MASK    0x01U /**< ADMA Error State
+						    FDS */
+#define XSDPS_ADMA_ERR_STATE_TFR_MASK    0x03U /**< ADMA Error State
+						    TFR */
 /* @} */
 
 /** @name Preset Values Register
@@ -574,12 +574,12 @@ extern "C" {
  * Read Only
  * @{
  */
-#define XSDPS_PRE_VAL_SDCLK_FSEL_MASK	0x03FFU /**< SDCLK Frequency
-							Select Value */
-#define XSDPS_PRE_VAL_CLK_GEN_SEL_MASK	0x0400U /**< Clock Generator
-							Mode Select */
-#define XSDPS_PRE_VAL_DRV_STR_SEL_MASK	0xC000U /**< Driver Strength
-							Select Value */
+#define XSDPS_PRE_VAL_SDCLK_FSEL_MASK    0x03FFU /**< SDCLK Frequency
+						    Select Value */
+#define XSDPS_PRE_VAL_CLK_GEN_SEL_MASK    0x0400U /**< Clock Generator
+						    Mode Select */
+#define XSDPS_PRE_VAL_DRV_STR_SEL_MASK    0xC000U /**< Driver Strength
+						    Select Value */
 
 /* @} */
 
@@ -590,8 +590,8 @@ extern "C" {
  * Read Only
  * @{
  */
-#define XSDPS_SLOT_INTR_STS_INT_MASK	0x0007U /**< Interrupt Signal
-							mask */
+#define XSDPS_SLOT_INTR_STS_INT_MASK    0x0007U /**< Interrupt Signal
+						    mask */
 
 /* @} */
 
@@ -602,15 +602,15 @@ extern "C" {
  * Read Only
  * @{
  */
-#define XSDPS_HC_VENDOR_VER		0xFF00U /**< Vendor
-							Specification
-							version mask */
-#define XSDPS_HC_SPEC_VER_MASK		0x00FFU /**< Host
-							Specification
-							version mask */
-#define XSDPS_HC_SPEC_V3		0x0002U
-#define XSDPS_HC_SPEC_V2		0x0001U
-#define XSDPS_HC_SPEC_V1		0x0000U
+#define XSDPS_HC_VENDOR_VER	    0xFF00U /**< Vendor
+						    Specification
+						    version mask */
+#define XSDPS_HC_SPEC_VER_MASK	    0x00FFU /**< Host
+						    Specification
+						    version mask */
+#define XSDPS_HC_SPEC_V3	    0x0002U
+#define XSDPS_HC_SPEC_V2	    0x0001U
+#define XSDPS_HC_SPEC_V1	    0x0000U
 
 /** @name Block size mask for 512 bytes
  *
@@ -618,7 +618,7 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_BLK_SIZE_512_MASK	0x200U
+#define XSDPS_BLK_SIZE_512_MASK    0x200U
 
 /* @} */
 
@@ -692,7 +692,7 @@ extern "C" {
 /* @} */
 
 /* Card Interface Conditions Definitions */
-#define XSDPS_CIC_CHK_PATTERN	0xAAU
+#define XSDPS_CIC_CHK_PATTERN    0xAAU
 #define XSDPS_CIC_VOLT_MASK	(0xFU<<8)
 #define XSDPS_CIC_VOLT_2V7_3V6	(1U<<8)
 #define XSDPS_CIC_VOLT_LOW	(1U<<9)
@@ -711,19 +711,19 @@ extern "C" {
 #define XSDPS_OCR_2V8_2V9	(1U<<16)
 #define XSDPS_OCR_2V7_2V8	(1U<<15)
 #define XSDPS_OCR_1V7_1V95	(1U<<7)
-#define XSDPS_OCR_HIGH_VOL	0x00FF8000U
-#define XSDPS_OCR_LOW_VOL	0x00000080U
+#define XSDPS_OCR_HIGH_VOL    0x00FF8000U
+#define XSDPS_OCR_LOW_VOL    0x00000080U
 
 /* SD Card Configuration Register Definitions */
-#define XSDPS_SCR_REG_LEN		8U
+#define XSDPS_SCR_REG_LEN	    8U
 #define XSDPS_SCR_STRUCT_MASK		(0xFU<<28)
 #define XSDPS_SCR_SPEC_MASK		(0xFU<<24)
-#define XSDPS_SCR_SPEC_1V0		0U
+#define XSDPS_SCR_SPEC_1V0	    0U
 #define XSDPS_SCR_SPEC_1V1		(1U<<24)
 #define XSDPS_SCR_SPEC_2V0_3V0		(2U<<24)
 #define XSDPS_SCR_MEM_VAL_AF_ERASE	(1U<<23)
 #define XSDPS_SCR_SEC_SUPP_MASK		(7U<<20)
-#define XSDPS_SCR_SEC_SUPP_NONE		0U
+#define XSDPS_SCR_SEC_SUPP_NONE	    0U
 #define XSDPS_SCR_SEC_SUPP_1V1		(2U<<20)
 #define XSDPS_SCR_SEC_SUPP_2V0		(3U<<20)
 #define XSDPS_SCR_SEC_SUPP_3V0		(4U<<20)
@@ -731,9 +731,9 @@ extern "C" {
 #define XSDPS_SCR_BUS_WIDTH_1		(1U<<16)
 #define XSDPS_SCR_BUS_WIDTH_4		(4U<<16)
 #define XSDPS_SCR_SPEC3_MASK		(1U<<12)
-#define XSDPS_SCR_SPEC3_2V0		0U
+#define XSDPS_SCR_SPEC3_2V0	    0U
 #define XSDPS_SCR_SPEC3_3V0		(1U<<12)
-#define XSDPS_SCR_CMD_SUPP_MASK		0x3U
+#define XSDPS_SCR_CMD_SUPP_MASK	    0x3U
 #define XSDPS_SCR_CMD23_SUPP		(1U<<1)
 #define XSDPS_SCR_CMD20_SUPP		(1U<<0)
 
@@ -761,56 +761,56 @@ extern "C" {
 #define XSDPS_CD_STS_AKE_SEQ_ERR	(1U<<2)
 
 /* Switch Function Definitions CMD6 */
-#define XSDPS_SWITCH_SD_RESP_LEN	64U
+#define XSDPS_SWITCH_SD_RESP_LEN    64U
 
 #define XSDPS_SWITCH_FUNC_SWITCH	(1U<<31)
-#define XSDPS_SWITCH_FUNC_CHECK		0U
+#define XSDPS_SWITCH_FUNC_CHECK	    0U
 
-#define XSDPS_MODE_FUNC_GRP1		1U
-#define XSDPS_MODE_FUNC_GRP2		2U
-#define XSDPS_MODE_FUNC_GRP3		3U
-#define XSDPS_MODE_FUNC_GRP4		4U
-#define XSDPS_MODE_FUNC_GRP5		5U
-#define XSDPS_MODE_FUNC_GRP6		6U
+#define XSDPS_MODE_FUNC_GRP1	    1U
+#define XSDPS_MODE_FUNC_GRP2	    2U
+#define XSDPS_MODE_FUNC_GRP3	    3U
+#define XSDPS_MODE_FUNC_GRP4	    4U
+#define XSDPS_MODE_FUNC_GRP5	    5U
+#define XSDPS_MODE_FUNC_GRP6	    6U
 
-#define XSDPS_FUNC_GRP_DEF_VAL		0xFU
-#define XSDPS_FUNC_ALL_GRP_DEF_VAL	0xFFFFFFU
+#define XSDPS_FUNC_GRP_DEF_VAL	    0xFU
+#define XSDPS_FUNC_ALL_GRP_DEF_VAL    0xFFFFFFU
 
-#define XSDPS_ACC_MODE_DEF_SDR12	0U
-#define XSDPS_ACC_MODE_HS_SDR25		1U
-#define XSDPS_ACC_MODE_SDR50		2U
-#define XSDPS_ACC_MODE_SDR104		3U
-#define XSDPS_ACC_MODE_DDR50		4U
+#define XSDPS_ACC_MODE_DEF_SDR12    0U
+#define XSDPS_ACC_MODE_HS_SDR25	    1U
+#define XSDPS_ACC_MODE_SDR50	    2U
+#define XSDPS_ACC_MODE_SDR104	    3U
+#define XSDPS_ACC_MODE_DDR50	    4U
 
-#define XSDPS_CMD_SYS_ARG_SHIFT		4U
-#define XSDPS_CMD_SYS_DEF		0U
-#define XSDPS_CMD_SYS_eC		1U
-#define XSDPS_CMD_SYS_OTP		3U
-#define XSDPS_CMD_SYS_ASSD		4U
-#define XSDPS_CMD_SYS_VEND		5U
+#define XSDPS_CMD_SYS_ARG_SHIFT	    4U
+#define XSDPS_CMD_SYS_DEF	    0U
+#define XSDPS_CMD_SYS_eC	    1U
+#define XSDPS_CMD_SYS_OTP	    3U
+#define XSDPS_CMD_SYS_ASSD	    4U
+#define XSDPS_CMD_SYS_VEND	    5U
 
-#define XSDPS_DRV_TYPE_ARG_SHIFT	8U
-#define XSDPS_DRV_TYPE_B		0U
-#define XSDPS_DRV_TYPE_A		1U
-#define XSDPS_DRV_TYPE_C		2U
-#define XSDPS_DRV_TYPE_D		3U
+#define XSDPS_DRV_TYPE_ARG_SHIFT    8U
+#define XSDPS_DRV_TYPE_B	    0U
+#define XSDPS_DRV_TYPE_A	    1U
+#define XSDPS_DRV_TYPE_C	    2U
+#define XSDPS_DRV_TYPE_D	    3U
 
-#define XSDPS_CUR_LIM_ARG_SHIFT		12U
-#define XSDPS_CUR_LIM_200		0U
-#define XSDPS_CUR_LIM_400		1U
-#define XSDPS_CUR_LIM_600		2U
-#define XSDPS_CUR_LIM_800		3U
+#define XSDPS_CUR_LIM_ARG_SHIFT	    12U
+#define XSDPS_CUR_LIM_200	    0U
+#define XSDPS_CUR_LIM_400	    1U
+#define XSDPS_CUR_LIM_600	    2U
+#define XSDPS_CUR_LIM_800	    3U
 
-#define CSD_SPEC_VER_MASK		0x3C0000U
-#define READ_BLK_LEN_MASK		0x00000F00U
-#define C_SIZE_MULT_MASK		0x00000380U
-#define C_SIZE_LOWER_MASK		0xFFC00000U
-#define C_SIZE_UPPER_MASK		0x00000003U
-#define CSD_STRUCT_MASK			0x00C00000U
-#define CSD_V2_C_SIZE_MASK		0x3FFFFF00U
+#define CSD_SPEC_VER_MASK	    0x3C0000U
+#define READ_BLK_LEN_MASK	    0x00000F00U
+#define C_SIZE_MULT_MASK	    0x00000380U
+#define C_SIZE_LOWER_MASK	    0xFFC00000U
+#define C_SIZE_UPPER_MASK	    0x00000003U
+#define CSD_STRUCT_MASK		    0x00C00000U
+#define CSD_V2_C_SIZE_MASK	    0x3FFFFF00U
 
 /* EXT_CSD field definitions */
-#define XSDPS_EXT_CSD_SIZE		512U
+#define XSDPS_EXT_CSD_SIZE	    512U
 
 #define EXT_CSD_WR_REL_PARAM_EN		(1U<<2)
 
@@ -824,7 +824,7 @@ extern "C" {
 #define EXT_CSD_PART_CONFIG_ACC_BOOT1   (0x2U)
 #define EXT_CSD_PART_CONFIG_ACC_RPMB    (0x3U)
 #define EXT_CSD_PART_CONFIG_ACC_GP0     (0x4U)
-#define EXT_CSD_PART_CONFIG_BYTE		179U
+#define EXT_CSD_PART_CONFIG_BYTE	    179U
 #define XSDPS_MMC_PART_CFG_0_ARG		((XSDPS_EXT_CSD_WRITE_BYTE << 24U) \
 					 | (EXT_CSD_PART_CONFIG_BYTE << 16U) \
 					 | ((0U) << 8U))
@@ -845,7 +845,7 @@ extern "C" {
 
 #define EXT_CSD_CARD_TYPE_26    	(1U<<0)  /* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_52    	(1U<<1)  /* Card can run at 52MHz */
-#define EXT_CSD_CARD_TYPE_MASK  	0x3FU    /* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_MASK      0x3FU    /* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_DDR_1_8V	(1U<<2)   /* Card can run at 52MHz */
                                              /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V	(1U<<3)   /* Card can run at 52MHz */
@@ -855,27 +855,27 @@ extern "C" {
 #define EXT_CSD_CARD_TYPE_SDR_1_8V      (1U<<4)  /* Card can run at 200MHz */
 #define EXT_CSD_CARD_TYPE_SDR_1_2V      (1U<<5)  /* Card can run at 200MHz */
                                                 /* SDR mode @1.2V I/O */
-#define EXT_CSD_BUS_WIDTH_BYTE			183U
-#define EXT_CSD_BUS_WIDTH_1_BIT			0U	/* Card is in 1 bit mode */
-#define EXT_CSD_BUS_WIDTH_4_BIT			1U	/* Card is in 4 bit mode */
-#define EXT_CSD_BUS_WIDTH_8_BIT			2U	/* Card is in 8 bit mode */
-#define EXT_CSD_BUS_WIDTH_DDR_4_BIT		5U	/* Card is in 4 bit DDR mode */
-#define EXT_CSD_BUS_WIDTH_DDR_8_BIT		6U	/* Card is in 8 bit DDR mode */
+#define EXT_CSD_BUS_WIDTH_BYTE		    183U
+#define EXT_CSD_BUS_WIDTH_1_BIT		    0U	/* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4_BIT		    1U	/* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8_BIT		    2U	/* Card is in 8 bit mode */
+#define EXT_CSD_BUS_WIDTH_DDR_4_BIT	    5U	/* Card is in 4 bit DDR mode */
+#define EXT_CSD_BUS_WIDTH_DDR_8_BIT	    6U	/* Card is in 8 bit DDR mode */
 
-#define EXT_CSD_HS_TIMING_BYTE		185U
-#define EXT_CSD_HS_TIMING_DEF		0U
-#define EXT_CSD_HS_TIMING_HIGH		1U	/* Card is in high speed mode */
-#define EXT_CSD_HS_TIMING_HS200		2U	/* Card is in HS200 mode */
+#define EXT_CSD_HS_TIMING_BYTE	    185U
+#define EXT_CSD_HS_TIMING_DEF	    0U
+#define EXT_CSD_HS_TIMING_HIGH	    1U	/* Card is in high speed mode */
+#define EXT_CSD_HS_TIMING_HS200	    2U	/* Card is in HS200 mode */
 
-#define EXT_CSD_RST_N_FUN_BYTE		162U
-#define EXT_CSD_RST_N_FUN_TEMP_DIS	0U	/* RST_n signal is temporarily disabled */
-#define EXT_CSD_RST_N_FUN_PERM_EN	1U	/* RST_n signal is permanently enabled */
-#define EXT_CSD_RST_N_FUN_PERM_DIS	2U	/* RST_n signal is permanently disabled */
+#define EXT_CSD_RST_N_FUN_BYTE	    162U
+#define EXT_CSD_RST_N_FUN_TEMP_DIS    0U	/* RST_n signal is temporarily disabled */
+#define EXT_CSD_RST_N_FUN_PERM_EN    1U	/* RST_n signal is permanently enabled */
+#define EXT_CSD_RST_N_FUN_PERM_DIS    2U	/* RST_n signal is permanently disabled */
 
-#define XSDPS_EXT_CSD_CMD_SET		0U
-#define XSDPS_EXT_CSD_SET_BITS		1U
-#define XSDPS_EXT_CSD_CLR_BITS		2U
-#define XSDPS_EXT_CSD_WRITE_BYTE	3U
+#define XSDPS_EXT_CSD_CMD_SET	    0U
+#define XSDPS_EXT_CSD_SET_BITS	    1U
+#define XSDPS_EXT_CSD_CLR_BITS	    2U
+#define XSDPS_EXT_CSD_WRITE_BYTE    3U
 
 #define XSDPS_MMC_DEF_SPEED_ARG		(((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
 					| ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \
@@ -913,23 +913,23 @@ extern "C" {
 					 | ((u32)EXT_CSD_RST_N_FUN_BYTE << 16) \
 					 | ((u32)EXT_CSD_RST_N_FUN_PERM_EN << 8))
 
-#define XSDPS_MMC_DELAY_FOR_SWITCH	1000U
+#define XSDPS_MMC_DELAY_FOR_SWITCH    1000U
 
 /* @} */
 
 /* @400KHz, in usec */
-#define XSDPS_74CLK_DELAY	2960U
-#define XSDPS_100CLK_DELAY	4000U
-#define XSDPS_INIT_DELAY	10000U
+#define XSDPS_74CLK_DELAY    2960U
+#define XSDPS_100CLK_DELAY    4000U
+#define XSDPS_INIT_DELAY    10000U
 
-#define XSDPS_DEF_VOLT_LVL	XSDPS_PC_BUS_VSEL_3V0_MASK
-#define XSDPS_CARD_DEF_ADDR	0x1234U
+#define XSDPS_DEF_VOLT_LVL    XSDPS_PC_BUS_VSEL_3V0_MASK
+#define XSDPS_CARD_DEF_ADDR    0x1234U
 
-#define XSDPS_CARD_SD		1U
-#define XSDPS_CARD_MMC		2U
-#define XSDPS_CARD_SDIO		3U
-#define XSDPS_CARD_SDCOMBO	4U
-#define XSDPS_CHIP_EMMC		5U
+#define XSDPS_CARD_SD	    1U
+#define XSDPS_CARD_MMC	    2U
+#define XSDPS_CARD_SDIO	    3U
+#define XSDPS_CARD_SDCOMBO    4U
+#define XSDPS_CHIP_EMMC	    5U
 
 
 /** @name ADMA2 Descriptor related definitions
@@ -948,150 +948,150 @@ extern "C" {
 /* @} */
 
 /* For changing clock frequencies */
-#define XSDPS_CLK_400_KHZ		400000U		/**< 400 KHZ */
-#define XSDPS_CLK_50_MHZ		50000000U	/**< 50 MHZ */
-#define XSDPS_CLK_52_MHZ		52000000U	/**< 52 MHZ */
-#define XSDPS_SD_VER_1_0		0x1U		/**< SD ver 1 */
-#define XSDPS_SD_VER_2_0		0x2U		/**< SD ver 2 */
-#define XSDPS_SCR_BLKCNT	1U
-#define XSDPS_SCR_BLKSIZE	8U
-#define XSDPS_1_BIT_WIDTH	0x1U
-#define XSDPS_4_BIT_WIDTH	0x2U
-#define XSDPS_8_BIT_WIDTH	0x3U
-#define XSDPS_UHS_SPEED_MODE_SDR12	0x0U
-#define XSDPS_UHS_SPEED_MODE_SDR25	0x1U
-#define XSDPS_UHS_SPEED_MODE_SDR50	0x2U
-#define XSDPS_UHS_SPEED_MODE_SDR104	0x3U
-#define XSDPS_UHS_SPEED_MODE_DDR50	0x4U
-#define XSDPS_HIGH_SPEED_MODE		0x5U
-#define XSDPS_DEFAULT_SPEED_MODE	0x6U
-#define XSDPS_HS200_MODE			0x7U
-#define XSDPS_DDR52_MODE			0x4U
-#define XSDPS_SWITCH_CMD_BLKCNT		1U
-#define XSDPS_SWITCH_CMD_BLKSIZE	64U
-#define XSDPS_SWITCH_CMD_HS_GET		0x00FFFFF0U
-#define XSDPS_SWITCH_CMD_HS_SET		0x80FFFFF1U
-#define XSDPS_SWITCH_CMD_SDR12_SET		0x80FFFFF0U
-#define XSDPS_SWITCH_CMD_SDR25_SET		0x80FFFFF1U
-#define XSDPS_SWITCH_CMD_SDR50_SET		0x80FFFFF2U
-#define XSDPS_SWITCH_CMD_SDR104_SET		0x80FFFFF3U
-#define XSDPS_SWITCH_CMD_DDR50_SET		0x80FFFFF4U
-#define XSDPS_EXT_CSD_CMD_BLKCNT	1U
-#define XSDPS_EXT_CSD_CMD_BLKSIZE	512U
-#define XSDPS_TUNING_CMD_BLKCNT		1U
-#define XSDPS_TUNING_CMD_BLKSIZE	64U
-#define XSDPS_SD_STATUS_BLKCNT		1U
-#define XSDPS_SD_STATUS_BLKSIZE		64U
+#define XSDPS_CLK_400_KHZ	    400000U		/**< 400 KHZ */
+#define XSDPS_CLK_50_MHZ	    50000000U	/**< 50 MHZ */
+#define XSDPS_CLK_52_MHZ	    52000000U	/**< 52 MHZ */
+#define XSDPS_SD_VER_1_0	    0x1U		/**< SD ver 1 */
+#define XSDPS_SD_VER_2_0	    0x2U		/**< SD ver 2 */
+#define XSDPS_SCR_BLKCNT    1U
+#define XSDPS_SCR_BLKSIZE    8U
+#define XSDPS_1_BIT_WIDTH    0x1U
+#define XSDPS_4_BIT_WIDTH    0x2U
+#define XSDPS_8_BIT_WIDTH    0x3U
+#define XSDPS_UHS_SPEED_MODE_SDR12    0x0U
+#define XSDPS_UHS_SPEED_MODE_SDR25    0x1U
+#define XSDPS_UHS_SPEED_MODE_SDR50    0x2U
+#define XSDPS_UHS_SPEED_MODE_SDR104    0x3U
+#define XSDPS_UHS_SPEED_MODE_DDR50    0x4U
+#define XSDPS_HIGH_SPEED_MODE	    0x5U
+#define XSDPS_DEFAULT_SPEED_MODE    0x6U
+#define XSDPS_HS200_MODE		    0x7U
+#define XSDPS_DDR52_MODE		    0x4U
+#define XSDPS_SWITCH_CMD_BLKCNT	    1U
+#define XSDPS_SWITCH_CMD_BLKSIZE    64U
+#define XSDPS_SWITCH_CMD_HS_GET	    0x00FFFFF0U
+#define XSDPS_SWITCH_CMD_HS_SET	    0x80FFFFF1U
+#define XSDPS_SWITCH_CMD_SDR12_SET	    0x80FFFFF0U
+#define XSDPS_SWITCH_CMD_SDR25_SET	    0x80FFFFF1U
+#define XSDPS_SWITCH_CMD_SDR50_SET	    0x80FFFFF2U
+#define XSDPS_SWITCH_CMD_SDR104_SET	    0x80FFFFF3U
+#define XSDPS_SWITCH_CMD_DDR50_SET	    0x80FFFFF4U
+#define XSDPS_EXT_CSD_CMD_BLKCNT    1U
+#define XSDPS_EXT_CSD_CMD_BLKSIZE    512U
+#define XSDPS_TUNING_CMD_BLKCNT	    1U
+#define XSDPS_TUNING_CMD_BLKSIZE    64U
+#define XSDPS_SD_STATUS_BLKCNT	    1U
+#define XSDPS_SD_STATUS_BLKSIZE	    64U
 
-#define XSDPS_HIGH_SPEED_MAX_CLK	50000000U
-#define XSDPS_UHS_SDR104_MAX_CLK	208000000U
-#define XSDPS_UHS_SDR50_MAX_CLK		100000000U
-#define XSDPS_UHS_DDR50_MAX_CLK		50000000U
-#define XSDPS_UHS_SDR25_MAX_CLK		50000000U
-#define XSDPS_UHS_SDR12_MAX_CLK		25000000U
+#define XSDPS_HIGH_SPEED_MAX_CLK    50000000U
+#define XSDPS_UHS_SDR104_MAX_CLK    208000000U
+#define XSDPS_UHS_SDR50_MAX_CLK	    100000000U
+#define XSDPS_UHS_DDR50_MAX_CLK	    50000000U
+#define XSDPS_UHS_SDR25_MAX_CLK	    50000000U
+#define XSDPS_UHS_SDR12_MAX_CLK	    25000000U
 
-#define SD_DRIVER_TYPE_B	0x01U
-#define SD_DRIVER_TYPE_A	0x02U
-#define SD_DRIVER_TYPE_C	0x04U
-#define SD_DRIVER_TYPE_D	0x08U
-#define SD_SET_CURRENT_LIMIT_200	0U
-#define SD_SET_CURRENT_LIMIT_400	1U
-#define SD_SET_CURRENT_LIMIT_600	2U
-#define SD_SET_CURRENT_LIMIT_800	3U
+#define SD_DRIVER_TYPE_B    0x01U
+#define SD_DRIVER_TYPE_A    0x02U
+#define SD_DRIVER_TYPE_C    0x04U
+#define SD_DRIVER_TYPE_D    0x08U
+#define SD_SET_CURRENT_LIMIT_200    0U
+#define SD_SET_CURRENT_LIMIT_400    1U
+#define SD_SET_CURRENT_LIMIT_600    2U
+#define SD_SET_CURRENT_LIMIT_800    3U
 
 #define SD_MAX_CURRENT_200	(1U << SD_SET_CURRENT_LIMIT_200)
 #define SD_MAX_CURRENT_400	(1U << SD_SET_CURRENT_LIMIT_400)
 #define SD_MAX_CURRENT_600	(1U << SD_SET_CURRENT_LIMIT_600)
 #define SD_MAX_CURRENT_800	(1U << SD_SET_CURRENT_LIMIT_800)
 
-#define XSDPS_SD_SDR12_MAX_CLK	25000000U
-#define XSDPS_SD_SDR25_MAX_CLK	50000000U
-#define XSDPS_SD_SDR50_MAX_CLK	100000000U
-#define XSDPS_SD_DDR50_MAX_CLK	50000000U
-#define XSDPS_SD_SDR104_MAX_CLK	208000000U
+#define XSDPS_SD_SDR12_MAX_CLK    25000000U
+#define XSDPS_SD_SDR25_MAX_CLK    50000000U
+#define XSDPS_SD_SDR50_MAX_CLK    100000000U
+#define XSDPS_SD_DDR50_MAX_CLK    50000000U
+#define XSDPS_SD_SDR104_MAX_CLK    208000000U
 /*
  * XSDPS_SD_INPUT_MAX_CLK is set to 175000000 in order to keep it smaller
  * than the clock value coming from the core. This value is kept to safely
  * switch to SDR104 mode if the SD card supports it.
  */
-#define XSDPS_SD_INPUT_MAX_CLK	175000000U
+#define XSDPS_SD_INPUT_MAX_CLK    175000000U
 
-#define XSDPS_MMC_HS200_MAX_CLK	200000000U
-#define XSDPS_MMC_HSD_MAX_CLK	52000000U
-#define XSDPS_MMC_DDR_MAX_CLK	52000000U
+#define XSDPS_MMC_HS200_MAX_CLK    200000000U
+#define XSDPS_MMC_HSD_MAX_CLK    52000000U
+#define XSDPS_MMC_DDR_MAX_CLK    52000000U
 
-#define XSDPS_CARD_STATE_IDLE		0U
-#define XSDPS_CARD_STATE_RDY		1U
-#define XSDPS_CARD_STATE_IDEN		2U
-#define XSDPS_CARD_STATE_STBY		3U
-#define XSDPS_CARD_STATE_TRAN		4U
-#define XSDPS_CARD_STATE_DATA		5U
-#define XSDPS_CARD_STATE_RCV		6U
-#define XSDPS_CARD_STATE_PROG		7U
-#define XSDPS_CARD_STATE_DIS		8U
-#define XSDPS_CARD_STATE_BTST		9U
-#define XSDPS_CARD_STATE_SLP		10U
+#define XSDPS_CARD_STATE_IDLE	    0U
+#define XSDPS_CARD_STATE_RDY	    1U
+#define XSDPS_CARD_STATE_IDEN	    2U
+#define XSDPS_CARD_STATE_STBY	    3U
+#define XSDPS_CARD_STATE_TRAN	    4U
+#define XSDPS_CARD_STATE_DATA	    5U
+#define XSDPS_CARD_STATE_RCV	    6U
+#define XSDPS_CARD_STATE_PROG	    7U
+#define XSDPS_CARD_STATE_DIS	    8U
+#define XSDPS_CARD_STATE_BTST	    9U
+#define XSDPS_CARD_STATE_SLP	    10U
 
-#define XSDPS_SLOT_REM			0U
-#define XSDPS_SLOT_EMB			1U
+#define XSDPS_SLOT_REM		    0U
+#define XSDPS_SLOT_EMB		    1U
 
-#define XSDPS_WIDTH_8		8U
-#define XSDPS_WIDTH_4		4U
+#define XSDPS_WIDTH_8	    8U
+#define XSDPS_WIDTH_4	    4U
 
 
 #ifdef versal
-#define SD_ITAPDLY_SEL_MASK			0x000000FFU
-#define SD_OTAPDLY_SEL_MASK			0x0000003FU
-#define SD_ITAPDLY					0x0000F0F8U
-#define SD_OTAPDLY					0x0000F0FCU
-#define SD0_DLL_CTRL 				0x00000448U
-#define SD1_DLL_CTRL 				0x000004C8U
-#define SD_DLL_RST					0x00000004U
-#define SD_ITAPCHGWIN				0x00000200U
-#define SD_ITAPDLYENA				0x00000100U
-#define SD_OTAPDLYENA				0x00000040U
-#define SD_OTAPDLYSEL_HS200_B0		0x00000002U
-#define SD_OTAPDLYSEL_HS200_B2		0x00000002U
-#define SD_ITAPDLYSEL_SD50			0x0000000EU
-#define SD_OTAPDLYSEL_SD50			0x00000003U
-#define SD_ITAPDLYSEL_SD_DDR50		0x00000036U
-#define SD_ITAPDLYSEL_EMMC_DDR50	0x0000001EU
-#define SD_OTAPDLYSEL_SD_DDR50		0x00000003U
-#define SD_OTAPDLYSEL_EMMC_DDR50	0x00000005U
-#define SD_ITAPDLYSEL_HSD			0x0000002CU
-#define SD_OTAPDLYSEL_SD_HSD		0x00000004U
-#define SD_OTAPDLYSEL_EMMC_HSD		0x00000005U
+#define SD_ITAPDLY_SEL_MASK		    0x000000FFU
+#define SD_OTAPDLY_SEL_MASK		    0x0000003FU
+#define SD_ITAPDLY				    0x0000F0F8U
+#define SD_OTAPDLY				    0x0000F0FCU
+#define SD0_DLL_CTRL 			    0x00000448U
+#define SD1_DLL_CTRL 			    0x000004C8U
+#define SD_DLL_RST				    0x00000004U
+#define SD_ITAPCHGWIN			    0x00000200U
+#define SD_ITAPDLYENA			    0x00000100U
+#define SD_OTAPDLYENA			    0x00000040U
+#define SD_OTAPDLYSEL_HS200_B0	    0x00000002U
+#define SD_OTAPDLYSEL_HS200_B2	    0x00000002U
+#define SD_ITAPDLYSEL_SD50		    0x0000000EU
+#define SD_OTAPDLYSEL_SD50		    0x00000003U
+#define SD_ITAPDLYSEL_SD_DDR50	    0x00000036U
+#define SD_ITAPDLYSEL_EMMC_DDR50    0x0000001EU
+#define SD_OTAPDLYSEL_SD_DDR50	    0x00000003U
+#define SD_OTAPDLYSEL_EMMC_DDR50    0x00000005U
+#define SD_ITAPDLYSEL_HSD		    0x0000002CU
+#define SD_OTAPDLYSEL_SD_HSD	    0x00000004U
+#define SD_OTAPDLYSEL_EMMC_HSD	    0x00000005U
 #else
-#define SD0_ITAPDLY_SEL_MASK		0x000000FFU
-#define SD0_OTAPDLY_SEL_MASK		0x0000003FU
-#define SD1_ITAPDLY_SEL_MASK		0x00FF0000U
-#define SD1_OTAPDLY_SEL_MASK		0x003F0000U
-#define SD_DLL_CTRL 				0x00000358U
-#define SD_ITAPDLY					0x00000314U
-#define SD_OTAPDLY					0x00000318U
-#define SD0_DLL_RST					0x00000004U
-#define SD1_DLL_RST					0x00040000U
-#define SD0_ITAPCHGWIN				0x00000200U
-#define SD0_ITAPDLYENA				0x00000100U
-#define SD0_OTAPDLYENA				0x00000040U
-#define SD1_ITAPCHGWIN				0x02000000U
-#define SD1_ITAPDLYENA				0x01000000U
-#define SD1_OTAPDLYENA				0x00400000U
-#define SD_OTAPDLYSEL_HS200_B0		0x00000003U
-#define SD_OTAPDLYSEL_HS200_B2		0x00000002U
-#define SD_ITAPDLYSEL_SD50			0x00000014U
-#define SD_OTAPDLYSEL_SD50			0x00000003U
-#define SD_ITAPDLYSEL_SD_DDR50		0x0000003DU
-#define SD_ITAPDLYSEL_EMMC_DDR50	0x00000012U
-#define SD_OTAPDLYSEL_SD_DDR50		0x00000004U
-#define SD_OTAPDLYSEL_EMMC_DDR50	0x00000006U
-#define SD_ITAPDLYSEL_HSD			0x00000015U
-#define SD_OTAPDLYSEL_SD_HSD		0x00000005U
-#define SD_OTAPDLYSEL_EMMC_HSD		0x00000006U
+#define SD0_ITAPDLY_SEL_MASK	    0x000000FFU
+#define SD0_OTAPDLY_SEL_MASK	    0x0000003FU
+#define SD1_ITAPDLY_SEL_MASK	    0x00FF0000U
+#define SD1_OTAPDLY_SEL_MASK	    0x003F0000U
+#define SD_DLL_CTRL 			    0x00000358U
+#define SD_ITAPDLY				    0x00000314U
+#define SD_OTAPDLY				    0x00000318U
+#define SD0_DLL_RST				    0x00000004U
+#define SD1_DLL_RST				    0x00040000U
+#define SD0_ITAPCHGWIN			    0x00000200U
+#define SD0_ITAPDLYENA			    0x00000100U
+#define SD0_OTAPDLYENA			    0x00000040U
+#define SD1_ITAPCHGWIN			    0x02000000U
+#define SD1_ITAPDLYENA			    0x01000000U
+#define SD1_OTAPDLYENA			    0x00400000U
+#define SD_OTAPDLYSEL_HS200_B0	    0x00000003U
+#define SD_OTAPDLYSEL_HS200_B2	    0x00000002U
+#define SD_ITAPDLYSEL_SD50		    0x00000014U
+#define SD_OTAPDLYSEL_SD50		    0x00000003U
+#define SD_ITAPDLYSEL_SD_DDR50	    0x0000003DU
+#define SD_ITAPDLYSEL_EMMC_DDR50    0x00000012U
+#define SD_OTAPDLYSEL_SD_DDR50	    0x00000004U
+#define SD_OTAPDLYSEL_EMMC_DDR50    0x00000006U
+#define SD_ITAPDLYSEL_HSD		    0x00000015U
+#define SD_OTAPDLYSEL_SD_HSD	    0x00000005U
+#define SD_OTAPDLYSEL_EMMC_HSD	    0x00000006U
 #endif
 
 #ifdef __MICROBLAZE__
-#define XPS_SYS_CTRL_BASEADDR	0xFF180000U
+#define XPS_SYS_CTRL_BASEADDR    0xFF180000U
 #endif
 
 /**************************** Type Definitions *******************************/
@@ -1113,99 +1113,99 @@ extern "C" {
 /**
 * Read a register.
 *
-* @param	InstancePtr is the pointer to the sdps instance.
-* @param	RegOffset contains the offset from the 1st register of the
-*		device to the target register.
+* @param    InstancePtr is the pointer to the sdps instance.
+* @param    RegOffset contains the offset from the 1st register of the
+*	    device to the target register.
 *
-* @return	The value read from the register.
+* @return    The value read from the register.
 *
-* @note		C-Style signature:
-*		u32 XSdPs_ReadReg(XSdPs *InstancePtr. s32 RegOffset)
+* @note	    C-Style signature:
+*	    u32 XSdPs_ReadReg(XSdPs *InstancePtr. s32 RegOffset)
 *
 ******************************************************************************/
 #define XSdPs_ReadReg64(InstancePtr, RegOffset) \
-	XSdPs_In64((InstancePtr->Config.BaseAddress) + RegOffset)
+    XSdPs_In64((InstancePtr->Config.BaseAddress) + RegOffset)
 
 /***************************************************************************/
 /**
 * Write to a register.
 *
-* @param	InstancePtr is the pointer to the sdps instance.
-* @param	RegOffset contains the offset from the 1st register of the
-*		device to target register.
-* @param	RegisterValue is the value to be written to the register.
+* @param    InstancePtr is the pointer to the sdps instance.
+* @param    RegOffset contains the offset from the 1st register of the
+*	    device to target register.
+* @param    RegisterValue is the value to be written to the register.
 *
-* @return	None.
+* @return    None.
 *
-* @note		C-Style signature:
-*		void XSdPs_WriteReg(XSdPs *InstancePtr, s32 RegOffset,
-*		u64 RegisterValue)
+* @note	    C-Style signature:
+*	    void XSdPs_WriteReg(XSdPs *InstancePtr, s32 RegOffset,
+*	    u64 RegisterValue)
 *
 ******************************************************************************/
 #define XSdPs_WriteReg64(InstancePtr, RegOffset, RegisterValue) \
-	XSdPs_Out64((InstancePtr->Config.BaseAddress) + (RegOffset), \
+    XSdPs_Out64((InstancePtr->Config.BaseAddress) + (RegOffset), \
 		(RegisterValue))
 
 /****************************************************************************/
 /**
 * Read a register.
 *
-* @param	BaseAddress contains the base address of the device.
-* @param	RegOffset contains the offset from the 1st register of the
-*		device to the target register.
+* @param    BaseAddress contains the base address of the device.
+* @param    RegOffset contains the offset from the 1st register of the
+*	    device to the target register.
 *
-* @return	The value read from the register.
+* @return    The value read from the register.
 *
-* @note		C-Style signature:
-*		u32 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
+* @note	    C-Style signature:
+*	    u32 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
 *
 ******************************************************************************/
 #define XSdPs_ReadReg(BaseAddress, RegOffset) \
-	XSdPs_In32((BaseAddress) + (RegOffset))
+    XSdPs_In32((BaseAddress) + (RegOffset))
 
 /***************************************************************************/
 /**
 * Write to a register.
 *
-* @param	BaseAddress contains the base address of the device.
-* @param	RegOffset contains the offset from the 1st register of the
-*		device to target register.
-* @param	RegisterValue is the value to be written to the register.
+* @param    BaseAddress contains the base address of the device.
+* @param    RegOffset contains the offset from the 1st register of the
+*	    device to target register.
+* @param    RegisterValue is the value to be written to the register.
 *
-* @return	None.
+* @return    None.
 *
-* @note		C-Style signature:
-*		void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
-*		u32 RegisterValue)
+* @note	    C-Style signature:
+*	    void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
+*	    u32 RegisterValue)
 *
 ******************************************************************************/
 #define XSdPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \
-	XSdPs_Out32((BaseAddress) + (RegOffset), (RegisterValue))
+    XSdPs_Out32((BaseAddress) + (RegOffset), (RegisterValue))
 
 /****************************************************************************/
 /**
 * Read a register.
 *
-* @param	BaseAddress contains the base address of the device.
-* @param	RegOffset contains the offset from the 1st register of the
-*		device to the target register.
+* @param    BaseAddress contains the base address of the device.
+* @param    RegOffset contains the offset from the 1st register of the
+*	    device to the target register.
 *
-* @return	The value read from the register.
+* @return    The value read from the register.
 *
-* @note		C-Style signature:
-*		u16 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
+* @note	    C-Style signature:
+*	    u16 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
 *
 ******************************************************************************/
 static INLINE u16 XSdPs_ReadReg16(u32 BaseAddress, u8 RegOffset)
 {
 #if defined (__MICROBLAZE__)
-	u32 Reg;
-	BaseAddress += RegOffset & 0xFC;
-	Reg = XSdPs_In32(BaseAddress);
-	Reg >>= ((RegOffset & 0x3)*8);
-	return (u16)Reg;
+    u32 Reg;
+    BaseAddress += RegOffset & 0xFC;
+    Reg = XSdPs_In32(BaseAddress);
+    Reg >>= ((RegOffset & 0x3)*8);
+    return (u16)Reg;
 #else
-	return XSdPs_In16((BaseAddress) + (RegOffset));
+    return XSdPs_In16((BaseAddress) + (RegOffset));
 #endif
 }
 
@@ -1213,30 +1213,30 @@ static INLINE u16 XSdPs_ReadReg16(u32 BaseAddress, u8 RegOffset)
 /**
 * Write to a register.
 *
-* @param	BaseAddress contains the base address of the device.
-* @param	RegOffset contains the offset from the 1st register of the
-*		device to target register.
-* @param	RegisterValue is the value to be written to the register.
+* @param    BaseAddress contains the base address of the device.
+* @param    RegOffset contains the offset from the 1st register of the
+*	    device to target register.
+* @param    RegisterValue is the value to be written to the register.
 *
-* @return	None.
+* @return    None.
 *
-* @note		C-Style signature:
-*		void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
-*		u16 RegisterValue)
+* @note	    C-Style signature:
+*	    void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
+*	    u16 RegisterValue)
 *
 ******************************************************************************/
 
 static INLINE void XSdPs_WriteReg16(u32 BaseAddress, u8 RegOffset, u16 RegisterValue)
 {
 #if defined (__MICROBLAZE__)
-	u32 Reg;
-	BaseAddress += RegOffset & 0xFC;
-	Reg = XSdPs_In32(BaseAddress);
-	Reg &= ~(0xFFFF<<((RegOffset & 0x3)*8));
-	Reg |= RegisterValue <<((RegOffset & 0x3)*8);
-	XSdPs_Out32(BaseAddress, Reg);
+    u32 Reg;
+    BaseAddress += RegOffset & 0xFC;
+    Reg = XSdPs_In32(BaseAddress);
+    Reg &= ~(0xFFFF<<((RegOffset & 0x3)*8));
+    Reg |= RegisterValue <<((RegOffset & 0x3)*8);
+    XSdPs_Out32(BaseAddress, Reg);
 #else
-	XSdPs_Out16((BaseAddress) + (RegOffset), (RegisterValue));
+    XSdPs_Out16((BaseAddress) + (RegOffset), (RegisterValue));
 #endif
 }
 
@@ -1244,72 +1244,72 @@ static INLINE void XSdPs_WriteReg16(u32 BaseAddress, u8 RegOffset, u16 RegisterV
 /**
 * Read a register.
 *
-* @param	BaseAddress contains the base address of the device.
-* @param	RegOffset contains the offset from the 1st register of the
-*		device to the target register.
+* @param    BaseAddress contains the base address of the device.
+* @param    RegOffset contains the offset from the 1st register of the
+*	    device to the target register.
 *
-* @return	The value read from the register.
+* @return    The value read from the register.
 *
-* @note		C-Style signature:
-*		u8 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
+* @note	    C-Style signature:
+*	    u8 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
 *
 ******************************************************************************/
 static INLINE u8 XSdPs_ReadReg8(u32 BaseAddress, u8 RegOffset)
 {
 #if defined (__MICROBLAZE__)
-	u32 Reg;
-	BaseAddress += RegOffset & 0xFC;
-	Reg = XSdPs_In32(BaseAddress);
-	Reg >>= ((RegOffset & 0x3)*8);
-	return (u8)Reg;
+    u32 Reg;
+    BaseAddress += RegOffset & 0xFC;
+    Reg = XSdPs_In32(BaseAddress);
+    Reg >>= ((RegOffset & 0x3)*8);
+    return (u8)Reg;
 #else
-	return XSdPs_In8((BaseAddress) + (RegOffset));
+    return XSdPs_In8((BaseAddress) + (RegOffset));
 #endif
 }
 /***************************************************************************/
 /**
 * Write to a register.
 *
-* @param	BaseAddress contains the base address of the device.
-* @param	RegOffset contains the offset from the 1st register of the
-*		device to target register.
-* @param	RegisterValue is the value to be written to the register.
+* @param    BaseAddress contains the base address of the device.
+* @param    RegOffset contains the offset from the 1st register of the
+*	    device to target register.
+* @param    RegisterValue is the value to be written to the register.
 *
-* @return	None.
+* @return    None.
 *
-* @note		C-Style signature:
-*		void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
-*		u8 RegisterValue)
+* @note	    C-Style signature:
+*	    void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
+*	    u8 RegisterValue)
 *
 ******************************************************************************/
 static INLINE void XSdPs_WriteReg8(u32 BaseAddress, u8 RegOffset, u8 RegisterValue)
 {
 #if defined (__MICROBLAZE__)
-	u32 Reg;
-	BaseAddress += RegOffset & 0xFC;
-	Reg = XSdPs_In32(BaseAddress);
-	Reg &= ~(0xFF<<((RegOffset & 0x3)*8));
-	Reg |= RegisterValue <<((RegOffset & 0x3)*8);
-	XSdPs_Out32(BaseAddress, Reg);
+    u32 Reg;
+    BaseAddress += RegOffset & 0xFC;
+    Reg = XSdPs_In32(BaseAddress);
+    Reg &= ~(0xFF<<((RegOffset & 0x3)*8));
+    Reg |= RegisterValue <<((RegOffset & 0x3)*8);
+    XSdPs_Out32(BaseAddress, Reg);
 #else
-	XSdPs_Out8((BaseAddress) + (RegOffset), (RegisterValue));
+    XSdPs_Out8((BaseAddress) + (RegOffset), (RegisterValue));
 #endif
 }
 /***************************************************************************/
 /**
 * Macro to get present status register
 *
-* @param	BaseAddress contains the base address of the device.
+* @param    BaseAddress contains the base address of the device.
 *
-* @return	None.
+* @return    None.
 *
-* @note		C-Style signature:
-*		void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
-*		u8 RegisterValue)
+* @note	    C-Style signature:
+*	    void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
+*	    u8 RegisterValue)
 *
 ******************************************************************************/
 #define XSdPs_GetPresentStatusReg(BaseAddress) \
-		XSdPs_In32((BaseAddress) + (XSDPS_PRES_STATE_OFFSET))
+	    XSdPs_In32((BaseAddress) + (XSDPS_PRES_STATE_OFFSET))
 
 /************************** Function Prototypes ******************************/
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c
index ecf28d3589..8fed55e9bd 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c
@@ -22,8 +22,8 @@
 * 2.1   hk     04/18/14 Increase sleep for eMMC switch command.
 *                       Add sleep for microblaze designs. CR# 781117.
 * 2.3   sk     09/23/14 Use XSdPs_Change_ClkFreq API whenever changing
-*						clock.CR# 816586.
-* 2.5 	sg	   07/09/15 Added SD 3.0 features
+*					    clock.CR# 816586.
+* 2.5     sg	   07/09/15 Added SD 3.0 features
 *       kvn    07/15/15 Modified the code according to MISRAC-2012.
 * 2.7   sk     01/08/16 Added workaround for issue in auto tuning mode
 *                       of SDR50, SDR104 and HS200.
@@ -43,8 +43,8 @@
 *       vns    03/13/17 Fixed MISRAC mandatory violation
 *       sk     03/20/17 Add support for EL1 non-secure mode.
 * 3.3   mn     07/25/17 Removed SD0_OTAPDLYENA and SD1_OTAPDLYENA bits
-*       mn     08/07/17	Properly set OTAPDLY value by clearing previous bit
-* 			settings
+*       mn     08/07/17    Properly set OTAPDLY value by clearing previous bit
+* 		    settings
 *       mn     08/17/17 Added CCI support for A53 and disabled data cache
 *                       operations when it is enabled.
 *       mn     08/22/17 Updated for Word Access System support
@@ -79,33 +79,33 @@
 * API to change clock freq to given value.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	SelFreq - Clock frequency in Hz.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    SelFreq - Clock frequency in Hz.
 *
-* @return	None
+* @return    None
 *
-* @note		This API will change clock frequency to the value less than
-*		or equal to the given value using the permissible dividors.
+* @note	    This API will change clock frequency to the value less than
+*	    or equal to the given value using the permissible dividors.
 *
 ******************************************************************************/
 s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
+    if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
 		/* Program the Tap delays */
-		XSdPs_SetTapDelay(InstancePtr);
+	    XSdPs_SetTapDelay(InstancePtr);
 	}
 
-	Status = XSdPs_SetClock(InstancePtr, SelFreq);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdPs_SetClock(InstancePtr, SelFreq);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -113,41 +113,41 @@ s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq)
 * @brief
 * Update Block size for read/write operations.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	BlkSize - Block size passed by the user.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    BlkSize - Block size passed by the user.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	Status = XSdPs_CheckBusIdle(InstancePtr, (XSDPS_PSR_INHIBIT_CMD_MASK
+    Status = XSdPs_CheckBusIdle(InstancePtr, (XSDPS_PSR_INHIBIT_CMD_MASK
 											| XSDPS_PSR_INHIBIT_DAT_MASK
 											| XSDPS_PSR_WR_ACTIVE_MASK
 											| XSDPS_PSR_RD_ACTIVE_MASK));
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH ;
 	}
 
 	/* Send block write command */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Set block size to the value passed */
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
 			 BlkSize & XSDPS_BLK_SIZE_MASK);
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -157,64 +157,64 @@ RETURN_PATH:
 * API to get bus width support by card.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	SCR - buffer to store SCR register returned by card.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    SCR - buffer to store SCR register returned by card.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if fail.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff)
 {
-	s32 Status;
-	u16 BlkCnt;
-	u16 BlkSize;
-	s32 LoopCnt;
+    s32 Status;
+    u16 BlkCnt;
+    u16 BlkSize;
+    s32 LoopCnt;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	for (LoopCnt = 0; LoopCnt < 8; LoopCnt++) {
-		ReadBuff[LoopCnt] = 0U;
+    for (LoopCnt = 0; LoopCnt < 8; LoopCnt++) {
+	    ReadBuff[LoopCnt] = 0U;
 	}
 
 	/* Send block write command */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
-			InstancePtr->RelCardAddr, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
+		    InstancePtr->RelCardAddr, 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	BlkCnt = XSDPS_SCR_BLKCNT;
-	BlkSize = XSDPS_SCR_BLKSIZE;
+    BlkCnt = XSDPS_SCR_BLKCNT;
+    BlkSize = XSDPS_SCR_BLKSIZE;
 
-	XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
+    XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
 
-	Status = XSdPs_CmdTransfer(InstancePtr, ACMD51, 0U, BlkCnt);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, ACMD51, 0U, BlkCnt);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+	    Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
 				(INTPTR)BlkCnt * BlkSize);
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+	    return Status;
 
 }
 
@@ -225,99 +225,99 @@ s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff)
 * API to set bus width to 4-bit in card and host
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if fail.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr)
 {
-	s32 Status;
-	u32 StatusReg;
-	u32 Arg;
+    s32 Status;
+    u32 StatusReg;
+    u32 Arg;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
 	/*
 	 * check for bus width for 3.0 controller and return if
 	 * bus width is <4
 	 */
-	if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
+    if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
 			(InstancePtr->Config.BusWidth < XSDPS_WIDTH_4)) {
-		Status = XST_SUCCESS;
-		goto RETURN_PATH;
+	    Status = XST_SUCCESS;
+	    goto RETURN_PATH;
 	}
 
-	if (InstancePtr->CardType == XSDPS_CARD_SD) {
+    if (InstancePtr->CardType == XSDPS_CARD_SD) {
 
-		Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr,
-				0U);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr,
+			    0U);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 
-		Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, (u32)InstancePtr->BusWidth, 0U);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, (u32)InstancePtr->BusWidth, 0U);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	} else {
-		if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
-			if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
-				Arg = XSDPS_MMC_DDR_8_BIT_BUS_ARG;
+	    if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
+		    if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
+			    Arg = XSDPS_MMC_DDR_8_BIT_BUS_ARG;
 			} else {
-				Arg = XSDPS_MMC_8_BIT_BUS_ARG;
+			    Arg = XSDPS_MMC_8_BIT_BUS_ARG;
 			}
 		} else {
-			if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
-				Arg = XSDPS_MMC_DDR_4_BIT_BUS_ARG;
+		    if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
+			    Arg = XSDPS_MMC_DDR_4_BIT_BUS_ARG;
 			} else {
-				Arg = XSDPS_MMC_4_BIT_BUS_ARG;
+			    Arg = XSDPS_MMC_4_BIT_BUS_ARG;
 			}
 		}
 
-		Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, Arg);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, Arg);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
+    usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
 
-	StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
-					XSDPS_HOST_CTRL1_OFFSET);
+    StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
+				    XSDPS_HOST_CTRL1_OFFSET);
 
 	/* Width setting in controller */
-	if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
-		StatusReg |= XSDPS_HC_EXT_BUS_WIDTH;
+    if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
+	    StatusReg |= XSDPS_HC_EXT_BUS_WIDTH;
 	} else {
-		StatusReg |= XSDPS_HC_WIDTH_MASK;
+	    StatusReg |= XSDPS_HC_WIDTH_MASK;
 	}
 
-	XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			XSDPS_HOST_CTRL1_OFFSET,
+    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+		    XSDPS_HOST_CTRL1_OFFSET,
 			(u8)StatusReg);
 
-	if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
-		StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_HOST_CTRL2_OFFSET);
-		StatusReg &= (u32)(~XSDPS_HC2_UHS_MODE_MASK);
-		StatusReg |= InstancePtr->Mode;
-		XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_HOST_CTRL2_OFFSET, (u16)StatusReg);
+    if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
+	    StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+				    XSDPS_HOST_CTRL2_OFFSET);
+	    StatusReg &= (u32)(~XSDPS_HC2_UHS_MODE_MASK);
+	    StatusReg |= InstancePtr->Mode;
+	    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+				    XSDPS_HOST_CTRL2_OFFSET, (u16)StatusReg);
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+	    return Status;
 
 }
 
@@ -328,60 +328,60 @@ s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr)
 * API to get bus speed supported by card.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	ReadBuff - buffer to store function group support data
-*		returned by card.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    ReadBuff - buffer to store function group support data
+*	    returned by card.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if fail.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
 {
-	s32 Status;
-	u32 Arg;
-	u16 BlkCnt;
-	u16 BlkSize;
-	s32 LoopCnt;
+    s32 Status;
+    u32 Arg;
+    u16 BlkCnt;
+    u16 BlkSize;
+    s32 LoopCnt;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	for (LoopCnt = 0; LoopCnt < 64; LoopCnt++) {
-		ReadBuff[LoopCnt] = 0U;
+    for (LoopCnt = 0; LoopCnt < 64; LoopCnt++) {
+	    ReadBuff[LoopCnt] = 0U;
 	}
 
-	BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
-	BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
+    BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
+    BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
 
-	XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
+    XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
 
-	Arg = XSDPS_SWITCH_CMD_HS_GET;
+    Arg = XSDPS_SWITCH_CMD_HS_GET;
 
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+	    Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
 				(INTPTR)BlkCnt * BlkSize);
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+	    return Status;
 
 }
 
@@ -392,59 +392,59 @@ s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
 * API to get SD card status information.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	SdStatReg - buffer to store status data returned by card.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    SdStatReg - buffer to store status data returned by card.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if fail.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg)
 {
-	s32 Status;
-	u16 BlkCnt;
-	u16 BlkSize;
+    s32 Status;
+    u16 BlkCnt;
+    u16 BlkSize;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
 	/* Send block write command */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
-			InstancePtr->RelCardAddr, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
+		    InstancePtr->RelCardAddr, 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	BlkCnt = XSDPS_SD_STATUS_BLKCNT;
-	BlkSize = XSDPS_SD_STATUS_BLKSIZE;
+    BlkCnt = XSDPS_SD_STATUS_BLKCNT;
+    BlkSize = XSDPS_SD_STATUS_BLKSIZE;
 
-	XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, SdStatReg);
+    XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, SdStatReg);
 
-	Status = XSdPs_CmdTransfer(InstancePtr, ACMD13, 0U, BlkCnt);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, ACMD13, 0U, BlkCnt);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheInvalidateRange((INTPTR)SdStatReg,
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+	    Xil_DCacheInvalidateRange((INTPTR)SdStatReg,
 				(INTPTR)BlkCnt * BlkSize);
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+	    return Status;
 }
 
 /*****************************************************************************/
@@ -454,65 +454,65 @@ s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg)
 * API to set high speed in card and host. Changes clock in host accordingly.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if fail.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
 {
-	s32 Status;
-	u32 StatusReg;
+    s32 Status;
+    u32 StatusReg;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		Status = XSdPs_Change_SdBusSpeed(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+	    Status = XSdPs_Change_SdBusSpeed(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	} else {
-		Status = XSdPs_Change_MmcBusSpeed(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_Change_MmcBusSpeed(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	if ((InstancePtr->Mode == XSDPS_HS200_MODE) ||
+    if ((InstancePtr->Mode == XSDPS_HS200_MODE) ||
 		(InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR104) ||
 		(InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR50)) {
-		Status = XSdPs_Execute_Tuning(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
+	    Status = XSdPs_Execute_Tuning(InstancePtr);
+	    if (Status != XST_SUCCESS) {
+		    Status = XST_FAILURE;
+		    goto RETURN_PATH;
 		}
 	}
 
-	usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
+    usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
 
-	StatusReg = (u32)XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
-					XSDPS_HOST_CTRL1_OFFSET);
-	StatusReg |= XSDPS_HC_SPEED_MASK;
-	XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			XSDPS_HOST_CTRL1_OFFSET, (u8)StatusReg);
+    StatusReg = (u32)XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
+				    XSDPS_HOST_CTRL1_OFFSET);
+    StatusReg |= XSDPS_HC_SPEED_MASK;
+    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+		    XSDPS_HOST_CTRL1_OFFSET, (u8)StatusReg);
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+	    return Status;
 
 }
 
@@ -523,58 +523,58 @@ s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
 * API to get EXT_CSD register of eMMC.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	ReadBuff - buffer to store EXT_CSD
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    ReadBuff - buffer to store EXT_CSD
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if fail.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
 {
-	s32 Status;
-	u32 Arg = 0U;
-	u16 BlkCnt;
-	u16 BlkSize;
-	s32 LoopCnt;
+    s32 Status;
+    u32 Arg = 0U;
+    u16 BlkCnt;
+    u16 BlkSize;
+    s32 LoopCnt;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	for (LoopCnt = 0; LoopCnt < 512; LoopCnt++) {
-		ReadBuff[LoopCnt] = 0U;
+    for (LoopCnt = 0; LoopCnt < 512; LoopCnt++) {
+	    ReadBuff[LoopCnt] = 0U;
 	}
 
-	BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT;
-	BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE;
+    BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT;
+    BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE;
 
-	XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
+    XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
 
 	/* Send SEND_EXT_CSD command */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+	    Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
 				(INTPTR)BlkCnt * BlkSize);
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+	    return Status;
 
 }
 
@@ -585,39 +585,39 @@ s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
 * API to write EXT_CSD register of eMMC.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	Arg is the argument to be sent along with the command
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    Arg is the argument to be sent along with the command
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if fail.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
 	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+	    return Status;
 
 }
 
@@ -628,39 +628,39 @@ s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg)
 * API to send pullup command to card before using DAT line 3(using 4-bit bus)
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if fail.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 s32 XSdPs_Pullup(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
-			InstancePtr->RelCardAddr, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
+		    InstancePtr->RelCardAddr, 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0U, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
+    Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0U, 0U);
+    if (Status != XST_SUCCESS) {
+	    Status = XST_FAILURE;
+	    goto RETURN_PATH;
 	}
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+	    return Status;
 
 }
 
@@ -671,28 +671,28 @@ s32 XSdPs_Pullup(XSdPs *InstancePtr)
 * Selects card and sets default block size
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if fail.
 *		- XSDPS_CT_ERROR if Command Transfer fail.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 s32 XSdPs_Select_Card (XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
 	/* Send CMD7 - Select card */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD7,
-			InstancePtr->RelCardAddr, 0U);
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD7,
+		    InstancePtr->RelCardAddr, 0U);
 
-	return Status;
+    return Status;
 }
 
 /** @} */
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c
index cf5708a864..3af50efa07 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c
@@ -48,28 +48,28 @@ extern XSdPs_Config XSdPs_ConfigTable[XPAR_XSDPS_NUM_INSTANCES];
 * Looks up the device configuration based on the unique device ID. A table
 * contains the configuration info for each device in the system.
 *
-* @param	DeviceId contains the ID of the device to look up the
-*		configuration for.
+* @param    DeviceId contains the ID of the device to look up the
+*	    configuration for.
 *
 * @return
 *
 * A pointer to the configuration found or NULL if the specified device ID was
 * not found. See xsdps.h for the definition of XSdPs_Config.
 *
-* @note		None.
+* @note	    None.
 *
 ******************************************************************************/
 XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId)
 {
-	XSdPs_Config *CfgPtr = NULL;
-	u32 Index;
+    XSdPs_Config *CfgPtr = NULL;
+    u32 Index;
 
-	for (Index = 0U; Index < (u32)XPAR_XSDPS_NUM_INSTANCES; Index++) {
-		if (XSdPs_ConfigTable[Index].DeviceId == DeviceId) {
-			CfgPtr = &XSdPs_ConfigTable[Index];
-			break;
+    for (Index = 0U; Index < (u32)XPAR_XSDPS_NUM_INSTANCES; Index++) {
+	    if (XSdPs_ConfigTable[Index].DeviceId == DeviceId) {
+		    CfgPtr = &XSdPs_ConfigTable[Index];
+		    break;
 		}
 	}
-	return (XSdPs_Config *)CfgPtr;
+    return (XSdPs_Config *)CfgPtr;
 }
 /** @} */
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h
index eca569e5b4..7e8c778295 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h
@@ -13,15 +13,15 @@ extern "C" {
 
 static inline void usleep(unsigned long useconds)
 {
-	rt_uint32_t milliseconds = useconds/1000;
-	useconds = useconds%1000;
-	if (milliseconds) rt_thread_mdelay(milliseconds);
-	if (useconds) rt_hw_us_delay(useconds);
+    rt_uint32_t milliseconds = useconds/1000;
+    useconds = useconds%1000;
+    if (milliseconds) rt_thread_mdelay(milliseconds);
+    if (useconds) rt_hw_us_delay(useconds);
 }
 
 static inline void sleep(unsigned int seconds)
 {
-	rt_thread_delay(seconds*RT_TICK_PER_SECOND);
+    rt_thread_delay(seconds*RT_TICK_PER_SECOND);
 }
 
 #ifdef __cplusplus
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h
index aaff03e647..fc5767d3e9 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h
@@ -52,34 +52,34 @@ extern "C" {
 #include 
 
 struct xemac_s {
-	enum xemac_types type;
-	int  topology_index;
-	void *state;
+    enum xemac_types type;
+    int  topology_index;
+    void *state;
 #if 0
     sys_sem_t sem_rx_data_available;
 #else
-	struct eth_device *rt_eth_device;
+    struct eth_device *rt_eth_device;
 #endif
 #if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
-	TimerHandle_t xTimer;
+    TimerHandle_t xTimer;
 #endif
 };
 
 enum ethernet_link_status {
-	ETH_LINK_UNDEFINED = 0,
-	ETH_LINK_UP,
-	ETH_LINK_DOWN,
-	ETH_LINK_NEGOTIATING
+    ETH_LINK_UNDEFINED = 0,
+    ETH_LINK_UP,
+    ETH_LINK_DOWN,
+    ETH_LINK_NEGOTIATING
 };
 
 void eth_link_detect(struct netif *netif);
-void 		lwip_raw_init();
-int 		xemacif_input(struct netif *netif);
-void 		xemacif_input_thread(struct netif *netif);
-struct netif *	xemac_add(struct netif *netif,
-	ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw,
-	unsigned char *mac_ethernet_address,
-	unsigned mac_baseaddr);
+void 	    lwip_raw_init();
+int 	    xemacif_input(struct netif *netif);
+void 	    xemacif_input_thread(struct netif *netif);
+struct netif *    xemac_add(struct netif *netif,
+    ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw,
+    unsigned char *mac_ethernet_address,
+    unsigned mac_baseaddr);
 #if defined (__arm__) || defined (__aarch64__)
 void xemacpsif_resetrx_on_no_rxdata(struct netif *netif);
 #endif
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h
index 796cdd7f66..da23a43d80 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h
@@ -72,24 +72,24 @@ extern "C" {
 #define ZYNQMP_EMACPS_2_BASEADDR 0xFF0D0000
 #define ZYNQMP_EMACPS_3_BASEADDR 0xFF0E0000
 
-#define CRL_APB_GEM0_REF_CTRL	0xFF5E0050
-#define CRL_APB_GEM1_REF_CTRL	0xFF5E0054
-#define CRL_APB_GEM2_REF_CTRL	0xFF5E0058
-#define CRL_APB_GEM3_REF_CTRL	0xFF5E005C
+#define CRL_APB_GEM0_REF_CTRL    0xFF5E0050
+#define CRL_APB_GEM1_REF_CTRL    0xFF5E0054
+#define CRL_APB_GEM2_REF_CTRL    0xFF5E0058
+#define CRL_APB_GEM3_REF_CTRL    0xFF5E005C
 
-#define CRL_APB_GEM_DIV0_MASK	0x00003F00
-#define CRL_APB_GEM_DIV0_SHIFT	8
-#define CRL_APB_GEM_DIV1_MASK	0x003F0000
-#define CRL_APB_GEM_DIV1_SHIFT	16
+#define CRL_APB_GEM_DIV0_MASK    0x00003F00
+#define CRL_APB_GEM_DIV0_SHIFT    8
+#define CRL_APB_GEM_DIV1_MASK    0x003F0000
+#define CRL_APB_GEM_DIV1_SHIFT    16
 
 #define VERSAL_EMACPS_0_BASEADDR 0xFF0C0000
 #define VERSAL_EMACPS_1_BASEADDR 0xFF0D0000
 
-#define VERSAL_CRL_GEM0_REF_CTRL	0xFF5E0118
-#define VERSAL_CRL_GEM1_REF_CTRL	0xFF5E011C
+#define VERSAL_CRL_GEM0_REF_CTRL    0xFF5E0118
+#define VERSAL_CRL_GEM1_REF_CTRL    0xFF5E011C
 
-#define VERSAL_CRL_GEM_DIV_MASK		0x0003FF00
-#define VERSAL_CRL_APB_GEM_DIV_SHIFT	8
+#define VERSAL_CRL_GEM_DIV_MASK	    0x0003FF00
+#define VERSAL_CRL_APB_GEM_DIV_SHIFT    8
 
 #if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (__MICROBLAZE__)
 #if defined (USE_JUMBO_FRAMES)
@@ -97,40 +97,40 @@ extern "C" {
 #endif
 #endif
 
-#define GEM_VERSION_ZYNQMP	7
-#define GEM_VERSION_VERSAL	0x107
+#define GEM_VERSION_ZYNQMP    7
+#define GEM_VERSION_VERSAL    0x107
 
 #define MAX_FRAME_SIZE_JUMBO (XEMACPS_MTU_JUMBO + XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE)
 
-void 	xemacpsif_setmac(u32_t index, u8_t *addr);
-u8_t*	xemacpsif_getmac(u32_t index);
-err_t 	xemacpsif_init(struct netif *netif);
-s32_t 	xemacpsif_input(struct netif *netif);
+void     xemacpsif_setmac(u32_t index, u8_t *addr);
+u8_t*    xemacpsif_getmac(u32_t index);
+err_t     xemacpsif_init(struct netif *netif);
+s32_t     xemacpsif_input(struct netif *netif);
 
 /* xaxiemacif_hw.c */
-void 	xemacps_error_handler(XEmacPs * Temac);
+void     xemacps_error_handler(XEmacPs * Temac);
 
 /* structure within each netif, encapsulating all information required for
  * using a particular temac instance
  */
 typedef struct {
-	XEmacPs emacps;
+    XEmacPs emacps;
 
 	/* queue to store overflow packets */
-	pq_queue_t *recv_q;
-	pq_queue_t *send_q;
+    pq_queue_t *recv_q;
+    pq_queue_t *send_q;
 
 	/* pointers to memory holding buffer descriptors (used only with SDMA) */
-	void *rx_bdspace;
-	void *tx_bdspace;
+    void *rx_bdspace;
+    void *tx_bdspace;
 
-	unsigned int last_rx_frms_cntr;
+    unsigned int last_rx_frms_cntr;
 
 } xemacpsif_s;
 
 extern xemacpsif_s xemacpsif;
 
-s32_t	is_tx_space_available(xemacpsif_s *emac);
+s32_t    is_tx_space_available(xemacpsif_s *emac);
 
 /* xemacpsif_dma.c */
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h
index 132f02fb38..69f2c94ef8 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h
@@ -38,14 +38,14 @@ extern "C" {
 #define PQ_QUEUE_SIZE 4096
 
 typedef struct {
-	void *data[PQ_QUEUE_SIZE];
-	int head, tail, len;
+    void *data[PQ_QUEUE_SIZE];
+    int head, tail, len;
 } pq_queue_t;
 
-pq_queue_t*	pq_create_queue();
-int 		pq_enqueue(pq_queue_t *q, void *p);
-void*		pq_dequeue(pq_queue_t *q);
-int		pq_qlength(pq_queue_t *q);
+pq_queue_t*    pq_create_queue();
+int 	    pq_enqueue(pq_queue_t *q, void *p);
+void*	    pq_dequeue(pq_queue_t *q);
+int	    pq_qlength(pq_queue_t *q);
 
 #ifdef __cplusplus
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h
index f3474cba7c..b1a912fc62 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h
@@ -38,12 +38,12 @@ extern "C" {
 enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };
 
 struct xtopology_t {
-	unsigned emac_baseaddr;
-	enum xemac_types emac_type;
-	unsigned intc_baseaddr;
-	unsigned intc_emac_intr;	/* valid only for xemac_type_xps_emaclite */
-	unsigned scugic_baseaddr; /* valid only for Zynq */
-	unsigned scugic_emac_intr; /* valid only for GEM */
+    unsigned emac_baseaddr;
+    enum xemac_types emac_type;
+    unsigned intc_baseaddr;
+    unsigned intc_emac_intr;	/* valid only for xemac_type_xps_emaclite */
+    unsigned scugic_baseaddr; /* valid only for Zynq */
+    unsigned scugic_emac_intr; /* valid only for GEM */
 };
 
 extern int xtopology_n_emacs;
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c
index a9ed329d58..47f30b756c 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c
@@ -83,12 +83,12 @@ u32_t phyaddrforemac;
 void
 lwip_raw_init()
 {
-	ip_init();	/* Doesn't do much, it should be called to handle future changes. */
+    ip_init();	/* Doesn't do much, it should be called to handle future changes. */
 #if LWIP_UDP
-	udp_init();	/* Clears the UDP PCB list. */
+    udp_init();	/* Clears the UDP PCB list. */
 #endif
 #if LWIP_TCP
-	tcp_init();	/* Clears the TCP PCB list and clears some internal TCP timers. */
+    tcp_init();	/* Clears the TCP PCB list and clears some internal TCP timers. */
 			/* Note: you must call tcp_fasttmr() and tcp_slowtmr() at the */
 			/* predefined regular intervals after this initialization. */
 #endif
@@ -97,27 +97,27 @@ lwip_raw_init()
 static enum xemac_types
 find_mac_type(unsigned base)
 {
-	int i;
+    int i;
 
-	for (i = 0; i < xtopology_n_emacs; i++) {
-		if (xtopology[i].emac_baseaddr == base)
-			return xtopology[i].emac_type;
+    for (i = 0; i < xtopology_n_emacs; i++) {
+	    if (xtopology[i].emac_baseaddr == base)
+		    return xtopology[i].emac_type;
 	}
 
-	return xemac_type_unknown;
+    return xemac_type_unknown;
 }
 
 int
 xtopology_find_index(unsigned base)
 {
-	int i;
+    int i;
 
-	for (i = 0; i < xtopology_n_emacs; i++) {
-		if (xtopology[i].emac_baseaddr == base)
-			return i;
+    for (i = 0; i < xtopology_n_emacs; i++) {
+	    if (xtopology[i].emac_baseaddr == base)
+		    return i;
 	}
 
-	return -1;
+    return -1;
 }
 
 /*
@@ -128,72 +128,72 @@ xtopology_find_index(unsigned base)
  */
 struct netif *
 xemac_add(struct netif *netif,
-	ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw,
-	unsigned char *mac_ethernet_address,
-	unsigned mac_baseaddr)
+    ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw,
+    unsigned char *mac_ethernet_address,
+    unsigned mac_baseaddr)
 {
-	int i;
+    int i;
 
 #ifdef OS_IS_FREERTOS
 	/* Start thread to detect link periodically for Hot Plug autodetect */
-	sys_thread_new("link_detect_thread", link_detect_thread, netif,
-			THREAD_STACKSIZE, tskIDLE_PRIORITY);
+    sys_thread_new("link_detect_thread", link_detect_thread, netif,
+		    THREAD_STACKSIZE, tskIDLE_PRIORITY);
 #endif
 
 	/* set mac address */
-	netif->hwaddr_len = 6;
-	for (i = 0; i < 6; i++)
-		netif->hwaddr[i] = mac_ethernet_address[i];
+    netif->hwaddr_len = 6;
+    for (i = 0; i < 6; i++)
+	    netif->hwaddr[i] = mac_ethernet_address[i];
 
 	/* initialize based on MAC type */
-		switch (find_mac_type(mac_baseaddr)) {
-			case xemac_type_xps_emaclite:
+	    switch (find_mac_type(mac_baseaddr)) {
+		    case xemac_type_xps_emaclite:
 #ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
-				return netif_add(netif, ipaddr, netmask, gw,
+			    return netif_add(netif, ipaddr, netmask, gw,
 					(void*)(UINTPTR)mac_baseaddr,
-					xemacliteif_init,
+				    xemacliteif_init,
 #if NO_SYS
-					ethernet_input
+				    ethernet_input
 #else
-					tcpip_input
+				    tcpip_input
 #endif
 					);
 #else
-				return NULL;
+			    return NULL;
 #endif
-			case xemac_type_axi_ethernet:
+		    case xemac_type_axi_ethernet:
 #ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
-				return netif_add(netif, ipaddr, netmask, gw,
+			    return netif_add(netif, ipaddr, netmask, gw,
 					(void*)(UINTPTR)mac_baseaddr,
-					xaxiemacif_init,
+				    xaxiemacif_init,
 #if NO_SYS
-					ethernet_input
+				    ethernet_input
 #else
-					tcpip_input
+				    tcpip_input
 #endif
 					);
 #else
-				return NULL;
+			    return NULL;
 #endif
 #if defined (__arm__) || defined (__aarch64__)
-			case xemac_type_emacps:
+		    case xemac_type_emacps:
 #ifdef XLWIP_CONFIG_INCLUDE_GEM
-				return netif_add(netif, ipaddr, netmask, gw,
+			    return netif_add(netif, ipaddr, netmask, gw,
 						(void*)(UINTPTR)mac_baseaddr,
-						xemacpsif_init,
+					    xemacpsif_init,
 #if NO_SYS
-						ethernet_input
+					    ethernet_input
 #else
-						tcpip_input
+					    tcpip_input
 #endif
 
 						);
 #endif
 #endif
-			default:
-				xil_printf("unable to determine type of EMAC with baseaddress 0x%08x\r\n",
-						mac_baseaddr);
-				return NULL;
+		    default:
+			    xil_printf("unable to determine type of EMAC with baseaddress 0x%08x\r\n",
+					    mac_baseaddr);
+			    return NULL;
 	}
 }
 
@@ -206,16 +206,16 @@ xemac_add(struct netif *netif,
 void
 xemacif_input_thread(struct netif *netif)
 {
-	struct xemac_s *emac = (struct xemac_s *)netif->state;
-	while (1) {
+    struct xemac_s *emac = (struct xemac_s *)netif->state;
+    while (1) {
 		/* sleep until there are packets to process
 		 * This semaphore is set by the packet receive interrupt
 		 * routine.
 		 */
-		sys_sem_wait(&emac->sem_rx_data_available);
+	    sys_sem_wait(&emac->sem_rx_data_available);
 
 		/* move all received packets to lwIP */
-		xemacif_input(netif);
+	    xemacif_input(netif);
 	}
 }
 #endif
@@ -223,210 +223,210 @@ xemacif_input_thread(struct netif *netif)
 int
 xemacif_input(struct netif *netif)
 {
-	struct xemac_s *emac = (struct xemac_s *)netif->state;
+    struct xemac_s *emac = (struct xemac_s *)netif->state;
 
-	int n_packets = 0;
+    int n_packets = 0;
 
-	switch (emac->type) {
-		case xemac_type_xps_emaclite:
+    switch (emac->type) {
+	    case xemac_type_xps_emaclite:
 #ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
-			n_packets = xemacliteif_input(netif);
-			break;
+		    n_packets = xemacliteif_input(netif);
+		    break;
 #else
 			// print("incorrect configuration: xps_ethernetlite drivers not present?");
-			while(1);
-			return 0;
+		    while(1);
+		    return 0;
 #endif
-		case xemac_type_axi_ethernet:
+	    case xemac_type_axi_ethernet:
 #ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
-			n_packets = xaxiemacif_input(netif);
-			break;
+		    n_packets = xaxiemacif_input(netif);
+		    break;
 #else
 			// print("incorrect configuration: axi_ethernet drivers not present?");
-			while(1);
-			return 0;
+		    while(1);
+		    return 0;
 #endif
 #if defined (__arm__) || defined (__aarch64__)
-		case xemac_type_emacps:
+	    case xemac_type_emacps:
 #ifdef XLWIP_CONFIG_INCLUDE_GEM
-			n_packets = xemacpsif_input(netif);
-			break;
+		    n_packets = xemacpsif_input(netif);
+		    break;
 #else
-			xil_printf("incorrect configuration: ps7_ethernet drivers not present?\r\n");
-			while(1);
-			return 0;
+		    xil_printf("incorrect configuration: ps7_ethernet drivers not present?\r\n");
+		    while(1);
+		    return 0;
 #endif
 #endif
-		default:
+	    default:
 			// print("incorrect configuration: unknown temac type");
-			while(1);
-			return 0;
+		    while(1);
+		    return 0;
 	}
 
-	return n_packets;
+    return n_packets;
 }
 
 #if defined(XLWIP_CONFIG_INCLUDE_GEM)
 u32_t phy_link_detect(XEmacPs *xemacp, u32_t phy_addr)
 {
-	u16_t status;
+    u16_t status;
 
 	/* Read Phy Status register twice to get the confirmation of the current
 	 * link status.
 	 */
-	XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-	XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
-	if (status & IEEE_STAT_LINK_STATUS)
-		return 1;
-	return 0;
+    if (status & IEEE_STAT_LINK_STATUS)
+	    return 1;
+    return 0;
 }
 #elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
 static u32_t phy_link_detect(XAxiEthernet *xemacp, u32_t phy_addr)
 {
-	u16_t status;
+    u16_t status;
 
 	/* Read Phy Status register twice to get the confirmation of the current
 	 * link status.
 	 */
-	XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-	XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
-	if (status & IEEE_STAT_LINK_STATUS)
-		return 1;
-	return 0;
+    if (status & IEEE_STAT_LINK_STATUS)
+	    return 1;
+    return 0;
 }
 #elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
 static u32_t phy_link_detect(XEmacLite *xemacp, u32_t phy_addr)
 {
-	u16_t status;
+    u16_t status;
 
 	/* Read Phy Status register twice to get the confirmation of the current
 	 * link status.
 	 */
-	XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-	XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
-	if (status & IEEE_STAT_LINK_STATUS)
-		return 1;
-	return 0;
+    if (status & IEEE_STAT_LINK_STATUS)
+	    return 1;
+    return 0;
 }
 #endif
 
 #if defined(XLWIP_CONFIG_INCLUDE_GEM)
 u32_t phy_autoneg_status(XEmacPs *xemacp, u32_t phy_addr)
 {
-	u16_t status;
+    u16_t status;
 
 	/* Read Phy Status register twice to get the confirmation of the current
 	 * link status.
 	 */
-	XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-	XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
-	if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
-		return 1;
-	return 0;
+    if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
+	    return 1;
+    return 0;
 }
 #elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
 static u32_t phy_autoneg_status(XAxiEthernet *xemacp, u32_t phy_addr)
 {
-	u16_t status;
+    u16_t status;
 
 	/* Read Phy Status register twice to get the confirmation of the current
 	 * link status.
 	 */
-	XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-	XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
-	if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
-		return 1;
-	return 0;
+    if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
+	    return 1;
+    return 0;
 }
 #elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
 static u32_t phy_autoneg_status(XEmacLite *xemacp, u32_t phy_addr)
 {
-	u16_t status;
+    u16_t status;
 
 	/* Read Phy Status register twice to get the confirmation of the current
 	 * link status.
 	 */
-	XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-	XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
-	if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
-		return 1;
-	return 0;
+    if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
+	    return 1;
+    return 0;
 }
 #endif
 
 void eth_link_detect(struct netif *netif)
 {
-	u32_t link_speed, phy_link_status;
-	struct xemac_s *xemac = (struct xemac_s *)(netif->state);
+    u32_t link_speed, phy_link_status;
+    struct xemac_s *xemac = (struct xemac_s *)(netif->state);
 
 #if defined(XLWIP_CONFIG_INCLUDE_GEM)
-	xemacpsif_s *xemacs = (xemacpsif_s *)(xemac->state);
-	XEmacPs *xemacp = &xemacs->emacps;
+    xemacpsif_s *xemacs = (xemacpsif_s *)(xemac->state);
+    XEmacPs *xemacp = &xemacs->emacps;
 #elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
-	xaxiemacif_s *xemacs = (xaxiemacif_s *)(xemac->state);
-	XAxiEthernet *xemacp = &xemacs->axi_ethernet;
+    xaxiemacif_s *xemacs = (xaxiemacif_s *)(xemac->state);
+    XAxiEthernet *xemacp = &xemacs->axi_ethernet;
 #elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
-	xemacliteif_s *xemacs = (xemacliteif_s *)(xemac->state);
-	XEmacLite *xemacp = xemacs->instance;
+    xemacliteif_s *xemacs = (xemacliteif_s *)(xemac->state);
+    XEmacLite *xemacp = xemacs->instance;
 #endif
 
-	if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) ||
+    if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) ||
 			(eth_link_status == ETH_LINK_UNDEFINED))
-		return;
+	    return;
 
-	phy_link_status = phy_link_detect(xemacp, phyaddrforemac);
+    phy_link_status = phy_link_detect(xemacp, phyaddrforemac);
 
-	if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status))
-		eth_link_status = ETH_LINK_DOWN;
+    if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status))
+	    eth_link_status = ETH_LINK_DOWN;
 
-	switch (eth_link_status) {
-		case ETH_LINK_UNDEFINED:
-		case ETH_LINK_UP:
-			return;
-		case ETH_LINK_DOWN:
-			netif_set_link_down(netif);
-			eth_link_status = ETH_LINK_NEGOTIATING;
-			xil_printf("Ethernet Link down\r\n");
-			break;
-		case ETH_LINK_NEGOTIATING:
-			if (phy_link_status &&
-				phy_autoneg_status(xemacp, phyaddrforemac)) {
+    switch (eth_link_status) {
+	    case ETH_LINK_UNDEFINED:
+	    case ETH_LINK_UP:
+		    return;
+	    case ETH_LINK_DOWN:
+		    netif_set_link_down(netif);
+		    eth_link_status = ETH_LINK_NEGOTIATING;
+		    xil_printf("Ethernet Link down\r\n");
+		    break;
+	    case ETH_LINK_NEGOTIATING:
+		    if (phy_link_status &&
+			    phy_autoneg_status(xemacp, phyaddrforemac)) {
 
 				/* Initiate Phy setup to get link speed */
 #if defined(XLWIP_CONFIG_INCLUDE_GEM)
-				link_speed = phy_setup_emacps(xemacp,
-								phyaddrforemac);
-				XEmacPs_SetOperatingSpeed(xemacp, link_speed);
+			    link_speed = phy_setup_emacps(xemacp,
+							    phyaddrforemac);
+			    XEmacPs_SetOperatingSpeed(xemacp, link_speed);
 #elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
-				link_speed = phy_setup_axiemac(xemacp);
-				XAxiEthernet_SetOperatingSpeed(xemacp,
+			    link_speed = phy_setup_axiemac(xemacp);
+			    XAxiEthernet_SetOperatingSpeed(xemacp,
 							       link_speed);
 #endif
-				netif_set_link_up(netif);
-				eth_link_status = ETH_LINK_UP;
-				xil_printf("Ethernet Link up\r\n");
+			    netif_set_link_up(netif);
+			    eth_link_status = ETH_LINK_UP;
+			    xil_printf("Ethernet Link up\r\n");
 			}
-			break;
+		    break;
 	}
 }
 
 #ifdef OS_IS_FREERTOS
 void link_detect_thread(void *p)
 {
-	struct netif *netif = (struct netif *) p;
+    struct netif *netif = (struct netif *) p;
 
-	while (1) {
+    while (1) {
 		/* Call eth_link_detect() every second to detect Ethernet link
 		 * change.
 		 */
-		eth_link_detect(netif);
-		vTaskDelay(LINK_DETECT_THREAD_INTERVAL / portTICK_RATE_MS);
+	    eth_link_detect(netif);
+	    vTaskDelay(LINK_DETECT_THREAD_INTERVAL / portTICK_RATE_MS);
 	}
 }
 #endif
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h
index 4c240a9b7c..1134b9ca65 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h
@@ -44,7 +44,7 @@
 
 
 #define ADVERTISE_100_AND_10        (ADVERTISE_10FULL | ADVERTISE_100FULL | \
-					ADVERTISE_10HALF | ADVERTISE_100HALF)
+				    ADVERTISE_10HALF | ADVERTISE_100HALF)
 #define ADVERTISE_100               (ADVERTISE_100FULL | ADVERTISE_100HALF)
 #define ADVERTISE_10                (ADVERTISE_10FULL | ADVERTISE_10HALF)
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c
index d2aeaba3da..53df044cd5 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c
@@ -76,14 +76,14 @@
 
 #if LWIP_IGMP
 static err_t xemacpsif_mac_filter_update (struct netif *netif,
-							ip_addr_t *group, u8_t action);
+						    ip_addr_t *group, u8_t action);
 
 static u8_t xemacps_mcast_entry_mask = 0;
 #endif
 
 #if LWIP_IPV6 && LWIP_IPV6_MLD
 static err_t xemacpsif_mld6_mac_filter_update (struct netif *netif,
-							ip_addr_t *group, u8_t action);
+						    ip_addr_t *group, u8_t action);
 
 static u8_t xemacps_mld6_mcast_entry_mask;
 #endif
@@ -101,29 +101,29 @@ int32_t lExpireCounter = 0;
  * this function also assumes that there are available BD's
  */
 err_t _unbuffered_low_level_output(xemacpsif_s *xemacpsif,
-													struct pbuf *p)
+												    struct pbuf *p)
 {
-	XStatus status = 0;
+    XStatus status = 0;
 
 #if ETH_PAD_SIZE
-	pbuf_header(p, -ETH_PAD_SIZE);	/* drop the padding word */
+    pbuf_header(p, -ETH_PAD_SIZE);	/* drop the padding word */
 #endif
-	status = emacps_sgsend(xemacpsif, p);
-	if (status != XST_SUCCESS) {
+    status = emacps_sgsend(xemacpsif, p);
+    if (status != XST_SUCCESS) {
 #if LINK_STATS
-	lwip_stats.link.drop++;
+    lwip_stats.link.drop++;
 #endif
 	}
 
 #if ETH_PAD_SIZE
-	pbuf_header(p, ETH_PAD_SIZE);	/* reclaim the padding word */
+    pbuf_header(p, ETH_PAD_SIZE);	/* reclaim the padding word */
 #endif
 
 #if LINK_STATS
-	lwip_stats.link.xmit++;
+    lwip_stats.link.xmit++;
 #endif /* LINK_STATS */
 
-	return ERR_OK;
+    return ERR_OK;
 
 }
 
@@ -138,36 +138,36 @@ err_t _unbuffered_low_level_output(xemacpsif_s *xemacpsif,
 
 static err_t low_level_output(struct netif *netif, struct pbuf *p)
 {
-	SYS_ARCH_DECL_PROTECT(lev);
+    SYS_ARCH_DECL_PROTECT(lev);
     err_t err;
     s32_t freecnt;
     XEmacPs_BdRing *txring;
 
-	struct xemac_s *xemac = (struct xemac_s *)(netif->state);
-	xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+    struct xemac_s *xemac = (struct xemac_s *)(netif->state);
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
 
-	SYS_ARCH_PROTECT(lev);
+    SYS_ARCH_PROTECT(lev);
 
 	/* check if space is available to send */
     freecnt = is_tx_space_available(xemacpsif);
     if (freecnt <= 5) {
-	txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
-		process_sent_bds(xemacpsif, txring);
+    txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+	    process_sent_bds(xemacpsif, txring);
 	}
 
     if (is_tx_space_available(xemacpsif)) {
-		_unbuffered_low_level_output(xemacpsif, p);
-		err = ERR_OK;
+	    _unbuffered_low_level_output(xemacpsif, p);
+	    err = ERR_OK;
 	} else {
 #if LINK_STATS
-		lwip_stats.link.drop++;
+	    lwip_stats.link.drop++;
 #endif
-		rt_kprintf("pack dropped, no space\r\n");
-		err = ERR_MEM;
+	    rt_kprintf("pack dropped, no space\r\n");
+	    err = ERR_MEM;
 	}
 
-	SYS_ARCH_UNPROTECT(lev);
-	return err;
+    SYS_ARCH_UNPROTECT(lev);
+    return err;
 }
 
 /*
@@ -179,17 +179,17 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p)
  */
 static struct pbuf * low_level_input(struct netif *netif)
 {
-	struct xemac_s *xemac = (struct xemac_s *)(netif->state);
-	xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
-	struct pbuf *p;
+    struct xemac_s *xemac = (struct xemac_s *)(netif->state);
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+    struct pbuf *p;
 
 	/* see if there is data to process */
-	if (pq_qlength(xemacpsif->recv_q) == 0)
-		return NULL;
+    if (pq_qlength(xemacpsif->recv_q) == 0)
+	    return NULL;
 
 	/* return one packet from receive q */
-	p = (struct pbuf *)pq_dequeue(xemacpsif->recv_q);
-	return p;
+    p = (struct pbuf *)pq_dequeue(xemacpsif->recv_q);
+    return p;
 }
 
 /*
@@ -202,10 +202,10 @@ static struct pbuf * low_level_input(struct netif *netif)
  */
 
 static err_t xemacpsif_output(struct netif *netif, struct pbuf *p,
-		const ip_addr_t *ipaddr)
+	    const ip_addr_t *ipaddr)
 {
 	/* resolve hardware address, then send (or queue) packet */
-	return etharp_output(netif, p, ipaddr);
+    return etharp_output(netif, p, ipaddr);
 }
 
 /*
@@ -223,60 +223,60 @@ static err_t xemacpsif_output(struct netif *netif, struct pbuf *p,
 
 s32_t xemacpsif_input(struct netif *netif)
 {
-	struct eth_hdr *ethhdr;
-	struct pbuf *p;
-	SYS_ARCH_DECL_PROTECT(lev);
+    struct eth_hdr *ethhdr;
+    struct pbuf *p;
+    SYS_ARCH_DECL_PROTECT(lev);
 
 #ifdef OS_IS_FREERTOS
-	while (1)
+    while (1)
 #endif
 	{
 		/* move received packet into a new pbuf */
-		SYS_ARCH_PROTECT(lev);
-		p = low_level_input(netif);
-		SYS_ARCH_UNPROTECT(lev);
+	    SYS_ARCH_PROTECT(lev);
+	    p = low_level_input(netif);
+	    SYS_ARCH_UNPROTECT(lev);
 
 		/* no packet could be read, silently ignore this */
-		if (p == NULL) {
-			return 0;
+	    if (p == NULL) {
+		    return 0;
 		}
 
 		/* points to packet payload, which starts with an Ethernet header */
-		ethhdr = p->payload;
+	    ethhdr = p->payload;
 
 	#if LINK_STATS
-		lwip_stats.link.recv++;
+	    lwip_stats.link.recv++;
 	#endif /* LINK_STATS */
 
-		switch (htons(ethhdr->type)) {
+	    switch (htons(ethhdr->type)) {
 			/* IP or ARP packet? */
-			case ETHTYPE_IP:
-			case ETHTYPE_ARP:
+		    case ETHTYPE_IP:
+		    case ETHTYPE_ARP:
 	#if LWIP_IPV6
 			/*IPv6 Packet?*/
-			case ETHTYPE_IPV6:
+		    case ETHTYPE_IPV6:
 	#endif
 	#if PPPOE_SUPPORT
 				/* PPPoE packet? */
-			case ETHTYPE_PPPOEDISC:
-			case ETHTYPE_PPPOE:
+		    case ETHTYPE_PPPOEDISC:
+		    case ETHTYPE_PPPOE:
 	#endif /* PPPOE_SUPPORT */
 				/* full packet send to tcpip_thread to process */
-				if (netif->input(p, netif) != ERR_OK) {
-					LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_input: IP input error\r\n"));
-					pbuf_free(p);
-					p = NULL;
+			    if (netif->input(p, netif) != ERR_OK) {
+				    LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_input: IP input error\r\n"));
+				    pbuf_free(p);
+				    p = NULL;
 				}
-				break;
+			    break;
 
-			default:
-				pbuf_free(p);
-				p = NULL;
-				break;
+		    default:
+			    pbuf_free(p);
+			    p = NULL;
+			    break;
 		}
 	}
 
-	return 1;
+    return 1;
 }
 
 
@@ -284,419 +284,419 @@ s32_t xemacpsif_input(struct netif *netif)
 void vTimerCallback( TimerHandle_t pxTimer )
 {
 	/* Do something if the pxTimer parameter is NULL */
-	configASSERT(pxTimer);
+    configASSERT(pxTimer);
 
-	lExpireCounter++;
+    lExpireCounter++;
 	/* If the timer has expired 100 times then reset RX */
-	if(lExpireCounter >= RESETRXTIMEOUT) {
-		lExpireCounter = 0;
-		xemacpsif_resetrx_on_no_rxdata(NetIf);
+    if(lExpireCounter >= RESETRXTIMEOUT) {
+	    lExpireCounter = 0;
+	    xemacpsif_resetrx_on_no_rxdata(NetIf);
 	}
 }
  #endif
 
 static err_t low_level_init(struct netif *netif)
 {
-	UINTPTR mac_address = (UINTPTR)(netif->state);
-	struct xemac_s *xemac;
-	xemacpsif_s *xemacpsif;
-	u32 dmacrreg;
+    UINTPTR mac_address = (UINTPTR)(netif->state);
+    struct xemac_s *xemac;
+    xemacpsif_s *xemacpsif;
+    u32 dmacrreg;
 
-	s32_t status = XST_SUCCESS;
+    s32_t status = XST_SUCCESS;
 
-	NetIf = netif;
+    NetIf = netif;
 
-	xemacpsif = mem_malloc(sizeof *xemacpsif);
-	if (xemacpsif == NULL) {
-		LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
-		return ERR_MEM;
+    xemacpsif = mem_malloc(sizeof *xemacpsif);
+    if (xemacpsif == NULL) {
+	    LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
+	    return ERR_MEM;
 	}
 
-	xemac = mem_malloc(sizeof *xemac);
-	if (xemac == NULL) {
-		LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
-		return ERR_MEM;
+    xemac = mem_malloc(sizeof *xemac);
+    if (xemac == NULL) {
+	    LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
+	    return ERR_MEM;
 	}
 
-	xemac->state = (void *)xemacpsif;
-	xemac->topology_index = xtopology_find_index(mac_address);
-	xemac->type = xemac_type_emacps;
+    xemac->state = (void *)xemacpsif;
+    xemac->topology_index = xtopology_find_index(mac_address);
+    xemac->type = xemac_type_emacps;
 
-	xemacpsif->send_q = NULL;
-	xemacpsif->recv_q = pq_create_queue();
-	if (!xemacpsif->recv_q)
-		return ERR_MEM;
+    xemacpsif->send_q = NULL;
+    xemacpsif->recv_q = pq_create_queue();
+    if (!xemacpsif->recv_q)
+	    return ERR_MEM;
 
 	/* maximum transfer unit */
 #ifdef ZYNQMP_USE_JUMBO
-	netif->mtu = XEMACPS_MTU_JUMBO - XEMACPS_HDR_SIZE;
+    netif->mtu = XEMACPS_MTU_JUMBO - XEMACPS_HDR_SIZE;
 #else
-	netif->mtu = XEMACPS_MTU - XEMACPS_HDR_SIZE;
+    netif->mtu = XEMACPS_MTU - XEMACPS_HDR_SIZE;
 #endif
 
 #if LWIP_IGMP
-	netif->igmp_mac_filter = xemacpsif_mac_filter_update;
+    netif->igmp_mac_filter = xemacpsif_mac_filter_update;
 #endif
 
 #if LWIP_IPV6 && LWIP_IPV6_MLD
  netif->mld_mac_filter = xemacpsif_mld6_mac_filter_update;
 #endif
 
-	netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
-											NETIF_FLAG_LINK_UP;
+    netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
+										    NETIF_FLAG_LINK_UP;
 
 #if LWIP_IPV6 && LWIP_IPV6_MLD
-	netif->flags |= NETIF_FLAG_MLD6;
+    netif->flags |= NETIF_FLAG_MLD6;
 #endif
 
 #if LWIP_IGMP
-	netif->flags |= NETIF_FLAG_IGMP;
+    netif->flags |= NETIF_FLAG_IGMP;
 #endif
 
 #if 0
-	sys_sem_new(&xemac->sem_rx_data_available, 0);
+    sys_sem_new(&xemac->sem_rx_data_available, 0);
 #endif
 	/* obtain config of this emac */
-	mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)(UINTPTR)netif->state);
+    mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)(UINTPTR)netif->state);
 
 #if EL1_NONSECURE
 	/* Request device to indicate that this library is using it */
-	if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) {
-		Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_0, 1, 0, 100, 1, 0, 0);
+    if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) {
+	    Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_0, 1, 0, 100, 1, 0, 0);
 	}
-	if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) {
-		Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_1, 1, 0, 100, 1, 0, 0);
+    if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) {
+	    Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_1, 1, 0, 100, 1, 0, 0);
 	}
 #endif
 
-	status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
-						mac_config->BaseAddress);
-	if (status != XST_SUCCESS) {
-		xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
+    status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
+					    mac_config->BaseAddress);
+    if (status != XST_SUCCESS) {
+	    xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
 	}
 
 	/* initialize the mac */
-	init_emacps(xemacpsif, netif);
+    init_emacps(xemacpsif, netif);
 
-	dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-														XEMACPS_DMACR_OFFSET);
-	dmacrreg = dmacrreg | (0x00000010);
-	XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-											XEMACPS_DMACR_OFFSET, dmacrreg);
+    dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+													    XEMACPS_DMACR_OFFSET);
+    dmacrreg = dmacrreg | (0x00000010);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+										    XEMACPS_DMACR_OFFSET, dmacrreg);
 
 #if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
 	/* Freertos tick is 10ms by default; set period to the same */
-	xemac->xTimer = xTimerCreate("Timer", 10, pdTRUE, ( void * ) 1, vTimerCallback);
-	if (xemac->xTimer == NULL) {
-		xil_printf("In %s:Timer creation failed....\r\n", __func__);
+    xemac->xTimer = xTimerCreate("Timer", 10, pdTRUE, ( void * ) 1, vTimerCallback);
+    if (xemac->xTimer == NULL) {
+	    xil_printf("In %s:Timer creation failed....\r\n", __func__);
 	} else {
-		if(xTimerStart(xemac->xTimer, 0) != pdPASS) {
-			xil_printf("In %s:Timer start failed....\r\n", __func__);
+	    if(xTimerStart(xemac->xTimer, 0) != pdPASS) {
+		    xil_printf("In %s:Timer start failed....\r\n", __func__);
 		}
 	}
 #endif
-	setup_isr(xemac);
-	init_dma(xemac);
-	start_emacps(xemacpsif);
+    setup_isr(xemac);
+    init_dma(xemac);
+    start_emacps(xemacpsif);
 
 	/* replace the state in netif (currently the emac baseaddress)
 	 * with the mac instance pointer.
 	 */
-	netif->state = (void *)xemac;
+    netif->state = (void *)xemac;
 
-	return ERR_OK;
+    return ERR_OK;
 }
 
 void HandleEmacPsError(struct xemac_s *xemac)
 {
-	xemacpsif_s   *xemacpsif;
-	s32_t status = XST_SUCCESS;
-	u32 dmacrreg;
+    xemacpsif_s   *xemacpsif;
+    s32_t status = XST_SUCCESS;
+    u32 dmacrreg;
 
-	SYS_ARCH_DECL_PROTECT(lev);
-	SYS_ARCH_PROTECT(lev);
+    SYS_ARCH_DECL_PROTECT(lev);
+    SYS_ARCH_PROTECT(lev);
 
-	xemacpsif = (xemacpsif_s *)(xemac->state);
-	free_txrx_pbufs(xemacpsif);
-	status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
-						mac_config->BaseAddress);
-	if (status != XST_SUCCESS) {
-		xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
+    xemacpsif = (xemacpsif_s *)(xemac->state);
+    free_txrx_pbufs(xemacpsif);
+    status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
+					    mac_config->BaseAddress);
+    if (status != XST_SUCCESS) {
+	    xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
 	}
 	/* initialize the mac */
-	init_emacps_on_error(xemacpsif, NetIf);
-	dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-														XEMACPS_DMACR_OFFSET);
-	dmacrreg = dmacrreg | (0x01000000);
-	XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-											XEMACPS_DMACR_OFFSET, dmacrreg);
-	setup_isr(xemac);
-	init_dma(xemac);
-	start_emacps(xemacpsif);
+    init_emacps_on_error(xemacpsif, NetIf);
+    dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+													    XEMACPS_DMACR_OFFSET);
+    dmacrreg = dmacrreg | (0x01000000);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+										    XEMACPS_DMACR_OFFSET, dmacrreg);
+    setup_isr(xemac);
+    init_dma(xemac);
+    start_emacps(xemacpsif);
 
-	SYS_ARCH_UNPROTECT(lev);
+    SYS_ARCH_UNPROTECT(lev);
 }
 
 void HandleTxErrors(struct xemac_s *xemac)
 {
-	xemacpsif_s   *xemacpsif;
-	u32 netctrlreg;
+    xemacpsif_s   *xemacpsif;
+    u32 netctrlreg;
 
-	SYS_ARCH_DECL_PROTECT(lev);
-	SYS_ARCH_PROTECT(lev);
-	xemacpsif = (xemacpsif_s *)(xemac->state);
-	netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-												XEMACPS_NWCTRL_OFFSET);
+    SYS_ARCH_DECL_PROTECT(lev);
+    SYS_ARCH_PROTECT(lev);
+    xemacpsif = (xemacpsif_s *)(xemac->state);
+    netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+											    XEMACPS_NWCTRL_OFFSET);
     netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
-	XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-									XEMACPS_NWCTRL_OFFSET, netctrlreg);
-	free_onlytx_pbufs(xemacpsif);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+								    XEMACPS_NWCTRL_OFFSET, netctrlreg);
+    free_onlytx_pbufs(xemacpsif);
 
-	clean_dma_txdescs(xemac);
-	netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-													XEMACPS_NWCTRL_OFFSET);
-	netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
-	XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-										XEMACPS_NWCTRL_OFFSET, netctrlreg);
-	SYS_ARCH_UNPROTECT(lev);
+    clean_dma_txdescs(xemac);
+    netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+												    XEMACPS_NWCTRL_OFFSET);
+    netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+									    XEMACPS_NWCTRL_OFFSET, netctrlreg);
+    SYS_ARCH_UNPROTECT(lev);
 }
 
 #if LWIP_IPV6 && LWIP_IPV6_MLD
 static u8_t xemacpsif_ip6_addr_ismulticast(ip6_addr_t* ip_addr)
 {
-	if(ip6_addr_ismulticast_linklocal(ip_addr)||
+    if(ip6_addr_ismulticast_linklocal(ip_addr)||
            ip6_addr_ismulticast_iflocal(ip_addr)   ||
            ip6_addr_ismulticast_adminlocal(ip_addr)||
            ip6_addr_ismulticast_sitelocal(ip_addr) ||
            ip6_addr_ismulticast_orglocal(ip_addr)  ||
            ip6_addr_ismulticast_global(ip_addr)) {
 	/*Return TRUE if IPv6 is Multicast type*/
-	return TRUE;
+    return TRUE;
 	} else {
-	return FALSE;
+    return FALSE;
 	}
 }
 
 static void xemacpsif_mld6_mac_hash_update (struct netif *netif, u8_t *ip_addr,
-		u8_t action)
+	    u8_t action)
 {
-	u8_t multicast_mac_addr[6];
-	struct xemac_s *xemac = (struct xemac_s *) (netif->state);
-	xemacpsif_s *xemacpsif = (xemacpsif_s *) (xemac->state);
-	XEmacPs_BdRing *txring;
-	txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+    u8_t multicast_mac_addr[6];
+    struct xemac_s *xemac = (struct xemac_s *) (netif->state);
+    xemacpsif_s *xemacpsif = (xemacpsif_s *) (xemac->state);
+    XEmacPs_BdRing *txring;
+    txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
 
-	multicast_mac_addr[0] = LL_IP6_MULTICAST_ADDR_0;
-	multicast_mac_addr[1] = LL_IP6_MULTICAST_ADDR_1;
-	multicast_mac_addr[2] = ip_addr[12];
-	multicast_mac_addr[3] = ip_addr[13];
-	multicast_mac_addr[4] = ip_addr[14];
-	multicast_mac_addr[5] = ip_addr[15];
+    multicast_mac_addr[0] = LL_IP6_MULTICAST_ADDR_0;
+    multicast_mac_addr[1] = LL_IP6_MULTICAST_ADDR_1;
+    multicast_mac_addr[2] = ip_addr[12];
+    multicast_mac_addr[3] = ip_addr[13];
+    multicast_mac_addr[4] = ip_addr[14];
+    multicast_mac_addr[5] = ip_addr[15];
 
 	/* Wait till all sent packets are acknowledged from HW */
-	while(txring->HwCnt);
+    while(txring->HwCnt);
 
-	SYS_ARCH_DECL_PROTECT(lev);
+    SYS_ARCH_DECL_PROTECT(lev);
 
-	SYS_ARCH_PROTECT(lev);
+    SYS_ARCH_PROTECT(lev);
 
 	/* Stop Ethernet */
-	XEmacPs_Stop(&xemacpsif->emacps);
+    XEmacPs_Stop(&xemacpsif->emacps);
 
-	if (action == NETIF_ADD_MAC_FILTER) {
+    if (action == NETIF_ADD_MAC_FILTER) {
 		/* Set Mulitcast mac address in hash table */
-		XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
+	    XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
 
 	} else if (action == NETIF_DEL_MAC_FILTER) {
 		/* Remove Mulitcast mac address in hash table */
-		XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
+	    XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
 	}
 
 	/* Reset DMA */
-	reset_dma(xemac);
+    reset_dma(xemac);
 
 	/* Start Ethernet */
-	XEmacPs_Start(&xemacpsif->emacps);
+    XEmacPs_Start(&xemacpsif->emacps);
 
-	SYS_ARCH_UNPROTECT(lev);
+    SYS_ARCH_UNPROTECT(lev);
 }
 
 static err_t xemacpsif_mld6_mac_filter_update (struct netif *netif, ip_addr_t *group,
-		u8_t action)
+	    u8_t action)
 {
-	u8_t temp_mask;
-	unsigned int i;
-	u8_t * ip_addr = (u8_t *) group;
+    u8_t temp_mask;
+    unsigned int i;
+    u8_t * ip_addr = (u8_t *) group;
 
-	if(!(xemacpsif_ip6_addr_ismulticast((ip6_addr_t*) ip_addr))) {
-		LWIP_DEBUGF(NETIF_DEBUG,
+    if(!(xemacpsif_ip6_addr_ismulticast((ip6_addr_t*) ip_addr))) {
+	    LWIP_DEBUGF(NETIF_DEBUG,
                                 ("%s: The requested MAC address is not a multicast address.\r\n", __func__));								 LWIP_DEBUGF(NETIF_DEBUG,
 		                ("Multicast address add operation failure !!\r\n"));
                         return ERR_ARG;
 	}
-	if (action == NETIF_ADD_MAC_FILTER) {
-		for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
-			temp_mask = (0x01) << i;
-			if ((xemacps_mld6_mcast_entry_mask & temp_mask) == temp_mask) {
-				continue;
+    if (action == NETIF_ADD_MAC_FILTER) {
+	    for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+		    temp_mask = (0x01) << i;
+		    if ((xemacps_mld6_mcast_entry_mask & temp_mask) == temp_mask) {
+			    continue;
 			}
-			xemacps_mld6_mcast_entry_mask |= temp_mask;
+		    xemacps_mld6_mcast_entry_mask |= temp_mask;
 
 			/* Update mac address in hash table */
-			xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
+		    xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
 
-			LWIP_DEBUGF(NETIF_DEBUG,
+		    LWIP_DEBUGF(NETIF_DEBUG,
 					("%s: Multicast MAC address successfully added.\r\n", __func__));
 
-			return ERR_OK;
+		    return ERR_OK;
 		}
-		LWIP_DEBUGF(NETIF_DEBUG,
+	    LWIP_DEBUGF(NETIF_DEBUG,
 				("%s: No multicast address registers left.\r\n", __func__));
-		LWIP_DEBUGF(NETIF_DEBUG,
+	    LWIP_DEBUGF(NETIF_DEBUG,
 				("Multicast MAC address add operation failure !!\r\n"));
-		return ERR_MEM;
+	    return ERR_MEM;
 	} else if (action == NETIF_DEL_MAC_FILTER) {
-		for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
-			temp_mask = (0x01) << i;
-			if ((xemacps_mld6_mcast_entry_mask & temp_mask) != temp_mask) {
-				continue;
+	    for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+		    temp_mask = (0x01) << i;
+		    if ((xemacps_mld6_mcast_entry_mask & temp_mask) != temp_mask) {
+			    continue;
 			}
-			xemacps_mld6_mcast_entry_mask &= (~temp_mask);
+		    xemacps_mld6_mcast_entry_mask &= (~temp_mask);
 
 			/* Update mac address in hash table */
-			xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
+		    xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
 
-			LWIP_DEBUGF(NETIF_DEBUG,
+		    LWIP_DEBUGF(NETIF_DEBUG,
 					("%s: Multicast MAC address successfully removed.\r\n", __func__));
 
-			return ERR_OK;
+		    return ERR_OK;
 		}
-		LWIP_DEBUGF(NETIF_DEBUG,
+	    LWIP_DEBUGF(NETIF_DEBUG,
 				("%s: No multicast address registers present with\r\n", __func__));
-		LWIP_DEBUGF(NETIF_DEBUG,
+	    LWIP_DEBUGF(NETIF_DEBUG,
 				("the requested Multicast MAC address.\r\n"));
-		LWIP_DEBUGF(NETIF_DEBUG,
+	    LWIP_DEBUGF(NETIF_DEBUG,
 				("Multicast MAC address removal failure!!.\r\n"));
-		return ERR_MEM;
+	    return ERR_MEM;
 	}
-	return ERR_ARG;
+    return ERR_ARG;
 }
 #endif
 
 #if LWIP_IGMP
 static void xemacpsif_mac_hash_update (struct netif *netif, u8_t *ip_addr,
-		u8_t action)
+	    u8_t action)
 {
-	u8_t multicast_mac_addr[6];
-	struct xemac_s *xemac = (struct xemac_s *) (netif->state);
-	xemacpsif_s *xemacpsif = (xemacpsif_s *) (xemac->state);
-	XEmacPs_BdRing *txring;
-	txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+    u8_t multicast_mac_addr[6];
+    struct xemac_s *xemac = (struct xemac_s *) (netif->state);
+    xemacpsif_s *xemacpsif = (xemacpsif_s *) (xemac->state);
+    XEmacPs_BdRing *txring;
+    txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
 
-	multicast_mac_addr[0] = 0x01;
-	multicast_mac_addr[1] = 0x00;
-	multicast_mac_addr[2] = 0x5E;
-	multicast_mac_addr[3] = ip_addr[1] & 0x7F;
-	multicast_mac_addr[4] = ip_addr[2];
-	multicast_mac_addr[5] = ip_addr[3];
+    multicast_mac_addr[0] = 0x01;
+    multicast_mac_addr[1] = 0x00;
+    multicast_mac_addr[2] = 0x5E;
+    multicast_mac_addr[3] = ip_addr[1] & 0x7F;
+    multicast_mac_addr[4] = ip_addr[2];
+    multicast_mac_addr[5] = ip_addr[3];
 
 	/* Wait till all sent packets are acknowledged from HW */
-	while(txring->HwCnt);
+    while(txring->HwCnt);
 
-	SYS_ARCH_DECL_PROTECT(lev);
+    SYS_ARCH_DECL_PROTECT(lev);
 
-	SYS_ARCH_PROTECT(lev);
+    SYS_ARCH_PROTECT(lev);
 
 	/* Stop Ethernet */
-	XEmacPs_Stop(&xemacpsif->emacps);
+    XEmacPs_Stop(&xemacpsif->emacps);
 
-	if (action == IGMP_ADD_MAC_FILTER) {
+    if (action == IGMP_ADD_MAC_FILTER) {
 		/* Set Mulitcast mac address in hash table */
-		XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
+	    XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
 
 	} else if (action == IGMP_DEL_MAC_FILTER) {
 		/* Remove Mulitcast mac address in hash table */
-		XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
+	    XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
 	}
 
 	/* Reset DMA */
-	reset_dma(xemac);
+    reset_dma(xemac);
 
 	/* Start Ethernet */
-	XEmacPs_Start(&xemacpsif->emacps);
+    XEmacPs_Start(&xemacpsif->emacps);
 
-	SYS_ARCH_UNPROTECT(lev);
+    SYS_ARCH_UNPROTECT(lev);
 }
 
 static err_t xemacpsif_mac_filter_update (struct netif *netif, ip_addr_t *group,
-		u8_t action)
+	    u8_t action)
 {
-	u8_t temp_mask;
-	unsigned int i;
-	u8_t * ip_addr = (u8_t *) group;
+    u8_t temp_mask;
+    unsigned int i;
+    u8_t * ip_addr = (u8_t *) group;
 
-	if ((ip_addr[0] < 224) && (ip_addr[0] > 239)) {
-		LWIP_DEBUGF(NETIF_DEBUG,
+    if ((ip_addr[0] < 224) && (ip_addr[0] > 239)) {
+	    LWIP_DEBUGF(NETIF_DEBUG,
 				("%s: The requested MAC address is not a multicast address.\r\n", __func__));
-		LWIP_DEBUGF(NETIF_DEBUG,
+	    LWIP_DEBUGF(NETIF_DEBUG,
 				("Multicast address add operation failure !!\r\n"));
 
-		return ERR_ARG;
+	    return ERR_ARG;
 	}
 
-	if (action == IGMP_ADD_MAC_FILTER) {
+    if (action == IGMP_ADD_MAC_FILTER) {
 
-		for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
-			temp_mask = (0x01) << i;
-			if ((xemacps_mcast_entry_mask & temp_mask) == temp_mask) {
-				continue;
+	    for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+		    temp_mask = (0x01) << i;
+		    if ((xemacps_mcast_entry_mask & temp_mask) == temp_mask) {
+			    continue;
 			}
-			xemacps_mcast_entry_mask |= temp_mask;
+		    xemacps_mcast_entry_mask |= temp_mask;
 
 			/* Update mac address in hash table */
-			xemacpsif_mac_hash_update(netif, ip_addr, action);
+		    xemacpsif_mac_hash_update(netif, ip_addr, action);
 
-			LWIP_DEBUGF(NETIF_DEBUG,
+		    LWIP_DEBUGF(NETIF_DEBUG,
 					("%s: Multicast MAC address successfully added.\r\n", __func__));
 
-			return ERR_OK;
+		    return ERR_OK;
 		}
-		if (i == XEMACPS_MAX_MAC_ADDR) {
-			LWIP_DEBUGF(NETIF_DEBUG,
+	    if (i == XEMACPS_MAX_MAC_ADDR) {
+		    LWIP_DEBUGF(NETIF_DEBUG,
 					("%s: No multicast address registers left.\r\n", __func__));
-			LWIP_DEBUGF(NETIF_DEBUG,
+		    LWIP_DEBUGF(NETIF_DEBUG,
 					("Multicast MAC address add operation failure !!\r\n"));
 
-			return ERR_MEM;
+		    return ERR_MEM;
 		}
 	} else if (action == IGMP_DEL_MAC_FILTER) {
-		for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
-			temp_mask = (0x01) << i;
-			if ((xemacps_mcast_entry_mask & temp_mask) != temp_mask) {
-				continue;
+	    for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+		    temp_mask = (0x01) << i;
+		    if ((xemacps_mcast_entry_mask & temp_mask) != temp_mask) {
+			    continue;
 			}
-			xemacps_mcast_entry_mask &= (~temp_mask);
+		    xemacps_mcast_entry_mask &= (~temp_mask);
 
 			/* Update mac address in hash table */
-			xemacpsif_mac_hash_update(netif, ip_addr, action);
+		    xemacpsif_mac_hash_update(netif, ip_addr, action);
 
-			LWIP_DEBUGF(NETIF_DEBUG,
+		    LWIP_DEBUGF(NETIF_DEBUG,
 					("%s: Multicast MAC address successfully removed.\r\n", __func__));
 
-			return ERR_OK;
+		    return ERR_OK;
 		}
-		if (i == XEMACPS_MAX_MAC_ADDR) {
-			LWIP_DEBUGF(NETIF_DEBUG,
+	    if (i == XEMACPS_MAX_MAC_ADDR) {
+		    LWIP_DEBUGF(NETIF_DEBUG,
 					("%s: No multicast address registers present with\r\n", __func__));
-			LWIP_DEBUGF(NETIF_DEBUG,
+		    LWIP_DEBUGF(NETIF_DEBUG,
 					("the requested Multicast MAC address.\r\n"));
-			LWIP_DEBUGF(NETIF_DEBUG,
+		    LWIP_DEBUGF(NETIF_DEBUG,
 					("Multicast MAC address removal failure!!.\r\n"));
 
-			return ERR_MEM;
+		    return ERR_MEM;
 		}
 	}
-	return ERR_OK;
+    return ERR_OK;
 }
 #endif
 
@@ -713,30 +713,30 @@ err_t xemacpsif_init(struct netif *netif)
 {
 #if LWIP_SNMP
 	/* ifType ethernetCsmacd(6) @see RFC1213 */
-	netif->link_type = 6;
+    netif->link_type = 6;
 	/* your link speed here */
-	netif->link_speed = ;
-	netif->ts = 0;
-	netif->ifinoctets = 0;
-	netif->ifinucastpkts = 0;
-	netif->ifinnucastpkts = 0;
-	netif->ifindiscards = 0;
-	netif->ifoutoctets = 0;
-	netif->ifoutucastpkts = 0;
-	netif->ifoutnucastpkts = 0;
-	netif->ifoutdiscards = 0;
+    netif->link_speed = ;
+    netif->ts = 0;
+    netif->ifinoctets = 0;
+    netif->ifinucastpkts = 0;
+    netif->ifinnucastpkts = 0;
+    netif->ifindiscards = 0;
+    netif->ifoutoctets = 0;
+    netif->ifoutucastpkts = 0;
+    netif->ifoutnucastpkts = 0;
+    netif->ifoutdiscards = 0;
 #endif
 
-	netif->name[0] = IFNAME0;
-	netif->name[1] = IFNAME1;
-	netif->output = xemacpsif_output;
-	netif->linkoutput = low_level_output;
+    netif->name[0] = IFNAME0;
+    netif->name[1] = IFNAME1;
+    netif->output = xemacpsif_output;
+    netif->linkoutput = low_level_output;
 #if LWIP_IPV6
-	netif->output_ip6 = ethip6_output;
+    netif->output_ip6 = ethip6_output;
 #endif
 
-	low_level_init(netif);
-	return ERR_OK;
+    low_level_init(netif);
+    return ERR_OK;
 }
 
 /*
@@ -752,8 +752,8 @@ err_t xemacpsif_init(struct netif *netif)
 
 void xemacpsif_resetrx_on_no_rxdata(struct netif *netif)
 {
-	struct xemac_s *xemac = (struct xemac_s *)(netif->state);
-	xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+    struct xemac_s *xemac = (struct xemac_s *)(netif->state);
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
 
-	resetrx_on_no_rxdata(xemacpsif);
+    resetrx_on_no_rxdata(xemacpsif);
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c
index e52f6da6bb..af7da9d7dd 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c
@@ -2,7 +2,7 @@
  * Copyright (C) 2010 - 2019 Xilinx, Inc.
  * Copyright (C) 2021 WangHuachen.
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
@@ -57,8 +57,8 @@
 
 #include 
 
-#define INTC_BASE_ADDR		XPAR_SCUGIC_0_CPU_BASEADDR
-#define INTC_DIST_BASE_ADDR	XPAR_SCUGIC_0_DIST_BASEADDR
+#define INTC_BASE_ADDR	    XPAR_SCUGIC_0_CPU_BASEADDR
+#define INTC_DIST_BASE_ADDR    XPAR_SCUGIC_0_DIST_BASEADDR
 
 /* Byte alignment of BDs */
 #define BD_ALIGNMENT (XEMACPS_DMABD_MINIMUM_ALIGNMENT*2)
@@ -128,445 +128,445 @@ long xInsideISR = 0;
 
 s32_t is_tx_space_available(xemacpsif_s *emac)
 {
-	XEmacPs_BdRing *txring;
-	s32_t freecnt = 0;
+    XEmacPs_BdRing *txring;
+    s32_t freecnt = 0;
 
-	txring = &(XEmacPs_GetTxRing(&emac->emacps));
+    txring = &(XEmacPs_GetTxRing(&emac->emacps));
 
 	/* tx space is available as long as there are valid BD's */
-	freecnt = XEmacPs_BdRingGetFreeCnt(txring);
-	return freecnt;
+    freecnt = XEmacPs_BdRingGetFreeCnt(txring);
+    return freecnt;
 }
 
 
 static inline
 u32_t get_base_index_txpbufsstorage (xemacpsif_s *xemacpsif)
 {
-	u32_t index;
+    u32_t index;
 #ifdef XPAR_XEMACPS_0_BASEADDR
-	if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
-		index = 0;
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
+	    index = 0;
 	}
 #endif
 #ifdef XPAR_XEMACPS_1_BASEADDR
-	if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_1_BASEADDR) {
-		index = XLWIP_CONFIG_N_TX_DESC;
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_1_BASEADDR) {
+	    index = XLWIP_CONFIG_N_TX_DESC;
 	}
 #endif
 #ifdef XPAR_XEMACPS_2_BASEADDR
-	if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_2_BASEADDR) {
-		index = 2 * XLWIP_CONFIG_N_TX_DESC;
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_2_BASEADDR) {
+	    index = 2 * XLWIP_CONFIG_N_TX_DESC;
 	}
 #endif
 #ifdef XPAR_XEMACPS_3_BASEADDR
-	if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_3_BASEADDR) {
-		index = 3 * XLWIP_CONFIG_N_TX_DESC;
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_3_BASEADDR) {
+	    index = 3 * XLWIP_CONFIG_N_TX_DESC;
 	}
 #endif
-	return index;
+    return index;
 }
 
 static inline
 u32_t get_base_index_rxpbufsstorage (xemacpsif_s *xemacpsif)
 {
-	u32_t index;
+    u32_t index;
 #ifdef XPAR_XEMACPS_0_BASEADDR
-	if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
-		index = 0;
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
+	    index = 0;
 	}
 #endif
 #ifdef XPAR_XEMACPS_1_BASEADDR
-	if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_1_BASEADDR) {
-		index = XLWIP_CONFIG_N_RX_DESC;
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_1_BASEADDR) {
+	    index = XLWIP_CONFIG_N_RX_DESC;
 	}
 #endif
 #ifdef XPAR_XEMACPS_2_BASEADDR
-	if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_2_BASEADDR) {
-		index = 2 * XLWIP_CONFIG_N_RX_DESC;
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_2_BASEADDR) {
+	    index = 2 * XLWIP_CONFIG_N_RX_DESC;
 	}
 #endif
 #ifdef XPAR_XEMACPS_3_BASEADDR
-	if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_3_BASEADDR) {
-		index = 3 * XLWIP_CONFIG_N_RX_DESC;
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_3_BASEADDR) {
+	    index = 3 * XLWIP_CONFIG_N_RX_DESC;
 	}
 #endif
-	return index;
+    return index;
 }
 
 void process_sent_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *txring)
 {
-	XEmacPs_Bd *txbdset;
-	XEmacPs_Bd *curbdpntr;
-	s32_t n_bds;
-	XStatus status;
-	s32_t n_pbufs_freed = 0;
-	u32_t bdindex;
-	struct pbuf *p;
-	u32 *temp;
-	u32_t index;
+    XEmacPs_Bd *txbdset;
+    XEmacPs_Bd *curbdpntr;
+    s32_t n_bds;
+    XStatus status;
+    s32_t n_pbufs_freed = 0;
+    u32_t bdindex;
+    struct pbuf *p;
+    u32 *temp;
+    u32_t index;
 
-	index = get_base_index_txpbufsstorage (xemacpsif);
+    index = get_base_index_txpbufsstorage (xemacpsif);
 
-	while (1) {
+    while (1) {
 		/* obtain processed BD's */
-		n_bds = XEmacPs_BdRingFromHwTx(txring,
-								XLWIP_CONFIG_N_TX_DESC, &txbdset);
-		if (n_bds == 0)  {
-			return;
+	    n_bds = XEmacPs_BdRingFromHwTx(txring,
+							    XLWIP_CONFIG_N_TX_DESC, &txbdset);
+	    if (n_bds == 0)  {
+		    return;
 		}
 		/* free the processed BD's */
-		n_pbufs_freed = n_bds;
-		curbdpntr = txbdset;
-		while (n_pbufs_freed > 0) {
-			bdindex = XEMACPS_BD_TO_INDEX(txring, curbdpntr);
-			temp = (u32 *)curbdpntr;
+	    n_pbufs_freed = n_bds;
+	    curbdpntr = txbdset;
+	    while (n_pbufs_freed > 0) {
+		    bdindex = XEMACPS_BD_TO_INDEX(txring, curbdpntr);
+		    temp = (u32 *)curbdpntr;
 			*temp = 0;
-			temp++;
-			if (bdindex == (XLWIP_CONFIG_N_TX_DESC - 1)) {
+		    temp++;
+		    if (bdindex == (XLWIP_CONFIG_N_TX_DESC - 1)) {
 				*temp = 0xC0000000;
 			} else {
 				*temp = 0x80000000;
 			}
-			dsb();
-			p = (struct pbuf *)tx_pbufs_storage[index + bdindex];
-			if (p != NULL) {
-				pbuf_free(p);
+		    dsb();
+		    p = (struct pbuf *)tx_pbufs_storage[index + bdindex];
+		    if (p != NULL) {
+			    pbuf_free(p);
 			}
-			tx_pbufs_storage[index + bdindex] = 0;
-			curbdpntr = XEmacPs_BdRingNext(txring, curbdpntr);
-			n_pbufs_freed--;
-			dsb();
+		    tx_pbufs_storage[index + bdindex] = 0;
+		    curbdpntr = XEmacPs_BdRingNext(txring, curbdpntr);
+		    n_pbufs_freed--;
+		    dsb();
 		}
 
-		status = XEmacPs_BdRingFree(txring, n_bds, txbdset);
-		if (status != XST_SUCCESS) {
-			LWIP_DEBUGF(NETIF_DEBUG, ("Failure while freeing in Tx Done ISR\r\n"));
+	    status = XEmacPs_BdRingFree(txring, n_bds, txbdset);
+	    if (status != XST_SUCCESS) {
+		    LWIP_DEBUGF(NETIF_DEBUG, ("Failure while freeing in Tx Done ISR\r\n"));
 		}
 	}
-	return;
+    return;
 }
 
 void emacps_send_handler(void *arg)
 {
-	struct xemac_s *xemac;
-	xemacpsif_s   *xemacpsif;
-	XEmacPs_BdRing *txringptr;
-	u32_t regval;
+    struct xemac_s *xemac;
+    xemacpsif_s   *xemacpsif;
+    XEmacPs_BdRing *txringptr;
+    u32_t regval;
 #ifdef OS_IS_FREERTOS
-	xInsideISR++;
+    xInsideISR++;
 #endif
-	xemac = (struct xemac_s *)(arg);
-	xemacpsif = (xemacpsif_s *)(xemac->state);
-	txringptr = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
-	regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_TXSR_OFFSET);
-	XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,XEMACPS_TXSR_OFFSET, regval);
+    xemac = (struct xemac_s *)(arg);
+    xemacpsif = (xemacpsif_s *)(xemac->state);
+    txringptr = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+    regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_TXSR_OFFSET);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,XEMACPS_TXSR_OFFSET, regval);
 
 	/* If Transmit done interrupt is asserted, process completed BD's */
 	/* Since RT-Thread does not support freeing memory in interrupts, comment it out */
 	// process_sent_bds(xemacpsif, txringptr);
 #ifdef OS_IS_FREERTOS
-	xInsideISR--;
+    xInsideISR--;
 #endif
 }
 
 XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p)
 {
-	struct pbuf *q;
-	s32_t n_pbufs;
-	XEmacPs_Bd *txbdset, *txbd, *last_txbd = NULL;
-	XEmacPs_Bd *temp_txbd;
-	XStatus status;
-	XEmacPs_BdRing *txring;
-	u32_t bdindex;
-	u32_t lev;
-	u32_t index;
-	u32_t max_fr_size;
+    struct pbuf *q;
+    s32_t n_pbufs;
+    XEmacPs_Bd *txbdset, *txbd, *last_txbd = NULL;
+    XEmacPs_Bd *temp_txbd;
+    XStatus status;
+    XEmacPs_BdRing *txring;
+    u32_t bdindex;
+    u32_t lev;
+    u32_t index;
+    u32_t max_fr_size;
 
-	lev = mfcpsr();
-	mtcpsr(lev | 0x000000C0);
+    lev = mfcpsr();
+    mtcpsr(lev | 0x000000C0);
 
-	txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+    txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
 
-	index = get_base_index_txpbufsstorage (xemacpsif);
+    index = get_base_index_txpbufsstorage (xemacpsif);
 
 	/* first count the number of pbufs */
-	for (q = p, n_pbufs = 0; q != NULL; q = q->next)
-		n_pbufs++;
+    for (q = p, n_pbufs = 0; q != NULL; q = q->next)
+	    n_pbufs++;
 
 	/* obtain as many BD's */
-	status = XEmacPs_BdRingAlloc(txring, n_pbufs, &txbdset);
-	if (status != XST_SUCCESS) {
-		mtcpsr(lev);
-		LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error allocating TxBD\r\n"));
-		return XST_FAILURE;
+    status = XEmacPs_BdRingAlloc(txring, n_pbufs, &txbdset);
+    if (status != XST_SUCCESS) {
+	    mtcpsr(lev);
+	    LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error allocating TxBD\r\n"));
+	    return XST_FAILURE;
 	}
 
-	for(q = p, txbd = txbdset; q != NULL; q = q->next) {
-		bdindex = XEMACPS_BD_TO_INDEX(txring, txbd);
-		if (tx_pbufs_storage[index + bdindex] != 0) {
-			mtcpsr(lev);
-			LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n"));
-			return XST_FAILURE;
+    for(q = p, txbd = txbdset; q != NULL; q = q->next) {
+	    bdindex = XEMACPS_BD_TO_INDEX(txring, txbd);
+	    if (tx_pbufs_storage[index + bdindex] != 0) {
+		    mtcpsr(lev);
+		    LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n"));
+		    return XST_FAILURE;
 		}
 
 		/* Send the data from the pbuf to the interface, one pbuf at a
 		   time. The size of the data in each pbuf is kept in the ->len
 		   variable. */
-		if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
-			Xil_DCacheFlushRange((UINTPTR)q->payload, (UINTPTR)q->len);
+	    if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+		    Xil_DCacheFlushRange((UINTPTR)q->payload, (UINTPTR)q->len);
 		}
 
-		XEmacPs_BdSetAddressTx(txbd, (UINTPTR)q->payload);
+	    XEmacPs_BdSetAddressTx(txbd, (UINTPTR)q->payload);
 
 #ifdef ZYNQMP_USE_JUMBO
-		max_fr_size = MAX_FRAME_SIZE_JUMBO - 18;
+	    max_fr_size = MAX_FRAME_SIZE_JUMBO - 18;
 #else
-		max_fr_size = XEMACPS_MAX_FRAME_SIZE - 18;
+	    max_fr_size = XEMACPS_MAX_FRAME_SIZE - 18;
 #endif
-		if (q->len > max_fr_size)
-			XEmacPs_BdSetLength(txbd, max_fr_size & 0x3FFF);
-		else
-			XEmacPs_BdSetLength(txbd, q->len & 0x3FFF);
+	    if (q->len > max_fr_size)
+		    XEmacPs_BdSetLength(txbd, max_fr_size & 0x3FFF);
+	    else
+		    XEmacPs_BdSetLength(txbd, q->len & 0x3FFF);
 
-		tx_pbufs_storage[index + bdindex] = (UINTPTR)q;
+	    tx_pbufs_storage[index + bdindex] = (UINTPTR)q;
 
-		pbuf_ref(q);
-		last_txbd = txbd;
-		XEmacPs_BdClearLast(txbd);
-		txbd = XEmacPs_BdRingNext(txring, txbd);
+	    pbuf_ref(q);
+	    last_txbd = txbd;
+	    XEmacPs_BdClearLast(txbd);
+	    txbd = XEmacPs_BdRingNext(txring, txbd);
 	}
-	XEmacPs_BdSetLast(last_txbd);
+    XEmacPs_BdSetLast(last_txbd);
 	/* For fragmented packets, remember the 1st BD allocated for the 1st
 	   packet fragment. The used bit for this BD should be cleared at the end
 	   after clearing out used bits for other fragments. For packets without
 	   just remember the allocated BD. */
-	temp_txbd = txbdset;
-	txbd = txbdset;
-	txbd = XEmacPs_BdRingNext(txring, txbd);
-	q = p->next;
-	for(; q != NULL; q = q->next) {
-		XEmacPs_BdClearTxUsed(txbd);
-		dsb();
-		txbd = XEmacPs_BdRingNext(txring, txbd);
+    temp_txbd = txbdset;
+    txbd = txbdset;
+    txbd = XEmacPs_BdRingNext(txring, txbd);
+    q = p->next;
+    for(; q != NULL; q = q->next) {
+	    XEmacPs_BdClearTxUsed(txbd);
+	    dsb();
+	    txbd = XEmacPs_BdRingNext(txring, txbd);
 	}
-	XEmacPs_BdClearTxUsed(temp_txbd);
-	dsb();
+    XEmacPs_BdClearTxUsed(temp_txbd);
+    dsb();
 
-	status = XEmacPs_BdRingToHw(txring, n_pbufs, txbdset);
-	if (status != XST_SUCCESS) {
-		mtcpsr(lev);
-		LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error submitting TxBD\r\n"));
-		return XST_FAILURE;
+    status = XEmacPs_BdRingToHw(txring, n_pbufs, txbdset);
+    if (status != XST_SUCCESS) {
+	    mtcpsr(lev);
+	    LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error submitting TxBD\r\n"));
+	    return XST_FAILURE;
 	}
 	/* Start transmit */
-	XEmacPs_WriteReg((xemacpsif->emacps).Config.BaseAddress,
-	XEMACPS_NWCTRL_OFFSET,
+    XEmacPs_WriteReg((xemacpsif->emacps).Config.BaseAddress,
+    XEMACPS_NWCTRL_OFFSET,
 	(XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress,
-	XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK));
+    XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK));
 
-	mtcpsr(lev);
-	return status;
+    mtcpsr(lev);
+    return status;
 }
 
 void setup_rx_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *rxring)
 {
-	XEmacPs_Bd *rxbd;
-	XStatus status;
-	struct pbuf *p;
-	u32_t freebds;
-	u32_t bdindex;
-	u32 *temp;
-	u32_t index;
+    XEmacPs_Bd *rxbd;
+    XStatus status;
+    struct pbuf *p;
+    u32_t freebds;
+    u32_t bdindex;
+    u32 *temp;
+    u32_t index;
 
-	index = get_base_index_rxpbufsstorage (xemacpsif);
+    index = get_base_index_rxpbufsstorage (xemacpsif);
 
-	freebds = XEmacPs_BdRingGetFreeCnt (rxring);
-	while (freebds > 0) {
-		freebds--;
+    freebds = XEmacPs_BdRingGetFreeCnt (rxring);
+    while (freebds > 0) {
+	    freebds--;
 #ifdef ZYNQMP_USE_JUMBO
-		p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL);
+	    p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL);
 #else
-		p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
+	    p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
 #endif
-		if (!p) {
+	    if (!p) {
 #if LINK_STATS
-			lwip_stats.link.memerr++;
-			lwip_stats.link.drop++;
+		    lwip_stats.link.memerr++;
+		    lwip_stats.link.drop++;
 #endif
-			rt_kprintf("unable to alloc pbuf in recv_handler\r\n");
-			return;
+		    rt_kprintf("unable to alloc pbuf in recv_handler\r\n");
+		    return;
 		}
-		status = XEmacPs_BdRingAlloc(rxring, 1, &rxbd);
-		if (status != XST_SUCCESS) {
-			LWIP_DEBUGF(NETIF_DEBUG, ("setup_rx_bds: Error allocating RxBD\r\n"));
-			pbuf_free(p);
-			return;
+	    status = XEmacPs_BdRingAlloc(rxring, 1, &rxbd);
+	    if (status != XST_SUCCESS) {
+		    LWIP_DEBUGF(NETIF_DEBUG, ("setup_rx_bds: Error allocating RxBD\r\n"));
+		    pbuf_free(p);
+		    return;
 		}
-		status = XEmacPs_BdRingToHw(rxring, 1, rxbd);
-		if (status != XST_SUCCESS) {
-			LWIP_DEBUGF(NETIF_DEBUG, ("Error committing RxBD to hardware: "));
-			if (status == XST_DMA_SG_LIST_ERROR) {
-				LWIP_DEBUGF(NETIF_DEBUG, ("XST_DMA_SG_LIST_ERROR: this function was called out of sequence with XEmacPs_BdRingAlloc()\r\n"));
+	    status = XEmacPs_BdRingToHw(rxring, 1, rxbd);
+	    if (status != XST_SUCCESS) {
+		    LWIP_DEBUGF(NETIF_DEBUG, ("Error committing RxBD to hardware: "));
+		    if (status == XST_DMA_SG_LIST_ERROR) {
+			    LWIP_DEBUGF(NETIF_DEBUG, ("XST_DMA_SG_LIST_ERROR: this function was called out of sequence with XEmacPs_BdRingAlloc()\r\n"));
 			}
-			else {
-				LWIP_DEBUGF(NETIF_DEBUG, ("set of BDs was rejected because the first BD did not have its start-of-packet bit set, or the last BD did not have its end-of-packet bit set, or any one of the BD set has 0 as length value\r\n"));
+		    else {
+			    LWIP_DEBUGF(NETIF_DEBUG, ("set of BDs was rejected because the first BD did not have its start-of-packet bit set, or the last BD did not have its end-of-packet bit set, or any one of the BD set has 0 as length value\r\n"));
 			}
 
-			pbuf_free(p);
-			XEmacPs_BdRingUnAlloc(rxring, 1, rxbd);
-			return;
+		    pbuf_free(p);
+		    XEmacPs_BdRingUnAlloc(rxring, 1, rxbd);
+		    return;
 		}
 #ifdef ZYNQMP_USE_JUMBO
-		if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
-			Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO);
+	    if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+		    Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO);
 		}
 #else
-		if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
-			Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE);
+	    if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+		    Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE);
 		}
 #endif
-		bdindex = XEMACPS_BD_TO_INDEX(rxring, rxbd);
-		temp = (u32 *)rxbd;
-		if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
+	    bdindex = XEMACPS_BD_TO_INDEX(rxring, rxbd);
+	    temp = (u32 *)rxbd;
+	    if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
 			*temp = 0x00000002;
 		} else {
 			*temp = 0;
 		}
-		temp++;
+	    temp++;
 		*temp = 0;
-		dsb();
+	    dsb();
 
-		XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload);
-		rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
+	    XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload);
+	    rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
 	}
 }
 
 void emacps_recv_handler(void *arg)
 {
-	struct pbuf *p;
-	XEmacPs_Bd *rxbdset, *curbdptr;
-	struct xemac_s *xemac;
-	xemacpsif_s *xemacpsif;
-	XEmacPs_BdRing *rxring;
-	volatile s32_t bd_processed;
-	s32_t rx_bytes, k;
-	u32_t bdindex;
-	u32_t regval;
-	u32_t index;
-	u32_t gigeversion;
+    struct pbuf *p;
+    XEmacPs_Bd *rxbdset, *curbdptr;
+    struct xemac_s *xemac;
+    xemacpsif_s *xemacpsif;
+    XEmacPs_BdRing *rxring;
+    volatile s32_t bd_processed;
+    s32_t rx_bytes, k;
+    u32_t bdindex;
+    u32_t regval;
+    u32_t index;
+    u32_t gigeversion;
 
-	xemac = (struct xemac_s *)(arg);
-	xemacpsif = (xemacpsif_s *)(xemac->state);
-	rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps);
+    xemac = (struct xemac_s *)(arg);
+    xemacpsif = (xemacpsif_s *)(xemac->state);
+    rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps);
 
 #ifdef OS_IS_FREERTOS
-	xInsideISR++;
+    xInsideISR++;
 #endif
 
-	gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
-	index = get_base_index_rxpbufsstorage (xemacpsif);
+    gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
+    index = get_base_index_rxpbufsstorage (xemacpsif);
 	/*
 	 * If Reception done interrupt is asserted, call RX call back function
 	 * to handle the processed BDs and then raise the according flag.
 	 */
-	regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET);
-	XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET, regval);
-	if (gigeversion <= 2) {
-			resetrx_on_no_rxdata(xemacpsif);
+    regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET, regval);
+    if (gigeversion <= 2) {
+		    resetrx_on_no_rxdata(xemacpsif);
 	}
 
-	while(1) {
+    while(1) {
 
-		bd_processed = XEmacPs_BdRingFromHwRx(rxring, XLWIP_CONFIG_N_RX_DESC, &rxbdset);
-		if (bd_processed <= 0) {
-			break;
+	    bd_processed = XEmacPs_BdRingFromHwRx(rxring, XLWIP_CONFIG_N_RX_DESC, &rxbdset);
+	    if (bd_processed <= 0) {
+		    break;
 		}
-		for (k = 0, curbdptr=rxbdset; k < bd_processed; k++) {
+	    for (k = 0, curbdptr=rxbdset; k < bd_processed; k++) {
 
-			bdindex = XEMACPS_BD_TO_INDEX(rxring, curbdptr);
-			p = (struct pbuf *)rx_pbufs_storage[index + bdindex];
+		    bdindex = XEMACPS_BD_TO_INDEX(rxring, curbdptr);
+		    p = (struct pbuf *)rx_pbufs_storage[index + bdindex];
 			/*
 			 * Adjust the buffer size to the actual number of bytes received.
 			 */
 #ifdef ZYNQMP_USE_JUMBO
-			rx_bytes = XEmacPs_GetRxFrameSize(&xemacpsif->emacps, curbdptr);
+		    rx_bytes = XEmacPs_GetRxFrameSize(&xemacpsif->emacps, curbdptr);
 #else
-			rx_bytes = XEmacPs_BdGetLength(curbdptr);
+		    rx_bytes = XEmacPs_BdGetLength(curbdptr);
 #endif
-			pbuf_realloc(p, rx_bytes);
+		    pbuf_realloc(p, rx_bytes);
 			/* Invalidate RX frame before queuing to handle
 			 * L1 cache prefetch conditions on any architecture.
 			 */
-			Xil_DCacheInvalidateRange((UINTPTR)p->payload, rx_bytes);
+		    Xil_DCacheInvalidateRange((UINTPTR)p->payload, rx_bytes);
 			/* store it in the receive queue,
 			 * where it'll be processed by a different handler
 			 */
-			if (pq_enqueue(xemacpsif->recv_q, (void*)p) < 0) {
+		    if (pq_enqueue(xemacpsif->recv_q, (void*)p) < 0) {
 #if LINK_STATS
-				lwip_stats.link.memerr++;
-				lwip_stats.link.drop++;
+			    lwip_stats.link.memerr++;
+			    lwip_stats.link.drop++;
 #endif
-				pbuf_free(p);
+			    pbuf_free(p);
 			}
-			curbdptr = XEmacPs_BdRingNext( rxring, curbdptr);
+		    curbdptr = XEmacPs_BdRingNext( rxring, curbdptr);
 		}
 		/* free up the BD's */
-		XEmacPs_BdRingFree(rxring, bd_processed, rxbdset);
-		setup_rx_bds(xemacpsif, rxring);
+	    XEmacPs_BdRingFree(rxring, bd_processed, rxbdset);
+	    setup_rx_bds(xemacpsif, rxring);
 #if 0
-		sys_sem_signal(&xemac->sem_rx_data_available);
+	    sys_sem_signal(&xemac->sem_rx_data_available);
 #else
-		eth_device_ready(xemac->rt_eth_device);
+	    eth_device_ready(xemac->rt_eth_device);
 #endif
 	}
 
 #ifdef OS_IS_FREERTOS
-	xInsideISR--;
+    xInsideISR--;
 #endif
-	return;
+    return;
 }
 
 void clean_dma_txdescs(struct xemac_s *xemac)
 {
-	XEmacPs_Bd bdtemplate;
-	XEmacPs_BdRing *txringptr;
-	xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+    XEmacPs_Bd bdtemplate;
+    XEmacPs_BdRing *txringptr;
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
 
-	txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
+    txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
 
-	XEmacPs_BdClear(&bdtemplate);
-	XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK);
+    XEmacPs_BdClear(&bdtemplate);
+    XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK);
 
 	/*
 	 * Create the TxBD ring
 	 */
-	XEmacPs_BdRingCreate(txringptr, (UINTPTR) xemacpsif->tx_bdspace,
+    XEmacPs_BdRingCreate(txringptr, (UINTPTR) xemacpsif->tx_bdspace,
 			(UINTPTR) xemacpsif->tx_bdspace, BD_ALIGNMENT,
 				 XLWIP_CONFIG_N_TX_DESC);
-	XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND);
+    XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND);
 }
 
 XStatus init_dma(struct xemac_s *xemac)
 {
-	XEmacPs_Bd bdtemplate;
-	XEmacPs_BdRing *rxringptr, *txringptr;
-	XEmacPs_Bd *rxbd;
-	struct pbuf *p;
-	XStatus status;
-	s32_t i;
-	u32_t bdindex;
-	volatile UINTPTR tempaddress;
-	u32_t index;
-	u32_t gigeversion;
-	XEmacPs_Bd *bdtxterminate;
-	XEmacPs_Bd *bdrxterminate;
-	u32 *temp;
+    XEmacPs_Bd bdtemplate;
+    XEmacPs_BdRing *rxringptr, *txringptr;
+    XEmacPs_Bd *rxbd;
+    struct pbuf *p;
+    XStatus status;
+    s32_t i;
+    u32_t bdindex;
+    volatile UINTPTR tempaddress;
+    u32_t index;
+    u32_t gigeversion;
+    XEmacPs_Bd *bdtxterminate;
+    XEmacPs_Bd *bdrxterminate;
+    u32 *temp;
 
-	xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
-	struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+    struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];
 
-	index = get_base_index_rxpbufsstorage (xemacpsif);
-	gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
+    index = get_base_index_rxpbufsstorage (xemacpsif);
+    gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
 	/*
 	 * The BDs need to be allocated in uncached memory. Hence the 1 MB
 	 * address range allocated for Bd_Space is made uncached
@@ -574,47 +574,47 @@ XStatus init_dma(struct xemac_s *xemac)
 	 * The Bd_Space is aligned to 1MB and has a size of 1 MB. This ensures
 	 * a reserved uncached area used only for BDs.
 	 */
-	if (bd_space_attr_set == 0) {
+    if (bd_space_attr_set == 0) {
 #if defined (ARMR5)
-	Xil_SetTlbAttributes((s32_t)bd_space, STRONG_ORDERD_SHARED | PRIV_RW_USER_RW); // addr, attr
+    Xil_SetTlbAttributes((s32_t)bd_space, STRONG_ORDERD_SHARED | PRIV_RW_USER_RW); // addr, attr
 #else
 #if defined __aarch64__
-	Xil_SetTlbAttributes((u64)bd_space, NORM_NONCACHE | INNER_SHAREABLE);
+    Xil_SetTlbAttributes((u64)bd_space, NORM_NONCACHE | INNER_SHAREABLE);
 #else
-	Xil_SetTlbAttributes((s32_t)bd_space, DEVICE_MEMORY); // addr, attr
+    Xil_SetTlbAttributes((s32_t)bd_space, DEVICE_MEMORY); // addr, attr
 #endif
 #endif
-		bd_space_attr_set = 1;
+	    bd_space_attr_set = 1;
 	}
 
-	rxringptr = &XEmacPs_GetRxRing(&xemacpsif->emacps);
-	txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
-	LWIP_DEBUGF(NETIF_DEBUG, ("rxringptr: 0x%08x\r\n", rxringptr));
-	LWIP_DEBUGF(NETIF_DEBUG, ("txringptr: 0x%08x\r\n", txringptr));
+    rxringptr = &XEmacPs_GetRxRing(&xemacpsif->emacps);
+    txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
+    LWIP_DEBUGF(NETIF_DEBUG, ("rxringptr: 0x%08x\r\n", rxringptr));
+    LWIP_DEBUGF(NETIF_DEBUG, ("txringptr: 0x%08x\r\n", txringptr));
 
 	/* Allocate 64k for Rx and Tx bds each to take care of extreme cases */
-	tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
-	xemacpsif->rx_bdspace = (void *)tempaddress;
-	bd_space_index += 0x10000;
-	tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
-	xemacpsif->tx_bdspace = (void *)tempaddress;
-	bd_space_index += 0x10000;
-	if (gigeversion > 2) {
-		tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
-		bdrxterminate = (XEmacPs_Bd *)tempaddress;
-		bd_space_index += 0x10000;
-		tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
-		bdtxterminate = (XEmacPs_Bd *)tempaddress;
-		bd_space_index += 0x10000;
+    tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
+    xemacpsif->rx_bdspace = (void *)tempaddress;
+    bd_space_index += 0x10000;
+    tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
+    xemacpsif->tx_bdspace = (void *)tempaddress;
+    bd_space_index += 0x10000;
+    if (gigeversion > 2) {
+	    tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
+	    bdrxterminate = (XEmacPs_Bd *)tempaddress;
+	    bd_space_index += 0x10000;
+	    tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
+	    bdtxterminate = (XEmacPs_Bd *)tempaddress;
+	    bd_space_index += 0x10000;
 	}
 
-	LWIP_DEBUGF(NETIF_DEBUG, ("rx_bdspace: %p \r\n", xemacpsif->rx_bdspace));
-	LWIP_DEBUGF(NETIF_DEBUG, ("tx_bdspace: %p \r\n", xemacpsif->tx_bdspace));
+    LWIP_DEBUGF(NETIF_DEBUG, ("rx_bdspace: %p \r\n", xemacpsif->rx_bdspace));
+    LWIP_DEBUGF(NETIF_DEBUG, ("tx_bdspace: %p \r\n", xemacpsif->tx_bdspace));
 
-	if (!xemacpsif->rx_bdspace || !xemacpsif->tx_bdspace) {
-		xil_printf("%s@%d: Error: Unable to allocate memory for TX/RX buffer descriptors",
-				__FILE__, __LINE__);
-		return ERR_IF;
+    if (!xemacpsif->rx_bdspace || !xemacpsif->tx_bdspace) {
+	    xil_printf("%s@%d: Error: Unable to allocate memory for TX/RX buffer descriptors",
+			    __FILE__, __LINE__);
+	    return ERR_IF;
 	}
 
 	/*
@@ -623,107 +623,107 @@ XStatus init_dma(struct xemac_s *xemac)
 	 * Setup a BD template for the Rx channel. This template will be copied to
 	 * every RxBD. We will not have to explicitly set these again.
 	 */
-	XEmacPs_BdClear(&bdtemplate);
+    XEmacPs_BdClear(&bdtemplate);
 
 	/*
 	 * Create the RxBD ring
 	 */
 
-	status = XEmacPs_BdRingCreate(rxringptr, (UINTPTR) xemacpsif->rx_bdspace,
+    status = XEmacPs_BdRingCreate(rxringptr, (UINTPTR) xemacpsif->rx_bdspace,
 				(UINTPTR) xemacpsif->rx_bdspace, BD_ALIGNMENT,
 				     XLWIP_CONFIG_N_RX_DESC);
 
-	if (status != XST_SUCCESS) {
-		LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space\r\n"));
-		return ERR_IF;
+    if (status != XST_SUCCESS) {
+	    LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space\r\n"));
+	    return ERR_IF;
 	}
 
-	status = XEmacPs_BdRingClone(rxringptr, &bdtemplate, XEMACPS_RECV);
-	if (status != XST_SUCCESS) {
-		LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space\r\n"));
-		return ERR_IF;
+    status = XEmacPs_BdRingClone(rxringptr, &bdtemplate, XEMACPS_RECV);
+    if (status != XST_SUCCESS) {
+	    LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space\r\n"));
+	    return ERR_IF;
 	}
 
-	XEmacPs_BdClear(&bdtemplate);
-	XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK);
+    XEmacPs_BdClear(&bdtemplate);
+    XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK);
 	/*
 	 * Create the TxBD ring
 	 */
-	status = XEmacPs_BdRingCreate(txringptr, (UINTPTR) xemacpsif->tx_bdspace,
+    status = XEmacPs_BdRingCreate(txringptr, (UINTPTR) xemacpsif->tx_bdspace,
 				(UINTPTR) xemacpsif->tx_bdspace, BD_ALIGNMENT,
 				     XLWIP_CONFIG_N_TX_DESC);
 
-	if (status != XST_SUCCESS) {
-		return ERR_IF;
+    if (status != XST_SUCCESS) {
+	    return ERR_IF;
 	}
 
 	/* We reuse the bd template, as the same one will work for both rx and tx. */
-	status = XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND);
-	if (status != XST_SUCCESS) {
-		return ERR_IF;
+    status = XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND);
+    if (status != XST_SUCCESS) {
+	    return ERR_IF;
 	}
 
 	/*
 	 * Allocate RX descriptors, 1 RxBD at a time.
 	 */
-	for (i = 0; i < XLWIP_CONFIG_N_RX_DESC; i++) {
+    for (i = 0; i < XLWIP_CONFIG_N_RX_DESC; i++) {
 #ifdef ZYNQMP_USE_JUMBO
-		p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL);
+	    p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL);
 #else
-		p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
+	    p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
 #endif
-		if (!p) {
+	    if (!p) {
 #if LINK_STATS
-			lwip_stats.link.memerr++;
-			lwip_stats.link.drop++;
+		    lwip_stats.link.memerr++;
+		    lwip_stats.link.drop++;
 #endif
-			rt_kprintf("unable to alloc pbuf in init_dma\r\n");
-			return ERR_IF;
+		    rt_kprintf("unable to alloc pbuf in init_dma\r\n");
+		    return ERR_IF;
 		}
-		status = XEmacPs_BdRingAlloc(rxringptr, 1, &rxbd);
-		if (status != XST_SUCCESS) {
-			LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n"));
-			pbuf_free(p);
-			return ERR_IF;
+	    status = XEmacPs_BdRingAlloc(rxringptr, 1, &rxbd);
+	    if (status != XST_SUCCESS) {
+		    LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n"));
+		    pbuf_free(p);
+		    return ERR_IF;
 		}
 		/* Enqueue to HW */
-		status = XEmacPs_BdRingToHw(rxringptr, 1, rxbd);
-		if (status != XST_SUCCESS) {
-			LWIP_DEBUGF(NETIF_DEBUG, ("Error: committing RxBD to HW\r\n"));
-			pbuf_free(p);
-			XEmacPs_BdRingUnAlloc(rxringptr, 1, rxbd);
-			return ERR_IF;
+	    status = XEmacPs_BdRingToHw(rxringptr, 1, rxbd);
+	    if (status != XST_SUCCESS) {
+		    LWIP_DEBUGF(NETIF_DEBUG, ("Error: committing RxBD to HW\r\n"));
+		    pbuf_free(p);
+		    XEmacPs_BdRingUnAlloc(rxringptr, 1, rxbd);
+		    return ERR_IF;
 		}
 
-		bdindex = XEMACPS_BD_TO_INDEX(rxringptr, rxbd);
-		temp = (u32 *)rxbd;
+	    bdindex = XEMACPS_BD_TO_INDEX(rxringptr, rxbd);
+	    temp = (u32 *)rxbd;
 		*temp = 0;
-		if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
+	    if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
 			*temp = 0x00000002;
 		}
-		temp++;
+	    temp++;
 		*temp = 0;
-		dsb();
+	    dsb();
 #ifdef ZYNQMP_USE_JUMBO
-		if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
-			Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO);
+	    if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+		    Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO);
 		}
 #else
-		if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
-			Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE);
+	    if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+		    Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE);
 		}
 #endif
-		XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload);
+	    XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload);
 
-		rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
+	    rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
 	}
-	XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.RxBdRing.BaseBdAddr, 0, XEMACPS_RECV);
-	if (gigeversion > 2) {
-		XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 1, XEMACPS_SEND);
+    XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.RxBdRing.BaseBdAddr, 0, XEMACPS_RECV);
+    if (gigeversion > 2) {
+	    XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 1, XEMACPS_SEND);
 	}else {
-		XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 0, XEMACPS_SEND);
+	    XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 0, XEMACPS_SEND);
 	}
-	if (gigeversion > 2)
+    if (gigeversion > 2)
 	{
 		/*
 		 * This version of GEM supports priority queuing and the current
@@ -733,15 +733,15 @@ XStatus init_dma(struct xemac_s *xemac)
 		 * the controller to malfunction by fetching the descriptors
 		 * from these queues.
 		 */
-		XEmacPs_BdClear(bdrxterminate);
-		XEmacPs_BdSetAddressRx(bdrxterminate, (XEMACPS_RXBUF_NEW_MASK |
-						XEMACPS_RXBUF_WRAP_MASK));
-		XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_RXQ1BASE_OFFSET),
+	    XEmacPs_BdClear(bdrxterminate);
+	    XEmacPs_BdSetAddressRx(bdrxterminate, (XEMACPS_RXBUF_NEW_MASK |
+					    XEMACPS_RXBUF_WRAP_MASK));
+	    XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_RXQ1BASE_OFFSET),
 				   (UINTPTR)bdrxterminate);
-		XEmacPs_BdClear(bdtxterminate);
-		XEmacPs_BdSetStatus(bdtxterminate, (XEMACPS_TXBUF_USED_MASK |
-						XEMACPS_TXBUF_WRAP_MASK));
-		XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_TXQBASE_OFFSET),
+	    XEmacPs_BdClear(bdtxterminate);
+	    XEmacPs_BdSetStatus(bdtxterminate, (XEMACPS_TXBUF_USED_MASK |
+					    XEMACPS_TXBUF_WRAP_MASK));
+	    XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_TXQBASE_OFFSET),
 				   (UINTPTR)bdtxterminate);
 	}
 
@@ -757,8 +757,8 @@ XStatus init_dma(struct xemac_s *xemac)
 	 * Enable the interrupt for emacps.
 	 */
 	// XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, (u32) xtopologyp->scugic_emac_intr);
-	emac_intr_num = (u32) xtopologyp->scugic_emac_intr;
-	return 0;
+    emac_intr_num = (u32) xtopologyp->scugic_emac_intr;
+    return 0;
 }
 
 /*
@@ -777,62 +777,62 @@ XStatus init_dma(struct xemac_s *xemac)
 
 void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)
 {
-	u32_t regctrl;
-	u32_t tempcntr;
-	u32_t gigeversion;
+    u32_t regctrl;
+    u32_t tempcntr;
+    u32_t gigeversion;
 
-	gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
-	if (gigeversion == 2) {
-		tempcntr = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET);
-		if ((!tempcntr) && (!(xemacpsif->last_rx_frms_cntr))) {
-			regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-					XEMACPS_NWCTRL_OFFSET);
-			regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
-			XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-					XEMACPS_NWCTRL_OFFSET, regctrl);
-			regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
-			regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
-			XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
+    gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
+    if (gigeversion == 2) {
+	    tempcntr = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET);
+	    if ((!tempcntr) && (!(xemacpsif->last_rx_frms_cntr))) {
+		    regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+				    XEMACPS_NWCTRL_OFFSET);
+		    regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
+		    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+				    XEMACPS_NWCTRL_OFFSET, regctrl);
+		    regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
+		    regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
+		    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
 		}
-		xemacpsif->last_rx_frms_cntr = tempcntr;
+	    xemacpsif->last_rx_frms_cntr = tempcntr;
 	}
 }
 
 void free_txrx_pbufs(xemacpsif_s *xemacpsif)
 {
-	s32_t index;
-	s32_t index1;
-	struct pbuf *p;
+    s32_t index;
+    s32_t index1;
+    struct pbuf *p;
 
-	index1 = get_base_index_txpbufsstorage (xemacpsif);
+    index1 = get_base_index_txpbufsstorage (xemacpsif);
 
-	for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
-		if (tx_pbufs_storage[index] != 0) {
-			p = (struct pbuf *)tx_pbufs_storage[index];
-			pbuf_free(p);
-			tx_pbufs_storage[index] = 0;
+    for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
+	    if (tx_pbufs_storage[index] != 0) {
+		    p = (struct pbuf *)tx_pbufs_storage[index];
+		    pbuf_free(p);
+		    tx_pbufs_storage[index] = 0;
 		}
 	}
 
-	for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
-		p = (struct pbuf *)rx_pbufs_storage[index];
-		pbuf_free(p);
+    for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
+	    p = (struct pbuf *)rx_pbufs_storage[index];
+	    pbuf_free(p);
 
 	}
 }
 
 void free_onlytx_pbufs(xemacpsif_s *xemacpsif)
 {
-	s32_t index;
-	s32_t index1;
-	struct pbuf *p;
+    s32_t index;
+    s32_t index1;
+    struct pbuf *p;
 
-	index1 = get_base_index_txpbufsstorage (xemacpsif);
-	for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
-		if (tx_pbufs_storage[index] != 0) {
-			p = (struct pbuf *)tx_pbufs_storage[index];
-			pbuf_free(p);
-			tx_pbufs_storage[index] = 0;
+    index1 = get_base_index_txpbufsstorage (xemacpsif);
+    for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
+	    if (tx_pbufs_storage[index] != 0) {
+		    p = (struct pbuf *)tx_pbufs_storage[index];
+		    pbuf_free(p);
+		    tx_pbufs_storage[index] = 0;
 		}
 	}
 }
@@ -840,34 +840,34 @@ void free_onlytx_pbufs(xemacpsif_s *xemacpsif)
 /* reset Tx and Rx DMA pointers after XEmacPs_Stop */
 void reset_dma(struct xemac_s *xemac)
 {
-	u8 txqueuenum;
-	u32_t gigeversion;
-	xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
-	XEmacPs_BdRing *txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
-	XEmacPs_BdRing *rxringptr = &XEmacPs_GetRxRing(&xemacpsif->emacps);
+    u8 txqueuenum;
+    u32_t gigeversion;
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+    XEmacPs_BdRing *txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
+    XEmacPs_BdRing *rxringptr = &XEmacPs_GetRxRing(&xemacpsif->emacps);
 
-	XEmacPs_BdRingPtrReset(txringptr, xemacpsif->tx_bdspace);
-	XEmacPs_BdRingPtrReset(rxringptr, xemacpsif->rx_bdspace);
+    XEmacPs_BdRingPtrReset(txringptr, xemacpsif->tx_bdspace);
+    XEmacPs_BdRingPtrReset(rxringptr, xemacpsif->rx_bdspace);
 
-	gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
-	if (gigeversion > 2) {
-		txqueuenum = 1;
+    gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
+    if (gigeversion > 2) {
+	    txqueuenum = 1;
 	} else {
-		txqueuenum = 0;
+	    txqueuenum = 0;
 	}
 
-	XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.RxBdRing.BaseBdAddr, 0, XEMACPS_RECV);
-	XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, txqueuenum, XEMACPS_SEND);
+    XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.RxBdRing.BaseBdAddr, 0, XEMACPS_RECV);
+    XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, txqueuenum, XEMACPS_SEND);
 }
 
 void emac_disable_intr(void)
 {
 	// XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, emac_intr_num);
-	rt_hw_interrupt_mask(emac_intr_num);
+    rt_hw_interrupt_mask(emac_intr_num);
 }
 
 void emac_enable_intr(void)
 {
 	// XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, emac_intr_num);
-	rt_hw_interrupt_umask(emac_intr_num);
+    rt_hw_interrupt_umask(emac_intr_num);
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c
index a1bef1faa1..bf100119d8 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c
@@ -32,7 +32,7 @@
 #include "lwipopts.h"
 
 #if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
-	XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
+    XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
 #define PCM_PMA_CORE_PRESENT
 #else
 #undef PCM_PMA_CORE_PRESENT
@@ -51,44 +51,44 @@ extern long xInsideISR;
 
 XEmacPs_Config *xemacps_lookup_config(unsigned mac_base)
 {
-	XEmacPs_Config *cfgptr = NULL;
-	s32_t i;
+    XEmacPs_Config *cfgptr = NULL;
+    s32_t i;
 
-	for (i = 0; i < XPAR_XEMACPS_NUM_INSTANCES; i++) {
-		if (XEmacPs_ConfigTable[i].BaseAddress == mac_base) {
-			cfgptr = &XEmacPs_ConfigTable[i];
-			break;
+    for (i = 0; i < XPAR_XEMACPS_NUM_INSTANCES; i++) {
+	    if (XEmacPs_ConfigTable[i].BaseAddress == mac_base) {
+		    cfgptr = &XEmacPs_ConfigTable[i];
+		    break;
 		}
 	}
 
-	return (cfgptr);
+    return (cfgptr);
 }
 
 void init_emacps(xemacpsif_s *xemacps, struct netif *netif)
 {
-	XEmacPs *xemacpsp;
-	s32_t status = XST_SUCCESS;
-	u32_t i;
-	u32_t phyfoundforemac0 = FALSE;
-	u32_t phyfoundforemac1 = FALSE;
+    XEmacPs *xemacpsp;
+    s32_t status = XST_SUCCESS;
+    u32_t i;
+    u32_t phyfoundforemac0 = FALSE;
+    u32_t phyfoundforemac1 = FALSE;
 
-	xemacpsp = &xemacps->emacps;
+    xemacpsp = &xemacps->emacps;
 
 #ifdef ZYNQMP_USE_JUMBO
-	XEmacPs_SetOptions(xemacpsp, XEMACPS_JUMBO_ENABLE_OPTION);
+    XEmacPs_SetOptions(xemacpsp, XEMACPS_JUMBO_ENABLE_OPTION);
 #endif
 
 #ifdef LWIP_IGMP
-	XEmacPs_SetOptions(xemacpsp, XEMACPS_MULTICAST_OPTION);
+    XEmacPs_SetOptions(xemacpsp, XEMACPS_MULTICAST_OPTION);
 #endif
 
 	/* set mac address */
-	status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
-	if (status != XST_SUCCESS) {
-		xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
+    status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
+    if (status != XST_SUCCESS) {
+	    xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
 	}
 
-	XEmacPs_SetMdioDivisor(xemacpsp, MDC_DIV_224);
+    XEmacPs_SetMdioDivisor(xemacpsp, MDC_DIV_224);
 
 /*  Please refer to file header comments for the file xemacpsif_physpeed.c
  *  to know more about the PHY programming sequence.
@@ -102,92 +102,92 @@ void init_emacps(xemacpsif_s *xemacps, struct netif *netif)
  */
 #ifdef PCM_PMA_CORE_PRESENT
 #ifdef  XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT
-	link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_1000BASEX_PHYADDR);
+    link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_1000BASEX_PHYADDR);
 #elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT
-	link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_SGMII_PHYADDR);
+    link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_SGMII_PHYADDR);
 #endif
 #else
-	detect_phy(xemacpsp);
-	for (i = 31; i > 0; i--) {
-		if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
-			if (phymapemac0[i] == TRUE) {
-				link_speed = phy_setup_emacps(xemacpsp, i);
-				phyfoundforemac0 = TRUE;
-				phyaddrforemac = i;
+    detect_phy(xemacpsp);
+    for (i = 31; i > 0; i--) {
+	    if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
+		    if (phymapemac0[i] == TRUE) {
+			    link_speed = phy_setup_emacps(xemacpsp, i);
+			    phyfoundforemac0 = TRUE;
+			    phyaddrforemac = i;
 			}
 		} else {
-			if (phymapemac1[i] == TRUE) {
-				link_speed = phy_setup_emacps(xemacpsp, i);
-				phyfoundforemac1 = TRUE;
-				phyaddrforemac = i;
+		    if (phymapemac1[i] == TRUE) {
+			    link_speed = phy_setup_emacps(xemacpsp, i);
+			    phyfoundforemac1 = TRUE;
+			    phyaddrforemac = i;
 			}
 		}
 	}
 	/* If no PHY was detected, use broadcast PHY address of 0 */
-	if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
-		if (phyfoundforemac0 == FALSE)
-			link_speed = phy_setup_emacps(xemacpsp, 0);
+    if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
+	    if (phyfoundforemac0 == FALSE)
+		    link_speed = phy_setup_emacps(xemacpsp, 0);
 	} else {
-		if (phyfoundforemac1 == FALSE)
-			link_speed = phy_setup_emacps(xemacpsp, 0);
+	    if (phyfoundforemac1 == FALSE)
+		    link_speed = phy_setup_emacps(xemacpsp, 0);
 	}
 #endif
 
-	if (link_speed == XST_FAILURE) {
-		eth_link_status = ETH_LINK_DOWN;
-		xil_printf("Phy setup failure %s \n\r",__func__);
-		return;
+    if (link_speed == XST_FAILURE) {
+	    eth_link_status = ETH_LINK_DOWN;
+	    xil_printf("Phy setup failure %s \n\r",__func__);
+	    return;
 	} else {
-		eth_link_status = ETH_LINK_UP;
+	    eth_link_status = ETH_LINK_UP;
 	}
 
-	XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
+    XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
 	/* Setting the operating speed of the MAC needs a delay. */
 	{
-		volatile s32_t wait;
-		for (wait=0; wait < 20000; wait++);
+	    volatile s32_t wait;
+	    for (wait=0; wait < 20000; wait++);
 	}
 }
 
 void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif)
 {
-	XEmacPs *xemacpsp;
-	s32_t status = XST_SUCCESS;
+    XEmacPs *xemacpsp;
+    s32_t status = XST_SUCCESS;
 
-	xemacpsp = &xemacps->emacps;
+    xemacpsp = &xemacps->emacps;
 
 	/* set mac address */
-	status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
-	if (status != XST_SUCCESS) {
-		xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
+    status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
+    if (status != XST_SUCCESS) {
+	    xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
 	}
 
-	XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
+    XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
 
 	/* Setting the operating speed of the MAC needs a delay. */
 	{
-		volatile s32_t wait;
-		for (wait=0; wait < 20000; wait++);
+	    volatile s32_t wait;
+	    for (wait=0; wait < 20000; wait++);
 	}
 }
 
 void setup_isr (struct xemac_s *xemac)
 {
-	xemacpsif_s   *xemacpsif;
+    xemacpsif_s   *xemacpsif;
 
-	xemacpsif = (xemacpsif_s *)(xemac->state);
+    xemacpsif = (xemacpsif_s *)(xemac->state);
 	/*
 	 * Setup callbacks
 	 */
-	XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
+    XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
 				     (void *) emacps_send_handler,
 				     (void *) xemac);
 
-	XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
+    XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
 				    (void *) emacps_recv_handler,
 				    (void *) xemac);
 
-	XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
+    XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
 				    (void *) emacps_error_handler,
 				    (void *) xemac);
 }
@@ -195,82 +195,82 @@ void setup_isr (struct xemac_s *xemac)
 void start_emacps (xemacpsif_s *xemacps)
 {
 	/* start the temac */
-	XEmacPs_Start(&xemacps->emacps);
+    XEmacPs_Start(&xemacps->emacps);
 }
 
 void restart_emacps_transmitter (xemacpsif_s *xemacps) {
-	u32_t Reg;
-	Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
-					XEMACPS_NWCTRL_OFFSET);
-	Reg = Reg & (~XEMACPS_NWCTRL_TXEN_MASK);
-	XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
-										XEMACPS_NWCTRL_OFFSET, Reg);
+    u32_t Reg;
+    Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
+				    XEMACPS_NWCTRL_OFFSET);
+    Reg = Reg & (~XEMACPS_NWCTRL_TXEN_MASK);
+    XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
+									    XEMACPS_NWCTRL_OFFSET, Reg);
 
-	Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
-						XEMACPS_NWCTRL_OFFSET);
-	Reg = Reg | (XEMACPS_NWCTRL_TXEN_MASK);
-	XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
-										XEMACPS_NWCTRL_OFFSET, Reg);
+    Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
+					    XEMACPS_NWCTRL_OFFSET);
+    Reg = Reg | (XEMACPS_NWCTRL_TXEN_MASK);
+    XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
+									    XEMACPS_NWCTRL_OFFSET, Reg);
 }
 
 void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord)
 {
-	struct xemac_s *xemac;
-	xemacpsif_s   *xemacpsif;
-	XEmacPs_BdRing *rxring;
-	XEmacPs_BdRing *txring;
+    struct xemac_s *xemac;
+    xemacpsif_s   *xemacpsif;
+    XEmacPs_BdRing *rxring;
+    XEmacPs_BdRing *txring;
 #ifdef OS_IS_FREERTOS
-	xInsideISR++;
+    xInsideISR++;
 #endif
 
-	xemac = (struct xemac_s *)(arg);
-	xemacpsif = (xemacpsif_s *)(xemac->state);
-	rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps);
-	txring = &XEmacPs_GetTxRing(&xemacpsif->emacps);
+    xemac = (struct xemac_s *)(arg);
+    xemacpsif = (xemacpsif_s *)(xemac->state);
+    rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps);
+    txring = &XEmacPs_GetTxRing(&xemacpsif->emacps);
 
-	if (ErrorWord != 0) {
-		switch (Direction) {
-			case XEMACPS_RECV:
-			if (ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK) {
-				LWIP_DEBUGF(NETIF_DEBUG, ("Receive DMA error\r\n"));
-				HandleEmacPsError(xemac);
+    if (ErrorWord != 0) {
+	    switch (Direction) {
+		    case XEMACPS_RECV:
+		    if (ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK) {
+			    LWIP_DEBUGF(NETIF_DEBUG, ("Receive DMA error\r\n"));
+			    HandleEmacPsError(xemac);
 			}
-			if (ErrorWord & XEMACPS_RXSR_RXOVR_MASK) {
-				LWIP_DEBUGF(NETIF_DEBUG, ("Receive over run\r\n"));
-				emacps_recv_handler(arg);
-				setup_rx_bds(xemacpsif, rxring);
+		    if (ErrorWord & XEMACPS_RXSR_RXOVR_MASK) {
+			    LWIP_DEBUGF(NETIF_DEBUG, ("Receive over run\r\n"));
+			    emacps_recv_handler(arg);
+			    setup_rx_bds(xemacpsif, rxring);
 			}
-			if (ErrorWord & XEMACPS_RXSR_BUFFNA_MASK) {
-				LWIP_DEBUGF(NETIF_DEBUG, ("Receive buffer not available\r\n"));
-				emacps_recv_handler(arg);
-				setup_rx_bds(xemacpsif, rxring);
+		    if (ErrorWord & XEMACPS_RXSR_BUFFNA_MASK) {
+			    LWIP_DEBUGF(NETIF_DEBUG, ("Receive buffer not available\r\n"));
+			    emacps_recv_handler(arg);
+			    setup_rx_bds(xemacpsif, rxring);
 			}
-			break;
-			case XEMACPS_SEND:
-			if (ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK) {
-				LWIP_DEBUGF(NETIF_DEBUG, ("Transmit DMA error\r\n"));
-				HandleEmacPsError(xemac);
+		    break;
+		    case XEMACPS_SEND:
+		    if (ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK) {
+			    LWIP_DEBUGF(NETIF_DEBUG, ("Transmit DMA error\r\n"));
+			    HandleEmacPsError(xemac);
 			}
-			if (ErrorWord & XEMACPS_TXSR_URUN_MASK) {
-				LWIP_DEBUGF(NETIF_DEBUG, ("Transmit under run\r\n"));
-				HandleTxErrors(xemac);
+		    if (ErrorWord & XEMACPS_TXSR_URUN_MASK) {
+			    LWIP_DEBUGF(NETIF_DEBUG, ("Transmit under run\r\n"));
+			    HandleTxErrors(xemac);
 			}
-			if (ErrorWord & XEMACPS_TXSR_BUFEXH_MASK) {
-				LWIP_DEBUGF(NETIF_DEBUG, ("Transmit buffer exhausted\r\n"));
-				HandleTxErrors(xemac);
+		    if (ErrorWord & XEMACPS_TXSR_BUFEXH_MASK) {
+			    LWIP_DEBUGF(NETIF_DEBUG, ("Transmit buffer exhausted\r\n"));
+			    HandleTxErrors(xemac);
 			}
-			if (ErrorWord & XEMACPS_TXSR_RXOVR_MASK) {
-				LWIP_DEBUGF(NETIF_DEBUG, ("Transmit retry excessed limits\r\n"));
-				HandleTxErrors(xemac);
+		    if (ErrorWord & XEMACPS_TXSR_RXOVR_MASK) {
+			    LWIP_DEBUGF(NETIF_DEBUG, ("Transmit retry excessed limits\r\n"));
+			    HandleTxErrors(xemac);
 			}
-			if (ErrorWord & XEMACPS_TXSR_FRAMERX_MASK) {
-				LWIP_DEBUGF(NETIF_DEBUG, ("Transmit collision\r\n"));
+		    if (ErrorWord & XEMACPS_TXSR_FRAMERX_MASK) {
+			    LWIP_DEBUGF(NETIF_DEBUG, ("Transmit collision\r\n"));
 				// process_sent_bds(xemacpsif, txring);
 			}
-			break;
+		    break;
 		}
 	}
 #ifdef OS_IS_FREERTOS
-	xInsideISR--;
+    xInsideISR--;
 #endif
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c
index 9113e3fecb..2e0a4039bd 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c
@@ -119,50 +119,50 @@
 
 #define CONFIG_LINKSPEED_AUTODETECT 1
 
-#define PHY_DETECT_REG  						1
-#define PHY_IDENTIFIER_1_REG					2
-#define PHY_IDENTIFIER_2_REG					3
-#define PHY_DETECT_MASK 					0x1808
-#define PHY_MARVELL_IDENTIFIER				0x0141
-#define PHY_TI_IDENTIFIER					0x2000
-#define PHY_REALTEK_IDENTIFIER				0x001c
-#define PHY_XILINX_PCS_PMA_ID1			0x0174
-#define PHY_XILINX_PCS_PMA_ID2			0x0C00
+#define PHY_DETECT_REG  					    1
+#define PHY_IDENTIFIER_1_REG				    2
+#define PHY_IDENTIFIER_2_REG				    3
+#define PHY_DETECT_MASK 				    0x1808
+#define PHY_MARVELL_IDENTIFIER			    0x0141
+#define PHY_TI_IDENTIFIER				    0x2000
+#define PHY_REALTEK_IDENTIFIER			    0x001c
+#define PHY_XILINX_PCS_PMA_ID1		    0x0174
+#define PHY_XILINX_PCS_PMA_ID2		    0x0C00
 
-#define XEMACPS_GMII2RGMII_SPEED1000_FD		0x140
-#define XEMACPS_GMII2RGMII_SPEED100_FD		0x2100
-#define XEMACPS_GMII2RGMII_SPEED10_FD		0x100
-#define XEMACPS_GMII2RGMII_REG_NUM			0x10
+#define XEMACPS_GMII2RGMII_SPEED1000_FD	    0x140
+#define XEMACPS_GMII2RGMII_SPEED100_FD	    0x2100
+#define XEMACPS_GMII2RGMII_SPEED10_FD	    0x100
+#define XEMACPS_GMII2RGMII_REG_NUM		    0x10
 
-#define PHY_REGCR		0x0D
-#define PHY_ADDAR		0x0E
-#define PHY_RGMIIDCTL	0x86
-#define PHY_RGMIICTL	0x32
-#define PHY_STS			0x11
-#define PHY_TI_CR		0x10
-#define PHY_TI_CFG4		0x31
+#define PHY_REGCR	    0x0D
+#define PHY_ADDAR	    0x0E
+#define PHY_RGMIIDCTL    0x86
+#define PHY_RGMIICTL    0x32
+#define PHY_STS		    0x11
+#define PHY_TI_CR	    0x10
+#define PHY_TI_CFG4	    0x31
 
-#define MICREL_PHY_IDENTIFIER				0x22
-#define MICREL_PHY_KSZ9031_MODEL			0x220
+#define MICREL_PHY_IDENTIFIER			    0x22
+#define MICREL_PHY_KSZ9031_MODEL		    0x220
 
-#define PHY_REGCR_ADDR	0x001F
-#define PHY_REGCR_DATA	0x401F
-#define PHY_TI_CRVAL	0x5048
-#define PHY_TI_CFG4RESVDBIT7	0x80
+#define PHY_REGCR_ADDR    0x001F
+#define PHY_REGCR_DATA    0x401F
+#define PHY_TI_CRVAL    0x5048
+#define PHY_TI_CFG4RESVDBIT7    0x80
 
 /* Frequency setting */
 #define SLCR_LOCK_ADDR			(XPS_SYS_CTRL_BASEADDR + 0x4)
 #define SLCR_UNLOCK_ADDR		(XPS_SYS_CTRL_BASEADDR + 0x8)
 #define SLCR_GEM0_CLK_CTRL_ADDR	(XPS_SYS_CTRL_BASEADDR + 0x140)
 #define SLCR_GEM1_CLK_CTRL_ADDR	(XPS_SYS_CTRL_BASEADDR + 0x144)
-#define SLCR_GEM_SRCSEL_EMIO	0x40
-#define SLCR_LOCK_KEY_VALUE 	0x767B
-#define SLCR_UNLOCK_KEY_VALUE	0xDF0D
+#define SLCR_GEM_SRCSEL_EMIO    0x40
+#define SLCR_LOCK_KEY_VALUE     0x767B
+#define SLCR_UNLOCK_KEY_VALUE    0xDF0D
 #define SLCR_ADDR_GEM_RST_CTRL	(XPS_SYS_CTRL_BASEADDR + 0x214)
-#define EMACPS_SLCR_DIV_MASK	0xFC0FC0FF
+#define EMACPS_SLCR_DIV_MASK    0xFC0FC0FF
 
 #if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
-	XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
+    XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
 #define PCM_PMA_CORE_PRESENT
 #else
 #undef PCM_PMA_CORE_PRESENT
@@ -188,96 +188,96 @@ static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t s
 #ifdef PCM_PMA_CORE_PRESENT
 u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr)
 {
-	u32_t link_speed;
-	u16_t regval;
-	u16_t phy_id;
+    u32_t link_speed;
+    u16_t regval;
+    u16_t phy_id;
 
-	if(phy_addr == 0) {
-		for (phy_addr = 31; phy_addr > 0; phy_addr--) {
-			XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
+    if(phy_addr == 0) {
+	    for (phy_addr = 31; phy_addr > 0; phy_addr--) {
+		    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
 					&phy_id);
 
-			if (phy_id == PHY_XILINX_PCS_PMA_ID1) {
-				XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_2_REG,
+		    if (phy_id == PHY_XILINX_PCS_PMA_ID1) {
+			    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_2_REG,
 						&phy_id);
-				if (phy_id == PHY_XILINX_PCS_PMA_ID2) {
+			    if (phy_id == PHY_XILINX_PCS_PMA_ID2) {
 					/* Found a valid PHY address */
-					LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
-							phy_addr));
-					break;
+				    LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
+						    phy_addr));
+				    break;
 				}
 			}
 		}
 	}
 
-	link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr);
-	if (link_speed == 1000)
-		SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
-	else if (link_speed == 100)
-		SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
-	else
-		SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
+    link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr);
+    if (link_speed == 1000)
+	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
+    else if (link_speed == 100)
+	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
+    else
+	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
 
-	xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed);
-	return link_speed;
+    xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed);
+    return link_speed;
 }
 
 static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
 {
-	u16_t temp;
-	u16_t control;
-	u16_t status;
-	u16_t partner_capabilities;
+    u16_t temp;
+    u16_t control;
+    u16_t status;
+    u16_t partner_capabilities;
 
-	xil_printf("Start PHY autonegotiation \r\n");
+    xil_printf("Start PHY autonegotiation \r\n");
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
-	control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
-	control &= IEEE_CTRL_ISOLATE_DISABLE;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+    control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+    control &= IEEE_CTRL_ISOLATE_DISABLE;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
 
-	xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
+    xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-	while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
-		sleep(1);
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
+	    sleep(1);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
 																&status);
 	}
-	xil_printf("autonegotiation complete \r\n");
+    xil_printf("autonegotiation complete \r\n");
 
 #if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 1);
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
-	if ((temp & 0x0020) == 0x0020) {
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-		return 1000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 1);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
+    if ((temp & 0x0020) == 0x0020) {
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+	    return 1000;
 	}
-	else {
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-		xil_printf("Link error, temp = %x\r\n", temp);
-		return 0;
+    else {
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+	    xil_printf("Link error, temp = %x\r\n", temp);
+	    return 0;
 	}
 #elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
-	xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
-	while(!(temp & 0x8000)) {
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
+    xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
+    while(!(temp & 0x8000)) {
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
 	}
-	if((temp & 0x0C00) == 0x0800) {
-		return 1000;
+    if((temp & 0x0C00) == 0x0800) {
+	    return 1000;
 	}
-	else if((temp & 0x0C00) == 0x0400) {
-		return 100;
+    else if((temp & 0x0C00) == 0x0400) {
+	    return 100;
 	}
-	else if((temp & 0x0C00) == 0x0000) {
-		return 10;
+    else if((temp & 0x0C00) == 0x0000) {
+	    return 10;
 	} else {
-		xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Defaulting to Speed = 10 Mbps\r\n");
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &temp);
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, 0x0100);
-		return 10;
+	    xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Defaulting to Speed = 10 Mbps\r\n");
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &temp);
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, 0x0100);
+	    return 10;
 	}
 #endif
 
@@ -286,34 +286,34 @@ static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
 #else /*PCM_PMA_CORE_PRESENT not defined, GMII/RGMII case*/
 void detect_phy(XEmacPs *xemacpsp)
 {
-	u16_t phy_reg;
-	u32_t phy_addr;
-	u32_t emacnum;
+    u16_t phy_reg;
+    u32_t phy_addr;
+    u32_t emacnum;
 
-	if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR)
-		emacnum = 0;
-	else
-		emacnum = 1;
-	for (phy_addr = 31; phy_addr > 0; phy_addr--) {
-		XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
+    if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR)
+	    emacnum = 0;
+    else
+	    emacnum = 1;
+    for (phy_addr = 31; phy_addr > 0; phy_addr--) {
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
 							&phy_reg);
 
-		if ((phy_reg != 0xFFFF) &&
+	    if ((phy_reg != 0xFFFF) &&
 			((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
 			/* Found a valid PHY address */
-			LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
-																	phy_addr));
-			if (emacnum == 0)
-				phymapemac0[phy_addr] = TRUE;
-			else
-				phymapemac1[phy_addr] = TRUE;
+		    LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
+																    phy_addr));
+		    if (emacnum == 0)
+			    phymapemac0[phy_addr] = TRUE;
+		    else
+			    phymapemac1[phy_addr] = TRUE;
 
-			XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
+		    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
 							&phy_reg);
-			if ((phy_reg != PHY_MARVELL_IDENTIFIER) &&
+		    if ((phy_reg != PHY_MARVELL_IDENTIFIER) &&
 				(phy_reg != PHY_TI_IDENTIFIER) &&
 				(phy_reg != PHY_REALTEK_IDENTIFIER)) {
-				xil_printf("WARNING: Not a Marvell or TI or Realtek Ethernet PHY. Please verify the initialization sequence\r\n");
+			    xil_printf("WARNING: Not a Marvell or TI or Realtek Ethernet PHY. Please verify the initialization sequence\r\n");
 			}
 		}
 	}
@@ -321,492 +321,492 @@ void detect_phy(XEmacPs *xemacpsp)
 
 u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr)
 {
-	u32_t link_speed;
-	u32_t conv_present = 0;
-	u32_t convspeeddupsetting = 0;
-	u32_t convphyaddr = 0;
+    u32_t link_speed;
+    u32_t conv_present = 0;
+    u32_t convspeeddupsetting = 0;
+    u32_t convphyaddr = 0;
 
 #ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
-	convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
-	conv_present = 1;
+    convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
+    conv_present = 1;
 #endif
 #ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
-	convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
-	conv_present = 1;
+    convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
+    conv_present = 1;
 #endif
 
 #ifdef  CONFIG_LINKSPEED_AUTODETECT
-	link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr);
-	if (link_speed == 1000) {
-		SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
-		convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
+    link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr);
+    if (link_speed == 1000) {
+	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
+	    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
 	} else if (link_speed == 100) {
-		SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
-		convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
+	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
+	    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
 	} else if (link_speed != XST_FAILURE){
-		SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
-		convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
+	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
+	    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
 	} else {
-		xil_printf("Phy setup error \r\n");
-		return XST_FAILURE;
+	    xil_printf("Phy setup error \r\n");
+	    return XST_FAILURE;
 	}
-#elif	defined(CONFIG_LINKSPEED1000)
-	SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
-	link_speed = 1000;
-	configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
-	convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
-	sleep(1);
-#elif	defined(CONFIG_LINKSPEED100)
-	SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
-	link_speed = 100;
-	configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
-	convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
-	sleep(1);
-#elif	defined(CONFIG_LINKSPEED10)
-	SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
-	link_speed = 10;
-	configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
-	convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
-	sleep(1);
+#elif    defined(CONFIG_LINKSPEED1000)
+    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
+    link_speed = 1000;
+    configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
+    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
+    sleep(1);
+#elif    defined(CONFIG_LINKSPEED100)
+    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
+    link_speed = 100;
+    configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
+    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
+    sleep(1);
+#elif    defined(CONFIG_LINKSPEED10)
+    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
+    link_speed = 10;
+    configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
+    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
+    sleep(1);
 #endif
-	if (conv_present) {
-		XEmacPs_PhyWrite(xemacpsp, convphyaddr,
-		XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
+    if (conv_present) {
+	    XEmacPs_PhyWrite(xemacpsp, convphyaddr,
+	    XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
 	}
 
-	xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed);
-	return link_speed;
+    xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed);
+    return link_speed;
 }
 
 #if defined CONFIG_LINKSPEED_AUTODETECT
 static u32_t get_phy_speed_ksz9031(XEmacPs *xemacpsp, u32_t phy_addr)
 {
-	static int phy_init_flag = 0;
-	u16_t temp;
-	u16_t control;
-	u16_t status;
-	u16_t status_speed;
-	u32_t timeout_counter = 0;
+    static int phy_init_flag = 0;
+    u16_t temp;
+    u16_t control;
+    u16_t status;
+    u16_t status_speed;
+    u32_t timeout_counter = 0;
 
-	xil_printf("Start PHY autonegotiation \r\n");
+    xil_printf("Start PHY autonegotiation \r\n");
 
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
-	control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
+    control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
 
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
-	control |= IEEE_ASYMMETRIC_PAUSE_MASK;
-	control |= IEEE_PAUSE_MASK;
-	control |= ADVERTISE_100;
-	control |= ADVERTISE_10;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
+    control |= IEEE_ASYMMETRIC_PAUSE_MASK;
+    control |= IEEE_PAUSE_MASK;
+    control |= ADVERTISE_100;
+    control |= ADVERTISE_10;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
 					   &control);
-	control |= ADVERTISE_1000;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+    control |= ADVERTISE_1000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
 					   control);
 
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, &control);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, &control);
 
-	control |= (7 << 12); /* max number of gigabit attempts */
-	control |= (1 << 11); /* enable downshift */
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
+    control |= (7 << 12); /* max number of gigabit attempts */
+    control |= (1 << 11); /* enable downshift */
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
 					 control);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
-	control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+    control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	control |= IEEE_CTRL_RESET_MASK;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_RESET_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
 
-	while (1) {
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-		if (control & IEEE_CTRL_RESET_MASK)
+    while (1) {
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+	    if (control & IEEE_CTRL_RESET_MASK)
 			 continue;
-		else
-			break;
+	    else
+		    break;
 	}
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
-	xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
+    xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
 
-	while (!(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)) {
-		sleep(1);
-		XEmacPs_PhyRead(xemacpsp, phy_addr,
-							IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp);
-		timeout_counter++;
-		if ((phy_init_flag == 0) && (timeout_counter > 1))
+    while (!(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)) {
+	    sleep(1);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr,
+						    IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp);
+	    timeout_counter++;
+	    if ((phy_init_flag == 0) && (timeout_counter > 1))
 		{
-			phy_init_flag = 1;
-			return XST_FAILURE;
+		    phy_init_flag = 1;
+		    return XST_FAILURE;
 		}
-		if (timeout_counter == 30) {
-			xil_printf("Auto negotiation error \r\n");
-			return XST_FAILURE;
+	    if (timeout_counter == 30) {
+		    xil_printf("Auto negotiation error \r\n");
+		    return XST_FAILURE;
 		}
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 	}
-	xil_printf("autonegotiation complete \r\n");
+    xil_printf("autonegotiation complete \r\n");
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1f, &status_speed);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1f, &status_speed);
 
-	if ((status_speed & 0x40) == 0x40) /* 1000Mbps */
-		return 1000;
-	else if ((status_speed & 0x20) == 0x20) /* 100Mbps */
-		return 100;
-	else if ((status_speed & 0x10) == 0x10) /* 10Mbps */
-		return 10;
-	else
-		return 0;
-	return XST_SUCCESS;
+    if ((status_speed & 0x40) == 0x40) /* 1000Mbps */
+	    return 1000;
+    else if ((status_speed & 0x20) == 0x20) /* 100Mbps */
+	    return 100;
+    else if ((status_speed & 0x10) == 0x10) /* 10Mbps */
+	    return 10;
+    else
+	    return 0;
+    return XST_SUCCESS;
 }
 
 static u32_t get_TI_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
 {
-	u16_t control;
-	u16_t status;
-	u16_t status_speed;
-	u32_t timeout_counter = 0;
-	u32_t phyregtemp;
-	int i;
-	u32_t RetStatus;
-	static int phy_init_flag = 0;
+    u16_t control;
+    u16_t status;
+    u16_t status_speed;
+    u32_t timeout_counter = 0;
+    u32_t phyregtemp;
+    int i;
+    u32_t RetStatus;
+    static int phy_init_flag = 0;
 
-	xil_printf("Start PHY autonegotiation \r\n");
+    xil_printf("Start PHY autonegotiation \r\n");
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, (u16_t *)&phyregtemp);
-	phyregtemp |= 0x4000;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, phyregtemp);
-	RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, (u16_t *)&phyregtemp);
-	if (RetStatus != XST_SUCCESS) {
-		xil_printf("Error during sw reset \n\r");
-		return XST_FAILURE;
+    XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, (u16_t *)&phyregtemp);
+    phyregtemp |= 0x4000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, phyregtemp);
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, (u16_t *)&phyregtemp);
+    if (RetStatus != XST_SUCCESS) {
+	    xil_printf("Error during sw reset \n\r");
+	    return XST_FAILURE;
 	}
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp);
-	phyregtemp |= 0x8000;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, phyregtemp);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp);
+    phyregtemp |= 0x8000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, phyregtemp);
 
 	/*
 	 * Delay
 	 */
-	for(i=0;i<1000000000;i++);
+    for(i=0;i<1000000000;i++);
 
-	RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp);
-	if (RetStatus != XST_SUCCESS) {
-		xil_printf("Error during reset \n\r");
-		return XST_FAILURE;
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp);
+    if (RetStatus != XST_SUCCESS) {
+	    xil_printf("Error during reset \n\r");
+	    return XST_FAILURE;
 	}
 
 	/* FIFO depth */
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_TI_CR, PHY_TI_CRVAL);
-	RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_TI_CR, (u16_t *)&phyregtemp);
-	if (RetStatus != XST_SUCCESS) {
-		xil_printf("Error writing to 0x10 \n\r");
-		return XST_FAILURE;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_TI_CR, PHY_TI_CRVAL);
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_TI_CR, (u16_t *)&phyregtemp);
+    if (RetStatus != XST_SUCCESS) {
+	    xil_printf("Error writing to 0x10 \n\r");
+	    return XST_FAILURE;
 	}
 
 	/* TX/RX tuning */
 	/* Write to PHY_RGMIIDCTL */
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
-	RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xA8);
-	if (RetStatus != XST_SUCCESS) {
-		xil_printf("Error in tuning");
-		return XST_FAILURE;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xA8);
+    if (RetStatus != XST_SUCCESS) {
+	    xil_printf("Error in tuning");
+	    return XST_FAILURE;
 	}
 
 	/* Read PHY_RGMIIDCTL */
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
-	RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
-	if (RetStatus != XST_SUCCESS) {
-		xil_printf("Error in tuning");
-		return XST_FAILURE;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
+    if (RetStatus != XST_SUCCESS) {
+	    xil_printf("Error in tuning");
+	    return XST_FAILURE;
 	}
 
 	/* Write PHY_RGMIICTL */
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
-	RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xD3);
-	if (RetStatus != XST_SUCCESS) {
-		xil_printf("Error in tuning");
-		return XST_FAILURE;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xD3);
+    if (RetStatus != XST_SUCCESS) {
+	    xil_printf("Error in tuning");
+	    return XST_FAILURE;
 	}
 
 	/* Read PHY_RGMIICTL */
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
-	RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
-	if (RetStatus != XST_SUCCESS) {
-		xil_printf("Error in tuning");
-		return XST_FAILURE;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
+    if (RetStatus != XST_SUCCESS) {
+	    xil_printf("Error in tuning");
+	    return XST_FAILURE;
 	}
 
 	/* SW workaround for unstable link when RX_CTRL is not STRAP MODE 3 or 4 */
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
-	RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
-	phyregtemp &= ~(PHY_TI_CFG4RESVDBIT7);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4);
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
-	RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, phyregtemp);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
+    phyregtemp &= ~(PHY_TI_CFG4RESVDBIT7);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, phyregtemp);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
-	control |= IEEE_ASYMMETRIC_PAUSE_MASK;
-	control |= IEEE_PAUSE_MASK;
-	control |= ADVERTISE_100;
-	control |= ADVERTISE_10;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
+    control |= IEEE_ASYMMETRIC_PAUSE_MASK;
+    control |= IEEE_PAUSE_MASK;
+    control |= ADVERTISE_100;
+    control |= ADVERTISE_10;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
 					&control);
-	control |= ADVERTISE_1000;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-					control);
+    control |= ADVERTISE_1000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+				    control);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
-	control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+    control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
-	xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
+    xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
 
-	while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
-		sleep(1);
-		timeout_counter++;
-		if ((phy_init_flag == 0) && (timeout_counter > 1))
+    while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
+	    sleep(1);
+	    timeout_counter++;
+	    if ((phy_init_flag == 0) && (timeout_counter > 1))
 		{
-			phy_init_flag = 1;
-			return XST_FAILURE;
+		    phy_init_flag = 1;
+		    return XST_FAILURE;
 		}
-		if (timeout_counter == 30) {
-			xil_printf("Auto negotiation error \r\n");
-			return XST_FAILURE;
+	    if (timeout_counter == 30) {
+		    xil_printf("Auto negotiation error \r\n");
+		    return XST_FAILURE;
 		}
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 	}
-	xil_printf("autonegotiation complete \r\n");
+    xil_printf("autonegotiation complete \r\n");
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_STS, &status_speed);
-	if ((status_speed & 0xC000) == 0x8000) {
-		return 1000;
+    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_STS, &status_speed);
+    if ((status_speed & 0xC000) == 0x8000) {
+	    return 1000;
 	} else if ((status_speed & 0xC000) == 0x4000) {
-		return 100;
+	    return 100;
 	} else {
-		return 10;
+	    return 10;
 	}
 
-	return XST_SUCCESS;
+    return XST_SUCCESS;
 }
 
 static u32_t get_Marvell_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
 {
-	u16_t temp;
-	u16_t control;
-	u16_t status;
-	u16_t status_speed;
-	u32_t timeout_counter = 0;
-	u32_t temp_speed;
-	static int phy_init_flag = 0;
+    u16_t temp;
+    u16_t control;
+    u16_t status;
+    u16_t status_speed;
+    u32_t timeout_counter = 0;
+    u32_t temp_speed;
+    static int phy_init_flag = 0;
 
-	xil_printf("Start PHY autonegotiation \r\n");
+    xil_printf("Start PHY autonegotiation \r\n");
 
-	XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
-	control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
+    XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
+    control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
 
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
-	control |= IEEE_ASYMMETRIC_PAUSE_MASK;
-	control |= IEEE_PAUSE_MASK;
-	control |= ADVERTISE_100;
-	control |= ADVERTISE_10;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
+    control |= IEEE_ASYMMETRIC_PAUSE_MASK;
+    control |= IEEE_PAUSE_MASK;
+    control |= ADVERTISE_100;
+    control |= ADVERTISE_10;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
 					&control);
-	control |= ADVERTISE_1000;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-					control);
+    control |= ADVERTISE_1000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+				    control);
 
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
 																&control);
-	control |= (7 << 12);	/* max number of gigabit attempts */
-	control |= (1 << 11);	/* enable downshift */
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
-																control);
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
-	control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+    control |= (7 << 12);	/* max number of gigabit attempts */
+    control |= (1 << 11);	/* enable downshift */
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
+															    control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+    control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	control |= IEEE_CTRL_RESET_MASK;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_RESET_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
 
-	while (1) {
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-		if (control & IEEE_CTRL_RESET_MASK)
-			continue;
-		else
-			break;
+    while (1) {
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+	    if (control & IEEE_CTRL_RESET_MASK)
+		    continue;
+	    else
+		    break;
 	}
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
-	xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
+    xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
 
-	while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
-		sleep(1);
-		XEmacPs_PhyRead(xemacpsp, phy_addr,
-						IEEE_COPPER_SPECIFIC_STATUS_REG_2,  &temp);
-		timeout_counter++;
-		if ((phy_init_flag == 0) && (timeout_counter > 1))
+    while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
+	    sleep(1);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr,
+					    IEEE_COPPER_SPECIFIC_STATUS_REG_2,  &temp);
+	    timeout_counter++;
+	    if ((phy_init_flag == 0) && (timeout_counter > 1))
 		{
-			phy_init_flag = 1;
-			return XST_FAILURE;
+		    phy_init_flag = 1;
+		    return XST_FAILURE;
 		}
-		if (timeout_counter == 30) {
-			xil_printf("Auto negotiation error \r\n");
-			return XST_FAILURE;
+	    if (timeout_counter == 30) {
+		    xil_printf("Auto negotiation error \r\n");
+		    return XST_FAILURE;
 		}
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 	}
-	xil_printf("autonegotiation complete \r\n");
+    xil_printf("autonegotiation complete \r\n");
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG,
+    XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG,
 					&status_speed);
-	if (status_speed & 0x400) {
-		temp_speed = status_speed & IEEE_SPEED_MASK;
+    if (status_speed & 0x400) {
+	    temp_speed = status_speed & IEEE_SPEED_MASK;
 
-		if (temp_speed == IEEE_SPEED_1000)
-			return 1000;
-		else if(temp_speed == IEEE_SPEED_100)
-			return 100;
-		else
-			return 10;
+	    if (temp_speed == IEEE_SPEED_1000)
+		    return 1000;
+	    else if(temp_speed == IEEE_SPEED_100)
+		    return 100;
+	    else
+		    return 10;
 	}
 
-	return XST_SUCCESS;
+    return XST_SUCCESS;
 }
 
 static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
 {
-	u16_t control;
-	u16_t status;
-	u16_t status_speed;
-	u32_t timeout_counter = 0;
-	u32_t temp_speed;
-	static int phy_init_flag = 0;
+    u16_t control;
+    u16_t status;
+    u16_t status_speed;
+    u32_t timeout_counter = 0;
+    u32_t temp_speed;
+    static int phy_init_flag = 0;
 
-	xil_printf("Start PHY autonegotiation \r\n");
+    xil_printf("Start PHY autonegotiation \r\n");
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
-	control |= IEEE_ASYMMETRIC_PAUSE_MASK;
-	control |= IEEE_PAUSE_MASK;
-	control |= ADVERTISE_100;
-	control |= ADVERTISE_10;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
+    control |= IEEE_ASYMMETRIC_PAUSE_MASK;
+    control |= IEEE_PAUSE_MASK;
+    control |= ADVERTISE_100;
+    control |= ADVERTISE_10;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
 					&control);
-	control |= ADVERTISE_1000;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-					control);
+    control |= ADVERTISE_1000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+				    control);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
-	control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+    control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	control |= IEEE_CTRL_RESET_MASK;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_RESET_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
 
-	while (1) {
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-		if (control & IEEE_CTRL_RESET_MASK)
-			continue;
-		else
-			break;
+    while (1) {
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+	    if (control & IEEE_CTRL_RESET_MASK)
+		    continue;
+	    else
+		    break;
 	}
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
-	xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
+    xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
 
-	while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
-		sleep(1);
-		timeout_counter++;
-		if ((phy_init_flag == 0) && (timeout_counter > 1))
+    while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
+	    sleep(1);
+	    timeout_counter++;
+	    if ((phy_init_flag == 0) && (timeout_counter > 1))
 		{
-			phy_init_flag = 1;
-			return XST_FAILURE;
+		    phy_init_flag = 1;
+		    return XST_FAILURE;
 		}
-		if (timeout_counter == 30) {
-			xil_printf("Auto negotiation error \r\n");
-			return XST_FAILURE;
+	    if (timeout_counter == 30) {
+		    xil_printf("Auto negotiation error \r\n");
+		    return XST_FAILURE;
 		}
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 	}
-	xil_printf("autonegotiation complete \r\n");
+    xil_printf("autonegotiation complete \r\n");
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG,
+    XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG,
 					&status_speed);
-	if (status_speed & 0x400) {
-		temp_speed = status_speed & IEEE_SPEED_MASK;
+    if (status_speed & 0x400) {
+	    temp_speed = status_speed & IEEE_SPEED_MASK;
 
-		if (temp_speed == IEEE_SPEED_1000)
-			return 1000;
-		else if(temp_speed == IEEE_SPEED_100)
-			return 100;
-		else
-			return 10;
+	    if (temp_speed == IEEE_SPEED_1000)
+		    return 1000;
+	    else if(temp_speed == IEEE_SPEED_100)
+		    return 100;
+	    else
+		    return 10;
 	}
 
-	return XST_FAILURE;
+    return XST_FAILURE;
 }
 
 static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
 {
-	u16_t phy_identity;
-	u32_t RetStatus;
+    u16_t phy_identity;
+    u32_t RetStatus;
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
+    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
 					&phy_identity);
-	if(phy_identity == MICREL_PHY_IDENTIFIER){
-		RetStatus = get_phy_speed_ksz9031(xemacpsp, phy_addr);
+    if(phy_identity == MICREL_PHY_IDENTIFIER){
+	    RetStatus = get_phy_speed_ksz9031(xemacpsp, phy_addr);
 	} else if (phy_identity == PHY_TI_IDENTIFIER) {
-		RetStatus = get_TI_phy_speed(xemacpsp, phy_addr);
+	    RetStatus = get_TI_phy_speed(xemacpsp, phy_addr);
 	} else if (phy_identity == PHY_REALTEK_IDENTIFIER) {
-		RetStatus = get_Realtek_phy_speed(xemacpsp, phy_addr);
+	    RetStatus = get_Realtek_phy_speed(xemacpsp, phy_addr);
 	} else {
-		RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr);
+	    RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr);
 	}
 
-	return RetStatus;
+    return RetStatus;
 }
 #endif
 
@@ -814,339 +814,339 @@ static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
 	|| defined (CONFIG_LINKSPEED10)
 static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed)
 {
-	u16_t control;
-	u16_t autonereg;
+    u16_t control;
+    u16_t autonereg;
 
-	XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
-	control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
+    XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
+    control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
 
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-	autonereg |= IEEE_ASYMMETRIC_PAUSE_MASK;
-	autonereg |= IEEE_PAUSE_MASK;
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+    autonereg |= IEEE_ASYMMETRIC_PAUSE_MASK;
+    autonereg |= IEEE_PAUSE_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
 
-	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	control &= ~IEEE_CTRL_LINKSPEED_1000M;
-	control &= ~IEEE_CTRL_LINKSPEED_100M;
-	control &= ~IEEE_CTRL_LINKSPEED_10M;
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control &= ~IEEE_CTRL_LINKSPEED_1000M;
+    control &= ~IEEE_CTRL_LINKSPEED_100M;
+    control &= ~IEEE_CTRL_LINKSPEED_10M;
 
-	if (speed == 1000) {
-		control |= IEEE_CTRL_LINKSPEED_1000M;
+    if (speed == 1000) {
+	    control |= IEEE_CTRL_LINKSPEED_1000M;
 
 		/* Don't advertise PHY speed of 100 Mbps */
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-		autonereg &= (~ADVERTISE_100);
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+	    autonereg &= (~ADVERTISE_100);
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
 
 		/* Don't advertise PHY speed of 10 Mbps */
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-		autonereg &= (~ADVERTISE_10);
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+	    autonereg &= (~ADVERTISE_10);
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
 
 		/* Advertise PHY speed of 1000 Mbps */
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
-		autonereg |= ADVERTISE_1000;
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
+	    autonereg |= ADVERTISE_1000;
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
 	}
 
-	else if (speed == 100) {
-		control |= IEEE_CTRL_LINKSPEED_100M;
+    else if (speed == 100) {
+	    control |= IEEE_CTRL_LINKSPEED_100M;
 
 		/* Don't advertise PHY speed of 1000 Mbps */
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
-		autonereg &= (~ADVERTISE_1000);
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
+	    autonereg &= (~ADVERTISE_1000);
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
 
 		/* Don't advertise PHY speed of 10 Mbps */
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-		autonereg &= (~ADVERTISE_10);
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+	    autonereg &= (~ADVERTISE_10);
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
 
 		/* Advertise PHY speed of 100 Mbps */
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-		autonereg |= ADVERTISE_100;
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+	    autonereg |= ADVERTISE_100;
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
 	}
 
-	else if (speed == 10) {
-		control |= IEEE_CTRL_LINKSPEED_10M;
+    else if (speed == 10) {
+	    control |= IEEE_CTRL_LINKSPEED_10M;
 
 		/* Don't advertise PHY speed of 1000 Mbps */
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
-		autonereg &= (~ADVERTISE_1000);
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
+	    autonereg &= (~ADVERTISE_1000);
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
 
 		/* Don't advertise PHY speed of 100 Mbps */
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-		autonereg &= (~ADVERTISE_100);
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+	    autonereg &= (~ADVERTISE_100);
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
 
 		/* Advertise PHY speed of 10 Mbps */
-		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-		autonereg |= ADVERTISE_10;
-		XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+	    autonereg |= ADVERTISE_10;
+	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
 	}
 
-	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
-											control | IEEE_CTRL_RESET_MASK);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
+										    control | IEEE_CTRL_RESET_MASK);
 	{
-		volatile s32_t wait;
-		for (wait=0; wait < 100000; wait++);
+	    volatile s32_t wait;
+	    for (wait=0; wait < 100000; wait++);
 	}
-	return 0;
+    return 0;
 }
 #endif
 #endif /*PCM_PMA_CORE_PRESENT*/
 
 static void SetUpSLCRDivisors(u32_t mac_baseaddr, s32_t speed)
 {
-	volatile u32_t slcrBaseAddress;
-	u32_t SlcrDiv0 = 0;
-	u32_t SlcrDiv1 = 0;
-	u32_t SlcrTxClkCntrl;
-	u32_t gigeversion;
-	volatile u32_t CrlApbBaseAddr;
-	u32_t CrlApbDiv0 = 0;
-	u32_t CrlApbDiv1 = 0;
-	u32_t CrlApbGemCtrl;
+    volatile u32_t slcrBaseAddress;
+    u32_t SlcrDiv0 = 0;
+    u32_t SlcrDiv1 = 0;
+    u32_t SlcrTxClkCntrl;
+    u32_t gigeversion;
+    volatile u32_t CrlApbBaseAddr;
+    u32_t CrlApbDiv0 = 0;
+    u32_t CrlApbDiv1 = 0;
+    u32_t CrlApbGemCtrl;
 #if EL1_NONSECURE
-	u32_t ClkId;
+    u32_t ClkId;
 #endif
 
-	gigeversion = ((Xil_In32(mac_baseaddr + 0xFC)) >> 16) & 0xFFF;
-	if (gigeversion == 2) {
+    gigeversion = ((Xil_In32(mac_baseaddr + 0xFC)) >> 16) & 0xFFF;
+    if (gigeversion == 2) {
 
 		*(volatile u32_t *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
 
-		if (mac_baseaddr == ZYNQ_EMACPS_0_BASEADDR) {
-			slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
+	    if (mac_baseaddr == ZYNQ_EMACPS_0_BASEADDR) {
+		    slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
 		} else {
-			slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
+		    slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
 		}
 
-		if((*(volatile u32_t *)(UINTPTR)(slcrBaseAddress)) &
-			SLCR_GEM_SRCSEL_EMIO) {
-				return;
+	    if((*(volatile u32_t *)(UINTPTR)(slcrBaseAddress)) &
+		    SLCR_GEM_SRCSEL_EMIO) {
+			    return;
 		}
 
-		if (speed == 1000) {
-			if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
+	    if (speed == 1000) {
+		    if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
-				SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
-				SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
+			    SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
+			    SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
 #endif
 			} else {
 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
-				SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
-				SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
+			    SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
+			    SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
 #endif
 			}
 		} else if (speed == 100) {
-			if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
+		    if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
-				SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
-				SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
+			    SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
+			    SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
 #endif
 			} else {
 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
-				SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
-				SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
+			    SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
+			    SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
 #endif
 			}
 		} else {
-			if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
+		    if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
-				SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
-				SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
+			    SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
+			    SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
 #endif
 			} else {
 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
-				SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
-				SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
+			    SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
+			    SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
 #endif
 			}
 		}
 
-		if (SlcrDiv0 != 0 && SlcrDiv1 != 0) {
-			SlcrTxClkCntrl = *(volatile u32_t *)(UINTPTR)(slcrBaseAddress);
-			SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
-			SlcrTxClkCntrl |= (SlcrDiv1 << 20);
-			SlcrTxClkCntrl |= (SlcrDiv0 << 8);
+	    if (SlcrDiv0 != 0 && SlcrDiv1 != 0) {
+		    SlcrTxClkCntrl = *(volatile u32_t *)(UINTPTR)(slcrBaseAddress);
+		    SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
+		    SlcrTxClkCntrl |= (SlcrDiv1 << 20);
+		    SlcrTxClkCntrl |= (SlcrDiv0 << 8);
 			*(volatile u32_t *)(UINTPTR)(slcrBaseAddress) = SlcrTxClkCntrl;
 			*(volatile u32_t *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
 		} else {
-			xil_printf("Clock Divisors incorrect - Please check\r\n");
+		    xil_printf("Clock Divisors incorrect - Please check\r\n");
 		}
 	} else if (gigeversion == GEM_VERSION_ZYNQMP) {
 		/* Setup divisors in CRL_APB for Zynq Ultrascale+ MPSoC */
-		if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
-			CrlApbBaseAddr = CRL_APB_GEM0_REF_CTRL;
+	    if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+		    CrlApbBaseAddr = CRL_APB_GEM0_REF_CTRL;
 		} else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
-			CrlApbBaseAddr = CRL_APB_GEM1_REF_CTRL;
+		    CrlApbBaseAddr = CRL_APB_GEM1_REF_CTRL;
 		} else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
-			CrlApbBaseAddr = CRL_APB_GEM2_REF_CTRL;
+		    CrlApbBaseAddr = CRL_APB_GEM2_REF_CTRL;
 		} else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
-			CrlApbBaseAddr = CRL_APB_GEM3_REF_CTRL;
+		    CrlApbBaseAddr = CRL_APB_GEM3_REF_CTRL;
 		}
 
-		if (speed == 1000) {
-			if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+	    if (speed == 1000) {
+		    if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
 #endif
 			} else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
 #endif
 			} else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV1;
 #endif
 			} else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV1;
 #endif
 			}
 		} else if (speed == 100) {
-			if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+		    if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
 #endif
 			} else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
 #endif
 			} else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV1;
 #endif
 			} else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV1;
 #endif
 			}
 		} else {
-			if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+		    if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
 #endif
 			} else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
 #endif
 			} else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV1;
 #endif
 			} else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0;
-				CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV1;
+			    CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0;
+			    CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV1;
 #endif
 			}
 		}
 
-		if (CrlApbDiv0 != 0 && CrlApbDiv1 != 0) {
+	    if (CrlApbDiv0 != 0 && CrlApbDiv1 != 0) {
 		#if EL1_NONSECURE
-			XSmc_OutVar RegRead;
-			RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
-								0, 0, 0, 0, 0, 0);
-			CrlApbGemCtrl = RegRead.Arg0 >> 32;
+		    XSmc_OutVar RegRead;
+		    RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
+							    0, 0, 0, 0, 0, 0);
+		    CrlApbGemCtrl = RegRead.Arg0 >> 32;
 		#else
-			CrlApbGemCtrl = *(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr);
+		    CrlApbGemCtrl = *(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr);
         #endif
-			CrlApbGemCtrl &= ~CRL_APB_GEM_DIV0_MASK;
-			CrlApbGemCtrl |= CrlApbDiv0 << CRL_APB_GEM_DIV0_SHIFT;
-			CrlApbGemCtrl &= ~CRL_APB_GEM_DIV1_MASK;
-			CrlApbGemCtrl |= CrlApbDiv1 << CRL_APB_GEM_DIV1_SHIFT;
+		    CrlApbGemCtrl &= ~CRL_APB_GEM_DIV0_MASK;
+		    CrlApbGemCtrl |= CrlApbDiv0 << CRL_APB_GEM_DIV0_SHIFT;
+		    CrlApbGemCtrl &= ~CRL_APB_GEM_DIV1_MASK;
+		    CrlApbGemCtrl |= CrlApbDiv1 << CRL_APB_GEM_DIV1_SHIFT;
 		#if EL1_NONSECURE
-			Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(CrlApbBaseAddr) | ((u64)(0xFFFFFFFF) << 32),
+		    Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(CrlApbBaseAddr) | ((u64)(0xFFFFFFFF) << 32),
 				(u64)CrlApbGemCtrl, 0, 0, 0, 0, 0);
-			do {
-			RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
-				0, 0, 0, 0, 0, 0);
+		    do {
+		    RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
+			    0, 0, 0, 0, 0, 0);
 			} while((RegRead.Arg0 >> 32) != CrlApbGemCtrl);
 		#else
 			*(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr) = CrlApbGemCtrl;
         #endif
 		} else {
-			xil_printf("Clock Divisors incorrect - Please check\r\n");
+		    xil_printf("Clock Divisors incorrect - Please check\r\n");
 		}
 	} else if (gigeversion == GEM_VERSION_VERSAL) {
 		/* Setup divisors in CRL for Versal */
-		if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
-			CrlApbBaseAddr = VERSAL_CRL_GEM0_REF_CTRL;
+	    if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+		    CrlApbBaseAddr = VERSAL_CRL_GEM0_REF_CTRL;
 #if EL1_NONSECURE
-			ClkId = CLK_GEM0_REF;
+		    ClkId = CLK_GEM0_REF;
 #endif
 		} else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
-			CrlApbBaseAddr = VERSAL_CRL_GEM1_REF_CTRL;
+		    CrlApbBaseAddr = VERSAL_CRL_GEM1_REF_CTRL;
 #if EL1_NONSECURE
-			ClkId = CLK_GEM1_REF;
+		    ClkId = CLK_GEM1_REF;
 #endif
 		}
 
-		if (speed == 1000) {
-			if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+	    if (speed == 1000) {
+		    if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
+			    CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
 #endif
 			} else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
+			    CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
 #endif
 			}
 		} else if (speed == 100) {
-			if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+		    if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
+			    CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
 #endif
 			} else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
+			    CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
 #endif
 			}
 		} else {
-			if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+		    if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
+			    CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
 #endif
 			} else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
-				CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
+			    CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
 #endif
 			}
 		}
 
-		if (CrlApbDiv0 != 0) {
+	    if (CrlApbDiv0 != 0) {
 #if EL1_NONSECURE
-			Xil_Smc(PM_SET_DIVIDER_SMC_FID, (((u64)CrlApbDiv0 << 32) | ClkId), 0, 0, 0, 0, 0, 0);
+		    Xil_Smc(PM_SET_DIVIDER_SMC_FID, (((u64)CrlApbDiv0 << 32) | ClkId), 0, 0, 0, 0, 0, 0);
 #else
-			CrlApbGemCtrl = Xil_In32((UINTPTR)CrlApbBaseAddr);
-			CrlApbGemCtrl &= ~VERSAL_CRL_GEM_DIV_MASK;
-			CrlApbGemCtrl |= CrlApbDiv0 << VERSAL_CRL_APB_GEM_DIV_SHIFT;
+		    CrlApbGemCtrl = Xil_In32((UINTPTR)CrlApbBaseAddr);
+		    CrlApbGemCtrl &= ~VERSAL_CRL_GEM_DIV_MASK;
+		    CrlApbGemCtrl |= CrlApbDiv0 << VERSAL_CRL_APB_GEM_DIV_SHIFT;
 
-			Xil_Out32((UINTPTR)CrlApbBaseAddr, CrlApbGemCtrl);
+		    Xil_Out32((UINTPTR)CrlApbBaseAddr, CrlApbGemCtrl);
 #endif
 		} else {
-			xil_printf("Clock Divisors incorrect - Please check\r\n");
+		    xil_printf("Clock Divisors incorrect - Please check\r\n");
 		}
 	}
 
-	return;
+    return;
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c
index b5a773e29b..bc8bfbfe32 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c
@@ -33,61 +33,61 @@
 #include "netif/xpqueue.h"
 #include "xil_printf.h"
 
-#define NUM_QUEUES	2
+#define NUM_QUEUES    2
 
 pq_queue_t pq_queue[NUM_QUEUES];
 
 pq_queue_t *
 pq_create_queue()
 {
-	static int i;
-	pq_queue_t *q = NULL;
+    static int i;
+    pq_queue_t *q = NULL;
 
-	if (i >= NUM_QUEUES) {
-		xil_printf("ERR: Max Queues allocated\n\r");
-		return q;
+    if (i >= NUM_QUEUES) {
+	    xil_printf("ERR: Max Queues allocated\n\r");
+	    return q;
 	}
 
-	q = &pq_queue[i++];
+    q = &pq_queue[i++];
 
-	if (!q)
-		return q;
+    if (!q)
+	    return q;
 
-	q->head = q->tail = q->len = 0;
+    q->head = q->tail = q->len = 0;
 
-	return q;
+    return q;
 }
 
 int
 pq_enqueue(pq_queue_t *q, void *p)
 {
-	if (q->len == PQ_QUEUE_SIZE)
-		return -1;
+    if (q->len == PQ_QUEUE_SIZE)
+	    return -1;
 
-	q->data[q->head] = p;
-	q->head = (q->head + 1)%PQ_QUEUE_SIZE;
-	q->len++;
+    q->data[q->head] = p;
+    q->head = (q->head + 1)%PQ_QUEUE_SIZE;
+    q->len++;
 
-	return 0;
+    return 0;
 }
 
 void*
 pq_dequeue(pq_queue_t *q)
 {
-	int ptail;
+    int ptail;
 
-	if (q->len == 0)
-		return NULL;
+    if (q->len == 0)
+	    return NULL;
 
-	ptail = q->tail;
-	q->tail = (q->tail + 1)%PQ_QUEUE_SIZE;
-	q->len--;
+    ptail = q->tail;
+    q->tail = (q->tail + 1)%PQ_QUEUE_SIZE;
+    q->len--;
 
-	return q->data[ptail];
+    return q->data[ptail];
 }
 
 int
 pq_qlength(pq_queue_t *q)
 {
-	return q->len;
+    return q->len;
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c
index 9d6fb85f03..4ab0e7ece4 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c
@@ -3,12 +3,12 @@
 
 struct xtopology_t xtopology[] = {
 	{
-		0xFF0E0000,
-		xemac_type_emacps,
-		0x0,
-		0x0,
-		0xF8F00100,
-		XPAR_XEMACPS_3_INTR,
+	    0xFF0E0000,
+	    xemac_type_emacps,
+	    0x0,
+	    0x0,
+	    0xF8F00100,
+	    XPAR_XEMACPS_3_INTR,
 	},
 };
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_io.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_io.h
index c23ba948a3..87d7282c04 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_io.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_io.h
@@ -20,7 +20,7 @@
 *
 * Ver   Who      Date     Changes
 * ----- -------- -------- -----------------------------------------------
-* 5.00 	pkp  	 05/29/14 First release
+* 5.00     pkp  	 05/29/14 First release
 * 6.00  mus      08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
 *                         ARM processors
 * 7.20  har      01/03/20 Added Xil_SecureOut32 for avoiding blindwrite for
@@ -54,15 +54,15 @@ extern "C" {
 *           from the specified address and returning the 8 bit Value read from
 *            that address.
 *
-* @param	Addr: contains the address to perform the input operation
+* @param    Addr: contains the address to perform the input operation
 *
-* @return	The 8 bit Value read from the specified input address.
+* @return    The 8 bit Value read from the specified input address.
 
 *
 ******************************************************************************/
 static INLINE u8 Xil_In8(UINTPTR Addr)
 {
-	return *(volatile u8 *) Addr;
+    return *(volatile u8 *) Addr;
 }
 
 /*****************************************************************************/
@@ -72,14 +72,14 @@ static INLINE u8 Xil_In8(UINTPTR Addr)
 *           the specified address and returning the 16 bit Value read from that
 *           address.
 *
-* @param	Addr: contains the address to perform the input operation
+* @param    Addr: contains the address to perform the input operation
 *
-* @return	The 16 bit Value read from the specified input address.
+* @return    The 16 bit Value read from the specified input address.
 *
 ******************************************************************************/
 static INLINE u16 Xil_In16(UINTPTR Addr)
 {
-	return *(volatile u16 *) Addr;
+    return *(volatile u16 *) Addr;
 }
 
 /*****************************************************************************/
@@ -89,14 +89,14 @@ static INLINE u16 Xil_In16(UINTPTR Addr)
 *           reading from the specified address and returning the 32 bit Value
 *           read  from that address.
 *
-* @param	Addr: contains the address to perform the input operation
+* @param    Addr: contains the address to perform the input operation
 *
-* @return	The 32 bit Value read from the specified input address.
+* @return    The 32 bit Value read from the specified input address.
 *
 ******************************************************************************/
 static INLINE u32 Xil_In32(UINTPTR Addr)
 {
-	return *(volatile u32 *) Addr;
+    return *(volatile u32 *) Addr;
 }
 
 /*****************************************************************************/
@@ -106,14 +106,14 @@ static INLINE u32 Xil_In32(UINTPTR Addr)
 *            64 bit Value read  from that address.
 *
 *
-* @param	Addr: contains the address to perform the input operation
+* @param    Addr: contains the address to perform the input operation
 *
-* @return	The 64 bit Value read from the specified input address.
+* @return    The 64 bit Value read from the specified input address.
 *
 ******************************************************************************/
 static INLINE u64 Xil_In64(UINTPTR Addr)
 {
-	return *(volatile u64 *) Addr;
+    return *(volatile u64 *) Addr;
 }
 
 /*****************************************************************************/
@@ -122,16 +122,16 @@ static INLINE u64 Xil_In64(UINTPTR Addr)
 * @brief    Performs an output operation for an memory location by
 *           writing the 8 bit Value to the the specified address.
 *
-* @param	Addr: contains the address to perform the output operation
-* @param	Value: contains the 8 bit Value to be written at the specified
+* @param    Addr: contains the address to perform the output operation
+* @param    Value: contains the 8 bit Value to be written at the specified
 *           address.
 *
-* @return	None.
+* @return    None.
 *
 ******************************************************************************/
 static INLINE void Xil_Out8(UINTPTR Addr, u8 Value)
 {
-	volatile u8 *LocalAddr = (volatile u8 *)Addr;
+    volatile u8 *LocalAddr = (volatile u8 *)Addr;
 	*LocalAddr = Value;
 }
 
@@ -141,15 +141,15 @@ static INLINE void Xil_Out8(UINTPTR Addr, u8 Value)
 * @brief    Performs an output operation for a memory location by writing the
 *            16 bit Value to the the specified address.
 *
-* @param	Addr contains the address to perform the output operation
-* @param	Value contains the Value to be written at the specified address.
+* @param    Addr contains the address to perform the output operation
+* @param    Value contains the Value to be written at the specified address.
 *
-* @return	None.
+* @return    None.
 *
 ******************************************************************************/
 static INLINE void Xil_Out16(UINTPTR Addr, u16 Value)
 {
-	volatile u16 *LocalAddr = (volatile u16 *)Addr;
+    volatile u16 *LocalAddr = (volatile u16 *)Addr;
 	*LocalAddr = Value;
 }
 
@@ -159,20 +159,20 @@ static INLINE void Xil_Out16(UINTPTR Addr, u16 Value)
 * @brief    Performs an output operation for a memory location by writing the
 *           32 bit Value to the the specified address.
 *
-* @param	Addr contains the address to perform the output operation
-* @param	Value contains the 32 bit Value to be written at the specified
+* @param    Addr contains the address to perform the output operation
+* @param    Value contains the 32 bit Value to be written at the specified
 *           address.
 *
-* @return	None.
+* @return    None.
 *
 ******************************************************************************/
 static INLINE void Xil_Out32(UINTPTR Addr, u32 Value)
 {
 #ifndef ENABLE_SAFETY
-	volatile u32 *LocalAddr = (volatile u32 *)Addr;
+    volatile u32 *LocalAddr = (volatile u32 *)Addr;
 	*LocalAddr = Value;
 #else
-	XStl_RegUpdate(Addr, Value);
+    XStl_RegUpdate(Addr, Value);
 #endif
 }
 
@@ -182,15 +182,15 @@ static INLINE void Xil_Out32(UINTPTR Addr, u32 Value)
 * @brief    Performs an output operation for a memory location by writing the
 *           64 bit Value to the the specified address.
 *
-* @param	Addr contains the address to perform the output operation
-* @param	Value contains 64 bit Value to be written at the specified address.
+* @param    Addr contains the address to perform the output operation
+* @param    Value contains 64 bit Value to be written at the specified address.
 *
-* @return	None.
+* @return    None.
 *
 ******************************************************************************/
 static INLINE void Xil_Out64(UINTPTR Addr, u64 Value)
 {
-	volatile u64 *LocalAddr = (volatile u64 *)Addr;
+    volatile u64 *LocalAddr = (volatile u64 *)Addr;
 	*LocalAddr = Value;
 }
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h
index 107f0bd724..50feebc430 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h
@@ -12,15 +12,15 @@ extern "C" {
 /************************** Constant Definitions *****************************/
 
 #ifndef TRUE
-#  define TRUE		1U
+#  define TRUE	    1U
 #endif
 
 #ifndef FALSE
-#  define FALSE		0U
+#  define FALSE	    0U
 #endif
 
 #ifndef NULL
-#define NULL		0U
+#define NULL	    0U
 #endif
 
 #define XIL_COMPONENT_IS_READY     0x11111111U  /**< In device drivers, This macro will be
@@ -54,7 +54,7 @@ typedef long LONG;
 typedef unsigned long ULONG;
 #endif
 
-#define ULONG64_HI_MASK	0xFFFFFFFF00000000U
+#define ULONG64_HI_MASK    0xFFFFFFFF00000000U
 #define ULONG64_LO_MASK	~ULONG64_HI_MASK
 
 /** @{ */
@@ -73,15 +73,15 @@ typedef void (*XExceptionHandler) (void *InstancePtr);
 /************************** Constant Definitions *****************************/
 
 #ifndef TRUE
-#define TRUE		1U
+#define TRUE	    1U
 #endif
 
 #ifndef FALSE
-#define FALSE		0U
+#define FALSE	    0U
 #endif
 
 #ifndef NULL
-#define NULL		0U
+#define NULL	    0U
 #endif
 
 #ifdef __cplusplus
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters.h
index dc408009d7..8ee236d9c6 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters.h
@@ -38,16 +38,16 @@
 
 /* Platform specific definitions */
 #define PLATFORM_ZYNQMP
- 
+
 /* Definitions for debug logic configuration in lockstep mode */
 #define LOCKSTEP_MODE_DEBUG 0U
- 
+
 /* Definitions for sleep timer configuration */
 #define XSLEEP_TIMER_IS_DEFAULT_TIMER
- 
+
 /* Definitions for processor access to RPU/IOU slcr address space*/
 #define PROCESSOR_ACCESS_VALUE 255
- 
+
 /******************************************************************/
 /* Definitions for driver AVBUF */
 #define XPAR_XAVBUF_NUM_INSTANCES 1
@@ -750,11 +750,11 @@
 #define  XPAR_PSU_IPI_1_INT_ID  65U
 
 /* Canonical definitions for peripheral psu_ipi_1 */
-#define  XPAR_XIPIPSU_0_DEVICE_ID	XPAR_PSU_IPI_1_DEVICE_ID
-#define  XPAR_XIPIPSU_0_BASE_ADDRESS	XPAR_PSU_IPI_1_S_AXI_BASEADDR
-#define  XPAR_XIPIPSU_0_BIT_MASK	XPAR_PSU_IPI_1_BIT_MASK
-#define  XPAR_XIPIPSU_0_BUFFER_INDEX	XPAR_PSU_IPI_1_BUFFER_INDEX
-#define  XPAR_XIPIPSU_0_INT_ID	XPAR_PSU_IPI_1_INT_ID
+#define  XPAR_XIPIPSU_0_DEVICE_ID    XPAR_PSU_IPI_1_DEVICE_ID
+#define  XPAR_XIPIPSU_0_BASE_ADDRESS    XPAR_PSU_IPI_1_S_AXI_BASEADDR
+#define  XPAR_XIPIPSU_0_BIT_MASK    XPAR_PSU_IPI_1_BIT_MASK
+#define  XPAR_XIPIPSU_0_BUFFER_INDEX    XPAR_PSU_IPI_1_BUFFER_INDEX
+#define  XPAR_XIPIPSU_0_INT_ID    XPAR_PSU_IPI_1_INT_ID
 
 #define  XPAR_XIPIPSU_NUM_TARGETS  7U
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters_ps.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters_ps.h
index a3af88c450..dbd406ccbb 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters_ps.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters_ps.h
@@ -20,9 +20,9 @@
 *
 * Ver   Who     Date     Changes
 * ----- ------- -------- ---------------------------------------------------
-* 5.00  pkp  	02/29/14 Initial version
+* 5.00  pkp      02/29/14 Initial version
 * 6.0   mus     08/18/16 Defined ARMR5 flag
-* 7.2	pm	03/25/20 Add wakeup Interrupt Id for usbpsu controller
+* 7.2    pm    03/25/20 Add wakeup Interrupt Id for usbpsu controller
 * 
* ******************************************************************************/ @@ -48,105 +48,105 @@ extern "C" { */ /* Canonical definitions for DDR MEMORY */ -#define XPAR_DDR_MEM_BASEADDR 0x00000000U -#define XPAR_DDR_MEM_HIGHADDR 0x3FFFFFFFU +#define XPAR_DDR_MEM_BASEADDR 0x00000000U +#define XPAR_DDR_MEM_HIGHADDR 0x3FFFFFFFU /* Canonical definitions for Interrupts */ -#define XPAR_XUARTPS_0_INTR XPS_UART0_INT_ID -#define XPAR_XUARTPS_1_INTR XPS_UART1_INT_ID -#define XPAR_XIICPS_0_INTR XPS_I2C0_INT_ID -#define XPAR_XIICPS_1_INTR XPS_I2C1_INT_ID -#define XPAR_XSPIPS_0_INTR XPS_SPI0_INT_ID -#define XPAR_XSPIPS_1_INTR XPS_SPI1_INT_ID -#define XPAR_XCANPS_0_INTR XPS_CAN0_INT_ID -#define XPAR_XCANPS_1_INTR XPS_CAN1_INT_ID -#define XPAR_XGPIOPS_0_INTR XPS_GPIO_INT_ID -#define XPAR_XEMACPS_0_INTR XPS_GEM0_INT_ID -#define XPAR_XEMACPS_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID -#define XPAR_XEMACPS_1_INTR XPS_GEM1_INT_ID -#define XPAR_XEMACPS_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID -#define XPAR_XEMACPS_2_INTR XPS_GEM2_INT_ID -#define XPAR_XEMACPS_2_WAKE_INTR XPS_GEM2_WAKE_INT_ID -#define XPAR_XEMACPS_3_INTR XPS_GEM3_INT_ID -#define XPAR_XEMACPS_3_WAKE_INTR XPS_GEM3_WAKE_INT_ID -#define XPAR_XSDIOPS_0_INTR XPS_SDIO0_INT_ID -#define XPAR_XQSPIPS_0_INTR XPS_QSPI_INT_ID -#define XPAR_XSDIOPS_1_INTR XPS_SDIO1_INT_ID -#define XPAR_XWDTPS_0_INTR XPS_CSU_WDT_INT_ID -#define XPAR_XWDTPS_1_INTR XPS_LPD_SWDT_INT_ID -#define XPAR_XWDTPS_2_INTR XPS_FPD_SWDT_INT_ID -#define XPAR_XDCFG_0_INTR XPS_DVC_INT_ID -#define XPAR_XTTCPS_0_INTR XPS_TTC0_0_INT_ID -#define XPAR_XTTCPS_1_INTR XPS_TTC0_1_INT_ID -#define XPAR_XTTCPS_2_INTR XPS_TTC0_2_INT_ID -#define XPAR_XTTCPS_3_INTR XPS_TTC1_0_INT_ID -#define XPAR_XTTCPS_4_INTR XPS_TTC1_1_INT_ID -#define XPAR_XTTCPS_5_INTR XPS_TTC1_2_INT_ID -#define XPAR_XTTCPS_6_INTR XPS_TTC2_0_INT_ID -#define XPAR_XTTCPS_7_INTR XPS_TTC2_1_INT_ID -#define XPAR_XTTCPS_8_INTR XPS_TTC2_2_INT_ID -#define XPAR_XTTCPS_9_INTR XPS_TTC3_0_INT_ID -#define XPAR_XTTCPS_10_INTR XPS_TTC3_1_INT_ID -#define XPAR_XTTCPS_11_INTR XPS_TTC3_2_INT_ID -#define XPAR_XNANDPS8_0_INTR XPS_NAND_INT_ID -#define XPAR_XADMAPS_0_INTR XPS_ADMA_CH0_INT_ID -#define XPAR_XADMAPS_1_INTR XPS_ADMA_CH1_INT_ID -#define XPAR_XADMAPS_2_INTR XPS_ADMA_CH2_INT_ID -#define XPAR_XADMAPS_3_INTR XPS_ADMA_CH3_INT_ID -#define XPAR_XADMAPS_4_INTR XPS_ADMA_CH4_INT_ID -#define XPAR_XADMAPS_5_INTR XPS_ADMA_CH5_INT_ID -#define XPAR_XADMAPS_6_INTR XPS_ADMA_CH6_INT_ID -#define XPAR_XADMAPS_7_INTR XPS_ADMA_CH7_INT_ID -#define XPAR_XCSUDMA_INTR XPS_CSU_DMA_INT_ID -#define XPAR_PSU_ADMA_0_INTR XPS_ADMA_CH0_INT_ID -#define XPAR_PSU_ADMA_1_INTR XPS_ADMA_CH1_INT_ID -#define XPAR_PSU_ADMA_2_INTR XPS_ADMA_CH2_INT_ID -#define XPAR_PSU_ADMA_3_INTR XPS_ADMA_CH3_INT_ID -#define XPAR_PSU_ADMA_4_INTR XPS_ADMA_CH4_INT_ID -#define XPAR_PSU_ADMA_5_INTR XPS_ADMA_CH5_INT_ID -#define XPAR_PSU_ADMA_6_INTR XPS_ADMA_CH6_INT_ID -#define XPAR_PSU_ADMA_7_INTR XPS_ADMA_CH7_INT_ID -#define XPAR_PSU_CSUDMA_INTR XPS_CSU_DMA_INT_ID -#define XPAR_XMPU_LPD_INTR XPS_XMPU_LPD_INT_ID -#define XPAR_XZDMAPS_0_INTR XPS_ZDMA_CH0_INT_ID -#define XPAR_XZDMAPS_1_INTR XPS_ZDMA_CH1_INT_ID -#define XPAR_XZDMAPS_2_INTR XPS_ZDMA_CH2_INT_ID -#define XPAR_XZDMAPS_3_INTR XPS_ZDMA_CH3_INT_ID -#define XPAR_XZDMAPS_4_INTR XPS_ZDMA_CH4_INT_ID -#define XPAR_XZDMAPS_5_INTR XPS_ZDMA_CH5_INT_ID -#define XPAR_XZDMAPS_6_INTR XPS_ZDMA_CH6_INT_ID -#define XPAR_XZDMAPS_7_INTR XPS_ZDMA_CH7_INT_ID -#define XPAR_PSU_GDMA_0_INTR XPS_ZDMA_CH0_INT_ID -#define XPAR_PSU_GDMA_1_INTR XPS_ZDMA_CH1_INT_ID -#define XPAR_PSU_GDMA_2_INTR XPS_ZDMA_CH2_INT_ID -#define XPAR_PSU_GDMA_3_INTR XPS_ZDMA_CH3_INT_ID -#define XPAR_PSU_GDMA_4_INTR XPS_ZDMA_CH4_INT_ID -#define XPAR_PSU_GDMA_5_INTR XPS_ZDMA_CH5_INT_ID -#define XPAR_PSU_GDMA_6_INTR XPS_ZDMA_CH6_INT_ID -#define XPAR_PSU_GDMA_7_INTR XPS_ZDMA_CH7_INT_ID -#define XPAR_XMPU_FPD_INTR XPS_XMPU_FPD_INT_ID -#define XPAR_XCCI_FPD_INTR XPS_FPD_CCI_INT_ID -#define XPAR_XSMMU_FPD_INTR XPS_FPD_SMMU_INT_ID -#define XPAR_XUSBPS_0_INTR XPS_USB3_0_ENDPT_INT_ID -#define XPAR_XUSBPS_1_INTR XPS_USB3_1_ENDPT_INT_ID -#define XPAR_XUSBPS_0_WAKE_INTR XPS_USB3_0_WAKE_INT_ID -#define XPAR_XUSBPS_1_WAKE_INTR XPS_USB3_1_WAKE_INT_ID -#define XPAR_XRTCPSU_ALARM_INTR XPS_RTC_ALARM_INT_ID -#define XPAR_XRTCPSU_SECONDS_INTR XPS_RTC_SEC_INT_ID -#define XPAR_XAPMPS_0_INTR XPS_APM0_INT_ID -#define XPAR_XAPMPS_1_INTR XPS_APM1_INT_ID -#define XPAR_XAPMPS_2_INTR XPS_APM2_INT_ID -#define XPAR_XAPMPS_5_INTR XPS_APM5_INT_ID -#define XPAR_XSYSMONPSU_INTR XPS_AMS_INT_ID +#define XPAR_XUARTPS_0_INTR XPS_UART0_INT_ID +#define XPAR_XUARTPS_1_INTR XPS_UART1_INT_ID +#define XPAR_XIICPS_0_INTR XPS_I2C0_INT_ID +#define XPAR_XIICPS_1_INTR XPS_I2C1_INT_ID +#define XPAR_XSPIPS_0_INTR XPS_SPI0_INT_ID +#define XPAR_XSPIPS_1_INTR XPS_SPI1_INT_ID +#define XPAR_XCANPS_0_INTR XPS_CAN0_INT_ID +#define XPAR_XCANPS_1_INTR XPS_CAN1_INT_ID +#define XPAR_XGPIOPS_0_INTR XPS_GPIO_INT_ID +#define XPAR_XEMACPS_0_INTR XPS_GEM0_INT_ID +#define XPAR_XEMACPS_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_XEMACPS_1_INTR XPS_GEM1_INT_ID +#define XPAR_XEMACPS_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_XEMACPS_2_INTR XPS_GEM2_INT_ID +#define XPAR_XEMACPS_2_WAKE_INTR XPS_GEM2_WAKE_INT_ID +#define XPAR_XEMACPS_3_INTR XPS_GEM3_INT_ID +#define XPAR_XEMACPS_3_WAKE_INTR XPS_GEM3_WAKE_INT_ID +#define XPAR_XSDIOPS_0_INTR XPS_SDIO0_INT_ID +#define XPAR_XQSPIPS_0_INTR XPS_QSPI_INT_ID +#define XPAR_XSDIOPS_1_INTR XPS_SDIO1_INT_ID +#define XPAR_XWDTPS_0_INTR XPS_CSU_WDT_INT_ID +#define XPAR_XWDTPS_1_INTR XPS_LPD_SWDT_INT_ID +#define XPAR_XWDTPS_2_INTR XPS_FPD_SWDT_INT_ID +#define XPAR_XDCFG_0_INTR XPS_DVC_INT_ID +#define XPAR_XTTCPS_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_XTTCPS_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_XTTCPS_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_XTTCPS_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_XTTCPS_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_XTTCPS_5_INTR XPS_TTC1_2_INT_ID +#define XPAR_XTTCPS_6_INTR XPS_TTC2_0_INT_ID +#define XPAR_XTTCPS_7_INTR XPS_TTC2_1_INT_ID +#define XPAR_XTTCPS_8_INTR XPS_TTC2_2_INT_ID +#define XPAR_XTTCPS_9_INTR XPS_TTC3_0_INT_ID +#define XPAR_XTTCPS_10_INTR XPS_TTC3_1_INT_ID +#define XPAR_XTTCPS_11_INTR XPS_TTC3_2_INT_ID +#define XPAR_XNANDPS8_0_INTR XPS_NAND_INT_ID +#define XPAR_XADMAPS_0_INTR XPS_ADMA_CH0_INT_ID +#define XPAR_XADMAPS_1_INTR XPS_ADMA_CH1_INT_ID +#define XPAR_XADMAPS_2_INTR XPS_ADMA_CH2_INT_ID +#define XPAR_XADMAPS_3_INTR XPS_ADMA_CH3_INT_ID +#define XPAR_XADMAPS_4_INTR XPS_ADMA_CH4_INT_ID +#define XPAR_XADMAPS_5_INTR XPS_ADMA_CH5_INT_ID +#define XPAR_XADMAPS_6_INTR XPS_ADMA_CH6_INT_ID +#define XPAR_XADMAPS_7_INTR XPS_ADMA_CH7_INT_ID +#define XPAR_XCSUDMA_INTR XPS_CSU_DMA_INT_ID +#define XPAR_PSU_ADMA_0_INTR XPS_ADMA_CH0_INT_ID +#define XPAR_PSU_ADMA_1_INTR XPS_ADMA_CH1_INT_ID +#define XPAR_PSU_ADMA_2_INTR XPS_ADMA_CH2_INT_ID +#define XPAR_PSU_ADMA_3_INTR XPS_ADMA_CH3_INT_ID +#define XPAR_PSU_ADMA_4_INTR XPS_ADMA_CH4_INT_ID +#define XPAR_PSU_ADMA_5_INTR XPS_ADMA_CH5_INT_ID +#define XPAR_PSU_ADMA_6_INTR XPS_ADMA_CH6_INT_ID +#define XPAR_PSU_ADMA_7_INTR XPS_ADMA_CH7_INT_ID +#define XPAR_PSU_CSUDMA_INTR XPS_CSU_DMA_INT_ID +#define XPAR_XMPU_LPD_INTR XPS_XMPU_LPD_INT_ID +#define XPAR_XZDMAPS_0_INTR XPS_ZDMA_CH0_INT_ID +#define XPAR_XZDMAPS_1_INTR XPS_ZDMA_CH1_INT_ID +#define XPAR_XZDMAPS_2_INTR XPS_ZDMA_CH2_INT_ID +#define XPAR_XZDMAPS_3_INTR XPS_ZDMA_CH3_INT_ID +#define XPAR_XZDMAPS_4_INTR XPS_ZDMA_CH4_INT_ID +#define XPAR_XZDMAPS_5_INTR XPS_ZDMA_CH5_INT_ID +#define XPAR_XZDMAPS_6_INTR XPS_ZDMA_CH6_INT_ID +#define XPAR_XZDMAPS_7_INTR XPS_ZDMA_CH7_INT_ID +#define XPAR_PSU_GDMA_0_INTR XPS_ZDMA_CH0_INT_ID +#define XPAR_PSU_GDMA_1_INTR XPS_ZDMA_CH1_INT_ID +#define XPAR_PSU_GDMA_2_INTR XPS_ZDMA_CH2_INT_ID +#define XPAR_PSU_GDMA_3_INTR XPS_ZDMA_CH3_INT_ID +#define XPAR_PSU_GDMA_4_INTR XPS_ZDMA_CH4_INT_ID +#define XPAR_PSU_GDMA_5_INTR XPS_ZDMA_CH5_INT_ID +#define XPAR_PSU_GDMA_6_INTR XPS_ZDMA_CH6_INT_ID +#define XPAR_PSU_GDMA_7_INTR XPS_ZDMA_CH7_INT_ID +#define XPAR_XMPU_FPD_INTR XPS_XMPU_FPD_INT_ID +#define XPAR_XCCI_FPD_INTR XPS_FPD_CCI_INT_ID +#define XPAR_XSMMU_FPD_INTR XPS_FPD_SMMU_INT_ID +#define XPAR_XUSBPS_0_INTR XPS_USB3_0_ENDPT_INT_ID +#define XPAR_XUSBPS_1_INTR XPS_USB3_1_ENDPT_INT_ID +#define XPAR_XUSBPS_0_WAKE_INTR XPS_USB3_0_WAKE_INT_ID +#define XPAR_XUSBPS_1_WAKE_INTR XPS_USB3_1_WAKE_INT_ID +#define XPAR_XRTCPSU_ALARM_INTR XPS_RTC_ALARM_INT_ID +#define XPAR_XRTCPSU_SECONDS_INTR XPS_RTC_SEC_INT_ID +#define XPAR_XAPMPS_0_INTR XPS_APM0_INT_ID +#define XPAR_XAPMPS_1_INTR XPS_APM1_INT_ID +#define XPAR_XAPMPS_2_INTR XPS_APM2_INT_ID +#define XPAR_XAPMPS_5_INTR XPS_APM5_INT_ID +#define XPAR_XSYSMONPSU_INTR XPS_AMS_INT_ID /* Canonical definitions for SCU GIC */ -#define XPAR_SCUGIC_NUM_INSTANCES 1U -#define XPAR_SCUGIC_SINGLE_DEVICE_ID 0U +#define XPAR_SCUGIC_NUM_INSTANCES 1U +#define XPAR_SCUGIC_SINGLE_DEVICE_ID 0U #define XPAR_SCUGIC_CPU_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00001000U) #define XPAR_SCUGIC_DIST_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00002000U) -#define XPAR_SCUGIC_ACK_BEFORE 0U +#define XPAR_SCUGIC_ACK_BEFORE 0U -#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ /* @@ -154,27 +154,27 @@ extern "C" { * within the hardblock. These have been put for bacwards compatibility */ -#define XPS_SYS_CTRL_BASEADDR 0xFF180000U -#define XPS_SCU_PERIPH_BASE 0xF9000000U +#define XPS_SYS_CTRL_BASEADDR 0xFF180000U +#define XPS_SCU_PERIPH_BASE 0xF9000000U /* Shared Peripheral Interrupts (SPI) */ -#define XPS_FPGA0_INT_ID 121U -#define XPS_FPGA1_INT_ID 122U -#define XPS_FPGA2_INT_ID 123U -#define XPS_FPGA3_INT_ID 124U -#define XPS_FPGA4_INT_ID 125U -#define XPS_FPGA5_INT_ID 126U -#define XPS_FPGA6_INT_ID 127U -#define XPS_FPGA7_INT_ID 128U -#define XPS_FPGA8_INT_ID 136U -#define XPS_FPGA9_INT_ID 137U -#define XPS_FPGA10_INT_ID 138U -#define XPS_FPGA11_INT_ID 139U -#define XPS_FPGA12_INT_ID 140U -#define XPS_FPGA13_INT_ID 141U -#define XPS_FPGA14_INT_ID 142U -#define XPS_FPGA15_INT_ID 143U +#define XPS_FPGA0_INT_ID 121U +#define XPS_FPGA1_INT_ID 122U +#define XPS_FPGA2_INT_ID 123U +#define XPS_FPGA3_INT_ID 124U +#define XPS_FPGA4_INT_ID 125U +#define XPS_FPGA5_INT_ID 126U +#define XPS_FPGA6_INT_ID 127U +#define XPS_FPGA7_INT_ID 128U +#define XPS_FPGA8_INT_ID 136U +#define XPS_FPGA9_INT_ID 137U +#define XPS_FPGA10_INT_ID 138U +#define XPS_FPGA11_INT_ID 139U +#define XPS_FPGA12_INT_ID 140U +#define XPS_FPGA13_INT_ID 141U +#define XPS_FPGA14_INT_ID 142U +#define XPS_FPGA15_INT_ID 143U /* Updated Interrupt-IDs */ #define XPS_OCMINTR_INT_ID (10U + 32U) @@ -189,8 +189,8 @@ extern "C" { #define XPS_UART1_INT_ID (22U + 32U) #define XPS_CAN0_INT_ID (23U + 32U) #define XPS_CAN1_INT_ID (24U + 32U) -#define XPS_RTC_ALARM_INT_ID (26U + 32U) -#define XPS_RTC_SEC_INT_ID (27U + 32U) +#define XPS_RTC_ALARM_INT_ID (26U + 32U) +#define XPS_RTC_SEC_INT_ID (27U + 32U) #define XPS_LPD_SWDT_INT_ID (52U + 32U) #define XPS_CSU_WDT_INT_ID (53U + 32U) #define XPS_FPD_SWDT_INT_ID (113U + 32U) @@ -268,8 +268,8 @@ extern "C" { #define XPAR_PSU_ETHERNET_3_INTR XPS_GEM3_INT_ID #define XPAR_PSU_ETHERNET_3_WAKE_INTR XPS_GEM3_WAKE_INT_ID #define XPAR_PSU_QSPI_0_INTR XPS_QSPI_INT_ID -#define XPAR_PSU_WDT_0_INTR XPS_LPD_SWDT_INT_ID -#define XPAR_PSU_WDT_1_INTR XPS_FPD_SWDT_INT_ID +#define XPAR_PSU_WDT_0_INTR XPS_LPD_SWDT_INT_ID +#define XPAR_PSU_WDT_1_INTR XPS_FPD_SWDT_INT_ID #define XPAR_PSU_XADC_0_INTR XPS_SYSMON_INT_ID #define XPAR_PSU_TTC_0_INTR XPS_TTC0_0_INT_ID #define XPAR_PSU_TTC_1_INTR XPS_TTC0_1_INT_ID @@ -277,42 +277,42 @@ extern "C" { #define XPAR_PSU_TTC_3_INTR XPS_TTC1_0_INT_ID #define XPAR_PSU_TTC_4_INTR XPS_TTC1_1_INT_ID #define XPAR_PSU_TTC_5_INTR XPS_TTC1_2_INT_ID -#define XPAR_PSU_TTC_6_INTR XPS_TTC2_0_INT_ID -#define XPAR_PSU_TTC_7_INTR XPS_TTC2_1_INT_ID -#define XPAR_PSU_TTC_8_INTR XPS_TTC2_2_INT_ID -#define XPAR_PSU_TTC_9_INTR XPS_TTC3_0_INT_ID -#define XPAR_PSU_TTC_10_INTR XPS_TTC3_1_INT_ID -#define XPAR_PSU_TTC_11_INTR XPS_TTC3_2_INT_ID -#define XPAR_PSU_AMS_INTR XPS_AMS_INT_ID +#define XPAR_PSU_TTC_6_INTR XPS_TTC2_0_INT_ID +#define XPAR_PSU_TTC_7_INTR XPS_TTC2_1_INT_ID +#define XPAR_PSU_TTC_8_INTR XPS_TTC2_2_INT_ID +#define XPAR_PSU_TTC_9_INTR XPS_TTC3_0_INT_ID +#define XPAR_PSU_TTC_10_INTR XPS_TTC3_1_INT_ID +#define XPAR_PSU_TTC_11_INTR XPS_TTC3_2_INT_ID +#define XPAR_PSU_AMS_INTR XPS_AMS_INT_ID #define XPAR_XADCPS_NUM_INSTANCES 1U #define XPAR_XADCPS_0_DEVICE_ID 0U #define XPAR_XADCPS_0_BASEADDR (0xF8007000U) -#define XPAR_XADCPS_INT_ID XPS_SYSMON_INT_ID +#define XPAR_XADCPS_INT_ID XPS_SYSMON_INT_ID /* For backwards compatibility */ -#define XPAR_XUARTPS_0_CLOCK_HZ XPAR_XUARTPS_0_UART_CLK_FREQ_HZ -#define XPAR_XUARTPS_1_CLOCK_HZ XPAR_XUARTPS_1_UART_CLK_FREQ_HZ -#define XPAR_XTTCPS_0_CLOCK_HZ XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ -#define XPAR_XTTCPS_1_CLOCK_HZ XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ -#define XPAR_XTTCPS_2_CLOCK_HZ XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ -#define XPAR_XTTCPS_3_CLOCK_HZ XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ -#define XPAR_XTTCPS_4_CLOCK_HZ XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ -#define XPAR_XTTCPS_5_CLOCK_HZ XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ -#define XPAR_XIICPS_0_CLOCK_HZ XPAR_XIICPS_0_I2C_CLK_FREQ_HZ -#define XPAR_XIICPS_1_CLOCK_HZ XPAR_XIICPS_1_I2C_CLK_FREQ_HZ +#define XPAR_XUARTPS_0_CLOCK_HZ XPAR_XUARTPS_0_UART_CLK_FREQ_HZ +#define XPAR_XUARTPS_1_CLOCK_HZ XPAR_XUARTPS_1_UART_CLK_FREQ_HZ +#define XPAR_XTTCPS_0_CLOCK_HZ XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_1_CLOCK_HZ XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_2_CLOCK_HZ XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_3_CLOCK_HZ XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_4_CLOCK_HZ XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_5_CLOCK_HZ XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ +#define XPAR_XIICPS_0_CLOCK_HZ XPAR_XIICPS_0_I2C_CLK_FREQ_HZ +#define XPAR_XIICPS_1_CLOCK_HZ XPAR_XIICPS_1_I2C_CLK_FREQ_HZ -#define XPAR_XQSPIPS_0_CLOCK_HZ XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ +#define XPAR_XQSPIPS_0_CLOCK_HZ XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ #ifdef XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ -#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ #endif #ifdef XPAR_CPU_CORTEXR5_1_CPU_CLK_FREQ_HZ -#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXR5_1_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXR5_1_CPU_CLK_FREQ_HZ #endif -#define XPAR_SCUWDT_DEVICE_ID 0U +#define XPAR_SCUWDT_DEVICE_ID 0U #ifdef __cplusplus diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h index 534785e134..7a55d8b0b5 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h @@ -12,12 +12,12 @@ extern "C" { #define XPAR_PMC_TAP_BASEADDR 0xF11A0000U #define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U #define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \ - XPAR_PMC_TAP_VERSION_OFFSET) + XPAR_PMC_TAP_VERSION_OFFSET) #else #define XPAR_CSU_BASEADDR 0xFFCA0000U -#define XPAR_CSU_VER_OFFSET 0x00000044U +#define XPAR_CSU_VER_OFFSET 0x00000044U #define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \ - XPAR_CSU_VER_OFFSET) + XPAR_CSU_VER_OFFSET) #endif #define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0 #define XPLAT_ZYNQ_ULTRA_MP 0x1 @@ -44,13 +44,13 @@ extern "C" { static INLINE u32 XGetPlatform_Info() { #if defined (versal) - return XPLAT_VERSAL; + return XPLAT_VERSAL; #elif defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU) - return XPLAT_ZYNQ_ULTRA_MP; + return XPLAT_ZYNQ_ULTRA_MP; #elif (__microblaze__) - return XPLAT_MICROBLAZE; + return XPLAT_MICROBLAZE; #else - return XPLAT_ZYNQ; + return XPLAT_ZYNQ; #endif } diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xstatus.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xstatus.h index 035aed445a..8d4d0ac61a 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xstatus.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xstatus.h @@ -87,7 +87,7 @@ extern "C" { #define XST_NOT_ENABLED 29L /*!< A requested service is not available because it has not been enabled */ -#define XST_NO_ACCESS 30L /* Generic access error */ +#define XST_NO_ACCESS 30L /* Generic access error */ #define XST_TIMEOUT 31L /*!< Event timeout occurred */ /** @} */ @@ -258,7 +258,7 @@ extern "C" { #define XST_IIC_TBA_READBACK_ERROR 1087 /*!< Read of the 10 bit addr reg */ /* didn't return written value */ #define XST_IIC_NOT_SLAVE 1088 /*!< The device isn't a slave */ -#define XST_IIC_ARB_LOST 1089 /*!< Arbitration lost for master */ +#define XST_IIC_ARB_LOST 1089 /*!< Arbitration lost for master */ /** @} */ /** @name ATMC Status Codes 1101 - 1125 @@ -422,10 +422,10 @@ extern "C" { */ /********************** FlexRay constants 1400 - 1409 *************************/ -#define XST_FR_TX_ERROR 1400 -#define XST_FR_TX_BUSY 1401 -#define XST_FR_BUF_LOCKED 1402 -#define XST_FR_NO_BUF 1403 +#define XST_FR_TX_ERROR 1400 +#define XST_FR_TX_BUSY 1401 +#define XST_FR_BUF_LOCKED 1402 +#define XST_FR_NO_BUF 1403 /** @} */ /** @name USB constants 1410 - 1420 @@ -433,11 +433,11 @@ extern "C" { */ /****************** USB constants 1410 - 1420 *******************************/ -#define XST_USB_ALREADY_CONFIGURED 1410 -#define XST_USB_BUF_ALIGN_ERROR 1411 -#define XST_USB_NO_DESC_AVAILABLE 1412 -#define XST_USB_BUF_TOO_BIG 1413 -#define XST_USB_NO_BUF 1414 +#define XST_USB_ALREADY_CONFIGURED 1410 +#define XST_USB_BUF_ALIGN_ERROR 1411 +#define XST_USB_NO_DESC_AVAILABLE 1412 +#define XST_USB_BUF_TOO_BIG 1413 +#define XST_USB_NO_BUF 1414 /** @} */ /** @name HWICAP constants 1421 - 1429 @@ -445,7 +445,7 @@ extern "C" { */ /****************** HWICAP constants 1421 - 1429 *****************************/ -#define XST_HWICAP_WRITE_DONE 1421 +#define XST_HWICAP_WRITE_DONE 1421 /** @} */ /** @@ -454,7 +454,7 @@ extern "C" { */ /****************** AXI VDMA constants 1430 - 1440 *****************************/ -#define XST_VDMA_MISMATCH_ERROR 1430 +#define XST_VDMA_MISMATCH_ERROR 1430 /** @} */ /** @name NAND Flash Status Codes 1441 - 1459 @@ -462,35 +462,35 @@ extern "C" { */ /*********************** NAND Flash statuses 1441 - 1459 *********************/ -#define XST_NAND_BUSY 1441L /*!< Flash is erasing or +#define XST_NAND_BUSY 1441L /*!< Flash is erasing or * programming */ -#define XST_NAND_READY 1442L /*!< Flash is ready for commands +#define XST_NAND_READY 1442L /*!< Flash is ready for commands */ -#define XST_NAND_ERROR 1443L /*!< Flash had detected an +#define XST_NAND_ERROR 1443L /*!< Flash had detected an * internal error. */ -#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by +#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by * driver */ -#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported +#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported */ -#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase +#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase * operation aborted due to a * timeout */ -#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its +#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its * addressible range */ -#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error +#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error */ -#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter +#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter * page of the device */ -#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error +#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error */ -#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected +#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected */ /** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c b/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c index 758fc138df..e3e1884cf2 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c @@ -64,7 +64,7 @@ void rt_zynqmp_eth_link_detect(struct rt_zynqmp_eth *eth_dev) if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) || (eth_link_status == ETH_LINK_UNDEFINED)) return; - + phy_link_status = phy_link_detect(xemacp, phyaddrforemac); if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status)) @@ -173,7 +173,7 @@ static rt_err_t rt_zynqmp_eth_init(rt_device_t dev) setup_isr(xemac); init_dma(xemac); - + xtopologyp = &xtopology[xemac->topology_index]; /* * Connect the device driver handler that will be called when an @@ -190,7 +190,7 @@ static rt_err_t rt_zynqmp_eth_init(rt_device_t dev) if (eth_link_status == ETH_LINK_UP) eth_device_linkchange(ð_dev->parent, RT_TRUE); - + rt_thread_t tid; tid = rt_thread_create("phylnk", phy_monitor_thread, diff --git a/bsp/zynqmp-r5-axu4ev/drivers/drv_timer.c b/bsp/zynqmp-r5-axu4ev/drivers/drv_timer.c index 7b0c582790..cf59954d4b 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/drv_timer.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/drv_timer.c @@ -47,10 +47,10 @@ static int rt_hw_timer_init(void) /* Setup interval */ TTC_INTERVAL_VAL(TTC0_0_BASEADDR) = TTC0_0_CLK_FREQ_HZ / RT_TICK_PER_SECOND; /* Clear all of the prescaler control bits in the register */ - TTC_CLK_CNTRL(TTC0_0_BASEADDR) &= ~(TTC_CLK_CNTRL_PS_VAL_MASK | + TTC_CLK_CNTRL(TTC0_0_BASEADDR) &= ~(TTC_CLK_CNTRL_PS_VAL_MASK | TTC_CLK_CNTRL_PS_EN_MASK); /* We do not need a prescaler*/ - + /* Register the ticker handler with the GIC */ rt_hw_interrupt_install(XPAR_XTTCPS_0_INTR, rt_hw_timer_isr, RT_NULL, "tick"); /* Enable TTC interrupts in the GIC */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h b/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h index 6b2be30120..bd8fb38eb4 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h @@ -9,11 +9,11 @@ #define __REG8(x) (*((volatile rt_uint8_t *)(x))) #define ZynqMP_CRL_APB_BASEADDR XPAR_PSU_CRL_APB_S_AXI_BASEADDR -#define ZynqMP_CRL_APB_IOPLL_CTRL 0x020 -#define ZynqMP_CRL_APB_IOPLL_CFG 0x024 -#define ZynqMP_CRL_APB_UART0_REF_CTRL 0x074 -#define ZynqMP_CRL_APB_UART1_REF_CTRL 0x078 -#define ZynqMP_CRL_APB_LPD_LSBUS_CTRL 0x0AC +#define ZynqMP_CRL_APB_IOPLL_CTRL 0x020 +#define ZynqMP_CRL_APB_IOPLL_CFG 0x024 +#define ZynqMP_CRL_APB_UART0_REF_CTRL 0x074 +#define ZynqMP_CRL_APB_UART1_REF_CTRL 0x078 +#define ZynqMP_CRL_APB_LPD_LSBUS_CTRL 0x0AC #define ZynqMP_CRL_APB_RESET_CTRL 0x218 #define ZynqMP_RESET_MASK 0x10 From 956664eed955f302fd1af62590963fbbe9b7962a Mon Sep 17 00:00:00 2001 From: Wang-Huachen Date: Fri, 14 May 2021 14:42:21 +0800 Subject: [PATCH 068/255] format files in zynqmp-r5-axu4ev bsp --- bsp/zynqmp-r5-axu4ev/applications/SConscript | 2 +- .../Zynq_HAL_Driver/emacps_v3_11/xemacps.c | 260 +-- .../Zynq_HAL_Driver/emacps_v3_11/xemacps.h | 134 +- .../Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h | 24 +- .../emacps_v3_11/xemacps_bdring.c | 508 +++--- .../emacps_v3_11/xemacps_bdring.h | 38 +- .../emacps_v3_11/xemacps_control.c | 828 ++++----- .../Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c | 10 +- .../Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c | 34 +- .../Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h | 142 +- .../emacps_v3_11/xemacps_intr.c | 208 +-- .../emacps_v3_11/xemacps_sinit.c | 10 +- .../Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c | 364 ++-- .../Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h | 106 +- .../Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c | 8 +- .../Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c | 2 +- .../Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h | 40 +- .../gpiops_v3_7/xgpiops_intr.c | 408 ++--- .../gpiops_v3_7/xgpiops_selftest.c | 36 +- .../gpiops_v3_7/xgpiops_sinit.c | 16 +- .../drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c | 218 +-- .../drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h | 124 +- .../Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c | 1102 ++++++------ .../Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c | 44 +- .../Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c | 1588 ++++++++--------- .../Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h | 1098 ++++++------ .../Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c | 412 ++--- .../Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c | 14 +- .../xemacpsif/netif/xadapter.h | 6 +- .../xemacpsif/netif/xemacpsif.h | 10 +- .../Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h | 6 +- .../xemacpsif/netif/xtopology.h | 2 +- .../Zynq_HAL_Driver/xemacpsif/xadapter.c | 266 +-- .../xemacpsif/xemac_ieee_reg.h | 2 +- .../Zynq_HAL_Driver/xemacpsif/xemacpsif.c | 452 ++--- .../Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c | 710 ++++---- .../Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c | 206 +-- .../xemacpsif/xemacpsif_physpeed.c | 938 +++++----- .../Zynq_HAL_Driver/xemacpsif/xpqueue.c | 12 +- .../Zynq_HAL_Driver/xemacpsif/xtopology_g.c | 16 +- .../drivers/Zynq_HAL_Driver/xil_io.h | 10 +- .../drivers/Zynq_HAL_Driver/xil_printf.h | 2 +- .../drivers/Zynq_HAL_Driver/xil_types.h | 28 +- .../drivers/Zynq_HAL_Driver/xparameters_ps.h | 384 ++-- .../drivers/Zynq_HAL_Driver/xplatform_info.h | 8 +- .../drivers/Zynq_HAL_Driver/xstatus.h | 522 +++--- bsp/zynqmp-r5-axu4ev/drivers/drv_sdcard.c | 16 +- bsp/zynqmp-r5-axu4ev/drivers/drv_uart.c | 14 +- bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h | 4 +- bsp/zynqmp-r5-axu4ev/rtconfig.py | 4 +- 50 files changed, 5698 insertions(+), 5698 deletions(-) diff --git a/bsp/zynqmp-r5-axu4ev/applications/SConscript b/bsp/zynqmp-r5-axu4ev/applications/SConscript index 01eb940dfb..02d700cc50 100644 --- a/bsp/zynqmp-r5-axu4ev/applications/SConscript +++ b/bsp/zynqmp-r5-axu4ev/applications/SConscript @@ -3,7 +3,7 @@ Import('rtconfig') from building import * cwd = os.path.join(str(Dir('#')), 'applications') -src = Glob('*.c') +src = Glob('*.c') CPPPATH = [cwd, str(Dir('#'))] group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c index 8142b7072b..80d1a74e42 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c @@ -20,7 +20,7 @@ * ----- ---- -------- ------------------------------------------------------- * 1.00a wsy 01/10/10 First release * 2.1 srt 07/15/14 Add support for Zynq Ultrascale Mp GEM specification and -* 64-bit changes. +* 64-bit changes. * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. * 3.0 hk 02/20/15 Added support for jumbo frames. Increase AHB burst. * Disable extended mode. Perform all 64 bit changes under @@ -51,7 +51,7 @@ /************************** Function Prototypes ******************************/ -void XEmacPs_StubHandler(void); /* Default handler routine */ +void XEmacPs_StubHandler(void); /* Default handler routine */ /************************** Variable Definitions *****************************/ @@ -78,13 +78,13 @@ void XEmacPs_StubHandler(void); /* Default handler routine */ * ******************************************************************************/ LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr, - UINTPTR EffectiveAddress) + UINTPTR EffectiveAddress) { - /* Verify arguments */ + /* Verify arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(CfgPtr != NULL); - /* Set device base address and ID */ + /* Set device base address and ID */ InstancePtr->Config.DeviceId = CfgPtr->DeviceId; InstancePtr->Config.BaseAddress = EffectiveAddress; InstancePtr->Config.IsCacheCoherent = CfgPtr->IsCacheCoherent; @@ -92,12 +92,12 @@ LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr, InstancePtr->Config.RefClk = CfgPtr->RefClk; #endif - /* Set callbacks to an initial stub routine */ + /* Set callbacks to an initial stub routine */ InstancePtr->SendHandler = ((XEmacPs_Handler)((void*)XEmacPs_StubHandler)); InstancePtr->RecvHandler = ((XEmacPs_Handler)(void*)XEmacPs_StubHandler); InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void*)XEmacPs_StubHandler); - /* Reset the hardware and set default options */ + /* Reset the hardware and set default options */ InstancePtr->IsReady = XIL_COMPONENT_IS_READY; XEmacPs_Reset(InstancePtr); @@ -136,68 +136,68 @@ void XEmacPs_Start(XEmacPs *InstancePtr) { u32 Reg; - /* Assert bad arguments and conditions */ + /* Assert bad arguments and conditions */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); #if defined (XCLOCKING) if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) { - Xil_ClockEnable(InstancePtr->Config.RefClk); - } + Xil_ClockEnable(InstancePtr->Config.RefClk); + } #endif - /* Start DMA */ - /* When starting the DMA channels, both transmit and receive sides - * need an initialized BD list. - */ + /* Start DMA */ + /* When starting the DMA channels, both transmit and receive sides + * need an initialized BD list. + */ if (InstancePtr->Version == 2) { - Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0); - Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0); + Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0); + Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0); XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_RXQBASE_OFFSET, - InstancePtr->RxBdRing.BaseBdAddr); + XEMACPS_RXQBASE_OFFSET, + InstancePtr->RxBdRing.BaseBdAddr); XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_TXQBASE_OFFSET, - InstancePtr->TxBdRing.BaseBdAddr); - } + XEMACPS_TXQBASE_OFFSET, + InstancePtr->TxBdRing.BaseBdAddr); + } - /* clear any existed int status */ + /* clear any existed int status */ XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, - XEMACPS_IXR_ALL_MASK); + XEMACPS_IXR_ALL_MASK); - /* Enable transmitter if not already enabled */ + /* Enable transmitter if not already enabled */ if ((InstancePtr->Options & (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION)!=0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - if ((!(Reg & XEMACPS_NWCTRL_TXEN_MASK))==TRUE) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, - Reg | (u32)XEMACPS_NWCTRL_TXEN_MASK); - } - } + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + if ((!(Reg & XEMACPS_NWCTRL_TXEN_MASK))==TRUE) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, + Reg | (u32)XEMACPS_NWCTRL_TXEN_MASK); + } + } - /* Enable receiver if not already enabled */ + /* Enable receiver if not already enabled */ if ((InstancePtr->Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - if ((!(Reg & XEMACPS_NWCTRL_RXEN_MASK))==TRUE) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, - Reg | (u32)XEMACPS_NWCTRL_RXEN_MASK); - } - } + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + if ((!(Reg & XEMACPS_NWCTRL_RXEN_MASK))==TRUE) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, + Reg | (u32)XEMACPS_NWCTRL_RXEN_MASK); + } + } /* Enable TX and RX interrupts */ XEmacPs_IntEnable(InstancePtr, (XEMACPS_IXR_TX_ERR_MASK | XEMACPS_IXR_RX_ERR_MASK | (u32)XEMACPS_IXR_FRAMERX_MASK | - (u32)XEMACPS_IXR_TXCOMPL_MASK)); + (u32)XEMACPS_IXR_TXCOMPL_MASK)); - /* Enable TX Q1 Interrupts */ + /* Enable TX Q1 Interrupts */ if (InstancePtr->Version > 2) - XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK); + XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK); - /* Mark as started */ + /* Mark as started */ InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; return; @@ -236,19 +236,19 @@ void XEmacPs_Stop(XEmacPs *InstancePtr) Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - /* Disable all interrupts */ + /* Disable all interrupts */ XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET, - XEMACPS_IXR_ALL_MASK); + XEMACPS_IXR_ALL_MASK); - /* Disable the receiver & transmitter */ + /* Disable the receiver & transmitter */ Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); + XEMACPS_NWCTRL_OFFSET); Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK); XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, Reg); + XEMACPS_NWCTRL_OFFSET, Reg); - /* Mark as stopped */ + /* Mark as stopped */ InstancePtr->IsStarted = 0U; #if defined (XCLOCKING) Xil_ClockDisable(InstancePtr->Config.RefClk); @@ -297,7 +297,7 @@ void XEmacPs_Reset(XEmacPs *InstancePtr) Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - /* Stop the device and reset hardware */ + /* Stop the device and reset hardware */ XEmacPs_Stop(InstancePtr); InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS; @@ -307,104 +307,104 @@ void XEmacPs_Reset(XEmacPs *InstancePtr) InstancePtr->MaxMtuSize = XEMACPS_MTU; InstancePtr->MaxFrameSize = XEMACPS_MTU + XEMACPS_HDR_SIZE + - XEMACPS_TRL_SIZE; + XEMACPS_TRL_SIZE; InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + - XEMACPS_HDR_VLAN_SIZE; + XEMACPS_HDR_VLAN_SIZE; InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK; - /* Setup hardware with default values */ + /* Setup hardware with default values */ XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, - (XEMACPS_NWCTRL_STATCLR_MASK | - XEMACPS_NWCTRL_MDEN_MASK) & - (u32)(~XEMACPS_NWCTRL_LOOPEN_MASK)); + XEMACPS_NWCTRL_OFFSET, + (XEMACPS_NWCTRL_STATCLR_MASK | + XEMACPS_NWCTRL_MDEN_MASK) & + (u32)(~XEMACPS_NWCTRL_LOOPEN_MASK)); Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET); + XEMACPS_NWCFG_OFFSET); Reg &= XEMACPS_NWCFG_MDCCLKDIV_MASK; Reg = Reg | (u32)XEMACPS_NWCFG_100_MASK | - (u32)XEMACPS_NWCFG_FDEN_MASK | - (u32)XEMACPS_NWCFG_UCASTHASHEN_MASK; + (u32)XEMACPS_NWCFG_FDEN_MASK | + (u32)XEMACPS_NWCFG_UCASTHASHEN_MASK; XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET, Reg); + XEMACPS_NWCFG_OFFSET, Reg); if (InstancePtr->Version > 2) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET, - (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET) | - XEMACPS_NWCFG_DWIDTH_64_MASK)); - } + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET, + (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET) | + XEMACPS_NWCFG_DWIDTH_64_MASK)); + } XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET, - (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) + - (((((u32)XEMACPS_RX_BUF_SIZE % - (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << - (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & - (u32)(XEMACPS_DMACR_RXBUF_MASK)) | - (u32)XEMACPS_DMACR_RXSIZE_MASK | - (u32)XEMACPS_DMACR_TXSIZE_MASK); + XEMACPS_DMACR_OFFSET, + (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) + + (((((u32)XEMACPS_RX_BUF_SIZE % + (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << + (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & + (u32)(XEMACPS_DMACR_RXBUF_MASK)) | + (u32)XEMACPS_DMACR_RXSIZE_MASK | + (u32)XEMACPS_DMACR_TXSIZE_MASK); if (InstancePtr->Version > 2) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, - (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET) | + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, + (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET) | #if defined(__aarch64__) || defined(__arch64__) - (u32)XEMACPS_DMACR_ADDR_WIDTH_64 | + (u32)XEMACPS_DMACR_ADDR_WIDTH_64 | #endif - (u32)XEMACPS_DMACR_INCR16_AHB_BURST)); - } + (u32)XEMACPS_DMACR_INCR16_AHB_BURST)); + } XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_TXSR_OFFSET, XEMACPS_SR_ALL_MASK); + XEMACPS_TXSR_OFFSET, XEMACPS_SR_ALL_MASK); XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_SEND); if (InstancePtr->Version > 2) - XEmacPs_SetQueuePtr(InstancePtr, 0, 0x01U, (u16)XEMACPS_SEND); + XEmacPs_SetQueuePtr(InstancePtr, 0, 0x01U, (u16)XEMACPS_SEND); XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_RECV); XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_RXSR_OFFSET, XEMACPS_SR_ALL_MASK); + XEMACPS_RXSR_OFFSET, XEMACPS_SR_ALL_MASK); XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET, - XEMACPS_IXR_ALL_MASK); + XEMACPS_IXR_ALL_MASK); Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_ISR_OFFSET); + XEMACPS_ISR_OFFSET); XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, - Reg); + Reg); XEmacPs_ClearHash(InstancePtr); for (i = 1U; i < 5U; i++) { - (void)XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i); - (void)XEmacPs_SetTypeIdCheck(InstancePtr, 0x00000000U, i); - } + (void)XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i); + (void)XEmacPs_SetTypeIdCheck(InstancePtr, 0x00000000U, i); + } - /* clear all counters */ + /* clear all counters */ for (i = 0U; i < (u8)((XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4U); - i++) { - (void)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + i++) { + (void)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_OCTTXL_OFFSET + (u32)(((u32)i) * ((u32)4))); - } + } - /* Disable the receiver */ + /* Disable the receiver */ Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); + XEMACPS_NWCTRL_OFFSET); Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, Reg); + XEMACPS_NWCTRL_OFFSET, Reg); - /* Sync default options with hardware but leave receiver and + /* Sync default options with hardware but leave receiver and * transmitter disabled. They get enabled with XEmacPs_Start() if - * XEMACPS_TRANSMITTER_ENABLE_OPTION and + * XEMACPS_TRANSMITTER_ENABLE_OPTION and * XEMACPS_RECEIVER_ENABLE_OPTION are set. - */ - (void)XEmacPs_SetOptions(InstancePtr, InstancePtr->Options & - ~((u32)XEMACPS_TRANSMITTER_ENABLE_OPTION | - (u32)XEMACPS_RECEIVER_ENABLE_OPTION)); + */ + (void)XEmacPs_SetOptions(InstancePtr, InstancePtr->Options & + ~((u32)XEMACPS_TRANSMITTER_ENABLE_OPTION | + (u32)XEMACPS_RECEIVER_ENABLE_OPTION)); - (void)XEmacPs_ClearOptions(InstancePtr, ~InstancePtr->Options); + (void)XEmacPs_ClearOptions(InstancePtr, ~InstancePtr->Options); } @@ -436,9 +436,9 @@ void XEmacPs_StubHandler(void) * ******************************************************************************/ void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum, - u16 Direction) + u16 Direction) { - /* Assert bad arguments and conditions */ + /* Assert bad arguments and conditions */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); @@ -448,33 +448,33 @@ void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum, } if (QueueNum == 0x00U) { - if (Direction == XEMACPS_SEND) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_TXQBASE_OFFSET, - (QPtr & ULONG64_LO_MASK)); - } else { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_RXQBASE_OFFSET, - (QPtr & ULONG64_LO_MASK)); - } - } - else { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_TXQ1BASE_OFFSET, - (QPtr & ULONG64_LO_MASK)); - } + if (Direction == XEMACPS_SEND) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXQBASE_OFFSET, + (QPtr & ULONG64_LO_MASK)); + } else { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXQBASE_OFFSET, + (QPtr & ULONG64_LO_MASK)); + } + } + else { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXQ1BASE_OFFSET, + (QPtr & ULONG64_LO_MASK)); + } #ifdef __aarch64__ if (Direction == XEMACPS_SEND) { - /* Set the MSB of TX Queue start address */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_MSBBUF_TXQBASE_OFFSET, - (u32)((QPtr & ULONG64_HI_MASK) >> 32U)); - } else { - /* Set the MSB of RX Queue start address */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_MSBBUF_RXQBASE_OFFSET, - (u32)((QPtr & ULONG64_HI_MASK) >> 32U)); - } + /* Set the MSB of TX Queue start address */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_MSBBUF_TXQBASE_OFFSET, + (u32)((QPtr & ULONG64_HI_MASK) >> 32U)); + } else { + /* Set the MSB of RX Queue start address */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_MSBBUF_RXQBASE_OFFSET, + (u32)((QPtr & ULONG64_HI_MASK) >> 32U)); + } #endif } /** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h index cfb387a371..0114274b0f 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h @@ -241,46 +241,46 @@ * ----- ---- -------- ------------------------------------------------------- * 1.00a wsy 01/10/10 First release * 1.00a asa 11/21/11 The function XEmacPs_BdRingFromHwTx in file - * xemacps_bdring.c is modified. Earlier it was checking for - * "BdLimit"(passed argument) number of BDs for finding out - * which BDs are successfully processed. Now one more check - * is added. It looks for BDs till the current BD pointer - * reaches HwTail. By doing this processing time is saved. + * xemacps_bdring.c is modified. Earlier it was checking for + * "BdLimit"(passed argument) number of BDs for finding out + * which BDs are successfully processed. Now one more check + * is added. It looks for BDs till the current BD pointer + * reaches HwTail. By doing this processing time is saved. * 1.00a asa 01/24/12 The function XEmacPs_BdRingFromHwTx in file - * xemacps_bdring.c is modified. Now start of packet is - * searched for returning the number of BDs processed. + * xemacps_bdring.c is modified. Now start of packet is + * searched for returning the number of BDs processed. * 1.02a asa 11/05/12 Added a new API for deleting an entry from the HASH - * registers. Added a new API to set the bust length. - * Added some new hash-defines. + * registers. Added a new API to set the bust length. + * Added some new hash-defines. * 1.03a asa 01/23/12 Fix for CR #692702 which updates error handling for - * Rx errors. Under heavy Rx traffic, there will be a large - * number of errors related to receive buffer not available. - * Because of a HW bug (SI #692601), under such heavy errors, - * the Rx data path can become unresponsive. To reduce the - * probabilities for hitting this HW bug, the SW writes to - * bit 18 to flush a packet from Rx DPRAM immediately. The - * changes for it are done in the function - * XEmacPs_IntrHandler. + * Rx errors. Under heavy Rx traffic, there will be a large + * number of errors related to receive buffer not available. + * Because of a HW bug (SI #692601), under such heavy errors, + * the Rx data path can become unresponsive. To reduce the + * probabilities for hitting this HW bug, the SW writes to + * bit 18 to flush a packet from Rx DPRAM immediately. The + * changes for it are done in the function + * XEmacPs_IntrHandler. * 1.05a asa 09/23/13 Cache operations on BDs are not required and hence - * removed. It is expected that all BDs are allocated in - * from uncached area. + * removed. It is expected that all BDs are allocated in + * from uncached area. * 1.06a asa 11/02/13 Changed the value for XEMACPS_RXBUF_LEN_MASK from 0x3fff - * to 0x1fff. This fixes the CR#744902. - * Made changes in example file xemacps_example.h to fix compilation - * issues with iarcc compiler. + * to 0x1fff. This fixes the CR#744902. + * Made changes in example file xemacps_example.h to fix compilation + * issues with iarcc compiler. * 2.0 adk 10/12/13 Updated as per the New Tcl API's * 2.1 adk 11/08/14 Fixed the CR#811288. Changes are made in the driver tcl file. * 2.1 bss 09/08/14 Modified driver tcl to fix CR#820349 to export phy - * address in xparameters.h when GMII to RGMII converter - * is present in hw. + * address in xparameters.h when GMII to RGMII converter + * is present in hw. * 2.1 srt 07/15/14 Add support for Zynq Ultrascale Mp GEM specification and 64-bit - * changes. + * changes. * 2.2 adk 29/10/14 Fixed CR#827686 when PCS/PMA core is configured with * 1000BASE-X mode export proper values to the xparameters.h * file. Changes are made in the driver tcl file. * 3.0 adk 08/1/15 Don't include gem in peripheral test when gem is * configured with PCS/PMA Core. Changes are made in the - * test app tcl(CR:827686). + * test app tcl(CR:827686). * 3.0 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. * 3.0 hk 03/18/15 Added support for jumbo frames. Increase AHB burst. * Disable extended mode. Perform all 64 bit changes under @@ -302,10 +302,10 @@ * 3.5 hk 08/14/17 Update cache coherency information of the interface in * its config structure. * 3.6 rb 09/08/17 HwCnt variable (in XEmacPs_BdRing structure) is - * changed to volatile. - * Add API XEmacPs_BdRingPtrReset() to reset pointers + * changed to volatile. + * Add API XEmacPs_BdRingPtrReset() to reset pointers * 3.8 hk 07/19/18 Fixed CPP, GCC and doxygen warnings - CR-1006327 - * hk 09/17/18 Fix PTP interrupt masks and cleanup comments. + * hk 09/17/18 Fix PTP interrupt masks and cleanup comments. * 3.9 hk 01/23/19 Add RX watermark support * 3.11 sd 02/14/20 Add clock support * @@ -313,8 +313,8 @@ * ****************************************************************************/ -#ifndef XEMACPS_H /* prevent circular inclusions */ -#define XEMACPS_H /* by using protection macros */ +#ifndef XEMACPS_H /* prevent circular inclusions */ +#define XEMACPS_H /* by using protection macros */ #ifdef __cplusplus extern "C" { @@ -447,13 +447,13 @@ extern "C" { /* The next few constants help upper layers determine the size of memory * pools used for Ethernet buffers and descriptor lists. */ -#define XEMACPS_MAC_ADDR_SIZE 6U /* size of Ethernet header */ +#define XEMACPS_MAC_ADDR_SIZE 6U /* size of Ethernet header */ -#define XEMACPS_MTU 1500U /* max MTU size of Ethernet frame */ -#define XEMACPS_MTU_JUMBO 10240U /* max MTU size of jumbo frame */ -#define XEMACPS_HDR_SIZE 14U /* size of Ethernet header */ -#define XEMACPS_HDR_VLAN_SIZE 18U /* size of Ethernet header with VLAN */ -#define XEMACPS_TRL_SIZE 4U /* size of Ethernet trailer (FCS) */ +#define XEMACPS_MTU 1500U /* max MTU size of Ethernet frame */ +#define XEMACPS_MTU_JUMBO 10240U /* max MTU size of jumbo frame */ +#define XEMACPS_HDR_SIZE 14U /* size of Ethernet header */ +#define XEMACPS_HDR_VLAN_SIZE 18U /* size of Ethernet header with VLAN */ +#define XEMACPS_TRL_SIZE 4U /* size of Ethernet trailer (FCS) */ #define XEMACPS_MAX_FRAME_SIZE (XEMACPS_MTU + XEMACPS_HDR_SIZE + \ XEMACPS_TRL_SIZE) #define XEMACPS_MAX_VLAN_FRAME_SIZE (XEMACPS_MTU + XEMACPS_HDR_SIZE + \ @@ -464,8 +464,8 @@ extern "C" { /* DMACR Bust length hash defines */ #define XEMACPS_SINGLE_BURST 0x00000001 -#define XEMACPS_4BYTE_BURST 0x00000004 -#define XEMACPS_8BYTE_BURST 0x00000008 +#define XEMACPS_4BYTE_BURST 0x00000004 +#define XEMACPS_8BYTE_BURST 0x00000008 #define XEMACPS_16BYTE_BURST 0x00000010 @@ -499,7 +499,7 @@ typedef void (*XEmacPs_Handler) (void *CallBackRef); * */ typedef void (*XEmacPs_ErrHandler) (void *CallBackRef, u8 Direction, - u32 ErrorWord); + u32 ErrorWord); /*@}*/ @@ -507,12 +507,12 @@ typedef void (*XEmacPs_ErrHandler) (void *CallBackRef, u8 Direction, * This typedef contains configuration information for a device. */ typedef struct { - u16 DeviceId; /**< Unique ID of device */ + u16 DeviceId; /**< Unique ID of device */ UINTPTR BaseAddress;/**< Physical base address of IPIF registers */ u8 IsCacheCoherent; /**< Applicable only to A53 in EL1 mode; - * describes whether Cache Coherent or not */ + * describes whether Cache Coherent or not */ #if defined (XCLOCKING) - u32 RefClk; /**< Input clock */ + u32 RefClk; /**< Input clock */ #endif } XEmacPs_Config; @@ -523,13 +523,13 @@ typedef struct { * to a structure of this type is then passed to the driver API functions. */ typedef struct XEmacPs_Instance { - XEmacPs_Config Config; /* Hardware configuration */ - u32 IsStarted; /* Device is currently started */ - u32 IsReady; /* Device is initialized and ready */ - u32 Options; /* Current options word */ + XEmacPs_Config Config; /* Hardware configuration */ + u32 IsStarted; /* Device is currently started */ + u32 IsReady; /* Device is initialized and ready */ + u32 Options; /* Current options word */ - XEmacPs_BdRing TxBdRing; /* Transmit BD ring */ - XEmacPs_BdRing RxBdRing; /* Receive BD ring */ + XEmacPs_BdRing TxBdRing; /* Transmit BD ring */ + XEmacPs_BdRing RxBdRing; /* Receive BD ring */ XEmacPs_Handler SendHandler; XEmacPs_Handler RecvHandler; @@ -599,8 +599,8 @@ typedef struct XEmacPs_Instance { *****************************************************************************/ #define XEmacPs_IntEnable(InstancePtr, Mask) \ XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ - XEMACPS_IER_OFFSET, \ - ((Mask) & XEMACPS_IXR_ALL_MASK)); + XEMACPS_IER_OFFSET, \ + ((Mask) & XEMACPS_IXR_ALL_MASK)); /****************************************************************************/ /** @@ -620,8 +620,8 @@ typedef struct XEmacPs_Instance { *****************************************************************************/ #define XEmacPs_IntDisable(InstancePtr, Mask) \ XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ - XEMACPS_IDR_OFFSET, \ - ((Mask) & XEMACPS_IXR_ALL_MASK)); + XEMACPS_IDR_OFFSET, \ + ((Mask) & XEMACPS_IXR_ALL_MASK)); /****************************************************************************/ /** @@ -641,8 +641,8 @@ typedef struct XEmacPs_Instance { *****************************************************************************/ #define XEmacPs_IntQ1Enable(InstancePtr, Mask) \ XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ - XEMACPS_INTQ1_IER_OFFSET, \ - ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); + XEMACPS_INTQ1_IER_OFFSET, \ + ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); /****************************************************************************/ /** @@ -662,8 +662,8 @@ typedef struct XEmacPs_Instance { *****************************************************************************/ #define XEmacPs_IntQ1Disable(InstancePtr, Mask) \ XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ - XEMACPS_INTQ1_IDR_OFFSET, \ - ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); + XEMACPS_INTQ1_IDR_OFFSET, \ + ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); /****************************************************************************/ /** @@ -740,17 +740,17 @@ typedef struct XEmacPs_Instance { * * @param InstancePtr is a pointer to the XEmacPs instance to be worked on. * @param High is the non-zero RX high watermark value. When SRAM fill level -* is above this, a pause frame will be sent. +* is above this, a pause frame will be sent. * @param Low is the non-zero RX low watermark value. When SRAM fill level -* is below this, a zero length pause frame will be sent IF the last -* pause frame sent was non-zero. +* is below this, a zero length pause frame will be sent IF the last +* pause frame sent was non-zero. * * @return None * * @note * * Signature: void XEmacPs_SetRXWatermark(XEmacPs *InstancePtr, u16 High, -* u16 Low) +* u16 Low) * *****************************************************************************/ #define XEmacPs_SetRXWatermark(InstancePtr, High, Low) \ @@ -780,12 +780,12 @@ typedef struct XEmacPs_Instance { * Initialization functions in xemacps.c */ LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config *CfgPtr, - UINTPTR EffectiveAddress); + UINTPTR EffectiveAddress); void XEmacPs_Start(XEmacPs *InstancePtr); void XEmacPs_Stop(XEmacPs *InstancePtr); void XEmacPs_Reset(XEmacPs *InstancePtr); void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum, - u16 Direction); + u16 Direction); /* * Lookup configuration in xemacps_sinit.c @@ -797,7 +797,7 @@ XEmacPs_Config *XEmacPs_LookupConfig(u16 DeviceId); * DMA only and FIFO is not supported. This DMA does not support coalescing. */ LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType, - void *FuncPointer, void *CallBackRef); + void *FuncPointer, void *CallBackRef); void XEmacPs_IntrHandler(void *XEmacPsPtr); /* @@ -816,13 +816,13 @@ void XEmacPs_ClearHash(XEmacPs *InstancePtr); void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr); void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, - XEmacPs_MdcDiv Divisor); + XEmacPs_MdcDiv Divisor); void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed); u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr); LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, - u32 RegisterNum, u16 *PhyDataPtr); + u32 RegisterNum, u16 *PhyDataPtr); LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress, - u32 RegisterNum, u16 PhyData); + u32 RegisterNum, u16 PhyData); LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index); LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr); diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h index a757322615..918477b2d7 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h @@ -51,8 +51,8 @@ * *************************************************************************** */ -#ifndef XEMACPS_BD_H /* prevent circular inclusions */ -#define XEMACPS_BD_H /* by using protection macros */ +#ifndef XEMACPS_BD_H /* prevent circular inclusions */ +#define XEMACPS_BD_H /* by using protection macros */ #ifdef __cplusplus extern "C" { @@ -117,7 +117,7 @@ typedef u32 XEmacPs_Bd[XEMACPS_BD_NUM_WORDS]; * *****************************************************************************/ #define XEmacPs_BdRead(BaseAddress, Offset) \ - (*(u32 *)((UINTPTR)((void*)(BaseAddress)) + (u32)(Offset))) + (*(u32 *)((UINTPTR)((void*)(BaseAddress)) + (u32)(Offset))) /****************************************************************************/ /** @@ -153,10 +153,10 @@ typedef u32 XEmacPs_Bd[XEMACPS_BD_NUM_WORDS]; *****************************************************************************/ #if defined(__aarch64__) || defined(__arch64__) #define XEmacPs_BdSetAddressTx(BdPtr, Addr) \ - XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ - (u32)((Addr) & ULONG64_LO_MASK)); \ - XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET, \ - (u32)(((Addr) & ULONG64_HI_MASK) >> 32U)); + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + (u32)((Addr) & ULONG64_LO_MASK)); \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET, \ + (u32)(((Addr) & ULONG64_HI_MASK) >> 32U)); #else #define XEmacPs_BdSetAddressTx(BdPtr, Addr) \ XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, (u32)(Addr)) @@ -180,9 +180,9 @@ typedef u32 XEmacPs_Bd[XEMACPS_BD_NUM_WORDS]; #define XEmacPs_BdSetAddressRx(BdPtr, Addr) \ XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ - ~XEMACPS_RXBUF_ADD_MASK) | ((u32)((Addr) & ULONG64_LO_MASK)))); \ - XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET, \ - (u32)(((Addr) & ULONG64_HI_MASK) >> 32U)); + ~XEMACPS_RXBUF_ADD_MASK) | ((u32)((Addr) & ULONG64_LO_MASK)))); \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET, \ + (u32)(((Addr) & ULONG64_HI_MASK) >> 32U)); #else #define XEmacPs_BdSetAddressRx(BdPtr, Addr) \ XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ @@ -239,8 +239,8 @@ typedef u32 XEmacPs_Bd[XEMACPS_BD_NUM_WORDS]; *****************************************************************************/ #if defined(__aarch64__) || defined(__arch64__) #define XEmacPs_BdGetBufAddr(BdPtr) \ - (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) | \ - (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET)) << 32U) + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) | \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET)) << 32U) #else #define XEmacPs_BdGetBufAddr(BdPtr) \ (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET)) diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c index dad6ac0c84..dcf27fbc4b 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c @@ -19,20 +19,20 @@ * ----- ---- -------- ------------------------------------------------------- * 1.00a wsy 01/10/10 First release * 1.00a asa 11/21/11 The function XEmacPs_BdRingFromHwTx is modified. -* Earlier it used to search in "BdLimit" number of BDs to -* know which BDs are processed. Now one more check is -* added. It looks for BDs till the current BD pointer -* reaches HwTail. By doing this processing time is saved. +* Earlier it used to search in "BdLimit" number of BDs to +* know which BDs are processed. Now one more check is +* added. It looks for BDs till the current BD pointer +* reaches HwTail. By doing this processing time is saved. * 1.00a asa 01/24/12 The function XEmacPs_BdRingFromHwTx in file -* xemacps_bdring.c is modified. Now start of packet is -* searched for returning the number of BDs processed. +* xemacps_bdring.c is modified. Now start of packet is +* searched for returning the number of BDs processed. * 1.05a asa 09/23/13 Cache operations on BDs are not required and hence -* removed. It is expected that all BDs are allocated in -* from uncached area. Fix for CR #663885. +* removed. It is expected that all BDs are allocated in +* from uncached area. Fix for CR #663885. * 2.1 srt 07/15/14 Add support for Zynq Ultrascale Mp architecture. * 3.0 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. * 3.6 rb 09/08/17 Add XEmacPs_BdRingPtrReset() API to reset BD ring -* pointers +* pointers * * ******************************************************************************/ @@ -174,73 +174,73 @@ static void XEmacPs_BdSetTxWrap(UINTPTR BdPtr); * Make sure to pass in the right alignment value. *****************************************************************************/ LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr, - UINTPTR VirtAddr, u32 Alignment, u32 BdCount) + UINTPTR VirtAddr, u32 Alignment, u32 BdCount) { u32 i; UINTPTR BdVirtAddr; UINTPTR BdPhyAddr; UINTPTR VirtAddrLoc = VirtAddr; - /* In case there is a failure prior to creating list, make sure the - * following attributes are 0 to prevent calls to other functions - * from doing anything. - */ + /* In case there is a failure prior to creating list, make sure the + * following attributes are 0 to prevent calls to other functions + * from doing anything. + */ RingPtr->AllCnt = 0U; RingPtr->FreeCnt = 0U; RingPtr->HwCnt = 0U; RingPtr->PreCnt = 0U; RingPtr->PostCnt = 0U; - /* Make sure Alignment parameter meets minimum requirements */ + /* Make sure Alignment parameter meets minimum requirements */ if (Alignment < (u32)XEMACPS_DMABD_MINIMUM_ALIGNMENT) { - return (LONG)(XST_INVALID_PARAM); - } + return (LONG)(XST_INVALID_PARAM); + } - /* Make sure Alignment is a power of 2 */ + /* Make sure Alignment is a power of 2 */ if (((Alignment - 0x00000001U) & Alignment)!=0x00000000U) { - return (LONG)(XST_INVALID_PARAM); - } + return (LONG)(XST_INVALID_PARAM); + } - /* Make sure PhysAddr and VirtAddr are on same Alignment */ + /* Make sure PhysAddr and VirtAddr are on same Alignment */ if (((PhysAddr % Alignment)!=(u32)0) || ((VirtAddrLoc % Alignment)!=(u32)0)) { - return (LONG)(XST_INVALID_PARAM); - } + return (LONG)(XST_INVALID_PARAM); + } - /* Is BdCount reasonable? */ + /* Is BdCount reasonable? */ if (BdCount == 0x00000000U) { - return (LONG)(XST_INVALID_PARAM); - } + return (LONG)(XST_INVALID_PARAM); + } - /* Figure out how many bytes will be between the start of adjacent BDs */ + /* Figure out how many bytes will be between the start of adjacent BDs */ RingPtr->Separation = ((u32)sizeof(XEmacPs_Bd)); - /* Must make sure the ring doesn't span address 0x00000000. If it does, - * then the next/prev BD traversal macros will fail. - */ + /* Must make sure the ring doesn't span address 0x00000000. If it does, + * then the next/prev BD traversal macros will fail. + */ if (VirtAddrLoc > ((VirtAddrLoc + (RingPtr->Separation * BdCount)) - (u32)1)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } + return (LONG)(XST_DMA_SG_LIST_ERROR); + } - /* Initial ring setup: - * - Clear the entire space - * - Setup each BD's BDA field with the physical address of the next BD - */ - (void)memset((void *) VirtAddrLoc, 0, (RingPtr->Separation * BdCount)); + /* Initial ring setup: + * - Clear the entire space + * - Setup each BD's BDA field with the physical address of the next BD + */ + (void)memset((void *) VirtAddrLoc, 0, (RingPtr->Separation * BdCount)); BdVirtAddr = VirtAddrLoc; BdPhyAddr = PhysAddr + RingPtr->Separation; for (i = 1U; i < BdCount; i++) { - BdVirtAddr += RingPtr->Separation; - BdPhyAddr += RingPtr->Separation; - } + BdVirtAddr += RingPtr->Separation; + BdPhyAddr += RingPtr->Separation; + } - /* Setup and initialize pointers and counters */ + /* Setup and initialize pointers and counters */ RingPtr->RunState = (u32)(XST_DMA_SG_IS_STOPPED); RingPtr->BaseBdAddr = VirtAddrLoc; RingPtr->PhysBaseAddr = PhysAddr; RingPtr->HighBdAddr = BdVirtAddr; RingPtr->Length = - ((RingPtr->HighBdAddr - RingPtr->BaseBdAddr) + RingPtr->Separation); + ((RingPtr->HighBdAddr - RingPtr->BaseBdAddr) + RingPtr->Separation); RingPtr->AllCnt = (u32)BdCount; RingPtr->FreeCnt = (u32)BdCount; RingPtr->FreeHead = (XEmacPs_Bd *)(void *)VirtAddrLoc; @@ -279,47 +279,47 @@ LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr, * *****************************************************************************/ LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr, - u8 Direction) + u8 Direction) { u32 i; UINTPTR CurBd; - /* Can't do this function if there isn't a ring */ + /* Can't do this function if there isn't a ring */ if (RingPtr->AllCnt == 0x00000000U) { - return (LONG)(XST_DMA_SG_NO_LIST); - } + return (LONG)(XST_DMA_SG_NO_LIST); + } - /* Can't do this function with the channel running */ + /* Can't do this function with the channel running */ if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) { - return (LONG)(XST_DEVICE_IS_STARTED); - } + return (LONG)(XST_DEVICE_IS_STARTED); + } - /* Can't do this function with some of the BDs in use */ + /* Can't do this function with some of the BDs in use */ if (RingPtr->FreeCnt != RingPtr->AllCnt) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } + return (LONG)(XST_DMA_SG_LIST_ERROR); + } if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) { - return (LONG)(XST_INVALID_PARAM); - } + return (LONG)(XST_INVALID_PARAM); + } - /* Starting from the top of the ring, save BD.Next, overwrite the entire - * BD with the template, then restore BD.Next - */ + /* Starting from the top of the ring, save BD.Next, overwrite the entire + * BD with the template, then restore BD.Next + */ CurBd = RingPtr->BaseBdAddr; for (i = 0U; i < RingPtr->AllCnt; i++) { - memcpy((void *)CurBd, SrcBdPtr, sizeof(XEmacPs_Bd)); + memcpy((void *)CurBd, SrcBdPtr, sizeof(XEmacPs_Bd)); CurBd += RingPtr->Separation; - } + } CurBd -= RingPtr->Separation; if (Direction == XEMACPS_RECV) { - XEmacPs_BdSetRxWrap(CurBd); - } + XEmacPs_BdSetRxWrap(CurBd); + } else { - XEmacPs_BdSetTxWrap(CurBd); - } + XEmacPs_BdSetTxWrap(CurBd); + } return (LONG)(XST_SUCCESS); } @@ -398,20 +398,20 @@ LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr, * *****************************************************************************/ LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd ** BdSetPtr) + XEmacPs_Bd ** BdSetPtr) { LONG Status; - /* Enough free BDs available for the request? */ + /* Enough free BDs available for the request? */ if (RingPtr->FreeCnt < NumBd) { - Status = (LONG)(XST_FAILURE); - } else { - /* Set the return argument and move FreeHead forward */ - *BdSetPtr = RingPtr->FreeHead; + Status = (LONG)(XST_FAILURE); + } else { + /* Set the return argument and move FreeHead forward */ + *BdSetPtr = RingPtr->FreeHead; XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->FreeHead, NumBd); RingPtr->FreeCnt -= NumBd; RingPtr->PreCnt += NumBd; - Status = (LONG)(XST_SUCCESS); - } + Status = (LONG)(XST_SUCCESS); + } return Status; } @@ -478,23 +478,23 @@ LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, * *****************************************************************************/ LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd * BdSetPtr) + XEmacPs_Bd * BdSetPtr) { LONG Status; - (void) BdSetPtr; + (void) BdSetPtr; Xil_AssertNonvoid(RingPtr != NULL); Xil_AssertNonvoid(BdSetPtr != NULL); - /* Enough BDs in the free state for the request? */ + /* Enough BDs in the free state for the request? */ if (RingPtr->PreCnt < NumBd) { - Status = (LONG)(XST_FAILURE); - } else { - /* Set the return argument and move FreeHead backward */ - XEMACPS_RING_SEEKBACK(RingPtr, (RingPtr->FreeHead), NumBd); + Status = (LONG)(XST_FAILURE); + } else { + /* Set the return argument and move FreeHead backward */ + XEMACPS_RING_SEEKBACK(RingPtr, (RingPtr->FreeHead), NumBd); RingPtr->FreeCnt += NumBd; RingPtr->PreCnt -= NumBd; - Status = (LONG)(XST_SUCCESS); - } + Status = (LONG)(XST_SUCCESS); + } return Status; } @@ -526,32 +526,32 @@ LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, * *****************************************************************************/ LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd * BdSetPtr) + XEmacPs_Bd * BdSetPtr) { XEmacPs_Bd *CurBdPtr; u32 i; LONG Status; - /* if no bds to process, simply return. */ + /* if no bds to process, simply return. */ if (0U == NumBd){ - Status = (LONG)(XST_SUCCESS); - } else { - /* Make sure we are in sync with XEmacPs_BdRingAlloc() */ + Status = (LONG)(XST_SUCCESS); + } else { + /* Make sure we are in sync with XEmacPs_BdRingAlloc() */ if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) { - Status = (LONG)(XST_DMA_SG_LIST_ERROR); - } else { + Status = (LONG)(XST_DMA_SG_LIST_ERROR); + } else { CurBdPtr = BdSetPtr; - for (i = 0U; i < NumBd; i++) { - CurBdPtr = (XEmacPs_Bd *)((void *)XEmacPs_BdRingNext(RingPtr, CurBdPtr)); - } - /* Adjust ring pointers & counters */ + for (i = 0U; i < NumBd; i++) { + CurBdPtr = (XEmacPs_Bd *)((void *)XEmacPs_BdRingNext(RingPtr, CurBdPtr)); + } + /* Adjust ring pointers & counters */ XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd); RingPtr->PreCnt -= NumBd; RingPtr->HwTail = CurBdPtr; RingPtr->HwCnt += NumBd; - Status = (LONG)(XST_SUCCESS); - } - } + Status = (LONG)(XST_SUCCESS); + } + } return Status; } @@ -623,7 +623,7 @@ LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd, * *****************************************************************************/ u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, - XEmacPs_Bd ** BdSetPtr) + XEmacPs_Bd ** BdSetPtr) { XEmacPs_Bd *CurBdPtr; u32 BdStr = 0U; @@ -636,65 +636,65 @@ u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, BdCount = 0U; BdPartialCount = 0U; - /* If no BDs in work group, then there's nothing to search */ + /* If no BDs in work group, then there's nothing to search */ if (RingPtr->HwCnt == 0x00000000U) { - *BdSetPtr = NULL; - Status = 0U; - } else { + *BdSetPtr = NULL; + Status = 0U; + } else { - if (BdLimitLoc > RingPtr->HwCnt){ - BdLimitLoc = RingPtr->HwCnt; - } - /* Starting at HwHead, keep moving forward in the list until: - * - A BD is encountered with its new/used bit set which means - * hardware has not completed processing of that BD. - * - RingPtr->HwTail is reached and RingPtr->HwCnt is reached. - * - The number of requested BDs has been processed - */ - while (BdCount < BdLimitLoc) { - /* Read the status */ - if(CurBdPtr != NULL){ - BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET); - } + if (BdLimitLoc > RingPtr->HwCnt){ + BdLimitLoc = RingPtr->HwCnt; + } + /* Starting at HwHead, keep moving forward in the list until: + * - A BD is encountered with its new/used bit set which means + * hardware has not completed processing of that BD. + * - RingPtr->HwTail is reached and RingPtr->HwCnt is reached. + * - The number of requested BDs has been processed + */ + while (BdCount < BdLimitLoc) { + /* Read the status */ + if(CurBdPtr != NULL){ + BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET); + } - if ((Sop == 0x00000000U) && ((BdStr & XEMACPS_TXBUF_USED_MASK)!=0x00000000U)){ - Sop = 1U; - } - if (Sop == 0x00000001U) { - BdCount++; - BdPartialCount++; - } + if ((Sop == 0x00000000U) && ((BdStr & XEMACPS_TXBUF_USED_MASK)!=0x00000000U)){ + Sop = 1U; + } + if (Sop == 0x00000001U) { + BdCount++; + BdPartialCount++; + } - /* hardware has processed this BD so check the "last" bit. - * If it is clear, then there are more BDs for the current - * packet. Keep a count of these partial packet BDs. - */ - if ((Sop == 0x00000001U) && ((BdStr & XEMACPS_TXBUF_LAST_MASK)!=0x00000000U)) { - Sop = 0U; - BdPartialCount = 0U; - } + /* hardware has processed this BD so check the "last" bit. + * If it is clear, then there are more BDs for the current + * packet. Keep a count of these partial packet BDs. + */ + if ((Sop == 0x00000001U) && ((BdStr & XEMACPS_TXBUF_LAST_MASK)!=0x00000000U)) { + Sop = 0U; + BdPartialCount = 0U; + } - /* Move on to next BD in work group */ - CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); - } + /* Move on to next BD in work group */ + CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); + } - /* Subtract off any partial packet BDs found */ + /* Subtract off any partial packet BDs found */ BdCount -= BdPartialCount; - /* If BdCount is non-zero then BDs were found to return. Set return - * parameters, update pointers and counters, return success - */ - if (BdCount > 0x00000000U) { - *BdSetPtr = RingPtr->HwHead; - RingPtr->HwCnt -= BdCount; - RingPtr->PostCnt += BdCount; - XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); - Status = (BdCount); - } else { - *BdSetPtr = NULL; - Status = 0U; - } - } + /* If BdCount is non-zero then BDs were found to return. Set return + * parameters, update pointers and counters, return success + */ + if (BdCount > 0x00000000U) { + *BdSetPtr = RingPtr->HwHead; + RingPtr->HwCnt -= BdCount; + RingPtr->PostCnt += BdCount; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); + Status = (BdCount); + } else { + *BdSetPtr = NULL; + Status = 0U; + } + } return Status; } @@ -767,7 +767,7 @@ u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, * *****************************************************************************/ u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, - XEmacPs_Bd ** BdSetPtr) + XEmacPs_Bd ** BdSetPtr) { XEmacPs_Bd *CurBdPtr; u32 BdStr = 0U; @@ -779,61 +779,61 @@ u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, BdCount = 0U; BdPartialCount = 0U; - /* If no BDs in work group, then there's nothing to search */ + /* If no BDs in work group, then there's nothing to search */ if (RingPtr->HwCnt == 0x00000000U) { - *BdSetPtr = NULL; - Status = 0U; - } else { + *BdSetPtr = NULL; + Status = 0U; + } else { - /* Starting at HwHead, keep moving forward in the list until: - * - A BD is encountered with its new/used bit set which means - * hardware has completed processing of that BD. - * - RingPtr->HwTail is reached and RingPtr->HwCnt is reached. - * - The number of requested BDs has been processed - */ + /* Starting at HwHead, keep moving forward in the list until: + * - A BD is encountered with its new/used bit set which means + * hardware has completed processing of that BD. + * - RingPtr->HwTail is reached and RingPtr->HwCnt is reached. + * - The number of requested BDs has been processed + */ while (BdCount < BdLimit) { - /* Read the status */ - if(CurBdPtr!=NULL){ - BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET); - } - if ((!(XEmacPs_BdIsRxNew(CurBdPtr)))==TRUE) { - break; - } + /* Read the status */ + if(CurBdPtr!=NULL){ + BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET); + } + if ((!(XEmacPs_BdIsRxNew(CurBdPtr)))==TRUE) { + break; + } - BdCount++; + BdCount++; - /* hardware has processed this BD so check the "last" bit. If + /* hardware has processed this BD so check the "last" bit. If * it is clear, then there are more BDs for the current packet. * Keep a count of these partial packet BDs. - */ - if ((BdStr & XEMACPS_RXBUF_EOF_MASK)!=0x00000000U) { - BdPartialCount = 0U; - } else { - BdPartialCount++; - } + */ + if ((BdStr & XEMACPS_RXBUF_EOF_MASK)!=0x00000000U) { + BdPartialCount = 0U; + } else { + BdPartialCount++; + } - /* Move on to next BD in work group */ - CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); - } + /* Move on to next BD in work group */ + CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); + } - /* Subtract off any partial packet BDs found */ + /* Subtract off any partial packet BDs found */ BdCount -= BdPartialCount; - /* If BdCount is non-zero then BDs were found to return. Set return - * parameters, update pointers and counters, return success - */ - if (BdCount > 0x00000000U) { - *BdSetPtr = RingPtr->HwHead; - RingPtr->HwCnt -= BdCount; - RingPtr->PostCnt += BdCount; - XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); - Status = (BdCount); - } + /* If BdCount is non-zero then BDs were found to return. Set return + * parameters, update pointers and counters, return success + */ + if (BdCount > 0x00000000U) { + *BdSetPtr = RingPtr->HwHead; + RingPtr->HwCnt -= BdCount; + RingPtr->PostCnt += BdCount; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); + Status = (BdCount); + } else { - *BdSetPtr = NULL; - Status = 0U; - } + *BdSetPtr = NULL; + Status = 0U; + } } return Status; } @@ -860,24 +860,24 @@ u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, * *****************************************************************************/ LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd * BdSetPtr) + XEmacPs_Bd * BdSetPtr) { LONG Status; - /* if no bds to process, simply return. */ + /* if no bds to process, simply return. */ if (0x00000000U == NumBd){ - Status = (LONG)(XST_SUCCESS); - } else { - /* Make sure we are in sync with XEmacPs_BdRingFromHw() */ + Status = (LONG)(XST_SUCCESS); + } else { + /* Make sure we are in sync with XEmacPs_BdRingFromHw() */ if ((RingPtr->PostCnt < NumBd) || (RingPtr->PostHead != BdSetPtr)) { - Status = (LONG)(XST_DMA_SG_LIST_ERROR); - } else { - /* Update pointers and counters */ + Status = (LONG)(XST_DMA_SG_LIST_ERROR); + } else { + /* Update pointers and counters */ RingPtr->FreeCnt += NumBd; RingPtr->PostCnt -= NumBd; XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PostHead, NumBd); - Status = (LONG)(XST_SUCCESS); - } - } + Status = (LONG)(XST_SUCCESS); + } + } return Status; } @@ -916,84 +916,84 @@ LONG XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction) u32 i; if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) { - return (LONG)(XST_INVALID_PARAM); - } + return (LONG)(XST_INVALID_PARAM); + } - /* Is the list created */ + /* Is the list created */ if (RingPtr->AllCnt == 0x00000000U) { - return (LONG)(XST_DMA_SG_NO_LIST); - } + return (LONG)(XST_DMA_SG_NO_LIST); + } - /* Can't check if channel is running */ + /* Can't check if channel is running */ if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) { - return (LONG)(XST_IS_STARTED); - } + return (LONG)(XST_IS_STARTED); + } - /* RunState doesn't make sense */ + /* RunState doesn't make sense */ if (RingPtr->RunState != (u32)XST_DMA_SG_IS_STOPPED) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } + return (LONG)(XST_DMA_SG_LIST_ERROR); + } - /* Verify internal pointers point to correct memory space */ + /* Verify internal pointers point to correct memory space */ AddrV = (UINTPTR) RingPtr->FreeHead; if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } + return (LONG)(XST_DMA_SG_LIST_ERROR); + } AddrV = (UINTPTR) RingPtr->PreHead; if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } + return (LONG)(XST_DMA_SG_LIST_ERROR); + } AddrV = (UINTPTR) RingPtr->HwHead; if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } + return (LONG)(XST_DMA_SG_LIST_ERROR); + } AddrV = (UINTPTR) RingPtr->HwTail; if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } + return (LONG)(XST_DMA_SG_LIST_ERROR); + } AddrV = (UINTPTR) RingPtr->PostHead; if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } + return (LONG)(XST_DMA_SG_LIST_ERROR); + } - /* Verify internal counters add up */ + /* Verify internal counters add up */ if ((RingPtr->HwCnt + RingPtr->PreCnt + RingPtr->FreeCnt + - RingPtr->PostCnt) != RingPtr->AllCnt) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } + RingPtr->PostCnt) != RingPtr->AllCnt) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } - /* Verify BDs are linked correctly */ + /* Verify BDs are linked correctly */ AddrV = RingPtr->BaseBdAddr; AddrP = RingPtr->PhysBaseAddr + RingPtr->Separation; for (i = 1U; i < RingPtr->AllCnt; i++) { - /* Check BDA for this BD. It should point to next physical addr */ - if (XEmacPs_BdRead(AddrV, XEMACPS_BD_ADDR_OFFSET) != AddrP) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } + /* Check BDA for this BD. It should point to next physical addr */ + if (XEmacPs_BdRead(AddrV, XEMACPS_BD_ADDR_OFFSET) != AddrP) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } - /* Move on to next BD */ - AddrV += RingPtr->Separation; - AddrP += RingPtr->Separation; - } + /* Move on to next BD */ + AddrV += RingPtr->Separation; + AddrP += RingPtr->Separation; + } - /* Last BD should have wrap bit set */ + /* Last BD should have wrap bit set */ if (XEMACPS_SEND == Direction) { - if ((!XEmacPs_BdIsTxWrap(AddrV))==TRUE) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } - } - else { /* XEMACPS_RECV */ - if ((!XEmacPs_BdIsRxWrap(AddrV))==TRUE) { - return (LONG)(XST_DMA_SG_LIST_ERROR); - } - } + if ((!XEmacPs_BdIsTxWrap(AddrV))==TRUE) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + } + else { /* XEMACPS_RECV */ + if ((!XEmacPs_BdIsRxWrap(AddrV))==TRUE) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + } - /* No problems found */ + /* No problems found */ return (LONG)(XST_SUCCESS); } @@ -1017,10 +1017,10 @@ static void XEmacPs_BdSetRxWrap(UINTPTR BdPtr) BdPtr += (u32)(XEMACPS_BD_ADDR_OFFSET); TempPtr = (u32 *)BdPtr; if(TempPtr != NULL) { - DataValueRx = *TempPtr; - DataValueRx |= XEMACPS_RXBUF_WRAP_MASK; - *TempPtr = DataValueRx; - } + DataValueRx = *TempPtr; + DataValueRx |= XEMACPS_RXBUF_WRAP_MASK; + *TempPtr = DataValueRx; + } } /*****************************************************************************/ @@ -1043,10 +1043,10 @@ static void XEmacPs_BdSetTxWrap(UINTPTR BdPtr) BdPtr += (u32)(XEMACPS_BD_STAT_OFFSET); TempPtr = (u32 *)BdPtr; if(TempPtr != NULL) { - DataValueTx = *TempPtr; - DataValueTx |= XEMACPS_TXBUF_WRAP_MASK; - *TempPtr = DataValueTx; - } + DataValueTx = *TempPtr; + DataValueTx |= XEMACPS_TXBUF_WRAP_MASK; + *TempPtr = DataValueTx; + } } /*****************************************************************************/ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h index e454ecb3e1..82ad9a8595 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h @@ -22,14 +22,14 @@ * 2.1 srt 07/15/14 Add support for Zynq Ultrascale Mp architecture. * 3.0 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. * 3.6 rb 09/08/17 HwCnt variable (in XEmacPs_BdRing structure) is -* changed to volatile. +* changed to volatile. * * * ******************************************************************************/ -#ifndef XEMACPS_BDRING_H /* prevent curcular inclusions */ -#define XEMACPS_BDRING_H /* by using protection macros */ +#ifndef XEMACPS_BDRING_H /* prevent curcular inclusions */ +#define XEMACPS_BDRING_H /* by using protection macros */ #ifdef __cplusplus extern "C" { @@ -41,21 +41,21 @@ extern "C" { /** This is an internal structure used to maintain the DMA list */ typedef struct { UINTPTR PhysBaseAddr;/**< Physical address of 1st BD in list */ - UINTPTR BaseBdAddr; /**< Virtual address of 1st BD in list */ - UINTPTR HighBdAddr; /**< Virtual address of last BD in the list */ - u32 Length; /**< Total size of ring in bytes */ - u32 RunState; /**< Flag to indicate DMA is started */ - u32 Separation; /**< Number of bytes between the starting address + UINTPTR BaseBdAddr; /**< Virtual address of 1st BD in list */ + UINTPTR HighBdAddr; /**< Virtual address of last BD in the list */ + u32 Length; /**< Total size of ring in bytes */ + u32 RunState; /**< Flag to indicate DMA is started */ + u32 Separation; /**< Number of bytes between the starting address of adjacent BDs */ XEmacPs_Bd *FreeHead; - /**< First BD in the free group */ + /**< First BD in the free group */ XEmacPs_Bd *PreHead;/**< First BD in the pre-work group */ XEmacPs_Bd *HwHead; /**< First BD in the work group */ XEmacPs_Bd *HwTail; /**< Last BD in the work group */ XEmacPs_Bd *PostHead; - /**< First BD in the post-work group */ + /**< First BD in the post-work group */ XEmacPs_Bd *BdaRestart; - /**< BDA to load when channel is started */ + /**< BDA to load when channel is started */ volatile u32 HwCnt; /**< Number of BDs in work group */ u32 PreCnt; /**< Number of BDs in pre-work group */ @@ -187,21 +187,21 @@ typedef struct { * Scatter gather DMA related functions in xemacps_bdring.c */ LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr, - UINTPTR VirtAddr, u32 Alignment, u32 BdCount); + UINTPTR VirtAddr, u32 Alignment, u32 BdCount); LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr, - u8 Direction); + u8 Direction); LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd ** BdSetPtr); + XEmacPs_Bd ** BdSetPtr); LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd * BdSetPtr); + XEmacPs_Bd * BdSetPtr); LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd * BdSetPtr); + XEmacPs_Bd * BdSetPtr); LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd, - XEmacPs_Bd * BdSetPtr); + XEmacPs_Bd * BdSetPtr); u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, - XEmacPs_Bd ** BdSetPtr); + XEmacPs_Bd ** BdSetPtr); u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, - XEmacPs_Bd ** BdSetPtr); + XEmacPs_Bd ** BdSetPtr); LONG XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction); void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc); diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c index cb45bc7f10..4c15d918ce 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c @@ -20,8 +20,8 @@ * ----- ---- -------- ------------------------------------------------------- * 1.00a wsy 01/10/10 First release * 1.02a asa 11/05/12 Added a new API for deleting an entry from the HASH - * register. Added a new API for setting the BURST length - * in DMACR register. + * register. Added a new API for setting the BURST length + * in DMACR register. * 2.1 srt 07/15/14 Add support for Zynq Ultrascale Mp architecture. * 3.0 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. * 3.0 hk 02/20/15 Added support for jumbo frames. @@ -73,37 +73,37 @@ LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index) Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U)); - /* Be sure device has been stopped */ + /* Be sure device has been stopped */ if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); - } + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else{ - /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ - IndexLoc--; + /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ + IndexLoc--; - /* Set the MAC bits [31:0] in BOT */ - MacAddr = *(Aptr); - MacAddr |= ((u32)(*(Aptr+1)) << 8U); - MacAddr |= ((u32)(*(Aptr+2)) << 16U); - MacAddr |= ((u32)(*(Aptr+3)) << 24U); + /* Set the MAC bits [31:0] in BOT */ + MacAddr = *(Aptr); + MacAddr |= ((u32)(*(Aptr+1)) << 8U); + MacAddr |= ((u32)(*(Aptr+2)) << 16U); + MacAddr |= ((u32)(*(Aptr+3)) << 24U); XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr); + ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr); - /* There are reserved bits in TOP so don't affect them */ + /* There are reserved bits in TOP so don't affect them */ MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8))); + ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8))); - MacAddr &= (u32)(~XEMACPS_LADDR_MACH_MASK); + MacAddr &= (u32)(~XEMACPS_LADDR_MACH_MASK); - /* Set MAC bits [47:32] in TOP */ - MacAddr |= (u32)(*(Aptr+4)); - MacAddr |= (u32)(*(Aptr+5)) << 8U; + /* Set MAC bits [47:32] in TOP */ + MacAddr |= (u32)(*(Aptr+4)); + MacAddr |= (u32)(*(Aptr+5)) << 8U; XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr); + ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr); - Status = (LONG)(XST_SUCCESS); - } + Status = (LONG)(XST_SUCCESS); + } return Status; } @@ -128,21 +128,21 @@ void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index) Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); Xil_AssertVoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U)); - /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ + /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ IndexLoc--; MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8))); - *Aptr = (u8) MacAddr; - *(Aptr+1) = (u8) (MacAddr >> 8U); - *(Aptr+2) = (u8) (MacAddr >> 16U); - *(Aptr+3) = (u8) (MacAddr >> 24U); + ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8))); + *Aptr = (u8) MacAddr; + *(Aptr+1) = (u8) (MacAddr >> 8U); + *(Aptr+2) = (u8) (MacAddr >> 16U); + *(Aptr+3) = (u8) (MacAddr >> 24U); - /* Read MAC bits [47:32] in TOP */ + /* Read MAC bits [47:32] in TOP */ MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8))); - *(Aptr+4) = (u8) MacAddr; - *(Aptr+5) = (u8) (MacAddr >> 8U); + ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8))); + *(Aptr+4) = (u8) MacAddr; + *(Aptr+5) = (u8) (MacAddr >> 8U); } @@ -216,43 +216,43 @@ LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr) Xil_AssertNonvoid(AddressPtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - /* Be sure device has been stopped */ + /* Be sure device has been stopped */ if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); - } else { - Temp1 = (*(Aptr+0)) & 0x3FU; - Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + Temp1 = (*(Aptr+0)) & 0x3FU; + Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); - Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x3U) << 4U); - Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); - Temp5 = (*(Aptr+3)) & 0x3FU; - Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); - Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); - Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); + Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x3U) << 4U); + Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); + Temp5 = (*(Aptr+3)) & 0x3FU; + Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); + Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); + Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); - Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ - (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8); + Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ + (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8); - if (Result >= (u32)XEMACPS_MAX_HASH_BITS) { - Status = (LONG)(XST_INVALID_PARAM); - } else { + if (Result >= (u32)XEMACPS_MAX_HASH_BITS) { + Status = (LONG)(XST_INVALID_PARAM); + } else { - if (Result < (u32)32) { - HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHL_OFFSET); - HashAddr |= (u32)(0x00000001U << Result); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHL_OFFSET, HashAddr); - } else { - HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHH_OFFSET); - HashAddr |= (u32)(0x00000001U << (u32)(Result - (u32)32)); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHH_OFFSET, HashAddr); - } - Status = (LONG)(XST_SUCCESS); - } - } + if (Result < (u32)32) { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET); + HashAddr |= (u32)(0x00000001U << Result); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET, HashAddr); + } else { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET); + HashAddr |= (u32)(0x00000001U << (u32)(Result - (u32)32)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET, HashAddr); + } + Status = (LONG)(XST_SUCCESS); + } + } return Status; } @@ -286,41 +286,41 @@ LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr) Xil_AssertNonvoid(Aptr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - /* Be sure device has been stopped */ + /* Be sure device has been stopped */ if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); - } else { - Temp1 = (*(Aptr+0)) & 0x3FU; - Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); - Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x03U) << 4U); - Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); - Temp5 = (*(Aptr+3)) & 0x3FU; - Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); - Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); - Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + Temp1 = (*(Aptr+0)) & 0x3FU; + Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); + Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x03U) << 4U); + Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); + Temp5 = (*(Aptr+3)) & 0x3FU; + Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); + Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); + Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); - Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ - (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8); + Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ + (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8); - if (Result >= (u32)(XEMACPS_MAX_HASH_BITS)) { - Status = (LONG)(XST_INVALID_PARAM); - } else { - if (Result < (u32)32) { - HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHL_OFFSET); - HashAddr &= (u32)(~(0x00000001U << Result)); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHL_OFFSET, HashAddr); - } else { - HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHH_OFFSET); - HashAddr &= (u32)(~(0x00000001U << (u32)(Result - (u32)32))); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHH_OFFSET, HashAddr); - } - Status = (LONG)(XST_SUCCESS); - } - } + if (Result >= (u32)(XEMACPS_MAX_HASH_BITS)) { + Status = (LONG)(XST_INVALID_PARAM); + } else { + if (Result < (u32)32) { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET); + HashAddr &= (u32)(~(0x00000001U << Result)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET, HashAddr); + } else { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET); + HashAddr &= (u32)(~(0x00000001U << (u32)(Result - (u32)32))); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET, HashAddr); + } + Status = (LONG)(XST_SUCCESS); + } + } return Status; } /*****************************************************************************/ @@ -336,11 +336,11 @@ void XEmacPs_ClearHash(XEmacPs *InstancePtr) Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHL_OFFSET, 0x0U); + XEMACPS_HASHL_OFFSET, 0x0U); - /* write bits [63:32] in TOP */ + /* write bits [63:32] in TOP */ XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHH_OFFSET, 0x0U); + XEMACPS_HASHH_OFFSET, 0x0U); } @@ -361,12 +361,12 @@ void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr) Xil_AssertVoid(AddressPtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - *(Aptr+0) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHL_OFFSET); + *(Aptr+0) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET); - /* Read Hash bits [63:32] in TOP */ - *(Aptr+1) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_HASHH_OFFSET); + /* Read Hash bits [63:32] in TOP */ + *(Aptr+1) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET); } @@ -392,20 +392,20 @@ LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index) Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_TYPE_ID) && (IndexLoc > 0x00U)); - /* Be sure device has been stopped */ + /* Be sure device has been stopped */ if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); - } else { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { - /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ - IndexLoc--; + /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ + IndexLoc--; - /* Set the ID bits in MATCHx register */ + /* Set the ID bits in MATCHx register */ XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - ((u32)XEMACPS_MATCH1_OFFSET + ((u32)IndexLoc * (u32)4)), Id_Check); + ((u32)XEMACPS_MATCH1_OFFSET + ((u32)IndexLoc * (u32)4)), Id_Check); - Status = (LONG)(XST_SUCCESS); - } + Status = (LONG)(XST_SUCCESS); + } return Status; } @@ -429,150 +429,150 @@ LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index) *****************************************************************************/ LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options) { - u32 Reg; /* Generic register contents */ - u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ - u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ + u32 Reg; /* Generic register contents */ + u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ + u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ LONG Status; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - /* Be sure device has been stopped */ + /* Be sure device has been stopped */ if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); - } else { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { - /* Many of these options will change the NET_CONFIG registers. - * To reduce the amount of IO to the device, group these options here - * and change them all at once. - */ + /* Many of these options will change the NET_CONFIG registers. + * To reduce the amount of IO to the device, group these options here + * and change them all at once. + */ - /* Grab current register contents */ + /* Grab current register contents */ RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET); + XEMACPS_NWCFG_OFFSET); RegNewNetCfg = RegNetCfg; - /* - * It is configured to max 1536. - */ - if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { - RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK); - } + /* + * It is configured to max 1536. + */ + if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { + RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK); + } - /* Turn on VLAN packet only, only VLAN tagged will be accepted */ - if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK; - } + /* Turn on VLAN packet only, only VLAN tagged will be accepted */ + if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK; + } - /* Turn on FCS stripping on receive packets */ - if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK; - } + /* Turn on FCS stripping on receive packets */ + if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK; + } - /* Turn on length/type field checking on receive packets */ - if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_LENERRDSCRD_MASK; - } + /* Turn on length/type field checking on receive packets */ + if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_LENERRDSCRD_MASK; + } - /* Turn on flow control */ - if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK; - } + /* Turn on flow control */ + if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK; + } - /* Turn on promiscuous frame filtering (all frames are received) */ - if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK; - } + /* Turn on promiscuous frame filtering (all frames are received) */ + if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK; + } - /* Allow broadcast address reception */ - if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_BCASTDI_MASK); - } + /* Allow broadcast address reception */ + if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_BCASTDI_MASK); + } - /* Allow multicast address filtering */ - if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK; - } + /* Allow multicast address filtering */ + if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK; + } - /* enable RX checksum offload */ - if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK; - } + /* enable RX checksum offload */ + if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK; + } - /* Enable jumbo frames */ + /* Enable jumbo frames */ if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) && - (InstancePtr->Version > 2)) { - RegNewNetCfg |= XEMACPS_NWCFG_JUMBO_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_JUMBOMAXLEN_OFFSET, XEMACPS_RX_BUF_SIZE_JUMBO); - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET); - Reg &= ~XEMACPS_DMACR_RXBUF_MASK; - Reg |= (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO / (u32)XEMACPS_RX_BUF_UNIT) + - (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO % - (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << - (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & - (u32)(XEMACPS_DMACR_RXBUF_MASK)); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET, Reg); - InstancePtr->MaxMtuSize = XEMACPS_MTU_JUMBO; - InstancePtr->MaxFrameSize = XEMACPS_MTU_JUMBO + - XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; - InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + - XEMACPS_HDR_VLAN_SIZE; - InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_JUMBO_MASK; - } + (InstancePtr->Version > 2)) { + RegNewNetCfg |= XEMACPS_NWCFG_JUMBO_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_JUMBOMAXLEN_OFFSET, XEMACPS_RX_BUF_SIZE_JUMBO); + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg &= ~XEMACPS_DMACR_RXBUF_MASK; + Reg |= (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO / (u32)XEMACPS_RX_BUF_UNIT) + + (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO % + (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << + (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & + (u32)(XEMACPS_DMACR_RXBUF_MASK)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + InstancePtr->MaxMtuSize = XEMACPS_MTU_JUMBO; + InstancePtr->MaxFrameSize = XEMACPS_MTU_JUMBO + + XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; + InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + + XEMACPS_HDR_VLAN_SIZE; + InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_JUMBO_MASK; + } if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) && - (InstancePtr->Version > 2)) { - RegNewNetCfg |= (XEMACPS_NWCFG_SGMIIEN_MASK | - XEMACPS_NWCFG_PCSSEL_MASK); - } + (InstancePtr->Version > 2)) { + RegNewNetCfg |= (XEMACPS_NWCFG_SGMIIEN_MASK | + XEMACPS_NWCFG_PCSSEL_MASK); + } - /* Officially change the NET_CONFIG registers if it needs to be - * modified. - */ + /* Officially change the NET_CONFIG registers if it needs to be + * modified. + */ if (RegNetCfg != RegNewNetCfg) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET, RegNewNetCfg); - } + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, RegNewNetCfg); + } - /* Enable TX checksum offload */ - if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET); - Reg |= XEMACPS_DMACR_TCPCKSUM_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET, Reg); - } + /* Enable TX checksum offload */ + if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg |= XEMACPS_DMACR_TCPCKSUM_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + } - /* Enable transmitter */ - if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - Reg |= XEMACPS_NWCTRL_TXEN_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, Reg); - } + /* Enable transmitter */ + if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg |= XEMACPS_NWCTRL_TXEN_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } - /* Enable receiver */ - if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - Reg |= XEMACPS_NWCTRL_RXEN_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, Reg); - } + /* Enable receiver */ + if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg |= XEMACPS_NWCTRL_RXEN_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } - /* The remaining options not handled here are managed elsewhere in the - * driver. No register modifications are needed at this time. Reflecting - * the option in InstancePtr->Options is good enough for now. - */ + /* The remaining options not handled here are managed elsewhere in the + * driver. No register modifications are needed at this time. Reflecting + * the option in InstancePtr->Options is good enough for now. + */ - /* Set options word to its new value */ + /* Set options word to its new value */ InstancePtr->Options |= Options; - Status = (LONG)(XST_SUCCESS); - } + Status = (LONG)(XST_SUCCESS); + } return Status; } @@ -596,148 +596,148 @@ LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options) *****************************************************************************/ LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options) { - u32 Reg; /* Generic */ - u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ - u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ + u32 Reg; /* Generic */ + u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ + u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ LONG Status; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - /* Be sure device has been stopped */ + /* Be sure device has been stopped */ if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STARTED); - } else { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { - /* Many of these options will change the NET_CONFIG registers. - * To reduce the amount of IO to the device, group these options here - * and change them all at once. - */ + /* Many of these options will change the NET_CONFIG registers. + * To reduce the amount of IO to the device, group these options here + * and change them all at once. + */ - /* Grab current register contents */ + /* Grab current register contents */ RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET); + XEMACPS_NWCFG_OFFSET); RegNewNetCfg = RegNetCfg; - /* There is only RX configuration!? - * It is configured in two different length, up to 1536 and 10240 bytes - */ - if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_1536RXEN_MASK); - } + /* There is only RX configuration!? + * It is configured in two different length, up to 1536 and 10240 bytes + */ + if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_1536RXEN_MASK); + } - /* Turn off VLAN packet only */ - if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_NVLANDISC_MASK); - } + /* Turn off VLAN packet only */ + if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_NVLANDISC_MASK); + } - /* Turn off FCS stripping on receive packets */ - if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_FCSREM_MASK); - } + /* Turn off FCS stripping on receive packets */ + if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_FCSREM_MASK); + } - /* Turn off length/type field checking on receive packets */ - if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_LENERRDSCRD_MASK); - } + /* Turn off length/type field checking on receive packets */ + if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_LENERRDSCRD_MASK); + } - /* Turn off flow control */ - if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_PAUSEEN_MASK); - } + /* Turn off flow control */ + if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_PAUSEEN_MASK); + } - /* Turn off promiscuous frame filtering (all frames are received) */ - if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_COPYALLEN_MASK); - } + /* Turn off promiscuous frame filtering (all frames are received) */ + if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_COPYALLEN_MASK); + } - /* Disallow broadcast address filtering => broadcast reception */ - if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { - RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK; - } + /* Disallow broadcast address filtering => broadcast reception */ + if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK; + } - /* Disallow multicast address filtering */ - if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_MCASTHASHEN_MASK); - } + /* Disallow multicast address filtering */ + if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_MCASTHASHEN_MASK); + } - /* Disable RX checksum offload */ - if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_RXCHKSUMEN_MASK); - } + /* Disable RX checksum offload */ + if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_RXCHKSUMEN_MASK); + } - /* Disable jumbo frames */ + /* Disable jumbo frames */ if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) && - (InstancePtr->Version > 2)) { - RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_JUMBO_MASK); - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET); - Reg &= ~XEMACPS_DMACR_RXBUF_MASK; - Reg |= (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) + - (((((u32)XEMACPS_RX_BUF_SIZE % - (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << - (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & - (u32)(XEMACPS_DMACR_RXBUF_MASK)); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET, Reg); - InstancePtr->MaxMtuSize = XEMACPS_MTU; - InstancePtr->MaxFrameSize = XEMACPS_MTU + - XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; - InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + - XEMACPS_HDR_VLAN_SIZE; - InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK; - } + (InstancePtr->Version > 2)) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_JUMBO_MASK); + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg &= ~XEMACPS_DMACR_RXBUF_MASK; + Reg |= (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) + + (((((u32)XEMACPS_RX_BUF_SIZE % + (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << + (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & + (u32)(XEMACPS_DMACR_RXBUF_MASK)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + InstancePtr->MaxMtuSize = XEMACPS_MTU; + InstancePtr->MaxFrameSize = XEMACPS_MTU + + XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; + InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + + XEMACPS_HDR_VLAN_SIZE; + InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK; + } if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) && - (InstancePtr->Version > 2)) { - RegNewNetCfg &= (u32)(~(XEMACPS_NWCFG_SGMIIEN_MASK | - XEMACPS_NWCFG_PCSSEL_MASK)); - } + (InstancePtr->Version > 2)) { + RegNewNetCfg &= (u32)(~(XEMACPS_NWCFG_SGMIIEN_MASK | + XEMACPS_NWCFG_PCSSEL_MASK)); + } - /* Officially change the NET_CONFIG registers if it needs to be - * modified. - */ + /* Officially change the NET_CONFIG registers if it needs to be + * modified. + */ if (RegNetCfg != RegNewNetCfg) { - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET, RegNewNetCfg); - } + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, RegNewNetCfg); + } - /* Disable TX checksum offload */ - if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET); - Reg &= (u32)(~XEMACPS_DMACR_TCPCKSUM_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET, Reg); - } + /* Disable TX checksum offload */ + if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg &= (u32)(~XEMACPS_DMACR_TCPCKSUM_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + } - /* Disable transmitter */ - if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, Reg); - } + /* Disable transmitter */ + if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } - /* Disable receiver */ - if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { - Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, Reg); - } + /* Disable receiver */ + if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } - /* The remaining options not handled here are managed elsewhere in the - * driver. No register modifications are needed at this time. Reflecting - * option in InstancePtr->Options is good enough for now. - */ + /* The remaining options not handled here are managed elsewhere in the + * driver. No register modifications are needed at this time. Reflecting + * option in InstancePtr->Options is good enough for now. + */ - /* Set options word to its new value */ + /* Set options word to its new value */ InstancePtr->Options &= ~Options; - Status = (LONG)(XST_SUCCESS); - } + Status = (LONG)(XST_SUCCESS); + } return Status; } @@ -784,18 +784,18 @@ LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr) Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - /* Make sure device is ready for this operation */ + /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) { - Status = (LONG)(XST_DEVICE_IS_STOPPED); - } else { - /* Send flow control frame */ + Status = (LONG)(XST_DEVICE_IS_STOPPED); + } else { + /* Send flow control frame */ Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); + XEMACPS_NWCTRL_OFFSET); Reg |= XEMACPS_NWCTRL_PAUSETX_MASK; XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, Reg); - Status = (LONG)(XST_SUCCESS); - } + XEMACPS_NWCTRL_OFFSET, Reg); + Status = (LONG)(XST_SUCCESS); + } return Status; } @@ -821,17 +821,17 @@ u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr) Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET); + XEMACPS_NWCFG_OFFSET); if ((Reg & XEMACPS_NWCFG_1000_MASK) != 0x00000000U) { - Status = (u16)(1000); - } else { - if ((Reg & XEMACPS_NWCFG_100_MASK) != 0x00000000U) { - Status = (u16)(100); - } else { - Status = (u16)(10); - } - } + Status = (u16)(1000); + } else { + if ((Reg & XEMACPS_NWCFG_100_MASK) != 0x00000000U) { + Status = (u16)(100); + } else { + Status = (u16)(10); + } + } return Status; } @@ -857,11 +857,11 @@ void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed) Xil_AssertVoid((Speed == (u16)10) || (Speed == (u16)100) || (Speed == (u16)1000)); Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET); + XEMACPS_NWCFG_OFFSET); Reg &= (u32)(~(XEMACPS_NWCFG_1000_MASK | XEMACPS_NWCFG_100_MASK)); switch (Speed) { - case (u16)10: + case (u16)10: break; case (u16)100: @@ -919,14 +919,14 @@ void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor) Xil_AssertVoid(Divisor <= (XEmacPs_MdcDiv)0x7); /* only last three bits are valid */ Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET); - /* clear these three bits, could be done with mask */ + XEMACPS_NWCFG_OFFSET); + /* clear these three bits, could be done with mask */ Reg &= (u32)(~XEMACPS_NWCFG_MDCCLKDIV_MASK); Reg |= ((u32)Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK); XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCFG_OFFSET, Reg); + XEMACPS_NWCFG_OFFSET, Reg); } @@ -968,7 +968,7 @@ void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor) * ******************************************************************************/ LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, - u32 RegisterNum, u16 *PhyDataPtr) + u32 RegisterNum, u16 *PhyDataPtr) { u32 Mgtcr; volatile u32 Ipisr; @@ -977,33 +977,33 @@ LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, Xil_AssertNonvoid(InstancePtr != NULL); - /* Make sure no other PHY operation is currently in progress */ + /* Make sure no other PHY operation is currently in progress */ if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWSR_OFFSET) & - XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) { - Status = (LONG)(XST_EMAC_MII_BUSY); - } else { + XEMACPS_NWSR_OFFSET) & + XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) { + Status = (LONG)(XST_EMAC_MII_BUSY); + } else { - /* Construct Mgtcr mask for the operation */ + /* Construct Mgtcr mask for the operation */ Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK | - (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) | - (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK); + (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) | + (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK); - /* Write Mgtcr and wait for completion */ + /* Write Mgtcr and wait for completion */ XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_PHYMNTNC_OFFSET, Mgtcr); + XEMACPS_PHYMNTNC_OFFSET, Mgtcr); do { - Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWSR_OFFSET); - IpReadTemp = Ipisr; - } while ((IpReadTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U); + Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET); + IpReadTemp = Ipisr; + } while ((IpReadTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U); - /* Read data */ - *PhyDataPtr = (u16)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_PHYMNTNC_OFFSET); - Status = (LONG)(XST_SUCCESS); - } + /* Read data */ + *PhyDataPtr = (u16)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_PHYMNTNC_OFFSET); + Status = (LONG)(XST_SUCCESS); + } return Status; } @@ -1049,7 +1049,7 @@ LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, * ******************************************************************************/ LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress, - u32 RegisterNum, u16 PhyData) + u32 RegisterNum, u16 PhyData) { u32 Mgtcr; volatile u32 Ipisr; @@ -1058,29 +1058,29 @@ LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress, Xil_AssertNonvoid(InstancePtr != NULL); - /* Make sure no other PHY operation is currently in progress */ + /* Make sure no other PHY operation is currently in progress */ if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWSR_OFFSET) & - XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) { - Status = (LONG)(XST_EMAC_MII_BUSY); - } else { - /* Construct Mgtcr mask for the operation */ + XEMACPS_NWSR_OFFSET) & + XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) { + Status = (LONG)(XST_EMAC_MII_BUSY); + } else { + /* Construct Mgtcr mask for the operation */ Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK | - (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) | - (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK) | (u32)PhyData; + (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) | + (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK) | (u32)PhyData; - /* Write Mgtcr and wait for completion */ + /* Write Mgtcr and wait for completion */ XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_PHYMNTNC_OFFSET, Mgtcr); + XEMACPS_PHYMNTNC_OFFSET, Mgtcr); do { - Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWSR_OFFSET); - IpWriteTemp = Ipisr; - } while ((IpWriteTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U); + Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET); + IpWriteTemp = Ipisr; + } while ((IpWriteTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U); - Status = (LONG)(XST_SUCCESS); - } + Status = (LONG)(XST_SUCCESS); + } return Status; } @@ -1101,33 +1101,33 @@ void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength) Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid((BLength == XEMACPS_SINGLE_BURST) || - (BLength == XEMACPS_4BYTE_BURST) || - (BLength == XEMACPS_8BYTE_BURST) || - (BLength == XEMACPS_16BYTE_BURST)); + (BLength == XEMACPS_4BYTE_BURST) || + (BLength == XEMACPS_8BYTE_BURST) || + (BLength == XEMACPS_16BYTE_BURST)); switch (BLength) { - case XEMACPS_SINGLE_BURST: - RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST; - break; + case XEMACPS_SINGLE_BURST: + RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST; + break; - case XEMACPS_4BYTE_BURST: - RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST; - break; + case XEMACPS_4BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST; + break; - case XEMACPS_8BYTE_BURST: - RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST; - break; + case XEMACPS_8BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST; + break; - case XEMACPS_16BYTE_BURST: - RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST; - break; - } + case XEMACPS_16BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST; + break; + } Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_DMACR_OFFSET); + XEMACPS_DMACR_OFFSET); Reg &= (u32)(~XEMACPS_DMACR_BLENGTH_MASK); Reg |= RegUpdateVal; XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, - Reg); + Reg); } /** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c index c3d94f4d59..28578cf3a4 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c @@ -22,11 +22,11 @@ XEmacPs_Config XEmacPs_ConfigTable[XPAR_XEMACPS_NUM_INSTANCES] = { - { - XPAR_PSU_ETHERNET_3_DEVICE_ID, - XPAR_PSU_ETHERNET_3_BASEADDR, - XPAR_PSU_ETHERNET_3_IS_CACHE_COHERENT - } + { + XPAR_PSU_ETHERNET_3_DEVICE_ID, + XPAR_PSU_ETHERNET_3_BASEADDR, + XPAR_PSU_ETHERNET_3_IS_CACHE_COHERENT + } }; diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c index 6e72317e16..b47a286194 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c @@ -62,35 +62,35 @@ void XEmacPs_ResetHw(u32 BaseAddr) { u32 RegVal; - /* Disable the interrupts */ + /* Disable the interrupts */ XEmacPs_WriteReg(BaseAddr,XEMACPS_IDR_OFFSET,0x0U); - /* Stop transmission,disable loopback and Stop tx and Rx engines */ + /* Stop transmission,disable loopback and Stop tx and Rx engines */ RegVal = XEmacPs_ReadReg(BaseAddr,XEMACPS_NWCTRL_OFFSET); RegVal &= ~((u32)XEMACPS_NWCTRL_TXEN_MASK| - (u32)XEMACPS_NWCTRL_RXEN_MASK| - (u32)XEMACPS_NWCTRL_HALTTX_MASK| - (u32)XEMACPS_NWCTRL_LOOPEN_MASK); - /* Clear the statistic registers, flush the packets in DPRAM*/ + (u32)XEMACPS_NWCTRL_RXEN_MASK| + (u32)XEMACPS_NWCTRL_HALTTX_MASK| + (u32)XEMACPS_NWCTRL_LOOPEN_MASK); + /* Clear the statistic registers, flush the packets in DPRAM*/ RegVal |= (XEMACPS_NWCTRL_STATCLR_MASK| - XEMACPS_NWCTRL_FLUSH_DPRAM_MASK); + XEMACPS_NWCTRL_FLUSH_DPRAM_MASK); XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCTRL_OFFSET,RegVal); - /* Clear the interrupt status */ + /* Clear the interrupt status */ XEmacPs_WriteReg(BaseAddr,XEMACPS_ISR_OFFSET,XEMACPS_IXR_ALL_MASK); - /* Clear the tx status */ + /* Clear the tx status */ XEmacPs_WriteReg(BaseAddr,XEMACPS_TXSR_OFFSET,(XEMACPS_TXSR_ERROR_MASK| - (u32)XEMACPS_TXSR_TXCOMPL_MASK| - (u32)XEMACPS_TXSR_TXGO_MASK)); - /* Clear the rx status */ + (u32)XEMACPS_TXSR_TXCOMPL_MASK| + (u32)XEMACPS_TXSR_TXGO_MASK)); + /* Clear the rx status */ XEmacPs_WriteReg(BaseAddr,XEMACPS_RXSR_OFFSET, - XEMACPS_RXSR_FRAMERX_MASK); - /* Clear the tx base address */ + XEMACPS_RXSR_FRAMERX_MASK); + /* Clear the tx base address */ XEmacPs_WriteReg(BaseAddr,XEMACPS_TXQBASE_OFFSET,0x0U); - /* Clear the rx base address */ + /* Clear the rx base address */ XEmacPs_WriteReg(BaseAddr,XEMACPS_RXQBASE_OFFSET,0x0U); - /* Update the network config register with reset value */ + /* Update the network config register with reset value */ XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCFG_OFFSET,XEMACPS_NWCFG_RESET_MASK); - /* Update the hash address registers with reset value */ + /* Update the hash address registers with reset value */ XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHL_OFFSET,0x0U); XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHH_OFFSET,0x0U); } diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h index a8ea3a8315..11c5a4e86a 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h @@ -25,10 +25,10 @@ * 1.02a asa 11/05/12 Added hash defines for DMACR burst length configuration. * 1.05a kpc 28/06/13 Added XEmacPs_ResetHw function prototype * 1.06a asa 11/02/13 Changed the value for XEMACPS_RXBUF_LEN_MASK from 0x3fff -* to 0x1fff. This fixes the CR#744902. +* to 0x1fff. This fixes the CR#744902. * 2.1 srt 07/15/14 Add support for Zynq Ultrascale Mp GEM specification. * 3.0 kvn 12/16/14 Changed name of XEMACPS_NWCFG_LENGTHERRDSCRD_MASK to -* XEMACPS_NWCFG_LENERRDSCRD_MASK as it exceeds 31 characters. +* XEMACPS_NWCFG_LENERRDSCRD_MASK as it exceeds 31 characters. * 3.0 kpc 1/23/15 Corrected the extended descriptor macro values. * 3.0 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. * 3.0 hk 03/18/15 Added support for jumbo frames. @@ -42,8 +42,8 @@ * ******************************************************************************/ -#ifndef XEMACPS_HW_H /* prevent circular inclusions */ -#define XEMACPS_HW_H /* by using protection macros */ +#ifndef XEMACPS_HW_H /* prevent circular inclusions */ +#define XEMACPS_HW_H /* by using protection macros */ /***************************** Include Files *********************************/ @@ -80,8 +80,8 @@ extern "C" { * to specify whether an operation specifies a send or receive channel. * @{ */ -#define XEMACPS_SEND 1U /**< send direction */ -#define XEMACPS_RECV 2U /**< receive direction */ +#define XEMACPS_SEND 1U /**< send direction */ +#define XEMACPS_RECV 2U /**< receive direction */ /*@}*/ /** @name MDC clock division @@ -250,47 +250,47 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, #define XEMACPS_RXUDPCCNT_OFFSET 0x000001B0U /**< UDP Checksum Error Counter */ #define XEMACPS_LAST_OFFSET 0x000001B4U /**< Last statistic counter - offset, for clearing */ + offset, for clearing */ #define XEMACPS_1588_SEC_OFFSET 0x000001D0U /**< 1588 second counter */ #define XEMACPS_1588_NANOSEC_OFFSET 0x000001D4U /**< 1588 nanosecond counter */ #define XEMACPS_1588_ADJ_OFFSET 0x000001D8U /**< 1588 nanosecond - adjustment counter */ + adjustment counter */ #define XEMACPS_1588_INC_OFFSET 0x000001DCU /**< 1588 nanosecond - increment counter */ + increment counter */ #define XEMACPS_PTP_TXSEC_OFFSET 0x000001E0U /**< 1588 PTP transmit second - counter */ + counter */ #define XEMACPS_PTP_TXNANOSEC_OFFSET 0x000001E4U /**< 1588 PTP transmit - nanosecond counter */ + nanosecond counter */ #define XEMACPS_PTP_RXSEC_OFFSET 0x000001E8U /**< 1588 PTP receive second - counter */ + counter */ #define XEMACPS_PTP_RXNANOSEC_OFFSET 0x000001ECU /**< 1588 PTP receive - nanosecond counter */ + nanosecond counter */ #define XEMACPS_PTPP_TXSEC_OFFSET 0x000001F0U /**< 1588 PTP peer transmit - second counter */ + second counter */ #define XEMACPS_PTPP_TXNANOSEC_OFFSET 0x000001F4U /**< 1588 PTP peer transmit - nanosecond counter */ + nanosecond counter */ #define XEMACPS_PTPP_RXSEC_OFFSET 0x000001F8U /**< 1588 PTP peer receive - second counter */ + second counter */ #define XEMACPS_PTPP_RXNANOSEC_OFFSET 0x000001FCU /**< 1588 PTP peer receive - nanosecond counter */ + nanosecond counter */ #define XEMACPS_INTQ1_STS_OFFSET 0x00000400U /**< Interrupt Q1 Status - reg */ -#define XEMACPS_TXQ1BASE_OFFSET 0x00000440U /**< TX Q1 Base address - reg */ -#define XEMACPS_RXQ1BASE_OFFSET 0x00000480U /**< RX Q1 Base address - reg */ + reg */ +#define XEMACPS_TXQ1BASE_OFFSET 0x00000440U /**< TX Q1 Base address + reg */ +#define XEMACPS_RXQ1BASE_OFFSET 0x00000480U /**< RX Q1 Base address + reg */ #define XEMACPS_MSBBUF_TXQBASE_OFFSET 0x000004C8U /**< MSB Buffer TX Q Base - reg */ + reg */ #define XEMACPS_MSBBUF_RXQBASE_OFFSET 0x000004D4U /**< MSB Buffer RX Q Base - reg */ + reg */ #define XEMACPS_INTQ1_IER_OFFSET 0x00000600U /**< Interrupt Q1 Enable - reg */ + reg */ #define XEMACPS_INTQ1_IDR_OFFSET 0x00000620U /**< Interrupt Q1 Disable - reg */ + reg */ #define XEMACPS_INTQ1_IMR_OFFSET 0x00000640U /**< Interrupt Q1 Mask - reg */ + reg */ /* Define some bit positions for registers. */ @@ -298,7 +298,7 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, * @{ */ #define XEMACPS_NWCTRL_FLUSH_DPRAM_MASK 0x00040000U /**< Flush a packet from - Rx SRAM */ + Rx SRAM */ #define XEMACPS_NWCTRL_ZEROPAUSETX_MASK 0x00000800U /**< Transmit zero quantum pause frame */ #define XEMACPS_NWCTRL_PAUSETX_MASK 0x00000800U /**< Transmit pause frame */ @@ -333,7 +333,7 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, #define XEMACPS_NWCFG_PAUSECOPYDI_MASK 0x00800000U /**< Do not copy pause Frames to memory */ #define XEMACPS_NWCFG_DWIDTH_64_MASK 0x00200000U /**< 64 bit Data bus width */ -#define XEMACPS_NWCFG_MDC_SHIFT_MASK 18U /**< shift bits for MDC */ +#define XEMACPS_NWCFG_MDC_SHIFT_MASK 18U /**< shift bits for MDC */ #define XEMACPS_NWCFG_MDCCLKDIV_MASK 0x001C0000U /**< MDC Mask PCLK divisor */ #define XEMACPS_NWCFG_FCSREM_MASK 0x00020000U /**< Discard FCS from received frames */ @@ -382,19 +382,19 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, /** @name DMA control register bit definitions * @{ */ -#define XEMACPS_DMACR_ADDR_WIDTH_64 0x40000000U /**< 64 bit address bus */ -#define XEMACPS_DMACR_TXEXTEND_MASK 0x20000000U /**< Tx Extended desc mode */ -#define XEMACPS_DMACR_RXEXTEND_MASK 0x10000000U /**< Rx Extended desc mode */ -#define XEMACPS_DMACR_RXBUF_MASK 0x00FF0000U /**< Mask bit for RX buffer - size */ -#define XEMACPS_DMACR_RXBUF_SHIFT 16U /**< Shift bit for RX buffer - size */ -#define XEMACPS_DMACR_TCPCKSUM_MASK 0x00000800U /**< enable/disable TX - checksum offload */ -#define XEMACPS_DMACR_TXSIZE_MASK 0x00000400U /**< TX buffer memory size */ -#define XEMACPS_DMACR_RXSIZE_MASK 0x00000300U /**< RX buffer memory size */ -#define XEMACPS_DMACR_ENDIAN_MASK 0x00000080U /**< endian configuration */ -#define XEMACPS_DMACR_BLENGTH_MASK 0x0000001FU /**< buffer burst length */ +#define XEMACPS_DMACR_ADDR_WIDTH_64 0x40000000U /**< 64 bit address bus */ +#define XEMACPS_DMACR_TXEXTEND_MASK 0x20000000U /**< Tx Extended desc mode */ +#define XEMACPS_DMACR_RXEXTEND_MASK 0x10000000U /**< Rx Extended desc mode */ +#define XEMACPS_DMACR_RXBUF_MASK 0x00FF0000U /**< Mask bit for RX buffer + size */ +#define XEMACPS_DMACR_RXBUF_SHIFT 16U /**< Shift bit for RX buffer + size */ +#define XEMACPS_DMACR_TCPCKSUM_MASK 0x00000800U /**< enable/disable TX + checksum offload */ +#define XEMACPS_DMACR_TXSIZE_MASK 0x00000400U /**< TX buffer memory size */ +#define XEMACPS_DMACR_RXSIZE_MASK 0x00000300U /**< RX buffer memory size */ +#define XEMACPS_DMACR_ENDIAN_MASK 0x00000080U /**< endian configuration */ +#define XEMACPS_DMACR_BLENGTH_MASK 0x0000001FU /**< buffer burst length */ #define XEMACPS_DMACR_SINGLE_AHB_BURST 0x00000001U /**< single AHB bursts */ #define XEMACPS_DMACR_INCR4_AHB_BURST 0x00000004U /**< 4 bytes AHB bursts */ #define XEMACPS_DMACR_INCR8_AHB_BURST 0x00000008U /**< 8 bytes AHB bursts */ @@ -446,8 +446,8 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, #define XEMACPS_INTQ1SR_TXCOMPL_MASK 0x00000080U /**< Transmit completed OK */ #define XEMACPS_INTQ1SR_TXERR_MASK 0x00000040U /**< Transmit AMBA Error */ -#define XEMACPS_INTQ1_IXR_ALL_MASK ((u32)XEMACPS_INTQ1SR_TXCOMPL_MASK | \ - (u32)XEMACPS_INTQ1SR_TXERR_MASK) +#define XEMACPS_INTQ1_IXR_ALL_MASK ((u32)XEMACPS_INTQ1SR_TXCOMPL_MASK | \ + (u32)XEMACPS_INTQ1SR_TXERR_MASK) /*@}*/ @@ -462,27 +462,27 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, #define XEMACPS_IXR_PTPPSRX_MASK 0x00800000U /**< PTP Pdelay_resp RXed */ #define XEMACPS_IXR_PTPPDRRX_MASK 0x00400000U /**< PTP Pdelay_req RXed */ -#define XEMACPS_IXR_PTPSTX_MASK 0x00200000U /**< PTP Sync TXed */ +#define XEMACPS_IXR_PTPSTX_MASK 0x00200000U /**< PTP Sync TXed */ #define XEMACPS_IXR_PTPDRTX_MASK 0x00100000U /**< PTP Delay_req TXed */ -#define XEMACPS_IXR_PTPSRX_MASK 0x00080000U /**< PTP Sync RXed */ +#define XEMACPS_IXR_PTPSRX_MASK 0x00080000U /**< PTP Sync RXed */ #define XEMACPS_IXR_PTPDRRX_MASK 0x00040000U /**< PTP Delay_req RXed */ -#define XEMACPS_IXR_PAUSETX_MASK 0x00004000U /**< Pause frame transmitted */ -#define XEMACPS_IXR_PAUSEZERO_MASK 0x00002000U /**< Pause time has reached +#define XEMACPS_IXR_PAUSETX_MASK 0x00004000U /**< Pause frame transmitted */ +#define XEMACPS_IXR_PAUSEZERO_MASK 0x00002000U /**< Pause time has reached zero */ -#define XEMACPS_IXR_PAUSENZERO_MASK 0x00001000U /**< Pause frame received */ -#define XEMACPS_IXR_HRESPNOK_MASK 0x00000800U /**< hresp not ok */ -#define XEMACPS_IXR_RXOVR_MASK 0x00000400U /**< Receive overrun occurred */ -#define XEMACPS_IXR_TXCOMPL_MASK 0x00000080U /**< Frame transmitted ok */ -#define XEMACPS_IXR_TXEXH_MASK 0x00000040U /**< Transmit err occurred or +#define XEMACPS_IXR_PAUSENZERO_MASK 0x00001000U /**< Pause frame received */ +#define XEMACPS_IXR_HRESPNOK_MASK 0x00000800U /**< hresp not ok */ +#define XEMACPS_IXR_RXOVR_MASK 0x00000400U /**< Receive overrun occurred */ +#define XEMACPS_IXR_TXCOMPL_MASK 0x00000080U /**< Frame transmitted ok */ +#define XEMACPS_IXR_TXEXH_MASK 0x00000040U /**< Transmit err occurred or no buffers*/ -#define XEMACPS_IXR_RETRY_MASK 0x00000020U /**< Retry limit exceeded */ -#define XEMACPS_IXR_URUN_MASK 0x00000010U /**< Transmit underrun */ -#define XEMACPS_IXR_TXUSED_MASK 0x00000008U /**< Tx buffer used bit read */ -#define XEMACPS_IXR_RXUSED_MASK 0x00000004U /**< Rx buffer used bit read */ -#define XEMACPS_IXR_FRAMERX_MASK 0x00000002U /**< Frame received ok */ -#define XEMACPS_IXR_MGMNT_MASK 0x00000001U /**< PHY management complete */ -#define XEMACPS_IXR_ALL_MASK 0x00007FFFU /**< Everything! */ +#define XEMACPS_IXR_RETRY_MASK 0x00000020U /**< Retry limit exceeded */ +#define XEMACPS_IXR_URUN_MASK 0x00000010U /**< Transmit underrun */ +#define XEMACPS_IXR_TXUSED_MASK 0x00000008U /**< Tx buffer used bit read */ +#define XEMACPS_IXR_RXUSED_MASK 0x00000004U /**< Rx buffer used bit read */ +#define XEMACPS_IXR_FRAMERX_MASK 0x00000002U /**< Frame received ok */ +#define XEMACPS_IXR_MGMNT_MASK 0x00000001U /**< PHY management complete */ +#define XEMACPS_IXR_ALL_MASK 0x00007FFFU /**< Everything! */ #define XEMACPS_IXR_TX_ERR_MASK ((u32)XEMACPS_IXR_TXEXH_MASK | \ (u32)XEMACPS_IXR_RETRY_MASK | \ @@ -498,22 +498,22 @@ typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, /** @name PHY Maintenance bit definitions * @{ */ -#define XEMACPS_PHYMNTNC_OP_MASK 0x40020000U /**< operation mask bits */ -#define XEMACPS_PHYMNTNC_OP_R_MASK 0x20000000U /**< read operation */ -#define XEMACPS_PHYMNTNC_OP_W_MASK 0x10000000U /**< write operation */ -#define XEMACPS_PHYMNTNC_ADDR_MASK 0x0F800000U /**< Address bits */ -#define XEMACPS_PHYMNTNC_REG_MASK 0x007C0000U /**< register bits */ -#define XEMACPS_PHYMNTNC_DATA_MASK 0x00000FFFU /**< data bits */ -#define XEMACPS_PHYMNTNC_PHAD_SHFT_MSK 23U /**< Shift bits for PHYAD */ -#define XEMACPS_PHYMNTNC_PREG_SHFT_MSK 18U /**< Shift bits for PHREG */ +#define XEMACPS_PHYMNTNC_OP_MASK 0x40020000U /**< operation mask bits */ +#define XEMACPS_PHYMNTNC_OP_R_MASK 0x20000000U /**< read operation */ +#define XEMACPS_PHYMNTNC_OP_W_MASK 0x10000000U /**< write operation */ +#define XEMACPS_PHYMNTNC_ADDR_MASK 0x0F800000U /**< Address bits */ +#define XEMACPS_PHYMNTNC_REG_MASK 0x007C0000U /**< register bits */ +#define XEMACPS_PHYMNTNC_DATA_MASK 0x00000FFFU /**< data bits */ +#define XEMACPS_PHYMNTNC_PHAD_SHFT_MSK 23U /**< Shift bits for PHYAD */ +#define XEMACPS_PHYMNTNC_PREG_SHFT_MSK 18U /**< Shift bits for PHREG */ /*@}*/ /** @name RX watermark bit definitions * @{ */ -#define XEMACPS_RXWM_HIGH_MASK 0x0000FFFFU /**< RXWM high mask */ -#define XEMACPS_RXWM_LOW_MASK 0xFFFF0000U /**< RXWM low mask */ -#define XEMACPS_RXWM_LOW_SHFT_MSK 16U /**< Shift for RXWM low */ +#define XEMACPS_RXWM_HIGH_MASK 0x0000FFFFU /**< RXWM high mask */ +#define XEMACPS_RXWM_LOW_MASK 0xFFFF0000U /**< RXWM low mask */ +#define XEMACPS_RXWM_LOW_SHFT_MSK 16U /**< Shift for RXWM low */ /*@}*/ /* Transmit buffer descriptor status words offset diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c index f1af7b8613..69e07040e8 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c @@ -20,16 +20,16 @@ * ----- ---- -------- ------------------------------------------------------- * 1.00a wsy 01/10/10 First release * 1.03a asa 01/24/13 Fix for CR #692702 which updates error handling for -* Rx errors. Under heavy Rx traffic, there will be a large -* number of errors related to receive buffer not available. -* Because of a HW bug (SI #692601), under such heavy errors, -* the Rx data path can become unresponsive. To reduce the -* probabilities for hitting this HW bug, the SW writes to -* bit 18 to flush a packet from Rx DPRAM immediately. The -* changes for it are done in the function -* XEmacPs_IntrHandler. +* Rx errors. Under heavy Rx traffic, there will be a large +* number of errors related to receive buffer not available. +* Because of a HW bug (SI #692601), under such heavy errors, +* the Rx data path can become unresponsive. To reduce the +* probabilities for hitting this HW bug, the SW writes to +* bit 18 to flush a packet from Rx DPRAM immediately. The +* changes for it are done in the function +* XEmacPs_IntrHandler. * 2.1 srt 07/15/14 Add support for Zynq Ultrascale Mp GEM specification -* and 64-bit changes. +* and 64-bit changes. * 3.0 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. * 3.1 hk 07/27/15 Do not call error handler with '0' error code when * there is no error. CR# 869403 @@ -77,7 +77,7 @@ * *****************************************************************************/ LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType, - void *FuncPointer, void *CallBackRef) + void *FuncPointer, void *CallBackRef) { LONG Status; Xil_AssertNonvoid(InstancePtr != NULL); @@ -86,24 +86,24 @@ LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType, switch (HandlerType) { case XEMACPS_HANDLER_DMASEND: - Status = (LONG)(XST_SUCCESS); - InstancePtr->SendHandler = ((XEmacPs_Handler)(void *)FuncPointer); - InstancePtr->SendRef = CallBackRef; - break; + Status = (LONG)(XST_SUCCESS); + InstancePtr->SendHandler = ((XEmacPs_Handler)(void *)FuncPointer); + InstancePtr->SendRef = CallBackRef; + break; case XEMACPS_HANDLER_DMARECV: - Status = (LONG)(XST_SUCCESS); - InstancePtr->RecvHandler = ((XEmacPs_Handler)(void *)FuncPointer); - InstancePtr->RecvRef = CallBackRef; - break; + Status = (LONG)(XST_SUCCESS); + InstancePtr->RecvHandler = ((XEmacPs_Handler)(void *)FuncPointer); + InstancePtr->RecvRef = CallBackRef; + break; case XEMACPS_HANDLER_ERROR: - Status = (LONG)(XST_SUCCESS); - InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void *)FuncPointer); - InstancePtr->ErrorRef = CallBackRef; - break; + Status = (LONG)(XST_SUCCESS); + InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void *)FuncPointer); + InstancePtr->ErrorRef = CallBackRef; + break; default: - Status = (LONG)(XST_INVALID_PARAM); - break; - } + Status = (LONG)(XST_INVALID_PARAM); + break; + } return Status; } @@ -130,113 +130,113 @@ void XEmacPs_IntrHandler(void *XEmacPsPtr) Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); - /* This ISR will try to handle as many interrupts as it can in a single - * call. However, in most of the places where the user's error handler + /* This ISR will try to handle as many interrupts as it can in a single + * call. However, in most of the places where the user's error handler * is called, this ISR exits because it is expected that the user will * reset the device in nearly all instances. - */ + */ RegISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_ISR_OFFSET); + XEMACPS_ISR_OFFSET); - /* Read Transmit Q1 ISR */ + /* Read Transmit Q1 ISR */ if (InstancePtr->Version > 2) - RegQ1ISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_INTQ1_STS_OFFSET); + RegQ1ISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_INTQ1_STS_OFFSET); - /* Clear the interrupt status register */ + /* Clear the interrupt status register */ XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, - RegISR); + RegISR); - /* Receive complete interrupt */ + /* Receive complete interrupt */ if ((RegISR & XEMACPS_IXR_FRAMERX_MASK) != 0x00000000U) { - /* Clear RX status register RX complete indication but preserve - * error bits if there is any */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_RXSR_OFFSET, - ((u32)XEMACPS_RXSR_FRAMERX_MASK | - (u32)XEMACPS_RXSR_BUFFNA_MASK)); - InstancePtr->RecvHandler(InstancePtr->RecvRef); - } + /* Clear RX status register RX complete indication but preserve + * error bits if there is any */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXSR_OFFSET, + ((u32)XEMACPS_RXSR_FRAMERX_MASK | + (u32)XEMACPS_RXSR_BUFFNA_MASK)); + InstancePtr->RecvHandler(InstancePtr->RecvRef); + } - /* Transmit Q1 complete interrupt */ + /* Transmit Q1 complete interrupt */ if ((InstancePtr->Version > 2) && - ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) { - /* Clear TX status register TX complete indication but preserve - * error bits if there is any */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_INTQ1_STS_OFFSET, - XEMACPS_INTQ1SR_TXCOMPL_MASK); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_TXSR_OFFSET, - ((u32)XEMACPS_TXSR_TXCOMPL_MASK | - (u32)XEMACPS_TXSR_USEDREAD_MASK)); - InstancePtr->SendHandler(InstancePtr->SendRef); - } + ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) { + /* Clear TX status register TX complete indication but preserve + * error bits if there is any */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_INTQ1_STS_OFFSET, + XEMACPS_INTQ1SR_TXCOMPL_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET, + ((u32)XEMACPS_TXSR_TXCOMPL_MASK | + (u32)XEMACPS_TXSR_USEDREAD_MASK)); + InstancePtr->SendHandler(InstancePtr->SendRef); + } - /* Transmit complete interrupt */ + /* Transmit complete interrupt */ if ((RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U) { - /* Clear TX status register TX complete indication but preserve - * error bits if there is any */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_TXSR_OFFSET, - ((u32)XEMACPS_TXSR_TXCOMPL_MASK | - (u32)XEMACPS_TXSR_USEDREAD_MASK)); - InstancePtr->SendHandler(InstancePtr->SendRef); - } + /* Clear TX status register TX complete indication but preserve + * error bits if there is any */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET, + ((u32)XEMACPS_TXSR_TXCOMPL_MASK | + (u32)XEMACPS_TXSR_USEDREAD_MASK)); + InstancePtr->SendHandler(InstancePtr->SendRef); + } - /* Receive error conditions interrupt */ + /* Receive error conditions interrupt */ if ((RegISR & XEMACPS_IXR_RX_ERR_MASK) != 0x00000000U) { - /* Clear RX status register */ - RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_RXSR_OFFSET); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_RXSR_OFFSET, RegSR); + /* Clear RX status register */ + RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXSR_OFFSET); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXSR_OFFSET, RegSR); - /* Fix for CR # 692702. Write to bit 18 of net_ctrl - * register to flush a packet out of Rx SRAM upon - * an error for receive buffer not available. */ - if ((RegISR & XEMACPS_IXR_RXUSED_MASK) != 0x00000000U) { - RegCtrl = - XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET); - RegCtrl |= (u32)XEMACPS_NWCTRL_FLUSH_DPRAM_MASK; - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_NWCTRL_OFFSET, RegCtrl); - } + /* Fix for CR # 692702. Write to bit 18 of net_ctrl + * register to flush a packet out of Rx SRAM upon + * an error for receive buffer not available. */ + if ((RegISR & XEMACPS_IXR_RXUSED_MASK) != 0x00000000U) { + RegCtrl = + XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + RegCtrl |= (u32)XEMACPS_NWCTRL_FLUSH_DPRAM_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, RegCtrl); + } - if(RegSR != 0) { - InstancePtr->ErrorHandler(InstancePtr->ErrorRef, - XEMACPS_RECV, RegSR); - } - } + if(RegSR != 0) { + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, + XEMACPS_RECV, RegSR); + } + } /* When XEMACPS_IXR_TXCOMPL_MASK is flagged, XEMACPS_IXR_TXUSED_MASK * will be asserted the same time. * Have to distinguish this bit to handle the real error condition. */ - /* Transmit Q1 error conditions interrupt */ + /* Transmit Q1 error conditions interrupt */ if ((InstancePtr->Version > 2) && - ((RegQ1ISR & XEMACPS_INTQ1SR_TXERR_MASK) != 0x00000000U) && + ((RegQ1ISR & XEMACPS_INTQ1SR_TXERR_MASK) != 0x00000000U) && ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) { - /* Clear Interrupt Q1 status register */ - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_INTQ1_STS_OFFSET, RegQ1ISR); - InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, - RegQ1ISR); - } + /* Clear Interrupt Q1 status register */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_INTQ1_STS_OFFSET, RegQ1ISR); + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, + RegQ1ISR); + } - /* Transmit error conditions interrupt */ + /* Transmit error conditions interrupt */ if (((RegISR & XEMACPS_IXR_TX_ERR_MASK) != 0x00000000U) && (!(RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U)) { - /* Clear TX status register */ - RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, - XEMACPS_TXSR_OFFSET); - XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, - XEMACPS_TXSR_OFFSET, RegSR); - InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, - RegSR); - } + /* Clear TX status register */ + RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET, RegSR); + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, + RegSR); + } } /** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c index 9f0781d531..0ea882c2a6 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c @@ -60,11 +60,11 @@ XEmacPs_Config *XEmacPs_LookupConfig(u16 DeviceId) u32 i; for (i = 0U; i < (u32)XPAR_XEMACPS_NUM_INSTANCES; i++) { - if (XEmacPs_ConfigTable[i].DeviceId == DeviceId) { - CfgPtr = &XEmacPs_ConfigTable[i]; - break; - } - } + if (XEmacPs_ConfigTable[i].DeviceId == DeviceId) { + CfgPtr = &XEmacPs_ConfigTable[i]; + break; + } + } return (XEmacPs_Config *)(CfgPtr); } diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c index f0f43a1299..14716d9244 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c @@ -21,8 +21,8 @@ * 1.00a sv 01/15/10 First Release * 1.01a sv 04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin * XGpioPs_GetMode, XGpioPs_GetModePin as they are not -* relevant to Zynq device. The interrupts are disabled -* for output pins on all banks during initialization. +* relevant to Zynq device. The interrupts are disabled +* for output pins on all banks during initialization. * 2.1 hk 04/29/14 Use Input data register DATA_RO for read. CR# 771667. * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. * 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980. @@ -64,48 +64,48 @@ extern void StubHandler(void *CallBackRef, u32 Bank, u32 Status); * @param InstancePtr is a pointer to the XGpioPs instance. * @param ConfigPtr points to the XGpioPs device configuration structure. * @param EffectiveAddr is the device base address in the virtual memory -* address space. If the address translation is not used then the -* physical address should be passed. -* Unexpected errors may occur if the address mapping is changed -* after this function is invoked. +* address space. If the address translation is not used then the +* physical address should be passed. +* Unexpected errors may occur if the address mapping is changed +* after this function is invoked. * * @return XST_SUCCESS always. * -* @note None. +* @note None. * ******************************************************************************/ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, - u32 EffectiveAddr) + u32 EffectiveAddr) { s32 Status = XST_SUCCESS; u8 i; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(ConfigPtr != NULL); Xil_AssertNonvoid(EffectiveAddr != (u32)0); - /* - * Set some default values for instance data, don't indicate the device - * is ready to use until everything has been initialized successfully. - */ + /* + * Set some default values for instance data, don't indicate the device + * is ready to use until everything has been initialized successfully. + */ InstancePtr->IsReady = 0U; InstancePtr->GpioConfig.BaseAddr = EffectiveAddr; InstancePtr->GpioConfig.DeviceId = ConfigPtr->DeviceId; InstancePtr->Handler = (XGpioPs_Handler)StubHandler; InstancePtr->Platform = XGetPlatform_Info(); - /* Initialize the Bank data based on platform */ + /* Initialize the Bank data based on platform */ if (InstancePtr->Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { - /* - * Max pins in the ZynqMP GPIO device - * 0 - 25, Bank 0 - * 26 - 51, Bank 1 - * 52 - 77, Bank 2 - * 78 - 109, Bank 3 - * 110 - 141, Bank 4 - * 142 - 173, Bank 5 - */ - InstancePtr->MaxPinNum = (u32)174; - InstancePtr->MaxBanks = (u8)6; - } + /* + * Max pins in the ZynqMP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 + */ + InstancePtr->MaxPinNum = (u32)174; + InstancePtr->MaxBanks = (u8)6; + } else if (InstancePtr->Platform == (u32)XPLAT_VERSAL) { if(InstancePtr->PmcGpio == (u32)FALSE) @@ -130,21 +130,21 @@ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, } } else { - /* - * Max pins in the GPIO device - * 0 - 31, Bank 0 - * 32 - 53, Bank 1 - * 54 - 85, Bank 2 - * 86 - 117, Bank 3 - */ - InstancePtr->MaxPinNum = (u32)118; - InstancePtr->MaxBanks = (u8)4; - } + /* + * Max pins in the GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 + */ + InstancePtr->MaxPinNum = (u32)118; + InstancePtr->MaxBanks = (u8)4; + } - /* - * By default, interrupts are not masked in GPIO. Disable - * interrupts for all pins in all the 4 banks. - */ + /* + * By default, interrupts are not masked in GPIO. Disable + * interrupts for all pins in all the 4 banks. + */ for (i=(u8)0U;iMaxBanks;i++) { if (InstancePtr->Platform == XPLAT_VERSAL){ if(InstancePtr->PmcGpio == (u32)FALSE) @@ -171,13 +171,13 @@ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, } else { - XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); } - } + } - /* Indicate the component is now ready to use. */ + /* Indicate the component is now ready to use. */ InstancePtr->IsReady = XIL_COMPONENT_IS_READY; return Status; @@ -190,12 +190,12 @@ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * * @return Current value of the Data register. * -* @note This function is used for reading the state of all the GPIO pins -* of specified bank. +* @note This function is used for reading the state of all the GPIO pins +* of specified bank. * *****************************************************************************/ u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank) @@ -212,8 +212,8 @@ u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank) #endif return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + - XGPIOPS_DATA_RO_OFFSET); + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_RO_OFFSET); } /****************************************************************************/ @@ -223,13 +223,13 @@ u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Pin is the pin number for which the data has to be read. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. -* See xgpiops.h for the mapping of the pin numbers in the banks. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* See xgpiops.h for the mapping of the pin numbers in the banks. * * @return Current value of the Pin (0 or 1). * -* @note This function is used for reading the state of the specified -* GPIO pin. +* @note This function is used for reading the state of the specified +* GPIO pin. * *****************************************************************************/ u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin) @@ -241,15 +241,15 @@ u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin) Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + - XGPIOPS_DATA_RO_OFFSET) >> (u32)PinNumber) & (u32)1; + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_RO_OFFSET) >> (u32)PinNumber) & (u32)1; } @@ -260,13 +260,13 @@ u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * @param Data is the value to be written to the Data register. * * @return None. * -* @note This function is used for writing to all the GPIO pins of -* the bank. The previous state of the pins is not maintained. +* @note This function is used for writing to all the GPIO pins of +* the bank. The previous state of the pins is not maintained. * *****************************************************************************/ void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data) @@ -283,8 +283,8 @@ void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data) #endif XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + - XGPIOPS_DATA_OFFSET, Data); + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_OFFSET, Data); } /****************************************************************************/ @@ -294,14 +294,14 @@ void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Pin is the pin number to which the Data is to be written. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * @param Data is the data to be written to the specified pin (0 or 1). * * @return None. * -* @note This function does a masked write to the specified pin of -* the specified GPIO bank. The previous state of other pins -* is maintained. +* @note This function does a masked write to the specified pin of +* the specified GPIO bank. The previous state of other pins +* is maintained. * *****************************************************************************/ void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data) @@ -316,7 +316,7 @@ void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data) Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else @@ -324,22 +324,22 @@ void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data) #endif if (PinNumber > 15U) { - /* There are only 16 data bits in bit maskable register. */ - PinNumber -= (u8)16; - RegOffset = XGPIOPS_DATA_MSW_OFFSET; - } else { - RegOffset = XGPIOPS_DATA_LSW_OFFSET; - } + /* There are only 16 data bits in bit maskable register. */ + PinNumber -= (u8)16; + RegOffset = XGPIOPS_DATA_MSW_OFFSET; + } else { + RegOffset = XGPIOPS_DATA_LSW_OFFSET; + } - /* - * Get the 32 bit value to be written to the Mask/Data register where - * the upper 16 bits is the mask and lower 16 bits is the data. - */ + /* + * Get the 32 bit value to be written to the Mask/Data register where + * the upper 16 bits is the mask and lower 16 bits is the data. + */ DataVar &= (u32)0x01; Value = ~((u32)1 << (PinNumber + 16U)) & ((DataVar << PinNumber) | 0xFFFF0000U); XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) + - RegOffset, Value); + ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) + + RegOffset, Value); } @@ -352,16 +352,16 @@ void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * @param Direction is the 32 bit mask of the Pin direction to be set for -* all the pins in the Bank. Bits with 0 are set to Input mode, -* bits with 1 are set to Output Mode. +* all the pins in the Bank. Bits with 0 are set to Input mode, +* bits with 1 are set to Output Mode. * * @return None. * -* @note This function is used for setting the direction of all the pins -* in the specified bank. The previous state of the pins is -* not maintained. +* @note This function is used for setting the direction of all the pins +* in the specified bank. The previous state of the pins is +* not maintained. * *****************************************************************************/ void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction) @@ -378,8 +378,8 @@ void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction) #endif XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_DIRM_OFFSET, Direction); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET, Direction); } /****************************************************************************/ @@ -389,9 +389,9 @@ void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Pin is the pin number to which the Data is to be written. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * @param Direction is the direction to be set for the specified pin. -* Valid values are 0 for Input Direction, 1 for Output Direction. +* Valid values are 0 for Input Direction, 1 for Output Direction. * * @return None. * @@ -407,25 +407,25 @@ void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction) Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); Xil_AssertVoid(Direction <= (u32)1); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif DirModeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_DIRM_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET); if (Direction!=(u32)0) { /* Output Direction */ - DirModeReg |= ((u32)1 << (u32)PinNumber); - } else { /* Input Direction */ - DirModeReg &= ~ ((u32)1 << (u32)PinNumber); - } + DirModeReg |= ((u32)1 << (u32)PinNumber); + } else { /* Input Direction */ + DirModeReg &= ~ ((u32)1 << (u32)PinNumber); + } XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_DIRM_OFFSET, DirModeReg); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET, DirModeReg); } /****************************************************************************/ @@ -435,12 +435,12 @@ void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * * @return Returns a 32 bit mask of the Direction register. Bits with 0 are -* in Input mode, bits with 1 are in Output Mode. +* in Input mode, bits with 1 are in Output Mode. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank) @@ -457,8 +457,8 @@ u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank) #endif return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_DIRM_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET); } /****************************************************************************/ @@ -468,14 +468,14 @@ u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Pin is the pin number for which the Direction is to be -* retrieved. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* retrieved. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * * @return Direction of the specified pin. -* - 0 for Input Direction -* - 1 for Output Direction +* - 0 for Input Direction +* - 1 for Output Direction * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin) @@ -487,7 +487,7 @@ u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin) Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else @@ -495,8 +495,8 @@ u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin) #endif return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_DIRM_OFFSET) >> (u32)PinNumber) & (u32)1; + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET) >> (u32)PinNumber) & (u32)1; } /****************************************************************************/ @@ -506,16 +506,16 @@ u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * @param OpEnable is the 32 bit mask of the Output Enables to be set for -* all the pins in the Bank. The Output Enable of bits with 0 are -* disabled, the Output Enable of bits with 1 are enabled. +* all the pins in the Bank. The Output Enable of bits with 0 are +* disabled, the Output Enable of bits with 1 are enabled. * * @return None. * -* @note This function is used for setting the Output Enables of all the -* pins in the specified bank. The previous state of the Output -* Enables is not maintained. +* @note This function is used for setting the Output Enables of all the +* pins in the specified bank. The previous state of the Output +* Enables is not maintained. * *****************************************************************************/ void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable) @@ -532,8 +532,8 @@ void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable) #endif XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_OUTEN_OFFSET, OpEnable); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET, OpEnable); } /****************************************************************************/ @@ -543,15 +543,15 @@ void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Pin is the pin number to which the Data is to be written. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * @param OpEnable specifies whether the Output Enable for the specified -* pin should be enabled. -* Valid values are 0 for Disabling Output Enable, -* 1 for Enabling Output Enable. +* pin should be enabled. +* Valid values are 0 for Disabling Output Enable, +* 1 for Enabling Output Enable. * * @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable) @@ -565,7 +565,7 @@ void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnabl Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); Xil_AssertVoid(OpEnable <= (u32)1); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else @@ -573,18 +573,18 @@ void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnabl #endif OpEnableReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_OUTEN_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET); if (OpEnable != (u32)0) { /* Enable Output Enable */ - OpEnableReg |= ((u32)1 << (u32)PinNumber); - } else { /* Disable Output Enable */ - OpEnableReg &= ~ ((u32)1 << (u32)PinNumber); - } + OpEnableReg |= ((u32)1 << (u32)PinNumber); + } else { /* Disable Output Enable */ + OpEnableReg &= ~ ((u32)1 << (u32)PinNumber); + } XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_OUTEN_OFFSET, OpEnableReg); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET, OpEnableReg); } /****************************************************************************/ /** @@ -593,13 +593,13 @@ void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnabl * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * * @return Returns a a 32 bit mask of the Output Enable register. -* Bits with 0 are in Disabled state, bits with 1 are in -* Enabled State. +* Bits with 0 are in Disabled state, bits with 1 are in +* Enabled State. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank) @@ -616,8 +616,8 @@ u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank) #endif return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_OUTEN_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET); } /****************************************************************************/ @@ -627,14 +627,14 @@ u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Pin is the pin number for which the Output Enable status is to -* be retrieved. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* be retrieved. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * * @return Output Enable of the specified pin. -* - 0 if Output Enable is disabled for this pin -* - 1 if Output Enable is enabled for this pin +* - 0 if Output Enable is disabled for this pin +* - 1 if Output Enable is enabled for this pin * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin) @@ -646,7 +646,7 @@ u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin) Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else @@ -654,8 +654,8 @@ u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin) #endif return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_OUTEN_OFFSET) >> (u32)PinNumber) & (u32)1; + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET) >> (u32)PinNumber) & (u32)1; } /****************************************************************************/ @@ -666,12 +666,12 @@ u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin) * * @param PinNumber is the Pin number in the GPIO device. * @param BankNumber returns the Bank in which this GPIO pin is present. -* Valid values are 0 to XGPIOPS_MAX_BANKS - 1. +* Valid values are 0 to XGPIOPS_MAX_BANKS - 1. * @param PinNumberInBank returns the Pin Number within the Bank. * * @return None. * -* @note None. +* @note None. * *****************************************************************************/ #ifdef versal @@ -687,26 +687,26 @@ void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank) u32 Platform = XGetPlatform_Info(); if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { - /* - * This structure defines the mapping of the pin numbers to the banks when - * the driver APIs are used for working on the individual pins. - */ + /* + * This structure defines the mapping of the pin numbers to the banks when + * the driver APIs are used for working on the individual pins. + */ - XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ - XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */ - XGpioPsPinTable[2] = (u32)77; /* 52 - 77, Bank 2 */ - XGpioPsPinTable[3] = (u32)109; /* 78 - 109, Bank 3 */ - XGpioPsPinTable[4] = (u32)141; /* 110 - 141, Bank 4 */ - XGpioPsPinTable[5] = (u32)173; /* 142 - 173 Bank 5 */ + XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ + XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */ + XGpioPsPinTable[2] = (u32)77; /* 52 - 77, Bank 2 */ + XGpioPsPinTable[3] = (u32)109; /* 78 - 109, Bank 3 */ + XGpioPsPinTable[4] = (u32)141; /* 110 - 141, Bank 4 */ + XGpioPsPinTable[5] = (u32)173; /* 142 - 173 Bank 5 */ - *BankNumber = 0U; - while (*BankNumber < XGPIOPS_SIX) { - if (PinNumber <= XGpioPsPinTable[*BankNumber]) { - break; - } - (*BankNumber)++; - } - } + *BankNumber = 0U; + while (*BankNumber < XGPIOPS_SIX) { + if (PinNumber <= XGpioPsPinTable[*BankNumber]) { + break; + } + (*BankNumber)++; + } + } #ifdef versal else if(Platform == XPLAT_VERSAL) { @@ -760,22 +760,22 @@ void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank) } #endif else { - XGpioPsPinTable[0] = (u32)31; /* 0 - 31, Bank 0 */ - XGpioPsPinTable[1] = (u32)53; /* 32 - 53, Bank 1 */ - XGpioPsPinTable[2] = (u32)85; /* 54 - 85, Bank 2 */ - XGpioPsPinTable[3] = (u32)117; /* 86 - 117 Bank 3 */ + XGpioPsPinTable[0] = (u32)31; /* 0 - 31, Bank 0 */ + XGpioPsPinTable[1] = (u32)53; /* 32 - 53, Bank 1 */ + XGpioPsPinTable[2] = (u32)85; /* 54 - 85, Bank 2 */ + XGpioPsPinTable[3] = (u32)117; /* 86 - 117 Bank 3 */ - *BankNumber = 0U; - while (*BankNumber < XGPIOPS_FOUR) { - if (PinNumber <= XGpioPsPinTable[*BankNumber]) { - break; - } - (*BankNumber)++; - } - } + *BankNumber = 0U; + while (*BankNumber < XGPIOPS_FOUR) { + if (PinNumber <= XGpioPsPinTable[*BankNumber]) { + break; + } + (*BankNumber)++; + } + } if (*BankNumber == (u8)0) { - *PinNumberInBank = PinNumber; - } + *PinNumberInBank = PinNumber; + } #ifdef versal else if(Platform == XPLAT_VERSAL) @@ -801,8 +801,8 @@ void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank) #endif else { - *PinNumberInBank = (u8)((u32)PinNumber % - (XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1)); + *PinNumberInBank = (u8)((u32)PinNumber % + (XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1)); } } /** @} */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h index 4f5374297c..e6df7c8b60 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h @@ -15,10 +15,10 @@ * Controller. * * The GPIO Controller supports the following features: -* - 4 banks -* - Masked writes (There are no masked reads) -* - Bypass mode -* - Configurable Interrupts (Level/Edge) +* - 4 banks +* - Masked writes (There are no masked reads) +* - Bypass mode +* - Configurable Interrupts (Level/Edge) * * This driver is intended to be RTOS and processor independent. Any needs for * dynamic memory management, threads or thread mutual exclusion, virtual @@ -63,12 +63,12 @@ * 1.00a sv 01/15/10 First Release * 1.01a sv 04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin * XGpioPs_GetMode, XGpioPs_GetModePin as they are not -* relevant to Zynq device.The interrupts are disabled -* for output pins on all banks during initialization. +* relevant to Zynq device.The interrupts are disabled +* for output pins on all banks during initialization. * 1.02a hk 08/22/13 Added low level reset API * 2.1 hk 04/29/14 Use Input data register DATA_RO for read. CR# 771667. -* 2.2 sk 10/13/14 Used Pin number in Bank instead of pin number -* passed to APIs. CR# 822636 +* 2.2 sk 10/13/14 Used Pin number in Bank instead of pin number +* passed to APIs. CR# 822636 * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. * 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980. * ms 03/17/17 Added readme.txt file in examples folder for doxygen @@ -96,8 +96,8 @@ * * ******************************************************************************/ -#ifndef XGPIOPS_H /* prevent circular inclusions */ -#define XGPIOPS_H /* by using protection macros */ +#ifndef XGPIOPS_H /* prevent circular inclusions */ +#define XGPIOPS_H /* by using protection macros */ #ifdef __cplusplus extern "C" { @@ -123,37 +123,37 @@ extern "C" { #define XGPIOPS_IRQ_TYPE_LEVEL_LOW 0x04U /**< Interrupt on low level */ /*@}*/ -#define XGPIOPS_BANK_MAX_PINS (u32)32 /**< Max pins in a GPIO bank */ -#define XGPIOPS_BANK0 0x00U /**< GPIO Bank 0 */ -#define XGPIOPS_BANK1 0x01U /**< GPIO Bank 1 */ -#define XGPIOPS_BANK2 0x02U /**< GPIO Bank 2 */ -#define XGPIOPS_BANK3 0x03U /**< GPIO Bank 3 */ +#define XGPIOPS_BANK_MAX_PINS (u32)32 /**< Max pins in a GPIO bank */ +#define XGPIOPS_BANK0 0x00U /**< GPIO Bank 0 */ +#define XGPIOPS_BANK1 0x01U /**< GPIO Bank 1 */ +#define XGPIOPS_BANK2 0x02U /**< GPIO Bank 2 */ +#define XGPIOPS_BANK3 0x03U /**< GPIO Bank 3 */ #ifdef XPAR_PSU_GPIO_0_BASEADDR -#define XGPIOPS_BANK4 0x04U /**< GPIO Bank 4 */ -#define XGPIOPS_BANK5 0x05U /**< GPIO Bank 5 */ +#define XGPIOPS_BANK4 0x04U /**< GPIO Bank 4 */ +#define XGPIOPS_BANK5 0x05U /**< GPIO Bank 5 */ #endif -#define XGPIOPS_MAX_BANKS_ZYNQMP 0x06U /**< Max banks in a - * Zynq Ultrascale+ MP GPIO device - */ -#define XGPIOPS_MAX_BANKS 0x04U /**< Max banks in a Zynq GPIO device */ +#define XGPIOPS_MAX_BANKS_ZYNQMP 0x06U /**< Max banks in a + * Zynq Ultrascale+ MP GPIO device + */ +#define XGPIOPS_MAX_BANKS 0x04U /**< Max banks in a Zynq GPIO device */ -#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP (u32)174 /**< Max pins in the - * Zynq Ultrascale+ MP GPIO device - * 0 - 25, Bank 0 - * 26 - 51, Bank 1 - * 52 - 77, Bank 2 - * 78 - 109, Bank 3 - * 110 - 141, Bank 4 - * 142 - 173, Bank 5 - */ -#define XGPIOPS_DEVICE_MAX_PIN_NUM (u32)118 /**< Max pins in the Zynq GPIO device - * 0 - 31, Bank 0 - * 32 - 53, Bank 1 - * 54 - 85, Bank 2 - * 86 - 117, Bank 3 - */ +#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP (u32)174 /**< Max pins in the + * Zynq Ultrascale+ MP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 + */ +#define XGPIOPS_DEVICE_MAX_PIN_NUM (u32)118 /**< Max pins in the Zynq GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 + */ /**************************** Type Definitions *******************************/ @@ -166,10 +166,10 @@ extern "C" { * processing should be performed. * * @param CallBackRef is a callback reference passed in by the upper layer - * when setting the callback functions for a GPIO bank. It is - * passed back to the upper layer when the callback is invoked. Its - * type is not important to the driver component, so it is a void - * pointer. + * when setting the callback functions for a GPIO bank. It is + * passed back to the upper layer when the callback is invoked. Its + * type is not important to the driver component, so it is a void + * pointer. * @param Bank is the bank for which the interrupt status has changed. * @param Status is the Interrupt status of the GPIO bank. * @@ -180,8 +180,8 @@ typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status); * This typedef contains configuration information for a device. */ typedef struct { - u16 DeviceId; /**< Unique ID of device */ - u32 BaseAddr; /**< Register base address */ + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Register base address */ } XGpioPs_Config; /** @@ -190,13 +190,13 @@ typedef struct { * to a variable of this type is then passed to the driver API functions. */ typedef struct { - XGpioPs_Config GpioConfig; /**< Device configuration */ - u32 IsReady; /**< Device is initialized and ready */ - XGpioPs_Handler Handler; /**< Status handlers for all banks */ - void *CallBackRef; /**< Callback ref for bank handlers */ - u32 Platform; /**< Platform data */ - u32 MaxPinNum; /**< Max pins in the GPIO device */ - u8 MaxBanks; /**< Max banks in a GPIO device */ + XGpioPs_Config GpioConfig; /**< Device configuration */ + u32 IsReady; /**< Device is initialized and ready */ + XGpioPs_Handler Handler; /**< Status handlers for all banks */ + void *CallBackRef; /**< Callback ref for bank handlers */ + u32 Platform; /**< Platform data */ + u32 MaxPinNum; /**< Max pins in the GPIO device */ + u8 MaxBanks; /**< Max banks in a GPIO device */ u32 PmcGpio; /**< Flag for accessing PS GPIO for versal*/ } XGpioPs; @@ -206,7 +206,7 @@ typedef struct { /* Functions in xgpiops.c */ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, - u32 EffectiveAddr); + u32 EffectiveAddr); /* Bank APIs in xgpiops.c */ u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank); @@ -240,11 +240,11 @@ u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank); u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank); void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, - u32 IntrPolarity, u32 IntrOnAny); + u32 IntrPolarity, u32 IntrOnAny); void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, - u32 *IntrPolarity, u32 *IntrOnAny); + u32 *IntrPolarity, u32 *IntrOnAny); void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, - XGpioPs_Handler FuncPointer); + XGpioPs_Handler FuncPointer); void XGpioPs_IntrHandler(const XGpioPs *InstancePtr); /* Pin APIs in xgpiops_intr.c */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c index 71c225084d..4ed9338caf 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c @@ -22,10 +22,10 @@ XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES] = { - { - XPAR_PSU_GPIO_0_DEVICE_ID, - XPAR_PSU_GPIO_0_BASEADDR - } + { + XPAR_PSU_GPIO_0_DEVICE_ID, + XPAR_PSU_GPIO_0_BASEADDR + } }; diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c index 38fee0848b..9a871ef2c5 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c @@ -56,7 +56,7 @@ * * @return None * -* @note None. +* @note None. * ******************************************************************************/ void XGpioPs_ResetHw(u32 BaseAddress) diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h index ba23e13882..86b458e87f 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h @@ -28,8 +28,8 @@ * * ******************************************************************************/ -#ifndef XGPIOPS_HW_H /* prevent circular inclusions */ -#define XGPIOPS_HW_H /* by using protection macros */ +#ifndef XGPIOPS_HW_H /* prevent circular inclusions */ +#define XGPIOPS_HW_H /* by using protection macros */ #ifdef __cplusplus extern "C" { @@ -48,17 +48,17 @@ extern "C" { */ #define XGPIOPS_DATA_LSW_OFFSET 0x00000000U /* Mask and Data Register LSW, WO */ #define XGPIOPS_DATA_MSW_OFFSET 0x00000004U /* Mask and Data Register MSW, WO */ -#define XGPIOPS_DATA_OFFSET 0x00000040U /* Data Register, RW */ -#define XGPIOPS_DATA_RO_OFFSET 0x00000060U /* Data Register - Input, RO */ -#define XGPIOPS_DIRM_OFFSET 0x00000204U /* Direction Mode Register, RW */ -#define XGPIOPS_OUTEN_OFFSET 0x00000208U /* Output Enable Register, RW */ -#define XGPIOPS_INTMASK_OFFSET 0x0000020CU /* Interrupt Mask Register, RO */ -#define XGPIOPS_INTEN_OFFSET 0x00000210U /* Interrupt Enable Register, WO */ -#define XGPIOPS_INTDIS_OFFSET 0x00000214U /* Interrupt Disable Register, WO*/ -#define XGPIOPS_INTSTS_OFFSET 0x00000218U /* Interrupt Status Register, RO */ -#define XGPIOPS_INTTYPE_OFFSET 0x0000021CU /* Interrupt Type Register, RW */ -#define XGPIOPS_INTPOL_OFFSET 0x00000220U /* Interrupt Polarity Register, RW */ -#define XGPIOPS_INTANY_OFFSET 0x00000224U /* Interrupt On Any Register, RW */ +#define XGPIOPS_DATA_OFFSET 0x00000040U /* Data Register, RW */ +#define XGPIOPS_DATA_RO_OFFSET 0x00000060U /* Data Register - Input, RO */ +#define XGPIOPS_DIRM_OFFSET 0x00000204U /* Direction Mode Register, RW */ +#define XGPIOPS_OUTEN_OFFSET 0x00000208U /* Output Enable Register, RW */ +#define XGPIOPS_INTMASK_OFFSET 0x0000020CU /* Interrupt Mask Register, RO */ +#define XGPIOPS_INTEN_OFFSET 0x00000210U /* Interrupt Enable Register, WO */ +#define XGPIOPS_INTDIS_OFFSET 0x00000214U /* Interrupt Disable Register, WO*/ +#define XGPIOPS_INTSTS_OFFSET 0x00000218U /* Interrupt Status Register, RO */ +#define XGPIOPS_INTTYPE_OFFSET 0x0000021CU /* Interrupt Type Register, RW */ +#define XGPIOPS_INTPOL_OFFSET 0x00000220U /* Interrupt Polarity Register, RW */ +#define XGPIOPS_INTANY_OFFSET 0x00000224U /* Interrupt On Any Register, RW */ /* @} */ /** @name Register offsets for each Bank. @@ -70,7 +70,7 @@ extern "C" { /* @} */ /* For backwards compatibility */ -#define XGPIOPS_BYPM_MASK_OFFSET (u32)0x40 +#define XGPIOPS_BYPM_MASK_OFFSET (u32)0x40 /** @name Interrupt type reset values for each bank * @{ @@ -111,11 +111,11 @@ extern "C" { * * @return The 32-bit value of the register * -* @note None. +* @note None. * *****************************************************************************/ -#define XGpioPs_ReadReg(BaseAddr, RegOffset) \ - Xil_In32((BaseAddr) + (u32)(RegOffset)) +#define XGpioPs_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (u32)(RegOffset)) /****************************************************************************/ /** @@ -128,11 +128,11 @@ extern "C" { * * @return None. * -* @note None. +* @note None. * *****************************************************************************/ -#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data) \ - Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) +#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) /************************** Function Prototypes ******************************/ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_intr.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_intr.c index 43c8435c33..536c0c9a02 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_intr.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_intr.c @@ -18,8 +18,8 @@ * Ver Who Date Changes * ----- ---- -------- ----------------------------------------------- * 1.00a sv 01/18/10 First Release -* 2.2 sk 10/13/14 Used Pin number in Bank instead of pin number -* passed to API's. CR# 822636 +* 2.2 sk 10/13/14 Used Pin number in Bank instead of pin number +* passed to API's. CR# 822636 * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance. * 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980. * 3.1 aru 07/13/18 Ressolved doxygen reported warnings. CR# 1006331. @@ -63,14 +63,14 @@ void StubHandler(const void *CallBackRef, u32 Bank, u32 Status); * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * @param Mask is the bit mask of the pins for which interrupts are to -* be enabled. Bit positions of 1 will be enabled. Bit positions -* of 0 will keep the previous setting. +* be enabled. Bit positions of 1 will be enabled. Bit positions +* of 0 will keep the previous setting. * * @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) @@ -87,8 +87,8 @@ void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) #endif XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTEN_OFFSET, Mask); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET, Mask); } /****************************************************************************/ @@ -98,11 +98,11 @@ void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Pin is the pin number for which the interrupt is to be enabled. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * * @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin) @@ -115,7 +115,7 @@ void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin) Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else @@ -124,8 +124,8 @@ void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin) IntrReg = ((u32)1 << (u32)PinNumber); XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTEN_OFFSET, IntrReg); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET, IntrReg); } /****************************************************************************/ @@ -136,14 +136,14 @@ void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * @param Mask is the bit mask of the pins for which interrupts are -* to be disabled. Bit positions of 1 will be disabled. Bit -* positions of 0 will keep the previous setting. +* to be disabled. Bit positions of 1 will be disabled. Bit +* positions of 0 will keep the previous setting. * * @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) @@ -160,8 +160,8 @@ void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) #endif XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTDIS_OFFSET, Mask); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, Mask); } /****************************************************************************/ @@ -171,11 +171,11 @@ void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Pin is the pin number for which the interrupt is to be disabled. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * * @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin) @@ -188,7 +188,7 @@ void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin) Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else @@ -197,8 +197,8 @@ void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin) IntrReg = ((u32)1 << (u32)PinNumber); XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTDIS_OFFSET, IntrReg); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, IntrReg); } /****************************************************************************/ @@ -208,14 +208,14 @@ void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * * @return Enabled interrupt(s) in a 32-bit format. Bit positions with 1 -* indicate that the interrupt for that pin is enabled, bit -* positions with 0 indicate that the interrupt for that pin is -* disabled. +* indicate that the interrupt for that pin is enabled, bit +* positions with 0 indicate that the interrupt for that pin is +* disabled. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank) @@ -234,8 +234,8 @@ u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank) #endif IntrMask = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTMASK_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET); return (~IntrMask); } @@ -246,14 +246,14 @@ u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Pin is the pin number for which the interrupt enable status -* is to be known. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* is to be known. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * * @return -* - TRUE if the interrupt is enabled. -* - FALSE if the interrupt is disabled. +* - TRUE if the interrupt is enabled. +* - FALSE if the interrupt is disabled. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin) @@ -266,7 +266,7 @@ u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin) Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else @@ -274,8 +274,8 @@ u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin) #endif IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTMASK_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET); return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? FALSE : TRUE); } @@ -287,11 +287,11 @@ u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * * @return The value read from Interrupt Status Register. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank) @@ -308,8 +308,8 @@ u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank) #endif return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTSTS_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); } /****************************************************************************/ @@ -319,14 +319,14 @@ u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Pin is the pin number for which the interrupt enable status -* is to be known. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* is to be known. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * * @return -* - TRUE if the interrupt has occurred. -* - FALSE if the interrupt has not occurred. +* - TRUE if the interrupt has occurred. +* - FALSE if the interrupt has not occurred. * -* @note None. +* @note None. * *****************************************************************************/ u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin) @@ -339,7 +339,7 @@ u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin) Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else @@ -347,8 +347,8 @@ u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin) #endif IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTSTS_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? TRUE : FALSE); } @@ -362,12 +362,12 @@ u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * @param Mask is the mask of the interrupts to be cleared. Bit positions -* of 1 will be cleared. Bit positions of 0 will not change the -* previous interrupt status. +* of 1 will be cleared. Bit positions of 0 will not change the +* previous interrupt status. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) @@ -383,10 +383,10 @@ void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) } #endif - /* Clear the currently pending interrupts. */ + /* Clear the currently pending interrupts. */ XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTSTS_OFFSET, Mask); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET, Mask); } /****************************************************************************/ @@ -397,9 +397,9 @@ void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param Pin is the pin number for which the interrupt status is to be -* cleared. Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* cleared. Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin) @@ -412,22 +412,22 @@ void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin) Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); #endif - /* Clear the specified pending interrupts. */ + /* Clear the specified pending interrupts. */ IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTSTS_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); IntrReg &= ((u32)1 << PinNumber); XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTSTS_OFFSET, IntrReg); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET, IntrReg); } /****************************************************************************/ @@ -438,28 +438,28 @@ void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin) * * @param InstancePtr is a pointer to an XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * @param IntrType is the 32 bit mask of the interrupt type. -* 0 means Level Sensitive and 1 means Edge Sensitive. +* 0 means Level Sensitive and 1 means Edge Sensitive. * @param IntrPolarity is the 32 bit mask of the interrupt polarity. -* 0 means Active Low or Falling Edge and 1 means Active High or -* Rising Edge. +* 0 means Active Low or Falling Edge and 1 means Active High or +* Rising Edge. * @param IntrOnAny is the 32 bit mask of the interrupt trigger for -* edge triggered interrupts. 0 means trigger on single edge using -* the configured interrupt polarity and 1 means trigger on both -* edges. +* edge triggered interrupts. 0 means trigger on single edge using +* the configured interrupt polarity and 1 means trigger on both +* edges. * * @return None. * -* @note This function is used for setting the interrupt related -* properties of all the pins in the specified bank. The previous -* state of the pins is not maintained. -* To change the Interrupt properties of a single GPIO pin, use the -* function XGpioPs_SetPinIntrType(). +* @note This function is used for setting the interrupt related +* properties of all the pins in the specified bank. The previous +* state of the pins is not maintained. +* To change the Interrupt properties of a single GPIO pin, use the +* function XGpioPs_SetPinIntrType(). * *****************************************************************************/ void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, - u32 IntrPolarity, u32 IntrOnAny) + u32 IntrPolarity, u32 IntrOnAny) { Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); @@ -473,16 +473,16 @@ void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, #endif XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTTYPE_OFFSET, IntrType); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET, IntrType); XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTPOL_OFFSET, IntrPolarity); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET, IntrPolarity); XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTANY_OFFSET, IntrOnAny); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET, IntrOnAny); } /****************************************************************************/ @@ -493,24 +493,24 @@ void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, * * @param InstancePtr is a pointer to an XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. -* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. +* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * @param IntrType returns the 32 bit mask of the interrupt type. -* 0 means Level Sensitive and 1 means Edge Sensitive. +* 0 means Level Sensitive and 1 means Edge Sensitive. * @param IntrPolarity returns the 32 bit mask of the interrupt -* polarity. 0 means Active Low or Falling Edge and 1 means -* Active High or Rising Edge. +* polarity. 0 means Active Low or Falling Edge and 1 means +* Active High or Rising Edge. * @param IntrOnAny returns the 32 bit mask of the interrupt trigger for -* edge triggered interrupts. 0 means trigger on single edge using -* the configured interrupt polarity and 1 means trigger on both -* edges. +* edge triggered interrupts. 0 means trigger on single edge using +* the configured interrupt polarity and 1 means trigger on both +* edges. * * @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, - u32 *IntrPolarity, u32 *IntrOnAny) + u32 *IntrPolarity, u32 *IntrOnAny) { Xil_AssertVoid(InstancePtr != NULL); @@ -524,17 +524,17 @@ void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, } #endif - *IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTTYPE_OFFSET); + *IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET); - *IntrPolarity = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTPOL_OFFSET); + *IntrPolarity = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET); - *IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTANY_OFFSET); + *IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET); } /****************************************************************************/ @@ -544,13 +544,13 @@ void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, * * @param InstancePtr is a pointer to an XGpioPs instance. * @param Pin is the pin number whose IRQ type is to be set. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * @param IrqType is the IRQ type for GPIO Pin. Use XGPIOPS_IRQ_TYPE_* -* defined in xgpiops.h to specify the IRQ type. +* defined in xgpiops.h to specify the IRQ type. * * @return None. * -* @note None. +* @note None. * *****************************************************************************/ void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType) @@ -566,7 +566,7 @@ void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType) Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); Xil_AssertVoid(IrqType <= XGPIOPS_IRQ_TYPE_LEVEL_LOW); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else @@ -574,56 +574,56 @@ void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType) #endif IntrTypeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTTYPE_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET); IntrPolReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTPOL_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET); IntrOnAnyReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTANY_OFFSET); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET); switch (IrqType) { - case XGPIOPS_IRQ_TYPE_EDGE_RISING: - IntrTypeReg |= ((u32)1 << (u32)PinNumber); - IntrPolReg |= ((u32)1 << (u32)PinNumber); - IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); - break; - case XGPIOPS_IRQ_TYPE_EDGE_FALLING: - IntrTypeReg |= ((u32)1 << (u32)PinNumber); - IntrPolReg &= ~((u32)1 << (u32)PinNumber); - IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); - break; - case XGPIOPS_IRQ_TYPE_EDGE_BOTH: - IntrTypeReg |= ((u32)1 << (u32)PinNumber); - IntrOnAnyReg |= ((u32)1 << (u32)PinNumber); - break; - case XGPIOPS_IRQ_TYPE_LEVEL_HIGH: - IntrTypeReg &= ~((u32)1 << (u32)PinNumber); - IntrPolReg |= ((u32)1 << (u32)PinNumber); - break; - case XGPIOPS_IRQ_TYPE_LEVEL_LOW: - IntrTypeReg &= ~((u32)1 << (u32)PinNumber); - IntrPolReg &= ~((u32)1 << (u32)PinNumber); - break; - default: - /**< Default statement is added for MISRA C compliance. */ - break; - } + case XGPIOPS_IRQ_TYPE_EDGE_RISING: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrPolReg |= ((u32)1 << (u32)PinNumber); + IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_EDGE_FALLING: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrPolReg &= ~((u32)1 << (u32)PinNumber); + IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_EDGE_BOTH: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrOnAnyReg |= ((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_LEVEL_HIGH: + IntrTypeReg &= ~((u32)1 << (u32)PinNumber); + IntrPolReg |= ((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_LEVEL_LOW: + IntrTypeReg &= ~((u32)1 << (u32)PinNumber); + IntrPolReg &= ~((u32)1 << (u32)PinNumber); + break; + default: + /**< Default statement is added for MISRA C compliance. */ + break; + } XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTTYPE_OFFSET, IntrTypeReg); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET, IntrTypeReg); XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTPOL_OFFSET, IntrPolReg); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET, IntrPolReg); XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTANY_OFFSET, IntrOnAnyReg); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET, IntrOnAnyReg); } /****************************************************************************/ @@ -633,12 +633,12 @@ void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType) * * @param InstancePtr is a pointer to an XGpioPs instance. * @param Pin is the pin number whose IRQ type is to be obtained. -* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. +* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP. * * @return None. * -* @note Use XGPIOPS_IRQ_TYPE_* defined in xgpiops.h for the IRQ type -* returned by this function. +* @note Use XGPIOPS_IRQ_TYPE_* defined in xgpiops.h for the IRQ type +* returned by this function. * *****************************************************************************/ u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin) @@ -654,7 +654,7 @@ u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin) Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); - /* Get the Bank number and Pin number within the bank. */ + /* Get the Bank number and Pin number within the bank. */ #ifdef versal XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); #else @@ -662,39 +662,39 @@ u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin) #endif IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTTYPE_OFFSET) & ((u32)1 << PinNumber); + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET) & ((u32)1 << PinNumber); if (IntrType == ((u32)1 << PinNumber)) { - IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTANY_OFFSET) & ((u32)1 << PinNumber); + IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET) & ((u32)1 << PinNumber); - IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); + IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); - if (IntrOnAny == ((u32)1 << PinNumber)) { - IrqType = XGPIOPS_IRQ_TYPE_EDGE_BOTH; - } else if (IntrPol == ((u32)1 << PinNumber)) { - IrqType = XGPIOPS_IRQ_TYPE_EDGE_RISING; - } else { - IrqType = XGPIOPS_IRQ_TYPE_EDGE_FALLING; - } - } else { + if (IntrOnAny == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_BOTH; + } else if (IntrPol == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_RISING; + } else { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_FALLING; + } + } else { - IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, - ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + - XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); + IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); - if (IntrPol == ((u32)1 << PinNumber)) { - IrqType = XGPIOPS_IRQ_TYPE_LEVEL_HIGH; - } else { - IrqType = XGPIOPS_IRQ_TYPE_LEVEL_LOW; - } - } + if (IntrPol == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_LEVEL_HIGH; + } else { + IrqType = XGPIOPS_IRQ_TYPE_LEVEL_LOW; + } + } return IrqType; } @@ -707,19 +707,19 @@ u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin) * * @param InstancePtr is a pointer to the XGpioPs instance. * @param CallBackRef is the upper layer callback reference passed back -* when the callback function is invoked. +* when the callback function is invoked. * @param FuncPointer is the pointer to the callback function. * * * @return None. * -* @note The handler is called within interrupt context, so it should do -* its work quickly and queue potentially time-consuming work to a -* task-level thread. +* @note The handler is called within interrupt context, so it should do +* its work quickly and queue potentially time-consuming work to a +* task-level thread. * ******************************************************************************/ void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, - XGpioPs_Handler FuncPointer) + XGpioPs_Handler FuncPointer) { Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(FuncPointer != NULL); @@ -742,8 +742,8 @@ void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, * * @return None. * -* @note This function does not save and restore the processor context -* such that the user must provide this processing. +* @note This function does not save and restore the processor context +* such that the user must provide this processing. * ******************************************************************************/ void XGpioPs_IntrHandler(const XGpioPs *InstancePtr) @@ -757,26 +757,26 @@ void XGpioPs_IntrHandler(const XGpioPs *InstancePtr) for (Bank = 0U; Bank < InstancePtr->MaxBanks; Bank++) { #ifdef versal - if(InstancePtr->PmcGpio == TRUE) { - if(Bank == XGPIOPS_TWO) { - continue; - } - } else { - if((Bank == XGPIOPS_ONE) || (Bank == XGPIOPS_TWO)) { - continue; - } - } + if(InstancePtr->PmcGpio == TRUE) { + if(Bank == XGPIOPS_TWO) { + continue; + } + } else { + if((Bank == XGPIOPS_ONE) || (Bank == XGPIOPS_TWO)) { + continue; + } + } #endif - IntrStatus = XGpioPs_IntrGetStatus(InstancePtr, Bank); - IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr,Bank); - if ((IntrStatus & IntrEnabled) != (u32)0) { - XGpioPs_IntrClear(InstancePtr, Bank, - (IntrStatus & IntrEnabled)); - InstancePtr->Handler(InstancePtr-> - CallBackRef, Bank, - (IntrStatus & IntrEnabled)); - } - } + IntrStatus = XGpioPs_IntrGetStatus(InstancePtr, Bank); + IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr,Bank); + if ((IntrStatus & IntrEnabled) != (u32)0) { + XGpioPs_IntrClear(InstancePtr, Bank, + (IntrStatus & IntrEnabled)); + InstancePtr->Handler(InstancePtr-> + CallBackRef, Bank, + (IntrStatus & IntrEnabled)); + } + } } /*****************************************************************************/ @@ -791,14 +791,14 @@ void XGpioPs_IntrHandler(const XGpioPs *InstancePtr) * * @return None. * -* @note None. +* @note None. * ******************************************************************************/ void StubHandler(const void *CallBackRef, u32 Bank, u32 Status) { - (void) CallBackRef; - (void) Bank; - (void) Status; + (void) CallBackRef; + (void) Bank; + (void) Status; Xil_AssertVoidAlways(); } diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_selftest.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_selftest.c index 6ba43424e3..4ed3453a39 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_selftest.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_selftest.c @@ -55,8 +55,8 @@ * @param InstancePtr is a pointer to the XGpioPs instance. * * @return -* - XST_SUCCESS if the self-test passed. -* - XST_FAILURE otherwise. +* - XST_SUCCESS if the self-test passed. +* - XST_FAILURE otherwise. * * ******************************************************************************/ @@ -75,35 +75,35 @@ s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr) Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - /* Disable the Interrupts for Bank 0 . */ + /* Disable the Interrupts for Bank 0 . */ IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr, XGPIOPS_BANK0); XGpioPs_IntrDisable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); - /* - * Get the Current Interrupt properties for Bank 0. - * Set them to a known value, read it back and compare. - */ + /* + * Get the Current Interrupt properties for Bank 0. + * Set them to a known value, read it back and compare. + */ XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &CurrentIntrType, - &CurrentIntrPolarity, &CurrentIntrOnAny); + &CurrentIntrPolarity, &CurrentIntrOnAny); XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, IntrTestValue, - IntrTestValue, IntrTestValue); + IntrTestValue, IntrTestValue); XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &IntrType, - &IntrPolarity, &IntrOnAny); + &IntrPolarity, &IntrOnAny); if ((IntrType != IntrTestValue) && (IntrPolarity != IntrTestValue) && - (IntrOnAny != IntrTestValue)) { + (IntrOnAny != IntrTestValue)) { - Status = XST_FAILURE; - } + Status = XST_FAILURE; + } - /* - * Restore the contents of all the interrupt registers modified in this - * test. - */ + /* + * Restore the contents of all the interrupt registers modified in this + * test. + */ XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, CurrentIntrType, - CurrentIntrPolarity, CurrentIntrOnAny); + CurrentIntrPolarity, CurrentIntrOnAny); XGpioPs_IntrEnable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_sinit.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_sinit.c index 713e11f53f..c10c294821 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_sinit.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_sinit.c @@ -13,7 +13,7 @@ * This file contains the implementation of the XGpioPs driver's static * initialization functionality. * -* @note None. +* @note None. * *
 *
@@ -53,9 +53,9 @@ extern XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES];
 * @param    DeviceId is the unique device ID of the device being looked up.
 *
 * @return    A pointer to the configuration table entry corresponding to the
-*	    given device ID, or NULL if no match is found.
+*        given device ID, or NULL if no match is found.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId)
@@ -64,11 +64,11 @@ XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId)
     u32 Index;
 
     for (Index = 0U; Index < (u32)XPAR_XGPIOPS_NUM_INSTANCES; Index++) {
-	    if (XGpioPs_ConfigTable[Index].DeviceId == DeviceId) {
-		    CfgPtr = &XGpioPs_ConfigTable[Index];
-		    break;
-		}
-	}
+        if (XGpioPs_ConfigTable[Index].DeviceId == DeviceId) {
+            CfgPtr = &XGpioPs_ConfigTable[Index];
+            break;
+        }
+    }
 
     return (XGpioPs_Config *)CfgPtr;
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c
index f1237ca86c..926553c0e6 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c
@@ -24,14 +24,14 @@
 * 2.2   hk     07/28/14 Make changes to enable use of data cache.
 * 2.3   sk     09/23/14 Send command for relative card address
 *                       when re-initialization is done.CR# 819614.
-*					    Use XSdPs_Change_ClkFreq API whenever changing
-*					    clock.CR# 816586.
-* 2.4    sk	   12/04/14 Added support for micro SD without
-* 					    WP/CD. CR# 810655.
-*					    Checked for DAT Inhibit mask instead of CMD
-* 					    Inhibit mask in Cmd Transfer API.
-*					    Added Support for SD Card v1.0
-* 2.5     sg	   07/09/15 Added SD 3.0 features
+*                        Use XSdPs_Change_ClkFreq API whenever changing
+*                        clock.CR# 816586.
+* 2.4    sk       12/04/14 Added support for micro SD without
+*                         WP/CD. CR# 810655.
+*                        Checked for DAT Inhibit mask instead of CMD
+*                         Inhibit mask in Cmd Transfer API.
+*                        Added Support for SD Card v1.0
+* 2.5     sg       07/09/15 Added SD 3.0 features
 *       kvn    07/15/15 Modified the code according to MISRAC-2012.
 * 2.6   sk     10/12/15 Added support for SD card v1.0 CR# 840601.
 * 2.7   sk     11/24/15 Considered the slot type befoe checking CD/WP pins.
@@ -104,32 +104,32 @@
 *
 * @param    InstancePtr is a pointer to the XSdPs instance.
 * @param    ConfigPtr is a reference to a structure containing information
-*	    about a specific SD device. This function initializes an
-*	    InstancePtr object for a specific device specified by the
-*	    contents of Config.
+*        about a specific SD device. This function initializes an
+*        InstancePtr object for a specific device specified by the
+*        contents of Config.
 * @param    EffectiveAddr is the device base address in the virtual memory
-*	    address space. The caller is responsible for keeping the address
-*	    mapping from EffectiveAddr to the device physical base address
-*	    unchanged once this function is invoked. Unexpected errors may
-*	    occur if the address mapping changes after this function is
-*	    called. If address translation is not used, use
-*	    ConfigPtr->Config.BaseAddress for this device.
+*        address space. The caller is responsible for keeping the address
+*        mapping from EffectiveAddr to the device physical base address
+*        unchanged once this function is invoked. Unexpected errors may
+*        occur if the address mapping changes after this function is
+*        called. If address translation is not used, use
+*        ConfigPtr->Config.BaseAddress for this device.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_DEVICE_IS_STARTED if the device is already started.
-*	    It must be stopped to re-initialize.
+*        - XST_SUCCESS if successful.
+*        - XST_DEVICE_IS_STARTED if the device is already started.
+*        It must be stopped to re-initialize.
 *
-* @note	    This function initializes the host controller.
-*	    Initial clock of 400KHz is set.
-*	    Voltage of 3.3V is selected as that is supported by host.
-*	    Interrupts status is enabled and signal disabled by default.
-*	    Default data direction is card to host and
-*	    32 bit ADMA2 is selected. Default Block size is 512 bytes.
+* @note        This function initializes the host controller.
+*        Initial clock of 400KHz is set.
+*        Voltage of 3.3V is selected as that is supported by host.
+*        Interrupts status is enabled and signal disabled by default.
+*        Default data direction is card to host and
+*        32 bit ADMA2 is selected. Default Block size is 512 bytes.
 *
 ******************************************************************************/
 s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
-			    u32 EffectiveAddr)
+                u32 EffectiveAddr)
 {
     s32 Status;
 
@@ -140,13 +140,13 @@ s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
     InstancePtr->Config.RefClk = ConfigPtr->RefClk;
     Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
-	/* If this API is getting called twice, return value accordingly */
+    /* If this API is getting called twice, return value accordingly */
     if (InstancePtr->IsReady == XIL_COMPONENT_IS_READY) {
-	    Status = (s32)XST_DEVICE_IS_STARTED;
-	    goto RETURN_PATH ;
-	}
+        Status = (s32)XST_DEVICE_IS_STARTED;
+        goto RETURN_PATH ;
+    }
 
-	/* Set some default values. */
+    /* Set some default values. */
     InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
     InstancePtr->Config.BaseAddress = EffectiveAddr;
     InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
@@ -163,26 +163,26 @@ s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
     InstancePtr->Dma64BitAddr = 0U;
     InstancePtr->SlcrBaseAddr = XPS_SYS_CTRL_BASEADDR;
 
-	/* Host Controller version is read. */
+    /* Host Controller version is read. */
     InstancePtr->HC_Version =
-			(u8)(XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK);
+            (u8)(XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+            XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK);
 
-	/*
-	 * Read capabilities register and update it in Instance pointer.
-	 * It is sufficient to read this once on power on.
-	 */
+    /*
+     * Read capabilities register and update it in Instance pointer.
+     * It is sufficient to read this once on power on.
+     */
     InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-					    XSDPS_CAPS_OFFSET);
+                        XSDPS_CAPS_OFFSET);
 
-	/* Reset the SD bus lines */
+    /* Reset the SD bus lines */
     Status = XSdPs_ResetConfig(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
-	/* Configure the SD Host Controller */
+    /* Configure the SD Host Controller */
     XSdPs_HostConfig(InstancePtr);
 
     InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
@@ -205,12 +205,12 @@ RETURN_PATH:
 * @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because
-* 		    a) SD is already initialized
-* 		    b) There is no card inserted
-* 		    c) One of the steps (commands) in the
-*			   initialization cycle failed
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because
+*             a) SD is already initialized
+*             b) There is no card inserted
+*             c) One of the steps (commands) in the
+*               initialization cycle failed
 *
 *
 ******************************************************************************/
@@ -221,7 +221,7 @@ s32 XSdPs_CardInitialize(XSdPs *InstancePtr)
     Xil_AssertNonvoid(InstancePtr != NULL);
     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	/* Default settings */
+    /* Default settings */
     InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
     InstancePtr->CardType = XSDPS_CARD_SD;
     InstancePtr->Switch1v8 = 0U;
@@ -231,34 +231,34 @@ s32 XSdPs_CardInitialize(XSdPs *InstancePtr)
     Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
-	/* Change the clock frequency to 400 KHz */
+    /* Change the clock frequency to 400 KHz */
     Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
-	/* Identify the Card whether it is SD, MMC or eMMC */
+    /* Identify the Card whether it is SD, MMC or eMMC */
     Status = XSdPs_IdentifyCard(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Initialize the identified card */
+    /* Initialize the identified card */
     if (InstancePtr->CardType == XSDPS_CARD_SD) {
-	    Status = XSdPs_SdCardInitialize(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	} else {
-	    Status = XSdPs_MmcCardInitialize(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        Status = XSdPs_SdCardInitialize(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else {
+        Status = XSdPs_MmcCardInitialize(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
@@ -274,14 +274,14 @@ RETURN_PATH:
 *
 * @param    InstancePtr is a pointer to the instance to be worked on.
 * @param    Arg is the address passed by the user that is to be sent as
-* 	    argument along with the command.
+*         argument along with the command.
 * @param    BlkCnt - Block count passed by the user.
 * @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because another transfer
-* 	    is in progress or command or data inhibit is set
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because another transfer
+*         is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
@@ -295,19 +295,19 @@ s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
     Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
-	/* Setup the Read Transfer */
+    /* Setup the Read Transfer */
     Status = XSdPs_SetupTransfer(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Read from the card */
+    /* Read from the card */
     Status = XSdPs_Read(InstancePtr, Arg, BlkCnt, Buff);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
@@ -323,14 +323,14 @@ RETURN_PATH:
 *
 * @param    InstancePtr is a pointer to the instance to be worked on.
 * @param    Arg is the address passed by the user that is to be sent as
-* 	    argument along with the command.
+*         argument along with the command.
 * @param    BlkCnt - Block count passed by the user.
 * @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because another transfer
-* 	    is in progress or command or data inhibit is set
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because another transfer
+*         is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
@@ -344,19 +344,19 @@ s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
     Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
-	/* Setup the Write Transfer */
+    /* Setup the Write Transfer */
     Status = XSdPs_SetupTransfer(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Write to the card */
+    /* Write to the card */
     Status = XSdPs_Write(InstancePtr, Arg, BlkCnt, Buff);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
@@ -376,7 +376,7 @@ RETURN_PATH:
 *
 * @return    None
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Idle(XSdPs *InstancePtr)
@@ -390,24 +390,24 @@ s32 XSdPs_Idle(XSdPs *InstancePtr)
     Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
-	/* Check if the bus is idle */
+    /* Check if the bus is idle */
     Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK
-										| XSDPS_PSR_INHIBIT_DAT_MASK
-										| XSDPS_PSR_DAT_ACTIVE_MASK);
+                                        | XSDPS_PSR_INHIBIT_DAT_MASK
+                                        | XSDPS_PSR_DAT_ACTIVE_MASK);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
-	/* Disable the Bus Power */
+    /* Disable the Bus Power */
     XSdPs_DisableBusPower(InstancePtr);
 
-	/* Reset Command and Data Lines */
+    /* Reset Command and Data Lines */
     Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
     Status = XST_SUCCESS;
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h
index 3fe8bb64e8..8c05c589a5 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h
@@ -83,14 +83,14 @@
 * 2.2   hk     07/28/14 Make changes to enable use of data cache.
 * 2.3   sk     09/23/14 Send command for relative card address
 *                       when re-initialization is done.CR# 819614.
-*					    Use XSdPs_Change_ClkFreq API whenever changing
-*					    clock.CR# 816586.
-* 2.4    sk	   12/04/14 Added support for micro SD without
-* 					    WP/CD. CR# 810655.
-*					    Checked for DAT Inhibit mask instead of CMD
-* 					    Inhibit mask in Cmd Transfer API.
-*					    Added Support for SD Card v1.0
-* 2.5     sg	    07/09/15 Added SD 3.0 features
+*                        Use XSdPs_Change_ClkFreq API whenever changing
+*                        clock.CR# 816586.
+* 2.4    sk       12/04/14 Added support for micro SD without
+*                         WP/CD. CR# 810655.
+*                        Checked for DAT Inhibit mask instead of CMD
+*                         Inhibit mask in Cmd Transfer API.
+*                        Added Support for SD Card v1.0
+* 2.5     sg        07/09/15 Added SD 3.0 features
 *       kvn     07/15/15 Modified the code according to MISRAC-2012.
 * 2.6   sk     10/12/15 Added support for SD card v1.0 CR# 840601.
 * 2.7   sk     11/24/15 Considered the slot type befoe checking CD/WP pins.
@@ -155,9 +155,9 @@ extern "C" {
 
 /************************** Constant Definitions *****************************/
 
-#define XSDPS_CT_ERROR    0x2L	/**< Command timeout flag */
-#define MAX_TUNING_COUNT    40U		/**< Maximum Tuning count */
-#define MAX_TIMEOUT	    0x1FFFFFFFU		/**< Maximum Timeout */
+#define XSDPS_CT_ERROR    0x2L    /**< Command timeout flag */
+#define MAX_TUNING_COUNT    40U        /**< Maximum Tuning count */
+#define MAX_TIMEOUT        0x1FFFFFFFU        /**< Maximum Timeout */
 #define XSDPS_CMD8_VOL_PATTERN    0x1AAU
 #define XSDPS_RESPOCR_READY    0x80000000U
 #define XSDPS_ACMD41_HCS    0x40000000U
@@ -171,21 +171,21 @@ extern "C" {
 #define UHS_SDR104_SUPPORT    0x8U
 #define UHS_DDR50_SUPPORT    0x10U
 #define WIDTH_4_BIT_SUPPORT    0x4U
-#define SD_CLK_25_MHZ	    25000000U
-#define SD_CLK_19_MHZ	    19000000U
-#define SD_CLK_26_MHZ	    26000000U
+#define SD_CLK_25_MHZ        25000000U
+#define SD_CLK_19_MHZ        19000000U
+#define SD_CLK_26_MHZ        26000000U
 #define EXT_CSD_DEVICE_TYPE_BYTE    196U
-#define EXT_CSD_SEC_COUNT_BYTE1	    212U
-#define EXT_CSD_SEC_COUNT_BYTE2	    213U
-#define EXT_CSD_SEC_COUNT_BYTE3	    214U
-#define EXT_CSD_SEC_COUNT_BYTE4	    215U
-#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED		    0x2U
+#define EXT_CSD_SEC_COUNT_BYTE1        212U
+#define EXT_CSD_SEC_COUNT_BYTE2        213U
+#define EXT_CSD_SEC_COUNT_BYTE3        214U
+#define EXT_CSD_SEC_COUNT_BYTE4        215U
+#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED            0x2U
 #define EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED    0x4U
 #define EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED    0x8U
-#define EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200	    0x10U
-#define EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200	    0x20U
-#define CSD_SPEC_VER_3	    0x3U
-#define SCR_SPEC_VER_3	    0x80U
+#define EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200        0x10U
+#define EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200        0x20U
+#define CSD_SPEC_VER_3        0x3U
+#define SCR_SPEC_VER_3        0x80U
 #define ADDRESS_BEYOND_32BIT    0x100000000U
 
 /**************************** Type Definitions *******************************/
@@ -196,25 +196,25 @@ typedef void (*XSdPs_ConfigTap) (u32 Bank, u32 DeviceId, u32 CardType);
  * This typedef contains configuration information for the device.
  */
 typedef struct {
-    u16 DeviceId;			/**< Unique ID  of device */
-    u32 BaseAddress;		/**< Base address of the device */
-    u32 InputClockHz;		/**< Input clock frequency */
-    u32 CardDetect;			/**< Card Detect */
-    u32 WriteProtect;			/**< Write Protect */
-    u32 BusWidth;			/**< Bus Width */
-    u32 BankNumber;			/**< MIO Bank selection for SD */
-    u32 HasEMIO;			/**< If SD is connected to EMIO */
-    u8 IsCacheCoherent; 		/**< If SD is Cache Coherent or not */
+    u16 DeviceId;            /**< Unique ID  of device */
+    u32 BaseAddress;        /**< Base address of the device */
+    u32 InputClockHz;        /**< Input clock frequency */
+    u32 CardDetect;            /**< Card Detect */
+    u32 WriteProtect;            /**< Write Protect */
+    u32 BusWidth;            /**< Bus Width */
+    u32 BankNumber;            /**< MIO Bank selection for SD */
+    u32 HasEMIO;            /**< If SD is connected to EMIO */
+    u8 IsCacheCoherent;         /**< If SD is Cache Coherent or not */
 #if defined  (XCLOCKING)
-    u32 RefClk;			/**< Input clocks */
+    u32 RefClk;            /**< Input clocks */
 #endif
 } XSdPs_Config;
 
 /* ADMA2 32-Bit descriptor table */
 typedef struct {
-    u16 Attribute;		/**< Attributes of descriptor */
-    u16 Length;		/**< Length of current dma transfer */
-    u32 Address;		/**< Address of current dma transfer */
+    u16 Attribute;        /**< Attributes of descriptor */
+    u16 Length;        /**< Length of current dma transfer */
+    u32 Address;        /**< Address of current dma transfer */
 #ifdef __ICCARM__
 #pragma data_alignment = 32
 } XSdPs_Adma2Descriptor32;
@@ -224,9 +224,9 @@ typedef struct {
 
 /* ADMA2 64-Bit descriptor table */
 typedef struct {
-    u16 Attribute;		/**< Attributes of descriptor */
-    u16 Length;		/**< Length of current dma transfer */
-    u64 Address;		/**< Address of current dma transfer */
+    u16 Attribute;        /**< Attributes of descriptor */
+    u16 Length;        /**< Length of current dma transfer */
+    u64 Address;        /**< Address of current dma transfer */
 #ifdef __ICCARM__
 #pragma data_alignment = 32
 } XSdPs_Adma2Descriptor64;
@@ -240,28 +240,28 @@ typedef struct {
  * to a variable of this type is then passed to the driver API functions.
  */
 typedef struct {
-    XSdPs_Config Config;	/**< Configuration structure */
-    u32 IsReady;		/**< Device is initialized and ready */
-    u32 Host_Caps;		/**< Capabilities of host controller */
-    u32 Host_CapsExt;	/**< Extended Capabilities */
-    u32 HCS;		/**< High capacity support in card */
-    u8  CardType;		/**< Type of card - SD/MMC/eMMC */
-    u8  Card_Version;	/**< Card version */
-    u8  HC_Version;		/**< Host controller version */
-    u8  BusWidth;		/**< Current operating bus width */
-    u32 BusSpeed;		/**< Current operating bus speed */
-    u8  Switch1v8;		/**< 1.8V Switch support */
-    u32 CardID[4];		/**< Card ID Register */
-    u32 RelCardAddr;	/**< Relative Card Address */
-    u32 CardSpecData[4];	/**< Card Specific Data Register */
-    u32 SectorCount;		/**< Sector Count */
-    u32 SdCardConfig;	/**< Sd Card Configuration Register */
-    u32 Mode;			/**< Bus Speed Mode */
-    u32 OTapDelay;		/**< Output Tap Delay */
-    u32 ITapDelay;		/**< Input Tap Delay */
-    u64 Dma64BitAddr;	/**< 64 Bit DMA Address */
-    u16 TransferMode;	/**< Transfer Mode */
-    u32 SlcrBaseAddr;	/**< SLCR base address*/
+    XSdPs_Config Config;    /**< Configuration structure */
+    u32 IsReady;        /**< Device is initialized and ready */
+    u32 Host_Caps;        /**< Capabilities of host controller */
+    u32 Host_CapsExt;    /**< Extended Capabilities */
+    u32 HCS;        /**< High capacity support in card */
+    u8  CardType;        /**< Type of card - SD/MMC/eMMC */
+    u8  Card_Version;    /**< Card version */
+    u8  HC_Version;        /**< Host controller version */
+    u8  BusWidth;        /**< Current operating bus width */
+    u32 BusSpeed;        /**< Current operating bus speed */
+    u8  Switch1v8;        /**< 1.8V Switch support */
+    u32 CardID[4];        /**< Card ID Register */
+    u32 RelCardAddr;    /**< Relative Card Address */
+    u32 CardSpecData[4];    /**< Card Specific Data Register */
+    u32 SectorCount;        /**< Sector Count */
+    u32 SdCardConfig;    /**< Sd Card Configuration Register */
+    u32 Mode;            /**< Bus Speed Mode */
+    u32 OTapDelay;        /**< Output Tap Delay */
+    u32 ITapDelay;        /**< Input Tap Delay */
+    u64 Dma64BitAddr;    /**< 64 Bit DMA Address */
+    u16 TransferMode;    /**< Transfer Mode */
+    u32 SlcrBaseAddr;    /**< SLCR base address*/
 } XSdPs;
 
 /***************** Macros (Inline Functions) Definitions *********************/
@@ -269,7 +269,7 @@ typedef struct {
 /************************** Function Prototypes ******************************/
 XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId);
 s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
-			    u32 EffectiveAddr);
+                u32 EffectiveAddr);
 s32 XSdPs_CardInitialize(XSdPs *InstancePtr);
 s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff);
 s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff);
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c
index d6430a9a00..828d2f9b81 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c
@@ -43,14 +43,14 @@
 *
 * @param    InstancePtr is a pointer to the instance to be worked on.
 * @param    Arg is the address passed by the user that is to be sent as
-* 	    argument along with the command.
+*         argument along with the command.
 * @param    BlkCnt - Block count passed by the user.
 * @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because another transfer
-* 	    is in progress or command or data inhibit is set
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because another transfer
+*         is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_Read(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
@@ -63,31 +63,31 @@ s32 XSdPs_Read(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
     XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, Buff);
 
     if (BlkCnt == 1U) {
-		/* Send single block read command */
-	    Status = XSdPs_CmdTransfer(InstancePtr, CMD17, Arg, BlkCnt);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	} else {
-		/* Send multiple blocks read command */
-	    Status = XSdPs_CmdTransfer(InstancePtr, CMD18, Arg, BlkCnt);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        /* Send single block read command */
+        Status = XSdPs_CmdTransfer(InstancePtr, CMD17, Arg, BlkCnt);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else {
+        /* Send multiple blocks read command */
+        Status = XSdPs_CmdTransfer(InstancePtr, CMD18, Arg, BlkCnt);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
-	/* Check for transfer done */
+    /* Check for transfer done */
     Status = XSdps_CheckTransferDone(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     if (InstancePtr->Config.IsCacheCoherent == 0U) {
-	    Xil_DCacheInvalidateRange((INTPTR)Buff,
-				(INTPTR)BlkCnt * BlkSize);
-	}
+        Xil_DCacheInvalidateRange((INTPTR)Buff,
+                (INTPTR)BlkCnt * BlkSize);
+    }
 
     Status = XST_SUCCESS;
 
@@ -102,14 +102,14 @@ RETURN_PATH:
 *
 * @param    InstancePtr is a pointer to the instance to be worked on.
 * @param    Arg is the address passed by the user that is to be sent as
-* 	    argument along with the command.
+*         argument along with the command.
 * @param    BlkCnt - Block count passed by the user.
 * @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because another transfer
-* 	    is in progress or command or data inhibit is set
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because another transfer
+*         is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_Write(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
@@ -122,31 +122,31 @@ s32 XSdPs_Write(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
     XSdPs_SetupWriteDma(InstancePtr, BlkCnt, BlkSize, Buff);
 
     if (BlkCnt == 1U) {
-		/* Send single block write command */
-	    Status = XSdPs_CmdTransfer(InstancePtr, CMD24, Arg, BlkCnt);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	} else {
-		/* Send multiple blocks write command */
-	    Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        /* Send single block write command */
+        Status = XSdPs_CmdTransfer(InstancePtr, CMD24, Arg, BlkCnt);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else {
+        /* Send multiple blocks write command */
+        Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
-	/* Check for transfer done */
+    /* Check for transfer done */
     Status = XSdps_CheckTransferDone(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     Status = XST_SUCCESS;
 
     RETURN_PATH:
-	    return Status;
+        return Status;
 }
 /*****************************************************************************/
 /**
@@ -163,42 +163,42 @@ s32 XSdPs_IdentifyCard(XSdPs *InstancePtr)
     s32 Status;
 
     if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
-			((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
-			== XSDPS_CAPS_EMB_SLOT)) {
-	    InstancePtr->CardType = XSDPS_CHIP_EMMC;
-	    Status = XST_SUCCESS;
-	    goto RETURN_PATH;
-	}
+            ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
+            == XSDPS_CAPS_EMB_SLOT)) {
+        InstancePtr->CardType = XSDPS_CHIP_EMMC;
+        Status = XST_SUCCESS;
+        goto RETURN_PATH;
+    }
 
-	/* 74 CLK delay after card is powered up, before the first command. */
+    /* 74 CLK delay after card is powered up, before the first command. */
     usleep(XSDPS_INIT_DELAY);
 
-	/* CMD0 no response expected */
+    /* CMD0 no response expected */
     Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0U, 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Host High Capacity support & High voltage window */
+    /* Host High Capacity support & High voltage window */
     Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
-		    XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);
+            XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);
     if (Status != XST_SUCCESS) {
-	    InstancePtr->CardType = XSDPS_CARD_SD;
-	} else {
-	    InstancePtr->CardType = XSDPS_CARD_MMC;
-	}
+        InstancePtr->CardType = XSDPS_CARD_SD;
+    } else {
+        InstancePtr->CardType = XSDPS_CARD_MMC;
+    }
 
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
+            XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
+            XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
 
     Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_CMD_LINE_MASK);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
     Status = XST_SUCCESS;
 
@@ -215,21 +215,21 @@ RETURN_PATH:
 * @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because
-* 		    a) SD is already initialized
-* 		    b) There is no card inserted
-* 		    c) One of the steps (commands) in the
-			   initialization cycle failed
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because
+*             a) SD is already initialized
+*             b) There is no card inserted
+*             c) One of the steps (commands) in the
+               initialization cycle failed
 *
-* @note	    This function initializes the SD card by following its
-*	    initialization and identification state diagram.
-*	    CMD0 is sent to reset card.
-*	    CMD8 and ACDM41 are sent to identify voltage and
-*	    high capacity support
-*	    CMD2 and CMD3 are sent to obtain Card ID and
-*	    Relative card address respectively.
-*	    CMD9 is sent to read the card specific data.
+* @note        This function initializes the SD card by following its
+*        initialization and identification state diagram.
+*        CMD0 is sent to reset card.
+*        CMD8 and ACDM41 are sent to identify voltage and
+*        high capacity support
+*        CMD2 and CMD3 are sent to obtain Card ID and
+*        Relative card address respectively.
+*        CMD9 is sent to read the card specific data.
 *
 ******************************************************************************/
 s32 XSdPs_SdCardInitialize(XSdPs *InstancePtr)
@@ -242,15 +242,15 @@ s32 XSdPs_SdCardInitialize(XSdPs *InstancePtr)
 
     Status = XSdPs_SdCardEnum(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XSdPs_SdModeInit(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XST_SUCCESS;
 
@@ -268,19 +268,19 @@ RETURN_PATH:
 * @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because
-* 		    a) MMC is already initialized
-* 		    b) There is no card inserted
-* 		    c) One of the steps (commands) in the initialization
-*			   cycle failed
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because
+*             a) MMC is already initialized
+*             b) There is no card inserted
+*             c) One of the steps (commands) in the initialization
+*               cycle failed
 * @note     This function initializes the SD card by following its
-*	    initialization and identification state diagram.
-*	    CMD0 is sent to reset card.
-*	    CMD1 sent to identify voltage and high capacity support
-*	    CMD2 and CMD3 are sent to obtain Card ID and
-*	    Relative card address respectively.
-*	    CMD9 is sent to read the card specific data.
+*        initialization and identification state diagram.
+*        CMD0 is sent to reset card.
+*        CMD1 sent to identify voltage and high capacity support
+*        CMD2 and CMD3 are sent to obtain Card ID and
+*        Relative card address respectively.
+*        CMD9 is sent to read the card specific data.
 *
 ******************************************************************************/
 s32 XSdPs_MmcCardInitialize(XSdPs *InstancePtr)
@@ -289,37 +289,37 @@ s32 XSdPs_MmcCardInitialize(XSdPs *InstancePtr)
 
     Status = XSdPs_MmcCardEnum(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     if (((InstancePtr->CardType == XSDPS_CARD_MMC) &&
-				(InstancePtr->Card_Version > CSD_SPEC_VER_3)) &&
-				(InstancePtr->HC_Version == XSDPS_HC_SPEC_V2)) {
-	    Status = XSdPs_MmcModeInit(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	} else if (InstancePtr->CardType == XSDPS_CHIP_EMMC) {
-	    Status = XSdPs_EmmcModeInit(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	} else {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
+                (InstancePtr->Card_Version > CSD_SPEC_VER_3)) &&
+                (InstancePtr->HC_Version == XSDPS_HC_SPEC_V2)) {
+        Status = XSdPs_MmcModeInit(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else if (InstancePtr->CardType == XSDPS_CHIP_EMMC) {
+        Status = XSdPs_EmmcModeInit(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
 
-	}
+    }
 
     if (InstancePtr->Mode != XSDPS_DDR52_MODE) {
-	    Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     Status = XST_SUCCESS;
 
@@ -343,24 +343,24 @@ s32 XSdPs_CheckCardDetect(XSdPs *InstancePtr)
     s32 Status;
 
     if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
-				((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
-				== XSDPS_CAPS_EMB_SLOT)) {
-	    Status = XST_SUCCESS;
-	    goto RETURN_PATH;
-	}
+                ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
+                == XSDPS_CAPS_EMB_SLOT)) {
+        Status = XST_SUCCESS;
+        goto RETURN_PATH;
+    }
 
     if(InstancePtr->Config.CardDetect != 0U) {
-		/*
-		 * Check the present state register to make sure
-		 * card is inserted and detected by host controller
-		 */
-	    PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-			    XSDPS_PRES_STATE_OFFSET);
-	    if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U)	{
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        /*
+         * Check the present state register to make sure
+         * card is inserted and detected by host controller
+         */
+        PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XSDPS_PRES_STATE_OFFSET);
+        if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U)    {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     Status = XST_SUCCESS;
 
@@ -382,11 +382,11 @@ s32 XSdPs_CardReset(XSdPs *InstancePtr)
 {
     s32 Status;
 
-	/* CMD0 no response expected */
+    /* CMD0 no response expected */
     Status = XSdPs_CmdTransfer(InstancePtr, (u32)CMD0, 0U, 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     return Status;
 }
@@ -406,32 +406,32 @@ s32 XSdPs_CardIfCond(XSdPs *InstancePtr)
     u32 RespOCR;
     s32 Status;
 
-	/*
-	 * CMD8; response expected
-	 * 0x1AA - Supply Voltage 2.7 - 3.6V and AA is pattern
-	 */
+    /*
+     * CMD8; response expected
+     * 0x1AA - Supply Voltage 2.7 - 3.6V and AA is pattern
+     */
     Status = XSdPs_CmdTransfer(InstancePtr, CMD8,
-		    XSDPS_CMD8_VOL_PATTERN, 0U);
+            XSDPS_CMD8_VOL_PATTERN, 0U);
     if ((Status != XST_SUCCESS) && (Status != XSDPS_CT_ERROR)) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     if (Status == XSDPS_CT_ERROR) {
-	    Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_CMD_LINE_MASK);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH ;
-		}
-	}
+        Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_CMD_LINE_MASK);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH ;
+        }
+    }
 
     RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-					    XSDPS_RESP0_OFFSET);
+                        XSDPS_RESP0_OFFSET);
     if (RespOCR != XSDPS_CMD8_VOL_PATTERN) {
-	    InstancePtr->Card_Version = XSDPS_SD_VER_1_0;
-	} else {
-	    InstancePtr->Card_Version = XSDPS_SD_VER_2_0;
-	}
+        InstancePtr->Card_Version = XSDPS_SD_VER_1_0;
+    } else {
+        InstancePtr->Card_Version = XSDPS_SD_VER_2_0;
+    }
 
     Status = XST_SUCCESS;
 
@@ -455,52 +455,52 @@ s32 XSdPs_CardOpCond(XSdPs *InstancePtr)
     s32 Status;
     u32 Arg;
 
-	/* Send ACMD41 while card is still busy with power up */
+    /* Send ACMD41 while card is still busy with power up */
     do {
-	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		    Status = XSdPs_CmdTransfer(InstancePtr, CMD55, 0U, 0U);
-		    if (Status != XST_SUCCESS) {
-			    Status = XST_FAILURE;
-			    goto RETURN_PATH;
-			}
+        if (InstancePtr->CardType == XSDPS_CARD_SD) {
+            Status = XSdPs_CmdTransfer(InstancePtr, CMD55, 0U, 0U);
+            if (Status != XST_SUCCESS) {
+                Status = XST_FAILURE;
+                goto RETURN_PATH;
+            }
 
-		    Arg = XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3 | (0x1FFU << 15U);
-		    if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
-				(InstancePtr->Config.BusWidth == XSDPS_WIDTH_8)) {
-			    Arg |= XSDPS_OCR_S18;
-			}
+            Arg = XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3 | (0x1FFU << 15U);
+            if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
+                (InstancePtr->Config.BusWidth == XSDPS_WIDTH_8)) {
+                Arg |= XSDPS_OCR_S18;
+            }
 
-			/* 0x40300000 - Host High Capacity support & 3.3V window */
-		    Status = XSdPs_CmdTransfer(InstancePtr, ACMD41,
-				    Arg, 0U);
-		} else {
-			/* Send CMD1 while card is still busy with power up */
-		    Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
-				    XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);
-		}
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
+            /* 0x40300000 - Host High Capacity support & 3.3V window */
+            Status = XSdPs_CmdTransfer(InstancePtr, ACMD41,
+                    Arg, 0U);
+        } else {
+            /* Send CMD1 while card is still busy with power up */
+            Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
+                    XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);
+        }
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
 
-		/* Response with card capacity */
-	    RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-			    XSDPS_RESP0_OFFSET);
-	} while ((RespOCR & XSDPS_RESPOCR_READY) == 0U);
+        /* Response with card capacity */
+        RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XSDPS_RESP0_OFFSET);
+    } while ((RespOCR & XSDPS_RESPOCR_READY) == 0U);
 
-	/* Update HCS support flag based on card capacity response */
+    /* Update HCS support flag based on card capacity response */
     if ((RespOCR & XSDPS_ACMD41_HCS) != 0U) {
-	    InstancePtr->HCS = 1U;
-	}
+        InstancePtr->HCS = 1U;
+    }
 
     if ((RespOCR & XSDPS_OCR_S18) != 0U) {
-	    InstancePtr->Switch1v8 = 1U;
-	    Status = XSdPs_Switch_Voltage(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        InstancePtr->Switch1v8 = 1U;
+        Status = XSdPs_Switch_Voltage(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     Status = XST_SUCCESS;
 
@@ -522,51 +522,51 @@ s32 XSdPs_GetCardId(XSdPs *InstancePtr)
 {
     s32 Status;
 
-	/* CMD2 for Card ID */
+    /* CMD2 for Card ID */
     Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0U, 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     InstancePtr->CardID[0] =
-		    XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_RESP0_OFFSET);
+            XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+            XSDPS_RESP0_OFFSET);
     InstancePtr->CardID[1] =
-		    XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_RESP1_OFFSET);
+            XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+            XSDPS_RESP1_OFFSET);
     InstancePtr->CardID[2] =
-		    XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_RESP2_OFFSET);
+            XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+            XSDPS_RESP2_OFFSET);
     InstancePtr->CardID[3] =
-		    XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_RESP3_OFFSET);
+            XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+            XSDPS_RESP3_OFFSET);
 
     if(InstancePtr->CardType == XSDPS_CARD_SD) {
-	    do {
-		    Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0U, 0U);
-		    if (Status != XST_SUCCESS) {
-			    Status = XST_FAILURE;
-			    goto RETURN_PATH;
-			}
+        do {
+            Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0U, 0U);
+            if (Status != XST_SUCCESS) {
+                Status = XST_FAILURE;
+                goto RETURN_PATH;
+            }
 
-			/*
-			 * Relative card address is stored as the upper 16 bits
-			 * This is to avoid shifting when sending commands
-			 */
-		    InstancePtr->RelCardAddr =
-				    XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-					    XSDPS_RESP0_OFFSET) & 0xFFFF0000U;
-		} while (InstancePtr->RelCardAddr == 0U);
-	} else {
-		/* Set relative card address */
-	    InstancePtr->RelCardAddr = 0x12340000U;
-	    Status = XSdPs_CmdTransfer(InstancePtr, CMD3, (InstancePtr->RelCardAddr), 0U);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+            /*
+             * Relative card address is stored as the upper 16 bits
+             * This is to avoid shifting when sending commands
+             */
+            InstancePtr->RelCardAddr =
+                    XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                        XSDPS_RESP0_OFFSET) & 0xFFFF0000U;
+        } while (InstancePtr->RelCardAddr == 0U);
+    } else {
+        /* Set relative card address */
+        InstancePtr->RelCardAddr = 0x12340000U;
+        Status = XSdPs_CmdTransfer(InstancePtr, CMD3, (InstancePtr->RelCardAddr), 0U);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     Status = XST_SUCCESS;
 
@@ -594,44 +594,44 @@ s32 XSdPs_GetCsd(XSdPs *InstancePtr)
 
     Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/*
-	 * Card specific data is read.
-	 * Currently not used for any operation.
-	 */
+    /*
+     * Card specific data is read.
+     * Currently not used for any operation.
+     */
     CSD[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-		    XSDPS_RESP0_OFFSET);
+            XSDPS_RESP0_OFFSET);
     CSD[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-		    XSDPS_RESP1_OFFSET);
+            XSDPS_RESP1_OFFSET);
     CSD[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-		    XSDPS_RESP2_OFFSET);
+            XSDPS_RESP2_OFFSET);
     CSD[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-		    XSDPS_RESP3_OFFSET);
+            XSDPS_RESP3_OFFSET);
 
     if (InstancePtr->CardType != XSDPS_CARD_SD) {
-	    InstancePtr->Card_Version = (u8)((u32)(CSD[3] & CSD_SPEC_VER_MASK) >>18U);
-	    Status = XST_SUCCESS;
-	    goto RETURN_PATH;
-	}
+        InstancePtr->Card_Version = (u8)((u32)(CSD[3] & CSD_SPEC_VER_MASK) >>18U);
+        Status = XST_SUCCESS;
+        goto RETURN_PATH;
+    }
 
     if (((CSD[3] & CSD_STRUCT_MASK) >> 22U) == 0U) {
-	    BlkLen = 1U << ((u32)(CSD[2] & READ_BLK_LEN_MASK) >> 8U);
-	    Mult = 1U << ((u32)((CSD[1] & C_SIZE_MULT_MASK) >> 7U) + 2U);
-	    DeviceSize = (CSD[1] & C_SIZE_LOWER_MASK) >> 22U;
-	    DeviceSize |= (CSD[2] & C_SIZE_UPPER_MASK) << 10U;
-	    DeviceSize = (DeviceSize + 1U) * Mult;
-	    DeviceSize =  DeviceSize * BlkLen;
-	    InstancePtr->SectorCount = (DeviceSize/XSDPS_BLK_SIZE_512_MASK);
-	} else if (((CSD[3] & CSD_STRUCT_MASK) >> 22U) == 1U) {
-	    InstancePtr->SectorCount = (((CSD[1] & CSD_V2_C_SIZE_MASK) >> 8U) +
-									    1U) * 1024U;
-	} else {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        BlkLen = 1U << ((u32)(CSD[2] & READ_BLK_LEN_MASK) >> 8U);
+        Mult = 1U << ((u32)((CSD[1] & C_SIZE_MULT_MASK) >> 7U) + 2U);
+        DeviceSize = (CSD[1] & C_SIZE_LOWER_MASK) >> 22U;
+        DeviceSize |= (CSD[2] & C_SIZE_UPPER_MASK) << 10U;
+        DeviceSize = (DeviceSize + 1U) * Mult;
+        DeviceSize =  DeviceSize * BlkLen;
+        InstancePtr->SectorCount = (DeviceSize/XSDPS_BLK_SIZE_512_MASK);
+    } else if (((CSD[3] & CSD_STRUCT_MASK) >> 22U) == 1U) {
+        InstancePtr->SectorCount = (((CSD[1] & CSD_V2_C_SIZE_MASK) >> 8U) +
+                                        1U) * 1024U;
+    } else {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XST_SUCCESS;
 
@@ -655,30 +655,30 @@ s32 XSdPs_CardSetVoltage18(XSdPs *InstancePtr)
     u16 CtrlReg;
     u16 ClockReg;
 
-	/* Stop the clock */
+    /* Stop the clock */
     CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_CLK_CTRL_OFFSET);
+            XSDPS_CLK_CTRL_OFFSET);
     CtrlReg &= ~(XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_CLK_EN_MASK);
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,
-		    CtrlReg);
+            CtrlReg);
 
-	/* Check for 1.8V signal enable bit is cleared by Host */
+    /* Check for 1.8V signal enable bit is cleared by Host */
     Status = XSdPs_SetVoltage18(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			    XSDPS_CLK_CTRL_OFFSET);
-	/* Enable the clock in the controller */
+                XSDPS_CLK_CTRL_OFFSET);
+    /* Enable the clock in the controller */
     Status = XSdPs_EnableClock(InstancePtr, ClockReg);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
-	/* Wait for 1mSec */
-	(void)usleep(1000U);
+    /* Wait for 1mSec */
+    (void)usleep(1000U);
 
     Status = XST_SUCCESS;
 
@@ -704,9 +704,9 @@ s32 XSdPs_ResetConfig(XSdPs *InstancePtr)
 
     Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
     XSdPs_EnableBusPower(InstancePtr);
 
@@ -732,16 +732,16 @@ void XSdPs_HostConfig(XSdPs *InstancePtr)
 
     XSdPs_ConfigInterrupt(InstancePtr);
 
-	/*
-	 * Transfer mode register - default value
-	 * DMA enabled, block count enabled, data direction card to host(read)
-	 */
+    /*
+     * Transfer mode register - default value
+     * DMA enabled, block count enabled, data direction card to host(read)
+     */
     InstancePtr->TransferMode = XSDPS_TM_DMA_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK |
-		    XSDPS_TM_DAT_DIR_SEL_MASK;
+            XSDPS_TM_DAT_DIR_SEL_MASK;
 
-	/* Set block size to 512 by default */
+    /* Set block size to 512 by default */
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK);
+            XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK);
 }
 
 /*****************************************************************************/
@@ -761,19 +761,19 @@ s32 XSdPs_CheckResetDone(XSdPs *InstancePtr, u8 Value)
     u32 ReadReg;
     s32 Status;
 
-	/* Proceed with initialization only after reset is complete */
+    /* Proceed with initialization only after reset is complete */
     do {
-	    ReadReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
-			    XSDPS_SW_RST_OFFSET);
-	    Timeout = Timeout - 1U;
-	    usleep(1);
-	} while (((ReadReg & Value) != 0U)
-			&& (Timeout != 0U));
+        ReadReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
+                XSDPS_SW_RST_OFFSET);
+        Timeout = Timeout - 1U;
+        usleep(1);
+    } while (((ReadReg & Value) != 0U)
+            && (Timeout != 0U));
 
     if (Timeout == 0U) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
     Status = XST_SUCCESS;
 
@@ -797,27 +797,27 @@ s32 XSdPs_SetupVoltageSwitch(XSdPs *InstancePtr)
     s32 Status;
     u32 ReadReg;
 
-	/* Send switch voltage command */
+    /* Send switch voltage command */
     Status = XSdPs_CmdTransfer(InstancePtr, CMD11, 0U, 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Wait for CMD and DATA line to go low */
+    /* Wait for CMD and DATA line to go low */
     do {
-	    ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-			    XSDPS_PRES_STATE_OFFSET);
-	    Timeout = Timeout - 1;
-	    usleep(1);
-	} while (((ReadReg & (XSDPS_PSR_CMD_SG_LVL_MASK |
-		    XSDPS_PSR_DAT30_SG_LVL_MASK)) != 0U)
-			&& (Timeout != 0U));
+        ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XSDPS_PRES_STATE_OFFSET);
+        Timeout = Timeout - 1;
+        usleep(1);
+    } while (((ReadReg & (XSDPS_PSR_CMD_SG_LVL_MASK |
+            XSDPS_PSR_DAT30_SG_LVL_MASK)) != 0U)
+            && (Timeout != 0U));
 
     if (Timeout == 0U) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
 RETURN_PATH:
     return Status;
@@ -839,21 +839,21 @@ s32 XSdPs_CheckBusHigh(XSdPs *InstancePtr)
     s32 Status;
     u32 ReadReg;
 
-	/* Wait for CMD and DATA line to go high */
+    /* Wait for CMD and DATA line to go high */
     Timeout = MAX_TIMEOUT;
     do {
-	    ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-			    XSDPS_PRES_STATE_OFFSET);
-	    Timeout = Timeout - 1;
-	    usleep(1);
-	} while (((ReadReg & (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK))
-			!= (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK))
-			&& (Timeout != 0U));
+        ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XSDPS_PRES_STATE_OFFSET);
+        Timeout = Timeout - 1;
+        usleep(1);
+    } while (((ReadReg & (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK))
+            != (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK))
+            && (Timeout != 0U));
 
     if (Timeout == 0U) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
     Status = XST_SUCCESS;
 
@@ -875,36 +875,36 @@ RETURN_PATH:
 *
 * @return    None.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 void XSdPs_Identify_UhsMode(XSdPs *InstancePtr, u8 *ReadBuff)
 {
     if (((ReadBuff[13] & UHS_SDR104_SUPPORT) != 0U) &&
-		(InstancePtr->Config.InputClockHz >= XSDPS_SD_INPUT_MAX_CLK)) {
-	    InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR104;
-	    if (InstancePtr->Config.BankNumber == 2U) {
-		    InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2;
-		} else {
-		    InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0;
-		}
-	} else if (((ReadBuff[13] & UHS_SDR50_SUPPORT) != 0U) &&
-		(InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR50_MAX_CLK)) {
-	    InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR50;
-	    InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD50;
-	} else if (((ReadBuff[13] & UHS_DDR50_SUPPORT) != 0U) &&
-		(InstancePtr->Config.InputClockHz >= XSDPS_SD_DDR50_MAX_CLK)) {
-	    InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_DDR50;
-	    InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_DDR50;
-	    InstancePtr->ITapDelay = SD_ITAPDLYSEL_SD_DDR50;
-	} else if (((ReadBuff[13] & UHS_SDR25_SUPPORT) != 0U) &&
-		(InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR25_MAX_CLK)) {
-	    InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR25;
-	    InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD;
-	    InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
-	} else {
-	    InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR12;
-	}
+        (InstancePtr->Config.InputClockHz >= XSDPS_SD_INPUT_MAX_CLK)) {
+        InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR104;
+        if (InstancePtr->Config.BankNumber == 2U) {
+            InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2;
+        } else {
+            InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0;
+        }
+    } else if (((ReadBuff[13] & UHS_SDR50_SUPPORT) != 0U) &&
+        (InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR50_MAX_CLK)) {
+        InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR50;
+        InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD50;
+    } else if (((ReadBuff[13] & UHS_DDR50_SUPPORT) != 0U) &&
+        (InstancePtr->Config.InputClockHz >= XSDPS_SD_DDR50_MAX_CLK)) {
+        InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_DDR50;
+        InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_DDR50;
+        InstancePtr->ITapDelay = SD_ITAPDLYSEL_SD_DDR50;
+    } else if (((ReadBuff[13] & UHS_SDR25_SUPPORT) != 0U) &&
+        (InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR25_MAX_CLK)) {
+        InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR25;
+        InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD;
+        InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
+    } else {
+        InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR12;
+    }
 }
 
 /*****************************************************************************/
@@ -918,26 +918,26 @@ void XSdPs_Identify_UhsMode(XSdPs *InstancePtr, u8 *ReadBuff)
 *
 * @return    None
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 void XSdPs_SetTapDelay(XSdPs *InstancePtr)
 {
     if ((InstancePtr->Mode == XSDPS_DEFAULT_SPEED_MODE) ||
-		(InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR12)) {
-	    return;
-	}
+        (InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR12)) {
+        return;
+    }
 
 #ifndef versal
-	/* Issue DLL Reset */
+    /* Issue DLL Reset */
     XSdPs_DllRstCtrl(InstancePtr, 1U);
 #endif
 
-	/* Configure the Tap Delay Registers */
+    /* Configure the Tap Delay Registers */
     XSdPs_ConfigTapDelay(InstancePtr);
 
 #ifndef versal
-	/* Release the DLL out of reset */
+    /* Release the DLL out of reset */
     XSdPs_DllRstCtrl(InstancePtr, 0U);
 #endif
 }
@@ -963,9 +963,9 @@ s32 XSdPs_Change_SdBusSpeed(XSdPs *InstancePtr)
 
     Status = XSdPs_CalcBusSpeed(InstancePtr, &Arg);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
     BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
@@ -974,25 +974,25 @@ s32 XSdPs_Change_SdBusSpeed(XSdPs *InstancePtr)
 
     Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, BlkCnt);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check for transfer done */
+    /* Check for transfer done */
     Status = XSdps_CheckTransferDone(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     if (InstancePtr->Switch1v8 != 0U) {
-		/* Set UHS mode in controller */
-	    CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			    XSDPS_HOST_CTRL2_OFFSET);
-	    CtrlReg &= (u16)(~XSDPS_HC2_UHS_MODE_MASK);
-	    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-					    XSDPS_HOST_CTRL2_OFFSET,
-					    CtrlReg | InstancePtr->Mode);
-	}
+        /* Set UHS mode in controller */
+        CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                XSDPS_HOST_CTRL2_OFFSET);
+        CtrlReg &= (u16)(~XSDPS_HC2_UHS_MODE_MASK);
+        XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                        XSDPS_HOST_CTRL2_OFFSET,
+                        CtrlReg | InstancePtr->Mode);
+    }
 
     Status = XST_SUCCESS;
 
@@ -1017,21 +1017,21 @@ s32 XSdPs_Change_MmcBusSpeed(XSdPs *InstancePtr)
 
     Status = XSdPs_CalcBusSpeed(InstancePtr, &Arg);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check for transfer done */
+    /* Check for transfer done */
     Status = XSdps_CheckTransferDone(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     Status = XST_SUCCESS;
 
@@ -1057,50 +1057,50 @@ s32 XSdPs_AutoTuning(XSdPs *InstancePtr)
 
     BlkSize = XSDPS_TUNING_CMD_BLKSIZE;
     if(InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH)
-	{
-	    BlkSize = BlkSize*2U;
-	}
+    {
+        BlkSize = BlkSize*2U;
+    }
     BlkSize &= XSDPS_BLK_SIZE_MASK;
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
-		    BlkSize);
+            BlkSize);
 
     InstancePtr->TransferMode = XSDPS_TM_DAT_DIR_SEL_MASK;
 
     XSdPs_SetExecTuning(InstancePtr);
-	/*
-	 * workaround which can work for 1.0/2.0 silicon for auto tuning.
-	 * This can be revisited for 3.0 silicon if necessary.
-	 */
-	/* Wait for ~60 clock cycles to reset the tap values */
-	(void)usleep(1U);
+    /*
+     * workaround which can work for 1.0/2.0 silicon for auto tuning.
+     * This can be revisited for 3.0 silicon if necessary.
+     */
+    /* Wait for ~60 clock cycles to reset the tap values */
+    (void)usleep(1U);
 
     for (TuningCount = 0U; TuningCount < MAX_TUNING_COUNT; TuningCount++) {
 
-	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		    Status = XSdPs_CmdTransfer(InstancePtr, CMD19, 0U, 1U);
-		} else {
-		    Status = XSdPs_CmdTransfer(InstancePtr, CMD21, 0U, 1U);
-		}
+        if (InstancePtr->CardType == XSDPS_CARD_SD) {
+            Status = XSdPs_CmdTransfer(InstancePtr, CMD19, 0U, 1U);
+        } else {
+            Status = XSdPs_CmdTransfer(InstancePtr, CMD21, 0U, 1U);
+        }
 
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
 
-	    if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			    XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_EXEC_TNG_MASK) == 0U) {
-		    break;
-		}
-	}
+        if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_EXEC_TNG_MASK) == 0U) {
+            break;
+        }
+    }
 
     if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_SAMP_CLK_SEL_MASK) == 0U) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+            XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_SAMP_CLK_SEL_MASK) == 0U) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Wait for ~12 clock cycles to synchronize the new tap values */
-	(void)usleep(1U);
+    /* Wait for ~12 clock cycles to synchronize the new tap values */
+    (void)usleep(1U);
 
     Status = XST_SUCCESS;
 
@@ -1121,16 +1121,16 @@ RETURN_PATH:
 *
 * @return    None
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
 {
     if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-	    XSdPs_Setup64ADMA2DescTbl(InstancePtr, BlkCnt, Buff);
-	} else {
-	    XSdPs_Setup32ADMA2DescTbl(InstancePtr, BlkCnt, Buff);
-	}
+        XSdPs_Setup64ADMA2DescTbl(InstancePtr, BlkCnt, Buff);
+    } else {
+        XSdPs_Setup32ADMA2DescTbl(InstancePtr, BlkCnt, Buff);
+    }
 }
 
 /*****************************************************************************/
@@ -1145,7 +1145,7 @@ void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
 *
 * @return    None
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 void XSdPs_SetupADMA2DescTbl64Bit(XSdPs *InstancePtr, u32 BlkCnt)
@@ -1160,52 +1160,52 @@ void XSdPs_SetupADMA2DescTbl64Bit(XSdPs *InstancePtr, u32 BlkCnt)
     u64 DescNum;
     u32 BlkSize;
 
-	/* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */
+    /* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */
     BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				    XSDPS_BLK_SIZE_OFFSET) &
-				    XSDPS_BLK_SIZE_MASK;
+                    XSDPS_BLK_SIZE_OFFSET) &
+                    XSDPS_BLK_SIZE_MASK;
 
     if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
 
-	    TotalDescLines = 1U;
+        TotalDescLines = 1U;
 
-	} else {
+    } else {
 
-	    TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
-	    if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
-		    TotalDescLines += 1U;
-		}
+        TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
+        if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
+            TotalDescLines += 1U;
+        }
 
-	}
+    }
 
     for (DescNum = 0U; DescNum < (TotalDescLines-1); DescNum++) {
-	    Adma2_DescrTbl[DescNum].Address =
-			    InstancePtr->Dma64BitAddr +
-				(DescNum*XSDPS_DESC_MAX_LENGTH);
-	    Adma2_DescrTbl[DescNum].Attribute =
-			    XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
-	    Adma2_DescrTbl[DescNum].Length = 0U;
-	}
+        Adma2_DescrTbl[DescNum].Address =
+                InstancePtr->Dma64BitAddr +
+                (DescNum*XSDPS_DESC_MAX_LENGTH);
+        Adma2_DescrTbl[DescNum].Attribute =
+                XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
+        Adma2_DescrTbl[DescNum].Length = 0U;
+    }
 
     Adma2_DescrTbl[TotalDescLines-1].Address =
-			    InstancePtr->Dma64BitAddr +
-				(DescNum*XSDPS_DESC_MAX_LENGTH);
+                InstancePtr->Dma64BitAddr +
+                (DescNum*XSDPS_DESC_MAX_LENGTH);
 
     Adma2_DescrTbl[TotalDescLines-1].Attribute =
-		    XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
+            XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
 
     Adma2_DescrTbl[TotalDescLines-1].Length =
-			(u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH));
+            (u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH));
 
     XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
-			(u32)((UINTPTR)&(Adma2_DescrTbl[0]) & (u32)~0x0));
+            (u32)((UINTPTR)&(Adma2_DescrTbl[0]) & (u32)~0x0));
 
     if (InstancePtr->Config.IsCacheCoherent == 0U) {
-	    Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
-		    sizeof(XSdPs_Adma2Descriptor64) * 32U);
-	}
+        Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
+            sizeof(XSdPs_Adma2Descriptor64) * 32U);
+    }
 
-	/* Clear the 64-Bit Address variable */
+    /* Clear the 64-Bit Address variable */
     InstancePtr->Dma64BitAddr = 0U;
 
 }
@@ -1221,7 +1221,7 @@ void XSdPs_SetupADMA2DescTbl64Bit(XSdPs *InstancePtr, u32 BlkCnt)
 *
 * @return    None
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_DllReset(XSdPs *InstancePtr)
@@ -1229,28 +1229,28 @@ s32 XSdPs_DllReset(XSdPs *InstancePtr)
     u32 ClockReg;
     s32 Status;
 
-	/* Disable clock */
+    /* Disable clock */
     ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_CLK_CTRL_OFFSET);
+            XSDPS_CLK_CTRL_OFFSET);
     ClockReg &= ~XSDPS_CC_SD_CLK_EN_MASK;
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_CLK_CTRL_OFFSET, (u16)ClockReg);
+            XSDPS_CLK_CTRL_OFFSET, (u16)ClockReg);
 
-	/* Issue DLL Reset to load zero tap values */
+    /* Issue DLL Reset to load zero tap values */
     XSdPs_DllRstCtrl(InstancePtr, 1U);
 
-	/* Wait for 2 micro seconds */
-	(void)usleep(2U);
+    /* Wait for 2 micro seconds */
+    (void)usleep(2U);
 
     XSdPs_DllRstCtrl(InstancePtr, 0U);
 
     ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			    XSDPS_CLK_CTRL_OFFSET);
-	/* Enable the clock in the controller */
+                XSDPS_CLK_CTRL_OFFSET);
+    /* Enable the clock in the controller */
     Status = XSdPs_EnableClock(InstancePtr, ClockReg);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     return Status;
 }
@@ -1269,33 +1269,33 @@ s32 XSdPs_DllReset(XSdPs *InstancePtr)
 void XSdPs_IdentifyEmmcMode(XSdPs *InstancePtr, const u8 *ExtCsd)
 {
     if (InstancePtr->BusWidth < XSDPS_4_BIT_WIDTH) {
-	    InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
-	} else {
-		/* Check for card supported speed */
-	    if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
-				(EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 |
-			    EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200)) != 0U) {
-		    InstancePtr->Mode = XSDPS_HS200_MODE;
-		    if (InstancePtr->Config.BankNumber == 2U) {
-			    InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2;
-			} else {
-			    InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0;
-			}
-		} else if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
-				(EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED |
-			    EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED)) != 0U) {
-		    InstancePtr->Mode = XSDPS_DDR52_MODE;
-		    InstancePtr->OTapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
-		    InstancePtr->ITapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
-		} else if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
-			    EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) {
-		    InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
-		    InstancePtr->OTapDelay = SD_OTAPDLYSEL_EMMC_HSD;
-		    InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
-		} else {
-		    InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
-		}
-	}
+        InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
+    } else {
+        /* Check for card supported speed */
+        if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
+                (EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 |
+                EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200)) != 0U) {
+            InstancePtr->Mode = XSDPS_HS200_MODE;
+            if (InstancePtr->Config.BankNumber == 2U) {
+                InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2;
+            } else {
+                InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0;
+            }
+        } else if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
+                (EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED |
+                EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED)) != 0U) {
+            InstancePtr->Mode = XSDPS_DDR52_MODE;
+            InstancePtr->OTapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
+            InstancePtr->ITapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
+        } else if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
+                EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) {
+            InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
+            InstancePtr->OTapDelay = SD_OTAPDLYSEL_EMMC_HSD;
+            InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
+        } else {
+            InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
+        }
+    }
 }
 
 /*****************************************************************************/
@@ -1315,24 +1315,24 @@ s32 XSdPs_CheckEmmcTiming(XSdPs *InstancePtr, u8 *ExtCsd)
 
     Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     if (InstancePtr->Mode == XSDPS_HS200_MODE) {
-	    if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HS200) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	} else if ((InstancePtr->Mode == XSDPS_HIGH_SPEED_MODE) ||
-			(InstancePtr->Mode == XSDPS_DDR52_MODE)) {
-	    if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	} else {
-	    Status = XST_FAILURE;
-	}
+        if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HS200) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else if ((InstancePtr->Mode == XSDPS_HIGH_SPEED_MODE) ||
+            (InstancePtr->Mode == XSDPS_DDR52_MODE)) {
+        if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else {
+        Status = XST_FAILURE;
+    }
 
 RETURN_PATH:
     return Status;
@@ -1354,24 +1354,24 @@ s32 XSdPs_SetClock(XSdPs *InstancePtr, u32 SelFreq)
     u16 ClockReg;
     s32 Status;
 
-	/* Disable clock */
+    /* Disable clock */
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_CLK_CTRL_OFFSET, 0U);
+            XSDPS_CLK_CTRL_OFFSET, 0U);
 
-	/* If selected frequency is zero, return from here */
+    /* If selected frequency is zero, return from here */
     if (SelFreq == 0U) {
-	    Status = XST_SUCCESS;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_SUCCESS;
+        goto RETURN_PATH ;
+    }
 
-	/* Calculate the clock */
+    /* Calculate the clock */
     ClockReg = XSdPs_CalcClock(InstancePtr, SelFreq);
 
-	/* Enable the clock in the controller */
+    /* Enable the clock in the controller */
     Status = XSdPs_EnableClock(InstancePtr, ClockReg);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
 RETURN_PATH:
     return Status;
@@ -1385,8 +1385,8 @@ RETURN_PATH:
 * @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
-* 		- XST_SUCCESS if voltage is 1.8V
-* 		- XST_FAILURE if voltage is not 1.8V
+*         - XST_SUCCESS if voltage is 1.8V
+*         - XST_FAILURE if voltage is not 1.8V
 *
 ******************************************************************************/
 s32 XSdPs_CheckVoltage18(XSdPs *InstancePtr)
@@ -1394,10 +1394,10 @@ s32 XSdPs_CheckVoltage18(XSdPs *InstancePtr)
     u32 Status;
 
     if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_1V8_EN_MASK) == 0U) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+            XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_1V8_EN_MASK) == 0U) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XST_SUCCESS;
 
@@ -1412,7 +1412,7 @@ RETURN_PATH:
 *
 * @param    InstancePtr is a pointer to the instance to be worked on.
 * @param    Arg is the address passed by the user that is to be sent as
-* 	    argument along with the command.
+*         argument along with the command.
 * @param    BlkCnt - Block count passed by the user.
 *
 * @return    None
@@ -1422,31 +1422,31 @@ s32 XSdPs_SetupCmd(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt)
 {
     s32 Status;
 
-	/*
-	 * Check the command inhibit to make sure no other
-	 * command transfer is in progress
-	 */
+    /*
+     * Check the command inhibit to make sure no other
+     * command transfer is in progress
+     */
     Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
-	/* Write block count register */
+    /* Write block count register */
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_BLK_CNT_OFFSET, (u16)BlkCnt);
+            XSDPS_BLK_CNT_OFFSET, (u16)BlkCnt);
 
     XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-		    XSDPS_TIMEOUT_CTRL_OFFSET, 0xEU);
+            XSDPS_TIMEOUT_CTRL_OFFSET, 0xEU);
 
-	/* Write argument register */
+    /* Write argument register */
     XSdPs_WriteReg(InstancePtr->Config.BaseAddress,
-		    XSDPS_ARGMT_OFFSET, Arg);
+            XSDPS_ARGMT_OFFSET, Arg);
 
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
+            XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
+            XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
 
     Status = XST_SUCCESS;
 
@@ -1463,8 +1463,8 @@ RETURN_PATH:
 * @param    Cmd is the command to be sent
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure
 *
 ******************************************************************************/
 s32 XSdPs_SendCmd(XSdPs *InstancePtr, u32 Cmd)
@@ -1473,32 +1473,32 @@ s32 XSdPs_SendCmd(XSdPs *InstancePtr, u32 Cmd)
     u32 CommandReg;
     s32 Status;
 
-	/* Command register is set to trigger transfer of command */
+    /* Command register is set to trigger transfer of command */
     CommandReg = XSdPs_FrameCmd(InstancePtr, Cmd);
 
-	/*
-	 * Mask to avoid writing to reserved bits 31-30
-	 * This is necessary because 0x8000 is used  by this software to
-	 * distinguish between ACMD and CMD of same number
-	 */
+    /*
+     * Mask to avoid writing to reserved bits 31-30
+     * This is necessary because 0x8000 is used  by this software to
+     * distinguish between ACMD and CMD of same number
+     */
     CommandReg = CommandReg & 0x3FFFU;
 
-	/*
-	 * Check for data inhibit in case of command using DAT lines.
-	 * For Tuning Commands DAT lines check can be ignored.
-	 */
+    /*
+     * Check for data inhibit in case of command using DAT lines.
+     * For Tuning Commands DAT lines check can be ignored.
+     */
     if ((Cmd != CMD21) && (Cmd != CMD19)) {
-	    PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-			    XSDPS_PRES_STATE_OFFSET);
-	    if (((PresentStateReg & XSDPS_PSR_INHIBIT_DAT_MASK) != 0U) &&
-				((CommandReg & XSDPS_DAT_PRESENT_SEL_MASK) != 0U)) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XSDPS_PRES_STATE_OFFSET);
+        if (((PresentStateReg & XSDPS_PSR_INHIBIT_DAT_MASK) != 0U) &&
+                ((CommandReg & XSDPS_DAT_PRESENT_SEL_MASK) != 0U)) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET,
-			(CommandReg << 16) | InstancePtr->TransferMode);
+            (CommandReg << 16) | InstancePtr->TransferMode);
 
     Status = XST_SUCCESS;
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c
index f3c01598f0..25cb7817af 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c
@@ -22,28 +22,28 @@
 
 XSdPs_Config XSdPs_ConfigTable[XPAR_XSDPS_NUM_INSTANCES] =
 {
-	{
-	    XPAR_PSU_SD_0_DEVICE_ID,
-	    XPAR_PSU_SD_0_BASEADDR,
-	    XPAR_PSU_SD_0_SDIO_CLK_FREQ_HZ,
-	    XPAR_PSU_SD_0_HAS_CD,
-	    XPAR_PSU_SD_0_HAS_WP,
-	    XPAR_PSU_SD_0_BUS_WIDTH,
-	    XPAR_PSU_SD_0_MIO_BANK,
-	    XPAR_PSU_SD_0_HAS_EMIO,
-	    XPAR_PSU_SD_0_IS_CACHE_COHERENT
-	},
-	{
-	    XPAR_PSU_SD_1_DEVICE_ID,
-	    XPAR_PSU_SD_1_BASEADDR,
-	    XPAR_PSU_SD_1_SDIO_CLK_FREQ_HZ,
-	    XPAR_PSU_SD_1_HAS_CD,
-	    XPAR_PSU_SD_1_HAS_WP,
-	    XPAR_PSU_SD_1_BUS_WIDTH,
-	    XPAR_PSU_SD_1_MIO_BANK,
-	    XPAR_PSU_SD_1_HAS_EMIO,
-	    XPAR_PSU_SD_1_IS_CACHE_COHERENT
-	}
+    {
+        XPAR_PSU_SD_0_DEVICE_ID,
+        XPAR_PSU_SD_0_BASEADDR,
+        XPAR_PSU_SD_0_SDIO_CLK_FREQ_HZ,
+        XPAR_PSU_SD_0_HAS_CD,
+        XPAR_PSU_SD_0_HAS_WP,
+        XPAR_PSU_SD_0_BUS_WIDTH,
+        XPAR_PSU_SD_0_MIO_BANK,
+        XPAR_PSU_SD_0_HAS_EMIO,
+        XPAR_PSU_SD_0_IS_CACHE_COHERENT
+    },
+    {
+        XPAR_PSU_SD_1_DEVICE_ID,
+        XPAR_PSU_SD_1_BASEADDR,
+        XPAR_PSU_SD_1_SDIO_CLK_FREQ_HZ,
+        XPAR_PSU_SD_1_HAS_CD,
+        XPAR_PSU_SD_1_HAS_WP,
+        XPAR_PSU_SD_1_BUS_WIDTH,
+        XPAR_PSU_SD_1_MIO_BANK,
+        XPAR_PSU_SD_1_HAS_EMIO,
+        XPAR_PSU_SD_1_IS_CACHE_COHERENT
+    }
 };
 
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c
index cdfa65d125..69fa9883b1 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c
@@ -39,9 +39,9 @@
 #if EL1_NONSECURE && defined (__aarch64__)
 void XSdps_Smc(XSdPs *InstancePtr, u32 RegOffset, u32 Mask, u32 Val)
 {
-	(void)Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(InstancePtr->SlcrBaseAddr +
-		    RegOffset) | ((u64)Mask << 32),
-			(u64)Val, 0, 0, 0, 0, 0);
+    (void)Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(InstancePtr->SlcrBaseAddr +
+            RegOffset) | ((u64)Mask << 32),
+            (u64)Val, 0, 0, 0, 0, 0);
 }
 #endif
 
@@ -59,25 +59,25 @@ s32 XSdPs_Switch_Voltage(XSdPs *InstancePtr)
 {
     s32 Status;
 
-	/* Setup the voltage switching sequence */
+    /* Setup the voltage switching sequence */
     Status = XSdPs_SetupVoltageSwitch(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Set the card voltage to 1.8V */
+    /* Set the card voltage to 1.8V */
     Status = XSdPs_CardSetVoltage18(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check if the bus is high */
+    /* Check if the bus is high */
     Status = XSdPs_CheckBusHigh(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
 RETURN_PATH:
     return Status;
@@ -91,8 +91,8 @@ RETURN_PATH:
 * @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure
 *
 ******************************************************************************/
 s32 XSdPs_SetupTransfer(XSdPs *InstancePtr)
@@ -101,29 +101,29 @@ s32 XSdPs_SetupTransfer(XSdPs *InstancePtr)
     s32 Status;
 
     if ((InstancePtr->HC_Version != XSDPS_HC_SPEC_V3) ||
-				((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
-				!= XSDPS_CAPS_EMB_SLOT)) {
-	    if(InstancePtr->Config.CardDetect != 0U) {
-			/* Check status to ensure card is initialized */
-		    PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-				    XSDPS_PRES_STATE_OFFSET);
-		    if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) {
-			    Status = XST_FAILURE;
-			    goto RETURN_PATH;
-			}
-		}
-	}
+                ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
+                != XSDPS_CAPS_EMB_SLOT)) {
+        if(InstancePtr->Config.CardDetect != 0U) {
+            /* Check status to ensure card is initialized */
+            PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XSDPS_PRES_STATE_OFFSET);
+            if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) {
+                Status = XST_FAILURE;
+                goto RETURN_PATH;
+            }
+        }
+    }
 
-	/* Set block size to 512 if not already set */
+    /* Set block size to 512 if not already set */
     if(XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-		    XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {
-	    Status = XSdPs_SetBlkSize(InstancePtr,
-		    XSDPS_BLK_SIZE_512_MASK);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+            XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {
+        Status = XSdPs_SetBlkSize(InstancePtr,
+            XSDPS_BLK_SIZE_512_MASK);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     Status = XST_SUCCESS;
 
@@ -141,26 +141,26 @@ RETURN_PATH:
 * @param    Value is the type of reset
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure
 *
 ******************************************************************************/
 s32 XSdPs_Reset(XSdPs *InstancePtr, u8 Value)
 {
     s32 Status;
 
-	/* "Software reset for all" is initiated */
+    /* "Software reset for all" is initiated */
     XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET,
-		    Value);
+            Value);
 
     Status = XSdPs_CheckResetDone(InstancePtr, Value);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
     RETURN_PATH:
-	    return Status;
+        return Status;
 }
 
 /*****************************************************************************/
@@ -178,10 +178,10 @@ void XSdPs_SetExecTuning(XSdPs *InstancePtr)
     u16 CtrlReg;
 
     CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			    XSDPS_HOST_CTRL2_OFFSET);
+                XSDPS_HOST_CTRL2_OFFSET);
     CtrlReg |= XSDPS_HC2_EXEC_TNG_MASK;
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-			    XSDPS_HOST_CTRL2_OFFSET, CtrlReg);
+                XSDPS_HOST_CTRL2_OFFSET, CtrlReg);
 }
 
 /*****************************************************************************/
@@ -192,8 +192,8 @@ void XSdPs_SetExecTuning(XSdPs *InstancePtr)
 * @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
-* 		- XST_SUCCESS if initialization is successful
-* 		- XST_FAILURE if failure
+*         - XST_SUCCESS if initialization is successful
+*         - XST_FAILURE if failure
 *
 ******************************************************************************/
 s32 XSdPs_SdModeInit(XSdPs *InstancePtr)
@@ -209,76 +209,76 @@ s32 XSdPs_SdModeInit(XSdPs *InstancePtr)
 
     Status = XSdPs_Get_BusWidth(InstancePtr, SCR);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     if ((SCR[1] & WIDTH_4_BIT_SUPPORT) != 0U) {
-	    InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
-	    Status = XSdPs_Change_BusWidth(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
+        Status = XSdPs_Change_BusWidth(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
-	/* Get speed supported by device */
+    /* Get speed supported by device */
     Status = XSdPs_Get_BusSpeed(InstancePtr, ReadBuff);
     if (Status != XST_SUCCESS) {
-	    goto RETURN_PATH;
-	}
+        goto RETURN_PATH;
+    }
 
     if (((SCR[2] & SCR_SPEC_VER_3) != 0U) &&
-		(ReadBuff[13] >= UHS_SDR50_SUPPORT) &&
-		(InstancePtr->Config.BusWidth == XSDPS_WIDTH_8) &&
-		(InstancePtr->Switch1v8 == 0U)) {
+        (ReadBuff[13] >= UHS_SDR50_SUPPORT) &&
+        (InstancePtr->Config.BusWidth == XSDPS_WIDTH_8) &&
+        (InstancePtr->Switch1v8 == 0U)) {
 
-	    InstancePtr->Switch1v8 = 1U;
+        InstancePtr->Switch1v8 = 1U;
 
-	    Status = XSdPs_CardSetVoltage18(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        Status = XSdPs_CardSetVoltage18(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     if (InstancePtr->Switch1v8 != 0U) {
 
-		/* Identify the UHS mode supported by card */
-	    XSdPs_Identify_UhsMode(InstancePtr, ReadBuff);
+        /* Identify the UHS mode supported by card */
+        XSdPs_Identify_UhsMode(InstancePtr, ReadBuff);
 
-	    Status = XSdPs_Change_BusSpeed(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	} else {
-		/*
-		 * card supports CMD6 when SD_SPEC field in SCR register
-		 * indicates that the Physical Layer Specification Version
-		 * is 1.10 or later. So for SD v1.0 cmd6 is not supported.
-		 */
-	    if (SCR[0] != 0U) {
-			/* Check for high speed support */
-		    if (((ReadBuff[13] & HIGH_SPEED_SUPPORT) != 0U) &&
-					(InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH)) {
-			    InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
-			    InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD;
-			    InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
-			    Status = XSdPs_Change_BusSpeed(InstancePtr);
-			    if (Status != XST_SUCCESS) {
-				    Status = XST_FAILURE;
-				    goto RETURN_PATH;
-				}
-			}
-		}
-	}
+        Status = XSdPs_Change_BusSpeed(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else {
+        /*
+         * card supports CMD6 when SD_SPEC field in SCR register
+         * indicates that the Physical Layer Specification Version
+         * is 1.10 or later. So for SD v1.0 cmd6 is not supported.
+         */
+        if (SCR[0] != 0U) {
+            /* Check for high speed support */
+            if (((ReadBuff[13] & HIGH_SPEED_SUPPORT) != 0U) &&
+                    (InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH)) {
+                InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
+                InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD;
+                InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
+                Status = XSdPs_Change_BusSpeed(InstancePtr);
+                if (Status != XST_SUCCESS) {
+                    Status = XST_FAILURE;
+                    goto RETURN_PATH;
+                }
+            }
+        }
+    }
 
     Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XST_SUCCESS;
 
@@ -294,8 +294,8 @@ RETURN_PATH:
 * @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
-* 		- XST_SUCCESS if initialization is successful
-* 		- XST_FAILURE if failure
+*         - XST_SUCCESS if initialization is successful
+*         - XST_FAILURE if failure
 *
 ******************************************************************************/
 s32 XSdPs_MmcModeInit(XSdPs *InstancePtr)
@@ -311,15 +311,15 @@ s32 XSdPs_MmcModeInit(XSdPs *InstancePtr)
     InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
     Status = XSdPs_Change_BusWidth(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     InstancePtr->SectorCount = ((u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE4]) << 24;
     InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE3] << 16;
@@ -327,26 +327,26 @@ s32 XSdPs_MmcModeInit(XSdPs *InstancePtr)
     InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE1];
 
     if (((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
-		    EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) &&
-			(InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH)) {
-	    InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
-	    Status = XSdPs_Change_BusSpeed(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
+            EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) &&
+            (InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH)) {
+        InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
+        Status = XSdPs_Change_BusSpeed(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
 
-	    Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
+        Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
 
-	    if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     Status = XST_SUCCESS;
 
@@ -362,8 +362,8 @@ RETURN_PATH:
 * @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
-* 		- XST_SUCCESS if initialization is successful
-* 		- XST_FAILURE if failure
+*         - XST_SUCCESS if initialization is successful
+*         - XST_FAILURE if failure
 *
 ******************************************************************************/
 s32 XSdPs_EmmcModeInit(XSdPs *InstancePtr)
@@ -378,29 +378,29 @@ s32 XSdPs_EmmcModeInit(XSdPs *InstancePtr)
 #endif
 
     if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
-			(InstancePtr->Config.BusWidth == XSDPS_WIDTH_8)) {
-		/* in case of eMMC data width 8-bit */
-	    InstancePtr->BusWidth = XSDPS_8_BIT_WIDTH;
-	} else if (InstancePtr->Config.BusWidth == XSDPS_WIDTH_4) {
-		/* in case of eMMC data width 4-bit */
-	    InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
-	} else {
-		/* in case of eMMC data width 1-bit */
-	    InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
-	}
+            (InstancePtr->Config.BusWidth == XSDPS_WIDTH_8)) {
+        /* in case of eMMC data width 8-bit */
+        InstancePtr->BusWidth = XSDPS_8_BIT_WIDTH;
+    } else if (InstancePtr->Config.BusWidth == XSDPS_WIDTH_4) {
+        /* in case of eMMC data width 4-bit */
+        InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
+    } else {
+        /* in case of eMMC data width 1-bit */
+        InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
+    }
 
     Status = XSdPs_Change_BusWidth(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Get Extended CSD */
+    /* Get Extended CSD */
     Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     InstancePtr->SectorCount = ((u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE4]) << 24;
     InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE3] << 16;
@@ -410,27 +410,27 @@ s32 XSdPs_EmmcModeInit(XSdPs *InstancePtr)
     XSdPs_IdentifyEmmcMode(InstancePtr, ExtCsd);
 
     if (InstancePtr->Mode != XSDPS_DEFAULT_SPEED_MODE) {
-	    Status = XSdPs_Change_BusSpeed(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
+        Status = XSdPs_Change_BusSpeed(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
 
-	    Status = XSdPs_CheckEmmcTiming(InstancePtr, ExtCsd);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        Status = XSdPs_CheckEmmcTiming(InstancePtr, ExtCsd);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
-	/* Enable Rst_n_Fun bit if it is disabled */
+    /* Enable Rst_n_Fun bit if it is disabled */
     if(ExtCsd[EXT_CSD_RST_N_FUN_BYTE] == EXT_CSD_RST_N_FUN_TEMP_DIS) {
-	    Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, XSDPS_MMC_RST_FUN_EN_ARG);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, XSDPS_MMC_RST_FUN_EN_ARG);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     Status = XST_SUCCESS;
 
@@ -450,17 +450,17 @@ RETURN_PATH:
 ******************************************************************************/
 void XSdPs_DisableBusPower(XSdPs *InstancePtr)
 {
-	/* Disable SD bus power and issue eMMC HW reset */
+    /* Disable SD bus power and issue eMMC HW reset */
     if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			    XSDPS_POWER_CTRL_OFFSET, XSDPS_PC_EMMC_HW_RST_MASK);
-	} else {
-	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			    XSDPS_POWER_CTRL_OFFSET, 0x0);
-	}
+        XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                XSDPS_POWER_CTRL_OFFSET, XSDPS_PC_EMMC_HW_RST_MASK);
+    } else {
+        XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                XSDPS_POWER_CTRL_OFFSET, 0x0);
+    }
 
-	/* 1ms delay to poweroff card */
-	(void)usleep(1000U);
+    /* 1ms delay to poweroff card */
+    (void)usleep(1000U);
 }
 
 /*****************************************************************************/
@@ -475,19 +475,19 @@ void XSdPs_DisableBusPower(XSdPs *InstancePtr)
 ******************************************************************************/
 void XSdPs_EnableBusPower(XSdPs *InstancePtr)
 {
-	/* Select voltage and enable bus power. */
+    /* Select voltage and enable bus power. */
     if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			    XSDPS_POWER_CTRL_OFFSET,
-				(XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK) &
-				~XSDPS_PC_EMMC_HW_RST_MASK);
-	} else {
-	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			    XSDPS_POWER_CTRL_OFFSET,
-			    XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK);
-	}
+        XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                XSDPS_POWER_CTRL_OFFSET,
+                (XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK) &
+                ~XSDPS_PC_EMMC_HW_RST_MASK);
+    } else {
+        XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                XSDPS_POWER_CTRL_OFFSET,
+                XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK);
+    }
 
-	/* 0.2ms Delay after bus power on*/
+    /* 0.2ms Delay after bus power on*/
     usleep(200);
 }
 
@@ -505,83 +505,83 @@ s32 XSdPs_SdCardEnum(XSdPs *InstancePtr)
 {
     s32 Status;
 
-	/* Check if the card is present */
+    /* Check if the card is present */
     Status = XSdPs_CheckCardDetect(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Reset the SD card */
+    /* Reset the SD card */
     Status = XSdPs_CardReset(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Get the card interface condition */
+    /* Get the card interface condition */
     Status = XSdPs_CardIfCond(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Get the card operating condition */
+    /* Get the card operating condition */
     Status = XSdPs_CardOpCond(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Get the card ID */
+    /* Get the card ID */
     Status = XSdPs_GetCardId(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Get the CSD register */
+    /* Get the CSD register */
     Status = XSdPs_GetCsd(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Change clock to default clock 25MHz */
-	/*
-	 * SD default speed mode timing should be closed at 19 MHz.
-	 * The reason for this is SD requires a voltage level shifter.
-	 * This limitation applies to ZynqMPSoC.
-	 */
+    /* Change clock to default clock 25MHz */
+    /*
+     * SD default speed mode timing should be closed at 19 MHz.
+     * The reason for this is SD requires a voltage level shifter.
+     * This limitation applies to ZynqMPSoC.
+     */
     if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-	    InstancePtr->BusSpeed = SD_CLK_19_MHZ;
-	} else {
-	    InstancePtr->BusSpeed = SD_CLK_25_MHZ;
-	}
+        InstancePtr->BusSpeed = SD_CLK_19_MHZ;
+    } else {
+        InstancePtr->BusSpeed = SD_CLK_25_MHZ;
+    }
     Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Select the card to transition to transfer state */
+    /* Select the card to transition to transfer state */
     Status = XSdPs_Select_Card(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Pull-up disconnected during data transfer */
+    /* Pull-up disconnected during data transfer */
     Status = XSdPs_Pullup(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XST_SUCCESS;
 
     RETURN_PATH:
-	    return Status;
+        return Status;
 }
 
 /*****************************************************************************/
@@ -598,55 +598,55 @@ s32 XSdPs_MmcCardEnum(XSdPs *InstancePtr)
 {
     s32 Status;
 
-	/* Check if the card is preset */
+    /* Check if the card is preset */
     Status = XSdPs_CheckCardDetect(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Reset the card */
+    /* Reset the card */
     Status = XSdPs_CardReset(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Get the card operating condition */
+    /* Get the card operating condition */
     Status = XSdPs_CardOpCond(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Get the card ID */
+    /* Get the card ID */
     Status = XSdPs_GetCardId(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Get the CSD register */
+    /* Get the CSD register */
     Status = XSdPs_GetCsd(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Change clock to default clock 26MHz */
+    /* Change clock to default clock 26MHz */
     InstancePtr->BusSpeed = SD_CLK_26_MHZ;
     Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Send select card command to transition to transfer state */
+    /* Send select card command to transition to transfer state */
     Status = XSdPs_Select_Card(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XST_SUCCESS;
 
@@ -669,29 +669,29 @@ s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr)
     s32 Status;
 
 #ifndef versal
-	/* Issue DLL Reset to load new SDHC tuned tap values */
+    /* Issue DLL Reset to load new SDHC tuned tap values */
     Status = XSdPs_DllReset(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
 #endif
 
-	/* Perform the auto tuning */
+    /* Perform the auto tuning */
     Status = XSdPs_AutoTuning(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
 #ifndef versal
-	/* Issue DLL Reset to load new SDHC tuned tap values */
+    /* Issue DLL Reset to load new SDHC tuned tap values */
     Status = XSdPs_DllReset(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
 #endif
 
@@ -711,8 +711,8 @@ RETURN_PATH:
 * @param    ClockReg is the clock value to be set.
 *
 * @return
-* 		- XST_SUCCESS if success
-* 		- XST_FAILURE if failure
+*         - XST_SUCCESS if success
+*         - XST_FAILURE if failure
 *
 ******************************************************************************/
 s32 XSdPs_EnableClock(XSdPs *InstancePtr, u16 ClockReg)
@@ -723,26 +723,26 @@ s32 XSdPs_EnableClock(XSdPs *InstancePtr, u16 ClockReg)
 
     ClockReg |= (u16)XSDPS_CC_INT_CLK_EN_MASK;
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_CLK_CTRL_OFFSET, ClockReg);
+            XSDPS_CLK_CTRL_OFFSET, ClockReg);
 
-	/* Wait for 150ms for internal clock to stabilize */
+    /* Wait for 150ms for internal clock to stabilize */
     do {
-	    ReadReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			    XSDPS_CLK_CTRL_OFFSET);
-	    Timeout = Timeout - 1U;
-	    usleep(1);
-	} while (((ReadReg & XSDPS_CC_INT_CLK_STABLE_MASK) == 0U)
-				&& (Timeout != 0U));
+        ReadReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                XSDPS_CLK_CTRL_OFFSET);
+        Timeout = Timeout - 1U;
+        usleep(1);
+    } while (((ReadReg & XSDPS_CC_INT_CLK_STABLE_MASK) == 0U)
+                && (Timeout != 0U));
 
     if (Timeout == 0U) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
-	/* Enable SD clock */
+    /* Enable SD clock */
     ClockReg |= XSDPS_CC_SD_CLK_EN_MASK;
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_CLK_CTRL_OFFSET, ClockReg);
+            XSDPS_CLK_CTRL_OFFSET, ClockReg);
 
     Status = XST_SUCCESS;
 
@@ -757,11 +757,11 @@ RETURN_PATH:
 *
 * @param    InstancePtr is a pointer to the instance to be worked on.
 * @param    Arg is the argument to be sent along with the command.
-* 	    This could be address or any other information
+*         This could be address or any other information
 *
 * @return
-* 		- XST_SUCCESS if success
-* 		- XST_FAILURE if failure
+*         - XST_SUCCESS if success
+*         - XST_FAILURE if failure
 *
 ******************************************************************************/
 s32 XSdPs_CalcBusSpeed(XSdPs *InstancePtr, u32 *Arg)
@@ -769,54 +769,54 @@ s32 XSdPs_CalcBusSpeed(XSdPs *InstancePtr, u32 *Arg)
     s32 Status = XST_SUCCESS;
 
     if (InstancePtr->CardType == XSDPS_CARD_SD) {
-	    switch (InstancePtr->Mode) {
-	    case XSDPS_UHS_SPEED_MODE_SDR12:
-			*Arg = XSDPS_SWITCH_CMD_SDR12_SET;
-		    InstancePtr->BusSpeed = XSDPS_SD_SDR12_MAX_CLK;
-		    break;
-	    case XSDPS_UHS_SPEED_MODE_SDR25:
-			*Arg = XSDPS_SWITCH_CMD_SDR25_SET;
-		    InstancePtr->BusSpeed = XSDPS_SD_SDR25_MAX_CLK;
-		    break;
-	    case XSDPS_UHS_SPEED_MODE_SDR50:
-			*Arg = XSDPS_SWITCH_CMD_SDR50_SET;
-		    InstancePtr->BusSpeed = XSDPS_SD_SDR50_MAX_CLK;
-		    break;
-	    case XSDPS_UHS_SPEED_MODE_SDR104:
-			*Arg = XSDPS_SWITCH_CMD_SDR104_SET;
-		    InstancePtr->BusSpeed = XSDPS_SD_SDR104_MAX_CLK;
-		    break;
-	    case XSDPS_UHS_SPEED_MODE_DDR50:
-			*Arg = XSDPS_SWITCH_CMD_DDR50_SET;
-		    InstancePtr->BusSpeed = XSDPS_SD_DDR50_MAX_CLK;
-		    break;
-	    case XSDPS_HIGH_SPEED_MODE:
-			*Arg = XSDPS_SWITCH_CMD_HS_SET;
-		    InstancePtr->BusSpeed = XSDPS_CLK_50_MHZ;
-		    break;
-	    default:
-		    Status = XST_FAILURE;
-		    break;
-		}
-	} else {
-	    switch (InstancePtr->Mode) {
-	    case XSDPS_HS200_MODE:
-			*Arg = XSDPS_MMC_HS200_ARG;
-		    InstancePtr->BusSpeed = XSDPS_MMC_HS200_MAX_CLK;
-		    break;
-	    case XSDPS_DDR52_MODE:
-			*Arg = XSDPS_MMC_HIGH_SPEED_ARG;
-		    InstancePtr->BusSpeed = XSDPS_MMC_DDR_MAX_CLK;
-		    break;
-	    case XSDPS_HIGH_SPEED_MODE:
-			*Arg = XSDPS_MMC_HIGH_SPEED_ARG;
-		    InstancePtr->BusSpeed = XSDPS_MMC_HSD_MAX_CLK;
-		    break;
-	    default:
-		    Status = XST_FAILURE;
-		    break;
-		}
-	}
+        switch (InstancePtr->Mode) {
+        case XSDPS_UHS_SPEED_MODE_SDR12:
+            *Arg = XSDPS_SWITCH_CMD_SDR12_SET;
+            InstancePtr->BusSpeed = XSDPS_SD_SDR12_MAX_CLK;
+            break;
+        case XSDPS_UHS_SPEED_MODE_SDR25:
+            *Arg = XSDPS_SWITCH_CMD_SDR25_SET;
+            InstancePtr->BusSpeed = XSDPS_SD_SDR25_MAX_CLK;
+            break;
+        case XSDPS_UHS_SPEED_MODE_SDR50:
+            *Arg = XSDPS_SWITCH_CMD_SDR50_SET;
+            InstancePtr->BusSpeed = XSDPS_SD_SDR50_MAX_CLK;
+            break;
+        case XSDPS_UHS_SPEED_MODE_SDR104:
+            *Arg = XSDPS_SWITCH_CMD_SDR104_SET;
+            InstancePtr->BusSpeed = XSDPS_SD_SDR104_MAX_CLK;
+            break;
+        case XSDPS_UHS_SPEED_MODE_DDR50:
+            *Arg = XSDPS_SWITCH_CMD_DDR50_SET;
+            InstancePtr->BusSpeed = XSDPS_SD_DDR50_MAX_CLK;
+            break;
+        case XSDPS_HIGH_SPEED_MODE:
+            *Arg = XSDPS_SWITCH_CMD_HS_SET;
+            InstancePtr->BusSpeed = XSDPS_CLK_50_MHZ;
+            break;
+        default:
+            Status = XST_FAILURE;
+            break;
+        }
+    } else {
+        switch (InstancePtr->Mode) {
+        case XSDPS_HS200_MODE:
+            *Arg = XSDPS_MMC_HS200_ARG;
+            InstancePtr->BusSpeed = XSDPS_MMC_HS200_MAX_CLK;
+            break;
+        case XSDPS_DDR52_MODE:
+            *Arg = XSDPS_MMC_HIGH_SPEED_ARG;
+            InstancePtr->BusSpeed = XSDPS_MMC_DDR_MAX_CLK;
+            break;
+        case XSDPS_HIGH_SPEED_MODE:
+            *Arg = XSDPS_MMC_HIGH_SPEED_ARG;
+            InstancePtr->BusSpeed = XSDPS_MMC_HSD_MAX_CLK;
+            break;
+        default:
+            Status = XST_FAILURE;
+            break;
+        }
+    }
 
     return Status;
 }
@@ -832,9 +832,9 @@ s32 XSdPs_CalcBusSpeed(XSdPs *InstancePtr, u32 *Arg)
 * @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because another transfer
-* 		    is in progress or command or data inhibit is set
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because another transfer
+*             is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 void XSdPs_SetupReadDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, u8 *Buff)
@@ -842,26 +842,26 @@ void XSdPs_SetupReadDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, u8 *Buff)
     BlkSize &= XSDPS_BLK_SIZE_MASK;
 
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_BLK_SIZE_OFFSET, BlkSize);
+            XSDPS_BLK_SIZE_OFFSET, BlkSize);
 
     if (InstancePtr->Dma64BitAddr >= ADDRESS_BEYOND_32BIT) {
-	    XSdPs_SetupADMA2DescTbl64Bit(InstancePtr, BlkCnt);
-	} else {
-	    XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
-	    if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		    Xil_DCacheInvalidateRange((INTPTR)Buff,
-				(INTPTR)BlkCnt * BlkSize);
-		}
-	}
+        XSdPs_SetupADMA2DescTbl64Bit(InstancePtr, BlkCnt);
+    } else {
+        XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
+        if (InstancePtr->Config.IsCacheCoherent == 0U) {
+            Xil_DCacheInvalidateRange((INTPTR)Buff,
+                (INTPTR)BlkCnt * BlkSize);
+        }
+    }
 
     if (BlkCnt == 1U) {
-	    InstancePtr->TransferMode = XSDPS_TM_BLK_CNT_EN_MASK |
-		    XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK;
-	} else {
-	    InstancePtr->TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK |
-		    XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DAT_DIR_SEL_MASK |
-		    XSDPS_TM_DMA_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK;
-	}
+        InstancePtr->TransferMode = XSDPS_TM_BLK_CNT_EN_MASK |
+            XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK;
+    } else {
+        InstancePtr->TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK |
+            XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DAT_DIR_SEL_MASK |
+            XSDPS_TM_DMA_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK;
+    }
 }
 
 /*****************************************************************************/
@@ -875,9 +875,9 @@ void XSdPs_SetupReadDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, u8 *Buff)
 * @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because another transfer
-* 		    is in progress or command or data inhibit is set
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because another transfer
+*             is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 void XSdPs_SetupWriteDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, const u8 *Buff)
@@ -885,26 +885,26 @@ void XSdPs_SetupWriteDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, const u8 *
     BlkSize &= XSDPS_BLK_SIZE_MASK;
 
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_BLK_SIZE_OFFSET, BlkSize);
+            XSDPS_BLK_SIZE_OFFSET, BlkSize);
 
     if (InstancePtr->Dma64BitAddr >= ADDRESS_BEYOND_32BIT) {
-	    XSdPs_SetupADMA2DescTbl64Bit(InstancePtr, BlkCnt);
-	} else {
-	    XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
-	    if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		    Xil_DCacheFlushRange((INTPTR)Buff,
-				(INTPTR)BlkCnt * BlkSize);
-		}
-	}
+        XSdPs_SetupADMA2DescTbl64Bit(InstancePtr, BlkCnt);
+    } else {
+        XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
+        if (InstancePtr->Config.IsCacheCoherent == 0U) {
+            Xil_DCacheFlushRange((INTPTR)Buff,
+                (INTPTR)BlkCnt * BlkSize);
+        }
+    }
 
     if (BlkCnt == 1U) {
-	    InstancePtr->TransferMode = XSDPS_TM_BLK_CNT_EN_MASK |
-		    XSDPS_TM_DMA_EN_MASK;
-	} else {
-	    InstancePtr->TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK |
-		    XSDPS_TM_BLK_CNT_EN_MASK |
-		    XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK;
-	}
+        InstancePtr->TransferMode = XSDPS_TM_BLK_CNT_EN_MASK |
+            XSDPS_TM_DMA_EN_MASK;
+    } else {
+        InstancePtr->TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK |
+            XSDPS_TM_BLK_CNT_EN_MASK |
+            XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK;
+    }
 }
 
 /*****************************************************************************/
@@ -920,7 +920,7 @@ void XSdPs_SetupWriteDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, const u8 *
 *
 * @return    None
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 void XSdPs_Setup32ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
@@ -935,44 +935,44 @@ void XSdPs_Setup32ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
     u64 DescNum;
     u32 BlkSize;
 
-	/* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */
+    /* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */
     BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				    XSDPS_BLK_SIZE_OFFSET) &
-				    XSDPS_BLK_SIZE_MASK;
+                    XSDPS_BLK_SIZE_OFFSET) &
+                    XSDPS_BLK_SIZE_MASK;
 
     if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
-	    TotalDescLines = 1U;
-	} else {
-	    TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
-	    if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
-		    TotalDescLines += 1U;
-		}
-	}
+        TotalDescLines = 1U;
+    } else {
+        TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
+        if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
+            TotalDescLines += 1U;
+        }
+    }
 
     for (DescNum = 0U; DescNum < (TotalDescLines-1); DescNum++) {
-	    Adma2_DescrTbl[DescNum].Address =
-				(u32)((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
-	    Adma2_DescrTbl[DescNum].Attribute =
-			    XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
-	    Adma2_DescrTbl[DescNum].Length = 0U;
-	}
+        Adma2_DescrTbl[DescNum].Address =
+                (u32)((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
+        Adma2_DescrTbl[DescNum].Attribute =
+                XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
+        Adma2_DescrTbl[DescNum].Length = 0U;
+    }
 
     Adma2_DescrTbl[TotalDescLines-1].Address =
-			(u32)((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
+            (u32)((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
 
     Adma2_DescrTbl[TotalDescLines-1].Attribute =
-		    XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
+            XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
 
     Adma2_DescrTbl[TotalDescLines-1].Length =
-			(u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH));
+            (u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH));
 
     XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
-			(u32)((UINTPTR)&(Adma2_DescrTbl[0]) & (u32)~0x0));
+            (u32)((UINTPTR)&(Adma2_DescrTbl[0]) & (u32)~0x0));
 
     if (InstancePtr->Config.IsCacheCoherent == 0U) {
-	    Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
-		    sizeof(XSdPs_Adma2Descriptor32) * 32U);
-	}
+        Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
+            sizeof(XSdPs_Adma2Descriptor32) * 32U);
+    }
 }
 
 /*****************************************************************************/
@@ -988,7 +988,7 @@ void XSdPs_Setup32ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
 *
 * @return    None
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 void XSdPs_Setup64ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
@@ -1003,49 +1003,49 @@ void XSdPs_Setup64ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
     u64 DescNum;
     u32 BlkSize;
 
-	/* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */
+    /* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */
     BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				    XSDPS_BLK_SIZE_OFFSET) &
-				    XSDPS_BLK_SIZE_MASK;
+                    XSDPS_BLK_SIZE_OFFSET) &
+                    XSDPS_BLK_SIZE_MASK;
 
     if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
-	    TotalDescLines = 1U;
-	} else {
-	    TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
-	    if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
-		    TotalDescLines += 1U;
-		}
-	}
+        TotalDescLines = 1U;
+    } else {
+        TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
+        if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
+            TotalDescLines += 1U;
+        }
+    }
 
     for (DescNum = 0U; DescNum < (TotalDescLines-1); DescNum++) {
-	    Adma2_DescrTbl[DescNum].Address =
-				((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
-	    Adma2_DescrTbl[DescNum].Attribute =
-			    XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
-	    Adma2_DescrTbl[DescNum].Length = 0U;
-	}
+        Adma2_DescrTbl[DescNum].Address =
+                ((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
+        Adma2_DescrTbl[DescNum].Attribute =
+                XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
+        Adma2_DescrTbl[DescNum].Length = 0U;
+    }
 
     Adma2_DescrTbl[TotalDescLines-1].Address =
-			(u64)((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
+            (u64)((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
 
     Adma2_DescrTbl[TotalDescLines-1].Attribute =
-		    XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
+            XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
 
     Adma2_DescrTbl[TotalDescLines-1].Length =
-			(u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH));
+            (u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH));
 
 #if defined(__aarch64__) || defined(__arch64__)
     XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_EXT_OFFSET,
-			(u32)((UINTPTR)(Adma2_DescrTbl)>>32U));
+            (u32)((UINTPTR)(Adma2_DescrTbl)>>32U));
 #endif
 
     XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
-			(u32)((UINTPTR)&(Adma2_DescrTbl[0]) & (u32)~0x0));
+            (u32)((UINTPTR)&(Adma2_DescrTbl[0]) & (u32)~0x0));
 
     if (InstancePtr->Config.IsCacheCoherent == 0U) {
-	    Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
-		    sizeof(XSdPs_Adma2Descriptor64) * 32U);
-	}
+        Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
+            sizeof(XSdPs_Adma2Descriptor64) * 32U);
+    }
 }
 
 /*****************************************************************************/
@@ -1066,22 +1066,22 @@ u32 XSdPs_CalcClock(XSdPs *InstancePtr, u32 SelFreq)
     u16 Divisor = 0U;
 
     if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-		/* Calculate divisor */
-	    for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_EXT_MAX_DIV_CNT; DivCnt++) {
-		    if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
-			    Divisor = DivCnt >> 1;
-			    break;
-			}
-		}
-	} else {
-		/* Calculate divisor */
-	    for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_MAX_DIV_CNT; DivCnt <<= 1U) {
-		    if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
-			    Divisor = DivCnt / 2U;
-			    break;
-			}
-		}
-	}
+        /* Calculate divisor */
+        for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_EXT_MAX_DIV_CNT; DivCnt++) {
+            if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
+                Divisor = DivCnt >> 1;
+                break;
+            }
+        }
+    } else {
+        /* Calculate divisor */
+        for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_MAX_DIV_CNT; DivCnt <<= 1U) {
+            if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
+                Divisor = DivCnt / 2U;
+                break;
+            }
+        }
+    }
 
     ClockVal |= (Divisor & XSDPS_CC_SDCLK_FREQ_SEL_MASK) << XSDPS_CC_DIV_SHIFT;
     ClockVal |= ((Divisor >> 8U) & XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK) << XSDPS_CC_EXT_DIV_SHIFT;
@@ -1101,7 +1101,7 @@ u32 XSdPs_CalcClock(XSdPs *InstancePtr, u32 SelFreq)
 *
 * @return    None
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst)
@@ -1114,72 +1114,72 @@ void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst)
 #ifdef XPAR_PSV_PMC_SD_0_DEVICE_ID
     if (DeviceId == 0U) {
 #if EL1_NONSECURE && defined (__aarch64__)
-		(void)DllCtrl;
+        (void)DllCtrl;
 
-	    XSdps_Smc(InstancePtr, SD0_DLL_CTRL, SD_DLL_RST, (EnRst == 1U) ? SD0_DLL_RST : 0U);
+        XSdps_Smc(InstancePtr, SD0_DLL_CTRL, SD_DLL_RST, (EnRst == 1U) ? SD0_DLL_RST : 0U);
 #else /* EL1_NONSECURE && defined (__aarch64__) */
-	    DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD0_DLL_CTRL);
-	    if (EnRst == 1U) {
-		    DllCtrl |= SD_DLL_RST;
-		} else {
-		    DllCtrl &= ~SD_DLL_RST;
-		}
-	    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD0_DLL_CTRL, DllCtrl);
+        DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD0_DLL_CTRL);
+        if (EnRst == 1U) {
+            DllCtrl |= SD_DLL_RST;
+        } else {
+            DllCtrl &= ~SD_DLL_RST;
+        }
+        XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD0_DLL_CTRL, DllCtrl);
 #endif /* EL1_NONSECURE && defined (__aarch64__) */
-	} else {
+    } else {
 #endif /* XPAR_PSV_PMC_SD_0_DEVICE_ID */
-		(void) DeviceId;
+        (void) DeviceId;
 #if EL1_NONSECURE && defined (__aarch64__)
-		(void)DllCtrl;
+        (void)DllCtrl;
 
-	    XSdps_Smc(InstancePtr, SD1_DLL_CTRL, SD_DLL_RST, (EnRst == 1U) ? SD_DLL_RST : 0U);
+        XSdps_Smc(InstancePtr, SD1_DLL_CTRL, SD_DLL_RST, (EnRst == 1U) ? SD_DLL_RST : 0U);
 #else
-	    DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD1_DLL_CTRL);
-	    if (EnRst == 1U) {
-		    DllCtrl |= SD_DLL_RST;
-		} else {
-		    DllCtrl &= ~SD_DLL_RST;
-		}
-	    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD1_DLL_CTRL, DllCtrl);
+        DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD1_DLL_CTRL);
+        if (EnRst == 1U) {
+            DllCtrl |= SD_DLL_RST;
+        } else {
+            DllCtrl &= ~SD_DLL_RST;
+        }
+        XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD1_DLL_CTRL, DllCtrl);
 #endif
 #ifdef XPAR_PSV_PMC_SD_0_DEVICE_ID
-	}
+    }
 #endif /* XPAR_PSV_PMC_SD_0_DEVICE_ID */
 #else /* versal */
 
 #ifdef XPAR_PSU_SD_0_DEVICE_ID
     if (DeviceId == 0U) {
 #if EL1_NONSECURE && defined (__aarch64__)
-		(void)DllCtrl;
+        (void)DllCtrl;
 
-	    XSdps_Smc(InstancePtr, SD_DLL_CTRL, SD0_DLL_RST, (EnRst == 1U) ? SD0_DLL_RST : 0U);
+        XSdps_Smc(InstancePtr, SD_DLL_CTRL, SD0_DLL_RST, (EnRst == 1U) ? SD0_DLL_RST : 0U);
 #else
-	    DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL);
-	    if (EnRst == 1U) {
-		    DllCtrl |= SD0_DLL_RST;
-		} else {
-		    DllCtrl &= ~SD0_DLL_RST;
-		}
-	    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL, DllCtrl);
+        DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL);
+        if (EnRst == 1U) {
+            DllCtrl |= SD0_DLL_RST;
+        } else {
+            DllCtrl &= ~SD0_DLL_RST;
+        }
+        XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL, DllCtrl);
 #endif
-	} else {
+    } else {
 #endif /* XPAR_PSU_SD_0_DEVICE_ID */
-		(void) DeviceId;
+        (void) DeviceId;
 #if EL1_NONSECURE && defined (__aarch64__)
-		(void)DllCtrl;
+        (void)DllCtrl;
 
-	    XSdps_Smc(InstancePtr, SD_DLL_CTRL, SD1_DLL_RST, (EnRst == 1U) ? SD1_DLL_RST : 0U);
+        XSdps_Smc(InstancePtr, SD_DLL_CTRL, SD1_DLL_RST, (EnRst == 1U) ? SD1_DLL_RST : 0U);
 #else
-	    DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL);
-	    if (EnRst == 1U) {
-		    DllCtrl |= SD1_DLL_RST;
-		} else {
-		    DllCtrl &= ~SD1_DLL_RST;
-		}
-	    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL, DllCtrl);
+        DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL);
+        if (EnRst == 1U) {
+            DllCtrl |= SD1_DLL_RST;
+        } else {
+            DllCtrl &= ~SD1_DLL_RST;
+        }
+        XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL, DllCtrl);
 #endif
 #ifdef XPAR_PSU_SD_0_DEVICE_ID
-	}
+    }
 #endif
 #endif
 }
@@ -1195,7 +1195,7 @@ void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst)
 *
 * @return    None
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 void XSdPs_ConfigTapDelay(XSdPs *InstancePtr)
@@ -1211,99 +1211,99 @@ void XSdPs_ConfigTapDelay(XSdPs *InstancePtr)
     OTapDelay = InstancePtr->OTapDelay;
 
 #ifdef versal
-	(void) DeviceId;
+    (void) DeviceId;
     if (ITapDelay) {
-	    TapDelay = SD_ITAPCHGWIN;
-	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
-		/* Program the ITAPDLY */
-	    TapDelay |= SD_ITAPDLYENA;
-	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
-	    TapDelay |= ITapDelay;
-	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
-	    TapDelay &= ~SD_ITAPCHGWIN;
-	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
-	}
+        TapDelay = SD_ITAPCHGWIN;
+        XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
+        /* Program the ITAPDLY */
+        TapDelay |= SD_ITAPDLYENA;
+        XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
+        TapDelay |= ITapDelay;
+        XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
+        TapDelay &= ~SD_ITAPCHGWIN;
+        XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay);
+    }
     if (OTapDelay) {
-		/* Program the OTAPDLY */
-	    TapDelay = SD_OTAPDLYENA;
-	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_OTAPDLY, TapDelay);
-	    TapDelay |= OTapDelay;
-	    XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_OTAPDLY, TapDelay);
-	}
+        /* Program the OTAPDLY */
+        TapDelay = SD_OTAPDLYENA;
+        XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_OTAPDLY, TapDelay);
+        TapDelay |= OTapDelay;
+        XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_OTAPDLY, TapDelay);
+    }
 #else
 #ifdef XPAR_PSU_SD_0_DEVICE_ID
     if (DeviceId == 0U) {
 #if EL1_NONSECURE && defined (__aarch64__)
-		(void)TapDelay;
-	    if (ITapDelay) {
-		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPCHGWIN, SD0_ITAPCHGWIN);
-		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPDLYENA, SD0_ITAPDLYENA);
-		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPDLY_SEL_MASK, ITapDelay);
-		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPCHGWIN, 0U);
-		}
-	    if (OTapDelay) {
-		    XSdps_Smc(InstancePtr, SD_OTAPDLY, SD0_OTAPDLY_SEL_MASK, OTapDelay);
-		}
+        (void)TapDelay;
+        if (ITapDelay) {
+            XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPCHGWIN, SD0_ITAPCHGWIN);
+            XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPDLYENA, SD0_ITAPDLYENA);
+            XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPDLY_SEL_MASK, ITapDelay);
+            XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPCHGWIN, 0U);
+        }
+        if (OTapDelay) {
+            XSdps_Smc(InstancePtr, SD_OTAPDLY, SD0_OTAPDLY_SEL_MASK, OTapDelay);
+        }
 #else
-	    if (ITapDelay) {
-		    TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY);
-		    TapDelay |= SD0_ITAPCHGWIN;
-		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-			/* Program the ITAPDLY */
-		    TapDelay |= SD0_ITAPDLYENA;
-		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-		    TapDelay |= ITapDelay;
-		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-		    TapDelay &= ~SD0_ITAPCHGWIN;
-		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-		}
-	    if (OTapDelay) {
-			/* Program the OTAPDLY */
-		    TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY);
-		    TapDelay &= ~SD0_OTAPDLY_SEL_MASK;
-		    TapDelay |= OTapDelay;
-		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay);
-		}
+        if (ITapDelay) {
+            TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY);
+            TapDelay |= SD0_ITAPCHGWIN;
+            XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+            /* Program the ITAPDLY */
+            TapDelay |= SD0_ITAPDLYENA;
+            XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+            TapDelay |= ITapDelay;
+            XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+            TapDelay &= ~SD0_ITAPCHGWIN;
+            XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+        }
+        if (OTapDelay) {
+            /* Program the OTAPDLY */
+            TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY);
+            TapDelay &= ~SD0_OTAPDLY_SEL_MASK;
+            TapDelay |= OTapDelay;
+            XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay);
+        }
 #endif
-	} else {
+    } else {
 #endif
-		(void) DeviceId;
-	    ITapDelay = ITapDelay << 16U;
-	    OTapDelay = OTapDelay << 16U;
+        (void) DeviceId;
+        ITapDelay = ITapDelay << 16U;
+        OTapDelay = OTapDelay << 16U;
 #if EL1_NONSECURE && defined (__aarch64__)
-		(void)TapDelay;
-	    if (ITapDelay) {
-		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPCHGWIN, SD1_ITAPCHGWIN);
-		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPDLYENA, SD1_ITAPDLYENA);
-		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPDLY_SEL_MASK, ITapDelay);
-		    XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPCHGWIN, 0U);
-		}
-	    if (OTapDelay) {
-		    XSdps_Smc(InstancePtr, SD_OTAPDLY, SD1_OTAPDLY_SEL_MASK, OTapDelay);
-		}
+        (void)TapDelay;
+        if (ITapDelay) {
+            XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPCHGWIN, SD1_ITAPCHGWIN);
+            XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPDLYENA, SD1_ITAPDLYENA);
+            XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPDLY_SEL_MASK, ITapDelay);
+            XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPCHGWIN, 0U);
+        }
+        if (OTapDelay) {
+            XSdps_Smc(InstancePtr, SD_OTAPDLY, SD1_OTAPDLY_SEL_MASK, OTapDelay);
+        }
 #else
-	    if (ITapDelay) {
-		    TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY);
-		    TapDelay |= SD1_ITAPCHGWIN;
-		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-			/* Program the ITAPDLY */
-		    TapDelay |= SD1_ITAPDLYENA;
-		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-		    TapDelay |= ITapDelay;
-		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-		    TapDelay &= ~SD1_ITAPCHGWIN;
-		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
-		}
-	    if (OTapDelay) {
-			/* Program the OTAPDLY */
-		    TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY);
-		    TapDelay &= ~SD1_OTAPDLY_SEL_MASK;
-		    TapDelay |= OTapDelay;
-		    XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay);
-		}
+        if (ITapDelay) {
+            TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY);
+            TapDelay |= SD1_ITAPCHGWIN;
+            XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+            /* Program the ITAPDLY */
+            TapDelay |= SD1_ITAPDLYENA;
+            XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+            TapDelay |= ITapDelay;
+            XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+            TapDelay &= ~SD1_ITAPCHGWIN;
+            XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay);
+        }
+        if (OTapDelay) {
+            /* Program the OTAPDLY */
+            TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY);
+            TapDelay &= ~SD1_OTAPDLY_SEL_MASK;
+            TapDelay |= OTapDelay;
+            XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay);
+        }
 #endif
 #ifdef XPAR_PSU_SD_0_DEVICE_ID
-	}
+    }
 #endif
 #endif /* versal */
 }
@@ -1316,8 +1316,8 @@ void XSdPs_ConfigTapDelay(XSdPs *InstancePtr)
 * @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
-* 		- XST_SUCCESS if successful
-* 		- XST_FAILURE if failure
+*         - XST_SUCCESS if successful
+*         - XST_FAILURE if failure
 *
 ******************************************************************************/
 s32 XSdPs_SetVoltage18(XSdPs *InstancePtr)
@@ -1325,21 +1325,21 @@ s32 XSdPs_SetVoltage18(XSdPs *InstancePtr)
     s32 Status;
     u16 CtrlReg;
 
-	/* Enabling 1.8V in controller */
+    /* Enabling 1.8V in controller */
     CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_HOST_CTRL2_OFFSET);
+            XSDPS_HOST_CTRL2_OFFSET);
     CtrlReg |= XSDPS_HC2_1V8_EN_MASK;
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_HOST_CTRL2_OFFSET,
-		    CtrlReg);
+            CtrlReg);
 
-	/* Wait minimum 5mSec */
-	(void)usleep(5000U);
+    /* Wait minimum 5mSec */
+    (void)usleep(5000U);
 
-	/* Check for 1.8V signal enable bit is cleared by Host */
+    /* Check for 1.8V signal enable bit is cleared by Host */
     Status = XSdPs_CheckVoltage18(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     return Status;
 }
@@ -1359,19 +1359,19 @@ void XSdPs_ConfigPower(XSdPs *InstancePtr)
     u8 PowerLevel;
 
     if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V3_MASK) != 0U) {
-	    PowerLevel = XSDPS_PC_BUS_VSEL_3V3_MASK;
-	} else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V0_MASK) != 0U) {
-	    PowerLevel = XSDPS_PC_BUS_VSEL_3V0_MASK;
-	} else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_1V8_MASK) != 0U) {
-	    PowerLevel = XSDPS_PC_BUS_VSEL_1V8_MASK;
-	} else {
-	    PowerLevel = 0U;
-	}
+        PowerLevel = XSDPS_PC_BUS_VSEL_3V3_MASK;
+    } else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V0_MASK) != 0U) {
+        PowerLevel = XSDPS_PC_BUS_VSEL_3V0_MASK;
+    } else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_1V8_MASK) != 0U) {
+        PowerLevel = XSDPS_PC_BUS_VSEL_1V8_MASK;
+    } else {
+        PowerLevel = 0U;
+    }
 
-	/* Select voltage based on capability and enable bus power. */
+    /* Select voltage based on capability and enable bus power. */
     XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-		    XSDPS_POWER_CTRL_OFFSET,
-		    PowerLevel | XSDPS_PC_BUS_PWR_MASK);
+            XSDPS_POWER_CTRL_OFFSET,
+            PowerLevel | XSDPS_PC_BUS_PWR_MASK);
 }
 
 /*****************************************************************************/
@@ -1387,16 +1387,16 @@ void XSdPs_ConfigPower(XSdPs *InstancePtr)
 void XSdPs_ConfigDma(XSdPs *InstancePtr)
 {
     if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-		/* Enable ADMA2 in 64bit mode. */
-	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			    XSDPS_HOST_CTRL1_OFFSET,
-			    XSDPS_HC_DMA_ADMA2_64_MASK);
-	} else {
-		/* Enable ADMA2 in 32bit mode. */
-	    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			    XSDPS_HOST_CTRL1_OFFSET,
-			    XSDPS_HC_DMA_ADMA2_32_MASK);
-	}
+        /* Enable ADMA2 in 64bit mode. */
+        XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                XSDPS_HOST_CTRL1_OFFSET,
+                XSDPS_HC_DMA_ADMA2_64_MASK);
+    } else {
+        /* Enable ADMA2 in 32bit mode. */
+        XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                XSDPS_HOST_CTRL1_OFFSET,
+                XSDPS_HC_DMA_ADMA2_32_MASK);
+    }
 }
 
 /*****************************************************************************/
@@ -1411,20 +1411,20 @@ void XSdPs_ConfigDma(XSdPs *InstancePtr)
 ******************************************************************************/
 void XSdPs_ConfigInterrupt(XSdPs *InstancePtr)
 {
-	/* Enable all interrupt status except card interrupt initially */
+    /* Enable all interrupt status except card interrupt initially */
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_NORM_INTR_STS_EN_OFFSET,
-		    XSDPS_NORM_INTR_ALL_MASK & (~XSDPS_INTR_CARD_MASK));
+            XSDPS_NORM_INTR_STS_EN_OFFSET,
+            XSDPS_NORM_INTR_ALL_MASK & (~XSDPS_INTR_CARD_MASK));
 
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_ERR_INTR_STS_EN_OFFSET,
-		    XSDPS_ERROR_INTR_ALL_MASK);
+            XSDPS_ERR_INTR_STS_EN_OFFSET,
+            XSDPS_ERROR_INTR_ALL_MASK);
 
-	/* Disable all interrupt signals by default. */
+    /* Disable all interrupt signals by default. */
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_NORM_INTR_SIG_EN_OFFSET, 0x0U);
+            XSDPS_NORM_INTR_SIG_EN_OFFSET, 0x0U);
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_ERR_INTR_SIG_EN_OFFSET, 0x0U);
+            XSDPS_ERR_INTR_SIG_EN_OFFSET, 0x0U);
 
 }
 
@@ -1435,13 +1435,13 @@ void XSdPs_ConfigInterrupt(XSdPs *InstancePtr)
 * @param    InstancePtr is a pointer to the instance to be worked on.
 * @param    Cmd is the command to be sent.
 * @param    Arg is the argument to be sent along with the command.
-* 	    This could be address or any other information
+*         This could be address or any other information
 * @param    BlkCnt - Block count passed by the user.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because another transfer
-* 		    is in progress or command or data inhibit is set
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because another transfer
+*             is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt)
@@ -1452,53 +1452,53 @@ s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt)
 
     Status = XSdPs_SetupCmd(InstancePtr, Arg, BlkCnt);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XSdPs_SendCmd(InstancePtr, Cmd);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Polling for response for now */
+    /* Polling for response for now */
     do {
-	    StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				    XSDPS_NORM_INTR_STS_OFFSET);
-	    if ((Cmd == CMD21) || (Cmd == CMD19)) {
-		    if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				    XSDPS_NORM_INTR_STS_OFFSET) & XSDPS_INTR_BRR_MASK) != 0U){
-			    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-				    XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_BRR_MASK);
-			    break;
-			}
-		}
+        StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                    XSDPS_NORM_INTR_STS_OFFSET);
+        if ((Cmd == CMD21) || (Cmd == CMD19)) {
+            if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                    XSDPS_NORM_INTR_STS_OFFSET) & XSDPS_INTR_BRR_MASK) != 0U){
+                XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                    XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_BRR_MASK);
+                break;
+            }
+        }
 
-	    if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
-		    Status = (s32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-								    XSDPS_ERR_INTR_STS_OFFSET);
-		    if (((u32)Status & ~XSDPS_INTR_ERR_CT_MASK) == 0U) {
-			    Status = XSDPS_CT_ERROR;
-			}
-			 /* Write to clear error bits */
-		    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-				    XSDPS_ERR_INTR_STS_OFFSET,
-				    XSDPS_ERROR_INTR_ALL_MASK);
-		    goto RETURN_PATH;
-		}
-	    Timeout = Timeout - 1U;
-	} while (((StatusReg & XSDPS_INTR_CC_MASK) == 0U)
-				&& (Timeout != 0U));
-	/* Write to clear bit */
+        if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
+            Status = (s32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                                    XSDPS_ERR_INTR_STS_OFFSET);
+            if (((u32)Status & ~XSDPS_INTR_ERR_CT_MASK) == 0U) {
+                Status = XSDPS_CT_ERROR;
+            }
+             /* Write to clear error bits */
+            XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                    XSDPS_ERR_INTR_STS_OFFSET,
+                    XSDPS_ERROR_INTR_ALL_MASK);
+            goto RETURN_PATH;
+        }
+        Timeout = Timeout - 1U;
+    } while (((StatusReg & XSDPS_INTR_CC_MASK) == 0U)
+                && (Timeout != 0U));
+    /* Write to clear bit */
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_NORM_INTR_STS_OFFSET,
-		    XSDPS_INTR_CC_MASK);
+            XSDPS_NORM_INTR_STS_OFFSET,
+            XSDPS_INTR_CC_MASK);
 
     Status = XST_SUCCESS;
 
 RETURN_PATH:
-	    return Status;
+        return Status;
 
 }
 
@@ -1517,34 +1517,34 @@ s32 XSdps_CheckTransferDone(XSdPs *InstancePtr)
     u16 StatusReg;
     s32 Status;
 
-	/*
-	 * Check for transfer complete
-	 * Polling for response for now
-	 */
+    /*
+     * Check for transfer complete
+     * Polling for response for now
+     */
     do {
-	    StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				    XSDPS_NORM_INTR_STS_OFFSET);
-	    if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
-			/* Write to clear error bits */
-		    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-				    XSDPS_ERR_INTR_STS_OFFSET,
-				    XSDPS_ERROR_INTR_ALL_MASK);
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	    Timeout = Timeout - 1U;
-	    usleep(1);
-	} while (((StatusReg & XSDPS_INTR_TC_MASK) == 0U)
-			&& (Timeout != 0U));
+        StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                    XSDPS_NORM_INTR_STS_OFFSET);
+        if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
+            /* Write to clear error bits */
+            XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                    XSDPS_ERR_INTR_STS_OFFSET,
+                    XSDPS_ERROR_INTR_ALL_MASK);
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+        Timeout = Timeout - 1U;
+        usleep(1);
+    } while (((StatusReg & XSDPS_INTR_TC_MASK) == 0U)
+            && (Timeout != 0U));
 
     if (Timeout == 0U) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
-	/* Write to clear bit */
+    /* Write to clear bit */
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-		    XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
+            XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
 
     Status = XST_SUCCESS;
 
@@ -1571,23 +1571,23 @@ s32 XSdPs_CheckBusIdle(XSdPs *InstancePtr, u32 Value)
     s32 Status;
 
     PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-		    XSDPS_PRES_STATE_OFFSET);
-	/* Check for Card Present */
+            XSDPS_PRES_STATE_OFFSET);
+    /* Check for Card Present */
     if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) != 0U) {
-		/* Check for SD idle */
-	    do {
-		    StatusReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-				    XSDPS_PRES_STATE_OFFSET);
-		    Timeout = Timeout - 1;
-		    usleep(1);
-		} while (((StatusReg & Value) != 0U)
-				&& (Timeout != 0U));
-	}
+        /* Check for SD idle */
+        do {
+            StatusReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XSDPS_PRES_STATE_OFFSET);
+            Timeout = Timeout - 1;
+            usleep(1);
+        } while (((StatusReg & Value) != 0U)
+                && (Timeout != 0U));
+    }
 
     if (Timeout == 0U) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
     Status = XST_SUCCESS;
 
@@ -1608,7 +1608,7 @@ RETURN_PATH:
 * @param    Cmd is the Command to be sent.
 *
 * @return    Command register value complete with response type and
-* 	    data, CRC and index related flags.
+*         data, CRC and index related flags.
 *
 ******************************************************************************/
 u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd)
@@ -1619,181 +1619,181 @@ u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd)
 #if 0
     switch(Cmd) {
     case CMD0:
-	    RetVal |= RESP_NONE;
-	    break;
+        RetVal |= RESP_NONE;
+        break;
     case CMD1:
-	    RetVal |= RESP_R3;
-	    break;
+        RetVal |= RESP_R3;
+        break;
     case CMD2:
-	    RetVal |= RESP_R2;
-	    break;
+        RetVal |= RESP_R2;
+        break;
     case CMD3:
-	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		    RetVal |= RESP_R6;
-		} else {
-		    RetVal |= RESP_R1;
-		}
-	    break;
+        if (InstancePtr->CardType == XSDPS_CARD_SD) {
+            RetVal |= RESP_R6;
+        } else {
+            RetVal |= RESP_R1;
+        }
+        break;
     case CMD4:
-	    RetVal |= RESP_NONE;
-	    break;
+        RetVal |= RESP_NONE;
+        break;
     case CMD5:
-	    RetVal |= RESP_R1B;
-	    break;
+        RetVal |= RESP_R1B;
+        break;
     case CMD6:
-	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		} else {
-		    RetVal |= RESP_R1B;
-		}
-	    break;
+        if (InstancePtr->CardType == XSDPS_CARD_SD) {
+            RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        } else {
+            RetVal |= RESP_R1B;
+        }
+        break;
     case ACMD6:
-	    RetVal |= RESP_R1;
-	    break;
+        RetVal |= RESP_R1;
+        break;
     case CMD7:
-	    RetVal |= RESP_R1;
-	    break;
+        RetVal |= RESP_R1;
+        break;
     case CMD8:
-	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		    RetVal |= RESP_R1;
-		} else {
-		    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		}
-	    break;
+        if (InstancePtr->CardType == XSDPS_CARD_SD) {
+            RetVal |= RESP_R1;
+        } else {
+            RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        }
+        break;
     case CMD9:
-	    RetVal |= RESP_R2;
-	    break;
+        RetVal |= RESP_R2;
+        break;
     case CMD11:
     case CMD10:
     case CMD12:
-	    RetVal |= RESP_R1;
-	    break;
+        RetVal |= RESP_R1;
+        break;
     case ACMD13:
-	    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-	    break;
+        RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        break;
     case CMD16:
-	    RetVal |= RESP_R1;
-	    break;
+        RetVal |= RESP_R1;
+        break;
     case CMD17:
     case CMD18:
     case CMD19:
     case CMD21:
-	    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-	    break;
+        RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        break;
     case CMD23:
     case ACMD23:
     case CMD24:
     case CMD25:
-	    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-	    break;
+        RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        break;
     case ACMD41:
-	    RetVal |= RESP_R3;
-	    break;
+        RetVal |= RESP_R3;
+        break;
     case ACMD42:
-	    RetVal |= RESP_R1;
-	    break;
+        RetVal |= RESP_R1;
+        break;
     case ACMD51:
-	    RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-	    break;
+        RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        break;
     case CMD52:
     case CMD55:
-	    RetVal |= RESP_R1;
-	    break;
+        RetVal |= RESP_R1;
+        break;
     case CMD58:
-	    break;
+        break;
     default :
-	    RetVal |= Cmd;
-	    break;
-	}
+        RetVal |= Cmd;
+        break;
+    }
 #else
     switch(Cmd) {
     case CMD0:
-	    RetVal |= XSDPS_RESP_NONE;
-	    break;
+        RetVal |= XSDPS_RESP_NONE;
+        break;
     case CMD1:
-	    RetVal |= XSDPS_RESP_R3;
-	    break;
+        RetVal |= XSDPS_RESP_R3;
+        break;
     case CMD2:
-	    RetVal |= XSDPS_RESP_R2;
-	    break;
+        RetVal |= XSDPS_RESP_R2;
+        break;
     case CMD3:
-	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		    RetVal |= XSDPS_RESP_R6;
-		} else {
-		    RetVal |= XSDPS_RESP_R1;
-		}
-	    break;
+        if (InstancePtr->CardType == XSDPS_CARD_SD) {
+            RetVal |= XSDPS_RESP_R6;
+        } else {
+            RetVal |= XSDPS_RESP_R1;
+        }
+        break;
     case CMD4:
-	    RetVal |= XSDPS_RESP_NONE;
-	    break;
+        RetVal |= XSDPS_RESP_NONE;
+        break;
     case CMD5:
-	    RetVal |= XSDPS_RESP_R1B;
-	    break;
+        RetVal |= XSDPS_RESP_R1B;
+        break;
     case CMD6:
-	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		} else {
-		    RetVal |= XSDPS_RESP_R1B;
-		}
-	    break;
+        if (InstancePtr->CardType == XSDPS_CARD_SD) {
+            RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        } else {
+            RetVal |= XSDPS_RESP_R1B;
+        }
+        break;
     case ACMD6:
-	    RetVal |= XSDPS_RESP_R1;
-	    break;
+        RetVal |= XSDPS_RESP_R1;
+        break;
     case CMD7:
-	    RetVal |= XSDPS_RESP_R1;
-	    break;
+        RetVal |= XSDPS_RESP_R1;
+        break;
     case CMD8:
-	    if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		    RetVal |= XSDPS_RESP_R1;
-		} else {
-		    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-		}
-	    break;
+        if (InstancePtr->CardType == XSDPS_CARD_SD) {
+            RetVal |= XSDPS_RESP_R1;
+        } else {
+            RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        }
+        break;
     case CMD9:
-	    RetVal |= XSDPS_RESP_R2;
-	    break;
+        RetVal |= XSDPS_RESP_R2;
+        break;
     case CMD11:
     case CMD10:
     case CMD12:
-	    RetVal |= XSDPS_RESP_R1;
-	    break;
+        RetVal |= XSDPS_RESP_R1;
+        break;
     case ACMD13:
-	    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-	    break;
+        RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        break;
     case CMD16:
-	    RetVal |= XSDPS_RESP_R1;
-	    break;
+        RetVal |= XSDPS_RESP_R1;
+        break;
     case CMD17:
     case CMD18:
     case CMD19:
     case CMD21:
-	    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-	    break;
+        RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        break;
     case CMD23:
     case ACMD23:
     case CMD24:
     case CMD25:
-	    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-	    break;
+        RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        break;
     case ACMD41:
-	    RetVal |= XSDPS_RESP_R3;
-	    break;
+        RetVal |= XSDPS_RESP_R3;
+        break;
     case ACMD42:
-	    RetVal |= XSDPS_RESP_R1;
-	    break;
+        RetVal |= XSDPS_RESP_R1;
+        break;
     case ACMD51:
-	    RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
-	    break;
+        RetVal |= XSDPS_RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
+        break;
     case CMD52:
     case CMD55:
-	    RetVal |= XSDPS_RESP_R1;
-	    break;
+        RetVal |= XSDPS_RESP_R1;
+        break;
     case CMD58:
-	    break;
+        break;
     default :
-	    RetVal |= Cmd;
-	    break;
-	}
+        RetVal |= Cmd;
+        break;
+    }
 #endif
     return RetVal;
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h
index 21582fdee2..4038ac5454 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h
@@ -20,7 +20,7 @@
 * Ver   Who    Date     Changes
 * ----- ---    -------- -----------------------------------------------
 * 1.00a hk/sg  10/17/13 Initial release
-* 2.5     sg	   07/09/15 Added SD 3.0 features
+* 2.5     sg       07/09/15 Added SD 3.0 features
 *       kvn    07/15/15 Modified the code according to MISRAC-2012.
 * 2.7   sk     12/10/15 Added support for MMC cards.
 *       sk     03/02/16 Configured the Tap Delay values for eMMC HS200 mode.
@@ -67,122 +67,122 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_SDMA_SYS_ADDR_OFFSET    0x00U	/**< SDMA System Address
-						    Register */
+#define XSDPS_SDMA_SYS_ADDR_OFFSET    0x00U    /**< SDMA System Address
+                            Register */
 #define XSDPS_SDMA_SYS_ADDR_LO_OFFSET    XSDPS_SDMA_SYS_ADDR_OFFSET
-						/**< SDMA System Address
-						    Low Register */
-#define XSDPS_ARGMT2_LO_OFFSET	    0x00U	/**< Argument2 Low Register */
-#define XSDPS_SDMA_SYS_ADDR_HI_OFFSET    0x02U	/**< SDMA System Address
-						    High Register */
-#define XSDPS_ARGMT2_HI_OFFSET	    0x02U	/**< Argument2 High Register */
+                        /**< SDMA System Address
+                            Low Register */
+#define XSDPS_ARGMT2_LO_OFFSET        0x00U    /**< Argument2 Low Register */
+#define XSDPS_SDMA_SYS_ADDR_HI_OFFSET    0x02U    /**< SDMA System Address
+                            High Register */
+#define XSDPS_ARGMT2_HI_OFFSET        0x02U    /**< Argument2 High Register */
 
-#define XSDPS_BLK_SIZE_OFFSET	    0x04U	/**< Block Size Register */
-#define XSDPS_BLK_CNT_OFFSET	    0x06U	/**< Block Count Register */
-#define XSDPS_ARGMT_OFFSET	    0x08U	/**< Argument Register */
-#define XSDPS_ARGMT1_LO_OFFSET	    XSDPS_ARGMT_OFFSET
-						/**< Argument1 Register */
-#define XSDPS_ARGMT1_HI_OFFSET	    0x0AU	/**< Argument1 Register */
+#define XSDPS_BLK_SIZE_OFFSET        0x04U    /**< Block Size Register */
+#define XSDPS_BLK_CNT_OFFSET        0x06U    /**< Block Count Register */
+#define XSDPS_ARGMT_OFFSET        0x08U    /**< Argument Register */
+#define XSDPS_ARGMT1_LO_OFFSET        XSDPS_ARGMT_OFFSET
+                        /**< Argument1 Register */
+#define XSDPS_ARGMT1_HI_OFFSET        0x0AU    /**< Argument1 Register */
 
-#define XSDPS_XFER_MODE_OFFSET	    0x0CU	/**< Transfer Mode Register */
-#define XSDPS_CMD_OFFSET	    0x0EU	/**< Command Register */
-#define XSDPS_RESP0_OFFSET	    0x10U	/**< Response0 Register */
-#define XSDPS_RESP1_OFFSET	    0x14U	/**< Response1 Register */
-#define XSDPS_RESP2_OFFSET	    0x18U	/**< Response2 Register */
-#define XSDPS_RESP3_OFFSET	    0x1CU	/**< Response3 Register */
-#define XSDPS_BUF_DAT_PORT_OFFSET    0x20U	/**< Buffer Data Port */
-#define XSDPS_PRES_STATE_OFFSET	    0x24U	/**< Present State */
-#define XSDPS_HOST_CTRL1_OFFSET	    0x28U	/**< Host Control 1 */
-#define XSDPS_POWER_CTRL_OFFSET	    0x29U	/**< Power Control */
-#define XSDPS_BLK_GAP_CTRL_OFFSET    0x2AU	/**< Block Gap Control */
-#define XSDPS_WAKE_UP_CTRL_OFFSET    0x2BU	/**< Wake Up Control */
-#define XSDPS_CLK_CTRL_OFFSET	    0x2CU	/**< Clock Control */
-#define XSDPS_TIMEOUT_CTRL_OFFSET    0x2EU	/**< Timeout Control */
-#define XSDPS_SW_RST_OFFSET	    0x2FU	/**< Software Reset */
-#define XSDPS_NORM_INTR_STS_OFFSET     0x30U	/**< Normal Interrupt
-						    Status Register */
-#define XSDPS_ERR_INTR_STS_OFFSET     0x32U	/**< Error Interrupt
-						    Status Register */
-#define XSDPS_NORM_INTR_STS_EN_OFFSET    0x34U	/**< Normal Interrupt
-					    Status Enable Register */
-#define XSDPS_ERR_INTR_STS_EN_OFFSET    0x36U	/**< Error Interrupt
-					    Status Enable Register */
-#define XSDPS_NORM_INTR_SIG_EN_OFFSET    0x38U	/**< Normal Interrupt
-					    Signal Enable Register */
-#define XSDPS_ERR_INTR_SIG_EN_OFFSET    0x3AU	/**< Error Interrupt
-					    Signal Enable Register */
+#define XSDPS_XFER_MODE_OFFSET        0x0CU    /**< Transfer Mode Register */
+#define XSDPS_CMD_OFFSET        0x0EU    /**< Command Register */
+#define XSDPS_RESP0_OFFSET        0x10U    /**< Response0 Register */
+#define XSDPS_RESP1_OFFSET        0x14U    /**< Response1 Register */
+#define XSDPS_RESP2_OFFSET        0x18U    /**< Response2 Register */
+#define XSDPS_RESP3_OFFSET        0x1CU    /**< Response3 Register */
+#define XSDPS_BUF_DAT_PORT_OFFSET    0x20U    /**< Buffer Data Port */
+#define XSDPS_PRES_STATE_OFFSET        0x24U    /**< Present State */
+#define XSDPS_HOST_CTRL1_OFFSET        0x28U    /**< Host Control 1 */
+#define XSDPS_POWER_CTRL_OFFSET        0x29U    /**< Power Control */
+#define XSDPS_BLK_GAP_CTRL_OFFSET    0x2AU    /**< Block Gap Control */
+#define XSDPS_WAKE_UP_CTRL_OFFSET    0x2BU    /**< Wake Up Control */
+#define XSDPS_CLK_CTRL_OFFSET        0x2CU    /**< Clock Control */
+#define XSDPS_TIMEOUT_CTRL_OFFSET    0x2EU    /**< Timeout Control */
+#define XSDPS_SW_RST_OFFSET        0x2FU    /**< Software Reset */
+#define XSDPS_NORM_INTR_STS_OFFSET     0x30U    /**< Normal Interrupt
+                            Status Register */
+#define XSDPS_ERR_INTR_STS_OFFSET     0x32U    /**< Error Interrupt
+                            Status Register */
+#define XSDPS_NORM_INTR_STS_EN_OFFSET    0x34U    /**< Normal Interrupt
+                        Status Enable Register */
+#define XSDPS_ERR_INTR_STS_EN_OFFSET    0x36U    /**< Error Interrupt
+                        Status Enable Register */
+#define XSDPS_NORM_INTR_SIG_EN_OFFSET    0x38U    /**< Normal Interrupt
+                        Signal Enable Register */
+#define XSDPS_ERR_INTR_SIG_EN_OFFSET    0x3AU    /**< Error Interrupt
+                        Signal Enable Register */
 
-#define XSDPS_AUTO_CMD12_ERR_STS_OFFSET    0x3CU	/**< Auto CMD12 Error Status
-						    Register */
-#define XSDPS_HOST_CTRL2_OFFSET	    0x3EU	/**< Host Control2 Register */
-#define XSDPS_CAPS_OFFSET 	    0x40U	/**< Capabilities Register */
-#define XSDPS_CAPS_EXT_OFFSET 	    0x44U	/**< Capabilities Extended */
-#define XSDPS_MAX_CURR_CAPS_OFFSET    0x48U	/**< Maximum Current
-					    Capabilities Register */
-#define XSDPS_MAX_CURR_CAPS_EXT_OFFSET    0x4CU	/**< Maximum Current
-					    Capabilities Ext Register */
-#define XSDPS_FE_ERR_INT_STS_OFFSET    0x52U	/**< Force Event for
-					    Error Interrupt Status */
-#define XSDPS_FE_AUTO_CMD12_EIS_OFFSET    0x50U	/**< Auto CM12 Error Interrupt
-						    Status Register */
-#define XSDPS_ADMA_ERR_STS_OFFSET    0x54U	/**< ADMA Error Status
-						    Register */
-#define XSDPS_ADMA_SAR_OFFSET	    0x58U	/**< ADMA System Address
-						    Register */
-#define XSDPS_ADMA_SAR_EXT_OFFSET    0x5CU	/**< ADMA System Address
-						    Extended Register */
-#define XSDPS_PRE_VAL_1_OFFSET	    0x60U	/**< Preset Value Register */
-#define XSDPS_PRE_VAL_2_OFFSET	    0x64U	/**< Preset Value Register */
-#define XSDPS_PRE_VAL_3_OFFSET	    0x68U	/**< Preset Value Register */
-#define XSDPS_PRE_VAL_4_OFFSET	    0x6CU	/**< Preset Value Register */
-#define XSDPS_BOOT_TOUT_CTRL_OFFSET    0x70U	/**< Boot timeout control
-						    register */
+#define XSDPS_AUTO_CMD12_ERR_STS_OFFSET    0x3CU    /**< Auto CMD12 Error Status
+                            Register */
+#define XSDPS_HOST_CTRL2_OFFSET        0x3EU    /**< Host Control2 Register */
+#define XSDPS_CAPS_OFFSET         0x40U    /**< Capabilities Register */
+#define XSDPS_CAPS_EXT_OFFSET         0x44U    /**< Capabilities Extended */
+#define XSDPS_MAX_CURR_CAPS_OFFSET    0x48U    /**< Maximum Current
+                        Capabilities Register */
+#define XSDPS_MAX_CURR_CAPS_EXT_OFFSET    0x4CU    /**< Maximum Current
+                        Capabilities Ext Register */
+#define XSDPS_FE_ERR_INT_STS_OFFSET    0x52U    /**< Force Event for
+                        Error Interrupt Status */
+#define XSDPS_FE_AUTO_CMD12_EIS_OFFSET    0x50U    /**< Auto CM12 Error Interrupt
+                            Status Register */
+#define XSDPS_ADMA_ERR_STS_OFFSET    0x54U    /**< ADMA Error Status
+                            Register */
+#define XSDPS_ADMA_SAR_OFFSET        0x58U    /**< ADMA System Address
+                            Register */
+#define XSDPS_ADMA_SAR_EXT_OFFSET    0x5CU    /**< ADMA System Address
+                            Extended Register */
+#define XSDPS_PRE_VAL_1_OFFSET        0x60U    /**< Preset Value Register */
+#define XSDPS_PRE_VAL_2_OFFSET        0x64U    /**< Preset Value Register */
+#define XSDPS_PRE_VAL_3_OFFSET        0x68U    /**< Preset Value Register */
+#define XSDPS_PRE_VAL_4_OFFSET        0x6CU    /**< Preset Value Register */
+#define XSDPS_BOOT_TOUT_CTRL_OFFSET    0x70U    /**< Boot timeout control
+                            register */
 
-#define XSDPS_SHARED_BUS_CTRL_OFFSET    0xE0U	/**< Shared Bus Control
-						    Register */
-#define XSDPS_SLOT_INTR_STS_OFFSET    0xFCU	/**< Slot Interrupt Status
-						    Register */
-#define XSDPS_HOST_CTRL_VER_OFFSET    0xFEU	/**< Host Controller Version
-						    Register */
+#define XSDPS_SHARED_BUS_CTRL_OFFSET    0xE0U    /**< Shared Bus Control
+                            Register */
+#define XSDPS_SLOT_INTR_STS_OFFSET    0xFCU    /**< Slot Interrupt Status
+                            Register */
+#define XSDPS_HOST_CTRL_VER_OFFSET    0xFEU    /**< Host Controller Version
+                            Register */
 
 /* @} */
 
 /** @name Control Register - Host control, Power control,
- * 		    Block Gap control and Wakeup control
+ *             Block Gap control and Wakeup control
  *
  * This register contains bits for various configuration options of
  * the SD host controller. Read/Write apart from the reserved bits.
  * @{
  */
 
-#define XSDPS_HC_LED_MASK	    0x00000001U /**< LED Control */
-#define XSDPS_HC_WIDTH_MASK	    0x00000002U /**< Bus width */
-#define XSDPS_HC_BUS_WIDTH_4	    0x00000002U
-#define XSDPS_HC_SPEED_MASK	    0x00000004U /**< High Speed */
-#define XSDPS_HC_DMA_MASK	    0x00000018U /**< DMA Mode Select */
-#define XSDPS_HC_DMA_SDMA_MASK	    0x00000000U /**< SDMA Mode */
-#define XSDPS_HC_DMA_ADMA1_MASK	    0x00000008U /**< ADMA1 Mode */
+#define XSDPS_HC_LED_MASK        0x00000001U /**< LED Control */
+#define XSDPS_HC_WIDTH_MASK        0x00000002U /**< Bus width */
+#define XSDPS_HC_BUS_WIDTH_4        0x00000002U
+#define XSDPS_HC_SPEED_MASK        0x00000004U /**< High Speed */
+#define XSDPS_HC_DMA_MASK        0x00000018U /**< DMA Mode Select */
+#define XSDPS_HC_DMA_SDMA_MASK        0x00000000U /**< SDMA Mode */
+#define XSDPS_HC_DMA_ADMA1_MASK        0x00000008U /**< ADMA1 Mode */
 #define XSDPS_HC_DMA_ADMA2_32_MASK    0x00000010U /**< ADMA2 Mode - 32 bit */
 #define XSDPS_HC_DMA_ADMA2_64_MASK    0x00000018U /**< ADMA2 Mode - 64 bit */
-#define XSDPS_HC_EXT_BUS_WIDTH	    0x00000020U /**< Bus width - 8 bit */
+#define XSDPS_HC_EXT_BUS_WIDTH        0x00000020U /**< Bus width - 8 bit */
 #define XSDPS_HC_CARD_DET_TL_MASK    0x00000040U /**< Card Detect Tst Lvl */
 #define XSDPS_HC_CARD_DET_SD_MASK    0x00000080U /**< Card Detect Sig Det */
 
-#define XSDPS_PC_BUS_PWR_MASK	    0x00000001U /**< Bus Power Control */
-#define XSDPS_PC_BUS_VSEL_MASK	    0x0000000EU /**< Bus Voltage Select */
+#define XSDPS_PC_BUS_PWR_MASK        0x00000001U /**< Bus Power Control */
+#define XSDPS_PC_BUS_VSEL_MASK        0x0000000EU /**< Bus Voltage Select */
 #define XSDPS_PC_BUS_VSEL_3V3_MASK    0x0000000EU /**< Bus Voltage 3.3V */
 #define XSDPS_PC_BUS_VSEL_3V0_MASK    0x0000000CU /**< Bus Voltage 3.0V */
 #define XSDPS_PC_BUS_VSEL_1V8_MASK    0x0000000AU /**< Bus Voltage 1.8V */
 #define XSDPS_PC_EMMC_HW_RST_MASK    0x00000010U /**< HW reset for eMMC */
 
-#define XSDPS_BGC_STP_REQ_MASK	    0x00000001U /**< Block Gap Stop Req */
-#define XSDPS_BGC_CNT_REQ_MASK	    0x00000002U /**< Block Gap Cont Req */
-#define XSDPS_BGC_RWC_MASK	    0x00000004U /**< Block Gap Rd Wait */
-#define XSDPS_BGC_INTR_MASK	    0x00000008U /**< Block Gap Intr */
-#define XSDPS_BGC_SPI_MODE_MASK	    0x00000010U /**< Block Gap SPI Mode */
-#define XSDPS_BGC_BOOT_EN_MASK	    0x00000020U /**< Block Gap Boot Enb */
+#define XSDPS_BGC_STP_REQ_MASK        0x00000001U /**< Block Gap Stop Req */
+#define XSDPS_BGC_CNT_REQ_MASK        0x00000002U /**< Block Gap Cont Req */
+#define XSDPS_BGC_RWC_MASK        0x00000004U /**< Block Gap Rd Wait */
+#define XSDPS_BGC_INTR_MASK        0x00000008U /**< Block Gap Intr */
+#define XSDPS_BGC_SPI_MODE_MASK        0x00000010U /**< Block Gap SPI Mode */
+#define XSDPS_BGC_BOOT_EN_MASK        0x00000020U /**< Block Gap Boot Enb */
 #define XSDPS_BGC_ALT_BOOT_EN_MASK    0x00000040U /**< Block Gap Alt BootEn */
-#define XSDPS_BGC_BOOT_ACK_MASK	    0x00000080U /**< Block Gap Boot Ack */
+#define XSDPS_BGC_BOOT_ACK_MASK        0x00000080U /**< Block Gap Boot Ack */
 
 #define XSDPS_WC_WUP_ON_INTR_MASK    0x00000001U /**< Wakeup Card Intr */
 #define XSDPS_WC_WUP_ON_INSRT_MASK    0x00000002U /**< Wakeup Card Insert */
@@ -198,33 +198,33 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_CC_INT_CLK_EN_MASK	    0x00000001U
+#define XSDPS_CC_INT_CLK_EN_MASK        0x00000001U
 #define XSDPS_CC_INT_CLK_STABLE_MASK    0x00000002U
-#define XSDPS_CC_SD_CLK_EN_MASK		    0x00000004U
-#define XSDPS_CC_SD_CLK_GEN_SEL_MASK	    0x00000020U
+#define XSDPS_CC_SD_CLK_EN_MASK            0x00000004U
+#define XSDPS_CC_SD_CLK_GEN_SEL_MASK        0x00000020U
 #define XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK    0x00000003U
-#define XSDPS_CC_SDCLK_FREQ_SEL_MASK	    0x000000FFU
-#define XSDPS_CC_SDCLK_FREQ_D256_MASK	    0x00008000U
-#define XSDPS_CC_SDCLK_FREQ_D128_MASK	    0x00004000U
-#define XSDPS_CC_SDCLK_FREQ_D64_MASK	    0x00002000U
-#define XSDPS_CC_SDCLK_FREQ_D32_MASK	    0x00001000U
-#define XSDPS_CC_SDCLK_FREQ_D16_MASK	    0x00000800U
-#define XSDPS_CC_SDCLK_FREQ_D8_MASK	    0x00000400U
-#define XSDPS_CC_SDCLK_FREQ_D4_MASK	    0x00000200U
-#define XSDPS_CC_SDCLK_FREQ_D2_MASK	    0x00000100U
+#define XSDPS_CC_SDCLK_FREQ_SEL_MASK        0x000000FFU
+#define XSDPS_CC_SDCLK_FREQ_D256_MASK        0x00008000U
+#define XSDPS_CC_SDCLK_FREQ_D128_MASK        0x00004000U
+#define XSDPS_CC_SDCLK_FREQ_D64_MASK        0x00002000U
+#define XSDPS_CC_SDCLK_FREQ_D32_MASK        0x00001000U
+#define XSDPS_CC_SDCLK_FREQ_D16_MASK        0x00000800U
+#define XSDPS_CC_SDCLK_FREQ_D8_MASK        0x00000400U
+#define XSDPS_CC_SDCLK_FREQ_D4_MASK        0x00000200U
+#define XSDPS_CC_SDCLK_FREQ_D2_MASK        0x00000100U
 #define XSDPS_CC_SDCLK_FREQ_BASE_MASK    0x00000000U
-#define XSDPS_CC_MAX_DIV_CNT		    256U
-#define XSDPS_CC_EXT_MAX_DIV_CNT	    2046U
-#define XSDPS_CC_EXT_DIV_SHIFT		    6U
+#define XSDPS_CC_MAX_DIV_CNT            256U
+#define XSDPS_CC_EXT_MAX_DIV_CNT        2046U
+#define XSDPS_CC_EXT_DIV_SHIFT            6U
 
-#define XSDPS_TC_CNTR_VAL_MASK		    0x0000000FU
+#define XSDPS_TC_CNTR_VAL_MASK            0x0000000FU
 
-#define XSDPS_SWRST_ALL_MASK		    0x00000001U
-#define XSDPS_SWRST_CMD_LINE_MASK	    0x00000002U
-#define XSDPS_SWRST_DAT_LINE_MASK	    0x00000004U
+#define XSDPS_SWRST_ALL_MASK            0x00000001U
+#define XSDPS_SWRST_CMD_LINE_MASK        0x00000002U
+#define XSDPS_SWRST_DAT_LINE_MASK        0x00000004U
 
-#define XSDPS_CC_MAX_NUM_OF_DIV	    9U
-#define XSDPS_CC_DIV_SHIFT	    8U
+#define XSDPS_CC_MAX_NUM_OF_DIV        9U
+#define XSDPS_CC_DIV_SHIFT        8U
 
 /* @} */
 
@@ -251,41 +251,41 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_INTR_CC_MASK	    0x00000001U /**< Command Complete */
-#define XSDPS_INTR_TC_MASK	    0x00000002U /**< Transfer Complete */
-#define XSDPS_INTR_BGE_MASK	    0x00000004U /**< Block Gap Event */
-#define XSDPS_INTR_DMA_MASK	    0x00000008U /**< DMA Interrupt */
-#define XSDPS_INTR_BWR_MASK	    0x00000010U /**< Buffer Write Ready */
-#define XSDPS_INTR_BRR_MASK	    0x00000020U /**< Buffer Read Ready */
+#define XSDPS_INTR_CC_MASK        0x00000001U /**< Command Complete */
+#define XSDPS_INTR_TC_MASK        0x00000002U /**< Transfer Complete */
+#define XSDPS_INTR_BGE_MASK        0x00000004U /**< Block Gap Event */
+#define XSDPS_INTR_DMA_MASK        0x00000008U /**< DMA Interrupt */
+#define XSDPS_INTR_BWR_MASK        0x00000010U /**< Buffer Write Ready */
+#define XSDPS_INTR_BRR_MASK        0x00000020U /**< Buffer Read Ready */
 #define XSDPS_INTR_CARD_INSRT_MASK    0x00000040U /**< Card Insert */
 #define XSDPS_INTR_CARD_REM_MASK    0x00000080U /**< Card Remove */
-#define XSDPS_INTR_CARD_MASK	    0x00000100U /**< Card Interrupt */
-#define XSDPS_INTR_INT_A_MASK	    0x00000200U /**< INT A Interrupt */
-#define XSDPS_INTR_INT_B_MASK	    0x00000400U /**< INT B Interrupt */
-#define XSDPS_INTR_INT_C_MASK	    0x00000800U /**< INT C Interrupt */
+#define XSDPS_INTR_CARD_MASK        0x00000100U /**< Card Interrupt */
+#define XSDPS_INTR_INT_A_MASK        0x00000200U /**< INT A Interrupt */
+#define XSDPS_INTR_INT_B_MASK        0x00000400U /**< INT B Interrupt */
+#define XSDPS_INTR_INT_C_MASK        0x00000800U /**< INT C Interrupt */
 #define XSDPS_INTR_RE_TUNING_MASK    0x00001000U /**< Re-Tuning Interrupt */
 #define XSDPS_INTR_BOOT_ACK_RECV_MASK    0x00002000U /**< Boot Ack Recv
-						    Interrupt */
+                            Interrupt */
 #define XSDPS_INTR_BOOT_TERM_MASK    0x00004000U /**< Boot Terminate
-						    Interrupt */
-#define XSDPS_INTR_ERR_MASK	    0x00008000U /**< Error Interrupt */
+                            Interrupt */
+#define XSDPS_INTR_ERR_MASK        0x00008000U /**< Error Interrupt */
 #define XSDPS_NORM_INTR_ALL_MASK    0x0000FFFFU
 
-#define XSDPS_INTR_ERR_CT_MASK	    0x00000001U /**< Command Timeout
-						    Error */
+#define XSDPS_INTR_ERR_CT_MASK        0x00000001U /**< Command Timeout
+                            Error */
 #define XSDPS_INTR_ERR_CCRC_MASK    0x00000002U /**< Command CRC Error */
-#define XSDPS_INTR_ERR_CEB_MASK	    0x00000004U /**< Command End Bit
-						    Error */
-#define XSDPS_INTR_ERR_CI_MASK	    0x00000008U /**< Command Index Error */
-#define XSDPS_INTR_ERR_DT_MASK	    0x00000010U /**< Data Timeout Error */
+#define XSDPS_INTR_ERR_CEB_MASK        0x00000004U /**< Command End Bit
+                            Error */
+#define XSDPS_INTR_ERR_CI_MASK        0x00000008U /**< Command Index Error */
+#define XSDPS_INTR_ERR_DT_MASK        0x00000010U /**< Data Timeout Error */
 #define XSDPS_INTR_ERR_DCRC_MASK    0x00000020U /**< Data CRC Error */
-#define XSDPS_INTR_ERR_DEB_MASK	    0x00000040U /**< Data End Bit Error */
+#define XSDPS_INTR_ERR_DEB_MASK        0x00000040U /**< Data End Bit Error */
 #define XSDPS_INTR_ERR_CUR_LMT_MASK    0x00000080U /**< Current Limit Error */
 #define XSDPS_INTR_ERR_AUTO_CMD12_MASK    0x00000100U /**< Auto CMD12 Error */
 #define XSDPS_INTR_ERR_ADMA_MASK    0x00000200U /**< ADMA Error */
-#define XSDPS_INTR_ERR_TR_MASK	    0x00001000U /**< Tuning Error */
+#define XSDPS_INTR_ERR_TR_MASK        0x00001000U /**< Tuning Error */
 #define XSDPS_INTR_VEND_SPF_ERR_MASK    0x0000E000U /**< Vendor Specific
-						    Error */
+                            Error */
 #define XSDPS_ERROR_INTR_ALL_MASK    0x0000F3FFU /**< Mask for error bits */
 /* @} */
 
@@ -297,12 +297,12 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_BLK_SIZE_MASK	    0x00000FFFU /**< Transfer Block Size */
+#define XSDPS_BLK_SIZE_MASK        0x00000FFFU /**< Transfer Block Size */
 #define XSDPS_SDMA_BUFF_SIZE_MASK    0x00007000U /**< Host SDMA Buffer Size */
-#define XSDPS_BLK_SIZE_1024	    0x400U
-#define XSDPS_BLK_SIZE_2048	    0x800U
-#define XSDPS_BLK_CNT_MASK	    0x0000FFFFU /**< Block Count for
-							    Current Transfer */
+#define XSDPS_BLK_SIZE_1024        0x400U
+#define XSDPS_BLK_SIZE_2048        0x800U
+#define XSDPS_BLK_CNT_MASK        0x0000FFFFU /**< Block Count for
+                                Current Transfer */
 
 /* @} */
 
@@ -314,35 +314,35 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_TM_DMA_EN_MASK	    0x00000001U /**< DMA Enable */
+#define XSDPS_TM_DMA_EN_MASK        0x00000001U /**< DMA Enable */
 #define XSDPS_TM_BLK_CNT_EN_MASK    0x00000002U /**< Block Count Enable */
 #define XSDPS_TM_AUTO_CMD12_EN_MASK    0x00000004U /**< Auto CMD12 Enable */
 #define XSDPS_TM_DAT_DIR_SEL_MASK    0x00000010U /**< Data Transfer
-						    Direction Select */
+                            Direction Select */
 #define XSDPS_TM_MUL_SIN_BLK_SEL_MASK    0x00000020U /**< Multi/Single
-						    Block Select */
+                            Block Select */
 
-#define XSDPS_CMD_RESP_SEL_MASK	    0x00000003U /**< Response Type
-						    Select */
+#define XSDPS_CMD_RESP_SEL_MASK        0x00000003U /**< Response Type
+                            Select */
 #define XSDPS_CMD_RESP_NONE_MASK    0x00000000U /**< No Response */
 #define XSDPS_CMD_RESP_L136_MASK    0x00000001U /**< Response length 138 */
-#define XSDPS_CMD_RESP_L48_MASK	    0x00000002U /**< Response length 48 */
+#define XSDPS_CMD_RESP_L48_MASK        0x00000002U /**< Response length 48 */
 #define XSDPS_CMD_RESP_L48_BSY_CHK_MASK    0x00000003U /**< Response length 48 &
-						    check busy after
-						    response */
+                            check busy after
+                            response */
 #define XSDPS_CMD_CRC_CHK_EN_MASK    0x00000008U /**< Command CRC Check
-						    Enable */
+                            Enable */
 #define XSDPS_CMD_INX_CHK_EN_MASK    0x00000010U /**< Command Index Check
-						    Enable */
+                            Enable */
 #define XSDPS_DAT_PRESENT_SEL_MASK    0x00000020U /**< Data Present Select */
-#define XSDPS_CMD_TYPE_MASK	    0x000000C0U /**< Command Type */
+#define XSDPS_CMD_TYPE_MASK        0x000000C0U /**< Command Type */
 #define XSDPS_CMD_TYPE_NORM_MASK    0x00000000U /**< CMD Type - Normal */
 #define XSDPS_CMD_TYPE_SUSPEND_MASK    0x00000040U /**< CMD Type - Suspend */
 #define XSDPS_CMD_TYPE_RESUME_MASK    0x00000080U /**< CMD Type - Resume */
 #define XSDPS_CMD_TYPE_ABORT_MASK    0x000000C0U /**< CMD Type - Abort */
-#define XSDPS_CMD_MASK		    0x00003F00U /**< Command Index Mask -
-						    Set to CMD0-63,
-						    AMCD0-63 */
+#define XSDPS_CMD_MASK            0x00003F00U /**< Command Index Mask -
+                            Set to CMD0-63,
+                            AMCD0-63 */
 
 /* @} */
 
@@ -354,15 +354,15 @@ extern "C" {
  * @{
  */
 #define XSDPS_AUTO_CMD12_NT_EX_MASK    0x0001U /**< Auto CMD12 Not
-						    executed */
+                            executed */
 #define XSDPS_AUTO_CMD_TOUT_MASK    0x0002U /**< Auto CMD Timeout
-						    Error */
-#define XSDPS_AUTO_CMD_CRC_MASK	    0x0004U /**< Auto CMD CRC Error */
-#define XSDPS_AUTO_CMD_EB_MASK	    0x0008U /**< Auto CMD End Bit
-						    Error */
-#define XSDPS_AUTO_CMD_IND_MASK	    0x0010U /**< Auto CMD Index Error */
+                            Error */
+#define XSDPS_AUTO_CMD_CRC_MASK        0x0004U /**< Auto CMD CRC Error */
+#define XSDPS_AUTO_CMD_EB_MASK        0x0008U /**< Auto CMD End Bit
+                            Error */
+#define XSDPS_AUTO_CMD_IND_MASK        0x0010U /**< Auto CMD Index Error */
 #define XSDPS_AUTO_CMD_CNI_ERR_MASK    0x0080U /**< Command not issued by
-						    Auto CMD12 Error */
+                            Auto CMD12 Error */
 /* @} */
 
 /** @name Host Control2 Register
@@ -371,24 +371,24 @@ extern "C" {
  * Read Write
  * @{
  */
-#define XSDPS_HC2_UHS_MODE_MASK	    0x0007U /**< UHS Mode select bits */
+#define XSDPS_HC2_UHS_MODE_MASK        0x0007U /**< UHS Mode select bits */
 #define XSDPS_HC2_UHS_MODE_SDR12_MASK    0x0000U /**< SDR12 UHS Mode */
 #define XSDPS_HC2_UHS_MODE_SDR25_MASK    0x0001U /**< SDR25 UHS Mode */
 #define XSDPS_HC2_UHS_MODE_SDR50_MASK    0x0002U /**< SDR50 UHS Mode */
 #define XSDPS_HC2_UHS_MODE_SDR104_MASK    0x0003U /**< SDR104 UHS Mode */
 #define XSDPS_HC2_UHS_MODE_DDR50_MASK    0x0004U /**< DDR50 UHS Mode */
-#define XSDPS_HC2_1V8_EN_MASK	    0x0008U /**< 1.8V Signal Enable */
+#define XSDPS_HC2_1V8_EN_MASK        0x0008U /**< 1.8V Signal Enable */
 #define XSDPS_HC2_DRV_STR_SEL_MASK    0x0030U /**< Driver Strength
-						    Selection */
+                            Selection */
 #define XSDPS_HC2_DRV_STR_B_MASK    0x0000U /**< Driver Strength B */
 #define XSDPS_HC2_DRV_STR_A_MASK    0x0010U /**< Driver Strength A */
 #define XSDPS_HC2_DRV_STR_C_MASK    0x0020U /**< Driver Strength C */
 #define XSDPS_HC2_DRV_STR_D_MASK    0x0030U /**< Driver Strength D */
-#define XSDPS_HC2_EXEC_TNG_MASK	    0x0040U /**< Execute Tuning */
+#define XSDPS_HC2_EXEC_TNG_MASK        0x0040U /**< Execute Tuning */
 #define XSDPS_HC2_SAMP_CLK_SEL_MASK    0x0080U /**< Sampling Clock
-						    Selection */
+                            Selection */
 #define XSDPS_HC2_ASYNC_INTR_EN_MASK    0x4000U /**< Asynchronous Interrupt
-						    Enable */
+                            Enable */
 #define XSDPS_HC2_PRE_VAL_EN_MASK    0x8000U /**< Preset Value Enable */
 
 /* @} */
@@ -402,9 +402,9 @@ extern "C" {
  * @{
  */
 #define XSDPS_CAP_TOUT_CLK_FREQ_MASK    0x0000003FU /**< Timeout clock freq
-						    select */
+                            select */
 #define XSDPS_CAP_TOUT_CLK_UNIT_MASK    0x00000080U /**< Timeout clock unit -
-						    MHz/KHz */
+                            MHz/KHz */
 #define XSDPS_CAP_MAX_BLK_LEN_MASK    0x00030000U /**< Max block length */
 #define XSDPS_CAP_MAX_BLK_LEN_512B_MASK    0x00000000U /**< Max block 512 bytes */
 #define XSDPS_CAP_MAX_BL_LN_1024_MASK    0x00010000U /**< Max block 1024 bytes */
@@ -412,50 +412,50 @@ extern "C" {
 #define XSDPS_CAP_MAX_BL_LN_4096_MASK    0x00030000U /**< Max block 4096 bytes */
 
 #define XSDPS_CAP_EXT_MEDIA_BUS_MASK    0x00040000U /**< Extended media bus */
-#define XSDPS_CAP_ADMA2_MASK	    0x00080000U /**< ADMA2 support */
+#define XSDPS_CAP_ADMA2_MASK        0x00080000U /**< ADMA2 support */
 #define XSDPS_CAP_HIGH_SPEED_MASK    0x00200000U /**< High speed support */
-#define XSDPS_CAP_SDMA_MASK	    0x00400000U /**< SDMA support */
+#define XSDPS_CAP_SDMA_MASK        0x00400000U /**< SDMA support */
 #define XSDPS_CAP_SUSP_RESUME_MASK    0x00800000U /**< Suspend/Resume
-						    support */
-#define XSDPS_CAP_VOLT_3V3_MASK	    0x01000000U /**< 3.3V support */
-#define XSDPS_CAP_VOLT_3V0_MASK	    0x02000000U /**< 3.0V support */
-#define XSDPS_CAP_VOLT_1V8_MASK	    0x04000000U /**< 1.8V support */
+                            support */
+#define XSDPS_CAP_VOLT_3V3_MASK        0x01000000U /**< 3.3V support */
+#define XSDPS_CAP_VOLT_3V0_MASK        0x02000000U /**< 3.0V support */
+#define XSDPS_CAP_VOLT_1V8_MASK        0x04000000U /**< 1.8V support */
 
 #define XSDPS_CAP_SYS_BUS_64_MASK    0x10000000U /**< 64 bit system bus
-						    support */
+                            support */
 /* Spec 2.0 */
 #define XSDPS_CAP_INTR_MODE_MASK    0x08000000U /**< Interrupt mode
-						    support */
-#define XSDPS_CAP_SPI_MODE_MASK	    0x20000000U /**< SPI mode */
+                            support */
+#define XSDPS_CAP_SPI_MODE_MASK        0x20000000U /**< SPI mode */
 #define XSDPS_CAP_SPI_BLOCK_MODE_MASK    0x40000000U /**< SPI block mode */
 
 
 /* Spec 3.0 */
 #define XSDPS_CAPS_ASYNC_INTR_MASK    0x20000000U /**< Async Interrupt
-						    support */
+                            support */
 #define XSDPS_CAPS_SLOT_TYPE_MASK    0xC0000000U /**< Slot Type */
-#define XSDPS_CAPS_REM_CARD		    0x00000000U /**< Removable Slot */
-#define XSDPS_CAPS_EMB_SLOT		    0x40000000U /**< Embedded Slot */
-#define XSDPS_CAPS_SHR_BUS		    0x80000000U /**< Shared Bus Slot */
+#define XSDPS_CAPS_REM_CARD            0x00000000U /**< Removable Slot */
+#define XSDPS_CAPS_EMB_SLOT            0x40000000U /**< Embedded Slot */
+#define XSDPS_CAPS_SHR_BUS            0x80000000U /**< Shared Bus Slot */
 
-#define XSDPS_ECAPS_SDR50_MASK	    0x00000001U /**< SDR50 Mode support */
-#define XSDPS_ECAPS_SDR104_MASK	    0x00000002U /**< SDR104 Mode support */
-#define XSDPS_ECAPS_DDR50_MASK	    0x00000004U /**< DDR50 Mode support */
+#define XSDPS_ECAPS_SDR50_MASK        0x00000001U /**< SDR50 Mode support */
+#define XSDPS_ECAPS_SDR104_MASK        0x00000002U /**< SDR104 Mode support */
+#define XSDPS_ECAPS_DDR50_MASK        0x00000004U /**< DDR50 Mode support */
 #define XSDPS_ECAPS_DRV_TYPE_A_MASK    0x00000010U /**< DriverType A support */
 #define XSDPS_ECAPS_DRV_TYPE_C_MASK    0x00000020U /**< DriverType C support */
 #define XSDPS_ECAPS_DRV_TYPE_D_MASK    0x00000040U /**< DriverType D support */
 #define XSDPS_ECAPS_TMR_CNT_MASK    0x00000F00U /**< Timer Count for
-						    Re-tuning */
+                            Re-tuning */
 #define XSDPS_ECAPS_USE_TNG_SDR50_MASK    0x00002000U /**< SDR50 Mode needs
-						    tuning */
+                            tuning */
 #define XSDPS_ECAPS_RE_TNG_MODES_MASK    0x0000C000U /**< Re-tuning modes
-						    support */
+                            support */
 #define XSDPS_ECAPS_RE_TNG_MODE1_MASK    0x00000000U /**< Re-tuning mode 1 */
 #define XSDPS_ECAPS_RE_TNG_MODE2_MASK    0x00004000U /**< Re-tuning mode 2 */
 #define XSDPS_ECAPS_RE_TNG_MODE3_MASK    0x00008000U /**< Re-tuning mode 3 */
 #define XSDPS_ECAPS_CLK_MULT_MASK    0x00FF0000U /**< Clock Multiplier value
-						    for Programmable clock
-						    mode */
+                            for Programmable clock
+                            mode */
 #define XSDPS_ECAPS_SPI_MODE_MASK    0x01000000U /**< SPI mode */
 #define XSDPS_ECAPS_SPI_BLK_MODE_MASK    0x02000000U /**< SPI block mode */
 
@@ -478,9 +478,9 @@ extern "C" {
 #define XSDPS_PSR_BUFF_RD_EN_MASK    0x00000800U /**< Buffer read enable */
 #define XSDPS_PSR_CARD_INSRT_MASK    0x00010000U /**< Card inserted */
 #define XSDPS_PSR_CARD_STABLE_MASK    0x00020000U /**< Card state stable */
-#define XSDPS_PSR_CARD_DPL_MASK	    0x00040000U /**< Card detect pin level */
-#define XSDPS_PSR_WPS_PL_MASK	    0x00080000U /**< Write protect switch
-							    pin level */
+#define XSDPS_PSR_CARD_DPL_MASK        0x00040000U /**< Card detect pin level */
+#define XSDPS_PSR_WPS_PL_MASK        0x00080000U /**< Write protect switch
+                                pin level */
 #define XSDPS_PSR_DAT30_SG_LVL_MASK    0x00F00000U /**< Data 3:0 signal lvl */
 #define XSDPS_PSR_CMD_SG_LVL_MASK    0x01000000U /**< Cmd Line signal lvl */
 #define XSDPS_PSR_DAT74_SG_LVL_MASK    0x1E000000U /**< Data 7:4 signal lvl */
@@ -495,11 +495,11 @@ extern "C" {
  * @{
  */
 #define XSDPS_MAX_CUR_CAPS_1V8_MASK    0x00000F00U /**< Maximum Current
-						    Capability at 1.8V */
+                            Capability at 1.8V */
 #define XSDPS_MAX_CUR_CAPS_3V0_MASK    0x000000F0U /**< Maximum Current
-						    Capability at 3.0V */
+                            Capability at 3.0V */
 #define XSDPS_MAX_CUR_CAPS_3V3_MASK    0x0000000FU /**< Maximum Current
-						    Capability at 3.3V */
+                            Capability at 3.3V */
 /* @} */
 
 
@@ -511,15 +511,15 @@ extern "C" {
  * @{
  */
 #define XSDPS_FE_AUTO_CMD12_NT_EX_MASK    0x0001U /**< Auto CMD12 Not
-						    executed */
+                            executed */
 #define XSDPS_FE_AUTO_CMD_TOUT_MASK    0x0002U /**< Auto CMD Timeout
-						    Error */
+                            Error */
 #define XSDPS_FE_AUTO_CMD_CRC_MASK    0x0004U /**< Auto CMD CRC Error */
 #define XSDPS_FE_AUTO_CMD_EB_MASK    0x0008U /**< Auto CMD End Bit
-						    Error */
+                            Error */
 #define XSDPS_FE_AUTO_CMD_IND_MASK    0x0010U /**< Auto CMD Index Error */
 #define XSDPS_FE_AUTO_CMD_CNI_ERR_MASK    0x0080U /**< Command not issued by
-						    Auto CMD12 Error */
+                            Auto CMD12 Error */
 /* @} */
 
 
@@ -532,10 +532,10 @@ extern "C" {
  * @{
  */
 #define XSDPS_FE_INTR_ERR_CT_MASK    0x0001U /**< Command Timeout
-						    Error */
+                            Error */
 #define XSDPS_FE_INTR_ERR_CCRC_MASK    0x0002U /**< Command CRC Error */
 #define XSDPS_FE_INTR_ERR_CEB_MASK    0x0004U /**< Command End Bit
-						    Error */
+                            Error */
 #define XSDPS_FE_INTR_ERR_CI_MASK    0x0008U /**< Command Index Error */
 #define XSDPS_FE_INTR_ERR_DT_MASK    0x0010U /**< Data Timeout Error */
 #define XSDPS_FE_INTR_ERR_DCRC_MASK    0x0020U /**< Data CRC Error */
@@ -545,7 +545,7 @@ extern "C" {
 #define XSDPS_FE_INTR_ERR_ADMA_MASK    0x0200U /**< ADMA Error */
 #define XSDPS_FE_INTR_ERR_TR_MASK    0x1000U /**< Target Response */
 #define XSDPS_FE_INTR_VEND_SPF_ERR_MASK    0xE000U /**< Vendor Specific
-						    Error */
+                            Error */
 
 /* @} */
 
@@ -557,14 +557,14 @@ extern "C" {
  * @{
  */
 #define XSDPS_ADMA_ERR_MM_LEN_MASK    0x04U /**< ADMA Length Mismatch
-						    Error */
+                            Error */
 #define XSDPS_ADMA_ERR_STATE_MASK    0x03U /**< ADMA Error State */
 #define XSDPS_ADMA_ERR_STATE_STOP_MASK    0x00U /**< ADMA Error State
-						    STOP */
+                            STOP */
 #define XSDPS_ADMA_ERR_STATE_FDS_MASK    0x01U /**< ADMA Error State
-						    FDS */
+                            FDS */
 #define XSDPS_ADMA_ERR_STATE_TFR_MASK    0x03U /**< ADMA Error State
-						    TFR */
+                            TFR */
 /* @} */
 
 /** @name Preset Values Register
@@ -575,11 +575,11 @@ extern "C" {
  * @{
  */
 #define XSDPS_PRE_VAL_SDCLK_FSEL_MASK    0x03FFU /**< SDCLK Frequency
-						    Select Value */
+                            Select Value */
 #define XSDPS_PRE_VAL_CLK_GEN_SEL_MASK    0x0400U /**< Clock Generator
-						    Mode Select */
+                            Mode Select */
 #define XSDPS_PRE_VAL_DRV_STR_SEL_MASK    0xC000U /**< Driver Strength
-						    Select Value */
+                            Select Value */
 
 /* @} */
 
@@ -591,7 +591,7 @@ extern "C" {
  * @{
  */
 #define XSDPS_SLOT_INTR_STS_INT_MASK    0x0007U /**< Interrupt Signal
-						    mask */
+                            mask */
 
 /* @} */
 
@@ -602,15 +602,15 @@ extern "C" {
  * Read Only
  * @{
  */
-#define XSDPS_HC_VENDOR_VER	    0xFF00U /**< Vendor
-						    Specification
-						    version mask */
-#define XSDPS_HC_SPEC_VER_MASK	    0x00FFU /**< Host
-						    Specification
-						    version mask */
-#define XSDPS_HC_SPEC_V3	    0x0002U
-#define XSDPS_HC_SPEC_V2	    0x0001U
-#define XSDPS_HC_SPEC_V1	    0x0000U
+#define XSDPS_HC_VENDOR_VER        0xFF00U /**< Vendor
+                            Specification
+                            version mask */
+#define XSDPS_HC_SPEC_VER_MASK        0x00FFU /**< Host
+                            Specification
+                            version mask */
+#define XSDPS_HC_SPEC_V3        0x0002U
+#define XSDPS_HC_SPEC_V2        0x0001U
+#define XSDPS_HC_SPEC_V1        0x0000U
 
 /** @name Block size mask for 512 bytes
  *
@@ -628,191 +628,191 @@ extern "C" {
  * @{
  */
 
-#define XSDPS_APP_CMD_PREFIX	 0x8000U
-#define CMD0	 0x0000U
-#define CMD1	 0x0100U
-#define CMD2	 0x0200U
-#define CMD3	 0x0300U
-#define CMD4	 0x0400U
-#define CMD5	 0x0500U
-#define CMD6	 0x0600U
-#define ACMD6	(XSDPS_APP_CMD_PREFIX + 0x0600U)
-#define CMD7	 0x0700U
-#define CMD8	 0x0800U
-#define CMD9	 0x0900U
-#define CMD10	 0x0A00U
-#define CMD11	 0x0B00U
-#define CMD12	 0x0C00U
-#define ACMD13	 (XSDPS_APP_CMD_PREFIX + 0x0D00U)
-#define CMD16	 0x1000U
-#define CMD17	 0x1100U
-#define CMD18	 0x1200U
-#define CMD19	 0x1300U
-#define CMD21	 0x1500U
-#define CMD23	 0x1700U
-#define ACMD23	 (XSDPS_APP_CMD_PREFIX + 0x1700U)
-#define CMD24	 0x1800U
-#define CMD25	 0x1900U
-#define CMD41	 0x2900U
-#define ACMD41	 (XSDPS_APP_CMD_PREFIX + 0x2900U)
-#define ACMD42	 (XSDPS_APP_CMD_PREFIX + 0x2A00U)
-#define ACMD51	 (XSDPS_APP_CMD_PREFIX + 0x3300U)
-#define CMD52	 0x3400U
-#define CMD55	 0x3700U
-#define CMD58	 0x3A00U
+#define XSDPS_APP_CMD_PREFIX     0x8000U
+#define CMD0     0x0000U
+#define CMD1     0x0100U
+#define CMD2     0x0200U
+#define CMD3     0x0300U
+#define CMD4     0x0400U
+#define CMD5     0x0500U
+#define CMD6     0x0600U
+#define ACMD6    (XSDPS_APP_CMD_PREFIX + 0x0600U)
+#define CMD7     0x0700U
+#define CMD8     0x0800U
+#define CMD9     0x0900U
+#define CMD10     0x0A00U
+#define CMD11     0x0B00U
+#define CMD12     0x0C00U
+#define ACMD13     (XSDPS_APP_CMD_PREFIX + 0x0D00U)
+#define CMD16     0x1000U
+#define CMD17     0x1100U
+#define CMD18     0x1200U
+#define CMD19     0x1300U
+#define CMD21     0x1500U
+#define CMD23     0x1700U
+#define ACMD23     (XSDPS_APP_CMD_PREFIX + 0x1700U)
+#define CMD24     0x1800U
+#define CMD25     0x1900U
+#define CMD41     0x2900U
+#define ACMD41     (XSDPS_APP_CMD_PREFIX + 0x2900U)
+#define ACMD42     (XSDPS_APP_CMD_PREFIX + 0x2A00U)
+#define ACMD51     (XSDPS_APP_CMD_PREFIX + 0x3300U)
+#define CMD52     0x3400U
+#define CMD55     0x3700U
+#define CMD58     0x3A00U
 
 #if 0
-#define RESP_NONE	(u32)XSDPS_CMD_RESP_NONE_MASK
-#define RESP_R1		(u32)XSDPS_CMD_RESP_L48_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK | \
-			(u32)XSDPS_CMD_INX_CHK_EN_MASK
+#define RESP_NONE    (u32)XSDPS_CMD_RESP_NONE_MASK
+#define RESP_R1        (u32)XSDPS_CMD_RESP_L48_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK | \
+            (u32)XSDPS_CMD_INX_CHK_EN_MASK
 
-#define RESP_R1B	(u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \
-			(u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK
+#define RESP_R1B    (u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \
+            (u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK
 
-#define RESP_R2		(u32)XSDPS_CMD_RESP_L136_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK
-#define RESP_R3		(u32)XSDPS_CMD_RESP_L48_MASK
+#define RESP_R2        (u32)XSDPS_CMD_RESP_L136_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK
+#define RESP_R3        (u32)XSDPS_CMD_RESP_L48_MASK
 
-#define RESP_R6		(u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \
-			(u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK
+#define RESP_R6        (u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \
+            (u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK
 #else
-#define XSDPS_RESP_NONE	(u32)XSDPS_CMD_RESP_NONE_MASK
-#define XSDPS_RESP_R1		(u32)XSDPS_CMD_RESP_L48_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK | \
-			(u32)XSDPS_CMD_INX_CHK_EN_MASK
+#define XSDPS_RESP_NONE    (u32)XSDPS_CMD_RESP_NONE_MASK
+#define XSDPS_RESP_R1        (u32)XSDPS_CMD_RESP_L48_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK | \
+            (u32)XSDPS_CMD_INX_CHK_EN_MASK
 
-#define XSDPS_RESP_R1B	(u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \
-			(u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK
+#define XSDPS_RESP_R1B    (u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \
+            (u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK
 
-#define XSDPS_RESP_R2		(u32)XSDPS_CMD_RESP_L136_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK
-#define XSDPS_RESP_R3		(u32)XSDPS_CMD_RESP_L48_MASK
+#define XSDPS_RESP_R2        (u32)XSDPS_CMD_RESP_L136_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK
+#define XSDPS_RESP_R3        (u32)XSDPS_CMD_RESP_L48_MASK
 
-#define XSDPS_RESP_R6		(u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \
-			(u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK
+#define XSDPS_RESP_R6        (u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \
+            (u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK
 #endif
 
 /* @} */
 
 /* Card Interface Conditions Definitions */
 #define XSDPS_CIC_CHK_PATTERN    0xAAU
-#define XSDPS_CIC_VOLT_MASK	(0xFU<<8)
-#define XSDPS_CIC_VOLT_2V7_3V6	(1U<<8)
-#define XSDPS_CIC_VOLT_LOW	(1U<<9)
+#define XSDPS_CIC_VOLT_MASK    (0xFU<<8)
+#define XSDPS_CIC_VOLT_2V7_3V6    (1U<<8)
+#define XSDPS_CIC_VOLT_LOW    (1U<<9)
 
 /* Operation Conditions Register Definitions */
-#define XSDPS_OCR_PWRUP_STS	(1U<<31)
-#define XSDPS_OCR_CC_STS	(1U<<30)
-#define XSDPS_OCR_S18		(1U<<24)
-#define XSDPS_OCR_3V5_3V6	(1U<<23)
-#define XSDPS_OCR_3V4_3V5	(1U<<22)
-#define XSDPS_OCR_3V3_3V4	(1U<<21)
-#define XSDPS_OCR_3V2_3V3	(1U<<20)
-#define XSDPS_OCR_3V1_3V2	(1U<<19)
-#define XSDPS_OCR_3V0_3V1	(1U<<18)
-#define XSDPS_OCR_2V9_3V0	(1U<<17)
-#define XSDPS_OCR_2V8_2V9	(1U<<16)
-#define XSDPS_OCR_2V7_2V8	(1U<<15)
-#define XSDPS_OCR_1V7_1V95	(1U<<7)
+#define XSDPS_OCR_PWRUP_STS    (1U<<31)
+#define XSDPS_OCR_CC_STS    (1U<<30)
+#define XSDPS_OCR_S18        (1U<<24)
+#define XSDPS_OCR_3V5_3V6    (1U<<23)
+#define XSDPS_OCR_3V4_3V5    (1U<<22)
+#define XSDPS_OCR_3V3_3V4    (1U<<21)
+#define XSDPS_OCR_3V2_3V3    (1U<<20)
+#define XSDPS_OCR_3V1_3V2    (1U<<19)
+#define XSDPS_OCR_3V0_3V1    (1U<<18)
+#define XSDPS_OCR_2V9_3V0    (1U<<17)
+#define XSDPS_OCR_2V8_2V9    (1U<<16)
+#define XSDPS_OCR_2V7_2V8    (1U<<15)
+#define XSDPS_OCR_1V7_1V95    (1U<<7)
 #define XSDPS_OCR_HIGH_VOL    0x00FF8000U
 #define XSDPS_OCR_LOW_VOL    0x00000080U
 
 /* SD Card Configuration Register Definitions */
-#define XSDPS_SCR_REG_LEN	    8U
-#define XSDPS_SCR_STRUCT_MASK		(0xFU<<28)
-#define XSDPS_SCR_SPEC_MASK		(0xFU<<24)
-#define XSDPS_SCR_SPEC_1V0	    0U
-#define XSDPS_SCR_SPEC_1V1		(1U<<24)
-#define XSDPS_SCR_SPEC_2V0_3V0		(2U<<24)
-#define XSDPS_SCR_MEM_VAL_AF_ERASE	(1U<<23)
-#define XSDPS_SCR_SEC_SUPP_MASK		(7U<<20)
-#define XSDPS_SCR_SEC_SUPP_NONE	    0U
-#define XSDPS_SCR_SEC_SUPP_1V1		(2U<<20)
-#define XSDPS_SCR_SEC_SUPP_2V0		(3U<<20)
-#define XSDPS_SCR_SEC_SUPP_3V0		(4U<<20)
-#define XSDPS_SCR_BUS_WIDTH_MASK	(0xFU<<16)
-#define XSDPS_SCR_BUS_WIDTH_1		(1U<<16)
-#define XSDPS_SCR_BUS_WIDTH_4		(4U<<16)
-#define XSDPS_SCR_SPEC3_MASK		(1U<<12)
-#define XSDPS_SCR_SPEC3_2V0	    0U
-#define XSDPS_SCR_SPEC3_3V0		(1U<<12)
-#define XSDPS_SCR_CMD_SUPP_MASK	    0x3U
-#define XSDPS_SCR_CMD23_SUPP		(1U<<1)
-#define XSDPS_SCR_CMD20_SUPP		(1U<<0)
+#define XSDPS_SCR_REG_LEN        8U
+#define XSDPS_SCR_STRUCT_MASK        (0xFU<<28)
+#define XSDPS_SCR_SPEC_MASK        (0xFU<<24)
+#define XSDPS_SCR_SPEC_1V0        0U
+#define XSDPS_SCR_SPEC_1V1        (1U<<24)
+#define XSDPS_SCR_SPEC_2V0_3V0        (2U<<24)
+#define XSDPS_SCR_MEM_VAL_AF_ERASE    (1U<<23)
+#define XSDPS_SCR_SEC_SUPP_MASK        (7U<<20)
+#define XSDPS_SCR_SEC_SUPP_NONE        0U
+#define XSDPS_SCR_SEC_SUPP_1V1        (2U<<20)
+#define XSDPS_SCR_SEC_SUPP_2V0        (3U<<20)
+#define XSDPS_SCR_SEC_SUPP_3V0        (4U<<20)
+#define XSDPS_SCR_BUS_WIDTH_MASK    (0xFU<<16)
+#define XSDPS_SCR_BUS_WIDTH_1        (1U<<16)
+#define XSDPS_SCR_BUS_WIDTH_4        (4U<<16)
+#define XSDPS_SCR_SPEC3_MASK        (1U<<12)
+#define XSDPS_SCR_SPEC3_2V0        0U
+#define XSDPS_SCR_SPEC3_3V0        (1U<<12)
+#define XSDPS_SCR_CMD_SUPP_MASK        0x3U
+#define XSDPS_SCR_CMD23_SUPP        (1U<<1)
+#define XSDPS_SCR_CMD20_SUPP        (1U<<0)
 
 /* Card Status Register Definitions */
-#define XSDPS_CD_STS_OUT_OF_RANGE	(1U<<31)
-#define XSDPS_CD_STS_ADDR_ERR		(1U<<30)
-#define XSDPS_CD_STS_BLK_LEN_ERR	(1U<<29)
-#define XSDPS_CD_STS_ER_SEQ_ERR		(1U<<28)
-#define XSDPS_CD_STS_ER_PRM_ERR		(1U<<27)
-#define XSDPS_CD_STS_WP_VIO		(1U<<26)
-#define XSDPS_CD_STS_IS_LOCKED		(1U<<25)
-#define XSDPS_CD_STS_LOCK_UNLOCK_FAIL	(1U<<24)
-#define XSDPS_CD_STS_CMD_CRC_ERR	(1U<<23)
-#define XSDPS_CD_STS_ILGL_CMD		(1U<<22)
-#define XSDPS_CD_STS_CARD_ECC_FAIL	(1U<<21)
-#define XSDPS_CD_STS_CC_ERR		(1U<<20)
-#define XSDPS_CD_STS_ERR		(1U<<19)
-#define XSDPS_CD_STS_CSD_OVRWR		(1U<<16)
-#define XSDPS_CD_STS_WP_ER_SKIP		(1U<<15)
-#define XSDPS_CD_STS_CARD_ECC_DIS	(1U<<14)
-#define XSDPS_CD_STS_ER_RST		(1U<<13)
-#define XSDPS_CD_STS_CUR_STATE		(0xFU<<9)
-#define XSDPS_CD_STS_RDY_FOR_DATA	(1U<<8)
-#define XSDPS_CD_STS_APP_CMD		(1U<<5)
-#define XSDPS_CD_STS_AKE_SEQ_ERR	(1U<<2)
+#define XSDPS_CD_STS_OUT_OF_RANGE    (1U<<31)
+#define XSDPS_CD_STS_ADDR_ERR        (1U<<30)
+#define XSDPS_CD_STS_BLK_LEN_ERR    (1U<<29)
+#define XSDPS_CD_STS_ER_SEQ_ERR        (1U<<28)
+#define XSDPS_CD_STS_ER_PRM_ERR        (1U<<27)
+#define XSDPS_CD_STS_WP_VIO        (1U<<26)
+#define XSDPS_CD_STS_IS_LOCKED        (1U<<25)
+#define XSDPS_CD_STS_LOCK_UNLOCK_FAIL    (1U<<24)
+#define XSDPS_CD_STS_CMD_CRC_ERR    (1U<<23)
+#define XSDPS_CD_STS_ILGL_CMD        (1U<<22)
+#define XSDPS_CD_STS_CARD_ECC_FAIL    (1U<<21)
+#define XSDPS_CD_STS_CC_ERR        (1U<<20)
+#define XSDPS_CD_STS_ERR        (1U<<19)
+#define XSDPS_CD_STS_CSD_OVRWR        (1U<<16)
+#define XSDPS_CD_STS_WP_ER_SKIP        (1U<<15)
+#define XSDPS_CD_STS_CARD_ECC_DIS    (1U<<14)
+#define XSDPS_CD_STS_ER_RST        (1U<<13)
+#define XSDPS_CD_STS_CUR_STATE        (0xFU<<9)
+#define XSDPS_CD_STS_RDY_FOR_DATA    (1U<<8)
+#define XSDPS_CD_STS_APP_CMD        (1U<<5)
+#define XSDPS_CD_STS_AKE_SEQ_ERR    (1U<<2)
 
 /* Switch Function Definitions CMD6 */
 #define XSDPS_SWITCH_SD_RESP_LEN    64U
 
-#define XSDPS_SWITCH_FUNC_SWITCH	(1U<<31)
-#define XSDPS_SWITCH_FUNC_CHECK	    0U
+#define XSDPS_SWITCH_FUNC_SWITCH    (1U<<31)
+#define XSDPS_SWITCH_FUNC_CHECK        0U
 
-#define XSDPS_MODE_FUNC_GRP1	    1U
-#define XSDPS_MODE_FUNC_GRP2	    2U
-#define XSDPS_MODE_FUNC_GRP3	    3U
-#define XSDPS_MODE_FUNC_GRP4	    4U
-#define XSDPS_MODE_FUNC_GRP5	    5U
-#define XSDPS_MODE_FUNC_GRP6	    6U
+#define XSDPS_MODE_FUNC_GRP1        1U
+#define XSDPS_MODE_FUNC_GRP2        2U
+#define XSDPS_MODE_FUNC_GRP3        3U
+#define XSDPS_MODE_FUNC_GRP4        4U
+#define XSDPS_MODE_FUNC_GRP5        5U
+#define XSDPS_MODE_FUNC_GRP6        6U
 
-#define XSDPS_FUNC_GRP_DEF_VAL	    0xFU
+#define XSDPS_FUNC_GRP_DEF_VAL        0xFU
 #define XSDPS_FUNC_ALL_GRP_DEF_VAL    0xFFFFFFU
 
 #define XSDPS_ACC_MODE_DEF_SDR12    0U
-#define XSDPS_ACC_MODE_HS_SDR25	    1U
-#define XSDPS_ACC_MODE_SDR50	    2U
-#define XSDPS_ACC_MODE_SDR104	    3U
-#define XSDPS_ACC_MODE_DDR50	    4U
+#define XSDPS_ACC_MODE_HS_SDR25        1U
+#define XSDPS_ACC_MODE_SDR50        2U
+#define XSDPS_ACC_MODE_SDR104        3U
+#define XSDPS_ACC_MODE_DDR50        4U
 
-#define XSDPS_CMD_SYS_ARG_SHIFT	    4U
-#define XSDPS_CMD_SYS_DEF	    0U
-#define XSDPS_CMD_SYS_eC	    1U
-#define XSDPS_CMD_SYS_OTP	    3U
-#define XSDPS_CMD_SYS_ASSD	    4U
-#define XSDPS_CMD_SYS_VEND	    5U
+#define XSDPS_CMD_SYS_ARG_SHIFT        4U
+#define XSDPS_CMD_SYS_DEF        0U
+#define XSDPS_CMD_SYS_eC        1U
+#define XSDPS_CMD_SYS_OTP        3U
+#define XSDPS_CMD_SYS_ASSD        4U
+#define XSDPS_CMD_SYS_VEND        5U
 
 #define XSDPS_DRV_TYPE_ARG_SHIFT    8U
-#define XSDPS_DRV_TYPE_B	    0U
-#define XSDPS_DRV_TYPE_A	    1U
-#define XSDPS_DRV_TYPE_C	    2U
-#define XSDPS_DRV_TYPE_D	    3U
+#define XSDPS_DRV_TYPE_B        0U
+#define XSDPS_DRV_TYPE_A        1U
+#define XSDPS_DRV_TYPE_C        2U
+#define XSDPS_DRV_TYPE_D        3U
 
-#define XSDPS_CUR_LIM_ARG_SHIFT	    12U
-#define XSDPS_CUR_LIM_200	    0U
-#define XSDPS_CUR_LIM_400	    1U
-#define XSDPS_CUR_LIM_600	    2U
-#define XSDPS_CUR_LIM_800	    3U
+#define XSDPS_CUR_LIM_ARG_SHIFT        12U
+#define XSDPS_CUR_LIM_200        0U
+#define XSDPS_CUR_LIM_400        1U
+#define XSDPS_CUR_LIM_600        2U
+#define XSDPS_CUR_LIM_800        3U
 
-#define CSD_SPEC_VER_MASK	    0x3C0000U
-#define READ_BLK_LEN_MASK	    0x00000F00U
-#define C_SIZE_MULT_MASK	    0x00000380U
-#define C_SIZE_LOWER_MASK	    0xFFC00000U
-#define C_SIZE_UPPER_MASK	    0x00000003U
-#define CSD_STRUCT_MASK		    0x00C00000U
-#define CSD_V2_C_SIZE_MASK	    0x3FFFFF00U
+#define CSD_SPEC_VER_MASK        0x3C0000U
+#define READ_BLK_LEN_MASK        0x00000F00U
+#define C_SIZE_MULT_MASK        0x00000380U
+#define C_SIZE_LOWER_MASK        0xFFC00000U
+#define C_SIZE_UPPER_MASK        0x00000003U
+#define CSD_STRUCT_MASK            0x00C00000U
+#define CSD_V2_C_SIZE_MASK        0x3FFFFF00U
 
 /* EXT_CSD field definitions */
-#define XSDPS_EXT_CSD_SIZE	    512U
+#define XSDPS_EXT_CSD_SIZE        512U
 
-#define EXT_CSD_WR_REL_PARAM_EN		(1U<<2)
+#define EXT_CSD_WR_REL_PARAM_EN        (1U<<2)
 
 #define EXT_CSD_BOOT_WP_B_PWR_WP_DIS    (0x40U)
 #define EXT_CSD_BOOT_WP_B_PERM_WP_DIS   (0x10U)
@@ -824,18 +824,18 @@ extern "C" {
 #define EXT_CSD_PART_CONFIG_ACC_BOOT1   (0x2U)
 #define EXT_CSD_PART_CONFIG_ACC_RPMB    (0x3U)
 #define EXT_CSD_PART_CONFIG_ACC_GP0     (0x4U)
-#define EXT_CSD_PART_CONFIG_BYTE	    179U
-#define XSDPS_MMC_PART_CFG_0_ARG		((XSDPS_EXT_CSD_WRITE_BYTE << 24U) \
-					 | (EXT_CSD_PART_CONFIG_BYTE << 16U) \
-					 | ((0U) << 8U))
+#define EXT_CSD_PART_CONFIG_BYTE        179U
+#define XSDPS_MMC_PART_CFG_0_ARG        ((XSDPS_EXT_CSD_WRITE_BYTE << 24U) \
+                     | (EXT_CSD_PART_CONFIG_BYTE << 16U) \
+                     | ((0U) << 8U))
 
-#define XSDPS_MMC_PART_CFG_1_ARG		((XSDPS_EXT_CSD_WRITE_BYTE << 24U) \
-					 | (EXT_CSD_PART_CONFIG_BYTE << 16U) \
-					 | (EXT_CSD_PART_CONFIG_ACC_BOOT0 << 8U))
+#define XSDPS_MMC_PART_CFG_1_ARG        ((XSDPS_EXT_CSD_WRITE_BYTE << 24U) \
+                     | (EXT_CSD_PART_CONFIG_BYTE << 16U) \
+                     | (EXT_CSD_PART_CONFIG_ACC_BOOT0 << 8U))
 
-#define XSDPS_MMC_PART_CFG_2_ARG		((XSDPS_EXT_CSD_WRITE_BYTE << 24U) \
-					 | (EXT_CSD_PART_CONFIG_BYTE << 16U) \
-					 | (EXT_CSD_PART_CONFIG_ACC_BOOT1 << 8U))
+#define XSDPS_MMC_PART_CFG_2_ARG        ((XSDPS_EXT_CSD_WRITE_BYTE << 24U) \
+                     | (EXT_CSD_PART_CONFIG_BYTE << 16U) \
+                     | (EXT_CSD_PART_CONFIG_ACC_BOOT1 << 8U))
 
 #define EXT_CSD_PART_SUPPORT_PART_EN    (0x1U)
 
@@ -843,75 +843,75 @@ extern "C" {
 #define EXT_CSD_CMD_SET_SECURE          (1U<<1)
 #define EXT_CSD_CMD_SET_CPSECURE        (1U<<2)
 
-#define EXT_CSD_CARD_TYPE_26    	(1U<<0)  /* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52    	(1U<<1)  /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_26        (1U<<0)  /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52        (1U<<1)  /* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK      0x3FU    /* Mask out reserved bits */
-#define EXT_CSD_CARD_TYPE_DDR_1_8V	(1U<<2)   /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_DDR_1_8V    (1U<<2)   /* Card can run at 52MHz */
                                              /* DDR mode @1.8V or 3V I/O */
-#define EXT_CSD_CARD_TYPE_DDR_1_2V	(1U<<3)   /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_DDR_1_2V    (1U<<3)   /* Card can run at 52MHz */
                                              /* DDR mode @1.2V I/O */
-#define EXT_CSD_CARD_TYPE_DDR_52	(EXT_CSD_CARD_TYPE_DDR_1_8V  \
+#define EXT_CSD_CARD_TYPE_DDR_52    (EXT_CSD_CARD_TYPE_DDR_1_8V  \
                                         | EXT_CSD_CARD_TYPE_DDR_1_2V)
 #define EXT_CSD_CARD_TYPE_SDR_1_8V      (1U<<4)  /* Card can run at 200MHz */
 #define EXT_CSD_CARD_TYPE_SDR_1_2V      (1U<<5)  /* Card can run at 200MHz */
                                                 /* SDR mode @1.2V I/O */
-#define EXT_CSD_BUS_WIDTH_BYTE		    183U
-#define EXT_CSD_BUS_WIDTH_1_BIT		    0U	/* Card is in 1 bit mode */
-#define EXT_CSD_BUS_WIDTH_4_BIT		    1U	/* Card is in 4 bit mode */
-#define EXT_CSD_BUS_WIDTH_8_BIT		    2U	/* Card is in 8 bit mode */
-#define EXT_CSD_BUS_WIDTH_DDR_4_BIT	    5U	/* Card is in 4 bit DDR mode */
-#define EXT_CSD_BUS_WIDTH_DDR_8_BIT	    6U	/* Card is in 8 bit DDR mode */
+#define EXT_CSD_BUS_WIDTH_BYTE            183U
+#define EXT_CSD_BUS_WIDTH_1_BIT            0U    /* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4_BIT            1U    /* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8_BIT            2U    /* Card is in 8 bit mode */
+#define EXT_CSD_BUS_WIDTH_DDR_4_BIT        5U    /* Card is in 4 bit DDR mode */
+#define EXT_CSD_BUS_WIDTH_DDR_8_BIT        6U    /* Card is in 8 bit DDR mode */
 
-#define EXT_CSD_HS_TIMING_BYTE	    185U
-#define EXT_CSD_HS_TIMING_DEF	    0U
-#define EXT_CSD_HS_TIMING_HIGH	    1U	/* Card is in high speed mode */
-#define EXT_CSD_HS_TIMING_HS200	    2U	/* Card is in HS200 mode */
+#define EXT_CSD_HS_TIMING_BYTE        185U
+#define EXT_CSD_HS_TIMING_DEF        0U
+#define EXT_CSD_HS_TIMING_HIGH        1U    /* Card is in high speed mode */
+#define EXT_CSD_HS_TIMING_HS200        2U    /* Card is in HS200 mode */
 
-#define EXT_CSD_RST_N_FUN_BYTE	    162U
-#define EXT_CSD_RST_N_FUN_TEMP_DIS    0U	/* RST_n signal is temporarily disabled */
-#define EXT_CSD_RST_N_FUN_PERM_EN    1U	/* RST_n signal is permanently enabled */
-#define EXT_CSD_RST_N_FUN_PERM_DIS    2U	/* RST_n signal is permanently disabled */
+#define EXT_CSD_RST_N_FUN_BYTE        162U
+#define EXT_CSD_RST_N_FUN_TEMP_DIS    0U    /* RST_n signal is temporarily disabled */
+#define EXT_CSD_RST_N_FUN_PERM_EN    1U    /* RST_n signal is permanently enabled */
+#define EXT_CSD_RST_N_FUN_PERM_DIS    2U    /* RST_n signal is permanently disabled */
 
-#define XSDPS_EXT_CSD_CMD_SET	    0U
-#define XSDPS_EXT_CSD_SET_BITS	    1U
-#define XSDPS_EXT_CSD_CLR_BITS	    2U
+#define XSDPS_EXT_CSD_CMD_SET        0U
+#define XSDPS_EXT_CSD_SET_BITS        1U
+#define XSDPS_EXT_CSD_CLR_BITS        2U
 #define XSDPS_EXT_CSD_WRITE_BYTE    3U
 
-#define XSDPS_MMC_DEF_SPEED_ARG		(((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
-					| ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \
-					| ((u32)EXT_CSD_HS_TIMING_DEF << 8))
+#define XSDPS_MMC_DEF_SPEED_ARG        (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
+                    | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \
+                    | ((u32)EXT_CSD_HS_TIMING_DEF << 8))
 
-#define XSDPS_MMC_HIGH_SPEED_ARG	(((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
-					 | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \
-					 | ((u32)EXT_CSD_HS_TIMING_HIGH << 8))
+#define XSDPS_MMC_HIGH_SPEED_ARG    (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
+                     | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \
+                     | ((u32)EXT_CSD_HS_TIMING_HIGH << 8))
 
-#define XSDPS_MMC_HS200_ARG		(((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
-					 | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \
-					 | ((u32)EXT_CSD_HS_TIMING_HS200 << 8))
+#define XSDPS_MMC_HS200_ARG        (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
+                     | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \
+                     | ((u32)EXT_CSD_HS_TIMING_HS200 << 8))
 
-#define XSDPS_MMC_1_BIT_BUS_ARG		(((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
-					 | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \
-					 | ((u32)EXT_CSD_BUS_WITH_1_BIT << 8))
+#define XSDPS_MMC_1_BIT_BUS_ARG        (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
+                     | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \
+                     | ((u32)EXT_CSD_BUS_WITH_1_BIT << 8))
 
-#define XSDPS_MMC_4_BIT_BUS_ARG		(((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
-					 | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \
-					 | ((u32)EXT_CSD_BUS_WIDTH_4_BIT << 8))
+#define XSDPS_MMC_4_BIT_BUS_ARG        (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
+                     | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \
+                     | ((u32)EXT_CSD_BUS_WIDTH_4_BIT << 8))
 
-#define XSDPS_MMC_8_BIT_BUS_ARG		(((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
-					 | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \
-					 | ((u32)EXT_CSD_BUS_WIDTH_8_BIT << 8))
+#define XSDPS_MMC_8_BIT_BUS_ARG        (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
+                     | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \
+                     | ((u32)EXT_CSD_BUS_WIDTH_8_BIT << 8))
 
-#define XSDPS_MMC_DDR_4_BIT_BUS_ARG		(((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
-					 | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \
-					 | ((u32)EXT_CSD_BUS_WIDTH_DDR_4_BIT << 8))
+#define XSDPS_MMC_DDR_4_BIT_BUS_ARG        (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
+                     | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \
+                     | ((u32)EXT_CSD_BUS_WIDTH_DDR_4_BIT << 8))
 
-#define XSDPS_MMC_DDR_8_BIT_BUS_ARG		(((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
-					 | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \
-					 | ((u32)EXT_CSD_BUS_WIDTH_DDR_8_BIT << 8))
+#define XSDPS_MMC_DDR_8_BIT_BUS_ARG        (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
+                     | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \
+                     | ((u32)EXT_CSD_BUS_WIDTH_DDR_8_BIT << 8))
 
-#define XSDPS_MMC_RST_FUN_EN_ARG		(((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
-					 | ((u32)EXT_CSD_RST_N_FUN_BYTE << 16) \
-					 | ((u32)EXT_CSD_RST_N_FUN_PERM_EN << 8))
+#define XSDPS_MMC_RST_FUN_EN_ARG        (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \
+                     | ((u32)EXT_CSD_RST_N_FUN_BYTE << 16) \
+                     | ((u32)EXT_CSD_RST_N_FUN_PERM_EN << 8))
 
 #define XSDPS_MMC_DELAY_FOR_SWITCH    1000U
 
@@ -925,11 +925,11 @@ extern "C" {
 #define XSDPS_DEF_VOLT_LVL    XSDPS_PC_BUS_VSEL_3V0_MASK
 #define XSDPS_CARD_DEF_ADDR    0x1234U
 
-#define XSDPS_CARD_SD	    1U
-#define XSDPS_CARD_MMC	    2U
-#define XSDPS_CARD_SDIO	    3U
+#define XSDPS_CARD_SD        1U
+#define XSDPS_CARD_MMC        2U
+#define XSDPS_CARD_SDIO        3U
 #define XSDPS_CARD_SDCOMBO    4U
-#define XSDPS_CHIP_EMMC	    5U
+#define XSDPS_CHIP_EMMC        5U
 
 
 /** @name ADMA2 Descriptor related definitions
@@ -940,19 +940,19 @@ extern "C" {
 
 #define XSDPS_DESC_MAX_LENGTH 65536U
 
-#define XSDPS_DESC_VALID     	(0x1U << 0)
-#define XSDPS_DESC_END       	(0x1U << 1)
-#define XSDPS_DESC_INT       	(0x1U << 2)
-#define XSDPS_DESC_TRAN  	(0x2U << 4)
+#define XSDPS_DESC_VALID         (0x1U << 0)
+#define XSDPS_DESC_END           (0x1U << 1)
+#define XSDPS_DESC_INT           (0x1U << 2)
+#define XSDPS_DESC_TRAN      (0x2U << 4)
 
 /* @} */
 
 /* For changing clock frequencies */
-#define XSDPS_CLK_400_KHZ	    400000U		/**< 400 KHZ */
-#define XSDPS_CLK_50_MHZ	    50000000U	/**< 50 MHZ */
-#define XSDPS_CLK_52_MHZ	    52000000U	/**< 52 MHZ */
-#define XSDPS_SD_VER_1_0	    0x1U		/**< SD ver 1 */
-#define XSDPS_SD_VER_2_0	    0x2U		/**< SD ver 2 */
+#define XSDPS_CLK_400_KHZ        400000U        /**< 400 KHZ */
+#define XSDPS_CLK_50_MHZ        50000000U    /**< 50 MHZ */
+#define XSDPS_CLK_52_MHZ        52000000U    /**< 52 MHZ */
+#define XSDPS_SD_VER_1_0        0x1U        /**< SD ver 1 */
+#define XSDPS_SD_VER_2_0        0x2U        /**< SD ver 2 */
 #define XSDPS_SCR_BLKCNT    1U
 #define XSDPS_SCR_BLKSIZE    8U
 #define XSDPS_1_BIT_WIDTH    0x1U
@@ -963,32 +963,32 @@ extern "C" {
 #define XSDPS_UHS_SPEED_MODE_SDR50    0x2U
 #define XSDPS_UHS_SPEED_MODE_SDR104    0x3U
 #define XSDPS_UHS_SPEED_MODE_DDR50    0x4U
-#define XSDPS_HIGH_SPEED_MODE	    0x5U
+#define XSDPS_HIGH_SPEED_MODE        0x5U
 #define XSDPS_DEFAULT_SPEED_MODE    0x6U
-#define XSDPS_HS200_MODE		    0x7U
-#define XSDPS_DDR52_MODE		    0x4U
-#define XSDPS_SWITCH_CMD_BLKCNT	    1U
+#define XSDPS_HS200_MODE            0x7U
+#define XSDPS_DDR52_MODE            0x4U
+#define XSDPS_SWITCH_CMD_BLKCNT        1U
 #define XSDPS_SWITCH_CMD_BLKSIZE    64U
-#define XSDPS_SWITCH_CMD_HS_GET	    0x00FFFFF0U
-#define XSDPS_SWITCH_CMD_HS_SET	    0x80FFFFF1U
-#define XSDPS_SWITCH_CMD_SDR12_SET	    0x80FFFFF0U
-#define XSDPS_SWITCH_CMD_SDR25_SET	    0x80FFFFF1U
-#define XSDPS_SWITCH_CMD_SDR50_SET	    0x80FFFFF2U
-#define XSDPS_SWITCH_CMD_SDR104_SET	    0x80FFFFF3U
-#define XSDPS_SWITCH_CMD_DDR50_SET	    0x80FFFFF4U
+#define XSDPS_SWITCH_CMD_HS_GET        0x00FFFFF0U
+#define XSDPS_SWITCH_CMD_HS_SET        0x80FFFFF1U
+#define XSDPS_SWITCH_CMD_SDR12_SET        0x80FFFFF0U
+#define XSDPS_SWITCH_CMD_SDR25_SET        0x80FFFFF1U
+#define XSDPS_SWITCH_CMD_SDR50_SET        0x80FFFFF2U
+#define XSDPS_SWITCH_CMD_SDR104_SET        0x80FFFFF3U
+#define XSDPS_SWITCH_CMD_DDR50_SET        0x80FFFFF4U
 #define XSDPS_EXT_CSD_CMD_BLKCNT    1U
 #define XSDPS_EXT_CSD_CMD_BLKSIZE    512U
-#define XSDPS_TUNING_CMD_BLKCNT	    1U
+#define XSDPS_TUNING_CMD_BLKCNT        1U
 #define XSDPS_TUNING_CMD_BLKSIZE    64U
-#define XSDPS_SD_STATUS_BLKCNT	    1U
-#define XSDPS_SD_STATUS_BLKSIZE	    64U
+#define XSDPS_SD_STATUS_BLKCNT        1U
+#define XSDPS_SD_STATUS_BLKSIZE        64U
 
 #define XSDPS_HIGH_SPEED_MAX_CLK    50000000U
 #define XSDPS_UHS_SDR104_MAX_CLK    208000000U
-#define XSDPS_UHS_SDR50_MAX_CLK	    100000000U
-#define XSDPS_UHS_DDR50_MAX_CLK	    50000000U
-#define XSDPS_UHS_SDR25_MAX_CLK	    50000000U
-#define XSDPS_UHS_SDR12_MAX_CLK	    25000000U
+#define XSDPS_UHS_SDR50_MAX_CLK        100000000U
+#define XSDPS_UHS_DDR50_MAX_CLK        50000000U
+#define XSDPS_UHS_SDR25_MAX_CLK        50000000U
+#define XSDPS_UHS_SDR12_MAX_CLK        25000000U
 
 #define SD_DRIVER_TYPE_B    0x01U
 #define SD_DRIVER_TYPE_A    0x02U
@@ -999,10 +999,10 @@ extern "C" {
 #define SD_SET_CURRENT_LIMIT_600    2U
 #define SD_SET_CURRENT_LIMIT_800    3U
 
-#define SD_MAX_CURRENT_200	(1U << SD_SET_CURRENT_LIMIT_200)
-#define SD_MAX_CURRENT_400	(1U << SD_SET_CURRENT_LIMIT_400)
-#define SD_MAX_CURRENT_600	(1U << SD_SET_CURRENT_LIMIT_600)
-#define SD_MAX_CURRENT_800	(1U << SD_SET_CURRENT_LIMIT_800)
+#define SD_MAX_CURRENT_200    (1U << SD_SET_CURRENT_LIMIT_200)
+#define SD_MAX_CURRENT_400    (1U << SD_SET_CURRENT_LIMIT_400)
+#define SD_MAX_CURRENT_600    (1U << SD_SET_CURRENT_LIMIT_600)
+#define SD_MAX_CURRENT_800    (1U << SD_SET_CURRENT_LIMIT_800)
 
 #define XSDPS_SD_SDR12_MAX_CLK    25000000U
 #define XSDPS_SD_SDR25_MAX_CLK    50000000U
@@ -1020,74 +1020,74 @@ extern "C" {
 #define XSDPS_MMC_HSD_MAX_CLK    52000000U
 #define XSDPS_MMC_DDR_MAX_CLK    52000000U
 
-#define XSDPS_CARD_STATE_IDLE	    0U
-#define XSDPS_CARD_STATE_RDY	    1U
-#define XSDPS_CARD_STATE_IDEN	    2U
-#define XSDPS_CARD_STATE_STBY	    3U
-#define XSDPS_CARD_STATE_TRAN	    4U
-#define XSDPS_CARD_STATE_DATA	    5U
-#define XSDPS_CARD_STATE_RCV	    6U
-#define XSDPS_CARD_STATE_PROG	    7U
-#define XSDPS_CARD_STATE_DIS	    8U
-#define XSDPS_CARD_STATE_BTST	    9U
-#define XSDPS_CARD_STATE_SLP	    10U
+#define XSDPS_CARD_STATE_IDLE        0U
+#define XSDPS_CARD_STATE_RDY        1U
+#define XSDPS_CARD_STATE_IDEN        2U
+#define XSDPS_CARD_STATE_STBY        3U
+#define XSDPS_CARD_STATE_TRAN        4U
+#define XSDPS_CARD_STATE_DATA        5U
+#define XSDPS_CARD_STATE_RCV        6U
+#define XSDPS_CARD_STATE_PROG        7U
+#define XSDPS_CARD_STATE_DIS        8U
+#define XSDPS_CARD_STATE_BTST        9U
+#define XSDPS_CARD_STATE_SLP        10U
 
-#define XSDPS_SLOT_REM		    0U
-#define XSDPS_SLOT_EMB		    1U
+#define XSDPS_SLOT_REM            0U
+#define XSDPS_SLOT_EMB            1U
 
-#define XSDPS_WIDTH_8	    8U
-#define XSDPS_WIDTH_4	    4U
+#define XSDPS_WIDTH_8        8U
+#define XSDPS_WIDTH_4        4U
 
 
 #ifdef versal
-#define SD_ITAPDLY_SEL_MASK		    0x000000FFU
-#define SD_OTAPDLY_SEL_MASK		    0x0000003FU
-#define SD_ITAPDLY				    0x0000F0F8U
-#define SD_OTAPDLY				    0x0000F0FCU
-#define SD0_DLL_CTRL 			    0x00000448U
-#define SD1_DLL_CTRL 			    0x000004C8U
-#define SD_DLL_RST				    0x00000004U
-#define SD_ITAPCHGWIN			    0x00000200U
-#define SD_ITAPDLYENA			    0x00000100U
-#define SD_OTAPDLYENA			    0x00000040U
-#define SD_OTAPDLYSEL_HS200_B0	    0x00000002U
-#define SD_OTAPDLYSEL_HS200_B2	    0x00000002U
-#define SD_ITAPDLYSEL_SD50		    0x0000000EU
-#define SD_OTAPDLYSEL_SD50		    0x00000003U
-#define SD_ITAPDLYSEL_SD_DDR50	    0x00000036U
+#define SD_ITAPDLY_SEL_MASK            0x000000FFU
+#define SD_OTAPDLY_SEL_MASK            0x0000003FU
+#define SD_ITAPDLY                    0x0000F0F8U
+#define SD_OTAPDLY                    0x0000F0FCU
+#define SD0_DLL_CTRL                 0x00000448U
+#define SD1_DLL_CTRL                 0x000004C8U
+#define SD_DLL_RST                    0x00000004U
+#define SD_ITAPCHGWIN                0x00000200U
+#define SD_ITAPDLYENA                0x00000100U
+#define SD_OTAPDLYENA                0x00000040U
+#define SD_OTAPDLYSEL_HS200_B0        0x00000002U
+#define SD_OTAPDLYSEL_HS200_B2        0x00000002U
+#define SD_ITAPDLYSEL_SD50            0x0000000EU
+#define SD_OTAPDLYSEL_SD50            0x00000003U
+#define SD_ITAPDLYSEL_SD_DDR50        0x00000036U
 #define SD_ITAPDLYSEL_EMMC_DDR50    0x0000001EU
-#define SD_OTAPDLYSEL_SD_DDR50	    0x00000003U
+#define SD_OTAPDLYSEL_SD_DDR50        0x00000003U
 #define SD_OTAPDLYSEL_EMMC_DDR50    0x00000005U
-#define SD_ITAPDLYSEL_HSD		    0x0000002CU
-#define SD_OTAPDLYSEL_SD_HSD	    0x00000004U
-#define SD_OTAPDLYSEL_EMMC_HSD	    0x00000005U
+#define SD_ITAPDLYSEL_HSD            0x0000002CU
+#define SD_OTAPDLYSEL_SD_HSD        0x00000004U
+#define SD_OTAPDLYSEL_EMMC_HSD        0x00000005U
 #else
-#define SD0_ITAPDLY_SEL_MASK	    0x000000FFU
-#define SD0_OTAPDLY_SEL_MASK	    0x0000003FU
-#define SD1_ITAPDLY_SEL_MASK	    0x00FF0000U
-#define SD1_OTAPDLY_SEL_MASK	    0x003F0000U
-#define SD_DLL_CTRL 			    0x00000358U
-#define SD_ITAPDLY				    0x00000314U
-#define SD_OTAPDLY				    0x00000318U
-#define SD0_DLL_RST				    0x00000004U
-#define SD1_DLL_RST				    0x00040000U
-#define SD0_ITAPCHGWIN			    0x00000200U
-#define SD0_ITAPDLYENA			    0x00000100U
-#define SD0_OTAPDLYENA			    0x00000040U
-#define SD1_ITAPCHGWIN			    0x02000000U
-#define SD1_ITAPDLYENA			    0x01000000U
-#define SD1_OTAPDLYENA			    0x00400000U
-#define SD_OTAPDLYSEL_HS200_B0	    0x00000003U
-#define SD_OTAPDLYSEL_HS200_B2	    0x00000002U
-#define SD_ITAPDLYSEL_SD50		    0x00000014U
-#define SD_OTAPDLYSEL_SD50		    0x00000003U
-#define SD_ITAPDLYSEL_SD_DDR50	    0x0000003DU
+#define SD0_ITAPDLY_SEL_MASK        0x000000FFU
+#define SD0_OTAPDLY_SEL_MASK        0x0000003FU
+#define SD1_ITAPDLY_SEL_MASK        0x00FF0000U
+#define SD1_OTAPDLY_SEL_MASK        0x003F0000U
+#define SD_DLL_CTRL                 0x00000358U
+#define SD_ITAPDLY                    0x00000314U
+#define SD_OTAPDLY                    0x00000318U
+#define SD0_DLL_RST                    0x00000004U
+#define SD1_DLL_RST                    0x00040000U
+#define SD0_ITAPCHGWIN                0x00000200U
+#define SD0_ITAPDLYENA                0x00000100U
+#define SD0_OTAPDLYENA                0x00000040U
+#define SD1_ITAPCHGWIN                0x02000000U
+#define SD1_ITAPDLYENA                0x01000000U
+#define SD1_OTAPDLYENA                0x00400000U
+#define SD_OTAPDLYSEL_HS200_B0        0x00000003U
+#define SD_OTAPDLYSEL_HS200_B2        0x00000002U
+#define SD_ITAPDLYSEL_SD50            0x00000014U
+#define SD_OTAPDLYSEL_SD50            0x00000003U
+#define SD_ITAPDLYSEL_SD_DDR50        0x0000003DU
 #define SD_ITAPDLYSEL_EMMC_DDR50    0x00000012U
-#define SD_OTAPDLYSEL_SD_DDR50	    0x00000004U
+#define SD_OTAPDLYSEL_SD_DDR50        0x00000004U
 #define SD_OTAPDLYSEL_EMMC_DDR50    0x00000006U
-#define SD_ITAPDLYSEL_HSD		    0x00000015U
-#define SD_OTAPDLYSEL_SD_HSD	    0x00000005U
-#define SD_OTAPDLYSEL_EMMC_HSD	    0x00000006U
+#define SD_ITAPDLYSEL_HSD            0x00000015U
+#define SD_OTAPDLYSEL_SD_HSD        0x00000005U
+#define SD_OTAPDLYSEL_EMMC_HSD        0x00000006U
 #endif
 
 #ifdef __MICROBLAZE__
@@ -1115,12 +1115,12 @@ extern "C" {
 *
 * @param    InstancePtr is the pointer to the sdps instance.
 * @param    RegOffset contains the offset from the 1st register of the
-*	    device to the target register.
+*        device to the target register.
 *
 * @return    The value read from the register.
 *
-* @note	    C-Style signature:
-*	    u32 XSdPs_ReadReg(XSdPs *InstancePtr. s32 RegOffset)
+* @note        C-Style signature:
+*        u32 XSdPs_ReadReg(XSdPs *InstancePtr. s32 RegOffset)
 *
 ******************************************************************************/
 #define XSdPs_ReadReg64(InstancePtr, RegOffset) \
@@ -1132,19 +1132,19 @@ extern "C" {
 *
 * @param    InstancePtr is the pointer to the sdps instance.
 * @param    RegOffset contains the offset from the 1st register of the
-*	    device to target register.
+*        device to target register.
 * @param    RegisterValue is the value to be written to the register.
 *
 * @return    None.
 *
-* @note	    C-Style signature:
-*	    void XSdPs_WriteReg(XSdPs *InstancePtr, s32 RegOffset,
-*	    u64 RegisterValue)
+* @note        C-Style signature:
+*        void XSdPs_WriteReg(XSdPs *InstancePtr, s32 RegOffset,
+*        u64 RegisterValue)
 *
 ******************************************************************************/
 #define XSdPs_WriteReg64(InstancePtr, RegOffset, RegisterValue) \
     XSdPs_Out64((InstancePtr->Config.BaseAddress) + (RegOffset), \
-		(RegisterValue))
+        (RegisterValue))
 
 /****************************************************************************/
 /**
@@ -1152,12 +1152,12 @@ extern "C" {
 *
 * @param    BaseAddress contains the base address of the device.
 * @param    RegOffset contains the offset from the 1st register of the
-*	    device to the target register.
+*        device to the target register.
 *
 * @return    The value read from the register.
 *
-* @note	    C-Style signature:
-*	    u32 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
+* @note        C-Style signature:
+*        u32 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
 *
 ******************************************************************************/
 #define XSdPs_ReadReg(BaseAddress, RegOffset) \
@@ -1169,14 +1169,14 @@ extern "C" {
 *
 * @param    BaseAddress contains the base address of the device.
 * @param    RegOffset contains the offset from the 1st register of the
-*	    device to target register.
+*        device to target register.
 * @param    RegisterValue is the value to be written to the register.
 *
 * @return    None.
 *
-* @note	    C-Style signature:
-*	    void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
-*	    u32 RegisterValue)
+* @note        C-Style signature:
+*        void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
+*        u32 RegisterValue)
 *
 ******************************************************************************/
 #define XSdPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \
@@ -1188,12 +1188,12 @@ extern "C" {
 *
 * @param    BaseAddress contains the base address of the device.
 * @param    RegOffset contains the offset from the 1st register of the
-*	    device to the target register.
+*        device to the target register.
 *
 * @return    The value read from the register.
 *
-* @note	    C-Style signature:
-*	    u16 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
+* @note        C-Style signature:
+*        u16 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
 *
 ******************************************************************************/
 static INLINE u16 XSdPs_ReadReg16(u32 BaseAddress, u8 RegOffset)
@@ -1215,14 +1215,14 @@ static INLINE u16 XSdPs_ReadReg16(u32 BaseAddress, u8 RegOffset)
 *
 * @param    BaseAddress contains the base address of the device.
 * @param    RegOffset contains the offset from the 1st register of the
-*	    device to target register.
+*        device to target register.
 * @param    RegisterValue is the value to be written to the register.
 *
 * @return    None.
 *
-* @note	    C-Style signature:
-*	    void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
-*	    u16 RegisterValue)
+* @note        C-Style signature:
+*        void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
+*        u16 RegisterValue)
 *
 ******************************************************************************/
 
@@ -1246,12 +1246,12 @@ static INLINE void XSdPs_WriteReg16(u32 BaseAddress, u8 RegOffset, u16 RegisterV
 *
 * @param    BaseAddress contains the base address of the device.
 * @param    RegOffset contains the offset from the 1st register of the
-*	    device to the target register.
+*        device to the target register.
 *
 * @return    The value read from the register.
 *
-* @note	    C-Style signature:
-*	    u8 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
+* @note        C-Style signature:
+*        u8 XSdPs_ReadReg(u32 BaseAddress. int RegOffset)
 *
 ******************************************************************************/
 static INLINE u8 XSdPs_ReadReg8(u32 BaseAddress, u8 RegOffset)
@@ -1272,14 +1272,14 @@ static INLINE u8 XSdPs_ReadReg8(u32 BaseAddress, u8 RegOffset)
 *
 * @param    BaseAddress contains the base address of the device.
 * @param    RegOffset contains the offset from the 1st register of the
-*	    device to target register.
+*        device to target register.
 * @param    RegisterValue is the value to be written to the register.
 *
 * @return    None.
 *
-* @note	    C-Style signature:
-*	    void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
-*	    u8 RegisterValue)
+* @note        C-Style signature:
+*        void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
+*        u8 RegisterValue)
 *
 ******************************************************************************/
 static INLINE void XSdPs_WriteReg8(u32 BaseAddress, u8 RegOffset, u8 RegisterValue)
@@ -1303,13 +1303,13 @@ static INLINE void XSdPs_WriteReg8(u32 BaseAddress, u8 RegOffset, u8 RegisterVal
 *
 * @return    None.
 *
-* @note	    C-Style signature:
-*	    void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
-*	    u8 RegisterValue)
+* @note        C-Style signature:
+*        void XSdPs_WriteReg(u32 BaseAddress, int RegOffset,
+*        u8 RegisterValue)
 *
 ******************************************************************************/
 #define XSdPs_GetPresentStatusReg(BaseAddress) \
-	    XSdPs_In32((BaseAddress) + (XSDPS_PRES_STATE_OFFSET))
+        XSdPs_In32((BaseAddress) + (XSDPS_PRES_STATE_OFFSET))
 
 /************************** Function Prototypes ******************************/
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c
index 8fed55e9bd..35b40cb535 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c
@@ -22,8 +22,8 @@
 * 2.1   hk     04/18/14 Increase sleep for eMMC switch command.
 *                       Add sleep for microblaze designs. CR# 781117.
 * 2.3   sk     09/23/14 Use XSdPs_Change_ClkFreq API whenever changing
-*					    clock.CR# 816586.
-* 2.5     sg	   07/09/15 Added SD 3.0 features
+*                        clock.CR# 816586.
+* 2.5     sg       07/09/15 Added SD 3.0 features
 *       kvn    07/15/15 Modified the code according to MISRAC-2012.
 * 2.7   sk     01/08/16 Added workaround for issue in auto tuning mode
 *                       of SDR50, SDR104 and HS200.
@@ -44,7 +44,7 @@
 *       sk     03/20/17 Add support for EL1 non-secure mode.
 * 3.3   mn     07/25/17 Removed SD0_OTAPDLYENA and SD1_OTAPDLYENA bits
 *       mn     08/07/17    Properly set OTAPDLY value by clearing previous bit
-* 		    settings
+*             settings
 *       mn     08/17/17 Added CCI support for A53 and disabled data cache
 *                       operations when it is enabled.
 *       mn     08/22/17 Updated for Word Access System support
@@ -84,8 +84,8 @@
 *
 * @return    None
 *
-* @note	    This API will change clock frequency to the value less than
-*	    or equal to the given value using the permissible dividors.
+* @note        This API will change clock frequency to the value less than
+*        or equal to the given value using the permissible dividors.
 *
 ******************************************************************************/
 s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq)
@@ -96,14 +96,14 @@ s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq)
     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
     if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-		/* Program the Tap delays */
-	    XSdPs_SetTapDelay(InstancePtr);
-	}
+        /* Program the Tap delays */
+        XSdPs_SetTapDelay(InstancePtr);
+    }
 
     Status = XSdPs_SetClock(InstancePtr, SelFreq);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     return Status;
 }
@@ -127,24 +127,24 @@ s32 XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize)
     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
     Status = XSdPs_CheckBusIdle(InstancePtr, (XSDPS_PSR_INHIBIT_CMD_MASK
-											| XSDPS_PSR_INHIBIT_DAT_MASK
-											| XSDPS_PSR_WR_ACTIVE_MASK
-											| XSDPS_PSR_RD_ACTIVE_MASK));
+                                            | XSDPS_PSR_INHIBIT_DAT_MASK
+                                            | XSDPS_PSR_WR_ACTIVE_MASK
+                                            | XSDPS_PSR_RD_ACTIVE_MASK));
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH ;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
-	/* Send block write command */
+    /* Send block write command */
     Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Set block size to the value passed */
+    /* Set block size to the value passed */
     XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
-			 BlkSize & XSDPS_BLK_SIZE_MASK);
+             BlkSize & XSDPS_BLK_SIZE_MASK);
 
 RETURN_PATH:
     return Status;
@@ -161,10 +161,10 @@ RETURN_PATH:
 * @param    SCR - buffer to store SCR register returned by card.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff)
@@ -178,16 +178,16 @@ s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff)
     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
     for (LoopCnt = 0; LoopCnt < 8; LoopCnt++) {
-	    ReadBuff[LoopCnt] = 0U;
-	}
+        ReadBuff[LoopCnt] = 0U;
+    }
 
-	/* Send block write command */
+    /* Send block write command */
     Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
-		    InstancePtr->RelCardAddr, 0U);
+            InstancePtr->RelCardAddr, 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     BlkCnt = XSDPS_SCR_BLKCNT;
     BlkSize = XSDPS_SCR_BLKSIZE;
@@ -196,25 +196,25 @@ s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff)
 
     Status = XSdPs_CmdTransfer(InstancePtr, ACMD51, 0U, BlkCnt);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check for transfer done */
+    /* Check for transfer done */
     Status = XSdps_CheckTransferDone(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     if (InstancePtr->Config.IsCacheCoherent == 0U) {
-	    Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
-				(INTPTR)BlkCnt * BlkSize);
-	}
+        Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
+                (INTPTR)BlkCnt * BlkSize);
+    }
 
     Status = XST_SUCCESS;
 
     RETURN_PATH:
-	    return Status;
+        return Status;
 
 }
 
@@ -228,10 +228,10 @@ s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff)
 * @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr)
@@ -243,81 +243,81 @@ s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr)
     Xil_AssertNonvoid(InstancePtr != NULL);
     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	/*
-	 * check for bus width for 3.0 controller and return if
-	 * bus width is <4
-	 */
+    /*
+     * check for bus width for 3.0 controller and return if
+     * bus width is <4
+     */
     if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
-			(InstancePtr->Config.BusWidth < XSDPS_WIDTH_4)) {
-	    Status = XST_SUCCESS;
-	    goto RETURN_PATH;
-	}
+            (InstancePtr->Config.BusWidth < XSDPS_WIDTH_4)) {
+        Status = XST_SUCCESS;
+        goto RETURN_PATH;
+    }
 
     if (InstancePtr->CardType == XSDPS_CARD_SD) {
 
-	    Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr,
-			    0U);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
+        Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr,
+                0U);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
 
-	    Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, (u32)InstancePtr->BusWidth, 0U);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	} else {
-	    if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
-		    if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
-			    Arg = XSDPS_MMC_DDR_8_BIT_BUS_ARG;
-			} else {
-			    Arg = XSDPS_MMC_8_BIT_BUS_ARG;
-			}
-		} else {
-		    if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
-			    Arg = XSDPS_MMC_DDR_4_BIT_BUS_ARG;
-			} else {
-			    Arg = XSDPS_MMC_4_BIT_BUS_ARG;
-			}
-		}
+        Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, (u32)InstancePtr->BusWidth, 0U);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else {
+        if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
+            if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
+                Arg = XSDPS_MMC_DDR_8_BIT_BUS_ARG;
+            } else {
+                Arg = XSDPS_MMC_8_BIT_BUS_ARG;
+            }
+        } else {
+            if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
+                Arg = XSDPS_MMC_DDR_4_BIT_BUS_ARG;
+            } else {
+                Arg = XSDPS_MMC_4_BIT_BUS_ARG;
+            }
+        }
 
-	    Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, Arg);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, Arg);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
 
     StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
-				    XSDPS_HOST_CTRL1_OFFSET);
+                    XSDPS_HOST_CTRL1_OFFSET);
 
-	/* Width setting in controller */
+    /* Width setting in controller */
     if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
-	    StatusReg |= XSDPS_HC_EXT_BUS_WIDTH;
-	} else {
-	    StatusReg |= XSDPS_HC_WIDTH_MASK;
-	}
+        StatusReg |= XSDPS_HC_EXT_BUS_WIDTH;
+    } else {
+        StatusReg |= XSDPS_HC_WIDTH_MASK;
+    }
 
     XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-		    XSDPS_HOST_CTRL1_OFFSET,
-			(u8)StatusReg);
+            XSDPS_HOST_CTRL1_OFFSET,
+            (u8)StatusReg);
 
     if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
-	    StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-				    XSDPS_HOST_CTRL2_OFFSET);
-	    StatusReg &= (u32)(~XSDPS_HC2_UHS_MODE_MASK);
-	    StatusReg |= InstancePtr->Mode;
-	    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-				    XSDPS_HOST_CTRL2_OFFSET, (u16)StatusReg);
-	}
+        StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                    XSDPS_HOST_CTRL2_OFFSET);
+        StatusReg &= (u32)(~XSDPS_HC2_UHS_MODE_MASK);
+        StatusReg |= InstancePtr->Mode;
+        XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                    XSDPS_HOST_CTRL2_OFFSET, (u16)StatusReg);
+    }
 
     Status = XST_SUCCESS;
 
     RETURN_PATH:
-	    return Status;
+        return Status;
 
 }
 
@@ -330,13 +330,13 @@ s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr)
 *
 * @param    InstancePtr is a pointer to the XSdPs instance.
 * @param    ReadBuff - buffer to store function group support data
-*	    returned by card.
+*        returned by card.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
@@ -351,8 +351,8 @@ s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
     for (LoopCnt = 0; LoopCnt < 64; LoopCnt++) {
-	    ReadBuff[LoopCnt] = 0U;
-	}
+        ReadBuff[LoopCnt] = 0U;
+    }
 
     BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
     BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
@@ -363,25 +363,25 @@ s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
 
     Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check for transfer done */
+    /* Check for transfer done */
     Status = XSdps_CheckTransferDone(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     if (InstancePtr->Config.IsCacheCoherent == 0U) {
-	    Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
-				(INTPTR)BlkCnt * BlkSize);
-	}
+        Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
+                (INTPTR)BlkCnt * BlkSize);
+    }
 
     Status = XST_SUCCESS;
 
     RETURN_PATH:
-	    return Status;
+        return Status;
 
 }
 
@@ -396,10 +396,10 @@ s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
 * @param    SdStatReg - buffer to store status data returned by card.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg)
@@ -411,13 +411,13 @@ s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg)
     Xil_AssertNonvoid(InstancePtr != NULL);
     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	/* Send block write command */
+    /* Send block write command */
     Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
-		    InstancePtr->RelCardAddr, 0U);
+            InstancePtr->RelCardAddr, 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     BlkCnt = XSDPS_SD_STATUS_BLKCNT;
     BlkSize = XSDPS_SD_STATUS_BLKSIZE;
@@ -426,25 +426,25 @@ s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg)
 
     Status = XSdPs_CmdTransfer(InstancePtr, ACMD13, 0U, BlkCnt);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check for transfer done */
+    /* Check for transfer done */
     Status = XSdps_CheckTransferDone(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     if (InstancePtr->Config.IsCacheCoherent == 0U) {
-	    Xil_DCacheInvalidateRange((INTPTR)SdStatReg,
-				(INTPTR)BlkCnt * BlkSize);
-	}
+        Xil_DCacheInvalidateRange((INTPTR)SdStatReg,
+                (INTPTR)BlkCnt * BlkSize);
+    }
 
     Status = XST_SUCCESS;
 
     RETURN_PATH:
-	    return Status;
+        return Status;
 }
 
 /*****************************************************************************/
@@ -457,10 +457,10 @@ s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg)
 * @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
@@ -472,47 +472,47 @@ s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
     if (InstancePtr->CardType == XSDPS_CARD_SD) {
-	    Status = XSdPs_Change_SdBusSpeed(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	} else {
-	    Status = XSdPs_Change_MmcBusSpeed(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        Status = XSdPs_Change_SdBusSpeed(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else {
+        Status = XSdPs_Change_MmcBusSpeed(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     if ((InstancePtr->Mode == XSDPS_HS200_MODE) ||
-		(InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR104) ||
-		(InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR50)) {
-	    Status = XSdPs_Execute_Tuning(InstancePtr);
-	    if (Status != XST_SUCCESS) {
-		    Status = XST_FAILURE;
-		    goto RETURN_PATH;
-		}
-	}
+        (InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR104) ||
+        (InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR50)) {
+        Status = XSdPs_Execute_Tuning(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
     usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
 
     StatusReg = (u32)XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
-				    XSDPS_HOST_CTRL1_OFFSET);
+                    XSDPS_HOST_CTRL1_OFFSET);
     StatusReg |= XSDPS_HC_SPEED_MASK;
     XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-		    XSDPS_HOST_CTRL1_OFFSET, (u8)StatusReg);
+            XSDPS_HOST_CTRL1_OFFSET, (u8)StatusReg);
 
     Status = XST_SUCCESS;
 
     RETURN_PATH:
-	    return Status;
+        return Status;
 
 }
 
@@ -527,10 +527,10 @@ s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
 * @param    ReadBuff - buffer to store EXT_CSD
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
@@ -545,36 +545,36 @@ s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
     for (LoopCnt = 0; LoopCnt < 512; LoopCnt++) {
-	    ReadBuff[LoopCnt] = 0U;
-	}
+        ReadBuff[LoopCnt] = 0U;
+    }
 
     BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT;
     BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE;
 
     XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
 
-	/* Send SEND_EXT_CSD command */
+    /* Send SEND_EXT_CSD command */
     Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check for transfer done */
+    /* Check for transfer done */
     Status = XSdps_CheckTransferDone(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     if (InstancePtr->Config.IsCacheCoherent == 0U) {
-	    Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
-				(INTPTR)BlkCnt * BlkSize);
-	}
+        Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
+                (INTPTR)BlkCnt * BlkSize);
+    }
 
     Status = XST_SUCCESS;
 
     RETURN_PATH:
-	    return Status;
+        return Status;
 
 }
 
@@ -589,10 +589,10 @@ s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
 * @param    Arg is the argument to be sent along with the command
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg)
@@ -604,20 +604,20 @@ s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg)
 
     Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check for transfer done */
+    /* Check for transfer done */
     Status = XSdps_CheckTransferDone(InstancePtr);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	}
+        Status = XST_FAILURE;
+    }
 
     Status = XST_SUCCESS;
 
     RETURN_PATH:
-	    return Status;
+        return Status;
 
 }
 
@@ -631,10 +631,10 @@ s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg)
 * @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Pullup(XSdPs *InstancePtr)
@@ -645,22 +645,22 @@ s32 XSdPs_Pullup(XSdPs *InstancePtr)
     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
     Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
-		    InstancePtr->RelCardAddr, 0U);
+            InstancePtr->RelCardAddr, 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0U, 0U);
     if (Status != XST_SUCCESS) {
-	    Status = XST_FAILURE;
-	    goto RETURN_PATH;
-	}
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
     Status = XST_SUCCESS;
 
     RETURN_PATH:
-	    return Status;
+        return Status;
 
 }
 
@@ -674,11 +674,11 @@ s32 XSdPs_Pullup(XSdPs *InstancePtr)
 * @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
-*		- XSDPS_CT_ERROR if Command Transfer fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
+*        - XSDPS_CT_ERROR if Command Transfer fail.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Select_Card (XSdPs *InstancePtr)
@@ -688,9 +688,9 @@ s32 XSdPs_Select_Card (XSdPs *InstancePtr)
     Xil_AssertNonvoid(InstancePtr != NULL);
     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	/* Send CMD7 - Select card */
+    /* Send CMD7 - Select card */
     Status = XSdPs_CmdTransfer(InstancePtr, CMD7,
-		    InstancePtr->RelCardAddr, 0U);
+            InstancePtr->RelCardAddr, 0U);
 
     return Status;
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c
index 3af50efa07..dcf36c99e9 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c
@@ -49,14 +49,14 @@ extern XSdPs_Config XSdPs_ConfigTable[XPAR_XSDPS_NUM_INSTANCES];
 * contains the configuration info for each device in the system.
 *
 * @param    DeviceId contains the ID of the device to look up the
-*	    configuration for.
+*        configuration for.
 *
 * @return
 *
 * A pointer to the configuration found or NULL if the specified device ID was
 * not found. See xsdps.h for the definition of XSdPs_Config.
 *
-* @note	    None.
+* @note        None.
 *
 ******************************************************************************/
 XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId)
@@ -65,11 +65,11 @@ XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId)
     u32 Index;
 
     for (Index = 0U; Index < (u32)XPAR_XSDPS_NUM_INSTANCES; Index++) {
-	    if (XSdPs_ConfigTable[Index].DeviceId == DeviceId) {
-		    CfgPtr = &XSdPs_ConfigTable[Index];
-		    break;
-		}
-	}
+        if (XSdPs_ConfigTable[Index].DeviceId == DeviceId) {
+            CfgPtr = &XSdPs_ConfigTable[Index];
+            break;
+        }
+    }
     return (XSdPs_Config *)CfgPtr;
 }
 /** @} */
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h
index fc5767d3e9..4fe304f55d 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h
@@ -73,9 +73,9 @@ enum ethernet_link_status {
 };
 
 void eth_link_detect(struct netif *netif);
-void 	    lwip_raw_init();
-int 	    xemacif_input(struct netif *netif);
-void 	    xemacif_input_thread(struct netif *netif);
+void         lwip_raw_init();
+int         xemacif_input(struct netif *netif);
+void         xemacif_input_thread(struct netif *netif);
 struct netif *    xemac_add(struct netif *netif,
     ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw,
     unsigned char *mac_ethernet_address,
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h
index da23a43d80..925332a5c8 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h
@@ -45,7 +45,7 @@ extern "C" {
 #include "xstatus.h"
 #include "sleep.h"
 #include "xparameters.h"
-#include "xparameters_ps.h"	/* defines XPAR values */
+#include "xparameters_ps.h"    /* defines XPAR values */
 #include "xil_types.h"
 #include "xil_assert.h"
 #include "xil_io.h"
@@ -55,7 +55,7 @@ extern "C" {
 #include "xil_cache.h"
 #include "xil_printf.h"
 // #include "xscugic.h"
-#include "xemacps.h"		/* defines XEmacPs API */
+#include "xemacps.h"        /* defines XEmacPs API */
 
 #include "netif/xpqueue.h"
 #include "xlwipconfig.h"
@@ -88,7 +88,7 @@ extern "C" {
 #define VERSAL_CRL_GEM0_REF_CTRL    0xFF5E0118
 #define VERSAL_CRL_GEM1_REF_CTRL    0xFF5E011C
 
-#define VERSAL_CRL_GEM_DIV_MASK	    0x0003FF00
+#define VERSAL_CRL_GEM_DIV_MASK        0x0003FF00
 #define VERSAL_CRL_APB_GEM_DIV_SHIFT    8
 
 #if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (__MICROBLAZE__)
@@ -116,11 +116,11 @@ void     xemacps_error_handler(XEmacPs * Temac);
 typedef struct {
     XEmacPs emacps;
 
-	/* queue to store overflow packets */
+    /* queue to store overflow packets */
     pq_queue_t *recv_q;
     pq_queue_t *send_q;
 
-	/* pointers to memory holding buffer descriptors (used only with SDMA) */
+    /* pointers to memory holding buffer descriptors (used only with SDMA) */
     void *rx_bdspace;
     void *tx_bdspace;
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h
index 69f2c94ef8..f5387aea1d 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h
@@ -43,9 +43,9 @@ typedef struct {
 } pq_queue_t;
 
 pq_queue_t*    pq_create_queue();
-int 	    pq_enqueue(pq_queue_t *q, void *p);
-void*	    pq_dequeue(pq_queue_t *q);
-int	    pq_qlength(pq_queue_t *q);
+int         pq_enqueue(pq_queue_t *q, void *p);
+void*        pq_dequeue(pq_queue_t *q);
+int        pq_qlength(pq_queue_t *q);
 
 #ifdef __cplusplus
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h
index b1a912fc62..f809082428 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h
@@ -41,7 +41,7 @@ struct xtopology_t {
     unsigned emac_baseaddr;
     enum xemac_types emac_type;
     unsigned intc_baseaddr;
-    unsigned intc_emac_intr;	/* valid only for xemac_type_xps_emaclite */
+    unsigned intc_emac_intr;    /* valid only for xemac_type_xps_emaclite */
     unsigned scugic_baseaddr; /* valid only for Zynq */
     unsigned scugic_emac_intr; /* valid only for GEM */
 };
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c
index 47f30b756c..e5c0c77829 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c
@@ -83,14 +83,14 @@ u32_t phyaddrforemac;
 void
 lwip_raw_init()
 {
-    ip_init();	/* Doesn't do much, it should be called to handle future changes. */
+    ip_init();    /* Doesn't do much, it should be called to handle future changes. */
 #if LWIP_UDP
-    udp_init();	/* Clears the UDP PCB list. */
+    udp_init();    /* Clears the UDP PCB list. */
 #endif
 #if LWIP_TCP
-    tcp_init();	/* Clears the TCP PCB list and clears some internal TCP timers. */
-			/* Note: you must call tcp_fasttmr() and tcp_slowtmr() at the */
-			/* predefined regular intervals after this initialization. */
+    tcp_init();    /* Clears the TCP PCB list and clears some internal TCP timers. */
+            /* Note: you must call tcp_fasttmr() and tcp_slowtmr() at the */
+            /* predefined regular intervals after this initialization. */
 #endif
 }
 
@@ -100,9 +100,9 @@ find_mac_type(unsigned base)
     int i;
 
     for (i = 0; i < xtopology_n_emacs; i++) {
-	    if (xtopology[i].emac_baseaddr == base)
-		    return xtopology[i].emac_type;
-	}
+        if (xtopology[i].emac_baseaddr == base)
+            return xtopology[i].emac_type;
+    }
 
     return xemac_type_unknown;
 }
@@ -113,9 +113,9 @@ xtopology_find_index(unsigned base)
     int i;
 
     for (i = 0; i < xtopology_n_emacs; i++) {
-	    if (xtopology[i].emac_baseaddr == base)
-		    return i;
-	}
+        if (xtopology[i].emac_baseaddr == base)
+            return i;
+    }
 
     return -1;
 }
@@ -135,66 +135,66 @@ xemac_add(struct netif *netif,
     int i;
 
 #ifdef OS_IS_FREERTOS
-	/* Start thread to detect link periodically for Hot Plug autodetect */
+    /* Start thread to detect link periodically for Hot Plug autodetect */
     sys_thread_new("link_detect_thread", link_detect_thread, netif,
-		    THREAD_STACKSIZE, tskIDLE_PRIORITY);
+            THREAD_STACKSIZE, tskIDLE_PRIORITY);
 #endif
 
-	/* set mac address */
+    /* set mac address */
     netif->hwaddr_len = 6;
     for (i = 0; i < 6; i++)
-	    netif->hwaddr[i] = mac_ethernet_address[i];
+        netif->hwaddr[i] = mac_ethernet_address[i];
 
-	/* initialize based on MAC type */
-	    switch (find_mac_type(mac_baseaddr)) {
-		    case xemac_type_xps_emaclite:
+    /* initialize based on MAC type */
+        switch (find_mac_type(mac_baseaddr)) {
+            case xemac_type_xps_emaclite:
 #ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
-			    return netif_add(netif, ipaddr, netmask, gw,
-					(void*)(UINTPTR)mac_baseaddr,
-				    xemacliteif_init,
+                return netif_add(netif, ipaddr, netmask, gw,
+                    (void*)(UINTPTR)mac_baseaddr,
+                    xemacliteif_init,
 #if NO_SYS
-				    ethernet_input
+                    ethernet_input
 #else
-				    tcpip_input
+                    tcpip_input
 #endif
-					);
+                    );
 #else
-			    return NULL;
+                return NULL;
 #endif
-		    case xemac_type_axi_ethernet:
+            case xemac_type_axi_ethernet:
 #ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
-			    return netif_add(netif, ipaddr, netmask, gw,
-					(void*)(UINTPTR)mac_baseaddr,
-				    xaxiemacif_init,
+                return netif_add(netif, ipaddr, netmask, gw,
+                    (void*)(UINTPTR)mac_baseaddr,
+                    xaxiemacif_init,
 #if NO_SYS
-				    ethernet_input
+                    ethernet_input
 #else
-				    tcpip_input
+                    tcpip_input
 #endif
-					);
+                    );
 #else
-			    return NULL;
+                return NULL;
 #endif
 #if defined (__arm__) || defined (__aarch64__)
-		    case xemac_type_emacps:
+            case xemac_type_emacps:
 #ifdef XLWIP_CONFIG_INCLUDE_GEM
-			    return netif_add(netif, ipaddr, netmask, gw,
-						(void*)(UINTPTR)mac_baseaddr,
-					    xemacpsif_init,
+                return netif_add(netif, ipaddr, netmask, gw,
+                        (void*)(UINTPTR)mac_baseaddr,
+                        xemacpsif_init,
 #if NO_SYS
-					    ethernet_input
+                        ethernet_input
 #else
-					    tcpip_input
+                        tcpip_input
 #endif
 
-						);
+                        );
 #endif
 #endif
-		    default:
-			    xil_printf("unable to determine type of EMAC with baseaddress 0x%08x\r\n",
-					    mac_baseaddr);
-			    return NULL;
-	}
+            default:
+                xil_printf("unable to determine type of EMAC with baseaddress 0x%08x\r\n",
+                        mac_baseaddr);
+                return NULL;
+    }
 }
 
 #if 0
@@ -208,15 +208,15 @@ xemacif_input_thread(struct netif *netif)
 {
     struct xemac_s *emac = (struct xemac_s *)netif->state;
     while (1) {
-		/* sleep until there are packets to process
-		 * This semaphore is set by the packet receive interrupt
-		 * routine.
-		 */
-	    sys_sem_wait(&emac->sem_rx_data_available);
+        /* sleep until there are packets to process
+         * This semaphore is set by the packet receive interrupt
+         * routine.
+         */
+        sys_sem_wait(&emac->sem_rx_data_available);
 
-		/* move all received packets to lwIP */
-	    xemacif_input(netif);
-	}
+        /* move all received packets to lwIP */
+        xemacif_input(netif);
+    }
 }
 #endif
 
@@ -228,40 +228,40 @@ xemacif_input(struct netif *netif)
     int n_packets = 0;
 
     switch (emac->type) {
-	    case xemac_type_xps_emaclite:
+        case xemac_type_xps_emaclite:
 #ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
-		    n_packets = xemacliteif_input(netif);
-		    break;
+            n_packets = xemacliteif_input(netif);
+            break;
 #else
-			// print("incorrect configuration: xps_ethernetlite drivers not present?");
-		    while(1);
-		    return 0;
+            // print("incorrect configuration: xps_ethernetlite drivers not present?");
+            while(1);
+            return 0;
 #endif
-	    case xemac_type_axi_ethernet:
+        case xemac_type_axi_ethernet:
 #ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
-		    n_packets = xaxiemacif_input(netif);
-		    break;
+            n_packets = xaxiemacif_input(netif);
+            break;
 #else
-			// print("incorrect configuration: axi_ethernet drivers not present?");
-		    while(1);
-		    return 0;
+            // print("incorrect configuration: axi_ethernet drivers not present?");
+            while(1);
+            return 0;
 #endif
 #if defined (__arm__) || defined (__aarch64__)
-	    case xemac_type_emacps:
+        case xemac_type_emacps:
 #ifdef XLWIP_CONFIG_INCLUDE_GEM
-		    n_packets = xemacpsif_input(netif);
-		    break;
+            n_packets = xemacpsif_input(netif);
+            break;
 #else
-		    xil_printf("incorrect configuration: ps7_ethernet drivers not present?\r\n");
-		    while(1);
-		    return 0;
+            xil_printf("incorrect configuration: ps7_ethernet drivers not present?\r\n");
+            while(1);
+            return 0;
 #endif
 #endif
-	    default:
-			// print("incorrect configuration: unknown temac type");
-		    while(1);
-		    return 0;
-	}
+        default:
+            // print("incorrect configuration: unknown temac type");
+            while(1);
+            return 0;
+    }
 
     return n_packets;
 }
@@ -271,14 +271,14 @@ u32_t phy_link_detect(XEmacPs *xemacp, u32_t phy_addr)
 {
     u16_t status;
 
-	/* Read Phy Status register twice to get the confirmation of the current
-	 * link status.
-	 */
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
     XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
     XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
     if (status & IEEE_STAT_LINK_STATUS)
-	    return 1;
+        return 1;
     return 0;
 }
 #elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
@@ -286,14 +286,14 @@ static u32_t phy_link_detect(XAxiEthernet *xemacp, u32_t phy_addr)
 {
     u16_t status;
 
-	/* Read Phy Status register twice to get the confirmation of the current
-	 * link status.
-	 */
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
     XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
     XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
     if (status & IEEE_STAT_LINK_STATUS)
-	    return 1;
+        return 1;
     return 0;
 }
 #elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
@@ -301,14 +301,14 @@ static u32_t phy_link_detect(XEmacLite *xemacp, u32_t phy_addr)
 {
     u16_t status;
 
-	/* Read Phy Status register twice to get the confirmation of the current
-	 * link status.
-	 */
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
     XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
     XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
     if (status & IEEE_STAT_LINK_STATUS)
-	    return 1;
+        return 1;
     return 0;
 }
 #endif
@@ -318,14 +318,14 @@ u32_t phy_autoneg_status(XEmacPs *xemacp, u32_t phy_addr)
 {
     u16_t status;
 
-	/* Read Phy Status register twice to get the confirmation of the current
-	 * link status.
-	 */
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
     XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
     XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
     if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
-	    return 1;
+        return 1;
     return 0;
 }
 #elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
@@ -333,14 +333,14 @@ static u32_t phy_autoneg_status(XAxiEthernet *xemacp, u32_t phy_addr)
 {
     u16_t status;
 
-	/* Read Phy Status register twice to get the confirmation of the current
-	 * link status.
-	 */
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
     XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
     XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
     if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
-	    return 1;
+        return 1;
     return 0;
 }
 #elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
@@ -348,14 +348,14 @@ static u32_t phy_autoneg_status(XEmacLite *xemacp, u32_t phy_addr)
 {
     u16_t status;
 
-	/* Read Phy Status register twice to get the confirmation of the current
-	 * link status.
-	 */
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
     XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
     XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
     if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
-	    return 1;
+        return 1;
     return 0;
 }
 #endif
@@ -377,43 +377,43 @@ void eth_link_detect(struct netif *netif)
 #endif
 
     if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) ||
-			(eth_link_status == ETH_LINK_UNDEFINED))
-	    return;
+            (eth_link_status == ETH_LINK_UNDEFINED))
+        return;
 
     phy_link_status = phy_link_detect(xemacp, phyaddrforemac);
 
     if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status))
-	    eth_link_status = ETH_LINK_DOWN;
+        eth_link_status = ETH_LINK_DOWN;
 
     switch (eth_link_status) {
-	    case ETH_LINK_UNDEFINED:
-	    case ETH_LINK_UP:
-		    return;
-	    case ETH_LINK_DOWN:
-		    netif_set_link_down(netif);
-		    eth_link_status = ETH_LINK_NEGOTIATING;
-		    xil_printf("Ethernet Link down\r\n");
-		    break;
-	    case ETH_LINK_NEGOTIATING:
-		    if (phy_link_status &&
-			    phy_autoneg_status(xemacp, phyaddrforemac)) {
+        case ETH_LINK_UNDEFINED:
+        case ETH_LINK_UP:
+            return;
+        case ETH_LINK_DOWN:
+            netif_set_link_down(netif);
+            eth_link_status = ETH_LINK_NEGOTIATING;
+            xil_printf("Ethernet Link down\r\n");
+            break;
+        case ETH_LINK_NEGOTIATING:
+            if (phy_link_status &&
+                phy_autoneg_status(xemacp, phyaddrforemac)) {
 
-				/* Initiate Phy setup to get link speed */
+                /* Initiate Phy setup to get link speed */
 #if defined(XLWIP_CONFIG_INCLUDE_GEM)
-			    link_speed = phy_setup_emacps(xemacp,
-							    phyaddrforemac);
-			    XEmacPs_SetOperatingSpeed(xemacp, link_speed);
+                link_speed = phy_setup_emacps(xemacp,
+                                phyaddrforemac);
+                XEmacPs_SetOperatingSpeed(xemacp, link_speed);
 #elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
-			    link_speed = phy_setup_axiemac(xemacp);
-			    XAxiEthernet_SetOperatingSpeed(xemacp,
-							       link_speed);
+                link_speed = phy_setup_axiemac(xemacp);
+                XAxiEthernet_SetOperatingSpeed(xemacp,
+                                   link_speed);
 #endif
-			    netif_set_link_up(netif);
-			    eth_link_status = ETH_LINK_UP;
-			    xil_printf("Ethernet Link up\r\n");
-			}
-		    break;
-	}
+                netif_set_link_up(netif);
+                eth_link_status = ETH_LINK_UP;
+                xil_printf("Ethernet Link up\r\n");
+            }
+            break;
+    }
 }
 
 #ifdef OS_IS_FREERTOS
@@ -422,11 +422,11 @@ void link_detect_thread(void *p)
     struct netif *netif = (struct netif *) p;
 
     while (1) {
-		/* Call eth_link_detect() every second to detect Ethernet link
-		 * change.
-		 */
-	    eth_link_detect(netif);
-	    vTaskDelay(LINK_DETECT_THREAD_INTERVAL / portTICK_RATE_MS);
-	}
+        /* Call eth_link_detect() every second to detect Ethernet link
+         * change.
+         */
+        eth_link_detect(netif);
+        vTaskDelay(LINK_DETECT_THREAD_INTERVAL / portTICK_RATE_MS);
+    }
 }
 #endif
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h
index 1134b9ca65..1ff8d2b40e 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h
@@ -44,7 +44,7 @@
 
 
 #define ADVERTISE_100_AND_10        (ADVERTISE_10FULL | ADVERTISE_100FULL | \
-				    ADVERTISE_10HALF | ADVERTISE_100HALF)
+                    ADVERTISE_10HALF | ADVERTISE_100HALF)
 #define ADVERTISE_100               (ADVERTISE_100FULL | ADVERTISE_100HALF)
 #define ADVERTISE_10                (ADVERTISE_10FULL | ADVERTISE_10HALF)
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c
index 53df044cd5..9a7f93f42f 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c
@@ -76,14 +76,14 @@
 
 #if LWIP_IGMP
 static err_t xemacpsif_mac_filter_update (struct netif *netif,
-						    ip_addr_t *group, u8_t action);
+                            ip_addr_t *group, u8_t action);
 
 static u8_t xemacps_mcast_entry_mask = 0;
 #endif
 
 #if LWIP_IPV6 && LWIP_IPV6_MLD
 static err_t xemacpsif_mld6_mac_filter_update (struct netif *netif,
-						    ip_addr_t *group, u8_t action);
+                            ip_addr_t *group, u8_t action);
 
 static u8_t xemacps_mld6_mcast_entry_mask;
 #endif
@@ -101,22 +101,22 @@ int32_t lExpireCounter = 0;
  * this function also assumes that there are available BD's
  */
 err_t _unbuffered_low_level_output(xemacpsif_s *xemacpsif,
-												    struct pbuf *p)
+                                                    struct pbuf *p)
 {
     XStatus status = 0;
 
 #if ETH_PAD_SIZE
-    pbuf_header(p, -ETH_PAD_SIZE);	/* drop the padding word */
+    pbuf_header(p, -ETH_PAD_SIZE);    /* drop the padding word */
 #endif
     status = emacps_sgsend(xemacpsif, p);
     if (status != XST_SUCCESS) {
 #if LINK_STATS
     lwip_stats.link.drop++;
 #endif
-	}
+    }
 
 #if ETH_PAD_SIZE
-    pbuf_header(p, ETH_PAD_SIZE);	/* reclaim the padding word */
+    pbuf_header(p, ETH_PAD_SIZE);    /* reclaim the padding word */
 #endif
 
 #if LINK_STATS
@@ -148,23 +148,23 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p)
 
     SYS_ARCH_PROTECT(lev);
 
-	/* check if space is available to send */
+    /* check if space is available to send */
     freecnt = is_tx_space_available(xemacpsif);
     if (freecnt <= 5) {
     txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
-	    process_sent_bds(xemacpsif, txring);
-	}
+        process_sent_bds(xemacpsif, txring);
+    }
 
     if (is_tx_space_available(xemacpsif)) {
-	    _unbuffered_low_level_output(xemacpsif, p);
-	    err = ERR_OK;
-	} else {
+        _unbuffered_low_level_output(xemacpsif, p);
+        err = ERR_OK;
+    } else {
 #if LINK_STATS
-	    lwip_stats.link.drop++;
+        lwip_stats.link.drop++;
 #endif
-	    rt_kprintf("pack dropped, no space\r\n");
-	    err = ERR_MEM;
-	}
+        rt_kprintf("pack dropped, no space\r\n");
+        err = ERR_MEM;
+    }
 
     SYS_ARCH_UNPROTECT(lev);
     return err;
@@ -183,11 +183,11 @@ static struct pbuf * low_level_input(struct netif *netif)
     xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
     struct pbuf *p;
 
-	/* see if there is data to process */
+    /* see if there is data to process */
     if (pq_qlength(xemacpsif->recv_q) == 0)
-	    return NULL;
+        return NULL;
 
-	/* return one packet from receive q */
+    /* return one packet from receive q */
     p = (struct pbuf *)pq_dequeue(xemacpsif->recv_q);
     return p;
 }
@@ -202,9 +202,9 @@ static struct pbuf * low_level_input(struct netif *netif)
  */
 
 static err_t xemacpsif_output(struct netif *netif, struct pbuf *p,
-	    const ip_addr_t *ipaddr)
+        const ip_addr_t *ipaddr)
 {
-	/* resolve hardware address, then send (or queue) packet */
+    /* resolve hardware address, then send (or queue) packet */
     return etharp_output(netif, p, ipaddr);
 }
 
@@ -230,51 +230,51 @@ s32_t xemacpsif_input(struct netif *netif)
 #ifdef OS_IS_FREERTOS
     while (1)
 #endif
-	{
-		/* move received packet into a new pbuf */
-	    SYS_ARCH_PROTECT(lev);
-	    p = low_level_input(netif);
-	    SYS_ARCH_UNPROTECT(lev);
+    {
+        /* move received packet into a new pbuf */
+        SYS_ARCH_PROTECT(lev);
+        p = low_level_input(netif);
+        SYS_ARCH_UNPROTECT(lev);
 
-		/* no packet could be read, silently ignore this */
-	    if (p == NULL) {
-		    return 0;
-		}
+        /* no packet could be read, silently ignore this */
+        if (p == NULL) {
+            return 0;
+        }
 
-		/* points to packet payload, which starts with an Ethernet header */
-	    ethhdr = p->payload;
+        /* points to packet payload, which starts with an Ethernet header */
+        ethhdr = p->payload;
 
-	#if LINK_STATS
-	    lwip_stats.link.recv++;
-	#endif /* LINK_STATS */
+    #if LINK_STATS
+        lwip_stats.link.recv++;
+    #endif /* LINK_STATS */
 
-	    switch (htons(ethhdr->type)) {
-			/* IP or ARP packet? */
-		    case ETHTYPE_IP:
-		    case ETHTYPE_ARP:
-	#if LWIP_IPV6
-			/*IPv6 Packet?*/
-		    case ETHTYPE_IPV6:
-	#endif
-	#if PPPOE_SUPPORT
-				/* PPPoE packet? */
-		    case ETHTYPE_PPPOEDISC:
-		    case ETHTYPE_PPPOE:
-	#endif /* PPPOE_SUPPORT */
-				/* full packet send to tcpip_thread to process */
-			    if (netif->input(p, netif) != ERR_OK) {
-				    LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_input: IP input error\r\n"));
-				    pbuf_free(p);
-				    p = NULL;
-				}
-			    break;
+        switch (htons(ethhdr->type)) {
+            /* IP or ARP packet? */
+            case ETHTYPE_IP:
+            case ETHTYPE_ARP:
+    #if LWIP_IPV6
+            /*IPv6 Packet?*/
+            case ETHTYPE_IPV6:
+    #endif
+    #if PPPOE_SUPPORT
+                /* PPPoE packet? */
+            case ETHTYPE_PPPOEDISC:
+            case ETHTYPE_PPPOE:
+    #endif /* PPPOE_SUPPORT */
+                /* full packet send to tcpip_thread to process */
+                if (netif->input(p, netif) != ERR_OK) {
+                    LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_input: IP input error\r\n"));
+                    pbuf_free(p);
+                    p = NULL;
+                }
+                break;
 
-		    default:
-			    pbuf_free(p);
-			    p = NULL;
-			    break;
-		}
-	}
+            default:
+                pbuf_free(p);
+                p = NULL;
+                break;
+        }
+    }
 
     return 1;
 }
@@ -283,15 +283,15 @@ s32_t xemacpsif_input(struct netif *netif)
 #if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
 void vTimerCallback( TimerHandle_t pxTimer )
 {
-	/* Do something if the pxTimer parameter is NULL */
+    /* Do something if the pxTimer parameter is NULL */
     configASSERT(pxTimer);
 
     lExpireCounter++;
-	/* If the timer has expired 100 times then reset RX */
+    /* If the timer has expired 100 times then reset RX */
     if(lExpireCounter >= RESETRXTIMEOUT) {
-	    lExpireCounter = 0;
-	    xemacpsif_resetrx_on_no_rxdata(NetIf);
-	}
+        lExpireCounter = 0;
+        xemacpsif_resetrx_on_no_rxdata(NetIf);
+    }
 }
  #endif
 
@@ -308,15 +308,15 @@ static err_t low_level_init(struct netif *netif)
 
     xemacpsif = mem_malloc(sizeof *xemacpsif);
     if (xemacpsif == NULL) {
-	    LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
-	    return ERR_MEM;
-	}
+        LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
+        return ERR_MEM;
+    }
 
     xemac = mem_malloc(sizeof *xemac);
     if (xemac == NULL) {
-	    LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
-	    return ERR_MEM;
-	}
+        LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
+        return ERR_MEM;
+    }
 
     xemac->state = (void *)xemacpsif;
     xemac->topology_index = xtopology_find_index(mac_address);
@@ -325,9 +325,9 @@ static err_t low_level_init(struct netif *netif)
     xemacpsif->send_q = NULL;
     xemacpsif->recv_q = pq_create_queue();
     if (!xemacpsif->recv_q)
-	    return ERR_MEM;
+        return ERR_MEM;
 
-	/* maximum transfer unit */
+    /* maximum transfer unit */
 #ifdef ZYNQMP_USE_JUMBO
     netif->mtu = XEMACPS_MTU_JUMBO - XEMACPS_HDR_SIZE;
 #else
@@ -343,7 +343,7 @@ static err_t low_level_init(struct netif *netif)
 #endif
 
     netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
-										    NETIF_FLAG_LINK_UP;
+                                            NETIF_FLAG_LINK_UP;
 
 #if LWIP_IPV6 && LWIP_IPV6_MLD
     netif->flags |= NETIF_FLAG_MLD6;
@@ -356,52 +356,52 @@ static err_t low_level_init(struct netif *netif)
 #if 0
     sys_sem_new(&xemac->sem_rx_data_available, 0);
 #endif
-	/* obtain config of this emac */
+    /* obtain config of this emac */
     mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)(UINTPTR)netif->state);
 
 #if EL1_NONSECURE
-	/* Request device to indicate that this library is using it */
+    /* Request device to indicate that this library is using it */
     if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) {
-	    Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_0, 1, 0, 100, 1, 0, 0);
-	}
+        Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_0, 1, 0, 100, 1, 0, 0);
+    }
     if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) {
-	    Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_1, 1, 0, 100, 1, 0, 0);
-	}
+        Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_1, 1, 0, 100, 1, 0, 0);
+    }
 #endif
 
     status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
-					    mac_config->BaseAddress);
+                        mac_config->BaseAddress);
     if (status != XST_SUCCESS) {
-	    xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
-	}
+        xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
+    }
 
-	/* initialize the mac */
+    /* initialize the mac */
     init_emacps(xemacpsif, netif);
 
     dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-													    XEMACPS_DMACR_OFFSET);
+                                                        XEMACPS_DMACR_OFFSET);
     dmacrreg = dmacrreg | (0x00000010);
     XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-										    XEMACPS_DMACR_OFFSET, dmacrreg);
+                                            XEMACPS_DMACR_OFFSET, dmacrreg);
 
 #if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
-	/* Freertos tick is 10ms by default; set period to the same */
+    /* Freertos tick is 10ms by default; set period to the same */
     xemac->xTimer = xTimerCreate("Timer", 10, pdTRUE, ( void * ) 1, vTimerCallback);
     if (xemac->xTimer == NULL) {
-	    xil_printf("In %s:Timer creation failed....\r\n", __func__);
-	} else {
-	    if(xTimerStart(xemac->xTimer, 0) != pdPASS) {
-		    xil_printf("In %s:Timer start failed....\r\n", __func__);
-		}
-	}
+        xil_printf("In %s:Timer creation failed....\r\n", __func__);
+    } else {
+        if(xTimerStart(xemac->xTimer, 0) != pdPASS) {
+            xil_printf("In %s:Timer start failed....\r\n", __func__);
+        }
+    }
 #endif
     setup_isr(xemac);
     init_dma(xemac);
     start_emacps(xemacpsif);
 
-	/* replace the state in netif (currently the emac baseaddress)
-	 * with the mac instance pointer.
-	 */
+    /* replace the state in netif (currently the emac baseaddress)
+     * with the mac instance pointer.
+     */
     netif->state = (void *)xemac;
 
     return ERR_OK;
@@ -419,17 +419,17 @@ void HandleEmacPsError(struct xemac_s *xemac)
     xemacpsif = (xemacpsif_s *)(xemac->state);
     free_txrx_pbufs(xemacpsif);
     status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
-					    mac_config->BaseAddress);
+                        mac_config->BaseAddress);
     if (status != XST_SUCCESS) {
-	    xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
-	}
-	/* initialize the mac */
+        xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
+    }
+    /* initialize the mac */
     init_emacps_on_error(xemacpsif, NetIf);
     dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-													    XEMACPS_DMACR_OFFSET);
+                                                        XEMACPS_DMACR_OFFSET);
     dmacrreg = dmacrreg | (0x01000000);
     XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-										    XEMACPS_DMACR_OFFSET, dmacrreg);
+                                            XEMACPS_DMACR_OFFSET, dmacrreg);
     setup_isr(xemac);
     init_dma(xemac);
     start_emacps(xemacpsif);
@@ -446,18 +446,18 @@ void HandleTxErrors(struct xemac_s *xemac)
     SYS_ARCH_PROTECT(lev);
     xemacpsif = (xemacpsif_s *)(xemac->state);
     netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-											    XEMACPS_NWCTRL_OFFSET);
+                                                XEMACPS_NWCTRL_OFFSET);
     netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
     XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-								    XEMACPS_NWCTRL_OFFSET, netctrlreg);
+                                    XEMACPS_NWCTRL_OFFSET, netctrlreg);
     free_onlytx_pbufs(xemacpsif);
 
     clean_dma_txdescs(xemac);
     netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-												    XEMACPS_NWCTRL_OFFSET);
+                                                    XEMACPS_NWCTRL_OFFSET);
     netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
     XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-									    XEMACPS_NWCTRL_OFFSET, netctrlreg);
+                                        XEMACPS_NWCTRL_OFFSET, netctrlreg);
     SYS_ARCH_UNPROTECT(lev);
 }
 
@@ -470,15 +470,15 @@ static u8_t xemacpsif_ip6_addr_ismulticast(ip6_addr_t* ip_addr)
            ip6_addr_ismulticast_sitelocal(ip_addr) ||
            ip6_addr_ismulticast_orglocal(ip_addr)  ||
            ip6_addr_ismulticast_global(ip_addr)) {
-	/*Return TRUE if IPv6 is Multicast type*/
+    /*Return TRUE if IPv6 is Multicast type*/
     return TRUE;
-	} else {
+    } else {
     return FALSE;
-	}
+    }
 }
 
 static void xemacpsif_mld6_mac_hash_update (struct netif *netif, u8_t *ip_addr,
-	    u8_t action)
+        u8_t action)
 {
     u8_t multicast_mac_addr[6];
     struct xemac_s *xemac = (struct xemac_s *) (netif->state);
@@ -493,99 +493,99 @@ static void xemacpsif_mld6_mac_hash_update (struct netif *netif, u8_t *ip_addr,
     multicast_mac_addr[4] = ip_addr[14];
     multicast_mac_addr[5] = ip_addr[15];
 
-	/* Wait till all sent packets are acknowledged from HW */
+    /* Wait till all sent packets are acknowledged from HW */
     while(txring->HwCnt);
 
     SYS_ARCH_DECL_PROTECT(lev);
 
     SYS_ARCH_PROTECT(lev);
 
-	/* Stop Ethernet */
+    /* Stop Ethernet */
     XEmacPs_Stop(&xemacpsif->emacps);
 
     if (action == NETIF_ADD_MAC_FILTER) {
-		/* Set Mulitcast mac address in hash table */
-	    XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
+        /* Set Mulitcast mac address in hash table */
+        XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
 
-	} else if (action == NETIF_DEL_MAC_FILTER) {
-		/* Remove Mulitcast mac address in hash table */
-	    XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
-	}
+    } else if (action == NETIF_DEL_MAC_FILTER) {
+        /* Remove Mulitcast mac address in hash table */
+        XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
+    }
 
-	/* Reset DMA */
+    /* Reset DMA */
     reset_dma(xemac);
 
-	/* Start Ethernet */
+    /* Start Ethernet */
     XEmacPs_Start(&xemacpsif->emacps);
 
     SYS_ARCH_UNPROTECT(lev);
 }
 
 static err_t xemacpsif_mld6_mac_filter_update (struct netif *netif, ip_addr_t *group,
-	    u8_t action)
+        u8_t action)
 {
     u8_t temp_mask;
     unsigned int i;
     u8_t * ip_addr = (u8_t *) group;
 
     if(!(xemacpsif_ip6_addr_ismulticast((ip6_addr_t*) ip_addr))) {
-	    LWIP_DEBUGF(NETIF_DEBUG,
-                                ("%s: The requested MAC address is not a multicast address.\r\n", __func__));								 LWIP_DEBUGF(NETIF_DEBUG,
-		                ("Multicast address add operation failure !!\r\n"));
+        LWIP_DEBUGF(NETIF_DEBUG,
+                                ("%s: The requested MAC address is not a multicast address.\r\n", __func__));                                 LWIP_DEBUGF(NETIF_DEBUG,
+                        ("Multicast address add operation failure !!\r\n"));
                         return ERR_ARG;
-	}
+    }
     if (action == NETIF_ADD_MAC_FILTER) {
-	    for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
-		    temp_mask = (0x01) << i;
-		    if ((xemacps_mld6_mcast_entry_mask & temp_mask) == temp_mask) {
-			    continue;
-			}
-		    xemacps_mld6_mcast_entry_mask |= temp_mask;
+        for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+            temp_mask = (0x01) << i;
+            if ((xemacps_mld6_mcast_entry_mask & temp_mask) == temp_mask) {
+                continue;
+            }
+            xemacps_mld6_mcast_entry_mask |= temp_mask;
 
-			/* Update mac address in hash table */
-		    xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
+            /* Update mac address in hash table */
+            xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
 
-		    LWIP_DEBUGF(NETIF_DEBUG,
-					("%s: Multicast MAC address successfully added.\r\n", __func__));
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: Multicast MAC address successfully added.\r\n", __func__));
 
-		    return ERR_OK;
-		}
-	    LWIP_DEBUGF(NETIF_DEBUG,
-				("%s: No multicast address registers left.\r\n", __func__));
-	    LWIP_DEBUGF(NETIF_DEBUG,
-				("Multicast MAC address add operation failure !!\r\n"));
-	    return ERR_MEM;
-	} else if (action == NETIF_DEL_MAC_FILTER) {
-	    for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
-		    temp_mask = (0x01) << i;
-		    if ((xemacps_mld6_mcast_entry_mask & temp_mask) != temp_mask) {
-			    continue;
-			}
-		    xemacps_mld6_mcast_entry_mask &= (~temp_mask);
+            return ERR_OK;
+        }
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("%s: No multicast address registers left.\r\n", __func__));
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("Multicast MAC address add operation failure !!\r\n"));
+        return ERR_MEM;
+    } else if (action == NETIF_DEL_MAC_FILTER) {
+        for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+            temp_mask = (0x01) << i;
+            if ((xemacps_mld6_mcast_entry_mask & temp_mask) != temp_mask) {
+                continue;
+            }
+            xemacps_mld6_mcast_entry_mask &= (~temp_mask);
 
-			/* Update mac address in hash table */
-		    xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
+            /* Update mac address in hash table */
+            xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
 
-		    LWIP_DEBUGF(NETIF_DEBUG,
-					("%s: Multicast MAC address successfully removed.\r\n", __func__));
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: Multicast MAC address successfully removed.\r\n", __func__));
 
-		    return ERR_OK;
-		}
-	    LWIP_DEBUGF(NETIF_DEBUG,
-				("%s: No multicast address registers present with\r\n", __func__));
-	    LWIP_DEBUGF(NETIF_DEBUG,
-				("the requested Multicast MAC address.\r\n"));
-	    LWIP_DEBUGF(NETIF_DEBUG,
-				("Multicast MAC address removal failure!!.\r\n"));
-	    return ERR_MEM;
-	}
+            return ERR_OK;
+        }
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("%s: No multicast address registers present with\r\n", __func__));
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("the requested Multicast MAC address.\r\n"));
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("Multicast MAC address removal failure!!.\r\n"));
+        return ERR_MEM;
+    }
     return ERR_ARG;
 }
 #endif
 
 #if LWIP_IGMP
 static void xemacpsif_mac_hash_update (struct netif *netif, u8_t *ip_addr,
-	    u8_t action)
+        u8_t action)
 {
     u8_t multicast_mac_addr[6];
     struct xemac_s *xemac = (struct xemac_s *) (netif->state);
@@ -600,102 +600,102 @@ static void xemacpsif_mac_hash_update (struct netif *netif, u8_t *ip_addr,
     multicast_mac_addr[4] = ip_addr[2];
     multicast_mac_addr[5] = ip_addr[3];
 
-	/* Wait till all sent packets are acknowledged from HW */
+    /* Wait till all sent packets are acknowledged from HW */
     while(txring->HwCnt);
 
     SYS_ARCH_DECL_PROTECT(lev);
 
     SYS_ARCH_PROTECT(lev);
 
-	/* Stop Ethernet */
+    /* Stop Ethernet */
     XEmacPs_Stop(&xemacpsif->emacps);
 
     if (action == IGMP_ADD_MAC_FILTER) {
-		/* Set Mulitcast mac address in hash table */
-	    XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
+        /* Set Mulitcast mac address in hash table */
+        XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
 
-	} else if (action == IGMP_DEL_MAC_FILTER) {
-		/* Remove Mulitcast mac address in hash table */
-	    XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
-	}
+    } else if (action == IGMP_DEL_MAC_FILTER) {
+        /* Remove Mulitcast mac address in hash table */
+        XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
+    }
 
-	/* Reset DMA */
+    /* Reset DMA */
     reset_dma(xemac);
 
-	/* Start Ethernet */
+    /* Start Ethernet */
     XEmacPs_Start(&xemacpsif->emacps);
 
     SYS_ARCH_UNPROTECT(lev);
 }
 
 static err_t xemacpsif_mac_filter_update (struct netif *netif, ip_addr_t *group,
-	    u8_t action)
+        u8_t action)
 {
     u8_t temp_mask;
     unsigned int i;
     u8_t * ip_addr = (u8_t *) group;
 
     if ((ip_addr[0] < 224) && (ip_addr[0] > 239)) {
-	    LWIP_DEBUGF(NETIF_DEBUG,
-				("%s: The requested MAC address is not a multicast address.\r\n", __func__));
-	    LWIP_DEBUGF(NETIF_DEBUG,
-				("Multicast address add operation failure !!\r\n"));
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("%s: The requested MAC address is not a multicast address.\r\n", __func__));
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("Multicast address add operation failure !!\r\n"));
 
-	    return ERR_ARG;
-	}
+        return ERR_ARG;
+    }
 
     if (action == IGMP_ADD_MAC_FILTER) {
 
-	    for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
-		    temp_mask = (0x01) << i;
-		    if ((xemacps_mcast_entry_mask & temp_mask) == temp_mask) {
-			    continue;
-			}
-		    xemacps_mcast_entry_mask |= temp_mask;
+        for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+            temp_mask = (0x01) << i;
+            if ((xemacps_mcast_entry_mask & temp_mask) == temp_mask) {
+                continue;
+            }
+            xemacps_mcast_entry_mask |= temp_mask;
 
-			/* Update mac address in hash table */
-		    xemacpsif_mac_hash_update(netif, ip_addr, action);
+            /* Update mac address in hash table */
+            xemacpsif_mac_hash_update(netif, ip_addr, action);
 
-		    LWIP_DEBUGF(NETIF_DEBUG,
-					("%s: Multicast MAC address successfully added.\r\n", __func__));
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: Multicast MAC address successfully added.\r\n", __func__));
 
-		    return ERR_OK;
-		}
-	    if (i == XEMACPS_MAX_MAC_ADDR) {
-		    LWIP_DEBUGF(NETIF_DEBUG,
-					("%s: No multicast address registers left.\r\n", __func__));
-		    LWIP_DEBUGF(NETIF_DEBUG,
-					("Multicast MAC address add operation failure !!\r\n"));
+            return ERR_OK;
+        }
+        if (i == XEMACPS_MAX_MAC_ADDR) {
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: No multicast address registers left.\r\n", __func__));
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("Multicast MAC address add operation failure !!\r\n"));
 
-		    return ERR_MEM;
-		}
-	} else if (action == IGMP_DEL_MAC_FILTER) {
-	    for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
-		    temp_mask = (0x01) << i;
-		    if ((xemacps_mcast_entry_mask & temp_mask) != temp_mask) {
-			    continue;
-			}
-		    xemacps_mcast_entry_mask &= (~temp_mask);
+            return ERR_MEM;
+        }
+    } else if (action == IGMP_DEL_MAC_FILTER) {
+        for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+            temp_mask = (0x01) << i;
+            if ((xemacps_mcast_entry_mask & temp_mask) != temp_mask) {
+                continue;
+            }
+            xemacps_mcast_entry_mask &= (~temp_mask);
 
-			/* Update mac address in hash table */
-		    xemacpsif_mac_hash_update(netif, ip_addr, action);
+            /* Update mac address in hash table */
+            xemacpsif_mac_hash_update(netif, ip_addr, action);
 
-		    LWIP_DEBUGF(NETIF_DEBUG,
-					("%s: Multicast MAC address successfully removed.\r\n", __func__));
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: Multicast MAC address successfully removed.\r\n", __func__));
 
-		    return ERR_OK;
-		}
-	    if (i == XEMACPS_MAX_MAC_ADDR) {
-		    LWIP_DEBUGF(NETIF_DEBUG,
-					("%s: No multicast address registers present with\r\n", __func__));
-		    LWIP_DEBUGF(NETIF_DEBUG,
-					("the requested Multicast MAC address.\r\n"));
-		    LWIP_DEBUGF(NETIF_DEBUG,
-					("Multicast MAC address removal failure!!.\r\n"));
+            return ERR_OK;
+        }
+        if (i == XEMACPS_MAX_MAC_ADDR) {
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: No multicast address registers present with\r\n", __func__));
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("the requested Multicast MAC address.\r\n"));
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("Multicast MAC address removal failure!!.\r\n"));
 
-		    return ERR_MEM;
-		}
-	}
+            return ERR_MEM;
+        }
+    }
     return ERR_OK;
 }
 #endif
@@ -712,9 +712,9 @@ static err_t xemacpsif_mac_filter_update (struct netif *netif, ip_addr_t *group,
 err_t xemacpsif_init(struct netif *netif)
 {
 #if LWIP_SNMP
-	/* ifType ethernetCsmacd(6) @see RFC1213 */
+    /* ifType ethernetCsmacd(6) @see RFC1213 */
     netif->link_type = 6;
-	/* your link speed here */
+    /* your link speed here */
     netif->link_speed = ;
     netif->ts = 0;
     netif->ifinoctets = 0;
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c
index af7da9d7dd..f917b10a97 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c
@@ -57,7 +57,7 @@
 
 #include 
 
-#define INTC_BASE_ADDR	    XPAR_SCUGIC_0_CPU_BASEADDR
+#define INTC_BASE_ADDR        XPAR_SCUGIC_0_CPU_BASEADDR
 #define INTC_DIST_BASE_ADDR    XPAR_SCUGIC_0_DIST_BASEADDR
 
 /* Byte alignment of BDs */
@@ -122,8 +122,8 @@ static volatile u32_t bd_space_attr_set = 0;
 long xInsideISR = 0;
 #endif
 
-#define XEMACPS_BD_TO_INDEX(ringptr, bdptr)				\
-	(((UINTPTR)bdptr - (UINTPTR)(ringptr)->BaseBdAddr) / (ringptr)->Separation)
+#define XEMACPS_BD_TO_INDEX(ringptr, bdptr)                \
+    (((UINTPTR)bdptr - (UINTPTR)(ringptr)->BaseBdAddr) / (ringptr)->Separation)
 
 
 s32_t is_tx_space_available(xemacpsif_s *emac)
@@ -133,7 +133,7 @@ s32_t is_tx_space_available(xemacpsif_s *emac)
 
     txring = &(XEmacPs_GetTxRing(&emac->emacps));
 
-	/* tx space is available as long as there are valid BD's */
+    /* tx space is available as long as there are valid BD's */
     freecnt = XEmacPs_BdRingGetFreeCnt(txring);
     return freecnt;
 }
@@ -145,23 +145,23 @@ u32_t get_base_index_txpbufsstorage (xemacpsif_s *xemacpsif)
     u32_t index;
 #ifdef XPAR_XEMACPS_0_BASEADDR
     if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
-	    index = 0;
-	}
+        index = 0;
+    }
 #endif
 #ifdef XPAR_XEMACPS_1_BASEADDR
     if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_1_BASEADDR) {
-	    index = XLWIP_CONFIG_N_TX_DESC;
-	}
+        index = XLWIP_CONFIG_N_TX_DESC;
+    }
 #endif
 #ifdef XPAR_XEMACPS_2_BASEADDR
     if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_2_BASEADDR) {
-	    index = 2 * XLWIP_CONFIG_N_TX_DESC;
-	}
+        index = 2 * XLWIP_CONFIG_N_TX_DESC;
+    }
 #endif
 #ifdef XPAR_XEMACPS_3_BASEADDR
     if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_3_BASEADDR) {
-	    index = 3 * XLWIP_CONFIG_N_TX_DESC;
-	}
+        index = 3 * XLWIP_CONFIG_N_TX_DESC;
+    }
 #endif
     return index;
 }
@@ -172,23 +172,23 @@ u32_t get_base_index_rxpbufsstorage (xemacpsif_s *xemacpsif)
     u32_t index;
 #ifdef XPAR_XEMACPS_0_BASEADDR
     if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
-	    index = 0;
-	}
+        index = 0;
+    }
 #endif
 #ifdef XPAR_XEMACPS_1_BASEADDR
     if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_1_BASEADDR) {
-	    index = XLWIP_CONFIG_N_RX_DESC;
-	}
+        index = XLWIP_CONFIG_N_RX_DESC;
+    }
 #endif
 #ifdef XPAR_XEMACPS_2_BASEADDR
     if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_2_BASEADDR) {
-	    index = 2 * XLWIP_CONFIG_N_RX_DESC;
-	}
+        index = 2 * XLWIP_CONFIG_N_RX_DESC;
+    }
 #endif
 #ifdef XPAR_XEMACPS_3_BASEADDR
     if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_3_BASEADDR) {
-	    index = 3 * XLWIP_CONFIG_N_RX_DESC;
-	}
+        index = 3 * XLWIP_CONFIG_N_RX_DESC;
+    }
 #endif
     return index;
 }
@@ -208,41 +208,41 @@ void process_sent_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *txring)
     index = get_base_index_txpbufsstorage (xemacpsif);
 
     while (1) {
-		/* obtain processed BD's */
-	    n_bds = XEmacPs_BdRingFromHwTx(txring,
-							    XLWIP_CONFIG_N_TX_DESC, &txbdset);
-	    if (n_bds == 0)  {
-		    return;
-		}
-		/* free the processed BD's */
-	    n_pbufs_freed = n_bds;
-	    curbdpntr = txbdset;
-	    while (n_pbufs_freed > 0) {
-		    bdindex = XEMACPS_BD_TO_INDEX(txring, curbdpntr);
-		    temp = (u32 *)curbdpntr;
-			*temp = 0;
-		    temp++;
-		    if (bdindex == (XLWIP_CONFIG_N_TX_DESC - 1)) {
-				*temp = 0xC0000000;
-			} else {
-				*temp = 0x80000000;
-			}
-		    dsb();
-		    p = (struct pbuf *)tx_pbufs_storage[index + bdindex];
-		    if (p != NULL) {
-			    pbuf_free(p);
-			}
-		    tx_pbufs_storage[index + bdindex] = 0;
-		    curbdpntr = XEmacPs_BdRingNext(txring, curbdpntr);
-		    n_pbufs_freed--;
-		    dsb();
-		}
+        /* obtain processed BD's */
+        n_bds = XEmacPs_BdRingFromHwTx(txring,
+                                XLWIP_CONFIG_N_TX_DESC, &txbdset);
+        if (n_bds == 0)  {
+            return;
+        }
+        /* free the processed BD's */
+        n_pbufs_freed = n_bds;
+        curbdpntr = txbdset;
+        while (n_pbufs_freed > 0) {
+            bdindex = XEMACPS_BD_TO_INDEX(txring, curbdpntr);
+            temp = (u32 *)curbdpntr;
+            *temp = 0;
+            temp++;
+            if (bdindex == (XLWIP_CONFIG_N_TX_DESC - 1)) {
+                *temp = 0xC0000000;
+            } else {
+                *temp = 0x80000000;
+            }
+            dsb();
+            p = (struct pbuf *)tx_pbufs_storage[index + bdindex];
+            if (p != NULL) {
+                pbuf_free(p);
+            }
+            tx_pbufs_storage[index + bdindex] = 0;
+            curbdpntr = XEmacPs_BdRingNext(txring, curbdpntr);
+            n_pbufs_freed--;
+            dsb();
+        }
 
-	    status = XEmacPs_BdRingFree(txring, n_bds, txbdset);
-	    if (status != XST_SUCCESS) {
-		    LWIP_DEBUGF(NETIF_DEBUG, ("Failure while freeing in Tx Done ISR\r\n"));
-		}
-	}
+        status = XEmacPs_BdRingFree(txring, n_bds, txbdset);
+        if (status != XST_SUCCESS) {
+            LWIP_DEBUGF(NETIF_DEBUG, ("Failure while freeing in Tx Done ISR\r\n"));
+        }
+    }
     return;
 }
 
@@ -261,9 +261,9 @@ void emacps_send_handler(void *arg)
     regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_TXSR_OFFSET);
     XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,XEMACPS_TXSR_OFFSET, regval);
 
-	/* If Transmit done interrupt is asserted, process completed BD's */
-	/* Since RT-Thread does not support freeing memory in interrupts, comment it out */
-	// process_sent_bds(xemacpsif, txringptr);
+    /* If Transmit done interrupt is asserted, process completed BD's */
+    /* Since RT-Thread does not support freeing memory in interrupts, comment it out */
+    // process_sent_bds(xemacpsif, txringptr);
 #ifdef OS_IS_FREERTOS
     xInsideISR--;
 #endif
@@ -289,79 +289,79 @@ XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p)
 
     index = get_base_index_txpbufsstorage (xemacpsif);
 
-	/* first count the number of pbufs */
+    /* first count the number of pbufs */
     for (q = p, n_pbufs = 0; q != NULL; q = q->next)
-	    n_pbufs++;
+        n_pbufs++;
 
-	/* obtain as many BD's */
+    /* obtain as many BD's */
     status = XEmacPs_BdRingAlloc(txring, n_pbufs, &txbdset);
     if (status != XST_SUCCESS) {
-	    mtcpsr(lev);
-	    LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error allocating TxBD\r\n"));
-	    return XST_FAILURE;
-	}
+        mtcpsr(lev);
+        LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error allocating TxBD\r\n"));
+        return XST_FAILURE;
+    }
 
     for(q = p, txbd = txbdset; q != NULL; q = q->next) {
-	    bdindex = XEMACPS_BD_TO_INDEX(txring, txbd);
-	    if (tx_pbufs_storage[index + bdindex] != 0) {
-		    mtcpsr(lev);
-		    LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n"));
-		    return XST_FAILURE;
-		}
+        bdindex = XEMACPS_BD_TO_INDEX(txring, txbd);
+        if (tx_pbufs_storage[index + bdindex] != 0) {
+            mtcpsr(lev);
+            LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n"));
+            return XST_FAILURE;
+        }
 
-		/* Send the data from the pbuf to the interface, one pbuf at a
-		   time. The size of the data in each pbuf is kept in the ->len
-		   variable. */
-	    if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
-		    Xil_DCacheFlushRange((UINTPTR)q->payload, (UINTPTR)q->len);
-		}
+        /* Send the data from the pbuf to the interface, one pbuf at a
+           time. The size of the data in each pbuf is kept in the ->len
+           variable. */
+        if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+            Xil_DCacheFlushRange((UINTPTR)q->payload, (UINTPTR)q->len);
+        }
 
-	    XEmacPs_BdSetAddressTx(txbd, (UINTPTR)q->payload);
+        XEmacPs_BdSetAddressTx(txbd, (UINTPTR)q->payload);
 
 #ifdef ZYNQMP_USE_JUMBO
-	    max_fr_size = MAX_FRAME_SIZE_JUMBO - 18;
+        max_fr_size = MAX_FRAME_SIZE_JUMBO - 18;
 #else
-	    max_fr_size = XEMACPS_MAX_FRAME_SIZE - 18;
+        max_fr_size = XEMACPS_MAX_FRAME_SIZE - 18;
 #endif
-	    if (q->len > max_fr_size)
-		    XEmacPs_BdSetLength(txbd, max_fr_size & 0x3FFF);
-	    else
-		    XEmacPs_BdSetLength(txbd, q->len & 0x3FFF);
+        if (q->len > max_fr_size)
+            XEmacPs_BdSetLength(txbd, max_fr_size & 0x3FFF);
+        else
+            XEmacPs_BdSetLength(txbd, q->len & 0x3FFF);
 
-	    tx_pbufs_storage[index + bdindex] = (UINTPTR)q;
+        tx_pbufs_storage[index + bdindex] = (UINTPTR)q;
 
-	    pbuf_ref(q);
-	    last_txbd = txbd;
-	    XEmacPs_BdClearLast(txbd);
-	    txbd = XEmacPs_BdRingNext(txring, txbd);
-	}
+        pbuf_ref(q);
+        last_txbd = txbd;
+        XEmacPs_BdClearLast(txbd);
+        txbd = XEmacPs_BdRingNext(txring, txbd);
+    }
     XEmacPs_BdSetLast(last_txbd);
-	/* For fragmented packets, remember the 1st BD allocated for the 1st
-	   packet fragment. The used bit for this BD should be cleared at the end
-	   after clearing out used bits for other fragments. For packets without
-	   just remember the allocated BD. */
+    /* For fragmented packets, remember the 1st BD allocated for the 1st
+       packet fragment. The used bit for this BD should be cleared at the end
+       after clearing out used bits for other fragments. For packets without
+       just remember the allocated BD. */
     temp_txbd = txbdset;
     txbd = txbdset;
     txbd = XEmacPs_BdRingNext(txring, txbd);
     q = p->next;
     for(; q != NULL; q = q->next) {
-	    XEmacPs_BdClearTxUsed(txbd);
-	    dsb();
-	    txbd = XEmacPs_BdRingNext(txring, txbd);
-	}
+        XEmacPs_BdClearTxUsed(txbd);
+        dsb();
+        txbd = XEmacPs_BdRingNext(txring, txbd);
+    }
     XEmacPs_BdClearTxUsed(temp_txbd);
     dsb();
 
     status = XEmacPs_BdRingToHw(txring, n_pbufs, txbdset);
     if (status != XST_SUCCESS) {
-	    mtcpsr(lev);
-	    LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error submitting TxBD\r\n"));
-	    return XST_FAILURE;
-	}
-	/* Start transmit */
+        mtcpsr(lev);
+        LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error submitting TxBD\r\n"));
+        return XST_FAILURE;
+    }
+    /* Start transmit */
     XEmacPs_WriteReg((xemacpsif->emacps).Config.BaseAddress,
     XEMACPS_NWCTRL_OFFSET,
-	(XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress,
+    (XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress,
     XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK));
 
     mtcpsr(lev);
@@ -382,63 +382,63 @@ void setup_rx_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *rxring)
 
     freebds = XEmacPs_BdRingGetFreeCnt (rxring);
     while (freebds > 0) {
-	    freebds--;
+        freebds--;
 #ifdef ZYNQMP_USE_JUMBO
-	    p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL);
+        p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL);
 #else
-	    p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
+        p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
 #endif
-	    if (!p) {
+        if (!p) {
 #if LINK_STATS
-		    lwip_stats.link.memerr++;
-		    lwip_stats.link.drop++;
+            lwip_stats.link.memerr++;
+            lwip_stats.link.drop++;
 #endif
-		    rt_kprintf("unable to alloc pbuf in recv_handler\r\n");
-		    return;
-		}
-	    status = XEmacPs_BdRingAlloc(rxring, 1, &rxbd);
-	    if (status != XST_SUCCESS) {
-		    LWIP_DEBUGF(NETIF_DEBUG, ("setup_rx_bds: Error allocating RxBD\r\n"));
-		    pbuf_free(p);
-		    return;
-		}
-	    status = XEmacPs_BdRingToHw(rxring, 1, rxbd);
-	    if (status != XST_SUCCESS) {
-		    LWIP_DEBUGF(NETIF_DEBUG, ("Error committing RxBD to hardware: "));
-		    if (status == XST_DMA_SG_LIST_ERROR) {
-			    LWIP_DEBUGF(NETIF_DEBUG, ("XST_DMA_SG_LIST_ERROR: this function was called out of sequence with XEmacPs_BdRingAlloc()\r\n"));
-			}
-		    else {
-			    LWIP_DEBUGF(NETIF_DEBUG, ("set of BDs was rejected because the first BD did not have its start-of-packet bit set, or the last BD did not have its end-of-packet bit set, or any one of the BD set has 0 as length value\r\n"));
-			}
+            rt_kprintf("unable to alloc pbuf in recv_handler\r\n");
+            return;
+        }
+        status = XEmacPs_BdRingAlloc(rxring, 1, &rxbd);
+        if (status != XST_SUCCESS) {
+            LWIP_DEBUGF(NETIF_DEBUG, ("setup_rx_bds: Error allocating RxBD\r\n"));
+            pbuf_free(p);
+            return;
+        }
+        status = XEmacPs_BdRingToHw(rxring, 1, rxbd);
+        if (status != XST_SUCCESS) {
+            LWIP_DEBUGF(NETIF_DEBUG, ("Error committing RxBD to hardware: "));
+            if (status == XST_DMA_SG_LIST_ERROR) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("XST_DMA_SG_LIST_ERROR: this function was called out of sequence with XEmacPs_BdRingAlloc()\r\n"));
+            }
+            else {
+                LWIP_DEBUGF(NETIF_DEBUG, ("set of BDs was rejected because the first BD did not have its start-of-packet bit set, or the last BD did not have its end-of-packet bit set, or any one of the BD set has 0 as length value\r\n"));
+            }
 
-		    pbuf_free(p);
-		    XEmacPs_BdRingUnAlloc(rxring, 1, rxbd);
-		    return;
-		}
+            pbuf_free(p);
+            XEmacPs_BdRingUnAlloc(rxring, 1, rxbd);
+            return;
+        }
 #ifdef ZYNQMP_USE_JUMBO
-	    if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
-		    Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO);
-		}
+        if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+            Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO);
+        }
 #else
-	    if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
-		    Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE);
-		}
+        if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+            Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE);
+        }
 #endif
-	    bdindex = XEMACPS_BD_TO_INDEX(rxring, rxbd);
-	    temp = (u32 *)rxbd;
-	    if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
-			*temp = 0x00000002;
-		} else {
-			*temp = 0;
-		}
-	    temp++;
-		*temp = 0;
-	    dsb();
+        bdindex = XEMACPS_BD_TO_INDEX(rxring, rxbd);
+        temp = (u32 *)rxbd;
+        if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
+            *temp = 0x00000002;
+        } else {
+            *temp = 0;
+        }
+        temp++;
+        *temp = 0;
+        dsb();
 
-	    XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload);
-	    rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
-	}
+        XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload);
+        rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
+    }
 }
 
 void emacps_recv_handler(void *arg)
@@ -465,60 +465,60 @@ void emacps_recv_handler(void *arg)
 
     gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
     index = get_base_index_rxpbufsstorage (xemacpsif);
-	/*
-	 * If Reception done interrupt is asserted, call RX call back function
-	 * to handle the processed BDs and then raise the according flag.
-	 */
+    /*
+     * If Reception done interrupt is asserted, call RX call back function
+     * to handle the processed BDs and then raise the according flag.
+     */
     regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET);
     XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET, regval);
     if (gigeversion <= 2) {
-		    resetrx_on_no_rxdata(xemacpsif);
-	}
+            resetrx_on_no_rxdata(xemacpsif);
+    }
 
     while(1) {
 
-	    bd_processed = XEmacPs_BdRingFromHwRx(rxring, XLWIP_CONFIG_N_RX_DESC, &rxbdset);
-	    if (bd_processed <= 0) {
-		    break;
-		}
-	    for (k = 0, curbdptr=rxbdset; k < bd_processed; k++) {
+        bd_processed = XEmacPs_BdRingFromHwRx(rxring, XLWIP_CONFIG_N_RX_DESC, &rxbdset);
+        if (bd_processed <= 0) {
+            break;
+        }
+        for (k = 0, curbdptr=rxbdset; k < bd_processed; k++) {
 
-		    bdindex = XEMACPS_BD_TO_INDEX(rxring, curbdptr);
-		    p = (struct pbuf *)rx_pbufs_storage[index + bdindex];
-			/*
-			 * Adjust the buffer size to the actual number of bytes received.
-			 */
+            bdindex = XEMACPS_BD_TO_INDEX(rxring, curbdptr);
+            p = (struct pbuf *)rx_pbufs_storage[index + bdindex];
+            /*
+             * Adjust the buffer size to the actual number of bytes received.
+             */
 #ifdef ZYNQMP_USE_JUMBO
-		    rx_bytes = XEmacPs_GetRxFrameSize(&xemacpsif->emacps, curbdptr);
+            rx_bytes = XEmacPs_GetRxFrameSize(&xemacpsif->emacps, curbdptr);
 #else
-		    rx_bytes = XEmacPs_BdGetLength(curbdptr);
+            rx_bytes = XEmacPs_BdGetLength(curbdptr);
 #endif
-		    pbuf_realloc(p, rx_bytes);
-			/* Invalidate RX frame before queuing to handle
-			 * L1 cache prefetch conditions on any architecture.
-			 */
-		    Xil_DCacheInvalidateRange((UINTPTR)p->payload, rx_bytes);
-			/* store it in the receive queue,
-			 * where it'll be processed by a different handler
-			 */
-		    if (pq_enqueue(xemacpsif->recv_q, (void*)p) < 0) {
+            pbuf_realloc(p, rx_bytes);
+            /* Invalidate RX frame before queuing to handle
+             * L1 cache prefetch conditions on any architecture.
+             */
+            Xil_DCacheInvalidateRange((UINTPTR)p->payload, rx_bytes);
+            /* store it in the receive queue,
+             * where it'll be processed by a different handler
+             */
+            if (pq_enqueue(xemacpsif->recv_q, (void*)p) < 0) {
 #if LINK_STATS
-			    lwip_stats.link.memerr++;
-			    lwip_stats.link.drop++;
+                lwip_stats.link.memerr++;
+                lwip_stats.link.drop++;
 #endif
-			    pbuf_free(p);
-			}
-		    curbdptr = XEmacPs_BdRingNext( rxring, curbdptr);
-		}
-		/* free up the BD's */
-	    XEmacPs_BdRingFree(rxring, bd_processed, rxbdset);
-	    setup_rx_bds(xemacpsif, rxring);
+                pbuf_free(p);
+            }
+            curbdptr = XEmacPs_BdRingNext( rxring, curbdptr);
+        }
+        /* free up the BD's */
+        XEmacPs_BdRingFree(rxring, bd_processed, rxbdset);
+        setup_rx_bds(xemacpsif, rxring);
 #if 0
-	    sys_sem_signal(&xemac->sem_rx_data_available);
+        sys_sem_signal(&xemac->sem_rx_data_available);
 #else
-	    eth_device_ready(xemac->rt_eth_device);
+        eth_device_ready(xemac->rt_eth_device);
 #endif
-	}
+    }
 
 #ifdef OS_IS_FREERTOS
     xInsideISR--;
@@ -537,12 +537,12 @@ void clean_dma_txdescs(struct xemac_s *xemac)
     XEmacPs_BdClear(&bdtemplate);
     XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK);
 
-	/*
-	 * Create the TxBD ring
-	 */
+    /*
+     * Create the TxBD ring
+     */
     XEmacPs_BdRingCreate(txringptr, (UINTPTR) xemacpsif->tx_bdspace,
-			(UINTPTR) xemacpsif->tx_bdspace, BD_ALIGNMENT,
-				 XLWIP_CONFIG_N_TX_DESC);
+            (UINTPTR) xemacpsif->tx_bdspace, BD_ALIGNMENT,
+                 XLWIP_CONFIG_N_TX_DESC);
     XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND);
 }
 
@@ -567,13 +567,13 @@ XStatus init_dma(struct xemac_s *xemac)
 
     index = get_base_index_rxpbufsstorage (xemacpsif);
     gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
-	/*
-	 * The BDs need to be allocated in uncached memory. Hence the 1 MB
-	 * address range allocated for Bd_Space is made uncached
-	 * by setting appropriate attributes in the translation table.
-	 * The Bd_Space is aligned to 1MB and has a size of 1 MB. This ensures
-	 * a reserved uncached area used only for BDs.
-	 */
+    /*
+     * The BDs need to be allocated in uncached memory. Hence the 1 MB
+     * address range allocated for Bd_Space is made uncached
+     * by setting appropriate attributes in the translation table.
+     * The Bd_Space is aligned to 1MB and has a size of 1 MB. This ensures
+     * a reserved uncached area used only for BDs.
+     */
     if (bd_space_attr_set == 0) {
 #if defined (ARMR5)
     Xil_SetTlbAttributes((s32_t)bd_space, STRONG_ORDERD_SHARED | PRIV_RW_USER_RW); // addr, attr
@@ -584,15 +584,15 @@ XStatus init_dma(struct xemac_s *xemac)
     Xil_SetTlbAttributes((s32_t)bd_space, DEVICE_MEMORY); // addr, attr
 #endif
 #endif
-	    bd_space_attr_set = 1;
-	}
+        bd_space_attr_set = 1;
+    }
 
     rxringptr = &XEmacPs_GetRxRing(&xemacpsif->emacps);
     txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
     LWIP_DEBUGF(NETIF_DEBUG, ("rxringptr: 0x%08x\r\n", rxringptr));
     LWIP_DEBUGF(NETIF_DEBUG, ("txringptr: 0x%08x\r\n", txringptr));
 
-	/* Allocate 64k for Rx and Tx bds each to take care of extreme cases */
+    /* Allocate 64k for Rx and Tx bds each to take care of extreme cases */
     tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
     xemacpsif->rx_bdspace = (void *)tempaddress;
     bd_space_index += 0x10000;
@@ -600,163 +600,163 @@ XStatus init_dma(struct xemac_s *xemac)
     xemacpsif->tx_bdspace = (void *)tempaddress;
     bd_space_index += 0x10000;
     if (gigeversion > 2) {
-	    tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
-	    bdrxterminate = (XEmacPs_Bd *)tempaddress;
-	    bd_space_index += 0x10000;
-	    tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
-	    bdtxterminate = (XEmacPs_Bd *)tempaddress;
-	    bd_space_index += 0x10000;
-	}
+        tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
+        bdrxterminate = (XEmacPs_Bd *)tempaddress;
+        bd_space_index += 0x10000;
+        tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
+        bdtxterminate = (XEmacPs_Bd *)tempaddress;
+        bd_space_index += 0x10000;
+    }
 
     LWIP_DEBUGF(NETIF_DEBUG, ("rx_bdspace: %p \r\n", xemacpsif->rx_bdspace));
     LWIP_DEBUGF(NETIF_DEBUG, ("tx_bdspace: %p \r\n", xemacpsif->tx_bdspace));
 
     if (!xemacpsif->rx_bdspace || !xemacpsif->tx_bdspace) {
-	    xil_printf("%s@%d: Error: Unable to allocate memory for TX/RX buffer descriptors",
-			    __FILE__, __LINE__);
-	    return ERR_IF;
-	}
+        xil_printf("%s@%d: Error: Unable to allocate memory for TX/RX buffer descriptors",
+                __FILE__, __LINE__);
+        return ERR_IF;
+    }
 
-	/*
-	 * Setup RxBD space.
-	 *
-	 * Setup a BD template for the Rx channel. This template will be copied to
-	 * every RxBD. We will not have to explicitly set these again.
-	 */
+    /*
+     * Setup RxBD space.
+     *
+     * Setup a BD template for the Rx channel. This template will be copied to
+     * every RxBD. We will not have to explicitly set these again.
+     */
     XEmacPs_BdClear(&bdtemplate);
 
-	/*
-	 * Create the RxBD ring
-	 */
+    /*
+     * Create the RxBD ring
+     */
 
     status = XEmacPs_BdRingCreate(rxringptr, (UINTPTR) xemacpsif->rx_bdspace,
-				(UINTPTR) xemacpsif->rx_bdspace, BD_ALIGNMENT,
-				     XLWIP_CONFIG_N_RX_DESC);
+                (UINTPTR) xemacpsif->rx_bdspace, BD_ALIGNMENT,
+                     XLWIP_CONFIG_N_RX_DESC);
 
     if (status != XST_SUCCESS) {
-	    LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space\r\n"));
-	    return ERR_IF;
-	}
+        LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space\r\n"));
+        return ERR_IF;
+    }
 
     status = XEmacPs_BdRingClone(rxringptr, &bdtemplate, XEMACPS_RECV);
     if (status != XST_SUCCESS) {
-	    LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space\r\n"));
-	    return ERR_IF;
-	}
+        LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space\r\n"));
+        return ERR_IF;
+    }
 
     XEmacPs_BdClear(&bdtemplate);
     XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK);
-	/*
-	 * Create the TxBD ring
-	 */
+    /*
+     * Create the TxBD ring
+     */
     status = XEmacPs_BdRingCreate(txringptr, (UINTPTR) xemacpsif->tx_bdspace,
-				(UINTPTR) xemacpsif->tx_bdspace, BD_ALIGNMENT,
-				     XLWIP_CONFIG_N_TX_DESC);
+                (UINTPTR) xemacpsif->tx_bdspace, BD_ALIGNMENT,
+                     XLWIP_CONFIG_N_TX_DESC);
 
     if (status != XST_SUCCESS) {
-	    return ERR_IF;
-	}
+        return ERR_IF;
+    }
 
-	/* We reuse the bd template, as the same one will work for both rx and tx. */
+    /* We reuse the bd template, as the same one will work for both rx and tx. */
     status = XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND);
     if (status != XST_SUCCESS) {
-	    return ERR_IF;
-	}
+        return ERR_IF;
+    }
 
-	/*
-	 * Allocate RX descriptors, 1 RxBD at a time.
-	 */
+    /*
+     * Allocate RX descriptors, 1 RxBD at a time.
+     */
     for (i = 0; i < XLWIP_CONFIG_N_RX_DESC; i++) {
 #ifdef ZYNQMP_USE_JUMBO
-	    p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL);
+        p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL);
 #else
-	    p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
+        p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
 #endif
-	    if (!p) {
+        if (!p) {
 #if LINK_STATS
-		    lwip_stats.link.memerr++;
-		    lwip_stats.link.drop++;
+            lwip_stats.link.memerr++;
+            lwip_stats.link.drop++;
 #endif
-		    rt_kprintf("unable to alloc pbuf in init_dma\r\n");
-		    return ERR_IF;
-		}
-	    status = XEmacPs_BdRingAlloc(rxringptr, 1, &rxbd);
-	    if (status != XST_SUCCESS) {
-		    LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n"));
-		    pbuf_free(p);
-		    return ERR_IF;
-		}
-		/* Enqueue to HW */
-	    status = XEmacPs_BdRingToHw(rxringptr, 1, rxbd);
-	    if (status != XST_SUCCESS) {
-		    LWIP_DEBUGF(NETIF_DEBUG, ("Error: committing RxBD to HW\r\n"));
-		    pbuf_free(p);
-		    XEmacPs_BdRingUnAlloc(rxringptr, 1, rxbd);
-		    return ERR_IF;
-		}
+            rt_kprintf("unable to alloc pbuf in init_dma\r\n");
+            return ERR_IF;
+        }
+        status = XEmacPs_BdRingAlloc(rxringptr, 1, &rxbd);
+        if (status != XST_SUCCESS) {
+            LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n"));
+            pbuf_free(p);
+            return ERR_IF;
+        }
+        /* Enqueue to HW */
+        status = XEmacPs_BdRingToHw(rxringptr, 1, rxbd);
+        if (status != XST_SUCCESS) {
+            LWIP_DEBUGF(NETIF_DEBUG, ("Error: committing RxBD to HW\r\n"));
+            pbuf_free(p);
+            XEmacPs_BdRingUnAlloc(rxringptr, 1, rxbd);
+            return ERR_IF;
+        }
 
-	    bdindex = XEMACPS_BD_TO_INDEX(rxringptr, rxbd);
-	    temp = (u32 *)rxbd;
-		*temp = 0;
-	    if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
-			*temp = 0x00000002;
-		}
-	    temp++;
-		*temp = 0;
-	    dsb();
+        bdindex = XEMACPS_BD_TO_INDEX(rxringptr, rxbd);
+        temp = (u32 *)rxbd;
+        *temp = 0;
+        if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
+            *temp = 0x00000002;
+        }
+        temp++;
+        *temp = 0;
+        dsb();
 #ifdef ZYNQMP_USE_JUMBO
-	    if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
-		    Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO);
-		}
+        if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+            Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO);
+        }
 #else
-	    if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
-		    Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE);
-		}
+        if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+            Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE);
+        }
 #endif
-	    XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload);
+        XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload);
 
-	    rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
-	}
+        rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
+    }
     XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.RxBdRing.BaseBdAddr, 0, XEMACPS_RECV);
     if (gigeversion > 2) {
-	    XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 1, XEMACPS_SEND);
-	}else {
-	    XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 0, XEMACPS_SEND);
-	}
+        XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 1, XEMACPS_SEND);
+    }else {
+        XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 0, XEMACPS_SEND);
+    }
     if (gigeversion > 2)
-	{
-		/*
-		 * This version of GEM supports priority queuing and the current
-		 * driver is using tx priority queue 1 and normal rx queue for
-		 * packet transmit and receive. The below code ensure that the
-		 * other queue pointers are parked to known state for avoiding
-		 * the controller to malfunction by fetching the descriptors
-		 * from these queues.
-		 */
-	    XEmacPs_BdClear(bdrxterminate);
-	    XEmacPs_BdSetAddressRx(bdrxterminate, (XEMACPS_RXBUF_NEW_MASK |
-					    XEMACPS_RXBUF_WRAP_MASK));
-	    XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_RXQ1BASE_OFFSET),
-				   (UINTPTR)bdrxterminate);
-	    XEmacPs_BdClear(bdtxterminate);
-	    XEmacPs_BdSetStatus(bdtxterminate, (XEMACPS_TXBUF_USED_MASK |
-					    XEMACPS_TXBUF_WRAP_MASK));
-	    XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_TXQBASE_OFFSET),
-				   (UINTPTR)bdtxterminate);
-	}
+    {
+        /*
+         * This version of GEM supports priority queuing and the current
+         * driver is using tx priority queue 1 and normal rx queue for
+         * packet transmit and receive. The below code ensure that the
+         * other queue pointers are parked to known state for avoiding
+         * the controller to malfunction by fetching the descriptors
+         * from these queues.
+         */
+        XEmacPs_BdClear(bdrxterminate);
+        XEmacPs_BdSetAddressRx(bdrxterminate, (XEMACPS_RXBUF_NEW_MASK |
+                        XEMACPS_RXBUF_WRAP_MASK));
+        XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_RXQ1BASE_OFFSET),
+                   (UINTPTR)bdrxterminate);
+        XEmacPs_BdClear(bdtxterminate);
+        XEmacPs_BdSetStatus(bdtxterminate, (XEMACPS_TXBUF_USED_MASK |
+                        XEMACPS_TXBUF_WRAP_MASK));
+        XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_TXQBASE_OFFSET),
+                   (UINTPTR)bdtxterminate);
+    }
 
-	/*
-	 * Connect the device driver handler that will be called when an
-	 * interrupt for the device occurs, the handler defined above performs
-	 * the specific interrupt processing for the device.
-	 */
-	// XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,
-	// 			(Xil_ExceptionHandler)XEmacPs_IntrHandler,
-	// 					(void *)&xemacpsif->emacps);
-	/*
-	 * Enable the interrupt for emacps.
-	 */
-	// XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, (u32) xtopologyp->scugic_emac_intr);
+    /*
+     * Connect the device driver handler that will be called when an
+     * interrupt for the device occurs, the handler defined above performs
+     * the specific interrupt processing for the device.
+     */
+    // XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,
+    //             (Xil_ExceptionHandler)XEmacPs_IntrHandler,
+    //                     (void *)&xemacpsif->emacps);
+    /*
+     * Enable the interrupt for emacps.
+     */
+    // XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, (u32) xtopologyp->scugic_emac_intr);
     emac_intr_num = (u32) xtopologyp->scugic_emac_intr;
     return 0;
 }
@@ -783,19 +783,19 @@ void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)
 
     gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
     if (gigeversion == 2) {
-	    tempcntr = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET);
-	    if ((!tempcntr) && (!(xemacpsif->last_rx_frms_cntr))) {
-		    regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-				    XEMACPS_NWCTRL_OFFSET);
-		    regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
-		    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-				    XEMACPS_NWCTRL_OFFSET, regctrl);
-		    regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
-		    regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
-		    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
-		}
-	    xemacpsif->last_rx_frms_cntr = tempcntr;
-	}
+        tempcntr = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET);
+        if ((!tempcntr) && (!(xemacpsif->last_rx_frms_cntr))) {
+            regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET);
+            regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
+            XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET, regctrl);
+            regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
+            regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
+            XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
+        }
+        xemacpsif->last_rx_frms_cntr = tempcntr;
+    }
 }
 
 void free_txrx_pbufs(xemacpsif_s *xemacpsif)
@@ -807,18 +807,18 @@ void free_txrx_pbufs(xemacpsif_s *xemacpsif)
     index1 = get_base_index_txpbufsstorage (xemacpsif);
 
     for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
-	    if (tx_pbufs_storage[index] != 0) {
-		    p = (struct pbuf *)tx_pbufs_storage[index];
-		    pbuf_free(p);
-		    tx_pbufs_storage[index] = 0;
-		}
-	}
+        if (tx_pbufs_storage[index] != 0) {
+            p = (struct pbuf *)tx_pbufs_storage[index];
+            pbuf_free(p);
+            tx_pbufs_storage[index] = 0;
+        }
+    }
 
     for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
-	    p = (struct pbuf *)rx_pbufs_storage[index];
-	    pbuf_free(p);
+        p = (struct pbuf *)rx_pbufs_storage[index];
+        pbuf_free(p);
 
-	}
+    }
 }
 
 void free_onlytx_pbufs(xemacpsif_s *xemacpsif)
@@ -829,12 +829,12 @@ void free_onlytx_pbufs(xemacpsif_s *xemacpsif)
 
     index1 = get_base_index_txpbufsstorage (xemacpsif);
     for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
-	    if (tx_pbufs_storage[index] != 0) {
-		    p = (struct pbuf *)tx_pbufs_storage[index];
-		    pbuf_free(p);
-		    tx_pbufs_storage[index] = 0;
-		}
-	}
+        if (tx_pbufs_storage[index] != 0) {
+            p = (struct pbuf *)tx_pbufs_storage[index];
+            pbuf_free(p);
+            tx_pbufs_storage[index] = 0;
+        }
+    }
 }
 
 /* reset Tx and Rx DMA pointers after XEmacPs_Stop */
@@ -851,10 +851,10 @@ void reset_dma(struct xemac_s *xemac)
 
     gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
     if (gigeversion > 2) {
-	    txqueuenum = 1;
-	} else {
-	    txqueuenum = 0;
-	}
+        txqueuenum = 1;
+    } else {
+        txqueuenum = 0;
+    }
 
     XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.RxBdRing.BaseBdAddr, 0, XEMACPS_RECV);
     XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, txqueuenum, XEMACPS_SEND);
@@ -862,12 +862,12 @@ void reset_dma(struct xemac_s *xemac)
 
 void emac_disable_intr(void)
 {
-	// XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, emac_intr_num);
+    // XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, emac_intr_num);
     rt_hw_interrupt_mask(emac_intr_num);
 }
 
 void emac_enable_intr(void)
 {
-	// XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, emac_intr_num);
+    // XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, emac_intr_num);
     rt_hw_interrupt_umask(emac_intr_num);
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c
index bf100119d8..bf1c31e8fc 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c
@@ -55,11 +55,11 @@ XEmacPs_Config *xemacps_lookup_config(unsigned mac_base)
     s32_t i;
 
     for (i = 0; i < XPAR_XEMACPS_NUM_INSTANCES; i++) {
-	    if (XEmacPs_ConfigTable[i].BaseAddress == mac_base) {
-		    cfgptr = &XEmacPs_ConfigTable[i];
-		    break;
-		}
-	}
+        if (XEmacPs_ConfigTable[i].BaseAddress == mac_base) {
+            cfgptr = &XEmacPs_ConfigTable[i];
+            break;
+        }
+    }
 
     return (cfgptr);
 }
@@ -82,11 +82,11 @@ void init_emacps(xemacpsif_s *xemacps, struct netif *netif)
     XEmacPs_SetOptions(xemacpsp, XEMACPS_MULTICAST_OPTION);
 #endif
 
-	/* set mac address */
+    /* set mac address */
     status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
     if (status != XST_SUCCESS) {
-	    xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
-	}
+        xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
+    }
 
     XEmacPs_SetMdioDivisor(xemacpsp, MDC_DIV_224);
 
@@ -109,44 +109,44 @@ void init_emacps(xemacpsif_s *xemacps, struct netif *netif)
 #else
     detect_phy(xemacpsp);
     for (i = 31; i > 0; i--) {
-	    if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
-		    if (phymapemac0[i] == TRUE) {
-			    link_speed = phy_setup_emacps(xemacpsp, i);
-			    phyfoundforemac0 = TRUE;
-			    phyaddrforemac = i;
-			}
-		} else {
-		    if (phymapemac1[i] == TRUE) {
-			    link_speed = phy_setup_emacps(xemacpsp, i);
-			    phyfoundforemac1 = TRUE;
-			    phyaddrforemac = i;
-			}
-		}
-	}
-	/* If no PHY was detected, use broadcast PHY address of 0 */
+        if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
+            if (phymapemac0[i] == TRUE) {
+                link_speed = phy_setup_emacps(xemacpsp, i);
+                phyfoundforemac0 = TRUE;
+                phyaddrforemac = i;
+            }
+        } else {
+            if (phymapemac1[i] == TRUE) {
+                link_speed = phy_setup_emacps(xemacpsp, i);
+                phyfoundforemac1 = TRUE;
+                phyaddrforemac = i;
+            }
+        }
+    }
+    /* If no PHY was detected, use broadcast PHY address of 0 */
     if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
-	    if (phyfoundforemac0 == FALSE)
-		    link_speed = phy_setup_emacps(xemacpsp, 0);
-	} else {
-	    if (phyfoundforemac1 == FALSE)
-		    link_speed = phy_setup_emacps(xemacpsp, 0);
-	}
+        if (phyfoundforemac0 == FALSE)
+            link_speed = phy_setup_emacps(xemacpsp, 0);
+    } else {
+        if (phyfoundforemac1 == FALSE)
+            link_speed = phy_setup_emacps(xemacpsp, 0);
+    }
 #endif
 
     if (link_speed == XST_FAILURE) {
-	    eth_link_status = ETH_LINK_DOWN;
-	    xil_printf("Phy setup failure %s \n\r",__func__);
-	    return;
-	} else {
-	    eth_link_status = ETH_LINK_UP;
-	}
+        eth_link_status = ETH_LINK_DOWN;
+        xil_printf("Phy setup failure %s \n\r",__func__);
+        return;
+    } else {
+        eth_link_status = ETH_LINK_UP;
+    }
 
     XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
-	/* Setting the operating speed of the MAC needs a delay. */
-	{
-	    volatile s32_t wait;
-	    for (wait=0; wait < 20000; wait++);
-	}
+    /* Setting the operating speed of the MAC needs a delay. */
+    {
+        volatile s32_t wait;
+        for (wait=0; wait < 20000; wait++);
+    }
 }
 
 void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif)
@@ -156,19 +156,19 @@ void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif)
 
     xemacpsp = &xemacps->emacps;
 
-	/* set mac address */
+    /* set mac address */
     status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
     if (status != XST_SUCCESS) {
-	    xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
-	}
+        xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
+    }
 
     XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
 
-	/* Setting the operating speed of the MAC needs a delay. */
-	{
-	    volatile s32_t wait;
-	    for (wait=0; wait < 20000; wait++);
-	}
+    /* Setting the operating speed of the MAC needs a delay. */
+    {
+        volatile s32_t wait;
+        for (wait=0; wait < 20000; wait++);
+    }
 }
 
 void setup_isr (struct xemac_s *xemac)
@@ -176,41 +176,41 @@ void setup_isr (struct xemac_s *xemac)
     xemacpsif_s   *xemacpsif;
 
     xemacpsif = (xemacpsif_s *)(xemac->state);
-	/*
-	 * Setup callbacks
-	 */
+    /*
+     * Setup callbacks
+     */
     XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
-				     (void *) emacps_send_handler,
-				     (void *) xemac);
+                     (void *) emacps_send_handler,
+                     (void *) xemac);
 
     XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
-				    (void *) emacps_recv_handler,
-				    (void *) xemac);
+                    (void *) emacps_recv_handler,
+                    (void *) xemac);
 
     XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
-				    (void *) emacps_error_handler,
-				    (void *) xemac);
+                    (void *) emacps_error_handler,
+                    (void *) xemac);
 }
 
 void start_emacps (xemacpsif_s *xemacps)
 {
-	/* start the temac */
+    /* start the temac */
     XEmacPs_Start(&xemacps->emacps);
 }
 
 void restart_emacps_transmitter (xemacpsif_s *xemacps) {
     u32_t Reg;
     Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
-				    XEMACPS_NWCTRL_OFFSET);
+                    XEMACPS_NWCTRL_OFFSET);
     Reg = Reg & (~XEMACPS_NWCTRL_TXEN_MASK);
     XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
-									    XEMACPS_NWCTRL_OFFSET, Reg);
+                                        XEMACPS_NWCTRL_OFFSET, Reg);
 
     Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
-					    XEMACPS_NWCTRL_OFFSET);
+                        XEMACPS_NWCTRL_OFFSET);
     Reg = Reg | (XEMACPS_NWCTRL_TXEN_MASK);
     XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
-									    XEMACPS_NWCTRL_OFFSET, Reg);
+                                        XEMACPS_NWCTRL_OFFSET, Reg);
 }
 
 void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord)
@@ -229,47 +229,47 @@ void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord)
     txring = &XEmacPs_GetTxRing(&xemacpsif->emacps);
 
     if (ErrorWord != 0) {
-	    switch (Direction) {
-		    case XEMACPS_RECV:
-		    if (ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK) {
-			    LWIP_DEBUGF(NETIF_DEBUG, ("Receive DMA error\r\n"));
-			    HandleEmacPsError(xemac);
-			}
-		    if (ErrorWord & XEMACPS_RXSR_RXOVR_MASK) {
-			    LWIP_DEBUGF(NETIF_DEBUG, ("Receive over run\r\n"));
-			    emacps_recv_handler(arg);
-			    setup_rx_bds(xemacpsif, rxring);
-			}
-		    if (ErrorWord & XEMACPS_RXSR_BUFFNA_MASK) {
-			    LWIP_DEBUGF(NETIF_DEBUG, ("Receive buffer not available\r\n"));
-			    emacps_recv_handler(arg);
-			    setup_rx_bds(xemacpsif, rxring);
-			}
-		    break;
-		    case XEMACPS_SEND:
-		    if (ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK) {
-			    LWIP_DEBUGF(NETIF_DEBUG, ("Transmit DMA error\r\n"));
-			    HandleEmacPsError(xemac);
-			}
-		    if (ErrorWord & XEMACPS_TXSR_URUN_MASK) {
-			    LWIP_DEBUGF(NETIF_DEBUG, ("Transmit under run\r\n"));
-			    HandleTxErrors(xemac);
-			}
-		    if (ErrorWord & XEMACPS_TXSR_BUFEXH_MASK) {
-			    LWIP_DEBUGF(NETIF_DEBUG, ("Transmit buffer exhausted\r\n"));
-			    HandleTxErrors(xemac);
-			}
-		    if (ErrorWord & XEMACPS_TXSR_RXOVR_MASK) {
-			    LWIP_DEBUGF(NETIF_DEBUG, ("Transmit retry excessed limits\r\n"));
-			    HandleTxErrors(xemac);
-			}
-		    if (ErrorWord & XEMACPS_TXSR_FRAMERX_MASK) {
-			    LWIP_DEBUGF(NETIF_DEBUG, ("Transmit collision\r\n"));
-				// process_sent_bds(xemacpsif, txring);
-			}
-		    break;
-		}
-	}
+        switch (Direction) {
+            case XEMACPS_RECV:
+            if (ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Receive DMA error\r\n"));
+                HandleEmacPsError(xemac);
+            }
+            if (ErrorWord & XEMACPS_RXSR_RXOVR_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Receive over run\r\n"));
+                emacps_recv_handler(arg);
+                setup_rx_bds(xemacpsif, rxring);
+            }
+            if (ErrorWord & XEMACPS_RXSR_BUFFNA_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Receive buffer not available\r\n"));
+                emacps_recv_handler(arg);
+                setup_rx_bds(xemacpsif, rxring);
+            }
+            break;
+            case XEMACPS_SEND:
+            if (ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Transmit DMA error\r\n"));
+                HandleEmacPsError(xemac);
+            }
+            if (ErrorWord & XEMACPS_TXSR_URUN_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Transmit under run\r\n"));
+                HandleTxErrors(xemac);
+            }
+            if (ErrorWord & XEMACPS_TXSR_BUFEXH_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Transmit buffer exhausted\r\n"));
+                HandleTxErrors(xemac);
+            }
+            if (ErrorWord & XEMACPS_TXSR_RXOVR_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Transmit retry excessed limits\r\n"));
+                HandleTxErrors(xemac);
+            }
+            if (ErrorWord & XEMACPS_TXSR_FRAMERX_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Transmit collision\r\n"));
+                // process_sent_bds(xemacpsif, txring);
+            }
+            break;
+        }
+    }
 #ifdef OS_IS_FREERTOS
     xInsideISR--;
 #endif
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c
index 2e0a4039bd..108d75c6a8 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c
@@ -119,31 +119,31 @@
 
 #define CONFIG_LINKSPEED_AUTODETECT 1
 
-#define PHY_DETECT_REG  					    1
-#define PHY_IDENTIFIER_1_REG				    2
-#define PHY_IDENTIFIER_2_REG				    3
-#define PHY_DETECT_MASK 				    0x1808
-#define PHY_MARVELL_IDENTIFIER			    0x0141
-#define PHY_TI_IDENTIFIER				    0x2000
-#define PHY_REALTEK_IDENTIFIER			    0x001c
-#define PHY_XILINX_PCS_PMA_ID1		    0x0174
-#define PHY_XILINX_PCS_PMA_ID2		    0x0C00
+#define PHY_DETECT_REG                          1
+#define PHY_IDENTIFIER_1_REG                    2
+#define PHY_IDENTIFIER_2_REG                    3
+#define PHY_DETECT_MASK                     0x1808
+#define PHY_MARVELL_IDENTIFIER                0x0141
+#define PHY_TI_IDENTIFIER                    0x2000
+#define PHY_REALTEK_IDENTIFIER                0x001c
+#define PHY_XILINX_PCS_PMA_ID1            0x0174
+#define PHY_XILINX_PCS_PMA_ID2            0x0C00
 
-#define XEMACPS_GMII2RGMII_SPEED1000_FD	    0x140
-#define XEMACPS_GMII2RGMII_SPEED100_FD	    0x2100
-#define XEMACPS_GMII2RGMII_SPEED10_FD	    0x100
-#define XEMACPS_GMII2RGMII_REG_NUM		    0x10
+#define XEMACPS_GMII2RGMII_SPEED1000_FD        0x140
+#define XEMACPS_GMII2RGMII_SPEED100_FD        0x2100
+#define XEMACPS_GMII2RGMII_SPEED10_FD        0x100
+#define XEMACPS_GMII2RGMII_REG_NUM            0x10
 
-#define PHY_REGCR	    0x0D
-#define PHY_ADDAR	    0x0E
+#define PHY_REGCR        0x0D
+#define PHY_ADDAR        0x0E
 #define PHY_RGMIIDCTL    0x86
 #define PHY_RGMIICTL    0x32
-#define PHY_STS		    0x11
-#define PHY_TI_CR	    0x10
-#define PHY_TI_CFG4	    0x31
+#define PHY_STS            0x11
+#define PHY_TI_CR        0x10
+#define PHY_TI_CFG4        0x31
 
-#define MICREL_PHY_IDENTIFIER			    0x22
-#define MICREL_PHY_KSZ9031_MODEL		    0x220
+#define MICREL_PHY_IDENTIFIER                0x22
+#define MICREL_PHY_KSZ9031_MODEL            0x220
 
 #define PHY_REGCR_ADDR    0x001F
 #define PHY_REGCR_DATA    0x401F
@@ -151,14 +151,14 @@
 #define PHY_TI_CFG4RESVDBIT7    0x80
 
 /* Frequency setting */
-#define SLCR_LOCK_ADDR			(XPS_SYS_CTRL_BASEADDR + 0x4)
-#define SLCR_UNLOCK_ADDR		(XPS_SYS_CTRL_BASEADDR + 0x8)
-#define SLCR_GEM0_CLK_CTRL_ADDR	(XPS_SYS_CTRL_BASEADDR + 0x140)
-#define SLCR_GEM1_CLK_CTRL_ADDR	(XPS_SYS_CTRL_BASEADDR + 0x144)
+#define SLCR_LOCK_ADDR            (XPS_SYS_CTRL_BASEADDR + 0x4)
+#define SLCR_UNLOCK_ADDR        (XPS_SYS_CTRL_BASEADDR + 0x8)
+#define SLCR_GEM0_CLK_CTRL_ADDR    (XPS_SYS_CTRL_BASEADDR + 0x140)
+#define SLCR_GEM1_CLK_CTRL_ADDR    (XPS_SYS_CTRL_BASEADDR + 0x144)
 #define SLCR_GEM_SRCSEL_EMIO    0x40
 #define SLCR_LOCK_KEY_VALUE     0x767B
 #define SLCR_UNLOCK_KEY_VALUE    0xDF0D
-#define SLCR_ADDR_GEM_RST_CTRL	(XPS_SYS_CTRL_BASEADDR + 0x214)
+#define SLCR_ADDR_GEM_RST_CTRL    (XPS_SYS_CTRL_BASEADDR + 0x214)
 #define EMACPS_SLCR_DIV_MASK    0xFC0FC0FF
 
 #if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
@@ -181,7 +181,7 @@ static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr);
 #endif
 static void SetUpSLCRDivisors(u32_t mac_baseaddr, s32_t speed);
 #if defined (CONFIG_LINKSPEED1000) || defined (CONFIG_LINKSPEED100) \
-	|| defined (CONFIG_LINKSPEED10)
+    || defined (CONFIG_LINKSPEED10)
 static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed);
 #endif
 
@@ -193,30 +193,30 @@ u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr)
     u16_t phy_id;
 
     if(phy_addr == 0) {
-	    for (phy_addr = 31; phy_addr > 0; phy_addr--) {
-		    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
-					&phy_id);
+        for (phy_addr = 31; phy_addr > 0; phy_addr--) {
+            XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
+                    &phy_id);
 
-		    if (phy_id == PHY_XILINX_PCS_PMA_ID1) {
-			    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_2_REG,
-						&phy_id);
-			    if (phy_id == PHY_XILINX_PCS_PMA_ID2) {
-					/* Found a valid PHY address */
-				    LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
-						    phy_addr));
-				    break;
-				}
-			}
-		}
-	}
+            if (phy_id == PHY_XILINX_PCS_PMA_ID1) {
+                XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_2_REG,
+                        &phy_id);
+                if (phy_id == PHY_XILINX_PCS_PMA_ID2) {
+                    /* Found a valid PHY address */
+                    LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
+                            phy_addr));
+                    break;
+                }
+            }
+        }
+    }
 
     link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr);
     if (link_speed == 1000)
-	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
     else if (link_speed == 100)
-	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
     else
-	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
 
     xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed);
     return link_speed;
@@ -241,44 +241,44 @@ static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
     while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
-	    sleep(1);
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
-																&status);
-	}
+        sleep(1);
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
+                                                                &status);
+    }
     xil_printf("autonegotiation complete \r\n");
 
 #if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 1);
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
     if ((temp & 0x0020) == 0x0020) {
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-	    return 1000;
-	}
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+        return 1000;
+    }
     else {
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-	    xil_printf("Link error, temp = %x\r\n", temp);
-	    return 0;
-	}
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+        xil_printf("Link error, temp = %x\r\n", temp);
+        return 0;
+    }
 #elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
     xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
     while(!(temp & 0x8000)) {
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
-	}
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
+    }
     if((temp & 0x0C00) == 0x0800) {
-	    return 1000;
-	}
+        return 1000;
+    }
     else if((temp & 0x0C00) == 0x0400) {
-	    return 100;
-	}
+        return 100;
+    }
     else if((temp & 0x0C00) == 0x0000) {
-	    return 10;
-	} else {
-	    xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Defaulting to Speed = 10 Mbps\r\n");
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &temp);
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, 0x0100);
-	    return 10;
-	}
+        return 10;
+    } else {
+        xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Defaulting to Speed = 10 Mbps\r\n");
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &temp);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, 0x0100);
+        return 10;
+    }
 #endif
 
 }
@@ -291,32 +291,32 @@ void detect_phy(XEmacPs *xemacpsp)
     u32_t emacnum;
 
     if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR)
-	    emacnum = 0;
+        emacnum = 0;
     else
-	    emacnum = 1;
+        emacnum = 1;
     for (phy_addr = 31; phy_addr > 0; phy_addr--) {
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
-							&phy_reg);
+        XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
+                            &phy_reg);
 
-	    if ((phy_reg != 0xFFFF) &&
-			((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
-			/* Found a valid PHY address */
-		    LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
-																    phy_addr));
-		    if (emacnum == 0)
-			    phymapemac0[phy_addr] = TRUE;
-		    else
-			    phymapemac1[phy_addr] = TRUE;
+        if ((phy_reg != 0xFFFF) &&
+            ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
+            /* Found a valid PHY address */
+            LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
+                                                                    phy_addr));
+            if (emacnum == 0)
+                phymapemac0[phy_addr] = TRUE;
+            else
+                phymapemac1[phy_addr] = TRUE;
 
-		    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
-							&phy_reg);
-		    if ((phy_reg != PHY_MARVELL_IDENTIFIER) &&
-				(phy_reg != PHY_TI_IDENTIFIER) &&
-				(phy_reg != PHY_REALTEK_IDENTIFIER)) {
-			    xil_printf("WARNING: Not a Marvell or TI or Realtek Ethernet PHY. Please verify the initialization sequence\r\n");
-			}
-		}
-	}
+            XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
+                            &phy_reg);
+            if ((phy_reg != PHY_MARVELL_IDENTIFIER) &&
+                (phy_reg != PHY_TI_IDENTIFIER) &&
+                (phy_reg != PHY_REALTEK_IDENTIFIER)) {
+                xil_printf("WARNING: Not a Marvell or TI or Realtek Ethernet PHY. Please verify the initialization sequence\r\n");
+            }
+        }
+    }
 }
 
 u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr)
@@ -338,18 +338,18 @@ u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr)
 #ifdef  CONFIG_LINKSPEED_AUTODETECT
     link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr);
     if (link_speed == 1000) {
-	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
-	    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
-	} else if (link_speed == 100) {
-	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
-	    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
-	} else if (link_speed != XST_FAILURE){
-	    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
-	    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
-	} else {
-	    xil_printf("Phy setup error \r\n");
-	    return XST_FAILURE;
-	}
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
+        convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
+    } else if (link_speed == 100) {
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
+        convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
+    } else if (link_speed != XST_FAILURE){
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
+        convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
+    } else {
+        xil_printf("Phy setup error \r\n");
+        return XST_FAILURE;
+    }
 #elif    defined(CONFIG_LINKSPEED1000)
     SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
     link_speed = 1000;
@@ -370,9 +370,9 @@ u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr)
     sleep(1);
 #endif
     if (conv_present) {
-	    XEmacPs_PhyWrite(xemacpsp, convphyaddr,
-	    XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
-	}
+        XEmacPs_PhyWrite(xemacpsp, convphyaddr,
+        XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
+    }
 
     xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed);
     return link_speed;
@@ -405,10 +405,10 @@ static u32_t get_phy_speed_ksz9031(XEmacPs *xemacpsp, u32_t phy_addr)
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-					   &control);
+                       &control);
     control |= ADVERTISE_1000;
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-					   control);
+                       control);
 
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, &control);
@@ -416,7 +416,7 @@ static u32_t get_phy_speed_ksz9031(XEmacPs *xemacpsp, u32_t phy_addr)
     control |= (7 << 12); /* max number of gigabit attempts */
     control |= (1 << 11); /* enable downshift */
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
-					 control);
+                     control);
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
     control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
@@ -428,45 +428,45 @@ static u32_t get_phy_speed_ksz9031(XEmacPs *xemacpsp, u32_t phy_addr)
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
 
     while (1) {
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	    if (control & IEEE_CTRL_RESET_MASK)
-			 continue;
-	    else
-		    break;
-	}
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+        if (control & IEEE_CTRL_RESET_MASK)
+             continue;
+        else
+            break;
+    }
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
     xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
 
     while (!(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)) {
-	    sleep(1);
-	    XEmacPs_PhyRead(xemacpsp, phy_addr,
-						    IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp);
-	    timeout_counter++;
-	    if ((phy_init_flag == 0) && (timeout_counter > 1))
-		{
-		    phy_init_flag = 1;
-		    return XST_FAILURE;
-		}
-	    if (timeout_counter == 30) {
-		    xil_printf("Auto negotiation error \r\n");
-		    return XST_FAILURE;
-		}
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-	}
+        sleep(1);
+        XEmacPs_PhyRead(xemacpsp, phy_addr,
+                            IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp);
+        timeout_counter++;
+        if ((phy_init_flag == 0) && (timeout_counter > 1))
+        {
+            phy_init_flag = 1;
+            return XST_FAILURE;
+        }
+        if (timeout_counter == 30) {
+            xil_printf("Auto negotiation error \r\n");
+            return XST_FAILURE;
+        }
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    }
     xil_printf("autonegotiation complete \r\n");
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1f, &status_speed);
 
     if ((status_speed & 0x40) == 0x40) /* 1000Mbps */
-	    return 1000;
+        return 1000;
     else if ((status_speed & 0x20) == 0x20) /* 100Mbps */
-	    return 100;
+        return 100;
     else if ((status_speed & 0x10) == 0x10) /* 10Mbps */
-	    return 10;
+        return 10;
     else
-	    return 0;
+        return 0;
     return XST_SUCCESS;
 }
 
@@ -488,75 +488,75 @@ static u32_t get_TI_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
     XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, phyregtemp);
     RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, (u16_t *)&phyregtemp);
     if (RetStatus != XST_SUCCESS) {
-	    xil_printf("Error during sw reset \n\r");
-	    return XST_FAILURE;
-	}
+        xil_printf("Error during sw reset \n\r");
+        return XST_FAILURE;
+    }
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp);
     phyregtemp |= 0x8000;
     XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, phyregtemp);
 
-	/*
-	 * Delay
-	 */
+    /*
+     * Delay
+     */
     for(i=0;i<1000000000;i++);
 
     RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp);
     if (RetStatus != XST_SUCCESS) {
-	    xil_printf("Error during reset \n\r");
-	    return XST_FAILURE;
-	}
+        xil_printf("Error during reset \n\r");
+        return XST_FAILURE;
+    }
 
-	/* FIFO depth */
+    /* FIFO depth */
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_TI_CR, PHY_TI_CRVAL);
     RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_TI_CR, (u16_t *)&phyregtemp);
     if (RetStatus != XST_SUCCESS) {
-	    xil_printf("Error writing to 0x10 \n\r");
-	    return XST_FAILURE;
-	}
+        xil_printf("Error writing to 0x10 \n\r");
+        return XST_FAILURE;
+    }
 
-	/* TX/RX tuning */
-	/* Write to PHY_RGMIIDCTL */
+    /* TX/RX tuning */
+    /* Write to PHY_RGMIIDCTL */
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL);
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
     RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xA8);
     if (RetStatus != XST_SUCCESS) {
-	    xil_printf("Error in tuning");
-	    return XST_FAILURE;
-	}
+        xil_printf("Error in tuning");
+        return XST_FAILURE;
+    }
 
-	/* Read PHY_RGMIIDCTL */
+    /* Read PHY_RGMIIDCTL */
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL);
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
     RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
     if (RetStatus != XST_SUCCESS) {
-	    xil_printf("Error in tuning");
-	    return XST_FAILURE;
-	}
+        xil_printf("Error in tuning");
+        return XST_FAILURE;
+    }
 
-	/* Write PHY_RGMIICTL */
+    /* Write PHY_RGMIICTL */
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL);
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
     RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xD3);
     if (RetStatus != XST_SUCCESS) {
-	    xil_printf("Error in tuning");
-	    return XST_FAILURE;
-	}
+        xil_printf("Error in tuning");
+        return XST_FAILURE;
+    }
 
-	/* Read PHY_RGMIICTL */
+    /* Read PHY_RGMIICTL */
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL);
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
     RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
     if (RetStatus != XST_SUCCESS) {
-	    xil_printf("Error in tuning");
-	    return XST_FAILURE;
-	}
+        xil_printf("Error in tuning");
+        return XST_FAILURE;
+    }
 
-	/* SW workaround for unstable link when RX_CTRL is not STRAP MODE 3 or 4 */
+    /* SW workaround for unstable link when RX_CTRL is not STRAP MODE 3 or 4 */
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4);
     XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
@@ -575,10 +575,10 @@ static u32_t get_TI_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-					&control);
+                    &control);
     control |= ADVERTISE_1000;
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-				    control);
+                    control);
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
     control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
@@ -591,29 +591,29 @@ static u32_t get_TI_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
     xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
 
     while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
-	    sleep(1);
-	    timeout_counter++;
-	    if ((phy_init_flag == 0) && (timeout_counter > 1))
-		{
-		    phy_init_flag = 1;
-		    return XST_FAILURE;
-		}
-	    if (timeout_counter == 30) {
-		    xil_printf("Auto negotiation error \r\n");
-		    return XST_FAILURE;
-		}
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-	}
+        sleep(1);
+        timeout_counter++;
+        if ((phy_init_flag == 0) && (timeout_counter > 1))
+        {
+            phy_init_flag = 1;
+            return XST_FAILURE;
+        }
+        if (timeout_counter == 30) {
+            xil_printf("Auto negotiation error \r\n");
+            return XST_FAILURE;
+        }
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    }
     xil_printf("autonegotiation complete \r\n");
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_STS, &status_speed);
     if ((status_speed & 0xC000) == 0x8000) {
-	    return 1000;
-	} else if ((status_speed & 0xC000) == 0x4000) {
-	    return 100;
-	} else {
-	    return 10;
-	}
+        return 1000;
+    } else if ((status_speed & 0xC000) == 0x4000) {
+        return 100;
+    } else {
+        return 10;
+    }
 
     return XST_SUCCESS;
 }
@@ -645,18 +645,18 @@ static u32_t get_Marvell_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-					&control);
+                    &control);
     control |= ADVERTISE_1000;
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-				    control);
+                    control);
 
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
-																&control);
-    control |= (7 << 12);	/* max number of gigabit attempts */
-    control |= (1 << 11);	/* enable downshift */
+                                                                &control);
+    control |= (7 << 12);    /* max number of gigabit attempts */
+    control |= (1 << 11);    /* enable downshift */
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
-															    control);
+                                                                control);
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
     control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
     control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
@@ -667,47 +667,47 @@ static u32_t get_Marvell_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
 
     while (1) {
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	    if (control & IEEE_CTRL_RESET_MASK)
-		    continue;
-	    else
-		    break;
-	}
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+        if (control & IEEE_CTRL_RESET_MASK)
+            continue;
+        else
+            break;
+    }
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
     xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
 
     while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
-	    sleep(1);
-	    XEmacPs_PhyRead(xemacpsp, phy_addr,
-					    IEEE_COPPER_SPECIFIC_STATUS_REG_2,  &temp);
-	    timeout_counter++;
-	    if ((phy_init_flag == 0) && (timeout_counter > 1))
-		{
-		    phy_init_flag = 1;
-		    return XST_FAILURE;
-		}
-	    if (timeout_counter == 30) {
-		    xil_printf("Auto negotiation error \r\n");
-		    return XST_FAILURE;
-		}
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-	}
+        sleep(1);
+        XEmacPs_PhyRead(xemacpsp, phy_addr,
+                        IEEE_COPPER_SPECIFIC_STATUS_REG_2,  &temp);
+        timeout_counter++;
+        if ((phy_init_flag == 0) && (timeout_counter > 1))
+        {
+            phy_init_flag = 1;
+            return XST_FAILURE;
+        }
+        if (timeout_counter == 30) {
+            xil_printf("Auto negotiation error \r\n");
+            return XST_FAILURE;
+        }
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    }
     xil_printf("autonegotiation complete \r\n");
 
     XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG,
-					&status_speed);
+                    &status_speed);
     if (status_speed & 0x400) {
-	    temp_speed = status_speed & IEEE_SPEED_MASK;
+        temp_speed = status_speed & IEEE_SPEED_MASK;
 
-	    if (temp_speed == IEEE_SPEED_1000)
-		    return 1000;
-	    else if(temp_speed == IEEE_SPEED_100)
-		    return 100;
-	    else
-		    return 10;
-	}
+        if (temp_speed == IEEE_SPEED_1000)
+            return 1000;
+        else if(temp_speed == IEEE_SPEED_100)
+            return 100;
+        else
+            return 10;
+    }
 
     return XST_SUCCESS;
 }
@@ -731,10 +731,10 @@ static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-					&control);
+                    &control);
     control |= ADVERTISE_1000;
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-				    control);
+                    control);
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
     control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
@@ -746,45 +746,45 @@ static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
 
     while (1) {
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-	    if (control & IEEE_CTRL_RESET_MASK)
-		    continue;
-	    else
-		    break;
-	}
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+        if (control & IEEE_CTRL_RESET_MASK)
+            continue;
+        else
+            break;
+    }
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
 
     xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
 
     while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
-	    sleep(1);
-	    timeout_counter++;
-	    if ((phy_init_flag == 0) && (timeout_counter > 1))
-		{
-		    phy_init_flag = 1;
-		    return XST_FAILURE;
-		}
-	    if (timeout_counter == 30) {
-		    xil_printf("Auto negotiation error \r\n");
-		    return XST_FAILURE;
-		}
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-	}
+        sleep(1);
+        timeout_counter++;
+        if ((phy_init_flag == 0) && (timeout_counter > 1))
+        {
+            phy_init_flag = 1;
+            return XST_FAILURE;
+        }
+        if (timeout_counter == 30) {
+            xil_printf("Auto negotiation error \r\n");
+            return XST_FAILURE;
+        }
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    }
     xil_printf("autonegotiation complete \r\n");
 
     XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG,
-					&status_speed);
+                    &status_speed);
     if (status_speed & 0x400) {
-	    temp_speed = status_speed & IEEE_SPEED_MASK;
+        temp_speed = status_speed & IEEE_SPEED_MASK;
 
-	    if (temp_speed == IEEE_SPEED_1000)
-		    return 1000;
-	    else if(temp_speed == IEEE_SPEED_100)
-		    return 100;
-	    else
-		    return 10;
-	}
+        if (temp_speed == IEEE_SPEED_1000)
+            return 1000;
+        else if(temp_speed == IEEE_SPEED_100)
+            return 100;
+        else
+            return 10;
+    }
 
     return XST_FAILURE;
 }
@@ -795,23 +795,23 @@ static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
     u32_t RetStatus;
 
     XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
-					&phy_identity);
+                    &phy_identity);
     if(phy_identity == MICREL_PHY_IDENTIFIER){
-	    RetStatus = get_phy_speed_ksz9031(xemacpsp, phy_addr);
-	} else if (phy_identity == PHY_TI_IDENTIFIER) {
-	    RetStatus = get_TI_phy_speed(xemacpsp, phy_addr);
-	} else if (phy_identity == PHY_REALTEK_IDENTIFIER) {
-	    RetStatus = get_Realtek_phy_speed(xemacpsp, phy_addr);
-	} else {
-	    RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr);
-	}
+        RetStatus = get_phy_speed_ksz9031(xemacpsp, phy_addr);
+    } else if (phy_identity == PHY_TI_IDENTIFIER) {
+        RetStatus = get_TI_phy_speed(xemacpsp, phy_addr);
+    } else if (phy_identity == PHY_REALTEK_IDENTIFIER) {
+        RetStatus = get_Realtek_phy_speed(xemacpsp, phy_addr);
+    } else {
+        RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr);
+    }
 
     return RetStatus;
 }
 #endif
 
 #if defined (CONFIG_LINKSPEED1000) || defined (CONFIG_LINKSPEED100) \
-	|| defined (CONFIG_LINKSPEED10)
+    || defined (CONFIG_LINKSPEED10)
 static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed)
 {
     u16_t control;
@@ -835,68 +835,68 @@ static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t s
     control &= ~IEEE_CTRL_LINKSPEED_10M;
 
     if (speed == 1000) {
-	    control |= IEEE_CTRL_LINKSPEED_1000M;
+        control |= IEEE_CTRL_LINKSPEED_1000M;
 
-		/* Don't advertise PHY speed of 100 Mbps */
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-	    autonereg &= (~ADVERTISE_100);
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+        /* Don't advertise PHY speed of 100 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg &= (~ADVERTISE_100);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
 
-		/* Don't advertise PHY speed of 10 Mbps */
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-	    autonereg &= (~ADVERTISE_10);
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+        /* Don't advertise PHY speed of 10 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg &= (~ADVERTISE_10);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
 
-		/* Advertise PHY speed of 1000 Mbps */
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
-	    autonereg |= ADVERTISE_1000;
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
-	}
+        /* Advertise PHY speed of 1000 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
+        autonereg |= ADVERTISE_1000;
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
+    }
 
     else if (speed == 100) {
-	    control |= IEEE_CTRL_LINKSPEED_100M;
+        control |= IEEE_CTRL_LINKSPEED_100M;
 
-		/* Don't advertise PHY speed of 1000 Mbps */
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
-	    autonereg &= (~ADVERTISE_1000);
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
+        /* Don't advertise PHY speed of 1000 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
+        autonereg &= (~ADVERTISE_1000);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
 
-		/* Don't advertise PHY speed of 10 Mbps */
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-	    autonereg &= (~ADVERTISE_10);
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+        /* Don't advertise PHY speed of 10 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg &= (~ADVERTISE_10);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
 
-		/* Advertise PHY speed of 100 Mbps */
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-	    autonereg |= ADVERTISE_100;
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
-	}
+        /* Advertise PHY speed of 100 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg |= ADVERTISE_100;
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+    }
 
     else if (speed == 10) {
-	    control |= IEEE_CTRL_LINKSPEED_10M;
+        control |= IEEE_CTRL_LINKSPEED_10M;
 
-		/* Don't advertise PHY speed of 1000 Mbps */
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
-	    autonereg &= (~ADVERTISE_1000);
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
+        /* Don't advertise PHY speed of 1000 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
+        autonereg &= (~ADVERTISE_1000);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
 
-		/* Don't advertise PHY speed of 100 Mbps */
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-	    autonereg &= (~ADVERTISE_100);
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+        /* Don't advertise PHY speed of 100 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg &= (~ADVERTISE_100);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
 
-		/* Advertise PHY speed of 10 Mbps */
-	    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
-	    autonereg |= ADVERTISE_10;
-	    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
-	}
+        /* Advertise PHY speed of 10 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg |= ADVERTISE_10;
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+    }
 
     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
-										    control | IEEE_CTRL_RESET_MASK);
-	{
-	    volatile s32_t wait;
-	    for (wait=0; wait < 100000; wait++);
-	}
+                                            control | IEEE_CTRL_RESET_MASK);
+    {
+        volatile s32_t wait;
+        for (wait=0; wait < 100000; wait++);
+    }
     return 0;
 }
 #endif
@@ -920,233 +920,233 @@ static void SetUpSLCRDivisors(u32_t mac_baseaddr, s32_t speed)
     gigeversion = ((Xil_In32(mac_baseaddr + 0xFC)) >> 16) & 0xFFF;
     if (gigeversion == 2) {
 
-		*(volatile u32_t *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
+        *(volatile u32_t *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
 
-	    if (mac_baseaddr == ZYNQ_EMACPS_0_BASEADDR) {
-		    slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
-		} else {
-		    slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
-		}
+        if (mac_baseaddr == ZYNQ_EMACPS_0_BASEADDR) {
+            slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
+        } else {
+            slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
+        }
 
-	    if((*(volatile u32_t *)(UINTPTR)(slcrBaseAddress)) &
-		    SLCR_GEM_SRCSEL_EMIO) {
-			    return;
-		}
+        if((*(volatile u32_t *)(UINTPTR)(slcrBaseAddress)) &
+            SLCR_GEM_SRCSEL_EMIO) {
+                return;
+        }
 
-	    if (speed == 1000) {
-		    if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
+        if (speed == 1000) {
+            if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
-			    SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
-			    SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
+                SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
 #endif
-			} else {
+            } else {
 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
-			    SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
-			    SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
+                SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
 #endif
-			}
-		} else if (speed == 100) {
-		    if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
+            }
+        } else if (speed == 100) {
+            if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
-			    SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
-			    SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
+                SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
 #endif
-			} else {
+            } else {
 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
-			    SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
-			    SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
+                SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
 #endif
-			}
-		} else {
-		    if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
+            }
+        } else {
+            if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
-			    SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
-			    SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
+                SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
 #endif
-			} else {
+            } else {
 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
-			    SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
-			    SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
+                SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
 #endif
-			}
-		}
+            }
+        }
 
-	    if (SlcrDiv0 != 0 && SlcrDiv1 != 0) {
-		    SlcrTxClkCntrl = *(volatile u32_t *)(UINTPTR)(slcrBaseAddress);
-		    SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
-		    SlcrTxClkCntrl |= (SlcrDiv1 << 20);
-		    SlcrTxClkCntrl |= (SlcrDiv0 << 8);
-			*(volatile u32_t *)(UINTPTR)(slcrBaseAddress) = SlcrTxClkCntrl;
-			*(volatile u32_t *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
-		} else {
-		    xil_printf("Clock Divisors incorrect - Please check\r\n");
-		}
-	} else if (gigeversion == GEM_VERSION_ZYNQMP) {
-		/* Setup divisors in CRL_APB for Zynq Ultrascale+ MPSoC */
-	    if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
-		    CrlApbBaseAddr = CRL_APB_GEM0_REF_CTRL;
-		} else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
-		    CrlApbBaseAddr = CRL_APB_GEM1_REF_CTRL;
-		} else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
-		    CrlApbBaseAddr = CRL_APB_GEM2_REF_CTRL;
-		} else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
-		    CrlApbBaseAddr = CRL_APB_GEM3_REF_CTRL;
-		}
+        if (SlcrDiv0 != 0 && SlcrDiv1 != 0) {
+            SlcrTxClkCntrl = *(volatile u32_t *)(UINTPTR)(slcrBaseAddress);
+            SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
+            SlcrTxClkCntrl |= (SlcrDiv1 << 20);
+            SlcrTxClkCntrl |= (SlcrDiv0 << 8);
+            *(volatile u32_t *)(UINTPTR)(slcrBaseAddress) = SlcrTxClkCntrl;
+            *(volatile u32_t *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
+        } else {
+            xil_printf("Clock Divisors incorrect - Please check\r\n");
+        }
+    } else if (gigeversion == GEM_VERSION_ZYNQMP) {
+        /* Setup divisors in CRL_APB for Zynq Ultrascale+ MPSoC */
+        if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+            CrlApbBaseAddr = CRL_APB_GEM0_REF_CTRL;
+        } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
+            CrlApbBaseAddr = CRL_APB_GEM1_REF_CTRL;
+        } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
+            CrlApbBaseAddr = CRL_APB_GEM2_REF_CTRL;
+        } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
+            CrlApbBaseAddr = CRL_APB_GEM3_REF_CTRL;
+        }
 
-	    if (speed == 1000) {
-		    if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+        if (speed == 1000) {
+            if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
 #endif
-			} else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
 #endif
-			} else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV1;
 #endif
-			} else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV1;
 #endif
-			}
-		} else if (speed == 100) {
-		    if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+            }
+        } else if (speed == 100) {
+            if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
 #endif
-			} else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
 #endif
-			} else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV1;
 #endif
-			} else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV1;
 #endif
-			}
-		} else {
-		    if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+            }
+        } else {
+            if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
 #endif
-			} else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
 #endif
-			} else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV1;
 #endif
-			} else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
 #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0;
-			    CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV1;
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV1;
 #endif
-			}
-		}
+            }
+        }
 
-	    if (CrlApbDiv0 != 0 && CrlApbDiv1 != 0) {
-		#if EL1_NONSECURE
-		    XSmc_OutVar RegRead;
-		    RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
-							    0, 0, 0, 0, 0, 0);
-		    CrlApbGemCtrl = RegRead.Arg0 >> 32;
-		#else
-		    CrlApbGemCtrl = *(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr);
+        if (CrlApbDiv0 != 0 && CrlApbDiv1 != 0) {
+        #if EL1_NONSECURE
+            XSmc_OutVar RegRead;
+            RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
+                                0, 0, 0, 0, 0, 0);
+            CrlApbGemCtrl = RegRead.Arg0 >> 32;
+        #else
+            CrlApbGemCtrl = *(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr);
         #endif
-		    CrlApbGemCtrl &= ~CRL_APB_GEM_DIV0_MASK;
-		    CrlApbGemCtrl |= CrlApbDiv0 << CRL_APB_GEM_DIV0_SHIFT;
-		    CrlApbGemCtrl &= ~CRL_APB_GEM_DIV1_MASK;
-		    CrlApbGemCtrl |= CrlApbDiv1 << CRL_APB_GEM_DIV1_SHIFT;
-		#if EL1_NONSECURE
-		    Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(CrlApbBaseAddr) | ((u64)(0xFFFFFFFF) << 32),
-				(u64)CrlApbGemCtrl, 0, 0, 0, 0, 0);
-		    do {
-		    RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
-			    0, 0, 0, 0, 0, 0);
-			} while((RegRead.Arg0 >> 32) != CrlApbGemCtrl);
-		#else
-			*(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr) = CrlApbGemCtrl;
+            CrlApbGemCtrl &= ~CRL_APB_GEM_DIV0_MASK;
+            CrlApbGemCtrl |= CrlApbDiv0 << CRL_APB_GEM_DIV0_SHIFT;
+            CrlApbGemCtrl &= ~CRL_APB_GEM_DIV1_MASK;
+            CrlApbGemCtrl |= CrlApbDiv1 << CRL_APB_GEM_DIV1_SHIFT;
+        #if EL1_NONSECURE
+            Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(CrlApbBaseAddr) | ((u64)(0xFFFFFFFF) << 32),
+                (u64)CrlApbGemCtrl, 0, 0, 0, 0, 0);
+            do {
+            RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
+                0, 0, 0, 0, 0, 0);
+            } while((RegRead.Arg0 >> 32) != CrlApbGemCtrl);
+        #else
+            *(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr) = CrlApbGemCtrl;
         #endif
-		} else {
-		    xil_printf("Clock Divisors incorrect - Please check\r\n");
-		}
-	} else if (gigeversion == GEM_VERSION_VERSAL) {
-		/* Setup divisors in CRL for Versal */
-	    if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
-		    CrlApbBaseAddr = VERSAL_CRL_GEM0_REF_CTRL;
+        } else {
+            xil_printf("Clock Divisors incorrect - Please check\r\n");
+        }
+    } else if (gigeversion == GEM_VERSION_VERSAL) {
+        /* Setup divisors in CRL for Versal */
+        if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+            CrlApbBaseAddr = VERSAL_CRL_GEM0_REF_CTRL;
 #if EL1_NONSECURE
-		    ClkId = CLK_GEM0_REF;
+            ClkId = CLK_GEM0_REF;
 #endif
-		} else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
-		    CrlApbBaseAddr = VERSAL_CRL_GEM1_REF_CTRL;
+        } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
+            CrlApbBaseAddr = VERSAL_CRL_GEM1_REF_CTRL;
 #if EL1_NONSECURE
-		    ClkId = CLK_GEM1_REF;
+            ClkId = CLK_GEM1_REF;
 #endif
-		}
+        }
 
-	    if (speed == 1000) {
-		    if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+        if (speed == 1000) {
+            if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
 #endif
-			} else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
+            } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
 #endif
-			}
-		} else if (speed == 100) {
-		    if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+            }
+        } else if (speed == 100) {
+            if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
 #endif
-			} else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
+            } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
 #endif
-			}
-		} else {
-		    if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+            }
+        } else {
+            if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
 #endif
-			} else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
+            } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
 #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
-			    CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
 #endif
-			}
-		}
+            }
+        }
 
-	    if (CrlApbDiv0 != 0) {
+        if (CrlApbDiv0 != 0) {
 #if EL1_NONSECURE
-		    Xil_Smc(PM_SET_DIVIDER_SMC_FID, (((u64)CrlApbDiv0 << 32) | ClkId), 0, 0, 0, 0, 0, 0);
+            Xil_Smc(PM_SET_DIVIDER_SMC_FID, (((u64)CrlApbDiv0 << 32) | ClkId), 0, 0, 0, 0, 0, 0);
 #else
-		    CrlApbGemCtrl = Xil_In32((UINTPTR)CrlApbBaseAddr);
-		    CrlApbGemCtrl &= ~VERSAL_CRL_GEM_DIV_MASK;
-		    CrlApbGemCtrl |= CrlApbDiv0 << VERSAL_CRL_APB_GEM_DIV_SHIFT;
+            CrlApbGemCtrl = Xil_In32((UINTPTR)CrlApbBaseAddr);
+            CrlApbGemCtrl &= ~VERSAL_CRL_GEM_DIV_MASK;
+            CrlApbGemCtrl |= CrlApbDiv0 << VERSAL_CRL_APB_GEM_DIV_SHIFT;
 
-		    Xil_Out32((UINTPTR)CrlApbBaseAddr, CrlApbGemCtrl);
+            Xil_Out32((UINTPTR)CrlApbBaseAddr, CrlApbGemCtrl);
 #endif
-		} else {
-		    xil_printf("Clock Divisors incorrect - Please check\r\n");
-		}
-	}
+        } else {
+            xil_printf("Clock Divisors incorrect - Please check\r\n");
+        }
+    }
 
     return;
 }
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c
index bc8bfbfe32..f59ec15b95 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c
@@ -44,14 +44,14 @@ pq_create_queue()
     pq_queue_t *q = NULL;
 
     if (i >= NUM_QUEUES) {
-	    xil_printf("ERR: Max Queues allocated\n\r");
-	    return q;
-	}
+        xil_printf("ERR: Max Queues allocated\n\r");
+        return q;
+    }
 
     q = &pq_queue[i++];
 
     if (!q)
-	    return q;
+        return q;
 
     q->head = q->tail = q->len = 0;
 
@@ -62,7 +62,7 @@ int
 pq_enqueue(pq_queue_t *q, void *p)
 {
     if (q->len == PQ_QUEUE_SIZE)
-	    return -1;
+        return -1;
 
     q->data[q->head] = p;
     q->head = (q->head + 1)%PQ_QUEUE_SIZE;
@@ -77,7 +77,7 @@ pq_dequeue(pq_queue_t *q)
     int ptail;
 
     if (q->len == 0)
-	    return NULL;
+        return NULL;
 
     ptail = q->tail;
     q->tail = (q->tail + 1)%PQ_QUEUE_SIZE;
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c
index 4ab0e7ece4..4adcb450f1 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c
@@ -2,14 +2,14 @@
 #include "xparameters.h"
 
 struct xtopology_t xtopology[] = {
-	{
-	    0xFF0E0000,
-	    xemac_type_emacps,
-	    0x0,
-	    0x0,
-	    0xF8F00100,
-	    XPAR_XEMACPS_3_INTR,
-	},
+    {
+        0xFF0E0000,
+        xemac_type_emacps,
+        0x0,
+        0x0,
+        0xF8F00100,
+        XPAR_XEMACPS_3_INTR,
+    },
 };
 
 int xtopology_n_emacs = 1;
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_io.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_io.h
index 87d7282c04..1f16b03287 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_io.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_io.h
@@ -20,7 +20,7 @@
 *
 * Ver   Who      Date     Changes
 * ----- -------- -------- -----------------------------------------------
-* 5.00     pkp  	 05/29/14 First release
+* 5.00     pkp       05/29/14 First release
 * 6.00  mus      08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
 *                         ARM processors
 * 7.20  har      01/03/20 Added Xil_SecureOut32 for avoiding blindwrite for
@@ -132,7 +132,7 @@ static INLINE u64 Xil_In64(UINTPTR Addr)
 static INLINE void Xil_Out8(UINTPTR Addr, u8 Value)
 {
     volatile u8 *LocalAddr = (volatile u8 *)Addr;
-	*LocalAddr = Value;
+    *LocalAddr = Value;
 }
 
 /*****************************************************************************/
@@ -150,7 +150,7 @@ static INLINE void Xil_Out8(UINTPTR Addr, u8 Value)
 static INLINE void Xil_Out16(UINTPTR Addr, u16 Value)
 {
     volatile u16 *LocalAddr = (volatile u16 *)Addr;
-	*LocalAddr = Value;
+    *LocalAddr = Value;
 }
 
 /*****************************************************************************/
@@ -170,7 +170,7 @@ static INLINE void Xil_Out32(UINTPTR Addr, u32 Value)
 {
 #ifndef ENABLE_SAFETY
     volatile u32 *LocalAddr = (volatile u32 *)Addr;
-	*LocalAddr = Value;
+    *LocalAddr = Value;
 #else
     XStl_RegUpdate(Addr, Value);
 #endif
@@ -191,7 +191,7 @@ static INLINE void Xil_Out32(UINTPTR Addr, u32 Value)
 static INLINE void Xil_Out64(UINTPTR Addr, u64 Value)
 {
     volatile u64 *LocalAddr = (volatile u64 *)Addr;
-	*LocalAddr = Value;
+    *LocalAddr = Value;
 }
 
 #ifdef __cplusplus
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_printf.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_printf.h
index 89b6c3cc32..b6983a5d7e 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_printf.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_printf.h
@@ -13,4 +13,4 @@ extern "C" {
 }
 #endif
 
-#endif	/* end of protection macro */
+#endif    /* end of protection macro */
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h
index 50feebc430..a6988a20a5 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h
@@ -1,5 +1,5 @@
-#ifndef XIL_TYPES_H	/* prevent circular inclusions */
-#define XIL_TYPES_H	/* by using protection macros */
+#ifndef XIL_TYPES_H    /* prevent circular inclusions */
+#define XIL_TYPES_H    /* by using protection macros */
 
 #include 
 #include 
@@ -12,25 +12,25 @@ extern "C" {
 /************************** Constant Definitions *****************************/
 
 #ifndef TRUE
-#  define TRUE	    1U
+#  define TRUE        1U
 #endif
 
 #ifndef FALSE
-#  define FALSE	    0U
+#  define FALSE        0U
 #endif
 
 #ifndef NULL
-#define NULL	    0U
+#define NULL        0U
 #endif
 
 #define XIL_COMPONENT_IS_READY     0x11111111U  /**< In device drivers, This macro will be
                                                  assigend to "IsReady" member of driver
-												 instance to indicate that driver
-												 instance is initialized and ready to use. */
+                                                 instance to indicate that driver
+                                                 instance is initialized and ready to use. */
 #define XIL_COMPONENT_IS_STARTED   0x22222222U  /**< In device drivers, This macro will be assigend to
                                                  "IsStarted" member of driver instance
-												 to indicate that driver instance is
-												 started and it can be enabled. */
+                                                 to indicate that driver instance is
+                                                 started and it can be enabled. */
 
 typedef rt_uint8_t u8;
 typedef rt_uint16_t u16;
@@ -55,7 +55,7 @@ typedef unsigned long ULONG;
 #endif
 
 #define ULONG64_HI_MASK    0xFFFFFFFF00000000U
-#define ULONG64_LO_MASK	~ULONG64_HI_MASK
+#define ULONG64_LO_MASK    ~ULONG64_HI_MASK
 
 /** @{ */
 /**
@@ -73,15 +73,15 @@ typedef void (*XExceptionHandler) (void *InstancePtr);
 /************************** Constant Definitions *****************************/
 
 #ifndef TRUE
-#define TRUE	    1U
+#define TRUE        1U
 #endif
 
 #ifndef FALSE
-#define FALSE	    0U
+#define FALSE        0U
 #endif
 
 #ifndef NULL
-#define NULL	    0U
+#define NULL        0U
 #endif
 
 #ifdef __cplusplus
@@ -93,7 +93,7 @@ typedef void (*XExceptionHandler) (void *InstancePtr);
 }
 #endif
 
-#endif	/* end of protection macro */
+#endif    /* end of protection macro */
 /**
 * @} End of "addtogroup common_types".
 */
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters_ps.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters_ps.h
index dbd406ccbb..33117b152b 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters_ps.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters_ps.h
@@ -48,103 +48,103 @@ extern "C" {
  */
 
 /* Canonical definitions for DDR MEMORY */
-#define XPAR_DDR_MEM_BASEADDR	    0x00000000U
-#define XPAR_DDR_MEM_HIGHADDR	    0x3FFFFFFFU
+#define XPAR_DDR_MEM_BASEADDR        0x00000000U
+#define XPAR_DDR_MEM_HIGHADDR        0x3FFFFFFFU
 
 /* Canonical definitions for Interrupts  */
-#define XPAR_XUARTPS_0_INTR	    XPS_UART0_INT_ID
-#define XPAR_XUARTPS_1_INTR	    XPS_UART1_INT_ID
-#define XPAR_XIICPS_0_INTR	    XPS_I2C0_INT_ID
-#define XPAR_XIICPS_1_INTR	    XPS_I2C1_INT_ID
-#define XPAR_XSPIPS_0_INTR	    XPS_SPI0_INT_ID
-#define XPAR_XSPIPS_1_INTR	    XPS_SPI1_INT_ID
-#define XPAR_XCANPS_0_INTR	    XPS_CAN0_INT_ID
-#define XPAR_XCANPS_1_INTR	    XPS_CAN1_INT_ID
-#define XPAR_XGPIOPS_0_INTR	    XPS_GPIO_INT_ID
-#define XPAR_XEMACPS_0_INTR	    XPS_GEM0_INT_ID
+#define XPAR_XUARTPS_0_INTR        XPS_UART0_INT_ID
+#define XPAR_XUARTPS_1_INTR        XPS_UART1_INT_ID
+#define XPAR_XIICPS_0_INTR        XPS_I2C0_INT_ID
+#define XPAR_XIICPS_1_INTR        XPS_I2C1_INT_ID
+#define XPAR_XSPIPS_0_INTR        XPS_SPI0_INT_ID
+#define XPAR_XSPIPS_1_INTR        XPS_SPI1_INT_ID
+#define XPAR_XCANPS_0_INTR        XPS_CAN0_INT_ID
+#define XPAR_XCANPS_1_INTR        XPS_CAN1_INT_ID
+#define XPAR_XGPIOPS_0_INTR        XPS_GPIO_INT_ID
+#define XPAR_XEMACPS_0_INTR        XPS_GEM0_INT_ID
 #define XPAR_XEMACPS_0_WAKE_INTR    XPS_GEM0_WAKE_INT_ID
-#define XPAR_XEMACPS_1_INTR	    XPS_GEM1_INT_ID
+#define XPAR_XEMACPS_1_INTR        XPS_GEM1_INT_ID
 #define XPAR_XEMACPS_1_WAKE_INTR    XPS_GEM1_WAKE_INT_ID
-#define XPAR_XEMACPS_2_INTR	    XPS_GEM2_INT_ID
+#define XPAR_XEMACPS_2_INTR        XPS_GEM2_INT_ID
 #define XPAR_XEMACPS_2_WAKE_INTR    XPS_GEM2_WAKE_INT_ID
-#define XPAR_XEMACPS_3_INTR	    XPS_GEM3_INT_ID
+#define XPAR_XEMACPS_3_INTR        XPS_GEM3_INT_ID
 #define XPAR_XEMACPS_3_WAKE_INTR    XPS_GEM3_WAKE_INT_ID
-#define XPAR_XSDIOPS_0_INTR	    XPS_SDIO0_INT_ID
-#define XPAR_XQSPIPS_0_INTR	    XPS_QSPI_INT_ID
-#define XPAR_XSDIOPS_1_INTR	    XPS_SDIO1_INT_ID
-#define XPAR_XWDTPS_0_INTR	    XPS_CSU_WDT_INT_ID
-#define XPAR_XWDTPS_1_INTR	    XPS_LPD_SWDT_INT_ID
-#define XPAR_XWDTPS_2_INTR	    XPS_FPD_SWDT_INT_ID
-#define XPAR_XDCFG_0_INTR	    XPS_DVC_INT_ID
-#define XPAR_XTTCPS_0_INTR	    XPS_TTC0_0_INT_ID
-#define XPAR_XTTCPS_1_INTR	    XPS_TTC0_1_INT_ID
-#define XPAR_XTTCPS_2_INTR	    XPS_TTC0_2_INT_ID
-#define XPAR_XTTCPS_3_INTR	    XPS_TTC1_0_INT_ID
-#define XPAR_XTTCPS_4_INTR	    XPS_TTC1_1_INT_ID
-#define XPAR_XTTCPS_5_INTR	    XPS_TTC1_2_INT_ID
-#define XPAR_XTTCPS_6_INTR	    XPS_TTC2_0_INT_ID
-#define XPAR_XTTCPS_7_INTR	    XPS_TTC2_1_INT_ID
-#define XPAR_XTTCPS_8_INTR	    XPS_TTC2_2_INT_ID
-#define XPAR_XTTCPS_9_INTR	    XPS_TTC3_0_INT_ID
-#define XPAR_XTTCPS_10_INTR	    XPS_TTC3_1_INT_ID
-#define XPAR_XTTCPS_11_INTR	    XPS_TTC3_2_INT_ID
+#define XPAR_XSDIOPS_0_INTR        XPS_SDIO0_INT_ID
+#define XPAR_XQSPIPS_0_INTR        XPS_QSPI_INT_ID
+#define XPAR_XSDIOPS_1_INTR        XPS_SDIO1_INT_ID
+#define XPAR_XWDTPS_0_INTR        XPS_CSU_WDT_INT_ID
+#define XPAR_XWDTPS_1_INTR        XPS_LPD_SWDT_INT_ID
+#define XPAR_XWDTPS_2_INTR        XPS_FPD_SWDT_INT_ID
+#define XPAR_XDCFG_0_INTR        XPS_DVC_INT_ID
+#define XPAR_XTTCPS_0_INTR        XPS_TTC0_0_INT_ID
+#define XPAR_XTTCPS_1_INTR        XPS_TTC0_1_INT_ID
+#define XPAR_XTTCPS_2_INTR        XPS_TTC0_2_INT_ID
+#define XPAR_XTTCPS_3_INTR        XPS_TTC1_0_INT_ID
+#define XPAR_XTTCPS_4_INTR        XPS_TTC1_1_INT_ID
+#define XPAR_XTTCPS_5_INTR        XPS_TTC1_2_INT_ID
+#define XPAR_XTTCPS_6_INTR        XPS_TTC2_0_INT_ID
+#define XPAR_XTTCPS_7_INTR        XPS_TTC2_1_INT_ID
+#define XPAR_XTTCPS_8_INTR        XPS_TTC2_2_INT_ID
+#define XPAR_XTTCPS_9_INTR        XPS_TTC3_0_INT_ID
+#define XPAR_XTTCPS_10_INTR        XPS_TTC3_1_INT_ID
+#define XPAR_XTTCPS_11_INTR        XPS_TTC3_2_INT_ID
 #define XPAR_XNANDPS8_0_INTR            XPS_NAND_INT_ID
-#define XPAR_XADMAPS_0_INTR 	    XPS_ADMA_CH0_INT_ID
-#define XPAR_XADMAPS_1_INTR 	    XPS_ADMA_CH1_INT_ID
-#define XPAR_XADMAPS_2_INTR	    XPS_ADMA_CH2_INT_ID
-#define XPAR_XADMAPS_3_INTR 	    XPS_ADMA_CH3_INT_ID
-#define XPAR_XADMAPS_4_INTR	    XPS_ADMA_CH4_INT_ID
-#define XPAR_XADMAPS_5_INTR 	    XPS_ADMA_CH5_INT_ID
-#define XPAR_XADMAPS_6_INTR 	    XPS_ADMA_CH6_INT_ID
-#define XPAR_XADMAPS_7_INTR 	    XPS_ADMA_CH7_INT_ID
-#define XPAR_XCSUDMA_INTR 	    XPS_CSU_DMA_INT_ID
-#define XPAR_PSU_ADMA_0_INTR 	    XPS_ADMA_CH0_INT_ID
-#define XPAR_PSU_ADMA_1_INTR 	    XPS_ADMA_CH1_INT_ID
-#define XPAR_PSU_ADMA_2_INTR	    XPS_ADMA_CH2_INT_ID
-#define XPAR_PSU_ADMA_3_INTR 	    XPS_ADMA_CH3_INT_ID
-#define XPAR_PSU_ADMA_4_INTR	    XPS_ADMA_CH4_INT_ID
-#define XPAR_PSU_ADMA_5_INTR 	    XPS_ADMA_CH5_INT_ID
-#define XPAR_PSU_ADMA_6_INTR 	    XPS_ADMA_CH6_INT_ID
-#define XPAR_PSU_ADMA_7_INTR 	    XPS_ADMA_CH7_INT_ID
-#define XPAR_PSU_CSUDMA_INTR 	    XPS_CSU_DMA_INT_ID
-#define XPAR_XMPU_LPD_INTR 	    XPS_XMPU_LPD_INT_ID
-#define XPAR_XZDMAPS_0_INTR	    XPS_ZDMA_CH0_INT_ID
-#define XPAR_XZDMAPS_1_INTR	    XPS_ZDMA_CH1_INT_ID
-#define XPAR_XZDMAPS_2_INTR 	    XPS_ZDMA_CH2_INT_ID
-#define XPAR_XZDMAPS_3_INTR 	    XPS_ZDMA_CH3_INT_ID
-#define XPAR_XZDMAPS_4_INTR	    XPS_ZDMA_CH4_INT_ID
-#define XPAR_XZDMAPS_5_INTR 	    XPS_ZDMA_CH5_INT_ID
-#define XPAR_XZDMAPS_6_INTR 	    XPS_ZDMA_CH6_INT_ID
-#define XPAR_XZDMAPS_7_INTR 	    XPS_ZDMA_CH7_INT_ID
-#define XPAR_PSU_GDMA_0_INTR	    XPS_ZDMA_CH0_INT_ID
-#define XPAR_PSU_GDMA_1_INTR	    XPS_ZDMA_CH1_INT_ID
-#define XPAR_PSU_GDMA_2_INTR 	    XPS_ZDMA_CH2_INT_ID
-#define XPAR_PSU_GDMA_3_INTR 	    XPS_ZDMA_CH3_INT_ID
-#define XPAR_PSU_GDMA_4_INTR	    XPS_ZDMA_CH4_INT_ID
-#define XPAR_PSU_GDMA_5_INTR 	    XPS_ZDMA_CH5_INT_ID
-#define XPAR_PSU_GDMA_6_INTR 	    XPS_ZDMA_CH6_INT_ID
-#define XPAR_PSU_GDMA_7_INTR 	    XPS_ZDMA_CH7_INT_ID
-#define XPAR_XMPU_FPD_INTR 	    XPS_XMPU_FPD_INT_ID
-#define XPAR_XCCI_FPD_INTR 	    XPS_FPD_CCI_INT_ID
-#define XPAR_XSMMU_FPD_INTR 	    XPS_FPD_SMMU_INT_ID
-#define XPAR_XUSBPS_0_INTR	    XPS_USB3_0_ENDPT_INT_ID
-#define XPAR_XUSBPS_1_INTR	    XPS_USB3_1_ENDPT_INT_ID
-#define XPAR_XUSBPS_0_WAKE_INTR	    XPS_USB3_0_WAKE_INT_ID
-#define XPAR_XUSBPS_1_WAKE_INTR	    XPS_USB3_1_WAKE_INT_ID
+#define XPAR_XADMAPS_0_INTR         XPS_ADMA_CH0_INT_ID
+#define XPAR_XADMAPS_1_INTR         XPS_ADMA_CH1_INT_ID
+#define XPAR_XADMAPS_2_INTR        XPS_ADMA_CH2_INT_ID
+#define XPAR_XADMAPS_3_INTR         XPS_ADMA_CH3_INT_ID
+#define XPAR_XADMAPS_4_INTR        XPS_ADMA_CH4_INT_ID
+#define XPAR_XADMAPS_5_INTR         XPS_ADMA_CH5_INT_ID
+#define XPAR_XADMAPS_6_INTR         XPS_ADMA_CH6_INT_ID
+#define XPAR_XADMAPS_7_INTR         XPS_ADMA_CH7_INT_ID
+#define XPAR_XCSUDMA_INTR         XPS_CSU_DMA_INT_ID
+#define XPAR_PSU_ADMA_0_INTR         XPS_ADMA_CH0_INT_ID
+#define XPAR_PSU_ADMA_1_INTR         XPS_ADMA_CH1_INT_ID
+#define XPAR_PSU_ADMA_2_INTR        XPS_ADMA_CH2_INT_ID
+#define XPAR_PSU_ADMA_3_INTR         XPS_ADMA_CH3_INT_ID
+#define XPAR_PSU_ADMA_4_INTR        XPS_ADMA_CH4_INT_ID
+#define XPAR_PSU_ADMA_5_INTR         XPS_ADMA_CH5_INT_ID
+#define XPAR_PSU_ADMA_6_INTR         XPS_ADMA_CH6_INT_ID
+#define XPAR_PSU_ADMA_7_INTR         XPS_ADMA_CH7_INT_ID
+#define XPAR_PSU_CSUDMA_INTR         XPS_CSU_DMA_INT_ID
+#define XPAR_XMPU_LPD_INTR         XPS_XMPU_LPD_INT_ID
+#define XPAR_XZDMAPS_0_INTR        XPS_ZDMA_CH0_INT_ID
+#define XPAR_XZDMAPS_1_INTR        XPS_ZDMA_CH1_INT_ID
+#define XPAR_XZDMAPS_2_INTR         XPS_ZDMA_CH2_INT_ID
+#define XPAR_XZDMAPS_3_INTR         XPS_ZDMA_CH3_INT_ID
+#define XPAR_XZDMAPS_4_INTR        XPS_ZDMA_CH4_INT_ID
+#define XPAR_XZDMAPS_5_INTR         XPS_ZDMA_CH5_INT_ID
+#define XPAR_XZDMAPS_6_INTR         XPS_ZDMA_CH6_INT_ID
+#define XPAR_XZDMAPS_7_INTR         XPS_ZDMA_CH7_INT_ID
+#define XPAR_PSU_GDMA_0_INTR        XPS_ZDMA_CH0_INT_ID
+#define XPAR_PSU_GDMA_1_INTR        XPS_ZDMA_CH1_INT_ID
+#define XPAR_PSU_GDMA_2_INTR         XPS_ZDMA_CH2_INT_ID
+#define XPAR_PSU_GDMA_3_INTR         XPS_ZDMA_CH3_INT_ID
+#define XPAR_PSU_GDMA_4_INTR        XPS_ZDMA_CH4_INT_ID
+#define XPAR_PSU_GDMA_5_INTR         XPS_ZDMA_CH5_INT_ID
+#define XPAR_PSU_GDMA_6_INTR         XPS_ZDMA_CH6_INT_ID
+#define XPAR_PSU_GDMA_7_INTR         XPS_ZDMA_CH7_INT_ID
+#define XPAR_XMPU_FPD_INTR         XPS_XMPU_FPD_INT_ID
+#define XPAR_XCCI_FPD_INTR         XPS_FPD_CCI_INT_ID
+#define XPAR_XSMMU_FPD_INTR         XPS_FPD_SMMU_INT_ID
+#define XPAR_XUSBPS_0_INTR        XPS_USB3_0_ENDPT_INT_ID
+#define XPAR_XUSBPS_1_INTR        XPS_USB3_1_ENDPT_INT_ID
+#define XPAR_XUSBPS_0_WAKE_INTR        XPS_USB3_0_WAKE_INT_ID
+#define XPAR_XUSBPS_1_WAKE_INTR        XPS_USB3_1_WAKE_INT_ID
 #define    XPAR_XRTCPSU_ALARM_INTR     XPS_RTC_ALARM_INT_ID
 #define    XPAR_XRTCPSU_SECONDS_INTR    XPS_RTC_SEC_INT_ID
-#define XPAR_XAPMPS_0_INTR	    XPS_APM0_INT_ID
-#define XPAR_XAPMPS_1_INTR	    XPS_APM1_INT_ID
-#define XPAR_XAPMPS_2_INTR	    XPS_APM2_INT_ID
-#define XPAR_XAPMPS_5_INTR	    XPS_APM5_INT_ID
-#define XPAR_XSYSMONPSU_INTR	    XPS_AMS_INT_ID
+#define XPAR_XAPMPS_0_INTR        XPS_APM0_INT_ID
+#define XPAR_XAPMPS_1_INTR        XPS_APM1_INT_ID
+#define XPAR_XAPMPS_2_INTR        XPS_APM2_INT_ID
+#define XPAR_XAPMPS_5_INTR        XPS_APM5_INT_ID
+#define XPAR_XSYSMONPSU_INTR        XPS_AMS_INT_ID
 
 /* Canonical definitions for SCU GIC */
 #define XPAR_SCUGIC_NUM_INSTANCES    1U
 #define XPAR_SCUGIC_SINGLE_DEVICE_ID    0U
-#define XPAR_SCUGIC_CPU_BASEADDR	(XPS_SCU_PERIPH_BASE + 0x00001000U)
-#define XPAR_SCUGIC_DIST_BASEADDR	(XPS_SCU_PERIPH_BASE + 0x00002000U)
-#define XPAR_SCUGIC_ACK_BEFORE	    0U
+#define XPAR_SCUGIC_CPU_BASEADDR    (XPS_SCU_PERIPH_BASE + 0x00001000U)
+#define XPAR_SCUGIC_DIST_BASEADDR    (XPS_SCU_PERIPH_BASE + 0x00002000U)
+#define XPAR_SCUGIC_ACK_BEFORE        0U
 
 #define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ    XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ
 
@@ -155,97 +155,97 @@ extern "C" {
  */
 
 #define XPS_SYS_CTRL_BASEADDR    0xFF180000U
-#define XPS_SCU_PERIPH_BASE	    0xF9000000U
+#define XPS_SCU_PERIPH_BASE        0xF9000000U
 
 
 /* Shared Peripheral Interrupts (SPI) */
-#define XPS_FPGA0_INT_ID	    121U
-#define XPS_FPGA1_INT_ID	    122U
-#define XPS_FPGA2_INT_ID	    123U
-#define XPS_FPGA3_INT_ID	    124U
-#define XPS_FPGA4_INT_ID	    125U
-#define XPS_FPGA5_INT_ID	    126U
-#define XPS_FPGA6_INT_ID	    127U
-#define XPS_FPGA7_INT_ID	    128U
-#define XPS_FPGA8_INT_ID	    136U
-#define XPS_FPGA9_INT_ID	    137U
-#define XPS_FPGA10_INT_ID	    138U
-#define XPS_FPGA11_INT_ID	    139U
-#define XPS_FPGA12_INT_ID	    140U
-#define XPS_FPGA13_INT_ID	    141U
-#define XPS_FPGA14_INT_ID	    142U
-#define XPS_FPGA15_INT_ID	    143U
+#define XPS_FPGA0_INT_ID        121U
+#define XPS_FPGA1_INT_ID        122U
+#define XPS_FPGA2_INT_ID        123U
+#define XPS_FPGA3_INT_ID        124U
+#define XPS_FPGA4_INT_ID        125U
+#define XPS_FPGA5_INT_ID        126U
+#define XPS_FPGA6_INT_ID        127U
+#define XPS_FPGA7_INT_ID        128U
+#define XPS_FPGA8_INT_ID        136U
+#define XPS_FPGA9_INT_ID        137U
+#define XPS_FPGA10_INT_ID        138U
+#define XPS_FPGA11_INT_ID        139U
+#define XPS_FPGA12_INT_ID        140U
+#define XPS_FPGA13_INT_ID        141U
+#define XPS_FPGA14_INT_ID        142U
+#define XPS_FPGA15_INT_ID        143U
 
 /* Updated Interrupt-IDs */
-#define XPS_OCMINTR_INT_ID		(10U + 32U)
-#define XPS_NAND_INT_ID        		(14U + 32U)
-#define XPS_QSPI_INT_ID			(15U + 32U)
-#define XPS_GPIO_INT_ID			(16U + 32U)
-#define XPS_I2C0_INT_ID			(17U + 32U)
-#define XPS_I2C1_INT_ID			(18U + 32U)
-#define XPS_SPI0_INT_ID			(19U + 32U)
-#define XPS_SPI1_INT_ID			(20U + 32U)
-#define XPS_UART0_INT_ID		(21U + 32U)
-#define XPS_UART1_INT_ID		(22U + 32U)
-#define XPS_CAN0_INT_ID			(23U + 32U)
-#define XPS_CAN1_INT_ID			(24U + 32U)
-#define    XPS_RTC_ALARM_INT_ID 	(26U + 32U)
-#define    XPS_RTC_SEC_INT_ID	 	(27U + 32U)
-#define XPS_LPD_SWDT_INT_ID		(52U + 32U)
-#define XPS_CSU_WDT_INT_ID	    (53U + 32U)
-#define XPS_FPD_SWDT_INT_ID		(113U + 32U)
-#define XPS_TTC0_0_INT_ID		(36U + 32U)
-#define XPS_TTC0_1_INT_ID		(37U + 32U)
-#define XPS_TTC0_2_INT_ID 		(38U + 32U)
-#define XPS_TTC1_0_INT_ID		(39U + 32U)
-#define XPS_TTC1_1_INT_ID		(40U + 32U)
-#define XPS_TTC1_2_INT_ID		(41U + 32U)
-#define XPS_TTC2_0_INT_ID		(42U + 32U)
-#define XPS_TTC2_1_INT_ID		(43U + 32U)
-#define XPS_TTC2_2_INT_ID		(44U + 32U)
-#define XPS_TTC3_0_INT_ID		(45U + 32U)
-#define XPS_TTC3_1_INT_ID		(46U + 32U)
-#define XPS_TTC3_2_INT_ID		(47U + 32U)
-#define XPS_SDIO0_INT_ID		(48U + 32U)
-#define XPS_SDIO1_INT_ID		(49U + 32U)
-#define XPS_AMS_INT_ID			(56U + 32U)
-#define XPS_GEM0_INT_ID			(57U + 32U)
-#define XPS_GEM0_WAKE_INT_ID		(58U + 32U)
-#define XPS_GEM1_INT_ID			(59U + 32U)
-#define XPS_GEM1_WAKE_INT_ID		(60U + 32U)
-#define XPS_GEM2_INT_ID			(61U + 32U)
-#define XPS_GEM2_WAKE_INT_ID		(62U + 32U)
-#define XPS_GEM3_INT_ID			(63U + 32U)
-#define XPS_GEM3_WAKE_INT_ID		(64U + 32U)
-#define XPS_USB3_0_ENDPT_INT_ID		(65U + 32U)
-#define XPS_USB3_1_ENDPT_INT_ID		(70U + 32U)
-#define XPS_USB3_0_WAKE_INT_ID		(75U + 32U)
-#define XPS_USB3_1_WAKE_INT_ID		(76U + 32U)
-#define XPS_ADMA_CH0_INT_ID		(77U + 32U)
-#define XPS_ADMA_CH1_INT_ID		(78U + 32U)
-#define XPS_ADMA_CH2_INT_ID		(79U + 32U)
-#define XPS_ADMA_CH3_INT_ID		(80U + 32U)
-#define XPS_ADMA_CH4_INT_ID		(81U + 32U)
-#define XPS_ADMA_CH5_INT_ID		(82U + 32U)
-#define XPS_ADMA_CH6_INT_ID		(83U + 32U)
-#define XPS_ADMA_CH7_INT_ID		(84U + 32U)
-#define XPS_CSU_DMA_INT_ID		(86U + 32U)
-#define XPS_XMPU_LPD_INT_ID		(88U + 32U)
-#define XPS_ZDMA_CH0_INT_ID		(124U + 32U)
-#define XPS_ZDMA_CH1_INT_ID		(125U + 32U)
-#define XPS_ZDMA_CH2_INT_ID		(126U + 32U)
-#define XPS_ZDMA_CH3_INT_ID		(127U + 32U)
-#define XPS_ZDMA_CH4_INT_ID		(128U + 32U)
-#define XPS_ZDMA_CH5_INT_ID		(129U + 32U)
-#define XPS_ZDMA_CH6_INT_ID		(130U + 32U)
-#define XPS_ZDMA_CH7_INT_ID		(131U + 32U)
-#define XPS_XMPU_FPD_INT_ID		(134U + 32U)
-#define XPS_FPD_CCI_INT_ID		(154U + 32U)
-#define XPS_FPD_SMMU_INT_ID		(155U + 32U)
-#define XPS_APM0_INT_ID		(123U + 32U)
-#define XPS_APM1_INT_ID		(25U + 32U)
-#define XPS_APM2_INT_ID		(25U + 32U)
-#define XPS_APM5_INT_ID		(123U + 32U)
+#define XPS_OCMINTR_INT_ID        (10U + 32U)
+#define XPS_NAND_INT_ID                (14U + 32U)
+#define XPS_QSPI_INT_ID            (15U + 32U)
+#define XPS_GPIO_INT_ID            (16U + 32U)
+#define XPS_I2C0_INT_ID            (17U + 32U)
+#define XPS_I2C1_INT_ID            (18U + 32U)
+#define XPS_SPI0_INT_ID            (19U + 32U)
+#define XPS_SPI1_INT_ID            (20U + 32U)
+#define XPS_UART0_INT_ID        (21U + 32U)
+#define XPS_UART1_INT_ID        (22U + 32U)
+#define XPS_CAN0_INT_ID            (23U + 32U)
+#define XPS_CAN1_INT_ID            (24U + 32U)
+#define    XPS_RTC_ALARM_INT_ID     (26U + 32U)
+#define    XPS_RTC_SEC_INT_ID         (27U + 32U)
+#define XPS_LPD_SWDT_INT_ID        (52U + 32U)
+#define XPS_CSU_WDT_INT_ID        (53U + 32U)
+#define XPS_FPD_SWDT_INT_ID        (113U + 32U)
+#define XPS_TTC0_0_INT_ID        (36U + 32U)
+#define XPS_TTC0_1_INT_ID        (37U + 32U)
+#define XPS_TTC0_2_INT_ID         (38U + 32U)
+#define XPS_TTC1_0_INT_ID        (39U + 32U)
+#define XPS_TTC1_1_INT_ID        (40U + 32U)
+#define XPS_TTC1_2_INT_ID        (41U + 32U)
+#define XPS_TTC2_0_INT_ID        (42U + 32U)
+#define XPS_TTC2_1_INT_ID        (43U + 32U)
+#define XPS_TTC2_2_INT_ID        (44U + 32U)
+#define XPS_TTC3_0_INT_ID        (45U + 32U)
+#define XPS_TTC3_1_INT_ID        (46U + 32U)
+#define XPS_TTC3_2_INT_ID        (47U + 32U)
+#define XPS_SDIO0_INT_ID        (48U + 32U)
+#define XPS_SDIO1_INT_ID        (49U + 32U)
+#define XPS_AMS_INT_ID            (56U + 32U)
+#define XPS_GEM0_INT_ID            (57U + 32U)
+#define XPS_GEM0_WAKE_INT_ID        (58U + 32U)
+#define XPS_GEM1_INT_ID            (59U + 32U)
+#define XPS_GEM1_WAKE_INT_ID        (60U + 32U)
+#define XPS_GEM2_INT_ID            (61U + 32U)
+#define XPS_GEM2_WAKE_INT_ID        (62U + 32U)
+#define XPS_GEM3_INT_ID            (63U + 32U)
+#define XPS_GEM3_WAKE_INT_ID        (64U + 32U)
+#define XPS_USB3_0_ENDPT_INT_ID        (65U + 32U)
+#define XPS_USB3_1_ENDPT_INT_ID        (70U + 32U)
+#define XPS_USB3_0_WAKE_INT_ID        (75U + 32U)
+#define XPS_USB3_1_WAKE_INT_ID        (76U + 32U)
+#define XPS_ADMA_CH0_INT_ID        (77U + 32U)
+#define XPS_ADMA_CH1_INT_ID        (78U + 32U)
+#define XPS_ADMA_CH2_INT_ID        (79U + 32U)
+#define XPS_ADMA_CH3_INT_ID        (80U + 32U)
+#define XPS_ADMA_CH4_INT_ID        (81U + 32U)
+#define XPS_ADMA_CH5_INT_ID        (82U + 32U)
+#define XPS_ADMA_CH6_INT_ID        (83U + 32U)
+#define XPS_ADMA_CH7_INT_ID        (84U + 32U)
+#define XPS_CSU_DMA_INT_ID        (86U + 32U)
+#define XPS_XMPU_LPD_INT_ID        (88U + 32U)
+#define XPS_ZDMA_CH0_INT_ID        (124U + 32U)
+#define XPS_ZDMA_CH1_INT_ID        (125U + 32U)
+#define XPS_ZDMA_CH2_INT_ID        (126U + 32U)
+#define XPS_ZDMA_CH3_INT_ID        (127U + 32U)
+#define XPS_ZDMA_CH4_INT_ID        (128U + 32U)
+#define XPS_ZDMA_CH5_INT_ID        (129U + 32U)
+#define XPS_ZDMA_CH6_INT_ID        (130U + 32U)
+#define XPS_ZDMA_CH7_INT_ID        (131U + 32U)
+#define XPS_XMPU_FPD_INT_ID        (134U + 32U)
+#define XPS_FPD_CCI_INT_ID        (154U + 32U)
+#define XPS_FPD_SMMU_INT_ID        (155U + 32U)
+#define XPS_APM0_INT_ID        (123U + 32U)
+#define XPS_APM1_INT_ID        (25U + 32U)
+#define XPS_APM2_INT_ID        (25U + 32U)
+#define XPS_APM5_INT_ID        (123U + 32U)
 
 /* REDEFINES for TEST APP */
 #define XPAR_PSU_UART_0_INTR        XPS_UART0_INT_ID
@@ -268,7 +268,7 @@ extern "C" {
 #define XPAR_PSU_ETHERNET_3_INTR    XPS_GEM3_INT_ID
 #define XPAR_PSU_ETHERNET_3_WAKE_INTR   XPS_GEM3_WAKE_INT_ID
 #define XPAR_PSU_QSPI_0_INTR        XPS_QSPI_INT_ID
-#define XPAR_PSU_WDT_0_INTR    	    XPS_LPD_SWDT_INT_ID
+#define XPAR_PSU_WDT_0_INTR            XPS_LPD_SWDT_INT_ID
 #define XPAR_PSU_WDT_1_INTR         XPS_FPD_SWDT_INT_ID
 #define XPAR_PSU_XADC_0_INTR        XPS_SYSMON_INT_ID
 #define XPAR_PSU_TTC_0_INTR         XPS_TTC0_0_INT_ID
@@ -277,32 +277,32 @@ extern "C" {
 #define XPAR_PSU_TTC_3_INTR         XPS_TTC1_0_INT_ID
 #define XPAR_PSU_TTC_4_INTR         XPS_TTC1_1_INT_ID
 #define XPAR_PSU_TTC_5_INTR         XPS_TTC1_2_INT_ID
-#define XPAR_PSU_TTC_6_INTR		    XPS_TTC2_0_INT_ID
-#define XPAR_PSU_TTC_7_INTR		    XPS_TTC2_1_INT_ID
-#define XPAR_PSU_TTC_8_INTR		    XPS_TTC2_2_INT_ID
-#define XPAR_PSU_TTC_9_INTR		    XPS_TTC3_0_INT_ID
-#define XPAR_PSU_TTC_10_INTR	    XPS_TTC3_1_INT_ID
-#define XPAR_PSU_TTC_11_INTR	    XPS_TTC3_2_INT_ID
-#define XPAR_PSU_AMS_INTR		    XPS_AMS_INT_ID
+#define XPAR_PSU_TTC_6_INTR            XPS_TTC2_0_INT_ID
+#define XPAR_PSU_TTC_7_INTR            XPS_TTC2_1_INT_ID
+#define XPAR_PSU_TTC_8_INTR            XPS_TTC2_2_INT_ID
+#define XPAR_PSU_TTC_9_INTR            XPS_TTC3_0_INT_ID
+#define XPAR_PSU_TTC_10_INTR        XPS_TTC3_1_INT_ID
+#define XPAR_PSU_TTC_11_INTR        XPS_TTC3_2_INT_ID
+#define XPAR_PSU_AMS_INTR            XPS_AMS_INT_ID
 
 #define XPAR_XADCPS_NUM_INSTANCES 1U
 #define XPAR_XADCPS_0_DEVICE_ID   0U
-#define XPAR_XADCPS_0_BASEADDR	  (0xF8007000U)
-#define XPAR_XADCPS_INT_ID	    XPS_SYSMON_INT_ID
+#define XPAR_XADCPS_0_BASEADDR      (0xF8007000U)
+#define XPAR_XADCPS_INT_ID        XPS_SYSMON_INT_ID
 
 /* For backwards compatibility */
-#define XPAR_XUARTPS_0_CLOCK_HZ	    XPAR_XUARTPS_0_UART_CLK_FREQ_HZ
-#define XPAR_XUARTPS_1_CLOCK_HZ	    XPAR_XUARTPS_1_UART_CLK_FREQ_HZ
-#define XPAR_XTTCPS_0_CLOCK_HZ	    XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ
-#define XPAR_XTTCPS_1_CLOCK_HZ	    XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ
-#define XPAR_XTTCPS_2_CLOCK_HZ	    XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ
-#define XPAR_XTTCPS_3_CLOCK_HZ	    XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ
-#define XPAR_XTTCPS_4_CLOCK_HZ	    XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ
-#define XPAR_XTTCPS_5_CLOCK_HZ	    XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ
-#define XPAR_XIICPS_0_CLOCK_HZ	    XPAR_XIICPS_0_I2C_CLK_FREQ_HZ
-#define XPAR_XIICPS_1_CLOCK_HZ	    XPAR_XIICPS_1_I2C_CLK_FREQ_HZ
+#define XPAR_XUARTPS_0_CLOCK_HZ        XPAR_XUARTPS_0_UART_CLK_FREQ_HZ
+#define XPAR_XUARTPS_1_CLOCK_HZ        XPAR_XUARTPS_1_UART_CLK_FREQ_HZ
+#define XPAR_XTTCPS_0_CLOCK_HZ        XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ
+#define XPAR_XTTCPS_1_CLOCK_HZ        XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ
+#define XPAR_XTTCPS_2_CLOCK_HZ        XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ
+#define XPAR_XTTCPS_3_CLOCK_HZ        XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ
+#define XPAR_XTTCPS_4_CLOCK_HZ        XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ
+#define XPAR_XTTCPS_5_CLOCK_HZ        XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ
+#define XPAR_XIICPS_0_CLOCK_HZ        XPAR_XIICPS_0_I2C_CLK_FREQ_HZ
+#define XPAR_XIICPS_1_CLOCK_HZ        XPAR_XIICPS_1_I2C_CLK_FREQ_HZ
 
-#define XPAR_XQSPIPS_0_CLOCK_HZ	    XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ
+#define XPAR_XQSPIPS_0_CLOCK_HZ        XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ
 
 #ifdef XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ
 #define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ    XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ
@@ -312,7 +312,7 @@ extern "C" {
 #define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ    XPAR_CPU_CORTEXR5_1_CPU_CLK_FREQ_HZ
 #endif
 
-#define XPAR_SCUWDT_DEVICE_ID	    0U
+#define XPAR_SCUWDT_DEVICE_ID        0U
 
 
 #ifdef __cplusplus
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h
index 7a55d8b0b5..4213736270 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h
@@ -1,5 +1,5 @@
-#ifndef XPLATFORM_INFO_H		/* prevent circular inclusions */
-#define XPLATFORM_INFO_H		/* by using protection macros */
+#ifndef XPLATFORM_INFO_H        /* prevent circular inclusions */
+#define XPLATFORM_INFO_H        /* by using protection macros */
 
 #include "xil_types.h"
 #include "xparameters.h"
@@ -12,12 +12,12 @@ extern "C" {
 #define XPAR_PMC_TAP_BASEADDR 0xF11A0000U
 #define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U
 #define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \
-								    XPAR_PMC_TAP_VERSION_OFFSET)
+                                    XPAR_PMC_TAP_VERSION_OFFSET)
 #else
 #define XPAR_CSU_BASEADDR 0xFFCA0000U
 #define    XPAR_CSU_VER_OFFSET 0x00000044U
 #define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \
-								    XPAR_CSU_VER_OFFSET)
+                                    XPAR_CSU_VER_OFFSET)
 #endif
 #define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0
 #define XPLAT_ZYNQ_ULTRA_MP 0x1
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xstatus.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xstatus.h
index 8d4d0ac61a..abeb6b8838 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xstatus.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xstatus.h
@@ -16,8 +16,8 @@
 * @{
 ******************************************************************************/
 
-#ifndef XSTATUS_H		/* prevent circular inclusions */
-#define XSTATUS_H		/* by using protection macros */
+#ifndef XSTATUS_H        /* prevent circular inclusions */
+#define XSTATUS_H        /* by using protection macros */
 
 #ifdef __cplusplus
 extern "C" {
@@ -42,53 +42,53 @@ extern "C" {
 #define XST_INVALID_VERSION             4L
 #define XST_DEVICE_IS_STARTED           5L
 #define XST_DEVICE_IS_STOPPED           6L
-#define XST_FIFO_ERROR                  7L	/*!< An error occurred during an
-						   operation with a FIFO such as
-						   an underrun or overrun, this
-						   error requires the device to
-						   be reset */
-#define XST_RESET_ERROR                 8L	/*!< An error occurred which requires
-						   the device to be reset */
-#define XST_DMA_ERROR                   9L	/*!< A DMA error occurred, this error
-						   typically requires the device
-						   using the DMA to be reset */
-#define XST_NOT_POLLED                  10L	/*!< The device is not configured for
-						   polled mode operation */
-#define XST_FIFO_NO_ROOM                11L	/*!< A FIFO did not have room to put
-						   the specified data into */
-#define XST_BUFFER_TOO_SMALL            12L	/*!< The buffer is not large enough
-						   to hold the expected data */
-#define XST_NO_DATA                     13L	/*!< There was no data available */
-#define XST_REGISTER_ERROR              14L	/*!< A register did not contain the
-						   expected value */
-#define XST_INVALID_PARAM               15L	/*!< An invalid parameter was passed
-						   into the function */
-#define XST_NOT_SGDMA                   16L	/*!< The device is not configured for
-						   scatter-gather DMA operation */
-#define XST_LOOPBACK_ERROR              17L	/*!< A loopback test failed */
-#define XST_NO_CALLBACK                 18L	/*!< A callback has not yet been
-						   registered */
-#define XST_NO_FEATURE                  19L	/*!< Device is not configured with
-						   the requested feature */
-#define XST_NOT_INTERRUPT               20L	/*!< Device is not configured for
-						   interrupt mode operation */
-#define XST_DEVICE_BUSY                 21L	/*!< Device is busy */
-#define XST_ERROR_COUNT_MAX             22L	/*!< The error counters of a device
-						   have maxed out */
-#define XST_IS_STARTED                  23L	/*!< Used when part of device is
-						   already started i.e.
-						   sub channel */
-#define XST_IS_STOPPED                  24L	/*!< Used when part of device is
-						   already stopped i.e.
-						   sub channel */
-#define XST_DATA_LOST                   26L	/*!< Driver defined error */
-#define XST_RECV_ERROR                  27L	/*!< Generic receive error */
-#define XST_SEND_ERROR                  28L	/*!< Generic transmit error */
-#define XST_NOT_ENABLED                 29L	/*!< A requested service is not
-						   available because it has not
-						   been enabled */
-#define XST_NO_ACCESS		    30L	/* Generic access error */
-#define XST_TIMEOUT                     31L	/*!< Event timeout occurred */
+#define XST_FIFO_ERROR                  7L    /*!< An error occurred during an
+                           operation with a FIFO such as
+                           an underrun or overrun, this
+                           error requires the device to
+                           be reset */
+#define XST_RESET_ERROR                 8L    /*!< An error occurred which requires
+                           the device to be reset */
+#define XST_DMA_ERROR                   9L    /*!< A DMA error occurred, this error
+                           typically requires the device
+                           using the DMA to be reset */
+#define XST_NOT_POLLED                  10L    /*!< The device is not configured for
+                           polled mode operation */
+#define XST_FIFO_NO_ROOM                11L    /*!< A FIFO did not have room to put
+                           the specified data into */
+#define XST_BUFFER_TOO_SMALL            12L    /*!< The buffer is not large enough
+                           to hold the expected data */
+#define XST_NO_DATA                     13L    /*!< There was no data available */
+#define XST_REGISTER_ERROR              14L    /*!< A register did not contain the
+                           expected value */
+#define XST_INVALID_PARAM               15L    /*!< An invalid parameter was passed
+                           into the function */
+#define XST_NOT_SGDMA                   16L    /*!< The device is not configured for
+                           scatter-gather DMA operation */
+#define XST_LOOPBACK_ERROR              17L    /*!< A loopback test failed */
+#define XST_NO_CALLBACK                 18L    /*!< A callback has not yet been
+                           registered */
+#define XST_NO_FEATURE                  19L    /*!< Device is not configured with
+                           the requested feature */
+#define XST_NOT_INTERRUPT               20L    /*!< Device is not configured for
+                           interrupt mode operation */
+#define XST_DEVICE_BUSY                 21L    /*!< Device is busy */
+#define XST_ERROR_COUNT_MAX             22L    /*!< The error counters of a device
+                           have maxed out */
+#define XST_IS_STARTED                  23L    /*!< Used when part of device is
+                           already started i.e.
+                           sub channel */
+#define XST_IS_STOPPED                  24L    /*!< Used when part of device is
+                           already stopped i.e.
+                           sub channel */
+#define XST_DATA_LOST                   26L    /*!< Driver defined error */
+#define XST_RECV_ERROR                  27L    /*!< Generic receive error */
+#define XST_SEND_ERROR                  28L    /*!< Generic transmit error */
+#define XST_NOT_ENABLED                 29L    /*!< A requested service is not
+                           available because it has not
+                           been enabled */
+#define XST_NO_ACCESS            30L    /* Generic access error */
+#define XST_TIMEOUT                     31L    /*!< Event timeout occurred */
 
 /** @} */
 /***************** Utility Component statuses 401 - 500  *********************/
@@ -96,7 +96,7 @@ extern "C" {
 @name Utility Component Status Codes 401 - 500
 @{
 */
-#define XST_MEMTEST_FAILED              401L	/*!< Memory test failed */
+#define XST_MEMTEST_FAILED              401L    /*!< Memory test failed */
 
 /** @} */
 /***************** Common Components statuses 501 - 1000 *********************/
@@ -106,14 +106,14 @@ extern "C" {
 */
 /********************* Packet Fifo statuses 501 - 510 ************************/
 
-#define XST_PFIFO_LACK_OF_DATA          501L	/*!< Not enough data in FIFO   */
-#define XST_PFIFO_NO_ROOM               502L	/*!< Not enough room in FIFO   */
-#define XST_PFIFO_BAD_REG_VALUE         503L	/*!< Self test, a register value
-						   was invalid after reset */
-#define XST_PFIFO_ERROR                 504L	/*!< Generic packet FIFO error */
-#define XST_PFIFO_DEADLOCK              505L	/*!< Packet FIFO is reporting
-						 * empty and full simultaneously
-						 */
+#define XST_PFIFO_LACK_OF_DATA          501L    /*!< Not enough data in FIFO   */
+#define XST_PFIFO_NO_ROOM               502L    /*!< Not enough room in FIFO   */
+#define XST_PFIFO_BAD_REG_VALUE         503L    /*!< Self test, a register value
+                           was invalid after reset */
+#define XST_PFIFO_ERROR                 504L    /*!< Generic packet FIFO error */
+#define XST_PFIFO_DEADLOCK              505L    /*!< Packet FIFO is reporting
+                         * empty and full simultaneously
+                         */
 /** @} */
 /**
 @name DMA Status Codes 511 - 530
@@ -121,44 +121,44 @@ extern "C" {
 */
 /************************** DMA statuses 511 - 530 ***************************/
 
-#define XST_DMA_TRANSFER_ERROR          511L	/*!< Self test, DMA transfer
-						   failed */
-#define XST_DMA_RESET_REGISTER_ERROR    512L	/*!< Self test, a register value
-						   was invalid after reset */
-#define XST_DMA_SG_LIST_EMPTY           513L	/*!< Scatter gather list contains
-						   no buffer descriptors ready
-						   to be processed */
-#define XST_DMA_SG_IS_STARTED           514L	/*!< Scatter gather not stopped */
-#define XST_DMA_SG_IS_STOPPED           515L	/*!< Scatter gather not running */
-#define XST_DMA_SG_LIST_FULL            517L	/*!< All the buffer descriptors of
-						   the scatter gather list are
-						   being used */
-#define XST_DMA_SG_BD_LOCKED            518L	/*!< The scatter gather buffer
-						   descriptor which is to be
-						   copied over in the scatter
-						   list is locked */
-#define XST_DMA_SG_NOTHING_TO_COMMIT    519L	/*!< No buffer descriptors have been
-						   put into the scatter gather
-						   list to be committed */
-#define XST_DMA_SG_COUNT_EXCEEDED       521L	/*!< The packet count threshold
-						   specified was larger than the
-						   total # of buffer descriptors
-						   in the scatter gather list */
-#define XST_DMA_SG_LIST_EXISTS          522L	/*!< The scatter gather list has
-						   already been created */
-#define XST_DMA_SG_NO_LIST              523L	/*!< No scatter gather list has
-						   been created */
-#define XST_DMA_SG_BD_NOT_COMMITTED     524L	/*!< The buffer descriptor which was
-						   being started was not committed
-						   to the list */
-#define XST_DMA_SG_NO_DATA              525L	/*!< The buffer descriptor to start
-						   has already been used by the
-						   hardware so it can't be reused
-						 */
-#define XST_DMA_SG_LIST_ERROR           526L	/*!< General purpose list access
-						   error */
-#define XST_DMA_BD_ERROR                527L	/*!< General buffer descriptor
-						   error */
+#define XST_DMA_TRANSFER_ERROR          511L    /*!< Self test, DMA transfer
+                           failed */
+#define XST_DMA_RESET_REGISTER_ERROR    512L    /*!< Self test, a register value
+                           was invalid after reset */
+#define XST_DMA_SG_LIST_EMPTY           513L    /*!< Scatter gather list contains
+                           no buffer descriptors ready
+                           to be processed */
+#define XST_DMA_SG_IS_STARTED           514L    /*!< Scatter gather not stopped */
+#define XST_DMA_SG_IS_STOPPED           515L    /*!< Scatter gather not running */
+#define XST_DMA_SG_LIST_FULL            517L    /*!< All the buffer descriptors of
+                           the scatter gather list are
+                           being used */
+#define XST_DMA_SG_BD_LOCKED            518L    /*!< The scatter gather buffer
+                           descriptor which is to be
+                           copied over in the scatter
+                           list is locked */
+#define XST_DMA_SG_NOTHING_TO_COMMIT    519L    /*!< No buffer descriptors have been
+                           put into the scatter gather
+                           list to be committed */
+#define XST_DMA_SG_COUNT_EXCEEDED       521L    /*!< The packet count threshold
+                           specified was larger than the
+                           total # of buffer descriptors
+                           in the scatter gather list */
+#define XST_DMA_SG_LIST_EXISTS          522L    /*!< The scatter gather list has
+                           already been created */
+#define XST_DMA_SG_NO_LIST              523L    /*!< No scatter gather list has
+                           been created */
+#define XST_DMA_SG_BD_NOT_COMMITTED     524L    /*!< The buffer descriptor which was
+                           being started was not committed
+                           to the list */
+#define XST_DMA_SG_NO_DATA              525L    /*!< The buffer descriptor to start
+                           has already been used by the
+                           hardware so it can't be reused
+                         */
+#define XST_DMA_SG_LIST_ERROR           526L    /*!< General purpose list access
+                           error */
+#define XST_DMA_BD_ERROR                527L    /*!< General buffer descriptor
+                           error */
 /** @} */
 /**
 @name IPIF Status Codes Codes 531 - 550
@@ -166,34 +166,34 @@ extern "C" {
 */
 /************************** IPIF statuses 531 - 550 ***************************/
 
-#define XST_IPIF_REG_WIDTH_ERROR        531L	/*!< An invalid register width
-						   was passed into the function */
-#define XST_IPIF_RESET_REGISTER_ERROR   532L	/*!< The value of a register at
-						   reset was not valid */
-#define XST_IPIF_DEVICE_STATUS_ERROR    533L	/*!< A write to the device interrupt
-						   status register did not read
-						   back correctly */
-#define XST_IPIF_DEVICE_ACK_ERROR       534L	/*!< The device interrupt status
-						   register did not reset when
-						   acked */
-#define XST_IPIF_DEVICE_ENABLE_ERROR    535L	/*!< The device interrupt enable
-						   register was not updated when
-						   other registers changed */
-#define XST_IPIF_IP_STATUS_ERROR        536L	/*!< A write to the IP interrupt
-						   status register did not read
-						   back correctly */
-#define XST_IPIF_IP_ACK_ERROR           537L	/*!< The IP interrupt status register
-						   did not reset when acked */
-#define XST_IPIF_IP_ENABLE_ERROR        538L	/*!< IP interrupt enable register was
-						   not updated correctly when other
-						   registers changed */
-#define XST_IPIF_DEVICE_PENDING_ERROR   539L	/*!< The device interrupt pending
-						   register did not indicate the
-						   expected value */
-#define XST_IPIF_DEVICE_ID_ERROR        540L	/*!< The device interrupt ID register
-						   did not indicate the expected
-						   value */
-#define XST_IPIF_ERROR                  541L	/*!< Generic ipif error */
+#define XST_IPIF_REG_WIDTH_ERROR        531L    /*!< An invalid register width
+                           was passed into the function */
+#define XST_IPIF_RESET_REGISTER_ERROR   532L    /*!< The value of a register at
+                           reset was not valid */
+#define XST_IPIF_DEVICE_STATUS_ERROR    533L    /*!< A write to the device interrupt
+                           status register did not read
+                           back correctly */
+#define XST_IPIF_DEVICE_ACK_ERROR       534L    /*!< The device interrupt status
+                           register did not reset when
+                           acked */
+#define XST_IPIF_DEVICE_ENABLE_ERROR    535L    /*!< The device interrupt enable
+                           register was not updated when
+                           other registers changed */
+#define XST_IPIF_IP_STATUS_ERROR        536L    /*!< A write to the IP interrupt
+                           status register did not read
+                           back correctly */
+#define XST_IPIF_IP_ACK_ERROR           537L    /*!< The IP interrupt status register
+                           did not reset when acked */
+#define XST_IPIF_IP_ENABLE_ERROR        538L    /*!< IP interrupt enable register was
+                           not updated correctly when other
+                           registers changed */
+#define XST_IPIF_DEVICE_PENDING_ERROR   539L    /*!< The device interrupt pending
+                           register did not indicate the
+                           expected value */
+#define XST_IPIF_DEVICE_ID_ERROR        540L    /*!< The device interrupt ID register
+                           did not indicate the expected
+                           value */
+#define XST_IPIF_ERROR                  541L    /*!< Generic ipif error */
 /** @} */
 
 /****************** Device specific statuses 1001 - 4095 *********************/
@@ -203,16 +203,16 @@ extern "C" {
 */
 /********************* Ethernet statuses 1001 - 1050 *************************/
 
-#define XST_EMAC_MEMORY_SIZE_ERROR  1001L	/*!< Memory space is not big enough
-						 * to hold the minimum number of
-						 * buffers or descriptors */
-#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L	/*!< Memory allocation failed */
-#define XST_EMAC_MII_READ_ERROR     1003L	/*!< MII read error */
-#define XST_EMAC_MII_BUSY           1004L	/*!< An MII operation is in progress */
-#define XST_EMAC_OUT_OF_BUFFERS     1005L	/*!< Driver is out of buffers */
-#define XST_EMAC_PARSE_ERROR        1006L	/*!< Invalid driver init string */
-#define XST_EMAC_COLLISION_ERROR    1007L	/*!< Excess deferral or late
-						 * collision on polled send */
+#define XST_EMAC_MEMORY_SIZE_ERROR  1001L    /*!< Memory space is not big enough
+                         * to hold the minimum number of
+                         * buffers or descriptors */
+#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L    /*!< Memory allocation failed */
+#define XST_EMAC_MII_READ_ERROR     1003L    /*!< MII read error */
+#define XST_EMAC_MII_BUSY           1004L    /*!< An MII operation is in progress */
+#define XST_EMAC_OUT_OF_BUFFERS     1005L    /*!< Driver is out of buffers */
+#define XST_EMAC_PARSE_ERROR        1006L    /*!< Invalid driver init string */
+#define XST_EMAC_COLLISION_ERROR    1007L    /*!< Excess deferral or late
+                         * collision on polled send */
 /** @} */
 /**
 @name UART Status Codes 1051 - 1075
@@ -235,30 +235,30 @@ extern "C" {
 */
 /************************ IIC statuses 1076 - 1100 ***************************/
 
-#define XST_IIC_SELFTEST_FAILED         1076	/*!< self test failed            */
-#define XST_IIC_BUS_BUSY                1077	/*!< bus found busy              */
-#define XST_IIC_GENERAL_CALL_ADDRESS    1078	/*!< mastersend attempted with   */
-					     /* general call address        */
-#define XST_IIC_STAND_REG_RESET_ERROR   1079	/*!< A non parameterizable reg   */
-					     /* value after reset not valid */
-#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080	/*!< Tx fifo included in design  */
-					     /* value after reset not valid */
-#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081	/*!< Rx fifo included in design  */
-					     /* value after reset not valid */
-#define XST_IIC_TBA_REG_RESET_ERROR     1082	/*!< 10 bit addr incl in design  */
-					     /* value after reset not valid */
-#define XST_IIC_CR_READBACK_ERROR       1083	/*!< Read of the control register */
-					     /* didn't return value written */
-#define XST_IIC_DTR_READBACK_ERROR      1084	/*!< Read of the data Tx reg     */
-					     /* didn't return value written */
-#define XST_IIC_DRR_READBACK_ERROR      1085	/*!< Read of the data Receive reg */
-					     /* didn't return value written */
-#define XST_IIC_ADR_READBACK_ERROR      1086	/*!< Read of the data Tx reg     */
-					     /* didn't return value written */
-#define XST_IIC_TBA_READBACK_ERROR      1087	/*!< Read of the 10 bit addr reg */
-					     /* didn't return written value */
-#define XST_IIC_NOT_SLAVE               1088	/*!< The device isn't a slave    */
-#define XST_IIC_ARB_LOST 			    1089 	/*!< Arbitration lost for master	*/
+#define XST_IIC_SELFTEST_FAILED         1076    /*!< self test failed            */
+#define XST_IIC_BUS_BUSY                1077    /*!< bus found busy              */
+#define XST_IIC_GENERAL_CALL_ADDRESS    1078    /*!< mastersend attempted with   */
+                         /* general call address        */
+#define XST_IIC_STAND_REG_RESET_ERROR   1079    /*!< A non parameterizable reg   */
+                         /* value after reset not valid */
+#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080    /*!< Tx fifo included in design  */
+                         /* value after reset not valid */
+#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081    /*!< Rx fifo included in design  */
+                         /* value after reset not valid */
+#define XST_IIC_TBA_REG_RESET_ERROR     1082    /*!< 10 bit addr incl in design  */
+                         /* value after reset not valid */
+#define XST_IIC_CR_READBACK_ERROR       1083    /*!< Read of the control register */
+                         /* didn't return value written */
+#define XST_IIC_DTR_READBACK_ERROR      1084    /*!< Read of the data Tx reg     */
+                         /* didn't return value written */
+#define XST_IIC_DRR_READBACK_ERROR      1085    /*!< Read of the data Receive reg */
+                         /* didn't return value written */
+#define XST_IIC_ADR_READBACK_ERROR      1086    /*!< Read of the data Tx reg     */
+                         /* didn't return value written */
+#define XST_IIC_TBA_READBACK_ERROR      1087    /*!< Read of the 10 bit addr reg */
+                         /* didn't return written value */
+#define XST_IIC_NOT_SLAVE               1088    /*!< The device isn't a slave    */
+#define XST_IIC_ARB_LOST                 1089     /*!< Arbitration lost for master    */
 /** @} */
 /**
 @name ATMC Status Codes 1101 - 1125
@@ -266,10 +266,10 @@ extern "C" {
 */
 /*********************** ATMC statuses 1101 - 1125 ***************************/
 
-#define XST_ATMC_ERROR_COUNT_MAX    1101L	/*!< the error counters in the ATM
-						   controller hit the max value
-						   which requires the statistics
-						   to be cleared */
+#define XST_ATMC_ERROR_COUNT_MAX    1101L    /*!< the error counters in the ATM
+                           controller hit the max value
+                           which requires the statistics
+                           to be cleared */
 /** @} */
 /**
 @name Flash Status Codes 1126 - 1150
@@ -277,31 +277,31 @@ extern "C" {
 */
 /*********************** Flash statuses 1126 - 1150 **************************/
 
-#define XST_FLASH_BUSY                1126L	/*!< Flash is erasing or programming
-						 */
-#define XST_FLASH_READY               1127L	/*!< Flash is ready for commands */
-#define XST_FLASH_ERROR               1128L	/*!< Flash had detected an internal
-						   error. Use XFlash_DeviceControl
-						   to retrieve device specific codes
-						 */
-#define XST_FLASH_ERASE_SUSPENDED     1129L	/*!< Flash is in suspended erase state
-						 */
-#define XST_FLASH_WRITE_SUSPENDED     1130L	/*!< Flash is in suspended write state
-						 */
-#define XST_FLASH_PART_NOT_SUPPORTED  1131L	/*!< Flash type not supported by
-						   driver */
-#define XST_FLASH_NOT_SUPPORTED       1132L	/*!< Operation not supported */
-#define XST_FLASH_TOO_MANY_REGIONS    1133L	/*!< Too many erase regions */
-#define XST_FLASH_TIMEOUT_ERROR       1134L	/*!< Programming or erase operation
-						   aborted due to a timeout */
-#define XST_FLASH_ADDRESS_ERROR       1135L	/*!< Accessed flash outside its
-						   addressible range */
-#define XST_FLASH_ALIGNMENT_ERROR     1136L	/*!< Write alignment error */
-#define XST_FLASH_BLOCKING_CALL_ERROR 1137L	/*!< Couldn't return immediately from
-						   write/erase function with
-						   XFL_NON_BLOCKING_WRITE/ERASE
-						   option cleared */
-#define XST_FLASH_CFI_QUERY_ERROR     1138L	/*!< Failed to query the device */
+#define XST_FLASH_BUSY                1126L    /*!< Flash is erasing or programming
+                         */
+#define XST_FLASH_READY               1127L    /*!< Flash is ready for commands */
+#define XST_FLASH_ERROR               1128L    /*!< Flash had detected an internal
+                           error. Use XFlash_DeviceControl
+                           to retrieve device specific codes
+                         */
+#define XST_FLASH_ERASE_SUSPENDED     1129L    /*!< Flash is in suspended erase state
+                         */
+#define XST_FLASH_WRITE_SUSPENDED     1130L    /*!< Flash is in suspended write state
+                         */
+#define XST_FLASH_PART_NOT_SUPPORTED  1131L    /*!< Flash type not supported by
+                           driver */
+#define XST_FLASH_NOT_SUPPORTED       1132L    /*!< Operation not supported */
+#define XST_FLASH_TOO_MANY_REGIONS    1133L    /*!< Too many erase regions */
+#define XST_FLASH_TIMEOUT_ERROR       1134L    /*!< Programming or erase operation
+                           aborted due to a timeout */
+#define XST_FLASH_ADDRESS_ERROR       1135L    /*!< Accessed flash outside its
+                           addressible range */
+#define XST_FLASH_ALIGNMENT_ERROR     1136L    /*!< Write alignment error */
+#define XST_FLASH_BLOCKING_CALL_ERROR 1137L    /*!< Couldn't return immediately from
+                           write/erase function with
+                           XFL_NON_BLOCKING_WRITE/ERASE
+                           option cleared */
+#define XST_FLASH_CFI_QUERY_ERROR     1138L    /*!< Failed to query the device */
 /** @} */
 /**
 @name SPI Status Codes 1151 - 1175
@@ -309,23 +309,23 @@ extern "C" {
 */
 /*********************** SPI statuses 1151 - 1175 ****************************/
 
-#define XST_SPI_MODE_FAULT          1151	/*!< master was selected as slave */
-#define XST_SPI_TRANSFER_DONE       1152	/*!< data transfer is complete */
-#define XST_SPI_TRANSMIT_UNDERRUN   1153	/*!< slave underruns transmit register */
-#define XST_SPI_RECEIVE_OVERRUN     1154	/*!< device overruns receive register */
-#define XST_SPI_NO_SLAVE            1155	/*!< no slave has been selected yet */
-#define XST_SPI_TOO_MANY_SLAVES     1156	/*!< more than one slave is being
-						 * selected */
-#define XST_SPI_NOT_MASTER          1157	/*!< operation is valid only as master */
-#define XST_SPI_SLAVE_ONLY          1158	/*!< device is configured as slave-only
-						 */
-#define XST_SPI_SLAVE_MODE_FAULT    1159	/*!< slave was selected while disabled */
-#define XST_SPI_SLAVE_MODE          1160	/*!< device has been addressed as slave */
-#define XST_SPI_RECEIVE_NOT_EMPTY   1161	/*!< device received data in slave mode */
+#define XST_SPI_MODE_FAULT          1151    /*!< master was selected as slave */
+#define XST_SPI_TRANSFER_DONE       1152    /*!< data transfer is complete */
+#define XST_SPI_TRANSMIT_UNDERRUN   1153    /*!< slave underruns transmit register */
+#define XST_SPI_RECEIVE_OVERRUN     1154    /*!< device overruns receive register */
+#define XST_SPI_NO_SLAVE            1155    /*!< no slave has been selected yet */
+#define XST_SPI_TOO_MANY_SLAVES     1156    /*!< more than one slave is being
+                         * selected */
+#define XST_SPI_NOT_MASTER          1157    /*!< operation is valid only as master */
+#define XST_SPI_SLAVE_ONLY          1158    /*!< device is configured as slave-only
+                         */
+#define XST_SPI_SLAVE_MODE_FAULT    1159    /*!< slave was selected while disabled */
+#define XST_SPI_SLAVE_MODE          1160    /*!< device has been addressed as slave */
+#define XST_SPI_RECEIVE_NOT_EMPTY   1161    /*!< device received data in slave mode */
 
-#define XST_SPI_COMMAND_ERROR       1162	/*!< unrecognised command - qspi only */
+#define XST_SPI_COMMAND_ERROR       1162    /*!< unrecognised command - qspi only */
 #define XST_SPI_POLL_DONE           1163        /*!< controller completed polling the
-						   device for status */
+                           device for status */
 /** @} */
 /**
 @name OPB Arbiter Status Codes 1176 - 1200
@@ -333,23 +333,23 @@ extern "C" {
 */
 /********************** OPB Arbiter statuses 1176 - 1200 *********************/
 
-#define XST_OPBARB_INVALID_PRIORITY  1176	/*!< the priority registers have either
-						 * one master assigned to two or more
-						 * priorities, or one master not
-						 * assigned to any priority
-						 */
-#define XST_OPBARB_NOT_SUSPENDED     1177	/*!< an attempt was made to modify the
-						 * priority levels without first
-						 * suspending the use of priority
-						 * levels
-						 */
-#define XST_OPBARB_PARK_NOT_ENABLED  1178	/*!< bus parking by id was enabled but
-						 * bus parking was not enabled
-						 */
-#define XST_OPBARB_NOT_FIXED_PRIORITY 1179	/*!< the arbiter must be in fixed
-						 * priority mode to allow the
-						 * priorities to be changed
-						 */
+#define XST_OPBARB_INVALID_PRIORITY  1176    /*!< the priority registers have either
+                         * one master assigned to two or more
+                         * priorities, or one master not
+                         * assigned to any priority
+                         */
+#define XST_OPBARB_NOT_SUSPENDED     1177    /*!< an attempt was made to modify the
+                         * priority levels without first
+                         * suspending the use of priority
+                         * levels
+                         */
+#define XST_OPBARB_PARK_NOT_ENABLED  1178    /*!< bus parking by id was enabled but
+                         * bus parking was not enabled
+                         */
+#define XST_OPBARB_NOT_FIXED_PRIORITY 1179    /*!< the arbiter must be in fixed
+                         * priority mode to allow the
+                         * priorities to be changed
+                         */
 /** @} */
 /**
 @name INTC Status Codes 1201 - 1225
@@ -357,8 +357,8 @@ extern "C" {
 */
 /************************ Intc statuses 1201 - 1225 **************************/
 
-#define XST_INTC_FAIL_SELFTEST      1201	/*!< self test failed */
-#define XST_INTC_CONNECT_ERROR      1202	/*!< interrupt already in use */
+#define XST_INTC_FAIL_SELFTEST      1201    /*!< self test failed */
+#define XST_INTC_CONNECT_ERROR      1202    /*!< interrupt already in use */
 /** @} */
 /**
 @name TmrCtr Status Codes 1226 - 1250
@@ -366,7 +366,7 @@ extern "C" {
 */
 /********************** TmrCtr statuses 1226 - 1250 **************************/
 
-#define XST_TMRCTR_TIMER_FAILED     1226	/*!< self test failed */
+#define XST_TMRCTR_TIMER_FAILED     1226    /*!< self test failed */
 /** @} */
 /**
 @name WdtTb Status Codes 1251 - 1275
@@ -406,7 +406,7 @@ extern "C" {
 */
 /********************** SysAce statuses 1351 - 1360 **************************/
 
-#define XST_SYSACE_NO_LOCK          1351L	/*!< No MPU lock has been granted */
+#define XST_SYSACE_NO_LOCK          1351L    /*!< No MPU lock has been granted */
 /** @} */
 /**
 @name PCI Bridge Status Codes 1361 - 1375
@@ -422,10 +422,10 @@ extern "C" {
 */
 /********************** FlexRay constants 1400 - 1409 *************************/
 
-#define XST_FR_TX_ERROR		    1400
-#define XST_FR_TX_BUSY		    1401
-#define XST_FR_BUF_LOCKED	    1402
-#define XST_FR_NO_BUF		    1403
+#define XST_FR_TX_ERROR            1400
+#define XST_FR_TX_BUSY            1401
+#define XST_FR_BUF_LOCKED        1402
+#define XST_FR_NO_BUF            1403
 /** @} */
 /**
 @name USB constants 1410 - 1420
@@ -434,10 +434,10 @@ extern "C" {
 /****************** USB constants 1410 - 1420  *******************************/
 
 #define XST_USB_ALREADY_CONFIGURED    1410
-#define XST_USB_BUF_ALIGN_ERROR	    1411
+#define XST_USB_BUF_ALIGN_ERROR        1411
 #define XST_USB_NO_DESC_AVAILABLE    1412
-#define XST_USB_BUF_TOO_BIG	    1413
-#define XST_USB_NO_BUF		    1414
+#define XST_USB_BUF_TOO_BIG        1413
+#define XST_USB_NO_BUF            1414
 /** @} */
 /**
 @name HWICAP constants 1421 - 1429
@@ -445,7 +445,7 @@ extern "C" {
 */
 /****************** HWICAP constants 1421 - 1429  *****************************/
 
-#define XST_HWICAP_WRITE_DONE	    1421
+#define XST_HWICAP_WRITE_DONE        1421
 
 /** @} */
 /**
@@ -454,7 +454,7 @@ extern "C" {
 */
 /****************** AXI VDMA constants 1430 - 1440  *****************************/
 
-#define XST_VDMA_MISMATCH_ERROR	    1430
+#define XST_VDMA_MISMATCH_ERROR        1430
 /** @} */
 /**
 @name NAND Flash Status Codes 1441 - 1459
@@ -462,36 +462,36 @@ extern "C" {
 */
 /*********************** NAND Flash statuses 1441 - 1459  *********************/
 
-#define XST_NAND_BUSY		    1441L	/*!< Flash is erasing or
-						 * programming
-						 */
-#define XST_NAND_READY		    1442L	/*!< Flash is ready for commands
-						 */
-#define XST_NAND_ERROR		    1443L	/*!< Flash had detected an
-						 * internal error.
-						 */
-#define XST_NAND_PART_NOT_SUPPORTED    1444L	/*!< Flash type not supported by
-						 * driver
-						 */
-#define XST_NAND_OPT_NOT_SUPPORTED    1445L	/*!< Operation not supported
-						 */
-#define XST_NAND_TIMEOUT_ERROR	    1446L	/*!< Programming or erase
-						 * operation aborted due to a
-						 * timeout
-						 */
-#define XST_NAND_ADDRESS_ERROR	    1447L	/*!< Accessed flash outside its
-						 * addressible range
-						 */
-#define XST_NAND_ALIGNMENT_ERROR    1448L	/*!< Write alignment error
-						 */
-#define XST_NAND_PARAM_PAGE_ERROR    1449L	/*!< Failed to read parameter
-						 * page of the device
-						 */
-#define XST_NAND_CACHE_ERROR	    1450L	/*!< Flash page buffer error
-						 */
+#define XST_NAND_BUSY            1441L    /*!< Flash is erasing or
+                         * programming
+                         */
+#define XST_NAND_READY            1442L    /*!< Flash is ready for commands
+                         */
+#define XST_NAND_ERROR            1443L    /*!< Flash had detected an
+                         * internal error.
+                         */
+#define XST_NAND_PART_NOT_SUPPORTED    1444L    /*!< Flash type not supported by
+                         * driver
+                         */
+#define XST_NAND_OPT_NOT_SUPPORTED    1445L    /*!< Operation not supported
+                         */
+#define XST_NAND_TIMEOUT_ERROR        1446L    /*!< Programming or erase
+                         * operation aborted due to a
+                         * timeout
+                         */
+#define XST_NAND_ADDRESS_ERROR        1447L    /*!< Accessed flash outside its
+                         * addressible range
+                         */
+#define XST_NAND_ALIGNMENT_ERROR    1448L    /*!< Write alignment error
+                         */
+#define XST_NAND_PARAM_PAGE_ERROR    1449L    /*!< Failed to read parameter
+                         * page of the device
+                         */
+#define XST_NAND_CACHE_ERROR        1450L    /*!< Flash page buffer error
+                         */
 
-#define XST_NAND_WRITE_PROTECTED    1451L	/*!< Flash is write protected
-						 */
+#define XST_NAND_WRITE_PROTECTED    1451L    /*!< Flash is write protected
+                         */
 /** @} */
 
 /**************************** Type Definitions *******************************/
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/drv_sdcard.c b/bsp/zynqmp-r5-axu4ev/drivers/drv_sdcard.c
index b0d6f375c8..5aa866b8bf 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/drv_sdcard.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/drv_sdcard.c
@@ -184,9 +184,9 @@ static DSTATUS disk_initialize(
     if (CardDetect)
     {
         /*
-			 * Card detection check
-			 * If the HC detects the No Card State, power will be cleared
-			 */
+             * Card detection check
+             * If the HC detects the No Card State, power will be cleared
+             */
         while (!((XSDPS_PSR_CARD_DPL_MASK |
                   XSDPS_PSR_CARD_STABLE_MASK |
                   XSDPS_PSR_CARD_INSRT_MASK) ==
@@ -198,8 +198,8 @@ static DSTATUS disk_initialize(
     }
 
     /*
-	 * Initialize the host controller
-	 */
+     * Initialize the host controller
+     */
     SdConfig = XSdPs_LookupConfig((u16)pdrv);
     if (NULL == SdConfig)
     {
@@ -223,9 +223,9 @@ static DSTATUS disk_initialize(
     }
 
     /*
-	 * Disk is initialized.
-	 * Store the same in Stat.
-	 */
+     * Disk is initialized.
+     * Store the same in Stat.
+     */
     s &= (~STA_NOINIT);
 
     Stat[pdrv] = s;
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/drv_uart.c b/bsp/zynqmp-r5-axu4ev/drivers/drv_uart.c
index 1de379e5ae..84656bcc46 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/drv_uart.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/drv_uart.c
@@ -21,7 +21,7 @@
 
 #define XUARTPS_MAX_RATE    921600U
 #define XUARTPS_MIN_RATE    110U
-#define XUARTPS_MAX_BAUD_ERROR_RATE     3U	/* max % error allowed */
+#define XUARTPS_MAX_BAUD_ERROR_RATE     3U    /* max % error allowed */
 
 #define ZynqMP_UART_INT_DISABLE(UART)       \
     (UART->IER &= ~(UART_IXR_RXOVR | UART_IXR_RXFULL))
@@ -92,12 +92,12 @@ static void rt_hw_uart_isr(int irqno, void *param)
 
 static rt_err_t XUartPsSetBandRate(struct hw_uart_device *pdev, rt_uint32_t targetBandRate)
 {
-    rt_uint32_t IterBAUDDIV;	/* Iterator for available baud divisor values */
-    rt_uint32_t BRGR_Value;		/* Calculated value for baud rate generator */
-    rt_uint32_t CalcBaudRate;	/* Calculated baud rate */
-    rt_uint32_t BaudError;		/* Diff between calculated and requested baud rate */
-    rt_uint32_t Best_BRGR = 0U;	/* Best value for baud rate generator */
-    rt_uint8_t Best_BAUDDIV = 0U;	/* Best value for baud divisor */
+    rt_uint32_t IterBAUDDIV;    /* Iterator for available baud divisor values */
+    rt_uint32_t BRGR_Value;        /* Calculated value for baud rate generator */
+    rt_uint32_t CalcBaudRate;    /* Calculated baud rate */
+    rt_uint32_t BaudError;        /* Diff between calculated and requested baud rate */
+    rt_uint32_t Best_BRGR = 0U;    /* Best value for baud rate generator */
+    rt_uint8_t Best_BAUDDIV = 0U;    /* Best value for baud divisor */
     rt_uint32_t Best_Error = 0xFFFFFFFFU;
     rt_uint32_t PercentError;
     rt_uint32_t ModeReg;
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h b/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h
index bd8fb38eb4..3192942b57 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h
@@ -9,8 +9,8 @@
 #define __REG8(x)  (*((volatile rt_uint8_t *)(x)))
 
 #define ZynqMP_CRL_APB_BASEADDR        XPAR_PSU_CRL_APB_S_AXI_BASEADDR
-#define ZynqMP_CRL_APB_IOPLL_CTRL	   0x020
-#define ZynqMP_CRL_APB_IOPLL_CFG	   0x024
+#define ZynqMP_CRL_APB_IOPLL_CTRL       0x020
+#define ZynqMP_CRL_APB_IOPLL_CFG       0x024
 #define ZynqMP_CRL_APB_UART0_REF_CTRL  0x074
 #define ZynqMP_CRL_APB_UART1_REF_CTRL  0x078
 #define ZynqMP_CRL_APB_LPD_LSBUS_CTRL  0x0AC
diff --git a/bsp/zynqmp-r5-axu4ev/rtconfig.py b/bsp/zynqmp-r5-axu4ev/rtconfig.py
index e772c660d3..c16be9ba33 100644
--- a/bsp/zynqmp-r5-axu4ev/rtconfig.py
+++ b/bsp/zynqmp-r5-axu4ev/rtconfig.py
@@ -9,8 +9,8 @@ if os.getenv('RTT_CC'):
     CROSS_TOOL = os.getenv('RTT_CC')
 
 # only support GNU GCC compiler
-PLATFORM 	= 'gcc'
-EXEC_PATH 	= '/opt/arm-none-eabi-gcc'
+PLATFORM     = 'gcc'
+EXEC_PATH     = '/opt/arm-none-eabi-gcc'
 
 if os.getenv('RTT_EXEC_PATH'):
     EXEC_PATH = os.getenv('RTT_EXEC_PATH')

From 41d55a4d474464090df9c4e19cafb9fd176c9463 Mon Sep 17 00:00:00 2001
From: Wang-Huachen 
Date: Fri, 14 May 2021 14:50:06 +0800
Subject: [PATCH 069/255] format files in zynqmp-r5 libcpu

---
 libcpu/arm/zynqmp-r5/xil_mpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcpu/arm/zynqmp-r5/xil_mpu.c b/libcpu/arm/zynqmp-r5/xil_mpu.c
index 7115bbb0a6..9ab94a488b 100644
--- a/libcpu/arm/zynqmp-r5/xil_mpu.c
+++ b/libcpu/arm/zynqmp-r5/xil_mpu.c
@@ -64,7 +64,7 @@
 #include "xstatus.h"
 
 #include 
-#define DBG_TAG           "xil_mpu"  
+#define DBG_TAG           "xil_mpu"
 #define DBG_LVL           DBG_INFO
 #include 
 

From 42ce237dc969fa3e6c5f891e87e925f42d5d38ea Mon Sep 17 00:00:00 2001
From: zhouji <956133287@qq.com>
Date: Sat, 1 May 2021 16:06:02 +0800
Subject: [PATCH 070/255] =?UTF-8?q?[update]=20=E6=95=B4=E7=90=86cortex-a?=
 =?UTF-8?q?=20aarch32=E5=90=AF=E5=8A=A8=E4=BB=A3=E7=A0=81=201.=20=E5=8E=BB?=
 =?UTF-8?q?=E9=99=A4start=5Fgcc.s=E4=B8=ADset=5Fsecondary=5Fcpu=5Fboot=5Fa?=
 =?UTF-8?q?ddress=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=BF=99=E9=83=A8=E5=88=86?=
 =?UTF-8?q?=E6=8F=90=E5=8F=96=E5=88=B0qemu-vexpress-a9=20bsp=E4=B8=AD?=
 =?UTF-8?q?=E3=80=82=202.=20=E7=A7=BB=E5=8A=A8cpu.c=E4=B8=ADrt=5Fhw=5Fcpu?=
 =?UTF-8?q?=5Fid=E5=87=BD=E6=95=B0=E5=88=B0cp15=5Fgcc.s=EF=BC=8C=E4=BD=BF?=
 =?UTF-8?q?=E7=94=A8=E6=B1=87=E7=BC=96=E5=AE=9E=E7=8E=B0=EF=BC=8C=E9=87=87?=
 =?UTF-8?q?=E7=94=A8wake=E5=B1=9E=E6=80=A7=EF=BC=8C=E6=96=B9=E4=BE=BFbsp?=
 =?UTF-8?q?=E6=A0=B9=E6=8D=AEcpu=E7=89=B9=E6=80=A7=E8=8E=B7=E5=8F=96CPU=20?=
 =?UTF-8?q?ID=EF=BC=88=E5=A4=9Acpu=E9=9B=86=E7=BE=A4=E4=B8=AD=EF=BC=8C?=
 =?UTF-8?q?=E4=B8=8D=E5=90=8C=E5=8E=82=E5=AE=B6=E4=BD=BF=E7=94=A8=E7=BB=84?=
 =?UTF-8?q?=E5=90=88=E4=B8=8D=E4=B8=80=E6=A0=B7=EF=BC=89.=203.=20=E6=95=B4?=
 =?UTF-8?q?=E7=90=86start=5Fgcc.s=20=E9=80=82=E5=BA=94=E5=A4=9A=E6=A0=B8?=
 =?UTF-8?q?=E5=90=AF=E5=8A=A8=EF=BC=8C=E5=8E=9F=E6=9D=A5=E7=9A=84=E4=BB=A3?=
 =?UTF-8?q?=E7=A0=81=E5=8F=AA=E8=80=83=E8=99=91=E5=88=B0=E5=8F=8C=E6=A0=B8?=
 =?UTF-8?q?=E7=9A=84=E6=83=85=E5=86=B5=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 bsp/qemu-vexpress-a9/drivers/secondary_cpu.c |  10 +-
 libcpu/arm/cortex-a/cp15.h                   |   3 +-
 libcpu/arm/cortex-a/cp15_gcc.S               |   8 +-
 libcpu/arm/cortex-a/cpu.c                    |  11 --
 libcpu/arm/cortex-a/start_gcc.S              | 119 +++++++++++++------
 5 files changed, 97 insertions(+), 54 deletions(-)

diff --git a/bsp/qemu-vexpress-a9/drivers/secondary_cpu.c b/bsp/qemu-vexpress-a9/drivers/secondary_cpu.c
index 3b0428859f..c0fcb30aa4 100644
--- a/bsp/qemu-vexpress-a9/drivers/secondary_cpu.c
+++ b/bsp/qemu-vexpress-a9/drivers/secondary_cpu.c
@@ -26,10 +26,16 @@ static void rt_hw_timer2_isr(int vector, void *param)
     timer_clear_pending(0);
 }
 
+void set_secondary_cpu_boot_address(void)
+{
+    extern void secondary_cpu_start(void);
+    uint32_t *boot_address = (uint32_t *)0x10000030;
+    *(boot_address + 1) = ~0ul;
+    *boot_address = (uint32_t )&secondary_cpu_start;
+}
+
 void rt_hw_secondary_cpu_up(void)
 {
-    extern void set_secondary_cpu_boot_address(void);
-
     set_secondary_cpu_boot_address();
     __asm__ volatile ("dsb":::"memory");
     rt_hw_ipi_send(0, 1 << 1);
diff --git a/libcpu/arm/cortex-a/cp15.h b/libcpu/arm/cortex-a/cp15.h
index 6896fd9f71..2bf91ac5ad 100644
--- a/libcpu/arm/cortex-a/cp15.h
+++ b/libcpu/arm/cortex-a/cp15.h
@@ -15,8 +15,7 @@
 #define __get_cp64(cp, op1, Rt, CRm) __asm__ volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm  : "=r" (Rt) : : "memory" )
 #define __set_cp64(cp, op1, Rt, CRm) __asm__ volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm  : : "r" (Rt) : "memory" )
 
-unsigned long rt_cpu_get_smp_id(void);
-
+int rt_hw_cpu_id(void);
 void rt_cpu_mmu_disable(void);
 void rt_cpu_mmu_enable(void);
 void rt_cpu_tlb_set(volatile unsigned long*);
diff --git a/libcpu/arm/cortex-a/cp15_gcc.S b/libcpu/arm/cortex-a/cp15_gcc.S
index dd2436ffee..983ae522ef 100644
--- a/libcpu/arm/cortex-a/cp15_gcc.S
+++ b/libcpu/arm/cortex-a/cp15_gcc.S
@@ -8,9 +8,11 @@
  * 2013-07-05     Bernard      the first version
  */
 
-.globl rt_cpu_get_smp_id
-rt_cpu_get_smp_id:
-    mrc     p15, #0, r0, c0, c0, #5
+.weak rt_hw_cpu_id
+rt_hw_cpu_id:
+    mrc     p15, #0, r0, c0, c0, #5         @ read multiprocessor affinity register
+    ldr     r1, =0xFFFF03                   @ Affinity mask off, leaving CPU ID field, [0:1]CPU ID, [8:15]Cluster ID Aff1, [16:23]Cluster ID Aff2
+    and     r0, r0, r1
     bx      lr
 
 .globl rt_cpu_vector_set_base
diff --git a/libcpu/arm/cortex-a/cpu.c b/libcpu/arm/cortex-a/cpu.c
index 9555e01e9c..7367bddd9f 100644
--- a/libcpu/arm/cortex-a/cpu.c
+++ b/libcpu/arm/cortex-a/cpu.c
@@ -15,17 +15,6 @@
 
 #ifdef RT_USING_SMP
 
-int rt_hw_cpu_id(void)
-{
-    int cpu_id;
-    __asm__ volatile (
-            "mrc p15, 0, %0, c0, c0, 5"
-            :"=r"(cpu_id)
-            );
-    cpu_id &= 0xf;
-    return cpu_id;
-};
-
 void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock)
 {
     lock->slock = 0;
diff --git a/libcpu/arm/cortex-a/start_gcc.S b/libcpu/arm/cortex-a/start_gcc.S
index 2e99db7218..bd4bc84604 100644
--- a/libcpu/arm/cortex-a/start_gcc.S
+++ b/libcpu/arm/cortex-a/start_gcc.S
@@ -22,20 +22,26 @@
 .equ I_Bit,           0x80            @ when I bit is set, IRQ is disabled
 .equ F_Bit,           0x40            @ when F bit is set, FIQ is disabled
 
-#ifdef RT_USING_FPU
 .equ UND_Stack_Size,     0x00000400
-#else
-.equ UND_Stack_Size,     0x00000000
-#endif
 .equ SVC_Stack_Size,     0x00000400
-.equ ABT_Stack_Size,     0x00000000
+.equ ABT_Stack_Size,     0x00000400
 .equ RT_FIQ_STACK_PGSZ,  0x00000000
 .equ RT_IRQ_STACK_PGSZ,  0x00000800
 .equ USR_Stack_Size,     0x00000400
 
+.equ SUB_UND_Stack_Size,     0x00000400
+.equ SUB_SVC_Stack_Size,     0x00000400
+.equ SUB_ABT_Stack_Size,     0x00000400
+.equ SUB_RT_FIQ_STACK_PGSZ,  0x00000000
+.equ SUB_RT_IRQ_STACK_PGSZ,  0x00000400
+.equ SUB_USR_Stack_Size,     0x00000400
+
 #define ISR_Stack_Size  (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
                  RT_FIQ_STACK_PGSZ + RT_IRQ_STACK_PGSZ)
 
+#define SUB_ISR_Stack_Size  (SUB_UND_Stack_Size + SUB_SVC_Stack_Size + SUB_ABT_Stack_Size + \
+                 SUB_RT_FIQ_STACK_PGSZ + SUB_RT_IRQ_STACK_PGSZ)
+
 .section .data.share.isr
 /* stack */
 .globl stack_start
@@ -82,9 +88,40 @@ continue:
 
     /* disable the data alignment check */
     mrc p15, 0, r1, c1, c0, 0
-    bic r1, #(1<<1)
+    bic r1, #(1<<0)             /* Disable MMU */
+    bic r1, #(1<<1)             /* Disable Alignment fault checking */
+    bic r1, #(1<<2)             /* Disable data cache */
+    bic r1, #(1<<11)            /* Disable program flow prediction */
+    bic r1, #(1<<12)            /* Disable instruction cache */
+    bic r1, #(3<<19)            /* bit[20:19] must be zero */
     mcr p15, 0, r1, c1, c0, 0
 
+    @ get cpu id, and subtract the offset from the stacks base address
+    bl rt_hw_cpu_id
+    mov r5, r0
+
+    cmp     r5, #0              @ cpu id == 0
+    beq     normal_setup
+
+    @ cpu id > 0, stop or wait
+#ifdef RT_SMP_AUTO_BOOT
+    ldr r0, =secondary_cpu_entry
+    mov r1, #0
+    str r1, [r0] /* clean secondary_cpu_entry */
+#endif /* RT_SMP_AUTO_BOOT */
+
+secondary_loop:
+    @ cpu core 1 goes into sleep until core 0 wakeup it
+    wfe
+#ifdef RT_SMP_AUTO_BOOT
+    ldr r1, =secondary_cpu_entry
+    ldr r0, [r1]
+    cmp r0, #0
+    blxne r0 /* if(secondary_cpu_entry) secondary_cpu_entry(); */
+#endif /* RT_SMP_AUTO_BOOT */
+    b secondary_loop
+
+normal_setup:
     /* setup stack */
     bl      stack_setup
 
@@ -105,6 +142,11 @@ bss_loop:
     mcr p15, 0, r1, c1, c0, 1 //enable smp
 #endif
 
+    /* enable branch prediction */
+    mrc p15, 0, r0, c1, c0, 0
+    orr     r0, r0, #(1<<11)
+    mcr p15, 0, r0, c1, c0, 0
+
     /* initialize the mmu table and enable mmu */
     ldr r0, =platform_mem_desc
     ldr r1, =platform_mem_desc_size
@@ -137,6 +179,7 @@ stack_setup:
 
     @  Set the startup stack for svc
     mov     sp, r0
+    sub     r0, r0, #SVC_Stack_Size
 
     @  Enter Undefined Instruction Mode and set its Stack Pointer
     msr     cpsr_c, #Mode_UND|I_Bit|F_Bit
@@ -378,16 +421,6 @@ vector_resv:
     b       .
 
 #ifdef RT_USING_SMP
-.global set_secondary_cpu_boot_address
-set_secondary_cpu_boot_address:
-    ldr r0, =secondary_cpu_start
-
-    mvn r1, #0 //0xffffffff
-    ldr r2, =0x10000034
-    str r1, [r2]
-    str r0, [r2, #-4]
-    mov pc, lr
-
 .global secondary_cpu_start
 secondary_cpu_start:
 
@@ -405,38 +438,52 @@ secondary_cpu_start:
     bic r0, #(1<<13)
     mcr p15, 0, r0, c1, c0, 0
 
-#ifdef RT_USING_FPU
-    cps #Mode_UND
-    ldr sp, =und_stack_2_limit
-#endif
+    /* enable branch prediction */
+    mrc p15, 0, r0, c1, c0, 0
+    orr     r0, r0, #(1<<11)
+    mcr p15, 0, r0, c1, c0, 0
 
-    cps #Mode_IRQ
-    ldr sp, =irq_stack_2_limit
+    @ get cpu id, and subtract the offset from the stacks base address
+    bl rt_hw_cpu_id
+    sub r5, r0, #1
 
-    cps #Mode_FIQ
-    ldr sp, =irq_stack_2_limit
+    ldr r0, =SUB_ISR_Stack_Size
+    mul r0, r0, r5                      @r0 = SUB_ISR_Stack_Size * (cpuid - 1)
+    ldr r1, =sub_stack_top
+    sub r0, r1, r0                      @r0 = sub_stack_top - (SUB_ISR_Stack_Size * (cpuid - 1))
+
+    cps #Mode_SVC
+    mov     sp, r0
+    sub     r0, r0, #SUB_SVC_Stack_Size
+
+    cps #Mode_UND
+    mov     sp, r0
+    sub     r0, r0, #SUB_UND_Stack_Size
+
+    cps #Mode_ABT
+    mov     sp, r0
+    sub     r0, r0, #SUB_ABT_Stack_Size
+
+    cps #Mode_FIQ
+    mov     sp, r0
+    sub     r0, r0, #SUB_RT_FIQ_STACK_PGSZ
+
+    cps #Mode_IRQ
+    mov     sp, r0
+    sub     r0, r0, #SUB_RT_IRQ_STACK_PGSZ
 
     cps #Mode_SVC
-    ldr sp, =svc_stack_2_limit
 
     /* initialize the mmu table and enable mmu */
     bl rt_hw_mmu_init
 
     b secondary_cpu_c_start
-#endif
 
 .bss
 .align 2   //align to  2~2=4
-svc_stack_2:
-    .space (1 << 10)
-svc_stack_2_limit:
 
-irq_stack_2:
-    .space (1 << 10)
-irq_stack_2_limit:
+sub_stack_start:
+    .space (SUB_ISR_Stack_Size * (RT_CPUS_NR-1))
+sub_stack_top:
 
-#ifdef RT_USING_FPU
-und_stack_2:
-    .space (1 << 10)
-und_stack_2_limit:
 #endif

From 1523e4680d6b17a788314cb38386fd391daad819 Mon Sep 17 00:00:00 2001
From: zhouji <956133287@qq.com>
Date: Sat, 1 May 2021 19:15:37 +0800
Subject: [PATCH 071/255] =?UTF-8?q?[add]=20=E6=B7=BB=E5=8A=A0gicv3?=
 =?UTF-8?q?=E4=B8=AD=E6=96=AD=E6=8E=A7=E5=88=B6=E5=99=A8=E4=BB=A3=E7=A0=81?=
 =?UTF-8?q?=EF=BC=8C=E6=9B=B4=E6=96=B0menuconfig=E9=85=8D=E7=BD=AE?=
 =?UTF-8?q?=E9=80=89=E9=A1=B9=E4=B8=8Eutest=E7=9A=84config.h?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 examples/utest/configs/utest_self/config.h |   1 +
 libcpu/Kconfig                             |  20 +
 libcpu/arm/cortex-a/SConscript             |  23 +-
 libcpu/arm/cortex-a/gicv3.c                | 708 +++++++++++++++++++++
 libcpu/arm/cortex-a/gicv3.h                | 194 ++++++
 libcpu/arm/cortex-a/interrupt.c            |  40 +-
 6 files changed, 983 insertions(+), 3 deletions(-)
 create mode 100644 libcpu/arm/cortex-a/gicv3.c
 create mode 100644 libcpu/arm/cortex-a/gicv3.h

diff --git a/examples/utest/configs/utest_self/config.h b/examples/utest/configs/utest_self/config.h
index 287f0f539d..2080a544b0 100644
--- a/examples/utest/configs/utest_self/config.h
+++ b/examples/utest/configs/utest_self/config.h
@@ -55,6 +55,7 @@
 #define RT_VER_NUM 0x40004
 #define ARCH_ARM
 #define ARCH_ARM_CORTEX_A
+#define RT_USING_GIC_V2
 #define ARCH_ARM_CORTEX_A9
 
 /* RT-Thread Components */
diff --git a/libcpu/Kconfig b/libcpu/Kconfig
index 974c421138..bb54b487c7 100644
--- a/libcpu/Kconfig
+++ b/libcpu/Kconfig
@@ -58,6 +58,26 @@ config ARCH_ARM_CORTEX_A
     bool
     select ARCH_ARM
 
+    if ARCH_ARM_CORTEX_A
+        config RT_SMP_AUTO_BOOT
+            bool
+            default n
+
+        choice
+            prompt "GIC controller selection"
+            default RT_USING_GIC_V2
+
+            config RT_USING_GIC_V2
+                bool " Gic version 2 "
+
+            config RT_USING_GIC_V3
+                bool " Gic version 3 "
+
+            config RT_NO_USING_GIC
+                bool " GIC controller is not used "
+        endchoice
+    endif
+
 config ARCH_ARM_CORTEX_A5
     bool
     select ARCH_ARM_CORTEX_A
diff --git a/libcpu/arm/cortex-a/SConscript b/libcpu/arm/cortex-a/SConscript
index 28af7ba651..a9fe6f0bc9 100644
--- a/libcpu/arm/cortex-a/SConscript
+++ b/libcpu/arm/cortex-a/SConscript
@@ -5,9 +5,27 @@ from building import *
 Import('rtconfig')
 
 cwd     = GetCurrentDir()
-src     = Glob('*.c') + Glob('*.cpp')
+src     = Split('''
+cache.c
+cpu.c
+gtimer.c
+mmu.c
+pmu.c
+stack.c
+
+''')
 CPPPATH = [cwd]
 
+if GetDepend('RT_USING_GIC_V2'):
+    src += ['interrupt.c']
+    src += ['gic.c']
+    src += ['trap.c']
+
+if GetDepend('RT_USING_GIC_V3'):
+    src += ['interrupt.c']
+    src += ['gicv3.c']
+    src += ['trap.c']
+
 if rtconfig.PLATFORM == 'armcc':
     src += Glob('*_rvds.S')
 
@@ -18,6 +36,9 @@ if rtconfig.PLATFORM == 'gcc':
 if rtconfig.PLATFORM == 'iar':
     src += Glob('*_iar.S')
 
+if rtconfig.PLATFORM == 'iar':
+    src += Glob('*_iar.S')
+
 group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH)
 
 Return('group')
diff --git a/libcpu/arm/cortex-a/gicv3.c b/libcpu/arm/cortex-a/gicv3.c
new file mode 100644
index 0000000000..a3fb0e767b
--- /dev/null
+++ b/libcpu/arm/cortex-a/gicv3.c
@@ -0,0 +1,708 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2013-07-20     Bernard      first version
+ * 2014-04-03     Grissiom     many enhancements
+ * 2018-11-22     Jesven       add rt_hw_ipi_send()
+ *                             add rt_hw_ipi_handler_install()
+ */
+
+#include 
+#include 
+
+#include "gicv3.h"
+#include "cp15.h"
+
+#ifndef RT_CPUS_NR
+#define RT_CPUS_NR 1
+#endif
+
+struct arm_gic_v3
+{
+    rt_uint32_t offset;                     /* the first interrupt index in the vector table */
+    rt_uint32_t redist_hw_base[RT_CPUS_NR]; /* the pointer of the gic redistributor */
+    rt_uint32_t dist_hw_base;               /* the base address of the gic distributor */
+    rt_uint32_t cpu_hw_base[RT_CPUS_NR];    /* the base addrees of the gic cpu interface */
+};
+
+/* 'ARM_GIC_MAX_NR' is the number of cores */
+static struct arm_gic_v3 _gic_table[ARM_GIC_MAX_NR];
+static unsigned int _gic_max_irq;
+
+/**
+ * @name: arm_gic_cpumask_to_affval
+ * @msg:
+ * @in param cpu_mask:
+ * @out param cluster_id: aff1 [0:7],aff2 [8:15],aff3 [16:23]
+ * @out param target_list:  Target List. The set of PEs for which SGI interrupts will be generated. Each bit corresponds to the
+ *                          PE within a cluster with an Affinity 0 value equal to the bit number.
+ * @return {rt_uint32_t} 0 is finish , 1 is data valid
+ */
+RT_WEAK rt_uint32_t arm_gic_cpumask_to_affval(rt_uint32_t *cpu_mask, rt_uint32_t *cluster_id, rt_uint32_t *target_list)
+{
+    return 0;
+}
+
+RT_WEAK rt_uint64_t get_main_cpu_affval(void)
+{
+    return 0;
+}
+
+int arm_gic_get_active_irq(rt_uint32_t index)
+{
+    int irq;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    __get_gicv3_reg(ICC_IAR1, irq);
+
+    irq = (irq & 0x1FFFFFF) + _gic_table[index].offset;
+    return irq;
+}
+
+void arm_gic_ack(rt_uint32_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+    RT_ASSERT(irq >= 0U);
+
+    __asm__ volatile("dsb 0xF" ::
+                         : "memory");
+    __set_gicv3_reg(ICC_EOIR1, irq);
+}
+
+void arm_gic_mask(rt_uint32_t index, int irq)
+{
+    rt_uint32_t mask = 1U << (irq % 32U);
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    if (irq < 32U)
+    {
+        rt_int32_t cpu_id = rt_hw_cpu_id();
+        RT_ASSERT((cpu_id) < RT_CPUS_NR);
+        GIC_RDISTSGI_ICENABLER0(_gic_table[index].redist_hw_base[cpu_id]) = mask;
+    }
+    else
+    {
+        GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
+    }
+}
+
+void arm_gic_umask(rt_uint32_t index, int irq)
+{
+    rt_uint32_t mask = 1U << (irq % 32U);
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    if (irq < 32U)
+    {
+        rt_int32_t cpu_id = rt_hw_cpu_id();
+        RT_ASSERT((cpu_id) < RT_CPUS_NR);
+        GIC_RDISTSGI_ISENABLER0(_gic_table[index].redist_hw_base[cpu_id]) = mask;
+    }
+    else
+    {
+        GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
+    }
+}
+
+rt_uint32_t arm_gic_get_pending_irq(rt_uint32_t index, int irq)
+{
+    rt_uint32_t pend;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    if (irq >= 16U)
+    {
+        pend = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
+    }
+    else
+    {
+        /* INTID 0-15 Software Generated Interrupt */
+        pend = (GIC_DIST_SPENDSGI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
+        /* No CPU identification offered */
+        if (pend != 0U)
+        {
+            pend = 1U;
+        }
+        else
+        {
+            pend = 0U;
+        }
+    }
+
+    return (pend);
+}
+
+void arm_gic_set_pending_irq(rt_uint32_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    if (irq >= 16U)
+    {
+        GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) = 1U << (irq % 32U);
+    }
+    else
+    {
+        /* INTID 0-15 Software Generated Interrupt */
+        /* Forward the interrupt to the CPU interface that requested it */
+        GIC_DIST_SOFTINT(_gic_table[index].dist_hw_base) = (irq | 0x02000000U);
+    }
+}
+
+void arm_gic_clear_pending_irq(rt_uint32_t index, int irq)
+{
+    rt_uint32_t mask;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    if (irq >= 16U)
+    {
+        mask = 1U << (irq % 32U);
+        GIC_DIST_PENDING_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
+    }
+    else
+    {
+        mask = 1U << ((irq % 4U) * 8U);
+        GIC_DIST_CPENDSGI(_gic_table[index].dist_hw_base, irq) = mask;
+    }
+}
+
+void arm_gic_set_configuration(rt_uint32_t index, int irq, uint32_t config)
+{
+    rt_uint32_t icfgr;
+    rt_uint32_t shift;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    icfgr = GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq);
+    shift = (irq % 16U) << 1U;
+
+    icfgr &= (~(3U << shift));
+    icfgr |= (config << shift);
+
+    GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) = icfgr;
+}
+
+rt_uint32_t arm_gic_get_configuration(rt_uint32_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    return (GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) >> ((irq % 16U) >> 1U));
+}
+
+void arm_gic_clear_active(rt_uint32_t index, int irq)
+{
+    rt_uint32_t mask = 1U << (irq % 32U);
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    GIC_DIST_ACTIVE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
+}
+
+/* Set up the cpu mask for the specific interrupt */
+void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask)
+{
+    rt_uint32_t old_tgt;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    old_tgt = GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq);
+
+    old_tgt &= ~(0x0FFUL << ((irq % 4U) * 8U));
+    old_tgt |= cpumask << ((irq % 4U) * 8U);
+
+    GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) = old_tgt;
+}
+
+rt_uint32_t arm_gic_get_target_cpu(rt_uint32_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    return (GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
+}
+
+void arm_gic_set_priority(rt_uint32_t index, int irq, rt_uint32_t priority)
+{
+    rt_uint32_t mask;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    if (irq < 32U)
+    {
+        rt_int32_t cpu_id = rt_hw_cpu_id();
+        RT_ASSERT((cpu_id) < RT_CPUS_NR);
+
+        mask = GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq);
+        mask &= ~(0xFFUL << ((irq % 4U) * 8U));
+        mask |= ((priority & 0xFFUL) << ((irq % 4U) * 8U));
+        GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq) = mask;
+    }
+    else
+    {
+        mask = GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq);
+        mask &= ~(0xFFUL << ((irq % 4U) * 8U));
+        mask |= ((priority & 0xFFUL) << ((irq % 4U) * 8U));
+        GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) = mask;
+    }
+}
+
+rt_uint32_t arm_gic_get_priority(rt_uint32_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    if (irq < 32U)
+    {
+        rt_int32_t cpu_id = rt_hw_cpu_id();
+
+        RT_ASSERT((cpu_id) < RT_CPUS_NR);
+        return (GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
+    }
+    else
+    {
+        return (GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
+    }
+}
+
+void arm_gic_set_system_register_enable_mask(rt_uint32_t index, rt_uint32_t value)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    value &= 0xFFUL;
+    /* set priority mask */
+    __set_gicv3_reg(ICC_SRE, value);
+    __asm__ volatile ("isb 0xF"::
+                        :"memory");
+}
+
+rt_uint32_t arm_gic_get_system_register_enable_mask(rt_uint32_t index)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+    rt_uint32_t value;
+
+    __get_gicv3_reg(ICC_SRE, value);
+    return value;
+}
+
+void arm_gic_set_interface_prior_mask(rt_uint32_t index, rt_uint32_t priority)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    priority &= 0xFFUL;
+    /* set priority mask */
+    __set_gicv3_reg(ICC_PMR, priority);
+}
+
+rt_uint32_t arm_gic_get_interface_prior_mask(rt_uint32_t index)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+    rt_uint32_t priority;
+
+    __get_gicv3_reg(ICC_PMR, priority);
+    return priority;
+}
+
+void arm_gic_set_binary_point(rt_uint32_t index, rt_uint32_t binary_point)
+{
+    index = index;
+    binary_point &= 0x7U;
+
+    __set_gicv3_reg(ICC_BPR1, binary_point);
+}
+
+rt_uint32_t arm_gic_get_binary_point(rt_uint32_t index)
+{
+    rt_uint32_t binary_point;
+
+    index = index;
+    __get_gicv3_reg(ICC_BPR1, binary_point);
+    return binary_point;
+}
+
+rt_uint32_t arm_gic_get_irq_status(rt_uint32_t index, int irq)
+{
+    rt_uint32_t pending;
+    rt_uint32_t active;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    active = (GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
+    pending = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
+
+    return ((active << 1U) | pending);
+}
+
+void arm_gic_send_affinity_sgi(rt_uint32_t index, int irq, rt_uint32_t cpu_mask, rt_uint32_t routing_mode)
+{
+    rt_uint64_t sgi_val;
+
+    if (routing_mode)
+    {
+        sgi_val = (1ULL << 40) | ((irq & 0x0FULL) << 24); //Interrupts routed to all PEs in the system, excluding "self".
+        /*  Write the ICC_SGI1R registers */
+        __asm__ volatile("dsb 0xF" ::
+                            : "memory");
+        __set_cp64(15, 0, sgi_val, 12);
+        __asm__ volatile("isb 0xF" ::
+                            : "memory");
+    }
+    else
+    {
+        rt_uint32_t cluster_id, target_list;
+        while (arm_gic_cpumask_to_affval(&cpu_mask, &cluster_id, &target_list))
+        {
+            sgi_val = ((irq & 0x0FULL) << 24 |
+                       target_list |
+                       ((cluster_id >> 8) & 0xFFULL) << GIC_RSGI_AFF1_OFFSET |
+                       ((cluster_id >> 16) & 0xFFULL) << GIC_RSGI_AFF2_OFFSET |
+                       ((cluster_id >> 24) & 0xFFull) << GIC_RSGI_AFF3_OFFSET);
+
+            __asm__ volatile("dsb 0xF" ::
+                                : "memory");
+            __set_cp64(15, 0, sgi_val, 12);
+            __asm__ volatile("isb 0xF" ::
+                                : "memory");
+        }
+    }
+}
+
+rt_uint32_t arm_gic_get_high_pending_irq(rt_uint32_t index)
+{
+    rt_uint32_t irq;
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    index = index;
+    __get_gicv3_reg(ICC_HPPIR1, irq);
+    return irq;
+}
+
+rt_uint32_t arm_gic_get_interface_id(rt_uint32_t index)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    return GIC_CPU_IIDR(_gic_table[index].cpu_hw_base);
+}
+
+void arm_gic_set_group(rt_uint32_t index, int irq, rt_uint32_t group)
+{
+    uint32_t igroupr;
+    uint32_t shift;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+    RT_ASSERT(group <= 1U);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    igroupr = GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq);
+    shift = (irq % 32U);
+    igroupr &= (~(1U << shift));
+    igroupr |= ((group & 0x1U) << shift);
+
+    GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) = igroupr;
+}
+
+rt_uint32_t arm_gic_get_group(rt_uint32_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0U);
+
+    return (GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
+}
+
+static int arm_gicv3_wait_rwp(rt_uint32_t index, rt_uint32_t irq)
+{
+    rt_uint32_t rwp_bit;
+    rt_uint32_t base;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    if (irq < 32u)
+    {
+        rt_int32_t cpu_id = rt_hw_cpu_id();
+
+        RT_ASSERT((cpu_id) < RT_CPUS_NR);
+        base = _gic_table[index].redist_hw_base[cpu_id];
+        rwp_bit = GICR_CTLR_RWP;
+    }
+    else
+    {
+        base = _gic_table[index].dist_hw_base;
+        rwp_bit = GICD_CTLR_RWP;
+    }
+
+    while (__REG32(base) & rwp_bit)
+    {
+        ;
+    }
+
+    return 0;
+}
+
+int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
+{
+    rt_uint64_t cpu0_affval;
+    unsigned int gic_type, i;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    _gic_table[index].dist_hw_base = dist_base;
+    _gic_table[index].offset = irq_start;
+
+    /* Find out how many interrupts are supported. */
+    gic_type = GIC_DIST_TYPE(dist_base);
+    _gic_max_irq = ((gic_type & 0x1fU) + 1U) * 32U;
+
+    /*
+     * The GIC only supports up to 1020 interrupt sources.
+     * Limit this to either the architected maximum, or the
+     * platform maximum.
+     */
+    if (_gic_max_irq > 1020U)
+        _gic_max_irq = 1020U;
+    if (_gic_max_irq > ARM_GIC_NR_IRQS) /* the platform maximum interrupts */
+        _gic_max_irq = ARM_GIC_NR_IRQS;
+
+    GIC_DIST_CTRL(dist_base) = 0x0U;
+    /* Wait for register write pending */
+    arm_gicv3_wait_rwp(0, 32);
+
+    /* Set all global interrupts to be level triggered, active low. */
+    for (i = 32U; i < _gic_max_irq; i += 16U)
+        GIC_DIST_CONFIG(dist_base, i) = 0x0U;
+
+    arm_gicv3_wait_rwp(0, 32);
+
+    cpu0_affval = get_main_cpu_affval();
+    /* Set all global interrupts to this CPU only. */
+    for (i = 32U; i < _gic_max_irq; i++)
+    {
+        GIC_DIST_IROUTER_LOW(dist_base, i) = cpu0_affval;
+        GIC_DIST_IROUTER_HIGH(dist_base, i) = cpu0_affval >> 32;
+    }
+
+    arm_gicv3_wait_rwp(0, 32);
+
+    /* Set priority on spi interrupts. */
+    for (i = 32U; i < _gic_max_irq; i += 4U)
+        GIC_DIST_PRI(dist_base, i) = 0xa0a0a0a0U;
+
+    arm_gicv3_wait_rwp(0, 32);
+    /* Disable all interrupts. */
+    for (i = 0U; i < _gic_max_irq; i += 32U)
+    {
+        GIC_DIST_PENDING_CLEAR(dist_base, i) = 0xffffffffU;
+        GIC_DIST_ENABLE_CLEAR(dist_base, i) = 0xffffffffU;
+    }
+
+    arm_gicv3_wait_rwp(0, 32);
+    /* All interrupts defaults to IGROUP1(IRQ). */
+    for (i = 0U; i < _gic_max_irq; i += 32U)
+        GIC_DIST_IGROUP(dist_base, i) = 0xffffffffU;
+
+    arm_gicv3_wait_rwp(0, 32);
+
+    /*
+            The Distributor control register (GICD_CTLR) must be configured to enable the interrupt groups and to set the routing mode.
+            Enable Affinity routing (ARE bits) The ARE bits in GICD_CTLR control whether affinity routing is enabled.
+            If affinity routing is not enabled, GICv3 can be configured for legacy operation.
+            Whether affinity routing is enabled or not can be controlled separately for Secure and Non-secure state.
+            Enables GICD_CTLR contains separate enable bits for Group 0, Secure Group 1 and Non-secure Group 1:
+            GICD_CTLR.EnableGrp1S enables distribution of Secure Group 1 interrupts.
+            GICD_CTLR.EnableGrp1NS enables distribution of Non-secure Group 1 interrupts.
+            GICD_CTLR.EnableGrp0 enables distribution of Group 0 interrupts.
+      */
+    GIC_DIST_CTRL(dist_base) = GICD_CTLR_ARE_NS | GICD_CTLR_ENGRP1NS;
+
+    return 0;
+}
+
+int arm_gic_redist_address_set(rt_uint32_t index, rt_uint32_t redist_addr, rt_uint32_t cpu_id)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+    RT_ASSERT((cpu_id) < RT_CPUS_NR);
+    _gic_table[index].redist_hw_base[cpu_id] = redist_addr;
+
+    return 0;
+}
+
+int arm_gic_cpu_interface_address_set(rt_uint32_t index, rt_uint32_t interface_addr, rt_uint32_t cpu_id)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+    RT_ASSERT((cpu_id) < RT_CPUS_NR);
+    _gic_table[index].cpu_hw_base[cpu_id] = interface_addr;
+
+    return 0;
+}
+
+int arm_gic_redist_init(rt_uint32_t index)
+{
+    unsigned int i;
+    rt_uint32_t base;
+    rt_int32_t cpu_id = rt_hw_cpu_id();
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+    RT_ASSERT((cpu_id) < RT_CPUS_NR);
+
+    base = _gic_table[index].redist_hw_base[cpu_id];
+    /* redistributor enable */
+    GIC_RDIST_WAKER(base) &= ~(1U << 1);
+    while (GIC_RDIST_WAKER(base) & (1 << 2))
+    {
+        ;
+    }
+
+    /* Disable all sgi and ppi interrupt */
+    GIC_RDISTSGI_ICENABLER0(base) = 0xFFFFFFFF;
+    arm_gicv3_wait_rwp(0, 0);
+
+    /* Clear all inetrrupt pending */
+    GIC_RDISTSGI_ICPENDR0(base) = 0xFFFFFFFF;
+
+    /* the corresponding interrupt is Group 1 or Non-secure Group 1. */
+    GIC_RDISTSGI_IGROUPR0(base, 0) = 0xFFFFFFFF;
+    GIC_RDISTSGI_IGRPMODR0(base, 0) = 0xFFFFFFFF;
+
+    /* Configure default priorities for SGI 0:15 and PPI 16:31. */
+    for (i = 0; i < 32; i += 4)
+    {
+        GIC_RDISTSGI_IPRIORITYR(base, i) = 0xa0a0a0a0U;
+    }
+
+    /* Trigger level for PPI interrupts*/
+    GIC_RDISTSGI_ICFGR1(base) = 0x0U; // PPI is level-sensitive.
+    return 0;
+}
+
+int arm_gic_cpu_init(rt_uint32_t index)
+{
+    rt_uint32_t value;
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    value = arm_gic_get_system_register_enable_mask(index);
+    value |= (1U << 0);
+    arm_gic_set_system_register_enable_mask(index, value);
+    __set_gicv3_reg(ICC_CTLR, 0);
+
+    arm_gic_set_interface_prior_mask(index, 0xFFU);
+
+    /* Enable group1 interrupt */
+    value = 0x1U;
+    __set_gicv3_reg(ICC_IGRPEN1, value);
+
+    arm_gic_set_binary_point(0, 0);
+
+    /* ICC_BPR0_EL1 determines the preemption group for both
+       Group 0 and Group 1 interrupts.
+       */
+    value = 0x1U;
+    __set_gicv3_reg(ICC_CTLR, value);
+
+    return 0;
+}
+
+#ifdef RT_USING_SMP
+void arm_gic_secondary_cpu_init(void)
+{
+    arm_gic_redist_init(0);
+
+    arm_gic_cpu_init(0);
+}
+#endif
+
+void arm_gic_dump_type(rt_uint32_t index)
+{
+    unsigned int gic_type;
+
+    gic_type = GIC_DIST_TYPE(_gic_table[index].dist_hw_base);
+    rt_kprintf("GICv%d on %p, max IRQs: %d, %s security extension(%08x)\n",
+               (GIC_DIST_ICPIDR2(_gic_table[index].dist_hw_base) >> 4U) & 0xfUL,
+               _gic_table[index].dist_hw_base,
+               _gic_max_irq,
+               gic_type & (1U << 10U) ? "has" : "no",
+               gic_type);
+}
+
+void arm_gic_dump(rt_uint32_t index)
+{
+    unsigned int i, k;
+
+    k = arm_gic_get_high_pending_irq(0);
+    rt_kprintf("--- high pending priority: %d(%08x)\n", k, k);
+    rt_kprintf("--- hw mask ---\n");
+    for (i = 0U; i < _gic_max_irq / 32U; i++)
+    {
+        rt_kprintf("0x%08x, ",
+                   GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base,
+                                       i * 32U));
+    }
+    rt_kprintf("\n--- hw pending ---\n");
+    for (i = 0U; i < _gic_max_irq / 32U; i++)
+    {
+        rt_kprintf("0x%08x, ",
+                   GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base,
+                                        i * 32U));
+    }
+    rt_kprintf("\n--- hw active ---\n");
+    for (i = 0U; i < _gic_max_irq / 32U; i++)
+    {
+        rt_kprintf("0x%08x, ",
+                   GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base,
+                                       i * 32U));
+    }
+    rt_kprintf("\n");
+}
+
+long gic_dump(void)
+{
+    arm_gic_dump_type(0);
+    arm_gic_dump(0);
+
+    return 0;
+}
+MSH_CMD_EXPORT(gic_dump, show gic status);
diff --git a/libcpu/arm/cortex-a/gicv3.h b/libcpu/arm/cortex-a/gicv3.h
new file mode 100644
index 0000000000..813a4f4c8d
--- /dev/null
+++ b/libcpu/arm/cortex-a/gicv3.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2013-07-20     Bernard      first version
+ */
+
+#ifndef __GIC_V3_H__
+#define __GIC_V3_H__
+
+#include 
+#include 
+
+#define __get_gicv3_reg(CR, Rt) __asm__ volatile("MRC " CR  \
+                                                 : "=r"(Rt) \
+                                                 :          \
+                                                 : "memory")
+#define __set_gicv3_reg(CR, Rt) __asm__ volatile("MCR " CR \
+                                                 :         \
+                                                 : "r"(Rt) \
+                                                 : "memory")
+
+
+/* AArch32 System register interface to GICv3 */
+#define ICC_IAR0    "p15, 0, %0, c12, c8, 0"
+#define ICC_IAR1    "p15, 0, %0, c12, c12, 0"
+#define ICC_EOIR0   "p15, 0, %0, c12, c8, 1"
+#define ICC_EOIR1   "p15, 0, %0, c12, c12, 1"
+#define ICC_HPPIR0  "p15, 0, %0, c12, c8, 2"
+#define ICC_HPPIR1  "p15, 0, %0, c12, c12, 2"
+#define ICC_BPR0    "p15, 0, %0, c12, c8, 3"
+#define ICC_BPR1    "p15, 0, %0, c12, c12, 3"
+#define ICC_DIR     "p15, 0, %0, c12, c11, 1"
+#define ICC_PMR     "p15, 0, %0, c4, c6, 0"
+#define ICC_RPR     "p15, 0, %0, c12, c11, 3"
+#define ICC_CTLR    "p15, 0, %0, c12, c12, 4"
+#define ICC_MCTLR   "p15, 6, %0, c12, c12, 4"
+#define ICC_SRE     "p15, 0, %0, c12, c12, 5"
+#define ICC_HSRE    "p15, 4, %0, c12, c9, 5"
+#define ICC_MSRE    "p15, 6, %0, c12, c12, 5"
+#define ICC_IGRPEN0 "p15, 0, %0, c12, c12, 6"
+#define ICC_IGRPEN1 "p15, 0, %0, c12, c12, 7"
+#define ICC_MGRPEN1 "p15, 6, %0, c12, c12, 7"
+
+#define __REG32(x) (*((volatile unsigned int*)((rt_uint32_t)x)))
+
+#define ROUTED_TO_ALL (1)
+#define ROUTED_TO_SPEC (0)
+
+/** Macro to access the Distributor Control Register (GICD_CTLR)
+*/
+#define GICD_CTLR_RWP (1<<31)
+#define GICD_CTLR_E1NWF (1<<7)
+#define GICD_CTLR_DS (1<<6)
+#define GICD_CTLR_ARE_NS (1<<5)
+#define GICD_CTLR_ARE_S (1<<4)
+#define GICD_CTLR_ENGRP1S (1<<2)
+#define GICD_CTLR_ENGRP1NS (1<<1)
+#define GICD_CTLR_ENGRP0 (1<<0)
+
+/** Macro to access the Redistributor Control Register (GICR_CTLR)
+*/
+#define GICR_CTLR_UWP (1<<31)
+#define GICR_CTLR_DPG1S (1<<26)
+#define GICR_CTLR_DPG1NS (1<<25)
+#define GICR_CTLR_DPG0 (1<<24)
+#define GICR_CTLR_RWP (1<<3)
+#define GICR_CTLR_IR (1<<2)
+#define GICR_CTLR_CES (1<<1)
+#define GICR_CTLR_EnableLPI (1<<0)
+
+/** Macro to access the Generic Interrupt Controller Interface (GICC)
+*/
+#define GIC_CPU_CTRL(hw_base)               __REG32((hw_base) + 0x00U)
+#define GIC_CPU_PRIMASK(hw_base)            __REG32((hw_base) + 0x04U)
+#define GIC_CPU_BINPOINT(hw_base)           __REG32((hw_base) + 0x08U)
+#define GIC_CPU_INTACK(hw_base)             __REG32((hw_base) + 0x0cU)
+#define GIC_CPU_EOI(hw_base)                __REG32((hw_base) + 0x10U)
+#define GIC_CPU_RUNNINGPRI(hw_base)         __REG32((hw_base) + 0x14U)
+#define GIC_CPU_HIGHPRI(hw_base)            __REG32((hw_base) + 0x18U)
+#define GIC_CPU_IIDR(hw_base)               __REG32((hw_base) + 0xFCU)
+
+/** Macro to access the Generic Interrupt Controller Distributor (GICD)
+*/
+#define GIC_DIST_CTRL(hw_base)              __REG32((hw_base) + 0x000U)
+#define GIC_DIST_TYPE(hw_base)              __REG32((hw_base) + 0x004U)
+#define GIC_DIST_IGROUP(hw_base, n)         __REG32((hw_base) + 0x080U + ((n)/32U) * 4U)
+#define GIC_DIST_ENABLE_SET(hw_base, n)     __REG32((hw_base) + 0x100U + ((n)/32U) * 4U)
+#define GIC_DIST_ENABLE_CLEAR(hw_base, n)   __REG32((hw_base) + 0x180U + ((n)/32U) * 4U)
+#define GIC_DIST_PENDING_SET(hw_base, n)    __REG32((hw_base) + 0x200U + ((n)/32U) * 4U)
+#define GIC_DIST_PENDING_CLEAR(hw_base, n)  __REG32((hw_base) + 0x280U + ((n)/32U) * 4U)
+#define GIC_DIST_ACTIVE_SET(hw_base, n)     __REG32((hw_base) + 0x300U + ((n)/32U) * 4U)
+#define GIC_DIST_ACTIVE_CLEAR(hw_base, n)   __REG32((hw_base) + 0x380U + ((n)/32U) * 4U)
+#define GIC_DIST_PRI(hw_base, n)            __REG32((hw_base) + 0x400U + ((n)/4U) * 4U)
+#define GIC_DIST_TARGET(hw_base, n)         __REG32((hw_base) + 0x800U + ((n)/4U) * 4U)
+#define GIC_DIST_CONFIG(hw_base, n)         __REG32((hw_base) + 0xc00U + ((n)/16U) * 4U)
+#define GIC_DIST_SOFTINT(hw_base)           __REG32((hw_base) + 0xf00U)
+#define GIC_DIST_CPENDSGI(hw_base, n)       __REG32((hw_base) + 0xf10U + ((n)/4U) * 4U)
+#define GIC_DIST_SPENDSGI(hw_base, n)       __REG32((hw_base) + 0xf20U + ((n)/4U) * 4U)
+#define GIC_DIST_ICPIDR2(hw_base)           __REG32((hw_base) + 0xfe8U)
+#define GIC_DIST_IROUTER_LOW(hw_base, n)    __REG32((hw_base) + 0x6000U + (n)*8U)
+#define GIC_DIST_IROUTER_HIGH(hw_base, n)   __REG32((hw_base) + 0x6000U + (n)*8U + 4)
+
+/* SGI base address  is at 64K offset from Redistributor base address */
+#define GIC_RSGI_OFFSET 0x10000
+
+/** Macro to access the Generic Interrupt Controller Redistributor (GICD)
+*/
+#define GIC_RDIST_CTRL(hw_base)              __REG32((hw_base) + 0x000U)
+#define GIC_RDIST_IIDR(hw_base)              __REG32((hw_base) + 0x004U)
+#define GIC_RDIST_TYPER(hw_base)             __REG32((hw_base) + 0x008U)
+#define GIC_RDIST_TSTATUSR(hw_base)          __REG32((hw_base) + 0x010U)
+#define GIC_RDIST_WAKER(hw_base)             __REG32((hw_base) + 0x014U)
+#define GIC_RDIST_SETLPIR(hw_base)           __REG32((hw_base) + 0x040U)
+#define GIC_RDIST_CLRLPIR(hw_base)           __REG32((hw_base) + 0x048U)
+#define GIC_RDIST_PROPBASER(hw_base)         __REG32((hw_base) + 0x070U)
+#define GIC_RDIST_PENDBASER(hw_base)         __REG32((hw_base) + 0x078U)
+#define GIC_RDIST_INVLPIR(hw_base)           __REG32((hw_base) + 0x0A0U)
+#define GIC_RDIST_INVALLR(hw_base)           __REG32((hw_base) + 0x0B0U)
+#define GIC_RDIST_SYNCR(hw_base)             __REG32((hw_base) + 0x0C0U)
+
+#define GIC_RDISTSGI_IGROUPR0(hw_base, n)    __REG32((hw_base) + GIC_RSGI_OFFSET + 0x080U + (n)*4U)
+#define GIC_RDISTSGI_ISENABLER0(hw_base)     __REG32((hw_base) + GIC_RSGI_OFFSET + 0x100U)
+#define GIC_RDISTSGI_ICENABLER0(hw_base)     __REG32((hw_base) + GIC_RSGI_OFFSET + 0x180U)
+#define GIC_RDISTSGI_ISPENDR0(hw_base)       __REG32((hw_base) + GIC_RSGI_OFFSET + 0x200U)
+#define GIC_RDISTSGI_ICPENDR0(hw_base)       __REG32((hw_base) + GIC_RSGI_OFFSET + 0x280U)
+#define GIC_RDISTSGI_ISACTIVER0(hw_base)     __REG32((hw_base) + GIC_RSGI_OFFSET + 0x300U)
+#define GIC_RDISTSGI_ICACTIVER0(hw_base)     __REG32((hw_base) + GIC_RSGI_OFFSET + 0x380U)
+#define GIC_RDISTSGI_IPRIORITYR(hw_base, n)  __REG32((hw_base) + GIC_RSGI_OFFSET + 0x400U + ((n) / 4U) * 4U)
+#define GIC_RDISTSGI_ICFGR0(hw_base)         __REG32((hw_base) + GIC_RSGI_OFFSET + 0xC00U)
+#define GIC_RDISTSGI_ICFGR1(hw_base)         __REG32((hw_base) + GIC_RSGI_OFFSET + 0xC04U)
+#define GIC_RDISTSGI_IGRPMODR0(hw_base, n)   __REG32((hw_base) + GIC_RSGI_OFFSET + 0xD00U + (n)*4)
+#define GIC_RDISTSGI_NSACR(hw_base)          __REG32((hw_base) + GIC_RSGI_OFFSET + 0xE00U)
+
+#define GIC_RSGI_AFF1_OFFSET    16
+#define GIC_RSGI_AFF2_OFFSET    32
+#define GIC_RSGI_AFF3_OFFSET    48
+
+rt_uint32_t arm_gic_cpumask_to_affval(rt_uint32_t *cpu_mask, rt_uint32_t *cluster_id, rt_uint32_t *target_list);
+rt_uint64_t get_main_cpu_affval(void);
+int arm_gic_get_active_irq(rt_uint32_t index);
+void arm_gic_ack(rt_uint32_t index, int irq);
+
+void arm_gic_mask(rt_uint32_t index, int irq);
+void arm_gic_umask(rt_uint32_t index, int irq);
+
+rt_uint32_t arm_gic_get_pending_irq(rt_uint32_t index, int irq);
+void arm_gic_set_pending_irq(rt_uint32_t index, int irq);
+void arm_gic_clear_pending_irq(rt_uint32_t index, int irq);
+
+void arm_gic_set_configuration(rt_uint32_t index, int irq, uint32_t config);
+rt_uint32_t arm_gic_get_configuration(rt_uint32_t index, int irq);
+
+void arm_gic_clear_active(rt_uint32_t index, int irq);
+
+void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask);
+rt_uint32_t arm_gic_get_target_cpu(rt_uint32_t index, int irq);
+
+void arm_gic_set_priority(rt_uint32_t index, int irq, rt_uint32_t priority);
+rt_uint32_t arm_gic_get_priority(rt_uint32_t index, int irq);
+
+void arm_gic_set_interface_prior_mask(rt_uint32_t index, rt_uint32_t priority);
+rt_uint32_t arm_gic_get_interface_prior_mask(rt_uint32_t index);
+
+void arm_gic_set_binary_point(rt_uint32_t index, rt_uint32_t binary_point);
+rt_uint32_t arm_gic_get_binary_point(rt_uint32_t index);
+
+rt_uint32_t arm_gic_get_irq_status(rt_uint32_t index, int irq);
+
+void arm_gic_send_affinity_sgi(rt_uint32_t index, int irq, rt_uint32_t cpu_mask, rt_uint32_t routing_mode);
+rt_uint32_t arm_gic_get_high_pending_irq(rt_uint32_t index);
+
+rt_uint32_t arm_gic_get_interface_id(rt_uint32_t index);
+
+void arm_gic_set_group(rt_uint32_t index, int irq, rt_uint32_t group);
+rt_uint32_t arm_gic_get_group(rt_uint32_t index, int irq);
+
+int arm_gic_redist_address_set(rt_uint32_t index, rt_uint32_t redist_addr, rt_uint32_t cpu_id);
+int arm_gic_cpu_interface_address_set(rt_uint32_t index, rt_uint32_t interface_addr, rt_uint32_t cpu_id);
+int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start);
+int arm_gic_cpu_init(rt_uint32_t index);
+int arm_gic_redist_init(rt_uint32_t index);
+
+void arm_gic_dump_type(rt_uint32_t index);
+void arm_gic_dump(rt_uint32_t index);
+
+void arm_gic_set_system_register_enable_mask(rt_uint32_t index, rt_uint32_t value);
+rt_uint32_t arm_gic_get_system_register_enable_mask(rt_uint32_t index);
+void arm_gic_secondary_cpu_init(void);
+#endif
+
diff --git a/libcpu/arm/cortex-a/interrupt.c b/libcpu/arm/cortex-a/interrupt.c
index 65e51fa3ae..474a23fee1 100644
--- a/libcpu/arm/cortex-a/interrupt.c
+++ b/libcpu/arm/cortex-a/interrupt.c
@@ -12,8 +12,12 @@
 #include 
 #include 
 #include "interrupt.h"
-#include "gic.h"
 
+#ifdef RT_USING_GIC_V2
+#include "gic.h"
+#else
+#include "gicv3.h"
+#endif
 
 /* exception and interrupt handler table */
 struct rt_irq_desc isr_table[MAX_HANDLERS];
@@ -34,6 +38,7 @@ void rt_hw_vector_init(void)
     rt_cpu_vector_set_base((unsigned int)&system_vectors);
 }
 
+#ifdef RT_USING_GIC_V2
 /**
  * This function will initialize hardware interrupt
  */
@@ -58,6 +63,33 @@ void rt_hw_interrupt_init(void)
     arm_gic_dist_init(0, gic_dist_base, gic_irq_start);
     arm_gic_cpu_init(0, gic_cpu_base);
 }
+#else
+/**
+ * This function will initialize hardware interrupt
+ * Called by the primary cpu(cpu0)
+ */
+void rt_hw_interrupt_init(void)
+{
+    rt_uint32_t gic_dist_base;
+    rt_uint32_t gic_irq_start;
+
+    /* initialize vector table */
+    rt_hw_vector_init();
+
+    /* initialize exceptions table */
+    rt_memset(isr_table, 0x00, sizeof(isr_table));
+
+    /* initialize ARM GIC */
+    gic_dist_base = platform_get_gic_dist_base();
+    gic_irq_start = GIC_IRQ_START;
+
+    arm_gic_dist_init(0, gic_dist_base, gic_irq_start);
+
+    arm_gic_cpu_init(0);
+    arm_gic_redist_init(0);
+}
+
+#endif
 
 /**
  * This function will mask a interrupt.
@@ -245,7 +277,7 @@ unsigned int rt_hw_interrupt_get_prior_group_bits(void)
  * @param old_handler the old interrupt service routine
  */
 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
-        void *param, const char *name)
+                                         void *param, const char *name)
 {
     rt_isr_handler_t old_handler = RT_NULL;
 
@@ -269,7 +301,11 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
 #ifdef RT_USING_SMP
 void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
 {
+#ifdef RT_USING_GIC_V2
     arm_gic_send_sgi(0, ipi_vector, cpu_mask, 0);
+#else
+    arm_gic_send_affinity_sgi(0, ipi_vector, cpu_mask, ROUTED_TO_SPEC);
+#endif
 }
 
 void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler)

From ffe8d06bd3a5796cdfa33c979c1ec57b65703f08 Mon Sep 17 00:00:00 2001
From: zhouji <956133287@qq.com>
Date: Wed, 5 May 2021 23:13:10 +0800
Subject: [PATCH 072/255] =?UTF-8?q?[update]=20=E5=A2=9E=E5=8A=A0=E8=8E=B7?=
 =?UTF-8?q?=E5=8F=96cortex-a=20generic=20timer=E9=A2=91=E7=8E=87=E6=8E=A5?=
 =?UTF-8?q?=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 libcpu/arm/cortex-a/gtimer.c | 8 ++++++++
 libcpu/arm/cortex-a/gtimer.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/libcpu/arm/cortex-a/gtimer.c b/libcpu/arm/cortex-a/gtimer.c
index b193a1593d..b35acc6e6f 100644
--- a/libcpu/arm/cortex-a/gtimer.c
+++ b/libcpu/arm/cortex-a/gtimer.c
@@ -110,6 +110,14 @@ void gtimer_set_counter_frequency(rt_uint32_t value)
     __asm__ volatile ("isb 0xF":::"memory");
 }
 
+/** Get the frequency the timer shall run at.
+ *  return timer frequency in Hz.
+ */
+rt_uint32_t gtimer_get_counter_frequency(void)
+{
+    return(__get_cntfrq());
+}
+
 /** Sets the reset value of the timer.
  *  param value: The value the timer is loaded with.
  */
diff --git a/libcpu/arm/cortex-a/gtimer.h b/libcpu/arm/cortex-a/gtimer.h
index 160d0cefde..ec5d54127e 100644
--- a/libcpu/arm/cortex-a/gtimer.h
+++ b/libcpu/arm/cortex-a/gtimer.h
@@ -14,6 +14,7 @@
 #include 
 
 void gtimer_set_counter_frequency(rt_uint32_t value);
+rt_uint32_t gtimer_get_counter_frequency(void);
 void gtimer_set_load_value(rt_uint32_t value);
 rt_uint32_t gtimer_get_current_value(void);
 rt_uint64_t gtimer_get_current_physical_value(void);

From 2eea7259c21587d4d1b6f2dcb29415820cd01dbc Mon Sep 17 00:00:00 2001
From: zhouji <956133287@qq.com>
Date: Thu, 6 May 2021 18:54:25 +0800
Subject: [PATCH 073/255] =?UTF-8?q?[update]=20=E6=9B=B4=E6=96=B0=E4=B8=8El?=
 =?UTF-8?q?ibcpu\cortex-a=E7=9B=B8=E5=85=B3BSP=E7=9A=84=E9=85=8D=E7=BD=AE,?=
 =?UTF-8?q?=20=E9=80=89=E6=8B=A9=E5=90=88=E9=80=82=E7=9A=84GIC=E6=8E=A7?=
 =?UTF-8?q?=E5=88=B6=E5=99=A8=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 bsp/imx6ul/.config              | 100 +++++++++++++++-
 bsp/imx6ul/rtconfig.h           | 200 +-------------------------------
 bsp/qemu-vexpress-a9/.config    |   4 +
 bsp/qemu-vexpress-a9/rtconfig.h |   1 +
 4 files changed, 105 insertions(+), 200 deletions(-)

diff --git a/bsp/imx6ul/.config b/bsp/imx6ul/.config
index 0068adc43f..91e1e6fac2 100644
--- a/bsp/imx6ul/.config
+++ b/bsp/imx6ul/.config
@@ -22,6 +22,12 @@ CONFIG_RT_USING_IDLE_HOOK=y
 CONFIG_RT_IDLE_HOOK_LIST_SIZE=4
 CONFIG_IDLE_THREAD_STACK_SIZE=256
 # CONFIG_RT_USING_TIMER_SOFT is not set
+
+#
+# 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 is not set
 # CONFIG_RT_DEBUG_INIT_CONFIG is not set
@@ -53,6 +59,7 @@ CONFIG_RT_USING_MEMPOOL=y
 # CONFIG_RT_USING_NOHEAP is not set
 CONFIG_RT_USING_SMALL_MEM=y
 # CONFIG_RT_USING_SLAB is not set
+# CONFIG_RT_USING_USERHEAP is not set
 # CONFIG_RT_USING_MEMTRACE is not set
 CONFIG_RT_USING_HEAP=y
 
@@ -65,10 +72,14 @@ CONFIG_RT_USING_DEVICE=y
 CONFIG_RT_USING_CONSOLE=y
 CONFIG_RT_CONSOLEBUF_SIZE=128
 CONFIG_RT_CONSOLE_DEVICE_NAME="uart"
-CONFIG_RT_VER_NUM=0x40002
+CONFIG_RT_VER_NUM=0x40003
 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=y
+# CONFIG_RT_USING_GIC_V3 is not set
+# CONFIG_RT_NO_USING_GIC is not set
 CONFIG_ARCH_ARM_CORTEX_A7=y
 # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
 
@@ -115,8 +126,6 @@ CONFIG_DFS_FD_MAX=16
 CONFIG_RT_USING_DFS_DEVFS=y
 # CONFIG_RT_USING_DFS_ROMFS is not set
 # CONFIG_RT_USING_DFS_RAMFS is not set
-# CONFIG_RT_USING_DFS_UFFS is not set
-# CONFIG_RT_USING_DFS_JFFS2 is not set
 
 #
 # Device Drivers
@@ -131,8 +140,10 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64
 # 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=y
 # CONFIG_RT_USING_ADC is not set
+# CONFIG_RT_USING_DAC is not set
 # CONFIG_RT_USING_PWM is not set
 # CONFIG_RT_USING_MTD_NOR is not set
 # CONFIG_RT_USING_MTD_NAND is not set
@@ -163,6 +174,7 @@ CONFIG_RT_USING_LIBC=y
 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
 
@@ -210,10 +222,15 @@ CONFIG_RT_USING_POSIX=y
 #
 # 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
@@ -240,6 +257,8 @@ CONFIG_RT_USING_POSIX=y
 # 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
@@ -251,8 +270,10 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_GAGENT_CLOUD is not set
 # CONFIG_PKG_USING_ALI_IOTKIT is not set
 # CONFIG_PKG_USING_AZURE is not set
-# CONFIG_PKG_USING_TENCENT_IOTHUB is not set
+# CONFIG_PKG_USING_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
@@ -263,6 +284,19 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_PROTOBUF_C is not set
 # CONFIG_PKG_USING_ONNX_PARSER is not set
 # CONFIG_PKG_USING_ONNX_BACKEND is not set
+# CONFIG_PKG_USING_DLT645 is not set
+# CONFIG_PKG_USING_QXWZ is not set
+# CONFIG_PKG_USING_SMTP_CLIENT is not set
+# CONFIG_PKG_USING_ABUP_FOTA is not set
+# CONFIG_PKG_USING_LIBCURL2RTT is not set
+# CONFIG_PKG_USING_CAPNP is not set
+# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set
+# CONFIG_PKG_USING_AGILE_TELNET is not set
+# CONFIG_PKG_USING_NMEALIB is not set
+# CONFIG_PKG_USING_AGILE_JSMN is not set
+# CONFIG_PKG_USING_PDULIB is not set
+# CONFIG_PKG_USING_BTSTACK is not set
+# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set
 
 #
 # security packages
@@ -270,6 +304,8 @@ CONFIG_RT_USING_POSIX=y
 # 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
@@ -286,6 +322,7 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_STEMWIN is not set
 # CONFIG_PKG_USING_WAVPLAYER is not set
 # CONFIG_PKG_USING_TJPGD is not set
+# CONFIG_PKG_USING_HELIX is not set
 
 #
 # tools packages
@@ -298,6 +335,15 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_QRCODE is not set
 # CONFIG_PKG_USING_ULOG_EASYFLASH is not set
 # CONFIG_PKG_USING_ADBD is not set
+# CONFIG_PKG_USING_COREMARK is not set
+# CONFIG_PKG_USING_DHRYSTONE is not set
+# CONFIG_PKG_USING_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
 
 #
 # system packages
@@ -309,6 +355,7 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_LWEXT4 is not set
 # CONFIG_PKG_USING_PARTITION is not set
 # CONFIG_PKG_USING_FAL is not set
+# CONFIG_PKG_USING_FLASHDB is not set
 # CONFIG_PKG_USING_SQLITE is not set
 # CONFIG_PKG_USING_RTI is not set
 # CONFIG_PKG_USING_LITTLEVGL2RTT is not set
@@ -317,6 +364,14 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_LITTLEFS is not set
 # CONFIG_PKG_USING_THREAD_POOL is not set
 # CONFIG_PKG_USING_ROBOTS is not set
+# CONFIG_PKG_USING_EV is not set
+# CONFIG_PKG_USING_SYSWATCH is not set
+# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set
+# CONFIG_PKG_USING_PLCCORE is not set
+# CONFIG_PKG_USING_RAMDISK is not set
+# CONFIG_PKG_USING_MININI is not set
+# CONFIG_PKG_USING_QBOOT is not set
+# CONFIG_PKG_USING_PPOOL is not set
 
 #
 # peripheral libraries and drivers
@@ -324,6 +379,7 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_SENSORS_DRIVERS is not set
 # CONFIG_PKG_USING_REALTEK_AMEBA is not set
 # CONFIG_PKG_USING_SHT2X is not set
+# CONFIG_PKG_USING_SHT3X is not set
 # CONFIG_PKG_USING_STM32_SDIO is not set
 # CONFIG_PKG_USING_ICM20608 is not set
 # CONFIG_PKG_USING_U8G2 is not set
@@ -332,10 +388,16 @@ CONFIG_RT_USING_POSIX=y
 # 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
@@ -343,8 +405,28 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_I2C_TOOLS is not set
 # CONFIG_PKG_USING_NRF24L01 is not set
 # CONFIG_PKG_USING_TOUCH_DRIVERS is not set
-# CONFIG_PKG_USING_LCD_DRIVERS is not set
 # CONFIG_PKG_USING_MAX17048 is not set
+# CONFIG_PKG_USING_RPLIDAR is not set
+# 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
 
 #
 # miscellaneous packages
@@ -379,4 +461,12 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_ELAPACK is not set
 # CONFIG_PKG_USING_ARMv7M_DWT is not set
 # CONFIG_PKG_USING_VT100 is not set
+# CONFIG_PKG_USING_TETRIS is not set
+# CONFIG_PKG_USING_ULAPACK is not set
+# CONFIG_PKG_USING_UKAL is not set
+# CONFIG_PKG_USING_CRCLIB is not set
+# CONFIG_PKG_USING_THREES is not set
+# CONFIG_PKG_USING_2048 is not set
+# CONFIG_PKG_USING_LWGPS is not set
+# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set
 CONFIG_SOC_MCIMX6X4=y
diff --git a/bsp/imx6ul/rtconfig.h b/bsp/imx6ul/rtconfig.h
index 19826089e2..5478603dcb 100644
--- a/bsp/imx6ul/rtconfig.h
+++ b/bsp/imx6ul/rtconfig.h
@@ -9,12 +9,8 @@
 /* RT-Thread Kernel */
 
 #define RT_NAME_MAX 8
-/* RT_USING_ARCH_DATA_TYPE is not set */
-/* RT_USING_SMP is not set */
 #define RT_ALIGN_SIZE 4
-/* RT_THREAD_PRIORITY_8 is not set */
 #define RT_THREAD_PRIORITY_32
-/* RT_THREAD_PRIORITY_256 is not set */
 #define RT_THREAD_PRIORITY_MAX 32
 #define RT_TICK_PER_SECOND 100
 #define RT_USING_OVERFLOW_CHECK
@@ -22,19 +18,10 @@
 #define RT_USING_IDLE_HOOK
 #define RT_IDLE_HOOK_LIST_SIZE 4
 #define IDLE_THREAD_STACK_SIZE 256
-/* RT_USING_TIMER_SOFT is not set */
+
+/* kservice optimization */
+
 #define RT_DEBUG
-/* RT_DEBUG_COLOR is not set */
-/* RT_DEBUG_INIT_CONFIG is not set */
-/* RT_DEBUG_THREAD_CONFIG is not set */
-/* RT_DEBUG_SCHEDULER_CONFIG is not set */
-/* RT_DEBUG_IPC_CONFIG is not set */
-/* RT_DEBUG_TIMER_CONFIG is not set */
-/* RT_DEBUG_IRQ_CONFIG is not set */
-/* RT_DEBUG_MEM_CONFIG is not set */
-/* RT_DEBUG_SLAB_CONFIG is not set */
-/* RT_DEBUG_MEMHEAP_CONFIG is not set */
-/* RT_DEBUG_MODULE_CONFIG is not set */
 
 /* Inter-Thread communication */
 
@@ -43,41 +30,31 @@
 #define RT_USING_EVENT
 #define RT_USING_MAILBOX
 #define RT_USING_MESSAGEQUEUE
-/* RT_USING_SIGNALS is not set */
 
 /* Memory Management */
 
 #define RT_USING_MEMPOOL
-/* RT_USING_MEMHEAP is not set */
-/* RT_USING_NOHEAP is not set */
 #define RT_USING_SMALL_MEM
-/* RT_USING_SLAB is not set */
-/* RT_USING_MEMTRACE is not set */
 #define RT_USING_HEAP
 
 /* Kernel Device Object */
 
 #define RT_USING_DEVICE
-/* RT_USING_DEVICE_OPS is not set */
-/* RT_USING_INTERRUPT_INFO is not set */
 #define RT_USING_CONSOLE
 #define RT_CONSOLEBUF_SIZE 128
 #define RT_CONSOLE_DEVICE_NAME "uart"
-#define RT_VER_NUM 0x40002
+#define RT_VER_NUM 0x40003
 #define ARCH_ARM
-/* RT_USING_CPU_FFS is not set */
 #define ARCH_ARM_CORTEX_A
+#define RT_USING_GIC_V2
 #define ARCH_ARM_CORTEX_A7
-/* ARCH_CPU_STACK_GROWS_UPWARD is not set */
 
 /* RT-Thread Components */
 
 #define RT_USING_COMPONENTS_INIT
-/* RT_USING_USER_MAIN is not set */
 
 /* C++ features */
 
-/* RT_USING_CPLUSPLUS is not set */
 
 /* Command shell */
 
@@ -87,14 +64,11 @@
 #define FINSH_HISTORY_LINES 5
 #define FINSH_USING_SYMTAB
 #define FINSH_USING_DESCRIPTION
-/* FINSH_ECHO_DISABLE_DEFAULT is not set */
 #define FINSH_THREAD_PRIORITY 20
 #define FINSH_THREAD_STACK_SIZE 4096
 #define FINSH_CMD_SIZE 80
-/* FINSH_USING_AUTH is not set */
 #define FINSH_USING_MSH
 #define FINSH_USING_MSH_DEFAULT
-/* FINSH_USING_MSH_ONLY is not set */
 #define FINSH_ARG_MAX 10
 
 /* Device virtual file system */
@@ -104,248 +78,84 @@
 #define DFS_FILESYSTEMS_MAX 2
 #define DFS_FILESYSTEM_TYPES_MAX 2
 #define DFS_FD_MAX 16
-/* RT_USING_DFS_MNTTABLE is not set */
-/* RT_USING_DFS_ELMFAT is not set */
 #define RT_USING_DFS_DEVFS
-/* RT_USING_DFS_ROMFS is not set */
-/* RT_USING_DFS_RAMFS is not set */
-/* RT_USING_DFS_UFFS is not set */
-/* RT_USING_DFS_JFFS2 is not set */
 
 /* Device Drivers */
 
 #define RT_USING_DEVICE_IPC
 #define RT_PIPE_BUFSZ 512
-/* RT_USING_SYSTEM_WORKQUEUE is not set */
 #define RT_USING_SERIAL
 #define RT_SERIAL_USING_DMA
 #define RT_SERIAL_RB_BUFSZ 64
-/* RT_USING_CAN is not set */
-/* RT_USING_HWTIMER is not set */
-/* RT_USING_CPUTIME is not set */
-/* RT_USING_I2C is not set */
 #define RT_USING_PIN
-/* RT_USING_ADC is not set */
-/* RT_USING_PWM is not set */
-/* RT_USING_MTD_NOR is not set */
-/* RT_USING_MTD_NAND is not set */
-/* RT_USING_PM is not set */
-/* RT_USING_RTC is not set */
-/* RT_USING_SDIO is not set */
-/* RT_USING_SPI is not set */
-/* RT_USING_WDT is not set */
-/* RT_USING_AUDIO is not set */
-/* RT_USING_SENSOR is not set */
-/* RT_USING_TOUCH is not set */
-/* RT_USING_HWCRYPTO is not set */
-/* RT_USING_PULSE_ENCODER is not set */
-/* RT_USING_INPUT_CAPTURE is not set */
-/* RT_USING_WIFI is not set */
 
 /* Using USB */
 
-/* RT_USING_USB_HOST is not set */
-/* RT_USING_USB_DEVICE is not set */
 
 /* POSIX layer and C standard library */
 
 #define RT_USING_LIBC
-/* RT_USING_PTHREADS is not set */
 #define RT_USING_POSIX
-/* RT_USING_POSIX_MMAP is not set */
-/* RT_USING_POSIX_TERMIOS is not set */
-/* RT_USING_POSIX_AIO is not set */
-/* RT_USING_MODULE is not set */
 
 /* Network */
 
 /* Socket abstraction layer */
 
-/* RT_USING_SAL is not set */
 
 /* Network interface device */
 
-/* RT_USING_NETDEV is not set */
 
 /* light weight TCP/IP stack */
 
-/* RT_USING_LWIP is not set */
 
 /* AT commands */
 
-/* RT_USING_AT is not set */
 
 /* VBUS(Virtual Software BUS) */
 
-/* RT_USING_VBUS is not set */
 
 /* Utilities */
 
-/* RT_USING_RYM is not set */
-/* RT_USING_ULOG is not set */
-/* RT_USING_UTEST is not set */
-/* RT_USING_LWP is not set */
 
 /* RT-Thread online packages */
 
 /* IoT - internet of things */
 
-/* PKG_USING_PAHOMQTT is not set */
-/* PKG_USING_WEBCLIENT is not set */
-/* PKG_USING_WEBNET is not set */
-/* PKG_USING_MONGOOSE is not set */
-/* PKG_USING_WEBTERMINAL is not set */
-/* PKG_USING_CJSON is not set */
-/* PKG_USING_JSMN is not set */
-/* PKG_USING_LIBMODBUS is not set */
-/* PKG_USING_FREEMODBUS is not set */
-/* PKG_USING_LJSON is not set */
-/* PKG_USING_EZXML is not set */
-/* PKG_USING_NANOPB is not set */
 
 /* Wi-Fi */
 
 /* Marvell WiFi */
 
-/* PKG_USING_WLANMARVELL is not set */
 
 /* Wiced WiFi */
 
-/* PKG_USING_WLAN_WICED is not set */
-/* PKG_USING_RW007 is not set */
-/* PKG_USING_COAP is not set */
-/* PKG_USING_NOPOLL is not set */
-/* PKG_USING_NETUTILS is not set */
-/* PKG_USING_AT_DEVICE is not set */
-/* PKG_USING_ATSRV_SOCKET is not set */
-/* PKG_USING_WIZNET is not set */
 
 /* IoT Cloud */
 
-/* PKG_USING_ONENET is not set */
-/* PKG_USING_GAGENT_CLOUD is not set */
-/* PKG_USING_ALI_IOTKIT is not set */
-/* PKG_USING_AZURE is not set */
-/* PKG_USING_TENCENT_IOTHUB is not set */
-/* PKG_USING_JIOT-C-SDK is not set */
-/* PKG_USING_NIMBLE is not set */
-/* PKG_USING_OTA_DOWNLOADER is not set */
-/* PKG_USING_IPMSG is not set */
-/* PKG_USING_LSSDP is not set */
-/* PKG_USING_AIRKISS_OPEN is not set */
-/* PKG_USING_LIBRWS is not set */
-/* PKG_USING_TCPSERVER is not set */
-/* PKG_USING_PROTOBUF_C is not set */
-/* PKG_USING_ONNX_PARSER is not set */
-/* PKG_USING_ONNX_BACKEND is not set */
 
 /* security packages */
 
-/* PKG_USING_MBEDTLS is not set */
-/* PKG_USING_libsodium is not set */
-/* PKG_USING_TINYCRYPT is not set */
 
 /* language packages */
 
-/* PKG_USING_LUA is not set */
-/* PKG_USING_JERRYSCRIPT is not set */
-/* PKG_USING_MICROPYTHON is not set */
 
 /* multimedia packages */
 
-/* PKG_USING_OPENMV is not set */
-/* PKG_USING_MUPDF is not set */
-/* PKG_USING_STEMWIN is not set */
-/* PKG_USING_WAVPLAYER is not set */
-/* PKG_USING_TJPGD is not set */
 
 /* tools packages */
 
-/* PKG_USING_CMBACKTRACE is not set */
-/* PKG_USING_EASYFLASH is not set */
-/* PKG_USING_EASYLOGGER is not set */
-/* PKG_USING_SYSTEMVIEW is not set */
-/* PKG_USING_RDB is not set */
-/* PKG_USING_QRCODE is not set */
-/* PKG_USING_ULOG_EASYFLASH is not set */
-/* PKG_USING_ADBD is not set */
 
 /* system packages */
 
-/* PKG_USING_GUIENGINE is not set */
-/* PKG_USING_PERSIMMON is not set */
-/* PKG_USING_CAIRO is not set */
-/* PKG_USING_PIXMAN is not set */
-/* PKG_USING_LWEXT4 is not set */
-/* PKG_USING_PARTITION is not set */
-/* PKG_USING_FAL is not set */
-/* PKG_USING_SQLITE is not set */
-/* PKG_USING_RTI is not set */
-/* PKG_USING_LITTLEVGL2RTT is not set */
-/* PKG_USING_CMSIS is not set */
-/* PKG_USING_DFS_YAFFS is not set */
-/* PKG_USING_LITTLEFS is not set */
-/* PKG_USING_THREAD_POOL is not set */
-/* PKG_USING_ROBOTS is not set */
 
 /* peripheral libraries and drivers */
 
-/* PKG_USING_SENSORS_DRIVERS is not set */
-/* PKG_USING_REALTEK_AMEBA is not set */
-/* PKG_USING_SHT2X is not set */
-/* PKG_USING_STM32_SDIO is not set */
-/* PKG_USING_ICM20608 is not set */
-/* PKG_USING_U8G2 is not set */
-/* PKG_USING_BUTTON is not set */
-/* PKG_USING_PCF8574 is not set */
-/* PKG_USING_SX12XX is not set */
-/* PKG_USING_SIGNAL_LED is not set */
-/* PKG_USING_LEDBLINK is not set */
-/* PKG_USING_WM_LIBRARIES is not set */
-/* PKG_USING_KENDRYTE_SDK is not set */
-/* PKG_USING_INFRARED is not set */
-/* PKG_USING_ROSSERIAL is not set */
-/* PKG_USING_AT24CXX is not set */
-/* PKG_USING_MOTIONDRIVER2RTT is not set */
-/* PKG_USING_AD7746 is not set */
-/* PKG_USING_PCA9685 is not set */
-/* PKG_USING_I2C_TOOLS is not set */
-/* PKG_USING_NRF24L01 is not set */
-/* PKG_USING_TOUCH_DRIVERS is not set */
-/* PKG_USING_LCD_DRIVERS is not set */
-/* PKG_USING_MAX17048 is not set */
 
 /* miscellaneous packages */
 
-/* PKG_USING_LIBCSV is not set */
-/* PKG_USING_OPTPARSE is not set */
-/* PKG_USING_FASTLZ is not set */
-/* PKG_USING_MINILZO is not set */
-/* PKG_USING_QUICKLZ is not set */
-/* PKG_USING_MULTIBUTTON is not set */
-/* PKG_USING_FLEXIBLE_BUTTON is not set */
-/* PKG_USING_CANFESTIVAL is not set */
-/* PKG_USING_ZLIB is not set */
-/* PKG_USING_DSTR is not set */
-/* PKG_USING_TINYFRAME is not set */
-/* PKG_USING_KENDRYTE_DEMO is not set */
-/* PKG_USING_DIGITALCTRL is not set */
-/* PKG_USING_UPACKER is not set */
-/* PKG_USING_UPARAM is not set */
 
 /* samples: kernel and components samples */
 
-/* PKG_USING_KERNEL_SAMPLES is not set */
-/* PKG_USING_FILESYSTEM_SAMPLES is not set */
-/* PKG_USING_NETWORK_SAMPLES is not set */
-/* PKG_USING_PERIPHERAL_SAMPLES is not set */
-/* PKG_USING_HELLO is not set */
-/* PKG_USING_VI is not set */
-/* PKG_USING_NNOM is not set */
-/* PKG_USING_LIBANN is not set */
-/* PKG_USING_ELAPACK is not set */
-/* PKG_USING_ARMv7M_DWT is not set */
-/* PKG_USING_VT100 is not set */
 #define SOC_MCIMX6X4
 
 #endif
diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config
index 00929cbed0..f9fa185ce7 100644
--- a/bsp/qemu-vexpress-a9/.config
+++ b/bsp/qemu-vexpress-a9/.config
@@ -79,6 +79,10 @@ 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=y
+# CONFIG_RT_USING_GIC_V3 is not set
+# CONFIG_RT_NO_USING_GIC is not set
 CONFIG_ARCH_ARM_CORTEX_A9=y
 # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
 
diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h
index 4ca586afff..eb7b915d86 100644
--- a/bsp/qemu-vexpress-a9/rtconfig.h
+++ b/bsp/qemu-vexpress-a9/rtconfig.h
@@ -55,6 +55,7 @@
 #define RT_VER_NUM 0x40004
 #define ARCH_ARM
 #define ARCH_ARM_CORTEX_A
+#define RT_USING_GIC_V2
 #define ARCH_ARM_CORTEX_A9
 
 /* RT-Thread Components */

From 3369a2c1c89a79b4e773ace71c81b5f42b35e4d0 Mon Sep 17 00:00:00 2001
From: guozhanxin 
Date: Fri, 14 May 2021 17:07:58 +0800
Subject: [PATCH 074/255] [fix] Fix the problem of an error when opening
 menuconfig after the project is dist.

---
 tools/mkdist.py | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/tools/mkdist.py b/tools/mkdist.py
index 7765873baa..a29db7b080 100644
--- a/tools/mkdist.py
+++ b/tools/mkdist.py
@@ -105,6 +105,18 @@ def bsp_update_sconstruct(dist_dir):
                     f.write('if not os.getenv("RTT_ROOT"): \n    RTT_ROOT="rt-thread"\n\n')
             f.write(line)
 
+def bsp_update_kconfig_testcases(dist_dir):
+    # delete testcases in rt-thread/Kconfig
+    if not os.path.isfile(os.path.join(dist_dir, 'rt-thread/Kconfig')):
+        return
+
+    with open(os.path.join(dist_dir, 'rt-thread/Kconfig'), 'r') as f:
+        data = f.readlines()
+    with open(os.path.join(dist_dir, 'rt-thread/Kconfig'), 'w') as f:
+        for line in data:
+            if line.find('examples/utest/testcases/Kconfig') == -1:
+                f.write(line)
+
 def bsp_update_kconfig(dist_dir):
     # change RTT_ROOT in Kconfig
     if not os.path.isfile(os.path.join(dist_dir, 'Kconfig')):
@@ -307,11 +319,14 @@ def MkDist_Strip(program, BSP_ROOT, RTT_ROOT, Env):
     do_copy_file(os.path.join(RTT_ROOT, 'libcpu', 'Kconfig'), os.path.join(target_path, 'libcpu', 'Kconfig'))
     do_copy_file(os.path.join(RTT_ROOT, 'libcpu', 'SConscript'), os.path.join(target_path, 'libcpu', 'SConscript'))
 
+    print('Update configuration files...')
     # change RTT_ROOT in SConstruct
     bsp_update_sconstruct(dist_dir)
     # change RTT_ROOT in Kconfig
     bsp_update_kconfig(dist_dir)
     bsp_update_kconfig_library(dist_dir)
+    # delete testcases in Kconfig
+    bsp_update_kconfig_testcases(dist_dir)
     # update all project files
     bs_update_ide_project(dist_dir, target_path)
 
@@ -374,12 +389,14 @@ def MkDist(program, BSP_ROOT, RTT_ROOT, Env, rttide = None):
     do_copy_file(os.path.join(RTT_ROOT, 'README.md'), os.path.join(target_path, 'README.md'))
     do_copy_file(os.path.join(RTT_ROOT, 'README_zh.md'), os.path.join(target_path, 'README_zh.md'))
 
+    print('Update configuration files...')
     # change RTT_ROOT in SConstruct
     bsp_update_sconstruct(dist_dir)
     # change RTT_ROOT in Kconfig
     bsp_update_kconfig(dist_dir)
     bsp_update_kconfig_library(dist_dir)
-
+    # delete testcases in Kconfig
+    bsp_update_kconfig_testcases(dist_dir)
     # update all project files
     if rttide == None:
         bs_update_ide_project(dist_dir, target_path)

From 31b94778c3ee4e1430e6d578bda1e233de05ae40 Mon Sep 17 00:00:00 2001
From: Meco Man <920369182@qq.com>
Date: Sat, 15 May 2021 15:30:28 +0800
Subject: [PATCH 075/255] =?UTF-8?q?[bug][bsp][simulator]=20=E4=BF=AE?=
 =?UTF-8?q?=E5=A4=8Dsd=5Fsim.c=E7=BC=96=E8=AF=91=E6=8A=A5=E9=94=99?=
 =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BD=BF=E7=94=A8rt=5Fdgb?=
 =?UTF-8?q?=E4=BB=A3=E6=9B=BF=E8=80=81=E6=97=A7=E7=9A=84debug=E8=BE=93?=
 =?UTF-8?q?=E5=87=BA=E6=96=B9=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 bsp/simulator/drivers/sd_sim.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/bsp/simulator/drivers/sd_sim.c b/bsp/simulator/drivers/sd_sim.c
index adc489be20..bee76d8be7 100755
--- a/bsp/simulator/drivers/sd_sim.c
+++ b/bsp/simulator/drivers/sd_sim.c
@@ -13,11 +13,9 @@
 #include 
 #include 
 
-#ifdef DEBUG
-#  define SD_TRACE     rt_kprintf
-#else
-#  define SD_TRACE(...)
-#endif
+#define DBG_TAG    "sd.sim"
+#define DBG_LVL    DBG_INFO
+#include 
 
 #define SDCARD_SIM  "sd.bin"
 #define SDCARD_SIZE (16*1024*1024)  //16M
@@ -59,7 +57,7 @@ static rt_size_t rt_sdcard_read(rt_device_t device, rt_off_t position, void *buf
     struct sdcard_device *sd;
     int result = 0;
 
-    SD_TRACE("sd read: pos %d, size %d\n", position, size);
+    LOG_I("sd read: pos %d, size %d\n", position, size);
 
     rt_mutex_take(lock, RT_WAITING_FOREVER);
     sd = SDCARD_DEVICE(device);
@@ -73,7 +71,7 @@ static rt_size_t rt_sdcard_read(rt_device_t device, rt_off_t position, void *buf
     return size;
 
 _err:
-    SD_TRACE("sd read errors!\n");
+    LOG_E("sd read errors!\n");
     rt_mutex_release(lock);
     return 0;
 }
@@ -87,7 +85,7 @@ static rt_size_t rt_sdcard_write(rt_device_t device, rt_off_t position, const vo
     struct sdcard_device *sd;
     int result = 0;
 
-    SD_TRACE("sst write: pos %d, size %d\n", position, size);
+    LOG_I("sst write: pos %d, size %d\n", position, size);
 
     rt_mutex_take(lock, RT_WAITING_FOREVER);
     sd = SDCARD_DEVICE(device);
@@ -101,7 +99,7 @@ static rt_size_t rt_sdcard_write(rt_device_t device, rt_off_t position, const vo
     return size;
 
 _err:
-    SD_TRACE("sd write errors!\n");
+    LOG_E("sd write errors!\n");
     rt_mutex_release(lock);
     return 0;
 }
@@ -168,7 +166,7 @@ rt_err_t rt_hw_sdcard_init(const char *spi_device_name)
             ptr = (unsigned char *) malloc(1024 * 1024);
             if (ptr == NULL)
             {
-                SD_TRACE("malloc error, no memory!\n");
+                LOG_E("malloc error, no memory!\n");
                 return RT_ERROR;
             }
             memset(ptr, 0x0, 1024 * 1024);

From a00a463248bc66cff04e098c2440e90bf7ea273e Mon Sep 17 00:00:00 2001
From: Meco Man <920369182@qq.com>
Date: Sat, 15 May 2021 15:35:45 +0800
Subject: [PATCH 076/255] format codes

---
 bsp/simulator/drivers/sd_sim.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bsp/simulator/drivers/sd_sim.c b/bsp/simulator/drivers/sd_sim.c
index bee76d8be7..8a7619fe7e 100755
--- a/bsp/simulator/drivers/sd_sim.c
+++ b/bsp/simulator/drivers/sd_sim.c
@@ -141,7 +141,7 @@ rt_err_t rt_hw_sdcard_init(const char *spi_device_name)
     device = &(sd->parent);
 
     lock = rt_mutex_create("lock", RT_IPC_FLAG_FIFO);
-    if (lock == RT_NULL) 
+    if (lock == RT_NULL)
     {
         LOG_E("Create mutex in rt_hw_sdcard_init failed!");
         return -RT_ERROR;

From 69471e6242c16884762516cf8cd6a557b5ab4f50 Mon Sep 17 00:00:00 2001
From: Meco Man <920369182@qq.com>
Date: Sat, 15 May 2021 15:38:14 +0800
Subject: [PATCH 077/255] [bsp][simulator]format codes to prevent CI errors

---
 bsp/simulator/drivers/sdl_fb.c            | 2 +-
 bsp/simulator/drivers/sst25vfxx_mtd_sim.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/bsp/simulator/drivers/sdl_fb.c b/bsp/simulator/drivers/sdl_fb.c
index 7b25da9c3c..995b12219e 100755
--- a/bsp/simulator/drivers/sdl_fb.c
+++ b/bsp/simulator/drivers/sdl_fb.c
@@ -221,7 +221,7 @@ static void sdlfb_hw_init(void)
     rt_device_register(RT_DEVICE(&_device), "sdl", RT_DEVICE_FLAG_RDWR);
 
     sdllock = rt_mutex_create("fb", RT_IPC_FLAG_FIFO);
-    if (sdllock == RT_NULL) 
+    if (sdllock == RT_NULL)
     {
         LOG_E("Create mutex for sdlfb failed!");
     }
diff --git a/bsp/simulator/drivers/sst25vfxx_mtd_sim.c b/bsp/simulator/drivers/sst25vfxx_mtd_sim.c
index 4460e1da3b..bc44699a10 100644
--- a/bsp/simulator/drivers/sst25vfxx_mtd_sim.c
+++ b/bsp/simulator/drivers/sst25vfxx_mtd_sim.c
@@ -16,7 +16,7 @@
 
 #ifdef RT_USING_MTD_NOR
 #define NOR_SIM "nor.bin"
-/* JEDEC Manufacturer’s ID */
+/* JEDEC Manufacturer's ID */
 #define MF_ID           (0xBF)
 /* JEDEC Device ID : Memory Type */
 #define MT_ID           (0x25)

From 1773908df80316be89a74010cb2c5bdda347313f Mon Sep 17 00:00:00 2001
From: Meco Jianting Man <920369182@qq.com>
Date: Sat, 15 May 2021 16:16:34 +0800
Subject: [PATCH 078/255] remove \n from LOG_x

---
 bsp/simulator/drivers/sd_sim.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/bsp/simulator/drivers/sd_sim.c b/bsp/simulator/drivers/sd_sim.c
index 8a7619fe7e..7557fac12c 100755
--- a/bsp/simulator/drivers/sd_sim.c
+++ b/bsp/simulator/drivers/sd_sim.c
@@ -57,7 +57,7 @@ static rt_size_t rt_sdcard_read(rt_device_t device, rt_off_t position, void *buf
     struct sdcard_device *sd;
     int result = 0;
 
-    LOG_I("sd read: pos %d, size %d\n", position, size);
+    LOG_I("sd read: pos %d, size %d", position, size);
 
     rt_mutex_take(lock, RT_WAITING_FOREVER);
     sd = SDCARD_DEVICE(device);
@@ -71,7 +71,7 @@ static rt_size_t rt_sdcard_read(rt_device_t device, rt_off_t position, void *buf
     return size;
 
 _err:
-    LOG_E("sd read errors!\n");
+    LOG_E("sd read errors!");
     rt_mutex_release(lock);
     return 0;
 }
@@ -85,7 +85,7 @@ static rt_size_t rt_sdcard_write(rt_device_t device, rt_off_t position, const vo
     struct sdcard_device *sd;
     int result = 0;
 
-    LOG_I("sst write: pos %d, size %d\n", position, size);
+    LOG_I("sst write: pos %d, size %d", position, size);
 
     rt_mutex_take(lock, RT_WAITING_FOREVER);
     sd = SDCARD_DEVICE(device);
@@ -99,7 +99,7 @@ static rt_size_t rt_sdcard_write(rt_device_t device, rt_off_t position, const vo
     return size;
 
 _err:
-    LOG_E("sd write errors!\n");
+    LOG_E("sd write errors!");
     rt_mutex_release(lock);
     return 0;
 }
@@ -166,7 +166,7 @@ rt_err_t rt_hw_sdcard_init(const char *spi_device_name)
             ptr = (unsigned char *) malloc(1024 * 1024);
             if (ptr == NULL)
             {
-                LOG_E("malloc error, no memory!\n");
+                LOG_E("malloc error, no memory!");
                 return RT_ERROR;
             }
             memset(ptr, 0x0, 1024 * 1024);

From 21f9e5625357265245968061079e1c72ffa25ee4 Mon Sep 17 00:00:00 2001
From: Sherman 
Date: Sat, 15 May 2021 16:52:49 +0800
Subject: [PATCH 079/255] [add] add new component: rt-link

---
 components/utilities/Kconfig                  |    2 +
 components/utilities/rt-link/Kconfig          |   40 +
 components/utilities/rt-link/SConscript       |   15 +
 .../utilities/rt-link/hw_port/SConscript      |   14 +
 .../rt-link/hw_port/uart/rtlink_port_uart.c   |   73 +
 components/utilities/rt-link/inc/rtlink.h     |  175 +++
 components/utilities/rt-link/inc/rtlink_hw.h  |   24 +
 .../utilities/rt-link/inc/rtlink_port.h       |   31 +
 .../utilities/rt-link/inc/rtlink_utils.h      |   21 +
 components/utilities/rt-link/src/SConscript   |   13 +
 components/utilities/rt-link/src/rtlink.c     | 1192 +++++++++++++++++
 components/utilities/rt-link/src/rtlink_hw.c  |  256 ++++
 .../utilities/rt-link/src/rtlink_utils.c      |   90 ++
 examples/rt-link/rtlink_example.c             |  189 +++
 14 files changed, 2135 insertions(+)
 create mode 100644 components/utilities/rt-link/Kconfig
 create mode 100644 components/utilities/rt-link/SConscript
 create mode 100644 components/utilities/rt-link/hw_port/SConscript
 create mode 100644 components/utilities/rt-link/hw_port/uart/rtlink_port_uart.c
 create mode 100644 components/utilities/rt-link/inc/rtlink.h
 create mode 100644 components/utilities/rt-link/inc/rtlink_hw.h
 create mode 100644 components/utilities/rt-link/inc/rtlink_port.h
 create mode 100644 components/utilities/rt-link/inc/rtlink_utils.h
 create mode 100644 components/utilities/rt-link/src/SConscript
 create mode 100644 components/utilities/rt-link/src/rtlink.c
 create mode 100644 components/utilities/rt-link/src/rtlink_hw.c
 create mode 100644 components/utilities/rt-link/src/rtlink_utils.c
 create mode 100644 examples/rt-link/rtlink_example.c

diff --git a/components/utilities/Kconfig b/components/utilities/Kconfig
index 8b733ecf5c..39bb970f6b 100644
--- a/components/utilities/Kconfig
+++ b/components/utilities/Kconfig
@@ -205,4 +205,6 @@ config RT_USING_UTEST
             default 20
     endif
 
+source "$RTT_DIR/components/utilities/rt-link/Kconfig"
+
 endmenu
diff --git a/components/utilities/rt-link/Kconfig b/components/utilities/rt-link/Kconfig
new file mode 100644
index 0000000000..10ed129e69
--- /dev/null
+++ b/components/utilities/rt-link/Kconfig
@@ -0,0 +1,40 @@
+# Kconfig file for rt_link
+menuconfig RT_USING_RT_LINK
+    bool "RT-Link"
+    default n
+
+if RT_USING_RT_LINK
+    choice
+        prompt"use hw crc device or not"
+        default RT_LINK_USING_SF_CRC
+        
+        config RT_LINK_USING_SF_CRC
+            bool "use software crc table"
+        config RT_LINK_USING_HW_CRC
+            bool "use hardware crc device"
+    endchoice
+
+    menu "rt-link hardware device configuration"
+        config RT_LINK_HW_DEVICE_NAME
+            string "the name of base actual device"
+            default "uart2"
+
+        choice
+            prompt"hardware device is spi, uart or usb"
+            default RT_LINK_USING_UART
+
+            config RT_LINK_USING_UART
+                bool "use UART"
+        endchoice
+
+    endmenu
+
+    menu "rt link debug option"
+        config USING_RT_LINK_DEBUG
+            bool "Enable RT-Link debug"
+            default n
+        config USING_RT_LINK_HW_DEBUG
+            bool "Enable RT-Link hw debug"
+            default n
+    endmenu
+endif
diff --git a/components/utilities/rt-link/SConscript b/components/utilities/rt-link/SConscript
new file mode 100644
index 0000000000..4c815c49b8
--- /dev/null
+++ b/components/utilities/rt-link/SConscript
@@ -0,0 +1,15 @@
+# RT-Thread building script for bridge
+
+import os
+from building import *
+
+cwd = GetCurrentDir()
+objs = []
+list = os.listdir(cwd)
+
+for d in list:
+    path = os.path.join(cwd, d)
+    if os.path.isfile(os.path.join(path, 'SConscript')):
+        objs = objs + SConscript(os.path.join(d, 'SConscript'))
+
+Return('objs')
diff --git a/components/utilities/rt-link/hw_port/SConscript b/components/utilities/rt-link/hw_port/SConscript
new file mode 100644
index 0000000000..e34243ebda
--- /dev/null
+++ b/components/utilities/rt-link/hw_port/SConscript
@@ -0,0 +1,14 @@
+import os
+from building import *
+import rtconfig
+
+cwd  = GetCurrentDir()
+src  = []
+CPPPATH = []
+
+if GetDepend('RT_LINK_USING_UART'):
+    src += ['uart/rtlink_port_uart.c']
+
+group = DefineGroup('rt-link-port', src, depend = ['RT_USING_RT_LINK'], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/components/utilities/rt-link/hw_port/uart/rtlink_port_uart.c b/components/utilities/rt-link/hw_port/uart/rtlink_port_uart.c
new file mode 100644
index 0000000000..48fbb91bc3
--- /dev/null
+++ b/components/utilities/rt-link/hw_port/uart/rtlink_port_uart.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-12-09     xiangxistu   the first version
+ */
+
+#include 
+#include 
+
+#include 
+
+#ifndef RT_LINK_HW_DEVICE_NAME
+    #define RT_LINK_HW_DEVICE_NAME "uart2"
+#endif
+
+#define DBG_TAG              "rtlink_port"
+#define DBG_LVL              DBG_INFO
+#include 
+
+static struct rt_device *hw_device = RT_NULL;
+rt_err_t rt_link_port_rx_ind(rt_device_t device, rt_size_t size)
+{
+    RT_ASSERT(device != RT_NULL);
+
+    rt_uint8_t buffer[RT_SERIAL_RB_BUFSZ] = {0};
+    rt_size_t length = 0;
+    length = rt_device_read(device, 0, buffer, sizeof(buffer));
+    rt_link_hw_write_cb(&buffer, length);
+    return RT_EOK;
+}
+
+rt_size_t rt_link_port_send(void *data, rt_size_t length)
+{
+    rt_size_t size = 0;
+    size = rt_device_write(hw_device, 0, data, length);
+    return size;
+}
+
+int rt_link_port_init(void)
+{
+    hw_device = rt_device_find(RT_LINK_HW_DEVICE_NAME);
+    if (hw_device)
+    {
+        rt_device_open(hw_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
+        rt_device_set_rx_indicate(hw_device, rt_link_port_rx_ind);
+    }
+    else
+    {
+        LOG_E("Not find device %s", RT_LINK_HW_DEVICE_NAME);
+        return -RT_ERROR;
+    }
+    return RT_EOK;
+}
+
+int rt_link_port_deinit(void)
+{
+    hw_device = rt_device_find(RT_LINK_HW_DEVICE_NAME);
+    if (hw_device)
+    {
+        rt_device_close(hw_device);
+        rt_device_set_rx_indicate(hw_device, RT_NULL);
+    }
+    else
+    {
+        LOG_E("Not find device %s", RT_LINK_HW_DEVICE_NAME);
+        return -RT_ERROR;
+    }
+    return RT_EOK;
+}
diff --git a/components/utilities/rt-link/inc/rtlink.h b/components/utilities/rt-link/inc/rtlink.h
new file mode 100644
index 0000000000..dd98b57c30
--- /dev/null
+++ b/components/utilities/rt-link/inc/rtlink.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-02-02     xiangxistu   the first version
+ * 2021-03-19     Sherman      Streamline the struct rt_link_session
+ */
+
+#ifndef __RT_LINK_H__
+#define __RT_LINK_H__
+
+#include 
+
+#define RT_LINK_AUTO_INIT
+
+#define RT_LINK_FRAME_HEAD                 0x15
+#define RT_LINK_FRAME_HEAD_MASK            0x1F
+#define RT_LINK_MAX_DATA_LENGTH            2044 /*can exact divide by 4 bytes*/
+#define RT_LINK_FRAMES_MAX   0x03   /* The maximum number of split frames for a long package*/
+
+#define RT_LINK_ACK_MAX   0x07
+#define RT_LINK_CRC_LENGTH          4
+#define RT_LINK_HEAD_LENGTH         4
+#define RT_LINK_MAX_EXTEND_LENGTH       4
+#define RT_LINK_MAX_FRAME_LENGTH        (RT_LINK_HEAD_LENGTH + RT_LINK_MAX_EXTEND_LENGTH + RT_LINK_MAX_DATA_LENGTH + RT_LINK_CRC_LENGTH)
+#define RT_LINK_RECEIVE_BUFFER_LENGTH       (RT_LINK_MAX_FRAME_LENGTH * RT_LINK_FRAMES_MAX + RT_LINK_HEAD_LENGTH + RT_LINK_MAX_EXTEND_LENGTH)
+
+typedef enum
+{
+    RT_LINK_SERVICE_RTLINK = 0,
+    RT_LINK_SERVICE_LINK_SOCKET = 1,
+    RT_LINK_SERVICE_LINK_WIFI = 2,
+    RT_LINK_SERVICE_LINK_MNGT = 3,
+    RT_LINK_SERVICE_LINK_MSHTOOLS = 4,
+    RT_LINK_SERVICE_MAX
+} rt_link_service_t;
+
+enum
+{
+    FRAME_EXTEND = 1 << 0,
+    FRAME_CRC    = 1 << 1,
+    FRAME_ACK    = 1 << 2
+};
+
+typedef enum
+{
+    RT_LINK_RESERVE_FRAME = 0,
+
+    RT_LINK_RESEND_FRAME,
+    RT_LINK_CONFIRM_FRAME,
+    RT_LINK_SHORT_DATA_FRAME,
+    RT_LINK_LONG_DATA_FRAME,
+    RT_LINK_SESSION_END,  /* The retring failed to end the session */
+
+    RT_LINK_HANDSHAKE_FRAME
+} rt_link_frame_attribute_t;
+
+typedef enum
+{
+    /* receive event */
+    RT_LINK_READ_CHECK_EVENT            = 1 << 0,
+    RT_LINK_RECV_TIMEOUT_FRAME_EVENT    = 1 << 1,
+    RT_LINK_RECV_TIMEOUT_LONG_EVENT     = 1 << 2,
+
+    /* send event */
+    RT_LINK_SEND_READY_EVENT    = 1 << 4,
+    RT_LINK_SEND_OK_EVENT       = 1 << 5,
+    RT_LINK_SEND_FAILED_EVENT   = 1 << 6,
+    RT_LINK_SEND_TIMEOUT_EVENT  = 1 << 7
+} rt_link_notice_t;
+
+typedef enum
+{
+    RT_LINK_ESTABLISHING = 0,
+    RT_LINK_NO_RESPONSE,
+    RT_LINK_CONNECT_DONE,
+} rt_link_linkstatus_t;
+
+typedef enum
+{
+    RECVTIMER_NONE = 0,
+    RECVTIMER_FRAME,
+    RECVTIMER_LONGFRAME
+} rt_link_recvtimer_status_t;
+
+struct rt_link_receive_buffer
+{
+    rt_uint8_t data[RT_LINK_RECEIVE_BUFFER_LENGTH]; /* rt-link receive data buffer */
+    rt_uint8_t *read_point;
+    rt_uint8_t *write_point;
+    rt_uint8_t *end_point;
+};
+
+struct rt_link_frame_head
+{
+    rt_uint8_t magicid : 5;
+    rt_uint8_t extend  : 1;
+    rt_uint8_t crc     : 1;
+    rt_uint8_t ack     : 1;
+    rt_uint8_t sequence;
+    rt_uint16_t channel: 5;
+    rt_uint16_t length : 11;
+};
+
+/* record frame information that opposite */
+struct rt_link_record
+{
+    rt_uint8_t rx_seq; /* record the opposite sequence */
+    rt_uint8_t total;       /* the number of long frame number */
+    rt_uint8_t long_count;  /* long packet recv counter */
+    rt_uint8_t *dataspace;  /* the space of long frame */
+};
+
+struct rt_link_extend
+{
+    rt_uint16_t attribute;           /* rt_link_frame_attribute_t */
+    rt_uint16_t parameter;
+};
+
+struct rt_link_frame
+{
+    struct rt_link_frame_head head;         /* frame head */
+    struct rt_link_extend extend;           /* frame extend data */
+    rt_uint8_t *real_data;                  /* the origin data */
+    rt_uint32_t crc;                        /* CRC result */
+
+    rt_uint16_t data_len;         /* the length of frame length */
+    rt_uint16_t attribute;        /* this will show frame attribute , rt_link_frame_attribute_t */
+
+    rt_uint8_t index;              /* the index frame for long frame */
+    rt_uint8_t total;               /* the total frame for long frame */
+
+    rt_slist_t slist;            /* the frame will hang on the send list on session */
+};
+
+struct rt_link_service
+{
+    rt_err_t (*upload_callback)(void *data, rt_size_t size);
+};
+
+struct rt_link_session
+{
+    rt_link_linkstatus_t link_status;   /* Link connection status*/
+    struct rt_event event;      /* the event that core logic */
+    struct rt_link_service channel[RT_LINK_SERVICE_MAX]; /* thansfer to app layer */
+
+    rt_slist_t tx_data_slist;
+    rt_uint8_t tx_seq;     /* sequence for frame */
+    struct rt_mutex tx_lock;    /* protect send data interface, only one thread can hold it */
+    struct rt_timer sendtimer;  /* send function timer for rt link */
+
+    struct rt_link_record rx_record;    /* the memory of receive status */
+    struct rt_timer recvtimer;          /* receive a frame timer for rt link */
+    struct rt_timer longframetimer;     /* receive long frame timer for rt link */
+
+    struct rt_link_receive_buffer *rx_buffer; /* the buffer will store data */
+    rt_uint32_t (*calculate_crc)(rt_uint8_t using_buffer_ring, rt_uint8_t *data, rt_size_t size); /* this function will calculate crc */
+};
+
+/* rtlink init and deinit */
+int rt_link_init(void);
+rt_err_t rt_link_deinit(void);
+/* rtlink send data interface */
+rt_size_t rt_link_send(rt_link_service_t service, void *data, rt_size_t size);
+/* rtlink service attach and detach */
+rt_err_t rt_link_service_attach(rt_link_service_t service, rt_err_t (*function)(void *data, rt_size_t size));
+rt_err_t rt_link_service_detach(rt_link_service_t service);
+
+/* Private operator function */
+struct rt_link_session *rt_link_get_scb(void);
+
+#endif /* __RT_LINK_H__ */
diff --git a/components/utilities/rt-link/inc/rtlink_hw.h b/components/utilities/rt-link/inc/rtlink_hw.h
new file mode 100644
index 0000000000..c75609a23a
--- /dev/null
+++ b/components/utilities/rt-link/inc/rtlink_hw.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-02-02     xiangxistu   the first version
+ *
+ */
+#ifndef __RT_LINK_HW_H__
+#define __RT_LINK_HW_H__
+
+#include 
+
+rt_size_t rt_link_hw_recv_len(struct rt_link_receive_buffer *buffer);
+void rt_link_hw_copy(rt_uint8_t *dst, rt_uint8_t *src, rt_size_t count);
+void rt_link_hw_buffer_point_shift(rt_uint8_t **pointer_address, rt_size_t length);
+
+rt_err_t rt_link_hw_init(void);
+rt_err_t rt_link_hw_deinit(void);
+rt_err_t rt_link_hw_send(void *data, rt_size_t length);
+
+#endif /* _RT_LINK_PORT_INTERNAL_H_ */
diff --git a/components/utilities/rt-link/inc/rtlink_port.h b/components/utilities/rt-link/inc/rtlink_port.h
new file mode 100644
index 0000000000..54a064d117
--- /dev/null
+++ b/components/utilities/rt-link/inc/rtlink_port.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-02-02     xiangxistu   the first version
+ * 2021-05-15     Sherman      function rename
+ */
+#ifndef __RT_LINK_PORT_H__
+#define __RT_LINK_PORT_H__
+
+#include 
+
+/* Functions that need to be implemented at the hardware */
+int rt_link_port_init(void);
+int rt_link_port_deinit(void);
+rt_size_t rt_link_port_send(void *data, rt_size_t length);
+
+#ifdef RT_LINK_USING_HW_CRC
+    rt_err_t rt_link_hw_crc32_init(void);
+    rt_err_t rt_link_hw_crc32_deinit(void);
+    rt_err_t rt_link_hw_crc32_reset(void);
+    rt_uint32_t rt_link_hw_crc32(rt_uint8_t *data, rt_size_t u32_size)
+#endif
+
+/* Called when the hardware receives data and the data is transferred to RTLink */
+rt_size_t rt_link_hw_write_cb(void *data, rt_size_t length);
+
+#endif /* __RT_LINK_PORT_H__ */
diff --git a/components/utilities/rt-link/inc/rtlink_utils.h b/components/utilities/rt-link/inc/rtlink_utils.h
new file mode 100644
index 0000000000..564039c390
--- /dev/null
+++ b/components/utilities/rt-link/inc/rtlink_utils.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-05-15     Sherman      the first version
+ */
+#ifndef __RT_LINK_UTILITIES_H__
+#define __RT_LINK_UTILITIES_H__
+
+#include 
+
+/* Calculate the number of '1' */
+int rt_link_utils_num1(rt_uint32_t n);
+
+rt_err_t rt_link_sf_crc32_reset(void);
+rt_uint32_t rt_link_sf_crc32(rt_uint8_t *data, rt_size_t len);
+
+#endif /* __RT_LINK_UTILITIES_H__ */
diff --git a/components/utilities/rt-link/src/SConscript b/components/utilities/rt-link/src/SConscript
new file mode 100644
index 0000000000..8bbb969b2a
--- /dev/null
+++ b/components/utilities/rt-link/src/SConscript
@@ -0,0 +1,13 @@
+Import('rtconfig')
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+CPPPATH = [cwd + '/../inc']
+
+group = DefineGroup('rt-link', src, depend = ['RT_USING_RT_LINK'], CPPPATH = CPPPATH)
+
+if os.path.isfile(os.path.join(cwd, 'hw', 'SConscript')):
+    group = group + SConscript(os.path.join('hw', 'SConscript'))
+
+Return('group')
diff --git a/components/utilities/rt-link/src/rtlink.c b/components/utilities/rt-link/src/rtlink.c
new file mode 100644
index 0000000000..37a99538b6
--- /dev/null
+++ b/components/utilities/rt-link/src/rtlink.c
@@ -0,0 +1,1192 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-02-02     xiangxistu   the first version
+ * 2021-03-19     Sherman      Optimize the transfer process
+ * 2021-04-20     Sherman      Optimize memory footprint
+ * 2021-05-10     Sherman      Add rtlink_status  MSH command; Optimize transmission timer Settings; Fix known bugs
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#define DBG_ENABLE
+#ifdef USING_RT_LINK_DEBUG
+    #define DBG_LVL DBG_LOG
+#else
+    #define DBG_LVL DBG_INFO
+#endif
+#define DBG_TAG "rtlink"
+#define DBG_COLOR
+#include 
+
+#ifdef RT_LINK_USING_SPI
+    #define RT_LINK_LONG_FRAME_TIMEOUT      50
+    #define RT_LINK_SENT_FRAME_TIMEOUT      100
+#else
+    #define RT_LINK_LONG_FRAME_TIMEOUT      100
+    #define RT_LINK_SENT_FRAME_TIMEOUT      200
+#endif /* RT_LINK_USING_SPI */
+
+#define RT_LINK_RECV_DATA_SEQUENCE      0
+#define RT_LINK_INIT_FRAME_SEQENCE      129
+
+#define RT_LINK_THREAD_NAME "rtlink"
+#define RT_LINK_THREAD_TICK    20
+#define RT_LINK_THREAD_PRIORITY    15
+#define RT_LINK_THREAD_STACK_SIZE      832 /* 32 bytes aligned */
+
+typedef enum
+{
+    FIND_FRAME_HEAD = 0,
+    PARSE_FRAME_HEAD,
+    PARSE_FRAME_EXTEND,
+    PARSE_FRAME_SEQ,
+    CHECK_FRAME_CRC,
+    HEADLE_FRAME_DATA,
+} rt_link_frame_parse_t;
+
+/* rtlink SCB(Session control block) */
+static struct rt_link_session *rt_link_scb = RT_NULL;
+struct rt_link_session *rt_link_get_scb(void)
+{
+    return rt_link_scb;
+}
+
+static rt_int16_t rt_link_check_seq(rt_uint8_t new, rt_uint8_t used)
+{
+    rt_int16_t compare_seq = 0;
+    compare_seq = new - used;
+    if (compare_seq < 0)
+    {
+        compare_seq = compare_seq + 256;
+    }
+    return compare_seq;
+}
+
+static int rt_link_frame_init(struct rt_link_frame *frame, rt_uint8_t config)
+{
+    if (frame == RT_NULL)
+    {
+        return -RT_ERROR;
+    }
+
+    /* set frame control information */
+    rt_memset(&frame->head, 0, sizeof(struct rt_link_frame_head));
+    if (config & FRAME_CRC)
+    {
+        frame->head.crc = 1;
+    }
+    if (config & FRAME_ACK)
+    {
+        frame->head.ack = 1;
+    }
+
+    frame->head.magicid = RT_LINK_FRAME_HEAD;
+    /* frame data information */
+    rt_memset(&frame->extend, 0, sizeof(struct rt_link_extend));
+    frame->crc = 0;
+    frame->real_data = RT_NULL;
+    frame->data_len = 0;
+    frame->index = 0;
+    frame->total = 0;
+    frame->attribute = RT_LINK_RESERVE_FRAME;
+
+    rt_slist_init(&frame->slist);
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_link_frame_free(struct rt_link_frame *frame)
+{
+    if (frame == RT_NULL)
+    {
+        return -RT_ERROR;
+    }
+
+    if (frame->real_data != RT_NULL)
+    {
+        rt_free(frame->real_data);
+        frame->real_data = RT_NULL;
+    }
+    rt_memset(frame, 0, sizeof(struct rt_link_frame));
+    rt_free(frame);
+    return RT_EOK;
+}
+
+/* performs data transmission */
+static rt_err_t rt_link_frame_send(rt_slist_t *slist)
+{
+    struct rt_link_frame *frame = RT_NULL;
+    rt_uint8_t *origin_data = RT_NULL;
+    rt_uint8_t *data = RT_NULL;
+    rt_size_t length = 0;
+    rt_uint8_t send_max = RT_LINK_ACK_MAX;  /* The number of '1' in the binary number */
+
+    /* if slist is tx_data_slist, we should send all data on the slist*/
+    if (slist == &rt_link_scb->tx_data_slist)
+    {
+        slist = rt_slist_next(&rt_link_scb->tx_data_slist);
+    }
+    if (slist == RT_NULL)
+    {
+        LOG_W("tx_data_slist NULL");
+        return -RT_ERROR;
+    }
+    data = rt_malloc(RT_LINK_MAX_FRAME_LENGTH);
+    if (data == RT_NULL)
+    {
+        LOG_E("rt link alloc memory(%d B) failed, send frame failed.", RT_LINK_MAX_FRAME_LENGTH);
+        return -RT_ENOMEM;
+    }
+    origin_data = data;
+
+    do
+    {
+        /* get frame for send */
+        frame = rt_container_of(slist, struct rt_link_frame, slist);
+        slist = rt_slist_next(slist);
+
+        length = RT_LINK_HEAD_LENGTH;
+        if (frame->head.crc)
+        {
+            length += RT_LINK_CRC_LENGTH;
+        }
+        if (frame->head.extend)
+        {
+            length += RT_LINK_MAX_EXTEND_LENGTH;
+        }
+
+        length += frame->data_len;
+        frame->head.length = frame->data_len;
+        rt_memcpy(data, &frame->head, RT_LINK_HEAD_LENGTH);
+        data = data + RT_LINK_HEAD_LENGTH;
+        if (frame->head.extend)
+        {
+            rt_memcpy(data, &frame->extend, RT_LINK_MAX_EXTEND_LENGTH);
+            data = data + RT_LINK_MAX_EXTEND_LENGTH;
+        }
+        if (frame->attribute == RT_LINK_SHORT_DATA_FRAME || frame->attribute == RT_LINK_LONG_DATA_FRAME)
+        {
+            rt_memcpy(data, frame->real_data, frame->data_len);
+            data = data + frame->data_len;
+        }
+        if (frame->head.crc)
+        {
+            frame->crc = rt_link_scb->calculate_crc(RT_FALSE, origin_data, length - RT_LINK_CRC_LENGTH);
+            rt_memcpy(data, &frame->crc, RT_LINK_CRC_LENGTH);
+        }
+
+        LOG_D("frame send(%d) len(%d) attr:(%d), crc:(0x%08x).", frame->head.sequence, length, frame->attribute, frame->crc);
+        rt_link_hw_send(origin_data, length);
+
+        data = origin_data;
+        if (slist == RT_NULL)
+        {
+            send_max = 0;
+        }
+        send_max >>= 1;
+    }while (send_max);
+    rt_free(origin_data);
+    return RT_EOK;
+}
+
+static void _stop_recv_long(void)
+{
+    rt_timer_stop(&rt_link_scb->longframetimer);
+    if (rt_link_scb->rx_record.dataspace != RT_NULL)
+    {
+        rt_free(rt_link_scb->rx_record.dataspace);
+        rt_link_scb->rx_record.dataspace = RT_NULL;
+    }
+    rt_link_scb->rx_record.long_count = 0;
+    rt_link_scb->rx_record.total = 0;
+}
+
+static rt_err_t rt_link_frame_stop_receive(struct rt_link_frame *frame)
+{
+    rt_memset(frame, 0, sizeof(struct rt_link_frame));
+    rt_link_hw_buffer_point_shift(&rt_link_scb->rx_buffer->read_point, rt_link_hw_recv_len(rt_link_scb->rx_buffer));
+    return RT_EOK;
+}
+
+/* Configure the extended field of the frame */
+static rt_err_t rt_link_frame_extend_config(struct rt_link_frame *frame, rt_link_frame_attribute_t attribute, rt_uint16_t parameter)
+{
+    frame->head.extend = 1;
+    frame->extend.attribute = attribute;
+    frame->extend.parameter = parameter;
+    return RT_EOK;
+}
+
+static int rt_link_command_frame_send(rt_uint8_t sequence, rt_link_frame_attribute_t attribute, rt_uint16_t parameter)
+{
+    struct rt_link_frame command_frame = {0};
+    rt_uint8_t extend_flag = RT_FALSE;
+
+    /* command frame don't need crc and ack ability */
+    rt_link_frame_init(&command_frame, RT_NULL);
+    command_frame.head.sequence = sequence;
+    command_frame.head.length = RT_LINK_MAX_EXTEND_LENGTH;
+    command_frame.attribute = attribute;
+    switch (attribute)
+    {
+    case RT_LINK_RESEND_FRAME:
+        extend_flag = RT_TRUE;
+        LOG_D("send RESEND_FRAME(%d).", command_frame.head.sequence);
+        break;
+
+    case RT_LINK_HANDSHAKE_FRAME:
+        extend_flag = RT_TRUE;
+        LOG_D("send HANDSHAKE_FRAME(%d).", command_frame.head.sequence);
+        break;
+
+    case RT_LINK_CONFIRM_FRAME:
+        LOG_D("send CONFIRM_FRAME(%d).", command_frame.head.sequence);
+        break;
+
+    default:
+        break;
+    }
+
+    if (extend_flag)
+    {
+        rt_link_frame_extend_config(&command_frame, attribute, parameter);
+    }
+    rt_link_frame_send(&command_frame.slist);
+    return RT_EOK;
+}
+
+static rt_err_t rt_link_resend_handle(struct rt_link_frame *receive_frame)
+{
+    struct rt_link_frame *find_frame = RT_NULL;
+    rt_slist_t *tem_list = RT_NULL;
+
+    tem_list = rt_slist_first(&rt_link_scb->tx_data_slist);
+    while (tem_list != RT_NULL)
+    {
+        find_frame = rt_container_of(tem_list, struct rt_link_frame, slist);
+        if (find_frame->head.sequence == receive_frame->head.sequence)
+        {
+            LOG_D("resend frame(%d)", find_frame->head.sequence);
+            rt_link_frame_send(&find_frame->slist);
+            break;
+        }
+        tem_list = tem_list->next;
+    }
+
+    if (tem_list == RT_NULL)
+    {
+        LOG_D("frame resent failed, can't find(%d).", receive_frame->head.sequence);
+        rt_link_command_frame_send(receive_frame->head.sequence, RT_LINK_SESSION_END, RT_NULL);
+    }
+    return RT_EOK;
+}
+
+static rt_err_t rt_link_confirm_handle(struct rt_link_frame *receive_frame)
+{
+    static struct rt_link_frame *send_frame = RT_NULL;
+    struct rt_link_frame *find_frame = RT_NULL;
+    rt_slist_t *tem_list = RT_NULL;
+    rt_uint16_t seq_offset = 0;
+
+    LOG_D("confirm seq(%d) frame", receive_frame->head.sequence);
+    if (rt_link_scb->link_status == RT_LINK_NO_RESPONSE)
+    {
+        /* The handshake success and resends the data frame */
+        LOG_D("link_status RT_LINK_CONNECT_DONE, resend data");
+        rt_link_scb->link_status = RT_LINK_CONNECT_DONE;
+        if (rt_slist_first(&rt_link_scb->tx_data_slist))
+        {
+            rt_event_send(&rt_link_scb->event, RT_LINK_SEND_READY_EVENT);
+        }
+        return RT_EOK;
+    }
+
+    /* Check to see if the frame is send for confirm */
+    tem_list = rt_slist_first(&rt_link_scb->tx_data_slist);
+    if (tem_list == RT_NULL)
+    {
+        return -RT_ERROR;
+    }
+
+    send_frame = rt_container_of(tem_list, struct rt_link_frame, slist);
+    seq_offset = rt_link_check_seq(receive_frame->head.sequence,
+                                   rt_link_scb->tx_seq);
+    if (seq_offset <= send_frame->total)
+    {
+        LOG_D("confirm frame (%d)", receive_frame->head.sequence);
+        for (int i = 0; i < seq_offset; i++)
+        {
+            find_frame = rt_container_of(tem_list, struct rt_link_frame, slist);
+            LOG_D("confirm(%d), remove(%d)", receive_frame->head.sequence, find_frame->head.sequence);
+
+            rt_enter_critical();
+            rt_slist_remove(&rt_link_scb->tx_data_slist, &find_frame->slist);
+            rt_exit_critical();
+            find_frame->real_data = RT_NULL;
+            rt_link_frame_free(find_frame);
+
+            tem_list = rt_slist_first(&rt_link_scb->tx_data_slist);
+            if (tem_list == RT_NULL)
+            {
+                break;
+            }
+        }
+        rt_link_scb->tx_seq = receive_frame->head.sequence;
+        rt_link_scb->link_status = RT_LINK_CONNECT_DONE;
+        if (tem_list == RT_NULL)
+        {
+            LOG_D("SEND_OK");
+            rt_event_send(&rt_link_scb->event, RT_LINK_SEND_OK_EVENT);
+        }
+        else
+        {
+            LOG_D("Continue sending");
+            rt_event_send(&rt_link_scb->event, RT_LINK_SEND_READY_EVENT);
+        }
+    }
+    return RT_EOK;
+}
+
+static rt_err_t rt_link_short_handle(struct rt_link_frame *receive_frame)
+{
+    LOG_D("Seq(%d) short data", receive_frame->head.sequence);
+    rt_link_scb->rx_record.dataspace = rt_malloc(receive_frame->data_len);
+    if (rt_link_scb->rx_record.dataspace != RT_NULL)
+    {
+        rt_link_command_frame_send(receive_frame->head.sequence, RT_LINK_CONFIRM_FRAME, RT_NULL);
+        rt_link_scb->rx_record.rx_seq = receive_frame->head.sequence;
+
+        if (rt_link_scb->channel[receive_frame->head.channel].upload_callback == RT_NULL)
+        {
+            rt_free(rt_link_scb->rx_record.dataspace);
+            LOG_E("Channel %d has not been registered", receive_frame->head.channel);
+        }
+        else
+        {
+            rt_enter_critical();
+            rt_link_hw_copy(rt_link_scb->rx_record.dataspace, receive_frame->real_data, receive_frame->data_len);
+            rt_exit_critical();
+            rt_link_scb->channel[receive_frame->head.channel].upload_callback(rt_link_scb->rx_record.dataspace, receive_frame->data_len);
+        }
+        rt_link_scb->rx_record.dataspace = RT_NULL;
+        rt_link_frame_stop_receive(receive_frame);
+    }
+    else
+    {
+        LOG_W("short data %dB alloc failed", receive_frame->data_len);
+    }
+    receive_frame->real_data = RT_NULL;
+    return 0;
+}
+
+static void _long_handle_first(struct rt_link_frame *receive_frame, rt_uint8_t *count_mask)
+{
+    if (receive_frame->extend.parameter % RT_LINK_MAX_DATA_LENGTH == 0)
+    {
+        receive_frame->total = receive_frame->extend.parameter / RT_LINK_MAX_DATA_LENGTH;
+    }
+    else
+    {
+        receive_frame->total = receive_frame->extend.parameter / RT_LINK_MAX_DATA_LENGTH + 1;
+    }
+
+    rt_link_scb->rx_record.total = receive_frame->total;
+    rt_link_scb->rx_record.dataspace = rt_malloc(receive_frame->extend.parameter);
+    if (rt_link_scb->rx_record.dataspace == RT_NULL)
+    {
+        LOG_W("long data %dB alloc failed.", receive_frame->extend.parameter);
+    }
+
+}
+
+static void _long_handle_second(struct rt_link_frame *receive_frame, rt_uint8_t count_mask)
+{
+    static rt_uint8_t ack_mask = RT_LINK_ACK_MAX;
+
+    void *data = RT_NULL;
+    rt_size_t size = 0;
+    rt_uint16_t serve = 0;
+    rt_size_t offset = 0; /* offset, count from 0 */
+
+    receive_frame->index = rt_link_check_seq(receive_frame->head.sequence, rt_link_scb->rx_record.rx_seq) - 1;
+    LOG_D("index= %d, count= 0x%x, seq(%d), rxseq(%d)", receive_frame->index, rt_link_scb->rx_record.long_count, receive_frame->head.sequence, rt_link_scb->rx_record.rx_seq);
+
+    if ((receive_frame->index > RT_LINK_FRAMES_MAX) || (rt_link_scb->rx_record.long_count & (0x01 << receive_frame->index)))
+    {
+        LOG_D("ERR:index %d, rx_seq %d", receive_frame->index, rt_link_scb->rx_record.rx_seq);
+    }
+    else if (rt_link_scb->rx_record.dataspace != RT_NULL)
+    {
+        LOG_D("long_count (0x%02x)index(%d)total(%d) seq(%d)", rt_link_scb->rx_record.long_count, receive_frame->index, receive_frame->total, receive_frame->head.sequence);
+        rt_link_scb->rx_record.long_count |= (0x01 << receive_frame->index);
+        offset = RT_LINK_MAX_DATA_LENGTH * receive_frame->index;
+
+        rt_enter_critical();
+        rt_link_hw_copy(rt_link_scb->rx_record.dataspace + offset, receive_frame->real_data, receive_frame->data_len);
+        rt_exit_critical();
+
+        if (rt_link_utils_num1(rt_link_scb->rx_record.long_count) == rt_link_scb->rx_record.total)
+        {
+            rt_link_command_frame_send((rt_link_scb->rx_record.rx_seq + rt_link_scb->rx_record.total), RT_LINK_CONFIRM_FRAME, RT_NULL);
+        }
+        else if ((rt_link_scb->rx_record.long_count & ack_mask) == ack_mask)
+        {
+            rt_link_command_frame_send((rt_link_scb->rx_record.rx_seq + rt_link_utils_num1(ack_mask)), RT_LINK_CONFIRM_FRAME, RT_NULL);
+            ack_mask |= ack_mask << rt_link_utils_num1(RT_LINK_ACK_MAX);
+        }
+
+        /* receive a complete package */
+        if (rt_link_utils_num1(rt_link_scb->rx_record.long_count) == rt_link_scb->rx_record.total)
+        {
+            rt_timer_stop(&rt_link_scb->longframetimer);
+
+            rt_enter_critical();
+            data = rt_link_scb->rx_record.dataspace;
+            size = receive_frame->extend.parameter;
+            serve = receive_frame->head.channel;
+            /* empty  rx_record */
+            rt_link_scb->rx_record.rx_seq += rt_link_scb->rx_record.total;
+            rt_link_scb->rx_record.dataspace = RT_NULL;
+            rt_link_scb->rx_record.long_count = 0;
+            rt_link_scb->rx_record.total = 0;
+            ack_mask = RT_LINK_ACK_MAX;
+            rt_link_frame_stop_receive(receive_frame);
+            rt_exit_critical();
+
+            if (rt_link_scb->channel[serve].upload_callback == RT_NULL)
+            {
+                rt_free(data);
+                LOG_E("channel %d haven't been registered.", serve);
+            }
+            else
+            {
+                rt_link_scb->channel[serve].upload_callback(data, size);
+            }
+        }
+        else if (rt_link_hw_recv_len(rt_link_scb->rx_buffer) < (receive_frame->data_len % RT_LINK_MAX_DATA_LENGTH))
+        {
+            rt_int32_t timeout = RT_LINK_LONG_FRAME_TIMEOUT;
+            rt_timer_control(&rt_link_scb->longframetimer, RT_TIMER_CTRL_SET_TIME, &timeout);
+            rt_timer_start(&rt_link_scb->longframetimer);
+        }
+    }
+}
+
+static rt_err_t rt_link_long_handle(struct rt_link_frame *receive_frame)
+{
+    static rt_uint8_t count_mask = 0;
+    if (rt_link_scb->rx_record.long_count == 0)
+    {
+        /* Receive this long package for the first time:
+         * calculates the total number of frames,
+         * requests space, and turns on the receive timer */
+        _long_handle_first(receive_frame, &count_mask);
+    }
+    if (rt_link_scb->rx_record.total > 0)
+    {
+        /* Intermediate frame processing:
+         * serial number repeated check,
+         * receive completion check, reply to ACK */
+        _long_handle_second(receive_frame, count_mask);
+    }
+    receive_frame->real_data = RT_NULL;
+    return RT_EOK;
+}
+
+static rt_err_t rt_link_handshake_handle(struct rt_link_frame *receive_frame)
+{
+    LOG_D("Sequence(%d) is a connect handshake frame.", receive_frame->head.sequence);
+    rt_link_scb->link_status = RT_LINK_CONNECT_DONE;
+    /* sync requester tx seq, responder rx seq = requester tx seq */
+    rt_link_scb->rx_record.rx_seq = receive_frame->head.sequence;
+    /* sync requester rx seq, responder tx seq = requester rx seq */
+    rt_link_scb->tx_seq = receive_frame->extend.parameter;
+    rt_link_command_frame_send(receive_frame->head.sequence, RT_LINK_CONFIRM_FRAME, RT_NULL);
+    return RT_EOK;
+}
+
+/* Discriminate frame type */
+static rt_err_t rt_link_parse_frame(struct rt_link_frame *receive_frame)
+{
+    switch (receive_frame->attribute)
+    {
+    case RT_LINK_RESEND_FRAME:
+        rt_link_resend_handle(receive_frame);
+        break;
+    case RT_LINK_CONFIRM_FRAME:
+        rt_link_confirm_handle(receive_frame);
+        break;
+    case RT_LINK_SHORT_DATA_FRAME:
+        rt_link_short_handle(receive_frame);
+        break;
+    case RT_LINK_LONG_DATA_FRAME:
+        rt_link_long_handle(receive_frame);
+        break;
+    case RT_LINK_HANDSHAKE_FRAME:
+        rt_link_handshake_handle(receive_frame);
+        break;
+    case RT_LINK_SESSION_END:
+        rt_link_frame_stop_receive(receive_frame);
+        break;
+    default:
+        break;
+    }
+    return RT_EOK;
+}
+
+/* Empty the sending list */
+static void rt_link_datalist_empty(void)
+{
+    struct rt_link_frame *find_frame = RT_NULL;
+    rt_slist_t *tem_list = rt_slist_first(&rt_link_scb->tx_data_slist);
+    while (tem_list != RT_NULL)
+    {
+        find_frame = rt_container_of(tem_list, struct rt_link_frame, slist);
+        tem_list = rt_slist_next(tem_list);
+        rt_enter_critical();
+        rt_slist_remove(&rt_link_scb->tx_data_slist, &find_frame->slist);
+        rt_exit_critical();
+
+        find_frame->real_data = RT_NULL;
+        rt_link_frame_free(find_frame);
+    }
+}
+
+/* RT_LINK_READ_CHECK_EVENT handle */
+static void rt_link_frame_check(void)
+{
+    static struct rt_link_frame receive_frame = {0};
+    static rt_link_frame_parse_t analysis_status = FIND_FRAME_HEAD;
+    static rt_uint8_t *data = RT_NULL;
+    static rt_uint16_t buff_len = RT_LINK_HEAD_LENGTH;
+
+    struct rt_link_frame *send_frame = RT_NULL;
+    rt_tick_t timeout = 0;
+    rt_uint8_t *real_data = RT_NULL;
+    rt_uint32_t temporary_crc = 0;
+
+    rt_uint8_t offset = 0;
+    rt_size_t recv_len = rt_link_hw_recv_len(rt_link_scb->rx_buffer);
+    while (recv_len > 0)
+    {
+        switch (analysis_status)
+        {
+        case FIND_FRAME_HEAD:
+        {
+            /* if we can't find frame head, throw that data */
+            if ((*rt_link_scb->rx_buffer->read_point & RT_LINK_FRAME_HEAD_MASK) == RT_LINK_FRAME_HEAD)
+            {
+                analysis_status = PARSE_FRAME_HEAD;
+                break;
+            }
+            rt_link_hw_buffer_point_shift(&rt_link_scb->rx_buffer->read_point, 1);
+            break;
+        }
+
+        case PARSE_FRAME_HEAD:
+        {
+            if (recv_len < buff_len)
+            {
+                LOG_D("The length is not enough,recv=%d buff=%d", recv_len, buff_len);
+                return ;
+            }
+            /* Data is an offset address */
+            data = rt_link_scb->rx_buffer->read_point;
+            rt_link_frame_init(&receive_frame, RT_NULL);
+            rt_link_hw_copy((rt_uint8_t *)&receive_frame.head, data, sizeof(struct rt_link_frame_head));
+            rt_link_hw_buffer_point_shift(&data, sizeof(struct rt_link_frame_head));
+            receive_frame.data_len = receive_frame.head.length;
+            LOG_D("check seq(%d) data len(%d).", receive_frame.head.sequence, receive_frame.data_len);
+
+            if (receive_frame.head.extend)
+            {
+                buff_len += RT_LINK_MAX_EXTEND_LENGTH;
+                analysis_status = PARSE_FRAME_EXTEND;
+            }
+            else
+            {
+                analysis_status = PARSE_FRAME_SEQ;
+            }
+        }
+
+        case PARSE_FRAME_EXTEND:
+        {
+            if (receive_frame.head.extend)
+            {
+                if (recv_len < buff_len)
+                {
+                    LOG_D("PARSE_FRAME_EXTEND: actual: %d, need: %d.", recv_len, buff_len);
+
+                    /* should set timer, control receive frame timeout, one shot */
+                    timeout = 50;
+                    rt_timer_control(&rt_link_scb->recvtimer, RT_TIMER_CTRL_SET_TIME, &timeout);
+                    rt_timer_start(&rt_link_scb->recvtimer);
+                    return;
+                }
+                rt_link_hw_copy((rt_uint8_t *)&receive_frame.extend, data, sizeof(struct rt_link_extend));
+                rt_link_hw_buffer_point_shift(&data, sizeof(struct rt_link_extend));
+                switch (receive_frame.extend.attribute)
+                {
+                case RT_LINK_RESEND_FRAME:
+                case RT_LINK_LONG_DATA_FRAME:
+                case RT_LINK_HANDSHAKE_FRAME:
+                    receive_frame.attribute = receive_frame.extend.attribute;
+                    break;
+                default:
+                    receive_frame.attribute = RT_LINK_RESERVE_FRAME;
+                    break;
+                }
+            }
+            else
+            {
+                if (receive_frame.head.crc)
+                {
+                    receive_frame.attribute = RT_LINK_SHORT_DATA_FRAME;
+                }
+                else
+                {
+                    receive_frame.attribute = RT_LINK_CONFIRM_FRAME;
+                }
+            }
+            if (receive_frame.attribute == RT_LINK_RESERVE_FRAME)
+            {
+                LOG_D("quick filter error frame.");
+                rt_link_frame_stop_receive(&receive_frame);
+                buff_len = RT_LINK_HEAD_LENGTH;
+                analysis_status = FIND_FRAME_HEAD;
+                break;
+            }
+            analysis_status = PARSE_FRAME_SEQ;
+        }
+
+        case PARSE_FRAME_SEQ:
+        {
+            if ((receive_frame.attribute == RT_LINK_CONFIRM_FRAME) || (receive_frame.attribute == RT_LINK_RESEND_FRAME))
+            {
+                offset = rt_link_check_seq(receive_frame.head.sequence, rt_link_scb->tx_seq);
+                if (rt_slist_first(&rt_link_scb->tx_data_slist) != RT_NULL)
+                {
+                    send_frame = rt_container_of(rt_link_scb->tx_data_slist.next, struct rt_link_frame, slist);
+                    if (offset > send_frame->total)
+                    {
+                        /* exceptional frame, ignore it */
+                        LOG_D("seq (%d) failed, tx_seq (%d).offset=(%d) total= (%d)", receive_frame.head.sequence, rt_link_scb->tx_seq, offset, send_frame->total);
+                        rt_link_frame_stop_receive(&receive_frame);
+                        buff_len = RT_LINK_HEAD_LENGTH;
+                        analysis_status = FIND_FRAME_HEAD;
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                offset = rt_link_check_seq(receive_frame.head.sequence, rt_link_scb->rx_record.rx_seq) - 1;
+                if ((offset > RT_LINK_FRAMES_MAX) && (receive_frame.attribute != RT_LINK_HANDSHAKE_FRAME))
+                {
+                    /* exceptional frame, ignore it */
+                    LOG_D("seq (%d) failed, rx_seq (%d) offset=(%d) attr= (%d) status (%d)", receive_frame.head.sequence, rt_link_scb->rx_record.rx_seq, offset, receive_frame.attribute, rt_link_scb->link_status);
+                    rt_link_frame_stop_receive(&receive_frame);
+                    buff_len = RT_LINK_HEAD_LENGTH;
+                    analysis_status = FIND_FRAME_HEAD;
+                    break;
+                }
+            }
+
+            buff_len += receive_frame.data_len;
+            if (receive_frame.head.crc)
+            {
+                buff_len += RT_LINK_CRC_LENGTH;
+                analysis_status = CHECK_FRAME_CRC;
+            }
+            else
+            {
+                analysis_status = HEADLE_FRAME_DATA;
+            }
+        }
+
+        case CHECK_FRAME_CRC:
+        {
+            if (receive_frame.head.crc)
+            {
+                if (recv_len < buff_len)
+                {
+                    /* should set timer, control receive frame timeout, one shot */
+                    timeout = 50;
+                    rt_timer_control(&rt_link_scb->recvtimer, RT_TIMER_CTRL_SET_TIME, &timeout);
+                    rt_timer_start(&rt_link_scb->recvtimer);
+                    return;
+                }
+
+                real_data = data;
+                rt_timer_stop(&rt_link_scb->recvtimer);
+                rt_link_hw_buffer_point_shift(&data, receive_frame.data_len);
+                rt_link_hw_copy((rt_uint8_t *)&receive_frame.crc, data, RT_LINK_CRC_LENGTH);
+                temporary_crc = rt_link_scb->calculate_crc(RT_TRUE, rt_link_scb->rx_buffer->read_point, buff_len - RT_LINK_CRC_LENGTH);
+                if (receive_frame.crc != temporary_crc)
+                {
+                    /* check failed. ready resent */
+                    LOG_D("CRC: calc:(0x%08x) ,recv:(0x%08x).", temporary_crc, receive_frame.crc);
+                    /* quick resent, when sequence is right, we can ask for reset this frame */
+                    rt_link_command_frame_send(receive_frame.head.sequence, RT_LINK_RESEND_FRAME, RT_NULL);
+
+                    /* throw the error frame */
+                    buff_len = RT_LINK_HEAD_LENGTH;
+                    rt_link_frame_stop_receive(&receive_frame);
+
+                    /* clear the frame information */
+                    analysis_status = FIND_FRAME_HEAD;
+                    break;
+                }
+                /* fill real data point */
+                receive_frame.real_data = real_data;
+            }
+            analysis_status = HEADLE_FRAME_DATA;
+        }
+
+        case HEADLE_FRAME_DATA:
+        {
+            rt_link_hw_buffer_point_shift(&rt_link_scb->rx_buffer->read_point, buff_len);
+            rt_link_parse_frame(&receive_frame);
+            data = RT_NULL;
+            buff_len = RT_LINK_HEAD_LENGTH;
+            analysis_status = FIND_FRAME_HEAD;
+            break;
+        }
+
+        default:
+            LOG_E("analysis_status is error.");
+            break;
+        }
+        recv_len = rt_link_hw_recv_len(rt_link_scb->rx_buffer);
+    }
+}
+
+static void rt_link_send_ready(void)
+{
+    if (rt_link_scb->link_status != RT_LINK_CONNECT_DONE)
+    {
+        rt_link_scb->link_status = RT_LINK_NO_RESPONSE;
+        rt_link_command_frame_send(rt_link_scb->tx_seq, RT_LINK_HANDSHAKE_FRAME, rt_link_scb->rx_record.rx_seq);
+    }
+    else
+    {
+        if (RT_EOK != rt_link_frame_send(&rt_link_scb->tx_data_slist))
+        {
+            rt_event_send(&rt_link_scb->event, RT_LINK_SEND_FAILED_EVENT);
+        }
+    }
+}
+
+static void rt_link_frame_recv_timeout(void)
+{
+    /* The receiving frame timeout and a new receive begins */
+    rt_link_hw_buffer_point_shift(&rt_link_scb->rx_buffer->read_point, rt_link_hw_recv_len(rt_link_scb->rx_buffer));
+}
+
+static void rt_link_send_timeout(void)
+{
+    static rt_uint8_t count = 0;
+    if (count++ > 5)
+    {
+        LOG_W("Send timeout, please check the link status!");
+        count = 0;
+        rt_event_send(&rt_link_scb->event, RT_LINK_SEND_FAILED_EVENT);
+    }
+    else
+    {
+        rt_timer_start(&rt_link_scb->sendtimer);
+        rt_link_command_frame_send(rt_link_scb->tx_seq, RT_LINK_HANDSHAKE_FRAME, rt_link_scb->rx_record.rx_seq);
+    }
+}
+
+static int rt_link_long_recv_timeout(void)
+{
+    static rt_uint8_t count = 0;
+    if (count++ > 5)
+    {
+        LOG_W("long package receive timeout");
+        count = 0;
+        _stop_recv_long();
+    }
+    else
+    {
+        for (rt_uint8_t total = rt_link_scb->rx_record.total; total > 0; total--)
+        {
+            if (((rt_link_scb->rx_record.long_count >> (total - 1)) & 0x01) == 0x00)
+            {
+                /* resend command */
+                rt_link_command_frame_send((rt_link_scb->rx_record.rx_seq + total), RT_LINK_RESEND_FRAME, RT_NULL);
+            }
+        }
+    }
+    return RT_EOK;
+}
+
+void rt_link_thread(void *parameter)
+{
+    rt_uint32_t recved = 0;
+    while (1)
+    {
+        rt_event_recv(&rt_link_scb->event, RT_LINK_READ_CHECK_EVENT |
+                      RT_LINK_SEND_READY_EVENT  |
+                      RT_LINK_SEND_TIMEOUT_EVENT |
+                      RT_LINK_RECV_TIMEOUT_FRAME_EVENT |
+                      RT_LINK_RECV_TIMEOUT_LONG_EVENT,
+                      RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
+                      RT_WAITING_FOREVER,
+                      &recved);
+
+        if (recved & RT_LINK_READ_CHECK_EVENT)
+        {
+            rt_link_frame_check();
+        }
+
+        if (recved & RT_LINK_SEND_READY_EVENT)
+        {
+            rt_link_send_ready();
+        }
+
+        if (recved & RT_LINK_SEND_TIMEOUT_EVENT)
+        {
+            rt_link_send_timeout();
+        }
+
+        if (recved & RT_LINK_RECV_TIMEOUT_FRAME_EVENT)
+        {
+            rt_link_frame_recv_timeout();
+        }
+
+        if (recved & RT_LINK_RECV_TIMEOUT_LONG_EVENT)
+        {
+            rt_link_long_recv_timeout();
+        }
+    }
+}
+
+static void rt_link_sendtimer_callback(void *parameter)
+{
+    rt_event_send(&rt_link_scb->event, RT_LINK_SEND_TIMEOUT_EVENT);
+}
+
+static void rt_link_recvtimer_callback(void *parameter)
+{
+    rt_event_send(&rt_link_scb->event, RT_LINK_RECV_TIMEOUT_FRAME_EVENT);
+}
+
+static void rt_link_receive_long_frame_callback(void *parameter)
+{
+    rt_event_send(&rt_link_scb->event, RT_LINK_RECV_TIMEOUT_LONG_EVENT);
+}
+
+/**
+ * rtlink send data interface
+ * @param service   Registered service channel, choose enum rt_link_service_t
+ * @param data      send data
+ * @param size      send data size
+ * @return The actual size of the data sent
+ * */
+rt_size_t rt_link_send(rt_link_service_t service, void *data, rt_size_t size)
+{
+    if ((size == 0) || (data == RT_NULL) || (service >= RT_LINK_SERVICE_MAX))
+    {
+        return 0;
+    }
+    rt_mutex_take(&rt_link_scb->tx_lock, RT_WAITING_FOREVER);
+
+    rt_uint32_t recved = 0;
+    rt_err_t result = RT_EOK;
+    rt_uint32_t timeout = 0;
+
+    rt_uint8_t total = 0; /* The total number of frames to send */
+    rt_uint8_t index = 0; /* The index of the split packet */
+    rt_size_t offset = 0; /* The offset of the send data */
+
+    struct rt_link_frame *send_frame = RT_NULL;
+    rt_link_frame_attribute_t attribute;
+    if (size % RT_LINK_MAX_DATA_LENGTH == 0)
+    {
+        total = size / RT_LINK_MAX_DATA_LENGTH;
+    }
+    else
+    {
+        total = size / RT_LINK_MAX_DATA_LENGTH + 1;
+    }
+
+    if (total > RT_LINK_FRAMES_MAX)
+    {
+        result = -RT_ENOMEM;
+        goto __exit;
+    }
+    else if (total > 1)
+    {
+        attribute =  RT_LINK_LONG_DATA_FRAME;
+    }
+    else
+    {
+        attribute = RT_LINK_SHORT_DATA_FRAME;
+    }
+
+    do
+    {
+        send_frame = rt_malloc(sizeof(struct rt_link_frame));
+        rt_link_frame_init(send_frame, FRAME_CRC | FRAME_ACK);
+        send_frame->head.sequence = rt_link_scb->tx_seq + 1 + index;
+        send_frame->head.channel = service;
+        send_frame->real_data = (rt_uint8_t *)data + offset;
+        send_frame->index = index;
+        send_frame->total = total;
+
+        if (attribute == RT_LINK_LONG_DATA_FRAME)
+        {
+            send_frame->attribute = RT_LINK_LONG_DATA_FRAME;
+            if (offset + RT_LINK_MAX_DATA_LENGTH > size)
+            {
+                send_frame->data_len = size - offset;
+            }
+            else
+            {
+                send_frame->data_len = RT_LINK_MAX_DATA_LENGTH;
+                offset += RT_LINK_MAX_DATA_LENGTH;
+            }
+
+            rt_link_frame_extend_config(send_frame, RT_LINK_LONG_DATA_FRAME, size);
+        }
+        else
+        {
+            send_frame->attribute = RT_LINK_SHORT_DATA_FRAME;
+            send_frame->data_len = size;
+        }
+
+        /* append the frame on the tail of list */
+        LOG_D("new data append on the send slist, seq(%d), len(%d).", send_frame->head.sequence, send_frame->data_len);
+        rt_slist_append(&rt_link_scb->tx_data_slist, &send_frame->slist);
+
+        index++;
+    }while(total > index);
+
+    timeout = RT_LINK_SENT_FRAME_TIMEOUT * total;
+    rt_timer_control(&rt_link_scb->sendtimer, RT_TIMER_CTRL_SET_TIME, &timeout);
+    rt_timer_start(&rt_link_scb->sendtimer);
+    /* Notify the core thread to send packet */
+    rt_event_send(&rt_link_scb->event, RT_LINK_SEND_READY_EVENT);
+
+    /* Wait for the packet to be sent successfully */
+    rt_event_recv(&rt_link_scb->event, RT_LINK_SEND_OK_EVENT | RT_LINK_SEND_FAILED_EVENT, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &recved);
+
+    if (recved & RT_LINK_SEND_OK_EVENT)
+    {
+        result = RT_EOK;
+    }
+    else if (recved & RT_LINK_SEND_FAILED_EVENT)
+    {
+        LOG_E("the data (%dB) send failed", size);
+        result = -RT_ERROR;
+    }
+    else
+    {
+        LOG_E("unexpected event.");
+        result = -RT_ERROR;
+    }
+__exit:
+    rt_timer_stop(&rt_link_scb->sendtimer);
+    /* Empty the sending list */
+    rt_link_datalist_empty();
+    rt_mutex_release(&rt_link_scb->tx_lock);
+    if (result == RT_EOK)
+    {
+        return size;
+    }
+    return result;
+}
+
+void rtlink_status(void)
+{
+    rt_kprintf("rtlink status:\n");
+    if (rt_link_scb != RT_NULL)
+    {
+        rt_kprintf("\tlink status=%d\n", rt_link_scb->link_status);
+
+        rt_kprintf("\trx seq=%d\n", rt_link_scb->rx_record.rx_seq);
+        rt_kprintf("\ttx seq=%d\n", rt_link_scb->tx_seq);
+        rt_kprintf("\trecv len=%d\n", rt_link_hw_recv_len(rt_link_scb->rx_buffer));
+
+        rt_tick_t state = 0;
+        rt_timer_control(&rt_link_scb->longframetimer, RT_TIMER_CTRL_GET_STATE, &state);
+        rt_kprintf("\tlong timer state=%d\n", state);
+        rt_timer_control(&rt_link_scb->sendtimer, RT_TIMER_CTRL_GET_STATE, &state);
+        rt_kprintf("\tsend timer state=%d\n", state);
+
+        rt_kprintf("\tevent set=0x%08x\n", rt_link_scb->event.set);
+        if (rt_link_scb->tx_data_slist.next)
+        {
+            rt_slist_t *data = RT_NULL;
+            rt_slist_for_each(data, &rt_link_scb->tx_data_slist)
+            {
+                rt_kprintf("\tsend data list: serv %u\t", ((struct rt_link_frame_head *)data)->channel);
+                rt_kprintf(" seq %u\t", ((struct rt_link_frame_head *)data)->sequence);
+                rt_kprintf(" len %u\n", ((struct rt_link_frame_head *)data)->length);
+            }
+        }
+        else
+        {
+            rt_kprintf("\tsend data list: NULL\n");
+        }
+
+        rt_uint8_t serv = sizeof(rt_link_scb->channel) / sizeof(struct rt_link_service);
+        while (serv--)
+        {
+            rt_kprintf("\tservices [%d](0x%p)\n", serv, rt_link_scb->channel[serv]);
+        }
+    }
+    else
+    {
+        rt_kprintf("status NULL, please check the initialization status!\n");
+    }
+}
+MSH_CMD_EXPORT(rtlink_status, Display RTLINK status);
+
+/**
+ * rtlink deinit the interface
+ * */
+rt_err_t rt_link_deinit(void)
+{
+    rt_enter_critical();
+    rt_link_hw_deinit();
+    if (rt_link_scb)
+    {
+        rt_timer_detach(&rt_link_scb->longframetimer);
+        rt_timer_detach(&rt_link_scb->sendtimer);
+        rt_timer_detach(&rt_link_scb->recvtimer);
+        rt_mutex_detach(&rt_link_scb->tx_lock);
+        rt_event_detach(&rt_link_scb->event);
+        rt_free(rt_link_scb);
+        rt_link_scb = RT_NULL;
+    }
+    rt_thread_t thread = rt_thread_find(RT_LINK_THREAD_NAME);
+    if (thread)
+    {
+        rt_thread_delete(thread);
+    }
+    rt_exit_critical();
+    return RT_EOK;
+}
+MSH_CMD_EXPORT(rt_link_deinit, rt link deinit);
+
+/**
+ * rtlink initializes the interface, usually automatically.
+ * @return int Function Execution Result
+ * */
+int rt_link_init(void)
+{
+    rt_err_t result = RT_EOK;
+    rt_thread_t thread = RT_NULL;
+
+    if (rt_link_scb != RT_NULL)
+    {
+        goto __exit;
+    }
+
+    rt_link_scb = rt_malloc(sizeof(struct rt_link_session));
+    if (rt_link_scb == RT_NULL)
+    {
+        result = -RT_ENOMEM;
+        goto __exit;
+    }
+
+    rt_memset(rt_link_scb, 0, sizeof(struct rt_link_session));
+    rt_event_init(&rt_link_scb->event, "lny_event", RT_IPC_FLAG_FIFO);
+    rt_event_control(&rt_link_scb->event, RT_IPC_CMD_RESET, RT_NULL);
+
+    rt_mutex_init(&rt_link_scb->tx_lock, "tx_lock", RT_IPC_FLAG_FIFO);
+    rt_timer_init(&rt_link_scb->sendtimer, "tx_time", rt_link_sendtimer_callback,
+                  RT_NULL, 0, RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_PERIODIC);
+    rt_timer_init(&rt_link_scb->recvtimer, "rx_time", rt_link_recvtimer_callback,
+                  RT_NULL, 0, RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT);
+    rt_timer_init(&rt_link_scb->longframetimer, "rxl_time", rt_link_receive_long_frame_callback,
+                  RT_NULL, 0, RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_PERIODIC);
+
+    rt_link_scb->link_status = RT_LINK_ESTABLISHING;
+
+    rt_link_scb->rx_record.rx_seq = 255;
+
+    rt_slist_init(&rt_link_scb->tx_data_slist);
+    rt_link_scb->tx_seq = RT_LINK_INIT_FRAME_SEQENCE;
+
+    /* create rtlink core work thread */
+    thread = rt_thread_create(RT_LINK_THREAD_NAME,
+                              rt_link_thread,
+                              RT_NULL,
+                              RT_LINK_THREAD_STACK_SIZE,
+                              RT_LINK_THREAD_PRIORITY,
+                              RT_LINK_THREAD_TICK);
+    if (thread == RT_NULL)
+    {
+        result = -RT_ENOMEM;
+        goto __exit;
+    }
+    rt_thread_startup(thread);
+    result = rt_link_hw_init();
+
+__exit:
+    if (result != RT_EOK)
+    {
+        LOG_E("rtlink init failed.");
+        rt_link_deinit();
+    }
+    else
+    {
+        LOG_I("rtlink init success.");
+    }
+    return result;
+}
+#ifdef RT_LINK_AUTO_INIT
+    INIT_ENV_EXPORT(rt_link_init);
+#endif
+MSH_CMD_EXPORT(rt_link_init, rt link init);
+
+/**
+ * rtlink service attach
+ * @param service   Registered service channel, choose enum rt_link_service_t
+ * @param function  receive callback function
+ * @return Function Execution Result
+ * */
+rt_err_t rt_link_service_attach(rt_link_service_t service, rt_err_t (*function)(void *data, rt_size_t size))
+{
+    if (service >= RT_LINK_SERVICE_MAX)
+    {
+        LOG_W("Invalid parameter.");
+        return -RT_ERROR;
+    }
+    rt_link_scb->channel[service].upload_callback = function;
+    LOG_I("rt link attach service[%02d].", service);
+    return RT_EOK;
+}
+
+/**
+ * rtlink service detach
+ * @param service   Registered service channel, choose enum rt_link_service_t
+ * @return rt_err_t Function Execution Result
+ * */
+rt_err_t rt_link_service_detach(rt_link_service_t service)
+{
+    if (service >= RT_LINK_SERVICE_MAX)
+    {
+        LOG_W("Invalid parameter.");
+        return -RT_ERROR;
+    }
+    rt_link_scb->channel[service].upload_callback = RT_NULL;
+    LOG_I("rt link detach service[%02d].", service);
+    return RT_EOK;
+}
diff --git a/components/utilities/rt-link/src/rtlink_hw.c b/components/utilities/rt-link/src/rtlink_hw.c
new file mode 100644
index 0000000000..9c4567ab63
--- /dev/null
+++ b/components/utilities/rt-link/src/rtlink_hw.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-02-02     xiangxistu   the first version
+ * 2021-05-08     Sherman      Optimize the operation function on the rt_link_receive_buffer
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#define DBG_TAG "rtlink_hw"
+#ifdef USING_RT_LINK_HW_DEBUG
+    #define DBG_LVL DBG_LOG
+#else
+    #define DBG_LVL DBG_INFO
+#endif
+#define DBG_COLOR
+#include 
+
+static struct rt_link_receive_buffer *rx_buffer = RT_NULL;
+
+struct rt_link_receive_buffer *rt_link_hw_buffer_init(void *parameter)
+{
+    rx_buffer = rt_malloc(sizeof(struct rt_link_receive_buffer));
+    if (rx_buffer != RT_NULL)
+    {
+        rt_memset(rx_buffer, 0, sizeof(struct rt_link_receive_buffer));
+        rx_buffer->read_point = rx_buffer->data;
+        rx_buffer->write_point = rx_buffer->data;
+        rx_buffer->end_point = rx_buffer->data + RT_LINK_RECEIVE_BUFFER_LENGTH; /* Point to memory that has no access rights */
+    }
+    else
+    {
+        LOG_E("receive buffer alloc failed, init failed.");
+    }
+
+    return rx_buffer;
+}
+
+static rt_size_t rt_link_hw_buffer_write(void *data, rt_size_t count)
+{
+    int surplus = 0;
+    if (rx_buffer == RT_NULL)
+    {
+        return 0;
+    }
+    /* (data)----(r)----(w)----(end) */
+    if (rx_buffer->write_point >= rx_buffer->read_point)
+    {
+        rt_size_t w2end = rx_buffer->end_point - rx_buffer->write_point;
+        surplus = RT_LINK_RECEIVE_BUFFER_LENGTH - (rx_buffer->write_point - rx_buffer->read_point);
+        count = count > surplus ? surplus : count;
+        if (count >= w2end)
+        {
+            rt_memcpy(rx_buffer->write_point, data, w2end);
+            rx_buffer->write_point = rx_buffer->data;
+
+            rt_memcpy(rx_buffer->write_point, (rt_uint8_t *)data + w2end, (count - w2end));
+            rx_buffer->write_point += (count - w2end);
+        }
+        else
+        {
+            rt_memcpy(rx_buffer->write_point, data, count);
+            rx_buffer->write_point += count;
+        }
+    }
+    else    /* (data)----(w)----(r)----(end) */
+    {
+        surplus = rx_buffer->read_point - rx_buffer->write_point;
+        count = count > surplus ? surplus : count;
+        rt_memcpy(rx_buffer->write_point, data, count);
+        rx_buffer->write_point += count;
+    }
+    return count;
+}
+
+/* increases buffer pointer by one and circle around if necessary */
+void rt_link_hw_buffer_point_shift(rt_uint8_t **pointer_address, rt_size_t length)
+{
+    rt_uint8_t *pointer = RT_NULL;
+
+    pointer = *pointer_address + length;
+    if (pointer >= rx_buffer->end_point)
+    {
+        rt_size_t offset = 0;
+        offset = pointer - rx_buffer->end_point;
+        *pointer_address = rx_buffer->data + offset;
+    }
+    else
+    {
+        *pointer_address = *pointer_address + length;
+    }
+}
+
+/* copy data from receive buffer */
+void rt_link_hw_copy(rt_uint8_t *dst, rt_uint8_t *src, rt_size_t count)
+{
+    rt_uint8_t *pointer = RT_NULL;
+
+    pointer = src + count;
+    if (pointer >= rx_buffer->end_point)
+    {
+        rt_size_t offset = 0;
+        offset = rx_buffer->end_point - src;
+        rt_memcpy(dst, src, offset);
+        rt_memcpy(dst + offset,  rx_buffer->data, pointer - rx_buffer->end_point);
+    }
+    else
+    {
+        rt_memcpy(dst, src, count);
+    }
+}
+
+/* Tells, how many chars are saved into the buffer */
+rt_size_t rt_link_hw_recv_len(struct rt_link_receive_buffer *buffer)
+{
+    if (buffer->write_point >= buffer->read_point)
+    {
+        return (buffer->write_point - buffer->read_point);
+    }
+    else
+    {
+        return (RT_LINK_RECEIVE_BUFFER_LENGTH - (buffer->read_point - buffer->write_point));
+    }
+}
+
+rt_err_t rt_link_reset_crc32(void)
+{
+#ifdef RT_LINK_USING_HW_CRC
+    return rt_link_hw_crc32_reset();
+#else
+    return rt_link_sf_crc32_reset();
+#endif
+}
+
+rt_uint32_t rt_link_crc32(rt_uint8_t *data, rt_size_t u32_size)
+{
+#ifdef RT_LINK_USING_HW_CRC
+    return rt_link_hw_crc32(data, u32_size);
+#else
+    return rt_link_sf_crc32(data, u32_size);
+#endif
+}
+
+rt_uint32_t rt_link_get_crc(rt_uint8_t using_buffer_ring, rt_uint8_t *data, rt_size_t size)
+{
+    rt_uint32_t crc32 = 0x0;
+    rt_size_t surplus = 0;
+
+    if (data == RT_NULL)
+    {
+        LOG_D("warning, the parameter error: %d, data: 0x%08d.", size, data);
+        return 0;
+    }
+
+    rt_link_reset_crc32();
+    if (using_buffer_ring == 1)
+    {
+        /* modify the missing character */
+        surplus = rx_buffer->end_point - data;
+        if (surplus >= size)
+        {
+            crc32 = rt_link_crc32(data, size);
+        }
+        else
+        {
+            rt_link_crc32(data, surplus);
+            crc32 = rt_link_crc32(rx_buffer->data, size - surplus);
+        }
+    }
+    else
+    {
+        crc32 = rt_link_crc32(data, size);
+    }
+    return crc32;
+}
+
+rt_err_t rt_link_hw_send(void *data, rt_size_t length)
+{
+    rt_size_t send_len = 0;
+    send_len = rt_link_port_send(data, length);
+    LOG_D("hw_send len= %d", send_len);
+    return send_len;
+}
+
+/* provide this function to hardware spi/uart/usb to store data */
+rt_size_t rt_link_hw_write_cb(void *data, rt_size_t length)
+{
+    /* write real data into rtlink receive buffer */
+    rt_size_t len = rt_link_hw_buffer_write(data, length);
+    struct rt_link_session *scb = rt_link_get_scb();
+    if (scb)
+    {
+        rt_event_send(&scb->event, RT_LINK_READ_CHECK_EVENT);
+    }
+    return len;
+}
+
+rt_err_t rt_link_hw_init(void)
+{
+    struct rt_link_session *scb = rt_link_get_scb();
+    if ((rx_buffer != RT_NULL) || (scb == RT_NULL))
+    {
+        return -RT_ERROR;
+    }
+
+    /* alloc receive buffer to store data */
+    if (rt_link_hw_buffer_init(RT_NULL) == RT_NULL)
+    {
+        return -RT_ENOMEM;
+    }
+    scb->rx_buffer = rx_buffer;
+    scb->calculate_crc = rt_link_get_crc;
+
+    rt_link_port_init();
+
+#ifdef LINK_LAYER_USING_HW_CRC
+    /* crc hardware device for mcu and node */
+    rt_link_hw_crc32_init();
+#endif
+
+    LOG_I("link layer hardware environment init successful.");
+    return RT_EOK;
+}
+
+rt_err_t rt_link_hw_deinit(void)
+{
+    if (rx_buffer)
+    {
+        rt_free(rx_buffer);
+        rx_buffer = RT_NULL;
+    }
+    struct rt_link_session *scb = rt_link_get_scb();
+    if (scb)
+    {
+        scb->rx_buffer = rx_buffer;
+        scb->calculate_crc = RT_NULL;
+    }
+    rt_link_port_deinit();
+
+#ifdef LINK_LAYER_USING_HW_CRC
+    /* crc hardware device for mcu and node */
+    rt_link_hw_crc32_deinit();
+#endif
+
+    LOG_I("rtlink hardware deinit successful.");
+    return RT_EOK;
+}
diff --git a/components/utilities/rt-link/src/rtlink_utils.c b/components/utilities/rt-link/src/rtlink_utils.c
new file mode 100644
index 0000000000..c5cfbb9422
--- /dev/null
+++ b/components/utilities/rt-link/src/rtlink_utils.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-05-15     Sherman      the first version
+ */
+
+#include 
+
+/* Calculate the number of '1' */
+int rt_link_utils_num1(rt_uint32_t n)
+{
+    int ret = 0;
+    while (n)
+    {
+        n &= n - 1;
+        ret++;
+    }
+    return ret;
+}
+
+#ifdef RT_LINK_USING_SF_CRC
+
+static rt_uint32_t crc = 0xffffffff;
+const rt_uint32_t crc_table[256] =
+{
+    0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419,
+    0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+    0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148,
+    0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0,
+    0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8,
+    0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+    0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF,
+    0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
+    0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87,
+    0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+    0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E,
+    0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162,
+    0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6,
+    0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+    0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D,
+    0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5,
+    0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525,
+    0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+    0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C,
+    0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
+    0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344,
+    0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+    0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43,
+    0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767,
+    0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3,
+    0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+    0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92,
+    0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226,
+    0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82,
+    0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+    0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1,
+    0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
+    0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661,
+    0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+    0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330,
+    0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8,
+    0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+rt_err_t rt_link_sf_crc32_reset(void)
+{
+    crc = 0xffffffff;
+    return RT_EOK;
+}
+
+rt_uint32_t rt_link_sf_crc32(rt_uint8_t *data, rt_size_t len)
+{
+    rt_uint32_t x, y;
+    x = 0;
+    y = 0;
+    rt_size_t i;
+
+    for (i = 0; i < len; i++)
+    {
+        y = (crc ^ data[i]) & 0xff;
+        x = crc_table[y];
+        crc = (crc >> 8) ^ x;
+    }
+    return (crc ^ 0xffffffff);
+}
+#endif /* RT_LINK_USING_SF_CRC */
diff --git a/examples/rt-link/rtlink_example.c b/examples/rt-link/rtlink_example.c
new file mode 100644
index 0000000000..7c70c25e6f
--- /dev/null
+++ b/examples/rt-link/rtlink_example.c
@@ -0,0 +1,189 @@
+
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-05-15     Sherman      the first version
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define DBG_ENABLE
+#define DBG_TAG "rtlink_exam"
+#define DBG_LVL DBG_INFO
+#include 
+
+#define TEST_CONTEXT    "This message is sent by RT-Link"
+
+enum
+{
+    NONE_TEST = 0,
+    SHORT_FRAME_TEST,
+    LONG_FRAME_TEST
+};
+
+void rt_link_speed_test(void *paremeter);
+static rt_uint8_t speed_test_type = NONE_TEST;
+
+rt_err_t rt_link_receive_example_callback(void *data, rt_size_t length)
+{
+    LOG_I("recv data %d",length);
+    LOG_HEX("example",8,data,length);
+    rt_free(data);	
+    return RT_EOK;
+}
+
+void create_thead_to_test_speed(rt_uint8_t mutil_num)
+{
+    rt_uint8_t i = 0;
+
+    LOG_D("Speed test type [%02d], mutil [%02d]", speed_test_type, mutil_num);
+    for(i = 0; i< mutil_num; i++)
+    {
+        rt_thread_t tid;
+        char tid_name[RT_NAME_MAX + 1] = {0};
+
+        rt_snprintf(tid_name, sizeof(tid_name), "lny_s%03d", i + 1);
+        tid = rt_thread_create(tid_name, rt_link_speed_test, RT_NULL, 1024, 20, 10);
+        rt_thread_startup(tid);
+        LOG_I("Speed test thread[%s] startup", tid_name);
+    }
+}
+
+void rt_link_speed_test(void *paremeter)
+{
+    int ret;
+    rt_uint8_t *send_buf, *data;
+    rt_size_t bufflen = 0;
+    rt_size_t sentlen = 0;
+    rt_size_t count = 0;
+    rt_tick_t tick1, tick2;
+    rt_size_t total = 0;
+    rt_uint32_t integer, decimal;
+
+    if(speed_test_type == SHORT_FRAME_TEST)
+    {
+        bufflen = 2044;
+    }
+    else
+    {
+        bufflen = 6132;
+    }
+
+    send_buf = rt_malloc(bufflen);
+    if(send_buf != RT_NULL)
+    {
+        data = send_buf;
+        for(count = 0;count < bufflen; count++)
+        {
+            *data++ = (count % 93 + 33);
+        }
+    }
+    else
+    {
+        rt_kprintf("speed of send buffer malloc failed.");
+        return;
+    }
+
+    tick1 = rt_tick_get();
+    while (speed_test_type)
+    {
+        ret = rt_link_send(RT_LINK_SERVICE_RTLINK, send_buf, bufflen);
+        if(ret > 0)
+        {
+            sentlen += ret;
+        }
+
+        tick2 = rt_tick_get();
+        if (tick2 - tick1 >= RT_TICK_PER_SECOND)//* 10
+        {
+            total = sentlen * RT_TICK_PER_SECOND / 125 / (tick2 - tick1);
+            integer = total/1000;
+            decimal = total%1000;
+            LOG_I("%d.%03d0 Mbps!", integer, decimal);
+            sentlen = 0;
+            tick1 = tick2;
+        }
+    }
+    rt_free(send_buf);
+    LOG_W("speed test end, type %d",speed_test_type);
+}
+
+
+int rt_link_example_send(int argc, char **argv)
+{
+    char *receive = RT_NULL;
+    rt_size_t length = 0;
+    rt_uint16_t count = 0;
+
+    if(argc == 1)
+    {
+        receive = rt_malloc(sizeof(TEST_CONTEXT));
+        rt_memcpy(receive, TEST_CONTEXT, sizeof(TEST_CONTEXT) - 1);
+        length = rt_link_send(RT_LINK_SERVICE_RTLINK, receive, sizeof(TEST_CONTEXT) - 1);
+        LOG_I("send data length: %d.", length);
+        rt_free(receive);
+    }
+        else if(argc >= 3)
+    {
+        if(strcmp(argv[1], "-l") == 0)
+        {
+            receive = rt_malloc(atoi((const char *)argv[2]));
+            for(count = 0;count < atoi((const char *)argv[2]); count++)
+            {
+                *receive++ = (count % 93 + 33);
+            }
+            length = rt_link_send(RT_LINK_SERVICE_RTLINK, receive - atoi((const char *)argv[2]), atoi((const char *)argv[2]));
+            rt_free(receive - atoi((const char *)argv[2]));
+
+            LOG_I("send data length: %d.", length);
+        }
+        else if(strcmp(argv[1], "-s") == 0)
+        {
+            if(speed_test_type == NONE_TEST)
+            {
+                rt_uint8_t mutil_num = 1;
+                if(argc > 3)
+                {
+                    mutil_num = atoi((const char *)argv[3]);
+                }
+
+                if(strncmp(argv[2], "-s", rt_strlen(argv[2])) == 0)
+                {
+                    speed_test_type = SHORT_FRAME_TEST;
+                }
+                else if(strncmp(argv[2], "-l", rt_strlen(argv[2])) == 0)
+                {
+                    speed_test_type = LONG_FRAME_TEST;
+                }
+                create_thead_to_test_speed(mutil_num);
+            }
+            else
+            {
+                speed_test_type = NONE_TEST;
+                LOG_I("set NONE_TEST");
+            }
+        }
+        else
+        {
+            LOG_E("Invalid parameter.");
+        }
+    }
+    
+    return 0;
+}
+MSH_CMD_EXPORT(rt_link_example_send, rt link layer send test);
+
+int rt_link_example_init(void)
+{
+
+    rt_link_service_attach(RT_LINK_SERVICE_RTLINK, rt_link_receive_example_callback);
+    return RT_EOK;
+}
+MSH_CMD_EXPORT(rt_link_example_init, rt link layer example init);

From ce0c36422c87318ba2750b78f997722e6a17f17a Mon Sep 17 00:00:00 2001
From: Sherman 
Date: Sat, 15 May 2021 17:21:05 +0800
Subject: [PATCH 080/255] =?UTF-8?q?[fix]=20=E4=BF=AE=E6=94=B9=E6=A0=BC?=
 =?UTF-8?q?=E5=BC=8F=E9=94=99=E8=AF=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 examples/rt-link/rtlink_example.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/examples/rt-link/rtlink_example.c b/examples/rt-link/rtlink_example.c
index 7c70c25e6f..841e56b17e 100644
--- a/examples/rt-link/rtlink_example.c
+++ b/examples/rt-link/rtlink_example.c
@@ -35,7 +35,7 @@ rt_err_t rt_link_receive_example_callback(void *data, rt_size_t length)
 {
     LOG_I("recv data %d",length);
     LOG_HEX("example",8,data,length);
-    rt_free(data);	
+    rt_free(data);
     return RT_EOK;
 }
 
@@ -115,7 +115,6 @@ void rt_link_speed_test(void *paremeter)
     LOG_W("speed test end, type %d",speed_test_type);
 }
 
-
 int rt_link_example_send(int argc, char **argv)
 {
     char *receive = RT_NULL;
@@ -175,7 +174,6 @@ int rt_link_example_send(int argc, char **argv)
             LOG_E("Invalid parameter.");
         }
     }
-    
     return 0;
 }
 MSH_CMD_EXPORT(rt_link_example_send, rt link layer send test);

From d9abe8fa30f04e0ac54a7ea2c50f3df750cff04e Mon Sep 17 00:00:00 2001
From: Meco Man <920369182@qq.com>
Date: Sat, 15 May 2021 21:27:31 +0800
Subject: [PATCH 081/255] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9C=A8simulator=20?=
 =?UTF-8?q?win32=E5=B9=B3=E5=8F=B0=E4=B8=8B=EF=BC=8Cnonegcc=E6=96=87?=
 =?UTF-8?q?=E4=BB=B6=E5=A4=B9=E8=B7=AF=E5=BE=84=E6=B2=A1=E6=9C=89=E6=B7=BB?=
 =?UTF-8?q?=E5=8A=A0=E5=88=B0=E5=B7=A5=E7=A8=8B=E7=9A=84bug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 components/libc/compilers/common/SConscript          | 12 +++++++-----
 components/libc/compilers/common/none-gcc/SConscript |  2 +-
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/components/libc/compilers/common/SConscript b/components/libc/compilers/common/SConscript
index d9de1cf17f..039e53a0b3 100644
--- a/components/libc/compilers/common/SConscript
+++ b/components/libc/compilers/common/SConscript
@@ -23,9 +23,11 @@ else:
 
 if GetDepend('RT_USING_LIBC') or GetDepend('RT_LIBC_USING_TIME'):
     group = DefineGroup('libc', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
-    list = os.listdir(cwd)
-    for d in list:
-        path = os.path.join(cwd, d)
-        if os.path.isfile(os.path.join(path, 'SConscript')):
-            group = group + SConscript(os.path.join(d, 'SConscript'))
+
+list = os.listdir(cwd)
+for d in list:
+    path = os.path.join(cwd, d)
+    if os.path.isfile(os.path.join(path, 'SConscript')):
+        group = group + SConscript(os.path.join(d, 'SConscript'))
+
 Return('group')
diff --git a/components/libc/compilers/common/none-gcc/SConscript b/components/libc/compilers/common/none-gcc/SConscript
index 346e69b478..c5838f8949 100644
--- a/components/libc/compilers/common/none-gcc/SConscript
+++ b/components/libc/compilers/common/none-gcc/SConscript
@@ -8,6 +8,6 @@ CPPPATH = [cwd]
 group = []
 src += Glob('*.c')
 
-if rtconfig.PLATFORM != 'gcc':
+if rtconfig.PLATFORM != 'gcc' or rtconfig.ARCH == 'sim':
     group = DefineGroup('libc', src, depend = ['RT_USING_LIBC'], CPPPATH = CPPPATH)
 Return('group')

From f7d198463e9bff5554835a4ee86b9e28a0190ede Mon Sep 17 00:00:00 2001
From: Hunter 
Date: Sat, 15 May 2021 21:57:01 +0800
Subject: [PATCH 082/255] =?UTF-8?q?=E6=B3=A8=E9=87=8A=E9=94=99=E8=AF=AF?=
 =?UTF-8?q?=EF=BC=8C=E6=AD=A4=E5=A4=84=E7=9A=84=E5=9C=BA=E6=99=AF=E6=98=AF?=
 =?UTF-8?q?zone=E6=BB=A1=E4=BA=86=EF=BC=8C=E4=B8=8D=E6=98=AF=E7=A9=BA?=
 =?UTF-8?q?=E4=BA=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/slab.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/slab.c b/src/slab.c
index 12ca1a938c..114259002f 100644
--- a/src/slab.c
+++ b/src/slab.c
@@ -540,7 +540,7 @@ void *rt_malloc(rt_size_t size)
     {
         RT_ASSERT(z->z_nfree > 0);
 
-        /* Remove us from the zone_array[] when we become empty */
+        /* Remove us from the zone_array[] when we become full */
         if (--z->z_nfree == 0)
         {
             zone_array[zi] = z->z_next;

From cbcd9fe15e46276b4140a741f211e66b7478d523 Mon Sep 17 00:00:00 2001
From: Meco Man <920369182@qq.com>
Date: Sun, 16 May 2021 00:02:58 +0800
Subject: [PATCH 083/255] [POSIX] beautify Kconfig

---
 components/libc/Kconfig | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/components/libc/Kconfig b/components/libc/Kconfig
index 8a790c298d..a89b252caa 100644
--- a/components/libc/Kconfig
+++ b/components/libc/Kconfig
@@ -16,26 +16,26 @@ endif
 
 if RT_USING_LIBC && RT_USING_DFS
     config RT_USING_POSIX
-        bool "Enable POSIX layer for poll/select, stdin etc"
+        bool "Enable POSIX layer for compatibility with UNIX APIs, poll/select etc"
         select RT_USING_DFS_DEVFS
         default y
 
     if RT_USING_POSIX
-    config RT_USING_POSIX_MMAP
-        bool "Enable mmap() API"
-        default n
+        config RT_USING_POSIX_MMAP
+            bool "Enable mmap() API"
+            default n
 
-    config RT_USING_POSIX_TERMIOS
-        bool "Enable termios APIs"
-        default n
+        config RT_USING_POSIX_TERMIOS
+            bool "Enable termios APIs"
+            default n
 
-    config RT_USING_POSIX_GETLINE
-        bool "Enable getline()/getdelim() APIs"
-        default n
+        config RT_USING_POSIX_GETLINE
+            bool "Enable getline()/getdelim() APIs"
+            default n
 
-    config RT_USING_POSIX_AIO
-        bool "Enable AIO"
-        default n
+        config RT_USING_POSIX_AIO
+            bool "Enable AIO"
+            default n
     endif
 
 endif

From b57278f83021875dee66b6c0c438c82fa34e9539 Mon Sep 17 00:00:00 2001
From: Wang-Huachen 
Date: Sun, 16 May 2021 10:00:17 +0800
Subject: [PATCH 084/255] remove redundant code in zynqmp-r5-axu4ev bsp

---
 .../xemacpsif/netif/xadapter.h                |  4 ----
 .../Zynq_HAL_Driver/xemacpsif/xadapter.c      | 23 -------------------
 .../Zynq_HAL_Driver/xemacpsif/xemacpsif.c     |  3 ---
 .../Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c |  4 ----
 libcpu/arm/zynqmp-r5/cache.c                  |  8 -------
 5 files changed, 42 deletions(-)

diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h
index 4fe304f55d..106b5ff210 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h
@@ -55,11 +55,7 @@ struct xemac_s {
     enum xemac_types type;
     int  topology_index;
     void *state;
-#if 0
-    sys_sem_t sem_rx_data_available;
-#else
     struct eth_device *rt_eth_device;
-#endif
 #if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
     TimerHandle_t xTimer;
 #endif
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c
index e5c0c77829..a10d7a4016 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c
@@ -197,29 +197,6 @@ xemac_add(struct netif *netif,
     }
 }
 
-#if 0
-/*
- * The input thread calls lwIP to process any received packets.
- * This thread waits until a packet is received (sem_rx_data_available),
- * and then calls xemacif_input which processes 1 packet at a time.
- */
-void
-xemacif_input_thread(struct netif *netif)
-{
-    struct xemac_s *emac = (struct xemac_s *)netif->state;
-    while (1) {
-        /* sleep until there are packets to process
-         * This semaphore is set by the packet receive interrupt
-         * routine.
-         */
-        sys_sem_wait(&emac->sem_rx_data_available);
-
-        /* move all received packets to lwIP */
-        xemacif_input(netif);
-    }
-}
-#endif
-
 int
 xemacif_input(struct netif *netif)
 {
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c
index 9a7f93f42f..0ac650c5e6 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c
@@ -353,9 +353,6 @@ static err_t low_level_init(struct netif *netif)
     netif->flags |= NETIF_FLAG_IGMP;
 #endif
 
-#if 0
-    sys_sem_new(&xemac->sem_rx_data_available, 0);
-#endif
     /* obtain config of this emac */
     mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)(UINTPTR)netif->state);
 
diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c
index f917b10a97..3227d61b92 100644
--- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c
+++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c
@@ -513,11 +513,7 @@ void emacps_recv_handler(void *arg)
         /* free up the BD's */
         XEmacPs_BdRingFree(rxring, bd_processed, rxbdset);
         setup_rx_bds(xemacpsif, rxring);
-#if 0
-        sys_sem_signal(&xemac->sem_rx_data_available);
-#else
         eth_device_ready(xemac->rt_eth_device);
-#endif
     }
 
 #ifdef OS_IS_FREERTOS
diff --git a/libcpu/arm/zynqmp-r5/cache.c b/libcpu/arm/zynqmp-r5/cache.c
index ed0efa4824..6053b2fe47 100644
--- a/libcpu/arm/zynqmp-r5/cache.c
+++ b/libcpu/arm/zynqmp-r5/cache.c
@@ -108,14 +108,6 @@ void Xil_DCacheInvalidate(void)
     currmask = mfcpsr();
     mtcpsr(currmask | IRQ_FIQ_MASK);
 
-#if 0
-    stack_end = (u32 )&_stack_end;
-    stack_start = (u32 )&__undef_stack;
-    stack_size = stack_start-stack_end;
-
-    /* Flush stack memory to save return address */
-    Xil_DCacheFlushRange(stack_end, stack_size);
-#endif
     mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
 
     /*invalidate all D cache*/

From f0ca8be39d8102e7d779a31fae510f8ee94ee431 Mon Sep 17 00:00:00 2001
From: guozhanxin 
Date: Mon, 17 May 2021 15:11:34 +0800
Subject: [PATCH 085/255] =?UTF-8?q?=E3=80=90=E4=BF=AE=E5=A4=8D=E3=80=91stu?=
 =?UTF-8?q?dio=20=E7=94=9F=E6=88=90=E5=B7=A5=E7=A8=8B=E6=8A=A5=E9=94=99?=
 =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 tools/building.py   |  3 ++-
 tools/menuconfig.py | 27 ++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/tools/building.py b/tools/building.py
index 90554a3082..bfdd1ff55a 100644
--- a/tools/building.py
+++ b/tools/building.py
@@ -448,7 +448,8 @@ def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = [
                            duplicate=0,
                            exports='remove_components'))
     # include testcases
-    objs.extend(SConscript(Rtt_Root + '/examples/utest/testcases/SConscript',
+    if os.path.isfile(os.path.join(Rtt_Root, 'examples/utest/testcases/SConscript')):
+        objs.extend(SConscript(Rtt_Root + '/examples/utest/testcases/SConscript',
                            variant_dir=kernel_vdir + '/examples/utest/testcases',
                            duplicate=0))
 
diff --git a/tools/menuconfig.py b/tools/menuconfig.py
index c0a33718de..853e4fe7f8 100644
--- a/tools/menuconfig.py
+++ b/tools/menuconfig.py
@@ -217,8 +217,27 @@ def touch_env():
         if os.path.exists(os.path.join(env_dir, 'tools', 'scripts')):
             os.environ["PATH"] = os.path.join(env_dir, 'tools', 'scripts') + ';' + os.environ["PATH"]
 
+# Exclude utestcases 
+def exclude_utestcases(RTT_ROOT):
+    if os.path.isfile(os.path.join(RTT_ROOT, 'examples/utest/testcases/Kconfig')):
+        return
+
+    if not os.path.isfile(os.path.join(RTT_ROOT, 'Kconfig')):
+        return
+
+    with open(os.path.join(RTT_ROOT, 'Kconfig'), 'r') as f:
+        data = f.readlines()
+    with open(os.path.join(RTT_ROOT, 'Kconfig'), 'w') as f:
+        for line in data:
+            if line.find('examples/utest/testcases/Kconfig') == -1:
+                f.write(line)
+
 # menuconfig for Linux
 def menuconfig(RTT_ROOT):
+
+    # Exclude utestcases 
+    exclude_utestcases(RTT_ROOT)
+
     kconfig_dir = os.path.join(RTT_ROOT, 'tools', 'kconfig-frontends')
     os.system('scons -C ' + kconfig_dir)
 
@@ -250,6 +269,9 @@ def menuconfig(RTT_ROOT):
 def guiconfig(RTT_ROOT):
     import pyguiconfig
 
+    # Exclude utestcases 
+    exclude_utestcases(RTT_ROOT)
+
     if sys.platform != 'win32':
         touch_env()
 
@@ -260,7 +282,7 @@ def guiconfig(RTT_ROOT):
     fn = '.config'
     fn_old = '.config.old'
 
-    sys.argv = ['guiconfig', 'Kconfig'];
+    sys.argv = ['guiconfig', 'Kconfig']
     pyguiconfig._main()
 
     if os.path.isfile(fn):
@@ -281,6 +303,9 @@ def guiconfig(RTT_ROOT):
 def guiconfig_silent(RTT_ROOT):
     import defconfig
 
+    # Exclude utestcases 
+    exclude_utestcases(RTT_ROOT)
+    
     if sys.platform != 'win32':
         touch_env()
 

From 975a2ef684e829a5b3815886d244301662a2d5b2 Mon Sep 17 00:00:00 2001
From: guozhanxin 
Date: Mon, 17 May 2021 16:09:38 +0800
Subject: [PATCH 086/255] =?UTF-8?q?=E3=80=90=E5=AE=8C=E5=96=84=E3=80=91fil?=
 =?UTF-8?q?e=5Fcheck.py=20=E4=B8=AD=E6=A3=80=E6=9F=A5=E5=8F=98=E6=9B=B4?=
 =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=9A=84=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 tools/file_check.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/file_check.py b/tools/file_check.py
index 046b2a009f..63767782b5 100644
--- a/tools/file_check.py
+++ b/tools/file_check.py
@@ -84,6 +84,7 @@ class CheckOut:
         try:
             os.system('git remote add rtt_repo {}'.format(self.rtt_repo))
             os.system('git fetch rtt_repo')
+            os.system('git merge rtt_repo/{}'.format(self.rtt_branch))
             os.system('git reset rtt_repo/{} --soft'.format(self.rtt_branch))
             os.system('git status > git.txt')
         except Exception as e:

From 541426a72ad8f9d6b118994f9118ed7b7f8cfcea Mon Sep 17 00:00:00 2001
From: Wayne Lin 
Date: Mon, 17 May 2021 16:23:41 +0800
Subject: [PATCH 087/255] [nuvoton] Support M031 Series.

1. Import M031 porting.
2. Support numaker-m032ki BSP.
---
 bsp/nuvoton/README.md                         |    1 +
 .../m031/CMSIS/Include/arm_common_tables.h    |  136 +
 .../m031/CMSIS/Include/arm_const_structs.h    |   79 +
 .../libraries/m031/CMSIS/Include/arm_math.h   | 7154 +++++++++++++++++
 .../m031/CMSIS/Include/cmsis_armcc.h          |  734 ++
 .../m031/CMSIS/Include/cmsis_armcc_V6.h       | 1804 +++++
 .../libraries/m031/CMSIS/Include/cmsis_gcc.h  | 1373 ++++
 .../libraries/m031/CMSIS/Include/core_cm0.h   |  798 ++
 .../m031/CMSIS/Include/core_cm0plus.h         |  914 +++
 .../libraries/m031/CMSIS/Include/core_cm3.h   | 1763 ++++
 .../libraries/m031/CMSIS/Include/core_cm4.h   | 1937 +++++
 .../libraries/m031/CMSIS/Include/core_cm7.h   | 2512 ++++++
 .../m031/CMSIS/Include/core_cmFunc.h          |   87 +
 .../m031/CMSIS/Include/core_cmInstr.h         |   87 +
 .../m031/CMSIS/Include/core_cmSimd.h          |   96 +
 .../libraries/m031/CMSIS/Include/core_sc000.h |  926 +++
 .../libraries/m031/CMSIS/Include/core_sc300.h | 1745 ++++
 bsp/nuvoton/libraries/m031/CMSIS/SConscript   |   16 +
 .../Device/Nuvoton/M031/Include/M031Series.h  |  590 ++
 .../Device/Nuvoton/M031/Include/NuMicro.h     |   17 +
 .../Device/Nuvoton/M031/Include/acmp_reg.h    |  255 +
 .../Device/Nuvoton/M031/Include/adc_reg.h     |  400 +
 .../Device/Nuvoton/M031/Include/bpwm_reg.h    | 1743 ++++
 .../Device/Nuvoton/M031/Include/clk_reg.h     |  918 +++
 .../Device/Nuvoton/M031/Include/crc_reg.h     |  151 +
 .../Device/Nuvoton/M031/Include/ebi_reg.h     |  224 +
 .../Device/Nuvoton/M031/Include/fmc_reg.h     |  317 +
 .../Device/Nuvoton/M031/Include/gpio_reg.h    |  710 ++
 .../Device/Nuvoton/M031/Include/hdiv_reg.h    |  130 +
 .../Device/Nuvoton/M031/Include/i2c_reg.h     |  750 ++
 .../Device/Nuvoton/M031/Include/pdma_reg.h    |  675 ++
 .../Device/Nuvoton/M031/Include/pwm_reg.h     | 2294 ++++++
 .../Device/Nuvoton/M031/Include/qspi_reg.h    |  586 ++
 .../Device/Nuvoton/M031/Include/rtc_reg.h     |  419 +
 .../Device/Nuvoton/M031/Include/spi_reg.h     |  784 ++
 .../Device/Nuvoton/M031/Include/sys_reg.h     | 1484 ++++
 .../Nuvoton/M031/Include/system_M031Series.h  |  105 +
 .../Device/Nuvoton/M031/Include/timer_reg.h   |  336 +
 .../Device/Nuvoton/M031/Include/uart_reg.h    | 1085 +++
 .../Device/Nuvoton/M031/Include/ui2c_reg.h    |  570 ++
 .../Device/Nuvoton/M031/Include/usbd_reg.h    |  570 ++
 .../Device/Nuvoton/M031/Include/uspi_reg.h    |  673 ++
 .../Device/Nuvoton/M031/Include/uuart_reg.h   |  666 ++
 .../Device/Nuvoton/M031/Include/wdt_reg.h     |  174 +
 .../Device/Nuvoton/M031/Include/wwdt_reg.h    |  148 +
 .../M031/Source/ARM/startup_M031Series.s      |  259 +
 .../M031/Source/GCC/startup_M031Series.S      |  229 +
 .../M031/Source/IAR/startup_M031Series.s      |  202 +
 .../Nuvoton/M031/Source/system_M031Series.c   |  130 +
 bsp/nuvoton/libraries/m031/Device/SConscript  |   25 +
 bsp/nuvoton/libraries/m031/README.md          |   35 +
 bsp/nuvoton/libraries/m031/SConscript         |   14 +
 .../libraries/m031/StdDriver/SConscript       |   28 +
 .../libraries/m031/StdDriver/inc/nu_acmp.h    |  401 +
 .../libraries/m031/StdDriver/inc/nu_adc.h     |  418 +
 .../libraries/m031/StdDriver/inc/nu_bpwm.h    |  379 +
 .../libraries/m031/StdDriver/inc/nu_clk.h     |  600 ++
 .../libraries/m031/StdDriver/inc/nu_crc.h     |  117 +
 .../libraries/m031/StdDriver/inc/nu_ebi.h     |  260 +
 .../libraries/m031/StdDriver/inc/nu_fmc.h     |  269 +
 .../libraries/m031/StdDriver/inc/nu_gpio.h    |  481 ++
 .../libraries/m031/StdDriver/inc/nu_hdiv.h    |   88 +
 .../libraries/m031/StdDriver/inc/nu_i2c.h     |  540 ++
 .../libraries/m031/StdDriver/inc/nu_pdma.h    |  358 +
 .../libraries/m031/StdDriver/inc/nu_pwm.h     |  514 ++
 .../libraries/m031/StdDriver/inc/nu_qspi.h    |  412 +
 .../libraries/m031/StdDriver/inc/nu_rtc.h     |  300 +
 .../libraries/m031/StdDriver/inc/nu_spi.h     |  558 ++
 .../libraries/m031/StdDriver/inc/nu_sys.h     | 1391 ++++
 .../libraries/m031/StdDriver/inc/nu_timer.h   |  507 ++
 .../libraries/m031/StdDriver/inc/nu_uart.h    |  495 ++
 .../libraries/m031/StdDriver/inc/nu_usbd.h    |  699 ++
 .../m031/StdDriver/inc/nu_usci_i2c.h          |  332 +
 .../m031/StdDriver/inc/nu_usci_spi.h          |  428 +
 .../m031/StdDriver/inc/nu_usci_uart.h         |  523 ++
 .../libraries/m031/StdDriver/inc/nu_wdt.h     |  220 +
 .../libraries/m031/StdDriver/inc/nu_wwdt.h    |  155 +
 .../m031/StdDriver/lib/libStdDriver.ewd       | 2966 +++++++
 .../m031/StdDriver/lib/libStdDriver.ewp       | 2152 +++++
 .../m031/StdDriver/lib/libStdDriver.eww       |   10 +
 .../m031/StdDriver/lib/libStdDriver.uvprojx   |  513 ++
 .../m031/StdDriver/lib/nutool_clkcfg.h        |   27 +
 .../libraries/m031/StdDriver/src/nu_acmp.c    |   82 +
 .../libraries/m031/StdDriver/src/nu_adc.c     |  200 +
 .../libraries/m031/StdDriver/src/nu_bpwm.c    |  751 ++
 .../libraries/m031/StdDriver/src/nu_clk.c     |  836 ++
 .../libraries/m031/StdDriver/src/nu_crc.c     |   99 +
 .../libraries/m031/StdDriver/src/nu_ebi.c     |  182 +
 .../libraries/m031/StdDriver/src/nu_fmc.c     |  572 ++
 .../libraries/m031/StdDriver/src/nu_gpio.c    |  108 +
 .../libraries/m031/StdDriver/src/nu_i2c.c     | 1582 ++++
 .../libraries/m031/StdDriver/src/nu_pdma.c    |  412 +
 .../libraries/m031/StdDriver/src/nu_pwm.c     | 1063 +++
 .../libraries/m031/StdDriver/src/nu_qspi.c    |  813 ++
 .../libraries/m031/StdDriver/src/nu_rtc.c     |  782 ++
 .../libraries/m031/StdDriver/src/nu_spi.c     |  934 +++
 .../libraries/m031/StdDriver/src/nu_sys.c     |  205 +
 .../libraries/m031/StdDriver/src/nu_timer.c   |  333 +
 .../libraries/m031/StdDriver/src/nu_uart.c    |  722 ++
 .../libraries/m031/StdDriver/src/nu_usbd.c    |  705 ++
 .../m031/StdDriver/src/nu_usci_i2c.c          | 1689 ++++
 .../m031/StdDriver/src/nu_usci_spi.c          |  635 ++
 .../m031/StdDriver/src/nu_usci_uart.c         |  729 ++
 .../libraries/m031/StdDriver/src/nu_wdt.c     |   73 +
 .../libraries/m031/StdDriver/src/nu_wwdt.c    |   73 +
 bsp/nuvoton/libraries/m031/rtt_port/Kconfig   |  634 ++
 .../libraries/m031/rtt_port/SConscript        |   12 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_adc.c |  154 +
 .../libraries/m031/rtt_port/drv_bpwm.c        |  228 +
 .../m031/rtt_port/drv_bpwm_capture.c          |  335 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_clk.c |  287 +
 .../libraries/m031/rtt_port/drv_common.c      |  142 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_crc.c |  138 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_crc.h |   20 +
 .../libraries/m031/rtt_port/drv_crypto.c      |  126 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_ebi.c |   38 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_ebi.h |   48 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_fmc.c |  331 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_fmc.h |   24 +
 .../libraries/m031/rtt_port/drv_gpio.c        |  401 +
 .../libraries/m031/rtt_port/drv_gpio.h        |   34 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c |  317 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_i2s.h |   96 +
 .../libraries/m031/rtt_port/drv_pdma.c        | 1013 +++
 .../libraries/m031/rtt_port/drv_pdma.h        |   72 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_pwm.c |  266 +
 .../libraries/m031/rtt_port/drv_pwm_capture.c |  334 +
 .../libraries/m031/rtt_port/drv_qspi.c        |  405 +
 .../libraries/m031/rtt_port/drv_qspi.h        |   20 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_rtc.c |  346 +
 .../libraries/m031/rtt_port/drv_softi2c.c     |  217 +
 bsp/nuvoton/libraries/m031/rtt_port/drv_spi.c |  599 ++
 bsp/nuvoton/libraries/m031/rtt_port/drv_spi.h |   51 +
 .../libraries/m031/rtt_port/drv_spii2s.c      |  594 ++
 .../libraries/m031/rtt_port/drv_timer.c       |  326 +
 .../m031/rtt_port/drv_timer_capture.c         |  327 +
 .../libraries/m031/rtt_port/drv_uart.c        |  838 ++
 .../libraries/m031/rtt_port/drv_uart.h        |   20 +
 .../libraries/m031/rtt_port/drv_ui2c.c        |  377 +
 .../libraries/m031/rtt_port/drv_usbd.c        |  502 ++
 .../libraries/m031/rtt_port/drv_uspi.c        |  607 ++
 .../libraries/m031/rtt_port/drv_uuart.c       |  621 ++
 bsp/nuvoton/libraries/m031/rtt_port/drv_wdt.c |  481 ++
 bsp/nuvoton/numaker-m032ki/.config            |  675 ++
 bsp/nuvoton/numaker-m032ki/Kconfig            |   29 +
 bsp/nuvoton/numaker-m032ki/Nu_Link_Driver.ini | 1038 +++
 bsp/nuvoton/numaker-m032ki/README.md          |   72 +
 bsp/nuvoton/numaker-m032ki/SConscript         |   14 +
 bsp/nuvoton/numaker-m032ki/SConstruct         |   59 +
 .../numaker-m032ki/applications/SConscript    |   11 +
 .../numaker-m032ki/applications/main.c        |   38 +
 bsp/nuvoton/numaker-m032ki/applications/mnt.c |   54 +
 bsp/nuvoton/numaker-m032ki/board/Kconfig      |   27 +
 .../board/NuClockConfig/nutool_clkcfg.h       |   27 +
 .../board/NuClockConfig/nutool_modclkcfg.c    |  506 ++
 .../board/NuClockConfig/nutool_modclkcfg.cfg  |   33 +
 .../board/NuClockConfig/nutool_modclkcfg.h    |   72 +
 .../board/NuPinConfig/nutool_pincfg.c         |  233 +
 .../board/NuPinConfig/nutool_pincfg.cfg       |  159 +
 .../board/NuPinConfig/nutool_pincfg.h         |   44 +
 bsp/nuvoton/numaker-m032ki/board/SConscript   |   20 +
 bsp/nuvoton/numaker-m032ki/board/board.h      |   37 +
 bsp/nuvoton/numaker-m032ki/board/board_dev.c  |  152 +
 bsp/nuvoton/numaker-m032ki/board/fal_cfg.h    |   42 +
 .../linking_scripts/m031_flash.icf            |   28 +
 .../linking_scripts/m031_flash.sct            |   15 +
 .../linking_scripts/m031_link.ld              |  159 +
 bsp/nuvoton/numaker-m032ki/rtconfig.py        |  124 +
 bsp/nuvoton/numaker-m032ki/template.ewd       | 1485 ++++
 bsp/nuvoton/numaker-m032ki/template.ewp       | 1039 +++
 bsp/nuvoton/numaker-m032ki/template.eww       |   10 +
 bsp/nuvoton/numaker-m032ki/template.uvprojx   |  391 +
 172 files changed, 87525 insertions(+)
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/arm_common_tables.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/arm_const_structs.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/arm_math.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_armcc.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_armcc_V6.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_gcc.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm0.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm0plus.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm3.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm4.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm7.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmFunc.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmInstr.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmSimd.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/core_sc000.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/Include/core_sc300.h
 create mode 100644 bsp/nuvoton/libraries/m031/CMSIS/SConscript
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/M031Series.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/NuMicro.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/acmp_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/adc_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/bpwm_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/clk_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/crc_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/ebi_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/fmc_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/gpio_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/hdiv_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/i2c_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/pdma_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/pwm_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/qspi_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/rtc_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/spi_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/sys_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/system_M031Series.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/timer_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uart_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/ui2c_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/usbd_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uspi_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uuart_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/wdt_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/wwdt_reg.h
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/ARM/startup_M031Series.s
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/GCC/startup_M031Series.S
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/IAR/startup_M031Series.s
 create mode 100644 bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/system_M031Series.c
 create mode 100644 bsp/nuvoton/libraries/m031/Device/SConscript
 create mode 100644 bsp/nuvoton/libraries/m031/README.md
 create mode 100644 bsp/nuvoton/libraries/m031/SConscript
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/SConscript
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_acmp.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_adc.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_bpwm.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_clk.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_crc.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_ebi.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_fmc.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_gpio.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_hdiv.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_i2c.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_pdma.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_pwm.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_qspi.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_rtc.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_spi.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_sys.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_timer.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_uart.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usbd.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_i2c.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_spi.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_uart.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_wdt.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/inc/nu_wwdt.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.ewd
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.ewp
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.eww
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.uvprojx
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/lib/nutool_clkcfg.h
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_acmp.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_adc.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_bpwm.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_clk.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_crc.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_ebi.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_fmc.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_gpio.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_i2c.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_pdma.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_pwm.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_qspi.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_rtc.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_spi.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_sys.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_timer.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_uart.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_usbd.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_i2c.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_spi.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_uart.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_wdt.c
 create mode 100644 bsp/nuvoton/libraries/m031/StdDriver/src/nu_wwdt.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/Kconfig
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/SConscript
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_adc.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_bpwm.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_bpwm_capture.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_clk.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_common.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_crc.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_crc.h
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_crypto.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_ebi.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_ebi.h
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_fmc.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_fmc.h
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_gpio.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_gpio.h
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_i2s.h
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_pdma.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_pdma.h
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_pwm.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_pwm_capture.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_qspi.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_qspi.h
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_rtc.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_softi2c.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_spi.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_spi.h
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_spii2s.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_timer.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_timer_capture.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_uart.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_uart.h
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_ui2c.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_usbd.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_uspi.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_uuart.c
 create mode 100644 bsp/nuvoton/libraries/m031/rtt_port/drv_wdt.c
 create mode 100644 bsp/nuvoton/numaker-m032ki/.config
 create mode 100644 bsp/nuvoton/numaker-m032ki/Kconfig
 create mode 100644 bsp/nuvoton/numaker-m032ki/Nu_Link_Driver.ini
 create mode 100644 bsp/nuvoton/numaker-m032ki/README.md
 create mode 100644 bsp/nuvoton/numaker-m032ki/SConscript
 create mode 100644 bsp/nuvoton/numaker-m032ki/SConstruct
 create mode 100644 bsp/nuvoton/numaker-m032ki/applications/SConscript
 create mode 100644 bsp/nuvoton/numaker-m032ki/applications/main.c
 create mode 100644 bsp/nuvoton/numaker-m032ki/applications/mnt.c
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/Kconfig
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_clkcfg.h
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.c
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.cfg
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.h
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.c
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.cfg
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.h
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/SConscript
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/board.h
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/board_dev.c
 create mode 100644 bsp/nuvoton/numaker-m032ki/board/fal_cfg.h
 create mode 100644 bsp/nuvoton/numaker-m032ki/linking_scripts/m031_flash.icf
 create mode 100644 bsp/nuvoton/numaker-m032ki/linking_scripts/m031_flash.sct
 create mode 100644 bsp/nuvoton/numaker-m032ki/linking_scripts/m031_link.ld
 create mode 100644 bsp/nuvoton/numaker-m032ki/rtconfig.py
 create mode 100644 bsp/nuvoton/numaker-m032ki/template.ewd
 create mode 100644 bsp/nuvoton/numaker-m032ki/template.ewp
 create mode 100644 bsp/nuvoton/numaker-m032ki/template.eww
 create mode 100644 bsp/nuvoton/numaker-m032ki/template.uvprojx

diff --git a/bsp/nuvoton/README.md b/bsp/nuvoton/README.md
index ec049a5546..5958bdd3ab 100644
--- a/bsp/nuvoton/README.md
+++ b/bsp/nuvoton/README.md
@@ -9,3 +9,4 @@ Current supported BSP shown in below table:
 | [numaker-m2354](numaker-m2354) | Nuvoton NuMaker-M2354 |
 | [nk-rtu980](nk-rtu980) | Nuvoton NK-RTU980 |
 | [nk-n9h30](nk-n9h30) | Nuvoton NK-N9H30 |
+| [numaker-m032ki](numaker-m032ki) | Nuvoton NuMaker-M032KI |
diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/arm_common_tables.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/arm_common_tables.h
new file mode 100644
index 0000000000..03153851b8
--- /dev/null
+++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/arm_common_tables.h
@@ -0,0 +1,136 @@
+/* ----------------------------------------------------------------------
+* Copyright (C) 2010-2014 ARM Limited. All rights reserved.
+*
+* $Date:        19. October 2015
+* $Revision:    V.1.4.5 a
+*
+* Project:      CMSIS DSP Library
+* Title:        arm_common_tables.h
+*
+* Description:  This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions
+*
+* Target Processor: Cortex-M4/Cortex-M3
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*   - Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   - Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in
+*     the documentation and/or other materials provided with the
+*     distribution.
+*   - Neither the name of ARM LIMITED nor the names of its contributors
+*     may be used to endorse or promote products derived from this
+*     software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+* -------------------------------------------------------------------- */
+
+#ifndef _ARM_COMMON_TABLES_H
+#define _ARM_COMMON_TABLES_H
+
+#include "arm_math.h"
+
+extern const uint16_t armBitRevTable[1024];
+extern const q15_t armRecipTableQ15[64];
+extern const q31_t armRecipTableQ31[64];
+/* extern const q31_t realCoefAQ31[1024]; */
+/* extern const q31_t realCoefBQ31[1024]; */
+extern const float32_t twiddleCoef_16[32];
+extern const float32_t twiddleCoef_32[64];
+extern const float32_t twiddleCoef_64[128];
+extern const float32_t twiddleCoef_128[256];
+extern const float32_t twiddleCoef_256[512];
+extern const float32_t twiddleCoef_512[1024];
+extern const float32_t twiddleCoef_1024[2048];
+extern const float32_t twiddleCoef_2048[4096];
+extern const float32_t twiddleCoef_4096[8192];
+#define twiddleCoef twiddleCoef_4096
+extern const q31_t twiddleCoef_16_q31[24];
+extern const q31_t twiddleCoef_32_q31[48];
+extern const q31_t twiddleCoef_64_q31[96];
+extern const q31_t twiddleCoef_128_q31[192];
+extern const q31_t twiddleCoef_256_q31[384];
+extern const q31_t twiddleCoef_512_q31[768];
+extern const q31_t twiddleCoef_1024_q31[1536];
+extern const q31_t twiddleCoef_2048_q31[3072];
+extern const q31_t twiddleCoef_4096_q31[6144];
+extern const q15_t twiddleCoef_16_q15[24];
+extern const q15_t twiddleCoef_32_q15[48];
+extern const q15_t twiddleCoef_64_q15[96];
+extern const q15_t twiddleCoef_128_q15[192];
+extern const q15_t twiddleCoef_256_q15[384];
+extern const q15_t twiddleCoef_512_q15[768];
+extern const q15_t twiddleCoef_1024_q15[1536];
+extern const q15_t twiddleCoef_2048_q15[3072];
+extern const q15_t twiddleCoef_4096_q15[6144];
+extern const float32_t twiddleCoef_rfft_32[32];
+extern const float32_t twiddleCoef_rfft_64[64];
+extern const float32_t twiddleCoef_rfft_128[128];
+extern const float32_t twiddleCoef_rfft_256[256];
+extern const float32_t twiddleCoef_rfft_512[512];
+extern const float32_t twiddleCoef_rfft_1024[1024];
+extern const float32_t twiddleCoef_rfft_2048[2048];
+extern const float32_t twiddleCoef_rfft_4096[4096];
+
+
+/* floating-point bit reversal tables */
+#define ARMBITREVINDEXTABLE__16_TABLE_LENGTH ((uint16_t)20  )
+#define ARMBITREVINDEXTABLE__32_TABLE_LENGTH ((uint16_t)48  )
+#define ARMBITREVINDEXTABLE__64_TABLE_LENGTH ((uint16_t)56  )
+#define ARMBITREVINDEXTABLE_128_TABLE_LENGTH ((uint16_t)208 )
+#define ARMBITREVINDEXTABLE_256_TABLE_LENGTH ((uint16_t)440 )
+#define ARMBITREVINDEXTABLE_512_TABLE_LENGTH ((uint16_t)448 )
+#define ARMBITREVINDEXTABLE1024_TABLE_LENGTH ((uint16_t)1800)
+#define ARMBITREVINDEXTABLE2048_TABLE_LENGTH ((uint16_t)3808)
+#define ARMBITREVINDEXTABLE4096_TABLE_LENGTH ((uint16_t)4032)
+
+extern const uint16_t armBitRevIndexTable16[ARMBITREVINDEXTABLE__16_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable32[ARMBITREVINDEXTABLE__32_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable64[ARMBITREVINDEXTABLE__64_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable128[ARMBITREVINDEXTABLE_128_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable256[ARMBITREVINDEXTABLE_256_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable512[ARMBITREVINDEXTABLE_512_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable1024[ARMBITREVINDEXTABLE1024_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable2048[ARMBITREVINDEXTABLE2048_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable4096[ARMBITREVINDEXTABLE4096_TABLE_LENGTH];
+
+/* fixed-point bit reversal tables */
+#define ARMBITREVINDEXTABLE_FIXED___16_TABLE_LENGTH ((uint16_t)12  )
+#define ARMBITREVINDEXTABLE_FIXED___32_TABLE_LENGTH ((uint16_t)24  )
+#define ARMBITREVINDEXTABLE_FIXED___64_TABLE_LENGTH ((uint16_t)56  )
+#define ARMBITREVINDEXTABLE_FIXED__128_TABLE_LENGTH ((uint16_t)112 )
+#define ARMBITREVINDEXTABLE_FIXED__256_TABLE_LENGTH ((uint16_t)240 )
+#define ARMBITREVINDEXTABLE_FIXED__512_TABLE_LENGTH ((uint16_t)480 )
+#define ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH ((uint16_t)992 )
+#define ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH ((uint16_t)1984)
+#define ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH ((uint16_t)4032)
+
+extern const uint16_t armBitRevIndexTable_fixed_16[ARMBITREVINDEXTABLE_FIXED___16_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable_fixed_32[ARMBITREVINDEXTABLE_FIXED___32_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable_fixed_64[ARMBITREVINDEXTABLE_FIXED___64_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable_fixed_128[ARMBITREVINDEXTABLE_FIXED__128_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable_fixed_256[ARMBITREVINDEXTABLE_FIXED__256_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable_fixed_512[ARMBITREVINDEXTABLE_FIXED__512_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable_fixed_1024[ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable_fixed_2048[ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH];
+extern const uint16_t armBitRevIndexTable_fixed_4096[ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH];
+
+/* Tables for Fast Math Sine and Cosine */
+extern const float32_t sinTable_f32[FAST_MATH_TABLE_SIZE + 1];
+extern const q31_t sinTable_q31[FAST_MATH_TABLE_SIZE + 1];
+extern const q15_t sinTable_q15[FAST_MATH_TABLE_SIZE + 1];
+
+#endif /*  ARM_COMMON_TABLES_H */
diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/arm_const_structs.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/arm_const_structs.h
new file mode 100644
index 0000000000..4d02617344
--- /dev/null
+++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/arm_const_structs.h
@@ -0,0 +1,79 @@
+/* ----------------------------------------------------------------------
+* Copyright (C) 2010-2014 ARM Limited. All rights reserved.
+*
+* $Date:        19. March 2015
+* $Revision:    V.1.4.5
+*
+* Project:      CMSIS DSP Library
+* Title:        arm_const_structs.h
+*
+* Description:  This file has constant structs that are initialized for
+*              user convenience.  For example, some can be given as
+*              arguments to the arm_cfft_f32() function.
+*
+* Target Processor: Cortex-M4/Cortex-M3
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*   - Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   - Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in
+*     the documentation and/or other materials provided with the
+*     distribution.
+*   - Neither the name of ARM LIMITED nor the names of its contributors
+*     may be used to endorse or promote products derived from this
+*     software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+* -------------------------------------------------------------------- */
+
+#ifndef _ARM_CONST_STRUCTS_H
+#define _ARM_CONST_STRUCTS_H
+
+#include "arm_math.h"
+#include "arm_common_tables.h"
+
+extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16;
+extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32;
+extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64;
+extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128;
+extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256;
+extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512;
+extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024;
+extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048;
+extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096;
+
+extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len16;
+extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len32;
+extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len64;
+extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len128;
+extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len256;
+extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len512;
+extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024;
+extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048;
+extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096;
+
+extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len16;
+extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len32;
+extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len64;
+extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len128;
+extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len256;
+extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len512;
+extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024;
+extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048;
+extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096;
+
+#endif
diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/arm_math.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/arm_math.h
new file mode 100644
index 0000000000..d33f8a9b3b
--- /dev/null
+++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/arm_math.h
@@ -0,0 +1,7154 @@
+/* ----------------------------------------------------------------------
+* Copyright (C) 2010-2015 ARM Limited. All rights reserved.
+*
+* $Date:        20. October 2015
+* $Revision:    V1.4.5 b
+*
+* Project:      CMSIS DSP Library
+* Title:        arm_math.h
+*
+* Description:  Public header file for CMSIS DSP Library
+*
+* Target Processor: Cortex-M7/Cortex-M4/Cortex-M3/Cortex-M0
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*   - Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   - Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in
+*     the documentation and/or other materials provided with the
+*     distribution.
+*   - Neither the name of ARM LIMITED nor the names of its contributors
+*     may be used to endorse or promote products derived from this
+*     software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+ * -------------------------------------------------------------------- */
+
+/**
+   \mainpage CMSIS DSP Software Library
+   *
+   * Introduction
+   * ------------
+   *
+   * This user manual describes the CMSIS DSP software library,
+   * a suite of common signal processing functions for use on Cortex-M processor based devices.
+   *
+   * The library is divided into a number of functions each covering a specific category:
+   * - Basic math functions
+   * - Fast math functions
+   * - Complex math functions
+   * - Filters
+   * - Matrix functions
+   * - Transforms
+   * - Motor control functions
+   * - Statistical functions
+   * - Support functions
+   * - Interpolation functions
+   *
+   * The library has separate functions for operating on 8-bit integers, 16-bit integers,
+   * 32-bit integer and 32-bit floating-point values.
+   *
+   * Using the Library
+   * ------------
+   *
+   * The library installer contains prebuilt versions of the libraries in the Lib folder.
+   * - arm_cortexM7lfdp_math.lib (Little endian and Double Precision Floating Point Unit on Cortex-M7)
+   * - arm_cortexM7bfdp_math.lib (Big endian and Double Precision Floating Point Unit on Cortex-M7)
+   * - arm_cortexM7lfsp_math.lib (Little endian and Single Precision Floating Point Unit on Cortex-M7)
+   * - arm_cortexM7bfsp_math.lib (Big endian and Single Precision Floating Point Unit on Cortex-M7)
+   * - arm_cortexM7l_math.lib (Little endian on Cortex-M7)
+   * - arm_cortexM7b_math.lib (Big endian on Cortex-M7)
+   * - arm_cortexM4lf_math.lib (Little endian and Floating Point Unit on Cortex-M4)
+   * - arm_cortexM4bf_math.lib (Big endian and Floating Point Unit on Cortex-M4)
+   * - arm_cortexM4l_math.lib (Little endian on Cortex-M4)
+   * - arm_cortexM4b_math.lib (Big endian on Cortex-M4)
+   * - arm_cortexM3l_math.lib (Little endian on Cortex-M3)
+   * - arm_cortexM3b_math.lib (Big endian on Cortex-M3)
+   * - arm_cortexM0l_math.lib (Little endian on Cortex-M0 / CortexM0+)
+   * - arm_cortexM0b_math.lib (Big endian on Cortex-M0 / CortexM0+)
+   *
+   * The library functions are declared in the public file arm_math.h which is placed in the Include folder.
+   * Simply include this file and link the appropriate library in the application and begin calling the library functions. The Library supports single
+   * public header file  arm_math.h for Cortex-M7/M4/M3/M0/M0+ with little endian and big endian. Same header file will be used for floating point unit(FPU) variants.
+   * Define the appropriate pre processor MACRO ARM_MATH_CM7 or ARM_MATH_CM4 or  ARM_MATH_CM3 or
+   * ARM_MATH_CM0 or ARM_MATH_CM0PLUS depending on the target processor in the application.
+   *
+   * Examples
+   * --------
+   *
+   * The library ships with a number of examples which demonstrate how to use the library functions.
+   *
+   * Toolchain Support
+   * ------------
+   *
+   * The library has been developed and tested with MDK-ARM version 5.14.0.0
+   * The library is being tested in GCC and IAR toolchains and updates on this activity will be made available shortly.
+   *
+   * Building the Library
+   * ------------
+   *
+   * The library installer contains a project file to re build libraries on MDK-ARM Tool chain in the CMSIS\\DSP_Lib\\Source\\ARM folder.
+   * - arm_cortexM_math.uvprojx
+   *
+   *
+   * The libraries can be built by opening the arm_cortexM_math.uvprojx project in MDK-ARM, selecting a specific target, and defining the optional pre processor MACROs detailed above.
+   *
+   * Pre-processor Macros
+   * ------------
+   *
+   * Each library project have differant pre-processor macros.
+   *
+   * - UNALIGNED_SUPPORT_DISABLE:
+   *
+   * Define macro UNALIGNED_SUPPORT_DISABLE, If the silicon does not support unaligned memory access
+   *
+   * - ARM_MATH_BIG_ENDIAN:
+   *
+   * Define macro ARM_MATH_BIG_ENDIAN to build the library for big endian targets. By default library builds for little endian targets.
+   *
+   * - ARM_MATH_MATRIX_CHECK:
+   *
+   * Define macro ARM_MATH_MATRIX_CHECK for checking on the input and output sizes of matrices
+   *
+   * - ARM_MATH_ROUNDING:
+   *
+   * Define macro ARM_MATH_ROUNDING for rounding on support functions
+   *
+   * - ARM_MATH_CMx:
+   *
+   * Define macro ARM_MATH_CM4 for building the library on Cortex-M4 target, ARM_MATH_CM3 for building library on Cortex-M3 target
+   * and ARM_MATH_CM0 for building library on Cortex-M0 target, ARM_MATH_CM0PLUS for building library on Cortex-M0+ target, and
+   * ARM_MATH_CM7 for building the library on cortex-M7.
+   *
+   * - __FPU_PRESENT:
+   *
+   * Initialize macro __FPU_PRESENT = 1 when building on FPU supported Targets. Enable this macro for M4bf and M4lf libraries
+   *
+   * 
+ * CMSIS-DSP in ARM::CMSIS Pack + * ----------------------------- + * + * The following files relevant to CMSIS-DSP are present in the ARM::CMSIS Pack directories: + * |File/Folder |Content | + * |------------------------------|------------------------------------------------------------------------| + * |\b CMSIS\\Documentation\\DSP | This documentation | + * |\b CMSIS\\DSP_Lib | Software license agreement (license.txt) | + * |\b CMSIS\\DSP_Lib\\Examples | Example projects demonstrating the usage of the library functions | + * |\b CMSIS\\DSP_Lib\\Source | Source files for rebuilding the library | + * + *
+ * Revision History of CMSIS-DSP + * ------------ + * Please refer to \ref ChangeLog_pg. + * + * Copyright Notice + * ------------ + * + * Copyright (C) 2010-2015 ARM Limited. All rights reserved. + */ + + +/** + * @defgroup groupMath Basic Math Functions + */ + +/** + * @defgroup groupFastMath Fast Math Functions + * This set of functions provides a fast approximation to sine, cosine, and square root. + * As compared to most of the other functions in the CMSIS math library, the fast math functions + * operate on individual values and not arrays. + * There are separate functions for Q15, Q31, and floating-point data. + * + */ + +/** + * @defgroup groupCmplxMath Complex Math Functions + * This set of functions operates on complex data vectors. + * The data in the complex arrays is stored in an interleaved fashion + * (real, imag, real, imag, ...). + * In the API functions, the number of samples in a complex array refers + * to the number of complex values; the array contains twice this number of + * real values. + */ + +/** + * @defgroup groupFilters Filtering Functions + */ + +/** + * @defgroup groupMatrix Matrix Functions + * + * This set of functions provides basic matrix math operations. + * The functions operate on matrix data structures. For example, + * the type + * definition for the floating-point matrix structure is shown + * below: + *
+ *     typedef struct
+ *     {
+ *       uint16_t numRows;     // number of rows of the matrix.
+ *       uint16_t numCols;     // number of columns of the matrix.
+ *       float32_t *pData;     // points to the data of the matrix.
+ *     } arm_matrix_instance_f32;
+ * 
+ * There are similar definitions for Q15 and Q31 data types. + * + * The structure specifies the size of the matrix and then points to + * an array of data. The array is of size numRows X numCols + * and the values are arranged in row order. That is, the + * matrix element (i, j) is stored at: + *
+ *     pData[i*numCols + j]
+ * 
+ * + * \par Init Functions + * There is an associated initialization function for each type of matrix + * data structure. + * The initialization function sets the values of the internal structure fields. + * Refer to the function arm_mat_init_f32(), arm_mat_init_q31() + * and arm_mat_init_q15() for floating-point, Q31 and Q15 types, respectively. + * + * \par + * Use of the initialization function is optional. However, if initialization function is used + * then the instance structure cannot be placed into a const data section. + * To place the instance structure in a const data + * section, manually initialize the data structure. For example: + *
+ * arm_matrix_instance_f32 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q31 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q15 S = {nRows, nColumns, pData};
+ * 
+ * where nRows specifies the number of rows, nColumns + * specifies the number of columns, and pData points to the + * data array. + * + * \par Size Checking + * By default all of the matrix functions perform size checking on the input and + * output matrices. For example, the matrix addition function verifies that the + * two input matrices and the output matrix all have the same number of rows and + * columns. If the size check fails the functions return: + *
+ *     ARM_MATH_SIZE_MISMATCH
+ * 
+ * Otherwise the functions return + *
+ *     ARM_MATH_SUCCESS
+ * 
+ * There is some overhead associated with this matrix size checking. + * The matrix size checking is enabled via the \#define + *
+ *     ARM_MATH_MATRIX_CHECK
+ * 
+ * within the library project settings. By default this macro is defined + * and size checking is enabled. By changing the project settings and + * undefining this macro size checking is eliminated and the functions + * run a bit faster. With size checking disabled the functions always + * return ARM_MATH_SUCCESS. + */ + +/** + * @defgroup groupTransforms Transform Functions + */ + +/** + * @defgroup groupController Controller Functions + */ + +/** + * @defgroup groupStats Statistics Functions + */ +/** + * @defgroup groupSupport Support Functions + */ + +/** + * @defgroup groupInterpolation Interpolation Functions + * These functions perform 1- and 2-dimensional interpolation of data. + * Linear interpolation is used for 1-dimensional data and + * bilinear interpolation is used for 2-dimensional data. + */ + +/** + * @defgroup groupExamples Examples + */ +#ifndef _ARM_MATH_H +#define _ARM_MATH_H + +/* ignore some GCC warnings */ +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +#define __CMSIS_GENERIC /* disable NVIC and Systick functions */ + +#if defined(ARM_MATH_CM7) + #include "core_cm7.h" +#elif defined (ARM_MATH_CM4) + #include "core_cm4.h" +#elif defined (ARM_MATH_CM3) + #include "core_cm3.h" +#elif defined (ARM_MATH_CM0) + #include "core_cm0.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_CM0PLUS) + #include "core_cm0plus.h" + #define ARM_MATH_CM0_FAMILY +#else + #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS or ARM_MATH_CM0" +#endif + +#undef __CMSIS_GENERIC /* enable NVIC and Systick functions */ +#include "string.h" +#include "math.h" +#ifdef __cplusplus +extern "C" +{ +#endif + + + /** + * @brief Macros required for reciprocal calculation in Normalized LMS + */ + +#define DELTA_Q31 (0x100) +#define DELTA_Q15 0x5 +#define INDEX_MASK 0x0000003F +#ifndef PI +#define PI 3.14159265358979f +#endif + + /** + * @brief Macros required for SINE and COSINE Fast math approximations + */ + +#define FAST_MATH_TABLE_SIZE 512 +#define FAST_MATH_Q31_SHIFT (32 - 10) +#define FAST_MATH_Q15_SHIFT (16 - 10) +#define CONTROLLER_Q31_SHIFT (32 - 9) +#define TABLE_SIZE 256 +#define TABLE_SPACING_Q31 0x400000 +#define TABLE_SPACING_Q15 0x80 + + /** + * @brief Macros required for SINE and COSINE Controller functions + */ + /* 1.31(q31) Fixed value of 2/360 */ + /* -1 to +1 is divided into 360 values so total spacing is (2/360) */ +#define INPUT_SPACING 0xB60B61 + + /** + * @brief Macro for Unaligned Support + */ +#ifndef UNALIGNED_SUPPORT_DISABLE + #define ALIGN4 +#else + #if defined (__GNUC__) + #define ALIGN4 __attribute__((aligned(4))) + #else + #define ALIGN4 __align(4) + #endif +#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */ + + /** + * @brief Error status returned by some functions in the library. + */ + + typedef enum + { + ARM_MATH_SUCCESS = 0, /**< No error */ + ARM_MATH_ARGUMENT_ERROR = -1, /**< One or more arguments are incorrect */ + ARM_MATH_LENGTH_ERROR = -2, /**< Length of data buffer is incorrect */ + ARM_MATH_SIZE_MISMATCH = -3, /**< Size of matrices is not compatible with the operation. */ + ARM_MATH_NANINF = -4, /**< Not-a-number (NaN) or infinity is generated */ + ARM_MATH_SINGULAR = -5, /**< Generated by matrix inversion if the input matrix is singular and cannot be inverted. */ + ARM_MATH_TEST_FAILURE = -6 /**< Test Failed */ + } arm_status; + + /** + * @brief 8-bit fractional data type in 1.7 format. + */ + typedef int8_t q7_t; + + /** + * @brief 16-bit fractional data type in 1.15 format. + */ + typedef int16_t q15_t; + + /** + * @brief 32-bit fractional data type in 1.31 format. + */ + typedef int32_t q31_t; + + /** + * @brief 64-bit fractional data type in 1.63 format. + */ + typedef int64_t q63_t; + + /** + * @brief 32-bit floating-point type definition. + */ + typedef float float32_t; + + /** + * @brief 64-bit floating-point type definition. + */ + typedef double float64_t; + + /** + * @brief definition to read/write two 16 bit values. + */ +#if defined __CC_ARM + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined __GNUC__ + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined __ICCARM__ + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED + +#elif defined __CSMC__ + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED + +#elif defined __TASKING__ + #define __SIMD32_TYPE __unaligned int32_t + #define CMSIS_UNUSED + +#else + #error Unknown compiler +#endif + +#define __SIMD32(addr) (*(__SIMD32_TYPE **) & (addr)) +#define __SIMD32_CONST(addr) ((__SIMD32_TYPE *)(addr)) +#define _SIMD32_OFFSET(addr) (*(__SIMD32_TYPE *) (addr)) +#define __SIMD64(addr) (*(int64_t **) & (addr)) + +#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) + /** + * @brief definition to pack two 16 bit values. + */ +#define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \ + (((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) ) +#define __PKHTB(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0xFFFF0000) | \ + (((int32_t)(ARG2) >> ARG3) & (int32_t)0x0000FFFF) ) + +#endif + + + /** + * @brief definition to pack four 8 bit values. + */ +#ifndef ARM_MATH_BIG_ENDIAN + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v0) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v1) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v2) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v3) << 24) & (int32_t)0xFF000000) ) +#else + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v3) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v2) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v1) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v0) << 24) & (int32_t)0xFF000000) ) + +#endif + + + /** + * @brief Clips Q63 to Q31 values. + */ + static __INLINE q31_t clip_q63_to_q31( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFFFFFF ^ ((q31_t) (x >> 63)))) : (q31_t) x; + } + + /** + * @brief Clips Q63 to Q15 values. + */ + static __INLINE q15_t clip_q63_to_q15( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFF ^ ((q15_t) (x >> 63)))) : (q15_t) (x >> 15); + } + + /** + * @brief Clips Q31 to Q7 values. + */ + static __INLINE q7_t clip_q31_to_q7( + q31_t x) + { + return ((q31_t) (x >> 24) != ((q31_t) x >> 23)) ? + ((0x7F ^ ((q7_t) (x >> 31)))) : (q7_t) x; + } + + /** + * @brief Clips Q31 to Q15 values. + */ + static __INLINE q15_t clip_q31_to_q15( + q31_t x) + { + return ((q31_t) (x >> 16) != ((q31_t) x >> 15)) ? + ((0x7FFF ^ ((q15_t) (x >> 31)))) : (q15_t) x; + } + + /** + * @brief Multiplies 32 X 64 and returns 32 bit result in 2.30 format. + */ + + static __INLINE q63_t mult32x64( + q63_t x, + q31_t y) + { + return ((((q63_t) (x & 0x00000000FFFFFFFF) * y) >> 32) + + (((q63_t) (x >> 32) * y))); + } + +/* + #if defined (ARM_MATH_CM0_FAMILY) && defined ( __CC_ARM ) + #define __CLZ __clz + #endif + */ +/* note: function can be removed when all toolchain support __CLZ for Cortex-M0 */ +#if defined (ARM_MATH_CM0_FAMILY) && ((defined (__ICCARM__)) ) + static __INLINE uint32_t __CLZ( + q31_t data); + + static __INLINE uint32_t __CLZ( + q31_t data) + { + uint32_t count = 0; + uint32_t mask = 0x80000000; + + while((data & mask) == 0) + { + count += 1u; + mask = mask >> 1u; + } + + return (count); + } +#endif + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type. + */ + + static __INLINE uint32_t arm_recip_q31( + q31_t in, + q31_t * dst, + q31_t * pRecipTable) + { + q31_t out; + uint32_t tempVal; + uint32_t index, i; + uint32_t signBits; + + if(in > 0) + { + signBits = ((uint32_t) (__CLZ( in) - 1)); + } + else + { + signBits = ((uint32_t) (__CLZ(-in) - 1)); + } + + /* Convert input sample to 1.31 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 24); + index = (index & INDEX_MASK); + + /* 1.31 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0u; i < 2u; i++) + { + tempVal = (uint32_t) (((q63_t) in * out) >> 31); + tempVal = 0x7FFFFFFFu - tempVal; + /* 1.31 with exp 1 */ + /* out = (q31_t) (((q63_t) out * tempVal) >> 30); */ + out = clip_q63_to_q31(((q63_t) out * tempVal) >> 30); + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1u); + } + + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type. + */ + static __INLINE uint32_t arm_recip_q15( + q15_t in, + q15_t * dst, + q15_t * pRecipTable) + { + q15_t out = 0; + uint32_t tempVal = 0; + uint32_t index = 0, i = 0; + uint32_t signBits = 0; + + if(in > 0) + { + signBits = ((uint32_t)(__CLZ( in) - 17)); + } + else + { + signBits = ((uint32_t)(__CLZ(-in) - 17)); + } + + /* Convert input sample to 1.15 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 8); + index = (index & INDEX_MASK); + + /* 1.15 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0u; i < 2u; i++) + { + tempVal = (uint32_t) (((q31_t) in * out) >> 15); + tempVal = 0x7FFFu - tempVal; + /* 1.15 with exp 1 */ + out = (q15_t) (((q31_t) out * tempVal) >> 14); + /* out = clip_q31_to_q15(((q31_t) out * tempVal) >> 14); */ + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1); + } + + + /* + * @brief C custom defined intrinisic function for only M0 processors + */ +#if defined(ARM_MATH_CM0_FAMILY) + static __INLINE q31_t __SSAT( + q31_t x, + uint32_t y) + { + int32_t posMax, negMin; + uint32_t i; + + posMax = 1; + for (i = 0; i < (y - 1); i++) + { + posMax = posMax * 2; + } + + if(x > 0) + { + posMax = (posMax - 1); + + if(x > posMax) + { + x = posMax; + } + } + else + { + negMin = -posMax; + + if(x < negMin) + { + x = negMin; + } + } + return (x); + } +#endif /* end of ARM_MATH_CM0_FAMILY */ + + + /* + * @brief C custom defined intrinsic function for M3 and M0 processors + */ +#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) + + /* + * @brief C custom defined QADD8 for M3 and M0 processors + */ + static __INLINE uint32_t __QADD8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) + (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) + (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) + (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) + (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QSUB8 for M3 and M0 processors + */ + static __INLINE uint32_t __QSUB8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) - (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) - (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) - (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) - (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QADD16 for M3 and M0 processors + */ + static __INLINE uint32_t __QADD16( + uint32_t x, + uint32_t y) + { +/* q31_t r, s; without initialisation 'arm_offset_q15 test' fails but 'intrinsic' tests pass! for armCC */ + q31_t r = 0, s = 0; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHADD16 for M3 and M0 processors + */ + static __INLINE uint32_t __SHADD16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSUB16 for M3 and M0 processors + */ + static __INLINE uint32_t __QSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSUB16 for M3 and M0 processors + */ + static __INLINE uint32_t __SHSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QASX for M3 and M0 processors + */ + static __INLINE uint32_t __QASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHASX for M3 and M0 processors + */ + static __INLINE uint32_t __SHASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSAX for M3 and M0 processors + */ + static __INLINE uint32_t __QSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSAX for M3 and M0 processors + */ + static __INLINE uint32_t __SHSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SMUSDX for M3 and M0 processors + */ + static __INLINE uint32_t __SMUSDX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + /* + * @brief C custom defined SMUADX for M3 and M0 processors + */ + static __INLINE uint32_t __SMUADX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + + /* + * @brief C custom defined QADD for M3 and M0 processors + */ + static __INLINE int32_t __QADD( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x + (q31_t)y))); + } + + + /* + * @brief C custom defined QSUB for M3 and M0 processors + */ + static __INLINE int32_t __QSUB( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x - (q31_t)y))); + } + + + /* + * @brief C custom defined SMLAD for M3 and M0 processors + */ + static __INLINE uint32_t __SMLAD( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLADX for M3 and M0 processors + */ + static __INLINE uint32_t __SMLADX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLSDX for M3 and M0 processors + */ + static __INLINE uint32_t __SMLSDX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALD for M3 and M0 processors + */ + static __INLINE uint64_t __SMLALD( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) (y >> 16)) + ((q15_t) x * (q15_t) y)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALDX for M3 and M0 processors + */ + static __INLINE uint64_t __SMLALDX( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) y)) + ((q15_t) x * (q15_t) (y >> 16)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMUAD for M3 and M0 processors + */ + static __INLINE uint32_t __SMUAD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SMUSD for M3 and M0 processors + */ + static __INLINE uint32_t __SMUSD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SXTB16 for M3 and M0 processors + */ + static __INLINE uint32_t __SXTB16( + uint32_t x) + { + return ((uint32_t)(((((q31_t)x << 24) >> 24) & (q31_t)0x0000FFFF) | + ((((q31_t)x << 8) >> 8) & (q31_t)0xFFFF0000) )); + } + +#endif /* defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ + + + /** + * @brief Instance structure for the Q7 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q7_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q7; + + /** + * @brief Instance structure for the Q15 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_f32; + + + /** + * @brief Processing function for the Q7 FIR filter. + * @param[in] S points to an instance of the Q7 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q7( + const arm_fir_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 FIR filter. + * @param[in,out] S points to an instance of the Q7 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed. + */ + void arm_fir_init_q7( + arm_fir_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR filter. + * @param[in] S points to an instance of the Q15 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q15 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR filter. + * @param[in,out] S points to an instance of the Q15 FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + * @return The function returns ARM_MATH_SUCCESS if initialization was successful or ARM_MATH_ARGUMENT_ERROR if + * numTaps is not a supported value. + */ + arm_status arm_fir_init_q15( + arm_fir_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR filter. + * @param[in] S points to an instance of the Q31 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q31 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR filter. + * @param[in,out] S points to an instance of the Q31 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_q31( + arm_fir_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR filter. + * @param[in] S points to an instance of the floating-point FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_f32( + const arm_fir_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR filter. + * @param[in,out] S points to an instance of the floating-point FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_f32( + arm_fir_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 Biquad cascade filter. + */ + typedef struct + { + int8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q15_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q15_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + int8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q15; + + /** + * @brief Instance structure for the Q31 Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q31_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q31; + + /** + * @brief Instance structure for the floating-point Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_casd_df1_inst_f32; + + + /** + * @brief Processing function for the Q15 Biquad cascade filter. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q15( + arm_biquad_casd_df1_inst_q15 * S, + uint8_t numStages, + q15_t * pCoeffs, + q15_t * pState, + int8_t postShift); + + + /** + * @brief Fast but less precise processing function for the Q15 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 Biquad cascade filter + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fast but less precise processing function for the Q31 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q31( + arm_biquad_casd_df1_inst_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q31_t * pState, + int8_t postShift); + + + /** + * @brief Processing function for the floating-point Biquad cascade filter. + * @param[in] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_f32( + const arm_biquad_casd_df1_inst_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point Biquad cascade filter. + * @param[in,out] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df1_init_f32( + arm_biquad_casd_df1_inst_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float32_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f32; + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float64_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f64; + + /** + * @brief Instance structure for the Q15 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q15_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q15; + + /** + * @brief Instance structure for the Q31 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q31_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q31; + + + /** + * @brief Floating-point matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pScratch); + + + /** + * @brief Q31, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_f32( + const arm_matrix_instance_f32 * pSrc, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q15( + const arm_matrix_instance_q15 * pSrc, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q31( + const arm_matrix_instance_q31 * pSrc, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q15 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q31 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix scaling. + * @param[in] pSrc points to the input matrix + * @param[in] scale scale factor + * @param[out] pDst points to the output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_f32( + const arm_matrix_instance_f32 * pSrc, + float32_t scale, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q15( + const arm_matrix_instance_q15 * pSrc, + q15_t scaleFract, + int32_t shift, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q31( + const arm_matrix_instance_q31 * pSrc, + q31_t scaleFract, + int32_t shift, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q31( + arm_matrix_instance_q31 * S, + uint16_t nRows, + uint16_t nColumns, + q31_t * pData); + + + /** + * @brief Q15 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q15( + arm_matrix_instance_q15 * S, + uint16_t nRows, + uint16_t nColumns, + q15_t * pData); + + + /** + * @brief Floating-point matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_f32( + arm_matrix_instance_f32 * S, + uint16_t nRows, + uint16_t nColumns, + float32_t * pData); + + + + /** + * @brief Instance structure for the Q15 PID Control. + */ + typedef struct + { + q15_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ +#ifdef ARM_MATH_CM0_FAMILY + q15_t A1; + q15_t A2; +#else + q31_t A1; /**< The derived gain A1 = -Kp - 2Kd | Kd.*/ +#endif + q15_t state[3]; /**< The state array of length 3. */ + q15_t Kp; /**< The proportional gain. */ + q15_t Ki; /**< The integral gain. */ + q15_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q15; + + /** + * @brief Instance structure for the Q31 PID Control. + */ + typedef struct + { + q31_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + q31_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + q31_t A2; /**< The derived gain, A2 = Kd . */ + q31_t state[3]; /**< The state array of length 3. */ + q31_t Kp; /**< The proportional gain. */ + q31_t Ki; /**< The integral gain. */ + q31_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q31; + + /** + * @brief Instance structure for the floating-point PID Control. + */ + typedef struct + { + float32_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + float32_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + float32_t A2; /**< The derived gain, A2 = Kd . */ + float32_t state[3]; /**< The state array of length 3. */ + float32_t Kp; /**< The proportional gain. */ + float32_t Ki; /**< The integral gain. */ + float32_t Kd; /**< The derivative gain. */ + } arm_pid_instance_f32; + + + + /** + * @brief Initialization function for the floating-point PID Control. + * @param[in,out] S points to an instance of the PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_f32( + arm_pid_instance_f32 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + */ + void arm_pid_reset_f32( + arm_pid_instance_f32 * S); + + + /** + * @brief Initialization function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q31( + arm_pid_instance_q31 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + */ + + void arm_pid_reset_q31( + arm_pid_instance_q31 * S); + + + /** + * @brief Initialization function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q15( + arm_pid_instance_q15 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q15 PID Control. + * @param[in,out] S points to an instance of the q15 PID Control structure + */ + void arm_pid_reset_q15( + arm_pid_instance_q15 * S); + + + /** + * @brief Instance structure for the floating-point Linear Interpolate function. + */ + typedef struct + { + uint32_t nValues; /**< nValues */ + float32_t x1; /**< x1 */ + float32_t xSpacing; /**< xSpacing */ + float32_t *pYData; /**< pointer to the table of Y values */ + } arm_linear_interp_instance_f32; + + /** + * @brief Instance structure for the floating-point bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + float32_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_f32; + + /** + * @brief Instance structure for the Q31 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q31_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q31; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q15_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q15; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q7_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q7; + + + /** + * @brief Q7 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the Sin twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q15( + arm_cfft_radix2_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q15( + const arm_cfft_radix2_instance_q15 * S, + q15_t * pSrc); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q15( + arm_cfft_radix4_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_q15( + const arm_cfft_radix4_instance_q15 * S, + q15_t * pSrc); + + /** + * @brief Instance structure for the Radix-2 Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q31; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q31( + arm_cfft_radix2_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q31( + const arm_cfft_radix2_instance_q31 * S, + q31_t * pSrc); + + /** + * @brief Instance structure for the Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q31; + +/* Deprecated */ + void arm_cfft_radix4_q31( + const arm_cfft_radix4_instance_q31 * S, + q31_t * pSrc); + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q31( + arm_cfft_radix4_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix2_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_f32( + arm_cfft_radix2_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_f32( + const arm_cfft_radix2_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix4_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_f32( + arm_cfft_radix4_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_f32( + const arm_cfft_radix4_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q15_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q15; + +void arm_cfft_q15( + const arm_cfft_instance_q15 * S, + q15_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q31; + +void arm_cfft_q31( + const arm_cfft_instance_q31 * S, + q31_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_f32; + + void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + float32_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the Q15 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q15_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q15_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q15; + + arm_status arm_rfft_init_q15( + arm_rfft_instance_q15 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q15( + const arm_rfft_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst); + + /** + * @brief Instance structure for the Q31 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q31_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q31_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q31; + + arm_status arm_rfft_init_q31( + arm_rfft_instance_q31 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q31( + const arm_rfft_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint16_t fftLenBy2; /**< length of the complex FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + float32_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + float32_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_f32; + + arm_status arm_rfft_init_f32( + arm_rfft_instance_f32 * S, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_f32( + const arm_rfft_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ +typedef struct + { + arm_cfft_instance_f32 Sint; /**< Internal CFFT structure. */ + uint16_t fftLenRFFT; /**< length of the real sequence */ + float32_t * pTwiddleRFFT; /**< Twiddle factors real stage */ + } arm_rfft_fast_instance_f32 ; + +arm_status arm_rfft_fast_init_f32 ( + arm_rfft_fast_instance_f32 * S, + uint16_t fftLen); + +void arm_rfft_fast_f32( + arm_rfft_fast_instance_f32 * S, + float32_t * p, float32_t * pOut, + uint8_t ifftFlag); + + /** + * @brief Instance structure for the floating-point DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + float32_t normalize; /**< normalizing factor. */ + float32_t *pTwiddle; /**< points to the twiddle factor table. */ + float32_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_f32 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_f32; + + + /** + * @brief Initialization function for the floating-point DCT4/IDCT4. + * @param[in,out] S points to an instance of floating-point DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of floating-point RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of floating-point CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if fftLenReal is not a supported transform length. + */ + arm_status arm_dct4_init_f32( + arm_dct4_instance_f32 * S, + arm_rfft_instance_f32 * S_RFFT, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint16_t N, + uint16_t Nby2, + float32_t normalize); + + + /** + * @brief Processing function for the floating-point DCT4/IDCT4. + * @param[in] S points to an instance of the floating-point DCT4/IDCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_f32( + const arm_dct4_instance_f32 * S, + float32_t * pState, + float32_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q31 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q31_t normalize; /**< normalizing factor. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + q31_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q31 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q31; + + + /** + * @brief Initialization function for the Q31 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q31 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q31 RFFT/RIFFT structure + * @param[in] S_CFFT points to an instance of Q31 CFFT/CIFFT structure + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q31( + arm_dct4_instance_q31 * S, + arm_rfft_instance_q31 * S_RFFT, + arm_cfft_radix4_instance_q31 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q31_t normalize); + + + /** + * @brief Processing function for the Q31 DCT4/IDCT4. + * @param[in] S points to an instance of the Q31 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q31( + const arm_dct4_instance_q31 * S, + q31_t * pState, + q31_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q15 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q15_t normalize; /**< normalizing factor. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + q15_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q15 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q15; + + + /** + * @brief Initialization function for the Q15 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q15 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q15 RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of Q15 CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q15( + arm_dct4_instance_q15 * S, + arm_rfft_instance_q15 * S_RFFT, + arm_cfft_radix4_instance_q15 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q15_t normalize); + + + /** + * @brief Processing function for the Q15 DCT4/IDCT4. + * @param[in] S points to an instance of the Q15 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q15( + const arm_dct4_instance_q15 * S, + q15_t * pState, + q15_t * pInlineBuffer); + + + /** + * @brief Floating-point vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a floating-point vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scale scale factor to be applied + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_f32( + float32_t * pSrc, + float32_t scale, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q7 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q7( + q7_t * pSrc, + q7_t scaleFract, + int8_t shift, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q15 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q15( + q15_t * pSrc, + q15_t scaleFract, + int8_t shift, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q31 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q31( + q31_t * pSrc, + q31_t scaleFract, + int8_t shift, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Dot product of floating-point vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t blockSize, + float32_t * result); + + + /** + * @brief Dot product of Q7 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q7( + q7_t * pSrcA, + q7_t * pSrcB, + uint32_t blockSize, + q31_t * result); + + + /** + * @brief Dot product of Q15 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Dot product of Q31 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Shifts the elements of a Q7 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q7( + q7_t * pSrc, + int8_t shiftBits, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q15 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q15( + q15_t * pSrc, + int8_t shiftBits, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q31 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q31( + q31_t * pSrc, + int8_t shiftBits, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_f32( + float32_t * pSrc, + float32_t offset, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q7( + q7_t * pSrc, + q7_t offset, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q15( + q15_t * pSrc, + q15_t offset, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q31( + q31_t * pSrc, + q31_t offset, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a floating-point vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q7 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a floating-point vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_f32( + float32_t value, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q7 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q7( + q7_t value, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q15 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q15( + q15_t value, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q31 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q31( + q31_t value, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Partial convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q7 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Partial convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Instance structure for the Q15 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_f32; + + + /** + * @brief Processing function for the floating-point FIR decimator. + * @param[in] S points to an instance of the floating-point FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_f32( + const arm_fir_decimate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR decimator. + * @param[in,out] S points to an instance of the floating-point FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_f32( + arm_fir_decimate_instance_f32 * S, + uint16_t numTaps, + uint8_t M, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR decimator. + * @param[in,out] S points to an instance of the Q15 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q15( + arm_fir_decimate_instance_q15 * S, + uint16_t numTaps, + uint8_t M, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR decimator. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q31( + const arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + /** + * @brief Processing function for the Q31 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q31( + arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR decimator. + * @param[in,out] S points to an instance of the Q31 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q31( + arm_fir_decimate_instance_q31 * S, + uint16_t numTaps, + uint8_t M, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q15_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q31_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + float32_t *pState; /**< points to the state variable array. The array is of length phaseLength+numTaps-1. */ + } arm_fir_interpolate_instance_f32; + + + /** + * @brief Processing function for the Q15 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q15( + const arm_fir_interpolate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR interpolator. + * @param[in,out] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q15( + arm_fir_interpolate_instance_q15 * S, + uint8_t L, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q31( + const arm_fir_interpolate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR interpolator. + * @param[in,out] S points to an instance of the Q31 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q31( + arm_fir_interpolate_instance_q31 * S, + uint8_t L, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR interpolator. + * @param[in] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_f32( + const arm_fir_interpolate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR interpolator. + * @param[in,out] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_f32( + arm_fir_interpolate_instance_f32 * S, + uint8_t L, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the high precision Q31 Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q63_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< additional shift, in bits, applied to each output sample. */ + } arm_biquad_cas_df1_32x64_ins_q31; + + + /** + * @param[in] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cas_df1_32x64_q31( + const arm_biquad_cas_df1_32x64_ins_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @param[in,out] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cas_df1_32x64_init_q31( + arm_biquad_cas_df1_32x64_ins_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q63_t * pState, + uint8_t postShift); + + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_stereo_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float64_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float64_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f64; + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f32( + const arm_biquad_cascade_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. 2 channels + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_stereo_df2T_f32( + const arm_biquad_cascade_stereo_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f64( + const arm_biquad_cascade_df2T_instance_f64 * S, + float64_t * pSrc, + float64_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f32( + arm_biquad_cascade_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_stereo_df2T_init_f32( + arm_biquad_cascade_stereo_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f64( + arm_biquad_cascade_df2T_instance_f64 * S, + uint8_t numStages, + float64_t * pCoeffs, + float64_t * pState); + + + /** + * @brief Instance structure for the Q15 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_f32; + + + /** + * @brief Initialization function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q15( + arm_fir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pCoeffs, + q15_t * pState); + + + /** + * @brief Processing function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q15( + const arm_fir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q31( + arm_fir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pCoeffs, + q31_t * pState); + + + /** + * @brief Processing function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q31( + const arm_fir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_f32( + arm_fir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Processing function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_f32( + const arm_fir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q15_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q15_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q31_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q31_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + float32_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + float32_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_f32; + + + /** + * @brief Processing function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_f32( + const arm_iir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize-1. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_f32( + arm_iir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pkCoeffs, + float32_t * pvCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q31( + const arm_iir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_q31( + arm_iir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pkCoeffs, + q31_t * pvCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the Q15 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q15( + const arm_iir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the fixed-point Q15 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process per call. + */ + void arm_iir_lattice_init_q15( + arm_iir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pkCoeffs, + q15_t * pvCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the floating-point LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that controls filter coefficient updates. */ + } arm_lms_instance_f32; + + + /** + * @brief Processing function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_f32( + const arm_lms_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_init_f32( + arm_lms_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q15; + + + /** + * @brief Initialization function for the Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q15( + arm_lms_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Processing function for Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q15( + const arm_lms_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q31; + + + /** + * @brief Processing function for Q31 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q31( + const arm_lms_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 LMS filter. + * @param[in] S points to an instance of the Q31 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q31( + arm_lms_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Instance structure for the floating-point normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that control filter coefficient updates. */ + float32_t energy; /**< saves previous frame energy. */ + float32_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_f32; + + + /** + * @brief Processing function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_f32( + arm_lms_norm_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_init_f32( + arm_lms_norm_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q31_t *recipTable; /**< points to the reciprocal initial value table. */ + q31_t energy; /**< saves previous frame energy. */ + q31_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q31; + + + /** + * @brief Processing function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q31( + arm_lms_norm_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q31( + arm_lms_norm_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Instance structure for the Q15 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< Number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q15_t *recipTable; /**< Points to the reciprocal initial value table. */ + q15_t energy; /**< saves previous frame energy. */ + q15_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q15; + + + /** + * @brief Processing function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q15( + arm_lms_norm_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q15( + arm_lms_norm_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Correlation of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Correlation of Q15 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_correlate_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Instance structure for the floating-point sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + float32_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_f32; + + /** + * @brief Instance structure for the Q31 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q31_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q31; + + /** + * @brief Instance structure for the Q15 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q15_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q15; + + /** + * @brief Instance structure for the Q7 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q7_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q7; + + + /** + * @brief Processing function for the floating-point sparse FIR filter. + * @param[in] S points to an instance of the floating-point sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_f32( + arm_fir_sparse_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + float32_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point sparse FIR filter. + * @param[in,out] S points to an instance of the floating-point sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_f32( + arm_fir_sparse_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 sparse FIR filter. + * @param[in] S points to an instance of the Q31 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q31( + arm_fir_sparse_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + q31_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 sparse FIR filter. + * @param[in,out] S points to an instance of the Q31 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q31( + arm_fir_sparse_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 sparse FIR filter. + * @param[in] S points to an instance of the Q15 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q15( + arm_fir_sparse_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + q15_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 sparse FIR filter. + * @param[in,out] S points to an instance of the Q15 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q15( + arm_fir_sparse_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q7 sparse FIR filter. + * @param[in] S points to an instance of the Q7 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q7( + arm_fir_sparse_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + q7_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 sparse FIR filter. + * @param[in,out] S points to an instance of the Q7 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q7( + arm_fir_sparse_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Floating-point sin_cos function. + * @param[in] theta input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cos output. + */ + void arm_sin_cos_f32( + float32_t theta, + float32_t * pSinVal, + float32_t * pCosVal); + + + /** + * @brief Q31 sin_cos function. + * @param[in] theta scaled input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cosine output. + */ + void arm_sin_cos_q31( + q31_t theta, + q31_t * pSinVal, + q31_t * pCosVal); + + + /** + * @brief Floating-point complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + /** + * @brief Q31 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup PID PID Motor Control + * + * A Proportional Integral Derivative (PID) controller is a generic feedback control + * loop mechanism widely used in industrial control systems. + * A PID controller is the most commonly used type of feedback controller. + * + * This set of functions implements (PID) controllers + * for Q15, Q31, and floating-point data types. The functions operate on a single sample + * of data and each call to the function returns a single processed value. + * S points to an instance of the PID control data structure. in + * is the input sample value. The functions return the output value. + * + * \par Algorithm: + *
+   *    y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]
+   *    A0 = Kp + Ki + Kd
+   *    A1 = (-Kp ) - (2 * Kd )
+   *    A2 = Kd  
+ * + * \par + * where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant + * + * \par + * \image html PID.gif "Proportional Integral Derivative Controller" + * + * \par + * The PID controller calculates an "error" value as the difference between + * the measured output and the reference input. + * The controller attempts to minimize the error by adjusting the process control inputs. + * The proportional value determines the reaction to the current error, + * the integral value determines the reaction based on the sum of recent errors, + * and the derivative value determines the reaction based on the rate at which the error has been changing. + * + * \par Instance Structure + * The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure. + * A separate instance structure must be defined for each PID Controller. + * There are separate instance structure declarations for each of the 3 supported data types. + * + * \par Reset Functions + * There is also an associated reset function for each data type which clears the state array. + * + * \par Initialization Functions + * There is also an associated initialization function for each data type. + * The initialization function performs the following operations: + * - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains. + * - Zeros out the values in the state buffer. + * + * \par + * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function. + * + * \par Fixed-Point Behavior + * Care must be taken when using the fixed-point versions of the PID Controller functions. + * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup PID + * @{ + */ + + /** + * @brief Process function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + */ + static __INLINE float32_t arm_pid_f32( + arm_pid_instance_f32 * S, + float32_t in) + { + float32_t out; + + /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2] */ + out = (S->A0 * in) + + (S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + + } + + /** + * @brief Process function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 64-bit accumulator. + * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. + * Thus, if the accumulator result overflows it wraps around rather than clip. + * In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions. + * After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format. + */ + static __INLINE q31_t arm_pid_q31( + arm_pid_instance_q31 * S, + q31_t in) + { + q63_t acc; + q31_t out; + + /* acc = A0 * x[n] */ + acc = (q63_t) S->A0 * in; + + /* acc += A1 * x[n-1] */ + acc += (q63_t) S->A1 * S->state[0]; + + /* acc += A2 * x[n-2] */ + acc += (q63_t) S->A2 * S->state[1]; + + /* convert output to 1.31 format to add y[n-1] */ + out = (q31_t) (acc >> 31u); + + /* out += y[n-1] */ + out += S->state[2]; + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + + /** + * @brief Process function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using a 64-bit internal accumulator. + * Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result. + * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. + * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. + * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. + * Lastly, the accumulator is saturated to yield a result in 1.15 format. + */ + static __INLINE q15_t arm_pid_q15( + arm_pid_instance_q15 * S, + q15_t in) + { + q63_t acc; + q15_t out; + +#ifndef ARM_MATH_CM0_FAMILY + __SIMD32_TYPE *vstate; + + /* Implementation of PID controller */ + + /* acc = A0 * x[n] */ + acc = (q31_t) __SMUAD((uint32_t)S->A0, (uint32_t)in); + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + vstate = __SIMD32_CONST(S->state); + acc = (q63_t)__SMLALD((uint32_t)S->A1, (uint32_t)*vstate, (uint64_t)acc); +#else + /* acc = A0 * x[n] */ + acc = ((q31_t) S->A0) * in; + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + acc += (q31_t) S->A1 * S->state[0]; + acc += (q31_t) S->A2 * S->state[1]; +#endif + + /* acc += y[n-1] */ + acc += (q31_t) S->state[2] << 15; + + /* saturate the output */ + out = (q15_t) (__SSAT((acc >> 15), 16)); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + /** + * @} end of PID group + */ + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f32( + const arm_matrix_instance_f32 * src, + arm_matrix_instance_f32 * dst); + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f64( + const arm_matrix_instance_f64 * src, + arm_matrix_instance_f64 * dst); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup clarke Vector Clarke Transform + * Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector. + * Generally the Clarke transform uses three-phase currents Ia, Ib and Ic to calculate currents + * in the two-phase orthogonal stator axis Ialpha and Ibeta. + * When Ialpha is superposed with Ia as shown in the figure below + * \image html clarke.gif Stator current space vector and its components in (a,b). + * and Ia + Ib + Ic = 0, in this condition Ialpha and Ibeta + * can be calculated using only Ia and Ib. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeFormula.gif + * where Ia and Ib are the instantaneous stator phases and + * pIalpha and pIbeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup clarke + * @{ + */ + + /** + * + * @brief Floating-point Clarke transform + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + */ + static __INLINE void arm_clarke_f32( + float32_t Ia, + float32_t Ib, + float32_t * pIalpha, + float32_t * pIbeta) + { + /* Calculate pIalpha using the equation, pIalpha = Ia */ + *pIalpha = Ia; + + /* Calculate pIbeta using the equation, pIbeta = (1/sqrt(3)) * Ia + (2/sqrt(3)) * Ib */ + *pIbeta = ((float32_t) 0.57735026919 * Ia + (float32_t) 1.15470053838 * Ib); + } + + + /** + * @brief Clarke transform for Q31 version + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + static __INLINE void arm_clarke_q31( + q31_t Ia, + q31_t Ib, + q31_t * pIalpha, + q31_t * pIbeta) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIalpha from Ia by equation pIalpha = Ia */ + *pIalpha = Ia; + + /* Intermediate product is calculated by (1/(sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) Ia * 0x24F34E8B) >> 30); + + /* Intermediate product is calculated by (2/sqrt(3) * Ib) */ + product2 = (q31_t) (((q63_t) Ib * 0x49E69D16) >> 30); + + /* pIbeta is calculated by adding the intermediate products */ + *pIbeta = __QADD(product1, product2); + } + + /** + * @} end of clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q31( + q7_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_clarke Vector Inverse Clarke Transform + * Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeInvFormula.gif + * where pIa and pIb are the instantaneous stator phases and + * Ialpha and Ibeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_clarke + * @{ + */ + + /** + * @brief Floating-point Inverse Clarke transform + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + */ + static __INLINE void arm_inv_clarke_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pIa, + float32_t * pIb) + { + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */ + *pIb = -0.5f * Ialpha + 0.8660254039f * Ibeta; + } + + + /** + * @brief Inverse Clarke transform for Q31 version + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the subtraction, hence there is no risk of overflow. + */ + static __INLINE void arm_inv_clarke_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pIa, + q31_t * pIb) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Intermediate product is calculated by (1/(2*sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (0x40000000)) >> 31); + + /* Intermediate product is calculated by (1/sqrt(3) * pIb) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (0x6ED9EBA1)) >> 31); + + /* pIb is calculated by subtracting the products */ + *pIb = __QSUB(product2, product1); + } + + /** + * @} end of inv_clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q15( + q7_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup park Vector Park Transform + * + * Forward Park transform converts the input two-coordinate vector to flux and torque components. + * The Park transform can be used to realize the transformation of the Ialpha and the Ibeta currents + * from the stationary to the moving reference frame and control the spatial relationship between + * the stator vector current and rotor flux vector. + * If we consider the d axis aligned with the rotor flux, the diagram below shows the + * current vector and the relationship from the two reference frames: + * \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame" + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkFormula.gif + * where Ialpha and Ibeta are the stator vector components, + * pId and pIq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup park + * @{ + */ + + /** + * @brief Floating-point Park transform + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * The function implements the forward Park transform. + * + */ + static __INLINE void arm_park_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pId, + float32_t * pIq, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pId using the equation, pId = Ialpha * cosVal + Ibeta * sinVal */ + *pId = Ialpha * cosVal + Ibeta * sinVal; + + /* Calculate pIq using the equation, pIq = - Ialpha * sinVal + Ibeta * cosVal */ + *pIq = -Ialpha * sinVal + Ibeta * cosVal; + } + + + /** + * @brief Park transform for Q31 version + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition and subtraction, hence there is no risk of overflow. + */ + static __INLINE void arm_park_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pId, + q31_t * pIq, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Ialpha * cosVal) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * sinVal) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Ialpha * sinVal) */ + product3 = (q31_t) (((q63_t) (Ialpha) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * cosVal) */ + product4 = (q31_t) (((q63_t) (Ibeta) * (cosVal)) >> 31); + + /* Calculate pId by adding the two intermediate products 1 and 2 */ + *pId = __QADD(product1, product2); + + /* Calculate pIq by subtracting the two intermediate products 3 from 4 */ + *pIq = __QSUB(product4, product3); + } + + /** + * @} end of park group + */ + + /** + * @brief Converts the elements of the Q7 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q7_to_float( + q7_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_park Vector Inverse Park transform + * Inverse Park transform converts the input flux and torque components to two-coordinate vector. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkInvFormula.gif + * where pIalpha and pIbeta are the stator vector components, + * Id and Iq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_park + * @{ + */ + + /** + * @brief Floating-point Inverse Park transform + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + */ + static __INLINE void arm_inv_park_f32( + float32_t Id, + float32_t Iq, + float32_t * pIalpha, + float32_t * pIbeta, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pIalpha using the equation, pIalpha = Id * cosVal - Iq * sinVal */ + *pIalpha = Id * cosVal - Iq * sinVal; + + /* Calculate pIbeta using the equation, pIbeta = Id * sinVal + Iq * cosVal */ + *pIbeta = Id * sinVal + Iq * cosVal; + } + + + /** + * @brief Inverse Park transform for Q31 version + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + static __INLINE void arm_inv_park_q31( + q31_t Id, + q31_t Iq, + q31_t * pIalpha, + q31_t * pIbeta, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Id * cosVal) */ + product1 = (q31_t) (((q63_t) (Id) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Iq * sinVal) */ + product2 = (q31_t) (((q63_t) (Iq) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Id * sinVal) */ + product3 = (q31_t) (((q63_t) (Id) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Iq * cosVal) */ + product4 = (q31_t) (((q63_t) (Iq) * (cosVal)) >> 31); + + /* Calculate pIalpha by using the two intermediate products 1 and 2 */ + *pIalpha = __QSUB(product1, product2); + + /* Calculate pIbeta by using the two intermediate products 3 and 4 */ + *pIbeta = __QADD(product4, product3); + } + + /** + * @} end of Inverse park group + */ + + + /** + * @brief Converts the elements of the Q31 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_float( + q31_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup LinearInterpolate Linear Interpolation + * + * Linear interpolation is a method of curve fitting using linear polynomials. + * Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line + * + * \par + * \image html LinearInterp.gif "Linear interpolation" + * + * \par + * A Linear Interpolate function calculates an output value(y), for the input(x) + * using linear interpolation of the input values x0, x1( nearest input values) and the output values y0 and y1(nearest output values) + * + * \par Algorithm: + *
+   *       y = y0 + (x - x0) * ((y1 - y0)/(x1-x0))
+   *       where x0, x1 are nearest values of input x
+   *             y0, y1 are nearest values to output y
+   * 
+ * + * \par + * This set of functions implements Linear interpolation process + * for Q7, Q15, Q31, and floating-point data types. The functions operate on a single + * sample of data and each call to the function returns a single processed value. + * S points to an instance of the Linear Interpolate function data structure. + * x is the input sample value. The functions returns the output value. + * + * \par + * if x is outside of the table boundary, Linear interpolation returns first value of the table + * if x is below input range and returns last value of table if x is above range. + */ + + /** + * @addtogroup LinearInterpolate + * @{ + */ + + /** + * @brief Process function for the floating-point Linear Interpolation Function. + * @param[in,out] S is an instance of the floating-point Linear Interpolation structure + * @param[in] x input sample to process + * @return y processed output sample. + * + */ + static __INLINE float32_t arm_linear_interp_f32( + arm_linear_interp_instance_f32 * S, + float32_t x) + { + float32_t y; + float32_t x0, x1; /* Nearest input values */ + float32_t y0, y1; /* Nearest output values */ + float32_t xSpacing = S->xSpacing; /* spacing between input values */ + int32_t i; /* Index variable */ + float32_t *pYData = S->pYData; /* pointer to output table */ + + /* Calculation of index */ + i = (int32_t) ((x - S->x1) / xSpacing); + + if(i < 0) + { + /* Iniatilize output for below specified range as least output value of table */ + y = pYData[0]; + } + else if((uint32_t)i >= S->nValues) + { + /* Iniatilize output for above specified range as last output value of table */ + y = pYData[S->nValues - 1]; + } + else + { + /* Calculation of nearest input values */ + x0 = S->x1 + i * xSpacing; + x1 = S->x1 + (i + 1) * xSpacing; + + /* Read of nearest output values */ + y0 = pYData[i]; + y1 = pYData[i + 1]; + + /* Calculation of output */ + y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0)); + + } + + /* returns output value */ + return (y); + } + + + /** + * + * @brief Process function for the Q31 Linear Interpolation Function. + * @param[in] pYData pointer to Q31 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + static __INLINE q31_t arm_linear_interp_q31( + q31_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q31_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (q31_t)0xFFF00000) >> 20); + + if(index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if(index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* shift left by 11 to keep fract in 1.31 format */ + fract = (x & 0x000FFFFF) << 11; + + /* Read two nearest output values from the index in 1.31(q31) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 2.30 format */ + y = ((q31_t) ((q63_t) y0 * (0x7FFFFFFF - fract) >> 32)); + + /* Calculation of y0 * (1-fract) + y1 *fract and y is in 2.30 format */ + y += ((q31_t) (((q63_t) y1 * fract) >> 32)); + + /* Convert y to 1.31 format */ + return (y << 1u); + } + } + + + /** + * + * @brief Process function for the Q15 Linear Interpolation Function. + * @param[in] pYData pointer to Q15 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + static __INLINE q15_t arm_linear_interp_q15( + q15_t * pYData, + q31_t x, + uint32_t nValues) + { + q63_t y; /* output */ + q15_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (int32_t)0xFFF00000) >> 20); + + if(index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if(index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 13.35 format */ + y = ((q63_t) y0 * (0xFFFFF - fract)); + + /* Calculation of (y0 * (1-fract) + y1 * fract) and y is in 13.35 format */ + y += ((q63_t) y1 * (fract)); + + /* convert y to 1.15 format */ + return (q15_t) (y >> 20); + } + } + + + /** + * + * @brief Process function for the Q7 Linear Interpolation Function. + * @param[in] pYData pointer to Q7 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + */ + static __INLINE q7_t arm_linear_interp_q7( + q7_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q7_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + uint32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + if (x < 0) + { + return (pYData[0]); + } + index = (x >> 20) & 0xfff; + + if(index >= (nValues - 1)) + { + return (pYData[nValues - 1]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index and are in 1.7(q7) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract ) and y is in 13.27(q27) format */ + y = ((y0 * (0xFFFFF - fract))); + + /* Calculation of y1 * fract + y0 * (1-fract) and y is in 13.27(q27) format */ + y += (y1 * fract); + + /* convert y to 1.7(q7) format */ + return (q7_t) (y >> 20); + } + } + + /** + * @} end of LinearInterpolate group + */ + + /** + * @brief Fast approximation to the trigonometric sine function for floating-point data. + * @param[in] x input value in radians. + * @return sin(x). + */ + float32_t arm_sin_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q31_t arm_sin_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q15_t arm_sin_q15( + q15_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for floating-point data. + * @param[in] x input value in radians. + * @return cos(x). + */ + float32_t arm_cos_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q31_t arm_cos_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q15_t arm_cos_q15( + q15_t x); + + + /** + * @ingroup groupFastMath + */ + + + /** + * @defgroup SQRT Square Root + * + * Computes the square root of a number. + * There are separate functions for Q15, Q31, and floating-point data types. + * The square root function is computed using the Newton-Raphson algorithm. + * This is an iterative algorithm of the form: + *
+   *      x1 = x0 - f(x0)/f'(x0)
+   * 
+ * where x1 is the current estimate, + * x0 is the previous estimate, and + * f'(x0) is the derivative of f() evaluated at x0. + * For the square root function, the algorithm reduces to: + *
+   *     x0 = in/2                         [initial guess]
+   *     x1 = 1/2 * ( x0 + in / x0)        [each iteration]
+   * 
+ */ + + + /** + * @addtogroup SQRT + * @{ + */ + + /** + * @brief Floating-point square root function. + * @param[in] in input value. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + static __INLINE arm_status arm_sqrt_f32( + float32_t in, + float32_t * pOut) + { + if(in >= 0.0f) + { + +#if (__FPU_USED == 1) && defined ( __CC_ARM ) + *pOut = __sqrtf(in); +#elif (__FPU_USED == 1) && (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined(__GNUC__) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined ( __ICCARM__ ) && (__VER__ >= 6040000) + __ASM("VSQRT.F32 %0,%1" : "=t"(*pOut) : "t"(in)); +#else + *pOut = sqrtf(in); +#endif + + return (ARM_MATH_SUCCESS); + } + else + { + *pOut = 0.0f; + return (ARM_MATH_ARGUMENT_ERROR); + } + } + + + /** + * @brief Q31 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x00000000 to 0x7FFFFFFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q31( + q31_t in, + q31_t * pOut); + + + /** + * @brief Q15 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x0000 to 0x7FFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q15( + q15_t in, + q15_t * pOut); + + /** + * @} end of SQRT group + */ + + + /** + * @brief floating-point Circular write function. + */ + static __INLINE void arm_circularWrite_f32( + int32_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const int32_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + + /** + * @brief floating-point Circular Read function. + */ + static __INLINE void arm_circularRead_f32( + int32_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + int32_t * dst, + int32_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (int32_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q15 Circular write function. + */ + static __INLINE void arm_circularWrite_q15( + q15_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q15_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q15 Circular Read function. + */ + static __INLINE void arm_circularRead_q15( + q15_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q15_t * dst, + q15_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (q15_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update wOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q7 Circular write function. + */ + static __INLINE void arm_circularWrite_q7( + q7_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q7_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q7 Circular Read function. + */ + static __INLINE void arm_circularRead_q7( + q7_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q7_t * dst, + q7_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (q7_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Sum of the squares of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q31( + q31_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q15( + q15_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q7( + q7_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult); + + + /** + * @brief Mean value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Mean value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Variance of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Standard deviation of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Floating-point complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t numSamples, + q31_t * realResult, + q31_t * imagResult); + + + /** + * @brief Q31 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t numSamples, + q63_t * realResult, + q63_t * imagResult); + + + /** + * @brief Floating-point complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t numSamples, + float32_t * realResult, + float32_t * imagResult); + + + /** + * @brief Q15 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q15( + q15_t * pSrcCmplx, + q15_t * pSrcReal, + q15_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q31( + q31_t * pSrcCmplx, + q31_t * pSrcReal, + q31_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_f32( + float32_t * pSrcCmplx, + float32_t * pSrcReal, + float32_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Minimum value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] result is output pointer + * @param[in] index is the array index of the minimum value in the input buffer. + */ + void arm_min_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * result, + uint32_t * index); + + + /** + * @brief Minimum value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[in] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q7 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q15 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q31 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a floating-point vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Q15 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Converts the elements of the floating-point vector to Q31 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q31 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q31( + float32_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q15 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q15 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q15( + float32_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q7 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q7 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q7( + float32_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q15 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q15( + q31_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q7( + q31_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_float( + q15_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q31 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q31( + q15_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q7( + q15_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup BilinearInterpolate Bilinear Interpolation + * + * Bilinear interpolation is an extension of linear interpolation applied to a two dimensional grid. + * The underlying function f(x, y) is sampled on a regular grid and the interpolation process + * determines values between the grid points. + * Bilinear interpolation is equivalent to two step linear interpolation, first in the x-dimension and then in the y-dimension. + * Bilinear interpolation is often used in image processing to rescale images. + * The CMSIS DSP library provides bilinear interpolation functions for Q7, Q15, Q31, and floating-point data types. + * + * Algorithm + * \par + * The instance structure used by the bilinear interpolation functions describes a two dimensional data table. + * For floating-point, the instance structure is defined as: + *
+   *   typedef struct
+   *   {
+   *     uint16_t numRows;
+   *     uint16_t numCols;
+   *     float32_t *pData;
+   * } arm_bilinear_interp_instance_f32;
+   * 
+ * + * \par + * where numRows specifies the number of rows in the table; + * numCols specifies the number of columns in the table; + * and pData points to an array of size numRows*numCols values. + * The data table pTable is organized in row order and the supplied data values fall on integer indexes. + * That is, table element (x,y) is located at pTable[x + y*numCols] where x and y are integers. + * + * \par + * Let (x, y) specify the desired interpolation point. Then define: + *
+   *     XF = floor(x)
+   *     YF = floor(y)
+   * 
+ * \par + * The interpolated output point is computed as: + *
+   *  f(x, y) = f(XF, YF) * (1-(x-XF)) * (1-(y-YF))
+   *           + f(XF+1, YF) * (x-XF)*(1-(y-YF))
+   *           + f(XF, YF+1) * (1-(x-XF))*(y-YF)
+   *           + f(XF+1, YF+1) * (x-XF)*(y-YF)
+   * 
+ * Note that the coordinates (x, y) contain integer and fractional components. + * The integer components specify which portion of the table to use while the + * fractional components control the interpolation processor. + * + * \par + * if (x,y) are outside of the table boundary, Bilinear interpolation returns zero output. + */ + + /** + * @addtogroup BilinearInterpolate + * @{ + */ + + + /** + * + * @brief Floating-point bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate. + * @param[in] Y interpolation coordinate. + * @return out interpolated value. + */ + static __INLINE float32_t arm_bilinear_interp_f32( + const arm_bilinear_interp_instance_f32 * S, + float32_t X, + float32_t Y) + { + float32_t out; + float32_t f00, f01, f10, f11; + float32_t *pData = S->pData; + int32_t xIndex, yIndex, index; + float32_t xdiff, ydiff; + float32_t b1, b2, b3, b4; + + xIndex = (int32_t) X; + yIndex = (int32_t) Y; + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(xIndex < 0 || xIndex > (S->numRows - 1) || yIndex < 0 || yIndex > (S->numCols - 1)) + { + return (0); + } + + /* Calculation of index for two nearest points in X-direction */ + index = (xIndex - 1) + (yIndex - 1) * S->numCols; + + + /* Read two nearest points in X-direction */ + f00 = pData[index]; + f01 = pData[index + 1]; + + /* Calculation of index for two nearest points in Y-direction */ + index = (xIndex - 1) + (yIndex) * S->numCols; + + + /* Read two nearest points in Y-direction */ + f10 = pData[index]; + f11 = pData[index + 1]; + + /* Calculation of intermediate values */ + b1 = f00; + b2 = f01 - f00; + b3 = f10 - f00; + b4 = f00 - f01 - f10 + f11; + + /* Calculation of fractional part in X */ + xdiff = X - xIndex; + + /* Calculation of fractional part in Y */ + ydiff = Y - yIndex; + + /* Calculation of bi-linear interpolated output */ + out = b1 + b2 * xdiff + b3 * ydiff + b4 * xdiff * ydiff; + + /* return to application */ + return (out); + } + + + /** + * + * @brief Q31 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q31_t arm_bilinear_interp_q31( + arm_bilinear_interp_instance_q31 * S, + q31_t X, + q31_t Y) + { + q31_t out; /* Temporary output */ + q31_t acc = 0; /* output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q31_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q31_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* shift left xfract by 11 to keep 1.31 format */ + xfract = (X & 0x000FFFFF) << 11u; + + /* Read two nearest output values from the index */ + x1 = pYData[(rI) + (int32_t)nCols * (cI) ]; + x2 = pYData[(rI) + (int32_t)nCols * (cI) + 1]; + + /* 20 bits for the fractional part */ + /* shift left yfract by 11 to keep 1.31 format */ + yfract = (Y & 0x000FFFFF) << 11u; + + /* Read two nearest output values from the index */ + y1 = pYData[(rI) + (int32_t)nCols * (cI + 1) ]; + y2 = pYData[(rI) + (int32_t)nCols * (cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 3.29(q29) format */ + out = ((q31_t) (((q63_t) x1 * (0x7FFFFFFF - xfract)) >> 32)); + acc = ((q31_t) (((q63_t) out * (0x7FFFFFFF - yfract)) >> 32)); + + /* x2 * (xfract) * (1-yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) x2 * (0x7FFFFFFF - yfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (xfract) >> 32)); + + /* y1 * (1 - xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y1 * (0x7FFFFFFF - xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* y2 * (xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y2 * (xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* Convert acc to 1.31(q31) format */ + return ((q31_t)(acc << 2)); + } + + + /** + * @brief Q15 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q15_t arm_bilinear_interp_q15( + arm_bilinear_interp_instance_q15 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q15_t x1, x2, y1, y2; /* Nearest output values */ + q31_t xfract, yfract; /* X, Y fractional parts */ + int32_t rI, cI; /* Row and column indices */ + q15_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & 0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 13.51 format */ + + /* x1 is in 1.15(q15), xfract in 12.20 format and out is in 13.35 format */ + /* convert 13.35 to 13.31 by right shifting and out is in 1.31 */ + out = (q31_t) (((q63_t) x1 * (0xFFFFF - xfract)) >> 4u); + acc = ((q63_t) out * (0xFFFFF - yfract)); + + /* x2 * (xfract) * (1-yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) x2 * (0xFFFFF - yfract)) >> 4u); + acc += ((q63_t) out * (xfract)); + + /* y1 * (1 - xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y1 * (0xFFFFF - xfract)) >> 4u); + acc += ((q63_t) out * (yfract)); + + /* y2 * (xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y2 * (xfract)) >> 4u); + acc += ((q63_t) out * (yfract)); + + /* acc is in 13.51 format and down shift acc by 36 times */ + /* Convert out to 1.15 format */ + return ((q15_t)(acc >> 36)); + } + + + /** + * @brief Q7 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q7_t arm_bilinear_interp_q7( + arm_bilinear_interp_instance_q7 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q7_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q7_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 16.47 format */ + out = ((x1 * (0xFFFFF - xfract))); + acc = (((q63_t) out * (0xFFFFF - yfract))); + + /* x2 * (xfract) * (1-yfract) in 2.22 and adding to acc */ + out = ((x2 * (0xFFFFF - yfract))); + acc += (((q63_t) out * (xfract))); + + /* y1 * (1 - xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y1 * (0xFFFFF - xfract))); + acc += (((q63_t) out * (yfract))); + + /* y2 * (xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y2 * (yfract))); + acc += (((q63_t) out * (xfract))); + + /* acc in 16.47 format and down shift by 40 to convert to 1.7 format */ + return ((q7_t)(acc >> 40)); + } + + /** + * @} end of BilinearInterpolate group + */ + + +/* SMMLAR */ +#define multAcc_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) + ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMLSR */ +#define multSub_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) - ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMULR */ +#define mult_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((q63_t) x * y + 0x80000000LL ) >> 32) + +/* SMMLA */ +#define multAcc_32x32_keep32(a, x, y) \ + a += (q31_t) (((q63_t) x * y) >> 32) + +/* SMMLS */ +#define multSub_32x32_keep32(a, x, y) \ + a -= (q31_t) (((q63_t) x * y) >> 32) + +/* SMMUL */ +#define mult_32x32_keep32(a, x, y) \ + a = (q31_t) (((q63_t) x * y ) >> 32) + + +#if defined ( __CC_ARM ) + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("push") \ + _Pragma ("O1") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_EXIT \ + _Pragma ("pop") + #else + #define LOW_OPTIMIZATION_EXIT + #endif + + /* Enter low optimization region - place directly above function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__GNUC__) + #define LOW_OPTIMIZATION_ENTER __attribute__(( optimize("-O1") )) + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__ICCARM__) + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define LOW_OPTIMIZATION_EXIT + + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__CSMC__) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__TASKING__) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#endif + + +#ifdef __cplusplus +} +#endif + + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +#endif /* _ARM_MATH_H */ + +/** + * + * End of file. + */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_armcc.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_armcc.h new file mode 100644 index 0000000000..74c49c67de --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_armcc.h @@ -0,0 +1,734 @@ +/**************************************************************************//** + * @file cmsis_armcc.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CMSIS_ARMCC_H +#define __CMSIS_ARMCC_H + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + + +#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() do {\ + __schedule_barrier();\ + __isb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() do {\ + __schedule_barrier();\ + __dsb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() do {\ + __schedule_barrier();\ + __dmb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + #define __RBIT __rbit +#else +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ + return(result); +} +#endif + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) +#else + #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) +#else + #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) +#else + #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXB(value, ptr) __strex(value, ptr) +#else + #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ + +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32U) ) >> 32U)) + +#endif /* (__CORTEX_M >= 0x04) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_H */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_armcc_V6.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_armcc_V6.h new file mode 100644 index 0000000000..6d8f998d84 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_armcc_V6.h @@ -0,0 +1,1804 @@ +/**************************************************************************//** + * @file cmsis_armcc_V6.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CMSIS_ARMCC_V6_H +#define __CMSIS_ARMCC_V6_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, control" : "=r"(result)); + return (result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, control_ns" : "=r"(result)); + return (result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile("MSR control, %0" : : "r"(control) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile("MSR control_ns, %0" : : "r"(control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, ipsr" : "=r"(result)); + return (result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get IPSR Register (non-secure) + \details Returns the content of the non-secure IPSR Register when in secure state. + \return IPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_IPSR_NS(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, ipsr_ns" : "=r"(result)); + return (result); +} +#endif + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, apsr" : "=r"(result)); + return (result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get APSR Register (non-secure) + \details Returns the content of the non-secure APSR Register when in secure state. + \return APSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_APSR_NS(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, apsr_ns" : "=r"(result)); + return (result); +} +#endif + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, xpsr" : "=r"(result)); + return (result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get xPSR Register (non-secure) + \details Returns the content of the non-secure xPSR Register when in secure state. + \return xPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_xPSR_NS(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, xpsr_ns" : "=r"(result)); + return (result); +} +#endif + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile("MRS %0, psp" : "=r"(result)); + return (result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSP_NS(void) +{ + register uint32_t result; + + __ASM volatile("MRS %0, psp_ns" : "=r"(result)); + return (result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile("MSR psp, %0" : : "r"(topOfProcStack) : "sp"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile("MSR psp_ns, %0" : : "r"(topOfProcStack) : "sp"); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile("MRS %0, msp" : "=r"(result)); + return (result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSP_NS(void) +{ + register uint32_t result; + + __ASM volatile("MRS %0, msp_ns" : "=r"(result)); + return (result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile("MSR msp, %0" : : "r"(topOfMainStack) : "sp"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile("MSR msp_ns, %0" : : "r"(topOfMainStack) : "sp"); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, primask" : "=r"(result)); + return (result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, primask_ns" : "=r"(result)); + return (result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile("MSR primask, %0" : : "r"(priMask) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile("MSR primask_ns, %0" : : "r"(priMask) : "memory"); +} +#endif + + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, basepri" : "=r"(result)); + return (result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, basepri_ns" : "=r"(result)); + return (result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile("MSR basepri, %0" : : "r"(value) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_NS(uint32_t value) +{ + __ASM volatile("MSR basepri_ns, %0" : : "r"(value) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +{ + __ASM volatile("MSR basepri_max, %0" : : "r"(value) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Base Priority with condition (non_secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_MAX_NS(uint32_t value) +{ + __ASM volatile("MSR basepri_max_ns, %0" : : "r"(value) : "memory"); +} +#endif + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, faultmask" : "=r"(result)); + return (result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile("MRS %0, faultmask_ns" : "=r"(result)); + return (result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile("MSR faultmask, %0" : : "r"(faultMask) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile("MSR faultmask_ns, %0" : : "r"(faultMask) : "memory"); +} +#endif + + +#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + +#if (__ARM_ARCH_8M__ == 1U) + +/** + \brief Get Process Stack Pointer Limit + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSPLIM(void) +{ + register uint32_t result; + + __ASM volatile("MRS %0, psplim" : "=r"(result)); + return (result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Get Process Stack Pointer Limit (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ + register uint32_t result; + + __ASM volatile("MRS %0, psplim_ns" : "=r"(result)); + return (result); +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ + __ASM volatile("MSR psplim, %0" : : "r"(ProcStackPtrLimit)); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ + __ASM volatile("MSR psplim_ns, %0\n" : : "r"(ProcStackPtrLimit)); +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSPLIM(void) +{ + register uint32_t result; + + __ASM volatile("MRS %0, msplim" : "=r"(result)); + + return (result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Get Main Stack Pointer Limit (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ + register uint32_t result; + + __ASM volatile("MRS %0, msplim_ns" : "=r"(result)); + return (result); +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ + __ASM volatile("MSR msplim, %0" : : "r"(MainStackPtrLimit)); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Set Main Stack Pointer Limit (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ + __ASM volatile("MSR msplim_ns, %0" : : "r"(MainStackPtrLimit)); +} +#endif + +#endif /* (__ARM_ARCH_8M__ == 1U) */ + + +#if ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=4 */ + +/** + \brief Get FPSCR + \details eturns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#define __get_FPSCR __builtin_arm_get_fpscr +#if 0 +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + __ASM volatile(""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile("VMRS %0, fpscr" : "=r"(result)); + __ASM volatile(""); + return (result); +#else + return (0); +#endif +} +#endif + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get FPSCR (non-secure) + \details Returns the current value of the non-secure Floating Point Status/Control register when in secure state. + \return Floating Point Status/Control register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FPSCR_NS(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + __ASM volatile(""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile("VMRS %0, fpscr_ns" : "=r"(result)); + __ASM volatile(""); + return (result); +#else + return (0); +#endif +} +#endif + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#define __set_FPSCR __builtin_arm_set_fpscr +#if 0 +__attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + __ASM volatile(""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile("VMSR fpscr, %0" : : "r"(fpscr) : "vfpcc"); + __ASM volatile(""); +#endif +} +#endif + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set FPSCR (non-secure) + \details Assigns the given value to the non-secure Floating Point Status/Control register when in secure state. + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + __ASM volatile(""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile("VMSR fpscr_ns, %0" : : "r"(fpscr) : "vfpcc"); + __ASM volatile(""); +#endif +} +#endif + +#endif /* ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) + #define __CMSIS_GCC_OUT_REG(r) "=l" (r) + #define __CMSIS_GCC_USE_REG(r) "l" (r) +#else + #define __CMSIS_GCC_OUT_REG(r) "=r" (r) + #define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF); + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF); + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF); + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __builtin_bswap32 + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16 __builtin_bswap16 /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ +#if 0 +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile("rev16 %0, %1" : __CMSIS_GCC_OUT_REG(result) : __CMSIS_GCC_USE_REG(value)); + return (result); +} +#endif + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +/* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + int32_t result; + + __ASM volatile("revsh %0, %1" : __CMSIS_GCC_OUT_REG(result) : __CMSIS_GCC_USE_REG(value)); + return (result); +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +/* ToDo: ARMCC_V6: check if __builtin_arm_rbit is supported */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + __ASM volatile("rbit %0, %1" : "=r"(result) : "r"(value)); +#else + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return (result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz + + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +/*#define __SSAT __builtin_arm_ssat*/ +#define __SSAT(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat +#if 0 +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) +#endif + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile("rrx %0, %1" : __CMSIS_GCC_OUT_REG(result) : __CMSIS_GCC_USE_REG(value)); + return (result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile("ldrbt %0, %1" : "=r"(result) : "Q"(*ptr)); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile("ldrht %0, %1" : "=r"(result) : "Q"(*ptr)); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile("ldrt %0, %1" : "=r"(result) : "Q"(*ptr)); + return (result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile("strbt %1, %0" : "=Q"(*ptr) : "r"((uint32_t)value)); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile("strht %1, %0" : "=Q"(*ptr) : "r"((uint32_t)value)); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile("strt %1, %0" : "=Q"(*ptr) : "r"(value)); +} + +#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + +#if (__ARM_ARCH_8M__ == 1U) + +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile("ldab %0, %1" : "=r"(result) : "Q"(*ptr)); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile("ldah %0, %1" : "=r"(result) : "Q"(*ptr)); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile("lda %0, %1" : "=r"(result) : "Q"(*ptr)); + return (result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile("stlb %1, %0" : "=Q"(*ptr) : "r"((uint32_t)value)); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile("stlh %1, %0" : "=Q"(*ptr) : "r"((uint32_t)value)); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile("stl %1, %0" : "=Q"(*ptr) : "r"((uint32_t)value)); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* (__ARM_ARCH_8M__ == 1U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__ARM_FEATURE_DSP == 1U) /* ToDo: ARMCC_V6: This should be ARCH >= ARMv7-M + SIMD */ + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("sadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("qadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("shadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uqadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uhadd8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("ssub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("qsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("shsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("usub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uqsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uhsub8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("sadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("qadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("shadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uqadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uhadd16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("ssub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("qsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("shsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("usub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uqsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uhsub16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("sasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("qasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("shasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uqasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uhasx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("ssax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("qsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("shsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("usax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uqsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uhsax %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("usad8 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile("usada8 %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); + return (result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile("uxtb16 %0, %1" : "=r"(result) : "r"(op1)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("uxtab16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile("sxtb16 %0, %1" : "=r"(result) : "r"(op1)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("sxtab16 %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("smuad %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("smuadx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile("smlad %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile("smladx %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALD(uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u + { + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile("smlald %0, %1, %2, %3" : "=r"(llr.w32[0]), "=r"(llr.w32[1]): "r"(op1), "r"(op2), "0"(llr.w32[0]), "1"(llr.w32[1])); +#else /* Big endian */ + __ASM volatile("smlald %0, %1, %2, %3" : "=r"(llr.w32[1]), "=r"(llr.w32[0]): "r"(op1), "r"(op2), "0"(llr.w32[1]), "1"(llr.w32[0])); +#endif + + return (llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALDX(uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u + { + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile("smlaldx %0, %1, %2, %3" : "=r"(llr.w32[0]), "=r"(llr.w32[1]): "r"(op1), "r"(op2), "0"(llr.w32[0]), "1"(llr.w32[1])); +#else /* Big endian */ + __ASM volatile("smlaldx %0, %1, %2, %3" : "=r"(llr.w32[1]), "=r"(llr.w32[0]): "r"(op1), "r"(op2), "0"(llr.w32[1]), "1"(llr.w32[0])); +#endif + + return (llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("smusd %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("smusdx %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile("smlsd %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile("smlsdx %0, %1, %2, %3" : "=r"(result) : "r"(op1), "r"(op2), "r"(op3)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLD(uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u + { + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile("smlsld %0, %1, %2, %3" : "=r"(llr.w32[0]), "=r"(llr.w32[1]): "r"(op1), "r"(op2), "0"(llr.w32[0]), "1"(llr.w32[1])); +#else /* Big endian */ + __ASM volatile("smlsld %0, %1, %2, %3" : "=r"(llr.w32[1]), "=r"(llr.w32[0]): "r"(op1), "r"(op2), "0"(llr.w32[1]), "1"(llr.w32[0])); +#endif + + return (llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLDX(uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u + { + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile("smlsldx %0, %1, %2, %3" : "=r"(llr.w32[0]), "=r"(llr.w32[1]): "r"(op1), "r"(op2), "0"(llr.w32[0]), "1"(llr.w32[1])); +#else /* Big endian */ + __ASM volatile("smlsldx %0, %1, %2, %3" : "=r"(llr.w32[1]), "=r"(llr.w32[0]): "r"(op1), "r"(op2), "0"(llr.w32[1]), "1"(llr.w32[0])); +#endif + + return (llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile("sel %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE int32_t __QADD(int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile("qadd %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +__attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB(int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile("qsub %0, %1, %2" : "=r"(result) : "r"(op1), "r"(op2)); + return (result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMMLA(int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile("smmla %0, %1, %2, %3" : "=r"(result): "r"(op1), "r"(op2), "r"(op3)); + return (result); +} + +#endif /* (__ARM_FEATURE_DSP == 1U) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_V6_H */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_gcc.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_gcc.h new file mode 100644 index 0000000000..bb89fbba9e --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/cmsis_gcc.h @@ -0,0 +1,1373 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03U) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03U) */ + + +#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__((always_inline)) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__attribute__((always_inline)) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__((always_inline)) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__((always_inline)) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + int32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return(result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*addr) : "r" (value) ); +} + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x04) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +#endif /* __CMSIS_GCC_H */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm0.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm0.h new file mode 100644 index 0000000000..711dad5517 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm0.h @@ -0,0 +1,798 @@ +/**************************************************************************//** + * @file core_cm0.h + * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM0_H_GENERIC +#define __CORE_CM0_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M0 + @{ + */ + +/* CMSIS CM0 definitions */ +#define __CM0_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM0_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \ + __CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0_H_DEPENDANT +#define __CORE_CM0_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0_REV + #define __CM0_REV 0x0000U + #warning "__CM0_REV not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M0 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + uint32_t RESERVED0; + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the Cortex-M0 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M0 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm0plus.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm0plus.h new file mode 100644 index 0000000000..b04aa39053 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm0plus.h @@ -0,0 +1,914 @@ +/**************************************************************************//** + * @file core_cm0plus.h + * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM0PLUS_H_GENERIC +#define __CORE_CM0PLUS_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex-M0+ + @{ + */ + +/* CMSIS CM0+ definitions */ +#define __CM0PLUS_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM0PLUS_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16U) | \ + __CM0PLUS_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0PLUS_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0PLUS_H_DEPENDANT +#define __CORE_CM0PLUS_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0PLUS_REV + #define __CM0PLUS_REV 0x0000U + #warning "__CM0PLUS_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 0U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex-M0+ */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ +#if (__VTOR_PRESENT == 1U) + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ +#else + uint32_t RESERVED0; +#endif + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if (__VTOR_PRESENT == 1U) +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 8U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the Cortex-M0+ header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M0+ Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0PLUS_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm3.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm3.h new file mode 100644 index 0000000000..b4ac4c7b05 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm3.h @@ -0,0 +1,1763 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M3 + @{ + */ + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x03U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200U + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if (__CM3_REV < 0x0201U) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if ((defined __CM3_REV) && (__CM3_REV >= 0x200U)) + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1U]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm4.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm4.h new file mode 100644 index 0000000000..dc840ebf22 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm4.h @@ -0,0 +1,1937 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M4 + @{ + */ + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x04U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ +#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000U + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if (__FPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M4 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#if (__FPU_PRESENT == 1U) + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm7.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm7.h new file mode 100644 index 0000000000..3b7530ad50 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cm7.h @@ -0,0 +1,2512 @@ +/**************************************************************************//** + * @file core_cm7.h + * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM7_H_GENERIC +#define __CORE_CM7_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M7 + @{ + */ + +/* CMSIS CM7 definitions */ +#define __CM7_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM7_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ + __CM7_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x07U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ +#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM7_H_DEPENDANT +#define __CORE_CM7_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM7_REV + #define __CM7_REV 0x0000U + #warning "__CM7_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __ICACHE_PRESENT + #define __ICACHE_PRESENT 0U + #warning "__ICACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DCACHE_PRESENT + #define __DCACHE_PRESENT 0U + #warning "__DCACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DTCM_PRESENT + #define __DTCM_PRESENT 0U + #warning "__DTCM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M7 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_AFR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED3[93U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 1 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: Branch prediction enable bit Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: Branch prediction enable bit Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: Instruction cache enable bit Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: Instruction cache enable bit Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: Cache enable bit Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: Cache enable bit Mask */ + +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/* Instruction Tightly-Coupled Memory Control Register Definitions */ +#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ +#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ + +#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ +#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ + +#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ +#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ + +#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ +#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ + +/* Data Tightly-Coupled Memory Control Register Definitions */ +#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ +#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ + +#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ +#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ + +#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ +#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ + +#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ +#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ + +/* AHBP Control Register Definitions */ +#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ +#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ + +#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ +#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ + +/* L1 Cache Control Register Definitions */ +#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ +#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ + +#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ + +#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ +#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ + +/* AHBS Control Register Definitions */ +#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ + +#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ + +#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ + +/* Auxiliary Bus Fault Status Register Definitions */ +#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ +#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ + +#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ +#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ + +#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ +#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ + +#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ +#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ + +#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ +#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ + +#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ +#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */ + +#define SCnSCB_ACTLR_DISRAMODE_Pos 11U /*!< ACTLR: DISRAMODE Position */ +#define SCnSCB_ACTLR_DISRAMODE_Msk (1UL << SCnSCB_ACTLR_DISRAMODE_Pos) /*!< ACTLR: DISRAMODE Mask */ + +#define SCnSCB_ACTLR_FPEXCODIS_Pos 10U /*!< ACTLR: FPEXCODIS Position */ +#define SCnSCB_ACTLR_FPEXCODIS_Msk (1UL << SCnSCB_ACTLR_FPEXCODIS_Pos) /*!< ACTLR: FPEXCODIS Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED3[981U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( W) Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if (__FPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +/*@} end of group CMSIS_FPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M4 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#if (__FPU_PRESENT == 1U) + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = SCB->MVFR0; + if ((mvfr0 & 0x00000FF0UL) == 0x220UL) + { + return 2UL; /* Double + Single precision FPU */ + } + else if ((mvfr0 & 0x00000FF0UL) == 0x020UL) + { + return 1UL; /* Single precision FPU */ + } + else + { + return 0UL; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## Cache functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_CacheFunctions Cache Functions + \brief Functions that configure Instruction and Data cache. + @{ + */ + +/* Cache Size ID Register Macros */ +#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) +#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos ) + + +/** + \brief Enable I-Cache + \details Turns on I-Cache + */ +__STATIC_INLINE void SCB_EnableICache (void) +{ + #if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable I-Cache + \details Turns off I-Cache + */ +__STATIC_INLINE void SCB_DisableICache (void) +{ + #if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */ + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_INLINE void SCB_InvalidateICache (void) +{ + #if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Enable D-Cache + \details Turns on D-Cache + */ +__STATIC_INLINE void SCB_EnableDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + __DSB(); + + SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable D-Cache + \details Turns off D-Cache + */ +__STATIC_INLINE void SCB_DisableDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */ + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_INLINE void SCB_InvalidateDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_INLINE void SCB_CleanDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) | + ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean & Invalidate D-Cache + \details Cleans and Invalidates D-Cache + */ +__STATIC_INLINE void SCB_CleanInvalidateDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Invalidate by address + \details Invalidates D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if (__DCACHE_PRESENT == 1U) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t)addr; + int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCIMVAC = op_addr; + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Clean by address + \details Cleans D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if (__DCACHE_PRESENT == 1) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t) addr; + int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCCMVAC = op_addr; + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Clean and Invalidate by address + \details Cleans and invalidates D_Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if (__DCACHE_PRESENT == 1U) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t) addr; + int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCCIMVAC = op_addr; + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/*@} end of CMSIS_Core_CacheFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmFunc.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmFunc.h new file mode 100644 index 0000000000..652a48af07 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmFunc.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + +#endif /* __CORE_CMFUNC_H */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmInstr.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmInstr.h new file mode 100644 index 0000000000..f474b0e6f3 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmInstr.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmSimd.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmSimd.h new file mode 100644 index 0000000000..66bf5c2a72 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_cmSimd.h @@ -0,0 +1,96 @@ +/**************************************************************************//** + * @file core_cmSimd.h + * @brief CMSIS Cortex-M SIMD Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMSIMD_H +#define __CORE_CMSIMD_H + +#ifdef __cplusplus + extern "C" { +#endif + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CMSIMD_H */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/core_sc000.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_sc000.h new file mode 100644 index 0000000000..514dbd81b9 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_sc000.h @@ -0,0 +1,926 @@ +/**************************************************************************//** + * @file core_sc000.h + * @brief CMSIS SC000 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_SC000_H_GENERIC +#define __CORE_SC000_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup SC000 + @{ + */ + +/* CMSIS SC000 definitions */ +#define __SC000_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __SC000_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __SC000_CMSIS_VERSION ((__SC000_CMSIS_VERSION_MAIN << 16U) | \ + __SC000_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_SC (000U) /*!< Cortex secure core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC000_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_SC000_H_DEPENDANT +#define __CORE_SC000_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __SC000_REV + #define __SC000_REV 0x0000U + #warning "__SC000_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group SC000 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED0[1U]; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + uint32_t RESERVED1[154U]; + __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief SC000 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the SC000 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of SC000 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC000_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/Include/core_sc300.h b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_sc300.h new file mode 100644 index 0000000000..8bd18aa318 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/Include/core_sc300.h @@ -0,0 +1,1745 @@ +/**************************************************************************//** + * @file core_sc300.h + * @brief CMSIS SC300 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_SC300_H_GENERIC +#define __CORE_SC300_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup SC3000 + @{ + */ + +/* CMSIS SC300 definitions */ +#define __SC300_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __SC300_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __SC300_CMSIS_VERSION ((__SC300_CMSIS_VERSION_MAIN << 16U) | \ + __SC300_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_SC (300U) /*!< Cortex secure core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC300_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_SC300_H_DEPENDANT +#define __CORE_SC300_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __SC300_REV + #define __SC300_REV 0x0000U + #warning "__SC300_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group SC300 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED1[129U]; + __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + uint32_t RESERVED1[1U]; +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC300_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/bsp/nuvoton/libraries/m031/CMSIS/SConscript b/bsp/nuvoton/libraries/m031/CMSIS/SConscript new file mode 100644 index 0000000000..904fca4146 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/CMSIS/SConscript @@ -0,0 +1,16 @@ +import rtconfig +Import('RTT_ROOT') +from building import * + +# get current directory +cwd = GetCurrentDir() + +# The set of source files associated with this SConscript file. +src = Split(""" +""") + +path = [cwd + '/Include',] + +group = DefineGroup('CMSIS', src, depend = [''], CPPPATH = path) + +Return('group') diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/M031Series.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/M031Series.h new file mode 100644 index 0000000000..c8d840c71e --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/M031Series.h @@ -0,0 +1,590 @@ +/**************************************************************************//** + * @file m031series.h + * @version V3.0 + * $Revision: 12 $ + * $Date: 18/08/16 4:06p $ + * @brief M031 Series Peripheral Access Layer Header File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ + +/** + \mainpage NuMicro M031 Driver Reference Guide + * + * Introduction + * + * This user manual describes the usage of M031 Series MCU device driver + * + * Disclaimer + * + * The Software is furnished "AS IS", without warranty as to performance or results, and + * the entire risk as to performance or results is assumed by YOU. Nuvoton disclaims all + * warranties, express, implied or otherwise, with regard to the Software, its use, or + * operation, including without limitation any and all warranties of merchantability, fitness + * for a particular purpose, and non-infringement of intellectual property rights. + * + * Important Notice + * + * Nuvoton Products are neither intended nor warranted for usage in systems or equipment, + * any malfunction or failure of which may cause loss of human life, bodily injury or severe + * property damage. Such applications are deemed, "Insecure Usage". + * + * Insecure usage includes, but is not limited to: equipment for surgical implementation, + * atomic energy control instruments, airplane or spaceship instruments, the control or + * operation of dynamic, brake or safety systems designed for vehicular use, traffic signal + * instruments, all types of safety devices, and other applications intended to support or + * sustain life. + * + * All Insecure Usage shall be made at customer's risk, and in the event that third parties + * lay claims to Nuvoton as a result of customer's Insecure Usage, customer shall indemnify + * the damages and liabilities thus incurred by Nuvoton. + * + * Please note that all data and specifications are subject to change without notice. All the + * trademarks of products and companies mentioned in this datasheet belong to their respective + * owners. + * + * Copyright Notice + * + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + */ + +#ifndef __M031SERIES_H__ +#define __M031SERIES_H__ + +/******************************************************************************/ +/* Processor and Core Peripherals */ +/******************************************************************************/ +/** @addtogroup CMSIS_Device CMSIS Definitions + Configuration of the Cortex-M0 Processor and Core Peripherals + @{ +*/ + + +/* + * ========================================================================== + * ---------- Interrupt Number Definition ----------------------------------- + * ========================================================================== + */ + +/** + * @details Interrupt Number Definition. The maximum of 32 Specific Interrupts are possible. + */ +typedef enum IRQn +{ + /****** Cortex-M0 Processor Exceptions Numbers ***************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M0 Hard Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M0 SV Call Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M0 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M0 System Tick Interrupt */ + + /****** ARMIKMCU Swift specific Interrupt Numbers ************************************************/ + BOD_IRQn = 0, /*!< Brown-Out Low Voltage Detected Interrupt */ + WDT_IRQn = 1, /*!< Watch Dog Timer Interrupt */ + EINT024_IRQn = 2, /*!< EINT0, EINT2 and EINT4 Interrupt */ + EINT135_IRQn = 3, /*!< EINT1, EINT3 and EINT5 Interrupt */ + GPIO_PAPB_IRQn = 4, /*!< GPIO_PAPBPGPH Interrupt */ + GPIO_PAPBPGPH_IRQn = 4, /*!< GPIO_PAPBPGPH Interrupt */ + GPIO_PCPDPEPF_IRQn = 5, /*!< GPIO_PCPDPEPF Interrupt */ + PWM0_IRQn = 6, /*!< PWM0 Interrupt */ + PWM1_IRQn = 7, /*!< PWM1 Interrupt */ + TMR0_IRQn = 8, /*!< TIMER0 Interrupt */ + TMR1_IRQn = 9, /*!< TIMER1 Interrupt */ + TMR2_IRQn = 10, /*!< TIMER2 Interrupt */ + TMR3_IRQn = 11, /*!< TIMER3 Interrupt */ + UART02_IRQn = 12, /*!< UART0 and UART2 Interrupt */ + UART1_IRQn = 13, /*!< UART1 and UART3 Interrupt */ + UART13_IRQn = 13, /*!< UART1 and UART3 Interrupt */ + SPI0_IRQn = 14, /*!< SPI0 Interrupt */ + QSPI0_IRQn = 15, /*!< QSPI0 Interrupt */ + ISP_IRQn = 16, /*!< ISP Interrupt */ + UART57_IRQn = 17, /*!< UART5 and UART7 Interrupt */ + I2C0_IRQn = 18, /*!< I2C0 Interrupt */ + I2C1_IRQn = 19, /*!< I2C1 Interrupt */ + BPWM0_IRQn = 20, /*!< BPWM0 Interrupt */ + BPWM1_IRQn = 21, /*!< BPWM1 Interrupt */ + USCI_IRQn = 22, /*!< USCI0 and USCI1 interrupt */ + USCI01_IRQn = 22, /*!< USCI0 and USCI1 interrupt */ + USBD_IRQn = 23, /*!< USB Device Interrupt */ + ACMP01_IRQn = 25, /*!< ACMP0/1 Interrupt */ + PDMA_IRQn = 26, /*!< PDMA Interrupt */ + UART46_IRQn = 27, /*!< UART4 and UART6 Interrupt */ + PWRWU_IRQn = 28, /*!< Power Down Wake Up Interrupt */ + ADC_IRQn = 29, /*!< ADC Interrupt */ + CKFAIL_IRQn = 30, /*!< Clock fail detect Interrupt */ + RTC_IRQn = 31, /*!< RTC Interrupt */ +} IRQn_Type; + + +/* + * ========================================================================== + * ----------- Processor and Core Peripheral Section ------------------------ + * ========================================================================== + */ + +/* Configuration of the Cortex-M0 Processor and Core Peripherals */ +#define __MPU_PRESENT 0 /*!< armikcmu does not provide a MPU present or not */ +#define __NVIC_PRIO_BITS 2 /*!< armikcmu Supports 2 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + +/*@}*/ /* end of group CMSIS_Device */ + +#include "core_cm0.h" /*!< Cortex-M0 processor and core peripherals */ +#include "system_M031Series.h" /*!< M031 System */ + + +#if defined ( __CC_ARM ) + #pragma anon_unions +#endif + + +/** + * Initialize the system clock + * + * @param None + * @return None + * + * @brief Setup the microcontroller system + * Initialize the PLL and update the SystemFrequency variable + */ +extern void SystemInit(void); + + + +/******************************************************************************/ +/* Device Specific Peripheral registers structures */ +/******************************************************************************/ + +#include "acmp_reg.h" +#include "adc_reg.h" +#include "clk_reg.h" +#include "crc_reg.h" +#include "ebi_reg.h" +#include "fmc_reg.h" +#include "gpio_reg.h" +#include "hdiv_reg.h" +#include "i2c_reg.h" +#include "pdma_reg.h" +#include "pwm_reg.h" +#include "bpwm_reg.h" +#include "qspi_reg.h" +#include "spi_reg.h" +#include "sys_reg.h" +#include "rtc_reg.h" +#include "timer_reg.h" +#include "uart_reg.h" +#include "ui2c_reg.h" +#include "usbd_reg.h" +#include "uspi_reg.h" +#include "uuart_reg.h" +#include "wdt_reg.h" +#include "wwdt_reg.h" + + +/******************************************************************************/ +/* Peripheral memory map */ +/******************************************************************************/ +/** @addtogroup PERIPHERAL_BASE Peripheral Memory Base + Memory Mapped Structure for Series Peripheral + @{ + */ +/* Peripheral and SRAM base address */ +#define FLASH_BASE (( uint32_t)0x00000000) +#define SRAM_BASE (( uint32_t)0x20000000) +#define AHB_BASE (( uint32_t)0x40000000) +#define APB1_BASE (( uint32_t)0x40000000) +#define APB2_BASE (( uint32_t)0x40000000) + +/* Peripheral memory map */ + +#define SYS_BASE (AHB_BASE + 0x00000) /*!< System Global Controller Base Address */ +#define CLK_BASE (AHB_BASE + 0x00200) /*!< System Clock Controller Base Address */ +#define INT_BASE (AHB_BASE + 0x00300) /*!< Interrupt Source Controller Base Address */ +#define NMI_BASE (AHB_BASE + 0x00300) /*!< Interrupt Source Controller Base Address */ + +#define GPIO_BASE (AHB_BASE + 0x4000) /*!< GPIO Base Address */ +#define PA_BASE (GPIO_BASE ) /*!< GPIO PA Base Address */ +#define PB_BASE (GPIO_BASE + 0x0040) /*!< GPIO PB Base Address */ +#define PC_BASE (GPIO_BASE + 0x0080) /*!< GPIO PC Base Address */ +#define PD_BASE (GPIO_BASE + 0x00C0) /*!< GPIO PD Base Address */ +#define PE_BASE (GPIO_BASE + 0x0100) /*!< GPIO PE Base Address */ +#define PF_BASE (GPIO_BASE + 0x0140) /*!< GPIO PF Base Address */ +#define PG_BASE (GPIO_BASE + 0x0180) /*!< GPIO PG Base Address */ +#define PH_BASE (GPIO_BASE + 0x01C0) /*!< GPIO PH Base Address */ +#define GPIO_DBCTL_BASE (GPIO_BASE + 0x0440) /*!< GPIO De-bounce Cycle Control Base Address */ +#define GPIO_PIN_DATA_BASE (GPIO_BASE + 0x0800) /*!< GPIO Pin Data Input/Output Control Base Address */ + +#define PDMA_BASE (AHB_BASE + 0x08000) /*!< PDMA Base Address */ +#define FMC_BASE (AHB_BASE + 0x0C000) /*!< Flash Memory Controller Base Address */ +#define EBI_BASE (AHB_BASE + 0x10000) /*!< EBI Base Address */ +#define HDIV_BASE (AHB_BASE + 0x14000) /*!< HDIV Base Address */ +#define CRC_BASE (AHB_BASE + 0x31000) /*!< CRC Base Address */ + +#define WDT_BASE (APB1_BASE + 0x40000) /*!< Watch Dog Timer Base Address */ +#define WWDT_BASE (APB1_BASE + 0x40100) /*!< Window Watch Dog Timer Base Address */ +#define RTC_BASE (APB1_BASE + 0x41000) /*!< RTC Base Address */ +#define ADC_BASE (APB1_BASE + 0x43000) /*!< ADC Base Address */ +#define ACMP01_BASE (APB1_BASE + 0x45000) /*!< ACMP01 Base Address */ + +#define TIMER0_BASE (APB1_BASE + 0x50000) /*!< Timer0 Base Address */ +#define TIMER1_BASE (APB1_BASE + 0x50020) /*!< Timer1 Base Address */ +#define TIMER2_BASE (APB2_BASE + 0x51000) /*!< Timer2 Base Address */ +#define TIMER3_BASE (APB2_BASE + 0x51020) /*!< Timer3 Base Address */ + +#define PWM0_BASE (APB1_BASE + 0x58000) /*!< PWM0 Base Address */ +#define PWM1_BASE (APB2_BASE + 0x59000) /*!< PWM1 Base Address */ + +#define BPWM0_BASE (APB1_BASE + 0x5A000) /*!< BPWM0 Base Address */ +#define BPWM1_BASE (APB2_BASE + 0x5B000) /*!< BPWM1 Base Address */ + +#define QSPI0_BASE (APB1_BASE + 0x60000) /*!< QSPI0 Base Address */ +#define SPI0_BASE (APB1_BASE + 0x61000) /*!< SPI0 Base Address */ + +#define UART0_BASE (APB1_BASE + 0x70000) /*!< UART0 Base Address */ +#define UART1_BASE (APB2_BASE + 0x71000) /*!< UART1 Base Address */ +#define UART2_BASE (APB2_BASE + 0x72000) /*!< UART2 Base Address */ +#define UART3_BASE (APB2_BASE + 0x73000) /*!< UART3 Base Address */ +#define UART4_BASE (APB2_BASE + 0x74000) /*!< UART4 Base Address */ +#define UART5_BASE (APB2_BASE + 0x75000) /*!< UART5 Base Address */ +#define UART6_BASE (APB2_BASE + 0x76000) /*!< UART6 Base Address */ +#define UART7_BASE (APB2_BASE + 0x77000) /*!< UART7 Base Address */ + +#define I2C0_BASE (APB1_BASE + 0x80000) /*!< I2C0 Base Address */ +#define I2C1_BASE (APB2_BASE + 0x81000) /*!< I2C1 Base Address */ + +#define USBD_BASE (AHB_BASE + 0xC0000) /*!< USBD1.1 Base Address */ +#define USCI0_BASE (APB1_BASE + 0xD0000) /*!< USCI0 Base Address */ +#define USCI1_BASE (APB2_BASE + 0xD1000) /*!< USCI1 Base Address */ + + +/**@}*/ /* PERIPHERAL */ + +/******************************************************************************/ +/* Peripheral declaration */ +/******************************************************************************/ + +/** @addtogroup PMODULE Peripheral Pointer + The Declaration of Peripheral Pointer + @{ + */ +#define PA ((GPIO_T *) PA_BASE) /*!< GPIO PORTA Configuration Struct */ +#define PB ((GPIO_T *) PB_BASE) /*!< GPIO PORTB Configuration Struct */ +#define PC ((GPIO_T *) PC_BASE) /*!< GPIO PORTC Configuration Struct */ +#define PD ((GPIO_T *) PD_BASE) /*!< GPIO PORTD Configuration Struct */ +#define PE ((GPIO_T *) PE_BASE) /*!< GPIO PORTE Configuration Struct */ +#define PF ((GPIO_T *) PF_BASE) /*!< GPIO PORTF Configuration Struct */ +#define PG ((GPIO_T *) PG_BASE) /*!< GPIO PORTG Configuration Struct */ +#define PH ((GPIO_T *) PH_BASE) /*!< GPIO PORTH Configuration Struct */ +#define GPIO ((GPIO_DBCTL_T *) GPIO_DBCTL_BASE) /*!< Interrupt De-bounce Cycle Control Configuration Struct */ + +#define UART0 ((UART_T *) UART0_BASE) /*!< UART0 Configuration Struct */ +#define UART1 ((UART_T *) UART1_BASE) /*!< UART1 Configuration Struct */ +#define UART2 ((UART_T *) UART2_BASE) /*!< UART2 Configuration Struct */ +#define UART3 ((UART_T *) UART3_BASE) /*!< UART3 Configuration Struct */ +#define UART4 ((UART_T *) UART4_BASE) /*!< UART4 Configuration Struct */ +#define UART5 ((UART_T *) UART5_BASE) /*!< UART5 Configuration Struct */ +#define UART6 ((UART_T *) UART6_BASE) /*!< UART6 Configuration Struct */ +#define UART7 ((UART_T *) UART7_BASE) /*!< UART7 Configuration Struct */ + +#define TIMER0 ((TIMER_T *) TIMER0_BASE) /*!< TIMER0 Configuration Struct */ +#define TIMER1 ((TIMER_T *) TIMER1_BASE) /*!< TIMER1 Configuration Struct */ +#define TIMER2 ((TIMER_T *) TIMER2_BASE) /*!< TIMER2 Configuration Struct */ +#define TIMER3 ((TIMER_T *) TIMER3_BASE) /*!< TIMER3 Configuration Struct */ + +#define WDT ((WDT_T *) WDT_BASE) /*!< Watch Dog Timer Configuration Struct */ + +#define WWDT ((WWDT_T *) WWDT_BASE) /*!< Window Watch Dog Timer Configuration Struct */ + +#define SPI0 ((SPI_T *) SPI0_BASE) /*!< SPI0 Configuration Struct */ +#define QSPI0 ((QSPI_T *) QSPI0_BASE) /*!< QSPI0 Configuration Struct */ + +#define I2C0 ((I2C_T *) I2C0_BASE) /*!< I2C0 Configuration Struct */ +#define I2C1 ((I2C_T *) I2C1_BASE) /*!< I2C1 Configuration Struct */ + +#define ADC ((ADC_T *) ADC_BASE) /*!< ADC Configuration Struct */ + +#define ACMP01 ((ACMP_T *) ACMP01_BASE) /*!< ACMP01 Configuration Struct */ + +#define CLK ((CLK_T *) CLK_BASE) /*!< System Clock Controller Configuration Struct */ + +#define SYS ((SYS_T *) SYS_BASE) /*!< System Global Controller Configuration Struct */ + +#define SYSINT ((NMI_T *) INT_BASE) /*!< Interrupt Source Controller Configuration Struct */ +#define NMI ((NMI_T *) NMI_BASE) /*!< Interrupt Source Controller Configuration Struct */ + +#define FMC ((FMC_T *) FMC_BASE) /*!< Flash Memory Controller */ + +#define PWM0 ((PWM_T *) PWM0_BASE) /*!< PWM0 Configuration Struct */ +#define PWM1 ((PWM_T *) PWM1_BASE) /*!< PWM1 Configuration Struct */ +#define BPWM0 ((BPWM_T *) BPWM0_BASE) /*!< BPWM0 Configuration Struct */ +#define BPWM1 ((BPWM_T *) BPWM1_BASE) /*!< BPWM1 Configuration Struct */ + +#define EBI ((EBI_T *) EBI_BASE) /*!< EBI Configuration Struct */ + +#define HDIV ((HDIV_T *) HDIV_BASE) /*!< HDIV Configuration Struct */ + +#define CRC ((CRC_T *) CRC_BASE) /*!< CRC Configuration Struct */ + +#define USBD ((USBD_T *) USBD_BASE) /*!< CRC Configuration Struct */ + +#define PDMA ((PDMA_T *) PDMA_BASE) /*!< PDMA Configuration Struct */ + +#define UI2C0 ((UI2C_T *) USCI0_BASE) /*!< UI2C0 Configuration Struct */ +#define UI2C1 ((UI2C_T *) USCI1_BASE) /*!< UI2C1 Configuration Struct */ + +#define USPI0 ((USPI_T *) USCI0_BASE) /*!< USPI0 Configuration Struct */ +#define USPI1 ((USPI_T *) USCI1_BASE) /*!< USPI1 Configuration Struct */ + +#define UUART0 ((UUART_T *) USCI0_BASE) /*!< UUART0 Configuration Struct */ +#define UUART1 ((UUART_T *) USCI1_BASE) /*!< UUART1 Configuration Struct */ + +#define RTC ((RTC_T *) RTC_BASE) /*!< RTC Configuration Struct */ + +/**@}*/ /* end of group PMODULE */ + + +//============================================================================= + +/** @addtogroup IO_ROUTINE I/O Routines + The Declaration of I/O Routines + @{ + */ + +typedef volatile unsigned char vu8; +typedef volatile unsigned long vu32; +typedef volatile unsigned short vu16; + +/** + * @brief Get a 8-bit unsigned value from specified address + * @param[in] addr Address to get 8-bit data from + * @return 8-bit unsigned value stored in specified address + */ +#define M8(addr) (*((vu8 *) (addr))) + +/** + * @brief Get a 16-bit unsigned value from specified address + * @param[in] addr Address to get 16-bit data from + * @return 16-bit unsigned value stored in specified address + * @note The input address must be 16-bit aligned + */ +#define M16(addr) (*((vu16 *) (addr))) + +/** + * @brief Get a 32-bit unsigned value from specified address + * @param[in] addr Address to get 32-bit data from + * @return 32-bit unsigned value stored in specified address + * @note The input address must be 32-bit aligned + */ +#define M32(addr) (*((vu32 *) (addr))) + +/** + * @brief Set a 32-bit unsigned value to specified I/O port + * @param[in] port Port address to set 32-bit data + * @param[in] value Value to write to I/O port + * @return None + * @note The output port must be 32-bit aligned + */ +#define outpw(port,value) (*((volatile unsigned int *)(port))=(value)) + +/** + * @brief Get a 32-bit unsigned value from specified I/O port + * @param[in] port Port address to get 32-bit data from + * @return 32-bit unsigned value stored in specified I/O port + * @note The input port must be 32-bit aligned + */ +#define inpw(port) ((*((volatile unsigned int *)(port)))) + +/** + * @brief Set a 16-bit unsigned value to specified I/O port + * @param[in] port Port address to set 16-bit data + * @param[in] value Value to write to I/O port + * @return None + * @note The output port must be 16-bit aligned + */ +#define outps(port,value) (*((volatile unsigned short *)(port))=(value)) + +/** + * @brief Get a 16-bit unsigned value from specified I/O port + * @param[in] port Port address to get 16-bit data from + * @return 16-bit unsigned value stored in specified I/O port + * @note The input port must be 16-bit aligned + */ +#define inps(port) ((*((volatile unsigned short *)(port)))) + +/** + * @brief Set a 8-bit unsigned value to specified I/O port + * @param[in] port Port address to set 8-bit data + * @param[in] value Value to write to I/O port + * @return None + */ +#define outpb(port,value) (*((volatile unsigned char *)(port))=(value)) + +/** + * @brief Get a 8-bit unsigned value from specified I/O port + * @param[in] port Port address to get 8-bit data from + * @return 8-bit unsigned value stored in specified I/O port + */ +#define inpb(port) ((*((volatile unsigned char *)(port)))) + +/** + * @brief Set a 32-bit unsigned value to specified I/O port + * @param[in] port Port address to set 32-bit data + * @param[in] value Value to write to I/O port + * @return None + * @note The output port must be 32-bit aligned + */ +#define outp32(port,value) (*((volatile unsigned int *)(port))=(value)) + +/** + * @brief Get a 32-bit unsigned value from specified I/O port + * @param[in] port Port address to get 32-bit data from + * @return 32-bit unsigned value stored in specified I/O port + * @note The input port must be 32-bit aligned + */ +#define inp32(port) ((*((volatile unsigned int *)(port)))) + +/** + * @brief Set a 16-bit unsigned value to specified I/O port + * @param[in] port Port address to set 16-bit data + * @param[in] value Value to write to I/O port + * @return None + * @note The output port must be 16-bit aligned + */ +#define outp16(port,value) (*((volatile unsigned short *)(port))=(value)) + +/** + * @brief Get a 16-bit unsigned value from specified I/O port + * @param[in] port Port address to get 16-bit data from + * @return 16-bit unsigned value stored in specified I/O port + * @note The input port must be 16-bit aligned + */ +#define inp16(port) ((*((volatile unsigned short *)(port)))) + +/** + * @brief Set a 8-bit unsigned value to specified I/O port + * @param[in] port Port address to set 8-bit data + * @param[in] value Value to write to I/O port + * @return None + */ +#define outp8(port,value) (*((volatile unsigned char *)(port))=(value)) + +/** + * @brief Get a 8-bit unsigned value from specified I/O port + * @param[in] port Port address to get 8-bit data from + * @return 8-bit unsigned value stored in specified I/O port + */ +#define inp8(port) ((*((volatile unsigned char *)(port)))) + +/*@}*/ /* end of group IO_ROUTINE */ + +/******************************************************************************/ +/* Legacy Constants */ +/******************************************************************************/ + +/** @addtogroup Legacy_Constants Legacy Constants + Legacy Constants + @{ +*/ + +#define E_SUCCESS (0) + +#ifndef NULL + #define NULL (0) ///< NULL pointer +#endif + +#define TRUE (1UL) ///< Boolean true, define to use in API parameters or return value +#define FALSE (0UL) ///< Boolean false, define to use in API parameters or return value + +#define ENABLE (1UL) ///< Enable, define to use in API parameters +#define DISABLE (0UL) ///< Disable, define to use in API parameters + +/* Define one bit mask */ +#define BIT0 (0x00000001UL) ///< Bit 0 mask of an 32 bit integer +#define BIT1 (0x00000002UL) ///< Bit 1 mask of an 32 bit integer +#define BIT2 (0x00000004UL) ///< Bit 2 mask of an 32 bit integer +#define BIT3 (0x00000008UL) ///< Bit 3 mask of an 32 bit integer +#define BIT4 (0x00000010UL) ///< Bit 4 mask of an 32 bit integer +#define BIT5 (0x00000020UL) ///< Bit 5 mask of an 32 bit integer +#define BIT6 (0x00000040UL) ///< Bit 6 mask of an 32 bit integer +#define BIT7 (0x00000080UL) ///< Bit 7 mask of an 32 bit integer +#define BIT8 (0x00000100UL) ///< Bit 8 mask of an 32 bit integer +#define BIT9 (0x00000200UL) ///< Bit 9 mask of an 32 bit integer +#define BIT10 (0x00000400UL) ///< Bit 10 mask of an 32 bit integer +#define BIT11 (0x00000800UL) ///< Bit 11 mask of an 32 bit integer +#define BIT12 (0x00001000UL) ///< Bit 12 mask of an 32 bit integer +#define BIT13 (0x00002000UL) ///< Bit 13 mask of an 32 bit integer +#define BIT14 (0x00004000UL) ///< Bit 14 mask of an 32 bit integer +#define BIT15 (0x00008000UL) ///< Bit 15 mask of an 32 bit integer +#define BIT16 (0x00010000UL) ///< Bit 16 mask of an 32 bit integer +#define BIT17 (0x00020000UL) ///< Bit 17 mask of an 32 bit integer +#define BIT18 (0x00040000UL) ///< Bit 18 mask of an 32 bit integer +#define BIT19 (0x00080000UL) ///< Bit 19 mask of an 32 bit integer +#define BIT20 (0x00100000UL) ///< Bit 20 mask of an 32 bit integer +#define BIT21 (0x00200000UL) ///< Bit 21 mask of an 32 bit integer +#define BIT22 (0x00400000UL) ///< Bit 22 mask of an 32 bit integer +#define BIT23 (0x00800000UL) ///< Bit 23 mask of an 32 bit integer +#define BIT24 (0x01000000UL) ///< Bit 24 mask of an 32 bit integer +#define BIT25 (0x02000000UL) ///< Bit 25 mask of an 32 bit integer +#define BIT26 (0x04000000UL) ///< Bit 26 mask of an 32 bit integer +#define BIT27 (0x08000000UL) ///< Bit 27 mask of an 32 bit integer +#define BIT28 (0x10000000UL) ///< Bit 28 mask of an 32 bit integer +#define BIT29 (0x20000000UL) ///< Bit 29 mask of an 32 bit integer +#define BIT30 (0x40000000UL) ///< Bit 30 mask of an 32 bit integer +#define BIT31 (0x80000000UL) ///< Bit 31 mask of an 32 bit integer + + +/* Byte Mask Definitions */ +#define BYTE0_Msk (0x000000FFUL) ///< Mask to get bit0~bit7 from a 32 bit integer +#define BYTE1_Msk (0x0000FF00UL) ///< Mask to get bit8~bit15 from a 32 bit integer +#define BYTE2_Msk (0x00FF0000UL) ///< Mask to get bit16~bit23 from a 32 bit integer +#define BYTE3_Msk (0xFF000000UL) ///< Mask to get bit24~bit31 from a 32 bit integer + +#define GET_BYTE0(u32Param) (((u32Param) & BYTE0_Msk) ) /*!< Extract Byte 0 (Bit 0~ 7) from parameter u32Param */ +#define GET_BYTE1(u32Param) (((u32Param) & BYTE1_Msk) >> 8) /*!< Extract Byte 1 (Bit 8~15) from parameter u32Param */ +#define GET_BYTE2(u32Param) (((u32Param) & BYTE2_Msk) >> 16) /*!< Extract Byte 2 (Bit 16~23) from parameter u32Param */ +#define GET_BYTE3(u32Param) (((u32Param) & BYTE3_Msk) >> 24) /*!< Extract Byte 3 (Bit 24~31) from parameter u32Param */ + +/* Chip Series number definitions */ +#define GET_CHIP_SERIES_NUM ((SYS->PDID & 0xF00) >> 8) /*!< Extract chip series number from PDID */ +#define CHIP_SERIES_NUM_B (0xBUL) /*!< Chip series number for M031_B */ +#define CHIP_SERIES_NUM_C (0xCUL) /*!< Chip series number for M031_C */ +#define CHIP_SERIES_NUM_D (0xDUL) /*!< Chip series number for M031_D */ +#define CHIP_SERIES_NUM_E (0xEUL) /*!< Chip series number for M031_E */ +#define CHIP_SERIES_NUM_G (0x6UL) /*!< Chip series number for M031_G */ +#define CHIP_SERIES_NUM_I (0x1UL) /*!< Chip series number for M031_I */ + +/*@}*/ /* end of group Legacy_Constants */ + +/******************************************************************************/ +/* Peripheral header files */ +/******************************************************************************/ +#include "nu_sys.h" +#include "nu_clk.h" +#include "nu_acmp.h" +#include "nu_adc.h" +#include "nu_crc.h" +#include "nu_ebi.h" +#include "nu_fmc.h" +#include "nu_gpio.h" +#include "nu_i2c.h" +#include "nu_pdma.h" +#include "nu_pwm.h" +#include "nu_bpwm.h" +#include "nu_qspi.h" +#include "nu_spi.h" +#include "nu_rtc.h" +#include "nu_hdiv.h" +#include "nu_timer.h" +#include "nu_uart.h" +#include "nu_usbd.h" +#include "nu_usci_i2c.h" +#include "nu_usci_spi.h" +#include "nu_usci_uart.h" +#include "nu_wdt.h" +#include "nu_wwdt.h" + +#endif // __M031SERIES_H__ + +/* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/NuMicro.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/NuMicro.h new file mode 100644 index 0000000000..d4db737f90 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/NuMicro.h @@ -0,0 +1,17 @@ +/**************************************************************************//** + * @file NuMicro.h + * @version V1.00 + * @brief NuMicro peripheral access layer header file. + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NUMICRO_H__ +#define __NUMICRO_H__ + +#include "nutool_clkcfg.h" +#include "M031Series.h" + +#endif /* __NUMICRO_H__ */ + +/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/acmp_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/acmp_reg.h new file mode 100644 index 0000000000..b1878c2af9 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/acmp_reg.h @@ -0,0 +1,255 @@ +/**************************************************************************//** + * @file acmp_reg.h + * @version V1.00 + * @brief ACMP register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __ACMP_REG_H__ +#define __ACMP_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup ACMP Analog Comparator Controller (ACMP) + Memory Mapped Structure for ACMP Controller +@{ */ + +typedef struct +{ + + + /** + * @var ACMP_T::CTL + * Offset: 0x00/0x04 Analog Comparator 0/1 Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ACMPEN |Comparator Enable Bit + * | | |0 = Comparator 0 Disabled. + * | | |1 = Comparator 0 Enabled. + * |[1] |ACMPIE |Comparator Interrupt Enable Bit + * | | |0 = Comparator 0 interrupt Disabled. + * | | |1 = Comparator 0 interrupt Enabled. If WKEN (ACMP_CTL0[16]) is set to 1, the wake-up interrupt function will be enabled as well. + * |[3] |ACMPOINV |Comparator Output Inverse + * | | |0 = Comparator 0 output inverse Disabled. + * | | |1 = Comparator 0 output inverse Enabled. + * |[5:4] |NEGSEL |Comparator Negative Input Selection + * | | |00 = ACMP0_N pin. + * | | |01 = Internal comparator reference voltage (CRV). + * | | |10 = Band-gap voltage. + * | | |11 = Reserved. + * |[7:6] |POSSEL |Comparator Positive Input Selection + * | | |00 = Input from ACMP0_P0. + * | | |01 = Input from ACMP0_P1. + * | | |10 = Input from ACMP0_P2. + * | | |11 = Input from ACMP0_P3. + * |[9:8] |INTPOL |Interrupt Condition Polarity Selection + * | | |ACMPIF0 will be set to 1 when comparator output edge condition is detected. + * | | |00 = Rising edge or falling edge. + * | | |01 = Rising edge. + * | | |10 = Falling edge. + * | | |11 = Reserved. + * |[12] |OUTSEL |Comparator Output Select + * | | |0 = Comparator 0 output to ACMP0_O pin is unfiltered comparator output. + * | | |1 = Comparator 0 output to ACMP0_O pin is from filter output. + * |[15:13] |FILTSEL |Comparator Output Filter Count Selection + * | | |000 = Filter function is Disabled. + * | | |001 = ACMP0 output is sampled 1 consecutive PCLK. + * | | |010 = ACMP0 output is sampled 2 consecutive PCLKs. + * | | |011 = ACMP0 output is sampled 4 consecutive PCLKs. + * | | |100 = ACMP0 output is sampled 8 consecutive PCLKs. + * | | |101 = ACMP0 output is sampled 16 consecutive PCLKs. + * | | |110 = ACMP0 output is sampled 32 consecutive PCLKs. + * | | |111 = ACMP0 output is sampled 64 consecutive PCLKs. + * |[16] |WKEN |Power-down Wake-up Enable Bit + * | | |0 = Wake-up function Disabled. + * | | |1 = Wake-up function Enabled. + * |[17] |WLATEN |Window Latch Mode Enable Bit + * | | |0 = Window Latch Mode Disabled. + * | | |1 = Window Latch Mode Enabled. + * |[18] |WCMPSEL |Window Compare Mode Selection + * | | |0 = Window Compare Mode Disabled. + * | | |1 = Window Compare Mode is Selected. + * @var ACMP_T::STATUS + * Offset: 0x08 Analog Comparator Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ACMPIF0 |Comparator 0 Interrupt Flag + * | | |This bit is set by hardware when the edge condition defined by INTPOL (ACMP_CTL0[9:8]) is detected on comparator 0 output. This will generate an interrupt if ACMPIE (ACMP_CTL0[1]) is set to 1. + * | | |Note: Write 1 to clear this bit to 0. + * |[1] |ACMPIF1 |Comparator 1 Interrupt Flag + * | | |This bit is set by hardware when the edge condition defined by INTPOL (ACMP_CTL1[9:8]) is detected on comparator 1 output. + * | | |This will cause an interrupt if ACMPIE (ACMP_CTL1[1]) is set to 1. + * | | |Note: Write 1 to clear this bit to 0. + * |[4] |ACMPO0 |Comparator 0 Output + * | | |Synchronized to the PCLK to allow reading by software. Cleared when the comparator 0 is disabled, i.e. ACMPEN (ACMP_CTL0[0]) is cleared to 0. + * |[5] |ACMPO1 |Comparator 1 Output + * | | |Synchronized to the PCLK to allow reading by software + * | | |Cleared when the comparator 1 is disabled, i.e + * | | |ACMPEN (ACMP_CTL1[0]) is cleared to 0. + * |[8] |WKIF0 |Comparator 0 Power-down Wake-up Interrupt Flag + * | | |This bit will be set to 1 when ACMP0 wake-up interrupt event occurs. + * | | |0 = No power-down wake-up occurred. + * | | |1 = Power-down wake-up occurred. + * | | |Note: Write 1 to clear this bit to 0. + * |[9] |WKIF1 |Comparator 1 Power-down Wake-up Interrupt Flag + * | | |This bit will be set to 1 when ACMP1 wake-up interrupt event occurs. + * | | |0 = No power-down wake-up occurred. + * | | |1 = Power-down wake-up occurred. + * | | |Note: Write 1 to clear this bit to 0. + * |[12] |ACMPS0 |Comparator 0 Status + * | | |Synchronized to the PCLK to allow reading by software. Cleared when the comparator 0 is disabled, i.e. ACMPEN (ACMP_CTL0[0]) is cleared to 0. + * |[13] |ACMPS1 |Comparator 1 Status + * | | |Synchronized to the PCLK to allow reading by software. Cleared when the comparator 1 is disabled, i.e. ACMPEN (ACMP_CTL1[0]) is cleared to 0. + * |[16] |ACMPWO |Comparator Window Output + * | | |This bit shows the output status of window compare mode. + * | | |0 = The positive input voltage is outside the window. + * | | |1 = The positive input voltage is in the window. + * @var ACMP_T::VREF + * Offset: 0x0C Analog Comparator Reference Voltage Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |CRVCTL |Comparator Reference Voltage Setting + * | | |CRV = CRV source voltage * (1/6+CRVCTL/24). + * |[6] |CRVSSEL |CRV Source Voltage Selection + * | | |0 = AVDD is selected as CRV source voltage. + * | | |1 = VREF is selected as as CRV source voltage. + */ + __IO uint32_t CTL[2]; /*!< [0x0000~0x0004] Analog Comparator 0/1 Control Register */ + __IO uint32_t STATUS; /*!< [0x0008] Analog Comparator Status Register */ + __IO uint32_t VREF; /*!< [0x000c] Analog Comparator Reference Voltage Control Register */ + __IO uint32_t CALCTL; /*!< [0x0010] Analog Comparator Calibration Control Register */ + __I uint32_t CALSR; /*!< [0x0014] Analog Comparator Calibration Status Register */ + +} ACMP_T; + +/** + @addtogroup ACMP_CONST ACMP Bit Field Definition + Constant Definitions for ACMP Controller +@{ */ + +#define ACMP_CTL_ACMPEN_Pos (0) /*!< ACMP_T::CTL: ACMPEN Position */ +#define ACMP_CTL_ACMPEN_Msk (0x1ul << ACMP_CTL_ACMPEN_Pos) /*!< ACMP_T::CTL: ACMPEN Mask */ + +#define ACMP_CTL_ACMPIE_Pos (1) /*!< ACMP_T::CTL: ACMPIE Position */ +#define ACMP_CTL_ACMPIE_Msk (0x1ul << ACMP_CTL_ACMPIE_Pos) /*!< ACMP_T::CTL: ACMPIE Mask */ + +#define ACMP_CTL_HYSEN_Pos (2) /*!< ACMP_T::CTL: HYSEN Position */ +#define ACMP_CTL_HYSEN_Msk (0x1ul << ACMP_CTL_HYSEN_Pos) /*!< ACMP_T::CTL: HYSEN Mask */ + +#define ACMP_CTL_ACMPOINV_Pos (3) /*!< ACMP_T::CTL: ACMPOINV Position */ +#define ACMP_CTL_ACMPOINV_Msk (0x1ul << ACMP_CTL_ACMPOINV_Pos) /*!< ACMP_T::CTL: ACMPOINV Mask */ + +#define ACMP_CTL_NEGSEL_Pos (4) /*!< ACMP_T::CTL: NEGSEL Position */ +#define ACMP_CTL_NEGSEL_Msk (0x3ul << ACMP_CTL_NEGSEL_Pos) /*!< ACMP_T::CTL: NEGSEL Mask */ + +#define ACMP_CTL_POSSEL_Pos (6) /*!< ACMP_T::CTL: POSSEL Position */ +#define ACMP_CTL_POSSEL_Msk (0x3ul << ACMP_CTL_POSSEL_Pos) /*!< ACMP_T::CTL: POSSEL Mask */ + +#define ACMP_CTL_INTPOL_Pos (8) /*!< ACMP_T::CTL: INTPOL Position */ +#define ACMP_CTL_INTPOL_Msk (0x3ul << ACMP_CTL_INTPOL_Pos) /*!< ACMP_T::CTL: INTPOL Mask */ + +#define ACMP_CTL_OUTSEL_Pos (12) /*!< ACMP_T::CTL: OUTSEL Position */ +#define ACMP_CTL_OUTSEL_Msk (0x1ul << ACMP_CTL_OUTSEL_Pos) /*!< ACMP_T::CTL: OUTSEL Mask */ + +#define ACMP_CTL_FILTSEL_Pos (13) /*!< ACMP_T::CTL: FILTSEL Position */ +#define ACMP_CTL_FILTSEL_Msk (0x7ul << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_T::CTL: FILTSEL Mask */ + +#define ACMP_CTL_WKEN_Pos (16) /*!< ACMP_T::CTL: WKEN Position */ +#define ACMP_CTL_WKEN_Msk (0x1ul << ACMP_CTL_WKEN_Pos) /*!< ACMP_T::CTL: WKEN Mask */ + +#define ACMP_CTL_WLATEN_Pos (17) /*!< ACMP_T::CTL: WLATEN Position */ +#define ACMP_CTL_WLATEN_Msk (0x1ul << ACMP_CTL_WLATEN_Pos) /*!< ACMP_T::CTL: WLATEN Mask */ + +#define ACMP_CTL_WCMPSEL_Pos (18) /*!< ACMP_T::CTL: WCMPSEL Position */ +#define ACMP_CTL_WCMPSEL_Msk (0x1ul << ACMP_CTL_WCMPSEL_Pos) /*!< ACMP_T::CTL: WCMPSEL Mask */ + +#define ACMP_STATUS_ACMPIF0_Pos (0) /*!< ACMP_T::STATUS: ACMPIF0 Position */ +#define ACMP_STATUS_ACMPIF0_Msk (0x1ul << ACMP_STATUS_ACMPIF0_Pos) /*!< ACMP_T::STATUS: ACMPIF0 Mask */ + +#define ACMP_STATUS_ACMPIF1_Pos (1) /*!< ACMP_T::STATUS: ACMPIF1 Position */ +#define ACMP_STATUS_ACMPIF1_Msk (0x1ul << ACMP_STATUS_ACMPIF1_Pos) /*!< ACMP_T::STATUS: ACMPIF1 Mask */ + +#define ACMP_STATUS_ACMPO0_Pos (4) /*!< ACMP_T::STATUS: ACMPO0 Position */ +#define ACMP_STATUS_ACMPO0_Msk (0x1ul << ACMP_STATUS_ACMPO0_Pos) /*!< ACMP_T::STATUS: ACMPO0 Mask */ + +#define ACMP_STATUS_ACMPO1_Pos (5) /*!< ACMP_T::STATUS: ACMPO1 Position */ +#define ACMP_STATUS_ACMPO1_Msk (0x1ul << ACMP_STATUS_ACMPO1_Pos) /*!< ACMP_T::STATUS: ACMPO1 Mask */ + +#define ACMP_STATUS_WKIF0_Pos (8) /*!< ACMP_T::STATUS: WKIF0 Position */ +#define ACMP_STATUS_WKIF0_Msk (0x1ul << ACMP_STATUS_WKIF0_Pos) /*!< ACMP_T::STATUS: WKIF0 Mask */ + +#define ACMP_STATUS_WKIF1_Pos (9) /*!< ACMP_T::STATUS: WKIF1 Position */ +#define ACMP_STATUS_WKIF1_Msk (0x1ul << ACMP_STATUS_WKIF1_Pos) /*!< ACMP_T::STATUS: WKIF1 Mask */ + +#define ACMP_STATUS_ACMPS0_Pos (12) /*!< ACMP_T::STATUS: ACMPS0 Position */ +#define ACMP_STATUS_ACMPS0_Msk (0x1ul << ACMP_STATUS_ACMPS0_Pos) /*!< ACMP_T::STATUS: ACMPS0 Mask */ + +#define ACMP_STATUS_ACMPS1_Pos (13) /*!< ACMP_T::STATUS: ACMPS1 Position */ +#define ACMP_STATUS_ACMPS1_Msk (0x1ul << ACMP_STATUS_ACMPS1_Pos) /*!< ACMP_T::STATUS: ACMPS1 Mask */ + +#define ACMP_STATUS_ACMPWO_Pos (16) /*!< ACMP_T::STATUS: ACMPWO Position */ +#define ACMP_STATUS_ACMPWO_Msk (0x1ul << ACMP_STATUS_ACMPWO_Pos) /*!< ACMP_T::STATUS: ACMPWO Mask */ + +#define ACMP_VREF_CRVCTL_Pos (0) /*!< ACMP_T::VREF: CRVCTL Position */ +#define ACMP_VREF_CRVCTL_Msk (0xful << ACMP_VREF_CRVCTL_Pos) /*!< ACMP_T::VREF: CRVCTL Mask */ + +#define ACMP_VREF_CRVSSEL_Pos (6) /*!< ACMP_T::VREF: CRVSSEL Position */ +#define ACMP_VREF_CRVSSEL_Msk (0x1ul << ACMP_VREF_CRVSSEL_Pos) /*!< ACMP_T::VREF: CRVSSEL Mask */ + +#define ACMP_CALCTL_CALTRG0_Pos (0) /*!< ACMP_T::CALCTL: CALTRG0 Position */ +#define ACMP_CALCTL_CALTRG0_Msk (0x1ul << ACMP_CALCTL_CALTRG0_Pos) /*!< ACMP_T::CALCTL: CALTRG0 Mask */ + +#define ACMP_CALCTL_CALTRG1_Pos (1) /*!< ACMP_T::CALCTL: CALTRG1 Position */ +#define ACMP_CALCTL_CALTRG1_Msk (0x1ul << ACMP_CALCTL_CALTRG1_Pos) /*!< ACMP_T::CALCTL: CALTRG1 Mask */ + +#define ACMP_CALCTL_CALCLK0_Pos (4) /*!< ACMP_T::CALCTL: CALCLK0 Position */ +#define ACMP_CALCTL_CALCLK0_Msk (0x3ul << ACMP_CALCTL_CALCLK0_Pos) /*!< ACMP_T::CALCTL: CALCLK0 Mask */ + +#define ACMP_CALCTL_CALCLK1_Pos (6) /*!< ACMP_T::CALCTL: CALCLK1 Position */ +#define ACMP_CALCTL_CALCLK1_Msk (0x3ul << ACMP_CALCTL_CALCLK1_Pos) /*!< ACMP_T::CALCTL: CALCLK1 Mask */ + +#define ACMP_CALCTL_CALRVS0_Pos (16) /*!< ACMP_T::CALCTL: CALRVS0 Position */ +#define ACMP_CALCTL_CALRVS0_Msk (0x1ul << ACMP_CALCTL_CALRVS0_Pos) /*!< ACMP_T::CALCTL: CALRVS0 Mask */ + +#define ACMP_CALCTL_CALRVS1_Pos (17) /*!< ACMP_T::CALCTL: CALRVS1 Position */ +#define ACMP_CALCTL_CALRVS1_Msk (0x1ul << ACMP_CALCTL_CALRVS1_Pos) /*!< ACMP_T::CALCTL: CALRVS1 Mask */ + +#define ACMP_CALSR_DONE0_Pos (0) /*!< ACMP_T::CALSR: DONE0 Position */ +#define ACMP_CALSR_DONE0_Msk (0x1ul << ACMP_CALSR_DONE0_Pos) /*!< ACMP_T::CALSR: DONE0 Mask */ + +#define ACMP_CALSR_CALNS0_Pos (1) /*!< ACMP_T::CALSR: CALNS0 Position */ +#define ACMP_CALSR_CALNS0_Msk (0x1ul << ACMP_CALSR_CALNS0_Pos) /*!< ACMP_T::CALSR: CALNS0 Mask */ + +#define ACMP_CALSR_CALPS0_Pos (2) /*!< ACMP_T::CALSR: CALPS0 Position */ +#define ACMP_CALSR_CALPS0_Msk (0x1ul << ACMP_CALSR_CALPS0_Pos) /*!< ACMP_T::CALSR: CALPS0 Mask */ + +#define ACMP_CALSR_DONE1_Pos (4) /*!< ACMP_T::CALSR: DONE1 Position */ +#define ACMP_CALSR_DONE1_Msk (0x1ul << ACMP_CALSR_DONE1_Pos) /*!< ACMP_T::CALSR: DONE1 Mask */ + +#define ACMP_CALSR_CALNS1_Pos (5) /*!< ACMP_T::CALSR: CALNS1 Position */ +#define ACMP_CALSR_CALNS1_Msk (0x1ul << ACMP_CALSR_CALNS1_Pos) /*!< ACMP_T::CALSR: CALNS1 Mask */ + +#define ACMP_CALSR_CALPS1_Pos (6) /*!< ACMP_T::CALSR: CALPS1 Position */ +#define ACMP_CALSR_CALPS1_Msk (0x1ul << ACMP_CALSR_CALPS1_Pos) /*!< ACMP_T::CALSR: CALPS1 Mask */ + +/**@}*/ /* ACMP_CONST */ +/**@}*/ /* end of ACMP register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __ACMP_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/adc_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/adc_reg.h new file mode 100644 index 0000000000..77cd67586a --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/adc_reg.h @@ -0,0 +1,400 @@ +/**************************************************************************//** + * @file adc_reg.h + * @version V1.00 + * @brief ADC register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __ADC_REG_H__ +#define __ADC_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup ADC Analog to Digital Converter (ADC) + Memory Mapped Structure for ADC Controller +@{ */ + +typedef struct +{ + + + /** + * @var ADC_T::ADDR + * Offset: 0x00-0x74 ADC Data Register 0-29 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RSLT |A/D Conversion Result (Read Only) + * | | |This field contains conversion result of ADC. + * |[16] |OVERRUN |Overrun Flag (Read Only) + * | | |If converted data in RSLT bits has not been read before new conversion result is loaded to this register, OVERRUN bit is set to 1. It is cleared by hardware after ADDR register is read. + * | | |0 = Data in RSLT bits is not overwrote. + * | | |1 = Data in RSLT bits is overwrote. + * |[17] |VALID |Valid Flag (Read Only) + * | | |This bit will be set to 1 when the conversion of the corresponding channel is completed. This bit will be cleared to 0 by hardware after ADDR register is read. + * | | |0 = Data in RSLT bits is not valid. + * | | |1 = Data in RSLT bits is valid. + * @var ADC_T::ADCR + * Offset: 0x80 ADC Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ADEN |A/D Converter Enable Bit + * | | |0 = A/D converter Disabled. + * | | |1 = A/D converter Enabled. + * | | |Note: Before starting A/D conversion function, this bit should be set to 1. Clear it to 0 to disable A/D converter analog circuit to save power consumption. + * |[1] |ADIE |A/D Interrupt Enable Bit + * | | |A/D conversion end interrupt request is generated if ADIE bit is set to 1. + * | | |0 = A/D interrupt function Disabled. + * | | |1 = A/D interrupt function Enabled. + * |[3:2] |ADMD |A/D Converter Operation Mode Control + * | | |00 = Single conversion. + * | | |01 = Burst conversion. + * | | |10 = Single-cycle Scan. + * | | |11 = Continuous Scan. + * | | |Note1: When changing the operation mode, software should clear ADST bit first. + * | | |Note2: In Burst mode, the A/D result data is always at ADC Data Register 0. + * |[5:4] |TRGS |Hardware Trigger Source + * | | |00 = A/D conversion is started by external STADC pin. + * | | |01 = Timer0 ~ Timer3 overflow pulse trigger. + * | | |10 = Reserved. + * | | |11 = A/D conversion is started by PWM trigger. + * | | |Note: Software should clear TRGEN bit and ADST bit to 0 before changing TRGS bits. + * |[7:6] |TRGCOND |External Trigger Condition + * | | |These two bits decide external pin STADC trigger event is level or edge. The signal must be kept at stable state at least 8 PCLKs for level trigger and at least 4 PCLKs for edge trigger. + * | | |00 = Low level. + * | | |01 = High level. + * | | |10 = Falling edge. + * | | |11 = Rising edge. + * |[8] |TRGEN |External Trigger Enable Bit + * | | |Enable or disable triggering of A/D conversion by external STADC pin, PWM trigger and Timer trigger. If external trigger is enabled, the ADST bit can be set to 1 by the selected hardware trigger source. + * | | |0 = External trigger Disabled. + * | | |1 = External trigger Enabled. + * | | |Note: The ADC external trigger function is only supported in Single-cycle Scan mode. + * |[9] |PTEN |PDMA Transfer Enable Bit + * | | |When A/D conversion is completed, the converted data is loaded into ADDR0~15, ADDR29. Software can enable this bit to generate a PDMA data transfer request. + * | | |0 = PDMA data transfer Disabled. + * | | |1 = PDMA data transfer in ADDR0~15, ADDR29 Enabled. + * | | |Note: When PTEN=1, software must set ADIE=0 to disable interrupt. + * |[10] |DIFFEN |Differential Input Mode Control + * | | |Differential input voltage (Vdiff) = Vplus - Vminus. + * | | |The relation between Vplus and Vminus is Vplus + Vminus = Vref. + * | | |The Vplus of differential input paired channel x is from ADC0_CHy pin; Vminus is from ADC0_CHz pin, x=0,1..7, y=2*x, z=y+1. + * | | |0 = Single-end analog input mode. + * | | |1 = Differential analog input mode. + * | | |Note: In Differential Input mode, only the even number of the two corresponding channels needs to be enabled in ADCHER register. The conversion result will be placed to the corresponding data register of the enabled channel. + * |[11] |ADST |A/D Conversion Start or Calibration Start + * | | |ADST bit can be set to 1 from four sources: software, external pin STADC, PWM trigger and Timer trigger. ADST bit will be cleared to 0 by hardware automatically at the ends of Single mode, Single-cycle Scan mode and Calibration mode. In Continuous Scan mode and Burst mode, A/D conversion is continuously performed until software writes 0 to this bit or chip is reset. + * | | |0 = Conversion stops and A/D converter enters idle state. + * | | |1 = Conversion starts or Calibration Start. + * | | |Note1: When ADST become from 1 to 0, ADC macro will reset to initial state. After macro reset to initial state, user should wait at most 2 ADC clock and set this bit to start next conversion. + * | | |Note2: Calibration Start only if CALEN (ADC_ADCALR[0]) = 1. + * |[12] |RESET |ADC RESET (Write Protect) + * | | |If user writes this bit, the ADC analog macro will reset + * | | |Calibration data in macro will be deleted, but registers in ADC controller will keep. + * | | |Note: This bit is cleared by hardware. + * |[31] |DMOF |Differential Input Mode Output Format + * | | |If user enables differential input mode, the conversion result can be expressed with binary straight format (unsigned format) or 2's complement format (signed format). + * | | |0 = A/D Conversion result will be filled in RSLT at ADDRx registers with unsigned format (straight binary format). + * | | |1 = A/D Conversion result will be filled in RSLT at ADDRx registers with 2's complement format. + * @var ADC_T::ADCHER + * Offset: 0x84 ADC Channel Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |CHEN |Analog Input Channel Enable Control + * | | |Set ADCHER[15:0] bits to enable the corresponding analog input channel 15 ~ 0 + * | | |If DIFFEN bit is set to 1, only the even number channel needs to be enabled. + * | | |Besides, set ADCHER[29] bit will enable internal channel for band-gap voltage respectively + * | | |Other bits are reserved. + * | | |0 = Channel Disabled. + * | | |1 = Channel Enabled. + * | | |Note1: If the internal channel for band-gap voltage (CHEN[29]) is active, the maximum sampling rate will be 1M SPS. + * @var ADC_T::ADCMPR + * Offset: 0x88/0x8C ADC Compare Register 0/1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CMPEN |Compare Enable Bit + * | | |Set this bit to 1 to enable ADC controller to compare CMPD (ADCMPRx[27:16]) with specified channel conversion result when converted data is loaded into ADDR register. + * | | |0 = Compare function Disabled. + * | | |1 = Compare function Enabled. + * |[1] |CMPIE |Compare Interrupt Enable Bit + * | | |If the compare function is enabled and the compare condition matches the setting of CMPCOND and CMPMATCNT, CMPFx bit will be asserted, in the meanwhile, if CMPIE bit is set to 1, a compare interrupt request is generated. + * | | |0 = Compare function interrupt Disabled. + * | | |1 = Compare function interrupt Enabled. + * |[2] |CMPCOND |Compare Condition + * | | |0 = Set the compare condition as that when a 12-bit A/D conversion result is less than the 12-bit CMPD bits, the internal match counter will increase one. + * | | |1 = Set the compare condition as that when a 12-bit A/D conversion result is greater than or equal to the 12-bit CMPD bits, the internal match counter will increase one. + * | | |Note: When the internal counter reaches to (CMPMATCNT +1), the CMPFx bit will be set. + * |[7:3] |CMPCH |Compare Channel Selection + * | | |00000 = Channel 0 conversion result is selected to be compared. + * | | |00001 = Channel 1 conversion result is selected to be compared. + * | | |00010 = Channel 2 conversion result is selected to be compared. + * | | |00011 = Channel 3 conversion result is selected to be compared. + * | | |00100 = Channel 4 conversion result is selected to be compared. + * | | |00101 = Channel 5 conversion result is selected to be compared. + * | | |00110 = Channel 6 conversion result is selected to be compared. + * | | |00111 = Channel 7 conversion result is selected to be compared. + * | | |01000 = Channel 8 conversion result is selected to be compared. + * | | |01001 = Channel 9 conversion result is selected to be compared. + * | | |01010 = Channel 10 conversion result is selected to be compared. + * | | |01011 = Channel 11 conversion result is selected to be compared. + * | | |01100 = Channel 12 conversion result is selected to be compared. + * | | |01101 = Channel 13 conversion result is selected to be compared. + * | | |01110 = Channel 14 conversion result is selected to be compared. + * | | |01111 = Channel 15 conversion result is selected to be compared. + * | | |11101 = Band-gap voltage conversion result is selected to be compared. + * | | |Others = Reserved. + * |[11:8] |CMPMATCNT |Compare Match Count + * | | |When the specified A/D channel analog conversion result matches the compare condition defined by CMPCOND bit, the internal match counter will increase 1. When the internal counter reaches the value to (CMPMATCNT +1), the CMPFx bit will be set. + * |[15] |CMPWEN |Compare Window Mode Enable Bit + * | | |0 = Compare Window Mode Disabled. + * | | |1 = Compare Window Mode Enabled. + * | | |Note: This bit is only presented in ADCMPR0 register. + * |[27:16] |CMPD |Comparison Data + * | | |The 12-bit data is used to compare with conversion result of specified channel. + * | | |Note: CMPD bits should be filled in unsigned format (straight binary format). + * @var ADC_T::ADSR0 + * Offset: 0x90 ADC Status Register0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ADF |A/D Conversion End Flag + * | | |A status flag that indicates the end of A/D conversion. Software can write 1 to clear this bit. + * | | |ADF bit is set to 1 at the following three conditions: + * | | |1. When A/D conversion ends in Single mode. + * | | |2. When A/D conversion ends on all specified channels in Single-cycle Scan mode and Continuous Scan mode. + * | | |3. When more than or equal to 8 samples in FIFO in Burst mode. + * |[1] |CMPF0 |Compare Flag 0 + * | | |When the A/D conversion result of the selected channel meets setting condition in ADCMPR0 register then this bit is set to 1. This bit is cleared by writing 1 to it. + * | | |0 = Conversion result in ADDR does not meet ADCMPR0 setting. + * | | |1 = Conversion result in ADDR meets ADCMPR0 setting. + * |[2] |CMPF1 |Compare Flag 1 + * | | |When the A/D conversion result of the selected channel meets setting condition in ADCMPR1 register then this bit is set to 1; it is cleared by writing 1 to it. + * | | |0 = Conversion result in ADDR does not meet ADCMPR1 setting. + * | | |1 = Conversion result in ADDR meets ADCMPR1 setting. + * |[7] |BUSY |BUSY/IDLE (Read Only) + * | | |This bit is a mirror of ADST bit in ADCR register. + * | | |0 = A/D converter is in idle state. + * | | |1 = A/D converter is busy at conversion. + * |[8] |VALIDF |Data Valid Flag (Read Only) + * | | |If any one of VALID (ADDRx[17]) is set, this flag will be set to 1. + * | | |Note: When ADC is in burst mode and any conversion result is valid, this flag will be set to 1. + * |[16] |OVERRUNF |Overrun Flag (Read Only) + * | | |If any one of OVERRUN (ADDRx[16]) is set, this flag will be set to 1. + * | | |Note: When ADC is in burst mode and the FIFO is overrun, this flag will be set to 1. + * |[31:27] |CHANNEL |Current Conversion Channel (Read Only) + * | | |When BUSY=1, this filed reflects current conversion channel. When BUSY=0, it shows the number of the next converted channel. + * @var ADC_T::ADSR1 + * Offset: 0x94 ADC Status Register1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |VALID |Data Valid Flag (Read Only) + * | | |VALID[29, 15:0] are the mirror of the VALID bits in ADDR29[17], ADDR15[17]~ ADDR0[17]. The other bits are reserved. + * | | |Note: When ADC is in burst mode and any conversion result is valid, VALID[29, 15:0] will be set to 1. + * @var ADC_T::ADSR2 + * Offset: 0x98 ADC Status Register2 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |OVERRUN |Overrun Flag (Read Only) + * | | |OVERRUN[29, 15:0] are the mirror of the OVERRUN bit in ADDR29[16], ADDR15[16] ~ ADDR0[16]. The other bits are reserved. + * | | |Note: When ADC is in burst mode and the FIFO is overrun, OVERRUN[29, 15:0] will be set to 1. + * @var ADC_T::ESMPCTL + * Offset: 0xA0 ADC Extend Sample Time Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |EXTSMPT |ADC Sampling Time Extend + * | | |When ADC converting at high conversion rate, the sampling time of analog input voltage may not enough if input channel loading is heavy, user can extend ADC sampling time after trigger source is coming to get enough sampling time. + * | | |The range of start delay time is from 0~255 ADC clock. + * @var ADC_T::ADPDMA + * Offset: 0x100 ADC PDMA Current Transfer Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[17:0] |CURDAT |ADC PDMA Current Transfer Data Register (Read Only) + * | | |When PDMA transferring, read this register can monitor current PDMA transfer data. + * | | |Current PDMA transfer data could be the content of ADDR0 ~ ADDR15 and ADDR29 registers. + * @var ADC_T::ADCALR + * Offset: 0x180 ADC Calibration Mode Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CALEN |Calibration Function Enable Bit + * | | |0 = Calibration function Disable. + * | | |1 = Calibration function Enable. + * | | |Note: If chip power off, calibration function should be executed again. + * |[1] |CALIE |Calibration Interrupt Enable + * | | |If calibration function is enabled and the calibration finish, CALIF bit will be asserted, in the meanwhile, if CALIE bit is set to 1, a calibration interrupt request is generated. + * | | |0 = Calibration function Interrupt Disable. + * | | |1 = Calibration function Interrupt Enable. + * @var ADC_T::ADCALSTSR + * Offset: 0x184 ADC Calibration Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CALIF |Calibration Finish Interrupt Flag + * | | |If calibration finish, this flag will be set to 1. It is cleared by writing 1 to it. + */ + __I uint32_t ADDR[30]; /*!< [0x0000-0x0074] ADC Data Register 0 ~ 29 */ + __I uint32_t RESERVE1[2]; + __IO uint32_t ADCR; /*!< [0x0080] ADC Control Register */ + __IO uint32_t ADCHER; /*!< [0x0084] ADC Channel Enable Register */ + __IO uint32_t ADCMPR[2]; /*!< [0x0088-0x008c] ADC Compare Register 0/1 */ + __IO uint32_t ADSR0; /*!< [0x0090] ADC Status Register0 */ + __I uint32_t ADSR1; /*!< [0x0094] ADC Status Register1 */ + __I uint32_t ADSR2; /*!< [0x0098] ADC Status Register2 */ + __I uint32_t RESERVE2[1]; + __IO uint32_t ESMPCTL; /*!< [0x00a0] ADC Extend Sample Time Control Register */ + __IO uint32_t CFDCTL; /*!< [0x00a4] ADC Channel Floating Detect Control Register */ + __I uint32_t RESERVE3[22]; + __I uint32_t ADPDMA; /*!< [0x0100] ADC PDMA Current Transfer Data Register */ + __I uint32_t RESERVE4[31]; + __IO uint32_t ADCALR; /*!< [0x0180] ADC Calibration Mode Register */ + __IO uint32_t ADCALSTSR; /*!< [0x0184] ADC Calibration Status Register */ + __IO uint32_t ADCALDBR; /*!< [0x0188] ADC Calibration Debug Mode Register */ +} ADC_T; + +/** + @addtogroup ADC_CONST ADC Bit Field Definition + Constant Definitions for ADC Controller +@{ */ + +#define ADC_ADDR_RSLT_Pos (0) /*!< ADC_T::ADDR: RSLT Position */ +#define ADC_ADDR_RSLT_Msk (0xfffful << ADC_ADDR_RSLT_Pos) /*!< ADC_T::ADDR: RSLT Mask */ + +#define ADC_ADDR_OVERRUN_Pos (16) /*!< ADC_T::ADDR: OVERRUN Position */ +#define ADC_ADDR_OVERRUN_Msk (0x1ul << ADC_ADDR_OVERRUN_Pos) /*!< ADC_T::ADDR: OVERRUN Mask */ + +#define ADC_ADDR_VALID_Pos (17) /*!< ADC_T::ADDR: VALID Position */ +#define ADC_ADDR_VALID_Msk (0x1ul << ADC_ADDR_VALID_Pos) /*!< ADC_T::ADDR: VALID Mask */ + +#define ADC_ADCR_ADEN_Pos (0) /*!< ADC_T::ADCR: ADEN Position */ +#define ADC_ADCR_ADEN_Msk (0x1ul << ADC_ADCR_ADEN_Pos) /*!< ADC_T::ADCR: ADEN Mask */ + +#define ADC_ADCR_ADIE_Pos (1) /*!< ADC_T::ADCR: ADIE Position */ +#define ADC_ADCR_ADIE_Msk (0x1ul << ADC_ADCR_ADIE_Pos) /*!< ADC_T::ADCR: ADIE Mask */ + +#define ADC_ADCR_ADMD_Pos (2) /*!< ADC_T::ADCR: ADMD Position */ +#define ADC_ADCR_ADMD_Msk (0x3ul << ADC_ADCR_ADMD_Pos) /*!< ADC_T::ADCR: ADMD Mask */ + +#define ADC_ADCR_TRGS_Pos (4) /*!< ADC_T::ADCR: TRGS Position */ +#define ADC_ADCR_TRGS_Msk (0x3ul << ADC_ADCR_TRGS_Pos) /*!< ADC_T::ADCR: TRGS Mask */ + +#define ADC_ADCR_TRGCOND_Pos (6) /*!< ADC_T::ADCR: TRGCOND Position */ +#define ADC_ADCR_TRGCOND_Msk (0x3ul << ADC_ADCR_TRGCOND_Pos) /*!< ADC_T::ADCR: TRGCOND Mask */ + +#define ADC_ADCR_TRGEN_Pos (8) /*!< ADC_T::ADCR: TRGEN Position */ +#define ADC_ADCR_TRGEN_Msk (0x1ul << ADC_ADCR_TRGEN_Pos) /*!< ADC_T::ADCR: TRGEN Mask */ + +#define ADC_ADCR_PTEN_Pos (9) /*!< ADC_T::ADCR: PTEN Position */ +#define ADC_ADCR_PTEN_Msk (0x1ul << ADC_ADCR_PTEN_Pos) /*!< ADC_T::ADCR: PTEN Mask */ + +#define ADC_ADCR_DIFFEN_Pos (10) /*!< ADC_T::ADCR: DIFFEN Position */ +#define ADC_ADCR_DIFFEN_Msk (0x1ul << ADC_ADCR_DIFFEN_Pos) /*!< ADC_T::ADCR: DIFFEN Mask */ + +#define ADC_ADCR_ADST_Pos (11) /*!< ADC_T::ADCR: ADST Position */ +#define ADC_ADCR_ADST_Msk (0x1ul << ADC_ADCR_ADST_Pos) /*!< ADC_T::ADCR: ADST Mask */ + +#define ADC_ADCR_RESET_Pos (12) /*!< ADC_T::ADCR: RESET Position */ +#define ADC_ADCR_RESET_Msk (0x1ul << ADC_ADCR_RESET_Pos) /*!< ADC_T::ADCR: RESET Mask */ + +#define ADC_ADCR_DMOF_Pos (31) /*!< ADC_T::ADCR: DMOF Position */ +#define ADC_ADCR_DMOF_Msk (0x1ul << ADC_ADCR_DMOF_Pos) /*!< ADC_T::ADCR: DMOF Mask */ + +#define ADC_ADCHER_CHEN_Pos (0) /*!< ADC_T::ADCHER: CHEN Position */ +#define ADC_ADCHER_CHEN_Msk (0xfffffffful << ADC_ADCHER_CHEN_Pos) /*!< ADC_T::ADCHER: CHEN Mask */ + +#define ADC_ADCMPR_CMPEN_Pos (0) /*!< ADC_T::ADCMPR: CMPEN Position */ +#define ADC_ADCMPR_CMPEN_Msk (0x1ul << ADC_ADCMPR_CMPEN_Pos) /*!< ADC_T::ADCMPR: CMPEN Mask */ + +#define ADC_ADCMPR_CMPIE_Pos (1) /*!< ADC_T::ADCMPR: CMPIE Position */ +#define ADC_ADCMPR_CMPIE_Msk (0x1ul << ADC_ADCMPR_CMPIE_Pos) /*!< ADC_T::ADCMPR: CMPIE Mask */ + +#define ADC_ADCMPR_CMPCOND_Pos (2) /*!< ADC_T::ADCMPR: CMPCOND Position */ +#define ADC_ADCMPR_CMPCOND_Msk (0x1ul << ADC_ADCMPR_CMPCOND_Pos) /*!< ADC_T::ADCMPR: CMPCOND Mask */ + +#define ADC_ADCMPR_CMPCH_Pos (3) /*!< ADC_T::ADCMPR: CMPCH Position */ +#define ADC_ADCMPR_CMPCH_Msk (0x1ful << ADC_ADCMPR_CMPCH_Pos) /*!< ADC_T::ADCMPR: CMPCH Mask */ + +#define ADC_ADCMPR_CMPMATCNT_Pos (8) /*!< ADC_T::ADCMPR: CMPMATCNT Position */ +#define ADC_ADCMPR_CMPMATCNT_Msk (0xful << ADC_ADCMPR_CMPMATCNT_Pos) /*!< ADC_T::ADCMPR: CMPMATCNT Mask */ + +#define ADC_ADCMPR_CMPWEN_Pos (15) /*!< ADC_T::ADCMPR: CMPWEN Position */ +#define ADC_ADCMPR_CMPWEN_Msk (0x1ul << ADC_ADCMPR_CMPWEN_Pos) /*!< ADC_T::ADCMPR: CMPWEN Mask */ + +#define ADC_ADCMPR_CMPD_Pos (16) /*!< ADC_T::ADCMPR: CMPD Position */ +#define ADC_ADCMPR_CMPD_Msk (0xffful << ADC_ADCMPR_CMPD_Pos) /*!< ADC_T::ADCMPR: CMPD Mask */ + +#define ADC_ADSR0_ADF_Pos (0) /*!< ADC_T::ADSR0: ADF Position */ +#define ADC_ADSR0_ADF_Msk (0x1ul << ADC_ADSR0_ADF_Pos) /*!< ADC_T::ADSR0: ADF Mask */ + +#define ADC_ADSR0_CMPF0_Pos (1) /*!< ADC_T::ADSR0: CMPF0 Position */ +#define ADC_ADSR0_CMPF0_Msk (0x1ul << ADC_ADSR0_CMPF0_Pos) /*!< ADC_T::ADSR0: CMPF0 Mask */ + +#define ADC_ADSR0_CMPF1_Pos (2) /*!< ADC_T::ADSR0: CMPF1 Position */ +#define ADC_ADSR0_CMPF1_Msk (0x1ul << ADC_ADSR0_CMPF1_Pos) /*!< ADC_T::ADSR0: CMPF1 Mask */ + +#define ADC_ADSR0_BUSY_Pos (7) /*!< ADC_T::ADSR0: BUSY Position */ +#define ADC_ADSR0_BUSY_Msk (0x1ul << ADC_ADSR0_BUSY_Pos) /*!< ADC_T::ADSR0: BUSY Mask */ + +#define ADC_ADSR0_VALIDF_Pos (8) /*!< ADC_T::ADSR0: VALIDF Position */ +#define ADC_ADSR0_VALIDF_Msk (0x1ul << ADC_ADSR0_VALIDF_Pos) /*!< ADC_T::ADSR0: VALIDF Mask */ + +#define ADC_ADSR0_OVERRUNF_Pos (16) /*!< ADC_T::ADSR0: OVERRUNF Position */ +#define ADC_ADSR0_OVERRUNF_Msk (0x1ul << ADC_ADSR0_OVERRUNF_Pos) /*!< ADC_T::ADSR0: OVERRUNF Mask */ + +#define ADC_ADSR0_CHANNEL_Pos (27) /*!< ADC_T::ADSR0: CHANNEL Position */ +#define ADC_ADSR0_CHANNEL_Msk (0x1ful << ADC_ADSR0_CHANNEL_Pos) /*!< ADC_T::ADSR0: CHANNEL Mask */ + +#define ADC_ADSR1_VALID_Pos (0) /*!< ADC_T::ADSR1: VALID Position */ +#define ADC_ADSR1_VALID_Msk (0xfffffffful << ADC_ADSR1_VALID_Pos) /*!< ADC_T::ADSR1: VALID Mask */ + +#define ADC_ADSR2_OVERRUN_Pos (0) /*!< ADC_T::ADSR2: OVERRUN Position */ +#define ADC_ADSR2_OVERRUN_Msk (0xfffffffful << ADC_ADSR2_OVERRUN_Pos) /*!< ADC_T::ADSR2: OVERRUN Mask */ + +#define ADC_ESMPCTL_EXTSMPT_Pos (0) /*!< ADC_T::ESMPCTL: EXTSMPT Position */ +#define ADC_ESMPCTL_EXTSMPT_Msk (0xfful << ADC_ESMPCTL_EXTSMPT_Pos) /*!< ADC_T::ESMPCTL: EXTSMPT Mask */ + +#define ADC_CFDCTL_PRECHEN_Pos (0) /*!< ADC_T::CFDCTL: PRECHEN Position */ +#define ADC_CFDCTL_PRECHEN_Msk (0x1ul << ADC_CFDCTL_PRECHEN_Pos) /*!< ADC_T::CFDCTL: PRECHEN Mask */ + +#define ADC_CFDCTL_DISCHEN_Pos (1) /*!< ADC_T::CFDCTL: DISCHEN Position */ +#define ADC_CFDCTL_DISCHEN_Msk (0x1ul << ADC_CFDCTL_DISCHEN_Pos) /*!< ADC_T::CFDCTL: DISCHEN Mask */ + +#define ADC_CFDCTL_FDETCHEN_Pos (8) /*!< ADC_T::CFDCTL: FDETCHEN Position */ +#define ADC_CFDCTL_FDETCHEN_Msk (0x1ul << ADC_CFDCTL_FDETCHEN_Pos) /*!< ADC_T::CFDCTL: FDETCHEN Mask */ + +#define ADC_ADPDMA_CURDAT_Pos (0) /*!< ADC_T::ADPDMA: CURDAT Position */ +#define ADC_ADPDMA_CURDAT_Msk (0x3fffful << ADC_ADPDMA_CURDAT_Pos) /*!< ADC_T::ADPDMA: CURDAT Mask */ + +#define ADC_ADCALR_CALEN_Pos (0) /*!< ADC_T::ADCALR: CALEN Position */ +#define ADC_ADCALR_CALEN_Msk (0x1ul << ADC_ADCALR_CALEN_Pos) /*!< ADC_T::ADCALR: CALEN Mask */ + +#define ADC_ADCALR_CALIE_Pos (1) /*!< ADC_T::ADCALR: CALIE Position */ +#define ADC_ADCALR_CALIE_Msk (0x1ul << ADC_ADCALR_CALIE_Pos) /*!< ADC_T::ADCALR: CALIE Mask */ + +#define ADC_ADCALSTSR_CALIF_Pos (0) /*!< ADC_T::ADCALSTSR: CALIF Position */ +#define ADC_ADCALSTSR_CALIF_Msk (0x1ul << ADC_ADCALSTSR_CALIF_Pos) /*!< ADC_T::ADCALSTSR: CALIF Mask */ + +/**@}*/ /* ADC_CONST */ +/**@}*/ /* end of ADC register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __ADC_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/bpwm_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/bpwm_reg.h new file mode 100644 index 0000000000..25bcede03a --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/bpwm_reg.h @@ -0,0 +1,1743 @@ +/**************************************************************************//** + * @file bpwm_reg.h + * @version V1.00 + * @brief BPWM register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __BPWM_REG_H__ +#define __BPWM_REG_H__ + + +#if defined ( __CC_ARM ) + #pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup BPWM Basic Pulse Width Modulation Controller (BPWM) + Memory Mapped Structure for BPWM Controller +@{ */ +typedef struct +{ + /** + * @var BCAPDAT_T::RCAPDAT + * Offset: 0x20C~0x238 BPWM Rising Capture Data Register 0~5 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RCAPDAT |BPWM Rising Capture Data (Read Only) + * | | |When rising capture condition happened, the BPWM counter value will be saved in this register. + * @var BCAPDAT_T::FCAPDAT + * Offset: 0x210 BPWM Falling Capture Data Register 0~5 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |FCAPDAT |BPWM Falling Capture Data (Read Only) + * | | |When falling capture condition happened, the BPWM counter value will be saved in this register. + */ + __IO uint32_t RCAPDAT; /*!< [0x20C/0x214/0x21C/0x224/0x22C/0x234] BPWM Rising Capture Data Register 0~5 */ + __IO uint32_t FCAPDAT; /*!< [0x210/0x218/0x220/0x228/0x230/0x238] BPWM Falling Capture Data Register 0~5 */ +} BCAPDAT_T; + +typedef struct +{ + + + /** + * @var BPWM_T::CTL0 + * Offset: 0x00 BPWM Control Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CTRLD0 |Center Re-load + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |In up-down counter type, PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the center point of a period + * |[1] |CTRLD1 |Center Re-load + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |In up-down counter type, PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the center point of a period + * |[2] |CTRLD2 |Center Re-load + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |In up-down counter type, PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the center point of a period + * |[3] |CTRLD3 |Center Re-load + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |In up-down counter type, PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the center point of a period + * |[4] |CTRLD4 |Center Re-load + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |In up-down counter type, PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the center point of a period + * |[5] |CTRLD5 |Center Re-load + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |In up-down counter type, PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the center point of a period + * |[16] |IMMLDEN0 |Immediately Load Enable Bit(S) + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the end point or center point of each period by setting CTRLD bit. + * | | |1 = PERIOD/CMPDAT will load to PBUF and CMPBUF immediately when software update PERIOD/CMPDAT. + * | | |Note: If IMMLDENn is Enabled, WINLDENn and CTRLDn will be invalid. + * |[17] |IMMLDEN1 |Immediately Load Enable Bit(S) + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the end point or center point of each period by setting CTRLD bit. + * | | |1 = PERIOD/CMPDAT will load to PBUF and CMPBUF immediately when software update PERIOD/CMPDAT. + * | | |Note: If IMMLDENn is Enabled, WINLDENn and CTRLDn will be invalid. + * |[18] |IMMLDEN2 |Immediately Load Enable Bit(S) + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the end point or center point of each period by setting CTRLD bit. + * | | |1 = PERIOD/CMPDAT will load to PBUF and CMPBUF immediately when software update PERIOD/CMPDAT. + * | | |Note: If IMMLDENn is Enabled, WINLDENn and CTRLDn will be invalid. + * |[19] |IMMLDEN3 |Immediately Load Enable Bit(S) + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the end point or center point of each period by setting CTRLD bit. + * | | |1 = PERIOD/CMPDAT will load to PBUF and CMPBUF immediately when software update PERIOD/CMPDAT. + * | | |Note: If IMMLDENn is Enabled, WINLDENn and CTRLDn will be invalid. + * |[20] |IMMLDEN4 |Immediately Load Enable Bit(S) + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the end point or center point of each period by setting CTRLD bit. + * | | |1 = PERIOD/CMPDAT will load to PBUF and CMPBUF immediately when software update PERIOD/CMPDAT. + * | | |Note: If IMMLDENn is Enabled, WINLDENn and CTRLDn will be invalid. + * |[21] |IMMLDEN5 |Immediately Load Enable Bit(S) + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = PERIOD will load to PBUF at the end point of each period + * | | |CMPDAT will load to CMPBUF at the end point or center point of each period by setting CTRLD bit. + * | | |1 = PERIOD/CMPDAT will load to PBUF and CMPBUF immediately when software update PERIOD/CMPDAT. + * | | |Note: If IMMLDENn is Enabled, WINLDENn and CTRLDn will be invalid. + * |[30] |DBGHALT |ICE Debug Mode Counter Halt (Write Protect) + * | | |If counter halt is enabled, BPWM all counters will keep current value until exit ICE debug mode. + * | | |0 = ICE debug mode counter halt Disabled. + * | | |1 = ICE debug mode counter halt Enabled. + * | | |Note: This bit is write protected. Refer to SYS_REGLCTL register. + * |[31] |DBGTRIOFF |ICE Debug Mode Acknowledge Disable (Write Protect) + * | | |0 = ICE debug mode acknowledgement effects BPWM output. + * | | |BPWM pin will be forced as tri-state while ICE debug mode acknowledged. + * | | |1 = ICE debug mode acknowledgement Disabled. + * | | |BPWM pin will keep output no matter ICE debug mode acknowledged or not. + * | | |Note: This bit is write protected. Refer to SYS_REGLCTL register. + * @var BPWM_T::CTL1 + * Offset: 0x04 BPWM Control Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |CNTTYPE0 |BPWM Counter Behavior Type 0 + * | | |Each bit n controls corresponding BPWM channel n. + * | | |00 = Up counter type (supports in capture mode). + * | | |01 = Down count type (supports in capture mode). + * | | |10 = Up-down counter type. + * | | |11 = Reserved. + * @var BPWM_T::CLKSRC + * Offset: 0x10 BPWM Clock Source Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |ECLKSRC0 |BPWM_CH01 External Clock Source Select + * | | |000 = BPWMx_CLK, x denotes 0 or 1. + * | | |001 = TIMER0 overflow. + * | | |010 = TIMER1 overflow. + * | | |011 = TIMER2 overflow. + * | | |100 = TIMER3 overflow. + * | | |Others = Reserved. + * @var BPWM_T::CLKPSC + * Offset: 0x14 BPWM Clock Prescale Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[11:0] |CLKPSC |BPWM Counter Clock Prescale + * | | |The clock of BPWM counter is decided by clock prescaler + * | | |Each BPWM pair share one BPWM counter clock prescaler + * | | |The clock of BPWM counter is divided by (CLKPSC+ 1) + * @var BPWM_T::CNTEN + * Offset: 0x20 BPWM Counter Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CNTEN0 |BPWM Counter 0 Enable Bit + * | | |0 = BPWM Counter and clock prescaler stop running. + * | | |1 = BPWM Counter and clock prescaler start running. + * @var BPWM_T::CNTCLR + * Offset: 0x24 BPWM Clear Counter Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CNTCLR0 |Clear BPWM Counter Control Bit 0 + * | | |It is automatically cleared by hardware. + * | | |0 = No effect. + * | | |1 = Clear 16-bit BPWM counter to 0000H. + * @var BPWM_T::PERIOD + * Offset: 0x30 BPWM Period Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |PERIOD |BPWM Period Register + * | | |Up-Count mode: In this mode, BPWM counter counts from 0 to PERIOD, and restarts from 0. + * | | |Down-Count mode: In this mode, BPWM counter counts from PERIOD to 0, and restarts from PERIOD. + * | | |BPWM period time = (PERIOD+1) * BPWM_CLK period. + * | | |Up-Down-Count mode: In this mode, BPWM counter counts from 0 to PERIOD, then decrements to 0 and repeats again. + * | | |BPWM period time = 2 * PERIOD * BPWM_CLK period. + * @var BPWM_T::CMPDAT[6] + * Offset: 0x50~0x64 BPWM Comparator Register 0~5 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |CMPDAT |BPWM Comparator Register + * | | |CMPDAT use to compare with CNTR to generate BPWM waveform, interrupt and trigger EADC. + * | | |In independent mode, CMPDAT0~5 denote as 6 independent BPWM_CH0~5 compared point. + * @var BPWM_T::CNT + * Offset: 0x90 BPWM Counter Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |CNT |BPWM Data Register (Read Only) + * | | |User can monitor CNTR to know the current value in 16-bit period counter. + * |[16] |DIRF |BPWM Direction Indicator Flag (Read Only) + * | | |0 = Counter is Down count. + * | | |1 = Counter is UP count. + * @var BPWM_T::WGCTL0 + * Offset: 0xB0 BPWM Generation Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |ZPCTL0 |BPWM Zero Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM zero point output Low. + * | | |10 = BPWM zero point output High. + * | | |11 = BPWM zero point output Toggle. + * | | |BPWM can control output level when BPWM counter count to zero. + * |[3:2] |ZPCTL1 |BPWM Zero Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM zero point output Low. + * | | |10 = BPWM zero point output High. + * | | |11 = BPWM zero point output Toggle. + * | | |BPWM can control output level when BPWM counter count to zero. + * |[5:4] |ZPCTL2 |BPWM Zero Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM zero point output Low. + * | | |10 = BPWM zero point output High. + * | | |11 = BPWM zero point output Toggle. + * | | |BPWM can control output level when BPWM counter count to zero. + * |[7:6] |ZPCTL3 |BPWM Zero Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM zero point output Low. + * | | |10 = BPWM zero point output High. + * | | |11 = BPWM zero point output Toggle. + * | | |BPWM can control output level when BPWM counter count to zero. + * |[9:8] |ZPCTL4 |BPWM Zero Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM zero point output Low. + * | | |10 = BPWM zero point output High. + * | | |11 = BPWM zero point output Toggle. + * | | |BPWM can control output level when BPWM counter count to zero. + * |[11:10] |ZPCTL5 |BPWM Zero Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM zero point output Low. + * | | |10 = BPWM zero point output High. + * | | |11 = BPWM zero point output Toggle. + * | | |BPWM can control output level when BPWM counter count to zero. + * |[17:16] |PRDPCTL0 |BPWM Period (Center) Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM period (center) point output Low. + * | | |10 = BPWM period (center) point output High. + * | | |11 = BPWM period (center) point output Toggle. + * | | |BPWM can control output level when BPWM counter count to (PERIOD+1). + * | | |Note: This bit is center point control when BPWM counter operating in up-down counter type. + * |[19:18] |PRDPCTL1 |BPWM Period (Center) Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM period (center) point output Low. + * | | |10 = BPWM period (center) point output High. + * | | |11 = BPWM period (center) point output Toggle. + * | | |BPWM can control output level when BPWM counter count to (PERIOD+1). + * | | |Note: This bit is center point control when BPWM counter operating in up-down counter type. + * |[21:20] |PRDPCTL2 |BPWM Period (Center) Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM period (center) point output Low. + * | | |10 = BPWM period (center) point output High. + * | | |11 = BPWM period (center) point output Toggle. + * | | |BPWM can control output level when BPWM counter count to (PERIOD+1). + * | | |Note: This bit is center point control when BPWM counter operating in up-down counter type. + * |[23:22] |PRDPCTL3 |BPWM Period (Center) Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM period (center) point output Low. + * | | |10 = BPWM period (center) point output High. + * | | |11 = BPWM period (center) point output Toggle. + * | | |BPWM can control output level when BPWM counter count to (PERIOD+1). + * | | |Note: This bit is center point control when BPWM counter operating in up-down counter type. + * |[25:24] |PRDPCTL4 |BPWM Period (Center) Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM period (center) point output Low. + * | | |10 = BPWM period (center) point output High. + * | | |11 = BPWM period (center) point output Toggle. + * | | |BPWM can control output level when BPWM counter count to (PERIOD+1). + * | | |Note: This bit is center point control when BPWM counter operating in up-down counter type. + * |[27:26] |PRDPCTL5 |BPWM Period (Center) Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM period (center) point output Low. + * | | |10 = BPWM period (center) point output High. + * | | |11 = BPWM period (center) point output Toggle. + * | | |BPWM can control output level when BPWM counter count to (PERIOD+1). + * | | |Note: This bit is center point control when BPWM counter operating in up-down counter type. + * @var BPWM_T::WGCTL1 + * Offset: 0xB4 BPWM Generation Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |CMPUCTL0 |BPWM Compare Up Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare up point output Low. + * | | |10 = BPWM compare up point output High. + * | | |11 = BPWM compare up point output Toggle. + * | | |BPWM can control output level when BPWM counter up count to CMPDAT. + * |[3:2] |CMPUCTL1 |BPWM Compare Up Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare up point output Low. + * | | |10 = BPWM compare up point output High. + * | | |11 = BPWM compare up point output Toggle. + * | | |BPWM can control output level when BPWM counter up count to CMPDAT. + * |[5:4] |CMPUCTL2 |BPWM Compare Up Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare up point output Low. + * | | |10 = BPWM compare up point output High. + * | | |11 = BPWM compare up point output Toggle. + * | | |BPWM can control output level when BPWM counter up count to CMPDAT. + * |[7:6] |CMPUCTL3 |BPWM Compare Up Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare up point output Low. + * | | |10 = BPWM compare up point output High. + * | | |11 = BPWM compare up point output Toggle. + * | | |BPWM can control output level when BPWM counter up count to CMPDAT. + * |[9:8] |CMPUCTL4 |BPWM Compare Up Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare up point output Low. + * | | |10 = BPWM compare up point output High. + * | | |11 = BPWM compare up point output Toggle. + * | | |BPWM can control output level when BPWM counter up count to CMPDAT. + * |[11:10] |CMPUCTL5 |BPWM Compare Up Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare up point output Low. + * | | |10 = BPWM compare up point output High. + * | | |11 = BPWM compare up point output Toggle. + * | | |BPWM can control output level when BPWM counter up count to CMPDAT. + * |[17:16] |CMPDCTL0 |BPWM Compare Down Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare down point output Low. + * | | |10 = BPWM compare down point output High. + * | | |11 = BPWM compare down point output Toggle. + * | | |BPWM can control output level when BPWM counter down count to CMPDAT. + * |[19:18] |CMPDCTL1 |BPWM Compare Down Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare down point output Low. + * | | |10 = BPWM compare down point output High. + * | | |11 = BPWM compare down point output Toggle. + * | | |BPWM can control output level when BPWM counter down count to CMPDAT. + * |[21:20] |CMPDCTL2 |BPWM Compare Down Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare down point output Low. + * | | |10 = BPWM compare down point output High. + * | | |11 = BPWM compare down point output Toggle. + * | | |BPWM can control output level when BPWM counter down count to CMPDAT. + * |[23:22] |CMPDCTL3 |BPWM Compare Down Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare down point output Low. + * | | |10 = BPWM compare down point output High. + * | | |11 = BPWM compare down point output Toggle. + * | | |BPWM can control output level when BPWM counter down count to CMPDAT. + * |[25:24] |CMPDCTL4 |BPWM Compare Down Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare down point output Low. + * | | |10 = BPWM compare down point output High. + * | | |11 = BPWM compare down point output Toggle. + * | | |BPWM can control output level when BPWM counter down count to CMPDAT. + * |[27:26] |CMPDCTL5 |BPWM Compare Down Point Control + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |00 = Do nothing. + * | | |01 = BPWM compare down point output Low. + * | | |10 = BPWM compare down point output High. + * | | |11 = BPWM compare down point output Toggle. + * | | |BPWM can control output level when BPWM counter down count to CMPDAT. + * @var BPWM_T::MSKEN + * Offset: 0xB8 BPWM Mask Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |MSKEN0 |BPWM Mask Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |The BPWM output signal will be masked when this bit is enabled + * | | |The corresponding BPWM channel n will output MSKDATn (BPWM_MSK[5:0]) data. + * | | |0 = BPWM output signal is non-masked. + * | | |1 = BPWM output signal is masked and output MSKDATn data. + * |[1] |MSKEN1 |BPWM Mask Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |The BPWM output signal will be masked when this bit is enabled + * | | |The corresponding BPWM channel n will output MSKDATn (BPWM_MSK[5:0]) data. + * | | |0 = BPWM output signal is non-masked. + * | | |1 = BPWM output signal is masked and output MSKDATn data. + * |[2] |MSKEN2 |BPWM Mask Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |The BPWM output signal will be masked when this bit is enabled + * | | |The corresponding BPWM channel n will output MSKDATn (BPWM_MSK[5:0]) data. + * | | |0 = BPWM output signal is non-masked. + * | | |1 = BPWM output signal is masked and output MSKDATn data. + * |[3] |MSKEN3 |BPWM Mask Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |The BPWM output signal will be masked when this bit is enabled + * | | |The corresponding BPWM channel n will output MSKDATn (BPWM_MSK[5:0]) data. + * | | |0 = BPWM output signal is non-masked. + * | | |1 = BPWM output signal is masked and output MSKDATn data. + * |[4] |MSKEN4 |BPWM Mask Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |The BPWM output signal will be masked when this bit is enabled + * | | |The corresponding BPWM channel n will output MSKDATn (BPWM_MSK[5:0]) data. + * | | |0 = BPWM output signal is non-masked. + * | | |1 = BPWM output signal is masked and output MSKDATn data. + * |[5] |MSKEN5 |BPWM Mask Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |The BPWM output signal will be masked when this bit is enabled + * | | |The corresponding BPWM channel n will output MSKDATn (BPWM_MSK[5:0]) data. + * | | |0 = BPWM output signal is non-masked. + * | | |1 = BPWM output signal is masked and output MSKDATn data. + * @var BPWM_T::MSK + * Offset: 0xBC BPWM Mask Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |MSKDAT0 |BPWM Mask Data Bit + * | | |This data bit control the state of BPWMn output pin, if corresponding mask function is enabled + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Output logic low to BPWMn. + * | | |1 = Output logic high to BPWMn. + * |[1] |MSKDAT1 |BPWM Mask Data Bit + * | | |This data bit control the state of BPWMn output pin, if corresponding mask function is enabled + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Output logic low to BPWMn. + * | | |1 = Output logic high to BPWMn. + * |[2] |MSKDAT2 |BPWM Mask Data Bit + * | | |This data bit control the state of BPWMn output pin, if corresponding mask function is enabled + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Output logic low to BPWMn. + * | | |1 = Output logic high to BPWMn. + * |[3] |MSKDAT3 |BPWM Mask Data Bit + * | | |This data bit control the state of BPWMn output pin, if corresponding mask function is enabled + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Output logic low to BPWMn. + * | | |1 = Output logic high to BPWMn. + * |[4] |MSKDAT4 |BPWM Mask Data Bit + * | | |This data bit control the state of BPWMn output pin, if corresponding mask function is enabled + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Output logic low to BPWMn. + * | | |1 = Output logic high to BPWMn. + * |[5] |MSKDAT5 |BPWM Mask Data Bit + * | | |This data bit control the state of BPWMn output pin, if corresponding mask function is enabled + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Output logic low to BPWMn. + * | | |1 = Output logic high to BPWMn. + * @var BPWM_T::POLCTL + * Offset: 0xD4 BPWM Pin Polar Inverse Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |PINV0 |BPWM PIN Polar Inverse Control + * | | |The register controls polarity state of BPWM output + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM output polar inverse Disabled. + * | | |1 = BPWM output polar inverse Enabled. + * |[1] |PINV1 |BPWM PIN Polar Inverse Control + * | | |The register controls polarity state of BPWM output + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM output polar inverse Disabled. + * | | |1 = BPWM output polar inverse Enabled. + * |[2] |PINV2 |BPWM PIN Polar Inverse Control + * | | |The register controls polarity state of BPWM output + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM output polar inverse Disabled. + * | | |1 = BPWM output polar inverse Enabled. + * |[3] |PINV3 |BPWM PIN Polar Inverse Control + * | | |The register controls polarity state of BPWM output + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM output polar inverse Disabled. + * | | |1 = BPWM output polar inverse Enabled. + * |[4] |PINV4 |BPWM PIN Polar Inverse Control + * | | |The register controls polarity state of BPWM output + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM output polar inverse Disabled. + * | | |1 = BPWM output polar inverse Enabled. + * |[5] |PINV5 |BPWM PIN Polar Inverse Control + * | | |The register controls polarity state of BPWM output + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM output polar inverse Disabled. + * | | |1 = BPWM output polar inverse Enabled. + * @var BPWM_T::POEN + * Offset: 0xD8 BPWM Output Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |POEN0 |BPWM Pin Output Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM pin at tri-state. + * | | |1 = BPWM pin in output mode. + * |[1] |POEN1 |BPWM Pin Output Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM pin at tri-state. + * | | |1 = BPWM pin in output mode. + * |[2] |POEN2 |BPWM Pin Output Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM pin at tri-state. + * | | |1 = BPWM pin in output mode. + * |[3] |POEN3 |BPWM Pin Output Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM pin at tri-state. + * | | |1 = BPWM pin in output mode. + * |[4] |POEN4 |BPWM Pin Output Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM pin at tri-state. + * | | |1 = BPWM pin in output mode. + * |[5] |POEN5 |BPWM Pin Output Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM pin at tri-state. + * | | |1 = BPWM pin in output mode. + * @var BPWM_T::INTEN + * Offset: 0xE0 BPWM Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ZIEN0 |BPWM Zero Point Interrupt 0 Enable Bit + * | | |0 = Zero point interrupt Disabled. + * | | |1 = Zero point interrupt Enabled. + * |[8] |PIEN0 |BPWM Period Point Interrupt 0 Enable Bit + * | | |0 = Period point interrupt Disabled. + * | | |1 = Period point interrupt Enabled. + * | | |Note: When up-down counter type period point means center point. + * |[16] |CMPUIEN0 |BPWM Compare Up Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare up count interrupt Disabled. + * | | |1 = Compare up count interrupt Enabled. + * |[17] |CMPUIEN1 |BPWM Compare Up Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare up count interrupt Disabled. + * | | |1 = Compare up count interrupt Enabled. + * |[18] |CMPUIEN2 |BPWM Compare Up Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare up count interrupt Disabled. + * | | |1 = Compare up count interrupt Enabled. + * |[19] |CMPUIEN3 |BPWM Compare Up Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare up count interrupt Disabled. + * | | |1 = Compare up count interrupt Enabled. + * |[20] |CMPUIEN4 |BPWM Compare Up Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare up count interrupt Disabled. + * | | |1 = Compare up count interrupt Enabled. + * |[21] |CMPUIEN5 |BPWM Compare Up Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare up count interrupt Disabled. + * | | |1 = Compare up count interrupt Enabled. + * |[24] |CMPDIEN0 |BPWM Compare Down Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare down count interrupt Disabled. + * | | |1 = Compare down count interrupt Enabled. + * |[25] |CMPDIEN1 |BPWM Compare Down Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare down count interrupt Disabled. + * | | |1 = Compare down count interrupt Enabled. + * |[26] |CMPDIEN2 |BPWM Compare Down Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare down count interrupt Disabled. + * | | |1 = Compare down count interrupt Enabled. + * |[27] |CMPDIEN3 |BPWM Compare Down Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare down count interrupt Disabled. + * | | |1 = Compare down count interrupt Enabled. + * |[28] |CMPDIEN4 |BPWM Compare Down Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare down count interrupt Disabled. + * | | |1 = Compare down count interrupt Enabled. + * |[29] |CMPDIEN5 |BPWM Compare Down Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Compare down count interrupt Disabled. + * | | |1 = Compare down count interrupt Enabled. + * @var BPWM_T::INTSTS + * Offset: 0xE8 BPWM Interrupt Flag Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ZIF0 |BPWM Zero Point Interrupt Flag 0 + * | | |This bit is set by hardware when BPWM_CH0 counter reaches 0, software can write 1 to clear this bit to 0. + * |[8] |PIF0 |BPWM Period Point Interrupt Flag 0 + * | | |This bit is set by hardware when BPWM_CH0 counter reaches BPWM_PERIOD0, software can write 1 to clear this bit to 0. + * |[16] |CMPUIF0 |BPWM Compare Up Count Interrupt Flag + * | | |Flag is set by hardware when BPWM counter up count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in up counter type selection. + * |[17] |CMPUIF1 |BPWM Compare Up Count Interrupt Flag + * | | |Flag is set by hardware when BPWM counter up count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in up counter type selection. + * |[18] |CMPUIF2 |BPWM Compare Up Count Interrupt Flag + * | | |Flag is set by hardware when BPWM counter up count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in up counter type selection. + * |[19] |CMPUIF3 |BPWM Compare Up Count Interrupt Flag + * | | |Flag is set by hardware when BPWM counter up count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in up counter type selection. + * |[20] |CMPUIF4 |BPWM Compare Up Count Interrupt Flag + * | | |Flag is set by hardware when BPWM counter up count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in up counter type selection. + * |[21] |CMPUIF5 |BPWM Compare Up Count Interrupt Flag + * | | |Flag is set by hardware when BPWM counter up count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in up counter type selection. + * |[24] |CMPDIF0 |BPWM Compare Down Count Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Flag is set by hardware when BPWM counter down count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in down counter type selection. + * |[25] |CMPDIF1 |BPWM Compare Down Count Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Flag is set by hardware when BPWM counter down count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in down counter type selection. + * |[26] |CMPDIF2 |BPWM Compare Down Count Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Flag is set by hardware when BPWM counter down count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in down counter type selection. + * |[27] |CMPDIF3 |BPWM Compare Down Count Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Flag is set by hardware when BPWM counter down count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in down counter type selection. + * |[28] |CMPDIF4 |BPWM Compare Down Count Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Flag is set by hardware when BPWM counter down count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in down counter type selection. + * |[29] |CMPDIF5 |BPWM Compare Down Count Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Flag is set by hardware when BPWM counter down count and reaches BPWM_CMPDATn, software can clear this bit by writing 1 to it. + * | | |Note: If CMPDAT equal to PERIOD, this flag is not working in down counter type selection. + * @var BPWM_T::EADCTS0 + * Offset: 0xF8 BPWM Trigger EADC Source Select Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |TRGSEL0 |BPWM_CH0 Trigger EADC Source Select + * | | |0000 = BPWM_CH0 zero point. + * | | |0001 = BPWM_CH0 period point. + * | | |0010 = BPWM_CH0 zero or period point. + * | | |0011 = BPWM_CH0 up-count CMPDAT point. + * | | |0100 = BPWM_CH0 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = BPWM_CH1 up-count CMPDAT point. + * | | |1001 = BPWM_CH1 down-count CMPDAT point. + * | | |Others reserved + * |[7] |TRGEN0 |BPWM_CH0 Trigger EADC Enable Bit + * |[11:8] |TRGSEL1 |BPWM_CH1 Trigger EADC Source Select + * | | |0000 = BPWM_CH0 zero point. + * | | |0001 = BPWM_CH0 period point. + * | | |0010 = BPWM_CH0 zero or period point. + * | | |0011 = BPWM_CH0 up-count CMPDAT point. + * | | |0100 = BPWM_CH0 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = BPWM_CH1 up-count CMPDAT point. + * | | |1001 = BPWM_CH1 down-count CMPDAT point. + * | | |Others reserved + * |[15] |TRGEN1 |BPWM_CH1 Trigger EADC Enable Bit + * |[19:16] |TRGSEL2 |BPWM_CH2 Trigger EADC Source Select + * | | |0000 = BPWM_CH2 zero point. + * | | |0001 = BPWM_CH2 period point. + * | | |0010 = BPWM_CH2 zero or period point. + * | | |0011 = BPWM_CH2 up-count CMPDAT point. + * | | |0100 = BPWM_CH2 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = BPWM_CH3 up-count CMPDAT point. + * | | |1001 = BPWM_CH3 down-count CMPDAT point. + * | | |Others reserved + * |[23] |TRGEN2 |BPWM_CH2 Trigger EADC Enable Bit + * |[27:24] |TRGSEL3 |BPWM_CH3 Trigger EADC Source Select + * | | |0000 = BPWM_CH2 zero point. + * | | |0001 = BPWM_CH2 period point. + * | | |0010 = BPWM_CH2 zero or period point. + * | | |0011 = BPWM_CH2 up-count CMPDAT point. + * | | |0100 = BPWM_CH2 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = BPWM_CH3 up-count CMPDAT point. + * | | |1001 = BPWM_CH3 down-count CMPDAT point. + * | | |Others reserved. + * |[31] |TRGEN3 |BPWM_CH3 Trigger EADC Enable Bit + * @var BPWM_T::EADCTS1 + * Offset: 0xFC BPWM Trigger EADC Source Select Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |TRGSEL4 |BPWM_CH4 Trigger EADC Source Select + * | | |0000 = BPWM_CH4 zero point. + * | | |0001 = BPWM_CH4 period point. + * | | |0010 = BPWM_CH4 zero or period point. + * | | |0011 = BPWM_CH4 up-count CMPDAT point. + * | | |0100 = BPWM_CH4 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = BPWM_CH5 up-count CMPDAT point. + * | | |1001 = BPWM_CH5 down-count CMPDAT point. + * | | |Others reserved + * |[7] |TRGEN4 |BPWM_CH4 Trigger EADC Enable Bit + * |[11:8] |TRGSEL5 |BPWM_CH5 Trigger EADC Source Select + * | | |0000 = BPWM_CH4 zero point. + * | | |0001 = BPWM_CH4 period point. + * | | |0010 = BPWM_CH4 zero or period point. + * | | |0011 = BPWM_CH4 up-count CMPDAT point. + * | | |0100 = BPWM_CH4 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = BPWM_CH5 up-count CMPDAT point. + * | | |1001 = BPWM_CH5 down-count CMPDAT point. + * | | |Others reserved + * |[15] |TRGEN5 |BPWM_CH5 Trigger EADC Enable Bit + * @var BPWM_T::SSCTL + * Offset: 0x110 BPWM Synchronous Start Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SSEN0 |BPWM Synchronous Start Function 0 Enable Bit + * | | |When synchronous start function is enabled, the BPWM_CH0 counter enable bit (CNTEN0) can be enabled by writing BPWM synchronous start trigger bit (CNTSEN). + * | | |0 = BPWM synchronous start function Disabled. + * | | |1 = BPWM synchronous start function Enabled. + * |[9:8] |SSRC |BPWM Synchronous Start Source Select + * | | |00 = Synchronous start source come from PWM0. + * | | |01 = Synchronous start source come from PWM1. + * | | |10 = Synchronous start source come from BPWM0. + * | | |11 = Synchronous start source come from BPWM1. + * @var BPWM_T::SSTRG + * Offset: 0x114 BPWM Synchronous Start Trigger Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CNTSEN |BPWM Counter Synchronous Start Enable Bit(Write Only) + * | | |BPMW counter synchronous enable function is used to make PWM or BPWM channels start counting at the same time. + * | | |Writing this bit to 1 will also set the counter enable bit if correlated BPWM channel counter synchronous start function is enabled. + * @var BPWM_T::STATUS + * Offset: 0x120 BPWM Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CNTMAX0 |Time-base Counter 0 Equal to 0xFFFF Latched Status + * | | |0 = The time-base counter never reached its maximum value 0xFFFF. + * | | |1 = The time-base counter reached its maximum value. Software can write 1 to clear this bit. + * |[16] |EADCTRG0 |EADC Start of Conversion Status + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No EADC start of conversion trigger event has occurred. + * | | |1 = An EADC start of conversion trigger event has occurred. Software can write 1 to clear this bit. + * |[17] |EADCTRG1 |EADC Start of Conversion Status + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No EADC start of conversion trigger event has occurred. + * | | |1 = An EADC start of conversion trigger event has occurred. Software can write 1 to clear this bit. + * |[18] |EADCTRG2 |EADC Start of Conversion Status + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No EADC start of conversion trigger event has occurred. + * | | |1 = An EADC start of conversion trigger event has occurred. Software can write 1 to clear this bit. + * |[19] |EADCTRG3 |EADC Start of Conversion Status + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No EADC start of conversion trigger event has occurred. + * | | |1 = An EADC start of conversion trigger event has occurred. Software can write 1 to clear this bit. + * |[20] |EADCTRG4 |EADC Start of Conversion Status + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No EADC start of conversion trigger event has occurred. + * | | |1 = An EADC start of conversion trigger event has occurred. Software can write 1 to clear this bit. + * |[21] |EADCTRG5 |EADC Start of Conversion Status + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No EADC start of conversion trigger event has occurred. + * | | |1 = An EADC start of conversion trigger event has occurred. Software can write 1 to clear this bit. + * @var BPWM_T::CAPINEN + * Offset: 0x200 BPWM Capture Input Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CAPINEN0 |Capture Input Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM Channel capture input path Disabled + * | | |The input of BPWM channel capture function is always regarded as 0. + * | | |1 = BPWM Channel capture input path Enabled + * | | |The input of BPWM channel capture function comes from correlative multifunction pin. + * |[1] |CAPINEN1 |Capture Input Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM Channel capture input path Disabled + * | | |The input of BPWM channel capture function is always regarded as 0. + * | | |1 = BPWM Channel capture input path Enabled + * | | |The input of BPWM channel capture function comes from correlative multifunction pin. + * |[2] |CAPINEN2 |Capture Input Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM Channel capture input path Disabled + * | | |The input of BPWM channel capture function is always regarded as 0. + * | | |1 = BPWM Channel capture input path Enabled + * | | |The input of BPWM channel capture function comes from correlative multifunction pin. + * |[3] |CAPINEN3 |Capture Input Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM Channel capture input path Disabled + * | | |The input of BPWM channel capture function is always regarded as 0. + * | | |1 = BPWM Channel capture input path Enabled + * | | |The input of BPWM channel capture function comes from correlative multifunction pin. + * |[4] |CAPINEN4 |Capture Input Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM Channel capture input path Disabled + * | | |The input of BPWM channel capture function is always regarded as 0. + * | | |1 = BPWM Channel capture input path Enabled + * | | |The input of BPWM channel capture function comes from correlative multifunction pin. + * |[5] |CAPINEN5 |Capture Input Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = BPWM Channel capture input path Disabled + * | | |The input of BPWM channel capture function is always regarded as 0. + * | | |1 = BPWM Channel capture input path Enabled + * | | |The input of BPWM channel capture function comes from correlative multifunction pin. + * @var BPWM_T::CAPCTL + * Offset: 0x204 BPWM Capture Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CAPEN0 |Capture Function Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture function Disabled. RCAPDAT/FCAPDAT register will not be updated. + * | | |1 = Capture function Enabled + * | | |Capture latched the BPWM counter value when detected rising or falling edge of input signal and saved to RCAPDAT (Rising latch) and FCAPDAT (Falling latch). + * |[1] |CAPEN1 |Capture Function Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture function Disabled. RCAPDAT/FCAPDAT register will not be updated. + * | | |1 = Capture function Enabled + * | | |Capture latched the BPWM counter value when detected rising or falling edge of input signal and saved to RCAPDAT (Rising latch) and FCAPDAT (Falling latch). + * |[2] |CAPEN2 |Capture Function Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture function Disabled. RCAPDAT/FCAPDAT register will not be updated. + * | | |1 = Capture function Enabled + * | | |Capture latched the BPWM counter value when detected rising or falling edge of input signal and saved to RCAPDAT (Rising latch) and FCAPDAT (Falling latch). + * |[3] |CAPEN3 |Capture Function Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture function Disabled. RCAPDAT/FCAPDAT register will not be updated. + * | | |1 = Capture function Enabled + * | | |Capture latched the BPWM counter value when detected rising or falling edge of input signal and saved to RCAPDAT (Rising latch) and FCAPDAT (Falling latch). + * |[4] |CAPEN4 |Capture Function Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture function Disabled. RCAPDAT/FCAPDAT register will not be updated. + * | | |1 = Capture function Enabled + * | | |Capture latched the BPWM counter value when detected rising or falling edge of input signal and saved to RCAPDAT (Rising latch) and FCAPDAT (Falling latch). + * |[5] |CAPEN5 |Capture Function Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture function Disabled. RCAPDAT/FCAPDAT register will not be updated. + * | | |1 = Capture function Enabled + * | | |Capture latched the BPWM counter value when detected rising or falling edge of input signal and saved to RCAPDAT (Rising latch) and FCAPDAT (Falling latch). + * |[8] |CAPINV0 |Capture Inverter Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture source inverter Disabled. + * | | |1 = Capture source inverter Enabled. Reverse the input signal from GPIO. + * |[9] |CAPINV1 |Capture Inverter Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture source inverter Disabled. + * | | |1 = Capture source inverter Enabled. Reverse the input signal from GPIO. + * |[10] |CAPINV2 |Capture Inverter Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture source inverter Disabled. + * | | |1 = Capture source inverter Enabled. Reverse the input signal from GPIO. + * |[11] |CAPINV3 |Capture Inverter Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture source inverter Disabled. + * | | |1 = Capture source inverter Enabled. Reverse the input signal from GPIO. + * |[12] |CAPINV4 |Capture Inverter Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture source inverter Disabled. + * | | |1 = Capture source inverter Enabled. Reverse the input signal from GPIO. + * |[13] |CAPINV5 |Capture Inverter Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture source inverter Disabled. + * | | |1 = Capture source inverter Enabled. Reverse the input signal from GPIO. + * |[16] |RCRLDEN0 |Rising Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Rising capture reload counter Disabled. + * | | |1 = Rising capture reload counter Enabled. + * |[17] |RCRLDEN1 |Rising Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Rising capture reload counter Disabled. + * | | |1 = Rising capture reload counter Enabled. + * |[18] |RCRLDEN2 |Rising Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Rising capture reload counter Disabled. + * | | |1 = Rising capture reload counter Enabled. + * |[19] |RCRLDEN3 |Rising Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Rising capture reload counter Disabled. + * | | |1 = Rising capture reload counter Enabled. + * |[20] |RCRLDEN4 |Rising Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Rising capture reload counter Disabled. + * | | |1 = Rising capture reload counter Enabled. + * |[21] |RCRLDEN5 |Rising Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Rising capture reload counter Disabled. + * | | |1 = Rising capture reload counter Enabled. + * |[24] |FCRLDEN0 |Falling Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Falling capture reload counter Disabled. + * | | |1 = Falling capture reload counter Enabled. + * |[25] |FCRLDEN1 |Falling Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Falling capture reload counter Disabled. + * | | |1 = Falling capture reload counter Enabled. + * |[26] |FCRLDEN2 |Falling Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Falling capture reload counter Disabled. + * | | |1 = Falling capture reload counter Enabled. + * |[27] |FCRLDEN3 |Falling Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Falling capture reload counter Disabled. + * | | |1 = Falling capture reload counter Enabled. + * |[28] |FCRLDEN4 |Falling Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Falling capture reload counter Disabled. + * | | |1 = Falling capture reload counter Enabled. + * |[29] |FCRLDEN5 |Falling Capture Reload Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Falling capture reload counter Disabled. + * | | |1 = Falling capture reload counter Enabled. + * @var BPWM_T::CAPSTS + * Offset: 0x208 BPWM Capture Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CRIFOV0 |Capture Rising Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if rising latch happened when the corresponding CAPRIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPRIF. + * |[1] |CRIFOV1 |Capture Rising Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if rising latch happened when the corresponding CAPRIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPRIF. + * |[2] |CRIFOV2 |Capture Rising Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if rising latch happened when the corresponding CAPRIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPRIF. + * |[3] |CRIFOV3 |Capture Rising Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if rising latch happened when the corresponding CAPRIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPRIF. + * |[4] |CRIFOV4 |Capture Rising Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if rising latch happened when the corresponding CAPRIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPRIF. + * |[5] |CRIFOV5 |Capture Rising Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if rising latch happened when the corresponding CAPRIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPRIF. + * |[8] |CFIFOV0 |Capture Falling Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if falling latch happened when the corresponding CAPFIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPFIF. + * |[9] |CFIFOV1 |Capture Falling Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if falling latch happened when the corresponding CAPFIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPFIF. + * |[10] |CFIFOV2 |Capture Falling Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if falling latch happened when the corresponding CAPFIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPFIF. + * |[11] |CFIFOV3 |Capture Falling Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if falling latch happened when the corresponding CAPFIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPFIF. + * |[12] |CFIFOV4 |Capture Falling Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if falling latch happened when the corresponding CAPFIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPFIF. + * |[13] |CFIFOV5 |Capture Falling Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if falling latch happened when the corresponding CAPFIF is 1 + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CAPFIF. + * @var BPWM_T::CAPIEN + * Offset: 0x250 BPWM Capture Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |CAPRIENn |BPWM Capture Rising Latch Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture rising edge latch interrupt Disabled. + * | | |1 = Capture rising edge latch interrupt Enabled. + * |[13:8] |CAPFIENn |BPWM Capture Falling Latch Interrupt Enable Bits + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = Capture falling edge latch interrupt Disabled. + * | | |1 = Capture falling edge latch interrupt Enabled. + * @var BPWM_T::CAPIF + * Offset: 0x254 BPWM Capture Interrupt Flag Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CAPRIF0 |BPWM Capture Rising Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture rising latch condition happened. + * | | |1 = Capture rising latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * |[1] |CAPRIF1 |BPWM Capture Rising Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture rising latch condition happened. + * | | |1 = Capture rising latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * |[2] |CAPRIF2 |BPWM Capture Rising Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture rising latch condition happened. + * | | |1 = Capture rising latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * |[3] |CAPRIF3 |BPWM Capture Rising Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture rising latch condition happened. + * | | |1 = Capture rising latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * |[4] |CAPRIF4 |BPWM Capture Rising Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture rising latch condition happened. + * | | |1 = Capture rising latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * |[5] |CAPRIF5 |BPWM Capture Rising Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture rising latch condition happened. + * | | |1 = Capture rising latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * |[8] |CAPFIF0 |BPWM Capture Falling Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture falling latch condition happened. + * | | |1 = Capture falling latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * |[9] |CAPFIF1 |BPWM Capture Falling Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture falling latch condition happened. + * | | |1 = Capture falling latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * |[10] |CAPFIF2 |BPWM Capture Falling Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture falling latch condition happened. + * | | |1 = Capture falling latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * |[11] |CAPFIF3 |BPWM Capture Falling Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture falling latch condition happened. + * | | |1 = Capture falling latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * |[12] |CAPFIF4 |BPWM Capture Falling Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture falling latch condition happened. + * | | |1 = Capture falling latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * |[13] |CAPFIF5 |BPWM Capture Falling Latch Interrupt Flag + * | | |Each bit n controls the corresponding BPWM channel n. + * | | |0 = No capture falling latch condition happened. + * | | |1 = Capture falling latch condition happened, this flag will be set to high. + * | | |Note: This bit is cleared by writing 1 to it. + * @var BPWM_T::PBUF + * Offset: 0x304 BPWM PERIOD Buffer + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |PBUF |BPWM Period Buffer (Read Only) + * | | |Used as PERIOD active register. + * @var BPWM_T::CMPBUF[6] + * Offset: 0x31C~0x330 BPWM CMPDAT 0~5 Buffer + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |CMPBUF |BPWM Comparator Buffer (Read Only) + * | | |Used as CMP active register. + */ + __IO uint32_t CTL0; /*!< [0x0000] BPWM Control Register 0 */ + __IO uint32_t CTL1; /*!< [0x0004] BPWM Control Register 1 */ + __I uint32_t RESERVE0[2]; + __IO uint32_t CLKSRC; /*!< [0x0010] BPWM Clock Source Register */ + __IO uint32_t CLKPSC; /*!< [0x0014] BPWM Clock Prescale Register */ + __I uint32_t RESERVE1[2]; + __IO uint32_t CNTEN; /*!< [0x0020] BPWM Counter Enable Register */ + __IO uint32_t CNTCLR; /*!< [0x0024] BPWM Clear Counter Register */ + __I uint32_t RESERVE2[2]; + __IO uint32_t PERIOD; /*!< [0x0030] BPWM Period Register */ + __I uint32_t RESERVE3[7]; + __IO uint32_t CMPDAT[6]; /*!< [0x0050 ~ 0x0064] BPWM Comparator Register 0 ~ 6 */ + __I uint32_t RESERVE4[10]; + __I uint32_t CNT; /*!< [0x0090] BPWM Counter Register */ + __I uint32_t RESERVE5[7]; + __IO uint32_t WGCTL0; /*!< [0x00b0] BPWM Generation Register 0 */ + __IO uint32_t WGCTL1; /*!< [0x00b4] BPWM Generation Register 1 */ + __IO uint32_t MSKEN; /*!< [0x00b8] BPWM Mask Enable Register */ + __IO uint32_t MSK; /*!< [0x00bc] BPWM Mask Data Register */ + __I uint32_t RESERVE6[5]; + __IO uint32_t POLCTL; /*!< [0x00d4] BPWM Pin Polar Inverse Register */ + __IO uint32_t POEN; /*!< [0x00d8] BPWM Output Enable Register */ + __I uint32_t RESERVE7[1]; + __IO uint32_t INTEN; /*!< [0x00e0] BPWM Interrupt Enable Register */ + __I uint32_t RESERVE8[1]; + __IO uint32_t INTSTS; /*!< [0x00e8] BPWM Interrupt Flag Register */ + __I uint32_t RESERVE9[3]; + __IO uint32_t EADCTS0; /*!< [0x00f8] BPWM Trigger EADC Source Select Register 0 */ + __IO uint32_t EADCTS1; /*!< [0x00fc] BPWM Trigger EADC Source Select Register 1 */ + __I uint32_t RESERVE10[4]; + __IO uint32_t SSCTL; /*!< [0x0110] BPWM Synchronous Start Control Register */ + __O uint32_t SSTRG; /*!< [0x0114] BPWM Synchronous Start Trigger Register */ + __I uint32_t RESERVE11[2]; + __IO uint32_t STATUS; /*!< [0x0120] BPWM Status Register */ + __I uint32_t RESERVE12[55]; + __IO uint32_t CAPINEN; /*!< [0x0200] BPWM Capture Input Enable Register */ + __IO uint32_t CAPCTL; /*!< [0x0204] BPWM Capture Control Register */ + __I uint32_t CAPSTS; /*!< [0x0208] BPWM Capture Status Register */ + BCAPDAT_T CAPDAT[6]; /*!< [0x020C ~ 0x0238] BPWM Rising and Falling Capture Data Register 0~5 */ + __I uint32_t RESERVE13[5]; + __IO uint32_t CAPIEN; /*!< [0x0250] BPWM Capture Interrupt Enable Register */ + __IO uint32_t CAPIF; /*!< [0x0254] BPWM Capture Interrupt Flag Register */ + __I uint32_t RESERVE14[43]; + __I uint32_t PBUF; /*!< [0x0304] BPWM PERIOD Buffer */ + __I uint32_t RESERVE15[5]; + __I uint32_t CMPBUF[6]; /*!< [0x031c ~ 0x0330] BPWM CMPDAT 0 ~ 5 Buffer */ + +} BPWM_T; + +/** + @addtogroup BPWM_CONST BPWM Bit Field Definition + Constant Definitions for BPWM Controller +@{ */ + +#define BPWM_CTL0_CTRLD0_Pos (0) /*!< BPWM_T::CTL0: CTRLD0 Position */ +#define BPWM_CTL0_CTRLD0_Msk (0x1ul << BPWM_CTL0_CTRLD0_Pos) /*!< BPWM_T::CTL0: CTRLD0 Mask */ + +#define BPWM_CTL0_CTRLD1_Pos (1) /*!< BPWM_T::CTL0: CTRLD1 Position */ +#define BPWM_CTL0_CTRLD1_Msk (0x1ul << BPWM_CTL0_CTRLD1_Pos) /*!< BPWM_T::CTL0: CTRLD1 Mask */ + +#define BPWM_CTL0_CTRLD2_Pos (2) /*!< BPWM_T::CTL0: CTRLD2 Position */ +#define BPWM_CTL0_CTRLD2_Msk (0x1ul << BPWM_CTL0_CTRLD2_Pos) /*!< BPWM_T::CTL0: CTRLD2 Mask */ + +#define BPWM_CTL0_CTRLD3_Pos (3) /*!< BPWM_T::CTL0: CTRLD3 Position */ +#define BPWM_CTL0_CTRLD3_Msk (0x1ul << BPWM_CTL0_CTRLD3_Pos) /*!< BPWM_T::CTL0: CTRLD3 Mask */ + +#define BPWM_CTL0_CTRLD4_Pos (4) /*!< BPWM_T::CTL0: CTRLD4 Position */ +#define BPWM_CTL0_CTRLD4_Msk (0x1ul << BPWM_CTL0_CTRLD4_Pos) /*!< BPWM_T::CTL0: CTRLD4 Mask */ + +#define BPWM_CTL0_CTRLD5_Pos (5) /*!< BPWM_T::CTL0: CTRLD5 Position */ +#define BPWM_CTL0_CTRLD5_Msk (0x1ul << BPWM_CTL0_CTRLD5_Pos) /*!< BPWM_T::CTL0: CTRLD5 Mask */ + +#define BPWM_CTL0_IMMLDEN0_Pos (16) /*!< BPWM_T::CTL0: IMMLDEN0 Position */ +#define BPWM_CTL0_IMMLDEN0_Msk (0x1ul << BPWM_CTL0_IMMLDEN0_Pos) /*!< BPWM_T::CTL0: IMMLDEN0 Mask */ + +#define BPWM_CTL0_IMMLDEN1_Pos (17) /*!< BPWM_T::CTL0: IMMLDEN1 Position */ +#define BPWM_CTL0_IMMLDEN1_Msk (0x1ul << BPWM_CTL0_IMMLDEN1_Pos) /*!< BPWM_T::CTL0: IMMLDEN1 Mask */ + +#define BPWM_CTL0_IMMLDEN2_Pos (18) /*!< BPWM_T::CTL0: IMMLDEN2 Position */ +#define BPWM_CTL0_IMMLDEN2_Msk (0x1ul << BPWM_CTL0_IMMLDEN2_Pos) /*!< BPWM_T::CTL0: IMMLDEN2 Mask */ + +#define BPWM_CTL0_IMMLDEN3_Pos (19) /*!< BPWM_T::CTL0: IMMLDEN3 Position */ +#define BPWM_CTL0_IMMLDEN3_Msk (0x1ul << BPWM_CTL0_IMMLDEN3_Pos) /*!< BPWM_T::CTL0: IMMLDEN3 Mask */ + +#define BPWM_CTL0_IMMLDEN4_Pos (20) /*!< BPWM_T::CTL0: IMMLDEN4 Position */ +#define BPWM_CTL0_IMMLDEN4_Msk (0x1ul << BPWM_CTL0_IMMLDEN4_Pos) /*!< BPWM_T::CTL0: IMMLDEN4 Mask */ + +#define BPWM_CTL0_IMMLDEN5_Pos (21) /*!< BPWM_T::CTL0: IMMLDEN5 Position */ +#define BPWM_CTL0_IMMLDEN5_Msk (0x1ul << BPWM_CTL0_IMMLDEN5_Pos) /*!< BPWM_T::CTL0: IMMLDEN5 Mask */ + +#define BPWM_CTL0_DBGHALT_Pos (30) /*!< BPWM_T::CTL0: DBGHALT Position */ +#define BPWM_CTL0_DBGHALT_Msk (0x1ul << BPWM_CTL0_DBGHALT_Pos) /*!< BPWM_T::CTL0: DBGHALT Mask */ + +#define BPWM_CTL0_DBGTRIOFF_Pos (31) /*!< BPWM_T::CTL0: DBGTRIOFF Position */ +#define BPWM_CTL0_DBGTRIOFF_Msk (0x1ul << BPWM_CTL0_DBGTRIOFF_Pos) /*!< BPWM_T::CTL0: DBGTRIOFF Mask */ + +#define BPWM_CTL1_CNTTYPE0_Pos (0) /*!< BPWM_T::CTL1: CNTTYPE0 Position */ +#define BPWM_CTL1_CNTTYPE0_Msk (0x3ul << BPWM_CTL1_CNTTYPE0_Pos) /*!< BPWM_T::CTL1: CNTTYPE0 Mask */ + +#define BPWM_CLKSRC_ECLKSRC0_Pos (0) /*!< BPWM_T::CLKSRC: ECLKSRC0 Position */ +#define BPWM_CLKSRC_ECLKSRC0_Msk (0x7ul << BPWM_CLKSRC_ECLKSRC0_Pos) /*!< BPWM_T::CLKSRC: ECLKSRC0 Mask */ + +#define BPWM_CLKPSC_CLKPSC_Pos (0) /*!< BPWM_T::CLKPSC: CLKPSC Position */ +#define BPWM_CLKPSC_CLKPSC_Msk (0xffful << BPWM_CLKPSC_CLKPSC_Pos) /*!< BPWM_T::CLKPSC: CLKPSC Mask */ + +#define BPWM_CNTEN_CNTEN0_Pos (0) /*!< BPWM_T::CNTEN: CNTEN0 Position */ +#define BPWM_CNTEN_CNTEN0_Msk (0x1ul << BPWM_CNTEN_CNTEN0_Pos) /*!< BPWM_T::CNTEN: CNTEN0 Mask */ + +#define BPWM_CNTCLR_CNTCLR0_Pos (0) /*!< BPWM_T::CNTCLR: CNTCLR0 Position */ +#define BPWM_CNTCLR_CNTCLR0_Msk (0x1ul << BPWM_CNTCLR_CNTCLR0_Pos) /*!< BPWM_T::CNTCLR: CNTCLR0 Mask */ + +#define BPWM_PERIOD_PERIOD_Pos (0) /*!< BPWM_T::PERIOD: PERIOD Position */ +#define BPWM_PERIOD_PERIOD_Msk (0xfffful << BPWM_PERIOD_PERIOD_Pos) /*!< BPWM_T::PERIOD: PERIOD Mask */ + +#define BPWM_CMPDAT_CMPDAT_Pos (0) /*!< BPWM_T::CMPDAT0: CMPDAT Position */ +#define BPWM_CMPDAT_CMPDAT_Msk (0xfffful << BPWM_CMPDAT_CMPDAT_Pos) /*!< BPWM_T::CMPDAT0: CMPDAT Mask */ + +#define BPWM_CNT_CNT_Pos (0) /*!< BPWM_T::CNT: CNT Position */ +#define BPWM_CNT_CNT_Msk (0xfffful << BPWM_CNT_CNT_Pos) /*!< BPWM_T::CNT: CNT Mask */ + +#define BPWM_CNT_DIRF_Pos (16) /*!< BPWM_T::CNT: DIRF Position */ +#define BPWM_CNT_DIRF_Msk (0x1ul << BPWM_CNT_DIRF_Pos) /*!< BPWM_T::CNT: DIRF Mask */ + +#define BPWM_WGCTL0_ZPCTL0_Pos (0) /*!< BPWM_T::WGCTL0: ZPCTL0 Position */ +#define BPWM_WGCTL0_ZPCTL0_Msk (0x3ul << BPWM_WGCTL0_ZPCTL0_Pos) /*!< BPWM_T::WGCTL0: ZPCTL0 Mask */ + +#define BPWM_WGCTL0_ZPCTL1_Pos (2) /*!< BPWM_T::WGCTL0: ZPCTL1 Position */ +#define BPWM_WGCTL0_ZPCTL1_Msk (0x3ul << BPWM_WGCTL0_ZPCTL1_Pos) /*!< BPWM_T::WGCTL0: ZPCTL1 Mask */ + +#define BPWM_WGCTL0_ZPCTL2_Pos (4) /*!< BPWM_T::WGCTL0: ZPCTL2 Position */ +#define BPWM_WGCTL0_ZPCTL2_Msk (0x3ul << BPWM_WGCTL0_ZPCTL2_Pos) /*!< BPWM_T::WGCTL0: ZPCTL2 Mask */ + +#define BPWM_WGCTL0_ZPCTL3_Pos (6) /*!< BPWM_T::WGCTL0: ZPCTL3 Position */ +#define BPWM_WGCTL0_ZPCTL3_Msk (0x3ul << BPWM_WGCTL0_ZPCTL3_Pos) /*!< BPWM_T::WGCTL0: ZPCTL3 Mask */ + +#define BPWM_WGCTL0_ZPCTL4_Pos (8) /*!< BPWM_T::WGCTL0: ZPCTL4 Position */ +#define BPWM_WGCTL0_ZPCTL4_Msk (0x3ul << BPWM_WGCTL0_ZPCTL4_Pos) /*!< BPWM_T::WGCTL0: ZPCTL4 Mask */ + +#define BPWM_WGCTL0_ZPCTL5_Pos (10) /*!< BPWM_T::WGCTL0: ZPCTL5 Position */ +#define BPWM_WGCTL0_ZPCTL5_Msk (0x3ul << BPWM_WGCTL0_ZPCTL5_Pos) /*!< BPWM_T::WGCTL0: ZPCTL5 Mask */ + +#define BPWM_WGCTL0_PRDPCTL0_Pos (16) /*!< BPWM_T::WGCTL0: PRDPCTL0 Position */ +#define BPWM_WGCTL0_PRDPCTL0_Msk (0x3ul << BPWM_WGCTL0_PRDPCTL0_Pos) /*!< BPWM_T::WGCTL0: PRDPCTL0 Mask */ + +#define BPWM_WGCTL0_PRDPCTL1_Pos (18) /*!< BPWM_T::WGCTL0: PRDPCTL1 Position */ +#define BPWM_WGCTL0_PRDPCTL1_Msk (0x3ul << BPWM_WGCTL0_PRDPCTL1_Pos) /*!< BPWM_T::WGCTL0: PRDPCTL1 Mask */ + +#define BPWM_WGCTL0_PRDPCTL2_Pos (20) /*!< BPWM_T::WGCTL0: PRDPCTL2 Position */ +#define BPWM_WGCTL0_PRDPCTL2_Msk (0x3ul << BPWM_WGCTL0_PRDPCTL2_Pos) /*!< BPWM_T::WGCTL0: PRDPCTL2 Mask */ + +#define BPWM_WGCTL0_PRDPCTL3_Pos (22) /*!< BPWM_T::WGCTL0: PRDPCTL3 Position */ +#define BPWM_WGCTL0_PRDPCTL3_Msk (0x3ul << BPWM_WGCTL0_PRDPCTL3_Pos) /*!< BPWM_T::WGCTL0: PRDPCTL3 Mask */ + +#define BPWM_WGCTL0_PRDPCTL4_Pos (24) /*!< BPWM_T::WGCTL0: PRDPCTL4 Position */ +#define BPWM_WGCTL0_PRDPCTL4_Msk (0x3ul << BPWM_WGCTL0_PRDPCTL4_Pos) /*!< BPWM_T::WGCTL0: PRDPCTL4 Mask */ + +#define BPWM_WGCTL0_PRDPCTL5_Pos (26) /*!< BPWM_T::WGCTL0: PRDPCTL5 Position */ +#define BPWM_WGCTL0_PRDPCTL5_Msk (0x3ul << BPWM_WGCTL0_PRDPCTL5_Pos) /*!< BPWM_T::WGCTL0: PRDPCTL5 Mask */ + +#define BPWM_WGCTL1_CMPUCTL0_Pos (0) /*!< BPWM_T::WGCTL1: CMPUCTL0 Position */ +#define BPWM_WGCTL1_CMPUCTL0_Msk (0x3ul << BPWM_WGCTL1_CMPUCTL0_Pos) /*!< BPWM_T::WGCTL1: CMPUCTL0 Mask */ + +#define BPWM_WGCTL1_CMPUCTL1_Pos (2) /*!< BPWM_T::WGCTL1: CMPUCTL1 Position */ +#define BPWM_WGCTL1_CMPUCTL1_Msk (0x3ul << BPWM_WGCTL1_CMPUCTL1_Pos) /*!< BPWM_T::WGCTL1: CMPUCTL1 Mask */ + +#define BPWM_WGCTL1_CMPUCTL2_Pos (4) /*!< BPWM_T::WGCTL1: CMPUCTL2 Position */ +#define BPWM_WGCTL1_CMPUCTL2_Msk (0x3ul << BPWM_WGCTL1_CMPUCTL2_Pos) /*!< BPWM_T::WGCTL1: CMPUCTL2 Mask */ + +#define BPWM_WGCTL1_CMPUCTL3_Pos (6) /*!< BPWM_T::WGCTL1: CMPUCTL3 Position */ +#define BPWM_WGCTL1_CMPUCTL3_Msk (0x3ul << BPWM_WGCTL1_CMPUCTL3_Pos) /*!< BPWM_T::WGCTL1: CMPUCTL3 Mask */ + +#define BPWM_WGCTL1_CMPUCTL4_Pos (8) /*!< BPWM_T::WGCTL1: CMPUCTL4 Position */ +#define BPWM_WGCTL1_CMPUCTL4_Msk (0x3ul << BPWM_WGCTL1_CMPUCTL4_Pos) /*!< BPWM_T::WGCTL1: CMPUCTL4 Mask */ + +#define BPWM_WGCTL1_CMPUCTL5_Pos (10) /*!< BPWM_T::WGCTL1: CMPUCTL5 Position */ +#define BPWM_WGCTL1_CMPUCTL5_Msk (0x3ul << BPWM_WGCTL1_CMPUCTL5_Pos) /*!< BPWM_T::WGCTL1: CMPUCTL5 Mask */ + +#define BPWM_WGCTL1_CMPDCTL0_Pos (16) /*!< BPWM_T::WGCTL1: CMPDCTL0 Position */ +#define BPWM_WGCTL1_CMPDCTL0_Msk (0x3ul << BPWM_WGCTL1_CMPDCTL0_Pos) /*!< BPWM_T::WGCTL1: CMPDCTL0 Mask */ + +#define BPWM_WGCTL1_CMPDCTL1_Pos (18) /*!< BPWM_T::WGCTL1: CMPDCTL1 Position */ +#define BPWM_WGCTL1_CMPDCTL1_Msk (0x3ul << BPWM_WGCTL1_CMPDCTL1_Pos) /*!< BPWM_T::WGCTL1: CMPDCTL1 Mask */ + +#define BPWM_WGCTL1_CMPDCTL2_Pos (20) /*!< BPWM_T::WGCTL1: CMPDCTL2 Position */ +#define BPWM_WGCTL1_CMPDCTL2_Msk (0x3ul << BPWM_WGCTL1_CMPDCTL2_Pos) /*!< BPWM_T::WGCTL1: CMPDCTL2 Mask */ + +#define BPWM_WGCTL1_CMPDCTL3_Pos (22) /*!< BPWM_T::WGCTL1: CMPDCTL3 Position */ +#define BPWM_WGCTL1_CMPDCTL3_Msk (0x3ul << BPWM_WGCTL1_CMPDCTL3_Pos) /*!< BPWM_T::WGCTL1: CMPDCTL3 Mask */ + +#define BPWM_WGCTL1_CMPDCTL4_Pos (24) /*!< BPWM_T::WGCTL1: CMPDCTL4 Position */ +#define BPWM_WGCTL1_CMPDCTL4_Msk (0x3ul << BPWM_WGCTL1_CMPDCTL4_Pos) /*!< BPWM_T::WGCTL1: CMPDCTL4 Mask */ + +#define BPWM_WGCTL1_CMPDCTL5_Pos (26) /*!< BPWM_T::WGCTL1: CMPDCTL5 Position */ +#define BPWM_WGCTL1_CMPDCTL5_Msk (0x3ul << BPWM_WGCTL1_CMPDCTL5_Pos) /*!< BPWM_T::WGCTL1: CMPDCTL5 Mask */ + +#define BPWM_MSKEN_MSKEN0_Pos (0) /*!< BPWM_T::MSKEN: MSKEN0 Position */ +#define BPWM_MSKEN_MSKEN0_Msk (0x1ul << BPWM_MSKEN_MSKEN0_Pos) /*!< BPWM_T::MSKEN: MSKEN0 Mask */ + +#define BPWM_MSKEN_MSKEN1_Pos (1) /*!< BPWM_T::MSKEN: MSKEN1 Position */ +#define BPWM_MSKEN_MSKEN1_Msk (0x1ul << BPWM_MSKEN_MSKEN1_Pos) /*!< BPWM_T::MSKEN: MSKEN1 Mask */ + +#define BPWM_MSKEN_MSKEN2_Pos (2) /*!< BPWM_T::MSKEN: MSKEN2 Position */ +#define BPWM_MSKEN_MSKEN2_Msk (0x1ul << BPWM_MSKEN_MSKEN2_Pos) /*!< BPWM_T::MSKEN: MSKEN2 Mask */ + +#define BPWM_MSKEN_MSKEN3_Pos (3) /*!< BPWM_T::MSKEN: MSKEN3 Position */ +#define BPWM_MSKEN_MSKEN3_Msk (0x1ul << BPWM_MSKEN_MSKEN3_Pos) /*!< BPWM_T::MSKEN: MSKEN3 Mask */ + +#define BPWM_MSKEN_MSKEN4_Pos (4) /*!< BPWM_T::MSKEN: MSKEN4 Position */ +#define BPWM_MSKEN_MSKEN4_Msk (0x1ul << BPWM_MSKEN_MSKEN4_Pos) /*!< BPWM_T::MSKEN: MSKEN4 Mask */ + +#define BPWM_MSKEN_MSKEN5_Pos (5) /*!< BPWM_T::MSKEN: MSKEN5 Position */ +#define BPWM_MSKEN_MSKEN5_Msk (0x1ul << BPWM_MSKEN_MSKEN5_Pos) /*!< BPWM_T::MSKEN: MSKEN5 Mask */ + +#define BPWM_MSK_MSKDAT0_Pos (0) /*!< BPWM_T::MSK: MSKDAT0 Position */ +#define BPWM_MSK_MSKDAT0_Msk (0x1ul << BPWM_MSK_MSKDAT0_Pos) /*!< BPWM_T::MSK: MSKDAT0 Mask */ + +#define BPWM_MSK_MSKDAT1_Pos (1) /*!< BPWM_T::MSK: MSKDAT1 Position */ +#define BPWM_MSK_MSKDAT1_Msk (0x1ul << BPWM_MSK_MSKDAT1_Pos) /*!< BPWM_T::MSK: MSKDAT1 Mask */ + +#define BPWM_MSK_MSKDAT2_Pos (2) /*!< BPWM_T::MSK: MSKDAT2 Position */ +#define BPWM_MSK_MSKDAT2_Msk (0x1ul << BPWM_MSK_MSKDAT2_Pos) /*!< BPWM_T::MSK: MSKDAT2 Mask */ + +#define BPWM_MSK_MSKDAT3_Pos (3) /*!< BPWM_T::MSK: MSKDAT3 Position */ +#define BPWM_MSK_MSKDAT3_Msk (0x1ul << BPWM_MSK_MSKDAT3_Pos) /*!< BPWM_T::MSK: MSKDAT3 Mask */ + +#define BPWM_MSK_MSKDAT4_Pos (4) /*!< BPWM_T::MSK: MSKDAT4 Position */ +#define BPWM_MSK_MSKDAT4_Msk (0x1ul << BPWM_MSK_MSKDAT4_Pos) /*!< BPWM_T::MSK: MSKDAT4 Mask */ + +#define BPWM_MSK_MSKDAT5_Pos (5) /*!< BPWM_T::MSK: MSKDAT5 Position */ +#define BPWM_MSK_MSKDAT5_Msk (0x1ul << BPWM_MSK_MSKDAT5_Pos) /*!< BPWM_T::MSK: MSKDAT5 Mask */ + +#define BPWM_POLCTL_PINV0_Pos (0) /*!< BPWM_T::POLCTL: PINV0 Position */ +#define BPWM_POLCTL_PINV0_Msk (0x1ul << BPWM_POLCTL_PINV0_Pos) /*!< BPWM_T::POLCTL: PINV0 Mask */ + +#define BPWM_POLCTL_PINV1_Pos (1) /*!< BPWM_T::POLCTL: PINV1 Position */ +#define BPWM_POLCTL_PINV1_Msk (0x1ul << BPWM_POLCTL_PINV1_Pos) /*!< BPWM_T::POLCTL: PINV1 Mask */ + +#define BPWM_POLCTL_PINV2_Pos (2) /*!< BPWM_T::POLCTL: PINV2 Position */ +#define BPWM_POLCTL_PINV2_Msk (0x1ul << BPWM_POLCTL_PINV2_Pos) /*!< BPWM_T::POLCTL: PINV2 Mask */ + +#define BPWM_POLCTL_PINV3_Pos (3) /*!< BPWM_T::POLCTL: PINV3 Position */ +#define BPWM_POLCTL_PINV3_Msk (0x1ul << BPWM_POLCTL_PINV3_Pos) /*!< BPWM_T::POLCTL: PINV3 Mask */ + +#define BPWM_POLCTL_PINV4_Pos (4) /*!< BPWM_T::POLCTL: PINV4 Position */ +#define BPWM_POLCTL_PINV4_Msk (0x1ul << BPWM_POLCTL_PINV4_Pos) /*!< BPWM_T::POLCTL: PINV4 Mask */ + +#define BPWM_POLCTL_PINV5_Pos (5) /*!< BPWM_T::POLCTL: PINV5 Position */ +#define BPWM_POLCTL_PINV5_Msk (0x1ul << BPWM_POLCTL_PINV5_Pos) /*!< BPWM_T::POLCTL: PINV5 Mask */ + +#define BPWM_POEN_POEN0_Pos (0) /*!< BPWM_T::POEN: POEN0 Position */ +#define BPWM_POEN_POEN0_Msk (0x1ul << BPWM_POEN_POEN0_Pos) /*!< BPWM_T::POEN: POEN0 Mask */ + +#define BPWM_POEN_POEN1_Pos (1) /*!< BPWM_T::POEN: POEN1 Position */ +#define BPWM_POEN_POEN1_Msk (0x1ul << BPWM_POEN_POEN1_Pos) /*!< BPWM_T::POEN: POEN1 Mask */ + +#define BPWM_POEN_POEN2_Pos (2) /*!< BPWM_T::POEN: POEN2 Position */ +#define BPWM_POEN_POEN2_Msk (0x1ul << BPWM_POEN_POEN2_Pos) /*!< BPWM_T::POEN: POEN2 Mask */ + +#define BPWM_POEN_POEN3_Pos (3) /*!< BPWM_T::POEN: POEN3 Position */ +#define BPWM_POEN_POEN3_Msk (0x1ul << BPWM_POEN_POEN3_Pos) /*!< BPWM_T::POEN: POEN3 Mask */ + +#define BPWM_POEN_POEN4_Pos (4) /*!< BPWM_T::POEN: POEN4 Position */ +#define BPWM_POEN_POEN4_Msk (0x1ul << BPWM_POEN_POEN4_Pos) /*!< BPWM_T::POEN: POEN4 Mask */ + +#define BPWM_POEN_POEN5_Pos (5) /*!< BPWM_T::POEN: POEN5 Position */ +#define BPWM_POEN_POEN5_Msk (0x1ul << BPWM_POEN_POEN5_Pos) /*!< BPWM_T::POEN: POEN5 Mask */ + +#define BPWM_INTEN_ZIEN0_Pos (0) /*!< BPWM_T::INTEN: ZIEN0 Position */ +#define BPWM_INTEN_ZIEN0_Msk (0x1ul << BPWM_INTEN_ZIEN0_Pos) /*!< BPWM_T::INTEN: ZIEN0 Mask */ + +#define BPWM_INTEN_PIEN0_Pos (8) /*!< BPWM_T::INTEN: PIEN0 Position */ +#define BPWM_INTEN_PIEN0_Msk (0x1ul << BPWM_INTEN_PIEN0_Pos) /*!< BPWM_T::INTEN: PIEN0 Mask */ + +#define BPWM_INTEN_CMPUIEN0_Pos (16) /*!< BPWM_T::INTEN: CMPUIEN0 Position */ +#define BPWM_INTEN_CMPUIEN0_Msk (0x1ul << BPWM_INTEN_CMPUIEN0_Pos) /*!< BPWM_T::INTEN: CMPUIEN0 Mask */ + +#define BPWM_INTEN_CMPUIEN1_Pos (17) /*!< BPWM_T::INTEN: CMPUIEN1 Position */ +#define BPWM_INTEN_CMPUIEN1_Msk (0x1ul << BPWM_INTEN_CMPUIEN1_Pos) /*!< BPWM_T::INTEN: CMPUIEN1 Mask */ + +#define BPWM_INTEN_CMPUIEN2_Pos (18) /*!< BPWM_T::INTEN: CMPUIEN2 Position */ +#define BPWM_INTEN_CMPUIEN2_Msk (0x1ul << BPWM_INTEN_CMPUIEN2_Pos) /*!< BPWM_T::INTEN: CMPUIEN2 Mask */ + +#define BPWM_INTEN_CMPUIEN3_Pos (19) /*!< BPWM_T::INTEN: CMPUIEN3 Position */ +#define BPWM_INTEN_CMPUIEN3_Msk (0x1ul << BPWM_INTEN_CMPUIEN3_Pos) /*!< BPWM_T::INTEN: CMPUIEN3 Mask */ + +#define BPWM_INTEN_CMPUIEN4_Pos (20) /*!< BPWM_T::INTEN: CMPUIEN4 Position */ +#define BPWM_INTEN_CMPUIEN4_Msk (0x1ul << BPWM_INTEN_CMPUIEN4_Pos) /*!< BPWM_T::INTEN: CMPUIEN4 Mask */ + +#define BPWM_INTEN_CMPUIEN5_Pos (21) /*!< BPWM_T::INTEN: CMPUIEN5 Position */ +#define BPWM_INTEN_CMPUIEN5_Msk (0x1ul << BPWM_INTEN_CMPUIEN5_Pos) /*!< BPWM_T::INTEN: CMPUIEN5 Mask */ + +#define BPWM_INTEN_CMPDIEN0_Pos (24) /*!< BPWM_T::INTEN: CMPDIEN0 Position */ +#define BPWM_INTEN_CMPDIEN0_Msk (0x1ul << BPWM_INTEN_CMPDIEN0_Pos) /*!< BPWM_T::INTEN: CMPDIEN0 Mask */ + +#define BPWM_INTEN_CMPDIEN1_Pos (25) /*!< BPWM_T::INTEN: CMPDIEN1 Position */ +#define BPWM_INTEN_CMPDIEN1_Msk (0x1ul << BPWM_INTEN_CMPDIEN1_Pos) /*!< BPWM_T::INTEN: CMPDIEN1 Mask */ + +#define BPWM_INTEN_CMPDIEN2_Pos (26) /*!< BPWM_T::INTEN: CMPDIEN2 Position */ +#define BPWM_INTEN_CMPDIEN2_Msk (0x1ul << BPWM_INTEN_CMPDIEN2_Pos) /*!< BPWM_T::INTEN: CMPDIEN2 Mask */ + +#define BPWM_INTEN_CMPDIEN3_Pos (27) /*!< BPWM_T::INTEN: CMPDIEN3 Position */ +#define BPWM_INTEN_CMPDIEN3_Msk (0x1ul << BPWM_INTEN_CMPDIEN3_Pos) /*!< BPWM_T::INTEN: CMPDIEN3 Mask */ + +#define BPWM_INTEN_CMPDIEN4_Pos (28) /*!< BPWM_T::INTEN: CMPDIEN4 Position */ +#define BPWM_INTEN_CMPDIEN4_Msk (0x1ul << BPWM_INTEN_CMPDIEN4_Pos) /*!< BPWM_T::INTEN: CMPDIEN4 Mask */ + +#define BPWM_INTEN_CMPDIEN5_Pos (29) /*!< BPWM_T::INTEN: CMPDIEN5 Position */ +#define BPWM_INTEN_CMPDIEN5_Msk (0x1ul << BPWM_INTEN_CMPDIEN5_Pos) /*!< BPWM_T::INTEN: CMPDIEN5 Mask */ + +#define BPWM_INTSTS_ZIF0_Pos (0) /*!< BPWM_T::INTSTS: ZIF0 Position */ +#define BPWM_INTSTS_ZIF0_Msk (0x1ul << BPWM_INTSTS_ZIF0_Pos) /*!< BPWM_T::INTSTS: ZIF0 Mask */ + +#define BPWM_INTSTS_PIF0_Pos (8) /*!< BPWM_T::INTSTS: PIF0 Position */ +#define BPWM_INTSTS_PIF0_Msk (0x1ul << BPWM_INTSTS_PIF0_Pos) /*!< BPWM_T::INTSTS: PIF0 Mask */ + +#define BPWM_INTSTS_CMPUIF0_Pos (16) /*!< BPWM_T::INTSTS: CMPUIF0 Position */ +#define BPWM_INTSTS_CMPUIF0_Msk (0x1ul << BPWM_INTSTS_CMPUIF0_Pos) /*!< BPWM_T::INTSTS: CMPUIF0 Mask */ + +#define BPWM_INTSTS_CMPUIF1_Pos (17) /*!< BPWM_T::INTSTS: CMPUIF1 Position */ +#define BPWM_INTSTS_CMPUIF1_Msk (0x1ul << BPWM_INTSTS_CMPUIF1_Pos) /*!< BPWM_T::INTSTS: CMPUIF1 Mask */ + +#define BPWM_INTSTS_CMPUIF2_Pos (18) /*!< BPWM_T::INTSTS: CMPUIF2 Position */ +#define BPWM_INTSTS_CMPUIF2_Msk (0x1ul << BPWM_INTSTS_CMPUIF2_Pos) /*!< BPWM_T::INTSTS: CMPUIF2 Mask */ + +#define BPWM_INTSTS_CMPUIF3_Pos (19) /*!< BPWM_T::INTSTS: CMPUIF3 Position */ +#define BPWM_INTSTS_CMPUIF3_Msk (0x1ul << BPWM_INTSTS_CMPUIF3_Pos) /*!< BPWM_T::INTSTS: CMPUIF3 Mask */ + +#define BPWM_INTSTS_CMPUIF4_Pos (20) /*!< BPWM_T::INTSTS: CMPUIF4 Position */ +#define BPWM_INTSTS_CMPUIF4_Msk (0x1ul << BPWM_INTSTS_CMPUIF4_Pos) /*!< BPWM_T::INTSTS: CMPUIF4 Mask */ + +#define BPWM_INTSTS_CMPUIF5_Pos (21) /*!< BPWM_T::INTSTS: CMPUIF5 Position */ +#define BPWM_INTSTS_CMPUIF5_Msk (0x1ul << BPWM_INTSTS_CMPUIF5_Pos) /*!< BPWM_T::INTSTS: CMPUIF5 Mask */ + +#define BPWM_INTSTS_CMPDIF0_Pos (24) /*!< BPWM_T::INTSTS: CMPDIF0 Position */ +#define BPWM_INTSTS_CMPDIF0_Msk (0x1ul << BPWM_INTSTS_CMPDIF0_Pos) /*!< BPWM_T::INTSTS: CMPDIF0 Mask */ + +#define BPWM_INTSTS_CMPDIF1_Pos (25) /*!< BPWM_T::INTSTS: CMPDIF1 Position */ +#define BPWM_INTSTS_CMPDIF1_Msk (0x1ul << BPWM_INTSTS_CMPDIF1_Pos) /*!< BPWM_T::INTSTS: CMPDIF1 Mask */ + +#define BPWM_INTSTS_CMPDIF2_Pos (26) /*!< BPWM_T::INTSTS: CMPDIF2 Position */ +#define BPWM_INTSTS_CMPDIF2_Msk (0x1ul << BPWM_INTSTS_CMPDIF2_Pos) /*!< BPWM_T::INTSTS: CMPDIF2 Mask */ + +#define BPWM_INTSTS_CMPDIF3_Pos (27) /*!< BPWM_T::INTSTS: CMPDIF3 Position */ +#define BPWM_INTSTS_CMPDIF3_Msk (0x1ul << BPWM_INTSTS_CMPDIF3_Pos) /*!< BPWM_T::INTSTS: CMPDIF3 Mask */ + +#define BPWM_INTSTS_CMPDIF4_Pos (28) /*!< BPWM_T::INTSTS: CMPDIF4 Position */ +#define BPWM_INTSTS_CMPDIF4_Msk (0x1ul << BPWM_INTSTS_CMPDIF4_Pos) /*!< BPWM_T::INTSTS: CMPDIF4 Mask */ + +#define BPWM_INTSTS_CMPDIF5_Pos (29) /*!< BPWM_T::INTSTS: CMPDIF5 Position */ +#define BPWM_INTSTS_CMPDIF5_Msk (0x1ul << BPWM_INTSTS_CMPDIF5_Pos) /*!< BPWM_T::INTSTS: CMPDIF5 Mask */ + +#define BPWM_EADCTS0_TRGSEL0_Pos (0) /*!< BPWM_T::EADCTS0: TRGSEL0 Position */ +#define BPWM_EADCTS0_TRGSEL0_Msk (0xful << BPWM_EADCTS0_TRGSEL0_Pos) /*!< BPWM_T::EADCTS0: TRGSEL0 Mask */ + +#define BPWM_EADCTS0_TRGEN0_Pos (7) /*!< BPWM_T::EADCTS0: TRGEN0 Position */ +#define BPWM_EADCTS0_TRGEN0_Msk (0x1ul << BPWM_EADCTS0_TRGEN0_Pos) /*!< BPWM_T::EADCTS0: TRGEN0 Mask */ + +#define BPWM_EADCTS0_TRGSEL1_Pos (8) /*!< BPWM_T::EADCTS0: TRGSEL1 Position */ +#define BPWM_EADCTS0_TRGSEL1_Msk (0xful << BPWM_EADCTS0_TRGSEL1_Pos) /*!< BPWM_T::EADCTS0: TRGSEL1 Mask */ + +#define BPWM_EADCTS0_TRGEN1_Pos (15) /*!< BPWM_T::EADCTS0: TRGEN1 Position */ +#define BPWM_EADCTS0_TRGEN1_Msk (0x1ul << BPWM_EADCTS0_TRGEN1_Pos) /*!< BPWM_T::EADCTS0: TRGEN1 Mask */ + +#define BPWM_EADCTS0_TRGSEL2_Pos (16) /*!< BPWM_T::EADCTS0: TRGSEL2 Position */ +#define BPWM_EADCTS0_TRGSEL2_Msk (0xful << BPWM_EADCTS0_TRGSEL2_Pos) /*!< BPWM_T::EADCTS0: TRGSEL2 Mask */ + +#define BPWM_EADCTS0_TRGEN2_Pos (23) /*!< BPWM_T::EADCTS0: TRGEN2 Position */ +#define BPWM_EADCTS0_TRGEN2_Msk (0x1ul << BPWM_EADCTS0_TRGEN2_Pos) /*!< BPWM_T::EADCTS0: TRGEN2 Mask */ + +#define BPWM_EADCTS0_TRGSEL3_Pos (24) /*!< BPWM_T::EADCTS0: TRGSEL3 Position */ +#define BPWM_EADCTS0_TRGSEL3_Msk (0xful << BPWM_EADCTS0_TRGSEL3_Pos) /*!< BPWM_T::EADCTS0: TRGSEL3 Mask */ + +#define BPWM_EADCTS0_TRGEN3_Pos (31) /*!< BPWM_T::EADCTS0: TRGEN3 Position */ +#define BPWM_EADCTS0_TRGEN3_Msk (0x1ul << BPWM_EADCTS0_TRGEN3_Pos) /*!< BPWM_T::EADCTS0: TRGEN3 Mask */ + +#define BPWM_EADCTS1_TRGSEL4_Pos (0) /*!< BPWM_T::EADCTS1: TRGSEL4 Position */ +#define BPWM_EADCTS1_TRGSEL4_Msk (0xful << BPWM_EADCTS1_TRGSEL4_Pos) /*!< BPWM_T::EADCTS1: TRGSEL4 Mask */ + +#define BPWM_EADCTS1_TRGEN4_Pos (7) /*!< BPWM_T::EADCTS1: TRGEN4 Position */ +#define BPWM_EADCTS1_TRGEN4_Msk (0x1ul << BPWM_EADCTS1_TRGEN4_Pos) /*!< BPWM_T::EADCTS1: TRGEN4 Mask */ + +#define BPWM_EADCTS1_TRGSEL5_Pos (8) /*!< BPWM_T::EADCTS1: TRGSEL5 Position */ +#define BPWM_EADCTS1_TRGSEL5_Msk (0xful << BPWM_EADCTS1_TRGSEL5_Pos) /*!< BPWM_T::EADCTS1: TRGSEL5 Mask */ + +#define BPWM_EADCTS1_TRGEN5_Pos (15) /*!< BPWM_T::EADCTS1: TRGEN5 Position */ +#define BPWM_EADCTS1_TRGEN5_Msk (0x1ul << BPWM_EADCTS1_TRGEN5_Pos) /*!< BPWM_T::EADCTS1: TRGEN5 Mask */ + +#define BPWM_SSCTL_SSEN0_Pos (0) /*!< BPWM_T::SSCTL: SSEN0 Position */ +#define BPWM_SSCTL_SSEN0_Msk (0x1ul << BPWM_SSCTL_SSEN0_Pos) /*!< BPWM_T::SSCTL: SSEN0 Mask */ + +#define BPWM_SSCTL_SSRC_Pos (8) /*!< BPWM_T::SSCTL: SSRC Position */ +#define BPWM_SSCTL_SSRC_Msk (0x3ul << BPWM_SSCTL_SSRC_Pos) /*!< BPWM_T::SSCTL: SSRC Mask */ + +#define BPWM_SSTRG_CNTSEN_Pos (0) /*!< BPWM_T::SSTRG: CNTSEN Position */ +#define BPWM_SSTRG_CNTSEN_Msk (0x1ul << BPWM_SSTRG_CNTSEN_Pos) /*!< BPWM_T::SSTRG: CNTSEN Mask */ + +#define BPWM_STATUS_CNTMAX0_Pos (0) /*!< BPWM_T::STATUS: CNTMAX0 Position */ +#define BPWM_STATUS_CNTMAX0_Msk (0x1ul << BPWM_STATUS_CNTMAX0_Pos) /*!< BPWM_T::STATUS: CNTMAX0 Mask */ + +#define BPWM_STATUS_EADCTRG0_Pos (16) /*!< BPWM_T::STATUS: EADCTRG0 Position */ +#define BPWM_STATUS_EADCTRG0_Msk (0x1ul << BPWM_STATUS_EADCTRG0_Pos) /*!< BPWM_T::STATUS: EADCTRG0 Mask */ + +#define BPWM_STATUS_EADCTRG1_Pos (17) /*!< BPWM_T::STATUS: EADCTRG1 Position */ +#define BPWM_STATUS_EADCTRG1_Msk (0x1ul << BPWM_STATUS_EADCTRG1_Pos) /*!< BPWM_T::STATUS: EADCTRG1 Mask */ + +#define BPWM_STATUS_EADCTRG2_Pos (18) /*!< BPWM_T::STATUS: EADCTRG2 Position */ +#define BPWM_STATUS_EADCTRG2_Msk (0x1ul << BPWM_STATUS_EADCTRG2_Pos) /*!< BPWM_T::STATUS: EADCTRG2 Mask */ + +#define BPWM_STATUS_EADCTRG3_Pos (19) /*!< BPWM_T::STATUS: EADCTRG3 Position */ +#define BPWM_STATUS_EADCTRG3_Msk (0x1ul << BPWM_STATUS_EADCTRG3_Pos) /*!< BPWM_T::STATUS: EADCTRG3 Mask */ + +#define BPWM_STATUS_EADCTRG4_Pos (20) /*!< BPWM_T::STATUS: EADCTRG4 Position */ +#define BPWM_STATUS_EADCTRG4_Msk (0x1ul << BPWM_STATUS_EADCTRG4_Pos) /*!< BPWM_T::STATUS: EADCTRG4 Mask */ + +#define BPWM_STATUS_EADCTRG5_Pos (21) /*!< BPWM_T::STATUS: EADCTRG5 Position */ +#define BPWM_STATUS_EADCTRG5_Msk (0x1ul << BPWM_STATUS_EADCTRG5_Pos) /*!< BPWM_T::STATUS: EADCTRG5 Mask */ + +#define BPWM_CAPINEN_CAPINEN0_Pos (0) /*!< BPWM_T::CAPINEN: CAPINEN0 Position */ +#define BPWM_CAPINEN_CAPINEN0_Msk (0x1ul << BPWM_CAPINEN_CAPINEN0_Pos) /*!< BPWM_T::CAPINEN: CAPINEN0 Mask */ + +#define BPWM_CAPINEN_CAPINEN1_Pos (1) /*!< BPWM_T::CAPINEN: CAPINEN1 Position */ +#define BPWM_CAPINEN_CAPINEN1_Msk (0x1ul << BPWM_CAPINEN_CAPINEN1_Pos) /*!< BPWM_T::CAPINEN: CAPINEN1 Mask */ + +#define BPWM_CAPINEN_CAPINEN2_Pos (2) /*!< BPWM_T::CAPINEN: CAPINEN2 Position */ +#define BPWM_CAPINEN_CAPINEN2_Msk (0x1ul << BPWM_CAPINEN_CAPINEN2_Pos) /*!< BPWM_T::CAPINEN: CAPINEN2 Mask */ + +#define BPWM_CAPINEN_CAPINEN3_Pos (3) /*!< BPWM_T::CAPINEN: CAPINEN3 Position */ +#define BPWM_CAPINEN_CAPINEN3_Msk (0x1ul << BPWM_CAPINEN_CAPINEN3_Pos) /*!< BPWM_T::CAPINEN: CAPINEN3 Mask */ + +#define BPWM_CAPINEN_CAPINEN4_Pos (4) /*!< BPWM_T::CAPINEN: CAPINEN4 Position */ +#define BPWM_CAPINEN_CAPINEN4_Msk (0x1ul << BPWM_CAPINEN_CAPINEN4_Pos) /*!< BPWM_T::CAPINEN: CAPINEN4 Mask */ + +#define BPWM_CAPINEN_CAPINEN5_Pos (5) /*!< BPWM_T::CAPINEN: CAPINEN5 Position */ +#define BPWM_CAPINEN_CAPINEN5_Msk (0x1ul << BPWM_CAPINEN_CAPINEN5_Pos) /*!< BPWM_T::CAPINEN: CAPINEN5 Mask */ + +#define BPWM_CAPCTL_CAPEN0_Pos (0) /*!< BPWM_T::CAPCTL: CAPEN0 Position */ +#define BPWM_CAPCTL_CAPEN0_Msk (0x1ul << BPWM_CAPCTL_CAPEN0_Pos) /*!< BPWM_T::CAPCTL: CAPEN0 Mask */ + +#define BPWM_CAPCTL_CAPEN1_Pos (1) /*!< BPWM_T::CAPCTL: CAPEN1 Position */ +#define BPWM_CAPCTL_CAPEN1_Msk (0x1ul << BPWM_CAPCTL_CAPEN1_Pos) /*!< BPWM_T::CAPCTL: CAPEN1 Mask */ + +#define BPWM_CAPCTL_CAPEN2_Pos (2) /*!< BPWM_T::CAPCTL: CAPEN2 Position */ +#define BPWM_CAPCTL_CAPEN2_Msk (0x1ul << BPWM_CAPCTL_CAPEN2_Pos) /*!< BPWM_T::CAPCTL: CAPEN2 Mask */ + +#define BPWM_CAPCTL_CAPEN3_Pos (3) /*!< BPWM_T::CAPCTL: CAPEN3 Position */ +#define BPWM_CAPCTL_CAPEN3_Msk (0x1ul << BPWM_CAPCTL_CAPEN3_Pos) /*!< BPWM_T::CAPCTL: CAPEN3 Mask */ + +#define BPWM_CAPCTL_CAPEN4_Pos (4) /*!< BPWM_T::CAPCTL: CAPEN4 Position */ +#define BPWM_CAPCTL_CAPEN4_Msk (0x1ul << BPWM_CAPCTL_CAPEN4_Pos) /*!< BPWM_T::CAPCTL: CAPEN4 Mask */ + +#define BPWM_CAPCTL_CAPEN5_Pos (5) /*!< BPWM_T::CAPCTL: CAPEN5 Position */ +#define BPWM_CAPCTL_CAPEN5_Msk (0x1ul << BPWM_CAPCTL_CAPEN5_Pos) /*!< BPWM_T::CAPCTL: CAPEN5 Mask */ + +#define BPWM_CAPCTL_CAPINV0_Pos (8) /*!< BPWM_T::CAPCTL: CAPINV0 Position */ +#define BPWM_CAPCTL_CAPINV0_Msk (0x1ul << BPWM_CAPCTL_CAPINV0_Pos) /*!< BPWM_T::CAPCTL: CAPINV0 Mask */ + +#define BPWM_CAPCTL_CAPINV1_Pos (9) /*!< BPWM_T::CAPCTL: CAPINV1 Position */ +#define BPWM_CAPCTL_CAPINV1_Msk (0x1ul << BPWM_CAPCTL_CAPINV1_Pos) /*!< BPWM_T::CAPCTL: CAPINV1 Mask */ + +#define BPWM_CAPCTL_CAPINV2_Pos (10) /*!< BPWM_T::CAPCTL: CAPINV2 Position */ +#define BPWM_CAPCTL_CAPINV2_Msk (0x1ul << BPWM_CAPCTL_CAPINV2_Pos) /*!< BPWM_T::CAPCTL: CAPINV2 Mask */ + +#define BPWM_CAPCTL_CAPINV3_Pos (11) /*!< BPWM_T::CAPCTL: CAPINV3 Position */ +#define BPWM_CAPCTL_CAPINV3_Msk (0x1ul << BPWM_CAPCTL_CAPINV3_Pos) /*!< BPWM_T::CAPCTL: CAPINV3 Mask */ + +#define BPWM_CAPCTL_CAPINV4_Pos (12) /*!< BPWM_T::CAPCTL: CAPINV4 Position */ +#define BPWM_CAPCTL_CAPINV4_Msk (0x1ul << BPWM_CAPCTL_CAPINV4_Pos) /*!< BPWM_T::CAPCTL: CAPINV4 Mask */ + +#define BPWM_CAPCTL_CAPINV5_Pos (13) /*!< BPWM_T::CAPCTL: CAPINV5 Position */ +#define BPWM_CAPCTL_CAPINV5_Msk (0x1ul << BPWM_CAPCTL_CAPINV5_Pos) /*!< BPWM_T::CAPCTL: CAPINV5 Mask */ + +#define BPWM_CAPCTL_RCRLDEN0_Pos (16) /*!< BPWM_T::CAPCTL: RCRLDEN0 Position */ +#define BPWM_CAPCTL_RCRLDEN0_Msk (0x1ul << BPWM_CAPCTL_RCRLDEN0_Pos) /*!< BPWM_T::CAPCTL: RCRLDEN0 Mask */ + +#define BPWM_CAPCTL_RCRLDEN1_Pos (17) /*!< BPWM_T::CAPCTL: RCRLDEN1 Position */ +#define BPWM_CAPCTL_RCRLDEN1_Msk (0x1ul << BPWM_CAPCTL_RCRLDEN1_Pos) /*!< BPWM_T::CAPCTL: RCRLDEN1 Mask */ + +#define BPWM_CAPCTL_RCRLDEN2_Pos (18) /*!< BPWM_T::CAPCTL: RCRLDEN2 Position */ +#define BPWM_CAPCTL_RCRLDEN2_Msk (0x1ul << BPWM_CAPCTL_RCRLDEN2_Pos) /*!< BPWM_T::CAPCTL: RCRLDEN2 Mask */ + +#define BPWM_CAPCTL_RCRLDEN3_Pos (19) /*!< BPWM_T::CAPCTL: RCRLDEN3 Position */ +#define BPWM_CAPCTL_RCRLDEN3_Msk (0x1ul << BPWM_CAPCTL_RCRLDEN3_Pos) /*!< BPWM_T::CAPCTL: RCRLDEN3 Mask */ + +#define BPWM_CAPCTL_RCRLDEN4_Pos (20) /*!< BPWM_T::CAPCTL: RCRLDEN4 Position */ +#define BPWM_CAPCTL_RCRLDEN4_Msk (0x1ul << BPWM_CAPCTL_RCRLDEN4_Pos) /*!< BPWM_T::CAPCTL: RCRLDEN4 Mask */ + +#define BPWM_CAPCTL_RCRLDEN5_Pos (21) /*!< BPWM_T::CAPCTL: RCRLDEN5 Position */ +#define BPWM_CAPCTL_RCRLDEN5_Msk (0x1ul << BPWM_CAPCTL_RCRLDEN5_Pos) /*!< BPWM_T::CAPCTL: RCRLDEN5 Mask */ + +#define BPWM_CAPCTL_FCRLDEN0_Pos (24) /*!< BPWM_T::CAPCTL: FCRLDEN0 Position */ +#define BPWM_CAPCTL_FCRLDEN0_Msk (0x1ul << BPWM_CAPCTL_FCRLDEN0_Pos) /*!< BPWM_T::CAPCTL: FCRLDEN0 Mask */ + +#define BPWM_CAPCTL_FCRLDEN1_Pos (25) /*!< BPWM_T::CAPCTL: FCRLDEN1 Position */ +#define BPWM_CAPCTL_FCRLDEN1_Msk (0x1ul << BPWM_CAPCTL_FCRLDEN1_Pos) /*!< BPWM_T::CAPCTL: FCRLDEN1 Mask */ + +#define BPWM_CAPCTL_FCRLDEN2_Pos (26) /*!< BPWM_T::CAPCTL: FCRLDEN2 Position */ +#define BPWM_CAPCTL_FCRLDEN2_Msk (0x1ul << BPWM_CAPCTL_FCRLDEN2_Pos) /*!< BPWM_T::CAPCTL: FCRLDEN2 Mask */ + +#define BPWM_CAPCTL_FCRLDEN3_Pos (27) /*!< BPWM_T::CAPCTL: FCRLDEN3 Position */ +#define BPWM_CAPCTL_FCRLDEN3_Msk (0x1ul << BPWM_CAPCTL_FCRLDEN3_Pos) /*!< BPWM_T::CAPCTL: FCRLDEN3 Mask */ + +#define BPWM_CAPCTL_FCRLDEN4_Pos (28) /*!< BPWM_T::CAPCTL: FCRLDEN4 Position */ +#define BPWM_CAPCTL_FCRLDEN4_Msk (0x1ul << BPWM_CAPCTL_FCRLDEN4_Pos) /*!< BPWM_T::CAPCTL: FCRLDEN4 Mask */ + +#define BPWM_CAPCTL_FCRLDEN5_Pos (29) /*!< BPWM_T::CAPCTL: FCRLDEN5 Position */ +#define BPWM_CAPCTL_FCRLDEN5_Msk (0x1ul << BPWM_CAPCTL_FCRLDEN5_Pos) /*!< BPWM_T::CAPCTL: FCRLDEN5 Mask */ + +#define BPWM_CAPSTS_CRIFOV0_Pos (0) /*!< BPWM_T::CAPSTS: CRIFOV0 Position */ +#define BPWM_CAPSTS_CRIFOV0_Msk (0x1ul << BPWM_CAPSTS_CRIFOV0_Pos) /*!< BPWM_T::CAPSTS: CRIFOV0 Mask */ + +#define BPWM_CAPSTS_CRIFOV1_Pos (1) /*!< BPWM_T::CAPSTS: CRIFOV1 Position */ +#define BPWM_CAPSTS_CRIFOV1_Msk (0x1ul << BPWM_CAPSTS_CRIFOV1_Pos) /*!< BPWM_T::CAPSTS: CRIFOV1 Mask */ + +#define BPWM_CAPSTS_CRIFOV2_Pos (2) /*!< BPWM_T::CAPSTS: CRIFOV2 Position */ +#define BPWM_CAPSTS_CRIFOV2_Msk (0x1ul << BPWM_CAPSTS_CRIFOV2_Pos) /*!< BPWM_T::CAPSTS: CRIFOV2 Mask */ + +#define BPWM_CAPSTS_CRIFOV3_Pos (3) /*!< BPWM_T::CAPSTS: CRIFOV3 Position */ +#define BPWM_CAPSTS_CRIFOV3_Msk (0x1ul << BPWM_CAPSTS_CRIFOV3_Pos) /*!< BPWM_T::CAPSTS: CRIFOV3 Mask */ + +#define BPWM_CAPSTS_CRIFOV4_Pos (4) /*!< BPWM_T::CAPSTS: CRIFOV4 Position */ +#define BPWM_CAPSTS_CRIFOV4_Msk (0x1ul << BPWM_CAPSTS_CRIFOV4_Pos) /*!< BPWM_T::CAPSTS: CRIFOV4 Mask */ + +#define BPWM_CAPSTS_CRIFOV5_Pos (5) /*!< BPWM_T::CAPSTS: CRIFOV5 Position */ +#define BPWM_CAPSTS_CRIFOV5_Msk (0x1ul << BPWM_CAPSTS_CRIFOV5_Pos) /*!< BPWM_T::CAPSTS: CRIFOV5 Mask */ + +#define BPWM_CAPSTS_CFIFOV0_Pos (8) /*!< BPWM_T::CAPSTS: CFIFOV0 Position */ +#define BPWM_CAPSTS_CFIFOV0_Msk (0x1ul << BPWM_CAPSTS_CFIFOV0_Pos) /*!< BPWM_T::CAPSTS: CFIFOV0 Mask */ + +#define BPWM_CAPSTS_CFIFOV1_Pos (9) /*!< BPWM_T::CAPSTS: CFIFOV1 Position */ +#define BPWM_CAPSTS_CFIFOV1_Msk (0x1ul << BPWM_CAPSTS_CFIFOV1_Pos) /*!< BPWM_T::CAPSTS: CFIFOV1 Mask */ + +#define BPWM_CAPSTS_CFIFOV2_Pos (10) /*!< BPWM_T::CAPSTS: CFIFOV2 Position */ +#define BPWM_CAPSTS_CFIFOV2_Msk (0x1ul << BPWM_CAPSTS_CFIFOV2_Pos) /*!< BPWM_T::CAPSTS: CFIFOV2 Mask */ + +#define BPWM_CAPSTS_CFIFOV3_Pos (11) /*!< BPWM_T::CAPSTS: CFIFOV3 Position */ +#define BPWM_CAPSTS_CFIFOV3_Msk (0x1ul << BPWM_CAPSTS_CFIFOV3_Pos) /*!< BPWM_T::CAPSTS: CFIFOV3 Mask */ + +#define BPWM_CAPSTS_CFIFOV4_Pos (12) /*!< BPWM_T::CAPSTS: CFIFOV4 Position */ +#define BPWM_CAPSTS_CFIFOV4_Msk (0x1ul << BPWM_CAPSTS_CFIFOV4_Pos) /*!< BPWM_T::CAPSTS: CFIFOV4 Mask */ + +#define BPWM_CAPSTS_CFIFOV5_Pos (13) /*!< BPWM_T::CAPSTS: CFIFOV5 Position */ +#define BPWM_CAPSTS_CFIFOV5_Msk (0x1ul << BPWM_CAPSTS_CFIFOV5_Pos) /*!< BPWM_T::CAPSTS: CFIFOV5 Mask */ + +#define BPWM_RCAPDAT_RCAPDAT_Pos (0) /*!< BPWM_T::RCAPDAT: RCAPDAT Position */ +#define BPWM_RCAPDAT_RCAPDAT_Msk (0xfffful << BPWM_RCAPDAT_RCAPDAT_Pos) /*!< BPWM_T::RCAPDAT: RCAPDAT Mask */ + +#define BPWM_FCAPDAT_FCAPDAT_Pos (0) /*!< BPWM_T::FCAPDAT: FCAPDAT Position */ +#define BPWM_FCAPDAT_FCAPDAT_Msk (0xfffful << BPWM_FCAPDAT_FCAPDAT_Pos) /*!< BPWM_T::FCAPDAT: FCAPDAT Mask */ + +#define BPWM_RCAPDAT0_RCAPDAT_Pos (0) /*!< BPWM_T::RCAPDAT0: RCAPDAT Position */ +#define BPWM_RCAPDAT0_RCAPDAT_Msk (0xfffful << BPWM_RCAPDAT0_RCAPDAT_Pos) /*!< BPWM_T::RCAPDAT0: RCAPDAT Mask */ + +#define BPWM_FCAPDAT0_FCAPDAT_Pos (0) /*!< BPWM_T::FCAPDAT0: FCAPDAT Position */ +#define BPWM_FCAPDAT0_FCAPDAT_Msk (0xfffful << BPWM_FCAPDAT0_FCAPDAT_Pos) /*!< BPWM_T::FCAPDAT0: FCAPDAT Mask */ + +#define BPWM_RCAPDAT1_RCAPDAT_Pos (0) /*!< BPWM_T::RCAPDAT1: RCAPDAT Position */ +#define BPWM_RCAPDAT1_RCAPDAT_Msk (0xfffful << BPWM_RCAPDAT1_RCAPDAT_Pos) /*!< BPWM_T::RCAPDAT1: RCAPDAT Mask */ + +#define BPWM_FCAPDAT1_FCAPDAT_Pos (0) /*!< BPWM_T::FCAPDAT1: FCAPDAT Position */ +#define BPWM_FCAPDAT1_FCAPDAT_Msk (0xfffful << BPWM_FCAPDAT1_FCAPDAT_Pos) /*!< BPWM_T::FCAPDAT1: FCAPDAT Mask */ + +#define BPWM_RCAPDAT2_RCAPDAT_Pos (0) /*!< BPWM_T::RCAPDAT2: RCAPDAT Position */ +#define BPWM_RCAPDAT2_RCAPDAT_Msk (0xfffful << BPWM_RCAPDAT2_RCAPDAT_Pos) /*!< BPWM_T::RCAPDAT2: RCAPDAT Mask */ + +#define BPWM_FCAPDAT2_FCAPDAT_Pos (0) /*!< BPWM_T::FCAPDAT2: FCAPDAT Position */ +#define BPWM_FCAPDAT2_FCAPDAT_Msk (0xfffful << BPWM_FCAPDAT2_FCAPDAT_Pos) /*!< BPWM_T::FCAPDAT2: FCAPDAT Mask */ + +#define BPWM_RCAPDAT3_RCAPDAT_Pos (0) /*!< BPWM_T::RCAPDAT3: RCAPDAT Position */ +#define BPWM_RCAPDAT3_RCAPDAT_Msk (0xfffful << BPWM_RCAPDAT3_RCAPDAT_Pos) /*!< BPWM_T::RCAPDAT3: RCAPDAT Mask */ + +#define BPWM_FCAPDAT3_FCAPDAT_Pos (0) /*!< BPWM_T::FCAPDAT3: FCAPDAT Position */ +#define BPWM_FCAPDAT3_FCAPDAT_Msk (0xfffful << BPWM_FCAPDAT3_FCAPDAT_Pos) /*!< BPWM_T::FCAPDAT3: FCAPDAT Mask */ + +#define BPWM_RCAPDAT4_RCAPDAT_Pos (0) /*!< BPWM_T::RCAPDAT4: RCAPDAT Position */ +#define BPWM_RCAPDAT4_RCAPDAT_Msk (0xfffful << BPWM_RCAPDAT4_RCAPDAT_Pos) /*!< BPWM_T::RCAPDAT4: RCAPDAT Mask */ + +#define BPWM_FCAPDAT4_FCAPDAT_Pos (0) /*!< BPWM_T::FCAPDAT4: FCAPDAT Position */ +#define BPWM_FCAPDAT4_FCAPDAT_Msk (0xfffful << BPWM_FCAPDAT4_FCAPDAT_Pos) /*!< BPWM_T::FCAPDAT4: FCAPDAT Mask */ + +#define BPWM_RCAPDAT5_RCAPDAT_Pos (0) /*!< BPWM_T::RCAPDAT5: RCAPDAT Position */ +#define BPWM_RCAPDAT5_RCAPDAT_Msk (0xfffful << BPWM_RCAPDAT5_RCAPDAT_Pos) /*!< BPWM_T::RCAPDAT5: RCAPDAT Mask */ + +#define BPWM_FCAPDAT5_FCAPDAT_Pos (0) /*!< BPWM_T::FCAPDAT5: FCAPDAT Position */ +#define BPWM_FCAPDAT5_FCAPDAT_Msk (0xfffful << BPWM_FCAPDAT5_FCAPDAT_Pos) /*!< BPWM_T::FCAPDAT5: FCAPDAT Mask */ + +#define BPWM_CAPIEN_CAPRIENn_Pos (0) /*!< BPWM_T::CAPIEN: CAPRIENn Position */ +#define BPWM_CAPIEN_CAPRIENn_Msk (0x3ful << BPWM_CAPIEN_CAPRIENn_Pos) /*!< BPWM_T::CAPIEN: CAPRIENn Mask */ + +#define BPWM_CAPIEN_CAPFIENn_Pos (8) /*!< BPWM_T::CAPIEN: CAPFIENn Position */ +#define BPWM_CAPIEN_CAPFIENn_Msk (0x3ful << BPWM_CAPIEN_CAPFIENn_Pos) /*!< BPWM_T::CAPIEN: CAPFIENn Mask */ + +#define BPWM_CAPIF_CAPRIF0_Pos (0) /*!< BPWM_T::CAPIF: CAPRIF0 Position */ +#define BPWM_CAPIF_CAPRIF0_Msk (0x1ul << BPWM_CAPIF_CAPRIF0_Pos) /*!< BPWM_T::CAPIF: CAPRIF0 Mask */ + +#define BPWM_CAPIF_CAPRIF1_Pos (1) /*!< BPWM_T::CAPIF: CAPRIF1 Position */ +#define BPWM_CAPIF_CAPRIF1_Msk (0x1ul << BPWM_CAPIF_CAPRIF1_Pos) /*!< BPWM_T::CAPIF: CAPRIF1 Mask */ + +#define BPWM_CAPIF_CAPRIF2_Pos (2) /*!< BPWM_T::CAPIF: CAPRIF2 Position */ +#define BPWM_CAPIF_CAPRIF2_Msk (0x1ul << BPWM_CAPIF_CAPRIF2_Pos) /*!< BPWM_T::CAPIF: CAPRIF2 Mask */ + +#define BPWM_CAPIF_CAPRIF3_Pos (3) /*!< BPWM_T::CAPIF: CAPRIF3 Position */ +#define BPWM_CAPIF_CAPRIF3_Msk (0x1ul << BPWM_CAPIF_CAPRIF3_Pos) /*!< BPWM_T::CAPIF: CAPRIF3 Mask */ + +#define BPWM_CAPIF_CAPRIF4_Pos (4) /*!< BPWM_T::CAPIF: CAPRIF4 Position */ +#define BPWM_CAPIF_CAPRIF4_Msk (0x1ul << BPWM_CAPIF_CAPRIF4_Pos) /*!< BPWM_T::CAPIF: CAPRIF4 Mask */ + +#define BPWM_CAPIF_CAPRIF5_Pos (5) /*!< BPWM_T::CAPIF: CAPRIF5 Position */ +#define BPWM_CAPIF_CAPRIF5_Msk (0x1ul << BPWM_CAPIF_CAPRIF5_Pos) /*!< BPWM_T::CAPIF: CAPRIF5 Mask */ + +#define BPWM_CAPIF_CAPFIF0_Pos (8) /*!< BPWM_T::CAPIF: CAPFIF0 Position */ +#define BPWM_CAPIF_CAPFIF0_Msk (0x1ul << BPWM_CAPIF_CAPFIF0_Pos) /*!< BPWM_T::CAPIF: CAPFIF0 Mask */ + +#define BPWM_CAPIF_CAPFIF1_Pos (9) /*!< BPWM_T::CAPIF: CAPFIF1 Position */ +#define BPWM_CAPIF_CAPFIF1_Msk (0x1ul << BPWM_CAPIF_CAPFIF1_Pos) /*!< BPWM_T::CAPIF: CAPFIF1 Mask */ + +#define BPWM_CAPIF_CAPFIF2_Pos (10) /*!< BPWM_T::CAPIF: CAPFIF2 Position */ +#define BPWM_CAPIF_CAPFIF2_Msk (0x1ul << BPWM_CAPIF_CAPFIF2_Pos) /*!< BPWM_T::CAPIF: CAPFIF2 Mask */ + +#define BPWM_CAPIF_CAPFIF3_Pos (11) /*!< BPWM_T::CAPIF: CAPFIF3 Position */ +#define BPWM_CAPIF_CAPFIF3_Msk (0x1ul << BPWM_CAPIF_CAPFIF3_Pos) /*!< BPWM_T::CAPIF: CAPFIF3 Mask */ + +#define BPWM_CAPIF_CAPFIF4_Pos (12) /*!< BPWM_T::CAPIF: CAPFIF4 Position */ +#define BPWM_CAPIF_CAPFIF4_Msk (0x1ul << BPWM_CAPIF_CAPFIF4_Pos) /*!< BPWM_T::CAPIF: CAPFIF4 Mask */ + +#define BPWM_CAPIF_CAPFIF5_Pos (13) /*!< BPWM_T::CAPIF: CAPFIF5 Position */ +#define BPWM_CAPIF_CAPFIF5_Msk (0x1ul << BPWM_CAPIF_CAPFIF5_Pos) /*!< BPWM_T::CAPIF: CAPFIF5 Mask */ + +#define BPWM_PBUF_PBUF_Pos (0) /*!< BPWM_T::PBUF: PBUF Position */ +#define BPWM_PBUF_PBUF_Msk (0xfffful << BPWM_PBUF_PBUF_Pos) /*!< BPWM_T::PBUF: PBUF Mask */ + +#define BPWM_CMPBUF_CMPBUF_Pos (0) /*!< BPWM_T::CMPBUF0: CMPBUF Position */ +#define BPWM_CMPBUF_CMPBUF_Msk (0xfffful << BPWM_CMPBUFn_CMPBUF_Pos) /*!< BPWM_T::CMPBUF0: CMPBUF Mask */ + +#define BPWM_CMPBUF0_CMPBUF_Pos (0) /*!< BPWM_T::CMPBUF0: CMPBUF Position */ +#define BPWM_CMPBUF0_CMPBUF_Msk (0xfffful << BPWM_CMPBUF0_CMPBUF_Pos) /*!< BPWM_T::CMPBUF0: CMPBUF Mask */ + +#define BPWM_CMPBUF1_CMPBUF_Pos (0) /*!< BPWM_T::CMPBUF1: CMPBUF Position */ +#define BPWM_CMPBUF1_CMPBUF_Msk (0xfffful << BPWM_CMPBUF1_CMPBUF_Pos) /*!< BPWM_T::CMPBUF1: CMPBUF Mask */ + +#define BPWM_CMPBUF2_CMPBUF_Pos (0) /*!< BPWM_T::CMPBUF2: CMPBUF Position */ +#define BPWM_CMPBUF2_CMPBUF_Msk (0xfffful << BPWM_CMPBUF2_CMPBUF_Pos) /*!< BPWM_T::CMPBUF2: CMPBUF Mask */ + +#define BPWM_CMPBUF3_CMPBUF_Pos (0) /*!< BPWM_T::CMPBUF3: CMPBUF Position */ +#define BPWM_CMPBUF3_CMPBUF_Msk (0xfffful << BPWM_CMPBUF3_CMPBUF_Pos) /*!< BPWM_T::CMPBUF3: CMPBUF Mask */ + +#define BPWM_CMPBUF4_CMPBUF_Pos (0) /*!< BPWM_T::CMPBUF4: CMPBUF Position */ +#define BPWM_CMPBUF4_CMPBUF_Msk (0xfffful << BPWM_CMPBUF4_CMPBUF_Pos) /*!< BPWM_T::CMPBUF4: CMPBUF Mask */ + +#define BPWM_CMPBUF5_CMPBUF_Pos (0) /*!< BPWM_T::CMPBUF5: CMPBUF Position */ +#define BPWM_CMPBUF5_CMPBUF_Msk (0xfffful << BPWM_CMPBUF5_CMPBUF_Pos) /*!< BPWM_T::CMPBUF5: CMPBUF Mask */ + +/**@}*/ /* BPWM_CONST */ +/**@}*/ /* end of BPWM register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) + #pragma no_anon_unions +#endif + +#endif /* __BPWM_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/clk_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/clk_reg.h new file mode 100644 index 0000000000..ede4d17230 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/clk_reg.h @@ -0,0 +1,918 @@ +/**************************************************************************//** + * @file clk_reg.h + * @version V1.00 + * @brief CLK register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __CLK_REG_H__ +#define __CLK_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup CLK System Clock Controller (CLK) + Memory Mapped Structure for CLK Controller +@{ */ + +typedef struct +{ + + + /** + * @var CLK_T::PWRCTL + * Offset: 0x00 System Power-down Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |HXTEN |HXT Enable Bit (Write Protect) + * | | |0 = External high speed crystal (HXT) Disabled. + * | | |1 = External high speed crystal (HXT) Enabled. + * | | |Note1: Reset by power on reset. + * | | |Note2: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[1] |LXTEN |LXT Enable Bit (Write Protect) + * | | |0 = External low speed crystal (LXT) Disabled. + * | | |1 = External low speed crystal (LXT) Enabled. + * | | |Note1: Reset by RTC power on reset. + * | | |Note2: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[2] |HIRCEN |HIRC Enable Bit (Write Protect) + * | | |0 = Internal high speed RC oscillator (HIRC) Disabled. + * | | |1 = Internal high speed RC oscillator (HIRC) Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[3] |LIRCEN |LIRC Enable Bit (Write Protect) + * | | |0 = Internal low speed RC oscillator (LIRC) Disabled. + * | | |1 = Internal low speed RC oscillator (LIRC) Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[4] |PDWKDLY |Enable the Wake-up Delay Counter (Write Protect) + * | | |When the chip wakes up from Power-down mode, the clock control will delay certain clock cycles to wait system clock stable. + * | | |The delayed clock cycle is 4096 clock cycles when chip works at external high speed crystal oscillator (HXT), and 512 clock cycles when chip works at internal high speed RC oscillator (HIRC). + * | | |0 = Clock cycles delay Disabled. + * | | |1 = Clock cycles delay Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[5] |PDWKIEN |Power-down Mode Wake-up Interrupt Enable Bit (Write Protect) + * | | |0 = Power-down mode wake-up interrupt Disabled. + * | | |1 = Power-down mode wake-up interrupt Enabled. + * | | |Note1: The interrupt will occur when both PDWKIF and PDWKIEN are high. + * | | |Note2: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[6] |PDWKIF |Power-down Mode Wake-up Interrupt Status + * | | |Set by "Power-down wake-up event", it indicates that resume from Power-down mode. + * | | |The flag is set if any wake-up source is occurred. Refer Power Modes and Wake-up Sources chapter. + * | | |Note1: Write 1 to clear the bit to 0. + * | | |Note2: This bit works only if PDWKIEN (CLK_PWRCTL[5]) set to 1. + * |[7] |PDEN |System Power-down Enable (Write Protect) + * | | |When this bit is set to 1, Power-down mode is enabled and chip keeps active till the CPU sleep mode is also active and then the chip enters Power-down mode. + * | | |When chip wakes up from Power-down mode, this bit is auto cleared. Users need to set this bit again for next Power-down. + * | | |In Power-down mode, HXT and the HIRC will be disabled in this mode, but LXT and LIRC are not controlled by Power-down mode. + * | | |In Power-down mode, the PLL and system clock are disabled, and ignored the clock source selection. The clocks of peripheral are not controlled by Power-down mode, if the peripheral clock source is from LXT or LIRC. + * | | |0 = Chip operating normally or chip in idle mode because of WFI command. + * | | |1 = Chip enters Power-down mode instant or wait CPU sleep command WFI. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[13] |HXTTBEN |HXT Crystal TURBO Mode (Write Protect) + * | | |0 = HXT Crystal TURBO mode disabled. + * | | |1 = HXT Crystal TURBO mode enabled. + * | | |Note1: Reset by power on reset. + * | | |Note2: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[22:20] |HXTGAIN |HXT Gain Control Bit (Write Protect) + * | | |This is a protected register. Please refer to open lock sequence to program it. + * | | |Gain control is used to enlarge the gain of crystal to make sure crystal work normally. If gain control is enabled, crystal will consume more power than gain control off. + * | | |000 = HXT frequency is lower than from 4 MHz. + * | | |001 = HXT frequency is from 4 MHz to 8 MHz. + * | | |010 = HXT frequency is from 8 MHz to 12 MHz. + * | | |011 = HXT frequency is from 12 MHz to 16 MHz. + * | | |100 = HXT frequency is from 16 MHz to 24 MHz. + * | | |111 = HXT frequency is from 24 MHz to 32 MHz. + * | | |Others: Reserved + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[24] |LXTSELXT |LXT Mode Selection + * | | |0 = LXT work as crystal mode. PF.4 and PF.5 are configured as external low speed crystal (LXT) pins. + * | | |1 = LXT work as external clock mode. PF.5 is configured as external clock input pin. + * | | |Note1: When LXTSELXT = 1, PF.5 MFP should be setting as GPIO mode. The DC characteristic of X32_IN is the same as GPIO. + * | | |Note2: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[26:25] |LXTGAIN |LXT Gain Control Bit (Write Protect) + * | | |00 = LXT Crystal ESR = 35K, CL=12.5pFReserved. + * | | |10 = LXT Crystal ESR = 70K, CL=12.5pFReserved. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * @var CLK_T::AHBCLK + * Offset: 0x04 AHB Devices Clock Enable Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |PDMACKEN |PDMA Controller Clock Enable Bit + * | | |0 = PDMA peripheral clock Disabled. + * | | |1 = PDMA peripheral clock Enabled. + * |[2] |ISPCKEN |Flash ISP Controller Clock Enable Bit + * | | |0 = Flash ISP peripheral clock Disabled. + * | | |1 = Flash ISP peripheral clock Enabled. + * |[3] |EBICKEN |EBI Controller Clock Enable Bit + * | | |0 = EBI peripheral clock Disabled. + * | | |1 = EBI peripheral clock Enabled.Reserved. + * |[4] |HDIVCKEN |HDIV Controller Clock Enable Bit + * | | |0 = HDIV peripheral clock Disabled. + * | | |1 = HDIV peripheral clock Enabled.Reserved. + * |[7] |CRCCKEN |CRC Generator Controller Clock Enable Bit + * | | |0 = CRC peripheral clock Disabled. + * | | |1 = CRC peripheral clock Enabled. + * @var CLK_T::APBCLK0 + * Offset: 0x08 APB Devices Clock Enable Control Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WDTCKEN |Watchdog Timer Clock Enable Bit (Write Protect) + * | | |0 = Watchdog timer clock Disabled. + * | | |1 = Watchdog timer clock Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. Reserved. + * | | |Note: Reset by power on reset or watch dog reset or software chip reset. + * |[2] |TMR0CKEN |Timer0 Clock Enable Bit + * | | |0 = Timer0 clock Disabled. + * | | |1 = Timer0 clock Enabled. + * |[3] |TMR1CKEN |Timer1 Clock Enable Bit + * | | |0 = Timer1 clock Disabled. + * | | |1 = Timer1 clock Enabled. + * |[4] |TMR2CKEN |Timer2 Clock Enable Bit + * | | |0 = Timer2 clock Disabled. + * | | |1 = Timer2 clock Enabled. + * |[5] |TMR3CKEN |Timer3 Clock Enable Bit + * | | |0 = Timer3 clock Disabled. + * | | |1 = Timer3 clock Enabled. + * |[6] |CLKOCKEN |CLKO Clock Enable Bit + * | | |0 = CLKO clock Disabled. + * | | |1 = CLKO clock Enabled. + * |[7] |ACMP01CKEN|Analog Comparator 0/1 Clock Enable Bit + * | | |0 = Analog comparator 0/1 clock Disabled. + * | | |1 = Analog comparator 0/1 clock Enabled. + * |[8] |I2C0CKEN |I2C0 Clock Enable Bit + * | | |0 = I2C0 clock Disabled. + * | | |1 = I2C0 clock Enabled. + * |[9] |I2C1CKEN |I2C1 Clock Enable Bit + * | | |0 = I2C1 clock Disabled. + * | | |1 = I2C1 clock Enabled. + * |[13] |SPI0CKEN |SPI0 Clock Enable Bit + * | | |0 = SPI0 clock Disabled. + * | | |1 = SPI0 clock Enabled. + * |[16] |UART0CKEN |UART0 Clock Enable Bit + * | | |0 = UART0 clock Disabled. + * | | |1 = UART0 clock Enabled. + * |[17] |UART1CKEN |UART1 Clock Enable Bit + * | | |0 = UART1 clock Disabled. + * | | |1 = UART1 clock Enabled. + * |[18] |UART2CKEN |UART2 Clock Enable Bit + * | | |0 = UART2 clock Disabled. + * | | |1 = UART2 clock Enabled. + * |[27] |USBDCKEN |USB Device Clock Enable Bit + * | | |0 = USB Device clock Disabled. + * | | |1 = USB Device clock Enabled.Reserved. + * |[28] |ADCCKEN |Analog-digital-converter (ADC) Clock Enable Bit + * | | |0 = ADC clock Disabled. + * | | |1 = ADC clock Enabled.Reserved. + * @var CLK_T::APBCLK1 + * Offset: 0x0C APB Devices Clock Enable Control Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8] |USCI0CKEN |USCI0 Clock Enable Bit + * | | |0 = USCI0 clock Disabled. + * | | |1 = USCI0 clock Enabled. + * |[16] |PWM0CKEN |PWM0 Clock Enable Bit + * | | |0 = PWM0 clock Disabled. + * | | |1 = PWM0 clock Enabled. + * |[17] |PWM1CKEN |PWM1 Clock Enable Bit + * | | |0 = PWM1 clock Disabled. + * | | |1 = PWM1 clock Enabled. + * @var CLK_T::CLKSEL0 + * Offset: 0x10 Clock Source Select Control Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |HCLKSEL |HCLK Clock Source Selection (Write Protect) + * | | |Before clock switching, the related clock sources (both pre-select and new-select) must be turned on. + * | | |000 = Clock source from HXT. + * | | |001 = Clock source from LXT. + * | | |010 = Clock source from PLL. (M031_E/M032_E/M031_D only) + * | | | = Clock source from HIRC. (M031_C/B only) + * | | |011 = Clock source from LIRC. + * | | |111= Clock source from HIRC. + * | | |Other = Reserved. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * | | |Note: Reset by power on reset. + * |[5:3] |STCLKSEL |Cortex-M0 SysTick Clock Source Selection (Write Protect) + * | | |If SYST_CTRL[2]=0, SysTick uses listed clock source below. + * | | |000 = Clock source from HXT. + * | | |001 = Clock source from LXT. + * | | |010 = Clock source from HXT/2. + * | | |011 = Clock source from HCLK/2. + * | | |111 = Clock source from HIRC/2. + * | | |Other = Reserved. + * | | |Note: if SysTick clock source is not from HCLK (i.e. SYST_CTRL[2] = 0), SysTick clock source must less than or equal to HCLK/2. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[8] |USBDSEL |USB Device Clock Source Selection (Write Protect) + * | | |These bits are protected bit. It means programming this bit needs to write "59h", "16h", "88h" to address 0x4000_0100 to disable register protection. Refer to the register REGWRPROT at address GCR_BA+0x100. + * | | |0 = Clock source from HIRC. + * | | |1 = Clock source from PLL divided. (M031_E/M032_E only) + * | | | = Clock source from HIRC. (M031_D/C/B only) + * @var CLK_T::CLKSEL1 + * Offset: 0x14 Clock Source Select Control Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |WDTSEL |Watchdog Timer Clock Source Selection (Write Protect) + * | | |00 = Reserved. + * | | |01 = Clock source from external low speed crystal oscillator (LXT). + * | | |10 = Clock source from HCLK/2048. + * | | |11 = Clock source from internal low speed RC oscillator (LIRC). + * | | |Note1: This bit is write protected. Refer to the SYS_REGLCTL register. + * | | |Note2: Will be forced to 11 when CONFIG0[31], CONFIG0[4], CONFIG0[3] are all ones. + * |[3:2] |WWDTSEL |Window Watchdog Timer Clock Source Selection (Write Protect) + * | | |10 = Clock source from HCLK/2048. + * | | |11 = Clock source from internal low speed RC oscillator (LIRC). + * | | |Others = Reserved. + * |[6:4] |CLKOSEL |Clock Divider Clock Source Selection + * | | |000 = Clock source from external high speed crystal oscillator (HXT). + * | | |001 = Clock source from external low speed crystal oscillator (LXT). + * | | |010 = Clock source from HCLK. + * | | |011 = Clock source from internal high speed RC oscillator (HIRC). + * | | |100 = Clock source from internal low speed RC oscillator (LIRC). + * | | |101 = Clock source from internal high speed RC oscillator (HIRC). + * | | |110 = Clock source from PLL. (M031_E/D only). + * | | | = Clock source from internal high speed RC oscillator (HIRC). (M031_C/B only). + * |[10:8] |TMR0SEL |TIMER0 Clock Source Selection + * | | |000 = Clock source from external high speed crystal oscillator (HXT). + * | | |001 = Clock source from external low speed crystal oscillator (LXT). + * | | |010 = Clock source from PCLK0. + * | | |011 = Clock source from external clock T0 pin. + * | | |101 = Clock source from internal low speed RC oscillator (LIRC). + * | | |111 = Clock source from internal high speed RC oscillator (HIRC). + * | | |Others = Reserved. + * |[14:12] |TMR1SEL |TIMER1 Clock Source Selection + * | | |000 = Clock source from external high speed crystal oscillator (HXT). + * | | |001 = Clock source from external low speed crystal oscillator (LXT). + * | | |010 = Clock source from PCLK0. + * | | |011 = Clock source from external clock T1 pin. + * | | |101 = Clock source from internal low speed RC oscillator (LIRC). + * | | |111 = Clock source from internal high speed RC oscillator (HIRC). + * | | |Others = Reserved. + * |[18:16] |TMR2SEL |TIMER2 Clock Source Selection + * | | |000 = Clock source from external high speed crystal oscillator (HXT). + * | | |001 = Clock source from external low speed crystal oscillator (LXT). + * | | |010 = Clock source from PCLK1. + * | | |011 = Clock source from external clock T2 pin. + * | | |101 = Clock source from internal low speed RC oscillator (LIRC). + * | | |111 = Clock source from internal high speed RC oscillator (HIRC). + * | | |Others = Reserved. + * |[22:20] |TMR3SEL |TIMER3 Clock Source Selection + * | | |000 = Clock source from external high speed crystal oscillator (HXT). + * | | |001 = Clock source from external low speed crystal oscillator (LXT). + * | | |010 = Clock source from PCLK1. + * | | |011 = Clock source from external clock T3 pin. + * | | |101 = Clock source from internal low speed RC oscillator (LIRC). + * | | |111 = Clock source from internal high speed RC oscillator (HIRC). + * | | |Others = Reserved. + * |[26:24] |UART0SEL |UART0 Clock Source Selection + * | | |000 = Clock source from external high speed crystal oscillator (HXT). + * | | |001 = Clock source from PLL. (M031_E/D only) + * | | | = Clock source from PCLK0. (M031_C/B only). + * | | |010 = Clock source from external low speed crystal oscillator (LXT). + * | | |011 = Clock source from internal high speed RC oscillator (HIRC). + * | | |100 = Clock source from PCLK0. + * | | |Other = Reserved. + * |[30:28] |UART1SEL |UART1 Clock Source Selection + * | | |000 = Clock source from external high speed crystal oscillator (HXT). + * | | |001 = Clock source from PLL. (M031_E/D only) + * | | | = Clock source from PCLK1. (M031_C/B only). + * | | |010 = Clock source from external low speed crystal oscillator (LXT). + * | | |011 = Clock source from internal high speed RC oscillator (HIRC). + * | | |100 = Clock source from PCLK1. + * | | |Other = Reserved. + * @var CLK_T::CLKSEL2 + * Offset: 0x18 Clock Source Select Control Register 2 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |PWM0SEL |PWM0 Clock Source Selection + * | | |The peripheral clock source of PWM0 is defined by PWM0SEL. + * | | |0 = Clock source from PLL. (M031_E/D only) + * | | | = Clock source from PCLK0. (M031_C/B only). + * | | |1 = Clock source from PCLK0. + * |[1] |PWM1SEL |PWM1 Clock Source Selection + * | | |The peripheral clock source of PWM1 is defined by PWM1SEL. + * | | |0 = Clock source from PLL. (M031_E/D only) + * | | | = Clock source from PCLK1. (M031_C/B only). + * | | |1 = Clock source from PCLK1. + * |[5:4] |SPI0SEL |SPI0 Clock Source Selection + * | | |00 = Clock source from external high speed crystal oscillator (HXT). + * | | |01 = Clock source from PLL. (M031_E/D only) + * | | | = Clock source from PCLK1. (M031_C/B only). + * | | |10 = Clock source from PCLK1. + * | | |11 = Clock source from internal high speed RC oscillator (HIRC). + * |[21:20] |ADCSEL |ADC Clock Source Selection + * | | |00 = Clock source from external high speed crystal oscillator (HXT) clock. + * | | |01 = Clock source from PLL. (M031_E/D only) + * | | | = Clock source from PCLK1. (M031_C/B only). + * | | |10 = Clock source from PCLK1. + * | | |11 = Clock source from internal high speed RC oscillator (HIRC) clock. + * @var CLK_T::CLKSEL3 + * Offset: 0x1C Clock Source Select Control Register 3 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[26:24] |UART2SEL |UART2 Clock Source Selection + * | | |000 = Clock source from external high speed crystal oscillator (HXT). + * | | |001 = Clock source from PLL. (M031_E/D only) + * | | | = Clock source from PCLK0. (M031_C/B only). + * | | |010 = Clock source from external low speed crystal oscillator (LXT). + * | | |011 = Clock source from internal high speed RC oscillator (HIRC). + * | | |100 = Clock source from PCLK0. + * | | |Other = Reserved. + * @var CLK_T::CLKDIV0 + * Offset: 0x20 Clock Divider Number Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |HCLKDIV |HCLK Clock Divide Number From HCLK Clock Source + * | | |HCLK clock frequency = (HCLK clock source frequency) / (HCLKDIV + 1). + * |[7:4] |USBDIV |USB Clock Divide Number From PLL Clock + * | | |USB clock frequency = (PLL frequency) / (USBDIV + 1). + * |[11:8] |UART0DIV |UART0 Clock Divide Number From UART0 Clock Source + * | | |UART0 clock frequency = (UART0 clock source frequency) / (UART0DIV + 1). + * |[15:12] |UART1DIV |UART1 Clock Divide Number From UART1 Clock Source + * | | |UART1 clock frequency = (UART1 clock source frequency) / (UART1DIV + 1). + * |[23:16] |ADCDIV |ADC Clock Divide Number From ADC Clock Source + * | | |ADC clock frequency = (ADC clock source frequency) / (ADCDIV + 1). + * @var CLK_T::CLKDIV4 + * Offset: 0x30 Clock Divider Number Register 4 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |UART2DIV |UART2 Clock Divide Number From UART2 Clock Source + * | | |UART2 clock frequency = (UART2 clock source frequency) / (UART2DIV + 1). + * @var CLK_T::PCLKDIV + * Offset: 0x34 APB Clock Divider Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |APB0DIV |APB0 Clock DIvider + * | | |APB0 clock can be divided from HCLK. + * | | |000 = PCLK0 = HCLK. + * | | |001 = PCLK0 = 1/2 HCLK. + * | | |010 = PCLK0 = 1/4 HCLK. + * | | |011 = PCLK0 = 1/8 HCLK. + * | | |100 = PCLK0 = 1/16 HCLK. + * | | |Others = Reserved. + * |[6:4] |APB1DIV |APB1 Clock DIvider + * | | |APB1 clock can be divided from HCLK. + * | | |000 = PCLK1 = HCLK. + * | | |001 = PCLK1 = 1/2 HCLK. + * | | |010 = PCLK1 = 1/4 HCLK. + * | | |011 = PCLK1 = 1/8 HCLK. + * | | |100 = PCLK1 = 1/16 HCLK. + * | | |Others = Reserved. + * @var CLK_T::PLLCTL + * Offset: 0x40 PLL Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |FBDIV |PLL Feedback Divider Control (Write Protect) + * | | |Refer to the formulas below the table. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[13:9] |INDIV |PLL Input Divider Control (Write Protect) + * | | |Refer to the formulas below the table. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[15:14] |OUTDIV |PLL Output Divider Control (Write Protect) + * | | |Refer to the formulas below the table. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[16] |PD |Power-down Mode (Write Protect) + * | | |If set the PDEN bit to 1 in CLK_PWRCTL register, the PLL will enter Power-down mode, too. + * | | |0 = PLL is in normal mode. + * | | |1 = PLL is in Power-down mode (default). + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[17] |BP |PLL Bypass Control (Write Protect) + * | | |0 = PLL is in normal mode (default). + * | | |1 = PLL clock output is same as PLL input clock FIN. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[18] |OE |PLL OE (FOUT Enable) Pin Control (Write Protect) + * | | |0 = PLL FOUT Enabled. + * | | |1 = PLL FOUT is fixed low. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[19] |PLLSRC |PLL Source Clock Selection (Write Protect) + * | | |0 = PLL source clock from external high-speed crystal oscillator (HXT). + * | | |1 = PLL source clock from 48 MHz internal high-speed oscillator (HIRC/4). + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[23] |STBSEL |PLL Stable Counter Selection (Write Protect) + * | | |0 = PLL stable time is 6144 PLL source clock (suitable for source clock is equal to or less than 12 MHz). + * | | |1 = PLL stable time is 16128 PLL source clock (suitable for source clock is larger than 12 MHz). + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * @var CLK_T::STATUS + * Offset: 0x50 Clock Status Monitor Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |HXTSTB |HXT Clock Source Stable Flag (Read Only) + * | | |0 = External high speed crystal oscillator (HXT) clock is not stable or disabled. + * | | |1 = External high speed crystal oscillator (HXT) clock is stable and enabled. + * |[1] |LXTSTB |LXT Clock Source Stable Flag (Read Only) + * | | |0 = External low speed crystal oscillator (LXT) clock is not stable or disabled. + * | | |1 = External low speed crystal oscillator (LXT) clock is stabled and enabled. + * |[2] |PLLSTB |Internal PLL Clock Source Stable Flag (Read Only) + * | | |0 = Internal PLL clock is not stable or disabled. + * | | |1 = Internal PLL clock is stable and enabled. + * | | |Reserved. (M031_C/B only) + * |[3] |LIRCSTB |LIRC Clock Source Stable Flag (Read Only) + * | | |0 = Internal low speed RC oscillator (LIRC) clock is not stable or disabled. + * | | |1 = Internal low speed RC oscillator (LIRC) clock is stable and enabled. + * |[4] |HIRCSTB |HIRC Clock Source Stable Flag (Read Only) + * | | |0 = Internal high speed RC oscillator (HIRC) clock is not stable or disabled. + * | | |1 = Internal high speed RC oscillator (HIRC) clock is stable and enabled. + * |[7] |CLKSFAIL |Clock Switching Fail Flag (Read Only) + * | | |This bit is updated when software switches system clock source. If switch target clock is stable, this bit will be set to 0. If switch target clock is not stable, this bit will be set to 1. + * | | |0 = Clock switching success. + * | | |1 = Clock switching failure. + * | | |Note: Write 1 to clear the bit to 0. + * @var CLK_T::CLKOCTL + * Offset: 0x60 Clock Output Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |FREQSEL |Clock Output Frequency Selection + * | | |The formula of output frequency is + * | | |Fout = Fin/(2^(N+1)). + * | | |Fin is the input clock frequency. + * | | |Fout is the frequency of divider output clock. + * | | |N is the 4-bit value of FREQSEL[3:0]. + * |[4] |CLKOEN |Clock Output Enable Bit + * | | |0 = Clock Output function Disabled. + * | | |1 = Clock Output function Enabled. + * |[5] |DIV1EN |Clock Output Divide One Enable Bit + * | | |0 = Clock Output will output clock with source frequency divided by FREQSEL. + * | | |1 = Clock Output will output clock with source frequency. + * @var CLK_T::CLKDCTL + * Offset: 0x70 Clock Fail Detector Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[4] |HXTFDEN |HXT Clock Fail Detector Enable Bit + * | | |0 = External high speed crystal oscillator (HXT) clock fail detector Disabled. + * | | |1 = External high speed crystal oscillator (HXT) clock fail detector Enabled. + * |[5] |HXTFIEN |HXT Clock Fail Interrupt Enable Bit + * | | |0 = External high speed crystal oscillator (HXT) clock fail interrupt Disabled. + * | | |1 = External high speed crystal oscillator (HXT) clock fail interrupt Enabled. + * |[12] |LXTFDEN |LXT Clock Fail Detector Enable Bit + * | | |0 = External low speed crystal oscillator (LXT) clock fail detector Disabled. + * | | |1 = External low speed crystal oscillator (LXT) clock fail detector Enabled. + * |[13] |LXTFIEN |LXT Clock Fail Interrupt Enable Bit + * | | |0 = External low speed crystal oscillator (LXT) clock fail interrupt Disabled. + * | | |1 = External low speed crystal oscillator (LXT) clock fail interrupt Enabled. + * |[16] |HXTFQDEN |HXT Clock Frequency Range Detector Enable Bit + * | | |0 = External high speed crystal oscillator (HXT) clock frequency range detector Disabled. + * | | |1 = External high speed crystal oscillator (HXT) clock frequency range detector Enabled. + * |[17] |HXTFQIEN |HXT Clock Frequency Range Detector Interrupt Enable Bit + * | | |0 = External high speed crystal oscillator (HXT) clock frequency range detector fail interrupt Disabled. + * | | |1 = External high speed crystal oscillator (HXT) clock frequency range detector fail interrupt Enabled. + * @var CLK_T::CLKDSTS + * Offset: 0x74 Clock Fail Detector Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |HXTFIF |HXT Clock Fail Interrupt Flag (Write Protect) + * | | |0 = External high speed crystal oscillator (HXT) clock is normal. + * | | |1 = External high speed crystal oscillator (HXT) clock stops. + * | | |Note: Write 1 to clear the bit to 0. + * |[1] |LXTFIF |LXT Clock Fail Interrupt Flag (Write Protect) + * | | |0 = External low speed crystal oscillator (LXT) clock is normal. + * | | |1 = External low speed crystal oscillator (LXT) stops. + * | | |Note: Write 1 to clear the bit to 0. + * |[8] |HXTFQIF |HXT Clock Frequency Range Detector Interrupt Flag (Write Protect) + * | | |0 = External high speed crystal oscillator (HXT) clock frequency is normal. + * | | |1 = External high speed crystal oscillator (HXT) clock frequency is abnormal. + * | | |Note: Write 1 to clear the bit to 0. + * @var CLK_T::CDUPB + * Offset: 0x78 Clock Frequency Range Detector Upper Boundary Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[9:0] |UPERBD |HXT Clock Frequency Range Detector Upper Boundary Value + * | | |The bits define the maximum value of frequency range detector window. + * | | |When HXT frequency higher than this maximum frequency value, the HXT Clock Frequency Range Detector Interrupt Flag will set to 1. + * @var CLK_T::CDLOWB + * Offset: 0x7C Clock Frequency Range Detector Lower Boundary Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[9:0] |LOWERBD |HXT Clock Frequency Range Detector Lower Boundary Value + * | | |The bits define the minimum value of frequency range detector window. + * | | |When HXT frequency lower than this minimum frequency value, the HXT Clock Frequency Range Detector Interrupt Flag will set to 1. + * @var CLK_T::HXTFSEL + * Offset: 0xB4 HXT Filter Select Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |HXTFSEL |HXT Filter Select + * | | |0 = HXT frequency is > 12MHz. + * | | |1 = HXT frequency is <= 12MHz. + * | | |Note: This bit should not be changed during HXT is running. + */ + __IO uint32_t PWRCTL; /*!< [0x0000] System Power-down Control Register */ + __IO uint32_t AHBCLK; /*!< [0x0004] AHB Devices Clock Enable Control Register */ + __IO uint32_t APBCLK0; /*!< [0x0008] APB Devices Clock Enable Control Register 0 */ + __IO uint32_t APBCLK1; /*!< [0x000c] APB Devices Clock Enable Control Register 1 */ + __IO uint32_t CLKSEL0; /*!< [0x0010] Clock Source Select Control Register 0 */ + __IO uint32_t CLKSEL1; /*!< [0x0014] Clock Source Select Control Register 1 */ + __IO uint32_t CLKSEL2; /*!< [0x0018] Clock Source Select Control Register 2 */ + __IO uint32_t CLKSEL3; /*!< [0x001c] Clock Source Select Control Register 3 */ + __IO uint32_t CLKDIV0; /*!< [0x0020] Clock Divider Number Register 0 */ + __I uint32_t RESERVE0[3]; + __IO uint32_t CLKDIV4; /*!< [0x0030] Clock Divider Number Register 4 */ + __IO uint32_t PCLKDIV; /*!< [0x0034] APB Clock Divider Register */ + __I uint32_t RESERVE1[2]; + __IO uint32_t PLLCTL; /*!< [0x0040] PLL Control Register */ + __I uint32_t RESERVE2[3]; + __I uint32_t STATUS; /*!< [0x0050] Clock Status Monitor Register */ + __I uint32_t RESERVE3[3]; + __IO uint32_t CLKOCTL; /*!< [0x0060] Clock Output Control Register */ + __I uint32_t RESERVE4[3]; + __IO uint32_t CLKDCTL; /*!< [0x0070] Clock Fail Detector Control Register */ + __IO uint32_t CLKDSTS; /*!< [0x0074] Clock Fail Detector Status Register */ + __IO uint32_t CDUPB; /*!< [0x0078] Clock Frequency Range Detector Upper Boundary Register */ + __IO uint32_t CDLOWB; /*!< [0x007c] Clock Frequency Range Detector Lower Boundary Register */ + __IO uint32_t LDOCTL; /*!< [0x0080] LDO Control Register */ + __I uint32_t RESERVE5[12]; + __IO uint32_t HXTFSEL; /*!< [0x00b4] HXT Filter Select Control Register */ + __I uint32_t RESERVE9[14]; + __IO uint32_t TESTCLK; /*!< [0x00f0] Test Clock Control Register */ + +} CLK_T; + +/** + @addtogroup CLK_CONST CLK Bit Field Definition + Constant Definitions for CLK Controller +@{ */ + +#define CLK_PWRCTL_HXTEN_Pos (0) /*!< CLK_T::PWRCTL: HXTEN Position */ +#define CLK_PWRCTL_HXTEN_Msk (0x1ul << CLK_PWRCTL_HXTEN_Pos) /*!< CLK_T::PWRCTL: HXTEN Mask */ + +#define CLK_PWRCTL_LXTEN_Pos (1) /*!< CLK_T::PWRCTL: LXTEN Position */ +#define CLK_PWRCTL_LXTEN_Msk (0x1ul << CLK_PWRCTL_LXTEN_Pos) /*!< CLK_T::PWRCTL: LXTEN Mask */ + +#define CLK_PWRCTL_HIRCEN_Pos (2) /*!< CLK_T::PWRCTL: HIRCEN Position */ +#define CLK_PWRCTL_HIRCEN_Msk (0x1ul << CLK_PWRCTL_HIRCEN_Pos) /*!< CLK_T::PWRCTL: HIRCEN Mask */ + +#define CLK_PWRCTL_LIRCEN_Pos (3) /*!< CLK_T::PWRCTL: LIRCEN Position */ +#define CLK_PWRCTL_LIRCEN_Msk (0x1ul << CLK_PWRCTL_LIRCEN_Pos) /*!< CLK_T::PWRCTL: LIRCEN Mask */ + +#define CLK_PWRCTL_PDWKDLY_Pos (4) /*!< CLK_T::PWRCTL: PDWKDLY Position */ +#define CLK_PWRCTL_PDWKDLY_Msk (0x1ul << CLK_PWRCTL_PDWKDLY_Pos) /*!< CLK_T::PWRCTL: PDWKDLY Mask */ + +#define CLK_PWRCTL_PDWKIEN_Pos (5) /*!< CLK_T::PWRCTL: PDWKIEN Position */ +#define CLK_PWRCTL_PDWKIEN_Msk (0x1ul << CLK_PWRCTL_PDWKIEN_Pos) /*!< CLK_T::PWRCTL: PDWKIEN Mask */ + +#define CLK_PWRCTL_PDWKIF_Pos (6) /*!< CLK_T::PWRCTL: PDWKIF Position */ +#define CLK_PWRCTL_PDWKIF_Msk (0x1ul << CLK_PWRCTL_PDWKIF_Pos) /*!< CLK_T::PWRCTL: PDWKIF Mask */ + +#define CLK_PWRCTL_PDEN_Pos (7) /*!< CLK_T::PWRCTL: PDEN Position */ +#define CLK_PWRCTL_PDEN_Msk (0x1ul << CLK_PWRCTL_PDEN_Pos) /*!< CLK_T::PWRCTL: PDEN Mask */ + +#define CLK_PWRCTL_DBPDEN_Pos (9) /*!< CLK_T::PWRCTL: DBPDEN Position */ +#define CLK_PWRCTL_DBPDEN_Msk (0x1ul << CLK_PWRCTL_DBPDEN_Pos) /*!< CLK_T::PWRCTL: DBPDEN Mask */ + +#define CLK_PWRCTL_HXTTBEN_Pos (13) /*!< CLK_T::PWRCTL: HXTTBEN Position */ +#define CLK_PWRCTL_HXTTBEN_Msk (0x1ul << CLK_PWRCTL_HXTTBEN_Pos) /*!< CLK_T::PWRCTL: HXTTBEN Mask */ + +#define CLK_PWRCTL_HIRCSTBS_Pos (16) /*!< CLK_T::PWRCTL: HIRCSTBS Position */ +#define CLK_PWRCTL_HIRCSTBS_Msk (0x3ul << CLK_PWRCTL_HIRCSTBS_Pos) /*!< CLK_T::PWRCTL: HIRCSTBS Mask */ + +#define CLK_PWRCTL_HXTGAIN_Pos (20) /*!< CLK_T::PWRCTL: HXTGAIN Position */ +#define CLK_PWRCTL_HXTGAIN_Msk (0x7ul << CLK_PWRCTL_HXTGAIN_Pos) /*!< CLK_T::PWRCTL: HXTGAIN Mask */ + +#define CLK_PWRCTL_LXTSELXT_Pos (24) /*!< CLK_T::PWRCTL: LXTSELXT Position */ +#define CLK_PWRCTL_LXTSELXT_Msk (0x1ul << CLK_PWRCTL_LXTSELXT_Pos) /*!< CLK_T::PWRCTL: LXTSELXT Mask */ + +#define CLK_PWRCTL_LXTGAIN_Pos (25) /*!< CLK_T::PWRCTL: LXTGAIN Position */ +#define CLK_PWRCTL_LXTGAIN_Msk (0x3ul << CLK_PWRCTL_LXTGAIN_Pos) /*!< CLK_T::PWRCTL: LXTGAIN Mask */ + +#define CLK_PWRCTL_LXTSTBS_Pos (30) /*!< CLK_T::PWRCTL: LXTSTBS Position */ +#define CLK_PWRCTL_LXTSTBS_Msk (0x1ul << CLK_PWRCTL_LXTSTBS_Pos) /*!< CLK_T::PWRCTL: LXTSTBS Mask */ + +#define CLK_PWRCTL_LXTTBEN_Pos (31) /*!< CLK_T::PWRCTL: LXTTBEN Position */ +#define CLK_PWRCTL_LXTTBEN_Msk (0x1ul << CLK_PWRCTL_LXTTBEN_Pos) /*!< CLK_T::PWRCTL: LXTTBEN Mask */ + +#define CLK_AHBCLK_PDMACKEN_Pos (1) /*!< CLK_T::AHBCLK: PDMACKEN Position */ +#define CLK_AHBCLK_PDMACKEN_Msk (0x1ul << CLK_AHBCLK_PDMACKEN_Pos) /*!< CLK_T::AHBCLK: PDMACKEN Mask */ + +#define CLK_AHBCLK_ISPCKEN_Pos (2) /*!< CLK_T::AHBCLK: ISPCKEN Position */ +#define CLK_AHBCLK_ISPCKEN_Msk (0x1ul << CLK_AHBCLK_ISPCKEN_Pos) /*!< CLK_T::AHBCLK: ISPCKEN Mask */ + +#define CLK_AHBCLK_EBICKEN_Pos (3) /*!< CLK_T::AHBCLK: EBICKEN Position */ +#define CLK_AHBCLK_EBICKEN_Msk (0x1ul << CLK_AHBCLK_EBICKEN_Pos) /*!< CLK_T::AHBCLK: EBICKEN Mask */ + +#define CLK_AHBCLK_HDIVCKEN_Pos (4) /*!< CLK_T::AHBCLK: HDIVCKEN Position */ +#define CLK_AHBCLK_HDIVCKEN_Msk (0x1ul << CLK_AHBCLK_HDIVCKEN_Pos) /*!< CLK_T::AHBCLK: HDIVCKEN Mask */ + +#define CLK_AHBCLK_CRCCKEN_Pos (7) /*!< CLK_T::AHBCLK: CRCCKEN Position */ +#define CLK_AHBCLK_CRCCKEN_Msk (0x1ul << CLK_AHBCLK_CRCCKEN_Pos) /*!< CLK_T::AHBCLK: CRCCKEN Mask */ + +#define CLK_AHBCLK_SRAM0IDLE_Pos (20) /*!< CLK_T::AHBCLK: SRAM0IDLE Position */ +#define CLK_AHBCLK_SRAM0IDLE_Msk (0x1ul << CLK_AHBCLK_SRAM0IDLE_Pos) /*!< CLK_T::AHBCLK: SRAM0IDLE Mask */ + +#define CLK_APBCLK0_WDTCKEN_Pos (0) /*!< CLK_T::APBCLK0: WDTCKEN Position */ +#define CLK_APBCLK0_WDTCKEN_Msk (0x1ul << CLK_APBCLK0_WDTCKEN_Pos) /*!< CLK_T::APBCLK0: WDTCKEN Mask */ + +#define CLK_APBCLK0_RTCCKEN_Pos (1) /*!< CLK_T::APBCLK0: RTCCKEN Position */ +#define CLK_APBCLK0_RTCCKEN_Msk (0x1ul << CLK_APBCLK0_RTCCKEN_Pos) /*!< CLK_T::APBCLK0: RTCCKEN Mask */ + +#define CLK_APBCLK0_TMR0CKEN_Pos (2) /*!< CLK_T::APBCLK0: TMR0CKEN Position */ +#define CLK_APBCLK0_TMR0CKEN_Msk (0x1ul << CLK_APBCLK0_TMR0CKEN_Pos) /*!< CLK_T::APBCLK0: TMR0CKEN Mask */ + +#define CLK_APBCLK0_TMR1CKEN_Pos (3) /*!< CLK_T::APBCLK0: TMR1CKEN Position */ +#define CLK_APBCLK0_TMR1CKEN_Msk (0x1ul << CLK_APBCLK0_TMR1CKEN_Pos) /*!< CLK_T::APBCLK0: TMR1CKEN Mask */ + +#define CLK_APBCLK0_TMR2CKEN_Pos (4) /*!< CLK_T::APBCLK0: TMR2CKEN Position */ +#define CLK_APBCLK0_TMR2CKEN_Msk (0x1ul << CLK_APBCLK0_TMR2CKEN_Pos) /*!< CLK_T::APBCLK0: TMR2CKEN Mask */ + +#define CLK_APBCLK0_TMR3CKEN_Pos (5) /*!< CLK_T::APBCLK0: TMR3CKEN Position */ +#define CLK_APBCLK0_TMR3CKEN_Msk (0x1ul << CLK_APBCLK0_TMR3CKEN_Pos) /*!< CLK_T::APBCLK0: TMR3CKEN Mask */ + +#define CLK_APBCLK0_CLKOCKEN_Pos (6) /*!< CLK_T::APBCLK0: CLKOCKEN Position */ +#define CLK_APBCLK0_CLKOCKEN_Msk (0x1ul << CLK_APBCLK0_CLKOCKEN_Pos) /*!< CLK_T::APBCLK0: CLKOCKEN Mask */ + +#define CLK_APBCLK0_ACMP01CKEN_Pos (7) /*!< CLK_T::APBCLK0: ACMP01CKEN Position */ +#define CLK_APBCLK0_ACMP01CKEN_Msk (0x1ul << CLK_APBCLK0_ACMP01CKEN_Pos) /*!< CLK_T::APBCLK0: ACMP01CKEN Mask */ + +#define CLK_APBCLK0_I2C0CKEN_Pos (8) /*!< CLK_T::APBCLK0: I2C0CKEN Position */ +#define CLK_APBCLK0_I2C0CKEN_Msk (0x1ul << CLK_APBCLK0_I2C0CKEN_Pos) /*!< CLK_T::APBCLK0: I2C0CKEN Mask */ + +#define CLK_APBCLK0_I2C1CKEN_Pos (9) /*!< CLK_T::APBCLK0: I2C1CKEN Position */ +#define CLK_APBCLK0_I2C1CKEN_Msk (0x1ul << CLK_APBCLK0_I2C1CKEN_Pos) /*!< CLK_T::APBCLK0: I2C1CKEN Mask */ + +#define CLK_APBCLK0_QSPI0CKEN_Pos (12) /*!< CLK_T::APBCLK0: QSPI0CKEN Position */ +#define CLK_APBCLK0_QSPI0CKEN_Msk (0x1ul << CLK_APBCLK0_QSPI0CKEN_Pos) /*!< CLK_T::APBCLK0: QSPI0CKEN Mask */ + +#define CLK_APBCLK0_SPI0CKEN_Pos (13) /*!< CLK_T::APBCLK0: SPI0CKEN Position */ +#define CLK_APBCLK0_SPI0CKEN_Msk (0x1ul << CLK_APBCLK0_SPI0CKEN_Pos) /*!< CLK_T::APBCLK0: SPI0CKEN Mask */ + +#define CLK_APBCLK0_UART0CKEN_Pos (16) /*!< CLK_T::APBCLK0: UART0CKEN Position */ +#define CLK_APBCLK0_UART0CKEN_Msk (0x1ul << CLK_APBCLK0_UART0CKEN_Pos) /*!< CLK_T::APBCLK0: UART0CKEN Mask */ + +#define CLK_APBCLK0_UART1CKEN_Pos (17) /*!< CLK_T::APBCLK0: UART1CKEN Position */ +#define CLK_APBCLK0_UART1CKEN_Msk (0x1ul << CLK_APBCLK0_UART1CKEN_Pos) /*!< CLK_T::APBCLK0: UART1CKEN Mask */ + +#define CLK_APBCLK0_UART2CKEN_Pos (18) /*!< CLK_T::APBCLK0: UART2CKEN Position */ +#define CLK_APBCLK0_UART2CKEN_Msk (0x1ul << CLK_APBCLK0_UART2CKEN_Pos) /*!< CLK_T::APBCLK0: UART2CKEN Mask */ + +#define CLK_APBCLK0_UART3CKEN_Pos (19) /*!< CLK_T::APBCLK0: UART3CKEN Position */ +#define CLK_APBCLK0_UART3CKEN_Msk (0x1ul << CLK_APBCLK0_UART3CKEN_Pos) /*!< CLK_T::APBCLK0: UART3CKEN Mask */ + +#define CLK_APBCLK0_UART4CKEN_Pos (20) /*!< CLK_T::APBCLK0: UART4CKEN Position */ +#define CLK_APBCLK0_UART4CKEN_Msk (0x1ul << CLK_APBCLK0_UART4CKEN_Pos) /*!< CLK_T::APBCLK0: UART4CKEN Mask */ + +#define CLK_APBCLK0_UART5CKEN_Pos (21) /*!< CLK_T::APBCLK0: UART5CKEN Position */ +#define CLK_APBCLK0_UART5CKEN_Msk (0x1ul << CLK_APBCLK0_UART5CKEN_Pos) /*!< CLK_T::APBCLK0: UART5CKEN Mask */ + +#define CLK_APBCLK0_UART6CKEN_Pos (22) /*!< CLK_T::APBCLK0: UART6CKEN Position */ +#define CLK_APBCLK0_UART6CKEN_Msk (0x1ul << CLK_APBCLK0_UART6CKEN_Pos) /*!< CLK_T::APBCLK0: UART6CKEN Mask */ + +#define CLK_APBCLK0_UART7CKEN_Pos (23) /*!< CLK_T::APBCLK0: UART7CKEN Position */ +#define CLK_APBCLK0_UART7CKEN_Msk (0x1ul << CLK_APBCLK0_UART7CKEN_Pos) /*!< CLK_T::APBCLK0: UART7CKEN Mask */ + +#define CLK_APBCLK0_USBDCKEN_Pos (27) /*!< CLK_T::APBCLK0: USBDCKEN Position */ +#define CLK_APBCLK0_USBDCKEN_Msk (0x1ul << CLK_APBCLK0_USBDCKEN_Pos) /*!< CLK_T::APBCLK0: USBDCKEN Mask */ + +#define CLK_APBCLK0_ADCCKEN_Pos (28) /*!< CLK_T::APBCLK0: ADCCKEN Position */ +#define CLK_APBCLK0_ADCCKEN_Msk (0x1ul << CLK_APBCLK0_ADCCKEN_Pos) /*!< CLK_T::APBCLK0: ADCCKEN Mask */ + +#define CLK_APBCLK1_USCI0CKEN_Pos (8) /*!< CLK_T::APBCLK1: USCI0CKEN Position */ +#define CLK_APBCLK1_USCI0CKEN_Msk (0x1ul << CLK_APBCLK1_USCI0CKEN_Pos) /*!< CLK_T::APBCLK1: USCI0CKEN Mask */ + +#define CLK_APBCLK1_USCI1CKEN_Pos (9) /*!< CLK_T::APBCLK1: USCI1CKEN Position */ +#define CLK_APBCLK1_USCI1CKEN_Msk (0x1ul << CLK_APBCLK1_USCI1CKEN_Pos) /*!< CLK_T::APBCLK1: USCI1CKEN Mask */ + +#define CLK_APBCLK1_PWM0CKEN_Pos (16) /*!< CLK_T::APBCLK1: PWM0CKEN Position */ +#define CLK_APBCLK1_PWM0CKEN_Msk (0x1ul << CLK_APBCLK1_PWM0CKEN_Pos) /*!< CLK_T::APBCLK1: PWM0CKEN Mask */ + +#define CLK_APBCLK1_PWM1CKEN_Pos (17) /*!< CLK_T::APBCLK1: PWM1CKEN Position */ +#define CLK_APBCLK1_PWM1CKEN_Msk (0x1ul << CLK_APBCLK1_PWM1CKEN_Pos) /*!< CLK_T::APBCLK1: PWM1CKEN Mask */ + +#define CLK_APBCLK1_BPWM0CKEN_Pos (18) /*!< CLK_T::APBCLK1: BPWM0CKEN Position */ +#define CLK_APBCLK1_BPWM0CKEN_Msk (0x1ul << CLK_APBCLK1_BPWM0CKEN_Pos) /*!< CLK_T::APBCLK1: BPWM0CKEN Mask */ + +#define CLK_APBCLK1_BPWM1CKEN_Pos (19) /*!< CLK_T::APBCLK1: BPWM1CKEN Position */ +#define CLK_APBCLK1_BPWM1CKEN_Msk (0x1ul << CLK_APBCLK1_BPWM1CKEN_Pos) /*!< CLK_T::APBCLK1: BPWM1CKEN Mask */ + +#define CLK_CLKSEL0_HCLKSEL_Pos (0) /*!< CLK_T::CLKSEL0: HCLKSEL Position */ +#define CLK_CLKSEL0_HCLKSEL_Msk (0x7ul << CLK_CLKSEL0_HCLKSEL_Pos) /*!< CLK_T::CLKSEL0: HCLKSEL Mask */ + +#define CLK_CLKSEL0_STCLKSEL_Pos (3) /*!< CLK_T::CLKSEL0: STCLKSEL Position */ +#define CLK_CLKSEL0_STCLKSEL_Msk (0x7ul << CLK_CLKSEL0_STCLKSEL_Pos) /*!< CLK_T::CLKSEL0: STCLKSEL Mask */ + +#define CLK_CLKSEL0_USBDSEL_Pos (8) /*!< CLK_T::CLKSEL0: USBDSEL Position */ +#define CLK_CLKSEL0_USBDSEL_Msk (0x1ul << CLK_CLKSEL0_USBDSEL_Pos) /*!< CLK_T::CLKSEL0: USBDSEL Mask */ + +#define CLK_CLKSEL1_WDTSEL_Pos (0) /*!< CLK_T::CLKSEL1: WDTSEL Position */ +#define CLK_CLKSEL1_WDTSEL_Msk (0x3ul << CLK_CLKSEL1_WDTSEL_Pos) /*!< CLK_T::CLKSEL1: WDTSEL Mask */ + +#define CLK_CLKSEL1_WWDTSEL_Pos (2) /*!< CLK_T::CLKSEL1: WWDTSEL Position */ +#define CLK_CLKSEL1_WWDTSEL_Msk (0x3ul << CLK_CLKSEL1_WWDTSEL_Pos) /*!< CLK_T::CLKSEL1: WWDTSEL Mask */ + +#define CLK_CLKSEL1_CLKOSEL_Pos (4) /*!< CLK_T::CLKSEL1: CLKOSEL Position */ +#define CLK_CLKSEL1_CLKOSEL_Msk (0x7ul << CLK_CLKSEL1_CLKOSEL_Pos) /*!< CLK_T::CLKSEL1: CLKOSEL Mask */ + +#define CLK_CLKSEL1_TMR0SEL_Pos (8) /*!< CLK_T::CLKSEL1: TMR0SEL Position */ +#define CLK_CLKSEL1_TMR0SEL_Msk (0x7ul << CLK_CLKSEL1_TMR0SEL_Pos) /*!< CLK_T::CLKSEL1: TMR0SEL Mask */ + +#define CLK_CLKSEL1_TMR1SEL_Pos (12) /*!< CLK_T::CLKSEL1: TMR1SEL Position */ +#define CLK_CLKSEL1_TMR1SEL_Msk (0x7ul << CLK_CLKSEL1_TMR1SEL_Pos) /*!< CLK_T::CLKSEL1: TMR1SEL Mask */ + +#define CLK_CLKSEL1_TMR2SEL_Pos (16) /*!< CLK_T::CLKSEL1: TMR2SEL Position */ +#define CLK_CLKSEL1_TMR2SEL_Msk (0x7ul << CLK_CLKSEL1_TMR2SEL_Pos) /*!< CLK_T::CLKSEL1: TMR2SEL Mask */ + +#define CLK_CLKSEL1_TMR3SEL_Pos (20) /*!< CLK_T::CLKSEL1: TMR3SEL Position */ +#define CLK_CLKSEL1_TMR3SEL_Msk (0x7ul << CLK_CLKSEL1_TMR3SEL_Pos) /*!< CLK_T::CLKSEL1: TMR3SEL Mask */ + +#define CLK_CLKSEL1_UART0SEL_Pos (24) /*!< CLK_T::CLKSEL1: UART0SEL Position */ +#define CLK_CLKSEL1_UART0SEL_Msk (0x7ul << CLK_CLKSEL1_UART0SEL_Pos) /*!< CLK_T::CLKSEL1: UART0SEL Mask */ + +#define CLK_CLKSEL1_UART1SEL_Pos (28) /*!< CLK_T::CLKSEL1: UART1SEL Position */ +#define CLK_CLKSEL1_UART1SEL_Msk (0x7ul << CLK_CLKSEL1_UART1SEL_Pos) /*!< CLK_T::CLKSEL1: UART1SEL Mask */ + +#define CLK_CLKSEL2_PWM0SEL_Pos (0) /*!< CLK_T::CLKSEL2: PWM0SEL Position */ +#define CLK_CLKSEL2_PWM0SEL_Msk (0x1ul << CLK_CLKSEL2_PWM0SEL_Pos) /*!< CLK_T::CLKSEL2: PWM0SEL Mask */ + +#define CLK_CLKSEL2_PWM1SEL_Pos (1) /*!< CLK_T::CLKSEL2: PWM1SEL Position */ +#define CLK_CLKSEL2_PWM1SEL_Msk (0x1ul << CLK_CLKSEL2_PWM1SEL_Pos) /*!< CLK_T::CLKSEL2: PWM1SEL Mask */ + +#define CLK_CLKSEL2_QSPI0SEL_Pos (2) /*!< CLK_T::CLKSEL2: QSPI0SEL Position */ +#define CLK_CLKSEL2_QSPI0SEL_Msk (0x3ul << CLK_CLKSEL2_QSPI0SEL_Pos) /*!< CLK_T::CLKSEL2: QSPI0SEL Mask */ + +#define CLK_CLKSEL2_SPI0SEL_Pos (4) /*!< CLK_T::CLKSEL2: SPI0SEL Position */ +#define CLK_CLKSEL2_SPI0SEL_Msk (0x3ul << CLK_CLKSEL2_SPI0SEL_Pos) /*!< CLK_T::CLKSEL2: SPI0SEL Mask */ + +#define CLK_CLKSEL2_BPWM0SEL_Pos (8) /*!< CLK_T::CLKSEL2: BPWM0SEL Position */ +#define CLK_CLKSEL2_BPWM0SEL_Msk (0x1ul << CLK_CLKSEL2_BPWM0SEL_Pos) /*!< CLK_T::CLKSEL2: BPWM0SEL Mask */ + +#define CLK_CLKSEL2_BPWM1SEL_Pos (9) /*!< CLK_T::CLKSEL2: BPWM1SEL Position */ +#define CLK_CLKSEL2_BPWM1SEL_Msk (0x1ul << CLK_CLKSEL2_BPWM1SEL_Pos) /*!< CLK_T::CLKSEL2: BPWM1SEL Mask */ + +#define CLK_CLKSEL2_ADCSEL_Pos (20) /*!< CLK_T::CLKSEL2: ADCSEL Position */ +#define CLK_CLKSEL2_ADCSEL_Msk (0x3ul << CLK_CLKSEL2_ADCSEL_Pos) /*!< CLK_T::CLKSEL2: ADCSEL Mask */ + +#define CLK_CLKSEL3_UART6SEL_Pos (8) /*!< CLK_T::CLKSEL63: UART6SEL Position */ +#define CLK_CLKSEL3_UART6SEL_Msk (0x7ul << CLK_CLKSEL3_UART6SEL_Pos) /*!< CLK_T::CLKSEL3: UART6SEL Mask */ + +#define CLK_CLKSEL3_UART7SEL_Pos (12) /*!< CLK_T::CLKSEL3: UART7SEL Position */ +#define CLK_CLKSEL3_UART7SEL_Msk (0x7ul << CLK_CLKSEL3_UART7SEL_Pos) /*!< CLK_T::CLKSEL3: UART7SEL Mask */ + +#define CLK_CLKSEL3_UART4SEL_Pos (16) /*!< CLK_T::CLKSEL3: UART4SEL Position */ +#define CLK_CLKSEL3_UART4SEL_Msk (0x7ul << CLK_CLKSEL3_UART4SEL_Pos) /*!< CLK_T::CLKSEL3: UART4SEL Mask */ + +#define CLK_CLKSEL3_UART5SEL_Pos (20) /*!< CLK_T::CLKSEL3: UART5SEL Position */ +#define CLK_CLKSEL3_UART5SEL_Msk (0x7ul << CLK_CLKSEL3_UART5SEL_Pos) /*!< CLK_T::CLKSEL3: UART5SEL Mask */ + +#define CLK_CLKSEL3_UART2SEL_Pos (24) /*!< CLK_T::CLKSEL3: UART2SEL Position */ +#define CLK_CLKSEL3_UART2SEL_Msk (0x7ul << CLK_CLKSEL3_UART2SEL_Pos) /*!< CLK_T::CLKSEL3: UART2SEL Mask */ + +#define CLK_CLKSEL3_UART3SEL_Pos (28) /*!< CLK_T::CLKSEL3: UART3SEL Position */ +#define CLK_CLKSEL3_UART3SEL_Msk (0x7ul << CLK_CLKSEL3_UART3SEL_Pos) /*!< CLK_T::CLKSEL3: UART3SEL Mask */ + +#define CLK_CLKDIV0_HCLKDIV_Pos (0) /*!< CLK_T::CLKDIV0: HCLKDIV Position */ +#define CLK_CLKDIV0_HCLKDIV_Msk (0xful << CLK_CLKDIV0_HCLKDIV_Pos) /*!< CLK_T::CLKDIV0: HCLKDIV Mask */ + +#define CLK_CLKDIV0_USBDIV_Pos (4) /*!< CLK_T::CLKDIV0: USBDIV Position */ +#define CLK_CLKDIV0_USBDIV_Msk (0xful << CLK_CLKDIV0_USBDIV_Pos) /*!< CLK_T::CLKDIV0: USBDIV Mask */ + +#define CLK_CLKDIV0_UART0DIV_Pos (8) /*!< CLK_T::CLKDIV0: UART0DIV Position */ +#define CLK_CLKDIV0_UART0DIV_Msk (0xful << CLK_CLKDIV0_UART0DIV_Pos) /*!< CLK_T::CLKDIV0: UART0DIV Mask */ + +#define CLK_CLKDIV0_UART1DIV_Pos (12) /*!< CLK_T::CLKDIV0: UART1DIV Position */ +#define CLK_CLKDIV0_UART1DIV_Msk (0xful << CLK_CLKDIV0_UART1DIV_Pos) /*!< CLK_T::CLKDIV0: UART1DIV Mask */ + +#define CLK_CLKDIV0_ADCDIV_Pos (16) /*!< CLK_T::CLKDIV0: ADCDIV Position */ +#define CLK_CLKDIV0_ADCDIV_Msk (0xfful << CLK_CLKDIV0_ADCDIV_Pos) /*!< CLK_T::CLKDIV0: ADCDIV Mask */ + +#define CLK_CLKDIV4_UART2DIV_Pos (0) /*!< CLK_T::CLKDIV4: UART2DIV Position */ +#define CLK_CLKDIV4_UART2DIV_Msk (0xful << CLK_CLKDIV4_UART2DIV_Pos) /*!< CLK_T::CLKDIV4: UART2DIV Mask */ + +#define CLK_CLKDIV4_UART3DIV_Pos (4) /*!< CLK_T::CLKDIV4: UART3DIV Position */ +#define CLK_CLKDIV4_UART3DIV_Msk (0xful << CLK_CLKDIV4_UART3DIV_Pos) /*!< CLK_T::CLKDIV4: UART3DIV Mask */ + +#define CLK_CLKDIV4_UART4DIV_Pos (8) /*!< CLK_T::CLKDIV4: UART4DIV Position */ +#define CLK_CLKDIV4_UART4DIV_Msk (0xful << CLK_CLKDIV4_UART4DIV_Pos) /*!< CLK_T::CLKDIV4: UART4DIV Mask */ + +#define CLK_CLKDIV4_UART5DIV_Pos (12) /*!< CLK_T::CLKDIV4: UART5DIV Position */ +#define CLK_CLKDIV4_UART5DIV_Msk (0xful << CLK_CLKDIV4_UART5DIV_Pos) /*!< CLK_T::CLKDIV4: UART5DIV Mask */ + +#define CLK_CLKDIV4_UART6DIV_Pos (16) /*!< CLK_T::CLKDIV4: UART6DIV Position */ +#define CLK_CLKDIV4_UART6DIV_Msk (0xful << CLK_CLKDIV4_UART6DIV_Pos) /*!< CLK_T::CLKDIV4: UART6DIV Mask */ + +#define CLK_CLKDIV4_UART7DIV_Pos (20) /*!< CLK_T::CLKDIV4: UART7DIV Position */ +#define CLK_CLKDIV4_UART7DIV_Msk (0xful << CLK_CLKDIV4_UART7DIV_Pos) /*!< CLK_T::CLKDIV4: UART7DIV Mask */ + +#define CLK_PCLKDIV_APB0DIV_Pos (0) /*!< CLK_T::PCLKDIV: APB0DIV Position */ +#define CLK_PCLKDIV_APB0DIV_Msk (0x7ul << CLK_PCLKDIV_APB0DIV_Pos) /*!< CLK_T::PCLKDIV: APB0DIV Mask */ + +#define CLK_PCLKDIV_APB1DIV_Pos (4) /*!< CLK_T::PCLKDIV: APB1DIV Position */ +#define CLK_PCLKDIV_APB1DIV_Msk (0x7ul << CLK_PCLKDIV_APB1DIV_Pos) /*!< CLK_T::PCLKDIV: APB1DIV Mask */ + +#define CLK_PLLCTL_FBDIV_Pos (0) /*!< CLK_T::PLLCTL: FBDIV Position */ +#define CLK_PLLCTL_FBDIV_Msk (0x1fful << CLK_PLLCTL_FBDIV_Pos) /*!< CLK_T::PLLCTL: FBDIV Mask */ + +#define CLK_PLLCTL_INDIV_Pos (9) /*!< CLK_T::PLLCTL: INDIV Position */ +#define CLK_PLLCTL_INDIV_Msk (0x1ful << CLK_PLLCTL_INDIV_Pos) /*!< CLK_T::PLLCTL: INDIV Mask */ + +#define CLK_PLLCTL_OUTDIV_Pos (14) /*!< CLK_T::PLLCTL: OUTDIV Position */ +#define CLK_PLLCTL_OUTDIV_Msk (0x3ul << CLK_PLLCTL_OUTDIV_Pos) /*!< CLK_T::PLLCTL: OUTDIV Mask */ + +#define CLK_PLLCTL_PD_Pos (16) /*!< CLK_T::PLLCTL: PD Position */ +#define CLK_PLLCTL_PD_Msk (0x1ul << CLK_PLLCTL_PD_Pos) /*!< CLK_T::PLLCTL: PD Mask */ + +#define CLK_PLLCTL_BP_Pos (17) /*!< CLK_T::PLLCTL: BP Position */ +#define CLK_PLLCTL_BP_Msk (0x1ul << CLK_PLLCTL_BP_Pos) /*!< CLK_T::PLLCTL: BP Mask */ + +#define CLK_PLLCTL_OE_Pos (18) /*!< CLK_T::PLLCTL: OE Position */ +#define CLK_PLLCTL_OE_Msk (0x1ul << CLK_PLLCTL_OE_Pos) /*!< CLK_T::PLLCTL: OE Mask */ + +#define CLK_PLLCTL_PLLSRC_Pos (19) /*!< CLK_T::PLLCTL: PLLSRC Position */ +#define CLK_PLLCTL_PLLSRC_Msk (0x1ul << CLK_PLLCTL_PLLSRC_Pos) /*!< CLK_T::PLLCTL: PLLSRC Mask */ + +#define CLK_PLLCTL_STBSEL_Pos (23) /*!< CLK_T::PLLCTL: STBSEL Position */ +#define CLK_PLLCTL_STBSEL_Msk (0x1ul << CLK_PLLCTL_STBSEL_Pos) /*!< CLK_T::PLLCTL: STBSEL Mask */ + +#define CLK_STATUS_HXTSTB_Pos (0) /*!< CLK_T::STATUS: HXTSTB Position */ +#define CLK_STATUS_HXTSTB_Msk (0x1ul << CLK_STATUS_HXTSTB_Pos) /*!< CLK_T::STATUS: HXTSTB Mask */ + +#define CLK_STATUS_LXTSTB_Pos (1) /*!< CLK_T::STATUS: LXTSTB Position */ +#define CLK_STATUS_LXTSTB_Msk (0x1ul << CLK_STATUS_LXTSTB_Pos) /*!< CLK_T::STATUS: LXTSTB Mask */ + +#define CLK_STATUS_PLLSTB_Pos (2) /*!< CLK_T::STATUS: PLLSTB Position */ +#define CLK_STATUS_PLLSTB_Msk (0x1ul << CLK_STATUS_PLLSTB_Pos) /*!< CLK_T::STATUS: PLLSTB Mask */ + +#define CLK_STATUS_LIRCSTB_Pos (3) /*!< CLK_T::STATUS: LIRCSTB Position */ +#define CLK_STATUS_LIRCSTB_Msk (0x1ul << CLK_STATUS_LIRCSTB_Pos) /*!< CLK_T::STATUS: LIRCSTB Mask */ + +#define CLK_STATUS_HIRCSTB_Pos (4) /*!< CLK_T::STATUS: HIRCSTB Position */ +#define CLK_STATUS_HIRCSTB_Msk (0x1ul << CLK_STATUS_HIRCSTB_Pos) /*!< CLK_T::STATUS: HIRCSTB Mask */ + +#define CLK_STATUS_CLKSFAIL_Pos (7) /*!< CLK_T::STATUS: CLKSFAIL Position */ +#define CLK_STATUS_CLKSFAIL_Msk (0x1ul << CLK_STATUS_CLKSFAIL_Pos) /*!< CLK_T::STATUS: CLKSFAIL Mask */ + +#define CLK_CLKOCTL_FREQSEL_Pos (0) /*!< CLK_T::CLKOCTL: FREQSEL Position */ +#define CLK_CLKOCTL_FREQSEL_Msk (0xful << CLK_CLKOCTL_FREQSEL_Pos) /*!< CLK_T::CLKOCTL: FREQSEL Mask */ + +#define CLK_CLKOCTL_CLKOEN_Pos (4) /*!< CLK_T::CLKOCTL: CLKOEN Position */ +#define CLK_CLKOCTL_CLKOEN_Msk (0x1ul << CLK_CLKOCTL_CLKOEN_Pos) /*!< CLK_T::CLKOCTL: CLKOEN Mask */ + +#define CLK_CLKOCTL_DIV1EN_Pos (5) /*!< CLK_T::CLKOCTL: DIV1EN Position */ +#define CLK_CLKOCTL_DIV1EN_Msk (0x1ul << CLK_CLKOCTL_DIV1EN_Pos) /*!< CLK_T::CLKOCTL: DIV1EN Mask */ + +#define CLK_CLKOCTL_CLK1HZEN_Pos (6) /*!< CLK_T::CLKOCTL: CLK1HZEN Position */ +#define CLK_CLKOCTL_CLK1HZEN_Msk (0x1ul << CLK_CLKOCTL_CLK1HZEN_Pos) /*!< CLK_T::CLKOCTL: CLK1HZEN Mask */ + +#define CLK_CLKDCTL_HXTFDEN_Pos (4) /*!< CLK_T::CLKDCTL: HXTFDEN Position */ +#define CLK_CLKDCTL_HXTFDEN_Msk (0x1ul << CLK_CLKDCTL_HXTFDEN_Pos) /*!< CLK_T::CLKDCTL: HXTFDEN Mask */ + +#define CLK_CLKDCTL_HXTFIEN_Pos (5) /*!< CLK_T::CLKDCTL: HXTFIEN Position */ +#define CLK_CLKDCTL_HXTFIEN_Msk (0x1ul << CLK_CLKDCTL_HXTFIEN_Pos) /*!< CLK_T::CLKDCTL: HXTFIEN Mask */ + +#define CLK_CLKDCTL_LXTFDEN_Pos (12) /*!< CLK_T::CLKDCTL: LXTFDEN Position */ +#define CLK_CLKDCTL_LXTFDEN_Msk (0x1ul << CLK_CLKDCTL_LXTFDEN_Pos) /*!< CLK_T::CLKDCTL: LXTFDEN Mask */ + +#define CLK_CLKDCTL_LXTFIEN_Pos (13) /*!< CLK_T::CLKDCTL: LXTFIEN Position */ +#define CLK_CLKDCTL_LXTFIEN_Msk (0x1ul << CLK_CLKDCTL_LXTFIEN_Pos) /*!< CLK_T::CLKDCTL: LXTFIEN Mask */ + +#define CLK_CLKDCTL_HXTFQDEN_Pos (16) /*!< CLK_T::CLKDCTL: HXTFQDEN Position */ +#define CLK_CLKDCTL_HXTFQDEN_Msk (0x1ul << CLK_CLKDCTL_HXTFQDEN_Pos) /*!< CLK_T::CLKDCTL: HXTFQDEN Mask */ + +#define CLK_CLKDCTL_HXTFQIEN_Pos (17) /*!< CLK_T::CLKDCTL: HXTFQIEN Position */ +#define CLK_CLKDCTL_HXTFQIEN_Msk (0x1ul << CLK_CLKDCTL_HXTFQIEN_Pos) /*!< CLK_T::CLKDCTL: HXTFQIEN Mask */ + +#define CLK_CLKDSTS_HXTFIF_Pos (0) /*!< CLK_T::CLKDSTS: HXTFIF Position */ +#define CLK_CLKDSTS_HXTFIF_Msk (0x1ul << CLK_CLKDSTS_HXTFIF_Pos) /*!< CLK_T::CLKDSTS: HXTFIF Mask */ + +#define CLK_CLKDSTS_LXTFIF_Pos (1) /*!< CLK_T::CLKDSTS: LXTFIF Position */ +#define CLK_CLKDSTS_LXTFIF_Msk (0x1ul << CLK_CLKDSTS_LXTFIF_Pos) /*!< CLK_T::CLKDSTS: LXTFIF Mask */ + +#define CLK_CLKDSTS_HXTFQIF_Pos (8) /*!< CLK_T::CLKDSTS: HXTFQIF Position */ +#define CLK_CLKDSTS_HXTFQIF_Msk (0x1ul << CLK_CLKDSTS_HXTFQIF_Pos) /*!< CLK_T::CLKDSTS: HXTFQIF Mask */ + +#define CLK_CDUPB_UPERBD_Pos (0) /*!< CLK_T::CDUPB: UPERBD Position */ +#define CLK_CDUPB_UPERBD_Msk (0x3fful << CLK_CDUPB_UPERBD_Pos) /*!< CLK_T::CDUPB: UPERBD Mask */ + +#define CLK_CDLOWB_LOWERBD_Pos (0) /*!< CLK_T::CDLOWB: LOWERBD Position */ +#define CLK_CDLOWB_LOWERBD_Msk (0x3fful << CLK_CDLOWB_LOWERBD_Pos) /*!< CLK_T::CDLOWB: LOWERBD Mask */ + +#define CLK_HXTFSEL_HXTFSEL_Pos (0) /*!< CLK_T::HXTFSEL: HXTFSEL Position */ +#define CLK_HXTFSEL_HXTFSEL_Msk (0x1ul << CLK_HXTFSEL_HXTFSEL_Pos) /*!< CLK_T::HXTFSEL: HXTFSEL Mask */ + +/**@}*/ /* CLK_CONST */ +/**@}*/ /* end of CLK register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __CLK_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/crc_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/crc_reg.h new file mode 100644 index 0000000000..3a5d83177d --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/crc_reg.h @@ -0,0 +1,151 @@ +/**************************************************************************//** + * @file crc_reg.h + * @version V1.00 + * @brief CRC register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __CRC_REG_H__ +#define __CRC_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup CRC Cyclic Redundancy Check Controller(CRC) + Memory Mapped Structure for CRC Controller +@{ */ + +typedef struct +{ + + + /** + * @var CRC_T::CTL + * Offset: 0x00 CRC Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CRCEN |CRC Channel Enable Bit + * | | |0 = No effect. + * | | |1 = CRC operation Enabled. + * |[1] |CHKSINIT |Checksum Initialization + * | | |0 = No effect. + * | | |1 = Initial checksum value by auto reload CRC_SEED register value to CRC_CHECKSUM register value. + * | | |Note: This bit will be cleared automatically. + * |[24] |DATREV |Write Data Bit Order Reverse + * | | |This bit is used to enable the bit order reverse function per byte for write data value in CRC_DAT register. + * | | |0 = Bit order reversed for CRC write data in Disabled. + * | | |1 = Bit order reversed for CRC write data in Enabled (per byte). + * | | |Note: If the write data is 0xAABBCCDD, the bit order reverse for CRC write data in is 0x55DD33BB. + * |[25] |CHKSREV |Checksum Bit Order Reverse + * | | |This bit is used to enable the bit order reverse function for checksum result in CRC_CHECKSUM register. + * | | |0 = Bit order reverse for CRC checksum Disabled. + * | | |1 = Bit order reverse for CRC checksum Enabled. + * | | |Note: If the checksum result is 0xDD7B0F2E, the bit order reverse for CRC checksum is 0x74F0DEBB. + * |[26] |DATFMT |Write Data 1's Complement + * | | |This bit is used to enable the 1's complement function for write data value in CRC_DAT register. + * | | |0 = 1's complement for CRC writes data in Disabled. + * | | |1 = 1's complement for CRC writes data in Enabled. + * |[27] |CHKSFMT |Checksum 1's Complement + * | | |This bit is used to enable the 1's complement function for checksum result in CRC_CHECKSUM register. + * | | |0 = 1's complement for CRC checksum Disabled. + * | | |1 = 1's complement for CRC checksum Enabled. + * |[29:28] |DATLEN |CPU Write Data Length + * | | |This field indicates the write data length. + * | | |00 = Data length is 8-bit mode. + * | | |01 = Data length is 16-bit mode. + * | | |1x = Data length is 32-bit mode. + * | | |Note: When the write data length is 8-bit mode, the valid data in CRC_DAT register is only DATA[7:0] bits; if the write data length is 16-bit mode, the valid data in CRC_DAT register is only DATA[15:0]. + * |[31:30] |CRCMODE |CRC Polynomial Mode + * | | |This field indicates the CRC operation polynomial mode. + * | | |00 = CRC-CCITT Polynomial mode. + * | | |01 = CRC-8 Polynomial mode. + * | | |10 = CRC-16 Polynomial mode. + * | | |11 = CRC-32 Polynomial mode. + * @var CRC_T::DAT + * Offset: 0x04 CRC Write Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |DATA |CRC Write Data Bits + * | | |User can write data directly by CPU mode or use PDMA function to write data to this field to perform CRC operation. + * | | |Note: When the write data length is 8-bit mode, the valid data in CRC_DAT register is only DATA[7:0] bits; if the write data length is 16-bit mode, the valid data in CRC_DAT register is only DATA[15:0]. + * @var CRC_T::SEED + * Offset: 0x08 CRC Seed Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SEED |CRC Seed Value + * | | |This field indicates the CRC seed value. + * | | |Note: This field will be reloaded as checksum initial value (CRC_CHECKSUM register) after perform CHKSINIT (CRC_CTL[1]). + * @var CRC_T::CHECKSUM + * Offset: 0x0C CRC Checksum Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |CHECKSUM |CRC Checksum Results + * | | |This field indicates the CRC checksum result. + */ + __IO uint32_t CTL; /*!< [0x0000] CRC Control Register */ + __IO uint32_t DAT; /*!< [0x0004] CRC Write Data Register */ + __IO uint32_t SEED; /*!< [0x0008] CRC Seed Register */ + __I uint32_t CHECKSUM; /*!< [0x000c] CRC Checksum Register */ + +} CRC_T; + +/** + @addtogroup CRC_CONST CRC Bit Field Definition + Constant Definitions for CRC Controller +@{ */ + + +#define CRC_CTL_CRCEN_Pos (0) /*!< CRC_T::CTL: CRCEN Position */ +#define CRC_CTL_CRCEN_Msk (0x1ul << CRC_CTL_CRCEN_Pos) /*!< CRC_T::CTL: CRCEN Mask */ + +#define CRC_CTL_CHKSINIT_Pos (1) /*!< CRC_T::CTL: CHKSINIT Position */ +#define CRC_CTL_CHKSINIT_Msk (0x1ul << CRC_CTL_CHKSINIT_Pos) /*!< CRC_T::CTL: CHKSINIT Mask */ + +#define CRC_CTL_DATREV_Pos (24) /*!< CRC_T::CTL: DATREV Position */ +#define CRC_CTL_DATREV_Msk (0x1ul << CRC_CTL_DATREV_Pos) /*!< CRC_T::CTL: DATREV Mask */ + +#define CRC_CTL_CHKSREV_Pos (25) /*!< CRC_T::CTL: CHKSREV Position */ +#define CRC_CTL_CHKSREV_Msk (0x1ul << CRC_CTL_CHKSREV_Pos) /*!< CRC_T::CTL: CHKSREV Mask */ + +#define CRC_CTL_DATFMT_Pos (26) /*!< CRC_T::CTL: DATFMT Position */ +#define CRC_CTL_DATFMT_Msk (0x1ul << CRC_CTL_DATFMT_Pos) /*!< CRC_T::CTL: DATFMT Mask */ + +#define CRC_CTL_CHKSFMT_Pos (27) /*!< CRC_T::CTL: CHKSFMT Position */ +#define CRC_CTL_CHKSFMT_Msk (0x1ul << CRC_CTL_CHKSFMT_Pos) /*!< CRC_T::CTL: CHKSFMT Mask */ + +#define CRC_CTL_DATLEN_Pos (28) /*!< CRC_T::CTL: DATLEN Position */ +#define CRC_CTL_DATLEN_Msk (0x3ul << CRC_CTL_DATLEN_Pos) /*!< CRC_T::CTL: DATLEN Mask */ + +#define CRC_CTL_CRCMODE_Pos (30) /*!< CRC_T::CTL: CRCMODE Position */ +#define CRC_CTL_CRCMODE_Msk (0x3ul << CRC_CTL_CRCMODE_Pos) /*!< CRC_T::CTL: CRCMODE Mask */ + +#define CRC_DAT_DATA_Pos (0) /*!< CRC_T::DAT: DATA Position */ +#define CRC_DAT_DATA_Msk (0xfffffffful << CRC_DAT_DATA_Pos) /*!< CRC_T::DAT: DATA Mask */ + +#define CRC_SEED_SEED_Pos (0) /*!< CRC_T::SEED: SEED Position */ +#define CRC_SEED_SEED_Msk (0xfffffffful << CRC_SEED_SEED_Pos) /*!< CRC_T::SEED: SEED Mask */ + +#define CRC_CHECKSUM_CHECKSUM_Pos (0) /*!< CRC_T::CHECKSUM: CHECKSUM Position */ +#define CRC_CHECKSUM_CHECKSUM_Msk (0xfffffffful << CRC_CHECKSUM_CHECKSUM_Pos) /*!< CRC_T::CHECKSUM: CHECKSUM Mask */ + +/**@}*/ /* CRC_CONST */ +/**@}*/ /* end of CRC register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __CRC_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/ebi_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/ebi_reg.h new file mode 100644 index 0000000000..b147997f88 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/ebi_reg.h @@ -0,0 +1,224 @@ +/**************************************************************************//** + * @file ebi_reg.h + * @version V1.00 + * @brief EBI register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __EBI_REG_H__ +#define __EBI_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup EBI External Bus Interface Controller(EBI) + Memory Mapped Structure for EBI Controller +@{ */ + +typedef struct +{ + + + /** + * @var EBI_T::CTL0 + * Offset: 0x00 External Bus Interface Bank0 Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |EN |EBI Enable Bit + * | | |This bit is the functional enable bit for EBI. + * | | |0 = EBI function Disabled. + * | | |1 = EBI function Enabled. + * |[1] |DW16 |EBI Data Width 16-bit Select + * | | |This bit defines if the EBI data width is 8-bit or 16-bit. + * | | |0 = EBI data width is 8-bit. + * | | |1 = EBI data width is 16-bit. + * |[2] |CSPOLINV |Chip Select Pin Polar Inverse + * | | |This bit defines the active level of EBI chip select pin (EBI_nCS). + * | | |0 = Chip select pin (EBI_nCS) is active low. + * | | |1 = Chip select pin (EBI_nCS) is active high. + * |[4] |CACCESS |Continuous Data Access Mode + * | | |When continuous access mode enabled, the tASU, tALE and tLHD cycles are bypass for continuous data transfer request. + * | | |0 = Continuous data access mode Disabled. + * | | |1 = Continuous data access mode Enabled. + * |[10:8] |MCLKDIV |External Output Clock Divider + * | | |The frequency of EBI output clock (MCLK) is controlled by MCLKDIV as follow: + * | | |000 = HCLK/1. + * | | |001 = HCLK/2. + * | | |010 = HCLK/4. + * | | |011 = HCLK/8. + * | | |100 = HCLK/16. + * | | |101 = HCLK/32. + * | | |110 = HCLK/64. + * | | |111 = HCLK/128. + * |[18:16] |TALE |Extend Time Of of ALE + * | | |The EBI_ALE high pulse period (tALE) to latch the address can be controlled by TALE. + * | | |tALE = (TALE + 1)*EBI_MCLK. + * | | |Note: This field only available in EBI_CTL0 register. + * |[24] |WBUFEN |EBI Write Buffer Enable Bit + * | | |0 = EBI write buffer Disabled. + * | | |1 = EBI write buffer Enabled. + * | | |Note: This bit only available in EBI_CTL0 register. + * @var EBI_T::TCTL0 + * Offset: 0x04 External Bus Interface Bank0 Timing Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:3] |TACC |EBI Data Access Time + * | | |TACC define data access time (tACC). + * | | |tACC = (TACC + 1) * EBI_MCLK. + * |[10:8] |TAHD |EBI Data Access Hold Time + * | | |TAHD define data access hold time (tAHD). + * | | |tAHD = (TAHD + 1) * EBI_MCLK. + * |[15:12] |W2X |Idle Cycle After Write + * | | |This field defines the number of W2X idle cycle. + * | | |When write action is finish, W2X idle cycle is inserted and EBI_nCS return to idle state. + * | | |W2X idle cycle = (W2X * EBI_MCLK). + * | | |When write action is finish, W2X idle cycle is inserted and EBI_nCS return to idle state. + * |[22] |RAHDOFF |Access Hold Time Disable Control When Read + * | | |0 = The Data Access Hold Time (tAHD) during EBI reading is Enabled. + * | | |1 = The Data Access Hold Time (tAHD) during EBI reading is Disabled. + * |[23] |WAHDOFF |Access Hold Time Disable Control When Write + * | | |0 = The Data Access Hold Time (tAHD) during EBI writing is Enabled. + * | | |1 = The Data Access Hold Time (tAHD) during EBI writing is Disabled. + * |[27:24] |R2R |Idle Cycle Between Read-to-read + * | | |This field defines the number of R2R idle cycle. + * | | |When read action is finish and next action is going to read, R2R idle cycle is inserted and EBI_nCS return to idle state. + * | | |R2R idle cycle = (R2R * EBI_MCLK). + * | | |When read action is finish and next action is going to read, R2R idle cycle is inserted and EBI_nCS return to idle state. + * @var EBI_T::CTL1 + * Offset: 0x10 External Bus Interface Bank1 Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |EN |EBI Enable Bit + * | | |This bit is the functional enable bit for EBI. + * | | |0 = EBI function Disabled. + * | | |1 = EBI function Enabled. + * |[1] |DW16 |EBI Data Width 16-bit Select + * | | |This bit defines if the EBI data width is 8-bit or 16-bit. + * | | |0 = EBI data width is 8-bit. + * | | |1 = EBI data width is 16-bit. + * |[2] |CSPOLINV |Chip Select Pin Polar Inverse + * | | |This bit defines the active level of EBI chip select pin (EBI_nCS). + * | | |0 = Chip select pin (EBI_nCS) is active low. + * | | |1 = Chip select pin (EBI_nCS) is active high. + * |[4] |CACCESS |Continuous Data Access Mode + * | | |When con ttinuousenuous access mode enabled, the tASU, tALE and tLHD cycles are bypass for continuous data transfer request. + * | | |0 = Continuous data access mode Disabled. + * | | |1 = Continuous data access mode Enabled. + * |[10:8] |MCLKDIV |External Output Clock Divider + * | | |The frequency of EBI output clock (MCLK) is controlled by MCLKDIV as follow: + * | | |000 = HCLK/1. + * | | |001 = HCLK/2. + * | | |010 = HCLK/4. + * | | |011 = HCLK/8. + * | | |100 = HCLK/16. + * | | |101 = HCLK/32. + * | | |110 = HCLK/64. + * | | |111 = HCLK/128. + * |[18:16] |TALE |Extend Time Of of ALE + * | | |The EBI_ALE high pulse period (tALE) to latch the address can be controlled by TALE. + * | | |tALE = (TALE + 1)*EBI_MCLK. + * | | |Note: This field only available in EBI_CTL0 register. + * |[24] |WBUFEN |EBI Write Buffer Enable Bit + * | | |0 = EBI write buffer Disabled. + * | | |1 = EBI write buffer Enabled. + * | | |Note: This bit only available in EBI_CTL0 register. + * @var EBI_T::TCTL1 + * Offset: 0x14 External Bus Interface Bank1 Timing Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:3] |TACC |EBI Data Access Time + * | | |TACC define data access time (tACC). + * | | |tACC = (TACC + 1) * EBI_MCLK. + * |[10:8] |TAHD |EBI Data Access Hold Time + * | | |TAHD define data access hold time (tAHD). + * | | |tAHD = (TAHD + 1) * EBI_MCLK. + * |[15:12] |W2X |Idle Cycle After Write + * | | |This field defines the number of W2X idle cycle. + * | | |When write action is finish, W2X idle cycle is inserted and EBI_nCS return to idle state. + * | | |W2X idle cycle = (W2X * EBI_MCLK). + * | | |When write action is finish, W2X idle cycle is inserted and EBI_nCS return to idle state. + * |[22] |RAHDOFF |Access Hold Time Disable Control When Read + * | | |0 = The Data Access Hold Time (tAHD) during EBI reading is Enabled. + * | | |1 = The Data Access Hold Time (tAHD) during EBI reading is Disabled. + * |[23] |WAHDOFF |Access Hold Time Disable Control When Write + * | | |0 = The Data Access Hold Time (tAHD) during EBI writing is Enabled. + * | | |1 = The Data Access Hold Time (tAHD) during EBI writing is Disabled. + * |[27:24] |R2R |Idle Cycle Between Read-to-read + * | | |This field defines the number of R2R idle cycle. + * | | |When read action is finish and next action is going to read, R2R idle cycle is inserted and EBI_nCS return to idle state. + * | | |R2R idle cycle = (R2R * EBI_MCLK). + * | | |When read action is finish and next action is going to read, R2R idle cycle is inserted and EBI_nCS return to idle state. + */ + __IO uint32_t CTL0; /*!< [0x0000] External Bus Interface Bank0 Control Register */ + __IO uint32_t TCTL0; /*!< [0x0004] External Bus Interface Bank0 Timing Control Register */ + __I uint32_t RESERVE0[2]; + __IO uint32_t CTL1; /*!< [0x0010] External Bus Interface Bank1 Control Register */ + __IO uint32_t TCTL1; /*!< [0x0014] External Bus Interface Bank1 Timing Control Register */ + +} EBI_T; + +/** + @addtogroup EBI_CONST EBI Bit Field Definition + Constant Definitions for EBI Controller +@{ */ + +#define EBI_CTL_EN_Pos (0) /*!< EBI_T::CTL0: EN Position */ +#define EBI_CTL_EN_Msk (0x1ul << EBI_CTL_EN_Pos) /*!< EBI_T::CTL0: EN Mask */ + +#define EBI_CTL_DW16_Pos (1) /*!< EBI_T::CTL0: DW16 Position */ +#define EBI_CTL_DW16_Msk (0x1ul << EBI_CTL_DW16_Pos) /*!< EBI_T::CTL0: DW16 Mask */ + +#define EBI_CTL_CSPOLINV_Pos (2) /*!< EBI_T::CTL0: CSPOLINV Position */ +#define EBI_CTL_CSPOLINV_Msk (0x1ul << EBI_CTL_CSPOLINV_Pos) /*!< EBI_T::CTL0: CSPOLINV Mask */ + +#define EBI_CTL_CACCESS_Pos (4) /*!< EBI_T::CTL0: CACCESS Position */ +#define EBI_CTL_CACCESS_Msk (0x1ul << EBI_CTL_CACCESS_Pos) /*!< EBI_T::CTL0: CACCESS Mask */ + +#define EBI_CTL_MCLKDIV_Pos (8) /*!< EBI_T::CTL0: MCLKDIV Position */ +#define EBI_CTL_MCLKDIV_Msk (0x7ul << EBI_CTL_MCLKDIV_Pos) /*!< EBI_T::CTL0: MCLKDIV Mask */ + +#define EBI_CTL_TALE_Pos (16) /*!< EBI_T::CTL0: TALE Position */ +#define EBI_CTL_TALE_Msk (0x7ul << EBI_CTL_TALE_Pos) /*!< EBI_T::CTL0: TALE Mask */ + +#define EBI_CTL_WBUFEN_Pos (24) /*!< EBI_T::CTL0: WBUFEN Position */ +#define EBI_CTL_WBUFEN_Msk (0x1ul << EBI_CTL_WBUFEN_Pos) /*!< EBI_T::CTL0: WBUFEN Mask */ + +#define EBI_TCTL_TACC_Pos (3) /*!< EBI_T::TCTL0: TACC Position */ +#define EBI_TCTL_TACC_Msk (0x1ful << EBI_TCTL_TACC_Pos) /*!< EBI_T::TCTL0: TACC Mask */ + +#define EBI_TCTL_TAHD_Pos (8) /*!< EBI_T::TCTL0: TAHD Position */ +#define EBI_TCTL_TAHD_Msk (0x7ul << EBI_TCTL_TAHD_Pos) /*!< EBI_T::TCTL0: TAHD Mask */ + +#define EBI_TCTL_W2X_Pos (12) /*!< EBI_T::TCTL0: W2X Position */ +#define EBI_TCTL_W2X_Msk (0xful << EBI_TCTL_W2X_Pos) /*!< EBI_T::TCTL0: W2X Mask */ + +#define EBI_TCTL_RAHDOFF_Pos (22) /*!< EBI_T::TCTL0: RAHDOFF Position */ +#define EBI_TCTL_RAHDOFF_Msk (0x1ul << EBI_TCTL_RAHDOFF_Pos) /*!< EBI_T::TCTL0: RAHDOFF Mask */ + +#define EBI_TCTL_WAHDOFF_Pos (23) /*!< EBI_T::TCTL0: WAHDOFF Position */ +#define EBI_TCTL_WAHDOFF_Msk (0x1ul << EBI_TCTL_WAHDOFF_Pos) /*!< EBI_T::TCTL0: WAHDOFF Mask */ + +#define EBI_TCTL_R2R_Pos (24) /*!< EBI_T::TCTL0: R2R Position */ +#define EBI_TCTL_R2R_Msk (0xful << EBI_TCTL_R2R_Pos) /*!< EBI_T::TCTL0: R2R Mask */ + +/**@}*/ /* EBI_CONST */ +/**@}*/ /* end of EBI register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __EBI_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/fmc_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/fmc_reg.h new file mode 100644 index 0000000000..b40ecc1a45 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/fmc_reg.h @@ -0,0 +1,317 @@ +/**************************************************************************//** + * @file fmc_reg.h + * @version V1.00 + * @brief FMC register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __FMC_REG_H__ +#define __FMC_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup FMC Flash Memory Controller(FMC) + Memory Mapped Structure for FMC Controller +@{ */ + +typedef struct +{ + + + /** + * @var FMC_T::ISPCTL + * Offset: 0x00 ISP Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ISPEN |ISP Enable Bit (Write Protection) + * | | |ISP function enable bit. Set this bit to enable ISP function. + * | | |0 = ISP function Disabled. + * | | |1 = ISP function Enabled. + * | | |Note: This bit is write-protected. Refer to the SYS_REGLCTL register. + * |[1] |BS |Boot Select (Write Protection) + * | | |Set/clear this bit to select next booting from LDROM/APROM, respectively. + * | | |This bit also functions as chip booting status flag, which can be used to check where chip booted from. + * | | |This bit is initiated with the inversed value of CBS[1] (CONFIG0[7]) after any reset is happened except CPU reset (RSTS_CPU is 1) or system reset (RSTS_SYS) is happened. + * | | |0 = Booting from APROM. + * | | |1 = Booting from LDROM. + * | | |Note: This bit is write-protected. Refer to the SYS_REGLCTL register. + * |[2] |SPUEN |SPROM Update Enable Bit (Write Protection) + * | | |0 = SPROM cannot be updated. + * | | |1 = SPROM can be updated. + * | | |Note: This bit is write-protected. Refer to the SYS_REGLCTL register. + * |[3] |APUEN |APROM Update Enable Bit (Write Protection) + * | | |0 = APROM cannot be updated when the chip runs in APROM. + * | | |1 = APROM can be updated when the chip runs in APROM. + * | | |Note: This bit is write-protected. Refer to the SYS_REGLCTL register. + * |[4] |CFGUEN |CONFIG Update Enable Bit (Write Protection) + * | | |0 = CONFIG cannot be updated. + * | | |1 = CONFIG can be updated. + * | | |Note: This bit is write-protected. Refer to the SYS_REGLCTL register. + * |[5] |LDUEN |LDROM Update Enable Bit (Write Protection) + * | | |LDROM update enable bit. + * | | |0 = LDROM cannot be updated. + * | | |1 = LDROM can be updated. + * | | |Note: This bit is write-protected. Refer to the SYS_REGLCTL register. + * |[6] |ISPFF |ISP Fail Flag (Write Protection) + * | | |This bit is set by hardware when a triggered ISP meets any of the following conditions: + * | | |This bit needs to be cleared by writing 1 to it. + * | | |(1) APROM writes to itself if APUEN is set to 0. + * | | |(2) LDROM writes to itself if LDUEN is set to 0. + * | | |(3) CONFIG is erased/programmed if CFGUEN is set to 0. + * | | |(4) SPROM is erased/programmed if SPUEN is set to 0. + * | | |(5) SPROM is programmed at SPROM secured mode. + * | | |(6) Page Erase command at LOCK mode with ICE connection. + * | | |(7) Erase or Program command at brown-out detected. + * | | |(8) Destination address is illegal, such as over an available range. + * | | |(9) Invalid ISP commands. + * | | |Note: This bit is write-protected. Refer to the SYS_REGLCTL register. + * @var FMC_T::ISPADDR + * Offset: 0x04 ISP Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |ISPADDR |ISP Address + * | | |The NuMicro M031 series is equipped with embedded flash. + * | | |ISPADDR[1:0] must be kept 00 for ISP 32-bit operation and ISPADR[8:0] must be kept all 0 for Vector Page Re-map Command. + * | | |For CRC32 Checksum Calculation command, this field is the flash starting address for checksum calculation, 512 bytes alignment is necessary for checksum calculation. + * @var FMC_T::ISPDAT + * Offset: 0x08 ISP Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |ISPDAT |ISP Data + * | | |Write data to this register before ISP program operation. + * | | |Read data from this register after ISP read operation. + * | | |For Run CRC32 Checksum Calculation command, ISPDAT is the memory size (byte) and 512 bytes alignment. + * | | |For ISP Read Checksum command, ISPDAT is the checksum result. + * | | |If ISPDAT = 0x0000_0000, it means that (1) the checksum calculation is in progress, or (2) the memory range for checksum calculation is incorrect. + * @var FMC_T::ISPCMD + * Offset: 0x0C ISP Command Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[6:0] |CMD |ISP CMD + * | | |ISP command table is shown below: + * | | |0x00 = FLASH Read. + * | | |0x04 = Read Unique ID.. + * | | |0x0B = Read Company ID. + * | | |0x0C = Read Device ID. + * | | |0x0D = Read CRC32 Checksum. + * | | |0x21 = FLASH 32-bit Program. + * | | |0x22 = FLASH Page Erase.. + * | | |0x2D = Run CRC32 Checksum Calculation. + * | | |0x2E = Vector Remap. + * | | |The other commands are invalid. + * @var FMC_T::ISPTRG + * Offset: 0x10 ISP Trigger Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ISPGO |ISP Start Trigger (Write Protection) + * | | |Write 1 to start ISP operation and this bit will be cleared to 0 by hardware automatically when ISP operation is finished. + * | | |0 = ISP operation is finished. + * | | |1 = ISP is progressed. + * | | |Note: This bit is write-protected. Refer to the SYS_REGLCTL register. + * @var FMC_T::DFBA + * Offset: 0x14 Data Flash Base Address + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |DFBA |Data Flash Base Address + * | | |This register indicates Data Flash start address. It is a read only register. + * | | |The Data Flash is shared with APROM. the content of this register is loaded from CONFIG1. + * | | |This register is valid when DFEN (CONFIG0[0]) =0. + * @var FMC_T::FTCTL + * Offset: 0x18 Flash Access Time Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[6:4] |FOM |Frequency Optimization Mode (Write Protect) + * | | |The NuMicro Mini58TM series support adjustable flash access timing to optimize the flash access cycles in different working frequency. + * | | |0x1 = Frequency <= 24MHz.. + * | | |Others = Frequency <= 50MHz. + * | | |Note: This bit is write-protected. Refer to the SYS_REGLCTL register. + * @var FMC_T::ISPSTS + * Offset: 0x40 ISP Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ISPBUSY |ISP BUSY (Read Only) + * | | |0 = ISP operation is finished. + * | | |1 = ISP operation is busy. + * |[2:1] |CBS |Boot Selection of CONFIG (Read Only) + * | | |This bit is initiated with the CBS (CONFIG0[7:6]) after any reset is happened except CPU reset (RSTS_CPU is 1) or system reset (RSTS_SYS) is happened. + * | | |00 = LDROM with IAP mode. + * | | |01 = LDROM without IAP mode. + * | | |10 = APROM with IAP mode. + * | | |11 = APROM without IAP mode. + * |[6] |ISPFF |ISP Fail Flag (Write Protection) + * | | |This bit is the mirror of ISPFF (FMC_ISPCTL[6]), it needs to be cleared by writing 1 to FMC_ISPCTL[6] or FMC_ISPSTS[6]. + * | | |This bit is set by hardware when a triggered ISP meets any of the following conditions: + * | | |(1) APROM writes to itself if APUEN is set to 0. + * | | |(2) LDROM writes to itself if LDUEN is set to 0. + * | | |(3) CONFIG is erased/programmed if CFGUEN is set to 0. + * | | |(4) SPROM is erased/programmed if SPUEN is set to 0. + * | | |(5) SPROM is programmed at SPROM secured mode. + * | | |(6) Page Erase command at LOCK mode with ICE connection. + * | | |(7) Erase or Program command at brown-out detected. + * | | |(8) Destination address is illegal, such as over an available range. + * | | |(9) Invalid ISP commands. + * |[29:9] |VECMAP |Vector Page Mapping Address (Read Only) + * | | |All access to 0x0000_0000~0x0000_01FF is remapped to the Flash memory or SRAM address {VECMAP[20:0], 9'h000} ~ {VECMAP[20:0], 9'h1FF}, except SPROM. + * | | |VECMAP [20:19] = 00 system vector address is mapped to Flash memory. + * | | |VECMAP [20:19] = 10 system vector address is mapped to SRAM memory. + * | | |VECMAP [18:12] should be 0.All access to 0x0000_0000~0x0000_01FF is remapped to the flash memory address {VECMAP[11:0], 9'h000} ~ {VECMAP[11:0], 9'h1FF} + * |[31] |SCODE |Security Code Active Flag + * | | |This bit is set to 1 by hardware when detecting SPROM secured code is active at flash initialization, or software writes 1 to this bit to make secured code active; this bit is only cleared by SPROM page erase operation. + * | | |0 = SPROM secured code is inactive. + * | | |1 = SPROM secured code is active. + */ + __IO uint32_t ISPCTL; /*!< [0x0000] ISP Control Register */ + __IO uint32_t ISPADDR; /*!< [0x0004] ISP Address Register */ + __IO uint32_t ISPDAT; /*!< [0x0008] ISP Data Register */ + __IO uint32_t ISPCMD; /*!< [0x000c] ISP Command Register */ + __IO uint32_t ISPTRG; /*!< [0x0010] ISP Trigger Control Register */ + __I uint32_t DFBA; /*!< [0x0014] Data Flash Base Address */ + __IO uint32_t FTCTL; /*!< [0x0018] Flash Access Time Control Register */ + __IO uint32_t ICPCTL; /*!< [0x001C] Flash ICP Enable Control Register */ + __I uint32_t RESERVE0[8]; + __IO uint32_t ISPSTS; /*!< [0x0040] ISP Status Register */ + __I uint32_t RESERVE1[15]; + __IO uint32_t MPDAT0; /*!< [0x0080] ISP Data0 Register */ + __IO uint32_t MPDAT1; /*!< [0x0084] ISP Data1 Register */ + __IO uint32_t MPDAT2; /*!< [0x0088] ISP Data2 Register */ + __IO uint32_t MPDAT3; /*!< [0x008c] ISP Data3 Register */ + __I uint32_t RESERVE2[12]; + __I uint32_t MPSTS; /*!< [0x00c0] ISP Multi-Program Status Register */ + __I uint32_t MPADDR; /*!< [0x00c4] ISP Multi-Program Address Register */ + __I uint32_t RESERVE3[0x3CD]; + __I uint32_t VERSION; /*!< [0x0FFC] FMC Version Register */ +} FMC_T; + +/** + @addtogroup FMC_CONST FMC Bit Field Definition + Constant Definitions for FMC Controller +@{ */ + +#define FMC_ISPCTL_ISPEN_Pos (0) /*!< FMC_T::ISPCTL: ISPEN Position */ +#define FMC_ISPCTL_ISPEN_Msk (0x1ul << FMC_ISPCTL_ISPEN_Pos) /*!< FMC_T::ISPCTL: ISPEN Mask */ + +#define FMC_ISPCTL_BS_Pos (1) /*!< FMC_T::ISPCTL: BS Position */ +#define FMC_ISPCTL_BS_Msk (0x1ul << FMC_ISPCTL_BS_Pos) /*!< FMC_T::ISPCTL: BS Mask */ + +#define FMC_ISPCTL_SPUEN_Pos (2) /*!< FMC_T::ISPCTL: SPUEN Position */ +#define FMC_ISPCTL_SPUEN_Msk (0x1ul << FMC_ISPCTL_SPUEN_Pos) /*!< FMC_T::ISPCTL: SPUEN Mask */ + +#define FMC_ISPCTL_APUEN_Pos (3) /*!< FMC_T::ISPCTL: APUEN Position */ +#define FMC_ISPCTL_APUEN_Msk (0x1ul << FMC_ISPCTL_APUEN_Pos) /*!< FMC_T::ISPCTL: APUEN Mask */ + +#define FMC_ISPCTL_CFGUEN_Pos (4) /*!< FMC_T::ISPCTL: CFGUEN Position */ +#define FMC_ISPCTL_CFGUEN_Msk (0x1ul << FMC_ISPCTL_CFGUEN_Pos) /*!< FMC_T::ISPCTL: CFGUEN Mask */ + +#define FMC_ISPCTL_LDUEN_Pos (5) /*!< FMC_T::ISPCTL: LDUEN Position */ +#define FMC_ISPCTL_LDUEN_Msk (0x1ul << FMC_ISPCTL_LDUEN_Pos) /*!< FMC_T::ISPCTL: LDUEN Mask */ + +#define FMC_ISPCTL_ISPFF_Pos (6) /*!< FMC_T::ISPCTL: ISPFF Position */ +#define FMC_ISPCTL_ISPFF_Msk (0x1ul << FMC_ISPCTL_ISPFF_Pos) /*!< FMC_T::ISPCTL: ISPFF Mask */ + +#define FMC_ISPCTL_INTEN_Pos (24) /*!< FMC_T::ISPCTL: INTEN Position */ +#define FMC_ISPCTL_INTEN_Msk (0x1ul << FMC_ISPCTL_INTEN_Pos) /*!< FMC_T::ISPCTL: INTEN Mask */ + +#define FMC_ISPADDR_ISPADDR_Pos (0) /*!< FMC_T::ISPADDR: ISPADDR Position */ +#define FMC_ISPADDR_ISPADDR_Msk (0xfffffffful << FMC_ISPADDR_ISPADDR_Pos) /*!< FMC_T::ISPADDR: ISPADDR Mask */ + +#define FMC_ISPDAT_ISPDAT_Pos (0) /*!< FMC_T::ISPDAT: ISPDAT Position */ +#define FMC_ISPDAT_ISPDAT_Msk (0xfffffffful << FMC_ISPDAT_ISPDAT_Pos) /*!< FMC_T::ISPDAT: ISPDAT Mask */ + +#define FMC_ISPCMD_CMD_Pos (0) /*!< FMC_T::ISPCMD: CMD Position */ +#define FMC_ISPCMD_CMD_Msk (0x7ful << FMC_ISPCMD_CMD_Pos) /*!< FMC_T::ISPCMD: CMD Mask */ + +#define FMC_ISPTRG_ISPGO_Pos (0) /*!< FMC_T::ISPTRG: ISPGO Position */ +#define FMC_ISPTRG_ISPGO_Msk (0x1ul << FMC_ISPTRG_ISPGO_Pos) /*!< FMC_T::ISPTRG: ISPGO Mask */ + +#define FMC_DFBA_DFBA_Pos (0) /*!< FMC_T::DFBA: DFBA Position */ +#define FMC_DFBA_DFBA_Msk (0xfffffffful << FMC_DFBA_DFBA_Pos) /*!< FMC_T::DFBA: DFBA Mask */ + +#define FMC_FTCTL_FOM_Pos (4) /*!< FMC_T::FTCTL: FOM Position */ +#define FMC_FTCTL_FOM_Msk (0x7ul << FMC_FTCTL_FOM_Pos) /*!< FMC_T::FTCTL: FOM Mask */ + +#define FMC_ISPSTS_ISPBUSY_Pos (0) /*!< FMC_T::ISPSTS: ISPBUSY Position */ +#define FMC_ISPSTS_ISPBUSY_Msk (0x1ul << FMC_ISPSTS_ISPBUSY_Pos) /*!< FMC_T::ISPSTS: ISPBUSY Mask */ + +#define FMC_ISPSTS_CBS_Pos (1) /*!< FMC_T::ISPSTS: CBS Position */ +#define FMC_ISPSTS_CBS_Msk (0x3ul << FMC_ISPSTS_CBS_Pos) /*!< FMC_T::ISPSTS: CBS Mask */ + +#define FMC_ISPSTS_PGFF_Pos (5) /*!< FMC_T::ISPSTS: PGFF Position */ +#define FMC_ISPSTS_PGFF_Msk (0x1ul << FMC_ISPSTS_PGFF_Pos) /*!< FMC_T::ISPSTS: PGFF Mask */ + +#define FMC_ISPSTS_ISPFF_Pos (6) /*!< FMC_T::ISPSTS: ISPFF Position */ +#define FMC_ISPSTS_ISPFF_Msk (0x1ul << FMC_ISPSTS_ISPFF_Pos) /*!< FMC_T::ISPSTS: ISPFF Mask */ + +#define FMC_ISPSTS_ALLONE_Pos (7) /*!< FMC_T::ISPSTS: ISPFF Position */ +#define FMC_ISPSTS_ALLONE_Msk (0x1ul << FMC_ISPSTS_ALLONE_Pos) + +#define FMC_ISPSTS_INTFLAG_Pos (8) /*!< FMC_T::ISPSTS: INTFLAG Position */ +#define FMC_ISPSTS_INTFLAG_Msk (0x1ul << FMC_ISPSTS_INTFLAG_Pos) /*!< FMC_T::ISPSTS: INTFLAG Mask */ + +#define FMC_ISPSTS_VECMAP_Pos (9) /*!< FMC_T::ISPSTS: VECMAP Position */ +#define FMC_ISPSTS_VECMAP_Msk (0x1ffffful << FMC_ISPSTS_VECMAP_Pos) /*!< FMC_T::ISPSTS: VECMAP Mask */ + +#define FMC_ISPSTS_SCODE_Pos (31) /*!< FMC_T::ISPSTS: SCODE Position */ +#define FMC_ISPSTS_SCODE_Msk (0x1ul << FMC_ISPSTS_SCODE_Pos) /*!< FMC_T::ISPSTS: SCODE Mask */ + +#define FMC_MPDAT0_ISPDAT0_Pos (0) /*!< FMC_T::MPDAT0: ISPDAT0 Position */ +#define FMC_MPDAT0_ISPDAT0_Msk (0xfffffffful << FMC_MPDAT0_ISPDAT0_Pos) /*!< FMC_T::MPDAT0: ISPDAT0 Mask */ + +#define FMC_MPDAT1_ISPDAT1_Pos (0) /*!< FMC_T::MPDAT1: ISPDAT1 Position */ +#define FMC_MPDAT1_ISPDAT1_Msk (0xfffffffful << FMC_MPDAT1_ISPDAT1_Pos) /*!< FMC_T::MPDAT1: ISPDAT1 Mask */ + +#define FMC_MPDAT2_ISPDAT2_Pos (0) /*!< FMC_T::MPDAT2: ISPDAT2 Position */ +#define FMC_MPDAT2_ISPDAT2_Msk (0xfffffffful << FMC_MPDAT2_ISPDAT2_Pos) /*!< FMC_T::MPDAT2: ISPDAT2 Mask */ + +#define FMC_MPDAT3_ISPDAT3_Pos (0) /*!< FMC_T::MPDAT3: ISPDAT3 Position */ +#define FMC_MPDAT3_ISPDAT3_Msk (0xfffffffful << FMC_MPDAT3_ISPDAT3_Pos) /*!< FMC_T::MPDAT3: ISPDAT3 Mask */ + +#define FMC_MPSTS_MPBUSY_Pos (0) /*!< FMC_T::MPSTS: MPBUSY Position */ +#define FMC_MPSTS_MPBUSY_Msk (0x1ul << FMC_MPSTS_MPBUSY_Pos) /*!< FMC_T::MPSTS: MPBUSY Mask */ + +#define FMC_MPSTS_PPGO_Pos (1) /*!< FMC_T::MPSTS: PPGO Position */ +#define FMC_MPSTS_PPGO_Msk (0x1ul << FMC_MPSTS_PPGO_Pos) /*!< FMC_T::MPSTS: PPGO Mask */ + +#define FMC_MPSTS_ISPFF_Pos (2) /*!< FMC_T::MPSTS: ISPFF Position */ +#define FMC_MPSTS_ISPFF_Msk (0x1ul << FMC_MPSTS_ISPFF_Pos) /*!< FMC_T::MPSTS: ISPFF Mask */ + +#define FMC_MPSTS_D0_Pos (4) /*!< FMC_T::MPSTS: D0 Position */ +#define FMC_MPSTS_D0_Msk (0x1ul << FMC_MPSTS_D0_Pos) /*!< FMC_T::MPSTS: D0 Mask */ + +#define FMC_MPSTS_D1_Pos (5) /*!< FMC_T::MPSTS: D1 Position */ +#define FMC_MPSTS_D1_Msk (0x1ul << FMC_MPSTS_D1_Pos) /*!< FMC_T::MPSTS: D1 Mask */ + +#define FMC_MPSTS_D2_Pos (6) /*!< FMC_T::MPSTS: D2 Position */ +#define FMC_MPSTS_D2_Msk (0x1ul << FMC_MPSTS_D2_Pos) /*!< FMC_T::MPSTS: D2 Mask */ + +#define FMC_MPSTS_D3_Pos (7) /*!< FMC_T::MPSTS: D3 Position */ +#define FMC_MPSTS_D3_Msk (0x1ul << FMC_MPSTS_D3_Pos) /*!< FMC_T::MPSTS: D3 Mask */ + +#define FMC_MPADDR_MPADDR_Pos (0) /*!< FMC_T::MPADDR: MPADDR Position */ +#define FMC_MPADDR_MPADDR_Msk (0xfffffffful << FMC_MPADDR_MPADDR_Pos) /*!< FMC_T::MPADDR: MPADDR Mask */ + +/**@}*/ /* FMC_CONST */ +/**@}*/ /* end of FMC register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __FMC_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/gpio_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/gpio_reg.h new file mode 100644 index 0000000000..ab3d03ff02 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/gpio_reg.h @@ -0,0 +1,710 @@ +/**************************************************************************//** + * @file gpio_reg.h + * @version V1.00 + * @brief GPIO register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __GPIO_REG_H__ +#define __GPIO_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup GPIO General Purpose Input/Output Controller (GPIO) + Memory Mapped Structure for GPIO Controller +@{ */ + +typedef struct +{ + + + /** + * @var GPIO_T::MODE + * Offset: 0x00/0x40/0x80/0xC0/0x100/0x140 PA-PF I/O Mode Control + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2n+1:2n]|MODEn |Port A-F I/O Pin[n] Mode Control + * | | |Determine each I/O mode of Px.n pins. + * | | |00 = Px.n is in Input mode. + * | | |01 = Px.n is in Push-pull Output mode. + * | | |10 = Px.n is in Open-drain Output mode. + * | | |11 = Px.n is in Quasi-bidirectional mode. + * | | |Note1: The initial value of this field is defined by CIOINI (CONFIG0 [10]). If CIOINI is set to 0, the default value is 0xFFFF_FFFF and all pins will be quasi-bidirectional mode after chip powered on. If CIOINI is set to 1, the default value is 0x0000_0000 and all pins will be input mode after chip powered on. + * | | |Note2: + * | | |The PC.8~13,15/PD.4~14/PF.7~13 pin is ignored. + * @var GPIO_T::DINOFF + * Offset: 0x04/0x44/0x84/0xC4/0x104/0x144 PA-PF Digital Input Path Disable Control + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n+16] |DINOFFn |Port A-F Pin[n] Digital Input Path Disable Bit + * | | |Each of these bits is used to control if the digital input path of corresponding Px.n pin is disabled. If input is analog signal, users can disable Px.n digital input path to avoid input current leakage. + * | | |0 = Px.n digital input path Enabled. + * | | |1 = Px.n digital input path Disabled (digital input tied to low). + * | | |Note: + * | | |The PC.8~13,15/PD.4~14/PF.7~13 pin is ignored. + * @var GPIO_T::DOUT + * Offset: 0x08/0x48/0x88/0xC8/0x108/0x148 PA-PF Data Output Value + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |DOUTn |Port A-F Pin[n] Output Value + * | | |Each of these bits controls the status of a Px.n pin when the Px.n is configured as Push-pull output, Open-drain output or Quasi-bidirectional mode. + * | | |0 = Px.n will drive Low if the Px.n pin is configured as Push-pull output, Open-drain output or Quasi-bidirectional mode. + * | | |1 = Px.n will drive High if the Px.n pin is configured as Push-pull output or Quasi-bidirectional mode. + * | | |Note: + * | | |The PC.8~13,15/PD.4~14/PF.7~13 pin is ignored. + * @var GPIO_T::DATMSK + * Offset: 0x0C/0x4C/0x8C/0xCC/0x10C/0x14C PA-PF Data Output Write Mask + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |DATMSKn |Port A-F Pin[n] Data Output Write Mask + * | | |These bits are used to protect the corresponding DOUT (Px_DOUT[n]) bit. When the DATMSK (Px_DATMSK[n]) bit is set to 1, the corresponding DOUT (Px_DOUT[n]) bit is protected. If the write signal is masked, writing data to the protect bit is ignored. + * | | |0 = Corresponding DOUT (Px_DOUT[n]) bit can be updated. + * | | |1 = Corresponding DOUT (Px_DOUT[n]) bit protected. + * | | |Note1: This function only protects the corresponding DOUT (Px_DOUT[n]) bit, and will not protect the corresponding PDIO (Pxn_PDIO[0]) bit. + * | | |Note2: + * | | |The PC.8~13,15/PD.4~14/PF.7~13 pin is ignored. + * @var GPIO_T::PIN + * Offset: 0x10/0x50/0x90/0xD0/0x110/0x150 PA-PF Pin Value + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |PINn |Port A-F Pin[n] Pin Value + * | | |Each bit of the register reflects the actual status of the respective Px.n pin. If the bit is 1, it indicates the corresponding pin status is high; else the pin status is low. + * | | |Note: + * | | |The PC.8~13,15/PD.4~14/PF.7~13 pin is ignored. + * @var GPIO_T::DBEN + * Offset: 0x14/0x54/0x94/0xD4/0x114/0x154 PA-PF De-Bounce Enable Control + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |DBENn |Port A-F Pin[n] Input Signal De-bounce Enable Bit + * | | |The DBEN[n] bit is used to enable the de-bounce function for each corresponding bit. + * | | |If the input signal pulse width cannot be sampled by continuous two de-bounce sample cycle, the input signal transition is seen as the signal bounce and will not trigger the interrupt. The de-bounce clock source is controlled by DBCLKSRC (GPIO_DBCTL [4]), one de-bounce sample cycle period is controlled by DBCLKSEL (GPIO_DBCTL [3:0]). + * | | |0 = Px.n de-bounce function Disabled. + * | | |1 = Px.n de-bounce function Enabled. + * | | |The de-bounce function is valid only for edge triggered interrupt. If the interrupt mode is level triggered, the de-bounce enable bit is ignored. + * | | |Note: + * | | |The PC.8~13,15/PD.4~14/PF.7~13 pin is ignored. + * @var GPIO_T::INTTYPE + * Offset: 0x18/0x58/0x98/0xD8/0x118/0x158 PA-PF Interrupt Trigger Type Control + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |TYPEn |Port A-F Pin[n] Edge or Level Detection Interrupt Trigger Type Control + * | | |TYPE (Px_INTTYPE[n]) bit is used to control the triggered interrupt is by level trigger or by edge trigger. If the interrupt is by edge trigger, the trigger source can be controlled by de-bounce. + * | | |If the interrupt is by level trigger, the input source is sampled by one HCLK clock and generates the interrupt. + * | | |0 = Edge trigger interrupt. + * | | |1 = Level trigger interrupt. + * | | |If the pin is set as the level trigger interrupt, only one level can be set on the registers RHIEN (Px_INTEN[n+16])/FLIEN (Px_INTEN[n]). If both levels to trigger interrupt are set, the setting is ignored and no interrupt will occur. + * | | |The de-bounce function is valid only for edge triggered interrupt. If the interrupt mode is level triggered, the de-bounce enable bit is ignored. + * | | |Note: + * | | |The PC.8~13,15/PD.4~14/PF.7~13 pin is ignored. + * @var GPIO_T::INTEN + * Offset: 0x1C/0x5C/0x9C/0xDC/0x11C/0x15C PA-PF Interrupt Enable Control + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |FLIENn |Port A-F Pin[n] Falling Edge or Low Level Interrupt Trigger Type Enable Bit + * | | |The FLIEN (Px_INTEN[n]) bit is used to enable the interrupt for each of the corresponding input Px.n pin. Set bit to 1 also enable the pin wake-up function. + * | | |When setting the FLIEN (Px_INTEN[n]) bit to 1 : + * | | |If the interrupt is level trigger (TYPE (Px_INTTYPE[n]) bit is set to 1), the input Px.n pin will generate the interrupt while this pin state is at low level. + * | | |If the interrupt is edge trigger(TYPE (Px_INTTYPE[n]) bit is set to 0), the input Px.n pin will generate the interrupt while this pin state changed from high to low. + * | | |0 = Px.n level low or high to low interrupt Disabled. + * | | |1 = Px.n level low or high to low interrupt Enabled. + * | | |Note: + * | | |The PC.8~13,15/PD.4~14/PF.7~13 pin is ignored. + * |[n+16] |RHIENn |Port A-F Pin[n] Rising Edge or High Level Interrupt Trigger Type Enable Bit + * | | |The RHIEN (Px_INTEN[n+16]) bit is used to enable the interrupt for each of the corresponding input Px.n pin. Set bit to 1 also enable the pin wake-up function. + * | | |When setting the RHIEN (Px_INTEN[n+16]) bit to 1 : + * | | |If the interrupt is level trigger (TYPE (Px_INTTYPE[n]) bit is set to 1), the input Px.n pin will generate the interrupt while this pin state is at high level. + * | | |If the interrupt is edge trigger (TYPE (Px_INTTYPE[n]) bit is set to 0), the input Px.n pin will generate the interrupt while this pin state changed from low to high. + * | | |0 = Px.n level high or low to high interrupt Disabled. + * | | |1 = Px.n level high or low to high interrupt Enabled. + * | | |Note: + * | | |The PC.8~13,15/PD.4~14/PF.7~13 pin is ignored. + * @var GPIO_T::INTSRC + * Offset: 0x20/0x60/0xA0/0xE0/0x120/0x160 PA-PF Interrupt Source Flag + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[n] |INTSRCn |Port A-F Pin[n] Interrupt Source Flag + * | | |Write Operation : + * | | |0 = No action. + * | | |1 = Clear the corresponding pending interrupt. + * | | |Read Operation : + * | | |0 = No interrupt at Px.n. + * | | |1 = Px.n generates an interrupt. + * | | |Note: + * | | |The PC.8~13,15/PD.4~14/PF.7~13 pin is ignored. + */ + + __IO uint32_t MODE; /*!< [0x0000] PA I/O Mode Control */ + __IO uint32_t DINOFF; /*!< [0x0004] PA Digital Input Path Disable Control */ + __IO uint32_t DOUT; /*!< [0x0008] PA Data Output Value */ + __IO uint32_t DATMSK; /*!< [0x000c] PA Data Output Write Mask */ + __I uint32_t PIN; /*!< [0x0010] PA Pin Value */ + __IO uint32_t DBEN; /*!< [0x0014] PA De-bounce Enable Control Register */ + __IO uint32_t INTTYPE; /*!< [0x0018] PA Interrupt Trigger Type Control */ + __IO uint32_t INTEN; /*!< [0x001c] PA Interrupt Enable Control Register */ + __IO uint32_t INTSRC; /*!< [0x0020] PA Interrupt Source Flag */ +} GPIO_T; + +typedef struct +{ + + + /** + * @var GPIO_DBCTL_T::DBCTL + * Offset: 0x180 Interrupt De-bounce Control + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |DBCLKSEL |De-bounce Sampling Cycle Selection + * | | |0000 = Sample interrupt input once per 1 clocks. + * | | |0001 = Sample interrupt input once per 2 clocks. + * | | |0010 = Sample interrupt input once per 4 clocks. + * | | |0011 = Sample interrupt input once per 8 clocks. + * | | |0100 = Sample interrupt input once per 16 clocks. + * | | |0101 = Sample interrupt input once per 32 clocks. + * | | |0110 = Sample interrupt input once per 64 clocks. + * | | |0111 = Sample interrupt input once per 128 clocks. + * | | |1000 = Sample interrupt input once per 256 clocks. + * | | |1001 = Sample interrupt input once per 2*256 clocks. + * | | |1010 = Sample interrupt input once per 4*256 clocks. + * | | |1011 = Sample interrupt input once per 8*256 clocks. + * | | |1100 = Sample interrupt input once per 16*256 clocks. + * | | |1101 = Sample interrupt input once per 32*256 clocks. + * | | |1110 = Sample interrupt input once per 64*256 clocks. + * | | |1111 = Sample interrupt input once per 128*256 clocks. + * |[4] |DBCLKSRC |De-bounce Counter Clock Source Selection + * | | |0 = De-bounce counter clock source is the HCLK. + * | | |1 = De-bounce counter clock source is the 32 kHz internal low speed RC oscillator (LIRC). + * |[5] |ICLKON |Interrupt Clock on Mode + * | | |0 = Edge detection circuit is active only if I/O pin corresponding RHIEN (Px_INTEN[n+16])/FLIEN (Px_INTEN[n]) bit is set to 1. + * | | |1 = All I/O pins edge detection circuit is always active after reset. + * | | |Note: It is recommended to disable this bit to save system power if no special application concern. + */ + + __IO uint32_t DBCTL; /*!< [0x0440] Interrupt De-bounce Control Register */ +} GPIO_DBCTL_T; + + +/** + @addtogroup GPIO_CONST GPIO Bit Field Definition + Constant Definitions for GPIO Controller +@{ */ + +#define GPIO_MODE_MODE0_Pos (0) /*!< GPIO_T::MODE: MODE0 Position */ +#define GPIO_MODE_MODE0_Msk (0x3ul << GPIO_MODE_MODE0_Pos) /*!< GPIO_T::MODE: MODE0 Mask */ + +#define GPIO_MODE_MODE1_Pos (2) /*!< GPIO_T::MODE: MODE1 Position */ +#define GPIO_MODE_MODE1_Msk (0x3ul << GPIO_MODE_MODE1_Pos) /*!< GPIO_T::MODE: MODE1 Mask */ + +#define GPIO_MODE_MODE2_Pos (4) /*!< GPIO_T::MODE: MODE2 Position */ +#define GPIO_MODE_MODE2_Msk (0x3ul << GPIO_MODE_MODE2_Pos) /*!< GPIO_T::MODE: MODE2 Mask */ + +#define GPIO_MODE_MODE3_Pos (6) /*!< GPIO_T::MODE: MODE3 Position */ +#define GPIO_MODE_MODE3_Msk (0x3ul << GPIO_MODE_MODE3_Pos) /*!< GPIO_T::MODE: MODE3 Mask */ + +#define GPIO_MODE_MODE4_Pos (8) /*!< GPIO_T::MODE: MODE4 Position */ +#define GPIO_MODE_MODE4_Msk (0x3ul << GPIO_MODE_MODE4_Pos) /*!< GPIO_T::MODE: MODE4 Mask */ + +#define GPIO_MODE_MODE5_Pos (10) /*!< GPIO_T::MODE: MODE5 Position */ +#define GPIO_MODE_MODE5_Msk (0x3ul << GPIO_MODE_MODE5_Pos) /*!< GPIO_T::MODE: MODE5 Mask */ + +#define GPIO_MODE_MODE6_Pos (12) /*!< GPIO_T::MODE: MODE6 Position */ +#define GPIO_MODE_MODE6_Msk (0x3ul << GPIO_MODE_MODE6_Pos) /*!< GPIO_T::MODE: MODE6 Mask */ + +#define GPIO_MODE_MODE7_Pos (14) /*!< GPIO_T::MODE: MODE7 Position */ +#define GPIO_MODE_MODE7_Msk (0x3ul << GPIO_MODE_MODE7_Pos) /*!< GPIO_T::MODE: MODE7 Mask */ + +#define GPIO_MODE_MODE8_Pos (16) /*!< GPIO_T::MODE: MODE8 Position */ +#define GPIO_MODE_MODE8_Msk (0x3ul << GPIO_MODE_MODE8_Pos) /*!< GPIO_T::MODE: MODE8 Mask */ + +#define GPIO_MODE_MODE9_Pos (18) /*!< GPIO_T::MODE: MODE9 Position */ +#define GPIO_MODE_MODE9_Msk (0x3ul << GPIO_MODE_MODE9_Pos) /*!< GPIO_T::MODE: MODE9 Mask */ + +#define GPIO_MODE_MODE10_Pos (20) /*!< GPIO_T::MODE: MODE10 Position */ +#define GPIO_MODE_MODE10_Msk (0x3ul << GPIO_MODE_MODE10_Pos) /*!< GPIO_T::MODE: MODE10 Mask */ + +#define GPIO_MODE_MODE11_Pos (22) /*!< GPIO_T::MODE: MODE11 Position */ +#define GPIO_MODE_MODE11_Msk (0x3ul << GPIO_MODE_MODE11_Pos) /*!< GPIO_T::MODE: MODE11 Mask */ + +#define GPIO_MODE_MODE12_Pos (24) /*!< GPIO_T::MODE: MODE12 Position */ +#define GPIO_MODE_MODE12_Msk (0x3ul << GPIO_MODE_MODE12_Pos) /*!< GPIO_T::MODE: MODE12 Mask */ + +#define GPIO_MODE_MODE13_Pos (26) /*!< GPIO_T::MODE: MODE13 Position */ +#define GPIO_MODE_MODE13_Msk (0x3ul << GPIO_MODE_MODE13_Pos) /*!< GPIO_T::MODE: MODE13 Mask */ + +#define GPIO_MODE_MODE14_Pos (28) /*!< GPIO_T::MODE: MODE14 Position */ +#define GPIO_MODE_MODE14_Msk (0x3ul << GPIO_MODE_MODE14_Pos) /*!< GPIO_T::MODE: MODE14 Mask */ + +#define GPIO_MODE_MODE15_Pos (30) /*!< GPIO_T::MODE: MODE15 Position */ +#define GPIO_MODE_MODE15_Msk (0x3ul << GPIO_MODE_MODE15_Pos) /*!< GPIO_T::MODE: MODE15 Mask */ + +#define GPIO_DINOFF_DINOFF0_Pos (16) /*!< GPIO_T::DINOFF: DINOFF0 Position */ +#define GPIO_DINOFF_DINOFF0_Msk (0x1ul << GPIO_DINOFF_DINOFF0_Pos) /*!< GPIO_T::DINOFF: DINOFF0 Mask */ + +#define GPIO_DINOFF_DINOFF1_Pos (17) /*!< GPIO_T::DINOFF: DINOFF1 Position */ +#define GPIO_DINOFF_DINOFF1_Msk (0x1ul << GPIO_DINOFF_DINOFF1_Pos) /*!< GPIO_T::DINOFF: DINOFF1 Mask */ + +#define GPIO_DINOFF_DINOFF2_Pos (18) /*!< GPIO_T::DINOFF: DINOFF2 Position */ +#define GPIO_DINOFF_DINOFF2_Msk (0x1ul << GPIO_DINOFF_DINOFF2_Pos) /*!< GPIO_T::DINOFF: DINOFF2 Mask */ + +#define GPIO_DINOFF_DINOFF3_Pos (19) /*!< GPIO_T::DINOFF: DINOFF3 Position */ +#define GPIO_DINOFF_DINOFF3_Msk (0x1ul << GPIO_DINOFF_DINOFF3_Pos) /*!< GPIO_T::DINOFF: DINOFF3 Mask */ + +#define GPIO_DINOFF_DINOFF4_Pos (20) /*!< GPIO_T::DINOFF: DINOFF4 Position */ +#define GPIO_DINOFF_DINOFF4_Msk (0x1ul << GPIO_DINOFF_DINOFF4_Pos) /*!< GPIO_T::DINOFF: DINOFF4 Mask */ + +#define GPIO_DINOFF_DINOFF5_Pos (21) /*!< GPIO_T::DINOFF: DINOFF5 Position */ +#define GPIO_DINOFF_DINOFF5_Msk (0x1ul << GPIO_DINOFF_DINOFF5_Pos) /*!< GPIO_T::DINOFF: DINOFF5 Mask */ + +#define GPIO_DINOFF_DINOFF6_Pos (22) /*!< GPIO_T::DINOFF: DINOFF6 Position */ +#define GPIO_DINOFF_DINOFF6_Msk (0x1ul << GPIO_DINOFF_DINOFF6_Pos) /*!< GPIO_T::DINOFF: DINOFF6 Mask */ + +#define GPIO_DINOFF_DINOFF7_Pos (23) /*!< GPIO_T::DINOFF: DINOFF7 Position */ +#define GPIO_DINOFF_DINOFF7_Msk (0x1ul << GPIO_DINOFF_DINOFF7_Pos) /*!< GPIO_T::DINOFF: DINOFF7 Mask */ + +#define GPIO_DINOFF_DINOFF8_Pos (24) /*!< GPIO_T::DINOFF: DINOFF8 Position */ +#define GPIO_DINOFF_DINOFF8_Msk (0x1ul << GPIO_DINOFF_DINOFF8_Pos) /*!< GPIO_T::DINOFF: DINOFF8 Mask */ + +#define GPIO_DINOFF_DINOFF9_Pos (25) /*!< GPIO_T::DINOFF: DINOFF9 Position */ +#define GPIO_DINOFF_DINOFF9_Msk (0x1ul << GPIO_DINOFF_DINOFF9_Pos) /*!< GPIO_T::DINOFF: DINOFF9 Mask */ + +#define GPIO_DINOFF_DINOFF10_Pos (26) /*!< GPIO_T::DINOFF: DINOFF10 Position */ +#define GPIO_DINOFF_DINOFF10_Msk (0x1ul << GPIO_DINOFF_DINOFF10_Pos) /*!< GPIO_T::DINOFF: DINOFF10 Mask */ + +#define GPIO_DINOFF_DINOFF11_Pos (27) /*!< GPIO_T::DINOFF: DINOFF11 Position */ +#define GPIO_DINOFF_DINOFF11_Msk (0x1ul << GPIO_DINOFF_DINOFF11_Pos) /*!< GPIO_T::DINOFF: DINOFF11 Mask */ + +#define GPIO_DINOFF_DINOFF12_Pos (28) /*!< GPIO_T::DINOFF: DINOFF12 Position */ +#define GPIO_DINOFF_DINOFF12_Msk (0x1ul << GPIO_DINOFF_DINOFF12_Pos) /*!< GPIO_T::DINOFF: DINOFF12 Mask */ + +#define GPIO_DINOFF_DINOFF13_Pos (29) /*!< GPIO_T::DINOFF: DINOFF13 Position */ +#define GPIO_DINOFF_DINOFF13_Msk (0x1ul << GPIO_DINOFF_DINOFF13_Pos) /*!< GPIO_T::DINOFF: DINOFF13 Mask */ + +#define GPIO_DINOFF_DINOFF14_Pos (30) /*!< GPIO_T::DINOFF: DINOFF14 Position */ +#define GPIO_DINOFF_DINOFF14_Msk (0x1ul << GPIO_DINOFF_DINOFF14_Pos) /*!< GPIO_T::DINOFF: DINOFF14 Mask */ + +#define GPIO_DINOFF_DINOFF15_Pos (31) /*!< GPIO_T::DINOFF: DINOFF15 Position */ +#define GPIO_DINOFF_DINOFF15_Msk (0x1ul << GPIO_DINOFF_DINOFF15_Pos) /*!< GPIO_T::DINOFF: DINOFF15 Mask */ + +#define GPIO_DOUT_DOUT0_Pos (0) /*!< GPIO_T::DOUT: DOUT0 Position */ +#define GPIO_DOUT_DOUT0_Msk (0x1ul << GPIO_DOUT_DOUT0_Pos) /*!< GPIO_T::DOUT: DOUT0 Mask */ + +#define GPIO_DOUT_DOUT1_Pos (1) /*!< GPIO_T::DOUT: DOUT1 Position */ +#define GPIO_DOUT_DOUT1_Msk (0x1ul << GPIO_DOUT_DOUT1_Pos) /*!< GPIO_T::DOUT: DOUT1 Mask */ + +#define GPIO_DOUT_DOUT2_Pos (2) /*!< GPIO_T::DOUT: DOUT2 Position */ +#define GPIO_DOUT_DOUT2_Msk (0x1ul << GPIO_DOUT_DOUT2_Pos) /*!< GPIO_T::DOUT: DOUT2 Mask */ + +#define GPIO_DOUT_DOUT3_Pos (3) /*!< GPIO_T::DOUT: DOUT3 Position */ +#define GPIO_DOUT_DOUT3_Msk (0x1ul << GPIO_DOUT_DOUT3_Pos) /*!< GPIO_T::DOUT: DOUT3 Mask */ + +#define GPIO_DOUT_DOUT4_Pos (4) /*!< GPIO_T::DOUT: DOUT4 Position */ +#define GPIO_DOUT_DOUT4_Msk (0x1ul << GPIO_DOUT_DOUT4_Pos) /*!< GPIO_T::DOUT: DOUT4 Mask */ + +#define GPIO_DOUT_DOUT5_Pos (5) /*!< GPIO_T::DOUT: DOUT5 Position */ +#define GPIO_DOUT_DOUT5_Msk (0x1ul << GPIO_DOUT_DOUT5_Pos) /*!< GPIO_T::DOUT: DOUT5 Mask */ + +#define GPIO_DOUT_DOUT6_Pos (6) /*!< GPIO_T::DOUT: DOUT6 Position */ +#define GPIO_DOUT_DOUT6_Msk (0x1ul << GPIO_DOUT_DOUT6_Pos) /*!< GPIO_T::DOUT: DOUT6 Mask */ + +#define GPIO_DOUT_DOUT7_Pos (7) /*!< GPIO_T::DOUT: DOUT7 Position */ +#define GPIO_DOUT_DOUT7_Msk (0x1ul << GPIO_DOUT_DOUT7_Pos) /*!< GPIO_T::DOUT: DOUT7 Mask */ + +#define GPIO_DOUT_DOUT8_Pos (8) /*!< GPIO_T::DOUT: DOUT8 Position */ +#define GPIO_DOUT_DOUT8_Msk (0x1ul << GPIO_DOUT_DOUT8_Pos) /*!< GPIO_T::DOUT: DOUT8 Mask */ + +#define GPIO_DOUT_DOUT9_Pos (9) /*!< GPIO_T::DOUT: DOUT9 Position */ +#define GPIO_DOUT_DOUT9_Msk (0x1ul << GPIO_DOUT_DOUT9_Pos) /*!< GPIO_T::DOUT: DOUT9 Mask */ + +#define GPIO_DOUT_DOUT10_Pos (10) /*!< GPIO_T::DOUT: DOUT10 Position */ +#define GPIO_DOUT_DOUT10_Msk (0x1ul << GPIO_DOUT_DOUT10_Pos) /*!< GPIO_T::DOUT: DOUT10 Mask */ + +#define GPIO_DOUT_DOUT11_Pos (11) /*!< GPIO_T::DOUT: DOUT11 Position */ +#define GPIO_DOUT_DOUT11_Msk (0x1ul << GPIO_DOUT_DOUT11_Pos) /*!< GPIO_T::DOUT: DOUT11 Mask */ + +#define GPIO_DOUT_DOUT12_Pos (12) /*!< GPIO_T::DOUT: DOUT12 Position */ +#define GPIO_DOUT_DOUT12_Msk (0x1ul << GPIO_DOUT_DOUT12_Pos) /*!< GPIO_T::DOUT: DOUT12 Mask */ + +#define GPIO_DOUT_DOUT13_Pos (13) /*!< GPIO_T::DOUT: DOUT13 Position */ +#define GPIO_DOUT_DOUT13_Msk (0x1ul << GPIO_DOUT_DOUT13_Pos) /*!< GPIO_T::DOUT: DOUT13 Mask */ + +#define GPIO_DOUT_DOUT14_Pos (14) /*!< GPIO_T::DOUT: DOUT14 Position */ +#define GPIO_DOUT_DOUT14_Msk (0x1ul << GPIO_DOUT_DOUT14_Pos) /*!< GPIO_T::DOUT: DOUT14 Mask */ + +#define GPIO_DOUT_DOUT15_Pos (15) /*!< GPIO_T::DOUT: DOUT15 Position */ +#define GPIO_DOUT_DOUT15_Msk (0x1ul << GPIO_DOUT_DOUT15_Pos) /*!< GPIO_T::DOUT: DOUT15 Mask */ + +#define GPIO_DATMSK_DATMSK0_Pos (0) /*!< GPIO_T::DATMSK: DATMSK0 Position */ +#define GPIO_DATMSK_DATMSK0_Msk (0x1ul << GPIO_DATMSK_DATMSK0_Pos) /*!< GPIO_T::DATMSK: DATMSK0 Mask */ + +#define GPIO_DATMSK_DATMSK1_Pos (1) /*!< GPIO_T::DATMSK: DATMSK1 Position */ +#define GPIO_DATMSK_DATMSK1_Msk (0x1ul << GPIO_DATMSK_DATMSK1_Pos) /*!< GPIO_T::DATMSK: DATMSK1 Mask */ + +#define GPIO_DATMSK_DATMSK2_Pos (2) /*!< GPIO_T::DATMSK: DATMSK2 Position */ +#define GPIO_DATMSK_DATMSK2_Msk (0x1ul << GPIO_DATMSK_DATMSK2_Pos) /*!< GPIO_T::DATMSK: DATMSK2 Mask */ + +#define GPIO_DATMSK_DATMSK3_Pos (3) /*!< GPIO_T::DATMSK: DATMSK3 Position */ +#define GPIO_DATMSK_DATMSK3_Msk (0x1ul << GPIO_DATMSK_DATMSK3_Pos) /*!< GPIO_T::DATMSK: DATMSK3 Mask */ + +#define GPIO_DATMSK_DATMSK4_Pos (4) /*!< GPIO_T::DATMSK: DATMSK4 Position */ +#define GPIO_DATMSK_DATMSK4_Msk (0x1ul << GPIO_DATMSK_DATMSK4_Pos) /*!< GPIO_T::DATMSK: DATMSK4 Mask */ + +#define GPIO_DATMSK_DATMSK5_Pos (5) /*!< GPIO_T::DATMSK: DATMSK5 Position */ +#define GPIO_DATMSK_DATMSK5_Msk (0x1ul << GPIO_DATMSK_DATMSK5_Pos) /*!< GPIO_T::DATMSK: DATMSK5 Mask */ + +#define GPIO_DATMSK_DATMSK6_Pos (6) /*!< GPIO_T::DATMSK: DATMSK6 Position */ +#define GPIO_DATMSK_DATMSK6_Msk (0x1ul << GPIO_DATMSK_DATMSK6_Pos) /*!< GPIO_T::DATMSK: DATMSK6 Mask */ + +#define GPIO_DATMSK_DATMSK7_Pos (7) /*!< GPIO_T::DATMSK: DATMSK7 Position */ +#define GPIO_DATMSK_DATMSK7_Msk (0x1ul << GPIO_DATMSK_DATMSK7_Pos) /*!< GPIO_T::DATMSK: DATMSK7 Mask */ + +#define GPIO_DATMSK_DATMSK8_Pos (8) /*!< GPIO_T::DATMSK: DATMSK8 Position */ +#define GPIO_DATMSK_DATMSK8_Msk (0x1ul << GPIO_DATMSK_DATMSK8_Pos) /*!< GPIO_T::DATMSK: DATMSK8 Mask */ + +#define GPIO_DATMSK_DATMSK9_Pos (9) /*!< GPIO_T::DATMSK: DATMSK9 Position */ +#define GPIO_DATMSK_DATMSK9_Msk (0x1ul << GPIO_DATMSK_DATMSK9_Pos) /*!< GPIO_T::DATMSK: DATMSK9 Mask */ + +#define GPIO_DATMSK_DATMSK10_Pos (10) /*!< GPIO_T::DATMSK: DATMSK10 Position */ +#define GPIO_DATMSK_DATMSK10_Msk (0x1ul << GPIO_DATMSK_DATMSK10_Pos) /*!< GPIO_T::DATMSK: DATMSK10 Mask */ + +#define GPIO_DATMSK_DATMSK11_Pos (11) /*!< GPIO_T::DATMSK: DATMSK11 Position */ +#define GPIO_DATMSK_DATMSK11_Msk (0x1ul << GPIO_DATMSK_DATMSK11_Pos) /*!< GPIO_T::DATMSK: DATMSK11 Mask */ + +#define GPIO_DATMSK_DATMSK12_Pos (12) /*!< GPIO_T::DATMSK: DATMSK12 Position */ +#define GPIO_DATMSK_DATMSK12_Msk (0x1ul << GPIO_DATMSK_DATMSK12_Pos) /*!< GPIO_T::DATMSK: DATMSK12 Mask */ + +#define GPIO_DATMSK_DATMSK13_Pos (13) /*!< GPIO_T::DATMSK: DATMSK13 Position */ +#define GPIO_DATMSK_DATMSK13_Msk (0x1ul << GPIO_DATMSK_DATMSK13_Pos) /*!< GPIO_T::DATMSK: DATMSK13 Mask */ + +#define GPIO_DATMSK_DATMSK14_Pos (14) /*!< GPIO_T::DATMSK: DATMSK14 Position */ +#define GPIO_DATMSK_DATMSK14_Msk (0x1ul << GPIO_DATMSK_DATMSK14_Pos) /*!< GPIO_T::DATMSK: DATMSK14 Mask */ + +#define GPIO_DATMSK_DATMSK15_Pos (15) /*!< GPIO_T::DATMSK: DATMSK15 Position */ +#define GPIO_DATMSK_DATMSK15_Msk (0x1ul << GPIO_DATMSK_DATMSK15_Pos) /*!< GPIO_T::DATMSK: DATMSK15 Mask */ + +#define GPIO_PIN_PIN0_Pos (0) /*!< GPIO_T::PIN: PIN0 Position */ +#define GPIO_PIN_PIN0_Msk (0x1ul << GPIO_PIN_PIN0_Pos) /*!< GPIO_T::PIN: PIN0 Mask */ + +#define GPIO_PIN_PIN1_Pos (1) /*!< GPIO_T::PIN: PIN1 Position */ +#define GPIO_PIN_PIN1_Msk (0x1ul << GPIO_PIN_PIN1_Pos) /*!< GPIO_T::PIN: PIN1 Mask */ + +#define GPIO_PIN_PIN2_Pos (2) /*!< GPIO_T::PIN: PIN2 Position */ +#define GPIO_PIN_PIN2_Msk (0x1ul << GPIO_PIN_PIN2_Pos) /*!< GPIO_T::PIN: PIN2 Mask */ + +#define GPIO_PIN_PIN3_Pos (3) /*!< GPIO_T::PIN: PIN3 Position */ +#define GPIO_PIN_PIN3_Msk (0x1ul << GPIO_PIN_PIN3_Pos) /*!< GPIO_T::PIN: PIN3 Mask */ + +#define GPIO_PIN_PIN4_Pos (4) /*!< GPIO_T::PIN: PIN4 Position */ +#define GPIO_PIN_PIN4_Msk (0x1ul << GPIO_PIN_PIN4_Pos) /*!< GPIO_T::PIN: PIN4 Mask */ + +#define GPIO_PIN_PIN5_Pos (5) /*!< GPIO_T::PIN: PIN5 Position */ +#define GPIO_PIN_PIN5_Msk (0x1ul << GPIO_PIN_PIN5_Pos) /*!< GPIO_T::PIN: PIN5 Mask */ + +#define GPIO_PIN_PIN6_Pos (6) /*!< GPIO_T::PIN: PIN6 Position */ +#define GPIO_PIN_PIN6_Msk (0x1ul << GPIO_PIN_PIN6_Pos) /*!< GPIO_T::PIN: PIN6 Mask */ + +#define GPIO_PIN_PIN7_Pos (7) /*!< GPIO_T::PIN: PIN7 Position */ +#define GPIO_PIN_PIN7_Msk (0x1ul << GPIO_PIN_PIN7_Pos) /*!< GPIO_T::PIN: PIN7 Mask */ + +#define GPIO_PIN_PIN8_Pos (8) /*!< GPIO_T::PIN: PIN8 Position */ +#define GPIO_PIN_PIN8_Msk (0x1ul << GPIO_PIN_PIN8_Pos) /*!< GPIO_T::PIN: PIN8 Mask */ + +#define GPIO_PIN_PIN9_Pos (9) /*!< GPIO_T::PIN: PIN9 Position */ +#define GPIO_PIN_PIN9_Msk (0x1ul << GPIO_PIN_PIN9_Pos) /*!< GPIO_T::PIN: PIN9 Mask */ + +#define GPIO_PIN_PIN10_Pos (10) /*!< GPIO_T::PIN: PIN10 Position */ +#define GPIO_PIN_PIN10_Msk (0x1ul << GPIO_PIN_PIN10_Pos) /*!< GPIO_T::PIN: PIN10 Mask */ + +#define GPIO_PIN_PIN11_Pos (11) /*!< GPIO_T::PIN: PIN11 Position */ +#define GPIO_PIN_PIN11_Msk (0x1ul << GPIO_PIN_PIN11_Pos) /*!< GPIO_T::PIN: PIN11 Mask */ + +#define GPIO_PIN_PIN12_Pos (12) /*!< GPIO_T::PIN: PIN12 Position */ +#define GPIO_PIN_PIN12_Msk (0x1ul << GPIO_PIN_PIN12_Pos) /*!< GPIO_T::PIN: PIN12 Mask */ + +#define GPIO_PIN_PIN13_Pos (13) /*!< GPIO_T::PIN: PIN13 Position */ +#define GPIO_PIN_PIN13_Msk (0x1ul << GPIO_PIN_PIN13_Pos) /*!< GPIO_T::PIN: PIN13 Mask */ + +#define GPIO_PIN_PIN14_Pos (14) /*!< GPIO_T::PIN: PIN14 Position */ +#define GPIO_PIN_PIN14_Msk (0x1ul << GPIO_PIN_PIN14_Pos) /*!< GPIO_T::PIN: PIN14 Mask */ + +#define GPIO_PIN_PIN15_Pos (15) /*!< GPIO_T::PIN: PIN15 Position */ +#define GPIO_PIN_PIN15_Msk (0x1ul << GPIO_PIN_PIN15_Pos) /*!< GPIO_T::PIN: PIN15 Mask */ + +#define GPIO_DBEN_DBEN0_Pos (0) /*!< GPIO_T::DBEN: DBEN0 Position */ +#define GPIO_DBEN_DBEN0_Msk (0x1ul << GPIO_DBEN_DBEN0_Pos) /*!< GPIO_T::DBEN: DBEN0 Mask */ + +#define GPIO_DBEN_DBEN1_Pos (1) /*!< GPIO_T::DBEN: DBEN1 Position */ +#define GPIO_DBEN_DBEN1_Msk (0x1ul << GPIO_DBEN_DBEN1_Pos) /*!< GPIO_T::DBEN: DBEN1 Mask */ + +#define GPIO_DBEN_DBEN2_Pos (2) /*!< GPIO_T::DBEN: DBEN2 Position */ +#define GPIO_DBEN_DBEN2_Msk (0x1ul << GPIO_DBEN_DBEN2_Pos) /*!< GPIO_T::DBEN: DBEN2 Mask */ + +#define GPIO_DBEN_DBEN3_Pos (3) /*!< GPIO_T::DBEN: DBEN3 Position */ +#define GPIO_DBEN_DBEN3_Msk (0x1ul << GPIO_DBEN_DBEN3_Pos) /*!< GPIO_T::DBEN: DBEN3 Mask */ + +#define GPIO_DBEN_DBEN4_Pos (4) /*!< GPIO_T::DBEN: DBEN4 Position */ +#define GPIO_DBEN_DBEN4_Msk (0x1ul << GPIO_DBEN_DBEN4_Pos) /*!< GPIO_T::DBEN: DBEN4 Mask */ + +#define GPIO_DBEN_DBEN5_Pos (5) /*!< GPIO_T::DBEN: DBEN5 Position */ +#define GPIO_DBEN_DBEN5_Msk (0x1ul << GPIO_DBEN_DBEN5_Pos) /*!< GPIO_T::DBEN: DBEN5 Mask */ + +#define GPIO_DBEN_DBEN6_Pos (6) /*!< GPIO_T::DBEN: DBEN6 Position */ +#define GPIO_DBEN_DBEN6_Msk (0x1ul << GPIO_DBEN_DBEN6_Pos) /*!< GPIO_T::DBEN: DBEN6 Mask */ + +#define GPIO_DBEN_DBEN7_Pos (7) /*!< GPIO_T::DBEN: DBEN7 Position */ +#define GPIO_DBEN_DBEN7_Msk (0x1ul << GPIO_DBEN_DBEN7_Pos) /*!< GPIO_T::DBEN: DBEN7 Mask */ + +#define GPIO_DBEN_DBEN8_Pos (8) /*!< GPIO_T::DBEN: DBEN8 Position */ +#define GPIO_DBEN_DBEN8_Msk (0x1ul << GPIO_DBEN_DBEN8_Pos) /*!< GPIO_T::DBEN: DBEN8 Mask */ + +#define GPIO_DBEN_DBEN9_Pos (9) /*!< GPIO_T::DBEN: DBEN9 Position */ +#define GPIO_DBEN_DBEN9_Msk (0x1ul << GPIO_DBEN_DBEN9_Pos) /*!< GPIO_T::DBEN: DBEN9 Mask */ + +#define GPIO_DBEN_DBEN10_Pos (10) /*!< GPIO_T::DBEN: DBEN10 Position */ +#define GPIO_DBEN_DBEN10_Msk (0x1ul << GPIO_DBEN_DBEN10_Pos) /*!< GPIO_T::DBEN: DBEN10 Mask */ + +#define GPIO_DBEN_DBEN11_Pos (11) /*!< GPIO_T::DBEN: DBEN11 Position */ +#define GPIO_DBEN_DBEN11_Msk (0x1ul << GPIO_DBEN_DBEN11_Pos) /*!< GPIO_T::DBEN: DBEN11 Mask */ + +#define GPIO_DBEN_DBEN12_Pos (12) /*!< GPIO_T::DBEN: DBEN12 Position */ +#define GPIO_DBEN_DBEN12_Msk (0x1ul << GPIO_DBEN_DBEN12_Pos) /*!< GPIO_T::DBEN: DBEN12 Mask */ + +#define GPIO_DBEN_DBEN13_Pos (13) /*!< GPIO_T::DBEN: DBEN13 Position */ +#define GPIO_DBEN_DBEN13_Msk (0x1ul << GPIO_DBEN_DBEN13_Pos) /*!< GPIO_T::DBEN: DBEN13 Mask */ + +#define GPIO_DBEN_DBEN14_Pos (14) /*!< GPIO_T::DBEN: DBEN14 Position */ +#define GPIO_DBEN_DBEN14_Msk (0x1ul << GPIO_DBEN_DBEN14_Pos) /*!< GPIO_T::DBEN: DBEN14 Mask */ + +#define GPIO_DBEN_DBEN15_Pos (15) /*!< GPIO_T::DBEN: DBEN15 Position */ +#define GPIO_DBEN_DBEN15_Msk (0x1ul << GPIO_DBEN_DBEN15_Pos) /*!< GPIO_T::DBEN: DBEN15 Mask */ + +#define GPIO_INTTYPE_TYPE0_Pos (0) /*!< GPIO_T::INTTYPE: TYPE0 Position */ +#define GPIO_INTTYPE_TYPE0_Msk (0x1ul << GPIO_INTTYPE_TYPE0_Pos) /*!< GPIO_T::INTTYPE: TYPE0 Mask */ + +#define GPIO_INTTYPE_TYPE1_Pos (1) /*!< GPIO_T::INTTYPE: TYPE1 Position */ +#define GPIO_INTTYPE_TYPE1_Msk (0x1ul << GPIO_INTTYPE_TYPE1_Pos) /*!< GPIO_T::INTTYPE: TYPE1 Mask */ + +#define GPIO_INTTYPE_TYPE2_Pos (2) /*!< GPIO_T::INTTYPE: TYPE2 Position */ +#define GPIO_INTTYPE_TYPE2_Msk (0x1ul << GPIO_INTTYPE_TYPE2_Pos) /*!< GPIO_T::INTTYPE: TYPE2 Mask */ + +#define GPIO_INTTYPE_TYPE3_Pos (3) /*!< GPIO_T::INTTYPE: TYPE3 Position */ +#define GPIO_INTTYPE_TYPE3_Msk (0x1ul << GPIO_INTTYPE_TYPE3_Pos) /*!< GPIO_T::INTTYPE: TYPE3 Mask */ + +#define GPIO_INTTYPE_TYPE4_Pos (4) /*!< GPIO_T::INTTYPE: TYPE4 Position */ +#define GPIO_INTTYPE_TYPE4_Msk (0x1ul << GPIO_INTTYPE_TYPE4_Pos) /*!< GPIO_T::INTTYPE: TYPE4 Mask */ + +#define GPIO_INTTYPE_TYPE5_Pos (5) /*!< GPIO_T::INTTYPE: TYPE5 Position */ +#define GPIO_INTTYPE_TYPE5_Msk (0x1ul << GPIO_INTTYPE_TYPE5_Pos) /*!< GPIO_T::INTTYPE: TYPE5 Mask */ + +#define GPIO_INTTYPE_TYPE6_Pos (6) /*!< GPIO_T::INTTYPE: TYPE6 Position */ +#define GPIO_INTTYPE_TYPE6_Msk (0x1ul << GPIO_INTTYPE_TYPE6_Pos) /*!< GPIO_T::INTTYPE: TYPE6 Mask */ + +#define GPIO_INTTYPE_TYPE7_Pos (7) /*!< GPIO_T::INTTYPE: TYPE7 Position */ +#define GPIO_INTTYPE_TYPE7_Msk (0x1ul << GPIO_INTTYPE_TYPE7_Pos) /*!< GPIO_T::INTTYPE: TYPE7 Mask */ + +#define GPIO_INTTYPE_TYPE8_Pos (8) /*!< GPIO_T::INTTYPE: TYPE8 Position */ +#define GPIO_INTTYPE_TYPE8_Msk (0x1ul << GPIO_INTTYPE_TYPE8_Pos) /*!< GPIO_T::INTTYPE: TYPE8 Mask */ + +#define GPIO_INTTYPE_TYPE9_Pos (9) /*!< GPIO_T::INTTYPE: TYPE9 Position */ +#define GPIO_INTTYPE_TYPE9_Msk (0x1ul << GPIO_INTTYPE_TYPE9_Pos) /*!< GPIO_T::INTTYPE: TYPE9 Mask */ + +#define GPIO_INTTYPE_TYPE10_Pos (10) /*!< GPIO_T::INTTYPE: TYPE10 Position */ +#define GPIO_INTTYPE_TYPE10_Msk (0x1ul << GPIO_INTTYPE_TYPE10_Pos) /*!< GPIO_T::INTTYPE: TYPE10 Mask */ + +#define GPIO_INTTYPE_TYPE11_Pos (11) /*!< GPIO_T::INTTYPE: TYPE11 Position */ +#define GPIO_INTTYPE_TYPE11_Msk (0x1ul << GPIO_INTTYPE_TYPE11_Pos) /*!< GPIO_T::INTTYPE: TYPE11 Mask */ + +#define GPIO_INTTYPE_TYPE12_Pos (12) /*!< GPIO_T::INTTYPE: TYPE12 Position */ +#define GPIO_INTTYPE_TYPE12_Msk (0x1ul << GPIO_INTTYPE_TYPE12_Pos) /*!< GPIO_T::INTTYPE: TYPE12 Mask */ + +#define GPIO_INTTYPE_TYPE13_Pos (13) /*!< GPIO_T::INTTYPE: TYPE13 Position */ +#define GPIO_INTTYPE_TYPE13_Msk (0x1ul << GPIO_INTTYPE_TYPE13_Pos) /*!< GPIO_T::INTTYPE: TYPE13 Mask */ + +#define GPIO_INTTYPE_TYPE14_Pos (14) /*!< GPIO_T::INTTYPE: TYPE14 Position */ +#define GPIO_INTTYPE_TYPE14_Msk (0x1ul << GPIO_INTTYPE_TYPE14_Pos) /*!< GPIO_T::INTTYPE: TYPE14 Mask */ + +#define GPIO_INTTYPE_TYPE15_Pos (15) /*!< GPIO_T::INTTYPE: TYPE15 Position */ +#define GPIO_INTTYPE_TYPE15_Msk (0x1ul << GPIO_INTTYPE_TYPE15_Pos) /*!< GPIO_T::INTTYPE: TYPE15 Mask */ + +#define GPIO_INTEN_FLIEN0_Pos (0) /*!< GPIO_T::INTEN: FLIEN0 Position */ +#define GPIO_INTEN_FLIEN0_Msk (0x1ul << GPIO_INTEN_FLIEN0_Pos) /*!< GPIO_T::INTEN: FLIEN0 Mask */ + +#define GPIO_INTEN_FLIEN1_Pos (1) /*!< GPIO_T::INTEN: FLIEN1 Position */ +#define GPIO_INTEN_FLIEN1_Msk (0x1ul << GPIO_INTEN_FLIEN1_Pos) /*!< GPIO_T::INTEN: FLIEN1 Mask */ + +#define GPIO_INTEN_FLIEN2_Pos (2) /*!< GPIO_T::INTEN: FLIEN2 Position */ +#define GPIO_INTEN_FLIEN2_Msk (0x1ul << GPIO_INTEN_FLIEN2_Pos) /*!< GPIO_T::INTEN: FLIEN2 Mask */ + +#define GPIO_INTEN_FLIEN3_Pos (3) /*!< GPIO_T::INTEN: FLIEN3 Position */ +#define GPIO_INTEN_FLIEN3_Msk (0x1ul << GPIO_INTEN_FLIEN3_Pos) /*!< GPIO_T::INTEN: FLIEN3 Mask */ + +#define GPIO_INTEN_FLIEN4_Pos (4) /*!< GPIO_T::INTEN: FLIEN4 Position */ +#define GPIO_INTEN_FLIEN4_Msk (0x1ul << GPIO_INTEN_FLIEN4_Pos) /*!< GPIO_T::INTEN: FLIEN4 Mask */ + +#define GPIO_INTEN_FLIEN5_Pos (5) /*!< GPIO_T::INTEN: FLIEN5 Position */ +#define GPIO_INTEN_FLIEN5_Msk (0x1ul << GPIO_INTEN_FLIEN5_Pos) /*!< GPIO_T::INTEN: FLIEN5 Mask */ + +#define GPIO_INTEN_FLIEN6_Pos (6) /*!< GPIO_T::INTEN: FLIEN6 Position */ +#define GPIO_INTEN_FLIEN6_Msk (0x1ul << GPIO_INTEN_FLIEN6_Pos) /*!< GPIO_T::INTEN: FLIEN6 Mask */ + +#define GPIO_INTEN_FLIEN7_Pos (7) /*!< GPIO_T::INTEN: FLIEN7 Position */ +#define GPIO_INTEN_FLIEN7_Msk (0x1ul << GPIO_INTEN_FLIEN7_Pos) /*!< GPIO_T::INTEN: FLIEN7 Mask */ + +#define GPIO_INTEN_FLIEN8_Pos (8) /*!< GPIO_T::INTEN: FLIEN8 Position */ +#define GPIO_INTEN_FLIEN8_Msk (0x1ul << GPIO_INTEN_FLIEN8_Pos) /*!< GPIO_T::INTEN: FLIEN8 Mask */ + +#define GPIO_INTEN_FLIEN9_Pos (9) /*!< GPIO_T::INTEN: FLIEN9 Position */ +#define GPIO_INTEN_FLIEN9_Msk (0x1ul << GPIO_INTEN_FLIEN9_Pos) /*!< GPIO_T::INTEN: FLIEN9 Mask */ + +#define GPIO_INTEN_FLIEN10_Pos (10) /*!< GPIO_T::INTEN: FLIEN10 Position */ +#define GPIO_INTEN_FLIEN10_Msk (0x1ul << GPIO_INTEN_FLIEN10_Pos) /*!< GPIO_T::INTEN: FLIEN10 Mask */ + +#define GPIO_INTEN_FLIEN11_Pos (11) /*!< GPIO_T::INTEN: FLIEN11 Position */ +#define GPIO_INTEN_FLIEN11_Msk (0x1ul << GPIO_INTEN_FLIEN11_Pos) /*!< GPIO_T::INTEN: FLIEN11 Mask */ + +#define GPIO_INTEN_FLIEN12_Pos (12) /*!< GPIO_T::INTEN: FLIEN12 Position */ +#define GPIO_INTEN_FLIEN12_Msk (0x1ul << GPIO_INTEN_FLIEN12_Pos) /*!< GPIO_T::INTEN: FLIEN12 Mask */ + +#define GPIO_INTEN_FLIEN13_Pos (13) /*!< GPIO_T::INTEN: FLIEN13 Position */ +#define GPIO_INTEN_FLIEN13_Msk (0x1ul << GPIO_INTEN_FLIEN13_Pos) /*!< GPIO_T::INTEN: FLIEN13 Mask */ + +#define GPIO_INTEN_FLIEN14_Pos (14) /*!< GPIO_T::INTEN: FLIEN14 Position */ +#define GPIO_INTEN_FLIEN14_Msk (0x1ul << GPIO_INTEN_FLIEN14_Pos) /*!< GPIO_T::INTEN: FLIEN14 Mask */ + +#define GPIO_INTEN_FLIEN15_Pos (15) /*!< GPIO_T::INTEN: FLIEN15 Position */ +#define GPIO_INTEN_FLIEN15_Msk (0x1ul << GPIO_INTEN_FLIEN15_Pos) /*!< GPIO_T::INTEN: FLIEN15 Mask */ + +#define GPIO_INTEN_RHIEN0_Pos (16) /*!< GPIO_T::INTEN: RHIEN0 Position */ +#define GPIO_INTEN_RHIEN0_Msk (0x1ul << GPIO_INTEN_RHIEN0_Pos) /*!< GPIO_T::INTEN: RHIEN0 Mask */ + +#define GPIO_INTEN_RHIEN1_Pos (17) /*!< GPIO_T::INTEN: RHIEN1 Position */ +#define GPIO_INTEN_RHIEN1_Msk (0x1ul << GPIO_INTEN_RHIEN1_Pos) /*!< GPIO_T::INTEN: RHIEN1 Mask */ + +#define GPIO_INTEN_RHIEN2_Pos (18) /*!< GPIO_T::INTEN: RHIEN2 Position */ +#define GPIO_INTEN_RHIEN2_Msk (0x1ul << GPIO_INTEN_RHIEN2_Pos) /*!< GPIO_T::INTEN: RHIEN2 Mask */ + +#define GPIO_INTEN_RHIEN3_Pos (19) /*!< GPIO_T::INTEN: RHIEN3 Position */ +#define GPIO_INTEN_RHIEN3_Msk (0x1ul << GPIO_INTEN_RHIEN3_Pos) /*!< GPIO_T::INTEN: RHIEN3 Mask */ + +#define GPIO_INTEN_RHIEN4_Pos (20) /*!< GPIO_T::INTEN: RHIEN4 Position */ +#define GPIO_INTEN_RHIEN4_Msk (0x1ul << GPIO_INTEN_RHIEN4_Pos) /*!< GPIO_T::INTEN: RHIEN4 Mask */ + +#define GPIO_INTEN_RHIEN5_Pos (21) /*!< GPIO_T::INTEN: RHIEN5 Position */ +#define GPIO_INTEN_RHIEN5_Msk (0x1ul << GPIO_INTEN_RHIEN5_Pos) /*!< GPIO_T::INTEN: RHIEN5 Mask */ + +#define GPIO_INTEN_RHIEN6_Pos (22) /*!< GPIO_T::INTEN: RHIEN6 Position */ +#define GPIO_INTEN_RHIEN6_Msk (0x1ul << GPIO_INTEN_RHIEN6_Pos) /*!< GPIO_T::INTEN: RHIEN6 Mask */ + +#define GPIO_INTEN_RHIEN7_Pos (23) /*!< GPIO_T::INTEN: RHIEN7 Position */ +#define GPIO_INTEN_RHIEN7_Msk (0x1ul << GPIO_INTEN_RHIEN7_Pos) /*!< GPIO_T::INTEN: RHIEN7 Mask */ + +#define GPIO_INTEN_RHIEN8_Pos (24) /*!< GPIO_T::INTEN: RHIEN8 Position */ +#define GPIO_INTEN_RHIEN8_Msk (0x1ul << GPIO_INTEN_RHIEN8_Pos) /*!< GPIO_T::INTEN: RHIEN8 Mask */ + +#define GPIO_INTEN_RHIEN9_Pos (25) /*!< GPIO_T::INTEN: RHIEN9 Position */ +#define GPIO_INTEN_RHIEN9_Msk (0x1ul << GPIO_INTEN_RHIEN9_Pos) /*!< GPIO_T::INTEN: RHIEN9 Mask */ + +#define GPIO_INTEN_RHIEN10_Pos (26) /*!< GPIO_T::INTEN: RHIEN10 Position */ +#define GPIO_INTEN_RHIEN10_Msk (0x1ul << GPIO_INTEN_RHIEN10_Pos) /*!< GPIO_T::INTEN: RHIEN10 Mask */ + +#define GPIO_INTEN_RHIEN11_Pos (27) /*!< GPIO_T::INTEN: RHIEN11 Position */ +#define GPIO_INTEN_RHIEN11_Msk (0x1ul << GPIO_INTEN_RHIEN11_Pos) /*!< GPIO_T::INTEN: RHIEN11 Mask */ + +#define GPIO_INTEN_RHIEN12_Pos (28) /*!< GPIO_T::INTEN: RHIEN12 Position */ +#define GPIO_INTEN_RHIEN12_Msk (0x1ul << GPIO_INTEN_RHIEN12_Pos) /*!< GPIO_T::INTEN: RHIEN12 Mask */ + +#define GPIO_INTEN_RHIEN13_Pos (29) /*!< GPIO_T::INTEN: RHIEN13 Position */ +#define GPIO_INTEN_RHIEN13_Msk (0x1ul << GPIO_INTEN_RHIEN13_Pos) /*!< GPIO_T::INTEN: RHIEN13 Mask */ + +#define GPIO_INTEN_RHIEN14_Pos (30) /*!< GPIO_T::INTEN: RHIEN14 Position */ +#define GPIO_INTEN_RHIEN14_Msk (0x1ul << GPIO_INTEN_RHIEN14_Pos) /*!< GPIO_T::INTEN: RHIEN14 Mask */ + +#define GPIO_INTEN_RHIEN15_Pos (31) /*!< GPIO_T::INTEN: RHIEN15 Position */ +#define GPIO_INTEN_RHIEN15_Msk (0x1ul << GPIO_INTEN_RHIEN15_Pos) /*!< GPIO_T::INTEN: RHIEN15 Mask */ + +#define GPIO_INTSRC_INTSRC0_Pos (0) /*!< GPIO_T::INTSRC: INTSRC0 Position */ +#define GPIO_INTSRC_INTSRC0_Msk (0x1ul << GPIO_INTSRC_INTSRC0_Pos) /*!< GPIO_T::INTSRC: INTSRC0 Mask */ + +#define GPIO_INTSRC_INTSRC1_Pos (1) /*!< GPIO_T::INTSRC: INTSRC1 Position */ +#define GPIO_INTSRC_INTSRC1_Msk (0x1ul << GPIO_INTSRC_INTSRC1_Pos) /*!< GPIO_T::INTSRC: INTSRC1 Mask */ + +#define GPIO_INTSRC_INTSRC2_Pos (2) /*!< GPIO_T::INTSRC: INTSRC2 Position */ +#define GPIO_INTSRC_INTSRC2_Msk (0x1ul << GPIO_INTSRC_INTSRC2_Pos) /*!< GPIO_T::INTSRC: INTSRC2 Mask */ + +#define GPIO_INTSRC_INTSRC3_Pos (3) /*!< GPIO_T::INTSRC: INTSRC3 Position */ +#define GPIO_INTSRC_INTSRC3_Msk (0x1ul << GPIO_INTSRC_INTSRC3_Pos) /*!< GPIO_T::INTSRC: INTSRC3 Mask */ + +#define GPIO_INTSRC_INTSRC4_Pos (4) /*!< GPIO_T::INTSRC: INTSRC4 Position */ +#define GPIO_INTSRC_INTSRC4_Msk (0x1ul << GPIO_INTSRC_INTSRC4_Pos) /*!< GPIO_T::INTSRC: INTSRC4 Mask */ + +#define GPIO_INTSRC_INTSRC5_Pos (5) /*!< GPIO_T::INTSRC: INTSRC5 Position */ +#define GPIO_INTSRC_INTSRC5_Msk (0x1ul << GPIO_INTSRC_INTSRC5_Pos) /*!< GPIO_T::INTSRC: INTSRC5 Mask */ + +#define GPIO_INTSRC_INTSRC6_Pos (6) /*!< GPIO_T::INTSRC: INTSRC6 Position */ +#define GPIO_INTSRC_INTSRC6_Msk (0x1ul << GPIO_INTSRC_INTSRC6_Pos) /*!< GPIO_T::INTSRC: INTSRC6 Mask */ + +#define GPIO_INTSRC_INTSRC7_Pos (7) /*!< GPIO_T::INTSRC: INTSRC7 Position */ +#define GPIO_INTSRC_INTSRC7_Msk (0x1ul << GPIO_INTSRC_INTSRC7_Pos) /*!< GPIO_T::INTSRC: INTSRC7 Mask */ + +#define GPIO_INTSRC_INTSRC8_Pos (8) /*!< GPIO_T::INTSRC: INTSRC8 Position */ +#define GPIO_INTSRC_INTSRC8_Msk (0x1ul << GPIO_INTSRC_INTSRC8_Pos) /*!< GPIO_T::INTSRC: INTSRC8 Mask */ + +#define GPIO_INTSRC_INTSRC9_Pos (9) /*!< GPIO_T::INTSRC: INTSRC9 Position */ +#define GPIO_INTSRC_INTSRC9_Msk (0x1ul << GPIO_INTSRC_INTSRC9_Pos) /*!< GPIO_T::INTSRC: INTSRC9 Mask */ + +#define GPIO_INTSRC_INTSRC10_Pos (10) /*!< GPIO_T::INTSRC: INTSRC10 Position */ +#define GPIO_INTSRC_INTSRC10_Msk (0x1ul << GPIO_INTSRC_INTSRC10_Pos) /*!< GPIO_T::INTSRC: INTSRC10 Mask */ + +#define GPIO_INTSRC_INTSRC11_Pos (11) /*!< GPIO_T::INTSRC: INTSRC11 Position */ +#define GPIO_INTSRC_INTSRC11_Msk (0x1ul << GPIO_INTSRC_INTSRC11_Pos) /*!< GPIO_T::INTSRC: INTSRC11 Mask */ + +#define GPIO_INTSRC_INTSRC12_Pos (12) /*!< GPIO_T::INTSRC: INTSRC12 Position */ +#define GPIO_INTSRC_INTSRC12_Msk (0x1ul << GPIO_INTSRC_INTSRC12_Pos) /*!< GPIO_T::INTSRC: INTSRC12 Mask */ + +#define GPIO_INTSRC_INTSRC13_Pos (13) /*!< GPIO_T::INTSRC: INTSRC13 Position */ +#define GPIO_INTSRC_INTSRC13_Msk (0x1ul << GPIO_INTSRC_INTSRC13_Pos) /*!< GPIO_T::INTSRC: INTSRC13 Mask */ + +#define GPIO_INTSRC_INTSRC14_Pos (14) /*!< GPIO_T::INTSRC: INTSRC14 Position */ +#define GPIO_INTSRC_INTSRC14_Msk (0x1ul << GPIO_INTSRC_INTSRC14_Pos) /*!< GPIO_T::INTSRC: INTSRC14 Mask */ + +#define GPIO_INTSRC_INTSRC15_Pos (15) /*!< GPIO_T::INTSRC: INTSRC15 Position */ +#define GPIO_INTSRC_INTSRC15_Msk (0x1ul << GPIO_INTSRC_INTSRC15_Pos) /*!< GPIO_T::INTSRC: INTSRC15 Mask */ + +#define GPIO_DBCTL_DBCLKSEL_Pos (0) /*!< GPIO_DBCTL_T::DBCTL: DBCLKSEL Position */ +#define GPIO_DBCTL_DBCLKSEL_Msk (0xful << GPIO_DBCTL_DBCLKSEL_Pos) /*!< GPIO_DBCTL_T::DBCTL: DBCLKSEL Mask */ + +#define GPIO_DBCTL_DBCLKSRC_Pos (4) /*!< GPIO_DBCTL_T::DBCTL: DBCLKSRC Position */ +#define GPIO_DBCTL_DBCLKSRC_Msk (0x1ul << GPIO_DBCTL_DBCLKSRC_Pos) /*!< GPIO_DBCTL_T::DBCTL: DBCLKSRC Mask */ + +#define GPIO_DBCTL_ICLKON_Pos (5) /*!< GPIO_DBCTL_T::DBCTL: ICLKON Position */ +#define GPIO_DBCTL_ICLKON_Msk (0x1ul << GPIO_DBCTL_ICLKON_Pos) /*!< GPIO_DBCTL_T::DBCTL: ICLKON Mask */ + +#define GPIO_PDIO_PDIO_Pos (0) /*!< PDIO Position */ +#define GPIO_PDIO_PDIO_Msk (0x1ul << GPIO_PDIO_PDIO_Pos) /*!< PDIO Mask */ + +/**@}*/ /* GPIO_CONST */ +/**@}*/ /* end of GPIO register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __GPIO_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/hdiv_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/hdiv_reg.h new file mode 100644 index 0000000000..4cb467cbf7 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/hdiv_reg.h @@ -0,0 +1,130 @@ +/**************************************************************************//** + * @file hdiv_reg.h + * @version V1.00 + * @brief HDIV register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __HDIV_REG_H__ +#define __HDIV_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup HDIV Hardware Divider (HDIV) + Memory Mapped Structure for HDIV Controller +@{ */ + +typedef struct +{ + + + /** + * DIVIDEND + * =================================================================================================== + * Offset: 0x00 Dividend Source Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |DIVIDEND |Dividend Source + * | | |This register is given the dividend of divider before calculation starting. + */ + __IO uint32_t DIVIDEND; + + /** + * DIVISOR + * =================================================================================================== + * Offset: 0x04 Divisor Source Resister + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |DIVISOR |Divisor Source + * | | |This register is given the divisor of divider before calculation starts. + * | | |Note: When this register is written, hardware divider will start calculate. + */ + __IO uint32_t DIVISOR; + + /** + * QUOTIENT + * =================================================================================================== + * Offset: 0x08 Quotient Result Resister + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |QUOTIENT |Quotient Result + * | | |This register holds the quotient result of divider after calculation complete. + */ + __IO uint32_t QUOTIENT; + + /** + * REM + * =================================================================================================== + * Offset: 0x0C Remainder Result Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |REM |Remainder Result + * | | |The remainder of hardware divider is 16-bit sign integer (REM[15:0]) with sign extension + * | | |(REM[31:16]) to 32-bit integer. + */ + __IO uint32_t REM; + + /** + * STATUS + * =================================================================================================== + * Offset: 0x10 Divider Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |DIVBYZERO |Divisor Zero Warning + * | | |0 = The divisor is not 0. + * | | |1 = The divisor is 0. + * | | |Note: The DIVBYZERO flag is used to indicate divide-by-zero situation and updated whenever + * | | |HDIV_DIVISOR is written. + * | | |This register is read only. + */ + __I uint32_t STATUS; + +} HDIV_T; + +/** + @addtogroup HDIV_CONST HDIV Bit Field Definition + Constant Definitions for HDIV Controller +@{ */ + +#define HDIV_DIVIDEND_DIVIDEND_Pos (0) /*!< HDIV_T::DIVIDEND: DIVIDEND Position */ +#define HDIV_DIVIDEND_DIVIDEND_Msk (0xfffffffful << HDIV_DIVIDEND_DIVIDEND_Pos) /*!< HDIV_T::DIVIDEND: DIVIDEND Mask */ + +#define HDIV_DIVISOR_DIVISOR_Pos (0) /*!< HDIV_T::DIVISOR: DIVISOR Position */ +#define HDIV_DIVISOR_DIVISOR_Msk (0xfffful << HDIV_DIVISOR_DIVISOR_Pos) /*!< HDIV_T::DIVISOR: DIVISOR Mask */ + +#define HDIV_QUOTIENT_QUOTIENT_Pos (0) /*!< HDIV_T::QUOTIENT: QUOTIENT Position */ +#define HDIV_QUOTIENT_QUOTIENT_Msk (0xfffffffful << HDIV_QUOTIENT_QUOTIENT_Pos) /*!< HDIV_T::QUOTIENT: QUOTIENT Mask */ + +#define HDIV_REM_REM_Pos (0) /*!< HDIV_T::REM: REM Position */ +#define HDIV_REM_REM_Msk (0xfffffffful << HDIV_REM_REM_Pos) /*!< HDIV_T::REM: REM Mask */ + +#define HDIV_STATUS_DIVBYZERO_Pos (1) /*!< HDIV_T::STATUS: DIVBYZERO Position */ +#define HDIV_STATUS_DIVBYZERO_Msk (0x1ul << HDIV_STATUS_DIVBYZERO_Pos) /*!< HDIV_T::STATUS: DIVBYZERO Mask */ + +/**@}*/ /* HDIV_CONST */ +/**@}*/ /* end of HDIV register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __HDIV_REG_H__ */ + + +/**@}*/ /* HDIV_CONST */ +/**@}*/ /* end of HDIV register group */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/i2c_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/i2c_reg.h new file mode 100644 index 0000000000..8e7f9da7fd --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/i2c_reg.h @@ -0,0 +1,750 @@ +/**************************************************************************//** + * @file i2c_reg.h + * @version V1.00 + * @brief I2C register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __I2C_REG_H__ +#define __I2C_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup I2C Inter-IC Bus Controller (I2C) + Memory Mapped Structure for I2C Controller +@{ */ + +typedef struct +{ + + + /** + * @var I2C_T::CTL0 + * Offset: 0x00 I2C Control Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2] |AA |Assert Acknowledge Control + * | | |When AA =1 prior to address or data is received, an acknowledged (low level to SDA) will be returned during the acknowledge clock pulse on the SCL line when 1.) A slave is acknowledging the address sent from master, 2.) The receiver devices are acknowledging the data sent by transmitter. + * | | |When AA=0 prior to address or data received, a Not acknowledged (high level to SDA) will be returned during the acknowledge clock pulse on the SCL line. + * |[3] |SI |I2C Interrupt Flag + * | | |When a new I2C state is present in the I2C_STATUS0 register, the SI flag is set by hardware. + * | | |If bit INTEN (I2C_CTL0 [7]) is set, the I2C interrupt is requested. + * | | |SI must be cleared by software. + * | | |Clear SI by writing 1 to this bit. + * |[4] |STO |I2C STOP Control + * | | |In Master mode, setting STO to transmit a STOP condition to bus then I2C controller will check the bus condition if a STOP condition is detected. + * | | |This bit will be cleared by hardware automatically. + * |[5] |STA |I2C START Control + * | | |Setting STA to logic 1 to enter Master mode, the I2C hardware sends a START or repeat START condition to bus when the bus is free. + * |[6] |I2CEN |I2C Controller Enable Bit + * | | |Set to enable I2C serial function controller. + * | | |When I2CEN=1 the I2C serial function enable. + * | | |The multi-function pin function must set to SDA, and SCL of I2C function first. + * | | |0 = I2C controller Disabled. + * | | |1 = I2C controller Enabled. + * |[7] |INTEN |Enable Interrupt + * | | |0 = I2C interrupt Disabled. + * | | |1 = I2C interrupt Enabled. + * @var I2C_T::ADDR0 + * Offset: 0x04 I2C Slave Address Register0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |GC |General Call Function + * | | |0 = General Call Function Disabled. + * | | |1 = General Call Function Enabled. + * |[7:1] |ADDR |I2C Address + * | | |The content of this register is irrelevant when I2C is in Master mode. + * | | |In the slave mode, the seven most significant bits must be loaded with the chip's own address. + * | | |The I2C hardware will react if either of the address is matched. + * | | |Note: When software set 7'h00, the address can not be used. + * @var I2C_T::DAT + * Offset: 0x08 I2C Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |DAT |I2C Data + * | | |Bit [7:0] is located with the 8-bit transferred/received data of I2C serial port. + * @var I2C_T::STATUS0 + * Offset: 0x0C I2C Status Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |STATUS |I2C Status + * | | |The three least significant bits are always 0. + * | | |The five most significant bits contain the status code. + * | | |There are 28 possible status codes. + * | | |When the content of I2C_STATUS0 is F8H, no serial interrupt is requested. + * | | |Others I2C_STATUS0 values correspond to defined I2C states. + * | | |When each of these states is entered, a status interrupt is requested (SI = 1). + * | | |A valid status code is present in I2C_STATUS0 one cycle after SI is set by hardware and is still present one cycle after SI has been reset by software. + * | | |In addition, states 00H stands for a Bus Error. + * | | |A Bus Error occurs when a START or STOP condition is present at an illegal position in the formation frame. + * | | |Example of illegal position are during the serial transfer of an address byte, a data byte or an acknowledge bit. + * @var I2C_T::CLKDIV + * Offset: 0x10 I2C Clock Divided Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[9:0] |DIVIDER |I2C Clock Divided + * | | |Indicates the I2C clock rate: Data Baud Rate of I2C = (system clock) / (4x (I2C_CLKDIV+1)). + * | | |Note: The minimum value of I2C_CLKDIV is 4. + * @var I2C_T::TOCTL + * Offset: 0x14 I2C Time-out Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |TOIF |Time-out Flag + * | | |This bit is set by hardware when I2C time-out happened and it can interrupt CPU if I2C interrupt enable bit (INTEN) is set to 1. + * | | |Note: Software can write 1 to clear this bit. + * |[1] |TOCDIV4 |Time-out Counter Input Clock Divided by 4 + * | | |When enabled, the time-out period is extended 4 times. + * | | |0 = Time-out period is extend 4 times Disabled. + * | | |1 = Time-out period is extend 4 times Enabled. + * |[2] |TOCEN |Time-out Counter Enable Bit + * | | |When enabled, the 14-bit time-out counter will start counting when SI is cleared. + * | | |Setting flag SI to '1' will reset counter and re-start up counting after SI is cleared. + * | | |0 = Time-out counter Disabled. + * | | |1 = Time-out counter Enabled. + * @var I2C_T::ADDR1 + * Offset: 0x18 I2C Slave Address Register1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |GC |General Call Function + * | | |0 = General Call Function Disabled. + * | | |1 = General Call Function Enabled. + * |[7:1] |ADDR |I2C Address + * | | |The content of this register is irrelevant when I2C is in Master mode. + * | | |In the slave mode, the seven most significant bits must be loaded with the chip's own address. + * | | |The I2C hardware will react if either of the address is matched. + * | | |Note: When software set 7'h00, the address can not be used. + * @var I2C_T::ADDR2 + * Offset: 0x1C I2C Slave Address Register2 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |GC |General Call Function + * | | |0 = General Call Function Disabled. + * | | |1 = General Call Function Enabled. + * |[7:1] |ADDR |I2C Address + * | | |The content of this register is irrelevant when I2C is in Master mode. + * | | |In the slave mode, the seven most significant bits must be loaded with the chip's own address. + * | | |The I2C hardware will react if either of the address is matched. + * | | |Note: When software set 7'h00, the address can not be used. + * @var I2C_T::ADDR3 + * Offset: 0x20 I2C Slave Address Register3 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |GC |General Call Function + * | | |0 = General Call Function Disabled. + * | | |1 = General Call Function Enabled. + * |[7:1] |ADDR |I2C Address + * | | |The content of this register is irrelevant when I2C is in Master mode. + * | | |In the slave mode, the seven most significant bits must be loaded with the chip's own address. + * | | |The I2C hardware will react if either of the address is matched. + * | | |Note: When software set 7'h00, the address can not be used. + * @var I2C_T::ADDRMSK0 + * Offset: 0x24 I2C Slave Address Mask Register0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:1] |ADDRMSK |I2C Address Mask + * | | |0 = Mask Disabled (the received corresponding register bit should be exact the same as address register). + * | | |1 = Mask Enabled (the received corresponding address bit is don't care). + * | | |I2C bus controllers support multiple address recognition with four address mask register. + * | | |When the bit in the address mask register is set to one, it means the received corresponding address bit is don't-care. + * | | |If the bit is set to zero, that means the received corresponding register bit should be exact the same as address register. + * | | |Note: The wake-up function can not use address mask. + * @var I2C_T::ADDRMSK1 + * Offset: 0x28 I2C Slave Address Mask Register1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:1] |ADDRMSK |I2C Address Mask + * | | |0 = Mask Disabled (the received corresponding register bit should be exact the same as address register). + * | | |1 = Mask Enabled (the received corresponding address bit is don't care). + * | | |I2C bus controllers support multiple address recognition with four address mask register. + * | | |When the bit in the address mask register is set to one, it means the received corresponding address bit is don't-care. + * | | |If the bit is set to zero, that means the received corresponding register bit should be exact the same as address register. + * | | |Note: The wake-up function can not use address mask. + * @var I2C_T::ADDRMSK2 + * Offset: 0x2C I2C Slave Address Mask Register2 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:1] |ADDRMSK |I2C Address Mask + * | | |0 = Mask Disabled (the received corresponding register bit should be exact the same as address register). + * | | |1 = Mask Enabled (the received corresponding address bit is don't care). + * | | |I2C bus controllers support multiple address recognition with four address mask register. + * | | |When the bit in the address mask register is set to one, it means the received corresponding address bit is don't-care. + * | | |If the bit is set to zero, that means the received corresponding register bit should be exact the same as address register. + * | | |Note: The wake-up function can not use address mask. + * @var I2C_T::ADDRMSK3 + * Offset: 0x30 I2C Slave Address Mask Register3 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:1] |ADDRMSK |I2C Address Mask + * | | |0 = Mask Disabled (the received corresponding register bit should be exact the same as address register). + * | | |1 = Mask Enabled (the received corresponding address bit is don't care). + * | | |I2C bus controllers support multiple address recognition with four address mask register. + * | | |When the bit in the address mask register is set to one, it means the received corresponding address bit is don't-care. + * | | |If the bit is set to zero, that means the received corresponding register bit should be exact the same as address register. + * | | |Note: The wake-up function can not use address mask. + * @var I2C_T::WKCTL + * Offset: 0x3C I2C Wake-up Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WKEN |I2C Wake-up Enable Bit + * | | |0 = I2C wake-up function Disabled. + * | | |1= I2C wake-up function Enabled. + * |[7] |NHDBUSEN |I2C No Hold BUS Enable Bit + * | | |0 = I2C hold bus after wake-up. + * | | |1= I2C don't hold bus after wake-up. + * | | |Note: The I2C controller could respond when WKIF event is not clear, it may cause error data transmitted or received. + * | | |If data transmitted or received when WKIF event is not clear, user must reset I2C controller and execute the original operation again. + * @var I2C_T::WKSTS + * Offset: 0x40 I2C Wake-up Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WKIF |I2C Wake-up Flag + * | | |When chip is woken up from Power-down mode by I2C, this bit is set to 1. + * | | |Software can write 1 to clear this bit. + * |[1] |WKAKDONE |Wakeup Address Frame Acknowledge Bit Done + * | | |0 = The ACK bit cycle of address match frame isn't done. + * | | |1 = The ACK bit cycle of address match frame is done in power-down. + * | | |Note: This bit can't release WKIF. Software can write 1 to clear this bit. + * |[2] |WRSTSWK |Read/Write Status Bit in Address Wakeup Frame (Read Only) + * | | |0 = Write command be record on the address match wakeup frame. + * | | |1 = Read command be record on the address match wakeup frame. + * | | |Note: This bit will be cleared when software can write 1 to WKAKDONE (I2C_WKSTS[1]) bit. + * @var I2C_T::CTL1 + * Offset: 0x44 I2C Control Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |TXPDMAEN |PDMA Transmit Channel Available + * | | |0 = Transmit PDMA function Disabled. + * | | |1 = Transmit PDMA function Enabled. + * |[1] |RXPDMAEN |PDMA Receive Channel Available + * | | |0 = Receive PDMA function Disabled. + * | | |1 = Receive PDMA function Enabled. + * |[2] |PDMARST |PDMA Reset + * | | |0 = No effect. + * | | |1 = Reset the I2C request to PDMA. + * |[3] |OVRIEN |I2C over Run Interrupt Control Bit + * | | |Setting OVRIEN to logic 1 will send a interrupt to system when the TWOFF bit is enabled and there is over run event in received buffer. + * |[4] |UDRIEN |I2C Under Run Interrupt Control Bit + * | | |Setting UDRIEN to logic 1 will send a interrupt to system when the TWOFF bit is enabled and there is under run event happened in transmitted buffer. + * |[5] |TWOBUFEN |Two-level BUFFER Enable Bit + * | | |0 = Two-level buffer Disabled. + * | | |1 = Two-level buffer Enabled. + * | | |Set to enable the two-level buffer for I2C transmitted or received buffer. + * | | |It is used to improve the performance of the I2C bus. + * | | |If this bit is set = 1, the control bit of STA for repeat start or STO bit should be set after the current SI is cleared. + * | | |For example: if there are 4 data shall be transmitted and then stop it. + * | | |The STO bit shall be set after the 3rd data's SI event being clear. + * | | |In this time, the 4th data can be transmitted and the I2C stop after the 4th data transmission done. + * |[6] |BUFRST |Two-level BUFFER Reset + * | | |0 = No effect. + * | | |1 = Reset the related counters, two-level buffer state machine, and the content of data buffer. + * |[7] |NSTRETCH |No Stretch on the I2C Bus + * | | |0 = The I2C SCL bus is stretched by hardware if the SI is not cleared in master mode. + * | | |1 = The I2C SCL bus is not stretched by hardware if the SI is not cleared in master mode. + * |[8] |PDMASTR |PDMA Stretch Bit + * | | |0 = I2C send STOP automatically after PDMA transfer done. (only master TX) + * | | |1 = I2C SCL bus is stretched by hardware after PDMA transfer done if the SI is not cleared. + * | | |(only master TX) + * @var I2C_T::STATUS1 + * Offset: 0x48 I2C Status Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[4] |FULL |TWO-lEVEL BUFFER FULL + * | | |This bit indicates two-level buffer TX or RX full or not when the TWOBUFEN = 1. + * | | |This bit is set when POINTER is equal to 2. + * | | |Note:This bit is read only. + * |[5] |EMPTY |TWO-lEVEL BUFFER EMPTY + * | | |This bit indicates two-level buffer TX or RX empty or not when the TWOBUFEN = 1. + * | | |This bit is set when POINTER is equal to 0. + * | | |Note:This bit is read only. + * |[6] |OVR |I2C over Run Status Bit + * | | |This bit indicates the received two-level buffer TX or RX is over run when the TWOBUFEN = 1. + * | | |Note:This bit is read only. + * |[7] |UDR |I2C Under Run Status Bit + * | | |This bit indicates the transmitted two-level buffer TX or RX is under run when the TWOBUFEN = 1. + * | | |Note:This bit is read only. + * |[8] |ONBUSY |On Bus Busy (Read Only) + * | | |Indicates that a communication is in progress on the bus. + * | | |It is set by hardware when a START condition is detected. + * | | |It is cleared by hardware when a STOP condition is detected. + * | | |0 = The bus is IDLE (both SCLK and SDA High). + * | | |1 = The bus is busy. + * @var I2C_T::TMCTL + * Offset: 0x4C I2C Timing Configure Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |STCTL |Setup Time Configure Control + * | | |This field is used to generate a delay timing between SDA falling edge and SCL rising edge in transmission mode. + * | | |The delay setup time is numbers of peripheral clock = STCTL x PCLK. + * | | |Note: Setup time setting should not make SCL output less than three PCLKs. + * |[24:16] |HTCTL |Hold Time Configure Control + * | | |This field is used to generate the delay timing between SCL falling edge and SDA rising edge in transmission mode. + * | | |The delay hold time is numbers of peripheral clock = HTCTL x PCLK. + * @var I2C_T::BUSCTL + * Offset: 0x50 I2C Bus Management Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ACKMEN |Acknowledge Control by Manual + * | | |In order to allow ACK control in slave reception including the command and data, slave byte control mode must be enabled by setting the ACKMEN bit. + * | | |0 = Slave byte control Disabled. + * | | |1 = Slave byte control Enabled. + * | | |The 9th bit can response the ACK or NACK according the received data by user. + * | | |When the byte is received, stretching the SCLK signal low between the 8th and 9th SCLK pulse. + * | | |Note: If the BMDEN =1 and this bit is enabled, the information of I2C_STATUS0 will be fixed as 0xF0 in slave receive condition. + * |[1] |PECEN |Packet Error Checking Calculation Enable Bit + * | | |0 = Packet Error Checking Calculation Disabled. + * | | |1 = Packet Error Checking Calculation Enabled. + * | | |Note: When I2C enter powerdown mode, the bit should be enabled after wake-up if needed PEC calculation. + * |[2] |BMDEN |Bus Management Device Default Address Enable Bit + * | | |0 = Device default address Disable. + * | | |When the address 0'b1100001x coming and the both of BMDEN and ACKMEN are enabled, the device responses NACKed + * | | |1 = Device default address Enabled. + * | | |When the address 0'b1100001x coming and the both of BMDEN and ACKMEN are enabled, the device responses ACKed. + * |[3] |BMHEN |Bus Management Host Enable Bit + * | | |0 = Host function Disabled. + * | | |1 = Host function Enabled. + * |[4] |ALERTEN |Bus Management Alert Enable Bit + * | | |Device Mode (BMHEN =0). + * | | |0 = Release the BM_ALERT pin high and Alert Response Header disabled: 0001100x followed by NACK if both of BMDEN and ACKMEN are enabled. + * | | |1 = Drive BM_ALERT pin low and Alert Response Address Header enables: 0001100x followed by ACK if both of BMDEN and ACKMEN are enabled. + * | | |Host Mode (BMHEN =1). + * | | |0 = BM_ALERT pin not supported. + * | | |1 = BM_ALERT pin supported. + * |[5] |SCTLOSTS |Suspend/Control Data Output Status + * | | |0 = The output of SUSCON pin is low. + * | | |1 = The output of SUSCON pin is high. + * |[6] |SCTLOEN |Suspend or Control Pin Output Enable Bit + * | | |0 = The SUSCON pin in input. + * | | |1 = The output enable is active on the SUSCON pin. + * |[7] |BUSEN |BUS Enable Bit + * | | |0 = The system management function Disabled. + * | | |1 = The system management function Enabled. + * | | |Note: When the bit is enabled, the internal 14-bit counter is used to calculate the time out event of clock low condition. + * |[8] |PECTXEN |Packet Error Checking Byte Transmission/Reception + * | | |0 = No PEC transfer. + * | | |1 = PEC transmission is requested. + * | | |Note: 1.This bit has no effect in slave mode when ACKMEN =0. + * |[9] |TIDLE |Timer Check in Idle State + * | | |The BUSTOUT is used to calculate the time-out of clock low in bus active and the idle period in bus Idle. + * | | |This bit is used to define which condition is enabled. + * | | |0 = BUSTOUT is used to calculate the clock low period in bus active. + * | | |1 = BUSTOUT is used to calculate the IDLE period in bus Idle. + * | | |Note: The BUSY (I2C_BUSSTS[0]) indicate the current bus state. + * |[10] |PECCLR |PEC Clear at Repeat Start + * | | |The calculation of PEC starts when PECEN is set to 1 and it is cleared when the STA or STO bit is detected. + * | | |This PECCLR bit is used to enable the condition of REPEAT START can clear the PEC calculation. + * | | |0 = PEC calculation is cleared by "Repeat Start" function Disabled. + * | | |1 = PEC calculation is cleared by "Repeat Start" function Enabled. + * |[11] |ACKM9SI |Acknowledge Manual Enable Extra SI Interrupt + * | | |0 = There is no SI interrupt in the 9th clock cycle when the BUSEN =1 and ACKMEN =1. + * | | |1 = There is SI interrupt in the 9th clock cycle when the BUSEN =1 and ACKMEN =1. + * |[12] |BCDIEN |Packet Error Checking Byte Count Done Interrupt Enable Bit + * | | |0 = Byte count done interrupt Disabled. + * | | |1 = Byte count done interrupt Enabled. + * | | |Note: This bit is used in PECEN =1. + * |[13] |PECDIEN |Packet Error Checking Byte Transfer Done Interrupt Enable Bit + * | | |0 = PEC transfer done interrupt Disabled. + * | | |1 = PEC transfer done interrupt Enabled. + * | | |Note: This bit is used in PECEN =1. + * @var I2C_T::BUSTCTL + * Offset: 0x54 I2C Bus Management Timer Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BUSTOEN |Bus Time Out Enable Bit + * | | |0 = Bus clock low time-out detection Disabled. + * | | |1 = Bus clock low time-out detection Enabled (bus clock is low for more than TTime-out (in BIDLE=0) or high more than TTime-out(in BIDLE =1) + * |[1] |CLKTOEN |Cumulative Clock Low Time Out Enable Bit + * | | |0 = Cumulative clock low time-out detection Disabled. + * | | |1 = Cumulative clock low time-out detection Enabled. + * | | |For Master, it calculates the period from START to ACK + * | | |For Slave, it calculates the period from START to STOP + * |[2] |BUSTOIEN |Time-out Interrupt Enable Bit + * | | |BUSY =1. + * | | |0 = SCLK low time-out interrupt Disabled. + * | | |1 = SCLK low time-out interrupt Enabled. + * | | |BUSY =0. + * | | |0 = Bus IDLE time-out interrupt Disabled. + * | | |1 = Bus IDLE time-out interrupt Enabled. + * |[3] |CLKTOIEN |Extended Clock Time Out Interrupt Enable Bit + * | | |0 = Clock time out interrupt Disabled. + * | | |1 = Clock time out interrupt Enabled. + * |[4] |TORSTEN |Time Out Reset Enable Bit + * | | |0 = I2C state machine reset Disabled. + * | | |1 = I2C state machine reset Enabled. (The clock and data bus will be released to high) + * @var I2C_T::BUSSTS + * Offset: 0x58 I2C Bus Management Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BUSY |Bus Busy (Read Only) + * | | |Indicates that a communication is in progress on the bus. + * | | |It is set by hardware when a START condition is detected. + * | | |It is cleared by hardware when a STOP condition is detected. + * | | |0 = Bus is IDLE (both SCLK and SDA High). + * | | |1 = Bus is busy. + * |[1] |BCDONE |Byte Count Transmission/Receive Done + * | | |0 = Byte count transmission/ receive is not finished when the PECEN is set. + * | | |1 = Byte count transmission/ receive is finished when the PECEN is set. + * | | |Note: Software can write 1 to clear this bit. + * |[2] |PECERR |PEC Error in Reception + * | | |0 = PEC value equal the received PEC data packet. + * | | |1 = PEC value doesn't match the receive PEC data packet. + * | | |Note: Software can write 1 to clear this bit. + * |[3] |ALERT |SMBus Alert Status + * | | |Device Mode (BMHEN =0). + * | | |0 = SMBALERT pin state is low. + * | | |1 = SMBALERT pin state is high. + * | | |Host Mode (BMHEN =1). + * | | |0 = No SMBALERT event. + * | | |1 = There is SMBALERT event (falling edge) is detected in SMALERT pin when the BMHEN = 1 (SMBus host configuration) and the ALERTEN = 1. + * | | |Note: + * | | |1. The SMBALERT pin is an open-drain pin, the pull-high resistor is must in the system + * | | |2. Software can write 1 to clear this bit. + * |[4] |SCTLDIN |Bus Suspend or Control Signal Input Status (Read Only) + * | | |0 = The input status of SUSCON pin is 0. + * | | |1 = The input status of SUSCON pin is 1. + * |[5] |BUSTO |Bus Time-out Status + * | | |0 = There is no any time-out or external clock time-out. + * | | |1 = A time-out or external clock time-out occurred. + * | | |In bus busy, the bit indicates the total clock low time-out event occurred; otherwise, it indicates the bus idle time-out event occurred. + * | | |Note: Software can write 1 to clear this bit. + * |[6] |CLKTO |Clock Low Cumulate Time-out Status + * | | |0 = Cumulative clock low is no any time-out. + * | | |1 = Cumulative clock low time-out occurred. + * | | |Note: Software can write 1 to clear this bit. + * |[7] |PECDONE |PEC Byte Transmission/Receive Done + * | | |0 = PEC transmission/ receive is not finished when the PECEN is set. + * | | |1 = PEC transmission/ receive is finished when the PECEN is set. + * | | |Note: Software can write 1 to clear this bit. + * @var I2C_T::PKTSIZE + * Offset: 0x5C I2C Packet Error Checking Byte Number Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |PLDSIZE |Transfer Byte Number + * | | |The transmission or receive byte number in one transaction when the PECEN is set. + * | | |The maximum transaction or receive byte is 256 Bytes. + * | | |Note: The byte number counting includes address, command code, and data frame. + * @var I2C_T::PKTCRC + * Offset: 0x60 I2C Packet Error Checking Byte Value Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |PECCRC |Packet Error Checking Byte Value + * | | |This byte indicates the packet error checking content after transmission or receive byte count by using the C(x) = X8 + X2 + X + 1. + * | | |It is read only. + * @var I2C_T::BUSTOUT + * Offset: 0x64 I2C Bus Management Timer Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |BUSTO |Bus Management Time-out Value + * | | |Indicates the bus time-out value in bus is IDLE or SCLK low. + * | | |Note: If the user wants to revise the value of BUSTOUT, the TORSTEN (I2C_BUSTCTL[4]) bit shall be set to 1 and clear to 0 first in the BUSEN(I2C_BUSCTL[7]) is set. + * @var I2C_T::CLKTOUT + * Offset: 0x68 I2C Bus Management Clock Low Timer Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |CLKTO |Bus Clock Low Timer + * | | |The field is used to configure the cumulative clock extension time-out. + * | | |Note: If the user wants to revise the value of CLKLTOUT, the TORSTEN bit shall be set to 1 and clear to 0 first in the BUSEN is set. + */ + __IO uint32_t CTL0; /*!< [0x0000] I2C Control Register 0 */ + __IO uint32_t ADDR0; /*!< [0x0004] I2C Slave Address Register0 */ + __IO uint32_t DAT; /*!< [0x0008] I2C Data Register */ + __I uint32_t STATUS0; /*!< [0x000c] I2C Status Register 0 */ + __IO uint32_t CLKDIV; /*!< [0x0010] I2C Clock Divided Register */ + __IO uint32_t TOCTL; /*!< [0x0014] I2C Time-out Control Register */ + __IO uint32_t ADDR1; /*!< [0x0018] I2C Slave Address Register1 */ + __IO uint32_t ADDR2; /*!< [0x001c] I2C Slave Address Register2 */ + __IO uint32_t ADDR3; /*!< [0x0020] I2C Slave Address Register3 */ + __IO uint32_t ADDRMSK0; /*!< [0x0024] I2C Slave Address Mask Register0 */ + __IO uint32_t ADDRMSK1; /*!< [0x0028] I2C Slave Address Mask Register1 */ + __IO uint32_t ADDRMSK2; /*!< [0x002c] I2C Slave Address Mask Register2 */ + __IO uint32_t ADDRMSK3; /*!< [0x0030] I2C Slave Address Mask Register3 */ + __I uint32_t RESERVE0[2]; + __IO uint32_t WKCTL; /*!< [0x003c] I2C Wake-up Control Register */ + __IO uint32_t WKSTS; /*!< [0x0040] I2C Wake-up Status Register */ + __IO uint32_t CTL1; /*!< [0x0044] I2C Control Register 1 */ + __IO uint32_t STATUS1; /*!< [0x0048] I2C Status Register 1 */ + __IO uint32_t TMCTL; /*!< [0x004c] I2C Timing Configure Control Register */ + __IO uint32_t BUSCTL; /*!< [0x0050] I2C Bus Management Control Register */ + __IO uint32_t BUSTCTL; /*!< [0x0054] I2C Bus Management Timer Control Register */ + __IO uint32_t BUSSTS; /*!< [0x0058] I2C Bus Management Status Register */ + __IO uint32_t PKTSIZE; /*!< [0x005c] I2C Packet Error Checking Byte Number Register */ + __I uint32_t PKTCRC; /*!< [0x0060] I2C Packet Error Checking Byte Value Register */ + __IO uint32_t BUSTOUT; /*!< [0x0064] I2C Bus Management Timer Register */ + __IO uint32_t CLKTOUT; /*!< [0x0068] I2C Bus Management Clock Low Timer Register */ +} I2C_T; + +/** + @addtogroup I2C_CONST I2C Bit Field Definition + Constant Definitions for I2C Controller +@{ */ + +#define I2C_CTL0_AA_Pos (2) /*!< I2C_T::CTL0: AA Position */ +#define I2C_CTL0_AA_Msk (0x1ul << I2C_CTL0_AA_Pos) /*!< I2C_T::CTL0: AA Mask */ + +#define I2C_CTL0_SI_Pos (3) /*!< I2C_T::CTL0: SI Position */ +#define I2C_CTL0_SI_Msk (0x1ul << I2C_CTL0_SI_Pos) /*!< I2C_T::CTL0: SI Mask */ + +#define I2C_CTL0_STO_Pos (4) /*!< I2C_T::CTL0: STO Position */ +#define I2C_CTL0_STO_Msk (0x1ul << I2C_CTL0_STO_Pos) /*!< I2C_T::CTL0: STO Mask */ + +#define I2C_CTL0_STA_Pos (5) /*!< I2C_T::CTL0: STA Position */ +#define I2C_CTL0_STA_Msk (0x1ul << I2C_CTL0_STA_Pos) /*!< I2C_T::CTL0: STA Mask */ + +#define I2C_CTL0_I2CEN_Pos (6) /*!< I2C_T::CTL0: I2CEN Position */ +#define I2C_CTL0_I2CEN_Msk (0x1ul << I2C_CTL0_I2CEN_Pos) /*!< I2C_T::CTL0: I2CEN Mask */ + +#define I2C_CTL0_INTEN_Pos (7) /*!< I2C_T::CTL0: INTEN Position */ +#define I2C_CTL0_INTEN_Msk (0x1ul << I2C_CTL0_INTEN_Pos) /*!< I2C_T::CTL0: INTEN Mask */ + +#define I2C_ADDR0_GC_Pos (0) /*!< I2C_T::ADDR0: GC Position */ +#define I2C_ADDR0_GC_Msk (0x1ul << I2C_ADDR0_GC_Pos) /*!< I2C_T::ADDR0: GC Mask */ + +#define I2C_ADDR0_ADDR_Pos (1) /*!< I2C_T::ADDR0: ADDR Position */ +#define I2C_ADDR0_ADDR_Msk (0x7ful << I2C_ADDR0_ADDR_Pos) /*!< I2C_T::ADDR0: ADDR Mask */ + +#define I2C_DAT_DAT_Pos (0) /*!< I2C_T::DAT: DAT Position */ +#define I2C_DAT_DAT_Msk (0xfful << I2C_DAT_DAT_Pos) /*!< I2C_T::DAT: DAT Mask */ + +#define I2C_STATUS0_STATUS_Pos (0) /*!< I2C_T::STATUS0: STATUS Position */ +#define I2C_STATUS0_STATUS_Msk (0xfful << I2C_STATUS0_STATUS_Pos) /*!< I2C_T::STATUS0: STATUS Mask */ + +#define I2C_CLKDIV_DIVIDER_Pos (0) /*!< I2C_T::CLKDIV: DIVIDER Position */ +#define I2C_CLKDIV_DIVIDER_Msk (0x3fful << I2C_CLKDIV_DIVIDER_Pos) /*!< I2C_T::CLKDIV: DIVIDER Mask */ + +#define I2C_TOCTL_TOIF_Pos (0) /*!< I2C_T::TOCTL: TOIF Position */ +#define I2C_TOCTL_TOIF_Msk (0x1ul << I2C_TOCTL_TOIF_Pos) /*!< I2C_T::TOCTL: TOIF Mask */ + +#define I2C_TOCTL_TOCDIV4_Pos (1) /*!< I2C_T::TOCTL: TOCDIV4 Position */ +#define I2C_TOCTL_TOCDIV4_Msk (0x1ul << I2C_TOCTL_TOCDIV4_Pos) /*!< I2C_T::TOCTL: TOCDIV4 Mask */ + +#define I2C_TOCTL_TOCEN_Pos (2) /*!< I2C_T::TOCTL: TOCEN Position */ +#define I2C_TOCTL_TOCEN_Msk (0x1ul << I2C_TOCTL_TOCEN_Pos) /*!< I2C_T::TOCTL: TOCEN Mask */ + +#define I2C_ADDR1_GC_Pos (0) /*!< I2C_T::ADDR1: GC Position */ +#define I2C_ADDR1_GC_Msk (0x1ul << I2C_ADDR1_GC_Pos) /*!< I2C_T::ADDR1: GC Mask */ + +#define I2C_ADDR1_ADDR_Pos (1) /*!< I2C_T::ADDR1: ADDR Position */ +#define I2C_ADDR1_ADDR_Msk (0x7ful << I2C_ADDR1_ADDR_Pos) /*!< I2C_T::ADDR1: ADDR Mask */ + +#define I2C_ADDR2_GC_Pos (0) /*!< I2C_T::ADDR2: GC Position */ +#define I2C_ADDR2_GC_Msk (0x1ul << I2C_ADDR2_GC_Pos) /*!< I2C_T::ADDR2: GC Mask */ + +#define I2C_ADDR2_ADDR_Pos (1) /*!< I2C_T::ADDR2: ADDR Position */ +#define I2C_ADDR2_ADDR_Msk (0x7ful << I2C_ADDR2_ADDR_Pos) /*!< I2C_T::ADDR2: ADDR Mask */ + +#define I2C_ADDR3_GC_Pos (0) /*!< I2C_T::ADDR3: GC Position */ +#define I2C_ADDR3_GC_Msk (0x1ul << I2C_ADDR3_GC_Pos) /*!< I2C_T::ADDR3: GC Mask */ + +#define I2C_ADDR3_ADDR_Pos (1) /*!< I2C_T::ADDR3: ADDR Position */ +#define I2C_ADDR3_ADDR_Msk (0x7ful << I2C_ADDR3_ADDR_Pos) /*!< I2C_T::ADDR3: ADDR Mask */ + +#define I2C_ADDRMSK0_ADDRMSK_Pos (1) /*!< I2C_T::ADDRMSK0: ADDRMSK Position */ +#define I2C_ADDRMSK0_ADDRMSK_Msk (0x7ful << I2C_ADDRMSK0_ADDRMSK_Pos) /*!< I2C_T::ADDRMSK0: ADDRMSK Mask */ + +#define I2C_ADDRMSK1_ADDRMSK_Pos (1) /*!< I2C_T::ADDRMSK1: ADDRMSK Position */ +#define I2C_ADDRMSK1_ADDRMSK_Msk (0x7ful << I2C_ADDRMSK1_ADDRMSK_Pos) /*!< I2C_T::ADDRMSK1: ADDRMSK Mask */ + +#define I2C_ADDRMSK2_ADDRMSK_Pos (1) /*!< I2C_T::ADDRMSK2: ADDRMSK Position */ +#define I2C_ADDRMSK2_ADDRMSK_Msk (0x7ful << I2C_ADDRMSK2_ADDRMSK_Pos) /*!< I2C_T::ADDRMSK2: ADDRMSK Mask */ + +#define I2C_ADDRMSK3_ADDRMSK_Pos (1) /*!< I2C_T::ADDRMSK3: ADDRMSK Position */ +#define I2C_ADDRMSK3_ADDRMSK_Msk (0x7ful << I2C_ADDRMSK3_ADDRMSK_Pos) /*!< I2C_T::ADDRMSK3: ADDRMSK Mask */ + +#define I2C_WKCTL_WKEN_Pos (0) /*!< I2C_T::WKCTL: WKEN Position */ +#define I2C_WKCTL_WKEN_Msk (0x1ul << I2C_WKCTL_WKEN_Pos) /*!< I2C_T::WKCTL: WKEN Mask */ + +#define I2C_WKCTL_NHDBUSEN_Pos (7) /*!< I2C_T::WKCTL: NHDBUSEN Position */ +#define I2C_WKCTL_NHDBUSEN_Msk (0x1ul << I2C_WKCTL_NHDBUSEN_Pos) /*!< I2C_T::WKCTL: NHDBUSEN Mask */ + +#define I2C_WKSTS_WKIF_Pos (0) /*!< I2C_T::WKSTS: WKIF Position */ +#define I2C_WKSTS_WKIF_Msk (0x1ul << I2C_WKSTS_WKIF_Pos) /*!< I2C_T::WKSTS: WKIF Mask */ + +#define I2C_WKSTS_WKAKDONE_Pos (1) /*!< I2C_T::WKSTS: WKAKDONE Position */ +#define I2C_WKSTS_WKAKDONE_Msk (0x1ul << I2C_WKSTS_WKAKDONE_Pos) /*!< I2C_T::WKSTS: WKAKDONE Mask */ + +#define I2C_WKSTS_WRSTSWK_Pos (2) /*!< I2C_T::WKSTS: WRSTSWK Position */ +#define I2C_WKSTS_WRSTSWK_Msk (0x1ul << I2C_WKSTS_WRSTSWK_Pos) /*!< I2C_T::WKSTS: WRSTSWK Mask */ + +#define I2C_CTL1_TXPDMAEN_Pos (0) /*!< I2C_T::CTL1: TXPDMAEN Position */ +#define I2C_CTL1_TXPDMAEN_Msk (0x1ul << I2C_CTL1_TXPDMAEN_Pos) /*!< I2C_T::CTL1: TXPDMAEN Mask */ + +#define I2C_CTL1_RXPDMAEN_Pos (1) /*!< I2C_T::CTL1: RXPDMAEN Position */ +#define I2C_CTL1_RXPDMAEN_Msk (0x1ul << I2C_CTL1_RXPDMAEN_Pos) /*!< I2C_T::CTL1: RXPDMAEN Mask */ + +#define I2C_CTL1_PDMARST_Pos (2) /*!< I2C_T::CTL1: PDMARST Position */ +#define I2C_CTL1_PDMARST_Msk (0x1ul << I2C_CTL1_PDMARST_Pos) /*!< I2C_T::CTL1: PDMARST Mask */ + +#define I2C_CTL1_OVRIEN_Pos (3) /*!< I2C_T::CTL1: OVRIEN Position */ +#define I2C_CTL1_OVRIEN_Msk (0x1ul << I2C_CTL1_OVRIEN_Pos) /*!< I2C_T::CTL1: OVRIEN Mask */ + +#define I2C_CTL1_UDRIEN_Pos (4) /*!< I2C_T::CTL1: UDRIEN Position */ +#define I2C_CTL1_UDRIEN_Msk (0x1ul << I2C_CTL1_UDRIEN_Pos) /*!< I2C_T::CTL1: UDRIEN Mask */ + +#define I2C_CTL1_TWOBUFEN_Pos (5) /*!< I2C_T::CTL1: TWOBUFEN Position */ +#define I2C_CTL1_TWOBUFEN_Msk (0x1ul << I2C_CTL1_TWOBUFEN_Pos) /*!< I2C_T::CTL1: TWOBUFEN Mask */ + +#define I2C_CTL1_BUFRST_Pos (6) /*!< I2C_T::CTL1: BUFRST Position */ +#define I2C_CTL1_BUFRST_Msk (0x1ul << I2C_CTL1_BUFRST_Pos) /*!< I2C_T::CTL1: BUFRST Mask */ + +#define I2C_CTL1_NSTRETCH_Pos (7) /*!< I2C_T::CTL1: NSTRETCH Position */ +#define I2C_CTL1_NSTRETCH_Msk (0x1ul << I2C_CTL1_NSTRETCH_Pos) /*!< I2C_T::CTL1: NSTRETCH Mask */ + +#define I2C_CTL1_PDMASTR_Pos (8) /*!< I2C_T::CTL1: PDMASTR Position */ +#define I2C_CTL1_PDMASTR_Msk (0x1ul << I2C_CTL1_PDMASTR_Pos) /*!< I2C_T::CTL1: PDMASTR Mask */ + +#define I2C_STATUS1_FULL_Pos (4) /*!< I2C_T::STATUS1: FULL Position */ +#define I2C_STATUS1_FULL_Msk (0x1ul << I2C_STATUS1_FULL_Pos) /*!< I2C_T::STATUS1: FULL Mask */ + +#define I2C_STATUS1_EMPTY_Pos (5) /*!< I2C_T::STATUS1: EMPTY Position */ +#define I2C_STATUS1_EMPTY_Msk (0x1ul << I2C_STATUS1_EMPTY_Pos) /*!< I2C_T::STATUS1: EMPTY Mask */ + +#define I2C_STATUS1_OVR_Pos (6) /*!< I2C_T::STATUS1: OVR Position */ +#define I2C_STATUS1_OVR_Msk (0x1ul << I2C_STATUS1_OVR_Pos) /*!< I2C_T::STATUS1: OVR Mask */ + +#define I2C_STATUS1_UDR_Pos (7) /*!< I2C_T::STATUS1: UDR Position */ +#define I2C_STATUS1_UDR_Msk (0x1ul << I2C_STATUS1_UDR_Pos) /*!< I2C_T::STATUS1: UDR Mask */ + +#define I2C_STATUS1_ONBUSY_Pos (8) /*!< I2C_T::STATUS1: ONBUSY Position */ +#define I2C_STATUS1_ONBUSY_Msk (0x1ul << I2C_STATUS1_ONBUSY_Pos) /*!< I2C_T::STATUS1: ONBUSY Mask */ + +#define I2C_TMCTL_STCTL_Pos (0) /*!< I2C_T::TMCTL: STCTL Position */ +#define I2C_TMCTL_STCTL_Msk (0x1fful << I2C_TMCTL_STCTL_Pos) /*!< I2C_T::TMCTL: STCTL Mask */ + +#define I2C_TMCTL_HTCTL_Pos (16) /*!< I2C_T::TMCTL: HTCTL Position */ +#define I2C_TMCTL_HTCTL_Msk (0x1fful << I2C_TMCTL_HTCTL_Pos) /*!< I2C_T::TMCTL: HTCTL Mask */ + +#define I2C_BUSCTL_ACKMEN_Pos (0) /*!< I2C_T::BUSCTL: ACKMEN Position */ +#define I2C_BUSCTL_ACKMEN_Msk (0x1ul << I2C_BUSCTL_ACKMEN_Pos) /*!< I2C_T::BUSCTL: ACKMEN Mask */ + +#define I2C_BUSCTL_PECEN_Pos (1) /*!< I2C_T::BUSCTL: PECEN Position */ +#define I2C_BUSCTL_PECEN_Msk (0x1ul << I2C_BUSCTL_PECEN_Pos) /*!< I2C_T::BUSCTL: PECEN Mask */ + +#define I2C_BUSCTL_BMDEN_Pos (2) /*!< I2C_T::BUSCTL: BMDEN Position */ +#define I2C_BUSCTL_BMDEN_Msk (0x1ul << I2C_BUSCTL_BMDEN_Pos) /*!< I2C_T::BUSCTL: BMDEN Mask */ + +#define I2C_BUSCTL_BMHEN_Pos (3) /*!< I2C_T::BUSCTL: BMHEN Position */ +#define I2C_BUSCTL_BMHEN_Msk (0x1ul << I2C_BUSCTL_BMHEN_Pos) /*!< I2C_T::BUSCTL: BMHEN Mask */ + +#define I2C_BUSCTL_ALERTEN_Pos (4) /*!< I2C_T::BUSCTL: ALERTEN Position */ +#define I2C_BUSCTL_ALERTEN_Msk (0x1ul << I2C_BUSCTL_ALERTEN_Pos) /*!< I2C_T::BUSCTL: ALERTEN Mask */ + +#define I2C_BUSCTL_SCTLOSTS_Pos (5) /*!< I2C_T::BUSCTL: SCTLOSTS Position */ +#define I2C_BUSCTL_SCTLOSTS_Msk (0x1ul << I2C_BUSCTL_SCTLOSTS_Pos) /*!< I2C_T::BUSCTL: SCTLOSTS Mask */ + +#define I2C_BUSCTL_SCTLOEN_Pos (6) /*!< I2C_T::BUSCTL: SCTLOEN Position */ +#define I2C_BUSCTL_SCTLOEN_Msk (0x1ul << I2C_BUSCTL_SCTLOEN_Pos) /*!< I2C_T::BUSCTL: SCTLOEN Mask */ + +#define I2C_BUSCTL_BUSEN_Pos (7) /*!< I2C_T::BUSCTL: BUSEN Position */ +#define I2C_BUSCTL_BUSEN_Msk (0x1ul << I2C_BUSCTL_BUSEN_Pos) /*!< I2C_T::BUSCTL: BUSEN Mask */ + +#define I2C_BUSCTL_PECTXEN_Pos (8) /*!< I2C_T::BUSCTL: PECTXEN Position */ +#define I2C_BUSCTL_PECTXEN_Msk (0x1ul << I2C_BUSCTL_PECTXEN_Pos) /*!< I2C_T::BUSCTL: PECTXEN Mask */ + +#define I2C_BUSCTL_TIDLE_Pos (9) /*!< I2C_T::BUSCTL: TIDLE Position */ +#define I2C_BUSCTL_TIDLE_Msk (0x1ul << I2C_BUSCTL_TIDLE_Pos) /*!< I2C_T::BUSCTL: TIDLE Mask */ + +#define I2C_BUSCTL_PECCLR_Pos (10) /*!< I2C_T::BUSCTL: PECCLR Position */ +#define I2C_BUSCTL_PECCLR_Msk (0x1ul << I2C_BUSCTL_PECCLR_Pos) /*!< I2C_T::BUSCTL: PECCLR Mask */ + +#define I2C_BUSCTL_ACKM9SI_Pos (11) /*!< I2C_T::BUSCTL: ACKM9SI Position */ +#define I2C_BUSCTL_ACKM9SI_Msk (0x1ul << I2C_BUSCTL_ACKM9SI_Pos) /*!< I2C_T::BUSCTL: ACKM9SI Mask */ + +#define I2C_BUSCTL_BCDIEN_Pos (12) /*!< I2C_T::BUSCTL: BCDIEN Position */ +#define I2C_BUSCTL_BCDIEN_Msk (0x1ul << I2C_BUSCTL_BCDIEN_Pos) /*!< I2C_T::BUSCTL: BCDIEN Mask */ + +#define I2C_BUSCTL_PECDIEN_Pos (13) /*!< I2C_T::BUSCTL: PECDIEN Position */ +#define I2C_BUSCTL_PECDIEN_Msk (0x1ul << I2C_BUSCTL_PECDIEN_Pos) /*!< I2C_T::BUSCTL: PECDIEN Mask */ + +#define I2C_BUSTCTL_BUSTOEN_Pos (0) /*!< I2C_T::BUSTCTL: BUSTOEN Position */ +#define I2C_BUSTCTL_BUSTOEN_Msk (0x1ul << I2C_BUSTCTL_BUSTOEN_Pos) /*!< I2C_T::BUSTCTL: BUSTOEN Mask */ + +#define I2C_BUSTCTL_CLKTOEN_Pos (1) /*!< I2C_T::BUSTCTL: CLKTOEN Position */ +#define I2C_BUSTCTL_CLKTOEN_Msk (0x1ul << I2C_BUSTCTL_CLKTOEN_Pos) /*!< I2C_T::BUSTCTL: CLKTOEN Mask */ + +#define I2C_BUSTCTL_BUSTOIEN_Pos (2) /*!< I2C_T::BUSTCTL: BUSTOIEN Position */ +#define I2C_BUSTCTL_BUSTOIEN_Msk (0x1ul << I2C_BUSTCTL_BUSTOIEN_Pos) /*!< I2C_T::BUSTCTL: BUSTOIEN Mask */ + +#define I2C_BUSTCTL_CLKTOIEN_Pos (3) /*!< I2C_T::BUSTCTL: CLKTOIEN Position */ +#define I2C_BUSTCTL_CLKTOIEN_Msk (0x1ul << I2C_BUSTCTL_CLKTOIEN_Pos) /*!< I2C_T::BUSTCTL: CLKTOIEN Mask */ + +#define I2C_BUSTCTL_TORSTEN_Pos (4) /*!< I2C_T::BUSTCTL: TORSTEN Position */ +#define I2C_BUSTCTL_TORSTEN_Msk (0x1ul << I2C_BUSTCTL_TORSTEN_Pos) /*!< I2C_T::BUSTCTL: TORSTEN Mask */ + +#define I2C_BUSSTS_BUSY_Pos (0) /*!< I2C_T::BUSSTS: BUSY Position */ +#define I2C_BUSSTS_BUSY_Msk (0x1ul << I2C_BUSSTS_BUSY_Pos) /*!< I2C_T::BUSSTS: BUSY Mask */ + +#define I2C_BUSSTS_BCDONE_Pos (1) /*!< I2C_T::BUSSTS: BCDONE Position */ +#define I2C_BUSSTS_BCDONE_Msk (0x1ul << I2C_BUSSTS_BCDONE_Pos) /*!< I2C_T::BUSSTS: BCDONE Mask */ + +#define I2C_BUSSTS_PECERR_Pos (2) /*!< I2C_T::BUSSTS: PECERR Position */ +#define I2C_BUSSTS_PECERR_Msk (0x1ul << I2C_BUSSTS_PECERR_Pos) /*!< I2C_T::BUSSTS: PECERR Mask */ + +#define I2C_BUSSTS_ALERT_Pos (3) /*!< I2C_T::BUSSTS: ALERT Position */ +#define I2C_BUSSTS_ALERT_Msk (0x1ul << I2C_BUSSTS_ALERT_Pos) /*!< I2C_T::BUSSTS: ALERT Mask */ + +#define I2C_BUSSTS_SCTLDIN_Pos (4) /*!< I2C_T::BUSSTS: SCTLDIN Position */ +#define I2C_BUSSTS_SCTLDIN_Msk (0x1ul << I2C_BUSSTS_SCTLDIN_Pos) /*!< I2C_T::BUSSTS: SCTLDIN Mask */ + +#define I2C_BUSSTS_BUSTO_Pos (5) /*!< I2C_T::BUSSTS: BUSTO Position */ +#define I2C_BUSSTS_BUSTO_Msk (0x1ul << I2C_BUSSTS_BUSTO_Pos) /*!< I2C_T::BUSSTS: BUSTO Mask */ + +#define I2C_BUSSTS_CLKTO_Pos (6) /*!< I2C_T::BUSSTS: CLKTO Position */ +#define I2C_BUSSTS_CLKTO_Msk (0x1ul << I2C_BUSSTS_CLKTO_Pos) /*!< I2C_T::BUSSTS: CLKTO Mask */ + +#define I2C_BUSSTS_PECDONE_Pos (7) /*!< I2C_T::BUSSTS: PECDONE Position */ +#define I2C_BUSSTS_PECDONE_Msk (0x1ul << I2C_BUSSTS_PECDONE_Pos) /*!< I2C_T::BUSSTS: PECDONE Mask */ + +#define I2C_PKTSIZE_PLDSIZE_Pos (0) /*!< I2C_T::PKTSIZE: PLDSIZE Position */ +#define I2C_PKTSIZE_PLDSIZE_Msk (0x1fful << I2C_PKTSIZE_PLDSIZE_Pos) /*!< I2C_T::PKTSIZE: PLDSIZE Mask */ + +#define I2C_PKTCRC_PECCRC_Pos (0) /*!< I2C_T::PKTCRC: PECCRC Position */ +#define I2C_PKTCRC_PECCRC_Msk (0xfful << I2C_PKTCRC_PECCRC_Pos) /*!< I2C_T::PKTCRC: PECCRC Mask */ + +#define I2C_BUSTOUT_BUSTO_Pos (0) /*!< I2C_T::BUSTOUT: BUSTO Position */ +#define I2C_BUSTOUT_BUSTO_Msk (0xfful << I2C_BUSTOUT_BUSTO_Pos) /*!< I2C_T::BUSTOUT: BUSTO Mask */ + +#define I2C_CLKTOUT_CLKTO_Pos (0) /*!< I2C_T::CLKTOUT: CLKTO Position */ +#define I2C_CLKTOUT_CLKTO_Msk (0xfful << I2C_CLKTOUT_CLKTO_Pos) /*!< I2C_T::CLKTOUT: CLKTO Mask */ + +/**@}*/ /* I2C_CONST */ +/**@}*/ /* end of I2C register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __I2C_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/pdma_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/pdma_reg.h new file mode 100644 index 0000000000..3c51b398a4 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/pdma_reg.h @@ -0,0 +1,675 @@ +/**************************************************************************//** + * @file pdma_reg.h + * @version V1.00 + * @brief PDMA register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __PDMA_REG_H__ +#define __PDMA_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup PDMA Peripheral Direct Memory Access Controller (PDMA) + Memory Mapped Structure for PDMA Controller +@{ */ + + +typedef struct +{ + + + /** + * @var DSCT_T::CTL + * Offset: 0x00 Descriptor Table Control Register of PDMA Channel n + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |OPMODE |PDMA Operation Mode Selection + * | | |00 = Idle state: Channel is stopped or this table is complete, when PDMA finish channel table task, OPMODE will be cleared to idle state automatically. + * | | |01 = Basic mode: The descriptor table only has one task. When this task is finished, the PDMA_INTSTS[1] will be asserted. + * | | |10 = Scatter-Gather mode: When operating in this mode, user must give the next descriptor table address in PDMA_DSCT_NEXT register; PDMA controller will ignore this task, then load the next task to execute. + * | | |11 = Reserved. + * | | |Note: Before filling new transfer task in the Descriptor Table, user must check the PDMA_INTSTS[1] to make sure the curren task is complete. + * |[2] |TXTYPE |Transfer Type + * | | |0 = Burst transfer type. + * | | |1 = Single transfer type. + * |[6:4] |BURSIZE |Burst Size + * | | |000 = 128 Transfers. + * | | |001 = 64 Transfers. + * | | |010 = 32 Transfers. + * | | |011 = 16 Transfers. + * | | |100 = 8 Transfers. + * | | |101 = 4 Transfers. + * | | |110 = 2 Transfers. + * | | |111 = 1 Transfers. + * | | |Note: This field is only useful in burst transfer type. + * |[7] |TBINTDIS |Table Interrupt Disable Bit + * | | |This field can be used to decide whether to enable table interrupt or not. + * | | |If the TBINTDIS bit is enabled it will not generates TDIFn(PDMA_TDSTS[8:0]) when PDMA controller finishes transfer task. + * | | |0 = Table interrupt Enabled. + * | | |1 = Table interrupt Disabled. + * | | |Note: This function only for scatter-gather mode. + * |[9:8] |SAINC |Source Address Increment + * | | |This field is used to set the source address increment size. + * | | |11 = No increment (fixed address). + * | | |Others = Increment and size is depended on TXWIDTH selection. + * | | |Note: This function do not support in memory to memory transfer type. + * |[11:10] |DAINC |Destination Address Increment + * | | |This field is used to set the destination address increment size. + * | | |11 = No increment (fixed address). + * | | |Others = Increment and size is depended on TXWIDTH selection. + * | | |Note: This function do not support in memory to memory transfer type. + * |[13:12] |TXWIDTH |Transfer Width Selection + * | | |This field is used for transfer width. + * | | |00 = One byte (8 bit) is transferred for every operation. + * | | |01= One half-word (16 bit) is transferred for every operation. + * | | |10 = One word (32-bit) is transferred for every operation. + * | | |11 = Reserved. + * | | |Note: The PDMA transfer source address (PDMA_DSCT_SA) and PDMA transfer destination address (PDMA_DSCT_DA) should be alignment under the TXWIDTH selection + * |[31:16] |TXCNT |Transfer Count + * | | |The TXCNT represents the required number of PDMA transfer, the real transfer count is (TXCNT + 1); The maximum transfer count is 65536, every transfer may be byte, half-word or word that is dependent on TXWIDTH field. + * | | |Note: When PDMA finish each transfer data, this field will be decrease immediately. + * @var DSCT_T::SA + * Offset: 0x04 Source Address Register of PDMA Channel n + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |SA |PDMA Transfer Source Address + * | | |This field indicates a 32-bit source address of PDMA controller. + * @var DSCT_T::DA + * Offset: 0x08 Destination Address Register of PDMA Channel n + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |DA |PDMA Transfer Destination Address + * | | |This field indicates a 32-bit destination address of PDMA controller. + * @var DSCT_T::NEXT + * Offset: 0x0C Next Scatter-gather Descriptor Table Offset Address of PDMA Channel n + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |NEXT |PDMA Next Descriptor Table Offset + * | | |This field indicates the offset of the next descriptor table address in system memory. + * | | |Write Operation: + * | | |If the system memory based address is 0x2000_0000 (PDMA_SCATBA), and the next descriptor table is start from 0x2000_0100, then this field must fill in 0x0100. + * | | |Read Operation: + * | | |When operating in scatter-gather mode, the last two bits NEXT[1:0] will become reserved, and indicate the first next address of system memory. + * | | |Note1: The descriptor table address must be word boundary. + * | | |Note2: Before filled transfer task in the descriptor table, user must check if the descriptor table is complete. + * |[31:16] |EXENEXT |PDMA Execution Next Descriptor Table Offset + * | | |This field indicates the offset of next descriptor table address of current execution descriptor table in system memory. + * | | |Note: write operation is useless in this field. + */ + __IO uint32_t CTL; /*!< [0x0000] Descriptor Table Control Register of PDMA Channel n. */ + __IO uint32_t SA; /*!< [0x0004] Source Address Register of PDMA Channel n */ + __IO uint32_t DA; /*!< [0x0008] Destination Address Register of PDMA Channel n */ + __IO uint32_t NEXT; /*!< [0x000c] Next Scatter-Gather Descriptor Table Offset Address of PDMA Channel n */ + +} DSCT_T; + + +typedef struct +{ + + + /** + * @var PDMA_T::CURSCAT + * Offset: 0x100 Current Scatter-gather Descriptor Table Address of PDMA Channel n + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |CURADDR |PDMA Current Description Address (Read Only) + * | | |This field indicates a 32-bit current external description address of PDMA controller. + * | | |Note: This field is read only and used for Scatter-Gather mode only to indicate the current external description address. + * @var PDMA_T::CHCTL + * Offset: 0x400 PDMA Channel Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |CHENn |PDMA Channel Enable Bits + * | | |Set this bit to 1 to enable PDMAn operation. Channel cannot be active if it is not set as enabled. + * | | |0 = PDMA channel [n] Disabled. + * | | |1 = PDMA channel [n] Enabled. + * | | |Note: Setting the corresponding bit of PDMA_PAUSE or PDMA_CHRST register will also clear this bit. + * @var PDMA_T::PAUSE + * Offset: 0x404 PDMA Transfer Pause Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |PAUSEn |PDMA Channel N Transfer Pause Control (Write Only) + * | | |User can set PAUSEn bit field to pause the PDMA transfer. + * | | |When user sets PAUSEn bit, the PDMA controller will pause the on-going transfer, then clear the channel enable bit CHEN(PDMA_CHCTL [n], n=0,1..8) and clear request active flag(PDMA_TRGSTS[n:0], n=0,1..8). + * | | |If the paused channel is re-enabled again, the remaining transfers will be processed. + * | | |0 = No effect. + * | | |1 = Pause PDMA channel n transfer. + * @var PDMA_T::SWREQ + * Offset: 0x408 PDMA Software Request Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |SWREQn |PDMA Software Request (Write Only) + * | | |Set this bit to 1 to generate a software request to PDMA [n]. + * | | |0 = No effect. + * | | |1 = Generate a software request. + * | | |Note1: User can read PDMA_TRGSTS register to know which channel is on active. + * | | |Active flag may be triggered by software request or peripheral request. + * | | |Note2: If user does not enable corresponding PDMA channel, the software request will be ignored. + * @var PDMA_T::TRGSTS + * Offset: 0x40C PDMA Channel Request Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |REQSTSn |PDMA Channel Request Status (Read Only) + * | | |This flag indicates whether channel[n] have a request or not, no matter request from software or peripheral. + * | | |When PDMA controller finishes channel transfer, this bit will be cleared automatically. + * | | |0 = PDMA Channel n has no request. + * | | |1 = PDMA Channel n has a request. + * | | |Note: If user pauses or resets each PDMA transfer by setting PDMA_PAUSE or PDMA_CHRST register respectively, this bit will be cleared automatically after finishing the current transfer. + * @var PDMA_T::PRISET + * Offset: 0x410 PDMA Fixed Priority Setting Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |FPRISETn |PDMA Fixed Priority Setting + * | | |Set this bit to 1 to enable fixed priority level. + * | | |Write Operation: + * | | |0 = No effect. + * | | |1 = Set PDMA channel [n] to fixed priority channel. + * | | |Read Operation: + * | | |0 = Corresponding PDMA channel is round-robin priority. + * | | |1 = Corresponding PDMA channel is fixed priority. + * | | |Note: This field only set to fixed priority, clear fixed priority use PDMA_PRICLR register. + * @var PDMA_T::PRICLR + * Offset: 0x414 PDMA Fixed Priority Clear Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |FPRICLRn |PDMA Fixed Priority Clear Bits (Write Only) + * | | |Set this bit to 1 to clear fixed priority level. + * | | |0 = No effect. + * | | |1 = Clear PDMA channel [n] fixed priority setting. + * | | |Note: User can read PDMA_PRISET register to know the channel priority. + * @var PDMA_T::INTEN + * Offset: 0x418 PDMA Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |INTENn |PDMA Interrupt Enable Bits + * | | |This field is used to enable PDMA channel[n] interrupt. + * | | |0 = PDMA channel n interrupt Disabled. + * | | |1 = PDMA channel n interrupt Enabled. + * @var PDMA_T::INTSTS + * Offset: 0x41C PDMA Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ABTIF |PDMA Read/Write Target Abort Interrupt Flag (Read Only) + * | | |This bit indicates that PDMA has target abort error; Software can read PDMA_ABTSTS register to find which channel has target abort error. + * | | |0 = No AHB bus ERROR response received. + * | | |1 = AHB bus ERROR response received. + * |[1] |TDIF |Transfer Done Interrupt Flag (Read Only) + * | | |This bit indicates that PDMA controller has finished transmission; User can read PDMA_TDSTS register to indicate which channel finished transfer. + * | | |0 = Not finished yet. + * | | |1 = PDMA channel has finished transmission. + * |[2] |ALIGNF |Transfer Alignment Interrupt Flag (Read Only) + * | | |0 = PDMA channel source address and destination address both follow transfer width setting. + * | | |1 = PDMA channel source address or destination address is not follow transfer width setting. + * |[8] |REQTOF0 |Request Time-out Flag for Channel 0 + * | | |This flag indicates that PDMA controller has waited peripheral request for a period defined by PDMA_TOC0, user can write 1 to clear these bits. + * | | |0 = No request time-out. + * | | |1 = Peripheral request time-out. + * |[9] |REQTOF1 |Request Time-out Flag for Channel 1 + * | | |This flag indicates that PDMA controller has waited peripheral request for a period defined by PDMA_TOC1, user can write 1 to clear these bits. + * | | |0 = No request time-out. + * | | |1 = Peripheral request time-out. + * @var PDMA_T::ABTSTS + * Offset: 0x420 PDMA Channel Read/Write Target Abort Flag Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |ABTIFn |PDMA Read/Write Target Abort Interrupt Status Flag + * | | |This bit indicates which PDMA controller has target abort error; User can write 1 to clear these bits. + * | | |0 = No AHB bus ERROR response received when channel n transfer. + * | | |1 = AHB bus ERROR response received when channel n transfer. + * @var PDMA_T::TDSTS + * Offset: 0x424 PDMA Channel Transfer Done Flag Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |TDIFn |Transfer Done Flag + * | | |This bit indicates whether PDMA controller channel transfer has been finished or not, user can write 1 to clear these bits. + * | | |0 = PDMA channel transfer has not finished. + * | | |1 = PDMA channel has finished transmission. + * @var PDMA_T::ALIGN + * Offset: 0x428 PDMA Transfer Alignment Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |ALIGNn |Transfer Alignment Flag + * | | |0 = PDMA channel source address and destination address both follow transfer width setting. + * | | |1 = PDMA channel source address or destination address is not follow transfer width setting. + * @var PDMA_T::TACTSTS + * Offset: 0x42C PDMA Transfer Active Flag Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |TXACTFn |Transfer on Active Flag (Read Only) + * | | |This bit indicates which PDMA channel is in active. + * | | |0 = PDMA channel is not finished. + * | | |1 = PDMA channel is active. + * @var PDMA_T::TOUTPSC + * Offset: 0x430 PDMA Time-out Prescaler Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |TOUTPSC0 |PDMA Channel 0 Time-out Clock Source Prescaler Bits + * | | |000 = PDMA channel 0 time-out clock source is HCLK/2^8. + * | | |001 = PDMA channel 0 time-out clock source is HCLK/2^9. + * | | |010 = PDMA channel 0 time-out clock source is HCLK/2^10. + * | | |011 = PDMA channel 0 time-out clock source is HCLK/2^11. + * | | |100 = PDMA channel 0 time-out clock source is HCLK/2^12. + * | | |101 = PDMA channel 0 time-out clock source is HCLK/2^13. + * | | |110 = PDMA channel 0 time-out clock source is HCLK/2^14. + * | | |111 = PDMA channel 0 time-out clock source is HCLK/2^15. + * |[6:4] |TOUTPSC1 |PDMA Channel 1 Time-out Clock Source Prescaler Bits + * | | |000 = PDMA channel 1 time-out clock source is HCLK/2^8. + * | | |001 = PDMA channel 1 time-out clock source is HCLK/2^9. + * | | |010 = PDMA channel 1 time-out clock source is HCLK/2^10. + * | | |011 = PDMA channel 1 time-out clock source is HCLK/2^11. + * | | |100 = PDMA channel 1 time-out clock source is HCLK/2^12. + * | | |101 = PDMA channel 1 time-out clock source is HCLK/2^13. + * | | |110 = PDMA channel 1 time-out clock source is HCLK/2^14. + * | | |111 = PDMA channel 1 time-out clock source is HCLK/2^15. + * @var PDMA_T::TOUTEN + * Offset: 0x434 PDMA Time-out Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |TOUTENn |PDMA Time-out Enable Bits + * | | |0 = PDMA Channel n time-out function Disabled. + * | | |1 = PDMA Channel n time-out function Enabled. + * @var PDMA_T::TOUTIEN + * Offset: 0x438 PDMA Time-out Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |TOUTIENn |PDMA Time-out Interrupt Enable Bits + * | | |0 = PDMA Channel n time-out interrupt Disabled. + * | | |1 = PDMA Channel n time-out interrupt Enabled. + * @var PDMA_T::SCATBA + * Offset: 0x43C PDMA Scatter-gather Descriptor Table Base Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:16] |SCATBA |PDMA Scatter-gather Descriptor Table Address + * | | |In Scatter-Gather mode, this is the base address for calculating the next link - list address. + * | | |The next link address equation is + * | | |Next Link Address = PDMA_SCATBA + PDMA_DSCT_NEXT. + * | | |Note: Only useful in Scatter-Gather mode. + * @var PDMA_T::TOC0_1 + * Offset: 0x440 PDMA Time-out Counter Ch1 and Ch0 Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |TOC0 |Time-out Counter for Channel 0 + * | | |This controls the period of time-out function for channel 0. + * | | |The calculation unit is based on TOUTPSC0 (PDMA_TOUTPSC[2:0]) clock. + * | | |Time-out period = (Period of time-out clock) * (16-bit TOCn), n = 0,1. + * |[31:16] |TOC1 |Time-out Counter for Channel 1 + * | | |This controls the period of time-out function for channel 1. + * | | |The calculation unit is based on TOUTPSC1 (PDMA_TOUTPSC[6:4]) clock. + * | | |The example of time-out period can refer TOC0 bit description. + * @var PDMA_T::CHRST + * Offset: 0x460 PDMA Channel Reset Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |CHnRST |Channel N Reset + * | | |0 = corresponding channel n is not reset. + * | | |1 = corresponding channel n is reset. + * @var PDMA_T::REQSEL0_3 + * Offset: 0x480 PDMA Request Source Select Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |REQSRC0 |Channel 0 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 0. + * | | |User can configure the peripheral by setting REQSRC0. + * | | |0 = Disable PDMA peripheral request. + * | | |1 = reserved. + * | | |2 = reserved. + * | | |3 = reserved. + * | | |4 = Channel connects to UART0_TX. + * | | |5 = Channel connects to UART0_RX. + * | | |6 = Channel connects to UART1_TX. + * | | |7 = Channel connects to UART1_RX. + * | | |8 = Channel connects to UART2_TX. + * | | |9 = Channel connects to UART2_RX. + * | | |10 = Channel connects to USCI0_TX. + * | | |11 = Channel connects to USCI0_RX. + * | | |12 = Channel connects to USCI1_TX. + * | | |13 = Channel connects to USCI1_RX. + * | | |14 = Reserved. + * | | |15 = Reserved. + * | | |16 = Channel connects to QSPI0_TX. + * | | |17 = Channel connects to QSPI0_RX. + * | | |18 = Channel connects to SPI0_TX. + * | | |19 = Channel connects to SPI0_RX. + * | | |20 = Channel connects to ADC_RX. + * | | |21 = Channel connects to PWM0_P1_RX. + * | | |22 = Channel connects to PWM0_P2_RX. + * | | |23 = Channel connects to PWM0_P3_RX. + * | | |24 = Channel connects to PWM1_P1_RX. + * | | |25 = Channel connects to PWM1_P2_RX. + * | | |26 = Channel connects to PWM1_P3_RX. + * | | |27 = Reserved. + * | | |28 = Channel connects to I2C0_TX. + * | | |29 = Channel connects to I2C0_RX. + * | | |30 = Channel connects to I2C1_TX. + * | | |31 = Channel connects to I2C1_RX. + * | | |32 = Channel connects to TMR0. + * | | |33 = Channel connects to TMR1. + * | | |34 = Channel connects to TMR2. + * | | |35 = Channel connects to TMR3. + * | | |36 = Channel connects to UART3_TX. + * | | |37 = Channel connects to UART3_RX. + * | | |38 = Channel connects to UART4_TX. + * | | |39 = Channel connects to UART4_RX. + * | | |40 = Channel connects to UART5_TX. + * | | |41 = Channel connects to UART5_RX. + * | | |42 = Channel connects to UART6_TX. + * | | |43 = Channel connects to UART6_RX. + * | | |44 = Channel connects to UART7_TX. + * | | |45 = Channel connects to UART7_RX. + * | | |Others = Reserved. + * | | |Note 1: A peripheral cannot be assigned to two channels at the same time. + * | | |Note 2: This field is useless when transfer between memory and memory. + * |[13:8] |REQSRC1 |Channel 1 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 1. + * | | |User can configure the peripheral setting by REQSRC1. + * | | |Note: The channel configuration is the same as REQSRC0 field. + * | | |Please refer to the explanation of REQSRC0. + * |[21:16] |REQSRC2 |Channel 2 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 2. + * | | |User can configure the peripheral setting by REQSRC2. + * | | |Note: The channel configuration is the same as REQSRC0 field. + * | | |Please refer to the explanation of REQSRC0. + * |[29:24] |REQSRC3 |Channel 3 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 3. + * | | |User can configure the peripheral setting by REQSRC3. + * | | |Note: The channel configuration is the same as REQSRC0 field. + * | | |Please refer to the explanation of REQSRC0. + * @var PDMA_T::REQSEL4_7 + * Offset: 0x484 PDMA Request Source Select Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |REQSRC4 |Channel 4 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 4. + * | | |User can configure the peripheral setting by REQSRC4. + * | | |Note: The channel configuration is the same as REQSRC0 field. + * | | |Please refer to the explanation of REQSRC0. + * |[13:8] |REQSRC5 |Channel 5 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 5. + * | | |User can configure the peripheral setting by REQSRC5. + * | | |Note: The channel configuration is the same as REQSRC0 field. + * | | |Please refer to the explanation of REQSRC0. + * |[21:16] |REQSRC6 |Channel 6 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 6. + * | | |User can configure the peripheral setting by REQSRC6. + * | | |Note: The channel configuration is the same as REQSRC0 field. + * | | |Please refer to the explanation of REQSRC0. + * |[29:24] |REQSRC7 |Channel 7 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 7. + * | | |User can configure the peripheral setting by REQSRC7. + * | | |Note: The channel configuration is the same as REQSRC0 field. + * | | |Please refer to the explanation of REQSRC0. + * @var PDMA_T::REQSEL8 + * Offset: 0x488 PDMA Request Source Select Register 2 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |REQSRC8 |Channel 8 Request Source Selection + * | | |This filed defines which peripheral is connected to PDMA channel 8. + * | | |User can configure the peripheral setting by REQSRC8. + * | | |Note: The channel configuration is the same as REQSRC0 field. + * | | |Please refer to the explanation of REQSRC0. + */ + DSCT_T DSCT[9]; /*!< [0x0000 ~ 0x008C] Control Register of PDMA Channel 0 ~ 8 */ + __I uint32_t RESERVE0[28]; + __I uint32_t CURSCAT[9]; /*!< [0x0100 ~ 0x110] Current Scatter-gather Descriptor Table Address of PDMA Channel n */ + __I uint32_t RESERVE1[183]; + __IO uint32_t CHCTL; /*!< [0x0400] PDMA Channel Control Register */ + __O uint32_t PAUSE; /*!< [0x0404] PDMA Transfer Pause Control Register */ + __O uint32_t SWREQ; /*!< [0x0408] PDMA Software Request Register */ + __I uint32_t TRGSTS; /*!< [0x040c] PDMA Channel Request Status Register */ + __IO uint32_t PRISET; /*!< [0x0410] PDMA Fixed Priority Setting Register */ + __O uint32_t PRICLR; /*!< [0x0414] PDMA Fixed Priority Clear Register */ + __IO uint32_t INTEN; /*!< [0x0418] PDMA Interrupt Enable Register */ + __IO uint32_t INTSTS; /*!< [0x041c] PDMA Interrupt Status Register */ + __IO uint32_t ABTSTS; /*!< [0x0420] PDMA Channel Read/Write Target Abort Flag Register */ + __IO uint32_t TDSTS; /*!< [0x0424] PDMA Channel Transfer Done Flag Register */ + __IO uint32_t ALIGN; /*!< [0x0428] PDMA Transfer Alignment Status Register */ + __I uint32_t TACTSTS; /*!< [0x042c] PDMA Transfer Active Flag Register */ + __IO uint32_t TOUTPSC; /*!< [0x0430] PDMA Time-out Prescaler Register */ + __IO uint32_t TOUTEN; /*!< [0x0434] PDMA Time-out Enable Register */ + __IO uint32_t TOUTIEN; /*!< [0x0438] PDMA Time-out Interrupt Enable Register */ + __IO uint32_t SCATBA; /*!< [0x043c] PDMA Scatter-gather Descriptor Table Base Address Register */ + __IO uint32_t TOC0_1; /*!< [0x0440] PDMA Time-out Counter Ch1 and Ch0 Register */ + __I uint32_t RESERVE2[7]; + __IO uint32_t CHRST; /*!< [0x0460] PDMA Channel Reset Register */ + __I uint32_t RESERVE3[7]; + __IO uint32_t REQSEL0_3; /*!< [0x0480] PDMA Request Source Select Register 0 */ + __IO uint32_t REQSEL4_7; /*!< [0x0484] PDMA Request Source Select Register 1 */ + __IO uint32_t REQSEL8; /*!< [0x0488] PDMA Request Source Select Register 2 */ +} PDMA_T; + +/** + @addtogroup PDMA_CONST PDMA Bit Field Definition + Constant Definitions for PDMA Controller +@{ */ + +#define PDMA_DSCT_CTL_OPMODE_Pos (0) /*!< DSCT_T::CTL: OPMODE Position */ +#define PDMA_DSCT_CTL_OPMODE_Msk (0x3ul << PDMA_DSCT_CTL_OPMODE_Pos) /*!< DSCT_T::CTL: OPMODE Mask */ + +#define PDMA_DSCT_CTL_TXTYPE_Pos (2) /*!< DSCT_T::CTL: TXTYPE Position */ +#define PDMA_DSCT_CTL_TXTYPE_Msk (0x1ul << PDMA_DSCT_CTL_TXTYPE_Pos) /*!< DSCT_T::CTL: TXTYPE Mask */ + +#define PDMA_DSCT_CTL_BURSIZE_Pos (4) /*!< DSCT_T::CTL: BURSIZE Position */ +#define PDMA_DSCT_CTL_BURSIZE_Msk (0x7ul << PDMA_DSCT_CTL_BURSIZE_Pos) /*!< DSCT_T::CTL: BURSIZE Mask */ + +#define PDMA_DSCT_CTL_TBINTDIS_Pos (7) /*!< DSCT_T::CTL: TBINTDIS Position */ +#define PDMA_DSCT_CTL_TBINTDIS_Msk (0x1ul << PDMA_DSCT_CTL_TBINTDIS_Pos) /*!< DSCT_T::CTL: TBINTDIS Mask */ + +#define PDMA_DSCT_CTL_SAINC_Pos (8) /*!< DSCT_T::CTL: SAINC Position */ +#define PDMA_DSCT_CTL_SAINC_Msk (0x3ul << PDMA_DSCT_CTL_SAINC_Pos) /*!< DSCT_T::CTL: SAINC Mask */ + +#define PDMA_DSCT_CTL_DAINC_Pos (10) /*!< DSCT_T::CTL: DAINC Position */ +#define PDMA_DSCT_CTL_DAINC_Msk (0x3ul << PDMA_DSCT_CTL_DAINC_Pos) /*!< DSCT_T::CTL: DAINC Mask */ + +#define PDMA_DSCT_CTL_TXWIDTH_Pos (12) /*!< DSCT_T::CTL: TXWIDTH Position */ +#define PDMA_DSCT_CTL_TXWIDTH_Msk (0x3ul << PDMA_DSCT_CTL_TXWIDTH_Pos) /*!< DSCT_T::CTL: TXWIDTH Mask */ + +#define PDMA_DSCT_CTL_TXCNT_Pos (16) /*!< DSCT_T::CTL: TXCNT Position */ +#define PDMA_DSCT_CTL_TXCNT_Msk (0xfffful << PDMA_DSCT_CTL_TXCNT_Pos) /*!< DSCT_T::CTL: TXCNT Mask */ + +#define PDMA_DSCT_SA_SA_Pos (0) /*!< DSCT_T::SA: SA Position */ +#define PDMA_DSCT_SA_SA_Msk (0xfffffffful << PDMA_DSCT_SA_SA_Pos) /*!< DSCT_T::SA: SA Mask */ + +#define PDMA_DSCT_DA_DA_Pos (0) /*!< DSCT_T::DA: DA Position */ +#define PDMA_DSCT_DA_DA_Msk (0xfffffffful << PDMA_DSCT_DA_DA_Pos) /*!< DSCT_T::DA: DA Mask */ + +#define PDMA_DSCT_NEXT_NEXT_Pos (0) /*!< DSCT_T::NEXT: NEXT Position */ +#define PDMA_DSCT_NEXT_NEXT_Msk (0xfffful << PDMA_DSCT_NEXT_NEXT_Pos) /*!< DSCT_T::NEXT: NEXT Mask */ + +#define PDMA_DSCT_NEXT_EXENEXT_Pos (16) /*!< DSCT_T::NEXT: EXENEXT Position */ +#define PDMA_DSCT_NEXT_EXENEXT_Msk (0xfffful << PDMA_DSCT_NEXT_EXENEXT_Pos) /*!< DSCT_T::NEXT: EXENEXT Mask */ + +#define PDMA_CURSCAT_CURADDR_Pos (0) /*!< PDMA_T::CURSCAT: CURADDR Position */ +#define PDMA_CURSCAT_CURADDR_Msk (0xfffffffful << PDMA_CURSCAT_CURADDR_Pos) /*!< PDMA_T::CURSCAT: CURADDR Mask */ + +#define PDMA_CHCTL_CHENn_Pos (0) /*!< PDMA_T::CHCTL: CHENn Position */ +#define PDMA_CHCTL_CHENn_Msk (0x1fful << PDMA_CHCTL_CHENn_Pos) /*!< PDMA_T::CHCTL: CHENn Mask */ + +#define PDMA_PAUSE_PAUSEn_Pos (0) /*!< PDMA_T::PAUSE: PAUSEn Position */ +#define PDMA_PAUSE_PAUSEn_Msk (0x1fful << PDMA_PAUSE_PAUSEn_Pos) /*!< PDMA_T::PAUSE: PAUSEn Mask */ + +#define PDMA_SWREQ_SWREQn_Pos (0) /*!< PDMA_T::SWREQ: SWREQn Position */ +#define PDMA_SWREQ_SWREQn_Msk (0x1fful << PDMA_SWREQ_SWREQn_Pos) /*!< PDMA_T::SWREQ: SWREQn Mask */ + +#define PDMA_TRGSTS_REQSTSn_Pos (0) /*!< PDMA_T::TRGSTS: REQSTSn Position */ +#define PDMA_TRGSTS_REQSTSn_Msk (0x1fful << PDMA_TRGSTS_REQSTSn_Pos) /*!< PDMA_T::TRGSTS: REQSTSn Mask */ + +#define PDMA_PRISET_FPRISETn_Pos (0) /*!< PDMA_T::PRISET: FPRISETn Position */ +#define PDMA_PRISET_FPRISETn_Msk (0x1fful << PDMA_PRISET_FPRISETn_Pos) /*!< PDMA_T::PRISET: FPRISETn Mask */ + +#define PDMA_PRICLR_FPRICLRn_Pos (0) /*!< PDMA_T::PRICLR: FPRICLRn Position */ +#define PDMA_PRICLR_FPRICLRn_Msk (0x1fful << PDMA_PRICLR_FPRICLRn_Pos) /*!< PDMA_T::PRICLR: FPRICLRn Mask */ + +#define PDMA_INTEN_INTENn_Pos (0) /*!< PDMA_T::INTEN: INTENn Position */ +#define PDMA_INTEN_INTENn_Msk (0x1fful << PDMA_INTEN_INTENn_Pos) /*!< PDMA_T::INTEN: INTENn Mask */ + +#define PDMA_INTSTS_ABTIF_Pos (0) /*!< PDMA_T::INTSTS: ABTIF Position */ +#define PDMA_INTSTS_ABTIF_Msk (0x1ul << PDMA_INTSTS_ABTIF_Pos) /*!< PDMA_T::INTSTS: ABTIF Mask */ + +#define PDMA_INTSTS_TDIF_Pos (1) /*!< PDMA_T::INTSTS: TDIF Position */ +#define PDMA_INTSTS_TDIF_Msk (0x1ul << PDMA_INTSTS_TDIF_Pos) /*!< PDMA_T::INTSTS: TDIF Mask */ + +#define PDMA_INTSTS_ALIGNF_Pos (2) /*!< PDMA_T::INTSTS: ALIGNF Position */ +#define PDMA_INTSTS_ALIGNF_Msk (0x1ul << PDMA_INTSTS_ALIGNF_Pos) /*!< PDMA_T::INTSTS: ALIGNF Mask */ + +#define PDMA_INTSTS_REQTOF0_Pos (8) /*!< PDMA_T::INTSTS: REQTOF0 Position */ +#define PDMA_INTSTS_REQTOF0_Msk (0x1ul << PDMA_INTSTS_REQTOF0_Pos) /*!< PDMA_T::INTSTS: REQTOF0 Mask */ + +#define PDMA_INTSTS_REQTOF1_Pos (9) /*!< PDMA_T::INTSTS: REQTOF1 Position */ +#define PDMA_INTSTS_REQTOF1_Msk (0x1ul << PDMA_INTSTS_REQTOF1_Pos) /*!< PDMA_T::INTSTS: REQTOF1 Mask */ + +#define PDMA_ABTSTS_ABTIF0_Pos (0) /*!< PDMA_T::ABTSTS: ABTIF0 Position */ +#define PDMA_ABTSTS_ABTIF0_Msk (0x1ul << PDMA_ABTSTS_ABTIF0_Pos) /*!< PDMA_T::ABTSTS: ABTIF0 Mask */ + +#define PDMA_ABTSTS_ABTIF1_Pos (1) /*!< PDMA_T::ABTSTS: ABTIF1 Position */ +#define PDMA_ABTSTS_ABTIF1_Msk (0x1ul << PDMA_ABTSTS_ABTIF1_Pos) /*!< PDMA_T::ABTSTS: ABTIF1 Mask */ + +#define PDMA_ABTSTS_ABTIF2_Pos (2) /*!< PDMA_T::ABTSTS: ABTIF2 Position */ +#define PDMA_ABTSTS_ABTIF2_Msk (0x1ul << PDMA_ABTSTS_ABTIF2_Pos) /*!< PDMA_T::ABTSTS: ABTIF2 Mask */ + +#define PDMA_ABTSTS_ABTIF3_Pos (3) /*!< PDMA_T::ABTSTS: ABTIF3 Position */ +#define PDMA_ABTSTS_ABTIF3_Msk (0x1ul << PDMA_ABTSTS_ABTIF3_Pos) /*!< PDMA_T::ABTSTS: ABTIF3 Mask */ + +#define PDMA_ABTSTS_ABTIF4_Pos (4) /*!< PDMA_T::ABTSTS: ABTIF4 Position */ +#define PDMA_ABTSTS_ABTIF4_Msk (0x1ul << PDMA_ABTSTS_ABTIF4_Pos) /*!< PDMA_T::ABTSTS: ABTIF4 Mask */ + +#define PDMA_ABTSTS_ABTIF5_Pos (5) /*!< PDMA_T::ABTSTS: ABTIF5 Position */ +#define PDMA_ABTSTS_ABTIF5_Msk (0x1ul << PDMA_ABTSTS_ABTIF5_Pos) /*!< PDMA_T::ABTSTS: ABTIF5 Mask */ + +#define PDMA_ABTSTS_ABTIF6_Pos (6) /*!< PDMA_T::ABTSTS: ABTIF6 Position */ +#define PDMA_ABTSTS_ABTIF6_Msk (0x1ul << PDMA_ABTSTS_ABTIF6_Pos) /*!< PDMA_T::ABTSTS: ABTIF6 Mask */ + +#define PDMA_ABTSTS_ABTIF7_Pos (7) /*!< PDMA_T::ABTSTS: ABTIF7 Position */ +#define PDMA_ABTSTS_ABTIF7_Msk (0x1ul << PDMA_ABTSTS_ABTIF7_Pos) /*!< PDMA_T::ABTSTS: ABTIF7 Mask */ + +#define PDMA_ABTSTS_ABTIF8_Pos (8) /*!< PDMA_T::ABTSTS: ABTIF8 Position */ +#define PDMA_ABTSTS_ABTIF8_Msk (0x1ul << PDMA_ABTSTS_ABTIF8_Pos) /*!< PDMA_T::ABTSTS: ABTIF8 Mask */ + +#define PDMA_TDSTS_TDIF0_Pos (0) /*!< PDMA_T::TDSTS: TDIF0 Position */ +#define PDMA_TDSTS_TDIF0_Msk (0x1ul << PDMA_TDSTS_TDIF0_Pos) /*!< PDMA_T::TDSTS: TDIF0 Mask */ + +#define PDMA_TDSTS_TDIF1_Pos (1) /*!< PDMA_T::TDSTS: TDIF1 Position */ +#define PDMA_TDSTS_TDIF1_Msk (0x1ul << PDMA_TDSTS_TDIF1_Pos) /*!< PDMA_T::TDSTS: TDIF1 Mask */ + +#define PDMA_TDSTS_TDIF2_Pos (2) /*!< PDMA_T::TDSTS: TDIF2 Position */ +#define PDMA_TDSTS_TDIF2_Msk (0x1ul << PDMA_TDSTS_TDIF2_Pos) /*!< PDMA_T::TDSTS: TDIF2 Mask */ + +#define PDMA_TDSTS_TDIF3_Pos (3) /*!< PDMA_T::TDSTS: TDIF3 Position */ +#define PDMA_TDSTS_TDIF3_Msk (0x1ul << PDMA_TDSTS_TDIF3_Pos) /*!< PDMA_T::TDSTS: TDIF3 Mask */ + +#define PDMA_TDSTS_TDIF4_Pos (4) /*!< PDMA_T::TDSTS: TDIF4 Position */ +#define PDMA_TDSTS_TDIF4_Msk (0x1ul << PDMA_TDSTS_TDIF4_Pos) /*!< PDMA_T::TDSTS: TDIF4 Mask */ + +#define PDMA_TDSTS_TDIF5_Pos (5) /*!< PDMA_T::TDSTS: TDIF5 Position */ +#define PDMA_TDSTS_TDIF5_Msk (0x1ul << PDMA_TDSTS_TDIF5_Pos) /*!< PDMA_T::TDSTS: TDIF5 Mask */ + +#define PDMA_TDSTS_TDIF6_Pos (6) /*!< PDMA_T::TDSTS: TDIF6 Position */ +#define PDMA_TDSTS_TDIF6_Msk (0x1ul << PDMA_TDSTS_TDIF6_Pos) /*!< PDMA_T::TDSTS: TDIF6 Mask */ + +#define PDMA_TDSTS_TDIF7_Pos (7) /*!< PDMA_T::TDSTS: TDIF7 Position */ +#define PDMA_TDSTS_TDIF7_Msk (0x1ul << PDMA_TDSTS_TDIF7_Pos) /*!< PDMA_T::TDSTS: TDIF7 Mask */ + +#define PDMA_TDSTS_TDIF8_Pos (8) /*!< PDMA_T::TDSTS: TDIF8 Position */ +#define PDMA_TDSTS_TDIF8_Msk (0x1ul << PDMA_TDSTS_TDIF8_Pos) /*!< PDMA_T::TDSTS: TDIF8 Mask */ + +#define PDMA_ALIGN_ALIGNn_Pos (0) /*!< PDMA_T::ALIGN: ALIGNn Position */ +#define PDMA_ALIGN_ALIGNn_Msk (0x1fful << PDMA_ALIGN_ALIGNn_Pos) /*!< PDMA_T::ALIGN: ALIGNn Mask */ + +#define PDMA_TACTSTS_TXACTFn_Pos (0) /*!< PDMA_T::TACTSTS: TXACTFn Position */ +#define PDMA_TACTSTS_TXACTFn_Msk (0x1fful << PDMA_TACTSTS_TXACTFn_Pos) /*!< PDMA_T::TACTSTS: TXACTFn Mask */ + +#define PDMA_TOUTPSC_TOUTPSC0_Pos (0) /*!< PDMA_T::TOUTPSC: TOUTPSC0 Position */ +#define PDMA_TOUTPSC_TOUTPSC0_Msk (0x7ul << PDMA_TOUTPSC_TOUTPSC0_Pos) /*!< PDMA_T::TOUTPSC: TOUTPSC0 Mask */ + +#define PDMA_TOUTPSC_TOUTPSC1_Pos (4) /*!< PDMA_T::TOUTPSC: TOUTPSC1 Position */ +#define PDMA_TOUTPSC_TOUTPSC1_Msk (0x7ul << PDMA_TOUTPSC_TOUTPSC1_Pos) /*!< PDMA_T::TOUTPSC: TOUTPSC1 Mask */ + +#define PDMA_TOUTEN_TOUTENn_Pos (0) /*!< PDMA_T::TOUTEN: TOUTENn Position */ +#define PDMA_TOUTEN_TOUTENn_Msk (0x3ul << PDMA_TOUTEN_TOUTENn_Pos) /*!< PDMA_T::TOUTEN: TOUTENn Mask */ + +#define PDMA_TOUTIEN_TOUTIENn_Pos (0) /*!< PDMA_T::TOUTIEN: TOUTIENn Position */ +#define PDMA_TOUTIEN_TOUTIENn_Msk (0x3ul << PDMA_TOUTIEN_TOUTIENn_Pos) /*!< PDMA_T::TOUTIEN: TOUTIENn Mask */ + +#define PDMA_SCATBA_SCATBA_Pos (16) /*!< PDMA_T::SCATBA: SCATBA Position */ +#define PDMA_SCATBA_SCATBA_Msk (0xfffful << PDMA_SCATBA_SCATBA_Pos) /*!< PDMA_T::SCATBA: SCATBA Mask */ + +#define PDMA_TOC0_1_TOC0_Pos (0) /*!< PDMA_T::TOC0_1: TOC0 Position */ +#define PDMA_TOC0_1_TOC0_Msk (0xfffful << PDMA_TOC0_1_TOC0_Pos) /*!< PDMA_T::TOC0_1: TOC0 Mask */ + +#define PDMA_TOC0_1_TOC1_Pos (16) /*!< PDMA_T::TOC0_1: TOC1 Position */ +#define PDMA_TOC0_1_TOC1_Msk (0xfffful << PDMA_TOC0_1_TOC1_Pos) /*!< PDMA_T::TOC0_1: TOC1 Mask */ + +#define PDMA_CHRST_CHnRST_Pos (0) /*!< PDMA_T::CHRST: CHnRST Position */ +#define PDMA_CHRST_CHnRST_Msk (0x1fful << PDMA_CHRST_CHnRST_Pos) /*!< PDMA_T::CHRST: CHnRST Mask */ + +#define PDMA_REQSEL0_3_REQSRC0_Pos (0) /*!< PDMA_T::REQSEL0_3: REQSRC0 Position */ +#define PDMA_REQSEL0_3_REQSRC0_Msk (0x3ful << PDMA_REQSEL0_3_REQSRC0_Pos) /*!< PDMA_T::REQSEL0_3: REQSRC0 Mask */ + +#define PDMA_REQSEL0_3_REQSRC1_Pos (8) /*!< PDMA_T::REQSEL0_3: REQSRC1 Position */ +#define PDMA_REQSEL0_3_REQSRC1_Msk (0x3ful << PDMA_REQSEL0_3_REQSRC1_Pos) /*!< PDMA_T::REQSEL0_3: REQSRC1 Mask */ + +#define PDMA_REQSEL0_3_REQSRC2_Pos (16) /*!< PDMA_T::REQSEL0_3: REQSRC2 Position */ +#define PDMA_REQSEL0_3_REQSRC2_Msk (0x3ful << PDMA_REQSEL0_3_REQSRC2_Pos) /*!< PDMA_T::REQSEL0_3: REQSRC2 Mask */ + +#define PDMA_REQSEL0_3_REQSRC3_Pos (24) /*!< PDMA_T::REQSEL0_3: REQSRC3 Position */ +#define PDMA_REQSEL0_3_REQSRC3_Msk (0x3ful << PDMA_REQSEL0_3_REQSRC3_Pos) /*!< PDMA_T::REQSEL0_3: REQSRC3 Mask */ + +#define PDMA_REQSEL4_7_REQSRC4_Pos (0) /*!< PDMA_T::REQSEL4_7: REQSRC4 Position */ +#define PDMA_REQSEL4_7_REQSRC4_Msk (0x3ful << PDMA_REQSEL4_7_REQSRC4_Pos) /*!< PDMA_T::REQSEL4_7: REQSRC4 Mask */ + +#define PDMA_REQSEL4_7_REQSRC5_Pos (8) /*!< PDMA_T::REQSEL4_7: REQSRC5 Position */ +#define PDMA_REQSEL4_7_REQSRC5_Msk (0x3ful << PDMA_REQSEL4_7_REQSRC5_Pos) /*!< PDMA_T::REQSEL4_7: REQSRC5 Mask */ + +#define PDMA_REQSEL4_7_REQSRC6_Pos (16) /*!< PDMA_T::REQSEL4_7: REQSRC6 Position */ +#define PDMA_REQSEL4_7_REQSRC6_Msk (0x3ful << PDMA_REQSEL4_7_REQSRC6_Pos) /*!< PDMA_T::REQSEL4_7: REQSRC6 Mask */ + +#define PDMA_REQSEL4_7_REQSRC7_Pos (24) /*!< PDMA_T::REQSEL4_7: REQSRC7 Position */ +#define PDMA_REQSEL4_7_REQSRC7_Msk (0x3ful << PDMA_REQSEL4_7_REQSRC7_Pos) /*!< PDMA_T::REQSEL4_7: REQSRC7 Mask */ + +#define PDMA_REQSEL8_REQSRC8_Pos (0) /*!< PDMA_T::REQSEL8: REQSRC8 Position */ +#define PDMA_REQSEL8_REQSRC8_Msk (0x3ful << PDMA_REQSEL8_REQSRC8_Pos) /*!< PDMA_T::REQSEL8: REQSRC8 Mask */ +/**@}*/ /* PDMA_CONST */ +/**@}*/ /* end of PDMA register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __PDMA_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/pwm_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/pwm_reg.h new file mode 100644 index 0000000000..04d49de17b --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/pwm_reg.h @@ -0,0 +1,2294 @@ +/**************************************************************************//** + * @file pwm_reg.h + * @version V1.00 + * @brief PWM register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __PWM_REG_H__ +#define __PWM_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup PWM Pulse Width Modulation Controller (PWM) + Memory Mapped Structure for PWM Controller +@{ */ + +typedef struct +{ + /** + * @var PWM_T::CTL0 + * Offset: 0x00 PWM Control Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CTRLDn |Center Load Enable Bits + * | | |0 = Center Loading mode is disable for corresponding PWM channel n + * | | |1 = Center Loading mode is enable for corresponding PWM channel n + * | | |Each bit n controls the corresponding PWM channel n. + * | | |In up-down counter type, PERIOD will load to PBUF at the end point of each period. + * | | |CMPDAT will load to CMPBUF at the center point of a period. + * |[16] |IMMLDENn |Immediately Load Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = PERIOD will load to PBUF at the end point of each period. + * | | |CMPDAT will load to CMPBUF at the end point or center point of each period by setting CTRLD bit. + * | | |1 = PERIOD/CMPDAT will load to PBUF and CMPBUF immediately when software update PERIOD/CMPDAT. + * | | |Note: If IMMLDENn is enabled, WINLDENn and CTRLDn will be invalid. + * |[30] |DBGHALT |ICE Debug Mode Counter Halt (Write Protect) + * | | |If counter halt is enabled, PWM all counters will keep current value until exit ICE debug mode. + * | | |0 = ICE debug mode counter halt disable. + * | | |1 = ICE debug mode counter halt enable. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[31] |DBGTRIOFF |ICE Debug Mode Acknowledge Disable (Write Protect) + * | | |0 = ICE debug mode acknowledgement affects PWM output. + * | | |PWM pin will be forced as tri-state while ICE debug mode acknowledged. + * | | |1 = ICE debug mode acknowledgement disabled. + * | | |PWM pin will keep output no matter ICE debug mode acknowledged or not. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * @var PWM_T::CTL1 + * Offset: 0x04 PWM Control Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |CNTTYPE0 |PWM Counter Behavior Type 0 + * | | |The two bits control channel 1 and channel 0. + * | | |00 = Up counter type (supports in capture mode). + * | | |01 = Down count type (supports in capture mode). + * | | |10 = Up-down counter type. + * | | |11 = Reserved. + * |[5:4] |CNTTYPE2 |PWM Counter Behavior Type 2 + * | | |The two bits control channel 3 and channel 2. + * | | |00 = Up counter type (supports in capture mode). + * | | |01 = Down count type (supports in capture mode). + * | | |10 = Up-down counter type. + * | | |11 = Reserved. + * |[9:8] |CNTTYPE4 |PWM Counter Behavior Type 4 + * | | |The two bits control channel 5 and channel 4. + * | | |00 = Up counter type (supports in capture mode). + * | | |01 = Down count type (supports in capture mode). + * | | |10 = Up-down counter type. + * | | |11 = Reserved. + * |[26:24] |PWMMODEn |PWM Mode + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = PWM independent mode. + * | | |1 = PWM complementary mode. + * | | |Note: When operating in group function, these bits must all set to the same mode. + * @var PWM_T::CLKSRC + * Offset: 0x10 PWM Clock Source Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |ECLKSRC0 |PWM_CH01 External Clock Source Select + * | | |000 = PWMx_CLK, x denotes 0 or 1. + * | | |001 = TIMER0 overflow. + * | | |010 = TIMER1 overflow. + * | | |011 = TIMER2 overflow. + * | | |100 = TIMER3 overflow. + * | | |Others = Reserved. + * |[10:8] |ECLKSRC2 |PWM_CH23 External Clock Source Select + * | | |000 = PWMx_CLK, x denotes 0 or 1. + * | | |001 = TIMER0 overflow. + * | | |010 = TIMER1 overflow. + * | | |011 = TIMER2 overflow. + * | | |100 = TIMER3 overflow. + * | | |Others = Reserved. + * |[18:16] |ECLKSRC4 |PWM_CH45 External Clock Source Select + * | | |000 = PWMx_CLK, x denotes 0 or 1. + * | | |001 = TIMER0 overflow. + * | | |010 = TIMER1 overflow. + * | | |011 = TIMER2 overflow. + * | | |100 = TIMER3 overflow. + * | | |Others = Reserved. + * @var PWM_T::CLKPSC[3] + * Offset: 0x14 PWM Clock Prescale Register 0/1, 2/3, 4/5 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[11:0] |CLKPSC |PWM Counter Clock Prescale + * | | |The clock of PWM counter is decided by clock prescaler. + * | | |Each PWM pair share one PWM counter clock prescaler. + * | | |The clock of PWM counter is divided by (CLKPSC+1). + * @var PWM_T::CNTEN + * Offset: 0x20 PWM Counter Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CNTEN0 |PWM Counter Enable 0 + * | | |0 = PWM Counter and clock prescaler Stop Running. + * | | |1 = PWM Counter and clock prescaler Start Running. + * |[2] |CNTEN2 |PWM Counter Enable 2 + * | | |0 = PWM Counter and clock prescaler Stop Running. + * | | |1 = PWM Counter and clock prescaler Start Running. + * |[4] |CNTEN4 |PWM Counter Enable 4 + * | | |0 = PWM Counter and clock prescaler Stop Running. + * | | |1 = PWM Counter and clock prescaler Start Running. + * @var PWM_T::CNTCLR + * Offset: 0x24 PWM Clear Counter Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CNTCLR0 |Clear PWM Counter Control Bit 0 + * | | |It is automatically cleared by hardware. + * | | |0 = No effect. + * | | |1 = Clear 16-bit PWM counter to 0000H. + * |[2] |CNTCLR2 |Clear PWM Counter Control Bit 2 + * | | |It is automatically cleared by hardware. + * | | |0 = No effect. + * | | |1 = Clear 16-bit PWM counter to 0000H. + * |[4] |CNTCLR4 |Clear PWM Counter Control Bit 4 + * | | |It is automatically cleared by hardware. + * | | |0 = No effect. + * | | |1 = Clear 16-bit PWM counter to 0000H. + * @var PWM_T::PERIOD + * Offset: 0x30~0x44 PWM Period Register 0/2/4 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |PERIOD |PWM Period Register + * | | |Up-Count mode: In this mode, PWM counter counts from 0 to PERIOD, and restarts from 0. + * | | |Down-Count mode: In this mode, PWM counter counts from PERIOD to 0, and restarts from PERIOD. + * | | |PWM period time = (PERIOD+1) * PWM_CLK period. + * | | |Up-Down-Count mode: In this mode, PWM counter counts from 0 to PERIOD, then decrements to 0 and repeats again. + * | | |PWM period time = 2 * PERIOD * PWM_CLK period. + * @var PWM_T::CMPDAT + * Offset: 0x50~0x64 PWM Comparator Register 0~5 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |CMP |PWM Comparator Register + * | | |CMP use to compare with CNT to generate PWM waveform, interrupt and trigger ADC. + * | | |In independent mode, PWM_CMPDAT0~5 denote as 6 independent PWM_CH0~5 compared point. + * | | |In complementary mode, PWM_CMPDAT0, 2, 4 denote as first compared point, and PWM_CMPDAT1, 3, 5 denote as second compared point for the corresponding 3 complementary pairs PWM_CH0 and PWM_CH1, PWM_CH2 and PWM_CH3, PWM_CH4 and PWM_CH5. + * @var PWM_T::DTCTL[3] + * Offset: 0x70 PWM Dead-Time Control Register 0/1,2/3,4/5 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[11:0] |DTCNT |Dead-time Counter (Write Protect) + * | | |The dead-time can be calculated from the following formula: + * | | |Dead-time = (DTCNT[11:0]+1) * PWM_CLK period. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[16] |DTEN |Enable Dead-time Insertion for PWM Pair (PWM_CH0, PWM_CH1) (PWM_CH2, PWM_CH3) (PWM_CH4, PWM_CH5) (Write Protect) + * | | |Dead-time insertion is only active when this pair of complementary PWM is enabled. + * | | |If dead- time insertion is inactive, the outputs of pin pair are complementary without any delay. + * | | |0 = Dead-time insertion Disabled on the pin pair. + * | | |1 = Dead-time insertion Enabled on the pin pair. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[24] |DTCKSEL |Dead-time Clock Select (Write Protect) + * | | |0 = Dead-time clock source from PWM_CLK. + * | | |1 = Dead-time clock source from prescaler output. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * @var PWM_T::CNT + * Offset: 0x90~0xA4 PWM Counter Register 0/2/4 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |CNT |PWM Data Register (Read Only) + * | | |User can monitor CNT to know the current value in 16-bit period counter. + * |[16] |DIRF |PWM Direction Indicator Flag (Read Only) + * | | |0 = Counter is Down count. + * | | |1 = Counter is UP count. + * @var PWM_T::WGCTL0 + * Offset: 0xB0 PWM Generation Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |ZPCTL0 |PWM Zero Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM zero point output Low. + * | | |10 = PWM zero point output High. + * | | |11 = PWM zero point output Toggle. + * | | |Note: PWM can control output level when PWM counter count to 0. + * |[3:2] |ZPCTL1 |PWM Zero Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM zero point output Low. + * | | |10 = PWM zero point output High. + * | | |11 = PWM zero point output Toggle. + * | | |Note: PWM can control output level when PWM counter count to 0. + * |[5:4] |ZPCTL2 |PWM Zero Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM zero point output Low. + * | | |10 = PWM zero point output High. + * | | |11 = PWM zero point output Toggle. + * | | |Note: PWM can control output level when PWM counter count to 0. + * |[7:6] |ZPCTL3 |PWM Zero Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM zero point output Low. + * | | |10 = PWM zero point output High. + * | | |11 = PWM zero point output Toggle. + * | | |Note: PWM can control output level when PWM counter count to 0. + * |[9:8] |ZPCTL4 |PWM Zero Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM zero point output Low. + * | | |10 = PWM zero point output High. + * | | |11 = PWM zero point output Toggle. + * | | |Note: PWM can control output level when PWM counter count to 0. + * |[11:10] |ZPCTL5 |PWM Zero Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM zero point output Low. + * | | |10 = PWM zero point output High. + * | | |11 = PWM zero point output Toggle. + * | | |Note: PWM can control output level when PWM counter count to 0. + * |[17:16] |PRDPCTL0 |PWM Period (Center) Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM period (center) point output Low. + * | | |10 = PWM period (center) point output High. + * | | |11 = PWM period (center) point output Toggle. + * | | |Note1: PWM can control output level when PWM counter count to (PERIODn+1). + * | | |Note2: This bit is center point control when PWM counter operating in up-down counter type. + * |[19:18] |PRDPCTL1 |PWM Period (Center) Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM period (center) point output Low. + * | | |10 = PWM period (center) point output High. + * | | |11 = PWM period (center) point output Toggle. + * | | |Note1: PWM can control output level when PWM counter count to (PERIODn+1). + * | | |Note2: This bit is center point control when PWM counter operating in up-down counter type. + * |[21:20] |PRDPCTL2 |PWM Period (Center) Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM period (center) point output Low. + * | | |10 = PWM period (center) point output High. + * | | |11 = PWM period (center) point output Toggle. + * | | |Note1: PWM can control output level when PWM counter count to (PERIODn+1). + * | | |Note2: This bit is center point control when PWM counter operating in up-down counter type. + * |[23:22] |PRDPCTL3 |PWM Period (Center) Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM period (center) point output Low. + * | | |10 = PWM period (center) point output High. + * | | |11 = PWM period (center) point output Toggle. + * | | |Note1: PWM can control output level when PWM counter count to (PERIODn+1). + * | | |Note2: This bit is center point control when PWM counter operating in up-down counter type. + * |[25:24] |PRDPCTL4 |PWM Period (Center) Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM period (center) point output Low. + * | | |10 = PWM period (center) point output High. + * | | |11 = PWM period (center) point output Toggle. + * | | |Note1: PWM can control output level when PWM counter count to (PERIODn+1). + * | | |Note2: This bit is center point control when PWM counter operating in up-down counter type. + * |[27:26] |PRDPCTL5 |PWM Period (Center) Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM period (center) point output Low. + * | | |10 = PWM period (center) point output High. + * | | |11 = PWM period (center) point output Toggle. + * | | |Note1: PWM can control output level when PWM counter count to (PERIODn+1). + * | | |Note2: This bit is center point control when PWM counter operating in up-down counter type. + * @var PWM_T::WGCTL1 + * Offset: 0xB4 PWM Generation Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |CMPUCTL0 |PWM Compare Up Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare up point output Low. + * | | |10 = PWM compare up point output High. + * | | |11 = PWM compare up point output Toggle. + * | | |Note1: PWM can control output level when PWM counter up count to CMPDAT. + * | | |Note2: In complementary mode, CMPUCTL1, 3, 5 use as another CMPUCTL for channel 0, 2, 4. + * |[3:2] |CMPUCTL1 |PWM Compare Up Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare up point output Low. + * | | |10 = PWM compare up point output High. + * | | |11 = PWM compare up point output Toggle. + * | | |Note1: PWM can control output level when PWM counter up count to CMPDAT. + * | | |Note2: In complementary mode, CMPUCTL1, 3, 5 use as another CMPUCTL for channel 0, 2, 4. + * |[5:4] |CMPUCTL2 |PWM Compare Up Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare up point output Low. + * | | |10 = PWM compare up point output High. + * | | |11 = PWM compare up point output Toggle. + * | | |Note1: PWM can control output level when PWM counter up count to CMPDAT. + * | | |Note2: In complementary mode, CMPUCTL1, 3, 5 use as another CMPUCTL for channel 0, 2, 4. + * |[7:6] |CMPUCTL3 |PWM Compare Up Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare up point output Low. + * | | |10 = PWM compare up point output High. + * | | |11 = PWM compare up point output Toggle. + * | | |Note1: PWM can control output level when PWM counter up count to CMPDAT. + * | | |Note2: In complementary mode, CMPUCTL1, 3, 5 use as another CMPUCTL for channel 0, 2, 4. + * |[9:8] |CMPUCTL4 |PWM Compare Up Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare up point output Low. + * | | |10 = PWM compare up point output High. + * | | |11 = PWM compare up point output Toggle. + * | | |Note1: PWM can control output level when PWM counter up count to CMPDAT. + * | | |Note2: In complementary mode, CMPUCTL1, 3, 5 use as another CMPUCTL for channel 0, 2, 4. + * |[11:10] |CMPUCTL5 |PWM Compare Up Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare up point output Low. + * | | |10 = PWM compare up point output High. + * | | |11 = PWM compare up point output Toggle. + * | | |Note1: PWM can control output level when PWM counter up count to CMPDAT. + * | | |Note2: In complementary mode, CMPUCTL1, 3, 5 use as another CMPUCTL for channel 0, 2, 4. + * |[17:16] |CMPDCTL0 |PWM Compare Down Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare down point output Low. + * | | |10 = PWM compare down point output High. + * | | |11 = PWM compare down point output Toggle. + * | | |Note1: PWM can control output level when PWM counter down count to CMPDAT. + * | | |Note2: In complementary mode, CMPDCTL1, 3, 5 use as another CMPDCTL for channel 0, 2, 4. + * |[19:18] |CMPDCTL1 |PWM Compare Down Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare down point output Low. + * | | |10 = PWM compare down point output High. + * | | |11 = PWM compare down point output Toggle. + * | | |Note1: PWM can control output level when PWM counter down count to CMPDAT. + * | | |Note2: In complementary mode, CMPDCTL1, 3, 5 use as another CMPDCTL for channel 0, 2, 4. + * |[21:20] |CMPDCTL2 |PWM Compare Down Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare down point output Low. + * | | |10 = PWM compare down point output High. + * | | |11 = PWM compare down point output Toggle. + * | | |Note1: PWM can control output level when PWM counter down count to CMPDAT. + * | | |Note2: In complementary mode, CMPDCTL1, 3, 5 use as another CMPDCTL for channel 0, 2, 4. + * |[23:22] |CMPDCTL3 |PWM Compare Down Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare down point output Low. + * | | |10 = PWM compare down point output High. + * | | |11 = PWM compare down point output Toggle. + * | | |Note1: PWM can control output level when PWM counter down count to CMPDAT. + * | | |Note2: In complementary mode, CMPDCTL1, 3, 5 use as another CMPDCTL for channel 0, 2, 4. + * |[25:24] |CMPDCTL4 |PWM Compare Down Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare down point output Low. + * | | |10 = PWM compare down point output High. + * | | |11 = PWM compare down point output Toggle. + * | | |Note1: PWM can control output level when PWM counter down count to CMPDAT. + * | | |Note2: In complementary mode, CMPDCTL1, 3, 5 use as another CMPDCTL for channel 0, 2, 4. + * |[27:26] |CMPDCTL5 |PWM Compare Down Point Control + * | | |Each bit n controls the corresponding PWM channel n. + * | | |00 = Do nothing. + * | | |01 = PWM compare down point output Low. + * | | |10 = PWM compare down point output High. + * | | |11 = PWM compare down point output Toggle. + * | | |Note1: PWM can control output level when PWM counter down count to CMPDAT. + * | | |Note2: In complementary mode, CMPDCTL1, 3, 5 use as another CMPDCTL for channel 0, 2, 4. + * @var PWM_T::MSKEN + * Offset: 0xB8 PWM Mask Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |MSKENn |PWM Mask Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |The PWM output signal will be masked when this bit is enabled. + * | | |The corresponding PWM channel n will output MSKDATn (PWM_MSK[5:0]) data. + * | | |0 = PWM output signal is non-masked. + * | | |1 = PWM output signal is masked and output MSKDATn data. + * @var PWM_T::MSK + * Offset: 0xBC PWM Mask Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |MSKDATn |PWM Mask Data Bit + * | | |This data bit control the state of PWMn output pin, if corresponding mask function is enabled. + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = Output logic low to PWM channel n. + * | | |1 = Output logic high to PWM channel n. + * @var PWM_T::BNF + * Offset: 0xC0 PWM Brake Noise Filter Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BRK0FEN |PWM Brake 0 Noise Filter Enable Bit + * | | |0 = Noise filter of PWM Brake 0 Disabled. + * | | |1 = Noise filter of PWM Brake 0 Enabled. + * |[3:1] |BRK0FCS |Brake 0 Edge Detector Filter Clock Selection + * | | |000 = Filter clock is HCLK. + * | | |001 = Filter clock is HCLK/2. + * | | |010 = Filter clock is HCLK/4. + * | | |011 = Filter clock is HCLK/8. + * | | |100 = Filter clock is HCLK/16. + * | | |101 = Filter clock is HCLK/32. + * | | |110 = Filter clock is HCLK/64. + * | | |111 = Filter clock is HCLK/128. + * |[6:4] |BRK0FCNT |Brake 0 Edge Detector Filter Count + * | | |The register bits control the Brake0 filter counter to count from 0 to BRK1FCNT. + * |[7] |BRK0PINV |Brake 0 Pin Inverse + * | | |0 = The state of pin PWMx_BRAKE0 is passed to the negative edge detector. + * | | |1 = The inversed state of pin PWMx_BRAKE10 is passed to the negative edge detector. + * |[8] |BRK1FEN |PWM Brake 1 Noise Filter Enable Bit + * | | |0 = Noise filter of PWM Brake 1 Disabled. + * | | |1 = Noise filter of PWM Brake 1 Enabled. + * |[11:9] |BRK1FCS |Brake 1 Edge Detector Filter Clock Selection + * | | |000 = Filter clock = HCLK. + * | | |001 = Filter clock = HCLK/2. + * | | |010 = Filter clock = HCLK/4. + * | | |011 = Filter clock = HCLK/8. + * | | |100 = Filter clock = HCLK/16. + * | | |101 = Filter clock = HCLK/32. + * | | |110 = Filter clock = HCLK/64. + * | | |111 = Filter clock = HCLK/128. + * |[14:12] |BRK1FCNT |Brake 1 Edge Detector Filter Count + * | | |The register bits control the Brake1 filter counter to count from 0 to BRK1FCNT. + * |[15] |BRK1PINV |Brake 1 Pin Inverse + * | | |0 = The state of pin PWMx_BRAKE1 is passed to the negative edge detector. + * | | |1 = The inversed state of pin PWMx_BRAKE1 is passed to the negative edge detector. + * |[16] |BK0SRC |Brake 0 Pin Source Select + * | | |For PWM0 setting: + * | | |0 = Brake 0 pin source come from PWM0_BRAKE0. + * | | |1 = Brake 0 pin source come from PWM1_BRAKE0. + * | | |For PWM1 setting: + * | | |0 = Brake 0 pin source come from PWM1_BRAKE0. + * | | |1 = Brake 0 pin source come from PWM0_BRAKE0. + * |[24] |BK1SRC |Brake 1 Pin Source Select + * | | |For PWM0 setting: + * | | |0 = Brake 1 pin source come from PWM0_BRAKE1. + * | | |1 = Brake 1 pin source come from PWM1_BRAKE1. + * | | |For PWM1 setting: + * | | |0 = Brake 1 pin source come from PWM1_BRAKE1. + * | | |1 = Brake 1 pin source come from PWM0_BRAKE1. + * @var PWM_T::FAILBRK + * Offset: 0xC4 PWM System Fail Brake Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CSSBRKEN |Clock Security System Detection Trigger PWM Brake Function 0 Enable Bit + * | | |0 = Brake Function triggered by CSS detection Disabled. + * | | |1 = Brake Function triggered by CSS detection Enabled. + * |[1] |BODBRKEN |Brown-out Detection Trigger PWM Brake Function 0 Enable Bit + * | | |0 = Brake Function triggered by BOD Disabled. + * | | |1 = Brake Function triggered by BOD Enabled. + * |[3] |CORBRKEN |Core Lockup Detection Trigger PWM Brake Function 0 Enable Bit + * | | |0 = Brake Function triggered by Core lockup detection Disabled. + * | | |1 = Brake Function triggered by Core lockup detection Enabled. + * @var PWM_T::BRKCTL[3] + * Offset: 0xC8 PWM Brake Edge Detect Control Register 0/1,2/3,4/5 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CPO0EBEN |Enable ACMP0_O Digital Output As Edge-detect Brake Source (Write Protect) + * | | |0 = ACMP0_O as edge-detect brake source Disabled. + * | | |1 = ACMP0_O as edge-detect brake source Enabled. + * | | |Note: This register is write protected. Refer to SYS_REGLCTL register. + * |[1] |CPO1EBEN |Enable ACMP1_O Digital Output As Edge-detect Brake Source (Write Protect) + * | | |0 = ACMP1_O as edge-detect brake source Disabled. + * | | |1 = ACMP1_O as edge-detect brake source Enabled. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[4] |BRKP0EEN |Enable PWMx_BRAKE0 Pin As Edge-detect Brake Source (Write Protect) + * | | |0 = PWMx_BRAKE0 pin as edge-detect brake source Disabled. + * | | |1 = PWMx_BRAKE0 pin as edge-detect brake source Enabled. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[5] |BRKP1EEN |Enable PWMx_BRAKE1 Pin As Edge-detect Brake Source (Write Protect) + * | | |0 = PWMx_BRAKE1 pin as edge-detect brake source Disabled. + * | | |1 = PWMx_BRAKE1 pin as edge-detect brake source Enabled. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[7] |SYSEBEN |Enable System Fail As Edge-detect Brake Source (Write Protect) + * | | |0 = System Fail condition as edge-detect brake source Disabled. + * | | |1 = System Fail condition as edge-detect brake source Enabled. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[8] |CPO0LBEN |Enable ACMP0_O Digital Output As Level-detect Brake Source (Write Protect) + * | | |0 = ACMP0_O as level-detect brake source Disabled. + * | | |1 = ACMP0_O as level-detect brake source Enabled. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[9] |CPO1LBEN |Enable ACMP1_O Digital Output As Level-detect Brake Source (Write Protect) + * | | |0 = ACMP1_O as level-detect brake source Disabled. + * | | |1 = ACMP1_O as level-detect brake source Enabled. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[12] |BRKP0LEN |Enable BKP0 Pin As Level-detect Brake Source (Write Protect) + * | | |0 = PWMx_BRAKE0 pin as level-detect brake source Disabled. + * | | |1 = PWMx_BRAKE0 pin as level-detect brake source Enabled. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[13] |BRKP1LEN |Enable BKP1 Pin As Level-detect Brake Source (Write Protect) + * | | |0 = PWMx_BRAKE1 pin as level-detect brake source Disabled. + * | | |1 = PWMx_BRAKE1 pin as level-detect brake source Enabled. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[15] |SYSLBEN |Enable System Fail As Level-detect Brake Source (Write Protect) + * | | |0 = System Fail condition as level-detect brake source Disabled. + * | | |1 = System Fail condition as level-detect brake source Enabled. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[17:16] |BRKAEVEN |PWM Brake Action Select for Even Channel (Write Protect) + * | | |00 = PWMx brake event will not affect even channels output. + * | | |01 = PWM even channel output tri-state when PWMx brake event happened. + * | | |10 = PWM even channel output low level when PWMx brake event happened. + * | | |11 = PWM even channel output high level when PWMx brake event happened. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[19:18] |BRKAODD |PWM Brake Action Select for Odd Channel (Write Protect) + * | | |00 = PWMx brake event will not affect odd channels output. + * | | |01 = PWM odd channel output tri-state when PWMx brake event happened. + * | | |10 = PWM odd channel output low level when PWMx brake event happened. + * | | |11 = PWM odd channel output high level when PWMx brake event happened. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[20] |EADCEBEN |Enable EADC Result Monitor (EADCRM) As Edge-detect Brake Source (Write Protect) + * | | |0 = EADCRM as edge-detect brake source Disabled. + * | | |1 = EADCRM as edge-detect brake source Enabled. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * |[28] |EADCLBEN |Enable EADC Result Monitor (EADCRM) As Level-detect Brake Source (Write Protect) + * | | |0 = EADCRM as level-detect brake source Disabled. + * | | |1 = EADCRM as level-detect brake source Enabled. + * | | |Note: This register is write protected. Refer toSYS_REGLCTL register. + * @var PWM_T::POLCTL + * Offset: 0xD4 PWM Pin Polar Inverse Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |PINVn |PWM PIN Polar Inverse Control + * | | |The register controls polarity state of PWM output + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = PWM output polar inverse Disabled. + * | | |1 = PWM output polar inverse Enabled. + * @var PWM_T::POEN + * Offset: 0xD8 PWM Output Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |POENn |PWM Pin Output Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = PWM pin at tri-state. + * | | |1 = PWM pin in output mode. + * @var PWM_T::SWBRK + * Offset: 0xDC PWM Software Brake Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |BRKETRGn |PWM Edge Brake Software Trigger (Write Only) (Write Protect) + * | | |Each bit n controls the corresponding PWM pair n. + * | | |Write 1 to this bit will trigger Edge brake, and set BRKEIFn to 1 in PWM_INTSTS1 register. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[10:8] |BRKLTRGn |PWM Level Brake Software Trigger (Write Only) (Write Protect) + * | | |Each bit n controls the corresponding PWM pair n. + * | | |Write 1 to this bit will trigger level brake, and set BRKLIFn to 1 in PWM_INTSTS1 register. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * @var PWM_T::INTEN0 + * Offset: 0xE0 PWM Interrupt Enable Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ZIEN0 |PWM Zero Point Interrupt Enable 0 + * | | |0 = Zero point interrupt Disabled. + * | | |1 = Zero point interrupt Enabled. + * | | |Note: Odd channels will read always 0 at complementary mode. + * |[2] |ZIEN2 |PWM Zero Point Interrupt Enable 2 + * | | |0 = Zero point interrupt Disabled. + * | | |1 = Zero point interrupt Enabled. + * | | |Note: Odd channels will read always 0 at complementary mode. + * |[4] |ZIEN4 |PWM Zero Point Interrupt Enable 4 + * | | |0 = Zero point interrupt Disabled. + * | | |1 = Zero point interrupt Enabled. + * | | |Note: Odd channels will read always 0 at complementary mode. + * |[8] |PIEN0 |PWM Period Point Interrupt Enable 0 + * | | |0 = Period point interrupt Disabled. + * | | |1 = Period point interrupt Enabled. + * | | |Note: When counter type is up-down, period point means center point. + * |[10] |PIEN2 |PWM Period Point Interrupt Enable 2 + * | | |0 = Period point interrupt Disabled. + * | | |1 = Period point interrupt Enabled. + * | | |Note: When counter type is up-down, period point means center point. + * |[12] |PIEN4 |PWM Period Point Interrupt Enable 4 + * | | |0 = Period point interrupt Disabled. + * | | |1 = Period point interrupt Enabled. + * | | |Note: When counter type is up-down, period point means center point. + * |[21:16] |CMPUIENn |PWM Compare Up Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = Compare up count interrupt Disabled. + * | | |1 = Compare up count interrupt Enabled. + * | | |Note: In complementary mode, CMPUIEN1, 3, 5 use as another CMPUIEN for channel 0, 2, 4. + * |[29:24] |CMPDIENn |PWM Compare Down Count Interrupt Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = Compare down count interrupt Disabled. + * | | |1 = Compare down count interrupt Enabled. + * | | |Note: In complementary mode, CMPDIEN1, 3, 5 use as another CMPDIEN for channel 0, 2, 4. + * @var PWM_T::INTEN1 + * Offset: 0xE4 PWM Interrupt Enable Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BRKEIEN0_1|PWM Edge-detect Brake Interrupt Enable for Channel0/1 (Write Protect) + * | | |0 = Edge-detect Brake interrupt for channel0/1 Disabled. + * | | |1 = Edge-detect Brake interrupt for channel0/1 Enabled. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[1] |BRKEIEN2_3|PWM Edge-detect Brake Interrupt Enable for Channel2/3 (Write Protect) + * | | |0 = Edge-detect Brake interrupt for channel2/3 Disabled. + * | | |1 = Edge-detect Brake interrupt for channel2/3 Enabled. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[2] |BRKEIEN4_5|PWM Edge-detect Brake Interrupt Enable for Channel4/5 (Write Protect) + * | | |0 = Edge-detect Brake interrupt for channel4/5 Disabled. + * | | |1 = Edge-detect Brake interrupt for channel4/5 Enabled. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[8] |BRKLIEN0_1|PWM Level-detect Brake Interrupt Enable for Channel0/1 (Write Protect) + * | | |0 = Level-detect Brake interrupt for channel0/1 Disabled. + * | | |1 = Level-detect Brake interrupt for channel0/1 Enabled. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[9] |BRKLIEN2_3|PWM Level-detect Brake Interrupt Enable for Channel2/3 (Write Protect) + * | | |0 = Level-detect Brake interrupt for channel2/3 Disabled. + * | | |1 = Level-detect Brake interrupt for channel2/3 Enabled. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[10] |BRKLIEN4_5|PWM Level-detect Brake Interrupt Enable for Channel4/5 (Write Protect) + * | | |0 = Level-detect Brake interrupt for channel4/5 Disabled. + * | | |1 = Level-detect Brake interrupt for channel4/5 Enabled. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * @var PWM_T::INTSTS0 + * Offset: 0xE8 PWM Interrupt Flag Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ZIF0 |PWM Zero Point Interrupt Flag 0 + * | | |This bit is set by hardware when PWM_CH0 counter reaches zero, software can write 1 to clear this bit to zero. + * |[2] |ZIF2 |PWM Zero Point Interrupt Flag 2 + * | | |This bit is set by hardware when PWM_CH2 counter reaches zero, software can write 1 to clear this bit to zero. + * |[4] |ZIF4 |PWM Zero Point Interrupt Flag 4 + * | | |This bit is set by hardware when PWM_CH4 counter reaches zero, software can write 1 to clear this bit to zero. + * |[8] |PIF0 |PWM Period Point Interrupt Flag 0 + * | | |This bit is set by hardware when PWM_CH0 counter reaches PWM_PERIOD0, software can write 1 to clear this bit to zero. + * |[10] |PIF2 |PWM Period Point Interrupt Flag 2 + * | | |This bit is set by hardware when PWM_CH2 counter reaches PWM_PERIOD2, software can write 1 to clear this bit to zero. + * |[12] |PIF4 |PWM Period Point Interrupt Flag 4 + * | | |This bit is set by hardware when PWM_CH4 counter reaches PWM_PERIOD4, software can write 1 to clear this bit to zero. + * |[21:16] |CMPUIFn |PWM Compare Up Count Interrupt Flag + * | | |Flag is set by hardware when PWM counter up count and reaches PWM_CMPDATn, software can clear this bit by writing 1 to it + * | | |Each bit n controls the corresponding PWM channel n. + * | | |Note1: If CMPDAT equal to PERIOD, this flag is not working in up counter type selection. + * | | |Note2: In complementary mode, CMPUIF1, 3, 5 use as another CMPUIF for channel 0, 2, 4. + * |[29:24] |CMPDIFn |PWM Compare Down Count Interrupt Flag + * | | |Each bit n controls the corresponding PWM channel n. + * | | |Flag is set by hardware when PWM counter down count and reaches PWM_CMPDATn, software can clear this bit by writing 1 to it. + * | | |Note1: If CMPDAT equal to PERIOD, this flag is not working in down counter type selection. + * | | |Note2: In complementary mode, CMPDIF1, 3, 5 use as another CMPDIF for channel 0, 2, 4. + * @var PWM_T::INTSTS1 + * Offset: 0xEC PWM Interrupt Flag Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BRKEIF0 |PWM Channel 0 Edge-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 0 edge-detect brake event do not happened. + * | | |1 = When PWM channel 0 edge-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[1] |BRKEIF1 |PWM Channel 1 Edge-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 1 edge-detect brake event do not happened. + * | | |1 = When PWM channel 1 edge-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[2] |BRKEIF2 |PWM Channel 2 Edge-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 2 edge-detect brake event do not happened. + * | | |1 = When PWM channel 2 edge-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[3] |BRKEIF3 |PWM Channel 3 Edge-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 3 edge-detect brake event do not happened. + * | | |1 = When PWM channel 3 edge-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[4] |BRKEIF4 |PWM Channel 4 Edge-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 4 edge-detect brake event do not happened. + * | | |1 = When PWM channel 4 edge-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[5] |BRKEIF5 |PWM Channel 5 Edge-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 5 edge-detect brake event do not happened. + * | | |1 = When PWM channel 5 edge-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[8] |BRKLIF0 |PWM Channel 0 Level-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 0 level-detect brake event do not happened. + * | | |1 = When PWM channel 0 level-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[9] |BRKLIF1 |PWM Channel 1 Level-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 1 level-detect brake event do not happened. + * | | |1 = When PWM channel 1 level-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[10] |BRKLIF2 |PWM Channel 2 Level-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 2 level-detect brake event do not happened. + * | | |1 = When PWM channel 2 level-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[11] |BRKLIF3 |PWM Channel 3 Level-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 3 level-detect brake event do not happened. + * | | |1 = When PWM channel 3 level-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[12] |BRKLIF4 |PWM Channel 4 Level-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 4 level-detect brake event do not happened. + * | | |1 = When PWM channel 4 level-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[13] |BRKLIF5 |PWM Channel 5 Level-detect Brake Interrupt Flag (Write Protect) + * | | |0 = PWM channel 5 level-detect brake event do not happened. + * | | |1 = When PWM channel 5 level-detect brake event happened, this bit is set to 1, writing 1 to clear. + * | | |Note: This register is write protected. Refer toREGWRPROT register. + * |[16] |BRKESTS0 |PWM Channel 0 Edge-detect Brake Status + * | | |0 = PWM channel 0 edge-detect brake state is released. + * | | |1 = When PWM channel 0 edge-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel0 at brake state, writing 1 to clear. + * |[17] |BRKESTS1 |PWM Channel 1 Edge-detect Brake Status + * | | |0 = PWM channel 1 edge-detect brake state is released. + * | | |1 = When PWM channel 1 edge-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel1 at brake state, writing 1 to clear. + * |[18] |BRKESTS2 |PWM Channel 2 Edge-detect Brake Status + * | | |0 = PWM channel 2 edge-detect brake state is released. + * | | |1 = When PWM channel 2 edge-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel2 at brake state, writing 1 to clear. + * |[19] |BRKESTS3 |PWM Channel 3 Edge-detect Brake Status + * | | |0 = PWM channel 3 edge-detect brake state is released. + * | | |1 = When PWM channel 3 edge-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel3 at brake state, writing 1 to clear. + * |[20] |BRKESTS4 |PWM Channel 4 Edge-detect Brake Status + * | | |0 = PWM channel 4 edge-detect brake state is released. + * | | |1 = When PWM channel 4 edge-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel4 at brake state, writing 1 to clear. + * |[21] |BRKESTS5 |PWM Channel 5 Edge-detect Brake Status + * | | |0 = PWM channel 5 edge-detect brake state is released. + * | | |1 = When PWM channel 5 edge-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel5 at brake state, writing 1 to clear. + * |[24] |BRKLSTS0 |PWM Channel 0 Level-detect Brake Status (Read Only) + * | | |0 = PWM channel 0 level-detect brake state is released. + * | | |1 = When PWM channel 0 level-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel0 at brake state. + * | | |Note: This bit is read only and auto cleared by hardware + * | | |When enabled brake source return to high level, PWM will release brake state until current PWM period finished + * | | |The PWM waveform will start output from next full PWM period. + * |[25] |BRKLSTS1 |PWM Channel 1 Level-detect Brake Status (Read Only) + * | | |0 = PWM channel 1 level-detect brake state is released. + * | | |1 = When PWM channel 1 level-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel1 at brake state. + * | | |Note: This bit is read only and auto cleared by hardware + * | | |When enabled brake source return to high level, PWM will release brake state until current PWM period finished + * | | |The PWM waveform will start output from next full PWM period. + * |[26] |BRKLSTS2 |PWM Channel 2 Level-detect Brake Status (Read Only) + * | | |0 = PWM channel 2 level-detect brake state is released. + * | | |1 = When PWM channel 2 level-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel2 at brake state. + * | | |Note: This bit is read only and auto cleared by hardware + * | | |When enabled brake source return to high level, PWM will release brake state until current PWM period finished + * | | |The PWM waveform will start output from next full PWM period. + * |[27] |BRKLSTS3 |PWM Channel 3 Level-detect Brake Status (Read Only) + * | | |0 = PWM channel 3 level-detect brake state is released. + * | | |1 = When PWM channel 3 level-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel3 at brake state. + * | | |Note: This bit is read only and auto cleared by hardware + * | | |When enabled brake source return to high level, PWM will release brake state until current PWM period finished + * | | |The PWM waveform will start output from next full PWM period. + * |[28] |BRKLSTS4 |PWM Channel 4 Level-detect Brake Status (Read Only) + * | | |0 = PWM channel 4 level-detect brake state is released. + * | | |1 = When PWM channel 4 level-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel4 at brake state. + * | | |Note: This bit is read only and auto cleared by hardware + * | | |When enabled brake source return to high level, PWM will release brake state until current PWM period finished + * | | |The PWM waveform will start output from next full PWM period. + * |[29] |BRKLSTS5 |PWM Channel 5 Level-detect Brake Status (Read Only) + * | | |0 = PWM channel 5 level-detect brake state is released. + * | | |1 = When PWM channel 5 level-detect brake detects a falling edge of any enabled brake source; this flag will be set to indicate the PWM channel5 at brake state. + * | | |Note: This bit is read only and auto cleared by hardware + * | | |When enabled brake source return to high level, PWM will release brake state until current PWM period finished + * | | |The PWM waveform will start output from next full PWM period. + * @var PWM_T::ADCTS0 + * Offset: 0xF8 PWM Trigger ADC Source Select Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |TRGSEL0 |PWM_CH0 Trigger ADC Source Select + * | | |0000 = PWM_CH0 zero point. + * | | |0001 = PWM_CH0 period point. + * | | |0010 = PWM_CH0 zero or period point. + * | | |0011 = PWM_CH0 up-count CMPDAT point. + * | | |0100 = PWM_CH0 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = PWM_CH1 up-count CMPDAT point. + * | | |1001 = PWM_CH1 down-count CMPDAT point. + * | | |Others = reserved. + * |[7] |TRGEN0 |PWM_CH0 Trigger ADC Enable Bit + * |[11:8] |TRGSEL1 |PWM_CH1 Trigger ADC Source Select + * | | |0000 = PWM_CH0 zero point. + * | | |0001 = PWM_CH0 period point. + * | | |0010 = PWM_CH0 zero or period point. + * | | |0011 = PWM_CH0 up-count CMPDAT point. + * | | |0100 = PWM_CH0 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = PWM_CH1 up-count CMPDAT point. + * | | |1001 = PWM_CH1 down-count CMPDAT point. + * | | |Others = reserved. + * |[15] |TRGEN1 |PWM_CH1 Trigger ADC Enable Bit + * |[19:16] |TRGSEL2 |PWM_CH2 Trigger ADC Source Select + * | | |0000 = PWM_CH2 zero point. + * | | |0001 = PWM_CH2 period point. + * | | |0010 = PWM_CH2 zero or period point. + * | | |0011 = PWM_CH2 up-count CMPDAT point. + * | | |0100 = PWM_CH2 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = PWM_CH3 up-count CMPDAT point. + * | | |1001 = PWM_CH3 down-count CMPDAT point. + * | | |Others = reserved. + * |[23] |TRGEN2 |PWM_CH2 Trigger ADC Enable Bit + * |[27:24] |TRGSEL3 |PWM_CH3 Trigger ADC Source Select + * | | |0000 = PWM_CH2 zero point. + * | | |0001 = PWM_CH2 period point. + * | | |0010 = PWM_CH2 zero or period point. + * | | |0011 = PWM_CH2 up-count CMPDAT point. + * | | |0100 = PWM_CH2 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = PWM_CH3 up-count CMPDAT point. + * | | |1001 = PWM_CH3 down-count CMPDAT point. + * | | |Others = reserved. + * |[31] |TRGEN3 |PWM_CH3 Trigger ADC Enable Bit + * @var PWM_T::ADCTS1 + * Offset: 0xFC PWM Trigger ADC Source Select Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |TRGSEL4 |PWM_CH4 Trigger ADC Source Select + * | | |0000 = PWM_CH4 zero point. + * | | |0001 = PWM_CH4 period point. + * | | |0010 = PWM_CH4 zero or period point. + * | | |0011 = PWM_CH4 up-count CMPDAT point. + * | | |0100 = PWM_CH4 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = PWM_CH5 up-count CMPDAT point. + * | | |1001 = PWM_CH5 down-count CMPDAT point. + * | | |Others = reserved. + * |[7] |TRGEN4 |PWM_CH4 Trigger ADC Enable Bit + * |[11:8] |TRGSEL5 |PWM_CH5 Trigger ADC Source Select + * | | |0000 = PWM_CH4 zero point. + * | | |0001 = PWM_CH4 period point. + * | | |0010 = PWM_CH4 zero or period point. + * | | |0011 = PWM_CH4 up-count CMPDAT point. + * | | |0100 = PWM_CH4 down-count CMPDAT point. + * | | |0101 = Reserved. + * | | |0110 = Reserved. + * | | |0111 = Reserved. + * | | |1000 = PWM_CH5 up-count CMPDAT point. + * | | |1001 = PWM_CH5 down-count CMPDAT point. + * | | |Others = reserved. + * |[15] |TRGEN5 |PWM_CH5 Trigger ADC Enable Bit + * @var PWM_T::SSCTL + * Offset: 0x110 PWM Synchronous Start Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SSEN0 |PWM Synchronous Start Function Enable 0 + * | | |When synchronous start function is enabled, the PWM_CH0 counter enable bit (CNTEN0) can be enabled by writing PWM synchronous start trigger bit (CNTSEN). + * | | |0 = PWM synchronous start function Disabled. + * | | |1 = PWM synchronous start function Enabled. + * |[2] |SSEN2 |PWM Synchronous Start Function Enable 2 + * | | |When synchronous start function is enabled, the PWM_CH2 counter enable bit (CNTEN2) can be enabled by writing PWM synchronous start trigger bit (CNTSEN). + * | | |0 = PWM synchronous start function Disabled. + * | | |1 = PWM synchronous start function Enabled. + * |[4] |SSEN4 |PWM Synchronous Start Function Enable 4 + * | | |When synchronous start function is enabled, the PWM_CH4 counter enable bit (CNTEN4) can be enabled by writing PWM synchronous start trigger bit (CNTSEN). + * | | |0 = PWM synchronous start function Disabled. + * | | |1 = PWM synchronous start function Enabled. + * |[9:8] |SSRC |PWM Synchronous Start Source Select + * | | |00 = Synchronous start source come from PWM0. + * | | |01 = Synchronous start source come from PWM1. + * | | |10 = Synchronous start source come from BPWM0. + * | | |11 = Synchronous start source come from BPWM1. + * @var PWM_T::SSTRG + * Offset: 0x114 PWM Synchronous Start Trigger Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CNTSEN |PWM Counter Synchronous Start Enable (Write Only) + * | | |PMW counter synchronous enable function is used to make selected PWM channels (include PWM0_CHx and PWM1_CHx) start counting at the same time. + * | | |Writing this bit to 1 will also set the counter enable bit (CNTENn, n denotes channel 0 to 5) if correlated PWM channel counter synchronous start function is enabled. + * @var PWM_T::STATUS + * Offset: 0x120 PWM Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CNTMAX0 |Time-base Counter 0 Equal to 0xFFFF Latched Status + * | | |0 = indicates the time-base counter never reached its maximum value 0xFFFF. + * | | |1 = indicates the time-base counter reached its maximum value. + * | | |Note: This bit can be clear by software writing 1. + * |[2] |CNTMAX2 |Time-base Counter 2 Equal to 0xFFFF Latched Status + * | | |0 = indicates the time-base counter never reached its maximum value 0xFFFF. + * | | |1 = indicates the time-base counter reached its maximum value. + * | | |Note: This bit can be clear by software writing 1. + * |[4] |CNTMAX4 |Time-base Counter 4 Equal to 0xFFFF Latched Status + * | | |0 = indicates the time-base counter never reached its maximum value 0xFFFF. + * | | |1 = indicates the time-base counter reached its maximum value. + * | | |Note: This bit can be clear by software writing 1. + * |[21:16] |ADCTRGn |ADC Start of Conversion Status + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = Indicates no ADC start of conversion trigger event has occurred. + * | | |1 = Indicates an ADC start of conversion trigger event has occurred. + * | | |Note: This bit can be clear by software writing 1. + * @var PWM_T::CAPINEN + * Offset: 0x200 PWM Capture Input Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |CAPINENn |Capture Input Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = PWM Channel capture input path Disabled. + * | | |The input of PWM channel capture function is always regarded as 0. + * | | |1 = PWM Channel capture input path Enabled. + * | | |The input of PWM channel capture function comes from correlative multifunction pin. + * @var PWM_T::CAPCTL + * Offset: 0x204 PWM Capture Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |CAPENn |Capture Function Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = Capture function Disabled. RCAPDAT/FCAPDAT register will not be updated. + * | | |1 = Capture function Enabled + * | | |Capture latched the PWM counter value when detected rising or falling edge of input signal and saved to RCAPDAT (Rising latch) and FCAPDAT (Falling latch). + * |[13:8] |CAPINVn |Capture Inverter Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = Capture source inverter Disabled. + * | | |1 = Capture source inverter Enabled. Reverse the input signal from GPIO. + * |[21:16] |RCRLDENn |Rising Capture Reload Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = Rising capture reload counter Disabled. + * | | |1 = Rising capture reload counter Enabled. + * |[29:24] |FCRLDENn |Falling Capture Reload Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = Falling capture reload counter Disabled. + * | | |1 = Falling capture reload counter Enabled. + * @var PWM_T::CAPSTS + * Offset: 0x208 PWM Capture Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |CRLIFOVn |Capture Rising Latch Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if rising latch happened when the corresponding CRLIF is 1. + * | | |Each bit n controls the corresponding PWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CRLIF. + * |[13:8] |CFLIFOVn |Capture Falling Latch Interrupt Flag Overrun Status (Read Only) + * | | |This flag indicates if falling latch happened when the corresponding CFLIF is 1. + * | | |Each bit n controls the corresponding PWM channel n. + * | | |Note: This bit will be cleared automatically when user clear corresponding CFLIF. + * @var PWM_T::RCAPDAT0 + * Offset: 0x20C PWM Rising Capture Data Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RCAPDAT |PWM Rising Capture Data Register (Read Only) + * | | |When rising capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::FCAPDAT0 + * Offset: 0x210 PWM Falling Capture Data Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |FCAPDAT |PWM Falling Capture Data Register (Read Only) + * | | |When falling capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::RCAPDAT1 + * Offset: 0x214 PWM Rising Capture Data Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RCAPDAT |PWM Rising Capture Data Register (Read Only) + * | | |When rising capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::FCAPDAT1 + * Offset: 0x218 PWM Falling Capture Data Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |FCAPDAT |PWM Falling Capture Data Register (Read Only) + * | | |When falling capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::RCAPDAT2 + * Offset: 0x21C PWM Rising Capture Data Register 2 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RCAPDAT |PWM Rising Capture Data Register (Read Only) + * | | |When rising capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::FCAPDAT2 + * Offset: 0x220 PWM Falling Capture Data Register 2 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |FCAPDAT |PWM Falling Capture Data Register (Read Only) + * | | |When falling capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::RCAPDAT3 + * Offset: 0x224 PWM Rising Capture Data Register 3 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RCAPDAT |PWM Rising Capture Data Register (Read Only) + * | | |When rising capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::FCAPDAT3 + * Offset: 0x228 PWM Falling Capture Data Register 3 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |FCAPDAT |PWM Falling Capture Data Register (Read Only) + * | | |When falling capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::RCAPDAT4 + * Offset: 0x22C PWM Rising Capture Data Register 4 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RCAPDAT |PWM Rising Capture Data Register (Read Only) + * | | |When rising capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::FCAPDAT4 + * Offset: 0x230 PWM Falling Capture Data Register 4 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |FCAPDAT |PWM Falling Capture Data Register (Read Only) + * | | |When falling capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::RCAPDAT5 + * Offset: 0x234 PWM Rising Capture Data Register 5 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RCAPDAT |PWM Rising Capture Data Register (Read Only) + * | | |When rising capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::FCAPDAT5 + * Offset: 0x238 PWM Falling Capture Data Register 5 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |FCAPDAT |PWM Falling Capture Data Register (Read Only) + * | | |When falling capture condition happened, the PWM counter value will be saved in this register. + * @var PWM_T::PDMACTL + * Offset: 0x23C PWM PDMA Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CHEN0_1 |Channel 0/1 PDMA Enable Bit + * | | |0 = Channel 0/1 PDMA function Disabled. + * | | |1 = Channel 0/1 PDMA function Enabled for the channel 0/1 captured data and transfer to memory. + * |[2:1] |CAPMOD0_1 |Select PWM_RCAPDAT0/1 or PWM_FCAPDAT0/1 to Do PDMA Transfer + * | | |00 = Reserved. + * | | |01 = PWM_RCAPDAT0/1. + * | | |10 = PWM_FCAPDAT0/1. + * | | |11 = Both PWM_RCAPDAT0/1 and PWM_FCAPDAT0/1. + * |[3] |CAPORD0_1 |Capture Channel 0/1 Rising/Falling Order + * | | |Set this bit to determine whether the PWM_RCAPDAT0/1 or PWM_FCAPDAT0/1 is the first captured data transferred to memory through PDMA when CAPMOD0_1 =11. + * | | |0 = PWM_FCAPDAT0/1 is the first captured data to memory. + * | | |1 = PWM_RCAPDAT0/1 is the first captured data to memory. + * |[4] |CHSEL0_1 |Select Channel 0/1 to Do PDMA Transfer + * | | |0 = Channel 0. + * | | |1 = Channel 1. + * |[8] |CHEN2_3 |Channel 2/3 PDMA Enable Bit + * | | |0 = Channel 2/3 PDMA function Disabled. + * | | |1 = Channel 2/3 PDMA function Enabled for the channel 2/3 captured data and transfer to memory. + * |[10:9] |CAPMOD2_3 |Select PWM_RCAPDAT2/3 or PWM_FCAODAT2/3 to Do PDMA Transfer + * | | |00 = Reserved. + * | | |01 = PWM_RCAPDAT2/3. + * | | |10 = PWM_FCAPDAT2/3. + * | | |11 = Both PWM_RCAPDAT2/3 and PWM_FCAPDAT2/3. + * |[11] |CAPORD2_3 |Capture Channel 2/3 Rising/Falling Order + * | | |Set this bit to determine whether the PWM_RCAPDAT2/3 or PWM_FCAPDAT2/3 is the first captured data transferred to memory through PDMA when CAPMOD2_3 =11. + * | | |0 = PWM_FCAPDAT2/3 is the first captured data to memory. + * | | |1 = PWM_RCAPDAT2/3 is the first captured data to memory. + * |[12] |CHSEL2_3 |Select Channel 2/3 to Do PDMA Transfer + * | | |0 = Channel 2. + * | | |1 = Channel 3. + * |[16] |CHEN4_5 |Channel 4/5 PDMA Enable Bit + * | | |0 = Channel 4/5 PDMA function Disabled. + * | | |1 = Channel 4/5 PDMA function Enabled for the channel 4/5 captured data and transfer to memory. + * |[18:17] |CAPMOD4_5 |Select PWM_RCAPDAT4/5 or PWM_FCAPDAT4/5 to Do PDMA Transfer + * | | |00 = Reserved. + * | | |01 = PWM_RCAPDAT4/5. + * | | |10 = PWM_FCAPDAT4/5. + * | | |11 = Both PWM_RCAPDAT4/5 and PWM_FCAPDAT4/5. + * |[19] |CAPORD4_5 |Capture Channel 4/5 Rising/Falling Order + * | | |Set this bit to determine whether the PWM_RCAPDAT4/5 or PWM_FCAPDAT4/5 is the first captured data transferred to memory through PDMA when CAPMOD4_5 =11. + * | | |0 = PWM_FCAPDAT4/5 is the first captured data to memory. + * | | |1 = PWM_RCAPDAT4/5 is the first captured data to memory. + * |[20] |CHSEL4_5 |Select Channel 4/5 to Do PDMA Transfer + * | | |0 = Channel 4. + * | | |1 = Channel 5. + * @var PWM_T::PDMACAP0_1 + * Offset: 0x240 PWM Capture Channel 01 PDMA Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |CAPBUF |PWM Capture PDMA Register (Read Only) + * | | |This register is use as a buffer to transfer PWM capture rising or falling data to memory by PDMA. + * @var PWM_T::PDMACAP2_3 + * Offset: 0x244 PWM Capture Channel 23 PDMA Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |CAPBUF |PWM Capture PDMA Register (Read Only) + * | | |This register is use as a buffer to transfer PWM capture rising or falling data to memory by PDMA. + * @var PWM_T::PDMACAP4_5 + * Offset: 0x248 PWM Capture Channel 45 PDMA Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |CAPBUF |PWM Capture PDMA Register (Read Only) + * | | |This register is use as a buffer to transfer PWM capture rising or falling data to memory by PDMA. + * @var PWM_T::CAPIEN + * Offset: 0x250 PWM Capture Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |CAPRIENn |PWM Capture Rising Latch Interrupt Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = Capture rising edge latch interrupt Disabled. + * | | |1 = Capture rising edge latch interrupt Enabled. + * |[13:8] |CAPFIENn |PWM Capture Falling Latch Interrupt Enable Bits + * | | |Each bit n controls the corresponding PWM channel n. + * | | |0 = Capture falling edge latch interrupt Disabled. + * | | |1 = Capture falling edge latch interrupt Enabled. + * @var PWM_T::CAPIF + * Offset: 0x254 PWM Capture Interrupt Flag Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |CRLIFn |PWM Capture Rising Latch Interrupt Flag + * | | |This bit is writing 1 to clear. Each bit n controls the corresponding PWM channel n. + * | | |0 = No capture rising latch condition happened. + * | | |1 = Capture rising latch condition happened, this flag will be set to high. + * |[13:8] |CFLIFn |PWM Capture Falling Latch Interrupt Flag + * | | |This bit is writing 1 to clear. Each bit n controls the corresponding PWM channel n. + * | | |0 = No capture falling latch condition happened. + * | | |1 = Capture falling latch condition happened, this flag will be set to high. + * @var PWM_T::PBUF + * Offset: 0x304~0x318 PWM PERIOD0/2/4 Buffer + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |PBUF |PWM Period Register Buffer (Read Only) + * | | |Used as PERIOD active register. + * @var PWM_T::CMPBUF + * Offset: 0x31C~~0x330 PWM CMPDAT0~5 Buffer + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |CMPBUF |PWM Comparator Register Buffer (Read Only) + * | | |Used as CMP active register. + */ + __IO uint32_t CTL0; /*!< [0x0000] PWM Control Register 0 */ + __IO uint32_t CTL1; /*!< [0x0004] PWM Control Register 1 */ + __I uint32_t RESERVE0[2]; + __IO uint32_t CLKSRC; /*!< [0x0010] PWM Clock Source Register */ + __IO uint32_t CLKPSC[3]; /*!< [0x0014~0x001c] PWM Clock Pre-scale Register 0_1 ~ 4_5 */ + __IO uint32_t CNTEN; /*!< [0x0020] PWM Counter Enable Register */ + __IO uint32_t CNTCLR; /*!< [0x0024] PWM Clear Counter Register */ + __I uint32_t RESERVE1[2]; + __IO uint32_t PERIOD[6]; /*!< [0x0030~0x0044] PWM Period Register 0/2/4 */ + __I uint32_t RESERVE2[2]; + __IO uint32_t CMPDAT[6]; /*!< [0x0050~0x0064] PWM Comparator Register 0~5 */ + __I uint32_t RESERVE3[2]; + __IO uint32_t DTCTL[3]; /*!< [0x0070~0x0078] PWM Dead-Time Control Register 0_1 */ + __I uint32_t RESERVE4[5]; + __I uint32_t CNT[6]; /*!< [0x0090~0x00a4] PWM Counter Register 0/2/4 */ + __I uint32_t RESERVE5[2]; + __IO uint32_t WGCTL0; /*!< [0x00b0] PWM Generation Register 0 */ + __IO uint32_t WGCTL1; /*!< [0x00b4] PWM Generation Register 1 */ + __IO uint32_t MSKEN; /*!< [0x00b8] PWM Mask Enable Register */ + __IO uint32_t MSK; /*!< [0x00bc] PWM Mask Data Register */ + __IO uint32_t BNF; /*!< [0x00c0] PWM Brake Noise Filter Register */ + __IO uint32_t FAILBRK; /*!< [0x00c4] PWM System Fail Brake Control Register */ + __IO uint32_t BRKCTL[3]; /*!< [0x00c8~0x00d0] PWM Brake Edge Detect Control Register 0_5 */ + __IO uint32_t POLCTL; /*!< [0x00d4] PWM Pin Polar Inverse Register */ + __IO uint32_t POEN; /*!< [0x00d8] PWM Output Enable Register */ + __O uint32_t SWBRK; /*!< [0x00dc] PWM Software Brake Control Register */ + __IO uint32_t INTEN0; /*!< [0x00e0] PWM Interrupt Enable Register 0 */ + __IO uint32_t INTEN1; /*!< [0x00e4] PWM Interrupt Enable Register 1 */ + __IO uint32_t INTSTS0; /*!< [0x00e8] PWM Interrupt Flag Register 0 */ + __IO uint32_t INTSTS1; /*!< [0x00ec] PWM Interrupt Flag Register 1 */ + __I uint32_t RESERVE6[2]; + __IO uint32_t ADCTS0; /*!< [0x00f8] PWM Trigger ADC Source Select Register 0 */ + __IO uint32_t ADCTS1; /*!< [0x00fc] PWM Trigger ADC Source Select Register 1 */ + __I uint32_t RESERVE7[4]; + __IO uint32_t SSCTL; /*!< [0x0110] PWM Synchronous Start Control Register */ + __O uint32_t SSTRG; /*!< [0x0114] PWM Synchronous Start Trigger Register */ + __I uint32_t RESERVE8[2]; + __IO uint32_t STATUS; /*!< [0x0120] PWM Status Register */ + __I uint32_t RESERVE9[55]; + __IO uint32_t CAPINEN; /*!< [0x0200] PWM Capture Input Enable Register */ + __IO uint32_t CAPCTL; /*!< [0x0204] PWM Capture Control Register */ + __I uint32_t CAPSTS; /*!< [0x0208] PWM Capture Status Register */ + __I uint32_t RCAPDAT0; /*!< [0x020c] PWM Rising Capture Data Register 0 */ + __I uint32_t FCAPDAT0; /*!< [0x0210] PWM Falling Capture Data Register 0 */ + __I uint32_t RCAPDAT1; /*!< [0x0214] PWM Rising Capture Data Register 1 */ + __I uint32_t FCAPDAT1; /*!< [0x0218] PWM Falling Capture Data Register 1 */ + __I uint32_t RCAPDAT2; /*!< [0x021c] PWM Rising Capture Data Register 2 */ + __I uint32_t FCAPDAT2; /*!< [0x0220] PWM Falling Capture Data Register 2 */ + __I uint32_t RCAPDAT3; /*!< [0x0224] PWM Rising Capture Data Register 3 */ + __I uint32_t FCAPDAT3; /*!< [0x0228] PWM Falling Capture Data Register 3 */ + __I uint32_t RCAPDAT4; /*!< [0x022c] PWM Rising Capture Data Register 4 */ + __I uint32_t FCAPDAT4; /*!< [0x0230] PWM Falling Capture Data Register 4 */ + __I uint32_t RCAPDAT5; /*!< [0x0234] PWM Rising Capture Data Register 5 */ + __I uint32_t FCAPDAT5; /*!< [0x0238] PWM Falling Capture Data Register 5 */ + __IO uint32_t PDMACTL; /*!< [0x023c] PWM PDMA Control Register */ + __I uint32_t PDMACAP0_1; /*!< [0x0240] PWM Capture Channel 01 PDMA Register */ + __I uint32_t PDMACAP2_3; /*!< [0x0244] PWM Capture Channel 23 PDMA Register */ + __I uint32_t PDMACAP4_5; /*!< [0x0248] PWM Capture Channel 45 PDMA Register */ + __I uint32_t RESERVE10[1]; + __IO uint32_t CAPIEN; /*!< [0x0250] PWM Capture Interrupt Enable Register */ + __IO uint32_t CAPIF; /*!< [0x0254] PWM Capture Interrupt Flag Register */ + __I uint32_t RESERVE11[43]; + __I uint32_t PBUF[6]; /*!< [0x0304~0x0318] PWM PERIOD0/2/4 Buffer */ + __I uint32_t CMPBUF[6]; /*!< [0x031c~0x0330] PWM CMPDAT0~5 Buffer */ +} PWM_T; + +/** + @addtogroup PWM_CONST PWM Bit Field Definition + Constant Definitions for PWM Controller +@{ */ + +#define PWM_CTL0_CTRLD0_Pos (0) /*!< PWM_T::CTL0: CTRLD0 Position */ +#define PWM_CTL0_CTRLD0_Msk (0x1ul << PWM_CTL0_CTRLD0_Pos) /*!< PWM_T::CTL0: CTRLD0 Mask */ + +#define PWM_CTL0_CTRLD1_Pos (1) /*!< PWM_T::CTL0: CTRLD1 Position */ +#define PWM_CTL0_CTRLD1_Msk (0x1ul << PWM_CTL0_CTRLD1_Pos) /*!< PWM_T::CTL0: CTRLD1 Mask */ + +#define PWM_CTL0_CTRLD2_Pos (2) /*!< PWM_T::CTL0: CTRLD2 Position */ +#define PWM_CTL0_CTRLD2_Msk (0x1ul << PWM_CTL0_CTRLD2_Pos) /*!< PWM_T::CTL0: CTRLD2 Mask */ + +#define PWM_CTL0_CTRLD3_Pos (3) /*!< PWM_T::CTL0: CTRLD3 Position */ +#define PWM_CTL0_CTRLD3_Msk (0x1ul << PWM_CTL0_CTRLD3_Pos) /*!< PWM_T::CTL0: CTRLD3 Mask */ + +#define PWM_CTL0_CTRLD4_Pos (4) /*!< PWM_T::CTL0: CTRLD4 Position */ +#define PWM_CTL0_CTRLD4_Msk (0x1ul << PWM_CTL0_CTRLD4_Pos) /*!< PWM_T::CTL0: CTRLD4 Mask */ + +#define PWM_CTL0_CTRLD5_Pos (5) /*!< PWM_T::CTL0: CTRLD5 Position */ +#define PWM_CTL0_CTRLD5_Msk (0x1ul << PWM_CTL0_CTRLD5_Pos) /*!< PWM_T::CTL0: CTRLD5 Mask */ + +#define PWM_CTL0_IMMLDEN0_Pos (16) /*!< PWM_T::CTL0: IMMLDEN0 Position */ +#define PWM_CTL0_IMMLDEN0_Msk (0x1ul << PWM_CTL0_IMMLDEN0_Pos) /*!< PWM_T::CTL0: IMMLDEN0 Mask */ + +#define PWM_CTL0_IMMLDEN1_Pos (17) /*!< PWM_T::CTL0: IMMLDEN1 Position */ +#define PWM_CTL0_IMMLDEN1_Msk (0x1ul << PWM_CTL0_IMMLDEN1_Pos) /*!< PWM_T::CTL0: IMMLDEN1 Mask */ + +#define PWM_CTL0_IMMLDEN2_Pos (18) /*!< PWM_T::CTL0: IMMLDEN2 Position */ +#define PWM_CTL0_IMMLDEN2_Msk (0x1ul << PWM_CTL0_IMMLDEN2_Pos) /*!< PWM_T::CTL0: IMMLDEN2 Mask */ + +#define PWM_CTL0_IMMLDEN3_Pos (19) /*!< PWM_T::CTL0: IMMLDEN3 Position */ +#define PWM_CTL0_IMMLDEN3_Msk (0x1ul << PWM_CTL0_IMMLDEN3_Pos) /*!< PWM_T::CTL0: IMMLDEN3 Mask */ + +#define PWM_CTL0_IMMLDEN4_Pos (20) /*!< PWM_T::CTL0: IMMLDEN4 Position */ +#define PWM_CTL0_IMMLDEN4_Msk (0x1ul << PWM_CTL0_IMMLDEN4_Pos) /*!< PWM_T::CTL0: IMMLDEN4 Mask */ + +#define PWM_CTL0_IMMLDEN5_Pos (21) /*!< PWM_T::CTL0: IMMLDEN5 Position */ +#define PWM_CTL0_IMMLDEN5_Msk (0x1ul << PWM_CTL0_IMMLDEN5_Pos) /*!< PWM_T::CTL0: IMMLDEN5 Mask */ + +#define PWM_CTL0_DBGHALT_Pos (30) /*!< PWM_T::CTL0: DBGHALT Position */ +#define PWM_CTL0_DBGHALT_Msk (0x1ul << PWM_CTL0_DBGHALT_Pos) /*!< PWM_T::CTL0: DBGHALT Mask */ + +#define PWM_CTL0_DBGTRIOFF_Pos (31) /*!< PWM_T::CTL0: DBGTRIOFF Position */ +#define PWM_CTL0_DBGTRIOFF_Msk (0x1ul << PWM_CTL0_DBGTRIOFF_Pos) /*!< PWM_T::CTL0: DBGTRIOFF Mask */ + +#define PWM_CTL1_CNTTYPE0_Pos (0) /*!< PWM_T::CTL1: CNTTYPE0 Position */ +#define PWM_CTL1_CNTTYPE0_Msk (0x3ul << PWM_CTL1_CNTTYPE0_Pos) /*!< PWM_T::CTL1: CNTTYPE0 Mask */ + +#define PWM_CTL1_CNTTYPE2_Pos (4) /*!< PWM_T::CTL1: CNTTYPE2 Position */ +#define PWM_CTL1_CNTTYPE2_Msk (0x3ul << PWM_CTL1_CNTTYPE2_Pos) /*!< PWM_T::CTL1: CNTTYPE2 Mask */ + +#define PWM_CTL1_CNTTYPE4_Pos (8) /*!< PWM_T::CTL1: CNTTYPE4 Position */ +#define PWM_CTL1_CNTTYPE4_Msk (0x3ul << PWM_CTL1_CNTTYPE4_Pos) /*!< PWM_T::CTL1: CNTTYPE4 Mask */ + +#define PWM_CTL1_OUTMODE0_Pos (24) /*!< PWM_T::CTL1: PWMMODE0 Position */ +#define PWM_CTL1_OUTMODE0_Msk (0x1ul << PWM_CTL1_OUTMODE0_Pos) /*!< PWM_T::CTL1: PWMMODE0 Mask */ + +#define PWM_CTL1_OUTMODE2_Pos (25) /*!< PWM_T::CTL1: PWMMODE2 Position */ +#define PWM_CTL1_OUTMODE2_Msk (0x1ul << PWM_CTL1_OUTMODE2_Pos) /*!< PWM_T::CTL1: PWMMODE2 Mask */ + +#define PWM_CTL1_OUTMODE4_Pos (26) /*!< PWM_T::CTL1: PWMMODE4 Position */ +#define PWM_CTL1_OUTMODE4_Msk (0x1ul << PWM_CTL1_OUTMODE4_Pos) /*!< PWM_T::CTL1: PWMMODE4 Mask */ + +#define PWM_CLKSRC_ECLKSRC0_Pos (0) /*!< PWM_T::CLKSRC: ECLKSRC0 Position */ +#define PWM_CLKSRC_ECLKSRC0_Msk (0x7ul << PWM_CLKSRC_ECLKSRC0_Pos) /*!< PWM_T::CLKSRC: ECLKSRC0 Mask */ + +#define PWM_CLKSRC_ECLKSRC2_Pos (8) /*!< PWM_T::CLKSRC: ECLKSRC2 Position */ +#define PWM_CLKSRC_ECLKSRC2_Msk (0x7ul << PWM_CLKSRC_ECLKSRC2_Pos) /*!< PWM_T::CLKSRC: ECLKSRC2 Mask */ + +#define PWM_CLKSRC_ECLKSRC4_Pos (16) /*!< PWM_T::CLKSRC: ECLKSRC4 Position */ +#define PWM_CLKSRC_ECLKSRC4_Msk (0x7ul << PWM_CLKSRC_ECLKSRC4_Pos) /*!< PWM_T::CLKSRC: ECLKSRC4 Mask */ + +#define PWM_CLKPSC0_1_CLKPSC_Pos (0) /*!< PWM_T::CLKPSC: CLKPSC Position */ +#define PWM_CLKPSC0_1_CLKPSC_Msk (0xffful << PWM_CLKPSC0_1_CLKPSC_Pos) /*!< PWM_T::CLKPSC: CLKPSC Mask */ + +#define PWM_CLKPSC2_3_CLKPSC_Pos (0) /*!< PWM_T::CLKPSC: CLKPSC Position */ +#define PWM_CLKPSC2_3_CLKPSC_Msk (0xffful << PWM_CLKPSC2_3_CLKPSC_Pos) /*!< PWM_T::CLKPSC: CLKPSC Mask */ + +#define PWM_CLKPSC4_5_CLKPSC_Pos (0) /*!< PWM_T::CLKPSC: CLKPSC Position */ +#define PWM_CLKPSC4_5_CLKPSC_Msk (0xffful << PWM_CLKPSC4_5_CLKPSC_Pos) /*!< PWM_T::CLKPSC: CLKPSC Mask */ + +#define PWM_CNTEN_CNTEN0_Pos (0) /*!< PWM_T::CNTEN: CNTEN0 Position */ +#define PWM_CNTEN_CNTEN0_Msk (0x1ul << PWM_CNTEN_CNTEN0_Pos) /*!< PWM_T::CNTEN: CNTEN0 Mask */ + +#define PWM_CNTEN_CNTEN2_Pos (2) /*!< PWM_T::CNTEN: CNTEN2 Position */ +#define PWM_CNTEN_CNTEN2_Msk (0x1ul << PWM_CNTEN_CNTEN2_Pos) /*!< PWM_T::CNTEN: CNTEN2 Mask */ + +#define PWM_CNTEN_CNTEN4_Pos (4) /*!< PWM_T::CNTEN: CNTEN4 Position */ +#define PWM_CNTEN_CNTEN4_Msk (0x1ul << PWM_CNTEN_CNTEN4_Pos) /*!< PWM_T::CNTEN: CNTEN4 Mask */ + +#define PWM_CNTCLR_CNTCLR0_Pos (0) /*!< PWM_T::CNTCLR: CNTCLR0 Position */ +#define PWM_CNTCLR_CNTCLR0_Msk (0x1ul << PWM_CNTCLR_CNTCLR0_Pos) /*!< PWM_T::CNTCLR: CNTCLR0 Mask */ + +#define PWM_CNTCLR_CNTCLR2_Pos (2) /*!< PWM_T::CNTCLR: CNTCLR2 Position */ +#define PWM_CNTCLR_CNTCLR2_Msk (0x1ul << PWM_CNTCLR_CNTCLR2_Pos) /*!< PWM_T::CNTCLR: CNTCLR2 Mask */ + +#define PWM_CNTCLR_CNTCLR4_Pos (4) /*!< PWM_T::CNTCLR: CNTCLR4 Position */ +#define PWM_CNTCLR_CNTCLR4_Msk (0x1ul << PWM_CNTCLR_CNTCLR4_Pos) /*!< PWM_T::CNTCLR: CNTCLR4 Mask */ + +#define PWM_PERIOD_PERIOD_Pos (0) /*!< PWM_T::PERIOD: PERIOD Position */ +#define PWM_PERIOD_PERIOD_Msk (0xfffful << PWM_PERIOD_PERIOD_Pos) /*!< PWM_T::PERIOD: PERIOD Mask */ + +#define PWM_CMPDAT_CMP_Pos (0) /*!< PWM_T::CMPDAT: CMP Position */ +#define PWM_CMPDAT_CMP_Msk (0xfffful << PWM_CMPDAT_CMP_Pos) /*!< PWM_T::CMPDAT: CMP Mask */ + +#define PWM_DTCTL_DTCNT_Pos (0) /*!< PWM_T::DTCTL: DTCNT Position */ +#define PWM_DTCTL_DTCNT_Msk (0xffful << PWM_DTCTL_DTCNT_Pos) /*!< PWM_T::DTCTL: DTCNT Mask */ + +#define PWM_DTCTL_DTEN_Pos (16) /*!< PWM_T::DTCTL: DTEN Position */ +#define PWM_DTCTL_DTEN_Msk (0x1ul << PWM_DTCTL_DTEN_Pos) /*!< PWM_T::DTCTL: DTEN Mask */ + +#define PWM_DTCTL_DTCKSEL_Pos (24) /*!< PWM_T::DTCTL: DTCKSEL Position */ +#define PWM_DTCTL_DTCKSEL_Msk (0x1ul << PWM_DTCTL_DTCKSEL_Pos) /*!< PWM_T::DTCTL: DTCKSEL Mask */ + +#define PWM_DTCTL0_1_DTCNT_Pos (0) /*!< PWM_T::DTCTL: DTCNT Position */ +#define PWM_DTCTL0_1_DTCNT_Msk (0xffful << PWM_DTCTL0_1_DTCNT_Pos) /*!< PWM_T::DTCTL: DTCNT Mask */ + +#define PWM_DTCTL0_1_DTEN_Pos (16) /*!< PWM_T::DTCTL: DTEN Position */ +#define PWM_DTCTL0_1_DTEN_Msk (0x1ul << PWM_DTCTL0_1_DTEN_Pos) /*!< PWM_T::DTCTL: DTEN Mask */ + +#define PWM_DTCTL0_1_DTCKSEL_Pos (24) /*!< PWM_T::DTCTL: DTCKSEL Position */ +#define PWM_DTCTL0_1_DTCKSEL_Msk (0x1ul << PWM_DTCTL0_1_DTCKSEL_Pos) /*!< PWM_T::DTCTL: DTCKSEL Mask */ + +#define PWM_DTCTL2_3_DTCNT_Pos (0) /*!< PWM_T::DTCTL: DTCNT Position */ +#define PWM_DTCTL2_3_DTCNT_Msk (0xffful << PWM_DTCTL2_3_DTCNT_Pos) /*!< PWM_T::DTCTL: DTCNT Mask */ + +#define PWM_DTCTL2_3_DTEN_Pos (16) /*!< PWM_T::DTCTL: DTEN Position */ +#define PWM_DTCTL2_3_DTEN_Msk (0x1ul << PWM_DTCTL2_3_DTEN_Pos) /*!< PWM_T::DTCTL: DTEN Mask */ + +#define PWM_DTCTL2_3_DTCKSEL_Pos (24) /*!< PWM_T::DTCTL: DTCKSEL Position */ +#define PWM_DTCTL2_3_DTCKSEL_Msk (0x1ul << PWM_DTCTL2_3_DTCKSEL_Pos) /*!< PWM_T::DTCTL: DTCKSEL Mask */ + +#define PWM_DTCTL4_5_DTCNT_Pos (0) /*!< PWM_T::DTCTL: DTCNT Position */ +#define PWM_DTCTL4_5_DTCNT_Msk (0xffful << PWM_DTCTL4_5_DTCNT_Pos) /*!< PWM_T::DTCTL: DTCNT Mask */ + +#define PWM_DTCTL4_5_DTEN_Pos (16) /*!< PWM_T::DTCTL: DTEN Position */ +#define PWM_DTCTL4_5_DTEN_Msk (0x1ul << PWM_DTCTL4_5_DTEN_Pos) /*!< PWM_T::DTCTL: DTEN Mask */ + +#define PWM_DTCTL4_5_DTCKSEL_Pos (24) /*!< PWM_T::DTCTL: DTCKSEL Position */ +#define PWM_DTCTL4_5_DTCKSEL_Msk (0x1ul << PWM_DTCTL4_5_DTCKSEL_Pos) /*!< PWM_T::DTCTL: DTCKSEL Mask */ + +#define PWM_CNT_CNT_Pos (0) /*!< PWM_T::CNT: CNT Position */ +#define PWM_CNT_CNT_Msk (0xfffful << PWM_CNT_CNT_Pos) /*!< PWM_T::CNT: CNT Mask */ + +#define PWM_CNT_DIRF_Pos (16) /*!< PWM_T::CNT: DIRF Position */ +#define PWM_CNT_DIRF_Msk (0x1ul << PWM_CNT_DIRF_Pos) /*!< PWM_T::CNT: DIRF Mask */ + +#define PWM_WGCTL0_ZPCTL0_Pos (0) /*!< PWM_T::WGCTL0: ZPCTL0 Position */ +#define PWM_WGCTL0_ZPCTL0_Msk (0x3ul << PWM_WGCTL0_ZPCTL0_Pos) /*!< PWM_T::WGCTL0: ZPCTL0 Mask */ + +#define PWM_WGCTL0_ZPCTL1_Pos (2) /*!< PWM_T::WGCTL0: ZPCTL1 Position */ +#define PWM_WGCTL0_ZPCTL1_Msk (0x3ul << PWM_WGCTL0_ZPCTL1_Pos) /*!< PWM_T::WGCTL0: ZPCTL1 Mask */ + +#define PWM_WGCTL0_ZPCTL2_Pos (4) /*!< PWM_T::WGCTL0: ZPCTL2 Position */ +#define PWM_WGCTL0_ZPCTL2_Msk (0x3ul << PWM_WGCTL0_ZPCTL2_Pos) /*!< PWM_T::WGCTL0: ZPCTL2 Mask */ + +#define PWM_WGCTL0_ZPCTL3_Pos (6) /*!< PWM_T::WGCTL0: ZPCTL3 Position */ +#define PWM_WGCTL0_ZPCTL3_Msk (0x3ul << PWM_WGCTL0_ZPCTL3_Pos) /*!< PWM_T::WGCTL0: ZPCTL3 Mask */ + +#define PWM_WGCTL0_ZPCTL4_Pos (8) /*!< PWM_T::WGCTL0: ZPCTL4 Position */ +#define PWM_WGCTL0_ZPCTL4_Msk (0x3ul << PWM_WGCTL0_ZPCTL4_Pos) /*!< PWM_T::WGCTL0: ZPCTL4 Mask */ + +#define PWM_WGCTL0_ZPCTL5_Pos (10) /*!< PWM_T::WGCTL0: ZPCTL5 Position */ +#define PWM_WGCTL0_ZPCTL5_Msk (0x3ul << PWM_WGCTL0_ZPCTL5_Pos) /*!< PWM_T::WGCTL0: ZPCTL5 Mask */ + +#define PWM_WGCTL0_PRDPCTL0_Pos (16) /*!< PWM_T::WGCTL0: PRDPCTL0 Position */ +#define PWM_WGCTL0_PRDPCTL0_Msk (0x3ul << PWM_WGCTL0_PRDPCTL0_Pos) /*!< PWM_T::WGCTL0: PRDPCTL0 Mask */ + +#define PWM_WGCTL0_PRDPCTL1_Pos (18) /*!< PWM_T::WGCTL0: PRDPCTL1 Position */ +#define PWM_WGCTL0_PRDPCTL1_Msk (0x3ul << PWM_WGCTL0_PRDPCTL1_Pos) /*!< PWM_T::WGCTL0: PRDPCTL1 Mask */ + +#define PWM_WGCTL0_PRDPCTL2_Pos (20) /*!< PWM_T::WGCTL0: PRDPCTL2 Position */ +#define PWM_WGCTL0_PRDPCTL2_Msk (0x3ul << PWM_WGCTL0_PRDPCTL2_Pos) /*!< PWM_T::WGCTL0: PRDPCTL2 Mask */ + +#define PWM_WGCTL0_PRDPCTL3_Pos (22) /*!< PWM_T::WGCTL0: PRDPCTL3 Position */ +#define PWM_WGCTL0_PRDPCTL3_Msk (0x3ul << PWM_WGCTL0_PRDPCTL3_Pos) /*!< PWM_T::WGCTL0: PRDPCTL3 Mask */ + +#define PWM_WGCTL0_PRDPCTL4_Pos (24) /*!< PWM_T::WGCTL0: PRDPCTL4 Position */ +#define PWM_WGCTL0_PRDPCTL4_Msk (0x3ul << PWM_WGCTL0_PRDPCTL4_Pos) /*!< PWM_T::WGCTL0: PRDPCTL4 Mask */ + +#define PWM_WGCTL0_PRDPCTL5_Pos (26) /*!< PWM_T::WGCTL0: PRDPCTL5 Position */ +#define PWM_WGCTL0_PRDPCTL5_Msk (0x3ul << PWM_WGCTL0_PRDPCTL5_Pos) /*!< PWM_T::WGCTL0: PRDPCTL5 Mask */ + +#define PWM_WGCTL1_CMPUCTL0_Pos (0) /*!< PWM_T::WGCTL1: CMPUCTL0 Position */ +#define PWM_WGCTL1_CMPUCTL0_Msk (0x3ul << PWM_WGCTL1_CMPUCTL0_Pos) /*!< PWM_T::WGCTL1: CMPUCTL0 Mask */ + +#define PWM_WGCTL1_CMPUCTL1_Pos (2) /*!< PWM_T::WGCTL1: CMPUCTL1 Position */ +#define PWM_WGCTL1_CMPUCTL1_Msk (0x3ul << PWM_WGCTL1_CMPUCTL1_Pos) /*!< PWM_T::WGCTL1: CMPUCTL1 Mask */ + +#define PWM_WGCTL1_CMPUCTL2_Pos (4) /*!< PWM_T::WGCTL1: CMPUCTL2 Position */ +#define PWM_WGCTL1_CMPUCTL2_Msk (0x3ul << PWM_WGCTL1_CMPUCTL2_Pos) /*!< PWM_T::WGCTL1: CMPUCTL2 Mask */ + +#define PWM_WGCTL1_CMPUCTL3_Pos (6) /*!< PWM_T::WGCTL1: CMPUCTL3 Position */ +#define PWM_WGCTL1_CMPUCTL3_Msk (0x3ul << PWM_WGCTL1_CMPUCTL3_Pos) /*!< PWM_T::WGCTL1: CMPUCTL3 Mask */ + +#define PWM_WGCTL1_CMPUCTL4_Pos (8) /*!< PWM_T::WGCTL1: CMPUCTL4 Position */ +#define PWM_WGCTL1_CMPUCTL4_Msk (0x3ul << PWM_WGCTL1_CMPUCTL4_Pos) /*!< PWM_T::WGCTL1: CMPUCTL4 Mask */ + +#define PWM_WGCTL1_CMPUCTL5_Pos (10) /*!< PWM_T::WGCTL1: CMPUCTL5 Position */ +#define PWM_WGCTL1_CMPUCTL5_Msk (0x3ul << PWM_WGCTL1_CMPUCTL5_Pos) /*!< PWM_T::WGCTL1: CMPUCTL5 Mask */ + +#define PWM_WGCTL1_CMPDCTL0_Pos (16) /*!< PWM_T::WGCTL1: CMPDCTL0 Position */ +#define PWM_WGCTL1_CMPDCTL0_Msk (0x3ul << PWM_WGCTL1_CMPDCTL0_Pos) /*!< PWM_T::WGCTL1: CMPDCTL0 Mask */ + +#define PWM_WGCTL1_CMPDCTL1_Pos (18) /*!< PWM_T::WGCTL1: CMPDCTL1 Position */ +#define PWM_WGCTL1_CMPDCTL1_Msk (0x3ul << PWM_WGCTL1_CMPDCTL1_Pos) /*!< PWM_T::WGCTL1: CMPDCTL1 Mask */ + +#define PWM_WGCTL1_CMPDCTL2_Pos (20) /*!< PWM_T::WGCTL1: CMPDCTL2 Position */ +#define PWM_WGCTL1_CMPDCTL2_Msk (0x3ul << PWM_WGCTL1_CMPDCTL2_Pos) /*!< PWM_T::WGCTL1: CMPDCTL2 Mask */ + +#define PWM_WGCTL1_CMPDCTL3_Pos (22) /*!< PWM_T::WGCTL1: CMPDCTL3 Position */ +#define PWM_WGCTL1_CMPDCTL3_Msk (0x3ul << PWM_WGCTL1_CMPDCTL3_Pos) /*!< PWM_T::WGCTL1: CMPDCTL3 Mask */ + +#define PWM_WGCTL1_CMPDCTL4_Pos (24) /*!< PWM_T::WGCTL1: CMPDCTL4 Position */ +#define PWM_WGCTL1_CMPDCTL4_Msk (0x3ul << PWM_WGCTL1_CMPDCTL4_Pos) /*!< PWM_T::WGCTL1: CMPDCTL4 Mask */ + +#define PWM_WGCTL1_CMPDCTL5_Pos (26) /*!< PWM_T::WGCTL1: CMPDCTL5 Position */ +#define PWM_WGCTL1_CMPDCTL5_Msk (0x3ul << PWM_WGCTL1_CMPDCTL5_Pos) /*!< PWM_T::WGCTL1: CMPDCTL5 Mask */ + +#define PWM_MSKEN_MSKEN0_Pos (0) /*!< PWM_T::MSKEN: MSKEN0 Position */ +#define PWM_MSKEN_MSKEN0_Msk (0x1ul << PWM_MSKEN_MSKEN0_Pos) /*!< PWM_T::MSKEN: MSKEN0 Mask */ + +#define PWM_MSKEN_MSKEN1_Pos (1) /*!< PWM_T::MSKEN: MSKEN1 Position */ +#define PWM_MSKEN_MSKEN1_Msk (0x1ul << PWM_MSKEN_MSKEN1_Pos) /*!< PWM_T::MSKEN: MSKEN1 Mask */ + +#define PWM_MSKEN_MSKEN2_Pos (2) /*!< PWM_T::MSKEN: MSKEN2 Position */ +#define PWM_MSKEN_MSKEN2_Msk (0x1ul << PWM_MSKEN_MSKEN2_Pos) /*!< PWM_T::MSKEN: MSKEN2 Mask */ + +#define PWM_MSKEN_MSKEN3_Pos (3) /*!< PWM_T::MSKEN: MSKEN3 Position */ +#define PWM_MSKEN_MSKEN3_Msk (0x1ul << PWM_MSKEN_MSKEN3_Pos) /*!< PWM_T::MSKEN: MSKEN3 Mask */ + +#define PWM_MSKEN_MSKEN4_Pos (4) /*!< PWM_T::MSKEN: MSKEN4 Position */ +#define PWM_MSKEN_MSKEN4_Msk (0x1ul << PWM_MSKEN_MSKEN4_Pos) /*!< PWM_T::MSKEN: MSKEN4 Mask */ + +#define PWM_MSKEN_MSKEN5_Pos (5) /*!< PWM_T::MSKEN: MSKEN5 Position */ +#define PWM_MSKEN_MSKEN5_Msk (0x1ul << PWM_MSKEN_MSKEN5_Pos) /*!< PWM_T::MSKEN: MSKEN5 Mask */ + +#define PWM_MSK_MSKDAT0_Pos (0) /*!< PWM_T::MSK: MSKDAT0 Position */ +#define PWM_MSK_MSKDAT0_Msk (0x1ul << PWM_MSK_MSKDAT0_Pos) /*!< PWM_T::MSK: MSKDAT0 Mask */ + +#define PWM_MSK_MSKDAT1_Pos (1) /*!< PWM_T::MSK: MSKDAT1 Position */ +#define PWM_MSK_MSKDAT1_Msk (0x1ul << PWM_MSK_MSKDAT1_Pos) /*!< PWM_T::MSK: MSKDAT1 Mask */ + +#define PWM_MSK_MSKDAT2_Pos (2) /*!< PWM_T::MSK: MSKDAT2 Position */ +#define PWM_MSK_MSKDAT2_Msk (0x1ul << PWM_MSK_MSKDAT2_Pos) /*!< PWM_T::MSK: MSKDAT2 Mask */ + +#define PWM_MSK_MSKDAT3_Pos (3) /*!< PWM_T::MSK: MSKDAT3 Position */ +#define PWM_MSK_MSKDAT3_Msk (0x1ul << PWM_MSK_MSKDAT3_Pos) /*!< PWM_T::MSK: MSKDAT3 Mask */ + +#define PWM_MSK_MSKDAT4_Pos (4) /*!< PWM_T::MSK: MSKDAT4 Position */ +#define PWM_MSK_MSKDAT4_Msk (0x1ul << PWM_MSK_MSKDAT4_Pos) /*!< PWM_T::MSK: MSKDAT4 Mask */ + +#define PWM_MSK_MSKDAT5_Pos (5) /*!< PWM_T::MSK: MSKDAT5 Position */ +#define PWM_MSK_MSKDAT5_Msk (0x1ul << PWM_MSK_MSKDAT5_Pos) /*!< PWM_T::MSK: MSKDAT5 Mask */ + +#define PWM_BNF_BRK0NFEN_Pos (0) /*!< PWM_T::BNF: BRK0FEN Position */ +#define PWM_BNF_BRK0NFEN_Msk (0x1ul << PWM_BNF_BRK0NFEN_Pos) /*!< PWM_T::BNF: BRK0FEN Mask */ + +#define PWM_BNF_BRK0NFSEL_Pos (1) /*!< PWM_T::BNF: BRK0FCS Position */ +#define PWM_BNF_BRK0NFSEL_Msk (0x7ul << PWM_BNF_BRK0NFSEL_Pos) /*!< PWM_T::BNF: BRK0FCS Mask */ + +#define PWM_BNF_BRK0FCNT_Pos (4) /*!< PWM_T::BNF: BRK0FCNT Position */ +#define PWM_BNF_BRK0FCNT_Msk (0x7ul << PWM_BNF_BRK0FCNT_Pos) /*!< PWM_T::BNF: BRK0FCNT Mask */ + +#define PWM_BNF_BRK0PINV_Pos (7) /*!< PWM_T::BNF: BRK0PINV Position */ +#define PWM_BNF_BRK0PINV_Msk (0x1ul << PWM_BNF_BRK0PINV_Pos) /*!< PWM_T::BNF: BRK0PINV Mask */ + +#define PWM_BNF_BRK1NFEN_Pos (8) /*!< PWM_T::BNF: BRK1FEN Position */ +#define PWM_BNF_BRK1NFEN_Msk (0x1ul << PWM_BNF_BRK1NFEN_Pos) /*!< PWM_T::BNF: BRK1FEN Mask */ + +#define PWM_BNF_BRK1NFSEL_Pos (9) /*!< PWM_T::BNF: BRK1FCS Position */ +#define PWM_BNF_BRK1NFSEL_Msk (0x7ul << PWM_BNF_BRK1NFSEL_Pos) /*!< PWM_T::BNF: BRK1NFSEL Mask */ + +#define PWM_BNF_BRK1FCNT_Pos (12) /*!< PWM_T::BNF: BRK1FCNT Position */ +#define PWM_BNF_BRK1FCNT_Msk (0x7ul << PWM_BNF_BRK1FCNT_Pos) /*!< PWM_T::BNF: BRK1FCNT Mask */ + +#define PWM_BNF_BRK1PINV_Pos (15) /*!< PWM_T::BNF: BRK1PINV Position */ +#define PWM_BNF_BRK1PINV_Msk (0x1ul << PWM_BNF_BRK1PINV_Pos) /*!< PWM_T::BNF: BRK1PINV Mask */ + +#define PWM_BNF_BK0SRC_Pos (16) /*!< PWM_T::BNF: BK0SRC Position */ +#define PWM_BNF_BK0SRC_Msk (0x1ul << PWM_BNF_BK0SRC_Pos) /*!< PWM_T::BNF: BK0SRC Mask */ + +#define PWM_BNF_BK1SRC_Pos (24) /*!< PWM_T::BNF: BK1SRC Position */ +#define PWM_BNF_BK1SRC_Msk (0x1ul << PWM_BNF_BK1SRC_Pos) /*!< PWM_T::BNF: BK1SRC Mask */ + +#define PWM_FAILBRK_CSSBRKEN_Pos (0) /*!< PWM_T::FAILBRK: CSSBRKEN Position */ +#define PWM_FAILBRK_CSSBRKEN_Msk (0x1ul << PWM_FAILBRK_CSSBRKEN_Pos) /*!< PWM_T::FAILBRK: CSSBRKEN Mask */ + +#define PWM_FAILBRK_BODBRKEN_Pos (1) /*!< PWM_T::FAILBRK: BODBRKEN Position */ +#define PWM_FAILBRK_BODBRKEN_Msk (0x1ul << PWM_FAILBRK_BODBRKEN_Pos) /*!< PWM_T::FAILBRK: BODBRKEN Mask */ + +#define PWM_FAILBRK_CORBRKEN_Pos (3) /*!< PWM_T::FAILBRK: CORBRKEN Position */ +#define PWM_FAILBRK_CORBRKEN_Msk (0x1ul << PWM_FAILBRK_CORBRKEN_Pos) /*!< PWM_T::FAILBRK: CORBRKEN Mask */ + +#define PWM_BRKCTL_CPO0EBEN_Pos (0) /*!< PWM_T::BRKCTL: CPO0EBEN Position */ +#define PWM_BRKCTL_CPO0EBEN_Msk (0x1ul << PWM_BRKCTL_CPO0EBEN_Pos) /*!< PWM_T::BRKCTL: CPO0EBEN Mask */ + +#define PWM_BRKCTL_CPO1EBEN_Pos (1) /*!< PWM_T::BRKCTL: CPO1EBEN Position */ +#define PWM_BRKCTL_CPO1EBEN_Msk (0x1ul << PWM_BRKCTL_CPO1EBEN_Pos) /*!< PWM_T::BRKCTL: CPO1EBEN Mask */ + +#define PWM_BRKCTL_BRKP0EEN_Pos (4) /*!< PWM_T::BRKCTL: BRKP0EEN Position */ +#define PWM_BRKCTL_BRKP0EEN_Msk (0x1ul << PWM_BRKCTL_BRKP0EEN_Pos) /*!< PWM_T::BRKCTL: BRKP0EEN Mask */ + +#define PWM_BRKCTL_BRKP1EEN_Pos (5) /*!< PWM_T::BRKCTL: BRKP1EEN Position */ +#define PWM_BRKCTL_BRKP1EEN_Msk (0x1ul << PWM_BRKCTL_BRKP1EEN_Pos) /*!< PWM_T::BRKCTL: BRKP1EEN Mask */ + +#define PWM_BRKCTL_SYSEBEN_Pos (7) /*!< PWM_T::BRKCTL: SYSEBEN Position */ +#define PWM_BRKCTL_SYSEBEN_Msk (0x1ul << PWM_BRKCTL_SYSEBEN_Pos) /*!< PWM_T::BRKCTL: SYSEBEN Mask */ + +#define PWM_BRKCTL_CPO0LBEN_Pos (8) /*!< PWM_T::BRKCTL: CPO0LBEN Position */ +#define PWM_BRKCTL_CPO0LBEN_Msk (0x1ul << PWM_BRKCTL_CPO0LBEN_Pos) /*!< PWM_T::BRKCTL: CPO0LBEN Mask */ + +#define PWM_BRKCTL_CPO1LBEN_Pos (9) /*!< PWM_T::BRKCTL: CPO1LBEN Position */ +#define PWM_BRKCTL_CPO1LBEN_Msk (0x1ul << PWM_BRKCTL_CPO1LBEN_Pos) /*!< PWM_T::BRKCTL: CPO1LBEN Mask */ + +#define PWM_BRKCTL_BRKP0LEN_Pos (12) /*!< PWM_T::BRKCTL: BRKP0LEN Position */ +#define PWM_BRKCTL_BRKP0LEN_Msk (0x1ul << PWM_BRKCTL_BRKP0LEN_Pos) /*!< PWM_T::BRKCTL: BRKP0LEN Mask */ + +#define PWM_BRKCTL_BRKP1LEN_Pos (13) /*!< PWM_T::BRKCTL: BRKP1LEN Position */ +#define PWM_BRKCTL_BRKP1LEN_Msk (0x1ul << PWM_BRKCTL_BRKP1LEN_Pos) /*!< PWM_T::BRKCTL: BRKP1LEN Mask */ + +#define PWM_BRKCTL_SYSLBEN_Pos (15) /*!< PWM_T::BRKCTL: SYSLBEN Position */ +#define PWM_BRKCTL_SYSLBEN_Msk (0x1ul << PWM_BRKCTL_SYSLBEN_Pos) /*!< PWM_T::BRKCTL: SYSLBEN Mask */ + +#define PWM_BRKCTL_BRKAEVEN_Pos (16) /*!< PWM_T::BRKCTL: BRKAEVEN Position */ +#define PWM_BRKCTL_BRKAEVEN_Msk (0x3ul << PWM_BRKCTL_BRKAEVEN_Pos) /*!< PWM_T::BRKCTL: BRKAEVEN Mask */ + +#define PWM_BRKCTL_BRKAODD_Pos (18) /*!< PWM_T::BRKCTL: BRKAODD Position */ +#define PWM_BRKCTL_BRKAODD_Msk (0x3ul << PWM_BRKCTL_BRKAODD_Pos) /*!< PWM_T::BRKCTL: BRKAODD Mask */ + +#define PWM_BRKCTL0_1_CPO0EBEN_Pos (0) /*!< PWM_T::BRKCTL: CPO0EBEN Position */ +#define PWM_BRKCTL0_1_CPO0EBEN_Msk (0x1ul << PWM_BRKCTL0_1_CPO0EBEN_Pos) /*!< PWM_T::BRKCTL: CPO0EBEN Mask */ + +#define PWM_BRKCTL0_1_CPO1EBEN_Pos (1) /*!< PWM_T::BRKCTL: CPO1EBEN Position */ +#define PWM_BRKCTL0_1_CPO1EBEN_Msk (0x1ul << PWM_BRKCTL0_1_CPO1EBEN_Pos) /*!< PWM_T::BRKCTL: CPO1EBEN Mask */ + +#define PWM_BRKCTL0_1_BRKP0EEN_Pos (4) /*!< PWM_T::BRKCTL: BRKP0EEN Position */ +#define PWM_BRKCTL0_1_BRKP0EEN_Msk (0x1ul << PWM_BRKCTL0_1_BRKP0EEN_Pos) /*!< PWM_T::BRKCTL: BRKP0EEN Mask */ + +#define PWM_BRKCTL0_1_BRKP1EEN_Pos (5) /*!< PWM_T::BRKCTL: BRKP1EEN Position */ +#define PWM_BRKCTL0_1_BRKP1EEN_Msk (0x1ul << PWM_BRKCTL0_1_BRKP1EEN_Pos) /*!< PWM_T::BRKCTL: BRKP1EEN Mask */ + +#define PWM_BRKCTL0_1_SYSEBEN_Pos (7) /*!< PWM_T::BRKCTL: SYSEBEN Position */ +#define PWM_BRKCTL0_1_SYSEBEN_Msk (0x1ul << PWM_BRKCTL0_1_SYSEBEN_Pos) /*!< PWM_T::BRKCTL: SYSEBEN Mask */ + +#define PWM_BRKCTL0_1_CPO0LBEN_Pos (8) /*!< PWM_T::BRKCTL: CPO0LBEN Position */ +#define PWM_BRKCTL0_1_CPO0LBEN_Msk (0x1ul << PWM_BRKCTL0_1_CPO0LBEN_Pos) /*!< PWM_T::BRKCTL: CPO0LBEN Mask */ + +#define PWM_BRKCTL0_1_CPO1LBEN_Pos (9) /*!< PWM_T::BRKCTL: CPO1LBEN Position */ +#define PWM_BRKCTL0_1_CPO1LBEN_Msk (0x1ul << PWM_BRKCTL0_1_CPO1LBEN_Pos) /*!< PWM_T::BRKCTL: CPO1LBEN Mask */ + +#define PWM_BRKCTL0_1_BRKP0LEN_Pos (12) /*!< PWM_T::BRKCTL: BRKP0LEN Position */ +#define PWM_BRKCTL0_1_BRKP0LEN_Msk (0x1ul << PWM_BRKCTL0_1_BRKP0LEN_Pos) /*!< PWM_T::BRKCTL: BRKP0LEN Mask */ + +#define PWM_BRKCTL0_1_BRKP1LEN_Pos (13) /*!< PWM_T::BRKCTL: BRKP1LEN Position */ +#define PWM_BRKCTL0_1_BRKP1LEN_Msk (0x1ul << PWM_BRKCTL0_1_BRKP1LEN_Pos) /*!< PWM_T::BRKCTL: BRKP1LEN Mask */ + +#define PWM_BRKCTL0_1_SYSLBEN_Pos (15) /*!< PWM_T::BRKCTL: SYSLBEN Position */ +#define PWM_BRKCTL0_1_SYSLBEN_Msk (0x1ul << PWM_BRKCTL0_1_SYSLBEN_Pos) /*!< PWM_T::BRKCTL: SYSLBEN Mask */ + +#define PWM_BRKCTL0_1_BRKAEVEN_Pos (16) /*!< PWM_T::BRKCTL: BRKAEVEN Position */ +#define PWM_BRKCTL0_1_BRKAEVEN_Msk (0x3ul << PWM_BRKCTL0_1_BRKAEVEN_Pos) /*!< PWM_T::BRKCTL: BRKAEVEN Mask */ + +#define PWM_BRKCTL0_1_BRKAODD_Pos (18) /*!< PWM_T::BRKCTL: BRKAODD Position */ +#define PWM_BRKCTL0_1_BRKAODD_Msk (0x3ul << PWM_BRKCTL0_1_BRKAODD_Pos) /*!< PWM_T::BRKCTL: BRKAODD Mask */ + +#define PWM_BRKCTL2_3_CPO0EBEN_Pos (0) /*!< PWM_T::BRKCTL: CPO0EBEN Position */ +#define PWM_BRKCTL2_3_CPO0EBEN_Msk (0x1ul << PWM_BRKCTL2_3_CPO0EBEN_Pos) /*!< PWM_T::BRKCTL: CPO0EBEN Mask */ + +#define PWM_BRKCTL2_3_CPO1EBEN_Pos (1) /*!< PWM_T::BRKCTL: CPO1EBEN Position */ +#define PWM_BRKCTL2_3_CPO1EBEN_Msk (0x1ul << PWM_BRKCTL2_3_CPO1EBEN_Pos) /*!< PWM_T::BRKCTL: CPO1EBEN Mask */ + +#define PWM_BRKCTL2_3_BRKP0EEN_Pos (4) /*!< PWM_T::BRKCTL: BRKP0EEN Position */ +#define PWM_BRKCTL2_3_BRKP0EEN_Msk (0x1ul << PWM_BRKCTL2_3_BRKP0EEN_Pos) /*!< PWM_T::BRKCTL: BRKP0EEN Mask */ + +#define PWM_BRKCTL2_3_BRKP1EEN_Pos (5) /*!< PWM_T::BRKCTL: BRKP1EEN Position */ +#define PWM_BRKCTL2_3_BRKP1EEN_Msk (0x1ul << PWM_BRKCTL2_3_BRKP1EEN_Pos) /*!< PWM_T::BRKCTL: BRKP1EEN Mask */ + +#define PWM_BRKCTL2_3_SYSEBEN_Pos (7) /*!< PWM_T::BRKCTL: SYSEBEN Position */ +#define PWM_BRKCTL2_3_SYSEBEN_Msk (0x1ul << PWM_BRKCTL2_3_SYSEBEN_Pos) /*!< PWM_T::BRKCTL: SYSEBEN Mask */ + +#define PWM_BRKCTL2_3_CPO0LBEN_Pos (8) /*!< PWM_T::BRKCTL: CPO0LBEN Position */ +#define PWM_BRKCTL2_3_CPO0LBEN_Msk (0x1ul << PWM_BRKCTL2_3_CPO0LBEN_Pos) /*!< PWM_T::BRKCTL: CPO0LBEN Mask */ + +#define PWM_BRKCTL2_3_CPO1LBEN_Pos (9) /*!< PWM_T::BRKCTL: CPO1LBEN Position */ +#define PWM_BRKCTL2_3_CPO1LBEN_Msk (0x1ul << PWM_BRKCTL2_3_CPO1LBEN_Pos) /*!< PWM_T::BRKCTL: CPO1LBEN Mask */ + +#define PWM_BRKCTL2_3_BRKP0LEN_Pos (12) /*!< PWM_T::BRKCTL: BRKP0LEN Position */ +#define PWM_BRKCTL2_3_BRKP0LEN_Msk (0x1ul << PWM_BRKCTL2_3_BRKP0LEN_Pos) /*!< PWM_T::BRKCTL: BRKP0LEN Mask */ + +#define PWM_BRKCTL2_3_BRKP1LEN_Pos (13) /*!< PWM_T::BRKCTL: BRKP1LEN Position */ +#define PWM_BRKCTL2_3_BRKP1LEN_Msk (0x1ul << PWM_BRKCTL2_3_BRKP1LEN_Pos) /*!< PWM_T::BRKCTL: BRKP1LEN Mask */ + +#define PWM_BRKCTL2_3_SYSLBEN_Pos (15) /*!< PWM_T::BRKCTL: SYSLBEN Position */ +#define PWM_BRKCTL2_3_SYSLBEN_Msk (0x1ul << PWM_BRKCTL2_3_SYSLBEN_Pos) /*!< PWM_T::BRKCTL: SYSLBEN Mask */ + +#define PWM_BRKCTL2_3_BRKAEVEN_Pos (16) /*!< PWM_T::BRKCTL: BRKAEVEN Position */ +#define PWM_BRKCTL2_3_BRKAEVEN_Msk (0x3ul << PWM_BRKCTL2_3_BRKAEVEN_Pos) /*!< PWM_T::BRKCTL: BRKAEVEN Mask */ + +#define PWM_BRKCTL2_3_BRKAODD_Pos (18) /*!< PWM_T::BRKCTL: BRKAODD Position */ +#define PWM_BRKCTL2_3_BRKAODD_Msk (0x3ul << PWM_BRKCTL2_3_BRKAODD_Pos) /*!< PWM_T::BRKCTL: BRKAODD Mask */ + +#define PWM_BRKCTL4_5_CPO0EBEN_Pos (0) /*!< PWM_T::BRKCTL: CPO0EBEN Position */ +#define PWM_BRKCTL4_5_CPO0EBEN_Msk (0x1ul << PWM_BRKCTL4_5_CPO0EBEN_Pos) /*!< PWM_T::BRKCTL: CPO0EBEN Mask */ + +#define PWM_BRKCTL4_5_CPO1EBEN_Pos (1) /*!< PWM_T::BRKCTL: CPO1EBEN Position */ +#define PWM_BRKCTL4_5_CPO1EBEN_Msk (0x1ul << PWM_BRKCTL4_5_CPO1EBEN_Pos) /*!< PWM_T::BRKCTL: CPO1EBEN Mask */ + +#define PWM_BRKCTL4_5_BRKP0EEN_Pos (4) /*!< PWM_T::BRKCTL: BRKP0EEN Position */ +#define PWM_BRKCTL4_5_BRKP0EEN_Msk (0x1ul << PWM_BRKCTL4_5_BRKP0EEN_Pos) /*!< PWM_T::BRKCTL: BRKP0EEN Mask */ + +#define PWM_BRKCTL4_5_BRKP1EEN_Pos (5) /*!< PWM_T::BRKCTL: BRKP1EEN Position */ +#define PWM_BRKCTL4_5_BRKP1EEN_Msk (0x1ul << PWM_BRKCTL4_5_BRKP1EEN_Pos) /*!< PWM_T::BRKCTL: BRKP1EEN Mask */ + +#define PWM_BRKCTL4_5_SYSEBEN_Pos (7) /*!< PWM_T::BRKCTL: SYSEBEN Position */ +#define PWM_BRKCTL4_5_SYSEBEN_Msk (0x1ul << PWM_BRKCTL4_5_SYSEBEN_Pos) /*!< PWM_T::BRKCTL: SYSEBEN Mask */ + +#define PWM_BRKCTL4_5_CPO0LBEN_Pos (8) /*!< PWM_T::BRKCTL: CPO0LBEN Position */ +#define PWM_BRKCTL4_5_CPO0LBEN_Msk (0x1ul << PWM_BRKCTL4_5_CPO0LBEN_Pos) /*!< PWM_T::BRKCTL: CPO0LBEN Mask */ + +#define PWM_BRKCTL4_5_CPO1LBEN_Pos (9) /*!< PWM_T::BRKCTL: CPO1LBEN Position */ +#define PWM_BRKCTL4_5_CPO1LBEN_Msk (0x1ul << PWM_BRKCTL4_5_CPO1LBEN_Pos) /*!< PWM_T::BRKCTL: CPO1LBEN Mask */ + +#define PWM_BRKCTL4_5_BRKP0LEN_Pos (12) /*!< PWM_T::BRKCTL: BRKP0LEN Position */ +#define PWM_BRKCTL4_5_BRKP0LEN_Msk (0x1ul << PWM_BRKCTL4_5_BRKP0LEN_Pos) /*!< PWM_T::BRKCTL: BRKP0LEN Mask */ + +#define PWM_BRKCTL4_5_BRKP1LEN_Pos (13) /*!< PWM_T::BRKCTL: BRKP1LEN Position */ +#define PWM_BRKCTL4_5_BRKP1LEN_Msk (0x1ul << PWM_BRKCTL4_5_BRKP1LEN_Pos) /*!< PWM_T::BRKCTL: BRKP1LEN Mask */ + +#define PWM_BRKCTL4_5_SYSLBEN_Pos (15) /*!< PWM_T::BRKCTL: SYSLBEN Position */ +#define PWM_BRKCTL4_5_SYSLBEN_Msk (0x1ul << PWM_BRKCTL4_5_SYSLBEN_Pos) /*!< PWM_T::BRKCTL: SYSLBEN Mask */ + +#define PWM_BRKCTL4_5_BRKAEVEN_Pos (16) /*!< PWM_T::BRKCTL: BRKAEVEN Position */ +#define PWM_BRKCTL4_5_BRKAEVEN_Msk (0x3ul << PWM_BRKCTL4_5_BRKAEVEN_Pos) /*!< PWM_T::BRKCTL: BRKAEVEN Mask */ + +#define PWM_BRKCTL4_5_BRKAODD_Pos (18) /*!< PWM_T::BRKCTL: BRKAODD Position */ +#define PWM_BRKCTL4_5_BRKAODD_Msk (0x3ul << PWM_BRKCTL4_5_BRKAODD_Pos) /*!< PWM_T::BRKCTL: BRKAODD Mask */ + +#define PWM_POLCTL_PINV0_Pos (0) /*!< PWM_T::POLCTL: PINV0 Position */ +#define PWM_POLCTL_PINV0_Msk (0x1ul << PWM_POLCTL_PINV0_Pos) /*!< PWM_T::POLCTL: PINV0 Mask */ + +#define PWM_POLCTL_PINV1_Pos (1) /*!< PWM_T::POLCTL: PINV1 Position */ +#define PWM_POLCTL_PINV1_Msk (0x1ul << PWM_POLCTL_PINV1_Pos) /*!< PWM_T::POLCTL: PINV1 Mask */ + +#define PWM_POLCTL_PINV2_Pos (2) /*!< PWM_T::POLCTL: PINV2 Position */ +#define PWM_POLCTL_PINV2_Msk (0x1ul << PWM_POLCTL_PINV2_Pos) /*!< PWM_T::POLCTL: PINV2 Mask */ + +#define PWM_POLCTL_PINV3_Pos (3) /*!< PWM_T::POLCTL: PINV3 Position */ +#define PWM_POLCTL_PINV3_Msk (0x1ul << PWM_POLCTL_PINV3_Pos) /*!< PWM_T::POLCTL: PINV3 Mask */ + +#define PWM_POLCTL_PINV4_Pos (4) /*!< PWM_T::POLCTL: PINV4 Position */ +#define PWM_POLCTL_PINV4_Msk (0x1ul << PWM_POLCTL_PINV4_Pos) /*!< PWM_T::POLCTL: PINV4 Mask */ + +#define PWM_POLCTL_PINV5_Pos (5) /*!< PWM_T::POLCTL: PINV5 Position */ +#define PWM_POLCTL_PINV5_Msk (0x1ul << PWM_POLCTL_PINV5_Pos) /*!< PWM_T::POLCTL: PINV5 Mask */ + +#define PWM_POEN_POEN0_Pos (0) /*!< PWM_T::POEN: POEN0 Position */ +#define PWM_POEN_POEN0_Msk (0x1ul << PWM_POEN_POEN0_Pos) /*!< PWM_T::POEN: POEN0 Mask */ + +#define PWM_POEN_POEN1_Pos (1) /*!< PWM_T::POEN: POEN1 Position */ +#define PWM_POEN_POEN1_Msk (0x1ul << PWM_POEN_POEN1_Pos) /*!< PWM_T::POEN: POEN1 Mask */ + +#define PWM_POEN_POEN2_Pos (2) /*!< PWM_T::POEN: POEN2 Position */ +#define PWM_POEN_POEN2_Msk (0x1ul << PWM_POEN_POEN2_Pos) /*!< PWM_T::POEN: POEN2 Mask */ + +#define PWM_POEN_POEN3_Pos (3) /*!< PWM_T::POEN: POEN3 Position */ +#define PWM_POEN_POEN3_Msk (0x1ul << PWM_POEN_POEN3_Pos) /*!< PWM_T::POEN: POEN3 Mask */ + +#define PWM_POEN_POEN4_Pos (4) /*!< PWM_T::POEN: POEN4 Position */ +#define PWM_POEN_POEN4_Msk (0x1ul << PWM_POEN_POEN4_Pos) /*!< PWM_T::POEN: POEN4 Mask */ + +#define PWM_POEN_POEN5_Pos (5) /*!< PWM_T::POEN: POEN5 Position */ +#define PWM_POEN_POEN5_Msk (0x1ul << PWM_POEN_POEN5_Pos) /*!< PWM_T::POEN: POEN5 Mask */ + +#define PWM_SWBRK_BRKETRG0_Pos (0) /*!< PWM_T::SWBRK: BRKETRG0 Position */ +#define PWM_SWBRK_BRKETRG0_Msk (0x1ul << PWM_SWBRK_BRKETRG0_Pos) /*!< PWM_T::SWBRK: BRKETRG0 Mask */ + +#define PWM_SWBRK_BRKETRG2_Pos (1) /*!< PWM_T::SWBRK: BRKETRG2 Position */ +#define PWM_SWBRK_BRKETRG2_Msk (0x1ul << PWM_SWBRK_BRKETRG2_Pos) /*!< PWM_T::SWBRK: BRKETRG2 Mask */ + +#define PWM_SWBRK_BRKETRG4_Pos (2) /*!< PWM_T::SWBRK: BRKETRG4 Position */ +#define PWM_SWBRK_BRKETRG4_Msk (0x1ul << PWM_SWBRK_BRKETRG4_Pos) /*!< PWM_T::SWBRK: BRKETRG4 Mask */ + +#define PWM_SWBRK_BRKLTRG0_Pos (8) /*!< PWM_T::SWBRK: BRKLTRG0 Position */ +#define PWM_SWBRK_BRKLTRG0_Msk (0x1ul << PWM_SWBRK_BRKLTRG0_Pos) /*!< PWM_T::SWBRK: BRKLTRG0 Mask */ + +#define PWM_SWBRK_BRKLTRG2_Pos (9) /*!< PWM_T::SWBRK: BRKLTRG2 Position */ +#define PWM_SWBRK_BRKLTRG2_Msk (0x1ul << PWM_SWBRK_BRKLTRG2_Pos) /*!< PWM_T::SWBRK: BRKLTRG2 Mask */ + +#define PWM_SWBRK_BRKLTRG4_Pos (10) /*!< PWM_T::SWBRK: BRKLTRG4 Position */ +#define PWM_SWBRK_BRKLTRG4_Msk (0x1ul << PWM_SWBRK_BRKLTRG4_Pos) /*!< PWM_T::SWBRK: BRKLTRG4 Mask */ + +#define PWM_INTEN0_ZIEN0_Pos (0) /*!< PWM_T::INTEN0: ZIEN0 Position */ +#define PWM_INTEN0_ZIEN0_Msk (0x1ul << PWM_INTEN0_ZIEN0_Pos) /*!< PWM_T::INTEN0: ZIEN0 Mask */ + +#define PWM_INTEN0_ZIEN2_Pos (2) /*!< PWM_T::INTEN0: ZIEN2 Position */ +#define PWM_INTEN0_ZIEN2_Msk (0x1ul << PWM_INTEN0_ZIEN2_Pos) /*!< PWM_T::INTEN0: ZIEN2 Mask */ + +#define PWM_INTEN0_ZIEN4_Pos (4) /*!< PWM_T::INTEN0: ZIEN4 Position */ +#define PWM_INTEN0_ZIEN4_Msk (0x1ul << PWM_INTEN0_ZIEN4_Pos) /*!< PWM_T::INTEN0: ZIEN4 Mask */ + +#define PWM_INTEN0_PIEN0_Pos (8) /*!< PWM_T::INTEN0: PIEN0 Position */ +#define PWM_INTEN0_PIEN0_Msk (0x1ul << PWM_INTEN0_PIEN0_Pos) /*!< PWM_T::INTEN0: PIEN0 Mask */ + +#define PWM_INTEN0_PIEN2_Pos (10) /*!< PWM_T::INTEN0: PIEN2 Position */ +#define PWM_INTEN0_PIEN2_Msk (0x1ul << PWM_INTEN0_PIEN2_Pos) /*!< PWM_T::INTEN0: PIEN2 Mask */ + +#define PWM_INTEN0_PIEN4_Pos (12) /*!< PWM_T::INTEN0: PIEN4 Position */ +#define PWM_INTEN0_PIEN4_Msk (0x1ul << PWM_INTEN0_PIEN4_Pos) /*!< PWM_T::INTEN0: PIEN4 Mask */ + +#define PWM_INTEN0_CMPUIEN0_Pos (16) /*!< PWM_T::INTEN0: CMPUIEN0 Position */ +#define PWM_INTEN0_CMPUIEN0_Msk (0x1ul << PWM_INTEN0_CMPUIEN0_Pos) /*!< PWM_T::INTEN0: CMPUIEN0 Mask */ + +#define PWM_INTEN0_CMPUIEN1_Pos (17) /*!< PWM_T::INTEN0: CMPUIEN1 Position */ +#define PWM_INTEN0_CMPUIEN1_Msk (0x1ul << PWM_INTEN0_CMPUIEN1_Pos) /*!< PWM_T::INTEN0: CMPUIEN1 Mask */ + +#define PWM_INTEN0_CMPUIEN2_Pos (18) /*!< PWM_T::INTEN0: CMPUIEN2 Position */ +#define PWM_INTEN0_CMPUIEN2_Msk (0x1ul << PWM_INTEN0_CMPUIEN2_Pos) /*!< PWM_T::INTEN0: CMPUIEN2 Mask */ + +#define PWM_INTEN0_CMPUIEN3_Pos (19) /*!< PWM_T::INTEN0: CMPUIEN3 Position */ +#define PWM_INTEN0_CMPUIEN3_Msk (0x1ul << PWM_INTEN0_CMPUIEN3_Pos) /*!< PWM_T::INTEN0: CMPUIEN3 Mask */ + +#define PWM_INTEN0_CMPUIEN4_Pos (20) /*!< PWM_T::INTEN0: CMPUIEN4 Position */ +#define PWM_INTEN0_CMPUIEN4_Msk (0x1ul << PWM_INTEN0_CMPUIEN4_Pos) /*!< PWM_T::INTEN0: CMPUIEN4 Mask */ + +#define PWM_INTEN0_CMPUIEN5_Pos (21) /*!< PWM_T::INTEN0: CMPUIEN5 Position */ +#define PWM_INTEN0_CMPUIEN5_Msk (0x1ul << PWM_INTEN0_CMPUIEN5_Pos) /*!< PWM_T::INTEN0: CMPUIEN5 Mask */ + +#define PWM_INTEN0_CMPDIEN0_Pos (24) /*!< PWM_T::INTEN0: CMPDIEN0 Position */ +#define PWM_INTEN0_CMPDIEN0_Msk (0x1ul << PWM_INTEN0_CMPDIEN0_Pos) /*!< PWM_T::INTEN0: CMPDIEN0 Mask */ + +#define PWM_INTEN0_CMPDIEN1_Pos (25) /*!< PWM_T::INTEN0: CMPDIEN1 Position */ +#define PWM_INTEN0_CMPDIEN1_Msk (0x1ul << PWM_INTEN0_CMPDIEN1_Pos) /*!< PWM_T::INTEN0: CMPDIEN1 Mask */ + +#define PWM_INTEN0_CMPDIEN2_Pos (26) /*!< PWM_T::INTEN0: CMPDIEN2 Position */ +#define PWM_INTEN0_CMPDIEN2_Msk (0x1ul << PWM_INTEN0_CMPDIEN2_Pos) /*!< PWM_T::INTEN0: CMPDIEN2 Mask */ + +#define PWM_INTEN0_CMPDIEN3_Pos (27) /*!< PWM_T::INTEN0: CMPDIEN3 Position */ +#define PWM_INTEN0_CMPDIEN3_Msk (0x1ul << PWM_INTEN0_CMPDIEN3_Pos) /*!< PWM_T::INTEN0: CMPDIEN3 Mask */ + +#define PWM_INTEN0_CMPDIEN4_Pos (28) /*!< PWM_T::INTEN0: CMPDIEN4 Position */ +#define PWM_INTEN0_CMPDIEN4_Msk (0x1ul << PWM_INTEN0_CMPDIEN4_Pos) /*!< PWM_T::INTEN0: CMPDIEN4 Mask */ + +#define PWM_INTEN0_CMPDIEN5_Pos (29) /*!< PWM_T::INTEN0: CMPDIEN5 Position */ +#define PWM_INTEN0_CMPDIEN5_Msk (0x1ul << PWM_INTEN0_CMPDIEN5_Pos) /*!< PWM_T::INTEN0: CMPDIEN5 Mask */ + +#define PWM_INTEN1_BRKEIEN0_1_Pos (0) /*!< PWM_T::INTEN1: BRKEIEN0_1 Position */ +#define PWM_INTEN1_BRKEIEN0_1_Msk (0x1ul << PWM_INTEN1_BRKEIEN0_1_Pos) /*!< PWM_T::INTEN1: BRKEIEN0_1 Mask */ + +#define PWM_INTEN1_BRKEIEN2_3_Pos (1) /*!< PWM_T::INTEN1: BRKEIEN2_3 Position */ +#define PWM_INTEN1_BRKEIEN2_3_Msk (0x1ul << PWM_INTEN1_BRKEIEN2_3_Pos) /*!< PWM_T::INTEN1: BRKEIEN2_3 Mask */ + +#define PWM_INTEN1_BRKEIEN4_5_Pos (2) /*!< PWM_T::INTEN1: BRKEIEN4_5 Position */ +#define PWM_INTEN1_BRKEIEN4_5_Msk (0x1ul << PWM_INTEN1_BRKEIEN4_5_Pos) /*!< PWM_T::INTEN1: BRKEIEN4_5 Mask */ + +#define PWM_INTEN1_BRKLIEN0_1_Pos (8) /*!< PWM_T::INTEN1: BRKLIEN0_1 Position */ +#define PWM_INTEN1_BRKLIEN0_1_Msk (0x1ul << PWM_INTEN1_BRKLIEN0_1_Pos) /*!< PWM_T::INTEN1: BRKLIEN0_1 Mask */ + +#define PWM_INTEN1_BRKLIEN2_3_Pos (9) /*!< PWM_T::INTEN1: BRKLIEN2_3 Position */ +#define PWM_INTEN1_BRKLIEN2_3_Msk (0x1ul << PWM_INTEN1_BRKLIEN2_3_Pos) /*!< PWM_T::INTEN1: BRKLIEN2_3 Mask */ + +#define PWM_INTEN1_BRKLIEN4_5_Pos (10) /*!< PWM_T::INTEN1: BRKLIEN4_5 Position */ +#define PWM_INTEN1_BRKLIEN4_5_Msk (0x1ul << PWM_INTEN1_BRKLIEN4_5_Pos) /*!< PWM_T::INTEN1: BRKLIEN4_5 Mask */ + +#define PWM_INTSTS0_ZIF0_Pos (0) /*!< PWM_T::INTSTS0: ZIF0 Position */ +#define PWM_INTSTS0_ZIF0_Msk (0x1ul << PWM_INTSTS0_ZIF0_Pos) /*!< PWM_T::INTSTS0: ZIF0 Mask */ + +#define PWM_INTSTS0_ZIF2_Pos (2) /*!< PWM_T::INTSTS0: ZIF2 Position */ +#define PWM_INTSTS0_ZIF2_Msk (0x1ul << PWM_INTSTS0_ZIF2_Pos) /*!< PWM_T::INTSTS0: ZIF2 Mask */ + +#define PWM_INTSTS0_ZIF4_Pos (4) /*!< PWM_T::INTSTS0: ZIF4 Position */ +#define PWM_INTSTS0_ZIF4_Msk (0x1ul << PWM_INTSTS0_ZIF4_Pos) /*!< PWM_T::INTSTS0: ZIF4 Mask */ + +#define PWM_INTSTS0_PIF0_Pos (8) /*!< PWM_T::INTSTS0: PIF0 Position */ +#define PWM_INTSTS0_PIF0_Msk (0x1ul << PWM_INTSTS0_PIF0_Pos) /*!< PWM_T::INTSTS0: PIF0 Mask */ + +#define PWM_INTSTS0_PIF2_Pos (10) /*!< PWM_T::INTSTS0: PIF2 Position */ +#define PWM_INTSTS0_PIF2_Msk (0x1ul << PWM_INTSTS0_PIF2_Pos) /*!< PWM_T::INTSTS0: PIF2 Mask */ + +#define PWM_INTSTS0_PIF4_Pos (12) /*!< PWM_T::INTSTS0: PIF4 Position */ +#define PWM_INTSTS0_PIF4_Msk (0x1ul << PWM_INTSTS0_PIF4_Pos) /*!< PWM_T::INTSTS0: PIF4 Mask */ + +#define PWM_INTSTS0_CMPUIF0_Pos (16) /*!< PWM_T::INTSTS0: CMPUIF0 Position */ +#define PWM_INTSTS0_CMPUIF0_Msk (0x1ul << PWM_INTSTS0_CMPUIF0_Pos) /*!< PWM_T::INTSTS0: CMPUIF0 Mask */ + +#define PWM_INTSTS0_CMPUIF1_Pos (17) /*!< PWM_T::INTSTS0: CMPUIF1 Position */ +#define PWM_INTSTS0_CMPUIF1_Msk (0x1ul << PWM_INTSTS0_CMPUIF1_Pos) /*!< PWM_T::INTSTS0: CMPUIF1 Mask */ + +#define PWM_INTSTS0_CMPUIF2_Pos (18) /*!< PWM_T::INTSTS0: CMPUIF2 Position */ +#define PWM_INTSTS0_CMPUIF2_Msk (0x1ul << PWM_INTSTS0_CMPUIF2_Pos) /*!< PWM_T::INTSTS0: CMPUIF2 Mask */ + +#define PWM_INTSTS0_CMPUIF3_Pos (19) /*!< PWM_T::INTSTS0: CMPUIF3 Position */ +#define PWM_INTSTS0_CMPUIF3_Msk (0x1ul << PWM_INTSTS0_CMPUIF3_Pos) /*!< PWM_T::INTSTS0: CMPUIF3 Mask */ + +#define PWM_INTSTS0_CMPUIF4_Pos (20) /*!< PWM_T::INTSTS0: CMPUIF4 Position */ +#define PWM_INTSTS0_CMPUIF4_Msk (0x1ul << PWM_INTSTS0_CMPUIF4_Pos) /*!< PWM_T::INTSTS0: CMPUIF4 Mask */ + +#define PWM_INTSTS0_CMPUIF5_Pos (21) /*!< PWM_T::INTSTS0: CMPUIF5 Position */ +#define PWM_INTSTS0_CMPUIF5_Msk (0x1ul << PWM_INTSTS0_CMPUIF5_Pos) /*!< PWM_T::INTSTS0: CMPUIF5 Mask */ + +#define PWM_INTSTS0_CMPDIF0_Pos (24) /*!< PWM_T::INTSTS0: CMPDIF0 Position */ +#define PWM_INTSTS0_CMPDIF0_Msk (0x1ul << PWM_INTSTS0_CMPDIF0_Pos) /*!< PWM_T::INTSTS0: CMPDIF0 Mask */ + +#define PWM_INTSTS0_CMPDIF1_Pos (25) /*!< PWM_T::INTSTS0: CMPDIF1 Position */ +#define PWM_INTSTS0_CMPDIF1_Msk (0x1ul << PWM_INTSTS0_CMPDIF1_Pos) /*!< PWM_T::INTSTS0: CMPDIF1 Mask */ + +#define PWM_INTSTS0_CMPDIF2_Pos (26) /*!< PWM_T::INTSTS0: CMPDIF2 Position */ +#define PWM_INTSTS0_CMPDIF2_Msk (0x1ul << PWM_INTSTS0_CMPDIF2_Pos) /*!< PWM_T::INTSTS0: CMPDIF2 Mask */ + +#define PWM_INTSTS0_CMPDIF3_Pos (27) /*!< PWM_T::INTSTS0: CMPDIF3 Position */ +#define PWM_INTSTS0_CMPDIF3_Msk (0x1ul << PWM_INTSTS0_CMPDIF3_Pos) /*!< PWM_T::INTSTS0: CMPDIF3 Mask */ + +#define PWM_INTSTS0_CMPDIF4_Pos (28) /*!< PWM_T::INTSTS0: CMPDIF4 Position */ +#define PWM_INTSTS0_CMPDIF4_Msk (0x1ul << PWM_INTSTS0_CMPDIF4_Pos) /*!< PWM_T::INTSTS0: CMPDIF4 Mask */ + +#define PWM_INTSTS0_CMPDIF5_Pos (29) /*!< PWM_T::INTSTS0: CMPDIF5 Position */ +#define PWM_INTSTS0_CMPDIF5_Msk (0x1ul << PWM_INTSTS0_CMPDIF5_Pos) /*!< PWM_T::INTSTS0: CMPDIF5 Mask */ + +#define PWM_INTSTS1_BRKEIF0_Pos (0) /*!< PWM_T::INTSTS1: BRKEIF0 Position */ +#define PWM_INTSTS1_BRKEIF0_Msk (0x1ul << PWM_INTSTS1_BRKEIF0_Pos) /*!< PWM_T::INTSTS1: BRKEIF0 Mask */ + +#define PWM_INTSTS1_BRKEIF1_Pos (1) /*!< PWM_T::INTSTS1: BRKEIF1 Position */ +#define PWM_INTSTS1_BRKEIF1_Msk (0x1ul << PWM_INTSTS1_BRKEIF1_Pos) /*!< PWM_T::INTSTS1: BRKEIF1 Mask */ + +#define PWM_INTSTS1_BRKEIF2_Pos (2) /*!< PWM_T::INTSTS1: BRKEIF2 Position */ +#define PWM_INTSTS1_BRKEIF2_Msk (0x1ul << PWM_INTSTS1_BRKEIF2_Pos) /*!< PWM_T::INTSTS1: BRKEIF2 Mask */ + +#define PWM_INTSTS1_BRKEIF3_Pos (3) /*!< PWM_T::INTSTS1: BRKEIF3 Position */ +#define PWM_INTSTS1_BRKEIF3_Msk (0x1ul << PWM_INTSTS1_BRKEIF3_Pos) /*!< PWM_T::INTSTS1: BRKEIF3 Mask */ + +#define PWM_INTSTS1_BRKEIF4_Pos (4) /*!< PWM_T::INTSTS1: BRKEIF4 Position */ +#define PWM_INTSTS1_BRKEIF4_Msk (0x1ul << PWM_INTSTS1_BRKEIF4_Pos) /*!< PWM_T::INTSTS1: BRKEIF4 Mask */ + +#define PWM_INTSTS1_BRKEIF5_Pos (5) /*!< PWM_T::INTSTS1: BRKEIF5 Position */ +#define PWM_INTSTS1_BRKEIF5_Msk (0x1ul << PWM_INTSTS1_BRKEIF5_Pos) /*!< PWM_T::INTSTS1: BRKEIF5 Mask */ + +#define PWM_INTSTS1_BRKLIF0_Pos (8) /*!< PWM_T::INTSTS1: BRKLIF0 Position */ +#define PWM_INTSTS1_BRKLIF0_Msk (0x1ul << PWM_INTSTS1_BRKLIF0_Pos) /*!< PWM_T::INTSTS1: BRKLIF0 Mask */ + +#define PWM_INTSTS1_BRKLIF1_Pos (9) /*!< PWM_T::INTSTS1: BRKLIF1 Position */ +#define PWM_INTSTS1_BRKLIF1_Msk (0x1ul << PWM_INTSTS1_BRKLIF1_Pos) /*!< PWM_T::INTSTS1: BRKLIF1 Mask */ + +#define PWM_INTSTS1_BRKLIF2_Pos (10) /*!< PWM_T::INTSTS1: BRKLIF2 Position */ +#define PWM_INTSTS1_BRKLIF2_Msk (0x1ul << PWM_INTSTS1_BRKLIF2_Pos) /*!< PWM_T::INTSTS1: BRKLIF2 Mask */ + +#define PWM_INTSTS1_BRKLIF3_Pos (11) /*!< PWM_T::INTSTS1: BRKLIF3 Position */ +#define PWM_INTSTS1_BRKLIF3_Msk (0x1ul << PWM_INTSTS1_BRKLIF3_Pos) /*!< PWM_T::INTSTS1: BRKLIF3 Mask */ + +#define PWM_INTSTS1_BRKLIF4_Pos (12) /*!< PWM_T::INTSTS1: BRKLIF4 Position */ +#define PWM_INTSTS1_BRKLIF4_Msk (0x1ul << PWM_INTSTS1_BRKLIF4_Pos) /*!< PWM_T::INTSTS1: BRKLIF4 Mask */ + +#define PWM_INTSTS1_BRKLIF5_Pos (13) /*!< PWM_T::INTSTS1: BRKLIF5 Position */ +#define PWM_INTSTS1_BRKLIF5_Msk (0x1ul << PWM_INTSTS1_BRKLIF5_Pos) /*!< PWM_T::INTSTS1: BRKLIF5 Mask */ + +#define PWM_INTSTS1_BRKESTS0_Pos (16) /*!< PWM_T::INTSTS1: BRKESTS0 Position */ +#define PWM_INTSTS1_BRKESTS0_Msk (0x1ul << PWM_INTSTS1_BRKESTS0_Pos) /*!< PWM_T::INTSTS1: BRKESTS0 Mask */ + +#define PWM_INTSTS1_BRKESTS1_Pos (17) /*!< PWM_T::INTSTS1: BRKESTS1 Position */ +#define PWM_INTSTS1_BRKESTS1_Msk (0x1ul << PWM_INTSTS1_BRKESTS1_Pos) /*!< PWM_T::INTSTS1: BRKESTS1 Mask */ + +#define PWM_INTSTS1_BRKESTS2_Pos (18) /*!< PWM_T::INTSTS1: BRKESTS2 Position */ +#define PWM_INTSTS1_BRKESTS2_Msk (0x1ul << PWM_INTSTS1_BRKESTS2_Pos) /*!< PWM_T::INTSTS1: BRKESTS2 Mask */ + +#define PWM_INTSTS1_BRKESTS3_Pos (19) /*!< PWM_T::INTSTS1: BRKESTS3 Position */ +#define PWM_INTSTS1_BRKESTS3_Msk (0x1ul << PWM_INTSTS1_BRKESTS3_Pos) /*!< PWM_T::INTSTS1: BRKESTS3 Mask */ + +#define PWM_INTSTS1_BRKESTS4_Pos (20) /*!< PWM_T::INTSTS1: BRKESTS4 Position */ +#define PWM_INTSTS1_BRKESTS4_Msk (0x1ul << PWM_INTSTS1_BRKESTS4_Pos) /*!< PWM_T::INTSTS1: BRKESTS4 Mask */ + +#define PWM_INTSTS1_BRKESTS5_Pos (21) /*!< PWM_T::INTSTS1: BRKESTS5 Position */ +#define PWM_INTSTS1_BRKESTS5_Msk (0x1ul << PWM_INTSTS1_BRKESTS5_Pos) /*!< PWM_T::INTSTS1: BRKESTS5 Mask */ + +#define PWM_INTSTS1_BRKLSTS0_Pos (24) /*!< PWM_T::INTSTS1: BRKLSTS0 Position */ +#define PWM_INTSTS1_BRKLSTS0_Msk (0x1ul << PWM_INTSTS1_BRKLSTS0_Pos) /*!< PWM_T::INTSTS1: BRKLSTS0 Mask */ + +#define PWM_INTSTS1_BRKLSTS1_Pos (25) /*!< PWM_T::INTSTS1: BRKLSTS1 Position */ +#define PWM_INTSTS1_BRKLSTS1_Msk (0x1ul << PWM_INTSTS1_BRKLSTS1_Pos) /*!< PWM_T::INTSTS1: BRKLSTS1 Mask */ + +#define PWM_INTSTS1_BRKLSTS2_Pos (26) /*!< PWM_T::INTSTS1: BRKLSTS2 Position */ +#define PWM_INTSTS1_BRKLSTS2_Msk (0x1ul << PWM_INTSTS1_BRKLSTS2_Pos) /*!< PWM_T::INTSTS1: BRKLSTS2 Mask */ + +#define PWM_INTSTS1_BRKLSTS3_Pos (27) /*!< PWM_T::INTSTS1: BRKLSTS3 Position */ +#define PWM_INTSTS1_BRKLSTS3_Msk (0x1ul << PWM_INTSTS1_BRKLSTS3_Pos) /*!< PWM_T::INTSTS1: BRKLSTS3 Mask */ + +#define PWM_INTSTS1_BRKLSTS4_Pos (28) /*!< PWM_T::INTSTS1: BRKLSTS4 Position */ +#define PWM_INTSTS1_BRKLSTS4_Msk (0x1ul << PWM_INTSTS1_BRKLSTS4_Pos) /*!< PWM_T::INTSTS1: BRKLSTS4 Mask */ + +#define PWM_INTSTS1_BRKLSTS5_Pos (29) /*!< PWM_T::INTSTS1: BRKLSTS5 Position */ +#define PWM_INTSTS1_BRKLSTS5_Msk (0x1ul << PWM_INTSTS1_BRKLSTS5_Pos) /*!< PWM_T::INTSTS1: BRKLSTS5 Mask */ + +#define PWM_ADCTS0_TRGSEL0_Pos (0) /*!< PWM_T::ADCTS0: TRGSEL0 Position */ +#define PWM_ADCTS0_TRGSEL0_Msk (0xful << PWM_ADCTS0_TRGSEL0_Pos) /*!< PWM_T::ADCTS0: TRGSEL0 Mask */ + +#define PWM_ADCTS0_TRGEN0_Pos (7) /*!< PWM_T::ADCTS0: TRGEN0 Position */ +#define PWM_ADCTS0_TRGEN0_Msk (0x1ul << PWM_ADCTS0_TRGEN0_Pos) /*!< PWM_T::ADCTS0: TRGEN0 Mask */ + +#define PWM_ADCTS0_TRGSEL1_Pos (8) /*!< PWM_T::ADCTS0: TRGSEL1 Position */ +#define PWM_ADCTS0_TRGSEL1_Msk (0xful << PWM_ADCTS0_TRGSEL1_Pos) /*!< PWM_T::ADCTS0: TRGSEL1 Mask */ + +#define PWM_ADCTS0_TRGEN1_Pos (15) /*!< PWM_T::ADCTS0: TRGEN1 Position */ +#define PWM_ADCTS0_TRGEN1_Msk (0x1ul << PWM_ADCTS0_TRGEN1_Pos) /*!< PWM_T::ADCTS0: TRGEN1 Mask */ + +#define PWM_ADCTS0_TRGSEL2_Pos (16) /*!< PWM_T::ADCTS0: TRGSEL2 Position */ +#define PWM_ADCTS0_TRGSEL2_Msk (0xful << PWM_ADCTS0_TRGSEL2_Pos) /*!< PWM_T::ADCTS0: TRGSEL2 Mask */ + +#define PWM_ADCTS0_TRGEN2_Pos (23) /*!< PWM_T::ADCTS0: TRGEN2 Position */ +#define PWM_ADCTS0_TRGEN2_Msk (0x1ul << PWM_ADCTS0_TRGEN2_Pos) /*!< PWM_T::ADCTS0: TRGEN2 Mask */ + +#define PWM_ADCTS0_TRGSEL3_Pos (24) /*!< PWM_T::ADCTS0: TRGSEL3 Position */ +#define PWM_ADCTS0_TRGSEL3_Msk (0xful << PWM_ADCTS0_TRGSEL3_Pos) /*!< PWM_T::ADCTS0: TRGSEL3 Mask */ + +#define PWM_ADCTS0_TRGEN3_Pos (31) /*!< PWM_T::ADCTS0: TRGEN3 Position */ +#define PWM_ADCTS0_TRGEN3_Msk (0x1ul << PWM_ADCTS0_TRGEN3_Pos) /*!< PWM_T::ADCTS0: TRGEN3 Mask */ + +#define PWM_ADCTS1_TRGSEL4_Pos (0) /*!< PWM_T::ADCTS1: TRGSEL4 Position */ +#define PWM_ADCTS1_TRGSEL4_Msk (0xful << PWM_ADCTS1_TRGSEL4_Pos) /*!< PWM_T::ADCTS1: TRGSEL4 Mask */ + +#define PWM_ADCTS1_TRGEN4_Pos (7) /*!< PWM_T::ADCTS1: TRGEN4 Position */ +#define PWM_ADCTS1_TRGEN4_Msk (0x1ul << PWM_ADCTS1_TRGEN4_Pos) /*!< PWM_T::ADCTS1: TRGEN4 Mask */ + +#define PWM_ADCTS1_TRGSEL5_Pos (8) /*!< PWM_T::ADCTS1: TRGSEL5 Position */ +#define PWM_ADCTS1_TRGSEL5_Msk (0xful << PWM_ADCTS1_TRGSEL5_Pos) /*!< PWM_T::ADCTS1: TRGSEL5 Mask */ + +#define PWM_ADCTS1_TRGEN5_Pos (15) /*!< PWM_T::ADCTS1: TRGEN5 Position */ +#define PWM_ADCTS1_TRGEN5_Msk (0x1ul << PWM_ADCTS1_TRGEN5_Pos) /*!< PWM_T::ADCTS1: TRGEN5 Mask */ + +#define PWM_SSCTL_SSEN0_Pos (0) /*!< PWM_T::SSCTL: SSEN0 Position */ +#define PWM_SSCTL_SSEN0_Msk (0x1ul << PWM_SSCTL_SSEN0_Pos) /*!< PWM_T::SSCTL: SSEN0 Mask */ + +#define PWM_SSCTL_SSEN2_Pos (2) /*!< PWM_T::SSCTL: SSEN2 Position */ +#define PWM_SSCTL_SSEN2_Msk (0x1ul << PWM_SSCTL_SSEN2_Pos) /*!< PWM_T::SSCTL: SSEN2 Mask */ + +#define PWM_SSCTL_SSEN4_Pos (4) /*!< PWM_T::SSCTL: SSEN4 Position */ +#define PWM_SSCTL_SSEN4_Msk (0x1ul << PWM_SSCTL_SSEN4_Pos) /*!< PWM_T::SSCTL: SSEN4 Mask */ + +#define PWM_SSCTL_SSRC_Pos (8) /*!< PWM_T::SSCTL: SSRC Position */ +#define PWM_SSCTL_SSRC_Msk (0x3ul << PWM_SSCTL_SSRC_Pos) /*!< PWM_T::SSCTL: SSRC Mask */ + +#define PWM_SSTRG_CNTSEN_Pos (0) /*!< PWM_T::SSTRG: CNTSEN Position */ +#define PWM_SSTRG_CNTSEN_Msk (0x1ul << PWM_SSTRG_CNTSEN_Pos) /*!< PWM_T::SSTRG: CNTSEN Mask */ + +#define PWM_STATUS_CNTMAX0_Pos (0) /*!< PWM_T::STATUS: CNTMAX0 Position */ +#define PWM_STATUS_CNTMAX0_Msk (0x1ul << PWM_STATUS_CNTMAX0_Pos) /*!< PWM_T::STATUS: CNTMAX0 Mask */ + +#define PWM_STATUS_CNTMAX2_Pos (2) /*!< PWM_T::STATUS: CNTMAX2 Position */ +#define PWM_STATUS_CNTMAX2_Msk (0x1ul << PWM_STATUS_CNTMAX2_Pos) /*!< PWM_T::STATUS: CNTMAX2 Mask */ + +#define PWM_STATUS_CNTMAX4_Pos (4) /*!< PWM_T::STATUS: CNTMAX4 Position */ +#define PWM_STATUS_CNTMAX4_Msk (0x1ul << PWM_STATUS_CNTMAX4_Pos) /*!< PWM_T::STATUS: CNTMAX4 Mask */ + +#define PWM_STATUS_ADCTRG0_Pos (16) /*!< PWM_T::STATUS: ADCTRGF0 Position */ +#define PWM_STATUS_ADCTRG0_Msk (0x1ul << PWM_STATUS_ADCTRG0_Pos) /*!< PWM_T::STATUS: ADCTRGF0 Mask */ + +#define PWM_STATUS_ADCTRG1_Pos (17) /*!< PWM_T::STATUS: ADCTRGF1 Position */ +#define PWM_STATUS_ADCTRG1_Msk (0x1ul << PWM_STATUS_ADCTRG1_Pos) /*!< PWM_T::STATUS: ADCTRGF1 Mask */ + +#define PWM_STATUS_ADCTRG2_Pos (18) /*!< PWM_T::STATUS: ADCTRGF2 Position */ +#define PWM_STATUS_ADCTRG2_Msk (0x1ul << PWM_STATUS_ADCTRG2_Pos) /*!< PWM_T::STATUS: ADCTRGF2 Mask */ + +#define PWM_STATUS_ADCTRG3_Pos (19) /*!< PWM_T::STATUS: ADCTRGF3 Position */ +#define PWM_STATUS_ADCTRG3_Msk (0x1ul << PWM_STATUS_ADCTRG3_Pos) /*!< PWM_T::STATUS: ADCTRGF3 Mask */ + +#define PWM_STATUS_ADCTRG4_Pos (20) /*!< PWM_T::STATUS: ADCTRGF4 Position */ +#define PWM_STATUS_ADCTRG4_Msk (0x1ul << PWM_STATUS_ADCTRG4_Pos) /*!< PWM_T::STATUS: ADCTRGF4 Mask */ + +#define PWM_STATUS_ADCTRG5_Pos (21) /*!< PWM_T::STATUS: ADCTRGF5 Position */ +#define PWM_STATUS_ADCTRG5_Msk (0x1ul << PWM_STATUS_ADCTRG5_Pos) /*!< PWM_T::STATUS: ADCTRGF5 Mask */ + +#define PWM_CAPINEN_CAPINEN0_Pos (0) /*!< PWM_T::CAPINEN: CAPINEN0 Position */ +#define PWM_CAPINEN_CAPINEN0_Msk (0x1ul << PWM_CAPINEN_CAPINEN0_Pos) /*!< PWM_T::CAPINEN: CAPINEN0 Mask */ + +#define PWM_CAPINEN_CAPINEN1_Pos (1) /*!< PWM_T::CAPINEN: CAPINEN1 Position */ +#define PWM_CAPINEN_CAPINEN1_Msk (0x1ul << PWM_CAPINEN_CAPINEN1_Pos) /*!< PWM_T::CAPINEN: CAPINEN1 Mask */ + +#define PWM_CAPINEN_CAPINEN2_Pos (2) /*!< PWM_T::CAPINEN: CAPINEN2 Position */ +#define PWM_CAPINEN_CAPINEN2_Msk (0x1ul << PWM_CAPINEN_CAPINEN2_Pos) /*!< PWM_T::CAPINEN: CAPINEN2 Mask */ + +#define PWM_CAPINEN_CAPINEN3_Pos (3) /*!< PWM_T::CAPINEN: CAPINEN3 Position */ +#define PWM_CAPINEN_CAPINEN3_Msk (0x1ul << PWM_CAPINEN_CAPINEN3_Pos) /*!< PWM_T::CAPINEN: CAPINEN3 Mask */ + +#define PWM_CAPINEN_CAPINEN4_Pos (4) /*!< PWM_T::CAPINEN: CAPINEN4 Position */ +#define PWM_CAPINEN_CAPINEN4_Msk (0x1ul << PWM_CAPINEN_CAPINEN4_Pos) /*!< PWM_T::CAPINEN: CAPINEN4 Mask */ + +#define PWM_CAPINEN_CAPINEN5_Pos (5) /*!< PWM_T::CAPINEN: CAPINEN5 Position */ +#define PWM_CAPINEN_CAPINEN5_Msk (0x1ul << PWM_CAPINEN_CAPINEN5_Pos) /*!< PWM_T::CAPINEN: CAPINEN5 Mask */ + +#define PWM_CAPCTL_CAPEN0_Pos (0) /*!< PWM_T::CAPCTL: CAPEN0 Position */ +#define PWM_CAPCTL_CAPEN0_Msk (0x1ul << PWM_CAPCTL_CAPEN0_Pos) /*!< PWM_T::CAPCTL: CAPEN0 Mask */ + +#define PWM_CAPCTL_CAPEN1_Pos (1) /*!< PWM_T::CAPCTL: CAPEN1 Position */ +#define PWM_CAPCTL_CAPEN1_Msk (0x1ul << PWM_CAPCTL_CAPEN1_Pos) /*!< PWM_T::CAPCTL: CAPEN1 Mask */ + +#define PWM_CAPCTL_CAPEN2_Pos (2) /*!< PWM_T::CAPCTL: CAPEN2 Position */ +#define PWM_CAPCTL_CAPEN2_Msk (0x1ul << PWM_CAPCTL_CAPEN2_Pos) /*!< PWM_T::CAPCTL: CAPEN2 Mask */ + +#define PWM_CAPCTL_CAPEN3_Pos (3) /*!< PWM_T::CAPCTL: CAPEN3 Position */ +#define PWM_CAPCTL_CAPEN3_Msk (0x1ul << PWM_CAPCTL_CAPEN3_Pos) /*!< PWM_T::CAPCTL: CAPEN3 Mask */ + +#define PWM_CAPCTL_CAPEN4_Pos (4) /*!< PWM_T::CAPCTL: CAPEN4 Position */ +#define PWM_CAPCTL_CAPEN4_Msk (0x1ul << PWM_CAPCTL_CAPEN4_Pos) /*!< PWM_T::CAPCTL: CAPEN4 Mask */ + +#define PWM_CAPCTL_CAPEN5_Pos (5) /*!< PWM_T::CAPCTL: CAPEN5 Position */ +#define PWM_CAPCTL_CAPEN5_Msk (0x1ul << PWM_CAPCTL_CAPEN5_Pos) /*!< PWM_T::CAPCTL: CAPEN5 Mask */ + +#define PWM_CAPCTL_CAPINV0_Pos (8) /*!< PWM_T::CAPCTL: CAPINV0 Position */ +#define PWM_CAPCTL_CAPINV0_Msk (0x1ul << PWM_CAPCTL_CAPINV0_Pos) /*!< PWM_T::CAPCTL: CAPINV0 Mask */ + +#define PWM_CAPCTL_CAPINV1_Pos (9) /*!< PWM_T::CAPCTL: CAPINV1 Position */ +#define PWM_CAPCTL_CAPINV1_Msk (0x1ul << PWM_CAPCTL_CAPINV1_Pos) /*!< PWM_T::CAPCTL: CAPINV1 Mask */ + +#define PWM_CAPCTL_CAPINV2_Pos (10) /*!< PWM_T::CAPCTL: CAPINV2 Position */ +#define PWM_CAPCTL_CAPINV2_Msk (0x1ul << PWM_CAPCTL_CAPINV2_Pos) /*!< PWM_T::CAPCTL: CAPINV2 Mask */ + +#define PWM_CAPCTL_CAPINV3_Pos (11) /*!< PWM_T::CAPCTL: CAPINV3 Position */ +#define PWM_CAPCTL_CAPINV3_Msk (0x1ul << PWM_CAPCTL_CAPINV3_Pos) /*!< PWM_T::CAPCTL: CAPINV3 Mask */ + +#define PWM_CAPCTL_CAPINV4_Pos (12) /*!< PWM_T::CAPCTL: CAPINV4 Position */ +#define PWM_CAPCTL_CAPINV4_Msk (0x1ul << PWM_CAPCTL_CAPINV4_Pos) /*!< PWM_T::CAPCTL: CAPINV4 Mask */ + +#define PWM_CAPCTL_CAPINV5_Pos (13) /*!< PWM_T::CAPCTL: CAPINV5 Position */ +#define PWM_CAPCTL_CAPINV5_Msk (0x1ul << PWM_CAPCTL_CAPINV5_Pos) /*!< PWM_T::CAPCTL: CAPINV5 Mask */ + +#define PWM_CAPCTL_RCRLDEN0_Pos (16) /*!< PWM_T::CAPCTL: RCRLDEN0 Position */ +#define PWM_CAPCTL_RCRLDEN0_Msk (0x1ul << PWM_CAPCTL_RCRLDEN0_Pos) /*!< PWM_T::CAPCTL: RCRLDEN0 Mask */ + +#define PWM_CAPCTL_RCRLDEN1_Pos (17) /*!< PWM_T::CAPCTL: RCRLDEN1 Position */ +#define PWM_CAPCTL_RCRLDEN1_Msk (0x1ul << PWM_CAPCTL_RCRLDEN1_Pos) /*!< PWM_T::CAPCTL: RCRLDEN1 Mask */ + +#define PWM_CAPCTL_RCRLDEN2_Pos (18) /*!< PWM_T::CAPCTL: RCRLDEN2 Position */ +#define PWM_CAPCTL_RCRLDEN2_Msk (0x1ul << PWM_CAPCTL_RCRLDEN2_Pos) /*!< PWM_T::CAPCTL: RCRLDEN2 Mask */ + +#define PWM_CAPCTL_RCRLDEN3_Pos (19) /*!< PWM_T::CAPCTL: RCRLDEN3 Position */ +#define PWM_CAPCTL_RCRLDEN3_Msk (0x1ul << PWM_CAPCTL_RCRLDEN3_Pos) /*!< PWM_T::CAPCTL: RCRLDEN3 Mask */ + +#define PWM_CAPCTL_RCRLDEN4_Pos (20) /*!< PWM_T::CAPCTL: RCRLDEN4 Position */ +#define PWM_CAPCTL_RCRLDEN4_Msk (0x1ul << PWM_CAPCTL_RCRLDEN4_Pos) /*!< PWM_T::CAPCTL: RCRLDEN4 Mask */ + +#define PWM_CAPCTL_RCRLDEN5_Pos (21) /*!< PWM_T::CAPCTL: RCRLDEN5 Position */ +#define PWM_CAPCTL_RCRLDEN5_Msk (0x1ul << PWM_CAPCTL_RCRLDEN5_Pos) /*!< PWM_T::CAPCTL: RCRLDEN5 Mask */ + +#define PWM_CAPCTL_FCRLDEN0_Pos (24) /*!< PWM_T::CAPCTL: FCRLDEN0 Position */ +#define PWM_CAPCTL_FCRLDEN0_Msk (0x1ul << PWM_CAPCTL_FCRLDEN0_Pos) /*!< PWM_T::CAPCTL: FCRLDEN0 Mask */ + +#define PWM_CAPCTL_FCRLDEN1_Pos (25) /*!< PWM_T::CAPCTL: FCRLDEN1 Position */ +#define PWM_CAPCTL_FCRLDEN1_Msk (0x1ul << PWM_CAPCTL_FCRLDEN1_Pos) /*!< PWM_T::CAPCTL: FCRLDEN1 Mask */ + +#define PWM_CAPCTL_FCRLDEN2_Pos (26) /*!< PWM_T::CAPCTL: FCRLDEN2 Position */ +#define PWM_CAPCTL_FCRLDEN2_Msk (0x1ul << PWM_CAPCTL_FCRLDEN2_Pos) /*!< PWM_T::CAPCTL: FCRLDEN2 Mask */ + +#define PWM_CAPCTL_FCRLDEN3_Pos (27) /*!< PWM_T::CAPCTL: FCRLDEN3 Position */ +#define PWM_CAPCTL_FCRLDEN3_Msk (0x1ul << PWM_CAPCTL_FCRLDEN3_Pos) /*!< PWM_T::CAPCTL: FCRLDEN3 Mask */ + +#define PWM_CAPCTL_FCRLDEN4_Pos (28) /*!< PWM_T::CAPCTL: FCRLDEN4 Position */ +#define PWM_CAPCTL_FCRLDEN4_Msk (0x1ul << PWM_CAPCTL_FCRLDEN4_Pos) /*!< PWM_T::CAPCTL: FCRLDEN4 Mask */ + +#define PWM_CAPCTL_FCRLDEN5_Pos (29) /*!< PWM_T::CAPCTL: FCRLDEN5 Position */ +#define PWM_CAPCTL_FCRLDEN5_Msk (0x1ul << PWM_CAPCTL_FCRLDEN5_Pos) /*!< PWM_T::CAPCTL: FCRLDEN5 Mask */ + +#define PWM_CAPSTS_CRLIFOV0_Pos (0) /*!< PWM_T::CAPSTS: CRLIFOV0 Position */ +#define PWM_CAPSTS_CRLIFOV0_Msk (0x1ul << PWM_CAPSTS_CRLIFOV0_Pos) /*!< PWM_T::CAPSTS: CRLIFOV0 Mask */ + +#define PWM_CAPSTS_CRLIFOV1_Pos (1) /*!< PWM_T::CAPSTS: CRLIFOV1 Position */ +#define PWM_CAPSTS_CRLIFOV1_Msk (0x1ul << PWM_CAPSTS_CRLIFOV1_Pos) /*!< PWM_T::CAPSTS: CRLIFOV1 Mask */ + +#define PWM_CAPSTS_CRLIFOV2_Pos (2) /*!< PWM_T::CAPSTS: CRLIFOV2 Position */ +#define PWM_CAPSTS_CRLIFOV2_Msk (0x1ul << PWM_CAPSTS_CRLIFOV2_Pos) /*!< PWM_T::CAPSTS: CRLIFOV2 Mask */ + +#define PWM_CAPSTS_CRLIFOV3_Pos (3) /*!< PWM_T::CAPSTS: CRLIFOV3 Position */ +#define PWM_CAPSTS_CRLIFOV3_Msk (0x1ul << PWM_CAPSTS_CRLIFOV3_Pos) /*!< PWM_T::CAPSTS: CRLIFOV3 Mask */ + +#define PWM_CAPSTS_CRLIFOV4_Pos (4) /*!< PWM_T::CAPSTS: CRLIFOV4 Position */ +#define PWM_CAPSTS_CRLIFOV4_Msk (0x1ul << PWM_CAPSTS_CRLIFOV4_Pos) /*!< PWM_T::CAPSTS: CRLIFOV4 Mask */ + +#define PWM_CAPSTS_CRLIFOV5_Pos (5) /*!< PWM_T::CAPSTS: CRLIFOV5 Position */ +#define PWM_CAPSTS_CRLIFOV5_Msk (0x1ul << PWM_CAPSTS_CRLIFOV5_Pos) /*!< PWM_T::CAPSTS: CRLIFOV5 Mask */ + +#define PWM_CAPSTS_CFLIFOV0_Pos (8) /*!< PWM_T::CAPSTS: CFLIFOV0 Position */ +#define PWM_CAPSTS_CFLIFOV0_Msk (0x1ul << PWM_CAPSTS_CFLIFOV0_Pos) /*!< PWM_T::CAPSTS: CFLIFOV0 Mask */ + +#define PWM_CAPSTS_CFLIFOV1_Pos (9) /*!< PWM_T::CAPSTS: CFLIFOV1 Position */ +#define PWM_CAPSTS_CFLIFOV1_Msk (0x1ul << PWM_CAPSTS_CFLIFOV1_Pos) /*!< PWM_T::CAPSTS: CFLIFOV1 Mask */ + +#define PWM_CAPSTS_CFLIFOV2_Pos (10) /*!< PWM_T::CAPSTS: CFLIFOV2 Position */ +#define PWM_CAPSTS_CFLIFOV2_Msk (0x1ul << PWM_CAPSTS_CFLIFOV2_Pos) /*!< PWM_T::CAPSTS: CFLIFOV2 Mask */ + +#define PWM_CAPSTS_CFLIFOV3_Pos (11) /*!< PWM_T::CAPSTS: CFLIFOV3 Position */ +#define PWM_CAPSTS_CFLIFOV3_Msk (0x1ul << PWM_CAPSTS_CFLIFOV3_Pos) /*!< PWM_T::CAPSTS: CFLIFOV3 Mask */ + +#define PWM_CAPSTS_CFLIFOV4_Pos (12) /*!< PWM_T::CAPSTS: CFLIFOV4 Position */ +#define PWM_CAPSTS_CFLIFOV4_Msk (0x1ul << PWM_CAPSTS_CFLIFOV4_Pos) /*!< PWM_T::CAPSTS: CFLIFOV4 Mask */ + +#define PWM_CAPSTS_CFLIFOV5_Pos (13) /*!< PWM_T::CAPSTS: CFLIFOV5 Position */ +#define PWM_CAPSTS_CFLIFOV5_Msk (0x1ul << PWM_CAPSTS_CFLIFOV5_Pos) /*!< PWM_T::CAPSTS: CFLIFOV5 Mask */ + +#define PWM_RCAPDAT0_RCAPDAT_Pos (0) /*!< PWM_T::RCAPDAT0: RCAPDAT Position */ +#define PWM_RCAPDAT0_RCAPDAT_Msk (0xfffful << PWM_RCAPDAT0_RCAPDAT_Pos) /*!< PWM_T::RCAPDAT0: RCAPDAT Mask */ + +#define PWM_FCAPDAT0_FCAPDAT_Pos (0) /*!< PWM_T::FCAPDAT0: FCAPDAT Position */ +#define PWM_FCAPDAT0_FCAPDAT_Msk (0xfffful << PWM_FCAPDAT0_FCAPDAT_Pos) /*!< PWM_T::FCAPDAT0: FCAPDAT Mask */ + +#define PWM_RCAPDAT1_RCAPDAT_Pos (0) /*!< PWM_T::RCAPDAT1: RCAPDAT Position */ +#define PWM_RCAPDAT1_RCAPDAT_Msk (0xfffful << PWM_RCAPDAT1_RCAPDAT_Pos) /*!< PWM_T::RCAPDAT1: RCAPDAT Mask */ + +#define PWM_FCAPDAT1_FCAPDAT_Pos (0) /*!< PWM_T::FCAPDAT1: FCAPDAT Position */ +#define PWM_FCAPDAT1_FCAPDAT_Msk (0xfffful << PWM_FCAPDAT1_FCAPDAT_Pos) /*!< PWM_T::FCAPDAT1: FCAPDAT Mask */ + +#define PWM_RCAPDAT2_RCAPDAT_Pos (0) /*!< PWM_T::RCAPDAT2: RCAPDAT Position */ +#define PWM_RCAPDAT2_RCAPDAT_Msk (0xfffful << PWM_RCAPDAT2_RCAPDAT_Pos) /*!< PWM_T::RCAPDAT2: RCAPDAT Mask */ + +#define PWM_FCAPDAT2_FCAPDAT_Pos (0) /*!< PWM_T::FCAPDAT2: FCAPDAT Position */ +#define PWM_FCAPDAT2_FCAPDAT_Msk (0xfffful << PWM_FCAPDAT2_FCAPDAT_Pos) /*!< PWM_T::FCAPDAT2: FCAPDAT Mask */ + +#define PWM_RCAPDAT3_RCAPDAT_Pos (0) /*!< PWM_T::RCAPDAT3: RCAPDAT Position */ +#define PWM_RCAPDAT3_RCAPDAT_Msk (0xfffful << PWM_RCAPDAT3_RCAPDAT_Pos) /*!< PWM_T::RCAPDAT3: RCAPDAT Mask */ + +#define PWM_FCAPDAT3_FCAPDAT_Pos (0) /*!< PWM_T::FCAPDAT3: FCAPDAT Position */ +#define PWM_FCAPDAT3_FCAPDAT_Msk (0xfffful << PWM_FCAPDAT3_FCAPDAT_Pos) /*!< PWM_T::FCAPDAT3: FCAPDAT Mask */ + +#define PWM_RCAPDAT4_RCAPDAT_Pos (0) /*!< PWM_T::RCAPDAT4: RCAPDAT Position */ +#define PWM_RCAPDAT4_RCAPDAT_Msk (0xfffful << PWM_RCAPDAT4_RCAPDAT_Pos) /*!< PWM_T::RCAPDAT4: RCAPDAT Mask */ + +#define PWM_FCAPDAT4_FCAPDAT_Pos (0) /*!< PWM_T::FCAPDAT4: FCAPDAT Position */ +#define PWM_FCAPDAT4_FCAPDAT_Msk (0xfffful << PWM_FCAPDAT4_FCAPDAT_Pos) /*!< PWM_T::FCAPDAT4: FCAPDAT Mask */ + +#define PWM_RCAPDAT5_RCAPDAT_Pos (0) /*!< PWM_T::RCAPDAT5: RCAPDAT Position */ +#define PWM_RCAPDAT5_RCAPDAT_Msk (0xfffful << PWM_RCAPDAT5_RCAPDAT_Pos) /*!< PWM_T::RCAPDAT5: RCAPDAT Mask */ + +#define PWM_FCAPDAT5_FCAPDAT_Pos (0) /*!< PWM_T::FCAPDAT5: FCAPDAT Position */ +#define PWM_FCAPDAT5_FCAPDAT_Msk (0xfffful << PWM_FCAPDAT5_FCAPDAT_Pos) /*!< PWM_T::FCAPDAT5: FCAPDAT Mask */ + +#define PWM_PDMACTL_CHEN0_1_Pos (0) /*!< PWM_T::PDMACTL: CHEN0_1 Position */ +#define PWM_PDMACTL_CHEN0_1_Msk (0x1ul << PWM_PDMACTL_CHEN0_1_Pos) /*!< PWM_T::PDMACTL: CHEN0_1 Mask */ + +#define PWM_PDMACTL_CAPMOD0_1_Pos (1) /*!< PWM_T::PDMACTL: CAPMOD0_1 Position */ +#define PWM_PDMACTL_CAPMOD0_1_Msk (0x3ul << PWM_PDMACTL_CAPMOD0_1_Pos) /*!< PWM_T::PDMACTL: CAPMOD0_1 Mask */ + +#define PWM_PDMACTL_CAPORD0_1_Pos (3) /*!< PWM_T::PDMACTL: CAPORD0_1 Position */ +#define PWM_PDMACTL_CAPORD0_1_Msk (0x1ul << PWM_PDMACTL_CAPORD0_1_Pos) /*!< PWM_T::PDMACTL: CAPORD0_1 Mask */ + +#define PWM_PDMACTL_CHSEL0_1_Pos (4) /*!< PWM_T::PDMACTL: CHSEL0_1 Position */ +#define PWM_PDMACTL_CHSEL0_1_Msk (0x1ul << PWM_PDMACTL_CHSEL0_1_Pos) /*!< PWM_T::PDMACTL: CHSEL0_1 Mask */ + +#define PWM_PDMACTL_CHEN2_3_Pos (8) /*!< PWM_T::PDMACTL: CHEN2_3 Position */ +#define PWM_PDMACTL_CHEN2_3_Msk (0x1ul << PWM_PDMACTL_CHEN2_3_Pos) /*!< PWM_T::PDMACTL: CHEN2_3 Mask */ + +#define PWM_PDMACTL_CAPMOD2_3_Pos (9) /*!< PWM_T::PDMACTL: CAPMOD2_3 Position */ +#define PWM_PDMACTL_CAPMOD2_3_Msk (0x3ul << PWM_PDMACTL_CAPMOD2_3_Pos) /*!< PWM_T::PDMACTL: CAPMOD2_3 Mask */ + +#define PWM_PDMACTL_CAPORD2_3_Pos (11) /*!< PWM_T::PDMACTL: CAPORD2_3 Position */ +#define PWM_PDMACTL_CAPORD2_3_Msk (0x1ul << PWM_PDMACTL_CAPORD2_3_Pos) /*!< PWM_T::PDMACTL: CAPORD2_3 Mask */ + +#define PWM_PDMACTL_CHSEL2_3_Pos (12) /*!< PWM_T::PDMACTL: CHSEL2_3 Position */ +#define PWM_PDMACTL_CHSEL2_3_Msk (0x1ul << PWM_PDMACTL_CHSEL2_3_Pos) /*!< PWM_T::PDMACTL: CHSEL2_3 Mask */ + +#define PWM_PDMACTL_CHEN4_5_Pos (16) /*!< PWM_T::PDMACTL: CHEN4_5 Position */ +#define PWM_PDMACTL_CHEN4_5_Msk (0x1ul << PWM_PDMACTL_CHEN4_5_Pos) /*!< PWM_T::PDMACTL: CHEN4_5 Mask */ + +#define PWM_PDMACTL_CAPMOD4_5_Pos (17) /*!< PWM_T::PDMACTL: CAPMOD4_5 Position */ +#define PWM_PDMACTL_CAPMOD4_5_Msk (0x3ul << PWM_PDMACTL_CAPMOD4_5_Pos) /*!< PWM_T::PDMACTL: CAPMOD4_5 Mask */ + +#define PWM_PDMACTL_CAPORD4_5_Pos (19) /*!< PWM_T::PDMACTL: CAPORD4_5 Position */ +#define PWM_PDMACTL_CAPORD4_5_Msk (0x1ul << PWM_PDMACTL_CAPORD4_5_Pos) /*!< PWM_T::PDMACTL: CAPORD4_5 Mask */ + +#define PWM_PDMACTL_CHSEL4_5_Pos (20) /*!< PWM_T::PDMACTL: CHSEL4_5 Position */ +#define PWM_PDMACTL_CHSEL4_5_Msk (0x1ul << PWM_PDMACTL_CHSEL4_5_Pos) /*!< PWM_T::PDMACTL: CHSEL4_5 Mask */ + +#define PWM_PDMACAP0_1_CAPBUF_Pos (0) /*!< PWM_T::PDMACAP0_1: CAPBUF Position */ +#define PWM_PDMACAP0_1_CAPBUF_Msk (0xfffful << PWM_PDMACAP0_1_CAPBUF_Pos) /*!< PWM_T::PDMACAP0_1: CAPBUF Mask */ + +#define PWM_PDMACAP2_3_CAPBUF_Pos (0) /*!< PWM_T::PDMACAP2_3: CAPBUF Position */ +#define PWM_PDMACAP2_3_CAPBUF_Msk (0xfffful << PWM_PDMACAP2_3_CAPBUF_Pos) /*!< PWM_T::PDMACAP2_3: CAPBUF Mask */ + +#define PWM_PDMACAP4_5_CAPBUF_Pos (0) /*!< PWM_T::PDMACAP4_5: CAPBUF Position */ +#define PWM_PDMACAP4_5_CAPBUF_Msk (0xfffful << PWM_PDMACAP4_5_CAPBUF_Pos) /*!< PWM_T::PDMACAP4_5: CAPBUF Mask */ + +#define PWM_CAPIEN_CAPRIEN0_Pos (0) /*!< PWM_T::CAPIEN: CAPRIEN0 Position */ +#define PWM_CAPIEN_CAPRIEN0_Msk (0x1ul << PWM_CAPIEN_CAPRIEN0_Pos) /*!< PWM_T::CAPIEN: CAPRIEN0 Mask */ + +#define PWM_CAPIEN_CAPRIEN1_Pos (1) /*!< PWM_T::CAPIEN: CAPRIEN1 Position */ +#define PWM_CAPIEN_CAPRIEN1_Msk (0x1ul << PWM_CAPIEN_CAPRIEN1_Pos) /*!< PWM_T::CAPIEN: CAPRIEN1 Mask */ + +#define PWM_CAPIEN_CAPRIEN2_Pos (2) /*!< PWM_T::CAPIEN: CAPRIEN2 Position */ +#define PWM_CAPIEN_CAPRIEN2_Msk (0x1ul << PWM_CAPIEN_CAPRIEN2_Pos) /*!< PWM_T::CAPIEN: CAPRIEN2 Mask */ + +#define PWM_CAPIEN_CAPRIEN3_Pos (3) /*!< PWM_T::CAPIEN: CAPRIEN3 Position */ +#define PWM_CAPIEN_CAPRIEN3_Msk (0x1ul << PWM_CAPIEN_CAPRIEN3_Pos) /*!< PWM_T::CAPIEN: CAPRIEN3 Mask */ + +#define PWM_CAPIEN_CAPRIEN4_Pos (4) /*!< PWM_T::CAPIEN: CAPRIEN4 Position */ +#define PWM_CAPIEN_CAPRIEN4_Msk (0x1ul << PWM_CAPIEN_CAPRIEN4_Pos) /*!< PWM_T::CAPIEN: CAPRIEN4 Mask */ + +#define PWM_CAPIEN_CAPRIEN5_Pos (5) /*!< PWM_T::CAPIEN: CAPRIEN5 Position */ +#define PWM_CAPIEN_CAPRIEN5_Msk (0x1ul << PWM_CAPIEN_CAPRIEN5_Pos) /*!< PWM_T::CAPIEN: CAPRIEN5 Mask */ + +#define PWM_CAPIEN_CAPFIEN0_Pos (8) /*!< PWM_T::CAPIEN: CAPFIEN0 Position */ +#define PWM_CAPIEN_CAPFIEN0_Msk (0x1ul << PWM_CAPIEN_CAPFIEN0_Pos) /*!< PWM_T::CAPIEN: CAPFIEN0 Mask */ + +#define PWM_CAPIEN_CAPFIEN1_Pos (9) /*!< PWM_T::CAPIEN: CAPFIEN1 Position */ +#define PWM_CAPIEN_CAPFIEN1_Msk (0x1ul << PWM_CAPIEN_CAPFIEN1_Pos) /*!< PWM_T::CAPIEN: CAPFIEN1 Mask */ + +#define PWM_CAPIEN_CAPFIEN2_Pos (10) /*!< PWM_T::CAPIEN: CAPFIEN2 Position */ +#define PWM_CAPIEN_CAPFIEN2_Msk (0x1ul << PWM_CAPIEN_CAPFIEN2_Pos) /*!< PWM_T::CAPIEN: CAPFIEN2 Mask */ + +#define PWM_CAPIEN_CAPFIEN3_Pos (11) /*!< PWM_T::CAPIEN: CAPFIEN3 Position */ +#define PWM_CAPIEN_CAPFIEN3_Msk (0x1ul << PWM_CAPIEN_CAPFIEN3_Pos) /*!< PWM_T::CAPIEN: CAPFIEN3 Mask */ + +#define PWM_CAPIEN_CAPFIEN4_Pos (12) /*!< PWM_T::CAPIEN: CAPFIEN4 Position */ +#define PWM_CAPIEN_CAPFIEN4_Msk (0x1ul << PWM_CAPIEN_CAPFIEN4_Pos) /*!< PWM_T::CAPIEN: CAPFIEN4 Mask */ + +#define PWM_CAPIEN_CAPFIEN5_Pos (13) /*!< PWM_T::CAPIEN: CAPFIEN5 Position */ +#define PWM_CAPIEN_CAPFIEN5_Msk (0x1ul << PWM_CAPIEN_CAPFIEN5_Pos) /*!< PWM_T::CAPIEN: CAPFIEN5 Mask */ + +#define PWM_CAPIF_CRLIF0_Pos (0) /*!< PWM_T::CAPIF: CRLIF0 Position */ +#define PWM_CAPIF_CRLIF0_Msk (0x1ul << PWM_CAPIF_CRLIF0_Pos) /*!< PWM_T::CAPIF: CRLIF0 Mask */ + +#define PWM_CAPIF_CRLIF1_Pos (1) /*!< PWM_T::CAPIF: CRLIF1 Position */ +#define PWM_CAPIF_CRLIF1_Msk (0x1ul << PWM_CAPIF_CRLIF1_Pos) /*!< PWM_T::CAPIF: CRLIF1 Mask */ + +#define PWM_CAPIF_CRLIF2_Pos (2) /*!< PWM_T::CAPIF: CRLIF2 Position */ +#define PWM_CAPIF_CRLIF2_Msk (0x1ul << PWM_CAPIF_CRLIF2_Pos) /*!< PWM_T::CAPIF: CRLIF2 Mask */ + +#define PWM_CAPIF_CRLIF3_Pos (3) /*!< PWM_T::CAPIF: CRLIF3 Position */ +#define PWM_CAPIF_CRLIF3_Msk (0x1ul << PWM_CAPIF_CRLIF3_Pos) /*!< PWM_T::CAPIF: CRLIF3 Mask */ + +#define PWM_CAPIF_CRLIF4_Pos (4) /*!< PWM_T::CAPIF: CRLIF4 Position */ +#define PWM_CAPIF_CRLIF4_Msk (0x1ul << PWM_CAPIF_CRLIF4_Pos) /*!< PWM_T::CAPIF: CRLIF4 Mask */ + +#define PWM_CAPIF_CRLIF5_Pos (5) /*!< PWM_T::CAPIF: CRLIF5 Position */ +#define PWM_CAPIF_CRLIF5_Msk (0x1ul << PWM_CAPIF_CRLIF5_Pos) /*!< PWM_T::CAPIF: CRLIF5 Mask */ + +#define PWM_CAPIF_CFLIF0_Pos (8) /*!< PWM_T::CAPIF: CFLIF0 Position */ +#define PWM_CAPIF_CFLIF0_Msk (0x1ul << PWM_CAPIF_CFLIF0_Pos) /*!< PWM_T::CAPIF: CFLIF0 Mask */ + +#define PWM_CAPIF_CFLIF1_Pos (9) /*!< PWM_T::CAPIF: CFLIF1 Position */ +#define PWM_CAPIF_CFLIF1_Msk (0x1ul << PWM_CAPIF_CFLIF1_Pos) /*!< PWM_T::CAPIF: CFLIF1 Mask */ + +#define PWM_CAPIF_CFLIF2_Pos (10) /*!< PWM_T::CAPIF: CFLIF2 Position */ +#define PWM_CAPIF_CFLIF2_Msk (0x1ul << PWM_CAPIF_CFLIF2_Pos) /*!< PWM_T::CAPIF: CFLIF2 Mask */ + +#define PWM_CAPIF_CFLIF3_Pos (11) /*!< PWM_T::CAPIF: CFLIF3 Position */ +#define PWM_CAPIF_CFLIF3_Msk (0x1ul << PWM_CAPIF_CFLIF3_Pos) /*!< PWM_T::CAPIF: CFLIF3 Mask */ + +#define PWM_CAPIF_CFLIF4_Pos (12) /*!< PWM_T::CAPIF: CFLIF4 Position */ +#define PWM_CAPIF_CFLIF4_Msk (0x1ul << PWM_CAPIF_CFLIF4_Pos) /*!< PWM_T::CAPIF: CFLIF4 Mask */ + +#define PWM_CAPIF_CFLIF5_Pos (13) /*!< PWM_T::CAPIF: CFLIF5 Position */ +#define PWM_CAPIF_CFLIF5_Msk (0x1ul << PWM_CAPIF_CFLIF5_Pos) /*!< PWM_T::CAPIF: CFLIF5 Mask */ + +#define PWM_PBUF_PBUF_Pos (0) /*!< PWM_T::PBUF: PBUF Position */ +#define PWM_PBUF_PBUF_Msk (0xfffful << PWM_PBUF_PBUF_Pos) /*!< PWM_T::PBUF: PBUF Mask */ + +#define PWM_CMPBUF_CMPBUF_Pos (0) /*!< PWM_T::CMPBUF: CMPBUF Position */ +#define PWM_CMPBUF_CMPBUF_Msk (0xfffful << PWM_CMPBUF_CMPBUF_Pos) /*!< PWM_T::CMPBUF: CMPBUF Mask */ + +/**@}*/ /* PWM_CONST */ +/**@}*/ /* end of PWM register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __PWM_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/qspi_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/qspi_reg.h new file mode 100644 index 0000000000..978b29c9a3 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/qspi_reg.h @@ -0,0 +1,586 @@ +/**************************************************************************//** + * @file qspi_reg.h + * @version V1.00 + * @brief QSPI register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __QSPI_REG_H__ +#define __QSPI_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup QSPI Quad Serial Peripheral Interface Controller (QSPI) + Memory Mapped Structure for QSPI Controller +@{ */ +typedef struct +{ + + + /** + * @var QSPI_T::CTL + * Offset: 0x00 QSPI Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SPIEN |QSPI Transfer Control Enable Bit + * | | |In Master mode, the transfer will start when there is data in the FIFO buffer after this bit is set to 1. + * | | |In Slave mode, this device is ready to receive data when this bit is set to 1. + * | | |0 = Transfer control Disabled. + * | | |1 = Transfer control Enabled. + * | | |Note: Before changing the configurations of QSPIx_CTL, QSPIx_CLKDIV, QSPIx_SSCTL and QSPIx_FIFOCTL registers, user shall clear the SPIEN (QSPIx_CTL[0]) and confirm the SPIENSTS (QSPIx_STATUS[15]) is 0. + * |[1] |RXNEG |Receive on Negative Edge + * | | |0 = Received data input signal is latched on the rising edge of QSPI bus clock. + * | | |1 = Received data input signal is latched on the falling edge of QSPI bus clock. + * |[2] |TXNEG |Transmit on Negative Edge + * | | |0 = Transmitted data output signal is changed on the rising edge of QSPI bus clock. + * | | |1 = Transmitted data output signal is changed on the falling edge of QSPI bus clock. + * |[3] |CLKPOL |Clock Polarity + * | | |0 = QSPI bus clock is idle low. + * | | |1 = QSPI bus clock is idle high. + * |[7:4] |SUSPITV |Suspend Interval (Master Only) + * | | |The four bits provide configurable suspend interval between two successive transmit/receive transaction in a transfer. + * | | |The definition of the suspend interval is the interval between the last clock edge of the preceding transaction word and the first clock edge of the following transaction word. + * | | |The default value is 0x3. + * | | |The period of the suspend interval is obtained according to the following equation. + * | | |(SUSPITV[3:0] + 0.5) * period of QSPICLK clock cycle + * | | |Example: + * | | |SUSPITV = 0x0 .... 0.5 QSPICLK clock cycle. + * | | |SUSPITV = 0x1 .... 1.5 QSPICLK clock cycle. + * | | |..... + * | | |SUSPITV = 0xE .... 14.5 QSPICLK clock cycle. + * | | |SUSPITV = 0xF .... 15.5 QSPICLK clock cycle. + * |[12:8] |DWIDTH |Data Width + * | | |This field specifies how many bits can be transmitted / received in one transaction. + * | | |The minimum bit length is 8 bits and can up to 32 bits. + * | | |DWIDTH = 0x08 .... 8 bits. + * | | |DWIDTH = 0x09 .... 9 bits. + * | | |..... + * | | |DWIDTH = 0x1F .... 31 bits. + * | | |DWIDTH = 0x00 .... 32 bits. + * |[13] |LSB |Send LSB First + * | | |0 = The MSB, which bit of transmit/receive register depends on the setting of DWIDTH, is transmitted/received first. + * | | |1 = The LSB, bit 0 of the QSPI TX register, is sent first to the QSPI data output pin, and the first bit received from the QSPI data input pin will be put in the LSB position of the RX register (bit 0 of QSPI_RX). + * |[14] |HALFDPX |QSPI Half-duplex Transfer Enable Bit + * | | |This bit is used to select full-duplex or half-duplex for QSPI transfer. + * | | |The bit field DATDIR (QSPIx_CTL[20]) can be used to set the data direction in half-duplex transfer. + * | | |0 = QSPI operates in full-duplex transfer. + * | | |1 = QSPI operates in half-duplex transfer. + * |[15] |RXONLY |Receive-only Mode Enable Bit (Master Only) + * | | |This bit field is only available in Master mode. + * | | |In receive-only mode, QSPI Master will generate QSPI bus clock continuously for receiving data bit from QSPI slave device and assert the BUSY status. + * | | |0 = Receive-only mode Disabled. + * | | |1 = Receive-only mode Enabled. + * |[16] |TWOBIT |2-bit Transfer Mode Enable Bit + * | | |0 = 2-Bit Transfer mode Disabled. + * | | |1 = 2-Bit Transfer mode Enabled. + * | | |Note: When 2-Bit Transfer mode is enabled, the first serial transmitted bit data is from the first FIFO buffer data, and the 2nd serial transmitted bit data is from the second FIFO buffer data. + * | | |As the same as transmitted function, the first received bit data is stored into the first FIFO buffer and the 2nd received bit data is stored into the second FIFO buffer at the same time. + * |[17] |UNITIEN |Unit Transfer Interrupt Enable Bit + * | | |0 = QSPI unit transfer interrupt Disabled. + * | | |1 = QSPI unit transfer interrupt Enabled. + * |[18] |SLAVE |Slave Mode Control + * | | |0 = Master mode. + * | | |1 = Slave mode. + * |[19] |REORDER |Byte Reorder Function Enable Bit + * | | |0 = Byte Reorder function Disabled. + * | | |1 = Byte Reorder function Enabled. + * | | |A byte suspend interval will be inserted among each byte. + * | | |The period of the byte suspend interval depends on the setting of SUSPITV. + * | | |Note: Byte Reorder function is only available if DWIDTH is defined as 16, 24, and 32 bits. + * |[20] |DATDIR |Data Port Direction Control + * | | |This bit is used to select the data input/output direction in half-duplex transfer and Dual/Quad transfer. + * | | |0 = QSPI data is input direction. + * | | |1 = QSPI data is output direction. + * |[21] |DUALIOEN |Dual I/O Mode Enable Bit + * | | |0 = Dual I/O mode Disabled. + * | | |1 = Dual I/O mode Enabled. + * |[22] |QUADIOEN |Quad I/O Mode Enable Bit + * | | |0 = Quad I/O mode Disabled. + * | | |1 = Quad I/O mode Enabled. + * @var QSPI_T::CLKDIV + * Offset: 0x04 QSPI Clock Divider Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |DIVIDER |Clock Divider + * | | |The value in this field is the frequency divider for generating the peripheral clock, fspi_eclk, and the QSPI bus clock of QSPI Master. + * | | |The frequency is obtained according to the following equation. + * | | |fspi_eclk = fspi_clock_src / (DIVIDER + 1) + * | | |where + * | | |fspi_clock_src is the peripheral clock source, which is defined in the clock control register, CLK_CLKSEL2. + * | | |Note: The time interval must be larger than or equal 8 peripheral clock cycles between releasing QSPI IP software reset and setting this clock divider register. + * @var QSPI_T::SSCTL + * Offset: 0x08 QSPI Slave Select Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SS |Slave Selection Control (Master Only) + * | | |If AUTOSS bit is cleared to 0, + * | | |0 = set the QSPIx_SS line to inactive state. + * | | |1 = set the QSPIx_SS line to active state. + * | | |If the AUTOSS bit is set to 1, + * | | |0 = Keep the QSPIx_SS line at inactive state. + * | | |1 = QSPIx_SS line will be automatically driven to active state for the duration of data transfer, and will be driven to inactive state for the rest of the time. + * | | |The active state of QSPIx_SS is specified in SSACTPOL (QSPIx_SSCTL[2]). + * |[2] |SSACTPOL |Slave Selection Active Polarity + * | | |This bit defines the active polarity of slave selection signal (QSPIx_SS). + * | | |0 = The slave selection signal QSPIx_SS is active low. + * | | |1 = The slave selection signal QSPIx_SS is active high. + * |[3] |AUTOSS |Automatic Slave Selection Function Enable Bit (Master Only) + * | | |0 = Automatic slave selection function Disabled + * | | |Slave selection signal will be asserted/de-asserted according to SS (QSPIx_SSCTL[0]). + * | | |1 = Automatic slave selection function Enabled. + * |[4] |SLV3WIRE |Slave 3-wire Mode Enable Bit + * | | |In Slave 3-wire mode, the QSPI controller can work with 3-wire interface including QSPI0_CLK, QSPI0_MISO and QSPI0_MOSI pins. + * | | |0 = 4-wire bi-direction interface. + * | | |1 = 3-wire bi-direction interface. + * |[5] |SLVTOIEN |Slave Mode Time-out Interrupt Enable Bit + * | | |0 = Slave mode time-out interrupt Disabled. + * | | |1 = Slave mode time-out interrupt Enabled. + * |[6] |SLVTORST |Slave Mode Time-out Reset Control + * | | |0 = When Slave mode time-out event occurs, the TX and RX control circuit will not be reset. + * | | |1 = When Slave mode time-out event occurs, the TX and RX control circuit will be reset by hardware. + * |[8] |SLVBEIEN |Slave Mode Bit Count Error Interrupt Enable Bit + * | | |0 = Slave mode bit count error interrupt Disabled. + * | | |1 = Slave mode bit count error interrupt Enabled. + * |[9] |SLVURIEN |Slave Mode TX Under Run Interrupt Enable Bit + * | | |0 = Slave mode TX under run interrupt Disabled. + * | | |1 = Slave mode TX under run interrupt Enabled. + * |[12] |SSACTIEN |Slave Select Active Interrupt Enable Bit + * | | |0 = Slave select active interrupt Disabled. + * | | |1 = Slave select active interrupt Enabled. + * |[13] |SSINAIEN |Slave Select Inactive Interrupt Enable Bit + * | | |0 = Slave select inactive interrupt Disabled. + * | | |1 = Slave select inactive interrupt Enabled. + * |[31:16] |SLVTOCNT |Slave Mode Time-out Period + * | | |In Slave mode, these bits indicate the time-out period when there is bus clock input during slave select active. + * | | |The clock source of the time-out counter is Slave peripheral clock. + * | | |If the value is 0, it indicates the slave mode time-out function is disabled. + * @var QSPI_T::PDMACTL + * Offset: 0x0C QSPI PDMA Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |TXPDMAEN |Transmit PDMA Enable Bit + * | | |0 = Transmit PDMA function Disabled. + * | | |1 = Transmit PDMA function Enabled. + * | | |Note: In QSPI Master mode with full duplex transfer, if both TX and RX PDMA functions are enabled, RX PDMA function cannot be enabled prior to TX PDMA function. + * | | |User can enable TX PDMA function firstly or enable both functions simultaneously. + * |[1] |RXPDMAEN |Receive PDMA Enable Bit + * | | |0 = Receive PDMA function Disabled. + * | | |1 = Receive PDMA function Enabled. + * |[2] |PDMARST |PDMA Reset + * | | |0 = No effect. + * | | |1 = Reset the PDMA control logic of the QSPI controller. This bit will be automatically cleared to 0. + * @var QSPI_T::FIFOCTL + * Offset: 0x10 QSPI FIFO Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RXRST |Receive Reset + * | | |0 = No effect. + * | | |1 = Reset receive FIFO pointer and receive circuit. + * | | |The RXFULL bit will be cleared to 0 and the RXEMPTY bit will be set to 1. + * | | |This bit will be cleared to 0 by hardware about 3 system clock cycles + 2 peripheral clock cycles after it is set to 1. + * | | |User can read TXRXRST (QSPIx_STATUS[23]) to check if reset is accomplished or not. + * |[1] |TXRST |Transmit Reset + * | | |0 = No effect. + * | | |1 = Reset transmit FIFO pointer and transmit circuit. + * | | |The TXFULL bit will be cleared to 0 and the TXEMPTY bit will be set to 1. + * | | |This bit will be cleared to 0 by hardware about 3 system clock cycles + 2 peripheral clock cycles after it is set to 1. + * | | |User can read TXRXRST (QSPIx_STATUS[23]) to check if reset is accomplished or not. + * | | |Note: If TX underflow event occurs in QSPI Slave mode, this bit can be used to make QSPI return to idle state. + * |[2] |RXTHIEN |Receive FIFO Threshold Interrupt Enable Bit + * | | |0 = RX FIFO threshold interrupt Disabled. + * | | |1 = RX FIFO threshold interrupt Enabled. + * |[3] |TXTHIEN |Transmit FIFO Threshold Interrupt Enable Bit + * | | |0 = TX FIFO threshold interrupt Disabled. + * | | |1 = TX FIFO threshold interrupt Enabled. + * |[4] |RXTOIEN |Receive Time-out Interrupt Enable Bit + * | | |0 = Receive time-out interrupt Disabled. + * | | |1 = Receive time-out interrupt Enabled. + * |[5] |RXOVIEN |Receive FIFO Overrun Interrupt Enable Bit + * | | |0 = Receive FIFO overrun interrupt Disabled. + * | | |1 = Receive FIFO overrun interrupt Enabled. + * |[6] |TXUFPOL |TX Underflow Data Polarity + * | | |0 = The QSPI data out is keep 0 if there is TX underflow event in Slave mode. + * | | |1 = The QSPI data out is keep 1 if there is TX underflow event in Slave mode. + * | | |Note: + * | | |1. The TX underflow event occurs if there is no any data in TX FIFO when the slave selection signal is active. + * | | |2. When TX underflow event occurs, QSPIx_MISO pin state will be determined by this setting even though TX FIFO is not empty afterward. + * | | |Data stored in TX FIFO will be sent through QSPIx_MISO pin in the next transfer frame. + * |[7] |TXUFIEN |TX Underflow Interrupt Enable Bit + * | | |When TX underflow event occurs in Slave mode, TXUFIF (QSPIx_STATUS[19]) will be set to 1 + * | | |This bit is used to enable the TX underflow interrupt. + * | | |0 = Slave TX underflow interrupt Disabled. + * | | |1 = Slave TX underflow interrupt Enabled. + * |[8] |RXFBCLR |Receive FIFO Buffer Clear + * | | |0 = No effect. + * | | |1 = Clear receive FIFO pointer. + * | | |The RXFULL bit will be cleared to 0 and the RXEMPTY bit will be set to 1. + * | | |This bit will be cleared to 0 by hardware about 1 system clock after it is set to 1. + * | | |Note: The RX shift register will not be cleared. + * |[9] |TXFBCLR |Transmit FIFO Buffer Clear + * | | |0 = No effect. + * | | |1 = Clear transmit FIFO pointer. + * | | |The TXFULL bit will be cleared to 0 and the TXEMPTY bit will be set to 1. + * | | |This bit will be cleared to 0 by hardware about 1 system clock after it is set to 1. + * | | |Note: The TX shift register will not be cleared. + * |[26:24] |RXTH |Receive FIFO Threshold + * | | |If the valid data count of the receive FIFO buffer is larger than the RXTH setting, the RXTHIF bit will be set to 1, else the RXTHIF bit will be cleared to 0. + * |[30:28] |TXTH |Transmit FIFO Threshold + * | | |If the valid data count of the transmit FIFO buffer is less than or equal to the TXTH setting, the TXTHIF bit will be set to 1, else the TXTHIF bit will be cleared to 0. + * @var QSPI_T::STATUS + * Offset: 0x14 QSPI Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BUSY |Busy Status (Read Only) + * | | |0 = QSPI controller is in idle state. + * | | |1 = QSPI controller is in busy state. + * | | |The following lists the bus busy conditions: + * | | |a. QSPIx_CTL[0] = 1 and TXEMPTY = 0. + * | | |b. For QSPI Master mode, QSPIx_CTL[0] = 1 and TXEMPTY = 1 but the current transaction is not finished yet. + * | | |c. For QSPI Master mode, QSPIx_CTL[0] = 1 and RXONLY = 1. + * | | |d. For QSPI Slave mode, the QSPIx_CTL[0] = 1 and there is serial clock input into the QSPI core logic when slave select is active. + * | | |e. For QSPI Slave mode, the QSPIx_CTL[0] = 1 and the transmit buffer or transmit shift register is not empty even if the slave select is inactive. + * |[1] |UNITIF |Unit Transfer Interrupt Flag + * | | |0 = No transaction has been finished since this bit was cleared to 0. + * | | |1 = QSPI controller has finished one unit transfer. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[2] |SSACTIF |Slave Select Active Interrupt Flag + * | | |0 = Slave select active interrupt was cleared or not occurred. + * | | |1 = Slave select active interrupt event occurred. + * | | |Note: Only available in Slave mode. This bit will be cleared by writing 1 to it. + * |[3] |SSINAIF |Slave Select Inactive Interrupt Flag + * | | |0 = Slave select inactive interrupt was cleared or not occurred. + * | | |1 = Slave select inactive interrupt event occurred. + * | | |Note: Only available in Slave mode. This bit will be cleared by writing 1 to it. + * |[4] |SSLINE |Slave Select Line Bus Status (Read Only) + * | | |0 = The slave select line status is 0. + * | | |1 = The slave select line status is 1. + * | | |Note: This bit is only available in Slave mode. + * | | |If SSACTPOL (QSPIx_SSCTL[2]) is set 0, and the SSLINE is 1, the QSPI slave select is in inactive status. + * |[5] |SLVTOIF |Slave Time-out Interrupt Flag + * | | |When the slave select is active and the value of SLVTOCNT is not 0, as the bus clock is detected, the slave time-out counter in QSPI controller logic will be started. + * | | |When the value of time-out counter is greater than or equal to the value of SLVTOCNT (QSPI_SSCTL[31:16]) before one transaction is done, the slave time-out interrupt event will be asserted. + * | | |0 = Slave time-out is not active. + * | | |1 = Slave time-out is active. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[6] |SLVBEIF |Slave Mode Bit Count Error Interrupt Flag + * | | |In Slave mode, when the slave select line goes to inactive state, if bit counter is mismatch with DWIDTH, this interrupt flag will be set to 1. + * | | |0 = No Slave mode bit count error event. + * | | |1 = Slave mode bit count error event occurs. + * | | |Note: If the slave select active but there is no any bus clock input, the SLVBEIF also active when the slave select goes to inactive state. + * | | |This bit will be cleared by writing 1 to it. + * |[7] |SLVURIF |Slave Mode TX Under Run Interrupt Flag + * | | |In Slave mode, if TX underflow event occurs and the slave select line goes to inactive state, this interrupt flag will be set to 1. + * | | |0 = No Slave TX under run event. + * | | |1 = Slave TX under run event occurs. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[8] |RXEMPTY |Receive FIFO Buffer Empty Indicator (Read Only) + * | | |0 = Receive FIFO buffer is not empty. + * | | |1 = Receive FIFO buffer is empty. + * |[9] |RXFULL |Receive FIFO Buffer Full Indicator (Read Only) + * | | |0 = Receive FIFO buffer is not full. + * | | |1 = Receive FIFO buffer is full. + * |[10] |RXTHIF |Receive FIFO Threshold Interrupt Flag (Read Only) + * | | |0 = The valid data count within the receive FIFO buffer is smaller than or equal to the setting value of RXTH. + * | | |1 = The valid data count within the receive FIFO buffer is larger than the setting value of RXTH. + * |[11] |RXOVIF |Receive FIFO Overrun Interrupt Flag + * | | |When the receive FIFO buffer is full, the follow-up data will be dropped and this bit will be set to 1. + * | | |0 = No FIFO is overrun. + * | | |1 = Receive FIFO is overrun. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[12] |RXTOIF |Receive Time-out Interrupt Flag + * | | |0 = No receive FIFO time-out event. + * | | |1 = Receive FIFO buffer is not empty and no read operation on receive FIFO buffer over 64 QSPI peripheral clock periods in Master mode or over 576 QSPI peripheral clock periods in Slave mode. + * | | |When the received FIFO buffer is read by software, the time-out status will be cleared automatically. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[15] |SPIENSTS |QSPI Enable Status (Read Only) + * | | |0 = The QSPI controller is disabled. + * | | |1 = The QSPI controller is enabled. + * | | |Note: The QSPI peripheral clock is asynchronous with the system clock. + * | | |In order to make sure the QSPI control logic is disabled, this bit indicates the real status of QSPI controller. + * |[16] |TXEMPTY |Transmit FIFO Buffer Empty Indicator (Read Only) + * | | |0 = Transmit FIFO buffer is not empty. + * | | |1 = Transmit FIFO buffer is empty. + * |[17] |TXFULL |Transmit FIFO Buffer Full Indicator (Read Only) + * | | |0 = Transmit FIFO buffer is not full. + * | | |1 = Transmit FIFO buffer is full. + * |[18] |TXTHIF |Transmit FIFO Threshold Interrupt Flag (Read Only) + * | | |0 = The valid data count within the transmit FIFO buffer is larger than the setting value of TXTH. + * | | |1 = The valid data count within the transmit FIFO buffer is less than or equal to the setting value of TXTH. + * |[19] |TXUFIF |TX Underflow Interrupt Flag + * | | |When the TX underflow event occurs, this bit will be set to 1, the state of data output pin depends on the setting of TXUFPOL. + * | | |0 = No effect. + * | | |1 = No data in Transmit FIFO and TX shift register when the slave selection signal is active. + * | | |Note 1: This bit will be cleared by writing 1 to it. + * | | |Note 2: If reset slave's transmission circuit when slave selection signal is active, this flag will be set to 1 after 2 peripheral clock cycles + 3 system clock cycles since the reset operation is done. + * |[23] |TXRXRST |TX or RX Reset Status (Read Only) + * | | |0 = The reset function of TXRST or RXRST is done. + * | | |1 = Doing the reset function of TXRST or RXRST. + * | | |Note: Both the reset operations of TXRST and RXRST need 3 system clock cycles + 2 peripheral clock cycles. + * | | |User can check the status of this bit to monitor the reset function is doing or done. + * |[27:24] |RXCNT |Receive FIFO Data Count (Read Only) + * | | |This bit field indicates the valid data count of receive FIFO buffer. + * |[31:28] |TXCNT |Transmit FIFO Data Count (Read Only) + * | | |This bit field indicates the valid data count of transmit FIFO buffer. + * @var QSPI_T::TX + * Offset: 0x20 QSPI Data Transmit Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |TX |Data Transmit Register + * | | |The data transmit registers pass through the transmitted data into the 8-level transmit FIFO buffers. + * | | |The number of valid bits depends on the setting of DWIDTH (QSPIx_CTL[12:8]). + * | | |If DWIDTH is set to 0x08, the bits TX[7:0] will be transmitted. + * | | |If DWIDTH is set to 0x00 , the QSPI controller will perform a 32-bit transfer. + * | | |Note: In Master mode, QSPI controller will start to transfer the QSPI bus clock after 1 APB clock and 6 peripheral clock cycles after user writes to this register. + * @var QSPI_T::RX + * Offset: 0x30 QSPI Data Receive Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |RX |Data Receive Register (Read Only) + * | | |There are 8-level FIFO buffers in this controller. + * | | |The data receive register holds the data received from QSPI data input pin. + * | | |If the RXEMPTY (QSPIx_STATUS[8]) is not set to 1, the receive FIFO buffers can be accessed through software by reading this register. + */ + __IO uint32_t CTL; /*!< [0x0000] QSPI Control Register */ + __IO uint32_t CLKDIV; /*!< [0x0004] QSPI Clock Divider Register */ + __IO uint32_t SSCTL; /*!< [0x0008] QSPI Slave Select Control Register */ + __IO uint32_t PDMACTL; /*!< [0x000c] QSPI PDMA Control Register */ + __IO uint32_t FIFOCTL; /*!< [0x0010] QSPI FIFO Control Register */ + __IO uint32_t STATUS; /*!< [0x0014] QSPI Status Register */ + __I uint32_t RESERVE0[2]; + __O uint32_t TX; /*!< [0x0020] QSPI Data Transmit Register */ + __I uint32_t RESERVE1[3]; + __I uint32_t RX; /*!< [0x0030] QSPI Data Receive Register */ + +} QSPI_T; + +/** + @addtogroup QSPI_CONST QSPI Bit Field Definition + Constant Definitions for QSPI Controller +@{ */ + +#define QSPI_CTL_SPIEN_Pos (0) /*!< QSPI_T::CTL: SPIEN Position */ +#define QSPI_CTL_SPIEN_Msk (0x1ul << QSPI_CTL_SPIEN_Pos) /*!< QSPI_T::CTL: SPIEN Mask */ + +#define QSPI_CTL_RXNEG_Pos (1) /*!< QSPI_T::CTL: RXNEG Position */ +#define QSPI_CTL_RXNEG_Msk (0x1ul << QSPI_CTL_RXNEG_Pos) /*!< QSPI_T::CTL: RXNEG Mask */ + +#define QSPI_CTL_TXNEG_Pos (2) /*!< QSPI_T::CTL: TXNEG Position */ +#define QSPI_CTL_TXNEG_Msk (0x1ul << QSPI_CTL_TXNEG_Pos) /*!< QSPI_T::CTL: TXNEG Mask */ + +#define QSPI_CTL_CLKPOL_Pos (3) /*!< QSPI_T::CTL: CLKPOL Position */ +#define QSPI_CTL_CLKPOL_Msk (0x1ul << QSPI_CTL_CLKPOL_Pos) /*!< QSPI_T::CTL: CLKPOL Mask */ + +#define QSPI_CTL_SUSPITV_Pos (4) /*!< QSPI_T::CTL: SUSPITV Position */ +#define QSPI_CTL_SUSPITV_Msk (0xful << QSPI_CTL_SUSPITV_Pos) /*!< QSPI_T::CTL: SUSPITV Mask */ + +#define QSPI_CTL_DWIDTH_Pos (8) /*!< QSPI_T::CTL: DWIDTH Position */ +#define QSPI_CTL_DWIDTH_Msk (0x1ful << QSPI_CTL_DWIDTH_Pos) /*!< QSPI_T::CTL: DWIDTH Mask */ + +#define QSPI_CTL_LSB_Pos (13) /*!< QSPI_T::CTL: LSB Position */ +#define QSPI_CTL_LSB_Msk (0x1ul << QSPI_CTL_LSB_Pos) /*!< QSPI_T::CTL: LSB Mask */ + +#define QSPI_CTL_HALFDPX_Pos (14) /*!< QSPI_T::CTL: HALFDPX Position */ +#define QSPI_CTL_HALFDPX_Msk (0x1ul << QSPI_CTL_HALFDPX_Pos) /*!< QSPI_T::CTL: HALFDPX Mask */ + +#define QSPI_CTL_RXONLY_Pos (15) /*!< QSPI_T::CTL: RXONLY Position */ +#define QSPI_CTL_RXONLY_Msk (0x1ul << QSPI_CTL_RXONLY_Pos) /*!< QSPI_T::CTL: RXONLY Mask */ + +#define QSPI_CTL_TWOBIT_Pos (16) /*!< QSPI_T::CTL: TWOBIT Position */ +#define QSPI_CTL_TWOBIT_Msk (0x1ul << QSPI_CTL_TWOBIT_Pos) /*!< QSPI_T::CTL: TWOBIT Mask */ + +#define QSPI_CTL_UNITIEN_Pos (17) /*!< QSPI_T::CTL: UNITIEN Position */ +#define QSPI_CTL_UNITIEN_Msk (0x1ul << QSPI_CTL_UNITIEN_Pos) /*!< QSPI_T::CTL: UNITIEN Mask */ + +#define QSPI_CTL_SLAVE_Pos (18) /*!< QSPI_T::CTL: SLAVE Position */ +#define QSPI_CTL_SLAVE_Msk (0x1ul << QSPI_CTL_SLAVE_Pos) /*!< QSPI_T::CTL: SLAVE Mask */ + +#define QSPI_CTL_REORDER_Pos (19) /*!< QSPI_T::CTL: REORDER Position */ +#define QSPI_CTL_REORDER_Msk (0x1ul << QSPI_CTL_REORDER_Pos) /*!< QSPI_T::CTL: REORDER Mask */ + +#define QSPI_CTL_DATDIR_Pos (20) /*!< QSPI_T::CTL: DATDIR Position */ +#define QSPI_CTL_DATDIR_Msk (0x1ul << QSPI_CTL_DATDIR_Pos) /*!< QSPI_T::CTL: DATDIR Mask */ + +#define QSPI_CTL_DUALIOEN_Pos (21) /*!< QSPI_T::CTL: DUALIOEN Position */ +#define QSPI_CTL_DUALIOEN_Msk (0x1ul << QSPI_CTL_DUALIOEN_Pos) /*!< QSPI_T::CTL: DUALIOEN Mask */ + +#define QSPI_CTL_QUADIOEN_Pos (22) /*!< QSPI_T::CTL: QUADIOEN Position */ +#define QSPI_CTL_QUADIOEN_Msk (0x1ul << QSPI_CTL_QUADIOEN_Pos) /*!< QSPI_T::CTL: QUADIOEN Mask */ + +#define QSPI_CLKDIV_DIVIDER_Pos (0) /*!< QSPI_T::CLKDIV: DIVIDER Position */ +#define QSPI_CLKDIV_DIVIDER_Msk (0x1fful << QSPI_CLKDIV_DIVIDER_Pos) /*!< QSPI_T::CLKDIV: DIVIDER Mask */ + +#define QSPI_SSCTL_SS_Pos (0) /*!< QSPI_T::SSCTL: SS Position */ +#define QSPI_SSCTL_SS_Msk (0x1ul << QSPI_SSCTL_SS_Pos) /*!< QSPI_T::SSCTL: SS Mask */ + +#define QSPI_SSCTL_SSACTPOL_Pos (2) /*!< QSPI_T::SSCTL: SSACTPOL Position */ +#define QSPI_SSCTL_SSACTPOL_Msk (0x1ul << QSPI_SSCTL_SSACTPOL_Pos) /*!< QSPI_T::SSCTL: SSACTPOL Mask */ + +#define QSPI_SSCTL_AUTOSS_Pos (3) /*!< QSPI_T::SSCTL: AUTOSS Position */ +#define QSPI_SSCTL_AUTOSS_Msk (0x1ul << QSPI_SSCTL_AUTOSS_Pos) /*!< QSPI_T::SSCTL: AUTOSS Mask */ + +#define QSPI_SSCTL_SLV3WIRE_Pos (4) /*!< QSPI_T::SSCTL: SLV3WIRE Position */ +#define QSPI_SSCTL_SLV3WIRE_Msk (0x1ul << QSPI_SSCTL_SLV3WIRE_Pos) /*!< QSPI_T::SSCTL: SLV3WIRE Mask */ + +#define QSPI_SSCTL_SLVTOIEN_Pos (5) /*!< QSPI_T::SSCTL: SLVTOIEN Position */ +#define QSPI_SSCTL_SLVTOIEN_Msk (0x1ul << QSPI_SSCTL_SLVTOIEN_Pos) /*!< QSPI_T::SSCTL: SLVTOIEN Mask */ + +#define QSPI_SSCTL_SLVTORST_Pos (6) /*!< QSPI_T::SSCTL: SLVTORST Position */ +#define QSPI_SSCTL_SLVTORST_Msk (0x1ul << QSPI_SSCTL_SLVTORST_Pos) /*!< QSPI_T::SSCTL: SLVTORST Mask */ + +#define QSPI_SSCTL_SLVBEIEN_Pos (8) /*!< QSPI_T::SSCTL: SLVBEIEN Position */ +#define QSPI_SSCTL_SLVBEIEN_Msk (0x1ul << QSPI_SSCTL_SLVBEIEN_Pos) /*!< QSPI_T::SSCTL: SLVBEIEN Mask */ + +#define QSPI_SSCTL_SLVURIEN_Pos (9) /*!< QSPI_T::SSCTL: SLVURIEN Position */ +#define QSPI_SSCTL_SLVURIEN_Msk (0x1ul << QSPI_SSCTL_SLVURIEN_Pos) /*!< QSPI_T::SSCTL: SLVURIEN Mask */ + +#define QSPI_SSCTL_SSACTIEN_Pos (12) /*!< QSPI_T::SSCTL: SSACTIEN Position */ +#define QSPI_SSCTL_SSACTIEN_Msk (0x1ul << QSPI_SSCTL_SSACTIEN_Pos) /*!< QSPI_T::SSCTL: SSACTIEN Mask */ + +#define QSPI_SSCTL_SSINAIEN_Pos (13) /*!< QSPI_T::SSCTL: SSINAIEN Position */ +#define QSPI_SSCTL_SSINAIEN_Msk (0x1ul << QSPI_SSCTL_SSINAIEN_Pos) /*!< QSPI_T::SSCTL: SSINAIEN Mask */ + +#define QSPI_SSCTL_SLVTOCNT_Pos (16) /*!< QSPI_T::SSCTL: SLVTOCNT Position */ +#define QSPI_SSCTL_SLVTOCNT_Msk (0xfffful << QSPI_SSCTL_SLVTOCNT_Pos) /*!< QSPI_T::SSCTL: SLVTOCNT Mask */ + +#define QSPI_PDMACTL_TXPDMAEN_Pos (0) /*!< QSPI_T::PDMACTL: TXPDMAEN Position */ +#define QSPI_PDMACTL_TXPDMAEN_Msk (0x1ul << QSPI_PDMACTL_TXPDMAEN_Pos) /*!< QSPI_T::PDMACTL: TXPDMAEN Mask */ + +#define QSPI_PDMACTL_RXPDMAEN_Pos (1) /*!< QSPI_T::PDMACTL: RXPDMAEN Position */ +#define QSPI_PDMACTL_RXPDMAEN_Msk (0x1ul << QSPI_PDMACTL_RXPDMAEN_Pos) /*!< QSPI_T::PDMACTL: RXPDMAEN Mask */ + +#define QSPI_PDMACTL_PDMARST_Pos (2) /*!< QSPI_T::PDMACTL: PDMARST Position */ +#define QSPI_PDMACTL_PDMARST_Msk (0x1ul << QSPI_PDMACTL_PDMARST_Pos) /*!< QSPI_T::PDMACTL: PDMARST Mask */ + +#define QSPI_FIFOCTL_RXRST_Pos (0) /*!< QSPI_T::FIFOCTL: RXRST Position */ +#define QSPI_FIFOCTL_RXRST_Msk (0x1ul << QSPI_FIFOCTL_RXRST_Pos) /*!< QSPI_T::FIFOCTL: RXRST Mask */ + +#define QSPI_FIFOCTL_TXRST_Pos (1) /*!< QSPI_T::FIFOCTL: TXRST Position */ +#define QSPI_FIFOCTL_TXRST_Msk (0x1ul << QSPI_FIFOCTL_TXRST_Pos) /*!< QSPI_T::FIFOCTL: TXRST Mask */ + +#define QSPI_FIFOCTL_RXTHIEN_Pos (2) /*!< QSPI_T::FIFOCTL: RXTHIEN Position */ +#define QSPI_FIFOCTL_RXTHIEN_Msk (0x1ul << QSPI_FIFOCTL_RXTHIEN_Pos) /*!< QSPI_T::FIFOCTL: RXTHIEN Mask */ + +#define QSPI_FIFOCTL_TXTHIEN_Pos (3) /*!< QSPI_T::FIFOCTL: TXTHIEN Position */ +#define QSPI_FIFOCTL_TXTHIEN_Msk (0x1ul << QSPI_FIFOCTL_TXTHIEN_Pos) /*!< QSPI_T::FIFOCTL: TXTHIEN Mask */ + +#define QSPI_FIFOCTL_RXTOIEN_Pos (4) /*!< QSPI_T::FIFOCTL: RXTOIEN Position */ +#define QSPI_FIFOCTL_RXTOIEN_Msk (0x1ul << QSPI_FIFOCTL_RXTOIEN_Pos) /*!< QSPI_T::FIFOCTL: RXTOIEN Mask */ + +#define QSPI_FIFOCTL_RXOVIEN_Pos (5) /*!< QSPI_T::FIFOCTL: RXOVIEN Position */ +#define QSPI_FIFOCTL_RXOVIEN_Msk (0x1ul << QSPI_FIFOCTL_RXOVIEN_Pos) /*!< QSPI_T::FIFOCTL: RXOVIEN Mask */ + +#define QSPI_FIFOCTL_TXUFPOL_Pos (6) /*!< QSPI_T::FIFOCTL: TXUFPOL Position */ +#define QSPI_FIFOCTL_TXUFPOL_Msk (0x1ul << QSPI_FIFOCTL_TXUFPOL_Pos) /*!< QSPI_T::FIFOCTL: TXUFPOL Mask */ + +#define QSPI_FIFOCTL_TXUFIEN_Pos (7) /*!< QSPI_T::FIFOCTL: TXUFIEN Position */ +#define QSPI_FIFOCTL_TXUFIEN_Msk (0x1ul << QSPI_FIFOCTL_TXUFIEN_Pos) /*!< QSPI_T::FIFOCTL: TXUFIEN Mask */ + +#define QSPI_FIFOCTL_RXFBCLR_Pos (8) /*!< QSPI_T::FIFOCTL: RXFBCLR Position */ +#define QSPI_FIFOCTL_RXFBCLR_Msk (0x1ul << QSPI_FIFOCTL_RXFBCLR_Pos) /*!< QSPI_T::FIFOCTL: RXFBCLR Mask */ + +#define QSPI_FIFOCTL_TXFBCLR_Pos (9) /*!< QSPI_T::FIFOCTL: TXFBCLR Position */ +#define QSPI_FIFOCTL_TXFBCLR_Msk (0x1ul << QSPI_FIFOCTL_TXFBCLR_Pos) /*!< QSPI_T::FIFOCTL: TXFBCLR Mask */ + +#define QSPI_FIFOCTL_RXTH_Pos (24) /*!< QSPI_T::FIFOCTL: RXTH Position */ +#define QSPI_FIFOCTL_RXTH_Msk (0x7ul << QSPI_FIFOCTL_RXTH_Pos) /*!< QSPI_T::FIFOCTL: RXTH Mask */ + +#define QSPI_FIFOCTL_TXTH_Pos (28) /*!< QSPI_T::FIFOCTL: TXTH Position */ +#define QSPI_FIFOCTL_TXTH_Msk (0x7ul << QSPI_FIFOCTL_TXTH_Pos) /*!< QSPI_T::FIFOCTL: TXTH Mask */ + +#define QSPI_STATUS_BUSY_Pos (0) /*!< QSPI_T::STATUS: BUSY Position */ +#define QSPI_STATUS_BUSY_Msk (0x1ul << QSPI_STATUS_BUSY_Pos) /*!< QSPI_T::STATUS: BUSY Mask */ + +#define QSPI_STATUS_UNITIF_Pos (1) /*!< QSPI_T::STATUS: UNITIF Position */ +#define QSPI_STATUS_UNITIF_Msk (0x1ul << QSPI_STATUS_UNITIF_Pos) /*!< QSPI_T::STATUS: UNITIF Mask */ + +#define QSPI_STATUS_SSACTIF_Pos (2) /*!< QSPI_T::STATUS: SSACTIF Position */ +#define QSPI_STATUS_SSACTIF_Msk (0x1ul << QSPI_STATUS_SSACTIF_Pos) /*!< QSPI_T::STATUS: SSACTIF Mask */ + +#define QSPI_STATUS_SSINAIF_Pos (3) /*!< QSPI_T::STATUS: SSINAIF Position */ +#define QSPI_STATUS_SSINAIF_Msk (0x1ul << QSPI_STATUS_SSINAIF_Pos) /*!< QSPI_T::STATUS: SSINAIF Mask */ + +#define QSPI_STATUS_SSLINE_Pos (4) /*!< QSPI_T::STATUS: SSLINE Position */ +#define QSPI_STATUS_SSLINE_Msk (0x1ul << QSPI_STATUS_SSLINE_Pos) /*!< QSPI_T::STATUS: SSLINE Mask */ + +#define QSPI_STATUS_SLVTOIF_Pos (5) /*!< QSPI_T::STATUS: SLVTOIF Position */ +#define QSPI_STATUS_SLVTOIF_Msk (0x1ul << QSPI_STATUS_SLVTOIF_Pos) /*!< QSPI_T::STATUS: SLVTOIF Mask */ + +#define QSPI_STATUS_SLVBEIF_Pos (6) /*!< QSPI_T::STATUS: SLVBEIF Position */ +#define QSPI_STATUS_SLVBEIF_Msk (0x1ul << QSPI_STATUS_SLVBEIF_Pos) /*!< QSPI_T::STATUS: SLVBEIF Mask */ + +#define QSPI_STATUS_SLVURIF_Pos (7) /*!< QSPI_T::STATUS: SLVURIF Position */ +#define QSPI_STATUS_SLVURIF_Msk (0x1ul << QSPI_STATUS_SLVURIF_Pos) /*!< QSPI_T::STATUS: SLVURIF Mask */ + +#define QSPI_STATUS_RXEMPTY_Pos (8) /*!< QSPI_T::STATUS: RXEMPTY Position */ +#define QSPI_STATUS_RXEMPTY_Msk (0x1ul << QSPI_STATUS_RXEMPTY_Pos) /*!< QSPI_T::STATUS: RXEMPTY Mask */ + +#define QSPI_STATUS_RXFULL_Pos (9) /*!< QSPI_T::STATUS: RXFULL Position */ +#define QSPI_STATUS_RXFULL_Msk (0x1ul << QSPI_STATUS_RXFULL_Pos) /*!< QSPI_T::STATUS: RXFULL Mask */ + +#define QSPI_STATUS_RXTHIF_Pos (10) /*!< QSPI_T::STATUS: RXTHIF Position */ +#define QSPI_STATUS_RXTHIF_Msk (0x1ul << QSPI_STATUS_RXTHIF_Pos) /*!< QSPI_T::STATUS: RXTHIF Mask */ + +#define QSPI_STATUS_RXOVIF_Pos (11) /*!< QSPI_T::STATUS: RXOVIF Position */ +#define QSPI_STATUS_RXOVIF_Msk (0x1ul << QSPI_STATUS_RXOVIF_Pos) /*!< QSPI_T::STATUS: RXOVIF Mask */ + +#define QSPI_STATUS_RXTOIF_Pos (12) /*!< QSPI_T::STATUS: RXTOIF Position */ +#define QSPI_STATUS_RXTOIF_Msk (0x1ul << QSPI_STATUS_RXTOIF_Pos) /*!< QSPI_T::STATUS: RXTOIF Mask */ + +#define QSPI_STATUS_SPIENSTS_Pos (15) /*!< QSPI_T::STATUS: SPIENSTS Position */ +#define QSPI_STATUS_SPIENSTS_Msk (0x1ul << QSPI_STATUS_SPIENSTS_Pos) /*!< QSPI_T::STATUS: SPIENSTS Mask */ + +#define QSPI_STATUS_TXEMPTY_Pos (16) /*!< QSPI_T::STATUS: TXEMPTY Position */ +#define QSPI_STATUS_TXEMPTY_Msk (0x1ul << QSPI_STATUS_TXEMPTY_Pos) /*!< QSPI_T::STATUS: TXEMPTY Mask */ + +#define QSPI_STATUS_TXFULL_Pos (17) /*!< QSPI_T::STATUS: TXFULL Position */ +#define QSPI_STATUS_TXFULL_Msk (0x1ul << QSPI_STATUS_TXFULL_Pos) /*!< QSPI_T::STATUS: TXFULL Mask */ + +#define QSPI_STATUS_TXTHIF_Pos (18) /*!< QSPI_T::STATUS: TXTHIF Position */ +#define QSPI_STATUS_TXTHIF_Msk (0x1ul << QSPI_STATUS_TXTHIF_Pos) /*!< QSPI_T::STATUS: TXTHIF Mask */ + +#define QSPI_STATUS_TXUFIF_Pos (19) /*!< QSPI_T::STATUS: TXUFIF Position */ +#define QSPI_STATUS_TXUFIF_Msk (0x1ul << QSPI_STATUS_TXUFIF_Pos) /*!< QSPI_T::STATUS: TXUFIF Mask */ + +#define QSPI_STATUS_TXRXRST_Pos (23) /*!< QSPI_T::STATUS: TXRXRST Position */ +#define QSPI_STATUS_TXRXRST_Msk (0x1ul << QSPI_STATUS_TXRXRST_Pos) /*!< QSPI_T::STATUS: TXRXRST Mask */ + +#define QSPI_STATUS_RXCNT_Pos (24) /*!< QSPI_T::STATUS: RXCNT Position */ +#define QSPI_STATUS_RXCNT_Msk (0xful << QSPI_STATUS_RXCNT_Pos) /*!< QSPI_T::STATUS: RXCNT Mask */ + +#define QSPI_STATUS_TXCNT_Pos (28) /*!< QSPI_T::STATUS: TXCNT Position */ +#define QSPI_STATUS_TXCNT_Msk (0xful << QSPI_STATUS_TXCNT_Pos) /*!< QSPI_T::STATUS: TXCNT Mask */ + +#define QSPI_TX_TX_Pos (0) /*!< QSPI_T::TX: TX Position */ +#define QSPI_TX_TX_Msk (0xfffffffful << QSPI_TX_TX_Pos) /*!< QSPI_T::TX: TX Mask */ + +#define QSPI_RX_RX_Pos (0) /*!< QSPI_T::RX: RX Position */ +#define QSPI_RX_RX_Msk (0xfffffffful << QSPI_RX_RX_Pos) /*!< QSPI_T::RX: RX Mask */ + + + +/**@}*/ /* QSPI_CONST */ +/**@}*/ /* end of QSPI register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __QSPI_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/rtc_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/rtc_reg.h new file mode 100644 index 0000000000..91f27a32d3 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/rtc_reg.h @@ -0,0 +1,419 @@ +/**************************************************************************//** + * @file rtc_reg.h + * @version V1.00 + * @brief RTC register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __RTC_REG_H__ +#define __RTC_REG_H__ + +/** @addtogroup REGISTER Control Register + + @{ + +*/ + +/*---------------------- Real Time Clock Controller -------------------------*/ +/** + @addtogroup RTC Real Time Clock Controller(RTC) + Memory Mapped Structure for RTC Controller +@{ */ + +typedef struct +{ + + + /** + * @var RTC_T::INIT + * Offset: 0x00 RTC Initiation Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |INIT_ACTIVE|RTC Active Status (Read Only) + * | | |0 = RTC is at reset state. + * | | |1 = RTC is at normal active state. + * |[31:1] |INIT |RTC Initiation + * | | |When RTC block is powered on, RTC is at reset state + * | | |User has to write a number (0x a5eb1357) to INIT to make RTC leaving reset state + * | | |Once the INIT is written as 0xa5eb1357, the RTC will be in un-reset state permanently. + * | | |The INIT is a write-only field and read value will be always 0. + * @var RTC_T::FREQADJ + * Offset: 0x08 RTC Frequency Compensation Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |FRACTION |Fraction Part + * | | |Formula: FRACTION = (fraction part of detected value) X 64. + * | | |Note: Digit in FCR must be expressed as hexadecimal number. + * |[12:8] |INTEGER |Integer Part + * | | |00000 = Integer part of detected value is 32752. + * | | |00001 = Integer part of detected value is 32753. + * | | |00010 = Integer part of detected value is 32754. + * | | |00011 = Integer part of detected value is 32755. + * | | |00100 = Integer part of detected value is 32756. + * | | |00101 = Integer part of detected value is 32757. + * | | |00110 = Integer part of detected value is 32758. + * | | |00111 = Integer part of detected value is 32759. + * | | |01000 = Integer part of detected value is 32760. + * | | |01001 = Integer part of detected value is 32761. + * | | |01010 = Integer part of detected value is 32762. + * | | |01011 = Integer part of detected value is 32763. + * | | |01100 = Integer part of detected value is 32764. + * | | |01101 = Integer part of detected value is 32765. + * | | |01110 = Integer part of detected value is 32766. + * | | |01111 = Integer part of detected value is 32767. + * | | |10000 = Integer part of detected value is 32768. + * | | |10001 = Integer part of detected value is 32769. + * | | |10010 = Integer part of detected value is 32770. + * | | |10011 = Integer part of detected value is 32771. + * | | |10100 = Integer part of detected value is 32772. + * | | |10101 = Integer part of detected value is 32773. + * | | |10110 = Integer part of detected value is 32774. + * | | |10111 = Integer part of detected value is 32775. + * | | |11000 = Integer part of detected value is 32776. + * | | |11001 = Integer part of detected value is 32777. + * | | |11010 = Integer part of detected value is 32778. + * | | |11011 = Integer part of detected value is 32779. + * | | |11100 = Integer part of detected value is 32780. + * | | |11101 = Integer part of detected value is 32781. + * | | |11110 = Integer part of detected value is 32782. + * | | |11111 = Integer part of detected value is 32783. + * @var RTC_T::TIME + * Offset: 0x0C RTC Time Loading Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |SEC |1-Sec Time Digit (0~9) + * |[6:4] |TENSEC |10-Sec Time Digit (0~5) + * |[11:8] |MIN |1-Min Time Digit (0~9) + * |[14:12] |TENMIN |10-Min Time Digit (0~5) + * |[19:16] |HR |1-Hour Time Digit (0~9) + * |[21:20] |TENHR |10-Hour Time Digit (0~2) + * | | |When RTC runs as 12-hour time scale mode, RTC_TIME[21] (the high bit of TENHR[1:0]) means AM/PM indication (If RTC_TIME[21] is 1, it indicates PM time message.) + * |[30:24] |HZCNT |Index of sub-second counter(0x00 ~0x7F) + * @var RTC_T::CAL + * Offset: 0x10 RTC Calendar Loading Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |DAY |1-Day Calendar Digit (0~9) + * |[5:4] |TENDAY |10-Day Calendar Digit (0~3) + * |[11:8] |MON |1-Month Calendar Digit (0~9) + * |[12] |TENMON |10-Month Calendar Digit (0~1) + * |[19:16] |YEAR |1-Year Calendar Digit (0~9) + * |[23:20] |TENYEAR |10-Year Calendar Digit (0~9) + * @var RTC_T::CLKFMT + * Offset: 0x14 RTC Time Scale Selection Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |24HEN |24-hour / 12-hour Time Scale Selection + * | | |Indicates that RTC_TIME and RTC_TALM are in 24-hour time scale or 12-hour time scale + * | | |0 = 12-hour time scale with AM and PM indication selected. + * | | |1 = 24-hour time scale selected. + * |[8] |HZCNTEN |Sub-second Counter Enable Bit + * | | |0 = HZCNT disabled in RTC_TIME and RTC_TALM. + * | | |1 = HZCNT enabled in RTC_TIME and RTC_TALM . + * @var RTC_T::WEEKDAY + * Offset: 0x18 RTC Day of the Week Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |WEEKDAY |Day of the Week Register + * | | |000 = Sunday. + * | | |001 = Monday. + * | | |010 = Tuesday. + * | | |011 = Wednesday. + * | | |100 = Thursday. + * | | |101 = Friday. + * | | |110 = Saturday. + * | | |111 = Reserved. + * @var RTC_T::TALM + * Offset: 0x1C RTC Time Alarm Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |SEC |1-Sec Time Digit of Alarm Setting (0~9) + * |[6:4] |TENSEC |10-Sec Time Digit of Alarm Setting (0~5) + * |[11:8] |MIN |1-Min Time Digit of Alarm Setting (0~9) + * |[14:12] |TENMIN |10-Min Time Digit of Alarm Setting (0~5) + * |[19:16] |HR |1-Hour Time Digit of Alarm Setting (0~9) + * |[21:20] |TENHR |10-Hour Time Digit of Alarm Setting (0~2) + * | | |When RTC runs as 12-hour time scale mode, RTC_TIME[21] (the high bit of TENHR[1:0]) means AM/PM indication (If RTC_TIME[21] is 1, it indicates PM time message.) + * |[30:24] |HZCNT |Index of sub-second counter(0x00 ~0x7F) + * @var RTC_T::CALM + * Offset: 0x20 RTC Calendar Alarm Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |DAY |1-Day Calendar Digit of Alarm Setting (0~9) + * |[5:4] |TENDAY |10-Day Calendar Digit of Alarm Setting (0~3) + * |[11:8] |MON |1-Month Calendar Digit of Alarm Setting (0~9) + * |[12] |TENMON |10-Month Calendar Digit of Alarm Setting (0~1) + * |[19:16] |YEAR |1-Year Calendar Digit of Alarm Setting (0~9) + * |[23:20] |TENYEAR |10-Year Calendar Digit of Alarm Setting (0~9) + * @var RTC_T::LEAPYEAR + * Offset: 0x24 RTC Leap Year Indicator Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |LEAPYEAR |Leap Year Indication Register (Read Only) + * | | |0 = This year is not a leap year. + * | | |1 = This year is leap year. + * @var RTC_T::INTEN + * Offset: 0x28 RTC Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ALMIEN |Alarm Interrupt Enable Bit + * | | |Set ALMIEN to 1 can also enable chip wake-up function when RTC alarm interrupt event is generated. + * | | |0 = RTC Alarm interrupt Disabled. + * | | |1 = RTC Alarm interrupt Enabled. + * |[1] |TICKIEN |Time Tick Interrupt Enable Bit + * @var RTC_T::INTSTS + * Offset: 0x2C RTC Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ALMIF |RTC Alarm Interrupt Flag + * | | |0 = Alarm condition is not matched. + * | | |1 = Alarm condition is matched. + * | | |Note: Write 1 to clear this bit. + * |[1] |TICKIF |RTC Time Tick Interrupt Flag + * @var RTC_T::TICK + * Offset: 0x30 RTC Time Tick Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |TICK |Time Tick Register + * | | |These bits are used to select RTC time tick period for Periodic Time Tick Interrupt request. + * | | |000 = Time tick is 1 second. + * | | |001 = Time tick is 1/2 second. + * | | |010 = Time tick is 1/4 second. + * | | |011 = Time tick is 1/8 second. + * | | |100 = Time tick is 1/16 second. + * | | |101 = Time tick is 1/32 second. + * | | |110 = Time tick is 1/64 second. + * | | |111 = Time tick is 1/128 second. + * | | |Note: This register can be read back after the RTC register access enable bit RWENF (RTC_RWEN[16]) is active. + * @var RTC_T::TAMSK + * Offset: 0x34 RTC Time Alarm Mask Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |MSEC |Mask 1-Sec Time Digit of Alarm Setting (0~9) + * |[1] |MTENSEC |Mask 10-Sec Time Digit of Alarm Setting (0~5) + * |[2] |MMIN |Mask 1-Min Time Digit of Alarm Setting (0~9) + * |[3] |MTENMIN |Mask 10-Min Time Digit of Alarm Setting (0~5) + * |[4] |MHR |Mask 1-Hour Time Digit of Alarm Setting (0~9) + * | | |Note: MHR function is only for 24-hour time scale mode. + * |[5] |MTENHR |Mask 10-Hour Time Digit of Alarm Setting (0~2) + * | | |Note: MTENHR function is only for 24-hour time scale mode. + * @var RTC_T::CAMSK + * Offset: 0x38 RTC Calendar Alarm Mask Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |MDAY |Mask 1-Day Calendar Digit of Alarm Setting (0~9) + * |[1] |MTENDAY |Mask 10-Day Calendar Digit of Alarm Setting (0~3) + * |[2] |MMON |Mask 1-Month Calendar Digit of Alarm Setting (0~9) + * |[3] |MTENMON |Mask 10-Month Calendar Digit of Alarm Setting (0~1) + * |[4] |MYEAR |Mask 1-Year Calendar Digit of Alarm Setting (0~9) + * |[5] |MTENYEAR |Mask 10-Year Calendar Digit of Alarm Setting (0~9) + * @var RTC_T::LXTCTL + * Offset: 0x100 RTC 32.768 kHz Oscillator Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7] |C32KS |Clock 32K Source Selection: + * | | |0 = Internal 32K clock is from 32K crystal . + * | | |1 = Internal 32K clock is from LIRC32K. + */ + __IO uint32_t INIT; /*!< [0x0000] RTC Initiation Register */ + __I uint32_t RESERVE0[1]; + __IO uint32_t FREQADJ; /*!< [0x0008] RTC Frequency Compensation Register */ + __IO uint32_t TIME; /*!< [0x000c] RTC Time Loading Register */ + __IO uint32_t CAL; /*!< [0x0010] RTC Calendar Loading Register */ + __IO uint32_t CLKFMT; /*!< [0x0014] RTC Time Scale Selection Register */ + __IO uint32_t WEEKDAY; /*!< [0x0018] RTC Day of the Week Register */ + __IO uint32_t TALM; /*!< [0x001c] RTC Time Alarm Register */ + __IO uint32_t CALM; /*!< [0x0020] RTC Calendar Alarm Register */ + __I uint32_t LEAPYEAR; /*!< [0x0024] RTC Leap Year Indicator Register */ + __IO uint32_t INTEN; /*!< [0x0028] RTC Interrupt Enable Register */ + __IO uint32_t INTSTS; /*!< [0x002c] RTC Interrupt Status Register */ + __IO uint32_t TICK; /*!< [0x0030] RTC Time Tick Register */ + __IO uint32_t TAMSK; /*!< [0x0034] RTC Time Alarm Mask Register */ + __IO uint32_t CAMSK; /*!< [0x0038] RTC Calendar Alarm Mask Register */ + __I uint32_t RESERVE1[49]; /* 0x3C ~ 0xFC */ + __IO uint32_t LXTCTL; /*!< [0x0100] RTC 32.768 kHz Oscillator Control Register */ + +} RTC_T; + +/** + @addtogroup RTC_CONST RTC Bit Field Definition + Constant Definitions for RTC Controller +@{ */ + +#define RTC_INIT_ACTIVE_Pos (0) /*!< RTC_T::INIT: ACTIVE Position */ +#define RTC_INIT_ACTIVE_Msk (0x1ul << RTC_INIT_ACTIVE_Pos) /*!< RTC_T::INIT: ACTIVE Mask */ + +#define RTC_INIT_INIT_Pos (1) /*!< RTC_T::INIT: INIT Position */ +#define RTC_INIT_INIT_Msk (0x7ffffffful << RTC_INIT_INIT_Pos) /*!< RTC_T::INIT: INIT Mask */ + +#define RTC_FREQADJ_FRACTION_Pos (0) /*!< RTC_T::FREQADJ: FRACTION Position */ +#define RTC_FREQADJ_FRACTION_Msk (0x3ful << RTC_FREQADJ_FRACTION_Pos) /*!< RTC_T::FREQADJ: FRACTION Mask */ + +#define RTC_FREQADJ_INTEGER_Pos (8) /*!< RTC_T::FREQADJ: INTEGER Position */ +#define RTC_FREQADJ_INTEGER_Msk (0x1ful << RTC_FREQADJ_INTEGER_Pos) /*!< RTC_T::FREQADJ: INTEGER Mask */ + +#define RTC_TIME_SEC_Pos (0) /*!< RTC_T::TIME: SEC Position */ +#define RTC_TIME_SEC_Msk (0xful << RTC_TIME_SEC_Pos) /*!< RTC_T::TIME: SEC Mask */ + +#define RTC_TIME_TENSEC_Pos (4) /*!< RTC_T::TIME: TENSEC Position */ +#define RTC_TIME_TENSEC_Msk (0x7ul << RTC_TIME_TENSEC_Pos) /*!< RTC_T::TIME: TENSEC Mask */ + +#define RTC_TIME_MIN_Pos (8) /*!< RTC_T::TIME: MIN Position */ +#define RTC_TIME_MIN_Msk (0xful << RTC_TIME_MIN_Pos) /*!< RTC_T::TIME: MIN Mask */ + +#define RTC_TIME_TENMIN_Pos (12) /*!< RTC_T::TIME: TENMIN Position */ +#define RTC_TIME_TENMIN_Msk (0x7ul << RTC_TIME_TENMIN_Pos) /*!< RTC_T::TIME: TENMIN Mask */ + +#define RTC_TIME_HR_Pos (16) /*!< RTC_T::TIME: HR Position */ +#define RTC_TIME_HR_Msk (0xful << RTC_TIME_HR_Pos) /*!< RTC_T::TIME: HR Mask */ + +#define RTC_TIME_TENHR_Pos (20) /*!< RTC_T::TIME: TENHR Position */ +#define RTC_TIME_TENHR_Msk (0x3ul << RTC_TIME_TENHR_Pos) /*!< RTC_T::TIME: TENHR Mask */ + +#define RTC_TIME_HZCNT_Pos (24) /*!< RTC_T::TIME: HZCNT Position */ +#define RTC_TIME_HZCNT_Msk (0x7ful << RTC_TIME_HZCNT_Pos) /*!< RTC_T::TIME: HZCNT Mask */ + +#define RTC_CAL_DAY_Pos (0) /*!< RTC_T::CAL: DAY Position */ +#define RTC_CAL_DAY_Msk (0xful << RTC_CAL_DAY_Pos) /*!< RTC_T::CAL: DAY Mask */ + +#define RTC_CAL_TENDAY_Pos (4) /*!< RTC_T::CAL: TENDAY Position */ +#define RTC_CAL_TENDAY_Msk (0x3ul << RTC_CAL_TENDAY_Pos) /*!< RTC_T::CAL: TENDAY Mask */ + +#define RTC_CAL_MON_Pos (8) /*!< RTC_T::CAL: MON Position */ +#define RTC_CAL_MON_Msk (0xful << RTC_CAL_MON_Pos) /*!< RTC_T::CAL: MON Mask */ + +#define RTC_CAL_TENMON_Pos (12) /*!< RTC_T::CAL: TENMON Position */ +#define RTC_CAL_TENMON_Msk (0x1ul << RTC_CAL_TENMON_Pos) /*!< RTC_T::CAL: TENMON Mask */ + +#define RTC_CAL_YEAR_Pos (16) /*!< RTC_T::CAL: YEAR Position */ +#define RTC_CAL_YEAR_Msk (0xful << RTC_CAL_YEAR_Pos) /*!< RTC_T::CAL: YEAR Mask */ + +#define RTC_CAL_TENYEAR_Pos (20) /*!< RTC_T::CAL: TENYEAR Position */ +#define RTC_CAL_TENYEAR_Msk (0xful << RTC_CAL_TENYEAR_Pos) /*!< RTC_T::CAL: TENYEAR Mask */ + +#define RTC_CLKFMT_24HEN_Pos (0) /*!< RTC_T::CLKFMT: 24HEN Position */ +#define RTC_CLKFMT_24HEN_Msk (0x1ul << RTC_CLKFMT_24HEN_Pos) /*!< RTC_T::CLKFMT: 24HEN Mask */ + +#define RTC_CLKFMT_HZCNTEN_Pos (8) /*!< RTC_T::CLKFMT: HZCNTEN Position */ +#define RTC_CLKFMT_HZCNTEN_Msk (0x1ul << RTC_CLKFMT_HZCNTEN_Pos) /*!< RTC_T::CLKFMT: HZCNTEN Mask */ + +#define RTC_WEEKDAY_WEEKDAY_Pos (0) /*!< RTC_T::WEEKDAY: WEEKDAY Position */ +#define RTC_WEEKDAY_WEEKDAY_Msk (0x7ul << RTC_WEEKDAY_WEEKDAY_Pos) /*!< RTC_T::WEEKDAY: WEEKDAY Mask */ + +#define RTC_TALM_SEC_Pos (0) /*!< RTC_T::TALM: SEC Position */ +#define RTC_TALM_SEC_Msk (0xful << RTC_TALM_SEC_Pos) /*!< RTC_T::TALM: SEC Mask */ + +#define RTC_TALM_TENSEC_Pos (4) /*!< RTC_T::TALM: TENSEC Position */ +#define RTC_TALM_TENSEC_Msk (0x7ul << RTC_TALM_TENSEC_Pos) /*!< RTC_T::TALM: TENSEC Mask */ + +#define RTC_TALM_MIN_Pos (8) /*!< RTC_T::TALM: MIN Position */ +#define RTC_TALM_MIN_Msk (0xful << RTC_TALM_MIN_Pos) /*!< RTC_T::TALM: MIN Mask */ + +#define RTC_TALM_TENMIN_Pos (12) /*!< RTC_T::TALM: TENMIN Position */ +#define RTC_TALM_TENMIN_Msk (0x7ul << RTC_TALM_TENMIN_Pos) /*!< RTC_T::TALM: TENMIN Mask */ + +#define RTC_TALM_HR_Pos (16) /*!< RTC_T::TALM: HR Position */ +#define RTC_TALM_HR_Msk (0xful << RTC_TALM_HR_Pos) /*!< RTC_T::TALM: HR Mask */ + +#define RTC_TALM_TENHR_Pos (20) /*!< RTC_T::TALM: TENHR Position */ +#define RTC_TALM_TENHR_Msk (0x3ul << RTC_TALM_TENHR_Pos) /*!< RTC_T::TALM: TENHR Mask */ + +#define RTC_TALM_HZCNT_Pos (24) /*!< RTC_T::TALM: HZCNT Position */ +#define RTC_TALM_HZCNT_Msk (0x7ful << RTC_TALM_HZCNT_Pos) /*!< RTC_T::TALM: HZCNT Mask */ + +#define RTC_CALM_DAY_Pos (0) /*!< RTC_T::CALM: DAY Position */ +#define RTC_CALM_DAY_Msk (0xful << RTC_CALM_DAY_Pos) /*!< RTC_T::CALM: DAY Mask */ + +#define RTC_CALM_TENDAY_Pos (4) /*!< RTC_T::CALM: TENDAY Position */ +#define RTC_CALM_TENDAY_Msk (0x3ul << RTC_CALM_TENDAY_Pos) /*!< RTC_T::CALM: TENDAY Mask */ + +#define RTC_CALM_MON_Pos (8) /*!< RTC_T::CALM: MON Position */ +#define RTC_CALM_MON_Msk (0xful << RTC_CALM_MON_Pos) /*!< RTC_T::CALM: MON Mask */ + +#define RTC_CALM_TENMON_Pos (12) /*!< RTC_T::CALM: TENMON Position */ +#define RTC_CALM_TENMON_Msk (0x1ul << RTC_CALM_TENMON_Pos) /*!< RTC_T::CALM: TENMON Mask */ + +#define RTC_CALM_YEAR_Pos (16) /*!< RTC_T::CALM: YEAR Position */ +#define RTC_CALM_YEAR_Msk (0xful << RTC_CALM_YEAR_Pos) /*!< RTC_T::CALM: YEAR Mask */ + +#define RTC_CALM_TENYEAR_Pos (20) /*!< RTC_T::CALM: TENYEAR Position */ +#define RTC_CALM_TENYEAR_Msk (0xful << RTC_CALM_TENYEAR_Pos) /*!< RTC_T::CALM: TENYEAR Mask */ + +#define RTC_LEAPYEAR_LEAPYEAR_Pos (0) /*!< RTC_T::LEAPYEAR: LEAPYEAR Position */ +#define RTC_LEAPYEAR_LEAPYEAR_Msk (0x1ul << RTC_LEAPYEAR_LEAPYEAR_Pos) /*!< RTC_T::LEAPYEAR: LEAPYEAR Mask */ + +#define RTC_INTEN_ALMIEN_Pos (0) /*!< RTC_T::INTEN: ALMIEN Position */ +#define RTC_INTEN_ALMIEN_Msk (0x1ul << RTC_INTEN_ALMIEN_Pos) /*!< RTC_T::INTEN: ALMIEN Mask */ + +#define RTC_INTEN_TICKIEN_Pos (1) /*!< RTC_T::INTEN: TICKIEN Position */ +#define RTC_INTEN_TICKIEN_Msk (0x1ul << RTC_INTEN_TICKIEN_Pos) /*!< RTC_T::INTEN: TICKIEN Mask */ + +#define RTC_INTSTS_ALMIF_Pos (0) /*!< RTC_T::INTSTS: ALMIF Position */ +#define RTC_INTSTS_ALMIF_Msk (0x1ul << RTC_INTSTS_ALMIF_Pos) /*!< RTC_T::INTSTS: ALMIF Mask */ + +#define RTC_INTSTS_TICKIF_Pos (1) /*!< RTC_T::INTSTS: TICKIF Position */ +#define RTC_INTSTS_TICKIF_Msk (0x1ul << RTC_INTSTS_TICKIF_Pos) /*!< RTC_T::INTSTS: TICKIF Mask */ + +#define RTC_TICK_TICK_Pos (0) /*!< RTC_T::TICK: TICK Position */ +#define RTC_TICK_TICK_Msk (0x7ul << RTC_TICK_TICK_Pos) /*!< RTC_T::TICK: TICK Mask */ + +#define RTC_TAMSK_MSEC_Pos (0) /*!< RTC_T::TAMSK: MSEC Position */ +#define RTC_TAMSK_MSEC_Msk (0x1ul << RTC_TAMSK_MSEC_Pos) /*!< RTC_T::TAMSK: MSEC Mask */ + +#define RTC_TAMSK_MTENSEC_Pos (1) /*!< RTC_T::TAMSK: MTENSEC Position */ +#define RTC_TAMSK_MTENSEC_Msk (0x1ul << RTC_TAMSK_MTENSEC_Pos) /*!< RTC_T::TAMSK: MTENSEC Mask */ + +#define RTC_TAMSK_MMIN_Pos (2) /*!< RTC_T::TAMSK: MMIN Position */ +#define RTC_TAMSK_MMIN_Msk (0x1ul << RTC_TAMSK_MMIN_Pos) /*!< RTC_T::TAMSK: MMIN Mask */ + +#define RTC_TAMSK_MTENMIN_Pos (3) /*!< RTC_T::TAMSK: MTENMIN Position */ +#define RTC_TAMSK_MTENMIN_Msk (0x1ul << RTC_TAMSK_MTENMIN_Pos) /*!< RTC_T::TAMSK: MTENMIN Mask */ + +#define RTC_TAMSK_MHR_Pos (4) /*!< RTC_T::TAMSK: MHR Position */ +#define RTC_TAMSK_MHR_Msk (0x1ul << RTC_TAMSK_MHR_Pos) /*!< RTC_T::TAMSK: MHR Mask */ + +#define RTC_TAMSK_MTENHR_Pos (5) /*!< RTC_T::TAMSK: MTENHR Position */ +#define RTC_TAMSK_MTENHR_Msk (0x1ul << RTC_TAMSK_MTENHR_Pos) /*!< RTC_T::TAMSK: MTENHR Mask */ + +#define RTC_CAMSK_MDAY_Pos (0) /*!< RTC_T::CAMSK: MDAY Position */ +#define RTC_CAMSK_MDAY_Msk (0x1ul << RTC_CAMSK_MDAY_Pos) /*!< RTC_T::CAMSK: MDAY Mask */ + +#define RTC_CAMSK_MTENDAY_Pos (1) /*!< RTC_T::CAMSK: MTENDAY Position */ +#define RTC_CAMSK_MTENDAY_Msk (0x1ul << RTC_CAMSK_MTENDAY_Pos) /*!< RTC_T::CAMSK: MTENDAY Mask */ + +#define RTC_CAMSK_MMON_Pos (2) /*!< RTC_T::CAMSK: MMON Position */ +#define RTC_CAMSK_MMON_Msk (0x1ul << RTC_CAMSK_MMON_Pos) /*!< RTC_T::CAMSK: MMON Mask */ + +#define RTC_CAMSK_MTENMON_Pos (3) /*!< RTC_T::CAMSK: MTENMON Position */ +#define RTC_CAMSK_MTENMON_Msk (0x1ul << RTC_CAMSK_MTENMON_Pos) /*!< RTC_T::CAMSK: MTENMON Mask */ + +#define RTC_CAMSK_MYEAR_Pos (4) /*!< RTC_T::CAMSK: MYEAR Position */ +#define RTC_CAMSK_MYEAR_Msk (0x1ul << RTC_CAMSK_MYEAR_Pos) /*!< RTC_T::CAMSK: MYEAR Mask */ + +#define RTC_CAMSK_MTENYEAR_Pos (5) /*!< RTC_T::CAMSK: MTENYEAR Position */ +#define RTC_CAMSK_MTENYEAR_Msk (0x1ul << RTC_CAMSK_MTENYEAR_Pos) /*!< RTC_T::CAMSK: MTENYEAR Mask */ + +#define RTC_LXTCTL_C32KS_Pos (7) /*!< RTC_T::LXTCTL: C32KS Position */ +#define RTC_LXTCTL_C32KS_Msk (0x1ul << RTC_LXTCTL_C32KS_Pos) /*!< RTC_T::LXTCTL: C32KS Mask */ + +/**@}*/ /* RTC_CONST */ +/**@}*/ /* end of RTC register group */ +/**@}*/ /* end of REGISTER group */ + +#endif /* __RTC_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/spi_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/spi_reg.h new file mode 100644 index 0000000000..0d1a2dde65 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/spi_reg.h @@ -0,0 +1,784 @@ +/**************************************************************************//** + * @file spi_reg.h + * @version V1.00 + * @brief SPI register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __SPI_REG_H__ +#define __SPI_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup SPI Serial Peripheral Interface Controller(SPI) + Memory Mapped Structure for SPI Controller +@{ */ + +typedef struct +{ + + + /** + * @var SPI_T::CTL + * Offset: 0x00 SPI Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SPIEN |SPI Transfer Control Enable Bit + * | | |In Master mode, the transfer will start when there is data in the FIFO buffer after this bit is set to 1. + * | | |In Slave mode, this device is ready to receive data when this bit is set to 1. + * | | |0 = Transfer control Disabled. + * | | |1 = Transfer control Enabled. + * | | |Note: Before changing the configurations of SPIx_CTL, SPIx_CLKDIV, SPIx_SSCTL and SPIx_FIFOCTL registers, user shall clear the SPIEN (SPIx_CTL[0]) and confirm the SPIENSTS (SPIx_STATUS[15]) is 0. + * |[1] |RXNEG |Receive on Negative Edge + * | | |0 = Received data input signal is latched on the rising edge of SPI bus clock. + * | | |1 = Received data input signal is latched on the falling edge of SPI bus clock. + * |[2] |TXNEG |Transmit on Negative Edge + * | | |0 = Transmitted data output signal is changed on the rising edge of SPI bus clock. + * | | |1 = Transmitted data output signal is changed on the falling edge of SPI bus clock. + * |[3] |CLKPOL |Clock Polarity + * | | |0 = SPI bus clock is idle low. + * | | |1 = SPI bus clock is idle high. + * |[7:4] |SUSPITV |Suspend Interval (Master Only) + * | | |The four bits provide configurable suspend interval between two successive transmit/receive transaction in a transfer. + * | | |The definition of the suspend interval is the interval between the last clock edge of the preceding transaction word and the first clock edge of the following transaction word. + * | | |The default value is 0x3. + * | | |The period of the suspend interval is obtained according to the following equation. + * | | |(SUSPITV[3:0] + 0.5) * period of SPICLK clock cycle + * | | |Example: + * | | |SUSPITV = 0x0 u2026. 0.5 SPICLK clock cycle. + * | | |SUSPITV = 0x1 u2026. 1.5 SPICLK clock cycle. + * | | |...... + * | | |SUSPITV = 0xE u2026. 14.5 SPICLK clock cycle. + * | | |SUSPITV = 0xF u2026. 15.5 SPICLK clock cycle. + * |[12:8] |DWIDTH |Data Width + * | | |This field specifies how many bits can be transmitted / received in one transaction + * | | |The minimum bit length is 8 bits and can up to 32 bits. + * | | |DWIDTH = 0x08 ... 8 bits. + * | | |DWIDTH = 0x09 ... 9 bits. + * | | |...... + * | | |DWIDTH = 0x1F ... 31 bits. + * | | |DWIDTH = 0x00 ... 32 bits. + * |[13] |LSB |Send LSB First + * | | |0 = The MSB, which bit of transmit/receive register depends on the setting of DWIDTH, is transmitted/received first. + * | | |1 = The LSB, bit 0 of the SPI TX register, is sent first to the SPI data output pin, and the first bit received from the SPI data input pin will be put in the LSB position of the RX register (bit 0 of SPI_RX). + * |[14] |HALFDPX |SPI Half-duplex Transfer Enable Bit + * | | |This bit is used to select full-duplex or half-duplex for SPI transfer + * | | |The bit field DATDIR (SPIx_CTL[20]) can be used to set the data direction while in half-duplex transfer. + * | | |0 = SPI operates in full-duplex transfer. + * | | |1 = SPI operates in half-duplex transfer. + * |[15] |RXONLY |Receive-only FUNCTION Mode Enable Bit (Master Only) + * | | |This bit field is only available in Master mode. + * | | |In receive-only mode, SPI Master will generate SPI bus clock continuously for receiving data bit from SPI slave device and assert the BUSY status. + * | | |If both AUTOSS (SPI_SSCTL[3]) and RXONLY are enabled, the output slave select signal will be activated. + * | | |0 = Receive-only function mode Disabled. + * | | |1 = Receive-only functionmode Enabled. + * | | |Note: We suggest users switch to receive-only mode when BUSY (SPI_STATUS[0]) is low. + * |[17] |UNITIEN |Unit Transfer Interrupt Enable Bit + * | | |0 = SPI unit transfer interrupt Disabled. + * | | |1 = SPI unit transfer interrupt Enabled. + * |[18] |SLAVE |Slave Mode Control + * | | |0 = Master mode. + * | | |1 = Slave mode. + * |[19] |REORDER |Byte Reorder Function Enable Bit + * | | |0 = Byte Reorder function Disabled. + * | | |1 = Byte Reorder function Enabled. + * | | |A byte suspend interval will be inserted among each byte. + * | | |The period of the byte suspend interval depends on the setting of SUSPITV. + * | | |Note: + * | | |Byte Reorder function is only available if DWIDTH is defined as 16, 24, and 32 bits. + * |[20] |DATDIR |Data Port Direction Control + * | | |This bit is used to select the data input/output direction while in half-duplex transfer. + * | | |0 = SPI data is input direction. + * | | |1 = SPI data is output direction. + * @var SPI_T::CLKDIV + * Offset: 0x04 SPI Clock Divider Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |DIVIDER |Clock Divider + * | | |The value in this field is the frequency divider for generating the peripheral clock, fspi_eclk, and the SPI bus clock of SPI Master + * | | |The frequency is obtained according to the following equation. + * | | | FREQ_spi_eclk = FREQ_spi_clock_src/(DIVIDER+1) + * | | |where + * | | | FREQ_spi_clock_src is the peripheral clock source, which is defined in the clock control register, CLK_CLKSEL2. + * | | |Note: Not supported in I2S mode. + * @var SPI_T::SSCTL + * Offset: 0x08 SPI Slave Select Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SS |Slave Selection Control (Master Only) + * | | |If AUTOSS bit is cleared to 0, + * | | |0 = set the SPIx_SS line to inactive state. + * | | |1 = set the SPIx_SS line to active state. + * | | |If the AUTOSS bit is set to 1, + * | | |0 = Keep the SPIx_SS line at inactive state. + * | | |1 = SPIx_SS line will be automatically driven to active state for the duration of data transfer, and will be driven to inactive state for the rest of the time. + * | | |The active state of SPIx_SS is specified in SSACTPOL (SPIx_SSCTL[2]). + * |[2] |SSACTPOL |Slave Selection Active Polarity + * | | |This bit defines the active polarity of slave selection signal (SPIx_SS). + * | | |0 = The slave selection signal SPIx_SS is active low. + * | | |1 = The slave selection signal SPIx_SS is active high. + * |[3] |AUTOSS |Automatic Slave Selection Function Enable Bit (Master Only) + * | | |0 = Automatic slave selection function Disabled. + * | | |Slave selection signal will be asserted/de-asserted according to SS (SPIx_SSCTL[0]). + * | | |1 = Automatic slave selection function Enabled. + * |[8] |SLVBEIEN |Slave Mode Bit Count Error Interrupt Enable Bit + * | | |0 = Slave mode bit count error interrupt Disabled. + * | | |1 = Slave mode bit count error interrupt Enabled. + * |[9] |SLVURIEN |Slave Mode TX Under Run Interrupt Enable Bit + * | | |0 = Slave mode TX under run interrupt Disabled. + * | | |1 = Slave mode TX under run interrupt Enabled. + * |[12] |SSACTIEN |Slave Select Active Interrupt Enable Bit + * | | |0 = Slave select active interrupt Disabled. + * | | |1 = Slave select active interrupt Enabled. + * |[13] |SSINAIEN |Slave Select Inactive Interrupt Enable Bit + * | | |0 = Slave select inactive interrupt Disabled. + * | | |1 = Slave select inactive interrupt Enabled. + * @var SPI_T::PDMACTL + * Offset: 0x0C SPI PDMA Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |TXPDMAEN |Transmit PDMA Enable Bit + * | | |0 = Transmit PDMA function Disabled. + * | | |1 = Transmit PDMA function Enabled. + * | | |Note: In SPI Master mode with full duplex transfer, if both TX and RX PDMA functions are enabled, RX PDMA function cannot be enabled prior to TX PDMA function + * | | |User can enable TX PDMA function firstly or enable both functions simultaneously. + * |[1] |RXPDMAEN |Receive PDMA Enable Bit + * | | |0 = Receiver PDMA function Disabled. + * | | |1 = Receiver PDMA function Enabled. + * |[2] |PDMARST |PDMA Reset + * | | |0 = No effect. + * | | |1 = Reset the PDMA control logic of the SPI controller. This bit will be automatically cleared to 0. + * @var SPI_T::FIFOCTL + * Offset: 0x10 SPI FIFO Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RXRST |Receive Reset + * | | |0 = No effect. + * | | |1 = Reset receive FIFO pointer and receive circuit. + * | | |The RXFULL bit will be cleared to 0 and the RXEMPTY bit will be set to 1. + * | | |This bit will be cleared to 0 by hardware about 3 system clock cycles + 2 peripheral clock cycles after it is set to 1. + * | | |User can read TXRXRST (SPIx_STATUS[23]) to check if reset is accomplished or not. + * |[1] |TXRST |Transmit Reset + * | | |0 = No effect. + * | | |1 = Reset transmit FIFO pointer and transmit circuit. + * | | |The TXFULL bit will be cleared to 0 and the TXEMPTY bit will be set to 1. + * | | |This bit will be cleared to 0 by hardware about 3 system clock cycles + 2 peripheral clock cycles after it is set to 1. + * | | |User can read TXRXRST (SPIx_STATUS[23]) to check if reset is accomplished or not. + * |[2] |RXTHIEN |Receive FIFO Threshold Interrupt Enable Bit + * | | |0 = RX FIFO threshold interrupt Disabled. + * | | |1 = RX FIFO threshold interrupt Enabled. + * |[3] |TXTHIEN |Transmit FIFO Threshold Interrupt Enable Bit + * | | |0 = TX FIFO threshold interrupt Disabled. + * | | |1 = TX FIFO threshold interrupt Enabled. + * |[4] |RXTOIEN |Slave Receive Time-out Interrupt Enable Bit + * | | |0 = Receive time-out interrupt Disabled. + * | | |1 = Receive time-out interrupt Enabled. + * |[5] |RXOVIEN |Receive FIFO Overrun Interrupt Enable Bit + * | | |0 = Receive FIFO overrun interrupt Disabled. + * | | |1 = Receive FIFO overrun interrupt Enabled. + * |[6] |TXUFPOL |TX Underflow Data Polarity + * | | |0 = The SPI data out is keep 0 if there is TX underflow event in Slave mode. + * | | |1 = The SPI data out is keep 1 if there is TX underflow event in Slave mode. + * | | |Note: + * | | |1. The TX underflow event occurs if there is not any data in TX FIFO when the slave selection signal is active. + * | | |2. This bit should be set as 0 in I2S mode. + * | | |3. When TX underflow event occurs, SPIx_MISO pin state will be determined by this setting even though TX FIFO is not empty afterward. + * | | |Data stored in TX FIFO will be sent through SPIx_MISO pin in the next transfer frame. + * |[7] |TXUFIEN |TX Underflow Interrupt Enable Bit + * | | |0 = Slave TX underflow interrupt Disabled. + * | | |1 = Slave TX underflow interrupt Enabled. + * |[8] |RXFBCLR |Receive FIFO Buffer Clear + * | | |0 = No effect. + * | | |1 = Clear receive FIFO pointer. + * | | |The RXFULL bit will be cleared to 0 and the RXEMPTY bit will be set to 1. + * | | |This bit will be cleared to 0 by hardware about 1 system clock after it is set to 1. + * | | |Note: The RX shift register will not be cleared. + * |[9] |TXFBCLR |Transmit FIFO Buffer Clear + * | | |0 = No effect. + * | | |1 = Clear transmit FIFO pointer. + * | | |The TXFULL bit will be cleared to 0 and the TXEMPTY bit will be set to 1. + * | | |This bit will be cleared to 0 by hardware about 1 system clock after it is set to 1. + * | | |Note: The TX shift register will not be cleared. + * |[25:24] |RXTH |Receive FIFO Threshold + * | | |If the valid data count of the receive FIFO buffer is larger than the RXTH setting, the RXTHIF bit will be set to 1, else the RXTHIF bit will be cleared to 0. + * | | |The MSB of this bit field is only meaningful while SPI mode 8~16 bits of data length. + * |[29:28] |TXTH |Transmit FIFO Threshold + * | | |If the valid data count of the transmit FIFO buffer is less than or equal to the TXTH setting, the TXTHIF bit will be set to 1, else the TXTHIF bit will be cleared to 0. + * | | |The MSB of this bit field is only meaningful while SPI mode 8~16 bits of data length. + * @var SPI_T::STATUS + * Offset: 0x14 SPI Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BUSY |Busy Status (Read Only) + * | | |0 = SPI controller is in idle state. + * | | |1 = SPI controller is in busy state. + * | | |The following listing are the bus busy conditions: + * | | |a. SPIx_CTL[0] = 1 and the TXEMPTY = 0. + * | | |b. For SPI Master mode, SPIx_CTL[0] = 1 and the TXEMPTY = 1 but the current transaction is not finished yet. + * | | |c. For SPI Master mode, SPIx_CTL[0] = 1 and RXONLY = 1. + * | | |d. For SPI Slave mode, the SPIx_CTL[0] = 1 and there is serial clock input into the SPI core logic when slave select is active. + * | | |e. For SPI Slave mode, the SPIx_CTL[0] = 1 and the transmit buffer or transmit shift register is not empty even if the slave select is inactive. + * |[1] |UNITIF |Unit Transfer Interrupt Flag + * | | |0 = No transaction has been finished since this bit was cleared to 0. + * | | |1 = SPI controller has finished one unit transfer. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[2] |SSACTIF |Slave Select Active Interrupt Flag + * | | |0 = Slave select active interrupt was cleared or not occurred. + * | | |1 = Slave select active interrupt event occurred. + * | | |Note: Only available in Slave mode. This bit will be cleared by writing 1 to it. + * |[3] |SSINAIF |Slave Select Inactive Interrupt Flag + * | | |0 = Slave select inactive interrupt was cleared or not occurred. + * | | |1 = Slave select inactive interrupt event occurred. + * | | |Note: Only available in Slave mode. This bit will be cleared by writing 1 to it. + * |[4] |SSLINE |Slave Select Line Bus Status (Read Only) + * | | |0 = The slave select line status is 0. + * | | |1 = The slave select line status is 1. + * | | |Note: This bit is only available in Slave mode. + * | | |If SSACTPOL (SPIx_SSCTL[2]) is set 0, and the SSLINE is 1, the SPI slave select is in inactive status. + * |[6] |SLVBEIF |Slave Mode Bit Count Error Interrupt Flag + * | | |In Slave mode, when the slave select line goes to inactive state, if bit counter is mismatch with DWIDTH, this interrupt flag will be set to 1. + * | | |0 = No Slave mode bit count error event. + * | | |1 = Slave mode bit count error event occurs. + * | | |Note: If the slave select active but there is no any bus clock input, the SLVBCEEIF also active when the slave select goes to inactive state + * | | |This bit will be cleared by writing 1 to it. + * |[7] |SLVURIF |Slave Mode TX Under Run Interrupt Flag + * | | |In Slave mode, if TX underflow event occurs and the slave select line goes to inactive state, this interrupt flag will be set to 1. + * | | |0 = No Slave TX under run event. + * | | |1 = Slave TX under run event occurs. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[8] |RXEMPTY |Receive FIFO Buffer Empty Indicator (Read Only) + * | | |0 = Receive FIFO buffer is not empty. + * | | |1 = Receive FIFO buffer is empty. + * |[9] |RXFULL |Receive FIFO Buffer Full Indicator (Read Only) + * | | |0 = Receive FIFO buffer is not full. + * | | |1 = Receive FIFO buffer is full. + * |[10] |RXTHIF |Receive FIFO Threshold Interrupt Flag (Read Only) + * | | |0 = The valid data count within the RXreceive FIFO buffer is smaller than or equal to the setting value of RXTH. + * | | |1 = The valid data count within the receive FIFO buffer is larger than the setting value of RXTH. + * |[11] |RXOVIF |Receive FIFO Overrun Interrupt Flag + * | | |When the receive FIFO buffer is full, the follow-up data will be dropped and this bit will be set to 1. + * | | |0 = No FIFO is over run. + * | | |1 = Receive FIFO is over run. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[12] |RXTOIF |Receive Time-out Interrupt Flag + * | | |0 = No receive FIFO time-out event. + * | | |1 = Receive FIFO buffer is not empty and no read operation on receive FIFO buffer over 64 SPI peripheral clock periods in Master mode or over 576 SPI peripheral clock periods in Slave mode. + * | | |When the received FIFO buffer is read by software, the time-out status will be cleared automatically. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[15] |SPIENSTS |SPI Enable Status (Read Only) + * | | |0 = The SPI controller is disabled. + * | | |1 = The SPI controller is enabled. + * | | |Note: The SPI peripheral clock is asynchronous with the system clock. + * | | |In order to make sure the SPI control logic is disabled, this bit indicates the real status of SPI controller. + * |[16] |TXEMPTY |Transmit FIFO Buffer Empty Indicator (Read Only) + * | | |0 = Transmit FIFO buffer is not empty. + * | | |1 = Transmit FIFO buffer is empty. + * |[17] |TXFULL |Transmit FIFO Buffer Full Indicator (Read Only) + * | | |0 = Transmit FIFO buffer is not full. + * | | |1 = Transmit FIFO buffer is full. + * |[18] |TXTHIF |Transmit FIFO Threshold Interrupt Flag (Read Only) + * | | |0 = The valid data count within the transmit FIFO buffer is larger than the setting value of TXTH. + * | | |1 = The valid data count within the transmit FIFO buffer is less than or equal to the setting value of TXTH. + * |[19] |TXUFIF |TX Underflow Interrupt Flag + * | | |When the TX underflow event occurs, this bit will be set to 1, the state of data output pin depends on the setting of TXUFPOL. + * | | |0 = No effect. + * | | |1 = No data in Transmit FIFO and TX shift register when the slave selection signal is active. + * | | |Note 1: This bit will be cleared by writing 1 to it. + * | | |Note 2: If reset slaveu2019s transmission circuit when slave selection signal is active, this flag will be set to 1 after 2 peripheral clock cycles + 3 system clock cycles since the reset operation is done. + * |[23] |TXRXRST |TX or RX Reset Status (Read Only) + * | | |0 = The reset function of TXRST or RXRST is done. + * | | |1 = Doing the reset function of TXRST or RXRST. + * | | |Note: Both the reset operations of TXRST and RXRST need 3 system clock cycles + 2 peripheral clock cycles. + * | | |User can check the status of this bit to monitor the reset function is doing or done. + * |[27:24] |RXCNT |Receive FIFO Data Count (Read Only) + * | | |This bit field indicates the valid data count of receive FIFO buffer. + * |[31:28] |TXCNT |Transmit FIFO Data Count (Read Only) + * | | |This bit field indicates the valid data count of transmit FIFO buffer. + * @var SPI_T::TX + * Offset: 0x20 SPI Data Transmit Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |TX |Data Transmit Register + * | | |The data transmit registers pass through the transmitted data into the 4-level transmit FIFO buffers. + * | | |The number of valid bits depends on the setting of DWIDTH (SPIx_CTL[12:8]) in SPI mode or WDWIDTH (SPIx_I2SCTL[5:4]) in I2S mode. + * | | |For exampleIn SPI mode, if DWIDTH is set to 0x08, the bits TX[7:0] will be transmitted. + * | | |If DWIDTH is set to 0x00 , the SPI controller will perform a 32-bit transfer. + * | | |In I2S mode, if WDWIDTH (SPIx_I2SCTL[5:4]) is set to 0x2, the data width of audio channel is 24-bit and corresponding to TX[243:0]. + * | | |If WDWIDTH is set as 0x0, 0x1, or 0x3, all bits of this field are valid and referred to the data arrangement in I2S mode FIFO operation section. + * | | |Note: In Master mode, SPI controller will start to transfer the SPI bus clock after 1 APB clock and 6 peripheral clock cycles after user writes to this register. + * @var SPI_T::RX + * Offset: 0x30 SPI Data Receive Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |RX |Data Receive Register + * | | |There are 8-/4-level FIFO buffers in this controller. + * | | |The data receive register holds the data received from SPI data input pin. + * | | |If the RXEMPTY (SPIx_STATUS[8] or SPIx_I2SSTS[8]) is not set to 1, the receive FIFO buffers can be accessed through software by reading this register. + * | | |This is a read only register. + * @var SPI_T::I2SCTL + * Offset: 0x60 I2S Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |I2SEN |I2S Controller Enable Bit + * | | |0 = Disabled I2S mode. + * | | |1 = Enabled I2S mode. + * | | |Note: + * | | |1. If enable this bit, I2Sx_BCLK will start to output in master Master mode. + * | | |2. Before changing the configurations of SPIx_I2SCTL, SPIx_I2SCLK, and SPIx_FIFOCTL registers, user shall clear the I2SEN (SPIx_I2SCTL[0]) and confirm the I2SENSTS (SPIx_I2SSTS[15]) is 0. + * |[1] |TXEN |Transmit Enable Bit + * | | |0 = Data transmit Disabled. + * | | |1 = Data transmit Enabled. + * |[2] |RXEN |Receive Enable Bit + * | | |0 = Data receiving receive Disabled. + * | | |1 = Data receiving receive Enabled. + * |[3] |MUTE |Transmit Mute Enable Bit + * | | |0 = Transmit data is shifted from buffer. + * | | |1 = Transmit channel zero. + * |[5:4] |WDWIDTH |Word Width + * | | |00 = data size is 8-bit. + * | | |01 = data size is 16-bit. + * | | |10 = data size is 24-bit. + * | | |11 = data size is 32-bit. + * |[6] |MONO |Monaural Data + * | | |0 = Data is stereo format. + * | | |1 = Data is monaural format. + * |[7] |ORDER |Stereo Data Order in FIFO + * | | |0 = Left channel data at high byte. + * | | |1 = Left channel data at low byte. + * |[8] |SLAVE |Slave Mode + * | | |I2S can operate as master or slave + * | | |In Master mode, I2Sx_BCLK and I2Sx_LRCLK pins are output mode and send bit clock from M031 series to Audio audio CODEC chip. + * | | |In Slave mode, I2Sx_BCLK and I2Sx_LRCLK pins are input mode and I2Sx_BCLK and I2Sx_LRCLK signals are received from outer Audio audio CODEC chip. + * | | |0 = Master mode. + * | | |1 = Slave mode. + * |[15] |MCLKEN |Master Clock Enable Bit + * | | |If MCLKEN is set to 1, I2S controller will generate master clock on SPIx_I2SMCLK pin for external audio devices. + * | | |0 = Master clock Disabled. + * | | |1 = Master clock Enabled. + * |[16] |RZCEN |Right Channel Zero Cross Detection Enable Bit + * | | |If this bit is set to 1, when right channel data sign bit change or next shift data bits are all 0 then RZCIF flag in SPIx_I2SSTS register is set to 1. + * | | |This function is only available in transmit operation. + * | | |0 = Right channel zero cross detection Disabled. + * | | |1 = Right channel zero cross detection Enabled. + * |[17] |LZCEN |Left Channel Zero Cross Detection Enable Bit + * | | |If this bit is set to 1, when left channel data sign bit changes or next shift data bits are all 0 then LZCIF flag in SPIx_I2SSTS register is set to 1. + * | | |This function is only available in transmit operation. + * | | |0 = Left channel zero cross detection Disabled. + * | | |1 = Left channel zero cross detection Enabled. + * |[23] |RXLCH |Receive Left Channel Enable Bit + * | | |When monaural format is selected (MONO = 1), I2S controller will receive right channel data if RXLCH is set to 0, and receive left channel data if RXLCH is set to 1. + * | | |0 = Receive right channel data in Mono mode. + * | | |1 = Receive left channel data in Mono mode. + * |[24] |RZCIEN |Right Channel Zero- CCross Interrupt Enable Bit + * | | |Interrupt occurs if this bit is set to 1 and right channel zero- cross event occurs. + * | | |0 = Interrupt Disabled. + * | | |1 = Interrupt Enabled. + * |[25] |LZCIEN |Left Channel Zero- CCross Interrupt Enable Bit + * | | |Interrupt occurs if this bit is set to 1 and left channel zero- cross event occurs. + * | | |0 = Interrupt Disabled. + * | | |1 = Interrupt Enabled. + * |[29:28] |FORMAT |Data Format Selection + * | | |00 = I2S data format. + * | | |01 = MSB justified data format. + * | | |10 = PCM mode A. + * | | |11 = PCM mode B. + * @var SPI_T::I2SCLK + * Offset: 0x64 I2S Clock Divider Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[6:0] |MCLKDIV |Master Clock Divider + * | | |If MCLKEN is set to 1, I2S controller will generate master clock for external audio devices. + * | | |The master clock rate, F_MCLK, is determined by the following expressions. + * | | |If MCLKDIV >= 1, F_MCLK = F_I2SCLK/(2x(MCLKDIV)). + * | | |If MCLKDIV = 0, F_MCLK = F_I2SCLK. + * | | |F_I2SCLK is the frequency of I2S peripheral clock. + * | | |In general, the master clock rate is 256 times sampling clock rate. + * |[17:8] |BCLKDIV |Bit Clock Divider + * | | |The I2S controller will generate bit clock in Master mode. + * | | |The bit clock rate, F_BCLK, is determined by the following expression. + * | | |F_BCLK = F_I2SCLK /(2x(BCLKDIV + 1)) , where F_I2SCLK is the frequency of I2S peripheral clock. + * @var SPI_T::I2SSTS + * Offset: 0x68 I2S Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[4] |RIGHT |Right Channel (Read Only) + * | | |This bit indicates the current transmit data is belong to which channel. + * | | |0 = Left channel. + * | | |1 = Right channel. + * |[8] |RXEMPTY |Receive FIFO Buffer Empty Indicator (Read Only) + * | | |0 = Receive FIFO buffer is not empty. + * | | |1 = Receive FIFO buffer is empty. + * |[9] |RXFULL |Receive FIFO Buffer Full Indicator (Read Only) + * | | |0 = Receive FIFO buffer is not full. + * | | |1 = Receive FIFO buffer is full. + * |[10] |RXTHIF |Receive FIFO Threshold Interrupt Flag (Read Only) + * | | |0 = The valid data count within the Rxreceive FIFO buffer is smaller than or equal to the setting value of RXTH. + * | | |1 = The valid data count within the receive FIFO buffer is larger than the setting value of RXTH. + * | | |Note: If RXTHIEN = 1 and RXTHIF = 1, the SPI/I2S controller will generate a SPI interrupt request. + * |[11] |RXOVIF |Receive FIFO Overrun Interrupt Flag + * | | |When the receive FIFO buffer is full, the follow-up data will be dropped and this bit will be set to 1. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[12] |RXTOIF |Receive Time-out Interrupt Flag + * | | |0 = No receive FIFO time-out event. + * | | |1 = Receive FIFO buffer is not empty and no read operation on receive FIFO buffer over 64 SPI peripheral clock period in Master mode or over 576 SPI peripheral clock period in Slave mode. + * | | |When the received FIFO buffer is read by software, the time-out status will be cleared automatically. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[15] |I2SENSTS |I2S Enable Status (Read Only) + * | | |0 = The SPI/I2S control logic is disabled. + * | | |1 = The SPI/I2S control logic is enabled. + * | | |Note: The SPI peripheral clock is asynchronous with the system clock + * | | |In order to make sure the SPI/I2S controller logic is disabled, this bit indicates the real status of SPI/I2S controller logic for user. + * |[16] |TXEMPTY |Transmit FIFO Buffer Empty Indicator (Read Only) + * | | |0 = Transmit FIFO buffer is not empty. + * | | |1 = Transmit FIFO buffer is empty. + * |[17] |TXFULL |Transmit FIFO Buffer Full Indicator (Read Only) + * | | |0 = Transmit FIFO buffer is not full. + * | | |1 = Transmit FIFO buffer is full. + * |[18] |TXTHIF |Transmit FIFO Threshold Interrupt Flag (Read Only) + * | | |0 = The valid data count within the transmit FIFO buffer is larger than the setting value of TXTH. + * | | |1 = The valid data count within the transmit FIFO buffer is less than or equal to the setting value of TXTH. + * | | |Note: If TXTHIEN = 1 and TXTHIF = 1, the SPI/I2S controller will generate a SPI interrupt request. + * |[19] |TXUFIF |Transmit FIFO Underflow Interrupt Flag + * | | |When the transmit FIFO buffer is empty and there is no datum written into the FIFO buffer, if there is more bus clock input, this bit will be set to 1. + * | | |Note: This bit will be cleared by writing 1 to it. + * |[20] |RZCIF |Right Channel Zero Cross Interrupt Flag + * | | |0 = No zero cross event occurred on right channel. + * | | |1 = Zero cross event occurred on right channel. + * |[21] |LZCIF |Left Channel Zero Cross Interrupt Flag + * | | |0 = No zero cross event occurred on left channel. + * | | |1 = Zero cross event occurred on left channel. + * |[23] |TXRXRST |TX or RX Reset Status (Read Only) + * | | |0 = The reset function of TXRST or RXRST is done. + * | | |1 = Doing the reset function of TXRST or RXRST. + * | | |Note: Both the reset operations of TXRST and RXRST need 3 system clock cycles + 2 peripheral clock cycles. + * | | |User can check the status of this bit to monitor the reset function is doing or done. + * |[26:24] |RXCNT |Receive FIFO Data Count (Read Only) + * | | |This bit field indicates the valid data count of receive FIFO buffer. + * |[30:28] |TXCNT |Transmit FIFO Data Count (Read Only) + * | | |This bit field indicates the valid data count of transmit FIFO buffer. + */ + + __IO uint32_t CTL; /*!< [0x0000] SPI Control Register */ + __IO uint32_t CLKDIV; /*!< [0x0004] SPI Clock Divider Register */ + __IO uint32_t SSCTL; /*!< [0x0008] SPI Slave Select Control Register */ + __IO uint32_t PDMACTL; /*!< [0x000c] SPI PDMA Control Register */ + __IO uint32_t FIFOCTL; /*!< [0x0010] SPI FIFO Control Register */ + __IO uint32_t STATUS; /*!< [0x0014] SPI Status Register */ + __I uint32_t RESERVE0[2]; + __O uint32_t TX; /*!< [0x0020] SPI Data Transmit Register */ + __I uint32_t RESERVE1[3]; + __I uint32_t RX; /*!< [0x0030] SPI Data Receive Register */ + __I uint32_t RESERVE2[11]; + __IO uint32_t I2SCTL; /*!< [0x0060] I2S Control Register */ + __IO uint32_t I2SCLK; /*!< [0x0064] I2S Clock Divider Control Register */ + __IO uint32_t I2SSTS; /*!< [0x0068] I2S Status Register */ + +} SPI_T; + +/** + @addtogroup SPI_CONST SPI Bit Field Definition + Constant Definitions for SPI Controller +@{ */ + +#define SPI_CTL_SPIEN_Pos (0) /*!< SPI_T::CTL: SPIEN Position */ +#define SPI_CTL_SPIEN_Msk (0x1ul << SPI_CTL_SPIEN_Pos) /*!< SPI_T::CTL: SPIEN Mask */ + +#define SPI_CTL_RXNEG_Pos (1) /*!< SPI_T::CTL: RXNEG Position */ +#define SPI_CTL_RXNEG_Msk (0x1ul << SPI_CTL_RXNEG_Pos) /*!< SPI_T::CTL: RXNEG Mask */ + +#define SPI_CTL_TXNEG_Pos (2) /*!< SPI_T::CTL: TXNEG Position */ +#define SPI_CTL_TXNEG_Msk (0x1ul << SPI_CTL_TXNEG_Pos) /*!< SPI_T::CTL: TXNEG Mask */ + +#define SPI_CTL_CLKPOL_Pos (3) /*!< SPI_T::CTL: CLKPOL Position */ +#define SPI_CTL_CLKPOL_Msk (0x1ul << SPI_CTL_CLKPOL_Pos) /*!< SPI_T::CTL: CLKPOL Mask */ + +#define SPI_CTL_SUSPITV_Pos (4) /*!< SPI_T::CTL: SUSPITV Position */ +#define SPI_CTL_SUSPITV_Msk (0xful << SPI_CTL_SUSPITV_Pos) /*!< SPI_T::CTL: SUSPITV Mask */ + +#define SPI_CTL_DWIDTH_Pos (8) /*!< SPI_T::CTL: DWIDTH Position */ +#define SPI_CTL_DWIDTH_Msk (0x1ful << SPI_CTL_DWIDTH_Pos) /*!< SPI_T::CTL: DWIDTH Mask */ + +#define SPI_CTL_LSB_Pos (13) /*!< SPI_T::CTL: LSB Position */ +#define SPI_CTL_LSB_Msk (0x1ul << SPI_CTL_LSB_Pos) /*!< SPI_T::CTL: LSB Mask */ + +#define SPI_CTL_HALFDPX_Pos (14) /*!< SPI_T::CTL: HALFDPX Position */ +#define SPI_CTL_HALFDPX_Msk (0x1ul << SPI_CTL_HALFDPX_Pos) /*!< SPI_T::CTL: HALFDPX Mask */ + +#define SPI_CTL_RXONLY_Pos (15) /*!< SPI_T::CTL: RXONLY Position */ +#define SPI_CTL_RXONLY_Msk (0x1ul << SPI_CTL_RXONLY_Pos) /*!< SPI_T::CTL: RXONLY Mask */ + +#define SPI_CTL_UNITIEN_Pos (17) /*!< SPI_T::CTL: UNITIEN Position */ +#define SPI_CTL_UNITIEN_Msk (0x1ul << SPI_CTL_UNITIEN_Pos) /*!< SPI_T::CTL: UNITIEN Mask */ + +#define SPI_CTL_SLAVE_Pos (18) /*!< SPI_T::CTL: SLAVE Position */ +#define SPI_CTL_SLAVE_Msk (0x1ul << SPI_CTL_SLAVE_Pos) /*!< SPI_T::CTL: SLAVE Mask */ + +#define SPI_CTL_REORDER_Pos (19) /*!< SPI_T::CTL: REORDER Position */ +#define SPI_CTL_REORDER_Msk (0x1ul << SPI_CTL_REORDER_Pos) /*!< SPI_T::CTL: REORDER Mask */ + +#define SPI_CTL_DATDIR_Pos (20) /*!< SPI_T::CTL: DATDIR Position */ +#define SPI_CTL_DATDIR_Msk (0x1ul << SPI_CTL_DATDIR_Pos) /*!< SPI_T::CTL: DATDIR Mask */ + +#define SPI_CLKDIV_DIVIDER_Pos (0) /*!< SPI_T::CLKDIV: DIVIDER Position */ +#define SPI_CLKDIV_DIVIDER_Msk (0x1fful << SPI_CLKDIV_DIVIDER_Pos) /*!< SPI_T::CLKDIV: DIVIDER Mask */ + +#define SPI_SSCTL_SS_Pos (0) /*!< SPI_T::SSCTL: SS Position */ +#define SPI_SSCTL_SS_Msk (0x1ul << SPI_SSCTL_SS_Pos) /*!< SPI_T::SSCTL: SS Mask */ + +#define SPI_SSCTL_SSACTPOL_Pos (2) /*!< SPI_T::SSCTL: SSACTPOL Position */ +#define SPI_SSCTL_SSACTPOL_Msk (0x1ul << SPI_SSCTL_SSACTPOL_Pos) /*!< SPI_T::SSCTL: SSACTPOL Mask */ + +#define SPI_SSCTL_AUTOSS_Pos (3) /*!< SPI_T::SSCTL: AUTOSS Position */ +#define SPI_SSCTL_AUTOSS_Msk (0x1ul << SPI_SSCTL_AUTOSS_Pos) /*!< SPI_T::SSCTL: AUTOSS Mask */ + +#define SPI_SSCTL_SLVBEIEN_Pos (8) /*!< SPI_T::SSCTL: SLVBEIEN Position */ +#define SPI_SSCTL_SLVBEIEN_Msk (0x1ul << SPI_SSCTL_SLVBEIEN_Pos) /*!< SPI_T::SSCTL: SLVBEIEN Mask */ + +#define SPI_SSCTL_SLVURIEN_Pos (9) /*!< SPI_T::SSCTL: SLVURIEN Position */ +#define SPI_SSCTL_SLVURIEN_Msk (0x1ul << SPI_SSCTL_SLVURIEN_Pos) /*!< SPI_T::SSCTL: SLVURIEN Mask */ + +#define SPI_SSCTL_SSACTIEN_Pos (12) /*!< SPI_T::SSCTL: SSACTIEN Position */ +#define SPI_SSCTL_SSACTIEN_Msk (0x1ul << SPI_SSCTL_SSACTIEN_Pos) /*!< SPI_T::SSCTL: SSACTIEN Mask */ + +#define SPI_SSCTL_SSINAIEN_Pos (13) /*!< SPI_T::SSCTL: SSINAIEN Position */ +#define SPI_SSCTL_SSINAIEN_Msk (0x1ul << SPI_SSCTL_SSINAIEN_Pos) /*!< SPI_T::SSCTL: SSINAIEN Mask */ + +#define SPI_PDMACTL_TXPDMAEN_Pos (0) /*!< SPI_T::PDMACTL: TXPDMAEN Position */ +#define SPI_PDMACTL_TXPDMAEN_Msk (0x1ul << SPI_PDMACTL_TXPDMAEN_Pos) /*!< SPI_T::PDMACTL: TXPDMAEN Mask */ + +#define SPI_PDMACTL_RXPDMAEN_Pos (1) /*!< SPI_T::PDMACTL: RXPDMAEN Position */ +#define SPI_PDMACTL_RXPDMAEN_Msk (0x1ul << SPI_PDMACTL_RXPDMAEN_Pos) /*!< SPI_T::PDMACTL: RXPDMAEN Mask */ + +#define SPI_PDMACTL_PDMARST_Pos (2) /*!< SPI_T::PDMACTL: PDMARST Position */ +#define SPI_PDMACTL_PDMARST_Msk (0x1ul << SPI_PDMACTL_PDMARST_Pos) /*!< SPI_T::PDMACTL: PDMARST Mask */ + +#define SPI_FIFOCTL_RXRST_Pos (0) /*!< SPI_T::FIFOCTL: RXRST Position */ +#define SPI_FIFOCTL_RXRST_Msk (0x1ul << SPI_FIFOCTL_RXRST_Pos) /*!< SPI_T::FIFOCTL: RXRST Mask */ + +#define SPI_FIFOCTL_TXRST_Pos (1) /*!< SPI_T::FIFOCTL: TXRST Position */ +#define SPI_FIFOCTL_TXRST_Msk (0x1ul << SPI_FIFOCTL_TXRST_Pos) /*!< SPI_T::FIFOCTL: TXRST Mask */ + +#define SPI_FIFOCTL_RXTHIEN_Pos (2) /*!< SPI_T::FIFOCTL: RXTHIEN Position */ +#define SPI_FIFOCTL_RXTHIEN_Msk (0x1ul << SPI_FIFOCTL_RXTHIEN_Pos) /*!< SPI_T::FIFOCTL: RXTHIEN Mask */ + +#define SPI_FIFOCTL_TXTHIEN_Pos (3) /*!< SPI_T::FIFOCTL: TXTHIEN Position */ +#define SPI_FIFOCTL_TXTHIEN_Msk (0x1ul << SPI_FIFOCTL_TXTHIEN_Pos) /*!< SPI_T::FIFOCTL: TXTHIEN Mask */ + +#define SPI_FIFOCTL_RXTOIEN_Pos (4) /*!< SPI_T::FIFOCTL: RXTOIEN Position */ +#define SPI_FIFOCTL_RXTOIEN_Msk (0x1ul << SPI_FIFOCTL_RXTOIEN_Pos) /*!< SPI_T::FIFOCTL: RXTOIEN Mask */ + +#define SPI_FIFOCTL_RXOVIEN_Pos (5) /*!< SPI_T::FIFOCTL: RXOVIEN Position */ +#define SPI_FIFOCTL_RXOVIEN_Msk (0x1ul << SPI_FIFOCTL_RXOVIEN_Pos) /*!< SPI_T::FIFOCTL: RXOVIEN Mask */ + +#define SPI_FIFOCTL_TXUFPOL_Pos (6) /*!< SPI_T::FIFOCTL: TXUFPOL Position */ +#define SPI_FIFOCTL_TXUFPOL_Msk (0x1ul << SPI_FIFOCTL_TXUFPOL_Pos) /*!< SPI_T::FIFOCTL: TXUFPOL Mask */ + +#define SPI_FIFOCTL_TXUFIEN_Pos (7) /*!< SPI_T::FIFOCTL: TXUFIEN Position */ +#define SPI_FIFOCTL_TXUFIEN_Msk (0x1ul << SPI_FIFOCTL_TXUFIEN_Pos) /*!< SPI_T::FIFOCTL: TXUFIEN Mask */ + +#define SPI_FIFOCTL_RXFBCLR_Pos (8) /*!< SPI_T::FIFOCTL: RXFBCLR Position */ +#define SPI_FIFOCTL_RXFBCLR_Msk (0x1ul << SPI_FIFOCTL_RXFBCLR_Pos) /*!< SPI_T::FIFOCTL: RXFBCLR Mask */ + +#define SPI_FIFOCTL_TXFBCLR_Pos (9) /*!< SPI_T::FIFOCTL: TXFBCLR Position */ +#define SPI_FIFOCTL_TXFBCLR_Msk (0x1ul << SPI_FIFOCTL_TXFBCLR_Pos) /*!< SPI_T::FIFOCTL: TXFBCLR Mask */ + +#define SPI_FIFOCTL_RXTH_Pos (24) /*!< SPI_T::FIFOCTL: RXTH Position */ +#define SPI_FIFOCTL_RXTH_Msk (0x7ul << SPI_FIFOCTL_RXTH_Pos) /*!< SPI_T::FIFOCTL: RXTH Mask */ + +#define SPI_FIFOCTL_TXTH_Pos (28) /*!< SPI_T::FIFOCTL: TXTH Position */ +#define SPI_FIFOCTL_TXTH_Msk (0x7ul << SPI_FIFOCTL_TXTH_Pos) /*!< SPI_T::FIFOCTL: TXTH Mask */ + +#define SPI_STATUS_BUSY_Pos (0) /*!< SPI_T::STATUS: BUSY Position */ +#define SPI_STATUS_BUSY_Msk (0x1ul << SPI_STATUS_BUSY_Pos) /*!< SPI_T::STATUS: BUSY Mask */ + +#define SPI_STATUS_UNITIF_Pos (1) /*!< SPI_T::STATUS: UNITIF Position */ +#define SPI_STATUS_UNITIF_Msk (0x1ul << SPI_STATUS_UNITIF_Pos) /*!< SPI_T::STATUS: UNITIF Mask */ + +#define SPI_STATUS_SSACTIF_Pos (2) /*!< SPI_T::STATUS: SSACTIF Position */ +#define SPI_STATUS_SSACTIF_Msk (0x1ul << SPI_STATUS_SSACTIF_Pos) /*!< SPI_T::STATUS: SSACTIF Mask */ + +#define SPI_STATUS_SSINAIF_Pos (3) /*!< SPI_T::STATUS: SSINAIF Position */ +#define SPI_STATUS_SSINAIF_Msk (0x1ul << SPI_STATUS_SSINAIF_Pos) /*!< SPI_T::STATUS: SSINAIF Mask */ + +#define SPI_STATUS_SSLINE_Pos (4) /*!< SPI_T::STATUS: SSLINE Position */ +#define SPI_STATUS_SSLINE_Msk (0x1ul << SPI_STATUS_SSLINE_Pos) /*!< SPI_T::STATUS: SSLINE Mask */ + +#define SPI_STATUS_SLVBEIF_Pos (6) /*!< SPI_T::STATUS: SLVBEIF Position */ +#define SPI_STATUS_SLVBEIF_Msk (0x1ul << SPI_STATUS_SLVBEIF_Pos) /*!< SPI_T::STATUS: SLVBEIF Mask */ + +#define SPI_STATUS_SLVURIF_Pos (7) /*!< SPI_T::STATUS: SLVURIF Position */ +#define SPI_STATUS_SLVURIF_Msk (0x1ul << SPI_STATUS_SLVURIF_Pos) /*!< SPI_T::STATUS: SLVURIF Mask */ + +#define SPI_STATUS_RXEMPTY_Pos (8) /*!< SPI_T::STATUS: RXEMPTY Position */ +#define SPI_STATUS_RXEMPTY_Msk (0x1ul << SPI_STATUS_RXEMPTY_Pos) /*!< SPI_T::STATUS: RXEMPTY Mask */ + +#define SPI_STATUS_RXFULL_Pos (9) /*!< SPI_T::STATUS: RXFULL Position */ +#define SPI_STATUS_RXFULL_Msk (0x1ul << SPI_STATUS_RXFULL_Pos) /*!< SPI_T::STATUS: RXFULL Mask */ + +#define SPI_STATUS_RXTHIF_Pos (10) /*!< SPI_T::STATUS: RXTHIF Position */ +#define SPI_STATUS_RXTHIF_Msk (0x1ul << SPI_STATUS_RXTHIF_Pos) /*!< SPI_T::STATUS: RXTHIF Mask */ + +#define SPI_STATUS_RXOVIF_Pos (11) /*!< SPI_T::STATUS: RXOVIF Position */ +#define SPI_STATUS_RXOVIF_Msk (0x1ul << SPI_STATUS_RXOVIF_Pos) /*!< SPI_T::STATUS: RXOVIF Mask */ + +#define SPI_STATUS_RXTOIF_Pos (12) /*!< SPI_T::STATUS: RXTOIF Position */ +#define SPI_STATUS_RXTOIF_Msk (0x1ul << SPI_STATUS_RXTOIF_Pos) /*!< SPI_T::STATUS: RXTOIF Mask */ + +#define SPI_STATUS_SPIENSTS_Pos (15) /*!< SPI_T::STATUS: SPIENSTS Position */ +#define SPI_STATUS_SPIENSTS_Msk (0x1ul << SPI_STATUS_SPIENSTS_Pos) /*!< SPI_T::STATUS: SPIENSTS Mask */ + +#define SPI_STATUS_TXEMPTY_Pos (16) /*!< SPI_T::STATUS: TXEMPTY Position */ +#define SPI_STATUS_TXEMPTY_Msk (0x1ul << SPI_STATUS_TXEMPTY_Pos) /*!< SPI_T::STATUS: TXEMPTY Mask */ + +#define SPI_STATUS_TXFULL_Pos (17) /*!< SPI_T::STATUS: TXFULL Position */ +#define SPI_STATUS_TXFULL_Msk (0x1ul << SPI_STATUS_TXFULL_Pos) /*!< SPI_T::STATUS: TXFULL Mask */ + +#define SPI_STATUS_TXTHIF_Pos (18) /*!< SPI_T::STATUS: TXTHIF Position */ +#define SPI_STATUS_TXTHIF_Msk (0x1ul << SPI_STATUS_TXTHIF_Pos) /*!< SPI_T::STATUS: TXTHIF Mask */ + +#define SPI_STATUS_TXUFIF_Pos (19) /*!< SPI_T::STATUS: TXUFIF Position */ +#define SPI_STATUS_TXUFIF_Msk (0x1ul << SPI_STATUS_TXUFIF_Pos) /*!< SPI_T::STATUS: TXUFIF Mask */ + +#define SPI_STATUS_TXRXRST_Pos (23) /*!< SPI_T::STATUS: TXRXRST Position */ +#define SPI_STATUS_TXRXRST_Msk (0x1ul << SPI_STATUS_TXRXRST_Pos) /*!< SPI_T::STATUS: TXRXRST Mask */ + +#define SPI_STATUS_RXCNT_Pos (24) /*!< SPI_T::STATUS: RXCNT Position */ +#define SPI_STATUS_RXCNT_Msk (0xful << SPI_STATUS_RXCNT_Pos) /*!< SPI_T::STATUS: RXCNT Mask */ + +#define SPI_STATUS_TXCNT_Pos (28) /*!< SPI_T::STATUS: TXCNT Position */ +#define SPI_STATUS_TXCNT_Msk (0xful << SPI_STATUS_TXCNT_Pos) /*!< SPI_T::STATUS: TXCNT Mask */ + +#define SPI_TX_TX_Pos (0) /*!< SPI_T::TX: TX Position */ +#define SPI_TX_TX_Msk (0xfffffffful << SPI_TX_TX_Pos) /*!< SPI_T::TX: TX Mask */ + +#define SPI_RX_RX_Pos (0) /*!< SPI_T::RX: RX Position */ +#define SPI_RX_RX_Msk (0xfffffffful << SPI_RX_RX_Pos) /*!< SPI_T::RX: RX Mask */ + +#define SPI_I2SCTL_I2SEN_Pos (0) /*!< SPI_T::I2SCTL: I2SEN Position */ +#define SPI_I2SCTL_I2SEN_Msk (0x1ul << SPI_I2SCTL_I2SEN_Pos) /*!< SPI_T::I2SCTL: I2SEN Mask */ + +#define SPI_I2SCTL_TXEN_Pos (1) /*!< SPI_T::I2SCTL: TXEN Position */ +#define SPI_I2SCTL_TXEN_Msk (0x1ul << SPI_I2SCTL_TXEN_Pos) /*!< SPI_T::I2SCTL: TXEN Mask */ + +#define SPI_I2SCTL_RXEN_Pos (2) /*!< SPI_T::I2SCTL: RXEN Position */ +#define SPI_I2SCTL_RXEN_Msk (0x1ul << SPI_I2SCTL_RXEN_Pos) /*!< SPI_T::I2SCTL: RXEN Mask */ + +#define SPI_I2SCTL_MUTE_Pos (3) /*!< SPI_T::I2SCTL: MUTE Position */ +#define SPI_I2SCTL_MUTE_Msk (0x1ul << SPI_I2SCTL_MUTE_Pos) /*!< SPI_T::I2SCTL: MUTE Mask */ + +#define SPI_I2SCTL_WDWIDTH_Pos (4) /*!< SPI_T::I2SCTL: WDWIDTH Position */ +#define SPI_I2SCTL_WDWIDTH_Msk (0x3ul << SPI_I2SCTL_WDWIDTH_Pos) /*!< SPI_T::I2SCTL: WDWIDTH Mask */ + +#define SPI_I2SCTL_MONO_Pos (6) /*!< SPI_T::I2SCTL: MONO Position */ +#define SPI_I2SCTL_MONO_Msk (0x1ul << SPI_I2SCTL_MONO_Pos) /*!< SPI_T::I2SCTL: MONO Mask */ + +#define SPI_I2SCTL_ORDER_Pos (7) /*!< SPI_T::I2SCTL: ORDER Position */ +#define SPI_I2SCTL_ORDER_Msk (0x1ul << SPI_I2SCTL_ORDER_Pos) /*!< SPI_T::I2SCTL: ORDER Mask */ + +#define SPI_I2SCTL_SLAVE_Pos (8) /*!< SPI_T::I2SCTL: SLAVE Position */ +#define SPI_I2SCTL_SLAVE_Msk (0x1ul << SPI_I2SCTL_SLAVE_Pos) /*!< SPI_T::I2SCTL: SLAVE Mask */ + +#define SPI_I2SCTL_MCLKEN_Pos (15) /*!< SPI_T::I2SCTL: MCLKEN Position */ +#define SPI_I2SCTL_MCLKEN_Msk (0x1ul << SPI_I2SCTL_MCLKEN_Pos) /*!< SPI_T::I2SCTL: MCLKEN Mask */ + +#define SPI_I2SCTL_RZCEN_Pos (16) /*!< SPI_T::I2SCTL: RZCEN Position */ +#define SPI_I2SCTL_RZCEN_Msk (0x1ul << SPI_I2SCTL_RZCEN_Pos) /*!< SPI_T::I2SCTL: RZCEN Mask */ + +#define SPI_I2SCTL_LZCEN_Pos (17) /*!< SPI_T::I2SCTL: LZCEN Position */ +#define SPI_I2SCTL_LZCEN_Msk (0x1ul << SPI_I2SCTL_LZCEN_Pos) /*!< SPI_T::I2SCTL: LZCEN Mask */ + +#define SPI_I2SCTL_RXLCH_Pos (23) /*!< SPI_T::I2SCTL: RXLCH Position */ +#define SPI_I2SCTL_RXLCH_Msk (0x1ul << SPI_I2SCTL_RXLCH_Pos) /*!< SPI_T::I2SCTL: RXLCH Mask */ + +#define SPI_I2SCTL_RZCIEN_Pos (24) /*!< SPI_T::I2SCTL: RZCIEN Position */ +#define SPI_I2SCTL_RZCIEN_Msk (0x1ul << SPI_I2SCTL_RZCIEN_Pos) /*!< SPI_T::I2SCTL: RZCIEN Mask */ + +#define SPI_I2SCTL_LZCIEN_Pos (25) /*!< SPI_T::I2SCTL: LZCIEN Position */ +#define SPI_I2SCTL_LZCIEN_Msk (0x1ul << SPI_I2SCTL_LZCIEN_Pos) /*!< SPI_T::I2SCTL: LZCIEN Mask */ + +#define SPI_I2SCTL_FORMAT_Pos (28) /*!< SPI_T::I2SCTL: FORMAT Position */ +#define SPI_I2SCTL_FORMAT_Msk (0x3ul << SPI_I2SCTL_FORMAT_Pos) /*!< SPI_T::I2SCTL: FORMAT Mask */ + +#define SPI_I2SCLK_MCLKDIV_Pos (0) /*!< SPI_T::I2SCLK: MCLKDIV Position */ +#define SPI_I2SCLK_MCLKDIV_Msk (0x7ful << SPI_I2SCLK_MCLKDIV_Pos) /*!< SPI_T::I2SCLK: MCLKDIV Mask */ + +#define SPI_I2SCLK_BCLKDIV_Pos (8) /*!< SPI_T::I2SCLK: BCLKDIV Position */ +#define SPI_I2SCLK_BCLKDIV_Msk (0x3fful << SPI_I2SCLK_BCLKDIV_Pos) /*!< SPI_T::I2SCLK: BCLKDIV Mask */ + +#define SPI_I2SSTS_RIGHT_Pos (4) /*!< SPI_T::I2SSTS: RIGHT Position */ +#define SPI_I2SSTS_RIGHT_Msk (0x1ul << SPI_I2SSTS_RIGHT_Pos) /*!< SPI_T::I2SSTS: RIGHT Mask */ + +#define SPI_I2SSTS_RXEMPTY_Pos (8) /*!< SPI_T::I2SSTS: RXEMPTY Position */ +#define SPI_I2SSTS_RXEMPTY_Msk (0x1ul << SPI_I2SSTS_RXEMPTY_Pos) /*!< SPI_T::I2SSTS: RXEMPTY Mask */ + +#define SPI_I2SSTS_RXFULL_Pos (9) /*!< SPI_T::I2SSTS: RXFULL Position */ +#define SPI_I2SSTS_RXFULL_Msk (0x1ul << SPI_I2SSTS_RXFULL_Pos) /*!< SPI_T::I2SSTS: RXFULL Mask */ + +#define SPI_I2SSTS_RXTHIF_Pos (10) /*!< SPI_T::I2SSTS: RXTHIF Position */ +#define SPI_I2SSTS_RXTHIF_Msk (0x1ul << SPI_I2SSTS_RXTHIF_Pos) /*!< SPI_T::I2SSTS: RXTHIF Mask */ + +#define SPI_I2SSTS_RXOVIF_Pos (11) /*!< SPI_T::I2SSTS: RXOVIF Position */ +#define SPI_I2SSTS_RXOVIF_Msk (0x1ul << SPI_I2SSTS_RXOVIF_Pos) /*!< SPI_T::I2SSTS: RXOVIF Mask */ + +#define SPI_I2SSTS_RXTOIF_Pos (12) /*!< SPI_T::I2SSTS: RXTOIF Position */ +#define SPI_I2SSTS_RXTOIF_Msk (0x1ul << SPI_I2SSTS_RXTOIF_Pos) /*!< SPI_T::I2SSTS: RXTOIF Mask */ + +#define SPI_I2SSTS_I2SENSTS_Pos (15) /*!< SPI_T::I2SSTS: I2SENSTS Position */ +#define SPI_I2SSTS_I2SENSTS_Msk (0x1ul << SPI_I2SSTS_I2SENSTS_Pos) /*!< SPI_T::I2SSTS: I2SENSTS Mask */ + +#define SPI_I2SSTS_TXEMPTY_Pos (16) /*!< SPI_T::I2SSTS: TXEMPTY Position */ +#define SPI_I2SSTS_TXEMPTY_Msk (0x1ul << SPI_I2SSTS_TXEMPTY_Pos) /*!< SPI_T::I2SSTS: TXEMPTY Mask */ + +#define SPI_I2SSTS_TXFULL_Pos (17) /*!< SPI_T::I2SSTS: TXFULL Position */ +#define SPI_I2SSTS_TXFULL_Msk (0x1ul << SPI_I2SSTS_TXFULL_Pos) /*!< SPI_T::I2SSTS: TXFULL Mask */ + +#define SPI_I2SSTS_TXTHIF_Pos (18) /*!< SPI_T::I2SSTS: TXTHIF Position */ +#define SPI_I2SSTS_TXTHIF_Msk (0x1ul << SPI_I2SSTS_TXTHIF_Pos) /*!< SPI_T::I2SSTS: TXTHIF Mask */ + +#define SPI_I2SSTS_TXUFIF_Pos (19) /*!< SPI_T::I2SSTS: TXUFIF Position */ +#define SPI_I2SSTS_TXUFIF_Msk (0x1ul << SPI_I2SSTS_TXUFIF_Pos) /*!< SPI_T::I2SSTS: TXUFIF Mask */ + +#define SPI_I2SSTS_RZCIF_Pos (20) /*!< SPI_T::I2SSTS: RZCIF Position */ +#define SPI_I2SSTS_RZCIF_Msk (0x1ul << SPI_I2SSTS_RZCIF_Pos) /*!< SPI_T::I2SSTS: RZCIF Mask */ + +#define SPI_I2SSTS_LZCIF_Pos (21) /*!< SPI_T::I2SSTS: LZCIF Position */ +#define SPI_I2SSTS_LZCIF_Msk (0x1ul << SPI_I2SSTS_LZCIF_Pos) /*!< SPI_T::I2SSTS: LZCIF Mask */ + +#define SPI_I2SSTS_TXRXRST_Pos (23) /*!< SPI_T::I2SSTS: TXRXRST Position */ +#define SPI_I2SSTS_TXRXRST_Msk (0x1ul << SPI_I2SSTS_TXRXRST_Pos) /*!< SPI_T::I2SSTS: TXRXRST Mask */ + +#define SPI_I2SSTS_RXCNT_Pos (24) /*!< SPI_T::I2SSTS: RXCNT Position */ +#define SPI_I2SSTS_RXCNT_Msk (0x7ul << SPI_I2SSTS_RXCNT_Pos) /*!< SPI_T::I2SSTS: RXCNT Mask */ + +#define SPI_I2SSTS_TXCNT_Pos (28) /*!< SPI_T::I2SSTS: TXCNT Position */ +#define SPI_I2SSTS_TXCNT_Msk (0x7ul << SPI_I2SSTS_TXCNT_Pos) /*!< SPI_T::I2SSTS: TXCNT Mask */ + +/**@}*/ /* SPI_CONST */ +/**@}*/ /* end of SPI register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __SPI_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/sys_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/sys_reg.h new file mode 100644 index 0000000000..eaf4e2f7a8 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/sys_reg.h @@ -0,0 +1,1484 @@ +/**************************************************************************//** + * @file sys_reg.h + * @version V1.00 + * @brief SYS register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __SYS_REG_H__ +#define __SYS_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup SYS System Manger Controller (SYS) + Memory Mapped Structure for SYS Controller +@{ */ + +typedef struct +{ + + + /** + * @var SYS_T::PDID + * Offset: 0x00 Part Device Identification Number Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |PDID |Part Device Identification Number (Read Only) + * | | |This register reflects device part number code. Software can read this register to identify which device is used. + * @var SYS_T::RSTSTS + * Offset: 0x04 System Reset Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |PORF |POR Reset Flag + * | | |The POR reset flag is set by the "Reset Signal" from the Power-on Reset (POR) Controller or bit CHIPRST (SYS_IPRST0[0]) to indicate the previous reset source. + * | | |0 = No reset from POR or CHIPRST. + * | | |1 = Power-on Reset (POR) or CHIPRST had issued the reset signal to reset the system. + * | | |Note: Write 1 to clear this bit to 0. + * |[1] |PINRF |NRESET Pin Reset Flag + * | | |The nRESET pin reset flag is set by the "Reset Signal" from the nRESET Pin to indicate the previous reset source. + * | | |0 = No reset from nRESET pin. + * | | |1 = Pin nRESET had issued the reset signal to reset the system. + * | | |Note: Write 1 to clear this bit to 0. + * |[2] |WDTRF |WDT Reset Flag + * | | |The WDT reset flag is set by the "Reset Signal" from the Watchdog Timer or Window Watchdog Timer to indicate the previous reset source. + * | | |0 = No reset from watchdog timer or window watchdog timer. + * | | |1 = The watchdog timer or window watchdog timer had issued the reset signal to reset the system. + * | | |Note1: Write 1 to clear this bit to 0. + * | | |Note2: Watchdog Timer register RSTF(WDT_CTL[2]) bit is set if the system has been reset by WDT time-out reset + * | | |Window Watchdog Timer register WWDTRF(WWDT_STATUS[1]) bit is set if the system has been reset by WWDT time-out reset. + * |[3] |LVRF |LVR Reset Flag + * | | |The LVR reset flag is set by the "Reset Signal" from the Low Voltage Reset Controller to indicate the previous reset source. + * | | |0 = No reset from LVR. + * | | |1 = LVR controller had issued the reset signal to reset the system. + * | | |Note: Write 1 to clear this bit to 0. + * |[4] |BODRF |BOD Reset Flag + * | | |The BOD reset flag is set by the "Reset Signal" from the Brown-Out Detector to indicate the previous reset source. + * | | |0 = No reset from BOD. + * | | |1 = The BOD had issued the reset signal to reset the system. + * | | |Note: Write 1 to clear this bit to 0. + * |[5] |SYSRF |System Reset Flag + * | | |The system reset flag is set by the "Reset Signal" from the Cortex-M0 Core to indicate the previous reset source. + * | | |0 = No reset from Cortex-M0. + * | | |1 = The Cortex- M0 had issued the reset signal to reset the system by writing 1 to the bit SYSRESETREQ(AIRCR[2], Application Interrupt and Reset Control Register, address = 0xE000ED0C) in system control registers of Cortex-M0 core. + * | | |Note: Write 1 to clear this bit to 0. + * |[7] |CPURF |CPU Reset Flag + * | | |The CPU reset flag is set by hardware if software writes CPURST (SYS_IPRST0[1]) 1 to reset Cortex- M0 Core and Flash Memory Controller (FMC). + * | | |0 = No reset from CPU. + * | | |1 = The Cortex-M0 Core and FMC are reset by software setting CPURST to 1. + * | | |Note: Write to clear this bit to 0. + * |[8] |CPULKRF |CPU Lockup Reset Flag + * | | |0 = No reset from CPU lockup happened. + * | | |1 = The Cortex-M0 lockup happened and chip is reset. + * | | |Note1: Write 1 to clear this bit to 0. + * | | |Note2: When CPU lockup happened under ICE is connected, This flag will set to 1 but chip will not reset. + * @var SYS_T::IPRST0 + * Offset: 0x08 Peripheral Reset Control Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CHIPRST |Chip One-shot Reset (Write Protect) + * | | |Setting this bit will reset the whole chip, including Processor core and all peripherals, and this bit will automatically return to 0 after the 2 clock cycles. + * | | |The CHIPRST is same as the POR reset, all the chip controllers is reset and the chip setting from flash are also reload. + * | | |About the difference between CHIPRST and SYSRESETREQ(AIRCR[2]), please refer to section 6.2.2. + * | | |0 = Chip normal operation. + * | | |1 = Chip one-shot reset. + * | | |Note1: This bit is write protected. Refer to the SYS_REGLCTL register. + * | | |Note2: Reset by powr on reset. + * |[1] |CPURST |Processor Core One-shot Reset (Write Protect) + * | | |Setting this bit will only reset the processor core and Flash Memory Controller(FMC), and this bit will automatically return to 0 after the 2 clock cycles. + * | | |0 = Processor core normal operation. + * | | |1 = Processor core one-shot reset. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[2] |PDMARST |PDMA Controller Reset (Write Protect) + * | | |Setting this bit to 1 will generate a reset signal to the PDMA + * | | |User needs to set this bit to 0 to release from reset state. + * | | |0 = PDMA controller normal operation. + * | | |1 = PDMA controller reset. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[3] |EBIRST |EBI Controller Reset (Write Protect) + * | | |Set this bit to 1 will generate a reset signal to the EBI + * | | |User needs to set this bit to 0 to release from the reset state. + * | | |0 = EBI controller normal operation. + * | | |1 = EBI controller reset. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[4] |HDIVRST |HDIV Controller Reset (Write Protect) + * | | |Set this bit to 1 will generate a reset signal to the hardware divider. + * | | |User needs to set this bit to 0 to release from the reset state. + * | | |0 = Hardware divider controller normal operation. + * | | |1 = Hardware divider controller reset. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[7] |CRCRST |CRC Calculation Controller Reset (Write Protect) + * | | |Set this bit to 1 will generate a reset signal to the CRC calculation controller + * | | |User needs to set this bit to 0 to release from the reset state. + * | | |0 = CRC calculation controller normal operation. + * | | |1 = CRC calculation controller reset. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * @var SYS_T::IPRST1 + * Offset: 0x0C Peripheral Reset Control Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |GPIORST |GPIO Controller Reset + * | | |0 = GPIO controller normal operation. + * | | |1 = GPIO controller reset. + * |[2] |TMR0RST |Timer0 Controller Reset + * | | |0 = Timer0 controller normal operation. + * | | |1 = Timer0 controller reset. + * |[3] |TMR1RST |Timer1 Controller Reset + * | | |0 = Timer1 controller normal operation. + * | | |1 = Timer1 controller reset. + * |[4] |TMR2RST |Timer2 Controller Reset + * | | |0 = Timer2 controller normal operation. + * | | |1 = Timer2 controller reset. + * |[5] |TMR3RST |Timer3 Controller Reset + * | | |0 = Timer3 controller normal operation. + * | | |1 = Timer3 controller reset. + * |[7] |ACMP01RST |Analog Comparator 0/1 Controller Reset + * | | |0 = Analog Comparator 0/1 controller normal operation. + * | | |1 = Analog Comparator 0/1 controller reset. + * |[8] |I2C0RST |I2C0 Controller Reset + * | | |0 = I2C0 controller normal operation. + * | | |1 = I2C0 controller reset. + * |[9] |I2C1RST |I2C1 Controller Reset + * | | |0 = I2C1 controller normal operation. + * | | |1 = I2C1 controller reset. + * |[13] |SPI0RST |SPI0 Controller Reset + * | | |0 = SPI0 controller normal operation. + * | | |1 = SPI0 controller reset. + * |[16] |UART0RST |UART0 Controller Reset + * | | |0 = UART0 controller normal operation. + * | | |1 = UART0 controller reset. + * |[17] |UART1RST |UART1 Controller Reset + * | | |0 = UART1 controller normal operation. + * | | |1 = UART1 controller reset. + * |[18] |UART2RST |UART2 Controller Reset + * | | |0 = UART2 controller normal operation. + * | | |1 = UART2 controller reset. + * |[27] |USBDRST |USBD Controller Reset + * | | |0 = USBD controller normal operation. + * | | |1 = USBD controller reset. + * |[28] |ADCRST |ADC Controller Reset + * | | |0 = ADC controller normal operation. + * | | |1 = ADC controller reset. + * @var SYS_T::IPRST2 + * Offset: 0x10 Peripheral Reset Control Register 2 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8] |USCI0RST |USCI0 Controller Reset + * | | |0 = USCI0 controller normal operation. + * | | |1 = USCI0 controller reset. + * |[16] |PWM0RST |PWM0 Controller Reset + * | | |0 = PWM0 controller normal operation. + * | | |1 = PWM0 controller reset. + * |[17] |PWM1RST |PWM1 Controller Reset + * | | |0 = PWM1 controller normal operation. + * | | |1 = PWM1 controller reset. + * @var SYS_T::BODCTL + * Offset: 0x18 Brown-out Detector Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BODEN |Brown-out Detector Enable Bit (Write Protect) + * | | |The default value is set by flash controller user configuration register CBODEN (CONFIG0 [19]). + * | | |0 = Brown-out Detector function Disabled. + * | | |1 = Brown-out Detector function Enabled. + * | | |Note1: This bit is write protected. Refer to the SYS_REGLCTL register. + * | | |Note2: Reset by powr on reset. + * |[3] |BODRSTEN |Brown-out Reset Enable Bit (Write Protect) + * | | |The default value is set by flash controller user configuration register CBORST(CONFIG0[20]) bit . + * | | |0 = Brown-out "INTERRUPT" function Enabled. + * | | |1 = Brown-out "RESET" function Enabled. + * | | |Note1: + * | | |While the Brown-out Detector function is enabled (BODEN high) and BOD reset function is enabled (BODRSTEN high), BOD will assert a signal to reset chip when the detected voltage is lower than the threshold (BODOUT high). + * | | |While the BOD function is enabled (BODEN high) and BOD interrupt function is enabled (BODRSTEN low), BOD will assert an interrupt if BODOUT is high. BOD interrupt will keep till to the BODEN set to 0. BOD interrupt can be blocked by disabling the NVIC BOD interrupt or disabling BOD function (set BODEN low). + * | | |Note2: This bit is write protected. Refer to the SYS_REGLCTL register. + * | | |Note3: Reset by powr on reset. + * |[4] |BODIF |Brown-out Detector Interrupt Flag + * | | |0 = Brown-out Detector does not detect any voltage draft at VDD down through or up through the voltage of BODVL setting. + * | | |1 = When Brown-out Detector detects the VDD is dropped down through the voltage of BODVL setting or the VDD is raised up through the voltage of BODVL setting, this bit is set to 1 and the brown-out interrupt is requested if brown-out interrupt is enabled. + * | | |Note: Write 1 to clear this bit to 0. + * |[5] |BODLPM |Brown-out Detector Low Power Mode (Write Protect) + * | | |0 = BOD operate in normal mode (default). + * | | |1 = BOD Low Power mode Enabled. + * | | |Note1: The BOD consumes about 100uA in normal mode, the low power mode can reduce the current to about 1/10 but slow the BOD response. + * | | |Note2: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[6] |BODOUT |Brown-out Detector Output Status + * | | |0 = Brown-out Detector output status is 0. + * | | |It means the detected voltage is higher than BODVL setting or BODEN is 0. + * | | |1 = Brown-out Detector output status is 1. + * | | |It means the detected voltage is lower than BODVL setting. If the BODEN is 0, BOD function disabled , this bit always responds 0000. + * |[7] |LVREN |Low Voltage Reset Enable Bit (Write Protect) + * | | |The LVR function resets the chip when the input power voltage is lower than LVR circuit setting. LVR function is enabled by default. + * | | |0 = Low Voltage Reset function Disabled. + * | | |1 = Low Voltage Reset function Enabled. + * | | |Note1: After enabling the bit, the LVR function will be active with 200us delay for LVR output stable (default). + * | | |Note2: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[10:8] |BODDGSEL |Brown-out Detector Output De-glitch Time Select (Write Protect) + * | | |000 = BOD output is sampled by RC32K clock. + * | | |001 = 64 system clock (HCLK). + * | | |010 = 128 system clock (HCLK). + * | | |011 = 256 system clock (HCLK). + * | | |100 = 512 system clock (HCLK). + * | | |101 = 1024 system clock (HCLK). + * | | |110 = 2048 system clock (HCLK). + * | | |111 = 4096 system clock (HCLK). + * | | |Note: These bits are write protected. Refer to the SYS_REGLCTL register. + * |[14:12] |LVRDGSEL |LVR Output De-glitch Time Select (Write Protect) + * | | |000 = Without de-glitch function. + * | | |001 = 64 system clock (HCLK). + * | | |010 = 128 system clock (HCLK). + * | | |011 = 256 system clock (HCLK). + * | | |100 = 512 system clock (HCLK). + * | | |101 = 1024 system clock (HCLK). + * | | |110 = 2048 system clock (HCLK). + * | | |111 = 4096 system clock (HCLK). + * | | |Note: These bits are write protected. Refer to the SYS_REGLCTL register. + * |[16] |BODVL |Brown-out Detector Threshold Voltage Selection (Write Protect) + * | | |The default value is set by flash controller user configuration register CBOV (CONFIG0 [21]). + * | | |0 = Brown-Out Detector threshold voltage is 2.0V. + * | | |1 = Brown-Out Detector threshold voltage is 2.5V. + * | | |Note1: This bit is write protected. Refer to the SYS_REGLCTL register. + * | | |Note2: Reset by powr on reset. + * @var SYS_T::PORCTL + * Offset: 0x24 Power-On-reset Controller Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |POROFF |Power-on Reset Enable Bit (Write Protect) + * | | |When powered on, the POR circuit generates a reset signal to reset the whole chip function, but noise on the power may cause the POR active again. User can disable internal POR circuit to avoid unpredictable noise to cause chip reset by writing 0x5AA5 to this field. + * | | |The POR function will be active again when this field is set to another value or chip is reset by other reset source, including: + * | | |nRESET, Watchdog, LVR reset, BOD reset, ICE reset command and the software-chip reset function. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * @var SYS_T::GPA_MFPL + * Offset: 0x30 GPIOA Low Byte Multiple Function Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |PA0MFP |PA.0 Multi-function Pin Selection + * |[7:4] |PA1MFP |PA.1 Multi-function Pin Selection + * |[11:8] |PA2MFP |PA.2 Multi-function Pin Selection + * |[15:12] |PA3MFP |PA.3 Multi-function Pin Selection + * |[19:16] |PA4MFP |PA.4 Multi-function Pin Selection + * |[23:20] |PA5MFP |PA.5 Multi-function Pin Selection + * |[27:24] |PA6MFP |PA.6 Multi-function Pin Selection + * |[31:28] |PA7MFP |PA.7 Multi-function Pin Selection + * @var SYS_T::GPA_MFPH + * Offset: 0x34 GPIOA High Byte Multiple Function Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |PA8MFP |PA.8 Multi-function Pin Selection + * |[7:4] |PA9MFP |PA.9 Multi-function Pin Selection + * |[11:8] |PA10MFP |PA.10 Multi-function Pin Selection + * |[15:12] |PA11MFP |PA.11 Multi-function Pin Selection + * |[19:16] |PA12MFP |PA.12 Multi-function Pin Selection + * |[23:20] |PA13MFP |PA.13 Multi-function Pin Selection + * |[27:24] |PA14MFP |PA.14 Multi-function Pin Selection + * |[31:28] |PA15MFP |PA.15 Multi-function Pin Selection + * @var SYS_T::GPB_MFPL + * Offset: 0x38 GPIOB Low Byte Multiple Function Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |PB0MFP |PB.0 Multi-function Pin Selection + * |[7:4] |PB1MFP |PB.1 Multi-function Pin Selection + * |[11:8] |PB2MFP |PB.2 Multi-function Pin Selection + * |[15:12] |PB3MFP |PB.3 Multi-function Pin Selection + * |[19:16] |PB4MFP |PB.4 Multi-function Pin Selection + * |[23:20] |PB5MFP |PB.5 Multi-function Pin Selection + * |[27:24] |PB6MFP |PB.6 Multi-function Pin Selection + * |[31:28] |PB7MFP |PB.7 Multi-function Pin Selection + * @var SYS_T::GPB_MFPH + * Offset: 0x3C GPIOB High Byte Multiple Function Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |PB8MFP |PB.8 Multi-function Pin Selection + * |[7:4] |PB9MFP |PB.9 Multi-function Pin Selection + * |[11:8] |PB10MFP |PB.10 Multi-function Pin Selection + * |[15:12] |PB11MFP |PB.11 Multi-function Pin Selection + * |[19:16] |PB12MFP |PB.12 Multi-function Pin Selection + * |[23:20] |PB13MFP |PB.13 Multi-function Pin Selection + * |[27:24] |PB14MFP |PB.14 Multi-function Pin Selection + * |[31:28] |PB15MFP |PB.15 Multi-function Pin Selection + * @var SYS_T::GPC_MFPL + * Offset: 0x40 GPIOC Low Byte Multiple Function Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |PC0MFP |PC.0 Multi-function Pin Selection + * |[7:4] |PC1MFP |PC.1 Multi-function Pin Selection + * |[11:8] |PC2MFP |PC.2 Multi-function Pin Selection + * |[15:12] |PC3MFP |PC.3 Multi-function Pin Selection + * |[19:16] |PC4MFP |PC.4 Multi-function Pin Selection + * |[23:20] |PC5MFP |PC.5 Multi-function Pin Selection + * |[27:24] |PC6MFP |PC.6 Multi-function Pin Selection + * |[31:28] |PC7MFP |PC.7 Multi-function Pin Selection + * @var SYS_T::GPC_MFPH + * Offset: 0x44 GPIOC High Byte Multiple Function Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |PC8MFP |PC.8 Multi-function Pin Selection + * |[7:4] |PC9MFP |PC.9 Multi-function Pin Selection + * |[11:8] |PC10MFP |PC.10 Multi-function Pin Selection + * |[15:12] |PC11MFP |PC.11 Multi-function Pin Selection + * |[19:16] |PC12MFP |PC.12 Multi-function Pin Selection + * |[23:20] |PC13MFP |PC.13 Multi-function Pin Selection + * |[27:24] |PC14MFP |PC.14 Multi-function Pin Selection + * |[31:28] |PC15MFP |PC.15 Multi-function Pin Selection + * @var SYS_T::GPD_MFPL + * Offset: 0x48 GPIOD Low Byte Multiple Function Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |PD0MFP |PD.0 Multi-function Pin Selection + * |[7:4] |PD1MFP |PD.1 Multi-function Pin Selection + * |[11:8] |PD2MFP |PD.2 Multi-function Pin Selection + * |[15:12] |PD3MFP |PD.3 Multi-function Pin Selection + * |[19:16] |PD4MFP |PD.4 Multi-function Pin Selection + * |[23:20] |PD5MFP |PD.5 Multi-function Pin Selection + * |[27:24] |PD6MFP |PD.6 Multi-function Pin Selection + * |[31:28] |PD7MFP |PD.7 Multi-function Pin Selection + * @var SYS_T::GPD_MFPH + * Offset: 0x4C GPIOD High Byte Multiple Function Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |PD8MFP |PD.8 Multi-function Pin Selection + * |[7:4] |PD9MFP |PD.9 Multi-function Pin Selection + * |[11:8] |PD10MFP |PD.10 Multi-function Pin Selection + * |[15:12] |PD11MFP |PD.11 Multi-function Pin Selection + * |[19:16] |PD12MFP |PD.12 Multi-function Pin Selection + * |[23:20] |PD13MFP |PD.13 Multi-function Pin Selection + * |[27:24] |PD14MFP |PD.14 Multi-function Pin Selection + * |[31:28] |PD15MFP |PD.15 Multi-function Pin Selection + * @var SYS_T::GPF_MFPL + * Offset: 0x58 GPIOF Low Byte Multiple Function Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |PF0MFP |PF.0 Multi-function Pin Selection + * |[7:4] |PF1MFP |PF.1 Multi-function Pin Selection + * |[11:8] |PF2MFP |PF.2 Multi-function Pin Selection + * |[15:12] |PF3MFP |PF.3 Multi-function Pin Selection + * |[19:16] |PF4MFP |PF.4 Multi-function Pin Selection + * |[23:20] |PF5MFP |PF.5 Multi-function Pin Selection + * |[27:24] |PF6MFP |PF.6 Multi-function Pin Selection + * |[31:28] |PF7MFP |PF.7 Multi-function Pin Selection + * @var SYS_T::GPF_MFPH + * Offset: 0x5C GPIOF High Byte Multiple Function Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |PF8MFP |PF.8 Multi-function Pin Selection + * |[7:4] |PF9MFP |PF.9 Multi-function Pin Selection + * |[11:8] |PF10MFP |PF.10 Multi-function Pin Selection + * |[15:12] |PF11MFP |PF.11 Multi-function Pin Selection + * |[19:16] |PF12MFP |PF.12 Multi-function Pin Selection + * |[23:20] |PF13MFP |PF.13 Multi-function Pin Selection + * |[27:24] |PF14MFP |PF.14 Multi-function Pin Selection + * |[31:28] |PF15MFP |PF.15 Multi-function Pin Selection + * @var SYS_T::LPLDOCTL + * Offset: 0x78 Low Power LDO Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |LPLDO_EN |Low Power LDO Enalbe Bit + * | | |This bit enables uLDO voltage output. + * | | |0 = uLDO Voltage Output Disabled. + * | | |1 = uLDO Voltage Output Enabled. + * @var SYS_T::MODCTL + * Offset: 0xC0 Modulation Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |MODEN |Modulation Function Enable Bit + * | | |This bit enables modulation funcion by modulating with PWM0 channel output and USCI0(USCI0_DAT0) or UART0(UART0_TXD) output. + * | | |0 = Modulation Function Disabled. + * | | |1 = Modulation Function Enabled. + * |[1] |MODH |Modulation at Data High + * | | |Select modulation pulse(PWM0) at high or low of UART0_TXD or USCI0_DAT0. + * | | |0: Modulation pulse at UART0_TXD low or USCI0_DAT0 low. + * | | |1: Modulation pulse at UART0_TXD high or USCI0_DAT0 high. + * |[7:4] |MODPWMSEL |PWM0 Channel Select for Modulation + * | | |Select the PWM0 channel to modulate with the UART0_TXD or USCI0_DAT0. + * | | |0000: PWM0 Channel 0 modulate with UART0_TXD. + * | | |0001: PWM0 Channel 1 modulate with UART0_TXD. + * | | |0010: PWM0 Channel 2 modulate with UART0_TXD. + * | | |0011: PWM0 Channel 3 modulete with UART0_TXD. + * | | |0100: PWM0 Channel 4 modulete with UART0_TXD. + * | | |0101: PWM0 Channel 5 modulete with UART0_TXD. + * | | |0110: Reserved. + * | | |0111: Reserved. + * | | |1000: PWM0 Channel 0 modulate with USCI0_DAT0. + * | | |1001: PWM0 Channel 1 modulate with USCI0_DAT0. + * | | |1010: PWM0 Channel 2 modulate with USCI0_DAT0. + * | | |1011: PWM0 Channel 3 modulete with USCI0_DAT0. + * | | |1100: PWM0 Channel 4 modulete with USCI0_DAT0. + * | | |1101: PWM0 Channel 5 modulete with USCI0_DAT0. + * | | |1110: Reserved. + * | | |1111: Reserved. + * | | |Note: This bis is valid while MODEN (SYS_MODCTL[0]) is set to 1. + * @var SYS_T::SRAM_BISTCTL + * Offset: 0xD0 System SRAM BIST Test Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[4] |USBBIST |USB BIST Enable Bit (Write Protect) + * | | |This bit enables BIST test for USB RAM. + * | | |0 = system USB BIST Disabled. + * | | |1 = system USB BIST Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[7] |PDMABIST |PDMA BIST Enable Bit (Write Protect) + * | | |This bit enables BIST test for PDMA RAM. + * | | |0 = system PDMA BIST Disabled. + * | | |1 = system PDMA BIST Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * @var SYS_T::SRAM_BISTSTS + * Offset: 0xD4 System SRAM BIST Test Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[4] |USBBEF |USB SRAM BIST Fail Flag + * | | |0 = USB SRAM BIST test pass. + * | | |1 = USB SRAM BIST test fail. + * |[7] |PDMABISTF |PDMA SRAM BIST Failed Flag + * | | |0 = PDMA SRAM BIST pass. + * | | |1 = PDMA SRAM BIST failed. + * |[20] |USBBEND |USB SRAM BIST Test Finish + * | | |0 = USB SRAM BIST is active. + * | | |1 = USB SRAM BIST test finish. + * |[23] |PDMAEND |PDMA SRAM BIST Test Finish + * | | |0 = PDMA SRAM BIST is active. + * | | |1 = PDMA SRAM BIST test finish. + * @var SYS_T::HIRCTRIMCTL + * Offset: 0xF0 HIRC Trim Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |FREQSEL |Trim Frequency Selection + * | | |This field indicates the target frequency of 48 MHz internal high speed RC oscillator (HIRC) auto trim. + * | | |During auto trim operation, if clock error detected with CESTOPEN is set to 1 or trim retry limitation count reached, this field will be cleared to 00 automatically. + * | | |00 = Disable HIRC auto trim function. + * | | |01 = Enable HIRC auto trim function and trim HIRC to 48 MHz. + * | | |10 = Reserved.. + * | | |11 = Reserved. + * |[5:4] |LOOPSEL |Trim Calculation Loop Selection + * | | |This field defines that trim value calculation is based on how many reference clocks. + * | | |00 = Trim value calculation is based on average difference in 4 clocks of reference clock. + * | | |01 = Trim value calculation is based on average difference in 8 clocks of reference clock. + * | | |10 = Trim value calculation is based on average difference in 16 clocks of reference clock. + * | | |11 = Trim value calculation is based on average difference in 32 clocks of reference clock. + * | | |Note: For example, if LOOPSEL is set as 00, auto trim circuit will calculate trim value based on the average frequency difference in 4 clocks of reference clock. + * |[7:6] |RETRYCNT |Trim Value Update Limitation Count + * | | |This field defines that how many times the auto trim circuit will try to update the HIRC trim value before the frequency of HIRC locked. + * | | |Once the HIRC locked, the internal trim value update counter will be reset. + * | | |If the trim value update counter reached this limitation value and frequency of HIRC still doesn't lock, the auto trim operation will be disabled and FREQSEL will be cleared to 00. + * | | |00 = Trim retry count limitation is 64 loops. + * | | |01 = Trim retry count limitation is 128 loops. + * | | |10 = Trim retry count limitation is 256 loops. + * | | |11 = Trim retry count limitation is 512 loops. + * |[8] |CESTOPEN |Clock Error Stop Enable Bit + * | | |0 = The trim operation is keep going if clock is inaccuracy. + * | | |1 = The trim operation is stopped if clock is inaccuracy. + * |[9] |BOUNDEN |Boundary Enable Bit + * | | |0 = Boundary function is disable. + * | | |1 = Boundary function is enable. + * |[10] |REFCKSEL |Reference Clock Selection + * | | |0 = HIRC trim reference clock is from LXT (32.768 kHz). + * | | |1 = HIRC trim reference clock is from USB SOF (Start-Of-Frame) packet. + * | | |Note1: HIRC trim reference clock is 40Khz in test mode. + * | | |Note2: HIRC trim reference clock support LXT or HXT or SOF depends on the chip spec. + * | | |For M031 16k/2k, RC trim supports HXT as reference clock . + * | | |For M031 32k/4k, RC trim supports LXT and HXT as reference clock . + * | | |For M031 64k/8k, RC trim supports LXT as reference clock . + * | | |For M031 128k/16k, RC trim supports LXT and SOF as reference clock . + * |[20:16] |BOUNDARY |Boundary Selection + * | | |Fill the boundary range from 0x1 to 0x1F, 0x0 is reserved.Reserved. + * | | |Note: This field is effective only when the BOUNDEN(SYS_HIRCTRIMCTL[9]) is enable. + * @var SYS_T::HIRCTRIMIEN + * Offset: 0xF4 HIRC Trim Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |TFALIEN |Trim Failure Interrupt Enable Bit + * | | |This bit controls if an interrupt will be triggered while HIRC trim value update limitation count reached and HIRC frequency still not locked on target frequency set by FREQSEL(SYS_HIRCTRIMCTL[1:0]). + * | | |If this bit is high and TFAILIF(SYS_HIRCTRIMSTS[1]) is set during auto trim operation, an interrupt will be triggered to notify that HIRC trim value update limitation count was reached. + * | | |0 = Disable TFAILIF(SYS_HIRCTRIMSTS[1]) status to trigger an interrupt to CPU. + * | | |1 = Enable TFAILIF(SYS_HIRCTRIMSTS[1]) status to trigger an interrupt to CPU. + * |[2] |CLKEIEN |Clock Error Interrupt Enable Bit + * | | |This bit controls if CPU would get an interrupt while clock is inaccuracy during auto trim operation. + * | | |If this bit is set to1, and CLKERRIF(SYS_HIRCTRIMSTS[2]) is set during auto trim operation, an interrupt will be triggered to notify the clock frequency is inaccuracy. + * | | |0 = Disable CLKERRIF(SYS_HIRCTRIMSTS[2]) status to trigger an interrupt to CPU. + * | | |1 = Enable CLKERRIF(SYS_HIRCTRIMSTS[2]) status to trigger an interrupt to CPU. + * @var SYS_T::HIRCTRIMSTS + * Offset: 0xF8 HIRC Trim Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |FREQLOCK |HIRC Frequency Lock Status + * | | |This bit indicates the HIRC frequency is locked. + * | | |This is a status bit and doesn't trigger any interrupt. Write 1 to clear this to 0. This bit will be set automatically, if the frequecy is lock and the RC_TRIM is enabled. + * | | |0 = The internal high-speed oscillator frequency doesn't lock at 48 MHz yet. + * | | |1 = The internal high-speed oscillator frequency locked at 48 MHz. + * | | |Note: Reset by powr on reset. + * |[1] |TFAILIF |Trim Failure Interrupt Status + * | | |This bit indicates that HIRC trim value update limitation count reached and the HIRC clock frequency still doesn't be locked + * | | |Once this bit is set, the auto trim operation stopped and FREQSEL(SYS_HIRCTRIMCTL[1:0]) will be cleared to 00 by hardware automatically. + * | | |If this bit is set and TFAILIEN(SYS_HIRCIEN[1]) is high, an interrupt will be triggered to notify that HIRC trim value update limitation count was reached. Write 1 to clear this to 0. + * | | |0 = Trim value update limitation count does not reach. + * | | |1 = Trim value update limitation count reached and HIRC frequency still not locked. + * | | |Note: Reset by powr on reset. + * |[2] |CLKERIF |Clock Error Interrupt Status + * | | |When the frequency of 38.4 kHz external low speed crystal oscillator (LXT) or 48MHz internal high speed RC oscillator (HIRC) is shift larger to unreasonable value, this bit will be set and to be an indicate that clock frequency is inaccuracy. Once this bit is set to 1, the auto trim operation stopped and FREQSEL(SYS_HIRCTRIMCTL[1:0]) will be cleared to 00 by hardware automatically if CESTOPEN(SYS_HIRCTRIMCTL[8]) is set to 1. + * | | |If this bit is set and CLKEIEN(SYS_HIRCTIEN[2]) is high, an interrupt will be triggered to notify the clock frequency is inaccuracy. Write 1 to clear this to 0. + * | | |0 = Clock frequency is accuracy. + * | | |1 = Clock frequency is inaccuracy. + * | | |Note: Reset by powr on reset. + * |[3] |OVBDIF |Over Boundary Status + * | | |When the over boundary function is set, if there occurs the over boundary condition, this flag will be set. + * | | |0 = Over boundary coundition did not occur. + * | | |1 = Over boundary coundition occurred. + * | | |Note: Write 1 to clear this flag. + * @var SYS_T::REGLCTL + * Offset: 0x100 Register Lock Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |REGLCTL |Register Lock Control Code (Write Only) + * | | |Some registers have write-protection function. + * | | |Writing these registers have to disable the protected function by writing the sequence value "59h", "16h", "88h" to this field. After this sequence is completed, the REGLCTL bit will be set to 1 and write-protection registers can be normal write. + * | | |REGLCTL[0] + * | | |Register Lock Control Disable Index (Read Only) + * | | |0 = Write-protection Enabled for writing protected registers. Any write to the protected register is ignored. + * | | |1 = Write-protection Disabled for writing protected registers. + * @var SYS_T::PORDISAN + * Offset: 0x1EC Analog POR Disable Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |POROFFAN |Power-on Reset Enable Bit (Write Protect) + * | | |After powered on, User can turn off internal analog POR circuit to save power by writing 0x5AA5 to this field. + * | | |The analog POR circuit will be active again when this field is set to another value or chip is reset by other reset source, including: + * | | |nRESET, Watchdog, LVR reset, BOD reset, ICE reset command and the software-chip reset function. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + */ + __I uint32_t PDID; /*!< [0x0000] Part Device Identification Number Register */ + __IO uint32_t RSTSTS; /*!< [0x0004] System Reset Status Register */ + __IO uint32_t IPRST0; /*!< [0x0008] Peripheral Reset Control Register 0 */ + __IO uint32_t IPRST1; /*!< [0x000c] Peripheral Reset Control Register 1 */ + __IO uint32_t IPRST2; /*!< [0x0010] Peripheral Reset Control Register 2 */ + __I uint32_t RESERVE0[1]; + __IO uint32_t BODCTL; /*!< [0x0018] Brown-out Detector Control Register */ + __I uint32_t RESERVE1[2]; + __IO uint32_t PORCTL; /*!< [0x0024] Power-On-reset Controller Register */ + __I uint32_t RESERVE2[2]; + __IO uint32_t GPA_MFPL; /*!< [0x0030] GPIOA Low Byte Multiple Function Control Register */ + __IO uint32_t GPA_MFPH; /*!< [0x0034] GPIOA High Byte Multiple Function Control Register */ + __IO uint32_t GPB_MFPL; /*!< [0x0038] GPIOB Low Byte Multiple Function Control Register */ + __IO uint32_t GPB_MFPH; /*!< [0x003c] GPIOB High Byte Multiple Function Control Register */ + __IO uint32_t GPC_MFPL; /*!< [0x0040] GPIOC Low Byte Multiple Function Control Register */ + __IO uint32_t GPC_MFPH; /*!< [0x0044] GPIOC High Byte Multiple Function Control Register */ + __IO uint32_t GPD_MFPL; /*!< [0x0048] GPIOD Low Byte Multiple Function Control Register */ + __IO uint32_t GPD_MFPH; /*!< [0x004c] GPIOD High Byte Multiple Function Control Register */ + __IO uint32_t GPE_MFPL; /*!< [0x0050] GPIOE Low Byte Multiple Function Control Register */ + __IO uint32_t GPE_MFPH; /*!< [0x0054] GPIOE High Byte Multiple Function Control Register */ + __IO uint32_t GPF_MFPL; /*!< [0x0058] GPIOF Low Byte Multiple Function Control Register */ + __IO uint32_t GPF_MFPH; /*!< [0x005c] GPIOF High Byte Multiple Function Control Register */ + __IO uint32_t GPG_MFPL; /*!< [0x0060] GPIOG High Byte Multiple Function Control Register */ + __IO uint32_t GPG_MFPH; /*!< [0x0064] GPIOG High Byte Multiple Function Control Register */ + __IO uint32_t GPH_MFPL; /*!< [0x0068] GPIOH High Byte Multiple Function Control Register */ + __IO uint32_t GPH_MFPH; /*!< [0x006c] GPIOH High Byte Multiple Function Control Register */ + __I uint32_t RESERVE3[2]; + __IO uint32_t LPLDOCTL; /*!< [0x0078] Low Power LDO Control Register */ + __I uint32_t RESERVE4[17]; + __IO uint32_t MODCTL; /*!< [0x00c0] Modulation Control Register */ + __I uint32_t RESERVE5[3]; + __IO uint32_t SRAM_BISTCTL; /*!< [0x00d0] System SRAM BIST Test Control Register */ + __I uint32_t SRAM_BISTSTS; /*!< [0x00d4] System SRAM BIST Test Status Register */ + __IO uint32_t SRAM_PARITY; /*!< [0x00d8] System SRAM Parity Test Control Register (Only for Testing) */ + __IO uint32_t SRAM_INTCTL; /*!< [0x00dc] System SRAM Interrupt Enable Control Register */ + __IO uint32_t SRAM_STATUS; /*!< [0x00e0] System SRAM Parity Error Status Register */ + __I uint32_t SRAM_ERRADDR; /*!< [0x00e4] System SRAM Parity Check Error Address Register */ + __I uint32_t RESERVE6[2]; + __IO uint32_t HIRCTRIMCTL; /*!< [0x00f0] HIRC Trim Control Register */ + __IO uint32_t HIRCTRIMIEN; /*!< [0x00f4] HIRC Trim Interrupt Enable Register */ + __IO uint32_t HIRCTRIMSTS; /*!< [0x00f8] HIRC Trim Interrupt Status Register */ + __I uint32_t RESERVE7[1]; + __O uint32_t REGLCTL; /*!< [0x0100] Register Lock Control Register */ + __I uint32_t RESERVE8[5]; + __IO uint32_t HIRCADJ; /*!< [0x0118] HIRC Trim Value Register */ + __I uint32_t RESERVE9[1]; + __I uint32_t LDOTRIM; /*!< [0x0120] LDO Trim Code Register */ + __I uint32_t LVR16TRIM; /*!< [0x0124] LVR16 Trim Code Register */ + __I uint32_t RESERVE10[4]; + __I uint32_t LIRCT; /*!< [0x0138] Low Speed Internal Oscillator Trim Code Register */ + __I uint32_t RESERVE11[5]; + __I uint32_t LVR17TRIM; /*!< [0x0150] LVR17 Trim Code Register */ + __I uint32_t LVR20TRIM; /*!< [0x0154] LVR20 Trim Code Register */ + __I uint32_t LVR25TRIM; /*!< [0x0158] LVR25 Trim Code Register */ + __I uint32_t uLDOVITRIM; /*!< [0x015c] ULDO V Trim and I TRIM Code Register */ + __IO uint32_t LVRITRIMSEL; /*!< [0x0160] LVR Itrim and Version Select Register */ + __I uint32_t RESERVE12[9]; + __IO uint32_t HIRCTCTL; /*!< [0x0188] HIRC Test Mode Control Register */ + __IO uint32_t ADCCHIP; /*!< [0x018c] R/W ADC CHIP Control Register */ + __IO uint32_t HXTTCTL; /*!< [0x0190] R/W HXT Test Mode Control Register */ + __I uint32_t RESERVE13[22]; + __IO uint32_t PORDISAN; /*!< [0x01ec] Analog POR Disable Control Register */ +} SYS_T; + +typedef struct +{ + + + /** + * @var NMI_T::NMIEN + * Offset: 0x00 NMI Source Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BODOUT |BOD NMI Source Enable (Write Protect) + * | | |0 = BOD NMI source Disabled. + * | | |1 = BOD NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[1] |IRC_INT |IRC TRIM NMI Source Enable (Write Protect) + * | | |0 = IRC TRIM NMI source Disabled. + * | | |1 = IRC TRIM NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[2] |PWRWU_INT |Power-down Mode Wake-up NMI Source Enable (Write Protect) + * | | |0 = Power-down mode wake-up NMI source Disabled. + * | | |1 = Power-down mode wake-up NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[4] |CLKFAIL |Clock Fail Detected and IRC Auto Trim Interrupt NMI Source Enable (Write Protect) + * | | |0 = Clock fail detected and IRC Auto Trim interrupt NMI source Disabled. + * | | |1 = Clock fail detected and IRC Auto Trim interrupt NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[8] |EINT0 |External Interrupt From PA.6 or PB.5 Pin NMI Source Enable (Write Protect) + * | | |0 = External interrupt from PA.6 or PB.5 pin NMI source Disabled. + * | | |1 = External interrupt from PA.6 or PB.5 pin NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[9] |EINT1 |External Interrupt From PA.7, PB.4 or PD.15 Pin NMI Source Enable (Write Protect) + * | | |0 = External interrupt from PA.7, PB.4 or PD.15 pin NMI source Disabled. + * | | |1 = External interrupt from PA.7, PB.4 or PD.15 pin NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[10] |EINT2 |External Interrupt From PB.3 or PC.6 Pin NMI Source Enable (Write Protect) + * | | |0 = External interrupt from PB.3 or PC.6 pin NMI source Disabled. + * | | |1 = External interrupt from PB.3 or PC.6 pin NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[11] |EINT3 |External Interrupt From PB.2 or PC.7 Pin NMI Source Enable (Write Protect) + * | | |0 = External interrupt from PB.2 or PC.7 pin NMI source Disabled. + * | | |1 = External interrupt from PB.2 or PC.7 pin NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[12] |EINT4 |External Interrupt From PA.8, PB.6 or PF.15 Pin NMI Source Enable (Write Protect) + * | | |0 = External interrupt from PA.8, PB.6 or PF.15 pin NMI source Disabled. + * | | |1 = External interrupt from PA.8, PB.6 or PF.15 pin NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[13] |EINT5 |External Interrupt From PB.7 or PF.14 Pin NMI Source Enable (Write Protect) + * | | |0 = External interrupt from PB.7 or PF.14 pin NMI source Disabled. + * | | |1 = External interrupt from PB.7 or PF.14 pin NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[14] |UART0_INT |UART0 NMI Source Enable (Write Protect) + * | | |0 = UART0 NMI source Disabled. + * | | |1 = UART0 NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[15] |UART1_INT |UART1 NMI Source Enable (Write Protect) + * | | |0 = UART1 NMI source Disabled. + * | | |1 = UART1 NMI source Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * @var NMI_T::NMISTS + * Offset: 0x04 NMI Source Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BODOUT |BOD Interrupt Flag (Read Only) + * | | |0 = BOD interrupt is deasserted. + * | | |1 = BOD interrupt is asserted. + * |[1] |IRC_INT |IRC TRIM Interrupt Flag (Read Only) + * | | |0 = HIRC TRIM interrupt is deasserted. + * | | |1 = HIRC TRIM interrupt is asserted. + * |[2] |PWRWU_INT |Power-down Mode Wake-up Interrupt Flag (Read Only) + * | | |0 = Power-down mode wake-up interrupt is deasserted. + * | | |1 = Power-down mode wake-up interrupt is asserted. + * |[4] |CLKFAIL |Clock Fail Detected or IRC Auto Trim Interrupt Flag (Read Only) + * | | |0 = Clock fail detected or IRC Auto Trim interrupt is deasserted. + * | | |1 = Clock fail detected or IRC Auto Trim interrupt is asserted. + * |[8] |EINT0 |External Interrupt From PA.6 or PB.5 Pin Interrupt Flag (Read Only) + * | | |0 = External Interrupt from PA.6 or PB.5 interrupt is deasserted. + * | | |1 = External Interrupt from PA.6 or PB.5 interrupt is asserted. + * |[9] |EINT1 |External Interrupt From PA.7, PB.4 or PD.15 Pin Interrupt Flag (Read Only) + * | | |0 = External Interrupt from PA.7, PB.4 or PD.15 interrupt is deasserted. + * | | |1 = External Interrupt from PA.7, PB.4 or PD.15 interrupt is asserted. + * |[10] |EINT2 |External Interrupt From PB.3 or PC.6 Pin Interrupt Flag (Read Only) + * | | |0 = External Interrupt from PB.3 or PC.6 interrupt is deasserted. + * | | |1 = External Interrupt from PB.3 or PC.6 interrupt is asserted. + * |[11] |EINT3 |External Interrupt From PB.2 or PC.7 Pin Interrupt Flag (Read Only) + * | | |0 = External Interrupt from PB.2 or PC.7 interrupt is deasserted. + * | | |1 = External Interrupt from PB.2 or PC.7 interrupt is asserted. + * |[12] |EINT4 |External Interrupt From PA.8, PB.6 or PF.15 Pin Interrupt Flag (Read Only) + * | | |0 = External Interrupt from PA.8, PB.6 or PF.15 interrupt is deasserted. + * | | |1 = External Interrupt from PA.8, PB.6 or PF.15 interrupt is asserted. + * |[13] |EINT5 |External Interrupt From PB.7 or PF.14 Pin Interrupt Flag (Read Only) + * | | |0 = External Interrupt from PB.7 or PF.14 interrupt is deasserted. + * | | |1 = External Interrupt from PB.7 or PF.14 interrupt is asserted. + * |[14] |UART0_INT |UART0 Interrupt Flag (Read Only) + * | | |0 = UART1 interrupt is deasserted. + * | | |1 = UART1 interrupt is asserted. + * |[15] |UART1_INT |UART1 Interrupt Flag (Read Only) + * | | |0 = UART1 interrupt is deasserted. + * | | |1 = UART1 interrupt is asserted. + */ + __IO uint32_t NMIEN; /*!< [0x0000] NMI Source Interrupt Enable Register */ + __I uint32_t NMISTS; /*!< [0x0004] NMI Source Interrupt Status Register */ + +} NMI_T; + +/** + @addtogroup SYS_CONST SYS Bit Field Definition + Constant Definitions for SYS Controller +@{ */ + +#define SYS_PDID_PDID_Pos (0) /*!< SYS_T::PDID: PDID Position */ +#define SYS_PDID_PDID_Msk (0xfffffffful << SYS_PDID_PDID_Pos) /*!< SYS_T::PDID: PDID Mask */ + +#define SYS_RSTSTS_PORF_Pos (0) /*!< SYS_T::RSTSTS: PORF Position */ +#define SYS_RSTSTS_PORF_Msk (0x1ul << SYS_RSTSTS_PORF_Pos) /*!< SYS_T::RSTSTS: PORF Mask */ + +#define SYS_RSTSTS_PINRF_Pos (1) /*!< SYS_T::RSTSTS: PINRF Position */ +#define SYS_RSTSTS_PINRF_Msk (0x1ul << SYS_RSTSTS_PINRF_Pos) /*!< SYS_T::RSTSTS: PINRF Mask */ + +#define SYS_RSTSTS_WDTRF_Pos (2) /*!< SYS_T::RSTSTS: WDTRF Position */ +#define SYS_RSTSTS_WDTRF_Msk (0x1ul << SYS_RSTSTS_WDTRF_Pos) /*!< SYS_T::RSTSTS: WDTRF Mask */ + +#define SYS_RSTSTS_LVRF_Pos (3) /*!< SYS_T::RSTSTS: LVRF Position */ +#define SYS_RSTSTS_LVRF_Msk (0x1ul << SYS_RSTSTS_LVRF_Pos) /*!< SYS_T::RSTSTS: LVRF Mask */ + +#define SYS_RSTSTS_BODRF_Pos (4) /*!< SYS_T::RSTSTS: BODRF Position */ +#define SYS_RSTSTS_BODRF_Msk (0x1ul << SYS_RSTSTS_BODRF_Pos) /*!< SYS_T::RSTSTS: BODRF Mask */ + +#define SYS_RSTSTS_SYSRF_Pos (5) /*!< SYS_T::RSTSTS: SYSRF Position */ +#define SYS_RSTSTS_SYSRF_Msk (0x1ul << SYS_RSTSTS_SYSRF_Pos) /*!< SYS_T::RSTSTS: SYSRF Mask */ + +#define SYS_RSTSTS_CPURF_Pos (7) /*!< SYS_T::RSTSTS: CPURF Position */ +#define SYS_RSTSTS_CPURF_Msk (0x1ul << SYS_RSTSTS_CPURF_Pos) /*!< SYS_T::RSTSTS: CPURF Mask */ + +#define SYS_RSTSTS_CPULKRF_Pos (8) /*!< SYS_T::RSTSTS: CPULKRF Position */ +#define SYS_RSTSTS_CPULKRF_Msk (0x1ul << SYS_RSTSTS_CPULKRF_Pos) /*!< SYS_T::RSTSTS: CPULKRF Mask */ + +#define SYS_IPRST0_CHIPRST_Pos (0) /*!< SYS_T::IPRST0: CHIPRST Position */ +#define SYS_IPRST0_CHIPRST_Msk (0x1ul << SYS_IPRST0_CHIPRST_Pos) /*!< SYS_T::IPRST0: CHIPRST Mask */ + +#define SYS_IPRST0_CPURST_Pos (1) /*!< SYS_T::IPRST0: CPURST Position */ +#define SYS_IPRST0_CPURST_Msk (0x1ul << SYS_IPRST0_CPURST_Pos) /*!< SYS_T::IPRST0: CPURST Mask */ + +#define SYS_IPRST0_PDMARST_Pos (2) /*!< SYS_T::IPRST0: PDMARST Position */ +#define SYS_IPRST0_PDMARST_Msk (0x1ul << SYS_IPRST0_PDMARST_Pos) /*!< SYS_T::IPRST0: PDMARST Mask */ + +#define SYS_IPRST0_EBIRST_Pos (3) /*!< SYS_T::IPRST0: EBIRST Position */ +#define SYS_IPRST0_EBIRST_Msk (0x1ul << SYS_IPRST0_EBIRST_Pos) /*!< SYS_T::IPRST0: EBIRST Mask */ + +#define SYS_IPRST0_HDIVRST_Pos (4) /*!< SYS_T::IPRST0: HDIVRST Position */ +#define SYS_IPRST0_HDIVRST_Msk (0x1ul << SYS_IPRST0_HDIVRST_Pos) /*!< SYS_T::IPRST0: HDIVRST Mask */ + +#define SYS_IPRST0_CRCRST_Pos (7) /*!< SYS_T::IPRST0: CRCRST Position */ +#define SYS_IPRST0_CRCRST_Msk (0x1ul << SYS_IPRST0_CRCRST_Pos) /*!< SYS_T::IPRST0: CRCRST Mask */ + +#define SYS_IPRST1_GPIORST_Pos (1) /*!< SYS_T::IPRST1: GPIORST Position */ +#define SYS_IPRST1_GPIORST_Msk (0x1ul << SYS_IPRST1_GPIORST_Pos) /*!< SYS_T::IPRST1: GPIORST Mask */ + +#define SYS_IPRST1_TMR0RST_Pos (2) /*!< SYS_T::IPRST1: TMR0RST Position */ +#define SYS_IPRST1_TMR0RST_Msk (0x1ul << SYS_IPRST1_TMR0RST_Pos) /*!< SYS_T::IPRST1: TMR0RST Mask */ + +#define SYS_IPRST1_TMR1RST_Pos (3) /*!< SYS_T::IPRST1: TMR1RST Position */ +#define SYS_IPRST1_TMR1RST_Msk (0x1ul << SYS_IPRST1_TMR1RST_Pos) /*!< SYS_T::IPRST1: TMR1RST Mask */ + +#define SYS_IPRST1_TMR2RST_Pos (4) /*!< SYS_T::IPRST1: TMR2RST Position */ +#define SYS_IPRST1_TMR2RST_Msk (0x1ul << SYS_IPRST1_TMR2RST_Pos) /*!< SYS_T::IPRST1: TMR2RST Mask */ + +#define SYS_IPRST1_TMR3RST_Pos (5) /*!< SYS_T::IPRST1: TMR3RST Position */ +#define SYS_IPRST1_TMR3RST_Msk (0x1ul << SYS_IPRST1_TMR3RST_Pos) /*!< SYS_T::IPRST1: TMR3RST Mask */ + +#define SYS_IPRST1_ACMP01RST_Pos (7) /*!< SYS_T::IPRST1: ACMP01RST Position */ +#define SYS_IPRST1_ACMP01RST_Msk (0x1ul << SYS_IPRST1_ACMP01RST_Pos) /*!< SYS_T::IPRST1: ACMP01RST Mask */ + +#define SYS_IPRST1_I2C0RST_Pos (8) /*!< SYS_T::IPRST1: I2C0RST Position */ +#define SYS_IPRST1_I2C0RST_Msk (0x1ul << SYS_IPRST1_I2C0RST_Pos) /*!< SYS_T::IPRST1: I2C0RST Mask */ + +#define SYS_IPRST1_I2C1RST_Pos (9) /*!< SYS_T::IPRST1: I2C1RST Position */ +#define SYS_IPRST1_I2C1RST_Msk (0x1ul << SYS_IPRST1_I2C1RST_Pos) /*!< SYS_T::IPRST1: I2C1RST Mask */ + +#define SYS_IPRST1_QSPI0RST_Pos (12) /*!< SYS_T::IPRST1: QSPI0RST Position */ +#define SYS_IPRST1_QSPI0RST_Msk (0x1ul << SYS_IPRST1_QSPI0RST_Pos) /*!< SYS_T::IPRST1: QSPI0RST Mask */ + +#define SYS_IPRST1_SPI0RST_Pos (13) /*!< SYS_T::IPRST1: SPI0RST Position */ +#define SYS_IPRST1_SPI0RST_Msk (0x1ul << SYS_IPRST1_SPI0RST_Pos) /*!< SYS_T::IPRST1: SPI0RST Mask */ + +#define SYS_IPRST1_UART0RST_Pos (16) /*!< SYS_T::IPRST1: UART0RST Position */ +#define SYS_IPRST1_UART0RST_Msk (0x1ul << SYS_IPRST1_UART0RST_Pos) /*!< SYS_T::IPRST1: UART0RST Mask */ + +#define SYS_IPRST1_UART1RST_Pos (17) /*!< SYS_T::IPRST1: UART1RST Position */ +#define SYS_IPRST1_UART1RST_Msk (0x1ul << SYS_IPRST1_UART1RST_Pos) /*!< SYS_T::IPRST1: UART1RST Mask */ + +#define SYS_IPRST1_UART2RST_Pos (18) /*!< SYS_T::IPRST1: UART2RST Position */ +#define SYS_IPRST1_UART2RST_Msk (0x1ul << SYS_IPRST1_UART2RST_Pos) /*!< SYS_T::IPRST1: UART2RST Mask */ + +#define SYS_IPRST1_UART3RST_Pos (19) /*!< SYS_T::IPRST1: UART3RST Position */ +#define SYS_IPRST1_UART3RST_Msk (0x1ul << SYS_IPRST1_UART3RST_Pos) /*!< SYS_T::IPRST1: UART3RST Mask */ + +#define SYS_IPRST1_UART4RST_Pos (20) /*!< SYS_T::IPRST1: UART4RST Position */ +#define SYS_IPRST1_UART4RST_Msk (0x1ul << SYS_IPRST1_UART4RST_Pos) /*!< SYS_T::IPRST1: UART4RST Mask */ + +#define SYS_IPRST1_UART5RST_Pos (21) /*!< SYS_T::IPRST1: UART5RST Position */ +#define SYS_IPRST1_UART5RST_Msk (0x1ul << SYS_IPRST1_UART5RST_Pos) /*!< SYS_T::IPRST1: UART5RST Mask */ + +#define SYS_IPRST1_UART6RST_Pos (22) /*!< SYS_T::IPRST1: UART6RST Position */ +#define SYS_IPRST1_UART6RST_Msk (0x1ul << SYS_IPRST1_UART6RST_Pos) /*!< SYS_T::IPRST1: UART6RST Mask */ + +#define SYS_IPRST1_UART7RST_Pos (23) /*!< SYS_T::IPRST1: UART7RST Position */ +#define SYS_IPRST1_UART7RST_Msk (0x1ul << SYS_IPRST1_UART7RST_Pos) /*!< SYS_T::IPRST1: UART7RST Mask */ + +#define SYS_IPRST1_USBDRST_Pos (27) /*!< SYS_T::IPRST1: USBDRST Position */ +#define SYS_IPRST1_USBDRST_Msk (0x1ul << SYS_IPRST1_USBDRST_Pos) /*!< SYS_T::IPRST1: USBDRST Mask */ + +#define SYS_IPRST1_ADCRST_Pos (28) /*!< SYS_T::IPRST1: ADCRST Position */ +#define SYS_IPRST1_ADCRST_Msk (0x1ul << SYS_IPRST1_ADCRST_Pos) /*!< SYS_T::IPRST1: ADCRST Mask */ + +#define SYS_IPRST2_USCI0RST_Pos (8) /*!< SYS_T::IPRST2: USCI0RST Position */ +#define SYS_IPRST2_USCI0RST_Msk (0x1ul << SYS_IPRST2_USCI0RST_Pos) /*!< SYS_T::IPRST2: USCI0RST Mask */ + +#define SYS_IPRST2_USCI1RST_Pos (9) /*!< SYS_T::IPRST2: USCI1RST Position */ +#define SYS_IPRST2_USCI1RST_Msk (0x1ul << SYS_IPRST2_USCI1RST_Pos) /*!< SYS_T::IPRST2: USCI1RST Mask */ + +#define SYS_IPRST2_PWM0RST_Pos (16) /*!< SYS_T::IPRST2: PWM0RST Position */ +#define SYS_IPRST2_PWM0RST_Msk (0x1ul << SYS_IPRST2_PWM0RST_Pos) /*!< SYS_T::IPRST2: PWM0RST Mask */ + +#define SYS_IPRST2_PWM1RST_Pos (17) /*!< SYS_T::IPRST2: PWM1RST Position */ +#define SYS_IPRST2_PWM1RST_Msk (0x1ul << SYS_IPRST2_PWM1RST_Pos) /*!< SYS_T::IPRST2: PWM1RST Mask */ + +#define SYS_IPRST2_BPWM0RST_Pos (18) /*!< SYS_T::IPRST2: BPWM0RST Position */ +#define SYS_IPRST2_BPWM0RST_Msk (0x1ul << SYS_IPRST2_BPWM0RST_Pos) /*!< SYS_T::IPRST2: BPWM0RST Mask */ + +#define SYS_IPRST2_BPWM1RST_Pos (19) /*!< SYS_T::IPRST2: BPWM1RST Position */ +#define SYS_IPRST2_BPWM1RST_Msk (0x1ul << SYS_IPRST2_BPWM1RST_Pos) /*!< SYS_T::IPRST2: BPWM1RST Mask */ + +#define SYS_BODCTL_BODEN_Pos (0) /*!< SYS_T::BODCTL: BODEN Position */ +#define SYS_BODCTL_BODEN_Msk (0x1ul << SYS_BODCTL_BODEN_Pos) /*!< SYS_T::BODCTL: BODEN Mask */ + +#define SYS_BODCTL_BODRSTEN_Pos (3) /*!< SYS_T::BODCTL: BODRSTEN Position */ +#define SYS_BODCTL_BODRSTEN_Msk (0x1ul << SYS_BODCTL_BODRSTEN_Pos) /*!< SYS_T::BODCTL: BODRSTEN Mask */ + +#define SYS_BODCTL_BODIF_Pos (4) /*!< SYS_T::BODCTL: BODIF Position */ +#define SYS_BODCTL_BODIF_Msk (0x1ul << SYS_BODCTL_BODIF_Pos) /*!< SYS_T::BODCTL: BODIF Mask */ + +#define SYS_BODCTL_BODLPM_Pos (5) /*!< SYS_T::BODCTL: BODLPM Position */ +#define SYS_BODCTL_BODLPM_Msk (0x1ul << SYS_BODCTL_BODLPM_Pos) /*!< SYS_T::BODCTL: BODLPM Mask */ + +#define SYS_BODCTL_BODOUT_Pos (6) /*!< SYS_T::BODCTL: BODOUT Position */ +#define SYS_BODCTL_BODOUT_Msk (0x1ul << SYS_BODCTL_BODOUT_Pos) /*!< SYS_T::BODCTL: BODOUT Mask */ + +#define SYS_BODCTL_LVREN_Pos (7) /*!< SYS_T::BODCTL: LVREN Position */ +#define SYS_BODCTL_LVREN_Msk (0x1ul << SYS_BODCTL_LVREN_Pos) /*!< SYS_T::BODCTL: LVREN Mask */ + +#define SYS_BODCTL_BODDGSEL_Pos (8) /*!< SYS_T::BODCTL: BODDGSEL Position */ +#define SYS_BODCTL_BODDGSEL_Msk (0x7ul << SYS_BODCTL_BODDGSEL_Pos) /*!< SYS_T::BODCTL: BODDGSEL Mask */ + +#define SYS_BODCTL_LVRDGSEL_Pos (12) /*!< SYS_T::BODCTL: LVRDGSEL Position */ +#define SYS_BODCTL_LVRDGSEL_Msk (0x7ul << SYS_BODCTL_LVRDGSEL_Pos) /*!< SYS_T::BODCTL: LVRDGSEL Mask */ + +#define SYS_BODCTL_BODVL_Pos (16) /*!< SYS_T::BODCTL: BODVL Position */ +#define SYS_BODCTL_BODVL_Msk (0x1ul << SYS_BODCTL_BODVL_Pos) /*!< SYS_T::BODCTL: BODVL Mask */ + +#define SYS_BODCTL_LVRVL_Pos (20) /*!< SYS_T::BODCTL: LVRVL Position */ +#define SYS_BODCTL_LVRVL_Msk (0x1ul << SYS_BODCTL_LVRVL_Pos) /*!< SYS_T::BODCTL: LVRVL Mask */ + +#define SYS_PORCTL_POROFF_Pos (0) /*!< SYS_T::PORCTL: POROFF Position */ +#define SYS_PORCTL_POROFF_Msk (0xfffful << SYS_PORCTL_POROFF_Pos) /*!< SYS_T::PORCTL: POROFF Mask */ + +#define SYS_GPA_MFPL_PA0MFP_Pos (0) /*!< SYS_T::GPA_MFPL: PA0MFP Position */ +#define SYS_GPA_MFPL_PA0MFP_Msk (0xful << SYS_GPA_MFPL_PA0MFP_Pos) /*!< SYS_T::GPA_MFPL: PA0MFP Mask */ + +#define SYS_GPA_MFPL_PA1MFP_Pos (4) /*!< SYS_T::GPA_MFPL: PA1MFP Position */ +#define SYS_GPA_MFPL_PA1MFP_Msk (0xful << SYS_GPA_MFPL_PA1MFP_Pos) /*!< SYS_T::GPA_MFPL: PA1MFP Mask */ + +#define SYS_GPA_MFPL_PA2MFP_Pos (8) /*!< SYS_T::GPA_MFPL: PA2MFP Position */ +#define SYS_GPA_MFPL_PA2MFP_Msk (0xful << SYS_GPA_MFPL_PA2MFP_Pos) /*!< SYS_T::GPA_MFPL: PA2MFP Mask */ + +#define SYS_GPA_MFPL_PA3MFP_Pos (12) /*!< SYS_T::GPA_MFPL: PA3MFP Position */ +#define SYS_GPA_MFPL_PA3MFP_Msk (0xful << SYS_GPA_MFPL_PA3MFP_Pos) /*!< SYS_T::GPA_MFPL: PA3MFP Mask */ + +#define SYS_GPA_MFPL_PA4MFP_Pos (16) /*!< SYS_T::GPA_MFPL: PA4MFP Position */ +#define SYS_GPA_MFPL_PA4MFP_Msk (0xful << SYS_GPA_MFPL_PA4MFP_Pos) /*!< SYS_T::GPA_MFPL: PA4MFP Mask */ + +#define SYS_GPA_MFPL_PA5MFP_Pos (20) /*!< SYS_T::GPA_MFPL: PA5MFP Position */ +#define SYS_GPA_MFPL_PA5MFP_Msk (0xful << SYS_GPA_MFPL_PA5MFP_Pos) /*!< SYS_T::GPA_MFPL: PA5MFP Mask */ + +#define SYS_GPA_MFPL_PA6MFP_Pos (24) /*!< SYS_T::GPA_MFPL: PA6MFP Position */ +#define SYS_GPA_MFPL_PA6MFP_Msk (0xful << SYS_GPA_MFPL_PA6MFP_Pos) /*!< SYS_T::GPA_MFPL: PA6MFP Mask */ + +#define SYS_GPA_MFPL_PA7MFP_Pos (28) /*!< SYS_T::GPA_MFPL: PA7MFP Position */ +#define SYS_GPA_MFPL_PA7MFP_Msk (0xful << SYS_GPA_MFPL_PA7MFP_Pos) /*!< SYS_T::GPA_MFPL: PA7MFP Mask */ + +#define SYS_GPA_MFPH_PA8MFP_Pos (0) /*!< SYS_T::GPA_MFPH: PA8MFP Position */ +#define SYS_GPA_MFPH_PA8MFP_Msk (0xful << SYS_GPA_MFPH_PA8MFP_Pos) /*!< SYS_T::GPA_MFPH: PA8MFP Mask */ + +#define SYS_GPA_MFPH_PA9MFP_Pos (4) /*!< SYS_T::GPA_MFPH: PA9MFP Position */ +#define SYS_GPA_MFPH_PA9MFP_Msk (0xful << SYS_GPA_MFPH_PA9MFP_Pos) /*!< SYS_T::GPA_MFPH: PA9MFP Mask */ + +#define SYS_GPA_MFPH_PA10MFP_Pos (8) /*!< SYS_T::GPA_MFPH: PA10MFP Position */ +#define SYS_GPA_MFPH_PA10MFP_Msk (0xful << SYS_GPA_MFPH_PA10MFP_Pos) /*!< SYS_T::GPA_MFPH: PA10MFP Mask */ + +#define SYS_GPA_MFPH_PA11MFP_Pos (12) /*!< SYS_T::GPA_MFPH: PA11MFP Position */ +#define SYS_GPA_MFPH_PA11MFP_Msk (0xful << SYS_GPA_MFPH_PA11MFP_Pos) /*!< SYS_T::GPA_MFPH: PA11MFP Mask */ + +#define SYS_GPA_MFPH_PA12MFP_Pos (16) /*!< SYS_T::GPA_MFPH: PA12MFP Position */ +#define SYS_GPA_MFPH_PA12MFP_Msk (0xful << SYS_GPA_MFPH_PA12MFP_Pos) /*!< SYS_T::GPA_MFPH: PA12MFP Mask */ + +#define SYS_GPA_MFPH_PA13MFP_Pos (20) /*!< SYS_T::GPA_MFPH: PA13MFP Position */ +#define SYS_GPA_MFPH_PA13MFP_Msk (0xful << SYS_GPA_MFPH_PA13MFP_Pos) /*!< SYS_T::GPA_MFPH: PA13MFP Mask */ + +#define SYS_GPA_MFPH_PA14MFP_Pos (24) /*!< SYS_T::GPA_MFPH: PA14MFP Position */ +#define SYS_GPA_MFPH_PA14MFP_Msk (0xful << SYS_GPA_MFPH_PA14MFP_Pos) /*!< SYS_T::GPA_MFPH: PA14MFP Mask */ + +#define SYS_GPA_MFPH_PA15MFP_Pos (28) /*!< SYS_T::GPA_MFPH: PA15MFP Position */ +#define SYS_GPA_MFPH_PA15MFP_Msk (0xful << SYS_GPA_MFPH_PA15MFP_Pos) /*!< SYS_T::GPA_MFPH: PA15MFP Mask */ + +#define SYS_GPB_MFPL_PB0MFP_Pos (0) /*!< SYS_T::GPB_MFPL: PB0MFP Position */ +#define SYS_GPB_MFPL_PB0MFP_Msk (0xful << SYS_GPB_MFPL_PB0MFP_Pos) /*!< SYS_T::GPB_MFPL: PB0MFP Mask */ + +#define SYS_GPB_MFPL_PB1MFP_Pos (4) /*!< SYS_T::GPB_MFPL: PB1MFP Position */ +#define SYS_GPB_MFPL_PB1MFP_Msk (0xful << SYS_GPB_MFPL_PB1MFP_Pos) /*!< SYS_T::GPB_MFPL: PB1MFP Mask */ + +#define SYS_GPB_MFPL_PB2MFP_Pos (8) /*!< SYS_T::GPB_MFPL: PB2MFP Position */ +#define SYS_GPB_MFPL_PB2MFP_Msk (0xful << SYS_GPB_MFPL_PB2MFP_Pos) /*!< SYS_T::GPB_MFPL: PB2MFP Mask */ + +#define SYS_GPB_MFPL_PB3MFP_Pos (12) /*!< SYS_T::GPB_MFPL: PB3MFP Position */ +#define SYS_GPB_MFPL_PB3MFP_Msk (0xful << SYS_GPB_MFPL_PB3MFP_Pos) /*!< SYS_T::GPB_MFPL: PB3MFP Mask */ + +#define SYS_GPB_MFPL_PB4MFP_Pos (16) /*!< SYS_T::GPB_MFPL: PB4MFP Position */ +#define SYS_GPB_MFPL_PB4MFP_Msk (0xful << SYS_GPB_MFPL_PB4MFP_Pos) /*!< SYS_T::GPB_MFPL: PB4MFP Mask */ + +#define SYS_GPB_MFPL_PB5MFP_Pos (20) /*!< SYS_T::GPB_MFPL: PB5MFP Position */ +#define SYS_GPB_MFPL_PB5MFP_Msk (0xful << SYS_GPB_MFPL_PB5MFP_Pos) /*!< SYS_T::GPB_MFPL: PB5MFP Mask */ + +#define SYS_GPB_MFPL_PB6MFP_Pos (24) /*!< SYS_T::GPB_MFPL: PB6MFP Position */ +#define SYS_GPB_MFPL_PB6MFP_Msk (0xful << SYS_GPB_MFPL_PB6MFP_Pos) /*!< SYS_T::GPB_MFPL: PB6MFP Mask */ + +#define SYS_GPB_MFPL_PB7MFP_Pos (28) /*!< SYS_T::GPB_MFPL: PB7MFP Position */ +#define SYS_GPB_MFPL_PB7MFP_Msk (0xful << SYS_GPB_MFPL_PB7MFP_Pos) /*!< SYS_T::GPB_MFPL: PB7MFP Mask */ + +#define SYS_GPB_MFPH_PB8MFP_Pos (0) /*!< SYS_T::GPB_MFPH: PB8MFP Position */ +#define SYS_GPB_MFPH_PB8MFP_Msk (0xful << SYS_GPB_MFPH_PB8MFP_Pos) /*!< SYS_T::GPB_MFPH: PB8MFP Mask */ + +#define SYS_GPB_MFPH_PB9MFP_Pos (4) /*!< SYS_T::GPB_MFPH: PB9MFP Position */ +#define SYS_GPB_MFPH_PB9MFP_Msk (0xful << SYS_GPB_MFPH_PB9MFP_Pos) /*!< SYS_T::GPB_MFPH: PB9MFP Mask */ + +#define SYS_GPB_MFPH_PB10MFP_Pos (8) /*!< SYS_T::GPB_MFPH: PB10MFP Position */ +#define SYS_GPB_MFPH_PB10MFP_Msk (0xful << SYS_GPB_MFPH_PB10MFP_Pos) /*!< SYS_T::GPB_MFPH: PB10MFP Mask */ + +#define SYS_GPB_MFPH_PB11MFP_Pos (12) /*!< SYS_T::GPB_MFPH: PB11MFP Position */ +#define SYS_GPB_MFPH_PB11MFP_Msk (0xful << SYS_GPB_MFPH_PB11MFP_Pos) /*!< SYS_T::GPB_MFPH: PB11MFP Mask */ + +#define SYS_GPB_MFPH_PB12MFP_Pos (16) /*!< SYS_T::GPB_MFPH: PB12MFP Position */ +#define SYS_GPB_MFPH_PB12MFP_Msk (0xful << SYS_GPB_MFPH_PB12MFP_Pos) /*!< SYS_T::GPB_MFPH: PB12MFP Mask */ + +#define SYS_GPB_MFPH_PB13MFP_Pos (20) /*!< SYS_T::GPB_MFPH: PB13MFP Position */ +#define SYS_GPB_MFPH_PB13MFP_Msk (0xful << SYS_GPB_MFPH_PB13MFP_Pos) /*!< SYS_T::GPB_MFPH: PB13MFP Mask */ + +#define SYS_GPB_MFPH_PB14MFP_Pos (24) /*!< SYS_T::GPB_MFPH: PB14MFP Position */ +#define SYS_GPB_MFPH_PB14MFP_Msk (0xful << SYS_GPB_MFPH_PB14MFP_Pos) /*!< SYS_T::GPB_MFPH: PB14MFP Mask */ + +#define SYS_GPB_MFPH_PB15MFP_Pos (28) /*!< SYS_T::GPB_MFPH: PB15MFP Position */ +#define SYS_GPB_MFPH_PB15MFP_Msk (0xful << SYS_GPB_MFPH_PB15MFP_Pos) /*!< SYS_T::GPB_MFPH: PB15MFP Mask */ + +#define SYS_GPC_MFPL_PC0MFP_Pos (0) /*!< SYS_T::GPC_MFPL: PC0MFP Position */ +#define SYS_GPC_MFPL_PC0MFP_Msk (0xful << SYS_GPC_MFPL_PC0MFP_Pos) /*!< SYS_T::GPC_MFPL: PC0MFP Mask */ + +#define SYS_GPC_MFPL_PC1MFP_Pos (4) /*!< SYS_T::GPC_MFPL: PC1MFP Position */ +#define SYS_GPC_MFPL_PC1MFP_Msk (0xful << SYS_GPC_MFPL_PC1MFP_Pos) /*!< SYS_T::GPC_MFPL: PC1MFP Mask */ + +#define SYS_GPC_MFPL_PC2MFP_Pos (8) /*!< SYS_T::GPC_MFPL: PC2MFP Position */ +#define SYS_GPC_MFPL_PC2MFP_Msk (0xful << SYS_GPC_MFPL_PC2MFP_Pos) /*!< SYS_T::GPC_MFPL: PC2MFP Mask */ + +#define SYS_GPC_MFPL_PC3MFP_Pos (12) /*!< SYS_T::GPC_MFPL: PC3MFP Position */ +#define SYS_GPC_MFPL_PC3MFP_Msk (0xful << SYS_GPC_MFPL_PC3MFP_Pos) /*!< SYS_T::GPC_MFPL: PC3MFP Mask */ + +#define SYS_GPC_MFPL_PC4MFP_Pos (16) /*!< SYS_T::GPC_MFPL: PC4MFP Position */ +#define SYS_GPC_MFPL_PC4MFP_Msk (0xful << SYS_GPC_MFPL_PC4MFP_Pos) /*!< SYS_T::GPC_MFPL: PC4MFP Mask */ + +#define SYS_GPC_MFPL_PC5MFP_Pos (20) /*!< SYS_T::GPC_MFPL: PC5MFP Position */ +#define SYS_GPC_MFPL_PC5MFP_Msk (0xful << SYS_GPC_MFPL_PC5MFP_Pos) /*!< SYS_T::GPC_MFPL: PC5MFP Mask */ + +#define SYS_GPC_MFPL_PC6MFP_Pos (24) /*!< SYS_T::GPC_MFPL: PC6MFP Position */ +#define SYS_GPC_MFPL_PC6MFP_Msk (0xful << SYS_GPC_MFPL_PC6MFP_Pos) /*!< SYS_T::GPC_MFPL: PC6MFP Mask */ + +#define SYS_GPC_MFPL_PC7MFP_Pos (28) /*!< SYS_T::GPC_MFPL: PC7MFP Position */ +#define SYS_GPC_MFPL_PC7MFP_Msk (0xful << SYS_GPC_MFPL_PC7MFP_Pos) /*!< SYS_T::GPC_MFPL: PC7MFP Mask */ + +#define SYS_GPC_MFPH_PC8MFP_Pos (0) /*!< SYS_T::GPC_MFPH: PC8MFP Position */ +#define SYS_GPC_MFPH_PC8MFP_Msk (0xful << SYS_GPC_MFPH_PC8MFP_Pos) /*!< SYS_T::GPC_MFPH: PC8MFP Mask */ + +#define SYS_GPC_MFPH_PC9MFP_Pos (4) /*!< SYS_T::GPC_MFPH: PC9MFP Position */ +#define SYS_GPC_MFPH_PC9MFP_Msk (0xful << SYS_GPC_MFPH_PC9MFP_Pos) /*!< SYS_T::GPC_MFPH: PC9MFP Mask */ + +#define SYS_GPC_MFPH_PC10MFP_Pos (8) /*!< SYS_T::GPC_MFPH: PC10MFP Position */ +#define SYS_GPC_MFPH_PC10MFP_Msk (0xful << SYS_GPC_MFPH_PC10MFP_Pos) /*!< SYS_T::GPC_MFPH: PC10MFP Mask */ + +#define SYS_GPC_MFPH_PC11MFP_Pos (12) /*!< SYS_T::GPC_MFPH: PC11MFP Position */ +#define SYS_GPC_MFPH_PC11MFP_Msk (0xful << SYS_GPC_MFPH_PC11MFP_Pos) /*!< SYS_T::GPC_MFPH: PC11MFP Mask */ + +#define SYS_GPC_MFPH_PC12MFP_Pos (16) /*!< SYS_T::GPC_MFPH: PC12MFP Position */ +#define SYS_GPC_MFPH_PC12MFP_Msk (0xful << SYS_GPC_MFPH_PC12MFP_Pos) /*!< SYS_T::GPC_MFPH: PC12MFP Mask */ + +#define SYS_GPC_MFPH_PC13MFP_Pos (20) /*!< SYS_T::GPC_MFPH: PC13MFP Position */ +#define SYS_GPC_MFPH_PC13MFP_Msk (0xful << SYS_GPC_MFPH_PC13MFP_Pos) /*!< SYS_T::GPC_MFPH: PC13MFP Mask */ + +#define SYS_GPC_MFPH_PC14MFP_Pos (24) /*!< SYS_T::GPC_MFPH: PC14MFP Position */ +#define SYS_GPC_MFPH_PC14MFP_Msk (0xful << SYS_GPC_MFPH_PC14MFP_Pos) /*!< SYS_T::GPC_MFPH: PC14MFP Mask */ + +#define SYS_GPC_MFPH_PC15MFP_Pos (28) /*!< SYS_T::GPC_MFPH: PC15MFP Position */ +#define SYS_GPC_MFPH_PC15MFP_Msk (0xful << SYS_GPC_MFPH_PC15MFP_Pos) /*!< SYS_T::GPC_MFPH: PC15MFP Mask */ + +#define SYS_GPD_MFPL_PD0MFP_Pos (0) /*!< SYS_T::GPD_MFPL: PD0MFP Position */ +#define SYS_GPD_MFPL_PD0MFP_Msk (0xful << SYS_GPD_MFPL_PD0MFP_Pos) /*!< SYS_T::GPD_MFPL: PD0MFP Mask */ + +#define SYS_GPD_MFPL_PD1MFP_Pos (4) /*!< SYS_T::GPD_MFPL: PD1MFP Position */ +#define SYS_GPD_MFPL_PD1MFP_Msk (0xful << SYS_GPD_MFPL_PD1MFP_Pos) /*!< SYS_T::GPD_MFPL: PD1MFP Mask */ + +#define SYS_GPD_MFPL_PD2MFP_Pos (8) /*!< SYS_T::GPD_MFPL: PD2MFP Position */ +#define SYS_GPD_MFPL_PD2MFP_Msk (0xful << SYS_GPD_MFPL_PD2MFP_Pos) /*!< SYS_T::GPD_MFPL: PD2MFP Mask */ + +#define SYS_GPD_MFPL_PD3MFP_Pos (12) /*!< SYS_T::GPD_MFPL: PD3MFP Position */ +#define SYS_GPD_MFPL_PD3MFP_Msk (0xful << SYS_GPD_MFPL_PD3MFP_Pos) /*!< SYS_T::GPD_MFPL: PD3MFP Mask */ + +#define SYS_GPD_MFPL_PD4MFP_Pos (16) /*!< SYS_T::GPD_MFPL: PD4MFP Position */ +#define SYS_GPD_MFPL_PD4MFP_Msk (0xful << SYS_GPD_MFPL_PD4MFP_Pos) /*!< SYS_T::GPD_MFPL: PD4MFP Mask */ + +#define SYS_GPD_MFPL_PD5MFP_Pos (20) /*!< SYS_T::GPD_MFPL: PD5MFP Position */ +#define SYS_GPD_MFPL_PD5MFP_Msk (0xful << SYS_GPD_MFPL_PD5MFP_Pos) /*!< SYS_T::GPD_MFPL: PD5MFP Mask */ + +#define SYS_GPD_MFPL_PD6MFP_Pos (24) /*!< SYS_T::GPD_MFPL: PD6MFP Position */ +#define SYS_GPD_MFPL_PD6MFP_Msk (0xful << SYS_GPD_MFPL_PD6MFP_Pos) /*!< SYS_T::GPD_MFPL: PD6MFP Mask */ + +#define SYS_GPD_MFPL_PD7MFP_Pos (28) /*!< SYS_T::GPD_MFPL: PD7MFP Position */ +#define SYS_GPD_MFPL_PD7MFP_Msk (0xful << SYS_GPD_MFPL_PD7MFP_Pos) /*!< SYS_T::GPD_MFPL: PD7MFP Mask */ + +#define SYS_GPD_MFPH_PD8MFP_Pos (0) /*!< SYS_T::GPD_MFPH: PD8MFP Position */ +#define SYS_GPD_MFPH_PD8MFP_Msk (0xful << SYS_GPD_MFPH_PD8MFP_Pos) /*!< SYS_T::GPD_MFPH: PD8MFP Mask */ + +#define SYS_GPD_MFPH_PD9MFP_Pos (4) /*!< SYS_T::GPD_MFPH: PD9MFP Position */ +#define SYS_GPD_MFPH_PD9MFP_Msk (0xful << SYS_GPD_MFPH_PD9MFP_Pos) /*!< SYS_T::GPD_MFPH: PD9MFP Mask */ + +#define SYS_GPD_MFPH_PD10MFP_Pos (8) /*!< SYS_T::GPD_MFPH: PD10MFP Position */ +#define SYS_GPD_MFPH_PD10MFP_Msk (0xful << SYS_GPD_MFPH_PD10MFP_Pos) /*!< SYS_T::GPD_MFPH: PD10MFP Mask */ + +#define SYS_GPD_MFPH_PD11MFP_Pos (12) /*!< SYS_T::GPD_MFPH: PD11MFP Position */ +#define SYS_GPD_MFPH_PD11MFP_Msk (0xful << SYS_GPD_MFPH_PD11MFP_Pos) /*!< SYS_T::GPD_MFPH: PD11MFP Mask */ + +#define SYS_GPD_MFPH_PD12MFP_Pos (16) /*!< SYS_T::GPD_MFPH: PD12MFP Position */ +#define SYS_GPD_MFPH_PD12MFP_Msk (0xful << SYS_GPD_MFPH_PD12MFP_Pos) /*!< SYS_T::GPD_MFPH: PD12MFP Mask */ + +#define SYS_GPD_MFPH_PD13MFP_Pos (20) /*!< SYS_T::GPD_MFPH: PD13MFP Position */ +#define SYS_GPD_MFPH_PD13MFP_Msk (0xful << SYS_GPD_MFPH_PD13MFP_Pos) /*!< SYS_T::GPD_MFPH: PD13MFP Mask */ + +#define SYS_GPD_MFPH_PD14MFP_Pos (24) /*!< SYS_T::GPD_MFPH: PD14MFP Position */ +#define SYS_GPD_MFPH_PD14MFP_Msk (0xful << SYS_GPD_MFPH_PD14MFP_Pos) /*!< SYS_T::GPD_MFPH: PD14MFP Mask */ + +#define SYS_GPD_MFPH_PD15MFP_Pos (28) /*!< SYS_T::GPD_MFPH: PD15MFP Position */ +#define SYS_GPD_MFPH_PD15MFP_Msk (0xful << SYS_GPD_MFPH_PD15MFP_Pos) /*!< SYS_T::GPD_MFPH: PD15MFP Mask */ + +#define SYS_GPE_MFPL_PE0MFP_Pos (0) /*!< SYS_T::GPE_MFPL: PE0MFP Position */ +#define SYS_GPE_MFPL_PE0MFP_Msk (0xful << SYS_GPE_MFPL_PE0MFP_Pos) /*!< SYS_T::GPE_MFPL: PE0MFP Mask */ + +#define SYS_GPE_MFPL_PE1MFP_Pos (4) /*!< SYS_T::GPE_MFPL: PE1MFP Position */ +#define SYS_GPE_MFPL_PE1MFP_Msk (0xful << SYS_GPE_MFPL_PE1MFP_Pos) /*!< SYS_T::GPE_MFPL: PE1MFP Mask */ + +#define SYS_GPE_MFPL_PE2MFP_Pos (8) /*!< SYS_T::GPE_MFPL: PE2MFP Position */ +#define SYS_GPE_MFPL_PE2MFP_Msk (0xful << SYS_GPE_MFPL_PE2MFP_Pos) /*!< SYS_T::GPE_MFPL: PE2MFP Mask */ + +#define SYS_GPE_MFPL_PE3MFP_Pos (12) /*!< SYS_T::GPE_MFPL: PE3MFP Position */ +#define SYS_GPE_MFPL_PE3MFP_Msk (0xful << SYS_GPE_MFPL_PE3MFP_Pos) /*!< SYS_T::GPE_MFPL: PE3MFP Mask */ + +#define SYS_GPE_MFPL_PE4MFP_Pos (16) /*!< SYS_T::GPE_MFPL: PE4MFP Position */ +#define SYS_GPE_MFPL_PE4MFP_Msk (0xful << SYS_GPE_MFPL_PE4MFP_Pos) /*!< SYS_T::GPE_MFPL: PE4MFP Mask */ + +#define SYS_GPE_MFPL_PE5MFP_Pos (20) /*!< SYS_T::GPE_MFPL: PE5MFP Position */ +#define SYS_GPE_MFPL_PE5MFP_Msk (0xful << SYS_GPE_MFPL_PE5MFP_Pos) /*!< SYS_T::GPE_MFPL: PE5MFP Mask */ + +#define SYS_GPE_MFPL_PE6MFP_Pos (24) /*!< SYS_T::GPE_MFPL: PE6MFP Position */ +#define SYS_GPE_MFPL_PE6MFP_Msk (0xful << SYS_GPE_MFPL_PE6MFP_Pos) /*!< SYS_T::GPE_MFPL: PE6MFP Mask */ + +#define SYS_GPE_MFPL_PE7MFP_Pos (28) /*!< SYS_T::GPE_MFPL: PE7MFP Position */ +#define SYS_GPE_MFPL_PE7MFP_Msk (0xful << SYS_GPE_MFPL_PE7MFP_Pos) /*!< SYS_T::GPE_MFPL: PE7MFP Mask */ + +#define SYS_GPE_MFPH_PE8MFP_Pos (0) /*!< SYS_T::GPE_MFPH: PE8MFP Position */ +#define SYS_GPE_MFPH_PE8MFP_Msk (0xful << SYS_GPE_MFPH_PE8MFP_Pos) /*!< SYS_T::GPE_MFPH: PE8MFP Mask */ + +#define SYS_GPE_MFPH_PE9MFP_Pos (4) /*!< SYS_T::GPE_MFPH: PE9MFP Position */ +#define SYS_GPE_MFPH_PE9MFP_Msk (0xful << SYS_GPE_MFPH_PE9MFP_Pos) /*!< SYS_T::GPE_MFPH: PE9MFP Mask */ + +#define SYS_GPE_MFPH_PE10MFP_Pos (8) /*!< SYS_T::GPE_MFPH: PE10MFP Position */ +#define SYS_GPE_MFPH_PE10MFP_Msk (0xful << SYS_GPE_MFPH_PE10MFP_Pos) /*!< SYS_T::GPE_MFPH: PE10MFP Mask */ + +#define SYS_GPE_MFPH_PE11MFP_Pos (12) /*!< SYS_T::GPE_MFPH: PE11MFP Position */ +#define SYS_GPE_MFPH_PE11MFP_Msk (0xful << SYS_GPE_MFPH_PE11MFP_Pos) /*!< SYS_T::GPE_MFPH: PE11MFP Mask */ + +#define SYS_GPE_MFPH_PE12MFP_Pos (16) /*!< SYS_T::GPE_MFPH: PE12MFP Position */ +#define SYS_GPE_MFPH_PE12MFP_Msk (0xful << SYS_GPE_MFPH_PE12MFP_Pos) /*!< SYS_T::GPE_MFPH: PE12MFP Mask */ + +#define SYS_GPE_MFPH_PE13MFP_Pos (20) /*!< SYS_T::GPE_MFPH: PE13MFP Position */ +#define SYS_GPE_MFPH_PE13MFP_Msk (0xful << SYS_GPE_MFPH_PE13MFP_Pos) /*!< SYS_T::GPE_MFPH: PE13MFP Mask */ + +#define SYS_GPE_MFPH_PE14MFP_Pos (24) /*!< SYS_T::GPE_MFPH: PE14MFP Position */ +#define SYS_GPE_MFPH_PE14MFP_Msk (0xful << SYS_GPE_MFPH_PE14MFP_Pos) /*!< SYS_T::GPE_MFPH: PE14MFP Mask */ + +#define SYS_GPE_MFPH_PE15MFP_Pos (28) /*!< SYS_T::GPE_MFPH: PE15MFP Position */ +#define SYS_GPE_MFPH_PE15MFP_Msk (0xful << SYS_GPE_MFPH_PE15MFP_Pos) /*!< SYS_T::GPE_MFPH: PE15MFP Mask */ + +#define SYS_GPF_MFPL_PF0MFP_Pos (0) /*!< SYS_T::GPF_MFPL: PF0MFP Position */ +#define SYS_GPF_MFPL_PF0MFP_Msk (0xful << SYS_GPF_MFPL_PF0MFP_Pos) /*!< SYS_T::GPF_MFPL: PF0MFP Mask */ + +#define SYS_GPF_MFPL_PF1MFP_Pos (4) /*!< SYS_T::GPF_MFPL: PF1MFP Position */ +#define SYS_GPF_MFPL_PF1MFP_Msk (0xful << SYS_GPF_MFPL_PF1MFP_Pos) /*!< SYS_T::GPF_MFPL: PF1MFP Mask */ + +#define SYS_GPF_MFPL_PF2MFP_Pos (8) /*!< SYS_T::GPF_MFPL: PF2MFP Position */ +#define SYS_GPF_MFPL_PF2MFP_Msk (0xful << SYS_GPF_MFPL_PF2MFP_Pos) /*!< SYS_T::GPF_MFPL: PF2MFP Mask */ + +#define SYS_GPF_MFPL_PF3MFP_Pos (12) /*!< SYS_T::GPF_MFPL: PF3MFP Position */ +#define SYS_GPF_MFPL_PF3MFP_Msk (0xful << SYS_GPF_MFPL_PF3MFP_Pos) /*!< SYS_T::GPF_MFPL: PF3MFP Mask */ + +#define SYS_GPF_MFPL_PF4MFP_Pos (16) /*!< SYS_T::GPF_MFPL: PF4MFP Position */ +#define SYS_GPF_MFPL_PF4MFP_Msk (0xful << SYS_GPF_MFPL_PF4MFP_Pos) /*!< SYS_T::GPF_MFPL: PF4MFP Mask */ + +#define SYS_GPF_MFPL_PF5MFP_Pos (20) /*!< SYS_T::GPF_MFPL: PF5MFP Position */ +#define SYS_GPF_MFPL_PF5MFP_Msk (0xful << SYS_GPF_MFPL_PF5MFP_Pos) /*!< SYS_T::GPF_MFPL: PF5MFP Mask */ + +#define SYS_GPF_MFPL_PF6MFP_Pos (24) /*!< SYS_T::GPF_MFPL: PF6MFP Position */ +#define SYS_GPF_MFPL_PF6MFP_Msk (0xful << SYS_GPF_MFPL_PF6MFP_Pos) /*!< SYS_T::GPF_MFPL: PF6MFP Mask */ + +#define SYS_GPF_MFPL_PF7MFP_Pos (28) /*!< SYS_T::GPF_MFPL: PF7MFP Position */ +#define SYS_GPF_MFPL_PF7MFP_Msk (0xful << SYS_GPF_MFPL_PF7MFP_Pos) /*!< SYS_T::GPF_MFPL: PF7MFP Mask */ + +#define SYS_GPF_MFPH_PF8MFP_Pos (0) /*!< SYS_T::GPF_MFPH: PF8MFP Position */ +#define SYS_GPF_MFPH_PF8MFP_Msk (0xful << SYS_GPF_MFPH_PF8MFP_Pos) /*!< SYS_T::GPF_MFPH: PF8MFP Mask */ + +#define SYS_GPF_MFPH_PF9MFP_Pos (4) /*!< SYS_T::GPF_MFPH: PF9MFP Position */ +#define SYS_GPF_MFPH_PF9MFP_Msk (0xful << SYS_GPF_MFPH_PF9MFP_Pos) /*!< SYS_T::GPF_MFPH: PF9MFP Mask */ + +#define SYS_GPF_MFPH_PF10MFP_Pos (8) /*!< SYS_T::GPF_MFPH: PF10MFP Position */ +#define SYS_GPF_MFPH_PF10MFP_Msk (0xful << SYS_GPF_MFPH_PF10MFP_Pos) /*!< SYS_T::GPF_MFPH: PF10MFP Mask */ + +#define SYS_GPF_MFPH_PF11MFP_Pos (12) /*!< SYS_T::GPF_MFPH: PF11MFP Position */ +#define SYS_GPF_MFPH_PF11MFP_Msk (0xful << SYS_GPF_MFPH_PF11MFP_Pos) /*!< SYS_T::GPF_MFPH: PF11MFP Mask */ + +#define SYS_GPF_MFPH_PF12MFP_Pos (16) /*!< SYS_T::GPF_MFPH: PF12MFP Position */ +#define SYS_GPF_MFPH_PF12MFP_Msk (0xful << SYS_GPF_MFPH_PF12MFP_Pos) /*!< SYS_T::GPF_MFPH: PF12MFP Mask */ + +#define SYS_GPF_MFPH_PF13MFP_Pos (20) /*!< SYS_T::GPF_MFPH: PF13MFP Position */ +#define SYS_GPF_MFPH_PF13MFP_Msk (0xful << SYS_GPF_MFPH_PF13MFP_Pos) /*!< SYS_T::GPF_MFPH: PF13MFP Mask */ + +#define SYS_GPF_MFPH_PF14MFP_Pos (24) /*!< SYS_T::GPF_MFPH: PF14MFP Position */ +#define SYS_GPF_MFPH_PF14MFP_Msk (0xful << SYS_GPF_MFPH_PF14MFP_Pos) /*!< SYS_T::GPF_MFPH: PF14MFP Mask */ + +#define SYS_GPF_MFPH_PF15MFP_Pos (28) /*!< SYS_T::GPF_MFPH: PF15MFP Position */ +#define SYS_GPF_MFPH_PF15MFP_Msk (0xful << SYS_GPF_MFPH_PF15MFP_Pos) /*!< SYS_T::GPF_MFPH: PF15MFP Mask */ + +#define SYS_GPG_MFPL_PG0MFP_Pos (0) /*!< SYS_T::GPG_MFPL: PG0MFP Position */ +#define SYS_GPG_MFPL_PG0MFP_Msk (0xful << SYS_GPG_MFPL_PG0MFP_Pos) /*!< SYS_T::GPG_MFPL: PG0MFP Mask */ + +#define SYS_GPG_MFPL_PG1MFP_Pos (4) /*!< SYS_T::GPG_MFPL: PG1MFP Position */ +#define SYS_GPG_MFPL_PG1MFP_Msk (0xful << SYS_GPG_MFPL_PG1MFP_Pos) /*!< SYS_T::GPG_MFPL: PG1MFP Mask */ + +#define SYS_GPG_MFPL_PG2MFP_Pos (8) /*!< SYS_T::GPG_MFPL: PG2MFP Position */ +#define SYS_GPG_MFPL_PG2MFP_Msk (0xful << SYS_GPG_MFPL_PG2MFP_Pos) /*!< SYS_T::GPG_MFPL: PG2MFP Mask */ + +#define SYS_GPG_MFPL_PG3MFP_Pos (12) /*!< SYS_T::GPG_MFPL: PG3MFP Position */ +#define SYS_GPG_MFPL_PG3MFP_Msk (0xful << SYS_GPG_MFPL_PG3MFP_Pos) /*!< SYS_T::GPG_MFPL: PG3MFP Mask */ + +#define SYS_GPG_MFPL_PG4MFP_Pos (16) /*!< SYS_T::GPG_MFPL: PG4MFP Position */ +#define SYS_GPG_MFPL_PG4MFP_Msk (0xful << SYS_GPG_MFPL_PG4MFP_Pos) /*!< SYS_T::GPG_MFPL: PG4MFP Mask */ + +#define SYS_GPG_MFPL_PG5MFP_Pos (20) /*!< SYS_T::GPG_MFPL: PG5MFP Position */ +#define SYS_GPG_MFPL_PG5MFP_Msk (0xful << SYS_GPG_MFPL_PG5MFP_Pos) /*!< SYS_T::GPG_MFPL: PG5MFP Mask */ + +#define SYS_GPG_MFPL_PG6MFP_Pos (24) /*!< SYS_T::GPG_MFPL: PG6MFP Position */ +#define SYS_GPG_MFPL_PG6MFP_Msk (0xful << SYS_GPG_MFPL_PG6MFP_Pos) /*!< SYS_T::GPG_MFPL: PG6MFP Mask */ + +#define SYS_GPG_MFPL_PG7MFP_Pos (28) /*!< SYS_T::GPG_MFPL: PG7MFP Position */ +#define SYS_GPG_MFPL_PG7MFP_Msk (0xful << SYS_GPG_MFPL_PG7MFP_Pos) /*!< SYS_T::GPG_MFPL: PG7MFP Mask */ + +#define SYS_GPG_MFPH_PG8MFP_Pos (0) /*!< SYS_T::GPG_MFPH: PG8MFP Position */ +#define SYS_GPG_MFPH_PG8MFP_Msk (0xful << SYS_GPG_MFPH_PG8MFP_Pos) /*!< SYS_T::GPG_MFPH: PG8MFP Mask */ + +#define SYS_GPG_MFPH_PG9MFP_Pos (4) /*!< SYS_T::GPG_MFPH: PG9MFP Position */ +#define SYS_GPG_MFPH_PG9MFP_Msk (0xful << SYS_GPG_MFPH_PG9MFP_Pos) /*!< SYS_T::GPG_MFPH: PG9MFP Mask */ + +#define SYS_GPG_MFPH_PG10MFP_Pos (8) /*!< SYS_T::GPG_MFPH: PG10MFP Position */ +#define SYS_GPG_MFPH_PG10MFP_Msk (0xful << SYS_GPG_MFPH_PG10MFP_Pos) /*!< SYS_T::GPG_MFPH: PG10MFP Mask */ + +#define SYS_GPG_MFPH_PG11MFP_Pos (12) /*!< SYS_T::GPG_MFPH: PG11MFP Position */ +#define SYS_GPG_MFPH_PG11MFP_Msk (0xful << SYS_GPG_MFPH_PG11MFP_Pos) /*!< SYS_T::GPG_MFPH: PG11MFP Mask */ + +#define SYS_GPG_MFPH_PG12MFP_Pos (16) /*!< SYS_T::GPG_MFPH: PG12MFP Position */ +#define SYS_GPG_MFPH_PG12MFP_Msk (0xful << SYS_GPG_MFPH_PG12MFP_Pos) /*!< SYS_T::GPG_MFPH: PG12MFP Mask */ + +#define SYS_GPG_MFPH_PG13MFP_Pos (20) /*!< SYS_T::GPG_MFPH: PG13MFP Position */ +#define SYS_GPG_MFPH_PG13MFP_Msk (0xful << SYS_GPG_MFPH_PG13MFP_Pos) /*!< SYS_T::GPG_MFPH: PG13MFP Mask */ + +#define SYS_GPG_MFPH_PG14MFP_Pos (24) /*!< SYS_T::GPG_MFPH: PG14MFP Position */ +#define SYS_GPG_MFPH_PG14MFP_Msk (0xful << SYS_GPG_MFPH_PG14MFP_Pos) /*!< SYS_T::GPG_MFPH: PG14MFP Mask */ + +#define SYS_GPG_MFPH_PG15MFP_Pos (28) /*!< SYS_T::GPG_MFPH: PG15MFP Position */ +#define SYS_GPG_MFPH_PG15MFP_Msk (0xful << SYS_GPG_MFPH_PG15MFP_Pos) /*!< SYS_T::GPG_MFPH: PG15MFP Mask */ + +#define SYS_GPH_MFPL_PH0MFP_Pos (0) /*!< SYS_T::GPH_MFPL: PH0MFP Position */ +#define SYS_GPH_MFPL_PH0MFP_Msk (0xful << SYS_GPH_MFPL_PH0MFP_Pos) /*!< SYS_T::GPH_MFPL: PH0MFP Mask */ + +#define SYS_GPH_MFPL_PH1MFP_Pos (4) /*!< SYS_T::GPH_MFPL: PH1MFP Position */ +#define SYS_GPH_MFPL_PH1MFP_Msk (0xful << SYS_GPH_MFPL_PH1MFP_Pos) /*!< SYS_T::GPH_MFPL: PH1MFP Mask */ + +#define SYS_GPH_MFPL_PH2MFP_Pos (8) /*!< SYS_T::GPH_MFPL: PH2MFP Position */ +#define SYS_GPH_MFPL_PH2MFP_Msk (0xful << SYS_GPH_MFPL_PH2MFP_Pos) /*!< SYS_T::GPH_MFPL: PH2MFP Mask */ + +#define SYS_GPH_MFPL_PH3MFP_Pos (12) /*!< SYS_T::GPH_MFPL: PH3MFP Position */ +#define SYS_GPH_MFPL_PH3MFP_Msk (0xful << SYS_GPH_MFPL_PH3MFP_Pos) /*!< SYS_T::GPH_MFPL: PH3MFP Mask */ + +#define SYS_GPH_MFPL_PH4MFP_Pos (16) /*!< SYS_T::GPH_MFPL: PH4MFP Position */ +#define SYS_GPH_MFPL_PH4MFP_Msk (0xful << SYS_GPH_MFPL_PH4MFP_Pos) /*!< SYS_T::GPH_MFPL: PH4MFP Mask */ + +#define SYS_GPH_MFPL_PH5MFP_Pos (20) /*!< SYS_T::GPH_MFPL: PH5MFP Position */ +#define SYS_GPH_MFPL_PH5MFP_Msk (0xful << SYS_GPH_MFPL_PH5MFP_Pos) /*!< SYS_T::GPH_MFPL: PH5MFP Mask */ + +#define SYS_GPH_MFPL_PH6MFP_Pos (24) /*!< SYS_T::GPH_MFPL: PH6MFP Position */ +#define SYS_GPH_MFPL_PH6MFP_Msk (0xful << SYS_GPH_MFPL_PH6MFP_Pos) /*!< SYS_T::GPH_MFPL: PH6MFP Mask */ + +#define SYS_GPH_MFPL_PH7MFP_Pos (28) /*!< SYS_T::GPH_MFPL: PH7MFP Position */ +#define SYS_GPH_MFPL_PH7MFP_Msk (0xful << SYS_GPH_MFPL_PH7MFP_Pos) /*!< SYS_T::GPH_MFPL: PH7MFP Mask */ + +#define SYS_GPH_MFPH_PH8MFP_Pos (0) /*!< SYS_T::GPH_MFPH: PH8MFP Position */ +#define SYS_GPH_MFPH_PH8MFP_Msk (0xful << SYS_GPH_MFPH_PH8MFP_Pos) /*!< SYS_T::GPH_MFPH: PH8MFP Mask */ + +#define SYS_GPH_MFPH_PH9MFP_Pos (4) /*!< SYS_T::GPH_MFPH: PH9MFP Position */ +#define SYS_GPH_MFPH_PH9MFP_Msk (0xful << SYS_GPH_MFPH_PH9MFP_Pos) /*!< SYS_T::GPH_MFPH: PH9MFP Mask */ + +#define SYS_GPH_MFPH_PH10MFP_Pos (8) /*!< SYS_T::GPH_MFPH: PH10MFP Position */ +#define SYS_GPH_MFPH_PH10MFP_Msk (0xful << SYS_GPH_MFPH_PH10MFP_Pos) /*!< SYS_T::GPH_MFPH: PH10MFP Mask */ + +#define SYS_GPH_MFPH_PH11MFP_Pos (12) /*!< SYS_T::GPH_MFPH: PH11MFP Position */ +#define SYS_GPH_MFPH_PH11MFP_Msk (0xful << SYS_GPH_MFPH_PH11MFP_Pos) /*!< SYS_T::GPH_MFPH: PH11MFP Mask */ + +#define SYS_GPH_MFPH_PH12MFP_Pos (16) /*!< SYS_T::GPH_MFPH: PH12MFP Position */ +#define SYS_GPH_MFPH_PH12MFP_Msk (0xful << SYS_GPH_MFPH_PH12MFP_Pos) /*!< SYS_T::GPH_MFPH: PH12MFP Mask */ + +#define SYS_GPH_MFPH_PH13MFP_Pos (20) /*!< SYS_T::GPH_MFPH: PH13MFP Position */ +#define SYS_GPH_MFPH_PH13MFP_Msk (0xful << SYS_GPH_MFPH_PH13MFP_Pos) /*!< SYS_T::GPH_MFPH: PH13MFP Mask */ + +#define SYS_GPH_MFPH_PH14MFP_Pos (24) /*!< SYS_T::GPH_MFPH: PH14MFP Position */ +#define SYS_GPH_MFPH_PH14MFP_Msk (0xful << SYS_GPH_MFPH_PH14MFP_Pos) /*!< SYS_T::GPH_MFPH: PH14MFP Mask */ + +#define SYS_GPH_MFPH_PH15MFP_Pos (28) /*!< SYS_T::GPH_MFPH: PH15MFP Position */ +#define SYS_GPH_MFPH_PH15MFP_Msk (0xful << SYS_GPH_MFPH_PH15MFP_Pos) /*!< SYS_T::GPH_MFPH: PH15MFP Mask */ + +#define SYS_LPLDOCTL_LPLDO_EN_Pos (0) /*!< SYS_T::LPLDOCTL: LPLDO_EN Position */ +#define SYS_LPLDOCTL_LPLDO_EN_Msk (0x1ul << SYS_LPLDOCTL_LPLDO_EN_Pos) /*!< SYS_T::LPLDOCTL: LPLDO_EN Mask */ + +#define SYS_MODCTL_MODEN_Pos (0) /*!< SYS_T::MODCTL: MODEN Position */ +#define SYS_MODCTL_MODEN_Msk (0x1ul << SYS_MODCTL_MODEN_Pos) /*!< SYS_T::MODCTL: MODEN Mask */ + +#define SYS_MODCTL_MODH_Pos (1) /*!< SYS_T::MODCTL: MODH Position */ +#define SYS_MODCTL_MODH_Msk (0x1ul << SYS_MODCTL_MODH_Pos) /*!< SYS_T::MODCTL: MODH Mask */ + +#define SYS_MODCTL_MODPWMSEL_Pos (4) /*!< SYS_T::MODCTL: MODPWMSEL Position */ +#define SYS_MODCTL_MODPWMSEL_Msk (0xful << SYS_MODCTL_MODPWMSEL_Pos) /*!< SYS_T::MODCTL: MODPWMSEL Mask */ + +#define SYS_SRAM_BISTCTL_SRBIST_Pos (0) /*!< SYS_T::SRAM_BISTCTL: SRBIST Position */ +#define SYS_SRAM_BISTCTL_SRBIST_Msk (0x1ul << SYS_SRAM_BISTCTL_SRBIST_Pos) /*!< SYS_T::SRAM_BISTCTL: SRBIST Mask */ + +#define SYS_SRAM_BISTCTL_USBBIST_Pos (4) /*!< SYS_T::SRAM_BISTCTL: USBBIST Position */ +#define SYS_SRAM_BISTCTL_USBBIST_Msk (0x1ul << SYS_SRAM_BISTCTL_USBBIST_Pos) /*!< SYS_T::SRAM_BISTCTL: USBBIST Mask */ + +#define SYS_SRAM_BISTCTL_PDMABIST_Pos (7) /*!< SYS_T::SRAM_BISTCTL: PDMABIST Position */ +#define SYS_SRAM_BISTCTL_PDMABIST_Msk (0x1ul << SYS_SRAM_BISTCTL_PDMABIST_Pos) /*!< SYS_T::SRAM_BISTCTL: PDMABIST Mask */ + +#define SYS_SRAM_BISTSTS_SRBISTEF_Pos (0) /*!< SYS_T::SRAM_BISTSTS: SRBISTEF Position */ +#define SYS_SRAM_BISTSTS_SRBISTEF_Msk (0x1ul << SYS_SRAM_BISTSTS_SRBISTEF_Pos) /*!< SYS_T::SRAM_BISTSTS: SRBISTEF Mask */ + +#define SYS_SRAM_BISTSTS_USBBEF_Pos (4) /*!< SYS_T::SRAM_BISTSTS: USBBEF Position */ +#define SYS_SRAM_BISTSTS_USBBEF_Msk (0x1ul << SYS_SRAM_BISTSTS_USBBEF_Pos) /*!< SYS_T::SRAM_BISTSTS: USBBEF Mask */ + +#define SYS_SRAM_BISTSTS_PDMABISTF_Pos (7) /*!< SYS_T::SRAM_BISTSTS: PDMABISTF Position*/ +#define SYS_SRAM_BISTSTS_PDMABISTF_Msk (0x1ul << SYS_SRAM_BISTSTS_PDMABISTF_Pos) /*!< SYS_T::SRAM_BISTSTS: PDMABISTF Mask */ + +#define SYS_SRAM_BISTSTS_SRBEND_Pos (16) /*!< SYS_T::SRAM_BISTSTS: SRBEND Position */ +#define SYS_SRAM_BISTSTS_SRBEND_Msk (0x1ul << SYS_SRAM_BISTSTS_SRBEND_Pos) /*!< SYS_T::SRAM_BISTSTS: SRBEND Mask */ + +#define SYS_SRAM_BISTSTS_USBBEND_Pos (20) /*!< SYS_T::SRAM_BISTSTS: USBBEND Position */ +#define SYS_SRAM_BISTSTS_USBBEND_Msk (0x1ul << SYS_SRAM_BISTSTS_USBBEND_Pos) /*!< SYS_T::SRAM_BISTSTS: USBBEND Mask */ + +#define SYS_SRAM_BISTSTS_PDMAEND_Pos (23) /*!< SYS_T::SRAM_BISTSTS: PDMAEND Position */ +#define SYS_SRAM_BISTSTS_PDMAEND_Msk (0x1ul << SYS_SRAM_BISTSTS_PDMAEND_Pos) /*!< SYS_T::SRAM_BISTSTS: PDMAEND Mask */ + +#define SYS_SRAM_PARITY_PTESTEN_Pos (0) /*!< SYS_T::SRAM_PARITY: PTESTEN Position */ +#define SYS_SRAM_PARITY_PTESTEN_Msk (0x1ul << SYS_SRAM_PARITY_PTESTEN_Pos) /*!< SYS_T::SRAM_PARITY: PTESTEN Mask */ + +#define SYS_SRAM_PARITY_PTESTPB_Pos (4) /*!< SYS_T::SRAM_PARITY: PTESTPB Position */ +#define SYS_SRAM_PARITY_PTESTPB_Msk (0xful << SYS_SRAM_PARITY_PTESTPB_Pos) /*!< SYS_T::SRAM_PARITY: PTESTPB Mask */ + +#define SYS_SRAM_INTCTL_PERRIEN_Pos (0) /*!< SYS_T::SRAM_INTCTL: PERRIEN Position */ +#define SYS_SRAM_INTCTL_PERRIEN_Msk (0x1ul << SYS_SRAM_INTCTL_PERRIEN_Pos) /*!< SYS_T::SRAM_INTCTL: PERRIEN Mask */ + +#define SYS_SRAM_STATUS_PERRIF_Pos (0) /*!< SYS_T::SRAM_STATUS: PERRIF Position */ +#define SYS_SRAM_STATUS_PERRIF_Msk (0x1ul << SYS_SRAM_STATUS_PERRIF_Pos) /*!< SYS_T::SRAM_STATUS: PERRIF Mask */ + +#define SYS_SRAM_ERRADDR_ERRADDR_Pos (0) /*!< SYS_T::SRAM_ERRADDR: ERRADDR Position */ +#define SYS_SRAM_ERRADDR_ERRADDR_Msk (0xfffffffful << SYS_SRAM_ERRADDR_ERRADDR_Pos) /*!< SYS_T::SRAM_ERRADDR: ERRADDR Mask */ + +#define SYS_HIRCTRIMCTL_FREQSEL_Pos (0) /*!< SYS_T::HIRCTRIMCTL: FREQSEL Position */ +#define SYS_HIRCTRIMCTL_FREQSEL_Msk (0x3ul << SYS_HIRCTRIMCTL_FREQSEL_Pos) /*!< SYS_T::HIRCTRIMCTL: FREQSEL Mask */ + +#define SYS_HIRCTRIMCTL_LOOPSEL_Pos (4) /*!< SYS_T::HIRCTRIMCTL: LOOPSEL Position */ +#define SYS_HIRCTRIMCTL_LOOPSEL_Msk (0x3ul << SYS_HIRCTRIMCTL_LOOPSEL_Pos) /*!< SYS_T::HIRCTRIMCTL: LOOPSEL Mask */ + +#define SYS_HIRCTRIMCTL_RETRYCNT_Pos (6) /*!< SYS_T::HIRCTRIMCTL: RETRYCNT Position */ +#define SYS_HIRCTRIMCTL_RETRYCNT_Msk (0x3ul << SYS_HIRCTRIMCTL_RETRYCNT_Pos) /*!< SYS_T::HIRCTRIMCTL: RETRYCNT Mask */ + +#define SYS_HIRCTRIMCTL_CESTOPEN_Pos (8) /*!< SYS_T::HIRCTRIMCTL: CESTOPEN Position */ +#define SYS_HIRCTRIMCTL_CESTOPEN_Msk (0x1ul << SYS_HIRCTRIMCTL_CESTOPEN_Pos) /*!< SYS_T::HIRCTRIMCTL: CESTOPEN Mask */ + +#define SYS_HIRCTRIMCTL_BOUNDEN_Pos (9) /*!< SYS_T::HIRCTRIMCTL: BOUNDEN Position */ +#define SYS_HIRCTRIMCTL_BOUNDEN_Msk (0x1ul << SYS_HIRCTRIMCTL_BOUNDEN_Pos) /*!< SYS_T::HIRCTRIMCTL: BOUNDEN Mask */ + +#define SYS_HIRCTRIMCTL_REFCKSEL_Pos (10) /*!< SYS_T::HIRCTRIMCTL: REFCKSEL Position */ +#define SYS_HIRCTRIMCTL_REFCKSEL_Msk (0x1ul << SYS_HIRCTRIMCTL_REFCKSEL_Pos) /*!< SYS_T::HIRCTRIMCTL: REFCKSEL Mask */ + +#define SYS_HIRCTRIMCTL_BOUNDARY_Pos (16) /*!< SYS_T::HIRCTRIMCTL: BOUNDARY Position */ +#define SYS_HIRCTRIMCTL_BOUNDARY_Msk (0x1ful << SYS_HIRCTRIMCTL_BOUNDARY_Pos) /*!< SYS_T::HIRCTRIMCTL: BOUNDARY Mask */ + +#define SYS_HIRCTRIMIEN_TFALIEN_Pos (1) /*!< SYS_T::HIRCTRIMIEN: TFALIEN Position */ +#define SYS_HIRCTRIMIEN_TFALIEN_Msk (0x1ul << SYS_HIRCTRIMIEN_TFALIEN_Pos) /*!< SYS_T::HIRCTRIMIEN: TFALIEN Mask */ + +#define SYS_HIRCTRIMIEN_CLKEIEN_Pos (2) /*!< SYS_T::HIRCTRIMIEN: CLKEIEN Position */ +#define SYS_HIRCTRIMIEN_CLKEIEN_Msk (0x1ul << SYS_HIRCTRIMIEN_CLKEIEN_Pos) /*!< SYS_T::HIRCTRIMIEN: CLKEIEN Mask */ + +#define SYS_HIRCTRIMSTS_FREQLOCK_Pos (0) /*!< SYS_T::HIRCTRIMSTS: FREQLOCK Position */ +#define SYS_HIRCTRIMSTS_FREQLOCK_Msk (0x1ul << SYS_HIRCTRIMSTS_FREQLOCK_Pos) /*!< SYS_T::HIRCTRIMSTS: FREQLOCK Mask */ + +#define SYS_HIRCTRIMSTS_TFAILIF_Pos (1) /*!< SYS_T::HIRCTRIMSTS: TFAILIF Position */ +#define SYS_HIRCTRIMSTS_TFAILIF_Msk (0x1ul << SYS_HIRCTRIMSTS_TFAILIF_Pos) /*!< SYS_T::HIRCTRIMSTS: TFAILIF Mask */ + +#define SYS_HIRCTRIMSTS_CLKERIF_Pos (2) /*!< SYS_T::HIRCTRIMSTS: CLKERIF Position */ +#define SYS_HIRCTRIMSTS_CLKERIF_Msk (0x1ul << SYS_HIRCTRIMSTS_CLKERIF_Pos) /*!< SYS_T::HIRCTRIMSTS: CLKERIF Mask */ + +#define SYS_HIRCTRIMSTS_OVBDIF_Pos (3) /*!< SYS_T::HIRCTRIMSTS: OVBDIF Position */ +#define SYS_HIRCTRIMSTS_OVBDIF_Msk (0x1ul << SYS_HIRCTRIMSTS_OVBDIF_Pos) /*!< SYS_T::HIRCTRIMSTS: OVBDIF Mask */ + +#define SYS_REGLCTL_REGLCTL_Pos (0) /*!< SYS_T::REGLCTL: REGLCTL Position */ +#define SYS_REGLCTL_REGLCTL_Msk (0xfful << SYS_REGLCTL_REGLCTL_Pos) /*!< SYS_T::REGLCTL: REGLCTL Mask */ + +#define SYS_PORDISAN_POROFFAN_Pos (0) /*!< SYS_T::PORDISAN: POROFFAN Position */ +#define SYS_PORDISAN_POROFFAN_Msk (0xfffful << SYS_PORDISAN_POROFFAN_Pos) /*!< SYS_T::PORDISAN: POROFFAN Mask */ + +#define NMI_NMIEN_BODOUT_Pos (0) /*!< NMI_T::NMIEN: BODOUT Position */ +#define NMI_NMIEN_BODOUT_Msk (0x1ul << NMI_NMIEN_BODOUT_Pos) /*!< NMI_T::NMIEN: BODOUT Mask */ + +#define NMI_NMIEN_IRC_INT_Pos (1) /*!< NMI_T::NMIEN: IRC_INT Position */ +#define NMI_NMIEN_IRC_INT_Msk (0x1ul << NMI_NMIEN_IRC_INT_Pos) /*!< NMI_T::NMIEN: IRC_INT Mask */ + +#define NMI_NMIEN_PWRWU_INT_Pos (2) /*!< NMI_T::NMIEN: PWRWU_INT Position */ +#define NMI_NMIEN_PWRWU_INT_Msk (0x1ul << NMI_NMIEN_PWRWU_INT_Pos) /*!< NMI_T::NMIEN: PWRWU_INT Mask */ + +#define NMI_NMIEN_SRAM_PERR_Pos (3) /*!< NMI_T::NMIEN: SRAM_PERR Position */ +#define NMI_NMIEN_SRAM_PERR_Msk (0x1ul << NMI_NMIEN_SRAM_PERR_Pos) /*!< NMI_T::NMIEN: SRAM_PERR Mask */ + +#define NMI_NMIEN_CLKFAIL_Pos (4) /*!< NMI_T::NMIEN: CLKFAIL Position */ +#define NMI_NMIEN_CLKFAIL_Msk (0x1ul << NMI_NMIEN_CLKFAIL_Pos) /*!< NMI_T::NMIEN: CLKFAIL Mask */ + +#define NMI_NMIEN_RTC_INT_Pos (6) /*!< NMI_T::NMIEN: RTC_INT Position */ +#define NMI_NMIEN_RTC_INT_Msk (0x1ul << NMI_NMIEN_RTC_INT_Pos) /*!< NMI_T::NMIEN: RTC_INT Mask */ + +#define NMI_NMIEN_EINT0_Pos (8) /*!< NMI_T::NMIEN: EINT0 Position */ +#define NMI_NMIEN_EINT0_Msk (0x1ul << NMI_NMIEN_EINT0_Pos) /*!< NMI_T::NMIEN: EINT0 Mask */ + +#define NMI_NMIEN_EINT1_Pos (9) /*!< NMI_T::NMIEN: EINT1 Position */ +#define NMI_NMIEN_EINT1_Msk (0x1ul << NMI_NMIEN_EINT1_Pos) /*!< NMI_T::NMIEN: EINT1 Mask */ + +#define NMI_NMIEN_EINT2_Pos (10) /*!< NMI_T::NMIEN: EINT2 Position */ +#define NMI_NMIEN_EINT2_Msk (0x1ul << NMI_NMIEN_EINT2_Pos) /*!< NMI_T::NMIEN: EINT2 Mask */ + +#define NMI_NMIEN_EINT3_Pos (11) /*!< NMI_T::NMIEN: EINT3 Position */ +#define NMI_NMIEN_EINT3_Msk (0x1ul << NMI_NMIEN_EINT3_Pos) /*!< NMI_T::NMIEN: EINT3 Mask */ + +#define NMI_NMIEN_EINT4_Pos (12) /*!< NMI_T::NMIEN: EINT4 Position */ +#define NMI_NMIEN_EINT4_Msk (0x1ul << NMI_NMIEN_EINT4_Pos) /*!< NMI_T::NMIEN: EINT4 Mask */ + +#define NMI_NMIEN_EINT5_Pos (13) /*!< NMI_T::NMIEN: EINT5 Position */ +#define NMI_NMIEN_EINT5_Msk (0x1ul << NMI_NMIEN_EINT5_Pos) /*!< NMI_T::NMIEN: EINT5 Mask */ + +#define NMI_NMIEN_UART0_INT_Pos (14) /*!< NMI_T::NMIEN: UART0_INT Position */ +#define NMI_NMIEN_UART0_INT_Msk (0x1ul << NMI_NMIEN_UART0_INT_Pos) /*!< NMI_T::NMIEN: UART0_INT Mask */ + +#define NMI_NMIEN_UART1_INT_Pos (15) /*!< NMI_T::NMIEN: UART1_INT Position */ +#define NMI_NMIEN_UART1_INT_Msk (0x1ul << NMI_NMIEN_UART1_INT_Pos) /*!< NMI_T::NMIEN: UART1_INT Mask */ + +#define NMI_NMISTS_BODOUT_Pos (0) /*!< NMI_T::NMISTS: BODOUT Position */ +#define NMI_NMISTS_BODOUT_Msk (0x1ul << NMI_NMISTS_BODOUT_Pos) /*!< NMI_T::NMISTS: BODOUT Mask */ + +#define NMI_NMISTS_IRC_INT_Pos (1) /*!< NMI_T::NMISTS: IRC_INT Position */ +#define NMI_NMISTS_IRC_INT_Msk (0x1ul << NMI_NMISTS_IRC_INT_Pos) /*!< NMI_T::NMISTS: IRC_INT Mask */ + +#define NMI_NMISTS_PWRWU_INT_Pos (2) /*!< NMI_T::NMISTS: PWRWU_INT Position */ +#define NMI_NMISTS_PWRWU_INT_Msk (0x1ul << NMI_NMISTS_PWRWU_INT_Pos) /*!< NMI_T::NMISTS: PWRWU_INT Mask */ + +#define NMI_NMISTS_SRAM_PERR_Pos (3) /*!< NMI_T::NMISTS: SRAM_PERR Position */ +#define NMI_NMISTS_SRAM_PERR_Msk (0x1ul << NMI_NMISTS_SRAM_PERR_Pos) /*!< NMI_T::NMISTS: SRAM_PERR Mask */ + +#define NMI_NMISTS_CLKFAIL_Pos (4) /*!< NMI_T::NMISTS: CLKFAIL Position */ +#define NMI_NMISTS_CLKFAIL_Msk (0x1ul << NMI_NMISTS_CLKFAIL_Pos) /*!< NMI_T::NMISTS: CLKFAIL Mask */ + +#define NMI_NMISTS_RTC_INT_Pos (6) /*!< NMI_T::NMISTS: RTC_INT Position */ +#define NMI_NMISTS_RTC_INT_Msk (0x1ul << NMI_NMISTS_RTC_INT_Pos) /*!< NMI_T::NMISTS: RTC_INT Mask */ + +#define NMI_NMISTS_EINT0_Pos (8) /*!< NMI_T::NMISTS: EINT0 Position */ +#define NMI_NMISTS_EINT0_Msk (0x1ul << NMI_NMISTS_EINT0_Pos) /*!< NMI_T::NMISTS: EINT0 Mask */ + +#define NMI_NMISTS_EINT1_Pos (9) /*!< NMI_T::NMISTS: EINT1 Position */ +#define NMI_NMISTS_EINT1_Msk (0x1ul << NMI_NMISTS_EINT1_Pos) /*!< NMI_T::NMISTS: EINT1 Mask */ + +#define NMI_NMISTS_EINT2_Pos (10) /*!< NMI_T::NMISTS: EINT2 Position */ +#define NMI_NMISTS_EINT2_Msk (0x1ul << NMI_NMISTS_EINT2_Pos) /*!< NMI_T::NMISTS: EINT2 Mask */ + +#define NMI_NMISTS_EINT3_Pos (11) /*!< NMI_T::NMISTS: EINT3 Position */ +#define NMI_NMISTS_EINT3_Msk (0x1ul << NMI_NMISTS_EINT3_Pos) /*!< NMI_T::NMISTS: EINT3 Mask */ + +#define NMI_NMISTS_EINT4_Pos (12) /*!< NMI_T::NMISTS: EINT4 Position */ +#define NMI_NMISTS_EINT4_Msk (0x1ul << NMI_NMISTS_EINT4_Pos) /*!< NMI_T::NMISTS: EINT4 Mask */ + +#define NMI_NMISTS_EINT5_Pos (13) /*!< NMI_T::NMISTS: EINT5 Position */ +#define NMI_NMISTS_EINT5_Msk (0x1ul << NMI_NMISTS_EINT5_Pos) /*!< NMI_T::NMISTS: EINT5 Mask */ + +#define NMI_NMISTS_UART0_INT_Pos (14) /*!< NMI_T::NMISTS: UART0_INT Position */ +#define NMI_NMISTS_UART0_INT_Msk (0x1ul << NMI_NMISTS_UART0_INT_Pos) /*!< NMI_T::NMISTS: UART0_INT Mask */ + +#define NMI_NMISTS_UART1_INT_Pos (15) /*!< NMI_T::NMISTS: UART1_INT Position */ +#define NMI_NMISTS_UART1_INT_Msk (0x1ul << NMI_NMISTS_UART1_INT_Pos) /*!< NMI_T::NMISTS: UART1_INT Mask */ + +/**@}*/ /* SYS_CONST */ +/**@}*/ /* end of SYS register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __SYS_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/system_M031Series.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/system_M031Series.h new file mode 100644 index 0000000000..1f95fcdb01 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/system_M031Series.h @@ -0,0 +1,105 @@ +/**************************************************************************//** + * @file system_M031Series.h + * @version V3.00 + * $Revision: 5 $ + * $Date: 18/05/29 5:31p $ + * @brief M031 Series System Setting Header File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2017 Nuvoton Technology Corp. All rights reserved. + ******************************************************************************/ +#ifndef __SYSTEM_M031_H__ +#define __SYSTEM_M031_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------------------------------------*/ +/* Macro Definition */ +/*---------------------------------------------------------------------------------------------------------*/ +#ifndef DEBUG_PORT +#define DEBUG_PORT UART0 /*!< Select Debug Port which is used for retarget.c to output debug message to UART */ +#endif + +/** + * + * @details This is used to enable PLL to speed up booting at startup. Remove it will cause system using + * default clock source (External crystal or internal 22.1184MHz IRC). + * Enable this option will cause system booting in 72MHz(By XTAL) or 71.8848MHz(By IRC22M) according to + * user configuration setting in CONFIG0 + * + */ + +/*---------------------------------------------------------------------------- + Define SYSCLK + *----------------------------------------------------------------------------*/ +#ifndef __HXT +#define __HXT (32000000UL) /*!< External Crystal Clock Frequency */ +#endif /*!defined(__HXT) */ + +#ifndef __LXT +#define __LXT (32768UL) /*!< External Crystal Clock Frequency 32.768KHz */ +#endif /*!defined(__LXT) */ + +#define __LIRC (38400UL) /*!< Internal 38.4KHz RC Oscillator Frequency */ +#define __HIRC (48000000UL) /*!< Internal 48M RC Oscillator Frequency */ +#define __HSI (96000000UL) /*!< PLL default output is 96MHz from HIRC */ + +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ +extern uint32_t CyclesPerUs; /*!< Cycles per micro second */ +extern uint32_t PllClock; /*!< PLL Output Clock Frequency */ + +#if USE_ASSERT +/** + * @brief Assert Function + * + * @param[in] expr Expression to be evaluated + * + * @return None + * + * @details If the expression is false, an error message will be printed out + * from debug port (UART0 or UART1). + */ +#define ASSERT_PARAM(expr) { if (!(expr)) { AssertError((uint8_t*)__FILE__, __LINE__); } } + +void AssertError(uint8_t* file, uint32_t line); +#else +#define ASSERT_PARAM(expr) +#endif + +#define assert_param(expr) ASSERT_PARAM(expr) + + +/** + * @brief System Initialization + * + * @param None + * + * @return None + * + * @details The necessary initialization of system. + */ +extern void SystemInit(void); + + +/** + * @brief Update the Variable SystemCoreClock + * + * @param None + * + * @return None + * + * @details This function is used to update the variable SystemCoreClock + * and must be called whenever the core clock is changed. + */ +extern void SystemCoreClockUpdate(void); + +#ifdef __cplusplus +} +#endif + +#endif + +/* Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved. */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/timer_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/timer_reg.h new file mode 100644 index 0000000000..2e05d08ad2 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/timer_reg.h @@ -0,0 +1,336 @@ +/**************************************************************************//** + * @file timer_reg.h + * @version V1.00 + * @brief TIMER register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __TIMER_REG_H__ +#define __TIMER_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup TIMER Timer Controller (TIMER) + Memory Mapped Structure for TIMER Controller +@{ */ + +typedef struct +{ + + + /** + * @var TIMER_T::CTL + * Offset: 0x00/0x20 Timer0~3 Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |PSC |Prescale Counter + * | | |Timer input clock or event source is divided by (PSC+1) before it is fed to the timer up counter. If this field is 0 (PSC = 0), then there is no scaling. + * | | |Note: Update prescale counter value will reset internal 8-bit prescale counter and 24-bit up counter value. + * |[8] |TRGPDMA |Trigger PDMA Enable Bit + * | | |If this bit is set to 1, timer time-out interrupt or capture interrupt can trigger PDMA. + * | | |0 = Timer interrupt trigger PDMA Disabled. + * | | |1 = Timer interrupt trigger PDMA Enabled. + * | | |Note: If TRGSSEL (TIMERx_CTL[18]) = 0, time-out interrupt signal will trigger PDMA. If TRGSSEL (TIMERx_CTL[18]) = 1, capture interrupt signal will trigger PDMA. + * |[9] |TRGBPWM |Trigger BPWM Enable Bit + * | | |If this bit is set to 1, timer time-out interrupt or capture interrupt can trigger BPWM. + * | | |0 = Timer interrupt trigger BPWM Disabled. + * | | |1 = Timer interrupt trigger BPWM Enabled. + * | | |Note: If TRGSSEL (TIMERx_CTL[18]) = 0, time-out interrupt signal will trigger BPWM. If TRGSSEL (TIMERx_CTL[18]) = 1, capture interrupt signal will trigger BPWM. + * |[10] |INTRGEN |Inter-timer Trigger Mode Enable Bit + * | | |Setting this bit will enable the inter-timer trigger capture function. + * | | |The Timer0/2 will be in event counter mode and counting with external clock source or event. Also, Timer1/3 will be in trigger-counting mode of capture function. + * | | |0 = Inter-Timer Trigger mode Disabled. + * | | |1 = Inter-Timer Trigger mode Enabled. + * | | |Note: For Timer1/3, this bit is ignored and the read back value is always 0. + * |[16] |CAPSRC |Capture Pin Source Selection + * | | |0 = Capture Function source is from TMx_EXT (x= 0~3) pin. + * | | |1 = Capture Function source is from internal ACMP output signal or LIRC. User can set INTERCAPSEL (TIMERx_EXTCTL[10:8]) to decide which internal ACMP output signal or LIRC as timer capture source. + * |[18] |TRGSSEL |Trigger Source Select Bit + * | | |This bit is used to select trigger source is from Timer time-out interrupt signal or capture interrupt signal. + * | | |0 = Timer time-out interrupt signal is used to trigger PWM, ADC and PDMA. + * | | |1 = Capture interrupt signal is used to trigger PWM, ADC and PDMA. + * |[19] |TRGPWM |Trigger PWM Enable Bit + * | | |If this bit is set to 1, timer time-out interrupt or capture interrupt can trigger PWM. + * | | |0 = Timer interrupt trigger PWM Disabled. + * | | |1 = Timer interrupt trigger PWM Enabled. + * | | |Note: If TRGSSEL (TIMERx_CTL[18]) = 0, time-out interrupt signal will trigger PWM. If TRGSSEL (TIMERx_CTL[18]) = 1, capture interrupt signal will trigger PWM. + * |[21] |TRGADC |Trigger ADC Enable Bit + * | | |If this bit is set to 1, timer time-out interrupt or capture interrupt can trigger ADC. + * | | |0 = Timer interrupt trigger ADC Disabled. + * | | |1 = Timer interrupt trigger ADC Enabled. + * | | |Note: If TRGSSEL (TIMERx_CTL[18]) = 0, time-out interrupt signal will trigger ADC. If TRGSSEL (TIMERx_CTL[18]) = 1, capture interrupt signal will trigger ADC. + * |[22] |TGLPINSEL |Toggle-output Pin Select + * | | |0 = Toggle mode output to Tx (Timer Event Counter Pin). + * | | |1 = Toggle mode output to Tx_EXT (Timer External Capture Pin). + * |[23] |WKEN |Wake-up Function Enable Bit + * | | |If this bit is set to 1, while timer interrupt flag TIF (TIMERx_INTSTS[0]) is 1 and INTEN (TIMERx_CTL[29]) is enabled, the timer interrupt signal will generate a wake-up trigger event to CPU. + * | | |0 = Wake-up function Disabled if timer interrupt signal generated. + * | | |1 = Wake-up function Enabled if timer interrupt signal generated. + * |[24] |EXTCNTEN |Event Counter Mode Enable Bit + * | | |This bit is for external counting pin function enabled. + * | | |0 = Event counter mode Disabled. + * | | |1 = Event counter mode Enabled. + * | | |Note1: When timer is used as an event counter, this bit should be set to 1 and select PCLKx (x=0~1) as timer clock source. + * | | |Note2: When TMR0/TMR2 INTRGEN is set to 1, this bit is forced to 1. When INTRGEN is 1 and TMR1/TMR3 CAPIF (TIMERx_EINTSTS[0]) is 1, this bit is forced to 0. + * |[25] |ACTSTS |Timer Active Status Bit (Read Only) + * | | |This bit indicates the 24-bit up counter status. + * | | |0 = 24-bit up counter is not active. + * | | |1 = 24-bit up counter is active. + * | | |Note: This bit may active when CNT 0 transition to CNT 1. + * |[26] |RSTCNT |Timer Counter Reset Bit + * | | |Setting this bit will reset the 24-bit up counter value CNT (TIMERx_CNT[23:0]) and also force CNTEN (TIMERx_CTL[30]) to 0 if ACTSTS (TIMERx_CTL[25]) is 1. + * | | |0 = No effect. + * | | |1 = Reset internal 8-bit prescale counter, 24-bit up counter value and CNTEN bit. + * | | |Note: This bit will be auto cleared. + * |[28:27] |OPMODE |Timer Counting Mode Select + * | | |00 = The timer controller is operated in One-shot mode. + * | | |01 = The timer controller is operated in Periodic mode. + * | | |10 = The timer controller is operated in Toggle-output mode. + * | | |11 = The timer controller is operated in Continuous Counting mode. + * |[29] |INTEN |Timer Interrupt Enable Bit + * | | |0 = Timer time-out interrupt Disabled. + * | | |1 = Timer time-out interrupt Enabled. + * | | |Note: If this bit is enabled, when the timer time-out interrupt flag TIF is set to 1, the timer interrupt signal is generated and inform to CPU. + * |[30] |CNTEN |Timer Counting Enable Bit + * | | |0 = Stops/Suspends counting. + * | | |1 = Starts counting. + * | | |Note1: In stop status, and then set CNTEN to 1 will enable the 24-bit up counter to keep counting from the last stop counting value. + * | | |Note2: This bit is auto-cleared by hardware in one-shot mode (TIMER_CTL[28:27] = 00) when the timer time-out interrupt flag TIF (TIMERx_INTSTS[0]) is generated. + * | | |Note3: Set enable/disable this bit needs 2 * TMR_CLK period to become active, user can read ACTSTS (TIMERx_CTL[25]) to check enable/disable command is completed or not. + * |[31] |ICEDEBUG |ICE Debug Mode Acknowledge Disable Bit (Write Protect) + * | | |0 = ICE debug mode acknowledgement effects TIMER counting. + * | | |TIMER counter will be held while CPU is held by ICE. + * | | |1 = ICE debug mode acknowledgement Disabled. + * | | |TIMER counter will keep going no matter CPU is held by ICE or not. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * @var TIMER_T::CMP + * Offset: 0x04/0x24 Timer0~3 Comparator Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:0] |CMPDAT |Timer Comparator Value + * | | |CMPDAT is a 24-bit compared value register + * | | |When the internal 24-bit up counter value is equal to CMPDAT value, the TIF (TIMERx_INTSTS[0] Timer Interrupt Flag) will set to 1. + * | | |Time-out period = (Period of timer clock input) * (8-bit PSC + 1) * (24-bit CMPDAT). + * | | |Note1: Never write 0x0 or 0x1 in CMPDAT field, or the core will run into unknown state. + * | | |Note2: When timer is operating at continuous counting mode, the 24-bit up counter will keep counting continuously even if user writes a new value into CMPDAT field. But if timer is operating at other modes, the 24-bit up counter will restart counting from 0 and using newest CMPDAT value to be the timer compared value while user writes a new value into CMPDAT field. + * @var TIMER_T::INTSTS + * Offset: 0x08/0x28 Timer0~3 Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |TIF |Timer Interrupt Flag + * | | |This bit indicates the interrupt flag status of Timer while 24-bit timer up counter CNT (TIMERx_CNT[23:0]) value reaches to CMPDAT (TIMERx_CMP[23:0]) value. + * | | |0 = No effect. + * | | |1 = CNT value matches the CMPDAT value. + * | | |Note: This bit is cleared by writing 1 to it. + * |[1] |TWKF |Timer Wake-up Flag + * | | |This bit indicates the interrupt wake-up flag status of timer. + * | | |0 = Timer does not cause CPU wake-up. + * | | |1 = CPU wake-up from Idle or Power-down mode if timer time-out interrupt signal generated. + * | | |Note: This bit is cleared by writing 1 to it. + * @var TIMER_T::CNT + * Offset: 0x0C/0x2C Timer0~3 Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:0] |CNT |Timer Data Register + * | | |Read this register to get CNT value. For example: + * | | |If EXTCNTEN (TIMERx_CTL[24]) is 0, user can read CNT value for getting current 24-bit counter value. + * | | |If EXTCNTEN (TIMERx_CTL[24]) is 1, user can read CNT value for getting current 24-bit event input counter value. + * @var TIMER_T::CAP + * Offset: 0x10/0x30 Timer0~3 Capture Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[23:0] |CAPDAT |Timer Capture Data Register + * | | |When CAPEN (TIMERx_EXTCTL[3]) bit is set, CAPFUNCS (TIMERx_EXTCTL[4]) bit is 0, and a transition on TMx_EXT pin matched the CAPEDGE (TIMERx_EXTCTL[2:1]) setting, CAPIF (TIMERx_EINTSTS[0]) will set to 1 and the current timer counter value CNT (TIMERx_CNT[23:0]) will be auto-loaded into this CAPDAT field. + * @var TIMER_T::EXTCTL + * Offset: 0x14/0x34 Timer0~3 External Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CNTPHASE |Timer External Count Phase + * | | |This bit indicates the detection phase of external counting pin TMx (x= 0~3). + * | | |0 = A falling edge of external counting pin will be counted. + * | | |1 = A rising edge of external counting pin will be counted. + * |[2:1] |CAPEDGE |Timer External Capture Pin Edge Detect + * | | |00 = A Falling edge on Tx_EXT (x= 0~3) pin, LIRC or ACMPx (x=0~1) will be detected. + * | | |01 = A Rising edge on Tx_EXT (x= 0~3) pin, LIRC or ACMPx (x=0~1) will be detected. + * | | |10 = Either Rising or Falling edge on Tx_EXT (x= 0~3) pin, LIRC or ACMPx (x=0~1) will be detected. + * | | |11 = Reserved. + * |[3] |CAPEN |Timer Capture Enable Bit + * | | |This bit enables the capture input function. + * | | |0 =Capture source Disabled. + * | | |1 =Capture source Enabled. + * | | |Note: TMR1/TMR3 CAPEN will be forced to 1 when TMR0/TMR2 INTRGEN is enabled. + * |[4] |CAPFUNCS |Capture Function Selection + * | | |0 = External Capture Mode Enabled. + * | | |1 = External Reset Mode Enabled. + * | | |Note1: When CAPFUNCS is 0, transition on TMx_EXT (x= 0~3) pin is using to save current 24-bit timer counter value (CNT value) to CAPDAT field. + * | | |Note2: When CAPFUNCS is 1, transition on TMx_EXT (x= 0~3) pin is using to save current 24-bit timer counter value (CNT value) to CAPDAT field then CNT value will be reset immediately. + * |[5] |CAPIEN |Timer External Capture Interrupt Enable Bit + * | | |0 = TMx_EXT (x= 0~3) pin, LIRC, or ACMP detection Interrupt Disabled. + * | | |1 = TMx_EXT (x= 0~3) pin, LIRC, or ACMP detection Interrupt Enabled. + * | | |Note: CAPIEN is used to enable timer external interrupt + * | | |If CAPIEN enabled, timer will rise an interrupt when CAPIF (TIMERx_EINTSTS[0]) is 1. + * | | |For example, while CAPIEN = 1, CAPEN = 1, and CAPEDGE = 00, a 1 to 0 transition on the Tx_EXT (x= 0~3) pin, or ACMP will cause the CAPIF to be set then the interrupt signal is generated and sent to NVIC to inform CPU. + * |[6] |CAPDBEN |Timer External Capture Pin De-bounce Enable Bit + * | | |0 = TMx_EXT (x= 0~3) pin de-bounce or ACMP output de-bounce Disabled. + * | | |1 = TMx_EXT (x= 0~3) pin de-bounce or ACMP output de-bounce Enabled. + * | | |Note: If this bit is enabled, the edge detection of TMx_EXT pin or ACMP output is detected with de-bounce circuit. + * |[7] |CNTDBEN |Timer Counter Pin De-bounce Enable Bit + * | | |0 = TMx (x= 0~3) pin de-bounce Disabled. + * | | |1 = TMx (x= 0~3) pin de-bounce Enabled. + * | | |Note: If this bit is enabled, the edge detection of TMx pin is detected with de-bounce circuit. + * |[10:8] |INTERCAPSEL|Internal Capture Source Selection to Trigger Capture Function + * | | |000 = Capture Function source is from internal ACMP0 output signal. + * | | |001 = Capture Function source is from internal ACMP1 output signal. + * | | |101 = Capture Function source is from LIRC. + * | | |Others = Reserved. + * | | |Note: these bits only available when CAPSRC (TIMERx_CTL[16]) is 1. + * |[16] |ECNTSSEL |Event Counter Source Selection to Trigger Event Counter Function + * | | |0 = Event Counter input source is from TMx (x= 0~3) pin. + * | | |1 = Event Counter input source is from USB internal SOF output signal. + * @var TIMER_T::EINTSTS + * Offset: 0x18/0x38 Timer0~3 External Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CAPIF |Timer External Capture Interrupt Flag + * | | |This bit indicates the timer external capture interrupt flag status. + * | | |0 = TMx_EXT (x= 0~3) pin interrupt did not occur. + * | | |1 = TMx_EXT (x= 0~3) pin interrupt occurred. + * | | |Note1: This bit is cleared by writing 1 to it. + * | | |Note2: When CAPEN (TIMERx_EXTCTL[3]) bit is set, CAPFUNCS (TIMERx_EXTCTL[4]) bit is 0, and a transition on Tx_EXT (x= 0~3) pin matched the CAPEDGE (TIMERx_EXTCTL[2:1]) setting, this bit will set to 1 by hardware. + * | | |Note3: There is a new incoming capture event detected before CPU clearing the CAPIF status. If the above condition occurred, the Timer will keep register TIMERx_CAP unchanged and drop the new capture value. + */ + __IO uint32_t CTL; /*!< [0x0000] Timer0 Control Register */ + __IO uint32_t CMP; /*!< [0x0004] Timer0 Comparator Register */ + __IO uint32_t INTSTS; /*!< [0x0008] Timer0 Interrupt Status Register */ + __I uint32_t CNT; /*!< [0x000c] Timer0 Data Register */ + __I uint32_t CAP; /*!< [0x0010] Timer0 Capture Data Register */ + __IO uint32_t EXTCTL; /*!< [0x0014] Timer0 External Control Register */ + __IO uint32_t EINTSTS; /*!< [0x0018] Timer0 External Interrupt Status Register */ +} TIMER_T; + +/** + @addtogroup TIMER_CONST TIMER Bit Field Definition + Constant Definitions for TIMER Controller +@{ */ + +#define TIMER_CTL_PSC_Pos (0) /*!< TIMER_T::CTL: PSC Position */ +#define TIMER_CTL_PSC_Msk (0xfful << TIMER_CTL_PSC_Pos) /*!< TIMER_T::CTL: PSC Mask */ + +#define TIMER_CTL_TRGPDMA_Pos (8) /*!< TIMER_T::CTL: TRGPDMA Position */ +#define TIMER_CTL_TRGPDMA_Msk (0x1ul << TIMER_CTL_TRGPDMA_Pos) /*!< TIMER_T::CTL: TRGPDMA Mask */ + +#define TIMER_CTL_TRGBPWM_Pos (9) /*!< TIMER_T::CTL: TRGBPWM Position */ +#define TIMER_CTL_TRGBPWM_Msk (0x1ul << TIMER_CTL_TRGBPWM_Pos) /*!< TIMER_T::CTL: TRGBPWM Mask */ + +#define TIMER_CTL_INTRGEN_Pos (10) /*!< TIMER_T::CTL: INTRGEN Position */ +#define TIMER_CTL_INTRGEN_Msk (0x1ul << TIMER_CTL_INTRGEN_Pos) /*!< TIMER_T::CTL: INTRGEN Mask */ + +#define TIMER_CTL_CAPSRC_Pos (16) /*!< TIMER_T::CTL: CAPSRC Position */ +#define TIMER_CTL_CAPSRC_Msk (0x1ul << TIMER_CTL_CAPSRC_Pos) /*!< TIMER_T::CTL: CAPSRC Mask */ + +#define TIMER_CTL_TRGSSEL_Pos (18) /*!< TIMER_T::CTL: TRGSSEL Position */ +#define TIMER_CTL_TRGSSEL_Msk (0x1ul << TIMER_CTL_TRGSSEL_Pos) /*!< TIMER_T::CTL: TRGSSEL Mask */ + +#define TIMER_CTL_TRGPWM_Pos (19) /*!< TIMER_T::CTL: TRGPWM Position */ +#define TIMER_CTL_TRGPWM_Msk (0x1ul << TIMER_CTL_TRGPWM_Pos) /*!< TIMER_T::CTL: TRGPWM Mask */ + +#define TIMER_CTL_TRGADC_Pos (21) /*!< TIMER_T::CTL: TRGADC Position */ +#define TIMER_CTL_TRGADC_Msk (0x1ul << TIMER_CTL_TRGADC_Pos) /*!< TIMER_T::CTL: TRGADC Mask */ + +#define TIMER_CTL_TGLPINSEL_Pos (22) /*!< TIMER_T::CTL: TGLPINSEL Position */ +#define TIMER_CTL_TGLPINSEL_Msk (0x1ul << TIMER_CTL_TGLPINSEL_Pos) /*!< TIMER_T::CTL: TGLPINSEL Mask */ + +#define TIMER_CTL_WKEN_Pos (23) /*!< TIMER_T::CTL: WKEN Position */ +#define TIMER_CTL_WKEN_Msk (0x1ul << TIMER_CTL_WKEN_Pos) /*!< TIMER_T::CTL: WKEN Mask */ + +#define TIMER_CTL_EXTCNTEN_Pos (24) /*!< TIMER_T::CTL: EXTCNTEN Position */ +#define TIMER_CTL_EXTCNTEN_Msk (0x1ul << TIMER_CTL_EXTCNTEN_Pos) /*!< TIMER_T::CTL: EXTCNTEN Mask */ + +#define TIMER_CTL_ACTSTS_Pos (25) /*!< TIMER_T::CTL: ACTSTS Position */ +#define TIMER_CTL_ACTSTS_Msk (0x1ul << TIMER_CTL_ACTSTS_Pos) /*!< TIMER_T::CTL: ACTSTS Mask */ + +#define TIMER_CTL_RSTCNT_Pos (26) /*!< TIMER_T::CTL: RSTCNT Position */ +#define TIMER_CTL_RSTCNT_Msk (0x1ul << TIMER_CTL_RSTCNT_Pos) /*!< TIMER_T::CTL: RSTCNT Mask */ + +#define TIMER_CTL_OPMODE_Pos (27) /*!< TIMER_T::CTL: OPMODE Position */ +#define TIMER_CTL_OPMODE_Msk (0x3ul << TIMER_CTL_OPMODE_Pos) /*!< TIMER_T::CTL: OPMODE Mask */ + +#define TIMER_CTL_INTEN_Pos (29) /*!< TIMER_T::CTL: INTEN Position */ +#define TIMER_CTL_INTEN_Msk (0x1ul << TIMER_CTL_INTEN_Pos) /*!< TIMER_T::CTL: INTEN Mask */ + +#define TIMER_CTL_CNTEN_Pos (30) /*!< TIMER_T::CTL: CNTEN Position */ +#define TIMER_CTL_CNTEN_Msk (0x1ul << TIMER_CTL_CNTEN_Pos) /*!< TIMER_T::CTL: CNTEN Mask */ + +#define TIMER_CTL_ICEDEBUG_Pos (31) /*!< TIMER_T::CTL: ICEDEBUG Position */ +#define TIMER_CTL_ICEDEBUG_Msk (0x1ul << TIMER_CTL_ICEDEBUG_Pos) /*!< TIMER_T::CTL: ICEDEBUG Mask */ + +#define TIMER_CMP_CMPDAT_Pos (0) /*!< TIMER_T::CMP: CMPDAT Position */ +#define TIMER_CMP_CMPDAT_Msk (0xfffffful << TIMER_CMP_CMPDAT_Pos) /*!< TIMER_T::CMP: CMPDAT Mask */ + +#define TIMER_INTSTS_TIF_Pos (0) /*!< TIMER_T::INTSTS: TIF Position */ +#define TIMER_INTSTS_TIF_Msk (0x1ul << TIMER_INTSTS_TIF_Pos) /*!< TIMER_T::INTSTS: TIF Mask */ + +#define TIMER_INTSTS_TWKF_Pos (1) /*!< TIMER_T::INTSTS: TWKF Position */ +#define TIMER_INTSTS_TWKF_Msk (0x1ul << TIMER_INTSTS_TWKF_Pos) /*!< TIMER_T::INTSTS: TWKF Mask */ + +#define TIMER_CNT_CNT_Pos (0) /*!< TIMER_T::CNT: CNT Position */ +#define TIMER_CNT_CNT_Msk (0xfffffful << TIMER_CNT_CNT_Pos) /*!< TIMER_T::CNT: CNT Mask */ + +#define TIMER_CAP_CAPDAT_Pos (0) /*!< TIMER_T::CAP: CAPDAT Position */ +#define TIMER_CAP_CAPDAT_Msk (0xfffffful << TIMER_CAP_CAPDAT_Pos) /*!< TIMER_T::CAP: CAPDAT Mask */ + +#define TIMER_EXTCTL_CNTPHASE_Pos (0) /*!< TIMER_T::EXTCTL: CNTPHASE Position */ +#define TIMER_EXTCTL_CNTPHASE_Msk (0x1ul << TIMER_EXTCTL_CNTPHASE_Pos) /*!< TIMER_T::EXTCTL: CNTPHASE Mask */ + +#define TIMER_EXTCTL_CAPEDGE_Pos (1) /*!< TIMER_T::EXTCTL: CAPEDGE Position */ +#define TIMER_EXTCTL_CAPEDGE_Msk (0x3ul << TIMER_EXTCTL_CAPEDGE_Pos) /*!< TIMER_T::EXTCTL: CAPEDGE Mask */ + +#define TIMER_EXTCTL_CAPEN_Pos (3) /*!< TIMER_T::EXTCTL: CAPEN Position */ +#define TIMER_EXTCTL_CAPEN_Msk (0x1ul << TIMER_EXTCTL_CAPEN_Pos) /*!< TIMER_T::EXTCTL: CAPEN Mask */ + +#define TIMER_EXTCTL_CAPFUNCS_Pos (4) /*!< TIMER_T::EXTCTL: CAPFUNCS Position */ +#define TIMER_EXTCTL_CAPFUNCS_Msk (0x1ul << TIMER_EXTCTL_CAPFUNCS_Pos) /*!< TIMER_T::EXTCTL: CAPFUNCS Mask */ + +#define TIMER_EXTCTL_CAPIEN_Pos (5) /*!< TIMER_T::EXTCTL: CAPIEN Position */ +#define TIMER_EXTCTL_CAPIEN_Msk (0x1ul << TIMER_EXTCTL_CAPIEN_Pos) /*!< TIMER_T::EXTCTL: CAPIEN Mask */ + +#define TIMER_EXTCTL_CAPDBEN_Pos (6) /*!< TIMER_T::EXTCTL: CAPDBEN Position */ +#define TIMER_EXTCTL_CAPDBEN_Msk (0x1ul << TIMER_EXTCTL_CAPDBEN_Pos) /*!< TIMER_T::EXTCTL: CAPDBEN Mask */ + +#define TIMER_EXTCTL_CNTDBEN_Pos (7) /*!< TIMER_T::EXTCTL: CNTDBEN Position */ +#define TIMER_EXTCTL_CNTDBEN_Msk (0x1ul << TIMER_EXTCTL_CNTDBEN_Pos) /*!< TIMER_T::EXTCTL: CNTDBEN Mask */ + +#define TIMER_EXTCTL_INTERCAPSEL_Pos (8) /*!< TIMER_T::EXTCTL: INTERCAPSEL Position */ +#define TIMER_EXTCTL_INTERCAPSEL_Msk (0x7ul << TIMER_EXTCTL_INTERCAPSEL_Pos) /*!< TIMER_T::EXTCTL: INTERCAPSEL Mask */ + +#define TIMER_EXTCTL_ECNTSSEL_Pos (16) /*!< TIMER_T::EXTCTL: ECNTSSEL Position */ +#define TIMER_EXTCTL_ECNTSSEL_Msk (0x1ul << TIMER_EXTCTL_ECNTSSEL_Pos) /*!< TIMER_T::EXTCTL: ECNTSSEL Mask */ + +#define TIMER_EINTSTS_CAPIF_Pos (0) /*!< TIMER_T::EINTSTS: CAPIF Position */ +#define TIMER_EINTSTS_CAPIF_Msk (0x1ul << TIMER_EINTSTS_CAPIF_Pos) /*!< TIMER_T::EINTSTS: CAPIF Mask */ + +/**@}*/ /* TIMER_CONST */ +/**@}*/ /* end of TIMER register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __TIMER_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uart_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uart_reg.h new file mode 100644 index 0000000000..256a2950a8 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uart_reg.h @@ -0,0 +1,1085 @@ +/**************************************************************************//** + * @file uart_reg.h + * @version V1.00 + * @brief UART register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __UART_REG_H__ +#define __UART_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup UART Universal Asynchronous Receiver/Transmitter Controller(UART) + Memory Mapped Structure for UART Controller +@{ */ + +typedef struct +{ + + + /** + * @var UART_T::DAT + * Offset: 0x00 UART Receive/Transmit Buffer Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |DAT |Data Receive/Transmit Buffer + * | | |Write Operation: + * | | |By writing one byte to this register, the data byte will be stored in transmitter FIFO. + * | | |The UART controller will send out the data stored in transmitter FIFO top location through the UART_TXD. + * | | |Read Operation: + * | | |By reading this register, the UART controller will return an 8-bit data received from receiver FIFO. + * |[8] |PARITY |Parity Bit Receive/Transmit Buffer + * | | |Write Operation: + * | | |By writing to this bit, the parity bit will be stored in transmitter FIFO. + * | | |If PBE (UART_LINE[3]) and PSS (UART_LINE[7]) are set, the UART controller will send out this bit follow the DAT (UART_DAT[7:0]) through the UART_TXD. + * | | |Read Operation: + * | | |If PBE (UART_LINE[3]) and PSS (UART_LINE[7]) are enabled, the parity bit can be read by this bit. + * | | |Note: This bit has effect only when PBE (UART_LINE[3]) and PSS (UART_LINE[7]) are set. + * @var UART_T::INTEN + * Offset: 0x04 UART Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RDAIEN |Receive Data Available Interrupt Enable Bit + * | | |0 = Receive data available interrupt Disabled. + * | | |1 = Receive data available interrupt Enabled. + * |[1] |THREIEN |Transmit Holding Register Empty Interrupt Enable Bit + * | | |0 = Transmit holding register empty interrupt Disabled. + * | | |1 = Transmit holding register empty interrupt Enabled. + * |[2] |RLSIEN |Receive Line Status Interrupt Enable Bit + * | | |0 = Receive Line Status interrupt Disabled. + * | | |1 = Receive Line Status interrupt Enabled. + * |[3] |MODEMIEN |Modem Status Interrupt Enable Bit + * | | |0 = Modem status interrupt Disabled. + * | | |1 = Modem status interrupt Enabled. + * |[4] |RXTOIEN |RX Time-out Interrupt Enable Bit + * | | |0 = RX time-out interrupt Disabled. + * | | |1 = RX time-out interrupt Enabled. + * |[5] |BUFERRIEN |Buffer Error Interrupt Enable Bit + * | | |0 = Buffer error interrupt Disabled. + * | | |1 = Buffer error interrupt Enabled. + * |[6] |WKIEN |Wake-up Interrupt Enable Bit + * | | |0 = Wake-up Interrupt Disabled. + * | | |1 = Wake-up Interrupt Enabled. + * |[11] |TOCNTEN |Receive Buffer Time-out Counter Enable Bit + * | | |0 = Receive Buffer Time-out counter Disabled. + * | | |1 = Receive Buffer Time-out counter Enabled. + * |[12] |ATORTSEN |nRTS Auto-flow Control Enable Bit + * | | |0 = nRTS auto-flow control Disabled. + * | | |1 = nRTS auto-flow control Enabled. + * | | |Note: When nRTS auto-flow is enabled, if the number of bytes in the RX FIFO equals the RTSTRGLV (UART_FIFO[19:16]), the UART will de-assert nRTS signal. + * |[13] |ATOCTSEN |nCTS Auto-flow Control Enable Bit + * | | |0 = nCTS auto-flow control Disabled. + * | | |1 = nCTS auto-flow control Enabled. + * | | |Note: When nCTS auto-flow is enabled, the UART will send data to external device if nCTS input assert (UART will not send data to device until nCTS is asserted). + * |[14] |TXPDMAEN |TX PDMA Enable Bit + * | | |0 = TX PDMA Disabled. + * | | |1 = TX PDMA Enabled. + * | | |Note: If RLSIEN (UART_INTEN[2]) is enabled and HWRLSINT (UART_INTSTS[26]) is set to 1, the RLS (Receive Line Status) Interrupt is caused. + * | | |If RLS interrupt is caused by Break Error Flag BIF(UART_FIFOSTS[6]), Frame Error Flag FEF(UART_FIFO[5]) or Parity Error Flag PEF(UART_FIFOSTS[4]), UART PDMA transmit request operation is stopped. + * | | |Clear Break Error Flag BIF or Frame Error Flag FEF or Parity Error Flag PEF by writing "1" to corresponding BIF, FEF and PEF to make UART PDMA transmit request operation continue. + * |[15] |RXPDMAEN |RX PDMA Enable Bit + * | | |This bit can enable or disable RX PDMA service. + * | | |0 = RX PDMA Disabled. + * | | |1 = RX PDMA Enabled. + * | | |Note: If RLSIEN (UART_INTEN[2]) is enabled and HWRLSINT (UART_INTSTS[26]) is set to 1, the RLS (Receive Line Status) Interrupt is caused. + * | | |If RLS interrupt is caused by Break Error Flag BIF(UART_FIFOSTS[6]), Frame Error Flag FEF(UART_FIFO[5]) or Parity Error Flag PEF(UART_FIFOSTS[4]), UART PDMA receive request operation is stopped. + * | | |Clear Break Error Flag BIF or Frame Error Flag FEF or Parity Error Flag PEF by writing "1" to corresponding BIF, FEF and PEF to make UART PDMA receive request operation continue. + * |[16] |SWBEIEN |Single-wire Bit Error Detection Interrupt Enable Bit + * | | |Set this bit, the Single-wire Half Duplex Bit Error Detection Interrupt SWBEINT(UART_INTSTS[24]) is generated when Single-wire Bit Error Detection SWBEIF(UART_INTSTS[16]) is set. + * | | |0 = Single-wire Bit Error Detect Inerrupt Disabled. + * | | |1 = Single-wire Bit Error Detect Inerrupt Enabled. + * | | |Note: This bit is valid when FUNCSEL (UART_FUNCSEL[2:0]) is select UART Single-wire mode. + * |[18] |ABRIEN |Auto-baud Rate Interrupt Enable Bit + * | | |0 = Auto-baud rate interrupt Disabled. + * | | |1 = Auto-baud rate interrupt Enabled. + * |[22] |TXENDIEN |Transmitter Empty Interrupt Enable Bit + * | | |If TXENDIEN (UART_INTEN[22]) is enabled, the Transmitter Empty interrupt TXENDINT (UART_INTSTS[30]) will be generated when TXENDIF (UART_INTSTS[22]) is set (TX FIFO (UART_DAT) is empty and the STOP bit of the last byte has been transmitted). + * | | |0 = Transmitter empty interrupt Disabled. + * | | |1 = Transmitter empty interrupt Enabled. + * @var UART_T::FIFO + * Offset: 0x08 UART FIFO Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |RXRST |RX Field Software Reset + * | | |When RXRST (UART_FIFO[1]) is set, all the byte in the receiver FIFO and RX internal state machine are cleared. + * | | |0 = No effect. + * | | |1 = Reset the RX internal state machine and pointers. + * | | |Note1: This bit will automatically clear at least 3 UART peripheral clock cycles. + * | | |Note2: Before setting this bit, it should wait for the RXIDLE (UART_FIFOSTS[29]) be set. + * |[2] |TXRST |TX Field Software Reset + * | | |When TXRST (UART_FIFO[2]) is set, all the byte in the transmit FIFO and TX internal state machine are cleared. + * | | |0 = No effect. + * | | |1 = Reset the TX internal state machine and pointers. + * | | |Note1: This bit will automatically clear at least 3 UART peripheral clock cycles. + * | | |Note2: Before setting this bit, it should wait for the TXEMPTYF (UART_FIFOSTS[28]) be set. + * |[7:4] |RFITL |RX FIFO Interrupt Trigger Level + * | | |When the number of bytes in the receive FIFO equals the RFITL, the RDAIF (UART_INTSTS[0]) will be set (if RDAIEN (UART_INTEN [0]) enabled, and an interrupt will be generated). + * | | |0000 = RX FIFO Interrupt Trigger Level is 1 byte. + * | | |0001 = RX FIFO Interrupt Trigger Level is 4 bytes. + * | | |0010 = RX FIFO Interrupt Trigger Level is 8 bytes. + * | | |0011 = RX FIFO Interrupt Trigger Level is 14 bytes. + * | | |Others = Reserved. + * |[8] |RXOFF |Receiver Disable Bit + * | | |The receiver is disabled or not (set 1 to disable receiver). + * | | |0 = Receiver Enabled. + * | | |1 = Receiver Disabled. + * | | |Note: This bit is used for RS-485 Normal Multi-drop mode. + * | | |It should be programmed before RS485NMM (UART_ALTCTL [8]) is programmed. + * |[19:16] |RTSTRGLV |nRTS Trigger Level for Auto-flow Control + * | | |0000 = nRTS Trigger Level is 1 byte. + * | | |0001 = nRTS Trigger Level is 4 bytes. + * | | |0010 = nRTS Trigger Level is 8 bytes. + * | | |0011 = nRTS Trigger Level is 14 bytes. + * | | |Others = Reserved. + * | | |Note: This field is used for auto nRTS flow control. + * @var UART_T::LINE + * Offset: 0x0C UART Line Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |WLS |Word Length Selection + * | | |This field sets UART word length. + * | | |00 = 5 bits. + * | | |01 = 6 bits. + * | | |10 = 7 bits. + * | | |11 = 8 bits. + * |[2] |NSB |Number of "STOP Bit" + * | | |0 = One "STOP bit" is generated in the transmitted data. + * | | |1 = When select 5-bit word length, 1.5 "STOP bit" is generated in the transmitted data. + * | | |When select 6-, 7- and 8-bit word length, 2 "STOP bit" is generated in the transmitted data. + * |[3] |PBE |Parity Bit Enable Bit + * | | |0 = Parity bit generated Disabled. + * | | |1 = Parity bit generated Enabled. + * | | |Note: Parity bit is generated on each outgoing character and is checked on each incoming data. + * |[4] |EPE |Even Parity Enable Bit + * | | |0 = Odd number of logic 1's is transmitted and checked in each word. + * | | |1 = Even number of logic 1's is transmitted and checked in each word. + * | | |Note: This bit has effect only when PBE (UART_LINE[3]) is set. + * |[5] |SPE |Stick Parity Enable Bit + * | | |0 = Stick parity Disabled. + * | | |1 = Stick parity Enabled. + * | | |Note: If PBE (UART_LINE[3]) and EPE (UART_LINE[4]) are logic 1, the parity bit is transmitted and checked as logic 0 + * | | |If PBE (UART_LINE[3]) is 1 and EPE (UART_LINE[4]) is 0 then the parity bit is transmitted and checked as 1. + * |[6] |BCB |Break Control Bit + * | | |0 = Break Control Disabled. + * | | |1 = Break Control Enabled. + * | | |Note: When this bit is set to logic 1, the transmitted serial data output (TX) is forced to the Spacing State (logic 0) + * | | |This bit acts only on TX line and has no effect on the transmitter logic. + * |[7] |PSS |Parity Bit Source Selection + * | | |The parity bit can be selected to be generated and checked automatically or by software. + * | | |0 = Parity bit is generated by EPE (UART_LINE[4]) and SPE (UART_LINE[5]) setting and checked automatically. + * | | |1 = Parity bit generated and checked by software. + * | | |Note1: This bit has effect only when PBE (UART_LINE[3]) is set. + * | | |Note2: If PSS is 0, the parity bit is transmitted and checked automatically + * | | |If PSS is 1, the transmitted parity bit value can be determined by writing PARITY (UART_DAT[8]) and the parity bit can be read by reading PARITY (UART_DAT[8]). + * |[8] |TXDINV |TX Data Inverted + * | | |0 = Transmitted data signal inverted Disabled. + * | | |1 = Transmitted data signal inverted Enabled. + * | | |Note1: Before setting this bit, TXRXDIS (UART_FUNCSEL[3]) should be set then waited for TXRXACT (UART_FIFOSTS[31]) is cleared + * | | |When the configuration is done, cleared TXRXDIS (UART_FUNCSEL[3]) to activate UART controller. + * | | |Note2: This bit is valid when FUNCSEL (UART_FUNCSEL[1:0]) is select UART, LIN or RS485 function. + * |[9] |RXDINV |RX Data Inverted + * | | |0 = Received data signal inverted Disabled. + * | | |1 = Received data signal inverted Enabled. + * | | |Note1: Before setting this bit, TXRXDIS (UART_FUNCSEL[3]) should be set then waited for TXRXACT (UART_FIFOSTS[31]) is cleared. + * | | |When the configuration is done, cleared TXRXDIS (UART_FUNCSEL[3]) to activate UART controller. + * | | |Note2: This bit is valid when FUNCSEL (UART_FUNCSEL[1:0]) is select UART, LIN or RS485 function. + * @var UART_T::MODEM + * Offset: 0x10 UART Modem Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |RTS |nRTS (Request-to-send) Signal Control + * | | |This bit is direct control internal nRTS signal active or not, and then drive the nRTS pin output with RTSACTLV bit configuration. + * | | |0 = nRTS signal is active. + * | | |1 = nRTS signal is inactive. + * | | |Note1: The nRTS signal control bit is not effective when nRTS auto-flow control is enabled in UART function mode. + * | | |Note2: The nRTS signal control bit is not effective when RS-485 auto direction mode (AUD) is enabled in RS-485 function mode. + * | | |Note3: Single-wire mode is support this feature. + * |[9] |RTSACTLV |nRTS Pin Active Level + * | | |This bit defines the active level state of nRTS pin output. + * | | |0 = nRTS pin output is high level active. + * | | |1 = nRTS pin output is low level active. (Default). + * | | |Note1: Refer to Figure 7.11-13 and Figure 7.11-14 for UART function mode. + * | | |Note2: Refer to Figure 7.11-24 and Figure 7.11-25 for RS-485 function mode. + * | | |Note3: Before setting this bit, TXRXDIS (UART_FUNCSEL[3]) should be set then waited for TXRXACT (UART_FIFOSTS[31]) is cleared. + * | | |When the configuration is done, cleared TXRXDIS (UART_FUNCSEL[3]) to activate UART controller. + * |[13] |RTSSTS |nRTS Pin Status (Read Only) + * | | |This bit mirror from nRTS pin output of voltage logic status. + * | | |0 = nRTS pin output is low level voltage logic state. + * | | |1 = nRTS pin output is high level voltage logic state. + * @var UART_T::MODEMSTS + * Offset: 0x14 UART Modem Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CTSDETF |Detect nCTS State Change Flag + * | | |This bit is set whenever nCTS input has change state, and it will generate Modem interrupt to CPU when MODEMIEN (UART_INTEN [3]) is set to 1. + * | | |0 = nCTS input has not change state. + * | | |1 = nCTS input has change state. + * | | |Note: This bit can be cleared by writing "1" to it. + * |[4] |CTSSTS |nCTS Pin Status (Read Only) + * | | |This bit mirror from nCTS pin input of voltage logic status. + * | | |0 = nCTS pin input is low level voltage logic state. + * | | |1 = nCTS pin input is high level voltage logic state. + * | | |Note: This bit echoes when UART controller peripheral clock is enabled, and nCTS multi-function port is selected. + * |[8] |CTSACTLV |nCTS Pin Active Level + * | | |This bit defines the active level state of nCTS pin input. + * | | |0 = nCTS pin input is high level active. + * | | |1 = nCTS pin input is low level active. (Default). + * | | |Note: Before setting this bit, TXRXDIS (UART_FUNCSEL[3]) should be set then waited for TXRXACT (UART_FIFOSTS[31]) is cleared. + * | | |When the configuration is done, cleared TXRXDIS (UART_FUNCSEL[3]) to activate UART controller. + * @var UART_T::FIFOSTS + * Offset: 0x18 UART FIFO Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RXOVIF |RX Overflow Error Interrupt Flag + * | | |This bit is set when RX FIFO overflow. + * | | |If the number of bytes of received data is greater than RX_FIFO (UART_DAT) size 16 bytes, this bit will be set. + * | | |0 = RX FIFO is not overflow. + * | | |1 = RX FIFO is overflow. + * | | |Note: This bit can be cleared by writing "1" to it. + * |[1] |ABRDIF |Auto-baud Rate Detect Interrupt Flag + * | | |This bit is set to logic "1" when Auto-baud Rate detect function is finished. + * | | |0 = Auto-baud rate detect function is not finished. + * | | |1 = Auto-baud rate detect function is finished. + * | | |Note: This bit can be cleared by writing "1" to it. + * |[2] |ABRDTOIF |Auto-baud Rate Detect Time-out Interrupt Flag + * | | |This bit is set to logic "1" in Auto-baud Rate Detect mode when the baud rate counter is overflow. + * | | |0 = Auto-baud rate counter is underflow. + * | | |1 = Auto-baud rate counter is overflow. + * | | |Note: This bit can be cleared by writing "1" to it. + * |[3] |ADDRDETF |RS-485 Address Byte Detect Flag + * | | |0 = Receiver detects a data that is not an address bit (bit 9 ="0"). + * | | |1 = Receiver detects a data that is an address bit (bit 9 ="1"). + * | | |Note1: This field is used for RS-485 function mode and ADDRDEN (UART_ALTCTL[15]) is set to 1 to enable Address detection mode. + * | | |Note2: This bit can be cleared by writing "1" to it. + * |[4] |PEF |Parity Error Flag + * | | |This bit is set to logic 1 whenever the received character does not have a valid "parity bit". + * | | |0 = No parity error is generated. + * | | |1 = Parity error is generated. + * | | |Note: This bit can be cleared by writing "1" to it. + * |[5] |FEF |Framing Error Flag + * | | |This bit is set to logic 1 whenever the received character does not have a valid "stop bit" (that is, the stop bit following the last data bit or parity bit is detected as logic 0). + * | | |0 = No framing error is generated. + * | | |1 = Framing error is generated. + * | | |Note: This bit can be cleared by writing "1" to it. + * |[6] |BIF |Break Interrupt Flag + * | | |This bit is set to logic 1 whenever the received data input (RX) is held in the "spacing state" (logic 0) for longer than a full word transmission time (that is, the total time of "start bit" + data bits + parity + stop bits). + * | | |0 = No Break interrupt is generated. + * | | |1 = Break interrupt is generated. + * | | |Note: This bit can be cleared by writing "1" to it. + * |[13:8] |RXPTR |RX FIFO Pointer (Read Only) + * | | |This field indicates the RX FIFO Buffer Pointer + * | | |When UART receives one byte from external device, RXPTR increases one. + * | | |When one byte of RX FIFO is read by CPU, RXPTR decreases one. + * | | |The Maximum value shown in RXPTR is 15. + * | | |When the using level of RX FIFO Buffer equal to 16, the RXFULL bit is set to 1 and RXPTR will show 0. + * | | |As one byte of RX FIFO is read by CPU, the RXFULL bit is cleared to 0 and RXPTR will show 15. + * |[14] |RXEMPTY |Receiver FIFO Empty (Read Only) + * | | |This bit initiate RX FIFO empty or not. + * | | |0 = RX FIFO is not empty. + * | | |1 = RX FIFO is empty. + * | | |Note: When the last byte of RX FIFO has been read by CPU, hardware sets this bit high. + * | | |It will be cleared when UART receives any new data. + * |[15] |RXFULL |Receiver FIFO Full (Read Only) + * | | |This bit initiates RX FIFO full or not. + * | | |0 = RX FIFO is not full. + * | | |1 = RX FIFO is full. + * | | |Note: This bit is set when the number of usage in RX FIFO Buffer is equal to 16, otherwise it is cleared by hardware. + * |[21:16] |TXPTR |TX FIFO Pointer (Read Only) + * | | |This field indicates the TX FIFO Buffer Pointer. + * | | |When CPU writes one byte into UART_DAT, TXPTR increases one. + * | | |When one byte of TX FIFO is transferred to Transmitter Shift Register, TXPTR decreases one. + * | | |The Maximum value shown in TXPTR is 15 + * | | |When the using level of TX FIFO Buffer equal to 16, the TXFULL bit is set to 1 and TXPTR will show 0. + * | | |As one byte of TX FIFO is transferred to Transmitter Shift Register, the TXFULL bit is cleared to 0 and TXPTR will show 15. + * |[22] |TXEMPTY |Transmitter FIFO Empty (Read Only) + * | | |This bit indicates TX FIFO empty or not. + * | | |0 = TX FIFO is not empty. + * | | |1 = TX FIFO is empty. + * | | |Note: When the last byte of TX FIFO has been transferred to Transmitter Shift Register, hardware sets this bit high. + * | | |It will be cleared when writing data into UART_DAT (TX FIFO not empty). + * |[23] |TXFULL |Transmitter FIFO Full (Read Only) + * | | |This bit indicates TX FIFO full or not. + * | | |0 = TX FIFO is not full. + * | | |1 = TX FIFO is full. + * | | |Note: This bit is set when the number of usage in TX FIFO Buffer is equal to 16, otherwise it is cleared by hardware. + * |[24] |TXOVIF |TX Overflow Error Interrupt Flag + * | | |If TX FIFO (UART_DAT) is full, an additional write to UART_DAT will cause this bit to logic 1. + * | | |0 = TX FIFO is not overflow. + * | | |1 = TX FIFO is overflow. + * | | |Note: This bit can be cleared by writing "1" to it. + * |[28] |TXEMPTYF |Transmitter Empty Flag (Read Only) + * | | |This bit is set by hardware when TX FIFO (UART_DAT) is empty and the STOP bit of the last byte has been transmitted. + * | | |0 = TX FIFO is not empty or the STOP bit of the last byte has been not transmitted. + * | | |1 = TX FIFO is empty and the STOP bit of the last byte has been transmitted. + * | | |Note: This bit is cleared automatically when TX FIFO is not empty or the last byte transmission has not completed. + * |[29] |RXIDLE |RX Idle Status (Read Only) + * | | |This bit is set by hardware when RX is idle. + * | | |0 = RX is busy. + * | | |1 = RX is idle. (Default) + * |[31] |TXRXACT |TX and RX Active Status (Read Only) + * | | |This bit indicates TX and RX are active or inactive. + * | | |0 = TX and RX are inactive. + * | | |1 = TX and RX are active. (Default) + * | | |Note: When TXRXDIS (UART_FUNCSEL[3]) is set and both TX and RX are in idle state, this bit is cleared. + * | | |The UART controller can not transmit or receive data at this moment. + * | | |Otherwise this bit is set. + * @var UART_T::INTSTS + * Offset: 0x1C UART Interrupt Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RDAIF |Receive Data Available Interrupt Flag + * | | |When the number of bytes in the RX FIFO equals the RFITL then the RDAIF(UART_INTSTS[0]) will be set. + * | | |If RDAIEN (UART_INTEN [0]) is enabled, the RDA interrupt will be generated. + * | | |0 = No RDA interrupt flag is generated. + * | | |1 = RDA interrupt flag is generated. + * | | |Note: This bit is read only and it will be cleared when the number of unread bytes of RX FIFO drops below the threshold level (RFITL(UART_FIFO[7:4]). + * |[1] |THREIF |Transmit Holding Register Empty Interrupt Flag + * | | |This bit is set when the last data of TX FIFO is transferred to Transmitter Shift Register. + * | | |If THREIEN (UART_INTEN[1]) is enabled, the THRE interrupt will be generated. + * | | |0 = No THRE interrupt flag is generated. + * | | |1 = THRE interrupt flag is generated. + * | | |Note: This bit is read only and it will be cleared when writing data into UART_DAT (TX FIFO not empty). + * |[2] |RLSIF |Receive Line Interrupt Flag (Read Only) + * | | |This bit is set when the RX receive data have parity error, frame error or break error (at least one of 3 bits, BIF(UART_FIFOSTS[6]), FEF(UART_FIFOSTS[5]) and PEF(UART_FIFOSTS[4]), is set). + * | | |If RLSIEN (UART_INTEN [2]) is enabled, the RLS interrupt will be generated. + * | | |0 = No RLS interrupt flag is generated. + * | | |1 = RLS interrupt flag is generated. + * | | |Note1: In RS-485 function mode, this field is set include "receiver detect and received address byte character (bit9 = "1") bit". + * | | |At the same time, the bit of ADDRDETF (UART_FIFOSTS[3]) is also set. + * | | |Note2: This bit is read only and reset to 0 when all bits of BIF (UART_FIFOSTS[6]), FEF(UART_FIFOSTS[5]) and PEF(UART_FIFOSTS[4]) are cleared. + * | | |Note3: In RS-485 function mode, this bit is read only and reset to 0 when all bits of BIF (UART_FIFOSTS[6]), FEF(UART_FIFOSTS[5]), PEF(UART_FIFOSTS[4]) and ADDRDETF (UART_FIFOSTS[3]) are cleared. + * |[3] |MODEMIF |MODEM Interrupt Flag (Read Only) + * | | |This bit is set when the nCTS pin has state change (CTSDETF (UART_MODEMSTS[0]) = 1). + * | | |If MODEMIEN (UART_INTEN [3]) is enabled, the Modem interrupt will be generated. + * | | |0 = No Modem interrupt flag is generated. + * | | |1 = Modem interrupt flag is generated. + * | | |Note: This bit is read only and reset to 0 when bit CTSDETF is cleared by a write 1 on CTSDETF(UART_MODEMSTS[0]). + * |[4] |RXTOIF |RX Time-out Interrupt Flag (Read Only) + * | | |This bit is set when the RX FIFO is not empty and no activities occurred in the RX FIFO and the time-out counter equal to TOIC (UART_TOUT[7:0]) + * | | |If RXTOIEN (UART_INTEN [4]) is enabled, the RX time-out interrupt will be generated. + * | | |0 = No RX time-out interrupt flag is generated. + * | | |1 = RX time-out interrupt flag is generated. + * | | |Note: This bit is read only and user can read UART_DAT (RX is in active) to clear it. + * |[5] |BUFERRIF |Buffer Error Interrupt Flag (Read Only) + * | | |This bit is set when the TX FIFO or RX FIFO overflows (TXOVIF (UART_FIFOSTS[24]) or RXOVIF (UART_FIFOSTS[0]) is set). + * | | |When BUFERRIF (UART_INTSTS[5]) is set, the transfer is not correct. + * | | |If BUFERRIEN (UART_INTEN [5]) is enabled, the buffer error interrupt will be generated. + * | | |0 = No buffer error interrupt flag is generated. + * | | |1 = Buffer error interrupt flag is generated. + * | | |Note: This bit is cleared if both of RXOVIF(UART_FIFOSTS[0]) and TXOVIF(UART_FIFOSTS[24]) are cleared to 0 by writing 1 to RXOVIF(UART_FIFOSTS[0]) and TXOVIF(UART_FIFOSTS[24]). + * |[6] |WKIF |UART Wake-up Interrupt Flag (Read Only) + * | | |This bit is set when TOUTWKF (UART_WKSTS[4]), RS485WKF (UART_WKSTS[3]), RFRTWKF (UART_WKSTS[2]), DATWKF (UART_WKSTS[1]) or CTSWKF(UART_WKSTS[0]) is set to 1. + * | | |0 = No UART wake-up interrupt flag is generated. + * | | |1 = UART wake-up interrupt flag is generated. + * | | |Note: This bit is cleared if all of TOUTWKF, RS485WKF, RFRTWKF, DATWKF and CTSWKF are cleared to 0 by writing 1 to the corresponding interrupt flag. + * |[8] |RDAINT |Receive Data Available Interrupt Indicator (Read Only) + * | | |This bit is set if RDAIEN (UART_INTEN[0]) and RDAIF (UART_INTSTS[0]) are both set to 1. + * | | |0 = No RDA interrupt is generated. + * | | |1 = RDA interrupt is generated. + * |[9] |THREINT |Transmit Holding Register Empty Interrupt Indicator (Read Only) + * | | |This bit is set if THREIEN (UART_INTEN[1]) and THREIF(UART_INTSTS[1]) are both set to 1. + * | | |0 = No THRE interrupt is generated. + * | | |1 = THRE interrupt is generated. + * |[10] |RLSINT |Receive Line Status Interrupt Indicator (Read Only) + * | | |This bit is set if RLSIEN (UART_INTEN[2]) and RLSIF(UART_INTSTS[2]) are both set to 1. + * | | |0 = No RLS interrupt is generated. + * | | |1 = RLS interrupt is generated. + * |[11] |MODEMINT |MODEM Status Interrupt Indicator (Read Only) + * | | |This bit is set if MODEMIEN(UART_INTEN[3]) and MODEMIF(UART_INTSTS[3]) are both set to 1. + * | | |0 = No Modem interrupt is generated. + * | | |1 = Modem interrupt is generated. + * |[12] |RXTOINT |RX Time-out Interrupt Indicator (Read Only) + * | | |This bit is set if RXTOIEN (UART_INTEN[4]) and RXTOIF(UART_INTSTS[4]) are both set to 1. + * | | |0 = No RX time-out interrupt is generated. + * | | |1 = RX time-out interrupt is generated. + * |[13] |BUFERRINT |Buffer Error Interrupt Indicator (Read Only) + * | | |This bit is set if BUFERRIEN(UART_INTEN[5]) and BUFERRIF(UART_ INTSTS[5]) are both set to 1. + * | | |0 = No buffer error interrupt is generated. + * | | |1 = Buffer error interrupt is generated. + * |[14] |WKINT |UART Wake-up Interrupt Indicator (Read Only) + * | | |This bit is set if WKIEN (UART_INTEN[6]) and WKIF (UART_INTSTS[6]) are both set to 1. + * | | |0 = No UART wake-up interrupt is generated. + * | | |1 = UART wake-up interrupt is generated. + * |[16] |SWBEIF |Single-wire Bit Error Detection Interrupt Flag + * | | |This bit is set when the single wire bus state not equals to UART controller TX state in Single-wire mode. + * | | |0 = No single-wire bit error detection interrupt flag is generated. + * | | |1 = Single-wire bit error detection interrupt flag is generated. + * | | |Note1: This bit is active when FUNCSEL (UART_FUNCSEL[2:0]) is select UART Single-wire mode. + * | | |Note2: This bit can be cleared by writing "1" to it. + * |[18] |HWRLSIF |PDMA Mode Receive Line Status Flag (Read Only) + * | | |This bit is set when the RX receive data have parity error, frame error or break error (at least one of 3 bits, BIF (UART_FIFOSTS[6]), FEF (UART_FIFOSTS[5]) and PEF (UART_FIFOSTS[4]) is set). + * | | |If RLSIEN (UART_INTEN [2]) is enabled, the RLS interrupt will be generated. + * | | |0 = No RLS interrupt flag is generated in PDMA mode. + * | | |1 = RLS interrupt flag is generated in PDMA mode. + * | | |Note1: In RS-485 function mode, this field include "receiver detect any address byte received address byte character (bit9 = "1") bit". + * | | |Note2: In UART function mode, this bit is read only and reset to 0 when all bits of BIF(UART_FIFOSTS[6]), FEF(UART_FIFOSTS[5]) and PEF(UART_FIFOSTS[4]) are cleared. + * | | |Note3: In RS-485 function mode, this bit is read only and reset to 0 when all bits of BIF(UART_FIFOSTS[6]), FEF(UART_FIFOSTS[5]), PEF(UART_FIFOSTS[4]) and ADDRDETF (UART_FIFOSTS[3]) are cleared. + * |[19] |HWMODIF |PDMA Mode MODEM Interrupt Flag (Read Only) + * | | |This bit is set when the nCTS pin has state change (CTSDETF (UART_MODEMSTS [0] =1)). + * | | |If MODEMIEN (UART_INTEN [3]) is enabled, the Modem interrupt will be generated. + * | | |0 = No Modem interrupt flag is generated in PDMA mode. + * | | |1 = Modem interrupt flag is generated in PDMA mode. + * | | |Note: This bit is read only and reset to 0 when the bit CTSDETF (UART_MODEMSTS[0]) is cleared by writing 1 on CTSDETF (UART_MODEMSTS [0]). + * |[20] |HWTOIF |PDMA Mode RX Time-out Interrupt Flag (Read Only) + * | | |This bit is set when the RX FIFO is not empty and no activities occurred in the RX FIFO and the time-out counter equal to TOIC (UART_TOUT[7:0]) + * | | |If RXTOIEN (UART_INTEN [4]) is enabled, the RX time-out interrupt will be generated . + * | | |0 = No RX time-out interrupt flag is generated in PDMA mode. + * | | |1 = RX time-out interrupt flag is generated in PDMA mode. + * | | |Note: This bit is read only and user can read UART_DAT (RX is in active) to clear it. + * |[21] |HWBUFEIF |PDMA Mode Buffer Error Interrupt Flag (Read Only) + * | | |This bit is set when the TX or RX FIFO overflows (TXOVIF (UART_FIFOSTS [24]) or RXOVIF (UART_FIFOSTS[0]) is set). + * | | |When BUFERRIF (UART_INTSTS[5]) is set, the transfer maybe is not correct. + * | | |If BUFERRIEN (UART_INTEN [5]) is enabled, the buffer error interrupt will be generated. + * | | |0 = No buffer error interrupt flag is generated in PDMA mode. + * | | |1 = Buffer error interrupt flag is generated in PDMA mode. + * | | |Note: This bit is cleared when both TXOVIF (UART_FIFOSTS[24]]) and RXOVIF (UART_FIFOSTS[0]) are cleared. + * |[22] |TXENDIF |Transmitter Empty Interrupt Flag + * | | |This bit is set when TX FIFO (UART_DAT) is empty and the STOP bit of the last byte has been transmitted (TXEMPTYF (UART_FIFOSTS[28]) is set). + * | | |If TXENDIEN (UART_INTEN[22]) is enabled, the Transmitter Empty interrupt will be generated. + * | | |0 = No transmitter empty interrupt flag is generated. + * | | |1 = Transmitter empty interrupt flag is generated. + * | | |Note: This bit is cleared automatically when TX FIFO is not empty or the last byte transmission has not completed. + * |[24] |SWBEINT |Single-wire Bit Error Detect Interrupt Indicator (Read Only) + * | | |This bit is set if SWBEIEN (UART_INTEN[16]) and SWBEIF (UART_INTSTS[16]) are both set to 1. + * | | |0 = No Single-wire Bit Error Detection Interrupt generated. + * | | |1 = Single-wire Bit Error Detection Interrupt generated. + * |[26] |HWRLSINT |PDMA Mode Receive Line Status Interrupt Indicator (Read Only) + * | | |This bit is set if RLSIEN (UART_INTEN[2]) and HWRLSIF(UART_INTSTS[18]) are both set to 1. + * | | |0 = No RLS interrupt is generated in PDMA mode. + * | | |1 = RLS interrupt is generated in PDMA mode. + * |[27] |HWMODINT |PDMA Mode MODEM Status Interrupt Indicator (Read Only) + * | | |This bit is set if MODEMIEN (UART_INTEN[3]) and HWMODIF(UART_INTSTS[19]) are both set to 1. + * | | |0 = No Modem interrupt is generated in PDMA mode. + * | | |1 = Modem interrupt is generated in PDMA mode. + * |[28] |HWTOINT |PDMA Mode RX Time-out Interrupt Indicator (Read Only) + * | | |This bit is set if RXTOIEN (UART_INTEN[4]) and HWTOIF(UART_INTSTS[20]) are both set to 1. + * | | |0 = No RX time-out interrupt is generated in PDMA mode. + * | | |1 = RX time-out interrupt is generated in PDMA mode. + * |[29] |HWBUFEINT |PDMA Mode Buffer Error Interrupt Indicator (Read Only) + * | | |This bit is set if BUFERRIEN (UART_INTEN[5]) and HWBUFEIF (UART_INTSTS[21]) are both set to 1. + * | | |0 = No buffer error interrupt is generated in PDMA mode. + * | | |1 = Buffer error interrupt is generated in PDMA mode. + * |[30] |TXENDINT |Transmitter Empty Interrupt Indicator (Read Only) + * | | |This bit is set if TXENDIEN (UART_INTEN[22]) and TXENDIF(UART_INTSTS[22]) are both set to 1. + * | | |0 = No Transmitter Empty interrupt is generated. + * | | |1 = Transmitter Empty interrupt is generated. + * |[31] |ABRINT |Auto-baud Rate Interrupt Indicator (Read Only) + * | | |This bit is set if ABRIEN (UART_INTEN[18]) and ABRIF (UART_ALTCTL[17]) are both set to 1. + * | | |0 = No Auto-baud Rate interrupt is generated. + * | | |1 = The Auto-baud Rate interrupt is generated. + * @var UART_T::TOUT + * Offset: 0x20 UART Time-out Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7:0] |TOIC |Time-out Interrupt Comparator + * | | |The time-out counter resets and starts counting (the counting clock = baud rate) whenever the RX FIFO receives a new data word if time out counter is enabled by setting TOCNTEN (UART_INTEN[11]). + * | | |Once the content of time-out counter is equal to that of time-out interrupt comparator (TOIC (UART_TOUT[7:0])), a receiver time-out interrupt (RXTOINT(UART_INTSTS[12])) is generated if RXTOIEN (UART_INTEN [4]) enabled. + * | | |A new incoming data word or RX FIFO empty will clear RXTOIF (UART_INTSTS[4]). + * | | |In order to avoid receiver time-out interrupt generation immediately during one character is being received, TOIC value should be set between 40 and 255. + * | | |So, for example, if TOIC is set with 40, the time-out interrupt is generated after four characters are not received when 1 stop bit and no parity check is set for UART transfer. + * |[15:8] |DLY |TX Delay Time Value + * | | |This field is used to programming the transfer delay time between the last stop bit and next start bit + * | | |The unit is bit time. + * @var UART_T::BAUD + * Offset: 0x24 UART Baud Rate Divider Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |BRD |Baud Rate Divider + * | | |The field indicates the baud rate divider. + * | | |This filed is used in baud rate calculation. + * | | |The detail description is shown in Table 7.11-4. + * |[27:24] |EDIVM1 |Extra Divider for BAUD Rate Mode 1 + * | | |This field is used for baud rate calculation in mode 1 and has no effect for baud rate calculation in mode 0 and mode 2. + * | | |The detail description is shown in Table 7.11-4. + * |[28] |BAUDM0 |BAUD Rate Mode Selection Bit 0 + * | | |This bit is baud rate mode selection bit 0 + * | | |UART provides three baud rate calculation modes. + * | | |This bit combines with BAUDM1 (UART_BAUD[29]) to select baud rate calculation mode. + * | | |The detail description is shown in Table 7.11-4. + * |[29] |BAUDM1 |BAUD Rate Mode Selection Bit 1 + * | | |This bit is baud rate mode selection bit 1. + * | | |UART provides three baud rate calculation modes. + * | | |This bit combines with BAUDM0 (UART_BAUD[28]) to select baud rate calculation mode. + * | | |The detail description is shown in Table 7.11-4. + * | | |Note: In IrDA mode must be operated in mode 0. + * @var UART_T::IRDA + * Offset: 0x28 UART IrDA Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |TXEN |IrDA Receiver/Transmitter Selection Enable Bit + * | | |0 = IrDA Transmitter Disabled and Receiver Enabled. (Default) + * | | |1 = IrDA Transmitter Enabled and Receiver Disabled. + * |[5] |TXINV |IrDA Inverse Transmitting Output Signal + * | | |0 = None inverse transmitting signal. (Default). + * | | |1 = Inverse transmitting output signal. + * | | |Note1: Before setting this bit, TXRXDIS (UART_FUNCSEL[3]) should be set then waited for TXRXACT (UART_FIFOSTS[31]) is cleared + * | | |When the configuration is done, cleared TXRXDIS (UART_FUNCSEL[3]) to activate UART controller. + * | | |Note2: This bit is valid when FUNCSEL (UART_FUNCSEL[1:0]) is select IrDA function. + * |[6] |RXINV |IrDA Inverse Receive Input Signal + * | | |0 = None inverse receiving input signal. + * | | |1 = Inverse receiving input signal. (Default) + * | | |Note1: Before setting this bit, TXRXDIS (UART_FUNCSEL[3]) should be set then waited for TXRXACT (UART_FIFOSTS[31]) is cleared + * | | |When the configuration is done, cleared TXRXDIS (UART_FUNCSEL[3]) to activate UART controller. + * | | |Note2: This bit is valid when FUNCSEL (UART_FUNCSEL[1:0]) is select IrDA function. + * @var UART_T::ALTCTL + * Offset: 0x2C UART Alternate Control/Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |BRKFL |UART LIN Break Field Length + * | | |This field indicates a 4-bit LIN TX break field count. + * | | |Note1: This break field length is BRKFL + 1. + * | | |Note2: According to LIN spec, the reset value is 0xC (break field length = 13). + * |[6] |LINRXEN |LIN RX Enable Bit + * | | |0 = LIN RX mode Disabled. + * | | |1 = LIN RX mode Enabled. + * |[7] |LINTXEN |LIN TX Break Mode Enable Bit + * | | |0 = LIN TX Break mode Disabled. + * | | |1 = LIN TX Break mode Enabled. + * | | |Note: When TX break field transfer operation finished, this bit will be cleared automatically. + * |[8] |RS485NMM |RS-485 Normal Multi-drop Operation Mode (NMM) + * | | |0 = RS-485 Normal Multi-drop Operation mode (NMM) Disabled. + * | | |1 = RS-485 Normal Multi-drop Operation mode (NMM) Enabled. + * | | |Note: It cannot be active with RS-485_AAD operation mode. + * |[9] |RS485AAD |RS-485 Auto Address Detection Operation Mode (AAD) + * | | |0 = RS-485 Auto Address Detection Operation mode (AAD) Disabled. + * | | |1 = RS-485 Auto Address Detection Operation mode (AAD) Enabled. + * | | |Note: It cannot be active with RS-485_NMM operation mode. + * |[10] |RS485AUD |RS-485 Auto Direction Function (AUD) + * | | |0 = RS-485 Auto Direction Operation function (AUD) Disabled. + * | | |1 = RS-485 Auto Direction Operation function (AUD) Enabled. + * | | |Note: It can be active with RS-485_AAD or RS-485_NMM operation mode. + * |[15] |ADDRDEN |RS-485 Address Detection Enable Bit + * | | |This bit is used to enable RS-485 Address Detection mode. + * | | |0 = Address detection mode Disabled. + * | | |1 = Address detection mode Enabled. + * | | |Note: This bit is used for RS-485 any operation mode. + * |[17] |ABRIF |Auto-baud Rate Interrupt Flag (Read Only) + * | | |This bit is set when auto-baud rate detection function finished or the auto-baud rate counter was overflow and if ABRIEN(UART_INTEN [18]) is set then the auto-baud rate interrupt will be generated. + * | | |0 = No auto-baud rate interrupt flag is generated. + * | | |1 = Auto-baud rate interrupt flag is generated. + * | | |Note: This bit is read only, but it can be cleared by writing "1" to ABRDTOIF (UART_FIFOSTS[2]) and ABRDIF(UART_FIFOSTS[1]). + * |[18] |ABRDEN |Auto-baud Rate Detect Enable Bit + * | | |0 = Auto-baud rate detect function Disabled. + * | | |1 = Auto-baud rate detect function Enabled. + * | | |Note : This bit is cleared automatically after auto-baud detection is finished. + * |[20:19] |ABRDBITS |Auto-baud Rate Detect Bit Length + * | | |00 = 1-bit time from Start bit to the 1st rising edge. The input pattern shall be 0x01. + * | | |01 = 2-bit time from Start bit to the 1st rising edge. The input pattern shall be 0x02. + * | | |10 = 4-bit time from Start bit to the 1st rising edge. The input pattern shall be 0x08. + * | | |11 = 8-bit time from Start bit to the 1st rising edge. The input pattern shall be 0x80. + * | | |Note : The calculation of bit number includes the START bit. + * |[31:24] |ADDRMV |Address Match Value + * | | |This field contains the RS-485 address match values. + * | | |Note: This field is used for RS-485 auto address detection mode. + * @var UART_T::FUNCSEL + * Offset: 0x30 UART Function Select Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |FUNCSEL |Function Select + * | | |000 = UART function.Reserved. + * | | |010 = IrDA function. + * | | |011 = RS-485 function. + * | | |100 = UART Single-wire function. + * | | |Others = Reserved. + * |[3] |TXRXDIS |TX and RX Disable Bit + * | | |Setting this bit can disable TX and RX. + * | | |0 = TX and RX Enabled. + * | | |1 = TX and RX Disabled. + * | | |Note: The TX and RX will not disable immediately when this bit is set. + * | | |The TX and RX compelet current task before disable TX and RX. + * | | |When TX and RX disable, the TXRXACT (UART_FIFOSTS[31]) is cleared. + * @var UART_T::BRCOMP + * Offset: 0x3C UART Baud Rate Compensation Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |BRCOMP |Baud Rate Compensation Patten + * | | |These 9-bits are used to define the relative bit is compensated or not. + * | | |BRCOMP[7:0] is used to define the compensation of UART_DAT[7:0] and BRCOM[8] is used to define the parity bit. + * |[31] |BRCOMPDEC |Baud Rate Compensation Decrease + * | | |0 = Positive (increase one module clock) compensation for each compensated bit. + * | | |1 = Negative (decrease one module clock) compensation for each compensated bit. + * @var UART_T::WKCTL + * Offset: 0x40 UART Wake-up Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WKCTSEN |nCTS Wake-up Enable Bit + * | | |0 = nCTS Wake-up system function Disabled. + * | | |1 = nCTS Wake-up system function Enabled. + * | | |Note:When the system is in Power-down mode, an external.nCTS change will wake up system from Power-down mode. + * |[1] |WKDATEN |Incoming Data Wake-up Enable Bit + * | | |0 = Incoming data wake-up system function Disabled. + * | | |1 = Incoming data wake-up system function Enabled. + * | | |Note:When the system is in Power-down mode, incoming data will wake-up system from Power-down mode. + * |[2] |WKRFRTEN |Received Data FIFO Reached Threshold Wake-up Enable Bit + * | | |0 = Received Data FIFO reached threshold wake-up system function Disabled. + * | | |1 = Received Data FIFO reached threshold wake-up system function Enabled. + * | | |Note1: When the system is in Power-down mode, Received Data FIFO reached threshold will wake-up system from Power-down mode. + * | | |Note2: This bit is valid in UART0 and UART1. + * |[3] |WKRS485EN |RS-485 Address Match (AAD Mode) Wake-up Enable Bit + * | | |0 = RS-485 Address Match (AAD mode) wake-up system function Disabled. + * | | |1 = RS-485 Address Match (AAD mode) wake-up system function Enabled. + * | | |Note1: When the system is in.Power-down mode, RS-485 Address Match will wake-up system from Power-down mode. + * | | |Note2: This bit is used for RS-485 Auto Address Detection (AAD) mode in RS-485 function mode and ADDRDEN (UART_ALTCTL[15]) is set to 1. + * | | |Note3: This bit is valid in UART0 and UART1. + * |[4] |WKTOUTEN |Received Data FIFO Reached Threshold Time-out Wake-up Enable Bit + * | | |0 = Received Data FIFO reached threshold time-out wake-up system function Disabled. + * | | |1 = Received Data FIFO reached threshold time-out wake-up system function Enabled. + * | | |Note1: When the system is in Power-down mode, Received Data FIFO reached threshold time-out will wake up system from Power-down mode. + * | | |Note2: It is suggested the function is enabled when the WKRFRTEN (UART_WKCTL[2]) is set to 1. + * | | |Note3: This bit is valid in UART0 and UART1. + * @var UART_T::WKSTS + * Offset: 0x44 UART Wake-up Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CTSWKF |nCTS Wake-up Flag + * | | |This bit is set if chip wake-up from power-down state by nCTS wake-up. + * | | |0 = Chip stays in power-down state. + * | | |1 = Chip wake-up from power-down state by nCTS wake-up. + * | | |Note1: If WKCTSEN (UART_WKCTL[0]) is enabled, the nCTS wake-up cause this bit is set to "1". + * | | |Note2: This bit can be cleared by writing "1" to it. + * |[1] |DATWKF |Incoming Data Wake-up Flag + * | | |This bit is set if chip wake-up from power-down state by data wake-up. + * | | |0 = Chip stays in power-down state. + * | | |1 = Chip wake-up from power-down state by Incoming Data wake-up. + * | | |Note1: If WKDATEN (UART_WKCTL[1]) is enabled, the Incoming Data wake-up cause this bit is set to "1". + * | | |Note2: This bit can be cleared by writing "1" to it. + * |[2] |RFRTWKF |Received Data FIFO Reached Threshold Wake-up Flag + * | | |This bit is set if chip wake-up from power-down state by Received Data FIFO reached threshold wake-up. + * | | |0 = Chip stays in power-down state. + * | | |1 = Chip wake-up from power-down state by Received Data FIFO Reached Threshold wake-up. + * | | |Note1: If WKRFRTEN (UART_WKCTL[2]) is enabled, the Received Data FIFO Reached Threshold wake-up cause this bit is set to "1". + * | | |Note2: This bit can be cleared by writing "1" to it. + * | | |Note3: This bit is valid in UART0 and UART1. + * |[3] |RS485WKF |RS-485 Address Match (AAD Mode) Wake-up Flag + * | | |This bit is set if chip wake-up from power-down state by RS-485 Address Match (AAD mode). + * | | |0 = Chip stays in power-down state. + * | | |1 = Chip wake-up from power-down state by RS-485 Address Match (AAD mode) wake-up. + * | | |Note1: If WKRS485EN (UART_WKCTL[3]) is enabled, the RS-485 Address Match (AAD mode) wake-up cause this bit is set to "1". + * | | |Note2: This bit can be cleared by writing "1" to it. + * | | |Note3: This bit is valid in UART0 and UART1. + * |[4] |TOUTWKF |Received Data FIFO Threshold Time-out Wake-up Flag + * | | |This bit is set if chip wake-up from power-down state by Received Data FIFO Threshold Time-out wake-up. + * | | |0 = Chip stays in power-down state. + * | | |1 = Chip wake-up from power-down state by Received Data FIFO reached threshold time-out. + * | | |Note1: If WKTOUTEN (UART_WKCTL[4]) is enabled, the Received Data FIFO reached threshold time-out wake-up cause this bit is set to "1". + * | | |Note2: This bit can be cleared by writing "1" to it. + * | | |Note3: This bit is valid in UART0 and UART1. + * @var UART_T::DWKCOMP + * Offset: 0x48 UART Incoming Data Wake-up Compensation Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |STCOMP |Start Bit Compensation Value + * | | |These bits field indicate how many clock cycle selected by UART_CLK do the UART controller can get the 1st bit (start bit) when the device is wake-up from Power-down mode. + * | | |Note: It is valid only when WKDATEN (UART_WKCTL[1]) is set. + */ + __IO uint32_t DAT; /*!< [0x0000] UART Receive/Transmit Buffer Register */ + __IO uint32_t INTEN; /*!< [0x0004] UART Interrupt Enable Register */ + __IO uint32_t FIFO; /*!< [0x0008] UART FIFO Control Register */ + __IO uint32_t LINE; /*!< [0x000c] UART Line Control Register */ + __IO uint32_t MODEM; /*!< [0x0010] UART Modem Control Register */ + __IO uint32_t MODEMSTS; /*!< [0x0014] UART Modem Status Register */ + __IO uint32_t FIFOSTS; /*!< [0x0018] UART FIFO Status Register */ + __IO uint32_t INTSTS; /*!< [0x001c] UART Interrupt Status Register */ + __IO uint32_t TOUT; /*!< [0x0020] UART Time-out Register */ + __IO uint32_t BAUD; /*!< [0x0024] UART Baud Rate Divider Register */ + __IO uint32_t IRDA; /*!< [0x0028] UART IrDA Control Register */ + __IO uint32_t ALTCTL; /*!< [0x002c] UART Alternate Control/Status Register */ + __IO uint32_t FUNCSEL; /*!< [0x0030] UART Function Select Register */ + __I uint32_t RESERVE0[2]; + __IO uint32_t BRCOMP; /*!< [0x003c] UART Baud Rate Compensation Register */ + __IO uint32_t WKCTL; /*!< [0x0040] UART Wake-up Control Register */ + __IO uint32_t WKSTS; /*!< [0x0044] UART Wake-up Status Register */ + __IO uint32_t DWKCOMP; /*!< [0x0048] UART Incoming Data Wake-up Compensation Register */ + +} UART_T; + + +/** + @addtogroup UART_CONST UART Bit Field Definition + Constant Definitions for UART Controller +@{ */ + +#define UART_DAT_DAT_Pos (0) /*!< UART_T::DAT: DAT Position */ +#define UART_DAT_DAT_Msk (0xfful << UART_DAT_DAT_Pos) /*!< UART_T::DAT: DAT Mask */ + +#define UART_DAT_PARITY_Pos (8) /*!< UART_T::DAT: PARITY Position */ +#define UART_DAT_PARITY_Msk (0x1ul << UART_DAT_PARITY_Pos) /*!< UART_T::DAT: PARITY Mask */ + +#define UART_INTEN_RDAIEN_Pos (0) /*!< UART_T::INTEN: RDAIEN Position */ +#define UART_INTEN_RDAIEN_Msk (0x1ul << UART_INTEN_RDAIEN_Pos) /*!< UART_T::INTEN: RDAIEN Mask */ + +#define UART_INTEN_THREIEN_Pos (1) /*!< UART_T::INTEN: THREIEN Position */ +#define UART_INTEN_THREIEN_Msk (0x1ul << UART_INTEN_THREIEN_Pos) /*!< UART_T::INTEN: THREIEN Mask */ + +#define UART_INTEN_RLSIEN_Pos (2) /*!< UART_T::INTEN: RLSIEN Position */ +#define UART_INTEN_RLSIEN_Msk (0x1ul << UART_INTEN_RLSIEN_Pos) /*!< UART_T::INTEN: RLSIEN Mask */ + +#define UART_INTEN_MODEMIEN_Pos (3) /*!< UART_T::INTEN: MODEMIEN Position */ +#define UART_INTEN_MODEMIEN_Msk (0x1ul << UART_INTEN_MODEMIEN_Pos) /*!< UART_T::INTEN: MODEMIEN Mask */ + +#define UART_INTEN_RXTOIEN_Pos (4) /*!< UART_T::INTEN: RXTOIEN Position */ +#define UART_INTEN_RXTOIEN_Msk (0x1ul << UART_INTEN_RXTOIEN_Pos) /*!< UART_T::INTEN: RXTOIEN Mask */ + +#define UART_INTEN_BUFERRIEN_Pos (5) /*!< UART_T::INTEN: BUFERRIEN Position */ +#define UART_INTEN_BUFERRIEN_Msk (0x1ul << UART_INTEN_BUFERRIEN_Pos) /*!< UART_T::INTEN: BUFERRIEN Mask */ + +#define UART_INTEN_WKIEN_Pos (6) /*!< UART_T::INTEN: WKIEN Position */ +#define UART_INTEN_WKIEN_Msk (0x1ul << UART_INTEN_WKIEN_Pos) /*!< UART_T::INTEN: WKIEN Mask */ + +#define UART_INTEN_TOCNTEN_Pos (11) /*!< UART_T::INTEN: TOCNTEN Position */ +#define UART_INTEN_TOCNTEN_Msk (0x1ul << UART_INTEN_TOCNTEN_Pos) /*!< UART_T::INTEN: TOCNTEN Mask */ + +#define UART_INTEN_ATORTSEN_Pos (12) /*!< UART_T::INTEN: ATORTSEN Position */ +#define UART_INTEN_ATORTSEN_Msk (0x1ul << UART_INTEN_ATORTSEN_Pos) /*!< UART_T::INTEN: ATORTSEN Mask */ + +#define UART_INTEN_ATOCTSEN_Pos (13) /*!< UART_T::INTEN: ATOCTSEN Position */ +#define UART_INTEN_ATOCTSEN_Msk (0x1ul << UART_INTEN_ATOCTSEN_Pos) /*!< UART_T::INTEN: ATOCTSEN Mask */ + +#define UART_INTEN_TXPDMAEN_Pos (14) /*!< UART_T::INTEN: TXPDMAEN Position */ +#define UART_INTEN_TXPDMAEN_Msk (0x1ul << UART_INTEN_TXPDMAEN_Pos) /*!< UART_T::INTEN: TXPDMAEN Mask */ + +#define UART_INTEN_RXPDMAEN_Pos (15) /*!< UART_T::INTEN: RXPDMAEN Position */ +#define UART_INTEN_RXPDMAEN_Msk (0x1ul << UART_INTEN_RXPDMAEN_Pos) /*!< UART_T::INTEN: RXPDMAEN Mask */ + +#define UART_INTEN_SWBEIEN_Pos (16) /*!< UART_T::INTEN: SWBEIEN Position */ +#define UART_INTEN_SWBEIEN_Msk (0x1ul << UART_INTEN_SWBEIEN_Pos) /*!< UART_T::INTEN: SWBEIEN Mask */ + +#define UART_INTEN_ABRIEN_Pos (18) /*!< UART_T::INTEN: ABRIEN Position */ +#define UART_INTEN_ABRIEN_Msk (0x1ul << UART_INTEN_ABRIEN_Pos) /*!< UART_T::INTEN: ABRIEN Mask */ + +#define UART_INTEN_TXENDIEN_Pos (22) /*!< UART_T::INTEN: TXENDIEN Position */ +#define UART_INTEN_TXENDIEN_Msk (0x1ul << UART_INTEN_TXENDIEN_Pos) /*!< UART_T::INTEN: TXENDIEN Mask */ + +#define UART_FIFO_RXRST_Pos (1) /*!< UART_T::FIFO: RXRST Position */ +#define UART_FIFO_RXRST_Msk (0x1ul << UART_FIFO_RXRST_Pos) /*!< UART_T::FIFO: RXRST Mask */ + +#define UART_FIFO_TXRST_Pos (2) /*!< UART_T::FIFO: TXRST Position */ +#define UART_FIFO_TXRST_Msk (0x1ul << UART_FIFO_TXRST_Pos) /*!< UART_T::FIFO: TXRST Mask */ + +#define UART_FIFO_RFITL_Pos (4) /*!< UART_T::FIFO: RFITL Position */ +#define UART_FIFO_RFITL_Msk (0xful << UART_FIFO_RFITL_Pos) /*!< UART_T::FIFO: RFITL Mask */ + +#define UART_FIFO_RXOFF_Pos (8) /*!< UART_T::FIFO: RXOFF Position */ +#define UART_FIFO_RXOFF_Msk (0x1ul << UART_FIFO_RXOFF_Pos) /*!< UART_T::FIFO: RXOFF Mask */ + +#define UART_FIFO_RTSTRGLV_Pos (16) /*!< UART_T::FIFO: RTSTRGLV Position */ +#define UART_FIFO_RTSTRGLV_Msk (0xful << UART_FIFO_RTSTRGLV_Pos) /*!< UART_T::FIFO: RTSTRGLV Mask */ + +#define UART_LINE_WLS_Pos (0) /*!< UART_T::LINE: WLS Position */ +#define UART_LINE_WLS_Msk (0x3ul << UART_LINE_WLS_Pos) /*!< UART_T::LINE: WLS Mask */ + +#define UART_LINE_NSB_Pos (2) /*!< UART_T::LINE: NSB Position */ +#define UART_LINE_NSB_Msk (0x1ul << UART_LINE_NSB_Pos) /*!< UART_T::LINE: NSB Mask */ + +#define UART_LINE_PBE_Pos (3) /*!< UART_T::LINE: PBE Position */ +#define UART_LINE_PBE_Msk (0x1ul << UART_LINE_PBE_Pos) /*!< UART_T::LINE: PBE Mask */ + +#define UART_LINE_EPE_Pos (4) /*!< UART_T::LINE: EPE Position */ +#define UART_LINE_EPE_Msk (0x1ul << UART_LINE_EPE_Pos) /*!< UART_T::LINE: EPE Mask */ + +#define UART_LINE_SPE_Pos (5) /*!< UART_T::LINE: SPE Position */ +#define UART_LINE_SPE_Msk (0x1ul << UART_LINE_SPE_Pos) /*!< UART_T::LINE: SPE Mask */ + +#define UART_LINE_BCB_Pos (6) /*!< UART_T::LINE: BCB Position */ +#define UART_LINE_BCB_Msk (0x1ul << UART_LINE_BCB_Pos) /*!< UART_T::LINE: BCB Mask */ + +#define UART_LINE_PSS_Pos (7) /*!< UART_T::LINE: PSS Position */ +#define UART_LINE_PSS_Msk (0x1ul << UART_LINE_PSS_Pos) /*!< UART_T::LINE: PSS Mask */ + +#define UART_LINE_TXDINV_Pos (8) /*!< UART_T::LINE: TXDINV Position */ +#define UART_LINE_TXDINV_Msk (0x1ul << UART_LINE_TXDINV_Pos) /*!< UART_T::LINE: TXDINV Mask */ + +#define UART_LINE_RXDINV_Pos (9) /*!< UART_T::LINE: RXDINV Position */ +#define UART_LINE_RXDINV_Msk (0x1ul << UART_LINE_RXDINV_Pos) /*!< UART_T::LINE: RXDINV Mask */ + +#define UART_MODEM_RTS_Pos (1) /*!< UART_T::MODEM: RTS Position */ +#define UART_MODEM_RTS_Msk (0x1ul << UART_MODEM_RTS_Pos) /*!< UART_T::MODEM: RTS Mask */ + +#define UART_MODEM_RTSACTLV_Pos (9) /*!< UART_T::MODEM: RTSACTLV Position */ +#define UART_MODEM_RTSACTLV_Msk (0x1ul << UART_MODEM_RTSACTLV_Pos) /*!< UART_T::MODEM: RTSACTLV Mask */ + +#define UART_MODEM_RTSSTS_Pos (13) /*!< UART_T::MODEM: RTSSTS Position */ +#define UART_MODEM_RTSSTS_Msk (0x1ul << UART_MODEM_RTSSTS_Pos) /*!< UART_T::MODEM: RTSSTS Mask */ + +#define UART_MODEMSTS_CTSDETF_Pos (0) /*!< UART_T::MODEMSTS: CTSDETF Position */ +#define UART_MODEMSTS_CTSDETF_Msk (0x1ul << UART_MODEMSTS_CTSDETF_Pos) /*!< UART_T::MODEMSTS: CTSDETF Mask */ + +#define UART_MODEMSTS_CTSSTS_Pos (4) /*!< UART_T::MODEMSTS: CTSSTS Position */ +#define UART_MODEMSTS_CTSSTS_Msk (0x1ul << UART_MODEMSTS_CTSSTS_Pos) /*!< UART_T::MODEMSTS: CTSSTS Mask */ + +#define UART_MODEMSTS_CTSACTLV_Pos (8) /*!< UART_T::MODEMSTS: CTSACTLV Position */ +#define UART_MODEMSTS_CTSACTLV_Msk (0x1ul << UART_MODEMSTS_CTSACTLV_Pos) /*!< UART_T::MODEMSTS: CTSACTLV Mask */ + +#define UART_FIFOSTS_RXOVIF_Pos (0) /*!< UART_T::FIFOSTS: RXOVIF Position */ +#define UART_FIFOSTS_RXOVIF_Msk (0x1ul << UART_FIFOSTS_RXOVIF_Pos) /*!< UART_T::FIFOSTS: RXOVIF Mask */ + +#define UART_FIFOSTS_ABRDIF_Pos (1) /*!< UART_T::FIFOSTS: ABRDIF Position */ +#define UART_FIFOSTS_ABRDIF_Msk (0x1ul << UART_FIFOSTS_ABRDIF_Pos) /*!< UART_T::FIFOSTS: ABRDIF Mask */ + +#define UART_FIFOSTS_ABRDTOIF_Pos (2) /*!< UART_T::FIFOSTS: ABRDTOIF Position */ +#define UART_FIFOSTS_ABRDTOIF_Msk (0x1ul << UART_FIFOSTS_ABRDTOIF_Pos) /*!< UART_T::FIFOSTS: ABRDTOIF Mask */ + +#define UART_FIFOSTS_ADDRDETF_Pos (3) /*!< UART_T::FIFOSTS: ADDRDETF Position */ +#define UART_FIFOSTS_ADDRDETF_Msk (0x1ul << UART_FIFOSTS_ADDRDETF_Pos) /*!< UART_T::FIFOSTS: ADDRDETF Mask */ + +#define UART_FIFOSTS_PEF_Pos (4) /*!< UART_T::FIFOSTS: PEF Position */ +#define UART_FIFOSTS_PEF_Msk (0x1ul << UART_FIFOSTS_PEF_Pos) /*!< UART_T::FIFOSTS: PEF Mask */ + +#define UART_FIFOSTS_FEF_Pos (5) /*!< UART_T::FIFOSTS: FEF Position */ +#define UART_FIFOSTS_FEF_Msk (0x1ul << UART_FIFOSTS_FEF_Pos) /*!< UART_T::FIFOSTS: FEF Mask */ + +#define UART_FIFOSTS_BIF_Pos (6) /*!< UART_T::FIFOSTS: BIF Position */ +#define UART_FIFOSTS_BIF_Msk (0x1ul << UART_FIFOSTS_BIF_Pos) /*!< UART_T::FIFOSTS: BIF Mask */ + +#define UART_FIFOSTS_RXPTR_Pos (8) /*!< UART_T::FIFOSTS: RXPTR Position */ +#define UART_FIFOSTS_RXPTR_Msk (0x3ful << UART_FIFOSTS_RXPTR_Pos) /*!< UART_T::FIFOSTS: RXPTR Mask */ + +#define UART_FIFOSTS_RXEMPTY_Pos (14) /*!< UART_T::FIFOSTS: RXEMPTY Position */ +#define UART_FIFOSTS_RXEMPTY_Msk (0x1ul << UART_FIFOSTS_RXEMPTY_Pos) /*!< UART_T::FIFOSTS: RXEMPTY Mask */ + +#define UART_FIFOSTS_RXFULL_Pos (15) /*!< UART_T::FIFOSTS: RXFULL Position */ +#define UART_FIFOSTS_RXFULL_Msk (0x1ul << UART_FIFOSTS_RXFULL_Pos) /*!< UART_T::FIFOSTS: RXFULL Mask */ + +#define UART_FIFOSTS_TXPTR_Pos (16) /*!< UART_T::FIFOSTS: TXPTR Position */ +#define UART_FIFOSTS_TXPTR_Msk (0x3ful << UART_FIFOSTS_TXPTR_Pos) /*!< UART_T::FIFOSTS: TXPTR Mask */ + +#define UART_FIFOSTS_TXEMPTY_Pos (22) /*!< UART_T::FIFOSTS: TXEMPTY Position */ +#define UART_FIFOSTS_TXEMPTY_Msk (0x1ul << UART_FIFOSTS_TXEMPTY_Pos) /*!< UART_T::FIFOSTS: TXEMPTY Mask */ + +#define UART_FIFOSTS_TXFULL_Pos (23) /*!< UART_T::FIFOSTS: TXFULL Position */ +#define UART_FIFOSTS_TXFULL_Msk (0x1ul << UART_FIFOSTS_TXFULL_Pos) /*!< UART_T::FIFOSTS: TXFULL Mask */ + +#define UART_FIFOSTS_TXOVIF_Pos (24) /*!< UART_T::FIFOSTS: TXOVIF Position */ +#define UART_FIFOSTS_TXOVIF_Msk (0x1ul << UART_FIFOSTS_TXOVIF_Pos) /*!< UART_T::FIFOSTS: TXOVIF Mask */ + +#define UART_FIFOSTS_TXEMPTYF_Pos (28) /*!< UART_T::FIFOSTS: TXEMPTYF Position */ +#define UART_FIFOSTS_TXEMPTYF_Msk (0x1ul << UART_FIFOSTS_TXEMPTYF_Pos) /*!< UART_T::FIFOSTS: TXEMPTYF Mask */ + +#define UART_FIFOSTS_RXIDLE_Pos (29) /*!< UART_T::FIFOSTS: RXIDLE Position */ +#define UART_FIFOSTS_RXIDLE_Msk (0x1ul << UART_FIFOSTS_RXIDLE_Pos) /*!< UART_T::FIFOSTS: RXIDLE Mask */ + +#define UART_FIFOSTS_TXRXACT_Pos (31) /*!< UART_T::FIFOSTS: TXRXACT Position */ +#define UART_FIFOSTS_TXRXACT_Msk (0x1ul << UART_FIFOSTS_TXRXACT_Pos) /*!< UART_T::FIFOSTS: TXRXACT Mask */ + +#define UART_INTSTS_RDAIF_Pos (0) /*!< UART_T::INTSTS: RDAIF Position */ +#define UART_INTSTS_RDAIF_Msk (0x1ul << UART_INTSTS_RDAIF_Pos) /*!< UART_T::INTSTS: RDAIF Mask */ + +#define UART_INTSTS_THREIF_Pos (1) /*!< UART_T::INTSTS: THREIF Position */ +#define UART_INTSTS_THREIF_Msk (0x1ul << UART_INTSTS_THREIF_Pos) /*!< UART_T::INTSTS: THREIF Mask */ + +#define UART_INTSTS_RLSIF_Pos (2) /*!< UART_T::INTSTS: RLSIF Position */ +#define UART_INTSTS_RLSIF_Msk (0x1ul << UART_INTSTS_RLSIF_Pos) /*!< UART_T::INTSTS: RLSIF Mask */ + +#define UART_INTSTS_MODEMIF_Pos (3) /*!< UART_T::INTSTS: MODEMIF Position */ +#define UART_INTSTS_MODEMIF_Msk (0x1ul << UART_INTSTS_MODEMIF_Pos) /*!< UART_T::INTSTS: MODEMIF Mask */ + +#define UART_INTSTS_RXTOIF_Pos (4) /*!< UART_T::INTSTS: RXTOIF Position */ +#define UART_INTSTS_RXTOIF_Msk (0x1ul << UART_INTSTS_RXTOIF_Pos) /*!< UART_T::INTSTS: RXTOIF Mask */ + +#define UART_INTSTS_BUFERRIF_Pos (5) /*!< UART_T::INTSTS: BUFERRIF Position */ +#define UART_INTSTS_BUFERRIF_Msk (0x1ul << UART_INTSTS_BUFERRIF_Pos) /*!< UART_T::INTSTS: BUFERRIF Mask */ + +#define UART_INTSTS_WKIF_Pos (6) /*!< UART_T::INTSTS: WKIF Position */ +#define UART_INTSTS_WKIF_Msk (0x1ul << UART_INTSTS_WKIF_Pos) /*!< UART_T::INTSTS: WKIF Mask */ + +#define UART_INTSTS_RDAINT_Pos (8) /*!< UART_T::INTSTS: RDAINT Position */ +#define UART_INTSTS_RDAINT_Msk (0x1ul << UART_INTSTS_RDAINT_Pos) /*!< UART_T::INTSTS: RDAINT Mask */ + +#define UART_INTSTS_THREINT_Pos (9) /*!< UART_T::INTSTS: THREINT Position */ +#define UART_INTSTS_THREINT_Msk (0x1ul << UART_INTSTS_THREINT_Pos) /*!< UART_T::INTSTS: THREINT Mask */ + +#define UART_INTSTS_RLSINT_Pos (10) /*!< UART_T::INTSTS: RLSINT Position */ +#define UART_INTSTS_RLSINT_Msk (0x1ul << UART_INTSTS_RLSINT_Pos) /*!< UART_T::INTSTS: RLSINT Mask */ + +#define UART_INTSTS_MODEMINT_Pos (11) /*!< UART_T::INTSTS: MODEMINT Position */ +#define UART_INTSTS_MODEMINT_Msk (0x1ul << UART_INTSTS_MODEMINT_Pos) /*!< UART_T::INTSTS: MODEMINT Mask */ + +#define UART_INTSTS_RXTOINT_Pos (12) /*!< UART_T::INTSTS: RXTOINT Position */ +#define UART_INTSTS_RXTOINT_Msk (0x1ul << UART_INTSTS_RXTOINT_Pos) /*!< UART_T::INTSTS: RXTOINT Mask */ + +#define UART_INTSTS_BUFERRINT_Pos (13) /*!< UART_T::INTSTS: BUFERRINT Position */ +#define UART_INTSTS_BUFERRINT_Msk (0x1ul << UART_INTSTS_BUFERRINT_Pos) /*!< UART_T::INTSTS: BUFERRINT Mask */ + +#define UART_INTSTS_WKINT_Pos (14) /*!< UART_T::INTSTS: WKINT Position */ +#define UART_INTSTS_WKINT_Msk (0x1ul << UART_INTSTS_WKINT_Pos) /*!< UART_T::INTSTS: WKINT Mask */ + +#define UART_INTSTS_SWBEIF_Pos (16) /*!< UART_T::INTSTS: SWBEIF Position */ +#define UART_INTSTS_SWBEIF_Msk (0x1ul << UART_INTSTS_SWBEIF_Pos) /*!< UART_T::INTSTS: SWBEIF Mask */ + +#define UART_INTSTS_HWRLSIF_Pos (18) /*!< UART_T::INTSTS: HWRLSIF Position */ +#define UART_INTSTS_HWRLSIF_Msk (0x1ul << UART_INTSTS_HWRLSIF_Pos) /*!< UART_T::INTSTS: HWRLSIF Mask */ + +#define UART_INTSTS_HWMODIF_Pos (19) /*!< UART_T::INTSTS: HWMODIF Position */ +#define UART_INTSTS_HWMODIF_Msk (0x1ul << UART_INTSTS_HWMODIF_Pos) /*!< UART_T::INTSTS: HWMODIF Mask */ + +#define UART_INTSTS_HWTOIF_Pos (20) /*!< UART_T::INTSTS: HWTOIF Position */ +#define UART_INTSTS_HWTOIF_Msk (0x1ul << UART_INTSTS_HWTOIF_Pos) /*!< UART_T::INTSTS: HWTOIF Mask */ + +#define UART_INTSTS_HWBUFEIF_Pos (21) /*!< UART_T::INTSTS: HWBUFEIF Position */ +#define UART_INTSTS_HWBUFEIF_Msk (0x1ul << UART_INTSTS_HWBUFEIF_Pos) /*!< UART_T::INTSTS: HWBUFEIF Mask */ + +#define UART_INTSTS_TXENDIF_Pos (22) /*!< UART_T::INTSTS: TXENDIF Position */ +#define UART_INTSTS_TXENDIF_Msk (0x1ul << UART_INTSTS_TXENDIF_Pos) /*!< UART_T::INTSTS: TXENDIF Mask */ + +#define UART_INTSTS_SWBEINT_Pos (24) /*!< UART_T::INTSTS: SWBEINT Position */ +#define UART_INTSTS_SWBEINT_Msk (0x1ul << UART_INTSTS_SWBEINT_Pos) /*!< UART_T::INTSTS: SWBEINT Mask */ + +#define UART_INTSTS_HWRLSINT_Pos (26) /*!< UART_T::INTSTS: HWRLSINT Position */ +#define UART_INTSTS_HWRLSINT_Msk (0x1ul << UART_INTSTS_HWRLSINT_Pos) /*!< UART_T::INTSTS: HWRLSINT Mask */ + +#define UART_INTSTS_HWMODINT_Pos (27) /*!< UART_T::INTSTS: HWMODINT Position */ +#define UART_INTSTS_HWMODINT_Msk (0x1ul << UART_INTSTS_HWMODINT_Pos) /*!< UART_T::INTSTS: HWMODINT Mask */ + +#define UART_INTSTS_HWTOINT_Pos (28) /*!< UART_T::INTSTS: HWTOINT Position */ +#define UART_INTSTS_HWTOINT_Msk (0x1ul << UART_INTSTS_HWTOINT_Pos) /*!< UART_T::INTSTS: HWTOINT Mask */ + +#define UART_INTSTS_HWBUFEINT_Pos (29) /*!< UART_T::INTSTS: HWBUFEINT Position */ +#define UART_INTSTS_HWBUFEINT_Msk (0x1ul << UART_INTSTS_HWBUFEINT_Pos) /*!< UART_T::INTSTS: HWBUFEINT Mask */ + +#define UART_INTSTS_TXENDINT_Pos (30) /*!< UART_T::INTSTS: TXENDINT Position */ +#define UART_INTSTS_TXENDINT_Msk (0x1ul << UART_INTSTS_TXENDINT_Pos) /*!< UART_T::INTSTS: TXENDINT Mask */ + +#define UART_INTSTS_ABRINT_Pos (31) /*!< UART_T::INTSTS: ABRINT Position */ +#define UART_INTSTS_ABRINT_Msk (0x1ul << UART_INTSTS_ABRINT_Pos) /*!< UART_T::INTSTS: ABRINT Mask */ + +#define UART_TOUT_TOIC_Pos (0) /*!< UART_T::TOUT: TOIC Position */ +#define UART_TOUT_TOIC_Msk (0xfful << UART_TOUT_TOIC_Pos) /*!< UART_T::TOUT: TOIC Mask */ + +#define UART_TOUT_DLY_Pos (8) /*!< UART_T::TOUT: DLY Position */ +#define UART_TOUT_DLY_Msk (0xfful << UART_TOUT_DLY_Pos) /*!< UART_T::TOUT: DLY Mask */ + +#define UART_BAUD_BRD_Pos (0) /*!< UART_T::BAUD: BRD Position */ +#define UART_BAUD_BRD_Msk (0xfffful << UART_BAUD_BRD_Pos) /*!< UART_T::BAUD: BRD Mask */ + +#define UART_BAUD_EDIVM1_Pos (24) /*!< UART_T::BAUD: EDIVM1 Position */ +#define UART_BAUD_EDIVM1_Msk (0xful << UART_BAUD_EDIVM1_Pos) /*!< UART_T::BAUD: EDIVM1 Mask */ + +#define UART_BAUD_BAUDM0_Pos (28) /*!< UART_T::BAUD: BAUDM0 Position */ +#define UART_BAUD_BAUDM0_Msk (0x1ul << UART_BAUD_BAUDM0_Pos) /*!< UART_T::BAUD: BAUDM0 Mask */ + +#define UART_BAUD_BAUDM1_Pos (29) /*!< UART_T::BAUD: BAUDM1 Position */ +#define UART_BAUD_BAUDM1_Msk (0x1ul << UART_BAUD_BAUDM1_Pos) /*!< UART_T::BAUD: BAUDM1 Mask */ + +#define UART_IRDA_TXEN_Pos (1) /*!< UART_T::IRDA: TXEN Position */ +#define UART_IRDA_TXEN_Msk (0x1ul << UART_IRDA_TXEN_Pos) /*!< UART_T::IRDA: TXEN Mask */ + +#define UART_IRDA_TXINV_Pos (5) /*!< UART_T::IRDA: TXINV Position */ +#define UART_IRDA_TXINV_Msk (0x1ul << UART_IRDA_TXINV_Pos) /*!< UART_T::IRDA: TXINV Mask */ + +#define UART_IRDA_RXINV_Pos (6) /*!< UART_T::IRDA: RXINV Position */ +#define UART_IRDA_RXINV_Msk (0x1ul << UART_IRDA_RXINV_Pos) /*!< UART_T::IRDA: RXINV Mask */ + +#define UART_ALTCTL_BRKFL_Pos (0) /*!< UART_T::ALTCTL: BRKFL Position */ +#define UART_ALTCTL_BRKFL_Msk (0xful << UART_ALTCTL_BRKFL_Pos) /*!< UART_T::ALTCTL: BRKFL Mask */ + +#define UART_ALTCTL_LINRXEN_Pos (6) /*!< UART_T::ALTCTL: LINRXEN Position */ +#define UART_ALTCTL_LINRXEN_Msk (0x1ul << UART_ALTCTL_LINRXEN_Pos) /*!< UART_T::ALTCTL: LINRXEN Mask */ + +#define UART_ALTCTL_LINTXEN_Pos (7) /*!< UART_T::ALTCTL: LINTXEN Position */ +#define UART_ALTCTL_LINTXEN_Msk (0x1ul << UART_ALTCTL_LINTXEN_Pos) /*!< UART_T::ALTCTL: LINTXEN Mask */ + +#define UART_ALTCTL_RS485NMM_Pos (8) /*!< UART_T::ALTCTL: RS485NMM Position */ +#define UART_ALTCTL_RS485NMM_Msk (0x1ul << UART_ALTCTL_RS485NMM_Pos) /*!< UART_T::ALTCTL: RS485NMM Mask */ + +#define UART_ALTCTL_RS485AAD_Pos (9) /*!< UART_T::ALTCTL: RS485AAD Position */ +#define UART_ALTCTL_RS485AAD_Msk (0x1ul << UART_ALTCTL_RS485AAD_Pos) /*!< UART_T::ALTCTL: RS485AAD Mask */ + +#define UART_ALTCTL_RS485AUD_Pos (10) /*!< UART_T::ALTCTL: RS485AUD Position */ +#define UART_ALTCTL_RS485AUD_Msk (0x1ul << UART_ALTCTL_RS485AUD_Pos) /*!< UART_T::ALTCTL: RS485AUD Mask */ + +#define UART_ALTCTL_ADDRDEN_Pos (15) /*!< UART_T::ALTCTL: ADDRDEN Position */ +#define UART_ALTCTL_ADDRDEN_Msk (0x1ul << UART_ALTCTL_ADDRDEN_Pos) /*!< UART_T::ALTCTL: ADDRDEN Mask */ + +#define UART_ALTCTL_ABRIF_Pos (17) /*!< UART_T::ALTCTL: ABRIF Position */ +#define UART_ALTCTL_ABRIF_Msk (0x1ul << UART_ALTCTL_ABRIF_Pos) /*!< UART_T::ALTCTL: ABRIF Mask */ + +#define UART_ALTCTL_ABRDEN_Pos (18) /*!< UART_T::ALTCTL: ABRDEN Position */ +#define UART_ALTCTL_ABRDEN_Msk (0x1ul << UART_ALTCTL_ABRDEN_Pos) /*!< UART_T::ALTCTL: ABRDEN Mask */ + +#define UART_ALTCTL_ABRDBITS_Pos (19) /*!< UART_T::ALTCTL: ABRDBITS Position */ +#define UART_ALTCTL_ABRDBITS_Msk (0x3ul << UART_ALTCTL_ABRDBITS_Pos) /*!< UART_T::ALTCTL: ABRDBITS Mask */ + +#define UART_ALTCTL_ADDRMV_Pos (24) /*!< UART_T::ALTCTL: ADDRMV Position */ +#define UART_ALTCTL_ADDRMV_Msk (0xfful << UART_ALTCTL_ADDRMV_Pos) /*!< UART_T::ALTCTL: ADDRMV Mask */ + +#define UART_FUNCSEL_FUNCSEL_Pos (0) /*!< UART_T::FUNCSEL: FUNCSEL Position */ +#define UART_FUNCSEL_FUNCSEL_Msk (0x7ul << UART_FUNCSEL_FUNCSEL_Pos) /*!< UART_T::FUNCSEL: FUNCSEL Mask */ + +#define UART_FUNCSEL_TXRXDIS_Pos (3) /*!< UART_T::FUNCSEL: TXRXDIS Position */ +#define UART_FUNCSEL_TXRXDIS_Msk (0x1ul << UART_FUNCSEL_TXRXDIS_Pos) /*!< UART_T::FUNCSEL: TXRXDIS Mask */ + +#define UART_BRCOMP_BRCOMP_Pos (0) /*!< UART_T::BRCOMP: BRCOMP Position */ +#define UART_BRCOMP_BRCOMP_Msk (0x1fful << UART_BRCOMP_BRCOMP_Pos) /*!< UART_T::BRCOMP: BRCOMP Mask */ + +#define UART_BRCOMP_BRCOMPDEC_Pos (31) /*!< UART_T::BRCOMP: BRCOMPDEC Position */ +#define UART_BRCOMP_BRCOMPDEC_Msk (0x1ul << UART_BRCOMP_BRCOMPDEC_Pos) /*!< UART_T::BRCOMP: BRCOMPDEC Mask */ + +#define UART_WKCTL_WKCTSEN_Pos (0) /*!< UART_T::WKCTL: WKCTSEN Position */ +#define UART_WKCTL_WKCTSEN_Msk (0x1ul << UART_WKCTL_WKCTSEN_Pos) /*!< UART_T::WKCTL: WKCTSEN Mask */ + +#define UART_WKCTL_WKDATEN_Pos (1) /*!< UART_T::WKCTL: WKDATEN Position */ +#define UART_WKCTL_WKDATEN_Msk (0x1ul << UART_WKCTL_WKDATEN_Pos) /*!< UART_T::WKCTL: WKDATEN Mask */ + +#define UART_WKCTL_WKRFRTEN_Pos (2) /*!< UART_T::WKCTL: WKRFRTEN Position */ +#define UART_WKCTL_WKRFRTEN_Msk (0x1ul << UART_WKCTL_WKRFRTEN_Pos) /*!< UART_T::WKCTL: WKRFRTEN Mask */ + +#define UART_WKCTL_WKRS485EN_Pos (3) /*!< UART_T::WKCTL: WKRS485EN Position */ +#define UART_WKCTL_WKRS485EN_Msk (0x1ul << UART_WKCTL_WKRS485EN_Pos) /*!< UART_T::WKCTL: WKRS485EN Mask */ + +#define UART_WKCTL_WKTOUTEN_Pos (4) /*!< UART_T::WKCTL: WKTOUTEN Position */ +#define UART_WKCTL_WKTOUTEN_Msk (0x1ul << UART_WKCTL_WKTOUTEN_Pos) /*!< UART_T::WKCTL: WKTOUTEN Mask */ + +#define UART_WKSTS_CTSWKF_Pos (0) /*!< UART_T::WKSTS: CTSWKF Position */ +#define UART_WKSTS_CTSWKF_Msk (0x1ul << UART_WKSTS_CTSWKF_Pos) /*!< UART_T::WKSTS: CTSWKF Mask */ + +#define UART_WKSTS_DATWKF_Pos (1) /*!< UART_T::WKSTS: DATWKF Position */ +#define UART_WKSTS_DATWKF_Msk (0x1ul << UART_WKSTS_DATWKF_Pos) /*!< UART_T::WKSTS: DATWKF Mask */ + +#define UART_WKSTS_RFRTWKF_Pos (2) /*!< UART_T::WKSTS: RFRTWKF Position */ +#define UART_WKSTS_RFRTWKF_Msk (0x1ul << UART_WKSTS_RFRTWKF_Pos) /*!< UART_T::WKSTS: RFRTWKF Mask */ + +#define UART_WKSTS_RS485WKF_Pos (3) /*!< UART_T::WKSTS: RS485WKF Position */ +#define UART_WKSTS_RS485WKF_Msk (0x1ul << UART_WKSTS_RS485WKF_Pos) /*!< UART_T::WKSTS: RS485WKF Mask */ + +#define UART_WKSTS_TOUTWKF_Pos (4) /*!< UART_T::WKSTS: TOUTWKF Position */ +#define UART_WKSTS_TOUTWKF_Msk (0x1ul << UART_WKSTS_TOUTWKF_Pos) /*!< UART_T::WKSTS: TOUTWKF Mask */ + +#define UART_DWKCOMP_STCOMP_Pos (0) /*!< UART_T::DWKCOMP: STCOMP Position */ +#define UART_DWKCOMP_STCOMP_Msk (0xfffful << UART_DWKCOMP_STCOMP_Pos) /*!< UART_T::DWKCOMP: STCOMP Mask */ + +/**@}*/ /* UART_CONST */ +/**@}*/ /* end of UART register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __UART_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/ui2c_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/ui2c_reg.h new file mode 100644 index 0000000000..3cd53dc9e3 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/ui2c_reg.h @@ -0,0 +1,570 @@ +/**************************************************************************//** + * @file ui2c_reg.h + * @version V1.00 + * @brief UI2C register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __UI2C_REG_H__ +#define __UI2C_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup UI2C I2C Mode of USCI Controller (UI2C) + Memory Mapped Structure for UI2C Controller +@{ */ + +typedef struct +{ + + + /** + * @var UI2C_T::CTL + * Offset: 0x00 USCI Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |FUNMODE |Function Mode + * | | |This bit field selects the protocol for this USCI controller. + * | | |Selecting a protocol that is not available or a reserved combination disables the USCI. + * | | |When switching between two protocols, the USCI has to be disabled before selecting a new protocol. + * | | |Simultaneously, the USCI will be reset when user write 000 to FUNMODE. + * | | |000 = The USCI is disabled. All protocol related state machines are set to idle state. + * | | |001 = The SPI protocol is selected. + * | | |010 = The UART protocol is selected. + * | | |100 = The I2C protocol is selected. + * | | |Note: Other bit combinations are reserved. + * @var UI2C_T::BRGEN + * Offset: 0x08 USCI Baud Rate Generator Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RCLKSEL |Reference Clock Source Selection + * | | |This bit selects the source signal of reference clock (fREF_CLK). + * | | |0 = Peripheral device clock fPCLK. + * | | |1 = Reserved. + * |[1] |PTCLKSEL |Protocol Clock Source Selection + * | | |This bit selects the source signal of protocol clock (fPROT_CLK). + * | | |0 = Reference clock fREF_CLK. + * | | |1 = fREF_CLK2 (its frequency is half of fREF_CLK). + * |[3:2] |SPCLKSEL |Sample Clock Source Selection + * | | |This bit field used for the clock source selection of a sample clock (fSAMP_CLK) for the protocol processor. + * | | |00 = fSAMP_CLK = fDIV_CLK. + * | | |01 = fSAMP_CLK = fPROT_CLK. + * | | |10 = fSAMP_CLK = fSCLK. + * | | |11 = fSAMP_CLK = fREF_CLK. + * |[4] |TMCNTEN |Time Measurement Counter Enable Bit + * | | |This bit enables the 10-bit timing measurement counter. + * | | |0 = Time measurement counter is Disabled. + * | | |1 = Time measurement counter is Enabled. + * |[5] |TMCNTSRC |Time Measurement Counter Clock Source Selection + * | | |0 = Time measurement counter with fPROT_CLK. + * | | |1 = Time measurement counter with fDIV_CLK. + * |[9:8] |PDSCNT |Pre-divider for Sample Counter + * | | |This bit field defines the divide ratio of the clock division from sample clock fSAMP_CLK. + * | | |The divided frequency fPDS_CNT = fSAMP_CLK / (PDSCNT+1). + * |[14:10] |DSCNT |Denominator for Sample Counter + * | | |This bit field defines the divide ratio of the sample clock fSAMP_CLK. + * | | |The divided frequency fDS_CNT = fPDS_CNT / (DSCNT+1). + * |[25:16] |CLKDIV |Clock Divider + * | | |This bit field defines the ratio between the protocol clock frequency fPROT_CLK and the clock divider frequency fDIV_CLK (fDIV_CLK = fPROT_CLK / (CLKDIV+1) ). + * @var UI2C_T::LINECTL + * Offset: 0x2C USCI Line Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |LSB |LSB First Transmission Selection + * | | |0 = The MSB, which bit of transmit/receive data buffer depends on the setting of DWIDTH, is transmitted/received first. + * | | |1 = The LSB, the bit 0 of data buffer, will be transmitted/received first. + * |[11:8] |DWIDTH |Word Length of Transmission + * | | |This bit field defines the data word length (amount of bits) for reception and transmission. + * | | |The data word is always right-aligned in the data buffer. + * | | |USCI support word length from 4 to 16 bits. + * | | |0x0: The data word contains 16 bits located at bit positions [15:0]. + * | | |0x1: Reserved. + * | | |0x2: Reserved. + * | | |0x3: Reserved. + * | | |0x4: The data word contains 4 bits located at bit positions [3:0]. + * | | |0x5: The data word contains 5 bits located at bit positions [4:0]. + * | | |... + * | | |0xF: The data word contains 15 bits located at bit positions [14:0]. + * @var UI2C_T::TXDAT + * Offset: 0x30 USCI Transmit Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |TXDAT |Transmit Data + * | | |Software can use this bit field to write 16-bit transmit data for transmission. + * @var UI2C_T::RXDAT + * Offset: 0x34 USCI Receive Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RXDAT |Received Data + * | | |This bit field monitors the received data which stored in receive data buffer. + * | | |Note: In I2C protocol, RXDAT[12:8] indicate the different transmission conditions which defined in I2C. + * @var UI2C_T::DEVADDR0 + * Offset: 0x44 USCI Device Address Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[9:0] |DEVADDR |Device Address + * | | |In I2C protocol, this bit field contains the programmed slave address. + * | | |If the first received address byte are 1111 0AAXB, the AA bits are compared to the bits DEVADDR[9:8] to check for address match, where the X is R/W bit. + * | | |Then the second address byte is also compared to DEVADDR[7:0]. + * | | |Note1: The DEVADDR [9:7] must be set 3'b000 when I2C operating in 7-bit address mode. + * | | |Note2: When software set 10'h000, the address can not be used. + * @var UI2C_T::DEVADDR1 + * Offset: 0x48 USCI Device Address Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[9:0] |DEVADDR |Device Address + * | | |In I2C protocol, this bit field contains the programmed slave address. + * | | |If the first received address byte are 1111 0AAXB, the AA bits are compared to the bits DEVADDR[9:8] to check for address match, where the X is R/W bit. + * | | |Then the second address byte is also compared to DEVADDR[7:0]. + * | | |Note1: The DEVADDR [9:7] must be set 3'b000 when I2C operating in 7-bit address mode. + * | | |Note2: When software set 10'h000, the address can not be used. + * @var UI2C_T::ADDRMSK0 + * Offset: 0x4C USCI Device Address Mask Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[9:0] |ADDRMSK |USCI Device Address Mask + * | | |0 = Mask Disabled (the received corresponding register bit should be exact the same as address register). + * | | |1 = Mask Enabled (the received corresponding address bit is don't care). + * | | |USCI support multiple address recognition with two address mask register. + * | | |When the bit in the address mask register is set to one, it means the received corresponding address bit is don't-care. + * | | |If the bit is set to zero, that means the received corresponding register bit should be exact the same as address register. + * | | |Note: The wake-up function can not use address mask. + * @var UI2C_T::ADDRMSK1 + * Offset: 0x50 USCI Device Address Mask Register 1 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[9:0] |ADDRMSK |USCI Device Address Mask + * | | |0 = Mask Disabled (the received corresponding register bit should be exact the same as address register). + * | | |1 = Mask Enabled (the received corresponding address bit is don't care). + * | | |USCI support multiple address recognition with two address mask register. + * | | |When the bit in the address mask register is set to one, it means the received corresponding address bit is don't-care. + * | | |If the bit is set to zero, that means the received corresponding register bit should be exact the same as address register. + * | | |Note: The wake-up function can not use address mask. + * @var UI2C_T::WKCTL + * Offset: 0x54 USCI Wake-up Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WKEN |Wake-up Enable Bit + * | | |0 = Wake-up function Disabled. + * | | |1 = Wake-up function Enabled. + * |[1] |WKADDREN |Wake-up Address Match Enable Bit + * | | |0 = The chip is woken up according data toggle. + * | | |1 = The chip is woken up according address match. + * @var UI2C_T::WKSTS + * Offset: 0x58 USCI Wake-up Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WKF |Wake-up Flag + * | | |When chip is woken up from Power-down mode, this bit is set to 1. + * | | |Software can write 1 to clear this bit. + * @var UI2C_T::PROTCTL + * Offset: 0x5C USCI Protocol Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |GCFUNC |General Call Function + * | | |0 = General Call Function Disabled. + * | | |1 = General Call Function Enabled. + * |[1] |AA |Assert Acknowledge Control + * | | |When AA =1 prior to address or data received, an acknowledged (low level to SDA) will be returned during the acknowledge clock pulse on the SCL line when 1.) A slave is acknowledging the address sent from master, 2.) The receiver devices are acknowledging the data sent by transmitter. + * | | |When AA=0 prior to address or data received, a Not acknowledged (high level to SDA) will be returned during the acknowledge clock pulse on the SCL line. + * |[2] |STO |I2C STOP Control + * | | |In Master mode, setting STO to transmit a STOP condition to bus then I2C hardware will check the bus condition if a STOP condition is detected this bit will be cleared by hardware automatically. + * | | |In a slave mode, setting STO resets I2C hardware to the defined "not addressed" slave mode when bus error (UI2C_PROTSTS.ERRIF = 1). + * |[3] |STA |I2C START Control + * | | |Setting STA to logic 1 to enter Master mode, the I2C hardware sends a START or repeat START condition to bus when the bus is free. + * |[4] |ADDR10EN |Address 10-bit Function Enable Bit + * | | |0 = Address match 10 bit function Disabled. + * | | |1 = Address match 10 bit function Enabled. + * |[5] |PTRG |I2C Protocol Trigger (Write Only) + * | | |When a new state is present in the UI2C_PROTSTS register, if the related interrupt enable bits are set, the I2C interrupt is requested. + * | | |It must write one by software to this bit after the related interrupt flags are set to 1 and the I2C protocol function will go ahead until the STOP is active or the PROTEN is disabled. + * | | |0 = I2C's stretch disabled and the I2C protocol function will go ahead. + * | | |1 = I2C's stretch active. + * |[8] |SCLOUTEN |SCL Output Enable Bit + * | | |This bit enables monitor pulling SCL to low. + * | | |This monitor will pull SCL to low until it has had time to respond to an I2C interrupt. + * | | |0 = SCL output will be forced high due to open drain mechanism. + * | | |1 = I2C module may act as a slave peripheral just like in normal operation, the I2C holds the clock line low until it has had time to clear I2C interrupt. + * |[9] |MONEN |Monitor Mode Enable Bit + * | | |This bit enables monitor mode. + * | | |In monitor mode the SDA output will be put in high impedance mode. + * | | |This prevents the I2C module from outputting data of any kind (including ACK) onto the I2C data bus. + * | | |0 = The monitor mode Disabled. + * | | |1 = The monitor mode Enabled. + * | | |Note: Depending on the state of the SCLOUTEN bit, the SCL output may be also forced high, preventing the module from having control over the I2C clock line. + * |[25:16] |TOCNT |Time-out Clock Cycle + * | | |This bit field indicates how many clock cycle selected by TMCNTSRC (UI2C_BRGEN [5]) when each interrupt flags are clear. + * | | |The time-out is enable when TOCNT bigger than 0. + * | | |Note: The TMCNTSRC (UI2C_BRGEN [5]) must be set zero on I2C mode. + * |[31] |PROTEN |I2C Protocol Enable Bit + * | | |0 = I2C Protocol Disabled. + * | | |1 = I2C Protocol Enabled. + * @var UI2C_T::PROTIEN + * Offset: 0x60 USCI Protocol Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |TOIEN |Time-out Interrupt Enable Bit + * | | |In I2C protocol, this bit enables the interrupt generation in case of a time-out event. + * | | |0 = The time-out interrupt Disabled. + * | | |1 = The time-out interrupt Enabled. + * |[1] |STARIEN |START Condition Received Interrupt Enable Bit + * | | |This bit enables the generation of a protocol interrupt if a START condition is detected. + * | | |0 = The start condition interrupt Disabled. + * | | |1 = The start condition interrupt Enabled. + * |[2] |STORIEN |STOP Condition Received Interrupt Enable Bit + * | | |This bit enables the generation of a protocol interrupt if a STOP condition is detected. + * | | |0 = The stop condition interrupt Disabled. + * | | |1 = The stop condition interrupt Enabled. + * |[3] |NACKIEN |Non - Acknowledge Interrupt Enable Bit + * | | |This bit enables the generation of a protocol interrupt if a Non - acknowledge is detected by a master. + * | | |0 = The non - acknowledge interrupt Disabled. + * | | |1 = The non - acknowledge interrupt Enabled. + * |[4] |ARBLOIEN |Arbitration Lost Interrupt Enable Bit + * | | |This bit enables the generation of a protocol interrupt if an arbitration lost event is detected. + * | | |0 = The arbitration lost interrupt Disabled. + * | | |1 = The arbitration lost interrupt Enabled. + * |[5] |ERRIEN |Error Interrupt Enable Bit + * | | |This bit enables the generation of a protocol interrupt if an I2C error condition is detected (indicated by ERRIF (UI2C_PROTSTS [12])). + * | | |0 = The error interrupt Disabled. + * | | |1 = The error interrupt Enabled. + * |[6] |ACKIEN |Acknowledge Interrupt Enable Bit + * | | |This bit enables the generation of a protocol interrupt if an acknowledge is detected by a master. + * | | |0 = The acknowledge interrupt Disabled. + * | | |1 = The acknowledge interrupt Enabled. + * @var UI2C_T::PROTSTS + * Offset: 0x64 USCI Protocol Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5] |TOIF |Time-out Interrupt Flag + * | | |0 = A time-out interrupt status has not occurred. + * | | |1 = A time-out interrupt status has occurred. + * | | |Note: It is cleared by software writing 1 into this bit. + * |[6] |ONBUSY |On Bus Busy + * | | |Indicates that a communication is in progress on the bus. + * | | |It is set by hardware when a START condition is detected. + * | | |It is cleared by hardware when a STOP condition is detected. + * | | |0 = The bus is IDLE (both SCLK and SDA High). + * | | |1 = The bus is busy. + * |[8] |STARIF |Start Condition Received Interrupt Flag + * | | |This bit indicates that a start condition or repeated start condition has been detected on master mode. + * | | |However, this bit also indicates that a repeated start condition has been detected on slave mode. + * | | |A protocol interrupt can be generated if UI2C_PROTCTL.STARIEN = 1. + * | | |0 = A start condition has not yet been detected. + * | | |1 = A start condition has been detected. + * | | |Note: It is cleared by software writing 1 into this bit. + * |[9] |STORIF |Stop Condition Received Interrupt Flag + * | | |This bit indicates that a stop condition has been detected on the I2C bus lines. + * | | |A protocol interrupt can be generated if UI2C_PROTCTL.STORIEN = 1. + * | | |0 = A stop condition has not yet been detected. + * | | |1 = A stop condition has been detected. + * | | |Note1: It is cleared by software writing 1 into this bit. + * |[10] |NACKIF |Non - Acknowledge Received Interrupt Flag + * | | |This bit indicates that a non - acknowledge has been received in master mode. + * | | |A protocol interrupt can be generated if UI2C_PROTCTL.NACKIEN = 1. + * | | |0 = A non - acknowledge has not been received. + * | | |1 = A non - acknowledge has been received. + * | | |Note: It is cleared by software writing 1 into this bit. + * |[11] |ARBLOIF |Arbitration Lost Interrupt Flag + * | | |This bit indicates that an arbitration has been lost. + * | | |A protocol interrupt can be generated if UI2C_PROTCTL.ARBLOIEN = 1. + * | | |0 = An arbitration has not been lost. + * | | |1 = An arbitration has been lost. + * | | |Note: It is cleared by software writing 1 into this bit. + * |[12] |ERRIF |Error Interrupt Flag + * | | |This bit indicates that a Bus Error occurs when a START or STOP condition is present at an illegal position in the formation frame. + * | | |Example of illegal position are during the serial transfer of an address byte, a data byte or an acknowledge bit. + * | | |A protocol interrupt can be generated if UI2C_PROTCTL.ERRIEN = 1. + * | | |0 = An I2C error has not been detected. + * | | |1 = An I2C error has been detected. + * | | |Note1: It is cleared by software writing 1 into this bit. + * | | |Note2: This bit is set for slave mode, and user must write 1 into STO register to the defined "not addressed" slave mode. + * |[13] |ACKIF |Acknowledge Received Interrupt Flag + * | | |This bit indicates that an acknowledge has been received in master mode. + * | | |A protocol interrupt can be generated if UI2C_PROTCTL.ACKIEN = 1. + * | | |0 = An acknowledge has not been received. + * | | |1 = An acknowledge has been received. + * | | |Note: It is cleared by software writing 1 into this bit. + * |[14] |SLASEL |Slave Select Status + * | | |This bit indicates that this device has been selected as slave. + * | | |0 = The device is not selected as slave. + * | | |1 = The device is selected as slave. + * | | |Note: This bit has no interrupt signal, and it will be cleared automatically by hardware. + * |[15] |SLAREAD |Slave Read Request Status + * | | |This bit indicates that a slave read request has been detected. + * | | |0 = A slave R/W bit is 1 has not been detected. + * | | |1 = A slave R/W bit is 1 has been detected. + * | | |Note: This bit has no interrupt signal, and it will be cleared automatically by hardware. + * |[16] |WKAKDONE |Wake-up Address Frame Acknowledge Bit Done + * | | |0 = The ACK bit cycle of address match frame isn't done. + * | | |1 = The ACK bit cycle of address match frame is done in power-down. + * | | |Note: This bit can't release when WKUPIF is set. + * |[17] |WRSTSWK |Read/Write Status Bit in Address Wake-up Frame + * | | |0 = Write command be record on the address match wake-up frame. + * | | |1 = Read command be record on the address match wake-up frame. + * |[18] |BUSHANG |Bus Hang-up + * | | |This bit indicates bus hang-up status. + * | | |There is 4-bit counter count when SCL hold high and refer fSAMP_CLK. + * | | |The hang-up counter will count to overflow and set this bit when SDA is low. + * | | |The counter will be reset by falling edge of SCL signal. + * | | |0 = The bus is normal status for transmission. + * | | |1 = The bus is hang-up status for transmission. + * | | |Note: This bit has no interrupt signal, and it will be cleared automatically by hardware when a START condition is present. + * |[19] |ERRARBLO |Error Arbitration Lost + * | | |This bit indicates bus arbitration lost due to bigger noise which is can't be filtered by input processor. + * | | |The I2C can send start condition when ERRARBLO is set. + * | | |Thus this bit doesn't be cared on slave mode. + * | | |0 = The bus is normal status for transmission. + * | | |1 = The bus is error arbitration lost status for transmission. + * | | |Note: This bit has no interrupt signal, and it will be cleared automatically by hardware when a START condition is present. + * @var UI2C_T::ADMAT + * Offset: 0x88 I2C Slave Match Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |ADMAT0 |USCI Address 0 Match Status Register + * | | |When address 0 is matched, hardware will inform which address used. + * | | |This bit will set to 1, and software can write 1 to clear this bit. + * |[1] |ADMAT1 |USCI Address 1 Match Status Register + * | | |When address 1 is matched, hardware will inform which address used. + * | | |This bit will set to 1, and software can write 1 to clear this bit. + * @var UI2C_T::TMCTL + * Offset: 0x8C I2C Timing Configure Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |STCTL |Setup Time Configure Control + * | | |This field is used to generate a delay timing between SDA edge and SCL rising edge in transmission mode. + * | | |The delay setup time is numbers of peripheral clock = STCTL x fPCLK. + * |[24:16] |HTCTL |Hold Time Configure Control + * | | |This field is used to generate the delay timing between SCL falling edge SDA edge in + * | | |transmission mode. + * | | |The delay hold time is numbers of peripheral clock = HTCTL x fPCLK. + * | | |Note: Hold time adjust function can only work in master mode, when slave mode, this field should set as 0. + */ + __IO uint32_t CTL; /*!< [0x0000] USCI Control Register */ + __I uint32_t RESERVE0[1]; + __IO uint32_t BRGEN; /*!< [0x0008] USCI Baud Rate Generator Register */ + __I uint32_t RESERVE1[8]; + __IO uint32_t LINECTL; /*!< [0x002c] USCI Line Control Register */ + __O uint32_t TXDAT; /*!< [0x0030] USCI Transmit Data Register */ + __I uint32_t RXDAT; /*!< [0x0034] USCI Receive Data Register */ + __I uint32_t RESERVE2[3]; + __IO uint32_t DEVADDR0; /*!< [0x0044] USCI Device Address Register 0 */ + __IO uint32_t DEVADDR1; /*!< [0x0048] USCI Device Address Register 1 */ + __IO uint32_t ADDRMSK0; /*!< [0x004c] USCI Device Address Mask Register 0 */ + __IO uint32_t ADDRMSK1; /*!< [0x0050] USCI Device Address Mask Register 1 */ + __IO uint32_t WKCTL; /*!< [0x0054] USCI Wake-up Control Register */ + __IO uint32_t WKSTS; /*!< [0x0058] USCI Wake-up Status Register */ + __IO uint32_t PROTCTL; /*!< [0x005c] USCI Protocol Control Register */ + __IO uint32_t PROTIEN; /*!< [0x0060] USCI Protocol Interrupt Enable Register */ + __IO uint32_t PROTSTS; /*!< [0x0064] USCI Protocol Status Register */ + __I uint32_t RESERVE3[8]; + __IO uint32_t ADMAT; /*!< [0x0088] I2C Slave Match Address Register */ + __IO uint32_t TMCTL; /*!< [0x008c] I2C Timing Configure Control Register */ + +} UI2C_T; + +/** + @addtogroup UI2C_CONST UI2C Bit Field Definition + Constant Definitions for UI2C Controller +@{ */ + +#define UI2C_CTL_FUNMODE_Pos (0) /*!< UI2C_T::CTL: FUNMODE Position */ +#define UI2C_CTL_FUNMODE_Msk (0x7ul << UI2C_CTL_FUNMODE_Pos) /*!< UI2C_T::CTL: FUNMODE Mask */ + +#define UI2C_BRGEN_RCLKSEL_Pos (0) /*!< UI2C_T::BRGEN: RCLKSEL Position */ +#define UI2C_BRGEN_RCLKSEL_Msk (0x1ul << UI2C_BRGEN_RCLKSEL_Pos) /*!< UI2C_T::BRGEN: RCLKSEL Mask */ + +#define UI2C_BRGEN_PTCLKSEL_Pos (1) /*!< UI2C_T::BRGEN: PTCLKSEL Position */ +#define UI2C_BRGEN_PTCLKSEL_Msk (0x1ul << UI2C_BRGEN_PTCLKSEL_Pos) /*!< UI2C_T::BRGEN: PTCLKSEL Mask */ + +#define UI2C_BRGEN_SPCLKSEL_Pos (2) /*!< UI2C_T::BRGEN: SPCLKSEL Position */ +#define UI2C_BRGEN_SPCLKSEL_Msk (0x3ul << UI2C_BRGEN_SPCLKSEL_Pos) /*!< UI2C_T::BRGEN: SPCLKSEL Mask */ + +#define UI2C_BRGEN_TMCNTEN_Pos (4) /*!< UI2C_T::BRGEN: TMCNTEN Position */ +#define UI2C_BRGEN_TMCNTEN_Msk (0x1ul << UI2C_BRGEN_TMCNTEN_Pos) /*!< UI2C_T::BRGEN: TMCNTEN Mask */ + +#define UI2C_BRGEN_TMCNTSRC_Pos (5) /*!< UI2C_T::BRGEN: TMCNTSRC Position */ +#define UI2C_BRGEN_TMCNTSRC_Msk (0x1ul << UI2C_BRGEN_TMCNTSRC_Pos) /*!< UI2C_T::BRGEN: TMCNTSRC Mask */ + +#define UI2C_BRGEN_PDSCNT_Pos (8) /*!< UI2C_T::BRGEN: PDSCNT Position */ +#define UI2C_BRGEN_PDSCNT_Msk (0x3ul << UI2C_BRGEN_PDSCNT_Pos) /*!< UI2C_T::BRGEN: PDSCNT Mask */ + +#define UI2C_BRGEN_DSCNT_Pos (10) /*!< UI2C_T::BRGEN: DSCNT Position */ +#define UI2C_BRGEN_DSCNT_Msk (0x1ful << UI2C_BRGEN_DSCNT_Pos) /*!< UI2C_T::BRGEN: DSCNT Mask */ + +#define UI2C_BRGEN_CLKDIV_Pos (16) /*!< UI2C_T::BRGEN: CLKDIV Position */ +#define UI2C_BRGEN_CLKDIV_Msk (0x3fful << UI2C_BRGEN_CLKDIV_Pos) /*!< UI2C_T::BRGEN: CLKDIV Mask */ + +#define UI2C_LINECTL_LSB_Pos (0) /*!< UI2C_T::LINECTL: LSB Position */ +#define UI2C_LINECTL_LSB_Msk (0x1ul << UI2C_LINECTL_LSB_Pos) /*!< UI2C_T::LINECTL: LSB Mask */ + +#define UI2C_LINECTL_DWIDTH_Pos (8) /*!< UI2C_T::LINECTL: DWIDTH Position */ +#define UI2C_LINECTL_DWIDTH_Msk (0xful << UI2C_LINECTL_DWIDTH_Pos) /*!< UI2C_T::LINECTL: DWIDTH Mask */ + +#define UI2C_TXDAT_TXDAT_Pos (0) /*!< UI2C_T::TXDAT: TXDAT Position */ +#define UI2C_TXDAT_TXDAT_Msk (0xfffful << UI2C_TXDAT_TXDAT_Pos) /*!< UI2C_T::TXDAT: TXDAT Mask */ + +#define UI2C_RXDAT_RXDAT_Pos (0) /*!< UI2C_T::RXDAT: RXDAT Position */ +#define UI2C_RXDAT_RXDAT_Msk (0xfffful << UI2C_RXDAT_RXDAT_Pos) /*!< UI2C_T::RXDAT: RXDAT Mask */ + +#define UI2C_DEVADDR0_DEVADDR_Pos (0) /*!< UI2C_T::DEVADDR0: DEVADDR Position */ +#define UI2C_DEVADDR0_DEVADDR_Msk (0x3fful << UI2C_DEVADDR0_DEVADDR_Pos) /*!< UI2C_T::DEVADDR0: DEVADDR Mask */ + +#define UI2C_DEVADDR1_DEVADDR_Pos (0) /*!< UI2C_T::DEVADDR1: DEVADDR Position */ +#define UI2C_DEVADDR1_DEVADDR_Msk (0x3fful << UI2C_DEVADDR1_DEVADDR_Pos) /*!< UI2C_T::DEVADDR1: DEVADDR Mask */ + +#define UI2C_ADDRMSK0_ADDRMSK_Pos (0) /*!< UI2C_T::ADDRMSK0: ADDRMSK Position */ +#define UI2C_ADDRMSK0_ADDRMSK_Msk (0x3fful << UI2C_ADDRMSK0_ADDRMSK_Pos) /*!< UI2C_T::ADDRMSK0: ADDRMSK Mask */ + +#define UI2C_ADDRMSK1_ADDRMSK_Pos (0) /*!< UI2C_T::ADDRMSK1: ADDRMSK Position */ +#define UI2C_ADDRMSK1_ADDRMSK_Msk (0x3fful << UI2C_ADDRMSK1_ADDRMSK_Pos) /*!< UI2C_T::ADDRMSK1: ADDRMSK Mask */ + +#define UI2C_WKCTL_WKEN_Pos (0) /*!< UI2C_T::WKCTL: WKEN Position */ +#define UI2C_WKCTL_WKEN_Msk (0x1ul << UI2C_WKCTL_WKEN_Pos) /*!< UI2C_T::WKCTL: WKEN Mask */ + +#define UI2C_WKCTL_WKADDREN_Pos (1) /*!< UI2C_T::WKCTL: WKADDREN Position */ +#define UI2C_WKCTL_WKADDREN_Msk (0x1ul << UI2C_WKCTL_WKADDREN_Pos) /*!< UI2C_T::WKCTL: WKADDREN Mask */ + +#define UI2C_WKSTS_WKF_Pos (0) /*!< UI2C_T::WKSTS: WKF Position */ +#define UI2C_WKSTS_WKF_Msk (0x1ul << UI2C_WKSTS_WKF_Pos) /*!< UI2C_T::WKSTS: WKF Mask */ + +#define UI2C_PROTCTL_GCFUNC_Pos (0) /*!< UI2C_T::PROTCTL: GCFUNC Position */ +#define UI2C_PROTCTL_GCFUNC_Msk (0x1ul << UI2C_PROTCTL_GCFUNC_Pos) /*!< UI2C_T::PROTCTL: GCFUNC Mask */ + +#define UI2C_PROTCTL_AA_Pos (1) /*!< UI2C_T::PROTCTL: AA Position */ +#define UI2C_PROTCTL_AA_Msk (0x1ul << UI2C_PROTCTL_AA_Pos) /*!< UI2C_T::PROTCTL: AA Mask */ + +#define UI2C_PROTCTL_STO_Pos (2) /*!< UI2C_T::PROTCTL: STO Position */ +#define UI2C_PROTCTL_STO_Msk (0x1ul << UI2C_PROTCTL_STO_Pos) /*!< UI2C_T::PROTCTL: STO Mask */ + +#define UI2C_PROTCTL_STA_Pos (3) /*!< UI2C_T::PROTCTL: STA Position */ +#define UI2C_PROTCTL_STA_Msk (0x1ul << UI2C_PROTCTL_STA_Pos) /*!< UI2C_T::PROTCTL: STA Mask */ + +#define UI2C_PROTCTL_ADDR10EN_Pos (4) /*!< UI2C_T::PROTCTL: ADDR10EN Position */ +#define UI2C_PROTCTL_ADDR10EN_Msk (0x1ul << UI2C_PROTCTL_ADDR10EN_Pos) /*!< UI2C_T::PROTCTL: ADDR10EN Mask */ + +#define UI2C_PROTCTL_PTRG_Pos (5) /*!< UI2C_T::PROTCTL: PTRG Position */ +#define UI2C_PROTCTL_PTRG_Msk (0x1ul << UI2C_PROTCTL_PTRG_Pos) /*!< UI2C_T::PROTCTL: PTRG Mask */ + +#define UI2C_PROTCTL_SCLOUTEN_Pos (8) /*!< UI2C_T::PROTCTL: SCLOUTEN Position */ +#define UI2C_PROTCTL_SCLOUTEN_Msk (0x1ul << UI2C_PROTCTL_SCLOUTEN_Pos) /*!< UI2C_T::PROTCTL: SCLOUTEN Mask */ + +#define UI2C_PROTCTL_MONEN_Pos (9) /*!< UI2C_T::PROTCTL: MONEN Position */ +#define UI2C_PROTCTL_MONEN_Msk (0x1ul << UI2C_PROTCTL_MONEN_Pos) /*!< UI2C_T::PROTCTL: MONEN Mask */ + +#define UI2C_PROTCTL_TOCNT_Pos (16) /*!< UI2C_T::PROTCTL: TOCNT Position */ +#define UI2C_PROTCTL_TOCNT_Msk (0x3fful << UI2C_PROTCTL_TOCNT_Pos) /*!< UI2C_T::PROTCTL: TOCNT Mask */ + +#define UI2C_PROTCTL_PROTEN_Pos (31) /*!< UI2C_T::PROTCTL: PROTEN Position */ +#define UI2C_PROTCTL_PROTEN_Msk (0x1ul << UI2C_PROTCTL_PROTEN_Pos) /*!< UI2C_T::PROTCTL: PROTEN Mask */ + +#define UI2C_PROTIEN_TOIEN_Pos (0) /*!< UI2C_T::PROTIEN: TOIEN Position */ +#define UI2C_PROTIEN_TOIEN_Msk (0x1ul << UI2C_PROTIEN_TOIEN_Pos) /*!< UI2C_T::PROTIEN: TOIEN Mask */ + +#define UI2C_PROTIEN_STARIEN_Pos (1) /*!< UI2C_T::PROTIEN: STARIEN Position */ +#define UI2C_PROTIEN_STARIEN_Msk (0x1ul << UI2C_PROTIEN_STARIEN_Pos) /*!< UI2C_T::PROTIEN: STARIEN Mask */ + +#define UI2C_PROTIEN_STORIEN_Pos (2) /*!< UI2C_T::PROTIEN: STORIEN Position */ +#define UI2C_PROTIEN_STORIEN_Msk (0x1ul << UI2C_PROTIEN_STORIEN_Pos) /*!< UI2C_T::PROTIEN: STORIEN Mask */ + +#define UI2C_PROTIEN_NACKIEN_Pos (3) /*!< UI2C_T::PROTIEN: NACKIEN Position */ +#define UI2C_PROTIEN_NACKIEN_Msk (0x1ul << UI2C_PROTIEN_NACKIEN_Pos) /*!< UI2C_T::PROTIEN: NACKIEN Mask */ + +#define UI2C_PROTIEN_ARBLOIEN_Pos (4) /*!< UI2C_T::PROTIEN: ARBLOIEN Position */ +#define UI2C_PROTIEN_ARBLOIEN_Msk (0x1ul << UI2C_PROTIEN_ARBLOIEN_Pos) /*!< UI2C_T::PROTIEN: ARBLOIEN Mask */ + +#define UI2C_PROTIEN_ERRIEN_Pos (5) /*!< UI2C_T::PROTIEN: ERRIEN Position */ +#define UI2C_PROTIEN_ERRIEN_Msk (0x1ul << UI2C_PROTIEN_ERRIEN_Pos) /*!< UI2C_T::PROTIEN: ERRIEN Mask */ + +#define UI2C_PROTIEN_ACKIEN_Pos (6) /*!< UI2C_T::PROTIEN: ACKIEN Position */ +#define UI2C_PROTIEN_ACKIEN_Msk (0x1ul << UI2C_PROTIEN_ACKIEN_Pos) /*!< UI2C_T::PROTIEN: ACKIEN Mask */ + +#define UI2C_PROTSTS_TOIF_Pos (5) /*!< UI2C_T::PROTSTS: TOIF Position */ +#define UI2C_PROTSTS_TOIF_Msk (0x1ul << UI2C_PROTSTS_TOIF_Pos) /*!< UI2C_T::PROTSTS: TOIF Mask */ + +#define UI2C_PROTSTS_ONBUSY_Pos (6) /*!< UI2C_T::PROTSTS: ONBUSY Position */ +#define UI2C_PROTSTS_ONBUSY_Msk (0x1ul << UI2C_PROTSTS_ONBUSY_Pos) /*!< UI2C_T::PROTSTS: ONBUSY Mask */ + +#define UI2C_PROTSTS_STARIF_Pos (8) /*!< UI2C_T::PROTSTS: STARIF Position */ +#define UI2C_PROTSTS_STARIF_Msk (0x1ul << UI2C_PROTSTS_STARIF_Pos) /*!< UI2C_T::PROTSTS: STARIF Mask */ + +#define UI2C_PROTSTS_STORIF_Pos (9) /*!< UI2C_T::PROTSTS: STORIF Position */ +#define UI2C_PROTSTS_STORIF_Msk (0x1ul << UI2C_PROTSTS_STORIF_Pos) /*!< UI2C_T::PROTSTS: STORIF Mask */ + +#define UI2C_PROTSTS_NACKIF_Pos (10) /*!< UI2C_T::PROTSTS: NACKIF Position */ +#define UI2C_PROTSTS_NACKIF_Msk (0x1ul << UI2C_PROTSTS_NACKIF_Pos) /*!< UI2C_T::PROTSTS: NACKIF Mask */ + +#define UI2C_PROTSTS_ARBLOIF_Pos (11) /*!< UI2C_T::PROTSTS: ARBLOIF Position */ +#define UI2C_PROTSTS_ARBLOIF_Msk (0x1ul << UI2C_PROTSTS_ARBLOIF_Pos) /*!< UI2C_T::PROTSTS: ARBLOIF Mask */ + +#define UI2C_PROTSTS_ERRIF_Pos (12) /*!< UI2C_T::PROTSTS: ERRIF Position */ +#define UI2C_PROTSTS_ERRIF_Msk (0x1ul << UI2C_PROTSTS_ERRIF_Pos) /*!< UI2C_T::PROTSTS: ERRIF Mask */ + +#define UI2C_PROTSTS_ACKIF_Pos (13) /*!< UI2C_T::PROTSTS: ACKIF Position */ +#define UI2C_PROTSTS_ACKIF_Msk (0x1ul << UI2C_PROTSTS_ACKIF_Pos) /*!< UI2C_T::PROTSTS: ACKIF Mask */ + +#define UI2C_PROTSTS_SLASEL_Pos (14) /*!< UI2C_T::PROTSTS: SLASEL Position */ +#define UI2C_PROTSTS_SLASEL_Msk (0x1ul << UI2C_PROTSTS_SLASEL_Pos) /*!< UI2C_T::PROTSTS: SLASEL Mask */ + +#define UI2C_PROTSTS_SLAREAD_Pos (15) /*!< UI2C_T::PROTSTS: SLAREAD Position */ +#define UI2C_PROTSTS_SLAREAD_Msk (0x1ul << UI2C_PROTSTS_SLAREAD_Pos) /*!< UI2C_T::PROTSTS: SLAREAD Mask */ + +#define UI2C_PROTSTS_WKAKDONE_Pos (16) /*!< UI2C_T::PROTSTS: WKAKDONE Position */ +#define UI2C_PROTSTS_WKAKDONE_Msk (0x1ul << UI2C_PROTSTS_WKAKDONE_Pos) /*!< UI2C_T::PROTSTS: WKAKDONE Mask */ + +#define UI2C_PROTSTS_WRSTSWK_Pos (17) /*!< UI2C_T::PROTSTS: WRSTSWK Position */ +#define UI2C_PROTSTS_WRSTSWK_Msk (0x1ul << UI2C_PROTSTS_WRSTSWK_Pos) /*!< UI2C_T::PROTSTS: WRSTSWK Mask */ + +#define UI2C_PROTSTS_BUSHANG_Pos (18) /*!< UI2C_T::PROTSTS: BUSHANG Position */ +#define UI2C_PROTSTS_BUSHANG_Msk (0x1ul << UI2C_PROTSTS_BUSHANG_Pos) /*!< UI2C_T::PROTSTS: BUSHANG Mask */ + +#define UI2C_PROTSTS_ERRARBLO_Pos (19) /*!< UI2C_T::PROTSTS: ERRARBLO Position */ +#define UI2C_PROTSTS_ERRARBLO_Msk (0x1ul << UI2C_PROTSTS_ERRARBLO_Pos) /*!< UI2C_T::PROTSTS: ERRARBLO Mask */ + +#define UI2C_ADMAT_ADMAT0_Pos (0) /*!< UI2C_T::ADMAT: ADMAT0 Position */ +#define UI2C_ADMAT_ADMAT0_Msk (0x1ul << UI2C_ADMAT_ADMAT0_Pos) /*!< UI2C_T::ADMAT: ADMAT0 Mask */ + +#define UI2C_ADMAT_ADMAT1_Pos (1) /*!< UI2C_T::ADMAT: ADMAT1 Position */ +#define UI2C_ADMAT_ADMAT1_Msk (0x1ul << UI2C_ADMAT_ADMAT1_Pos) /*!< UI2C_T::ADMAT: ADMAT1 Mask */ + +#define UI2C_TMCTL_STCTL_Pos (0) /*!< UI2C_T::TMCTL: STCTL Position */ +#define UI2C_TMCTL_STCTL_Msk (0x1fful << UI2C_TMCTL_STCTL_Pos) /*!< UI2C_T::TMCTL: STCTL Mask */ + +#define UI2C_TMCTL_HTCTL_Pos (16) /*!< UI2C_T::TMCTL: HTCTL Position */ +#define UI2C_TMCTL_HTCTL_Msk (0x1fful << UI2C_TMCTL_HTCTL_Pos) /*!< UI2C_T::TMCTL: HTCTL Mask */ + +/**@}*/ /* UI2C_CONST */ +/**@}*/ /* end of UI2C register group */ + + +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __UI2C_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/usbd_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/usbd_reg.h new file mode 100644 index 0000000000..b9d80f392e --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/usbd_reg.h @@ -0,0 +1,570 @@ +/**************************************************************************//** + * @file usbd_reg.h + * @version V1.00 + * @brief USBD register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __USBD_REG_H__ +#define __USBD_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup USBD USB Device Controller(USBD) + Memory Mapped Structure for USBD Controller +@{ */ + + + +typedef struct +{ + + /** + * @var USBD_EP_T::BUFSEG + * Offset: 0x500/0x510/0x520/0x530/0x540/0x550/0x560/0x570 Endpoint Buffer Segmentation Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:3] |BUFSEG |Endpoint Buffer Segmentation + * | | |It is used to indicate the offset address for each endpoint with the USB SRAM starting address The effective starting address of the endpoint is + * | | |USBD_SRAM address + { BUFSEG[8:3], 3'b000} + * | | |Where the USBD_SRAM address = USBD_BA+0x100h. + * | | |Refer to the section 6.17.5.76.21.5.7 for the endpoint SRAM structure and its description. + * @var USBD_EP_T::MXPLD + * Offset: 0x504/0x514/0x524/0x534/0x544/0x554/0x564/0x574 Endpoint Maximal Payload Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:0] |MXPLD |Maximal Payload + * | | |Define the data length which is transmitted to host (IN token) or the actual data length which is received from the host (OUT token) + * | | |It also used to indicate that the endpoint is ready to be transmitted in IN token or received in OUT token. + * | | |(1) When the register is written by CPU, + * | | |For IN token, the value of MXPLD is used to define the data length to be transmitted and indicate the data buffer is ready. + * | | |For OUT token, it means that the controller is ready to receive data from the host and the value of MXPLD is the maximal data length comes from host. + * | | |(2) When the register is read by CPU, + * | | |For IN token, the value of MXPLD is indicated by the data length be transmitted to host + * | | |For OUT token, the value of MXPLD is indicated the actual data length receiving from host. + * | | |Note: Once MXPLD is written, the data packets will be transmitted/received immediately after IN/OUT token arrived. + * @var USBD_EP_T::CFG + * Offset: 0x508/0x518/0x528/0x538/0x548/0x558/0x568/0x578 Endpoint Configuration Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |EPNUM |Endpoint Number + * | | |These bits are used to define the endpoint number of the current endpoint. + * |[4] |ISOCH |Isochronous Endpoint + * | | |This bit is used to set the endpoint as Isochronous endpoint, no handshake. + * | | |0 = No Isochronous endpoint. + * | | |1 = Isochronous endpoint. + * |[6:5] |STATE |Endpoint STATE + * | | |00 = Endpoint is Disabled. + * | | |01 = Out endpoint. + * | | |10 = IN endpoint. + * | | |11 = Undefined. + * |[7] |DSQSYNC |Data Sequence Synchronization + * | | |0 = DATA0 PID. + * | | |1 = DATA1 PID. + * | | |Note: It is used to specify the DATA0 or DATA1 PID in the following IN token transaction. + * | | |Hardware will toggle automatically in IN token base on the bit. + * |[9] |CSTALL |Clear STALL Response + * | | |0 = Disable the device to clear the STALL handshake in setup stage. + * | | |1 = Clear the device to response STALL handshake in setup stage. + * @var USBD_EP_T::CFGP + * Offset: 0x50C/0x51C/0x52C/0x53C/0x54C/0x55C/0x56C/0x57C Endpoint Set Stall and Clear In/Out Ready Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |CLRRDY |Clear Ready + * | | |When the USBD_MXPLDx register is set by user, it means that the endpoint is ready to transmit or receive data. + * | | |If the user wants to disable this transaction before the transaction start, users can set this bit to 1 to disable it and it is auto clear to 0. + * | | |For IN token, write '1' to clear the IN token had ready to transmit the data to USB. + * | | |For OUT token, write '1' to clear the OUT token had ready to receive the data from USB. + * | | |This bit is write 1 only and is always 0 when it is read back. + * |[1] |SSTALL |Set STALL + * | | |0 = Disable the device to response STALL. + * | | |1 = Set the device to respond STALL automatically. + */ + __IO uint32_t BUFSEG; /*!< [0x0000] Endpoint Buffer Segmentation Register */ + __IO uint32_t MXPLD; /*!< [0x0004] Endpoint Maximal Payload Register */ + __IO uint32_t CFG; /*!< [0x0008] Endpoint Configuration Register */ + __IO uint32_t CFGP; /*!< [0x000c] Endpoint Set Stall and Clear In/Out Ready Control Register */ + +} USBD_EP_T; + +typedef struct +{ + /** + * @var USBD_T::INTEN + * Offset: 0x00 USB Device Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BUSIEN |Bus Event Interrupt Enable Bit + * | | |0 = BUS event interrupt Disabled. + * | | |1 = BUS event interrupt Enabled. + * |[1] |USBIEN |USB Event Interrupt Enable Bit + * | | |0 = USB event interrupt Disabled. + * | | |1 = USB event interrupt Enabled. + * |[2] |VBDETIEN |VBUS Detection Interrupt Enable Bit + * | | |0 = VBUS detection Interrupt Disabled. + * | | |1 = VBUS detection Interrupt Enabled. + * |[3] |NEVWKIEN |USB No-event-wake-up Interrupt Enable Bit + * | | |0 = No-event-wake-up Interrupt Disabled. + * | | |1 = No-event-wake-up Interrupt Enabled. + * |[4] |SOFIEN |Start of Frame Interrupt Enable Bit + * | | |0 = SOF Interrupt Disabled. + * | | |1 = SOF Interrupt Enabled. + * |[8] |WKEN |Wake-up Function Enable Bit + * | | |0 = USB wake-up function Disabled. + * | | |1 = USB wake-up function Enabled. + * |[15] |INNAKEN |Active NAK Function and Its Status in IN Token + * | | |0 = When device responds NAK after receiving IN token, IN NAK status will not be updated to USBD_EPSTS0 register, so that the USB interrupt event will not be asserted. + * | | |1 = IN NAK status will be updated to USBD_EPSTS0 register and the USB interrupt event will be asserted, when the device responds NAK after receiving IN token. + * @var USBD_T::INTSTS + * Offset: 0x04 USB Device Interrupt Event Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |BUSIF |BUS Interrupt Status + * | | |The BUS event means that there is one of the suspense or the resume function in the bus. + * | | |0 = No BUS event occurred. + * | | |1 = Bus event occurred; check USBD_ATTR[3:0] to know which kind of bus event was occurred, cleared by write 1 to USBD_INTSTS[0]. + * |[1] |USBIF |USB Event Interrupt Status + * | | |The USB event includes the SETUP Token, IN Token, OUT ACK, ISO IN, or ISO OUT events in the bus. + * | | |0 = No USB event occurred. + * | | |1 = USB event occurred, check EPSTS0~5[2:0] to know which kind of USB event was occurred, cleared by write 1 to USBD_INTSTS[1] or EPSTS0~11 and SETUP (USBD_INTSTS[31]). + * |[2] |VBDETIF |VBUS Detection Interrupt Status + * | | |0 = There is not attached/detached event in the USB. + * | | |1 = There is attached/detached event in the USB bus and it is cleared by write 1 to USBD_INTSTS[2]. + * |[3] |NEVWKIF |No-event-wake-up Interrupt Status + * | | |0 = NEVWK event does not occur. + * | | |1 = No-event-wake-up event occurred, cleared by write 1 to USBD_INTSTS[3]. + * |[4] |SOFIF |Start of Frame Interrupt Status + * | | |0 = SOF event does not occur. + * | | |1 = SOF event occurred, cleared by write 1 to USBD_INTSTS[4]. + * |[16] |EPEVT0 |Endpoint 0's USB Event Status + * | | |0 = No event occurred in endpoint 0. + * | | |1 = USB event occurred on Endpoint 0, check USBD_EPSTS0[3:0] to know which kind of USB event was occurred, cleared by write 1 to USBD_INTSTS[16] or USBD_INTSTS[1]. + * |[17] |EPEVT1 |Endpoint 1's USB Event Status + * | | |0 = No event occurred in endpoint 1. + * | | |1 = USB event occurred on Endpoint 1, check USBD_EPSTS0[7:4] to know which kind of USB event was occurred, cleared by write 1 to USBD_INTSTS[17] or USBD_INTSTS[1]. + * |[18] |EPEVT2 |Endpoint 2's USB Event Status + * | | |0 = No event occurred in endpoint 2. + * | | |1 = USB event occurred on Endpoint 2, check USBD_EPSTS0[11:8] to know which kind of USB event was occurred, cleared by write 1 to USBD_INTSTS[18] or USBD_INTSTS[1]. + * |[19] |EPEVT3 |Endpoint 3's USB Event Status + * | | |0 = No event occurred in endpoint 3. + * | | |1 = USB event occurred on Endpoint 3, check USBD_EPSTS0[15:12] to know which kind of USB event was occurred, cleared by write 1 to USBD_INTSTS[19] or USBD_INTSTS[1]. + * |[20] |EPEVT4 |Endpoint 4's USB Event Status + * | | |0 = No event occurred in endpoint 4. + * | | |1 = USB event occurred on Endpoint 4, check USBD_EPSTS0[19:16] to know which kind of USB event was occurred, cleared by write 1 to USBD_INTSTS[20] or USBD_INTSTS[1]. + * |[21] |EPEVT5 |Endpoint 5's USB Event Status + * | | |0 = No event occurred in endpoint 5. + * | | |1 = USB event occurred on Endpoint 5, check USBD_EPSTS0[23:20] to know which kind of USB event was occurred, cleared by write 1 to USBD_INTSTS[21] or USBD_INTSTS[1]. + * |[22] |EPEVT6 |Endpoint 6's USB Event Status + * | | |0 = No event occurred in endpoint 6. + * | | |1 = USB event occurred on Endpoint 6, check USBD_EPSTS0[27:24] to know which kind of USB event was occurred, cleared by write 1 to USBD_INTSTS[22] or USBD_INTSTS[1]. + * |[23] |EPEVT7 |Endpoint 7's USB Event Status + * | | |0 = No event occurred in endpoint 7. + * | | |1 = USB event occurred on Endpoint 7, check USBD_EPSTS0[31:28] to know which kind of USB event was occurred, cleared by write 1 to USBD_INTSTS[23] or USBD_INTSTS[1]. + * |[31] |SETUP |Setup Event Status + * | | |0 = No Setup event. + * | | |1 = Setup event occurred, cleared by write 1 to USBD_INTSTS[31]. + * @var USBD_T::FADDR + * Offset: 0x08 USB Device Function Address Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[6:0] |FADDR |USB Device Function Address + * @var USBD_T::EPSTS + * Offset: 0x0C USB Device Endpoint Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7] |OV |Overrun + * | | |It indicates that the received data is over the maximum payload number or not. + * | | |if received data is over the maximum payload number, the extra data will be ignored. + * | | |0 = No overrun. + * | | |1 = Out Data is more than the Max Payload in MXPLD register or the Setup Data is more than 8 Bytes. + * @var USBD_T::ATTR + * Offset: 0x10 USB Device Bus Status and Attribution Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |USBRST |USB Reset Status (Read Only) + * | | |0 = Bus no reset. + * | | |1 = Bus reset when SE0 (single-ended 0) more than 2.5us. + * |[1] |SUSPEND |Suspend Status (Read Only) + * | | |0 = Bus no suspend. + * | | |1 = Bus idle more than 3ms, either cable is plugged off or host is sleeping. + * |[2] |RESUME |Resume Status (Read Only) + * | | |0 = No bus resume. + * | | |1 = Resume from suspend. + * |[3] |TOUT |Time-out Status (Read Only) + * | | |When USB Device controller after received setup token or out token, USB controller stay J state to wait data package. + * | | |If the waiting time exceeds 18-bit length timing, TOUT flag will be generated. + * | | |0 = No time-out. + * | | |1 = No Bus response more than 18 bits time. + * |[4] |PHYEN |PHY Transceiver Function Enable Bit + * | | |0 = PHY transceiver function Disabled. + * | | |1 = PHY transceiver function Enabled. + * |[5] |RWAKEUP |Remote Wake-up + * | | |0 = Release the USB bus from K state. + * | | |1 = Force USB bus to K (USB_D+ low, USB_D-: high) state, used for remote wake-up. + * |[7] |USBEN |USB Controller Enable Bit + * | | |0 = USB Controller Disabled. + * | | |1 = USB Controller Enabled. + * |[8] |DPPUEN |Pull-up Resistor on USB_DP Enable Bit + * | | |0 = Pull-up resistor in USB_D+ bus Disabled. + * | | |1 = Pull-up resistor in USB_D+ bus Active. + * |[10] |BYTEM |CPU Access USB SRAM Size Mode Selection + * | | |0 = Word mode: The size of the transfer from CPU to USB SRAM can be Word only. + * | | |1 = Byte mode: The size of the transfer from CPU to USB SRAM can be Byte only. + * |[11] |LPMACK |LPM Token Acknowledge Enable Bit + * | | |The NYET/ACK will be returned only on a successful LPM transaction if no errors in both the EXT token and the LPM token and a valid bLinkState = 0001 (L1) is received, else ERROR and STALL will be returned automatically, respectively. + * | | |0= the valid LPM Token will be NYET. + * | | |1= the valid LPM Token will be ACK. + * |[12] |L1SUSPEND |LPM L1 Suspend (Read Only) + * | | |0 = Bus no L1 state suspend. + * | | |1 = This bit is set by the hardware when LPM command to enter the L1 state is successfully received and acknowledged. + * |[13] |L1RESUME |LPM L1 Resume (Read Only) + * | | |0 = Bus no LPM L1 state resume. + * | | |1 = LPM L1 state Resume from LPM L1 state suspend. + * @var USBD_T::VBUSDET + * Offset: 0x14 USB Device VBUS Detection Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |VBUSDET |Device VBUS Detection + * | | |0 = Controller is not attached to the USB host. + * | | |1 = Controller is attached to the USB host. + * @var USBD_T::STBUFSEG + * Offset: 0x18 SETUP Token Buffer Segmentation Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[8:3] |STBUFSEG |SETUP Token Buffer Segmentation + * | | |It is used to indicate the offset address for the SETUP token with the USB Device SRAM starting address The effective starting address is + * | | |USBD_SRAM address + {STBUFSEG, 3'b000} + * | | |Where the USBD_SRAM address = USBD_BA+0x100h. + * | | |Note: It is used for SETUP token only. + * @var USBD_T::EPSTS0 + * Offset: 0x20 USB Device Endpoint Status Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |EPSTS0 |Endpoint 0 Status + * | | |These bits are used to indicate the current status of this endpoint. + * | | |0000 = In ACK. + * | | |0001 = In NAK. + * | | |0010 = Out Packet Data0 ACK. + * | | |0011 = Setup ACK. + * | | |0110 = Out Packet Data1 ACK. + * | | |0111 = Isochronous transfer end. + * |[7:4] |EPSTS1 |Endpoint 1 Status + * | | |These bits are used to indicate the current status of this endpoint. + * | | |0000 = In ACK. + * | | |0001 = In NAK. + * | | |0010 = Out Packet Data0 ACK. + * | | |0011 = Setup ACK. + * | | |0110 = Out Packet Data1 ACK. + * | | |0111 = Isochronous transfer end. + * |[11:8] |EPSTS2 |Endpoint 2 Status + * | | |These bits are used to indicate the current status of this endpoint. + * | | |0000 = In ACK. + * | | |0001 = In NAK. + * | | |0010 = Out Packet Data0 ACK. + * | | |0011 = Setup ACK. + * | | |0110 = Out Packet Data1 ACK. + * | | |0111 = Isochronous transfer end. + * |[15:12] |EPSTS3 |Endpoint 3 Status + * | | |These bits are used to indicate the current status of this endpoint. + * | | |0000 = In ACK. + * | | |0001 = In NAK. + * | | |0010 = Out Packet Data0 ACK. + * | | |0011 = Setup ACK. + * | | |0110 = Out Packet Data1 ACK. + * | | |0111 = Isochronous transfer end. + * |[19:16] |EPSTS4 |Endpoint 4 Status + * | | |These bits are used to indicate the current status of this endpoint. + * | | |0000 = In ACK. + * | | |0001 = In NAK. + * | | |0010 = Out Packet Data0 ACK. + * | | |0011 = Setup ACK. + * | | |0110 = Out Packet Data1 ACK. + * | | |0111 = Isochronous transfer end. + * |[23:20] |EPSTS5 |Endpoint 5 Status + * | | |These bits are used to indicate the current status of this endpoint. + * | | |0000 = In ACK. + * | | |0001 = In NAK. + * | | |0010 = Out Packet Data0 ACK. + * | | |0011 = Setup ACK. + * | | |0110 = Out Packet Data1 ACK. + * | | |0111 = Isochronous transfer end. + * |[27:24] |EPSTS6 |Endpoint 6 Status + * | | |These bits are used to indicate the current status of this endpoint. + * | | |0000 = In ACK. + * | | |0001 = In NAK. + * | | |0010 = Out Packet Data0 ACK. + * | | |0011 = Setup ACK. + * | | |0110 = Out Packet Data1 ACK. + * | | |0111 = Isochronous transfer end. + * |[31:28] |EPSTS7 |Endpoint 7 Status + * | | |These bits are used to indicate the current status of this endpoint. + * | | |0000 = In ACK. + * | | |0001 = In NAK. + * | | |0010 = Out Packet Data0 ACK. + * | | |0011 = Setup ACK. + * | | |0110 = Out Packet Data1 ACK. + * | | |0111 = Isochronous transfer end. + * @var USBD_T::LPMATTR + * Offset: 0x88 USB LPM Attribution Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[3:0] |LPMLINKSTS|LPM Link State + * | | |These bits contain the bLinkState received with last ACK LPM Token. + * |[7:4] |LPMBESL |LPM Best Effort Service Latency + * | | |These bits contain the BESL value received with last ACK LPM Token. + * |[8] |LPMRWAKUP |LPM Remote Wakeup + * | | |This bit contains the bRemoteWake value received with last ACK LPM Token. + * @var USBD_T::FN + * Offset: 0x8C USB Frame Number Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[10:0] |FN |Frame Number + * | | |These bits contain the 11-bits frame number in the last received SOF packet. + * @var USBD_T::SE0 + * Offset: 0x90 USB Device Drive SE0 Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SE0 |Drive Single Ended Zero in USB Bus + * | | |The Single Ended Zero (SE0) is when both lines (USB_D+ and USB_D-) are being pulled low. + * | | |0 = Normal operation. + * | | |1 = Force USB PHY transceiver to drive SE0. + */ + __IO uint32_t INTEN; /*!< [0x0000] USB Device Interrupt Enable Register */ + __IO uint32_t INTSTS; /*!< [0x0004] USB Device Interrupt Event Status Register */ + __IO uint32_t FADDR; /*!< [0x0008] USB Device Function Address Register */ + __I uint32_t EPSTS; /*!< [0x000c] USB Device Endpoint Status Register */ + __IO uint32_t ATTR; /*!< [0x0010] USB Device Bus Status and Attribution Register */ + __I uint32_t VBUSDET; /*!< [0x0014] USB Device VBUS Detection Register */ + __IO uint32_t STBUFSEG; /*!< [0x0018] SETUP Token Buffer Segmentation Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE0[1]; + /// @endcond //HIDDEN_SYMBOLS + __I uint32_t EPSTS0; /*!< [0x0020] USB Device Endpoint Status Register 0 */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE1[25]; + /// @endcond //HIDDEN_SYMBOLS + __I uint32_t LPMATTR; /*!< [0x0088] USB LPM Attribution Register */ + __I uint32_t FN; /*!< [0x008c] USB Frame number Register */ + __IO uint32_t SE0; /*!< [0x0090] USB Device Drive SE0 Control Register */ + /// @cond HIDDEN_SYMBOLS + __I uint32_t RESERVE2[283]; + /// @endcond //HIDDEN_SYMBOLS + USBD_EP_T EP[8]; /*!< [0x0500~0x5BC] USB Device Endpoints(0~7) */ + +} USBD_T; + +/** + @addtogroup USBD_CONST USBD Bit Field Definition + Constant Definitions for USBD Controller +@{ */ + +#define USBD_INTEN_BUSIEN_Pos (0) /*!< USBD_T::INTEN: BUSIEN Position */ +#define USBD_INTEN_BUSIEN_Msk (0x1ul << USBD_INTEN_BUSIEN_Pos) /*!< USBD_T::INTEN: BUSIEN Mask */ + +#define USBD_INTEN_USBIEN_Pos (1) /*!< USBD_T::INTEN: USBIEN Position */ +#define USBD_INTEN_USBIEN_Msk (0x1ul << USBD_INTEN_USBIEN_Pos) /*!< USBD_T::INTEN: USBIEN Mask */ + +#define USBD_INTEN_VBDETIEN_Pos (2) /*!< USBD_T::INTEN: VBDETIEN Position */ +#define USBD_INTEN_VBDETIEN_Msk (0x1ul << USBD_INTEN_VBDETIEN_Pos) /*!< USBD_T::INTEN: VBDETIEN Mask */ + +#define USBD_INTEN_NEVWKIEN_Pos (3) /*!< USBD_T::INTEN: NEVWKIEN Position */ +#define USBD_INTEN_NEVWKIEN_Msk (0x1ul << USBD_INTEN_NEVWKIEN_Pos) /*!< USBD_T::INTEN: NEVWKIEN Mask */ + +#define USBD_INTEN_SOFIEN_Pos (4) /*!< USBD_T::INTEN: SOFIEN Position */ +#define USBD_INTEN_SOFIEN_Msk (0x1ul << USBD_INTEN_SOFIEN_Pos) /*!< USBD_T::INTEN: SOFIEN Mask */ + +#define USBD_INTEN_WKEN_Pos (8) /*!< USBD_T::INTEN: WKEN Position */ +#define USBD_INTEN_WKEN_Msk (0x1ul << USBD_INTEN_WKEN_Pos) /*!< USBD_T::INTEN: WKEN Mask */ + +#define USBD_INTEN_INNAKEN_Pos (15) /*!< USBD_T::INTEN: INNAKEN Position */ +#define USBD_INTEN_INNAKEN_Msk (0x1ul << USBD_INTEN_INNAKEN_Pos) /*!< USBD_T::INTEN: INNAKEN Mask */ + +#define USBD_INTSTS_BUSIF_Pos (0) /*!< USBD_T::INTSTS: BUSIF Position */ +#define USBD_INTSTS_BUSIF_Msk (0x1ul << USBD_INTSTS_BUSIF_Pos) /*!< USBD_T::INTSTS: BUSIF Mask */ + +#define USBD_INTSTS_USBIF_Pos (1) /*!< USBD_T::INTSTS: USBIF Position */ +#define USBD_INTSTS_USBIF_Msk (0x1ul << USBD_INTSTS_USBIF_Pos) /*!< USBD_T::INTSTS: USBIF Mask */ + +#define USBD_INTSTS_VBDETIF_Pos (2) /*!< USBD_T::INTSTS: VBDETIF Position */ +#define USBD_INTSTS_VBDETIF_Msk (0x1ul << USBD_INTSTS_VBDETIF_Pos) /*!< USBD_T::INTSTS: VBDETIF Mask */ + +#define USBD_INTSTS_NEVWKIF_Pos (3) /*!< USBD_T::INTSTS: NEVWKIF Position */ +#define USBD_INTSTS_NEVWKIF_Msk (0x1ul << USBD_INTSTS_NEVWKIF_Pos) /*!< USBD_T::INTSTS: NEVWKIF Mask */ + +#define USBD_INTSTS_SOFIF_Pos (4) /*!< USBD_T::INTSTS: SOFIF Position */ +#define USBD_INTSTS_SOFIF_Msk (0x1ul << USBD_INTSTS_SOFIF_Pos) /*!< USBD_T::INTSTS: SOFIF Mask */ + +#define USBD_INTSTS_EPEVT0_Pos (16) /*!< USBD_T::INTSTS: EPEVT0 Position */ +#define USBD_INTSTS_EPEVT0_Msk (0x1ul << USBD_INTSTS_EPEVT0_Pos) /*!< USBD_T::INTSTS: EPEVT0 Mask */ + +#define USBD_INTSTS_EPEVT1_Pos (17) /*!< USBD_T::INTSTS: EPEVT1 Position */ +#define USBD_INTSTS_EPEVT1_Msk (0x1ul << USBD_INTSTS_EPEVT1_Pos) /*!< USBD_T::INTSTS: EPEVT1 Mask */ + +#define USBD_INTSTS_EPEVT2_Pos (18) /*!< USBD_T::INTSTS: EPEVT2 Position */ +#define USBD_INTSTS_EPEVT2_Msk (0x1ul << USBD_INTSTS_EPEVT2_Pos) /*!< USBD_T::INTSTS: EPEVT2 Mask */ + +#define USBD_INTSTS_EPEVT3_Pos (19) /*!< USBD_T::INTSTS: EPEVT3 Position */ +#define USBD_INTSTS_EPEVT3_Msk (0x1ul << USBD_INTSTS_EPEVT3_Pos) /*!< USBD_T::INTSTS: EPEVT3 Mask */ + +#define USBD_INTSTS_EPEVT4_Pos (20) /*!< USBD_T::INTSTS: EPEVT4 Position */ +#define USBD_INTSTS_EPEVT4_Msk (0x1ul << USBD_INTSTS_EPEVT4_Pos) /*!< USBD_T::INTSTS: EPEVT4 Mask */ + +#define USBD_INTSTS_EPEVT5_Pos (21) /*!< USBD_T::INTSTS: EPEVT5 Position */ +#define USBD_INTSTS_EPEVT5_Msk (0x1ul << USBD_INTSTS_EPEVT5_Pos) /*!< USBD_T::INTSTS: EPEVT5 Mask */ + +#define USBD_INTSTS_EPEVT6_Pos (22) /*!< USBD_T::INTSTS: EPEVT6 Position */ +#define USBD_INTSTS_EPEVT6_Msk (0x1ul << USBD_INTSTS_EPEVT6_Pos) /*!< USBD_T::INTSTS: EPEVT6 Mask */ + +#define USBD_INTSTS_EPEVT7_Pos (23) /*!< USBD_T::INTSTS: EPEVT7 Position */ +#define USBD_INTSTS_EPEVT7_Msk (0x1ul << USBD_INTSTS_EPEVT7_Pos) /*!< USBD_T::INTSTS: EPEVT7 Mask */ + +#define USBD_INTSTS_SETUP_Pos (31) /*!< USBD_T::INTSTS: SETUP Position */ +#define USBD_INTSTS_SETUP_Msk (0x1ul << USBD_INTSTS_SETUP_Pos) /*!< USBD_T::INTSTS: SETUP Mask */ + +#define USBD_FADDR_FADDR_Pos (0) /*!< USBD_T::FADDR: FADDR Position */ +#define USBD_FADDR_FADDR_Msk (0x7ful << USBD_FADDR_FADDR_Pos) /*!< USBD_T::FADDR: FADDR Mask */ + +#define USBD_EPSTS_OV_Pos (7) /*!< USBD_T::EPSTS: OV Position */ +#define USBD_EPSTS_OV_Msk (0x1ul << USBD_EPSTS_OV_Pos) /*!< USBD_T::EPSTS: OV Mask */ + +#define USBD_ATTR_USBRST_Pos (0) /*!< USBD_T::ATTR: USBRST Position */ +#define USBD_ATTR_USBRST_Msk (0x1ul << USBD_ATTR_USBRST_Pos) /*!< USBD_T::ATTR: USBRST Mask */ + +#define USBD_ATTR_SUSPEND_Pos (1) /*!< USBD_T::ATTR: SUSPEND Position */ +#define USBD_ATTR_SUSPEND_Msk (0x1ul << USBD_ATTR_SUSPEND_Pos) /*!< USBD_T::ATTR: SUSPEND Mask */ + +#define USBD_ATTR_RESUME_Pos (2) /*!< USBD_T::ATTR: RESUME Position */ +#define USBD_ATTR_RESUME_Msk (0x1ul << USBD_ATTR_RESUME_Pos) /*!< USBD_T::ATTR: RESUME Mask */ + +#define USBD_ATTR_TOUT_Pos (3) /*!< USBD_T::ATTR: TOUT Position */ +#define USBD_ATTR_TOUT_Msk (0x1ul << USBD_ATTR_TOUT_Pos) /*!< USBD_T::ATTR: TOUT Mask */ + +#define USBD_ATTR_PHYEN_Pos (4) /*!< USBD_T::ATTR: PHYEN Position */ +#define USBD_ATTR_PHYEN_Msk (0x1ul << USBD_ATTR_PHYEN_Pos) /*!< USBD_T::ATTR: PHYEN Mask */ + +#define USBD_ATTR_RWAKEUP_Pos (5) /*!< USBD_T::ATTR: RWAKEUP Position */ +#define USBD_ATTR_RWAKEUP_Msk (0x1ul << USBD_ATTR_RWAKEUP_Pos) /*!< USBD_T::ATTR: RWAKEUP Mask */ + +#define USBD_ATTR_USBEN_Pos (7) /*!< USBD_T::ATTR: USBEN Position */ +#define USBD_ATTR_USBEN_Msk (0x1ul << USBD_ATTR_USBEN_Pos) /*!< USBD_T::ATTR: USBEN Mask */ + +#define USBD_ATTR_DPPUEN_Pos (8) /*!< USBD_T::ATTR: DPPUEN Position */ +#define USBD_ATTR_DPPUEN_Msk (0x1ul << USBD_ATTR_DPPUEN_Pos) /*!< USBD_T::ATTR: DPPUEN Mask */ + +#define USBD_ATTR_BYTEM_Pos (10) /*!< USBD_T::ATTR: BYTEM Position */ +#define USBD_ATTR_BYTEM_Msk (0x1ul << USBD_ATTR_BYTEM_Pos) /*!< USBD_T::ATTR: BYTEM Mask */ + +#define USBD_ATTR_LPMACK_Pos (11) /*!< USBD_T::ATTR: LPMACK Position */ +#define USBD_ATTR_LPMACK_Msk (0x1ul << USBD_ATTR_LPMACK_Pos) /*!< USBD_T::ATTR: LPMACK Mask */ + +#define USBD_ATTR_L1SUSPEND_Pos (12) /*!< USBD_T::ATTR: L1SUSPEND Position */ +#define USBD_ATTR_L1SUSPEND_Msk (0x1ul << USBD_ATTR_L1SUSPEND_Pos) /*!< USBD_T::ATTR: L1SUSPEND Mask */ + +#define USBD_ATTR_L1RESUME_Pos (13) /*!< USBD_T::ATTR: L1RESUME Position */ +#define USBD_ATTR_L1RESUME_Msk (0x1ul << USBD_ATTR_L1RESUME_Pos) /*!< USBD_T::ATTR: L1RESUME Mask */ + +#define USBD_VBUSDET_VBUSDET_Pos (0) /*!< USBD_T::VBUSDET: VBUSDET Position */ +#define USBD_VBUSDET_VBUSDET_Msk (0x1ul << USBD_VBUSDET_VBUSDET_Pos) /*!< USBD_T::VBUSDET: VBUSDET Mask */ + +#define USBD_STBUFSEG_STBUFSEG_Pos (3) /*!< USBD_T::STBUFSEG: STBUFSEG Position */ +#define USBD_STBUFSEG_STBUFSEG_Msk (0x3ful << USBD_STBUFSEG_STBUFSEG_Pos) /*!< USBD_T::STBUFSEG: STBUFSEG Mask */ + +#define USBD_EPSTS0_EPSTS0_Pos (0) /*!< USBD_T::EPSTS0: EPSTS0 Position */ +#define USBD_EPSTS0_EPSTS0_Msk (0xful << USBD_EPSTS0_EPSTS0_Pos) /*!< USBD_T::EPSTS0: EPSTS0 Mask */ + +#define USBD_EPSTS0_EPSTS1_Pos (4) /*!< USBD_T::EPSTS0: EPSTS1 Position */ +#define USBD_EPSTS0_EPSTS1_Msk (0xful << USBD_EPSTS0_EPSTS1_Pos) /*!< USBD_T::EPSTS0: EPSTS1 Mask */ + +#define USBD_EPSTS0_EPSTS2_Pos (8) /*!< USBD_T::EPSTS0: EPSTS2 Position */ +#define USBD_EPSTS0_EPSTS2_Msk (0xful << USBD_EPSTS0_EPSTS2_Pos) /*!< USBD_T::EPSTS0: EPSTS2 Mask */ + +#define USBD_EPSTS0_EPSTS3_Pos (12) /*!< USBD_T::EPSTS0: EPSTS3 Position */ +#define USBD_EPSTS0_EPSTS3_Msk (0xful << USBD_EPSTS0_EPSTS3_Pos) /*!< USBD_T::EPSTS0: EPSTS3 Mask */ + +#define USBD_EPSTS0_EPSTS4_Pos (16) /*!< USBD_T::EPSTS0: EPSTS4 Position */ +#define USBD_EPSTS0_EPSTS4_Msk (0xful << USBD_EPSTS0_EPSTS4_Pos) /*!< USBD_T::EPSTS0: EPSTS4 Mask */ +#define USBD_EPSTS0_EPSTS5_Pos (20) /*!< USBD_T::EPSTS0: EPSTS5 Position */ +#define USBD_EPSTS0_EPSTS5_Msk (0xful << USBD_EPSTS0_EPSTS5_Pos) /*!< USBD_T::EPSTS0: EPSTS5 Mask */ + +#define USBD_EPSTS0_EPSTS6_Pos (24) /*!< USBD_T::EPSTS0: EPSTS6 Position */ +#define USBD_EPSTS0_EPSTS6_Msk (0xful << USBD_EPSTS0_EPSTS6_Pos) /*!< USBD_T::EPSTS0: EPSTS6 Mask */ + +#define USBD_EPSTS0_EPSTS7_Pos (28) /*!< USBD_T::EPSTS0: EPSTS7 Position */ +#define USBD_EPSTS0_EPSTS7_Msk (0xful << USBD_EPSTS0_EPSTS7_Pos) /*!< USBD_T::EPSTS0: EPSTS7 Mask */ + +#define USBD_LPMATTR_LPMLINKSTS_Pos (0) /*!< USBD_T::LPMATTR: LPMLINKSTS Position */ +#define USBD_LPMATTR_LPMLINKSTS_Msk (0xful << USBD_LPMATTR_LPMLINKSTS_Pos) /*!< USBD_T::LPMATTR: LPMLINKSTS Mask */ + +#define USBD_LPMATTR_LPMBESL_Pos (4) /*!< USBD_T::LPMATTR: LPMBESL Position */ +#define USBD_LPMATTR_LPMBESL_Msk (0xful << USBD_LPMATTR_LPMBESL_Pos) /*!< USBD_T::LPMATTR: LPMBESL Mask */ + +#define USBD_LPMATTR_LPMRWAKUP_Pos (8) /*!< USBD_T::LPMATTR: LPMRWAKUP Position */ +#define USBD_LPMATTR_LPMRWAKUP_Msk (0x1ul << USBD_LPMATTR_LPMRWAKUP_Pos) /*!< USBD_T::LPMATTR: LPMRWAKUP Mask */ + +#define USBD_FN_FN_Pos (0) /*!< USBD_T::FN: FN Position */ +#define USBD_FN_FN_Msk (0x7fful << USBD_FN_FN_Pos) /*!< USBD_T::FN: FN Mask */ + +#define USBD_SE0_SE0_Pos (0) /*!< USBD_T::SE0: SE0 Position */ +#define USBD_SE0_SE0_Msk (0x1ul << USBD_SE0_SE0_Pos) /*!< USBD_T::SE0: SE0 Mask */ + +#define USBD_BUFSEG_BUFSEG_Pos (3) /*!< USBD_EP_T::BUFSEG: BUFSEG Position */ +#define USBD_BUFSEG_BUFSEG_Msk (0x3ful << USBD_BUFSEG_BUFSEG_Pos) /*!< USBD_EP_T::BUFSEG: BUFSEG Mask */ + +#define USBD_MXPLD_MXPLD_Pos (0) /*!< USBD_EP_T::MXPLD: MXPLD Position */ +#define USBD_MXPLD_MXPLD_Msk (0x1fful << USBD_MXPLD_MXPLD_Pos) /*!< USBD_EP_T::MXPLD: MXPLD Mask */ + +#define USBD_CFG_EPNUM_Pos (0) /*!< USBD_EP_T::CFG: EPNUM Position */ +#define USBD_CFG_EPNUM_Msk (0xful << USBD_CFG_EPNUM_Pos) /*!< USBD_EP_T::CFG: EPNUM Mask */ + +#define USBD_CFG_ISOCH_Pos (4) /*!< USBD_EP_T::CFG: ISOCH Position */ +#define USBD_CFG_ISOCH_Msk (0x1ul << USBD_CFG_ISOCH_Pos) /*!< USBD_EP_T::CFG: ISOCH Mask */ + +#define USBD_CFG_STATE_Pos (5) /*!< USBD_EP_T::CFG: STATE Position */ +#define USBD_CFG_STATE_Msk (0x3ul << USBD_CFG_STATE_Pos) /*!< USBD_EP_T::CFG: STATE Mask */ + +#define USBD_CFG_DSQSYNC_Pos (7) /*!< USBD_EP_T::CFG: DSQSYNC Position */ +#define USBD_CFG_DSQSYNC_Msk (0x1ul << USBD_CFG_DSQSYNC_Pos) /*!< USBD_EP_T::CFG: DSQSYNC Mask */ + +#define USBD_CFG_CSTALL_Pos (9) /*!< USBD_EP_T::CFG: CSTALL Position */ +#define USBD_CFG_CSTALL_Msk (0x1ul << USBD_CFG_CSTALL_Pos) /*!< USBD_EP_T::CFG: CSTALL Mask */ + +#define USBD_CFGP_CLRRDY_Pos (0) /*!< USBD_EP_T::CFGP: CLRRDY Position */ +#define USBD_CFGP_CLRRDY_Msk (0x1ul << USBD_CFGP_CLRRDY_Pos) /*!< USBD_EP_T::CFGP: CLRRDY Mask */ + +#define USBD_CFGP_SSTALL_Pos (1) /*!< USBD_EP_T::CFGP: SSTALL Position */ +#define USBD_CFGP_SSTALL_Msk (0x1ul << USBD_CFGP_SSTALL_Pos) /*!< USBD_EP_T::CFGP: SSTALL Mask */ + +/**@}*/ /* USBD_CONST */ +/**@}*/ /* end of USBD register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __USBD_REG_H__ */ + diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uspi_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uspi_reg.h new file mode 100644 index 0000000000..debfe82ded --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uspi_reg.h @@ -0,0 +1,673 @@ +/**************************************************************************//** + * @file uspi_reg.h + * @version V1.00 + * @brief USPI register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __USPI_REG_H__ +#define __USPI_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup USPI SPI Mode of USCI Controller (USPI) + Memory Mapped Structure for USPI Controller +@{ */ + +typedef struct +{ + + + /** + * @var USPI_T::CTL + * Offset: 0x00 USCI Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |FUNMODE |Function Mode + * | | |This bit field selects the protocol for this USCI controller. + * | | |Selecting a protocol that is not available or a reserved combination disables the USCI. + * | | |When switching between two protocols, the USCI has to be disabled before selecting a new protocol. + * | | |Simultaneously, the USCI will be reset when user write 000 to FUNMODE. + * | | |000 = The USCI is disabled. All protocol related state machines are set to idle state. + * | | |001 = The SPI protocol is selected. + * | | |010 = The UART protocol is selected. + * | | |100 = The I2C protocol is selected. + * | | |Note: Other bit combinations are reserved. + * @var USPI_T::INTEN + * Offset: 0x04 USCI Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |TXSTIEN |Transmit Start Interrupt Enable Bit + * | | |This bit enables the interrupt generation in case of a transmit start event. + * | | |0 = The transmit start interrupt Disabled. + * | | |1 = The transmit start interrupt Enabled. + * | | |Note: The transmit start event happens when hardware starts to move TX data from data buffer to shift data unit. + * |[2] |TXENDIEN |Transmit End Interrupt Enable Bit + * | | |This bit enables the interrupt generation in case of a transmit finish event. + * | | |0 = The transmit finish interrupt Disabled. + * | | |1 = The transmit finish interrupt Enabled. + * | | |Note: The transmit finish event happens when hardware sends the last bit of TX data from shift data unit. + * |[3] |RXSTIEN |Receive Start Interrupt Enable Bit + * | | |This bit enables the interrupt generation in case of a receive start event. + * | | |0 = The receive start interrupt Disabled. + * | | |1 = The receive start interrupt Enabled. + * | | |Note: For SPI master mode, the receive start event happens when SPI master sends slave select active and spi clock to the external SPI slave. + * | | |For SPI slave mode, the receive start event happens when slave select of SPI slave is active and spi clock of SPI slave is inputed from the external SPI master. + * |[4] |RXENDIEN |Receive End Interrupt Enable Bit + * | | |This bit enables the interrupt generation in case of a receive finish event. + * | | |0 = The receive end interrupt Disabled. + * | | |1 = The receive end interrupt Enabled. + * | | |Note: The receive finish event happens when hardware receives the last bit of RX data into shift data unit. + * @var USPI_T::BRGEN + * Offset: 0x08 USCI Baud Rate Generator Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RCLKSEL |Reference Clock Source Selection + * | | |This bit selects the source of reference clock (fREF_CLK). + * | | |0 = Peripheral device clock fPCLK. + * | | |1 = Reserved. + * |[1] |PTCLKSEL |Protocol Clock Source Selection + * | | |This bit selects the source of protocol clock (fPROT_CLK). + * | | |0 = Reference clock fREF_CLK. + * | | |1 = fREF_CLK2 (its frequency is half of fREF_CLK). + * |[3:2] |SPCLKSEL |Sample Clock Source Selection + * | | |This bit field used for the clock source selection of sample clock (fSAMP_CLK) for the protocol processor. + * | | |00 = fDIV_CLK. + * | | |01 = fPROT_CLK. + * | | |10 = fSCLK. + * | | |11 = fREF_CLK. + * |[4] |TMCNTEN |Time Measurement Counter Enable Bit + * | | |This bit enables the 10-bit timing measurement counter. + * | | |0 = Time measurement counter Disabled. + * | | |1 = Time measurement counter Enabled. + * |[5] |TMCNTSRC |Time Measurement Counter Clock Source Selection + * | | |0 = Time measurement counter with fPROT_CLK. + * | | |1 = Time measurement counter with fDIV_CLK. + * |[25:16] |CLKDIV |Clock Divider + * | | |This bit field defines the ratio between the protocol clock frequency fPROT_CLK and the clock divider frequency fDIV_CLK (fDIV_CLK = fPROT_CLK / (CLKDIV+1) ). + * @var USPI_T::DATIN0 + * Offset: 0x10 USCI Input Data Signal Configuration Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SYNCSEL |Input Signal Synchronization Selection + * | | |This bit selects if the un-synchronized input signal (with optionally inverted) or the synchronized (and optionally filtered) signal, which is synchronized with PCLK, can be used as input for the data shift unit. + * | | |0 = The un-synchronized signal can be taken as input for the data shift unit. + * | | |1 = The synchronized signal can be taken as input for the data shift unit. + * | | |Note: In SPI protocol, it is suggested this bit should be set as 0. + * |[2] |ININV |Input Signal Inverse Selection + * | | |This bit defines the inverter enable of the input asynchronous signal. + * | | |0 = The un-synchronized input signal will not be inverted. + * | | |1 = The un-synchronized input signal will be inverted. + * | | |Note: In SPI protocol, it is suggested this bit should be set as 0. + * @var USPI_T::CTLIN0 + * Offset: 0x20 USCI Input Control Signal Configuration Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SYNCSEL |Input Synchronization Signal Selection + * | | |This bit selects if the un-synchronized input signal (with optionally inverted) or the synchronized (and optionally filtered) signal, which is synchronized with PCLK, can be used as input for the data shift unit. + * | | |0 = The un-synchronized signal can be taken as input for the data shift unit. + * | | |1 = The synchronized signal can be taken as input for the data shift unit. + * | | |Note: In SPI protocol, it is suggested this bit should be set as 0. + * |[2] |ININV |Input Signal Inverse Selection + * | | |This bit defines the inverter enable of the input asynchronous signal. + * | | |0 = The un-synchronized input signal will not be inverted. + * | | |1 = The un-synchronized input signal will be inverted. + * @var USPI_T::CLKIN + * Offset: 0x28 USCI Input Clock Signal Configuration Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SYNCSEL |Input Synchronization Signal Selection + * | | |This bit selects if the un-synchronized input signal or the synchronized (and optionally filtered) signal, which is synchronized with PCLK, can be used as input for the data shift unit. + * | | |0 = The un-synchronized signal can be taken as input for the data shift unit. + * | | |1 = The synchronized signal can be taken as input for the data shift unit. + * | | |Note: In SPI protocol, it is suggested this bit should be set as 0. + * @var USPI_T::LINECTL + * Offset: 0x2C USCI Line Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |LSB |LSB First Transmission Selection + * | | |0 = The MSB, which bit of transmit/receive data buffer depends on the setting of DWIDTH, is transmitted/received first. + * | | |1 = The LSB, the bit 0 of data buffer, will be transmitted/received first. + * |[5] |DATOINV |Data Output Inverse Selection + * | | |This bit defines the relation between the internal shift data value and the output data signal of USCIx_DAT0/1 pin. + * | | |0 = Data output values of USCIx_DAT0/1 pins are not inverted. + * | | |1 = Data output values of USCIx_DAT0/1 pins are inverted. + * |[7] |CTLOINV |Control Signal Output Inverse Selection + * | | |This bit defines the relation between the internal control signal and the output control signal. + * | | |0 = No effect. + * | | |1 = The control signal will be inverted before its output. + * | | |Note: The control signal has different definitions in different protocol. + * | | |In SPI protocol, the control signal means slave select signal. + * |[11:8] |DWIDTH |Word Length of Transmission + * | | |This bit field defines the data word length (amount of bits) for reception and transmission. + * | | |The data word is always right-aligned in the data buffer. + * | | |USCI support word length from 4 to 16 bits. + * | | |0x0: The data word contains 16 bits located at bit positions [15:0]. + * | | |0x1: Reserved. + * | | |0x2: Reserved. + * | | |0x3: Reserved. + * | | |0x4: The data word contains 4 bits located at bit positions [3:0]. + * | | |0x5: The data word contains 5 bits located at bit positions [4:0]. + * | | |... + * | | |0xF: The data word contains 15 bits located at bit positions [14:0]. + * @var USPI_T::TXDAT + * Offset: 0x30 USCI Transmit Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |TXDAT |Transmit Data + * | | |Software can use this bit field to write 16-bit transmit data for transmission. + * | | |In order to avoid overwriting the transmit data, user have to check TXEMPTY (USPI_BUFSTS[8]) status before writing transmit data into this bit field. + * |[16] |PORTDIR |Port Direction Control + * | | |This bit field is only available while USCI operates in SPI protocol (FUNMODE = 0x1) with half-duplex transfer. + * | | |It is used to define the direction of the data port pin. + * | | |When software writes USPI_TXDAT register, the transmit data and its port direction are settled simultaneously. + * | | |0 = The data pin is configured as output mode. + * | | |1 = The data pin is configured as input mode. + * @var USPI_T::RXDAT + * Offset: 0x34 USCI Receive Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RXDAT |Received Data + * | | |This bit field monitors the received data which stored in receive data buffer. + * @var USPI_T::BUFCTL + * Offset: 0x38 USCI Transmit/Receive Buffer Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[6] |TXUDRIEN |Slave Transmit Under Run Interrupt Enable Bit + * | | |0 = Transmit under-run interrupt Disabled. + * | | |1 = Transmit under-run interrupt Enabled. + * |[7] |TXCLR |Clear Transmit Buffer + * | | |0 = No effect. + * | | |1 = The transmit buffer is cleared. + * | | |Should only be used while the buffer is not taking part in data traffic. + * | | |Note: It is cleared automatically after one PCLK cycle. + * |[14] |RXOVIEN |Receive Buffer Overrun Interrupt Enable Bit + * | | |0 = Receive overrun interrupt Disabled. + * | | |1 = Receive overrun interrupt Enabled. + * |[15] |RXCLR |Clear Receive Buffer + * | | |0 = No effect. + * | | |1 = The receive buffer is cleared. + * | | |Should only be used while the buffer is not taking part in data traffic. + * | | |Note: It is cleared automatically after one PCLK cycle. + * |[16] |TXRST |Transmit Reset + * | | |0 = No effect. + * | | |1 = Reset the transmit-related counters, state machine, and the content of transmit shift register and data buffer. + * | | |Note1: It is cleared automatically after one PCLK cycle. + * | | |Note2: Write 1 to this bit will set the output data pin to zero if USPI_PROTCTL[28]=0. + * |[17] |RXRST |Receive Reset + * | | |0 = No effect. + * | | |1 = Reset the receive-related counters, state machine, and the content of receive shift register and data buffer. + * | | |Note: It is cleared automatically after one PCLK cycle. + * @var USPI_T::BUFSTS + * Offset: 0x3C USCI Transmit/Receive Buffer Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RXEMPTY |Receive Buffer Empty Indicator + * | | |0 = Receive buffer is not empty. + * | | |1 = Receive buffer is empty. + * |[1] |RXFULL |Receive Buffer Full Indicator + * | | |0 = Receive buffer is not full. + * | | |1 = Receive buffer is full. + * |[3] |RXOVIF |Receive Buffer Over-run Interrupt Status + * | | |This bit indicates that a receive buffer overrun event has been detected. + * | | |If RXOVIEN (USPI_BUFCTL[14]) is enabled, the corresponding interrupt request is activated. + * | | |It is cleared by software writes 1 to this bit. + * | | |0 = A receive buffer overrun event has not been detected. + * | | |1 = A receive buffer overrun event has been detected. + * |[8] |TXEMPTY |Transmit Buffer Empty Indicator + * | | |0 = Transmit buffer is not empty. + * | | |1 = Transmit buffer is empty and available for the next transmission datum. + * |[9] |TXFULL |Transmit Buffer Full Indicator + * | | |0 = Transmit buffer is not full. + * | | |1 = Transmit buffer is full. + * |[11] |TXUDRIF |Transmit Buffer Under-run Interrupt Status + * | | |This bit indicates that a transmit buffer under-run event has been detected. + * | | |If enabled by TXUDRIEN (USPI_BUFCTL[6]), the corresponding interrupt request is activated. + * | | |It is cleared by software writes 1 to this bit. + * | | |0 = A transmit buffer under-run event has not been detected. + * | | |1 = A transmit buffer under-run event has been detected. + * @var USPI_T::PDMACTL + * Offset: 0x40 USCI PDMA Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |PDMARST |PDMA Reset + * | | |0 = No effect. + * | | |1 = Reset the USCI's PDMA control logic. This bit will be cleared to 0 automatically. + * |[1] |TXPDMAEN |PDMA Transmit Channel Available + * | | |0 = Transmit PDMA function Disabled. + * | | |1 = Transmit PDMA function Enabled. + * |[2] |RXPDMAEN |PDMA Receive Channel Available + * | | |0 = Receive PDMA function Disabled. + * | | |1 = Receive PDMA function Enabled. + * |[3] |PDMAEN |PDMA Mode Enable Bit + * | | |0 = PDMA function Disabled. + * | | |1 = PDMA function Enabled. + * @var USPI_T::WKCTL + * Offset: 0x54 USCI Wake-up Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WKEN |Wake-up Enable Bit + * | | |0 = Wake-up function Disabled. + * | | |1 = Wake-up function Enabled. + * |[2] |PDBOPT |Power Down Blocking Option + * | | |0 = If user attempts to enter Power-down mode by executing WFI while the protocol is in transferring, MCU will stop the transfer and enter Power-down mode immediately. + * | | |1 = If user attempts to enter Power-down mode by executing WFI while the protocol is in transferring, the on-going transfer will not be stopped and MCU will enter idle mode immediately. + * @var USPI_T::WKSTS + * Offset: 0x58 USCI Wake-up Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WKF |Wake-up Flag + * | | |When chip is woken up from Power-down mode, this bit is set to 1. + * | | |Software can write 1 to clear this bit. + * @var USPI_T::PROTCTL + * Offset: 0x5C USCI Protocol Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SLAVE |Slave Mode Selection + * | | |0 = Master mode. + * | | |1 = Slave mode. + * |[1] |SLV3WIRE |Slave 3-wire Mode Selection (Slave Only) + * | | |The SPI protocol can work with 3-wire interface (without slave select signal) in Slave mode. + * | | |0 = 4-wire bi-direction interface. + * | | |1 = 3-wire bi-direction interface. + * |[2] |SS |Slave Select Control (Master Only) + * | | |If AUTOSS bit is cleared, setting this bit to 1 will set the slave select signal to active state, and setting this bit to 0 will set the slave select back to inactive state. + * | | |If the AUTOSS function is enabled (AUTOSS = 1), the setting value of this bit will not affect the current state of slave select signal. + * | | |Note: In SPI protocol, the internal slave select signal is active high. + * |[3] |AUTOSS |Automatic Slave Select Function Enable (Master Only) + * | | |0 = Slave select signal will be controlled by the setting value of SS (USPI_PROTCTL[2]) bit. + * | | |1 = Slave select signal will be generated automatically. + * | | |The slave select signal will be asserted by the SPI controller when transmit/receive is started, and will be de-asserted after each transmit/receive is finished. + * |[7:6] |SCLKMODE |Serial Bus Clock Mode + * | | |This bit field defines the SCLK idle status, data transmit, and data receive edge. + * | | |MODE0 = The idle state of SPI clock is low level. + * | | |Data is transmitted with falling edge and received with rising edge. + * | | |MODE1 = The idle state of SPI clock is low level. + * | | |Data is transmitted with rising edge and received with falling edge. + * | | |MODE2 = The idle state of SPI clock is high level. + * | | |Data is transmitted with rising edge and received with falling edge. + * | | |MODE3 = The idle state of SPI clock is high level. + * | | |Data is transmitted with falling edge and received with rising edge. + * |[11:8] |SUSPITV |Suspend Interval (Master Only) + * | | |This bit field provides the configurable suspend interval between two successive transmit/receive transaction in a transfer. + * | | |The definition of the suspend interval is the interval between the last clock edge of the preceding transaction word and the first clock edge of the following transaction word. + * | | |The default value is 0x3. + * | | |The period of the suspend interval is obtained according to the following equation. + * | | |(SUSPITV[3:0] + 0.5) * period of SPI_CLK clock cycle + * | | |Example: + * | | |SUSPITV = 0x0 ... 0.5 SPI_CLK clock cycle. + * | | |SUSPITV = 0x1 ... 1.5 SPI_CLK clock cycle. + * | | |... + * | | |SUSPITV = 0xE ... 14.5 SPI_CLK clock cycle. + * | | |SUSPITV = 0xF ... 15.5 SPI_CLK clock cycle. + * |[14:12] |TSMSEL |Transmit Data Mode Selection + * | | |This bit field describes how receive and transmit data is shifted in and out. + * | | |TSMSEL = 000b: Full-duplex SPI. + * | | |TSMSEL = 100b: Half-duplex SPI. + * | | |Other values are reserved. + * | | |Note: Changing the value of this bit field will produce the TXRST and RXRST to clear the TX/RX data buffer automatically. + * |[25:16] |SLVTOCNT |Slave Mode Time-out Period (Slave Only) + * | | |In Slave mode, this bit field is used for Slave time-out period. + * | | |This bit field indicates how many clock periods (selected by TMCNTSRC, USPI_BRGEN[5]) between the two edges of input SCLK will assert the Slave time-out event. + * | | |Writing 0x0 into this bit field will disable the Slave time-out function. + * | | |Example: Assume SLVTOCNT is 0x0A and TMCNTSRC (USPI_BRGEN[5]) is 1, it means the time-out event will occur if the state of SPI bus clock pin is not changed more than (10+1) periods of fDIV_CLK. + * |[28] |TXUDRPOL |Transmit Under-run Data Polarity (for Slave) + * | | |This bit defines the transmitting data value of USCIx_DAT1 when no data is available for transferring. + * | | |0 = The output data value is 0 if TX under run event occurs. + * | | |1 = The output data value is 1 if TX under run event occurs. + * |[31] |PROTEN |SPI Protocol Enable Bit + * | | |0 = SPI Protocol Disabled. + * | | |1 = SPI Protocol Enabled. + * @var USPI_T::PROTIEN + * Offset: 0x60 USCI Protocol Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SSINAIEN |Slave Select Inactive Interrupt Enable Bit + * | | |This bit enables/disables the generation of a slave select interrupt if the slave select changes to inactive. + * | | |0 = Slave select inactive interrupt generation Disabled. + * | | |1 = Slave select inactive interrupt generation Enabled. + * |[1] |SSACTIEN |Slave Select Active Interrupt Enable Bit + * | | |This bit enables/disables the generation of a slave select interrupt if the slave select changes to active. + * | | |0 = Slave select active interrupt generation Disabled. + * | | |1 = Slave select active interrupt generation Enabled. + * |[2] |SLVTOIEN |Slave Time-out Interrupt Enable Bit + * | | |In SPI protocol, this bit enables the interrupt generation in case of a Slave time-out event. + * | | |0 = The Slave time-out interrupt Disabled. + * | | |1 = The Slave time-out interrupt Enabled. + * |[3] |SLVBEIEN |Slave Mode Bit Count Error Interrupt Enable Bit + * | | |If data transfer is terminated by slave time-out or slave select inactive event in Slave mode, so that the transmit/receive data bit count does not match the setting of DWIDTH (USPI_LINECTL[11:8]). + * | | |Bit count error event occurs. + * | | |0 = The Slave mode bit count error interrupt Disabled. + * | | |1 = The Slave mode bit count error interrupt Enabled. + * @var USPI_T::PROTSTS + * Offset: 0x64 USCI Protocol Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |TXSTIF |Transmit Start Interrupt Flag + * | | |0 = Transmit start event did not occur. + * | | |1 = Transmit start event occurred. + * | | |Note: It is cleared by software write 1 to this bit. + * | | |The transmit start event happens when hardware starts to move TX data from data buffer to shift data unit. + * |[2] |TXENDIF |Transmit End Interrupt Flag + * | | |0 = Transmit end event did not occur. + * | | |1 = Transmit end event occurred. + * | | |Note: It is cleared by software write 1 to this bit. + * | | |The transmit end event happens when hardware sends the last bit of TX data from shift data unit. + * |[3] |RXSTIF |Receive Start Interrupt Flag + * | | |0 = Receive start event did not occur. + * | | |1 = Receive start event occurred. + * | | |Note: It is cleared by software write 1 to this bit. + * | | |For SPI master mode, the receive start event happens when SPI master sends slave select active and spi clock to the external SPI slave. + * | | |For SPI slave mode, the receive start event happens when slave select of SPI slave is active and spi clock of SPI slave is inputed from the external SPI master. + * |[4] |RXENDIF |Receive End Interrupt Flag + * | | |0 = Receive end event did not occur. + * | | |1 = Receive end event occurred. + * | | |Note: It is cleared by software write 1 to this bit. + * | | |The receive end event happens when hardware receives the last bit of RX data into shift data unit. + * |[5] |SLVTOIF |Slave Time-out Interrupt Flag (for Slave Only) + * | | |0 = Slave time-out event did not occur. + * | | |1 = Slave time-out event occurred. + * | | |Note: It is cleared by software write 1 to this bit. + * |[6] |SLVBEIF |Slave Bit Count Error Interrupt Flag (for Slave Only) + * | | |0 = Slave bit count error event did not occur. + * | | |1 = Slave bit count error event occurred. + * | | |Note: It is cleared by software write 1 to this bit. + * | | |If the transmit/receive data bit count does not match the setting of DWIDTH (USPI_LINECTL[11:8]), bit count error event occurs.It is cleared by software write 1 to this bit. + * |[8] |SSINAIF |Slave Select Inactive Interrupt Flag (for Slave Only) + * | | |This bit indicates that the internal slave select signal has changed to inactive. + * | | |It is cleared by software writes 1 to this bit. + * | | |0 = The slave select signal has not changed to inactive. + * | | |1 = The slave select signal has changed to inactive. + * | | |Note: The internal slave select signal is active high. + * |[9] |SSACTIF |Slave Select Active Interrupt Flag (for Slave Only) + * | | |This bit indicates that the internal slave select signal has changed to active. + * | | |It is cleared by software writes one to this bit. + * | | |0 = The slave select signal has not changed to active. + * | | |1 = The slave select signal has changed to active. + * | | |Note: The internal slave select signal is active high. + * |[16] |SSLINE |Slave Select Line Bus Status (Read Only) + * | | |This bit is only available in Slave mode. + * | | |It used to monitor the current status of the input slave select signal on the bus. + * | | |0 = The slave select line status is 0. + * | | |1 = The slave select line status is 1. + * |[17] |BUSY |Busy Status (Read Only) + * | | |0 = SPI is in idle state. + * | | |1 = SPI is in busy state. + * | | |The following listing are the bus busy conditions: + * | | |a. USPI_PROTCTL[31] = 1 and the TXEMPTY = 0. + * | | |b. For SPI Master mode, the TXEMPTY = 1 but the current transaction is not finished yet. + * | | |c. For SPI Slave mode, the USPI_PROTCTL[31] = 1 and there is serial clock input into the SPI core logic when slave select is active. + * | | |d. For SPI Slave mode, the USPI_PROTCTL[31] = 1 and the transmit buffer or transmit shift register is not empty even if the slave select is inactive. + * |[18] |SLVUDR |Slave Mode Transmit Under-run Status (Read Only) + * | | |In Slave mode, if there is no available transmit data in buffer while transmit data shift out caused by input serial bus clock, this status flag will be set to 1. + * | | |This bit indicates whether the current shift-out data of word transmission is switched to TXUDRPOL (USPI_PROTCTL[28]) or not. + * | | |0 = Slave transmit under run event does not occur. + * | | |1 = Slave transmit under run event occurs. + */ + __IO uint32_t CTL; /*!< [0x0000] USCI Control Register */ + __IO uint32_t INTEN; /*!< [0x0004] USCI Interrupt Enable Register */ + __IO uint32_t BRGEN; /*!< [0x0008] USCI Baud Rate Generator Register */ + __I uint32_t RESERVE0[1]; + __IO uint32_t DATIN0; /*!< [0x0010] USCI Input Data Signal Configuration Register 0 */ + __I uint32_t RESERVE1[3]; + __IO uint32_t CTLIN0; /*!< [0x0020] USCI Input Control Signal Configuration Register 0 */ + __I uint32_t RESERVE2[1]; + __IO uint32_t CLKIN; /*!< [0x0028] USCI Input Clock Signal Configuration Register */ + __IO uint32_t LINECTL; /*!< [0x002c] USCI Line Control Register */ + __O uint32_t TXDAT; /*!< [0x0030] USCI Transmit Data Register */ + __I uint32_t RXDAT; /*!< [0x0034] USCI Receive Data Register */ + __IO uint32_t BUFCTL; /*!< [0x0038] USCI Transmit/Receive Buffer Control Register */ + __IO uint32_t BUFSTS; /*!< [0x003c] USCI Transmit/Receive Buffer Status Register */ + __IO uint32_t PDMACTL; /*!< [0x0040] USCI PDMA Control Register */ + __I uint32_t RESERVE3[4]; + __IO uint32_t WKCTL; /*!< [0x0054] USCI Wake-up Control Register */ + __IO uint32_t WKSTS; /*!< [0x0058] USCI Wake-up Status Register */ + __IO uint32_t PROTCTL; /*!< [0x005c] USCI Protocol Control Register */ + __IO uint32_t PROTIEN; /*!< [0x0060] USCI Protocol Interrupt Enable Register */ + __IO uint32_t PROTSTS; /*!< [0x0064] USCI Protocol Status Register */ + +} USPI_T; + +/** + @addtogroup USPI_CONST USPI Bit Field Definition + Constant Definitions for USPI Controller +@{ */ + +#define USPI_CTL_FUNMODE_Pos (0) /*!< USPI_T::CTL: FUNMODE Position */ +#define USPI_CTL_FUNMODE_Msk (0x7ul << USPI_CTL_FUNMODE_Pos) /*!< USPI_T::CTL: FUNMODE Mask */ + +#define USPI_INTEN_TXSTIEN_Pos (1) /*!< USPI_T::INTEN: TXSTIEN Position */ +#define USPI_INTEN_TXSTIEN_Msk (0x1ul << USPI_INTEN_TXSTIEN_Pos) /*!< USPI_T::INTEN: TXSTIEN Mask */ + +#define USPI_INTEN_TXENDIEN_Pos (2) /*!< USPI_T::INTEN: TXENDIEN Position */ +#define USPI_INTEN_TXENDIEN_Msk (0x1ul << USPI_INTEN_TXENDIEN_Pos) /*!< USPI_T::INTEN: TXENDIEN Mask */ + +#define USPI_INTEN_RXSTIEN_Pos (3) /*!< USPI_T::INTEN: RXSTIEN Position */ +#define USPI_INTEN_RXSTIEN_Msk (0x1ul << USPI_INTEN_RXSTIEN_Pos) /*!< USPI_T::INTEN: RXSTIEN Mask */ + +#define USPI_INTEN_RXENDIEN_Pos (4) /*!< USPI_T::INTEN: RXENDIEN Position */ +#define USPI_INTEN_RXENDIEN_Msk (0x1ul << USPI_INTEN_RXENDIEN_Pos) /*!< USPI_T::INTEN: RXENDIEN Mask */ + +#define USPI_BRGEN_RCLKSEL_Pos (0) /*!< USPI_T::BRGEN: RCLKSEL Position */ +#define USPI_BRGEN_RCLKSEL_Msk (0x1ul << USPI_BRGEN_RCLKSEL_Pos) /*!< USPI_T::BRGEN: RCLKSEL Mask */ + +#define USPI_BRGEN_PTCLKSEL_Pos (1) /*!< USPI_T::BRGEN: PTCLKSEL Position */ +#define USPI_BRGEN_PTCLKSEL_Msk (0x1ul << USPI_BRGEN_PTCLKSEL_Pos) /*!< USPI_T::BRGEN: PTCLKSEL Mask */ + +#define USPI_BRGEN_SPCLKSEL_Pos (2) /*!< USPI_T::BRGEN: SPCLKSEL Position */ +#define USPI_BRGEN_SPCLKSEL_Msk (0x3ul << USPI_BRGEN_SPCLKSEL_Pos) /*!< USPI_T::BRGEN: SPCLKSEL Mask */ + +#define USPI_BRGEN_TMCNTEN_Pos (4) /*!< USPI_T::BRGEN: TMCNTEN Position */ +#define USPI_BRGEN_TMCNTEN_Msk (0x1ul << USPI_BRGEN_TMCNTEN_Pos) /*!< USPI_T::BRGEN: TMCNTEN Mask */ + +#define USPI_BRGEN_TMCNTSRC_Pos (5) /*!< USPI_T::BRGEN: TMCNTSRC Position */ +#define USPI_BRGEN_TMCNTSRC_Msk (0x1ul << USPI_BRGEN_TMCNTSRC_Pos) /*!< USPI_T::BRGEN: TMCNTSRC Mask */ + +#define USPI_BRGEN_CLKDIV_Pos (16) /*!< USPI_T::BRGEN: CLKDIV Position */ +#define USPI_BRGEN_CLKDIV_Msk (0x3fful << USPI_BRGEN_CLKDIV_Pos) /*!< USPI_T::BRGEN: CLKDIV Mask */ + +#define USPI_DATIN0_SYNCSEL_Pos (0) /*!< USPI_T::DATIN0: SYNCSEL Position */ +#define USPI_DATIN0_SYNCSEL_Msk (0x1ul << USPI_DATIN0_SYNCSEL_Pos) /*!< USPI_T::DATIN0: SYNCSEL Mask */ + +#define USPI_DATIN0_ININV_Pos (2) /*!< USPI_T::DATIN0: ININV Position */ +#define USPI_DATIN0_ININV_Msk (0x1ul << USPI_DATIN0_ININV_Pos) /*!< USPI_T::DATIN0: ININV Mask */ + +#define USPI_CTLIN0_SYNCSEL_Pos (0) /*!< USPI_T::CTLIN0: SYNCSEL Position */ +#define USPI_CTLIN0_SYNCSEL_Msk (0x1ul << USPI_CTLIN0_SYNCSEL_Pos) /*!< USPI_T::CTLIN0: SYNCSEL Mask */ + +#define USPI_CTLIN0_ININV_Pos (2) /*!< USPI_T::CTLIN0: ININV Position */ +#define USPI_CTLIN0_ININV_Msk (0x1ul << USPI_CTLIN0_ININV_Pos) /*!< USPI_T::CTLIN0: ININV Mask */ + +#define USPI_CLKIN_SYNCSEL_Pos (0) /*!< USPI_T::CLKIN: SYNCSEL Position */ +#define USPI_CLKIN_SYNCSEL_Msk (0x1ul << USPI_CLKIN_SYNCSEL_Pos) /*!< USPI_T::CLKIN: SYNCSEL Mask */ + +#define USPI_LINECTL_LSB_Pos (0) /*!< USPI_T::LINECTL: LSB Position */ +#define USPI_LINECTL_LSB_Msk (0x1ul << USPI_LINECTL_LSB_Pos) /*!< USPI_T::LINECTL: LSB Mask */ + +#define USPI_LINECTL_DATOINV_Pos (5) /*!< USPI_T::LINECTL: DATOINV Position */ +#define USPI_LINECTL_DATOINV_Msk (0x1ul << USPI_LINECTL_DATOINV_Pos) /*!< USPI_T::LINECTL: DATOINV Mask */ + +#define USPI_LINECTL_CTLOINV_Pos (7) /*!< USPI_T::LINECTL: CTLOINV Position */ +#define USPI_LINECTL_CTLOINV_Msk (0x1ul << USPI_LINECTL_CTLOINV_Pos) /*!< USPI_T::LINECTL: CTLOINV Mask */ + +#define USPI_LINECTL_DWIDTH_Pos (8) /*!< USPI_T::LINECTL: DWIDTH Position */ +#define USPI_LINECTL_DWIDTH_Msk (0xful << USPI_LINECTL_DWIDTH_Pos) /*!< USPI_T::LINECTL: DWIDTH Mask */ + +#define USPI_TXDAT_TXDAT_Pos (0) /*!< USPI_T::TXDAT: TXDAT Position */ +#define USPI_TXDAT_TXDAT_Msk (0xfffful << USPI_TXDAT_TXDAT_Pos) /*!< USPI_T::TXDAT: TXDAT Mask */ + +#define USPI_TXDAT_PORTDIR_Pos (16) /*!< USPI_T::TXDAT: PORTDIR Position */ +#define USPI_TXDAT_PORTDIR_Msk (0x1ul << USPI_TXDAT_PORTDIR_Pos) /*!< USPI_T::TXDAT: PORTDIR Mask */ + +#define USPI_RXDAT_RXDAT_Pos (0) /*!< USPI_T::RXDAT: RXDAT Position */ +#define USPI_RXDAT_RXDAT_Msk (0xfffful << USPI_RXDAT_RXDAT_Pos) /*!< USPI_T::RXDAT: RXDAT Mask */ + +#define USPI_BUFCTL_TXUDRIEN_Pos (6) /*!< USPI_T::BUFCTL: TXUDRIEN Position */ +#define USPI_BUFCTL_TXUDRIEN_Msk (0x1ul << USPI_BUFCTL_TXUDRIEN_Pos) /*!< USPI_T::BUFCTL: TXUDRIEN Mask */ + +#define USPI_BUFCTL_TXCLR_Pos (7) /*!< USPI_T::BUFCTL: TXCLR Position */ +#define USPI_BUFCTL_TXCLR_Msk (0x1ul << USPI_BUFCTL_TXCLR_Pos) /*!< USPI_T::BUFCTL: TXCLR Mask */ + +#define USPI_BUFCTL_RXOVIEN_Pos (14) /*!< USPI_T::BUFCTL: RXOVIEN Position */ +#define USPI_BUFCTL_RXOVIEN_Msk (0x1ul << USPI_BUFCTL_RXOVIEN_Pos) /*!< USPI_T::BUFCTL: RXOVIEN Mask */ + +#define USPI_BUFCTL_RXCLR_Pos (15) /*!< USPI_T::BUFCTL: RXCLR Position */ +#define USPI_BUFCTL_RXCLR_Msk (0x1ul << USPI_BUFCTL_RXCLR_Pos) /*!< USPI_T::BUFCTL: RXCLR Mask */ + +#define USPI_BUFCTL_TXRST_Pos (16) /*!< USPI_T::BUFCTL: TXRST Position */ +#define USPI_BUFCTL_TXRST_Msk (0x1ul << USPI_BUFCTL_TXRST_Pos) /*!< USPI_T::BUFCTL: TXRST Mask */ + +#define USPI_BUFCTL_RXRST_Pos (17) /*!< USPI_T::BUFCTL: RXRST Position */ +#define USPI_BUFCTL_RXRST_Msk (0x1ul << USPI_BUFCTL_RXRST_Pos) /*!< USPI_T::BUFCTL: RXRST Mask */ + +#define USPI_BUFSTS_RXEMPTY_Pos (0) /*!< USPI_T::BUFSTS: RXEMPTY Position */ +#define USPI_BUFSTS_RXEMPTY_Msk (0x1ul << USPI_BUFSTS_RXEMPTY_Pos) /*!< USPI_T::BUFSTS: RXEMPTY Mask */ + +#define USPI_BUFSTS_RXFULL_Pos (1) /*!< USPI_T::BUFSTS: RXFULL Position */ +#define USPI_BUFSTS_RXFULL_Msk (0x1ul << USPI_BUFSTS_RXFULL_Pos) /*!< USPI_T::BUFSTS: RXFULL Mask */ + +#define USPI_BUFSTS_RXOVIF_Pos (3) /*!< USPI_T::BUFSTS: RXOVIF Position */ +#define USPI_BUFSTS_RXOVIF_Msk (0x1ul << USPI_BUFSTS_RXOVIF_Pos) /*!< USPI_T::BUFSTS: RXOVIF Mask */ + +#define USPI_BUFSTS_TXEMPTY_Pos (8) /*!< USPI_T::BUFSTS: TXEMPTY Position */ +#define USPI_BUFSTS_TXEMPTY_Msk (0x1ul << USPI_BUFSTS_TXEMPTY_Pos) /*!< USPI_T::BUFSTS: TXEMPTY Mask */ + +#define USPI_BUFSTS_TXFULL_Pos (9) /*!< USPI_T::BUFSTS: TXFULL Position */ +#define USPI_BUFSTS_TXFULL_Msk (0x1ul << USPI_BUFSTS_TXFULL_Pos) /*!< USPI_T::BUFSTS: TXFULL Mask */ + +#define USPI_BUFSTS_TXUDRIF_Pos (11) /*!< USPI_T::BUFSTS: TXUDRIF Position */ +#define USPI_BUFSTS_TXUDRIF_Msk (0x1ul << USPI_BUFSTS_TXUDRIF_Pos) /*!< USPI_T::BUFSTS: TXUDRIF Mask */ + +#define USPI_PDMACTL_PDMARST_Pos (0) /*!< USPI_T::PDMACTL: PDMARST Position */ +#define USPI_PDMACTL_PDMARST_Msk (0x1ul << USPI_PDMACTL_PDMARST_Pos) /*!< USPI_T::PDMACTL: PDMARST Mask */ + +#define USPI_PDMACTL_TXPDMAEN_Pos (1) /*!< USPI_T::PDMACTL: TXPDMAEN Position */ +#define USPI_PDMACTL_TXPDMAEN_Msk (0x1ul << USPI_PDMACTL_TXPDMAEN_Pos) /*!< USPI_T::PDMACTL: TXPDMAEN Mask */ + +#define USPI_PDMACTL_RXPDMAEN_Pos (2) /*!< USPI_T::PDMACTL: RXPDMAEN Position */ +#define USPI_PDMACTL_RXPDMAEN_Msk (0x1ul << USPI_PDMACTL_RXPDMAEN_Pos) /*!< USPI_T::PDMACTL: RXPDMAEN Mask */ + +#define USPI_PDMACTL_PDMAEN_Pos (3) /*!< USPI_T::PDMACTL: PDMAEN Position */ +#define USPI_PDMACTL_PDMAEN_Msk (0x1ul << USPI_PDMACTL_PDMAEN_Pos) /*!< USPI_T::PDMACTL: PDMAEN Mask */ + +#define USPI_WKCTL_WKEN_Pos (0) /*!< USPI_T::WKCTL: WKEN Position */ +#define USPI_WKCTL_WKEN_Msk (0x1ul << USPI_WKCTL_WKEN_Pos) /*!< USPI_T::WKCTL: WKEN Mask */ + +#define USPI_WKCTL_PDBOPT_Pos (2) /*!< USPI_T::WKCTL: PDBOPT Position */ +#define USPI_WKCTL_PDBOPT_Msk (0x1ul << USPI_WKCTL_PDBOPT_Pos) /*!< USPI_T::WKCTL: PDBOPT Mask */ + +#define USPI_WKSTS_WKF_Pos (0) /*!< USPI_T::WKSTS: WKF Position */ +#define USPI_WKSTS_WKF_Msk (0x1ul << USPI_WKSTS_WKF_Pos) /*!< USPI_T::WKSTS: WKF Mask */ + +#define USPI_PROTCTL_SLAVE_Pos (0) /*!< USPI_T::PROTCTL: SLAVE Position */ +#define USPI_PROTCTL_SLAVE_Msk (0x1ul << USPI_PROTCTL_SLAVE_Pos) /*!< USPI_T::PROTCTL: SLAVE Mask */ + +#define USPI_PROTCTL_SLV3WIRE_Pos (1) /*!< USPI_T::PROTCTL: SLV3WIRE Position */ +#define USPI_PROTCTL_SLV3WIRE_Msk (0x1ul << USPI_PROTCTL_SLV3WIRE_Pos) /*!< USPI_T::PROTCTL: SLV3WIRE Mask */ + +#define USPI_PROTCTL_SS_Pos (2) /*!< USPI_T::PROTCTL: SS Position */ +#define USPI_PROTCTL_SS_Msk (0x1ul << USPI_PROTCTL_SS_Pos) /*!< USPI_T::PROTCTL: SS Mask */ + +#define USPI_PROTCTL_AUTOSS_Pos (3) /*!< USPI_T::PROTCTL: AUTOSS Position */ +#define USPI_PROTCTL_AUTOSS_Msk (0x1ul << USPI_PROTCTL_AUTOSS_Pos) /*!< USPI_T::PROTCTL: AUTOSS Mask */ + +#define USPI_PROTCTL_SCLKMODE_Pos (6) /*!< USPI_T::PROTCTL: SCLKMODE Position */ +#define USPI_PROTCTL_SCLKMODE_Msk (0x3ul << USPI_PROTCTL_SCLKMODE_Pos) /*!< USPI_T::PROTCTL: SCLKMODE Mask */ + +#define USPI_PROTCTL_SUSPITV_Pos (8) /*!< USPI_T::PROTCTL: SUSPITV Position */ +#define USPI_PROTCTL_SUSPITV_Msk (0xful << USPI_PROTCTL_SUSPITV_Pos) /*!< USPI_T::PROTCTL: SUSPITV Mask */ + +#define USPI_PROTCTL_TSMSEL_Pos (12) /*!< USPI_T::PROTCTL: TSMSEL Position */ +#define USPI_PROTCTL_TSMSEL_Msk (0x7ul << USPI_PROTCTL_TSMSEL_Pos) /*!< USPI_T::PROTCTL: TSMSEL Mask */ + +#define USPI_PROTCTL_SLVTOCNT_Pos (16) /*!< USPI_T::PROTCTL: SLVTOCNT Position */ +#define USPI_PROTCTL_SLVTOCNT_Msk (0x3fful << USPI_PROTCTL_SLVTOCNT_Pos) /*!< USPI_T::PROTCTL: SLVTOCNT Mask */ + +#define USPI_PROTCTL_TXUDRPOL_Pos (28) /*!< USPI_T::PROTCTL: TXUDRPOL Position */ +#define USPI_PROTCTL_TXUDRPOL_Msk (0x1ul << USPI_PROTCTL_TXUDRPOL_Pos) /*!< USPI_T::PROTCTL: TXUDRPOL Mask */ + +#define USPI_PROTCTL_PROTEN_Pos (31) /*!< USPI_T::PROTCTL: PROTEN Position */ +#define USPI_PROTCTL_PROTEN_Msk (0x1ul << USPI_PROTCTL_PROTEN_Pos) /*!< USPI_T::PROTCTL: PROTEN Mask */ + +#define USPI_PROTIEN_SSINAIEN_Pos (0) /*!< USPI_T::PROTIEN: SSINAIEN Position */ +#define USPI_PROTIEN_SSINAIEN_Msk (0x1ul << USPI_PROTIEN_SSINAIEN_Pos) /*!< USPI_T::PROTIEN: SSINAIEN Mask */ + +#define USPI_PROTIEN_SSACTIEN_Pos (1) /*!< USPI_T::PROTIEN: SSACTIEN Position */ +#define USPI_PROTIEN_SSACTIEN_Msk (0x1ul << USPI_PROTIEN_SSACTIEN_Pos) /*!< USPI_T::PROTIEN: SSACTIEN Mask */ + +#define USPI_PROTIEN_SLVTOIEN_Pos (2) /*!< USPI_T::PROTIEN: SLVTOIEN Position */ +#define USPI_PROTIEN_SLVTOIEN_Msk (0x1ul << USPI_PROTIEN_SLVTOIEN_Pos) /*!< USPI_T::PROTIEN: SLVTOIEN Mask */ + +#define USPI_PROTIEN_SLVBEIEN_Pos (3) /*!< USPI_T::PROTIEN: SLVBEIEN Position */ +#define USPI_PROTIEN_SLVBEIEN_Msk (0x1ul << USPI_PROTIEN_SLVBEIEN_Pos) /*!< USPI_T::PROTIEN: SLVBEIEN Mask */ + +#define USPI_PROTSTS_TXSTIF_Pos (1) /*!< USPI_T::PROTSTS: TXSTIF Position */ +#define USPI_PROTSTS_TXSTIF_Msk (0x1ul << USPI_PROTSTS_TXSTIF_Pos) /*!< USPI_T::PROTSTS: TXSTIF Mask */ + +#define USPI_PROTSTS_TXENDIF_Pos (2) /*!< USPI_T::PROTSTS: TXENDIF Position */ +#define USPI_PROTSTS_TXENDIF_Msk (0x1ul << USPI_PROTSTS_TXENDIF_Pos) /*!< USPI_T::PROTSTS: TXENDIF Mask */ + +#define USPI_PROTSTS_RXSTIF_Pos (3) /*!< USPI_T::PROTSTS: RXSTIF Position */ +#define USPI_PROTSTS_RXSTIF_Msk (0x1ul << USPI_PROTSTS_RXSTIF_Pos) /*!< USPI_T::PROTSTS: RXSTIF Mask */ + +#define USPI_PROTSTS_RXENDIF_Pos (4) /*!< USPI_T::PROTSTS: RXENDIF Position */ +#define USPI_PROTSTS_RXENDIF_Msk (0x1ul << USPI_PROTSTS_RXENDIF_Pos) /*!< USPI_T::PROTSTS: RXENDIF Mask */ + +#define USPI_PROTSTS_SLVTOIF_Pos (5) /*!< USPI_T::PROTSTS: SLVTOIF Position */ +#define USPI_PROTSTS_SLVTOIF_Msk (0x1ul << USPI_PROTSTS_SLVTOIF_Pos) /*!< USPI_T::PROTSTS: SLVTOIF Mask */ + +#define USPI_PROTSTS_SLVBEIF_Pos (6) /*!< USPI_T::PROTSTS: SLVBEIF Position */ +#define USPI_PROTSTS_SLVBEIF_Msk (0x1ul << USPI_PROTSTS_SLVBEIF_Pos) /*!< USPI_T::PROTSTS: SLVBEIF Mask */ + +#define USPI_PROTSTS_SSINAIF_Pos (8) /*!< USPI_T::PROTSTS: SSINAIF Position */ +#define USPI_PROTSTS_SSINAIF_Msk (0x1ul << USPI_PROTSTS_SSINAIF_Pos) /*!< USPI_T::PROTSTS: SSINAIF Mask */ + +#define USPI_PROTSTS_SSACTIF_Pos (9) /*!< USPI_T::PROTSTS: SSACTIF Position */ +#define USPI_PROTSTS_SSACTIF_Msk (0x1ul << USPI_PROTSTS_SSACTIF_Pos) /*!< USPI_T::PROTSTS: SSACTIF Mask */ + +#define USPI_PROTSTS_SSLINE_Pos (16) /*!< USPI_T::PROTSTS: SSLINE Position */ +#define USPI_PROTSTS_SSLINE_Msk (0x1ul << USPI_PROTSTS_SSLINE_Pos) /*!< USPI_T::PROTSTS: SSLINE Mask */ + +#define USPI_PROTSTS_BUSY_Pos (17) /*!< USPI_T::PROTSTS: BUSY Position */ +#define USPI_PROTSTS_BUSY_Msk (0x1ul << USPI_PROTSTS_BUSY_Pos) /*!< USPI_T::PROTSTS: BUSY Mask */ + +#define USPI_PROTSTS_SLVUDR_Pos (18) /*!< USPI_T::PROTSTS: SLVUDR Position */ +#define USPI_PROTSTS_SLVUDR_Msk (0x1ul << USPI_PROTSTS_SLVUDR_Pos) /*!< USPI_T::PROTSTS: SLVUDR Mask */ + +/**@}*/ /* USPI_CONST */ +/**@}*/ /* end of USPI register group */ + + +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __USPI_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uuart_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uuart_reg.h new file mode 100644 index 0000000000..68023d166e --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/uuart_reg.h @@ -0,0 +1,666 @@ +/**************************************************************************//** + * @file uuart_reg.h + * @version V1.00 + * @brief UUART register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __UUART_REG_H__ +#define __UUART_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup UUART UART Mode of USCI Controller (UUART) + Memory Mapped Structure for UUART Controller +@{ */ + +typedef struct +{ + + + /** + * @var UUART_T::CTL + * Offset: 0x00 USCI Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[2:0] |FUNMODE |Function Mode + * | | |This bit field selects the protocol for this USCI controller. + * | | |Selecting a protocol that is not available or a reserved combination disables the USCI. + * | | |When switching between two protocols, the USCI has to be disabled before selecting a new protocol. + * | | |Simultaneously, the USCI will be reset when user write 000 to FUNMODE. + * | | |000 = The USCI is disabled. All protocol related state machines are set to idle state. + * | | |001 = The SPI protocol is selected. + * | | |010 = The UART protocol is selected. + * | | |100 = The I2C protocol is selected. + * | | |Note: Other bit combinations are reserved. + * @var UUART_T::INTEN + * Offset: 0x04 USCI Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |TXSTIEN |Transmit Start Interrupt Enable Bit + * | | |This bit enables the interrupt generation in case of a transmit start event. + * | | |0 = The transmit start interrupt Disabled. + * | | |1 = The transmit start interrupt Enabled. + * |[2] |TXENDIEN |Transmit End Interrupt Enable Bit + * | | |This bit enables the interrupt generation in case of a transmit finish event. + * | | |0 = The transmit finish interrupt Disabled. + * | | |1 = The transmit finish interrupt Enabled. + * |[3] |RXSTIEN |Receive Start Interrupt Enable BIt + * | | |This bit enables the interrupt generation in case of a receive start event. + * | | |0 = The receive start interrupt Disabled. + * | | |1 = The receive start interrupt Enabled. + * |[4] |RXENDIEN |Receive End Interrupt Enable Bit + * | | |This bit enables the interrupt generation in case of a receive finish event. + * | | |0 = The receive end interrupt Disabled. + * | | |1 = The receive end interrupt Enabled. + * @var UUART_T::BRGEN + * Offset: 0x08 USCI Baud Rate Generator Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RCLKSEL |Reference Clock Source Selection + * | | |This bit selects the source signal of reference clock (fREF_CLK). + * | | |0 = Peripheral device clock fPCLK. + * | | |1 = Reserved. + * |[1] |PTCLKSEL |Protocol Clock Source Selection + * | | |This bit selects the source signal of protocol clock (fPROT_CLK). + * | | |0 = Reference clock fREF_CLK. + * | | |1 = fREF_CLK2 (its frequency is half of fREF_CLK). + * |[3:2] |SPCLKSEL |Sample Clock Source Selection + * | | |This bit field used for the clock source selection of a sample clock (fSAMP_CLK) for the protocol processor. + * | | |00 = fSAMP_CLK = fDIV_CLK. + * | | |01 = fSAMP_CLK = fPROT_CLK. + * | | |10 = fSAMP_CLK = fSCLK. + * | | |11 = fSAMP_CLK = fREF_CLK. + * |[4] |TMCNTEN |Timing Measurement Counter Enable Bit + * | | |This bit enables the 10-bit timing measurement counter. + * | | |0 = Timing measurement counter is Disabled. + * | | |1 = Timing measurement counter is Enabled. + * |[5] |TMCNTSRC |Timing Measurement Counter Clock Source Selection + * | | |0 = Timing measurement counter with fPROT_CLK. + * | | |1 = Timing measurement counter with fDIV_CLK. + * |[9:8] |PDSCNT |Pre-divider for Sample Counter + * | | |This bit field defines the divide ratio of the clock division from sample clock fSAMP_CLK. + * | | |The divided frequency fPDS_CNT = fSAMP_CLK / (PDSCNT+1). + * |[14:10] |DSCNT |Denominator for Sample Counter + * | | |This bit field defines the divide ratio of the sample clock fSAMP_CLK. + * | | |The divided frequency fDS_CNT = fPDS_CNT / (DSCNT+1). + * | | |Note: The maximum value of DSCNT is 0xF on UART mode and suggest to set over 4 to confirm the receiver data is sampled in right value. + * |[25:16] |CLKDIV |Clock Divider + * | | |This bit field defines the ratio between the protocol clock frequency fPROT_CLK and the clock divider frequency fDIV_CLK (fDIV_CLK = fPROT_CLK / (CLKDIV+1) ). + * | | |Note: In UART function, it can be updated by hardware in the 4th falling edge of the input data 0x55 when the auto baud rate function (ABREN(UUART_PROTCTL[6])) is enabled. + * | | |The revised value is the average bit time between bit 5 and bit 6. + * | | |The user can use revised CLKDIV and new BRDETITV (UUART_PROTCTL[24:16]) to calculate the precise baud rate. + * @var UUART_T::DATIN0 + * Offset: 0x10 USCI Input Data Signal Configuration Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SYNCSEL |Input Signal Synchronization Selection + * | | |This bit selects if the un-synchronized input signal (with optionally inverted) or the synchronized (and optionally filtered) signal can be used as input for the data shift unit. + * | | |0 = The un-synchronized signal can be taken as input for the data shift unit. + * | | |1 = The synchronized signal can be taken as input for the data shift unit. + * |[2] |ININV |Input Signal Inverse Selection + * | | |This bit defines the inverter enable of the input asynchronous signal. + * | | |0 = The un-synchronized input signal will not be inverted. + * | | |1 = The un-synchronized input signal will be inverted. + * |[4:3] |EDGEDET |Input Signal Edge Detection Mode + * | | |This bit field selects which edge actives the trigger event of input data signal. + * | | |00 = The trigger event activation is disabled. + * | | |01 = A rising edge activates the trigger event of input data signal. + * | | |10 = A falling edge activates the trigger event of input data signal. + * | | |11 = Both edges activate the trigger event of input data signal. + * | | |Note: In UART function mode, it is suggested to set this bit field as 10. + * @var UUART_T::CTLIN0 + * Offset: 0x20 USCI Input Control Signal Configuration Register 0 + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SYNCSEL |Input Synchronization Signal Selection + * | | |This bit selects if the un-synchronized input signal (with optionally inverted) or the synchronized (and optionally filtered) signal can be used as input for the data shift unit. + * | | |0 = The un-synchronized signal can be taken as input for the data shift unit. + * | | |1 = The synchronized signal can be taken as input for the data shift unit. + * |[2] |ININV |Input Signal Inverse Selection + * | | |This bit defines the inverter enable of the input asynchronous signal. + * | | |0 = The un-synchronized input signal will not be inverted. + * | | |1 = The un-synchronized input signal will be inverted. + * @var UUART_T::CLKIN + * Offset: 0x28 USCI Input Clock Signal Configuration Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |SYNCSEL |Input Synchronization Signal Selection + * | | |This bit selects if the un-synchronized input signal or the synchronized (and optionally filtered) signal can be used as input for the data shift unit. + * | | |0 = The un-synchronized signal can be taken as input for the data shift unit. + * | | |1 = The synchronized signal can be taken as input for the data shift unit. + * @var UUART_T::LINECTL + * Offset: 0x2C USCI Line Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |LSB |LSB First Transmission Selection + * | | |0 = The MSB, which bit of transmit/receive data buffer depends on the setting of DWIDTH, is transmitted/received first. + * | | |1 = The LSB, the bit 0 of data buffer, will be transmitted/received first. + * |[5] |DATOINV |Data Output Inverse Selection + * | | |This bit defines the relation between the internal shift data value and the output data signal of USCIx_DAT1 pin. + * | | |0 = The value of USCIx_DAT1 is equal to the data shift register. + * | | |1 = The value of USCIx_DAT1 is the inversion of data shift register. + * |[7] |CTLOINV |Control Signal Output Inverse Selection + * | | |This bit defines the relation between the internal control signal and the output control signal. + * | | |0 = No effect. + * | | |1 = The control signal will be inverted before its output. + * | | |Note: In UART protocol, the control signal means nRTS signal. + * |[11:8] |DWIDTH |Word Length of Transmission + * | | |This bit field defines the data word length (amount of bits) for reception and transmission. + * | | |The data word is always right-aligned in the data buffer. + * | | |USCI support word length from 4 to 16 bits. + * | | |0x0: The data word contains 16 bits located at bit positions [15:0]. + * | | |0x1: Reserved. + * | | |0x2: Reserved. + * | | |0x3: Reserved. + * | | |0x4: The data word contains 4 bits located at bit positions [3:0]. + * | | |0x5: The data word contains 5 bits located at bit positions [4:0]. + * | | |... + * | | |0xF: The data word contains 15 bits located at bit positions [14:0]. + * | | |Note: In UART protocol, the length can be configured as 6~13 bits. + * @var UUART_T::TXDAT + * Offset: 0x30 USCI Transmit Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |TXDAT |Transmit Data + * | | |Software can use this bit field to write 16-bit transmit data for transmission. + * @var UUART_T::RXDAT + * Offset: 0x34 USCI Receive Data Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[15:0] |RXDAT |Received Data + * | | |This bit field monitors the received data which stored in receive data buffer. + * | | |Note: RXDAT[15:13] indicate the same frame status of BREAK, FRMERR and PARITYERR (UUART_PROTSTS[7:5]). + * @var UUART_T::BUFCTL + * Offset: 0x38 USCI Transmit/Receive Buffer Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[7] |TXCLR |Clear Transmit Buffer + * | | |0 = No effect. + * | | |1 = The transmit buffer is cleared (filling level is cleared and output pointer is set to input pointer value). + * | | |Should only be used while the buffer is not taking part in data traffic. + * | | |Note: It is cleared automatically after one PCLK cycle. + * |[14] |RXOVIEN |Receive Buffer Overrun Error Interrupt Enable Bit + * | | |0 = Receive overrun interrupt Disabled. + * | | |1 = Receive overrun interrupt Enabled. + * |[15] |RXCLR |Clear Receive Buffer + * | | |0 = No effect. + * | | |1 = The receive buffer is cleared (filling level is cleared and output pointer is set to input pointer value). + * | | |Should only be used while the buffer is not taking part in data traffic. + * | | |Note: It is cleared automatically after one PCLK cycle. + * |[16] |TXRST |Transmit Reset + * | | |0 = No effect. + * | | |1 = Reset the transmit-related counters, state machine, and the content of transmit shift register and data buffer. + * | | |Note: It is cleared automatically after one PCLK cycle. + * |[17] |RXRST |Receive Reset + * | | |0 = No effect. + * | | |1 = Reset the receive-related counters, state machine, and the content of receive shift register and data buffer. + * | | |Note1: It is cleared automatically after one PCLK cycle. + * | | |Note2: It is suggested to check the RXBUSY (UUART_PROTSTS[10]) before this bit will be set to 1. + * @var UUART_T::BUFSTS + * Offset: 0x3C USCI Transmit/Receive Buffer Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |RXEMPTY |Receive Buffer Empty Indicator + * | | |0 = Receive buffer is not empty. + * | | |1 = Receive buffer is empty. + * |[1] |RXFULL |Receive Buffer Full Indicator + * | | |0 = Receive buffer is not full. + * | | |1 = Receive buffer is full. + * |[3] |RXOVIF |Receive Buffer Over-run Error Interrupt Status + * | | |This bit indicates that a receive buffer overrun error event has been detected. + * | | |If RXOVIEN (UUART_BUFCTL[14]) is enabled, the corresponding interrupt request is activated. + * | | |It is cleared by software writes 1 to this bit. + * | | |0 = A receive buffer overrun error event has not been detected. + * | | |1 = A receive buffer overrun error event has been detected. + * |[8] |TXEMPTY |Transmit Buffer Empty Indicator + * | | |0 = Transmit buffer is not empty. + * | | |1 = Transmit buffer is empty. + * |[9] |TXFULL |Transmit Buffer Full Indicator + * | | |0 = Transmit buffer is not full. + * | | |1 = Transmit buffer is full. + * @var UUART_T::PDMACTL + * Offset: 0x40 USCI PDMA Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |PDMARST |PDMA Reset + * | | |0 = No effect. + * | | |1 = Reset the USCI's PDMA control logic. This bit will be cleared to 0 automatically. + * |[1] |TXPDMAEN |PDMA Transmit Channel Available + * | | |0 = Transmit PDMA function Disabled. + * | | |1 = Transmit PDMA function Enabled. + * |[2] |RXPDMAEN |PDMA Receive Channel Available + * | | |0 = Receive PDMA function Disabled. + * | | |1 = Receive PDMA function Enabled. + * |[3] |PDMAEN |PDMA Mode Enable Bit + * | | |0 = PDMA function Disabled. + * | | |1 = PDMA function Enabled. + * @var UUART_T::WKCTL + * Offset: 0x54 USCI Wake-up Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WKEN |Wake-up Enable Bit + * | | |0 = Wake-up function Disabled. + * | | |1 = Wake-up function Enabled. + * |[2] |PDBOPT |Power Down Blocking Option + * | | |0 = If user attempts to enter Power-down mode by executing WFI while the protocol is in transferring, MCU will stop the transfer and enter Power-down mode immediately. + * | | |1 = If user attempts to enter Power-down mode by executing WFI while the protocol is in transferring, the on-going transfer will not be stopped and MCU will enter idle mode immediately. + * @var UUART_T::WKSTS + * Offset: 0x58 USCI Wake-up Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WKF |Wake-up Flag + * | | |When chip is woken up from Power-down mode, this bit is set to 1. + * | | |Software can write 1 to clear this bit. + * @var UUART_T::PROTCTL + * Offset: 0x5C USCI Protocol Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |STOPB |Stop Bits + * | | |This bit defines the number of stop bits in an UART frame. + * | | |0 = The number of stop bits is 1. + * | | |1 = The number of stop bits is 2. + * |[1] |PARITYEN |Parity Enable Bit + * | | |This bit defines the parity bit is enabled in an UART frame. + * | | |0 = The parity bit Disabled. + * | | |1 = The parity bit Enabled. + * |[2] |EVENPARITY|Even Parity Enable Bit + * | | |0 = Odd number of logic 1's is transmitted and checked in each word. + * | | |1 = Even number of logic 1's is transmitted and checked in each word. + * | | |Note: This bit has effect only when PARITYEN is set. + * |[3] |RTSAUTOEN |nRTS Auto-flow Control Enable Bit + * | | |When nRTS auto-flow is enabled, if the receiver buffer is full (RXFULL (UUART_BUFSTS[1] =1), the UART will de-assert nRTS signal. + * | | |0 = nRTS auto-flow control Disabled. + * | | |1 = nRTS auto-flow control Enabled. + * | | |Note: This bit has effect only when the RTSAUDIREN is not set. + * |[4] |CTSAUTOEN |nCTS Auto-flow Control Enable Bit + * | | |When nCTS auto-flow is enabled, the UART will send data to external device when nCTS input assert (UART will not send data to device if nCTS input is dis-asserted). + * | | |0 = nCTS auto-flow control Disabled. + * | | |1 = nCTS auto-flow control Enabled. + * |[5] |RTSAUDIREN|nRTS Auto Direction Enable Bit + * | | |When nRTS auto direction is enabled, if the transmitted bytes in the TX buffer is empty, the UART asserted nRTS signal automatically. + * | | |0 = nRTS auto direction control Disabled. + * | | |1 = nRTS auto direction control Enabled. + * | | |Note 1: This bit is used for nRTS auto direction control for RS485. + * | | |Note 2: This bit has effect only when the RTSAUTOEN is not set. + * |[6] |ABREN |Auto-baud Rate Detect Enable Bit + * | | |0 = Auto-baud rate detect function Disabled. + * | | |1 = Auto-baud rate detect function Enabled. + * | | |Note: When the auto - baud rate detect operation finishes, hardware will clear this bit. + * | | |The associated interrupt ABRDETIF (UUART_PROTST[9]) will be generated (If ARBIEN (UUART_PROTIEN [1]) is enabled). + * |[9] |DATWKEN |Data Wake-up Mode Enable Bit + * | | |0 = Data wake-up mode Disabled. + * | | |1 = Data wake-up mode Enabled. + * |[10] |CTSWKEN |nCTS Wake-up Mode Enable Bit + * | | |0 = nCTS wake-up mode Disabled. + * | | |1 = nCTS wake-up mode Enabled. + * |[14:11] |WAKECNT |Wake-up Counter + * | | |These bits field indicate how many clock cycle selected by fPDS_CNT do the slave can get the 1st bit (start bit) when the device is wake-up from Power-down mode. + * |[24:16] |BRDETITV |Baud Rate Detection Interval + * | | |This bit fields indicate how many clock cycle selected by TMCNTSRC (UUART_BRGEN [5]) does the slave calculates the baud rate in one bits. + * | | |The order of the bus shall be 1 and 0 step by step (e.g. + * | | |the input data pattern shall be 0x55). + * | | |The user can read the value to know the current input baud rate of the bus whenever the ABRDETIF (UUART_PROTSTS[9]) is set. + * | | |Note: This bit can be cleared to 0 by software writing '0' to the BRDETITV. + * |[26] |STICKEN |Stick Parity Enable Bit + * | | |0 = Stick parity Disabled. + * | | |1 = Stick parity Enabled. + * | | |Note: Refer to RS-485 Support section for detailed information. + * |[29] |BCEN |Transmit Break Control Enable Bit + * | | |0 = Transmit Break Control Disabled. + * | | |1 = Transmit Break Control Enabled. + * | | |Note: When this bit is set to logic 1, the serial data output (TX) is forced to the Spacing State (logic 0). + * | | |This bit acts only on TX line and has no effect on the transmitter logic. + * |[31] |PROTEN |UART Protocol Enable Bit + * | | |0 = UART Protocol Disabled. + * | | |1 = UART Protocol Enabled. + * @var UUART_T::PROTIEN + * Offset: 0x60 USCI Protocol Interrupt Enable Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |ABRIEN |Auto-baud Rate Interrupt Enable Bit + * | | |0 = Auto-baud rate interrupt Disabled. + * | | |1 = Auto-baud rate interrupt Enabled. + * |[2] |RLSIEN |Receive Line Status Interrupt Enable Bit + * | | |0 = Receive line status interrupt Disabled. + * | | |1 = Receive line status interrupt Enabled. + * | | |Note: UUART_PROTSTS[7:5] indicates the current interrupt event for receive line status interrupt. + * @var UUART_T::PROTSTS + * Offset: 0x64 USCI Protocol Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |TXSTIF |Transmit Start Interrupt Flag + * | | |0 = A transmit start interrupt status has not occurred. + * | | |1 = A transmit start interrupt status has occurred. + * | | |Note1: It is cleared by software writing one into this bit. + * | | |Note2: Used for user to load next transmit data when there is no data in transmit buffer. + * |[2] |TXENDIF |Transmit End Interrupt Flag + * | | |0 = A transmit end interrupt status has not occurred. + * | | |1 = A transmit end interrupt status has occurred. + * | | |Note: It is cleared by software writing 1 into this bit. + * |[3] |RXSTIF |Receive Start Interrupt Flag + * | | |0 = A receive start interrupt status has not occurred. + * | | |1 = A receive start interrupt status has occurred. + * | | |Note: It is cleared by software writing 1 into this bit. + * |[4] |RXENDIF |Receive End Interrupt Flag + * | | |0 = A receive finish interrupt status has not occurred. + * | | |1 = A receive finish interrupt status has occurred. + * | | |Note: It is cleared by software writing 1 into this bit. + * |[5] |PARITYERR |Parity Error Flag + * | | |This bit is set to logic 1 whenever the received character does not have a valid "parity bit". + * | | |0 = No parity error is generated. + * | | |1 = Parity error is generated. + * | | |Note: This bit can be cleared by writing "1" among the BREAK, FRMERR and PARITYERR bits. + * |[6] |FRMERR |Framing Error Flag + * | | |This bit is set to logic 1 whenever the received character does not have a valid "stop bit" (that is, the stop bit following the last data bit or parity bit is detected as logic 0). + * | | |0 = No framing error is generated. + * | | |1 = Framing error is generated. + * | | |Note: This bit can be cleared by writing "1" among the BREAK, FRMERR and PARITYERR bits. + * |[7] |BREAK |Break Flag + * | | |This bit is set to logic 1 whenever the received data input (RX) is held in the "spacing state" (logic 0) for longer than a full word transmission time (that is, the total time of "start bit" + data bits + parity + stop bits). + * | | |0 = No Break is generated. + * | | |1 = Break is generated in the receiver bus. + * | | |Note: This bit can be cleared by writing "1" among the BREAK, FRMERR and PARITYERR bits. + * |[9] |ABRDETIF |Auto-baud Rate Interrupt Flag + * | | |This bit is set when auto-baud rate detection is done among the falling edge of the input data. + * | | |If the ABRIEN (UUART_PROTCTL[6]) is set, the auto-baud rate interrupt will be generated. + * | | |This bit can be set 4 times when the input data pattern is 0x55 and it is cleared before the next falling edge of the input bus. + * | | |0 = Auto-baud rate detect function is not done. + * | | |1 = One Bit auto-baud rate detect function is done. + * | | |Note: This bit can be cleared by writing "1" to it. + * |[10] |RXBUSY |RX Bus Status Flag (Read Only) + * | | |This bit indicates the busy status of the receiver. + * | | |0 = The receiver is Idle. + * | | |1 = The receiver is BUSY. + * |[11] |ABERRSTS |Auto-baud Rate Error Status + * | | |This bit is set when auto-baud rate detection counter overrun. + * | | |When the auto-baud rate counter overrun, the user shall revise the CLKDIV (UUART_BRGEN[25:16]) value and enable ABREN (UUART_PROTCTL[6]) to detect the correct baud rate again. + * | | |0 = Auto-baud rate detect counter is not overrun. + * | | |1 = Auto-baud rate detect counter is overrun. + * | | |Note 1: This bit is set at the same time of ABRDETIF. + * | | |Note 2: This bit can be cleared by writing "1" to ABRDETIF or ABERRSTS. + * |[16] |CTSSYNCLV |nCTS Synchronized Level Status (Read Only) + * | | |This bit used to indicate the current status of the internal synchronized nCTS signal. + * | | |0 = The internal synchronized nCTS is low. + * | | |1 = The internal synchronized nCTS is high. + * |[17] |CTSLV |nCTS Pin Status (Read Only) + * | | |This bit used to monitor the current status of nCTS pin input. + * | | |0 = nCTS pin input is low level voltage logic state. + * | | |1 = nCTS pin input is high level voltage logic state. + */ + __IO uint32_t CTL; /*!< [0x0000] USCI Control Register */ + __IO uint32_t INTEN; /*!< [0x0004] USCI Interrupt Enable Register */ + __IO uint32_t BRGEN; /*!< [0x0008] USCI Baud Rate Generator Register */ + __I uint32_t RESERVE0[1]; + __IO uint32_t DATIN0; /*!< [0x0010] USCI Input Data Signal Configuration Register 0 */ + __I uint32_t RESERVE1[3]; + __IO uint32_t CTLIN0; /*!< [0x0020] USCI Input Control Signal Configuration Register 0 */ + __I uint32_t RESERVE2[1]; + __IO uint32_t CLKIN; /*!< [0x0028] USCI Input Clock Signal Configuration Register */ + __IO uint32_t LINECTL; /*!< [0x002c] USCI Line Control Register */ + __O uint32_t TXDAT; /*!< [0x0030] USCI Transmit Data Register */ + __I uint32_t RXDAT; /*!< [0x0034] USCI Receive Data Register */ + __IO uint32_t BUFCTL; /*!< [0x0038] USCI Transmit/Receive Buffer Control Register */ + __IO uint32_t BUFSTS; /*!< [0x003c] USCI Transmit/Receive Buffer Status Register */ + __IO uint32_t PDMACTL; /*!< [0x0040] USCI PDMA Control Register */ + __I uint32_t RESERVE3[4]; + __IO uint32_t WKCTL; /*!< [0x0054] USCI Wake-up Control Register */ + __IO uint32_t WKSTS; /*!< [0x0058] USCI Wake-up Status Register */ + __IO uint32_t PROTCTL; /*!< [0x005c] USCI Protocol Control Register */ + __IO uint32_t PROTIEN; /*!< [0x0060] USCI Protocol Interrupt Enable Register */ + __IO uint32_t PROTSTS; /*!< [0x0064] USCI Protocol Status Register */ + +} UUART_T; + +/** + @addtogroup UUART_CONST UUART Bit Field Definition + Constant Definitions for UUART Controller +@{ */ + +#define UUART_CTL_FUNMODE_Pos (0) /*!< UUART_T::CTL: FUNMODE Position */ +#define UUART_CTL_FUNMODE_Msk (0x7ul << UUART_CTL_FUNMODE_Pos) /*!< UUART_T::CTL: FUNMODE Mask */ + +#define UUART_INTEN_TXSTIEN_Pos (1) /*!< UUART_T::INTEN: TXSTIEN Position */ +#define UUART_INTEN_TXSTIEN_Msk (0x1ul << UUART_INTEN_TXSTIEN_Pos) /*!< UUART_T::INTEN: TXSTIEN Mask */ + +#define UUART_INTEN_TXENDIEN_Pos (2) /*!< UUART_T::INTEN: TXENDIEN Position */ +#define UUART_INTEN_TXENDIEN_Msk (0x1ul << UUART_INTEN_TXENDIEN_Pos) /*!< UUART_T::INTEN: TXENDIEN Mask */ + +#define UUART_INTEN_RXSTIEN_Pos (3) /*!< UUART_T::INTEN: RXSTIEN Position */ +#define UUART_INTEN_RXSTIEN_Msk (0x1ul << UUART_INTEN_RXSTIEN_Pos) /*!< UUART_T::INTEN: RXSTIEN Mask */ + +#define UUART_INTEN_RXENDIEN_Pos (4) /*!< UUART_T::INTEN: RXENDIEN Position */ +#define UUART_INTEN_RXENDIEN_Msk (0x1ul << UUART_INTEN_RXENDIEN_Pos) /*!< UUART_T::INTEN: RXENDIEN Mask */ + +#define UUART_BRGEN_RCLKSEL_Pos (0) /*!< UUART_T::BRGEN: RCLKSEL Position */ +#define UUART_BRGEN_RCLKSEL_Msk (0x1ul << UUART_BRGEN_RCLKSEL_Pos) /*!< UUART_T::BRGEN: RCLKSEL Mask */ + +#define UUART_BRGEN_PTCLKSEL_Pos (1) /*!< UUART_T::BRGEN: PTCLKSEL Position */ +#define UUART_BRGEN_PTCLKSEL_Msk (0x1ul << UUART_BRGEN_PTCLKSEL_Pos) /*!< UUART_T::BRGEN: PTCLKSEL Mask */ + +#define UUART_BRGEN_SPCLKSEL_Pos (2) /*!< UUART_T::BRGEN: SPCLKSEL Position */ +#define UUART_BRGEN_SPCLKSEL_Msk (0x3ul << UUART_BRGEN_SPCLKSEL_Pos) /*!< UUART_T::BRGEN: SPCLKSEL Mask */ + +#define UUART_BRGEN_TMCNTEN_Pos (4) /*!< UUART_T::BRGEN: TMCNTEN Position */ +#define UUART_BRGEN_TMCNTEN_Msk (0x1ul << UUART_BRGEN_TMCNTEN_Pos) /*!< UUART_T::BRGEN: TMCNTEN Mask */ + +#define UUART_BRGEN_TMCNTSRC_Pos (5) /*!< UUART_T::BRGEN: TMCNTSRC Position */ +#define UUART_BRGEN_TMCNTSRC_Msk (0x1ul << UUART_BRGEN_TMCNTSRC_Pos) /*!< UUART_T::BRGEN: TMCNTSRC Mask */ + +#define UUART_BRGEN_PDSCNT_Pos (8) /*!< UUART_T::BRGEN: PDSCNT Position */ +#define UUART_BRGEN_PDSCNT_Msk (0x3ul << UUART_BRGEN_PDSCNT_Pos) /*!< UUART_T::BRGEN: PDSCNT Mask */ + +#define UUART_BRGEN_DSCNT_Pos (10) /*!< UUART_T::BRGEN: DSCNT Position */ +#define UUART_BRGEN_DSCNT_Msk (0x1ful << UUART_BRGEN_DSCNT_Pos) /*!< UUART_T::BRGEN: DSCNT Mask */ + +#define UUART_BRGEN_CLKDIV_Pos (16) /*!< UUART_T::BRGEN: CLKDIV Position */ +#define UUART_BRGEN_CLKDIV_Msk (0x3fful << UUART_BRGEN_CLKDIV_Pos) /*!< UUART_T::BRGEN: CLKDIV Mask */ + +#define UUART_DATIN0_SYNCSEL_Pos (0) /*!< UUART_T::DATIN0: SYNCSEL Position */ +#define UUART_DATIN0_SYNCSEL_Msk (0x1ul << UUART_DATIN0_SYNCSEL_Pos) /*!< UUART_T::DATIN0: SYNCSEL Mask */ + +#define UUART_DATIN0_ININV_Pos (2) /*!< UUART_T::DATIN0: ININV Position */ +#define UUART_DATIN0_ININV_Msk (0x1ul << UUART_DATIN0_ININV_Pos) /*!< UUART_T::DATIN0: ININV Mask */ + +#define UUART_DATIN0_EDGEDET_Pos (3) /*!< UUART_T::DATIN0: EDGEDET Position */ +#define UUART_DATIN0_EDGEDET_Msk (0x3ul << UUART_DATIN0_EDGEDET_Pos) /*!< UUART_T::DATIN0: EDGEDET Mask */ + +#define UUART_CTLIN0_SYNCSEL_Pos (0) /*!< UUART_T::CTLIN0: SYNCSEL Position */ +#define UUART_CTLIN0_SYNCSEL_Msk (0x1ul << UUART_CTLIN0_SYNCSEL_Pos) /*!< UUART_T::CTLIN0: SYNCSEL Mask */ + +#define UUART_CTLIN0_ININV_Pos (2) /*!< UUART_T::CTLIN0: ININV Position */ +#define UUART_CTLIN0_ININV_Msk (0x1ul << UUART_CTLIN0_ININV_Pos) /*!< UUART_T::CTLIN0: ININV Mask */ + +#define UUART_CLKIN_SYNCSEL_Pos (0) /*!< UUART_T::CLKIN: SYNCSEL Position */ +#define UUART_CLKIN_SYNCSEL_Msk (0x1ul << UUART_CLKIN_SYNCSEL_Pos) /*!< UUART_T::CLKIN: SYNCSEL Mask */ + +#define UUART_LINECTL_LSB_Pos (0) /*!< UUART_T::LINECTL: LSB Position */ +#define UUART_LINECTL_LSB_Msk (0x1ul << UUART_LINECTL_LSB_Pos) /*!< UUART_T::LINECTL: LSB Mask */ + +#define UUART_LINECTL_DATOINV_Pos (5) /*!< UUART_T::LINECTL: DATOINV Position */ +#define UUART_LINECTL_DATOINV_Msk (0x1ul << UUART_LINECTL_DATOINV_Pos) /*!< UUART_T::LINECTL: DATOINV Mask */ + +#define UUART_LINECTL_CTLOINV_Pos (7) /*!< UUART_T::LINECTL: CTLOINV Position */ +#define UUART_LINECTL_CTLOINV_Msk (0x1ul << UUART_LINECTL_CTLOINV_Pos) /*!< UUART_T::LINECTL: CTLOINV Mask */ + +#define UUART_LINECTL_DWIDTH_Pos (8) /*!< UUART_T::LINECTL: DWIDTH Position */ +#define UUART_LINECTL_DWIDTH_Msk (0xful << UUART_LINECTL_DWIDTH_Pos) /*!< UUART_T::LINECTL: DWIDTH Mask */ + +#define UUART_TXDAT_TXDAT_Pos (0) /*!< UUART_T::TXDAT: TXDAT Position */ +#define UUART_TXDAT_TXDAT_Msk (0xfffful << UUART_TXDAT_TXDAT_Pos) /*!< UUART_T::TXDAT: TXDAT Mask */ + +#define UUART_RXDAT_RXDAT_Pos (0) /*!< UUART_T::RXDAT: RXDAT Position */ +#define UUART_RXDAT_RXDAT_Msk (0xfffful << UUART_RXDAT_RXDAT_Pos) /*!< UUART_T::RXDAT: RXDAT Mask */ + +#define UUART_BUFCTL_TXCLR_Pos (7) /*!< UUART_T::BUFCTL: TXCLR Position */ +#define UUART_BUFCTL_TXCLR_Msk (0x1ul << UUART_BUFCTL_TXCLR_Pos) /*!< UUART_T::BUFCTL: TXCLR Mask */ + +#define UUART_BUFCTL_RXOVIEN_Pos (14) /*!< UUART_T::BUFCTL: RXOVIEN Position */ +#define UUART_BUFCTL_RXOVIEN_Msk (0x1ul << UUART_BUFCTL_RXOVIEN_Pos) /*!< UUART_T::BUFCTL: RXOVIEN Mask */ + +#define UUART_BUFCTL_RXCLR_Pos (15) /*!< UUART_T::BUFCTL: RXCLR Position */ +#define UUART_BUFCTL_RXCLR_Msk (0x1ul << UUART_BUFCTL_RXCLR_Pos) /*!< UUART_T::BUFCTL: RXCLR Mask */ + +#define UUART_BUFCTL_TXRST_Pos (16) /*!< UUART_T::BUFCTL: TXRST Position */ +#define UUART_BUFCTL_TXRST_Msk (0x1ul << UUART_BUFCTL_TXRST_Pos) /*!< UUART_T::BUFCTL: TXRST Mask */ + +#define UUART_BUFCTL_RXRST_Pos (17) /*!< UUART_T::BUFCTL: RXRST Position */ +#define UUART_BUFCTL_RXRST_Msk (0x1ul << UUART_BUFCTL_RXRST_Pos) /*!< UUART_T::BUFCTL: RXRST Mask */ + +#define UUART_BUFSTS_RXEMPTY_Pos (0) /*!< UUART_T::BUFSTS: RXEMPTY Position */ +#define UUART_BUFSTS_RXEMPTY_Msk (0x1ul << UUART_BUFSTS_RXEMPTY_Pos) /*!< UUART_T::BUFSTS: RXEMPTY Mask */ + +#define UUART_BUFSTS_RXFULL_Pos (1) /*!< UUART_T::BUFSTS: RXFULL Position */ +#define UUART_BUFSTS_RXFULL_Msk (0x1ul << UUART_BUFSTS_RXFULL_Pos) /*!< UUART_T::BUFSTS: RXFULL Mask */ + +#define UUART_BUFSTS_RXOVIF_Pos (3) /*!< UUART_T::BUFSTS: RXOVIF Position */ +#define UUART_BUFSTS_RXOVIF_Msk (0x1ul << UUART_BUFSTS_RXOVIF_Pos) /*!< UUART_T::BUFSTS: RXOVIF Mask */ + +#define UUART_BUFSTS_TXEMPTY_Pos (8) /*!< UUART_T::BUFSTS: TXEMPTY Position */ +#define UUART_BUFSTS_TXEMPTY_Msk (0x1ul << UUART_BUFSTS_TXEMPTY_Pos) /*!< UUART_T::BUFSTS: TXEMPTY Mask */ + +#define UUART_BUFSTS_TXFULL_Pos (9) /*!< UUART_T::BUFSTS: TXFULL Position */ +#define UUART_BUFSTS_TXFULL_Msk (0x1ul << UUART_BUFSTS_TXFULL_Pos) /*!< UUART_T::BUFSTS: TXFULL Mask */ + +#define UUART_PDMACTL_PDMARST_Pos (0) /*!< UUART_T::PDMACTL: PDMARST Position */ +#define UUART_PDMACTL_PDMARST_Msk (0x1ul << UUART_PDMACTL_PDMARST_Pos) /*!< UUART_T::PDMACTL: PDMARST Mask */ + +#define UUART_PDMACTL_TXPDMAEN_Pos (1) /*!< UUART_T::PDMACTL: TXPDMAEN Position*/ +#define UUART_PDMACTL_TXPDMAEN_Msk (0x1ul << UUART_PDMACTL_TXPDMAEN_Pos) /*!< UUART_T::PDMACTL: TXPDMAEN Mask */ + +#define UUART_PDMACTL_RXPDMAEN_Pos (2) /*!< UUART_T::PDMACTL: RXPDMAEN Position*/ +#define UUART_PDMACTL_RXPDMAEN_Msk (0x1ul << UUART_PDMACTL_RXPDMAEN_Pos) /*!< UUART_T::PDMACTL: RXPDMAEN Mask */ + +#define UUART_PDMACTL_PDMAEN_Pos (3) /*!< UUART_T::PDMACTL: PDMAEN Position */ +#define UUART_PDMACTL_PDMAEN_Msk (0x1ul << UUART_PDMACTL_PDMAEN_Pos) /*!< UUART_T::PDMACTL: PDMAEN Mask */ + +#define UUART_WKCTL_WKEN_Pos (0) /*!< UUART_T::WKCTL: WKEN Position */ +#define UUART_WKCTL_WKEN_Msk (0x1ul << UUART_WKCTL_WKEN_Pos) /*!< UUART_T::WKCTL: WKEN Mask */ + +#define UUART_WKCTL_PDBOPT_Pos (2) /*!< UUART_T::WKCTL: PDBOPT Position */ +#define UUART_WKCTL_PDBOPT_Msk (0x1ul << UUART_WKCTL_PDBOPT_Pos) /*!< UUART_T::WKCTL: PDBOPT Mask */ + +#define UUART_WKSTS_WKF_Pos (0) /*!< UUART_T::WKSTS: WKF Position */ +#define UUART_WKSTS_WKF_Msk (0x1ul << UUART_WKSTS_WKF_Pos) /*!< UUART_T::WKSTS: WKF Mask */ + +#define UUART_PROTCTL_STOPB_Pos (0) /*!< UUART_T::PROTCTL: STOPB Position */ +#define UUART_PROTCTL_STOPB_Msk (0x1ul << UUART_PROTCTL_STOPB_Pos) /*!< UUART_T::PROTCTL: STOPB Mask */ + +#define UUART_PROTCTL_PARITYEN_Pos (1) /*!< UUART_T::PROTCTL: PARITYEN Position*/ +#define UUART_PROTCTL_PARITYEN_Msk (0x1ul << UUART_PROTCTL_PARITYEN_Pos) /*!< UUART_T::PROTCTL: PARITYEN Mask */ + +#define UUART_PROTCTL_EVENPARITY_Pos (2) /*!< UUART_T::PROTCTL: EVENPARITY Position*/ +#define UUART_PROTCTL_EVENPARITY_Msk (0x1ul << UUART_PROTCTL_EVENPARITY_Pos) /*!< UUART_T::PROTCTL: EVENPARITY Mask */ + +#define UUART_PROTCTL_RTSAUTOEN_Pos (3) /*!< UUART_T::PROTCTL: RTSAUTOEN Position*/ +#define UUART_PROTCTL_RTSAUTOEN_Msk (0x1ul << UUART_PROTCTL_RTSAUTOEN_Pos) /*!< UUART_T::PROTCTL: RTSAUTOEN Mask */ + +#define UUART_PROTCTL_CTSAUTOEN_Pos (4) /*!< UUART_T::PROTCTL: CTSAUTOEN Position*/ +#define UUART_PROTCTL_CTSAUTOEN_Msk (0x1ul << UUART_PROTCTL_CTSAUTOEN_Pos) /*!< UUART_T::PROTCTL: CTSAUTOEN Mask */ + +#define UUART_PROTCTL_RTSAUDIREN_Pos (5) /*!< UUART_T::PROTCTL: RTSAUDIREN Position*/ +#define UUART_PROTCTL_RTSAUDIREN_Msk (0x1ul << UUART_PROTCTL_RTSAUDIREN_Pos) /*!< UUART_T::PROTCTL: RTSAUDIREN Mask */ + +#define UUART_PROTCTL_ABREN_Pos (6) /*!< UUART_T::PROTCTL: ABREN Position */ +#define UUART_PROTCTL_ABREN_Msk (0x1ul << UUART_PROTCTL_ABREN_Pos) /*!< UUART_T::PROTCTL: ABREN Mask */ + +#define UUART_PROTCTL_DATWKEN_Pos (9) /*!< UUART_T::PROTCTL: DATWKEN Position */ +#define UUART_PROTCTL_DATWKEN_Msk (0x1ul << UUART_PROTCTL_DATWKEN_Pos) /*!< UUART_T::PROTCTL: DATWKEN Mask */ + +#define UUART_PROTCTL_CTSWKEN_Pos (10) /*!< UUART_T::PROTCTL: CTSWKEN Position */ +#define UUART_PROTCTL_CTSWKEN_Msk (0x1ul << UUART_PROTCTL_CTSWKEN_Pos) /*!< UUART_T::PROTCTL: CTSWKEN Mask */ + +#define UUART_PROTCTL_WAKECNT_Pos (11) /*!< UUART_T::PROTCTL: WAKECNT Position */ +#define UUART_PROTCTL_WAKECNT_Msk (0xful << UUART_PROTCTL_WAKECNT_Pos) /*!< UUART_T::PROTCTL: WAKECNT Mask */ + +#define UUART_PROTCTL_BRDETITV_Pos (16) /*!< UUART_T::PROTCTL: BRDETITV Position*/ +#define UUART_PROTCTL_BRDETITV_Msk (0x1fful << UUART_PROTCTL_BRDETITV_Pos) /*!< UUART_T::PROTCTL: BRDETITV Mask */ + +#define UUART_PROTCTL_STICKEN_Pos (26) /*!< UUART_T::PROTCTL: STICKEN Position */ +#define UUART_PROTCTL_STICKEN_Msk (0x1ul << UUART_PROTCTL_STICKEN_Pos) /*!< UUART_T::PROTCTL: STICKEN Mask */ + +#define UUART_PROTCTL_BCEN_Pos (29) /*!< UUART_T::PROTCTL: BCEN Position */ +#define UUART_PROTCTL_BCEN_Msk (0x1ul << UUART_PROTCTL_BCEN_Pos) /*!< UUART_T::PROTCTL: BCEN Mask */ + +#define UUART_PROTCTL_PROTEN_Pos (31) /*!< UUART_T::PROTCTL: PROTEN Position */ +#define UUART_PROTCTL_PROTEN_Msk (0x1ul << UUART_PROTCTL_PROTEN_Pos) /*!< UUART_T::PROTCTL: PROTEN Mask */ + +#define UUART_PROTIEN_ABRIEN_Pos (1) /*!< UUART_T::PROTIEN: ABRIEN Position */ +#define UUART_PROTIEN_ABRIEN_Msk (0x1ul << UUART_PROTIEN_ABRIEN_Pos) /*!< UUART_T::PROTIEN: ABRIEN Mask */ + +#define UUART_PROTIEN_RLSIEN_Pos (2) /*!< UUART_T::PROTIEN: RLSIEN Position */ +#define UUART_PROTIEN_RLSIEN_Msk (0x1ul << UUART_PROTIEN_RLSIEN_Pos) /*!< UUART_T::PROTIEN: RLSIEN Mask */ + +#define UUART_PROTSTS_TXSTIF_Pos (1) /*!< UUART_T::PROTSTS: TXSTIF Position */ +#define UUART_PROTSTS_TXSTIF_Msk (0x1ul << UUART_PROTSTS_TXSTIF_Pos) /*!< UUART_T::PROTSTS: TXSTIF Mask */ + +#define UUART_PROTSTS_TXENDIF_Pos (2) /*!< UUART_T::PROTSTS: TXENDIF Position */ +#define UUART_PROTSTS_TXENDIF_Msk (0x1ul << UUART_PROTSTS_TXENDIF_Pos) /*!< UUART_T::PROTSTS: TXENDIF Mask */ + +#define UUART_PROTSTS_RXSTIF_Pos (3) /*!< UUART_T::PROTSTS: RXSTIF Position */ +#define UUART_PROTSTS_RXSTIF_Msk (0x1ul << UUART_PROTSTS_RXSTIF_Pos) /*!< UUART_T::PROTSTS: RXSTIF Mask */ + +#define UUART_PROTSTS_RXENDIF_Pos (4) /*!< UUART_T::PROTSTS: RXENDIF Position */ +#define UUART_PROTSTS_RXENDIF_Msk (0x1ul << UUART_PROTSTS_RXENDIF_Pos) /*!< UUART_T::PROTSTS: RXENDIF Mask */ + +#define UUART_PROTSTS_PARITYERR_Pos (5) /*!< UUART_T::PROTSTS: PARITYERR Position*/ +#define UUART_PROTSTS_PARITYERR_Msk (0x1ul << UUART_PROTSTS_PARITYERR_Pos) /*!< UUART_T::PROTSTS: PARITYERR Mask */ + +#define UUART_PROTSTS_FRMERR_Pos (6) /*!< UUART_T::PROTSTS: FRMERR Position */ +#define UUART_PROTSTS_FRMERR_Msk (0x1ul << UUART_PROTSTS_FRMERR_Pos) /*!< UUART_T::PROTSTS: FRMERR Mask */ + +#define UUART_PROTSTS_BREAK_Pos (7) /*!< UUART_T::PROTSTS: BREAK Position */ +#define UUART_PROTSTS_BREAK_Msk (0x1ul << UUART_PROTSTS_BREAK_Pos) /*!< UUART_T::PROTSTS: BREAK Mask */ + +#define UUART_PROTSTS_ABRDETIF_Pos (9) /*!< UUART_T::PROTSTS: ABRDETIF Position*/ +#define UUART_PROTSTS_ABRDETIF_Msk (0x1ul << UUART_PROTSTS_ABRDETIF_Pos) /*!< UUART_T::PROTSTS: ABRDETIF Mask */ + +#define UUART_PROTSTS_RXBUSY_Pos (10) /*!< UUART_T::PROTSTS: RXBUSY Position */ +#define UUART_PROTSTS_RXBUSY_Msk (0x1ul << UUART_PROTSTS_RXBUSY_Pos) /*!< UUART_T::PROTSTS: RXBUSY Mask */ + +#define UUART_PROTSTS_ABERRSTS_Pos (11) /*!< UUART_T::PROTSTS: ABERRSTS Position*/ +#define UUART_PROTSTS_ABERRSTS_Msk (0x1ul << UUART_PROTSTS_ABERRSTS_Pos) /*!< UUART_T::PROTSTS: ABERRSTS Mask */ + +#define UUART_PROTSTS_CTSSYNCLV_Pos (16) /*!< UUART_T::PROTSTS: CTSSYNCLV Position*/ +#define UUART_PROTSTS_CTSSYNCLV_Msk (0x1ul << UUART_PROTSTS_CTSSYNCLV_Pos) /*!< UUART_T::PROTSTS: CTSSYNCLV Mask */ + +#define UUART_PROTSTS_CTSLV_Pos (17) /*!< UUART_T::PROTSTS: CTSLV Position */ +#define UUART_PROTSTS_CTSLV_Msk (0x1ul << UUART_PROTSTS_CTSLV_Pos) /*!< UUART_T::PROTSTS: CTSLV Mask */ + +/**@}*/ /* UUART_CONST */ +/**@}*/ /* end of UUART register group */ + + +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __UUART_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/wdt_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/wdt_reg.h new file mode 100644 index 0000000000..89eba1f6e0 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/wdt_reg.h @@ -0,0 +1,174 @@ +/**************************************************************************//** + * @file wdt_reg.h + * @version V1.00 + * @brief WDT register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __WDT_REG_H__ +#define __WDT_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup WDT Watch Dog Timer Controller(WDT) + Memory Mapped Structure for WDT Controller +@{ */ + +typedef struct +{ + + /** + * @var WDT_T::CTL + * Offset: 0x00 WDT Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1] |RSTEN |WDT Time-out Reset Enable Bit (Write Protect) + * | | |Setting this bit will enable the WDT time-out reset function If the WDT up counter value has not been cleared after the specific WDT reset delay period expires. + * | | |0 = WDT time-out reset function Disabled. + * | | |1 = WDT time-out reset function Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[2] |RSTF |WDT Time-out Reset Flag + * | | |This bit indicates the system has been reset by WDT time-out reset or not. + * | | |0 = WDT time-out reset did not occur. + * | | |1 = WDT time-out reset occurred. + * | | |Note: This bit is cleared by writing 1 to it. + * |[3] |IF |WDT Time-out Interrupt Flag + * | | |This bit will set to 1 while WDT up counter value reaches the selected WDT time-out interval. + * | | |0 = WDT time-out interrupt did not occur. + * | | |1 = WDT time-out interrupt occurred. + * | | |Note: This bit is cleared by writing 1 to it. + * |[4] |WKEN |WDT Time-out Wake-up Function Control (Write Protect) + * | | |If this bit is set to 1, while WDT time-out interrupt flag IF (WDT_CTL[3]) is generated to 1 and interrupt enable bit INTEN (WDT_CTL[6]) is enabled, the WDT time-out interrupt signal will generate a wake-up trigger event to chip. + * | | |0 = Wake-up trigger event Disabled if WDT time-out interrupt signal generated. + * | | |1 = Wake-up trigger event Enabled if WDT time-out interrupt signal generated. + * | | |Note1: This bit is write protected. Refer to the SYS_REGLCTL register. + * | | |Note2: Chip can be woken up by WDT time-out interrupt signal generated only if WDT clock source is selected to 10 kHz internal low speed RC oscillator (LIRC) or LXT. + * |[5] |WKF |WDT Time-out Wake-up Flag (Write Protect) + * | | |This bit indicates the interrupt wake-up flag status of WDT. + * | | |0 = WDT does not cause chip wake-up. + * | | |1 = Chip wake-up from Idle or Power-down mode if WDT time-out interrupt signal generated. + * | | |Note1: This bit is write protected. Refer to the SYS_REGLCTL register. + * | | |Note2: This bit is cleared by writing 1 to it. + * |[6] |INTEN |WDT Time-out Interrupt Enable Bit (Write Protect) + * | | |If this bit is enabled, the WDT time-out interrupt signal is generated and inform to CPU. + * | | |0 = WDT time-out interrupt Disabled. + * | | |1 = WDT time-out interrupt Enabled. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[7] |WDTEN |WDT Enable Bit (Write Protect) + * | | |0 = WDT Disabled (This action will reset the internal up counter value). + * | | |1 = WDT Enabled. + * | | |Note1: This bit is write protected. Refer to the SYS_REGLCTL register. + * | | |Note2: If CWDTEN[2:0] (combined by Config0[31] and Config0[4:3]) bits is not configured to 111, this bit is forced as 1 and user cannot change this bit to 0. + * |[11:8] |TOUTSEL |WDT Time-out Interval Selection (Write Protect) + * | | |These four bits select the time-out interval period for the WDT. + * | | |0000 = 24 * WDT_CLK. + * | | |0001 = 26 * WDT_CLK. + * | | |0010 = 28 * WDT_CLK. + * | | |0011 = 210 * WDT_CLK. + * | | |0100 = 212 * WDT_CLK. + * | | |0101 = 214 * WDT_CLK. + * | | |0110 = 216 * WDT_CLK. + * | | |0111 = 218 * WDT_CLK. + * | | |1000 = 220 * WDT_CLK. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * |[30] |SYNC |WDT Enable Control SYNC Flag Indicator (Read Only) + * | | |If user executes enable/disable WDTEN (WDT_CTL[7]), this flag can be indicated enable/disable WDTEN function is completed or not. + * | | |0 = Set WDTEN bit is completed. + * | | |1 = Set WDTEN bit is synchronizing and not become active yet. + * | | |Note: Performing enable or disable WDTEN bit needs 2 * WDT_CLK period to become active. + * |[31] |ICEDEBUG |ICE Debug Mode Acknowledge Disable Bit (Write Protect) + * | | |0 = ICE debug mode acknowledgement affects WDT counting. + * | | |WDT up counter will be held while CPU is held by ICE. + * | | |1 = ICE debug mode acknowledgement Disabled. + * | | |WDT up counter will keep going no matter CPU is held by ICE or not. + * | | |Note: This bit is write protected. Refer to the SYS_REGLCTL register. + * @var WDT_T::ALTCTL + * Offset: 0x04 WDT Alternative Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[1:0] |RSTDSEL |WDT Reset Delay Selection (Write Protect). + * | | |When WDT time-out happened, user has a time named WDT Reset Delay Period to clear WDT counter by writing 0x00005aa5 to RSTCNT (WDT_RSTCNT[31:0]) to prevent WDT time-out reset happened. + * | | |User can select a suitable setting of RSTDSEL for different WDT Reset Delay Period. + * | | |00 = WDT Reset Delay Period is 1026 * WDT_CLK. + * | | |01 = WDT Reset Delay Period is 130 * WDT_CLK. + * | | |10 = WDT Reset Delay Period is 18 * WDT_CLK. + * | | |11 = WDT Reset Delay Period is 3 * WDT_CLK. + * | | |Note1: This bit is write protected. Refer to the SYS_REGLCTL register. + * | | |Note2: This register will be reset to 0 if WDT time-out reset happened. + * @var WDT_T::RSTCNT + * Offset: 0x08 WDT Reset Counter Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |RSTCNT |WDT Reset Counter Register + * | | |Writing 0x00005AA5 to this field will reset the internal 18-bit WDT up counter value to 0. + * | | |Note1: Performing RSTCNT to reset counter needs 2 * WDT_CLK period to become active. + */ + __IO uint32_t CTL; /*!< [0x0000] WDT Control Register */ + __IO uint32_t ALTCTL; /*!< [0x0004] WDT Alternative Control Register */ + __O uint32_t RSTCNT; /*!< [0x0008] WDT Reset Counter Register */ + +} WDT_T; + +/** + @addtogroup WDT_CONST WDT Bit Field Definition + Constant Definitions for WDT Controller +@{ */ + +#define WDT_CTL_RSTEN_Pos (1) /*!< WDT_T::CTL: RSTEN Position */ +#define WDT_CTL_RSTEN_Msk (0x1ul << WDT_CTL_RSTEN_Pos) /*!< WDT_T::CTL: RSTEN Mask */ + +#define WDT_CTL_RSTF_Pos (2) /*!< WDT_T::CTL: RSTF Position */ +#define WDT_CTL_RSTF_Msk (0x1ul << WDT_CTL_RSTF_Pos) /*!< WDT_T::CTL: RSTF Mask */ + +#define WDT_CTL_IF_Pos (3) /*!< WDT_T::CTL: IF Position */ +#define WDT_CTL_IF_Msk (0x1ul << WDT_CTL_IF_Pos) /*!< WDT_T::CTL: IF Mask */ + +#define WDT_CTL_WKEN_Pos (4) /*!< WDT_T::CTL: WKEN Position */ +#define WDT_CTL_WKEN_Msk (0x1ul << WDT_CTL_WKEN_Pos) /*!< WDT_T::CTL: WKEN Mask */ + +#define WDT_CTL_WKF_Pos (5) /*!< WDT_T::CTL: WKF Position */ +#define WDT_CTL_WKF_Msk (0x1ul << WDT_CTL_WKF_Pos) /*!< WDT_T::CTL: WKF Mask */ + +#define WDT_CTL_INTEN_Pos (6) /*!< WDT_T::CTL: INTEN Position */ +#define WDT_CTL_INTEN_Msk (0x1ul << WDT_CTL_INTEN_Pos) /*!< WDT_T::CTL: INTEN Mask */ + +#define WDT_CTL_WDTEN_Pos (7) /*!< WDT_T::CTL: WDTEN Position */ +#define WDT_CTL_WDTEN_Msk (0x1ul << WDT_CTL_WDTEN_Pos) /*!< WDT_T::CTL: WDTEN Mask */ + +#define WDT_CTL_TOUTSEL_Pos (8) /*!< WDT_T::CTL: TOUTSEL Position */ +#define WDT_CTL_TOUTSEL_Msk (0xful << WDT_CTL_TOUTSEL_Pos) /*!< WDT_T::CTL: TOUTSEL Mask */ + +#define WDT_CTL_SYNC_Pos (30) /*!< WDT_T::CTL: SYNC Position */ +#define WDT_CTL_SYNC_Msk (0x1ul << WDT_CTL_SYNC_Pos) /*!< WDT_T::CTL: SYNC Mask */ + +#define WDT_CTL_ICEDEBUG_Pos (31) /*!< WDT_T::CTL: ICEDEBUG Position */ +#define WDT_CTL_ICEDEBUG_Msk (0x1ul << WDT_CTL_ICEDEBUG_Pos) /*!< WDT_T::CTL: ICEDEBUG Mask */ + +#define WDT_ALTCTL_RSTDSEL_Pos (0) /*!< WDT_T::ALTCTL: RSTDSEL Position */ +#define WDT_ALTCTL_RSTDSEL_Msk (0x3ul << WDT_ALTCTL_RSTDSEL_Pos) /*!< WDT_T::ALTCTL: RSTDSEL Mask */ + +#define WDT_RSTCNT_RSTCNT_Pos (0) /*!< WDT_T::RSTCNT: RSTCNT Position */ +#define WDT_RSTCNT_RSTCNT_Msk (0xfffffffful << WDT_RSTCNT_RSTCNT_Pos) /*!< WDT_T::RSTCNT: RSTCNT Mask */ + +/**@}*/ /* WDT_CONST */ +/**@}*/ /* end of WDT register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __WDT_REG_H__ */ + diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/wwdt_reg.h b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/wwdt_reg.h new file mode 100644 index 0000000000..0b01cc6b8a --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Include/wwdt_reg.h @@ -0,0 +1,148 @@ +/**************************************************************************//** + * @file wwdt_reg.h + * @version V1.00 + * @brief WWDT register definition header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __WWDT_REG_H__ +#define __WWDT_REG_H__ + +#if defined ( __CC_ARM ) +#pragma anon_unions +#endif + +/** + @addtogroup REGISTER Control Register + @{ +*/ + +/** + @addtogroup WWDT Window Watchdog Timer(WWDT) + Memory Mapped Structure for WWDT Controller +@{ */ + +typedef struct +{ + + + /** + * @var WWDT_T::RLDCNT + * Offset: 0x00 WWDT Reload Counter Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[31:0] |RLDCNT |WWDT Reload Counter Register + * | | |Writing 0x00005AA5 to this register will reload the WWDT counter value to 0x3F. + * | | |Note: User can only write WWDT_RLDCNT register to reload WWDT counter value when current WWDT counter value between 0 and CMPDAT (WWDT_CTL[21:16]). + * | | |If user writes WWDT_RLDCNT when current WWDT counter value is larger than CMPDAT, WWDT reset signal will be generated immediately. + * @var WWDT_T::CTL + * Offset: 0x04 WWDT Control Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WWDTEN |WWDT Enable Bit + * | | |0 = WWDT counter is stopped. + * | | |1 = WWDT counter starts counting. + * |[1] |INTEN |WWDT Interrupt Enable Bit + * | | |If this bit is enabled, the WWDT counter compare match interrupt signal is generated and inform to CPU. + * | | |0 = WWDT counter compare match interrupt Disabled. + * | | |1 = WWDT counter compare match interrupt Enabled. + * |[11:8] |PSCSEL |WWDT Counter Prescale Period Selection + * | | |0000 = Pre-scale is 1; Max time-out period is 1 * 64 * WWDT_CLK. + * | | |0001 = Pre-scale is 2; Max time-out period is 2 * 64 * WWDT_CLK. + * | | |0010 = Pre-scale is 4; Max time-out period is 4 * 64 * WWDT_CLK. + * | | |0011 = Pre-scale is 8; Max time-out period is 8 * 64 * WWDT_CLK. + * | | |0100 = Pre-scale is 16; Max time-out period is 16 * 64 * WWDT_CLK. + * | | |0101 = Pre-scale is 32; Max time-out period is 32 * 64 * WWDT_CLK. + * | | |0110 = Pre-scale is 64; Max time-out period is 64 * 64 * WWDT_CLK. + * | | |0111 = Pre-scale is 128; Max time-out period is 128 * 64 * WWDT_CLK. + * | | |1000 = Pre-scale is 192; Max time-out period is 192 * 64 * WWDT_CLK. + * | | |1001 = Pre-scale is 256; Max time-out period is 256 * 64 * WWDT_CLK. + * | | |1010 = Pre-scale is 384; Max time-out period is 384 * 64 * WWDT_CLK. + * | | |1011 = Pre-scale is 512; Max time-out period is 512 * 64 * WWDT_CLK. + * | | |1100 = Pre-scale is 768; Max time-out period is 768 * 64 * WWDT_CLK. + * | | |1101 = Pre-scale is 1024; Max time-out period is 1024 * 64 * WWDT_CLK. + * | | |1110 = Pre-scale is 1536; Max time-out period is 1536 * 64 * WWDT_CLK. + * | | |1111 = Pre-scale is 2048; Max time-out period is 2048 * 64 * WWDT_CLK. + * |[21:16] |CMPDAT |WWDT Window Compare Register + * | | |Set this register to adjust the valid reload window. + * | | |Note: User can only write WWDT_RLDCNT register to reload WWDT counter value when current WWDT counter value between 0 and CMPDAT. + * | | |If user writes WWDT_RLDCNT register when current WWDT counter value larger than CMPDAT, WWDT reset signal will generate immediately. + * |[31] |ICEDEBUG |ICE Debug Mode Acknowledge Disable Bit + * | | |0 = ICE debug mode acknowledgement effects WWDT counting. + * | | |WWDT down counter will be held while CPU is held by ICE. + * | | |1 = ICE debug mode acknowledgement Disabled. + * | | |Note: WWDT down counter will keep going no matter CPU is held by ICE or not. + * @var WWDT_T::STATUS + * Offset: 0x08 WWDT Status Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[0] |WWDTIF |WWDT Compare Match Interrupt Flag + * | | |This bit indicates the interrupt flag status of WWDT while WWDT counter value matches CMPDAT (WWDT_CTL[21:16]). + * | | |0 = No effect. + * | | |1 = WWDT counter value matches CMPDAT. + * | | |Note: This bit is cleared by writing 1 to it. + * |[1] |WWDTRF |WWDT Timer-out Reset Flag + * | | |This bit indicates the system has been reset by WWDT time-out reset or not. + * | | |0 = WWDT time-out reset did not occur. + * | | |1 = WWDT time-out reset occurred. + * | | |Note: This bit is cleared by writing 1 to it. + * @var WWDT_T::CNT + * Offset: 0x0C WWDT Counter Value Register + * --------------------------------------------------------------------------------------------------- + * |Bits |Field |Descriptions + * | :----: | :----: | :---- | + * |[5:0] |CNTDAT |WWDT Counter Value + * | | |CNTDAT will be updated continuously to monitor 6-bit WWDT down counter value. + */ + __O uint32_t RLDCNT; /*!< [0x0000] WWDT Reload Counter Register */ + __IO uint32_t CTL; /*!< [0x0004] WWDT Control Register */ + __IO uint32_t STATUS; /*!< [0x0008] WWDT Status Register */ + __I uint32_t CNT; /*!< [0x000c] WWDT Counter Value Register */ + +} WWDT_T; + +/** + @addtogroup WWDT_CONST WWDT Bit Field Definition + Constant Definitions for WWDT Controller +@{ */ + +#define WWDT_RLDCNT_RLDCNT_Pos (0) /*!< WWDT_T::RLDCNT: RLDCNT Position */ +#define WWDT_RLDCNT_RLDCNT_Msk (0xfffffffful << WWDT_RLDCNT_RLDCNT_Pos) /*!< WWDT_T::RLDCNT: RLDCNT Mask */ + +#define WWDT_CTL_WWDTEN_Pos (0) /*!< WWDT_T::CTL: WWDTEN Position */ +#define WWDT_CTL_WWDTEN_Msk (0x1ul << WWDT_CTL_WWDTEN_Pos) /*!< WWDT_T::CTL: WWDTEN Mask */ + +#define WWDT_CTL_INTEN_Pos (1) /*!< WWDT_T::CTL: INTEN Position */ +#define WWDT_CTL_INTEN_Msk (0x1ul << WWDT_CTL_INTEN_Pos) /*!< WWDT_T::CTL: INTEN Mask */ + +#define WWDT_CTL_PSCSEL_Pos (8) /*!< WWDT_T::CTL: PSCSEL Position */ +#define WWDT_CTL_PSCSEL_Msk (0xful << WWDT_CTL_PSCSEL_Pos) /*!< WWDT_T::CTL: PSCSEL Mask */ + +#define WWDT_CTL_CMPDAT_Pos (16) /*!< WWDT_T::CTL: CMPDAT Position */ +#define WWDT_CTL_CMPDAT_Msk (0x3ful << WWDT_CTL_CMPDAT_Pos) /*!< WWDT_T::CTL: CMPDAT Mask */ + +#define WWDT_CTL_ICEDEBUG_Pos (31) /*!< WWDT_T::CTL: ICEDEBUG Position */ +#define WWDT_CTL_ICEDEBUG_Msk (0x1ul << WWDT_CTL_ICEDEBUG_Pos) /*!< WWDT_T::CTL: ICEDEBUG Mask */ + +#define WWDT_STATUS_WWDTIF_Pos (0) /*!< WWDT_T::STATUS: WWDTIF Position */ +#define WWDT_STATUS_WWDTIF_Msk (0x1ul << WWDT_STATUS_WWDTIF_Pos) /*!< WWDT_T::STATUS: WWDTIF Mask */ + +#define WWDT_STATUS_WWDTRF_Pos (1) /*!< WWDT_T::STATUS: WWDTRF Position */ +#define WWDT_STATUS_WWDTRF_Msk (0x1ul << WWDT_STATUS_WWDTRF_Pos) /*!< WWDT_T::STATUS: WWDTRF Mask */ + +#define WWDT_CNT_CNTDAT_Pos (0) /*!< WWDT_T::CNT: CNTDAT Position */ +#define WWDT_CNT_CNTDAT_Msk (0x3ful << WWDT_CNT_CNTDAT_Pos) /*!< WWDT_T::CNT: CNTDAT Mask */ + +/**@}*/ /* WWDT_CONST */ +/**@}*/ /* end of WWDT register group */ +/**@}*/ /* end of REGISTER group */ + +#if defined ( __CC_ARM ) +#pragma no_anon_unions +#endif + +#endif /* __WWDT_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/ARM/startup_M031Series.s b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/ARM/startup_M031Series.s new file mode 100644 index 0000000000..843ca6e087 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/ARM/startup_M031Series.s @@ -0,0 +1,259 @@ +;/**************************************************************************//** +; * @file startup_m031series.s +; * @version V2.00 +; * $Revision: 4 $ +; * $Date: 18/04/02 4:02p $ +; * @brief M031 Series Startup Source File +; * +; * @note +; * SPDX-License-Identifier: Apache-2.0 +; * Copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved. +; * +; ******************************************************************************/ + IF :LNOT: :DEF: Stack_Size +Stack_Size EQU 0x00002000 + ENDIF + + AREA |.STACK|, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + IF :LNOT: :DEF: Heap_Size +Heap_Size EQU 0x00000000 + ENDIF + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT g_pfnVectors + +g_pfnVectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + ; maximum of 32 External Interrupts are possible + DCD BOD_IRQHandler + DCD WDT_IRQHandler + DCD EINT024_IRQHandler + DCD EINT135_IRQHandler + DCD GPABGH_IRQHandler + DCD GPCDEF_IRQHandler + DCD PWM0_IRQHandler + DCD PWM1_IRQHandler + DCD TMR0_IRQHandler + DCD TMR1_IRQHandler + DCD TMR2_IRQHandler + DCD TMR3_IRQHandler + DCD UART02_IRQHandler + DCD UART13_IRQHandler + DCD SPI0_IRQHandler + DCD QSPI0_IRQHandler + DCD ISP_IRQHandler + DCD UART57_IRQHandler + DCD I2C0_IRQHandler + DCD I2C1_IRQHandler + DCD BPWM0_IRQHandler + DCD BPWM1_IRQHandler + DCD USCI01_IRQHandler + DCD USBD_IRQHandler + DCD Default_Handler + DCD ACMP01_IRQHandler + DCD PDMA_IRQHandler + DCD UART46_IRQHandler + DCD PWRWU_IRQHandler + DCD ADC_IRQHandler + DCD CKFAIL_IRQHandler + DCD RTC_IRQHandler + + + + AREA |.text|, CODE, READONLY + + + +; Reset Handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + + + LDR R0, =0x40000100 + ; Unlock Register + + LDR R1, =0x59 + STR R1, [R0] + LDR R1, =0x16 + STR R1, [R0] + LDR R1, =0x88 + STR R1, [R0] + + ; Init POR + LDR R2, =0x40000024 + LDR R1, =0x00005AA5 + STR R1, [R2] + + ; Init LDO_RDY + LDR R2, =0x40000280 + LDR R1, =0x00000001 + STR R1, [R2] + + ; Lock register + MOVS R1, #0 + STR R1, [R0] + + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + + + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT BOD_IRQHandler [WEAK] + EXPORT WDT_IRQHandler [WEAK] + EXPORT EINT024_IRQHandler [WEAK] + EXPORT EINT135_IRQHandler [WEAK] + EXPORT GPABGH_IRQHandler [WEAK] + EXPORT GPCDEF_IRQHandler [WEAK] + EXPORT PWM0_IRQHandler [WEAK] + EXPORT PWM1_IRQHandler [WEAK] + EXPORT TMR0_IRQHandler [WEAK] + EXPORT TMR1_IRQHandler [WEAK] + EXPORT TMR2_IRQHandler [WEAK] + EXPORT TMR3_IRQHandler [WEAK] + EXPORT UART02_IRQHandler [WEAK] + EXPORT UART13_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT QSPI0_IRQHandler [WEAK] + EXPORT ISP_IRQHandler [WEAK] + EXPORT UART57_IRQHandler [WEAK] + EXPORT I2C0_IRQHandler [WEAK] + EXPORT I2C1_IRQHandler [WEAK] + EXPORT BPWM0_IRQHandler [WEAK] + EXPORT BPWM1_IRQHandler [WEAK] + EXPORT USCI01_IRQHandler [WEAK] + EXPORT USBD_IRQHandler [WEAK] + EXPORT ACMP01_IRQHandler [WEAK] + EXPORT PDMA_IRQHandler [WEAK] + EXPORT UART46_IRQHandler [WEAK] + EXPORT PWRWU_IRQHandler [WEAK] + EXPORT ADC_IRQHandler [WEAK] + EXPORT CKFAIL_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + +BOD_IRQHandler +WDT_IRQHandler +EINT024_IRQHandler +EINT135_IRQHandler +GPABGH_IRQHandler +GPCDEF_IRQHandler +PWM0_IRQHandler +PWM1_IRQHandler +TMR0_IRQHandler +TMR1_IRQHandler +TMR2_IRQHandler +TMR3_IRQHandler +UART02_IRQHandler +UART13_IRQHandler +SPI0_IRQHandler +QSPI0_IRQHandler +ISP_IRQHandler +UART57_IRQHandler +I2C0_IRQHandler +I2C1_IRQHandler +BPWM0_IRQHandler +BPWM1_IRQHandler +USCI01_IRQHandler +USBD_IRQHandler +ACMP01_IRQHandler +PDMA_IRQHandler +UART46_IRQHandler +PWRWU_IRQHandler +ADC_IRQHandler +CKFAIL_IRQHandler +RTC_IRQHandler + B . + ENDP + + + ALIGN + + +; User Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, = (Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/GCC/startup_M031Series.S b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/GCC/startup_M031Series.S new file mode 100644 index 0000000000..365f092a23 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/GCC/startup_M031Series.S @@ -0,0 +1,229 @@ +/**************************************************************************//** + * @file startup_m031series.s + * @version V2.00 + * $Revision: 6 $ + * $Date: 18/04/12 4:44p $ + * @brief CMSIS Cortex-M0 Core Device Startup File for M031 + * + * @note + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + ******************************************************************************/ + + .syntax unified + .cpu cortex-m0 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: +/* Unlock Register */ + ldr r0, =0x40000100 + ldr r1, =0x59 + str r1, [r0] + ldr r1, =0x16 + str r1, [r0] + ldr r1, =0x88 + str r1, [r0] + +#if 1 +/* Init POR */ + ldr r0, =0x40000024 + ldr r1, =0x00005AA5 + str r1, [r0] + +/* Init LDO_RDY */ + ldr r0, =0x40000280 + ldr r1, =0x00000001 + str r1, [r0] +#endif + /* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss + +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2, #4] + adds r2, r2, #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + /* Call the clock system intitialization function.*/ + bl SystemInit + +/* Lock register */ + ldr r0, =0x40000100 + ldr r1, =0 + str r1, [r0] + +/* Call the application entry point.*/ + + bl entry + bx lr + +.size Reset_Handler, . - Reset_Handler +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + + .size Default_Handler, .-Default_Handler +/******************************************************************************* +* +* The minimal vector table for a Cortex M0. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +*******************************************************************************/ + + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + +g_pfnVectors: + .long _estack /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long NMI_Handler /* NMI Handler */ + .long HardFault_Handler /* Hard Fault Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long SVC_Handler /* SVCall Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long PendSV_Handler /* PendSV Handler */ + .long SysTick_Handler /* SysTick Handler */ + + /* External interrupts */ + .long BOD_IRQHandler /* 0: BOD */ + .long WDT_IRQHandler /* 1: WDT */ + .long EINT024_IRQHandler /* 2: EINT0 */ + .long EINT135_IRQHandler /* 3: EINT1 */ + .long GPABGH_IRQHandler /* 4: GPAB */ + .long GPCDEF_IRQHandler /* 5: GPCDEF */ + .long PWM0_IRQHandler /* 6: PWM0 */ + .long PWM1_IRQHandler /* 7: PWM1 */ + .long TMR0_IRQHandler /* 8: TIMER0 */ + .long TMR1_IRQHandler /* 9: TIMER1 */ + .long TMR2_IRQHandler /* 10: TIMER2 */ + .long TMR3_IRQHandler /* 11: TIMER3 */ + .long UART02_IRQHandler /* 12: UART02 */ + .long UART13_IRQHandler /* 13: UART13 */ + .long SPI0_IRQHandler /* 14: SPI0 */ + .long QSPI0_IRQHandler /* 15: QSPI0 */ + .long ISP_IRQHandler /* 16: Reserved */ + .long UART57_IRQHandler /* 17: UART57 */ + .long I2C0_IRQHandler /* 18: I2C0 */ + .long I2C1_IRQHandler /* 19: I2C1 */ + .long BPWM0_IRQHandler /* 20: BPWM0 */ + .long BPWM1_IRQHandler /* 21: BPWM1 */ + .long USCI01_IRQHandler /* 22: USCI01 */ + .long USBD_IRQHandler /* 23: USBD */ + .long Default_Handler /* 24: Reserved */ + .long ACMP01_IRQHandler /* 25: ACMP01 */ + .long PDMA_IRQHandler /* 26: PDMA */ + .long UART46_IRQHandler /* 27: UART46 */ + .long PWRWU_IRQHandler /* 28: PWRWU */ + .long ADC_IRQHandler /* 29: ADC */ + .long CKFAIL_IRQHandler /* 30: CLK Fail Detect */ + .long RTC_IRQHandler /* 31: RTC */ +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler NMI_Handler + def_irq_handler HardFault_Handler + def_irq_handler SVC_Handler + def_irq_handler PendSV_Handler + def_irq_handler SysTick_Handler + def_irq_handler BOD_IRQHandler + def_irq_handler WDT_IRQHandler + def_irq_handler EINT024_IRQHandler + def_irq_handler EINT135_IRQHandler + def_irq_handler GPABGH_IRQHandler + def_irq_handler GPCDEF_IRQHandler + def_irq_handler PWM0_IRQHandler + def_irq_handler PWM1_IRQHandler + def_irq_handler TMR0_IRQHandler + def_irq_handler TMR1_IRQHandler + def_irq_handler TMR2_IRQHandler + def_irq_handler TMR3_IRQHandler + def_irq_handler UART02_IRQHandler + def_irq_handler UART13_IRQHandler + def_irq_handler SPI0_IRQHandler + def_irq_handler QSPI0_IRQHandler + def_irq_handler ISP_IRQHandler + def_irq_handler UART57_IRQHandler + def_irq_handler I2C0_IRQHandler + def_irq_handler I2C1_IRQHandler + def_irq_handler BPWM0_IRQHandler + def_irq_handler BPWM1_IRQHandler + def_irq_handler USCI01_IRQHandler + def_irq_handler USBD_IRQHandler + def_irq_handler ACMP01_IRQHandler + def_irq_handler PDMA_IRQHandler + def_irq_handler UART46_IRQHandler + def_irq_handler PWRWU_IRQHandler + def_irq_handler ADC_IRQHandler + def_irq_handler CKFAIL_IRQHandler + def_irq_handler RTC_IRQHandler + + + + .end diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/IAR/startup_M031Series.s b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/IAR/startup_M031Series.s new file mode 100644 index 0000000000..6d9f364364 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/IAR/startup_M031Series.s @@ -0,0 +1,202 @@ +;/**************************************************************************//** +; * @file startup_M031Series.s +; * @version V3.00 +; * $Revision: 5 $ +; * $Date: 18/04/02 4:02p $ +; * @brief M031 Series Startup Source File for IAR Platform +; * +; * @note +; * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +; * +; ******************************************************************************/ + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) ;; 8 bytes alignment + + SECTION .intvec:CODE:NOROOT(2);; 4 bytes alignment + + EXTERN SystemInit + EXTERN __iar_program_start + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) + DCD Reset_Handler + + DCD NMI_Handler + DCD HardFault_Handler + DCD 0 + DCD 0 + DCD 0 + DCD 0 + DCD 0 + DCD 0 + DCD 0 + DCD SVC_Handler + DCD 0 + DCD 0 + DCD PendSV_Handler + DCD SysTick_Handler + + ; External Interrupts + DCD BOD_IRQHandler ; Brownout low voltage detected interrupt + DCD WDT_IRQHandler ; Watch Dog Timer interrupt + DCD EINT024_IRQHandler + DCD EINT135_IRQHandler + DCD GPABGH_IRQHandler + DCD GPCDEF_IRQHandler + DCD PWM0_IRQHandler ; PWM0 or PWM2 interrupt + DCD PWM1_IRQHandler ; PWM1 or PWM3 interrupt + DCD TMR0_IRQHandler ; Timer 0 interrupt + DCD TMR1_IRQHandler ; Timer 1 interrupt + DCD TMR2_IRQHandler ; Timer 2 interrupt + DCD TMR3_IRQHandler ; Timer 3 interrupt + DCD UART02_IRQHandler + DCD UART13_IRQHandler + DCD SPI0_IRQHandler + DCD QSPI0_IRQHandler + DCD ISP_IRQHandler + DCD UART57_IRQHandler + DCD I2C0_IRQHandler + DCD I2C1_IRQHandler + DCD BPWM0_IRQHandler + DCD BPWM1_IRQHandler + DCD USCI01_IRQHandler + DCD USBD_IRQHandler + DCD Default_Handler + DCD ACMP01_IRQHandler + DCD PDMA_IRQHandler + DCD UART46_IRQHandler + DCD PWRWU_IRQHandler ; Clock controller interrupt for chip wake up from power-down + DCD ADC_IRQHandler ; ADC interrupt + DCD CKFAIL_IRQHandler ; Clock fail detect and IRC TRIM interrupt + DCD RTC_IRQHandler + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + PUBWEAK Reset_Handler + SECTION .text:CODE:REORDER:NOROOT(2) ; 4 bytes alignment +Reset_Handler + LDR R0, =0x40000100 + ; Unlock Register + LDR R1, =0x59 + STR R1, [R0] + LDR R1, =0x16 + STR R1, [R0] + LDR R1, =0x88 + STR R1, [R0] + + ; Init POR + LDR R2, =0x40000024 + LDR R1, =0x00005AA5 + STR R1, [R2] + + ; Init LDO_RDY + LDR R2, =0x40000280 + LDR R1, =0x00000001 + STR R1, [R2] + + ; Disable NMI (Assign to reserved IRQ) + LDR R2, =0x40000380 + LDR R1, =0x0000001F + STR R1, [R2] + + ; Lock register + MOVS R1, #0 + STR R1, [R0] + + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK HardFault_Handler + PUBWEAK NMI_Handler + PUBWEAK SVC_Handler + PUBWEAK PendSV_Handler + PUBWEAK SysTick_Handler + PUBWEAK BOD_IRQHandler + PUBWEAK WDT_IRQHandler + PUBWEAK EINT024_IRQHandler + PUBWEAK EINT135_IRQHandler + PUBWEAK GPABGH_IRQHandler + PUBWEAK GPCDEF_IRQHandler + PUBWEAK PWM0_IRQHandler + PUBWEAK PWM1_IRQHandler + PUBWEAK TMR0_IRQHandler + PUBWEAK TMR1_IRQHandler + PUBWEAK TMR2_IRQHandler + PUBWEAK TMR3_IRQHandler + PUBWEAK UART02_IRQHandler + PUBWEAK UART13_IRQHandler + PUBWEAK SPI0_IRQHandler + PUBWEAK QSPI0_IRQHandler + PUBWEAK ISP_IRQHandler + PUBWEAK UART57_IRQHandler + PUBWEAK I2C0_IRQHandler + PUBWEAK I2C1_IRQHandler + PUBWEAK BPWM0_IRQHandler + PUBWEAK BPWM1_IRQHandler + PUBWEAK USCI01_IRQHandler + PUBWEAK USBD_IRQHandler + PUBWEAK ACMP01_IRQHandler + PUBWEAK PDMA_IRQHandler + PUBWEAK UART46_IRQHandler + PUBWEAK PWRWU_IRQHandler + PUBWEAK ADC_IRQHandler + PUBWEAK CKFAIL_IRQHandler + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:REORDER:NOROOT(2) + +HardFault_Handler +NMI_Handler +SVC_Handler +PendSV_Handler +SysTick_Handler +BOD_IRQHandler +WDT_IRQHandler +EINT024_IRQHandler +EINT135_IRQHandler +GPABGH_IRQHandler +GPCDEF_IRQHandler +PWM0_IRQHandler +PWM1_IRQHandler +TMR0_IRQHandler +TMR1_IRQHandler +TMR2_IRQHandler +TMR3_IRQHandler +UART02_IRQHandler +UART13_IRQHandler +SPI0_IRQHandler +QSPI0_IRQHandler +ISP_IRQHandler +UART57_IRQHandler +I2C0_IRQHandler +I2C1_IRQHandler +BPWM0_IRQHandler +BPWM1_IRQHandler +USCI01_IRQHandler +USBD_IRQHandler +ACMP01_IRQHandler +PDMA_IRQHandler +UART46_IRQHandler +PWRWU_IRQHandler +ADC_IRQHandler +CKFAIL_IRQHandler +RTC_IRQHandler +Default_Handler + + B Default_Handler + + + END + diff --git a/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/system_M031Series.c b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/system_M031Series.c new file mode 100644 index 0000000000..dea5e692d7 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/Nuvoton/M031/Source/system_M031Series.c @@ -0,0 +1,130 @@ +/**************************************************************************//** + * @file system_M031Series.c + * @version V2.00 + * $Revision: 5 $ + * $Date: 18/07/19 1:44p $ + * @brief M031 Series System Setting Source File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2017 Nuvoton Technology Corp. All rights reserved. + * + ******************************************************************************/ +#include +#include +#include "NuMicro.h" + + + +/*---------------------------------------------------------------------------- + Clock Variable definitions + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = __HSI; /*!< System Clock Frequency (Core Clock) */ +uint32_t CyclesPerUs = (__HSI / 1000000); /*!< Cycles per micro second */ +uint32_t PllClock = __HSI; /*!< PLL Output Clock Frequency */ +const uint32_t gau32ClkSrcTbl[] = {__HXT, __LXT, __HSI, __LIRC, __HIRC, 0UL, 0UL, __HIRC}; + + +/** + * @brief Update the Variable SystemCoreClock + * + * @param None + * + * @return None + * + * @details This function is used to update the variable SystemCoreClock + * and must be called whenever the core clock is changed. + */ +void SystemCoreClockUpdate(void) +{ + uint32_t u32Freq, u32ClkSrc; + uint32_t u32HclkDiv; + + u32ClkSrc = CLK->CLKSEL0 & CLK_CLKSEL0_HCLKSEL_Msk; + + /* Update PLL Clock */ + PllClock = CLK_GetPLLClockFreq(); + + if(u32ClkSrc != CLK_CLKSEL0_HCLKSEL_PLL) + { + /* Use the clock sources directly */ + u32Freq = gau32ClkSrcTbl[u32ClkSrc]; + } + else + { + /* Use PLL clock */ + u32Freq = PllClock; + } + + u32HclkDiv = (CLK->CLKDIV0 & CLK_CLKDIV0_HCLKDIV_Msk) + 1; + + /* Update System Core Clock */ + SystemCoreClock = u32Freq / u32HclkDiv; + + CyclesPerUs = (SystemCoreClock + 500000) / 1000000; +} + + +/** + * @brief System Initialization + * + * @param None + * + * @return None + * + * @details The necessary initialization of system. Global variables are forbidden here. + */ +void SystemInit(void) +{ + /* Unlock protected registers */ + SYS_UnlockReg(); + + /* Set HXTGain Level dependend on HXT Frequency */ + CLK->PWRCTL = CLK->PWRCTL & ~CLK_PWRCTL_HXTGAIN_Msk; + if ((__HXT >= FREQ_4MHZ) && (__HXT < FREQ_8MHZ)) + { + CLK->PWRCTL |= (1 << CLK_PWRCTL_HXTGAIN_Pos); + } + else if ((__HXT >= FREQ_8MHZ) && (__HXT < FREQ_12MHZ)) + { + CLK->PWRCTL |= (2 << CLK_PWRCTL_HXTGAIN_Pos); + } + else if ((__HXT >= FREQ_12MHZ) && (__HXT < FREQ_16MHZ)) + { + CLK->PWRCTL |= (3 << CLK_PWRCTL_HXTGAIN_Pos); + } + else if ((__HXT >= FREQ_16MHZ) && (__HXT < FREQ_24MHZ)) + { + CLK->PWRCTL |= (4 << CLK_PWRCTL_HXTGAIN_Pos); + } + else + { + CLK->PWRCTL |= (7 << CLK_PWRCTL_HXTGAIN_Pos); + } + + /* Lock protected registers */ + SYS_LockReg(); +} + +#if USE_ASSERT + +/** + * @brief Assert Error Message + * + * @param[in] file the source file name + * @param[in] line line number + * + * @return None + * + * @details The function prints the source file name and line number where + * the ASSERT_PARAM() error occurs, and then stops in an infinite loop. + */ +void AssertError(uint8_t * file, uint32_t line) +{ + + printf("[%s] line %d : wrong parameters.\r\n", file, line); + + /* Infinite loop */ + while(1) ; +} +#endif diff --git a/bsp/nuvoton/libraries/m031/Device/SConscript b/bsp/nuvoton/libraries/m031/Device/SConscript new file mode 100644 index 0000000000..6513b60c71 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/Device/SConscript @@ -0,0 +1,25 @@ +import rtconfig +Import('RTT_ROOT') +from building import * + +# get current directory +cwd = GetCurrentDir() + +# The set of source files associated with this SConscript file. +src = Split(""" +Nuvoton/M031/Source/system_M031Series.c +""") + +# add for startup script +if rtconfig.CROSS_TOOL == 'gcc': + src = src + ['Nuvoton/M031/Source/GCC/startup_M031Series.S'] +elif rtconfig.CROSS_TOOL == 'keil': + src = src + ['Nuvoton/M031/Source/ARM/startup_M031Series.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src = src + ['Nuvoton/M031/Source/IAR/startup_M031Series.s'] + +path = [cwd + '/Nuvoton/M031/Include',] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) + +Return('group') diff --git a/bsp/nuvoton/libraries/m031/README.md b/bsp/nuvoton/libraries/m031/README.md new file mode 100644 index 0000000000..ca60d25182 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/README.md @@ -0,0 +1,35 @@ +# M031 Series + +## Supported drivers + +| Peripheral | rt_device_class_type | Device name | +| ------ | ---- | :------: | +| ADC | RT_Device_Class_Miscellaneous (ADC) | ***adc0*** | +| BPWM | RT_Device_Class_Miscellaneous (PWM) | ***bpwm[0-1]*** | +| BPWM (Capture function)| RT_Device_Class_Miscellaneous (Input capture) | ***bpwm[0-1]i[0-5]*** | +| CLK | RT_Device_Class_PM | ***pm*** | +| CRC | RT_Device_Class_Miscellaneous (HW Crypto) | ***hwcryto*** | +| EBI | N/A | ***N/A*** | +| FMC | FAL | ***N/A*** | +| GPIO | RT_Device_Class_Miscellaneous (Pin) | ***gpio*** | +| GPIO | RT_Device_Class_I2CBUS | ***softi2c0[0-1]*** | +| I2C | RT_Device_Class_I2CBUS | ***i2c[0-1]*** | +| PDMA | N/A | ***N/A*** | +| PWM | RT_Device_Class_Miscellaneous (PWM) | ***pwm[0-1]*** | +| PWM (Capture function) | RT_Device_Class_Miscellaneous (Input capture) | ***pwm[0-1]i[0-5]*** | +| QSPI | RT_Device_Class_SPIBUS | ***qspi0*** | +| RTC | RT_Device_Class_RTC | ***rtc*** | +| SPI | RT_Device_Class_SPIBUS | ***spi0*** | +| SPI (I2S function) | RT_Device_Class_Sound/RT_Device_Class_Pipe | ***spii2s0*** | +| TIMER | RT_Device_Class_Timer | ***timer[0-3]*** | +| TIMER (Capture function) | RT_Device_Class_Miscellaneous (Input capture) | ***timer[0-3]i0*** | +| UART | RT_Device_Class_Char | ***uart[0-7]*** | +| USBD | RT_Device_Class_USBDevice | ***usbd*** | +| USCI (I2C function) | RT_Device_Class_I2CBUS | ***ui2c[0-1]*** | +| USCI (SPI function) | RT_Device_Class_SPIBUS | ***uspi[0-1]*** | +| USCI (UART function) | RT_Device_Class_Char | ***uuart[0-1]*** | +| WDT | RT_Device_Class_Miscellaneous (Watchdog) | ***wdt*** | + + +## Resources +* [Download M031 TRM](https://www.nuvoton.com/resource-download.jsp?tp_GUID=DA05-M031) diff --git a/bsp/nuvoton/libraries/m031/SConscript b/bsp/nuvoton/libraries/m031/SConscript new file mode 100644 index 0000000000..c7ef7659ec --- /dev/null +++ b/bsp/nuvoton/libraries/m031/SConscript @@ -0,0 +1,14 @@ +# for module compiling +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/nuvoton/libraries/m031/StdDriver/SConscript b/bsp/nuvoton/libraries/m031/StdDriver/SConscript new file mode 100644 index 0000000000..57025d2246 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/SConscript @@ -0,0 +1,28 @@ +# RT-Thread building script for component +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +libs = [] +src = Glob('*src/*.c') + Glob('src/*.cpp') +cpppath = [cwd + '/inc'] +libpath = [cwd + '/lib'] + +if not GetDepend('BSP_USE_STDDRIVER_SOURCE'): + if rtconfig.CROSS_TOOL == 'keil': + if GetOption('target') == 'mdk5' and os.path.isfile('./lib/libstddriver_keil.lib'): + libs += ['libstddriver_keil'] + elif GetOption('target') == 'mdk4' and os.path.isfile('./lib/libstddriver_keil4.lib'): + libs += ['libstddriver_keil4'] + elif rtconfig.CROSS_TOOL == 'gcc' and os.path.isfile('./lib/libstddriver_gcc.a'): + libs += ['libstddriver_gcc'] + elif os.path.isfile('./lib/libstddriver_iar.a'): + libs += ['libstddriver_iar'] + +if not libs: + group = DefineGroup('Libraries', src, depend = [''], CPPPATH = cpppath) +else: + src = [] + group = DefineGroup('Libraries', src, depend = [''], CPPPATH = cpppath, LIBS = libs, LIBPATH = libpath) + +Return('group') diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_acmp.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_acmp.h new file mode 100644 index 0000000000..4f09de47da --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_acmp.h @@ -0,0 +1,401 @@ +/**************************************************************************//** + * @file nu_acmp.h + * @version V0.10 + * $Revision: 2 $ + * $Date: 18/12/21 10:53a $ + * @brief M031 Series ACMP Driver Header File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_ACMP_H__ +#define __NU_ACMP_H__ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Include related headers */ +/*---------------------------------------------------------------------------------------------------------*/ +#include "M031Series.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup ACMP_Driver ACMP Driver + @{ +*/ + + +/** @addtogroup ACMP_EXPORTED_CONSTANTS ACMP Exported Constants + @{ +*/ + + +/*---------------------------------------------------------------------------------------------------------*/ +/* ACMP_CTL constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define ACMP_CTL_FILTSEL_OFF (0UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for filter function disabled. \hideinitializer */ +#define ACMP_CTL_FILTSEL_1PCLK (1UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 1 PCLK filter count. \hideinitializer */ +#define ACMP_CTL_FILTSEL_2PCLK (2UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 2 PCLK filter count. \hideinitializer */ +#define ACMP_CTL_FILTSEL_4PCLK (3UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 4 PCLK filter count. \hideinitializer */ +#define ACMP_CTL_FILTSEL_8PCLK (4UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 8 PCLK filter count. \hideinitializer */ +#define ACMP_CTL_FILTSEL_16PCLK (5UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 16 PCLK filter count. \hideinitializer */ +#define ACMP_CTL_FILTSEL_32PCLK (6UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 32 PCLK filter count. \hideinitializer */ +#define ACMP_CTL_FILTSEL_64PCLK (7UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 64 PCLK filter count. \hideinitializer */ +#define ACMP_CTL_INTPOL_RF (0UL << ACMP_CTL_INTPOL_Pos) /*!< ACMP_CTL setting for selecting rising edge and falling edge as interrupt condition. \hideinitializer */ +#define ACMP_CTL_INTPOL_R (1UL << ACMP_CTL_INTPOL_Pos) /*!< ACMP_CTL setting for selecting rising edge as interrupt condition. \hideinitializer */ +#define ACMP_CTL_INTPOL_F (2UL << ACMP_CTL_INTPOL_Pos) /*!< ACMP_CTL setting for selecting falling edge as interrupt condition. \hideinitializer */ +#define ACMP_CTL_POSSEL_P0 (0UL << ACMP_CTL_POSSEL_Pos) /*!< ACMP_CTL setting for selecting ACMPx_P0 pin as the source of ACMP V+. \hideinitializer */ +#define ACMP_CTL_POSSEL_P1 (1UL << ACMP_CTL_POSSEL_Pos) /*!< ACMP_CTL setting for selecting ACMPx_P1 pin as the source of ACMP V+. \hideinitializer */ +#define ACMP_CTL_POSSEL_P2 (2UL << ACMP_CTL_POSSEL_Pos) /*!< ACMP_CTL setting for selecting ACMPx_P2 pin as the source of ACMP V+. \hideinitializer */ +#define ACMP_CTL_POSSEL_P3 (3UL << ACMP_CTL_POSSEL_Pos) /*!< ACMP_CTL setting for selecting ACMPx_P3 pin as the source of ACMP V+. \hideinitializer */ +#define ACMP_CTL_NEGSEL_PIN (0UL << ACMP_CTL_NEGSEL_Pos) /*!< ACMP_CTL setting for selecting the voltage of ACMP negative input pin as the source of ACMP V-. \hideinitializer */ +#define ACMP_CTL_NEGSEL_CRV (1UL << ACMP_CTL_NEGSEL_Pos) /*!< ACMP_CTL setting for selecting internal comparator reference voltage as the source of ACMP V-. \hideinitializer */ +#define ACMP_CTL_NEGSEL_VBG (2UL << ACMP_CTL_NEGSEL_Pos) /*!< ACMP_CTL setting for selecting internal Band-gap voltage as the source of ACMP V-. \hideinitializer */ +#define ACMP_CTL_HYSTERESIS_ENABLE (1UL << ACMP_CTL_HYSEN_Pos) /*!< ACMP_CTL setting for enabling the hysteresis function. \hideinitializer */ +#define ACMP_CTL_HYSTERESIS_DISABLE (0UL << ACMP_CTL_HYSEN_Pos) /*!< ACMP_CTL setting for disabling the hysteresis function. \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* ACMP_VREF constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define ACMP_VREF_CRVSSEL_VDDA (0UL << ACMP_VREF_CRVSSEL_Pos) /*!< ACMP_VREF setting for selecting analog supply voltage VDDA as the CRV source voltage \hideinitializer */ +#define ACMP_VREF_CRVSSEL_INTVREF (1UL << ACMP_VREF_CRVSSEL_Pos) /*!< ACMP_VREF setting for selecting internal reference voltage as the CRV source voltage \hideinitializer */ + + +/*@}*/ /* end of group ACMP_EXPORTED_CONSTANTS */ + + +/** @addtogroup ACMP_EXPORTED_FUNCTIONS ACMP Exported Functions + @{ +*/ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Define Macros and functions */ +/*---------------------------------------------------------------------------------------------------------*/ + + +/** + * @brief This macro is used to enable output inverse function + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will set ACMPOINV bit of ACMP_CTL register to enable output inverse function. + * \hideinitializer + */ +#define ACMP_ENABLE_OUTPUT_INVERSE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_ACMPOINV_Msk) + +/** + * @brief This macro is used to disable output inverse function + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will clear ACMPOINV bit of ACMP_CTL register to disable output inverse function. + * \hideinitializer + */ +#define ACMP_DISABLE_OUTPUT_INVERSE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_ACMPOINV_Msk) + +/** + * @brief This macro is used to select ACMP negative input source + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @param[in] u32Src is comparator negative input selection. Including: + * - \ref ACMP_CTL_NEGSEL_PIN + * - \ref ACMP_CTL_NEGSEL_CRV + * - \ref ACMP_CTL_NEGSEL_VBG + * @return None + * @details This macro will set NEGSEL (ACMP_CTL[5:4]) to determine the source of negative input. + * \hideinitializer + */ +#define ACMP_SET_NEG_SRC(acmp, u32ChNum, u32Src) ((acmp)->CTL[(u32ChNum)] = ((acmp)->CTL[(u32ChNum)] & ~ACMP_CTL_NEGSEL_Msk) | (u32Src)) + +/** + * @brief This macro is used to enable hysteresis function + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will set HYSEN bit of ACMP_CTL register to enable hysteresis function. + * \hideinitializer + */ +#define ACMP_ENABLE_HYSTERESIS(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_HYSEN_Msk) + +/** + * @brief This macro is used to disable hysteresis function + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will clear HYSEN bit of ACMP_CTL register to disable hysteresis function. + * \hideinitializer + */ +#define ACMP_DISABLE_HYSTERESIS(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_HYSEN_Msk) + +/** + * @brief This macro is used to enable interrupt + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will set ACMPIE bit of ACMP_CTL register to enable interrupt function. + * If wake-up function is enabled, the wake-up interrupt will be enabled as well. + * \hideinitializer + */ +#define ACMP_ENABLE_INT(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_ACMPIE_Msk) + +/** + * @brief This macro is used to disable interrupt + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will clear ACMPIE bit of ACMP_CTL register to disable interrupt function. + * \hideinitializer + */ +#define ACMP_DISABLE_INT(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_ACMPIE_Msk) + +/** + * @brief This macro is used to enable ACMP + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will set ACMPEN bit of ACMP_CTL register to enable analog comparator. + * \hideinitializer + */ +#define ACMP_ENABLE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_ACMPEN_Msk) + +/** + * @brief This macro is used to disable ACMP + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will clear ACMPEN bit of ACMP_CTL register to disable analog comparator. + * \hideinitializer + */ +#define ACMP_DISABLE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_ACMPEN_Msk) + +/** + * @brief This macro is used to get ACMP output value + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return ACMP output value + * @details This macro will return the ACMP output value. + * \hideinitializer + */ +#define ACMP_GET_OUTPUT(acmp, u32ChNum) (((acmp)->STATUS & (ACMP_STATUS_ACMPO0_Msk<<((u32ChNum))))?1:0) + +/** + * @brief This macro is used to get ACMP interrupt flag + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return ACMP interrupt occurred (1) or not (0) + * @details This macro will return the ACMP interrupt flag. + * \hideinitializer + */ +#define ACMP_GET_INT_FLAG(acmp, u32ChNum) (((acmp)->STATUS & (ACMP_STATUS_ACMPIF0_Msk<<((u32ChNum))))?1:0) + +/** + * @brief This macro is used to clear ACMP interrupt flag + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will write 1 to ACMPIFn bit of ACMP_STATUS register to clear interrupt flag. + * \hideinitializer + */ +#define ACMP_CLR_INT_FLAG(acmp, u32ChNum) ((acmp)->STATUS = (ACMP_STATUS_ACMPIF0_Msk<<((u32ChNum)))) + +/** + * @brief This macro is used to clear ACMP wake-up interrupt flag + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will write 1 to WKIFn bit of ACMP_STATUS register to clear interrupt flag. + * \hideinitializer + */ +#define ACMP_CLR_WAKEUP_INT_FLAG(acmp, u32ChNum) ((acmp)->STATUS = (ACMP_STATUS_WKIF0_Msk<<((u32ChNum)))) + +/** + * @brief This macro is used to enable ACMP wake-up function + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will set WKEN (ACMP_CTL[16]) to enable ACMP wake-up function. + * \hideinitializer + */ +#define ACMP_ENABLE_WAKEUP(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_WKEN_Msk) + +/** + * @brief This macro is used to disable ACMP wake-up function + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will clear WKEN (ACMP_CTL[16]) to disable ACMP wake-up function. + * \hideinitializer + */ +#define ACMP_DISABLE_WAKEUP(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_WKEN_Msk) + +/** + * @brief This macro is used to select ACMP positive input pin + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @param[in] u32Pin Comparator positive pin selection. Including: + * - \ref ACMP_CTL_POSSEL_P0 + * - \ref ACMP_CTL_POSSEL_P1 + * - \ref ACMP_CTL_POSSEL_P2 + * - \ref ACMP_CTL_POSSEL_P3 + * @return None + * @details This macro will set POSSEL (ACMP_CTL[7:6]) to determine the comparator positive input pin. + * \hideinitializer + */ +#define ACMP_SELECT_P(acmp, u32ChNum, u32Pin) ((acmp)->CTL[(u32ChNum)] = ((acmp)->CTL[(u32ChNum)] & ~ACMP_CTL_POSSEL_Msk) | (u32Pin)) + +/** + * @brief This macro is used to enable ACMP filter function + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will set OUTSEL (ACMP_CTL[12]) to enable output filter function. + * \hideinitializer + */ +#define ACMP_ENABLE_FILTER(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_OUTSEL_Msk) + +/** + * @brief This macro is used to disable ACMP filter function + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will clear OUTSEL (ACMP_CTL[12]) to disable output filter function. + * \hideinitializer + */ +#define ACMP_DISABLE_FILTER(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_OUTSEL_Msk) + +/** + * @brief This macro is used to set ACMP filter function + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @param[in] u32Cnt is comparator filter count setting. + * - \ref ACMP_CTL_FILTSEL_OFF + * - \ref ACMP_CTL_FILTSEL_1PCLK + * - \ref ACMP_CTL_FILTSEL_2PCLK + * - \ref ACMP_CTL_FILTSEL_4PCLK + * - \ref ACMP_CTL_FILTSEL_8PCLK + * - \ref ACMP_CTL_FILTSEL_16PCLK + * - \ref ACMP_CTL_FILTSEL_32PCLK + * - \ref ACMP_CTL_FILTSEL_64PCLK + * @return None + * @details When ACMP output filter function is enabled, the output sampling count is determined by FILTSEL (ACMP_CTL[15:13]). + * \hideinitializer + */ +#define ACMP_SET_FILTER(acmp, u32ChNum, u32Cnt) ((acmp)->CTL[(u32ChNum)] = ((acmp)->CTL[(u32ChNum)] & ~ACMP_CTL_FILTSEL_Msk) | (u32Cnt)) + +/** + * @brief This macro is used to select comparator reference voltage + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32Level The comparator reference voltage setting. + * The formula is: + * comparator reference voltage = CRV source voltage x (1/6 + u32Level/24) + * The range of u32Level is 0 ~ 15. + * @return None + * @details When CRV is selected as ACMP negative input source, the CRV level is determined by CRVCTL (ACMP_VREF[3:0]). + * \hideinitializer + */ +#define ACMP_CRV_SEL(acmp, u32Level) ((acmp)->VREF = ((acmp)->VREF & ~ACMP_VREF_CRVCTL_Msk) | ((u32Level)<VREF = ((acmp)->VREF & ~ACMP_VREF_CRVSSEL_Msk) | (u32Src)) + +/** + * @brief This macro is used to select ACMP interrupt condition + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @param[in] u32Cond Comparator interrupt condition selection. Including: + * - \ref ACMP_CTL_INTPOL_RF + * - \ref ACMP_CTL_INTPOL_R + * - \ref ACMP_CTL_INTPOL_F + * @return None + * @details The ACMP output interrupt condition can be rising edge, falling edge or any edge. + * \hideinitializer + */ +#define ACMP_SELECT_INT_COND(acmp, u32ChNum, u32Cond) ((acmp)->CTL[(u32ChNum)] = ((acmp)->CTL[(u32ChNum)] & ~ACMP_CTL_INTPOL_Msk) | (u32Cond)) + +/** + * @brief This macro is used to enable ACMP window latch mode + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will set WLATEN (ACMP_CTL[17]) to enable ACMP window latch mode. + * When ACMP0/1_WLAT pin is at high level, ACMPO0/1 passes through window latch + * block; when ACMP0/1_WLAT pin is at low level, the output of window latch block, + * WLATOUT, is frozen. + * \hideinitializer + */ +#define ACMP_ENABLE_WINDOW_LATCH(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_WLATEN_Msk) + +/** + * @brief This macro is used to disable ACMP window latch mode + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will clear WLATEN (ACMP_CTL[17]) to disable ACMP window latch mode. + * \hideinitializer + */ +#define ACMP_DISABLE_WINDOW_LATCH(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_WLATEN_Msk) + +/** + * @brief This macro is used to enable ACMP window compare mode + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will set WCMPSEL (ACMP_CTL[18]) to enable ACMP window compare mode. + * When window compare mode is enabled, user can connect the specific analog voltage + * source to either the positive inputs of both comparators or the negative inputs of + * both comparators. The upper bound and lower bound of the designated range are + * determined by the voltages applied to the other inputs of both comparators. If the + * output of a comparator is low and the other comparator outputs high, which means two + * comparators implies the upper and lower bound. User can directly monitor a specific + * analog voltage source via ACMPWO (ACMP_STATUS[16]). + * \hideinitializer + */ +#define ACMP_ENABLE_WINDOW_COMPARE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_WCMPSEL_Msk) + +/** + * @brief This macro is used to disable ACMP window compare mode + * @param[in] acmp The pointer of the specified ACMP module + * @param[in] u32ChNum The ACMP number + * @return None + * @details This macro will clear WCMPSEL (ACMP_CTL[18]) to disable ACMP window compare mode. + * \hideinitializer + */ +#define ACMP_DISABLE_WINDOW_COMPARE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_WCMPSEL_Msk) + + +/* Function prototype declaration */ +void ACMP_Open(ACMP_T *, uint32_t u32ChNum, uint32_t u32NegSrc, uint32_t u32HysteresisEn); +void ACMP_Close(ACMP_T *, uint32_t u32ChNum); + + + +/*@}*/ /* end of group ACMP_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group ACMP_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + + +#endif //__NU_ACMP_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_adc.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_adc.h new file mode 100644 index 0000000000..16cfca998f --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_adc.h @@ -0,0 +1,418 @@ +/**************************************************************************//** + * @file nu_adc.h + * @version V0.10 + * $Revision: 2 $ + * $Date: 19/01/11 11:23a $ + * @brief M031 Series ADC Driver Header File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_ADC_H__ +#define __NU_ADC_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup ADC_Driver ADC Driver + @{ +*/ + +/** @addtogroup ADC_EXPORTED_CONSTANTS ADC Exported Constants + @{ +*/ + +/*---------------------------------------------------------------------------------------------------------*/ +/* ADCR Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define ADC_ADCR_ADEN_CONVERTER_DISABLE (0UL<ADDR[(u32ChNum)] & ADC_ADDR_RSLT_Msk) + +/** + * @brief Return the user-specified interrupt flags. + * @param[in] adc The pointer of the specified ADC module. + * @param[in] u32Mask The combination of following interrupt status bits. Each bit corresponds to a interrupt status. + * Valid values are: + * - \ref ADC_ADF_INT :Convert complete interrupt flag. + * - \ref ADC_CMP0_INT :Comparator 0 interrupt flag. + * - \ref ADC_CMP1_INT :Comparator 1 interrupt flag. + * @return User specified interrupt flags. + * @details Get the status of the ADC interrupt flag. + * \hideinitializer + */ +#define ADC_GET_INT_FLAG(adc, u32Mask) ((adc)->ADSR0 & (u32Mask)) + +/** + * @brief This macro clear the selected interrupt status bits. + * @param[in] adc The pointer of the specified ADC module. + * @param[in] u32Mask The combination of following interrupt status bits. Each bit corresponds to a interrupt status. + * Valid values are: + * - \ref ADC_ADF_INT :Convert complete interrupt flag. + * - \ref ADC_CMP0_INT :Comparator 0 interrupt flag. + * - \ref ADC_CMP1_INT :Comparator 1 interrupt flag. + * @return None + * @details ADF (ADSR0[0])/CMPF0 (ADSR0[1])/CMPF1 (ADSR0[2]) can be cleared by writing 1 to itself. + * \hideinitializer + */ +#define ADC_CLR_INT_FLAG(adc, u32Mask) ((adc)->ADSR0 = (u32Mask)) + +/** + * @brief Get the busy state of ADC. + * @param[in] adc The pointer of the specified ADC module. + * @retval 0 ADC is not busy. + * @retval 1 ADC is busy. + * @details ADSR0[7] (BUSY) is a mirror of ADCR[11] (ADST). + * \hideinitializer + */ +#define ADC_IS_BUSY(adc) ((adc)->ADSR0 & ADC_ADSR0_BUSY_Msk ? 1 : 0) + +/** + * @brief Check if the ADC conversion data is over written or not. + * @param[in] adc The pointer of the specified ADC module. + * @param[in] u32ChNum ADC Channel, valid value are from 0 to 15 and 29. + * @retval 0 ADC data is not overrun. + * @retval 1 ADC data is overrun. + * @details ADSR2[31:0] (OVERRUN) is the mirror of ADDR0~31[16] OVERRUN bits. + * \hideinitializer + */ +#define ADC_IS_DATA_OVERRUN(adc, u32ChNum) (((adc)->ADSR2 & (1<<(u32ChNum))) ? 1 : 0) + +/** + * @brief Check if the ADC conversion data is valid or not. + * @param[in] adc The pointer of the specified ADC module. + * @param[in] u32ChNum ADC Channel, valid value are from 0 to 15 and 29. + * @retval 0 ADC data is not valid. + * @retval 1 ADC data is valid. + * @details VALID (ADDR0~31[17]) is set to 1 when corresponding channel analog input conversion is completed and cleared by hardware after ADDR register is read. + * \hideinitializer + */ +#define ADC_IS_DATA_VALID(adc, u32ChNum) ((adc)->ADSR1 & (0x1<<(u32ChNum)) ? 1 : 0) + +/** + * @brief Power down ADC module. + * @param[in] adc The pointer of the specified ADC module. + * @return None + * @details Disable A/D converter analog circuit for saving power consumption. + * \hideinitializer + */ +#define ADC_POWER_DOWN(adc) ((adc)->ADCR &= ~ADC_ADCR_ADEN_Msk) + +/** + * @brief Power on ADC module. + * @param[in] adc The pointer of the specified ADC module. + * @return None + * @details Before starting A/D conversion function, ADEN bit (ADCR[0]) should be set to 1. + * \hideinitializer + */ +#define ADC_POWER_ON(adc) ((adc)->ADCR |= ADC_ADCR_ADEN_Msk) + +/** + * @brief Configure the comparator 0 and enable it. + * @param[in] adc The pointer of the specified ADC module. + * @param[in] u32ChNum Specifies the source channel, valid value are from 0 to 15 and 29. + * @param[in] u32Condition Specifies the compare condition. Valid values are: + * - \ref ADC_ADCMPR_CMPCOND_LESS_THAN :The compare condition is "less than the compare value". + * - \ref ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL :The compare condition is "greater than or equal to the compare value". + * @param[in] u32Data Specifies the compare value, valid value are between 0 ~ 0xFFF. + * @param[in] u32MatchCount Specifies the match count setting, valid values are between 1~16. + * @return None + * @details For example, ADC_ENABLE_CMP0(ADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x800, 10); + * means ADC will assert comparator 0 flag if channel 5 conversion result is greater than or + * equal to 0x800 for 10 times continuously. + * \hideinitializer + */ +#define ADC_ENABLE_CMP0(adc, \ + u32ChNum, \ + u32Condition, \ + u32Data, \ + u32MatchCount) ((adc)->ADCMPR[0] = ((u32ChNum) << ADC_ADCMPR_CMPCH_Pos) | \ + (u32Condition) | \ + ((u32Data) << ADC_ADCMPR_CMPD_Pos) | \ + (((u32MatchCount) - 1) << ADC_ADCMPR_CMPMATCNT_Pos) |\ + ADC_ADCMPR_CMPEN_Msk) + +/** + * @brief Disable comparator 0 + * @param[in] adc The pointer of the specified ADC module + * @return None + * @details Set CMPEN (ADCMPR0[0]) to 0 and reset comparator 0 configurations to disable ADC compare function. + * \hideinitializer + */ +#define ADC_DISABLE_CMP0(adc) ((adc)->ADCMPR[0] = 0) + +/** + * @brief Configure the comparator 1 and enable it. + * @param[in] adc The pointer of the specified ADC module. + * @param[in] u32ChNum Specifies the source channel, valid value are from 0 to 15 and 29. + * @param[in] u32Condition Specifies the compare condition. Valid values are: + * - \ref ADC_ADCMPR_CMPCOND_LESS_THAN :The compare condition is "less than the compare value". + * - \ref ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL :The compare condition is "greater than or equal to the compare value". + * @param[in] u32Data Specifies the compare value, valid value are between 0 ~ 0xFFF. + * @param[in] u32MatchCount Specifies the match count setting, valid values are between 1~16. + * @return None + * @details For example, ADC_ENABLE_CMP1(ADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x800, 10); + * means ADC will assert comparator 1 flag if channel 5 conversion result is greater than or + * equal to 0x800 for 10 times continuously. + * \hideinitializer + */ +#define ADC_ENABLE_CMP1(adc, \ + u32ChNum, \ + u32Condition, \ + u32Data, \ + u32MatchCount) ((adc)->ADCMPR[1] = ((u32ChNum) << ADC_ADCMPR_CMPCH_Pos) | \ + (u32Condition) | \ + ((u32Data) << ADC_ADCMPR_CMPD_Pos) | \ + (((u32MatchCount) - 1) << ADC_ADCMPR_CMPMATCNT_Pos) |\ + ADC_ADCMPR_CMPEN_Msk) + +/** + * @brief Disable comparator 1. + * @param[in] adc The pointer of the specified ADC module. + * @return None + * @details Set CMPEN (ADCMPR1[0]) to 0 and reset comparator 1 configurations to disable ADC compare function. + * \hideinitializer + */ +#define ADC_DISABLE_CMP1(adc) ((adc)->ADCMPR[1] = 0) + +/** + * @brief Enable the compare window mode. + * @param[in] adc The pointer of the specified ADC module. + * @param[in] u32CMP Specifies the compare register, valid value are 0. + * @return None + * @details CMPF0 (ADSR0[1]) will be set when both ADC_CMP0 and ADC_CMP1 compared condition matched. + * \hideinitializer + */ +#define ADC_ENABLE_CMP_WINDOW_MODE(adc, u32CMP) ((adc)->ADCMPR[(u32CMP)] |= ADC_ADCMPR_CMPWEN_Msk) + +/** + * @brief Disable the compare window mode. + * @param[in] adc The pointer of the specified ADC module. + * @param[in] u32CMP Specifies the compare register, valid value are 0. + * @return None + * @details Disable the compare window mode for specified ADC module. + * \hideinitializer + */ +#define ADC_DISABLE_CMP_WINDOW_MODE(adc, u32CMP) ((adc)->ADCMPR[(u32CMP)] &= ~ADC_ADCMPR_CMPWEN_Msk) + +/** + * @brief Set ADC input channel. + * @param[in] adc The pointer of the specified ADC module. + * @param[in] u32Mask Channel enable bit. Each bit corresponds to a input channel. Bit 0 is channel 0, bit 1 is channel 1..., bit 15 is channel 15. + * @return None + * @details Enabled channel will be converted while ADC starts. + * @note In single mode, ADC can only convert 1 channel. If more than 1 channel are enabled, only the channel with smallest number will be converted. + * \hideinitializer + */ +#define ADC_SET_INPUT_CHANNEL(adc, u32Mask) ((adc)->ADCHER = ((adc)->ADCHER & ~ADC_ADCHER_CHEN_Msk) | (u32Mask)) + +/** + * @brief Set the output format mode. + * @param[in] adc The pointer of the specified ADC module. + * @param[in] u32Format Decides the output format. Valid values are: + * - \ref ADC_ADCR_DMOF_UNSIGNED_OUTPUT : Select the straight binary format as the output format of the conversion result. + * - \ref ADC_ADCR_DMOF_TWOS_COMPLEMENT : Select the 2's complement format as the output format of the conversion result. + * @return None + * @details The macro is used to set the output format of ADC differential input mode. + * @note ADC compare function can not support 2's complement output format, u32Format should be set to ADC_ADCR_DMOF_UNSIGNED_OUTPUT. + * \hideinitializer + */ +#define ADC_SET_DMOF(adc, u32Format) ((adc)->ADCR = ((adc)->ADCR & ~ADC_ADCR_DMOF_Msk) | (u32Format)) + +/** + * @brief Start the A/D conversion. + * @param[in] adc The pointer of the specified ADC module. + * @return None + * @details Set ADST bit to 1 to start the A/D conversion. + * \hideinitializer + */ +#define ADC_START_CONV(adc) ((adc)->ADCR |= ADC_ADCR_ADST_Msk) + +/** + * @brief Stop the A/D conversion. + * @param[in] adc The pointer of the specified ADC module. + * @return None + * @details ADST (ADCR[11]) will be cleared to 0 by hardware automatically at the ends of single mode and single-cycle scan mode. + * In continuous scan mode and burst mode, A/D conversion is continuously performed until software writes 0 to this bit. + * @note When the ADST bit is cleared to 0, the ADST bit must be kept at 0 at least one ADC peripheral clock period + * before setting it to 1 again, otherwise the A/D converter may not work. + * If ADST bit is cleared to 0 when ADC is in converting, the BUSY bit will be cleared to 0 immediately, + * ADC will terminate the current conversion and enter idle state directly. + * \hideinitializer + */ +#define ADC_STOP_CONV(adc) ((adc)->ADCR &= ~ADC_ADCR_ADST_Msk) + +/** + * @brief Enable PDMA transfer. + * @param[in] adc The pointer of the specified ADC module + * @return None + * @details Enable PDMA to transfer the conversion data. + * @note While enable PDMA transfer, software must set ADIE = 0 to disable interrupt. + * \hideinitializer + */ +#define ADC_ENABLE_PDMA(adc) ((adc)->ADCR |= ADC_ADCR_PTEN_Msk) + +/** + * @brief Disable PDMA transfer. + * @param[in] adc The pointer of the specified ADC module + * @return None + * @details Disable PDMA to transfer the conversion data. + * \hideinitializer + */ +#define ADC_DISABLE_PDMA(adc) ((adc)->ADCR &= ~ADC_ADCR_PTEN_Msk) + +/** + * @brief Get PDMA current transfer data + * @param[in] adc The pointer of the specified ADC module. + * @return PDMA current transfer data + * \hideinitializer + */ +#define ADC_GET_PDMA_DATA(adc) ((adc)->ADPDMA & ADC_ADPDMA_CURDAT_Msk) + +/** + * @brief Enable the interrupt(s) selected by u32Mask parameter. + * @param[in] adc The pointer of the specified ADC module + * @param[in] u32Mask The combination of interrupt status bits listed below. Each bit + * corresponds to a interrupt status. This parameter decides which + * interrupts will be enabled. + * - \ref ADC_ADF_INT :ADC convert complete interrupt + * - \ref ADC_CMP0_INT :ADC comparator 0 interrupt + * - \ref ADC_CMP1_INT :ADC comparator 1 interrupt + * @return None + * \hideinitializer + */ +#define ADC_ENABLE_INT ADC_EnableInt + +/** + * @brief Disable the interrupt(s) selected by u32Mask parameter. + * @param[in] adc The pointer of the specified ADC module + * @param[in] u32Mask The combination of interrupt status bits listed below. Each bit + * corresponds to a interrupt status. This parameter decides which + * interrupts will be disabled. + * - \ref ADC_ADF_INT :ADC convert complete interrupt + * - \ref ADC_CMP0_INT :ADC comparator 0 interrupt + * - \ref ADC_CMP1_INT :ADC comparator 1 interrupt + * @return None + * \hideinitializer + */ +#define ADC_DISABLE_INT ADC_DisableInt + + +void ADC_Open(ADC_T *adc, + uint32_t u32InputMode, + uint32_t u32OpMode, + uint32_t u32ChMask); +void ADC_Close(ADC_T *adc); +void ADC_EnableHWTrigger(ADC_T *adc, + uint32_t u32Source, + uint32_t u32Param); +void ADC_DisableHWTrigger(ADC_T *adc); +void ADC_EnableInt(ADC_T *adc, uint32_t u32Mask); +void ADC_DisableInt(ADC_T *adc, uint32_t u32Mask); +void ADC_SetExtendSampleTime(ADC_T *adc, + uint32_t u32ModuleNum, + uint32_t u32ExtendSampleTime); + + +/*@}*/ /* end of group ADC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group ADC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_ADC_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_bpwm.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_bpwm.h new file mode 100644 index 0000000000..538963760c --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_bpwm.h @@ -0,0 +1,379 @@ +/****************************************************************************** + * @file nu_bpwm.h + * @version V1.00 + * $Revision: 9 $ + * $Date: 18/06/07 3:47p $ + * @brief M031 series BPWM driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_BPWM_H__ +#define __NU_BPWM_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup BPWM_Driver BPWM Driver + @{ +*/ + + +/** @addtogroup BPWM_EXPORTED_CONSTANTS BPWM Exported Constants + @{ +*/ +#define BPWM_CHANNEL_NUM (6UL) /*!< BPWM channel number */ +#define BPWM_CH_0_MASK (0x1UL) /*!< BPWM channel 0 mask */ +#define BPWM_CH_1_MASK (0x2UL) /*!< BPWM channel 1 mask */ +#define BPWM_CH_2_MASK (0x4UL) /*!< BPWM channel 2 mask */ +#define BPWM_CH_3_MASK (0x8UL) /*!< BPWM channel 3 mask */ +#define BPWM_CH_4_MASK (0x10UL) /*!< BPWM channel 4 mask */ +#define BPWM_CH_5_MASK (0x20UL) /*!< BPWM channel 5 mask */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Counter Type Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define BPWM_UP_COUNTER (0UL) /*!< Up counter type */ +#define BPWM_DOWN_COUNTER (1UL) /*!< Down counter type */ +#define BPWM_UP_DOWN_COUNTER (2UL) /*!< Up-Down counter type */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Aligned Type Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define BPWM_EDGE_ALIGNED (1UL) /*!< BPWM working in edge aligned type(down count) */ +#define BPWM_CENTER_ALIGNED (2UL) /*!< BPWM working in center aligned type */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Output Level Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define BPWM_OUTPUT_NOTHING (0UL) /*!< BPWM output nothing */ +#define BPWM_OUTPUT_LOW (1UL) /*!< BPWM output low */ +#define BPWM_OUTPUT_HIGH (2UL) /*!< BPWM output high */ +#define BPWM_OUTPUT_TOGGLE (3UL) /*!< BPWM output toggle */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Synchronous Start Function Control Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define BPWM_SSCTL_SSRC_PWM0 (0UL<SSCTL = ((bpwm)->SSCTL & ~BPWM_SSCTL_SSRC_Msk) | (u32SyncSrc) | BPWM_SSCTL_SSEN0_Msk) + +/** + * @brief Disable timer synchronous start counting function of specified channel(s) + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used. + * @return None + * @details This macro is used to disable timer synchronous start counting function of specified channel(s). + * @note All channels share channel 0's setting. + * \hideinitializer + */ +#define BPWM_DISABLE_TIMER_SYNC(bpwm, u32ChannelMask) ((bpwm)->SSCTL &= ~BPWM_SSCTL_SSEN0_Msk) + +/** + * @brief This macro enable BPWM counter synchronous start counting function. + * @param[in] bpwm The pointer of the specified BPWM module + * @return None + * @details This macro is used to make selected BPWM0 and BPWM1 channel(s) start counting at the same time. + * To configure synchronous start counting channel(s) by BPWM_ENABLE_TIMER_SYNC() and BPWM_DISABLE_TIMER_SYNC(). + * \hideinitializer + */ +#define BPWM_TRIGGER_SYNC_START(bpwm) ((bpwm)->SSTRG = BPWM_SSTRG_CNTSEN_Msk) + +/** + * @brief This macro enable output inverter of specified channel(s) + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Bit 0 represents channel 0, bit 1 represents channel 1... + * @return None + * \hideinitializer + */ +#define BPWM_ENABLE_OUTPUT_INVERTER(bpwm, u32ChannelMask) ((bpwm)->POLCTL = (u32ChannelMask)) + +/** + * @brief This macro get captured rising data + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @return None + * \hideinitializer + */ +#define BPWM_GET_CAPTURE_RISING_DATA(bpwm, u32ChannelNum) ((bpwm)->CAPDAT[(u32ChannelNum)].RCAPDAT) + +/** + * @brief This macro get captured falling data + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @return None + * \hideinitializer + */ +#define BPWM_GET_CAPTURE_FALLING_DATA(bpwm, u32ChannelNum) ((bpwm)->CAPDAT[(u32ChannelNum)].FCAPDAT) + +/** + * @brief This macro mask output logic to high or low + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Bit 0 represents channel 0, bit 1 represents channel 1... + * @param[in] u32LevelMask Output logic to high or low + * @return None + * @details This macro is used to mask output logic to high or low of specified channel(s). + * @note If u32ChannelMask parameter is 0, then mask function will be disabled. + * \hideinitializer + */ +#define BPWM_MASK_OUTPUT(bpwm, u32ChannelMask, u32LevelMask) \ + { \ + (bpwm)->MSKEN = (u32ChannelMask); \ + (bpwm)->MSK = (u32LevelMask); \ + } + +/** + * @brief This macro set the prescaler of all channels + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @param[in] u32Prescaler Clock prescaler of specified channel. Valid values are between 1 ~ 0xFFF + * @return None + * \hideinitializer + */ +#define BPWM_SET_PRESCALER(bpwm, u32ChannelNum, u32Prescaler) ((bpwm)->CLKPSC = (u32Prescaler)) + +/** +* @brief This macro get the prescaler of the selected channel +* @param[in] bpwm The pointer of the specified BPWM module +* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5. This parameter is not used. +* @return Return Clock prescaler of specified channel. Valid values are between 0 ~ 0xFFF +* @details This macro is used to get the prescaler of specified channel. +* @note All channels share channel 0's setting. +* The clock of BPWM counter is divided by (u32Prescaler + 1). +* \hideinitializer +*/ +#define BPWM_GET_PRESCALER(bpwm, u32ChannelNum) (bpwm)->CLKPSC + +/** + * @brief This macro set the duty of the selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @param[in] u32CMR Duty of specified channel. Valid values are between 0~0xFFFF + * @return None + * @note This new setting will take effect on next BPWM period + * \hideinitializer + */ +#define BPWM_SET_CMR(bpwm, u32ChannelNum, u32CMR) ((bpwm)->CMPDAT[(u32ChannelNum)] = (u32CMR)) + +/** + * @brief This macro get the duty of the selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @return Return the duty of specified channel. Valid values are between 0~0xFFFF + * @details This macro is used to get the duty of specified channel. + * \hideinitializer + */ +#define BPWM_GET_CMR(bpwm, u32ChannelNum) ((bpwm)->CMPDAT[(u32ChannelNum)]) + +/** + * @brief This macro set the period of all channels + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @param[in] u32CNR Period of specified channel. Valid values are between 0~0xFFFF + * @return None + * @note This new setting will take effect on next BPWM period + * @note BPWM counter will stop if period length set to 0 + * \hideinitializer + */ +#define BPWM_SET_CNR(bpwm, u32ChannelNum, u32CNR) ((bpwm)->PERIOD = (u32CNR)) + +/** + * @brief This macro get the period of all channels + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @return Return the period of specified channel. + * @details This macro is used to get the period of specified channel. + * \hideinitializer + */ +#define BPWM_GET_CNR(bpwm, u32ChannelNum) ((bpwm)->PERIOD) + +/** + * @brief This macro set the BPWM aligned type + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used. + * @param[in] u32AlignedType BPWM aligned type, valid values are: + * - \ref BPWM_UP_COUNTER + * - \ref BPWM_DOWN_COUNTER + * - \ref BPWM_UP_DOWN_COUNTER + * @return None + * @note All channels share channel 0's setting. + * \hideinitializer + */ +#define BPWM_SET_ALIGNED_TYPE(bpwm, u32ChannelMask, u32AlignedType) ((bpwm)->CTL1 = (u32AlignedType)) + +/** + * @brief Clear counter of channel 0 + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used. + * @return None + * @details This macro is used to clear counter of channel 0 + * \hideinitializer + */ +#define BPWM_CLR_COUNTER(bpwm, u32ChannelMask) ((bpwm)->CNTCLR = (BPWM_CNTCLR_CNTCLR0_Msk)) + +/** + * @brief Set output level at zero, compare up, period(center) and compare down of specified channel(s) + * @param[in] bpwm The pointer of the specified BPWM module + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Bit 0 represents channel 0, bit 1 represents channel 1... + * @param[in] u32ZeroLevel output level at zero point, valid values are: + * - \ref BPWM_OUTPUT_NOTHING + * - \ref BPWM_OUTPUT_LOW + * - \ref BPWM_OUTPUT_HIGH + * - \ref BPWM_OUTPUT_TOGGLE + * @param[in] u32CmpUpLevel output level at compare up point, valid values are: + * - \ref BPWM_OUTPUT_NOTHING + * - \ref BPWM_OUTPUT_LOW + * - \ref BPWM_OUTPUT_HIGH + * - \ref BPWM_OUTPUT_TOGGLE + * @param[in] u32PeriodLevel output level at period(center) point, valid values are: + * - \ref BPWM_OUTPUT_NOTHING + * - \ref BPWM_OUTPUT_LOW + * - \ref BPWM_OUTPUT_HIGH + * - \ref BPWM_OUTPUT_TOGGLE + * @param[in] u32CmpDownLevel output level at compare down point, valid values are: + * - \ref BPWM_OUTPUT_NOTHING + * - \ref BPWM_OUTPUT_LOW + * - \ref BPWM_OUTPUT_HIGH + * - \ref BPWM_OUTPUT_TOGGLE + * @return None + * @details This macro is used to Set output level at zero, compare up, period(center) and compare down of specified channel(s) + * \hideinitializer + */ +#define BPWM_SET_OUTPUT_LEVEL(bpwm, u32ChannelMask, u32ZeroLevel, u32CmpUpLevel, u32PeriodLevel, u32CmpDownLevel) \ + do{ \ + uint32_t i; \ + for(i = 0UL; i < 6UL; i++) { \ + if((u32ChannelMask) & (1UL << i)) { \ + (bpwm)->WGCTL0 = (((bpwm)->WGCTL0 & ~(3UL << (i << 1UL))) | ((u32ZeroLevel) << (i << 1UL))); \ + (bpwm)->WGCTL0 = (((bpwm)->WGCTL0 & ~(3UL << (BPWM_WGCTL0_PRDPCTL0_Pos + (i << 1UL)))) | ((u32PeriodLevel) << (BPWM_WGCTL0_PRDPCTL0_Pos + (i << 1UL)))); \ + (bpwm)->WGCTL1 = (((bpwm)->WGCTL1 & ~(3UL << (i << 1UL))) | ((u32CmpUpLevel) << (i << 1UL))); \ + (bpwm)->WGCTL1 = (((bpwm)->WGCTL1 & ~(3UL << (BPWM_WGCTL1_CMPDCTL0_Pos + (i << 1UL)))) | ((u32CmpDownLevel) << (BPWM_WGCTL1_CMPDCTL0_Pos + (i << 1UL)))); \ + } \ + } \ + }while(0) + + +/*---------------------------------------------------------------------------------------------------------*/ +/* Define BPWM functions prototype */ +/*---------------------------------------------------------------------------------------------------------*/ +uint32_t BPWM_ConfigCaptureChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32UnitTimeNsec, uint32_t u32CaptureEdge); +uint32_t BPWM_ConfigOutputChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Frequency, uint32_t u32DutyCycle); +void BPWM_Start(BPWM_T *bpwm, uint32_t u32ChannelMask); +void BPWM_Stop(BPWM_T *bpwm, uint32_t u32ChannelMask); +void BPWM_ForceStop(BPWM_T *bpwm, uint32_t u32ChannelMask); +void BPWM_EnableADCTrigger(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Condition); +void BPWM_DisableADCTrigger(BPWM_T *bpwm, uint32_t u32ChannelNum); +void BPWM_ClearADCTriggerFlag(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Condition); +uint32_t BPWM_GetADCTriggerFlag(BPWM_T *bpwm, uint32_t u32ChannelNum); +void BPWM_EnableCapture(BPWM_T *bpwm, uint32_t u32ChannelMask); +void BPWM_DisableCapture(BPWM_T *bpwm, uint32_t u32ChannelMask); +void BPWM_EnableOutput(BPWM_T *bpwm, uint32_t u32ChannelMask); +void BPWM_DisableOutput(BPWM_T *bpwm, uint32_t u32ChannelMask); +void BPWM_EnableCaptureInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge); +void BPWM_DisableCaptureInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge); +void BPWM_ClearCaptureIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge); +uint32_t BPWM_GetCaptureIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum); +void BPWM_EnableDutyInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType); +void BPWM_DisableDutyInt(BPWM_T *bpwm, uint32_t u32ChannelNum); +void BPWM_ClearDutyIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum); +uint32_t BPWM_GetDutyIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum); +void BPWM_EnablePeriodInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType); +void BPWM_DisablePeriodInt(BPWM_T *bpwm, uint32_t u32ChannelNum); +void BPWM_ClearPeriodIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum); +uint32_t BPWM_GetPeriodIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum); +void BPWM_EnableZeroInt(BPWM_T *bpwm, uint32_t u32ChannelNum); +void BPWM_DisableZeroInt(BPWM_T *bpwm, uint32_t u32ChannelNum); +void BPWM_ClearZeroIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum); +uint32_t BPWM_GetZeroIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum); +void BPWM_EnableLoadMode(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32LoadMode); +void BPWM_DisableLoadMode(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32LoadMode); +void BPWM_SetClockSource(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32ClkSrcSel); +uint32_t BPWM_GetWrapAroundFlag(BPWM_T *bpwm, uint32_t u32ChannelNum); +void BPWM_ClearWrapAroundFlag(BPWM_T *bpwm, uint32_t u32ChannelNum); + + +/*@}*/ /* end of group BPWM_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group BPWM_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_BPWM_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_clk.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_clk.h new file mode 100644 index 0000000000..a5fd1dce66 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_clk.h @@ -0,0 +1,600 @@ +/**************************************************************************//** + * @file nu_clk.h + * @version V0.10 + * $Revision: 12 $ + * $Date: 18/07/05 4:42p $ + * @brief M031 Series Clock Controller (CLK) Driver Header File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_CLK_H__ +#define __NU_CLK_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup CLK_Driver CLK Driver + @{ +*/ + +/** @addtogroup CLK_EXPORTED_CONSTANTS CLK Exported Constants + @{ +*/ + + +#define FREQ_4MHZ 4000000 /*!< Define frequency macro 4MHz \hideinitializer */ +#define FREQ_8MHZ 8000000 /*!< Define frequency macro 8MHz \hideinitializer */ +#define FREQ_12MHZ 12000000 /*!< Define frequency macro 12MHz \hideinitializer */ +#define FREQ_16MHZ 16000000 /*!< Define frequency macro 16MHz \hideinitializer */ +#define FREQ_24MHZ 24000000 /*!< Define frequency macro 24MHz \hideinitializer */ +#define FREQ_25MHZ 25000000 /*!< Define frequency macro 25MHz \hideinitializer */ +#define FREQ_32MHZ 32000000 /*!< Define frequency macro 32MHz \hideinitializer */ +#define FREQ_48MHZ 48000000 /*!< Define frequency macro 48MHz \hideinitializer */ +#define FREQ_50MHZ 50000000 /*!< Define frequency macro 50MHz \hideinitializer */ +#define FREQ_51MHZ 51000000 /*!< Define frequency macro 51MHz \hideinitializer */ +#define FREQ_64MHZ 64000000 /*!< Define frequency macro 64MHz \hideinitializer */ +#define FREQ_68MHZ 68000000 /*!< Define frequency macro 68MHz \hideinitializer */ +#define FREQ_72MHZ 72000000 /*!< Define frequency macro 72MHz \hideinitializer */ +#define FREQ_96MHZ 96000000 /*!< Define frequency macro 96MHz \hideinitializer */ +#define FREQ_100MHZ 100000000 /*!< Define frequency macro 100MHz \hideinitializer */ +#define FREQ_144MHZ 144000000 /*!< Define frequency macro 144MHz \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* PWRCTL constant definitions. (Write-protection) */ +/*---------------------------------------------------------------------------------------------------------*/ +#define CLK_PWRCTL_HXTGAIN_L0 (0) /*!< Setting HXT Gain Control to level 0 for lower than 4MHz external crystal \hideinitializer */ +#define CLK_PWRCTL_HXTGAIN_L1 (1) /*!< Setting HXT Gain Control to level 1 for 4MHz ~ 8MHz external crystal \hideinitializer */ +#define CLK_PWRCTL_HXTGAIN_L2 (2) /*!< Setting HXT Gain Control to level 2 for 8MHz ~ 12MHz external crystal \hideinitializer */ +#define CLK_PWRCTL_HXTGAIN_L3 (3) /*!< Setting HXT Gain Control to level 3 for 12MHz ~ 16MHz external crystal \hideinitializer */ +#define CLK_PWRCTL_HXTGAIN_L4 (4) /*!< Setting HXT Gain Control to level 4 for 16MHz ~ 24MHz external crystal \hideinitializer */ +#define CLK_PWRCTL_HXTGAIN_L5 (5) /*!< Setting HXT Gain Control to level 5 \hideinitializer */ +#define CLK_PWRCTL_HXTGAIN_L6 (6) /*!< Setting HXT Gain Control to level 6 \hideinitializer */ +#define CLK_PWRCTL_HXTGAIN_L7 (7) /*!< Setting HXT Gain Control to level 7 for 24MHz ~ 32MHz external crystal \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* CLKSEL0 constant definitions. (Write-protection) */ +/*---------------------------------------------------------------------------------------------------------*/ +#define CLK_CLKSEL0_HCLKSEL_HXT (0x00UL<= 2 \hideinitializer */ +#define CLK_PLLCTL_NF(x) ((x-2)<>30) & 0x3UL) /*!< Calculate AHBCLK/APBCLK offset on MODULE index, 0x0:AHBCLK, 0x1:APBCLK0, 0x2:APBCLK1 \hideinitializer */ +#define MODULE_CLKSEL(x) (((x) >>28) & 0x3UL) /*!< Calculate CLKSEL offset on MODULE index, 0x0:CLKSEL0, 0x1:CLKSEL1, 0x2:CLKSEL2, 0x3:CLKSEL3 \hideinitializer */ +#define MODULE_CLKSEL_Msk(x) (((x) >>25) & 0x7UL) /*!< Calculate CLKSEL mask offset on MODULE index \hideinitializer */ +#define MODULE_CLKSEL_Pos(x) (((x) >>20) & 0x1fUL) /*!< Calculate CLKSEL position offset on MODULE index \hideinitializer */ +#define MODULE_CLKDIV(x) (((x) >>18) & 0x3UL) /*!< Calculate CLKDIV offset on MODULE index, 0x0:CLKDIV0, 0x1:CLKDIV1, 0x2:CLKDIV3, 0x3:CLKDIV4 \hideinitializer */ +#define MODULE_CLKDIV_Msk(x) (((x) >>10) & 0xffUL) /*!< Calculate CLKDIV mask offset on MODULE index \hideinitializer */ +#define MODULE_CLKDIV_Pos(x) (((x) >>5 ) & 0x1fUL) /*!< Calculate CLKDIV position offset on MODULE index \hideinitializer */ +#define MODULE_IP_EN_Pos(x) (((x) >>0 ) & 0x1fUL) /*!< Calculate APBCLK offset on MODULE index \hideinitializer */ +#define MODULE_NoMsk 0x0 /*!< Not mask on MODULE index \hideinitializer */ +#define NA MODULE_NoMsk /*!< Not Available \hideinitializer */ + +#define MODULE_APBCLK_ENC(x) (((x) & 0x03UL) << 30) /*!< MODULE index, 0x0:AHBCLK, 0x1:APBCLK0, 0x2:APBCLK1 \hideinitializer */ +#define MODULE_CLKSEL_ENC(x) (((x) & 0x03UL) << 28) /*!< CLKSEL offset on MODULE index, 0x0:CLKSEL0, 0x1:CLKSEL1, 0x2:CLKSEL2, 0x3:CLKSEL3 \hideinitializer */ +#define MODULE_CLKSEL_Msk_ENC(x) (((x) & 0x07UL) << 25) /*!< CLKSEL mask offset on MODULE index \hideinitializer */ +#define MODULE_CLKSEL_Pos_ENC(x) (((x) & 0x1fUL) << 20) /*!< CLKSEL position offset on MODULE index \hideinitializer */ +#define MODULE_CLKDIV_ENC(x) (((x) & 0x03UL) << 18) /*!< APBCLK CLKDIV on MODULE index, 0x0:CLKDIV, 0x1:CLKDIV1, 0x2:CLKDIV3, 0x3:CLKDIV4 \hideinitializer */ +#define MODULE_CLKDIV_Msk_ENC(x) (((x) & 0xffUL) << 10) /*!< CLKDIV mask offset on MODULE index \hideinitializer */ +#define MODULE_CLKDIV_Pos_ENC(x) (((x) & 0x1fUL) << 5) /*!< CLKDIV position offset on MODULE index \hideinitializer */ +#define MODULE_IP_EN_Pos_ENC(x) (((x) & 0x1fUL) << 0) /*!< AHBCLK/APBCLK offset on MODULE index \hideinitializer */ + + +//AHBCLK +#define PDMA_MODULE (MODULE_APBCLK_ENC( 0)|MODULE_IP_EN_Pos_ENC(CLK_AHBCLK_PDMACKEN_Pos)|\ + MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< PDMA Module \hideinitializer */ + +#define ISP_MODULE (MODULE_APBCLK_ENC( 0)|MODULE_IP_EN_Pos_ENC(CLK_AHBCLK_ISPCKEN_Pos)|\ + MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< ISP Module \hideinitializer */ + +#define EBI_MODULE (MODULE_APBCLK_ENC( 0)|MODULE_IP_EN_Pos_ENC(CLK_AHBCLK_EBICKEN_Pos)|\ + MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< EBI Module \hideinitializer */ + +#define HDIV_MODULE (MODULE_APBCLK_ENC( 0)|MODULE_IP_EN_Pos_ENC(CLK_AHBCLK_HDIVCKEN_Pos)|\ + MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< HDIV Module \hideinitializer */ + +#define CRC_MODULE (MODULE_APBCLK_ENC( 0)|MODULE_IP_EN_Pos_ENC(CLK_AHBCLK_CRCCKEN_Pos)|\ + MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< CRC Module \hideinitializer */ + +//APBCLK0 +#define WDT_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_WDTCKEN_Pos)|\ + MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL1_WDTSEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< WDT Module \hideinitializer */ + +#define WWDT_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_WDTCKEN_Pos)|\ + MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL1_WWDTSEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< WWDT Module \hideinitializer */ + +#define RTC_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_RTCCKEN_Pos)|\ + MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< RTC Module \hideinitializer */ + +#define TMR0_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_TMR0CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL1_TMR0SEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< TMR0 Module \hideinitializer */ + +#define TMR1_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_TMR1CKEN_Pos) |\ + MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL1_TMR1SEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< TMR1 Module \hideinitializer */ + +#define TMR2_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_TMR2CKEN_Pos) |\ + MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL1_TMR2SEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< TMR2 Module \hideinitializer */ + +#define TMR3_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_TMR3CKEN_Pos) |\ + MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL1_TMR3SEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< TMR3 Module \hideinitializer */ + +#define CLKO_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_CLKOCKEN_Pos) |\ + MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL1_CLKOSEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< CLKO Module \hideinitializer */ + +#define UART0_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_UART0CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL1_UART0SEL_Pos)|\ + MODULE_CLKDIV_ENC( 0)|MODULE_CLKDIV_Msk_ENC(0xF)|MODULE_CLKDIV_Pos_ENC(CLK_CLKDIV0_UART0DIV_Pos)) /*!< UART0 Module \hideinitializer */ + +#define UART1_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_UART1CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL1_UART1SEL_Pos)|\ + MODULE_CLKDIV_ENC( 0)|MODULE_CLKDIV_Msk_ENC(0xF)|MODULE_CLKDIV_Pos_ENC(CLK_CLKDIV0_UART1DIV_Pos)) /*!< UART1 Module \hideinitializer */ + +#define UART2_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_UART2CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 3)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL3_UART2SEL_Pos)|\ + MODULE_CLKDIV_ENC( 3)|MODULE_CLKDIV_Msk_ENC(0xF)|MODULE_CLKDIV_Pos_ENC(CLK_CLKDIV4_UART2DIV_Pos)) /*!< UART2 Module \hideinitializer */ + +#define UART3_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_UART3CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 3)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL3_UART3SEL_Pos)|\ + MODULE_CLKDIV_ENC( 3)|MODULE_CLKDIV_Msk_ENC(0xF)|MODULE_CLKDIV_Pos_ENC(CLK_CLKDIV4_UART3DIV_Pos)) /*!< UART3 Module \hideinitializer */ + +#define UART4_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_UART4CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 3)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL3_UART4SEL_Pos)|\ + MODULE_CLKDIV_ENC( 3)|MODULE_CLKDIV_Msk_ENC(0xF)|MODULE_CLKDIV_Pos_ENC(CLK_CLKDIV4_UART4DIV_Pos)) /*!< UART4 Module \hideinitializer */ + +#define UART5_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_UART5CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 3)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL3_UART5SEL_Pos)|\ + MODULE_CLKDIV_ENC( 3)|MODULE_CLKDIV_Msk_ENC(0xF)|MODULE_CLKDIV_Pos_ENC(CLK_CLKDIV4_UART5DIV_Pos)) /*!< UART5 Module \hideinitializer */ + +#define UART6_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_UART6CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 3)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL3_UART6SEL_Pos)|\ + MODULE_CLKDIV_ENC( 3)|MODULE_CLKDIV_Msk_ENC(0xF)|MODULE_CLKDIV_Pos_ENC(CLK_CLKDIV4_UART6DIV_Pos)) /*!< UART6 Module \hideinitializer */ + +#define UART7_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_UART7CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 3)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL3_UART7SEL_Pos)|\ + MODULE_CLKDIV_ENC( 3)|MODULE_CLKDIV_Msk_ENC(0xF)|MODULE_CLKDIV_Pos_ENC(CLK_CLKDIV4_UART7DIV_Pos)) /*!< UART7 Module \hideinitializer */ + +#define I2C0_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_I2C0CKEN_Pos) |\ + MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< I2C0 Module \hideinitializer */ + +#define I2C1_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_I2C1CKEN_Pos) |\ + MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< I2C1 Module \hideinitializer */ + +#define QSPI0_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_QSPI0CKEN_Pos) |\ + MODULE_CLKSEL_ENC( 2)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL2_QSPI0SEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< QSPI0 Module \hideinitializer */ + +#define SPI0_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_SPI0CKEN_Pos) |\ + MODULE_CLKSEL_ENC( 2)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL2_SPI0SEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< SPI0 Module \hideinitializer */ + +#define ADC_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_ADCCKEN_Pos)|\ + MODULE_CLKSEL_ENC( 2)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL2_ADCSEL_Pos)|\ + MODULE_CLKDIV_ENC( 0)|MODULE_CLKDIV_Msk_ENC(0xFF)|MODULE_CLKDIV_Pos_ENC(CLK_CLKDIV0_ADCDIV_Pos)) /*!< ADC Module \hideinitializer */ + +#define ACMP01_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_ACMP01CKEN_Pos)|\ + MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< ACMP Module \hideinitializer */ + +#define USBD_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK0_USBDCKEN_Pos)|\ + MODULE_CLKSEL_ENC( 0)|MODULE_CLKSEL_Msk_ENC( 1)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL0_USBDSEL_Pos)|\ + MODULE_CLKDIV_ENC( 0)|MODULE_CLKDIV_Msk_ENC(0xF)|MODULE_CLKDIV_Pos_ENC(CLK_CLKDIV0_USBDIV_Pos)) /*!< USBD Module \hideinitializer */ + +//APBCLK1 +#define PWM0_MODULE (MODULE_APBCLK_ENC( 2)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK1_PWM0CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 2)|MODULE_CLKSEL_Msk_ENC( 1)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL2_PWM0SEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< PWM0 Module \hideinitializer */ + +#define PWM1_MODULE (MODULE_APBCLK_ENC( 2)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK1_PWM1CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 2)|MODULE_CLKSEL_Msk_ENC( 1)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL2_PWM1SEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< PWM1 Module \hideinitializer */ + +#define BPWM0_MODULE (MODULE_APBCLK_ENC( 2)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK1_BPWM0CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 2)|MODULE_CLKSEL_Msk_ENC( 1)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL2_BPWM0SEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< BPWM0 Module \hideinitializer */ + +#define BPWM1_MODULE (MODULE_APBCLK_ENC( 2)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK1_BPWM1CKEN_Pos)|\ + MODULE_CLKSEL_ENC( 2)|MODULE_CLKSEL_Msk_ENC( 1)|MODULE_CLKSEL_Pos_ENC(CLK_CLKSEL2_BPWM1SEL_Pos)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< BPWM1 Module \hideinitializer */ + +#define USCI0_MODULE (MODULE_APBCLK_ENC( 2)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK1_USCI0CKEN_Pos)|\ + MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< USCI0 Module \hideinitializer */ + +#define USCI1_MODULE (MODULE_APBCLK_ENC( 2)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK1_USCI1CKEN_Pos)|\ + MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\ + MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< USCI1 Module \hideinitializer */ + +/*@}*/ /* end of group CLK_EXPORTED_CONSTANTS */ + +/** @addtogroup CLK_EXPORTED_FUNCTIONS CLK Exported Functions + @{ +*/ + +/*---------------------------------------------------------------------------------------------------------*/ +/* static inline functions */ +/*---------------------------------------------------------------------------------------------------------*/ + +/** + * @brief Get PLL Clock Output Frequency + * @param None + * @return PLL clock output frequency + * @details To get actual PLL clock output frequency. The clock uint is in Hz. + * \hideinitializer + */ +static __INLINE uint32_t CLK_GetPLLClockFreq(void) +{ + uint32_t u32PllFreq; + uint32_t u32FIN, u32NF, u32NR, u32NO; + uint8_t au8NoTbl[4] = {1, 2, 2, 4}; /* OUTDIV :DEF: {1, 2, 2, 4} */ + uint32_t u32Reg; + + u32PllFreq = 0; + u32Reg = CLK->PLLCTL; + + if ((u32Reg & (CLK_PLLCTL_PD_Msk | CLK_PLLCTL_OE_Msk)) == 0) + { + /* PLL is enabled and output enabled */ + if (u32Reg & CLK_PLLCTL_PLLSRC_Msk) + { + u32FIN = (__HIRC >> 2); + } else + u32FIN = __HXT; + + if (u32Reg & CLK_PLLCTL_BP_Msk) + { + /* PLL is in bypass mode */ + u32PllFreq = u32FIN; + } + else + { + /* PLL is in normal work mode */ + u32NO = au8NoTbl[((u32Reg & CLK_PLLCTL_OUTDIV_Msk) >> CLK_PLLCTL_OUTDIV_Pos)]; + u32NF = ((u32Reg & CLK_PLLCTL_FBDIV_Msk) >> CLK_PLLCTL_FBDIV_Pos) + 2; + u32NR = ((u32Reg & CLK_PLLCTL_INDIV_Msk) >> CLK_PLLCTL_INDIV_Pos) + 2; + /* u32FIN is shifted 2 bits to avoid overflow */ + u32PllFreq = (((u32FIN >> 2) * u32NF) / (u32NR * u32NO) << 2); + } + } + + return u32PllFreq; +} + +/** + * @brief This function execute delay function. + * @param[in] us Delay time. The Max value is 2^24 / CPU Clock(MHz). Ex: + * 50MHz => 335544us, 48MHz => 349525us, 28MHz => 699050us ... + * @return None + * @details Use the SysTick to generate the delay time and the UNIT is in us. + * The SysTick clock source is from HCLK, i.e. the same as system core clock. + * User can use SystemCoreClockUpdate() to calculate CyclesPerUs automatically before using this function. + * \hideinitializer + */ +__STATIC_INLINE void CLK_SysTickDelay(uint32_t us) +{ + SysTick->LOAD = us * CyclesPerUs; + SysTick->VAL = (0x00); + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; + + /* Waiting for down-count to zero */ + while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0); + + /* Disable SysTick counter */ + SysTick->CTRL = 0; +} + + +/** + * @brief Get current UART0 clock frquency. + * @param None. + * @return UART0 clock frquency. The clock UNIT is in Hz. + * \hideinitializer + */ +static __INLINE uint32_t CLK_GetUARTFreq(void) +{ + uint32_t u32Freqout, u32AHBDivider, u32ClkSel, PCLK0Div; + + u32Freqout = 0; + u32ClkSel = CLK->CLKSEL1 & CLK_CLKSEL1_UART0SEL_Msk ; + + if (u32ClkSel == CLK_CLKSEL1_UART0SEL_HXT) /* external HXT crystal clock */ + { + u32Freqout = __HXT; + } + else if(u32ClkSel == CLK_CLKSEL1_UART0SEL_PLL) /* PLL clock */ + { + u32Freqout = CLK_GetPLLClockFreq(); + } + else if(u32ClkSel == CLK_CLKSEL1_UART0SEL_LXT) /* LXT clock */ + { + u32Freqout = __LXT; + } + else if(u32ClkSel == CLK_CLKSEL1_UART0SEL_HIRC) /* HIRC clock */ + { + u32Freqout = __HIRC; + } + else if(u32ClkSel == CLK_CLKSEL1_UART0SEL_PCLK0) /* PCLK0 clock */ + { + PCLK0Div = (CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) >> CLK_PCLKDIV_APB0DIV_Pos; + u32Freqout = (SystemCoreClock >> PCLK0Div); + } + else if(u32ClkSel == CLK_CLKSEL1_UART0SEL_LIRC) /* LIRC clock */ + { + u32Freqout = __LIRC; + } + + u32AHBDivider = (CLK->CLKDIV0 & CLK_CLKDIV0_UART0DIV_Msk) + 1 ; + + return (u32Freqout/u32AHBDivider); +} + + +uint32_t CLK_WaitClockReady(uint32_t); +void CLK_DisableCKO(void); +void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En); +uint32_t CLK_GetHCLKFreq(void); +uint32_t CLK_GetCPUFreq(void); +uint32_t CLK_GetLXTFreq(void); +uint32_t CLK_GetHXTFreq(void); +void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv); +uint32_t CLK_SetCoreClock(uint32_t u32Hclk); +uint32_t CLK_GetPCLK0Freq(void); +uint32_t CLK_GetPCLK1Freq(void); +void CLK_EnableXtalRC(uint32_t u32ClkMask); +void CLK_DisableXtalRC(uint32_t u32ClkMask); +void CLK_DisableModuleClock(uint32_t u32ModuleIdx); +void CLK_EnableModuleClock(uint32_t u32ModuleIdx); +void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv); +void CLK_DisablePLL(void); +uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq); +void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc); +void CLK_DisableSysTick(void); +void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count); +void CLK_PowerDown(void); +void CLK_Idle(void); + +/*@}*/ /* end of group CLK_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group CLK_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_CLK_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_crc.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_crc.h new file mode 100644 index 0000000000..5090bdf1d4 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_crc.h @@ -0,0 +1,117 @@ +/****************************************************************************** + * @file nu_crc.h + * @version V1.00 + * $Revision: 9 $ + * $Date: 18/07/09 4:18p $ + * @brief M031 series CRC driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +****************************************************************************/ + +#ifndef __NU_CRC_H__ +#define __NU_CRC_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup CRC_Driver CRC Driver + @{ +*/ + +/** @addtogroup CRC_EXPORTED_CONSTANTS CRC Exported Constants + @{ +*/ +/*---------------------------------------------------------------------------------------------------------*/ +/* CRC Polynomial Mode Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define CRC_CCITT (0UL << CRC_CTL_CRCMODE_Pos) /*!SEED = (u32Seed); CRC->CTL |= CRC_CTL_CHKSINIT_Msk; }while(0) + +/** + * @brief Get CRC Seed Value + * + * @param None + * + * @return CRC seed value + * + * @details This macro gets the current CRC seed value. + * \hideinitializer + */ +#define CRC_GET_SEED() (CRC->SEED) + +/** + * @brief CRC Write Data + * + * @param[in] u32Data Write data + * + * @return None + * + * @details User can write data directly to CRC Write Data Register(CRC_DAT) by this macro to perform CRC operation. + * \hideinitializer + */ +#define CRC_WRITE_DATA(u32Data) (CRC->DAT = (u32Data)) + +void CRC_Open(uint32_t u32Mode, uint32_t u32Attribute, uint32_t u32Seed, uint32_t u32DataLen); +uint32_t CRC_GetChecksum(void); + +/*@}*/ /* end of group CRC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group CRC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_ebi.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_ebi.h new file mode 100644 index 0000000000..ae66aa18b6 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_ebi.h @@ -0,0 +1,260 @@ +/**************************************************************************//** + * @file nu_ebi.h + * @version V1.00 + * $Revision: 3 $ + * $Date: 18/06/07 2:32p $ + * @brief M031 series External Bus Interface(EBI) driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_EBI_H__ +#define __NU_EBI_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup EBI_Driver EBI Driver + @{ +*/ + +/** @addtogroup EBI_EXPORTED_CONSTANTS EBI Exported Constants + @{ +*/ +/*---------------------------------------------------------------------------------------------------------*/ +/* Miscellaneous Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define EBI_BANK0_BASE_ADDR 0x60000000UL /*!< EBI bank0 base address \hideinitializer */ +#define EBI_BANK1_BASE_ADDR 0x60100000UL /*!< EBI bank1 base address \hideinitializer */ +#define EBI_MAX_SIZE 0x00100000UL /*!< Maximum EBI size for each bank is 1 MB \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Constants for EBI bank number */ +/*---------------------------------------------------------------------------------------------------------*/ +#define EBI_BANK0 0UL /*!< EBI bank 0 \hideinitializer */ +#define EBI_BANK1 1UL /*!< EBI bank 1 \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Constants for EBI data bus width */ +/*---------------------------------------------------------------------------------------------------------*/ +#define EBI_BUSWIDTH_8BIT 8UL /*!< EBI bus width is 8-bit \hideinitializer */ +#define EBI_BUSWIDTH_16BIT 16UL /*!< EBI bus width is 16-bit \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Constants for EBI CS Active Level */ +/*---------------------------------------------------------------------------------------------------------*/ +#define EBI_CS_ACTIVE_LOW 0UL /*!< EBI CS active level is low \hideinitializer */ +#define EBI_CS_ACTIVE_HIGH 1UL /*!< EBI CS active level is high \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Constants for EBI MCLK divider and Timing */ +/*---------------------------------------------------------------------------------------------------------*/ +#define EBI_MCLKDIV_1 0x0UL /*!< EBI output clock(MCLK) is HCLK/1 \hideinitializer */ +#define EBI_MCLKDIV_2 0x1UL /*!< EBI output clock(MCLK) is HCLK/2 \hideinitializer */ +#define EBI_MCLKDIV_4 0x2UL /*!< EBI output clock(MCLK) is HCLK/4 \hideinitializer */ +#define EBI_MCLKDIV_8 0x3UL /*!< EBI output clock(MCLK) is HCLK/8 \hideinitializer */ +#define EBI_MCLKDIV_16 0x4UL /*!< EBI output clock(MCLK) is HCLK/16 \hideinitializer */ +#define EBI_MCLKDIV_32 0x5UL /*!< EBI output clock(MCLK) is HCLK/32 \hideinitializer */ + +#define EBI_TIMING_FASTEST 0x0UL /*!< EBI timing is the fastest \hideinitializer */ +#define EBI_TIMING_VERYFAST 0x1UL /*!< EBI timing is very fast \hideinitializer */ +#define EBI_TIMING_FAST 0x2UL /*!< EBI timing is fast \hideinitializer */ +#define EBI_TIMING_NORMAL 0x3UL /*!< EBI timing is normal \hideinitializer */ +#define EBI_TIMING_SLOW 0x4UL /*!< EBI timing is slow \hideinitializer */ +#define EBI_TIMING_VERYSLOW 0x5UL /*!< EBI timing is very slow \hideinitializer */ +#define EBI_TIMING_SLOWEST 0x6UL /*!< EBI timing is the slowest \hideinitializer */ + +#define EBI_OPMODE_NORMAL 0x0UL /*!< EBI bus operate in normal mode \hideinitializer */ +#define EBI_OPMODE_CACCESS (EBI_CTL_CACCESS_Msk) /*!< EBI bus operate in Continuous Data Access mode \hideinitializer */ + +/*@}*/ /* end of group EBI_EXPORTED_CONSTANTS */ + + +/** @addtogroup EBI_EXPORTED_FUNCTIONS EBI Exported Functions + @{ +*/ + +/** + * @brief Read 8-bit data on EBI bank0 + * + * @param[in] u32Addr The data address on EBI bank0. + * + * @return 8-bit Data + * + * @details This macro is used to read 8-bit data from specify address on EBI bank0. + */ +#define EBI0_READ_DATA8(u32Addr) (*((volatile unsigned char *)(EBI_BANK0_BASE_ADDR+(u32Addr)))) + +/** + * @brief Write 8-bit data to EBI bank0 + * + * @param[in] u32Addr The data address on EBI bank0. + * @param[in] u32Data Specify data to be written. + * + * @return None + * + * @details This macro is used to write 8-bit data to specify address on EBI bank0. + */ +#define EBI0_WRITE_DATA8(u32Addr, u32Data) (*((volatile unsigned char *)(EBI_BANK0_BASE_ADDR+(u32Addr))) = (u32Data)) + +/** + * @brief Read 16-bit data on EBI bank0 + * + * @param[in] u32Addr The data address on EBI bank0. + * + * @return 16-bit Data + * + * @details This macro is used to read 16-bit data from specify address on EBI bank0. + */ +#define EBI0_READ_DATA16(u32Addr) (*((volatile unsigned short *)(EBI_BANK0_BASE_ADDR+(u32Addr)))) + +/** + * @brief Write 16-bit data to EBI bank0 + * + * @param[in] u32Addr The data address on EBI bank0. + * @param[in] u32Data Specify data to be written. + * + * @return None + * + * @details This macro is used to write 16-bit data to specify address on EBI bank0. + */ +#define EBI0_WRITE_DATA16(u32Addr, u32Data) (*((volatile unsigned short *)(EBI_BANK0_BASE_ADDR+(u32Addr))) = (u32Data)) + +/** + * @brief Read 32-bit data on EBI bank0 + * + * @param[in] u32Addr The data address on EBI bank0. + * + * @return 32-bit Data + * + * @details This macro is used to read 32-bit data from specify address on EBI bank0. + */ +#define EBI0_READ_DATA32(u32Addr) (*((volatile unsigned int *)(EBI_BANK0_BASE_ADDR+(u32Addr)))) + +/** + * @brief Write 32-bit data to EBI bank0 + * + * @param[in] u32Addr The data address on EBI bank0. + * @param[in] u32Data Specify data to be written. + * + * @return None + * + * @details This macro is used to write 32-bit data to specify address on EBI bank0. + */ +#define EBI0_WRITE_DATA32(u32Addr, u32Data) (*((volatile unsigned int *)(EBI_BANK0_BASE_ADDR+(u32Addr))) = (u32Data)) + +/** + * @brief Read 8-bit data on EBI bank1 + * + * @param[in] u32Addr The data address on EBI bank1. + * + * @return 8-bit Data + * + * @details This macro is used to read 8-bit data from specify address on EBI bank1. + */ +#define EBI1_READ_DATA8(u32Addr) (*((volatile unsigned char *)(EBI_BANK1_BASE_ADDR+(u32Addr)))) + +/** + * @brief Write 8-bit data to EBI bank1 + * + * @param[in] u32Addr The data address on EBI bank1. + * @param[in] u32Data Specify data to be written. + * + * @return None + * + * @details This macro is used to write 8-bit data to specify address on EBI bank1. + */ +#define EBI1_WRITE_DATA8(u32Addr, u32Data) (*((volatile unsigned char *)(EBI_BANK1_BASE_ADDR+(u32Addr))) = (u32Data)) + +/** + * @brief Read 16-bit data on EBI bank1 + * + * @param[in] u32Addr The data address on EBI bank1. + * + * @return 16-bit Data + * + * @details This macro is used to read 16-bit data from specify address on EBI bank1. + */ +#define EBI1_READ_DATA16(u32Addr) (*((volatile unsigned short *)(EBI_BANK1_BASE_ADDR+(u32Addr)))) + +/** + * @brief Write 16-bit data to EBI bank1 + * + * @param[in] u32Addr The data address on EBI bank1. + * @param[in] u32Data Specify data to be written. + * + * @return None + * + * @details This macro is used to write 16-bit data to specify address on EBI bank1. + */ +#define EBI1_WRITE_DATA16(u32Addr, u32Data) (*((volatile unsigned short *)(EBI_BANK1_BASE_ADDR+(u32Addr))) = (u32Data)) + +/** + * @brief Read 32-bit data on EBI bank1 + * + * @param[in] u32Addr The data address on EBI bank1. + * + * @return 32-bit Data + * + * @details This macro is used to read 32-bit data from specify address on EBI bank1. + */ +#define EBI1_READ_DATA32(u32Addr) (*((volatile unsigned int *)(EBI_BANK1_BASE_ADDR+(u32Addr)))) + +/** + * @brief Write 32-bit data to EBI bank1 + * + * @param[in] u32Addr The data address on EBI bank1. + * @param[in] u32Data Specify data to be written. + * + * @return None + * + * @details This macro is used to write 32-bit data to specify address on EBI bank1. + */ +#define EBI1_WRITE_DATA32(u32Addr, u32Data) (*((volatile unsigned int *)(EBI_BANK1_BASE_ADDR+(u32Addr))) = (u32Data)) + +/** + * @brief Enable EBI Write Buffer + * + * @param None + * + * @return None + * + * @details This macro is used to improve EBI write operation for EBI bank0 and bank1. + */ +#define EBI_ENABLE_WRITE_BUFFER() (EBI->CTL0 |= EBI_CTL_WBUFEN_Msk); + +/** + * @brief Disable EBI Write Buffer + * + * @param None + * + * @return None + * + * @details This macro is used to disable EBI write buffer function. + */ +#define EBI_DISABLE_WRITE_BUFFER() (EBI->CTL0 &= ~EBI_CTL_WBUFEN_Msk); + +void EBI_Open(uint32_t u32Bank, uint32_t u32DataWidth, uint32_t u32TimingClass, uint32_t u32BusMode, uint32_t u32CSActiveLevel); +void EBI_Close(uint32_t u32Bank); +void EBI_SetBusTiming(uint32_t u32Bank, uint32_t u32TimingConfig, uint32_t u32MclkDiv); + +/*@}*/ /* end of group EBI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group EBI_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_EBI_H__ + +/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_fmc.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_fmc.h new file mode 100644 index 0000000000..b6cf1b4b77 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_fmc.h @@ -0,0 +1,269 @@ +/**************************************************************************//** + * @file nu_fmc.h + * @version V1.00 + * $Revision: 11 $ + * $Date: 18/06/20 3:38p $ + * @brief M031 Series Flash Memory Controller Driver Header File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + ******************************************************************************/ +#ifndef __NU_FMC_H__ +#define __NU_FMC_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup FMC_Driver FMC Driver + @{ +*/ + + +/** @addtogroup FMC_EXPORTED_CONSTANTS FMC Exported Constants + @{ +*/ + +//#define PAGE_SIZE_2048 /*!< Please enable the compiler option for 2K page size */ + +/*----------------------------------------------------------------------------------------------------------*/ +/* Define Base Address */ +/*----------------------------------------------------------------------------------------------------------*/ +#define FMC_APROM_BASE 0x00000000UL /*!< APROM base address \hideinitializer */ +#define FMC_LDROM_BASE 0x00100000UL /*!< LDROM Base Address \hideinitializer */ +#define FMC_SPROM_BASE 0x00200000UL /*!< SPROM Base Address \hideinitializer */ +#define FMC_CONFIG_BASE 0x00300000UL /*!< CONFIG Base Address \hideinitializer */ +#define FMC_USER_CONFIG_0 0x00300000UL /*!< User Config 0 address \hideinitializer */ +#define FMC_USER_CONFIG_1 0x00300004UL /*!< User Config 1 address \hideinitializer */ +#define FMC_USER_CONFIG_2 0x00300008UL /*!< User Config 2 address \hideinitializer */ + +#ifndef PAGE_SIZE_2048 +#define FMC_FLASH_PAGE_SIZE (0x200) /*!< Flash Page Size (512 bytes) \hideinitializer */ +#define FMC_PAGE_ADDR_MASK (0xFFFFFE00UL) /*!< Flash page address mask \hideinitializer */ + +#define FMC_SPROM_SIZE (0x200) /*!< SPROM Size (512 bytes) \hideinitializer */ +#else +#define FMC_FLASH_PAGE_SIZE (0x800) /*!< Flash Page Size (2048 bytes) \hideinitializer */ +#define FMC_PAGE_ADDR_MASK (0xFFFFF800UL) /*!< Flash page address mask \hideinitializer */ + +#define FMC_SPROM_SIZE (0x800) /*!< SPROM Size (2048 bytes) \hideinitializer */ +#endif + +#define FMC_MULTI_WORD_PROG_LEN (256UL) /*!< The length of a multi-word program. \hideinitializer */ + +/*----------------------------------------------------------------------------------------------------------*/ +/* ISPCMD constant definitions */ +/*----------------------------------------------------------------------------------------------------------*/ +#define FMC_ISPCMD_READ 0x00UL /*!< ISP Command: Read flash word \hideinitializer */ +#define FMC_ISPCMD_READ_UID 0x04UL /*!< ISP Command: Read Unique ID \hideinitializer */ +#define FMC_ISPCMD_READ_ALL1 0x08UL /*!< ISP Command: Read all-one result \hideinitializer */ // I version +#define FMC_ISPCMD_READ_CID 0x0BUL /*!< ISP Command: Read Company ID \hideinitializer */ +#define FMC_ISPCMD_READ_DID 0x0CUL /*!< ISP Command: Read Device ID \hideinitializer */ +#define FMC_ISPCMD_READ_CKS 0x0DUL /*!< ISP Command: Read checksum \hideinitializer */ +#define FMC_ISPCMD_PROGRAM 0x21UL /*!< ISP Command: Write flash word \hideinitializer */ +#define FMC_ISPCMD_PROGRAM_64 0x61UL /*!< ISP Command: 64-bit program Flash \hideinitializer */ +#define FMC_ISPCMD_PAGE_ERASE 0x22UL /*!< ISP Command: Page Erase Flash \hideinitializer */ +#define FMC_ISPCMD_BANK_ERASE 0x23UL /*!< ISP Command: Bank Erase Flash \hideinitializer */ +#define FMC_ISPCMD_MULTI_PROG 0x27UL /*!< ISP Command: Flash Multi-Word Program \hideinitializer */ +#define FMC_ISPCMD_RUN_ALL1 0x28UL /*!< ISP Command: Run all-one verification \hideinitializer */ // I version +#define FMC_ISPCMD_RUN_CKS 0x2DUL /*!< ISP Command: Run checksum calculation \hideinitializer */ +#define FMC_ISPCMD_BANK_REMAP 0x2CUL /*!< ISP Command: Bank Remap \hideinitializer */ +#define FMC_ISPCMD_VECMAP 0x2EUL /*!< ISP Command: Vector Page Remap \hideinitializer */ + +#define IS_BOOT_FROM_APROM 0UL /*!< Is booting from APROM \hideinitializer */ +#define IS_BOOT_FROM_LDROM 1UL /*!< Is booting from LDROM \hideinitializer */ + +#define READ_ALLONE_YES 0xA11FFFFFUL /*!< Check-all-one result is all one. \hideinitializer */ +#define READ_ALLONE_NOT 0xA1100000UL /*!< Check-all-one result is not all one. \hideinitializer */ +#define READ_ALLONE_CMD_FAIL 0xFFFFFFFFUL /*!< Check-all-one command failed. \hideinitializer */ +/*@}*/ /* end of group FMC_EXPORTED_CONSTANTS */ + + +/** @addtogroup FMC_EXPORTED_FUNCTIONS FMC Exported Functions + @{ +*/ + + +/*---------------------------------------------------------------------------------------------------------*/ +/* Macros */ +/*---------------------------------------------------------------------------------------------------------*/ + +#define FMC_SET_APROM_BOOT() (FMC->ISPCTL &= ~FMC_ISPCTL_BS_Msk) /*!< Select booting from APROM \hideinitializer */ +#define FMC_SET_LDROM_BOOT() (FMC->ISPCTL |= FMC_ISPCTL_BS_Msk) /*!< Select booting from LDROM \hideinitializer */ +#define FMC_ENABLE_AP_UPDATE() (FMC->ISPCTL |= FMC_ISPCTL_APUEN_Msk) /*!< Enable APROM update \hideinitializer */ +#define FMC_DISABLE_AP_UPDATE() (FMC->ISPCTL &= ~FMC_ISPCTL_APUEN_Msk) /*!< Disable APROM update \hideinitializer */ +#define FMC_ENABLE_CFG_UPDATE() (FMC->ISPCTL |= FMC_ISPCTL_CFGUEN_Msk) /*!< Enable User Config update \hideinitializer */ +#define FMC_DISABLE_CFG_UPDATE() (FMC->ISPCTL &= ~FMC_ISPCTL_CFGUEN_Msk) /*!< Disable User Config update \hideinitializer */ +#define FMC_ENABLE_LD_UPDATE() (FMC->ISPCTL |= FMC_ISPCTL_LDUEN_Msk) /*!< Enable LDROM update \hideinitializer */ +#define FMC_DISABLE_LD_UPDATE() (FMC->ISPCTL &= ~FMC_ISPCTL_LDUEN_Msk) /*!< Disable LDROM update \hideinitializer */ +#define FMC_ENABLE_SP_UPDATE() (FMC->ISPCTL |= FMC_ISPCTL_SPUEN_Msk) /*!< Enable SPROM update \hideinitializer */ +#define FMC_DISABLE_SP_UPDATE() (FMC->ISPCTL &= ~FMC_ISPCTL_SPUEN_Msk) /*!< Disable SPROM update \hideinitializer */ +#define FMC_DISABLE_ISP() (FMC->ISPCTL &= ~FMC_ISPCTL_ISPEN_Msk) /*!< Disable ISP function \hideinitializer */ +#define FMC_ENABLE_ISP() (FMC->ISPCTL |= FMC_ISPCTL_ISPEN_Msk) /*!< Enable ISP function \hideinitializer */ +#define FMC_GET_FAIL_FLAG() ((FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) ? 1UL : 0UL) /*!< Get ISP fail flag \hideinitializer */ +#define FMC_CLR_FAIL_FLAG() (FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk) /*!< Clear ISP fail flag \hideinitializer */ +#define FMC_ENABLE_ISP_INT() (FMC->ISPCTL |= FMC_ISPCTL_INTEN_Msk) /*!< Enable ISP interrupt */ +#define FMC_DISABLE_ISP_INT() (FMC->ISPCTL &= ~FMC_ISPCTL_INTEN_Msk) /*!< Disable ISP interrupt */ +#define FMC_GET_ISP_INT_FLAG() ((FMC->ISPSTS & FMC_ISPSTS_INTFLAG_Msk) ? 1UL : 0UL) /*!< Get ISP interrupt flag Status */ +#define FMC_CLEAR_ISP_INT_FLAG() (FMC->ISPSTS = FMC_ISPSTS_INTFLAG_Msk) /*!< Clear ISP interrupt flag*/ + +/*---------------------------------------------------------------------------------------------------------*/ + +__STATIC_INLINE uint32_t FMC_ReadCID(void); +__STATIC_INLINE uint32_t FMC_ReadPID(void); +__STATIC_INLINE uint32_t FMC_ReadUID(uint8_t u8Index); +__STATIC_INLINE uint32_t FMC_ReadUCID(uint32_t u32Index); +__STATIC_INLINE void FMC_SetVectorPageAddr(uint32_t u32PageAddr); +__STATIC_INLINE uint32_t FMC_GetVECMAP(void); + +/** + * @brief Get current vector mapping address. + * @param None + * @return The current vector mapping address. + * @details To get VECMAP value which is the page address for remapping to vector page (0x0). + * @note + * VECMAP only valid when new IAP function is enabled. (CBS = 10'b or 00'b) + */ +__STATIC_INLINE uint32_t FMC_GetVECMAP(void) +{ + return (FMC->ISPSTS & FMC_ISPSTS_VECMAP_Msk); +} + +/** + * @brief Read company ID + * @param None + * @return The company ID (32-bit) + * @details The company ID of Nuvoton is fixed to be 0xDA + */ +__STATIC_INLINE uint32_t FMC_ReadCID(void) +{ + FMC->ISPCMD = FMC_ISPCMD_READ_CID; /* Set ISP Command Code */ + FMC->ISPADDR = 0x0u; /* Must keep 0x0 when read CID */ + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; /* Trigger to start ISP procedure */ +#if ISBEN + __ISB(); +#endif /* To make sure ISP/CPU be Synchronized */ + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) {} /* Waiting for ISP Done */ + + return FMC->ISPDAT; +} + +/** + * @brief Read product ID + * @param None + * @return The product ID (32-bit) + * @details This function is used to read product ID. + */ +__STATIC_INLINE uint32_t FMC_ReadPID(void) +{ + FMC->ISPCMD = FMC_ISPCMD_READ_DID; /* Set ISP Command Code */ + FMC->ISPADDR = 0x04u; /* Must keep 0x4 when read PID */ + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; /* Trigger to start ISP procedure */ +#if ISBEN + __ISB(); +#endif /* To make sure ISP/CPU be Synchronized */ + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) {} /* Waiting for ISP Done */ + + return FMC->ISPDAT; +} + +/** + * @brief Read Unique ID + * @param[in] u8Index UID index. 0 = UID[31:0], 1 = UID[63:32], 2 = UID[95:64] + * @return The 32-bit unique ID data of specified UID index. + * @details To read out 96-bit Unique ID. + */ +__STATIC_INLINE uint32_t FMC_ReadUID(uint8_t u8Index) +{ + FMC->ISPCMD = FMC_ISPCMD_READ_UID; + FMC->ISPADDR = ((uint32_t)u8Index << 2u); + FMC->ISPDAT = 0u; + FMC->ISPTRG = 0x1u; +#if ISBEN + __ISB(); +#endif + while (FMC->ISPTRG) {} + + return FMC->ISPDAT; +} + +/** + * @brief To read UCID + * @param[in] u32Index Index of the UCID to read. u32Index must be 0, 1, 2, or 3. + * @return The UCID of specified index + * @details This function is used to read unique chip ID (UCID). + */ +__STATIC_INLINE uint32_t FMC_ReadUCID(uint32_t u32Index) +{ + FMC->ISPCMD = FMC_ISPCMD_READ_UID; /* Set ISP Command Code */ + FMC->ISPADDR = (0x04u * u32Index) + 0x10u; /* The UCID is at offset 0x10 with word alignment. */ + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; /* Trigger to start ISP procedure */ +#if ISBEN + __ISB(); +#endif /* To make sure ISP/CPU be Synchronized */ + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) {} /* Waiting for ISP Done */ + + return FMC->ISPDAT; +} + +/** + * @brief Set vector mapping address + * @param[in] u32PageAddr The page address to remap to address 0x0. The address must be page alignment. + * @return To set VECMAP to remap specified page address to 0x0. + * @details This function is used to set VECMAP to map specified page to vector page (0x0). + * @note + * VECMAP only valid when new IAP function is enabled. (CBS = 10'b or 00'b) + */ +__STATIC_INLINE void FMC_SetVectorPageAddr(uint32_t u32PageAddr) +{ + FMC->ISPCMD = FMC_ISPCMD_VECMAP; /* Set ISP Command Code */ + FMC->ISPADDR = u32PageAddr; /* The address of specified page which will be map to address 0x0. It must be page alignment. */ + FMC->ISPTRG = 0x1u; /* Trigger to start ISP procedure */ +#if ISBEN + __ISB(); +#endif /* To make sure ISP/CPU be Synchronized */ + while (FMC->ISPTRG) {} /* Waiting for ISP Done */ +} + + +/*---------------------------------------------------------------------------------------------------------*/ +/* Functions */ +/*---------------------------------------------------------------------------------------------------------*/ + +extern void FMC_Close(void); +extern int32_t FMC_Erase(uint32_t u32PageAddr); +extern int32_t FMC_Erase_SPROM(void); +extern int32_t FMC_Erase_Bank(uint32_t u32BankAddr); +extern int32_t FMC_GetBootSource(void); +extern void FMC_Open(void); +extern uint32_t FMC_Read(uint32_t u32Addr); +extern uint32_t FMC_ReadDataFlashBaseAddr(void); +extern void FMC_SetBootSource(int32_t i32BootSrc); +extern void FMC_Write(uint32_t u32Addr, uint32_t u32Data); +extern int32_t FMC_Write8Bytes(uint32_t u32addr, uint32_t u32data0, uint32_t u32data1); +extern int32_t FMC_ReadConfig(uint32_t u32Config[], uint32_t u32Count); +extern int32_t FMC_WriteConfig(uint32_t u32Config[], uint32_t u32Count); +extern uint32_t FMC_GetChkSum(uint32_t u32addr, uint32_t u32count); +extern uint32_t FMC_CheckAllOne(uint32_t u32addr, uint32_t u32count); +extern int32_t FMC_WriteMultiple(uint32_t u32Addr, uint32_t pu32Buf[], uint32_t u32Len); +extern int32_t FMC_RemapBank(uint32_t u32BankIdx); + +/*@}*/ /* end of group FMC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group FMC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_FMC_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_gpio.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_gpio.h new file mode 100644 index 0000000000..bf0f4dc57a --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_gpio.h @@ -0,0 +1,481 @@ +/**************************************************************************//** + * @file nu_gpio.h + * @version V0.10 + * $Revision: 2 $ + * $Date: 18/12/20 6:49p $ + * @brief M031 Series General Purpose I/O (GPIO) Driver Header File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_GPIO_H__ +#define __NU_GPIO_H__ + +#include "M031Series.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup GPIO_Driver GPIO Driver + @{ +*/ + +/** @addtogroup GPIO_EXPORTED_CONSTANTS GPIO Exported Constants + @{ +*/ + +#define GPIO_PIN_MAX 16 /*!< Specify Maximum Pins of Each GPIO Port \hideinitializer */ + + +/* Define GPIO Pin Data Input/Output. It could be used to control each I/O pin by pin address mapping. + Example 1: + + PA0 = 1; + + It is used to set GPIO PA.0 to high; + + Example 2: + + if (PA0) + PA0 = 0; + + If GPIO PA.0 pin status is high, then set GPIO PA.0 data output to low. + */ +#define GPIO_PIN_DATA(port, pin) (*((volatile uint32_t *)((GPIO_PIN_DATA_BASE+(0x40*(port))) + ((pin)<<2)))) /*!< Specify GPIO Pin Data Input/Output \hideinitializer */ +#define PA0 GPIO_PIN_DATA(0, 0 ) /*!< Specify PA.0 Pin Data Input/Output \hideinitializer */ +#define PA1 GPIO_PIN_DATA(0, 1 ) /*!< Specify PA.1 Pin Data Input/Output \hideinitializer */ +#define PA2 GPIO_PIN_DATA(0, 2 ) /*!< Specify PA.2 Pin Data Input/Output \hideinitializer */ +#define PA3 GPIO_PIN_DATA(0, 3 ) /*!< Specify PA.3 Pin Data Input/Output \hideinitializer */ +#define PA4 GPIO_PIN_DATA(0, 4 ) /*!< Specify PA.4 Pin Data Input/Output \hideinitializer */ +#define PA5 GPIO_PIN_DATA(0, 5 ) /*!< Specify PA.5 Pin Data Input/Output \hideinitializer */ +#define PA6 GPIO_PIN_DATA(0, 6 ) /*!< Specify PA.6 Pin Data Input/Output \hideinitializer */ +#define PA7 GPIO_PIN_DATA(0, 7 ) /*!< Specify PA.7 Pin Data Input/Output \hideinitializer */ +#define PA8 GPIO_PIN_DATA(0, 8 ) /*!< Specify PA.8 Pin Data Input/Output \hideinitializer */ +#define PA9 GPIO_PIN_DATA(0, 9 ) /*!< Specify PA.9 Pin Data Input/Output \hideinitializer */ +#define PA10 GPIO_PIN_DATA(0, 10) /*!< Specify PA.10 Pin Data Input/Output \hideinitializer */ +#define PA11 GPIO_PIN_DATA(0, 11) /*!< Specify PA.11 Pin Data Input/Output \hideinitializer */ +#define PA12 GPIO_PIN_DATA(0, 12) /*!< Specify PA.12 Pin Data Input/Output \hideinitializer */ +#define PA13 GPIO_PIN_DATA(0, 13) /*!< Specify PA.13 Pin Data Input/Output \hideinitializer */ +#define PA14 GPIO_PIN_DATA(0, 14) /*!< Specify PA.14 Pin Data Input/Output \hideinitializer */ +#define PA15 GPIO_PIN_DATA(0, 15) /*!< Specify PA.15 Pin Data Input/Output \hideinitializer */ + +#define PB0 GPIO_PIN_DATA(1, 0 ) /*!< Specify PB.0 Pin Data Input/Output \hideinitializer */ +#define PB1 GPIO_PIN_DATA(1, 1 ) /*!< Specify PB.1 Pin Data Input/Output \hideinitializer */ +#define PB2 GPIO_PIN_DATA(1, 2 ) /*!< Specify PB.2 Pin Data Input/Output \hideinitializer */ +#define PB3 GPIO_PIN_DATA(1, 3 ) /*!< Specify PB.3 Pin Data Input/Output \hideinitializer */ +#define PB4 GPIO_PIN_DATA(1, 4 ) /*!< Specify PB.4 Pin Data Input/Output \hideinitializer */ +#define PB5 GPIO_PIN_DATA(1, 5 ) /*!< Specify PB.5 Pin Data Input/Output \hideinitializer */ +#define PB6 GPIO_PIN_DATA(1, 6 ) /*!< Specify PB.6 Pin Data Input/Output \hideinitializer */ +#define PB7 GPIO_PIN_DATA(1, 7 ) /*!< Specify PB.7 Pin Data Input/Output \hideinitializer */ +#define PB8 GPIO_PIN_DATA(1, 8 ) /*!< Specify PB.8 Pin Data Input/Output \hideinitializer */ +#define PB9 GPIO_PIN_DATA(1, 9 ) /*!< Specify PB.9 Pin Data Input/Output \hideinitializer */ +#define PB10 GPIO_PIN_DATA(1, 10) /*!< Specify PB.10 Pin Data Input/Output \hideinitializer */ +#define PB11 GPIO_PIN_DATA(1, 11) /*!< Specify PB.11 Pin Data Input/Output \hideinitializer */ +#define PB12 GPIO_PIN_DATA(1, 12) /*!< Specify PB.12 Pin Data Input/Output \hideinitializer */ +#define PB13 GPIO_PIN_DATA(1, 13) /*!< Specify PB.13 Pin Data Input/Output \hideinitializer */ +#define PB14 GPIO_PIN_DATA(1, 14) /*!< Specify PB.14 Pin Data Input/Output \hideinitializer */ +#define PB15 GPIO_PIN_DATA(1, 15) /*!< Specify PB.15 Pin Data Input/Output \hideinitializer */ + +#define PC0 GPIO_PIN_DATA(2, 0 ) /*!< Specify PC.0 Pin Data Input/Output \hideinitializer */ +#define PC1 GPIO_PIN_DATA(2, 1 ) /*!< Specify PC.1 Pin Data Input/Output \hideinitializer */ +#define PC2 GPIO_PIN_DATA(2, 2 ) /*!< Specify PC.2 Pin Data Input/Output \hideinitializer */ +#define PC3 GPIO_PIN_DATA(2, 3 ) /*!< Specify PC.3 Pin Data Input/Output \hideinitializer */ +#define PC4 GPIO_PIN_DATA(2, 4 ) /*!< Specify PC.4 Pin Data Input/Output \hideinitializer */ +#define PC5 GPIO_PIN_DATA(2, 5 ) /*!< Specify PC.5 Pin Data Input/Output \hideinitializer */ +#define PC6 GPIO_PIN_DATA(2, 6 ) /*!< Specify PC.6 Pin Data Input/Output \hideinitializer */ +#define PC7 GPIO_PIN_DATA(2, 7 ) /*!< Specify PC.7 Pin Data Input/Output \hideinitializer */ +#define PC8 GPIO_PIN_DATA(2, 8 ) /*!< Specify PC.8 Pin Data Input/Output \hideinitializer */ +#define PC9 GPIO_PIN_DATA(2, 9 ) /*!< Specify PC.9 Pin Data Input/Output \hideinitializer */ +#define PC10 GPIO_PIN_DATA(2, 10) /*!< Specify PC.10 Pin Data Input/Output \hideinitializer */ +#define PC11 GPIO_PIN_DATA(2, 11) /*!< Specify PC.11 Pin Data Input/Output \hideinitializer */ +#define PC12 GPIO_PIN_DATA(2, 12) /*!< Specify PC.12 Pin Data Input/Output \hideinitializer */ +#define PC13 GPIO_PIN_DATA(2, 13) /*!< Specify PC.13 Pin Data Input/Output \hideinitializer */ +#define PC14 GPIO_PIN_DATA(2, 14) /*!< Specify PC.14 Pin Data Input/Output \hideinitializer */ + +#define PD0 GPIO_PIN_DATA(3, 0 ) /*!< Specify PD.0 Pin Data Input/Output \hideinitializer */ +#define PD1 GPIO_PIN_DATA(3, 1 ) /*!< Specify PD.1 Pin Data Input/Output \hideinitializer */ +#define PD2 GPIO_PIN_DATA(3, 2 ) /*!< Specify PD.2 Pin Data Input/Output \hideinitializer */ +#define PD3 GPIO_PIN_DATA(3, 3 ) /*!< Specify PD.3 Pin Data Input/Output \hideinitializer */ +#define PD4 GPIO_PIN_DATA(3, 4 ) /*!< Specify PD.4 Pin Data Input/Output \hideinitializer */ +#define PD5 GPIO_PIN_DATA(3, 5 ) /*!< Specify PD.5 Pin Data Input/Output \hideinitializer */ +#define PD6 GPIO_PIN_DATA(3, 6 ) /*!< Specify PD.6 Pin Data Input/Output \hideinitializer */ +#define PD7 GPIO_PIN_DATA(3, 7 ) /*!< Specify PD.7 Pin Data Input/Output \hideinitializer */ +#define PD8 GPIO_PIN_DATA(3, 8 ) /*!< Specify PD.8 Pin Data Input/Output \hideinitializer */ +#define PD9 GPIO_PIN_DATA(3, 9 ) /*!< Specify PD.9 Pin Data Input/Output \hideinitializer */ +#define PD10 GPIO_PIN_DATA(3, 10) /*!< Specify PD.10 Pin Data Input/Output \hideinitializer */ +#define PD11 GPIO_PIN_DATA(3, 11) /*!< Specify PD.11 Pin Data Input/Output \hideinitializer */ +#define PD12 GPIO_PIN_DATA(3, 12) /*!< Specify PD.12 Pin Data Input/Output \hideinitializer */ +#define PD13 GPIO_PIN_DATA(3, 13) /*!< Specify PD.13 Pin Data Input/Output \hideinitializer */ +#define PD14 GPIO_PIN_DATA(3, 14) /*!< Specify PD.14 Pin Data Input/Output \hideinitializer */ +#define PD15 GPIO_PIN_DATA(3, 15) /*!< Specify PD.15 Pin Data Input/Output \hideinitializer */ + +#define PE0 GPIO_PIN_DATA(4, 0 ) /*!< Specify PE.0 Pin Data Input/Output \hideinitializer */ +#define PE1 GPIO_PIN_DATA(4, 1 ) /*!< Specify PE.1 Pin Data Input/Output \hideinitializer */ +#define PE2 GPIO_PIN_DATA(4, 2 ) /*!< Specify PE.2 Pin Data Input/Output \hideinitializer */ +#define PE3 GPIO_PIN_DATA(4, 3 ) /*!< Specify PE.3 Pin Data Input/Output \hideinitializer */ +#define PE4 GPIO_PIN_DATA(4, 4 ) /*!< Specify PE.4 Pin Data Input/Output \hideinitializer */ +#define PE5 GPIO_PIN_DATA(4, 5 ) /*!< Specify PE.5 Pin Data Input/Output \hideinitializer */ +#define PE6 GPIO_PIN_DATA(4, 6 ) /*!< Specify PE.6 Pin Data Input/Output \hideinitializer */ +#define PE7 GPIO_PIN_DATA(4, 7 ) /*!< Specify PE.7 Pin Data Input/Output \hideinitializer */ +#define PE8 GPIO_PIN_DATA(4, 8 ) /*!< Specify PE.8 Pin Data Input/Output \hideinitializer */ +#define PE9 GPIO_PIN_DATA(4, 9 ) /*!< Specify PE.9 Pin Data Input/Output \hideinitializer */ +#define PE10 GPIO_PIN_DATA(4, 10) /*!< Specify PE.10 Pin Data Input/Output \hideinitializer */ +#define PE11 GPIO_PIN_DATA(4, 11) /*!< Specify PE.11 Pin Data Input/Output \hideinitializer */ +#define PE12 GPIO_PIN_DATA(4, 12) /*!< Specify PE.12 Pin Data Input/Output \hideinitializer */ +#define PE13 GPIO_PIN_DATA(4, 13) /*!< Specify PE.13 Pin Data Input/Output \hideinitializer */ +#define PE14 GPIO_PIN_DATA(4, 14) /*!< Specify PE.14 Pin Data Input/Output \hideinitializer */ +#define PE15 GPIO_PIN_DATA(4, 15) /*!< Specify PE.15 Pin Data Input/Output \hideinitializer */ + +#define PF0 GPIO_PIN_DATA(5, 0 ) /*!< Specify PF.0 Pin Data Input/Output \hideinitializer */ +#define PF1 GPIO_PIN_DATA(5, 1 ) /*!< Specify PF.1 Pin Data Input/Output \hideinitializer */ +#define PF2 GPIO_PIN_DATA(5, 2 ) /*!< Specify PF.2 Pin Data Input/Output \hideinitializer */ +#define PF3 GPIO_PIN_DATA(5, 3 ) /*!< Specify PF.3 Pin Data Input/Output \hideinitializer */ +#define PF4 GPIO_PIN_DATA(5, 4 ) /*!< Specify PF.4 Pin Data Input/Output \hideinitializer */ +#define PF5 GPIO_PIN_DATA(5, 5 ) /*!< Specify PF.5 Pin Data Input/Output \hideinitializer */ +#define PF6 GPIO_PIN_DATA(5, 6 ) /*!< Specify PF.6 Pin Data Input/Output \hideinitializer */ +#define PF7 GPIO_PIN_DATA(5, 7 ) /*!< Specify PF.7 Pin Data Input/Output \hideinitializer */ +#define PF8 GPIO_PIN_DATA(5, 8 ) /*!< Specify PF.8 Pin Data Input/Output \hideinitializer */ +#define PF9 GPIO_PIN_DATA(5, 9 ) /*!< Specify PF.9 Pin Data Input/Output \hideinitializer */ +#define PF10 GPIO_PIN_DATA(5, 10) /*!< Specify PF.10 Pin Data Input/Output \hideinitializer */ +#define PF11 GPIO_PIN_DATA(5, 11) /*!< Specify PF.11 Pin Data Input/Output \hideinitializer */ +#define PF14 GPIO_PIN_DATA(5, 14) /*!< Specify PF.14 Pin Data Input/Output \hideinitializer */ +#define PF15 GPIO_PIN_DATA(5, 15) /*!< Specify PF.15 Pin Data Input/Output \hideinitializer */ + +#define PG2 GPIO_PIN_DATA(6, 2 ) /*!< Specify PG.2 Pin Data Input/Output \hideinitializer */ +#define PG3 GPIO_PIN_DATA(6, 3 ) /*!< Specify PG.3 Pin Data Input/Output \hideinitializer */ +#define PG4 GPIO_PIN_DATA(6, 4 ) /*!< Specify PG.4 Pin Data Input/Output \hideinitializer */ +#define PG9 GPIO_PIN_DATA(6, 9 ) /*!< Specify PG.9 Pin Data Input/Output \hideinitializer */ +#define PG10 GPIO_PIN_DATA(6, 10) /*!< Specify PG.10 Pin Data Input/Output \hideinitializer */ +#define PG11 GPIO_PIN_DATA(6, 11) /*!< Specify PG.11 Pin Data Input/Output \hideinitializer */ +#define PG12 GPIO_PIN_DATA(6, 12) /*!< Specify PG.12 Pin Data Input/Output \hideinitializer */ +#define PG13 GPIO_PIN_DATA(6, 13) /*!< Specify PG.13 Pin Data Input/Output \hideinitializer */ +#define PG14 GPIO_PIN_DATA(6, 14) /*!< Specify PG.14 Pin Data Input/Output \hideinitializer */ +#define PG15 GPIO_PIN_DATA(6, 15) /*!< Specify PG.15 Pin Data Input/Output \hideinitializer */ + +#define PH4 GPIO_PIN_DATA(7, 4 ) /*!< Specify PH.4 Pin Data Input/Output \hideinitializer */ +#define PH5 GPIO_PIN_DATA(7, 5 ) /*!< Specify PH.5 Pin Data Input/Output \hideinitializer */ +#define PH6 GPIO_PIN_DATA(7, 6 ) /*!< Specify PH.6 Pin Data Input/Output \hideinitializer */ +#define PH7 GPIO_PIN_DATA(7, 7 ) /*!< Specify PH.7 Pin Data Input/Output \hideinitializer */ +#define PH8 GPIO_PIN_DATA(7, 8 ) /*!< Specify PH.8 Pin Data Input/Output \hideinitializer */ +#define PH9 GPIO_PIN_DATA(7, 9 ) /*!< Specify PH.9 Pin Data Input/Output \hideinitializer */ +#define PH10 GPIO_PIN_DATA(7, 10) /*!< Specify PH.10 Pin Data Input/Output \hideinitializer */ +#define PH11 GPIO_PIN_DATA(7, 11) /*!< Specify PH.11 Pin Data Input/Output \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* GPIO_MODE Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define GPIO_MODE_INPUT 0x0UL /*!< Input Mode \hideinitializer */ +#define GPIO_MODE_OUTPUT 0x1UL /*!< Output Mode \hideinitializer */ +#define GPIO_MODE_OPEN_DRAIN 0x2UL /*!< Open-Drain Mode \hideinitializer */ +#define GPIO_MODE_QUASI 0x3UL /*!< Quasi-bidirectional Mode \hideinitializer */ +#define GPIO_MODE(pin, mode) ((mode) << ((pin)<<1)) /*!< Generate the PMD mode setting for each pin \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* GPIO Interrupt Type Constant Definitions (Parameter of GPIO_EnableInt()) */ +/*---------------------------------------------------------------------------------------------------------*/ +#define GPIO_INT_RISING 0x00010000UL /*!< Interrupt enable by Input Rising Edge \hideinitializer */ +#define GPIO_INT_FALLING 0x00000001UL /*!< Interrupt enable by Input Falling Edge \hideinitializer */ +#define GPIO_INT_BOTH_EDGE 0x00010001UL /*!< Interrupt enable by both Rising Edge and Falling Edge \hideinitializer */ +#define GPIO_INT_HIGH 0x01010000UL /*!< Interrupt enable by Level-High \hideinitializer */ +#define GPIO_INT_LOW 0x01000001UL /*!< Interrupt enable by Level-Low \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* GPIO_INTTYPE Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define GPIO_INTTYPE_EDGE 0UL /*!< GPIO_INTTYPE Setting for Edge Trigger Mode \hideinitializer */ +#define GPIO_INTTYPE_LEVEL 1UL /*!< GPIO_INTTYPE Setting for Level Mode \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* GPIO_DBCTL Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define GPIO_DBCTL_ICLK_OFF (0x0UL<INTSRC = (u32PinMask)) + +/** + * @brief Disable Pin De-bounce Function + * @param[in] port GPIO port. It could be PA, PB, PC, PD, PE, PF, PG, or PH. + * @param[in] u32PinMask The single or multiple pins of specified GPIO port. + * It could be BIT0 ~ BIT15 for PA, PB, PD, and PE. + * It could be BIT0 ~ BIT14 for PC. + * It could be BIT0 ~ BIT11, BIT14, and BIT15 for PF. + * It could be BIT2 ~ BIT4, and BIT9 ~ BIT15 for PG. + * It could be BIT4 ~ BIT11 for PH. + * @return None + * @details Disable the interrupt de-bounce function of specified GPIO pin. + * \hideinitializer + */ +#define GPIO_DISABLE_DEBOUNCE(port, u32PinMask) ((port)->DBEN &= ~(u32PinMask)) + +/** + * @brief Enable Pin De-bounce Function + * @param[in] port GPIO port. It could be PA, PB, PC, PD, PE, PF, PG, or PH. + * @param[in] u32PinMask The single or multiple pins of specified GPIO port. + * It could be BIT0 ~ BIT15 for PA, PB, PD, and PE. + * It could be BIT0 ~ BIT14 for PC. + * It could be BIT0 ~ BIT11, BIT14, and BIT15 for PF. + * It could be BIT2 ~ BIT4, and BIT9 ~ BIT15 for PG. + * It could be BIT4 ~ BIT11 for PH. + * @return None + * @details Enable the interrupt de-bounce function of specified GPIO pin. + * \hideinitializer + */ +#define GPIO_ENABLE_DEBOUNCE(port, u32PinMask) ((port)->DBEN |= (u32PinMask)) + +/** + * @brief Disable I/O Digital Input Path + * @param[in] port GPIO port. It could be PA, PB, PC, PD, PE, PF, PG, or PH. + * @param[in] u32PinMask The single or multiple pins of specified GPIO port. + * It could be BIT0 ~ BIT15 for PA, PB, PD, and PE. + * It could be BIT0 ~ BIT14 for PC. + * It could be BIT0 ~ BIT11, BIT14, and BIT15 for PF. + * It could be BIT2 ~ BIT4, and BIT9 ~ BIT15 for PG. + * It could be BIT4 ~ BIT11 for PH. + * @return None + * @details Disable I/O digital input path of specified GPIO pin. + * \hideinitializer + */ +#define GPIO_DISABLE_DIGITAL_PATH(port, u32PinMask) ((port)->DINOFF |= ((u32PinMask)<<16)) + +/** + * @brief Enable I/O Digital Input Path + * @param[in] port GPIO port. It could be PA, PB, PC, PD, PE, PF, PG, or PH. + * @param[in] u32PinMask The single or multiple pins of specified GPIO port. + * It could be BIT0 ~ BIT15 for PA, PB, PD, and PE. + * It could be BIT0 ~ BIT14 for PC. + * It could be BIT0 ~ BIT11, BIT14, and BIT15 for PF. + * It could be BIT2 ~ BIT4, and BIT9 ~ BIT15 for PG. + * It could be BIT4 ~ BIT11 for PH. + * @return None + * @details Enable I/O digital input path of specified GPIO pin. + * \hideinitializer + */ +#define GPIO_ENABLE_DIGITAL_PATH(port, u32PinMask) ((port)->DINOFF &= ~((u32PinMask)<<16)) + +/** + * @brief Disable I/O DOUT mask + * @param[in] port GPIO port. It could be PA, PB, PC, PD, PE, PF, PG, or PH. + * @param[in] u32PinMask The single or multiple pins of specified GPIO port. + * It could be BIT0 ~ BIT15 for PA, PB, PD, and PE. + * It could be BIT0 ~ BIT14 for PC. + * It could be BIT0 ~ BIT11, BIT14, and BIT15 for PF. + * It could be BIT2 ~ BIT4, and BIT9 ~ BIT15 for PG. + * It could be BIT4 ~ BIT11 for PH. + * @return None + * @details Disable I/O DOUT mask of specified GPIO pin. + * \hideinitializer + */ +#define GPIO_DISABLE_DOUT_MASK(port, u32PinMask) ((port)->DATMSK &= ~(u32PinMask)) + +/** + * @brief Enable I/O DOUT mask + * @param[in] port GPIO port. It could be PA, PB, PC, PD, PE, PF, PG, or PH. + * @param[in] u32PinMask The single or multiple pins of specified GPIO port. + * It could be BIT0 ~ BIT15 for PA, PB, PD, and PE. + * It could be BIT0 ~ BIT14 for PC. + * It could be BIT0 ~ BIT11, BIT14, and BIT15 for PF. + * It could be BIT2 ~ BIT4, and BIT9 ~ BIT15 for PG. + * It could be BIT4 ~ BIT11 for PH. + * @return None + * @details Enable I/O DOUT mask of specified GPIO pin. + * \hideinitializer + */ +#define GPIO_ENABLE_DOUT_MASK(port, u32PinMask) ((port)->DATMSK |= (u32PinMask)) + +/** + * @brief Get GPIO Pin Interrupt Flag + * @param[in] port GPIO port. It could be PA, PB, PC, PD, PE, PF, PG, or PH. + * @param[in] u32PinMask The single or multiple pins of specified GPIO port. + * It could be BIT0 ~ BIT15 for PA, PB, PD, and PE. + * It could be BIT0 ~ BIT14 for PC. + * It could be BIT0 ~ BIT11, BIT14, and BIT15 for PF. + * It could be BIT2 ~ BIT4, and BIT9 ~ BIT15 for PG. + * It could be BIT4 ~ BIT11 for PH. + * @retval 0 No interrupt at specified GPIO pin + * @retval 1 The specified GPIO pin generate an interrupt + * @details Get the interrupt status of specified GPIO pin. + * \hideinitializer + */ +#define GPIO_GET_INT_FLAG(port, u32PinMask) ((port)->INTSRC & (u32PinMask)) + +/** + * @brief Set De-bounce Sampling Cycle Time + * @param[in] u32ClkSrc The de-bounce counter clock source. It could be + * - \ref GPIO_DBCTL_DBCLKSRC_HCLK + * - \ref GPIO_DBCTL_DBCLKSRC_LIRC + * @param[in] u32ClkSel The de-bounce sampling cycle selection. It could be + * - \ref GPIO_DBCTL_DBCLKSEL_1 + * - \ref GPIO_DBCTL_DBCLKSEL_2 + * - \ref GPIO_DBCTL_DBCLKSEL_4 + * - \ref GPIO_DBCTL_DBCLKSEL_8 + * - \ref GPIO_DBCTL_DBCLKSEL_16 + * - \ref GPIO_DBCTL_DBCLKSEL_32 + * - \ref GPIO_DBCTL_DBCLKSEL_64 + * - \ref GPIO_DBCTL_DBCLKSEL_128 + * - \ref GPIO_DBCTL_DBCLKSEL_256 + * - \ref GPIO_DBCTL_DBCLKSEL_512 + * - \ref GPIO_DBCTL_DBCLKSEL_1024 + * - \ref GPIO_DBCTL_DBCLKSEL_2048 + * - \ref GPIO_DBCTL_DBCLKSEL_4096 + * - \ref GPIO_DBCTL_DBCLKSEL_8192 + * - \ref GPIO_DBCTL_DBCLKSEL_16384 + * - \ref GPIO_DBCTL_DBCLKSEL_32768 + * @return None + * @details Set the interrupt de-bounce sampling cycle time based on the debounce counter clock source. \n + * Example: GPIO_SET_DEBOUNCE_TIME(GPIO_DBCTL_DBCLKSRC_LIRC, GPIO_DBCTL_DBCLKSEL_4). \n + * It's meaning the de-bounce counter clock source is LIRC (38.4 KHz) and sampling cycle selection is 4. \n + * Then the target de-bounce sampling cycle time is (4)*(1/38400) s = 4*26.042 us = 104.168 us, + * and system will sampling interrupt input once per 104.168 us. + * \hideinitializer + */ +#define GPIO_SET_DEBOUNCE_TIME(u32ClkSrc, u32ClkSel) (GPIO->DBCTL = (GPIO_DBCTL_ICLKON_Msk | (u32ClkSrc) | (u32ClkSel))) + +/** + * @brief Set GPIO Interrupt Clock on bit + * @param[in] port Not used in M031. + * @return None + * @details Set the I/O pins edge detection circuit always active after reset for specified port. + * \hideinitializer + */ +#define GPIO_SET_DEBOUNCE_ICLKON(port) (GPIO->DBCTL |= GPIO_DBCTL_ICLKON_Msk) + +/** + * @brief Clear GPIO Interrupt Clock on bit + * @param[in] port Not used in M031. + * @return None + * @details Set edge detection circuit active only if I/O pin edge interrupt enabled for specified port + * \hideinitializer + */ +#define GPIO_CLR_DEBOUNCE_ICLKON(port) (GPIO->DBCTL &= ~(GPIO_DBCTL_ICLKON_Msk)) + +/** + * @brief Get GPIO Port IN Data + * @param[in] port GPIO port. It could be PA, PB, PC, PD, PE, PF, PG, or PH. + * @return The specified port data + * @details Get the PIN register of specified GPIO port. + * \hideinitializer + */ +#define GPIO_GET_IN_DATA(port) ((port)->PIN) + +/** + * @brief Set GPIO Port OUT Data + * @param[in] port GPIO port. It could be PA, PB, PC, PD, PE, PF, PG, or PH. + * @param[in] u32Data GPIO port data. + * @return None + * @details Set the Data into specified GPIO port. + * \hideinitializer + */ +#define GPIO_SET_OUT_DATA(port, u32Data) ((port)->DOUT = (u32Data)) + +/** + * @brief Toggle Specified GPIO pin + * @param[in] u32Pin Pxy + * @return None + * @details Toggle the specified GPIO pint. + * \hideinitializer + */ +#define GPIO_TOGGLE(u32Pin) ((u32Pin) ^= 1) + +/** + * @brief Enable External GPIO interrupt + * @param[in] port GPIO port. It could be PA, PB, PC, PD, or PF. + * @param[in] u32Pin The pin of specified GPIO port. + * It could be 0 ~ 15 for PA, PB, PD, and PE. + * It could be 0 ~ 14 for PC. + * It could be 0 ~ 11, 14, and 15 for PF. + * It could be 2 ~ 4, and 9 ~ 15 for PG. + * It could be 4 ~ 11 for PH. + * @param[in] u32IntAttribs The interrupt attribute of specified GPIO pin. It could be + * - \ref GPIO_INT_RISING + * - \ref GPIO_INT_FALLING + * - \ref GPIO_INT_BOTH_EDGE + * - \ref GPIO_INT_HIGH + * - \ref GPIO_INT_LOW + * @return None + * @details This function is used to enable specified GPIO pin interrupt. + * \hideinitializer + */ +#define GPIO_EnableEINT GPIO_EnableInt + +/** + * @brief Disable External GPIO interrupt + * @param[in] port GPIO port. It could be PA, PB, PC, PD, or PF. + * @param[in] u32Pin The pin of specified GPIO port. + * It could be 0 ~ 15 for PA, PB, PD, and PE. + * It could be 0 ~ 14 for PC. + * It could be 0 ~ 11, 14, and 15 for PF. + * It could be 2 ~ 4, and 9 ~ 15 for PG. + * It could be 4 ~ 11 for PH. + * @return None + * @details This function is used to enable specified GPIO pin interrupt. + * \hideinitializer + */ +#define GPIO_DisableEINT GPIO_DisableInt + + +void GPIO_SetMode(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode); +void GPIO_EnableInt(GPIO_T *port, uint32_t u32Pin, uint32_t u32IntAttribs); +void GPIO_DisableInt(GPIO_T *port, uint32_t u32Pin); + + +/*@}*/ /* end of group GPIO_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group GPIO_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_GPIO_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_hdiv.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_hdiv.h new file mode 100644 index 0000000000..8013b9f797 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_hdiv.h @@ -0,0 +1,88 @@ +/**************************************************************************//** + * @file nu_hdiv.h + * @version V1.00 + * $Revision: 1 $ + * $Date: 18/07/25 3:42p $ + * @brief M031 series Hardware Divider(HDIV) driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + ******************************************************************************/ +#ifndef __NU_HDIV_H__ +#define __NU_HDIV_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup HDIV_Driver HDIV Driver + @{ +*/ + +/** @addtogroup HDIV_EXPORTED_FUNCTIONS HDIV Exported Functions + @{ +*/ + +/** + * @brief Division function to calculate (x/y) + * + * @param[in] x the dividend of the division + * @param[in] y the divisor of the division + * + * @return The result of (x/y) + * + * @details This is a division function to calculate x/y + * + */ +static __INLINE int32_t HDIV_Div(int32_t x, int16_t y) +{ + uint32_t *p32; + + p32 = (uint32_t *)HDIV_BASE; + *p32++ = x; + *p32++ = y; + return *p32; +} + + +/** + * @brief To calculate the remainder of x/y, i.e., the result of x mod y. + * + * @param[in] x the dividend of the division + * @param[in] y the divisor of the division + * + * @return The remainder of (x/y) + * + * @details This function is used to calculate the remainder of x/y. + */ +static __INLINE int16_t HDIV_Mod(int32_t x, int16_t y) +{ + uint32_t *p32; + + p32 = (uint32_t *)HDIV_BASE; + *p32++ = x; + *p32++ = y; + return p32[1]; +} + +/*@}*/ /* end of group HDIV_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group HDIV_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_HDIV_H__ + +/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ + + diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_i2c.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_i2c.h new file mode 100644 index 0000000000..70ddf33479 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_i2c.h @@ -0,0 +1,540 @@ +/****************************************************************************//** + * @file nu_i2c.h + * @version V1.00 + * @brief M031 series I2C driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#ifndef __NU_I2C_H__ +#define __NU_I2C_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup I2C_Driver I2C Driver + @{ +*/ + +/** @addtogroup I2C_EXPORTED_CONSTANTS I2C Exported Constants + @{ +*/ + +/*---------------------------------------------------------------------------------------------------------*/ +/* I2C_CTL constant definitions. */ +/*---------------------------------------------------------------------------------------------------------*/ +#define I2C_CTL_STA_SI 0x28UL /*!< I2C_CTL setting for I2C control bits. It would set STA and SI bits \hideinitializer */ +#define I2C_CTL_STA_SI_AA 0x2CUL /*!< I2C_CTL setting for I2C control bits. It would set STA, SI and AA bits \hideinitializer */ +#define I2C_CTL_STO_SI 0x18UL /*!< I2C_CTL setting for I2C control bits. It would set STO and SI bits \hideinitializer */ +#define I2C_CTL_STO_SI_AA 0x1CUL /*!< I2C_CTL setting for I2C control bits. It would set STO, SI and AA bits \hideinitializer */ +#define I2C_CTL_SI 0x08UL /*!< I2C_CTL setting for I2C control bits. It would set SI bit \hideinitializer */ +#define I2C_CTL_SI_AA 0x0CUL /*!< I2C_CTL setting for I2C control bits. It would set SI and AA bits \hideinitializer */ +#define I2C_CTL_STA 0x20UL /*!< I2C_CTL setting for I2C control bits. It would set STA bit \hideinitializer */ +#define I2C_CTL_STO 0x10UL /*!< I2C_CTL setting for I2C control bits. It would set STO bit \hideinitializer */ +#define I2C_CTL_AA 0x04UL /*!< I2C_CTL setting for I2C control bits. It would set AA bit \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* I2C GCMode constant definitions. */ +/*---------------------------------------------------------------------------------------------------------*/ +#define I2C_GCMODE_ENABLE 1 /*!< Enable I2C GC Mode \hideinitializer */ +#define I2C_GCMODE_DISABLE 0 /*!< Disable I2C GC Mode \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* I2C SMBUS constant definitions. */ +/*---------------------------------------------------------------------------------------------------------*/ +#define I2C_SMBH_ENABLE 1 /*!< Enable SMBus Host Mode enable \hideinitializer */ +#define I2C_SMBD_ENABLE 0 /*!< Enable SMBus Device Mode enable \hideinitializer */ +#define I2C_PECTX_ENABLE 1 /*!< Enable SMBus Packet Error Check Transmit function \hideinitializer */ +#define I2C_PECTX_DISABLE 0 /*!< Disable SMBus Packet Error Check Transmit function \hideinitializer */ + +/*@}*/ /* end of group I2C_EXPORTED_CONSTANTS */ + +/** @addtogroup I2C_EXPORTED_FUNCTIONS I2C Exported Functions + @{ +*/ +/** + * @brief The macro is used to set I2C bus condition at One Time + * + * @param[in] i2c Specify I2C port + * @param[in] u8Ctrl A byte writes to I2C control register + * + * @return None + * + * @details Set I2C_CTL register to control I2C bus conditions of START, STOP, SI, ACK. + * \hideinitializer + */ +#define I2C_SET_CONTROL_REG(i2c, u8Ctrl) ((i2c)->CTL0 = ((i2c)->CTL0 & ~0x3C) | (u8Ctrl)) + +/** + * @brief The macro is used to set START condition of I2C Bus + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details Set the I2C bus START condition in I2C_CTL register. + * \hideinitializer + */ +#define I2C_START(i2c) ((i2c)->CTL0 = ((i2c)->CTL0 | I2C_CTL0_SI_Msk) | I2C_CTL0_STA_Msk) + +/** + * @brief The macro is used to wait I2C bus status get ready + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details When a new status is presented of I2C bus, the SI flag will be set in I2C_CTL register. + * \hideinitializer + */ +#define I2C_WAIT_READY(i2c) while(!((i2c)->CTL0 & I2C_CTL0_SI_Msk)) + +/** + * @brief The macro is used to Read I2C Bus Data Register + * + * @param[in] i2c Specify I2C port + * + * @return A byte of I2C data register + * + * @details I2C controller read data from bus and save it in I2C_DAT register. + * \hideinitializer + */ +#define I2C_GET_DATA(i2c) ((i2c)->DAT) + +/** + * @brief Write a Data to I2C Data Register + * + * @param[in] i2c Specify I2C port + * @param[in] u8Data A byte that writes to data register + * + * @return None + * + * @details When write a data to I2C_DAT register, the I2C controller will shift it to I2C bus. + * \hideinitializer + */ +#define I2C_SET_DATA(i2c, u8Data) ((i2c)->DAT = (u8Data)) + +/** + * @brief Get I2C Bus status code + * + * @param[in] i2c Specify I2C port + * + * @return I2C status code + * + * @details To get this status code to monitor I2C bus event. + * \hideinitializer + */ +#define I2C_GET_STATUS(i2c) ((i2c)->STATUS0) + +/** + * @brief Get Time-out flag from I2C Bus + * + * @param[in] i2c Specify I2C port + * + * @retval 0 I2C Bus time-out is not happened + * @retval 1 I2C Bus time-out is happened + * + * @details When I2C bus occurs time-out event, the time-out flag will be set. + * \hideinitializer + */ +#define I2C_GET_TIMEOUT_FLAG(i2c) ( ((i2c)->TOCTL & I2C_TOCTL_TOIF_Msk) == I2C_TOCTL_TOIF_Msk ? 1:0 ) + +/** + * @brief To get wake-up flag from I2C Bus + * + * @param[in] i2c Specify I2C port + * + * @retval 0 Chip is not woken-up from power-down mode + * @retval 1 Chip is woken-up from power-down mode + * + * @details I2C bus occurs wake-up event, wake-up flag will be set. + * \hideinitializer + */ +#define I2C_GET_WAKEUP_FLAG(i2c) ( ((i2c)->WKSTS & I2C_WKSTS_WKIF_Msk) == I2C_WKSTS_WKIF_Msk ? 1:0 ) + +/** + * @brief To clear wake-up flag + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details If wake-up flag is set, use this macro to clear it. + * \hideinitializer + */ +#define I2C_CLEAR_WAKEUP_FLAG(i2c) ((i2c)->WKSTS = I2C_WKSTS_WKIF_Msk) + +/** + * @brief To get wake-up address frame ACK done flag from I2C Bus + * + * @param[in] i2c Specify I2C port + * + * @retval 0 The ACK bit cycle of address match frame is not done + * @retval 1 The ACK bit cycle of address match frame is done in power-down + * + * @details I2C bus occurs wake-up event and address frame ACK is done, this flag will be set. + * \hideinitializer + */ +#define I2C_GET_WAKEUP_DONE(i2c) ( ((i2c)->WKSTS & I2C_WKSTS_WKAKDONE_Msk) == I2C_WKSTS_WKAKDONE_Msk ? 1 : 0) + +/** + * @brief To clear address frame ACK done flag + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details If wake-up done is set, use this macro to clear it. + * \hideinitializer + */ +#define I2C_CLEAR_WAKEUP_DONE(i2c) ((i2c)->WKSTS = I2C_WKSTS_WKAKDONE_Msk) + +/** + * @brief To get read/write status bit in address wakeup frame + * + * @param[in] i2c Specify I2C port + * + * @retval 0 Write command be record on the address match wakeup frame + * @retval 1 Read command be record on the address match wakeup frame. + * + * @details I2C bus occurs wake-up event and address frame is received, this bit will record read/write status. + * \hideinitializer +*/ +#define I2C_GET_WAKEUP_WR_STATUS(i2c) ( ((i2c)->WKSTS & I2C_WKSTS_WRSTSWK_Msk) == I2C_WKSTS_WRSTSWK_Msk ? 1 : 0) + +/** + * @brief To get SMBus Status + * + * @param[in] i2c Specify I2C port + * + * @return SMBus status + * + * @details To get the Bus Management status of I2C_BUSSTS register + * \hideinitializer + * + */ +#define I2C_SMBUS_GET_STATUS(i2c) ((i2c)->BUSSTS) + +/** + * @brief Get SMBus CRC value + * + * @param[in] i2c Specify I2C port + * + * @return Packet error check byte value + * + * @details The CRC check value after a transmission or a reception by count by using CRC8 + * \hideinitializer + */ +#define I2C_SMBUS_GET_PEC_VALUE(i2c) ((i2c)->PKTCRC) + +/** + * @brief Set SMBus Bytes number of Transmission or reception + * + * @param[in] i2c Specify I2C port + * @param[in] u32PktSize Transmit / Receive bytes + * + * @return None + * + * @details The transmission or receive byte number in one transaction when PECEN is set. The maximum is 255 bytes. + * \hideinitializer + */ +#define I2C_SMBUS_SET_PACKET_BYTE_COUNT(i2c, u32PktSize) ((i2c)->PKTSIZE = (u32PktSize)) + +/** + * @brief Enable SMBus Alert function + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details Device Mode(BMHEN=0): If ALERTEN(I2C_BUSCTL[4]) is set, the Alert pin will pull lo, and reply ACK when get ARP from host + * Host Mode(BMHEN=1): If ALERTEN(I2C_BUSCTL[4]) is set, the Alert pin is supported to receive alert state(Lo trigger) + * \hideinitializer + */ +#define I2C_SMBUS_ENABLE_ALERT(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_ALERTEN_Msk) + +/** + * @brief Disable SMBus Alert pin function + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details Device Mode(BMHEN=0): If ALERTEN(I2C_BUSCTL[4]) is clear, the Alert pin will pull hi, and reply NACK when get ARP from host + * Host Mode(BMHEN=1): If ALERTEN(I2C_BUSCTL[4]) is clear, the Alert pin is not supported to receive alert state(Lo trigger) + * \hideinitializer + */ +#define I2C_SMBUS_DISABLE_ALERT(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_ALERTEN_Msk) + +/** + * @brief Set SMBus SUSCON pin is output mode + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details This function to set SUSCON(I2C_BUSCTL[6]) pin is output mode. + * + * \hideinitializer + */ +#define I2C_SMBUS_SET_SUSCON_OUT(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_SCTLOEN_Msk) + +/** + * @brief Set SMBus SUSCON pin is input mode + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details This function to set SUSCON(I2C_BUSCTL[6]) pin is input mode. + * + * \hideinitializer + */ +#define I2C_SMBUS_SET_SUSCON_IN(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_SCTLOEN_Msk) + +/** + * @brief Set SMBus SUSCON pin output high state + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details This function to set SUSCON(I2C_BUSCTL[6]) pin is output hi state. + * \hideinitializer + */ +#define I2C_SMBUS_SET_SUSCON_HIGH(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_SCTLOSTS_Msk) + + +/** + * @brief Set SMBus SUSCON pin output low state + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details This function to set SUSCON(I2C_BUSCTL[6]) pin is output lo state. + * \hideinitializer + */ +#define I2C_SMBUS_SET_SUSCON_LOW(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_SCTLOSTS_Msk) + +/** + * @brief Enable SMBus Acknowledge control by manual + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details The 9th bit can response the ACK or NACK according the received data by user. When the byte is received, SCLK line stretching to low between the 8th and 9th SCLK pulse. + * \hideinitializer + */ +#define I2C_SMBUS_ACK_MANUAL(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_ACKMEN_Msk) + +/** + * @brief Disable SMBus Acknowledge control by manual + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details Disable acknowledge response control by user. + * \hideinitializer + */ +#define I2C_SMBUS_ACK_AUTO(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_ACKMEN_Msk) + +/** + * @brief Enable SMBus Acknowledge manual interrupt + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details This function is used to enable SMBUS acknowledge manual interrupt on the 9th clock cycle when SMBUS=1 and ACKMEN=1 + * \hideinitializer + */ +#define I2C_SMBUS_9THBIT_INT_ENABLE(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_ACKM9SI_Msk) + +/** + * @brief Disable SMBus Acknowledge manual interrupt + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details This function is used to disable SMBUS acknowledge manual interrupt on the 9th clock cycle when SMBUS=1 and ACKMEN=1 + * \hideinitializer + */ +#define I2C_SMBUS_9THBIT_INT_DISABLE(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_ACKM9SI_Msk) + +/** + * @brief Enable SMBus PEC clear at REPEAT START + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details This function is used to enable the condition of REAEAT START can clear the PEC calculation. + * \hideinitializer + */ +#define I2C_SMBUS_RST_PEC_AT_START_ENABLE(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_PECCLR_Msk) + +/** + * @brief Disable SMBus PEC clear at Repeat START + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details This function is used to disable the condition of Repeat START can clear the PEC calculation. + * \hideinitializer + */ +#define I2C_SMBUS_RST_PEC_AT_START_DISABLE(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_PECCLR_Msk) + +/** + * @brief Enable RX PDMA function. + * @param[in] i2c The pointer of the specified I2C module. + * @return None. + * @details Set RXPDMAEN bit of I2C_CTL1 register to enable RX PDMA transfer function. + * \hideinitializer + */ +#define I2C_ENABLE_RX_PDMA(i2c) ((i2c)->CTL1 |= I2C_CTL1_RXPDMAEN_Msk) + +/** + * @brief Enable TX PDMA function. + * @param[in] i2c The pointer of the specified I2C module. + * @return None. + * @details Set TXPDMAEN bit of I2C_CTL1 register to enable TX PDMA transfer function. + * \hideinitializer + */ +#define I2C_ENABLE_TX_PDMA(i2c) ((i2c)->CTL1 |= I2C_CTL1_TXPDMAEN_Msk) + +/** + * @brief Disable RX PDMA transfer. + * @param[in] i2c The pointer of the specified I2C module. + * @return None. + * @details Clear RXPDMAEN bit of I2C_CTL1 register to disable RX PDMA transfer function. + * \hideinitializer + */ +#define I2C_DISABLE_RX_PDMA(i2c) ((i2c)->CTL1 &= ~I2C_CTL1_RXPDMAEN_Msk) + +/** + * @brief Disable TX PDMA transfer. + * @param[in] i2c The pointer of the specified I2C module. + * @return None. + * @details Clear TXPDMAEN bit of I2C_CTL1 register to disable TX PDMA transfer function. + * \hideinitializer + */ +#define I2C_DISABLE_TX_PDMA(i2c) ((i2c)->CTL1 &= ~I2C_CTL1_TXPDMAEN_Msk) + +/** + * @brief Enable PDMA stretch function. + * @param[in] i2c The pointer of the specified I2C module. + * @return None. + * @details Enable this function is to stretch bus by hardware after PDMA transfer is done if SI is not cleared. + * \hideinitializer + */ +#define I2C_ENABLE_PDMA_STRETCH(i2c) ((i2c)->CTL1 |= I2C_CTL1_PDMASTR_Msk) + +/** + * @brief Disable PDMA stretch function. + * @param[in] i2c The pointer of the specified I2C module. + * @return None. + * @details I2C will send STOP after PDMA transfers done automatically. + * \hideinitializer + */ +#define I2C_DISABLE_PDMA_STRETCH(i2c) ((i2c)->CTL1 &= ~I2C_CTL1_PDMASTR_Msk) + +/** + * @brief Reset PDMA function. + * @param[in] i2c The pointer of the specified I2C module. + * @return None. + * @details I2C PDMA engine will be reset after this function is called. + * \hideinitializer + */ +#define I2C_DISABLE_RST_PDMA(i2c) ((i2c)->CTL1 |= I2C_CTL1_PDMARST_Msk) + +/*---------------------------------------------------------------------------------------------------------*/ +/* inline functions */ +/*---------------------------------------------------------------------------------------------------------*/ + +/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */ +__STATIC_INLINE void I2C_STOP(I2C_T *i2c); + +/** + * @brief The macro is used to set STOP condition of I2C Bus + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details Set the I2C bus STOP condition in I2C_CTL register. + */ +__STATIC_INLINE void I2C_STOP(I2C_T *i2c) +{ + + (i2c)->CTL0 |= (I2C_CTL0_SI_Msk | I2C_CTL0_STO_Msk); + while(i2c->CTL0 & I2C_CTL0_STO_Msk) + { + } +} + +void I2C_ClearTimeoutFlag(I2C_T *i2c); +void I2C_Close(I2C_T *i2c); +void I2C_Trigger(I2C_T *i2c, uint8_t u8Start, uint8_t u8Stop, uint8_t u8Si, uint8_t u8Ack); +void I2C_DisableInt(I2C_T *i2c); +void I2C_EnableInt(I2C_T *i2c); +uint32_t I2C_GetBusClockFreq(I2C_T *i2c); +uint32_t I2C_GetIntFlag(I2C_T *i2c); +uint32_t I2C_GetStatus(I2C_T *i2c); +uint32_t I2C_Open(I2C_T *i2c, uint32_t u32BusClock); +uint8_t I2C_GetData(I2C_T *i2c); +void I2C_SetSlaveAddr(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddr, uint8_t u8GCMode); +void I2C_SetSlaveAddrMask(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddrMask); +uint32_t I2C_SetBusClockFreq(I2C_T *i2c, uint32_t u32BusClock); +void I2C_EnableTimeout(I2C_T *i2c, uint8_t u8LongTimeout); +void I2C_DisableTimeout(I2C_T *i2c); +void I2C_EnableWakeup(I2C_T *i2c); +void I2C_DisableWakeup(I2C_T *i2c); +void I2C_SetData(I2C_T *i2c, uint8_t u8Data); +uint8_t I2C_WriteByte(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t data); +uint32_t I2C_WriteMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t data[], uint32_t u32wLen); +uint8_t I2C_WriteByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t data); +uint32_t I2C_WriteMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t data[], uint32_t u32wLen); +uint8_t I2C_WriteByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t data); +uint32_t I2C_WriteMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t data[], uint32_t u32wLen); +uint8_t I2C_ReadByte(I2C_T *i2c, uint8_t u8SlaveAddr); +uint32_t I2C_ReadMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t rdata[], uint32_t u32rLen); +uint8_t I2C_ReadByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr); +uint32_t I2C_ReadMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t rdata[], uint32_t u32rLen); +uint8_t I2C_ReadByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr); +uint32_t I2C_ReadMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t rdata[], uint32_t u32rLen); +uint32_t I2C_SMBusGetStatus(I2C_T *i2c); +void I2C_SMBusClearInterruptFlag(I2C_T *i2c, uint8_t u8SMBusIntFlag); +void I2C_SMBusSetPacketByteCount(I2C_T *i2c, uint32_t u32PktSize); +void I2C_SMBusOpen(I2C_T *i2c, uint8_t u8HostDevice); +void I2C_SMBusClose(I2C_T *i2c); +void I2C_SMBusPECTxEnable(I2C_T *i2c, uint8_t u8PECTxEn); +uint8_t I2C_SMBusGetPECValue(I2C_T *i2c); +void I2C_SMBusIdleTimeout(I2C_T *i2c, uint32_t us, uint32_t u32Hclk); +void I2C_SMBusTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk); +void I2C_SMBusClockLoTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk); + +/*@}*/ /* end of group I2C_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group I2C_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_pdma.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_pdma.h new file mode 100644 index 0000000000..10fcaabc87 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_pdma.h @@ -0,0 +1,358 @@ +/**************************************************************************//** + * @file nu_pdma.h + * @version V1.00 + * @brief M031 series PDMA driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_PDMA_H__ +#define __NU_PDMA_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup PDMA_Driver PDMA Driver + @{ +*/ + +/** @addtogroup PDMA_EXPORTED_CONSTANTS PDMA Exported Constants + @{ +*/ +#define PDMA_CH_MAX 9UL /*!< Specify Maximum Channels of PDMA \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Operation Mode Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define PDMA_OP_STOP 0x00000000UL /*!INTSTS)) + +/** + * @brief Get Transfer Done Interrupt Status + * + * @param[in] pdma The pointer of the specified PDMA module + * + * @return None + * + * @details Get the transfer done Interrupt status. + * \hideinitializer + */ +#define PDMA_GET_TD_STS(pdma) ((uint32_t)((pdma)->TDSTS)) + +/** + * @brief Clear Transfer Done Interrupt Status + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Mask The channel mask + * + * @return None + * + * @details Clear the transfer done Interrupt status. + * \hideinitializer + */ +#define PDMA_CLR_TD_FLAG(pdma, u32Mask) ((uint32_t)((pdma)->TDSTS = (u32Mask))) + +/** + * @brief Get Target Abort Interrupt Status + * + * @param[in] pdma The pointer of the specified PDMA module + * + * @return None + * + * @details Get the target abort Interrupt status. + * \hideinitializer + */ +#define PDMA_GET_ABORT_STS(pdma) ((uint32_t)((pdma)->ABTSTS)) + +/** + * @brief Clear Target Abort Interrupt Status + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Mask The channel mask + * + * @return None + * + * @details Clear the target abort Interrupt status. + * \hideinitializer + */ +#define PDMA_CLR_ABORT_FLAG(pdma, u32Mask) ((uint32_t)((pdma)->ABTSTS = (u32Mask))) + +/** + * @brief Get Alignment Interrupt Status + * + * @param[in] pdma The pointer of the specified PDMA module + * + * @return None + * + * @details Get Alignment Interrupt status. + * \hideinitializer + */ +#define PDMA_GET_ALIGN_STS(pdma) ((uint32_t)((pdma)->ALIGN)) + +/** + * @brief Clear Alignment Interrupt Status + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Mask The channel mask + * + * @return None + * + * @details Clear the Alignment Interrupt status. + * \hideinitializer + */ +#define PDMA_CLR_ALIGN_FLAG(pdma,u32Mask) ((uint32_t)((pdma)->ALIGN = (u32Mask))) + +/** + * @brief Clear Timeout Interrupt Status + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * + * @return None + * + * @details Clear the selected channel timeout interrupt status. + * \hideinitializer + */ +#define PDMA_CLR_TMOUT_FLAG(pdma, u32Ch) ((uint32_t)((pdma)->INTSTS = (1UL << ((u32Ch) + 8UL)))) + +/** + * @brief Check Channel Status + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * + * @retval 0 Idle state + * @retval 1 Busy state + * + * @details Check the selected channel is busy or not. + * \hideinitializer + */ +#define PDMA_IS_CH_BUSY(pdma, u32Ch) ((uint32_t)((pdma)->TRGSTS & (1UL << (u32Ch)))? 1 : 0) + +/** + * @brief Set Source Address + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32Addr The selected address + * + * @return None + * + * @details This macro set the selected channel source address. + * \hideinitializer + */ +#define PDMA_SET_SRC_ADDR(pdma, u32Ch, u32Addr) ((uint32_t)((pdma)->DSCT[(u32Ch)].SA = (u32Addr))) + +/** + * @brief Set Destination Address + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32Addr The selected address + * + * @return None + * + * @details This macro set the selected channel destination address. + * \hideinitializer + */ +#define PDMA_SET_DST_ADDR(pdma, u32Ch, u32Addr) ((uint32_t)((pdma)->DSCT[(u32Ch)].DA = (u32Addr))) + +/** + * @brief Set Transfer Count + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32TransCount Transfer Count + * + * @return None + * + * @details This macro set the selected channel transfer count. + * \hideinitializer + */ +#define PDMA_SET_TRANS_CNT(pdma, u32Ch, u32TransCount) ((uint32_t)((pdma)->DSCT[(u32Ch)].CTL=((pdma)->DSCT[(u32Ch)].CTL&~PDMA_DSCT_CTL_TXCNT_Msk)|(((u32TransCount)-1UL) << PDMA_DSCT_CTL_TXCNT_Pos))) + +/** + * @brief Set Scatter-gather descriptor Address + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32Addr The descriptor address + * + * @return None + * + * @details This macro set the selected channel scatter-gather descriptor address. + * \hideinitializer + */ +#define PDMA_SET_SCATTER_DESC(pdma, u32Ch, u32Addr) ((uint32_t)((pdma)->DSCT[(u32Ch)].NEXT = (u32Addr) - ((pdma)->SCATBA))) + +/** + * @brief Stop the channel + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * + * @return None + * + * @details This macro stop the selected channel. + * \hideinitializer + */ +#define PDMA_STOP(pdma, u32Ch) ((uint32_t)((pdma)->PAUSE = (1UL << (u32Ch)))) + +/** + * @brief Pause the channel + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * + * @return None + * + * @details This macro pause the selected channel. + * \hideinitializer + */ +#define PDMA_PAUSE(pdma, u32Ch) ((uint32_t)((pdma)->PAUSE = (1UL << (u32Ch)))) + +/*---------------------------------------------------------------------------------------------------------*/ +/* Define PDMA functions prototype */ +/*---------------------------------------------------------------------------------------------------------*/ +void PDMA_Open(PDMA_T *pdma, uint32_t u32Mask); +void PDMA_Close(PDMA_T *pdma); +void PDMA_SetTransferCnt(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Width, uint32_t u32TransCount); +void PDMA_SetTransferAddr(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32SrcAddr, uint32_t u32SrcCtrl, uint32_t u32DstAddr, uint32_t u32DstCtrl); +void PDMA_SetTransferMode(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Peripheral, uint32_t u32ScatterEn, uint32_t u32DescAddr); +void PDMA_SetBurstType(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32BurstType, uint32_t u32BurstSize); +void PDMA_EnableTimeout(PDMA_T *pdma, uint32_t u32Mask); +void PDMA_DisableTimeout(PDMA_T *pdma, uint32_t u32Mask); +void PDMA_SetTimeOut(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32OnOff, uint32_t u32TimeOutCnt); +void PDMA_Trigger(PDMA_T *pdma, uint32_t u32Ch); +void PDMA_EnableInt(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Mask); +void PDMA_DisableInt(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Mask); + + +/*@}*/ /* end of group PDMA_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group PDMA_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_PDMA_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_pwm.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_pwm.h new file mode 100644 index 0000000000..45539bdc17 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_pwm.h @@ -0,0 +1,514 @@ +/**************************************************************************//** + * @file nu_pwm.h + * @version V1.00 + * $Revision: 9 $ + * $Date: 18/06/07 3:47p $ + * @brief M031 series PWM driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_PWM_H__ +#define __NU_PWM_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup PWM_Driver PWM Driver + @{ +*/ + +/** @addtogroup PWM_EXPORTED_CONSTANTS PWM Exported Constants + @{ +*/ +#define PWM_CHANNEL_NUM (6UL) /*!< PWM channel number \hideinitializer */ +#define PWM_CH_0_MASK (0x1UL) /*!< PWM channel 0 mask \hideinitializer */ +#define PWM_CH_1_MASK (0x2UL) /*!< PWM channel 1 mask \hideinitializer */ +#define PWM_CH_2_MASK (0x4UL) /*!< PWM channel 2 mask \hideinitializer */ +#define PWM_CH_3_MASK (0x8UL) /*!< PWM channel 3 mask \hideinitializer */ +#define PWM_CH_4_MASK (0x10UL) /*!< PWM channel 4 mask \hideinitializer */ +#define PWM_CH_5_MASK (0x20UL) /*!< PWM channel 5 mask \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Counter Type Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define PWM_UP_COUNTER (0UL) /*!< Up counter type \hideinitializer */ +#define PWM_DOWN_COUNTER (1UL) /*!< Down counter type \hideinitializer */ +#define PWM_UP_DOWN_COUNTER (2UL) /*!< Up-Down counter type \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Aligned Type Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define PWM_EDGE_ALIGNED (1UL) /*!< PWM working in edge aligned type(down count) \hideinitializer */ +#define PWM_CENTER_ALIGNED (2UL) /*!< PWM working in center aligned type \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Output Level Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define PWM_OUTPUT_NOTHING (0UL) /*!< PWM output nothing \hideinitializer */ +#define PWM_OUTPUT_LOW (1UL) /*!< PWM output low \hideinitializer */ +#define PWM_OUTPUT_HIGH (2UL) /*!< PWM output high \hideinitializer */ +#define PWM_OUTPUT_TOGGLE (3UL) /*!< PWM output toggle \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Synchronous Start Function Control Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define PWM_SSCTL_SSRC_PWM0 (0UL<CTL1 = (pwm)->CTL1 | (0x7ul<CTL1 = (pwm)->CTL1 & ~(0x7ul<SSCTL = ((pwm)->SSCTL & ~PWM_SSCTL_SSRC_Msk) | (u32SyncSrc) | (u32ChannelMask)) + +/** + * @brief Disable timer synchronous start counting function of specified channel(s) + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Bit 0 represents channel 0, bit 1 represents channel 1... + * @return None + * @details This macro is used to disable timer synchronous start counting function of specified channel(s). + * \hideinitializer + */ +#define PWM_DISABLE_TIMER_SYNC(pwm, u32ChannelMask) \ + do{ \ + int i;\ + for(i = 0; i < 6; i++) { \ + if((u32ChannelMask) & (1 << i)) \ + (pwm)->SSCTL &= ~(1UL << i); \ + } \ + }while(0) + +/** + * @brief This macro enable PWM counter synchronous start counting function. + * @param[in] pwm The pointer of the specified PWM module + * @return None + * @details This macro is used to make selected PWM0 and PWM1 channel(s) start counting at the same time. + * To configure synchronous start counting channel(s) by PWM_ENABLE_TIMER_SYNC() and PWM_DISABLE_TIMER_SYNC(). + * \hideinitializer + */ +#define PWM_TRIGGER_SYNC_START(pwm) ((pwm)->SSTRG = PWM_SSTRG_CNTSEN_Msk) + +/** + * @brief This macro enable output inverter of specified channel(s) + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Bit 0 represents channel 0, bit 1 represents channel 1... + * @return None + * @details This macro is used to enable output inverter of specified channel(s). + * \hideinitializer + */ +#define PWM_ENABLE_OUTPUT_INVERTER(pwm, u32ChannelMask) ((pwm)->POLCTL = (u32ChannelMask)) + +/** + * @brief This macro get captured rising data + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @return None + * @details This macro is used to get captured rising data of specified channel. + * \hideinitializer + */ +#define PWM_GET_CAPTURE_RISING_DATA(pwm, u32ChannelNum) (*(__IO uint32_t *) (&((pwm)->RCAPDAT0) + ((u32ChannelNum) << 1))) + +/** + * @brief This macro get captured falling data + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @return None + * @details This macro is used to get captured falling data of specified channel. + * \hideinitializer + */ +#define PWM_GET_CAPTURE_FALLING_DATA(pwm, u32ChannelNum) (*(__IO uint32_t *) (&((pwm)->FCAPDAT0) + ((u32ChannelNum) << 1))) + +/** + * @brief This macro mask output logic to high or low + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Bit 0 represents channel 0, bit 1 represents channel 1... + * @param[in] u32LevelMask Output logic to high or low + * @return None + * @details This macro is used to mask output logic to high or low of specified channel(s). + * @note If u32ChannelMask parameter is 0, then mask function will be disabled. + * \hideinitializer + */ +#define PWM_MASK_OUTPUT(pwm, u32ChannelMask, u32LevelMask) \ + { \ + (pwm)->MSKEN = (u32ChannelMask); \ + (pwm)->MSK = (u32LevelMask); \ + } + +/** + * @brief This macro set the prescaler of the selected channel + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32Prescaler Clock prescaler of specified channel. Valid values are between 0 ~ 0xFFF + * @return None + * @details This macro is used to set the prescaler of specified channel. + * @note Every even channel N, and channel (N + 1) share a prescaler. So if channel 0 prescaler changed, channel 1 will also be affected. + * The clock of PWM counter is divided by (u32Prescaler + 1). + * \hideinitializer + */ +#define PWM_SET_PRESCALER(pwm, u32ChannelNum, u32Prescaler) ((pwm)->CLKPSC[(u32ChannelNum) >> 1] = (u32Prescaler)) + +/** + * @brief This macro get the prescaler of the selected channel + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @return Return Clock prescaler of specified channel. Valid values are between 0 ~ 0xFFF + * @details This macro is used to get the prescaler of specified channel. + * @note Every even channel N, and channel (N + 1) share a prescaler. So if channel 0 prescaler changed, channel 1 will also be affected. + * The clock of PWM counter is divided by (u32Prescaler + 1). + * \hideinitializer + */ +#define PWM_GET_PRESCALER(pwm, u32ChannelNum) (*(__IO uint32_t *) (&((pwm)->CLKPSC[0]) + ((u32ChannelNum) >> 1))) + +/** + * @brief This macro set the comparator of the selected channel + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32CMR Comparator of specified channel. Valid values are between 0~0xFFFF + * @return None + * @details This macro is used to set the comparator of specified channel. + * @note This new setting will take effect on next PWM period. + * \hideinitializer + */ +#define PWM_SET_CMR(pwm, u32ChannelNum, u32CMR) ((pwm)->CMPDAT[(u32ChannelNum)]= (u32CMR)) + +/** + * @brief This macro get the comparator of the selected channel + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @return Return the comparator of specified channel. Valid values are between 0~0xFFFF + * @details This macro is used to get the comparator of specified channel. + * \hideinitializer + */ +#define PWM_GET_CMR(pwm, u32ChannelNum) ((pwm)->CMPDAT[(u32ChannelNum)]) + +/** + * @brief This macro set the period of the selected channel + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32CNR Period of specified channel. Valid values are between 0~0xFFFF + * @return None + * @details This macro is used to set the period of specified channel. + * @note This new setting will take effect on next PWM period. + * @note PWM counter will stop if period length set to 0. + * \hideinitializer + */ +#define PWM_SET_CNR(pwm, u32ChannelNum, u32CNR) ((pwm)->PERIOD[(u32ChannelNum>>1)<<1] = (u32CNR)) + +/** + * @brief This macro get the period of the selected channel + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @return Return the period of specified channel. Valid values are between 0~0xFFFF + * @details This macro is used to get the period of specified channel. + * \hideinitializer + */ +#define PWM_GET_CNR(pwm, u32ChannelNum) ((pwm)->PERIOD[(u32ChannelNum>>1)<<1]) + +/** + * @brief This macro set the PWM aligned type + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Bit 0 represents channel 0, bit 1 represents channel 1... + * @param[in] u32AlignedType PWM aligned type, valid values are: + * - \ref PWM_EDGE_ALIGNED + * - \ref PWM_CENTER_ALIGNED + * @return None + * @details This macro is used to set the PWM aligned type of specified channel(s). + * \hideinitializer + */ +#define PWM_SET_ALIGNED_TYPE(pwm, u32ChannelMask, u32AlignedType) \ + do{ \ + int i; \ + for(i = 0; i < 6; i++) { \ + if((u32ChannelMask) & (1 << i)) \ + (pwm)->CTL1 = (((pwm)->CTL1 & ~(3UL << (i << 1))) | ((u32AlignedType) << (i << 1))); \ + } \ + }while(0) + +/** + * @brief Clear counter of specified channel(s) + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Bit 0 represents channel 0, bit 1 represents channel 1... + * @return None + * @details This macro is used to clear counter of specified channel(s). + * \hideinitializer + */ +#define PWM_CLR_COUNTER(pwm, u32ChannelMask) \ + do{ \ + uint32_t i; \ + for(i = 0UL; i < 6UL; i++) { \ + if((u32ChannelMask) & (1UL << i)) \ + ((pwm)->CNTCLR |= (1UL << ((i >> 1UL) << 1UL))); \ + } \ + }while(0) + +/** + * @brief Set output level at zero, compare up, period(center) and compare down of specified channel(s) + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Bit 0 represents channel 0, bit 1 represents channel 1... + * @param[in] u32ZeroLevel output level at zero point, valid values are: + * - \ref PWM_OUTPUT_NOTHING + * - \ref PWM_OUTPUT_LOW + * - \ref PWM_OUTPUT_HIGH + * - \ref PWM_OUTPUT_TOGGLE + * @param[in] u32CmpUpLevel output level at compare up point, valid values are: + * - \ref PWM_OUTPUT_NOTHING + * - \ref PWM_OUTPUT_LOW + * - \ref PWM_OUTPUT_HIGH + * - \ref PWM_OUTPUT_TOGGLE + * @param[in] u32PeriodLevel output level at period(center) point, valid values are: + * - \ref PWM_OUTPUT_NOTHING + * - \ref PWM_OUTPUT_LOW + * - \ref PWM_OUTPUT_HIGH + * - \ref PWM_OUTPUT_TOGGLE + * @param[in] u32CmpDownLevel output level at compare down point, valid values are: + * - \ref PWM_OUTPUT_NOTHING + * - \ref PWM_OUTPUT_LOW + * - \ref PWM_OUTPUT_HIGH + * - \ref PWM_OUTPUT_TOGGLE + * @return None + * @details This macro is used to Set output level at zero, compare up, period(center) and compare down of specified channel(s). + * \hideinitializer + */ +#define PWM_SET_OUTPUT_LEVEL(pwm, u32ChannelMask, u32ZeroLevel, u32CmpUpLevel, u32PeriodLevel, u32CmpDownLevel) \ + do{ \ + int i; \ + for(i = 0; i < 6; i++) { \ + if((u32ChannelMask) & (1 << i)) { \ + (pwm)->WGCTL0 = (((pwm)->WGCTL0 & ~(3UL << (i << 1))) | ((u32ZeroLevel) << (i << 1))); \ + (pwm)->WGCTL0 = (((pwm)->WGCTL0 & ~(3UL << (PWM_WGCTL0_PRDPCTL0_Pos + (i << 1)))) | ((u32PeriodLevel) << (PWM_WGCTL0_PRDPCTL0_Pos + (i << 1)))); \ + (pwm)->WGCTL1 = (((pwm)->WGCTL1 & ~(3UL << (i << 1))) | ((u32CmpUpLevel) << (i << 1))); \ + (pwm)->WGCTL1 = (((pwm)->WGCTL1 & ~(3UL << (PWM_WGCTL1_CMPDCTL0_Pos + (i << 1)))) | ((u32CmpDownLevel) << (PWM_WGCTL1_CMPDCTL0_Pos + (i << 1)))); \ + } \ + } \ + }while(0) + +/** + * @brief Trigger brake event from specified channel(s) + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Bit 0 represents channel 0, bit 1 represents channel 2 and bit 2 represents channel 4 + * @param[in] u32BrakeType Type of brake trigger. PWM_FB_EDGE of this macro is only supported in M45xD/M45xC. + * - \ref PWM_FB_EDGE + * - \ref PWM_FB_LEVEL + * @return None + * @details This macro is used to trigger brake event from specified channel(s). + * \hideinitializer + */ +#define PWM_TRIGGER_BRAKE(pwm, u32ChannelMask, u32BrakeType) ((pwm)->SWBRK |= ((u32ChannelMask) << (u32BrakeType))) + +/** + * @brief Set Dead zone clock source + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32AfterPrescaler Dead zone clock source is from prescaler output. Valid values are TRUE (after prescaler) or FALSE (before prescaler). + * @return None + * @details This macro is used to set Dead zone clock source. Every two channels share the same setting. + * @note The write-protection function should be disabled before using this function. + * @note This function is only supported in M45xD/M45xC. + * \hideinitializer + */ +#define PWM_SET_DEADZONE_CLK_SRC(pwm, u32ChannelNum, u32AfterPrescaler) \ + ((pwm)->DTCTL[(u32ChannelNum) >> 1] = (((pwm)->DTCTL[(u32ChannelNum) >> 1] & ~PWM_DTCTL0_1_DTCKSEL_Msk) | \ + ((u32AfterPrescaler) << PWM_DTCTL0_1_DTCKSEL_Pos))) + +/*---------------------------------------------------------------------------------------------------------*/ +/* Define PWM functions prototype */ +/*---------------------------------------------------------------------------------------------------------*/ +uint32_t PWM_ConfigCaptureChannel(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32UnitTimeNsec, uint32_t u32CaptureEdge); +uint32_t PWM_ConfigOutputChannel(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Frequency, uint32_t u32DutyCycle); +void PWM_Start(PWM_T *pwm, uint32_t u32ChannelMask); +void PWM_Stop(PWM_T *pwm, uint32_t u32ChannelMask); +void PWM_ForceStop(PWM_T *pwm, uint32_t u32ChannelMask); +void PWM_EnableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition); +void PWM_DisableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_ClearADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition); +uint32_t PWM_GetADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_EnableFaultBrake(PWM_T *pwm, uint32_t u32ChannelMask, uint32_t u32LevelMask, uint32_t u32BrakeSource); +void PWM_EnableCapture(PWM_T *pwm, uint32_t u32ChannelMask); +void PWM_DisableCapture(PWM_T *pwm, uint32_t u32ChannelMask); +void PWM_EnableOutput(PWM_T *pwm, uint32_t u32ChannelMask); +void PWM_DisableOutput(PWM_T *pwm, uint32_t u32ChannelMask); +void PWM_EnablePDMA(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32RisingFirst, uint32_t u32Mode); +void PWM_DisablePDMA(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_EnableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Duration); +void PWM_DisableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_EnableCaptureInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge); +void PWM_DisableCaptureInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge); +void PWM_ClearCaptureIntFlag(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge); +uint32_t PWM_GetCaptureIntFlag(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_EnableDutyInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType); +void PWM_DisableDutyInt(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_ClearDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum); +uint32_t PWM_GetDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_EnableFaultBrakeInt(PWM_T *pwm, uint32_t u32BrakeSource); +void PWM_DisableFaultBrakeInt(PWM_T *pwm, uint32_t u32BrakeSource); +void PWM_ClearFaultBrakeIntFlag(PWM_T *pwm, uint32_t u32BrakeSource); +uint32_t PWM_GetFaultBrakeIntFlag(PWM_T *pwm, uint32_t u32BrakeSource); +void PWM_EnablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType); +void PWM_DisablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_ClearPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum); +uint32_t PWM_GetPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_EnableZeroInt(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_DisableZeroInt(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_ClearZeroIntFlag(PWM_T *pwm, uint32_t u32ChannelNum); +uint32_t PWM_GetZeroIntFlag(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_EnableLoadMode(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32LoadMode); +void PWM_DisableLoadMode(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32LoadMode); +void PWM_SetClockSource(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32ClkSrcSel); +void PWM_EnableBrakeNoiseFilter(PWM_T *pwm, uint32_t u32BrakePinNum, uint32_t u32ClkCnt, uint32_t u32ClkDivSel); +void PWM_DisableBrakeNoiseFilter(PWM_T *pwm, uint32_t u32BrakePinNum); +void PWM_EnableBrakePinInverse(PWM_T *pwm, uint32_t u32BrakePinNum); +void PWM_DisableBrakePinInverse(PWM_T *pwm, uint32_t u32BrakePinNum); +void PWM_SetBrakePinSource(PWM_T *pwm, uint32_t u32BrakePinNum, uint32_t u32SelAnotherModule); +uint32_t PWM_GetWrapAroundFlag(PWM_T *pwm, uint32_t u32ChannelNum); +void PWM_ClearWrapAroundFlag(PWM_T *pwm, uint32_t u32ChannelNum); + +/*@}*/ /* end of group PWM_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group PWM_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_PWM_H__ + +/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_qspi.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_qspi.h new file mode 100644 index 0000000000..63bdeb9f27 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_qspi.h @@ -0,0 +1,412 @@ +/**************************************************************************//** + * @file nu_qspi.h + * @version V1.00 + * @brief M031 series QSPI driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#ifndef __NU_QSPI_H__ +#define __NU_QSPI_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup QSPI_Driver QSPI Driver + @{ +*/ + +/** @addtogroup QSPI_EXPORTED_CONSTANTS QSPI Exported Constants + @{ +*/ + +#define QSPI_MODE_0 (QSPI_CTL_TXNEG_Msk) /*!< CLKPOL=0; RXNEG=0; TXNEG=1 \hideinitializer */ +#define QSPI_MODE_1 (QSPI_CTL_RXNEG_Msk) /*!< CLKPOL=0; RXNEG=1; TXNEG=0 \hideinitializer */ +#define QSPI_MODE_2 (QSPI_CTL_CLKPOL_Msk | QSPI_CTL_RXNEG_Msk) /*!< CLKPOL=1; RXNEG=1; TXNEG=0 \hideinitializer */ +#define QSPI_MODE_3 (QSPI_CTL_CLKPOL_Msk | QSPI_CTL_TXNEG_Msk) /*!< CLKPOL=1; RXNEG=0; TXNEG=1 \hideinitializer */ + +#define QSPI_SLAVE (QSPI_CTL_SLAVE_Msk) /*!< Set as slave \hideinitializer */ +#define QSPI_MASTER (0x0UL) /*!< Set as master \hideinitializer */ + +#define QSPI_SS (QSPI_SSCTL_SS_Msk) /*!< Set SS \hideinitializer */ +#define QSPI_SS_ACTIVE_HIGH (QSPI_SSCTL_SSACTPOL_Msk) /*!< SS active high \hideinitializer */ +#define QSPI_SS_ACTIVE_LOW (0x0UL) /*!< SS active low \hideinitializer */ + +/* QSPI Interrupt Mask */ +#define QSPI_UNIT_INT_MASK (0x001UL) /*!< Unit transfer interrupt mask \hideinitializer */ +#define QSPI_SSACT_INT_MASK (0x002UL) /*!< Slave selection signal active interrupt mask \hideinitializer */ +#define QSPI_SSINACT_INT_MASK (0x004UL) /*!< Slave selection signal inactive interrupt mask \hideinitializer */ +#define QSPI_SLVUR_INT_MASK (0x008UL) /*!< Slave under run interrupt mask \hideinitializer */ +#define QSPI_SLVBE_INT_MASK (0x010UL) /*!< Slave bit count error interrupt mask \hideinitializer */ +#define QSPI_SLVTO_INT_MASK (0x020UL) /*!< Slave Mode Time-out interrupt mask \hideinitializer */ +#define QSPI_TXUF_INT_MASK (0x040UL) /*!< Slave TX underflow interrupt mask \hideinitializer */ +#define QSPI_FIFO_TXTH_INT_MASK (0x080UL) /*!< FIFO TX threshold interrupt mask \hideinitializer */ +#define QSPI_FIFO_RXTH_INT_MASK (0x100UL) /*!< FIFO RX threshold interrupt mask \hideinitializer */ +#define QSPI_FIFO_RXOV_INT_MASK (0x200UL) /*!< FIFO RX overrun interrupt mask \hideinitializer */ +#define QSPI_FIFO_RXTO_INT_MASK (0x400UL) /*!< FIFO RX time-out interrupt mask \hideinitializer */ + +/* QSPI Status Mask */ +#define QSPI_BUSY_MASK (0x01UL) /*!< Busy status mask \hideinitializer */ +#define QSPI_RX_EMPTY_MASK (0x02UL) /*!< RX empty status mask \hideinitializer */ +#define QSPI_RX_FULL_MASK (0x04UL) /*!< RX full status mask \hideinitializer */ +#define QSPI_TX_EMPTY_MASK (0x08UL) /*!< TX empty status mask \hideinitializer */ +#define QSPI_TX_FULL_MASK (0x10UL) /*!< TX full status mask \hideinitializer */ +#define QSPI_TXRX_RESET_MASK (0x20UL) /*!< TX or RX reset status mask \hideinitializer */ +#define QSPI_SPIEN_STS_MASK (0x40UL) /*!< SPIEN status mask \hideinitializer */ +#define QSPI_SSLINE_STS_MASK (0x80UL) /*!< QSPIx_SS line status mask \hideinitializer */ + +/*@}*/ /* end of group QSPI_EXPORTED_CONSTANTS */ + + +/** @addtogroup QSPI_EXPORTED_FUNCTIONS QSPI Exported Functions + @{ +*/ + +/** + * @brief Clear the unit transfer interrupt flag. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Write 1 to UNITIF bit of QSPI_STATUS register to clear the unit transfer interrupt flag. + * \hideinitializer + */ +#define QSPI_CLR_UNIT_TRANS_INT_FLAG(qspi) ((qspi)->STATUS = QSPI_STATUS_UNITIF_Msk) + +/** + * @brief Trigger RX PDMA function. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Set RXPDMAEN bit of QSPI_PDMACTL register to enable RX PDMA transfer function. + * \hideinitializer + */ +#define QSPI_TRIGGER_RX_PDMA(qspi) ((qspi)->PDMACTL |= QSPI_PDMACTL_RXPDMAEN_Msk) + +/** + * @brief Trigger TX PDMA function. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Set TXPDMAEN bit of QSPI_PDMACTL register to enable TX PDMA transfer function. + * \hideinitializer + */ +#define QSPI_TRIGGER_TX_PDMA(qspi) ((qspi)->PDMACTL |= QSPI_PDMACTL_TXPDMAEN_Msk) + +/** + * @brief Trigger TX and RX PDMA function. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Set TXPDMAEN bit and RXPDMAEN bit of QSPI_PDMACTL register to enable TX and RX PDMA transfer function. + * \hideinitializer + */ +#define QSPI_TRIGGER_TX_RX_PDMA(qspi) ((qspi)->PDMACTL |= (QSPI_PDMACTL_TXPDMAEN_Msk | QSPI_PDMACTL_RXPDMAEN_Msk)) + +/** + * @brief Disable RX PDMA transfer. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Clear RXPDMAEN bit of QSPI_PDMACTL register to disable RX PDMA transfer function. + * \hideinitializer + */ +#define QSPI_DISABLE_RX_PDMA(qspi) ( (qspi)->PDMACTL &= ~QSPI_PDMACTL_RXPDMAEN_Msk ) + +/** + * @brief Disable TX PDMA transfer. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Clear TXPDMAEN bit of QSPI_PDMACTL register to disable TX PDMA transfer function. + * \hideinitializer + */ +#define QSPI_DISABLE_TX_PDMA(qspi) ( (qspi)->PDMACTL &= ~QSPI_PDMACTL_TXPDMAEN_Msk ) + +/** + * @brief Disable TX and RX PDMA transfer. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Clear TXPDMAEN bit and RXPDMAEN bit of QSPI_PDMACTL register to disable TX and RX PDMA transfer function. + * \hideinitializer + */ +#define QSPI_DISABLE_TX_RX_PDMA(qspi) ( (qspi)->PDMACTL &= ~(QSPI_PDMACTL_TXPDMAEN_Msk | QSPI_PDMACTL_RXPDMAEN_Msk) ) + +/** + * @brief Get the count of available data in RX FIFO. + * @param[in] qspi The pointer of the specified QSPI module. + * @return The count of available data in RX FIFO. + * @details Read RXCNT (QSPI_STATUS[27:24]) to get the count of available data in RX FIFO. + * \hideinitializer + */ +#define QSPI_GET_RX_FIFO_COUNT(qspi) (((qspi)->STATUS & QSPI_STATUS_RXCNT_Msk) >> QSPI_STATUS_RXCNT_Pos) + +/** + * @brief Get the RX FIFO empty flag. + * @param[in] qspi The pointer of the specified QSPI module. + * @retval 0 RX FIFO is not empty. + * @retval 1 RX FIFO is empty. + * @details Read RXEMPTY bit of QSPI_STATUS register to get the RX FIFO empty flag. + * \hideinitializer + */ +#define QSPI_GET_RX_FIFO_EMPTY_FLAG(qspi) (((qspi)->STATUS & QSPI_STATUS_RXEMPTY_Msk)>>QSPI_STATUS_RXEMPTY_Pos) + +/** + * @brief Get the TX FIFO empty flag. + * @param[in] qspi The pointer of the specified QSPI module. + * @retval 0 TX FIFO is not empty. + * @retval 1 TX FIFO is empty. + * @details Read TXEMPTY bit of QSPI_STATUS register to get the TX FIFO empty flag. + * \hideinitializer + */ +#define QSPI_GET_TX_FIFO_EMPTY_FLAG(qspi) (((qspi)->STATUS & QSPI_STATUS_TXEMPTY_Msk)>>QSPI_STATUS_TXEMPTY_Pos) + +/** + * @brief Get the TX FIFO full flag. + * @param[in] qspi The pointer of the specified QSPI module. + * @retval 0 TX FIFO is not full. + * @retval 1 TX FIFO is full. + * @details Read TXFULL bit of QSPI_STATUS register to get the TX FIFO full flag. + * \hideinitializer + */ +#define QSPI_GET_TX_FIFO_FULL_FLAG(qspi) (((qspi)->STATUS & QSPI_STATUS_TXFULL_Msk)>>QSPI_STATUS_TXFULL_Pos) + +/** + * @brief Get the datum read from RX register. + * @param[in] qspi The pointer of the specified QSPI module. + * @return Data in RX register. + * @details Read QSPI_RX register to get the received datum. + * \hideinitializer + */ +#define QSPI_READ_RX(qspi) ((qspi)->RX) + +/** + * @brief Write datum to TX register. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32TxData The datum which user attempt to transfer through QSPI bus. + * @return None. + * @details Write u32TxData to QSPI_TX register. + * \hideinitializer + */ +#define QSPI_WRITE_TX(qspi, u32TxData) ((qspi)->TX = (u32TxData)) + +/** + * @brief Set QSPIx_SS pin to high state. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Disable automatic slave selection function and set QSPIx_SS pin to high state. + * \hideinitializer + */ +#define QSPI_SET_SS_HIGH(qspi) ((qspi)->SSCTL = ((qspi)->SSCTL & (~QSPI_SSCTL_AUTOSS_Msk)) | (QSPI_SSCTL_SSACTPOL_Msk | QSPI_SSCTL_SS_Msk)) + +/** + * @brief Set QSPIx_SS pin to low state. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Disable automatic slave selection function and set QSPIx_SS pin to low state. + * \hideinitializer + */ +#define QSPI_SET_SS_LOW(qspi) ((qspi)->SSCTL = ((qspi)->SSCTL & (~(QSPI_SSCTL_AUTOSS_Msk | QSPI_SSCTL_SSACTPOL_Msk))) | QSPI_SSCTL_SS_Msk) + +/** + * @brief Enable Byte Reorder function. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Enable Byte Reorder function. The suspend interval depends on the setting of SUSPITV (QSPI_CTL[7:4]). + * \hideinitializer + */ +#define QSPI_ENABLE_BYTE_REORDER(qspi) ((qspi)->CTL |= QSPI_CTL_REORDER_Msk) + +/** + * @brief Disable Byte Reorder function. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Clear REORDER bit field of QSPI_CTL register to disable Byte Reorder function. + * \hideinitializer + */ +#define QSPI_DISABLE_BYTE_REORDER(qspi) ((qspi)->CTL &= ~QSPI_CTL_REORDER_Msk) + +/** + * @brief Set the length of suspend interval. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32SuspCycle Decides the length of suspend interval. It could be 0 ~ 15. + * @return None. + * @details Set the length of suspend interval according to u32SuspCycle. + * The length of suspend interval is ((u32SuspCycle + 0.5) * the length of one QSPI bus clock cycle). + * \hideinitializer + */ +#define QSPI_SET_SUSPEND_CYCLE(qspi, u32SuspCycle) ((qspi)->CTL = ((qspi)->CTL & ~QSPI_CTL_SUSPITV_Msk) | ((u32SuspCycle) << QSPI_CTL_SUSPITV_Pos)) + +/** + * @brief Set the QSPI transfer sequence with LSB first. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Set LSB bit of QSPI_CTL register to set the QSPI transfer sequence with LSB first. + * \hideinitializer + */ +#define QSPI_SET_LSB_FIRST(qspi) ((qspi)->CTL |= QSPI_CTL_LSB_Msk) + +/** + * @brief Set the QSPI transfer sequence with MSB first. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Clear LSB bit of QSPI_CTL register to set the QSPI transfer sequence with MSB first. + * \hideinitializer + */ +#define QSPI_SET_MSB_FIRST(qspi) ((qspi)->CTL &= ~QSPI_CTL_LSB_Msk) + +/** + * @brief Set the data width of a QSPI transaction. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32Width The bit width of one transaction. + * @return None. + * @details The data width can be 8 ~ 32 bits. + * \hideinitializer + */ +#define QSPI_SET_DATA_WIDTH(qspi, u32Width) ((qspi)->CTL = ((qspi)->CTL & ~QSPI_CTL_DWIDTH_Msk) | (((u32Width)&0x1F) << QSPI_CTL_DWIDTH_Pos)) + +/** + * @brief Get the QSPI busy state. + * @param[in] qspi The pointer of the specified QSPI module. + * @retval 0 QSPI controller is not busy. + * @retval 1 QSPI controller is busy. + * @details This macro will return the busy state of QSPI controller. + * \hideinitializer + */ +#define QSPI_IS_BUSY(qspi) ( ((qspi)->STATUS & QSPI_STATUS_BUSY_Msk)>>QSPI_STATUS_BUSY_Pos ) + +/** + * @brief Enable QSPI controller. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Set SPIEN (QSPI_CTL[0]) to enable QSPI controller. + * \hideinitializer + */ +#define QSPI_ENABLE(qspi) ((qspi)->CTL |= QSPI_CTL_SPIEN_Msk) + +/** + * @brief Disable QSPI controller. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Clear SPIEN (QSPI_CTL[0]) to disable QSPI controller. + * \hideinitializer + */ +#define QSPI_DISABLE(qspi) ((qspi)->CTL &= ~QSPI_CTL_SPIEN_Msk) + +/** + * @brief Disable 2-bit Transfer mode. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Clear TWOBIT bit of QSPI_CTL register to disable 2-bit Transfer mode. + * \hideinitializer + */ +#define QSPI_DISABLE_2BIT_MODE(qspi) ( (qspi)->CTL &= ~QSPI_CTL_TWOBIT_Msk ) + +/** + * @brief Enable 2-bit Transfer mode. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Set TWOBIT bit of QSPI_CTL register to enable 2-bit Transfer mode. + * \hideinitializer + */ +#define QSPI_ENABLE_2BIT_MODE(qspi) ( (qspi)->CTL |= QSPI_CTL_TWOBIT_Msk ) + +/** + * @brief Disable Slave 3-wire mode. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Clear SLV3WIRE bit of QSPI_SSCTL register to disable Slave 3-wire mode. + * \hideinitializer + */ +#define QSPI_DISABLE_3WIRE_MODE(qspi) ( (qspi)->SSCTL &= ~QSPI_SSCTL_SLV3WIRE_Msk ) + +/** + * @brief Enable Slave 3-wire mode. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None. + * @details Set SLV3WIRE bit of QSPI_SSCTL register to enable Slave 3-wire mode. + * \hideinitializer + */ +#define QSPI_ENABLE_3WIRE_MODE(qspi) ( (qspi)->SSCTL |= QSPI_SSCTL_SLV3WIRE_Msk ) + +/** + * @brief Disable QSPI Dual IO function. + * @param[in] qspi is the base address of QSPI module. + * @return none + * \hideinitializer + */ +#define QSPI_DISABLE_DUAL_MODE(qspi) ( (qspi)->CTL &= ~QSPI_CTL_DUALIOEN_Msk ) + +/** + * @brief Enable Dual IO function and set QSPI Dual IO direction to input. + * @param[in] qspi is the base address of QSPI module. + * @return none + * \hideinitializer + */ +#define QSPI_ENABLE_DUAL_INPUT_MODE(qspi) ( (qspi)->CTL = ((qspi)->CTL & ~QSPI_CTL_DATDIR_Msk) | QSPI_CTL_DUALIOEN_Msk ) + +/** + * @brief Enable Dual IO function and set QSPI Dual IO direction to output. + * @param[in] qspi is the base address of QSPI module. + * @return none + * \hideinitializer + */ +#define QSPI_ENABLE_DUAL_OUTPUT_MODE(qspi) ( (qspi)->CTL |= QSPI_CTL_DATDIR_Msk | QSPI_CTL_DUALIOEN_Msk ) + +/** + * @brief Disable QSPI Quad IO function. + * @param[in] qspi is the base address of QSPI module. + * @return none + * \hideinitializer + */ +#define QSPI_DISABLE_QUAD_MODE(qspi) ( (qspi)->CTL &= ~QSPI_CTL_QUADIOEN_Msk ) + +/** + * @brief Set QSPI Quad IO direction to input. + * @param[in] qspi is the base address of QSPI module. + * @return none + * \hideinitializer + */ +#define QSPI_ENABLE_QUAD_INPUT_MODE(qspi) ( (qspi)->CTL = ((qspi)->CTL & ~QSPI_CTL_DATDIR_Msk) | QSPI_CTL_QUADIOEN_Msk ) + +/** + * @brief Set QSPI Quad IO direction to output. + * @param[in] qspi is the base address of QSPI module. + * @return none + * \hideinitializer + */ +#define QSPI_ENABLE_QUAD_OUTPUT_MODE(qspi) ( (qspi)->CTL |= QSPI_CTL_DATDIR_Msk | QSPI_CTL_QUADIOEN_Msk ) + + + + +/* Function prototype declaration */ +uint32_t QSPI_Open(QSPI_T *qspi, uint32_t u32MasterSlave, uint32_t u32QSPIMode, uint32_t u32DataWidth, uint32_t u32BusClock); +void QSPI_Close(QSPI_T *qspi); +void QSPI_ClearRxFIFO(QSPI_T *qspi); +void QSPI_ClearTxFIFO(QSPI_T *qspi); +void QSPI_DisableAutoSS(QSPI_T *qspi); +void QSPI_EnableAutoSS(QSPI_T *qspi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel); +uint32_t QSPI_SetBusClock(QSPI_T *qspi, uint32_t u32BusClock); +void QSPI_SetFIFO(QSPI_T *qspi, uint32_t u32TxThreshold, uint32_t u32RxThreshold); +uint32_t QSPI_GetBusClock(QSPI_T *qspi); +void QSPI_EnableInt(QSPI_T *qspi, uint32_t u32Mask); +void QSPI_DisableInt(QSPI_T *qspi, uint32_t u32Mask); +uint32_t QSPI_GetIntFlag(QSPI_T *qspi, uint32_t u32Mask); +void QSPI_ClearIntFlag(QSPI_T *qspi, uint32_t u32Mask); +uint32_t QSPI_GetStatus(QSPI_T *qspi, uint32_t u32Mask); + + +/*@}*/ /* end of group QSPI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group QSPI_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_QSPI_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_rtc.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_rtc.h new file mode 100644 index 0000000000..fdebdeccb4 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_rtc.h @@ -0,0 +1,300 @@ +/****************************************************************************** + * @file nu_rtc.h + * @version V1.00 + * $Revision: 4 $ + * $Date: 18/06/07 2:32p $ + * @brief M031 series Real Time Clock(RTC) driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NU_RTC_H__ +#define __NU_RTC_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup RTC_Driver RTC Driver + @{ +*/ + +/** @addtogroup RTC_EXPORTED_CONSTANTS RTC Exported Constants + @{ +*/ +/*---------------------------------------------------------------------------------------------------------*/ +/* RTC Initial Keyword Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define RTC_INIT_KEY 0xA5EB1357UL /*!< RTC Initiation Key to make RTC leaving reset state \hideinitializer */ +#define RTC_WRITE_KEY 0x0000A965UL /*!< RTC Register Access Enable Key to enable RTC read/write accessible and kept 1024 RTC clock \hideinitializer */ +/*---------------------------------------------------------------------------------------------------------*/ +/* RTC Frequency Compensation Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define RTC_INTEGER_32752 (0x0ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32752HZ \hideinitializer */ +#define RTC_INTEGER_32753 (0x1ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32753HZ \hideinitializer */ +#define RTC_INTEGER_32754 (0x2ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32754HZ \hideinitializer */ +#define RTC_INTEGER_32755 (0x3ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32755HZ \hideinitializer */ +#define RTC_INTEGER_32756 (0x4ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32756HZ \hideinitializer */ +#define RTC_INTEGER_32757 (0x5ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32757HZ \hideinitializer */ +#define RTC_INTEGER_32758 (0x6ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32758HZ \hideinitializer */ +#define RTC_INTEGER_32759 (0x7ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32759HZ \hideinitializer */ +#define RTC_INTEGER_32760 (0x8ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32760HZ \hideinitializer */ +#define RTC_INTEGER_32761 (0x9ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32761HZ \hideinitializer */ +#define RTC_INTEGER_32762 (0xaul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32762HZ \hideinitializer */ +#define RTC_INTEGER_32763 (0xbul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32763HZ \hideinitializer */ +#define RTC_INTEGER_32764 (0xcul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32764HZ \hideinitializer */ +#define RTC_INTEGER_32765 (0xdul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32765HZ \hideinitializer */ +#define RTC_INTEGER_32766 (0xeul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32766HZ \hideinitializer */ +#define RTC_INTEGER_32767 (0xful << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32767HZ \hideinitializer */ +#define RTC_INTEGER_32768 (0x10ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32768HZ \hideinitializer */ +#define RTC_INTEGER_32769 (0x11ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32769HZ \hideinitializer */ +#define RTC_INTEGER_32770 (0x12ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32770HZ \hideinitializer */ +#define RTC_INTEGER_32771 (0x13ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32771HZ \hideinitializer */ +#define RTC_INTEGER_32772 (0x14ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32772HZ \hideinitializer */ +#define RTC_INTEGER_32773 (0x15ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32773HZ \hideinitializer */ +#define RTC_INTEGER_32774 (0x16ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32774HZ \hideinitializer */ +#define RTC_INTEGER_32775 (0x17ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32775HZ \hideinitializer */ +#define RTC_INTEGER_32776 (0x18ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32776HZ \hideinitializer */ +#define RTC_INTEGER_32777 (0x19ul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32777HZ \hideinitializer */ +#define RTC_INTEGER_32778 (0x1aul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32778HZ \hideinitializer */ +#define RTC_INTEGER_32779 (0x1bul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32779HZ \hideinitializer */ +#define RTC_INTEGER_32780 (0x1cul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32780HZ \hideinitializer */ +#define RTC_INTEGER_32781 (0x1dul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32781HZ \hideinitializer */ +#define RTC_INTEGER_32782 (0x1eul << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32782HZ \hideinitializer */ +#define RTC_INTEGER_32783 (0x1ful << RTC_FREQADJ_INTEGER_Pos ) /*!< RTC Frequency is 32783HZ \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* RTC Time Attribute Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define RTC_CLOCK_12 0UL /*!< RTC as 12-hour time scale with AM and PM indication \hideinitializer */ +#define RTC_CLOCK_24 1UL /*!< RTC as 24-hour time scale \hideinitializer */ +#define RTC_AM 1UL /*!< RTC as AM indication \hideinitializer */ +#define RTC_PM 2UL /*!< RTC as PM indication \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* RTC Tick Period Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define RTC_TICK_1_SEC 0x0UL /*!< RTC time tick period is 1 second \hideinitializer */ +#define RTC_TICK_1_2_SEC 0x1UL /*!< RTC time tick period is 1/2 second \hideinitializer */ +#define RTC_TICK_1_4_SEC 0x2UL /*!< RTC time tick period is 1/4 second \hideinitializer */ +#define RTC_TICK_1_8_SEC 0x3UL /*!< RTC time tick period is 1/8 second \hideinitializer */ +#define RTC_TICK_1_16_SEC 0x4UL /*!< RTC time tick period is 1/16 second \hideinitializer */ +#define RTC_TICK_1_32_SEC 0x5UL /*!< RTC time tick period is 1/32 second \hideinitializer */ +#define RTC_TICK_1_64_SEC 0x6UL /*!< RTC time tick period is 1/64 second \hideinitializer */ +#define RTC_TICK_1_128_SEC 0x7UL /*!< RTC time tick period is 1/128 second \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* RTC Day of Week Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define RTC_SUNDAY 0x0UL /*!< Day of the Week is Sunday \hideinitializer */ +#define RTC_MONDAY 0x1UL /*!< Day of the Week is Monday \hideinitializer */ +#define RTC_TUESDAY 0x2UL /*!< Day of the Week is Tuesday \hideinitializer */ +#define RTC_WEDNESDAY 0x3UL /*!< Day of the Week is Wednesday \hideinitializer */ +#define RTC_THURSDAY 0x4UL /*!< Day of the Week is Thursday \hideinitializer */ +#define RTC_FRIDAY 0x5UL /*!< Day of the Week is Friday \hideinitializer */ +#define RTC_SATURDAY 0x6UL /*!< Day of the Week is Saturday \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* RTC Miscellaneous Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define RTC_YEAR2000 2000UL /*!< RTC Reference for compute year data \hideinitializer */ +#define RTC_FCR_REFERENCE 32761UL /*!< RTC Reference for frequency compensation \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* RTC Clock Source Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define RTC_CLKSRC_LXT 0x0UL /*!< Clock Source from LXT \hideinitializer */ +#define RTC_CLKSRC_LIRC 0x1UL /*!< Clock Source from LIRC \hideinitializer */ + +/*@}*/ /* end of group RTC_EXPORTED_CONSTANTS */ + + +/** @addtogroup RTC_EXPORTED_STRUCTS RTC Exported Structs + @{ +*/ +/** + * @details RTC define Time Data Struct + */ +typedef struct +{ + uint32_t u32Year; /*!< Year value */ + uint32_t u32Month; /*!< Month value */ + uint32_t u32Day; /*!< Day value */ + uint32_t u32DayOfWeek; /*!< Day of week value */ + uint32_t u32Hour; /*!< Hour value */ + uint32_t u32Minute; /*!< Minute value */ + uint32_t u32Second; /*!< Second value */ + uint32_t u32TimeScale; /*!< 12-Hour, 24-Hour */ + uint32_t u32AmPm; /*!< Only Time Scale select 12-hr used */ +} S_RTC_TIME_DATA_T; + +/*@}*/ /* end of group RTC_EXPORTED_STRUCTS */ + + +/** @addtogroup RTC_EXPORTED_FUNCTIONS RTC Exported Functions + @{ +*/ + +/** + * @brief Indicate is Leap Year or not + * + * @param None + * + * @retval 0 This year is not a leap year + * @retval 1 This year is a leap year + * + * @details According to current date, return this year is leap year or not. + * \hideinitializer + */ +#define RTC_IS_LEAP_YEAR() (RTC->LEAPYEAR & RTC_LEAPYEAR_LEAPYEAR_Msk ? 1:0) + +/** + * @brief Clear RTC Alarm Interrupt Flag + * + * @param None + * + * @return None + * + * @details This macro is used to clear RTC alarm interrupt flag. + * \hideinitializer + */ +#define RTC_CLEAR_ALARM_INT_FLAG() (RTC->INTSTS = RTC_INTSTS_ALMIF_Msk) + +/** + * @brief Clear RTC Tick Interrupt Flag + * + * @param None + * + * @return None + * + * @details This macro is used to clear RTC tick interrupt flag. + * \hideinitializer + */ +#define RTC_CLEAR_TICK_INT_FLAG() (RTC->INTSTS = RTC_INTSTS_TICKIF_Msk) + +/** + * @brief Get RTC Alarm Interrupt Flag + * + * @param None + * + * @retval 0 RTC alarm interrupt did not occur + * @retval 1 RTC alarm interrupt occurred + * + * @details This macro indicates RTC alarm interrupt occurred or not. + * \hideinitializer + */ +#define RTC_GET_ALARM_INT_FLAG() ((RTC->INTSTS & RTC_INTSTS_ALMIF_Msk)? 1:0) + +/** + * @brief Get RTC Time Tick Interrupt Flag + * + * @param None + * + * @retval 0 RTC time tick interrupt did not occur + * @retval 1 RTC time tick interrupt occurred + * + * @details This macro indicates RTC time tick interrupt occurred or not. + * \hideinitializer + */ +#define RTC_GET_TICK_INT_FLAG() ((RTC->INTSTS & RTC_INTSTS_TICKIF_Msk)? 1:0) + +/** + * @brief Enable RTC Tick Wake-up Function + * + * @param None + * + * @return None + * + * @details This macro is used to enable RTC tick interrupt wake-up function. + * \hideinitializer + */ +#define RTC_ENABLE_TICK_WAKEUP() ((RTC->INTEN |= RTC_INTEN_TICKIEN_Msk)) + +/** + * @brief Disable RTC Tick Wake-up Function + * + * @param None + * + * @return None + * + * @details This macro is used to disable RTC tick interrupt wake-up function. + * \hideinitializer + */ +#define RTC_DISABLE_TICK_WAKEUP() ((RTC->INTEN &= ~RTC_INTEN_TICKIEN_Msk)); + +/** + * @brief Enable RTC Alarm Wake-up Function + * + * @param None + * + * @return None + * + * @details This macro is used to enable RTC Alarm interrupt wake-up function. + * \hideinitializer + */ +#define RTC_ENABLE_ALARM_WAKEUP() ((RTC->INTEN |= RTC_INTEN_ALMIEN_Msk)) + +/** + * @brief Disable RTC Alarm Wake-up Function + * + * @param None + * + * @return None + * + * @details This macro is used to disable RTC Alarm interrupt wake-up function. + * \hideinitializer + */ +#define RTC_DISABLE_ALARM_WAKEUP() ((RTC->INTEN &= ~RTC_INTEN_ALMIEN_Msk)); + +/** + * @brief Select RTC Clock Source + * + * @param[in] u32ClkSrc Specify the clock source. It consists of: + * - \ref RTC_CLKSRC_LXT : Clock source from LXT + * - \ref RTC_CLKSRC_LIRC : Clock source from LIRC + * @return None + * + * @details This macro is used to select RTC clock source. + * \hideinitializer + */ +#define RTC_CLKSRCSEL(u32ClkSrc) ((RTC->LXTCTL &= ~RTC_LXTCTL_C32KS_Msk) | u32ClkSrc); + +void RTC_Open(S_RTC_TIME_DATA_T *psPt); +void RTC_Close(void); +void RTC_32KCalibration(int32_t i32FrequencyX10000); +void RTC_GetDateAndTime(S_RTC_TIME_DATA_T *psPt); +void RTC_GetAlarmDateAndTime(S_RTC_TIME_DATA_T *psPt); +void RTC_SetDateAndTime(S_RTC_TIME_DATA_T *psPt); +void RTC_SetAlarmDateAndTime(S_RTC_TIME_DATA_T *psPt); +void RTC_SetDate(uint32_t u32Year, uint32_t u32Month, uint32_t u32Day, uint32_t u32DayOfWeek); +void RTC_SetTime(uint32_t u32Hour, uint32_t u32Minute, uint32_t u32Second, uint32_t u32TimeMode, uint32_t u32AmPm); +void RTC_SetAlarmDate(uint32_t u32Year, uint32_t u32Month, uint32_t u32Day); +void RTC_SetAlarmTime(uint32_t u32Hour, uint32_t u32Minute, uint32_t u32Second, uint32_t u32TimeMode, uint32_t u32AmPm); +void RTC_SetAlarmDateMask(uint8_t u8IsTenYMsk, uint8_t u8IsYMsk, uint8_t u8IsTenMMsk, uint8_t u8IsMMsk, uint8_t u8IsTenDMsk, uint8_t u8IsDMsk); +void RTC_SetAlarmTimeMask(uint8_t u8IsTenHMsk, uint8_t u8IsHMsk, uint8_t u8IsTenMMsk, uint8_t u8IsMMsk, uint8_t u8IsTenSMsk, uint8_t u8IsSMsk); +uint32_t RTC_GetDayOfWeek(void); +void RTC_SetTickPeriod(uint32_t u32TickSelection); +void RTC_EnableInt(uint32_t u32IntFlagMask); +void RTC_DisableInt(uint32_t u32IntFlagMask); + +/*@}*/ /* end of group RTC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group RTC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_RTC_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_spi.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_spi.h new file mode 100644 index 0000000000..1d2b3da1ad --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_spi.h @@ -0,0 +1,558 @@ +/****************************************************************************** + * @file nu_spi.h + * @version V1.00 + * $Revision: 4 $ + * $Date: 18/06/07 2:32p $ + * @brief M031 series SPI driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#ifndef __NU_SPI_H__ +#define __NU_SPI_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup SPI_Driver SPI Driver + @{ +*/ + +/** @addtogroup SPI_EXPORTED_CONSTANTS SPI Exported Constants + @{ +*/ +#define SPI_NONE (0x00ul) /*!< SPI interface not existed \hideinitializer */ +#define SPI_MODE_0 (SPI_CTL_TXNEG_Msk) /*!< CLKPOL=0; RXNEG=0; TXNEG=1 \hideinitializer */ +#define SPI_MODE_1 (SPI_CTL_RXNEG_Msk) /*!< CLKPOL=0; RXNEG=1; TXNEG=0 \hideinitializer */ +#define SPI_MODE_2 (SPI_CTL_CLKPOL_Msk | SPI_CTL_RXNEG_Msk) /*!< CLKPOL=1; RXNEG=1; TXNEG=0 \hideinitializer */ +#define SPI_MODE_3 (SPI_CTL_CLKPOL_Msk | SPI_CTL_TXNEG_Msk) /*!< CLKPOL=1; RXNEG=0; TXNEG=1 \hideinitializer */ +#define SPI_SLAVE (SPI_CTL_SLAVE_Msk) /*!< Set as slave \hideinitializer */ +#define SPI_MASTER (0x0ul) /*!< Set as master \hideinitializer */ +#define SPI_SS (SPI_SSCTL_SS_Msk) /*!< Set SS \hideinitializer */ +#define SPI_SS_ACTIVE_HIGH (SPI_SSCTL_SSACTPOL_Msk) /*!< SS active high \hideinitializer */ +#define SPI_SS_ACTIVE_LOW (0x0ul) /*!< SS active low \hideinitializer */ + +/* SPI Interrupt Mask */ +#define SPI_UNIT_INT_MASK (0x001ul) /*!< Unit transfer interrupt mask \hideinitializer */ +#define SPI_SSACT_INT_MASK (0x002ul) /*!< Slave selection signal active interrupt mask \hideinitializer */ +#define SPI_SSINACT_INT_MASK (0x004ul) /*!< Slave selection signal inactive interrupt mask \hideinitializer */ +#define SPI_SLVUR_INT_MASK (0x008ul) /*!< Slave under run interrupt mask \hideinitializer */ +#define SPI_SLVBE_INT_MASK (0x010ul) /*!< Slave bit count error interrupt mask \hideinitializer */ +#define SPI_TXUF_INT_MASK (0x040ul) /*!< Slave TX underflow interrupt mask \hideinitializer */ +#define SPI_FIFO_TXTH_INT_MASK (0x080ul) /*!< FIFO TX threshold interrupt mask \hideinitializer */ +#define SPI_FIFO_RXTH_INT_MASK (0x100ul) /*!< FIFO RX threshold interrupt mask \hideinitializer */ +#define SPI_FIFO_RXOV_INT_MASK (0x200ul) /*!< FIFO RX overrun interrupt mask \hideinitializer */ +#define SPI_FIFO_RXTO_INT_MASK (0x400ul) /*!< FIFO RX time-out interrupt mask \hideinitializer */ + +/* SPI Status Mask */ +#define SPI_BUSY_MASK (0x01ul) /*!< Busy status mask \hideinitializer */ +#define SPI_RX_EMPTY_MASK (0x02ul) /*!< RX empty status mask \hideinitializer */ +#define SPI_RX_FULL_MASK (0x04ul) /*!< RX full status mask \hideinitializer */ +#define SPI_TX_EMPTY_MASK (0x08ul) /*!< TX empty status mask \hideinitializer */ +#define SPI_TX_FULL_MASK (0x10ul) /*!< TX full status mask \hideinitializer */ +#define SPI_TXRX_RESET_MASK (0x20ul) /*!< TX or RX reset status mask \hideinitializer */ +#define SPI_SPIEN_STS_MASK (0x40ul) /*!< SPIEN status mask \hideinitializer */ +#define SPI_SSLINE_STS_MASK (0x80ul) /*!< SPIx_SS line status mask \hideinitializer */ + + +/* SPII2S Data Width */ +#define SPII2S_DATABIT_8 (0ul << SPI_I2SCTL_WDWIDTH_Pos) /*!< SPII2S data width is 8-bit \hideinitializer */ +#define SPII2S_DATABIT_16 (1ul << SPI_I2SCTL_WDWIDTH_Pos) /*!< SPII2S data width is 16-bit \hideinitializer */ +#define SPII2S_DATABIT_24 (2ul << SPI_I2SCTL_WDWIDTH_Pos) /*!< SPII2S data width is 24-bit \hideinitializer */ +#define SPII2S_DATABIT_32 (3ul << SPI_I2SCTL_WDWIDTH_Pos) /*!< SPII2S data width is 32-bit \hideinitializer */ + +/* SPII2S Audio Format */ +#define SPII2S_MONO SPI_I2SCTL_MONO_Msk /*!< Monaural channel \hideinitializer */ +#define SPII2S_STEREO (0x0ul) /*!< Stereo channel \hideinitializer */ + +/* SPII2S Data Format */ +#define SPII2S_FORMAT_I2S (0ul<STATUS = SPI_STATUS_UNITIF_Msk) + +/** + * @brief Trigger RX PDMA function. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Set RXPDMAEN bit of SPI_PDMACTL register to enable RX PDMA transfer function. + */ +#define SPI_TRIGGER_RX_PDMA(spi) ((spi)->PDMACTL |= SPI_PDMACTL_RXPDMAEN_Msk) + +/** + * @brief Trigger TX PDMA function. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Set TXPDMAEN bit of SPI_PDMACTL register to enable TX PDMA transfer function. + */ +#define SPI_TRIGGER_TX_PDMA(spi) ((spi)->PDMACTL |= SPI_PDMACTL_TXPDMAEN_Msk) + +/** + * @brief Trigger TX and RX PDMA function. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Set TXPDMAEN bit and RXPDMAEN bit of SPI_PDMACTL register to enable TX and RX PDMA transfer function. + */ +#define SPI_TRIGGER_TX_RX_PDMA(spi) ( (spi)->PDMACTL |= (SPI_PDMACTL_TXPDMAEN_Msk | SPI_PDMACTL_RXPDMAEN_Msk) ) + +/** + * @brief Disable RX PDMA transfer. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Clear RXPDMAEN bit of SPI_PDMACTL register to disable RX PDMA transfer function. + */ +#define SPI_DISABLE_RX_PDMA(spi) ( (spi)->PDMACTL &= ~SPI_PDMACTL_RXPDMAEN_Msk ) + +/** + * @brief Disable TX PDMA transfer. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Clear TXPDMAEN bit of SPI_PDMACTL register to disable TX PDMA transfer function. + */ +#define SPI_DISABLE_TX_PDMA(spi) ( (spi)->PDMACTL &= ~SPI_PDMACTL_TXPDMAEN_Msk ) + +/** + * @brief Disable TX and RX PDMA transfer. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Clear TXPDMAEN bit and RXPDMAEN bit of SPI_PDMACTL register to disable TX and RX PDMA transfer function. + */ +#define SPI_DISABLE_TX_RX_PDMA(spi) ( (spi)->PDMACTL &= ~(SPI_PDMACTL_TXPDMAEN_Msk | SPI_PDMACTL_RXPDMAEN_Msk) ) + +/** + * @brief Get the count of available data in RX FIFO. + * @param[in] spi The pointer of the specified SPI module. + * @return The count of available data in RX FIFO. + * @details Read RXCNT (SPI_STATUS[27:24]) to get the count of available data in RX FIFO. + */ +#define SPI_GET_RX_FIFO_COUNT(spi) (((spi)->STATUS & SPI_STATUS_RXCNT_Msk) >> SPI_STATUS_RXCNT_Pos) + +/** + * @brief Get the RX FIFO empty flag. + * @param[in] spi The pointer of the specified SPI module. + * @retval 0 RX FIFO is not empty. + * @retval 1 RX FIFO is empty. + * @details Read RXEMPTY bit of SPI_STATUS register to get the RX FIFO empty flag. + */ +#define SPI_GET_RX_FIFO_EMPTY_FLAG(spi) (((spi)->STATUS & SPI_STATUS_RXEMPTY_Msk)>>SPI_STATUS_RXEMPTY_Pos) + +/** + * @brief Get the TX FIFO empty flag. + * @param[in] spi The pointer of the specified SPI module. + * @retval 0 TX FIFO is not empty. + * @retval 1 TX FIFO is empty. + * @details Read TXEMPTY bit of SPI_STATUS register to get the TX FIFO empty flag. + */ +#define SPI_GET_TX_FIFO_EMPTY_FLAG(spi) (((spi)->STATUS & SPI_STATUS_TXEMPTY_Msk)>>SPI_STATUS_TXEMPTY_Pos) + +/** + * @brief Get the TX FIFO full flag. + * @param[in] spi The pointer of the specified SPI module. + * @retval 0 TX FIFO is not full. + * @retval 1 TX FIFO is full. + * @details Read TXFULL bit of SPI_STATUS register to get the TX FIFO full flag. + */ +#define SPI_GET_TX_FIFO_FULL_FLAG(spi) (((spi)->STATUS & SPI_STATUS_TXFULL_Msk)>>SPI_STATUS_TXFULL_Pos) + +/** + * @brief Get the datum read from RX register. + * @param[in] spi The pointer of the specified SPI module. + * @return Data in RX register. + * @details Read SPI_RX register to get the received datum. + */ +#define SPI_READ_RX(spi) ((spi)->RX) + +/** + * @brief Write datum to TX register. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32TxData The datum which user attempt to transfer through SPI bus. + * @return None. + * @details Write u32TxData to SPI_TX register. + */ +#define SPI_WRITE_TX(spi, u32TxData) ((spi)->TX = (u32TxData)) + +/** + * @brief Set SPIx_SS pin to high state. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Disable automatic slave selection function and set SPIx_SS pin to high state. + */ +#define SPI_SET_SS_HIGH(spi) ((spi)->SSCTL = ((spi)->SSCTL & (~SPI_SSCTL_AUTOSS_Msk)) | (SPI_SSCTL_SSACTPOL_Msk | SPI_SSCTL_SS_Msk)) + +/** + * @brief Set SPIx_SS pin to low state. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Disable automatic slave selection function and set SPIx_SS pin to low state. + */ +#define SPI_SET_SS_LOW(spi) ((spi)->SSCTL = ((spi)->SSCTL & (~(SPI_SSCTL_AUTOSS_Msk | SPI_SSCTL_SSACTPOL_Msk))) | SPI_SSCTL_SS_Msk) + +/** + * @brief Enable Byte Reorder function. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Enable Byte Reorder function. The suspend interval depends on the setting of SUSPITV (SPI_CTL[7:4]). + */ +#define SPI_ENABLE_BYTE_REORDER(spi) ((spi)->CTL |= SPI_CTL_REORDER_Msk) + +/** + * @brief Disable Byte Reorder function. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Clear REORDER bit field of SPI_CTL register to disable Byte Reorder function. + */ +#define SPI_DISABLE_BYTE_REORDER(spi) ((spi)->CTL &= ~SPI_CTL_REORDER_Msk) + +/** + * @brief Set the length of suspend interval. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32SuspCycle Decides the length of suspend interval. It could be 0 ~ 15. + * @return None. + * @details Set the length of suspend interval according to u32SuspCycle. + * The length of suspend interval is ((u32SuspCycle + 0.5) * the length of one SPI bus clock cycle). + */ +#define SPI_SET_SUSPEND_CYCLE(spi, u32SuspCycle) ((spi)->CTL = ((spi)->CTL & ~SPI_CTL_SUSPITV_Msk) | ((u32SuspCycle) << SPI_CTL_SUSPITV_Pos)) + +/** + * @brief Set the SPI transfer sequence with LSB first. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Set LSB bit of SPI_CTL register to set the SPI transfer sequence with LSB first. + */ +#define SPI_SET_LSB_FIRST(spi) ((spi)->CTL |= SPI_CTL_LSB_Msk) + +/** + * @brief Set the SPI transfer sequence with MSB first. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Clear LSB bit of SPI_CTL register to set the SPI transfer sequence with MSB first. + */ +#define SPI_SET_MSB_FIRST(spi) ((spi)->CTL &= ~SPI_CTL_LSB_Msk) + +/** + * @brief Set the data width of a SPI transaction. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32Width The bit width of one transaction. + * @return None. + * @details The data width can be 8 ~ 32 bits. + */ +#define SPI_SET_DATA_WIDTH(spi, u32Width) ((spi)->CTL = ((spi)->CTL & ~SPI_CTL_DWIDTH_Msk) | (((u32Width)&0x1F) << SPI_CTL_DWIDTH_Pos)) + +/** + * @brief Get the SPI busy state. + * @param[in] spi The pointer of the specified SPI module. + * @retval 0 SPI controller is not busy. + * @retval 1 SPI controller is busy. + * @details This macro will return the busy state of SPI controller. + */ +#define SPI_IS_BUSY(spi) ( ((spi)->STATUS & SPI_STATUS_BUSY_Msk)>>SPI_STATUS_BUSY_Pos ) + +/** + * @brief Enable SPI controller. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Set SPIEN (SPI_CTL[0]) to enable SPI controller. + */ +#define SPI_ENABLE(spi) ((spi)->CTL |= SPI_CTL_SPIEN_Msk) + +/** + * @brief Disable SPI controller. + * @param[in] spi The pointer of the specified SPI module. + * @return None. + * @details Clear SPIEN (SPI_CTL[0]) to disable SPI controller. + */ +#define SPI_DISABLE(spi) ((spi)->CTL &= ~SPI_CTL_SPIEN_Msk) + + +/** + * @brief Enable zero cross detection function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @param[in] u32ChMask The mask for left or right channel. Valid values are: + * - \ref SPII2S_RIGHT + * - \ref SPII2S_LEFT + * @return None + * @details This function will set RZCEN or LZCEN bit of SPI_I2SCTL register to enable zero cross detection function. + */ +static __INLINE void SPII2S_ENABLE_TX_ZCD(SPI_T *i2s, uint32_t u32ChMask) +{ + if (u32ChMask == SPII2S_RIGHT) + i2s->I2SCTL |= SPI_I2SCTL_RZCEN_Msk; + else + i2s->I2SCTL |= SPI_I2SCTL_LZCEN_Msk; +} + +/** + * @brief Disable zero cross detection function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @param[in] u32ChMask The mask for left or right channel. Valid values are: + * - \ref SPII2S_RIGHT + * - \ref SPII2S_LEFT + * @return None + * @details This function will clear RZCEN or LZCEN bit of SPI_I2SCTL register to disable zero cross detection function. + */ +static __INLINE void SPII2S_DISABLE_TX_ZCD(SPI_T *i2s, uint32_t u32ChMask) +{ + if (u32ChMask == SPII2S_RIGHT) + i2s->I2SCTL &= ~SPI_I2SCTL_RZCEN_Msk; + else + i2s->I2SCTL &= ~SPI_I2SCTL_LZCEN_Msk; +} + +/** + * @brief Enable SPII2S TX DMA function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will set TXPDMAEN bit of SPI_PDMACTL register to transmit data with PDMA. + */ +#define SPII2S_ENABLE_TXDMA(i2s) ( (i2s)->PDMACTL |= SPI_PDMACTL_TXPDMAEN_Msk ) + +/** + * @brief Disable SPII2S TX DMA function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will clear TXPDMAEN bit of SPI_PDMACTL register to disable TX DMA function. + */ +#define SPII2S_DISABLE_TXDMA(i2s) ( (i2s)->PDMACTL &= ~SPI_PDMACTL_TXPDMAEN_Msk ) + +/** + * @brief Enable SPII2S RX DMA function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will set RXPDMAEN bit of SPI_PDMACTL register to receive data with PDMA. + */ +#define SPII2S_ENABLE_RXDMA(i2s) ( (i2s)->PDMACTL |= SPI_PDMACTL_RXPDMAEN_Msk ) + +/** + * @brief Disable SPII2S RX DMA function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will clear RXPDMAEN bit of SPI_PDMACTL register to disable RX DMA function. + */ +#define SPII2S_DISABLE_RXDMA(i2s) ( (i2s)->PDMACTL &= ~SPI_PDMACTL_RXPDMAEN_Msk ) + +/** + * @brief Enable SPII2S TX function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will set TXEN bit of SPI_I2SCTL register to enable SPII2S TX function. + */ +#define SPII2S_ENABLE_TX(i2s) ( (i2s)->I2SCTL |= SPI_I2SCTL_TXEN_Msk ) + +/** + * @brief Disable SPII2S TX function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will clear TXEN bit of SPI_I2SCTL register to disable SPII2S TX function. + */ +#define SPII2S_DISABLE_TX(i2s) ( (i2s)->I2SCTL &= ~SPI_I2SCTL_TXEN_Msk ) + +/** + * @brief Enable SPII2S RX function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will set RXEN bit of SPI_I2SCTL register to enable SPII2S RX function. + */ +#define SPII2S_ENABLE_RX(i2s) ( (i2s)->I2SCTL |= SPI_I2SCTL_RXEN_Msk ) + +/** + * @brief Disable SPII2S RX function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will clear RXEN bit of SPI_I2SCTL register to disable SPII2S RX function. + */ +#define SPII2S_DISABLE_RX(i2s) ( (i2s)->I2SCTL &= ~SPI_I2SCTL_RXEN_Msk ) + +/** + * @brief Enable TX Mute function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will set MUTE bit of SPI_I2SCTL register to enable SPII2S TX mute function. + */ +#define SPII2S_ENABLE_TX_MUTE(i2s) ( (i2s)->I2SCTL |= SPI_I2SCTL_MUTE_Msk ) + +/** + * @brief Disable TX Mute function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will clear MUTE bit of SPI_I2SCTL register to disable SPII2S TX mute function. + */ +#define SPII2S_DISABLE_TX_MUTE(i2s) ( (i2s)->I2SCTL &= ~SPI_I2SCTL_MUTE_Msk ) + +/** + * @brief Clear TX FIFO. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will clear TX FIFO. The internal TX FIFO pointer will be reset to FIFO start point. + */ +#define SPII2S_CLR_TX_FIFO(i2s) ( (i2s)->FIFOCTL |= SPI_FIFOCTL_TXFBCLR_Msk ) + +/** + * @brief Clear RX FIFO. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details This macro will clear RX FIFO. The internal RX FIFO pointer will be reset to FIFO start point. + */ +#define SPII2S_CLR_RX_FIFO(i2s) ( (i2s)->FIFOCTL |= SPI_FIFOCTL_RXFBCLR_Msk ) + +/** + * @brief This function sets the recording source channel when mono mode is used. + * @param[in] i2s The pointer of the specified SPII2S module. + * @param[in] u32Ch left or right channel. Valid values are: + * - \ref SPII2S_MONO_LEFT + * - \ref SPII2S_MONO_RIGHT + * @return None + * @details This function selects the recording source channel of monaural mode. + */ +static __INLINE void SPII2S_SET_MONO_RX_CHANNEL(SPI_T *i2s, uint32_t u32Ch) +{ + u32Ch == SPII2S_MONO_LEFT ? + (i2s->I2SCTL |= SPI_I2SCTL_RXLCH_Msk) : + (i2s->I2SCTL &= ~SPI_I2SCTL_RXLCH_Msk); +} + +/** + * @brief Write data to SPII2S TX FIFO. + * @param[in] i2s The pointer of the specified SPII2S module. + * @param[in] u32Data The value written to TX FIFO. + * @return None + * @details This macro will write a value to TX FIFO. + */ +#define SPII2S_WRITE_TX_FIFO(i2s, u32Data) ( (i2s)->TX = (u32Data) ) + +/** + * @brief Read RX FIFO. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return The value read from RX FIFO. + * @details This function will return a value read from RX FIFO. + */ +#define SPII2S_READ_RX_FIFO(i2s) ( (i2s)->RX ) + +/** + * @brief Get the interrupt flag. + * @param[in] i2s The pointer of the specified SPII2S module. + * @param[in] u32Mask The mask value for all interrupt flags. + * @return The interrupt flags specified by the u32mask parameter. + * @details This macro will return the combination interrupt flags of SPI_I2SSTS register. The flags are specified by the u32mask parameter. + */ +#define SPII2S_GET_INT_FLAG(i2s, u32Mask) ( (i2s)->I2SSTS & (u32Mask) ) + +/** + * @brief Clear the interrupt flag. + * @param[in] i2s The pointer of the specified SPII2S module. + * @param[in] u32Mask The mask value for all interrupt flags. + * @return None + * @details This macro will clear the interrupt flags specified by the u32mask parameter. + * @note Except TX and RX FIFO threshold interrupt flags, the other interrupt flags can be cleared by writing 1 to itself. + */ +#define SPII2S_CLR_INT_FLAG(i2s, u32Mask) ( (i2s)->I2SSTS = (u32Mask) ) + +/** + * @brief Get transmit FIFO level + * @param[in] i2s The pointer of the specified SPII2S module. + * @return TX FIFO level + * @details This macro will return the number of available words in TX FIFO. + */ +#define SPII2S_GET_TX_FIFO_LEVEL(i2s) ( ((i2s)->I2SSTS & SPI_I2SSTS_TXCNT_Msk) >> SPI_I2SSTS_TXCNT_Pos ) + +/** + * @brief Get receive FIFO level + * @param[in] i2s The pointer of the specified SPII2S module. + * @return RX FIFO level + * @details This macro will return the number of available words in RX FIFO. + */ +#define SPII2S_GET_RX_FIFO_LEVEL(i2s) ( ((i2s)->I2SSTS & SPI_I2SSTS_RXCNT_Msk) >> SPI_I2SSTS_RXCNT_Pos ) + + + +/* Function prototype declaration */ +uint32_t SPI_Open(SPI_T *spi, uint32_t u32MasterSlave, uint32_t u32SPIMode, uint32_t u32DataWidth, uint32_t u32BusClock); +void SPI_Close(SPI_T *spi); +void SPI_ClearRxFIFO(SPI_T *spi); +void SPI_ClearTxFIFO(SPI_T *spi); +void SPI_DisableAutoSS(SPI_T *spi); +void SPI_EnableAutoSS(SPI_T *spi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel); +uint32_t SPI_SetBusClock(SPI_T *spi, uint32_t u32BusClock); +void SPI_SetFIFO(SPI_T *spi, uint32_t u32TxThreshold, uint32_t u32RxThreshold); +uint32_t SPI_GetBusClock(SPI_T *spi); +void SPI_EnableInt(SPI_T *spi, uint32_t u32Mask); +void SPI_DisableInt(SPI_T *spi, uint32_t u32Mask); +uint32_t SPI_GetIntFlag(SPI_T *spi, uint32_t u32Mask); +void SPI_ClearIntFlag(SPI_T *spi, uint32_t u32Mask); +uint32_t SPI_GetStatus(SPI_T *spi, uint32_t u32Mask); + +uint32_t SPII2S_Open(SPI_T *i2s, uint32_t u32MasterSlave, uint32_t u32SampleRate, uint32_t u32WordWidth, uint32_t u32Channels, uint32_t u32DataFormat); +void SPII2S_Close(SPI_T *i2s); +void SPII2S_EnableInt(SPI_T *i2s, uint32_t u32Mask); +void SPII2S_DisableInt(SPI_T *i2s, uint32_t u32Mask); +uint32_t SPII2S_EnableMCLK(SPI_T *i2s, uint32_t u32BusClock); +void SPII2S_DisableMCLK(SPI_T *i2s); +void SPII2S_SetFIFO(SPI_T *i2s, uint32_t u32TxThreshold, uint32_t u32RxThreshold); + + +/*@}*/ /* end of group SPI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group SPI_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_SPI_H__ + +/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_sys.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_sys.h new file mode 100644 index 0000000000..e36ea74cc5 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_sys.h @@ -0,0 +1,1391 @@ +/**************************************************************************//** + * @file nu_sys.h + * @version V0.10 + * $Revision: 7 $ + * $Date: 19/06/10 2:48p $ + * @brief M031 Series SYS Driver Header File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_SYS_H__ +#define __NU_SYS_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup SYS_Driver SYS Driver + @{ +*/ + +/** @addtogroup SYS_EXPORTED_CONSTANTS SYS Exported Constants + @{ +*/ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Module Reset Control Resister constant definitions. */ +/*---------------------------------------------------------------------------------------------------------*/ +#define PDMA_RST ((0x0<<24)|SYS_IPRST0_PDMARST_Pos) /*!< PDMA reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define EBI_RST ((0x0<<24)|SYS_IPRST0_EBIRST_Pos) /*!< EBI reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define HDIV_RST ((0x0<<24)|SYS_IPRST0_HDIVRST_Pos) /*!< HDIV reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define CRC_RST ((0x0<<24)|SYS_IPRST0_CRCRST_Pos) /*!< CRC reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ + +#define GPIO_RST ((0x4<<24)|SYS_IPRST1_GPIORST_Pos) /*!< GPIO reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define TMR0_RST ((0x4<<24)|SYS_IPRST1_TMR0RST_Pos) /*!< TMR0 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define TMR1_RST ((0x4<<24)|SYS_IPRST1_TMR1RST_Pos) /*!< TMR1 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define TMR2_RST ((0x4<<24)|SYS_IPRST1_TMR2RST_Pos) /*!< TMR2 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define TMR3_RST ((0x4<<24)|SYS_IPRST1_TMR3RST_Pos) /*!< TMR3 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define ACMP01_RST ((0x4<<24)|SYS_IPRST1_ACMP01RST_Pos) /*!< ACMP reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define I2C0_RST ((0x4<<24)|SYS_IPRST1_I2C0RST_Pos) /*!< I2C0 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define I2C1_RST ((0x4<<24)|SYS_IPRST1_I2C1RST_Pos) /*!< I2C1 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define QSPI0_RST ((0x4<<24)|SYS_IPRST1_QSPI0RST_Pos) /*!< QSPI0 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define SPI0_RST ((0x4<<24)|SYS_IPRST1_SPI0RST_Pos) /*!< SPI0 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define UART0_RST ((0x4<<24)|SYS_IPRST1_UART0RST_Pos) /*!< UART0 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define UART1_RST ((0x4<<24)|SYS_IPRST1_UART1RST_Pos) /*!< UART1 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define UART2_RST ((0x4<<24)|SYS_IPRST1_UART2RST_Pos) /*!< UART2 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define UART3_RST ((0x4<<24)|SYS_IPRST1_UART3RST_Pos) /*!< UART3 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define UART4_RST ((0x4<<24)|SYS_IPRST1_UART4RST_Pos) /*!< UART4 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define UART5_RST ((0x4<<24)|SYS_IPRST1_UART5RST_Pos) /*!< UART5 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define UART6_RST ((0x4<<24)|SYS_IPRST1_UART6RST_Pos) /*!< UART6 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define UART7_RST ((0x4<<24)|SYS_IPRST1_UART7RST_Pos) /*!< UART7 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define USBD_RST ((0x4<<24)|SYS_IPRST1_USBDRST_Pos) /*!< USBD reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define ADC_RST ((0x4<<24)|SYS_IPRST1_ADCRST_Pos) /*!< ADC reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ + +#define USCI0_RST ((0x8<<24)|SYS_IPRST2_USCI0RST_Pos) /*!< USCI0 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define USCI1_RST ((0x8<<24)|SYS_IPRST2_USCI1RST_Pos) /*!< USCI1 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define PWM0_RST ((0x8<<24)|SYS_IPRST2_PWM0RST_Pos) /*!< PWM0 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define PWM1_RST ((0x8<<24)|SYS_IPRST2_PWM1RST_Pos) /*!< PWM1 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define BPWM0_RST ((0x8<<24)|SYS_IPRST2_BPWM0RST_Pos) /*!< BPWM0 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ +#define BPWM1_RST ((0x8<<24)|SYS_IPRST2_BPWM1RST_Pos) /*!< BPWM1 reset is one of the \ref SYS_ResetModule parameter \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Brown Out Detector Threshold Voltage Selection constant definitions. */ +/*---------------------------------------------------------------------------------------------------------*/ +#define SYS_BODCTL_BOD_RST_EN (1UL<GPD_MFPL = (SYS->GPD_MFPL & ~SYS_GPD_MFPL_PD2MFP_Msk) | SYS_GPD_MFPL_PD2MFP_UART0_RXD; + SYS->GPD_MFPL = (SYS->GPD_MFPL & ~SYS_GPD_MFPL_PD3MFP_Msk) | SYS_GPD_MFPL_PD3MFP_UART0_TXD; +*/ +/* PA.0 MFP */ +#define SYS_GPA_MFPL_PA0MFP_GPIO (0x00UL<BODCTL |= SYS_BODCTL_BODIF_Msk) + +/** + * @brief Set Brown-out detector function to normal mode + * @param None + * @return None + * @details This macro set Brown-out detector to normal mode. + * The register write-protection function should be disabled before using this macro. + * \hideinitializer + */ +#define SYS_CLEAR_BOD_LPM() (SYS->BODCTL &= ~SYS_BODCTL_BODLPM_Msk) + +/** + * @brief Disable Brown-out detector function + * @param None + * @return None + * @details This macro disable Brown-out detector function. + * The register write-protection function should be disabled before using this macro. + * \hideinitializer + */ +#define SYS_DISABLE_BOD() (SYS->BODCTL &= ~SYS_BODCTL_BODEN_Msk) + +/** + * @brief Enable Brown-out detector function + * @param None + * @return None + * @details This macro enable Brown-out detector function. + * The register write-protection function should be disabled before using this macro. + * \hideinitializer + */ +#define SYS_ENABLE_BOD() (SYS->BODCTL |= SYS_BODCTL_BODEN_Msk) + +/** + * @brief Get Brown-out detector interrupt flag + * @param None + * @retval 0 Brown-out detect interrupt flag is not set. + * @retval >=1 Brown-out detect interrupt flag is set. + * @details This macro get Brown-out detector interrupt flag. + * \hideinitializer + */ +#define SYS_GET_BOD_INT_FLAG() (SYS->BODCTL & SYS_BODCTL_BODIF_Msk) + +/** + * @brief Get Brown-out detector status + * @param None + * @retval 0 System voltage is higher than BOD threshold voltage setting or BOD function is disabled. + * @retval >=1 System voltage is lower than BOD threshold voltage setting. + * @details This macro get Brown-out detector output status. + * If the BOD function is disabled, this function always return 0. + * \hideinitializer + */ +#define SYS_GET_BOD_OUTPUT() (SYS->BODCTL & SYS_BODCTL_BODOUT_Msk) + +/** + * @brief Disable Brown-out detector reset function + * @param None + * @return None + * @details This macro disable Brown-out detector reset function. + * The register write-protection function should be disabled before using this macro. + * \hideinitializer + */ +#define SYS_DISABLE_BOD_RST() (SYS->BODCTL &= ~SYS_BODCTL_BODRSTEN_Msk) + +/** + * @brief Enable Brown-out detector reset function + * @param None + * @return None + * @details This macro enable Brown-out detect reset function. + * The register write-protection function should be disabled before using this macro. + * \hideinitializer + */ +#define SYS_ENABLE_BOD_RST() (SYS->BODCTL |= SYS_BODCTL_BODRSTEN_Msk) + +/** + * @brief Set Brown-out detector function low power mode + * @param None + * @return None + * @details This macro set Brown-out detector to low power mode. + * The register write-protection function should be disabled before using this macro. + * \hideinitializer + */ +#define SYS_SET_BOD_LPM() (SYS->BODCTL |= SYS_BODCTL_BODLPM_Msk) + +/** + * @brief Set Brown-out detector voltage level + * @param[in] u32Level is Brown-out voltage level. Including : + * - \ref SYS_BODCTL_BODVL_2_5V + * - \ref SYS_BODCTL_BODVL_2_0V + * @return None + * @details This macro set Brown-out detector voltage level. + * The write-protection function should be disabled before using this macro. + * \hideinitializer + */ +#define SYS_SET_BOD_LEVEL(u32Level) (SYS->BODCTL = (SYS->BODCTL & ~SYS_BODCTL_BODVL_Msk) | (u32Level)) + +/** + * @brief Get reset source is from Brown-out detector reset + * @param None + * @retval 0 Previous reset source is not from Brown-out detector reset + * @retval >=1 Previous reset source is from Brown-out detector reset + * @details This macro get previous reset source is from Brown-out detect reset or not. + * \hideinitializer + */ +#define SYS_IS_BOD_RST() (SYS->RSTSTS & SYS_RSTSTS_BODRF_Msk) + +/** + * @brief Get reset source is from CPU reset + * @param None + * @retval 0 Previous reset source is not from CPU reset + * @retval >=1 Previous reset source is from CPU reset + * @details This macro get previous reset source is from CPU reset. + * \hideinitializer + */ +#define SYS_IS_CPU_RST() (SYS->RSTSTS & SYS_RSTSTS_CPURF_Msk) + +/** + * @brief Get reset source is from LVR Reset + * @param None + * @retval 0 Previous reset source is not from Low-Voltage-Reset + * @retval >=1 Previous reset source is from Low-Voltage-Reset + * @details This macro get previous reset source is from Low-Voltage-Reset. + * \hideinitializer + */ +#define SYS_IS_LVR_RST() (SYS->RSTSTS & SYS_RSTSTS_LVRF_Msk) + +/** + * @brief Get reset source is from Power-on Reset + * @param None + * @retval 0 Previous reset source is not from Power-on Reset + * @retval >=1 Previous reset source is from Power-on Reset + * @details This macro get previous reset source is from Power-on Reset. + * \hideinitializer + */ +#define SYS_IS_POR_RST() (SYS->RSTSTS & SYS_RSTSTS_PORF_Msk) + +/** + * @brief Get reset source is from reset pin reset + * @param None + * @retval 0 Previous reset source is not from reset pin reset + * @retval >=1 Previous reset source is from reset pin reset + * @details This macro get previous reset source is from reset pin reset. + * \hideinitializer + */ +#define SYS_IS_RSTPIN_RST() (SYS->RSTSTS & SYS_RSTSTS_PINRF_Msk) + +/** + * @brief Get reset source is from system reset + * @param None + * @retval 0 Previous reset source is not from system reset + * @retval >=1 Previous reset source is from system reset + * @details This macro get previous reset source is from system reset. + * \hideinitializer + */ +#define SYS_IS_SYSTEM_RST() (SYS->RSTSTS & SYS_RSTSTS_SYSRF_Msk) + +/** + * @brief Get reset source is from watchdog timer or window watchdog timer reset + * @param None + * @retval 0 Previous reset source is not from watchdog timer or window watchdog timer reset + * @retval >=1 Previous reset source is from watchdog timer or window watchdog timer reset + * @details This macro get previous reset source is from watchdog timer or window watchdog timer reset. + * \hideinitializer + */ +#define SYS_IS_WDT_RST() (SYS->RSTSTS & SYS_RSTSTS_WDTRF_Msk) + +/** + * @brief Disable Low-Voltage-Reset function + * @param None + * @return None + * @details This macro disable Low-Voltage-Reset function. + * The register write-protection function should be disabled before using this macro. + * \hideinitializer + */ +#define SYS_DISABLE_LVR() (SYS->BODCTL &= ~SYS_BODCTL_LVREN_Msk) + +/** + * @brief Enable Low-Voltage-Reset function + * @param None + * @return None + * @details This macro enable Low-Voltage-Reset function. + * The register write-protection function should be disabled before using this macro. + * \hideinitializer + */ +#define SYS_ENABLE_LVR() (SYS->BODCTL |= SYS_BODCTL_LVREN_Msk) + +/** + * @brief Disable Power-on Reset function + * @param None + * @return None + * @details This macro disable Power-on Reset function. + * The register write-protection function should be disabled before using this macro. + * \hideinitializer + */ +#define SYS_DISABLE_POR() (SYS->PORCTL = 0x5AA5) + +/** + * @brief Enable Power-on Reset function + * @param None + * @return None + * @details This macro enable Power-on Reset function. + * The register write-protection function should be disabled before using this macro. + * \hideinitializer + */ +#define SYS_ENABLE_POR() (SYS->PORCTL = 0) + +/** + * @brief Clear reset source flag + * @param[in] u32RstSrc is reset source. Including : + * - \ref SYS_RSTSTS_PORF_Msk + * - \ref SYS_RSTSTS_PINRF_Msk + * - \ref SYS_RSTSTS_WDTRF_Msk + * - \ref SYS_RSTSTS_LVRF_Msk + * - \ref SYS_RSTSTS_BODRF_Msk + * - \ref SYS_RSTSTS_SYSRF_Msk + * - \ref SYS_RSTSTS_CPURF_Msk + * - \ref SYS_RSTSTS_CPULKRF_Msk + * @return None + * @details This macro clear reset source flag. + * \hideinitializer + */ +#define SYS_CLEAR_RST_SOURCE(u32RstSrc) ((SYS->RSTSTS) = (u32RstSrc) ) + + +/** + * @brief Disable register write-protection function + * @param None + * @return None + * @details This function disable register write-protection function. + * To unlock the protected register to allow write access. + * \hideinitializer + */ +__STATIC_INLINE void SYS_UnlockReg(void) +{ + do { + SYS->REGLCTL = 0x59; + SYS->REGLCTL = 0x16; + SYS->REGLCTL = 0x88; + } while (SYS->REGLCTL == 0); +} + +/** + * @brief Enable register write-protection function + * @param None + * @return None + * @details This function is used to enable register write-protection function. + * To lock the protected register to forbid write access. + * \hideinitializer + */ +__STATIC_INLINE void SYS_LockReg(void) +{ + SYS->REGLCTL = 0; +} + + +void SYS_ClearResetSrc(uint32_t u32Src); +uint32_t SYS_GetBODStatus(void); +uint32_t SYS_GetResetSrc(void); +uint32_t SYS_IsRegLocked(void); +uint32_t SYS_ReadPDID(void); +void SYS_ResetChip(void); +void SYS_ResetCPU(void); +void SYS_ResetModule(uint32_t u32ModuleIndex); +void SYS_EnableBOD(int32_t i32Mode, uint32_t u32BODLevel); +void SYS_DisableBOD(void); + + +/*@}*/ /* end of group SYS_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group SYS_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_SYS_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_timer.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_timer.h new file mode 100644 index 0000000000..1090174ca6 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_timer.h @@ -0,0 +1,507 @@ +/**************************************************************************//** + * @file nu_timer.h + * @version V0.10 + * $Revision: 6 $ + * $Date: 18/07/13 4:59p $ + * @brief M031 Series Timer Controller (TIMER) Driver Header File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_TIMER_H__ +#define __NU_TIMER_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup TIMER_Driver TIMER Driver + @{ +*/ + +/** @addtogroup TIMER_EXPORTED_CONSTANTS TIMER Exported Constants + @{ +*/ + +/*---------------------------------------------------------------------------------------------------------*/ +/* TIMER Operation Mode, External Counter and Capture Mode Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define TIMER_ONESHOT_MODE (0UL << TIMER_CTL_OPMODE_Pos) /*!< Timer working in one-shot mode \hideinitializer */ +#define TIMER_PERIODIC_MODE (1UL << TIMER_CTL_OPMODE_Pos) /*!< Timer working in periodic mode \hideinitializer */ +#define TIMER_TOGGLE_MODE (2UL << TIMER_CTL_OPMODE_Pos) /*!< Timer working in toggle-output mode \hideinitializer */ +#define TIMER_CONTINUOUS_MODE (3UL << TIMER_CTL_OPMODE_Pos) /*!< Timer working in continuous counting mode \hideinitializer */ + +#define TIMER_TOUT_PIN_FROM_TX (0UL << TIMER_CTL_TGLPINSEL_Pos) /*!< Timer toggle-output pin is from Tx pin \hideinitializer */ +#define TIMER_TOUT_PIN_FROM_TX_EXT (1UL << TIMER_CTL_TGLPINSEL_Pos) /*!< Timer toggle-output pin is from Tx_EXT pin \hideinitializer */ + +#define TIMER_CAPTURE_FREE_COUNTING_MODE (0UL << TIMER_EXTCTL_CAPFUNCS_Pos) /*!< Timer capture event to get timer counter value \hideinitializer */ +#define TIMER_CAPTURE_COUNTER_RESET_MODE (1UL << TIMER_EXTCTL_CAPFUNCS_Pos) /*!< Timer capture event to reset timer counter \hideinitializer */ + +#define TIMER_CAPTURE_FALLING_EDGE (0UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< Falling edge detection to trigger timer capture \hideinitializer */ +#define TIMER_CAPTURE_RISING_EDGE (1UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< Rising edge detection to trigger timer capture \hideinitializer */ +#define TIMER_CAPTURE_FALLING_AND_RISING_EDGE (2UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< Both falling and rising edge detection to trigger timer capture \hideinitializer */ + +#define TIMER_COUNTER_FALLING_EDGE (0UL << TIMER_EXTCTL_CNTPHASE_Pos) /*!< Counter increase on falling edge detection \hideinitializer */ +#define TIMER_COUNTER_RISING_EDGE (1UL << TIMER_EXTCTL_CNTPHASE_Pos) /*!< Counter increase on rising edge detection \hideinitializer */ + +#define TIMER_TRGSRC_TIMEOUT_EVENT (0UL << TIMER_CTL_TRGSSEL_Pos) /*!< Trigger source from Timeout event \hideinitializer */ +#define TIMER_TRGSRC_CAPTURE_EVENT (1UL << TIMER_CTL_TRGSSEL_Pos) /*!< Trigger source from Capture event \hideinitializer */ + +#define TIMER_CAPSRC_TX_EXT (0UL << TIMER_CTL_CAPSRC_Pos) /*!< Capture source from Tx_EXT pin \hideinitializer */ +#define TIMER_CAPSRC_INTERNAL (1UL << TIMER_CTL_CAPSRC_Pos) /*!< Capture source from Internal event such as LIRC or ACMP0/1 \hideinitializer */ + +#define TIMER_INTERCAPSEL_ACMP0 (0UL << TIMER_EXTCTL_INTERCAPSEL_Pos) /*!< Capture source from Internal event ACMP0 \hideinitializer */ +#define TIMER_INTERCAPSEL_ACMP1 (1UL << TIMER_EXTCTL_INTERCAPSEL_Pos) /*!< Capture source from Internal event ACMP1 \hideinitializer */ +#define TIMER_INTERCAPSEL_LIRC (5UL << TIMER_EXTCTL_INTERCAPSEL_Pos) /*!< Capture source from Internal event LIRC \hideinitializer */ + +#define TIMER_TRG_TO_PWM (TIMER_CTL_TRGPWM_Msk) /*!< Timer trigger PWM \hideinitializer */ +#define TIMER_TRG_TO_ADC (TIMER_CTL_TRGADC_Msk) /*!< Timer trigger ADC \hideinitializer */ +#define TIMER_TRG_TO_PDMA (TIMER_CTL_TRGPDMA_Msk) /*!< Timer trigger PDMA \hideinitializer */ +#define TIMER_TRG_TO_BPWM (TIMER_CTL_TRGBPWM_Msk) /*!< Timer trigger BPWM \hideinitializer */ + +#define TIMER_CMP_MAX_VALUE (0xFFFFFFUL) /*!< Max Timer compare value \hideinitializer */ + +/*@}*/ /* end of group TIMER_EXPORTED_CONSTANTS */ + + +/** @addtogroup TIMER_EXPORTED_FUNCTIONS TIMER Exported Functions + @{ +*/ + +/** + * @brief Set Timer Compared Value + * + * @param[in] timer The pointer of the specified Timer module. + * @param[in] u32Value Timer compare value. Valid values are between 2 to 0xFFFFFF. + * + * @return None + * + * @details This macro is used to set timer compared value to adjust timer time-out interval. + * @note 1. Never write 0x0 or 0x1 in this field, or the core will run into unknown state. + * @note 2. If update timer compared value in continuous counting mode, timer counter value will keep counting continuously. + * But if timer is operating at other modes, the timer up counter will restart counting and start from 0. + * + * \hideinitializer + */ +#define TIMER_SET_CMP_VALUE(timer, u32Value) ((timer)->CMP = (u32Value)) + +/** + * @brief Set Timer Prescale Value + * + * @param[in] timer The pointer of the specified Timer module. + * @param[in] u32Value Timer prescale value. Valid values are between 0 to 0xFF. + * + * @return None + * + * @details This macro is used to set timer prescale value and timer source clock will be divided by (prescale + 1) \n + * before it is fed into timer. + * + * \hideinitializer + */ +#define TIMER_SET_PRESCALE_VALUE(timer, u32Value) ((timer)->CTL = ((timer)->CTL & ~TIMER_CTL_PSC_Msk) | (u32Value)) + +/** + * @brief Check specify Timer Status + * + * @param[in] timer The pointer of the specified Timer module. + * + * @retval 0 Timer 24-bit up counter is inactive + * @retval 1 Timer 24-bit up counter is active + * + * @details This macro is used to check if specify Timer counter is inactive or active. + * + * \hideinitializer + */ +#define TIMER_IS_ACTIVE(timer) (((timer)->CTL & TIMER_CTL_ACTSTS_Msk)? 1 : 0) + +/** + * @brief Select Toggle-output Pin + * + * @param[in] timer The pointer of the specified Timer module. + * @param[in] u32ToutSel Toggle-output pin selection, valid values are: + * - \ref TIMER_TOUT_PIN_FROM_TX + * - \ref TIMER_TOUT_PIN_FROM_TX_EXT + * + * @return None + * + * @details This macro is used to select timer toggle-output pin is output on Tx or Tx_EXT pin. + * + * \hideinitializer + */ +#define TIMER_SELECT_TOUT_PIN(timer, u32ToutSel) ((timer)->CTL = ((timer)->CTL & ~TIMER_CTL_TGLPINSEL_Msk) | (u32ToutSel)) + +/** + * @brief Start Timer Counting + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to start Timer counting. + * + * \hideinitializer + */ +static __INLINE void TIMER_Start(TIMER_T *timer) +{ + timer->CTL |= TIMER_CTL_CNTEN_Msk; +} + +/** + * @brief Stop Timer Counting + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to stop/suspend Timer counting. + * + * \hideinitializer + */ +static __INLINE void TIMER_Stop(TIMER_T *timer) +{ + timer->CTL &= ~TIMER_CTL_CNTEN_Msk; +} + +/** + * @brief Enable Timer Interrupt Wake-up Function + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to enable the timer interrupt wake-up function and interrupt source could be time-out interrupt, \n + * counter event interrupt or capture trigger interrupt. + * @note To wake the system from Power-down mode, timer clock source must be ether LXT or LIRC. + * + * \hideinitializer + */ +static __INLINE void TIMER_EnableWakeup(TIMER_T *timer) +{ + timer->CTL |= TIMER_CTL_WKEN_Msk; +} + +/** + * @brief Disable Timer Wake-up Function + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to disable the timer interrupt wake-up function. + * + * \hideinitializer + */ +static __INLINE void TIMER_DisableWakeup(TIMER_T *timer) +{ + timer->CTL &= ~TIMER_CTL_WKEN_Msk; +} + +/** + * @brief Enable Capture Pin De-bounce + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to enable the detect de-bounce function of capture pin. + * + * \hideinitializer + */ +static __INLINE void TIMER_EnableCaptureDebounce(TIMER_T *timer) +{ + timer->EXTCTL |= TIMER_EXTCTL_CAPDBEN_Msk; +} + +/** + * @brief Disable Capture Pin De-bounce + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to disable the detect de-bounce function of capture pin. + * + * \hideinitializer + */ +static __INLINE void TIMER_DisableCaptureDebounce(TIMER_T *timer) +{ + timer->EXTCTL &= ~TIMER_EXTCTL_CAPDBEN_Msk; +} + +/** + * @brief Enable Counter Pin De-bounce + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to enable the detect de-bounce function of counter pin. + * + * \hideinitializer + */ +static __INLINE void TIMER_EnableEventCounterDebounce(TIMER_T *timer) +{ + timer->EXTCTL |= TIMER_EXTCTL_CNTDBEN_Msk; +} + +/** + * @brief Disable Counter Pin De-bounce + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to disable the detect de-bounce function of counter pin. + * + * \hideinitializer + */ +static __INLINE void TIMER_DisableEventCounterDebounce(TIMER_T *timer) +{ + timer->EXTCTL &= ~TIMER_EXTCTL_CNTDBEN_Msk; +} + +/** + * @brief Enable Timer Time-out Interrupt + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to enable the timer time-out interrupt function. + * + * \hideinitializer + */ +static __INLINE void TIMER_EnableInt(TIMER_T *timer) +{ + timer->CTL |= TIMER_CTL_INTEN_Msk; +} + +/** + * @brief Disable Timer Time-out Interrupt + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to disable the timer time-out interrupt function. + * + * \hideinitializer + */ +static __INLINE void TIMER_DisableInt(TIMER_T *timer) +{ + timer->CTL &= ~TIMER_CTL_INTEN_Msk; +} + +/** + * @brief Enable Capture Trigger Interrupt + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to enable the timer capture trigger interrupt function. + * + * \hideinitializer + */ +static __INLINE void TIMER_EnableCaptureInt(TIMER_T *timer) +{ + timer->EXTCTL |= TIMER_EXTCTL_CAPIEN_Msk; +} + +/** + * @brief Disable Capture Trigger Interrupt + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to disable the timer capture trigger interrupt function. + * + * \hideinitializer + */ +static __INLINE void TIMER_DisableCaptureInt(TIMER_T *timer) +{ + timer->EXTCTL &= ~TIMER_EXTCTL_CAPIEN_Msk; +} + +/** + * @brief Get Timer Time-out Interrupt Flag + * + * @param[in] timer The pointer of the specified Timer module. + * + * @retval 0 Timer time-out interrupt did not occur + * @retval 1 Timer time-out interrupt occurred + * + * @details This function indicates timer time-out interrupt occurred or not. + * + * \hideinitializer + */ +static __INLINE uint32_t TIMER_GetIntFlag(TIMER_T *timer) +{ + return ((timer->INTSTS & TIMER_INTSTS_TIF_Msk) ? 1 : 0); +} + +/** + * @brief Clear Timer Time-out Interrupt Flag + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function clears timer time-out interrupt flag to 0. + * + * \hideinitializer + */ +static __INLINE void TIMER_ClearIntFlag(TIMER_T *timer) +{ + timer->INTSTS = TIMER_INTSTS_TIF_Msk; +} + +/** + * @brief Get Timer Capture Interrupt Flag + * + * @param[in] timer The pointer of the specified Timer module. + * + * @retval 0 Timer capture interrupt did not occur + * @retval 1 Timer capture interrupt occurred + * + * @details This function indicates timer capture trigger interrupt occurred or not. + * + * \hideinitializer + */ +static __INLINE uint32_t TIMER_GetCaptureIntFlag(TIMER_T *timer) +{ + return timer->EINTSTS; +} + +/** + * @brief Clear Timer Capture Interrupt Flag + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function clears timer capture trigger interrupt flag to 0. + * + * \hideinitializer + */ +static __INLINE void TIMER_ClearCaptureIntFlag(TIMER_T *timer) +{ + timer->EINTSTS = TIMER_EINTSTS_CAPIF_Msk; +} + +/** + * @brief Get Timer Wake-up Flag + * + * @param[in] timer The pointer of the specified Timer module. + * + * @retval 0 Timer does not cause CPU wake-up + * @retval 1 Timer interrupt event cause CPU wake-up + * + * @details This function indicates timer interrupt event has waked up system or not. + * + * \hideinitializer + */ +static __INLINE uint32_t TIMER_GetWakeupFlag(TIMER_T *timer) +{ + return (timer->INTSTS & TIMER_INTSTS_TWKF_Msk ? 1 : 0); +} + +/** + * @brief Clear Timer Wake-up Flag + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function clears the timer wake-up system flag to 0. + * + * \hideinitializer + */ +static __INLINE void TIMER_ClearWakeupFlag(TIMER_T *timer) +{ + timer->INTSTS = TIMER_INTSTS_TWKF_Msk; +} + +/** + * @brief Get Capture value + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return 24-bit Capture Value + * + * @details This function reports the current 24-bit timer capture value. + * + * \hideinitializer + */ +static __INLINE uint32_t TIMER_GetCaptureData(TIMER_T *timer) +{ + return timer->CAP; +} + +/** + * @brief Get Counter value + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return 24-bit Counter Value + * + * @details This function reports the current 24-bit timer counter value. + * + * \hideinitializer + */ +static __INLINE uint32_t TIMER_GetCounter(TIMER_T *timer) +{ + return timer->CNT; +} + +/** + * @brief Reset Counter + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This function is used to reset current counter value and internal prescale counter value. + */ +__STATIC_INLINE void TIMER_ResetCounter(TIMER_T *timer) +{ + timer->CTL |= TIMER_CTL_RSTCNT_Msk; +} + +uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq); +void TIMER_Close(TIMER_T *timer); +void TIMER_Delay(TIMER_T *timer, uint32_t u32Usec); +void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge); +void TIMER_DisableCapture(TIMER_T *timer); +void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge); +void TIMER_DisableEventCounter(TIMER_T *timer); +uint32_t TIMER_GetModuleClock(TIMER_T *timer); +void TIMER_EnableFreqCounter(TIMER_T *timer, + uint32_t u32DropCount, + uint32_t u32Timeout, + uint32_t u32EnableInt); +void TIMER_DisableFreqCounter(TIMER_T *timer); +void TIMER_SetTriggerSource(TIMER_T *timer, uint32_t u32Src); +void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask); + +/*@}*/ /* end of group TIMER_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group TIMER_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_TIMER_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_uart.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_uart.h new file mode 100644 index 0000000000..a9b0cd0844 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_uart.h @@ -0,0 +1,495 @@ +/**************************************************************************** + * @file nu_uart.h + * @version V1.00 + * @brief M031 series UART driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_UART_H__ +#define __NU_UART_H__ + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup UART_Driver UART Driver + @{ +*/ + +/** @addtogroup UART_EXPORTED_CONSTANTS UART Exported Constants + @{ +*/ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART FIFO size constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ + +#define UART0_FIFO_SIZE 16ul /*!< UART0 supports separated receive/transmit 16/16 bytes entry FIFO \hideinitializer */ +#define UART1_FIFO_SIZE 16ul /*!< UART1 supports separated receive/transmit 16/16 bytes entry FIFO \hideinitializer */ +#define UART2_FIFO_SIZE 1ul /*!< UART2 supports separated receive/transmit 1/1 bytes entry FIFO \hideinitializer */ +#define UART3_FIFO_SIZE 1ul /*!< UART3 supports separated receive/transmit 1/1 bytes entry FIFO \hideinitializer */ +#define UART4_FIFO_SIZE 16ul /*!< UART4 supports separated receive/transmit 16/16 bytes entry FIFO \hideinitializer */ +#define UART5_FIFO_SIZE 16ul /*!< UART5 supports separated receive/transmit 16/16 bytes entry FIFO \hideinitializer */ +#define UART6_FIFO_SIZE 1ul /*!< UART6 supports separated receive/transmit 1/1 bytes entry FIFO \hideinitializer */ +#define UART7_FIFO_SIZE 1ul /*!< UART7 supports separated receive/transmit 1/1 bytes entry FIFO \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART_FIFO constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ + +#define UART_FIFO_RFITL_1BYTE (0x0ul << UART_FIFO_RFITL_Pos) /*!< UART_FIFO setting to set RX FIFO Trigger Level to 1 byte \hideinitializer */ +#define UART_FIFO_RFITL_4BYTES (0x1ul << UART_FIFO_RFITL_Pos) /*!< UART_FIFO setting to set RX FIFO Trigger Level to 4 bytes \hideinitializer */ +#define UART_FIFO_RFITL_8BYTES (0x2ul << UART_FIFO_RFITL_Pos) /*!< UART_FIFO setting to set RX FIFO Trigger Level to 8 bytes \hideinitializer */ +#define UART_FIFO_RFITL_14BYTES (0x3ul << UART_FIFO_RFITL_Pos) /*!< UART_FIFO setting to set RX FIFO Trigger Level to 14 bytes \hideinitializer */ + +#define UART_FIFO_RTSTRGLV_1BYTE (0x0ul << UART_FIFO_RTSTRGLV_Pos) /*!< UART_FIFO setting to set RTS Trigger Level to 1 byte \hideinitializer */ +#define UART_FIFO_RTSTRGLV_4BYTES (0x1ul << UART_FIFO_RTSTRGLV_Pos) /*!< UART_FIFO setting to set RTS Trigger Level to 4 bytes \hideinitializer */ +#define UART_FIFO_RTSTRGLV_8BYTES (0x2ul << UART_FIFO_RTSTRGLV_Pos) /*!< UART_FIFO setting to set RTS Trigger Level to 8 bytes \hideinitializer */ +#define UART_FIFO_RTSTRGLV_14BYTES (0x3ul << UART_FIFO_RTSTRGLV_Pos) /*!< UART_FIFO setting to set RTS Trigger Level to 14 bytes \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART_LINE constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_WORD_LEN_5 (0ul) /*!< UART_LINE setting to set UART word length to 5 bits \hideinitializer */ +#define UART_WORD_LEN_6 (1ul) /*!< UART_LINE setting to set UART word length to 6 bits \hideinitializer */ +#define UART_WORD_LEN_7 (2ul) /*!< UART_LINE setting to set UART word length to 7 bits \hideinitializer */ +#define UART_WORD_LEN_8 (3ul) /*!< UART_LINE setting to set UART word length to 8 bits \hideinitializer */ + +#define UART_PARITY_NONE (0x0ul << UART_LINE_PBE_Pos) /*!< UART_LINE setting to set UART as no parity \hideinitializer */ +#define UART_PARITY_ODD (0x1ul << UART_LINE_PBE_Pos) /*!< UART_LINE setting to set UART as odd parity \hideinitializer */ +#define UART_PARITY_EVEN (0x3ul << UART_LINE_PBE_Pos) /*!< UART_LINE setting to set UART as even parity \hideinitializer */ +#define UART_PARITY_MARK (0x5ul << UART_LINE_PBE_Pos) /*!< UART_LINE setting to keep parity bit as '1' \hideinitializer */ +#define UART_PARITY_SPACE (0x7ul << UART_LINE_PBE_Pos) /*!< UART_LINE setting to keep parity bit as '0' \hideinitializer */ + +#define UART_STOP_BIT_1 (0x0ul << UART_LINE_NSB_Pos) /*!< UART_LINE setting for one stop bit \hideinitializer */ +#define UART_STOP_BIT_1_5 (0x1ul << UART_LINE_NSB_Pos) /*!< UART_LINE setting for 1.5 stop bit when 5-bit word length \hideinitializer */ +#define UART_STOP_BIT_2 (0x1ul << UART_LINE_NSB_Pos) /*!< UART_LINE setting for two stop bit when 6, 7, 8-bit word length \hideinitializer */ + + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART RTS ACTIVE LEVEL constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_RTS_IS_LOW_LEV_ACTIVE (0x1ul << UART_MODEM_RTSACTLV_Pos) /*!< Set RTS is Low Level Active \hideinitializer */ +#define UART_RTS_IS_HIGH_LEV_ACTIVE (0x0ul << UART_MODEM_RTSACTLV_Pos) /*!< Set RTS is High Level Active \hideinitializer */ + + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART_IRDA constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_IRDA_TXEN (0x1ul << UART_IRDA_TXEN_Pos) /*!< Set IrDA function Tx mode \hideinitializer */ +#define UART_IRDA_RXEN (0x0ul << UART_IRDA_TXEN_Pos) /*!< Set IrDA function Rx mode \hideinitializer */ + + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART_FUNCSEL constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_FUNCSEL_UART (0x0ul << UART_FUNCSEL_FUNCSEL_Pos) /*!< UART_FUNCSEL setting to set UART Function (Default) \hideinitializer */ +#define UART_FUNCSEL_LIN (0x1ul << UART_FUNCSEL_FUNCSEL_Pos) /*!< UART_FUNCSEL setting to set LIN Function \hideinitializer */ +#define UART_FUNCSEL_IrDA (0x2ul << UART_FUNCSEL_FUNCSEL_Pos) /*!< UART_FUNCSEL setting to set IrDA Function \hideinitializer */ +#define UART_FUNCSEL_RS485 (0x3ul << UART_FUNCSEL_FUNCSEL_Pos) /*!< UART_FUNCSEL setting to set RS485 Function \hideinitializer */ +#define UART_FUNCSEL_SINGLE_WIRE (0x4ul << UART_FUNCSEL_FUNCSEL_Pos) /*!< UART_FUNCSEL setting to set Single Wire Function \hideinitializer */ + + +/*---------------------------------------------------------------------------------------------------------*/ +/* UART BAUDRATE MODE constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UART_BAUD_MODE0 (0ul) /*!< Set UART Baudrate Mode is Mode0 \hideinitializer */ +#define UART_BAUD_MODE2 (UART_BAUD_BAUDM1_Msk | UART_BAUD_BAUDM0_Msk) /*!< Set UART Baudrate Mode is Mode2 \hideinitializer */ + + +/*@}*/ /* end of group UART_EXPORTED_CONSTANTS */ + + +/** @addtogroup UART_EXPORTED_FUNCTIONS UART Exported Functions + @{ +*/ + + +/** + * @brief Calculate UART baudrate mode0 divider + * + * @param[in] u32SrcFreq UART clock frequency + * @param[in] u32BaudRate Baudrate of UART module + * + * @return UART baudrate mode0 divider + * + * @details This macro calculate UART baudrate mode0 divider. + * \hideinitializer + */ +#define UART_BAUD_MODE0_DIVIDER(u32SrcFreq, u32BaudRate) ((((u32SrcFreq) + ((u32BaudRate)*8ul)) / (u32BaudRate) >> 4ul)-2ul) + + +/** + * @brief Calculate UART baudrate mode2 divider + * + * @param[in] u32SrcFreq UART clock frequency + * @param[in] u32BaudRate Baudrate of UART module + * + * @return UART baudrate mode2 divider + * + * @details This macro calculate UART baudrate mode2 divider. + * \hideinitializer + */ +#define UART_BAUD_MODE2_DIVIDER(u32SrcFreq, u32BaudRate) ((((u32SrcFreq) + ((u32BaudRate)/2ul)) / (u32BaudRate))-2ul) + + +/** + * @brief Write UART data + * + * @param[in] uart The pointer of the specified UART module + * @param[in] u8Data Data byte to transmit. + * + * @return None + * + * @details This macro write Data to Tx data register. + * \hideinitializer + */ +#define UART_WRITE(uart, u8Data) ((uart)->DAT = (u8Data)) + + +/** + * @brief Read UART data + * + * @param[in] uart The pointer of the specified UART module + * + * @return The oldest data byte in RX FIFO. + * + * @details This macro read Rx data register. + * \hideinitializer + */ +#define UART_READ(uart) ((uart)->DAT) + + +/** + * @brief Get Tx empty + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 0 Tx FIFO is not empty + * @retval >=1 Tx FIFO is empty + * + * @details This macro get Transmitter FIFO empty register value. + * \hideinitializer + */ +#define UART_GET_TX_EMPTY(uart) ((uart)->FIFOSTS & UART_FIFOSTS_TXEMPTY_Msk) + + +/** + * @brief Get Rx empty + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 0 Rx FIFO is not empty + * @retval >=1 Rx FIFO is empty + * + * @details This macro get Receiver FIFO empty register value. + * \hideinitializer + */ +#define UART_GET_RX_EMPTY(uart) ((uart)->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) + + +/** + * @brief Check specified UART port transmission is over. + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 0 Tx transmission is not over + * @retval 1 Tx transmission is over + * + * @details This macro return Transmitter Empty Flag register bit value. + * It indicates if specified UART port transmission is over nor not. + * \hideinitializer + */ +#define UART_IS_TX_EMPTY(uart) (((uart)->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk) >> UART_FIFOSTS_TXEMPTYF_Pos) + + +/** + * @brief Wait specified UART port transmission is over + * + * @param[in] uart The pointer of the specified UART module + * + * @return None + * + * @details This macro wait specified UART port transmission is over. + * \hideinitializer + */ +#define UART_WAIT_TX_EMPTY(uart) while(!((((uart)->FIFOSTS) & UART_FIFOSTS_TXEMPTYF_Msk) >> UART_FIFOSTS_TXEMPTYF_Pos)) + + +/** + * @brief Check RX is ready or not + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 0 The number of bytes in the RX FIFO is less than the RFITL + * @retval 1 The number of bytes in the RX FIFO equals or larger than RFITL + * + * @details This macro check receive data available interrupt flag is set or not. + * \hideinitializer + */ +#define UART_IS_RX_READY(uart) (((uart)->INTSTS & UART_INTSTS_RDAIF_Msk)>>UART_INTSTS_RDAIF_Pos) + + +/** + * @brief Check TX FIFO is full or not + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 1 TX FIFO is full + * @retval 0 TX FIFO is not full + * + * @details This macro check TX FIFO is full or not. + * \hideinitializer + */ +#define UART_IS_TX_FULL(uart) (((uart)->FIFOSTS & UART_FIFOSTS_TXFULL_Msk)>>UART_FIFOSTS_TXFULL_Pos) + + +/** + * @brief Check RX FIFO is full or not + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 1 RX FIFO is full + * @retval 0 RX FIFO is not full + * + * @details This macro check RX FIFO is full or not. + * \hideinitializer + */ +#define UART_IS_RX_FULL(uart) (((uart)->FIFOSTS & UART_FIFOSTS_RXFULL_Msk)>>UART_FIFOSTS_RXFULL_Pos) + + +/** + * @brief Get Tx full register value + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 0 Tx FIFO is not full. + * @retval >=1 Tx FIFO is full. + * + * @details This macro get Tx full register value. + * \hideinitializer + */ +#define UART_GET_TX_FULL(uart) ((uart)->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) + + +/** + * @brief Get Rx full register value + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 0 Rx FIFO is not full. + * @retval >=1 Rx FIFO is full. + * + * @details This macro get Rx full register value. + * \hideinitializer + */ +#define UART_GET_RX_FULL(uart) ((uart)->FIFOSTS & UART_FIFOSTS_RXFULL_Msk) + +/** + * @brief Rx Idle Status register value + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 0 Rx is busy. + * @retval 1 Rx is Idle(Default) + * + * @details This macro get Rx Idle Status register value. + * \hideinitializer + */ +#define UART_RX_IDLE(uart) (((uart)->FIFOSTS & UART_FIFOSTS_RXIDLE_Msk )>> UART_FIFOSTS_RXIDLE_Pos) + + +/** + * @brief Enable specified UART interrupt + * + * @param[in] uart The pointer of the specified UART module + * @param[in] u32eIntSel Interrupt type select + * - \ref UART_INTEN_TXENDIEN_Msk : Transmitter Empty interrupt + * - \ref UART_INTEN_ABRIEN_Msk : Auto baud rate interrupt + * - \ref UART_INTEN_SWBEIEN_Msk : Single-wire bit error detection interrupt + * - \ref UART_INTEN_RXPDMAEN_Msk : RX PDMA interrupt + * - \ref UART_INTEN_TXPDMAEN_Msk : TX PDMA interrupt + * - \ref UART_INTEN_WKIEN_Msk : Wakeup interrupt + * - \ref UART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt + * - \ref UART_INTEN_RXTOIEN_Msk : Rx time-out interrupt + * - \ref UART_INTEN_MODEMIEN_Msk : Modem interrupt + * - \ref UART_INTEN_RLSIEN_Msk : Rx Line status interrupt + * - \ref UART_INTEN_THREIEN_Msk : Tx empty interrupt + * - \ref UART_INTEN_RDAIEN_Msk : Rx ready interrupt + * + * @return None + * + * @details This macro enable specified UART interrupt. + * \hideinitializer + */ +#define UART_ENABLE_INT(uart, u32eIntSel) ((uart)->INTEN |= (u32eIntSel)) + + +/** + * @brief Disable specified UART interrupt + * + * @param[in] uart The pointer of the specified UART module + * @param[in] u32eIntSel Interrupt type select + * - \ref UART_INTEN_TXENDIEN_Msk : Transmitter Empty interrupt + * - \ref UART_INTEN_ABRIEN_Msk : Auto baud rate interrupt + * - \ref UART_INTEN_SWBEIEN_Msk : Single-wire bit error detection interrupt + * - \ref UART_INTEN_RXPDMAEN_Msk : RX PDMA interrupt + * - \ref UART_INTEN_TXPDMAEN_Msk : TX PDMA interrupt + * - \ref UART_INTEN_WKIEN_Msk : Wakeup interrupt + * - \ref UART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt + * - \ref UART_INTEN_RXTOIEN_Msk : Rx time-out interrupt + * - \ref UART_INTEN_MODEMIEN_Msk : Modem status interrupt + * - \ref UART_INTEN_RLSIEN_Msk : Receive Line status interrupt + * - \ref UART_INTEN_THREIEN_Msk : Tx empty interrupt + * - \ref UART_INTEN_RDAIEN_Msk : Rx ready interrupt + * + * @return None + * + * @details This macro enable specified UART interrupt. + * \hideinitializer + */ +#define UART_DISABLE_INT(uart, u32eIntSel) ((uart)->INTEN &= ~ (u32eIntSel)) + + +/** + * @brief Get specified interrupt flag/status + * + * @param[in] uart The pointer of the specified UART module + * @param[in] u32eIntTypeFlag Interrupt Type Flag, should be + * - \ref UART_INTSTS_ABRINT_Msk : Auto-baud Rate Interrupt Indicator + * - \ref UART_INTSTS_TXENDINT_Msk : Transmitter Empty Interrupt Indicator + * - \ref UART_INTSTS_HWBUFEINT_Msk : In PDMA Mode, Buffer Error Interrupt Indicator + * - \ref UART_INTSTS_HWTOINT_Msk : In PDMA Mode, Time-out Interrupt Indicator + * - \ref UART_INTSTS_HWMODINT_Msk : In PDMA Mode, MODEM Status Interrupt Indicator + * - \ref UART_INTSTS_HWRLSINT_Msk : In PDMA Mode, Receive Line Status Interrupt Indicator + * - \ref UART_INTSTS_SWBEINT_Msk : In Single-wire Mode, Bit Error Detect Interrupt Indicator + * - \ref UART_INTSTS_TXENDIF_Msk : Transmitter Empty Interrupt Flag + * - \ref UART_INTSTS_HWBUFEIF_Msk : In PDMA Mode, Buffer Error Interrupt Flag + * - \ref UART_INTSTS_HWTOIF_Msk : In PDMA Mode, Time-out Interrupt Flag + * - \ref UART_INTSTS_HWMODIF_Msk : In PDMA Mode, MODEM Interrupt Flag + * - \ref UART_INTSTS_HWRLSIF_Msk : In PDMA Mode, Receive Line Status Flag + * - \ref UART_INTSTS_SWBEIF_Msk : In Single-wire Mode, Bit Error Detection Interrupt Flag + * - \ref UART_INTSTS_WKINT_Msk : Wake-up Interrupt Indicator + * - \ref UART_INTSTS_BUFERRINT_Msk : Buffer Error Interrupt Indicator + * - \ref UART_INTSTS_RXTOINT_Msk : Time-out Interrupt Indicator + * - \ref UART_INTSTS_MODEMINT_Msk : Modem Status Interrupt Indicator + * - \ref UART_INTSTS_RLSINT_Msk : Receive Line Status Interrupt Indicator + * - \ref UART_INTSTS_THREINT_Msk : Transmit Holding Register Empty Interrupt Indicator + * - \ref UART_INTSTS_RDAINT_Msk : Receive Data Available Interrupt Indicator + * - \ref UART_INTSTS_WKIF_Msk : Wake-up Interrupt Flag + * - \ref UART_INTSTS_BUFERRIF_Msk : Buffer Error Interrupt Flag + * - \ref UART_INTSTS_RXTOIF_Msk : Rx Time-out Interrupt Flag + * - \ref UART_INTSTS_MODEMIF_Msk : Modem Interrupt Flag + * - \ref UART_INTSTS_RLSIF_Msk : Receive Line Status Interrupt Flag + * - \ref UART_INTSTS_THREIF_Msk : Tx Empty Interrupt Flag + * - \ref UART_INTSTS_RDAIF_Msk : Rx Ready Interrupt Flag + * + * @retval 0 The specified interrupt is not happened. + * @retval 1 The specified interrupt is happened. + * + * @details This macro get specified interrupt flag or interrupt indicator status. + * \hideinitializer + */ +#define UART_GET_INT_FLAG(uart,u32eIntTypeFlag) (((uart)->INTSTS & (u32eIntTypeFlag))?1:0) + + +/** + * @brief Clear RS-485 Address Byte Detection Flag + * + * @param[in] uart The pointer of the specified UART module + * + * @return None + * + * @details This macro clear RS-485 address byte detection flag. + * \hideinitializer + */ +#define UART_RS485_CLEAR_ADDR_FLAG(uart) ((uart)->FIFOSTS = UART_FIFOSTS_ADDRDETF_Msk) + + +/** + * @brief Get RS-485 Address Byte Detection Flag + * + * @param[in] uart The pointer of the specified UART module + * + * @retval 0 Receiver detects a data that is not an address bit. + * @retval 1 Receiver detects a data that is an address bit. + * + * @details This macro get RS-485 address byte detection flag. + * \hideinitializer + */ +#define UART_RS485_GET_ADDR_FLAG(uart) (((uart)->FIFOSTS & UART_FIFOSTS_ADDRDETF_Msk) >> UART_FIFOSTS_ADDRDETF_Pos) + +/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */ +__STATIC_INLINE void UART_CLEAR_RTS(UART_T *uart); +__STATIC_INLINE void UART_SET_RTS(UART_T *uart); + + +/** + * @brief Set RTS pin to low + * + * @param[in] uart The pointer of the specified UART module + * + * @return None + * + * @details This macro set RTS pin to low. + */ +__STATIC_INLINE void UART_CLEAR_RTS(UART_T *uart) +{ + uart->MODEM |= UART_MODEM_RTSACTLV_Msk; + uart->MODEM &= ~UART_MODEM_RTS_Msk; +} + + +/** + * @brief Set RTS pin to high + * + * @param[in] uart The pointer of the specified UART module + * + * @return None + * + * @details This macro set RTS pin to high. + */ +__STATIC_INLINE void UART_SET_RTS(UART_T *uart) +{ + uart->MODEM |= UART_MODEM_RTSACTLV_Msk | UART_MODEM_RTS_Msk; +} + + +void UART_ClearIntFlag(UART_T *uart, uint32_t u32InterruptFlag); +void UART_Close(UART_T *uart); +void UART_DisableFlowCtrl(UART_T *uart); +void UART_DisableInt(UART_T *uart, uint32_t u32InterruptFlag); +void UART_EnableFlowCtrl(UART_T *uart); +void UART_EnableInt(UART_T *uart, uint32_t u32InterruptFlag); +void UART_Open(UART_T *uart, uint32_t u32baudrate); +uint32_t UART_Read(UART_T *uart, uint8_t pu8RxBuf[], uint32_t u32ReadBytes); +void UART_SetLine_Config(UART_T *uart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits); +void UART_SetTimeoutCnt(UART_T *uart, uint32_t u32TOC); +void UART_SelectIrDAMode(UART_T *uart, uint32_t u32Buadrate, uint32_t u32Direction); +void UART_SelectRS485Mode(UART_T *uart, uint32_t u32Mode, uint32_t u32Addr); +uint32_t UART_Write(UART_T *uart, uint8_t pu8TxBuf[], uint32_t u32WriteBytes); +void UART_SelectSingleWireMode(UART_T *uart); + + + +/*@}*/ /* end of group UART_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group UART_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /*__NU_UART_H__*/ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usbd.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usbd.h new file mode 100644 index 0000000000..d876170372 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usbd.h @@ -0,0 +1,699 @@ + +/**************************************************************************//** + * @file usbd.H + * @version V1.00 + * $Revision: 9 $ + * $Date: 18/07/13 3:05p $ + * @brief M031 series USB driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_USBD_H__ +#define __NU_USBD_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup USBD_Driver USBD Driver + @{ +*/ + +/** @addtogroup USBD_EXPORTED_STRUCT USBD Exported Struct + @{ +*/ +typedef struct s_usbd_info +{ + uint8_t *gu8DevDesc; /*!< Pointer for USB Device Descriptor */ + uint8_t *gu8ConfigDesc; /*!< Pointer for USB Configuration Descriptor */ + uint8_t **gu8StringDesc; /*!< Pointer for USB String Descriptor pointers */ + uint8_t **gu8HidReportDesc; /*!< Pointer for USB HID Report Descriptor */ + uint8_t *gu8BosDesc; /*!< Pointer for USB BOS Descriptor */ + uint32_t *gu32HidReportSize; /*!< Pointer for HID Report descriptor Size */ + uint32_t *gu32ConfigHidDescIdx; /*!< Pointer for HID Descriptor start index */ + +} S_USBD_INFO_T; /*!< Device description structure */ + +extern const S_USBD_INFO_T gsInfo; + +/*@}*/ /* end of group USBD_EXPORTED_STRUCTS */ + + + + +/** @addtogroup USBD_EXPORTED_CONSTANTS USBD Exported Constants + @{ +*/ +#define USBD_BUF_BASE (USBD_BASE+0x100ul) /*!< USBD buffer base address \hideinitializer */ +#define USBD_MAX_EP 8ul /*!< Total EP number \hideinitializer */ + +#define EP0 0ul /*!< Endpoint 0 \hideinitializer */ +#define EP1 1ul /*!< Endpoint 1 \hideinitializer */ +#define EP2 2ul /*!< Endpoint 2 \hideinitializer */ +#define EP3 3ul /*!< Endpoint 3 \hideinitializer */ +#define EP4 4ul /*!< Endpoint 4 \hideinitializer */ +#define EP5 5ul /*!< Endpoint 5 \hideinitializer */ +#define EP6 6ul /*!< Endpoint 6 \hideinitializer */ +#define EP7 7ul /*!< Endpoint 7 \hideinitializer */ + +/** @cond HIDDEN_SYMBOLS */ +/* USB Request Type */ +#define REQ_STANDARD 0x00ul +#define REQ_CLASS 0x20ul +#define REQ_VENDOR 0x40ul + +/* USB Standard Request */ +#define GET_STATUS 0x00ul +#define CLEAR_FEATURE 0x01ul +#define SET_FEATURE 0x03ul +#define SET_ADDRESS 0x05ul +#define GET_DESCRIPTOR 0x06ul +#define SET_DESCRIPTOR 0x07ul +#define GET_CONFIGURATION 0x08ul +#define SET_CONFIGURATION 0x09ul +#define GET_INTERFACE 0x0Aul +#define SET_INTERFACE 0x0Bul +#define SYNC_FRAME 0x0Cul + +/* USB Descriptor Type */ +#define DESC_DEVICE 0x01ul +#define DESC_CONFIG 0x02ul +#define DESC_STRING 0x03ul +#define DESC_INTERFACE 0x04ul +#define DESC_ENDPOINT 0x05ul +#define DESC_QUALIFIER 0x06ul +#define DESC_OTHERSPEED 0x07ul +#define DESC_IFPOWER 0x08ul +#define DESC_OTG 0x09ul +#define DESC_BOS 0x0Ful +#define DESC_CAPABILITY 0x10ul + +/* USB Device Capability Type */ +#define CAP_WIRELESS 0x01ul +#define CAP_USB20_EXT 0x02ul + +/* USB HID Descriptor Type */ +#define DESC_HID 0x21ul +#define DESC_HID_RPT 0x22ul + +/* USB Descriptor Length */ +#define LEN_DEVICE 18ul +#define LEN_QUALIFIER 10ul +#define LEN_CONFIG 9ul +#define LEN_INTERFACE 9ul +#define LEN_ENDPOINT 7ul +#define LEN_OTG 5ul +#define LEN_BOS 5ul +#define LEN_HID 9ul +#define LEN_CCID 0x36ul +#define LEN_BOSCAP 7ul + +/*! b, then return a. Otherwise, return b. + * \hideinitializer + */ +#define USBD_Maximum(a,b) ((a)>(b) ? (a) : (b)) + + +/** + * @brief Compare two input numbers and return minimum one + * + * @param[in] a First number to be compared + * @param[in] b Second number to be compared + * + * @return Minimum value between a and b + * + * @details If a < b, then return a. Otherwise, return b. + * \hideinitializer + */ +#define USBD_Minimum(a,b) ((a)<(b) ? (a) : (b)) + + +/** + * @brief Enable USB + * + * @param None + * + * @return None + * + * @details To set USB ATTR control register to enable USB and PHY. + * \hideinitializer + */ +#define USBD_ENABLE_USB() ((uint32_t)(USBD->ATTR |= 0x7D0)) + +/** + * @brief Disable USB + * + * @param None + * + * @return None + * + * @details To set USB ATTR control register to disable USB. + * \hideinitializer + */ +#define USBD_DISABLE_USB() ((uint32_t)(USBD->ATTR &= ~USBD_USB_EN)) + +/** + * @brief Enable USB PHY + * + * @param None + * + * @return None + * + * @details To set USB ATTR control register to enable USB PHY. + * \hideinitializer + */ +#define USBD_ENABLE_PHY() ((uint32_t)(USBD->ATTR |= USBD_PHY_EN)) + +/** + * @brief Disable USB PHY + * + * @param None + * + * @return None + * + * @details To set USB ATTR control register to disable USB PHY. + * \hideinitializer + */ +#define USBD_DISABLE_PHY() ((uint32_t)(USBD->ATTR &= ~USBD_PHY_EN)) + +/** + * @brief Enable SE0. Force USB PHY transceiver to drive SE0. + * + * @param None + * + * @return None + * + * @details Set DRVSE0 bit of USB_DRVSE0 register to enable software-disconnect function. Force USB PHY transceiver to drive SE0 to bus. + * \hideinitializer + */ +#define USBD_SET_SE0() ((uint32_t)(USBD->SE0 |= USBD_DRVSE0)) + +/** + * @brief Disable SE0 + * + * @param None + * + * @return None + * + * @details Clear DRVSE0 bit of USB_DRVSE0 register to disable software-disconnect function. + * \hideinitializer + */ +#define USBD_CLR_SE0() ((uint32_t)(USBD->SE0 &= ~USBD_DRVSE0)) + +/** + * @brief Set USB device address + * + * @param[in] addr The USB device address. + * + * @return None + * + * @details Write USB device address to USB_FADDR register. + * \hideinitializer + */ +#define USBD_SET_ADDR(addr) (USBD->FADDR = (addr)) + +/** + * @brief Get USB device address + * + * @param None + * + * @return USB device address + * + * @details Read USB_FADDR register to get USB device address. + * \hideinitializer + */ +#define USBD_GET_ADDR() ((uint32_t)(USBD->FADDR)) + +/** + * @brief Enable USB interrupt function + * + * @param[in] intr The combination of the specified interrupt enable bits. + * Each bit corresponds to a interrupt enable bit. + * This parameter decides which interrupts will be enabled. + * (USBD_INT_WAKEUP, USBD_INT_FLDET, USBD_INT_USB, USBD_INT_BUS) + * + * @return None + * + * @details Enable USB related interrupt functions specified by intr parameter. + * \hideinitializer + */ +#define USBD_ENABLE_INT(intr) (USBD->INTEN |= (intr)) + +/** + * @brief Get interrupt status + * + * @param None + * + * @return The value of USB_INTSTS register + * + * @details Return all interrupt flags of USB_INTSTS register. + * \hideinitializer + */ +#define USBD_GET_INT_FLAG() ((uint32_t)(USBD->INTSTS)) + +/** + * @brief Clear USB interrupt flag + * + * @param[in] flag The combination of the specified interrupt flags. + * Each bit corresponds to a interrupt source. + * This parameter decides which interrupt flags will be cleared. + * (USBD_INTSTS_WAKEUP, USBD_INTSTS_FLDET, USBD_INTSTS_BUS, USBD_INTSTS_USB) + * + * @return None + * + * @details Clear USB related interrupt flags specified by flag parameter. + * \hideinitializer + */ +#define USBD_CLR_INT_FLAG(flag) (USBD->INTSTS = (flag)) + +/** + * @brief Get endpoint status + * + * @param None + * + * @return The value of USB_EPSTS register. + * + * @details Return all endpoint status. + * \hideinitializer + */ +#define USBD_GET_EP_FLAG() ((uint32_t)(USBD->EPSTS)) + +/** + * @brief Get USB bus state + * + * @param None + * + * @return The value of USB_ATTR[3:0]. + * Bit 0 indicates USB bus reset status. + * Bit 1 indicates USB bus suspend status. + * Bit 2 indicates USB bus resume status. + * Bit 3 indicates USB bus time-out status. + * + * @details Return USB_ATTR[3:0] for USB bus events. + * \hideinitializer + */ +#define USBD_GET_BUS_STATE() ((uint32_t)(USBD->ATTR & 0xf)) + +/** + * @brief Check cable connection state + * + * @param None + * + * @retval 0 USB cable is not attached. + * @retval 1 USB cable is attached. + * + * @details Check the connection state by FLDET bit of USB_FLDET register. + * \hideinitializer + */ +#define USBD_IS_ATTACHED() ((uint32_t)(USBD->VBUSDET & USBD_VBUSDET_VBUSDET_Msk)) + +/** + * @brief Stop USB transaction of the specified endpoint ID + * + * @param[in] ep The USB endpoint ID. M451 Series supports 8 hardware endpoint ID. This parameter could be 0 ~ 7. + * + * @return None + * + * @details Write 1 to CLRRDY bit of USB_CFGPx register to stop USB transaction of the specified endpoint ID. + * \hideinitializer + */ +#define USBD_STOP_TRANSACTION(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFGP + (uint32_t)((ep) << 4))) |= USBD_CFGP_CLRRDY_Msk) + +/** + * @brief Set USB DATA1 PID for the specified endpoint ID + * + * @param[in] ep The USB endpoint ID. M451 Series supports 8 hardware endpoint ID. This parameter could be 0 ~ 7. + * + * @return None + * + * @details Set DSQ_SYNC bit of USB_CFGx register to specify the DATA1 PID for the following IN token transaction. + * Base on this setting, hardware will toggle PID between DATA0 and DATA1 automatically for IN token transactions. + * \hideinitializer + */ +#define USBD_SET_DATA1(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFG + (uint32_t)((ep) << 4))) |= USBD_CFG_DSQSYNC_Msk) + +/** + * @brief Set USB DATA0 PID for the specified endpoint ID + * + * @param[in] ep The USB endpoint ID. M451 Series supports 8 hardware endpoint ID. This parameter could be 0 ~ 7. + * + * @return None + * + * @details Clear DSQ_SYNC bit of USB_CFGx register to specify the DATA0 PID for the following IN token transaction. + * Base on this setting, hardware will toggle PID between DATA0 and DATA1 automatically for IN token transactions. + * \hideinitializer + */ +#define USBD_SET_DATA0(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFG + (uint32_t)((ep) << 4))) &= (~USBD_CFG_DSQSYNC_Msk)) + +/** + * @brief Set USB payload size (IN data) + * + * @param[in] ep The USB endpoint ID. M451 Series supports 8 hardware endpoint ID. This parameter could be 0 ~ 7. + * + * @param[in] size The transfer length. + * + * @return None + * + * @details This macro will write the transfer length to USB_MXPLDx register for IN data transaction. + * \hideinitializer + */ +#define USBD_SET_PAYLOAD_LEN(ep, size) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].MXPLD + (uint32_t)((ep) << 4))) = (size)) + +/** + * @brief Get USB payload size (OUT data) + * + * @param[in] ep The USB endpoint ID. M451 Series supports 8 endpoint ID. This parameter could be 0 ~ 7. + * + * @return The value of USB_MXPLDx register. + * + * @details Get the data length of OUT data transaction by reading USB_MXPLDx register. + * \hideinitializer + */ +#define USBD_GET_PAYLOAD_LEN(ep) ((uint32_t)*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].MXPLD + (uint32_t)((ep) << 4)))) + +/** + * @brief Configure endpoint + * + * @param[in] ep The USB endpoint ID. M451 Series supports 8 hardware endpoint ID. This parameter could be 0 ~ 7. + * + * @param[in] config The USB configuration. + * + * @return None + * + * @details This macro will write config parameter to USB_CFGx register of specified endpoint ID. + * \hideinitializer + */ +#define USBD_CONFIG_EP(ep, config) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFG + (uint32_t)((ep) << 4))) = (config)) + +/** + * @brief Set USB endpoint buffer + * + * @param[in] ep The USB endpoint ID. M451 Series supports 8 hardware endpoint ID. This parameter could be 0 ~ 7. + * + * @param[in] offset The SRAM offset. + * + * @return None + * + * @details This macro will set the SRAM offset for the specified endpoint ID. + * \hideinitializer + */ +#define USBD_SET_EP_BUF_ADDR(ep, offset) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].BUFSEG + (uint32_t)((ep) << 4))) = (offset)) + +/** + * @brief Get the offset of the specified USB endpoint buffer + * + * @param[in] ep The USB endpoint ID. M451 Series supports 8 hardware endpoint ID. This parameter could be 0 ~ 7. + * + * @return The offset of the specified endpoint buffer. + * + * @details This macro will return the SRAM offset of the specified endpoint ID. + * \hideinitializer + */ +#define USBD_GET_EP_BUF_ADDR(ep) ((uint32_t)*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].BUFSEG + (uint32_t)((ep) << 4)))) + +/** + * @brief Set USB endpoint stall state + * + * @param[in] ep The USB endpoint ID. M451 Series supports 8 hardware endpoint ID. This parameter could be 0 ~ 7. + * + * @return None + * + * @details Set USB endpoint stall state for the specified endpoint ID. Endpoint will respond STALL token automatically. + * \hideinitializer + */ +#define USBD_SET_EP_STALL(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0ul].CFGP + (uint32_t)((ep) << 4))) |= USBD_CFGP_SSTALL_Msk) + +/** + * @brief Clear USB endpoint stall state + * + * @param[in] ep The USB endpoint ID. M451 Series supports 8 hardware endpoint ID. This parameter could be 0 ~ 7. + * + * @return None + * + * @details Clear USB endpoint stall state for the specified endpoint ID. Endpoint will respond ACK/NAK token. + * \hideinitializer + */ +#define USBD_CLR_EP_STALL(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFGP + (uint32_t)((ep) << 4))) &= ~USBD_CFGP_SSTALL_Msk) + +/** + * @brief Get USB endpoint stall state + * + * @param[in] ep The USB endpoint ID. M451 Series supports 8 hardware endpoint ID. This parameter could be 0 ~ 7. + * + * @retval 0 USB endpoint is not stalled. + * @retval Others USB endpoint is stalled. + * + * @details Get USB endpoint stall state of the specified endpoint ID. + * \hideinitializer + */ +#define USBD_GET_EP_STALL(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFGP + (uint32_t)((ep) << 4))) & USBD_CFGP_SSTALL_Msk) + +/** + * @brief To support byte access between USB SRAM and system SRAM + * + * @param[in] dest Destination pointer. + * + * @param[in] src Source pointer. + * + * @param[in] size Byte count. + * + * @return None + * + * @details This function will copy the number of data specified by size and src parameters to the address specified by dest parameter. + * + */ +__STATIC_INLINE void USBD_MemCopy(uint8_t dest[], uint8_t src[], uint32_t size) +{ + uint32_t volatile i = 0ul; + + while (size--) + { + dest[i] = src[i]; + i++; + } +} + +/** + * @brief Set USB endpoint stall state + * + * @param[in] epnum USB endpoint number + * + * @return None + * + * @details Set USB endpoint stall state. Endpoint will respond STALL token automatically. + * + */ +__STATIC_INLINE void USBD_SetStall(uint8_t epnum) +{ + uint32_t u32CfgAddr; + uint32_t u32Cfg; + uint32_t i; + + for (i = 0ul; i < USBD_MAX_EP; i++) + { + u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFG; /* USBD_CFG0 */ + u32Cfg = *((__IO uint32_t *)(u32CfgAddr)); + + if ((u32Cfg & 0xful) == epnum) + { + u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFGP; /* USBD_CFGP0 */ + u32Cfg = *((__IO uint32_t *)(u32CfgAddr)); + + *((__IO uint32_t *)(u32CfgAddr)) = (u32Cfg | USBD_CFGP_SSTALL); + break; + } + } +} + +/** + * @brief Clear USB endpoint stall state + * + * @param[in] epnum USB endpoint number + * + * @return None + * + * @details Clear USB endpoint stall state. Endpoint will respond ACK/NAK token. + */ +__STATIC_INLINE void USBD_ClearStall(uint8_t epnum) +{ + uint32_t u32CfgAddr; + uint32_t u32Cfg; + uint32_t i; + + for (i = 0ul; i < USBD_MAX_EP; i++) + { + u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFG; /* USBD_CFG0 */ + u32Cfg = *((__IO uint32_t *)(u32CfgAddr)); + + if ((u32Cfg & 0xful) == epnum) + { + u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFGP; /* USBD_CFGP0 */ + u32Cfg = *((__IO uint32_t *)(u32CfgAddr)); + + *((__IO uint32_t *)(u32CfgAddr)) = (u32Cfg & ~USBD_CFGP_SSTALL); + break; + } + } +} + +/** + * @brief Get USB endpoint stall state + * + * @param[in] epnum USB endpoint number + * + * @retval 0 USB endpoint is not stalled. + * @retval Others USB endpoint is stalled. + * + * @details Get USB endpoint stall state. + * + */ +__STATIC_INLINE uint32_t USBD_GetStall(uint8_t epnum) +{ + uint32_t u32CfgAddr; + uint32_t u32Cfg; + uint32_t i; + + for (i = 0ul; i < USBD_MAX_EP; i++) + { + u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFG; /* USBD_CFG0 */ + u32Cfg = *((__IO uint32_t *)(u32CfgAddr)); + + if ((u32Cfg & 0xful) == epnum) + { + u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFGP; /* USBD_CFGP0 */ + break; + } + } + + return ((*((__IO uint32_t *)(u32CfgAddr))) & USBD_CFGP_SSTALL); +} + + +extern volatile uint8_t g_usbd_RemoteWakeupEn; + + +typedef void (*VENDOR_REQ)(void); /*!< Functional pointer type definition for Vendor class */ +typedef void (*CLASS_REQ)(void); /*!< Functional pointer type declaration for USB class request callback handler */ +typedef void (*SET_INTERFACE_REQ)(uint32_t u32AltInterface); /*!< Functional pointer type declaration for USB set interface request callback handler */ +typedef void (*SET_CONFIG_CB)(void); /*!< Functional pointer type declaration for USB set configuration request callback handler */ + + +/*--------------------------------------------------------------------*/ +void USBD_Open(const S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface); +void USBD_Start(void); +void USBD_GetSetupPacket(uint8_t *buf); +void USBD_ProcessSetupPacket(void); +void USBD_StandardRequest(void); +void USBD_PrepareCtrlIn(uint8_t pu8Buf[], uint32_t u32Size); +void USBD_CtrlIn(void); +void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size); +void USBD_CtrlOut(void); +void USBD_SwReset(void); +void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq); +void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback); +void USBD_LockEpStall(uint32_t u32EpBitmap); + +/*@}*/ /* end of group USBD_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group USBD_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_USBD_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_i2c.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_i2c.h new file mode 100644 index 0000000000..64e6f45671 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_i2c.h @@ -0,0 +1,332 @@ +/**************************************************************************//** + * @file nu_usci_i2c.h + * @version V1.00 + * @brief M031 series USCI I2C(UI2C) driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + ******************************************************************************/ +#ifndef __NU_USCI_I2C_H__ +#define __NU_USCI_I2C_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup USCI_I2C_Driver USCI_I2C Driver + @{ +*/ + +/** @addtogroup USCI_I2C_EXPORTED_CONSTANTS USCI_I2C Exported Constants + @{ +*/ + +/*---------------------------------------------------------------------------------------------------------*/ +/* USCI_I2C master event definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +enum UI2C_MASTER_EVENT +{ + MASTER_SEND_ADDRESS = 10u, /*!< Master send address to Slave */ + MASTER_SEND_H_WR_ADDRESS, /*!< Master send High address to Slave */ + MASTER_SEND_H_RD_ADDRESS, /*!< Master send address to Slave (Read ADDR) */ + MASTER_SEND_L_ADDRESS, /*!< Master send Low address to Slave */ + MASTER_SEND_DATA, /*!< Master Send Data to Slave */ + MASTER_SEND_REPEAT_START, /*!< Master send repeat start to Slave */ + MASTER_READ_DATA, /*!< Master Get Data from Slave */ + MASTER_STOP, /*!< Master send stop to Slave */ + MASTER_SEND_START /*!< Master send start to Slave */ +}; + +/*---------------------------------------------------------------------------------------------------------*/ +/* USCI_I2C slave event definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +enum UI2C_SLAVE_EVENT +{ + SLAVE_ADDRESS_ACK = 100u, /*!< Slave send address ACK */ + SLAVE_H_WR_ADDRESS_ACK, /*!< Slave send High address ACK */ + SLAVE_L_WR_ADDRESS_ACK, /*!< Slave send Low address ACK */ + SLAVE_GET_DATA, /*!< Slave Get Data from Master (Write CMD) */ + SLAVE_SEND_DATA, /*!< Slave Send Data to Master (Read CMD) */ + SLAVE_H_RD_ADDRESS_ACK, /*!< Slave send High address ACK */ + SLAVE_L_RD_ADDRESS_ACK /*!< Slave send Low address ACK */ +}; + +/*---------------------------------------------------------------------------------------------------------*/ +/* USCI_CTL constant definitions. */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UI2C_CTL_PTRG 0x20UL /*!< USCI_CTL setting for I2C control bits. It would set PTRG bit \hideinitializer */ +#define UI2C_CTL_STA 0x08UL /*!< USCI_CTL setting for I2C control bits. It would set STA bit \hideinitializer */ +#define UI2C_CTL_STO 0x04UL /*!< USCI_CTL setting for I2C control bits. It would set STO bit \hideinitializer */ +#define UI2C_CTL_AA 0x02UL /*!< USCI_CTL setting for I2C control bits. It would set AA bit \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* USCI_I2C GCMode constant definitions. */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UI2C_GCMODE_ENABLE (1U) /*!< Enable USCI_I2C GC Mode \hideinitializer */ +#define UI2C_GCMODE_DISABLE (0U) /*!< Disable USCI_I2C GC Mode \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* USCI_I2C Wakeup Mode constant definitions. */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UI2C_DATA_TOGGLE_WK (0x0U << UI2C_WKCTL_WKADDREN_Pos) /*!< Wakeup according data toggle \hideinitializer */ +#define UI2C_ADDR_MATCH_WK (0x1U << UI2C_WKCTL_WKADDREN_Pos) /*!< Wakeup according address match \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* USCI_I2C interrupt mask definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UI2C_TO_INT_MASK (0x001U) /*!< Time-out interrupt mask \hideinitializer */ +#define UI2C_STAR_INT_MASK (0x002U) /*!< Start condition received interrupt mask \hideinitializer */ +#define UI2C_STOR_INT_MASK (0x004U) /*!< Stop condition received interrupt mask \hideinitializer */ +#define UI2C_NACK_INT_MASK (0x008U) /*!< Non-acknowledge interrupt mask \hideinitializer */ +#define UI2C_ARBLO_INT_MASK (0x010U) /*!< Arbitration lost interrupt mask \hideinitializer */ +#define UI2C_ERR_INT_MASK (0x020U) /*!< Error interrupt mask \hideinitializer */ +#define UI2C_ACK_INT_MASK (0x040U) /*!< Acknowledge interrupt mask \hideinitializer */ + +/*@}*/ /* end of group USCI_I2C_EXPORTED_CONSTANTS */ + + +/** @addtogroup USCI_I2C_EXPORTED_FUNCTIONS USCI_I2C Exported Functions + @{ +*/ + +/** + * @brief This macro sets the USCI_I2C protocol control register at one time + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8Ctrl Set the register value of USCI_I2C control register. + * + * @return None + * + * @details Set UI2C_PROTCTL register to control USCI_I2C bus conditions of START, STOP, PTRG, ACK. + * \hideinitializer + */ +#define UI2C_SET_CONTROL_REG(ui2c, u8Ctrl) ((ui2c)->PROTCTL = ((ui2c)->PROTCTL & ~0x2EU) | (u8Ctrl)) + +/** + * @brief This macro only set START bit to protocol control register of USCI_I2C module. + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return None + * + * @details Set the USCI_I2C bus START condition in UI2C_PROTCTL register. + * \hideinitializer + */ +#define UI2C_START(ui2c) ((ui2c)->PROTCTL = ((ui2c)->PROTCTL & ~UI2C_PROTCTL_PTRG_Msk) | UI2C_PROTCTL_STA_Msk) + +/** + * @brief This macro only set STOP bit to the control register of USCI_I2C module + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return None + * + * @details Set the USCI_I2C bus STOP condition in UI2C_PROTCTL register. + * \hideinitializer + */ +#define UI2C_STOP(ui2c) ((ui2c)->PROTCTL = ((ui2c)->PROTCTL & ~0x2E) | (UI2C_PROTCTL_PTRG_Msk | UI2C_PROTCTL_STO_Msk)) + +/** + * @brief This macro returns the data stored in data register of USCI_I2C module + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return Data + * + * @details Read a byte data value of UI2C_RXDAT register from USCI_I2C bus + * \hideinitializer + */ +#define UI2C_GET_DATA(ui2c) ((ui2c)->RXDAT) + +/** + * @brief This macro writes the data to data register of USCI_I2C module + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8Data The data which will be written to data register of USCI_I2C module. + * + * @return None + * + * @details Write a byte data value of UI2C_TXDAT register, then sends address or data to USCI I2C bus + * \hideinitializer + */ +#define UI2C_SET_DATA(ui2c, u8Data) ((ui2c)->TXDAT = (u8Data)) + +/** + * @brief This macro returns time-out flag + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @retval 0 USCI_I2C bus time-out is not happened + * @retval 1 USCI_I2C bus time-out is happened + * + * @details USCI_I2C bus occurs time-out event, the time-out flag will be set. If not occurs time-out event, this bit is cleared. + * \hideinitializer + */ +#define UI2C_GET_TIMEOUT_FLAG(ui2c) (((ui2c)->PROTSTS & UI2C_PROTSTS_TOIF_Msk) == UI2C_PROTSTS_TOIF_Msk ? 1:0) + +/** + * @brief This macro returns wake-up flag + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @retval 0 Chip is not woken-up from power-down mode + * @retval 1 Chip is woken-up from power-down mode + * + * @details USCI_I2C controller wake-up flag will be set when USCI_I2C bus occurs wake-up from deep-sleep. + * \hideinitializer + */ +#define UI2C_GET_WAKEUP_FLAG(ui2c) (((ui2c)->WKSTS & UI2C_WKSTS_WKF_Msk) == UI2C_WKSTS_WKF_Msk ? 1:0) + +/** + * @brief This macro is used to clear USCI_I2C wake-up flag + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return None + * + * @details If USCI_I2C wake-up flag is set, use this macro to clear it. + * \hideinitializer + */ +#define UI2C_CLR_WAKEUP_FLAG(ui2c) ((ui2c)->WKSTS = UI2C_WKSTS_WKF_Msk) + +/** + * @brief This macro disables the USCI_I2C 10-bit address mode + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return None + * + * @details The UI2C_I2C is 7-bit address mode, when disable USCI_I2C 10-bit address match function. + * \hideinitializer + */ +#define UI2C_DISABLE_10BIT_ADDR_MODE(ui2c) ((ui2c)->PROTCTL &= ~(UI2C_PROTCTL_ADDR10EN_Msk)) + +/** + * @brief This macro enables the 10-bit address mode + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return None + * + * @details To enable USCI_I2C 10-bit address match function. + * \hideinitializer + */ +#define UI2C_ENABLE_10BIT_ADDR_MODE(ui2c) ((ui2c)->PROTCTL |= UI2C_PROTCTL_ADDR10EN_Msk) + +/** + * @brief This macro gets USCI_I2C protocol interrupt flag or bus status + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return A word data of USCI_I2C_PROTSTS register + * + * @details Read a word data of USCI_I2C PROTSTS register to get USCI_I2C bus Interrupt flags or status. + * \hideinitializer + */ +#define UI2C_GET_PROT_STATUS(ui2c) ((ui2c)->PROTSTS) + +/** + * @brief This macro clears specified protocol interrupt flag + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u32IntTypeFlag Interrupt Type Flag, should be + * - \ref UI2C_PROTSTS_ACKIF_Msk + * - \ref UI2C_PROTSTS_ERRIF_Msk + * - \ref UI2C_PROTSTS_ARBLOIF_Msk + * - \ref UI2C_PROTSTS_NACKIF_Msk + * - \ref UI2C_PROTSTS_STORIF_Msk + * - \ref UI2C_PROTSTS_STARIF_Msk + * - \ref UI2C_PROTSTS_TOIF_Msk + * @return None + * + * @details To clear interrupt flag when USCI_I2C occurs interrupt and set interrupt flag. + * \hideinitializer + */ +#define UI2C_CLR_PROT_INT_FLAG(ui2c,u32IntTypeFlag) ((ui2c)->PROTSTS = (u32IntTypeFlag)) + +/** + * @brief This macro enables specified protocol interrupt + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u32IntSel Interrupt Type, should be + * - \ref UI2C_PROTIEN_ACKIEN_Msk + * - \ref UI2C_PROTIEN_ERRIEN_Msk + * - \ref UI2C_PROTIEN_ARBLOIEN_Msk + * - \ref UI2C_PROTIEN_NACKIEN_Msk + * - \ref UI2C_PROTIEN_STORIEN_Msk + * - \ref UI2C_PROTIEN_STARIEN_Msk + * - \ref UI2C_PROTIEN_TOIEN_Msk + * @return None + * + * @details Set specified USCI_I2C protocol interrupt bits to enable interrupt function. + * \hideinitializer + */ +#define UI2C_ENABLE_PROT_INT(ui2c, u32IntSel) ((ui2c)->PROTIEN |= (u32IntSel)) + +/** + * @brief This macro disables specified protocol interrupt + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u32IntSel Interrupt Type, should be + * - \ref UI2C_PROTIEN_ACKIEN_Msk + * - \ref UI2C_PROTIEN_ERRIEN_Msk + * - \ref UI2C_PROTIEN_ARBLOIEN_Msk + * - \ref UI2C_PROTIEN_NACKIEN_Msk + * - \ref UI2C_PROTIEN_STORIEN_Msk + * - \ref UI2C_PROTIEN_STARIEN_Msk + * - \ref UI2C_PROTIEN_TOIEN_Msk + * @return None + * + * @details Clear specified USCI_I2C protocol interrupt bits to disable interrupt function. + * \hideinitializer + */ +#define UI2C_DISABLE_PROT_INT(ui2c, u32IntSel) ((ui2c)->PROTIEN &= ~ (u32IntSel)) + + +uint32_t UI2C_Open(UI2C_T *ui2c, uint32_t u32BusClock); +void UI2C_Close(UI2C_T *ui2c); +void UI2C_ClearTimeoutFlag(UI2C_T *ui2c); +void UI2C_Trigger(UI2C_T *ui2c, uint8_t u8Start, uint8_t u8Stop, uint8_t u8Ptrg, uint8_t u8Ack); +void UI2C_DisableInt(UI2C_T *ui2c, uint32_t u32Mask); +void UI2C_EnableInt(UI2C_T *ui2c, uint32_t u32Mask); +uint32_t UI2C_GetBusClockFreq(UI2C_T *ui2c); +uint32_t UI2C_SetBusClockFreq(UI2C_T *ui2c, uint32_t u32BusClock); +uint32_t UI2C_GetIntFlag(UI2C_T *ui2c, uint32_t u32Mask); +void UI2C_ClearIntFlag(UI2C_T *ui2c , uint32_t u32Mask); +uint32_t UI2C_GetData(UI2C_T *ui2c); +void UI2C_SetData(UI2C_T *ui2c, uint8_t u8Data); +void UI2C_SetSlaveAddr(UI2C_T *ui2c, uint8_t u8SlaveNo, uint16_t u16SlaveAddr, uint8_t u8GCMode); +void UI2C_SetSlaveAddrMask(UI2C_T *ui2c, uint8_t u8SlaveNo, uint16_t u16SlaveAddrMask); +void UI2C_EnableTimeout(UI2C_T *ui2c, uint32_t u32TimeoutCnt); +void UI2C_DisableTimeout(UI2C_T *ui2c); +void UI2C_EnableWakeup(UI2C_T *ui2c, uint8_t u8WakeupMode); +void UI2C_DisableWakeup(UI2C_T *ui2c); +uint8_t UI2C_WriteByte(UI2C_T *ui2c, uint8_t u8SlaveAddr, const uint8_t data); +uint32_t UI2C_WriteMultiBytes(UI2C_T *ui2c, uint8_t u8SlaveAddr, const uint8_t *data, uint32_t u32wLen); +uint8_t UI2C_WriteByteOneReg(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, const uint8_t data); +uint32_t UI2C_WriteMultiBytesOneReg(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, const uint8_t *data, uint32_t u32wLen); +uint8_t UI2C_WriteByteTwoRegs(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, const uint8_t data); +uint32_t UI2C_WriteMultiBytesTwoRegs(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, const uint8_t *data, uint32_t u32wLen); +uint8_t UI2C_ReadByte(UI2C_T *ui2c, uint8_t u8SlaveAddr); +uint32_t UI2C_ReadMultiBytes(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint8_t *rdata, uint32_t u32rLen); +uint8_t UI2C_ReadByteOneReg(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr); +uint32_t UI2C_ReadMultiBytesOneReg(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t *rdata, uint32_t u32rLen); +uint8_t UI2C_ReadByteTwoRegs(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr); +uint32_t UI2C_ReadMultiBytesTwoRegs(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t *rdata, uint32_t u32rLen); + +/*@}*/ /* end of group USCI_I2C_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group USCI_I2C_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_USCI_I2C_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_spi.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_spi.h new file mode 100644 index 0000000000..09900787c1 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_spi.h @@ -0,0 +1,428 @@ +/****************************************************************************//** + * @file nu_usci_spi.h + * @version V1.00 + * @brief M031 series USCI_SPI driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#ifndef __NU_USCI_SPI_H__ +#define __NU_USCI_SPI_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup USCI_SPI_Driver USCI_SPI Driver + @{ +*/ + +/** @addtogroup USCI_SPI_EXPORTED_CONSTANTS USCI_SPI Exported Constants + @{ +*/ + +#define USPI_MODE_0 (0x0UL << USPI_PROTCTL_SCLKMODE_Pos) /*!< SCLK idle low; data transmit with falling edge and receive with rising edge \hideinitializer */ +#define USPI_MODE_1 (0x1UL << USPI_PROTCTL_SCLKMODE_Pos) /*!< SCLK idle low; data transmit with rising edge and receive with falling edge \hideinitializer */ +#define USPI_MODE_2 (0x2UL << USPI_PROTCTL_SCLKMODE_Pos) /*!< SCLK idle high; data transmit with rising edge and receive with falling edge \hideinitializer */ +#define USPI_MODE_3 (0x3UL << USPI_PROTCTL_SCLKMODE_Pos) /*!< SCLK idle high; data transmit with falling edge and receive with rising edge \hideinitializer */ + +#define USPI_SLAVE (USPI_PROTCTL_SLAVE_Msk) /*!< Set as slave \hideinitializer */ +#define USPI_MASTER (0x0UL) /*!< Set as master \hideinitializer */ + +#define USPI_SS (USPI_PROTCTL_SS_Msk) /*!< Set SS \hideinitializer */ +#define USPI_SS_ACTIVE_HIGH (0x0UL) /*!< SS active high \hideinitializer */ +#define USPI_SS_ACTIVE_LOW (USPI_LINECTL_CTLOINV_Msk) /*!< SS active low \hideinitializer */ + +/* USCI_SPI Interrupt Mask */ +#define USPI_SSINACT_INT_MASK (0x001UL) /*!< Slave Select Inactive interrupt mask \hideinitializer */ +#define USPI_SSACT_INT_MASK (0x002UL) /*!< Slave Select Active interrupt mask \hideinitializer */ +#define USPI_SLVTO_INT_MASK (0x004UL) /*!< Slave Mode Time-out interrupt mask \hideinitializer */ +#define USPI_SLVBE_INT_MASK (0x008UL) /*!< Slave Mode Bit Count Error interrupt mask \hideinitializer */ +#define USPI_TXUDR_INT_MASK (0x010UL) /*!< Slave Transmit Under Run interrupt mask \hideinitializer */ +#define USPI_RXOV_INT_MASK (0x020UL) /*!< Receive Buffer Overrun interrupt mask \hideinitializer */ +#define USPI_TXST_INT_MASK (0x040UL) /*!< Transmit Start interrupt mask \hideinitializer */ +#define USPI_TXEND_INT_MASK (0x080UL) /*!< Transmit End interrupt mask \hideinitializer */ +#define USPI_RXST_INT_MASK (0x100UL) /*!< Receive Start interrupt mask \hideinitializer */ +#define USPI_RXEND_INT_MASK (0x200UL) /*!< Receive End interrupt mask \hideinitializer */ + +/* USCI_SPI Status Mask */ +#define USPI_BUSY_MASK (0x01UL) /*!< Busy status mask \hideinitializer */ +#define USPI_RX_EMPTY_MASK (0x02UL) /*!< RX empty status mask \hideinitializer */ +#define USPI_RX_FULL_MASK (0x04UL) /*!< RX full status mask \hideinitializer */ +#define USPI_TX_EMPTY_MASK (0x08UL) /*!< TX empty status mask \hideinitializer */ +#define USPI_TX_FULL_MASK (0x10UL) /*!< TX full status mask \hideinitializer */ +#define USPI_SSLINE_STS_MASK (0x20UL) /*!< USCI_SPI_SS line status mask \hideinitializer */ + +/*@}*/ /* end of group USCI_SPI_EXPORTED_CONSTANTS */ + + +/** @addtogroup USCI_SPI_EXPORTED_FUNCTIONS USCI_SPI Exported Functions + @{ +*/ + +/** + * @brief Disable slave 3-wire mode. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None + * \hideinitializer + */ +#define USPI_DISABLE_3WIRE_MODE(uspi) ( (uspi)->PROTCTL &= ~USPI_PROTCTL_SLV3WIRE_Msk ) + +/** + * @brief Enable slave 3-wire mode. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None + * \hideinitializer + */ +#define USPI_ENABLE_3WIRE_MODE(uspi) ( (uspi)->PROTCTL |= USPI_PROTCTL_SLV3WIRE_Msk ) + +/** + * @brief Get the Rx buffer empty flag. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return Rx buffer flag + * @retval 0: Rx buffer is not empty + * @retval 1: Rx buffer is empty + * \hideinitializer + */ +#define USPI_GET_RX_EMPTY_FLAG(uspi) ( ((uspi)->BUFSTS & USPI_BUFSTS_RXEMPTY_Msk) == USPI_BUFSTS_RXEMPTY_Msk ? 1:0 ) + +/** + * @brief Get the Tx buffer empty flag. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return Tx buffer flag + * @retval 0: Tx buffer is not empty + * @retval 1: Tx buffer is empty + * \hideinitializer + */ +#define USPI_GET_TX_EMPTY_FLAG(uspi) ( ((uspi)->BUFSTS & USPI_BUFSTS_TXEMPTY_Msk) == USPI_BUFSTS_TXEMPTY_Msk ? 1:0 ) + +/** + * @brief Get the Tx buffer full flag. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return Tx buffer flag + * @retval 0: Tx buffer is not full + * @retval 1: Tx buffer is full + * \hideinitializer + */ +#define USPI_GET_TX_FULL_FLAG(uspi) ( ((uspi)->BUFSTS & USPI_BUFSTS_TXFULL_Msk) == USPI_BUFSTS_TXFULL_Msk ? 1:0 ) + +/** + * @brief Get the datum read from RX register. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return data in Rx register + * \hideinitializer + */ +#define USPI_READ_RX(uspi) ( (uspi)->RXDAT ) + +/** + * @brief Write datum to TX register. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32TxData The datum which user attempt to transfer through USCI_SPI bus. + * @return None + * \hideinitializer + */ +#define USPI_WRITE_TX(uspi, u32TxData) ( (uspi)->TXDAT = (u32TxData) ) + +/** + * @brief Set USCI_SPI_SS pin to high state. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None. + * @details Disable automatic slave selection function and set USCI_SPI_SS pin to high state. Only available in Master mode. + * \hideinitializer + */ +#define USPI_SET_SS_HIGH(uspi) \ + do{ \ + (uspi)->LINECTL &= ~(USPI_LINECTL_CTLOINV_Msk); \ + (uspi)->PROTCTL = (((uspi)->PROTCTL & ~USPI_PROTCTL_AUTOSS_Msk) | USPI_PROTCTL_SS_Msk); \ + }while(0) + +/** + * @brief Set USCI_SPI_SS pin to low state. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None. + * @details Disable automatic slave selection function and set USCI_SPI_SS pin to low state. Only available in Master mode. + * \hideinitializer + */ +#define USPI_SET_SS_LOW(uspi) \ + do{ \ + (uspi)->LINECTL |= (USPI_LINECTL_CTLOINV_Msk); \ + (uspi)->PROTCTL = (((uspi)->PROTCTL & ~USPI_PROTCTL_AUTOSS_Msk) | USPI_PROTCTL_SS_Msk); \ + }while(0) + +/** + * @brief Set the length of suspend interval. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32SuspCycle Decide the length of suspend interval. + * @return None + * \hideinitializer + */ +#define USPI_SET_SUSPEND_CYCLE(uspi, u32SuspCycle) ( (uspi)->PROTCTL = ((uspi)->PROTCTL & ~USPI_PROTCTL_SUSPITV_Msk) | ((u32SuspCycle) << USPI_PROTCTL_SUSPITV_Pos) ) + +/** + * @brief Set the USCI_SPI transfer sequence with LSB first. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None + * \hideinitializer + */ +#define USPI_SET_LSB_FIRST(uspi) ( (uspi)->LINECTL |= USPI_LINECTL_LSB_Msk ) + +/** + * @brief Set the USCI_SPI transfer sequence with MSB first. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None + * \hideinitializer + */ +#define USPI_SET_MSB_FIRST(uspi) ( (uspi)->LINECTL &= ~USPI_LINECTL_LSB_Msk ) + +/** + * @brief Set the data width of a USCI_SPI transaction. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32Width The data width + * @return None + * \hideinitializer + */ +#define USPI_SET_DATA_WIDTH(uspi, u32Width) \ + do{ \ + if((u32Width) == 16ul){ \ + (uspi)->LINECTL = ((uspi)->LINECTL & ~USPI_LINECTL_DWIDTH_Msk) | (0 << USPI_LINECTL_DWIDTH_Pos); \ + }else { \ + (uspi)->LINECTL = ((uspi)->LINECTL & ~USPI_LINECTL_DWIDTH_Msk) | ((u32Width) << USPI_LINECTL_DWIDTH_Pos); \ + } \ + }while(0) + +/** + * @brief Get the USCI_SPI busy state. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return USCI_SPI busy status + * @retval 0: USCI_SPI module is not busy + * @retval 1: USCI_SPI module is busy + * \hideinitializer + */ +#define USPI_IS_BUSY(uspi) ( ((uspi)->PROTSTS & USPI_PROTSTS_BUSY_Msk) == USPI_PROTSTS_BUSY_Msk ? 1:0 ) + +/** + * @brief Get the USCI_SPI wakeup flag. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return Wakeup status. + * @retval 0 Flag is not set. + * @retval 1 Flag is set. + * \hideinitializer + */ +#define USPI_GET_WAKEUP_FLAG(uspi) ( ((uspi)->WKSTS & USPI_WKSTS_WKF_Msk) == USPI_WKSTS_WKF_Msk ? 1:0 ) + +/** + * @brief Clear the USCI_SPI wakeup flag. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None + * \hideinitializer + */ +#define USPI_CLR_WAKEUP_FLAG(uspi) ( (uspi)->WKSTS |= USPI_WKSTS_WKF_Msk ) + +/** + * @brief Get protocol interrupt flag/status. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return The interrupt flag/status of protocol status register. + * \hideinitializer + */ +#define USPI_GET_PROT_STATUS(uspi) ( (uspi)->PROTSTS ) + +/** + * @brief Clear specified protocol interrupt flag. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32IntTypeFlag Interrupt Type Flag, should be + * - \ref USPI_PROTSTS_SSACTIF_Msk + * - \ref USPI_PROTSTS_SSINAIF_Msk + * - \ref USPI_PROTSTS_SLVBEIF_Msk + * - \ref USPI_PROTSTS_SLVTOIF_Msk + * - \ref USPI_PROTSTS_RXENDIF_Msk + * - \ref USPI_PROTSTS_RXSTIF_Msk + * - \ref USPI_PROTSTS_TXENDIF_Msk + * - \ref USPI_PROTSTS_TXSTIF_Msk + * @return None + * \hideinitializer + */ +#define USPI_CLR_PROT_INT_FLAG(uspi, u32IntTypeFlag) ( (uspi)->PROTSTS = (u32IntTypeFlag) ) + +/** + * @brief Get buffer interrupt flag/status. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return The interrupt flag/status of buffer status register. + * \hideinitializer + */ +#define USPI_GET_BUF_STATUS(uspi) ( (uspi)->BUFSTS ) + +/** + * @brief Clear specified buffer interrupt flag. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32IntTypeFlag Interrupt Type Flag, should be + * - \ref USPI_BUFSTS_TXUDRIF_Msk + * - \ref USPI_BUFSTS_RXOVIF_Msk + * @return None + * \hideinitializer + */ +#define USPI_CLR_BUF_INT_FLAG(uspi, u32IntTypeFlag) ( (uspi)->BUFSTS = (u32IntTypeFlag) ) + +/** + * @brief Enable specified protocol interrupt. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32IntSel Interrupt Type, should be + * - \ref USPI_PROTIEN_SLVBEIEN_Msk + * - \ref USPI_PROTIEN_SLVTOIEN_Msk + * - \ref USPI_PROTIEN_SSACTIEN_Msk + * - \ref USPI_PROTIEN_SSINAIEN_Msk + * @return None + * \hideinitializer + */ +#define USPI_ENABLE_PROT_INT(uspi, u32IntSel) ( (uspi)->PROTIEN |= (u32IntSel) ) + +/** + * @brief Disable specified protocol interrupt. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32IntSel Interrupt Type, should be + * - \ref USPI_PROTIEN_SLVBEIEN_Msk + * - \ref USPI_PROTIEN_SLVTOIEN_Msk + * - \ref USPI_PROTIEN_SSACTIEN_Msk + * - \ref USPI_PROTIEN_SSINAIEN_Msk + * @return None + * \hideinitializer + */ +#define USPI_DISABLE_PROT_INT(uspi, u32IntSel) ( (uspi)->PROTIEN &= ~ (u32IntSel) ) + +/** + * @brief Enable specified buffer interrupt. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32IntSel Interrupt Type, should be + * - \ref USPI_BUFCTL_RXOVIEN_Msk + * - \ref USPI_BUFCTL_TXUDRIEN_Msk + * @return None + * \hideinitializer + */ +#define USPI_ENABLE_BUF_INT(uspi, u32IntSel) ( (uspi)->BUFCTL |= (u32IntSel) ) + +/** + * @brief Disable specified buffer interrupt. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32IntSel Interrupt Type, should be + * - \ref USPI_BUFCTL_RXOVIEN_Msk + * - \ref USPI_BUFCTL_TXUDRIEN_Msk + * @return None + * \hideinitializer + */ +#define USPI_DISABLE_BUF_INT(uspi, u32IntSel) ( (uspi)->BUFCTL &= ~ (u32IntSel) ) + +/** + * @brief Enable specified transfer interrupt. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32IntSel Interrupt Type, should be + * - \ref USPI_INTEN_RXENDIEN_Msk + * - \ref USPI_INTEN_RXSTIEN_Msk + * - \ref USPI_INTEN_TXENDIEN_Msk + * - \ref USPI_INTEN_TXSTIEN_Msk + * @return None + * \hideinitializer + */ +#define USPI_ENABLE_TRANS_INT(uspi, u32IntSel) ( (uspi)->INTEN |= (u32IntSel) ) + +/** + * @brief Disable specified transfer interrupt. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32IntSel Interrupt Type, should be + * - \ref USPI_INTEN_RXENDIEN_Msk + * - \ref USPI_INTEN_RXSTIEN_Msk + * - \ref USPI_INTEN_TXENDIEN_Msk + * - \ref USPI_INTEN_TXSTIEN_Msk + * @return None + * \hideinitializer + */ +#define USPI_DISABLE_TRANS_INT(uspi, u32IntSel) ( (uspi)->INTEN &= ~ (u32IntSel) ) + +/** + * @brief Trigger RX PDMA function. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None. + * @details Set RXPDMAEN bit of USPI_PDMACTL register to enable RX PDMA transfer function. + * \hideinitializer + */ +#define USPI_TRIGGER_RX_PDMA(uspi) ( (uspi)->PDMACTL |= USPI_PDMACTL_RXPDMAEN_Msk | USPI_PDMACTL_PDMAEN_Msk ) + +/** + * @brief Trigger TX PDMA function. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None. + * @details Set TXPDMAEN bit of USPI_PDMACTL register to enable TX PDMA transfer function. + * \hideinitializer + */ +#define USPI_TRIGGER_TX_PDMA(uspi) ( (uspi)->PDMACTL |= USPI_PDMACTL_TXPDMAEN_Msk | USPI_PDMACTL_PDMAEN_Msk ) + +/** + * @brief Trigger TX and RX PDMA function. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None. + * @details Set TXPDMAEN bit and RXPDMAEN bit of USPI_PDMACTL register to enable TX and RX PDMA transfer function. + * \hideinitializer + */ +#define USPI_TRIGGER_TX_RX_PDMA(uspi) ((uspi)->PDMACTL |= USPI_PDMACTL_TXPDMAEN_Msk|USPI_PDMACTL_RXPDMAEN_Msk|USPI_PDMACTL_PDMAEN_Msk) + +/** + * @brief Disable RX PDMA transfer. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None. + * @details Clear RXPDMAEN bit of USPI_PDMACTL register to disable RX PDMA transfer function. + * \hideinitializer + */ +#define USPI_DISABLE_RX_PDMA(uspi) ( (uspi)->PDMACTL &= ~USPI_PDMACTL_RXPDMAEN_Msk ) + +/** + * @brief Disable TX PDMA transfer. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None. + * @details Clear TXPDMAEN bit of USPI_PDMACTL register to disable TX PDMA transfer function. + * \hideinitializer + */ +#define USPI_DISABLE_TX_PDMA(uspi) ( (uspi)->PDMACTL &= ~USPI_PDMACTL_TXPDMAEN_Msk ) + +/** + * @brief Disable TX and RX PDMA transfer. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None. + * @details Clear TXPDMAEN bit and RXPDMAEN bit of USPI_PDMACTL register to disable TX and RX PDMA transfer function. + * \hideinitializer + */ +#define USPI_DISABLE_TX_RX_PDMA(uspi) ( (uspi)->PDMACTL &= ~(USPI_PDMACTL_TXPDMAEN_Msk | USPI_PDMACTL_RXPDMAEN_Msk)) + +uint32_t USPI_Open(USPI_T *uspi, uint32_t u32MasterSlave, uint32_t u32SPIMode, uint32_t u32DataWidth, uint32_t u32BusClock); +void USPI_Close(USPI_T *uspi); +void USPI_ClearRxBuf(USPI_T *uspi); +void USPI_ClearTxBuf(USPI_T *uspi); +void USPI_DisableAutoSS(USPI_T *uspi); +void USPI_EnableAutoSS(USPI_T *uspi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel); +uint32_t USPI_SetBusClock(USPI_T *uspi, uint32_t u32BusClock); +uint32_t USPI_GetBusClock(USPI_T *uspi); +void USPI_EnableInt(USPI_T *uspi, uint32_t u32Mask); +void USPI_DisableInt(USPI_T *uspi, uint32_t u32Mask); +uint32_t USPI_GetIntFlag(USPI_T *uspi, uint32_t u32Mask); +void USPI_ClearIntFlag(USPI_T *uspi, uint32_t u32Mask); +uint32_t USPI_GetStatus(USPI_T *uspi, uint32_t u32Mask); +void USPI_EnableWakeup(USPI_T *uspi); +void USPI_DisableWakeup(USPI_T *uspi); + + +/*@}*/ /* end of group USCI_SPI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group USCI_SPI_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_USCI_SPI_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_uart.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_uart.h new file mode 100644 index 0000000000..d3fcd317a6 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_usci_uart.h @@ -0,0 +1,523 @@ +/**************************************************************************//** + * @file nu_usci_uart.h + * @version V1.00 + * @brief M031 series USCI UART (UUART) driver header file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#ifndef __NU_USCI_UART_H__ +#define __NU_USCI_UART_H__ + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup USCI_UART_Driver USCI_UART Driver + @{ +*/ + +/** @addtogroup USCI_UART_EXPORTED_CONSTANTS USCI_UART Exported Constants + @{ +*/ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UUART_LINECTL constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UUART_WORD_LEN_6 (6ul << UUART_LINECTL_DWIDTH_Pos) /*!< UUART_LINECTL setting to set UART word length to 6 bits \hideinitializer */ +#define UUART_WORD_LEN_7 (7ul << UUART_LINECTL_DWIDTH_Pos) /*!< UUART_LINECTL setting to set UART word length to 7 bits \hideinitializer */ +#define UUART_WORD_LEN_8 (8ul << UUART_LINECTL_DWIDTH_Pos) /*!< UUART_LINECTL setting to set UART word length to 8 bits \hideinitializer */ +#define UUART_WORD_LEN_9 (9ul << UUART_LINECTL_DWIDTH_Pos) /*!< UUART_LINECTL setting to set UART word length to 9 bits \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* UUART_PROTCTL constants definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UUART_PARITY_NONE (0x0ul << UUART_PROTCTL_PARITYEN_Pos) /*!< UUART_PROTCTL setting to set UART as no parity \hideinitializer */ +#define UUART_PARITY_ODD (0x1ul << UUART_PROTCTL_PARITYEN_Pos) /*!< UUART_PROTCTL setting to set UART as odd parity \hideinitializer */ +#define UUART_PARITY_EVEN (0x3ul << UUART_PROTCTL_PARITYEN_Pos) /*!< UUART_PROTCTL setting to set UART as even parity \hideinitializer */ + +#define UUART_STOP_BIT_1 (0x0ul) /*!< UUART_PROTCTL setting for one stop bit \hideinitializer */ +#define UUART_STOP_BIT_2 (0x1ul) /*!< UUART_PROTCTL setting for two stop bit \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* USCI UART interrupt mask definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define UUART_ABR_INT_MASK (0x002ul) /*!< Auto-baud rate interrupt mask \hideinitializer */ +#define UUART_RLS_INT_MASK (0x004ul) /*!< Receive line status interrupt mask \hideinitializer */ +#define UUART_BUF_RXOV_INT_MASK (0x008ul) /*!< Buffer RX overrun interrupt mask \hideinitializer */ +#define UUART_TXST_INT_MASK (0x010ul) /*!< TX start interrupt mask \hideinitializer */ +#define UUART_TXEND_INT_MASK (0x020ul) /*!< Tx end interrupt mask \hideinitializer */ +#define UUART_RXST_INT_MASK (0x040ul) /*!< RX start interrupt mask \hideinitializer */ +#define UUART_RXEND_INT_MASK (0x080ul) /*!< RX end interrupt mask \hideinitializer */ + + +/*@}*/ /* end of group USCI_UART_EXPORTED_CONSTANTS */ + + +/** @addtogroup USCI_UART_EXPORTED_FUNCTIONS USCI_UART Exported Functions + @{ +*/ + + +/** + * @brief Write USCI_UART data + * + * @param[in] uuart The pointer of the specified USCI_UART module + * @param[in] u8Data Data byte to transmit. + * + * @return None + * + * @details This macro write Data to Tx data register. + * \hideinitializer + */ +#define UUART_WRITE(uuart, u8Data) ((uuart)->TXDAT = (u8Data)) + + +/** + * @brief Read USCI_UART data + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @return The oldest data byte in RX buffer. + * + * @details This macro read Rx data register. + * \hideinitializer + */ +#define UUART_READ(uuart) ((uuart)->RXDAT) + + +/** + * @brief Get Tx empty + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @retval 0 Tx buffer is not empty + * @retval >=1 Tx buffer is empty + * + * @details This macro get Transmitter buffer empty register value. + * \hideinitializer + */ +#define UUART_GET_TX_EMPTY(uuart) ((uuart)->BUFSTS & UUART_BUFSTS_TXEMPTY_Msk) + + +/** + * @brief Get Rx empty + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @retval 0 Rx buffer is not empty + * @retval >=1 Rx buffer is empty + * + * @details This macro get Receiver buffer empty register value. + * \hideinitializer + */ +#define UUART_GET_RX_EMPTY(uuart) ((uuart)->BUFSTS & UUART_BUFSTS_RXEMPTY_Msk) + + +/** + * @brief Check specified usci_uart port transmission is over. + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @retval 0 Tx transmission is not over + * @retval 1 Tx transmission is over + * + * @details This macro return Transmitter Empty Flag register bit value. \n + * It indicates if specified usci_uart port transmission is over nor not. + * \hideinitializer + */ +#define UUART_IS_TX_EMPTY(uuart) (((uuart)->BUFSTS & UUART_BUFSTS_TXEMPTY_Msk) >> UUART_BUFSTS_TXEMPTY_Pos) + + +/** + * @brief Check specified usci_uart port receiver is empty. + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @retval 0 Rx receiver is not empty + * @retval 1 Rx receiver is empty + * + * @details This macro return Receive Empty Flag register bit value. \n + * It indicates if specified usci_uart port receiver is empty nor not. + * \hideinitializer + */ +#define UUART_IS_RX_EMPTY(uuart) (((uuart)->BUFSTS & UUART_BUFSTS_RXEMPTY_Msk) >> UUART_BUFSTS_RXEMPTY_Pos) + + +/** + * @brief Wait specified usci_uart port transmission is over + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @return None + * + * @details This macro wait specified usci_uart port transmission is over. + * \hideinitializer + */ +#define UUART_WAIT_TX_EMPTY(uuart) while(!((((uuart)->BUFSTS) & UUART_BUFSTS_TXEMPTY_Msk) >> UUART_BUFSTS_TXEMPTY_Pos)) + + +/** + * @brief Check TX buffer is full or not + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @retval 1 TX buffer is full + * @retval 0 TX buffer is not full + * + * @details This macro check TX buffer is full or not. + * \hideinitializer + */ +#define UUART_IS_TX_FULL(uuart) (((uuart)->BUFSTS & UUART_BUFSTS_TXFULL_Msk)>>UUART_BUFSTS_TXFULL_Pos) + + +/** + * @brief Check RX buffer is full or not + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @retval 1 RX buffer is full + * @retval 0 RX buffer is not full + * + * @details This macro check RX buffer is full or not. + * \hideinitializer + */ +#define UUART_IS_RX_FULL(uuart) (((uuart)->BUFSTS & UUART_BUFSTS_RXFULL_Msk)>>UUART_BUFSTS_RXFULL_Pos) + + +/** + * @brief Get Tx full register value + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @retval 0 Tx buffer is not full. + * @retval >=1 Tx buffer is full. + * + * @details This macro get Tx full register value. + * \hideinitializer + */ +#define UUART_GET_TX_FULL(uuart) ((uuart)->BUFSTS & UUART_BUFSTS_TXFULL_Msk) + + +/** + * @brief Get Rx full register value + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @retval 0 Rx buffer is not full. + * @retval >=1 Rx buffer is full. + * + * @details This macro get Rx full register value. + * \hideinitializer + */ +#define UUART_GET_RX_FULL(uuart) ((uuart)->BUFSTS & UUART_BUFSTS_RXFULL_Msk) + + +/** + * @brief Enable specified USCI_UART protocol interrupt + * + * @param[in] uuart The pointer of the specified USCI_UART module + * @param[in] u32IntSel Interrupt type select + * - \ref UUART_PROTIEN_RLSIEN_Msk : Rx Line status interrupt + * - \ref UUART_PROTIEN_ABRIEN_Msk : Auto-baud rate interrupt + * + * @return None + * + * @details This macro enable specified USCI_UART protocol interrupt. + * \hideinitializer + */ +#define UUART_ENABLE_PROT_INT(uuart, u32IntSel) ((uuart)->PROTIEN |= (u32IntSel)) + + +/** + * @brief Disable specified USCI_UART protocol interrupt + * + * @param[in] uuart The pointer of the specified USCI_UART module + * @param[in] u32IntSel Interrupt type select + * - \ref UUART_PROTIEN_RLSIEN_Msk : Rx Line status interrupt + * - \ref UUART_PROTIEN_ABRIEN_Msk : Auto-baud rate interrupt + * + * @return None + * + * @details This macro disable specified USCI_UART protocol interrupt. + * \hideinitializer + */ +#define UUART_DISABLE_PROT_INT(uuart, u32IntSel) ((uuart)->PROTIEN &= ~(u32IntSel)) + + +/** + * @brief Enable specified USCI_UART buffer interrupt + * + * @param[in] uuart The pointer of the specified USCI_UART module + * @param[in] u32IntSel Interrupt type select + * - \ref UUART_BUFCTL_RXOVIEN_Msk : Receive buffer overrun error interrupt + * + * @return None + * + * @details This macro enable specified USCI_UART buffer interrupt. + * \hideinitializer + */ +#define UUART_ENABLE_BUF_INT(uuart, u32IntSel) ((uuart)->BUFCTL |= (u32IntSel)) + + +/** + * @brief Disable specified USCI_UART buffer interrupt + * + * @param[in] uuart The pointer of the specified USCI_UART module + * @param[in] u32IntSel Interrupt type select + * - \ref UUART_BUFCTL_RXOVIEN_Msk : Receive buffer overrun error interrupt + * + * @return None + * + * @details This macro disable specified USCI_UART buffer interrupt. + * \hideinitializer + */ +#define UUART_DISABLE_BUF_INT(uuart, u32IntSel) ((uuart)->BUFCTL &= ~ (u32IntSel)) + + +/** + * @brief Enable specified USCI_UART transfer interrupt + * + * @param[in] uuart The pointer of the specified USCI_UART module + * @param[in] u32IntSel Interrupt type select + * - \ref UUART_INTEN_RXENDIEN_Msk : Receive end interrupt + * - \ref UUART_INTEN_RXSTIEN_Msk : Receive start interrupt + * - \ref UUART_INTEN_TXENDIEN_Msk : Transmit end interrupt + * - \ref UUART_INTEN_TXSTIEN_Msk : Transmit start interrupt + * + * @return None + * + * @details This macro enable specified USCI_UART transfer interrupt. + * \hideinitializer + */ +#define UUART_ENABLE_TRANS_INT(uuart, u32IntSel) ((uuart)->INTEN |= (u32IntSel)) + + +/** + * @brief Disable specified USCI_UART transfer interrupt + * + * @param[in] uuart The pointer of the specified USCI_UART module + * @param[in] u32IntSel Interrupt type select + * - \ref UUART_INTEN_RXENDIEN_Msk : Receive end interrupt + * - \ref UUART_INTEN_RXSTIEN_Msk : Receive start interrupt + * - \ref UUART_INTEN_TXENDIEN_Msk : Transmit end interrupt + * - \ref UUART_INTEN_TXSTIEN_Msk : Transmit start interrupt + * + * @return None + * + * @details This macro disable specified USCI_UART transfer interrupt. + * \hideinitializer + */ +#define UUART_DISABLE_TRANS_INT(uuart, u32IntSel) ((uuart)->INTEN &= ~(u32IntSel)) + + +/** + * @brief Get protocol interrupt flag/status + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @return The interrupt flag/status of protocol status register. + * + * @details This macro get protocol status register value. + * \hideinitializer + */ +#define UUART_GET_PROT_STATUS(uuart) ((uuart)->PROTSTS) + + +/** + * @brief Clear specified protocol interrupt flag + * + * @param[in] uuart The pointer of the specified USCI_UART module + * @param[in] u32IntTypeFlag Interrupt Type Flag, should be + * - \ref UUART_PROTSTS_ABERRSTS_Msk : Auto-baud Rate Error Interrupt Indicator + * - \ref UUART_PROTSTS_ABRDETIF_Msk : Auto-baud Rate Detected Interrupt Flag + * - \ref UUART_PROTSTS_BREAK_Msk : Break Flag + * - \ref UUART_PROTSTS_FRMERR_Msk : Framing Error Flag + * - \ref UUART_PROTSTS_PARITYERR_Msk : Parity Error Flag + * - \ref UUART_PROTSTS_RXENDIF_Msk : Receive End Interrupt Flag + * - \ref UUART_PROTSTS_RXSTIF_Msk : Receive Start Interrupt Flag + * - \ref UUART_PROTSTS_TXENDIF_Msk : Transmit End Interrupt Flag + * - \ref UUART_PROTSTS_TXSTIF_Msk : Transmit Start Interrupt Flag + * + * @return None + * + * @details This macro clear specified protocol interrupt flag. + * \hideinitializer + */ +#define UUART_CLR_PROT_INT_FLAG(uuart,u32IntTypeFlag) ((uuart)->PROTSTS = (u32IntTypeFlag)) + + +/** + * @brief Get transmit/receive buffer interrupt flag/status + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @return The interrupt flag/status of buffer status register. + * + * @details This macro get buffer status register value. + * \hideinitializer + */ +#define UUART_GET_BUF_STATUS(uuart) ((uuart)->BUFSTS) + + +/** + * @brief Clear specified buffer interrupt flag + * + * @param[in] uuart The pointer of the specified USCI_UART module + * @param[in] u32IntTypeFlag Interrupt Type Flag, should be + * - \ref UUART_BUFSTS_RXOVIF_Msk : Receive Buffer Over-run Error Interrupt Indicator + * + * @return None + * + * @details This macro clear specified buffer interrupt flag. + * \hideinitializer + */ +#define UUART_CLR_BUF_INT_FLAG(uuart,u32IntTypeFlag) ((uuart)->BUFSTS = (u32IntTypeFlag)) + + +/** + * @brief Get wakeup flag + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @retval 0 Chip did not wake up from power-down mode. + * @retval 1 Chip waked up from power-down mode. + * + * @details This macro get wakeup flag. + * \hideinitializer + */ +#define UUART_GET_WAKEUP_FLAG(uuart) ((uuart)->WKSTS & UUART_WKSTS_WKF_Msk ? 1: 0 ) + + +/** + * @brief Clear wakeup flag + * + * @param[in] uuart The pointer of the specified USCI_UART module + * + * @return None + * + * @details This macro clear wakeup flag. + * \hideinitializer + */ +#define UUART_CLR_WAKEUP_FLAG(uuart) ((uuart)->WKSTS = UUART_WKSTS_WKF_Msk) + + +/** + * @brief Enable specified USCI_UART PDMA function + * + * @param[in] uuart The pointer of the specified USCI_UART module + * @param[in] u32FuncSel Combination of following functions + * - \ref UUART_PDMACTL_TXPDMAEN_Msk + * - \ref UUART_PDMACTL_RXPDMAEN_Msk + * - \ref UUART_PDMACTL_PDMAEN_Msk + * + * @return None + * + * \hideinitializer + */ +#define UUART_PDMA_ENABLE(uuart, u32FuncSel) ((uuart)->PDMACTL |= (u32FuncSel)) + + +/** + * @brief Disable specified USCI_UART PDMA function + * + * @param[in] uuart The pointer of the specified USCI_UART module + * @param[in] u32FuncSel Combination of following functions + * - \ref UUART_PDMACTL_TXPDMAEN_Msk + * - \ref UUART_PDMACTL_RXPDMAEN_Msk + * - \ref UUART_PDMACTL_PDMAEN_Msk + * + * @return None + * + * \hideinitializer + */ +#define UUART_PDMA_DISABLE(uuart, u32FuncSel) ((uuart)->PDMACTL &= ~(u32FuncSel)) + + +/** + * @brief Trigger RX PDMA function. + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * + * @return None. + * + * @details Set RXPDMAEN bit of UUART_PDMACTL register to enable RX PDMA transfer function. + * \hideinitializer + */ +#define UUART_TRIGGER_RX_PDMA(uuart) ((uuart)->PDMACTL |= UUART_PDMACTL_RXPDMAEN_Msk|UUART_PDMACTL_PDMAEN_Msk) + + +/** + * @brief Trigger TX PDMA function. + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * + * @return None. + * + * @details Set TXPDMAEN bit of UUART_PDMACTL register to enable TX PDMA transfer function. + * \hideinitializer + */ +#define UUART_TRIGGER_TX_PDMA(uuart) ((uuart)->PDMACTL |= UUART_PDMACTL_TXPDMAEN_Msk|UUART_PDMACTL_PDMAEN_Msk) + + +/** + * @brief Disable RX PDMA transfer. + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * + * @return None. + * + * @details Clear RXPDMAEN bit of UUART_PDMACTL register to disable RX PDMA transfer function. + * \hideinitializer + */ +#define UUART_DISABLE_RX_PDMA(uuart) ( (uuart)->PDMACTL &= ~UUART_PDMACTL_RXPDMAEN_Msk ) + + +/** + * @brief Disable TX PDMA transfer. + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * + * @return None. + * + * @details Clear TXPDMAEN bit of UUART_PDMACTL register to disable TX PDMA transfer function. + * \hideinitializer + */ +#define UUART_DISABLE_TX_PDMA(uuart) ( (uuart)->PDMACTL &= ~UUART_PDMACTL_TXPDMAEN_Msk ) + + +void UUART_ClearIntFlag(UUART_T* uuart, uint32_t u32Mask); +uint32_t UUART_GetIntFlag(UUART_T* uuart, uint32_t u32Mask); +void UUART_Close(UUART_T* uuart); +void UUART_DisableInt(UUART_T* uuart, uint32_t u32Mask); +void UUART_EnableInt(UUART_T* uuart, uint32_t u32Mask); +uint32_t UUART_Open(UUART_T* uuart, uint32_t u32baudrate); +uint32_t UUART_Read(UUART_T* uuart, uint8_t pu8RxBuf[], uint32_t u32ReadBytes); +uint32_t UUART_SetLine_Config(UUART_T* uuart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits); +uint32_t UUART_Write(UUART_T* uuart, uint8_t pu8TxBuf[], uint32_t u32WriteBytes); +void UUART_EnableWakeup(UUART_T* uuart, uint32_t u32WakeupMode); +void UUART_DisableWakeup(UUART_T* uuart); +void UUART_EnableFlowCtrl(UUART_T* uuart); +void UUART_DisableFlowCtrl(UUART_T* uuart); + + +/*@}*/ /* end of group USCI_UART_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group USCI_UART_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NU_USCI_UART_H__ */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_wdt.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_wdt.h new file mode 100644 index 0000000000..90e4c78c7b --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_wdt.h @@ -0,0 +1,220 @@ +/**************************************************************************//** + * @file nu_wdt.h + * @version V3.00 + * $Revision: 6 $ + * $Date: 18/06/08 11:34a $ + * @brief M031 series Watchdog Timer(WDT) driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_WDT_H__ +#define __NU_WDT_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup WDT_Driver WDT Driver + @{ +*/ + +/** @addtogroup WDT_EXPORTED_CONSTANTS WDT Exported Constants + @{ +*/ +/*---------------------------------------------------------------------------------------------------------*/ +/* WDT Time-out Interval Period Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define WDT_TIMEOUT_2POW4 (0UL << WDT_CTL_TOUTSEL_Pos) /*!< Setting WDT time-out interval to 2^4 * WDT clocks \hideinitializer */ +#define WDT_TIMEOUT_2POW6 (1UL << WDT_CTL_TOUTSEL_Pos) /*!< Setting WDT time-out interval to 2^6 * WDT clocks \hideinitializer */ +#define WDT_TIMEOUT_2POW8 (2UL << WDT_CTL_TOUTSEL_Pos) /*!< Setting WDT time-out interval to 2^8 * WDT clocks \hideinitializer */ +#define WDT_TIMEOUT_2POW10 (3UL << WDT_CTL_TOUTSEL_Pos) /*!< Setting WDT time-out interval to 2^10 * WDT clocks \hideinitializer */ +#define WDT_TIMEOUT_2POW12 (4UL << WDT_CTL_TOUTSEL_Pos) /*!< Setting WDT time-out interval to 2^12 * WDT clocks \hideinitializer */ +#define WDT_TIMEOUT_2POW14 (5UL << WDT_CTL_TOUTSEL_Pos) /*!< Setting WDT time-out interval to 2^14 * WDT clocks \hideinitializer */ +#define WDT_TIMEOUT_2POW16 (6UL << WDT_CTL_TOUTSEL_Pos) /*!< Setting WDT time-out interval to 2^16 * WDT clocks \hideinitializer */ +#define WDT_TIMEOUT_2POW18 (7UL << WDT_CTL_TOUTSEL_Pos) /*!< Setting WDT time-out interval to 2^18 * WDT clocks \hideinitializer */ +#define WDT_TIMEOUT_2POW20 (8UL << WDT_CTL_TOUTSEL_Pos) /*!< Setting WDT time-out interval to 2^20 * WDT clocks \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* WDT Reset Delay Period Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define WDT_RESET_DELAY_1026CLK (0UL << WDT_ALTCTL_RSTDSEL_Pos) /*!< Setting WDT reset delay period to 1026 * WDT clocks \hideinitializer */ +#define WDT_RESET_DELAY_130CLK (1UL << WDT_ALTCTL_RSTDSEL_Pos) /*!< Setting WDT reset delay period to 130 * WDT clocks \hideinitializer */ +#define WDT_RESET_DELAY_18CLK (2UL << WDT_ALTCTL_RSTDSEL_Pos) /*!< Setting WDT reset delay period to 18 * WDT clocks \hideinitializer */ +#define WDT_RESET_DELAY_3CLK (3UL << WDT_ALTCTL_RSTDSEL_Pos) /*!< Setting WDT reset delay period to 3 * WDT clocks \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* WDT Free Reset Counter Keyword Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define WDT_RESET_COUNTER_KEYWORD (0x00005AA5UL) /*!< Fill this value to WDT_RSTCNT register to free reset WDT counter \hideinitializer */ + +/*@}*/ /* end of group WDT_EXPORTED_CONSTANTS */ + + +/** @addtogroup WDT_EXPORTED_FUNCTIONS WDT Exported Functions + @{ +*/ + +/** + * @brief Clear WDT Reset System Flag + * + * @param None + * + * @return None + * + * @details This macro clears WDT time-out reset system flag. + * \hideinitializer + */ +#define WDT_CLEAR_RESET_FLAG() (WDT->CTL = (WDT->CTL & ~(WDT_CTL_IF_Msk | WDT_CTL_WKF_Msk)) | WDT_CTL_RSTF_Msk) + +/** + * @brief Clear WDT Time-out Interrupt Flag + * + * @param None + * + * @return None + * + * @details This macro clears WDT time-out interrupt flag. + * \hideinitializer + */ +#define WDT_CLEAR_TIMEOUT_INT_FLAG() (WDT->CTL = (WDT->CTL & ~(WDT_CTL_RSTF_Msk | WDT_CTL_WKF_Msk)) | WDT_CTL_IF_Msk) + +/** + * @brief Clear WDT Wake-up Flag + * + * @param None + * + * @return None + * + * @details This macro clears WDT time-out wake-up system flag. + * \hideinitializer + */ +#define WDT_CLEAR_TIMEOUT_WAKEUP_FLAG() (WDT->CTL = (WDT->CTL & ~(WDT_CTL_RSTF_Msk | WDT_CTL_IF_Msk)) | WDT_CTL_WKF_Msk) + +/** + * @brief Get WDT Time-out Reset Flag + * + * @param None + * + * @retval 0 WDT time-out reset system did not occur + * @retval 1 WDT time-out reset system occurred + * + * @details This macro indicates system has been reset by WDT time-out reset or not. + * \hideinitializer + */ +#define WDT_GET_RESET_FLAG() ((WDT->CTL & WDT_CTL_RSTF_Msk)? 1UL : 0UL) + +/** + * @brief Get WDT Time-out Interrupt Flag + * + * @param None + * + * @retval 0 WDT time-out interrupt did not occur + * @retval 1 WDT time-out interrupt occurred + * + * @details This macro indicates WDT time-out interrupt occurred or not. + * \hideinitializer + */ +#define WDT_GET_TIMEOUT_INT_FLAG() ((WDT->CTL & WDT_CTL_IF_Msk)? 1UL : 0UL) + +/** + * @brief Get WDT Time-out Wake-up Flag + * + * @param None + * + * @retval 0 WDT time-out interrupt does not cause CPU wake-up + * @retval 1 WDT time-out interrupt event cause CPU wake-up + * + * @details This macro indicates WDT time-out interrupt event has waked up system or not. + * \hideinitializer + */ +#define WDT_GET_TIMEOUT_WAKEUP_FLAG() ((WDT->CTL & WDT_CTL_WKF_Msk)? 1UL : 0UL) + +/** + * @brief Reset WDT Counter + * + * @param None + * + * @return None + * + * @details This macro is used to reset the internal 18-bit WDT up counter value. + * @note If WDT is activated and time-out reset system function is enabled also, user should \n + * reset the 18-bit WDT up counter value to avoid generate WDT time-out reset signal to \n + * reset system before the WDT time-out reset delay period expires. + * \hideinitializer + */ +#define WDT_RESET_COUNTER() (WDT->RSTCNT = WDT_RESET_COUNTER_KEYWORD) + +__STATIC_INLINE void WDT_Close(void); +__STATIC_INLINE void WDT_EnableInt(void); +__STATIC_INLINE void WDT_DisableInt(void); +/** + * @brief Stop WDT Counting + * + * @param None + * + * @return None + * + * @details This function will stop WDT counting and disable WDT module. + */ +__STATIC_INLINE void WDT_Close(void) +{ + WDT->CTL = 0UL; + while(WDT->CTL & WDT_CTL_SYNC_Msk); // Wait disable WDTEN bit completed, it needs 2 * WDT_CLK. + return; +} + +/** + * @brief Enable WDT Time-out Interrupt + * + * @param None + * + * @return None + * + * @details This function will enable the WDT time-out interrupt function. + */ +__STATIC_INLINE void WDT_EnableInt(void) +{ + WDT->CTL |= WDT_CTL_INTEN_Msk; + while(WDT->CTL & WDT_CTL_SYNC_Msk); // Wait enable WDTEN bit completed, it needs 2 * WDT_CLK. + return; +} + +/** + * @brief Disable WDT Time-out Interrupt + * + * @param None + * + * @return None + * + * @details This function will disable the WDT time-out interrupt function. + */ +__STATIC_INLINE void WDT_DisableInt(void) +{ + /* Do not touch another write 1 clear bits */ + WDT->CTL &= ~(WDT_CTL_INTEN_Msk | WDT_CTL_RSTF_Msk | WDT_CTL_IF_Msk | WDT_CTL_WKF_Msk); + return; +} + +void WDT_Open(uint32_t u32TimeoutInterval, uint32_t u32ResetDelay, uint32_t u32EnableReset, uint32_t u32EnableWakeup); + +/*@}*/ /* end of group WDT_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group WDT_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_WDT_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_wwdt.h b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_wwdt.h new file mode 100644 index 0000000000..6c61a55695 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/inc/nu_wwdt.h @@ -0,0 +1,155 @@ +/**************************************************************************//** + * @file nu_wwdt.h + * @version V3.00 + * $Revision: 5 $ + * $Date: 18/06/07 9:48a $ + * @brief M031 series Window Watchdog Timet(WWDT) driver header file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#ifndef __NU_WWDT_H__ +#define __NU_WWDT_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup WWDT_Driver WWDT Driver + @{ +*/ + +/** @addtogroup WWDT_EXPORTED_CONSTANTS WWDT Exported Constants + @{ +*/ +/*---------------------------------------------------------------------------------------------------------*/ +/* WWDT Prescale Period Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define WWDT_PRESCALER_1 (0 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 1 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_2 (1 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 2 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_4 (2 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 4 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_8 (3 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 8 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_16 (4 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 16 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_32 (5 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 32 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_64 (6 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 64 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_128 (7 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 128 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_192 (8 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 192 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_256 (9 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 256 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_384 (10 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 384 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_512 (11 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 512 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_768 (12 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 768 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_1024 (13 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 1024 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_1536 (14 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 1536 * (64*WWDT_CLK) \hideinitializer */ +#define WWDT_PRESCALER_2048 (15 << WWDT_CTL_PSCSEL_Pos) /*!< Select max time-out period to 2048 * (64*WWDT_CLK) \hideinitializer */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* WWDT Reload Counter Keyword Constant Definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define WWDT_RELOAD_WORD (0x00005AA5) /*!< Fill this value to WWDT_RLDCNT register to reload WWDT counter \hideinitializer */ + +/*@}*/ /* end of group WWDT_EXPORTED_CONSTANTS */ + + +/** @addtogroup WWDT_EXPORTED_FUNCTIONS WWDT Exported Functions + @{ +*/ + +/** + * @brief Clear WWDT Reset System Flag + * + * @param None + * + * @return None + * + * @details This macro is used to clear WWDT time-out reset system flag. + * \hideinitializer + */ +#define WWDT_CLEAR_RESET_FLAG() (WWDT->STATUS = WWDT_STATUS_WWDTRF_Msk) + +/** + * @brief Clear WWDT Compared Match Interrupt Flag + * + * @param None + * + * @return None + * + * @details This macro is used to clear WWDT compared match interrupt flag. + * \hideinitializer + */ +#define WWDT_CLEAR_INT_FLAG() (WWDT->STATUS = WWDT_STATUS_WWDTIF_Msk) + +/** + * @brief Get WWDT Reset System Flag + * + * @param None + * + * @retval 0 WWDT time-out reset system did not occur + * @retval 1 WWDT time-out reset system occurred + * + * @details This macro is used to indicate system has been reset by WWDT time-out reset or not. + * \hideinitializer + */ +#define WWDT_GET_RESET_FLAG() ((WWDT->STATUS & WWDT_STATUS_WWDTRF_Msk)? 1 : 0) + +/** + * @brief Get WWDT Compared Match Interrupt Flag + * + * @param None + * + * @retval 0 WWDT compare match interrupt did not occur + * @retval 1 WWDT compare match interrupt occurred + * + * @details This macro is used to indicate WWDT counter value matches CMPDAT value or not. + * \hideinitializer + */ +#define WWDT_GET_INT_FLAG() ((WWDT->STATUS & WWDT_STATUS_WWDTIF_Msk)? 1 : 0) + +/** + * @brief Get WWDT Counter + * + * @param None + * + * @return WWDT Counter Value + * + * @details This macro reflects the current WWDT counter value. + * \hideinitializer + */ +#define WWDT_GET_COUNTER() (WWDT->CNT) + +/** + * @brief Reload WWDT Counter + * + * @param None + * + * @return None + * + * @details This macro is used to reload the WWDT counter value to 0x3F. + * @note User can only write WWDT_RLDCNT register to reload WWDT counter value when current WWDT counter value \n + * between 0 and CMPDAT value. If user writes WWDT_RLDCNT when current WWDT counter value is larger than CMPDAT, \n + * WWDT reset signal will generate immediately to reset system. + * \hideinitializer + */ +#define WWDT_RELOAD_COUNTER() (WWDT->RLDCNT = WWDT_RELOAD_WORD) + +void WWDT_Open(uint32_t u32PreScale, uint32_t u32CmpValue, uint32_t u32EnableInt); + +/*@}*/ /* end of group WWDT_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group WWDT_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +#endif //__NU_WWDT_H__ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.ewd b/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.ewd new file mode 100644 index 0000000000..243a7f2ba5 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.ewd @@ -0,0 +1,2966 @@ + + + 3 + + Release + + ARM + + 0 + + C-SPY + 2 + + 30 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 0 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 0 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 0 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + NULINK_ID + 2 + + 0 + 1 + 0 + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 0 + + + + + + + + STLINK_ID + 2 + + 6 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 0 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 8 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\HWRTOSplugin\HWRTOSplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8BE.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + + Debug + + ARM + + 1 + + C-SPY + 2 + + 30 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 1 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 1 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + NULINK_ID + 2 + + 0 + 1 + 1 + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 1 + + + + + + + + STLINK_ID + 2 + + 6 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 1 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 8 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\HWRTOSplugin\HWRTOSplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8BE.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + diff --git a/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.ewp b/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.ewp new file mode 100644 index 0000000000..53e51392c1 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.ewp @@ -0,0 +1,2152 @@ + + + 3 + + Release + + ARM + + 0 + + General + 3 + + 31 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 35 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 0 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 22 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 0 + + + + + + + BILINK + 0 + + + + + Debug + + ARM + + 1 + + General + 3 + + 31 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 35 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 22 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + + src + + $PROJ_DIR$\..\src\nu_acmp.c + + + $PROJ_DIR$\..\src\nu_adc.c + + + $PROJ_DIR$\..\src\nu_bpwm.c + + + $PROJ_DIR$\..\src\nu_clk.c + + + $PROJ_DIR$\..\src\nu_crc.c + + + $PROJ_DIR$\..\src\nu_ebi.c + + + $PROJ_DIR$\..\src\nu_fmc.c + + + $PROJ_DIR$\..\src\nu_gpio.c + + + $PROJ_DIR$\..\src\nu_i2c.c + + + $PROJ_DIR$\..\src\nu_pdma.c + + + $PROJ_DIR$\..\src\nu_pwm.c + + + $PROJ_DIR$\..\src\nu_qspi.c + + + $PROJ_DIR$\..\src\nu_rtc.c + + + $PROJ_DIR$\..\src\nu_spi.c + + + $PROJ_DIR$\..\src\nu_sys.c + + + $PROJ_DIR$\..\src\nu_timer.c + + + $PROJ_DIR$\..\src\nu_uart.c + + + $PROJ_DIR$\..\src\nu_usbd.c + + + $PROJ_DIR$\..\src\nu_usci_i2c.c + + + $PROJ_DIR$\..\src\nu_usci_spi.c + + + $PROJ_DIR$\..\src\nu_usci_uart.c + + + $PROJ_DIR$\..\src\nu_wdt.c + + + $PROJ_DIR$\..\src\nu_wwdt.c + + + diff --git a/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.eww b/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.eww new file mode 100644 index 0000000000..fcdfcdfe30 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.eww @@ -0,0 +1,10 @@ + + + + + $WS_DIR$\libStdDriver.ewp + + + + + diff --git a/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.uvprojx b/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.uvprojx new file mode 100644 index 0000000000..4bd7f3545a --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/lib/libStdDriver.uvprojx @@ -0,0 +1,513 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + libstddriver-m031 + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::ARMCC + 5060750::V5.06 update 6 (build 750)::ARMCC + 0 + + + M032KIAAE + Nuvoton + Nuvoton.NuMicro_DFP.1.3.10 + http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack + IRAM(0x20000000,0x18000) IROM(0x00000000,0x80000) CPUTYPE("Cortex-M0") CLOCK(12000000) + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0M031_AP_512 -FS00 -FL080000 -FP0($$Device:M032KIAAE$Flash\M031_AP_512.FLM)) + 0 + $$Device:M032KIAAE$Device\M031\Include\M031Series.h + + + + + + + + + + $$Device:M032KIAAE$SVD\Nuvoton\M031AE_v1.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\keil5\ + libstddriver_keil + 0 + 1 + 1 + 1 + 1 + .\build\keil5\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + xcopy /y ".\build\keil5\@L.lib" "." + + 0 + 0 + 0 + 0 + + 1 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + + DARMCM1.DLL + -pCM0 + SARMCM3.DLL + + TARMCM1.DLL + -pCM0 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M0" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x0 + 0x80000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x80000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 5 + 3 + 0 + 0 + 0 + 1 + 0 + + + + + ..\inc;..\..\CMSIS\Include;..\..\Device\Nuvoton\M031\Include;. + + + + 1 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x00000000 + 0x20000000 + + + + + + + + + + + + + src + + + nu_acmp.c + 1 + ..\src\nu_acmp.c + + + nu_adc.c + 1 + ..\src\nu_adc.c + + + nu_bpwm.c + 1 + ..\src\nu_bpwm.c + + + nu_clk.c + 1 + ..\src\nu_clk.c + + + nu_crc.c + 1 + ..\src\nu_crc.c + + + nu_ebi.c + 1 + ..\src\nu_ebi.c + + + nu_fmc.c + 1 + ..\src\nu_fmc.c + + + nu_gpio.c + 1 + ..\src\nu_gpio.c + + + nu_i2c.c + 1 + ..\src\nu_i2c.c + + + nu_pdma.c + 1 + ..\src\nu_pdma.c + + + nu_pwm.c + 1 + ..\src\nu_pwm.c + + + nu_qspi.c + 1 + ..\src\nu_qspi.c + + + nu_rtc.c + 1 + ..\src\nu_rtc.c + + + nu_spi.c + 1 + ..\src\nu_spi.c + + + nu_sys.c + 1 + ..\src\nu_sys.c + + + nu_timer.c + 1 + ..\src\nu_timer.c + + + nu_uart.c + 1 + ..\src\nu_uart.c + + + nu_usbd.c + 1 + ..\src\nu_usbd.c + + + nu_usci_i2c.c + 1 + ..\src\nu_usci_i2c.c + + + nu_usci_spi.c + 1 + ..\src\nu_usci_spi.c + + + nu_usci_uart.c + 1 + ..\src\nu_usci_uart.c + + + nu_wdt.c + 1 + ..\src\nu_wdt.c + + + nu_wwdt.c + 1 + ..\src\nu_wwdt.c + + + + + + + + + + + + + +
diff --git a/bsp/nuvoton/libraries/m031/StdDriver/lib/nutool_clkcfg.h b/bsp/nuvoton/libraries/m031/StdDriver/lib/nutool_clkcfg.h new file mode 100644 index 0000000000..3a712eee97 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/lib/nutool_clkcfg.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * @file nutool_clkcfg.h + * @version V1.05 + * @Date 2020/09/15-18:09:27 + * @brief NuMicro generated code file + * + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2013-2020 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NUTOOL_CLKCFG_H__ +#define __NUTOOL_CLKCFG_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif +#undef __HXT +#define __HXT (32000000UL) /*!< High Speed External Crystal Clock Frequency */ + +#ifdef __cplusplus +} +#endif +#endif /*__NUTOOL_CLKCFG_H__*/ + +/*** (C) COPYRIGHT 2013-2020 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_acmp.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_acmp.c new file mode 100644 index 0000000000..9568bbed07 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_acmp.c @@ -0,0 +1,82 @@ +/**************************************************************************//** + * @file acmp.c + * @version V3.00 + * $Revision: 3 $ + * $Date: 18/03/16 11:13a $ + * @brief M031 Series Analog Comparator(ACMP) Driver Source File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#include "M031Series.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup ACMP_Driver ACMP Driver + @{ +*/ + + +/** @addtogroup ACMP_EXPORTED_FUNCTIONS ACMP Exported Functions + @{ +*/ + + +/** + * @brief Configure the specified ACMP module + * + * @param[in] Acmp The pointer of the specified ACMP module + * @param[in] u32ChNum Comparator number. + * @param[in] u32NegSrc Comparator negative input selection. Including: + * - \ref ACMP_CTL_NEGSEL_PIN + * - \ref ACMP_CTL_NEGSEL_CRV + * - \ref ACMP_CTL_NEGSEL_VBG + * @param[in] u32HysteresisEn The hysteresis function option. Including: + * - \ref ACMP_CTL_HYSTERESIS_ENABLE + * - \ref ACMP_CTL_HYSTERESIS_DISABLE + * + * @return None + * + * @details Configure hysteresis function, select the source of negative input and enable analog comparator. + */ +void ACMP_Open(ACMP_T *Acmp, uint32_t u32ChNum, uint32_t u32NegSrc, uint32_t u32HysteresisEn) +{ + Acmp->CTL[u32ChNum] = (Acmp->CTL[u32ChNum] & (~(ACMP_CTL_NEGSEL_Msk | ACMP_CTL_HYSEN_Msk))) | (u32NegSrc | u32HysteresisEn | ACMP_CTL_ACMPEN_Msk); +} + +/** + * @brief Close analog comparator + * + * @param[in] Acmp The pointer of the specified ACMP module + * @param[in] u32ChNum Comparator number. + * + * @return None + * + * @details This function will clear ACMPEN bit of ACMP_CTL register to disable analog comparator. + */ +void ACMP_Close(ACMP_T *Acmp, uint32_t u32ChNum) +{ + Acmp->CTL[u32ChNum] &= (~ACMP_CTL_ACMPEN_Msk); +} + + + +/*@}*/ /* end of group ACMP_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group ACMP_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_adc.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_adc.c new file mode 100644 index 0000000000..508589cec8 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_adc.c @@ -0,0 +1,200 @@ +/**************************************************************************//** + * @file adc.c + * @version V3.00 + * $Revision: 7 $ + * $Date: 18/07/24 2:17p $ + * @brief M031 Series ADC Driver Source File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#include "M031Series.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup ADC_Driver ADC Driver + @{ +*/ + +/** @addtogroup ADC_EXPORTED_FUNCTIONS ADC Exported Functions + @{ +*/ + +/** + * @brief This API configures ADC module to be ready for convert the input from selected channel + * @param[in] adc The pointer of the specified ADC module + * @param[in] u32InputMode Decides the ADC analog input mode. Valid values are: + * - \ref ADC_ADCR_DIFFEN_SINGLE_END :Single-end input mode + * - \ref ADC_ADCR_DIFFEN_DIFFERENTIAL :Differential input mode + * @param[in] u32OpMode Decides the ADC operation mode. Valid values are: + * - \ref ADC_ADCR_ADMD_SINGLE :Single mode. + * - \ref ADC_ADCR_ADMD_BURST :Burst mode. + * - \ref ADC_ADCR_ADMD_SINGLE_CYCLE :Single cycle scan mode. + * - \ref ADC_ADCR_ADMD_CONTINUOUS :Continuous scan mode. + * @param[in] u32ChMask Channel enable bit. Each bit corresponds to a input channel. Bit 0 is channel 0, bit 1 is channel 1..., bit 15 is channel 15. + * @return None + * @note M031 series MCU ADC can only convert 1 channel at a time. If more than 1 channels are enabled, only channel + * with smallest number will be convert. + * @note This API does not turn on ADC power nor does trigger ADC conversion. + * @note This API will reset and calibrate ADC if ADC never be calibrated after chip power on. + */ +void ADC_Open(ADC_T *adc, + uint32_t u32InputMode, + uint32_t u32OpMode, + uint32_t u32ChMask) +{ + /* Do calibration for ADC to decrease the effect of electrical random noise. */ + if ((adc->ADCALSTSR & ADC_ADCALSTSR_CALIF_Msk) == 0) + { + /* Must reset ADC before ADC calibration */ + adc->ADCR |= ADC_ADCR_RESET_Msk; + while((adc->ADCR & ADC_ADCR_RESET_Msk) == ADC_ADCR_RESET_Msk); + + adc->ADCALSTSR |= ADC_ADCALSTSR_CALIF_Msk; /* Clear Calibration Finish Interrupt Flag */ + adc->ADCALR |= ADC_ADCALR_CALEN_Msk; /* Enable Calibration function */ + ADC_START_CONV(adc); /* Start to calibration */ + while((adc->ADCALSTSR & ADC_ADCALSTSR_CALIF_Msk) != ADC_ADCALSTSR_CALIF_Msk); /* Wait calibration finish */ + } + + adc->ADCR = (adc->ADCR & (~(ADC_ADCR_DIFFEN_Msk | ADC_ADCR_ADMD_Msk))) | \ + (u32InputMode) | \ + (u32OpMode); + + adc->ADCHER = (adc->ADCHER & ~ADC_ADCHER_CHEN_Msk) | (u32ChMask); + + return; +} + +/** + * @brief Disable ADC module + * @param[in] adc The pointer of the specified ADC module + * @return None + */ +void ADC_Close(ADC_T *adc) +{ + SYS->IPRST1 |= SYS_IPRST1_ADCRST_Msk; + SYS->IPRST1 &= ~SYS_IPRST1_ADCRST_Msk; + return; +} + +/** + * @brief Configure the hardware trigger condition and enable hardware trigger + * @param[in] adc The pointer of the specified ADC module + * @param[in] u32Source Decides the hardware trigger source. Valid values are: + * - \ref ADC_ADCR_TRGS_STADC :A/D conversion is started by external STADC pin. + * - \ref ADC_ADCR_TRGS_TIMER :A/D conversion is started by Timer. + * - \ref ADC_ADCR_TRGS_PWM :A/D conversion is started by PWM. + * @param[in] u32Param While ADC trigger by PWM or Timer, this parameter is unused. + * While ADC trigger by external pin, this parameter is used to set trigger condition. + * Valid values are: + * - \ref ADC_ADCR_TRGCOND_LOW_LEVEL :STADC Low level active + * - \ref ADC_ADCR_TRGCOND_HIGH_LEVEL :STADC High level active + * - \ref ADC_ADCR_TRGCOND_FALLING_EDGE :STADC Falling edge active + * - \ref ADC_ADCR_TRGCOND_RISING_EDGE :STADC Rising edge active + * @return None + * @note Software should disable TRGEN (ADCR[8]) and ADST (ADCR[11]) before change TRGS(ADCR[5:4]). + */ +void ADC_EnableHWTrigger(ADC_T *adc, + uint32_t u32Source, + uint32_t u32Param) +{ + if(u32Source == ADC_ADCR_TRGS_STADC) + { + adc->ADCR = (adc->ADCR & ~(ADC_ADCR_TRGS_Msk | ADC_ADCR_TRGCOND_Msk | ADC_ADCR_TRGEN_Msk)) | + ((u32Source) | (u32Param) | ADC_ADCR_TRGEN_Msk); + } + else if(u32Source == ADC_ADCR_TRGS_TIMER) + { + adc->ADCR = (adc->ADCR & ~(ADC_ADCR_TRGS_Msk | ADC_ADCR_TRGCOND_Msk | ADC_ADCR_TRGEN_Msk)) | + ((u32Source) | ADC_ADCR_TRGEN_Msk); + } + else + { + adc->ADCR = (adc->ADCR & ~(ADC_ADCR_TRGS_Msk | ADC_ADCR_TRGCOND_Msk | ADC_ADCR_TRGEN_Msk)) | + ((u32Source) | ADC_ADCR_TRGEN_Msk); + } + return; +} + +/** + * @brief Disable hardware trigger ADC function. + * @param[in] adc The pointer of the specified ADC module + * @return None + */ +void ADC_DisableHWTrigger(ADC_T *adc) +{ + adc->ADCR &= ~(ADC_ADCR_TRGS_Msk | ADC_ADCR_TRGCOND_Msk | ADC_ADCR_TRGEN_Msk); + return; +} + +/** + * @brief Enable the interrupt(s) selected by u32Mask parameter. + * @param[in] adc The pointer of the specified ADC module + * @param[in] u32Mask The combination of interrupt status bits listed below. Each bit + * corresponds to a interrupt status. This parameter decides which + * interrupts will be enabled. + * - \ref ADC_ADF_INT :ADC convert complete interrupt + * - \ref ADC_CMP0_INT :ADC comparator 0 interrupt + * - \ref ADC_CMP1_INT :ADC comparator 1 interrupt + * @return None + */ +void ADC_EnableInt(ADC_T *adc, uint32_t u32Mask) +{ + if((u32Mask) & ADC_ADF_INT) + adc->ADCR |= ADC_ADCR_ADIE_Msk; + if((u32Mask) & ADC_CMP0_INT) + adc->ADCMPR[0] |= ADC_ADCMPR_CMPIE_Msk; + if((u32Mask) & ADC_CMP1_INT) + adc->ADCMPR[1] |= ADC_ADCMPR_CMPIE_Msk; + + return; +} + +/** + * @brief Disable the interrupt(s) selected by u32Mask parameter. + * @param[in] adc The pointer of the specified ADC module + * @param[in] u32Mask The combination of interrupt status bits listed below. Each bit + * corresponds to a interrupt status. This parameter decides which + * interrupts will be disabled. + * - \ref ADC_ADF_INT :ADC convert complete interrupt + * - \ref ADC_CMP0_INT :ADC comparator 0 interrupt + * - \ref ADC_CMP1_INT :ADC comparator 1 interrupt + * @return None + */ +void ADC_DisableInt(ADC_T *adc, uint32_t u32Mask) +{ + if((u32Mask) & ADC_ADF_INT) + adc->ADCR &= ~ADC_ADCR_ADIE_Msk; + if((u32Mask) & ADC_CMP0_INT) + adc->ADCMPR[0] &= ~ADC_ADCMPR_CMPIE_Msk; + if((u32Mask) & ADC_CMP1_INT) + adc->ADCMPR[1] &= ~ADC_ADCMPR_CMPIE_Msk; + + return; +} + +/** + * @brief Set ADC extend sample time. + * @param[in] adc The pointer of the specified ADC module. + * @param[in] u32ModuleNum Decides the sample module number, valid value are 0. + * @param[in] u32ExtendSampleTime Decides the extend sampling time, the range is from 0~255 ADC clock. Valid value are from 0 to 0xFF. + * @return None + * @details When A/D converting at high conversion rate, the sampling time of analog input voltage may not enough if input channel loading is heavy, + * user can extend A/D sampling time after trigger source is coming to get enough sampling time. + */ +void ADC_SetExtendSampleTime(ADC_T *adc, uint32_t u32ModuleNum, uint32_t u32ExtendSampleTime) +{ + adc->ESMPCTL = (adc->ESMPCTL & ~ADC_ESMPCTL_EXTSMPT_Msk) | + (u32ExtendSampleTime << ADC_ESMPCTL_EXTSMPT_Pos); +} + +/*@}*/ /* end of group ADC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group ADC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_bpwm.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_bpwm.c new file mode 100644 index 0000000000..3e27ebb915 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_bpwm.c @@ -0,0 +1,751 @@ +/**************************************************************************//** + * @file bpwm.c + * @version V1.00 + * $Revision: 4 $ + * $Date: 18/04/24 3:49p $ + * @brief M031 series BPWM driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "NuMicro.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup BPWM_Driver BPWM Driver + @{ +*/ + + +/** @addtogroup BPWM_EXPORTED_FUNCTIONS BPWM Exported Functions + @{ +*/ + +/** + * @brief Configure BPWM capture and get the nearest unit time. + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @param[in] u32UnitTimeNsec The unit time of counter + * @param[in] u32CaptureEdge The condition to latch the counter. This parameter is not used + * @return The nearest unit time in nano second. + * @details This function is used to Configure BPWM capture and get the nearest unit time. + */ +uint32_t BPWM_ConfigCaptureChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32UnitTimeNsec, uint32_t u32CaptureEdge) +{ + uint32_t u32Src; + uint32_t u32BPWMClockSrc; + uint32_t u32NearestUnitTimeNsec; + uint16_t u16Prescale = 1UL, u16CNR = 0xFFFFUL; + uint8_t u8BreakLoop = 0UL; + + if (bpwm == BPWM0) + { + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM0SEL_Msk; + } + else /* (bpwm == BPWM1) */ + { + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM1SEL_Msk; + } + + if (u32Src == 0UL) + { + //clock source is from PLL clock + u32BPWMClockSrc = CLK_GetPLLClockFreq(); + } + else + { + //clock source is from PCLK + SystemCoreClockUpdate(); + + if (bpwm == BPWM0) + { + u32BPWMClockSrc = CLK_GetPCLK0Freq(); + } + else /* (bpwm == BPWM1) */ + { + u32BPWMClockSrc = CLK_GetPCLK1Freq(); + } + } + + u32BPWMClockSrc /= 1000UL; + + for (u16Prescale = 1UL; u16Prescale <= 0x1000UL; u16Prescale++) + { + u32NearestUnitTimeNsec = (1000000UL * u16Prescale) / u32BPWMClockSrc; + + if (u32NearestUnitTimeNsec < u32UnitTimeNsec) + { + if (u16Prescale == 0x1000UL) + { + /* limit to the maximum unit time(nano second) */ + u8BreakLoop = 1UL; + } + + if (!((1000000UL * (u16Prescale + 1UL) > (u32NearestUnitTimeNsec * u32BPWMClockSrc)))) + { + u8BreakLoop = 1UL; + } + } + else + { + u8BreakLoop = 1UL; + } + + if (u8BreakLoop) + { + break; + } + } + + // convert to real register value + u16Prescale = u16Prescale - 1UL; + // all channels share a prescaler + BPWM_SET_PRESCALER(bpwm, u32ChannelNum, (uint32_t)u16Prescale); + + // set BPWM to down count type(edge aligned) + (bpwm)->CTL1 = BPWM_DOWN_COUNTER; + + BPWM_SET_CNR(bpwm, u32ChannelNum, u16CNR); + + return (u32NearestUnitTimeNsec); +} + +/** + * @brief This function Configure BPWM generator and get the nearest frequency in edge aligned(down countertype) auto-reload mode + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @param[in] u32Frequency Target generator frequency + * @param[in] u32DutyCycle Target generator duty cycle percentage. Valid range are between 0 ~ 100. 10 means 10%, 20 means 20%... + * @return Nearest frequency clock in nano second + * @note Since all channels shares a prescaler. Call this API to configure BPWM frequency may affect + * existing frequency of other channel. + */ +uint32_t BPWM_ConfigOutputChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Frequency, uint32_t u32DutyCycle) +{ + uint32_t u32Src; + uint32_t u32BPWMClockSrc; + uint32_t i; + uint16_t u16Prescale = 1UL, u16CNR = 0xFFFFUL; + + if (bpwm == BPWM0) + { + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM0SEL_Msk; + } + else /* (bpwm == BPWM1) */ + { + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM1SEL_Msk; + } + + if (u32Src == 0UL) + { + //clock source is from PLL clock + u32BPWMClockSrc = CLK_GetPLLClockFreq(); + } + else + { + //clock source is from PCLK + SystemCoreClockUpdate(); + + if (bpwm == BPWM0) + { + u32BPWMClockSrc = CLK_GetPCLK0Freq(); + } + else /* (bpwm == BPWM1) */ + { + u32BPWMClockSrc = CLK_GetPCLK1Freq(); + } + } + + for (u16Prescale = 1UL; u16Prescale < 0xFFFUL; u16Prescale++) //prescale could be 0~0xFFF + { + i = (u32BPWMClockSrc / u32Frequency) / u16Prescale; + + // If target value is larger than CNR, need to use a larger prescaler + if (i <= (0x10000UL)) + { + u16CNR = (uint16_t)i; + break; + } + } + + // Store return value here 'cos we're gonna change u16Prescale & u16CNR to the real value to fill into register + i = u32BPWMClockSrc / ((uint32_t)u16Prescale * (uint32_t)u16CNR); + + // convert to real register value + u16Prescale = u16Prescale - 1UL; + // all channels share a prescaler + BPWM_SET_PRESCALER(bpwm, u32ChannelNum, (uint32_t)u16Prescale); + // set BPWM to down count type + (bpwm)->CTL1 = BPWM_DOWN_COUNTER; + + u16CNR = u16CNR - 1UL; + BPWM_SET_CNR(bpwm, u32ChannelNum, u16CNR); + + if (u32DutyCycle) + { + if (u32DutyCycle >= 100UL) + BPWM_SET_CMR(bpwm, u32ChannelNum, u16CNR); + else + BPWM_SET_CMR(bpwm, u32ChannelNum, u32DutyCycle * (u16CNR + 1UL) / 100UL); + + (bpwm)->WGCTL0 &= ~((BPWM_WGCTL0_PRDPCTL0_Msk | BPWM_WGCTL0_ZPCTL0_Msk) << (u32ChannelNum << 1UL)); + (bpwm)->WGCTL0 |= (BPWM_OUTPUT_LOW << ((u32ChannelNum << 1UL) + BPWM_WGCTL0_PRDPCTL0_Pos)); + (bpwm)->WGCTL1 &= ~((BPWM_WGCTL1_CMPDCTL0_Msk | BPWM_WGCTL1_CMPUCTL0_Msk) << (u32ChannelNum << 1UL)); + (bpwm)->WGCTL1 |= (BPWM_OUTPUT_HIGH << ((u32ChannelNum << 1UL) + BPWM_WGCTL1_CMPDCTL0_Pos)); + } + else + { + BPWM_SET_CMR(bpwm, u32ChannelNum, 0UL); + (bpwm)->WGCTL0 &= ~((BPWM_WGCTL0_PRDPCTL0_Msk | BPWM_WGCTL0_ZPCTL0_Msk) << (u32ChannelNum << 1UL)); + (bpwm)->WGCTL0 |= (BPWM_OUTPUT_LOW << ((u32ChannelNum << 1UL) + BPWM_WGCTL0_ZPCTL0_Pos)); + (bpwm)->WGCTL1 &= ~((BPWM_WGCTL1_CMPDCTL0_Msk | BPWM_WGCTL1_CMPUCTL0_Msk) << (u32ChannelNum << 1UL)); + (bpwm)->WGCTL1 |= (BPWM_OUTPUT_HIGH << ((u32ChannelNum << 1UL) + BPWM_WGCTL1_CMPDCTL0_Pos)); + } + + return (i); +} + +/** + * @brief Start BPWM module + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used. + * @return None + * @details This function is used to start BPWM module. + * @note All channels share one counter. + */ +void BPWM_Start(BPWM_T *bpwm, uint32_t u32ChannelMask) +{ + (bpwm)->CNTEN = BPWM_CNTEN_CNTEN0_Msk; +} + +/** + * @brief Stop BPWM module + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used. + * @return None + * @details This function is used to stop BPWM module. + * @note All channels share one period. + */ +void BPWM_Stop(BPWM_T *bpwm, uint32_t u32ChannelMask) +{ + (bpwm)->PERIOD = 0UL; +} + +/** + * @brief Stop BPWM generation immediately by clear channel enable bit + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used. + * @return None + * @details This function is used to stop BPWM generation immediately by clear channel enable bit. + * @note All channels share one counter. + */ +void BPWM_ForceStop(BPWM_T *bpwm, uint32_t u32ChannelMask) +{ + (bpwm)->CNTEN &= ~BPWM_CNTEN_CNTEN0_Msk; +} + +/** + * @brief Enable selected channel to trigger ADC + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @param[in] u32Condition The condition to trigger ADC. Combination of following conditions: + * - \ref BPWM_TRIGGER_ADC_EVEN_ZERO_POINT + * - \ref BPWM_TRIGGER_ADC_EVEN_PERIOD_POINT + * - \ref BPWM_TRIGGER_ADC_EVEN_ZERO_OR_PERIOD_POINT + * - \ref BPWM_TRIGGER_ADC_EVEN_CMP_UP_COUNT_POINT + * - \ref BPWM_TRIGGER_ADC_EVEN_CMP_DOWN_COUNT_POINT + * - \ref BPWM_TRIGGER_ADC_ODD_CMP_UP_COUNT_POINT + * - \ref BPWM_TRIGGER_ADC_ODD_CMP_DOWN_COUNT_POINT + * @return None + * @details This function is used to enable selected channel to trigger ADC + */ +void BPWM_EnableADCTrigger(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Condition) +{ + if (u32ChannelNum < 4UL) + { + (bpwm)->EADCTS0 &= ~((BPWM_EADCTS0_TRGSEL0_Msk) << (u32ChannelNum << 3UL)); + (bpwm)->EADCTS0 |= ((BPWM_EADCTS0_TRGEN0_Msk | u32Condition) << (u32ChannelNum << 3UL)); + } + else + { + (bpwm)->EADCTS1 &= ~((BPWM_EADCTS1_TRGSEL4_Msk) << ((u32ChannelNum - 4UL) << 3UL)); + (bpwm)->EADCTS1 |= ((BPWM_EADCTS1_TRGEN4_Msk | u32Condition) << ((u32ChannelNum - 4UL) << 3UL)); + } +} + +/** + * @brief Disable selected channel to trigger ADC + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @return None + * @details This function is used to disable selected channel to trigger ADC + */ +void BPWM_DisableADCTrigger(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + if (u32ChannelNum < 4UL) + { + (bpwm)->EADCTS0 &= ~(BPWM_EADCTS0_TRGEN0_Msk << (u32ChannelNum << 3UL)); + } + else + { + (bpwm)->EADCTS1 &= ~(BPWM_EADCTS1_TRGEN4_Msk << ((u32ChannelNum - 4UL) << 3UL)); + } +} + +/** + * @brief Clear selected channel trigger ADC flag + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @param[in] u32Condition This parameter is not used + * @return None + * @details This function is used to clear selected channel trigger ADC flag + */ +void BPWM_ClearADCTriggerFlag(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Condition) +{ + (bpwm)->STATUS = (BPWM_STATUS_EADCTRG0_Msk << u32ChannelNum); +} + +/** + * @brief Get selected channel trigger ADC flag + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @retval 0 The specified channel trigger ADC to start of conversion flag is not set + * @retval 1 The specified channel trigger ADC to start of conversion flag is set + * @details This function is used to get BPWM trigger ADC to start of conversion flag for specified channel + */ +uint32_t BPWM_GetADCTriggerFlag(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + return (((bpwm)->STATUS & (BPWM_STATUS_EADCTRG0_Msk << u32ChannelNum)) ? 1UL : 0UL); +} + +/** + * @brief Enable capture of selected channel(s) + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. + * Bit 0 is channel 0, bit 1 is channel 1... + * @return None + * @details This function is used to enable capture of selected channel(s) + */ +void BPWM_EnableCapture(BPWM_T *bpwm, uint32_t u32ChannelMask) +{ + (bpwm)->CAPINEN |= u32ChannelMask; + (bpwm)->CAPCTL |= u32ChannelMask; +} + +/** + * @brief Disable capture of selected channel(s) + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. + * Bit 0 is channel 0, bit 1 is channel 1... + * @return None + * @details This function is used to disable capture of selected channel(s) + */ +void BPWM_DisableCapture(BPWM_T *bpwm, uint32_t u32ChannelMask) +{ + (bpwm)->CAPINEN &= ~u32ChannelMask; + (bpwm)->CAPCTL &= ~u32ChannelMask; +} + +/** + * @brief Enables BPWM output generation of selected channel(s) + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. + * Set bit 0 to 1 enables channel 0 output, set bit 1 to 1 enables channel 1 output... + * @return None + * @details This function is used to enables BPWM output generation of selected channel(s) + */ +void BPWM_EnableOutput(BPWM_T *bpwm, uint32_t u32ChannelMask) +{ + (bpwm)->POEN |= u32ChannelMask; +} + +/** + * @brief Disables BPWM output generation of selected channel(s) + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Set bit 0 to 1 disables channel 0 output, set bit 1 to 1 disables channel 1 output... + * @return None + * @details This function is used to disables BPWM output generation of selected channel(s) + */ +void BPWM_DisableOutput(BPWM_T *bpwm, uint32_t u32ChannelMask) +{ + (bpwm)->POEN &= ~u32ChannelMask; +} + +/** + * @brief Enable capture interrupt of selected channel. + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @param[in] u32Edge Rising or falling edge to latch counter. + * - \ref BPWM_CAPTURE_INT_RISING_LATCH + * - \ref BPWM_CAPTURE_INT_FALLING_LATCH + * @return None + * @details This function is used to enable capture interrupt of selected channel. + */ +void BPWM_EnableCaptureInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge) +{ + (bpwm)->CAPIEN |= (u32Edge << u32ChannelNum); +} + +/** + * @brief Disable capture interrupt of selected channel. + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @param[in] u32Edge Rising or falling edge to latch counter. + * - \ref BPWM_CAPTURE_INT_RISING_LATCH + * - \ref BPWM_CAPTURE_INT_FALLING_LATCH + * @return None + * @details This function is used to disable capture interrupt of selected channel. + */ +void BPWM_DisableCaptureInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge) +{ + (bpwm)->CAPIEN &= ~(u32Edge << u32ChannelNum); +} + +/** + * @brief Clear capture interrupt of selected channel. + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @param[in] u32Edge Rising or falling edge to latch counter. + * - \ref BPWM_CAPTURE_INT_RISING_LATCH + * - \ref BPWM_CAPTURE_INT_FALLING_LATCH + * @return None + * @details This function is used to clear capture interrupt of selected channel. + */ +void BPWM_ClearCaptureIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge) +{ + (bpwm)->CAPIF = (u32Edge << u32ChannelNum); +} + +/** + * @brief Get capture interrupt of selected channel. + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @retval 0 No capture interrupt + * @retval 1 Rising edge latch interrupt + * @retval 2 Falling edge latch interrupt + * @retval 3 Rising and falling latch interrupt + * @details This function is used to get capture interrupt of selected channel. + */ +uint32_t BPWM_GetCaptureIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + return (((((bpwm)->CAPIF & (BPWM_CAPIF_CAPFIF0_Msk << u32ChannelNum)) ? 1UL : 0UL) << 1UL) | \ + (((bpwm)->CAPIF & (BPWM_CAPIF_CAPRIF0_Msk << u32ChannelNum)) ? 1UL : 0UL)); +} +/** + * @brief Enable duty interrupt of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @param[in] u32IntDutyType Duty interrupt type, could be either + * - \ref BPWM_DUTY_INT_DOWN_COUNT_MATCH_CMP + * - \ref BPWM_DUTY_INT_UP_COUNT_MATCH_CMP + * @return None + * @details This function is used to enable duty interrupt of selected channel. + */ +void BPWM_EnableDutyInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType) +{ + (bpwm)->INTEN |= (u32IntDutyType << u32ChannelNum); +} + +/** + * @brief Disable duty interrupt of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @return None + * @details This function is used to disable duty interrupt of selected channel + */ +void BPWM_DisableDutyInt(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + (bpwm)->INTEN &= ~((uint32_t)(BPWM_DUTY_INT_DOWN_COUNT_MATCH_CMP | BPWM_DUTY_INT_UP_COUNT_MATCH_CMP) << u32ChannelNum); +} + +/** + * @brief Clear duty interrupt flag of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @return None + * @details This function is used to clear duty interrupt flag of selected channel + */ +void BPWM_ClearDutyIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + (bpwm)->INTSTS = (BPWM_INTSTS_CMPUIF0_Msk | BPWM_INTSTS_CMPDIF0_Msk) << u32ChannelNum; +} + +/** + * @brief Get duty interrupt flag of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @return Duty interrupt flag of specified channel + * @retval 0 Duty interrupt did not occur + * @retval 1 Duty interrupt occurred + * @details This function is used to get duty interrupt flag of selected channel + */ +uint32_t BPWM_GetDutyIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + return ((((bpwm)->INTSTS & ((BPWM_INTSTS_CMPDIF0_Msk | BPWM_INTSTS_CMPUIF0_Msk) << u32ChannelNum))) ? 1UL : 0UL); +} + +/** + * @brief Enable period interrupt of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @param[in] u32IntPeriodType Period interrupt type. This parameter is not used. + * @return None + * @details This function is used to enable period interrupt of selected channel. + * @note All channels share channel 0's setting. + */ +void BPWM_EnablePeriodInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType) +{ + (bpwm)->INTEN |= BPWM_INTEN_PIEN0_Msk; +} + +/** + * @brief Disable period interrupt of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @return None + * @details This function is used to disable period interrupt of selected channel. + * @note All channels share channel 0's setting. + */ +void BPWM_DisablePeriodInt(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + (bpwm)->INTEN &= ~BPWM_INTEN_PIEN0_Msk; +} + +/** + * @brief Clear period interrupt of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @return None + * @details This function is used to clear period interrupt of selected channel + * @note All channels share channel 0's setting. + */ +void BPWM_ClearPeriodIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + (bpwm)->INTSTS = BPWM_INTSTS_PIF0_Msk; +} + +/** + * @brief Get period interrupt of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @return Period interrupt flag of specified channel + * @retval 0 Period interrupt did not occur + * @retval 1 Period interrupt occurred + * @details This function is used to get period interrupt of selected channel + * @note All channels share channel 0's setting. + */ +uint32_t BPWM_GetPeriodIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + return (((bpwm)->INTSTS & BPWM_INTSTS_PIF0_Msk) ? 1UL : 0UL); +} + +/** + * @brief Enable zero interrupt of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @return None + * @details This function is used to enable zero interrupt of selected channel. + * @note All channels share channel 0's setting. + */ +void BPWM_EnableZeroInt(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + (bpwm)->INTEN |= BPWM_INTEN_ZIEN0_Msk; +} + +/** + * @brief Disable zero interrupt of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @return None + * @details This function is used to disable zero interrupt of selected channel. + * @note All channels share channel 0's setting. + */ +void BPWM_DisableZeroInt(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + (bpwm)->INTEN &= ~BPWM_INTEN_ZIEN0_Msk; +} + +/** + * @brief Clear zero interrupt of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @return None + * @details This function is used to clear zero interrupt of selected channel. + * @note All channels share channel 0's setting. + */ +void BPWM_ClearZeroIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + (bpwm)->INTSTS = BPWM_INTSTS_ZIF0_Msk; +} + +/** + * @brief Get zero interrupt of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @return zero interrupt flag of specified channel + * @retval 0 zero interrupt did not occur + * @retval 1 zero interrupt occurred + * @details This function is used to get zero interrupt of selected channel. + * @note All channels share channel 0's setting. + */ +uint32_t BPWM_GetZeroIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + return (((bpwm)->INTSTS & BPWM_INTSTS_ZIF0_Msk) ? 1UL : 0UL); +} + +/** + * @brief Enable load mode of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @param[in] u32LoadMode BPWM counter loading mode. + * - \ref BPWM_LOAD_MODE_IMMEDIATE + * - \ref BPWM_LOAD_MODE_CENTER + * @return None + * @details This function is used to enable load mode of selected channel. + */ +void BPWM_EnableLoadMode(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32LoadMode) +{ + (bpwm)->CTL0 |= (u32LoadMode << u32ChannelNum); +} + +/** + * @brief Disable load mode of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 + * @param[in] u32LoadMode BPWM counter loading mode. + * - \ref BPWM_LOAD_MODE_IMMEDIATE + * - \ref BPWM_LOAD_MODE_CENTER + * @return None + * @details This function is used to disable load mode of selected channel. + */ +void BPWM_DisableLoadMode(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32LoadMode) +{ + (bpwm)->CTL0 &= ~(u32LoadMode << u32ChannelNum); +} + +/** + * @brief Set BPWM clock source + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @param[in] u32ClkSrcSel BPWM external clock source. + * - \ref BPWM_CLKSRC_BPWM_CLK + * - \ref BPWM_CLKSRC_TIMER0 + * - \ref BPWM_CLKSRC_TIMER1 + * - \ref BPWM_CLKSRC_TIMER2 + * - \ref BPWM_CLKSRC_TIMER3 + * @return None + * @details This function is used to set BPWM clock source. + * @note All channels share channel 0's setting. + */ +void BPWM_SetClockSource(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32ClkSrcSel) +{ + (bpwm)->CLKSRC = (u32ClkSrcSel); +} + +/** + * @brief Get the time-base counter reached its maximum value flag of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @return Count to max interrupt flag of specified channel + * @retval 0 Count to max interrupt did not occur + * @retval 1 Count to max interrupt occurred + * @details This function is used to get the time-base counter reached its maximum value flag of selected channel. + * @note All channels share channel 0's setting. + */ +uint32_t BPWM_GetWrapAroundFlag(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + return (((bpwm)->STATUS & BPWM_STATUS_CNTMAX0_Msk) ? 1UL : 0UL); +} + +/** + * @brief Clear the time-base counter reached its maximum value flag of selected channel + * @param[in] bpwm The pointer of the specified BPWM module + * - BPWM0 : BPWM Group 0 + * - BPWM1 : BPWM Group 1 + * @param[in] u32ChannelNum BPWM channel number. This parameter is not used. + * @return None + * @details This function is used to clear the time-base counter reached its maximum value flag of selected channel. + * @note All channels share channel 0's setting. + */ +void BPWM_ClearWrapAroundFlag(BPWM_T *bpwm, uint32_t u32ChannelNum) +{ + (bpwm)->STATUS = BPWM_STATUS_CNTMAX0_Msk; +} + + +/*@}*/ /* end of group BPWM_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group BPWM_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_clk.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_clk.c new file mode 100644 index 0000000000..25c0519082 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_clk.c @@ -0,0 +1,836 @@ +/**************************************************************************//** + * @file clk.c + * @version V3.00 + * $Revision: 6 $ + * $Date: 18/07/05 4:42p $ + * @brief M031 Series Clock Controller (CLK) Driver Source File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#include "M031Series.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup CLK_Driver CLK Driver + @{ +*/ + +/** @addtogroup CLK_EXPORTED_FUNCTIONS CLK Exported Functions + @{ +*/ + +/** + * @brief Disable frequency output function + * @param None + * @return None + * @details This function disable frequency output function. + */ +void CLK_DisableCKO(void) +{ + /* Disable CKO clock source */ + CLK->APBCLK0 &= (~CLK_APBCLK0_CLKOCKEN_Msk); +} + +/** + * @brief This function enable frequency output function and + * configure frequency clock source and divider. + * @param[in] u32ClkSrc is frequency output function clock source. Including : + * - \ref CLK_CLKSEL1_CLKOSEL_HXT + * - \ref CLK_CLKSEL1_CLKOSEL_LXT + * - \ref CLK_CLKSEL1_CLKOSEL_HCLK + * - \ref CLK_CLKSEL1_CLKOSEL_HIRC + * - \ref CLK_CLKSEL1_CLKOSEL_LIRC + * - \ref CLK_CLKSEL1_CLKOSEL_PLL + * - \ref CLK_CLKSEL1_CLKOSEL_SOF + * @param[in] u32ClkDiv is divider selection for output frequency. + * @param[in] u32ClkDivBy1En is frequency divided by one enable. + * @return None + * + * @details Output selected clock to CKO. The output clock frequency is divided by u32ClkDiv. + * The formula is: + * CKO frequency = (Clock source frequency) / 2^(u32ClkDiv + 1) + * This function is just used to set CKO clock. + * User must enable I/O for CKO clock output pin by themselves. + */ +void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En) +{ + /* CKO = clock source / 2^(u32ClkDiv + 1) */ + CLK->CLKOCTL = CLK_CLKOCTL_CLKOEN_Msk | u32ClkDiv | (u32ClkDivBy1En << CLK_CLKOCTL_DIV1EN_Pos); + + /* Enable CKO clock source */ + CLK->APBCLK0 |= CLK_APBCLK0_CLKOCKEN_Msk; + + /* Select CKO clock source */ + CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_CLKOSEL_Msk)) | (u32ClkSrc); +} + +/** + * @brief Enter to Power-down mode + * @param None + * @return None + * @details This function is used to let system enter to Power-down mode. \n + * The register write-protection function should be disabled before using this function. + * @note Must be care of HIRC/MIRC auto trim is disabled when using this function. + */ +void CLK_PowerDown(void) +{ + volatile uint32_t u32SysTickTICKINT = 0; /* Backup Systick interrupt enable bit */ + + /* Check HIRC/MIRC auto trim function disable */ + if(SYS->HIRCTRIMCTL & SYS_HIRCTRIMCTL_FREQSEL_Msk) + { + return; + } + + /* Set the processor uses deep sleep as its low power mode */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + /* Set system Power-down enabled */ + CLK->PWRCTL |= CLK_PWRCTL_PDEN_Msk; + + /* Backup systick interrupt setting */ + u32SysTickTICKINT = SysTick->CTRL & SysTick_CTRL_TICKINT_Msk; + + /* Disable systick interrupt */ + SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; + + /* Chip enter Power-down mode after CPU run WFI instruction */ + __WFI(); + + /* Restore systick interrupt setting */ + if(u32SysTickTICKINT) SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; +} + +/** + * @brief Enter to Idle mode + * @param None + * @return None + * @details This function let system enter to Idle mode. \n + * The register write-protection function should be disabled before using this function. + */ +void CLK_Idle(void) +{ + /* Set the processor uses sleep as its low power mode */ + SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + + /* Set chip in idle mode because of WFI command */ + CLK->PWRCTL &= ~CLK_PWRCTL_PDEN_Msk; + + /* Chip enter idle mode after CPU run WFI instruction */ + __WFI(); +} + +/** + * @brief Get external high speed crystal clock frequency + * @param None + * @return External high frequency crystal frequency + * @details This function get external high frequency crystal frequency. The frequency unit is Hz. + */ +uint32_t CLK_GetHXTFreq(void) +{ + if(CLK->PWRCTL & CLK_PWRCTL_HXTEN_Msk) + return __HXT; + else + return 0; +} + +/** + * @brief Get external low speed crystal clock frequency + * @param None + * @return External low speed crystal clock frequency + * @details This function get external low frequency crystal frequency. The frequency unit is Hz. + */ +uint32_t CLK_GetLXTFreq(void) +{ + if(CLK->PWRCTL & CLK_PWRCTL_LXTEN_Msk) + return __LXT; + else + return 0; +} + +/** + * @brief Get PCLK0 frequency + * @param None + * @return PCLK0 frequency + * @details This function get PCLK0 frequency. The frequency unit is Hz. + */ +uint32_t CLK_GetPCLK0Freq(void) +{ + uint32_t PCLK0Div; + + SystemCoreClockUpdate(); + PCLK0Div = (CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) >> CLK_PCLKDIV_APB0DIV_Pos; + return (SystemCoreClock >> PCLK0Div); +} + +/** + * @brief Get PCLK1 frequency + * @param None + * @return PCLK1 frequency + * @details This function get PCLK1 frequency. The frequency unit is Hz. + */ +uint32_t CLK_GetPCLK1Freq(void) +{ + uint32_t PCLK1Div; + + SystemCoreClockUpdate(); + PCLK1Div = (CLK->PCLKDIV & CLK_PCLKDIV_APB1DIV_Msk) >> CLK_PCLKDIV_APB1DIV_Pos; + return (SystemCoreClock >> PCLK1Div); +} + +/** + * @brief Get HCLK frequency + * @param None + * @return HCLK frequency + * @details This function get HCLK frequency. The frequency unit is Hz. + */ +uint32_t CLK_GetHCLKFreq(void) +{ + SystemCoreClockUpdate(); + return SystemCoreClock; +} + +/** + * @brief Get CPU frequency + * @param None + * @return CPU frequency + * @details This function get CPU frequency. The frequency unit is Hz. + */ +uint32_t CLK_GetCPUFreq(void) +{ + SystemCoreClockUpdate(); + return SystemCoreClock; +} + +/** + * @brief Set HCLK frequency + * @param[in] u32Hclk is HCLK frequency. The range of u32Hclk is 25.5MHz ~ 48MHz. +* NOTE: For M031_G/I, the HCLK frequency up to 72MHz. + * @return HCLK frequency + * @details This function is used to set HCLK frequency. The frequency unit is Hz. \n + * It would configure PLL frequency to 51MHz ~ 96MHz, + * set HCLK clock divider as 2 and switch HCLK clock source to PLL. \n + * The register write-protection function should be disabled before using this function. + * NOTE: For M031_G/I, the PLL frequency up to 144MHz. + */ +uint32_t CLK_SetCoreClock(uint32_t u32Hclk) +{ + uint32_t u32HIRCSTB; + uint32_t u32HCLK_UpperLimit; + + /* Read HIRC clock source stable flag */ + u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk; + + /* The range of u32Hclk is 25.5 MHz ~ 48 MHz or 72 MHz */ + if ((GET_CHIP_SERIES_NUM == CHIP_SERIES_NUM_G) || (GET_CHIP_SERIES_NUM == CHIP_SERIES_NUM_I)) + u32HCLK_UpperLimit = FREQ_72MHZ; + else + u32HCLK_UpperLimit = FREQ_48MHZ; + + if(u32Hclk > u32HCLK_UpperLimit) + u32Hclk = u32HCLK_UpperLimit; + if(u32Hclk < (FREQ_51MHZ >> 1)) + u32Hclk = (FREQ_51MHZ >> 1); + + /* Switch HCLK clock source to HIRC clock for safe */ + CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk; + CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk); + CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_Msk; + CLK->CLKDIV0 &= (~CLK_CLKDIV0_HCLKDIV_Msk); + + /* Configure PLL setting if HXT clock is stable */ + if(CLK->STATUS & CLK_STATUS_HXTSTB_Msk) + u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HXT, (u32Hclk << 1)); + + /* Configure PLL setting if HXT clock is not stable */ + else + { + u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HIRC_DIV4, (u32Hclk << 1)); + + /* Read HIRC clock source stable flag */ + u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk; + } + + /* Select HCLK clock source to PLL, + Select HCLK clock source divider as 2 + and update system core clock + */ + CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL, CLK_CLKDIV0_HCLK(2)); + + /* Disable HIRC if HIRC is disabled before setting core clock */ + if(u32HIRCSTB == 0) + CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk; + + /* Return actually HCLK frequency is PLL frequency divide 2 */ + return u32Hclk >> 1; +} + +/** + * @brief Set HCLK clock source and HCLK clock divider + * @param[in] u32ClkSrc is HCLK clock source. Including : + * - \ref CLK_CLKSEL0_HCLKSEL_HXT + * - \ref CLK_CLKSEL0_HCLKSEL_LXT + * - \ref CLK_CLKSEL0_HCLKSEL_PLL + * - \ref CLK_CLKSEL0_HCLKSEL_LIRC + * - \ref CLK_CLKSEL0_HCLKSEL_HIRC + * @param[in] u32ClkDiv is HCLK clock divider. Including : + * - \ref CLK_CLKDIV0_HCLK(x) + * @return None + * @details This function set HCLK clock source and HCLK clock divider. The HCLK clock divider is set by CLK_CLKDIV0_HCLK(x) where x = 1~16. + * The register write-protection function should be disabled before using this function. + */ +void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv) +{ + uint32_t u32HIRCSTB; + + /* Read HIRC clock source stable flag */ + u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk; + + /* Switch to HIRC for Safe. Avoid HCLK too high when applying new divider. */ + CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk; + CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk); + CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_HIRC; + + /* Apply new Divider */ + CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_HCLKDIV_Msk)) | u32ClkDiv; + + /* Switch HCLK to new HCLK source */ + CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | u32ClkSrc; + + /* Update System Core Clock */ + SystemCoreClockUpdate(); + + /* Disable HIRC if HIRC is disabled before switching HCLK source */ + if(u32HIRCSTB == 0) + CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk; +} + +/** + * @brief This function set selected module clock source and module clock divider + * @param[in] u32ModuleIdx is module index. + * @param[in] u32ClkSrc is module clock source. + * @param[in] u32ClkDiv is module clock divider. + * @return None + * @details Valid parameter combinations listed in following table: + * + * |Module index |Clock source |Divider | + * | :---------------- | :----------------------------------- | :----------------------- | + * |\ref USBD_MODULE |\ref CLK_CLKSEL0_USBDSEL_HIRC |\ref CLK_CLKDIV0_USB(x) | + * |\ref USBD_MODULE |\ref CLK_CLKSEL0_USBDSEL_PLL |\ref CLK_CLKDIV0_USB(x) | + * |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_LXT | x | + * |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_HCLK_DIV2048 | x | + * |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_LIRC | x | + * |\ref WWDT_MODULE |\ref CLK_CLKSEL1_WWDTSEL_HCLK_DIV2048 | x | + * |\ref WWDT_MODULE |\ref CLK_CLKSEL1_WWDTSEL_LIRC | x | + * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_HXT | x | + * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_LXT | x | + * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_HCLK | x | + * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_HIRC | x | + * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_LIRC | x | + * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_PLL | x | + * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_SOF | x | + * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_HXT | x | + * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_LXT | x | + * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_PCLK0 | x | + * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_EXT_TRG | x | + * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_LIRC | x | + * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_HIRC | x | + * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_HXT | x | + * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_LXT | x | + * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_PCLK0 | x | + * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_EXT_TRG | x | + * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_LIRC | x | + * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_HIRC | x | + * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_HXT | x | + * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_LXT | x | + * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_PCLK1 | x | + * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_EXT_TRG | x | + * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_LIRC | x | + * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_HIRC | x | + * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_HXT | x | + * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_LXT | x | + * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_PCLK1 | x | + * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_EXT_TRG | x | + * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_LIRC | x | + * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_HIRC | x | + * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART0SEL_HXT |\ref CLK_CLKDIV0_UART0(x) | + * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART0SEL_PLL |\ref CLK_CLKDIV0_UART0(x) | + * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART0SEL_LXT |\ref CLK_CLKDIV0_UART0(x) | + * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART0SEL_HIRC |\ref CLK_CLKDIV0_UART0(x) | + * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART0SEL_PCLK0 |\ref CLK_CLKDIV0_UART0(x) | + * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART0SEL_LIRC |\ref CLK_CLKDIV0_UART0(x) | + * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART1SEL_HXT |\ref CLK_CLKDIV0_UART1(x) | + * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART1SEL_PLL |\ref CLK_CLKDIV0_UART1(x) | + * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART1SEL_LXT |\ref CLK_CLKDIV0_UART1(x) | + * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART1SEL_HIRC |\ref CLK_CLKDIV0_UART1(x) | + * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART1SEL_PCLK1 |\ref CLK_CLKDIV0_UART1(x) | + * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART1SEL_LIRC |\ref CLK_CLKDIV0_UART1(x) | + * |\ref UART2_MODULE |\ref CLK_CLKSEL3_UART2SEL_HXT |\ref CLK_CLKDIV4_UART2(x) | + * |\ref UART2_MODULE |\ref CLK_CLKSEL3_UART2SEL_PLL |\ref CLK_CLKDIV4_UART2(x) | + * |\ref UART2_MODULE |\ref CLK_CLKSEL3_UART2SEL_LXT |\ref CLK_CLKDIV4_UART2(x) | + * |\ref UART2_MODULE |\ref CLK_CLKSEL3_UART2SEL_HIRC |\ref CLK_CLKDIV4_UART2(x) | + * |\ref UART2_MODULE |\ref CLK_CLKSEL3_UART2SEL_PCLK0 |\ref CLK_CLKDIV4_UART2(x) | + * |\ref UART2_MODULE |\ref CLK_CLKSEL3_UART2SEL_LIRC |\ref CLK_CLKDIV4_UART2(x) | + * |\ref UART3_MODULE |\ref CLK_CLKSEL3_UART3SEL_HXT |\ref CLK_CLKDIV4_UART3(x) | + * |\ref UART3_MODULE |\ref CLK_CLKSEL3_UART3SEL_PLL |\ref CLK_CLKDIV4_UART3(x) | + * |\ref UART3_MODULE |\ref CLK_CLKSEL3_UART3SEL_LXT |\ref CLK_CLKDIV4_UART3(x) | + * |\ref UART3_MODULE |\ref CLK_CLKSEL3_UART3SEL_HIRC |\ref CLK_CLKDIV4_UART3(x) | + * |\ref UART3_MODULE |\ref CLK_CLKSEL3_UART3SEL_PCLK1 |\ref CLK_CLKDIV4_UART3(x) | + * |\ref UART3_MODULE |\ref CLK_CLKSEL3_UART3SEL_LIRC |\ref CLK_CLKDIV4_UART3(x) | + * |\ref UART4_MODULE |\ref CLK_CLKSEL3_UART4SEL_HXT |\ref CLK_CLKDIV4_UART4(x) | + * |\ref UART4_MODULE |\ref CLK_CLKSEL3_UART4SEL_PLL |\ref CLK_CLKDIV4_UART4(x) | + * |\ref UART4_MODULE |\ref CLK_CLKSEL3_UART4SEL_LXT |\ref CLK_CLKDIV4_UART4(x) | + * |\ref UART4_MODULE |\ref CLK_CLKSEL3_UART4SEL_HIRC |\ref CLK_CLKDIV4_UART4(x) | + * |\ref UART4_MODULE |\ref CLK_CLKSEL3_UART4SEL_PCLK0 |\ref CLK_CLKDIV4_UART4(x) | + * |\ref UART4_MODULE |\ref CLK_CLKSEL3_UART4SEL_LIRC |\ref CLK_CLKDIV4_UART4(x) | + * |\ref UART5_MODULE |\ref CLK_CLKSEL3_UART5SEL_HXT |\ref CLK_CLKDIV4_UART5(x) | + * |\ref UART5_MODULE |\ref CLK_CLKSEL3_UART5SEL_PLL |\ref CLK_CLKDIV4_UART5(x) | + * |\ref UART5_MODULE |\ref CLK_CLKSEL3_UART5SEL_LXT |\ref CLK_CLKDIV4_UART5(x) | + * |\ref UART5_MODULE |\ref CLK_CLKSEL3_UART5SEL_HIRC |\ref CLK_CLKDIV4_UART5(x) | + * |\ref UART5_MODULE |\ref CLK_CLKSEL3_UART5SEL_PCLK1 |\ref CLK_CLKDIV4_UART5(x) | + * |\ref UART5_MODULE |\ref CLK_CLKSEL3_UART5SEL_LIRC |\ref CLK_CLKDIV4_UART5(x) | + * |\ref UART6_MODULE |\ref CLK_CLKSEL3_UART6SEL_HXT |\ref CLK_CLKDIV4_UART6(x) | + * |\ref UART6_MODULE |\ref CLK_CLKSEL3_UART6SEL_PLL |\ref CLK_CLKDIV4_UART6(x) | + * |\ref UART6_MODULE |\ref CLK_CLKSEL3_UART6SEL_LXT |\ref CLK_CLKDIV4_UART6(x) | + * |\ref UART6_MODULE |\ref CLK_CLKSEL3_UART6SEL_HIRC |\ref CLK_CLKDIV4_UART6(x) | + * |\ref UART6_MODULE |\ref CLK_CLKSEL3_UART6SEL_PCLK0 |\ref CLK_CLKDIV4_UART6(x) | + * |\ref UART6_MODULE |\ref CLK_CLKSEL3_UART6SEL_LIRC |\ref CLK_CLKDIV4_UART6(x) | + * |\ref UART7_MODULE |\ref CLK_CLKSEL3_UART7SEL_HXT |\ref CLK_CLKDIV4_UART7(x) | + * |\ref UART7_MODULE |\ref CLK_CLKSEL3_UART7SEL_PLL |\ref CLK_CLKDIV4_UART7(x) | + * |\ref UART7_MODULE |\ref CLK_CLKSEL3_UART7SEL_LXT |\ref CLK_CLKDIV4_UART7(x) | + * |\ref UART7_MODULE |\ref CLK_CLKSEL3_UART7SEL_HIRC |\ref CLK_CLKDIV4_UART7(x) | + * |\ref UART7_MODULE |\ref CLK_CLKSEL3_UART7SEL_PCLK1 |\ref CLK_CLKDIV4_UART7(x) | + * |\ref UART7_MODULE |\ref CLK_CLKSEL3_UART7SEL_LIRC |\ref CLK_CLKDIV4_UART7(x) | + * |\ref PWM0_MODULE |\ref CLK_CLKSEL2_PWM0SEL_PLL | x | + * |\ref PWM0_MODULE |\ref CLK_CLKSEL2_PWM0SEL_PCLK0 | x | + * |\ref PWM1_MODULE |\ref CLK_CLKSEL2_PWM1SEL_PLL | x | + * |\ref PWM1_MODULE |\ref CLK_CLKSEL2_PWM1SEL_PCLK1 | x | + * |\ref QSPI0_MODULE |\ref CLK_CLKSEL2_QSPI0SEL_HXT | x | + * |\ref QSPI0_MODULE |\ref CLK_CLKSEL2_QSPI0SEL_PLL | x | + * |\ref QSPI0_MODULE |\ref CLK_CLKSEL2_QSPI0SEL_PCLK0 | x | + * |\ref QSPI0_MODULE |\ref CLK_CLKSEL2_QSPI0SEL_HIRC | x | + * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_HXT | x | + * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_PLL | x | + * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_PCLK1 | x | + * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_HIRC | x | + * |\ref BPWM0_MODULE |\ref CLK_CLKSEL2_BPWM0SEL_PLL | x | + * |\ref BPWM0_MODULE |\ref CLK_CLKSEL2_BPWM0SEL_PCLK0 | x | + * |\ref BPWM1_MODULE |\ref CLK_CLKSEL2_BPWM1SEL_PLL | x | + * |\ref BPWM1_MODULE |\ref CLK_CLKSEL2_BPWM1SEL_PCLK1 | x | + * |\ref ADC_MODULE |\ref CLK_CLKSEL2_ADCSEL_HXT |\ref CLK_CLKDIV0_ADC(x) | + * |\ref ADC_MODULE |\ref CLK_CLKSEL2_ADCSEL_PLL |\ref CLK_CLKDIV0_ADC(x) | + * |\ref ADC_MODULE |\ref CLK_CLKSEL2_ADCSEL_PCLK1 |\ref CLK_CLKDIV0_ADC(x) | + * |\ref ADC_MODULE |\ref CLK_CLKSEL2_ADCSEL_HIRC |\ref CLK_CLKDIV0_ADC(x) | + */ +void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv) +{ + uint32_t u32sel = 0, u32div = 0; + uint32_t u32SelTbl[4] = {0x0, 0x4, 0x8, 0xC}; /* CLKSEL offset on MODULE index, 0x0:CLKSEL0, 0x1:CLKSEL1, 0x2:CLKSEL2, 0x3:CLKSEL3 */ + uint32_t u32DivTbl[4] = {0x0, 0x0, 0x0, 0x10}; /* CLKDIV offset on MODULE index, 0x0:CLKDIV0, 0x1:CLKDIV1, 0x2:CLKDIV3, 0x3:CLKDIV4 */ + + if(MODULE_CLKDIV_Msk(u32ModuleIdx) != MODULE_NoMsk) + { + /* Get clock divider control register address */ + u32div = (uint32_t)&CLK->CLKDIV0 + (u32DivTbl[MODULE_CLKDIV(u32ModuleIdx)]); + /* Apply new divider */ + M32(u32div) = (M32(u32div) & (~(MODULE_CLKDIV_Msk(u32ModuleIdx) << MODULE_CLKDIV_Pos(u32ModuleIdx)))) | u32ClkDiv; + } + + if(MODULE_CLKSEL_Msk(u32ModuleIdx) != MODULE_NoMsk) + { + /* Get clock select control register address */ + u32sel = (uint32_t)&CLK->CLKSEL0 + (u32SelTbl[MODULE_CLKSEL(u32ModuleIdx)]); + /* Set new clock selection setting */ + M32(u32sel) = (M32(u32sel) & (~(MODULE_CLKSEL_Msk(u32ModuleIdx) << MODULE_CLKSEL_Pos(u32ModuleIdx)))) | u32ClkSrc; + } +} + +/** + * @brief Set SysTick clock source + * @param[in] u32ClkSrc is module clock source. Including: + * - \ref CLK_CLKSEL0_STCLKSEL_HXT + * - \ref CLK_CLKSEL0_STCLKSEL_LXT + * - \ref CLK_CLKSEL0_STCLKSEL_HXT_DIV2 + * - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2 + * - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2 + * @return None + * @details This function set SysTick clock source. \n + * The register write-protection function should be disabled before using this function. + */ +void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc) +{ + CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc; +} + +/** + * @brief Enable clock source + * @param[in] u32ClkMask is clock source mask. Including : + * - \ref CLK_PWRCTL_HXTEN_Msk + * - \ref CLK_PWRCTL_LXTEN_Msk + * - \ref CLK_PWRCTL_HIRCEN_Msk + * - \ref CLK_PWRCTL_LIRCEN_Msk + * @return None + * @details This function enable clock source. \n + * The register write-protection function should be disabled before using this function. + */ +void CLK_EnableXtalRC(uint32_t u32ClkMask) +{ + CLK->PWRCTL |= u32ClkMask; +} + +/** + * @brief Disable clock source + * @param[in] u32ClkMask is clock source mask. Including : + * - \ref CLK_PWRCTL_HXTEN_Msk + * - \ref CLK_PWRCTL_LXTEN_Msk + * - \ref CLK_PWRCTL_HIRCEN_Msk + * - \ref CLK_PWRCTL_LIRCEN_Msk + * @return None + * @details This function disable clock source. \n + * The register write-protection function should be disabled before using this function. + */ +void CLK_DisableXtalRC(uint32_t u32ClkMask) +{ + CLK->PWRCTL &= ~u32ClkMask; +} + +/** + * @brief This function enable module clock + * @param[in] u32ModuleIdx is module index. Including : + * - \ref PDMA_MODULE + * - \ref ISP_MODULE + * - \ref EBI_MODULE + * - \ref HDIV_MODULE + * - \ref CRC_MODULE + * - \ref WDT_MODULE + * - \ref WWDT_MODULE + * - \ref RTC_MODULE + * - \ref TMR0_MODULE + * - \ref TMR1_MODULE + * - \ref TMR2_MODULE + * - \ref TMR3_MODULE + * - \ref CLKO_MODULE + * - \ref UART0_MODULE + * - \ref UART1_MODULE + * - \ref UART2_MODULE + * - \ref UART3_MODULE + * - \ref UART4_MODULE + * - \ref UART5_MODULE + * - \ref UART6_MODULE + * - \ref UART7_MODULE + * - \ref I2C0_MODULE + * - \ref I2C1_MODULE + * - \ref QSPI0_MODULE + * - \ref SPI0_MODULE + * - \ref ADC_MODULE + * - \ref ACMP01_MODULE + * - \ref USBD_MODULE + * - \ref PWM0_MODULE + * - \ref PWM1_MODULE + * - \ref BPWM0_MODULE + * - \ref BPWM1_MODULE + * - \ref USCI0_MODULE + * - \ref USCI1_MODULE + * @return None + * @details This function enable module clock. + */ +void CLK_EnableModuleClock(uint32_t u32ModuleIdx) +{ + uint32_t u32ClkTbl[3] = {0x0, 0x4, 0x8}; /* AHBCLK/APBCLK offset on MODULE index, 0x0:AHBCLK, 0x1:APBCLK0, 0x2:APBCLK1 */ + + *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + (u32ClkTbl[MODULE_APBCLK(u32ModuleIdx)])) |= 1 << MODULE_IP_EN_Pos(u32ModuleIdx); +} + +/** + * @brief This function disable module clock + * @param[in] u32ModuleIdx is module index + * - \ref PDMA_MODULE + * - \ref ISP_MODULE + * - \ref EBI_MODULE + * - \ref HDIV_MODULE + * - \ref CRC_MODULE + * - \ref WDT_MODULE + * - \ref WWDT_MODULE + * - \ref RTC_MODULE + * - \ref TMR0_MODULE + * - \ref TMR1_MODULE + * - \ref TMR2_MODULE + * - \ref TMR3_MODULE + * - \ref CLKO_MODULE + * - \ref UART0_MODULE + * - \ref UART1_MODULE + * - \ref UART2_MODULE + * - \ref UART3_MODULE + * - \ref UART4_MODULE + * - \ref UART5_MODULE + * - \ref UART6_MODULE + * - \ref UART7_MODULE + * - \ref I2C0_MODULE + * - \ref I2C1_MODULE + * - \ref QSPI0_MODULE + * - \ref SPI0_MODULE + * - \ref ADC_MODULE + * - \ref ACMP01_MODULE + * - \ref USBD_MODULE + * - \ref PWM0_MODULE + * - \ref PWM1_MODULE + * - \ref BPWM0_MODULE + * - \ref BPWM1_MODULE + * - \ref USCI0_MODULE + * - \ref USCI1_MODULE + * @return None + * @details This function disable module clock. + */ +void CLK_DisableModuleClock(uint32_t u32ModuleIdx) +{ + uint32_t u32ClkTbl[3] = {0x0, 0x4, 0x8}; /* AHBCLK/APBCLK offset on MODULE index, 0x0:AHBCLK, 0x1:APBCLK0, 0x2:APBCLK1 */ + + *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + (u32ClkTbl[MODULE_APBCLK(u32ModuleIdx)])) &= ~(1 << MODULE_IP_EN_Pos(u32ModuleIdx)); +} + +/** + * @brief Set PLL frequency + * @param[in] u32PllClkSrc is PLL clock source. Including : + * - \ref CLK_PLLCTL_PLLSRC_HXT + * - \ref CLK_PLLCTL_PLLSRC_HIRC_DIV4 + * @param[in] u32PllFreq is PLL frequency. The frequency unit is Hz. + * @return Actual PLL frequency + * @details This function is used to configure PLLCTL register to set specified PLL frequency. \n + * The register write-protection function should be disabled before using this function. + */ +uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq) +{ + uint32_t u32PllSrcClk, u32NR, u32NF, u32NO, u32CLK_SRC, u32Outdiv; + uint32_t u32Tmp, u32Tmp2, u32Tmp3, u32Min, u32MinNF, u32MinNR; + uint32_t u32PLL_UpperLimit; + + /* Disable PLL first to avoid unstable when setting PLL */ + CLK_DisablePLL(); + + /* PLL source clock is from HXT */ + if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT) + { + /* Enable HXT clock */ + CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk; + + /* Wait for HXT clock ready */ + CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk); + + /* Select PLL source clock from HXT */ + u32CLK_SRC = CLK_PLLCTL_PLLSRC_HXT; + u32PllSrcClk = __HXT; + + /* u32NR start from 2 since NR = INDIV + 2 */ + u32NR = 2; + } + + /* PLL source clock is from HIRC/4 */ + else + { + /* Enable HIRC clock */ + CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk; + + /* Wait for HIRC clock ready */ + CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk); + + /* Select PLL source clock from HIRC */ + u32CLK_SRC = CLK_PLLCTL_PLLSRC_HIRC_DIV4; + u32PllSrcClk = __HIRC >> 2; + + /* u32NR start from 2 since NR = INDIV + 2 */ + u32NR = 2; + } + + /* Select "NO" according to request frequency */ + /* Constraint: PLL output frequency must <= 96MHz */ + /* PLL output frequency must > 50.14MHz to meet all constraints */ + if ((GET_CHIP_SERIES_NUM == CHIP_SERIES_NUM_G) || (GET_CHIP_SERIES_NUM == CHIP_SERIES_NUM_I)) + u32PLL_UpperLimit = FREQ_144MHZ; + else + u32PLL_UpperLimit = FREQ_96MHZ; + + if((u32PllFreq <= u32PLL_UpperLimit) && (u32PllFreq >= FREQ_51MHZ)) + { + if (u32PllFreq <= FREQ_96MHZ) + { + u32NO = 4; + u32Outdiv = 3; + u32PllFreq = u32PllFreq << 2; /* u32PllFreq = (FIN * NF / NR) now */ + } + else + { + u32NO = 2; + u32Outdiv = 2; + u32PllFreq = u32PllFreq << 1; /* u32PllFreq = (FIN * NF / NR) now */ + } + } + else + { + /* Wrong frequency request. Just return default setting. */ + goto lexit; + } + + /* Find best solution */ + u32Min = (uint32_t) 0xFFFFFFFF; /* initial u32Min to max value of uint32_t */ + u32MinNR = 0; + u32MinNF = 0; + for(; u32NR <= 33; u32NR++) /* max NR = 33 since NR = INDIV + 2 and INDIV = 0 ~ 31 */ + { + u32Tmp = u32PllSrcClk / u32NR; + /* Constraint 2: 800KHz < (FIN / (2*NR)) < 8MHz */ + if((u32Tmp > 1600000) && (u32Tmp < 16000000)) + { + for(u32NF = 2; u32NF <= 513; u32NF++) /* NF = 2~513 since NF = FBDIV + 2 and FBDIV = 0 ~ 511 */ + { + u32Tmp2 = u32Tmp * u32NF; + /* Constraint 3: 200MHz < (FIN * NF / NR) < 500MHz */ + if((u32Tmp2 >= 200000000) && (u32Tmp2 < 500000000)) + { + u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2; + if(u32Tmp3 < u32Min) + { + u32Min = u32Tmp3; + u32MinNR = u32NR; + u32MinNF = u32NF; + + /* Break when get good results */ + if(u32Min == 0) + break; + } + } + } + } + } + + /* Enable and apply new PLL setting. */ + CLK->PLLCTL = u32CLK_SRC | + (u32Outdiv << CLK_PLLCTL_OUTDIV_Pos) | + ((u32MinNR - 2) << CLK_PLLCTL_INDIV_Pos) | + ((u32MinNF - 2) << CLK_PLLCTL_FBDIV_Pos); + + /* Wait for PLL clock stable */ + CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk); + + /* Return actual PLL output clock frequency */ + return (u32PllSrcClk / (u32NO * u32MinNR) * u32MinNF); + +lexit: + + /* Apply default PLL setting and return */ + if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT) + CLK->PLLCTL = CLK_PLLCTL_96MHz_HXT; + else + CLK->PLLCTL = CLK_PLLCTL_96MHz_HIRC_DIV4; + + /* Wait for PLL clock stable */ + CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk); + + return CLK_GetPLLClockFreq(); +} + +/** + * @brief Disable PLL + * @param None + * @return None + * @details This function set PLL in Power-down mode. \n + * If the current HCLK is PLL, this function will switch HCLK to HIRC before disable PLL. \n + * The register write-protection function should be disabled before using this function. + */ +void CLK_DisablePLL(void) +{ + /* Switch HCLK to HIRC before disable PLL if current HCLK is PLL */ + if ((CLK->CLKSEL0 & CLK_CLKSEL0_HCLKSEL_Msk) == CLK_CLKSEL0_HCLKSEL_PLL) + { + CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk; + CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk); + CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_HIRC; + } + + CLK->PLLCTL |= CLK_PLLCTL_PD_Msk; +} + +/** + * @brief This function check selected clock source status + * @param[in] u32ClkMask is selected clock source. Including : + * - \ref CLK_STATUS_HXTSTB_Msk + * - \ref CLK_STATUS_LXTSTB_Msk + * - \ref CLK_STATUS_HIRCSTB_Msk + * - \ref CLK_STATUS_LIRCSTB_Msk + * - \ref CLK_STATUS_PLLSTB_Msk + * @retval 0 clock is not stable + * @retval 1 clock is stable + * @details To wait for clock ready by specified clock source stable flag or timeout (~300ms) + */ +uint32_t CLK_WaitClockReady(uint32_t u32ClkMask) +{ + int32_t i32TimeOutCnt = 2160000; + + while((CLK->STATUS & u32ClkMask) != u32ClkMask) + { + if(i32TimeOutCnt-- <= 0) + return 0; + } + + return 1; +} + +/** + * @brief Enable System Tick counter + * @param[in] u32ClkSrc is System Tick clock source. Including: + * - \ref CLK_CLKSEL0_STCLKSEL_HXT + * - \ref CLK_CLKSEL0_STCLKSEL_LXT + * - \ref CLK_CLKSEL0_STCLKSEL_HXT_DIV2 + * - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2 + * - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2 + * - \ref CLK_CLKSEL0_STCLKSEL_HCLK + * @param[in] u32Count is System Tick reload value. It could be 0~0xFFFFFF. + * @return None + * @details This function set System Tick clock source, reload value, enable System Tick counter and interrupt. \n + * The register write-protection function should be disabled before using this function. + */ +void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count) +{ + /* Set System Tick counter disabled */ + SysTick->CTRL = 0; + + /* Set System Tick clock source */ + if(u32ClkSrc == CLK_CLKSEL0_STCLKSEL_HCLK) + SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk; + else + CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc; + + /* Set System Tick reload value */ + SysTick->LOAD = u32Count; + + /* Clear System Tick current value and counter flag */ + SysTick->VAL = 0; + + /* Set System Tick interrupt enabled and counter enabled */ + SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; +} + +/** + * @brief Disable System Tick counter + * @param None + * @return None + * @details This function disable System Tick counter. + */ +void CLK_DisableSysTick(void) +{ + /* Set System Tick counter disabled */ + SysTick->CTRL = 0; +} + + + +/*@}*/ /* end of group CLK_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group CLK_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_crc.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_crc.c new file mode 100644 index 0000000000..ddda689cbf --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_crc.c @@ -0,0 +1,99 @@ +/**************************************************************************//** + * @file crc.c + * @version V3.00 + * $Revision: 4 $ + * $Date: 18/04/24 3:49p $ + * @brief M031 series Cyclic Redundancy Check(CRC) driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#include "NuMicro.h" + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup CRC_Driver CRC Driver + @{ +*/ + +/** @addtogroup CRC_EXPORTED_FUNCTIONS CRC Exported Functions + @{ +*/ + +/** + * @brief CRC Open + * + * @param[in] u32Mode CRC operation polynomial mode. Valid values are: + * - \ref CRC_CCITT + * - \ref CRC_8 + * - \ref CRC_16 + * - \ref CRC_32 + * @param[in] u32Attribute CRC operation data attribute. Valid values are combined with: + * - \ref CRC_CHECKSUM_COM + * - \ref CRC_CHECKSUM_RVS + * - \ref CRC_WDATA_COM + * - \ref CRC_WDATA_RVS + * @param[in] u32Seed Seed value. + * @param[in] u32DataLen CPU Write Data Length. Valid values are: + * - \ref CRC_CPU_WDATA_8 + * - \ref CRC_CPU_WDATA_16 + * - \ref CRC_CPU_WDATA_32 + * + * @return None + * + * @details This function will enable the CRC controller by specify CRC operation mode, attribute, initial seed and write data length. \n + * After that, user can start to perform CRC calculate by calling CRC_WRITE_DATA macro or CRC_DAT register directly. + */ +void CRC_Open(uint32_t u32Mode, uint32_t u32Attribute, uint32_t u32Seed, uint32_t u32DataLen) +{ + CRC->SEED = u32Seed; + CRC->CTL = u32Mode | u32Attribute | u32DataLen | CRC_CTL_CRCEN_Msk; + + /* Setting CRCRST bit will reload the initial seed value(CRC_SEED register) to CRC controller */ + CRC->CTL |= CRC_CTL_CHKSINIT_Msk; +} + +/** + * @brief Get CRC Checksum + * + * @param[in] None + * + * @return Checksum Result + * + * @details This macro gets the CRC checksum result by current CRC polynomial mode. + */ +uint32_t CRC_GetChecksum(void) +{ + uint32_t ret; + + switch(CRC->CTL & CRC_CTL_CRCMODE_Msk) + { + case CRC_CCITT: + case CRC_16: + ret = (CRC->CHECKSUM & 0xFFFFU); + break; + case CRC_32: + ret = (CRC->CHECKSUM); + break; + case CRC_8: + ret = (CRC->CHECKSUM & 0xFFU); + break; + default: + ret = 0U; + break; + } + + return ret; +} + +/*@}*/ /* end of group CRC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group CRC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_ebi.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_ebi.c new file mode 100644 index 0000000000..19ab6a6db1 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_ebi.c @@ -0,0 +1,182 @@ +/**************************************************************************//** + * @file ebi.c + * @version V1.00 + * $Revision: 5 $ + * $Date: 18/08/20 11:48a $ + * @brief M031 series External Bus Interface(EBI) driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "NuMicro.h" + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup EBI_Driver EBI Driver + @{ +*/ + +/** @addtogroup EBI_EXPORTED_FUNCTIONS EBI Exported Functions + @{ +*/ + +/** + * @brief Initialize EBI for specify Bank + * + * @param[in] u32Bank Bank number for EBI. Valid values are: + * - \ref EBI_BANK0 + * - \ref EBI_BANK1 + * @param[in] u32DataWidth Data bus width. Valid values are: + * - \ref EBI_BUSWIDTH_8BIT + * - \ref EBI_BUSWIDTH_16BIT + * @param[in] u32TimingClass Default timing configuration. Valid values are: + * - \ref EBI_TIMING_FASTEST + * - \ref EBI_TIMING_VERYFAST + * - \ref EBI_TIMING_FAST + * - \ref EBI_TIMING_NORMAL + * - \ref EBI_TIMING_SLOW + * - \ref EBI_TIMING_VERYSLOW + * - \ref EBI_TIMING_SLOWEST + * @param[in] u32BusMode Set EBI bus operate mode. Valid values are: + * - \ref EBI_OPMODE_NORMAL + * - \ref EBI_OPMODE_CACCESS + * @param[in] u32CSActiveLevel CS is active High/Low. Valid values are: + * - \ref EBI_CS_ACTIVE_HIGH + * - \ref EBI_CS_ACTIVE_LOW + * + * @return None + * + * @details This function is used to open specify EBI bank with different bus width, timing setting and \n + * active level of CS pin to access EBI device. + * @note Write Buffer Enable(WBUFEN) and Extend Time Of ALE(TALE) are only available in EBI bank0 control register. + */ +void EBI_Open(uint32_t u32Bank, uint32_t u32DataWidth, uint32_t u32TimingClass, uint32_t u32BusMode, uint32_t u32CSActiveLevel) +{ + volatile uint32_t *pu32EBICTL = (uint32_t *)((uint32_t)&EBI->CTL0 + (u32Bank * 0x10)); + volatile uint32_t *pu32EBITCTL = (uint32_t *)((uint32_t)&EBI->TCTL0 + (u32Bank * 0x10)); + + if(u32DataWidth == EBI_BUSWIDTH_8BIT) + *pu32EBICTL &= ~EBI_CTL_DW16_Msk; + else + *pu32EBICTL |= EBI_CTL_DW16_Msk; + + *pu32EBICTL |= u32BusMode; + + switch (u32TimingClass) + { + case EBI_TIMING_FASTEST: + *pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) | + (EBI_MCLKDIV_1 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk; + *pu32EBITCTL = 0x0U; + break; + + case EBI_TIMING_VERYFAST: + *pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) | + (EBI_MCLKDIV_1 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk | + (0x3U << EBI_CTL_TALE_Pos) ; + *pu32EBITCTL = 0x03003318U; + break; + + case EBI_TIMING_FAST: + *pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) | + (EBI_MCLKDIV_2 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk; + *pu32EBITCTL = 0x0U; + break; + + case EBI_TIMING_NORMAL: + *pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) | + (EBI_MCLKDIV_2 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk | + (0x3U << EBI_CTL_TALE_Pos) ; + *pu32EBITCTL = 0x03003318U; + break; + + case EBI_TIMING_SLOW: + *pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) | + (EBI_MCLKDIV_2 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk | + (0x7U << EBI_CTL_TALE_Pos) ; + *pu32EBITCTL = 0x07007738U; + break; + + case EBI_TIMING_VERYSLOW: + *pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) | + (EBI_MCLKDIV_4 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk | + (0x7U << EBI_CTL_TALE_Pos) ; + *pu32EBITCTL = 0x07007738U; + break; + + case EBI_TIMING_SLOWEST: + *pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) | + (EBI_MCLKDIV_8 << EBI_CTL_MCLKDIV_Pos) | + (u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk | + (0x7U << EBI_CTL_TALE_Pos) ; + *pu32EBITCTL = 0x07007738U; + break; + + default: + *pu32EBICTL &= ~EBI_CTL_EN_Msk; + break; + } +} + +/** + * @brief Disable EBI on specify Bank + * + * @param[in] u32Bank Bank number for EBI. Valid values are: + * - \ref EBI_BANK0 + * - \ref EBI_BANK1 + * + * @return None + * + * @details This function is used to close specify EBI function. + */ +void EBI_Close(uint32_t u32Bank) +{ + volatile uint32_t *pu32EBICTL = (uint32_t *)((uint32_t)&EBI->CTL0 + (u32Bank * 0x10U)); + + *pu32EBICTL &= ~EBI_CTL_EN_Msk; +} + +/** + * @brief Set EBI Bus Timing for specify Bank + * + * @param[in] u32Bank Bank number for EBI. Valid values are: + * - \ref EBI_BANK0 + * - \ref EBI_BANK1 + * @param[in] u32TimingConfig Configure EBI timing settings, includes TACC, TAHD, W2X and R2R setting. + * @param[in] u32MclkDiv Divider for MCLK. Valid values are: + * - \ref EBI_MCLKDIV_1 + * - \ref EBI_MCLKDIV_2 + * - \ref EBI_MCLKDIV_4 + * - \ref EBI_MCLKDIV_8 + * - \ref EBI_MCLKDIV_16 + * - \ref EBI_MCLKDIV_32 + * + * @return None + * + * @details This function is used to configure specify EBI bus timing for access EBI device. + */ +void EBI_SetBusTiming(uint32_t u32Bank, uint32_t u32TimingConfig, uint32_t u32MclkDiv) +{ + volatile uint32_t *pu32EBICTL = (uint32_t *)((uint32_t)&EBI->CTL0 + (u32Bank * 0x10U)); + volatile uint32_t *pu32EBITCTL = (uint32_t *)((uint32_t)&EBI->TCTL0 + (u32Bank * 0x10U)); + + *pu32EBICTL = (*pu32EBICTL & ~EBI_CTL_MCLKDIV_Msk) | (u32MclkDiv << EBI_CTL_MCLKDIV_Pos); + *pu32EBITCTL = u32TimingConfig; +} + +/*@}*/ /* end of group EBI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group EBI_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_fmc.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_fmc.c new file mode 100644 index 0000000000..a5a1149a7a --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_fmc.c @@ -0,0 +1,572 @@ +/**************************************************************************//** + * @file fmc.c + * @version V1.00 + * $Revision: 3 $ + * $Date: 18/04/24 3:05p $ + * @brief M031 series FMC driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include + +#include "NuMicro.h" + + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup FMC_Driver FMC Driver + @{ +*/ + + +/** @addtogroup FMC_EXPORTED_FUNCTIONS FMC Exported Functions + @{ +*/ + + +/** + * @brief Disable FMC ISP function. + * @return None + */ +void FMC_Close(void) +{ + FMC->ISPCTL &= ~FMC_ISPCTL_ISPEN_Msk; +} + + +/** + * @brief Execute FMC_ISPCMD_PAGE_ERASE command to erase a flash page. The page size is 4096 bytes. + * @param[in] u32PageAddr Address of the flash page to be erased. + * It must be a 4096 bytes aligned address. + * @return ISP page erase success or not. + * @retval 0 Success + * @retval -1 Erase failed + */ +int32_t FMC_Erase(uint32_t u32PageAddr) +{ + int32_t ret = 0; + + if (u32PageAddr == FMC_SPROM_BASE) + { + ret = FMC_Erase_SPROM(); + } + else + { + FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE; + FMC->ISPADDR = u32PageAddr; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } + + if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) + { + FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk; + ret = -1; + } + } + return ret; +} + +/** + * @brief Execute Flash Bank erase + * + * @param[in] u32BankAddr Base address of the flash bank to be erased. + * + * @return ISP bank erase success or not. + * @retval 0 Success + * @retval -1 Erase failed + * + * @details Execute FMC_ISPCMD_BANK_ERASE command to erase a flash bank. + */ +int32_t FMC_Erase_Bank(uint32_t u32BankAddr) +{ + int32_t ret = 0; + + FMC->ISPCMD = FMC_ISPCMD_BANK_ERASE; + FMC->ISPADDR = u32BankAddr; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } + + if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) + { + FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk; + ret = -1; + } + return ret; +} + +/** + * @brief Execute FMC_ISPCMD_PAGE_ERASE command to erase SPROM. The page size is 4096 bytes. + * @return SPROM page erase success or not. + * @retval 0 Success + * @retval -1 Erase failed + */ +int32_t FMC_Erase_SPROM(void) +{ + int32_t ret = 0; + + FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE; + FMC->ISPADDR = FMC_SPROM_BASE; + FMC->ISPDAT = 0x0055AA03UL; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } + + if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) + { + FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk; + ret = -1; + } + return ret; +} + +/** + * @brief Execute FMC_ISPCMD_BANK_REMAP command to remap bank. + * @return Bank remap success or not. + * @retval 0 Success + * @retval -1 Erase failed + */ +int32_t FMC_RemapBank(uint32_t u32BankIdx) +{ + int32_t ret = 0; + + FMC->ISPCMD = FMC_ISPCMD_BANK_REMAP; + FMC->ISPADDR = u32BankIdx; + FMC->ISPDAT = 0x5AA55AA5UL; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } + + if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) + { + FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk; + ret = -1; + } + return ret; +} + +/** + * @brief Get the current boot source. + * @return The current boot source. + * @retval 0 Is boot from APROM. + * @retval 1 Is boot from LDROM. + */ +int32_t FMC_GetBootSource (void) +{ + int32_t ret = 0; + + if (FMC->ISPCTL & FMC_ISPCTL_BS_Msk) + { + ret = 1; + } + + return ret; +} + + +/** + * @brief Enable FMC ISP function + * @return None + */ +void FMC_Open(void) +{ + FMC->ISPCTL |= FMC_ISPCTL_ISPEN_Msk; +} + + +/** + * @brief Execute FMC_ISPCMD_READ command to read a word from flash. + * @param[in] u32Addr Address of the flash location to be read. + * It must be a word aligned address. + * @return The word data read from specified flash address. + */ +uint32_t FMC_Read(uint32_t u32Addr) +{ + FMC->ISPCMD = FMC_ISPCMD_READ; + FMC->ISPADDR = u32Addr; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } + + return FMC->ISPDAT; +} + + +/** + * @brief Get the base address of Data Flash if enabled. + * @retval The base address of Data Flash + */ +uint32_t FMC_ReadDataFlashBaseAddr(void) +{ + return FMC->DFBA; +} + +/** + * @brief Set boot source from LDROM or APROM after next software reset + * @param[in] i32BootSrc + * 1: Boot from LDROM + * 0: Boot from APROM + * @return None + * @details This function is used to switch APROM boot or LDROM boot. User need to call + * FMC_SetBootSource to select boot source first, then use CPU reset or + * System Reset Request to reset system. + */ +void FMC_SetBootSource(int32_t i32BootSrc) +{ + if(i32BootSrc) + { + FMC->ISPCTL |= FMC_ISPCTL_BS_Msk; /* Boot from LDROM */ + } + else + { + FMC->ISPCTL &= ~FMC_ISPCTL_BS_Msk;/* Boot from APROM */ + } +} + +/** + * @brief Execute ISP FMC_ISPCMD_PROGRAM to program a word to flash. + * @param[in] u32Addr Address of the flash location to be programmed. + * It must be a word aligned address. + * @param[in] u32Data The word data to be programmed. + * @return None + */ +void FMC_Write(uint32_t u32Addr, uint32_t u32Data) +{ + FMC->ISPCMD = FMC_ISPCMD_PROGRAM; + FMC->ISPADDR = u32Addr; + FMC->ISPDAT = u32Data; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } +} + +/** + * @brief Execute ISP FMC_ISPCMD_PROGRAM_64 to program a double-word to flash. + * @param[in] u32addr Address of the flash location to be programmed. + * It must be a double-word aligned address. + * @param[in] u32data0 The word data to be programmed to flash address u32addr. + * @param[in] u32data1 The word data to be programmed to flash address u32addr+4. + * @return 0 Success + * @return -1 Failed + */ +int32_t FMC_Write8Bytes(uint32_t u32addr, uint32_t u32data0, uint32_t u32data1) +{ + int32_t ret = 0; + + FMC->ISPCMD = FMC_ISPCMD_PROGRAM_64; + FMC->ISPADDR = u32addr; + FMC->MPDAT0 = u32data0; + FMC->MPDAT1 = u32data1; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } + + if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) + { + FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk; + ret = -1; + } + return ret; +} + +/** + * @brief Execute FMC_ISPCMD_READ command to read User Configuration. + * @param[out] u32Config A three-word array. + * u32Config[0] holds CONFIG0, while u32Config[1] holds CONFIG1. + * @param[in] u32Count Available word count in u32Config. + * @return Success or not. + * @retval 0 Success. + * @retval -1 Invalid parameter. + */ +int32_t FMC_ReadConfig(uint32_t u32Config[], uint32_t u32Count) +{ + int32_t ret = 0; + + u32Config[0] = FMC_Read(FMC_CONFIG_BASE); + + if (u32Count > 3UL) + { + ret = -1; + } + else + { + if(u32Count > 1UL) + { + u32Config[1] = FMC_Read(FMC_CONFIG_BASE+4UL); + } + if(u32Count > 2UL) + { + u32Config[2] = FMC_Read(FMC_CONFIG_BASE+8UL); + } + } + return ret; +} + +/** + * @brief Execute ISP commands to erase then write User Configuration. + * @param[in] u32Config A two-word array. + * u32Config[0] holds CONFIG0, while u32Config[1] holds CONFIG1. + * @param[in] u32Count Always be 2 in this BSP. + * @return Success or not. + * @retval 0 Success. + * @retval -1 Invalid parameter. + */ +int32_t FMC_WriteConfig(uint32_t u32Config[], uint32_t u32Count) +{ + int32_t ret = 0; + uint32_t i; + + for (i = 0u; i < u32Count; i++) + { + FMC_Write(FMC_CONFIG_BASE + i * 4u, u32Config[i]); + + if (FMC_Read(FMC_CONFIG_BASE + i * 4u) != u32Config[i]) + { + ret = -1; + } + } + + return ret; +} + +/** + * @brief Run CRC32 checksum calculation and get result. + * @param[in] u32addr Starting flash address. It must be a page aligned address. + * @param[in] u32count Byte count of flash to be calculated. It must be multiple of 512 bytes. + * @return Success or not. + * @retval 0 Success. + * @retval 0xFFFFFFFF Invalid parameter. + */ +uint32_t FMC_GetChkSum(uint32_t u32addr, uint32_t u32count) +{ + uint32_t ret; + + if ((u32addr % 512UL) || (u32count % 512UL)) + { + ret = 0xFFFFFFFF; + } + else + { + FMC->ISPCMD = FMC_ISPCMD_RUN_CKS; + FMC->ISPADDR = u32addr; + FMC->ISPDAT = u32count; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } + + FMC->ISPCMD = FMC_ISPCMD_READ_CKS; + FMC->ISPADDR = u32addr; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } + + ret = FMC->ISPDAT; + } + + return ret; +} + +/** + * @brief Run flash all one verification and get result. + * + * @param[in] u32addr Starting flash address. It must be a page aligned address. + * @param[in] u32count Byte count of flash to be calculated. It must be multiple of 512 bytes. + * + * @retval READ_ALLONE_YES The contents of verified flash area are 0xFFFFFFFF. + * @retval READ_ALLONE_NOT Some contents of verified flash area are not 0xFFFFFFFF. + * @retval READ_ALLONE_CMD_FAIL Unexpected error occurred. + * + * @details Run ISP check all one command to check specify area is all one or not. + */ +#define FMC_APROM_BANK1_BASE (0x40000) +#define FMC_CHECKALLONE_UNIT (512) +uint32_t FMC_CheckAllOne(uint32_t u32addr, uint32_t u32count) +{ + uint32_t ret = READ_ALLONE_CMD_FAIL; + + /** Workaround solution for M031 with 512KB Flash uses FMC Read command instead of FMC All-One-Verification command to + * check the Flash content from 0x40000 to 0x401FF. + */ + if(u32addr == FMC_APROM_BANK1_BASE) + { + uint32_t i; + u32count = u32count - FMC_CHECKALLONE_UNIT; + for(i = FMC_APROM_BANK1_BASE; i < (FMC_APROM_BANK1_BASE + FMC_CHECKALLONE_UNIT); i = i+4) + { + if( FMC_Read(i) != 0xFFFFFFFF) + return READ_ALLONE_NOT; + } + + if(u32count == 0) + return READ_ALLONE_YES; + else + u32addr = u32addr + FMC_CHECKALLONE_UNIT; + } + + FMC->ISPSTS = 0x80UL; /* clear check all one bit */ + + FMC->ISPCMD = FMC_ISPCMD_RUN_ALL1; + FMC->ISPADDR = u32addr; + FMC->ISPDAT = u32count; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } + + do + { + FMC->ISPCMD = FMC_ISPCMD_READ_ALL1; + FMC->ISPADDR = u32addr; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } + } + while (FMC->ISPDAT == 0UL); + + if (FMC->ISPDAT == READ_ALLONE_YES) + { + ret = FMC->ISPDAT; + } + + if (FMC->ISPDAT == READ_ALLONE_NOT) + { + ret = FMC->ISPDAT; + } + + return ret; +} + +/** + * @brief Write Multi-Word bytes to flash + * + * @param[in] u32Addr Start flash address in APROM where the data chunk to be programmed into. + * This address must be 8-bytes aligned to flash address. + * @param[in] pu32Buf Buffer that carry the data chunk. + * @param[in] u32Len Length of the data chunk in bytes. + * + * @retval >=0 Number of data bytes were programmed. + * @return -1 Invalid address. + * + * @detail Program Multi-Word data into specified address of flash. + */ +#if defined ( __CC_ARM ) +#pragma arm section code="fastcode" +int32_t FMC_WriteMultiple(uint32_t u32Addr, uint32_t pu32Buf[], uint32_t u32Len) + +#elif defined ( __ICCARM__ ) +int32_t FMC_WriteMultiple(uint32_t u32Addr, uint32_t pu32Buf[], uint32_t u32Len) @ "fastcode" + +#elif defined ( __GNUC__ ) +#pragma GCC push_options +#pragma GCC optimize ("O0") +__attribute__ ((used, long_call, section(".fastcode"))) int32_t FMC_WriteMultiple(uint32_t u32Addr, uint32_t pu32Buf[], uint32_t u32Len) + +#else +int32_t FMC_WriteMultiple(uint32_t u32Addr, uint32_t pu32Buf[], uint32_t u32Len) +#endif +{ + + uint32_t i, idx, u32OnProg, retval = 0; + int32_t err; + + if ((u32Addr % 8) != 0) + { + return -1; + } + + idx = 0u; + FMC->ISPCMD = FMC_ISPCMD_MULTI_PROG; + FMC->ISPADDR = u32Addr; + retval += 16; + do + { + err = 0; + u32OnProg = 1u; + FMC->MPDAT0 = pu32Buf[idx + 0u]; + FMC->MPDAT1 = pu32Buf[idx + 1u]; + FMC->MPDAT2 = pu32Buf[idx + 2u]; + FMC->MPDAT3 = pu32Buf[idx + 3u]; + FMC->ISPTRG = 0x1u; + idx += 4u; + + for (i = idx; i < (FMC_MULTI_WORD_PROG_LEN / 4u); i += 4u) /* Max data length is 256 bytes (512/4 words)*/ + { + __set_PRIMASK(1u); /* Mask interrupt to avoid status check coherence error*/ + do + { + if ((FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk) == 0u) + { + __set_PRIMASK(0u); + + FMC->ISPADDR = FMC->MPADDR & (~0xful); + idx = (FMC->ISPADDR - u32Addr) / 4u; + err = -1; + } + } + while ((FMC->MPSTS & (3u << FMC_MPSTS_D0_Pos)) && (err == 0)); + + if (err == 0) + { + retval += 8; + + /* Update new data for D0 */ + FMC->MPDAT0 = pu32Buf[i]; + FMC->MPDAT1 = pu32Buf[i + 1u]; + do + { + if ((FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk) == 0u) + { + __set_PRIMASK(0u); + FMC->ISPADDR = FMC->MPADDR & (~0xful); + idx = (FMC->ISPADDR - u32Addr) / 4u; + err = -1; + } + } + while ((FMC->MPSTS & (3u << FMC_MPSTS_D2_Pos)) && (err == 0)); + + if (err == 0) + { + retval += 8; + + /* Update new data for D2*/ + FMC->MPDAT2 = pu32Buf[i + 2u]; + FMC->MPDAT3 = pu32Buf[i + 3u]; + __set_PRIMASK(0u); + } + } + + if (err < 0) + { + break; + } + } + if (err == 0) + { + u32OnProg = 0u; + while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } + } + } + while (u32OnProg); + return retval; +} +#if defined ( __CC_ARM ) +#pragma arm section + +#elif defined ( __GNUC__ ) +#pragma GCC pop_options + +#endif + +/*@}*/ /* end of group FMC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group FMC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + + diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_gpio.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_gpio.c new file mode 100644 index 0000000000..e0644a56fc --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_gpio.c @@ -0,0 +1,108 @@ +/**************************************************************************//** + * @file gpio.c + * @version V3.00 + * $Revision: 2 $ + * $Date: 18/03/28 5:52p $ + * @brief M031 Series General Purpose I/O (GPIO) Driver Source File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#include "M031Series.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup GPIO_Driver GPIO Driver + @{ +*/ + +/** @addtogroup GPIO_EXPORTED_FUNCTIONS GPIO Exported Functions + @{ +*/ + +/** + * @brief Set GPIO operation mode + * @param[in] port GPIO port. It could be PA, PB, PC, PD, or PF. + * @param[in] u32PinMask The single or multiple pins of specified GPIO port. + * It could be BIT0 ~ BIT15 for PA and PB. + * It could be BIT0 ~ BIT7, and BIT14 for PC. + * It could be BIT0 ~ BIT3, and BIT15 for PD. + * It could be BIT0 ~ BIT6, BIT14, and BIT15 for PF. + * @param[in] u32Mode Operation mode. It could be + * - \ref GPIO_MODE_INPUT + * - \ref GPIO_MODE_OUTPUT + * - \ref GPIO_MODE_OPEN_DRAIN + * - \ref GPIO_MODE_QUASI + * @return None + * @details This function is used to set specified GPIO operation mode. + */ +void GPIO_SetMode(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode) +{ + uint32_t i; + + for(i = 0; i < GPIO_PIN_MAX; i++) + { + if(u32PinMask & (1 << i)) + { + port->MODE = (port->MODE & ~(GPIO_MODE_MODE0_Msk << (i << 1))) | (u32Mode << (i << 1)); + } + } +} + +/** + * @brief Enable GPIO interrupt + * @param[in] port GPIO port. It could be PA, PB, PC, PD, or PF. + * @param[in] u32Pin The pin of specified GPIO port. + * It could be 0 ~ 15 for PA and PB. + * It could be 0 ~ 7, and 14 for PC. + * It could be 0 ~ 3, and 15 for PD. + * It could be 0 ~ 6, 14, and 15 for PF. + * @param[in] u32IntAttribs The interrupt attribute of specified GPIO pin. It could be + * - \ref GPIO_INT_RISING + * - \ref GPIO_INT_FALLING + * - \ref GPIO_INT_BOTH_EDGE + * - \ref GPIO_INT_HIGH + * - \ref GPIO_INT_LOW + * @return None + * @details This function is used to enable specified GPIO pin interrupt. + */ +void GPIO_EnableInt(GPIO_T *port, uint32_t u32Pin, uint32_t u32IntAttribs) +{ + /* Configure interrupt mode of specified pin */ + port->INTTYPE |= (((u32IntAttribs >> 24) & 0xFFUL) << u32Pin); + + /* Enable interrupt function of specified pin */ + port->INTEN |= ((u32IntAttribs & 0xFFFFFFUL) << u32Pin); +} + +/** + * @brief Disable GPIO interrupt + * @param[in] port GPIO port. It could be PA, PB, PC, PD, or PF. + * @param[in] u32Pin The pin of specified GPIO port. + * It could be 0 ~ 15 for PA and PB. + * It could be 0 ~ 7, and 14 for PC. + * It could be 0 ~ 3, and 15 for PD. + * It could be 0 ~ 6, 14, and 15 for PF. + * @return None + * @details This function is used to enable specified GPIO pin interrupt. + */ +void GPIO_DisableInt(GPIO_T *port, uint32_t u32Pin) +{ + /* Configure interrupt mode of specified pin */ + port->INTTYPE &= ~(1UL << u32Pin); + + /* Disable interrupt function of specified pin */ + port->INTEN &= ~((0x00010001UL) << u32Pin); +} + + +/*@}*/ /* end of group GPIO_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group GPIO_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_i2c.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_i2c.c new file mode 100644 index 0000000000..e4f99a7769 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_i2c.c @@ -0,0 +1,1582 @@ +/**************************************************************************//** + * @file i2c.c + * @version V1.00 + * @brief M031 series I2C driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#include "M031Series.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup I2C_Driver I2C Driver + @{ +*/ + + +/** @addtogroup I2C_EXPORTED_FUNCTIONS I2C Exported Functions + @{ +*/ + +/** + * @brief Enable specify I2C Controller and set Clock Divider + * + * @param[in] i2c Specify I2C port + * @param[in] u32BusClock The target I2C bus clock in Hz + * + * @return Actual I2C bus clock frequency + * + * @details The function enable the specify I2C Controller and set proper Clock Divider + * in I2C CLOCK DIVIDED REGISTER (I2CLK) according to the target I2C Bus clock. + * I2C Bus clock = PCLK / (4*(divider+1). + * + */ +uint32_t I2C_Open(I2C_T *i2c, uint32_t u32BusClock) +{ + uint32_t u32Div; + uint32_t u32Pclk; + + if (i2c == I2C1) + { + u32Pclk = CLK_GetPCLK1Freq(); + } + else + { + u32Pclk = CLK_GetPCLK0Freq(); + } + + u32Div = (uint32_t)(((u32Pclk * 10U) / (u32BusClock * 4U) + 5U) / 10U - 1U); /* Compute proper divider for I2C clock */ + i2c->CLKDIV = u32Div; + + /* Enable I2C */ + i2c->CTL0 |= I2C_CTL0_I2CEN_Msk; + + return (u32Pclk / ((u32Div + 1U) << 2U)); +} + +/** + * @brief Disable specify I2C Controller + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details Reset I2C Controller and disable specify I2C port. + * + */ + +void I2C_Close(I2C_T *i2c) +{ + /* Reset I2C Controller */ + if (i2c == I2C0) + { + SYS->IPRST1 |= SYS_IPRST1_I2C0RST_Msk; + SYS->IPRST1 &= ~SYS_IPRST1_I2C0RST_Msk; + } + else if (i2c == I2C1) + { + SYS->IPRST1 |= SYS_IPRST1_I2C1RST_Msk; + SYS->IPRST1 &= ~SYS_IPRST1_I2C1RST_Msk; + } + + /* Disable I2C */ + i2c->CTL0 &= ~I2C_CTL0_I2CEN_Msk; +} + +/** + * @brief Clear Time-out Counter flag + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details When Time-out flag will be set, use this function to clear I2C Bus Time-out counter flag . + * + */ +void I2C_ClearTimeoutFlag(I2C_T *i2c) +{ + i2c->TOCTL |= I2C_TOCTL_TOIF_Msk; +} + +/** + * @brief Set Control bit of I2C Controller + * + * @param[in] i2c Specify I2C port + * @param[in] u8Start Set I2C START condition + * @param[in] u8Stop Set I2C STOP condition + * @param[in] u8Si Clear SI flag + * @param[in] u8Ack Set I2C ACK bit + * + * @return None + * + * @details The function set I2C Control bit of I2C Bus protocol. + * + */ +void I2C_Trigger(I2C_T *i2c, uint8_t u8Start, uint8_t u8Stop, uint8_t u8Si, uint8_t u8Ack) +{ + uint32_t u32Reg = 0U; + + if (u8Start) + { + u32Reg |= I2C_CTL_STA; + } + + if (u8Stop) + { + u32Reg |= I2C_CTL_STO; + } + + if (u8Si) + { + u32Reg |= I2C_CTL_SI; + } + + if (u8Ack) + { + u32Reg |= I2C_CTL_AA; + } + + i2c->CTL0 = (i2c->CTL0 & ~0x3CU) | u32Reg; +} + +/** + * @brief Disable Interrupt of I2C Controller + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details The function is used for disable I2C interrupt + * + */ +void I2C_DisableInt(I2C_T *i2c) +{ + i2c->CTL0 &= ~I2C_CTL0_INTEN_Msk; +} + +/** + * @brief Enable Interrupt of I2C Controller + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details The function is used for enable I2C interrupt + * + */ +void I2C_EnableInt(I2C_T *i2c) +{ + i2c->CTL0 |= I2C_CTL0_INTEN_Msk; +} + +/** + * @brief Get I2C Bus Clock + * + * @param[in] i2c Specify I2C port + * + * @return The actual I2C Bus clock in Hz + * + * @details To get the actual I2C Bus Clock frequency. + */ +uint32_t I2C_GetBusClockFreq(I2C_T *i2c) +{ + uint32_t u32Divider = i2c->CLKDIV; + uint32_t u32Pclk; + + if (i2c == I2C1) + { + u32Pclk = CLK_GetPCLK1Freq(); + } + else + { + u32Pclk = CLK_GetPCLK0Freq(); + } + + return (u32Pclk / ((u32Divider + 1U) << 2U)); +} + +/** + * @brief Set I2C Bus Clock + * + * @param[in] i2c Specify I2C port + * @param[in] u32BusClock The target I2C Bus Clock in Hz + * + * @return The actual I2C Bus Clock in Hz + * + * @details To set the actual I2C Bus Clock frequency. + */ +uint32_t I2C_SetBusClockFreq(I2C_T *i2c, uint32_t u32BusClock) +{ + uint32_t u32Div; + uint32_t u32Pclk; + + if (i2c == I2C1) + { + u32Pclk = CLK_GetPCLK1Freq(); + } + else + { + u32Pclk = CLK_GetPCLK0Freq(); + } + + u32Div = (uint32_t)(((u32Pclk * 10U) / (u32BusClock * 4U) + 5U) / 10U - 1U); /* Compute proper divider for I2C clock */ + i2c->CLKDIV = u32Div; + + return (u32Pclk / ((u32Div + 1U) << 2U)); +} + +/** + * @brief Get Interrupt Flag + * + * @param[in] i2c Specify I2C port + * + * @return I2C interrupt flag status + * + * @details To get I2C Bus interrupt flag. + */ +uint32_t I2C_GetIntFlag(I2C_T *i2c) +{ + return ((i2c->CTL0 & I2C_CTL0_SI_Msk) == I2C_CTL0_SI_Msk ? 1U : 0U); +} + +/** + * @brief Get I2C Bus Status Code + * + * @param[in] i2c Specify I2C port + * + * @return I2C Status Code + * + * @details To get I2C Bus Status Code. + */ +uint32_t I2C_GetStatus(I2C_T *i2c) +{ + return (i2c->STATUS0); +} + +/** + * @brief Read a Byte from I2C Bus + * + * @param[in] i2c Specify I2C port + * + * @return I2C Data + * + * @details To read a bytes data from specify I2C port. + */ +uint8_t I2C_GetData(I2C_T *i2c) +{ + return (uint8_t)(i2c->DAT); +} + +/** + * @brief Send a byte to I2C Bus + * + * @param[in] i2c Specify I2C port + * @param[in] u8Data The data to send to I2C bus + * + * @return None + * + * @details This function is used to write a byte to specified I2C port + */ +void I2C_SetData(I2C_T *i2c, uint8_t u8Data) +{ + i2c->DAT = u8Data; +} + +/** + * @brief Set 7-bit Slave Address and GC Mode + * + * @param[in] i2c Specify I2C port + * @param[in] u8SlaveNo Set the number of I2C address register (0~3) + * @param[in] u8SlaveAddr 7-bit slave address + * @param[in] u8GCMode Enable/Disable GC mode (I2C_GCMODE_ENABLE / I2C_GCMODE_DISABLE) + * + * @return None + * + * @details This function is used to set 7-bit slave addresses in I2C SLAVE ADDRESS REGISTER (I2C_ADDR0~3) + * and enable GC Mode. + * + */ +void I2C_SetSlaveAddr(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddr, uint8_t u8GCMode) +{ + switch (u8SlaveNo) + { + case 1: + i2c->ADDR1 = ((uint32_t)u8SlaveAddr << 1U); + break; + + case 2: + i2c->ADDR2 = ((uint32_t)u8SlaveAddr << 1U); + break; + + case 3: + i2c->ADDR3 = ((uint32_t)u8SlaveAddr << 1U); + break; + + case 0: + default: + i2c->ADDR0 = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode; + break; + } +} + +/** + * @brief Configure the mask bits of 7-bit Slave Address + * + * @param[in] i2c Specify I2C port + * @param[in] u8SlaveNo Set the number of I2C address mask register (0~3) + * @param[in] u8SlaveAddrMask A byte for slave address mask + * + * @return None + * + * @details This function is used to set 7-bit slave addresses. + * + */ +void I2C_SetSlaveAddrMask(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddrMask) +{ + switch (u8SlaveNo) + { + case 1: + i2c->ADDRMSK1 = (uint32_t)u8SlaveAddrMask << 1U; + break; + + case 2: + i2c->ADDRMSK2 = (uint32_t)u8SlaveAddrMask << 1U; + break; + + case 3: + i2c->ADDRMSK3 = (uint32_t)u8SlaveAddrMask << 1U; + break; + + case 0: + default: + i2c->ADDRMSK0 = (uint32_t)u8SlaveAddrMask << 1U; + break; + } +} + +/** + * @brief Enable Time-out Counter Function and support Long Time-out + * + * @param[in] i2c Specify I2C port + * @param[in] u8LongTimeout Configure DIV4 to enable Long Time-out (0/1) + * + * @return None + * + * @details This function enable Time-out Counter function and configure DIV4 to support Long + * Time-out. + * + */ +void I2C_EnableTimeout(I2C_T *i2c, uint8_t u8LongTimeout) +{ + if (u8LongTimeout) + { + i2c->TOCTL |= I2C_TOCTL_TOCDIV4_Msk; + } + else + { + i2c->TOCTL &= ~I2C_TOCTL_TOCDIV4_Msk; + } + + i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk; +} + +/** + * @brief Disable Time-out Counter Function + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details To disable Time-out Counter function in I2C_TOCTL register. + * + */ +void I2C_DisableTimeout(I2C_T *i2c) +{ + i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk; +} + +/** + * @brief Enable I2C Wake-up Function + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details To enable Wake-up function of I2C Wake-up control register. + * + */ +void I2C_EnableWakeup(I2C_T *i2c) +{ + i2c->WKCTL |= I2C_WKCTL_WKEN_Msk; +} + +/** + * @brief Disable I2C Wake-up Function + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details To disable Wake-up function of I2C Wake-up control register. + * + */ +void I2C_DisableWakeup(I2C_T *i2c) +{ + i2c->WKCTL &= ~I2C_WKCTL_WKEN_Msk; +} + +/** + * @brief To get SMBus Status + * + * @param[in] i2c Specify I2C port + * + * @return SMBus status + * + * @details To get the Bus Management status of I2C_BUSSTS register + * + */ +uint32_t I2C_SMBusGetStatus(I2C_T *i2c) +{ + return (i2c->BUSSTS); +} + +/** + * @brief Clear SMBus Interrupt Flag + * + * @param[in] i2c Specify I2C port + * @param[in] u8SMBusIntFlag Specify SMBus interrupt flag + * + * @return None + * + * @details To clear flags of I2C_BUSSTS status register if interrupt set. + * + */ +void I2C_SMBusClearInterruptFlag(I2C_T *i2c, uint8_t u8SMBusIntFlag) +{ + i2c->BUSSTS = u8SMBusIntFlag; +} + +/** + * @brief Set SMBus Bytes Counts of Transmission or Reception + * + * @param[in] i2c Specify I2C port + * @param[in] u32PktSize Transmit / Receive bytes + * + * @return None + * + * @details The transmission or receive byte number in one transaction when PECEN is set. The maximum is 255 bytes. + * + */ +void I2C_SMBusSetPacketByteCount(I2C_T *i2c, uint32_t u32PktSize) +{ + i2c->PKTSIZE = u32PktSize; +} + +/** + * @brief Init SMBus Host/Device Mode + * + * @param[in] i2c Specify I2C port + * @param[in] u8HostDevice Init SMBus port mode(I2C_SMBH_ENABLE/I2C_SMBD_ENABLE) + * + * @return None + * + * @details Using SMBus communication must specify the port is a Host or a Device. + * + */ +void I2C_SMBusOpen(I2C_T *i2c, uint8_t u8HostDevice) +{ + /* Clear BMHEN, BMDEN of BUSCTL Register */ + i2c->BUSCTL &= ~(I2C_BUSCTL_BMHEN_Msk | I2C_BUSCTL_BMDEN_Msk); + + /* Set SMBus Host/Device Mode, and enable Bus Management*/ + if(u8HostDevice == (uint8_t)I2C_SMBH_ENABLE) + { + i2c->BUSCTL |= (I2C_BUSCTL_BMHEN_Msk | I2C_BUSCTL_BUSEN_Msk); + } + else + { + i2c->BUSCTL |= (I2C_BUSCTL_BMDEN_Msk | I2C_BUSCTL_BUSEN_Msk); + } +} + +/** + * @brief Disable SMBus function + * + * @param[in] i2c Specify I2C port + * + * @return None + * + * @details Disable all SMBus function include Bus disable, CRC check, Acknowledge by manual, Host/Device Mode. + * + */ +void I2C_SMBusClose(I2C_T *i2c) +{ + + i2c->BUSCTL = 0x00U; +} + +/** + * @brief Enable SMBus PEC Transmit Function + * + * @param[in] i2c Specify I2C port + * @param[in] u8PECTxEn CRC transmit enable(PECTX_ENABLE) or disable(PECTX_DISABLE) + * + * @return None + * + * @details When enable CRC check function, the Host or Device needs to transmit CRC byte. + * + */ +void I2C_SMBusPECTxEnable(I2C_T *i2c, uint8_t u8PECTxEn) +{ + i2c->BUSCTL &= ~I2C_BUSCTL_PECTXEN_Msk; + + if(u8PECTxEn) + { + i2c->BUSCTL |= (I2C_BUSCTL_PECEN_Msk | I2C_BUSCTL_PECTXEN_Msk); + } + else + { + i2c->BUSCTL |= I2C_BUSCTL_PECEN_Msk; + } +} + +/** + * @brief Get SMBus CRC value + * + * @param[in] i2c Specify I2C port + * + * @return A byte is packet error check value + * + * @details The CRC check value after a transmission or a reception by count by using CRC8 + * + */ +uint8_t I2C_SMBusGetPECValue(I2C_T *i2c) +{ + return (uint8_t)i2c->PKTCRC; +} + +/** + * @brief Calculate Time-out of SMBus idle period + * + * @param[in] i2c Specify I2C port + * @param[in] us Time-out length(us) + * @param[in] u32Hclk I2C peripheral clock frequency + * + * @return None + * + * @details This function is used to set SMBus Time-out length when bus is in Idle state. + * + */ + +void I2C_SMBusIdleTimeout(I2C_T *i2c, uint32_t us, uint32_t u32Hclk) +{ + uint32_t u32Div, u32Hclk_kHz; + + i2c->BUSCTL |= I2C_BUSCTL_TIDLE_Msk; + u32Hclk_kHz = u32Hclk / 1000U; + u32Div = (((us * u32Hclk_kHz) / 1000U) >> 2U) - 1U; + if(u32Div > 255U) + { + i2c->BUSTOUT = 0xFFU; + } + else + { + i2c->BUSTOUT = u32Div; + } + +} + +/** + * @brief Calculate Time-out of SMBus active period + * + * @param[in] i2c Specify I2C port + * @param[in] ms Time-out length(ms) + * @param[in] u32Pclk peripheral clock frequency + * + * @return None + * + * @details This function is used to set SMBus Time-out length when bus is in active state. + * Time-out length is calculate the SCL line "one clock" pull low timing. + * + */ + +void I2C_SMBusTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk) +{ + uint32_t u32Div, u32Pclk_kHz; + + i2c->BUSCTL &= ~I2C_BUSCTL_TIDLE_Msk; + + /* DIV4 disabled */ + i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk; + u32Pclk_kHz = u32Pclk / 1000U; + u32Div = ((ms * u32Pclk_kHz) / (16U * 1024U)) - 1U; + if(u32Div <= 0xFFU) + { + i2c->BUSTOUT = u32Div; + } + else + { + /* DIV4 enabled */ + i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk; + i2c->BUSTOUT = (((ms * u32Pclk_kHz) / (16U * 1024U * 4U)) - 1U) & 0xFFU; /* The max value is 255 */ + } +} + +/** + * @brief Calculate Cumulative Clock low Time-out of SMBus active period + * + * @param[in] i2c Specify I2C port + * @param[in] ms Time-out length(ms) + * @param[in] u32Pclk peripheral clock frequency + * + * @return None + * + * @details This function is used to set SMBus Time-out length when bus is in Active state. + * Time-out length is calculate the SCL line "clocks" low cumulative timing. + * + */ + +void I2C_SMBusClockLoTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk) +{ + uint32_t u32Div, u32Pclk_kHz; + + i2c->BUSCTL &= ~I2C_BUSCTL_TIDLE_Msk; + + /* DIV4 disabled */ + i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk; + u32Pclk_kHz = u32Pclk / 1000U; + u32Div = ((ms * u32Pclk_kHz) / (16U * 1024U)) - 1U; + if(u32Div <= 0xFFU) + { + i2c->CLKTOUT = u32Div; + } + else + { + /* DIV4 enabled */ + i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk; + i2c->CLKTOUT = (((ms * u32Pclk_kHz) / (16U * 1024U * 4U)) - 1U) & 0xFFU; /* The max value is 255 */ + } +} + +/** + * @brief Write a byte to Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] data Write a byte data to Slave + * + * @retval 0 Write data success + * @retval 1 Write data fail, or bus occurs error events + * + * @details The function is used for I2C Master write a byte data to Slave. + * + */ + +uint8_t I2C_WriteByte(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t data) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Ctrl = 0U; + + I2C_START(i2c); + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1U | 0x00U)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x18: /* Slave Address ACK */ + I2C_SET_DATA(i2c, data); /* Write data to I2CDAT */ + break; + + case 0x20: /* Slave Address NACK */ + case 0x30: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x28: + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + return (u8Err | u8Xfering); /* return (Success)/(Fail) status */ +} + +/** + * @brief Write multi bytes to Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] data[] Pointer to array to write data to Slave + * @param[in] u32wLen How many bytes need to write to Slave + * + * @return A length of how many bytes have been transmitted. + * + * @details The function is used for I2C Master write multi bytes data to Slave. + * + */ + +uint32_t I2C_WriteMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t data[], uint32_t u32wLen) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Ctrl = 0U; + uint32_t u32txLen = 0U; + + I2C_START(i2c); /* Send START */ + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1U | 0x00U)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x18: /* Slave Address ACK */ + case 0x28: + if (u32txLen < u32wLen) + I2C_SET_DATA(i2c, data[u32txLen++]); /* Write Data to I2CDAT */ + else + { + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + } + + break; + + case 0x20: /* Slave Address NACK */ + case 0x30: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + return u32txLen; /* Return bytes length that have been transmitted */ +} + +/** + * @brief Specify a byte register address and write a byte to Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u8DataAddr Specify a address (1 byte) of data write to + * @param[in] data A byte data to write it to Slave + * + * @retval 0 Write data success + * @retval 1 Write data fail, or bus occurs error events + * + * @details The function is used for I2C Master specify a address that data write to in Slave. + * + */ + +uint8_t I2C_WriteByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t data) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Ctrl = 0U; + uint32_t u32txLen = 0U; + + I2C_START(i2c); /* Send START */ + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1U | 0x00U)); /* Send Slave address with write bit */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x18: /* Slave Address ACK */ + I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */ + break; + + case 0x20: /* Slave Address NACK */ + case 0x30: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x28: + if (u32txLen < 1U) + { + I2C_SET_DATA(i2c, data); + u32txLen++; + } + else + { + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + } + + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + return (u8Err | u8Xfering); /* return (Success)/(Fail) status */ +} + + +/** + * @brief Specify a byte register address and write multi bytes to Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u8DataAddr Specify a address (1 byte) of data write to + * @param[in] data[] Pointer to array to write data to Slave + * @param[in] u32wLen How many bytes need to write to Slave + * + * @return A length of how many bytes have been transmitted. + * + * @details The function is used for I2C Master specify a byte address that multi data bytes write to in Slave. + * + */ + +uint32_t I2C_WriteMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t data[], uint32_t u32wLen) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Ctrl = 0U; + uint32_t u32txLen = 0U; + + I2C_START(i2c); /* Send START */ + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1U | 0x00U)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; + break; + + case 0x18: /* Slave Address ACK */ + I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */ + break; + + case 0x20: /* Slave Address NACK */ + case 0x30: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x28: + if (u32txLen < u32wLen) + I2C_SET_DATA(i2c, data[u32txLen++]); + else + { + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + } + + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + return u32txLen; /* Return bytes length that have been transmitted */ +} + +/** + * @brief Specify two bytes register address and Write a byte to Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u16DataAddr Specify a address (2 byte) of data write to + * @param[in] data Write a byte data to Slave + * + * @retval 0 Write data success + * @retval 1 Write data fail, or bus occurs error events + * + * @details The function is used for I2C Master specify two bytes address that data write to in Slave. + * + */ + +uint8_t I2C_WriteByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t data) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Addr = 1U, u8Ctrl = 0U; + uint32_t u32txLen = 0U; + + I2C_START(i2c); /* Send START */ + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1U | 0x00U)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x18: /* Slave Address ACK */ + I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00U) >> 8U)); /* Write Hi byte address of register */ + break; + + case 0x20: /* Slave Address NACK */ + case 0x30: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1; + break; + + case 0x28: + if (u8Addr) + { + I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFU)); /* Write Lo byte address of register */ + u8Addr = 0U; + } + else if ((u32txLen < 1U) && (u8Addr == 0U)) + { + I2C_SET_DATA(i2c, data); + u32txLen++; + } + else + { + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + } + + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + return (u8Err | u8Xfering); /* return (Success)/(Fail) status */ +} + + +/** + * @brief Specify two bytes register address and write multi bytes to Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u16DataAddr Specify a address (2 bytes) of data write to + * @param[in] data[] A data array for write data to Slave + * @param[in] u32wLen How many bytes need to write to Slave + * + * @return A length of how many bytes have been transmitted. + * + * @details The function is used for I2C Master specify two bytes address that multi data write to in Slave. + * + */ + +uint32_t I2C_WriteMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t data[], uint32_t u32wLen) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Addr = 1U, u8Ctrl = 0U; + uint32_t u32txLen = 0U; + + I2C_START(i2c); /* Send START */ + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1U | 0x00U)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x18: /* Slave Address ACK */ + I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00U) >> 8U)); /* Write Hi byte address of register */ + break; + + case 0x20: /* Slave Address NACK */ + case 0x30: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x28: + if (u8Addr) + { + I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFU)); /* Write Lo byte address of register */ + u8Addr = 0U; + } + else if ((u32txLen < u32wLen) && (u8Addr == 0U)) + I2C_SET_DATA(i2c, data[u32txLen++]); /* Write data to Register I2CDAT*/ + else + { + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + } + + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + return u32txLen; /* Return bytes length that have been transmitted */ +} + +/** + * @brief Read a byte from Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * + * @return Read a byte data from Slave + * + * @details The function is used for I2C Master to read a byte data from Slave. + * + */ +uint8_t I2C_ReadByte(I2C_T *i2c, uint8_t u8SlaveAddr) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, rdata = 0U, u8Ctrl = 0U; + + I2C_START(i2c); /* Send START */ + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1U) | 0x01U)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x40: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x48: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x58: + rdata = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + if (u8Err) + rdata = 0U; /* If occurs error, return 0 */ + + return rdata; /* Return read data */ +} +/** + * @brief Read multi bytes from Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[out] rdata[] A data array to store data from Slave + * @param[in] u32rLen How many bytes need to read from Slave + * + * @return A length of how many bytes have been received + * + * @details The function is used for I2C Master to read multi data bytes from Slave. + * + * + */ +uint32_t I2C_ReadMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t rdata[], uint32_t u32rLen) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Ctrl = 0U; + uint32_t u32rxLen = 0U; + + I2C_START(i2c); /* Send START */ + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1U) | 0x01U)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x40: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */ + break; + + case 0x48: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1; + break; + + case 0x50: + rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */ + + if (u32rxLen < (u32rLen - 1)) + { + u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */ + } + else + { + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + } + + break; + + case 0x58: + rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + return u32rxLen; /* Return bytes length that have been received */ +} + + +/** + * @brief Specify a byte register address and read a byte from Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u8DataAddr Specify a address(1 byte) of data read from + * + * @return Read a byte data from Slave + * + * @details The function is used for I2C Master specify a byte address that a data byte read from Slave. + * + * + */ +uint8_t I2C_ReadByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, rdata = 0U, u8Ctrl = 0U; + + I2C_START(i2c); /* Send START */ + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1U | 0x00U)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x18: /* Slave Address ACK */ + I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */ + break; + + case 0x20: /* Slave Address NACK */ + case 0x30: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x28: + u8Ctrl = I2C_CTL_STA_SI; /* Send repeat START */ + break; + + case 0x10: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1U) | 0x01U)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x40: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x48: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x58: + rdata = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + if (u8Err) + rdata = 0U; /* If occurs error, return 0 */ + + return rdata; /* Return read data */ +} + +/** + * @brief Specify a byte register address and read multi bytes from Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u8DataAddr Specify a address (1 byte) of data read from + * @param[out] rdata[] A data array to store data from Slave + * @param[in] u32rLen How many bytes need to read from Slave + * + * @return A length of how many bytes have been received + * + * @details The function is used for I2C Master specify a byte address that multi data bytes read from Slave. + * + * + */ +uint32_t I2C_ReadMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t rdata[], uint32_t u32rLen) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Ctrl = 0U; + uint32_t u32rxLen = 0U; + + I2C_START(i2c); /* Send START */ + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1U | 0x00U)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x18: /* Slave Address ACK */ + I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */ + break; + + case 0x20: /* Slave Address NACK */ + case 0x30: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x28: + u8Ctrl = I2C_CTL_STA_SI; /* Send repeat START */ + break; + + case 0x10: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1U) | 0x01U)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x40: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */ + break; + + case 0x48: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x50: + rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */ + + if (u32rxLen < (u32rLen - 1U)) + u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */ + else + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + + break; + + case 0x58: + rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + return u32rxLen; /* Return bytes length that have been received */ +} + +/** + * @brief Specify two bytes register address and read a byte from Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u16DataAddr Specify an address(2 bytes) of data read from + * + * @return Read a byte data from Slave + * + * @details The function is used for I2C Master specify two bytes address that a data byte read from Slave. + * + * + */ +uint8_t I2C_ReadByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, rdata = 0U, u8Addr = 1U, u8Ctrl = 0U; + + I2C_START(i2c); /* Send START */ + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1U | 0x00U)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x18: /* Slave Address ACK */ + I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00U) >> 8U));/* Write Hi byte address of register */ + break; + + case 0x20: /* Slave Address NACK */ + case 0x30: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x28: + if (u8Addr) + { + I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFU)); /* Write Lo byte address of register */ + u8Addr = 0U; + } + else + u8Ctrl = I2C_CTL_STA_SI; /* Clear SI and send repeat START */ + + break; + + case 0x10: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1U) | 0x01U)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x40: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x48: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x58: + rdata = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + if (u8Err) + rdata = 0U; /* If occurs error, return 0 */ + + return rdata; /* Return read data */ +} + +/** + * @brief Specify two bytes register address and read multi bytes from Slave + * + * @param[in] i2c Point to I2C peripheral + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u16DataAddr Specify a address (2 bytes) of data read from + * @param[out] rdata[] A data array to store data from Slave + * @param[in] u32rLen How many bytes need to read from Slave + * + * @return A length of how many bytes have been received + * + * @details The function is used for I2C Master specify two bytes address that multi data bytes read from Slave. + * + * + */ +uint32_t I2C_ReadMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t rdata[], uint32_t u32rLen) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Addr = 1U, u8Ctrl = 0U; + uint32_t u32rxLen = 0U; + + I2C_START(i2c); /* Send START */ + + while (u8Xfering && (u8Err == 0U)) + { + I2C_WAIT_READY(i2c) {} + + switch (I2C_GET_STATUS(i2c)) + { + case 0x08: + I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1U | 0x00U)); /* Write SLA+W to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x18: /* Slave Address ACK */ + I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00U) >> 8U));/* Write Hi byte address of register */ + break; + + case 0x20: /* Slave Address NACK */ + case 0x30: /* Master transmit data NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x28: + if (u8Addr) + { + I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFU)); /* Write Lo byte address of register */ + u8Addr = 0U; + } + else + u8Ctrl = I2C_CTL_STA_SI; /* Clear SI and send repeat START */ + + break; + + case 0x10: + I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1U) | 0x01U)); /* Write SLA+R to Register I2CDAT */ + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + break; + + case 0x40: /* Slave Address ACK */ + u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */ + break; + + case 0x48: /* Slave Address NACK */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case 0x50: + rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */ + + if (u32rxLen < (u32rLen - 1U)) + { + u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */ + } + else + { + u8Ctrl = I2C_CTL_SI; /* Clear SI */ + } + + break; + + case 0x58: + rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */ + u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */ + u8Xfering = 0U; + break; + + case 0x38: /* Arbitration Lost */ + default: /* Unknow status */ + I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */ + u8Ctrl = I2C_CTL_SI; + u8Err = 1U; + break; + } + + I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */ + } + + return u32rxLen; /* Return bytes length that have been received */ +} + + +/*@}*/ /* end of group I2C_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group I2C_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_pdma.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_pdma.c new file mode 100644 index 0000000000..78dcdf4248 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_pdma.c @@ -0,0 +1,412 @@ +/**************************************************************************//** + * @file pdma.c + * @version V1.00 + * @brief M031 series PDMA driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "M031Series.h" + + +static uint8_t u8ChSelect[PDMA_CH_MAX]; + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup PDMA_Driver PDMA Driver + @{ +*/ + + +/** @addtogroup PDMA_EXPORTED_FUNCTIONS PDMA Exported Functions + @{ +*/ + +/** + * @brief PDMA Open + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Mask Channel enable bits. + * + * @return None + * + * @details This function enable the PDMA channels. + */ +void PDMA_Open(PDMA_T *pdma, uint32_t u32Mask) +{ + uint32_t i; + + for (i = 0UL; i < PDMA_CH_MAX; i++) + { + if((1 << i) & u32Mask) + { + pdma->DSCT[i].CTL = 0UL; + u8ChSelect[i] = PDMA_MEM; + } + } + + pdma->CHCTL |= u32Mask; +} + +/** + * @brief PDMA Close + * + * @param[in] pdma The pointer of the specified PDMA module + * + * @return None + * + * @details This function disable all PDMA channels. + */ +void PDMA_Close(PDMA_T *pdma) +{ + pdma->CHCTL = 0UL; +} + +/** + * @brief Set PDMA Transfer Count + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32Width Data width. Valid values are + * - \ref PDMA_WIDTH_8 + * - \ref PDMA_WIDTH_16 + * - \ref PDMA_WIDTH_32 + * @param[in] u32TransCount Transfer count + * + * @return None + * + * @details This function set the selected channel data width and transfer count. + */ +void PDMA_SetTransferCnt(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Width, uint32_t u32TransCount) +{ + pdma->DSCT[u32Ch].CTL &= ~(PDMA_DSCT_CTL_TXCNT_Msk | PDMA_DSCT_CTL_TXWIDTH_Msk); + pdma->DSCT[u32Ch].CTL |= (u32Width | ((u32TransCount - 1UL) << PDMA_DSCT_CTL_TXCNT_Pos)); +} + +/** + * @brief Set PDMA Transfer Address + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32SrcAddr Source address + * @param[in] u32SrcCtrl Source control attribute. Valid values are + * - \ref PDMA_SAR_INC + * - \ref PDMA_SAR_FIX + * @param[in] u32DstAddr Destination address + * @param[in] u32DstCtrl Destination control attribute. Valid values are + * - \ref PDMA_DAR_INC + * - \ref PDMA_DAR_FIX + * + * @return None + * + * @details This function set the selected channel source/destination address and attribute. + */ +void PDMA_SetTransferAddr(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32SrcAddr, uint32_t u32SrcCtrl, uint32_t u32DstAddr, uint32_t u32DstCtrl) +{ + pdma->DSCT[u32Ch].SA = u32SrcAddr; + pdma->DSCT[u32Ch].DA = u32DstAddr; + pdma->DSCT[u32Ch].CTL &= ~(PDMA_DSCT_CTL_SAINC_Msk | PDMA_DSCT_CTL_DAINC_Msk); + pdma->DSCT[u32Ch].CTL |= (u32SrcCtrl | u32DstCtrl); +} + +/** + * @brief Set PDMA Transfer Mode + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32Peripheral The selected peripheral. Valid values are + * - \ref PDMA_MEM + * - \ref PDMA_UART0_TX + * - \ref PDMA_UART0_RX + * - \ref PDMA_UART1_TX + * - \ref PDMA_UART1_RX + * - \ref PDMA_UART2_TX + * - \ref PDMA_UART2_RX + * - \ref PDMA_USCI0_TX + * - \ref PDMA_USCI0_RX + * - \ref PDMA_USCI1_TX + * - \ref PDMA_USCI1_RX + * - \ref PDMA_QSPI0_TX + * - \ref PDMA_QSPI0_RX + * - \ref PDMA_SPI0_TX + * - \ref PDMA_SPI0_RX + * - \ref PDMA_ADC_RX + * - \ref PDMA_PWM0_P1_RX + * - \ref PDMA_PWM0_P2_RX + * - \ref PDMA_PWM0_P3_RX + * - \ref PDMA_PWM1_P1_RX + * - \ref PDMA_PWM1_P2_RX + * - \ref PDMA_PWM1_P3_RX + * - \ref PDMA_I2C0_TX + * - \ref PDMA_I2C0_RX + * - \ref PDMA_I2C1_TX + * - \ref PDMA_I2C1_RX + * - \ref PDMA_TMR0 + * - \ref PDMA_TMR1 + * - \ref PDMA_TMR2 + * - \ref PDMA_TMR3 + * - \ref PDMA_UART3_TX + * - \ref PDMA_UART3_RX + * - \ref PDMA_UART4_TX + * - \ref PDMA_UART4_RX + * - \ref PDMA_UART5_TX + * - \ref PDMA_UART5_RX + * - \ref PDMA_UART6_TX + * - \ref PDMA_UART6_RX + * - \ref PDMA_UART7_TX + * - \ref PDMA_UART7_RX + * @param[in] u32ScatterEn Scatter-gather mode enable + * @param[in] u32DescAddr Scatter-gather descriptor address + * + * @return None + * + * @details This function set the selected channel transfer mode. Include peripheral setting. + */ +void PDMA_SetTransferMode(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Peripheral, uint32_t u32ScatterEn, uint32_t u32DescAddr) +{ + u8ChSelect[u32Ch] = u32Peripheral; + + switch (u32Ch) + { + case 0ul: + pdma->REQSEL0_3 = (pdma->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC0_Msk) | u32Peripheral; + break; + + case 1ul: + pdma->REQSEL0_3 = (pdma->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC1_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC1_Pos); + break; + + case 2ul: + pdma->REQSEL0_3 = (pdma->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC2_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC2_Pos); + break; + + case 3ul: + pdma->REQSEL0_3 = (pdma->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC3_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC3_Pos); + break; + + case 4ul: + pdma->REQSEL4_7 = (pdma->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC4_Msk) | u32Peripheral; + break; + + case 5ul: + pdma->REQSEL4_7 = (pdma->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC5_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC5_Pos); + break; + + case 6ul: + pdma->REQSEL4_7 = (pdma->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC6_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC6_Pos); + break; + + case 7ul: + pdma->REQSEL4_7 = (pdma->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC7_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC7_Pos); + break; + + case 8ul: + pdma->REQSEL8 = (pdma->REQSEL8 & ~PDMA_REQSEL8_REQSRC8_Msk) | u32Peripheral; + break; + + default: + break; + } + + if (u32ScatterEn) + { + pdma->DSCT[u32Ch].CTL = (pdma->DSCT[u32Ch].CTL & ~PDMA_DSCT_CTL_OPMODE_Msk) | PDMA_OP_SCATTER; + pdma->DSCT[u32Ch].NEXT = u32DescAddr - (pdma->SCATBA); + } + else + { + pdma->DSCT[u32Ch].CTL = (pdma->DSCT[u32Ch].CTL & ~PDMA_DSCT_CTL_OPMODE_Msk) | PDMA_OP_BASIC; + } +} + +/** + * @brief Set PDMA Burst Type and Size + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32BurstType Burst mode or single mode. Valid values are + * - \ref PDMA_REQ_SINGLE + * - \ref PDMA_REQ_BURST + * @param[in] u32BurstSize Set the size of burst mode. Valid values are + * - \ref PDMA_BURST_128 + * - \ref PDMA_BURST_64 + * - \ref PDMA_BURST_32 + * - \ref PDMA_BURST_16 + * - \ref PDMA_BURST_8 + * - \ref PDMA_BURST_4 + * - \ref PDMA_BURST_2 + * - \ref PDMA_BURST_1 + * + * @return None + * + * @details This function set the selected channel burst type and size. + */ +void PDMA_SetBurstType(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32BurstType, uint32_t u32BurstSize) +{ + pdma->DSCT[u32Ch].CTL &= ~(PDMA_DSCT_CTL_TXTYPE_Msk | PDMA_DSCT_CTL_BURSIZE_Msk); + pdma->DSCT[u32Ch].CTL |= (u32BurstType | u32BurstSize); +} + +/** + * @brief Enable timeout function + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Mask Channel enable bits. + * + * @return None + * + * @details This function enable timeout function of the selected channel(s). + */ +void PDMA_EnableTimeout(PDMA_T *pdma, uint32_t u32Mask) +{ + pdma->TOUTEN |= u32Mask; +} + +/** + * @brief Disable timeout function + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Mask Channel enable bits. + * + * @return None + * + * @details This function disable timeout function of the selected channel(s). + */ +void PDMA_DisableTimeout(PDMA_T *pdma, uint32_t u32Mask) +{ + pdma->TOUTEN &= ~u32Mask; +} + +/** + * @brief Set PDMA Timeout Count + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32OnOff Enable/disable time out function + * @param[in] u32TimeOutCnt Timeout count + * + * @return None + * + * @details This function set the timeout count. + * @note M031 only supported channel 0/1. + */ +void PDMA_SetTimeOut(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32OnOff, uint32_t u32TimeOutCnt) +{ + switch (u32Ch) + { + case 0ul: + pdma->TOC0_1 = (pdma->TOC0_1 & ~PDMA_TOC0_1_TOC0_Msk) | u32TimeOutCnt; + break; + + case 1ul: + pdma->TOC0_1 = (pdma->TOC0_1 & ~PDMA_TOC0_1_TOC1_Msk) | (u32TimeOutCnt << PDMA_TOC0_1_TOC1_Pos); + break; + + default: + break; + } + + if (u32OnOff) + pdma->TOUTEN |= (1ul << u32Ch); + else + pdma->TOUTEN &= ~(1ul << u32Ch); +} + +/** + * @brief Trigger PDMA + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * + * @return None + * + * @details This function trigger the selected channel. + */ +void PDMA_Trigger(PDMA_T *pdma, uint32_t u32Ch) +{ + if (u8ChSelect[u32Ch] == PDMA_MEM) + { + pdma->SWREQ = (1ul << u32Ch); + } + else {} +} + +/** + * @brief Enable Interrupt + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32Mask The Interrupt Type. Valid values are + * - \ref PDMA_INT_TRANS_DONE + * - \ref PDMA_INT_TEMPTY + * - \ref PDMA_INT_TIMEOUT + * + * @return None + * + * @details This function enable the selected channel interrupt. + */ +void PDMA_EnableInt(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Mask) +{ + switch (u32Mask) + { + case PDMA_INT_TRANS_DONE: + pdma->INTEN |= (1ul << u32Ch); + break; + + case PDMA_INT_TEMPTY: + pdma->DSCT[u32Ch].CTL &= ~PDMA_DSCT_CTL_TBINTDIS_Msk; + break; + + case PDMA_INT_TIMEOUT: + pdma->TOUTIEN |= (1ul << u32Ch); + break; + + default: + break; + } +} + +/** + * @brief Disable Interrupt + * + * @param[in] pdma The pointer of the specified PDMA module + * @param[in] u32Ch The selected channel + * @param[in] u32Mask The Interrupt Type. Valid values are + * - \ref PDMA_INT_TRANS_DONE + * - \ref PDMA_INT_TEMPTY + * - \ref PDMA_INT_TIMEOUT + * + * @return None + * + * @details This function disable the selected channel interrupt. + */ +void PDMA_DisableInt(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Mask) +{ + switch (u32Mask) + { + case PDMA_INT_TRANS_DONE: + pdma->INTEN &= ~(1ul << u32Ch); + break; + + case PDMA_INT_TEMPTY: + pdma->DSCT[u32Ch].CTL |= PDMA_DSCT_CTL_TBINTDIS_Msk; + break; + + case PDMA_INT_TIMEOUT: + pdma->TOUTIEN &= ~(1ul << u32Ch); + break; + + default: + break; + } +} + +/*@}*/ /* end of group PDMA_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group PDMA_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_pwm.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_pwm.c new file mode 100644 index 0000000000..eb5acf9551 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_pwm.c @@ -0,0 +1,1063 @@ +/**************************************************************************//** + * @file pwm.c + * @version V1.00 + * $Revision: 4 $ + * $Date: 18/04/25 11:43a $ + * @brief M031 series PWM driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "NuMicro.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup PWM_Driver PWM Driver + @{ +*/ + + +/** @addtogroup PWM_EXPORTED_FUNCTIONS PWM Exported Functions + @{ +*/ + +/** + * @brief Configure PWM capture and get the nearest unit time. + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32UnitTimeNsec The unit time of counter + * @param[in] u32CaptureEdge The condition to latch the counter. This parameter is not used + * @return The nearest unit time in nano second. + * @details This function is used to Configure PWM capture and get the nearest unit time. + */ +uint32_t PWM_ConfigCaptureChannel(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32UnitTimeNsec, uint32_t u32CaptureEdge) +{ + uint32_t u32Src; + uint32_t u32PWMClockSrc; + uint32_t u32NearestUnitTimeNsec; + uint16_t u16Prescale = 1UL, u16CNR = 0xFFFFUL; + uint8_t u8BreakLoop = 0UL; + + if (pwm == PWM0) + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_PWM0SEL_Msk; + else//(pwm == PWM1) + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_PWM1SEL_Msk; + + if (u32Src == 0UL) + { + //clock source is from PLL clock + u32PWMClockSrc = CLK_GetPLLClockFreq(); + } + else + { + //clock source is from PCLK + SystemCoreClockUpdate(); + + if (pwm == PWM0) + { + u32PWMClockSrc = CLK_GetPCLK0Freq(); + } + else /* (pwm == PWM1) */ + { + u32PWMClockSrc = CLK_GetPCLK1Freq(); + } + } + + u32PWMClockSrc /= 1000UL; + + for (u16Prescale = 1UL; u16Prescale <= 0x1000UL; u16Prescale++) + { + u32NearestUnitTimeNsec = (1000000UL * u16Prescale) / u32PWMClockSrc; + + if (u32NearestUnitTimeNsec < u32UnitTimeNsec) + { + if (u16Prescale == 0x1000UL) + { + /* limit to the maximum unit time(nano second) */ + u8BreakLoop = 1UL; + } + + if (!((1000000UL * (u16Prescale + 1UL) > (u32NearestUnitTimeNsec * u32PWMClockSrc)))) + { + u8BreakLoop = 1UL; + } + } + else + { + u8BreakLoop = 1UL; + } + + if (u8BreakLoop) + { + break; + } + } + + // convert to real register value + u16Prescale = u16Prescale - 1UL; + // every two channels share a prescaler + PWM_SET_PRESCALER(pwm, u32ChannelNum, (uint32_t)u16Prescale); + + // set PWM to down count type(edge aligned) + (pwm)->CTL1 = ((pwm)->CTL1 & ~(PWM_CTL1_CNTTYPE0_Msk << ((u32ChannelNum >> 1UL) << 2UL))) | (1UL << ((u32ChannelNum >> 1UL) << 2UL)); + + PWM_SET_CNR(pwm, u32ChannelNum, u16CNR); + + return (u32NearestUnitTimeNsec); +} + +/** + * @brief This function Configure PWM generator and get the nearest frequency in edge aligned auto-reload mode + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32Frequency Target generator frequency + * @param[in] u32DutyCycle Target generator duty cycle percentage. Valid range are between 0 ~ 100. 10 means 10%, 20 means 20%... + * @return Nearest frequency clock in nano second + * @note Since every two channels, (0 & 1), (2 & 3), shares a prescaler. Call this API to configure PWM frequency may affect + * existing frequency of other channel. + */ +uint32_t PWM_ConfigOutputChannel(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Frequency, uint32_t u32DutyCycle) +{ + uint32_t u32Src; + uint32_t u32PWMClockSrc; + uint32_t i; + uint16_t u16Prescale = 1UL, u16CNR = 0xFFFFUL; + + if (pwm == PWM0) + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_PWM0SEL_Msk; + else//(pwm == PWM1) + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_PWM1SEL_Msk; + + if (u32Src == 0UL) + { + //clock source is from PLL clock + u32PWMClockSrc = CLK_GetPLLClockFreq(); + } + else + { + //clock source is from PCLK + SystemCoreClockUpdate(); + + if (pwm == PWM0) + { + u32PWMClockSrc = CLK_GetPCLK0Freq(); + } + else /* (pwm == PWM1) */ + { + u32PWMClockSrc = CLK_GetPCLK1Freq(); + } + } + + for (u16Prescale = 1UL; u16Prescale < 0xFFFUL; u16Prescale++) //prescale could be 0~0xFFF + { + i = (u32PWMClockSrc / u32Frequency) / u16Prescale; + + // If target value is larger than CNR, need to use a larger prescaler + if (i <= (0x10000UL)) + { + u16CNR = (uint16_t)i; + break; + } + } + + // Store return value here 'cos we're gonna change u16Prescale & u16CNR to the real value to fill into register + i = u32PWMClockSrc / ((uint32_t)u16Prescale * (uint32_t)u16CNR); + + // convert to real register value + u16Prescale = u16Prescale - 1UL; + // every two channels share a prescaler + PWM_SET_PRESCALER(pwm, u32ChannelNum, (uint32_t)u16Prescale); + // set PWM to down count type(edge aligned) + (pwm)->CTL1 = ((pwm)->CTL1 & ~(PWM_CTL1_CNTTYPE0_Msk << ((u32ChannelNum >> 1UL) << 2UL))) | (1UL << ((u32ChannelNum >> 1UL) << 2UL)); + + u16CNR -= 1UL; + PWM_SET_CNR(pwm, u32ChannelNum, u16CNR); + + if (u32DutyCycle) + { + if (u32DutyCycle >= 100UL) + PWM_SET_CMR(pwm, u32ChannelNum, u16CNR); + else + PWM_SET_CMR(pwm, u32ChannelNum, u32DutyCycle * (u16CNR + 1UL) / 100UL); + + (pwm)->WGCTL0 &= ~((PWM_WGCTL0_PRDPCTL0_Msk | PWM_WGCTL0_ZPCTL0_Msk) << (u32ChannelNum << 1UL)); + (pwm)->WGCTL0 |= (PWM_OUTPUT_LOW << ((u32ChannelNum << 1UL) + PWM_WGCTL0_PRDPCTL0_Pos)); + (pwm)->WGCTL1 &= ~((PWM_WGCTL1_CMPDCTL0_Msk | PWM_WGCTL1_CMPUCTL0_Msk) << (u32ChannelNum << 1UL)); + (pwm)->WGCTL1 |= (PWM_OUTPUT_HIGH << ((u32ChannelNum << 1UL) + PWM_WGCTL1_CMPDCTL0_Pos)); + } + else + { + PWM_SET_CMR(pwm, u32ChannelNum, 0UL); + (pwm)->WGCTL0 &= ~((PWM_WGCTL0_PRDPCTL0_Msk | PWM_WGCTL0_ZPCTL0_Msk) << (u32ChannelNum << 1UL)); + (pwm)->WGCTL0 |= (PWM_OUTPUT_LOW << ((u32ChannelNum << 1UL) + PWM_WGCTL0_ZPCTL0_Pos)); + (pwm)->WGCTL1 &= ~((PWM_WGCTL1_CMPDCTL0_Msk | PWM_WGCTL1_CMPUCTL0_Msk) << (u32ChannelNum << 1UL)); + (pwm)->WGCTL1 |= (PWM_OUTPUT_HIGH << ((u32ChannelNum << 1UL) + PWM_WGCTL1_CMPDCTL0_Pos)); + } + + return (i); +} + +/** + * @brief Start PWM module + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. + * Bit 0 is channel 0, bit 1 is channel 1... + * @return None + * @details This function is used to start PWM module. + * @note Every two channels share the same setting. + */ +void PWM_Start(PWM_T *pwm, uint32_t u32ChannelMask) +{ + uint32_t i; + + for (i = 0UL; i < PWM_CHANNEL_NUM; i ++) + { + if (u32ChannelMask & (1UL << i)) + { + (pwm)->CNTEN |= (1UL << ((i >> 1UL) << 1UL)); + } + } +} + +/** + * @brief Stop PWM module + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. + * Bit 0 is channel 0, bit 1 is channel 1... + * @return None + * @details This function is used to stop PWM module. + * @note Every two channels share the same setting. + */ +void PWM_Stop(PWM_T *pwm, uint32_t u32ChannelMask) +{ + uint32_t i; + + for (i = 0UL; i < PWM_CHANNEL_NUM; i ++) + { + if (u32ChannelMask & (1UL << i)) + { + (pwm)->PERIOD[((i >> 1UL) << 1UL)] = 0UL; + } + } +} + +/** + * @brief Stop PWM generation immediately by clear channel enable bit + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. + * Bit 0 is channel 0, bit 1 is channel 1... + * @return None + * @details This function is used to stop PWM generation immediately by clear channel enable bit. + * @note Every two channels share the same setting. + */ +void PWM_ForceStop(PWM_T *pwm, uint32_t u32ChannelMask) +{ + uint32_t i; + + for (i = 0UL; i < PWM_CHANNEL_NUM; i ++) + { + if (u32ChannelMask & (1UL << i)) + { + (pwm)->CNTEN &= ~(1UL << ((i >> 1UL) << 1UL)); + } + } +} + +/** + * @brief Enable selected channel to trigger ADC + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32Condition The condition to trigger ADC. Combination of following conditions: + * - \ref PWM_TRIGGER_ADC_EVEN_ZERO_POINT + * - \ref PWM_TRIGGER_ADC_EVEN_PERIOD_POINT + * - \ref PWM_TRIGGER_ADC_EVEN_ZERO_OR_PERIOD_POINT + * - \ref PWM_TRIGGER_ADC_EVEN_COMPARE_UP_COUNT_POINT + * - \ref PWM_TRIGGER_ADC_EVEN_COMPARE_DOWN_COUNT_POINT + * - \ref PWM_TRIGGER_ADC_ODD_COMPARE_UP_COUNT_POINT + * - \ref PWM_TRIGGER_ADC_ODD_COMPARE_DOWN_COUNT_POINT + * @return None + * @details This function is used to enable selected channel to trigger ADC. + */ +void PWM_EnableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition) +{ + if (u32ChannelNum < 4UL) + { + (pwm)->ADCTS0 &= ~((PWM_ADCTS0_TRGSEL0_Msk) << (u32ChannelNum << 3UL)); + (pwm)->ADCTS0 |= ((PWM_ADCTS0_TRGEN0_Msk | u32Condition) << (u32ChannelNum << 3UL)); + } + else + { + (pwm)->ADCTS1 &= ~((PWM_ADCTS1_TRGSEL4_Msk) << ((u32ChannelNum - 4UL) << 3UL)); + (pwm)->ADCTS1 |= ((PWM_ADCTS1_TRGEN4_Msk | u32Condition) << ((u32ChannelNum - 4UL) << 3UL)); + } +} + +/** + * @brief Disable selected channel to trigger ADC + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @return None + * @details This function is used to disable selected channel to trigger ADC. + */ +void PWM_DisableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum) +{ + if (u32ChannelNum < 4UL) + { + (pwm)->ADCTS0 &= ~(PWM_ADCTS0_TRGEN0_Msk << (u32ChannelNum << 3UL)); + } + else + { + (pwm)->ADCTS1 &= ~(PWM_ADCTS1_TRGEN4_Msk << ((u32ChannelNum - 4UL) << 3UL)); + } +} + +/** + * @brief Clear selected channel trigger ADC flag + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32Condition This parameter is not used + * @return None + * @details This function is used to clear selected channel trigger ADC flag. + */ +void PWM_ClearADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition) +{ + (pwm)->STATUS = (PWM_STATUS_ADCTRG0_Msk << u32ChannelNum); +} + +/** + * @brief Get selected channel trigger ADC flag + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @retval 0 The specified channel trigger ADC to start of conversion flag is not set + * @retval 1 The specified channel trigger ADC to start of conversion flag is set + * @details This function is used to get PWM trigger ADC to start of conversion flag for specified channel. + */ +uint32_t PWM_GetADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum) +{ + return (((pwm)->STATUS & (PWM_STATUS_ADCTRG0_Msk << u32ChannelNum)) ? 1UL : 0UL); +} + +/** + * @brief This function enable fault brake of selected channel(s) + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. + * @param[in] u32LevelMask Output high or low while fault brake occurs, each bit represent the level of a channel + * while fault brake occurs. Bit 0 represents channel 0, bit 1 represents channel 1... + * @param[in] u32BrakeSource Fault brake source, could be one of following source + * - \ref PWM_FB_EDGE_ACMP0 + * - \ref PWM_FB_EDGE_ACMP1 + * - \ref PWM_FB_EDGE_BKP0 + * - \ref PWM_FB_EDGE_BKP1 + * - \ref PWM_FB_EDGE_SYS_CSS + * - \ref PWM_FB_EDGE_SYS_BOD + * - \ref PWM_FB_EDGE_SYS_COR + * - \ref PWM_FB_LEVEL_ACMP0 + * - \ref PWM_FB_LEVEL_ACMP1 + * - \ref PWM_FB_LEVEL_BKP0 + * - \ref PWM_FB_LEVEL_BKP1 + * - \ref PWM_FB_LEVEL_SYS_CSS + * - \ref PWM_FB_LEVEL_SYS_BOD + * - \ref PWM_FB_LEVEL_SYS_COR + * @return None + * @details This function is used to enable fault brake of selected channel(s). + * The write-protection function should be disabled before using this function. + */ +void PWM_EnableFaultBrake(PWM_T *pwm, uint32_t u32ChannelMask, uint32_t u32LevelMask, uint32_t u32BrakeSource) +{ + uint32_t i; + + for (i = 0UL; i < PWM_CHANNEL_NUM; i ++) + { + if (u32ChannelMask & (1UL << i)) + { + if ((u32BrakeSource == PWM_FB_EDGE_SYS_CSS) || (u32BrakeSource == PWM_FB_EDGE_SYS_BOD) || \ + (u32BrakeSource == PWM_FB_EDGE_SYS_COR) || \ + (u32BrakeSource == PWM_FB_LEVEL_SYS_CSS) || (u32BrakeSource == PWM_FB_LEVEL_SYS_BOD) || \ + (u32BrakeSource == PWM_FB_LEVEL_SYS_COR)) + { + (pwm)->BRKCTL[i >> 1UL] |= (u32BrakeSource & (PWM_BRKCTL_SYSEBEN_Msk | PWM_BRKCTL_SYSLBEN_Msk)); + (pwm)->FAILBRK |= (u32BrakeSource & 0xBUL); + } + else + { + (pwm)->BRKCTL[i >> 1UL] |= u32BrakeSource; + } + } + + if (u32LevelMask & (1UL << i)) + { + if ((i & 0x1UL) == 0UL) + { + //set brake action as high level for even channel + (pwm)->BRKCTL[i >> 1UL] &= ~PWM_BRKCTL0_1_BRKAEVEN_Msk; + (pwm)->BRKCTL[i >> 1UL] |= ((3UL) << PWM_BRKCTL0_1_BRKAEVEN_Pos); + } + else + { + //set brake action as high level for odd channel + (pwm)->BRKCTL[i >> 1UL] &= ~PWM_BRKCTL0_1_BRKAODD_Msk; + (pwm)->BRKCTL[i >> 1UL] |= ((3UL) << PWM_BRKCTL0_1_BRKAODD_Pos); + } + } + else + { + if ((i & 0x1UL) == 0UL) + { + //set brake action as low level for even channel + (pwm)->BRKCTL[i >> 1UL] &= ~PWM_BRKCTL0_1_BRKAEVEN_Msk; + (pwm)->BRKCTL[i >> 1UL] |= ((2UL) << PWM_BRKCTL0_1_BRKAEVEN_Pos); + } + else + { + //set brake action as low level for odd channel + (pwm)->BRKCTL[i >> 1UL] &= ~PWM_BRKCTL0_1_BRKAODD_Msk; + (pwm)->BRKCTL[i >> 1UL] |= ((2UL) << PWM_BRKCTL0_1_BRKAODD_Pos); + } + } + } + +} + +/** + * @brief Enable capture of selected channel(s) + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. + * Bit 0 is channel 0, bit 1 is channel 1... + * @return None + * @details This function is used to enable capture of selected channel(s). + */ +void PWM_EnableCapture(PWM_T *pwm, uint32_t u32ChannelMask) +{ + (pwm)->CAPINEN |= u32ChannelMask; + (pwm)->CAPCTL |= u32ChannelMask; +} + +/** + * @brief Disable capture of selected channel(s) + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. + * Bit 0 is channel 0, bit 1 is channel 1... + * @return None + * @details This function is used to disable capture of selected channel(s). + */ +void PWM_DisableCapture(PWM_T *pwm, uint32_t u32ChannelMask) +{ + (pwm)->CAPINEN &= ~u32ChannelMask; + (pwm)->CAPCTL &= ~u32ChannelMask; +} + +/** + * @brief Enables PWM output generation of selected channel(s) + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. + * Set bit 0 to 1 enables channel 0 output, set bit 1 to 1 enables channel 1 output... + * @return None + * @details This function is used to enable PWM output generation of selected channel(s). + */ +void PWM_EnableOutput(PWM_T *pwm, uint32_t u32ChannelMask) +{ + (pwm)->POEN |= u32ChannelMask; +} + +/** + * @brief Disables PWM output generation of selected channel(s) + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel + * Set bit 0 to 1 disables channel 0 output, set bit 1 to 1 disables channel 1 output... + * @return None + * @details This function is used to disable PWM output generation of selected channel(s). + */ +void PWM_DisableOutput(PWM_T *pwm, uint32_t u32ChannelMask) +{ + (pwm)->POEN &= ~u32ChannelMask; +} + +/** + * @brief Enable Dead zone of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32Duration Dead zone length in PWM clock count, valid values are between 0~0xFFF, but 0 means there is no Dead zone. + * @return None + * @details This function is used to enable Dead zone of selected channel. + * The write-protection function should be disabled before using this function. + * @note Every two channels share the same setting. + */ +void PWM_EnableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Duration) +{ + // every two channels share the same setting + (pwm)->DTCTL[(u32ChannelNum) >> 1UL] &= ~PWM_DTCTL0_1_DTCNT_Msk; + (pwm)->DTCTL[(u32ChannelNum) >> 1UL] |= PWM_DTCTL0_1_DTEN_Msk | u32Duration; +} + +/** + * @brief Disable Dead zone of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @return None + * @details This function is used to disable Dead zone of selected channel. + * The write-protection function should be disabled before using this function. + */ +void PWM_DisableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum) +{ + // every two channels shares the same setting + (pwm)->DTCTL[(u32ChannelNum) >> 1UL] &= ~PWM_DTCTL0_1_DTEN_Msk; +} + +/** + * @brief Enable capture interrupt of selected channel. + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32Edge Rising or falling edge to latch counter. + * - \ref PWM_CAPTURE_INT_RISING_LATCH + * - \ref PWM_CAPTURE_INT_FALLING_LATCH + * @return None + * @details This function is used to enable capture interrupt of selected channel. + */ +void PWM_EnableCaptureInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge) +{ + (pwm)->CAPIEN |= (u32Edge << u32ChannelNum); +} + +/** + * @brief Disable capture interrupt of selected channel. + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32Edge Rising or falling edge to latch counter. + * - \ref PWM_CAPTURE_INT_RISING_LATCH + * - \ref PWM_CAPTURE_INT_FALLING_LATCH + * @return None + * @details This function is used to disable capture interrupt of selected channel. + */ +void PWM_DisableCaptureInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge) +{ + (pwm)->CAPIEN &= ~(u32Edge << u32ChannelNum); +} + +/** + * @brief Clear capture interrupt of selected channel. + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32Edge Rising or falling edge to latch counter. + * - \ref PWM_CAPTURE_INT_RISING_LATCH + * - \ref PWM_CAPTURE_INT_FALLING_LATCH + * @return None + * @details This function is used to clear capture interrupt of selected channel. + */ +void PWM_ClearCaptureIntFlag(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge) +{ + (pwm)->CAPIF = (u32Edge << u32ChannelNum); +} + +/** + * @brief Get capture interrupt of selected channel. + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @retval 0 No capture interrupt + * @retval 1 Rising edge latch interrupt + * @retval 2 Falling edge latch interrupt + * @retval 3 Rising and falling latch interrupt + * @details This function is used to get capture interrupt of selected channel. + */ +uint32_t PWM_GetCaptureIntFlag(PWM_T *pwm, uint32_t u32ChannelNum) +{ + uint32_t u32CapFFlag, u32CapRFlag ; + u32CapFFlag = (((pwm)->CAPIF & (PWM_CAPIF_CFLIF0_Msk << u32ChannelNum)) ? 1UL : 0UL) ; + u32CapRFlag = (((pwm)->CAPIF & (PWM_CAPIF_CRLIF0_Msk << u32ChannelNum)) ? 1UL : 0UL) ; + return ((u32CapFFlag << 1UL) | u32CapRFlag); +} +/** + * @brief Enable duty interrupt of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32IntDutyType Duty interrupt type, could be either + * - \ref PWM_DUTY_INT_DOWN_COUNT_MATCH_CMP + * - \ref PWM_DUTY_INT_UP_COUNT_MATCH_CMP + * @return None + * @details This function is used to enable duty interrupt of selected channel. + */ +void PWM_EnableDutyInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType) +{ + (pwm)->INTEN0 |= (u32IntDutyType << u32ChannelNum); +} + +/** + * @brief Disable duty interrupt of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @return None + * @details This function is used to disable duty interrupt of selected channel. + */ +void PWM_DisableDutyInt(PWM_T *pwm, uint32_t u32ChannelNum) +{ + (pwm)->INTEN0 &= ~((PWM_DUTY_INT_DOWN_COUNT_MATCH_CMP | PWM_DUTY_INT_UP_COUNT_MATCH_CMP) << u32ChannelNum); +} + +/** + * @brief Clear duty interrupt flag of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @return None + * @details This function is used to clear duty interrupt flag of selected channel. + */ +void PWM_ClearDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum) +{ + (pwm)->INTSTS0 = (PWM_INTSTS0_CMPUIF0_Msk | PWM_INTSTS0_CMPDIF0_Msk) << u32ChannelNum; +} + +/** + * @brief Get duty interrupt flag of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @return Duty interrupt flag of specified channel + * @retval 0 Duty interrupt did not occur + * @retval 1 Duty interrupt occurred + * @details This function is used to get duty interrupt flag of selected channel. + */ +uint32_t PWM_GetDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum) +{ + return ((((pwm)->INTSTS0 & ((PWM_INTSTS0_CMPDIF0_Msk | PWM_INTSTS0_CMPUIF0_Msk) << u32ChannelNum))) ? 1 : 0); +} + +/** + * @brief Enable load mode of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32LoadMode PWM counter loading mode. + * - \ref PWM_LOAD_MODE_IMMEDIATE + * - \ref PWM_LOAD_MODE_CENTER + * @return None + * @details This function is used to enable load mode of selected channel. + */ +void PWM_EnableLoadMode(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32LoadMode) +{ + (pwm)->CTL0 |= (u32LoadMode << u32ChannelNum); +} + +/** + * @brief Disable load mode of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32LoadMode PWM counter loading mode. + * - \ref PWM_LOAD_MODE_IMMEDIATE + * - \ref PWM_LOAD_MODE_CENTER + * @return None + * @details This function is used to disable load mode of selected channel. + */ +void PWM_DisableLoadMode(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32LoadMode) +{ + (pwm)->CTL0 &= ~(u32LoadMode << u32ChannelNum); +} + +/** + * @brief This function enable fault brake interrupt + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32BrakeSource Fault brake source. + * - \ref PWM_FB_EDGE + * - \ref PWM_FB_LEVEL + * @return None + * @details This function is used to enable fault brake interrupt. + * The write-protection function should be disabled before using this function. + * @note Every two channels share the same setting. + */ +void PWM_EnableFaultBrakeInt(PWM_T *pwm, uint32_t u32BrakeSource) +{ + (pwm)->INTEN1 |= (0x7UL << u32BrakeSource); +} + +/** + * @brief This function disable fault brake interrupt + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32BrakeSource Fault brake source. + * - \ref PWM_FB_EDGE + * - \ref PWM_FB_LEVEL + * @return None + * @details This function is used to disable fault brake interrupt. + * The write-protection function should be disabled before using this function. + * @note Every two channels share the same setting. + */ +void PWM_DisableFaultBrakeInt(PWM_T *pwm, uint32_t u32BrakeSource) +{ + (pwm)->INTEN1 &= ~(0x7UL << u32BrakeSource); +} + +/** + * @brief This function clear fault brake interrupt of selected source + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32BrakeSource Fault brake source. + * - \ref PWM_FB_EDGE + * - \ref PWM_FB_LEVEL + * @return None + * @details This function is used to clear fault brake interrupt of selected source. + * The write-protection function should be disabled before using this function. + */ +void PWM_ClearFaultBrakeIntFlag(PWM_T *pwm, uint32_t u32BrakeSource) +{ + (pwm)->INTSTS1 = (0x3fUL << u32BrakeSource); +} + +/** + * @brief This function get fault brake interrupt flag of selected source + * @param[in] pwm The pointer of the specified PWM module + * @param[in] u32BrakeSource Fault brake source, could be either + * - \ref PWM_FB_EDGE + * - \ref PWM_FB_LEVEL + * @return Fault brake interrupt flag of specified source + * @retval 0 Fault brake interrupt did not occurred + * @retval 1 Fault brake interrupt occurred + * @details This function is used to get fault brake interrupt flag of selected source. + */ +uint32_t PWM_GetFaultBrakeIntFlag(PWM_T *pwm, uint32_t u32BrakeSource) +{ + return (((pwm)->INTSTS1 & (0x3fUL << u32BrakeSource)) ? 1UL : 0UL); +} + +/** + * @brief Enable period interrupt of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. + * @param[in] u32IntPeriodType Period interrupt type. This parameter is not used. + * @return None + * @details This function is used to enable period interrupt of selected channel. + */ +void PWM_EnablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType) +{ + (pwm)->INTEN0 |= (PWM_INTEN0_PIEN0_Msk << ((u32ChannelNum >> 1UL) << 1UL)); +} + +/** + * @brief Disable period interrupt of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. + * @return None + * @details This function is used to disable period interrupt of selected channel. + */ +void PWM_DisablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum) +{ + (pwm)->INTEN0 &= ~(PWM_INTEN0_PIEN0_Msk << ((u32ChannelNum >> 1UL) << 1UL)); +} + +/** + * @brief Clear period interrupt of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. + * @return None + * @details This function is used to clear period interrupt of selected channel. + */ +void PWM_ClearPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum) +{ + (pwm)->INTSTS0 = (PWM_INTSTS0_PIF0_Msk << ((u32ChannelNum >> 1UL) << 1UL)); +} + +/** + * @brief Get period interrupt of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. + * @return Period interrupt flag of specified channel + * @retval 0 Period interrupt did not occur + * @retval 1 Period interrupt occurred + * @details This function is used to get period interrupt of selected channel. + */ +uint32_t PWM_GetPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum) +{ + return (((pwm)->INTSTS0 & (PWM_INTSTS0_PIF0_Msk << ((u32ChannelNum >> 1UL) << 1UL))) ? 1UL : 0UL); +} + +/** + * @brief Enable zero interrupt of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. + * @return None + * @details This function is used to enable zero interrupt of selected channel. + */ +void PWM_EnableZeroInt(PWM_T *pwm, uint32_t u32ChannelNum) +{ + (pwm)->INTEN0 |= (PWM_INTEN0_ZIEN0_Msk << ((u32ChannelNum >> 1UL) << 1UL)); +} + +/** + * @brief Disable zero interrupt of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. + * @return None + * @details This function is used to disable zero interrupt of selected channel. + */ +void PWM_DisableZeroInt(PWM_T *pwm, uint32_t u32ChannelNum) +{ + (pwm)->INTEN0 &= ~(PWM_INTEN0_ZIEN0_Msk << ((u32ChannelNum >> 1UL) << 1UL)); +} + +/** + * @brief Clear zero interrupt of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. + * @return None + * @details This function is used to clear zero interrupt of selected channel. + */ +void PWM_ClearZeroIntFlag(PWM_T *pwm, uint32_t u32ChannelNum) +{ + (pwm)->INTSTS0 = (PWM_INTSTS0_ZIF0_Msk << ((u32ChannelNum >> 1UL) << 1UL)); +} + +/** + * @brief Get zero interrupt of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. + * @return zero interrupt flag of specified channel + * @retval 0 zero interrupt did not occur + * @retval 1 zero interrupt occurred + * @details This function is used to get zero interrupt of selected channel. + */ +uint32_t PWM_GetZeroIntFlag(PWM_T *pwm, uint32_t u32ChannelNum) +{ + return (((pwm)->INTSTS0 & (PWM_INTSTS0_ZIF0_Msk << ((u32ChannelNum >> 1UL) << 1UL))) ? 1UL : 0UL); +} + +/** + * @brief Set PWM clock source + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 + * @param[in] u32ClkSrcSel PWM external clock source. + * - \ref PWM_CLKSRC_PWM_CLK + * - \ref PWM_CLKSRC_TIMER0 + * - \ref PWM_CLKSRC_TIMER1 + * - \ref PWM_CLKSRC_TIMER2 + * - \ref PWM_CLKSRC_TIMER3 + * @return None + * @details This function is used to set PWM clock source. + * @note Every two channels share the same setting. + */ +void PWM_SetClockSource(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32ClkSrcSel) +{ + (pwm)->CLKSRC = ((pwm)->CLKSRC & ~(PWM_CLKSRC_ECLKSRC0_Msk << ((u32ChannelNum >> 1UL) * PWM_CLKSRC_ECLKSRC2_Pos))) | \ + (u32ClkSrcSel << ((u32ChannelNum >> 1UL) * PWM_CLKSRC_ECLKSRC2_Pos)); +} + +/** + * @brief Enable PWM brake noise filter function + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32BrakePinNum Brake pin selection. Valid values are 0 or 1. + * @param[in] u32ClkCnt SYNC Edge Detector Filter Count. This controls the counter number of edge detector + * @param[in] u32ClkDivSel SYNC Edge Detector Filter Clock Selection. + * - \ref PWM_NF_CLK_DIV_1 + * - \ref PWM_NF_CLK_DIV_2 + * - \ref PWM_NF_CLK_DIV_4 + * - \ref PWM_NF_CLK_DIV_8 + * - \ref PWM_NF_CLK_DIV_16 + * - \ref PWM_NF_CLK_DIV_32 + * - \ref PWM_NF_CLK_DIV_64 + * - \ref PWM_NF_CLK_DIV_128 + * @return None + * @details This function is used to enable PWM brake noise filter function. + */ +void PWM_EnableBrakeNoiseFilter(PWM_T *pwm, uint32_t u32BrakePinNum, uint32_t u32ClkCnt, uint32_t u32ClkDivSel) +{ + (pwm)->BNF = ((pwm)->BNF & ~((PWM_BNF_BRK0FCNT_Msk | PWM_BNF_BRK0NFSEL_Msk) << (u32BrakePinNum * PWM_BNF_BRK1NFEN_Pos))) | \ + (((u32ClkCnt << PWM_BNF_BRK0FCNT_Pos) | (u32ClkDivSel << PWM_BNF_BRK0NFSEL_Pos) | PWM_BNF_BRK0NFEN_Msk) << (u32BrakePinNum * PWM_BNF_BRK1NFEN_Pos)); +} + +/** + * @brief Disable PWM brake noise filter function + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32BrakePinNum Brake pin selection. Valid values are 0 or 1. + * @return None + * @details This function is used to disable PWM brake noise filter function. + */ +void PWM_DisableBrakeNoiseFilter(PWM_T *pwm, uint32_t u32BrakePinNum) +{ + (pwm)->BNF &= ~(PWM_BNF_BRK0NFEN_Msk << (u32BrakePinNum * PWM_BNF_BRK1NFEN_Pos)); +} + +/** + * @brief Enable PWM brake pin inverse function + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32BrakePinNum Brake pin selection. Valid values are 0 or 1. + * @return None + * @details This function is used to enable PWM brake pin inverse function. + */ +void PWM_EnableBrakePinInverse(PWM_T *pwm, uint32_t u32BrakePinNum) +{ + (pwm)->BNF |= (PWM_BNF_BRK0PINV_Msk << (u32BrakePinNum * PWM_BNF_BRK1NFEN_Pos)); +} + +/** + * @brief Disable PWM brake pin inverse function + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32BrakePinNum Brake pin selection. Valid values are 0 or 1. + * @return None + * @details This function is used to disable PWM brake pin inverse function. + */ +void PWM_DisableBrakePinInverse(PWM_T *pwm, uint32_t u32BrakePinNum) +{ + (pwm)->BNF &= ~(PWM_BNF_BRK0PINV_Msk << (u32BrakePinNum * PWM_BNF_BRK1NFEN_Pos)); +} + +/** + * @brief Set PWM brake pin source + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32BrakePinNum Brake pin selection. Valid values are 0 or 1. + * @param[in] u32SelAnotherModule Select to another module. Valid values are TRUE or FALSE. + * @return None + * @details This function is used to set PWM brake pin source. + */ +void PWM_SetBrakePinSource(PWM_T *pwm, uint32_t u32BrakePinNum, uint32_t u32SelAnotherModule) +{ + (pwm)->BNF = ((pwm)->BNF & ~(PWM_BNF_BK0SRC_Msk << (u32BrakePinNum << 3UL))) | (u32SelAnotherModule << (PWM_BNF_BK0SRC_Pos + (u32BrakePinNum << 3UL))); +} + +/** + * @brief Get the time-base counter reached its maximum value flag of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. + * @return Count to max interrupt flag of specified channel + * @retval 0 Count to max interrupt did not occur + * @retval 1 Count to max interrupt occurred + * @details This function is used to get the time-base counter reached its maximum value flag of selected channel. + */ +uint32_t PWM_GetWrapAroundFlag(PWM_T *pwm, uint32_t u32ChannelNum) +{ + return (((pwm)->STATUS & (PWM_STATUS_CNTMAX0_Msk << ((u32ChannelNum >> 1UL) << 1UL))) ? 1UL : 0UL); +} + +/** + * @brief Clear the time-base counter reached its maximum value flag of selected channel + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. + * @return None + * @details This function is used to clear the time-base counter reached its maximum value flag of selected channel. + */ +void PWM_ClearWrapAroundFlag(PWM_T *pwm, uint32_t u32ChannelNum) +{ + (pwm)->STATUS = (PWM_STATUS_CNTMAX0_Msk << ((u32ChannelNum >> 1UL) << 1UL)); +} + +/** + * @brief Enables PDMA transfer of selected channel for PWM capture + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. + * @param[in] u32RisingFirst The capture order is rising, falling first. Every two channels share the same setting. Valid values are TRUE and FALSE. + * @param[in] u32Mode Captured data transferred by PDMA interrupt type. It could be either + * - \ref PWM_CAPTURE_PDMA_RISING_LATCH + * - \ref PWM_CAPTURE_PDMA_FALLING_LATCH + * - \ref PWM_CAPTURE_PDMA_RISING_FALLING_LATCH + * @return None + * @details This function is used to enable PDMA transfer of selected channel(s) for PWM capture. + * @note This function can only selects even or odd channel of pairs to do PDMA transfer. + */ +void PWM_EnablePDMA(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32RisingFirst, uint32_t u32Mode) +{ + uint32_t u32IsOddCh; + u32IsOddCh = u32ChannelNum % 2UL; + (pwm)->PDMACTL = ((pwm)->PDMACTL & ~((PWM_PDMACTL_CHSEL0_1_Msk | PWM_PDMACTL_CAPORD0_1_Msk | PWM_PDMACTL_CAPMOD0_1_Msk) << ((u32ChannelNum >> 1UL) << 3UL))) | \ + (((u32IsOddCh << PWM_PDMACTL_CHSEL0_1_Pos) | (u32RisingFirst << PWM_PDMACTL_CAPORD0_1_Pos) | \ + u32Mode | PWM_PDMACTL_CHEN0_1_Msk) << ((u32ChannelNum >> 1UL) << 3UL)); +} + +/** + * @brief Disables PDMA transfer of selected channel for PWM capture + * @param[in] pwm The pointer of the specified PWM module + * - PWM0 : PWM Group 0 + * - PWM1 : PWM Group 1 + * @param[in] u32ChannelNum PWM channel number. + * @return None + * @details This function is used to enable PDMA transfer of selected channel(s) for PWM capture. + */ +void PWM_DisablePDMA(PWM_T *pwm, uint32_t u32ChannelNum) +{ + (pwm)->PDMACTL &= ~(PWM_PDMACTL_CHEN0_1_Msk << ((u32ChannelNum >> 1UL) << 3UL)); +} + +/*@}*/ /* end of group PWM_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group PWM_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_qspi.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_qspi.c new file mode 100644 index 0000000000..209cc12092 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_qspi.c @@ -0,0 +1,813 @@ +/**************************************************************************//** + * @file qspi.c + * @version V1.00 + * @brief M031 series QSPI driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "M031Series.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup QSPI_Driver QSPI Driver + @{ +*/ + + +/** @addtogroup QSPI_EXPORTED_FUNCTIONS QSPI Exported Functions + @{ +*/ + +/** + * @brief This function make QSPI module be ready to transfer. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32MasterSlave Decides the QSPI module is operating in master mode or in slave mode. (QSPI_SLAVE, QSPI_MASTER) + * @param[in] u32QSPIMode Decides the transfer timing. (QSPI_MODE_0, QSPI_MODE_1, QSPI_MODE_2, QSPI_MODE_3) + * @param[in] u32DataWidth Decides the data width of a QSPI transaction. + * @param[in] u32BusClock The expected frequency of QSPI bus clock in Hz. + * @return Actual frequency of QSPI peripheral clock. + * @details By default, the QSPI transfer sequence is MSB first, the slave selection signal is active low and the automatic + * slave selection function is disabled. + * In Slave mode, the u32BusClock shall be NULL and the QSPI clock divider setting will be 0. + * The actual clock rate may be different from the target QSPI clock rate. + * For example, if the QSPI source clock rate is 12 MHz and the target QSPI bus clock rate is 7 MHz, the + * actual QSPI clock rate will be 6MHz. + * @note If u32BusClock = 0, DIVIDER setting will be set to the maximum value. + * @note If u32BusClock >= system clock frequency, QSPI peripheral clock source will be set to APB clock and DIVIDER will be set to 0. + * @note If u32BusClock >= QSPI peripheral clock source, DIVIDER will be set to 0. + * @note In slave mode, the QSPI peripheral clock rate will be equal to APB clock rate. + */ +uint32_t QSPI_Open(QSPI_T *qspi, + uint32_t u32MasterSlave, + uint32_t u32QSPIMode, + uint32_t u32DataWidth, + uint32_t u32BusClock) +{ + uint32_t u32ClkSrc = 0UL, u32Div, u32HCLKFreq, u32RetValue = 0UL; + + if (u32DataWidth == 32UL) + { + u32DataWidth = 0UL; + } + + /* Get system clock frequency */ + u32HCLKFreq = CLK_GetHCLKFreq(); + + if (u32MasterSlave == QSPI_MASTER) + { + /* Default setting: slave selection signal is active low; disable automatic slave selection function. */ + qspi->SSCTL = QSPI_SS_ACTIVE_LOW; + + /* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */ + qspi->CTL = u32MasterSlave | (u32DataWidth << QSPI_CTL_DWIDTH_Pos) | (u32QSPIMode) | QSPI_CTL_SPIEN_Msk; + + if (u32BusClock >= u32HCLKFreq) + { + /* Select PCLK as the clock source of QSPI */ + CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_QSPI0SEL_Msk)) | CLK_CLKSEL2_QSPI0SEL_PCLK0; + } + + /* Check clock source of QSPI */ + if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT) + { + u32ClkSrc = __HXT; /* Clock source is HXT */ + } + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL) + { + u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ + } + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0) + { + /* Clock source is PCLK0 */ + u32ClkSrc = CLK_GetPCLK0Freq(); + } + else + { + u32ClkSrc = __HIRC; /* Clock source is HIRC */ + } + + if (u32BusClock >= u32HCLKFreq) + { + /* Set DIVIDER = 0 */ + qspi->CLKDIV = 0UL; + /* Return master peripheral clock rate */ + u32RetValue = u32ClkSrc; + } + else if (u32BusClock >= u32ClkSrc) + { + /* Set DIVIDER = 0 */ + qspi->CLKDIV = 0UL; + /* Return master peripheral clock rate */ + u32RetValue = u32ClkSrc; + } + else if (u32BusClock == 0UL) + { + /* Set DIVIDER to the maximum value 0x1FF. f_qspi = f_qspi_clk_src / (DIVIDER + 1) */ + qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk; + /* Return master peripheral clock rate */ + u32RetValue = (u32ClkSrc / (0x1FFUL + 1UL)); + } + else + { + u32Div = (((u32ClkSrc * 10UL) / u32BusClock + 5UL) / 10UL) - 1UL; /* Round to the nearest integer */ + + if (u32Div > 0x1FFUL) + { + u32Div = 0x1FFUL; + qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk; + /* Return master peripheral clock rate */ + u32RetValue = (u32ClkSrc / (0x1FFUL + 1UL)); + } + else + { + qspi->CLKDIV = (qspi->CLKDIV & (~QSPI_CLKDIV_DIVIDER_Msk)) | (u32Div << QSPI_CLKDIV_DIVIDER_Pos); + /* Return master peripheral clock rate */ + u32RetValue = (u32ClkSrc / (u32Div + 1UL)); + } + } + } + else /* For slave mode, force the QSPI peripheral clock rate to equal APB clock rate. */ + { + /* Default setting: slave selection signal is low level active. */ + qspi->SSCTL = QSPI_SS_ACTIVE_LOW; + + /* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */ + qspi->CTL = u32MasterSlave | (u32DataWidth << QSPI_CTL_DWIDTH_Pos) | (u32QSPIMode) | QSPI_CTL_SPIEN_Msk; + + /* Set DIVIDER = 0 */ + qspi->CLKDIV = 0UL; + + /* Select PCLK as the clock source of QSPI */ + CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_QSPI0SEL_Msk)) | CLK_CLKSEL2_QSPI0SEL_PCLK0; + /* Return slave peripheral clock rate */ + u32RetValue = CLK_GetPCLK0Freq(); + } + + return u32RetValue; +} + +/** + * @brief Disable QSPI controller. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None + * @details This function will reset QSPI controller. + */ +void QSPI_Close(QSPI_T *qspi) +{ + /* Reset QSPI */ + SYS->IPRST1 |= SYS_IPRST1_QSPI0RST_Msk; + SYS->IPRST1 &= ~SYS_IPRST1_QSPI0RST_Msk; +} + +/** + * @brief Clear RX FIFO buffer. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None + * @details This function will clear QSPI RX FIFO buffer. The RXEMPTY (QSPI_STATUS[8]) will be set to 1. + */ +void QSPI_ClearRxFIFO(QSPI_T *qspi) +{ + qspi->FIFOCTL |= QSPI_FIFOCTL_RXFBCLR_Msk; +} + +/** + * @brief Clear TX FIFO buffer. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None + * @details This function will clear QSPI TX FIFO buffer. The TXEMPTY (QSPI_STATUS[16]) will be set to 1. + * @note The TX shift register will not be cleared. + */ +void QSPI_ClearTxFIFO(QSPI_T *qspi) +{ + qspi->FIFOCTL |= QSPI_FIFOCTL_TXFBCLR_Msk; +} + +/** + * @brief Disable the automatic slave selection function. + * @param[in] qspi The pointer of the specified QSPI module. + * @return None + * @details This function will disable the automatic slave selection function and set slave selection signal to inactive state. + */ +void QSPI_DisableAutoSS(QSPI_T *qspi) +{ + qspi->SSCTL &= ~(QSPI_SSCTL_AUTOSS_Msk | QSPI_SSCTL_SS_Msk); +} + +/** + * @brief Enable the automatic slave selection function. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32SSPinMask Specifies slave selection pins. (QSPI_SS) + * @param[in] u32ActiveLevel Specifies the active level of slave selection signal. (QSPI_SS_ACTIVE_HIGH, QSPI_SS_ACTIVE_LOW) + * @return None + * @details This function will enable the automatic slave selection function. Only available in Master mode. + * The slave selection pin and the active level will be set in this function. + */ +void QSPI_EnableAutoSS(QSPI_T *qspi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel) +{ + qspi->SSCTL = (qspi->SSCTL & (~(QSPI_SSCTL_AUTOSS_Msk | QSPI_SSCTL_SSACTPOL_Msk | QSPI_SSCTL_SS_Msk))) | (u32SSPinMask | u32ActiveLevel | QSPI_SSCTL_AUTOSS_Msk); +} + +/** + * @brief Set the QSPI bus clock. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32BusClock The expected frequency of QSPI bus clock in Hz. + * @return Actual frequency of QSPI bus clock. + * @details This function is only available in Master mode. The actual clock rate may be different from the target QSPI bus clock rate. + * For example, if the QSPI source clock rate is 12 MHz and the target QSPI bus clock rate is 7 MHz, the actual QSPI bus clock + * rate will be 6 MHz. + * @note If u32BusClock = 0, DIVIDER setting will be set to the maximum value. + * @note If u32BusClock >= system clock frequency, QSPI peripheral clock source will be set to APB clock and DIVIDER will be set to 0. + * @note If u32BusClock >= QSPI peripheral clock source, DIVIDER will be set to 0. + */ +uint32_t QSPI_SetBusClock(QSPI_T *qspi, uint32_t u32BusClock) +{ + uint32_t u32ClkSrc, u32HCLKFreq; + uint32_t u32Div, u32RetValue; + + /* Get system clock frequency */ + u32HCLKFreq = CLK_GetHCLKFreq(); + + if (u32BusClock >= u32HCLKFreq) + { + /* Select PCLK as the clock source of QSPI */ + CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_QSPI0SEL_Msk)) | CLK_CLKSEL2_QSPI0SEL_PCLK0; + } + + /* Check clock source of QSPI */ + if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT) + { + u32ClkSrc = __HXT; /* Clock source is HXT */ + } + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL) + { + u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ + } + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0) + { + /* Clock source is PCLK0 */ + u32ClkSrc = CLK_GetPCLK0Freq(); + } + else + { + u32ClkSrc = __HIRC; /* Clock source is HIRC */ + } + + if (u32BusClock >= u32HCLKFreq) + { + /* Set DIVIDER = 0 */ + qspi->CLKDIV = 0UL; + /* Return master peripheral clock rate */ + u32RetValue = u32ClkSrc; + } + else if (u32BusClock >= u32ClkSrc) + { + /* Set DIVIDER = 0 */ + qspi->CLKDIV = 0UL; + /* Return master peripheral clock rate */ + u32RetValue = u32ClkSrc; + } + else if (u32BusClock == 0UL) + { + /* Set DIVIDER to the maximum value 0x1FF. f_qspi = f_qspi_clk_src / (DIVIDER + 1) */ + qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk; + /* Return master peripheral clock rate */ + u32RetValue = (u32ClkSrc / (0x1FFUL + 1UL)); + } + else + { + u32Div = (((u32ClkSrc * 10UL) / u32BusClock + 5UL) / 10UL) - 1UL; /* Round to the nearest integer */ + + if (u32Div > 0x1FFUL) + { + u32Div = 0x1FFUL; + qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk; + /* Return master peripheral clock rate */ + u32RetValue = (u32ClkSrc / (0x1FFUL + 1UL)); + } + else + { + qspi->CLKDIV = (qspi->CLKDIV & (~QSPI_CLKDIV_DIVIDER_Msk)) | (u32Div << QSPI_CLKDIV_DIVIDER_Pos); + /* Return master peripheral clock rate */ + u32RetValue = (u32ClkSrc / (u32Div + 1UL)); + } + } + + return u32RetValue; +} + +/** + * @brief Configure FIFO threshold setting. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32TxThreshold Decides the TX FIFO threshold. It could be 0 ~ 7. + * @param[in] u32RxThreshold Decides the RX FIFO threshold. It could be 0 ~ 7. + * @return None + * @details Set TX FIFO threshold and RX FIFO threshold configurations. + */ +void QSPI_SetFIFO(QSPI_T *qspi, uint32_t u32TxThreshold, uint32_t u32RxThreshold) +{ + qspi->FIFOCTL = (qspi->FIFOCTL & ~(QSPI_FIFOCTL_TXTH_Msk | QSPI_FIFOCTL_RXTH_Msk)) | + (u32TxThreshold << QSPI_FIFOCTL_TXTH_Pos) | + (u32RxThreshold << QSPI_FIFOCTL_RXTH_Pos); +} + +/** + * @brief Get the actual frequency of QSPI bus clock. Only available in Master mode. + * @param[in] qspi The pointer of the specified QSPI module. + * @return Actual QSPI bus clock frequency in Hz. + * @details This function will calculate the actual QSPI bus clock rate according to the QSPInSEL and DIVIDER settings. Only available in Master mode. + */ +uint32_t QSPI_GetBusClock(QSPI_T *qspi) +{ + uint32_t u32Div; + uint32_t u32ClkSrc; + + /* Get DIVIDER setting */ + u32Div = (qspi->CLKDIV & QSPI_CLKDIV_DIVIDER_Msk) >> QSPI_CLKDIV_DIVIDER_Pos; + + /* Check clock source of QSPI */ + if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT) + { + u32ClkSrc = __HXT; /* Clock source is HXT */ + } + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL) + { + u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ + } + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0) + { + /* Clock source is PCLK0 */ + u32ClkSrc = CLK_GetPCLK0Freq(); + } + else + { + u32ClkSrc = __HIRC; /* Clock source is HIRC */ + } + + /* Return QSPI bus clock rate */ + return (u32ClkSrc / (u32Div + 1UL)); +} + +/** + * @brief Enable interrupt function. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to a interrupt enable bit. + * This parameter decides which interrupts will be enabled. It is combination of: + * - \ref QSPI_UNIT_INT_MASK + * - \ref QSPI_SSACT_INT_MASK + * - \ref QSPI_SSINACT_INT_MASK + * - \ref QSPI_SLVUR_INT_MASK + * - \ref QSPI_SLVBE_INT_MASK + * - \ref QSPI_SLVTO_INT_MASK + * - \ref QSPI_TXUF_INT_MASK + * - \ref QSPI_FIFO_TXTH_INT_MASK + * - \ref QSPI_FIFO_RXTH_INT_MASK + * - \ref QSPI_FIFO_RXOV_INT_MASK + * - \ref QSPI_FIFO_RXTO_INT_MASK + * + * @return None + * @details Enable QSPI related interrupts specified by u32Mask parameter. + */ +void QSPI_EnableInt(QSPI_T *qspi, uint32_t u32Mask) +{ + /* Enable unit transfer interrupt flag */ + if ((u32Mask & QSPI_UNIT_INT_MASK) == QSPI_UNIT_INT_MASK) + { + qspi->CTL |= QSPI_CTL_UNITIEN_Msk; + } + + /* Enable slave selection signal active interrupt flag */ + if ((u32Mask & QSPI_SSACT_INT_MASK) == QSPI_SSACT_INT_MASK) + { + qspi->SSCTL |= QSPI_SSCTL_SSACTIEN_Msk; + } + + /* Enable slave selection signal inactive interrupt flag */ + if ((u32Mask & QSPI_SSINACT_INT_MASK) == QSPI_SSINACT_INT_MASK) + { + qspi->SSCTL |= QSPI_SSCTL_SSINAIEN_Msk; + } + + /* Enable slave TX under run interrupt flag */ + if ((u32Mask & QSPI_SLVUR_INT_MASK) == QSPI_SLVUR_INT_MASK) + { + qspi->SSCTL |= QSPI_SSCTL_SLVURIEN_Msk; + } + + /* Enable slave bit count error interrupt flag */ + if ((u32Mask & QSPI_SLVBE_INT_MASK) == QSPI_SLVBE_INT_MASK) + { + qspi->SSCTL |= QSPI_SSCTL_SLVBEIEN_Msk; + } + + /* Enable slave mode time-out interrupt flag */ + if ((u32Mask & QSPI_SLVTO_INT_MASK) == QSPI_SLVTO_INT_MASK) + { + qspi->SSCTL |= QSPI_SSCTL_SLVTOIEN_Msk; + } + + /* Enable slave TX underflow interrupt flag */ + if ((u32Mask & QSPI_TXUF_INT_MASK) == QSPI_TXUF_INT_MASK) + { + qspi->FIFOCTL |= QSPI_FIFOCTL_TXUFIEN_Msk; + } + + /* Enable TX threshold interrupt flag */ + if ((u32Mask & QSPI_FIFO_TXTH_INT_MASK) == QSPI_FIFO_TXTH_INT_MASK) + { + qspi->FIFOCTL |= QSPI_FIFOCTL_TXTHIEN_Msk; + } + + /* Enable RX threshold interrupt flag */ + if ((u32Mask & QSPI_FIFO_RXTH_INT_MASK) == QSPI_FIFO_RXTH_INT_MASK) + { + qspi->FIFOCTL |= QSPI_FIFOCTL_RXTHIEN_Msk; + } + + /* Enable RX overrun interrupt flag */ + if ((u32Mask & QSPI_FIFO_RXOV_INT_MASK) == QSPI_FIFO_RXOV_INT_MASK) + { + qspi->FIFOCTL |= QSPI_FIFOCTL_RXOVIEN_Msk; + } + + /* Enable RX time-out interrupt flag */ + if ((u32Mask & QSPI_FIFO_RXTO_INT_MASK) == QSPI_FIFO_RXTO_INT_MASK) + { + qspi->FIFOCTL |= QSPI_FIFOCTL_RXTOIEN_Msk; + } +} + +/** + * @brief Disable interrupt function. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to a interrupt bit. + * This parameter decides which interrupts will be disabled. It is combination of: + * - \ref QSPI_UNIT_INT_MASK + * - \ref QSPI_SSACT_INT_MASK + * - \ref QSPI_SSINACT_INT_MASK + * - \ref QSPI_SLVUR_INT_MASK + * - \ref QSPI_SLVBE_INT_MASK + * - \ref QSPI_SLVTO_INT_MASK + * - \ref QSPI_TXUF_INT_MASK + * - \ref QSPI_FIFO_TXTH_INT_MASK + * - \ref QSPI_FIFO_RXTH_INT_MASK + * - \ref QSPI_FIFO_RXOV_INT_MASK + * - \ref QSPI_FIFO_RXTO_INT_MASK + * + * @return None + * @details Disable QSPI related interrupts specified by u32Mask parameter. + */ +void QSPI_DisableInt(QSPI_T *qspi, uint32_t u32Mask) +{ + /* Disable unit transfer interrupt flag */ + if ((u32Mask & QSPI_UNIT_INT_MASK) == QSPI_UNIT_INT_MASK) + { + qspi->CTL &= ~QSPI_CTL_UNITIEN_Msk; + } + + /* Disable slave selection signal active interrupt flag */ + if ((u32Mask & QSPI_SSACT_INT_MASK) == QSPI_SSACT_INT_MASK) + { + qspi->SSCTL &= ~QSPI_SSCTL_SSACTIEN_Msk; + } + + /* Disable slave selection signal inactive interrupt flag */ + if ((u32Mask & QSPI_SSINACT_INT_MASK) == QSPI_SSINACT_INT_MASK) + { + qspi->SSCTL &= ~QSPI_SSCTL_SSINAIEN_Msk; + } + + /* Disable slave TX under run interrupt flag */ + if ((u32Mask & QSPI_SLVUR_INT_MASK) == QSPI_SLVUR_INT_MASK) + { + qspi->SSCTL &= ~QSPI_SSCTL_SLVURIEN_Msk; + } + + /* Disable slave bit count error interrupt flag */ + if ((u32Mask & QSPI_SLVBE_INT_MASK) == QSPI_SLVBE_INT_MASK) + { + qspi->SSCTL &= ~QSPI_SSCTL_SLVBEIEN_Msk; + } + + /* Disable slave mode time-out interrupt flag */ + if ((u32Mask & QSPI_SLVTO_INT_MASK) == QSPI_SLVTO_INT_MASK) + { + qspi->SSCTL &= ~QSPI_SSCTL_SLVTOIEN_Msk; + } + + /* Disable slave TX underflow interrupt flag */ + if ((u32Mask & QSPI_TXUF_INT_MASK) == QSPI_TXUF_INT_MASK) + { + qspi->FIFOCTL &= ~QSPI_FIFOCTL_TXUFIEN_Msk; + } + + /* Disable TX threshold interrupt flag */ + if ((u32Mask & QSPI_FIFO_TXTH_INT_MASK) == QSPI_FIFO_TXTH_INT_MASK) + { + qspi->FIFOCTL &= ~QSPI_FIFOCTL_TXTHIEN_Msk; + } + + /* Disable RX threshold interrupt flag */ + if ((u32Mask & QSPI_FIFO_RXTH_INT_MASK) == QSPI_FIFO_RXTH_INT_MASK) + { + qspi->FIFOCTL &= ~QSPI_FIFOCTL_RXTHIEN_Msk; + } + + /* Disable RX overrun interrupt flag */ + if ((u32Mask & QSPI_FIFO_RXOV_INT_MASK) == QSPI_FIFO_RXOV_INT_MASK) + { + qspi->FIFOCTL &= ~QSPI_FIFOCTL_RXOVIEN_Msk; + } + + /* Disable RX time-out interrupt flag */ + if ((u32Mask & QSPI_FIFO_RXTO_INT_MASK) == QSPI_FIFO_RXTO_INT_MASK) + { + qspi->FIFOCTL &= ~QSPI_FIFOCTL_RXTOIEN_Msk; + } +} + +/** + * @brief Get interrupt flag. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32Mask The combination of all related interrupt sources. + * Each bit corresponds to a interrupt source. + * This parameter decides which interrupt flags will be read. It is combination of: + * - \ref QSPI_UNIT_INT_MASK + * - \ref QSPI_SSACT_INT_MASK + * - \ref QSPI_SSINACT_INT_MASK + * - \ref QSPI_SLVUR_INT_MASK + * - \ref QSPI_SLVBE_INT_MASK + * - \ref QSPI_SLVTO_INT_MASK + * - \ref QSPI_TXUF_INT_MASK + * - \ref QSPI_FIFO_TXTH_INT_MASK + * - \ref QSPI_FIFO_RXTH_INT_MASK + * - \ref QSPI_FIFO_RXOV_INT_MASK + * - \ref QSPI_FIFO_RXTO_INT_MASK + * + * @return Interrupt flags of selected sources. + * @details Get QSPI related interrupt flags specified by u32Mask parameter. + */ +uint32_t QSPI_GetIntFlag(QSPI_T *qspi, uint32_t u32Mask) +{ + uint32_t u32IntFlag = 0U, u32TmpVal; + + u32TmpVal = qspi->STATUS & QSPI_STATUS_UNITIF_Msk; + + /* Check unit transfer interrupt flag */ + if ((u32Mask & QSPI_UNIT_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= QSPI_UNIT_INT_MASK; + } + + u32TmpVal = qspi->STATUS & QSPI_STATUS_SSACTIF_Msk; + + /* Check slave selection signal active interrupt flag */ + if ((u32Mask & QSPI_SSACT_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= QSPI_SSACT_INT_MASK; + } + + u32TmpVal = qspi->STATUS & QSPI_STATUS_SSINAIF_Msk; + + /* Check slave selection signal inactive interrupt flag */ + if ((u32Mask & QSPI_SSINACT_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= QSPI_SSINACT_INT_MASK; + } + + u32TmpVal = qspi->STATUS & QSPI_STATUS_SLVURIF_Msk; + + /* Check slave TX under run interrupt flag */ + if ((u32Mask & QSPI_SLVUR_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= QSPI_SLVUR_INT_MASK; + } + + u32TmpVal = qspi->STATUS & QSPI_STATUS_SLVBEIF_Msk; + + /* Check slave bit count error interrupt flag */ + if ((u32Mask & QSPI_SLVBE_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= QSPI_SLVBE_INT_MASK; + } + + u32TmpVal = qspi->STATUS & QSPI_STATUS_SLVTOIF_Msk; + + /* Check slave mode time-out interrupt flag */ + if ((u32Mask & QSPI_SLVTO_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= QSPI_SLVTO_INT_MASK; + } + + u32TmpVal = qspi->STATUS & QSPI_STATUS_TXUFIF_Msk; + + /* Check slave TX underflow interrupt flag */ + if ((u32Mask & QSPI_TXUF_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= QSPI_TXUF_INT_MASK; + } + + u32TmpVal = qspi->STATUS & QSPI_STATUS_TXTHIF_Msk; + + /* Check TX threshold interrupt flag */ + if ((u32Mask & QSPI_FIFO_TXTH_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= QSPI_FIFO_TXTH_INT_MASK; + } + + u32TmpVal = qspi->STATUS & QSPI_STATUS_RXTHIF_Msk; + + /* Check RX threshold interrupt flag */ + if ((u32Mask & QSPI_FIFO_RXTH_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= QSPI_FIFO_RXTH_INT_MASK; + } + + u32TmpVal = qspi->STATUS & QSPI_STATUS_RXOVIF_Msk; + + /* Check RX overrun interrupt flag */ + if ((u32Mask & QSPI_FIFO_RXOV_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= QSPI_FIFO_RXOV_INT_MASK; + } + + u32TmpVal = qspi->STATUS & QSPI_STATUS_RXTOIF_Msk; + + /* Check RX time-out interrupt flag */ + if ((u32Mask & QSPI_FIFO_RXTO_INT_MASK) && (u32TmpVal)) + { + u32IntFlag |= QSPI_FIFO_RXTO_INT_MASK; + } + + return u32IntFlag; +} + +/** + * @brief Clear interrupt flag. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32Mask The combination of all related interrupt sources. + * Each bit corresponds to a interrupt source. + * This parameter decides which interrupt flags will be cleared. It could be the combination of: + * - \ref QSPI_UNIT_INT_MASK + * - \ref QSPI_SSACT_INT_MASK + * - \ref QSPI_SSINACT_INT_MASK + * - \ref QSPI_SLVUR_INT_MASK + * - \ref QSPI_SLVBE_INT_MASK + * - \ref QSPI_SLVTO_INT_MASK + * - \ref QSPI_TXUF_INT_MASK + * - \ref QSPI_FIFO_RXOV_INT_MASK + * - \ref QSPI_FIFO_RXTO_INT_MASK + * + * @return None + * @details Clear QSPI related interrupt flags specified by u32Mask parameter. + */ +void QSPI_ClearIntFlag(QSPI_T *qspi, uint32_t u32Mask) +{ + if (u32Mask & QSPI_UNIT_INT_MASK) + { + qspi->STATUS = QSPI_STATUS_UNITIF_Msk; /* Clear unit transfer interrupt flag */ + } + + if (u32Mask & QSPI_SSACT_INT_MASK) + { + qspi->STATUS = QSPI_STATUS_SSACTIF_Msk; /* Clear slave selection signal active interrupt flag */ + } + + if (u32Mask & QSPI_SSINACT_INT_MASK) + { + qspi->STATUS = QSPI_STATUS_SSINAIF_Msk; /* Clear slave selection signal inactive interrupt flag */ + } + + if (u32Mask & QSPI_SLVUR_INT_MASK) + { + qspi->STATUS = QSPI_STATUS_SLVURIF_Msk; /* Clear slave TX under run interrupt flag */ + } + + if (u32Mask & QSPI_SLVBE_INT_MASK) + { + qspi->STATUS = QSPI_STATUS_SLVBEIF_Msk; /* Clear slave bit count error interrupt flag */ + } + + if (u32Mask & QSPI_SLVTO_INT_MASK) + { + qspi->STATUS = QSPI_STATUS_SLVTOIF_Msk; /* Clear slave mode time-out interrupt flag */ + } + + if (u32Mask & QSPI_TXUF_INT_MASK) + { + qspi->STATUS = QSPI_STATUS_TXUFIF_Msk; /* Clear slave TX underflow interrupt flag */ + } + + if (u32Mask & QSPI_FIFO_RXOV_INT_MASK) + { + qspi->STATUS = QSPI_STATUS_RXOVIF_Msk; /* Clear RX overrun interrupt flag */ + } + + if (u32Mask & QSPI_FIFO_RXTO_INT_MASK) + { + qspi->STATUS = QSPI_STATUS_RXTOIF_Msk; /* Clear RX time-out interrupt flag */ + } +} + +/** + * @brief Get QSPI status. + * @param[in] qspi The pointer of the specified QSPI module. + * @param[in] u32Mask The combination of all related sources. + * Each bit corresponds to a source. + * This parameter decides which flags will be read. It is combination of: + * - \ref QSPI_BUSY_MASK + * - \ref QSPI_RX_EMPTY_MASK + * - \ref QSPI_RX_FULL_MASK + * - \ref QSPI_TX_EMPTY_MASK + * - \ref QSPI_TX_FULL_MASK + * - \ref QSPI_TXRX_RESET_MASK + * - \ref QSPI_SPIEN_STS_MASK + * - \ref QSPI_SSLINE_STS_MASK + * + * @return Flags of selected sources. + * @details Get QSPI related status specified by u32Mask parameter. + */ +uint32_t QSPI_GetStatus(QSPI_T *qspi, uint32_t u32Mask) +{ + uint32_t u32Flag = 0UL, u32TmpValue; + + u32TmpValue = qspi->STATUS & QSPI_STATUS_BUSY_Msk; + + /* Check busy status */ + if ((u32Mask & QSPI_BUSY_MASK) && (u32TmpValue)) + { + u32Flag |= QSPI_BUSY_MASK; + } + + u32TmpValue = qspi->STATUS & QSPI_STATUS_RXEMPTY_Msk; + + /* Check RX empty flag */ + if ((u32Mask & QSPI_RX_EMPTY_MASK) && (u32TmpValue)) + { + u32Flag |= QSPI_RX_EMPTY_MASK; + } + + u32TmpValue = qspi->STATUS & QSPI_STATUS_RXFULL_Msk; + + /* Check RX full flag */ + if ((u32Mask & QSPI_RX_FULL_MASK) && (u32TmpValue)) + { + u32Flag |= QSPI_RX_FULL_MASK; + } + + u32TmpValue = qspi->STATUS & QSPI_STATUS_TXEMPTY_Msk; + + /* Check TX empty flag */ + if ((u32Mask & QSPI_TX_EMPTY_MASK) && (u32TmpValue)) + { + u32Flag |= QSPI_TX_EMPTY_MASK; + } + + u32TmpValue = qspi->STATUS & QSPI_STATUS_TXFULL_Msk; + + /* Check TX full flag */ + if ((u32Mask & QSPI_TX_FULL_MASK) && (u32TmpValue)) + { + u32Flag |= QSPI_TX_FULL_MASK; + } + + u32TmpValue = qspi->STATUS & QSPI_STATUS_TXRXRST_Msk; + + /* Check TX/RX reset flag */ + if ((u32Mask & QSPI_TXRX_RESET_MASK) && (u32TmpValue)) + { + u32Flag |= QSPI_TXRX_RESET_MASK; + } + + u32TmpValue = qspi->STATUS & QSPI_STATUS_SPIENSTS_Msk; + + /* Check SPIEN flag */ + if ((u32Mask & QSPI_SPIEN_STS_MASK) && (u32TmpValue)) + { + u32Flag |= QSPI_SPIEN_STS_MASK; + } + + u32TmpValue = qspi->STATUS & QSPI_STATUS_SSLINE_Msk; + + /* Check QSPIx_SS line status */ + if ((u32Mask & QSPI_SSLINE_STS_MASK) && (u32TmpValue)) + { + u32Flag |= QSPI_SSLINE_STS_MASK; + } + + return u32Flag; +} + + + +/*@}*/ /* end of group QSPI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group QSPI_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_rtc.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_rtc.c new file mode 100644 index 0000000000..5d56d2b629 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_rtc.c @@ -0,0 +1,782 @@ +/**************************************************************************//** + * @file rtc.c + * @version V1.00 + * $Revision: 4 $ + * $Date: 18/04/25 11:43a $ + * @brief M031 series Real Time Clock(RTC) driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "M031Series.h" + + +/** @cond HIDDEN_SYMBOLS */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Macro, type and constant definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#define RTC_GLOBALS + +/*---------------------------------------------------------------------------------------------------------*/ +/* Global file scope (static) variables */ +/*---------------------------------------------------------------------------------------------------------*/ +static volatile uint32_t g_u32HiYear, g_u32LoYear, g_u32HiMonth, g_u32LoMonth, g_u32HiDay, g_u32LoDay; +static volatile uint32_t g_u32HiHour, g_u32LoHour, g_u32HiMin, g_u32LoMin, g_u32HiSec, g_u32LoSec; + +/** @endcond HIDDEN_SYMBOLS */ + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup RTC_Driver RTC Driver + @{ +*/ + +/** @addtogroup RTC_EXPORTED_FUNCTIONS RTC Exported Functions + @{ +*/ + +/** + * @brief Initialize RTC module and start counting + * + * @param[in] psPt Specify the time property and current date and time. It includes: \n + * u32Year: Year value, range between 2000 ~ 2099. \n + * u32Month: Month value, range between 1 ~ 12. \n + * u32Day: Day value, range between 1 ~ 31. \n + * u32DayOfWeek: Day of the week. [RTC_SUNDAY / RTC_MONDAY / RTC_TUESDAY / + * RTC_WEDNESDAY / RTC_THURSDAY / RTC_FRIDAY / + * RTC_SATURDAY] \n + * u32Hour: Hour value, range between 0 ~ 23. \n + * u32Minute: Minute value, range between 0 ~ 59. \n + * u32Second: Second value, range between 0 ~ 59. \n + * u32TimeScale: [RTC_CLOCK_12 / RTC_CLOCK_24] \n + * u8AmPm: [RTC_AM / RTC_PM] \n + * + * @return None + * + * @details This function is used to: \n + * 1. Write initial key to let RTC start count. \n + * 2. Input parameter indicates start date/time. \n + * 3. User has to make sure that parameters of RTC date/time are reasonable. \n + * @note Null pointer for using default starting date/time. + */ +void RTC_Open(S_RTC_TIME_DATA_T *psPt) +{ + RTC->INIT = RTC_INIT_KEY; + + if (RTC->INIT != RTC_INIT_ACTIVE_Msk) + { + RTC->INIT = RTC_INIT_KEY; + + while (RTC->INIT != RTC_INIT_ACTIVE_Msk) + { + } + } + + if (psPt == NULL) + { + /* No RTC date/time data */ + } + else + { + /* Set RTC date and time */ + RTC_SetDateAndTime(psPt); + } +} + +/** + * @brief Disable RTC Clock + * + * @param None + * + * @return None + * + * @details This API will disable RTC peripheral clock and stops RTC counting. + */ +void RTC_Close(void) +{ + CLK->APBCLK0 &= ~CLK_APBCLK0_RTCCKEN_Msk; +} + +/** + * @brief Set Frequency Compensation Data + * + * @param[in] i32FrequencyX10000 Specify the RTC clock X 10000, ex: 327736512 means 32773.6512. + * + * @return None + * + */ +void RTC_32KCalibration(int32_t i32FrequencyX10000) +{ + + /* + Frequency counter measurement : 32773.6512 Hz + */ + uint32_t u32Index; + uint32_t u32Compensate; + + /* 327736512 %10000 = 6512 */ + u32Compensate = (uint32_t)(i32FrequencyX10000 % 10000); + /*Fraction Part: (6512 X 64)/10000 = 41.6768(0x2A) => RTC_FREQADJ[5:0]=0x2A*/ + u32Compensate = ((u32Compensate * 64) / 10000); + u32Compensate &= 0x3F; + /* + Formula for 32K compensation is + FREQADJ = 0~0x00001F00 (Frequency range : 32752Hz ~ 32783Hz) + */ + + if (i32FrequencyX10000 >= (uint32_t)327840000) + { + u32Compensate = 0x1F3F; + } + else if (i32FrequencyX10000 < (uint32_t)327520000) + { + u32Compensate = 0x0; + } + else + { + /* Integer Part: 32773 => RTC_FREQADJ[12:8] = 0x15 */ + for (u32Index = 0; u32Index < 0x20 ; u32Index++) + { + if ((i32FrequencyX10000 >= 327520000 + (u32Index * 10000)) && (i32FrequencyX10000 < 327520000 + ((u32Index + 1) * 10000))) + { + u32Compensate += (u32Index << RTC_FREQADJ_INTEGER_Pos); + break; + } + } + } + + + RTC->FREQADJ = (uint32_t)u32Compensate; +} + +/** + * @brief Get Current RTC Date and Time + * + * @param[out] psPt The returned pointer is specified the current RTC value. It includes: \n + * u32Year: Year value \n + * u32Month: Month value \n + * u32Day: Day value \n + * u32DayOfWeek: Day of week \n + * u32Hour: Hour value \n + * u32Minute: Minute value \n + * u32Second: Second value \n + * u32TimeScale: [RTC_CLOCK_12 / RTC_CLOCK_24] \n + * u8AmPm: [RTC_AM / RTC_PM] \n + * + * @return None + * + * @details This API is used to get the current RTC date and time value. + */ +void RTC_GetDateAndTime(S_RTC_TIME_DATA_T *psPt) +{ + uint32_t u32Tmp; + + psPt->u32TimeScale = RTC->CLKFMT & RTC_CLKFMT_24HEN_Msk; /* 12/24-hour */ + psPt->u32DayOfWeek = RTC->WEEKDAY & RTC_WEEKDAY_WEEKDAY_Msk; /* Day of the week */ + + /* Get [Date digit] data */ + g_u32HiYear = (RTC->CAL & RTC_CAL_TENYEAR_Msk) >> RTC_CAL_TENYEAR_Pos; + g_u32LoYear = (RTC->CAL & RTC_CAL_YEAR_Msk) >> RTC_CAL_YEAR_Pos; + g_u32HiMonth = (RTC->CAL & RTC_CAL_TENMON_Msk) >> RTC_CAL_TENMON_Pos; + g_u32LoMonth = (RTC->CAL & RTC_CAL_MON_Msk) >> RTC_CAL_MON_Pos; + g_u32HiDay = (RTC->CAL & RTC_CAL_TENDAY_Msk) >> RTC_CAL_TENDAY_Pos; + g_u32LoDay = (RTC->CAL & RTC_CAL_DAY_Msk) >> RTC_CAL_DAY_Pos; + + /* Get [Time digit] data */ + g_u32HiHour = (RTC->TIME & RTC_TIME_TENHR_Msk) >> RTC_TIME_TENHR_Pos; + g_u32LoHour = (RTC->TIME & RTC_TIME_HR_Msk) >> RTC_TIME_HR_Pos; + g_u32HiMin = (RTC->TIME & RTC_TIME_TENMIN_Msk) >> RTC_TIME_TENMIN_Pos; + g_u32LoMin = (RTC->TIME & RTC_TIME_MIN_Msk) >> RTC_TIME_MIN_Pos; + g_u32HiSec = (RTC->TIME & RTC_TIME_TENSEC_Msk) >> RTC_TIME_TENSEC_Pos; + g_u32LoSec = (RTC->TIME & RTC_TIME_SEC_Msk) >> RTC_TIME_SEC_Pos; + + /* Compute to 20XX year */ + u32Tmp = (g_u32HiYear * 10ul); + u32Tmp += g_u32LoYear; + psPt->u32Year = u32Tmp + RTC_YEAR2000; + + /* Compute 0~12 month */ + u32Tmp = (g_u32HiMonth * 10ul); + psPt->u32Month = u32Tmp + g_u32LoMonth; + + /* Compute 0~31 day */ + u32Tmp = (g_u32HiDay * 10ul); + psPt->u32Day = u32Tmp + g_u32LoDay; + + /* Compute 12/24 hour */ + if (psPt->u32TimeScale == RTC_CLOCK_12) + { + u32Tmp = (g_u32HiHour * 10ul); + u32Tmp += g_u32LoHour; + psPt->u32Hour = u32Tmp; /* AM: 1~12. PM: 21~32. */ + + if (psPt->u32Hour >= 21ul) + { + psPt->u32AmPm = RTC_PM; + psPt->u32Hour -= 20ul; + } + else + { + psPt->u32AmPm = RTC_AM; + } + + u32Tmp = (g_u32HiMin * 10ul); + u32Tmp += g_u32LoMin; + psPt->u32Minute = u32Tmp; + + u32Tmp = (g_u32HiSec * 10ul); + u32Tmp += g_u32LoSec; + psPt->u32Second = u32Tmp; + } + else + { + u32Tmp = (g_u32HiHour * 10ul); + u32Tmp += g_u32LoHour; + psPt->u32Hour = u32Tmp; + + u32Tmp = (g_u32HiMin * 10ul); + u32Tmp += g_u32LoMin; + psPt->u32Minute = u32Tmp; + + u32Tmp = (g_u32HiSec * 10ul); + u32Tmp += g_u32LoSec; + psPt->u32Second = u32Tmp; + } +} + +/** + * @brief Get RTC Alarm Date and Time + * + * @param[out] psPt The returned pointer is specified the RTC alarm value. It includes: \n + * u32Year: Year value \n + * u32Month: Month value \n + * u32Day: Day value \n + * u32DayOfWeek: Day of week \n + * u32Hour: Hour value \n + * u32Minute: Minute value \n + * u32Second: Second value \n + * u32TimeScale: [RTC_CLOCK_12 / RTC_CLOCK_24] \n + * u8AmPm: [RTC_AM / RTC_PM] \n + * + * @return None + * + * @details This API is used to get the RTC alarm date and time setting. + */ +void RTC_GetAlarmDateAndTime(S_RTC_TIME_DATA_T *psPt) +{ + uint32_t u32Tmp; + + psPt->u32TimeScale = RTC->CLKFMT & RTC_CLKFMT_24HEN_Msk; /* 12/24-hour */ + psPt->u32DayOfWeek = RTC->WEEKDAY & RTC_WEEKDAY_WEEKDAY_Msk; /* Day of the week */ + + /* Get alarm [Date digit] data */ + g_u32HiYear = (RTC->CALM & RTC_CALM_TENYEAR_Msk) >> RTC_CALM_TENYEAR_Pos; + g_u32LoYear = (RTC->CALM & RTC_CALM_YEAR_Msk) >> RTC_CALM_YEAR_Pos; + g_u32HiMonth = (RTC->CALM & RTC_CALM_TENMON_Msk) >> RTC_CALM_TENMON_Pos; + g_u32LoMonth = (RTC->CALM & RTC_CALM_MON_Msk) >> RTC_CALM_MON_Pos; + g_u32HiDay = (RTC->CALM & RTC_CALM_TENDAY_Msk) >> RTC_CALM_TENDAY_Pos; + g_u32LoDay = (RTC->CALM & RTC_CALM_DAY_Msk) >> RTC_CALM_DAY_Pos; + + /* Get alarm [Time digit] data */ + g_u32HiHour = (RTC->TALM & RTC_TALM_TENHR_Msk) >> RTC_TALM_TENHR_Pos; + g_u32LoHour = (RTC->TALM & RTC_TALM_HR_Msk) >> RTC_TALM_HR_Pos; + g_u32HiMin = (RTC->TALM & RTC_TALM_TENMIN_Msk) >> RTC_TALM_TENMIN_Pos; + g_u32LoMin = (RTC->TALM & RTC_TALM_MIN_Msk) >> RTC_TALM_MIN_Pos; + g_u32HiSec = (RTC->TALM & RTC_TALM_TENSEC_Msk) >> RTC_TALM_TENSEC_Pos; + g_u32LoSec = (RTC->TALM & RTC_TALM_SEC_Msk) >> RTC_TALM_SEC_Pos; + + /* Compute to 20XX year */ + u32Tmp = (g_u32HiYear * 10ul); + u32Tmp += g_u32LoYear; + psPt->u32Year = u32Tmp + RTC_YEAR2000; + + /* Compute 0~12 month */ + u32Tmp = (g_u32HiMonth * 10ul); + psPt->u32Month = u32Tmp + g_u32LoMonth; + + /* Compute 0~31 day */ + u32Tmp = (g_u32HiDay * 10ul); + psPt->u32Day = u32Tmp + g_u32LoDay; + + /* Compute 12/24 hour */ + if (psPt->u32TimeScale == RTC_CLOCK_12) + { + u32Tmp = (g_u32HiHour * 10ul); + u32Tmp += g_u32LoHour; + psPt->u32Hour = u32Tmp; /* AM: 1~12. PM: 21~32. */ + + if (psPt->u32Hour >= 21ul) + { + psPt->u32AmPm = RTC_PM; + psPt->u32Hour -= 20ul; + } + else + { + psPt->u32AmPm = RTC_AM; + } + + u32Tmp = (g_u32HiMin * 10ul); + u32Tmp += g_u32LoMin; + psPt->u32Minute = u32Tmp; + + u32Tmp = (g_u32HiSec * 10ul); + u32Tmp += g_u32LoSec; + psPt->u32Second = u32Tmp; + + } + else + { + u32Tmp = (g_u32HiHour * 10ul); + u32Tmp += g_u32LoHour; + psPt->u32Hour = u32Tmp; + + u32Tmp = (g_u32HiMin * 10ul); + u32Tmp += g_u32LoMin; + psPt->u32Minute = u32Tmp; + + u32Tmp = (g_u32HiSec * 10ul); + u32Tmp += g_u32LoSec; + psPt->u32Second = u32Tmp; + } +} + +/** + * @brief Update Current RTC Date and Time + * + * @param[in] psPt Specify the time property and current date and time. It includes: \n + * u32Year: Year value, range between 2000 ~ 2099. \n + * u32Month: Month value, range between 1 ~ 12. \n + * u32Day: Day value, range between 1 ~ 31. \n + * u32DayOfWeek: Day of the week. [RTC_SUNDAY / RTC_MONDAY / RTC_TUESDAY / + * RTC_WEDNESDAY / RTC_THURSDAY / RTC_FRIDAY / + * RTC_SATURDAY] \n + * u32Hour: Hour value, range between 0 ~ 23. \n + * u32Minute: Minute value, range between 0 ~ 59. \n + * u32Second: Second value, range between 0 ~ 59. \n + * u32TimeScale: [RTC_CLOCK_12 / RTC_CLOCK_24] \n + * u8AmPm: [RTC_AM / RTC_PM] \n + * + * @return None + * + * @details This API is used to update current date and time to RTC. + */ +void RTC_SetDateAndTime(S_RTC_TIME_DATA_T *psPt) +{ + uint32_t u32RegCAL, u32RegTIME; + + if (psPt == NULL) + { + /* No RTC date/time data */ + } + else + { + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC 24/12 hour setting and Day of the Week */ + /*-----------------------------------------------------------------------------------------------------*/ + + if (psPt->u32TimeScale == RTC_CLOCK_12) + { + RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk; + + /*-------------------------------------------------------------------------------------------------*/ + /* Important, range of 12-hour PM mode is 21 up to 32 */ + /*-------------------------------------------------------------------------------------------------*/ + if (psPt->u32AmPm == RTC_PM) + { + psPt->u32Hour += 20ul; + } + } + else + { + RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk; + } + + /* Set Day of the Week */ + RTC->WEEKDAY = psPt->u32DayOfWeek; + + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC Current Date and Time */ + /*-----------------------------------------------------------------------------------------------------*/ + u32RegCAL = ((psPt->u32Year - RTC_YEAR2000) / 10ul) << 20; + u32RegCAL |= (((psPt->u32Year - RTC_YEAR2000) % 10ul) << 16); + u32RegCAL |= ((psPt->u32Month / 10ul) << 12); + u32RegCAL |= ((psPt->u32Month % 10ul) << 8); + u32RegCAL |= ((psPt->u32Day / 10ul) << 4); + u32RegCAL |= (psPt->u32Day % 10ul); + + u32RegTIME = ((psPt->u32Hour / 10ul) << 20); + u32RegTIME |= ((psPt->u32Hour % 10ul) << 16); + u32RegTIME |= ((psPt->u32Minute / 10ul) << 12); + u32RegTIME |= ((psPt->u32Minute % 10ul) << 8); + u32RegTIME |= ((psPt->u32Second / 10ul) << 4); + u32RegTIME |= (psPt->u32Second % 10ul); + + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC Calender and Time Loading */ + /*-----------------------------------------------------------------------------------------------------*/ + + RTC->CAL = (uint32_t)u32RegCAL; + RTC->TIME = (uint32_t)u32RegTIME; + } +} + +/** + * @brief Update RTC Alarm Date and Time + * + * @param[in] psPt Specify the time property and alarm date and time. It includes: \n + * u32Year: Year value, range between 2000 ~ 2099. \n + * u32Month: Month value, range between 1 ~ 12. \n + * u32Day: Day value, range between 1 ~ 31. \n + * u32DayOfWeek: Day of the week. [RTC_SUNDAY / RTC_MONDAY / RTC_TUESDAY / + * RTC_WEDNESDAY / RTC_THURSDAY / RTC_FRIDAY / + * RTC_SATURDAY] \n + * u32Hour: Hour value, range between 0 ~ 23. \n + * u32Minute: Minute value, range between 0 ~ 59. \n + * u32Second: Second value, range between 0 ~ 59. \n + * u32TimeScale: [RTC_CLOCK_12 / RTC_CLOCK_24] \n + * u8AmPm: [RTC_AM / RTC_PM] \n + * + * @return None + * + * @details This API is used to update alarm date and time setting to RTC. + */ +void RTC_SetAlarmDateAndTime(S_RTC_TIME_DATA_T *psPt) +{ + uint32_t u32RegCALM, u32RegTALM; + + if (psPt == NULL) + { + /* No RTC date/time data */ + } + else + { + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC 24/12 hour setting and Day of the Week */ + /*-----------------------------------------------------------------------------------------------------*/ + + if (psPt->u32TimeScale == RTC_CLOCK_12) + { + RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk; + + /*-------------------------------------------------------------------------------------------------*/ + /* Important, range of 12-hour PM mode is 21 up to 32 */ + /*-------------------------------------------------------------------------------------------------*/ + if (psPt->u32AmPm == RTC_PM) + { + psPt->u32Hour += 20ul; + } + } + else + { + RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk; + } + + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC Alarm Date and Time */ + /*-----------------------------------------------------------------------------------------------------*/ + u32RegCALM = ((psPt->u32Year - RTC_YEAR2000) / 10ul) << 20; + u32RegCALM |= (((psPt->u32Year - RTC_YEAR2000) % 10ul) << 16); + u32RegCALM |= ((psPt->u32Month / 10ul) << 12); + u32RegCALM |= ((psPt->u32Month % 10ul) << 8); + u32RegCALM |= ((psPt->u32Day / 10ul) << 4); + u32RegCALM |= (psPt->u32Day % 10ul); + + u32RegTALM = ((psPt->u32Hour / 10ul) << 20); + u32RegTALM |= ((psPt->u32Hour % 10ul) << 16); + u32RegTALM |= ((psPt->u32Minute / 10ul) << 12); + u32RegTALM |= ((psPt->u32Minute % 10ul) << 8); + u32RegTALM |= ((psPt->u32Second / 10ul) << 4); + u32RegTALM |= (psPt->u32Second % 10ul); + + + RTC->CALM = (uint32_t)u32RegCALM; + RTC->TALM = (uint32_t)u32RegTALM; + } +} + +/** + * @brief Update RTC Current Date + * + * @param[in] u32Year The year calendar digit of current RTC setting. + * @param[in] u32Month The month calendar digit of current RTC setting. + * @param[in] u32Day The day calendar digit of current RTC setting. + * @param[in] u32DayOfWeek The Day of the week. [RTC_SUNDAY / RTC_MONDAY / RTC_TUESDAY / + * RTC_WEDNESDAY / RTC_THURSDAY / RTC_FRIDAY / + * RTC_SATURDAY] + * + * @return None + * + * @details This API is used to update current date to RTC. + */ +void RTC_SetDate(uint32_t u32Year, uint32_t u32Month, uint32_t u32Day, uint32_t u32DayOfWeek) +{ + uint32_t u32RegCAL; + + u32RegCAL = ((u32Year - RTC_YEAR2000) / 10ul) << 20; + u32RegCAL |= (((u32Year - RTC_YEAR2000) % 10ul) << 16); + u32RegCAL |= ((u32Month / 10ul) << 12); + u32RegCAL |= ((u32Month % 10ul) << 8); + u32RegCAL |= ((u32Day / 10ul) << 4); + u32RegCAL |= (u32Day % 10ul); + + /* Set Day of the Week */ + RTC->WEEKDAY = u32DayOfWeek & RTC_WEEKDAY_WEEKDAY_Msk; + + /* Set RTC Calender Loading */ + RTC->CAL = (uint32_t)u32RegCAL; +} + +/** + * @brief Update RTC Current Time + * + * @param[in] u32Hour The hour time digit of current RTC setting. + * @param[in] u32Minute The minute time digit of current RTC setting. + * @param[in] u32Second The second time digit of current RTC setting. + * @param[in] u32TimeMode The 24-Hour / 12-Hour Time Scale Selection. [RTC_CLOCK_12 / RTC_CLOCK_24] + * @param[in] u32AmPm 12-hour time scale with AM and PM indication. Only Time Scale select 12-hour used. [RTC_AM / RTC_PM] + * + * @return None + * + * @details This API is used to update current time to RTC. + */ +void RTC_SetTime(uint32_t u32Hour, uint32_t u32Minute, uint32_t u32Second, uint32_t u32TimeMode, uint32_t u32AmPm) +{ + uint32_t u32RegTIME; + + /* Important, range of 12-hour PM mode is 21 up to 32 */ + if ((u32TimeMode == RTC_CLOCK_12) && (u32AmPm == RTC_PM)) + { + u32Hour += 20ul; + } + + u32RegTIME = ((u32Hour / 10ul) << 20); + u32RegTIME |= ((u32Hour % 10ul) << 16); + u32RegTIME |= ((u32Minute / 10ul) << 12); + u32RegTIME |= ((u32Minute % 10ul) << 8); + u32RegTIME |= ((u32Second / 10ul) << 4); + u32RegTIME |= (u32Second % 10ul); + + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC 24/12 hour setting and Day of the Week */ + /*-----------------------------------------------------------------------------------------------------*/ + if (u32TimeMode == RTC_CLOCK_12) + { + RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk; + } + else + { + RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk; + } + + RTC->TIME = (uint32_t)u32RegTIME; +} + +/** + * @brief Update RTC Alarm Date + * + * @param[in] u32Year The year calendar digit of RTC alarm setting. + * @param[in] u32Month The month calendar digit of RTC alarm setting. + * @param[in] u32Day The day calendar digit of RTC alarm setting. + * + * @return None + * + * @details This API is used to update alarm date setting to RTC. + */ +void RTC_SetAlarmDate(uint32_t u32Year, uint32_t u32Month, uint32_t u32Day) +{ + uint32_t u32RegCALM; + + u32RegCALM = ((u32Year - RTC_YEAR2000) / 10ul) << 20; + u32RegCALM |= (((u32Year - RTC_YEAR2000) % 10ul) << 16); + u32RegCALM |= ((u32Month / 10ul) << 12); + u32RegCALM |= ((u32Month % 10ul) << 8); + u32RegCALM |= ((u32Day / 10ul) << 4); + u32RegCALM |= (u32Day % 10ul); + + /* Set RTC Alarm Date */ + RTC->CALM = (uint32_t)u32RegCALM; +} + +/** + * @brief Update RTC Alarm Time + * + * @param[in] u32Hour The hour time digit of RTC alarm setting. + * @param[in] u32Minute The minute time digit of RTC alarm setting. + * @param[in] u32Second The second time digit of RTC alarm setting. + * @param[in] u32TimeMode The 24-Hour / 12-Hour Time Scale Selection. [RTC_CLOCK_12 / RTC_CLOCK_24] + * @param[in] u32AmPm 12-hour time scale with AM and PM indication. Only Time Scale select 12-hour used. [RTC_AM / RTC_PM] + * + * @return None + * + * @details This API is used to update alarm time setting to RTC. + */ +void RTC_SetAlarmTime(uint32_t u32Hour, uint32_t u32Minute, uint32_t u32Second, uint32_t u32TimeMode, uint32_t u32AmPm) +{ + uint32_t u32RegTALM; + + /* Important, range of 12-hour PM mode is 21 up to 32 */ + if((u32TimeMode == (uint32_t)RTC_CLOCK_12) && (u32AmPm == (uint32_t)RTC_PM)) + { + u32Hour += 20ul; + } + + u32RegTALM = ((u32Hour / 10ul) << 20); + u32RegTALM |= ((u32Hour % 10ul) << 16); + u32RegTALM |= ((u32Minute / 10ul) << 12); + u32RegTALM |= ((u32Minute % 10ul) << 8); + u32RegTALM |= ((u32Second / 10ul) << 4); + u32RegTALM |= (u32Second % 10ul); + + /*-----------------------------------------------------------------------------------------------------*/ + /* Set RTC 24/12 hour setting and Day of the Week */ + /*-----------------------------------------------------------------------------------------------------*/ + if(u32TimeMode == (uint32_t)RTC_CLOCK_12) + { + RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk; + } + else + { + RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk; + } + + /* Set RTC Alarm Time */ + RTC->TALM = (uint32_t)u32RegTALM; +} + +/** + * @brief Set RTC Alarm Date Mask Function + * + * @param[in] u8IsTenYMsk 1: enable 10-Year digit alarm mask; 0: disabled. + * @param[in] u8IsYMsk 1: enable 1-Year digit alarm mask; 0: disabled. + * @param[in] u8IsTenMMsk 1: enable 10-Mon digit alarm mask; 0: disabled. + * @param[in] u8IsMMsk 1: enable 1-Mon digit alarm mask; 0: disabled. + * @param[in] u8IsTenDMsk 1: enable 10-Day digit alarm mask; 0: disabled. + * @param[in] u8IsDMsk 1: enable 1-Day digit alarm mask; 0: disabled. + * + * @return None + * + * @details This API is used to enable or disable RTC alarm date mask function. + */ +void RTC_SetAlarmDateMask(uint8_t u8IsTenYMsk, uint8_t u8IsYMsk, uint8_t u8IsTenMMsk, uint8_t u8IsMMsk, uint8_t u8IsTenDMsk, uint8_t u8IsDMsk) +{ + RTC->CAMSK = ((uint32_t)u8IsTenYMsk << RTC_CAMSK_MTENYEAR_Pos) | + ((uint32_t)u8IsYMsk << RTC_CAMSK_MYEAR_Pos) | + ((uint32_t)u8IsTenMMsk << RTC_CAMSK_MTENMON_Pos) | + ((uint32_t)u8IsMMsk << RTC_CAMSK_MMON_Pos) | + ((uint32_t)u8IsTenDMsk << RTC_CAMSK_MTENDAY_Pos) | + ((uint32_t)u8IsDMsk << RTC_CAMSK_MDAY_Pos); +} + +/** + * @brief Set RTC Alarm Time Mask Function + * + * @param[in] u8IsTenHMsk 1: enable 10-Hour digit alarm mask; 0: disabled. + * @param[in] u8IsHMsk 1: enable 1-Hour digit alarm mask; 0: disabled. + * @param[in] u8IsTenMMsk 1: enable 10-Min digit alarm mask; 0: disabled. + * @param[in] u8IsMMsk 1: enable 1-Min digit alarm mask; 0: disabled. + * @param[in] u8IsTenSMsk 1: enable 10-Sec digit alarm mask; 0: disabled. + * @param[in] u8IsSMsk 1: enable 1-Sec digit alarm mask; 0: disabled. + * + * @return None + * + * @details This API is used to enable or disable RTC alarm time mask function. + */ +void RTC_SetAlarmTimeMask(uint8_t u8IsTenHMsk, uint8_t u8IsHMsk, uint8_t u8IsTenMMsk, uint8_t u8IsMMsk, uint8_t u8IsTenSMsk, uint8_t u8IsSMsk) +{ + RTC->TAMSK = ((uint32_t)u8IsTenHMsk << RTC_TAMSK_MTENHR_Pos) | + ((uint32_t)u8IsHMsk << RTC_TAMSK_MHR_Pos) | + ((uint32_t)u8IsTenMMsk << RTC_TAMSK_MTENMIN_Pos) | + ((uint32_t)u8IsMMsk << RTC_TAMSK_MMIN_Pos) | + ((uint32_t)u8IsTenSMsk << RTC_TAMSK_MTENSEC_Pos) | + ((uint32_t)u8IsSMsk << RTC_TAMSK_MSEC_Pos); +} + +/** + * @brief Get Day of the Week + * + * @param None + * + * @retval 0 Sunday + * @retval 1 Monday + * @retval 2 Tuesday + * @retval 3 Wednesday + * @retval 4 Thursday + * @retval 5 Friday + * @retval 6 Saturday + * + * @details This API is used to get day of the week of current RTC date. + */ +uint32_t RTC_GetDayOfWeek(void) +{ + return (RTC->WEEKDAY & RTC_WEEKDAY_WEEKDAY_Msk); +} + +/** + * @brief Set RTC Tick Period Time + * + * @param[in] u32TickSelection It is used to set the RTC tick period time for Periodic Time Tick request. \n + * It consists of: + * - \ref RTC_TICK_1_SEC : Time tick is 1 second + * - \ref RTC_TICK_1_2_SEC : Time tick is 1/2 second + * - \ref RTC_TICK_1_4_SEC : Time tick is 1/4 second + * - \ref RTC_TICK_1_8_SEC : Time tick is 1/8 second + * - \ref RTC_TICK_1_16_SEC : Time tick is 1/16 second + * - \ref RTC_TICK_1_32_SEC : Time tick is 1/32 second + * - \ref RTC_TICK_1_64_SEC : Time tick is 1/64 second + * - \ref RTC_TICK_1_128_SEC : Time tick is 1/128 second + * + * @return None + * + * @details This API is used to set RTC tick period time for each tick interrupt. + */ +void RTC_SetTickPeriod(uint32_t u32TickSelection) +{ + RTC->TICK = (RTC->TICK & ~RTC_TICK_TICK_Msk) | u32TickSelection; +} + +/** + * @brief Enable RTC Interrupt + * + * @param[in] u32IntFlagMask Specify the interrupt source. It consists of: + * - \ref RTC_INTEN_ALMIEN_Msk : Alarm interrupt + * - \ref RTC_INTEN_TICKIEN_Msk : Tick interrupt + * + * @return None + * + * @details This API is used to enable the specify RTC interrupt function. + */ +void RTC_EnableInt(uint32_t u32IntFlagMask) +{ + RTC->INTEN |= u32IntFlagMask; +} + +/** + * @brief Disable RTC Interrupt + * + * @param[in] u32IntFlagMask Specify the interrupt source. It consists of: + * - \ref RTC_INTEN_ALMIEN_Msk : Alarm interrupt + * - \ref RTC_INTEN_TICKIEN_Msk : Tick interrupt + * + * @return None + * + * @details This API is used to disable the specify RTC interrupt function. + */ +void RTC_DisableInt(uint32_t u32IntFlagMask) +{ + RTC->INTEN &= ~u32IntFlagMask; + RTC->INTSTS = u32IntFlagMask; +} + +/*@}*/ /* end of group RTC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group RTC_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_spi.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_spi.c new file mode 100644 index 0000000000..1109859222 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_spi.c @@ -0,0 +1,934 @@ +/**************************************************************************//** + * @file spi.c + * @version V1.00 + * $Revision: 4 $ + * $Date: 18/04/25 11:43a $ + * @brief M031 series SPI driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "M031Series.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup SPI_Driver SPI Driver + @{ +*/ + + +/** @addtogroup SPI_EXPORTED_FUNCTIONS SPI Exported Functions + @{ +*/ + +/** + * @brief This function make SPI module be ready to transfer. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32MasterSlave Decides the SPI module is operating in master mode or in slave mode. (SPI_SLAVE, SPI_MASTER) + * @param[in] u32SPIMode Decides the transfer timing. (SPI_MODE_0, SPI_MODE_1, SPI_MODE_2, SPI_MODE_3) + * @param[in] u32DataWidth Decides the data width of a SPI transaction. + * @param[in] u32BusClock The expected frequency of SPI bus clock in Hz. + * @return Actual frequency of SPI peripheral clock. + * @details By default, the SPI transfer sequence is MSB first, the slave selection signal is active low and the automatic + * slave selection function is disabled. + * In Slave mode, the u32BusClock shall be NULL and the SPI clock divider setting will be 0. + * The actual clock rate may be different from the target SPI clock rate. + * For example, if the SPI source clock rate is 12 MHz and the target SPI bus clock rate is 7 MHz, the + * actual SPI clock rate will be 6MHz. + * @note If u32BusClock = 0, DIVIDER setting will be set to the maximum value. + * @note If u32BusClock >= system clock frequency, SPI peripheral clock source will be set to APB clock and DIVIDER will be set to 0. + * @note If u32BusClock >= SPI peripheral clock source, DIVIDER will be set to 0. + * @note In slave mode, the SPI peripheral clock rate will be equal to APB clock rate. + */ +uint32_t SPI_Open(SPI_T *spi, + uint32_t u32MasterSlave, + uint32_t u32SPIMode, + uint32_t u32DataWidth, + uint32_t u32BusClock) +{ + uint32_t u32ClkSrc = 0, u32Div, u32HCLKFreq; + + /* check SPI interface */ + if (spi != SPI0) return SPI_NONE; + + /* Disable I2S mode */ + spi->I2SCTL &= ~SPI_I2SCTL_I2SEN_Msk; + + if (u32DataWidth == 32) + u32DataWidth = 0; + + /* Get system clock frequency */ + u32HCLKFreq = CLK_GetHCLKFreq(); + + if (u32MasterSlave == SPI_MASTER) + { + /* Default setting: slave selection signal is active low; disable automatic slave selection function. */ + spi->SSCTL = SPI_SS_ACTIVE_LOW; + + /* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */ + spi->CTL = u32MasterSlave | (u32DataWidth << SPI_CTL_DWIDTH_Pos) | (u32SPIMode) | SPI_CTL_SPIEN_Msk; + + if (u32BusClock >= u32HCLKFreq) + { + /* Select PCLK as the clock source of SPI */ + if (spi == SPI0) + CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI0SEL_Msk)) | CLK_CLKSEL2_SPI0SEL_PCLK1; + } + + /* Check clock source of SPI */ + if (spi == SPI0) + { + if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_HXT) + u32ClkSrc = __HXT; /* Clock source is HXT */ + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PLL) + u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PCLK1) + u32ClkSrc = u32HCLKFreq / ((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) + 1); + else + u32ClkSrc = 48000000; /* Clock source is HIRC48 */ + } + + if (u32BusClock >= u32HCLKFreq) + { + /* Set DIVIDER = 0 */ + spi->CLKDIV = 0; + /* Return master peripheral clock rate */ + return u32ClkSrc; + } + else if (u32BusClock >= u32ClkSrc) + { + /* Set DIVIDER = 0 */ + spi->CLKDIV = 0; + /* Return master peripheral clock rate */ + return u32ClkSrc; + } + else if (u32BusClock == 0) + { + /* Set DIVIDER to the maximum value 0xFF. f_spi = f_spi_clk_src / (DIVIDER + 1) */ + spi->CLKDIV |= SPI_CLKDIV_DIVIDER_Msk; + /* Return master peripheral clock rate */ + return (u32ClkSrc / (0xFF + 1)); + } + else + { + u32Div = (((u32ClkSrc * 10) / u32BusClock + 5) / 10) - 1; /* Round to the nearest integer */ + if (u32Div > 0xFF) + { + u32Div = 0xFF; + spi->CLKDIV |= SPI_CLKDIV_DIVIDER_Msk; + /* Return master peripheral clock rate */ + return (u32ClkSrc / (0xFF + 1)); + } + else + { + spi->CLKDIV = (spi->CLKDIV & (~SPI_CLKDIV_DIVIDER_Msk)) | (u32Div << SPI_CLKDIV_DIVIDER_Pos); + /* Return master peripheral clock rate */ + return (u32ClkSrc / (u32Div + 1)); + } + } + } + else /* For slave mode, force the SPI peripheral clock rate to equal APB clock rate. */ + { + /* Default setting: slave selection signal is low level active. */ + spi->SSCTL = SPI_SS_ACTIVE_LOW; + + /* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */ + spi->CTL = u32MasterSlave | (u32DataWidth << SPI_CTL_DWIDTH_Pos) | (u32SPIMode) | SPI_CTL_SPIEN_Msk; + + /* Set DIVIDER = 0 */ + spi->CLKDIV = 0; + + /* Select PCLK as the clock source of SPI */ + CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI0SEL_Msk)) | CLK_CLKSEL2_SPI0SEL_PCLK1; + /* Return slave peripheral clock rate */ + return (CLK_GetHCLKFreq() / ((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) + 1)); + } +} + +/** + * @brief Disable SPI controller. + * @param[in] spi The pointer of the specified SPI module. + * @return None + * @details This function will reset SPI controller. + */ +void SPI_Close(SPI_T *spi) +{ + if (spi == SPI0) + { + /* Reset SPI */ + SYS->IPRST1 |= SYS_IPRST1_SPI0RST_Msk; + SYS->IPRST1 &= ~SYS_IPRST1_SPI0RST_Msk; + } +} + +/** + * @brief Clear RX FIFO buffer. + * @param[in] spi The pointer of the specified SPI module. + * @return None + * @details This function will clear SPI RX FIFO buffer. The RXEMPTY (SPI_STATUS[8]) will be set to 1. + */ +void SPI_ClearRxFIFO(SPI_T *spi) +{ + spi->FIFOCTL |= SPI_FIFOCTL_RXFBCLR_Msk; +} + +/** + * @brief Clear TX FIFO buffer. + * @param[in] spi The pointer of the specified SPI module. + * @return None + * @details This function will clear SPI TX FIFO buffer. The TXEMPTY (SPI_STATUS[16]) will be set to 1. + * @note The TX shift register will not be cleared. + */ +void SPI_ClearTxFIFO(SPI_T *spi) +{ + spi->FIFOCTL |= SPI_FIFOCTL_TXFBCLR_Msk; +} + +/** + * @brief Disable the automatic slave selection function. + * @param[in] spi The pointer of the specified SPI module. + * @return None + * @details This function will disable the automatic slave selection function and set slave selection signal to inactive state. + */ +void SPI_DisableAutoSS(SPI_T *spi) +{ + spi->SSCTL &= ~(SPI_SSCTL_AUTOSS_Msk | SPI_SSCTL_SS_Msk); +} + +/** + * @brief Enable the automatic slave selection function. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32SSPinMask Specifies slave selection pins. (SPI_SS) + * @param[in] u32ActiveLevel Specifies the active level of slave selection signal. (SPI_SS_ACTIVE_HIGH, SPI_SS_ACTIVE_LOW) + * @return None + * @details This function will enable the automatic slave selection function. Only available in Master mode. + * The slave selection pin and the active level will be set in this function. + */ +void SPI_EnableAutoSS(SPI_T *spi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel) +{ + spi->SSCTL = (spi->SSCTL & (~(SPI_SSCTL_AUTOSS_Msk | SPI_SSCTL_SSACTPOL_Msk | SPI_SSCTL_SS_Msk))) | (u32SSPinMask | u32ActiveLevel | SPI_SSCTL_AUTOSS_Msk); +} + +/** + * @brief Set the SPI bus clock. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32BusClock The expected frequency of SPI bus clock in Hz. + * @return Actual frequency of SPI bus clock. + * @details This function is only available in Master mode. The actual clock rate may be different from the target SPI bus clock rate. + * For example, if the SPI source clock rate is 12 MHz and the target SPI bus clock rate is 7 MHz, the actual SPI bus clock + * rate will be 6 MHz. + * @note If u32BusClock = 0, DIVIDER setting will be set to the maximum value. + * @note If u32BusClock >= system clock frequency, SPI peripheral clock source will be set to APB clock and DIVIDER will be set to 0. + * @note If u32BusClock >= SPI peripheral clock source, DIVIDER will be set to 0. + */ +uint32_t SPI_SetBusClock(SPI_T *spi, uint32_t u32BusClock) +{ + uint32_t u32ClkSrc, u32HCLKFreq; + uint32_t u32Div; + + /* check SPI interface */ + if (spi != SPI0) return SPI_NONE; + + /* Get system clock frequency */ + u32HCLKFreq = CLK_GetHCLKFreq(); + + if (u32BusClock >= u32HCLKFreq) + { + /* Select PCLK as the clock source of SPI */ + if (spi == SPI0) + CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI0SEL_Msk)) | CLK_CLKSEL2_SPI0SEL_PCLK1; + } + + /* Check clock source of SPI */ + if (spi == SPI0) + { + if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_HXT) + u32ClkSrc = __HXT; /* Clock source is HXT */ + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PLL) + u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PCLK1) + u32ClkSrc = CLK_GetHCLKFreq() / ((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) + 1); + else + u32ClkSrc = 48000000; /* Clock source is HIRC48 */ + } + + if (u32BusClock >= u32HCLKFreq) + { + /* Set DIVIDER = 0 */ + spi->CLKDIV = 0; + /* Return master peripheral clock rate */ + return u32ClkSrc; + } + else if (u32BusClock >= u32ClkSrc) + { + /* Set DIVIDER = 0 */ + spi->CLKDIV = 0; + /* Return master peripheral clock rate */ + return u32ClkSrc; + } + else if (u32BusClock == 0) + { + /* Set DIVIDER to the maximum value 0xFF. f_spi = f_spi_clk_src / (DIVIDER + 1) */ + spi->CLKDIV |= SPI_CLKDIV_DIVIDER_Msk; + /* Return master peripheral clock rate */ + return (u32ClkSrc / (0xFF + 1)); + } + else + { + u32Div = (((u32ClkSrc * 10) / u32BusClock + 5) / 10) - 1; /* Round to the nearest integer */ + if (u32Div > 0xFF) + { + u32Div = 0xFF; + spi->CLKDIV |= SPI_CLKDIV_DIVIDER_Msk; + /* Return master peripheral clock rate */ + return (u32ClkSrc / (0xFF + 1)); + } + else + { + spi->CLKDIV = (spi->CLKDIV & (~SPI_CLKDIV_DIVIDER_Msk)) | (u32Div << SPI_CLKDIV_DIVIDER_Pos); + /* Return master peripheral clock rate */ + return (u32ClkSrc / (u32Div + 1)); + } + } +} + +/** + * @brief Configure FIFO threshold setting. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32TxThreshold Decides the TX FIFO threshold. It could be 0 ~ 3. + * @param[in] u32RxThreshold Decides the RX FIFO threshold. It could be 0 ~ 3. + * @return None + * @details Set TX FIFO threshold and RX FIFO threshold configurations. + */ +void SPI_SetFIFO(SPI_T *spi, uint32_t u32TxThreshold, uint32_t u32RxThreshold) +{ + spi->FIFOCTL = (spi->FIFOCTL & ~(SPI_FIFOCTL_TXTH_Msk | SPI_FIFOCTL_RXTH_Msk)) | + (u32TxThreshold << SPI_FIFOCTL_TXTH_Pos) | + (u32RxThreshold << SPI_FIFOCTL_RXTH_Pos); +} + +/** + * @brief Get the actual frequency of SPI bus clock. Only available in Master mode. + * @param[in] spi The pointer of the specified SPI module. + * @return Actual SPI bus clock frequency in Hz. + * @details This function will calculate the actual SPI bus clock rate according to the SPInSEL and DIVIDER settings. Only available in Master mode. + */ +uint32_t SPI_GetBusClock(SPI_T *spi) +{ + uint32_t u32Div; + uint32_t u32ClkSrc = 0, u32HCLKFreq; + + /* check SPI interface */ + if (spi != SPI0) return SPI_NONE; + + /* Get DIVIDER setting */ + u32Div = (spi->CLKDIV & SPI_CLKDIV_DIVIDER_Msk) >> SPI_CLKDIV_DIVIDER_Pos; + + /* Get system clock frequency */ + u32HCLKFreq = CLK_GetHCLKFreq(); + + /* Check clock source of SPI */ + if (spi == SPI0) + { + if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_HXT) + u32ClkSrc = __HXT; /* Clock source is HXT */ + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PLL) + u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */ + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PCLK1) + u32ClkSrc = u32HCLKFreq / ((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) + 1); + else + u32ClkSrc = 48000000; /* Clock source is HIRC48 */ + } + + /* Return SPI bus clock rate */ + return (u32ClkSrc / (u32Div + 1)); +} + +/** + * @brief Enable interrupt function. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to a interrupt enable bit. + * This parameter decides which interrupts will be enabled. It is combination of: + * - \ref SPI_UNIT_INT_MASK + * - \ref SPI_SSACT_INT_MASK + * - \ref SPI_SSINACT_INT_MASK + * - \ref SPI_SLVUR_INT_MASK + * - \ref SPI_SLVBE_INT_MASK + * - \ref SPI_TXUF_INT_MASK + * - \ref SPI_FIFO_TXTH_INT_MASK + * - \ref SPI_FIFO_RXTH_INT_MASK + * - \ref SPI_FIFO_RXOV_INT_MASK + * - \ref SPI_FIFO_RXTO_INT_MASK + * + * @return None + * @details Enable SPI related interrupts specified by u32Mask parameter. + */ +void SPI_EnableInt(SPI_T *spi, uint32_t u32Mask) +{ + /* Enable unit transfer interrupt flag */ + if ((u32Mask & SPI_UNIT_INT_MASK) == SPI_UNIT_INT_MASK) + spi->CTL |= SPI_CTL_UNITIEN_Msk; + + /* Enable slave selection signal active interrupt flag */ + if ((u32Mask & SPI_SSACT_INT_MASK) == SPI_SSACT_INT_MASK) + spi->SSCTL |= SPI_SSCTL_SSACTIEN_Msk; + + /* Enable slave selection signal inactive interrupt flag */ + if ((u32Mask & SPI_SSINACT_INT_MASK) == SPI_SSINACT_INT_MASK) + spi->SSCTL |= SPI_SSCTL_SSINAIEN_Msk; + + /* Enable slave TX under run interrupt flag */ + if ((u32Mask & SPI_SLVUR_INT_MASK) == SPI_SLVUR_INT_MASK) + spi->SSCTL |= SPI_SSCTL_SLVURIEN_Msk; + + /* Enable slave bit count error interrupt flag */ + if ((u32Mask & SPI_SLVBE_INT_MASK) == SPI_SLVBE_INT_MASK) + spi->SSCTL |= SPI_SSCTL_SLVBEIEN_Msk; + + /* Enable slave TX underflow interrupt flag */ + if ((u32Mask & SPI_TXUF_INT_MASK) == SPI_TXUF_INT_MASK) + spi->FIFOCTL |= SPI_FIFOCTL_TXUFIEN_Msk; + + /* Enable TX threshold interrupt flag */ + if ((u32Mask & SPI_FIFO_TXTH_INT_MASK) == SPI_FIFO_TXTH_INT_MASK) + spi->FIFOCTL |= SPI_FIFOCTL_TXTHIEN_Msk; + + /* Enable RX threshold interrupt flag */ + if ((u32Mask & SPI_FIFO_RXTH_INT_MASK) == SPI_FIFO_RXTH_INT_MASK) + spi->FIFOCTL |= SPI_FIFOCTL_RXTHIEN_Msk; + + /* Enable RX overrun interrupt flag */ + if ((u32Mask & SPI_FIFO_RXOV_INT_MASK) == SPI_FIFO_RXOV_INT_MASK) + spi->FIFOCTL |= SPI_FIFOCTL_RXOVIEN_Msk; + + /* Enable RX time-out interrupt flag */ + if ((u32Mask & SPI_FIFO_RXTO_INT_MASK) == SPI_FIFO_RXTO_INT_MASK) + spi->FIFOCTL |= SPI_FIFOCTL_RXTOIEN_Msk; +} + +/** + * @brief Disable interrupt function. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to a interrupt bit. + * This parameter decides which interrupts will be disabled. It is combination of: + * - \ref SPI_UNIT_INT_MASK + * - \ref SPI_SSACT_INT_MASK + * - \ref SPI_SSINACT_INT_MASK + * - \ref SPI_SLVUR_INT_MASK + * - \ref SPI_SLVBE_INT_MASK + * - \ref SPI_TXUF_INT_MASK + * - \ref SPI_FIFO_TXTH_INT_MASK + * - \ref SPI_FIFO_RXTH_INT_MASK + * - \ref SPI_FIFO_RXOV_INT_MASK + * - \ref SPI_FIFO_RXTO_INT_MASK + * + * @return None + * @details Disable SPI related interrupts specified by u32Mask parameter. + */ +void SPI_DisableInt(SPI_T *spi, uint32_t u32Mask) +{ + /* Disable unit transfer interrupt flag */ + if ((u32Mask & SPI_UNIT_INT_MASK) == SPI_UNIT_INT_MASK) + spi->CTL &= ~SPI_CTL_UNITIEN_Msk; + + /* Disable slave selection signal active interrupt flag */ + if ((u32Mask & SPI_SSACT_INT_MASK) == SPI_SSACT_INT_MASK) + spi->SSCTL &= ~SPI_SSCTL_SSACTIEN_Msk; + + /* Disable slave selection signal inactive interrupt flag */ + if ((u32Mask & SPI_SSINACT_INT_MASK) == SPI_SSINACT_INT_MASK) + spi->SSCTL &= ~SPI_SSCTL_SSINAIEN_Msk; + + /* Disable slave TX under run interrupt flag */ + if ((u32Mask & SPI_SLVUR_INT_MASK) == SPI_SLVUR_INT_MASK) + spi->SSCTL &= ~SPI_SSCTL_SLVURIEN_Msk; + + /* Disable slave bit count error interrupt flag */ + if ((u32Mask & SPI_SLVBE_INT_MASK) == SPI_SLVBE_INT_MASK) + spi->SSCTL &= ~SPI_SSCTL_SLVBEIEN_Msk; + + /* Disable slave TX underflow interrupt flag */ + if ((u32Mask & SPI_TXUF_INT_MASK) == SPI_TXUF_INT_MASK) + spi->FIFOCTL &= ~SPI_FIFOCTL_TXUFIEN_Msk; + + /* Disable TX threshold interrupt flag */ + if ((u32Mask & SPI_FIFO_TXTH_INT_MASK) == SPI_FIFO_TXTH_INT_MASK) + spi->FIFOCTL &= ~SPI_FIFOCTL_TXTHIEN_Msk; + + /* Disable RX threshold interrupt flag */ + if ((u32Mask & SPI_FIFO_RXTH_INT_MASK) == SPI_FIFO_RXTH_INT_MASK) + spi->FIFOCTL &= ~SPI_FIFOCTL_RXTHIEN_Msk; + + /* Disable RX overrun interrupt flag */ + if ((u32Mask & SPI_FIFO_RXOV_INT_MASK) == SPI_FIFO_RXOV_INT_MASK) + spi->FIFOCTL &= ~SPI_FIFOCTL_RXOVIEN_Msk; + + /* Disable RX time-out interrupt flag */ + if ((u32Mask & SPI_FIFO_RXTO_INT_MASK) == SPI_FIFO_RXTO_INT_MASK) + spi->FIFOCTL &= ~SPI_FIFOCTL_RXTOIEN_Msk; +} + +/** + * @brief Get interrupt flag. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32Mask The combination of all related interrupt sources. + * Each bit corresponds to a interrupt source. + * This parameter decides which interrupt flags will be read. It is combination of: + * - \ref SPI_UNIT_INT_MASK + * - \ref SPI_SSACT_INT_MASK + * - \ref SPI_SSINACT_INT_MASK + * - \ref SPI_SLVUR_INT_MASK + * - \ref SPI_SLVBE_INT_MASK + * - \ref SPI_TXUF_INT_MASK + * - \ref SPI_FIFO_TXTH_INT_MASK + * - \ref SPI_FIFO_RXTH_INT_MASK + * - \ref SPI_FIFO_RXOV_INT_MASK + * - \ref SPI_FIFO_RXTO_INT_MASK + * + * @return Interrupt flags of selected sources. + * @details Get SPI related interrupt flags specified by u32Mask parameter. + */ +uint32_t SPI_GetIntFlag(SPI_T *spi, uint32_t u32Mask) +{ + uint32_t u32IntFlag = 0; + + /* Check unit transfer interrupt flag */ + if ((u32Mask & SPI_UNIT_INT_MASK) && (spi->STATUS & SPI_STATUS_UNITIF_Msk)) + u32IntFlag |= SPI_UNIT_INT_MASK; + + /* Check slave selection signal active interrupt flag */ + if ((u32Mask & SPI_SSACT_INT_MASK) && (spi->STATUS & SPI_STATUS_SSACTIF_Msk)) + u32IntFlag |= SPI_SSACT_INT_MASK; + + /* Check slave selection signal inactive interrupt flag */ + if ((u32Mask & SPI_SSINACT_INT_MASK) && (spi->STATUS & SPI_STATUS_SSINAIF_Msk)) + u32IntFlag |= SPI_SSINACT_INT_MASK; + + /* Check slave TX under run interrupt flag */ + if ((u32Mask & SPI_SLVUR_INT_MASK) && (spi->STATUS & SPI_STATUS_SLVURIF_Msk)) + u32IntFlag |= SPI_SLVUR_INT_MASK; + + /* Check slave bit count error interrupt flag */ + if ((u32Mask & SPI_SLVBE_INT_MASK) && (spi->STATUS & SPI_STATUS_SLVBEIF_Msk)) + u32IntFlag |= SPI_SLVBE_INT_MASK; + + /* Check slave TX underflow interrupt flag */ + if ((u32Mask & SPI_TXUF_INT_MASK) && (spi->STATUS & SPI_STATUS_TXUFIF_Msk)) + u32IntFlag |= SPI_TXUF_INT_MASK; + + /* Check TX threshold interrupt flag */ + if ((u32Mask & SPI_FIFO_TXTH_INT_MASK) && (spi->STATUS & SPI_STATUS_TXTHIF_Msk)) + u32IntFlag |= SPI_FIFO_TXTH_INT_MASK; + + /* Check RX threshold interrupt flag */ + if ((u32Mask & SPI_FIFO_RXTH_INT_MASK) && (spi->STATUS & SPI_STATUS_RXTHIF_Msk)) + u32IntFlag |= SPI_FIFO_RXTH_INT_MASK; + + /* Check RX overrun interrupt flag */ + if ((u32Mask & SPI_FIFO_RXOV_INT_MASK) && (spi->STATUS & SPI_STATUS_RXOVIF_Msk)) + u32IntFlag |= SPI_FIFO_RXOV_INT_MASK; + + /* Check RX time-out interrupt flag */ + if ((u32Mask & SPI_FIFO_RXTO_INT_MASK) && (spi->STATUS & SPI_STATUS_RXTOIF_Msk)) + u32IntFlag |= SPI_FIFO_RXTO_INT_MASK; + + return u32IntFlag; +} + +/** + * @brief Clear interrupt flag. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32Mask The combination of all related interrupt sources. + * Each bit corresponds to a interrupt source. + * This parameter decides which interrupt flags will be cleared. It could be the combination of: + * - \ref SPI_UNIT_INT_MASK + * - \ref SPI_SSACT_INT_MASK + * - \ref SPI_SSINACT_INT_MASK + * - \ref SPI_SLVUR_INT_MASK + * - \ref SPI_SLVBE_INT_MASK + * - \ref SPI_TXUF_INT_MASK + * - \ref SPI_FIFO_RXOV_INT_MASK + * - \ref SPI_FIFO_RXTO_INT_MASK + * + * @return None + * @details Clear SPI related interrupt flags specified by u32Mask parameter. + */ +void SPI_ClearIntFlag(SPI_T *spi, uint32_t u32Mask) +{ + if (u32Mask & SPI_UNIT_INT_MASK) + spi->STATUS = SPI_STATUS_UNITIF_Msk; /* Clear unit transfer interrupt flag */ + + if (u32Mask & SPI_SSACT_INT_MASK) + spi->STATUS = SPI_STATUS_SSACTIF_Msk; /* Clear slave selection signal active interrupt flag */ + + if (u32Mask & SPI_SSINACT_INT_MASK) + spi->STATUS = SPI_STATUS_SSINAIF_Msk; /* Clear slave selection signal inactive interrupt flag */ + + if (u32Mask & SPI_SLVUR_INT_MASK) + spi->STATUS = SPI_STATUS_SLVURIF_Msk; /* Clear slave TX under run interrupt flag */ + + if (u32Mask & SPI_SLVBE_INT_MASK) + spi->STATUS = SPI_STATUS_SLVBEIF_Msk; /* Clear slave bit count error interrupt flag */ + + if (u32Mask & SPI_TXUF_INT_MASK) + spi->STATUS = SPI_STATUS_TXUFIF_Msk; /* Clear slave TX underflow interrupt flag */ + + if (u32Mask & SPI_FIFO_RXOV_INT_MASK) + spi->STATUS = SPI_STATUS_RXOVIF_Msk; /* Clear RX overrun interrupt flag */ + + if (u32Mask & SPI_FIFO_RXTO_INT_MASK) + spi->STATUS = SPI_STATUS_RXTOIF_Msk; /* Clear RX time-out interrupt flag */ +} + +/** + * @brief Get SPI status. + * @param[in] spi The pointer of the specified SPI module. + * @param[in] u32Mask The combination of all related sources. + * Each bit corresponds to a source. + * This parameter decides which flags will be read. It is combination of: + * - \ref SPI_BUSY_MASK + * - \ref SPI_RX_EMPTY_MASK + * - \ref SPI_RX_FULL_MASK + * - \ref SPI_TX_EMPTY_MASK + * - \ref SPI_TX_FULL_MASK + * - \ref SPI_TXRX_RESET_MASK + * - \ref SPI_SPIEN_STS_MASK + * - \ref SPI_SSLINE_STS_MASK + * + * @return Flags of selected sources. + * @details Get SPI related status specified by u32Mask parameter. + */ +uint32_t SPI_GetStatus(SPI_T *spi, uint32_t u32Mask) +{ + uint32_t u32Flag = 0; + + /* Check busy status */ + if ((u32Mask & SPI_BUSY_MASK) && (spi->STATUS & SPI_STATUS_BUSY_Msk)) + u32Flag |= SPI_BUSY_MASK; + + /* Check RX empty flag */ + if ((u32Mask & SPI_RX_EMPTY_MASK) && (spi->STATUS & SPI_STATUS_RXEMPTY_Msk)) + u32Flag |= SPI_RX_EMPTY_MASK; + + /* Check RX full flag */ + if ((u32Mask & SPI_RX_FULL_MASK) && (spi->STATUS & SPI_STATUS_RXFULL_Msk)) + u32Flag |= SPI_RX_FULL_MASK; + + /* Check TX empty flag */ + if ((u32Mask & SPI_TX_EMPTY_MASK) && (spi->STATUS & SPI_STATUS_TXEMPTY_Msk)) + u32Flag |= SPI_TX_EMPTY_MASK; + + /* Check TX full flag */ + if ((u32Mask & SPI_TX_FULL_MASK) && (spi->STATUS & SPI_STATUS_TXFULL_Msk)) + u32Flag |= SPI_TX_FULL_MASK; + + /* Check TX/RX reset flag */ + if ((u32Mask & SPI_TXRX_RESET_MASK) && (spi->STATUS & SPI_STATUS_TXRXRST_Msk)) + u32Flag |= SPI_TXRX_RESET_MASK; + + /* Check SPIEN flag */ + if ((u32Mask & SPI_SPIEN_STS_MASK) && (spi->STATUS & SPI_STATUS_SPIENSTS_Msk)) + u32Flag |= SPI_SPIEN_STS_MASK; + + /* Check SPIx_SS line status */ + if ((u32Mask & SPI_SSLINE_STS_MASK) && (spi->STATUS & SPI_STATUS_SSLINE_Msk)) + u32Flag |= SPI_SSLINE_STS_MASK; + + return u32Flag; +} + + +/** + * @brief This function is used to get SPII2S source clock frequency. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return SPII2S source clock frequency (Hz). + * @details Return the source clock frequency according to the setting of SPI0SEL (CLKSEL2[25:24]) + */ +static uint32_t SPII2S_GetSourceClockFreq(SPI_T *i2s) +{ + uint32_t u32Freq = 0, u32HCLKFreq; + + /* check SPI interface */ + if (i2s != SPI0) return SPI_NONE; + + if (i2s == SPI0) + { + if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_HXT) + u32Freq = __HXT; /* Clock source is HXT */ + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PLL) + u32Freq = CLK_GetPLLClockFreq(); /* Clock source is PLL */ + else if ((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PCLK1) + { + /* Get system clock frequency */ + u32HCLKFreq = CLK_GetHCLKFreq(); + /* Clock source is PCLK0 */ + u32Freq = u32HCLKFreq / ((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) + 1); + } + else + u32Freq = 48000000; /* Clock source is HIRC48 */ + } + + return u32Freq; +} + +/** + * @brief This function configures some parameters of SPII2S interface for general purpose use. + * @param[in] i2s The pointer of the specified SPII2S module. + * @param[in] u32MasterSlave SPII2S operation mode. Valid values are listed below. + * - \ref SPII2S_MODE_MASTER + * - \ref SPII2S_MODE_SLAVE + * @param[in] u32SampleRate Sample rate + * @param[in] u32WordWidth Data length. Valid values are listed below. + * - \ref SPII2S_DATABIT_8 + * - \ref SPII2S_DATABIT_16 + * - \ref SPII2S_DATABIT_24 + * - \ref SPII2S_DATABIT_32 + * @param[in] u32Channels Audio format. Valid values are listed below. + * - \ref SPII2S_MONO + * - \ref SPII2S_STEREO + * @param[in] u32DataFormat Data format. Valid values are listed below. + * - \ref SPII2S_FORMAT_I2S + * - \ref SPII2S_FORMAT_MSB + * - \ref SPII2S_FORMAT_PCMA + * - \ref SPII2S_FORMAT_PCMB + * @return Real sample rate of master mode or peripheral clock rate of slave mode. + * @details This function will reset SPI/I2S controller and configure SPII2S controller according to the input parameters. + * Set TX FIFO threshold to 2 and RX FIFO threshold to 1. Both the TX and RX functions will be enabled. + * The actual sample rate may be different from the target sample rate. The real sample rate will be returned for reference. + * @note In slave mode, the SPI peripheral clock rate will be equal to APB clock rate. + */ +uint32_t SPII2S_Open(SPI_T *i2s, uint32_t u32MasterSlave, uint32_t u32SampleRate, uint32_t u32WordWidth, uint32_t u32Channels, uint32_t u32DataFormat) +{ + uint32_t u32Divider; + uint32_t u32BitRate, u32SrcClk; + uint32_t u32HCLKFreq; + + /* check SPI interface */ + if (i2s != SPI0) return SPI_NONE; + + /* Reset SPI/I2S */ + if (i2s == SPI0) + { + SYS->IPRST1 |= SYS_IPRST1_SPI0RST_Msk; + SYS->IPRST1 &= ~SYS_IPRST1_SPI0RST_Msk; + } + + /* Configure SPII2S controller */ + i2s->I2SCTL = u32MasterSlave | u32WordWidth | u32Channels | u32DataFormat; + /* Set TX FIFO threshold to 2 and RX FIFO threshold to 1 */ + i2s->FIFOCTL = SPII2S_FIFO_TX_LEVEL_WORD_2 | SPII2S_FIFO_RX_LEVEL_WORD_2; + + if (u32MasterSlave == SPI_MASTER) + { + /* Get the source clock rate */ + u32SrcClk = SPII2S_GetSourceClockFreq(i2s); + + /* Calculate the bit clock rate */ + u32BitRate = u32SampleRate * ((u32WordWidth >> SPI_I2SCTL_WDWIDTH_Pos) + 1) * 16; + u32Divider = ((u32SrcClk / u32BitRate) >> 1) - 1; + /* Set BCLKDIV setting */ + i2s->I2SCLK = (i2s->I2SCLK & ~SPI_I2SCLK_BCLKDIV_Msk) | (u32Divider << SPI_I2SCLK_BCLKDIV_Pos); + + /* Calculate bit clock rate */ + u32BitRate = u32SrcClk / ((u32Divider + 1) * 2); + /* Calculate real sample rate */ + u32SampleRate = u32BitRate / (((u32WordWidth >> SPI_I2SCTL_WDWIDTH_Pos) + 1) * 16); + + /* Enable TX function, RX function and SPII2S mode. */ + i2s->I2SCTL |= (SPI_I2SCTL_RXEN_Msk | SPI_I2SCTL_TXEN_Msk | SPI_I2SCTL_I2SEN_Msk); + + /* Return the real sample rate */ + return u32SampleRate; + } + else + { + /* Set BCLKDIV = 0 */ + i2s->I2SCLK &= ~SPI_I2SCLK_BCLKDIV_Msk; + /* Get system clock frequency */ + u32HCLKFreq = CLK_GetHCLKFreq(); + + /* Set the peripheral clock rate to equal APB clock rate */ + CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI0SEL_Msk)) | CLK_CLKSEL2_SPI0SEL_PCLK1; + /* Enable TX function, RX function and SPII2S mode. */ + i2s->I2SCTL |= (SPI_I2SCTL_RXEN_Msk | SPI_I2SCTL_TXEN_Msk | SPI_I2SCTL_I2SEN_Msk); + /* Return slave peripheral clock rate */ + return (u32HCLKFreq / ((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) + 1)); + } +} + +/** + * @brief Disable SPII2S function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details Disable SPII2S function. + */ +void SPII2S_Close(SPI_T *i2s) +{ + i2s->I2SCTL &= ~SPI_I2SCTL_I2SEN_Msk; +} + +/** + * @brief Enable interrupt function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to a interrupt source. Valid values are listed below. + * - \ref SPII2S_FIFO_TXTH_INT_MASK + * - \ref SPII2S_FIFO_RXTH_INT_MASK + * - \ref SPII2S_FIFO_RXOV_INT_MASK + * - \ref SPII2S_FIFO_RXTO_INT_MASK + * - \ref SPII2S_TXUF_INT_MASK + * - \ref SPII2S_RIGHT_ZC_INT_MASK + * - \ref SPII2S_LEFT_ZC_INT_MASK + * @return None + * @details This function enables the interrupt according to the u32Mask parameter. + */ +void SPII2S_EnableInt(SPI_T *i2s, uint32_t u32Mask) +{ + /* Enable TX threshold interrupt flag */ + if ((u32Mask & SPII2S_FIFO_TXTH_INT_MASK) == SPII2S_FIFO_TXTH_INT_MASK) + i2s->FIFOCTL |= SPI_FIFOCTL_TXTHIEN_Msk; + + /* Enable RX threshold interrupt flag */ + if ((u32Mask & SPII2S_FIFO_RXTH_INT_MASK) == SPII2S_FIFO_RXTH_INT_MASK) + i2s->FIFOCTL |= SPI_FIFOCTL_RXTHIEN_Msk; + + /* Enable RX overrun interrupt flag */ + if ((u32Mask & SPII2S_FIFO_RXOV_INT_MASK) == SPII2S_FIFO_RXOV_INT_MASK) + i2s->FIFOCTL |= SPI_FIFOCTL_RXOVIEN_Msk; + + /* Enable RX time-out interrupt flag */ + if ((u32Mask & SPII2S_FIFO_RXTO_INT_MASK) == SPII2S_FIFO_RXTO_INT_MASK) + i2s->FIFOCTL |= SPI_FIFOCTL_RXTOIEN_Msk; + + /* Enable TX underflow interrupt flag */ + if ((u32Mask & SPII2S_TXUF_INT_MASK) == SPII2S_TXUF_INT_MASK) + i2s->FIFOCTL |= SPI_FIFOCTL_TXUFIEN_Msk; + + /* Enable right channel zero cross interrupt flag */ + if ((u32Mask & SPII2S_RIGHT_ZC_INT_MASK) == SPII2S_RIGHT_ZC_INT_MASK) + i2s->I2SCTL |= SPI_I2SCTL_RZCIEN_Msk; + + /* Enable left channel zero cross interrupt flag */ + if ((u32Mask & SPII2S_LEFT_ZC_INT_MASK) == SPII2S_LEFT_ZC_INT_MASK) + i2s->I2SCTL |= SPI_I2SCTL_LZCIEN_Msk; +} + +/** + * @brief Disable interrupt function. + * @param[in] i2s The pointer of the specified SPII2S module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to a interrupt source. Valid values are listed below. + * - \ref SPII2S_FIFO_TXTH_INT_MASK + * - \ref SPII2S_FIFO_RXTH_INT_MASK + * - \ref SPII2S_FIFO_RXOV_INT_MASK + * - \ref SPII2S_FIFO_RXTO_INT_MASK + * - \ref SPII2S_TXUF_INT_MASK + * - \ref SPII2S_RIGHT_ZC_INT_MASK + * - \ref SPII2S_LEFT_ZC_INT_MASK + * @return None + * @details This function disables the interrupt according to the u32Mask parameter. + */ +void SPII2S_DisableInt(SPI_T *i2s, uint32_t u32Mask) +{ + /* Disable TX threshold interrupt flag */ + if ((u32Mask & SPII2S_FIFO_TXTH_INT_MASK) == SPII2S_FIFO_TXTH_INT_MASK) + i2s->FIFOCTL &= ~SPI_FIFOCTL_TXTHIEN_Msk; + + /* Disable RX threshold interrupt flag */ + if ((u32Mask & SPII2S_FIFO_RXTH_INT_MASK) == SPII2S_FIFO_RXTH_INT_MASK) + i2s->FIFOCTL &= ~SPI_FIFOCTL_RXTHIEN_Msk; + + /* Disable RX overrun interrupt flag */ + if ((u32Mask & SPII2S_FIFO_RXOV_INT_MASK) == SPII2S_FIFO_RXOV_INT_MASK) + i2s->FIFOCTL &= ~SPI_FIFOCTL_RXOVIEN_Msk; + + /* Disable RX time-out interrupt flag */ + if ((u32Mask & SPII2S_FIFO_RXTO_INT_MASK) == SPII2S_FIFO_RXTO_INT_MASK) + i2s->FIFOCTL &= ~SPI_FIFOCTL_RXTOIEN_Msk; + + /* Disable TX underflow interrupt flag */ + if ((u32Mask & SPII2S_TXUF_INT_MASK) == SPII2S_TXUF_INT_MASK) + i2s->FIFOCTL &= ~SPI_FIFOCTL_TXUFIEN_Msk; + + /* Disable right channel zero cross interrupt flag */ + if ((u32Mask & SPII2S_RIGHT_ZC_INT_MASK) == SPII2S_RIGHT_ZC_INT_MASK) + i2s->I2SCTL &= ~SPI_I2SCTL_RZCIEN_Msk; + + /* Disable left channel zero cross interrupt flag */ + if ((u32Mask & SPII2S_LEFT_ZC_INT_MASK) == SPII2S_LEFT_ZC_INT_MASK) + i2s->I2SCTL &= ~SPI_I2SCTL_LZCIEN_Msk; +} + +/** + * @brief Enable master clock (MCLK). + * @param[in] i2s The pointer of the specified SPII2S module. + * @param[in] u32BusClock The target MCLK clock rate. + * @return Actual MCLK clock rate + * @details Set the master clock rate according to u32BusClock parameter and enable master clock output. + * The actual master clock rate may be different from the target master clock rate. The real master clock rate will be returned for reference. + */ +uint32_t SPII2S_EnableMCLK(SPI_T *i2s, uint32_t u32BusClock) +{ + uint32_t u32Divider; + uint32_t u32SrcClk; + + u32SrcClk = SPII2S_GetSourceClockFreq(i2s); + if (u32BusClock == u32SrcClk) + u32Divider = 0; + else + { + u32Divider = (u32SrcClk / u32BusClock) >> 1; + /* MCLKDIV is a 7-bit width configuration. The maximum value is 0xFF. */ + if (u32Divider > 0xFF) + u32Divider = 0xFF; + } + + /* Write u32Divider to MCLKDIV (SPI_I2SCLK[5:0]) */ + i2s->I2SCLK = (i2s->I2SCLK & ~SPI_I2SCLK_MCLKDIV_Msk) | (u32Divider << SPI_I2SCLK_MCLKDIV_Pos); + + /* Enable MCLK output */ + i2s->I2SCTL |= SPI_I2SCTL_MCLKEN_Msk; + + if (u32Divider == 0) + return u32SrcClk; /* If MCLKDIV=0, master clock rate is equal to the source clock rate. */ + else + return ((u32SrcClk >> 1) / u32Divider); /* If MCLKDIV>0, master clock rate = source clock rate / (MCLKDIV * 2) */ +} + +/** + * @brief Disable master clock (MCLK). + * @param[in] i2s The pointer of the specified SPII2S module. + * @return None + * @details Clear MCLKEN bit of SPI_I2SCTL register to disable master clock output. + */ +void SPII2S_DisableMCLK(SPI_T *i2s) +{ + i2s->I2SCTL &= ~SPI_I2SCTL_MCLKEN_Msk; +} + +/** + * @brief Configure FIFO threshold setting. + * @param[in] i2s The pointer of the specified SPII2S module. + * @param[in] u32TxThreshold Decides the TX FIFO threshold. It could be 0 ~ 3. + * @param[in] u32RxThreshold Decides the RX FIFO threshold. It could be 0 ~ 3. + * @return None + * @details Set TX FIFO threshold and RX FIFO threshold configurations. + */ +void SPII2S_SetFIFO(SPI_T *i2s, uint32_t u32TxThreshold, uint32_t u32RxThreshold) +{ + i2s->FIFOCTL = (i2s->FIFOCTL & ~(SPI_FIFOCTL_TXTH_Msk | SPI_FIFOCTL_RXTH_Msk)) | + (u32TxThreshold << SPI_FIFOCTL_TXTH_Pos) | + (u32RxThreshold << SPI_FIFOCTL_RXTH_Pos); +} + +/*@}*/ /* end of group SPI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group SPI_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_sys.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_sys.c new file mode 100644 index 0000000000..ee0433c07b --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_sys.c @@ -0,0 +1,205 @@ +/**************************************************************************//** + * @file sys.c + * @version V3.00 + * $Revision: 3 $ + * $Date: 18/07/05 4:42p $ + * @brief M031 Series System Manager (SYS) Driver Source File + * + * @note + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + *****************************************************************************/ +#include "M031Series.h" +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup SYS_Driver SYS Driver + @{ +*/ + + +/** @addtogroup SYS_EXPORTED_FUNCTIONS SYS Exported Functions + @{ +*/ + +/** + * @brief Clear reset source + * @param[in] u32Src is reset source. Including : + * - \ref SYS_RSTSTS_CPULKRF_Msk + * - \ref SYS_RSTSTS_CPURF_Msk + * - \ref SYS_RSTSTS_SYSRF_Msk + * - \ref SYS_RSTSTS_BODRF_Msk + * - \ref SYS_RSTSTS_LVRF_Msk + * - \ref SYS_RSTSTS_WDTRF_Msk + * - \ref SYS_RSTSTS_PINRF_Msk + * - \ref SYS_RSTSTS_PORF_Msk + * @return None + * @details This function clear the selected reset source. + */ +void SYS_ClearResetSrc(uint32_t u32Src) +{ + SYS->RSTSTS = u32Src; +} + +/** + * @brief Get Brown-out detector output status + * @param None + * @retval 0 System voltage is higher than BODVL setting or BODEN is 0. + * @retval 1 System voltage is lower than BODVL setting. + * @details This function get Brown-out detector output status. + */ +uint32_t SYS_GetBODStatus(void) +{ + return ((SYS->BODCTL & SYS_BODCTL_BODOUT_Msk) >> SYS_BODCTL_BODOUT_Pos); +} + +/** + * @brief Get reset status register value + * @param None + * @return Reset source + * @details This function get the system reset status register value. + */ +uint32_t SYS_GetResetSrc(void) +{ + return (SYS->RSTSTS); +} + +/** + * @brief Check if register is locked or not + * @param None + * @retval 0 Write-protection function is disabled. + * 1 Write-protection function is enabled. + * @details This function check register write-protection bit setting. + */ +uint32_t SYS_IsRegLocked(void) +{ + return !(SYS->REGLCTL & 0x1); +} + +/** + * @brief Get product ID + * @param None + * @return Product ID + * @details This function get product ID. + */ +uint32_t SYS_ReadPDID(void) +{ + return SYS->PDID; +} + +/** + * @brief Reset chip with chip reset + * @param None + * @return None + * @details This function reset chip with chip reset. + * The register write-protection function should be disabled before using this function. + */ +void SYS_ResetChip(void) +{ + SYS->IPRST0 |= SYS_IPRST0_CHIPRST_Msk; +} + +/** + * @brief Reset chip with CPU reset + * @param None + * @return None + * @details This function reset CPU with CPU reset. + * The register write-protection function should be disabled before using this function. + */ +void SYS_ResetCPU(void) +{ + SYS->IPRST0 |= SYS_IPRST0_CPURST_Msk; +} + +/** + * @brief Reset selected module + * @param[in] u32ModuleIndex is module index. Including : + * - \ref PDMA_RST + * - \ref EBI_RST + * - \ref HDIV_RST + * - \ref CRC_RST + * - \ref GPIO_RST + * - \ref TMR0_RST + * - \ref TMR1_RST + * - \ref TMR2_RST + * - \ref TMR3_RST + * - \ref ACMP01_RST + * - \ref I2C0_RST + * - \ref I2C1_RST + * - \ref QSPI0_RST + * - \ref SPI0_RST + * - \ref UART0_RST + * - \ref UART1_RST + * - \ref UART2_RST + * - \ref UART3_RST + * - \ref UART4_RST + * - \ref UART5_RST + * - \ref UART6_RST + * - \ref UART7_RST + * - \ref USBD_RST + * - \ref ADC_RST + * - \ref USCI0_RST + * - \ref USCI1_RST + * - \ref PWM0_RST + * - \ref PWM1_RST + * - \ref BPWM0_RST + * - \ref BPWM1_RST + * @return None + * @details This function reset selected module. + */ +void SYS_ResetModule(uint32_t u32ModuleIndex) +{ + /* Generate reset signal to the corresponding module */ + *(volatile uint32_t *)((uint32_t)&SYS->IPRST0 + (u32ModuleIndex >> 24)) |= 1 << (u32ModuleIndex & 0x00ffffff); + + /* Release corresponding module from reset state */ + *(volatile uint32_t *)((uint32_t)&SYS->IPRST0 + (u32ModuleIndex >> 24)) &= ~(1 << (u32ModuleIndex & 0x00ffffff)); +} + + +/** + * @brief Enable and configure Brown-out detector function + * @param[in] i32Mode is reset or interrupt mode. Including : + * - \ref SYS_BODCTL_BOD_RST_EN + * - \ref SYS_BODCTL_BOD_INTERRUPT_EN + * @param[in] u32BODLevel is Brown-out voltage level. Including : + * - \ref SYS_BODCTL_BODVL_2_5V + * - \ref SYS_BODCTL_BODVL_2_0V + * @return None + * @details This function configure Brown-out detector reset or interrupt mode, enable Brown-out function and set Brown-out voltage level. + * The register write-protection function should be disabled before using this function. + */ +void SYS_EnableBOD(int32_t i32Mode, uint32_t u32BODLevel) +{ + /* Enable Brown-out Detector function */ + SYS->BODCTL |= SYS_BODCTL_BODEN_Msk; + + /* Enable Brown-out interrupt or reset function */ + SYS->BODCTL = (SYS->BODCTL & ~SYS_BODCTL_BODRSTEN_Msk) | i32Mode; + + /* Select Brown-out Detector threshold voltage */ + SYS->BODCTL = (SYS->BODCTL & ~SYS_BODCTL_BODVL_Msk) | u32BODLevel; +} + +/** + * @brief Disable Brown-out detector function + * @param None + * @return None + * @details This function disable Brown-out detector function. + * The register write-protection function should be disabled before using this function. + */ +void SYS_DisableBOD(void) +{ + SYS->BODCTL &= ~SYS_BODCTL_BODEN_Msk; +} + + + +/*@}*/ /* end of group SYS_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group SYS_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_timer.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_timer.c new file mode 100644 index 0000000000..eb118f8618 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_timer.c @@ -0,0 +1,333 @@ +/**************************************************************************//** + * @file timer.c + * @version V3.00 + * $Revision: 5 $ + * $Date: 18/07/13 5:00p $ + * @brief M031 Series Timer Controller (TIMER) Driver Source File + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#include "M031Series.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup TIMER_Driver TIMER Driver + @{ +*/ + +/** @addtogroup TIMER_EXPORTED_FUNCTIONS TIMER Exported Functions + @{ +*/ + +/** + * @brief Open Timer with Operate Mode and Frequency + * + * @param[in] timer The pointer of the specified Timer module. + * @param[in] u32Mode Operation mode. Possible options are + * - \ref TIMER_ONESHOT_MODE + * - \ref TIMER_PERIODIC_MODE + * - \ref TIMER_TOGGLE_MODE + * - \ref TIMER_CONTINUOUS_MODE + * @param[in] u32Freq Target working frequency + * + * @return Real timer working frequency + * + * @details This API is used to configure timer to operate in specified mode and frequency. + * If timer cannot work in target frequency, a closest frequency will be chose and returned. + * @note After calling this API, Timer is \b NOT running yet. But could start timer running be calling + * \ref TIMER_Start macro or program registers directly. + */ +uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq) +{ + uint32_t u32Clk = TIMER_GetModuleClock(timer); + uint32_t u32Cmpr = 0, u32Prescale = 0; + + /* Fastest possible timer working freq is (u32Clk / 2). While cmpr = 2, pre-scale = 0. */ + if(u32Freq >= (u32Clk >> 1)) + { + u32Cmpr = 2; + } + else + { + u32Cmpr = u32Clk / u32Freq; + u32Prescale = (u32Cmpr >> 24); /* for 24 bits CMPDAT */ + if (u32Prescale > 0) + u32Cmpr = u32Cmpr / (u32Prescale + 1); + } + + timer->CTL = u32Mode | u32Prescale; + timer->CMP = u32Cmpr; + + return(u32Clk / (u32Cmpr * (u32Prescale + 1))); +} + +/** + * @brief Stop Timer Counting + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This API stops timer counting and disable all timer interrupt function. + */ +void TIMER_Close(TIMER_T *timer) +{ + timer->CTL = 0; + timer->EXTCTL = 0; +} + +/** + * @brief Create a specify Delay Time + * + * @param[in] timer The pointer of the specified Timer module. + * @param[in] u32Usec Delay period in micro seconds. Valid values are between 100~1000000 (100 micro second ~ 1 second). + * + * @return None + * + * @details This API is used to create a delay loop for u32Usec micro seconds by using timer one-shot mode. + * @note This API overwrites the register setting of the timer used to count the delay time. + * @note This API use polling mode. So there is no need to enable interrupt for the timer module used to generate delay. + */ +void TIMER_Delay(TIMER_T *timer, uint32_t u32Usec) +{ + uint32_t u32Clk = TIMER_GetModuleClock(timer); + uint32_t u32Prescale = 0, delay = (SystemCoreClock / u32Clk) + 1; + uint32_t u32Cmpr, u32NsecPerTick; + + /* Clear current timer configuration */ + timer->CTL = 0; + timer->EXTCTL = 0; + + if(u32Clk <= 1000000) /* min delay is 1000 us if timer clock source is <= 1 MHz */ + { + if(u32Usec < 1000) + u32Usec = 1000; + if(u32Usec > 1000000) + u32Usec = 1000000; + } + else + { + if(u32Usec < 100) + u32Usec = 100; + if(u32Usec > 1000000) + u32Usec = 1000000; + } + + if(u32Clk <= 1000000) + { + u32Prescale = 0; + u32NsecPerTick = 1000000000 / u32Clk; + u32Cmpr = (u32Usec * 1000) / u32NsecPerTick; + } + else + { + u32Cmpr = u32Usec * (u32Clk / 1000000); + u32Prescale = (u32Cmpr >> 24); /* for 24 bits CMPDAT */ + if (u32Prescale > 0) + u32Cmpr = u32Cmpr / (u32Prescale + 1); + } + + timer->CMP = u32Cmpr; + timer->CTL = TIMER_CTL_CNTEN_Msk | TIMER_ONESHOT_MODE | u32Prescale; + + /* When system clock is faster than timer clock, it is possible timer active bit cannot set in time while we check it. */ + /* And the while loop below return immediately, so put a tiny delay here allowing timer start counting and raise active flag. */ + for(; delay > 0; delay--) + { + __NOP(); + } + + while(timer->CTL & TIMER_CTL_ACTSTS_Msk); +} + +/** + * @brief Enable Timer Capture Function + * + * @param[in] timer The pointer of the specified Timer module. + * @param[in] u32CapMode Timer capture mode. Could be + * - \ref TIMER_CAPTURE_FREE_COUNTING_MODE + * - \ref TIMER_CAPTURE_COUNTER_RESET_MODE + * @param[in] u32Edge Timer capture event trigger edge. Possible values are + * - \ref TIMER_CAPTURE_FALLING_EDGE + * - \ref TIMER_CAPTURE_RISING_EDGE + * - \ref TIMER_CAPTURE_FALLING_AND_RISING_EDGE + * + * @return None + * + * @details This API is used to enable timer capture function with specify capture trigger edge \n + * to get current counter value or reset counter value to 0. + * @note Timer frequency should be configured separately by using \ref TIMER_Open API, or program registers directly. + */ +void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge) +{ + timer->EXTCTL = (timer->EXTCTL & ~(TIMER_EXTCTL_CAPFUNCS_Msk | TIMER_EXTCTL_CAPEDGE_Msk)) | + u32CapMode | u32Edge | TIMER_EXTCTL_CAPEN_Msk; +} + +/** + * @brief Disable Timer Capture Function + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This API is used to disable the timer capture function. + */ +void TIMER_DisableCapture(TIMER_T *timer) +{ + timer->EXTCTL &= ~TIMER_EXTCTL_CAPEN_Msk; +} + +/** + * @brief Enable Timer Counter Function + * + * @param[in] timer The pointer of the specified Timer module. + * @param[in] u32Edge Detection edge of counter pin. Could be ether + * - \ref TIMER_COUNTER_FALLING_EDGE, or + * - \ref TIMER_COUNTER_RISING_EDGE + * + * @return None + * + * @details This function is used to enable the timer counter function with specify detection edge. + * @note Timer compare value should be configured separately by using \ref TIMER_SET_CMP_VALUE macro or program registers directly. + * @note While using event counter function, \ref TIMER_TOGGLE_MODE cannot set as timer operation mode. + */ +void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge) +{ + timer->EXTCTL = (timer->EXTCTL & ~TIMER_EXTCTL_CNTPHASE_Msk) | u32Edge; + timer->CTL |= TIMER_CTL_EXTCNTEN_Msk; +} + +/** + * @brief Disable Timer Counter Function + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + * + * @details This API is used to disable the timer event counter function. + */ +void TIMER_DisableEventCounter(TIMER_T *timer) +{ + timer->CTL &= ~TIMER_CTL_EXTCNTEN_Msk; +} + +/** + * @brief Get Timer Clock Frequency + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return Timer clock frequency + * + * @details This API is used to get the timer clock frequency. + * @note This API cannot return correct clock rate if timer source is from external clock input. + */ +uint32_t TIMER_GetModuleClock(TIMER_T *timer) +{ + uint32_t u32Src; + const uint32_t au32Clk[] = {__HXT, __LXT, 0, 0, 0, __LIRC, 0, __HIRC}; + + if(timer == TIMER0) + u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR0SEL_Msk) >> CLK_CLKSEL1_TMR0SEL_Pos; + else if(timer == TIMER1) + u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1SEL_Msk) >> CLK_CLKSEL1_TMR1SEL_Pos; + else if(timer == TIMER2) + u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR2SEL_Msk) >> CLK_CLKSEL1_TMR2SEL_Pos; + else /* Timer 3 */ + u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR3SEL_Msk) >> CLK_CLKSEL1_TMR3SEL_Pos; + + if(u32Src == 2) + { + if ((timer == TIMER0) || (timer == TIMER1)) + return CLK_GetPCLK0Freq(); + else + return CLK_GetPCLK1Freq(); + } + + return (au32Clk[u32Src]); +} + +/** + * @brief Enable the Timer Frequency Counter Function + * + * @param[in] timer The pointer of the specified Timer module. + * @param[in] u32DropCount This parameter has no effect in M031 series BSP. + * @param[in] u32Timeout This parameter has no effect in M031 series BSP. + * @param[in] u32EnableInt Enable interrupt assertion after capture complete or not. Valid values are TRUE and FALSE. + * + * @return None + * + * @details This function is used to calculate input event frequency. After enable + * this function, a pair of timers, such as TIMER0 and TIMER1, + * will be configured for this function. The mode used to calculate input + * event frequency is mentioned as "Inter Timer Trigger Mode" in Technical + * Reference Manual + */ +void TIMER_EnableFreqCounter(TIMER_T *timer, uint32_t u32DropCount, uint32_t u32Timeout, uint32_t u32EnableInt) +{ + TIMER_T *t; /* store the timer base to configure compare value */ + + t = (timer == TIMER0) ? TIMER1 : TIMER3; + + t->CMP = 0xFFFFFF; + t->EXTCTL = u32EnableInt ? TIMER_EXTCTL_CAPIEN_Msk : 0; + timer->CTL = TIMER_CTL_INTRGEN_Msk | TIMER_CTL_CNTEN_Msk; + + return; +} + +/** + * @brief Disable the Timer Frequency Counter Function + * + * @param[in] timer The pointer of the specified Timer module. + * + * @return None + */ +void TIMER_DisableFreqCounter(TIMER_T *timer) +{ + timer->CTL &= ~TIMER_CTL_INTRGEN_Msk; +} + +/** + * @brief Select Other Modules Triggered Source + * + * @param[in] timer The pointer of the specified Timer module. + * @param[in] u32Src Selects the interrupt source to trigger other modules. Could be: + * - \ref TIMER_TRGSRC_TIMEOUT_EVENT + * - \ref TIMER_TRGSRC_CAPTURE_EVENT + * + * @return None + */ +void TIMER_SetTriggerSource(TIMER_T *timer, uint32_t u32Src) +{ + timer->CTL = (timer->CTL & ~TIMER_CTL_TRGSSEL_Msk) | u32Src; +} + +/** + * @brief Set Modules Trigger by Timer Interrupt Event + * + * @param[in] timer The pointer of the specified Timer module. + * @param[in] u32Mask The mask of modules (PWM, ADC, BPWM and PDMA) trigger by timer. Is the combination of + * - \ref TIMER_TRG_TO_PWM + * - \ref TIMER_TRG_TO_ADC + * - \ref TIMER_TRG_TO_PDMA + * - \ref TIMER_TRG_TO_BPWM + * + * @return None + */ +void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask) +{ + timer->CTL = (timer->CTL & ~(TIMER_CTL_TRGPWM_Msk | TIMER_CTL_TRGADC_Msk | TIMER_CTL_TRGPDMA_Msk | TIMER_CTL_TRGBPWM_Msk)) | (u32Mask); +} + +/*@}*/ /* end of group TIMER_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group TIMER_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_uart.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_uart.c new file mode 100644 index 0000000000..9e0336cab1 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_uart.c @@ -0,0 +1,722 @@ +/**************************************************************************** + * @file uart.c + * @version V1.00 + * @brief M031 series UART driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ + +#include +#include "NuMicro.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup UART_Driver UART Driver + @{ +*/ + +/** @addtogroup UART_EXPORTED_FUNCTIONS UART Exported Functions + @{ +*/ + +/** + * @brief Clear UART specified interrupt flag + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] u32InterruptFlag The specified interrupt of UART module. + * - \ref UART_INTSTS_SWBEINT_Msk : Single-wire Bit Error Detect Interrupt + * - \ref UART_INTEN_WKIEN_Msk : Wake-up interrupt + * - \ref UART_INTSTS_BUFERRINT_Msk : Buffer Error interrupt + * - \ref UART_INTSTS_MODEMINT_Msk : Modem Status interrupt + * - \ref UART_INTSTS_RLSINT_Msk : Receive Line Status interrupt + * + * @return None + * + * @details The function is used to clear UART specified interrupt flag. + */ + +void UART_ClearIntFlag(UART_T *uart, uint32_t u32InterruptFlag) +{ + + + if (u32InterruptFlag & UART_INTSTS_SWBEINT_Msk) /* Clear Bit Error Detection Interrupt */ + { + uart->INTSTS = UART_INTSTS_SWBEIF_Msk; + } + + if (u32InterruptFlag & UART_INTSTS_RLSINT_Msk) /* Clear Receive Line Status Interrupt */ + { + uart->FIFOSTS = UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_PEF_Msk; + uart->FIFOSTS = UART_FIFOSTS_ADDRDETF_Msk; + } + + if (u32InterruptFlag & UART_INTSTS_MODEMINT_Msk) /* Clear Modem Status Interrupt */ + { + uart->MODEMSTS |= UART_MODEMSTS_CTSDETF_Msk; + } + + if (u32InterruptFlag & UART_INTSTS_BUFERRINT_Msk) /* Clear Buffer Error Interrupt */ + { + uart->FIFOSTS = UART_FIFOSTS_RXOVIF_Msk | UART_FIFOSTS_TXOVIF_Msk; + } + + if (u32InterruptFlag & UART_INTSTS_WKINT_Msk) /* Clear Wake-up Interrupt */ + { + uart->WKSTS = UART_WKSTS_CTSWKF_Msk | UART_WKSTS_DATWKF_Msk | + UART_WKSTS_RFRTWKF_Msk | UART_WKSTS_RS485WKF_Msk | + UART_WKSTS_TOUTWKF_Msk; + } + +} + + +/** + * @brief Disable UART interrupt + * + * @param[in] uart The pointer of the specified UART module. + * + * @return None + * + * @details The function is used to disable UART interrupt. + */ +void UART_Close(UART_T *uart) +{ + uart->INTEN = 0ul; +} + + +/** + * @brief Disable UART auto flow control function + * + * @param[in] uart The pointer of the specified UART module. + * + * @return None + * + * @details The function is used to disable UART auto flow control. + */ +void UART_DisableFlowCtrl(UART_T *uart) +{ + uart->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk); +} + + +/** + * @brief Disable UART specified interrupt + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] u32InterruptFlag The specified interrupt of UART module. + * - \ref UART_INTSTS_SWBEINT_Msk : Single-wire Bit Error Detect Interrupt + * - \ref UART_INTEN_WKIEN_Msk : Wake-up interrupt + * - \ref UART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt + * - \ref UART_INTEN_RXTOIEN_Msk : Rx time-out interrupt + * - \ref UART_INTEN_MODEMIEN_Msk : Modem status interrupt + * - \ref UART_INTEN_RLSIEN_Msk : Receive Line status interrupt + * - \ref UART_INTEN_THREIEN_Msk : Tx empty interrupt + * - \ref UART_INTEN_RDAIEN_Msk : Rx ready interrupt * + * + * @return None + * + * @details The function is used to disable UART specified interrupt and disable NVIC UART IRQ. + */ +void UART_DisableInt(UART_T *uart, uint32_t u32InterruptFlag) +{ + /* Disable UART specified interrupt */ + UART_DISABLE_INT(uart, u32InterruptFlag); + +} + + +/** + * @brief Enable UART auto flow control function + * + * @param[in] uart The pointer of the specified UART module. + * + * @return None + * + * @details The function is used to Enable UART auto flow control. + */ +void UART_EnableFlowCtrl(UART_T *uart) +{ + /* Set RTS pin output is low level active */ + uart->MODEM |= UART_MODEM_RTSACTLV_Msk; + + /* Set CTS pin input is low level active */ + uart->MODEMSTS |= UART_MODEMSTS_CTSACTLV_Msk; + + /* Set RTS and CTS auto flow control enable */ + uart->INTEN |= UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk; +} + + +/** + * @brief The function is used to enable UART specified interrupt and enable NVIC UART IRQ. + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] u32InterruptFlag The specified interrupt of UART module: + * - \ref UART_INTSTS_SWBEINT_Msk : Single-wire Bit Error Detect Interrupt + * - \ref UART_INTEN_WKIEN_Msk : Wake-up interrupt + * - \ref UART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt + * - \ref UART_INTEN_RXTOIEN_Msk : Rx time-out interrupt + * - \ref UART_INTEN_MODEMIEN_Msk : Modem status interrupt + * - \ref UART_INTEN_RLSIEN_Msk : Receive Line status interrupt + * - \ref UART_INTEN_THREIEN_Msk : Tx empty interrupt + * - \ref UART_INTEN_RDAIEN_Msk : Rx ready interrupt * + * + * @return None + * + * @details The function is used to enable UART specified interrupt and enable NVIC UART IRQ. + */ +void UART_EnableInt(UART_T *uart, uint32_t u32InterruptFlag) +{ + /* Enable UART specified interrupt */ + UART_ENABLE_INT(uart, u32InterruptFlag); + +} + + +/** + * @brief Open and set UART function + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] u32baudrate The baudrate of UART module. + * + * @return None + * + * @details This function use to enable UART function and set baud-rate. + */ +void UART_Open(UART_T *uart, uint32_t u32baudrate) +{ + uint32_t u32UartClkSrcSel = 0ul, u32UartClkDivNum = 0ul; + uint32_t u32ClkTbl[6ul] = {__HXT, 0ul, __LXT, __HIRC, 0ul, __LIRC}; + uint32_t u32Baud_Div = 0ul; + + + if (uart == (UART_T *)UART0) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = ((uint32_t)(CLK->CLKSEL1 & CLK_CLKSEL1_UART0SEL_Msk)) >> CLK_CLKSEL1_UART0SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART0DIV_Msk) >> CLK_CLKDIV0_UART0DIV_Pos; + } + else if (uart == (UART_T *)UART1) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART1SEL_Msk) >> CLK_CLKSEL1_UART1SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART1DIV_Msk) >> CLK_CLKDIV0_UART1DIV_Pos; + } + else if (uart == (UART_T *)UART2) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART2SEL_Msk) >> CLK_CLKSEL3_UART2SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART2DIV_Msk) >> CLK_CLKDIV4_UART2DIV_Pos; + } + else if (uart == (UART_T *)UART3) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART3SEL_Msk) >> CLK_CLKSEL3_UART3SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART3DIV_Msk) >> CLK_CLKDIV4_UART3DIV_Pos; + } + else if (uart == (UART_T *)UART4) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART4SEL_Msk) >> CLK_CLKSEL3_UART4SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART4DIV_Msk) >> CLK_CLKDIV4_UART4DIV_Pos; + } + else if (uart == (UART_T *)UART5) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART5SEL_Msk) >> CLK_CLKSEL3_UART5SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART5DIV_Msk) >> CLK_CLKDIV4_UART5DIV_Pos; + } + else if (uart == (UART_T *)UART6) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART6SEL_Msk) >> CLK_CLKSEL3_UART6SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART6DIV_Msk) >> CLK_CLKDIV4_UART6DIV_Pos; + } + else if (uart == (UART_T *)UART7) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART7SEL_Msk) >> CLK_CLKSEL3_UART7SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART7DIV_Msk) >> CLK_CLKDIV4_UART7DIV_Pos; + } + + /* Select UART function */ + uart->FUNCSEL = UART_FUNCSEL_UART; + + /* Set UART line configuration */ + uart->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1; + + /* Set UART Rx and RTS trigger level */ + uart->FIFO &= ~(UART_FIFO_RFITL_Msk | UART_FIFO_RTSTRGLV_Msk); + + /* Get PLL clock frequency if UART clock source selection is PLL */ + if (u32UartClkSrcSel == 1ul) + { + u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq(); + } + + /* Get PCLK clock frequency if UART clock source selection is PCLK */ + if (u32UartClkSrcSel == 4ul) + { + /* UART Port as UART0 ,UART2, UART4 or UART6 */ + if ((uart == (UART_T *)UART0) || (uart == (UART_T *)UART2) || (uart == (UART_T *)UART4) || (uart == (UART_T *)UART6)) + { + u32ClkTbl[u32UartClkSrcSel] = CLK_GetPCLK0Freq(); + } + else /* UART Port as UART1, UART3, UART5 or UART7*/ + { + u32ClkTbl[u32UartClkSrcSel] = CLK_GetPCLK1Freq(); + } + + } + + /* Set UART baud rate */ + if (u32baudrate != 0ul) + { + u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate); + + if (u32Baud_Div > 0xFFFFul) + { + uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate)); + } + else + { + uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div); + } + } +} + + +/** + * @brief Read UART data + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] pu8RxBuf The buffer to receive the data of receive FIFO. + * @param[in] u32ReadBytes The the read bytes number of data. + * + * @return u32Count Receive byte count + * + * @details The function is used to read Rx data from RX FIFO and the data will be stored in pu8RxBuf. + */ +uint32_t UART_Read(UART_T *uart, uint8_t pu8RxBuf[], uint32_t u32ReadBytes) +{ + uint32_t u32Count, u32delayno; + uint32_t u32Exit = 0ul; + + for (u32Count = 0ul; u32Count < u32ReadBytes; u32Count++) + { + u32delayno = 0ul; + + while (uart->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) /* Check RX empty => failed */ + { + u32delayno++; + + if (u32delayno >= 0x40000000ul) + { + u32Exit = 1ul; + break; + } + } + + if (u32Exit == 1ul) + { + break; + } + else + { + pu8RxBuf[u32Count] = (uint8_t)uart->DAT; /* Get Data from UART RX */ + } + } + + return u32Count; + +} + + +/** + * @brief Set UART line configuration + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] u32baudrate The register value of baudrate of UART module. + * If u32baudrate = 0, UART baudrate will not change. + * @param[in] u32data_width The data length of UART module. + * - \ref UART_WORD_LEN_5 + * - \ref UART_WORD_LEN_6 + * - \ref UART_WORD_LEN_7 + * - \ref UART_WORD_LEN_8 + * @param[in] u32parity The parity setting (none/odd/even/mark/space) of UART module. + * - \ref UART_PARITY_NONE + * - \ref UART_PARITY_ODD + * - \ref UART_PARITY_EVEN + * - \ref UART_PARITY_MARK + * - \ref UART_PARITY_SPACE + * @param[in] u32stop_bits The stop bit length (1/1.5/2 bit) of UART module. + * - \ref UART_STOP_BIT_1 + * - \ref UART_STOP_BIT_1_5 + * - \ref UART_STOP_BIT_2 + * + * @return None + * + * @details This function use to config UART line setting. + */ +void UART_SetLine_Config(UART_T *uart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits) +{ + uint32_t u32UartClkSrcSel = 0ul, u32UartClkDivNum = 0ul; + uint32_t u32ClkTbl[6ul] = {__HXT, 0ul, __LXT, __HIRC, 0, __LIRC}; + uint32_t u32Baud_Div = 0ul; + + + if (uart == (UART_T *)UART0) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART0SEL_Msk) >> CLK_CLKSEL1_UART0SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART0DIV_Msk) >> CLK_CLKDIV0_UART0DIV_Pos; + } + else if (uart == (UART_T *)UART1) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART1SEL_Msk) >> CLK_CLKSEL1_UART1SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART1DIV_Msk) >> CLK_CLKDIV0_UART1DIV_Pos; + } + else if (uart == (UART_T *)UART2) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART2SEL_Msk) >> CLK_CLKSEL3_UART2SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART2DIV_Msk) >> CLK_CLKDIV4_UART2DIV_Pos; + } + else if (uart == (UART_T *)UART3) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART3SEL_Msk) >> CLK_CLKSEL3_UART3SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART3DIV_Msk) >> CLK_CLKDIV4_UART3DIV_Pos; + } + else if (uart == (UART_T *)UART4) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART4SEL_Msk) >> CLK_CLKSEL3_UART4SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART4DIV_Msk) >> CLK_CLKDIV4_UART4DIV_Pos; + } + else if (uart == (UART_T *)UART5) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART5SEL_Msk) >> CLK_CLKSEL3_UART5SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART5DIV_Msk) >> CLK_CLKDIV4_UART5DIV_Pos; + } + else if (uart == (UART_T *)UART6) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART6SEL_Msk) >> CLK_CLKSEL3_UART6SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART6DIV_Msk) >> CLK_CLKDIV4_UART6DIV_Pos; + } + else if (uart == (UART_T *)UART7) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART7SEL_Msk) >> CLK_CLKSEL3_UART7SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART7DIV_Msk) >> CLK_CLKDIV4_UART7DIV_Pos; + } + + /* Get PLL clock frequency if UART clock source selection is PLL */ + if (u32UartClkSrcSel == 1ul) + { + u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq(); + } + + /* Get PCLK clock frequency if UART clock source selection is PCLK */ + if (u32UartClkSrcSel == 4ul) + { + if ((uart == (UART_T *)UART0) || (uart == (UART_T *)UART2) || (uart == (UART_T *)UART4) || (uart == (UART_T *)UART6)) + { + u32ClkTbl[u32UartClkSrcSel] = CLK_GetPCLK0Freq(); + } + else /* UART Port as UART1, UART3, UART5, UART7*/ + { + u32ClkTbl[u32UartClkSrcSel] = CLK_GetPCLK1Freq(); + } + } + + + /* Set UART baud rate */ + if (u32baudrate != 0ul) + { + u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate); + + if (u32Baud_Div > 0xFFFFul) + { + uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate)); + } + else + { + uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div); + } + } + + /* Set UART line configuration */ + uart->LINE = u32data_width | u32parity | u32stop_bits; +} + + +/** + * @brief Set Rx timeout count + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] u32TOC Rx timeout counter. + * + * @return None + * + * @details This function use to set Rx timeout count. + */ +void UART_SetTimeoutCnt(UART_T *uart, uint32_t u32TOC) +{ + /* Set time-out interrupt comparator */ + uart->TOUT = (uart->TOUT & ~UART_TOUT_TOIC_Msk) | (u32TOC); + + /* Set time-out counter enable */ + uart->INTEN |= UART_INTEN_TOCNTEN_Msk; +} + + +/** + * @brief Select and configure IrDA function + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] u32Buadrate The baudrate of UART module. + * @param[in] u32Direction The direction of UART module in IrDA mode: + * - \ref UART_IRDA_TXEN + * - \ref UART_IRDA_RXEN + * + * @return None + * + * @details The function is used to configure IrDA relative settings. It consists of TX or RX mode and baudrate. + */ +void UART_SelectIrDAMode(UART_T *uart, uint32_t u32Buadrate, uint32_t u32Direction) +{ + uint32_t u32UartClkSrcSel = 0ul, u32UartClkDivNum = 0ul; + uint32_t u32ClkTbl[6ul] = {__HXT, 0ul, __LXT, __HIRC, 0ul, __LIRC}; + uint32_t u32Baud_Div; + + /* Select IrDA function mode */ + uart->FUNCSEL = UART_FUNCSEL_IrDA; + + + if (uart == UART0) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART0SEL_Msk) >> CLK_CLKSEL1_UART0SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART0DIV_Msk) >> CLK_CLKDIV0_UART0DIV_Pos; + } + else if (uart == UART1) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART1SEL_Msk) >> CLK_CLKSEL1_UART1SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART1DIV_Msk) >> CLK_CLKDIV0_UART1DIV_Pos; + } + else if (uart == UART2) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART2SEL_Msk) >> CLK_CLKSEL3_UART2SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART2DIV_Msk) >> CLK_CLKDIV4_UART2DIV_Pos; + } + else if (uart == UART3) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART3SEL_Msk) >> CLK_CLKSEL3_UART3SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART3DIV_Msk) >> CLK_CLKDIV4_UART3DIV_Pos; + } + else if (uart == UART4) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART4SEL_Msk) >> CLK_CLKSEL3_UART4SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART4DIV_Msk) >> CLK_CLKDIV4_UART4DIV_Pos; + } + else if (uart == UART5) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART5SEL_Msk) >> CLK_CLKSEL3_UART5SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART5DIV_Msk) >> CLK_CLKDIV4_UART5DIV_Pos; + } + else if (uart == UART6) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART6SEL_Msk) >> CLK_CLKSEL3_UART6SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART6DIV_Msk) >> CLK_CLKDIV4_UART6DIV_Pos; + } + else if (uart == UART7) + { + /* Get UART clock source selection */ + u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART7SEL_Msk) >> CLK_CLKSEL3_UART7SEL_Pos; + /* Get UART clock divider number */ + u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART7DIV_Msk) >> CLK_CLKDIV4_UART7DIV_Pos; + } + + /* Get PLL clock frequency if UART clock source selection is PLL */ + if (u32UartClkSrcSel == 1ul) + { + u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq(); + } + + /* Get PCLK clock frequency if UART clock source selection is PCLK */ + if (u32UartClkSrcSel == 4ul) + { + if ((uart == (UART_T *)UART0) || (uart == (UART_T *)UART2) || (uart == (UART_T *)UART4) || (uart == (UART_T *)UART6)) + { + u32ClkTbl[u32UartClkSrcSel] = CLK_GetPCLK0Freq(); + } + else /* UART Port as UART1, UART3, UART5, UART7*/ + { + u32ClkTbl[u32UartClkSrcSel] = CLK_GetPCLK1Freq(); + } + } + + + /* Set UART IrDA baud rate in mode 0 */ + if (u32Buadrate != 0ul) + { + u32Baud_Div = UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32Buadrate); + + if (u32Baud_Div < 0xFFFFul) + { + uart->BAUD = (UART_BAUD_MODE0 | u32Baud_Div); + } + else + { + } + } + + /* Configure IrDA relative settings */ + if (u32Direction == UART_IRDA_RXEN) + { + uart->IRDA |= UART_IRDA_RXINV_Msk; /*Rx signal is inverse*/ + uart->IRDA &= ~UART_IRDA_TXEN_Msk; + } + else + { + uart->IRDA &= ~UART_IRDA_TXINV_Msk; /*Tx signal is not inverse*/ + uart->IRDA |= UART_IRDA_TXEN_Msk; + } + +} + + +/** + * @brief Select and configure RS485 function + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] u32Mode The operation mode(NMM/AUD/AAD). + * - \ref UART_ALTCTL_RS485NMM_Msk + * - \ref UART_ALTCTL_RS485AUD_Msk + * - \ref UART_ALTCTL_RS485AAD_Msk + * @param[in] u32Addr The RS485 address. + * + * @return None + * + * @details The function is used to set RS485 relative setting. + */ +void UART_SelectRS485Mode(UART_T *uart, uint32_t u32Mode, uint32_t u32Addr) +{ + /* Select UART RS485 function mode */ + uart->FUNCSEL = UART_FUNCSEL_RS485; + + /* Set RS485 configuration */ + uart->ALTCTL &= ~(UART_ALTCTL_RS485NMM_Msk | UART_ALTCTL_RS485AUD_Msk | UART_ALTCTL_RS485AAD_Msk | UART_ALTCTL_ADDRMV_Msk); + uart->ALTCTL |= (u32Mode | (u32Addr << UART_ALTCTL_ADDRMV_Pos)); +} + + +/** + * @brief Write UART data + * + * @param[in] uart The pointer of the specified UART module. + * @param[in] pu8TxBuf The buffer to send the data to UART transmission FIFO. + * @param[out] u32WriteBytes The byte number of data. + * + * @return u32Count transfer byte count + * + * @details The function is to write data into TX buffer to transmit data by UART. + */ +uint32_t UART_Write(UART_T *uart, uint8_t pu8TxBuf[], uint32_t u32WriteBytes) +{ + uint32_t u32Count, u32delayno; + uint32_t u32Exit = 0ul; + + for (u32Count = 0ul; u32Count != u32WriteBytes; u32Count++) + { + u32delayno = 0ul; + + while (uart->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) /* Check Tx Full */ + { + u32delayno++; + + if (u32delayno >= 0x40000000ul) + { + u32Exit = 1ul; + break; + } + } + + if (u32Exit == 1ul) + { + break; + } + else + { + uart->DAT = pu8TxBuf[u32Count]; /* Send UART Data from buffer */ + } + } + + return u32Count; + +} +/** + * @brief Select Single Wire mode function + * + * @param[in] uart The pointer of the specified UART module. + * + * @return None + * + * @details The function is used to select Single Wire mode. + */ +void UART_SelectSingleWireMode(UART_T *uart) +{ + + /* Select UART SingleWire function mode */ + uart->FUNCSEL = ((uart->FUNCSEL & (~UART_FUNCSEL_FUNCSEL_Msk)) | UART_FUNCSEL_SINGLE_WIRE); + +} + + +/*@}*/ /* end of group UART_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group UART_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + + + diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usbd.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usbd.c new file mode 100644 index 0000000000..d4b52db39b --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usbd.c @@ -0,0 +1,705 @@ +/**************************************************************************//** + * @file usbd.c + * @version V1.00 + * $Revision: 5 $ + * $Date: 18/06/12 9:23a $ + * @brief M031 series USBD driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ + +#include +#include "NuMicro.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup USBD_Driver USBD Driver + @{ +*/ + + +/** @addtogroup USBD_EXPORTED_FUNCTIONS USBD Exported Functions + @{ +*/ + +/* Global variables for Control Pipe */ +uint8_t g_usbd_SetupPacket[8] = {0ul}; /*!< Setup packet buffer */ +volatile uint8_t g_usbd_RemoteWakeupEn = 0ul; /*!< Remote wake up function enable flag */ + +/** + * @cond HIDDEN_SYMBOLS + */ +static uint8_t *g_usbd_CtrlInPointer = 0; +static uint8_t *g_usbd_CtrlOutPointer = 0; +static volatile uint32_t g_usbd_CtrlInSize = 0ul; +static volatile uint32_t g_usbd_CtrlOutSize = 0ul; +static volatile uint32_t g_usbd_CtrlOutSizeLimit = 0ul; +static volatile uint32_t g_usbd_UsbAddr = 0ul; +static volatile uint32_t g_usbd_UsbConfig = 0ul; +static volatile uint32_t g_usbd_CtrlMaxPktSize = 8ul; +static volatile uint32_t g_usbd_UsbAltInterface = 0ul; +static volatile uint8_t g_usbd_CtrlInZeroFlag = 0ul; +/** + * @endcond + */ + +const S_USBD_INFO_T *g_usbd_sInfo; /*!< A pointer for USB information structure */ + +VENDOR_REQ g_usbd_pfnVendorRequest = NULL; /*!< USB Vendor Request Functional Pointer */ +CLASS_REQ g_usbd_pfnClassRequest = NULL; /*!< USB Class Request Functional Pointer */ +SET_INTERFACE_REQ g_usbd_pfnSetInterface = NULL; /*!< USB Set Interface Functional Pointer */ +SET_CONFIG_CB g_usbd_pfnSetConfigCallback = NULL; /*!< USB Set configuration callback function pointer */ +uint32_t g_u32EpStallLock = 0ul; /*!< Bit map flag to lock specified EP when SET_FEATURE */ + +/** + * @brief This function makes USBD module to be ready to use + * + * @param[in] param The structure of USBD information. + * @param[in] pfnClassReq USB Class request callback function. + * @param[in] pfnSetInterface USB Set Interface request callback function. + * + * @return None + * + * @details This function will enable USB controller, USB PHY transceiver and pull-up resistor of USB_D+ pin. USB PHY will drive SE0 to bus. + */ +void USBD_Open(const S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface) +{ + g_usbd_sInfo = param; + g_usbd_pfnClassRequest = pfnClassReq; + g_usbd_pfnSetInterface = pfnSetInterface; + + /* get EP0 maximum packet size */ + g_usbd_CtrlMaxPktSize = g_usbd_sInfo->gu8DevDesc[7]; + + /* Initial USB engine */ + USBD->ATTR = 0x6D0ul; + /* Force SE0 */ + USBD_SET_SE0(); +} + +/** + * @brief This function makes USB host to recognize the device + * + * @param None + * + * @return None + * + * @details Enable WAKEUP, FLDET, USB and BUS interrupts. Disable software-disconnect function after 100ms delay with SysTick timer. + */ +void USBD_Start(void) +{ + /* Disable software-disconnect function */ + USBD_CLR_SE0(); + USBD->ATTR = 0x7D0ul; + + /* Clear USB-related interrupts before enable interrupt */ + USBD_CLR_INT_FLAG(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP); + + /* Enable USB-related interrupts. */ + USBD_ENABLE_INT(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP); +} + +/** + * @brief Get the received SETUP packet + * + * @param[in] buf A buffer pointer used to store 8-byte SETUP packet. + * + * @return None + * + * @details Store SETUP packet to a user-specified buffer. + * + */ +void USBD_GetSetupPacket(uint8_t *buf) +{ + USBD_MemCopy(buf, g_usbd_SetupPacket, 8ul); +} + +/** + * @brief Process SETUP packet + * + * @param None + * + * @return None + * + * @details Parse SETUP packet and perform the corresponding action. + * + */ +void USBD_ProcessSetupPacket(void) +{ + /* Get SETUP packet from USB buffer */ + USBD_MemCopy(g_usbd_SetupPacket, (uint8_t *)USBD_BUF_BASE, 8ul); + + /* Check the request type */ + switch(g_usbd_SetupPacket[0] & 0x60ul) + { + case REQ_STANDARD: + { + USBD_StandardRequest(); + break; + } + case REQ_CLASS: + { + if(g_usbd_pfnClassRequest != NULL) + { + g_usbd_pfnClassRequest(); + } + break; + } + case REQ_VENDOR: + { + if(g_usbd_pfnVendorRequest != NULL) + { + g_usbd_pfnVendorRequest(); + } + break; + } + default: + { + /* Setup error, stall the device */ + USBD_SET_EP_STALL(EP0); + USBD_SET_EP_STALL(EP1); + break; + } + } +} + +/** + * @brief Process GetDescriptor request + * + * @param None + * + * @return None + * + * @details Parse GetDescriptor request and perform the corresponding action. + * + */ +void USBD_GetDescriptor(void) +{ + uint32_t u32Len; + + u32Len = 0ul; + u32Len = g_usbd_SetupPacket[7]; + u32Len <<= 8ul; + u32Len += g_usbd_SetupPacket[6]; + + switch(g_usbd_SetupPacket[3]) + { + /* Get Device Descriptor */ + case DESC_DEVICE: + { + u32Len = USBD_Minimum(u32Len, (uint32_t)LEN_DEVICE); + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len); + break; + } + /* Get Configuration Descriptor */ + case DESC_CONFIG: + { + uint32_t u32TotalLen; + u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3]; + u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8); + u32Len = USBD_Minimum(u32Len, u32TotalLen); + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len); + break; + } + + /* Get BOS Descriptor */ + case DESC_BOS: + { + if(g_usbd_sInfo->gu8BosDesc) + { + u32Len = USBD_Minimum(u32Len, LEN_BOS+LEN_BOSCAP); + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8BosDesc, u32Len); + } + else + { + /* Not support. Reply STALL. */ + USBD_SET_EP_STALL(EP0); + USBD_SET_EP_STALL(EP1); + } + + break; + } + /* Get HID Descriptor */ + case DESC_HID: + { + /* CV3.0 HID Class Descriptor Test, + Need to indicate index of the HID Descriptor within gu8ConfigDescriptor, specifically HID Composite device. */ + uint32_t u32ConfigDescOffset; /* u32ConfigDescOffset is configuration descriptor offset (HID descriptor start index) */ + u32Len = USBD_Minimum(u32Len, LEN_HID); + u32ConfigDescOffset = g_usbd_sInfo->gu32ConfigHidDescIdx[g_usbd_SetupPacket[4]]; + USBD_PrepareCtrlIn((uint8_t *)&g_usbd_sInfo->gu8ConfigDesc[u32ConfigDescOffset], u32Len); + break; + } + /* Get Report Descriptor */ + case DESC_HID_RPT: + { + u32Len = USBD_Minimum(u32Len, g_usbd_sInfo->gu32HidReportSize[g_usbd_SetupPacket[4]]); + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8HidReportDesc[g_usbd_SetupPacket[4]], u32Len); + break; + } + /* Get String Descriptor */ + case DESC_STRING: + { + /* Get String Descriptor */ + if(g_usbd_SetupPacket[2] < 4ul) + { + u32Len = USBD_Minimum(u32Len, g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0]); + USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]], u32Len); + break; + } + else + { + /* Not support. Reply STALL. */ + USBD_SET_EP_STALL(EP0); + USBD_SET_EP_STALL(EP1); + break; + } + } + default: + /* Not support. Reply STALL.*/ + USBD_SET_EP_STALL(EP0); + USBD_SET_EP_STALL(EP1); + break; + } +} + +/** + * @brief Process standard request + * + * @param None + * + * @return None + * + * @details Parse standard request and perform the corresponding action. + * + */ +void USBD_StandardRequest(void) +{ + uint32_t addr; + /* clear global variables for new request */ + g_usbd_CtrlInPointer = 0; + g_usbd_CtrlInSize = 0ul; + + if((g_usbd_SetupPacket[0] & 0x80ul) == 0x80ul) /* request data transfer direction */ + { + /* Device to host */ + switch(g_usbd_SetupPacket[1]) + { + case GET_CONFIGURATION: + { + /* Return current configuration setting */ + /* Data stage */ + addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); + M8(addr) = (uint8_t)g_usbd_UsbConfig; + USBD_SET_DATA1(EP0); + USBD_SET_PAYLOAD_LEN(EP0, 1ul); + /* Status stage */ + USBD_PrepareCtrlOut(0, 0ul); + break; + } + case GET_DESCRIPTOR: + { + USBD_GetDescriptor(); + USBD_PrepareCtrlOut(0, 0ul); /* For status stage */ + break; + } + case GET_INTERFACE: + { + /* Return current interface setting */ + /* Data stage */ + addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); + M8(addr) = (uint8_t)g_usbd_UsbAltInterface; + USBD_SET_DATA1(EP0); + USBD_SET_PAYLOAD_LEN(EP0, 1ul); + /* Status stage */ + USBD_PrepareCtrlOut(0, 0ul); + break; + } + case GET_STATUS: + { + /* Device */ + if(g_usbd_SetupPacket[0] == 0x80ul) + { + uint8_t u8Tmp; + + u8Tmp = (uint8_t)0ul; + if ((g_usbd_sInfo->gu8ConfigDesc[7] & 0x40ul) == 0x40ul) + { + u8Tmp |= (uint8_t)1ul; /* Self-Powered/Bus-Powered.*/ + } + if ((g_usbd_sInfo->gu8ConfigDesc[7] & 0x20ul) == 0x20ul) + { + u8Tmp |= (uint8_t)(g_usbd_RemoteWakeupEn << 1ul); /* Remote wake up */ + } + + addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); + M8(addr) = u8Tmp; + } + /* Interface */ + else if(g_usbd_SetupPacket[0] == 0x81ul) + { + addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); + M8(addr) = (uint8_t)0ul; + } + /* Endpoint */ + else if(g_usbd_SetupPacket[0] == 0x82ul) + { + uint8_t ep = (uint8_t)(g_usbd_SetupPacket[4] & 0xFul); + addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); + M8(addr) = (uint8_t)(USBD_GetStall(ep) ? 1ul : 0ul); + } + + addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0) + 1ul; + M8(addr) = (uint8_t)0ul; + /* Data stage */ + USBD_SET_DATA1(EP0); + USBD_SET_PAYLOAD_LEN(EP0, 2ul); + /* Status stage */ + USBD_PrepareCtrlOut(0, 0ul); + break; + } + default: + { + /* Setup error, stall the device */ + USBD_SET_EP_STALL(EP0); + USBD_SET_EP_STALL(EP1); + break; + } + } + } + else + { + /* Host to device */ + switch(g_usbd_SetupPacket[1]) + { + case CLEAR_FEATURE: + { + if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT) + { + uint32_t epNum, i; + /* EP number stall is not allow to be clear in MSC class "Error Recovery Test". + a flag: g_u32EpStallLock is added to support it */ + epNum = (uint8_t)(g_usbd_SetupPacket[4] & 0xFul); + for(i = 0ul; i < USBD_MAX_EP; i++) + { + if(((USBD->EP[i].CFG & 0xFul) == epNum) && ((g_u32EpStallLock & (1ul << i)) == 0ul)) + { + USBD->EP[i].CFGP &= ~USBD_CFGP_SSTALL_Msk; + } + } + } + else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP) + { + g_usbd_RemoteWakeupEn = (uint8_t)0; + } + /* Status stage */ + USBD_SET_DATA1(EP0); + USBD_SET_PAYLOAD_LEN(EP0, 0ul); + break; + } + case SET_ADDRESS: + { + g_usbd_UsbAddr = g_usbd_SetupPacket[2]; + /* Status Stage */ + USBD_SET_DATA1(EP0); + USBD_SET_PAYLOAD_LEN(EP0, 0ul); + + break; + } + case SET_CONFIGURATION: + { + g_usbd_UsbConfig = g_usbd_SetupPacket[2]; + + if(g_usbd_pfnSetConfigCallback) + { + g_usbd_pfnSetConfigCallback(); + } + + /* Status stage */ + USBD_SET_DATA1(EP0); + USBD_SET_PAYLOAD_LEN(EP0, 0ul); + break; + } + case SET_FEATURE: + { + if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT) + { + USBD_SetStall((uint8_t)(g_usbd_SetupPacket[4] & 0xFul)); + } + else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP) + { + g_usbd_RemoteWakeupEn = (uint8_t)1ul; + } + + /* Status stage */ + USBD_SET_DATA1(EP0); + USBD_SET_PAYLOAD_LEN(EP0, 0ul); + + break; + } + case SET_INTERFACE: + { + g_usbd_UsbAltInterface = g_usbd_SetupPacket[2]; + if(g_usbd_pfnSetInterface != NULL) + { + g_usbd_pfnSetInterface(g_usbd_UsbAltInterface); + } + /* Status stage */ + USBD_SET_DATA1(EP0); + USBD_SET_PAYLOAD_LEN(EP0, 0ul); + break; + } + default: + { + /* Setup error, stall the device */ + USBD_SET_EP_STALL(EP0); + USBD_SET_EP_STALL(EP1); + break; + } + } + } +} + +/** + * @brief Prepare the first Control IN pipe + * + * @param[in] pu8Buf The pointer of data sent to USB host. + * @param[in] u32Size The IN transfer size. + * + * @return None + * + * @details Prepare data for Control IN transfer. + * + */ +void USBD_PrepareCtrlIn(uint8_t pu8Buf[], uint32_t u32Size) +{ + uint32_t addr; + if(u32Size > g_usbd_CtrlMaxPktSize) + { + /* Data size > MXPLD */ + g_usbd_CtrlInPointer = pu8Buf + g_usbd_CtrlMaxPktSize; + g_usbd_CtrlInSize = u32Size - g_usbd_CtrlMaxPktSize; + USBD_SET_DATA1(EP0); + addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); + USBD_MemCopy((uint8_t *)addr, pu8Buf, g_usbd_CtrlMaxPktSize); + USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize); + } + else + { + /* Data size <= MXPLD */ + g_usbd_CtrlInPointer = 0; + g_usbd_CtrlInSize = 0ul; + if (u32Size == g_usbd_CtrlMaxPktSize) + g_usbd_CtrlInZeroFlag = 1ul; + USBD_SET_DATA1(EP0); + addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); + USBD_MemCopy((uint8_t *)addr, pu8Buf, u32Size); + USBD_SET_PAYLOAD_LEN(EP0, u32Size); + } +} + +/** + * @brief Repeat Control IN pipe + * + * @param None + * + * @return None + * + * @details This function processes the remained data of Control IN transfer. + * + */ +void USBD_CtrlIn(void) +{ + uint32_t addr; + + if(g_usbd_CtrlInSize) + { + /* Process remained data */ + if(g_usbd_CtrlInSize > g_usbd_CtrlMaxPktSize) + { + /* Data size > MXPLD */ + addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); + USBD_MemCopy((uint8_t *)addr, (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlMaxPktSize); + USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize); + g_usbd_CtrlInPointer += g_usbd_CtrlMaxPktSize; + g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize; + } + else + { + /* Data size <= MXPLD */ + addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0); + USBD_MemCopy((uint8_t *)addr, (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlInSize); + USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlInSize); + if(g_usbd_CtrlInSize == g_usbd_CtrlMaxPktSize) + g_usbd_CtrlInZeroFlag = 1ul; + g_usbd_CtrlInPointer = 0ul; + g_usbd_CtrlInSize = 0ul; + } + } + else + { + /* In ACK for Set address */ + if((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == SET_ADDRESS)) + { + addr = USBD_GET_ADDR(); + if((addr != g_usbd_UsbAddr) && (addr == 0ul)) + USBD_SET_ADDR(g_usbd_UsbAddr); + } + + /* For the case of data size is integral times maximum packet size */ + if (g_usbd_CtrlInZeroFlag) + { + USBD_SET_PAYLOAD_LEN(EP0, 0ul); + g_usbd_CtrlInZeroFlag = 0ul; + } + } +} + +/** + * @brief Prepare the first Control OUT pipe + * + * @param[in] pu8Buf The pointer of data received from USB host. + * @param[in] u32Size The OUT transfer size. + * + * @return None + * + * @details This function is used to prepare the first Control OUT transfer. + * + */ +void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size) +{ + g_usbd_CtrlOutPointer = pu8Buf; + g_usbd_CtrlOutSize = 0ul; + g_usbd_CtrlOutSizeLimit = u32Size; + USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize); +} + +/** + * @brief Repeat Control OUT pipe + * + * @param None + * + * @return None + * + * @details This function processes the successive Control OUT transfer. + * + */ +void USBD_CtrlOut(void) +{ + uint32_t u32Size; + uint32_t addr; + + if(g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit) + { + u32Size = USBD_GET_PAYLOAD_LEN(EP1); + addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1); + USBD_MemCopy((uint8_t *)g_usbd_CtrlOutPointer, (uint8_t *)addr, u32Size); + g_usbd_CtrlOutPointer += u32Size; + g_usbd_CtrlOutSize += u32Size; + + if(g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit) + { + USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize); + } + + } +} + +/** + * @brief Reset software flags + * + * @param None + * + * @return None + * + * @details This function resets all variables for protocol and resets USB device address to 0. + * + */ +void USBD_SwReset(void) +{ + uint32_t i; + + /* Reset all variables for protocol */ + g_usbd_CtrlInPointer = 0; + g_usbd_CtrlInSize = 0ul; + g_usbd_CtrlOutPointer = 0; + g_usbd_CtrlOutSize = 0ul; + g_usbd_CtrlOutSizeLimit = 0ul; + g_u32EpStallLock = 0ul; + memset(g_usbd_SetupPacket, 0, 8ul); + + /* Reset PID DATA0 */ + for(i=0ul; iEP[i].CFG &= ~USBD_CFG_DSQSYNC_Msk; + } + + /* Reset USB device address */ + USBD_SET_ADDR(0ul); +} + +/** + * @brief USBD Set Vendor Request + * + * @param[in] pfnVendorReq Vendor Request Callback Function + * + * @return None + * + * @details This function is used to set USBD vendor request callback function + */ +void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq) +{ + g_usbd_pfnVendorRequest = pfnVendorReq; +} + +/** + * @brief The callback function which called when get SET CONFIGURATION request + * + * @param[in] pfnSetConfigCallback Callback function pointer for SET CONFIGURATION request + * + * @return None + * + * @details This function is used to set the callback function which will be called at SET CONFIGURATION request. + */ +void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback) +{ + g_usbd_pfnSetConfigCallback = pfnSetConfigCallback; +} + + +/** + * @brief EP stall lock function to avoid stall clear by USB SET FEATURE request. + * + * @param[in] u32EpBitmap Use bitmap to select which endpoints will be locked + * + * @return None + * + * @details This function is used to lock relative endpoint to avoid stall clear by SET FEATURE request. + * If ep stall locked, user needs to reset USB device or re-configure device to clear it. + */ +void USBD_LockEpStall(uint32_t u32EpBitmap) +{ + g_u32EpStallLock = u32EpBitmap; +} + + +/*@}*/ /* end of group USBD_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group USBD_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +#ifdef __cplusplus +} +#endif + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_i2c.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_i2c.c new file mode 100644 index 0000000000..bdc89a9c1c --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_i2c.c @@ -0,0 +1,1689 @@ +/**************************************************************************//** + * @file usci_i2c.c + * @version V1.00 + * @brief M031 series USCI I2C(UI2C) driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "M031Series.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup USCI_I2C_Driver USCI_I2C Driver + @{ +*/ + + +/** @addtogroup USCI_I2C_EXPORTED_FUNCTIONS USCI_I2C Exported Functions + @{ +*/ + +/** + * @brief This function makes USCI_I2C module be ready and set the wanted bus clock + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u32BusClock The target bus speed of USCI_I2C module. + * + * @return Actual USCI_I2C bus clock frequency. + * + * @details Enable USCI_I2C module and configure USCI_I2C module(bus clock, data format). + */ +uint32_t UI2C_Open(UI2C_T *ui2c, uint32_t u32BusClock) +{ + uint32_t u32ClkDiv; + uint32_t u32Pclk; + + if (ui2c == UI2C0) + { + u32Pclk = CLK_GetPCLK0Freq(); + } + else + { + u32Pclk = CLK_GetPCLK1Freq(); + } + + u32ClkDiv = (uint32_t)((((((u32Pclk / 2U) * 10U) / (u32BusClock)) + 5U) / 10U) - 1U); /* Compute proper divider for USCI_I2C clock */ + + /* Enable USCI_I2C protocol */ + ui2c->CTL &= ~UI2C_CTL_FUNMODE_Msk; + ui2c->CTL = 4U << UI2C_CTL_FUNMODE_Pos; + + /* Data format configuration */ + /* 8 bit data length */ + ui2c->LINECTL &= ~UI2C_LINECTL_DWIDTH_Msk; + ui2c->LINECTL |= 8U << UI2C_LINECTL_DWIDTH_Pos; + + /* MSB data format */ + ui2c->LINECTL &= ~UI2C_LINECTL_LSB_Msk; + + /* Set USCI_I2C bus clock */ + ui2c->BRGEN &= ~UI2C_BRGEN_CLKDIV_Msk; + ui2c->BRGEN |= (u32ClkDiv << UI2C_BRGEN_CLKDIV_Pos); + ui2c->PROTCTL |= UI2C_PROTCTL_PROTEN_Msk; + + return (u32Pclk / ((u32ClkDiv + 1U) << 1U)); +} + +/** + * @brief This function closes the USCI_I2C module + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return None + * + * @details Close USCI_I2C protocol function. + */ +void UI2C_Close(UI2C_T *ui2c) +{ + /* Disable USCI_I2C function */ + ui2c->CTL &= ~UI2C_CTL_FUNMODE_Msk; +} + +/** + * @brief This function clears the time-out flag + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return None + * + * @details Clear time-out flag when time-out flag is set. + */ +void UI2C_ClearTimeoutFlag(UI2C_T *ui2c) +{ + ui2c->PROTSTS = UI2C_PROTSTS_TOIF_Msk; +} + +/** + * @brief This function sets the control bit of the USCI_I2C module. + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8Start Set START bit to USCI_I2C module. + * @param[in] u8Stop Set STOP bit to USCI_I2C module. + * @param[in] u8Ptrg Set PTRG bit to USCI_I2C module. + * @param[in] u8Ack Set ACK bit to USCI_I2C module. + * + * @return None + * + * @details The function set USCI_I2C control bit of USCI_I2C bus protocol. + */ +void UI2C_Trigger(UI2C_T *ui2c, uint8_t u8Start, uint8_t u8Stop, uint8_t u8Ptrg, uint8_t u8Ack) +{ + uint32_t u32Reg = 0U; + uint32_t u32Val = ui2c->PROTCTL & ~(UI2C_PROTCTL_STA_Msk | UI2C_PROTCTL_STO_Msk | UI2C_PROTCTL_AA_Msk); + + if (u8Start) + { + u32Reg |= UI2C_PROTCTL_STA_Msk; + } + + if (u8Stop) + { + u32Reg |= UI2C_PROTCTL_STO_Msk; + } + + if (u8Ptrg) + { + u32Reg |= UI2C_PROTCTL_PTRG_Msk; + } + + if (u8Ack) + { + u32Reg |= UI2C_PROTCTL_AA_Msk; + } + + ui2c->PROTCTL = u32Val | u32Reg; +} + +/** + * @brief This function disables the interrupt of USCI_I2C module + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to an interrupt enable bit. + * This parameter decides which interrupts will be disabled. It is combination of: + * - \ref UI2C_TO_INT_MASK + * - \ref UI2C_STAR_INT_MASK + * - \ref UI2C_STOR_INT_MASK + * - \ref UI2C_NACK_INT_MASK + * - \ref UI2C_ARBLO_INT_MASK + * - \ref UI2C_ERR_INT_MASK + * - \ref UI2C_ACK_INT_MASK + * + * @return None + * + * @details The function is used to disable USCI_I2C bus interrupt events. + */ +void UI2C_DisableInt(UI2C_T *ui2c, uint32_t u32Mask) +{ + /* Disable time-out interrupt flag */ + if ((u32Mask & UI2C_TO_INT_MASK) == UI2C_TO_INT_MASK) + { + ui2c->PROTIEN &= ~UI2C_PROTIEN_TOIEN_Msk; + } + + /* Disable start condition received interrupt flag */ + if ((u32Mask & UI2C_STAR_INT_MASK) == UI2C_STAR_INT_MASK) + { + ui2c->PROTIEN &= ~UI2C_PROTIEN_STARIEN_Msk; + } + + /* Disable stop condition received interrupt flag */ + if ((u32Mask & UI2C_STOR_INT_MASK) == UI2C_STOR_INT_MASK) + { + ui2c->PROTIEN &= ~UI2C_PROTIEN_STORIEN_Msk; + } + + /* Disable non-acknowledge interrupt flag */ + if ((u32Mask & UI2C_NACK_INT_MASK) == UI2C_NACK_INT_MASK) + { + ui2c->PROTIEN &= ~UI2C_PROTIEN_NACKIEN_Msk; + } + + /* Disable arbitration lost interrupt flag */ + if ((u32Mask & UI2C_ARBLO_INT_MASK) == UI2C_ARBLO_INT_MASK) + { + ui2c->PROTIEN &= ~UI2C_PROTIEN_ARBLOIEN_Msk; + } + + /* Disable error interrupt flag */ + if ((u32Mask & UI2C_ERR_INT_MASK) == UI2C_ERR_INT_MASK) + { + ui2c->PROTIEN &= ~UI2C_PROTIEN_ERRIEN_Msk; + } + + /* Disable acknowledge interrupt flag */ + if ((u32Mask & UI2C_ACK_INT_MASK) == UI2C_ACK_INT_MASK) + { + ui2c->PROTIEN &= ~UI2C_PROTIEN_ACKIEN_Msk; + } +} + +/** + * @brief This function enables the interrupt of USCI_I2C module. + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to a interrupt enable bit. + * This parameter decides which interrupts will be enabled. It is combination of: + * - \ref UI2C_TO_INT_MASK + * - \ref UI2C_STAR_INT_MASK + * - \ref UI2C_STOR_INT_MASK + * - \ref UI2C_NACK_INT_MASK + * - \ref UI2C_ARBLO_INT_MASK + * - \ref UI2C_ERR_INT_MASK + * - \ref UI2C_ACK_INT_MASK + * @return None + * + * @details The function is used to enable USCI_I2C bus interrupt events. + */ +void UI2C_EnableInt(UI2C_T *ui2c, uint32_t u32Mask) +{ + /* Enable time-out interrupt flag */ + if ((u32Mask & UI2C_TO_INT_MASK) == UI2C_TO_INT_MASK) + { + ui2c->PROTIEN |= UI2C_PROTIEN_TOIEN_Msk; + } + + /* Enable start condition received interrupt flag */ + if ((u32Mask & UI2C_STAR_INT_MASK) == UI2C_STAR_INT_MASK) + { + ui2c->PROTIEN |= UI2C_PROTIEN_STARIEN_Msk; + } + + /* Enable stop condition received interrupt flag */ + if ((u32Mask & UI2C_STOR_INT_MASK) == UI2C_STOR_INT_MASK) + { + ui2c->PROTIEN |= UI2C_PROTIEN_STORIEN_Msk; + } + + /* Enable non-acknowledge interrupt flag */ + if ((u32Mask & UI2C_NACK_INT_MASK) == UI2C_NACK_INT_MASK) + { + ui2c->PROTIEN |= UI2C_PROTIEN_NACKIEN_Msk; + } + + /* Enable arbitration lost interrupt flag */ + if ((u32Mask & UI2C_ARBLO_INT_MASK) == UI2C_ARBLO_INT_MASK) + { + ui2c->PROTIEN |= UI2C_PROTIEN_ARBLOIEN_Msk; + } + + /* Enable error interrupt flag */ + if ((u32Mask & UI2C_ERR_INT_MASK) == UI2C_ERR_INT_MASK) + { + ui2c->PROTIEN |= UI2C_PROTIEN_ERRIEN_Msk; + } + + /* Enable acknowledge interrupt flag */ + if ((u32Mask & UI2C_ACK_INT_MASK) == UI2C_ACK_INT_MASK) + { + ui2c->PROTIEN |= UI2C_PROTIEN_ACKIEN_Msk; + } +} + +/** + * @brief This function returns the real bus clock of USCI_I2C module + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return Actual USCI_I2C bus clock frequency. + * + * @details The function returns the actual USCI_I2C module bus clock. + */ +uint32_t UI2C_GetBusClockFreq(UI2C_T *ui2c) +{ + uint32_t u32Divider; + uint32_t u32Pclk; + + if (ui2c == UI2C0) + { + u32Pclk = CLK_GetPCLK0Freq(); + } + else + { + u32Pclk = CLK_GetPCLK1Freq(); + } + + u32Divider = (ui2c->BRGEN & UI2C_BRGEN_CLKDIV_Msk) >> UI2C_BRGEN_CLKDIV_Pos; + + return (u32Pclk / ((u32Divider + 1U) << 1U)); +} + +/** + * @brief This function sets bus clock frequency of USCI_I2C module + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u32BusClock The target bus speed of USCI_I2C module. + * + * @return Actual USCI_I2C bus clock frequency. + * + * @details Use this function set USCI_I2C bus clock frequency and return actual bus clock. + */ +uint32_t UI2C_SetBusClockFreq(UI2C_T *ui2c, uint32_t u32BusClock) +{ + uint32_t u32ClkDiv; + uint32_t u32Pclk; + + if (ui2c == UI2C0) + { + u32Pclk = CLK_GetPCLK0Freq(); + } + else + { + u32Pclk = CLK_GetPCLK1Freq(); + } + + u32ClkDiv = (uint32_t)((((((u32Pclk / 2U) * 10U) / (u32BusClock)) + 5U) / 10U) - 1U); /* Compute proper divider for USCI_I2C clock */ + + /* Set USCI_I2C bus clock */ + ui2c->BRGEN &= ~UI2C_BRGEN_CLKDIV_Msk; + ui2c->BRGEN |= (u32ClkDiv << UI2C_BRGEN_CLKDIV_Pos); + + return (u32Pclk / ((u32ClkDiv + 1U) << 1U)); +} + +/** + * @brief This function gets the interrupt flag of USCI_I2C module + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u32Mask The combination of all related interrupt sources. + * Each bit corresponds to a interrupt source. + * This parameter decides which interrupt flags will be read. It is combination of: + * - \ref UI2C_TO_INT_MASK + * - \ref UI2C_STAR_INT_MASK + * - \ref UI2C_STOR_INT_MASK + * - \ref UI2C_NACK_INT_MASK + * - \ref UI2C_ARBLO_INT_MASK + * - \ref UI2C_ERR_INT_MASK + * - \ref UI2C_ACK_INT_MASK + * + * @return Interrupt flags of selected sources. + * + * @details Use this function to get USCI_I2C interrupt flag when module occurs interrupt event. + */ +uint32_t UI2C_GetIntFlag(UI2C_T *ui2c, uint32_t u32Mask) +{ + uint32_t u32IntFlag = 0U; + uint32_t u32TmpValue; + + u32TmpValue = ui2c->PROTSTS & UI2C_PROTSTS_TOIF_Msk; + + /* Check Time-out Interrupt Flag */ + if ((u32Mask & UI2C_TO_INT_MASK) && (u32TmpValue)) + { + u32IntFlag |= UI2C_TO_INT_MASK; + } + + u32TmpValue = ui2c->PROTSTS & UI2C_PROTSTS_STARIF_Msk; + + /* Check Start Condition Received Interrupt Flag */ + if ((u32Mask & UI2C_STAR_INT_MASK) && (u32TmpValue)) + { + u32IntFlag |= UI2C_STAR_INT_MASK; + } + + u32TmpValue = ui2c->PROTSTS & UI2C_PROTSTS_STORIF_Msk; + + /* Check Stop Condition Received Interrupt Flag */ + if ((u32Mask & UI2C_STOR_INT_MASK) && (u32TmpValue)) + { + u32IntFlag |= UI2C_STOR_INT_MASK; + } + + u32TmpValue = ui2c->PROTSTS & UI2C_PROTSTS_NACKIF_Msk; + + /* Check Non-Acknowledge Interrupt Flag */ + if ((u32Mask & UI2C_NACK_INT_MASK) && (u32TmpValue)) + { + u32IntFlag |= UI2C_NACK_INT_MASK; + } + + u32TmpValue = ui2c->PROTSTS & UI2C_PROTSTS_ARBLOIF_Msk; + + /* Check Arbitration Lost Interrupt Flag */ + if ((u32Mask & UI2C_ARBLO_INT_MASK) && (u32TmpValue)) + { + u32IntFlag |= UI2C_ARBLO_INT_MASK; + } + + u32TmpValue = ui2c->PROTSTS & UI2C_PROTSTS_ERRIF_Msk; + + /* Check Error Interrupt Flag */ + if ((u32Mask & UI2C_ERR_INT_MASK) && (u32TmpValue)) + { + u32IntFlag |= UI2C_ERR_INT_MASK; + } + + u32TmpValue = ui2c->PROTSTS & UI2C_PROTSTS_ACKIF_Msk; + + /* Check Acknowledge Interrupt Flag */ + if ((u32Mask & UI2C_ACK_INT_MASK) && (u32TmpValue)) + { + u32IntFlag |= UI2C_ACK_INT_MASK; + } + + return u32IntFlag; +} + +/** + * @brief This function clears the interrupt flag of USCI_I2C module. + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u32Mask The combination of all related interrupt sources. + * Each bit corresponds to a interrupt source. + * This parameter decides which interrupt flags will be cleared. It is combination of: + * - \ref UI2C_TO_INT_MASK + * - \ref UI2C_STAR_INT_MASK + * - \ref UI2C_STOR_INT_MASK + * - \ref UI2C_NACK_INT_MASK + * - \ref UI2C_ARBLO_INT_MASK + * - \ref UI2C_ERR_INT_MASK + * - \ref UI2C_ACK_INT_MASK + * + * @return None + * + * @details Use this function to clear USCI_I2C interrupt flag when module occurs interrupt event and set flag. + */ +void UI2C_ClearIntFlag(UI2C_T *ui2c , uint32_t u32Mask) +{ + /* Clear Time-out Interrupt Flag */ + if (u32Mask & UI2C_TO_INT_MASK) + { + ui2c->PROTSTS = UI2C_PROTSTS_TOIF_Msk; + } + + /* Clear Start Condition Received Interrupt Flag */ + if (u32Mask & UI2C_STAR_INT_MASK) + { + ui2c->PROTSTS = UI2C_PROTSTS_STARIF_Msk; + } + + /* Clear Stop Condition Received Interrupt Flag */ + if (u32Mask & UI2C_STOR_INT_MASK) + { + ui2c->PROTSTS = UI2C_PROTSTS_STORIF_Msk; + } + + /* Clear Non-Acknowledge Interrupt Flag */ + if (u32Mask & UI2C_NACK_INT_MASK) + { + ui2c->PROTSTS = UI2C_PROTSTS_NACKIF_Msk; + } + + /* Clear Arbitration Lost Interrupt Flag */ + if (u32Mask & UI2C_ARBLO_INT_MASK) + { + ui2c->PROTSTS = UI2C_PROTSTS_ARBLOIF_Msk; + } + + /* Clear Error Interrupt Flag */ + if (u32Mask & UI2C_ERR_INT_MASK) + { + ui2c->PROTSTS = UI2C_PROTSTS_ERRIF_Msk; + } + + /* Clear Acknowledge Interrupt Flag */ + if (u32Mask & UI2C_ACK_INT_MASK) + { + ui2c->PROTSTS = UI2C_PROTSTS_ACKIF_Msk; + } +} + +/** + * @brief This function returns the data stored in data register of USCI_I2C module. + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return USCI_I2C data. + * + * @details To read a byte data from USCI_I2C module receive data register. + */ +uint32_t UI2C_GetData(UI2C_T *ui2c) +{ + return (ui2c->RXDAT); +} + +/** + * @brief This function writes a byte data to data register of USCI_I2C module + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8Data The data which will be written to data register of USCI_I2C module. + * + * @return None + * + * @details To write a byte data to transmit data register to transmit data. + */ +void UI2C_SetData(UI2C_T *ui2c, uint8_t u8Data) +{ + ui2c->TXDAT = u8Data; +} + +/** + * @brief Configure slave address and enable GC mode + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveNo Slave channel number [0/1] + * @param[in] u16SlaveAddr The slave address. + * @param[in] u8GCMode GC mode enable or not. Valid values are: + * - \ref UI2C_GCMODE_ENABLE + * - \ref UI2C_GCMODE_DISABLE + * + * @return None + * + * @details To configure USCI_I2C module slave address and GC mode. + */ +void UI2C_SetSlaveAddr(UI2C_T *ui2c, uint8_t u8SlaveNo, uint16_t u16SlaveAddr, uint8_t u8GCMode) +{ + if (u8SlaveNo) + { + ui2c->DEVADDR1 = u16SlaveAddr; + } + else + { + ui2c->DEVADDR0 = u16SlaveAddr; + } + + ui2c->PROTCTL = (ui2c->PROTCTL & ~UI2C_PROTCTL_GCFUNC_Msk) | u8GCMode; +} + +/** + * @brief Configure the mask bit of slave address. + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveNo Slave channel number [0/1] + * @param[in] u16SlaveAddrMask The slave address mask. + * + * @return None + * + * @details To configure USCI_I2C module slave address mask bit. + * @note The corresponding address bit is "Don't Care". + */ +void UI2C_SetSlaveAddrMask(UI2C_T *ui2c, uint8_t u8SlaveNo, uint16_t u16SlaveAddrMask) +{ + if (u8SlaveNo) + { + ui2c->ADDRMSK1 = u16SlaveAddrMask; + } + else + { + ui2c->ADDRMSK0 = u16SlaveAddrMask; + } +} + +/** + * @brief This function enables time-out function and configures timeout counter + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u32TimeoutCnt Timeout counter. Valid values are between 0~0x3FF + * + * @return None + * + * @details To enable USCI_I2C bus time-out function and set time-out counter. + */ +void UI2C_EnableTimeout(UI2C_T *ui2c, uint32_t u32TimeoutCnt) +{ + ui2c->PROTCTL = (ui2c->PROTCTL & ~UI2C_PROTCTL_TOCNT_Msk) | (u32TimeoutCnt << UI2C_PROTCTL_TOCNT_Pos); + ui2c->BRGEN = (ui2c->BRGEN & ~UI2C_BRGEN_TMCNTSRC_Msk) | UI2C_BRGEN_TMCNTEN_Msk; +} + +/** + * @brief This function disables time-out function + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return None + * + * @details To disable USCI_I2C bus time-out function. + */ +void UI2C_DisableTimeout(UI2C_T *ui2c) +{ + ui2c->PROTCTL &= ~UI2C_PROTCTL_TOCNT_Msk; + ui2c->BRGEN &= ~UI2C_BRGEN_TMCNTEN_Msk; +} + +/** + * @brief This function enables the wakeup function of USCI_I2C module + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8WakeupMode The wake-up mode selection. Valid values are: + * - \ref UI2C_DATA_TOGGLE_WK + * - \ref UI2C_ADDR_MATCH_WK + * + * @return None + * + * @details To enable USCI_I2C module wake-up function. + */ +void UI2C_EnableWakeup(UI2C_T *ui2c, uint8_t u8WakeupMode) +{ + ui2c->WKCTL = (ui2c->WKCTL & ~UI2C_WKCTL_WKADDREN_Msk) | (u8WakeupMode | UI2C_WKCTL_WKEN_Msk); +} + +/** + * @brief This function disables the wakeup function of USCI_I2C module + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * + * @return None + * + * @details To disable USCI_I2C module wake-up function. + */ +void UI2C_DisableWakeup(UI2C_T *ui2c) +{ + ui2c->WKCTL &= ~UI2C_WKCTL_WKEN_Msk; +} + +/** + * @brief Write a byte to Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] data Write a byte data to Slave + * + * @retval 0 Write data success + * @retval 1 Write data fail, or bus occurs error events + * + * @details The function is used for USCI_I2C Master write a byte data to Slave. + * + */ + +uint8_t UI2C_WriteByte(UI2C_T *ui2c, uint8_t u8SlaveAddr, const uint8_t data) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Ctrl = 0U; + enum UI2C_MASTER_EVENT eEvent = MASTER_SEND_START; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x00U); /* Write SLA+W to Register UI2C_TXDAT */ + eEvent = MASTER_SEND_ADDRESS; + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + + if (eEvent == MASTER_SEND_ADDRESS) + { + UI2C_SET_DATA(ui2c, data); /* Write data to UI2C_TXDAT */ + eEvent = MASTER_SEND_DATA; + } + else + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + } + + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + u8Err = 1U; + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_PROTCTL register */ + } + + return (u8Err | u8Xfering); /* return (Success)/(Fail) status */ +} + +/** + * @brief Write multi bytes to Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] *data Pointer to array to write data to Slave + * @param[in] u32wLen How many bytes need to write to Slave + * + * @return A length of how many bytes have been transmitted. + * + * @details The function is used for USCI_I2C Master write multi bytes data to Slave. + * + */ + +uint32_t UI2C_WriteMultiBytes(UI2C_T *ui2c, uint8_t u8SlaveAddr, const uint8_t *data, uint32_t u32wLen) +{ + uint8_t u8Xfering = 1U, u8Ctrl = 0U; + uint32_t u32txLen = 0U; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x00U); /* Write SLA+W to Register UI2C_TXDAT */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + + if (u32txLen < u32wLen) + UI2C_SET_DATA(ui2c, data[u32txLen++]); /* Write data to UI2C_TXDAT */ + else + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + } + + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_CTL register */ + } + + return u32txLen; /* Return bytes length that have been transmitted */ +} + +/** + * @brief Specify a byte register address and write a byte to Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u8DataAddr Specify a address (1 byte) of data write to + * @param[in] data A byte data to write it to Slave + * + * @retval 0 Write data success + * @retval 1 Write data fail, or bus occurs error events + * + * @details The function is used for USCI_I2C Master specify a address that data write to in Slave. + * + */ + +uint8_t UI2C_WriteByteOneReg(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, const uint8_t data) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Ctrl = 0U; + uint32_t u32txLen = 0U; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x00U); /* Write SLA+W to Register UI2C_TXDAT */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + + if (u32txLen == 0U) + { + UI2C_SET_DATA(ui2c, u8DataAddr); /* Write data address to UI2C_TXDAT */ + u32txLen++; + } + else if (u32txLen == 1U) + { + UI2C_SET_DATA(ui2c, data); /* Write data to UI2C_TXDAT */ + u32txLen++; + } + else + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + } + + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + u8Err = 1U; + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_CTL register */ + } + + return (u8Err | u8Xfering); /* return (Success)/(Fail) status */ +} + + +/** + * @brief Specify a byte register address and write multi bytes to Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u8DataAddr Specify a address (1 byte) of data write to + * @param[in] *data Pointer to array to write data to Slave + * @param[in] u32wLen How many bytes need to write to Slave + * + * @return A length of how many bytes have been transmitted. + * + * @details The function is used for USCI_I2C Master specify a byte address that multi data bytes write to in Slave. + * + */ + +uint32_t UI2C_WriteMultiBytesOneReg(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, const uint8_t *data, uint32_t u32wLen) +{ + uint8_t u8Xfering = 1U, u8Ctrl = 0U; + uint32_t u32txLen = 0U; + enum UI2C_MASTER_EVENT eEvent = MASTER_SEND_START; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x00U); /* Write SLA+W to Register UI2C_TXDAT */ + eEvent = MASTER_SEND_ADDRESS; + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + + if (eEvent == MASTER_SEND_ADDRESS) + { + UI2C_SET_DATA(ui2c, u8DataAddr); /* Write data address to UI2C_TXDAT */ + eEvent = MASTER_SEND_DATA; + } + else + { + if (u32txLen < u32wLen) + UI2C_SET_DATA(ui2c, data[u32txLen++]); /* Write data to UI2C_TXDAT */ + else + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + } + } + + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_CTL register */ + } + + return u32txLen; /* Return bytes length that have been transmitted */ +} + +/** + * @brief Specify two bytes register address and Write a byte to Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u16DataAddr Specify a address (2 byte) of data write to + * @param[in] data Write a byte data to Slave + * + * @retval 0 Write data success + * @retval 1 Write data fail, or bus occurs error events + * + * @details The function is used for USCI_I2C Master specify two bytes address that data write to in Slave. + * + */ + +uint8_t UI2C_WriteByteTwoRegs(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, const uint8_t data) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, u8Ctrl = 0U; + uint32_t u32txLen = 0U; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x00U); /* Write SLA+W to Register UI2C_TXDAT */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + + if (u32txLen == 0U) + { + UI2C_SET_DATA(ui2c, (uint8_t)((u16DataAddr & 0xFF00U) >> 8U)); /* Write Hi byte data address to UI2C_TXDAT */ + u32txLen++; + } + else if (u32txLen == 1U) + { + UI2C_SET_DATA(ui2c, (uint8_t)(u16DataAddr & 0xFFU)); /* Write Lo byte data address to UI2C_TXDAT */ + u32txLen++; + } + else if (u32txLen == 2U) + { + UI2C_SET_DATA(ui2c, data); /* Write data to UI2C_TXDAT */ + u32txLen++; + } + else + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + } + + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + u8Err = 1U; + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + u8Err = 1U; + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_CTL register */ + } + + return (u8Err | u8Xfering); +} + + +/** + * @brief Specify two bytes register address and write multi bytes to Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u16DataAddr Specify a address (2 bytes) of data write to + * @param[in] *data Pointer to array to write data to Slave + * @param[in] u32wLen How many bytes need to write to Slave + * + * @return A length of how many bytes have been transmitted. + * + * @details The function is used for USCI_I2C Master specify two bytes address that multi data write to in Slave. + * + */ + +uint32_t UI2C_WriteMultiBytesTwoRegs(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, const uint8_t *data, uint32_t u32wLen) +{ + uint8_t u8Xfering = 1U, u8Addr = 1U, u8Ctrl = 0U; + uint32_t u32txLen = 0U; + enum UI2C_MASTER_EVENT eEvent = MASTER_SEND_START; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x00U); /* Write SLA+W to Register UI2C_TXDAT */ + eEvent = MASTER_SEND_ADDRESS; + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + + if (eEvent == MASTER_SEND_ADDRESS) + { + UI2C_SET_DATA(ui2c, (uint8_t)((u16DataAddr & 0xFF00U) >> 8U)); /* Write Hi byte data address to UI2C_TXDAT */ + eEvent = MASTER_SEND_DATA; + } + else if (eEvent == MASTER_SEND_DATA) + { + if (u8Addr) + { + UI2C_SET_DATA(ui2c, (uint8_t)(u16DataAddr & 0xFFU)); /* Write Lo byte data address to UI2C_TXDAT */ + u8Addr = 0; + } + else + { + if (u32txLen < u32wLen) + { + UI2C_SET_DATA(ui2c, data[u32txLen++]); /* Write data to UI2C_TXDAT */ + } + else + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + } + } + } + + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_CTL register */ + } + + return u32txLen; /* Return bytes length that have been transmitted */ +} + +/** + * @brief Read a byte from Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * + * @return Read a byte data from Slave + * + * @details The function is used for USCI_I2C Master to read a byte data from Slave. + * + */ +uint8_t UI2C_ReadByte(UI2C_T *ui2c, uint8_t u8SlaveAddr) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, rdata = 0U, u8Ctrl = 0U; + enum UI2C_MASTER_EVENT eEvent = MASTER_SEND_START; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x01U); /* Write SLA+R to Register UI2C_TXDAT */ + eEvent = MASTER_SEND_H_RD_ADDRESS; + u8Ctrl = UI2C_CTL_PTRG; + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + eEvent = MASTER_READ_DATA; + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + + if (eEvent == MASTER_SEND_H_RD_ADDRESS) + { + u8Err = 1U; + } + else + { + rdata = (unsigned char) UI2C_GET_DATA(ui2c); /* Receive Data */ + } + + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + u8Err = 1U; + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_PROTCTL register */ + } + + if (u8Err) + rdata = 0U; + + return rdata; /* Return read data */ +} + + +/** + * @brief Read multi bytes from Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[out] *rdata Point to array to store data from Slave + * @param[in] u32rLen How many bytes need to read from Slave + * + * @return A length of how many bytes have been received + * + * @details The function is used for USCI_I2C Master to read multi data bytes from Slave. + * + * + */ +uint32_t UI2C_ReadMultiBytes(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint8_t *rdata, uint32_t u32rLen) +{ + uint8_t u8Xfering = 1U, u8Ctrl = 0U; + uint32_t u32rxLen = 0U; + enum UI2C_MASTER_EVENT eEvent = MASTER_SEND_START; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x01U); /* Write SLA+R to Register UI2C_TXDAT */ + eEvent = MASTER_SEND_H_RD_ADDRESS; + u8Ctrl = UI2C_CTL_PTRG; + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + + if (eEvent == MASTER_SEND_H_RD_ADDRESS) + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_AA); + eEvent = MASTER_READ_DATA; + } + else + { + rdata[u32rxLen++] = (unsigned char) UI2C_GET_DATA(ui2c); /* Receive Data */ + + if (u32rxLen < (u32rLen - 1U)) + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_AA); + else + u8Ctrl = UI2C_CTL_PTRG; + } + + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + + if (eEvent == MASTER_READ_DATA) + rdata[u32rxLen++] = (unsigned char) UI2C_GET_DATA(ui2c); /* Receive Data */ + + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_PROTCTL register */ + } + + return u32rxLen; /* Return bytes length that have been received */ +} + + +/** + * @brief Specify a byte register address and read a byte from Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u8DataAddr Specify a address(1 byte) of data read from + * + * @return Read a byte data from Slave + * + * @details The function is used for USCI_I2C Master specify a byte address that a data byte read from Slave. + * + * + */ +uint8_t UI2C_ReadByteOneReg(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, rdata = 0U, u8Ctrl = 0U; + enum UI2C_MASTER_EVENT eEvent = MASTER_SEND_START; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + + if (eEvent == MASTER_SEND_START) + { + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x00U); /* Write SLA+W to Register UI2C_TXDAT */ + eEvent = MASTER_SEND_ADDRESS; + } + else if (eEvent == MASTER_SEND_REPEAT_START) + { + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x01U); /* Write SLA+R to Register TXDAT */ + eEvent = MASTER_SEND_H_RD_ADDRESS; + } + + u8Ctrl = UI2C_CTL_PTRG; + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + + if (eEvent == MASTER_SEND_ADDRESS) + { + UI2C_SET_DATA(ui2c, u8DataAddr); /* Write data address of register */ + u8Ctrl = UI2C_CTL_PTRG; + eEvent = MASTER_SEND_DATA; + } + else if (eEvent == MASTER_SEND_DATA) + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STA); /* Send repeat START signal */ + eEvent = MASTER_SEND_REPEAT_START; + } + else + { + /* SLA+R ACK */ + u8Ctrl = UI2C_CTL_PTRG; + eEvent = MASTER_READ_DATA; + } + + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + + if (eEvent == MASTER_READ_DATA) + { + rdata = (uint8_t) UI2C_GET_DATA(ui2c); /* Receive Data */ + } + else + { + u8Err = 1U; + } + + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + u8Err = 1U; + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_PROTCTL register */ + } + + if (u8Err) + rdata = 0U; /* If occurs error, return 0 */ + + return rdata; /* Return read data */ +} + +/** + * @brief Specify a byte register address and read multi bytes from Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u8DataAddr Specify a address (1 bytes) of data read from + * @param[out] *rdata Point to array to store data from Slave + * @param[in] u32rLen How many bytes need to read from Slave + * + * @return A length of how many bytes have been received + * + * @details The function is used for USCI_I2C Master specify a byte address that multi data bytes read from Slave. + * + * + */ +uint32_t UI2C_ReadMultiBytesOneReg(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t *rdata, uint32_t u32rLen) +{ + uint8_t u8Xfering = 1U, u8Ctrl = 0U; + uint32_t u32rxLen = 0U; + enum UI2C_MASTER_EVENT eEvent = MASTER_SEND_START; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + + if (eEvent == MASTER_SEND_START) + { + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x00U); /* Write SLA+W to Register UI2C_TXDAT */ + eEvent = MASTER_SEND_ADDRESS; + } + else if (eEvent == MASTER_SEND_REPEAT_START) + { + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x01U); /* Write SLA+R to Register TXDAT */ + eEvent = MASTER_SEND_H_RD_ADDRESS; + } + + u8Ctrl = UI2C_CTL_PTRG; + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + + if (eEvent == MASTER_SEND_ADDRESS) + { + UI2C_SET_DATA(ui2c, u8DataAddr); /* Write data address of register */ + u8Ctrl = UI2C_CTL_PTRG; + eEvent = MASTER_SEND_DATA; + } + else if (eEvent == MASTER_SEND_DATA) + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STA); /* Send repeat START signal */ + eEvent = MASTER_SEND_REPEAT_START; + } + else if (eEvent == MASTER_SEND_H_RD_ADDRESS) + { + /* SLA+R ACK */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_AA); + eEvent = MASTER_READ_DATA; + } + else + { + rdata[u32rxLen++] = (uint8_t) UI2C_GET_DATA(ui2c); /* Receive Data */ + + if (u32rxLen < u32rLen - 1U) + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_AA); + else + u8Ctrl = UI2C_CTL_PTRG; + } + + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + + if (eEvent == MASTER_READ_DATA) + rdata[u32rxLen++] = (uint8_t) UI2C_GET_DATA(ui2c); /* Receive Data */ + + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_PROTCTL register */ + } + + return u32rxLen; /* Return bytes length that have been received */ +} + +/** + * @brief Specify two bytes register address and read a byte from Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u16DataAddr Specify a address(2 byte) of data read from + * + * @return Read a byte data from Slave + * + * @details The function is used for USCI_I2C Master specify two bytes address that a data byte read from Slave. + * + * + */ +uint8_t UI2C_ReadByteTwoRegs(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr) +{ + uint8_t u8Xfering = 1U, u8Err = 0U, rdata = 0U, u8Addr = 1U, u8Ctrl = 0U; + enum UI2C_MASTER_EVENT eEvent = MASTER_SEND_START; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + + if (eEvent == MASTER_SEND_START) + { + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x00U); /* Write SLA+W to Register UI2C_TXDAT */ + eEvent = MASTER_SEND_ADDRESS; + } + else if (eEvent == MASTER_SEND_REPEAT_START) + { + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x01U); /* Write SLA+R to Register TXDAT */ + eEvent = MASTER_SEND_H_RD_ADDRESS; + } + + u8Ctrl = UI2C_CTL_PTRG; + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + + if (eEvent == MASTER_SEND_ADDRESS) + { + UI2C_SET_DATA(ui2c, (uint8_t)((u16DataAddr & 0xFF00U) >> 8U)); /* Write Hi byte address of register */ + eEvent = MASTER_SEND_DATA; + } + else if (eEvent == MASTER_SEND_DATA) + { + if (u8Addr) + { + UI2C_SET_DATA(ui2c, (uint8_t)(u16DataAddr & 0xFFU)); /* Write Lo byte address of register */ + u8Addr = 0; + } + else + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STA); /* Send repeat START signal */ + eEvent = MASTER_SEND_REPEAT_START; + } + } + else + { + /* SLA+R ACK */ + u8Ctrl = UI2C_CTL_PTRG; + eEvent = MASTER_READ_DATA; + } + + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + + if (eEvent == MASTER_READ_DATA) + { + rdata = (uint8_t) UI2C_GET_DATA(ui2c); /* Receive Data */ + } + else + { + u8Err = 1U; + } + + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + u8Err = 1U; + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_PROTCTL register */ + } + + if (u8Err) + rdata = 0U; /* If occurs error, return 0 */ + + return rdata; /* Return read data */ +} + +/** + * @brief Specify two bytes register address and read multi bytes from Slave + * + * @param[in] ui2c The pointer of the specified USCI_I2C module. + * @param[in] u8SlaveAddr Access Slave address(7-bit) + * @param[in] u16DataAddr Specify a address (2 bytes) of data read from + * @param[out] *rdata Point to array to store data from Slave + * @param[in] u32rLen How many bytes need to read from Slave + * + * @return A length of how many bytes have been received + * + * @details The function is used for USCI_I2C Master specify two bytes address that multi data bytes read from Slave. + * + * + */ +uint32_t UI2C_ReadMultiBytesTwoRegs(UI2C_T *ui2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t *rdata, uint32_t u32rLen) +{ + uint8_t u8Xfering = 1U, u8Addr = 1U, u8Ctrl = 0U; + uint32_t u32rxLen = 0U; + enum UI2C_MASTER_EVENT eEvent = MASTER_SEND_START; + + UI2C_START(ui2c); /* Send START */ + + while (u8Xfering) + { + while (!(UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U)); /* Wait UI2C new status occur */ + + switch (UI2C_GET_PROT_STATUS(ui2c) & 0x3F00U) + { + case UI2C_PROTSTS_STARIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STARIF_Msk); /* Clear START INT Flag */ + + if (eEvent == MASTER_SEND_START) + { + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x00U); /* Write SLA+W to Register UI2C_TXDAT */ + eEvent = MASTER_SEND_ADDRESS; + } + else if (eEvent == MASTER_SEND_REPEAT_START) + { + UI2C_SET_DATA(ui2c, (u8SlaveAddr << 1U) | 0x01U); /* Write SLA+R to Register TXDAT */ + eEvent = MASTER_SEND_H_RD_ADDRESS; + } + + u8Ctrl = UI2C_CTL_PTRG; + break; + + case UI2C_PROTSTS_ACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_ACKIF_Msk); /* Clear ACK INT Flag */ + + if (eEvent == MASTER_SEND_ADDRESS) + { + UI2C_SET_DATA(ui2c, (uint8_t)((u16DataAddr & 0xFF00U) >> 8U)); /* Write Hi byte address of register */ + eEvent = MASTER_SEND_DATA; + } + else if (eEvent == MASTER_SEND_DATA) + { + if (u8Addr) + { + UI2C_SET_DATA(ui2c, (uint8_t)(u16DataAddr & 0xFFU)); /* Write Lo byte address of register */ + u8Addr = 0; + } + else + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STA); /* Send repeat START signal */ + eEvent = MASTER_SEND_REPEAT_START; + } + } + else if (eEvent == MASTER_SEND_H_RD_ADDRESS) + { + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_AA); + eEvent = MASTER_READ_DATA; + } + else + { + rdata[u32rxLen++] = (uint8_t) UI2C_GET_DATA(ui2c); /* Receive Data */ + + if (u32rxLen < u32rLen - 1U) + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_AA); + else + u8Ctrl = UI2C_CTL_PTRG; + } + + break; + + case UI2C_PROTSTS_NACKIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_NACKIF_Msk); /* Clear NACK INT Flag */ + + if (eEvent == MASTER_READ_DATA) + rdata[u32rxLen++] = (uint8_t) UI2C_GET_DATA(ui2c); /* Receive Data */ + + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + + break; + + case UI2C_PROTSTS_STORIF_Msk: + UI2C_CLR_PROT_INT_FLAG(ui2c, UI2C_PROTSTS_STORIF_Msk); /* Clear STOP INT Flag */ + u8Ctrl = UI2C_CTL_PTRG; /* Clear SI */ + u8Xfering = 0U; + break; + + case UI2C_PROTSTS_ARBLOIF_Msk: /* Arbitration Lost */ + default: /* Unknow status */ + u8Ctrl = (UI2C_CTL_PTRG | UI2C_CTL_STO); /* Clear SI and send STOP */ + break; + } + + UI2C_SET_CONTROL_REG(ui2c, u8Ctrl); /* Write controlbit to UI2C_PROTCTL register */ + } + + return u32rxLen; /* Return bytes length that have been received */ +} + +/*@}*/ /* end of group USCI_I2C_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group USCI_I2C_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_spi.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_spi.c new file mode 100644 index 0000000000..ee91b5fb2a --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_spi.c @@ -0,0 +1,635 @@ +/****************************************************************************//** + * @file usci_spi.c + * @version V1.00 + * @brief M031 series USCI_SPI driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +#include "M031Series.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup USCI_SPI_Driver USCI_SPI Driver + @{ +*/ + + +/** @addtogroup USCI_SPI_EXPORTED_FUNCTIONS USCI_SPI Exported Functions + @{ +*/ + +/** + * @brief This function make USCI_SPI module be ready to transfer. + * By default, the USCI_SPI transfer sequence is MSB first, the slave selection + * signal is active low and the automatic slave select function is disabled. In + * Slave mode, the u32BusClock must be NULL and the USCI_SPI clock + * divider setting will be 0. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32MasterSlave Decide the USCI_SPI module is operating in master mode or in slave mode. Valid values are: + * - \ref USPI_SLAVE + * - \ref USPI_MASTER + * @param[in] u32SPIMode Decide the transfer timing. Valid values are: + * - \ref USPI_MODE_0 + * - \ref USPI_MODE_1 + * - \ref USPI_MODE_2 + * - \ref USPI_MODE_3 + * @param[in] u32DataWidth The data width of a USCI_SPI transaction. + * @param[in] u32BusClock The expected frequency of USCI_SPI bus clock in Hz. + * @return Actual frequency of USCI_SPI peripheral clock. + */ +uint32_t USPI_Open(USPI_T *uspi, uint32_t u32MasterSlave, uint32_t u32SPIMode, uint32_t u32DataWidth, uint32_t u32BusClock) +{ + uint32_t u32ClkDiv = 0UL; + uint32_t u32Pclk; + uint32_t u32RetValue = 0UL; + + if (uspi == USPI0) + { + u32Pclk = CLK_GetPCLK0Freq(); + } + else + { + u32Pclk = CLK_GetPCLK1Freq(); + } + + if(u32BusClock != 0UL) + { + u32ClkDiv = (uint32_t)((((((u32Pclk / 2UL) * 10UL) / (u32BusClock)) + 5UL) / 10UL) - 1UL); /* Compute proper divider for USCI_SPI clock */ + } + + /* Enable USCI_SPI protocol */ + uspi->CTL &= ~USPI_CTL_FUNMODE_Msk; + uspi->CTL = 1UL << USPI_CTL_FUNMODE_Pos; + + /* Data format configuration */ + if(u32DataWidth == 16UL) + { + u32DataWidth = 0UL; + } + uspi->LINECTL &= ~USPI_LINECTL_DWIDTH_Msk; + uspi->LINECTL |= (u32DataWidth << USPI_LINECTL_DWIDTH_Pos); + + /* MSB data format */ + uspi->LINECTL &= ~USPI_LINECTL_LSB_Msk; + + /* Set slave selection signal active low */ + if(u32MasterSlave == USPI_MASTER) + { + uspi->LINECTL |= USPI_LINECTL_CTLOINV_Msk; + } + else + { + uspi->CTLIN0 |= USPI_CTLIN0_ININV_Msk; + } + + /* Set operating mode and transfer timing */ + uspi->PROTCTL &= ~(USPI_PROTCTL_SCLKMODE_Msk | USPI_PROTCTL_AUTOSS_Msk | USPI_PROTCTL_SLAVE_Msk); + uspi->PROTCTL |= (u32MasterSlave | u32SPIMode); + + /* Set USCI_SPI bus clock */ + uspi->BRGEN &= ~USPI_BRGEN_CLKDIV_Msk; + uspi->BRGEN |= (u32ClkDiv << USPI_BRGEN_CLKDIV_Pos); + uspi->PROTCTL |= USPI_PROTCTL_PROTEN_Msk; + + if(u32BusClock != 0UL) + { + u32RetValue = (u32Pclk / ((u32ClkDiv + 1UL) << 1UL)); + } + else + { + u32RetValue = 0UL; + } + + return u32RetValue; +} + +/** + * @brief Disable USCI_SPI function mode. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None + */ +void USPI_Close(USPI_T *uspi) +{ + uspi->CTL &= ~USPI_CTL_FUNMODE_Msk; +} + +/** + * @brief Clear Rx buffer. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None + */ +void USPI_ClearRxBuf(USPI_T *uspi) +{ + uspi->BUFCTL |= USPI_BUFCTL_RXCLR_Msk; +} + +/** + * @brief Clear Tx buffer. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None + */ +void USPI_ClearTxBuf(USPI_T *uspi) +{ + uspi->BUFCTL |= USPI_BUFCTL_TXCLR_Msk; +} + +/** + * @brief Disable the automatic slave select function. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None + */ +void USPI_DisableAutoSS(USPI_T *uspi) +{ + uspi->PROTCTL &= ~(USPI_PROTCTL_AUTOSS_Msk | USPI_PROTCTL_SS_Msk); +} + +/** + * @brief Enable the automatic slave select function. Only available in Master mode. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32SSPinMask This parameter is not used. + * @param[in] u32ActiveLevel The active level of slave select signal. Valid values are: + * - \ref USPI_SS_ACTIVE_HIGH + * - \ref USPI_SS_ACTIVE_LOW + * @return None + */ +void USPI_EnableAutoSS(USPI_T *uspi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel) +{ + uspi->LINECTL = (uspi->LINECTL & ~USPI_LINECTL_CTLOINV_Msk) | u32ActiveLevel; + uspi->PROTCTL |= USPI_PROTCTL_AUTOSS_Msk; +} + +/** + * @brief Set the USCI_SPI bus clock. Only available in Master mode. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32BusClock The expected frequency of USCI_SPI bus clock. + * @return Actual frequency of USCI_SPI peripheral clock. + */ +uint32_t USPI_SetBusClock(USPI_T *uspi, uint32_t u32BusClock) +{ + uint32_t u32ClkDiv; + uint32_t u32Pclk; + + if (uspi == USPI0) + { + u32Pclk = CLK_GetPCLK0Freq(); + } + else + { + u32Pclk = CLK_GetPCLK1Freq(); + } + + u32ClkDiv = (uint32_t)((((((u32Pclk / 2UL) * 10UL) / (u32BusClock)) + 5UL) / 10UL) - 1UL); /* Compute proper divider for USCI_SPI clock */ + + /* Set USCI_SPI bus clock */ + uspi->BRGEN &= ~USPI_BRGEN_CLKDIV_Msk; + uspi->BRGEN |= (u32ClkDiv << USPI_BRGEN_CLKDIV_Pos); + + return (u32Pclk / ((u32ClkDiv + 1UL) << 1UL)); +} + +/** + * @brief Get the actual frequency of USCI_SPI bus clock. Only available in Master mode. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return Actual USCI_SPI bus clock frequency. + */ +uint32_t USPI_GetBusClock(USPI_T *uspi) +{ + uint32_t u32ClkDiv, u32BusClk; + + u32ClkDiv = (uspi->BRGEN & USPI_BRGEN_CLKDIV_Msk) >> USPI_BRGEN_CLKDIV_Pos; + + if (uspi == USPI0) + { + u32BusClk = (CLK_GetPCLK0Freq() / ((u32ClkDiv + 1UL) << 1UL)); + } + else + { + u32BusClk = (CLK_GetPCLK1Freq() / ((u32ClkDiv + 1UL) << 1UL)); + } + + return u32BusClk; +} + +/** + * @brief Enable related interrupts specified by u32Mask parameter. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to a interrupt bit. + * This parameter decides which interrupts will be enabled. Valid values are: + * - \ref USPI_SSINACT_INT_MASK + * - \ref USPI_SSACT_INT_MASK + * - \ref USPI_SLVTO_INT_MASK + * - \ref USPI_SLVBE_INT_MASK + * - \ref USPI_TXUDR_INT_MASK + * - \ref USPI_RXOV_INT_MASK + * - \ref USPI_TXST_INT_MASK + * - \ref USPI_TXEND_INT_MASK + * - \ref USPI_RXST_INT_MASK + * - \ref USPI_RXEND_INT_MASK + * @return None + */ +void USPI_EnableInt(USPI_T *uspi, uint32_t u32Mask) +{ + /* Enable slave selection signal inactive interrupt flag */ + if((u32Mask & USPI_SSINACT_INT_MASK) == USPI_SSINACT_INT_MASK) + { + uspi->PROTIEN |= USPI_PROTIEN_SSINAIEN_Msk; + } + + /* Enable slave selection signal active interrupt flag */ + if((u32Mask & USPI_SSACT_INT_MASK) == USPI_SSACT_INT_MASK) + { + uspi->PROTIEN |= USPI_PROTIEN_SSACTIEN_Msk; + } + + /* Enable slave time-out interrupt flag */ + if((u32Mask & USPI_SLVTO_INT_MASK) == USPI_SLVTO_INT_MASK) + { + uspi->PROTIEN |= USPI_PROTIEN_SLVTOIEN_Msk; + } + + /* Enable slave bit count error interrupt flag */ + if((u32Mask & USPI_SLVBE_INT_MASK) == USPI_SLVBE_INT_MASK) + { + uspi->PROTIEN |= USPI_PROTIEN_SLVBEIEN_Msk; + } + + /* Enable TX under run interrupt flag */ + if((u32Mask & USPI_TXUDR_INT_MASK) == USPI_TXUDR_INT_MASK) + { + uspi->BUFCTL |= USPI_BUFCTL_TXUDRIEN_Msk; + } + + /* Enable RX overrun interrupt flag */ + if((u32Mask & USPI_RXOV_INT_MASK) == USPI_RXOV_INT_MASK) + { + uspi->BUFCTL |= USPI_BUFCTL_RXOVIEN_Msk; + } + + /* Enable TX start interrupt flag */ + if((u32Mask & USPI_TXST_INT_MASK) == USPI_TXST_INT_MASK) + { + uspi->INTEN |= USPI_INTEN_TXSTIEN_Msk; + } + + /* Enable TX end interrupt flag */ + if((u32Mask & USPI_TXEND_INT_MASK) == USPI_TXEND_INT_MASK) + { + uspi->INTEN |= USPI_INTEN_TXENDIEN_Msk; + } + + /* Enable RX start interrupt flag */ + if((u32Mask & USPI_RXST_INT_MASK) == USPI_RXST_INT_MASK) + { + uspi->INTEN |= USPI_INTEN_RXSTIEN_Msk; + } + + /* Enable RX end interrupt flag */ + if((u32Mask & USPI_RXEND_INT_MASK) == USPI_RXEND_INT_MASK) + { + uspi->INTEN |= USPI_INTEN_RXENDIEN_Msk; + } +} + +/** + * @brief Disable related interrupts specified by u32Mask parameter. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to a interrupt bit. + * This parameter decides which interrupts will be disabled. Valid values are: + * - \ref USPI_SSINACT_INT_MASK + * - \ref USPI_SSACT_INT_MASK + * - \ref USPI_SLVTO_INT_MASK + * - \ref USPI_SLVBE_INT_MASK + * - \ref USPI_TXUDR_INT_MASK + * - \ref USPI_RXOV_INT_MASK + * - \ref USPI_TXST_INT_MASK + * - \ref USPI_TXEND_INT_MASK + * - \ref USPI_RXST_INT_MASK + * - \ref USPI_RXEND_INT_MASK + * @return None + */ +void USPI_DisableInt(USPI_T *uspi, uint32_t u32Mask) +{ + /* Disable slave selection signal inactive interrupt flag */ + if((u32Mask & USPI_SSINACT_INT_MASK) == USPI_SSINACT_INT_MASK) + { + uspi->PROTIEN &= ~USPI_PROTIEN_SSINAIEN_Msk; + } + + /* Disable slave selection signal active interrupt flag */ + if((u32Mask & USPI_SSACT_INT_MASK) == USPI_SSACT_INT_MASK) + { + uspi->PROTIEN &= ~USPI_PROTIEN_SSACTIEN_Msk; + } + + /* Disable slave time-out interrupt flag */ + if((u32Mask & USPI_SLVTO_INT_MASK) == USPI_SLVTO_INT_MASK) + { + uspi->PROTIEN &= ~USPI_PROTIEN_SLVTOIEN_Msk; + } + + /* Disable slave bit count error interrupt flag */ + if((u32Mask & USPI_SLVBE_INT_MASK) == USPI_SLVBE_INT_MASK) + { + uspi->PROTIEN &= ~USPI_PROTIEN_SLVBEIEN_Msk; + } + + /* Disable TX under run interrupt flag */ + if((u32Mask & USPI_TXUDR_INT_MASK) == USPI_TXUDR_INT_MASK) + { + uspi->BUFCTL &= ~USPI_BUFCTL_TXUDRIEN_Msk; + } + + /* Disable RX overrun interrupt flag */ + if((u32Mask & USPI_RXOV_INT_MASK) == USPI_RXOV_INT_MASK) + { + uspi->BUFCTL &= ~USPI_BUFCTL_RXOVIEN_Msk; + } + + /* Disable TX start interrupt flag */ + if((u32Mask & USPI_TXST_INT_MASK) == USPI_TXST_INT_MASK) + { + uspi->INTEN &= ~USPI_INTEN_TXSTIEN_Msk; + } + + /* Disable TX end interrupt flag */ + if((u32Mask & USPI_TXEND_INT_MASK) == USPI_TXEND_INT_MASK) + { + uspi->INTEN &= ~USPI_INTEN_TXENDIEN_Msk; + } + + /* Disable RX start interrupt flag */ + if((u32Mask & USPI_RXST_INT_MASK) == USPI_RXST_INT_MASK) + { + uspi->INTEN &= ~USPI_INTEN_RXSTIEN_Msk; + } + + /* Disable RX end interrupt flag */ + if((u32Mask & USPI_RXEND_INT_MASK) == USPI_RXEND_INT_MASK) + { + uspi->INTEN &= ~USPI_INTEN_RXENDIEN_Msk; + } +} + +/** + * @brief Get interrupt flag. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32Mask The combination of all related interrupt sources. + * Each bit corresponds to a interrupt source. + * This parameter decides which interrupt flags will be read. It is combination of: + * - \ref USPI_SSINACT_INT_MASK + * - \ref USPI_SSACT_INT_MASK + * - \ref USPI_SLVTO_INT_MASK + * - \ref USPI_SLVBE_INT_MASK + * - \ref USPI_TXUDR_INT_MASK + * - \ref USPI_RXOV_INT_MASK + * - \ref USPI_TXST_INT_MASK + * - \ref USPI_TXEND_INT_MASK + * - \ref USPI_RXST_INT_MASK + * - \ref USPI_RXEND_INT_MASK + * @return Interrupt flags of selected sources. + */ +uint32_t USPI_GetIntFlag(USPI_T *uspi, uint32_t u32Mask) +{ + uint32_t u32ProtStatus, u32BufStatus; + uint32_t u32IntFlag = 0UL; + + u32ProtStatus = uspi->PROTSTS; + u32BufStatus = uspi->BUFSTS; + + /* Check slave selection signal inactive interrupt flag */ + if((u32Mask & USPI_SSINACT_INT_MASK) && (u32ProtStatus & USPI_PROTSTS_SSINAIF_Msk)) + { + u32IntFlag |= USPI_SSINACT_INT_MASK; + } + + /* Check slave selection signal active interrupt flag */ + if((u32Mask & USPI_SSACT_INT_MASK) && (u32ProtStatus & USPI_PROTSTS_SSACTIF_Msk)) + { + u32IntFlag |= USPI_SSACT_INT_MASK; + } + + /* Check slave time-out interrupt flag */ + if((u32Mask & USPI_SLVTO_INT_MASK) && (u32ProtStatus & USPI_PROTSTS_SLVTOIF_Msk)) + { + u32IntFlag |= USPI_SLVTO_INT_MASK; + } + + /* Check slave bit count error interrupt flag */ + if((u32Mask & USPI_SLVBE_INT_MASK) && (u32ProtStatus & USPI_PROTSTS_SLVBEIF_Msk)) + { + u32IntFlag |= USPI_SLVBE_INT_MASK; + } + + /* Check TX under run interrupt flag */ + if((u32Mask & USPI_TXUDR_INT_MASK) && (u32BufStatus & USPI_BUFSTS_TXUDRIF_Msk)) + { + u32IntFlag |= USPI_TXUDR_INT_MASK; + } + + /* Check RX overrun interrupt flag */ + if((u32Mask & USPI_RXOV_INT_MASK) && (u32BufStatus & USPI_BUFSTS_RXOVIF_Msk)) + { + u32IntFlag |= USPI_RXOV_INT_MASK; + } + + /* Check TX start interrupt flag */ + if((u32Mask & USPI_TXST_INT_MASK) && (u32ProtStatus & USPI_PROTSTS_TXSTIF_Msk)) + { + u32IntFlag |= USPI_TXST_INT_MASK; + } + + /* Check TX end interrupt flag */ + if((u32Mask & USPI_TXEND_INT_MASK) && (u32ProtStatus & USPI_PROTSTS_TXENDIF_Msk)) + { + u32IntFlag |= USPI_TXEND_INT_MASK; + } + + /* Check RX start interrupt flag */ + if((u32Mask & USPI_RXST_INT_MASK) && (u32ProtStatus & USPI_PROTSTS_RXSTIF_Msk)) + { + u32IntFlag |= USPI_RXST_INT_MASK; + } + + /* Check RX end interrupt flag */ + if((u32Mask & USPI_RXEND_INT_MASK) && (u32ProtStatus & USPI_PROTSTS_RXENDIF_Msk)) + { + u32IntFlag |= USPI_RXEND_INT_MASK; + } + + return u32IntFlag; +} + +/** + * @brief Clear interrupt flag. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32Mask The combination of all related interrupt sources. + * Each bit corresponds to a interrupt source. + * This parameter decides which interrupt flags will be cleared. It could be the combination of: + * - \ref USPI_SSINACT_INT_MASK + * - \ref USPI_SSACT_INT_MASK + * - \ref USPI_SLVTO_INT_MASK + * - \ref USPI_SLVBE_INT_MASK + * - \ref USPI_TXUDR_INT_MASK + * - \ref USPI_RXOV_INT_MASK + * - \ref USPI_TXST_INT_MASK + * - \ref USPI_TXEND_INT_MASK + * - \ref USPI_RXST_INT_MASK + * - \ref USPI_RXEND_INT_MASK + * @return None + */ +void USPI_ClearIntFlag(USPI_T *uspi, uint32_t u32Mask) +{ + /* Clear slave selection signal inactive interrupt flag */ + if(u32Mask & USPI_SSINACT_INT_MASK) + { + uspi->PROTSTS = USPI_PROTSTS_SSINAIF_Msk; + } + + /* Clear slave selection signal active interrupt flag */ + if(u32Mask & USPI_SSACT_INT_MASK) + { + uspi->PROTSTS = USPI_PROTSTS_SSACTIF_Msk; + } + + /* Clear slave time-out interrupt flag */ + if(u32Mask & USPI_SLVTO_INT_MASK) + { + uspi->PROTSTS = USPI_PROTSTS_SLVTOIF_Msk; + } + + /* Clear slave bit count error interrupt flag */ + if(u32Mask & USPI_SLVBE_INT_MASK) + { + uspi->PROTSTS = USPI_PROTSTS_SLVBEIF_Msk; + } + + /* Clear TX under run interrupt flag */ + if(u32Mask & USPI_TXUDR_INT_MASK) + { + uspi->BUFSTS = USPI_BUFSTS_TXUDRIF_Msk; + } + + /* Clear RX overrun interrupt flag */ + if(u32Mask & USPI_RXOV_INT_MASK) + { + uspi->BUFSTS = USPI_BUFSTS_RXOVIF_Msk; + } + + /* Clear TX start interrupt flag */ + if(u32Mask & USPI_TXST_INT_MASK) + { + uspi->PROTSTS = USPI_PROTSTS_TXSTIF_Msk; + } + + /* Clear TX end interrupt flag */ + if(u32Mask & USPI_TXEND_INT_MASK) + { + uspi->PROTSTS = USPI_PROTSTS_TXENDIF_Msk; + } + + /* Clear RX start interrupt flag */ + if(u32Mask & USPI_RXST_INT_MASK) + { + uspi->PROTSTS = USPI_PROTSTS_RXSTIF_Msk; + } + + /* Clear RX end interrupt flag */ + if(u32Mask & USPI_RXEND_INT_MASK) + { + uspi->PROTSTS = USPI_PROTSTS_RXENDIF_Msk; + } +} + +/** + * @brief Get USCI_SPI status. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @param[in] u32Mask The combination of all related sources. + * Each bit corresponds to a source. + * This parameter decides which flags will be read. It is combination of: + * - \ref USPI_BUSY_MASK + * - \ref USPI_RX_EMPTY_MASK + * - \ref USPI_RX_FULL_MASK + * - \ref USPI_TX_EMPTY_MASK + * - \ref USPI_TX_FULL_MASK + * - \ref USPI_SSLINE_STS_MASK + * @return Flags of selected sources. + */ +uint32_t USPI_GetStatus(USPI_T *uspi, uint32_t u32Mask) +{ + uint32_t u32ProtStatus, u32BufStatus; + uint32_t u32Flag = 0UL; + + u32ProtStatus = uspi->PROTSTS; + u32BufStatus = uspi->BUFSTS; + + /* Check busy status */ + if((u32Mask & USPI_BUSY_MASK) && (u32ProtStatus & USPI_PROTSTS_BUSY_Msk)) + { + u32Flag |= USPI_BUSY_MASK; + } + + /* Check RX empty flag */ + if((u32Mask & USPI_RX_EMPTY_MASK) && (u32BufStatus & USPI_BUFSTS_RXEMPTY_Msk)) + { + u32Flag |= USPI_RX_EMPTY_MASK; + } + + /* Check RX full flag */ + if((u32Mask & USPI_RX_FULL_MASK) && (u32BufStatus & USPI_BUFSTS_RXFULL_Msk)) + { + u32Flag |= USPI_RX_FULL_MASK; + } + + /* Check TX empty flag */ + if((u32Mask & USPI_TX_EMPTY_MASK) && (u32BufStatus & USPI_BUFSTS_TXEMPTY_Msk)) + { + u32Flag |= USPI_TX_EMPTY_MASK; + } + + /* Check TX full flag */ + if((u32Mask & USPI_TX_FULL_MASK) && (u32BufStatus & USPI_BUFSTS_TXFULL_Msk)) + { + u32Flag |= USPI_TX_FULL_MASK; + } + + /* Check USCI_SPI_SS line status */ + if((u32Mask & USPI_SSLINE_STS_MASK) && (u32ProtStatus & USPI_PROTSTS_SSLINE_Msk)) + { + u32Flag |= USPI_SSLINE_STS_MASK; + } + + return u32Flag; +} + +/** + * @brief Enable USCI_SPI Wake-up Function. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None + */ +void USPI_EnableWakeup(USPI_T *uspi) +{ + uspi->WKCTL |= USPI_WKCTL_WKEN_Msk; +} + +/** + * @brief Disable USCI_SPI Wake-up Function. + * @param[in] uspi The pointer of the specified USCI_SPI module. + * @return None + */ +void USPI_DisableWakeup(USPI_T *uspi) +{ + uspi->WKCTL &= ~USPI_WKCTL_WKEN_Msk; +} + +/*@}*/ /* end of group USCI_SPI_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group USCI_SPI_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_uart.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_uart.c new file mode 100644 index 0000000000..847cba7a6b --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_usci_uart.c @@ -0,0 +1,729 @@ +/**************************************************************************//** + * @file usci_uart.c + * @version V1.00 + * @brief M031 series USCI UART (UUART) driver source file + * + * SPDX-License-Identifier: Apache-2.0 + * copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#include +#include "M031Series.h" + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup USCI_UART_Driver USCI_UART Driver + @{ +*/ + +/** @addtogroup USCI_UART_EXPORTED_FUNCTIONS USCI_UART Exported Functions + @{ +*/ + +/** + * @brief Clear USCI_UART specified interrupt flag + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * @param[in] u32Mask The combination of all related interrupt sources. + * Each bit corresponds to a interrupt source. + * This parameter decides which interrupt flags will be cleared. It could be the combination of: + * - \ref UUART_ABR_INT_MASK + * - \ref UUART_RLS_INT_MASK + * - \ref UUART_BUF_RXOV_INT_MASK + * - \ref UUART_TXST_INT_MASK + * - \ref UUART_TXEND_INT_MASK + * - \ref UUART_RXST_INT_MASK + * - \ref UUART_RXEND_INT_MASK + * + * @return None + * + * @details The function is used to clear USCI_UART related interrupt flags specified by u32Mask parameter. + */ + +void UUART_ClearIntFlag(UUART_T* uuart, uint32_t u32Mask) +{ + + if(u32Mask & UUART_ABR_INT_MASK) /* Clear Auto-baud Rate Interrupt */ + { + uuart->PROTSTS = UUART_PROTSTS_ABRDETIF_Msk; + } + + if(u32Mask & UUART_RLS_INT_MASK) /* Clear Receive Line Status Interrupt */ + { + uuart->PROTSTS = (UUART_PROTSTS_BREAK_Msk | UUART_PROTSTS_FRMERR_Msk | UUART_PROTSTS_PARITYERR_Msk); + } + + if(u32Mask & UUART_BUF_RXOV_INT_MASK) /* Clear Receive Buffer Over-run Error Interrupt */ + { + uuart->BUFSTS = UUART_BUFSTS_RXOVIF_Msk; + } + + if(u32Mask & UUART_TXST_INT_MASK) /* Clear Transmit Start Interrupt */ + { + uuart->PROTSTS = UUART_PROTSTS_TXSTIF_Msk; + } + + if(u32Mask & UUART_TXEND_INT_MASK) /* Clear Transmit End Interrupt */ + { + uuart->PROTSTS = UUART_PROTSTS_TXENDIF_Msk; + } + + if(u32Mask & UUART_RXST_INT_MASK) /* Clear Receive Start Interrupt */ + { + uuart->PROTSTS = UUART_PROTSTS_RXSTIF_Msk; + } + + if(u32Mask & UUART_RXEND_INT_MASK) /* Clear Receive End Interrupt */ + { + uuart->PROTSTS = UUART_PROTSTS_RXENDIF_Msk; + } + +} + + +/** + * @brief Get USCI_UART specified interrupt flag + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * @param[in] u32Mask The combination of all related interrupt sources. + * Each bit corresponds to a interrupt source. + * This parameter decides which interrupt flags will be read. It is combination of: + * - \ref UUART_ABR_INT_MASK + * - \ref UUART_RLS_INT_MASK + * - \ref UUART_BUF_RXOV_INT_MASK + * - \ref UUART_TXST_INT_MASK + * - \ref UUART_TXEND_INT_MASK + * - \ref UUART_RXST_INT_MASK + * - \ref UUART_RXEND_INT_MASK + * + * @return Interrupt flags of selected sources. + * + * @details The function is used to get USCI_UART related interrupt flags specified by u32Mask parameter. + */ + +uint32_t UUART_GetIntFlag(UUART_T* uuart, uint32_t u32Mask) +{ + uint32_t u32IntFlag = 0ul; + uint32_t u32Tmp1, u32Tmp2; + + /* Check Auto-baud Rate Interrupt Flag */ + u32Tmp1 = (u32Mask & UUART_ABR_INT_MASK); + u32Tmp2 = (uuart->PROTSTS & UUART_PROTSTS_ABRDETIF_Msk); + if(u32Tmp1 && u32Tmp2) + { + u32IntFlag |= UUART_ABR_INT_MASK; + } + + /* Check Receive Line Status Interrupt Flag */ + u32Tmp1 = (u32Mask & UUART_RLS_INT_MASK); + u32Tmp2 = (uuart->PROTSTS & (UUART_PROTSTS_BREAK_Msk | UUART_PROTSTS_FRMERR_Msk | UUART_PROTSTS_PARITYERR_Msk)); + if(u32Tmp1 && u32Tmp2) + { + u32IntFlag |= UUART_RLS_INT_MASK; + } + + /* Check Receive Buffer Over-run Error Interrupt Flag */ + u32Tmp1 = (u32Mask & UUART_BUF_RXOV_INT_MASK); + u32Tmp2 = (uuart->BUFSTS & UUART_BUFSTS_RXOVIF_Msk); + if(u32Tmp1 && u32Tmp2) + { + u32IntFlag |= UUART_BUF_RXOV_INT_MASK; + } + + /* Check Transmit Start Interrupt Flag */ + u32Tmp1 = (u32Mask & UUART_TXST_INT_MASK); + u32Tmp2 = (uuart->PROTSTS & UUART_PROTSTS_TXSTIF_Msk); + if(u32Tmp1 && u32Tmp2) + { + u32IntFlag |= UUART_TXST_INT_MASK; + } + + /* Check Transmit End Interrupt Flag */ + u32Tmp1 = (u32Mask & UUART_TXEND_INT_MASK); + u32Tmp2 = (uuart->PROTSTS & UUART_PROTSTS_TXENDIF_Msk); + if(u32Tmp1 && u32Tmp2) + { + u32IntFlag |= UUART_TXEND_INT_MASK; + } + + /* Check Receive Start Interrupt Flag */ + u32Tmp1 = (u32Mask & UUART_RXST_INT_MASK); + u32Tmp2 = (uuart->PROTSTS & UUART_PROTSTS_RXSTIF_Msk); + if(u32Tmp1 && u32Tmp2) + { + u32IntFlag |= UUART_RXST_INT_MASK; + } + + /* Check Receive End Interrupt Flag */ + u32Tmp1 = (u32Mask & UUART_RXEND_INT_MASK); + u32Tmp2 = (uuart->PROTSTS & UUART_PROTSTS_RXENDIF_Msk); + if(u32Tmp1 && u32Tmp2) + { + u32IntFlag |= UUART_RXEND_INT_MASK; + } + + return u32IntFlag; +} + + +/** + * @brief Disable USCI_UART function mode + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * + * @return None + * + * @details The function is used to disable USCI_UART function mode. + */ +void UUART_Close(UUART_T* uuart) +{ + uuart->CTL = 0UL; +} + + +/** + * @brief Disable interrupt function. + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to a interrupt enable bit. + * This parameter decides which interrupts will be disabled. It is combination of: + * - \ref UUART_ABR_INT_MASK + * - \ref UUART_RLS_INT_MASK + * - \ref UUART_BUF_RXOV_INT_MASK + * - \ref UUART_TXST_INT_MASK + * - \ref UUART_TXEND_INT_MASK + * - \ref UUART_RXST_INT_MASK + * - \ref UUART_RXEND_INT_MASK + * + * @return None + * + * @details The function is used to disabled USCI_UART related interrupts specified by u32Mask parameter. + */ +void UUART_DisableInt(UUART_T* uuart, uint32_t u32Mask) +{ + + /* Disable Auto-baud rate interrupt flag */ + if((u32Mask & UUART_ABR_INT_MASK) == UUART_ABR_INT_MASK) + { + uuart->PROTIEN &= ~UUART_PROTIEN_ABRIEN_Msk; + } + + /* Disable receive line status interrupt flag */ + if((u32Mask & UUART_RLS_INT_MASK) == UUART_RLS_INT_MASK) + { + uuart->PROTIEN &= ~UUART_PROTIEN_RLSIEN_Msk; + } + + /* Disable RX overrun interrupt flag */ + if((u32Mask & UUART_BUF_RXOV_INT_MASK) == UUART_BUF_RXOV_INT_MASK) + { + uuart->BUFCTL &= ~UUART_BUFCTL_RXOVIEN_Msk; + } + + /* Disable TX start interrupt flag */ + if((u32Mask & UUART_TXST_INT_MASK) == UUART_TXST_INT_MASK) + { + uuart->INTEN &= ~UUART_INTEN_TXSTIEN_Msk; + } + + /* Disable TX end interrupt flag */ + if((u32Mask & UUART_TXEND_INT_MASK) == UUART_TXEND_INT_MASK) + { + uuart->INTEN &= ~UUART_INTEN_TXENDIEN_Msk; + } + + /* Disable RX start interrupt flag */ + if((u32Mask & UUART_RXST_INT_MASK) == UUART_RXST_INT_MASK) + { + uuart->INTEN &= ~UUART_INTEN_RXSTIEN_Msk; + } + + /* Disable RX end interrupt flag */ + if((u32Mask & UUART_RXEND_INT_MASK) == UUART_RXEND_INT_MASK) + { + uuart->INTEN &= ~UUART_INTEN_RXENDIEN_Msk; + } +} + + +/** + * @brief Enable interrupt function. + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * @param[in] u32Mask The combination of all related interrupt enable bits. + * Each bit corresponds to a interrupt enable bit. + * This parameter decides which interrupts will be enabled. It is combination of: + * - \ref UUART_ABR_INT_MASK + * - \ref UUART_RLS_INT_MASK + * - \ref UUART_BUF_RXOV_INT_MASK + * - \ref UUART_TXST_INT_MASK + * - \ref UUART_TXEND_INT_MASK + * - \ref UUART_RXST_INT_MASK + * - \ref UUART_RXEND_INT_MASK + * + * @return None + * + * @details The function is used to enable USCI_UART related interrupts specified by u32Mask parameter. + */ +void UUART_EnableInt(UUART_T* uuart, uint32_t u32Mask) +{ + /* Enable Auto-baud rate interrupt flag */ + if((u32Mask & UUART_ABR_INT_MASK) == UUART_ABR_INT_MASK) + { + uuart->PROTIEN |= UUART_PROTIEN_ABRIEN_Msk; + } + + /* Enable receive line status interrupt flag */ + if((u32Mask & UUART_RLS_INT_MASK) == UUART_RLS_INT_MASK) + { + uuart->PROTIEN |= UUART_PROTIEN_RLSIEN_Msk; + } + + /* Enable RX overrun interrupt flag */ + if((u32Mask & UUART_BUF_RXOV_INT_MASK) == UUART_BUF_RXOV_INT_MASK) + { + uuart->BUFCTL |= UUART_BUFCTL_RXOVIEN_Msk; + } + + /* Enable TX start interrupt flag */ + if((u32Mask & UUART_TXST_INT_MASK) == UUART_TXST_INT_MASK) + { + uuart->INTEN |= UUART_INTEN_TXSTIEN_Msk; + } + + /* Enable TX end interrupt flag */ + if((u32Mask & UUART_TXEND_INT_MASK) == UUART_TXEND_INT_MASK) + { + uuart->INTEN |= UUART_INTEN_TXENDIEN_Msk; + } + + /* Enable RX start interrupt flag */ + if((u32Mask & UUART_RXST_INT_MASK) == UUART_RXST_INT_MASK) + { + uuart->INTEN |= UUART_INTEN_RXSTIEN_Msk; + } + + /* Enable RX end interrupt flag */ + if((u32Mask & UUART_RXEND_INT_MASK) == UUART_RXEND_INT_MASK) + { + uuart->INTEN |= UUART_INTEN_RXENDIEN_Msk; + } +} + + +/** + * @brief Open and set USCI_UART function + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * @param[in] u32baudrate The baud rate of USCI_UART module. + * + * @return Real baud rate of USCI_UART module. + * + * @details This function use to enable USCI_UART function and set baud-rate. + */ +uint32_t UUART_Open(UUART_T* uuart, uint32_t u32baudrate) +{ + uint32_t u32PCLKFreq, u32PDSCnt, u32DSCnt, u32ClkDiv; + uint32_t u32Tmp, u32Tmp2, u32Min, u32MinClkDiv, u32MinDSCnt; + uint32_t u32Div; + + /* Get PCLK frequency */ + if(uuart == UUART0) + { + u32PCLKFreq = CLK_GetPCLK0Freq(); + } + else + { + u32PCLKFreq = CLK_GetPCLK1Freq(); + } + + /* Calculate baud rate divider */ + u32Div = u32PCLKFreq / u32baudrate; + u32Tmp = (u32PCLKFreq / u32Div) - u32baudrate; + u32Tmp2 = u32baudrate - (u32PCLKFreq / (u32Div + 1ul)); + + if(u32Tmp >= u32Tmp2) u32Div = u32Div + 1ul; + + if(u32Div >= 65536ul) + { + + /* Set the smallest baud rate that USCI_UART can generate */ + u32PDSCnt = 0x4ul; + u32MinDSCnt = 0x10ul; + u32MinClkDiv = 0x400ul; + + } + else + { + + u32Tmp = 0x400ul * 0x10ul; + for(u32PDSCnt = 1ul; u32PDSCnt <= 0x04ul; u32PDSCnt++) + { + if(u32Div <= (u32Tmp * u32PDSCnt)) break; + } + + if(u32PDSCnt > 0x4ul) u32PDSCnt = 0x4ul; + + u32Div = u32Div / u32PDSCnt; + + /* Find best solution */ + u32Min = (uint32_t) - 1; + u32MinDSCnt = 0ul; + u32MinClkDiv = 0ul; + u32Tmp = 0ul; + + for(u32DSCnt = 6ul; u32DSCnt <= 0x10ul; u32DSCnt++) /* DSCNT could be 0x5~0xF */ + { + + u32ClkDiv = u32Div / u32DSCnt; + + if(u32ClkDiv > 0x400ul) + { + u32ClkDiv = 0x400ul; + u32Tmp = u32Div - (u32ClkDiv * u32DSCnt); + u32Tmp2 = u32Tmp + 1ul; + } + else + { + u32Tmp = u32Div - (u32ClkDiv * u32DSCnt); + u32Tmp2 = ((u32ClkDiv + 1ul) * u32DSCnt) - u32Div; + } + + if(u32Tmp >= u32Tmp2) + { + u32ClkDiv = u32ClkDiv + 1ul; + } + else u32Tmp2 = u32Tmp; + + if(u32Tmp2 < u32Min) + { + u32Min = u32Tmp2; + u32MinDSCnt = u32DSCnt; + u32MinClkDiv = u32ClkDiv; + + /* Break when get good results */ + if(u32Min == 0ul) + { + break; + } + } + } + + } + + /* Enable USCI_UART protocol */ + uuart->CTL &= ~UUART_CTL_FUNMODE_Msk; + uuart->CTL = 2ul << UUART_CTL_FUNMODE_Pos; + + /* Set USCI_UART line configuration */ + uuart->LINECTL = UUART_WORD_LEN_8 | UUART_LINECTL_LSB_Msk; + uuart->DATIN0 = (2ul << UUART_DATIN0_EDGEDET_Pos); /* Set falling edge detection */ + + /* Set USCI_UART baud rate */ + uuart->BRGEN = ((u32MinClkDiv - 1ul) << UUART_BRGEN_CLKDIV_Pos) | + ((u32MinDSCnt - 1ul) << UUART_BRGEN_DSCNT_Pos) | + ((u32PDSCnt - 1ul) << UUART_BRGEN_PDSCNT_Pos); + + uuart->PROTCTL |= UUART_PROTCTL_PROTEN_Msk; + + return (u32PCLKFreq / u32PDSCnt / u32MinDSCnt / u32MinClkDiv); +} + + +/** + * @brief Read USCI_UART data + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * @param[in] pu8RxBuf The buffer to receive the data of receive buffer. + * @param[in] u32ReadBytes The read bytes number of data. + * + * @return Receive byte count + * + * @details The function is used to read Rx data from RX buffer and the data will be stored in pu8RxBuf. + */ +uint32_t UUART_Read(UUART_T* uuart, uint8_t pu8RxBuf[], uint32_t u32ReadBytes) +{ + uint32_t u32Count, u32delayno; + + for(u32Count = 0ul; u32Count < u32ReadBytes; u32Count++) + { + u32delayno = 0ul; + + while(uuart->BUFSTS & UUART_BUFSTS_RXEMPTY_Msk) /* Check RX empty => failed */ + { + u32delayno++; + if(u32delayno >= 0x40000000ul) + { + break; + } + } + + if(u32delayno >= 0x40000000ul) + { + break; + } + + pu8RxBuf[u32Count] = (uint8_t)uuart->RXDAT; /* Get Data from USCI RX */ + } + + return u32Count; + +} + + +/** + * @brief Set USCI_UART line configuration + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * @param[in] u32baudrate The register value of baud rate of USCI_UART module. + * If u32baudrate = 0, USCI_UART baud rate will not change. + * @param[in] u32data_width The data length of USCI_UART module. + * - \ref UUART_WORD_LEN_6 + * - \ref UUART_WORD_LEN_7 + * - \ref UUART_WORD_LEN_8 + * - \ref UUART_WORD_LEN_9 + * @param[in] u32parity The parity setting (none/odd/even) of USCI_UART module. + * - \ref UUART_PARITY_NONE + * - \ref UUART_PARITY_ODD + * - \ref UUART_PARITY_EVEN + * @param[in] u32stop_bits The stop bit length (1/2 bit) of USCI_UART module. + * - \ref UUART_STOP_BIT_1 + * - \ref UUART_STOP_BIT_2 + * + * @return Real baud rate of USCI_UART module. + * + * @details This function use to config USCI_UART line setting. + */ +uint32_t UUART_SetLine_Config(UUART_T* uuart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits) +{ + uint32_t u32PCLKFreq, u32PDSCnt, u32DSCnt, u32ClkDiv; + uint32_t u32Tmp, u32Tmp2, u32Min, u32MinClkDiv, u32MinDSCnt; + uint32_t u32Div; + + /* Get PCLK frequency */ + if(uuart == UUART0) + { + u32PCLKFreq = CLK_GetPCLK0Freq(); + } + else + { + u32PCLKFreq = CLK_GetPCLK1Freq(); + } + + if(u32baudrate != 0ul) + { + + /* Calculate baud rate divider */ + u32Div = u32PCLKFreq / u32baudrate; + u32Tmp = (u32PCLKFreq / u32Div) - u32baudrate; + u32Tmp2 = u32baudrate - (u32PCLKFreq / (u32Div + 1ul)); + + if(u32Tmp >= u32Tmp2) u32Div = u32Div + 1ul; + + if(u32Div >= 65536ul) + { + + /* Set the smallest baud rate that USCI_UART can generate */ + u32PDSCnt = 0x4ul; + u32MinDSCnt = 0x10ul; + u32MinClkDiv = 0x400ul; + + } + else + { + + u32Tmp = 0x400ul * 0x10ul; + for(u32PDSCnt = 1ul; u32PDSCnt <= 0x04ul; u32PDSCnt++) + { + if(u32Div <= (u32Tmp * u32PDSCnt)) break; + } + + if(u32PDSCnt > 0x4ul) u32PDSCnt = 0x4ul; + + u32Div = u32Div / u32PDSCnt; + + /* Find best solution */ + u32Min = (uint32_t) - 1; + u32MinDSCnt = 0ul; + u32MinClkDiv = 0ul; + + for(u32DSCnt = 6ul; u32DSCnt <= 0x10ul; u32DSCnt++) /* DSCNT could be 0x5~0xF */ + { + u32ClkDiv = u32Div / u32DSCnt; + + if(u32ClkDiv > 0x400ul) + { + u32ClkDiv = 0x400ul; + u32Tmp = u32Div - (u32ClkDiv * u32DSCnt); + u32Tmp2 = u32Tmp + 1ul; + } + else + { + u32Tmp = u32Div - (u32ClkDiv * u32DSCnt); + u32Tmp2 = ((u32ClkDiv + 1ul) * u32DSCnt) - u32Div; + } + + if(u32Tmp >= u32Tmp2) + { + u32ClkDiv = u32ClkDiv + 1ul; + } + else u32Tmp2 = u32Tmp; + + if(u32Tmp2 < u32Min) + { + u32Min = u32Tmp2; + u32MinDSCnt = u32DSCnt; + u32MinClkDiv = u32ClkDiv; + + /* Break when get good results */ + if(u32Min == 0ul) + { + break; + } + } + } + + } + + /* Set USCI_UART baud rate */ + uuart->BRGEN = ((u32MinClkDiv - 1ul) << UUART_BRGEN_CLKDIV_Pos) | + ((u32MinDSCnt - 1ul) << UUART_BRGEN_DSCNT_Pos) | + ((u32PDSCnt - 1ul) << UUART_BRGEN_PDSCNT_Pos); + } + else + { + u32PDSCnt = ((uuart->BRGEN & UUART_BRGEN_PDSCNT_Msk) >> UUART_BRGEN_PDSCNT_Pos) + 1ul; + u32MinDSCnt = ((uuart->BRGEN & UUART_BRGEN_DSCNT_Msk) >> UUART_BRGEN_DSCNT_Pos) + 1ul; + u32MinClkDiv = ((uuart->BRGEN & UUART_BRGEN_CLKDIV_Msk) >> UUART_BRGEN_CLKDIV_Pos) + 1ul; + } + + /* Set USCI_UART line configuration */ + uuart->LINECTL = (uuart->LINECTL & ~UUART_LINECTL_DWIDTH_Msk) | u32data_width; + uuart->PROTCTL = (uuart->PROTCTL & ~(UUART_PROTCTL_STICKEN_Msk | UUART_PROTCTL_EVENPARITY_Msk | + UUART_PROTCTL_PARITYEN_Msk)) | u32parity; + uuart->PROTCTL = (uuart->PROTCTL & ~UUART_PROTCTL_STOPB_Msk) | u32stop_bits; + + return (u32PCLKFreq / u32PDSCnt / u32MinDSCnt / u32MinClkDiv); +} + + +/** + * @brief Write USCI_UART data + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * @param[in] pu8TxBuf The buffer to send the data to USCI transmission buffer. + * @param[out] u32WriteBytes The byte number of data. + * + * @return Transfer byte count + * + * @details The function is to write data into TX buffer to transmit data by USCI_UART. + */ +uint32_t UUART_Write(UUART_T* uuart, uint8_t pu8TxBuf[], uint32_t u32WriteBytes) +{ + uint32_t u32Count, u32delayno; + + for(u32Count = 0ul; u32Count != u32WriteBytes; u32Count++) + { + u32delayno = 0ul; + while((uuart->BUFSTS & UUART_BUFSTS_TXEMPTY_Msk) == 0ul) /* Wait Tx empty */ + { + u32delayno++; + if(u32delayno >= 0x40000000ul) + { + break; + } + } + + if(u32delayno >= 0x40000000ul) + { + break; + } + + uuart->TXDAT = (uint8_t)pu8TxBuf[u32Count]; /* Send USCI_UART Data to buffer */ + } + + return u32Count; +} + + +/** + * @brief Enable USCI_UART Wake-up Function + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * @param[in] u32WakeupMode The wakeup mode of USCI_UART module. +* - \ref UUART_PROTCTL_DATWKEN_Msk : Data wake-up Mode +* - \ref UUART_PROTCTL_CTSWKEN_Msk : nCTS wake-up Mode + * + * @return None + * + * @details The function is used to enable Wake-up function of USCI_UART. + */ +void UUART_EnableWakeup(UUART_T* uuart, uint32_t u32WakeupMode) +{ + uuart->PROTCTL |= u32WakeupMode; + uuart->WKCTL |= UUART_WKCTL_WKEN_Msk; +} + + +/** + * @brief Disable USCI_UART Wake-up Function + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * + * @return None + * + * @details The function is used to disable Wake-up function of USCI_UART. + */ +void UUART_DisableWakeup(UUART_T* uuart) +{ + uuart->PROTCTL &= ~(UUART_PROTCTL_DATWKEN_Msk | UUART_PROTCTL_CTSWKEN_Msk); + uuart->WKCTL &= ~UUART_WKCTL_WKEN_Msk; +} + +/** + * @brief Enable USCI_UART auto flow control + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * + * @return None + * + * @details The function is used to enable USCI_UART auto flow control. + */ +void UUART_EnableFlowCtrl(UUART_T* uuart) +{ + /* Set RTS signal is low level active */ + uuart->LINECTL &= ~UUART_LINECTL_CTLOINV_Msk; + + /* Set CTS signal is low level active */ + uuart->CTLIN0 &= ~UUART_CTLIN0_ININV_Msk; + + /* Enable CTS and RTS auto flow control function */ + uuart->PROTCTL |= UUART_PROTCTL_RTSAUTOEN_Msk | UUART_PROTCTL_CTSAUTOEN_Msk; +} + +/** + * @brief Disable USCI_UART auto flow control + * + * @param[in] uuart The pointer of the specified USCI_UART module. + * + * @return None + * + * @details The function is used to disable USCI_UART auto flow control. + */ +void UUART_DisableFlowCtrl(UUART_T* uuart) +{ + /* Disable CTS and RTS auto flow control function */ + uuart->PROTCTL &= ~(UUART_PROTCTL_RTSAUTOEN_Msk | UUART_PROTCTL_CTSAUTOEN_Msk); +} + +/*@}*/ /* end of group USCI_UART_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group USCI_UART_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_wdt.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_wdt.c new file mode 100644 index 0000000000..5575df4cd3 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_wdt.c @@ -0,0 +1,73 @@ +/**************************************************************************//** + * @file wdt.c + * @version V3.00 + * $Revision: 3 $ + * $Date: 18/04/03 5:38p $ + * @brief M031 series Watchdog Timer(WDT) driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#include "NuMicro.h" + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup WDT_Driver WDT Driver + @{ +*/ + +/** @addtogroup WDT_EXPORTED_FUNCTIONS WDT Exported Functions + @{ +*/ + +/** + * @brief Initialize WDT and start counting + * + * @param[in] u32TimeoutInterval Time-out interval period of WDT module. Valid values are: + * - \ref WDT_TIMEOUT_2POW4 + * - \ref WDT_TIMEOUT_2POW6 + * - \ref WDT_TIMEOUT_2POW8 + * - \ref WDT_TIMEOUT_2POW10 + * - \ref WDT_TIMEOUT_2POW12 + * - \ref WDT_TIMEOUT_2POW14 + * - \ref WDT_TIMEOUT_2POW16 + * - \ref WDT_TIMEOUT_2POW18 + * - \ref WDT_TIMEOUT_2POW20 + * @param[in] u32ResetDelay Configure WDT time-out reset delay period. Valid values are: + * - \ref WDT_RESET_DELAY_1026CLK + * - \ref WDT_RESET_DELAY_130CLK + * - \ref WDT_RESET_DELAY_18CLK + * - \ref WDT_RESET_DELAY_3CLK + * @param[in] u32EnableReset Enable WDT time-out reset system function. Valid values are TRUE and FALSE. + * @param[in] u32EnableWakeup Enable WDT time-out wake-up system function. Valid values are TRUE and FALSE. + * + * @return None + * + * @details This function makes WDT module start counting with different time-out interval, reset delay period and choose to \n + * enable or disable WDT time-out reset system or wake-up system. + * @note Please make sure that Register Write-Protection Function has been disabled before using this function. + */ +void WDT_Open(uint32_t u32TimeoutInterval, + uint32_t u32ResetDelay, + uint32_t u32EnableReset, + uint32_t u32EnableWakeup) +{ + WDT->ALTCTL = u32ResetDelay; + + WDT->CTL = u32TimeoutInterval | WDT_CTL_WDTEN_Msk | + (u32EnableReset << WDT_CTL_RSTEN_Pos) | + (u32EnableWakeup << WDT_CTL_WKEN_Pos); + return; +} + +/*@}*/ /* end of group WDT_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group WDT_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/libraries/m031/StdDriver/src/nu_wwdt.c b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_wwdt.c new file mode 100644 index 0000000000..a9e5c38f1d --- /dev/null +++ b/bsp/nuvoton/libraries/m031/StdDriver/src/nu_wwdt.c @@ -0,0 +1,73 @@ +/**************************************************************************//** + * @file wwdt.c + * @version V3.00 + * $Revision: 3 $ + * $Date: 18/04/03 5:38p $ + * @brief M031 series Window Watchdog Timer(WWDT) driver source file + * + * @note + * SPDX-License-Identifier: Apache-2.0 + * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved. + *****************************************************************************/ +#include "NuMicro.h" + + +/** @addtogroup Standard_Driver Standard Driver + @{ +*/ + +/** @addtogroup WWDT_Driver WWDT Driver + @{ +*/ + +/** @addtogroup WWDT_EXPORTED_FUNCTIONS WWDT Exported Functions + @{ +*/ + +/** + * @brief Open WWDT function to start counting + * + * @param[in] u32PreScale Prescale period for the WWDT counter period. Valid values are: + * - \ref WWDT_PRESCALER_1 + * - \ref WWDT_PRESCALER_2 + * - \ref WWDT_PRESCALER_4 + * - \ref WWDT_PRESCALER_8 + * - \ref WWDT_PRESCALER_16 + * - \ref WWDT_PRESCALER_32 + * - \ref WWDT_PRESCALER_64 + * - \ref WWDT_PRESCALER_128 + * - \ref WWDT_PRESCALER_192 + * - \ref WWDT_PRESCALER_256 + * - \ref WWDT_PRESCALER_384 + * - \ref WWDT_PRESCALER_512 + * - \ref WWDT_PRESCALER_768 + * - \ref WWDT_PRESCALER_1024 + * - \ref WWDT_PRESCALER_1536 + * - \ref WWDT_PRESCALER_2048 + * @param[in] u32CmpValue Setting the window compared value. Valid values are between 0x0 to 0x3F. + * @param[in] u32EnableInt Enable WWDT interrupt function. Valid values are TRUE and FALSE. + * + * @return None + * + * @details This function make WWDT module start counting with different counter period and compared window value. + * @note Application can call this function only once after boot up. + */ +void WWDT_Open(uint32_t u32PreScale, + uint32_t u32CmpValue, + uint32_t u32EnableInt) +{ + WWDT->CTL = u32PreScale | + (u32CmpValue << WWDT_CTL_CMPDAT_Pos) | + ((u32EnableInt == TRUE) ? WWDT_CTL_INTEN_Msk : 0U) | + WWDT_CTL_WWDTEN_Msk; + return; +} + +/*@}*/ /* end of group WWDT_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group WWDT_Driver */ + +/*@}*/ /* end of group Standard_Driver */ + +/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/ + diff --git a/bsp/nuvoton/libraries/m031/rtt_port/Kconfig b/bsp/nuvoton/libraries/m031/rtt_port/Kconfig new file mode 100644 index 0000000000..1b1d57fca3 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/Kconfig @@ -0,0 +1,634 @@ +config SOC_SERIES_M032 + bool + select ARCH_ARM_CORTEX_M0 + select SOC_FAMILY_NUMICRO + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + + config BSP_USE_STDDRIVER_SOURCE + bool "Build StdDriver source" + default n + + menuconfig BSP_USING_PDMA + bool "Enable Peripheral Direct Memory Access Controller(PDMA)" + default y + + if BSP_USING_PDMA + config NU_PDMA_MEMFUN_ACTOR_MAX + int "Specify maximum mem actor for memfun" + range 1 4 + default 4 + + config NU_PDMA_SGTBL_POOL_SIZE + int "Specify maximum scatter-gather pool size" + range 1 32 + default 16 + endif + + config BSP_USING_FMC + bool "Enable Flash Memory Controller(FMC)" + select PKG_USING_FAL + default n + + config BSP_USING_GPIO + bool "Enable General Purpose I/O(GPIO)" + select RT_USING_PIN + default y + + menuconfig BSP_USING_CLK + bool "Enable Clock Controller(CLK)" + select RT_USING_PM + select BSP_USING_TMR + default y + help + Choose this option if you need CLK/PM function. + Notice: Enable the option will hold timer3 resource + + if BSP_USING_CLK + config NU_CLK_INVOKE_WKTMR + bool "Enable SPD1 and DPD mode wakeup timer. (About 6.6 Secs)" + default y + endif + + menuconfig BSP_USING_RTC + bool "Enable Real Time Clock(RTC)" + select RT_USING_RTC + + config NU_RTC_SUPPORT_IO_RW + bool "Support device RW entry" + depends on BSP_USING_RTC && RT_USING_RTC + + config NU_RTC_SUPPORT_MSH_CMD + bool "Support module shell command" + depends on BSP_USING_RTC && RT_USING_RTC + + menuconfig BSP_USING_ADC + bool "Enable Enhanced Analog-to-Digital Converter(ADC)" + select RT_USING_ADC + + if BSP_USING_ADC + config BSP_USING_ADC0 + bool "Enable ADC0" + endif + + menuconfig BSP_USING_TMR + bool "Enable Timer Controller(TIMER)" + + config BSP_USING_TIMER + bool + + config BSP_USING_TIMER_CAPTURE + bool + + config BSP_USING_TMR0 + bool "Enable TIMER0" + depends on BSP_USING_TMR + + if BSP_USING_TMR0 + choice + prompt "Select TIMER0 function mode" + + config BSP_USING_TIMER0 + select BSP_USING_TIMER + select RT_USING_HWTIMER + bool "TIMER" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_TIMER0_CAPTURE + select BSP_USING_TIMER_CAPTURE + select RT_USING_INPUT_CAPTURE + bool "TIMER CAPTURE" + help + Choose this option if you need CAPTURE function mode. + + endchoice + endif + + config BSP_USING_TMR1 + bool "Enable TIMER1" + depends on BSP_USING_TMR + + if BSP_USING_TMR1 + choice + prompt "Select TIMER1 function mode" + + config BSP_USING_TIMER1 + select BSP_USING_TIMER + select RT_USING_HWTIMER + bool "TIMER" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_TIMER1_CAPTURE + select BSP_USING_TIMER_CAPTURE + select RT_USING_INPUT_CAPTURE + bool "TIMER CAPTURE" + help + Choose this option if you need CAPTURE function mode. + endchoice + endif + + config BSP_USING_TMR2 + bool "Enable TIMER2" + depends on BSP_USING_TMR + + if BSP_USING_TMR2 + choice + prompt "Select TIMER2 function mode" + + config BSP_USING_TIMER2 + select BSP_USING_TIMER + select RT_USING_HWTIMER + bool "TIMER" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_TIMER2_CAPTURE + select BSP_USING_TIMER_CAPTURE + select RT_USING_INPUT_CAPTURE + bool "TIMER CAPTURE" + help + Choose this option if you need CAPTURE function mode. + endchoice + endif + + config BSP_USING_TMR3 + bool "Enable TIMER3" + depends on BSP_USING_TMR && !BSP_USING_CLK + + if BSP_USING_TMR3 + choice + prompt "Select TIMER3 function mode" + + config BSP_USING_TIMER3 + select BSP_USING_TIMER + select RT_USING_HWTIMER + bool "TIMER" + help + Choose this option if you need TIMER function mode. + + config BSP_USING_TIMER3_CAPTURE + select BSP_USING_TIMER_CAPTURE + select RT_USING_INPUT_CAPTURE + bool "TIMER CAPTURE" + help + Choose this option if you need CAPTURE function mode. + endchoice + endif + + menuconfig BSP_USING_UART + bool "Enable Universal Asynchronous Receiver/Transmitters(UART)" + select RT_USING_SERIAL + + if BSP_USING_UART + config BSP_USING_UART0 + bool "Enable UART0" + + config BSP_USING_UART0_TX_DMA + bool "Enable UART0 TX DMA" + depends on BSP_USING_UART0 && RT_SERIAL_USING_DMA + + config BSP_USING_UART0_RX_DMA + bool "Enable UART0 RX DMA" + depends on BSP_USING_UART0 && RT_SERIAL_USING_DMA + + config BSP_USING_UART1 + bool "Enable UART1" + + config BSP_USING_UART1_TX_DMA + bool "Enable UART1 TX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + + config BSP_USING_UART1_RX_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + + config BSP_USING_UART2 + bool "Enable UART2" + + config BSP_USING_UART2_TX_DMA + bool "Enable UART2 TX DMA" + depends on BSP_USING_UART2 && RT_SERIAL_USING_DMA + + config BSP_USING_UART2_RX_DMA + bool "Enable UART2 RX DMA" + depends on BSP_USING_UART2 && RT_SERIAL_USING_DMA + + config BSP_USING_UART3 + bool "Enable UART3" + + config BSP_USING_UART3_TX_DMA + bool "Enable UART3 TX DMA" + depends on BSP_USING_UART3 && RT_SERIAL_USING_DMA + + config BSP_USING_UART3_RX_DMA + bool "Enable UART3 RX DMA" + depends on BSP_USING_UART3 && RT_SERIAL_USING_DMA + + config BSP_USING_UART4 + bool "Enable UART4" + + config BSP_USING_UART4_TX_DMA + bool "Enable UART4 TX DMA" + depends on BSP_USING_UART4 && RT_SERIAL_USING_DMA + + config BSP_USING_UART4_RX_DMA + bool "Enable UART4 RX DMA" + depends on BSP_USING_UART4 && RT_SERIAL_USING_DMA + + config BSP_USING_UART5 + bool "Enable UART5" + + config BSP_USING_UART5_TX_DMA + bool "Enable UART5 TX DMA" + depends on BSP_USING_UART5 && RT_SERIAL_USING_DMA + + config BSP_USING_UART5_RX_DMA + bool "Enable UART5 RX DMA" + depends on BSP_USING_UART5 && RT_SERIAL_USING_DMA + + config BSP_USING_UART6 + bool "Enable UART6" + + config BSP_USING_UART6_TX_DMA + bool "Enable UART6 TX DMA" + depends on BSP_USING_UART6 && RT_SERIAL_USING_DMA + + config BSP_USING_UART6_RX_DMA + bool "Enable UART6 RX DMA" + depends on BSP_USING_UART6 && RT_SERIAL_USING_DMA + + config BSP_USING_UART7 + bool "Enable UART7" + + config BSP_USING_UART7_TX_DMA + bool "Enable UART7 TX DMA" + depends on BSP_USING_UART7 && RT_SERIAL_USING_DMA + + config BSP_USING_UART7_RX_DMA + bool "Enable UART7 RX DMA" + depends on BSP_USING_UART7 && RT_SERIAL_USING_DMA + endif + + menuconfig BSP_USING_I2C + bool "Enable I2C Serial Interface Controller(I2C)" + select RT_USING_I2C + + if BSP_USING_I2C + config BSP_USING_I2C0 + bool "Enable I2C0" + + config BSP_USING_I2C1 + bool "Enable I2C1" + endif + + menuconfig BSP_USING_USCI + bool "Enable Universal Serial Control Interface Controller(USCI)" + + if BSP_USING_USCI + + config BSP_USING_UUART + bool + + config BSP_USING_USPI + bool + + config BSP_USING_USPI_PDMA + bool + default n + + config BSP_USING_UI2C + bool + + config BSP_USING_USCI0 + bool "Enable USCI0" + + if BSP_USING_USCI0 + choice + prompt "Select USCI0 function mode" + + config BSP_USING_UUART0 + select RT_USING_SERIAL + select BSP_USING_UUART + bool "UUART0" + help + Choose this option if you need UART function mode. + + config BSP_USING_UI2C0 + select RT_USING_I2C + select BSP_USING_UI2C + bool "UI2C0" + help + Choose this option if you need I2C function mode. + + config BSP_USING_USPI0 + select RT_USING_SPI + select BSP_USING_USPI + bool "USPI0" + help + Choose this option if you need SPI function mode. + endchoice + + config BSP_USING_UUART0_TX_DMA + bool "Enable UUART0 TX DMA" + depends on BSP_USING_UUART0 && RT_SERIAL_USING_DMA + + config BSP_USING_UUART0_RX_DMA + bool "Enable UUART0 RX DMA" + depends on BSP_USING_UUART0 && RT_SERIAL_USING_DMA + + config BSP_USING_USPI0_PDMA + bool "Use PDMA for data transferring" + select BSP_USING_USPI_PDMA + depends on BSP_USING_USPI0 + endif + + config BSP_USING_USCI1 + bool "Enable USCI1" + + if BSP_USING_USCI1 + choice + prompt "Select USCI1 function mode" + + config BSP_USING_UUART1 + select RT_USING_SERIAL + select BSP_USING_UUART + bool "UUART1" + help + Choose this option if you need UART function mode. + + config BSP_USING_UI2C1 + select RT_USING_I2C + select BSP_USING_UI2C + bool "UI2C1" + help + Choose this option if you need I2C function mode. + + config BSP_USING_USPI1 + select RT_USING_SPI + select BSP_USING_USPI + bool "USPI1" + help + Choose this option if you need SPI function mode. + endchoice + + config BSP_USING_UUART1_TX_DMA + bool "Enable UUART1 TX DMA" + depends on BSP_USING_UUART1 && RT_SERIAL_USING_DMA + + config BSP_USING_UUART1_RX_DMA + bool "Enable UUART1 RX DMA" + depends on BSP_USING_UUART1 && RT_SERIAL_USING_DMA + + config BSP_USING_USPI1_PDMA + bool "Use PDMA for data transferring" + select BSP_USING_USPI_PDMA + depends on BSP_USING_USPI1 + endif + + endif + + menuconfig BSP_USING_BPWM + bool "Enable Basic PWM Generator and Capture Timer(BPWM)" + select RT_USING_PWM + + if BSP_USING_BPWM + + config BSP_USING_BPWM_CAPTURE + bool + + choice + prompt "Select BPWM0 function mode" + config BSP_USING_BPWM0 + select RT_USING_PWM + bool "Enable BPWM0" + help + Choose this option if you need PWM function mode. + + config BSP_USING_BPWM0_CAPTURE + select RT_USING_INPUT_CAPTURE + select BSP_USING_BPWM_CAPTURE + bool "Enable BPWM0_CAPTURE" + help + Choose this option if you need PWM capture function mode. + endchoice + + if BSP_USING_BPWM0_CAPTURE + config BSP_USING_BPWM0_CAPTURE_CHMSK + hex "Specify channel mask for BPWM0_CAP channel." + range 0 0x3F + default 0 + endif + + choice + prompt "Select BPWM1 function mode" + config BSP_USING_BPWM1 + select RT_USING_PWM + bool "Enable BPWM1" + help + Choose this option if you need PWM function mode. + + config BSP_USING_BPWM1_CAPTURE + select RT_USING_INPUT_CAPTURE + select BSP_USING_BPWM_CAPTURE + bool "Enable BPWM1_CAPTURE" + help + Choose this option if you need PWM capture function mode. + endchoice + + if BSP_USING_BPWM1_CAPTURE + config BSP_USING_BPWM1_CAPTURE_CHMSK + hex "Specify channel mask for BPWM1_CAP channel." + range 0 0x3F + default 0 + endif + + endif + + menuconfig BSP_USING_PWM + bool "Enable PWM Generator and Capture Timer(PWM)" + + if BSP_USING_PWM + + config BSP_USING_PWM_CAPTURE + bool + + choice + prompt "Select PWM0 function mode" + config BSP_USING_PWM0 + select RT_USING_PWM + bool "Enable PWM0" + help + Choose this option if you need PWM function mode. + + config BSP_USING_PWM0_CAPTURE + select RT_USING_INPUT_CAPTURE + select BSP_USING_PWM_CAPTURE + bool "Enable PWM0_CAPTURE" + help + Choose this option if you need PWM capture function mode. + endchoice + + if BSP_USING_PWM0_CAPTURE + config BSP_USING_PWM0_CAPTURE_CHMSK + hex "Specify channel mask for PWM0_CAP channel." + range 0 0x3F + default 0 + endif + + choice + prompt "Select PWM1 function mode" + config BSP_USING_PWM1 + select RT_USING_PWM + bool "Enable PWM1" + help + Choose this option if you need PWM function mode. + + config BSP_USING_PWM1_CAPTURE + select RT_USING_INPUT_CAPTURE + select BSP_USING_PWM_CAPTURE + bool "Enable PWM1_CAPTURE" + help + Choose this option if you need PWM capture function mode. + endchoice + + if BSP_USING_PWM1_CAPTURE + config BSP_USING_PWM1_CAPTURE_CHMSK + hex "Specify channel mask for PWM1_CAP channel." + range 0 0x3F + default 0 + endif + + endif + + menuconfig BSP_USING_SPI + bool "Enable Serial Peripheral Interface(SPI)" + select RT_USING_SPI + + if BSP_USING_SPI + config BSP_USING_SPI_PDMA + bool + default n + + config BSP_USING_SPII2S + bool + default n + + choice + prompt "Select SPI0 function mode" + config BSP_USING_SPI0_NONE + bool "NONE" + help + Choose this option if you need not SPI0. + + config BSP_USING_SPI0 + bool "Enable SPI0" + help + Choose this option if you need SPI function mode. + + config BSP_USING_SPII2S0 + select RT_USING_AUDIO + select BSP_USING_SPII2S + bool "Enable SPII2S0" + help + Choose this option if you need SPII2S function mode. + endchoice + + if BSP_USING_SPI0 + config BSP_USING_SPI0_PDMA + bool "Enable PDMA for SPI0" + select BSP_USING_SPI_PDMA + depends on BSP_USING_SPI0 + endif + + endif + + menuconfig BSP_USING_QSPI + bool "Enable Quad Serial Peripheral Interface(QSPI)" + select RT_USING_SPI + select RT_USING_QSPI + select BSP_USING_SPI + + if BSP_USING_QSPI + config BSP_USING_QSPI0 + bool "Enable QSPI0" + + config BSP_USING_QSPI0_PDMA + bool "Enable PDMA for QSPI0" + select BSP_USING_SPI_PDMA + depends on BSP_USING_QSPI0 + endif + + menuconfig BSP_USING_CRC + bool "Enable Cyclic Redundancy Check Generator(CRC)" + select BSP_USING_CRYPTO + select RT_USING_HWCRYPTO + select RT_HWCRYPTO_USING_CRC + select RT_HWCRYPTO_USING_CRC_07 + select RT_HWCRYPTO_USING_CRC_8005 + select RT_HWCRYPTO_USING_CRC_1021 + select RT_HWCRYPTO_USING_CRC_04C11DB7 + + if BSP_USING_CRC + config NU_CRC_USE_PDMA + bool "Use PDMA for data transferring." + select BSP_USING_PDMA + default y + endif + + menuconfig BSP_USING_SOFT_I2C + bool "Enable SOFT I2C" + + if BSP_USING_SOFT_I2C + config BSP_USING_SOFT_I2C0 + bool "Enable SOFT I2C0" + select RT_USING_I2C + select RT_USING_I2C_BITOPS + default n + + if BSP_USING_SOFT_I2C0 + config BSP_SOFT_I2C0_SCL_PIN + hex "Specify the pin index of SCL of SOFT I2C0" + range 0 0x7F + default 0x18 + + config BSP_SOFT_I2C0_SDA_PIN + hex "Specify the pin index of SDA of SOFT I2C0" + range 0 0x7F + default 0x17 + endif + + config BSP_USING_SOFT_I2C1 + bool "Enable SOFT I2C1" + select RT_USING_I2C + select RT_USING_I2C_BITOPS + default n + + if BSP_USING_SOFT_I2C1 + config BSP_SOFT_I2C1_SCL_PIN + hex "Specify the pin index of SCL of SOFT I2C1" + range 0 0x7F + default 0x0B + + config BSP_SOFT_I2C1_SDA_PIN + hex "Specify the pin index of SDA of SOFT I2C1" + range 0 0x7F + default 0x0A + endif + endif + + config BSP_USING_WDT + bool "Enable Watchdog Timer(WDT)" + select RT_USING_WDT + default y + + config BSP_USING_EBI + bool "Enable External Bus Interface(EBI)" + default n + + config BSP_USING_USBD + bool "Enable Full-Speed USB Device Controller(USBD)" + select RT_USING_USB_DEVICE + diff --git a/bsp/nuvoton/libraries/m031/rtt_port/SConscript b/bsp/nuvoton/libraries/m031/rtt_port/SConscript new file mode 100644 index 0000000000..54a599e9d7 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/SConscript @@ -0,0 +1,12 @@ +# RT-Thread building script for component + +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +CPPPATH = [cwd] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_adc.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_adc.c new file mode 100644 index 0000000000..4a9c9aa4c6 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_adc.c @@ -0,0 +1,154 @@ +/**************************************************************************//** +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-9-16 Philo First version +* +******************************************************************************/ + +#include +#include +#include "NuMicro.h" + +#ifdef BSP_USING_ADC + +/* Private define ---------------------------------------------------------------*/ + +/* Private Typedef --------------------------------------------------------------*/ +struct nu_adc +{ + struct rt_adc_device dev; + char *name; + ADC_T *adc_base; + int adc_reg_tab; + int adc_max_ch_num; + +}; +typedef struct nu_adc *nu_adc_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled); +static rt_err_t nu_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value); + +/* Public functions ------------------------------------------------------------*/ +int rt_hw_adc_init(void); + +/* Private variables ------------------------------------------------------------*/ + +static struct nu_adc nu_adc_arr [] = +{ +#if defined(BSP_USING_ADC0) + { + .name = "adc0", + .adc_base = ADC, + .adc_max_ch_num = 15, + }, +#endif + + {0} +}; + +static const struct rt_adc_ops nu_adc_ops = +{ + nu_adc_enabled, + nu_get_adc_value, +}; +typedef struct rt_adc_ops *rt_adc_ops_t; + + +/* nu_adc_enabled - Enable ADC clock and wait for ready */ +static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) +{ + + ADC_T *adc_base = ((nu_adc_t)device)->adc_base; + int *padc_reg_tab = &((nu_adc_t)device)->adc_reg_tab; + RT_ASSERT(device != RT_NULL); + + if (channel >= ((nu_adc_t)device)->adc_max_ch_num) + return -(RT_EINVAL); + + if (enabled) + { + ADC_POWER_ON(adc_base); + + if (*padc_reg_tab == 0) + { + ADC_Open(adc_base, ADC_ADCR_DIFFEN_SINGLE_END, ADC_ADCR_ADMD_SINGLE, (0x1 << channel)); + } + + *padc_reg_tab |= (0x1 << channel); + } + else + { + *padc_reg_tab &= ~(0x1 << channel); + + if (*padc_reg_tab == 0) + { + ADC_Close(adc_base); + } + + ADC_POWER_DOWN(adc_base); + } + + return RT_EOK; +} + +static rt_err_t nu_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) +{ + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(value != RT_NULL); + + ADC_T *adc_base = ((nu_adc_t)device)->adc_base; + int *padc_reg_tab = &((nu_adc_t)device)->adc_reg_tab; + + if (channel >= ((nu_adc_t)device)->adc_max_ch_num) + { + *value = 0xFFFFFFFF; + return -(RT_EINVAL); + } + + if ((*padc_reg_tab & (1 << channel)) == 0) + { + *value = 0xFFFFFFFF; + return -(RT_EBUSY); + } + + ADC_SET_INPUT_CHANNEL(adc_base, (0x1< + +#if defined(BSP_USING_BPWM) + +#define LOG_TAG "drv.bpwm" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include + +#include +#include +#include +#include "NuMicro.h" + +#define DEFAULT_DUTY 50 +#define DEFAULT_FREQ 1000 + +enum +{ + BPWM_START = -1, +#if defined(BSP_USING_BPWM0) + BPWM0_IDX, +#endif +#if defined(BSP_USING_BPWM1) + BPWM1_IDX, +#endif + BPWM_CNT +}; + +struct nu_bpwm +{ + struct rt_device_pwm dev; + char *name; + BPWM_T *bpwm_base; + rt_int32_t pwm_period_time; +}; + +typedef struct nu_bpwm *nu_bpwm_t; + +static struct nu_bpwm nu_bpwm_arr [] = +{ +#if defined(BSP_USING_BPWM0) + { + .name = "bpwm0", + .bpwm_base = BPWM0, + }, +#endif + +#if defined(BSP_USING_BPWM1) + { + .name = "bpwm1", + .bpwm_base = BPWM1, + }, +#endif + {0} +}; /* bpwm nu_epwm */ + +static rt_err_t nu_bpwm_control(struct rt_device_pwm *device, int cmd, void *arg); + +static struct rt_pwm_ops nu_bpwm_ops = +{ + .control = nu_bpwm_control +}; + +static rt_err_t nu_bpwm_enable(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration, rt_bool_t enable) +{ + rt_err_t result = RT_EOK; + + BPWM_T *pwm_base = ((nu_bpwm_t)device)->bpwm_base; + rt_uint32_t pwm_channel = configuration->channel; + + if (enable == RT_TRUE) + { + BPWM_EnableOutput(pwm_base, 1 << pwm_channel); + BPWM_Start(pwm_base, 1 << pwm_channel); + } + else if (enable == RT_FALSE) + { + BPWM_DisableOutput(pwm_base, 1 << pwm_channel); + BPWM_ForceStop(pwm_base, 1 << pwm_channel); + } + + return result; +} + +static rt_err_t nu_bpwm_set(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration) +{ + if ((configuration->period) <= 0) + return -(RT_ERROR); + rt_uint32_t pwm_freq, pwm_dutycycle; + BPWM_T *pwm_base = ((nu_bpwm_t)device)->bpwm_base; + rt_uint8_t pwm_channel = configuration->channel; + rt_uint32_t pwm_period = configuration->period; + rt_uint32_t pwm_pulse = configuration->pulse; + + pwm_dutycycle = (pwm_pulse * 100) / pwm_period; + + if (BPWM_GET_CNR(pwm_base, pwm_channel) != 0) + { + pwm_period = ((nu_bpwm_t)device)->pwm_period_time; + LOG_I("%s output frequency is determined, user can only change the duty\n", ((nu_bpwm_t)device)->name); + } + else + { + ((nu_bpwm_t)device)->pwm_period_time = pwm_period; + } + + pwm_freq = 1000000000 / pwm_period; + + + BPWM_ConfigOutputChannel(pwm_base, pwm_channel, pwm_freq, pwm_dutycycle) ; + + return RT_EOK; +} + +static rt_uint32_t nu_bpwm_clksr(struct rt_device_pwm *device) +{ + rt_uint32_t u32Src, u32BPWMClockSrc; + BPWM_T *pwm_base = ((nu_bpwm_t)device)->bpwm_base; + if (pwm_base == BPWM0) + { + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM0SEL_Msk; + } + else /* (bpwm == BPWM1) */ + { + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM1SEL_Msk; + } + + if (u32Src == 0U) + { + /* clock source is from PLL clock */ + u32BPWMClockSrc = CLK_GetPLLClockFreq(); + } + else + { + /* clock source is from PCLK */ + SystemCoreClockUpdate(); + if (pwm_base == BPWM0) + { + u32BPWMClockSrc = CLK_GetPCLK0Freq(); + } + else /* (bpwm == BPWM1) */ + { + u32BPWMClockSrc = CLK_GetPCLK1Freq(); + } + } + return u32BPWMClockSrc; +} + +static rt_err_t nu_bpwm_get(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration) +{ + rt_uint32_t pwm_real_period, pwm_real_duty, time_tick, u32BPWMClockSrc ; + + BPWM_T *pwm_base = ((nu_bpwm_t)device)->bpwm_base; + rt_uint32_t pwm_channel = configuration->channel; + rt_uint32_t pwm_prescale = pwm_base->CLKPSC; + rt_uint32_t pwm_period = BPWM_GET_CNR(pwm_base, pwm_channel); + rt_uint32_t pwm_pulse = BPWM_GET_CMR(pwm_base, pwm_channel); + + u32BPWMClockSrc = nu_bpwm_clksr(device); + time_tick = 1000000000000 / u32BPWMClockSrc; + + pwm_real_period = (((pwm_prescale + 1) * (pwm_period + 1)) * time_tick) / 1000; + pwm_real_duty = (((pwm_prescale + 1) * pwm_pulse * time_tick)) / 1000; + configuration->period = pwm_real_period; + configuration->pulse = pwm_real_duty; + + LOG_I("%s %d %d %d\n", ((nu_bpwm_t)device)->name, configuration->channel, configuration->period, configuration->pulse); + + return RT_EOK; +} + +static rt_err_t nu_bpwm_control(struct rt_device_pwm *device, int cmd, void *arg) +{ + struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + if (((configuration->channel) + 1) > BPWM_CHANNEL_NUM) + return -(RT_ERROR); + + switch (cmd) + { + case PWM_CMD_ENABLE: + return nu_bpwm_enable(device, configuration, RT_TRUE); + case PWM_CMD_DISABLE: + return nu_bpwm_enable(device, configuration, RT_FALSE); + case PWM_CMD_SET: + return nu_bpwm_set(device, configuration); + case PWM_CMD_GET: + return nu_bpwm_get(device, configuration); + default: + return RT_EINVAL; + } +} + +int rt_hw_bpwm_init(void) +{ + rt_err_t ret; + rt_uint8_t i; + + for (i = (BPWM_START + 1); i < BPWM_CNT; i++) + { + ret = rt_device_pwm_register(&nu_bpwm_arr[i].dev, nu_bpwm_arr[i].name, &nu_bpwm_ops, RT_NULL); + RT_ASSERT(ret == RT_EOK); + } + + return 0; +} + +INIT_DEVICE_EXPORT(rt_hw_bpwm_init); + +#endif diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_bpwm_capture.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_bpwm_capture.c new file mode 100644 index 0000000000..c18cf4e6bd --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_bpwm_capture.c @@ -0,0 +1,335 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-05 klcheng First version +* +******************************************************************************/ +#include + +#if defined(BSP_USING_BPWM_CAPTURE) +#if ((BSP_USING_BPWM0_CAPTURE_CHMSK+BSP_USING_BPWM1_CAPTURE_CHMSK)!=0) +#include +#include "NuMicro.h" + +/* Private typedef --------------------------------------------------------------*/ +typedef struct _bpwm_dev +{ + BPWM_T *bpwm_base; + IRQn_Type irq; + float fUsPerTick; +} nu_bpwm_dev_t; + +typedef struct _bpwm +{ + struct rt_inputcapture_device parent; + nu_bpwm_dev_t *bpwm_dev; + uint8_t u8Channel; + uint8_t u8DummyData; + uint32_t u32CurrentRisingCnt; + uint32_t u32CurrentFallingCnt; + uint32_t u32LastRisingCnt; + uint32_t u32LastFallingCnt; + rt_bool_t input_data_level; +} nu_capture_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us); + +/* Private define ---------------------------------------------------------------*/ +#define NU_DUMMY_DATA 2 /* First rising and falling edge should be ignore */ + +#define NU_NO_EDGE 0 +#define NU_RISING_EDGE 1 +#define NU_FALLING_EDGE 2 + +/* Public functions -------------------------------------------------------------*/ + + +/* Private variables ------------------------------------------------------------*/ +#if (BSP_USING_BPWM0_CAPTURE_CHMSK!=0) +static const char *nu_bpwm0_device_name[BPWM_CHANNEL_NUM] = { "bpwm0i0", "bpwm0i1", "bpwm0i2", "bpwm0i3", "bpwm0i4", "bpwm0i5"}; +static nu_capture_t *nu_bpwm0_capture[BPWM_CHANNEL_NUM] = {0}; +static nu_bpwm_dev_t nu_bpwm0_dev = {.bpwm_base = BPWM0}; +#endif + +#if (BSP_USING_BPWM1_CAPTURE_CHMSK!=0) +static const char *nu_bpwm1_device_name[BPWM_CHANNEL_NUM] = { "bpwm1i0", "bpwm1i1", "bpwm1i2", "bpwm1i3", "bpwm1i4", "bpwm1i5"}; +static nu_capture_t *nu_bpwm1_capture[BPWM_CHANNEL_NUM] = {0}; +static nu_bpwm_dev_t nu_bpwm1_dev = {.bpwm_base = BPWM1}; +#endif + +static struct rt_inputcapture_ops nu_capture_ops = +{ + .init = nu_capture_init, + .open = nu_capture_open, + .close = nu_capture_close, + .get_pulsewidth = nu_capture_get_pulsewidth, +}; + +/* Functions define ------------------------------------------------------------*/ +void bpwm_interrupt_handler(nu_capture_t *nu_capture[], uint32_t u32ChMsk) +{ + uint32_t u32Status; + + for (uint8_t i = 0; i < BPWM_CHANNEL_NUM ; i++) + { + if ((0x1 << i) & u32ChMsk) + { + if (nu_capture[i]->u8DummyData < NU_DUMMY_DATA) + { + nu_capture[i]->u8DummyData++; + } + else + { + u32Status = BPWM_GetCaptureIntFlag(nu_capture[i]->bpwm_dev->bpwm_base, nu_capture[i]->u8Channel); + + switch (u32Status) + { + case NU_NO_EDGE: + break; + case NU_RISING_EDGE: + BPWM_ClearCaptureIntFlag(nu_capture[i]->bpwm_dev->bpwm_base, nu_capture[i]->u8Channel, BPWM_CAPTURE_INT_RISING_LATCH); + nu_capture[i]->u32CurrentRisingCnt = BPWM_GET_CAPTURE_RISING_DATA(nu_capture[i]->bpwm_dev->bpwm_base, nu_capture[i]->u8Channel); + rt_hw_inputcapture_isr(&nu_capture[i]->parent, nu_capture[i]->input_data_level); + + break; + case NU_FALLING_EDGE: + BPWM_ClearCaptureIntFlag(nu_capture[i]->bpwm_dev->bpwm_base, nu_capture[i]->u8Channel, BPWM_CAPTURE_INT_FALLING_LATCH); + nu_capture[i]->u32CurrentFallingCnt = BPWM_GET_CAPTURE_FALLING_DATA(nu_capture[i]->bpwm_dev->bpwm_base, nu_capture[i]->u8Channel); + rt_hw_inputcapture_isr(&nu_capture[i]->parent, nu_capture[i]->input_data_level); + + break; + default: + BPWM_ClearCaptureIntFlag(nu_capture[i]->bpwm_dev->bpwm_base, nu_capture[i]->u8Channel, BPWM_CAPTURE_INT_RISING_LATCH | BPWM_CAPTURE_INT_FALLING_LATCH); + BPWM_GET_CAPTURE_RISING_DATA(nu_capture[i]->bpwm_dev->bpwm_base, nu_capture[i]->u8Channel); + BPWM_GET_CAPTURE_FALLING_DATA(nu_capture[i]->bpwm_dev->bpwm_base, nu_capture[i]->u8Channel); + + break; + } + } + } + } +} + +#if (BSP_USING_BPWM0_CAPTURE_CHMSK!=0) +void BPWM0_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + bpwm_interrupt_handler(nu_bpwm0_capture, BSP_USING_BPWM0_CAPTURE_CHMSK); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif //(BSP_USING_BPWM0_CAPTURE_CHMSK!=0) + +#if (BSP_USING_BPWM1_CAPTURE_CHMSK!=0) +void BPWM1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + bpwm_interrupt_handler(nu_bpwm1_capture, BSP_USING_BPWM1_CAPTURE_CHMSK); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif //(BSP_USING_BPWM1_CAPTURE_CHMSK!=0) + +static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us) +{ + rt_err_t ret = RT_EOK; + nu_capture_t *nu_capture; + float fTempCnt; + + nu_capture = (nu_capture_t *)inputcapture; + + if (nu_capture->u32CurrentFallingCnt) + { + if (nu_capture->u32CurrentFallingCnt > nu_capture->u32LastRisingCnt) + fTempCnt = nu_capture->u32CurrentFallingCnt - nu_capture->u32LastRisingCnt; + else /* Overrun case */ + fTempCnt = nu_capture->u32CurrentFallingCnt + (0x10000 - nu_capture->u32LastRisingCnt); + + *pulsewidth_us = fTempCnt * nu_capture->bpwm_dev->fUsPerTick; + nu_capture->input_data_level = RT_FALSE; + nu_capture->u32LastFallingCnt = nu_capture->u32CurrentFallingCnt; + nu_capture->u32CurrentFallingCnt = 0; + } + else if (nu_capture->u32CurrentRisingCnt) + { + if (nu_capture->u32CurrentRisingCnt > nu_capture->u32LastFallingCnt) + fTempCnt = nu_capture->u32CurrentRisingCnt - nu_capture->u32LastFallingCnt; + else /* Overrun case */ + fTempCnt = nu_capture->u32CurrentRisingCnt + (0x10000 - nu_capture->u32LastFallingCnt); + + *pulsewidth_us = fTempCnt * nu_capture->bpwm_dev->fUsPerTick; + nu_capture->input_data_level = RT_TRUE; + nu_capture->u32LastRisingCnt = nu_capture->u32CurrentRisingCnt; + nu_capture->u32CurrentRisingCnt = 0; + } + else + { + ret = RT_ERROR; + } + return -(ret); +} + +static void bpwm_config(nu_capture_t *nu_capture) +{ + /* Set capture time as 500 nano second */ + nu_capture->bpwm_dev->fUsPerTick = (float)BPWM_ConfigCaptureChannel(nu_capture->bpwm_dev->bpwm_base, 0, 500, 0) / 1000; + + /* Enable BPWM NVIC interrupt */ + NVIC_EnableIRQ(nu_capture->bpwm_dev->irq); + + /* Set counter type as up count */ + BPWM_SET_ALIGNED_TYPE(nu_capture->bpwm_dev->bpwm_base, 0, BPWM_UP_COUNTER); + + /* Enable BPWM Timer */ + BPWM_Start(nu_capture->bpwm_dev->bpwm_base, 0); +} + +static rt_err_t nu_bpwm_init(nu_capture_t *nu_capture) +{ + rt_err_t ret = RT_ERROR; + static rt_bool_t bBPWM0Inited = RT_FALSE; + static rt_bool_t bBPWM1Inited = RT_FALSE; + + if (nu_capture->bpwm_dev->bpwm_base == BPWM0) + { + if (bBPWM0Inited == RT_FALSE) + { + /* Enable BPWM0 clock */ + SYS_UnlockReg(); + CLK_EnableModuleClock(BPWM0_MODULE); + CLK_SetModuleClock(BPWM0_MODULE, CLK_CLKSEL2_BPWM0SEL_PCLK0, 0); + SYS_LockReg(); + bpwm_config(nu_capture); + bBPWM0Inited = RT_TRUE; + } + ret = RT_EOK; + } + else if (nu_capture->bpwm_dev->bpwm_base == BPWM1) + { + if (bBPWM1Inited == RT_FALSE) + { + /* Enable BPWM1 clock */ + SYS_UnlockReg(); + CLK_EnableModuleClock(BPWM1_MODULE); + CLK_SetModuleClock(BPWM1_MODULE, CLK_CLKSEL2_BPWM1SEL_PCLK1, 0); + SYS_LockReg(); + bpwm_config(nu_capture); + bBPWM1Inited = RT_TRUE; + } + ret = RT_EOK; + } + + return -(ret); +} + +static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture) +{ + rt_err_t ret = RT_EOK; + nu_capture_t *nu_capture; + + RT_ASSERT(inputcapture != RT_NULL); + + nu_capture = (nu_capture_t *) inputcapture; + + if (nu_bpwm_init(nu_capture) != RT_EOK) + { + rt_kprintf("Failed to initialize BPWM.\n"); + ret = RT_ERROR; + } + + return -(ret); +} + +static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture) +{ + nu_capture_t *nu_capture; + + RT_ASSERT(inputcapture != RT_NULL); + + nu_capture = (nu_capture_t *) inputcapture; + + /* Enable capture rising/falling edge interrupt */ + BPWM_EnableCaptureInt(nu_capture->bpwm_dev->bpwm_base, nu_capture->u8Channel, BPWM_CAPTURE_INT_FALLING_LATCH | BPWM_CAPTURE_INT_RISING_LATCH); + + /* Enable Capture Function for BPWM */ + BPWM_EnableCapture(nu_capture->bpwm_dev->bpwm_base, 0x1 << nu_capture->u8Channel); + + return RT_EOK; +} + +static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture) +{ + nu_capture_t *nu_capture; + + RT_ASSERT(inputcapture != RT_NULL); + + nu_capture = (nu_capture_t *) inputcapture; + + /* Enable Capture Function for BPWM */ + BPWM_DisableCapture(nu_capture->bpwm_dev->bpwm_base, 0x1 << nu_capture->u8Channel); + + /* Disable capture rising/falling edge interrupt */ + BPWM_DisableCaptureInt(nu_capture->bpwm_dev->bpwm_base, nu_capture->u8Channel, BPWM_CAPTURE_INT_FALLING_LATCH | BPWM_CAPTURE_INT_RISING_LATCH); + + return RT_EOK; +} + +static void bpwm_init(nu_capture_t *nu_capture, uint8_t u8Channel, nu_bpwm_dev_t *bpwm_dev, const char *device_name, IRQn_Type irq) +{ + nu_capture->bpwm_dev = bpwm_dev; + nu_capture->bpwm_dev->irq = irq; + nu_capture->u8Channel = u8Channel; + nu_capture->u8DummyData = 0; + nu_capture->u32CurrentFallingCnt = 0; + nu_capture->u32CurrentRisingCnt = 0; + nu_capture->u32LastRisingCnt = 0; + nu_capture->u32LastFallingCnt = 0; + nu_capture->parent.ops = &nu_capture_ops; + + /* register inputcapture device */ + rt_device_inputcapture_register(&nu_capture->parent, device_name, &nu_capture); +} + +/* Init and register bpwm capture */ +static int nu_bpwm_capture_device_init(void) +{ + for (int i = 0; i < BPWM_CHANNEL_NUM; i++) + { +#if (BSP_USING_BPWM0_CAPTURE_CHMSK!=0) + if (BSP_USING_BPWM0_CAPTURE_CHMSK & (0x1 << i)) + { + nu_bpwm0_capture[i] = (nu_capture_t *)rt_malloc(sizeof(nu_capture_t)); + bpwm_init(nu_bpwm0_capture[i], i, &nu_bpwm0_dev, nu_bpwm0_device_name[i], BPWM0_IRQn); + } +#endif //#if (BSP_USING_BPWM0_CAPTURE_CHMSK!=0) + +#if (BSP_USING_BPWM1_CAPTURE_CHMSK!=0) + if (BSP_USING_BPWM1_CAPTURE_CHMSK & (0x1 << i)) + { + nu_bpwm1_capture[i] = (nu_capture_t *)rt_malloc(sizeof(nu_capture_t)); + bpwm_init(nu_bpwm1_capture[i], i, &nu_bpwm1_dev, nu_bpwm1_device_name[i], BPWM1_IRQn); + } +#endif //#if (BSP_USING_BPWM1_CAPTURE_CHMSK!=0) + } + + return 0; +} +INIT_DEVICE_EXPORT(nu_bpwm_capture_device_init); + +#endif //#if ((BSP_USING_BPWM0_CAPTURE_CHMSK+BSP_USING_BPWM1_CAPTURE_CHMSK)!=0) +#endif //#if defined(BSP_USING_BPWM_CAPTURE) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_clk.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_clk.c new file mode 100644 index 0000000000..7eb08534f7 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_clk.c @@ -0,0 +1,287 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-09-29 PLWang First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_CLK) + +#include +#include +#include +#include +#include "NuMicro.h" + + +/* Private define ---------------------------------------------------------------*/ + +/* pm run mode speed mapping */ +#define CONFIG_HIGH_SPEED_FREQ (72000000ul) +#define CONFIG_NORMAL_SPEED_FREQ (72000000ul) +#define CONFIG_MEDIUM_SPEED_FREQ (54000000ul) +#define CONFIG_LOW_SPEED_FREQ (36000000ul) + +/* Timer module assigned for pm device usage. */ +/* e.g. If TIMERn is reserved for pm, then define the PM_TIMER_USE_INSTANCE + macro to n value (without parentheses). */ +#define PM_TIMER_USE_INSTANCE 3 + + +/* Concatenate */ +#define _CONCAT2_(x, y) x##y +#define _CONCAT3_(x, y, z) x##y##z +#define CONCAT2(x, y) _CONCAT2_(x, y) +#define CONCAT3(x, y, z) _CONCAT3_(x,y,z) + +/* Concatenate the macros of timer instance for driver usage. */ +#define PM_TIMER CONCAT2(TIMER, PM_TIMER_USE_INSTANCE) +#define PM_TMR CONCAT2(TMR, PM_TIMER_USE_INSTANCE) +#define PM_TIMER_MODULE CONCAT2(PM_TMR, _MODULE) +#define PM_TIMER_IRQn CONCAT2(PM_TMR, _IRQn) +#define PM_TIMER_IRQHandler CONCAT2(PM_TMR, _IRQHandler) +#define PM_TIMER_SEL_LXT CONCAT3(CLK_CLKSEL1_, PM_TMR, SEL_LXT) + +/* Private typedef --------------------------------------------------------------*/ +#define TIMER_RESET_CNT(timer) do{(timer)->CTL |= TIMER_CTL_RSTCNT_Msk; \ + while(((timer)->CTL & TIMER_CTL_RSTCNT_Msk) == TIMER_CTL_RSTCNT_Msk); \ + }while(0) + +/* Private functions ------------------------------------------------------------*/ +static void pm_sleep(struct rt_pm *pm, rt_uint8_t mode); +static void pm_run(struct rt_pm *pm, rt_uint8_t mode); +static void pm_timer_start(struct rt_pm *pm, rt_uint32_t timeout); +static void pm_timer_stop(struct rt_pm *pm); +static rt_tick_t pm_timer_get_tick(struct rt_pm *pm); +static rt_tick_t pm_tick_from_os_tick(rt_tick_t os_tick); +static rt_tick_t os_tick_from_pm_tick(rt_tick_t pm_tick); + +/* Public functions -------------------------------------------------------------*/ +int rt_hw_pm_init(void); + +/* Private variables ------------------------------------------------------------*/ +static struct rt_pm_ops ops = +{ + .sleep = pm_sleep, + .run = pm_run, + .timer_start = pm_timer_start, + .timer_stop = pm_timer_stop, + .timer_get_tick = pm_timer_get_tick, +}; + +struct rt_device pm; + + + +/* pm sleep() entry */ +static void pm_sleep(struct rt_pm *pm, rt_uint8_t mode) +{ + SYS_UnlockReg(); + + switch (mode) + { + /* wake-up source: */ + /* PM_SLEEP_MODE_LIGHT : TIMERn */ + /* PM_SLEEP_MODE_DEEP : TIMERn */ + /* PM_SLEEP_MODE_STANDBY : wake-up timer (optional) */ + /* PM_SLEEP_MODE_SHUTDOWN : wake-up timer (optional) */ + + case PM_SLEEP_MODE_NONE: + case PM_SLEEP_MODE_IDLE: + break; + + case PM_SLEEP_MODE_LIGHT: + case PM_SLEEP_MODE_DEEP: + CLK_PowerDown(); + break; + + case PM_SLEEP_MODE_STANDBY: + LOG_W("Device does not support PM_SLEEP_MODE_STANDBY!"); + break; + + case PM_SLEEP_MODE_SHUTDOWN: + LOG_W("Device does not support PM_SLEEP_MODE_SHUTDOWN!"); + break; + + default: + RT_ASSERT(0); + break; + } + + SYS_LockReg(); +} + + +/* pm run() entry */ +static void pm_run(struct rt_pm *pm, rt_uint8_t mode) +{ + static uint8_t prev_mode = RT_PM_DEFAULT_RUN_MODE; + + /* ignore it if power mode is the same. */ + if (mode == prev_mode) + return; + + prev_mode = mode; + + SYS_UnlockReg(); + + /* Switch run mode frequency using PLL + HXT if HXT is enabled. + Otherwise, the system clock will use PLL + HIRC. */ + switch (mode) + { + case PM_RUN_MODE_HIGH_SPEED: + + CLK_SetCoreClock(CONFIG_HIGH_SPEED_FREQ); + break; + + case PM_RUN_MODE_NORMAL_SPEED: + + CLK_SetCoreClock(CONFIG_NORMAL_SPEED_FREQ); + break; + + case PM_RUN_MODE_MEDIUM_SPEED: + + CLK_SetCoreClock(CONFIG_MEDIUM_SPEED_FREQ); + break; + + case PM_RUN_MODE_LOW_SPEED: + + CLK_SetCoreClock(CONFIG_LOW_SPEED_FREQ); + break; + + default: + RT_ASSERT(0); + break; + } + + SystemCoreClockUpdate(); + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + + SYS_LockReg(); +} + + +static void hw_timer_init(void) +{ + /* Assign a hardware timer for pm usage. */ + SYS_UnlockReg(); + CLK_SetModuleClock(PM_TIMER_MODULE, PM_TIMER_SEL_LXT, MODULE_NoMsk); + CLK_EnableModuleClock(PM_TIMER_MODULE); + SYS_LockReg(); + + /* Initialize timer and enable wakeup function. */ + TIMER_Open(PM_TIMER, TIMER_CONTINUOUS_MODE, 1); + TIMER_SET_PRESCALE_VALUE(PM_TIMER, 0); + TIMER_EnableInt(PM_TIMER); + TIMER_EnableWakeup(PM_TIMER); + NVIC_EnableIRQ(PM_TIMER_IRQn); +} + + +/* convert os tick to pm timer tick */ +static rt_tick_t pm_tick_from_os_tick(rt_tick_t os_tick) +{ + rt_uint32_t hz = TIMER_GetModuleClock(PM_TIMER); + + return (rt_tick_t)(hz * os_tick / RT_TICK_PER_SECOND); +} + + +/* convert pm timer tick to os tick */ +static rt_tick_t os_tick_from_pm_tick(rt_tick_t pm_tick) +{ + static rt_uint32_t os_tick_remain = 0; + rt_uint32_t ret, hz; + + hz = TIMER_GetModuleClock(PM_TIMER); + ret = (pm_tick * RT_TICK_PER_SECOND + os_tick_remain) / hz; + + os_tick_remain += (pm_tick * RT_TICK_PER_SECOND); + os_tick_remain %= hz; + + return ret; +} + + +/* pm_ops timer_get_tick() entry */ +static rt_tick_t pm_timer_get_tick(struct rt_pm *pm) +{ + rt_tick_t tick; + + tick = TIMER_GetCounter(PM_TIMER); + + return os_tick_from_pm_tick(tick); +} + + +/* pm timer_start() entry */ +static void pm_timer_start(struct rt_pm *pm, rt_uint32_t timeout) +{ + int tick; + + if (timeout == RT_TICK_MAX) + return; + + /* start pm timer to compensate the os tick in power down mode */ + tick = pm_tick_from_os_tick(timeout); + TIMER_SET_CMP_VALUE(PM_TIMER, tick); + TIMER_Start(PM_TIMER); +} + + +/* pm timer_stop() entry */ +static void pm_timer_stop(struct rt_pm *pm) +{ + TIMER_Stop(PM_TIMER); + TIMER_RESET_CNT(PM_TIMER); +} + + +/* pm device driver initialize. */ +int rt_hw_pm_init(void) +{ + rt_uint8_t timer_mask; + + hw_timer_init(); + + /* initialize timer mask */ + timer_mask = (1UL << PM_SLEEP_MODE_LIGHT) | + (1UL << PM_SLEEP_MODE_DEEP); + + /* initialize system pm module */ + rt_system_pm_init(&ops, timer_mask, RT_NULL); + + return RT_EOK; +} +INIT_BOARD_EXPORT(rt_hw_pm_init); + + +/* pm timer interrupt entry */ +void PM_TIMER_IRQHandler(void) +{ + rt_interrupt_enter(); + + if (TIMER_GetIntFlag(PM_TIMER)) + { + TIMER_ClearIntFlag(PM_TIMER); + } + + if (TIMER_GetWakeupFlag(PM_TIMER)) + { + TIMER_ClearWakeupFlag(PM_TIMER); + } + + rt_interrupt_leave(); +} + +#endif /* BSP_USING_CLK */ + + + diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_common.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_common.c new file mode 100644 index 0000000000..65b100bbe9 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_common.c @@ -0,0 +1,142 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-9-1 Philo First version +* +******************************************************************************/ + +#include +#include +#include "NuMicro.h" +#include +#include "drv_uart.h" +#include "board.h" +#include "nutool_pincfg.h" +#include "nutool_modclkcfg.h" + + + +/** + * This function will initial M032 board. + */ +RT_WEAK void rt_hw_board_init(void) +{ + /* Init System/modules clock */ + nutool_modclkcfg_init(); + + /* Unlock protected registers */ + SYS_UnlockReg(); + + /* Init all pin function setting */ + nutool_pincfg_init(); + + /* Configure SysTick */ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + + /* Update System Core Clock */ + /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */ + SystemCoreClockUpdate(); + +#if defined(BSP_USING_EADC) + /* Vref connect to internal */ + SYS->VREFCTL = (SYS->VREFCTL & ~SYS_VREFCTL_VREFCTL_Msk) | SYS_VREFCTL_VREF_3_0V; +#endif + + /* Lock protected registers */ + SYS_LockReg(); + +#ifdef RT_USING_HEAP + rt_system_heap_init(HEAP_BEGIN, HEAP_END); +#endif /* RT_USING_HEAP */ + +#if defined(BSP_USING_UART) + rt_hw_uart_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif +} + +/** + * The time delay function. + * + * @param microseconds. + */ +void rt_hw_us_delay(rt_uint32_t us) +{ + rt_uint32_t ticks; + rt_uint32_t told, tnow, tcnt = 0; + rt_uint32_t reload = SysTick->LOAD; + + ticks = us * reload / (1000000 / RT_TICK_PER_SECOND); + told = SysTick->VAL; + while (1) + { + tnow = SysTick->VAL; + if (tnow != told) + { + if (tnow < told) + { + tcnt += told - tnow; + } + else + { + tcnt += reload - tnow + told; + } + told = tnow; + if (tcnt >= ticks) + { + break; + } + } + } +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +void rt_hw_cpu_reset(void) +{ + SYS_UnlockReg(); + + SYS->IPRST0 |= SYS_IPRST0_CHIPRST_Msk; +} + +#ifdef RT_USING_CPU_FFS +int __rt_ffs(int value) +{ + if (!value) return 0; + return __CLZ(__RBIT(value)) + 1; +} +#endif + +#ifdef RT_USING_FINSH +#include +static void reboot(uint8_t argc, char **argv) +{ + rt_hw_cpu_reset(); +} +FINSH_FUNCTION_EXPORT_ALIAS(reboot, __cmd_reboot, Reboot System); +#endif /* RT_USING_FINSH */ diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_crc.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_crc.c new file mode 100644 index 0000000000..9adef9ca90 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_crc.c @@ -0,0 +1,138 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-01 klcheng First version +* +******************************************************************************/ + +#include + +#if (defined(BSP_USING_CRC) && defined(RT_HWCRYPTO_USING_CRC)) + +#include + +#include +#include + +#include "NuMicro.h" +#include "drv_crc.h" +#include "drv_pdma.h" + +/* Private define ---------------------------------------------------------------*/ +#define NU_CRYPTO_CRC_NAME "nu_CRC" + +#define CRC_32_POLY 0x04C11DB7 +#define CRC_CCITT_POLY 0x00001021 +#define CRC_16_POLY 0x00008005 +#define CRC_8_POLY 0x00000007 + +/* Private variables ------------------------------------------------------------*/ + +static struct rt_mutex s_CRC_mutex; + +static rt_uint32_t nu_crc_run( + uint32_t u32OpMode, + uint32_t u32Seed, + uint32_t u32Attr, + uint8_t *pu8InData, + uint32_t u32DataLen +) +{ + uint32_t u32CalChecksum = 0; + uint32_t i = 0; + + rt_mutex_take(&s_CRC_mutex, RT_WAITING_FOREVER); + + /* Configure CRC controller */ + CRC_Open(u32OpMode, u32Attr, u32Seed, CRC_WDATA_8); + + uint8_t *pu8InTempData = pu8InData; + + while (i < u32DataLen) + { + if (((((uint32_t)pu8InTempData) % 4) != 0) || (u32DataLen - i < 4)) + { + CRC->CTL &= ~CRC_CTL_DATLEN_Msk; + CRC_WRITE_DATA((*pu8InTempData) & 0xFF); + pu8InTempData ++; + i++; + } + else + { + CRC->CTL &= ~CRC_CTL_DATLEN_Msk; + CRC->CTL |= CRC_WDATA_32; +#if defined (NU_CRC_USE_PDMA) + int32_t i32PDMATransCnt = (u32DataLen - i) / 4 ; + + i32PDMATransCnt = nu_pdma_mempush((void *)&CRC->DAT, pu8InTempData, 32, i32PDMATransCnt); + + if (i32PDMATransCnt > 0) + { + pu8InTempData += (i32PDMATransCnt * 4); + i += (i32PDMATransCnt * 4); + } +#else + CRC_WRITE_DATA(*(uint32_t *)pu8InTempData); + pu8InTempData += 4; + i += 4; +#endif + } + } + + /* Get checksum value */ + u32CalChecksum = CRC_GetChecksum(); + rt_mutex_release(&s_CRC_mutex); + + return u32CalChecksum; +} + +rt_err_t nu_crc_init(void) +{ + SYS_ResetModule(CRC_RST); + + rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO); + return RT_EOK; +} + +rt_uint32_t nu_crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in, rt_size_t length) +{ + uint32_t u32OpMode; + uint32_t u32CRCAttr = 0; + rt_uint32_t crc_result = 0; + + //select CRC operation mode + switch (ctx->crc_cfg.poly) + { + case CRC_32_POLY: + u32OpMode = CRC_32; + break; + case CRC_CCITT_POLY: + u32OpMode = CRC_CCITT; + break; + case CRC_16_POLY: + u32OpMode = CRC_16; + break; + case CRC_8_POLY: + u32OpMode = CRC_8; + break; + default: + return 0; + } + + u32CRCAttr |= (ctx->crc_cfg.flags & CRC_FLAG_REFOUT) ? CRC_CHECKSUM_RVS : 0; //CRC Checksum Reverse + u32CRCAttr |= (ctx->crc_cfg.flags & CRC_FLAG_REFIN) ? CRC_WDATA_RVS : 0; //CRC Write Data Reverse + + //Calculate CRC checksum, using config's last value as CRC seed + crc_result = nu_crc_run(u32OpMode, ctx->crc_cfg.last_val, u32CRCAttr, (uint8_t *)in, length); + + //update CRC result to config's last value + ctx->crc_cfg.last_val = crc_result; + return crc_result ^ 0x00 ^ ctx->crc_cfg.xorout; +} + +#endif //#if (defined(BSP_USING_CRC) && defined(RT_HWCRYPTO_USING_CRC)) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_crc.h b/bsp/nuvoton/libraries/m031/rtt_port/drv_crc.h new file mode 100644 index 0000000000..a5b048f038 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_crc.h @@ -0,0 +1,20 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-02-01 klcheng First version +* +******************************************************************************/ + +#ifndef __DRV_CRC_H__ +#define __DRV_CRC_H__ + +rt_err_t nu_crc_init(void); + +rt_uint32_t nu_crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in, rt_size_t length); + +#endif diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_crypto.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_crypto.c new file mode 100644 index 0000000000..cc71a4905c --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_crypto.c @@ -0,0 +1,126 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-26 klcheng First version +* +******************************************************************************/ + +#include + +#if ((defined(BSP_USING_CRC)) && defined(RT_USING_HWCRYPTO)) + +#include +#include +#include +#include "NuMicro.h" +#include + +#if defined(BSP_USING_CRC) + #include "drv_crc.h" +#endif + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx); +static void nu_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx); +static rt_err_t nu_hwcrypto_clone(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src); +static void nu_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx); + +/* Private variables ------------------------------------------------------------*/ +static const struct rt_hwcrypto_ops nu_hwcrypto_ops = +{ + .create = nu_hwcrypto_create, + .destroy = nu_hwcrypto_destroy, + .copy = nu_hwcrypto_clone, + .reset = nu_hwcrypto_reset, +}; + + +/* CRC operation ------------------------------------------------------------*/ +#if defined(BSP_USING_CRC) + +static const struct hwcrypto_crc_ops nu_crc_ops = +{ + .update = nu_crc_update, +}; + +#endif + +/* Register crypto interface ----------------------------------------------------------*/ +static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) +{ + rt_err_t res = RT_EOK; + + switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK) + { +#if defined(BSP_USING_CRC) + case HWCRYPTO_TYPE_CRC: + { + ctx->contex = RT_NULL; + //Setup CRC operation + ((struct hwcrypto_crc *)ctx)->ops = &nu_crc_ops; + break; + } +#endif /* BSP_USING_CRC */ + + default: + res = -RT_ERROR; + break; + } + + return res; +} + +static void nu_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx) +{ + if (ctx->contex) + rt_free(ctx->contex); +} + +static rt_err_t nu_hwcrypto_clone(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) +{ + rt_err_t res = RT_EOK; + + if (des->contex && src->contex) + { + rt_memcpy(des->contex, src->contex, sizeof(struct rt_hwcrypto_ctx)); + } + else + return -RT_EINVAL; + return res; +} + +static void nu_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx) +{ + /* no need to implement */ + return; +} + +/* Init and register nu_hwcrypto_dev */ +int nu_hwcrypto_device_init(void) +{ + static struct rt_hwcrypto_device nu_hwcrypto_dev; + + nu_hwcrypto_dev.ops = &nu_hwcrypto_ops; + nu_hwcrypto_dev.id = 0; + nu_hwcrypto_dev.user_data = &nu_hwcrypto_dev; + +#if defined(BSP_USING_CRC) + nu_crc_init(); +#endif + + // register hwcrypto operation + if (rt_hwcrypto_register(&nu_hwcrypto_dev, RT_HWCRYPTO_DEFAULT_NAME) != RT_EOK) + { + return -1; + } + + return 0; +} +INIT_DEVICE_EXPORT(nu_hwcrypto_device_init); + +#endif //#if ((defined(BSP_USING_CRC)) && defined(RT_USING_HWCRYPTO)) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_ebi.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_ebi.c new file mode 100644 index 0000000000..d4c91bfdf5 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_ebi.c @@ -0,0 +1,38 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-18 klcheng First version +* +******************************************************************************/ +#include + +#ifdef BSP_USING_EBI +#define MAX_BANK EBI_BANK1 + +/* Private variables ------------------------------------------------------------*/ +static uint8_t nu_ebi_bank_mask = 0; + +/* Public functions -------------------------------------------------------------*/ +rt_err_t nu_ebi_init(uint32_t u32Bank, uint32_t u32DataWidth, uint32_t u32TimingClass, uint32_t u32BusMode, uint32_t u32CSActiveLevel) +{ + if (u32Bank > MAX_BANK) + return -(RT_ERROR); + + /* Check this bank is not used */ + if ((1 << u32Bank) & nu_ebi_bank_mask) + return -(RT_ERROR); + + /* Initialize EBI */ + EBI_Open(u32Bank, u32DataWidth, u32TimingClass, u32BusMode, u32CSActiveLevel); + + nu_ebi_bank_mask |= (1 << u32Bank); + + return RT_EOK; +} + +#endif //BSP_USING_EBI diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_ebi.h b/bsp/nuvoton/libraries/m031/rtt_port/drv_ebi.h new file mode 100644 index 0000000000..3cdd05c771 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_ebi.h @@ -0,0 +1,48 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-18 klcheng First version +* +******************************************************************************/ +#ifndef __DRV_EBI_H___ +#define __DRV_EBI_H___ + +#include +#include "NuMicro.h" + +/** + * @brief Initialize EBI for specify Bank + * + * @param[in] u32Bank Bank number for EBI. Valid values are: + * - \ref EBI_BANK0 + * - \ref EBI_BANK1 + * - \ref EBI_BANK2 + * @param[in] u32DataWidth Data bus width. Valid values are: + * - \ref EBI_BUSWIDTH_8BIT + * - \ref EBI_BUSWIDTH_16BIT + * @param[in] u32TimingClass Default timing configuration. Valid values are: + * - \ref EBI_TIMING_FASTEST + * - \ref EBI_TIMING_VERYFAST + * - \ref EBI_TIMING_FAST + * - \ref EBI_TIMING_NORMAL + * - \ref EBI_TIMING_SLOW + * - \ref EBI_TIMING_VERYSLOW + * - \ref EBI_TIMING_SLOWEST + * @param[in] u32BusMode Set EBI bus operate mode. Valid values are: + * - \ref EBI_OPMODE_NORMAL + * - \ref EBI_OPMODE_CACCESS + * - \ref EBI_OPMODE_ADSEPARATE + * @param[in] u32CSActiveLevel CS is active High/Low. Valid values are: + * - \ref EBI_CS_ACTIVE_HIGH + * - \ref EBI_CS_ACTIVE_LOW + * + * @return RT_EOK/RT_ERROR Bank is used or not + */ +rt_err_t nu_ebi_init(uint32_t u32Bank, uint32_t u32DataWidth, uint32_t u32TimingClass, uint32_t u32BusMode, uint32_t u32CSActiveLevel); + +#endif // __DRV_EBI_H___ diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_fmc.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_fmc.c new file mode 100644 index 0000000000..ec5f1b69dc --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_fmc.c @@ -0,0 +1,331 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-17 FYChou First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_FMC) +#include +#include "NuMicro.h" + +#if defined(PKG_USING_FAL) + #include +#endif + +/* Private define ---------------------------------------------------------------*/ +#define FMC_APROM_END (FMC_APROM_BASE + 0x80000) +#define FMC_LDROM_END (FMC_LDROM_BASE + 0x2000) + +#define NU_GETBYTE_OFST(addr) (((addr)&0x3)*8) +#define NU_GET_WALIGN(addr) ((addr)&~0x3) +#define NU_GET_LSB2BIT(addr) ((addr)&0x3) +/* Private typedef --------------------------------------------------------------*/ + +/* Private functions ------------------------------------------------------------*/ +static int nu_fmc_init(void); +#if defined(PKG_USING_FAL) + static int aprom_read(long offset, uint8_t *buf, size_t size); + static int aprom_write(long offset, const uint8_t *buf, size_t size); + static int aprom_erase(long offset, size_t size); + + static int ldrom_read(long offset, uint8_t *buf, size_t size); + static int ldrom_write(long offset, const uint8_t *buf, size_t size); + static int ldrom_erase(long offset, size_t size); +#endif /* PKG_USING_FAL */ + +/* Public functions -------------------------------------------------------------*/ +int nu_fmc_read(long offset, uint8_t *buf, size_t size); +int nu_fmc_write(long offset, const uint8_t *buf, size_t size); +int nu_fmc_erase(long offset, size_t size); + +/* Private variables ------------------------------------------------------------*/ +static rt_mutex_t g_mutex_fmc = RT_NULL; + +/* Public variables -------------------------------------------------------------*/ +#if defined(PKG_USING_FAL) +const struct fal_flash_dev Onchip_aprom_flash = { "OnChip_APROM", FMC_APROM_BASE, FMC_APROM_END, FMC_FLASH_PAGE_SIZE, {NULL, aprom_read, aprom_write, aprom_erase} }; +const struct fal_flash_dev Onchip_ldrom_flash = { "OnChip_LDROM", FMC_LDROM_BASE, FMC_LDROM_END, FMC_FLASH_PAGE_SIZE, {NULL, ldrom_read, ldrom_write, ldrom_erase} }; +#endif /* PKG_USING_FAL */ + +int nu_fmc_read(long addr, uint8_t *buf, size_t size) +{ + size_t read_size = 0; + uint32_t addr_end = addr + size; + uint32_t isp_rdata = 0; + rt_mutex_take(g_mutex_fmc, RT_WAITING_FOREVER); + SYS_UnlockReg(); + + if (NU_GET_LSB2BIT(addr)) + isp_rdata = FMC_Read(NU_GET_WALIGN(addr)); + + + for (; addr < addr_end ;) + { + if (NU_GET_LSB2BIT(addr) == 0) + { + isp_rdata = FMC_Read(addr); + if (addr_end - addr >= 4) + { + *(uint32_t *)buf = isp_rdata; + addr += 4; + buf += 4; + read_size += 4; + continue; + } + } + + *buf = isp_rdata >> NU_GETBYTE_OFST(addr); + addr++; + buf++; + read_size++; + + } + + SYS_LockReg(); + rt_mutex_release(g_mutex_fmc); + + return read_size; +} + +int nu_fmc_write(long addr, const uint8_t *buf, size_t size) +{ + size_t write_size = 0; + uint32_t addr_end = addr + size; + uint32_t isp_rdata = 0; + + rt_mutex_take(g_mutex_fmc, RT_WAITING_FOREVER); + SYS_UnlockReg(); + + if (addr < FMC_APROM_END) + FMC_ENABLE_AP_UPDATE(); + else if ((addr < FMC_LDROM_END) && addr >= FMC_LDROM_BASE) + FMC_ENABLE_LD_UPDATE(); + else + { + goto Exit2; + } + + if (NU_GET_LSB2BIT(addr)) + isp_rdata = FMC_Read(NU_GET_WALIGN(addr)); + + for (; addr < addr_end ;) + { + + if (addr_end - addr >= 4 && NU_GET_LSB2BIT(addr) == 0) + { + FMC_Write(addr, *((uint32_t *)buf)); + addr += 4; + buf += 4; + write_size += 4; + continue; + } + + if ((NU_GET_LSB2BIT(addr)) == 0x0) + isp_rdata = FMC_Read(NU_GET_WALIGN(addr)); + + isp_rdata = (isp_rdata & ~(0xFF << NU_GETBYTE_OFST(addr))) | ((*buf) << NU_GETBYTE_OFST(addr)); + + if ((NU_GET_LSB2BIT(addr)) == 0x3) + FMC_Write(NU_GET_WALIGN(addr), isp_rdata); + + addr++; + buf++; + write_size++; + + } + + if (NU_GET_LSB2BIT(addr)) + FMC_Write(NU_GET_WALIGN(addr), isp_rdata); + + FMC_DISABLE_AP_UPDATE(); + FMC_DISABLE_LD_UPDATE(); +Exit2: + SYS_LockReg(); + rt_mutex_release(g_mutex_fmc); + + return write_size; + +} + +int nu_fmc_erase(long addr, size_t size) +{ + size_t erased_size = 0; + uint32_t addrptr; + uint32_t addr_end = addr + size; + +#if defined(NU_SUPPORT_NONALIGN) + uint8_t *page_sdtemp = RT_NULL; + uint8_t *page_edtemp = RT_NULL; + + + addrptr = addr & (FMC_FLASH_PAGE_SIZE - 1); + if (addrptr) + { + page_sdtemp = rt_malloc(addrptr); + if (page_sdtemp == RT_NULL) + { + erased_size = 0; + + goto Exit3; + } + + if (nu_fmc_read(addr & ~(FMC_FLASH_PAGE_SIZE - 1), page_sdtemp, addrptr) != addrptr) + { + + erased_size = 0; + + goto Exit3; + } + + } + + addrptr = addr_end & (FMC_FLASH_PAGE_SIZE - 1); + if (addrptr) + { + page_edtemp = rt_malloc(FMC_FLASH_PAGE_SIZE - addrptr); + if (page_edtemp == RT_NULL) + { + erased_size = 0; + + goto Exit3; + } + + if (nu_fmc_read(addr_end, page_edtemp, FMC_FLASH_PAGE_SIZE - addrptr) != FMC_FLASH_PAGE_SIZE - addrptr) + { + erased_size = 0; + + goto Exit3; + } + + } +#endif + + rt_mutex_take(g_mutex_fmc, RT_WAITING_FOREVER); + SYS_UnlockReg(); + + if (addr <= FMC_APROM_END) + FMC_ENABLE_AP_UPDATE(); + else if ((addr < FMC_LDROM_END) && addr >= FMC_LDROM_BASE) + FMC_ENABLE_LD_UPDATE(); + else + { + goto Exit2; + } + + addrptr = (addr & ~(FMC_FLASH_PAGE_SIZE - 1)); + while (addrptr < addr_end) + { + if (FMC_Erase(addrptr) != RT_EOK) + { + goto Exit1; + } + erased_size += FMC_FLASH_PAGE_SIZE; + addrptr += FMC_FLASH_PAGE_SIZE; + } + +Exit1: + FMC_DISABLE_AP_UPDATE(); + FMC_DISABLE_LD_UPDATE(); +Exit2: + SYS_LockReg(); + rt_mutex_release(g_mutex_fmc); + +#if defined(NU_SUPPORT_NONALIGN) + + if (erased_size >= size) + { + addrptr = addr & (FMC_FLASH_PAGE_SIZE - 1); + if (addrptr) + { + if (nu_fmc_write(addr & ~(FMC_FLASH_PAGE_SIZE - 1), page_sdtemp, addrptr) != addrptr) + goto Exit3; + + erased_size += addrptr; + } + + addrptr = addr_end & (FMC_FLASH_PAGE_SIZE - 1); + if (addrptr) + { + + if (nu_fmc_write(addr_end, page_edtemp, FMC_FLASH_PAGE_SIZE - addrptr) != FMC_FLASH_PAGE_SIZE - addrptr) + goto Exit3; + + erased_size += FMC_FLASH_PAGE_SIZE - addrptr; + + } + } + else + erased_size = 0; + + +Exit3: + if (page_sdtemp != RT_NULL) + rt_free(page_sdtemp); + + if (page_edtemp != RT_NULL) + rt_free(page_edtemp); +#endif + + return erased_size; +} + +#if defined(PKG_USING_FAL) + +static int aprom_read(long offset, uint8_t *buf, size_t size) +{ + return nu_fmc_read(Onchip_aprom_flash.addr + offset, buf, size); +} + +static int aprom_write(long offset, const uint8_t *buf, size_t size) +{ + return nu_fmc_write(Onchip_aprom_flash.addr + offset, buf, size); +} + +static int aprom_erase(long offset, size_t size) +{ + return nu_fmc_erase(Onchip_aprom_flash.addr + offset, size); +} + +static int ldrom_read(long offset, uint8_t *buf, size_t size) +{ + return nu_fmc_read(Onchip_ldrom_flash.addr + offset, buf, size); +} + +static int ldrom_write(long offset, const uint8_t *buf, size_t size) +{ + return nu_fmc_write(Onchip_ldrom_flash.addr + offset, buf, size); +} + +static int ldrom_erase(long offset, size_t size) +{ + return nu_fmc_erase(Onchip_ldrom_flash.addr + offset, size); +} + +#endif /* PKG_USING_FAL */ + +static int nu_fmc_init(void) +{ + SYS_UnlockReg(); + FMC_ENABLE_ISP(); + SYS_LockReg(); + + g_mutex_fmc = rt_mutex_create("nu_fmc_lock", RT_IPC_FLAG_PRIO); + + /* PKG_USING_FAL */ +#if defined(PKG_USING_FAL) + fal_init(); +#endif + + return (int)RT_EOK; +} +INIT_APP_EXPORT(nu_fmc_init); + +#endif /* BSP_USING_FMC */ diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_fmc.h b/bsp/nuvoton/libraries/m031/rtt_port/drv_fmc.h new file mode 100644 index 0000000000..f9a77d5b38 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_fmc.h @@ -0,0 +1,24 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-17 FYChou First version +* +******************************************************************************/ + +#ifndef __DRV_FMC_H__ +#define __DRV_FMC_H__ + +#include +#include "NuMicro.h" + +int nu_fmc_read(long offset, uint8_t *buf, size_t size); +int nu_fmc_write(long offset, const uint8_t *buf, size_t size); +int nu_fmc_erase(long offset, size_t size); + + +#endif // __DRV_FMC_H___ diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_gpio.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_gpio.c new file mode 100644 index 0000000000..1ad5c19c36 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_gpio.c @@ -0,0 +1,401 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-9-4 Philo First version +* +******************************************************************************/ + +#include + +#if (defined(BSP_USING_GPIO) && defined(RT_USING_PIN)) + +#include +#include +#include "NuMicro.h" +#include +#include +#include + +/* Private define ---------------------------------------------------------------*/ + +#define PORT_OFFSET 0x40 +#define IRQ_MAX_NUM 16 //Max support 32 +#define MAX_PORTH_PIN_MAX 11 + +/* Private functions ------------------------------------------------------------*/ + +static void nu_gpio_mode(struct rt_device *device, rt_base_t pin, rt_base_t mode); +static void nu_gpio_write(struct rt_device *device, rt_base_t pin, rt_base_t value); +static int nu_gpio_read(struct rt_device *device, rt_base_t pin); +static rt_err_t nu_gpio_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args); +static rt_err_t nu_gpio_detach_irq(struct rt_device *device, rt_int32_t pin); +static rt_err_t nu_gpio_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled); +static rt_base_t nu_gpio_get(const char *name); + +/* Private variables ------------------------------------------------------------*/ +static struct rt_pin_irq_hdr pin_irq_hdr_tab[IRQ_MAX_NUM]; +static struct rt_pin_ops nu_gpio_ops = +{ + nu_gpio_mode, + nu_gpio_write, + nu_gpio_read, + nu_gpio_attach_irq, + nu_gpio_detach_irq, + nu_gpio_irq_enable, + nu_gpio_get, +}; + +static rt_uint32_t g_u32PinIrqMask = 0x0; + +/* Functions define ------------------------------------------------------------*/ + +static rt_err_t nu_port_check(rt_int32_t pin) +{ + if (NU_GET_PORT(pin) >= NU_PORT_CNT) + return -(RT_ERROR); + else if ((NU_GET_PORT(pin) == NU_PH) && (NU_GET_PINS(pin) > MAX_PORTH_PIN_MAX)) + return -(RT_ERROR); + + return RT_EOK; +} + +static rt_int32_t nu_find_irqindex(rt_uint32_t pin_index) +{ + rt_int32_t irqindex; + rt_int32_t u32PinIrqStatus = g_u32PinIrqMask; + + // Find index of pin is attached in pool. + while ((irqindex = nu_ctz(u32PinIrqStatus)) < IRQ_MAX_NUM) // Count Trailing Zeros ==> Find First One + { + if (pin_irq_hdr_tab[irqindex].pin == pin_index) + return irqindex; + + u32PinIrqStatus &= ~(1 << irqindex); + } + + return -(RT_ERROR); +} + +static void pin_irq_hdr(rt_uint32_t irq_status, rt_uint32_t port_index) +{ + rt_int32_t irqindex, i; + rt_int32_t pinindex = port_index * GPIO_PIN_MAX ; + + while ((i = nu_ctz(irq_status)) < GPIO_PIN_MAX)// Count Trailing Zeros ==> Find First One + { + int pin_mask = (1 << i); + irqindex = nu_find_irqindex(pinindex + i); + if (irqindex != -(RT_ERROR)) + { + if (pin_irq_hdr_tab[irqindex].hdr) + { + pin_irq_hdr_tab[irqindex].hdr(pin_irq_hdr_tab[irqindex].args); + } + } + // Clear the served bit. + irq_status &= ~pin_mask; + } +} + +static void nu_gpio_mode(struct rt_device *device, rt_base_t pin, rt_base_t mode) +{ + GPIO_T *PORT; + + if (nu_port_check(pin)) + return; + + PORT = (GPIO_T *)(PA_BASE + (NU_GET_PORT(pin) * PORT_OFFSET)); + + if (mode == PIN_MODE_OUTPUT) + { + GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_OUTPUT); + } + else if (mode == PIN_MODE_INPUT) + { + GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_INPUT); + } + else if (mode == PIN_MODE_OUTPUT_OD) + { + GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_OPEN_DRAIN); + } +#if 0 + else if (mode == PIN_MODE_INPUT_PULLUP) + { + GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_INPUT); + } + else if (mode == PIN_MODE_INPUT_PULLDOWN) + { + GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_INPUT); + } +#else + else + { + rt_kprintf("M031 not support this GPIO mode\n"); + } +#endif +} + +static void nu_gpio_write(struct rt_device *device, rt_base_t pin, rt_base_t value) +{ + if (nu_port_check(pin)) + return; + + GPIO_PIN_DATA(NU_GET_PORT(pin), NU_GET_PINS(pin)) = value; +} + +static int nu_gpio_read(struct rt_device *device, rt_base_t pin) +{ + if (nu_port_check(pin)) + return PIN_LOW; + + return GPIO_PIN_DATA(NU_GET_PORT(pin), NU_GET_PINS(pin)); +} + +static rt_err_t nu_gpio_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args) +{ + rt_base_t level; + rt_int32_t irqindex; + + if (nu_port_check(pin)) + return -(RT_ERROR); + + level = rt_hw_interrupt_disable(); + + // Find index of pin is attached in pool. + if ((irqindex = nu_find_irqindex(pin)) >= 0) + goto exit_nu_gpio_attach_irq; + + // Find available index of pin in pool. + if ((irqindex = nu_cto(g_u32PinIrqMask)) < IRQ_MAX_NUM) // Count Trailing Ones ==> Find First Zero + goto exit_nu_gpio_attach_irq; + + rt_hw_interrupt_enable(level); + + return -(RT_EBUSY); + +exit_nu_gpio_attach_irq: + + pin_irq_hdr_tab[irqindex].pin = pin; + pin_irq_hdr_tab[irqindex].hdr = hdr; + pin_irq_hdr_tab[irqindex].mode = mode; + pin_irq_hdr_tab[irqindex].args = args; + + g_u32PinIrqMask |= (1 << irqindex); + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +static rt_err_t nu_gpio_detach_irq(struct rt_device *device, rt_int32_t pin) +{ + rt_base_t level; + rt_int32_t irqindex; + rt_int32_t u32PinIrqStatus; + + if (nu_port_check(pin)) + return -(RT_ERROR); + + level = rt_hw_interrupt_disable(); + + u32PinIrqStatus = g_u32PinIrqMask; + + // Find index of pin is attached in pool. + while ((irqindex = nu_ctz(u32PinIrqStatus)) < IRQ_MAX_NUM)// Count Trailing Zeros ==> Find First One + { + if (pin_irq_hdr_tab[irqindex].pin == pin) + { + pin_irq_hdr_tab[irqindex].pin = PIN_IRQ_PIN_NONE; + pin_irq_hdr_tab[irqindex].hdr = RT_NULL; + pin_irq_hdr_tab[irqindex].mode = PIN_IRQ_MODE_RISING; + pin_irq_hdr_tab[irqindex].args = RT_NULL; + g_u32PinIrqMask &= ~(1 << irqindex); + break; + } + u32PinIrqStatus &= ~(1 << irqindex); + } + + rt_hw_interrupt_enable(level); + return RT_EOK; +} + +static rt_err_t nu_gpio_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) +{ + GPIO_T *PORT; + rt_base_t level; + uint32_t u32IntAttribs; + rt_int32_t irqindex; + rt_err_t ret = RT_EOK; + + if (nu_port_check(pin)) + return -(RT_ERROR); + + level = rt_hw_interrupt_disable(); + + irqindex = nu_find_irqindex(pin); + if (irqindex == -(RT_ERROR)) + { + ret = RT_ERROR; + goto exit_nu_gpio_irq_enable; + } + + PORT = (GPIO_T *)(PA_BASE + (NU_GET_PORT(pin) * PORT_OFFSET)); + + if (enabled == PIN_IRQ_ENABLE) + { + if (pin_irq_hdr_tab[irqindex].mode == PIN_IRQ_MODE_RISING) + u32IntAttribs = GPIO_INT_RISING; + else if (pin_irq_hdr_tab[irqindex].mode == PIN_IRQ_MODE_FALLING) + u32IntAttribs = GPIO_INT_FALLING; + else if (pin_irq_hdr_tab[irqindex].mode == PIN_IRQ_MODE_RISING_FALLING) + u32IntAttribs = GPIO_INT_BOTH_EDGE; + else if (pin_irq_hdr_tab[irqindex].mode == PIN_IRQ_MODE_HIGH_LEVEL) + u32IntAttribs = GPIO_INT_HIGH; + else if (pin_irq_hdr_tab[irqindex].mode == PIN_IRQ_MODE_LOW_LEVEL) + u32IntAttribs = GPIO_INT_LOW; + else + goto exit_nu_gpio_irq_enable; + + GPIO_EnableInt(PORT, NU_GET_PINS(pin), u32IntAttribs); + + if ((NU_GET_PORT(pin) == NU_PA) || (NU_GET_PORT(pin) == NU_PB) || (NU_GET_PORT(pin) == NU_PG) || (NU_GET_PORT(pin) == NU_PH)) + { + NVIC_EnableIRQ(GPIO_PAPBPGPH_IRQn); + } + else + { + NVIC_EnableIRQ(GPIO_PCPDPEPF_IRQn); + } + } + else + { + GPIO_DisableInt(PORT, NU_GET_PINS(pin)); + } + +exit_nu_gpio_irq_enable: + + rt_hw_interrupt_enable(level); + return -(ret); +} + +static rt_base_t nu_gpio_get(const char *name) +{ + /* Get pin number by name,such as PA.0, PF12 */ + if ((name[2] == '\0')||((name[2] == '.')&&(name[3] == '\0'))) + return -(RT_EINVAL); + + long number; + + if ((name[2] == '.')) + number = atol(&name[3]); + else + number = atol(&name[2]); + + if (number > 15) + return -(RT_EINVAL); + + if (name[1] >= 'A' && name[1] <= 'H') + return ((name[1] - 'A') * 0x10) + number; + + if (name[1] >= 'a' && name[1] <= 'h') + return ((name[1] - 'a') * 0x10) + number; + + return -(RT_EINVAL); + +} + +int rt_hw_gpio_init(void) +{ + rt_int32_t irqindex; + for (irqindex = 0; irqindex < IRQ_MAX_NUM ; irqindex++) + { + pin_irq_hdr_tab[irqindex].pin = PIN_IRQ_PIN_NONE; + pin_irq_hdr_tab[irqindex].hdr = RT_NULL; + pin_irq_hdr_tab[irqindex].mode = PIN_IRQ_MODE_RISING; + pin_irq_hdr_tab[irqindex].args = RT_NULL; + } + + return rt_device_pin_register("gpio", &nu_gpio_ops, RT_NULL); +} + +INIT_BOARD_EXPORT(rt_hw_gpio_init); + +void GPABGH_IRQHandler(void) +{ + rt_uint32_t int_status; + + rt_interrupt_enter(); + + int_status = PA->INTSRC; + if (int_status) + { + pin_irq_hdr(int_status, NU_PA); + PA->INTSRC = int_status; + } + + int_status = PB->INTSRC; + if (int_status) + { + pin_irq_hdr(int_status, NU_PB); + PB->INTSRC = int_status; + } + + int_status = PG->INTSRC; + if (int_status) + { + pin_irq_hdr(int_status, NU_PG); + PG->INTSRC = int_status; + } + + int_status = PH->INTSRC; + if (int_status) + { + pin_irq_hdr(int_status, NU_PH); + PH->INTSRC = int_status; + } + + rt_interrupt_leave(); +} + +void GPCDEF_IRQHandler(void) +{ + rt_uint32_t int_status; + + rt_interrupt_enter(); + + int_status = PC->INTSRC; + if (int_status) + { + pin_irq_hdr(int_status, NU_PC); + PC->INTSRC = int_status; + } + + int_status = PD->INTSRC; + if (int_status) + { + pin_irq_hdr(int_status, NU_PD); + PD->INTSRC = int_status; + } + + int_status = PE->INTSRC; + if (int_status) + { + pin_irq_hdr(int_status, NU_PE); + PE->INTSRC = int_status; + } + + int_status = PF->INTSRC; + if (int_status) + { + pin_irq_hdr(int_status, NU_PF); + PF->INTSRC = int_status; + } + + rt_interrupt_leave(); +} + +#endif //#if (defined(BSP_USING_GPIO) && defined(RT_USING_PIN)) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_gpio.h b/bsp/nuvoton/libraries/m031/rtt_port/drv_gpio.h new file mode 100644 index 0000000000..e0627a640d --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_gpio.h @@ -0,0 +1,34 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-9-4 Philo First version +* +******************************************************************************/ + +#ifndef __DRV_GPIO_H__ +#define __DRV_GPIO_H__ + +typedef enum +{ + NU_PA, + NU_PB, + NU_PC, + NU_PD, + NU_PE, + NU_PF, + NU_PG, + NU_PH, + NU_PORT_CNT, +} nu_gpio_port; + +#define NU_GET_PININDEX(port, pin) ((port)*16+(pin)) +#define NU_GET_PINS(rt_pin_index) ((rt_pin_index) & 0x0000000F) +#define NU_GET_PORT(rt_pin_index) (((rt_pin_index)>>4) & 0x0000000F) +#define NU_GET_PIN_MASK(nu_gpio_pin) (1 << (nu_gpio_pin)) + +#endif //__DRV_GPIO_H__ diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c new file mode 100644 index 0000000000..788526c72c --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c @@ -0,0 +1,317 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-1-13 klcheng First version +******************************************************************************/ + + +#include + +#ifdef BSP_USING_I2C +#include +#include "NuMicro.h" + +/* Private define ---------------------------------------------------------------*/ +#define LOG_TAG "drv.i2c" +#define DBG_ENABLE +#define DBG_SECTION_NAME "drv.i2c" +#define DBG_LEVEL DBG_ERROR +#define DBG_COLOR +#include + +const rt_uint32_t u32I2C_MASTER_STATUS_START = 0x08UL; +const rt_uint32_t u32I2C_MASTER_STATUS_REPEAT_START = 0x10UL; +const rt_uint32_t u32I2C_MASTER_STATUS_TRANSMIT_ADDRESS_ACK = 0x18UL; +const rt_uint32_t u32I2C_MASTER_STATUS_TRANSMIT_ADDRESS_NACK = 0x20UL; +const rt_uint32_t u32I2C_MASTER_STATUS_TRANSMIT_DATA_ACK = 0x28UL; +const rt_uint32_t u32I2C_MASTER_STATUS_TRANSMIT_DATA_NACK = 0x30UL; +const rt_uint32_t u32I2C_MASTER_STATUS_ARBITRATION_LOST = 0x38UL; +const rt_uint32_t u32I2C_MASTER_STATUS_RECEIVE_ADDRESS_ACK = 0x40UL; +const rt_uint32_t u32I2C_MASTER_STATUS_RECEIVE_ADDRESS_NACK = 0x48UL; +const rt_uint32_t u32I2C_MASTER_STATUS_RECEIVE_DATA_ACK = 0x50UL; +const rt_uint32_t u32I2C_MASTER_STATUS_RECEIVE_DATA_NACK = 0x58UL; +const rt_uint32_t u32I2C_MASTER_STATUS_BUS_ERROR = 0x00UL; +const rt_uint32_t u32I2C_MASTER_STATUS_BUS_RELEASED = 0xF8UL; + +/* Private typedef --------------------------------------------------------------*/ +typedef struct _nu_i2c_bus +{ + struct rt_i2c_bus_device parent; + I2C_T *I2C; + struct rt_i2c_msg *msg; + char *device_name; +} nu_i2c_bus_t; + +/* Private variables ------------------------------------------------------------*/ +#ifdef BSP_USING_I2C0 +#define I2C0BUS_NAME "i2c0" +static nu_i2c_bus_t nu_i2c0 = +{ + .I2C = I2C0, + .device_name = I2C0BUS_NAME, +}; +#endif /* BSP_USING_I2C0 */ + +#ifdef BSP_USING_I2C1 +#define I2C1BUS_NAME "i2c1" +static nu_i2c_bus_t nu_i2c1 = +{ + .I2C = I2C1, + .device_name = I2C1BUS_NAME, +}; +#endif /* BSP_USING_I2C1 */ + +/* Private functions ------------------------------------------------------------*/ +#if (defined(BSP_USING_I2C0) || defined(BSP_USING_I2C1)) + +static rt_size_t nu_i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); + +static const struct rt_i2c_bus_device_ops nu_i2c_ops = +{ + .master_xfer = nu_i2c_mst_xfer, + .slave_xfer = NULL, + .i2c_bus_control = NULL, +}; + +static rt_err_t nu_i2c_configure(nu_i2c_bus_t *bus) +{ + RT_ASSERT(bus != RT_NULL); + + bus->parent.ops = &nu_i2c_ops; + I2C_Open(bus->I2C, 100000); + + return RT_EOK; +} + +static inline rt_err_t nu_i2c_wait_ready_with_timeout(nu_i2c_bus_t *bus) +{ + rt_tick_t start = rt_tick_get(); + while (!(bus->I2C->CTL0 & I2C_CTL0_SI_Msk)) + { + if ((rt_tick_get() - start) > bus->parent.timeout) + { + LOG_E("\ni2c: timeout!\n"); + return -RT_ETIMEOUT; + } + } + + return RT_EOK; +} + +static inline rt_err_t nu_i2c_send_data(nu_i2c_bus_t *nu_i2c, rt_uint8_t data) +{ + I2C_SET_DATA(nu_i2c->I2C, data); + I2C_SET_CONTROL_REG(nu_i2c->I2C, I2C_CTL_SI); + return nu_i2c_wait_ready_with_timeout(nu_i2c); +} + +static rt_err_t nu_i2c_send_address(nu_i2c_bus_t *nu_i2c, + struct rt_i2c_msg *msg) +{ + rt_uint16_t flags = msg->flags; + rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; + rt_uint8_t addr1; + rt_err_t ret; + + + if (flags & RT_I2C_ADDR_10BIT) + { + LOG_E("do not supprot i2c 10-bit address mode\n"); + return -RT_EIO; + } + else + { + /* 7-bit addr */ + addr1 = msg->addr << 1; + if (flags & RT_I2C_RD) + addr1 |= 1; + + /* Send device address */ + ret = nu_i2c_send_data(nu_i2c, addr1); /* Send Address */ + if (ret != RT_EOK) /* for timeout condition */ + return -RT_EIO; + + if ((I2C_GET_STATUS(nu_i2c->I2C) + != ((flags & RT_I2C_RD) ? u32I2C_MASTER_STATUS_RECEIVE_ADDRESS_ACK : u32I2C_MASTER_STATUS_TRANSMIT_ADDRESS_ACK)) + && !ignore_nack) + { + LOG_E("sending address failed\n"); + return -RT_EIO; + } + } + + return RT_EOK; +} + +static rt_size_t nu_i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + struct rt_i2c_msg *msg; + nu_i2c_bus_t *nu_i2c; + rt_size_t i; + rt_uint32_t cnt_data; + rt_uint16_t ignore_nack; + rt_err_t ret; + + RT_ASSERT(bus != RT_NULL); + nu_i2c = (nu_i2c_bus_t *) bus; + + nu_i2c->msg = msgs; + + nu_i2c->I2C->CTL0 |= I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk; + ret = nu_i2c_wait_ready_with_timeout(nu_i2c); + if (ret != RT_EOK) /* for timeout condition */ + { + rt_set_errno(-RT_ETIMEOUT); + return 0; + } + if (I2C_GET_STATUS(nu_i2c->I2C) != u32I2C_MASTER_STATUS_START) + { + i = 0; + LOG_E("Send START Failed"); + return i; + } + + for (i = 0; i < num; i++) + { + msg = &msgs[i]; + ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; + + if (!(msg->flags & RT_I2C_NO_START)) + { + if (i) + { + I2C_SET_CONTROL_REG(nu_i2c->I2C, I2C_CTL_STA_SI); + ret = nu_i2c_wait_ready_with_timeout(nu_i2c); + if (ret != RT_EOK) /* for timeout condition */ + break; + + if (I2C_GET_STATUS(nu_i2c->I2C) != u32I2C_MASTER_STATUS_REPEAT_START) + { + i = 0; + LOG_E("Send repeat START Fail"); + break; + } + } + + if ((RT_EOK != nu_i2c_send_address(nu_i2c, msg)) + && !ignore_nack) + { + i = 0; + LOG_E("Send Address Fail"); + break; + } + } + + + if (nu_i2c->msg[i].flags & RT_I2C_RD) /* Receive Bytes */ + { + rt_uint32_t do_rd_nack = (i == (num - 1)); + for (cnt_data = 0 ; cnt_data < (nu_i2c->msg[i].len) ; cnt_data++) + { + do_rd_nack += (cnt_data == (nu_i2c->msg[i].len - 1)); /* NACK after last byte for hardware setting */ + if (do_rd_nack == 2) + { + I2C_SET_CONTROL_REG(nu_i2c->I2C, I2C_CTL_SI); + } + else + { + I2C_SET_CONTROL_REG(nu_i2c->I2C, I2C_CTL_SI_AA); + } + + ret = nu_i2c_wait_ready_with_timeout(nu_i2c); + if (ret != RT_EOK) /* for timeout condition */ + break; + + if (nu_i2c->I2C->CTL0 & I2C_CTL_AA) + { + if (I2C_GET_STATUS(nu_i2c->I2C) != u32I2C_MASTER_STATUS_RECEIVE_DATA_ACK) + { + i = 0; + break; + } + } + else + { + if (I2C_GET_STATUS(nu_i2c->I2C) != u32I2C_MASTER_STATUS_RECEIVE_DATA_NACK) + { + i = 0; + break; + } + } + + nu_i2c->msg[i].buf[cnt_data] = nu_i2c->I2C->DAT; + } + } + else /* Send Bytes */ + { + for (cnt_data = 0 ; cnt_data < (nu_i2c->msg[i].len) ; cnt_data++) + { + /* Send register number and MSB of data */ + ret = nu_i2c_send_data(nu_i2c, (uint8_t)(nu_i2c->msg[i].buf[cnt_data])); + if (ret != RT_EOK) /* for timeout condition */ + break; + + if (I2C_GET_STATUS(nu_i2c->I2C) != u32I2C_MASTER_STATUS_TRANSMIT_DATA_ACK + && !ignore_nack + ) /* Send aata and get Ack */ + { + i = 0; + break; + } + } + } + } + + I2C_STOP(nu_i2c->I2C); + + RT_ASSERT(I2C_GET_STATUS(nu_i2c->I2C) == u32I2C_MASTER_STATUS_BUS_RELEASED); + if (I2C_GET_STATUS(nu_i2c->I2C) != u32I2C_MASTER_STATUS_BUS_RELEASED) + { + i = 0; + } + + nu_i2c->msg = RT_NULL; + nu_i2c->I2C->CTL1 = 0; /*clear all sub modes like 10 bit mode*/ + return i; +} + +#endif + +/* Public functions -------------------------------------------------------------*/ +int rt_hw_i2c_init(void) +{ + rt_err_t ret = RT_ERROR; +#if defined(BSP_USING_I2C0) + SYS_UnlockReg(); + SYS_ResetModule(I2C0_RST); + SYS_LockReg(); + nu_i2c_configure(&nu_i2c0); + ret = rt_i2c_bus_device_register(&nu_i2c0.parent, nu_i2c0.device_name); + RT_ASSERT(RT_EOK == ret); +#endif /* BSP_USING_I2C0 */ + +#if defined(BSP_USING_I2C1) + SYS_UnlockReg(); + SYS_ResetModule(I2C1_RST); + SYS_LockReg(); + nu_i2c_configure(&nu_i2c1); + ret = rt_i2c_bus_device_register(&nu_i2c1.parent, nu_i2c1.device_name); + RT_ASSERT(RT_EOK == ret); +#endif /* BSP_USING_I2C1 */ + + return ret; +} + +INIT_DEVICE_EXPORT(rt_hw_i2c_init); + +#endif /* BSP_USING_I2C */ + diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_i2s.h b/bsp/nuvoton/libraries/m031/rtt_port/drv_i2s.h new file mode 100644 index 0000000000..96343c6a79 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_i2s.h @@ -0,0 +1,96 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-2-7 Wayne First version +* +******************************************************************************/ + +#ifndef __DRV_I2S_H__ +#define __DRV_I2S_H__ + +#include +#include "NuMicro.h" +#include + +#if !defined(NU_I2S_DMA_FIFO_SIZE) + #define NU_I2S_DMA_FIFO_SIZE (2048) +#endif + +#if !defined(NU_I2S_DMA_BUF_BLOCK_NUMBER) + #define NU_I2S_DMA_BUF_BLOCK_NUMBER (2) +#endif + +#if ( (NU_I2S_DMA_FIFO_SIZE % NU_I2S_DMA_BUF_BLOCK_NUMBER) != 0 ) + #error "Please give an aligned definition" +#endif +#if ( NU_I2S_DMA_FIFO_SIZE < 2048 ) + #warning "DMA FIFO too small, miss voice?" +#endif + +#define NU_I2S_DMA_BUF_BLOCK_SIZE (NU_I2S_DMA_FIFO_SIZE/NU_I2S_DMA_BUF_BLOCK_NUMBER) + +typedef enum +{ + NU_I2S_DAI_PLAYBACK, + NU_I2S_DAI_CAPTURE, + NU_I2S_DAI_CNT +} E_NU_I2S_DAI; + +typedef enum +{ + NU_ACODEC_ROLE_MASTER, + NU_ACODEC_ROLE_SLAVE, +} E_NU_ACODEC_ROLE; + +typedef struct +{ + char *name; + + E_NU_ACODEC_ROLE role; + + struct rt_audio_configure config; + + rt_err_t (*nu_acodec_init)(void); + + rt_err_t (*nu_acodec_reset)(void); + + rt_err_t (*nu_acodec_dsp_control)(struct rt_audio_configure *config); + + rt_err_t (*nu_acodec_mixer_control)(rt_uint32_t ui32Item, rt_uint32_t ui32Value); + + rt_err_t (*nu_acodec_mixer_query)(rt_uint32_t ui32Item, rt_uint32_t *ui32Value); + +} nu_acodec_ops; + +typedef nu_acodec_ops *nu_acodec_ops_t; + +struct nu_i2s_dai +{ + int16_t pdma_perp; + int8_t pdma_chanid; + rt_uint8_t *fifo; + int16_t fifo_block_idx; + nu_pdma_desc_t pdma_descs[NU_I2S_DMA_BUF_BLOCK_NUMBER]; +}; +typedef struct nu_i2s_dai *nu_i2s_dai_t; + +struct nu_i2s +{ + struct rt_audio_device audio; + struct rt_audio_configure config; + + char *name; + SPI_T *i2s_base; + uint32_t i2s_rst; + + struct nu_i2s_dai i2s_dais[NU_I2S_DAI_CNT]; + nu_acodec_ops_t AcodecOps; +}; +typedef struct nu_i2s *nu_i2s_t; + +#endif // __DRV_I2S_H___ diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_pdma.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_pdma.c new file mode 100644 index 0000000000..1e9dcdc3d7 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_pdma.c @@ -0,0 +1,1013 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-9-7 Philo First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_PDMA) + +#include +#include +#include +#include + +/* Private define ---------------------------------------------------------------*/ +// RT_DEV_NAME_PREFIX pdma + +#ifndef NU_PDMA_MEMFUN_ACTOR_MAX + #define NU_PDMA_MEMFUN_ACTOR_MAX (4) +#endif + +#define NU_PDMA_SG_TBL_MAXSIZE (NU_PDMA_SG_LIMITED_DISTANCE/sizeof(DSCT_T)) + +#define NU_PDMA_CH_MAX (PDMA_CH_MAX) /* Specify maximum channels of PDMA */ +#define NU_PDMA_CH_Pos (0) /* Specify first channel number of PDMA */ +#define NU_PDMA_CH_Msk (((1 << NU_PDMA_CH_MAX) - 1) << NU_PDMA_CH_Pos) + +/* Private typedef --------------------------------------------------------------*/ +struct nu_pdma_periph_ctl +{ + uint32_t m_u32Peripheral; + nu_pdma_memctrl_t m_eMemCtl; +}; +typedef struct nu_pdma_periph_ctl nu_pdma_periph_ctl_t; + +struct nu_pdma_chn +{ + nu_pdma_cb_handler_t m_pfnCBHandler; + void *m_pvUserData; + uint32_t m_u32EventFilter; + uint32_t m_u32IdleTimeout_us; + nu_pdma_periph_ctl_t m_spPeripCtl; +}; +typedef struct nu_pdma_chn nu_pdma_chn_t; + +struct nu_pdma_memfun_actor +{ + int m_i32ChannID; + uint32_t m_u32Result; + rt_sem_t m_psSemMemFun; +} ; +typedef struct nu_pdma_memfun_actor *nu_pdma_memfun_actor_t; + +/* Private functions ------------------------------------------------------------*/ +static int nu_pdma_peripheral_set(uint32_t u32PeriphType); +static void nu_pdma_init(void); +static void nu_pdma_channel_enable(int i32ChannID); +static void nu_pdma_channel_disable(int i32ChannID); +static void nu_pdma_channel_reset(int i32ChannID); +static rt_err_t nu_pdma_timeout_set(int i32ChannID, int i32Timeout_us); +static void nu_pdma_periph_ctrl_fill(int i32ChannID, int i32CtlPoolIdx); +static rt_size_t nu_pdma_memfun(void *dest, void *src, uint32_t u32DataWidth, unsigned int count, nu_pdma_memctrl_t eMemCtl); +static void nu_pdma_memfun_cb(void *pvUserData, uint32_t u32Events); +static void nu_pdma_memfun_actor_init(void); +static int nu_pdma_memfun_employ(void); +static int nu_pdma_non_transfer_count_get(int32_t i32ChannID); + +/* Public functions -------------------------------------------------------------*/ + + +/* Private variables ------------------------------------------------------------*/ +static volatile int nu_pdma_inited = 0; +static volatile uint32_t nu_pdma_chn_mask = 0; +static nu_pdma_chn_t nu_pdma_chn_arr[NU_PDMA_CH_MAX]; +static rt_mutex_t g_mutex_res = RT_NULL; +static volatile uint32_t nu_pdma_memfun_actor_mask = 0; +static volatile uint32_t nu_pdma_memfun_actor_maxnum = 0; +static rt_sem_t nu_pdma_memfun_actor_pool_sem = RT_NULL; +static rt_mutex_t nu_pdma_memfun_actor_pool_lock = RT_NULL; + +static const nu_pdma_periph_ctl_t g_nu_pdma_peripheral_ctl_pool[ ] = +{ + // M2M + { PDMA_MEM, eMemCtl_SrcInc_DstInc }, + + // M2P + { PDMA_UART0_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_UART1_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_UART2_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_UART3_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_UART4_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_UART5_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_UART6_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_UART7_TX, eMemCtl_SrcInc_DstFix }, + + { PDMA_USCI0_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_USCI1_TX, eMemCtl_SrcInc_DstFix }, + + { PDMA_QSPI0_TX, eMemCtl_SrcInc_DstFix }, + + { PDMA_SPI0_TX, eMemCtl_SrcInc_DstFix }, + + { PDMA_I2C0_TX, eMemCtl_SrcInc_DstFix }, + { PDMA_I2C1_TX, eMemCtl_SrcInc_DstFix }, + + // P2M + { PDMA_UART0_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_UART1_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_UART2_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_UART3_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_UART4_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_UART5_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_UART6_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_UART7_RX, eMemCtl_SrcFix_DstInc }, + + { PDMA_USCI0_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_USCI1_RX, eMemCtl_SrcFix_DstInc }, + + { PDMA_QSPI0_RX, eMemCtl_SrcFix_DstInc }, + + { PDMA_SPI0_RX, eMemCtl_SrcFix_DstInc }, + + { PDMA_PWM0_P1_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_PWM0_P2_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_PWM0_P3_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_PWM1_P1_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_PWM1_P2_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_PWM1_P3_RX, eMemCtl_SrcFix_DstInc }, + + { PDMA_I2C0_RX, eMemCtl_SrcFix_DstInc }, + { PDMA_I2C1_RX, eMemCtl_SrcFix_DstInc }, + + { PDMA_TMR0, eMemCtl_SrcFix_DstInc }, + { PDMA_TMR1, eMemCtl_SrcFix_DstInc }, + { PDMA_TMR2, eMemCtl_SrcFix_DstInc }, + { PDMA_TMR3, eMemCtl_SrcFix_DstInc }, + + { PDMA_ADC_RX, eMemCtl_SrcFix_DstInc }, +}; +#define NU_PERIPHERAL_SIZE ( sizeof(g_nu_pdma_peripheral_ctl_pool) / sizeof(g_nu_pdma_peripheral_ctl_pool[0]) ) + +static struct nu_pdma_memfun_actor nu_pdma_memfun_actor_arr[NU_PDMA_MEMFUN_ACTOR_MAX]; + +/* SG table pool */ +static DSCT_T nu_pdma_sgtbl_arr[NU_PDMA_SGTBL_POOL_SIZE] = { 0 }; +static uint32_t nu_pdma_sgtbl_token[RT_ALIGN(NU_PDMA_SGTBL_POOL_SIZE, 32) / 32]; +static rt_mutex_t g_mutex_sg = RT_NULL; + +static int nu_pdma_peripheral_set(uint32_t u32PeriphType) +{ + int idx = 0; + + while (idx < NU_PERIPHERAL_SIZE) + { + if (g_nu_pdma_peripheral_ctl_pool[idx].m_u32Peripheral == u32PeriphType) + return idx; + idx++; + } + + // Not such peripheral + return -1; +} + +static void nu_pdma_periph_ctrl_fill(int i32ChannID, int i32CtlPoolIdx) +{ + nu_pdma_chn_t *psPdmaChann = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos]; + psPdmaChann->m_spPeripCtl.m_u32Peripheral = g_nu_pdma_peripheral_ctl_pool[i32CtlPoolIdx].m_u32Peripheral; + psPdmaChann->m_spPeripCtl.m_eMemCtl = g_nu_pdma_peripheral_ctl_pool[i32CtlPoolIdx].m_eMemCtl; +} + +static void nu_pdma_init(void) +{ + int latest = 0; + if (nu_pdma_inited) + return; + + g_mutex_res = rt_mutex_create("pdmalock", RT_IPC_FLAG_PRIO); + RT_ASSERT(g_mutex_res != RT_NULL); + + g_mutex_sg = rt_mutex_create("sgtbles", RT_IPC_FLAG_PRIO); + RT_ASSERT(g_mutex_sg != RT_NULL); + + nu_pdma_chn_mask = ~NU_PDMA_CH_Msk; + rt_memset(nu_pdma_chn_arr, 0x00, sizeof(nu_pdma_chn_t)); + + NVIC_EnableIRQ(PDMA_IRQn); + + /* Initialize PDMA setting */ + PDMA_Open(PDMA, NU_PDMA_CH_Msk); + PDMA_Close(PDMA); + + rt_memset(&nu_pdma_sgtbl_arr[0], 0x00, sizeof(nu_pdma_sgtbl_arr)); + + /* Assign first SG table address as PDMA SG table base address */ + PDMA->SCATBA = (uint32_t)&nu_pdma_sgtbl_arr[0]; + + /* Initializa token pool. */ + rt_memset(&nu_pdma_sgtbl_token[0], 0xff, sizeof(nu_pdma_sgtbl_token)); + latest = NU_PDMA_SGTBL_POOL_SIZE / 32; + nu_pdma_sgtbl_token[latest] ^= ~((1 << (NU_PDMA_SGTBL_POOL_SIZE % 32)) - 1) ; + + nu_pdma_inited = 1; +} + +static void nu_pdma_channel_enable(int i32ChannID) +{ + PDMA_Open(PDMA, 1 << i32ChannID); +} + +static inline void nu_pdma_channel_disable(int i32ChannID) +{ + PDMA->CHCTL &= ~(1 << i32ChannID); +} + +static inline void nu_pdma_channel_reset(int i32ChannID) +{ + PDMA->CHRST = (1 << i32ChannID); +} + +void nu_pdma_channel_terminate(int i32ChannID) +{ + int i; + uint32_t u32EnabledChans; + int ch_mask = 0; + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_pdma_channel_terminate; + + rt_mutex_take(g_mutex_res, RT_WAITING_FOREVER); + + // Suspend all channels. + u32EnabledChans = nu_pdma_chn_mask & NU_PDMA_CH_Msk; + while ((i = nu_ctz(u32EnabledChans)) != 32) + { + ch_mask = (1 << i); + if (i == i32ChannID) + { + u32EnabledChans &= ~ch_mask; + continue; + } + + // Pause the channel + PDMA_PAUSE(PDMA, i); + + // Wait for channel to finish current transfer + while (PDMA->TACTSTS & ch_mask) { } + + u32EnabledChans &= ~ch_mask; + } //while + + // Reset specified channel ID + nu_pdma_channel_reset(i32ChannID); + + // Clean descriptor table control register. + PDMA->DSCT[i32ChannID].CTL = 0UL; + + // Resume all channels. + u32EnabledChans = nu_pdma_chn_mask & NU_PDMA_CH_Msk; + while ((i = nu_ctz(u32EnabledChans)) != 32) + { + ch_mask = (1 << i); + + PDMA->CHCTL |= ch_mask; + PDMA_Trigger(PDMA, i); + u32EnabledChans &= ~ch_mask; + } + + rt_mutex_release(g_mutex_res); + +exit_pdma_channel_terminate: + + return; +} + +static rt_err_t nu_pdma_timeout_set(int i32ChannID, int i32Timeout_us) +{ + rt_err_t ret = RT_EINVAL; + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_timeout_set; + + nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_u32IdleTimeout_us = i32Timeout_us; + + if (i32Timeout_us && i32ChannID <= 1) // M480 limit + { + uint32_t u32ToClk_Max = 1000000 / (CLK_GetHCLKFreq() / (1 << 8)); + uint32_t u32Divider = (i32Timeout_us / u32ToClk_Max) / (1 << 16); + uint32_t u32TOutCnt = (i32Timeout_us / u32ToClk_Max) % (1 << 16); + + PDMA_DisableTimeout(PDMA, 1 << i32ChannID); + PDMA_EnableInt(PDMA, i32ChannID, PDMA_INT_TIMEOUT); // Interrupt type + + if (u32Divider > 7) + { + u32Divider = 7; + u32TOutCnt = (1 << 16); + } + PDMA->TOUTPSC |= (u32Divider << (PDMA_TOUTPSC_TOUTPSC1_Pos * i32ChannID)); + PDMA_SetTimeOut(PDMA, i32ChannID, 1, u32TOutCnt); + + ret = RT_EOK; + } + else + { + PDMA_DisableInt(PDMA, i32ChannID, PDMA_INT_TIMEOUT); // Interrupt type + PDMA_DisableTimeout(PDMA, 1 << i32ChannID); + } + +exit_nu_pdma_timeout_set: + + return -(ret); +} + +int nu_pdma_channel_allocate(int32_t i32PeripType) +{ + int i, i32PeripCtlIdx; + + nu_pdma_init(); + + if ((i32PeripCtlIdx = nu_pdma_peripheral_set(i32PeripType)) < 0) + goto exit_nu_pdma_channel_allocate; + + /* Find the position of first '0' in nu_pdma_chn_mask. */ + i = nu_cto(nu_pdma_chn_mask); + if (i != 32) + { + nu_pdma_chn_mask |= (1 << i); + rt_memset(nu_pdma_chn_arr + i - NU_PDMA_CH_Pos, 0x00, sizeof(nu_pdma_chn_t)); + + /* Set idx number of g_nu_pdma_peripheral_ctl_pool */ + nu_pdma_periph_ctrl_fill(i, i32PeripCtlIdx); + + /* Reset channel */ + nu_pdma_channel_reset(i); + + nu_pdma_channel_enable(i); + + return i; + } + +exit_nu_pdma_channel_allocate: + // No channel available + return -(RT_ERROR); +} + +rt_err_t nu_pdma_channel_free(int i32ChannID) +{ + rt_err_t ret = RT_EINVAL; + + if (! nu_pdma_inited) + goto exit_nu_pdma_channel_free; + + if (i32ChannID < NU_PDMA_CH_MAX && i32ChannID >= NU_PDMA_CH_Pos) + { + nu_pdma_chn_mask &= ~(1 << i32ChannID); + nu_pdma_channel_disable(i32ChannID); + ret = RT_EOK; + } +exit_nu_pdma_channel_free: + + return -(ret); +} + +rt_err_t nu_pdma_callback_register(int i32ChannID, nu_pdma_cb_handler_t pfnHandler, void *pvUserData, uint32_t u32EventFilter) +{ + rt_err_t ret = RT_EINVAL; + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_callback_register; + + nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_pfnCBHandler = pfnHandler; + nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_pvUserData = pvUserData; + nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_u32EventFilter = u32EventFilter; + + ret = RT_EOK; + +exit_nu_pdma_callback_register: + + return -(ret) ; +} + +nu_pdma_cb_handler_t nu_pdma_callback_hijack(int i32ChannID, nu_pdma_cb_handler_t *ppfnHandler_Hijack, + void **ppvUserData_Hijack, uint32_t *pu32Events_Hijack) +{ + nu_pdma_cb_handler_t pfnHandler_Org = NULL; + void *pvUserData_Org; + uint32_t u32Events_Org; + + RT_ASSERT(ppfnHandler_Hijack != NULL); + RT_ASSERT(ppvUserData_Hijack != NULL); + RT_ASSERT(pu32Events_Hijack != NULL); + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_callback_hijack; + + pfnHandler_Org = nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_pfnCBHandler; + pvUserData_Org = nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_pvUserData; + u32Events_Org = nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_u32EventFilter; + + nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_pfnCBHandler = *ppfnHandler_Hijack; + nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_pvUserData = *ppvUserData_Hijack; + nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_u32EventFilter = *pu32Events_Hijack; + + *ppfnHandler_Hijack = pfnHandler_Org; + *ppvUserData_Hijack = pvUserData_Org; + *pu32Events_Hijack = u32Events_Org; + +exit_nu_pdma_callback_hijack: + + return pfnHandler_Org; +} + +static int nu_pdma_non_transfer_count_get(int32_t i32ChannID) +{ + return ((PDMA->DSCT[i32ChannID].CTL & PDMA_DSCT_CTL_TXCNT_Msk) >> PDMA_DSCT_CTL_TXCNT_Pos) + 1; +} + +int nu_pdma_transferred_byte_get(int32_t i32ChannID, int32_t i32TriggerByteLen) +{ + int i32BitWidth = 0; + int cur_txcnt = 0; + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_transferred_byte_get; + + i32BitWidth = PDMA->DSCT[i32ChannID].CTL & PDMA_DSCT_CTL_TXWIDTH_Msk; + i32BitWidth = (i32BitWidth == PDMA_WIDTH_8) ? 1 : (i32BitWidth == PDMA_WIDTH_16) ? 2 : (i32BitWidth == PDMA_WIDTH_32) ? 4 : 0; + + cur_txcnt = nu_pdma_non_transfer_count_get(i32ChannID); + + return (i32TriggerByteLen - (cur_txcnt) * i32BitWidth); + +exit_nu_pdma_transferred_byte_get: + + return -1; +} + +nu_pdma_memctrl_t nu_pdma_channel_memctrl_get(int i32ChannID) +{ + nu_pdma_memctrl_t eMemCtrl = eMemCtl_Undefined; + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_channel_memctrl_get; + + eMemCtrl = nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_spPeripCtl.m_eMemCtl; + +exit_nu_pdma_channel_memctrl_get: + + return eMemCtrl; +} + +rt_err_t nu_pdma_channel_memctrl_set(int i32ChannID, nu_pdma_memctrl_t eMemCtrl) +{ + rt_err_t ret = RT_EINVAL; + nu_pdma_chn_t *psPdmaChann = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos]; + + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_channel_memctrl_set; + else if ((eMemCtrl < eMemCtl_SrcFix_DstFix) || (eMemCtrl > eMemCtl_SrcInc_DstInc)) + goto exit_nu_pdma_channel_memctrl_set; + + /* PDMA_MEM/SAR_FIX/BURST mode is not supported. */ + if ((psPdmaChann->m_spPeripCtl.m_u32Peripheral == PDMA_MEM) && + ((eMemCtrl == eMemCtl_SrcFix_DstInc) || (eMemCtrl == eMemCtl_SrcFix_DstFix))) + goto exit_nu_pdma_channel_memctrl_set; + + nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_spPeripCtl.m_eMemCtl = eMemCtrl; + + ret = RT_EOK; + +exit_nu_pdma_channel_memctrl_set: + + return -(ret); +} + +static void nu_pdma_channel_memctrl_fill(nu_pdma_memctrl_t eMemCtl, uint32_t *pu32SrcCtl, uint32_t *pu32DstCtl) +{ + switch ((int)eMemCtl) + { + case eMemCtl_SrcFix_DstFix: + *pu32SrcCtl = PDMA_SAR_FIX; + *pu32DstCtl = PDMA_DAR_FIX; + break; + case eMemCtl_SrcFix_DstInc: + *pu32SrcCtl = PDMA_SAR_FIX; + *pu32DstCtl = PDMA_DAR_INC; + break; + case eMemCtl_SrcInc_DstFix: + *pu32SrcCtl = PDMA_SAR_INC; + *pu32DstCtl = PDMA_DAR_FIX; + break; + case eMemCtl_SrcInc_DstInc: + *pu32SrcCtl = PDMA_SAR_INC; + *pu32DstCtl = PDMA_DAR_INC; + break; + default: + break; + } +} + +/* This is for Scatter-gather DMA. */ +rt_err_t nu_pdma_desc_setup(int i32ChannID, nu_pdma_desc_t dma_desc, uint32_t u32DataWidth, uint32_t u32AddrSrc, + uint32_t u32AddrDst, int32_t i32TransferCnt, nu_pdma_desc_t next) +{ + nu_pdma_periph_ctl_t *psPeriphCtl = NULL; + + uint32_t u32SrcCtl = 0; + uint32_t u32DstCtl = 0; + + rt_err_t ret = RT_EINVAL; + + if (!dma_desc) + goto exit_nu_pdma_desc_setup; + else if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_desc_setup; + else if (!(u32DataWidth == 8 || u32DataWidth == 16 || u32DataWidth == 32)) + goto exit_nu_pdma_desc_setup; + else if ((u32AddrSrc % (u32DataWidth / 8)) || (u32AddrDst % (u32DataWidth / 8))) + goto exit_nu_pdma_desc_setup; + else if (i32TransferCnt > NU_PDMA_MAX_TXCNT) + goto exit_nu_pdma_desc_setup; + + psPeriphCtl = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_spPeripCtl; + + nu_pdma_channel_memctrl_fill(psPeriphCtl->m_eMemCtl, &u32SrcCtl, &u32DstCtl); + + dma_desc->CTL = ((i32TransferCnt - 1) << PDMA_DSCT_CTL_TXCNT_Pos) | + ((u32DataWidth == 8) ? PDMA_WIDTH_8 : (u32DataWidth == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32) | + u32SrcCtl | + u32DstCtl | + PDMA_OP_BASIC; + + dma_desc->SA = u32AddrSrc; + dma_desc->DA = u32AddrDst; + dma_desc->NEXT = 0; /* Terminating node by default. */ + + if (psPeriphCtl->m_u32Peripheral == PDMA_MEM) + { + /* For M2M transfer */ + dma_desc->CTL |= (PDMA_REQ_BURST | PDMA_BURST_32); + } + else + { + /* For P2M and M2P transfer */ + dma_desc->CTL |= (PDMA_REQ_SINGLE); + } + + if (next) + { + /* Link to Next and modify to scatter-gather DMA mode. */ + dma_desc->CTL = (dma_desc->CTL & ~PDMA_DSCT_CTL_OPMODE_Msk) | PDMA_OP_SCATTER; + dma_desc->NEXT = (uint32_t)next - (PDMA->SCATBA); + } + + ret = RT_EOK; + +exit_nu_pdma_desc_setup: + + return -(ret); +} + +static int nu_pdma_sgtbls_token_allocate(void) +{ + int idx, i; + + int pool_size = sizeof(nu_pdma_sgtbl_token) / sizeof(uint32_t); + + for (i = 0; i < pool_size; i++) + { + if ((idx = nu_ctz(nu_pdma_sgtbl_token[i])) != 32) + { + nu_pdma_sgtbl_token[i] &= ~(1 << idx); + idx += i * 32; + return idx; + } + } + + /* No available */ + return -1; +} + +static void nu_pdma_sgtbls_token_free(nu_pdma_desc_t psSgtbls) +{ + int idx = (int)(psSgtbls - &nu_pdma_sgtbl_arr[0]); + RT_ASSERT(idx >= 0); + RT_ASSERT((idx + 1) <= NU_PDMA_SGTBL_POOL_SIZE); + nu_pdma_sgtbl_token[idx / 32] |= (1 << (idx % 32)); +} + +rt_err_t nu_pdma_sgtbls_allocate(nu_pdma_desc_t *ppsSgtbls, int num) +{ + int i, j, idx; + + RT_ASSERT(ppsSgtbls != NULL); + RT_ASSERT(num <= NU_PDMA_SG_TBL_MAXSIZE); + + rt_mutex_take(g_mutex_sg, RT_WAITING_FOREVER); + + for (i = 0; i < num; i++) + { + ppsSgtbls[i] = NULL; + /* Get token. */ + if ((idx = nu_pdma_sgtbls_token_allocate()) < 0) + { + rt_kprintf("No available sgtbl.\n"); + goto fail_nu_pdma_sgtbls_allocate; + } + + ppsSgtbls[i] = (nu_pdma_desc_t)&nu_pdma_sgtbl_arr[idx]; + } + + rt_mutex_release(g_mutex_sg); + + return RT_EOK; + +fail_nu_pdma_sgtbls_allocate: + + /* Release allocated tables. */ + for (j = 0; j < i; j++) + { + if (ppsSgtbls[j] != NULL) + { + nu_pdma_sgtbls_token_free(ppsSgtbls[j]); + } + ppsSgtbls[j] = NULL; + } + + rt_mutex_release(g_mutex_sg); + return -RT_ERROR; +} + +void nu_pdma_sgtbls_free(nu_pdma_desc_t *ppsSgtbls, int num) +{ + int i; + + RT_ASSERT(ppsSgtbls != NULL); + RT_ASSERT(num <= NU_PDMA_SG_TBL_MAXSIZE); + + rt_mutex_take(g_mutex_sg, RT_WAITING_FOREVER); + + for (i = 0; i < num; i++) + { + if (ppsSgtbls[i] != NULL) + { + nu_pdma_sgtbls_token_free(ppsSgtbls[i]); + } + ppsSgtbls[i] = NULL; + } + + rt_mutex_release(g_mutex_sg); +} + +static rt_err_t nu_pdma_sgtbls_valid(nu_pdma_desc_t head) +{ + uint32_t node_addr; + nu_pdma_desc_t node = head; + + do + { + node_addr = (uint32_t)node; + if ((node_addr < PDMA->SCATBA) || (node_addr - PDMA->SCATBA) >= NU_PDMA_SG_LIMITED_DISTANCE) + { + rt_kprintf("The distance is over %d between 0x%08x and 0x%08x. \n", NU_PDMA_SG_LIMITED_DISTANCE, PDMA->SCATBA, node); + rt_kprintf("Please use nu_pdma_sgtbl_allocate to allocate valid sg-table.\n"); + return RT_ERROR; + } + + node = (nu_pdma_desc_t)(node->NEXT + PDMA->SCATBA); + + } + while (((uint32_t)node != PDMA->SCATBA) && (node != head)); + + return RT_EOK; +} + +static void _nu_pdma_transfer(int i32ChannID, uint32_t u32Peripheral, nu_pdma_desc_t head, uint32_t u32IdleTimeout_us) +{ + PDMA_DisableTimeout(PDMA, 1 << i32ChannID); + + PDMA_EnableInt(PDMA, i32ChannID, PDMA_INT_TRANS_DONE); + + nu_pdma_timeout_set(i32ChannID, u32IdleTimeout_us); + + /* Set scatter-gather mode and head */ + PDMA_SetTransferMode(PDMA, + i32ChannID, + u32Peripheral, + (head->NEXT != 0) ? 1 : 0, + (uint32_t)head); + + /* If peripheral is M2M, trigger it. */ + if (u32Peripheral == PDMA_MEM) + PDMA_Trigger(PDMA, i32ChannID); +} + +rt_err_t nu_pdma_transfer(int i32ChannID, uint32_t u32DataWidth, uint32_t u32AddrSrc, uint32_t u32AddrDst, int32_t i32TransferCnt, uint32_t u32IdleTimeout_us) +{ + rt_err_t ret = RT_EINVAL; + + nu_pdma_periph_ctl_t *psPeriphCtl = NULL; + + if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_transfer; + + psPeriphCtl = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_spPeripCtl; + + ret = nu_pdma_desc_setup(i32ChannID, + &PDMA->DSCT[i32ChannID], + u32DataWidth, + u32AddrSrc, + u32AddrDst, + i32TransferCnt, + NULL); + if (ret != RT_EOK) + goto exit_nu_pdma_transfer; + + _nu_pdma_transfer(i32ChannID, psPeriphCtl->m_u32Peripheral, &PDMA->DSCT[i32ChannID], u32IdleTimeout_us); + + ret = RT_EOK; + +exit_nu_pdma_transfer: + + return -(ret); +} + +rt_err_t nu_pdma_sg_transfer(int i32ChannID, nu_pdma_desc_t head, uint32_t u32IdleTimeout_us) +{ + rt_err_t ret = RT_EINVAL; + nu_pdma_periph_ctl_t *psPeriphCtl = NULL; + + if (!head) + goto exit_nu_pdma_sg_transfer; + else if (!(nu_pdma_chn_mask & (1 << i32ChannID))) + goto exit_nu_pdma_sg_transfer; + else if ((ret = nu_pdma_sgtbls_valid(head)) != RT_EOK) /* Check SG-tbls. */ + goto exit_nu_pdma_sg_transfer; + + psPeriphCtl = &nu_pdma_chn_arr[i32ChannID - NU_PDMA_CH_Pos].m_spPeripCtl; + + _nu_pdma_transfer(i32ChannID, psPeriphCtl->m_u32Peripheral, head, u32IdleTimeout_us); + + ret = RT_EOK; + +exit_nu_pdma_sg_transfer: + + return -(ret); +} + +void PDMA_IRQHandler(void) +{ + int i; + + /* enter interrupt */ + rt_interrupt_enter(); + + uint32_t intsts = PDMA_GET_INT_STATUS(PDMA); + uint32_t abtsts = PDMA_GET_ABORT_STS(PDMA); + uint32_t tdsts = PDMA_GET_TD_STS(PDMA); + uint32_t reqto = intsts & (PDMA_INTSTS_REQTOF0_Msk | PDMA_INTSTS_REQTOF1_Msk); + uint32_t reqto_ch = ((reqto & PDMA_INTSTS_REQTOF0_Msk) ? (1 << 0) : 0x0) | ((reqto & PDMA_INTSTS_REQTOF1_Msk) ? (1 << 1) : 0x0); + + int allch_sts = (reqto_ch | tdsts | abtsts); + + // Abort + if (intsts & PDMA_INTSTS_ABTIF_Msk) + { + // Clear all Abort flags + PDMA_CLR_ABORT_FLAG(PDMA, abtsts); + } + + // Transfer done + if (intsts & PDMA_INTSTS_TDIF_Msk) + { + // Clear all transfer done flags + PDMA_CLR_TD_FLAG(PDMA, tdsts); + } + + // Timeout + if (reqto) + { + // Clear all Timeout flags + PDMA->INTSTS = reqto; + } + + // Find the position of first '1' in allch_sts. + while ((i = nu_ctz(allch_sts)) != 32) + { + int ch_mask = (1 << i); + + if (nu_pdma_chn_mask & ch_mask) + { + int ch_event = 0; + nu_pdma_chn_t *dma_chn = nu_pdma_chn_arr + i - NU_PDMA_CH_Pos; + + if (dma_chn->m_pfnCBHandler) + { + if (abtsts & ch_mask) + { + ch_event |= NU_PDMA_EVENT_ABORT; + } + + if (tdsts & ch_mask) ch_event |= NU_PDMA_EVENT_TRANSFER_DONE; + + if (reqto_ch & ch_mask) + { + PDMA_DisableTimeout(PDMA, ch_mask); + ch_event |= NU_PDMA_EVENT_TIMEOUT; + } + + if (dma_chn->m_u32EventFilter & ch_event) + dma_chn->m_pfnCBHandler(dma_chn->m_pvUserData, ch_event); + + if (reqto_ch & ch_mask) + nu_pdma_timeout_set(i, nu_pdma_chn_arr[i - NU_PDMA_CH_Pos].m_u32IdleTimeout_us); + + }//if(dma_chn->handler) + } //if (nu_pdma_chn_mask & ch_mask) + + // Clear the served bit. + allch_sts &= ~ch_mask; + + } //while + + /* leave interrupt */ + rt_interrupt_leave(); +} + +static void nu_pdma_memfun_actor_init(void) +{ + int i = 0 ; + nu_pdma_init(); + for (i = 0; i < NU_PDMA_MEMFUN_ACTOR_MAX; i++) + { + rt_memset(&nu_pdma_memfun_actor_arr[i], 0, sizeof(struct nu_pdma_memfun_actor)); + if (-(RT_ERROR) != (nu_pdma_memfun_actor_arr[i].m_i32ChannID = nu_pdma_channel_allocate(PDMA_MEM))) + { + nu_pdma_memfun_actor_arr[i].m_psSemMemFun = rt_sem_create("memactor_sem", 0, RT_IPC_FLAG_FIFO); + } + else + break; + } + if (i) + { + nu_pdma_memfun_actor_maxnum = i; + nu_pdma_memfun_actor_mask = ~(((1 << i) - 1)); + nu_pdma_memfun_actor_pool_sem = rt_sem_create("mempool_sem", nu_pdma_memfun_actor_maxnum, RT_IPC_FLAG_FIFO); + nu_pdma_memfun_actor_pool_lock = rt_mutex_create("mempool_lock", RT_IPC_FLAG_PRIO); + } +} + +static void nu_pdma_memfun_cb(void *pvUserData, uint32_t u32Events) +{ + nu_pdma_memfun_actor_t psMemFunActor = (nu_pdma_memfun_actor_t)pvUserData; + psMemFunActor->m_u32Result = u32Events; + rt_sem_release(psMemFunActor->m_psSemMemFun); +} + +static int nu_pdma_memfun_employ(void) +{ + int idx = -1 ; + + /* Headhunter */ + if (nu_pdma_memfun_actor_pool_sem && (rt_sem_take(nu_pdma_memfun_actor_pool_sem, RT_WAITING_FOREVER) == RT_EOK)) + { + rt_mutex_take(nu_pdma_memfun_actor_pool_lock, RT_WAITING_FOREVER); + /* Find the position of first '0' in nu_pdma_memfun_actor_mask. */ + idx = nu_cto(nu_pdma_memfun_actor_mask); + if (idx != 32) + { + nu_pdma_memfun_actor_mask |= (1 << idx); + } + else + { + idx = -1; + } + rt_mutex_release(nu_pdma_memfun_actor_pool_lock); + } + + return idx; +} + +static rt_size_t nu_pdma_memfun(void *dest, void *src, uint32_t u32DataWidth, unsigned int u32TransferCnt, nu_pdma_memctrl_t eMemCtl) +{ + nu_pdma_memfun_actor_t psMemFunActor = NULL; + int idx; + rt_size_t ret = 0; + rt_uint32_t u32Offset = 0; + rt_uint32_t u32TxCnt = 0; + + while (1) + { + /* Employ actor */ + if ((idx = nu_pdma_memfun_employ()) < 0) + continue; + + psMemFunActor = &nu_pdma_memfun_actor_arr[idx]; + + do + { + + u32TxCnt = (u32TransferCnt > NU_PDMA_MAX_TXCNT) ? NU_PDMA_MAX_TXCNT : u32TransferCnt; + + /* Set PDMA memory control to eMemCtl. */ + nu_pdma_channel_memctrl_set(psMemFunActor->m_i32ChannID, eMemCtl); + + /* Register ISR callback function */ + nu_pdma_callback_register(psMemFunActor->m_i32ChannID, nu_pdma_memfun_cb, (void *)psMemFunActor, NU_PDMA_EVENT_ABORT | NU_PDMA_EVENT_TRANSFER_DONE); + + psMemFunActor->m_u32Result = 0; + + /* Trigger it */ + nu_pdma_transfer(psMemFunActor->m_i32ChannID, + u32DataWidth, + (eMemCtl & 0x2ul) ? (uint32_t)src + u32Offset : (uint32_t)src, /* Src address is Inc or not. */ + (eMemCtl & 0x1ul) ? (uint32_t)dest + u32Offset : (uint32_t)dest, /* Dst address is Inc or not. */ + u32TxCnt, + 0); + + /* Wait it done. */ + rt_sem_take(psMemFunActor->m_psSemMemFun, RT_WAITING_FOREVER); + + /* Give result if get NU_PDMA_EVENT_TRANSFER_DONE.*/ + if (psMemFunActor->m_u32Result & NU_PDMA_EVENT_TRANSFER_DONE) + { + ret += u32TxCnt; + } + else + { + ret += (u32TxCnt - nu_pdma_non_transfer_count_get(psMemFunActor->m_i32ChannID)); + } + + /* Terminate it if get ABORT event */ + if (psMemFunActor->m_u32Result & NU_PDMA_EVENT_ABORT) + { + nu_pdma_channel_terminate(psMemFunActor->m_i32ChannID); + break; + } + + u32TransferCnt -= u32TxCnt; + u32Offset += u32TxCnt; + } + while (u32TransferCnt > 0); + + rt_mutex_take(nu_pdma_memfun_actor_pool_lock, RT_WAITING_FOREVER); + nu_pdma_memfun_actor_mask &= ~(1 << idx); + rt_mutex_release(nu_pdma_memfun_actor_pool_lock); + + /* Fire actor */ + rt_sem_release(nu_pdma_memfun_actor_pool_sem); + + break; + } + + return ret; +} + +rt_size_t nu_pdma_mempush(void *dest, void *src, uint32_t data_width, unsigned int transfer_count) +{ + if (data_width == 8 || data_width == 16 || data_width == 32) + return nu_pdma_memfun(dest, src, data_width, transfer_count, eMemCtl_SrcInc_DstFix); + return 0; +} + +void *nu_pdma_memcpy(void *dest, void *src, unsigned int count) +{ + int i = 0; + uint32_t u32Offset = 0; + uint32_t u32Remaining = count; + + for (i = 4; (i > 0) && (u32Remaining > 0) ; i >>= 1) + { + uint32_t u32src = (uint32_t)src + u32Offset; + uint32_t u32dest = (uint32_t)dest + u32Offset; + + if (((u32src % i) == (u32dest % i)) && + ((u32src % i) == 0) && + (RT_ALIGN_DOWN(u32Remaining, i) >= i)) + { + uint32_t u32TXCnt = u32Remaining / i; + if (u32TXCnt != nu_pdma_memfun((void *)u32dest, (void *)u32src, i * 8, u32TXCnt, eMemCtl_SrcInc_DstInc)) + goto exit_nu_pdma_memcpy; + + u32Offset += (u32TXCnt * i); + u32Remaining -= (u32TXCnt * i); + } + } + + if (count == u32Offset) + return dest; + +exit_nu_pdma_memcpy: + + return NULL; +} + +/** + * PDMA memfun actor initialization + */ +int rt_hw_pdma_memfun_init(void) +{ + nu_pdma_memfun_actor_init(); + return 0; +} +INIT_DEVICE_EXPORT(rt_hw_pdma_memfun_init); +#endif // #if defined(BSP_USING_PDMA) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_pdma.h b/bsp/nuvoton/libraries/m031/rtt_port/drv_pdma.h new file mode 100644 index 0000000000..abffd1c8b7 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_pdma.h @@ -0,0 +1,72 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-9-7 Philo First version +* +******************************************************************************/ + +#ifndef __DRV_PDMA_H__ +#define __DRV_PDMA_H__ + +#include +#include +#include "NuMicro.h" + +#ifndef NU_PDMA_SGTBL_POOL_SIZE + #define NU_PDMA_SGTBL_POOL_SIZE (16) +#endif + +#define NU_PDMA_CAP_NONE (0 << 0) + +#define NU_PDMA_EVENT_ABORT (1 << 0) +#define NU_PDMA_EVENT_TRANSFER_DONE (1 << 1) +#define NU_PDMA_EVENT_TIMEOUT (1 << 2) +#define NU_PDMA_EVENT_ALL (NU_PDMA_EVENT_ABORT | NU_PDMA_EVENT_TRANSFER_DONE | NU_PDMA_EVENT_TIMEOUT) +#define NU_PDMA_EVENT_MASK NU_PDMA_EVENT_ALL +#define NU_PDMA_UNUSED (-1) + +#define NU_PDMA_SG_LIMITED_DISTANCE ((PDMA_DSCT_NEXT_NEXT_Msk>>PDMA_DSCT_NEXT_NEXT_Pos)+1) +#define NU_PDMA_MAX_TXCNT ((PDMA_DSCT_CTL_TXCNT_Msk>>PDMA_DSCT_CTL_TXCNT_Pos) + 1) + +typedef enum +{ + eMemCtl_SrcFix_DstFix, + eMemCtl_SrcFix_DstInc, + eMemCtl_SrcInc_DstFix, + eMemCtl_SrcInc_DstInc, + eMemCtl_Undefined = (-1) +} nu_pdma_memctrl_t; + +typedef DSCT_T *nu_pdma_desc_t; + +typedef void (*nu_pdma_cb_handler_t)(void *, uint32_t); + +int nu_pdma_channel_allocate(int32_t i32PeripType); +rt_err_t nu_pdma_channel_free(int i32ChannID); +rt_err_t nu_pdma_callback_register(int i32ChannID, nu_pdma_cb_handler_t pfnHandler, void *pvUserData, uint32_t u32EventFilter); +rt_err_t nu_pdma_transfer(int i32ChannID, uint32_t u32DataWidth, uint32_t u32AddrSrc, uint32_t u32AddrDst, int32_t i32TransferCnt, uint32_t u32IdleTimeout_us); +int nu_pdma_transferred_byte_get(int32_t i32ChannID, int32_t i32TriggerByteLen); +void nu_pdma_channel_terminate(int i32ChannID); +nu_pdma_memctrl_t nu_pdma_channel_memctrl_get(int i32ChannID); +rt_err_t nu_pdma_channel_memctrl_set(int i32ChannID, nu_pdma_memctrl_t eMemCtrl); + +nu_pdma_cb_handler_t nu_pdma_callback_hijack(int i32ChannID, nu_pdma_cb_handler_t *ppfnHandler_Hijack, + void **ppvUserData_Hijack, uint32_t *pu32EventFilter_Hijack); + +// For scatter-gather DMA +rt_err_t nu_pdma_desc_setup(int i32ChannID, nu_pdma_desc_t dma_desc, uint32_t u32DataWidth, uint32_t u32AddrSrc, uint32_t u32AddrDst, int32_t TransferCnt, nu_pdma_desc_t next); +rt_err_t nu_pdma_sg_transfer(int i32ChannID, nu_pdma_desc_t head, uint32_t u32IdleTimeout_us); +rt_err_t nu_pdma_sgtbls_allocate(nu_pdma_desc_t *ppsSgtbls, int num); +void nu_pdma_sgtbls_free(nu_pdma_desc_t *ppsSgtbls, int num); + + +// For memory actor +void *nu_pdma_memcpy(void *dest, void *src, unsigned int count); +rt_size_t nu_pdma_mempush(void *dest, void *src, uint32_t data_width, unsigned int transfer_count); + +#endif // __DRV_PDMA_H___ diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_pwm.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_pwm.c new file mode 100644 index 0000000000..a500898c89 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_pwm.c @@ -0,0 +1,266 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-04 klcheng First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_PWM) + +#define LOG_TAG "drv.pwm" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include + +#include +#include +#include +#include "NuMicro.h" + +enum +{ + PWM_START = -1, +#if defined(BSP_USING_PWM0) + PWM0_IDX, +#endif +#if defined(BSP_USING_PWM1) + PWM1_IDX, +#endif + PWM_CNT +}; + +struct nu_pwm +{ + struct rt_device_pwm dev; + char *name; + PWM_T *pwm_base; + rt_int32_t pwm_period_time; +}; + +typedef struct nu_pwm *nu_pwm_t; + +static struct nu_pwm nu_pwm_arr [] = +{ +#if defined(BSP_USING_PWM0) + { + .name = "pwm0", + .pwm_base = PWM0, + }, +#endif + +#if defined(BSP_USING_PWM1) + { + .name = "pwm1", + .pwm_base = PWM1, + }, +#endif + {0} +}; /* pwm nu_pwm */ + +static rt_err_t nu_pwm_control(struct rt_device_pwm *device, int cmd, void *arg); + +static struct rt_pwm_ops nu_pwm_ops = +{ + .control = nu_pwm_control +}; + +static rt_err_t nu_pwm_enable(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration, rt_bool_t enable) +{ + rt_err_t result = RT_EOK; + + PWM_T *pwm_base = ((nu_pwm_t)device)->pwm_base; + rt_uint32_t pwm_channel = ((struct rt_pwm_configuration *)configuration)->channel; + + if (enable == RT_TRUE) + { + PWM_EnableOutput(pwm_base, 1 << pwm_channel); + PWM_Start(pwm_base, 1 << pwm_channel); + } + else + { + PWM_DisableOutput(pwm_base, 1 << pwm_channel); + PWM_ForceStop(pwm_base, 1 << pwm_channel); + } + + return result; +} + +static rt_err_t nu_pwm_set(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration) +{ + if ((((struct rt_pwm_configuration *)configuration)->period) <= 0) + return -(RT_ERROR); + rt_uint8_t pwm_channel_pair; + rt_uint32_t pwm_freq, pwm_dutycycle ; + PWM_T *pwm_base = ((nu_pwm_t)device)->pwm_base; + rt_uint8_t pwm_channel = ((struct rt_pwm_configuration *)configuration)->channel; + rt_uint32_t pwm_period = ((struct rt_pwm_configuration *)configuration)->period; + rt_uint32_t pwm_pulse = ((struct rt_pwm_configuration *)configuration)->pulse; + + //rt_uint32_t pre_pwm_prescaler = PWM_GET_PRESCALER(pwm_base, pwm_channel); + + if ((pwm_channel % 2) == 0) + pwm_channel_pair = pwm_channel + 1; + else + pwm_channel_pair = pwm_channel - 1; + + if (PWM_GET_CNR(pwm_base, pwm_channel_pair!= 0)) + { + pwm_period = ((nu_pwm_t)device)->pwm_period_time; + LOG_I("%s output frequency is determined, user can only change the duty\n", ((nu_pwm_t)device)->name); + } + else + { + ((nu_pwm_t)device)->pwm_period_time = pwm_period; + } + + pwm_freq = 1000000000 / pwm_period; + pwm_dutycycle = (pwm_pulse * 100) / pwm_period; + PWM_ConfigOutputChannel(pwm_base, pwm_channel, pwm_freq, pwm_dutycycle) ; + + return RT_EOK; +} + +static rt_uint32_t nu_pwm_clksr(struct rt_device_pwm *device) +{ + rt_uint32_t u32Src, u32PWMClockSrc; + PWM_T *pwm_base = ((nu_pwm_t)device)->pwm_base; + if (pwm_base == PWM0) + { + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_PWM0SEL_Msk; + } + else /* (pwm == PWM1) */ + { + u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_PWM1SEL_Msk; + } + + if (u32Src == 0U) + { + /* clock source is from PLL clock */ + u32PWMClockSrc = CLK_GetPLLClockFreq(); + } + else + { + /* clock source is from PCLK */ + SystemCoreClockUpdate(); + if (pwm_base == PWM0) + { + u32PWMClockSrc = CLK_GetPCLK0Freq(); + } + else /* (pwm == PWM1) */ + { + u32PWMClockSrc = CLK_GetPCLK1Freq(); + } + } + return u32PWMClockSrc; +} + +static rt_err_t nu_pwm_get(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration) +{ + rt_uint32_t pwm_real_period, pwm_real_duty, time_tick, u32PWMClockSrc ; + + PWM_T *pwm_base = ((nu_pwm_t)device)->pwm_base; + rt_uint32_t pwm_channel = ((struct rt_pwm_configuration *)configuration)->channel; + rt_uint32_t pwm_prescale = PWM_GET_PRESCALER(pwm_base, pwm_channel); + rt_uint32_t pwm_period = PWM_GET_CNR(pwm_base, pwm_channel); + rt_uint32_t pwm_pulse = PWM_GET_CMR(pwm_base, pwm_channel); + + u32PWMClockSrc = nu_pwm_clksr(device); + time_tick = 1000000000000 / u32PWMClockSrc; + + pwm_real_period = (((pwm_prescale + 1) * (pwm_period + 1)) * time_tick) / 1000; + pwm_real_duty = (((pwm_prescale + 1) * pwm_pulse * time_tick)) / 1000; + ((struct rt_pwm_configuration *)configuration)->period = pwm_real_period; + ((struct rt_pwm_configuration *)configuration)->pulse = pwm_real_duty; + + LOG_I("%s %d %d %d\n", ((nu_pwm_t)device)->name, configuration->channel, configuration->period, configuration->pulse); + + return RT_EOK; +} + +static rt_err_t nu_pwm_control(struct rt_device_pwm *device, int cmd, void *arg) +{ + struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + if (((((struct rt_pwm_configuration *)configuration)->channel) + 1) > PWM_CHANNEL_NUM) + return -(RT_ERROR); + + switch (cmd) + { + case PWM_CMD_ENABLE: + return nu_pwm_enable(device, configuration, RT_TRUE); + case PWM_CMD_DISABLE: + return nu_pwm_enable(device, configuration, RT_FALSE); + case PWM_CMD_SET: + return nu_pwm_set(device, configuration); + case PWM_CMD_GET: + return nu_pwm_get(device, configuration); + } + return -(RT_EINVAL); +} + +int rt_hw_pwm_init(void) +{ + rt_err_t ret; + int i; + + for (i = (PWM_START + 1); i < PWM_CNT; i++) + { + ret = rt_device_pwm_register(&nu_pwm_arr[i].dev, nu_pwm_arr[i].name, &nu_pwm_ops, RT_NULL); + RT_ASSERT(ret == RT_EOK); + } + + return 0; +} + +INIT_DEVICE_EXPORT(rt_hw_pwm_init); + +#ifdef RT_USING_FINSH +#include + +#ifdef FINSH_USING_MSH + +static int xpwm_get(int argc, char **argv) +{ + int result = 0; + struct rt_device_pwm *device = RT_NULL; + struct rt_pwm_configuration configuration = {0}; + + if (argc != 3) + { + rt_kprintf("Usage: pwm_get pwm1 1\n"); + result = -RT_ERROR; + goto _exit; + } + + device = (struct rt_device_pwm *)rt_device_find(argv[1]); + if (!device) + { + result = -RT_EIO; + goto _exit; + } + + configuration.channel = atoi(argv[2]); + result = rt_device_control(&device->parent, PWM_CMD_GET, &configuration); + +_exit: + return result; +} + +MSH_CMD_EXPORT(xpwm_get, xpwm_get ); + +#endif /* FINSH_USING_MSH */ +#endif /* RT_USING_FINSH */ + +#endif diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_pwm_capture.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_pwm_capture.c new file mode 100644 index 0000000000..0ea950c5d4 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_pwm_capture.c @@ -0,0 +1,334 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-17 klcheng First version +* +******************************************************************************/ +#include + +#if defined(BSP_USING_PWM_CAPTURE) +#if ((BSP_USING_PWM0_CAPTURE_CHMSK+BSP_USING_PWM1_CAPTURE_CHMSK)!=0) +#include +#include "NuMicro.h" + + +/* Private typedef --------------------------------------------------------------*/ +typedef struct nu_capture +{ + struct rt_inputcapture_device parent; + PWM_T *pwm; + uint8_t u8Channel; + IRQn_Type irq; + uint32_t u32CurrentRisingCnt; + uint32_t u32CurrentFallingCnt; + uint32_t u32LastRisingCnt; + uint32_t u32LastFallingCnt; + rt_bool_t input_data_level; + rt_bool_t pwm_init; + struct nu_capture *pair; +} nu_capture_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us); + +/* Public functions -------------------------------------------------------------*/ + + +/* Private variables ------------------------------------------------------------*/ +#if (BSP_USING_PWM0_CAPTURE_CHMSK!=0) +static const char *nu_pwm0_device_name[PWM_CHANNEL_NUM] = {"pwm0i0", "pwm0i1", "pwm0i2", "pwm0i3", "pwm0i4", "pwm0i5"}; +static nu_capture_t nu_pwm0_capture[PWM_CHANNEL_NUM] = {0}; +#endif + +#if (BSP_USING_PWM1_CAPTURE_CHMSK!=0) +static const char *nu_pwm1_device_name[PWM_CHANNEL_NUM] = {"pwm1i0", "pwm1i1", "pwm1i2", "pwm1i3", "pwm1i4", "pwm1i5"}; +static nu_capture_t nu_pwm1_capture[PWM_CHANNEL_NUM] = {0}; +#endif + +static struct rt_inputcapture_ops nu_capture_ops = +{ + .init = nu_capture_init, + .open = nu_capture_open, + .close = nu_capture_close, + .get_pulsewidth = nu_capture_get_pulsewidth, +}; + +/* Functions define ------------------------------------------------------------*/ +static rt_err_t CalPulseWidth(nu_capture_t *nu_capture) +{ + /* Read the capture counter value if falling/rising edge */ + if (PWM_GetCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel) == 1)//Rising edge + { + PWM_ClearCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_RISING_LATCH); + nu_capture->u32CurrentRisingCnt = PWM_GET_CAPTURE_RISING_DATA(nu_capture->pwm, nu_capture->u8Channel); + } + else if (PWM_GetCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel) == 2)//Falling edge + { + PWM_ClearCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_FALLING_LATCH); + nu_capture->u32CurrentFallingCnt += PWM_GET_CAPTURE_FALLING_DATA(nu_capture->pwm, nu_capture->u8Channel); + } + else + { + PWM_ClearCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_RISING_LATCH); + PWM_ClearCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_FALLING_LATCH); + + return -(RT_ERROR); + } + + return RT_EOK; +} + +#if (BSP_USING_PWM0_CAPTURE_CHMSK!=0) +void PWM0_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + for (uint8_t i = 0; i < PWM_CHANNEL_NUM ; i++) + { + if (PWM_GetCaptureIntFlag(nu_pwm0_capture[i].pwm, nu_pwm0_capture[i].u8Channel) != 0) + { + /* Calculate pulse width */ + if (CalPulseWidth(&nu_pwm0_capture[i]) == RT_EOK) + { + rt_hw_inputcapture_isr(&nu_pwm0_capture[i].parent, nu_pwm0_capture[i].input_data_level); + } + } + } + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif + + +#if (BSP_USING_PWM1_CAPTURE_CHMSK!=0) +void PWM1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + for (uint8_t i = 0; i < PWM_CHANNEL_NUM ; i++) + { + if (PWM_GetCaptureIntFlag(nu_pwm1_capture[i].pwm, nu_pwm1_capture[i].u8Channel) != 0) + { + /* Calculate pulse width */ + if (CalPulseWidth(&nu_pwm1_capture[i]) == RT_EOK) + { + rt_hw_inputcapture_isr(&nu_pwm1_capture[i].parent, nu_pwm1_capture[i].input_data_level); + } + } + } + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif + + +static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us) +{ + rt_err_t ret = RT_EOK; + nu_capture_t *nu_capture; + + nu_capture = (nu_capture_t *)inputcapture; + + if (nu_capture->u32CurrentFallingCnt) + { + if (nu_capture->u32CurrentFallingCnt > nu_capture->u32LastRisingCnt) + *pulsewidth_us = nu_capture->u32CurrentFallingCnt - nu_capture->u32LastRisingCnt; + else /* Overrun case */ + *pulsewidth_us = nu_capture->u32CurrentFallingCnt + (0x10000 - nu_capture->u32LastRisingCnt); + + nu_capture->input_data_level = RT_FALSE; + nu_capture->u32LastFallingCnt = nu_capture->u32CurrentFallingCnt; + nu_capture->u32CurrentFallingCnt = 0; + } + else if (nu_capture->u32CurrentRisingCnt) + { + if (nu_capture->u32CurrentRisingCnt > nu_capture->u32LastFallingCnt) + *pulsewidth_us = nu_capture->u32CurrentRisingCnt - nu_capture->u32LastFallingCnt; + else /* Overrun case */ + *pulsewidth_us = nu_capture->u32CurrentRisingCnt + (0x10000 - nu_capture->u32LastFallingCnt); + + nu_capture->input_data_level = RT_TRUE; + nu_capture->u32LastRisingCnt = nu_capture->u32CurrentRisingCnt; + nu_capture->u32CurrentRisingCnt = 0; + } + else + { + ret = RT_ERROR; + } + return -(ret); +} + +static rt_err_t nu_pwm_init(nu_capture_t *nu_capture) +{ + rt_err_t ret = RT_ERROR; + static rt_bool_t bPWM0Inited = RT_FALSE; + static rt_bool_t bPWM1Inited = RT_FALSE; + + if (nu_capture->pwm == PWM0) + { + if (bPWM0Inited == RT_FALSE) + { + /* Enable PWM0 clock */ + SYS_UnlockReg(); + CLK_EnableModuleClock(PWM0_MODULE); + CLK_SetModuleClock(PWM0_MODULE, CLK_CLKSEL2_PWM0SEL_PCLK0, 0); + SYS_LockReg(); + bPWM0Inited = RT_TRUE; + } + ret = RT_EOK; + } + else if (nu_capture->pwm == PWM1) + { + if (bPWM1Inited == RT_FALSE) + { + /* Enable PWM1 clock */ + SYS_UnlockReg(); + CLK_EnableModuleClock(PWM1_MODULE); + CLK_SetModuleClock(PWM1_MODULE, CLK_CLKSEL2_PWM1SEL_PCLK1, 0); + SYS_LockReg(); + bPWM1Inited = RT_TRUE; + } + ret = RT_EOK; + } + + return -(ret); +} + +static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture) +{ + rt_err_t ret = RT_EOK; + nu_capture_t *nu_capture; + + RT_ASSERT(inputcapture != RT_NULL); + + nu_capture = (nu_capture_t *) inputcapture; + + if (nu_pwm_init(nu_capture) != RT_EOK) + { + rt_kprintf("Failed to initialize PWM%d.\n", nu_capture->pwm); + ret = RT_ERROR; + } + + return -(ret); +} + +static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture) +{ + rt_err_t ret = RT_EOK; + nu_capture_t *nu_capture; + + RT_ASSERT(inputcapture != RT_NULL); + + nu_capture = (nu_capture_t *) inputcapture; + + /* Enable capture rising/falling edge interrupt */ + PWM_EnableCaptureInt(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_FALLING_LATCH | PWM_CAPTURE_INT_RISING_LATCH); + + /* Enable PWM NVIC interrupt */ + NVIC_EnableIRQ(nu_capture->irq); + + /* Enable Capture Function for PWM */ + PWM_EnableCapture(nu_capture->pwm, 0x1 << nu_capture->u8Channel); + + if ((nu_capture->pwm_init == RT_FALSE) && (nu_capture->pair->pwm_init == RT_FALSE)) + { + nu_capture->pwm_init = RT_TRUE; + + /* Set capture time as 1000 nanosecond */ + PWM_ConfigCaptureChannel(nu_capture->pwm, nu_capture->u8Channel, 1000, 0); + + /* Set counter type as down count */ + PWM_SET_ALIGNED_TYPE(nu_capture->pwm, 0x1 << nu_capture->u8Channel, PWM_UP_COUNTER); + + /* Enable PWM Timer */ + PWM_Start(nu_capture->pwm, 0x1 << nu_capture->u8Channel); + } + + return ret; +} + +static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture) +{ + rt_err_t ret = RT_EOK; + + nu_capture_t *nu_capture; + + RT_ASSERT(inputcapture != RT_NULL); + + nu_capture = (nu_capture_t *) inputcapture; + + /* Disable capture rising/falling edge interrupt */ + PWM_DisableCaptureInt(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_FALLING_LATCH | PWM_CAPTURE_INT_RISING_LATCH); + + /* Disable PWM NVIC interrupt */ + NVIC_DisableIRQ(nu_capture->irq); + + /* Enable PWM Timer */ + PWM_Stop(nu_capture->pwm, 0x1 << nu_capture->u8Channel); + + nu_capture->pwm_init = RT_FALSE; + + return ret; +} + +/* Init and register pwm capture */ +int nu_pwm_capture_device_init(void) +{ + /* Init PWM0 6 channel and PWM1 6 channel */ +#if (BSP_USING_PWM0_CAPTURE_CHMSK!=0) + for (int i = 0; i < PWM_CHANNEL_NUM; i++) + { + if (BSP_USING_PWM0_CAPTURE_CHMSK & (0x1 << i)) + { + nu_pwm0_capture[i].pwm = PWM0; + nu_pwm0_capture[i].u8Channel = i; + nu_pwm0_capture[i].irq = PWM0_IRQn; + nu_pwm0_capture[i].u32CurrentRisingCnt = 0; + nu_pwm0_capture[i].u32CurrentFallingCnt = 0; + nu_pwm0_capture[i].parent.ops = &nu_capture_ops; + nu_pwm0_capture[i].pair = &nu_pwm0_capture[((i>>1) << 1) == i? i+1 : i-1]; + nu_pwm0_capture[i].pwm_init = RT_FALSE; + + /* register inputcapture device */ + rt_device_inputcapture_register(&nu_pwm0_capture[i].parent, nu_pwm0_device_name[i], &nu_pwm0_capture[i]); + + } + } +#endif //#if (BSP_USING_PWM0_CAPTURE_CHMSK!=0) +#if (BSP_USING_PWM1_CAPTURE_CHMSK!=0) + for (int i = 0; i < PWM_CHANNEL_NUM; i++) + { + if (BSP_USING_PWM1_CAPTURE_CHMSK & (0x1 << i)) + { + nu_pwm1_capture[i].pwm = PWM1; + nu_pwm1_capture[i].u8Channel = i; + nu_pwm1_capture[i].irq = PWM1_IRQn; + nu_pwm1_capture[i].u32CurrentRisingCnt = 0; + nu_pwm1_capture[i].u32CurrentFallingCnt = 0; + nu_pwm1_capture[i].parent.ops = &nu_capture_ops; + nu_pwm1_capture[i].pair = &nu_pwm1_capture[((i>>1) << 1) == i? i+1 : i-1]; + nu_pwm1_capture[i].pwm_init = RT_FALSE; + + /* register inputcapture device */ + rt_device_inputcapture_register(&nu_pwm1_capture[i].parent, nu_pwm1_device_name[i], &nu_pwm1_capture[i]); + } + } +#endif //#if (BSP_USING_PWM1_CAPTURE_CHMSK!=0) + return 0; + +} +INIT_DEVICE_EXPORT(nu_pwm_capture_device_init); +#endif //#if ((BSP_USING_PWM0_CAPTURE_CHMSK+BSP_USING_PWM1_CAPTURE_CHMSK)!=0) +#endif //#if defined(BSP_USING_PWM_CAPTURE) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_qspi.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_qspi.c new file mode 100644 index 0000000000..1e08f396db --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_qspi.c @@ -0,0 +1,405 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-01-27 klcheng First version +* +******************************************************************************/ +#include + +#if defined(BSP_USING_QSPI) + +#define LOG_TAG "drv.qspi" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include + +#include +#include + +#include + +/* Private define ---------------------------------------------------------------*/ +enum +{ + QSPI_START = -1, +#if defined(BSP_USING_QSPI0) + QSPI0_IDX, +#endif + QSPI_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_qspi_bus_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration); +static rt_uint32_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message); +static int nu_qspi_register_bus(struct nu_spi *qspi_bus, const char *name); + +/* Public functions -------------------------------------------------------------*/ + +/* Private variables ------------------------------------------------------------*/ +static struct rt_spi_ops nu_qspi_poll_ops = +{ + .configure = nu_qspi_bus_configure, + .xfer = nu_qspi_bus_xfer, +}; + +static struct nu_spi nu_qspi_arr [] = +{ +#if defined(BSP_USING_QSPI0) + { + .name = "qspi0", + .spi_base = (SPI_T *)QSPI0, + +#if defined(BSP_USING_SPI_PDMA) +#if defined(BSP_USING_QSPI0_PDMA) + .pdma_perp_tx = PDMA_QSPI0_TX, + .pdma_perp_rx = PDMA_QSPI0_RX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + {0} +}; /* qspi nu_qspi */ + +static rt_err_t nu_qspi_bus_configure(struct rt_spi_device *device, + struct rt_spi_configuration *configuration) +{ + struct nu_spi *spi_bus; + rt_uint32_t u32SPIMode; + rt_uint32_t u32BusClock; + rt_err_t ret = RT_EOK; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + spi_bus = (struct nu_spi *) device->bus; + + /* Check mode */ + switch (configuration->mode & RT_SPI_MODE_3) + { + case RT_SPI_MODE_0: + u32SPIMode = SPI_MODE_0; + break; + case RT_SPI_MODE_1: + u32SPIMode = SPI_MODE_1; + break; + case RT_SPI_MODE_2: + u32SPIMode = SPI_MODE_2; + break; + case RT_SPI_MODE_3: + u32SPIMode = SPI_MODE_3; + break; + default: + ret = RT_EIO; + goto exit_nu_qspi_bus_configure; + } + + /* Check data width */ + if (!(configuration->data_width == 8 || + configuration->data_width == 16 || + configuration->data_width == 24 || + configuration->data_width == 32)) + { + ret = RT_EINVAL; + goto exit_nu_qspi_bus_configure; + } + + /* Try to set clock and get actual spi bus clock */ + u32BusClock = QSPI_SetBusClock((QSPI_T *)spi_bus->spi_base, configuration->max_hz); + if (configuration->max_hz > u32BusClock) + { + LOG_W("%s clock max frequency is %dHz (!= %dHz)\n", spi_bus->name, u32BusClock, configuration->max_hz); + configuration->max_hz = u32BusClock; + } + + /* Need to initialize new configuration? */ + if (rt_memcmp(configuration, &spi_bus->configuration, sizeof(struct rt_spi_configuration)) != 0) + { + rt_memcpy(&spi_bus->configuration, configuration, sizeof(struct rt_spi_configuration)); + + QSPI_Open((QSPI_T *)spi_bus->spi_base, SPI_MASTER, u32SPIMode, configuration->data_width, u32BusClock); + + if (configuration->mode & RT_SPI_CS_HIGH) + { + /* Set CS pin to LOW */ + SPI_SET_SS_LOW(spi_bus->spi_base); + } + else + { + /* Set CS pin to HIGH */ + SPI_SET_SS_HIGH(spi_bus->spi_base); + } + + if (configuration->mode & RT_SPI_MSB) + { + /* Set sequence to MSB first */ + SPI_SET_MSB_FIRST(spi_bus->spi_base); + } + else + { + /* Set sequence to LSB first */ + SPI_SET_LSB_FIRST(spi_bus->spi_base); + } + } + + /* Clear SPI RX FIFO */ + nu_spi_drain_rxfifo(spi_bus->spi_base); + +exit_nu_qspi_bus_configure: + + return -(ret); +} + +static int nu_qspi_mode_config(struct nu_spi *qspi_bus, rt_uint8_t *tx, rt_uint8_t *rx, int qspi_lines) +{ + QSPI_T *qspi_base = (QSPI_T *)qspi_bus->spi_base; +#if defined(RT_SFUD_USING_QSPI) + if (qspi_lines > 1) + { + if (tx) + { + switch (qspi_lines) + { + case 2: + QSPI_ENABLE_DUAL_OUTPUT_MODE(qspi_base); + break; + case 4: + QSPI_ENABLE_QUAD_OUTPUT_MODE(qspi_base); + break; + default: + LOG_E("Data line is not supported.\n"); + break; + } + } + else + { + switch (qspi_lines) + { + case 2: + QSPI_ENABLE_DUAL_INPUT_MODE(qspi_base); + break; + case 4: + QSPI_ENABLE_QUAD_INPUT_MODE(qspi_base); + break; + default: + LOG_E("Data line is not supported.\n"); + break; + } + } + } + else +#endif + { + QSPI_DISABLE_DUAL_MODE(qspi_base); + QSPI_DISABLE_QUAD_MODE(qspi_base); + } + return qspi_lines; +} + +static rt_uint32_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + struct nu_spi *qspi_bus; + struct rt_qspi_configuration *qspi_configuration; +#if defined(RT_SFUD_USING_QSPI) + struct rt_qspi_message *qspi_message; + rt_uint8_t u8last = 1; +#endif + rt_uint8_t bytes_per_word; + QSPI_T *qspi_base; + rt_uint32_t u32len = 0; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(message != RT_NULL); + + qspi_bus = (struct nu_spi *) device->bus; + qspi_base = (QSPI_T *)qspi_bus->spi_base; + qspi_configuration = &qspi_bus->configuration; + + bytes_per_word = qspi_configuration->parent.data_width / 8; + + if (message->cs_take && !(qspi_configuration->parent.mode & RT_SPI_NO_CS)) + { + if (qspi_configuration->parent.mode & RT_SPI_CS_HIGH) + { + QSPI_SET_SS_HIGH(qspi_base); + } + else + { + QSPI_SET_SS_LOW(qspi_base); + } + } + +#if defined(RT_SFUD_USING_QSPI) + qspi_message = (struct rt_qspi_message *)message; + + /* Command + Address + Dummy + Data */ + /* Command stage */ + if (qspi_message->instruction.content != 0) + { + u8last = nu_qspi_mode_config(qspi_bus, (rt_uint8_t *) &qspi_message->instruction.content, RT_NULL, qspi_message->instruction.qspi_lines); + nu_spi_transfer((struct nu_spi *)qspi_bus, + (rt_uint8_t *) &qspi_message->instruction.content, + RT_NULL, + 1, + 1); + } + + /* Address stage */ + if (qspi_message->address.size != 0) + { + rt_uint32_t u32ReversedAddr = 0; + rt_uint32_t u32AddrNumOfByte = qspi_message->address.size / 8; + switch (u32AddrNumOfByte) + { + case 1: + u32ReversedAddr = (qspi_message->address.content & 0xff); + break; + case 2: + nu_set16_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content); + break; + case 3: + nu_set24_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content); + break; + case 4: + nu_set32_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content); + break; + default: + RT_ASSERT(0); + break; + } + u8last = nu_qspi_mode_config(qspi_bus, (rt_uint8_t *)&u32ReversedAddr, RT_NULL, qspi_message->address.qspi_lines); + nu_spi_transfer((struct nu_spi *)qspi_bus, + (rt_uint8_t *) &u32ReversedAddr, + RT_NULL, + u32AddrNumOfByte, + 1); + } + + /* Dummy_cycles stage */ + if (qspi_message->dummy_cycles != 0) + { + qspi_bus->dummy = 0x00; + + u8last = nu_qspi_mode_config(qspi_bus, (rt_uint8_t *) &qspi_bus->dummy, RT_NULL, u8last); + nu_spi_transfer((struct nu_spi *)qspi_bus, + (rt_uint8_t *) &qspi_bus->dummy, + RT_NULL, + qspi_message->dummy_cycles / (8 / u8last), + 1); + } + /* Data stage */ + nu_qspi_mode_config(qspi_bus, (rt_uint8_t *) message->send_buf, (rt_uint8_t *) message->recv_buf, qspi_message->qspi_data_lines); +#else + /* Data stage */ + nu_qspi_mode_config(qspi_bus, RT_NULL, RT_NULL, 1); +#endif //#if defined(RT_SFUD_USING_QSPI) + + if (message->length != 0) + { + nu_spi_transfer((struct nu_spi *)qspi_bus, + (rt_uint8_t *) message->send_buf, + (rt_uint8_t *) message->recv_buf, + message->length, + bytes_per_word); + u32len = message->length; + } + else + { + u32len = 1; + } + + if (message->cs_release && !(qspi_configuration->parent.mode & RT_SPI_NO_CS)) + { + if (qspi_configuration->parent.mode & RT_SPI_CS_HIGH) + { + QSPI_SET_SS_LOW(qspi_base); + } + else + { + QSPI_SET_SS_HIGH(qspi_base); + } + } + + return u32len; +} + +static int nu_qspi_register_bus(struct nu_spi *qspi_bus, const char *name) +{ + return rt_qspi_bus_register(&qspi_bus->dev, name, &nu_qspi_poll_ops); +} + +/** + * Hardware SPI Initial + */ +static int rt_hw_qspi_init(void) +{ + rt_uint8_t i; + + for (i = (QSPI_START + 1); i < QSPI_CNT; i++) + { + nu_qspi_register_bus(&nu_qspi_arr[i], nu_qspi_arr[i].name); +#if defined(BSP_USING_SPI_PDMA) + nu_qspi_arr[i].pdma_chanid_tx = -1; + nu_qspi_arr[i].pdma_chanid_rx = -1; + + if ((nu_qspi_arr[i].pdma_perp_tx != NU_PDMA_UNUSED) && (nu_qspi_arr[i].pdma_perp_rx != NU_PDMA_UNUSED)) + { + if (nu_hw_spi_pdma_allocate(&nu_qspi_arr[i]) != RT_EOK) + { + LOG_E("Failed to allocate DMA channels for %s. We will use poll-mode for this bus.\n", nu_qspi_arr[i].name); + } + } +#endif + } + + return 0; +} +INIT_DEVICE_EXPORT(rt_hw_qspi_init); + +rt_err_t nu_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!\n"); + 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; +} + +#endif //#if defined(BSP_USING_QSPI) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_qspi.h b/bsp/nuvoton/libraries/m031/rtt_port/drv_qspi.h new file mode 100644 index 0000000000..87be3e6e42 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_qspi.h @@ -0,0 +1,20 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-2-7 Wayne First version +* +******************************************************************************/ + +#ifndef __DRV_QSPI_H__ +#define __DRV_QSPI_H__ + +#include + +rt_err_t nu_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)()); + +#endif // __DRV_QSPI_H___ diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_rtc.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_rtc.c new file mode 100644 index 0000000000..7c24e65b72 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_rtc.c @@ -0,0 +1,346 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-22 klcheng First version +* +******************************************************************************/ +#include +#if defined (BSP_USING_RTC) + +#include +#include +#include +#include "NuMicro.h" + +/* Private define ---------------------------------------------------------------*/ + +/* convert the real year and month value to the format of struct tm. */ +#define CONV_TO_TM_YEAR(year) ((year) - 1900) +#define CONV_TO_TM_MON(mon) ((mon) - 1) + +/* convert the tm_year and tm_mon from struct tm to the real value. */ +#define CONV_FROM_TM_YEAR(tm_year) ((tm_year) + 1900) +#define CONV_FROM_TM_MON(tm_mon) ((tm_mon) + 1) + +/* rtc date upper bound reaches the year of 2099. */ +#define RTC_TM_UPPER_BOUND \ +{ .tm_year = CONV_TO_TM_YEAR(2099), \ + .tm_mon = CONV_TO_TM_MON(12), \ + .tm_mday = 31, \ + .tm_hour = 23, \ + .tm_min = 59, \ + .tm_sec = 59, \ +} + +/* rtc date lower bound reaches the year of 2000. */ +#define RTC_TM_LOWER_BOUND \ +{ .tm_year = CONV_TO_TM_YEAR(2000), \ + .tm_mon = CONV_TO_TM_MON(1), \ + .tm_mday = 1, \ + .tm_hour = 0, \ + .tm_min = 0, \ + .tm_sec = 0, \ +} + +/* Private typedef --------------------------------------------------------------*/ + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_rtc_control(rt_device_t dev, int cmd, void *args); + +#if defined (NU_RTC_SUPPORT_IO_RW) +static rt_size_t nu_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size); +static rt_size_t nu_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size); +#endif + +static rt_err_t nu_rtc_is_date_valid(const time_t *const t); +static void nu_rtc_init(void); + +#if defined(RT_USING_ALARM) +static void nu_rtc_alarm_reset(void); +#endif + +/* Public functions -------------------------------------------------------------*/ +#if defined (NU_RTC_SUPPORT_MSH_CMD) +extern rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day); +extern rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second); +#endif + +/* Private variables ------------------------------------------------------------*/ +static struct rt_device device_rtc; + + +static void nu_rtc_init(void) +{ + /* hw rtc initialise */ + RTC_Open(NULL); + RTC_DisableInt(RTC_INTEN_ALMIEN_Msk | RTC_INTEN_TICKIEN_Msk ); + +#if defined(RT_USING_ALARM) + + nu_rtc_alarm_reset(); + RTC_EnableInt(RTC_INTEN_ALMIEN_Msk); + NVIC_EnableIRQ(RTC_IRQn); +#endif +} + + +#if defined(RT_USING_ALARM) +/* Reset alarm settings to avoid the unwanted values remain in rtc registers. */ +static void nu_rtc_alarm_reset(void) +{ + S_RTC_TIME_DATA_T alarm; + + /* Reset alarm time and calendar. */ + alarm.u32Year = RTC_YEAR2000; + alarm.u32Month = 0; + alarm.u32Day = 0; + alarm.u32Hour = 0; + alarm.u32Minute = 0; + alarm.u32Second = 0; + alarm.u32TimeScale = RTC_CLOCK_24; + + RTC_SetAlarmDateAndTime(&alarm); + + /* Reset alarm time mask and calendar mask. */ + RTC_SetAlarmDateMask(0, 0, 0, 0, 0, 0); + RTC_SetAlarmTimeMask(0, 0, 0, 0, 0, 0); + + /* Clear alarm flag for safe */ + RTC_CLEAR_ALARM_INT_FLAG(); +} +#endif + + +/* rtc device driver initialise. */ +int rt_hw_rtc_init(void) +{ + rt_err_t ret; + + nu_rtc_init(); + + /* register rtc device IO operations */ + device_rtc.type = RT_Device_Class_RTC; + device_rtc.init = NULL; + device_rtc.open = NULL; + device_rtc.close = NULL; + device_rtc.control = nu_rtc_control; + +#if defined (NU_RTC_SUPPORT_IO_RW) + device_rtc.read = nu_rtc_read; + device_rtc.write = nu_rtc_write; +#else + device_rtc.read = NULL; + device_rtc.write = NULL; +#endif + + device_rtc.user_data = RT_NULL; + device_rtc.rx_indicate = RT_NULL; + device_rtc.tx_complete = RT_NULL; + + ret = rt_device_register(&device_rtc, "rtc", RT_DEVICE_FLAG_RDWR); + + return (int)ret; +} +INIT_BOARD_EXPORT(rt_hw_rtc_init); + + +#if defined (NU_RTC_SUPPORT_IO_RW) +/* Register rt-thread device.read() entry. */ +static rt_size_t nu_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + (void) pos; + nu_rtc_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, buffer); + + return size; +} +#endif + + +#if defined (NU_RTC_SUPPORT_IO_RW) +/* Register rt-thread device.write() entry. */ +static rt_size_t nu_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + (void) pos; + nu_rtc_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, (void *)buffer); + + return size; +} +#endif + + +static rt_err_t nu_rtc_is_date_valid(const time_t *const t) +{ + static struct tm tm_upper = RTC_TM_UPPER_BOUND; + static struct tm tm_lower = RTC_TM_LOWER_BOUND; + static time_t t_upper, t_lower; + static rt_bool_t initialised = RT_FALSE; + + if (!initialised) + { + t_upper = timegm((struct tm *)&tm_upper); + t_lower = timegm((struct tm *)&tm_lower); + initialised = RT_TRUE; + } + + /* check the date is supported by rtc. */ + if ((*t > t_upper) || (*t < t_lower)) + return -(RT_EINVAL); + + return RT_EOK; +} + + +/* Register rt-thread device.control() entry. */ +static rt_err_t nu_rtc_control(rt_device_t dev, int cmd, void *args) +{ + struct tm tm_out, *tm_in; + time_t *time; + S_RTC_TIME_DATA_T hw_time; + +#if defined(RT_USING_ALARM) + + struct rt_rtc_wkalarm *wkalarm; + S_RTC_TIME_DATA_T hw_alarm; +#endif + + if ((dev == NULL) || (args == NULL)) + return -(RT_EINVAL); + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + + time = (time_t *)args; + RTC_GetDateAndTime(&hw_time); + + tm_out.tm_year = CONV_TO_TM_YEAR(hw_time.u32Year); + tm_out.tm_mon = CONV_TO_TM_MON(hw_time.u32Month); + tm_out.tm_mday = hw_time.u32Day; + tm_out.tm_hour = hw_time.u32Hour; + tm_out.tm_min = hw_time.u32Minute; + tm_out.tm_sec = hw_time.u32Second; + *time = timegm(&tm_out); + break; + + case RT_DEVICE_CTRL_RTC_SET_TIME: + + time = (time_t *) args; + tm_in = gmtime(time); + + if (nu_rtc_is_date_valid(time) != RT_EOK) + return RT_ERROR; + + hw_time.u32Year = CONV_FROM_TM_YEAR(tm_in->tm_year); + hw_time.u32Month = CONV_FROM_TM_MON(tm_in->tm_mon); + hw_time.u32Day = tm_in->tm_mday; + hw_time.u32Hour = tm_in->tm_hour; + hw_time.u32Minute = tm_in->tm_min; + hw_time.u32Second = tm_in->tm_sec; + hw_time.u32TimeScale = RTC_CLOCK_24; + hw_time.u32AmPm = 0; + + RTC_SetDateAndTime(&hw_time); + break; + +#if defined(RT_USING_ALARM) + case RT_DEVICE_CTRL_RTC_GET_ALARM: + + wkalarm = (struct rt_rtc_wkalarm *) args; + RTC_GetAlarmDateAndTime(&hw_alarm); + + wkalarm->tm_hour = hw_alarm.u32Hour; + wkalarm->tm_min = hw_alarm.u32Minute; + wkalarm->tm_sec = hw_alarm.u32Second; + break; + + case RT_DEVICE_CTRL_RTC_SET_ALARM: + + wkalarm = (struct rt_rtc_wkalarm *) args; + hw_alarm.u32Hour = wkalarm->tm_hour; + hw_alarm.u32Minute = wkalarm->tm_min; + hw_alarm.u32Second = wkalarm->tm_sec; + + RTC_SetAlarmDateMask(1, 1, 1, 1, 1, 1); + RTC_SetAlarmDateAndTime(&hw_alarm); + break; + + default: + return -(RT_EINVAL); +#endif + } + + return RT_EOK; +} + + +#if defined (NU_RTC_SUPPORT_MSH_CMD) + +/* Support "rtc_det_date" command line in msh mode */ +static rt_err_t msh_rtc_set_date(int argc, char **argv) +{ + rt_uint32_t index, len, arg[3]; + + rt_memset(arg, 0, sizeof(arg)); + len = (argc >= 4) ? 4 : argc; + + /* The date information stored in argv is represented by the following order : + argv[0,1,2,3] = [cmd, year, month, day] */ + for (index = 0; index < (len - 1); index ++) + { + arg[index] = atol(argv[index + 1]); + } + + return set_date(arg[0], arg[1], arg[2]); +} +MSH_CMD_EXPORT_ALIAS(msh_rtc_set_date, rtc_set_date, e.g: rtc_set_date 2020 1 20); +#endif + + +#if defined (NU_RTC_SUPPORT_MSH_CMD) + +/* Support "rtc_det_time" command line in msh mode */ +static rt_err_t msh_rtc_set_time(int argc, char **argv) +{ + rt_uint32_t index, len, arg[3]; + + rt_memset(arg, 0, sizeof(arg)); + len = (argc >= 4) ? 4 : argc; + + /* The time information stored in argv is represented by the following order : + argv[0,1,2,3] = [cmd, hour, minute, second] */ + for (index = 0; index < (len - 1); index ++) + { + arg[index] = atol(argv[index + 1]); + } + + return set_time(arg[0], arg[1], arg[2]); +} +MSH_CMD_EXPORT_ALIAS(msh_rtc_set_time, rtc_set_time, e.g: rtc_set_time 18 30 00); +#endif + + +#if defined(RT_USING_ALARM) +/* rtc interrupt entry */ +void RTC_IRQHandler(void) +{ + rt_interrupt_enter(); + + if (RTC_GET_ALARM_INT_FLAG()) + { + RTC_CLEAR_ALARM_INT_FLAG(); + + /* Send an alarm event to notify rt-thread alarm service. */ + rt_alarm_update(&device_rtc, (rt_uint32_t)NULL); + } + + rt_interrupt_leave(); +} +#endif + +#endif /* BSP_USING_RTC */ + diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_softi2c.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_softi2c.c new file mode 100644 index 0000000000..bd4f6af0fa --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_softi2c.c @@ -0,0 +1,217 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-01-15 klcheng First version +* +******************************************************************************/ + +#include + +#if (defined(BSP_USING_SOFT_I2C) && defined(BSP_USING_GPIO) && defined(RT_USING_I2C_BITOPS) && defined(RT_USING_I2C) && defined(RT_USING_PIN)) + +#include +#include +#include +#include "NuMicro.h" + +/* Private define ---------------------------------------------------------------*/ +#define LOG_TAG "drv.softi2c" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_INFO +#include + +#ifdef BSP_USING_SOFT_I2C0 +#define NU_SOFT_I2C0_BUS_CONFIG \ + { \ + .scl = BSP_SOFT_I2C0_SCL_PIN, \ + .sda = BSP_SOFT_I2C0_SDA_PIN, \ + .bus_name = "softi2c0", \ + } +#endif + +#ifdef BSP_USING_SOFT_I2C1 +#define NU_SOFT_I2C1_BUS_CONFIG \ + { \ + .scl = BSP_SOFT_I2C1_SCL_PIN, \ + .sda = BSP_SOFT_I2C1_SDA_PIN, \ + .bus_name = "softi2c1", \ + } +#endif + +#if (!defined(BSP_USING_SOFT_I2C0) && !defined(BSP_USING_SOFT_I2C1)) + #error "Please define at least one BSP_USING_SOFT_I2Cx" + /* this driver can be disabled at menuconfig ? RT-Thread Components ? Device Drivers */ +#endif + +/* Private typedef --------------------------------------------------------------*/ +/* soft i2c config class */ +struct nu_soft_i2c_config +{ + rt_uint8_t scl; + rt_uint8_t sda; + const char *bus_name; +}; +/* soft i2c driver class */ +struct nu_soft_i2c +{ + struct rt_i2c_bit_ops ops; + struct rt_i2c_bus_device soft_i2c_bus; +}; + +/* Private functions ------------------------------------------------------------*/ +static void nu_soft_i2c_set_sda(void *data, rt_int32_t state); +static void nu_soft_i2c_set_scl(void *data, rt_int32_t state); +static rt_int32_t nu_soft_i2c_get_sda(void *data); +static rt_int32_t nu_soft_i2c_get_scl(void *data); + +/* Private variables ------------------------------------------------------------*/ +static const struct nu_soft_i2c_config nu_soft_i2c_cfg[] = +{ +#ifdef BSP_USING_SOFT_I2C0 + NU_SOFT_I2C0_BUS_CONFIG, +#endif +#ifdef BSP_USING_SOFT_I2C1 + NU_SOFT_I2C1_BUS_CONFIG, +#endif +}; + +static struct nu_soft_i2c nu_soft_i2c_obj[sizeof(nu_soft_i2c_cfg) / sizeof(nu_soft_i2c_cfg[0])]; + +static const struct rt_i2c_bit_ops nu_soft_i2c_bit_ops = +{ + .data = RT_NULL, + .set_sda = nu_soft_i2c_set_sda, + .set_scl = nu_soft_i2c_set_scl, + .get_sda = nu_soft_i2c_get_sda, + .get_scl = nu_soft_i2c_get_scl, + .udelay = rt_hw_us_delay, + .delay_us = 1, + .timeout = 100 +}; + +/* Functions define ------------------------------------------------------------*/ + +/** + * This function initializes the soft i2c pin. + * + * @param soft i2c config class. + */ +static void nu_soft_i2c_gpio_init(const struct nu_soft_i2c_config *cfg) +{ + rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD); + rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD); + + rt_pin_write(cfg->scl, PIN_HIGH); + rt_pin_write(cfg->sda, PIN_HIGH); +} + +/** + * if i2c is locked, this function will unlock it + * + * @param soft i2c config class + * + * @return RT_EOK indicates successful unlock. + */ +static rt_err_t nu_soft_i2c_bus_unlock(const struct nu_soft_i2c_config *cfg) +{ + rt_int32_t i = 0; + + if (PIN_LOW == rt_pin_read(cfg->sda)) + { + while (i++ < 9) + { + rt_pin_write(cfg->scl, PIN_HIGH); + rt_hw_us_delay(100); + rt_pin_write(cfg->scl, PIN_LOW); + rt_hw_us_delay(100); + } + } + if (PIN_LOW == rt_pin_read(cfg->sda)) + { + return -RT_ERROR; + } + + return RT_EOK; +} + +/** + * This function sets the sda pin. + * + * @param soft i2c config class. + * @param The sda pin state. + */ +static void nu_soft_i2c_set_sda(void *data, rt_int32_t state) +{ + struct nu_soft_i2c_config *cfg = (struct nu_soft_i2c_config *)data; + + rt_pin_write(cfg->sda, state ? PIN_HIGH : PIN_LOW); +} + +/** + * This function sets the scl pin. + * + * @param soft i2c config class. + * @param The scl pin state. + */ +static void nu_soft_i2c_set_scl(void *data, rt_int32_t state) +{ + struct nu_soft_i2c_config *cfg = (struct nu_soft_i2c_config *)data; + + rt_pin_write(cfg->scl, state ? PIN_HIGH : PIN_LOW); +} + +/** + * This function gets the sda pin state. + * + * @param The sda pin state. + */ +static rt_int32_t nu_soft_i2c_get_sda(void *data) +{ + struct nu_soft_i2c_config *cfg = (struct nu_soft_i2c_config *)data; + return rt_pin_read(cfg->sda); +} + +/** + * This function gets the scl pin state. + * + * @param The scl pin state. + */ +static rt_int32_t nu_soft_i2c_get_scl(void *data) +{ + struct nu_soft_i2c_config *cfg = (struct nu_soft_i2c_config *)data; + return rt_pin_read(cfg->scl); +} + +/* Soft I2C initialization function */ +int rt_soft_i2c_init(void) +{ + rt_size_t obj_num = sizeof(nu_soft_i2c_obj) / sizeof(struct nu_soft_i2c); + rt_err_t result; + + for (int i = 0; i < obj_num; i++) + { + nu_soft_i2c_obj[i].ops = nu_soft_i2c_bit_ops; + nu_soft_i2c_obj[i].ops.data = (void *)&nu_soft_i2c_cfg[i]; + nu_soft_i2c_obj[i].soft_i2c_bus.priv = &nu_soft_i2c_obj[i].ops; + nu_soft_i2c_gpio_init(&nu_soft_i2c_cfg[i]); + result = rt_i2c_bit_add_bus(&nu_soft_i2c_obj[i].soft_i2c_bus, nu_soft_i2c_cfg[i].bus_name); + RT_ASSERT(result == RT_EOK); + nu_soft_i2c_bus_unlock(&nu_soft_i2c_cfg[i]); + + LOG_D("software simulation %s init done, pin scl: %d, pin sda %d", + nu_soft_i2c_cfg[i].bus_name, + nu_soft_i2c_cfg[i].scl, + nu_soft_i2c_cfg[i].sda); + } + + return 0; +} +INIT_DEVICE_EXPORT(rt_soft_i2c_init); + +#endif //#if (defined(BSP_USING_SOFT_I2C) && defined(BSP_USING_GPIO) && defined(RT_USING_I2C_BITOPS) && defined(RT_USING_I2C) && defined(RT_USING_PIN)) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_spi.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_spi.c new file mode 100644 index 0000000000..c11c6512de --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_spi.c @@ -0,0 +1,599 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-01-19 klcheng First version +* +******************************************************************************/ +#include + +#if defined(BSP_USING_SPI) + +#define LOG_TAG "drv.spi" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include + +#include +#include +#include + +#include + + +/* Private define ---------------------------------------------------------------*/ + +#ifndef NU_SPI_USE_PDMA_MIN_THRESHOLD + #define NU_SPI_USE_PDMA_MIN_THRESHOLD (128) +#endif + +enum +{ + SPI_START = -1, +#if defined(BSP_USING_SPI0) + SPI0_IDX, +#endif + SPI_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ + +/* Private functions ------------------------------------------------------------*/ +static void nu_spi_transmission_with_poll(struct nu_spi *spi_bus, + uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word); +static int nu_spi_register_bus(struct nu_spi *spi_bus, const char *name); +static rt_uint32_t nu_spi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message); +static rt_err_t nu_spi_bus_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration); + +#if defined(BSP_USING_SPI_PDMA) + static void nu_pdma_spi_rx_cb(void *pvUserData, uint32_t u32EventFilter); + static rt_err_t nu_pdma_spi_rx_config(struct nu_spi *spi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word); + static rt_err_t nu_pdma_spi_tx_config(struct nu_spi *spi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word); + static rt_size_t nu_spi_pdma_transmit(struct nu_spi *spi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word); +#endif +/* Public functions -------------------------------------------------------------*/ +void nu_spi_transfer(struct nu_spi *spi_bus, uint8_t *tx, uint8_t *rx, int length, uint8_t bytes_per_word); +void nu_spi_drain_rxfifo(SPI_T *spi_base); + +/* Private variables ------------------------------------------------------------*/ +static struct rt_spi_ops nu_spi_poll_ops = +{ + .configure = nu_spi_bus_configure, + .xfer = nu_spi_bus_xfer, +}; + +static struct nu_spi nu_spi_arr [] = +{ +#if defined(BSP_USING_SPI0) + { + .name = "spi0", + .spi_base = SPI0, + +#if defined(BSP_USING_SPI_PDMA) +#if defined(BSP_USING_SPI0_PDMA) + .pdma_perp_tx = PDMA_SPI0_TX, + .pdma_perp_rx = PDMA_SPI0_RX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + {0} +}; /* spi nu_spi */ + +static rt_err_t nu_spi_bus_configure(struct rt_spi_device *device, + struct rt_spi_configuration *configuration) +{ + struct nu_spi *spi_bus; + uint32_t u32SPIMode; + uint32_t u32BusClock; + rt_err_t ret = RT_EOK; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + spi_bus = (struct nu_spi *) device->bus; + + /* Check mode */ + switch (configuration->mode & RT_SPI_MODE_3) + { + case RT_SPI_MODE_0: + u32SPIMode = SPI_MODE_0; + break; + case RT_SPI_MODE_1: + u32SPIMode = SPI_MODE_1; + break; + case RT_SPI_MODE_2: + u32SPIMode = SPI_MODE_2; + break; + case RT_SPI_MODE_3: + u32SPIMode = SPI_MODE_3; + break; + default: + ret = RT_EIO; + goto exit_nu_spi_bus_configure; + } + + /* Check data width */ + if (!(configuration->data_width == 8 || + configuration->data_width == 16 || + configuration->data_width == 24 || + configuration->data_width == 32)) + { + ret = RT_EINVAL; + goto exit_nu_spi_bus_configure; + } + + /* Try to set clock and get actual spi bus clock */ + u32BusClock = SPI_SetBusClock(spi_bus->spi_base, configuration->max_hz); + if (configuration->max_hz > u32BusClock) + { + LOG_W("%s clock max frequency is %dHz (!= %dHz)\n", spi_bus->name, u32BusClock, configuration->max_hz); + configuration->max_hz = u32BusClock; + } + + /* Need to initialize new configuration? */ + if (rt_memcmp(configuration, &spi_bus->configuration, sizeof(*configuration)) != 0) + { + rt_memcpy(&spi_bus->configuration, configuration, sizeof(*configuration)); + + SPI_Open(spi_bus->spi_base, SPI_MASTER, u32SPIMode, configuration->data_width, u32BusClock); + + if (configuration->mode & RT_SPI_CS_HIGH) + { + /* Set CS pin to LOW */ + SPI_SET_SS_LOW(spi_bus->spi_base); + } + else + { + /* Set CS pin to HIGH */ + SPI_SET_SS_HIGH(spi_bus->spi_base); + } + + if (configuration->mode & RT_SPI_MSB) + { + /* Set sequence to MSB first */ + SPI_SET_MSB_FIRST(spi_bus->spi_base); + } + else + { + /* Set sequence to LSB first */ + SPI_SET_LSB_FIRST(spi_bus->spi_base); + } + } + + /* Clear SPI RX FIFO */ + nu_spi_drain_rxfifo(spi_bus->spi_base); + +exit_nu_spi_bus_configure: + + return -(ret); +} + +#if defined(BSP_USING_SPI_PDMA) +static void nu_pdma_spi_rx_cb(void *pvUserData, uint32_t u32EventFilter) +{ + rt_err_t result; + struct nu_spi *spi_bus = (struct nu_spi *)pvUserData; + + RT_ASSERT(spi_bus != RT_NULL); + + result = rt_sem_release(spi_bus->m_psSemBus); + RT_ASSERT(result == RT_EOK); +} +static rt_err_t nu_pdma_spi_rx_config(struct nu_spi *spi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word) +{ + rt_err_t result = RT_EOK; + rt_uint8_t *dst_addr = NULL; + nu_pdma_memctrl_t memctrl = eMemCtl_Undefined; + + /* Get base address of spi register */ + SPI_T *spi_base = spi_bus->spi_base; + + rt_uint8_t spi_pdma_rx_chid = spi_bus->pdma_chanid_rx; + + result = nu_pdma_callback_register(spi_pdma_rx_chid, + nu_pdma_spi_rx_cb, + (void *)spi_bus, + NU_PDMA_EVENT_TRANSFER_DONE); + if (result != RT_EOK) + { + goto exit_nu_pdma_spi_rx_config; + } + + if (pu8Buf == RT_NULL) + { + memctrl = eMemCtl_SrcFix_DstFix; + dst_addr = (rt_uint8_t *) &spi_bus->dummy; + } + else + { + memctrl = eMemCtl_SrcFix_DstInc; + dst_addr = pu8Buf; + } + + result = nu_pdma_channel_memctrl_set(spi_pdma_rx_chid, memctrl); + if (result != RT_EOK) + { + goto exit_nu_pdma_spi_rx_config; + } + + result = nu_pdma_transfer(spi_pdma_rx_chid, + bytes_per_word * 8, + (uint32_t)&spi_base->RX, + (uint32_t)dst_addr, + i32RcvLen / bytes_per_word, + 0); +exit_nu_pdma_spi_rx_config: + + return result; +} + +static rt_err_t nu_pdma_spi_tx_config(struct nu_spi *spi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word) +{ + rt_err_t result = RT_EOK; + rt_uint8_t *src_addr = NULL; + nu_pdma_memctrl_t memctrl = eMemCtl_Undefined; + + /* Get base address of spi register */ + SPI_T *spi_base = spi_bus->spi_base; + + rt_uint8_t spi_pdma_tx_chid = spi_bus->pdma_chanid_tx; + + if (pu8Buf == RT_NULL) + { + spi_bus->dummy = 0; + memctrl = eMemCtl_SrcFix_DstFix; + src_addr = (rt_uint8_t *)&spi_bus->dummy; + } + else + { + memctrl = eMemCtl_SrcInc_DstFix; + src_addr = (rt_uint8_t *)pu8Buf; + } + + result = nu_pdma_channel_memctrl_set(spi_pdma_tx_chid, memctrl); + if (result != RT_EOK) + { + goto exit_nu_pdma_spi_tx_config; + } + + result = nu_pdma_transfer(spi_pdma_tx_chid, + bytes_per_word * 8, + (uint32_t)src_addr, + (uint32_t)&spi_base->TX, + i32SndLen / bytes_per_word, + 0); +exit_nu_pdma_spi_tx_config: + + return result; +} + + +/** + * SPI PDMA transfer + */ +static rt_size_t nu_spi_pdma_transmit(struct nu_spi *spi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word) +{ + rt_err_t result = RT_EOK; + rt_uint32_t u32Offset = 0; + rt_uint32_t u32TransferCnt = length / bytes_per_word; + rt_uint32_t u32TxCnt = 0; + + /* Get base address of spi register */ + SPI_T *spi_base = spi_bus->spi_base; + + do + { + u32TxCnt = (u32TransferCnt > NU_PDMA_MAX_TXCNT) ? NU_PDMA_MAX_TXCNT : u32TransferCnt; + result = nu_pdma_spi_rx_config(spi_bus, (recv_addr == RT_NULL) ? recv_addr : &recv_addr[u32Offset], (u32TxCnt * bytes_per_word), bytes_per_word); + RT_ASSERT(result == RT_EOK); + + result = nu_pdma_spi_tx_config(spi_bus, (send_addr == RT_NULL) ? send_addr : &send_addr[u32Offset], (u32TxCnt * bytes_per_word), bytes_per_word); + RT_ASSERT(result == RT_EOK); + + /* Trigger TX/RX PDMA transfer. */ + SPI_TRIGGER_TX_RX_PDMA(spi_base); + + /* Wait RX-PDMA transfer done */ + result = rt_sem_take(spi_bus->m_psSemBus, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + /* Stop TX/RX DMA transfer. */ + SPI_DISABLE_TX_RX_PDMA(spi_base); + + u32TransferCnt -= u32TxCnt; + u32Offset += u32TxCnt; + + } + while (u32TransferCnt > 0); + + return length; +} + +rt_err_t nu_hw_spi_pdma_allocate(struct nu_spi *spi_bus) +{ + /* Allocate SPI_TX nu_dma channel */ + if ((spi_bus->pdma_chanid_tx = nu_pdma_channel_allocate(spi_bus->pdma_perp_tx)) < 0) + { + goto exit_nu_hw_spi_pdma_allocate; + } + /* Allocate SPI_RX nu_dma channel */ + else if ((spi_bus->pdma_chanid_rx = nu_pdma_channel_allocate(spi_bus->pdma_perp_rx)) < 0) + { + nu_pdma_channel_free(spi_bus->pdma_chanid_tx); + goto exit_nu_hw_spi_pdma_allocate; + } + + spi_bus->m_psSemBus = rt_sem_create("spibus_sem", 0, RT_IPC_FLAG_FIFO); + RT_ASSERT(spi_bus->m_psSemBus != RT_NULL); + + return RT_EOK; + +exit_nu_hw_spi_pdma_allocate: + + return -(RT_ERROR); +} +#endif /* #if defined(BSP_USING_SPI_PDMA) */ + +void nu_spi_drain_rxfifo(SPI_T *spi_base) +{ + while (SPI_IS_BUSY(spi_base)); + + // Drain SPI RX FIFO, make sure RX FIFO is empty + while (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base)) + { + SPI_ClearRxFIFO(spi_base); + } +} + +static int nu_spi_read(SPI_T *spi_base, uint8_t *recv_addr, uint8_t bytes_per_word) +{ + int size = 0; + + // Read RX data + if (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base)) + { + uint32_t val; + // Read data from SPI RX FIFO + switch (bytes_per_word) + { + case 4: + val = SPI_READ_RX(spi_base); + nu_set32_le(recv_addr, val); + break; + case 3: + val = SPI_READ_RX(spi_base); + nu_set24_le(recv_addr, val); + break; + case 2: + val = SPI_READ_RX(spi_base); + nu_set16_le(recv_addr, val); + break; + case 1: + *recv_addr = SPI_READ_RX(spi_base); + break; + default: + LOG_E("Data length is not supported.\n"); + break; + } + size = bytes_per_word; + } + return size; +} + +static int nu_spi_write(SPI_T *spi_base, const uint8_t *send_addr, uint8_t bytes_per_word) +{ + // Wait SPI TX send data + while (SPI_GET_TX_FIFO_FULL_FLAG(spi_base)); + + // Input data to SPI TX + switch (bytes_per_word) + { + case 4: + SPI_WRITE_TX(spi_base, nu_get32_le(send_addr)); + break; + case 3: + SPI_WRITE_TX(spi_base, nu_get24_le(send_addr)); + break; + case 2: + SPI_WRITE_TX(spi_base, nu_get16_le(send_addr)); + break; + case 1: + SPI_WRITE_TX(spi_base, *((uint8_t *)send_addr)); + break; + default: + LOG_E("Data length is not supported.\n"); + break; + } + + return bytes_per_word; +} + +/** + * @brief SPI bus polling + * @param dev : The pointer of the specified SPI module. + * @param send_addr : Source address + * @param recv_addr : Destination address + * @param length : Data length + */ +static void nu_spi_transmission_with_poll(struct nu_spi *spi_bus, + uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word) +{ + SPI_T *spi_base = spi_bus->spi_base; + + // Write-only + if ((send_addr != RT_NULL) && (recv_addr == RT_NULL)) + { + while (length > 0) + { + send_addr += nu_spi_write(spi_base, send_addr, bytes_per_word); + length -= bytes_per_word; + } + } // if (send_addr != RT_NULL && recv_addr == RT_NULL) + // Read-only + else if ((send_addr == RT_NULL) && (recv_addr != RT_NULL)) + { + spi_bus->dummy = 0; + while (length > 0) + { + /* Input data to SPI TX FIFO */ + length -= nu_spi_write(spi_base, (const uint8_t *)&spi_bus->dummy, bytes_per_word); + + /* Read data from RX FIFO */ + recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word); + } + } // else if (send_addr == RT_NULL && recv_addr != RT_NULL) + // Read&Write + else + { + while (length > 0) + { + /* Input data to SPI TX FIFO */ + send_addr += nu_spi_write(spi_base, send_addr, bytes_per_word); + length -= bytes_per_word; + + /* Read data from RX FIFO */ + recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word); + } + } // else + + /* Wait RX or drain RX-FIFO */ + if (recv_addr) + { + // Wait SPI transmission done + while (SPI_IS_BUSY(spi_base)) + { + while (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base)) + { + recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word); + } + } + + while (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base)) + { + recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word); + } + } + else + { + /* Clear SPI RX FIFO */ + nu_spi_drain_rxfifo(spi_base); + } +} + +void nu_spi_transfer(struct nu_spi *spi_bus, uint8_t *tx, uint8_t *rx, int length, uint8_t bytes_per_word) +{ + RT_ASSERT(spi_bus != RT_NULL); + +#if defined(BSP_USING_SPI_PDMA) + /* DMA transfer constrains */ + if ((spi_bus->pdma_chanid_rx >= 0) && + !((uint32_t)tx % bytes_per_word) && + !((uint32_t)rx % bytes_per_word) && + (bytes_per_word != 3) && + (length >= NU_SPI_USE_PDMA_MIN_THRESHOLD)) + nu_spi_pdma_transmit(spi_bus, tx, rx, length, bytes_per_word); + else + nu_spi_transmission_with_poll(spi_bus, tx, rx, length, bytes_per_word); +#else + nu_spi_transmission_with_poll(spi_bus, tx, rx, length, bytes_per_word); +#endif +} + +static rt_uint32_t nu_spi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + struct nu_spi *spi_bus; + struct rt_spi_configuration *configuration; + uint8_t bytes_per_word; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + RT_ASSERT(message != RT_NULL); + + spi_bus = (struct nu_spi *) device->bus; + configuration = (struct rt_spi_configuration *)&spi_bus->configuration; + bytes_per_word = configuration->data_width / 8; + + if ((message->length % bytes_per_word) != 0) + { + /* Say bye. */ + LOG_E("%s: error payload length(%d%%%d != 0).\n", spi_bus->name, message->length, bytes_per_word); + return 0; + } + + if (message->length > 0) + { + if (message->cs_take && !(configuration->mode & RT_SPI_NO_CS)) + { + if (configuration->mode & RT_SPI_CS_HIGH) + { + SPI_SET_SS_HIGH(spi_bus->spi_base); + } + else + { + SPI_SET_SS_LOW(spi_bus->spi_base); + } + } + + nu_spi_transfer(spi_bus, (uint8_t *)message->send_buf, (uint8_t *)message->recv_buf, message->length, bytes_per_word); + + if (message->cs_release && !(configuration->mode & RT_SPI_NO_CS)) + { + if (configuration->mode & RT_SPI_CS_HIGH) + { + SPI_SET_SS_LOW(spi_bus->spi_base); + } + else + { + SPI_SET_SS_HIGH(spi_bus->spi_base); + } + } + + } + + return message->length; +} + +static int nu_spi_register_bus(struct nu_spi *spi_bus, const char *name) +{ + return rt_spi_bus_register(&spi_bus->dev, name, &nu_spi_poll_ops); +} + +/** + * Hardware SPI Initial + */ +static int rt_hw_spi_init(void) +{ + int i; + + for (i = (SPI_START + 1); i < SPI_CNT; i++) + { + nu_spi_register_bus(&nu_spi_arr[i], nu_spi_arr[i].name); +#if defined(BSP_USING_SPI_PDMA) + nu_spi_arr[i].pdma_chanid_tx = -1; + nu_spi_arr[i].pdma_chanid_rx = -1; + if ((nu_spi_arr[i].pdma_perp_tx != NU_PDMA_UNUSED) && (nu_spi_arr[i].pdma_perp_rx != NU_PDMA_UNUSED)) + { + if (nu_hw_spi_pdma_allocate(&nu_spi_arr[i]) != RT_EOK) + { + LOG_W("Failed to allocate DMA channels for %s. We will use poll-mode for this bus.\n", nu_spi_arr[i].name); + } + } +#endif + } + + return 0; +} + +INIT_DEVICE_EXPORT(rt_hw_spi_init); + +#endif //#if defined(BSP_USING_SPI) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_spi.h b/bsp/nuvoton/libraries/m031/rtt_port/drv_spi.h new file mode 100644 index 0000000000..ec91c2ec37 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_spi.h @@ -0,0 +1,51 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-01-19 klcheng First version +* +******************************************************************************/ + +#ifndef __DRV_SPI_H__ +#define __DRV_SPI_H__ + +#include + +#include +#include "NuMicro.h" +#include + +#if defined(BSP_USING_SPI_PDMA) + #include +#endif + +struct nu_spi +{ + struct rt_spi_bus dev; + char *name; + SPI_T *spi_base; + uint32_t dummy; +#if defined(BSP_USING_SPI_PDMA) + int16_t pdma_perp_tx; + int8_t pdma_chanid_tx; + int16_t pdma_perp_rx; + int8_t pdma_chanid_rx; + rt_sem_t m_psSemBus; +#endif + struct rt_qspi_configuration configuration; +}; + +typedef struct nu_spi *nu_spi_t; + +void nu_spi_drain_rxfifo(SPI_T *spi_base); +void nu_spi_transfer(struct nu_spi *spi_bus, uint8_t *tx, uint8_t *rx, int length, uint8_t bytes_per_word); + +#if defined(BSP_USING_SPI_PDMA) + rt_err_t nu_hw_spi_pdma_allocate(struct nu_spi *spi_bus); +#endif + +#endif // __DRV_SPI_H___ diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_spii2s.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_spii2s.c new file mode 100644 index 0000000000..9415469f73 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_spii2s.c @@ -0,0 +1,594 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-22 klcheng First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_SPII2S) + +#include +#include +#include + +/* Private define ---------------------------------------------------------------*/ +#define DBG_ENABLE +#define DBG_LEVEL DBG_LOG +#define DBG_SECTION_NAME "spii2s" +#define DBG_COLOR +#include + +enum +{ + SPII2S_START = -1, +#if defined(BSP_USING_SPII2S0) + SPII2S0_IDX, +#endif + SPII2S_CNT +}; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_spii2s_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps); +static rt_err_t nu_spii2s_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps); +static rt_err_t nu_spii2s_init(struct rt_audio_device *audio); +static rt_err_t nu_spii2s_start(struct rt_audio_device *audio, int stream); +static rt_err_t nu_spii2s_stop(struct rt_audio_device *audio, int stream); +static void nu_spii2s_buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info); +/* Public functions -------------------------------------------------------------*/ +rt_err_t nu_spii2s_acodec_register(struct rt_audio_device *audio, nu_acodec_ops_t); + +/* Private variables ------------------------------------------------------------*/ +static struct nu_i2s g_nu_spii2s_arr [] = +{ +#if defined(BSP_USING_SPII2S0) + { + .name = "spii2s0", + .i2s_base = (SPI_T *)SPI0, //Avoid warning + .i2s_rst = SPI0_RST, + .i2s_dais = { + [NU_I2S_DAI_PLAYBACK] = { + .pdma_perp = PDMA_SPI0_TX, + }, + [NU_I2S_DAI_CAPTURE] = { + .pdma_perp = PDMA_SPI0_RX, + } + } + }, +#endif +}; + +static void nu_pdma_spii2s_rx_cb(void *pvUserData, uint32_t u32EventFilter) +{ + nu_i2s_t psNuSPII2s = (nu_i2s_t)pvUserData; + nu_i2s_dai_t psNuSPII2sDai; + + RT_ASSERT(psNuSPII2s != RT_NULL); + psNuSPII2sDai = &psNuSPII2s->i2s_dais[NU_I2S_DAI_CAPTURE]; + + if (u32EventFilter & NU_PDMA_EVENT_TRANSFER_DONE) + { + // Report a buffer ready. + rt_uint8_t *pbuf_old = &psNuSPII2sDai->fifo[psNuSPII2sDai->fifo_block_idx * NU_I2S_DMA_BUF_BLOCK_SIZE] ; + psNuSPII2sDai->fifo_block_idx = (psNuSPII2sDai->fifo_block_idx + 1) % NU_I2S_DMA_BUF_BLOCK_NUMBER; + + /* Report upper layer. */ + rt_audio_rx_done(&psNuSPII2s->audio, pbuf_old, NU_I2S_DMA_BUF_BLOCK_SIZE); + } +} + +static void nu_pdma_spii2s_tx_cb(void *pvUserData, uint32_t u32EventFilter) +{ + nu_i2s_t psNuSPII2s = (nu_i2s_t)pvUserData; + nu_i2s_dai_t psNuSPII2sDai; + + RT_ASSERT(psNuSPII2s != RT_NULL); + psNuSPII2sDai = &psNuSPII2s->i2s_dais[NU_I2S_DAI_PLAYBACK]; + + if (u32EventFilter & NU_PDMA_EVENT_TRANSFER_DONE) + { + rt_audio_tx_complete(&psNuSPII2s->audio); + psNuSPII2sDai->fifo_block_idx = (psNuSPII2sDai->fifo_block_idx + 1) % NU_I2S_DMA_BUF_BLOCK_NUMBER; + } +} + +static rt_err_t nu_spii2s_pdma_sc_config(nu_i2s_t psNuSPII2s, E_NU_I2S_DAI dai) +{ + rt_err_t result = RT_EOK; + SPI_T *spii2s_base; + nu_i2s_dai_t psNuSPII2sDai; + int i; + uint32_t u32Src, u32Dst; + nu_pdma_cb_handler_t pfm_pdma_cb; + + RT_ASSERT(psNuSPII2s != RT_NULL); + + /* Get base address of spii2s register */ + spii2s_base = (SPI_T *)psNuSPII2s->i2s_base; + psNuSPII2sDai = &psNuSPII2s->i2s_dais[dai]; + + switch ((int)dai) + { + case NU_I2S_DAI_PLAYBACK: + pfm_pdma_cb = nu_pdma_spii2s_tx_cb; + u32Src = (uint32_t)&psNuSPII2sDai->fifo[0]; + u32Dst = (uint32_t)&spii2s_base->TX; + break; + + case NU_I2S_DAI_CAPTURE: + pfm_pdma_cb = nu_pdma_spii2s_rx_cb; + u32Src = (uint32_t)&spii2s_base->RX; + u32Dst = (uint32_t)&psNuSPII2sDai->fifo[0]; + break; + + default: + return -RT_EINVAL; + } + + result = nu_pdma_callback_register(psNuSPII2sDai->pdma_chanid, + pfm_pdma_cb, + (void *)psNuSPII2s, + NU_PDMA_EVENT_TRANSFER_DONE); + RT_ASSERT(result == RT_EOK); + + for (i = 0; i < NU_I2S_DMA_BUF_BLOCK_NUMBER; i++) + { + /* Setup dma descriptor entry */ + result = nu_pdma_desc_setup(psNuSPII2sDai->pdma_chanid, // Channel ID + psNuSPII2sDai->pdma_descs[i], // this descriptor + 32, // 32-bits + (dai == NU_I2S_DAI_PLAYBACK) ? u32Src + (i * NU_I2S_DMA_BUF_BLOCK_SIZE) : u32Src, //Memory or RXFIFO + (dai == NU_I2S_DAI_PLAYBACK) ? u32Dst : u32Dst + (i * NU_I2S_DMA_BUF_BLOCK_SIZE), //TXFIFO or Memory + (int32_t)NU_I2S_DMA_BUF_BLOCK_SIZE / 4, // Transfer count + psNuSPII2sDai->pdma_descs[(i + 1) % NU_I2S_DMA_BUF_BLOCK_NUMBER]); // Next descriptor + RT_ASSERT(result == RT_EOK); + } + + /* Assign head descriptor */ + result = nu_pdma_sg_transfer(psNuSPII2sDai->pdma_chanid, psNuSPII2sDai->pdma_descs[0], 0); + RT_ASSERT(result == RT_EOK); + + return result; +} + +static rt_bool_t nu_spii2s_capacity_check(struct rt_audio_configure *pconfig) +{ + switch (pconfig->samplebits) + { + case 8: + case 16: + /* case 24: PDMA constrain */ + case 32: + break; + default: + goto exit_nu_spii2s_capacity_check; + } + + switch (pconfig->channels) + { + case 1: + case 2: + break; + default: + goto exit_nu_spii2s_capacity_check; + } + + return RT_TRUE; + +exit_nu_spii2s_capacity_check: + + return RT_FALSE; +} + +static rt_err_t nu_spii2s_dai_setup(nu_i2s_t psNuSPII2s, struct rt_audio_configure *pconfig) +{ + rt_err_t result = RT_EOK; + nu_acodec_ops_t pNuACodecOps; + SPI_T *spii2s_base = (SPI_T *)psNuSPII2s->i2s_base; + + RT_ASSERT(psNuSPII2s->AcodecOps != RT_NULL); + pNuACodecOps = psNuSPII2s->AcodecOps; + + /* Open SPII2S */ + if (nu_spii2s_capacity_check(pconfig) == RT_TRUE) + { + /* Reset audio codec */ + if (pNuACodecOps->nu_acodec_reset) + result = pNuACodecOps->nu_acodec_reset(); + + if (result != RT_EOK) + goto exit_nu_spii2s_dai_setup; + + /* Setup audio codec */ + if (pNuACodecOps->nu_acodec_init) + result = pNuACodecOps->nu_acodec_init(); + + if (!pNuACodecOps->nu_acodec_init || result != RT_EOK) + goto exit_nu_spii2s_dai_setup; + + /* Setup acodec samplerate/samplebit/channel */ + if (pNuACodecOps->nu_acodec_dsp_control) + result = pNuACodecOps->nu_acodec_dsp_control(pconfig); + + if (!pNuACodecOps->nu_acodec_dsp_control || result != RT_EOK) + goto exit_nu_spii2s_dai_setup; + + SPII2S_Open(spii2s_base, + (psNuSPII2s->AcodecOps->role == NU_ACODEC_ROLE_MASTER) ? SPII2S_MODE_SLAVE : SPII2S_MODE_MASTER, + pconfig->samplerate, + (((pconfig->samplebits / 8) - 1) << SPI_I2SCTL_WDWIDTH_Pos), + (pconfig->channels == 1) ? SPII2S_MONO : SPII2S_STEREO, + SPII2S_FORMAT_I2S); + LOG_I("Open SPII2S."); + + /* Set MCLK and enable MCLK */ + /* The target MCLK is related to audio codec setting. */ + SPII2S_EnableMCLK(spii2s_base, 12000000); + + /* Set un-mute */ + if (pNuACodecOps->nu_acodec_mixer_control) + pNuACodecOps->nu_acodec_mixer_control(AUDIO_MIXER_MUTE, RT_FALSE); + } + else + result = -RT_EINVAL; + +exit_nu_spii2s_dai_setup: + + return result; +} + +static rt_err_t nu_spii2s_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps) +{ + rt_err_t result = RT_EOK; + nu_i2s_t psNuSPII2s = (nu_i2s_t)audio; + nu_acodec_ops_t pNuACodecOps; + + RT_ASSERT(audio != RT_NULL); + RT_ASSERT(caps != RT_NULL); + RT_ASSERT(psNuSPII2s->AcodecOps != RT_NULL); + + pNuACodecOps = psNuSPII2s->AcodecOps; + + switch (caps->main_type) + { + case AUDIO_TYPE_QUERY: + switch (caps->sub_type) + { + case AUDIO_TYPE_QUERY: + caps->udata.mask = AUDIO_TYPE_INPUT | AUDIO_TYPE_OUTPUT | AUDIO_TYPE_MIXER; + break; + default: + result = -RT_ERROR; + break; + } // switch (caps->sub_type) + break; + + case AUDIO_TYPE_MIXER: + + if (pNuACodecOps->nu_acodec_mixer_query) + { + switch (caps->sub_type) + { + case AUDIO_MIXER_QUERY: + return pNuACodecOps->nu_acodec_mixer_query(AUDIO_MIXER_QUERY, &caps->udata.mask); + + default: + return pNuACodecOps->nu_acodec_mixer_query(caps->sub_type, (rt_uint32_t *)&caps->udata.value); + } // switch (caps->sub_type) + + } // if (pNuACodecOps->nu_acodec_mixer_query) + + result = -RT_ERROR; + break; + + case AUDIO_TYPE_INPUT: + case AUDIO_TYPE_OUTPUT: + + switch (caps->sub_type) + { + case AUDIO_DSP_PARAM: + caps->udata.config.channels = psNuSPII2s->config.channels; + caps->udata.config.samplebits = psNuSPII2s->config.samplebits; + caps->udata.config.samplerate = psNuSPII2s->config.samplerate; + break; + case AUDIO_DSP_SAMPLERATE: + caps->udata.config.samplerate = psNuSPII2s->config.samplerate; + break; + case AUDIO_DSP_CHANNELS: + caps->udata.config.channels = psNuSPII2s->config.channels; + break; + case AUDIO_DSP_SAMPLEBITS: + caps->udata.config.samplebits = psNuSPII2s->config.samplebits; + break; + default: + result = -RT_ERROR; + break; + } // switch (caps->sub_type) + break; + + default: + result = -RT_ERROR; + break; + + } // switch (caps->main_type) + + return result; +} + +static rt_err_t nu_spii2s_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps) +{ + rt_err_t result = RT_EOK; + nu_i2s_t psNuSPII2s = (nu_i2s_t)audio; + nu_acodec_ops_t pNuACodecOps; + int stream = -1; + + RT_ASSERT(audio != RT_NULL); + RT_ASSERT(caps != RT_NULL); + RT_ASSERT(psNuSPII2s->AcodecOps != RT_NULL); + + pNuACodecOps = psNuSPII2s->AcodecOps; + + switch (caps->main_type) + { + case AUDIO_TYPE_MIXER: + if (psNuSPII2s->AcodecOps->nu_acodec_mixer_control) + psNuSPII2s->AcodecOps->nu_acodec_mixer_control(caps->sub_type, caps->udata.value); + break; + + case AUDIO_TYPE_INPUT: + stream = AUDIO_STREAM_RECORD; + case AUDIO_TYPE_OUTPUT: + { + rt_bool_t bNeedReset = RT_FALSE; + + if (stream < 0) + stream = AUDIO_STREAM_REPLAY; + + switch (caps->sub_type) + { + case AUDIO_DSP_PARAM: + if (rt_memcmp(&psNuSPII2s->config, &caps->udata.config, sizeof(struct rt_audio_configure)) != 0) + { + rt_memcpy(&psNuSPII2s->config, &caps->udata.config, sizeof(struct rt_audio_configure)); + bNeedReset = RT_TRUE; + } + break; + case AUDIO_DSP_SAMPLEBITS: + if (psNuSPII2s->config.samplerate != caps->udata.config.samplebits) + { + psNuSPII2s->config.samplerate = caps->udata.config.samplebits; + bNeedReset = RT_TRUE; + } + break; + case AUDIO_DSP_CHANNELS: + if (psNuSPII2s->config.channels != caps->udata.config.channels) + { + pNuACodecOps->config.channels = caps->udata.config.channels; + bNeedReset = RT_TRUE; + } + break; + case AUDIO_DSP_SAMPLERATE: + if (psNuSPII2s->config.samplerate != caps->udata.config.samplerate) + { + psNuSPII2s->config.samplerate = caps->udata.config.samplerate; + bNeedReset = RT_TRUE; + } + break; + default: + result = -RT_ERROR; + break; + } // switch (caps->sub_type) + + if (bNeedReset) + { + return nu_spii2s_start(audio, stream); + } + } + break; + + default: + result = -RT_ERROR; + break; + } // switch (caps->main_type) + + return result; +} + +static rt_err_t nu_spii2s_init(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + nu_i2s_t psNuSPII2s = (nu_i2s_t)audio; + + RT_ASSERT(audio != RT_NULL); + + /* Reset this module */ + SYS_ResetModule(psNuSPII2s->i2s_rst); + + return -(result); +} + +static rt_err_t nu_spii2s_start(struct rt_audio_device *audio, int stream) +{ + nu_i2s_t psNuSPII2s = (nu_i2s_t)audio; + SPI_T *spii2s_base; + + RT_ASSERT(audio != RT_NULL); + + spii2s_base = (SPI_T *)psNuSPII2s->i2s_base; + + /* Restart all: SPII2S and codec. */ + nu_spii2s_stop(audio, stream); + if (nu_spii2s_dai_setup(psNuSPII2s, &psNuSPII2s->config) != RT_EOK) + return -RT_ERROR; + + switch (stream) + { + case AUDIO_STREAM_REPLAY: + { + nu_spii2s_pdma_sc_config(psNuSPII2s, NU_I2S_DAI_PLAYBACK); + + /* Start TX DMA */ + SPII2S_ENABLE_TXDMA(spii2s_base); + + /* Enable I2S Tx function */ + SPII2S_ENABLE_TX(spii2s_base); + + LOG_I("Start replay."); + } + break; + + case AUDIO_STREAM_RECORD: + { + nu_spii2s_pdma_sc_config(psNuSPII2s, NU_I2S_DAI_CAPTURE); + + /* Start RX DMA */ + SPII2S_ENABLE_RXDMA(spii2s_base); + + /* Enable I2S Rx function */ + SPII2S_ENABLE_RX(spii2s_base); + + LOG_I("Start record."); + } + break; + default: + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t nu_spii2s_stop(struct rt_audio_device *audio, int stream) +{ + nu_i2s_t psNuSPII2s = (nu_i2s_t)audio; + nu_i2s_dai_t psNuSPII2sDai = RT_NULL; + SPI_T *spii2s_base; + + RT_ASSERT(audio != RT_NULL); + + spii2s_base = (SPI_T *)psNuSPII2s->i2s_base; + + switch (stream) + { + case AUDIO_STREAM_REPLAY: + psNuSPII2sDai = &psNuSPII2s->i2s_dais[NU_I2S_DAI_PLAYBACK]; + + // Disable TX + SPII2S_DISABLE_TXDMA(spii2s_base); + SPII2S_DISABLE_TX(spii2s_base); + + LOG_I("Stop replay."); + break; + + case AUDIO_STREAM_RECORD: + psNuSPII2sDai = &psNuSPII2s->i2s_dais[NU_I2S_DAI_CAPTURE]; + + // Disable RX + SPII2S_DISABLE_RXDMA(spii2s_base); + SPII2S_DISABLE_RX(spii2s_base); + + LOG_I("Stop record."); + break; + + default: + return -RT_EINVAL; + } + + /* Stop DMA transfer. */ + nu_pdma_channel_terminate(psNuSPII2sDai->pdma_chanid); + + /* Close SPII2S */ + if (!(spii2s_base->I2SCTL & (SPI_I2SCTL_TXEN_Msk | SPI_I2SCTL_RXEN_Msk))) + { + SPII2S_DisableMCLK(spii2s_base); + SPII2S_Close(spii2s_base); + LOG_I("Close SPII2S."); + } + + /* Silence */ + rt_memset((void *)psNuSPII2sDai->fifo, 0, NU_I2S_DMA_FIFO_SIZE); + psNuSPII2sDai->fifo_block_idx = 0; + + return RT_EOK; +} + +static void nu_spii2s_buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info) +{ + nu_i2s_t psNuSPII2s = (nu_i2s_t)audio; + + RT_ASSERT(audio != RT_NULL); + RT_ASSERT(info != RT_NULL); + + info->buffer = (rt_uint8_t *)psNuSPII2s->i2s_dais[NU_I2S_DAI_PLAYBACK].fifo ; + info->total_size = NU_I2S_DMA_FIFO_SIZE; + info->block_size = NU_I2S_DMA_BUF_BLOCK_SIZE; + info->block_count = NU_I2S_DMA_BUF_BLOCK_NUMBER; + + return; +} + +static struct rt_audio_ops nu_spii2s_audio_ops = +{ + .getcaps = nu_spii2s_getcaps, + .configure = nu_spii2s_configure, + + .init = nu_spii2s_init, + .start = nu_spii2s_start, + .stop = nu_spii2s_stop, + .transmit = RT_NULL, + .buffer_info = nu_spii2s_buffer_info +}; + +static rt_err_t nu_hw_spii2s_pdma_allocate(nu_i2s_dai_t psNuSPII2sDai) +{ + /* Allocate I2S nu_dma channel */ + if ((psNuSPII2sDai->pdma_chanid = nu_pdma_channel_allocate(psNuSPII2sDai->pdma_perp)) < 0) + { + goto nu_hw_spii2s_pdma_allocate; + } + + return RT_EOK; + +nu_hw_spii2s_pdma_allocate: + + return -(RT_ERROR); +} + +int rt_hw_spii2s_init(void) +{ + int j = 0; + nu_i2s_dai_t psNuSPII2sDai; + + for (j = (SPII2S_START + 1); j < SPII2S_CNT; j++) + { + int i = 0; + for (i = 0; i < NU_I2S_DAI_CNT; i++) + { + uint8_t *pu8ptr = rt_malloc(NU_I2S_DMA_FIFO_SIZE); + psNuSPII2sDai = &g_nu_spii2s_arr[j].i2s_dais[i]; + psNuSPII2sDai->fifo = pu8ptr; + rt_memset(pu8ptr, 0, NU_I2S_DMA_FIFO_SIZE); + RT_ASSERT(psNuSPII2sDai->fifo != RT_NULL); + + psNuSPII2sDai->pdma_chanid = -1; + psNuSPII2sDai->fifo_block_idx = 0; + RT_ASSERT(nu_hw_spii2s_pdma_allocate(psNuSPII2sDai) == RT_EOK); + RT_ASSERT(nu_pdma_sgtbls_allocate(&psNuSPII2sDai->pdma_descs[0], NU_I2S_DMA_BUF_BLOCK_NUMBER) == RT_EOK); + } + + /* Register ops of audio device */ + g_nu_spii2s_arr[j].audio.ops = &nu_spii2s_audio_ops; + + /* Register device, RW: it is with replay and record functions. */ + rt_audio_register(&g_nu_spii2s_arr[j].audio, g_nu_spii2s_arr[j].name, RT_DEVICE_FLAG_RDWR, &g_nu_spii2s_arr[j]); + } + + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_spii2s_init); +#endif //#if defined(BSP_USING_SPII2S) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_timer.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_timer.c new file mode 100644 index 0000000000..ec2b1d72cb --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_timer.c @@ -0,0 +1,326 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-9-7 Philo First version +* +******************************************************************************/ + +#include + +#if (defined(BSP_USING_TIMER) && defined(RT_USING_HWTIMER)) + +#include +#include "NuMicro.h" + +/* Private define ---------------------------------------------------------------*/ +#define NU_TIMER_DEVICE(timer) (nu_timer_t *)(timer) +#define TIMER_SET_OPMODE(timer, u32OpMode) ((timer)->CTL = ((timer)->CTL & ~TIMER_CTL_OPMODE_Msk) | (u32OpMode)) + +/* Private typedef --------------------------------------------------------------*/ +typedef struct nu_timer +{ + rt_hwtimer_t parent; + TIMER_T *timer_periph; + IRQn_Type IRQn; +} nu_timer_t; + +/* Private functions ------------------------------------------------------------*/ +static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state); +static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode); +static void nu_timer_stop(rt_hwtimer_t *timer); +static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer); +static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args); + +/* Public functions -------------------------------------------------------------*/ + + +/* Private variables ------------------------------------------------------------*/ +#ifdef BSP_USING_TIMER0 + static nu_timer_t nu_timer0; +#endif + +#ifdef BSP_USING_TIMER1 + static nu_timer_t nu_timer1; +#endif + +#ifdef BSP_USING_TIMER2 + static nu_timer_t nu_timer2; +#endif + +#ifdef BSP_USING_TIMER3 + static nu_timer_t nu_timer3; +#endif + +static struct rt_hwtimer_info nu_timer_info = +{ + 12000000, /* maximum count frequency */ + 46875, /* minimum count frequency */ + 0xFFFFFF, /* the maximum counter value */ + HWTIMER_CNTMODE_UP,/* Increment or Decreasing count mode */ +}; + +static struct rt_hwtimer_ops nu_timer_ops = +{ + nu_timer_init, + nu_timer_start, + nu_timer_stop, + nu_timer_count_get, + nu_timer_control +}; + +/* Functions define ------------------------------------------------------------*/ +static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state) +{ + RT_ASSERT(timer != RT_NULL); + + nu_timer_t *nu_timer = NU_TIMER_DEVICE(timer->parent.user_data); + RT_ASSERT(nu_timer != RT_NULL); + RT_ASSERT(nu_timer->timer_periph != RT_NULL); + + if (1 == state) + { + uint32_t timer_clk; + struct rt_hwtimer_info *info = &nu_timer_info; + + timer_clk = TIMER_GetModuleClock(nu_timer->timer_periph); + info->maxfreq = timer_clk; + info->minfreq = timer_clk / 256; + TIMER_Open(nu_timer->timer_periph, TIMER_ONESHOT_MODE, 1); + TIMER_EnableInt(nu_timer->timer_periph); + NVIC_EnableIRQ(nu_timer->IRQn); + } + else + { + NVIC_DisableIRQ(nu_timer->IRQn); + TIMER_DisableInt(nu_timer->timer_periph); + TIMER_Close(nu_timer->timer_periph); + } +} + +static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode) +{ + rt_err_t err = RT_EOK; + RT_ASSERT(timer != RT_NULL); + + nu_timer_t *nu_timer = NU_TIMER_DEVICE(timer->parent.user_data); + RT_ASSERT(nu_timer != RT_NULL); + RT_ASSERT(nu_timer->timer_periph != RT_NULL); + + if (cnt > 1 && cnt <= 0xFFFFFF) + { + TIMER_SET_CMP_VALUE(nu_timer->timer_periph, cnt); + } + else + { + rt_kprintf("nu_timer_start set compared value failed\n"); + err = RT_ERROR; + } + + if (HWTIMER_MODE_PERIOD == opmode) + { + TIMER_SET_OPMODE(nu_timer->timer_periph, TIMER_PERIODIC_MODE); + } + else if (HWTIMER_MODE_ONESHOT == opmode) + { + TIMER_SET_OPMODE(nu_timer->timer_periph, TIMER_ONESHOT_MODE); + } + else + { + rt_kprintf("nu_timer_start set operation mode failed\n"); + err = RT_ERROR; + } + + TIMER_Start(nu_timer->timer_periph); + + return err; +} + +static void nu_timer_stop(rt_hwtimer_t *timer) +{ + RT_ASSERT(timer != RT_NULL); + + nu_timer_t *nu_timer = NU_TIMER_DEVICE(timer->parent.user_data); + RT_ASSERT(nu_timer != RT_NULL); + RT_ASSERT(nu_timer->timer_periph != RT_NULL); + + TIMER_Stop(nu_timer->timer_periph); +} + +static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer) +{ + RT_ASSERT(timer != RT_NULL); + + nu_timer_t *nu_timer = NU_TIMER_DEVICE(timer->parent.user_data); + RT_ASSERT(nu_timer != RT_NULL); + RT_ASSERT(nu_timer->timer_periph != RT_NULL); + + return TIMER_GetCounter(nu_timer->timer_periph); +} + +static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args) +{ + rt_err_t ret = RT_EOK; + + RT_ASSERT(timer != RT_NULL); + + nu_timer_t *nu_timer = NU_TIMER_DEVICE(timer->parent.user_data); + RT_ASSERT(nu_timer != RT_NULL); + RT_ASSERT(nu_timer->timer_periph != RT_NULL); + + switch (cmd) + { + case HWTIMER_CTRL_FREQ_SET: + { + uint32_t clk; + uint32_t pre; + + clk = TIMER_GetModuleClock(nu_timer->timer_periph); + pre = clk / *((uint32_t *)args) - 1; + TIMER_SET_PRESCALE_VALUE(nu_timer->timer_periph, pre); + *((uint32_t *)args) = clk / (pre + 1) ; + } + break; + + case HWTIMER_CTRL_STOP: + TIMER_Stop(nu_timer->timer_periph); + break; + + default: + ret = RT_EINVAL; + break; + } + + return ret; +} + +int rt_hw_timer_init(void) +{ + rt_err_t ret = RT_EOK; + +#ifdef BSP_USING_TIMER0 + nu_timer0.timer_periph = TIMER0; + nu_timer0.parent.info = &nu_timer_info; + nu_timer0.parent.ops = &nu_timer_ops; + nu_timer0.IRQn = TMR0_IRQn; + ret = rt_device_hwtimer_register(&nu_timer0.parent, "timer0", &nu_timer0); + if (ret != RT_EOK) + { + rt_kprintf("timer0 register failed\n"); + } + SYS_ResetModule(TMR0_RST); + CLK_EnableModuleClock(TMR0_MODULE); +#endif + +#ifdef BSP_USING_TIMER1 + nu_timer1.timer_periph = TIMER1; + nu_timer1.parent.info = &nu_timer_info; + nu_timer1.parent.ops = &nu_timer_ops; + nu_timer1.IRQn = TMR1_IRQn; + ret = rt_device_hwtimer_register(&nu_timer1.parent, "timer1", &nu_timer1); + if (ret != RT_EOK) + { + rt_kprintf("timer1 register failed\n"); + } + SYS_ResetModule(TMR1_RST); + CLK_EnableModuleClock(TMR1_MODULE); +#endif + +#ifdef BSP_USING_TIMER2 + nu_timer2.timer_periph = TIMER2; + nu_timer2.parent.info = &nu_timer_info; + nu_timer2.parent.ops = &nu_timer_ops; + nu_timer2.IRQn = TMR2_IRQn; + ret = rt_device_hwtimer_register(&nu_timer2.parent, "timer2", &nu_timer2); + if (ret != RT_EOK) + { + rt_kprintf("timer2 register failed\n"); + } + SYS_ResetModule(TMR2_RST); + CLK_EnableModuleClock(TMR2_MODULE); +#endif + +#ifdef BSP_USING_TIMER3 + nu_timer3.timer_periph = TIMER3; + nu_timer3.parent.info = &nu_timer_info; + nu_timer3.parent.ops = &nu_timer_ops; + nu_timer3.IRQn = TMR3_IRQn; + ret = rt_device_hwtimer_register(&nu_timer3.parent, "timer3", &nu_timer3); + if (ret != RT_EOK) + { + rt_kprintf("timer3 register failed\n"); + } + SYS_ResetModule(TMR3_RST); + CLK_EnableModuleClock(TMR3_MODULE); +#endif + + return ret; +} + +INIT_BOARD_EXPORT(rt_hw_timer_init); + +#ifdef BSP_USING_TIMER0 +void TMR0_IRQHandler(void) +{ + rt_interrupt_enter(); + + if (TIMER_GetIntFlag(TIMER0)) + { + TIMER_ClearIntFlag(TIMER0); + rt_device_hwtimer_isr(&nu_timer0.parent); + } + + rt_interrupt_leave(); +} +#endif + +#ifdef BSP_USING_TIMER1 +void TMR1_IRQHandler(void) +{ + rt_interrupt_enter(); + + if (TIMER_GetIntFlag(TIMER1)) + { + TIMER_ClearIntFlag(TIMER1); + rt_device_hwtimer_isr(&nu_timer1.parent); + } + + rt_interrupt_leave(); +} +#endif + +#ifdef BSP_USING_TIMER2 +void TMR2_IRQHandler(void) +{ + rt_interrupt_enter(); + + if (TIMER_GetIntFlag(TIMER2)) + { + TIMER_ClearIntFlag(TIMER2); + rt_device_hwtimer_isr(&nu_timer2.parent); + } + + rt_interrupt_leave(); +} +#endif + +#ifdef BSP_USING_TIMER3 +void TMR3_IRQHandler(void) +{ + rt_interrupt_enter(); + + if (TIMER_GetIntFlag(TIMER3)) + { + TIMER_ClearIntFlag(TIMER3); + rt_device_hwtimer_isr(&nu_timer3.parent); + } + + rt_interrupt_leave(); +} +#endif + +#endif //#if (defined(BSP_USING_TIMER) && defined(RT_USING_HWTIMER)) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_timer_capture.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_timer_capture.c new file mode 100644 index 0000000000..740f86312b --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_timer_capture.c @@ -0,0 +1,327 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-08 klcheng First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_TIMER_CAPTURE) +#if defined(BSP_USING_TIMER0_CAPTURE)|| \ + defined(BSP_USING_TIMER1_CAPTURE)|| \ + defined(BSP_USING_TIMER2_CAPTURE)|| \ + defined(BSP_USING_TIMER3_CAPTURE) + +#include +#include "NuMicro.h" + +/* Private typedef --------------------------------------------------------------*/ +typedef struct _timer +{ + struct rt_inputcapture_device parent; + TIMER_T *timer; + uint8_t u8Channel; + IRQn_Type irq; + uint32_t u32CurrentCnt; + rt_bool_t input_data_level; + rt_bool_t first_edge; +} nu_capture_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture); +static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us); + +/* Private define ---------------------------------------------------------------*/ +#define TIMER_CHANNEL_NUM (4) + +#define TIMER0_POS (0) +#define TIMER1_POS (1) +#define TIMER2_POS (2) +#define TIMER3_POS (3) + +/* Timer prescale setting. Since it will affect the pulse width of measure, it is recommended to set to 2. */ +#define PSC_DIV (2) + +/* Public functions -------------------------------------------------------------*/ + + +/* Private variables ------------------------------------------------------------*/ +static const char *nu_timer_device_name[TIMER_CHANNEL_NUM] = { "timer0i0", "timer1i0", "timer2i0", "timer3i0"}; +static const IRQn_Type nu_timer_irq[TIMER_CHANNEL_NUM] = { TMR0_IRQn, TMR1_IRQn, TMR2_IRQn, TMR3_IRQn}; +static TIMER_T *nu_timer_base[TIMER_CHANNEL_NUM] = { TIMER0, TIMER1, TIMER2, TIMER3}; +static nu_capture_t *nu_timer_capture[TIMER_CHANNEL_NUM] = {0}; + +static struct rt_inputcapture_ops nu_capture_ops = +{ + .init = nu_capture_init, + .open = nu_capture_open, + .close = nu_capture_close, + .get_pulsewidth = nu_capture_get_pulsewidth, +}; + +/* Functions define ------------------------------------------------------------*/ +void timer_interrupt_handler(nu_capture_t *nu_timer_capture) +{ + TIMER_ClearCaptureIntFlag(nu_timer_capture->timer); + + /* First event is rising edge */ + if (nu_timer_capture->first_edge == RT_TRUE) + { + TIMER_EnableCapture(nu_timer_capture->timer, TIMER_CAPTURE_COUNTER_RESET_MODE, TIMER_CAPTURE_FALLING_AND_RISING_EDGE); + nu_timer_capture->first_edge = RT_FALSE; + nu_timer_capture->input_data_level = RT_FALSE; + } + else + { + nu_timer_capture->input_data_level = !nu_timer_capture->input_data_level; + nu_timer_capture->u32CurrentCnt = TIMER_GetCaptureData(nu_timer_capture->timer); + + rt_hw_inputcapture_isr(&nu_timer_capture->parent, nu_timer_capture->input_data_level); + } +} + +#if defined(BSP_USING_TIMER0_CAPTURE) +void TMR0_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + timer_interrupt_handler(nu_timer_capture[0]); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif //defined(BSP_USING_TIMER0_CAPTURE) + +#if defined(BSP_USING_TIMER1_CAPTURE) +void TMR1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + timer_interrupt_handler(nu_timer_capture[1]); + + /* leave interrupt */ + rt_interrupt_leave(); + +} +#endif //defined(BSP_USING_TIMER1_CAPTURE) + +#if defined(BSP_USING_TIMER2_CAPTURE) +void TMR2_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + timer_interrupt_handler(nu_timer_capture[2]); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif //defined(BSP_USING_TIMER2_CAPTURE) + +#if defined(BSP_USING_TIMER3_CAPTURE) +void TMR3_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + timer_interrupt_handler(nu_timer_capture[3]); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif //defined(BSP_USING_TIMER3_CAPTURE) + +static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us) +{ + rt_err_t ret = RT_EOK; + nu_capture_t *nu_capture; + + nu_capture = (nu_capture_t *)inputcapture; + + *pulsewidth_us = nu_capture->u32CurrentCnt / PSC_DIV; + + return -(ret); +} + +static rt_err_t nu_timer_init(nu_capture_t *nu_capture) +{ + SYS_UnlockReg(); + +#if defined(BSP_USING_TIMER0_CAPTURE) + if (nu_capture->timer == TIMER0) + { + /* Enable TIMER0 clock */ + CLK_EnableModuleClock(TMR0_MODULE); + CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_PCLK0, 0); + goto exit_nu_timer_init; + } +#endif +#if defined(BSP_USING_TIMER1_CAPTURE) + if (nu_capture->timer == TIMER1) + { + /* Enable TIMER1 clock */ + CLK_EnableModuleClock(TMR1_MODULE); + CLK_SetModuleClock(TMR1_MODULE, CLK_CLKSEL1_TMR1SEL_PCLK0, 0); + goto exit_nu_timer_init; + } +#endif +#if defined(BSP_USING_TIMER2_CAPTURE) + if (nu_capture->timer == TIMER2) + { + /* Enable TIMER2 clock */ + CLK_EnableModuleClock(TMR2_MODULE); + CLK_SetModuleClock(TMR2_MODULE, CLK_CLKSEL1_TMR2SEL_PCLK1, 0); + goto exit_nu_timer_init; + } +#endif +#if defined(BSP_USING_TIMER3_CAPTURE) + if (nu_capture->timer == TIMER3) + { + /* Enable TIMER3 clock */ + CLK_EnableModuleClock(TMR3_MODULE); + CLK_SetModuleClock(TMR3_MODULE, CLK_CLKSEL1_TMR3SEL_PCLK1, 0); + goto exit_nu_timer_init; + } +#endif + + SYS_LockReg(); + return -(RT_ERROR); + +exit_nu_timer_init: + + SYS_LockReg(); + return RT_EOK; +} + +static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture) +{ + rt_err_t ret = RT_EOK; + nu_capture_t *nu_capture; + + RT_ASSERT(inputcapture != RT_NULL); + + nu_capture = (nu_capture_t *) inputcapture; + + if (nu_timer_init(nu_capture) != RT_EOK) + { + rt_kprintf("Failed to initialize TIMER.\n"); + ret = RT_ERROR; + } + + return -(ret); +} + +static uint8_t cal_time_prescale(nu_capture_t *nu_capture) +{ + uint32_t u32Clk = TIMER_GetModuleClock(nu_capture->timer); + + /* 1 tick = 1/PSC_DIV us */ + return (u32Clk / 1000000 / PSC_DIV) - 1; +} + +static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture) +{ + rt_err_t ret = RT_EOK; + nu_capture_t *nu_capture; + + RT_ASSERT(inputcapture != RT_NULL); + + nu_capture = (nu_capture_t *) inputcapture; + + nu_capture->first_edge = RT_TRUE; + + /* Enable Timer NVIC */ + NVIC_EnableIRQ(nu_capture->irq); + + /* Reset counter before openning. */ + TIMER_ResetCounter(nu_capture->timer); + + TIMER_Open(nu_capture->timer, TIMER_CONTINUOUS_MODE, 1); + TIMER_SET_PRESCALE_VALUE(nu_capture->timer, cal_time_prescale(nu_capture)); + TIMER_SET_CMP_VALUE(nu_capture->timer, 0xFFFFFF); + + TIMER_EnableCapture(nu_capture->timer, TIMER_CAPTURE_COUNTER_RESET_MODE, TIMER_CAPTURE_RISING_EDGE); + + TIMER_EnableInt(nu_capture->timer); + + TIMER_EnableCaptureInt(nu_capture->timer); + + TIMER_Start(nu_capture->timer); + + return ret; +} + +static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture) +{ + rt_err_t ret = RT_EOK; + + nu_capture_t *nu_capture; + + RT_ASSERT(inputcapture != RT_NULL); + + nu_capture = (nu_capture_t *) inputcapture; + + TIMER_Stop(nu_capture->timer); + + TIMER_DisableCaptureInt(nu_capture->timer); + + TIMER_DisableInt(nu_capture->timer); + + TIMER_Close(nu_capture->timer); + + NVIC_DisableIRQ(nu_capture->irq); + + return ret; +} + +/* Init and register timer capture */ +static int nu_timer_capture_device_init(void) +{ + uint8_t TIMER_MSK = 0; + +#if defined(BSP_USING_TIMER0_CAPTURE) + TIMER_MSK |= (0x1 << 0); +#endif +#if defined(BSP_USING_TIMER1_CAPTURE) + TIMER_MSK |= (0x1 << 1); +#endif +#if defined(BSP_USING_TIMER2_CAPTURE) + TIMER_MSK |= (0x1 << 2); +#endif +#if defined(BSP_USING_TIMER3_CAPTURE) + TIMER_MSK |= (0x1 << 3); +#endif + + for (int i = 0; i < TIMER_CHANNEL_NUM; i++) + { + if (TIMER_MSK & (0x1 << i)) + { + nu_timer_capture[i] = (nu_capture_t *)rt_malloc(sizeof(nu_capture_t)); + + nu_timer_capture[i]->timer = nu_timer_base[i]; + nu_timer_capture[i]->u8Channel = i; + nu_timer_capture[i]->irq = nu_timer_irq[i]; + nu_timer_capture[i]->u32CurrentCnt = 0; + nu_timer_capture[i]->parent.ops = &nu_capture_ops; + nu_timer_capture[i]->first_edge = RT_TRUE; + + /* register inputcapture device */ + rt_device_inputcapture_register(&nu_timer_capture[i]->parent, nu_timer_device_name[i], &nu_timer_capture[i]); + } + } + + return 0; +} +INIT_DEVICE_EXPORT(nu_timer_capture_device_init); +#endif //#if defined(BSP_USING_TIMER*_CAPTURE) +#endif //#if defined(BSP_USING_TIMER_CAPTURE) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_uart.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_uart.c new file mode 100644 index 0000000000..e8af9c6f5d --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_uart.c @@ -0,0 +1,838 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-9-2 Philo First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_UART) + +#include +#include +#include "NuMicro.h" +#include + +#if defined(RT_SERIAL_USING_DMA) + #include +#endif + +/* Private define ---------------------------------------------------------------*/ +enum +{ + UART_START = -1, +#if defined(BSP_USING_UART0) + UART0_IDX, +#endif +#if defined(BSP_USING_UART1) + UART1_IDX, +#endif +#if defined(BSP_USING_UART2) + UART2_IDX, +#endif +#if defined(BSP_USING_UART3) + UART3_IDX, +#endif +#if defined(BSP_USING_UART4) + UART4_IDX, +#endif +#if defined(BSP_USING_UART5) + UART5_IDX, +#endif +#if defined(BSP_USING_UART6) + UART6_IDX, +#endif +#if defined(BSP_USING_UART7) + UART7_IDX, +#endif + UART_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ +struct nu_uart +{ + rt_serial_t dev; + char *name; + UART_T *uart_base; + uint32_t uart_rst; + IRQn_Type uart_irq_n; + +#if defined(RT_SERIAL_USING_DMA) + uint32_t dma_flag; + int16_t pdma_perp_tx; + int8_t pdma_chanid_tx; + + int16_t pdma_perp_rx; + int8_t pdma_chanid_rx; + int32_t rx_write_offset; + int32_t rxdma_trigger_len; +#endif + +}; +typedef struct nu_uart *nu_uart_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg); +static rt_err_t nu_uart_control(struct rt_serial_device *serial, int cmd, void *arg); +static int nu_uart_send(struct rt_serial_device *serial, char c); +static int nu_uart_receive(struct rt_serial_device *serial); +static void nu_uart_isr(nu_uart_t serial); + +#if defined(RT_SERIAL_USING_DMA) + static rt_size_t nu_uart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction); + static void nu_pdma_uart_rx_cb(void *pvOwner, uint32_t u32Events); + static void nu_pdma_uart_tx_cb(void *pvOwner, uint32_t u32Events); +#endif + +/* Public functions ------------------------------------------------------------*/ + +/* Private variables ------------------------------------------------------------*/ + +static const struct rt_uart_ops nu_uart_ops = +{ + .configure = nu_uart_configure, + .control = nu_uart_control, + .putc = nu_uart_send, + .getc = nu_uart_receive, +#if defined(RT_SERIAL_USING_DMA) + .dma_transmit = nu_uart_dma_transmit +#else + .dma_transmit = RT_NULL +#endif +}; + +static const struct serial_configure nu_uart_default_config = + RT_SERIAL_CONFIG_DEFAULT; + +static struct nu_uart nu_uart_arr [] = +{ +#if defined(BSP_USING_UART0) + { + .name = "uart0", + .uart_base = UART0, + .uart_rst = UART0_RST, + .uart_irq_n = UART02_IRQn, + +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UART0_TX_DMA) + .pdma_perp_tx = PDMA_UART0_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UART0_RX_DMA) + .pdma_perp_rx = PDMA_UART0_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + +#if defined(BSP_USING_UART1) + { + .name = "uart1", + .uart_base = UART1, + .uart_rst = UART1_RST, + .uart_irq_n = UART13_IRQn, +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UART1_TX_DMA) + .pdma_perp_tx = PDMA_UART1_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UART1_RX_DMA) + .pdma_perp_rx = PDMA_UART1_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + +#if defined(BSP_USING_UART2) + { + .name = "uart2", + .uart_base = UART2, + .uart_rst = UART2_RST, + .uart_irq_n = UART02_IRQn, +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UART2_TX_DMA) + .pdma_perp_tx = PDMA_UART2_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UART2_RX_DMA) + .pdma_perp_rx = PDMA_UART2_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + +#if defined(BSP_USING_UART3) + { + .name = "uart3", + .uart_base = UART3, + .uart_rst = UART3_RST, + .uart_irq_n = UART13_IRQn, +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UART3_TX_DMA) + .pdma_perp_tx = PDMA_UART3_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UART3_RX_DMA) + .pdma_perp_rx = PDMA_UART3_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + +#if defined(BSP_USING_UART4) + { + .name = "uart4", + .uart_base = UART4, + .uart_rst = UART4_RST, + .uart_irq_n = UART46_IRQn, +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UART4_TX_DMA) + .pdma_perp_tx = PDMA_UART4_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UART4_RX_DMA) + .pdma_perp_rx = PDMA_UART4_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + +#if defined(BSP_USING_UART5) + { + .name = "uart5", + .uart_base = UART5, + .uart_rst = UART5_RST, + .uart_irq_n = UART57_IRQn, +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UART5_TX_DMA) + .pdma_perp_tx = PDMA_UART5_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UART5_RX_DMA) + .pdma_perp_rx = PDMA_UART5_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + +#if defined(BSP_USING_UART6) + { + .name = "uart6", + .uart_base = UART6, + .uart_rst = UART6_RST, + .uart_irq_n = UART46_IRQn, +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UART6_TX_DMA) + .pdma_perp_tx = PDMA_UART6_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UART6_RX_DMA) + .pdma_perp_rx = PDMA_UART6_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + +#if defined(BSP_USING_UART7) + { + .name = "uart7", + .uart_base = UART7, + .uart_rst = UART7_RST, + .uart_irq_n = UART57_IRQn, +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UART7_TX_DMA) + .pdma_perp_tx = PDMA_UART7_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UART7_RX_DMA) + .pdma_perp_rx = PDMA_UART7_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + {0} +}; /* uart nu_uart */ + +/* Interrupt Handle Function ----------------------------------------------------*/ +#if defined(BSP_USING_UART0) || defined(BSP_USING_UART2) +/* UART02 interrupt entry */ +void UART02_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + +#if defined(BSP_USING_UART0) + nu_uart_isr(&nu_uart_arr[UART0_IDX]); +#endif + +#if defined(BSP_USING_UART2) + nu_uart_isr(&nu_uart_arr[UART2_IDX]); +#endif + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif + +#if defined(BSP_USING_UART1) || defined(BSP_USING_UART3) +/* UART13 interrupt entry */ +void UART13_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + +#if defined(BSP_USING_UART1) + nu_uart_isr(&nu_uart_arr[UART1_IDX]); +#endif + +#if defined(BSP_USING_UART3) + nu_uart_isr(&nu_uart_arr[UART3_IDX]); +#endif + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif + +#if defined(BSP_USING_UART4) || defined(BSP_USING_UART6) +/* UART46 interrupt entry */ +void UART46_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + +#if defined(BSP_USING_UART4) + nu_uart_isr(&nu_uart_arr[UART4_IDX]); +#endif + +#if defined(BSP_USING_UART6) + nu_uart_isr(&nu_uart_arr[UART6_IDX]); +#endif + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif + +#if defined(BSP_USING_UART5) || defined(BSP_USING_UART7) +/* UART57 interrupt entry */ +void UART57_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + +#if defined(BSP_USING_UART5) + nu_uart_isr(&nu_uart_arr[UART5_IDX]); +#endif + +#if defined(BSP_USING_UART7) + nu_uart_isr(&nu_uart_arr[UART7_IDX]); +#endif + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif + +/** + * All UART interrupt service routine + */ +static void nu_uart_isr(nu_uart_t serial) +{ + /* Get base address of uart register */ + UART_T *uart_base = ((nu_uart_t)serial)->uart_base; + + /* Get interrupt event */ + uint32_t u32IntSts = uart_base->INTSTS; + uint32_t u32FIFOSts = uart_base->FIFOSTS; + +#if defined(RT_SERIAL_USING_DMA) + if (u32IntSts & UART_INTSTS_HWRLSIF_Msk) + { + /* Drain RX FIFO to remove remain FEF frames in FIFO. */ + uart_base->FIFO |= UART_FIFO_RXRST_Msk; + uart_base->FIFOSTS |= (UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_PEF_Msk); + return; + } +#endif + + /* Handle RX event */ + if (u32IntSts & (UART_INTSTS_RDAINT_Msk | UART_INTSTS_RXTOINT_Msk)) + { + rt_hw_serial_isr(&serial->dev, RT_SERIAL_EVENT_RX_IND); + } + uart_base->INTSTS = u32IntSts; + uart_base->FIFOSTS = u32FIFOSts; +} + +/** + * Configure uart port + */ +static rt_err_t nu_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + rt_err_t ret = RT_EOK; + uint32_t uart_word_len = 0; + uint32_t uart_stop_bit = 0; + uint32_t uart_parity = 0; + + /* Get base address of uart register */ + UART_T *uart_base = ((nu_uart_t)serial)->uart_base; + + /* Check baudrate */ + RT_ASSERT(cfg->baud_rate != 0); + + /* Check word len */ + switch (cfg->data_bits) + { + case DATA_BITS_5: + uart_word_len = UART_WORD_LEN_5; + break; + + case DATA_BITS_6: + uart_word_len = UART_WORD_LEN_6; + break; + + case DATA_BITS_7: + uart_word_len = UART_WORD_LEN_7; + break; + + case DATA_BITS_8: + uart_word_len = UART_WORD_LEN_8; + break; + + default: + rt_kprintf("Unsupported data length"); + ret = RT_EINVAL; + goto exit_nu_uart_configure; + } + + /* Check stop bit */ + switch (cfg->stop_bits) + { + case STOP_BITS_1: + uart_stop_bit = UART_STOP_BIT_1; + break; + + case STOP_BITS_2: + uart_stop_bit = UART_STOP_BIT_2; + break; + + default: + rt_kprintf("Unsupported stop bit"); + ret = RT_EINVAL; + goto exit_nu_uart_configure; + } + + /* Check parity */ + switch (cfg->parity) + { + case PARITY_NONE: + uart_parity = UART_PARITY_NONE; + break; + + case PARITY_ODD: + uart_parity = UART_PARITY_ODD; + break; + + case PARITY_EVEN: + uart_parity = UART_PARITY_EVEN; + break; + + default: + rt_kprintf("Unsupported parity"); + ret = RT_EINVAL; + goto exit_nu_uart_configure; + } + + /* Reset this module */ + SYS_ResetModule(((nu_uart_t)serial)->uart_rst); + + /* Open Uart and set UART Baudrate */ + UART_Open(uart_base, cfg->baud_rate); + + /* Set line configuration. */ + UART_SetLine_Config(uart_base, 0, uart_word_len, uart_parity, uart_stop_bit); + + /* Enable NVIC interrupt. */ + NVIC_EnableIRQ(((nu_uart_t)serial)->uart_irq_n); + +exit_nu_uart_configure: + + if (ret != RT_EOK) + UART_Close(uart_base); + + return -(ret); +} + +#if defined(RT_SERIAL_USING_DMA) +static rt_err_t nu_pdma_uart_rx_config(struct rt_serial_device *serial, uint8_t *pu8Buf, int32_t i32TriggerLen) +{ + rt_err_t result = RT_EOK; + + /* Get base address of uart register */ + UART_T *uart_base = ((nu_uart_t)serial)->uart_base; + + result = nu_pdma_callback_register(((nu_uart_t)serial)->pdma_chanid_rx, + nu_pdma_uart_rx_cb, + (void *)serial, + NU_PDMA_EVENT_TRANSFER_DONE | NU_PDMA_EVENT_TIMEOUT); + if ( result != RT_EOK ) + { + goto exit_nu_pdma_uart_rx_config; + } + + result = nu_pdma_transfer(((nu_uart_t)serial)->pdma_chanid_rx, + 8, + (uint32_t)uart_base, + (uint32_t)pu8Buf, + i32TriggerLen, + 1000); //Idle-timeout, 1ms + if ( result != RT_EOK ) + { + goto exit_nu_pdma_uart_rx_config; + } + + /* Enable Receive Line interrupt & Start DMA RX transfer. */ + UART_ENABLE_INT(uart_base, UART_INTEN_RLSIEN_Msk); + UART_ENABLE_INT(uart_base, UART_INTEN_RXPDMAEN_Msk); + +exit_nu_pdma_uart_rx_config: + + return result; +} + +static void nu_pdma_uart_rx_cb(void *pvOwner, uint32_t u32Events) +{ + rt_size_t recv_len = 0; + rt_size_t transferred_rxbyte = 0; + struct rt_serial_device *serial = (struct rt_serial_device *)pvOwner; + nu_uart_t puart = (nu_uart_t)serial; + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uart register */ + UART_T *uart_base = puart->uart_base; + + transferred_rxbyte = nu_pdma_transferred_byte_get(puart->pdma_chanid_rx, puart->rxdma_trigger_len); + + if (u32Events & (NU_PDMA_EVENT_TRANSFER_DONE | NU_PDMA_EVENT_TIMEOUT)) + { + if (u32Events & NU_PDMA_EVENT_TRANSFER_DONE) + { + if (serial->config.bufsz != 0) + { + struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + + nu_pdma_uart_rx_config(serial, &rx_fifo->buffer[0], puart->rxdma_trigger_len); // Config & trigger next + } + else + { + UART_DISABLE_INT(uart_base, UART_INTEN_RLSIEN_Msk); + UART_DISABLE_INT(uart_base, UART_INTEN_RXPDMAEN_Msk); + } + transferred_rxbyte = puart->rxdma_trigger_len; + } + else if ((u32Events & NU_PDMA_EVENT_TIMEOUT) && !UART_GET_RX_EMPTY(uart_base)) + { + return; + } + + recv_len = transferred_rxbyte - puart->rx_write_offset; + + puart->rx_write_offset = transferred_rxbyte % puart->rxdma_trigger_len; + + } + + if ((serial->config.bufsz == 0) && (u32Events & NU_PDMA_EVENT_TRANSFER_DONE)) + { + recv_len = puart->rxdma_trigger_len; + } + + if (recv_len) + { + rt_hw_serial_isr(&puart->dev, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); + } +} + +static rt_err_t nu_pdma_uart_tx_config(struct rt_serial_device *serial) +{ + rt_err_t result = RT_EOK; + RT_ASSERT(serial != RT_NULL); + + result = nu_pdma_callback_register(((nu_uart_t)serial)->pdma_chanid_tx, + nu_pdma_uart_tx_cb, + (void *)serial, + NU_PDMA_EVENT_TRANSFER_DONE); + + return result; +} + +static void nu_pdma_uart_tx_cb(void *pvOwner, uint32_t u32Events) +{ + nu_uart_t puart = (nu_uart_t)pvOwner; + + RT_ASSERT(puart != RT_NULL); + + UART_DISABLE_INT(puart->uart_base, UART_INTEN_TXPDMAEN_Msk);// Stop DMA TX transfer + + if (u32Events & NU_PDMA_EVENT_TRANSFER_DONE) + { + rt_hw_serial_isr(&puart->dev, RT_SERIAL_EVENT_TX_DMADONE); + } +} + +/** + * Uart DMA transfer + */ +static rt_size_t nu_uart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction) +{ + rt_err_t result = RT_EOK; + + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(buf != RT_NULL); + + /* Get base address of uart register */ + UART_T *uart_base = ((nu_uart_t)serial)->uart_base; + if (direction == RT_SERIAL_DMA_TX) + { + result = nu_pdma_transfer(((nu_uart_t)serial)->pdma_chanid_tx, + 8, + (uint32_t)buf, + (uint32_t)uart_base, + size, + 0); // wait-forever + UART_ENABLE_INT(uart_base, UART_INTEN_TXPDMAEN_Msk); // Start DMA TX transfer + } + else if (direction == RT_SERIAL_DMA_RX) + { + UART_DISABLE_INT(uart_base, UART_INTEN_RLSIEN_Msk); + UART_DISABLE_INT(uart_base, UART_INTEN_RXPDMAEN_Msk); + // If config.bufsz = 0, serial will trigger once. + ((nu_uart_t)serial)->rxdma_trigger_len = size; + ((nu_uart_t)serial)->rx_write_offset = 0; + result = nu_pdma_uart_rx_config(serial, buf, size); + } + else + { + result = RT_ERROR; + } + + return result; +} + +static int nu_hw_uart_dma_allocate(nu_uart_t pusrt) +{ + RT_ASSERT(pusrt != RT_NULL); + + /* Allocate UART_TX nu_dma channel */ + if (pusrt->pdma_perp_tx != NU_PDMA_UNUSED) + { + pusrt->pdma_chanid_tx = nu_pdma_channel_allocate(pusrt->pdma_perp_tx); + if (pusrt->pdma_chanid_tx >= 0) + { + pusrt->dma_flag |= RT_DEVICE_FLAG_DMA_TX; + } + } + + /* Allocate UART_RX nu_dma channel */ + if (pusrt->pdma_perp_rx != NU_PDMA_UNUSED) + { + pusrt->pdma_chanid_rx = nu_pdma_channel_allocate(pusrt->pdma_perp_rx); + if (pusrt->pdma_chanid_rx >= 0) + { + pusrt->dma_flag |= RT_DEVICE_FLAG_DMA_RX; + } + } + + return RT_EOK; +} +#endif + +/** + * Uart interrupt control + */ +static rt_err_t nu_uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + rt_err_t result = RT_EOK; + rt_uint32_t flag; + rt_ubase_t ctrl_arg = (rt_ubase_t)arg; + + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uart register */ + UART_T *uart_base = ((nu_uart_t)serial)->uart_base; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) /* Disable INT-RX */ + { + flag = UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk | UART_INTEN_TOCNTEN_Msk; + UART_DISABLE_INT(uart_base, flag); + } + else if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) /* Disable DMA-RX */ + { + /* Disable Receive Line interrupt & Stop DMA RX transfer. */ +#if defined(RT_SERIAL_USING_DMA) + nu_pdma_channel_terminate(((nu_uart_t)serial)->pdma_chanid_rx); + UART_DISABLE_INT(uart_base, UART_INTEN_RLSIEN_Msk); + UART_DISABLE_INT(uart_base, UART_INTEN_RXPDMAEN_Msk); +#endif + } + break; + + case RT_DEVICE_CTRL_SET_INT: + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) /* Enable INT-RX */ + { + flag = UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk | UART_INTEN_TOCNTEN_Msk; + UART_ENABLE_INT(uart_base, flag); + } + break; + +#if defined(RT_SERIAL_USING_DMA) + case RT_DEVICE_CTRL_CONFIG: + if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) /* Configure and trigger DMA-RX */ + { + struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + ((nu_uart_t)serial)->rxdma_trigger_len = serial->config.bufsz; + ((nu_uart_t)serial)->rx_write_offset = 0; + result = nu_pdma_uart_rx_config(serial, &rx_fifo->buffer[0], ((nu_uart_t)serial)->rxdma_trigger_len); // Config & trigger + } + else if (ctrl_arg == RT_DEVICE_FLAG_DMA_TX) /* Configure DMA-TX */ + { + result = nu_pdma_uart_tx_config(serial); + } + break; +#endif + + case RT_DEVICE_CTRL_CLOSE: + /* Disable NVIC interrupt. */ + NVIC_DisableIRQ(((nu_uart_t)serial)->uart_irq_n); + +#if defined(RT_SERIAL_USING_DMA) + nu_pdma_channel_terminate(((nu_uart_t)serial)->pdma_chanid_tx); + nu_pdma_channel_terminate(((nu_uart_t)serial)->pdma_chanid_rx); +#endif + + /* Reset this module */ + SYS_ResetModule(((nu_uart_t)serial)->uart_rst); + + /* Close UART port */ + UART_Close(uart_base); + + break; + + default: + result = -RT_EINVAL; + break; + + } + return result; +} + +/** + * Uart put char + */ +static int nu_uart_send(struct rt_serial_device *serial, char c) +{ + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uart register */ + UART_T *uart_base = ((nu_uart_t)serial)->uart_base; + + /* Waiting if TX-FIFO is full. */ + while (UART_IS_TX_FULL(uart_base)); + + /* Put char into TX-FIFO */ + UART_WRITE(uart_base, c); + + return 1; +} + +/** + * Uart get char + */ +static int nu_uart_receive(struct rt_serial_device *serial) +{ + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uart register */ + UART_T *uart_base = ((nu_uart_t)serial)->uart_base; + + /* Return failure if RX-FIFO is empty. */ + if (UART_GET_RX_EMPTY(uart_base)) + { + return -1; + } + + /* Get char from RX-FIFO */ + return UART_READ(uart_base); +} + +/** + * Hardware UART Initialization + */ +rt_err_t rt_hw_uart_init(void) +{ + int i; + rt_uint32_t flag; + rt_err_t ret = RT_EOK; + + for (i = (UART_START + 1); i < UART_CNT; i++) + { + flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX; + + nu_uart_arr[i].dev.ops = &nu_uart_ops; + nu_uart_arr[i].dev.config = nu_uart_default_config; + +#if defined(RT_SERIAL_USING_DMA) + nu_uart_arr[i].dma_flag = 0; + nu_hw_uart_dma_allocate(&nu_uart_arr[i]); + flag |= nu_uart_arr[i].dma_flag; +#endif + + ret = rt_hw_serial_register(&nu_uart_arr[i].dev, nu_uart_arr[i].name, flag, NULL); + RT_ASSERT(ret == RT_EOK); + } + + return ret; +} + +#endif //#if defined(BSP_USING_UART) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_uart.h b/bsp/nuvoton/libraries/m031/rtt_port/drv_uart.h new file mode 100644 index 0000000000..21d8714b99 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_uart.h @@ -0,0 +1,20 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-2-7 Wayne First version +* +******************************************************************************/ + +#ifndef __DRV_UART_H__ +#define __DRV_UART_H__ + +#include + +rt_err_t rt_hw_uart_init(void); + +#endif /* __DRV_UART_H__ */ diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_ui2c.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_ui2c.c new file mode 100644 index 0000000000..4f4d143784 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_ui2c.c @@ -0,0 +1,377 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-1-14 klcheng First version +* +******************************************************************************/ + +#include + +#if (defined(BSP_USING_UI2C) && defined(RT_USING_I2C)) + +#include +#include "NuMicro.h" + +/* Private define ---------------------------------------------------------------*/ +#define LOG_TAG "drv.ui2c" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include + +#define SLV_10BIT_ADDR (0x1E<<2) //1111+0xx+r/w + +/* Private typedef --------------------------------------------------------------*/ +typedef struct nu_ui2c_bus +{ + struct rt_i2c_bus_device ui2c_dev; + struct rt_i2c_msg *msg; + UI2C_T *ui2c_base; + char *dev_name; +} nu_ui2c_bus_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_size_t nu_ui2c_mst_xfer(struct rt_i2c_bus_device *ui2c_dev, + struct rt_i2c_msg msgs[], + rt_uint32_t num); + +static const struct rt_i2c_bus_device_ops nu_ui2c_ops = +{ + .master_xfer = nu_ui2c_mst_xfer, + .slave_xfer = NULL, + .i2c_bus_control = NULL, +}; + +/* Private variables ------------------------------------------------------------*/ +#ifdef BSP_USING_UI2C0 +#define UI2C0BUS_NAME "ui2c0" +static nu_ui2c_bus_t nu_ui2c0 = +{ + .ui2c_base = UI2C0, + .dev_name = UI2C0BUS_NAME, +}; +#endif /* BSP_USING_UI2C0 */ + +#ifdef BSP_USING_UI2C1 +#define UI2C1BUS_NAME "ui2c1" +static nu_ui2c_bus_t nu_ui2c1 = +{ + .ui2c_base = UI2C1, + .dev_name = UI2C1BUS_NAME, +}; +#endif /* BSP_USING_UI2C1 */ + +/* Functions define ------------------------------------------------------------*/ +#if (defined(BSP_USING_UI2C0) || defined(BSP_USING_UI2C1)) + +static inline rt_err_t nu_ui2c_wait_ready_with_timeout(nu_ui2c_bus_t *nu_ui2c) +{ + rt_tick_t start = rt_tick_get(); + while (!(UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & (UI2C_PROTSTS_STARIF_Msk | UI2C_PROTSTS_ACKIF_Msk | UI2C_PROTSTS_NACKIF_Msk | UI2C_PROTSTS_STORIF_Msk))) + { + if ((rt_tick_get() - start) > nu_ui2c->ui2c_dev.timeout) + { + LOG_E("\nui2c: timeout!\n"); + return -RT_ETIMEOUT; + } + } + + return RT_EOK; +} + +static inline rt_err_t nu_ui2c_send_data(nu_ui2c_bus_t *nu_ui2c, rt_uint8_t data) +{ + UI2C_SET_DATA(nu_ui2c->ui2c_base, data); + UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, UI2C_CTL_PTRG); + return nu_ui2c_wait_ready_with_timeout(nu_ui2c); +} + +static rt_err_t nu_ui2c_send_address(nu_ui2c_bus_t *nu_ui2c, + struct rt_i2c_msg *msg) +{ + rt_uint16_t flags = msg->flags; + rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; + rt_uint8_t addr1, addr2; + rt_err_t ret; + + if (flags & RT_I2C_ADDR_10BIT) + { + UI2C_ENABLE_10BIT_ADDR_MODE(nu_ui2c->ui2c_base); + /* Init Send 10-bit Addr */ + addr1 = ((msg->addr >> 8) | SLV_10BIT_ADDR) << 1; + addr2 = msg->addr & 0xff; + + LOG_D("addr1: %d, addr2: %d\n", addr1, addr2); + + ret = nu_ui2c_send_data(nu_ui2c, addr1); + if (ret != RT_EOK) //for timeout condition + return -RT_EIO; + + if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk) && !ignore_nack) + { + LOG_E("NACK: sending first addr\n"); + + return -RT_EIO; + } + UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk); + + ret = nu_ui2c_send_data(nu_ui2c, addr2); + if (ret != RT_EOK) //for timeout condition + return -RT_EIO; + + if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk) && !ignore_nack) + { + LOG_E("NACK: sending second addr\n"); + + return -RT_EIO; + } + UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk); + + if (flags & RT_I2C_RD) + { + LOG_D("send repeated start condition\n"); + + UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, (UI2C_CTL_PTRG | UI2C_CTL_STA)); + ret = nu_ui2c_wait_ready_with_timeout(nu_ui2c); + if (ret != RT_EOK) //for timeout condition + return -RT_EIO; + + if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_STARIF_Msk) != UI2C_PROTSTS_STARIF_Msk) && !ignore_nack) + { + LOG_E("sending repeated START fail\n"); + + return -RT_EIO; + } + UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_STARIF_Msk); + + addr1 |= RT_I2C_RD; + + ret = nu_ui2c_send_data(nu_ui2c, addr1); + if (ret != RT_EOK) //for timeout condition + return -RT_EIO; + + if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk) && !ignore_nack) + { + LOG_E("NACK: sending repeated addr\n"); + return -RT_EIO; + } + UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk); + } + } + else + { + /* 7-bit addr */ + addr1 = msg->addr << 1; + if (flags & RT_I2C_RD) + addr1 |= RT_I2C_RD; + + /* Send device address */ + ret = nu_ui2c_send_data(nu_ui2c, addr1); /* Send Address */ + if (ret != RT_EOK) //for timeout condition + return -RT_EIO; + + if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk) + && !ignore_nack) + { + LOG_E("sending addr fail\n"); + return -RT_EIO; + } + UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk); + } + + return RT_EOK; +} + +static rt_size_t nu_ui2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + struct rt_i2c_msg *msg; + nu_ui2c_bus_t *nu_ui2c; + rt_size_t i; + rt_uint32_t cnt_data; + rt_uint16_t ignore_nack; + rt_err_t ret; + + RT_ASSERT(bus != RT_NULL); + nu_ui2c = (nu_ui2c_bus_t *) bus; + + nu_ui2c->msg = msgs; + + (nu_ui2c->ui2c_base)->PROTSTS = (nu_ui2c->ui2c_base)->PROTSTS;//Clear status + + UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, UI2C_CTL_STA); + ret = nu_ui2c_wait_ready_with_timeout(nu_ui2c); + + if (ret != RT_EOK) //for timeout condition + { + rt_set_errno(-RT_ETIMEOUT); + return 0; + } + + if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_STARIF_Msk) != UI2C_PROTSTS_STARIF_Msk)) /* Check Send START */ + { + i = 0; + LOG_E("Send START Fail"); + return i; + } + UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_STARIF_Msk); + + for (i = 0; i < num; i++) + { + msg = &msgs[i]; + ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; + + if (!(msg->flags & RT_I2C_NO_START)) + { + if (i) + { + UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, (UI2C_CTL_PTRG | UI2C_CTL_STA));/* Send repeat START */ + ret = nu_ui2c_wait_ready_with_timeout(nu_ui2c); + if (ret != RT_EOK) //for timeout condition + break; + + if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_STARIF_Msk) != UI2C_PROTSTS_STARIF_Msk)) /* Check Send repeat START */ + { + i = 0; + LOG_E("Send repeat START Fail"); + break; + } + UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_STARIF_Msk); + } + + if ((RT_EOK != nu_ui2c_send_address(nu_ui2c, msg)) + && !ignore_nack) + { + i = 0; + LOG_E("Send Address Fail"); + break; + } + } + + if (nu_ui2c->msg[i].flags & RT_I2C_RD) /* Receive Bytes */ + { + rt_uint32_t do_rd_nack = (i == (num - 1)); + for (cnt_data = 0 ; cnt_data < (nu_ui2c->msg[i].len) ; cnt_data++) + { + do_rd_nack += (cnt_data == (nu_ui2c->msg[i].len - 1)); /* NACK after last byte for hardware setting */ + if (do_rd_nack == 2) + { + UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, UI2C_CTL_PTRG); + } + else + { + UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, (UI2C_CTL_PTRG | UI2C_CTL_AA)); + } + + ret = nu_ui2c_wait_ready_with_timeout(nu_ui2c); + if (ret != RT_EOK) //for timeout condition + break; + + if (nu_ui2c->ui2c_base->PROTCTL & UI2C_CTL_AA) + { + if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk)) /*Master Receive Data ACK*/ + { + i = 0; + break; + } + UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk); + } + else + { + if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_NACKIF_Msk) != UI2C_PROTSTS_NACKIF_Msk)) /*Master Receive Data NACK*/ + { + i = 0; + break; + } + UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_NACKIF_Msk); + } + + nu_ui2c->msg[i].buf[cnt_data] = nu_ui2c->ui2c_base->RXDAT; + } + } + else /* Send Bytes */ + { + for (cnt_data = 0 ; cnt_data < (nu_ui2c->msg[i].len) ; cnt_data++) + { + /* Send register number and MSB of data */ + ret = nu_ui2c_send_data(nu_ui2c, (uint8_t)(nu_ui2c->msg[i].buf[cnt_data])); + if (ret != RT_EOK) //for timeout condition + break; + + if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_ACKIF_Msk) != UI2C_PROTSTS_ACKIF_Msk) + && !ignore_nack + ) /* Send data and get Ack */ + { + i = 0; + break; + } + UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_ACKIF_Msk); + } + } + } + + UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, (UI2C_CTL_PTRG | UI2C_CTL_STO)); /* Send STOP signal */ + ret = nu_ui2c_wait_ready_with_timeout(nu_ui2c); + if (ret != RT_EOK) //for timeout condition + { + rt_set_errno(-RT_ETIMEOUT); + return 0; + } + + RT_ASSERT(((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_STORIF_Msk) == UI2C_PROTSTS_STORIF_Msk)); + if (((UI2C_GET_PROT_STATUS(nu_ui2c->ui2c_base) & UI2C_PROTSTS_STORIF_Msk) != UI2C_PROTSTS_STORIF_Msk)) /* Bus Free*/ + { + i = 0; + LOG_E("Send STOP Fail"); + } + + UI2C_CLR_PROT_INT_FLAG(nu_ui2c->ui2c_base, UI2C_PROTSTS_STORIF_Msk); + UI2C_SET_CONTROL_REG(nu_ui2c->ui2c_base, UI2C_CTL_PTRG); + UI2C_DISABLE_10BIT_ADDR_MODE(nu_ui2c->ui2c_base); /*clear all sub modes like 10 bit mode*/ + nu_ui2c->msg = RT_NULL; + + return i; +} + +#endif //(defined(BSP_USING_UI2C0) || defined(BSP_USING_UI2C1)) + +/* Public functions -------------------------------------------------------------*/ +int rt_hw_ui2c_init(void) +{ + rt_err_t ret = RT_ERROR; + +#if defined(BSP_USING_UI2C0) + SYS_UnlockReg(); + SYS_ResetModule(USCI0_RST); + SYS_LockReg(); + + nu_ui2c0.ui2c_dev.ops = &nu_ui2c_ops; + UI2C_Open(nu_ui2c0.ui2c_base, 100000); + ret = rt_i2c_bus_device_register(&nu_ui2c0.ui2c_dev, nu_ui2c0.dev_name); + RT_ASSERT(RT_EOK == ret); +#endif /* BSP_USING_UI2C0 */ + +#if defined(BSP_USING_UI2C1) + SYS_UnlockReg(); + SYS_ResetModule(USCI1_RST); + SYS_LockReg(); + + nu_ui2c1.ui2c_dev.ops = &nu_ui2c_ops; + UI2C_Open(nu_ui2c1.ui2c_base, 100000); + ret = rt_i2c_bus_device_register(&nu_ui2c1.ui2c_dev, nu_ui2c1.dev_name); + RT_ASSERT(RT_EOK == ret); +#endif /* BSP_USING_UI2C1 */ + + return ret; +} + +INIT_DEVICE_EXPORT(rt_hw_ui2c_init); + +#endif //#if defined(BSP_USING_UI2C) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_usbd.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_usbd.c new file mode 100644 index 0000000000..9cbb7dba12 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_usbd.c @@ -0,0 +1,502 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-02-24 klcheng First version +* +******************************************************************************/ + +#include + +#ifdef BSP_USING_USBD +#include +#include +#include +#include "NuMicro.h" + +#define LOG_TAG "drv.usbd" +#define DBG_ENABLE +#define DBG_SECTION_NAME "drv.usbd" +#define DBG_LEVEL DBG_ERROR +#define DBG_COLOR +#include + +/* Private define ---------------------------------------------------------------*/ +/* Define EP maximum packet size */ +#define EP0_MAX_PKT_SIZE 64 +#define EP1_MAX_PKT_SIZE EP0_MAX_PKT_SIZE /* EP0 and EP1 are assigned the same size for control endpoint */ +#define EP2_MAX_PKT_SIZE 64 +#define EP3_MAX_PKT_SIZE 64 +#define EP4_MAX_PKT_SIZE 64 +#define EP5_MAX_PKT_SIZE 64 +#define EP6_MAX_PKT_SIZE 64 +#define EP7_MAX_PKT_SIZE 64 + +#define SETUP_BUF_BASE 0 +#define SETUP_BUF_LEN 8 +#define EP0_BUF_BASE (SETUP_BUF_BASE + SETUP_BUF_LEN) +#define EP0_BUF_LEN EP0_MAX_PKT_SIZE + +#define EP1_BUF_BASE (SETUP_BUF_BASE + SETUP_BUF_LEN) +#define EP1_BUF_LEN EP1_MAX_PKT_SIZE +#define EP2_BUF_BASE (EP1_BUF_BASE + EP1_BUF_LEN) +#define EP2_BUF_LEN EP2_MAX_PKT_SIZE +#define EP3_BUF_BASE (EP2_BUF_BASE + EP2_BUF_LEN) +#define EP3_BUF_LEN EP3_MAX_PKT_SIZE +#define EP4_BUF_BASE (EP3_BUF_BASE + EP3_BUF_LEN) +#define EP4_BUF_LEN EP4_MAX_PKT_SIZE +#define EP5_BUF_BASE (EP4_BUF_BASE + EP4_BUF_LEN) +#define EP5_BUF_LEN EP5_MAX_PKT_SIZE +#define EP6_BUF_BASE (EP5_BUF_BASE + EP5_BUF_LEN) +#define EP6_BUF_LEN EP6_MAX_PKT_SIZE +#define EP7_BUF_BASE (EP6_BUF_BASE + EP6_BUF_LEN) +#define EP7_BUF_LEN EP7_MAX_PKT_SIZE + +#define EPADR_SW2HW(address) ((((address & USB_EPNO_MASK) * 2) + (!(address & USB_DIR_IN)))) +#define EPADR_HW2SW(address) ((address & USB_EPNO_MASK) / 2) +/* Private typedef --------------------------------------------------------------*/ +typedef struct _nu_usbd_t +{ + USBD_T *Instance; /* REG base */ + uint8_t address_tmp; /* Keep assigned address for flow control */ +} nu_usbd_t; + + +/* Private variables ------------------------------------------------------------*/ +static nu_usbd_t nu_usbd = +{ + .Instance = USBD, + .address_tmp = 0, +}; + +static struct udcd _rt_obj_udc; + +static struct ep_id _ep_pool[] = +{ + {EPADR_HW2SW(EP0), USB_EP_ATTR_CONTROL, USB_DIR_INOUT, EP0_MAX_PKT_SIZE, ID_ASSIGNED }, + {EPADR_HW2SW(EP2), USB_EP_ATTR_BULK, USB_DIR_IN, EP2_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EP3), USB_EP_ATTR_BULK, USB_DIR_OUT, EP3_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EP4), USB_EP_ATTR_INT, USB_DIR_IN, EP4_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EP5), USB_EP_ATTR_INT, USB_DIR_OUT, EP5_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EP6), USB_EP_ATTR_BULK, USB_DIR_IN, EP6_MAX_PKT_SIZE, ID_UNASSIGNED}, + {EPADR_HW2SW(EP7), USB_EP_ATTR_BULK, USB_DIR_OUT, EP7_MAX_PKT_SIZE, ID_UNASSIGNED}, + {0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED }, +}; + +static void _nu_ep_partition(void) +{ + /* Init setup packet buffer */ + /* Buffer range for setup packet -> [0 ~ 0x7] */ + USBD->STBUFSEG = SETUP_BUF_BASE; + + /*****************************************************/ + /* EP0 ==> control IN endpoint, address 0 */ + USBD_CONFIG_EP(EP0, USBD_CFG_CSTALL | USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP0)); + /* Buffer range for EP0 */ + USBD_SET_EP_BUF_ADDR(EP0, EP0_BUF_BASE); + + /* EP1 ==> control OUT endpoint, address 0 */ + USBD_CONFIG_EP(EP1, USBD_CFG_CSTALL | USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP1)); + /* Buffer range for EP1 */ + USBD_SET_EP_BUF_ADDR(EP1, EP1_BUF_BASE); + + /*****************************************************/ + /* EP2 ==> Bulk IN endpoint, address 1 */ + USBD_CONFIG_EP(EP2, USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP2)); + /* Buffer range for EP2 */ + USBD_SET_EP_BUF_ADDR(EP2, EP2_BUF_BASE); + + /* EP3 ==> Bulk OUT endpoint, address 1 */ + USBD_CONFIG_EP(EP3, USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP3)); + /* Buffer range for EP3 */ + USBD_SET_EP_BUF_ADDR(EP3, EP3_BUF_BASE); + + /*****************************************************/ + /* EP4 ==> Interrupt IN endpoint, address 2 */ + USBD_CONFIG_EP(EP4, USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP4)); + /* Buffer range for EP4 */ + USBD_SET_EP_BUF_ADDR(EP4, EP4_BUF_BASE); + + /* EP5 ==> Interrupt Out endpoint, address 2 */ + USBD_CONFIG_EP(EP5, USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP5)); + /* Buffer range for EP5 */ + USBD_SET_EP_BUF_ADDR(EP5, EP5_BUF_BASE); + + /*****************************************************/ + /* EP6 ==> Bulk IN endpoint, address 3 */ + USBD_CONFIG_EP(EP6, USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP6)); + /* Buffer range for EP4 */ + USBD_SET_EP_BUF_ADDR(EP6, EP6_BUF_BASE); + + /* EP7 ==> Bulk Out endpoint, address 3 */ + USBD_CONFIG_EP(EP7, USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP7)); + /* Buffer range for EP5 */ + USBD_SET_EP_BUF_ADDR(EP7, EP7_BUF_BASE); + +} + +static rt_err_t _ep_set_stall(rt_uint8_t address) +{ + USBD_SET_EP_STALL(EPADR_SW2HW(address)); + return RT_EOK; +} + +static rt_err_t _ep_clear_stall(rt_uint8_t address) +{ + USBD_ClearStall(EPADR_SW2HW(address)); + + return RT_EOK; +} + + +static rt_err_t _set_address(rt_uint8_t address) +{ + if (0 != address) + { + nu_usbd.address_tmp = address; + } + + return RT_EOK; +} + +static rt_err_t _set_config(rt_uint8_t address) +{ + return RT_EOK; +} + +static rt_err_t _ep_enable(uep_t ep) +{ + RT_ASSERT(ep != RT_NULL); + RT_ASSERT(ep->ep_desc != RT_NULL); + + USBD_CONFIG_EP(EPADR_SW2HW(EP_ADDRESS(ep)), + USBD_CFG_CSTALL + | ((EP_ADDRESS(ep) & USB_DIR_IN) ? USBD_CFG_EPMODE_IN : USBD_CFG_EPMODE_OUT) + | (EP_ADDRESS(ep) & USB_EPNO_MASK)); + + return RT_EOK; +} + +static rt_err_t _ep_disable(uep_t ep) +{ + RT_ASSERT(ep != RT_NULL); + RT_ASSERT(ep->ep_desc != RT_NULL); + + USBD_CONFIG_EP(EPADR_SW2HW(EP_ADDRESS(ep)), USBD_CFG_EPMODE_DISABLE); + + return RT_EOK; +} + +static rt_size_t _ep_read(rt_uint8_t address, void *buffer) +{ + rt_size_t size = 0; + rt_uint8_t *buf; + rt_uint32_t hw_ep_num = EPADR_SW2HW(address); + + RT_ASSERT(!(address & USB_DIR_IN)); + RT_ASSERT(buffer != RT_NULL); + + size = USBD_GET_PAYLOAD_LEN(hw_ep_num); + buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(hw_ep_num)); + USBD_MemCopy(buffer, (uint8_t *)buf, size); + + return size; +} + +static rt_size_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size) +{ + RT_ASSERT(!(address & USB_DIR_IN)); + + USBD_SET_PAYLOAD_LEN(EPADR_SW2HW(address), size); + + return size; +} + +static rt_size_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size) +{ + RT_ASSERT((address & USB_DIR_IN)); + + /* even number is for IN endpoint */ + rt_uint32_t hw_ep_num = EPADR_SW2HW(address); + uint8_t *buf; + buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(hw_ep_num)); + + USBD_MemCopy(buf, (uint8_t *)buffer, size); + + USBD_SET_PAYLOAD_LEN(hw_ep_num, size); + + return size; +} + +static rt_err_t _ep0_send_status(void) +{ + /* Status stage */ + USBD_SET_DATA1(EP0); + USBD_SET_PAYLOAD_LEN(EP0, 0); + return RT_EOK; +} + +static rt_err_t _suspend(void) +{ + return RT_EOK; +} + +static rt_err_t _wakeup(void) +{ + return RT_EOK; +} + +__STATIC_INLINE void _USBD_IRQHandler(void) +{ + rt_uint32_t u32IntSts = USBD_GET_INT_FLAG(); + rt_uint32_t u32State = USBD_GET_BUS_STATE(); + +//------------------------------------------------------------------ + if (u32IntSts & USBD_INTSTS_VBDETIF_Msk) + { + // Floating detect + USBD_CLR_INT_FLAG(USBD_INTSTS_VBDETIF_Msk); + + if (USBD_IS_ATTACHED()) + { + /* USB Plug In */ + USBD_ENABLE_USB(); + rt_usbd_connect_handler(&_rt_obj_udc); + } + else + { + /* USB Unplug */ + USBD_DISABLE_USB(); + rt_usbd_disconnect_handler(&_rt_obj_udc); + } + } + + if (u32IntSts & USBD_INTSTS_SOFIF_Msk) + { + USBD_CLR_INT_FLAG(USBD_INTSTS_SOFIF_Msk); + rt_usbd_sof_handler(&_rt_obj_udc); + } +//------------------------------------------------------------------ + if (u32IntSts & USBD_INTSTS_BUSIF_Msk) + { + /* Clear event flag */ + USBD_CLR_INT_FLAG(USBD_INTSTS_BUSIF_Msk); + + if (u32State & USBD_ATTR_USBRST_Msk) + { + USBD_ENABLE_USB(); + + /* Reset PID DATA0 */ + for (rt_uint32_t i = 0ul; i < USBD_MAX_EP; i++) + { + nu_usbd.Instance->EP[i].CFG &= ~USBD_CFG_DSQSYNC_Msk; + } + + /* Reset USB device address */ + USBD_SET_ADDR(0ul); + + /* Bus reset */ + rt_usbd_reset_handler(&_rt_obj_udc); + } + if (u32State & USBD_ATTR_SUSPEND_Msk) + { + /* Enable USB but disable PHY */ + USBD_DISABLE_PHY(); + } + if (u32State & USBD_ATTR_RESUME_Msk) + { + /* Enable USB and enable PHY */ + USBD_ENABLE_USB(); + } + } + +//------------------------------------------------------------------ + if (u32IntSts & USBD_INTSTS_WAKEUP) + { + /* Clear event flag */ + USBD_CLR_INT_FLAG(USBD_INTSTS_WAKEUP); + USBD_ENABLE_USB(); + } + + if (u32IntSts & USBD_INTSTS_USBIF_Msk) + { + // USB event + if (u32IntSts & USBD_INTSTS_SETUP_Msk) + { + // Setup packet + /* Clear event flag */ + USBD_CLR_INT_FLAG(USBD_INTSTS_SETUP_Msk); + + /* Clear the data IN/OUT ready flag of control end-points */ + USBD_STOP_TRANSACTION(EP0); + USBD_STOP_TRANSACTION(EP1); + + USBD_SET_DATA1(EP0); + rt_usbd_ep0_setup_handler(&_rt_obj_udc, (struct urequest *)USBD_BUF_BASE); + } + + // EP events + if (u32IntSts & USBD_INTSTS_EP0) + { + /* Clear event flag */ + USBD_CLR_INT_FLAG(USBD_INTSTS_EP0); + + if ((USBD_GET_ADDR() == 0) + && (nu_usbd.address_tmp) + ) + { + USBD_SET_ADDR(nu_usbd.address_tmp); + LOG_I("SET ADDR: 0x%02x", nu_usbd.address_tmp); + nu_usbd.address_tmp = 0; + } + + rt_usbd_ep0_in_handler(&_rt_obj_udc); + } + + if (u32IntSts & USBD_INTSTS_EP1) + { + /* Clear event flag */ + USBD_CLR_INT_FLAG(USBD_INTSTS_EP1); + rt_usbd_ep0_out_handler(&_rt_obj_udc, 0); + } + + if (u32IntSts & USBD_INTSTS_EP2) + { + /* Clear event flag */ + USBD_CLR_INT_FLAG(USBD_INTSTS_EP2); + rt_usbd_ep_in_handler(&_rt_obj_udc, USB_DIR_IN | EPADR_HW2SW(EP2), 0); + } + + if (u32IntSts & USBD_INTSTS_EP3) + { + /* Clear event flag */ + USBD_CLR_INT_FLAG(USBD_INTSTS_EP3); + rt_usbd_ep_out_handler(&_rt_obj_udc, USB_DIR_OUT | EPADR_HW2SW(EP3), 0); + } + + if (u32IntSts & USBD_INTSTS_EP4) + { + /* Clear event flag */ + USBD_CLR_INT_FLAG(USBD_INTSTS_EP4); + rt_usbd_ep_in_handler(&_rt_obj_udc, USB_DIR_IN | EPADR_HW2SW(EP4), 0); + } + + if (u32IntSts & USBD_INTSTS_EP5) + { + /* Clear event flag */ + USBD_CLR_INT_FLAG(USBD_INTSTS_EP5); + rt_usbd_ep_out_handler(&_rt_obj_udc, USB_DIR_OUT | EPADR_HW2SW(EP5), 0); + } + + if (u32IntSts & USBD_INTSTS_EP6) + { + /* Clear event flag */ + USBD_CLR_INT_FLAG(USBD_INTSTS_EP6); + rt_usbd_ep_in_handler(&_rt_obj_udc, USB_DIR_IN | EPADR_HW2SW(EP6), 0); + } + + if (u32IntSts & USBD_INTSTS_EP7) + { + /* Clear event flag */ + USBD_CLR_INT_FLAG(USBD_INTSTS_EP7); + rt_usbd_ep_out_handler(&_rt_obj_udc, USB_DIR_OUT | EPADR_HW2SW(EP7), 0); + } + } +} + +void USBD_IRQHandler(void) +{ + rt_interrupt_enter(); + + _USBD_IRQHandler(); + + rt_interrupt_leave(); +} + +static rt_err_t _init(rt_device_t device) +{ + nu_usbd_t *nu_usbd = (nu_usbd_t *)device->user_data; + + /* Initialize USB PHY */ + SYS_UnlockReg(); + /* Select USBD */ + SYS_ResetModule(USBD_RST); + SYS_LockReg(); + + _nu_ep_partition(); + + /* Initial USB engine */ + nu_usbd->Instance->ATTR = 0x6D0ul; + + /* Force SE0 */ + USBD_SET_SE0(); + + NVIC_EnableIRQ(USBD_IRQn); + + USBD_Start(); + return RT_EOK; +} + +const static struct udcd_ops _udc_ops = +{ + _set_address, + _set_config, + _ep_set_stall, + _ep_clear_stall, + _ep_enable, + _ep_disable, + _ep_read_prepare, + _ep_read, + _ep_write, + _ep0_send_status, + _suspend, + _wakeup, +}; + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops _ops = +{ + _init, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, +}; +#endif + +int nu_usbd_register(void) +{ + if (RT_NULL != rt_device_find("usbd")) + { + LOG_E("\nUSBD Register failed. Another USBD device registered\n"); + return -RT_ERROR; + } + + rt_memset((void *)&_rt_obj_udc, 0, sizeof(struct udcd)); + _rt_obj_udc.parent.type = RT_Device_Class_USBDevice; + +#ifdef RT_USING_DEVICE_OPS + _rt_obj_udc.parent.ops = &_ops; +#else + _rt_obj_udc.parent.init = _init; +#endif + + _rt_obj_udc.parent.user_data = &nu_usbd; + _rt_obj_udc.ops = &_udc_ops; + /* Register endpoint information */ + _rt_obj_udc.ep_pool = _ep_pool; + _rt_obj_udc.ep0.id = &_ep_pool[0]; + + _rt_obj_udc.device_is_hs = RT_FALSE; /* Support Full-Speed only */ + + rt_device_register((rt_device_t)&_rt_obj_udc, "usbd", 0); + rt_usb_device_init(); + return RT_EOK; +} +INIT_DEVICE_EXPORT(nu_usbd_register); +#endif diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_uspi.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_uspi.c new file mode 100644 index 0000000000..27859c74b4 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_uspi.c @@ -0,0 +1,607 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-01-20 klcheng First version +* +******************************************************************************/ +#include + +#if defined(BSP_USING_USPI) + +#define LOG_TAG "drv.uspi" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include + +#include +#include +#include + +#include "NuMicro.h" +#include + +#if defined(BSP_USING_USPI_PDMA) + #include +#endif +/* Private define ---------------------------------------------------------------*/ +enum +{ + USPI_START = -1, +#if defined(BSP_USING_USPI0) + USPI0_IDX, +#endif +#if defined(BSP_USING_USPI1) + USPI1_IDX, +#endif + USPI_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ +struct nu_uspi +{ + struct rt_spi_bus dev; + char *name; + USPI_T *uspi_base; + struct rt_spi_configuration configuration; + uint32_t dummy; +#if defined(BSP_USING_USPI_PDMA) + int16_t pdma_perp_tx; + int8_t pdma_chanid_tx; + int16_t pdma_perp_rx; + int8_t pdma_chanid_rx; + rt_sem_t m_psSemBus; +#endif +}; +typedef struct nu_uspi *uspi_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_uspi_bus_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration); +static rt_uint32_t nu_uspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message); +static void nu_uspi_transmission_with_poll(struct nu_uspi *uspi_bus, + uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word); +static int nu_uspi_register_bus(struct nu_uspi *uspi_bus, const char *name); +static void nu_uspi_drain_rxfifo(USPI_T *uspi_base); + +#if defined(BSP_USING_USPI_PDMA) + static void nu_pdma_uspi_rx_cb(void *pvUserData, uint32_t u32EventFilter); + static rt_err_t nu_pdma_uspi_rx_config(struct nu_uspi *uspi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word); + static rt_err_t nu_pdma_uspi_tx_config(struct nu_uspi *uspi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word); + static rt_size_t nu_uspi_pdma_transmit(struct nu_uspi *uspi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word); + static rt_err_t nu_hw_uspi_pdma_allocate(struct nu_uspi *uspi_bus); +#endif +/* Public functions -------------------------------------------------------------*/ + + +/* Private variables ------------------------------------------------------------*/ +static struct rt_spi_ops nu_uspi_poll_ops = +{ + .configure = nu_uspi_bus_configure, + .xfer = nu_uspi_bus_xfer, +}; + +static struct nu_uspi nu_uspi_arr [] = +{ +#if defined(BSP_USING_USPI0) + { + .name = "uspi0", + .uspi_base = USPI0, + +#if defined(BSP_USING_USPI_PDMA) +#if defined(BSP_USING_USPI0_PDMA) + .pdma_perp_tx = PDMA_USCI0_TX, + .pdma_perp_rx = PDMA_USCI0_RX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif //BSP_USING_USPI0_PDMA +#endif //BSP_USING_USPI_PDMA + }, +#endif +#if defined(BSP_USING_USPI1) + { + .name = "uspi1", + .uspi_base = USPI1, + +#if defined(BSP_USING_USPI_PDMA) +#if defined(BSP_USING_USPI1_PDMA) + .pdma_perp_tx = PDMA_USCI1_TX, + .pdma_perp_rx = PDMA_USCI1_RX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif //BSP_USING_USPI1_PDMA +#endif //BSP_USING_USPI_PDMA + + }, +#endif + {0} +}; /* uspi nu_uspi */ + +static rt_err_t nu_uspi_bus_configure(struct rt_spi_device *device, + struct rt_spi_configuration *configuration) +{ + struct nu_uspi *uspi_bus; + uint32_t u32SPIMode; + uint32_t u32BusClock; + rt_err_t ret = RT_EOK; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + uspi_bus = (struct nu_uspi *) device->bus; + + /* Check mode */ + switch (configuration->mode & RT_SPI_MODE_3) + { + case RT_SPI_MODE_0: + u32SPIMode = USPI_MODE_0; + break; + case RT_SPI_MODE_1: + u32SPIMode = USPI_MODE_1; + break; + case RT_SPI_MODE_2: + u32SPIMode = USPI_MODE_2; + break; + case RT_SPI_MODE_3: + u32SPIMode = USPI_MODE_3; + break; + default: + ret = RT_EIO; + goto exit_nu_uspi_bus_configure; + } + + /* Check data width */ + if (!(configuration->data_width == 8 || + configuration->data_width == 16)) + { + ret = RT_EINVAL; + goto exit_nu_uspi_bus_configure; + } + + /* Try to set clock and get actual uspi bus clock */ + u32BusClock = USPI_SetBusClock(uspi_bus->uspi_base, configuration->max_hz); + if (configuration->max_hz > u32BusClock) + { + LOG_W("%s clock max frequency is %dHz (!= %dHz)\n", uspi_bus->name, u32BusClock, configuration->max_hz); + configuration->max_hz = u32BusClock; + } + + /* Need to initialize new configuration? */ + if (rt_memcmp(configuration, &uspi_bus->configuration, sizeof(*configuration)) != 0) + { + rt_memcpy(&uspi_bus->configuration, configuration, sizeof(*configuration)); + + USPI_Open(uspi_bus->uspi_base, USPI_MASTER, u32SPIMode, configuration->data_width, u32BusClock); + + if (configuration->mode & RT_SPI_CS_HIGH) + { + /* Set CS pin to LOW */ + USPI_SET_SS_LOW(uspi_bus->uspi_base); + } + else + { + /* Set CS pin to HIGH */ + USPI_SET_SS_HIGH(uspi_bus->uspi_base); + } + + if (configuration->mode & RT_SPI_MSB) + { + /* Set sequence to MSB first */ + USPI_SET_MSB_FIRST(uspi_bus->uspi_base); + } + else + { + /* Set sequence to LSB first */ + USPI_SET_LSB_FIRST(uspi_bus->uspi_base); + } + } + + /* Clear USPI RX FIFO */ + nu_uspi_drain_rxfifo(uspi_bus->uspi_base); + +exit_nu_uspi_bus_configure: + + return -(ret); +} + +#if defined(BSP_USING_USPI_PDMA) +static void nu_pdma_uspi_rx_cb(void *pvUserData, uint32_t u32EventFilter) +{ + rt_err_t result; + struct nu_uspi *uspi_bus = (struct nu_uspi *)pvUserData; + + RT_ASSERT(uspi_bus != RT_NULL); + + result = rt_sem_release(uspi_bus->m_psSemBus); + RT_ASSERT(result == RT_EOK); +} + +static rt_err_t nu_pdma_uspi_rx_config(struct nu_uspi *uspi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word) +{ + rt_err_t result; + rt_uint8_t *dst_addr = NULL; + nu_pdma_memctrl_t memctrl = eMemCtl_Undefined; + + /* Get base address of uspi register */ + USPI_T *uspi_base = uspi_bus->uspi_base; + + rt_uint8_t uspi_pdma_rx_chid = uspi_bus->pdma_chanid_rx; + + result = nu_pdma_callback_register(uspi_pdma_rx_chid, + nu_pdma_uspi_rx_cb, + (void *)uspi_bus, + NU_PDMA_EVENT_TRANSFER_DONE); + if (result != RT_EOK) + { + goto exit_nu_pdma_uspi_rx_config; + } + + if (pu8Buf == RT_NULL) + { + memctrl = eMemCtl_SrcFix_DstFix; + dst_addr = (rt_uint8_t *) &uspi_bus->dummy; + } + else + { + memctrl = eMemCtl_SrcFix_DstInc; + dst_addr = pu8Buf; + } + + result = nu_pdma_channel_memctrl_set(uspi_pdma_rx_chid, memctrl); + if (result != RT_EOK) + { + goto exit_nu_pdma_uspi_rx_config; + } + + result = nu_pdma_transfer(uspi_pdma_rx_chid, + bytes_per_word * 8, + (uint32_t)&uspi_base->RXDAT, + (uint32_t)dst_addr, + i32RcvLen / bytes_per_word, + 0); + +exit_nu_pdma_uspi_rx_config: + + return result; +} + +static rt_err_t nu_pdma_uspi_tx_config(struct nu_uspi *uspi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word) +{ + rt_err_t result; + rt_uint8_t *src_addr = NULL; + nu_pdma_memctrl_t memctrl = eMemCtl_Undefined; + + /* Get base address of uspi register */ + USPI_T *uspi_base = uspi_bus->uspi_base; + + rt_uint8_t uspi_pdma_tx_chid = uspi_bus->pdma_chanid_tx; + + if (pu8Buf == RT_NULL) + { + uspi_bus->dummy = 0; + memctrl = eMemCtl_SrcFix_DstFix; + src_addr = (rt_uint8_t *)&uspi_bus->dummy; + } + else + { + memctrl = eMemCtl_SrcInc_DstFix; + src_addr = (rt_uint8_t *)pu8Buf; + } + + result = nu_pdma_channel_memctrl_set(uspi_pdma_tx_chid, memctrl); + if (result != RT_EOK) + { + goto exit_nu_pdma_uspi_tx_config; + } + + result = nu_pdma_transfer(uspi_pdma_tx_chid, + bytes_per_word * 8, + (uint32_t)src_addr, + (uint32_t)&uspi_base->TXDAT, + i32SndLen / bytes_per_word, + 0); + +exit_nu_pdma_uspi_tx_config: + + return result; +} + + +/** + * USPI PDMA transfer + **/ +static rt_size_t nu_uspi_pdma_transmit(struct nu_uspi *uspi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word) +{ + rt_err_t result; + + /* Get base address of uspi register */ + USPI_T *uspi_base = uspi_bus->uspi_base; + + result = nu_pdma_uspi_rx_config(uspi_bus, recv_addr, length, bytes_per_word); + RT_ASSERT(result == RT_EOK); + result = nu_pdma_uspi_tx_config(uspi_bus, send_addr, length, bytes_per_word); + RT_ASSERT(result == RT_EOK); + + /* Trigger TX/RX at the same time. */ + USPI_TRIGGER_TX_RX_PDMA(uspi_base); + + /* Wait PDMA transfer done */ + result = rt_sem_take(uspi_bus->m_psSemBus, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + /* Stop DMA TX/RX transfer */ + USPI_DISABLE_TX_RX_PDMA(uspi_base); + + return result; +} + +static rt_err_t nu_hw_uspi_pdma_allocate(struct nu_uspi *uspi_bus) +{ + /* Allocate USPI_TX nu_dma channel */ + if ((uspi_bus->pdma_chanid_tx = nu_pdma_channel_allocate(uspi_bus->pdma_perp_tx)) < 0) + { + goto exit_nu_hw_uspi_pdma_allocate; + } + /* Allocate USPI_RX nu_dma channel */ + else if ((uspi_bus->pdma_chanid_rx = nu_pdma_channel_allocate(uspi_bus->pdma_perp_rx)) < 0) + { + nu_pdma_channel_free(uspi_bus->pdma_chanid_tx); + goto exit_nu_hw_uspi_pdma_allocate; + } + + uspi_bus->m_psSemBus = rt_sem_create("uspibus_sem", 0, RT_IPC_FLAG_FIFO); + RT_ASSERT(uspi_bus->m_psSemBus != RT_NULL); + + return RT_EOK; + +exit_nu_hw_uspi_pdma_allocate: + + return -(RT_ERROR); +} + +#endif + +static void nu_uspi_drain_rxfifo(USPI_T *uspi_base) +{ + while (USPI_IS_BUSY(uspi_base)); + + // Drain USPI RX FIFO, make sure RX FIFO is empty + while (!USPI_GET_RX_EMPTY_FLAG(uspi_base)) + { + USPI_ClearRxBuf(uspi_base); + } +} + +static int nu_uspi_read(USPI_T *uspi_base, uint8_t *recv_addr, uint8_t bytes_per_word) +{ + int size = 0; + + // Read RX data + if (!USPI_GET_RX_EMPTY_FLAG(uspi_base)) + { + uint32_t val; + // Read data from USPI RX FIFO + switch (bytes_per_word) + { + case 2: + val = USPI_READ_RX(uspi_base); + nu_set16_le(recv_addr, val); + break; + case 1: + *recv_addr = USPI_READ_RX(uspi_base); + break; + default: + LOG_E("Data length is not supported.\n"); + break; + } + size = bytes_per_word; + } + return size; +} + +static int nu_uspi_write(USPI_T *uspi_base, const uint8_t *send_addr, uint8_t bytes_per_word) +{ + // Wait USPI TX send data + while (USPI_GET_TX_FULL_FLAG(uspi_base)); + + // Input data to USPI TX + switch (bytes_per_word) + { + case 2: + USPI_WRITE_TX(uspi_base, nu_get16_le(send_addr)); + break; + case 1: + USPI_WRITE_TX(uspi_base, *((uint8_t *)send_addr)); + break; + default: + LOG_E("Data length is not supported.\n"); + break; + } + + return bytes_per_word; +} + +/** + * @brief USPI bus polling + * @param dev : The pointer of the specified USPI module. + * @param send_addr : Source address + * @param recv_addr : Destination address + * @param length : Data length + */ +static void nu_uspi_transmission_with_poll(struct nu_uspi *uspi_bus, + uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word) +{ + USPI_T *uspi_base = uspi_bus->uspi_base; + + // Write-only + if ((send_addr != RT_NULL) && (recv_addr == RT_NULL)) + { + while (length > 0) + { + send_addr += nu_uspi_write(uspi_base, send_addr, bytes_per_word); + length -= bytes_per_word; + } + } // if (send_addr != RT_NULL && recv_addr == RT_NULL) + // Read-only + else if ((send_addr == RT_NULL) && (recv_addr != RT_NULL)) + { + uspi_bus->dummy = 0; + while (length > 0) + { + /* Input data to USPI TX FIFO */ + length -= nu_uspi_write(uspi_base, (const uint8_t *)&uspi_bus->dummy, bytes_per_word); + + /* Read data from USPI RX FIFO */ + while (USPI_GET_RX_EMPTY_FLAG(uspi_base)); + recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word); + } + } // else if (send_addr == RT_NULL && recv_addr != RT_NULL) + // Read&Write + else + { + while (length > 0) + { + /* Input data to USPI TX FIFO */ + send_addr += nu_uspi_write(uspi_base, send_addr, bytes_per_word); + length -= bytes_per_word; + + /* Read data from USPI RX FIFO */ + while (USPI_GET_RX_EMPTY_FLAG(uspi_base)); + recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word); + } + } // else + + /* Wait USPI RX or drain USPI RX-FIFO */ + if (recv_addr) + { + // Wait USPI transmission done + while (USPI_IS_BUSY(uspi_base)) + { + while (!USPI_GET_RX_EMPTY_FLAG(uspi_base)) + { + recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word); + } + } + + while (!USPI_GET_RX_EMPTY_FLAG(uspi_base)) + { + recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word); + } + } + else + { + /* Clear USPI RX FIFO */ + nu_uspi_drain_rxfifo(uspi_base); + } +} + +static void nu_uspi_transfer(struct nu_uspi *uspi_bus, uint8_t *tx, uint8_t *rx, int length, uint8_t bytes_per_word) +{ +#if defined(BSP_USING_USPI_PDMA) + /* PDMA transfer constrains */ + if ((uspi_bus->pdma_chanid_rx >= 0) && + (!((uint32_t)tx % bytes_per_word)) && + (!((uint32_t)rx % bytes_per_word))) + nu_uspi_pdma_transmit(uspi_bus, tx, rx, length, bytes_per_word); + else + nu_uspi_transmission_with_poll(uspi_bus, tx, rx, length, bytes_per_word); +#else + nu_uspi_transmission_with_poll(uspi_bus, tx, rx, length, bytes_per_word); +#endif +} + +static rt_uint32_t nu_uspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + struct nu_uspi *uspi_bus; + struct rt_spi_configuration *configuration; + uint8_t bytes_per_word; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + RT_ASSERT(message != RT_NULL); + + uspi_bus = (struct nu_uspi *) device->bus; + configuration = &uspi_bus->configuration; + bytes_per_word = configuration->data_width / 8; + + if ((message->length % bytes_per_word) != 0) + { + /* Say bye. */ + LOG_E("%s: error payload length(%d%%%d != 0).\n", uspi_bus->name, message->length, bytes_per_word); + return 0; + } + + if (message->length > 0) + { + if (message->cs_take && !(configuration->mode & RT_SPI_NO_CS)) + { + if (configuration->mode & RT_SPI_CS_HIGH) + { + USPI_SET_SS_HIGH(uspi_bus->uspi_base); + } + else + { + USPI_SET_SS_LOW(uspi_bus->uspi_base); + } + } + + nu_uspi_transfer(uspi_bus, (uint8_t *)message->send_buf, (uint8_t *)message->recv_buf, message->length, bytes_per_word); + + if (message->cs_release && !(configuration->mode & RT_SPI_NO_CS)) + { + if (configuration->mode & RT_SPI_CS_HIGH) + { + USPI_SET_SS_LOW(uspi_bus->uspi_base); + } + else + { + USPI_SET_SS_HIGH(uspi_bus->uspi_base); + } + } + + } + + return message->length; +} + +static int nu_uspi_register_bus(struct nu_uspi *uspi_bus, const char *name) +{ + return rt_spi_bus_register(&uspi_bus->dev, name, &nu_uspi_poll_ops); +} + +/** + * Hardware USPI Initial + */ +static int rt_hw_uspi_init(void) +{ + int i; + + for (i = (USPI_START + 1); i < USPI_CNT; i++) + { + nu_uspi_register_bus(&nu_uspi_arr[i], nu_uspi_arr[i].name); +#if defined(BSP_USING_USPI_PDMA) + nu_uspi_arr[i].pdma_chanid_tx = -1; + nu_uspi_arr[i].pdma_chanid_rx = -1; + if ((nu_uspi_arr[i].pdma_perp_tx != NU_PDMA_UNUSED) && (nu_uspi_arr[i].pdma_perp_rx != NU_PDMA_UNUSED)) + { + if (nu_hw_uspi_pdma_allocate(&nu_uspi_arr[i]) != RT_EOK) + { + LOG_E("Failed to allocate DMA channels for %s. We will use poll-mode for this bus.\n", nu_uspi_arr[i].name); + } + } +#endif + } + + return 0; +} + +INIT_DEVICE_EXPORT(rt_hw_uspi_init); + +#endif //#if defined(BSP_USING_USPI) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_uuart.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_uuart.c new file mode 100644 index 0000000000..49f4750a5f --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_uuart.c @@ -0,0 +1,621 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-01-28 klcheng First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_UUART) + +#include +#include +#include "NuMicro.h" + +#if defined(RT_SERIAL_USING_DMA) + #include +#endif + +/* Private define ---------------------------------------------------------------*/ +enum +{ + UUART_START = -1, +#if defined(BSP_USING_UUART0) + UUART0_IDX, +#endif +#if defined(BSP_USING_UUART1) + UUART1_IDX, +#endif + UUART_CNT +}; + +/* Private typedef --------------------------------------------------------------*/ +struct nu_uuart +{ + rt_serial_t dev; + char *name; + UUART_T *uuart_base; + uint32_t uuart_rst; + IRQn_Type uuart_irq_n; +#if defined(RT_SERIAL_USING_DMA) + uint32_t dma_flag; + int16_t pdma_perp_tx; + int8_t pdma_chanid_tx; + + int16_t pdma_perp_rx; + int8_t pdma_chanid_rx; + int32_t rx_write_offset; + int32_t rxdma_trigger_len; +#endif +}; +typedef struct nu_uuart *nu_uuart_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t nu_uuart_configure(struct rt_serial_device *serial, struct serial_configure *cfg); +static rt_err_t nu_uuart_control(struct rt_serial_device *serial, int cmd, void *arg); +static int nu_uuart_send(struct rt_serial_device *serial, char c); +static int nu_uuart_receive(struct rt_serial_device *serial); +static void nu_uuart_isr(nu_uuart_t serial); + +#if defined(RT_SERIAL_USING_DMA) + static rt_size_t nu_uuart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction); + static void nu_pdma_uuart_rx_cb(void *pvOwner, uint32_t u32Events); + static void nu_pdma_uuart_tx_cb(void *pvOwner, uint32_t u32Events); +#endif + +/* Public functions ------------------------------------------------------------*/ + +/* Private variables ------------------------------------------------------------*/ + +static const struct rt_uart_ops nu_uuart_ops = +{ + .configure = nu_uuart_configure, + .control = nu_uuart_control, + .putc = nu_uuart_send, + .getc = nu_uuart_receive, +#if defined(RT_SERIAL_USING_DMA) + .dma_transmit = nu_uuart_dma_transmit +#else + .dma_transmit = RT_NULL +#endif +}; + +static const struct serial_configure nu_uuart_default_config = + RT_SERIAL_CONFIG_DEFAULT; + + +static struct nu_uuart nu_uuart_arr [] = +{ +#if defined(BSP_USING_UUART0) + { + .name = "uuart0", + .uuart_base = UUART0, + .uuart_rst = USCI0_RST, + .uuart_irq_n = USCI01_IRQn, +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UUART0_TX_DMA) + .pdma_perp_tx = PDMA_USCI0_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UUART0_RX_DMA) + .pdma_perp_rx = PDMA_USCI0_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + +#if defined(BSP_USING_UUART1) + { + .name = "uuart1", + .uuart_base = UUART1, + .uuart_rst = USCI1_RST, + .uuart_irq_n = USCI01_IRQn, +#if defined(RT_SERIAL_USING_DMA) +#if defined(BSP_USING_UUART1_TX_DMA) + .pdma_perp_tx = PDMA_USCI1_TX, +#else + .pdma_perp_tx = NU_PDMA_UNUSED, +#endif +#if defined(BSP_USING_UUART1_RX_DMA) + .pdma_perp_rx = PDMA_USCI1_RX, + .rx_write_offset = 0, +#else + .pdma_perp_rx = NU_PDMA_UNUSED, +#endif +#endif + }, +#endif + + {0} +}; /* uuart nu_uuart */ + +/* Interrupt Handle Function ----------------------------------------------------*/ +#if defined(BSP_USING_UUART0) || defined(BSP_USING_UUART1) +/* USCI0 interrupt entry */ +void USCI01_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + +#if defined(BSP_USING_UUART0) + nu_uuart_isr(&nu_uuart_arr[UUART0_IDX]); +#endif + +#if defined(BSP_USING_UUART1) + nu_uuart_isr(&nu_uuart_arr[UUART1_IDX]); +#endif + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif + +/** + * All UUART interrupt service routine + */ +static void nu_uuart_isr(nu_uuart_t serial) +{ + /* Get base address of uuart register */ + UUART_T *uuart_base = ((nu_uuart_t)serial)->uuart_base; + + /* Get interrupt event */ + uint32_t u32IntSts = uuart_base->PROTSTS; + uint32_t u32FIFOSts = uuart_base->BUFSTS; + + if (u32IntSts & (UUART_PROTSTS_PARITYERR_Msk | UUART_PROTSTS_FRMERR_Msk | UUART_PROTSTS_BREAK_Msk)) + { + uuart_base->PROTSTS |= (UUART_PROTSTS_PARITYERR_Msk | UUART_PROTSTS_FRMERR_Msk | UUART_PROTSTS_BREAK_Msk); + return; + } + + /* Handle RX event */ + if (u32IntSts & UUART_PROTSTS_RXENDIF_Msk) + { + rt_hw_serial_isr(&serial->dev, RT_SERIAL_EVENT_RX_IND); + } + uuart_base->PROTSTS = u32IntSts; + uuart_base->BUFSTS = u32FIFOSts; +} + +/** + * Configure uuart port + */ +static rt_err_t nu_uuart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + rt_err_t ret = RT_EOK; + uint32_t uuart_word_len = 0; + uint32_t uuart_stop_bit = 0; + uint32_t uuart_parity = 0; + + /* Get base address of uuart register */ + UUART_T *uuart_base = ((nu_uuart_t)serial)->uuart_base; + + /* Check baud rate */ + RT_ASSERT(cfg->baud_rate != 0); + + /* Check word len */ + switch (cfg->data_bits) + { + case DATA_BITS_5: + rt_kprintf("Unsupported data length"); + goto exit_nu_uuart_configure; + + case DATA_BITS_6: + uuart_word_len = UUART_WORD_LEN_6; + break; + + case DATA_BITS_7: + uuart_word_len = UUART_WORD_LEN_7; + break; + + case DATA_BITS_8: + uuart_word_len = UUART_WORD_LEN_8; + break; + + default: + rt_kprintf("Unsupported data length"); + ret = RT_EINVAL; + goto exit_nu_uuart_configure; + } + + /* Check stop bit */ + switch (cfg->stop_bits) + { + case STOP_BITS_1: + uuart_stop_bit = UUART_STOP_BIT_1; + break; + + case STOP_BITS_2: + uuart_stop_bit = UUART_STOP_BIT_2; + break; + + default: + rt_kprintf("Unsupported stop bit"); + ret = RT_EINVAL; + goto exit_nu_uuart_configure; + } + + /* Check parity */ + switch (cfg->parity) + { + case PARITY_NONE: + uuart_parity = UUART_PARITY_NONE; + break; + + case PARITY_ODD: + uuart_parity = UUART_PARITY_ODD; + break; + + case PARITY_EVEN: + uuart_parity = UUART_PARITY_EVEN; + break; + + default: + rt_kprintf("Unsupported parity"); + ret = RT_EINVAL; + goto exit_nu_uuart_configure; + } + /* Reset this module */ + SYS_ResetModule(((nu_uuart_t)serial)->uuart_rst); + + /* Open UUart and set UUART baud rate */ + UUART_Open(uuart_base, cfg->baud_rate); + + /* Set line configuration. */ + UUART_SetLine_Config(uuart_base, 0, uuart_word_len, uuart_parity, uuart_stop_bit); + + /* Enable NVIC interrupt. */ + NVIC_EnableIRQ(((nu_uuart_t)serial)->uuart_irq_n); + +exit_nu_uuart_configure: + + if (ret != RT_EOK) + UUART_Close(uuart_base); + + return -(ret); +} + +#if defined(RT_SERIAL_USING_DMA) +static rt_err_t nu_pdma_uuart_rx_config(struct rt_serial_device *serial, uint8_t *pu8Buf, int32_t i32TriggerLen) +{ + rt_err_t result = RT_EOK; + + /* Get base address of uuart register */ + UUART_T *uuart_base = ((nu_uuart_t)serial)->uuart_base; + + result = nu_pdma_callback_register(((nu_uuart_t)serial)->pdma_chanid_rx, + nu_pdma_uuart_rx_cb, + (void *)serial, + NU_PDMA_EVENT_TRANSFER_DONE | NU_PDMA_EVENT_TIMEOUT); + + if (result != RT_EOK) + { + goto exit_nu_pdma_uuart_rx_config; + } + + result = nu_pdma_transfer(((nu_uuart_t)serial)->pdma_chanid_rx, + 8, + (uint32_t)&uuart_base->RXDAT, + (uint32_t)pu8Buf, + i32TriggerLen, + 1000); //Idle-timeout, 1ms + + if (result != RT_EOK) + { + goto exit_nu_pdma_uuart_rx_config; + } + + //UUART PDMA reset + UUART_PDMA_ENABLE(uuart_base, UUART_PDMACTL_PDMARST_Msk); + + /* Enable Receive Line interrupt & Start DMA RX transfer. */ + UUART_EnableInt(uuart_base, UUART_RLS_INT_MASK); + UUART_PDMA_ENABLE(uuart_base, UUART_PDMACTL_RXPDMAEN_Msk | UUART_PDMACTL_PDMAEN_Msk); + +exit_nu_pdma_uuart_rx_config: + + return result; +} + +static void nu_pdma_uuart_rx_cb(void *pvOwner, uint32_t u32Events) +{ + rt_size_t recv_len = 0; + rt_size_t transferred_rxbyte = 0; + struct rt_serial_device *serial = (struct rt_serial_device *)pvOwner; + nu_uuart_t puuart = (nu_uuart_t)serial; + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uuart register */ + UUART_T *uuart_base = puuart->uuart_base; + + transferred_rxbyte = nu_pdma_transferred_byte_get(puuart->pdma_chanid_rx, puuart->rxdma_trigger_len); + + if (u32Events & (NU_PDMA_EVENT_TRANSFER_DONE | NU_PDMA_EVENT_TIMEOUT)) + { + if (u32Events & NU_PDMA_EVENT_TRANSFER_DONE) + { + if (serial->config.bufsz != 0) + { + struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + + nu_pdma_uuart_rx_config(serial, &rx_fifo->buffer[0], puuart->rxdma_trigger_len); // Config & trigger next + } + + transferred_rxbyte = puuart->rxdma_trigger_len; + } + else if ((u32Events & NU_PDMA_EVENT_TIMEOUT) && !UUART_GET_RX_EMPTY(uuart_base)) + { + return; + } + + recv_len = transferred_rxbyte - puuart->rx_write_offset; + + puuart->rx_write_offset = transferred_rxbyte % puuart->rxdma_trigger_len; + + } + + if ((serial->config.bufsz == 0) && (u32Events & NU_PDMA_EVENT_TRANSFER_DONE)) + { + recv_len = puuart->rxdma_trigger_len; + } + + if (recv_len) + { + rt_hw_serial_isr(&puuart->dev, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); + } +} + +static rt_err_t nu_pdma_uuart_tx_config(struct rt_serial_device *serial) +{ + rt_err_t result = RT_EOK; + RT_ASSERT(serial != RT_NULL); + + result = nu_pdma_callback_register(((nu_uuart_t)serial)->pdma_chanid_tx, + nu_pdma_uuart_tx_cb, + (void *)serial, + NU_PDMA_EVENT_TRANSFER_DONE); + + return result; +} + +static void nu_pdma_uuart_tx_cb(void *pvOwner, uint32_t u32Events) +{ + nu_uuart_t puuart = (nu_uuart_t)pvOwner; + + RT_ASSERT(puuart != RT_NULL); + + // Stop DMA TX transfer + UUART_PDMA_DISABLE(puuart->uuart_base, UUART_PDMACTL_TXPDMAEN_Msk); + + if (u32Events & NU_PDMA_EVENT_TRANSFER_DONE) + { + rt_hw_serial_isr(&puuart->dev, RT_SERIAL_EVENT_TX_DMADONE); + } +} + +/** + * UUart DMA transfer + */ +static rt_size_t nu_uuart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction) +{ + rt_err_t result = RT_EOK; + + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(buf != RT_NULL); + + /* Get base address of uuart register */ + UUART_T *uuart_base = ((nu_uuart_t)serial)->uuart_base; + if (direction == RT_SERIAL_DMA_TX) + { + result = nu_pdma_transfer(((nu_uuart_t)serial)->pdma_chanid_tx, + 8, + (uint32_t)buf, + (uint32_t)&uuart_base->TXDAT, + size, + 0); // wait-forever + // Start DMA TX transfer + UUART_PDMA_ENABLE(uuart_base, UUART_PDMACTL_TXPDMAEN_Msk | UUART_PDMACTL_PDMAEN_Msk); + } + else if (direction == RT_SERIAL_DMA_RX) + { + // If config.bufsz = 0, serial will trigger once. + ((nu_uuart_t)serial)->rxdma_trigger_len = size; + ((nu_uuart_t)serial)->rx_write_offset = 0; + result = nu_pdma_uuart_rx_config(serial, buf, size); + } + else + { + result = RT_ERROR; + } + + return result; +} + +static int nu_hw_uuart_dma_allocate(nu_uuart_t puuart) +{ + RT_ASSERT(puuart != RT_NULL); + + /* Allocate UUART_TX nu_dma channel */ + if (puuart->pdma_perp_tx != NU_PDMA_UNUSED) + { + puuart->pdma_chanid_tx = nu_pdma_channel_allocate(puuart->pdma_perp_tx); + if (puuart->pdma_chanid_tx >= 0) + { + puuart->dma_flag |= RT_DEVICE_FLAG_DMA_TX; + } + } + + /* Allocate UUART_RX nu_dma channel */ + if (puuart->pdma_perp_rx != NU_PDMA_UNUSED) + { + puuart->pdma_chanid_rx = nu_pdma_channel_allocate(puuart->pdma_perp_rx); + if (puuart->pdma_chanid_rx >= 0) + { + puuart->dma_flag |= RT_DEVICE_FLAG_DMA_RX; + } + } + + return RT_EOK; +} +#endif + +/** + * UUart interrupt control + */ +static rt_err_t nu_uuart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + rt_err_t result = RT_EOK; + rt_uint32_t flag = 0; + rt_ubase_t ctrl_arg = (rt_ubase_t)arg; + + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uuart register */ + UUART_T *uuart_base = ((nu_uuart_t)serial)->uuart_base; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) /* Disable INT-RX */ + { + flag = UUART_RXEND_INT_MASK; + UUART_DisableInt(uuart_base, flag); + } + else if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) /* Disable DMA-RX */ + { + /* Disable Receive Line interrupt & Stop DMA RX transfer. */ + flag = UUART_RLS_INT_MASK; + nu_pdma_channel_terminate(((nu_uuart_t)serial)->pdma_chanid_rx); + UUART_PDMA_DISABLE(uuart_base, UUART_PDMACTL_RXPDMAEN_Msk); + UUART_DisableInt(uuart_base, flag); + } + break; + + case RT_DEVICE_CTRL_SET_INT: + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) /* Enable INT-RX */ + { + flag = UUART_RXEND_INT_MASK; + UUART_EnableInt(uuart_base, flag); + } + break; + +#if defined(RT_SERIAL_USING_DMA) + case RT_DEVICE_CTRL_CONFIG: + if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) /* Configure and trigger DMA-RX */ + { + struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + ((nu_uuart_t)serial)->rxdma_trigger_len = serial->config.bufsz; + ((nu_uuart_t)serial)->rx_write_offset = 0; + result = nu_pdma_uuart_rx_config(serial, &rx_fifo->buffer[0], ((nu_uuart_t)serial)->rxdma_trigger_len); // Config & trigger + } + else if (ctrl_arg == RT_DEVICE_FLAG_DMA_TX) /* Configure DMA-TX */ + { + result = nu_pdma_uuart_tx_config(serial); + } + break; +#endif + + case RT_DEVICE_CTRL_CLOSE: + /* Disable NVIC interrupt. */ + NVIC_DisableIRQ(((nu_uuart_t)serial)->uuart_irq_n); + +#if defined(RT_SERIAL_USING_DMA) + nu_pdma_channel_terminate(((nu_uuart_t)serial)->pdma_chanid_tx); + nu_pdma_channel_terminate(((nu_uuart_t)serial)->pdma_chanid_rx); +#endif + + /* Reset this module */ + SYS_ResetModule(((nu_uuart_t)serial)->uuart_rst); + + /* Close UUART port */ + UUART_Close(uuart_base); + + break; + default: + result = -RT_EINVAL; + break; + } + return result; +} + +/** + * UUart put char + */ +static int nu_uuart_send(struct rt_serial_device *serial, char c) +{ + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uuart register */ + UUART_T *uuart_base = ((nu_uuart_t)serial)->uuart_base; + + /* Waiting if TX-FIFO is full. */ + while (UUART_IS_TX_FULL(uuart_base)) {}; + + /* Put char into TX-FIFO */ + UUART_WRITE(uuart_base, c); + + return 1; +} + +/** + * UUart get char + */ +static int nu_uuart_receive(struct rt_serial_device *serial) +{ + RT_ASSERT(serial != RT_NULL); + + /* Get base address of uuart register */ + UUART_T *uuart_base = ((nu_uuart_t)serial)->uuart_base; + + /* Return failure if RX-FIFO is empty. */ + if (UUART_GET_RX_EMPTY(uuart_base) != 0) + { + return -1; + } + + /* Get char from RX-FIFO */ + return UUART_READ(uuart_base); +} + +/** + * Hardware UUART Initialization + */ +static int rt_hw_uuart_init(void) +{ + int i; + rt_uint32_t flag; + rt_err_t ret = RT_EOK; + + for (i = (UUART_START + 1); i < UUART_CNT; i++) + { + flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX; + + nu_uuart_arr[i].dev.ops = &nu_uuart_ops; + nu_uuart_arr[i].dev.config = nu_uuart_default_config; + +#if defined(RT_SERIAL_USING_DMA) + nu_uuart_arr[i].dma_flag = 0; + nu_hw_uuart_dma_allocate(&nu_uuart_arr[i]); + flag |= nu_uuart_arr[i].dma_flag; +#endif + + ret = rt_hw_serial_register(&nu_uuart_arr[i].dev, nu_uuart_arr[i].name, flag, NULL); + RT_ASSERT(ret == RT_EOK); + } + + return (int)ret; +} + +INIT_DEVICE_EXPORT(rt_hw_uuart_init); + +#endif //#if defined(BSP_USING_UUART) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_wdt.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_wdt.c new file mode 100644 index 0000000000..fabcb92760 --- /dev/null +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_wdt.c @@ -0,0 +1,481 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-07-24 klcheng First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_WDT) +#include +#include +#include +#include "NuMicro.h" + +/*-------------------------------------------------------------------------------*/ +/* watchdog timer timeout look up table */ +/*-------------------------------------------------------------------------------*/ +/* clock = LIRC 32000Hz. */ +/* */ +/* working hz toutsel exp cycles timeout (s) */ +/* 32000 0 4 16 0.0005 */ +/* 1 6 64 0.0020 */ +/* 2 8 256 0.0080 */ +/* 3 10 1024 0.0320 */ +/* 4 12 4096 0.1280 */ +/* 5 14 16384 0.5120 */ +/* 6 16 65536 2.0480 */ +/* 7 18 262144 8.1920 */ +/* 8 20 1048576 32.7680 */ +/*-------------------------------------------------------------------------------*/ +/* clock = LXT 32768Hz. */ +/* */ +/* working hz toutsel exp cycles timeout (s) */ +/* 32768 0 4 16 0.0005 */ +/* 1 6 64 0.0020 */ +/* 2 8 256 0.0078 */ +/* 3 10 1024 0.0313 */ +/* 4 12 4096 0.1250 */ +/* 5 14 16384 0.5000 */ +/* 6 16 65536 2.0000 */ +/* 7 18 262144 8.0000 */ +/* 8 20 1048576 32.000 */ +/*-------------------------------------------------------------------------------*/ +/* clock = 96MHz HCLK divide 2048 = 93750 Hz. */ +/* */ +/* working hz toutsel exp cycles timeout (s) */ +/* 46875 0 4 16 0.00034 */ +/* 1 6 64 0.00137 */ +/* 2 8 256 0.00546 */ +/* 3 10 1024 0.02185 */ +/* 4 12 4096 0.08738 */ +/* 5 14 16384 0.34953 */ +/* 6 16 65536 1.39810 */ +/* 7 18 262144 5.59241 */ +/* 8 20 1048576 22.3696 */ +/*-------------------------------------------------------------------------------*/ + +/* Private define ---------------------------------------------------------------*/ + +/* Pick a suitable wdt timeout interval, it is a trade-off between the + consideration of timeout accuracy and the system performance. The MIN_CYCLES + parameter is a numerical value of the toutsel setting, and it must be set to + a correct one which matches to the literal meaning of MIN_TOUTSEL. */ +#define MIN_TOUTSEL (WDT_TIMEOUT_2POW10) +#define MIN_CYCLES (1024) + + +/* Macros to convert the value between the timeout interval and the soft time iterations. */ +#define ROUND_TO_INTEGER(value) ((int)(((value) * 10 + 5) / 10)) +#define CONV_SEC_TO_IT(hz, secs) (ROUND_TO_INTEGER((float)((secs) * (hz)) / (float)(MIN_CYCLES))) +#define CONV_IT_TO_SEC(hz, iterations) (ROUND_TO_INTEGER((float)((iterations) * (MIN_CYCLES)) / (float)(hz))) + + +/* Private typedef --------------------------------------------------------------*/ +struct soft_time_handle +{ + int clock_hz; + int wanted_sec; + int report_sec; + int left_iterations; + int full_iterations; + rt_bool_t expired; + rt_bool_t feed_dog; +}; + +typedef volatile struct soft_time_handle soft_time_handle_t; + +/* Private functions ------------------------------------------------------------*/ +static rt_err_t wdt_init(rt_watchdog_t *dev); +static rt_err_t wdt_control(rt_watchdog_t *dev, int cmd, void *args); +static uint32_t wdt_get_module_clock(void); +static uint32_t wdt_get_working_hz(void); +static void soft_time_init(soft_time_handle_t *const soft_time); +static void soft_time_setup(uint32_t wanted_sec, uint32_t hz, soft_time_handle_t *const soft_time); +static void soft_time_feed_dog(soft_time_handle_t *const soft_time); + +#if defined(RT_USING_PM) +static int wdt_pm_suspend(const struct rt_device *device, rt_uint8_t mode); +static void wdt_pm_resume(const struct rt_device *device, rt_uint8_t mode); +static int wdt_pm_frequency_change(const struct rt_device *device, rt_uint8_t mode); +static void soft_time_freqeucy_change(uint32_t new_hz, soft_time_handle_t *const soft_time); +#endif + +/* Public functions -------------------------------------------------------------*/ + +/* Private variables ------------------------------------------------------------*/ +static struct soft_time_handle soft_time; +static struct rt_watchdog_device device_wdt; +static struct rt_watchdog_ops ops_wdt = +{ + .init = wdt_init, + .control = wdt_control, +}; + +#if defined(RT_USING_PM) + +static struct rt_device_pm_ops device_pm_ops = +{ + .suspend = wdt_pm_suspend, + .resume = wdt_pm_resume, + .frequency_change = wdt_pm_frequency_change +}; +#endif + + +#if defined(RT_USING_PM) + +/* device pm suspend() entry. */ +static int wdt_pm_suspend(const struct rt_device *device, rt_uint8_t mode) +{ + switch (mode) + { + case PM_SLEEP_MODE_NONE: + case PM_SLEEP_MODE_IDLE: + case PM_SLEEP_MODE_STANDBY: + case PM_SLEEP_MODE_SHUTDOWN: + break; + + case PM_SLEEP_MODE_LIGHT: + case PM_SLEEP_MODE_DEEP: + + SYS_UnlockReg(); + WDT->CTL &= ~WDT_CTL_WDTEN_Msk; + SYS_LockReg(); + break; + + default: + break; + } + + return (int)RT_EOK; +} + + +/* device pm resume() entry. */ +static void wdt_pm_resume(const struct rt_device *device, rt_uint8_t mode) +{ + switch (mode) + { + case PM_SLEEP_MODE_NONE: + case PM_SLEEP_MODE_IDLE: + case PM_SLEEP_MODE_STANDBY: + case PM_SLEEP_MODE_SHUTDOWN: + break; + + case PM_SLEEP_MODE_LIGHT: + case PM_SLEEP_MODE_DEEP: + + SYS_UnlockReg(); + WDT->CTL |= WDT_CTL_WDTEN_Msk; + SYS_LockReg(); + break; + + default: + break; + } +} + + +/* device pm frequency_change() entry. */ +static int wdt_pm_frequency_change(const struct rt_device *device, rt_uint8_t mode) +{ + uint32_t clk, new_hz; + + new_hz = wdt_get_working_hz(); + clk = wdt_get_module_clock(); + + if (clk == CLK_CLKSEL1_WDTSEL_HCLK_DIV2048) + { + if (new_hz == soft_time.clock_hz) + return (int)(RT_EOK); + + /* frequency change occurs in critical section */ + soft_time_freqeucy_change(new_hz, &soft_time); + } + + return (int)(RT_EOK); +} + + +static void soft_time_freqeucy_change(uint32_t new_hz, soft_time_handle_t *const soft_time) +{ + rt_base_t level; + soft_time_handle_t new_time; + rt_bool_t corner_case = RT_FALSE; + + level = rt_hw_interrupt_disable(); + + new_time.clock_hz = new_hz; + new_time.feed_dog = soft_time->feed_dog; + new_time.expired = soft_time->expired; + new_time.wanted_sec = soft_time->wanted_sec; + new_time.full_iterations = CONV_SEC_TO_IT(new_hz, soft_time->wanted_sec); + new_time.report_sec = CONV_IT_TO_SEC(new_hz, new_time.full_iterations); + + new_time.left_iterations = ROUND_TO_INTEGER((float)soft_time->left_iterations * + (float)new_hz / (float)soft_time->clock_hz); + + if ((new_time.left_iterations == 0) && (soft_time->left_iterations > 0)) + { + new_time.left_iterations++;; + corner_case = RT_TRUE; + } + + *soft_time = new_time; + rt_hw_interrupt_enable(level); + + if (corner_case) + { + LOG_W("pm frequency change cause wdt internal left iterations convert to 0.\n\r \ + wdt driver will add another 1 iteration for this corner case."); + } +} +#endif + + +static void hw_wdt_init(void) +{ + SYS_UnlockReg(); + + if (WDT_GET_RESET_FLAG()) + { + LOG_W("System re-boots from watchdog timer reset.\n"); + WDT_CLEAR_RESET_FLAG(); + } + + SYS_LockReg(); + NVIC_EnableIRQ(WDT_IRQn); +} + + +/* wdt device driver initialize. */ +int rt_hw_wdt_init(void) +{ + rt_err_t ret; + + hw_wdt_init(); + + device_wdt.ops = &ops_wdt; + ret = rt_hw_watchdog_register(&device_wdt, "wdt", RT_DEVICE_FLAG_RDWR, RT_NULL); + +#if defined(RT_USING_PM) + + rt_pm_device_register((struct rt_device *)&device_wdt, &device_pm_ops); +#endif + + return (int)ret; +} +INIT_BOARD_EXPORT(rt_hw_wdt_init); + + +/* Register rt-thread device.init() entry. */ +static rt_err_t wdt_init(rt_watchdog_t *dev) +{ + soft_time_init(&soft_time); + hw_wdt_init(); + + return RT_EOK; +} + + +static uint32_t wdt_get_module_clock(void) +{ + + return ((CLK->CLKSEL1 & CLK_CLKSEL1_WDTSEL_Msk)); +} + + +static uint32_t wdt_get_working_hz(void) +{ + uint32_t clk, hz = 0; + + clk = wdt_get_module_clock(); + + switch (clk) + { + case CLK_CLKSEL1_WDTSEL_LIRC: + hz = __LIRC; + break; + + case CLK_CLKSEL1_WDTSEL_LXT: + hz = __LXT; + break; + + case CLK_CLKSEL1_WDTSEL_HCLK_DIV2048: + hz = CLK_GetHCLKFreq() / 2048; + break; + + default: + break; + } + + return hz; +} + + +static void soft_time_init(soft_time_handle_t *const soft_time) +{ + rt_memset((void *)soft_time, 0, sizeof(struct soft_time_handle)); + +} + + +static void soft_time_setup(uint32_t wanted_sec, uint32_t hz, soft_time_handle_t *const soft_time) +{ + rt_base_t level; + + level = rt_hw_interrupt_disable(); + + soft_time->expired = RT_FALSE; + soft_time->feed_dog = RT_FALSE; + soft_time->wanted_sec = wanted_sec; + soft_time->full_iterations = CONV_SEC_TO_IT(hz, wanted_sec); + soft_time->left_iterations = soft_time->full_iterations; + soft_time->report_sec = CONV_IT_TO_SEC(hz, soft_time->full_iterations); + soft_time->clock_hz = hz; + + rt_hw_interrupt_enable(level); +} + + +static void soft_time_feed_dog(soft_time_handle_t *const soft_time) +{ + soft_time->feed_dog = RT_TRUE; +} + + +/* Register rt-thread device.control() entry. */ +static rt_err_t wdt_control(rt_watchdog_t *dev, int cmd, void *args) +{ + uint32_t wanted_sec, hz; + uint32_t *buf; + rt_err_t ret = RT_EOK; + + if (dev == NULL) + return -(RT_EINVAL); + + SYS_UnlockReg(); + + hz = wdt_get_working_hz(); + + switch (cmd) + { + case RT_DEVICE_CTRL_WDT_GET_TIMEOUT: + + if (args == RT_NULL) + { + ret = RT_EINVAL; + break; + } + + buf = (uint32_t *)args; + *buf = soft_time.report_sec; + break; + + case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: + + wanted_sec = *((uint32_t *)args); + + if (wanted_sec == 0) + { + ret = RT_EINVAL; + break; + } + + soft_time_setup(wanted_sec, hz, &soft_time); + break; + + case RT_DEVICE_CTRL_WDT_GET_TIMELEFT: + + if (args == RT_NULL) + { + ret = RT_EINVAL; + break; + } + + buf = (uint32_t *)args; + *buf = CONV_IT_TO_SEC(hz, soft_time.left_iterations); + break; + + case RT_DEVICE_CTRL_WDT_KEEPALIVE: + + /* Make a mark that the application has fed the watchdog. */ + soft_time_feed_dog(&soft_time); + break; + + case RT_DEVICE_CTRL_WDT_START: + + WDT_RESET_COUNTER(); + WDT_Open(MIN_TOUTSEL, WDT_RESET_DELAY_1026CLK, TRUE, TRUE); + WDT_EnableInt(); + break; + + case RT_DEVICE_CTRL_WDT_STOP: + + WDT_Close(); + break; + + default: + ret = RT_ERROR; + } + + SYS_LockReg(); + + return -(ret); +} + + +/* wdt interrupt entry */ +void WDT_IRQHandler(void) +{ + rt_interrupt_enter(); + + /* Clear wdt interrupt flag */ + if (WDT_GET_TIMEOUT_INT_FLAG()) + { + WDT_CLEAR_TIMEOUT_INT_FLAG(); + } + + /* Clear wdt wakeup flag */ + if (WDT_GET_TIMEOUT_WAKEUP_FLAG()) + { + WDT_CLEAR_TIMEOUT_WAKEUP_FLAG(); + } + + /* The soft time has not reached the configured timeout yet. Clear the wdt counter + any way to prevent the system from hardware wdt reset. */ + if (soft_time.left_iterations-- > 0) + { + WDT_RESET_COUNTER(); + } + + /* The soft time reaches the configured timeout boundary. Clear the wdt + counter if he application has fed the dog at least once until now. */ + else + { + if ((soft_time.feed_dog) && (!soft_time.expired)) + { + WDT_RESET_COUNTER(); + soft_time.feed_dog = RT_FALSE; + soft_time.left_iterations = soft_time.full_iterations; + } + else + { + /* Application does not feed the dog in time. */ + soft_time.expired = RT_TRUE; + } + } + + rt_interrupt_leave(); +} + +#endif /* BSP_USING_WDT */ + + diff --git a/bsp/nuvoton/numaker-m032ki/.config b/bsp/nuvoton/numaker-m032ki/.config new file mode 100644 index 0000000000..e94f821c48 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/.config @@ -0,0 +1,675 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=1000 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=512 +CONFIG_RT_USING_TIMER_SOFT=y +CONFIG_RT_TIMER_THREAD_PRIO=4 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 + +# +# 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 is not set +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_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 is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=256 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" +CONFIG_RT_VER_NUM=0x40004 +CONFIG_ARCH_ARM=y +# CONFIG_RT_USING_CPU_FFS is not set +CONFIG_ARCH_ARM_CORTEX_M=y +CONFIG_ARCH_ARM_CORTEX_M0=y +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_CMD_SIZE=80 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +# CONFIG_FINSH_USING_MSH_ONLY 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 is not set +CONFIG_RT_USING_DFS_DEVFS=y +# CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_RAMFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +CONFIG_RT_USING_HWTIMER=y +# 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=y +CONFIG_RT_USING_ADC=y +# CONFIG_RT_USING_DAC is not set +CONFIG_RT_USING_PWM=y +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +CONFIG_RT_USING_PM=y +CONFIG_RT_USING_RTC=y +# CONFIG_RT_USING_ALARM is not set +# CONFIG_RT_USING_SOFT_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +CONFIG_RT_USING_WDT=y +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_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=y +CONFIG_RT_USBD_THREAD_STACK_SZ=4096 +CONFIG_USB_VENDOR_ID=0x0FFE +CONFIG_USB_PRODUCT_ID=0x0001 +CONFIG_RT_USB_DEVICE_COMPOSITE=y +# CONFIG__RT_USB_DEVICE_NONE is not set +# CONFIG__RT_USB_DEVICE_CDC is not set +# CONFIG__RT_USB_DEVICE_MSTORAGE is not set +# CONFIG__RT_USB_DEVICE_HID is not set +# CONFIG__RT_USB_DEVICE_WINUSB is not set +# CONFIG__RT_USB_DEVICE_AUDIO is not set +# CONFIG_RT_USB_DEVICE_CDC is not set +CONFIG_RT_USB_DEVICE_NONE=y +# CONFIG_RT_USB_DEVICE_MSTORAGE is not set +CONFIG_RT_USB_DEVICE_HID=y +# CONFIG_RT_USB_DEVICE_WINUSB is not set +# CONFIG_RT_USB_DEVICE_AUDIO is not set +# CONFIG_RT_USB_DEVICE_HID_KEYBOARD is not set +CONFIG_RT_USB_DEVICE_HID_MOUSE=y +# CONFIG_RT_USB_DEVICE_HID_GENERAL is not set +# CONFIG_RT_USB_DEVICE_HID_MEDIA 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 is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +CONFIG_RT_USING_UTEST=y +CONFIG_UTEST_THR_STACK_SIZE=4096 +CONFIG_UTEST_THR_PRIORITY=20 +# 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_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 +# +# CONFIG_PKG_USING_GUIENGINE 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 + +# +# 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_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# 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 +# 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_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 + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +CONFIG_NU_PKG_USING_DEMO=y +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +# CONFIG_NU_PKG_USING_NAU88L25 is not set +# CONFIG_NU_PKG_USING_NAU8822 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set + +# +# Hardware Drivers Config +# + +# +# On-chip Peripheral Drivers +# +CONFIG_SOC_SERIES_M032=y +# CONFIG_BSP_USE_STDDRIVER_SOURCE is not set +CONFIG_BSP_USING_PDMA=y +CONFIG_NU_PDMA_MEMFUN_ACTOR_MAX=4 +CONFIG_NU_PDMA_SGTBL_POOL_SIZE=16 +# CONFIG_BSP_USING_FMC is not set +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_CLK=y +CONFIG_NU_CLK_INVOKE_WKTMR=y +CONFIG_BSP_USING_RTC=y +CONFIG_NU_RTC_SUPPORT_IO_RW=y +CONFIG_NU_RTC_SUPPORT_MSH_CMD=y +CONFIG_BSP_USING_ADC=y +CONFIG_BSP_USING_ADC0=y +CONFIG_BSP_USING_TMR=y +CONFIG_BSP_USING_TIMER=y +CONFIG_BSP_USING_TMR0=y +CONFIG_BSP_USING_TIMER0=y +# CONFIG_BSP_USING_TIMER0_CAPTURE is not set +CONFIG_BSP_USING_TMR1=y +CONFIG_BSP_USING_TIMER1=y +# CONFIG_BSP_USING_TIMER1_CAPTURE is not set +CONFIG_BSP_USING_TMR2=y +CONFIG_BSP_USING_TIMER2=y +# CONFIG_BSP_USING_TIMER2_CAPTURE is not set +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART0=y +# CONFIG_BSP_USING_UART0_TX_DMA is not set +# CONFIG_BSP_USING_UART0_RX_DMA is not set +CONFIG_BSP_USING_UART1=y +CONFIG_BSP_USING_UART1_TX_DMA=y +CONFIG_BSP_USING_UART1_RX_DMA=y +CONFIG_BSP_USING_UART2=y +# CONFIG_BSP_USING_UART2_TX_DMA is not set +# CONFIG_BSP_USING_UART2_RX_DMA is not set +CONFIG_BSP_USING_UART3=y +# CONFIG_BSP_USING_UART3_TX_DMA is not set +# CONFIG_BSP_USING_UART3_RX_DMA is not set +CONFIG_BSP_USING_UART4=y +# CONFIG_BSP_USING_UART4_TX_DMA is not set +# CONFIG_BSP_USING_UART4_RX_DMA is not set +CONFIG_BSP_USING_UART5=y +# CONFIG_BSP_USING_UART5_TX_DMA is not set +# CONFIG_BSP_USING_UART5_RX_DMA is not set +CONFIG_BSP_USING_UART6=y +# CONFIG_BSP_USING_UART6_TX_DMA is not set +# CONFIG_BSP_USING_UART6_RX_DMA is not set +CONFIG_BSP_USING_UART7=y +# CONFIG_BSP_USING_UART7_TX_DMA is not set +# CONFIG_BSP_USING_UART7_RX_DMA is not set +# CONFIG_BSP_USING_I2C is not set +# CONFIG_BSP_USING_USCI is not set +# CONFIG_BSP_USING_BPWM is not set +# CONFIG_BSP_USING_PWM is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_QSPI is not set +# CONFIG_BSP_USING_CRC is not set +# CONFIG_BSP_USING_SOFT_I2C is not set +CONFIG_BSP_USING_WDT=y +# CONFIG_BSP_USING_EBI is not set +CONFIG_BSP_USING_USBD=y + +# +# On-board Peripheral Drivers +# +CONFIG_BSP_USING_NULINKME=y + +# +# Board extended module drivers +# +# CONFIG_BOARD_USING_STORAGE_SPIFLASH is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-m032ki.test.utest." diff --git a/bsp/nuvoton/numaker-m032ki/Kconfig b/bsp/nuvoton/numaker-m032ki/Kconfig new file mode 100644 index 0000000000..5c55e87c61 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/Kconfig @@ -0,0 +1,29 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +# you can change the RTT_ROOT default "../../.." to your rtthread_root, +# example : default "F:/git_repositories/rt-thread" + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +config NU_PKGS_DIR + string + option env="NU_PKGS_ROOT" + default "../libraries/nu_packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "$NU_PKGS_DIR/Kconfig" +source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/numaker-m032ki/Nu_Link_Driver.ini b/bsp/nuvoton/numaker-m032ki/Nu_Link_Driver.ini new file mode 100644 index 0000000000..73b252707a --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/Nu_Link_Driver.ini @@ -0,0 +1,1038 @@ +[Version] +Nu_LinkVersion=V5.14 +[Process] +ProcessID=0x0000b660 +ProcessCreationTime_L=0xe87ebcaf +ProcessCreationTime_H=0x01d74ae4 +NuLinkID=0x18000000 +NuLinkIDs_Count=0x00000001 +NuLinkID0=0x18000000 +[ChipSelect] +;ChipName= +ChipName=M031 +[NUC505] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=NUC505_SPIFLASH.FLM +[NUC4xx] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=NUC400_AP_512.FLM +TraceConf0=0x00000002 +TraceConf1=0x014fb180 +TraceConf2=0x00000800 +TraceConf3=0x00000000 +TraceConf4=0x00000001 +TraceConf5=0x00000000 +[NUC2xx] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=NUC200_AP_128.FLM +[NUC1311] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=NUC1311_AP_64.FLM +[NUC126] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x2000 +ProgramAlgorithm=NUC126_AP_256.FLM +[NUC121] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=NUC121_AP_32.FLM +[NUC1xx] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=NUC100_AP_128.FLM +[NUC029] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=NUC029_AP_16.FLM +[NM1820] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=NM1820_AP_17_5.FLM +[NM1810] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=NM1810_AP_29_5.FLM +[NM1500] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=NM1500_AP_128.FLM +[NM1330] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=NM1330_AP_64.FLM +[NM1320] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=NM1320_AP_32.FLM +[NM1240] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=NM1240_AP_64.FLM +[NM1230] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=NM1230_AP_64.FLM +[NM1200] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=NM1200_AP_8.FLM +[NM1120] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=NM1120_AP_29_5.FLM +[TF5100] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=TF5100_AP_64.FLM +[NDA102] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=NDA102_AP_29_5.FLM +[Nano103] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=Nano103_AP_64.FLM +[Nano100] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=Nano100_AP_64.FLM +[N576] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=N576_AP_145.FLM +[N575] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=N575_AP_145.FLM +[N572] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x2000 +ProgramAlgorithm=N572Fxxx.FLM +[N571] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x2000 +ProgramAlgorithm=N571E000.FLM +[N570] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=N570_AP_64.FLM +[N569] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=N569_AP_64.FLM +[N512] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=N512_AP_64.FLM +[Mini57] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=Mini57_AP_29_5.FLM +[Mini51] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=Mini51_AP_16.FLM +[M481] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=M481_AP_512.FLM +TraceConf0=0x00000002 +TraceConf1=0x00b71b00 +TraceConf2=0x00000800 +TraceConf3=0x00000000 +TraceConf4=0x00000001 +TraceConf5=0x00000000 +[M480LD] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=M480LD_AP_256.FLM +[M479] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=M479_AP_256.FLM +[M451] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=M451_AP_256.FLM +[M471] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Bank=0 +Erase=1 +Program=1 +Verify=1 +ResetAndRun=1 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=M471_AP_512.FLM +TraceConf0=0x00000002 +TraceConf1=0x00b71b00 +TraceConf2=0x00000800 +TraceConf3=0x00000000 +TraceConf4=0x00000001 +TraceConf5=0x00000000 +[M251] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x2000 +ProgramAlgorithm=M251_AP_192.FLM +[M2351] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=1 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=M2351_AP_512.FLM +TraceConf0=0x00000002 +TraceConf1=0x00b71b00 +TraceConf2=0x00000800 +TraceConf3=0x00000000 +TraceConf4=0x00000001 +TraceConf5=0x00000000 +[M261] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=1 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=M261_AP_512.FLM +TraceConf0=0x00000002 +TraceConf1=0x00b71b00 +TraceConf2=0x00000800 +TraceConf3=0x00000000 +TraceConf4=0x00000001 +TraceConf5=0x00000000 +[MR63] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=1 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=MR63_AP_512.FLM +TraceConf0=0x00000002 +TraceConf1=0x00b71b00 +TraceConf2=0x00000800 +TraceConf3=0x00000000 +TraceConf4=0x00000001 +TraceConf5=0x00000000 +[M2354] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Bank=0 +Erase=1 +Program=1 +Verify=1 +ResetAndRun=1 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +CheckDPM=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=M2354_AP_1M.FLM +TraceConf0=0x00000002 +TraceConf1=0x00b71b00 +TraceConf2=0x00000800 +TraceConf3=0x00000000 +TraceConf4=0x00000001 +TraceConf5=0x00000000 +[M071] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x2000 +ProgramAlgorithm=M071_AP_128.FLM +[M0564] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x2000 +ProgramAlgorithm=M0564_AP_256.FLM +[M0519] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=M0519_AP_128.FLM +[M0518] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=M0518_AP_64.FLM +[M05x] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=1 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=M0516_AP_64.FLM +[M0A21] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=1 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=M0A21_AP_32.FLM +[M030G] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=1 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +DisableTimeoutDetect=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=M030G_AP_64.FLM +[M031] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Bank=0 +Erase=1 +Program=1 +Verify=1 +ResetAndRun=1 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x800 +ProgramAlgorithm=M031_AP_128.FLM +CheckDPM=0 +DisableTimeoutDetect=0 +[NPCX] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=NPCX_AP_512.FLM +[I96000] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +Erase=2 +Program=0 +Verify=0 +ResetAndRun=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x8000 +ProgramAlgorithm= +[I94000] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm=I94000_AP_512.FLM +[ISD9300] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=ISD9300_AP_145.FLM +[I9200] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=I9200_AP_128.FLM +[ISD9xxx] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=ISD9100_AP_145.FLM +[ISD9000] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=ISD9000_AP_64.FLM +[AU9xxx] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +FlashSelect=APROM +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableFlashBreakpoint=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x1000 +ProgramAlgorithm=AU9100_AP_145.FLM +[Autodetect] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm= +[General] +Connect=0 +Reset=Autodetect +MaxClock=1MHz +MemoryVerify=0 +IOVoltage=3300 +Erase=1 +Program=1 +Verify=1 +ResetAndRun=0 +EnableLog=0 +MemAccessWhileRun=0 +RAMForAlgorithmStart=0x20000000 +RAMForAlgorithmSize=0x4000 +ProgramAlgorithm= diff --git a/bsp/nuvoton/numaker-m032ki/README.md b/bsp/nuvoton/numaker-m032ki/README.md new file mode 100644 index 0000000000..b5d2d8a97f --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/README.md @@ -0,0 +1,72 @@ +# NuMaker-M032KI + +## 1. Introduction + +The NuMaker-M032KI is an evaluation board for Nuvoton NuMicro M032 microcontrollers. The NuMaker-M032KI consists of two parts, a M032 target board and an on-board Nu-Link2-Me debugger and programmer. The NuMaker-M032KI is designed for secure evaluation, prototype development and validation with power consumption monitoring function. + +[![NuMaker-M032KI](https://i.imgur.com/6SEc2Aa.png "NuMaker-M032KI")](https://i.imgur.com/uncXX0g.jpg "NuMaker-M032KI") + +### 1.1 MCU specification + +| | Features | +| -- | -- | +| MCU | M032KIAAE | +| Operation frequency | 72MHz | +| embedded Flash size | 512KB, Dual Bank | +| SRAM size | 96kB | + +### 1.2 Interface + +| Interface | +| -- | +| Arduino UNO | +| USB 1.1 port | + +### 1.3 On-board devices + +| Device | Description | Driver supporting status | +| -- | -- | -- | +| LED | PB14 Led | Supported + +## 2. Supported compiler + +Support GCC, MDK5, IAR IDE/compilers. More information of these compiler version as following: + +| IDE/Compiler | Tested version | +| ---------- | ------------------------------------ | +| MDK5 | 5.28.0 | +| IAR | 8.32 | +| GCC | GCC 6.3.1 20170620 (Need update env) | + +Notice: Please install Nu-Link_Keil_Driver or Nu-Link_IAR_Driver for development. + +## 3. Program firmware + +### Step 1: + +At first, you need to configure ISW1 switch on the NuMaker-M032KI board. Set the four switches to ‘ON’ position. After the configuration is done, connect the NuMaker-M032KI board and your computer using the USB Micro cable. After that, window manager will show a ‘NuMicro MCU’ virtual disk. Finally, you will use this virtual disk to burn firmware. + +[![NuLinkMe](https://i.imgur.com/us0Fhhu.png "NuLinkMe")](https://i.imgur.com/us0Fhhu.png "NuLinkMe") + +[![NuMicro MCU](https://i.imgur.com/lWnNtpM.png "NuMicro MCU")](https://i.imgur.com/lWnNtpM.png "NuMicro MCU") + +### Step 2: + +A simple firmware burning method is that you can drag and drop the binary image file to NuMicro MCU virtual disk or copy the binary file to NuMicro MCU disk to burn firmware. + +[![CopyTo](https://i.imgur.com/6NfGS7m.png "CopyTo")](https://i.imgur.com/6NfGS7m.png "CopyTo") + + +## 4. Test + +You can use Tera Term terminate emulator (or other software) to type commands of RTT. All parameters of serial communication are shown in below image. Here, you can find out the corresponding port number of Nuvoton Virtual Com Port in window device manager. + +[![Serial settings](https://i.imgur.com/5NYuSNM.png "Serial settings")](https://i.imgur.com/5NYuSNM.png "Serial settings") + +## 5. Purchase +* [Nuvoton Direct](https://direct.nuvoton.com/en/numaker-m032ki) + +## 6. Resources +* [Board Introduction](https://www.nuvoton.com/board/numaker-m032ki/?index=2) +* [Download Board Schematics](https://www.nuvoton.com/resource-download.jsp?tp_GUID=UG0120191106152943) +* [Download MCU TRM](https://www.nuvoton.com/resource-download.jsp?tp_GUID=DA05-M031) diff --git a/bsp/nuvoton/numaker-m032ki/SConscript b/bsp/nuvoton/numaker-m032ki/SConscript new file mode 100644 index 0000000000..fe0ae941ae --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/SConscript @@ -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') diff --git a/bsp/nuvoton/numaker-m032ki/SConstruct b/bsp/nuvoton/numaker-m032ki/SConstruct new file mode 100644 index 0000000000..c8d9fa6fde --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/SConstruct @@ -0,0 +1,59 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rt-thread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +nuvoton_library = 'm031' +rtconfig.BSP_LIBRARY_TYPE = nuvoton_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, nuvoton_library, 'SConscript'))) + +# include nu_pkgs +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'nu_packages', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/nuvoton/numaker-m032ki/applications/SConscript b/bsp/nuvoton/numaker-m032ki/applications/SConscript new file mode 100644 index 0000000000..9ffdbcd0f9 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/applications/SConscript @@ -0,0 +1,11 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/nuvoton/numaker-m032ki/applications/main.c b/bsp/nuvoton/numaker-m032ki/applications/main.c new file mode 100644 index 0000000000..736831b7fa --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/applications/main.c @@ -0,0 +1,38 @@ +/**************************************************************************//** +* +* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-9-9 Philo First version +* +******************************************************************************/ + +#include +#include +#include + +/* defined the LEDR pin: PB14 */ +#define LEDR NU_GET_PININDEX(NU_PB, 14) + +int main(int argc, char **argv) +{ +#if defined(RT_USING_PIN) + + int counter = 0; + + /* set LEDR1 pin mode to output */ + rt_pin_mode(LEDR, PIN_MODE_OUTPUT); + + while (counter++ < 100) + { + rt_pin_write(LEDR, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LEDR, PIN_LOW); + rt_thread_mdelay(500); + } + +#endif +} diff --git a/bsp/nuvoton/numaker-m032ki/applications/mnt.c b/bsp/nuvoton/numaker-m032ki/applications/mnt.c new file mode 100644 index 0000000000..914fa657f6 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/applications/mnt.c @@ -0,0 +1,54 @@ +/**************************************************************************//** +* +* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-1-16 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(RT_USING_DFS) + #include + #include +#endif + +#if defined(PKG_USING_FAL) + #include +#endif + +#if defined(BOARD_USING_STORAGE_SPIFLASH) + #define MOUNT_POINT_SPIFLASH0 "/" +#endif + +#if defined(BOARD_USING_STORAGE_SPIFLASH) + +#if defined(RT_USB_DEVICE_MSTORAGE) +int mnt_init_spiflash0(void) +{ + rt_kprintf("Sorry, you enabled RT_USB_DEVICE_MSTORAGE option in menu, so we won't mount flash0 on /.\n"); + return 0; +} +#else + +int mnt_init_spiflash0(void) +{ + if (dfs_mount("flash0", MOUNT_POINT_SPIFLASH0, "elm", 0, 0) != 0) + { + rt_kprintf("Failed to mount elm on %s.\n", MOUNT_POINT_SPIFLASH0); + rt_kprintf("Try to execute 'mkfs -t elm flash0' first, then reboot.\n"); + goto exit_mnt_init_spiflash0; + } + rt_kprintf("mount flash0 with elmfat type: ok\n"); + +exit_mnt_init_spiflash0: + + return 0; +} +#endif +INIT_ENV_EXPORT(mnt_init_spiflash0); +#endif diff --git a/bsp/nuvoton/numaker-m032ki/board/Kconfig b/bsp/nuvoton/numaker-m032ki/board/Kconfig new file mode 100644 index 0000000000..a3f0437b7b --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/Kconfig @@ -0,0 +1,27 @@ +menu "Hardware Drivers Config" + + menu "On-chip Peripheral Drivers" + source "$BSP_DIR/../libraries/m031/rtt_port/Kconfig" + endmenu + + menu "On-board Peripheral Drivers" + + config BSP_USING_NULINKME + bool "Enable UART0 for RTT Console.(uart0)" + select BSP_USING_UART + select BSP_USING_UART0 + default y + + endmenu + + menu "Board extended module drivers" + + config BOARD_USING_STORAGE_SPIFLASH + bool "SPIFLASH supporting(over qspi0)" + select BSP_USING_QSPI + select BSP_USING_QSPI0 + default n + + endmenu + +endmenu diff --git a/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_clkcfg.h b/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_clkcfg.h new file mode 100644 index 0000000000..3a712eee97 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_clkcfg.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * @file nutool_clkcfg.h + * @version V1.05 + * @Date 2020/09/15-18:09:27 + * @brief NuMicro generated code file + * + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2013-2020 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NUTOOL_CLKCFG_H__ +#define __NUTOOL_CLKCFG_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif +#undef __HXT +#define __HXT (32000000UL) /*!< High Speed External Crystal Clock Frequency */ + +#ifdef __cplusplus +} +#endif +#endif /*__NUTOOL_CLKCFG_H__*/ + +/*** (C) COPYRIGHT 2013-2020 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.c b/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.c new file mode 100644 index 0000000000..7f90843d34 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.c @@ -0,0 +1,506 @@ +/**************************************************************************** + * @file nutool_modclkcfg.c + * @version V1.05 + * @Date 2020/09/30-13:56:58 + * @brief NuMicro generated code file + * + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2013-2020 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +/******************** +MCU:M032SE3AE(ULQFP64) +Base Clocks: +LIRC:38.4000kHz +HIRC:48MHz +LXT:32.7680kHz +HXT:12MHz +PLL:72MHz +HCLK:48MHz +PCLK0:48MHz +PCLK1:48MHz +Enabled-Module Frequencies: +ACMP01=Bus Clock(PCLK1):48MHz +ADC=Bus Clock(PCLK1):48MHz/Engine Clock:48MHz +CRC=Bus Clock(HCLK):48MHz +EBI=Bus Clock(HCLK):48MHz +HDIV=Bus Clock(HCLK):48MHz +I2C0=Bus Clock(PCLK0):48MHz +I2C1=Bus Clock(PCLK1):48MHz +ISP=Bus Clock(HCLK):48MHz/Engine Clock:48MHz +PDMA=Bus Clock(HCLK):48MHz +PWM0=Bus Clock(PCLK0):48MHz/Engine Clock:48MHz +PWM1=Bus Clock(PCLK1):48MHz/Engine Clock:48MHz +SPI0=Bus Clock(PCLK1):48MHz/Engine Clock:48MHz +SYSTICK=Bus Clock(HCLK):48MHz/Engine Clock:24MHz +TMR0=Bus Clock(PCLK0):48MHz/Engine Clock:48MHz +TMR1=Bus Clock(PCLK0):48MHz/Engine Clock:48MHz +TMR2=Bus Clock(PCLK1):48MHz/Engine Clock:48MHz +TMR3=Bus Clock(PCLK1):48MHz/Engine Clock:48MHz +UART0=Bus Clock(PCLK0):48MHz/Engine Clock:48MHz +UART1=Bus Clock(PCLK1):48MHz/Engine Clock:48MHz +UART2=Bus Clock(PCLK0):48MHz/Engine Clock:48MHz +USBD=Bus Clock(PCLK0):48MHz/Engine Clock:48MHz +USCI0=Bus Clock(PCLK0):48MHz +WDT=Bus Clock(PCLK0):48MHz/Engine Clock:38.4000kHz +WWDT=Bus Clock(PCLK0):48MHz/Engine Clock:23.4375kHz +********************/ + +#include "M031Series.h" + +void nutool_modclkcfg_init_acmp01(void) +{ + CLK_EnableModuleClock(ACMP01_MODULE); + + return; +} + +void nutool_modclkcfg_deinit_acmp01(void) +{ + CLK_DisableModuleClock(ACMP01_MODULE); + + return; +} + +void nutool_modclkcfg_init_adc(void) +{ + CLK_EnableModuleClock(ADC_MODULE); + CLK_SetModuleClock(ADC_MODULE, CLK_CLKSEL2_ADCSEL_PCLK1, CLK_CLKDIV0_ADC(1)); + + return; +} + +void nutool_modclkcfg_deinit_adc(void) +{ + CLK_DisableModuleClock(ADC_MODULE); + + return; +} + +void nutool_modclkcfg_init_crc(void) +{ + CLK_EnableModuleClock(CRC_MODULE); + + return; +} + +void nutool_modclkcfg_deinit_crc(void) +{ + CLK_DisableModuleClock(CRC_MODULE); + + return; +} + +void nutool_modclkcfg_init_ebi(void) +{ + CLK_EnableModuleClock(EBI_MODULE); + + return; +} + +void nutool_modclkcfg_deinit_ebi(void) +{ + CLK_DisableModuleClock(EBI_MODULE); + + return; +} + +void nutool_modclkcfg_init_hdiv(void) +{ + CLK_EnableModuleClock(HDIV_MODULE); + + return; +} + +void nutool_modclkcfg_deinit_hdiv(void) +{ + CLK_DisableModuleClock(HDIV_MODULE); + + return; +} + +void nutool_modclkcfg_init_i2c0(void) +{ + CLK_EnableModuleClock(I2C0_MODULE); + + return; +} + +void nutool_modclkcfg_deinit_i2c0(void) +{ + CLK_DisableModuleClock(I2C0_MODULE); + + return; +} + +void nutool_modclkcfg_init_i2c1(void) +{ + CLK_EnableModuleClock(I2C1_MODULE); + + return; +} + +void nutool_modclkcfg_deinit_i2c1(void) +{ + CLK_DisableModuleClock(I2C1_MODULE); + + return; +} + +void nutool_modclkcfg_init_isp(void) +{ + CLK_EnableModuleClock(ISP_MODULE); + + return; +} + +void nutool_modclkcfg_deinit_isp(void) +{ + CLK_DisableModuleClock(ISP_MODULE); + + return; +} + +void nutool_modclkcfg_init_pdma(void) +{ + CLK_EnableModuleClock(PDMA_MODULE); + + return; +} + +void nutool_modclkcfg_deinit_pdma(void) +{ + CLK_DisableModuleClock(PDMA_MODULE); + + return; +} + +void nutool_modclkcfg_init_pwm0(void) +{ + CLK_EnableModuleClock(PWM0_MODULE); + CLK_SetModuleClock(PWM0_MODULE, CLK_CLKSEL2_PWM0SEL_PCLK0, MODULE_NoMsk); + + return; +} + +void nutool_modclkcfg_deinit_pwm0(void) +{ + CLK_DisableModuleClock(PWM0_MODULE); + + return; +} + +void nutool_modclkcfg_init_pwm1(void) +{ + CLK_EnableModuleClock(PWM1_MODULE); + CLK_SetModuleClock(PWM1_MODULE, CLK_CLKSEL2_PWM1SEL_PCLK1, MODULE_NoMsk); + + return; +} + +void nutool_modclkcfg_deinit_pwm1(void) +{ + CLK_DisableModuleClock(PWM1_MODULE); + + return; +} + +void nutool_modclkcfg_init_spi0(void) +{ + CLK_EnableModuleClock(SPI0_MODULE); + CLK_SetModuleClock(SPI0_MODULE, CLK_CLKSEL2_SPI0SEL_PCLK1, MODULE_NoMsk); + + return; +} + +void nutool_modclkcfg_deinit_spi0(void) +{ + CLK_DisableModuleClock(SPI0_MODULE); + + return; +} + +void nutool_modclkcfg_init_systick(void) +{ + CLK_EnableSysTick(CLK_CLKSEL0_STCLKSEL_HIRC_DIV2, 0); + + return; +} + +void nutool_modclkcfg_deinit_systick(void) +{ + CLK_DisableSysTick(); + + return; +} + +void nutool_modclkcfg_init_tmr0(void) +{ + CLK_EnableModuleClock(TMR0_MODULE); + CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_HIRC, MODULE_NoMsk); + + return; +} + +void nutool_modclkcfg_deinit_tmr0(void) +{ + CLK_DisableModuleClock(TMR0_MODULE); + + return; +} + +void nutool_modclkcfg_init_tmr1(void) +{ + CLK_EnableModuleClock(TMR1_MODULE); + CLK_SetModuleClock(TMR1_MODULE, CLK_CLKSEL1_TMR1SEL_HIRC, MODULE_NoMsk); + + return; +} + +void nutool_modclkcfg_deinit_tmr1(void) +{ + CLK_DisableModuleClock(TMR1_MODULE); + + return; +} + +void nutool_modclkcfg_init_tmr2(void) +{ + CLK_EnableModuleClock(TMR2_MODULE); + CLK_SetModuleClock(TMR2_MODULE, CLK_CLKSEL1_TMR2SEL_HIRC, MODULE_NoMsk); + + return; +} + +void nutool_modclkcfg_deinit_tmr2(void) +{ + CLK_DisableModuleClock(TMR2_MODULE); + + return; +} + +void nutool_modclkcfg_init_tmr3(void) +{ + CLK_EnableModuleClock(TMR3_MODULE); + CLK_SetModuleClock(TMR3_MODULE, CLK_CLKSEL1_TMR3SEL_HIRC, MODULE_NoMsk); + + return; +} + +void nutool_modclkcfg_deinit_tmr3(void) +{ + CLK_DisableModuleClock(TMR3_MODULE); + + return; +} + +void nutool_modclkcfg_init_uart0(void) +{ + CLK_EnableModuleClock(UART0_MODULE); + CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HXT, CLK_CLKDIV0_UART0(1)); + + return; +} + +void nutool_modclkcfg_deinit_uart0(void) +{ + CLK_DisableModuleClock(UART0_MODULE); + + return; +} + +void nutool_modclkcfg_init_uart1(void) +{ + CLK_EnableModuleClock(UART1_MODULE); + CLK_SetModuleClock(UART1_MODULE, CLK_CLKSEL1_UART1SEL_PCLK1, CLK_CLKDIV0_UART1(1)); + + return; +} + +void nutool_modclkcfg_deinit_uart1(void) +{ + CLK_DisableModuleClock(UART1_MODULE); + + return; +} + +void nutool_modclkcfg_init_uart2(void) +{ + CLK_EnableModuleClock(UART2_MODULE); + CLK_SetModuleClock(UART2_MODULE, CLK_CLKSEL3_UART2SEL_PCLK0, CLK_CLKDIV4_UART2(1)); + + return; +} + +void nutool_modclkcfg_deinit_uart2(void) +{ + CLK_DisableModuleClock(UART2_MODULE); + + return; +} + +void nutool_modclkcfg_init_usbd(void) +{ + CLK_EnableModuleClock(USBD_MODULE); + CLK_SetModuleClock(USBD_MODULE, CLK_CLKSEL0_USBDSEL_HIRC, MODULE_NoMsk); + + return; +} + +void nutool_modclkcfg_deinit_usbd(void) +{ + CLK_DisableModuleClock(USBD_MODULE); + + return; +} + +void nutool_modclkcfg_init_usci0(void) +{ + CLK_EnableModuleClock(USCI0_MODULE); + + return; +} + +void nutool_modclkcfg_deinit_usci0(void) +{ + CLK_DisableModuleClock(USCI0_MODULE); + + return; +} + +void nutool_modclkcfg_init_wdt(void) +{ + CLK_EnableModuleClock(WDT_MODULE); + CLK_SetModuleClock(WDT_MODULE, CLK_CLKSEL1_WDTSEL_LIRC, MODULE_NoMsk); + + return; +} + +void nutool_modclkcfg_deinit_wdt(void) +{ + CLK_DisableModuleClock(WDT_MODULE); + + return; +} + +void nutool_modclkcfg_init_wwdt(void) +{ + CLK_EnableModuleClock(WWDT_MODULE); + CLK_SetModuleClock(WWDT_MODULE, CLK_CLKSEL1_WWDTSEL_HCLK_DIV2048, MODULE_NoMsk); + + return; +} + +void nutool_modclkcfg_deinit_wwdt(void) +{ + CLK_DisableModuleClock(WWDT_MODULE); + + return; +} + +void nutool_modclkcfg_init_rtc(void) +{ + CLK_EnableModuleClock(RTC_MODULE); + + return; +} + +void nutool_modclkcfg_deinit_rtc(void) +{ + CLK_DisableModuleClock(RTC_MODULE); + + return; +} + +void nutool_modclkcfg_init_base(void) +{ + /* Enable clock source */ + CLK_EnableXtalRC(CLK_PWRCTL_LIRCEN_Msk | CLK_PWRCTL_HIRCEN_Msk | CLK_PWRCTL_LXTEN_Msk | CLK_PWRCTL_HXTEN_Msk); + + /* Waiting for clock source ready */ + CLK_WaitClockReady(CLK_STATUS_LIRCSTB_Msk | CLK_STATUS_HIRCSTB_Msk | CLK_STATUS_LXTSTB_Msk | CLK_STATUS_HXTSTB_Msk); + + /* Disable PLL first to avoid unstable when setting PLL */ + CLK_DisablePLL(); + + /* Set PLL frequency */ + CLK->PLLCTL = (CLK->PLLCTL & ~(0x000FFFFFul)) | 0x0008C02Eul; + + /* Waiting for PLL ready */ + CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk); + + /* If the defines do not exist in your project, please refer to the related clk.h in the Header folder appended to the tool package. */ + /* Set HCLK clock */ + CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1)); + + /* Set PCLK-related clock */ + CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV1 | CLK_PCLKDIV_APB1DIV_DIV1); + + return; +} + +void nutool_modclkcfg_init(void) +{ + /*---------------------------------------------------------------------------------------------------------*/ + /* Init System Clock */ + /*---------------------------------------------------------------------------------------------------------*/ + //CLK->PWRCTL = (CLK->PWRCTL & ~(0x0000000Ful)) | 0x0231001Ful; + //CLK->PLLCTL = (CLK->PLLCTL & ~(0x000FFFFFul)) | 0x0008C02Eul; + //CLK->CLKDIV0 = (CLK->CLKDIV0 & ~(0x00FFFFFFul)) | 0x00000000ul; + //CLK->CLKDIV4 = (CLK->CLKDIV4 & ~(0x0000000Ful)) | 0x00000000ul; + //CLK->PCLKDIV = (CLK->PCLKDIV & ~(0x00000077ul)) | 0x00000000ul; + //CLK->CLKSEL0 = (CLK->CLKSEL0 & ~(0x0000013Ful)) | 0x0000003Ful; + //CLK->CLKSEL1 = (CLK->CLKSEL1 & ~(0x7777777Ful)) | 0x4477773Bul; + //CLK->CLKSEL2 = (CLK->CLKSEL2 & ~(0x00300033ul)) | 0x00200023ul; + //CLK->CLKSEL3 = (CLK->CLKSEL3 & ~(0x07000000ul)) | 0x04000000ul; + //CLK->AHBCLK = (CLK->AHBCLK & ~(0x0000009Eul)) | 0x0000009Eul; + //CLK->APBCLK0 = (CLK->APBCLK0 & ~(0x180723FDul)) | 0x180723BDul; + //CLK->APBCLK1 = (CLK->APBCLK1 & ~(0x00030100ul)) | 0x00030100ul; + //CLK->CLKOCTL = (CLK->CLKOCTL & ~(0x0000003Ful)) | 0x00000000ul; + //SysTick->CTRL = (SysTick->CTRL & ~(0x00000005ul)) | 0x00000001ul; + + /* Unlock protected registers */ + SYS_UnlockReg(); + + /* Enable base clock */ + nutool_modclkcfg_init_base(); + + /* Enable module clock and set clock source */ + nutool_modclkcfg_init_acmp01(); + nutool_modclkcfg_init_adc(); + nutool_modclkcfg_init_crc(); + nutool_modclkcfg_init_ebi(); + nutool_modclkcfg_init_hdiv(); + nutool_modclkcfg_init_i2c0(); + nutool_modclkcfg_init_i2c1(); + nutool_modclkcfg_init_isp(); + nutool_modclkcfg_init_pdma(); + nutool_modclkcfg_init_pwm0(); + nutool_modclkcfg_init_pwm1(); + nutool_modclkcfg_init_spi0(); + nutool_modclkcfg_init_systick(); + nutool_modclkcfg_init_tmr0(); + nutool_modclkcfg_init_tmr1(); + nutool_modclkcfg_init_tmr2(); + nutool_modclkcfg_init_tmr3(); + nutool_modclkcfg_init_uart0(); + nutool_modclkcfg_init_uart1(); + nutool_modclkcfg_init_uart2(); + nutool_modclkcfg_init_usbd(); + nutool_modclkcfg_init_usci0(); + nutool_modclkcfg_init_wdt(); + nutool_modclkcfg_init_wwdt(); + nutool_modclkcfg_init_rtc(); + + /* Update System Core Clock */ + /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */ + SystemCoreClockUpdate(); + + /* Lock protected registers */ + SYS_LockReg(); + + return; +} + +/*** (C) COPYRIGHT 2013-2020 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.cfg b/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.cfg new file mode 100644 index 0000000000..7148794bc3 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.cfg @@ -0,0 +1,33 @@ +/**************************************************************************** + * @file nutool_modclkcfg.cfg + * @version V1.05 + * @Date 2020/09/15-18:09:27 + * @brief NuMicro clock config file + * + * @note Please do not modify this file. + * Otherwise, it may not be loaded successfully. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2013-2020 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +MCU:M032SE3AE(ULQFP64) +Reg:CLKDIV0 = 0x00000000 +Reg:CLKDIV4 = 0x00000000 +Reg:PCLKDIV = 0x00000000 +Reg:CLKSEL0 = 0x0000001F +Reg:CLKSEL1 = 0x4477773B +Reg:CLKSEL2 = 0x00200020 +Reg:CLKSEL3 = 0x04000000 +Reg:PWRCTL = 0x0231001F +Reg:AHBCLK = 0x0000009E +Reg:APBCLK0 = 0x180723BD +Reg:APBCLK1 = 0x00030100 +Reg:PLLCTL = 0x0000C25E +Reg:CLKOCTL = 0x00000000 +Reg:SYST_CTRL = 0x00000000 +LXT:32768 +HXT:12000000 +PLL:96000000 +Step:4 +/*** (C) COPYRIGHT 2013-2020 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.h b/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.h new file mode 100644 index 0000000000..1f010e13ef --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/NuClockConfig/nutool_modclkcfg.h @@ -0,0 +1,72 @@ +/**************************************************************************** + * @file nutool_modclkcfg.h + * @version V1.05 + * @Date 2020/09/15-18:09:27 + * @brief NuMicro generated code file + * + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2013-2020 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NUTOOL_MODCLKCFG_H__ +#define __NUTOOL_MODCLKCFG_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif +void nutool_modclkcfg_init_acmp01(void); +void nutool_modclkcfg_deinit_acmp01(void); +void nutool_modclkcfg_init_adc(void); +void nutool_modclkcfg_deinit_adc(void); +void nutool_modclkcfg_init_crc(void); +void nutool_modclkcfg_deinit_crc(void); +void nutool_modclkcfg_init_ebi(void); +void nutool_modclkcfg_deinit_ebi(void); +void nutool_modclkcfg_init_hdiv(void); +void nutool_modclkcfg_deinit_hdiv(void); +void nutool_modclkcfg_init_i2c0(void); +void nutool_modclkcfg_deinit_i2c0(void); +void nutool_modclkcfg_init_i2c1(void); +void nutool_modclkcfg_deinit_i2c1(void); +void nutool_modclkcfg_init_isp(void); +void nutool_modclkcfg_deinit_isp(void); +void nutool_modclkcfg_init_pdma(void); +void nutool_modclkcfg_deinit_pdma(void); +void nutool_modclkcfg_init_pwm0(void); +void nutool_modclkcfg_deinit_pwm0(void); +void nutool_modclkcfg_init_pwm1(void); +void nutool_modclkcfg_deinit_pwm1(void); +void nutool_modclkcfg_init_spi0(void); +void nutool_modclkcfg_deinit_spi0(void); +void nutool_modclkcfg_init_tmr0(void); +void nutool_modclkcfg_deinit_tmr0(void); +void nutool_modclkcfg_init_tmr1(void); +void nutool_modclkcfg_deinit_tmr1(void); +void nutool_modclkcfg_init_tmr2(void); +void nutool_modclkcfg_deinit_tmr2(void); +void nutool_modclkcfg_init_tmr3(void); +void nutool_modclkcfg_deinit_tmr3(void); +void nutool_modclkcfg_init_uart0(void); +void nutool_modclkcfg_deinit_uart0(void); +void nutool_modclkcfg_init_uart1(void); +void nutool_modclkcfg_deinit_uart1(void); +void nutool_modclkcfg_init_uart2(void); +void nutool_modclkcfg_deinit_uart2(void); +void nutool_modclkcfg_init_usbd(void); +void nutool_modclkcfg_deinit_usbd(void); +void nutool_modclkcfg_init_usci0(void); +void nutool_modclkcfg_deinit_usci0(void); +void nutool_modclkcfg_init_wdt(void); +void nutool_modclkcfg_deinit_wdt(void); +void nutool_modclkcfg_init_wwdt(void); +void nutool_modclkcfg_deinit_wwdt(void); +void nutool_modclkcfg_init_base(void); +void nutool_modclkcfg_init(void); +#ifdef __cplusplus +} +#endif +#endif /*__NUTOOL_MODCLKCFG_H__*/ + +/*** (C) COPYRIGHT 2013-2020 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.c b/bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.c new file mode 100644 index 0000000000..0c4d2e3e4d --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.c @@ -0,0 +1,233 @@ +/**************************************************************************** + * @file nutool_pincfg.c + * @version V1.21 + * @Date 2021/03/03-17:36:00 + * @brief NuMicro generated code file + * + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2013-2020 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +/******************** +MCU:M032KIAAE(LQFP128) +Pin Configuration: +Pin1:ADC0_CH5 +Pin2:ADC0_CH4 +Pin3:UART1_TXD +Pin4:UART1_RXD +Pin9:ADC0_CH1 +Pin10:ADC0_CH0 +Pin31:X32_IN +Pin32:X32_OUT +Pin37:XT1_IN +Pin38:XT1_OUT +Pin50:PWM1_CH4 +Pin51:PWM1_CH5 +Pin55:QSPI0_MISO1 +Pin56:QSPI0_MOSI1 +Pin57:QSPI0_SS +Pin58:QSPI0_CLK +Pin59:QSPI0_MISO0 +Pin60:QSPI0_MOSI0 +Pin65:ICE_DAT +Pin66:ICE_CLK +Pin69:PWM1_CH0 +Pin70:PWM1_CH1 +Pin71:PWM1_CH2 +Pin72:PWM1_CH3 +Pin73:I2C0_SCL +Pin74:I2C0_SDA +Pin118:UART0_TXD +Pin119:UART0_RXD +Pin127:ADC0_CH7 +Pin128:ADC0_CH6 +********************/ + +#include "M031Series.h" + +void nutool_pincfg_init_ice(void) +{ + SYS->GPF_MFPL &= ~(SYS_GPF_MFPL_PF1MFP_Msk | SYS_GPF_MFPL_PF0MFP_Msk); + SYS->GPF_MFPL |= (SYS_GPF_MFPL_PF1MFP_ICE_CLK | SYS_GPF_MFPL_PF0MFP_ICE_DAT); + + return; +} + +void nutool_pincfg_deinit_ice(void) +{ + SYS->GPF_MFPL &= ~(SYS_GPF_MFPL_PF1MFP_Msk | SYS_GPF_MFPL_PF0MFP_Msk); + + return; +} + +void nutool_pincfg_init_uart0(void) +{ + SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB13MFP_Msk | SYS_GPB_MFPH_PB12MFP_Msk); + SYS->GPB_MFPH |= (SYS_GPB_MFPH_PB13MFP_UART0_TXD | SYS_GPB_MFPH_PB12MFP_UART0_RXD); + + return; +} + +void nutool_pincfg_deinit_uart0(void) +{ + SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB13MFP_Msk | SYS_GPB_MFPH_PB12MFP_Msk); + + return; +} + +void nutool_pincfg_init_x32(void) +{ + SYS->GPF_MFPL &= ~(SYS_GPF_MFPL_PF5MFP_Msk | SYS_GPF_MFPL_PF4MFP_Msk); + SYS->GPF_MFPL |= (SYS_GPF_MFPL_PF5MFP_X32_IN | SYS_GPF_MFPL_PF4MFP_X32_OUT); + + return; +} + +void nutool_pincfg_deinit_x32(void) +{ + SYS->GPF_MFPL &= ~(SYS_GPF_MFPL_PF5MFP_Msk | SYS_GPF_MFPL_PF4MFP_Msk); + + return; +} + +void nutool_pincfg_init_xt1(void) +{ + SYS->GPF_MFPL &= ~(SYS_GPF_MFPL_PF3MFP_Msk | SYS_GPF_MFPL_PF2MFP_Msk); + SYS->GPF_MFPL |= (SYS_GPF_MFPL_PF3MFP_XT1_IN | SYS_GPF_MFPL_PF2MFP_XT1_OUT); + + return; +} + +void nutool_pincfg_deinit_xt1(void) +{ + SYS->GPF_MFPL &= ~(SYS_GPF_MFPL_PF3MFP_Msk | SYS_GPF_MFPL_PF2MFP_Msk); + + return; +} + +void nutool_pincfg_init_qspi0(void) +{ + SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA0MFP_Msk | SYS_GPA_MFPL_PA1MFP_Msk | SYS_GPA_MFPL_PA2MFP_Msk | SYS_GPA_MFPL_PA3MFP_Msk | + SYS_GPA_MFPL_PA4MFP_Msk | SYS_GPA_MFPL_PA5MFP_Msk); + + SYS->GPA_MFPL |= (SYS_GPA_MFPL_PA0MFP_QSPI0_MOSI0 | SYS_GPA_MFPL_PA1MFP_QSPI0_MISO0 | + SYS_GPA_MFPL_PA2MFP_QSPI0_CLK | SYS_GPA_MFPL_PA3MFP_QSPI0_SS | + SYS_GPA_MFPL_PA4MFP_QSPI0_MOSI1 | SYS_GPA_MFPL_PA5MFP_QSPI0_MISO1); + + /* pull high qspi quad mode pins. */ + GPIO_SetMode(PA, BIT4 | BIT5, GPIO_MODE_QUASI); + +} + +void nutool_pincfg_deinit_qspi0(void) +{ + SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA0MFP_Msk | SYS_GPA_MFPL_PA1MFP_Msk | SYS_GPA_MFPL_PA2MFP_Msk | SYS_GPA_MFPL_PA3MFP_Msk | + SYS_GPA_MFPL_PA4MFP_Msk | SYS_GPA_MFPL_PA5MFP_Msk); +} + +void nutool_pincfg_init_i2c0(void) +{ + SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC0MFP_Msk | SYS_GPC_MFPL_PC1MFP_Msk); + SYS->GPC_MFPL |= (SYS_GPC_MFPL_PC0MFP_I2C0_SDA | SYS_GPC_MFPL_PC1MFP_I2C0_SCL); +} + +void nutool_pincfg_deinit_i2c0(void) +{ + SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC0MFP_Msk | SYS_GPC_MFPL_PC1MFP_Msk); +} + +void nutool_pincfg_init_adc0(void) +{ + SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB0MFP_Msk | SYS_GPB_MFPL_PB1MFP_Msk | SYS_GPB_MFPL_PB4MFP_Msk | + SYS_GPB_MFPL_PB5MFP_Msk | SYS_GPB_MFPL_PB6MFP_Msk | SYS_GPB_MFPL_PB7MFP_Msk); + + SYS->GPB_MFPL |= (SYS_GPB_MFPL_PB0MFP_ADC_CH0 | SYS_GPB_MFPL_PB1MFP_ADC_CH1 | SYS_GPB_MFPL_PB4MFP_ADC_CH4 | + SYS_GPB_MFPL_PB5MFP_ADC_CH5 | SYS_GPB_MFPL_PB6MFP_ADC_CH6 | SYS_GPB_MFPL_PB7MFP_ADC_CH7); + + /* Disable digital path on these ADC pins */ + GPIO_DISABLE_DIGITAL_PATH(PB, BIT0 | BIT1 | BIT4 | BIT5 | BIT6 | BIT7); +} + +void nutool_pincfg_deinit_adc0(void) +{ + SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB0MFP_Msk | SYS_GPB_MFPL_PB1MFP_Msk | SYS_GPB_MFPL_PB4MFP_Msk | + SYS_GPB_MFPL_PB5MFP_Msk | SYS_GPB_MFPL_PB6MFP_Msk | SYS_GPB_MFPL_PB7MFP_Msk); + + /* Enable digital path on these ADC pins */ + GPIO_ENABLE_DIGITAL_PATH(PB, BIT0 | BIT1 | BIT4 | BIT5 | BIT6 | BIT7); +} + +void nutool_pincfg_init_pwm0(void) +{ + SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk); + SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC2MFP_Msk | SYS_GPC_MFPL_PC3MFP_Msk | SYS_GPC_MFPL_PC4MFP_Msk | SYS_GPC_MFPL_PC5MFP_Msk); + + SYS->GPA_MFPL |= (SYS_GPA_MFPL_PA6MFP_PWM1_CH5 | SYS_GPA_MFPL_PA7MFP_PWM1_CH4); + SYS->GPC_MFPL |= (SYS_GPC_MFPL_PC2MFP_PWM1_CH3 | SYS_GPC_MFPL_PC3MFP_PWM1_CH2 | SYS_GPC_MFPL_PC4MFP_PWM1_CH1 | SYS_GPC_MFPL_PC5MFP_PWM1_CH0); +} + +void nutool_pincfg_deinit_pwm0(void) +{ + SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk); + SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC2MFP_Msk | SYS_GPC_MFPL_PC3MFP_Msk | SYS_GPC_MFPL_PC4MFP_Msk | SYS_GPC_MFPL_PC5MFP_Msk); +} + +void nutool_pincfg_init_uart1(void) +{ + SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB2MFP_Msk | SYS_GPB_MFPL_PB3MFP_Msk); + SYS->GPB_MFPL |= (SYS_GPB_MFPL_PB2MFP_UART1_RXD | SYS_GPB_MFPL_PB3MFP_UART1_TXD); +} + +void nutool_pincfg_deinit_uart1(void) +{ + SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB2MFP_Msk | SYS_GPB_MFPL_PB3MFP_Msk); +} + +void nutool_pincfg_init(void) +{ + //SYS->GPA_MFPH = 0x00000000UL; + //SYS->GPA_MFPL = 0xBB333333UL; + //SYS->GPB_MFPH = 0x00660000UL; + //SYS->GPB_MFPL = 0x11116611UL; + //SYS->GPC_MFPH = 0x00000000UL; + //SYS->GPC_MFPL = 0x00CCCC99UL; + //SYS->GPD_MFPH = 0x00000000UL; + //SYS->GPD_MFPL = 0x00000000UL; + //SYS->GPE_MFPH = 0x00000000UL; + //SYS->GPE_MFPL = 0x00000000UL; + //SYS->GPF_MFPH = 0x00000000UL; + //SYS->GPF_MFPL = 0x00AAAAEEUL; + //SYS->GPG_MFPH = 0x00000000UL; + //SYS->GPG_MFPL = 0x00000000UL; + //SYS->GPH_MFPH = 0x00000000UL; + //SYS->GPH_MFPL = 0x00000000UL; + + nutool_pincfg_init_ice(); + nutool_pincfg_init_uart0(); + nutool_pincfg_init_x32(); + nutool_pincfg_init_xt1(); + nutool_pincfg_init_qspi0(); + nutool_pincfg_init_i2c0(); + nutool_pincfg_init_adc0(); + nutool_pincfg_init_pwm0(); + nutool_pincfg_init_uart1(); + + return; +} + +void nutool_pincfg_deinit(void) +{ + nutool_pincfg_deinit_ice(); + nutool_pincfg_deinit_uart0(); + nutool_pincfg_deinit_x32(); + nutool_pincfg_deinit_xt1(); + nutool_pincfg_deinit_qspi0(); + nutool_pincfg_deinit_i2c0(); + nutool_pincfg_deinit_adc0(); + nutool_pincfg_deinit_pwm0(); + nutool_pincfg_deinit_uart1(); + + return; +} +/*** (C) COPYRIGHT 2013-2020 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.cfg b/bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.cfg new file mode 100644 index 0000000000..813cfcca31 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.cfg @@ -0,0 +1,159 @@ +/**************************************************************************** + * @file nutool_pincfg.cfg + * @version V1.21 + * @Date 2021/03/03-17:36:00 + * @brief NuMicro config file + * + * @note Please do not modify this file. + * Otherwise, it may not be loaded successfully. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2013-2021 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ +MCU:M032KIAAE(LQFP128) +Pin1:ADC0_CH5 +Pin2:ADC0_CH4 +Pin3:UART1_TXD +Pin4:UART1_RXD +Pin5:PC.12 +Pin6:PC.11 +Pin7:PC.10 +Pin8:PC.9 +Pin9:ADC0_CH1 +Pin10:ADC0_CH0 +Pin11:VSS +Pin12:VDD +Pin13:PA.11 +Pin14:PA.10 +Pin15:PA.9 +Pin16:PA.8 +Pin17:PC.13 +Pin18:PD.12 +Pin19:PD.11 +Pin20:PD.10 +Pin21:PG.2 +Pin22:PG.3 +Pin23:PG.4 +Pin24:PF.11 +Pin25:PF.10 +Pin26:PF.9 +Pin27:PF.8 +Pin28:PF.7 +Pin29:PF.6 +Pin30:PF.14 +Pin31:X32_IN +Pin32:X32_OUT +Pin33:PH.4 +Pin34:PH.5 +Pin35:PH.6 +Pin36:PH.7 +Pin37:XT1_IN +Pin38:XT1_OUT +Pin39:VSS +Pin40:VDD +Pin41:PE.8 +Pin42:PE.9 +Pin43:PE.10 +Pin44:PE.11 +Pin45:PE.12 +Pin46:PE.13 +Pin47:PC.8 +Pin48:PC.7 +Pin49:PC.6 +Pin50:PWM1_CH4 +Pin51:PWM1_CH5 +Pin52:VSS +Pin53:VDD +Pin54:PD.15 +Pin55:QSPI0_MISO1 +Pin56:QSPI0_MOSI1 +Pin57:QSPI0_SS +Pin58:QSPI0_CLK +Pin59:QSPI0_MISO0 +Pin60:QSPI0_MOSI0 +Pin61:PF.15 +Pin62:PE.14 +Pin63:PE.15 +Pin64:nRESET +Pin65:ICE_DAT +Pin66:ICE_CLK +Pin67:PD.9 +Pin68:PD.8 +Pin69:PWM1_CH0 +Pin70:PWM1_CH1 +Pin71:PWM1_CH2 +Pin72:PWM1_CH3 +Pin73:I2C0_SCL +Pin74:I2C0_SDA +Pin75:VSS +Pin76:VDD +Pin77:PG.9 +Pin78:PG.10 +Pin79:PG.11 +Pin80:PG.12 +Pin81:PG.13 +Pin82:PG.14 +Pin83:PG.15 +Pin84:PD.7 +Pin85:PD.6 +Pin86:PD.5 +Pin87:PD.4 +Pin88:PD.3 +Pin89:PD.2 +Pin90:PD.1 +Pin91:PD.0 +Pin92:PD.13 +Pin93:USB_VBUS +Pin94:USB_D- +Pin95:USB_D+ +Pin96:USB_VDD33_CAP +Pin97:PE.7 +Pin98:PE.6 +Pin99:PE.5 +Pin100:PE.4 +Pin101:PE.3 +Pin102:PE.2 +Pin103:VSS +Pin104:VDD +Pin105:PE.1 +Pin106:PE.0 +Pin107:PH.8 +Pin108:PH.9 +Pin109:PH.10 +Pin110:PH.11 +Pin111:PD.14 +Pin112:VSS +Pin113:LDO_CAP +Pin114:VDD +Pin115:PC.14 +Pin116:PB.15 +Pin117:PB.14 +Pin118:UART0_TXD +Pin119:UART0_RXD +Pin120:AVDD +Pin121:VREF +Pin122:AVSS +Pin123:PB.11 +Pin124:PB.10 +Pin125:PB.9 +Pin126:PB.8 +Pin127:ADC0_CH7 +Pin128:ADC0_CH6 +SYS->GPA_MFPH = 0x00000000 +SYS->GPA_MFPL = 0xBB333333 +SYS->GPB_MFPH = 0x00660000 +SYS->GPB_MFPL = 0x11116611 +SYS->GPC_MFPH = 0x00000000 +SYS->GPC_MFPL = 0x00CCCC99 +SYS->GPD_MFPH = 0x00000000 +SYS->GPD_MFPL = 0x00000000 +SYS->GPE_MFPH = 0x00000000 +SYS->GPE_MFPL = 0x00000000 +SYS->GPF_MFPH = 0x00000000 +SYS->GPF_MFPL = 0x00AAAAEE +SYS->GPG_MFPH = 0x00000000 +SYS->GPG_MFPL = 0x00000000 +SYS->GPH_MFPH = 0x00000000 +SYS->GPH_MFPL = 0x00000000 +/*** (C) COPYRIGHT 2013-2021 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.h b/bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.h new file mode 100644 index 0000000000..d0e4a8f2d9 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/NuPinConfig/nutool_pincfg.h @@ -0,0 +1,44 @@ +/**************************************************************************** + * @file nutool_pincfg.h + * @version V1.21 + * @Date 2021/03/03-17:36:00 + * @brief NuMicro generated code file + * + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2013-2020 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +#ifndef __NUTOOL_PINCFG_H__ +#define __NUTOOL_PINCFG_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif +void nutool_pincfg_init_ice(void); +void nutool_pincfg_deinit_ice(void); +void nutool_pincfg_init_uart0(void); +void nutool_pincfg_deinit_uart0(void); +void nutool_pincfg_init_x32(void); +void nutool_pincfg_deinit_x32(void); +void nutool_pincfg_init_xt1(void); +void nutool_pincfg_deinit_xt1(void); +void nutool_pincfg_init_qspi0(void); +void nutool_pincfg_deinit_qspi0(void); +void nutool_pincfg_init_i2c0(void); +void nutool_pincfg_deinit_i2c0(void); +void nutool_pincfg_init_adc0(void); +void nutool_pincfg_deinit_adc0(void); +void nutool_pincfg_init_pwm0(void); +void nutool_pincfg_deinit_pwm0(void); +void nutool_pincfg_init_uart1(void); +void nutool_pincfg_deinit_uart1(void); +void nutool_pincfg_init(void); +void nutool_pincfg_deinit(void); +#ifdef __cplusplus +} +#endif +#endif /*__NUTOOL_PINCFG_H__*/ + +/*** (C) COPYRIGHT 2013-2020 Nuvoton Technology Corp. ***/ diff --git a/bsp/nuvoton/numaker-m032ki/board/SConscript b/bsp/nuvoton/numaker-m032ki/board/SConscript new file mode 100644 index 0000000000..6ed8f178ba --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/SConscript @@ -0,0 +1,20 @@ +# RT-Thread building script for component + +from building import * + + +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +src = Split(""" +NuClockConfig/nutool_modclkcfg.c +NuPinConfig/nutool_pincfg.c +""") + +src += Glob('*.c') + Glob('*.cpp') +CPPPATH = [cwd, cwd + '/NuClockConfig', cwd + '/NuPinConfig'] + +group = DefineGroup('board', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/nuvoton/numaker-m032ki/board/board.h b/bsp/nuvoton/numaker-m032ki/board/board.h new file mode 100644 index 0000000000..acdd559291 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/board.h @@ -0,0 +1,37 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-9-1 Philo First version +* +******************************************************************************/ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +// Internal SRAM memory size[Kbytes] <8-64> +#define SRAM_SIZE (96) +#define SRAM_END (0x20000000 + SRAM_SIZE * 1024) + +#if defined(__CC_ARM) || defined(__CLANG_ARM) +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="CSTACK" +#define HEAP_BEGIN (__segment_end("CSTACK")) +#else +extern int __bss_end; +#define HEAP_BEGIN ((void *)&__bss_end) +#endif + +#define HEAP_END (void *)SRAM_END + + +void rt_hw_board_init(void); +void rt_hw_cpu_reset(void); + +#endif /* BOARD_H_ */ diff --git a/bsp/nuvoton/numaker-m032ki/board/board_dev.c b/bsp/nuvoton/numaker-m032ki/board/board_dev.c new file mode 100644 index 0000000000..d8464812c7 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/board_dev.c @@ -0,0 +1,152 @@ +/**************************************************************************//** +* +* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2022-02-22 klcheng First version +* +******************************************************************************/ +#include "NuMicro.h" +#include +#include + +#if defined(BOARD_USING_STORAGE_SPIFLASH) +#if defined(RT_USING_SFUD) + #include "spi_flash.h" + #include "spi_flash_sfud.h" +#endif + +#include "drv_qspi.h" + +#define W25X_REG_READSTATUS (0x05) +#define W25X_REG_READSTATUS2 (0x35) +#define W25X_REG_WRITEENABLE (0x06) +#define W25X_REG_WRITESTATUS (0x01) +#define W25X_REG_QUADENABLE (0x02) + +static rt_uint8_t SpiFlash_ReadStatusReg(struct rt_qspi_device *qspi_device) +{ + rt_uint8_t u8Val; + rt_err_t result = RT_EOK; + rt_uint8_t w25x_txCMD1 = W25X_REG_READSTATUS; + + result = rt_qspi_send_then_recv(qspi_device, &w25x_txCMD1, 1, &u8Val, 1); + RT_ASSERT(result > 0); + + return u8Val; +} + +static rt_uint8_t SpiFlash_ReadStatusReg2(struct rt_qspi_device *qspi_device) +{ + rt_uint8_t u8Val; + rt_err_t result = RT_EOK; + rt_uint8_t w25x_txCMD1 = W25X_REG_READSTATUS2; + + result = rt_qspi_send_then_recv(qspi_device, &w25x_txCMD1, 1, &u8Val, 1); + RT_ASSERT(result > 0); + + return u8Val; +} + +static rt_err_t SpiFlash_WriteStatusReg(struct rt_qspi_device *qspi_device, uint8_t u8Value1, uint8_t u8Value2) +{ + rt_uint8_t w25x_txCMD1; + rt_uint8_t au8Val[2]; + rt_err_t result; + struct rt_qspi_message qspi_message = {0}; + + /* Enable WE */ + w25x_txCMD1 = W25X_REG_WRITEENABLE; + result = rt_qspi_send(qspi_device, &w25x_txCMD1, sizeof(w25x_txCMD1)); + if (result != sizeof(w25x_txCMD1)) + goto exit_SpiFlash_WriteStatusReg; + + /* Prepare status-1, 2 data */ + au8Val[0] = u8Value1; + au8Val[1] = u8Value2; + + /* 1-bit mode: Instruction+payload */ + qspi_message.instruction.content = W25X_REG_WRITESTATUS; + qspi_message.instruction.qspi_lines = 1; + + qspi_message.qspi_data_lines = 1; + qspi_message.parent.cs_take = 1; + qspi_message.parent.cs_release = 1; + qspi_message.parent.send_buf = &au8Val[0]; + qspi_message.parent.length = sizeof(au8Val); + qspi_message.parent.next = RT_NULL; + + if (rt_qspi_transfer_message(qspi_device, &qspi_message) != sizeof(au8Val)) + { + result = -RT_ERROR; + } + + result = RT_EOK; + +exit_SpiFlash_WriteStatusReg: + + return result; +} + +static void SpiFlash_WaitReady(struct rt_qspi_device *qspi_device) +{ + volatile uint8_t u8ReturnValue; + + do + { + u8ReturnValue = SpiFlash_ReadStatusReg(qspi_device); + u8ReturnValue = u8ReturnValue & 1; + } + while (u8ReturnValue != 0); // check the BUSY bit +} + +static void SpiFlash_EnterQspiMode(struct rt_qspi_device *qspi_device) +{ + rt_err_t result = RT_EOK; + + uint8_t u8Status1 = SpiFlash_ReadStatusReg(qspi_device); + uint8_t u8Status2 = SpiFlash_ReadStatusReg2(qspi_device); + + u8Status2 |= W25X_REG_QUADENABLE; + + result = SpiFlash_WriteStatusReg(qspi_device, u8Status1, u8Status2); + RT_ASSERT(result == RT_EOK); + + SpiFlash_WaitReady(qspi_device); +} + +static void SpiFlash_ExitQspiMode(struct rt_qspi_device *qspi_device) +{ + rt_err_t result = RT_EOK; + uint8_t u8Status1 = SpiFlash_ReadStatusReg(qspi_device); + uint8_t u8Status2 = SpiFlash_ReadStatusReg2(qspi_device); + + u8Status2 &= ~W25X_REG_QUADENABLE; + + result = SpiFlash_WriteStatusReg(qspi_device, u8Status1, u8Status2); + RT_ASSERT(result == RT_EOK); + + SpiFlash_WaitReady(qspi_device); +} + +static int rt_hw_spiflash_init(void) +{ + /* Here, we use Dual I/O to drive the SPI flash by default. */ + /* If you want to use Quad I/O, you can modify to 4 from 2 and crossover D2/D3 pin of SPI flash. */ + if (nu_qspi_bus_attach_device("qspi0", "qspi01", 2, SpiFlash_EnterQspiMode, SpiFlash_ExitQspiMode) != RT_EOK) + return -1; + +#if defined(RT_USING_SFUD) + if (rt_sfud_flash_probe("flash0", "qspi01") == RT_NULL) + { + return -(RT_ERROR); + } +#endif + return 0; +} +INIT_COMPONENT_EXPORT(rt_hw_spiflash_init); +#endif /* BOARD_USING_STORAGE_SPIFLASH */ + diff --git a/bsp/nuvoton/numaker-m032ki/board/fal_cfg.h b/bsp/nuvoton/numaker-m032ki/board/fal_cfg.h new file mode 100644 index 0000000000..d63249b836 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/board/fal_cfg.h @@ -0,0 +1,42 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2020-3-03 FYChou First version +* +******************************************************************************/ + +#ifndef _FAL_CFG_H_ +#define _FAL_CFG_H_ + +#include +#include + + +/* ===================== Flash device Configuration ========================= */ +extern const struct fal_flash_dev Onchip_aprom_flash; +extern const struct fal_flash_dev Onchip_ldrom_flash; + +/* -flash device table------------------------------------------------------- */ +#define FAL_FLASH_DEV_TABLE \ +{ \ + &Onchip_aprom_flash, \ + &Onchip_ldrom_flash, \ +} + +/* ====================== Partition Configuration ============================ */ +#ifdef FAL_PART_HAS_TABLE_CFG + +/* -partition table----------------------------------------------------------- */ +#define FAL_PART_TABLE \ +{ \ + {FAL_PART_MAGIC_WORD, "ldrom", "OnChip_LDROM", 0, 0x1000, 0}, \ + {FAL_PART_MAGIC_WORD, "aprom", "OnChip_APROM", 0x60000, 0x20000, 0}, \ +} +#endif /* FAL_PART_HAS_TABLE_CFG */ + +#endif /* _FAL_CFG_H_ */ diff --git a/bsp/nuvoton/numaker-m032ki/linking_scripts/m031_flash.icf b/bsp/nuvoton/numaker-m032ki/linking_scripts/m031_flash.icf new file mode 100644 index 0000000000..5c594d150f --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/linking_scripts/m031_flash.icf @@ -0,0 +1,28 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x00000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x00000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0007ffff; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20017fff; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x2000; +define symbol __ICFEDIT_size_heap__ = 0x0000; +/**** End of ICF editor section. ###ICF###*/ + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, block CSTACK }; \ No newline at end of file diff --git a/bsp/nuvoton/numaker-m032ki/linking_scripts/m031_flash.sct b/bsp/nuvoton/numaker-m032ki/linking_scripts/m031_flash.sct new file mode 100644 index 0000000000..e26a437581 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/linking_scripts/m031_flash.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x00000000 0x80000 { ; load region size_region + ER_IROM1 0x00000000 0x80000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x18000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/nuvoton/numaker-m032ki/linking_scripts/m031_link.ld b/bsp/nuvoton/numaker-m032ki/linking_scripts/m031_link.ld new file mode 100644 index 0000000000..9e00e23676 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/linking_scripts/m031_link.ld @@ -0,0 +1,159 @@ +/* + * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-09-2 Philo First version + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x00000000, LENGTH = 512K /* 512K flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 96K /* 96K sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x2000; + +SECTIONS +{ + .vector : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + } > CODE = 0 + + .text : + { + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + /* section information for utest */ + . = ALIGN(4); + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data section */ + _sidata = .; + } > CODE + __exidx_end = .; + + .stack : + { + _sstack = .; + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + /* .data section which is used for initialized data */ + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data section */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data section */ + _edata = . ; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss section */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + __ram_top = ORIGIN(DATA) + LENGTH(DATA); + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/nuvoton/numaker-m032ki/rtconfig.py b/bsp/nuvoton/numaker-m032ki/rtconfig.py new file mode 100644 index 0000000000..bc7ec5b5c1 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/rtconfig.py @@ -0,0 +1,124 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m0' +CROSS_TOOL='keil' + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR + +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Program Files (x86)\GNU Tools ARM Embedded\6 2017-q1-update\bin' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:\Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:\Program Files (x86)\IAR Systems\Embedded Workbench 8.2' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = '' +# BUILD = 'debug' + + +if PLATFORM == 'gcc': + # tool-chains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m0 -mthumb -ffunction-sections -fdata-sections -Wuninitialized' + CFLAGS = DEVICE + ' -Dgcc' # -D' + PART_TYPE + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T ./linking_scripts/m031_link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M0' + CFLAGS = DEVICE + ' --apcs=interwork' + AFLAGS = DEVICE + LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers --list rtthread.map --scatter ./linking_scripts/m031_flash.sct' + + LFLAGS += ' --keep *.o(.rti_fn.*) --keep *.o(FSymTab) --keep *.o(VSymTab)' + + EXEC_PATH += '/ARM/ARMCC/bin' + print(EXEC_PATH) + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --debug' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M0' + CFLAGS += ' -e' + CFLAGS += ' --fpu=None' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' -Ol' + CFLAGS += ' --use_c++_inline' + + AFLAGS = '' + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M0' + AFLAGS += ' --fpu None' + + LFLAGS = ' --config ./linking_scripts/m031_flash.icf' + LFLAGS += ' --redirect _Printf=_PrintfTiny' + LFLAGS += ' --redirect _Scanf=_ScanfSmall' + LFLAGS += ' --entry __iar_program_start' + + EXEC_PATH += '/arm/bin/' + POST_ACTION = '' diff --git a/bsp/nuvoton/numaker-m032ki/template.ewd b/bsp/nuvoton/numaker-m032ki/template.ewd new file mode 100644 index 0000000000..9d51348a1f --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/template.ewd @@ -0,0 +1,1485 @@ + + + 3 + + Release + + ARM + + 0 + + C-SPY + 2 + + 30 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 0 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 0 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 0 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + NULINK_ID + 2 + + 0 + 1 + 0 + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 0 + + + + + + + + STLINK_ID + 2 + + 6 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 0 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 8 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\HWRTOSplugin\HWRTOSplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8BE.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + diff --git a/bsp/nuvoton/numaker-m032ki/template.ewp b/bsp/nuvoton/numaker-m032ki/template.ewp new file mode 100644 index 0000000000..fa570321b6 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/template.ewp @@ -0,0 +1,1039 @@ + + + 3 + + Release + + ARM + + 0 + + General + 3 + + 31 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 35 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 0 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 22 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 0 + + + + + + + BILINK + 0 + + + + diff --git a/bsp/nuvoton/numaker-m032ki/template.eww b/bsp/nuvoton/numaker-m032ki/template.eww new file mode 100644 index 0000000000..e09d1b57a4 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/template.eww @@ -0,0 +1,10 @@ + + + + + $WS_DIR$\Template.ewp + + + + + diff --git a/bsp/nuvoton/numaker-m032ki/template.uvprojx b/bsp/nuvoton/numaker-m032ki/template.uvprojx new file mode 100644 index 0000000000..1a62e3dc43 --- /dev/null +++ b/bsp/nuvoton/numaker-m032ki/template.uvprojx @@ -0,0 +1,391 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rtthread-m031 + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::ARMCC + 5060750::V5.06 update 6 (build 750)::ARMCC + 0 + + + M032KIAAE + Nuvoton + Nuvoton.NuMicro_DFP.1.3.10 + http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack + IRAM(0x20000000,0x18000) IROM(0x00000000,0x80000) CPUTYPE("Cortex-M0") CLOCK(12000000) + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0M031_AP_512 -FS00 -FL080000 -FP0($$Device:M032KIAAE$Flash\M031_AP_512.FLM)) + 0 + $$Device:M032KIAAE$Device\M031\Include\M031Series.h + + + + + + + + + + $$Device:M032KIAAE$SVD\Nuvoton\M031AE_v1.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\keil5\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\keil5\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 1 + fromelf --bin ".\build\keil5\\@L.axf" --output ".\build\keil5\\@L.bin" + fromelf --text -c ".\build\keil5\\@L.axf" --output ".\build\keil5\\@L.txt" + 0 + 0 + 0 + 0 + + 1 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + + DARMCM1.DLL + -pCM0 + SARMCM3.DLL + + TARMCM1.DLL + -pCM0 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4103 + + 1 + NULink\Nu_Link.dll + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M0" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x0 + 0x80000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x80000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 0 + 5 + 3 + 0 + 0 + 0 + 1 + 0 + + + + + + + + + 1 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x00000000 + 0x20000000 + + .\linking_scripts\m031_flash.sct + + + --entry Reset_Handler + + + + + + + + + + + + + + +
From 02331fd30d1f1ca8c886aac4db6c8c111987913c Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 17 May 2021 21:00:40 +0800 Subject: [PATCH 088/255] revert #3647 --- src/ipc.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/src/ipc.c b/src/ipc.c index 111d724c23..27ee92e3fd 100755 --- a/src/ipc.c +++ b/src/ipc.c @@ -38,7 +38,6 @@ * event without pending * 2020-10-11 Meco Man add value overflow-check code * 2021-01-03 Meco Man add rt_mb_urgent() - * 2021-01-20 hupu fix priority inversion bug of mutex */ #include @@ -192,31 +191,6 @@ rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list) return RT_EOK; } -/** - * This function will get the highest priority from the specified - * list of threads - * - * @param list of the threads - * - * @return the highest priority - */ -rt_uint8_t rt_ipc_get_highest_priority(rt_list_t *list) -{ - struct rt_list_node *n; - struct rt_thread *sthread; - rt_uint8_t priority = RT_THREAD_PRIORITY_MAX - 1; - - for (n = list->next; n != list; n = n->next) - { - sthread = rt_list_entry(n, struct rt_thread, tlist); - - priority = priority < sthread->current_priority ? - priority : - sthread->current_priority; - } - return priority; -} - #ifdef RT_USING_SEMAPHORE /** * This function will initialize a semaphore and put it under control of @@ -855,7 +829,6 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) register rt_base_t temp; struct rt_thread *thread; rt_bool_t need_schedule; - rt_uint8_t max_priority_in_queue = RT_THREAD_PRIORITY_MAX - 1; /* parameter check */ RT_ASSERT(mutex != RT_NULL); @@ -917,21 +890,6 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) mutex->owner = thread; mutex->original_priority = thread->current_priority; - /* Priority adjustment occurs only when the following conditions - * are met simultaneously: - * 1.The type of mutex is RT_IPC_FLAG_FIFO; - * 2.The priority of the thread to be resumed is not equal to the - * highest priority in the queue; - */ - max_priority_in_queue = rt_ipc_get_highest_priority(&mutex->parent.suspend_thread); - if (mutex->parent.parent.flag == RT_IPC_FLAG_FIFO && - thread->current_priority != max_priority_in_queue) - { - rt_thread_control(thread, - RT_THREAD_CTRL_CHANGE_PRIORITY, - &(max_priority_in_queue)); - } - if(mutex->hold < RT_MUTEX_HOLD_MAX) { mutex->hold ++; From 5036816967c3e3a3fb72d7f27024641d32bad0e2 Mon Sep 17 00:00:00 2001 From: lizhirui Date: Tue, 18 May 2021 09:57:25 +0800 Subject: [PATCH 089/255] add qemu-riscv-virt64 bsp add qemu-riscv-virt64 bsp --- bsp/qemu-riscv-virt64/.config | 564 +++++++ bsp/qemu-riscv-virt64/Kconfig | 36 + bsp/qemu-riscv-virt64/SConscript | 14 + bsp/qemu-riscv-virt64/SConstruct | 38 + bsp/qemu-riscv-virt64/applications/SConscript | 9 + bsp/qemu-riscv-virt64/applications/main.c | 22 + bsp/qemu-riscv-virt64/driver/Kconfig | 18 + bsp/qemu-riscv-virt64/driver/SConscript | 19 + bsp/qemu-riscv-virt64/driver/asm/sbiasm.h | 10 + bsp/qemu-riscv-virt64/driver/asm/sbidef.h | 27 + bsp/qemu-riscv-virt64/driver/board.c | 217 +++ bsp/qemu-riscv-virt64/driver/board.h | 27 + bsp/qemu-riscv-virt64/driver/drv_uart.c | 170 +++ bsp/qemu-riscv-virt64/driver/drv_uart.h | 15 + bsp/qemu-riscv-virt64/driver/encoding.h | 1316 +++++++++++++++++ bsp/qemu-riscv-virt64/driver/io.h | 52 + bsp/qemu-riscv-virt64/driver/sbi.h | 126 ++ bsp/qemu-riscv-virt64/link.lds | 167 +++ bsp/qemu-riscv-virt64/link_stacksize.lds | 1 + bsp/qemu-riscv-virt64/qemu-dbg.sh | 1 + bsp/qemu-riscv-virt64/qemu-dumpdtb.sh | 1 + bsp/qemu-riscv-virt64/qemu-nographic.sh | 1 + bsp/qemu-riscv-virt64/rtconfig.h | 184 +++ bsp/qemu-riscv-virt64/rtconfig.py | 57 + libcpu/risc-v/SConscript | 2 + libcpu/risc-v/virt64/SConscript | 14 + libcpu/risc-v/virt64/context_gcc.S | 52 + libcpu/risc-v/virt64/cpuport.c | 120 ++ libcpu/risc-v/virt64/cpuport.h | 28 + libcpu/risc-v/virt64/interrupt_gcc.S | 101 ++ libcpu/risc-v/virt64/riscv.h | 29 + libcpu/risc-v/virt64/riscv_io.h | 109 ++ libcpu/risc-v/virt64/stack.h | 52 + libcpu/risc-v/virt64/stackframe.h | 163 ++ libcpu/risc-v/virt64/startup_gcc.S | 80 + libcpu/risc-v/virt64/tick.c | 59 + libcpu/risc-v/virt64/tick.h | 17 + 37 files changed, 3918 insertions(+) create mode 100644 bsp/qemu-riscv-virt64/.config create mode 100644 bsp/qemu-riscv-virt64/Kconfig create mode 100644 bsp/qemu-riscv-virt64/SConscript create mode 100644 bsp/qemu-riscv-virt64/SConstruct create mode 100644 bsp/qemu-riscv-virt64/applications/SConscript create mode 100644 bsp/qemu-riscv-virt64/applications/main.c create mode 100644 bsp/qemu-riscv-virt64/driver/Kconfig create mode 100644 bsp/qemu-riscv-virt64/driver/SConscript create mode 100644 bsp/qemu-riscv-virt64/driver/asm/sbiasm.h create mode 100644 bsp/qemu-riscv-virt64/driver/asm/sbidef.h create mode 100644 bsp/qemu-riscv-virt64/driver/board.c create mode 100644 bsp/qemu-riscv-virt64/driver/board.h create mode 100644 bsp/qemu-riscv-virt64/driver/drv_uart.c create mode 100644 bsp/qemu-riscv-virt64/driver/drv_uart.h create mode 100644 bsp/qemu-riscv-virt64/driver/encoding.h create mode 100644 bsp/qemu-riscv-virt64/driver/io.h create mode 100644 bsp/qemu-riscv-virt64/driver/sbi.h create mode 100644 bsp/qemu-riscv-virt64/link.lds create mode 100644 bsp/qemu-riscv-virt64/link_stacksize.lds create mode 100644 bsp/qemu-riscv-virt64/qemu-dbg.sh create mode 100644 bsp/qemu-riscv-virt64/qemu-dumpdtb.sh create mode 100644 bsp/qemu-riscv-virt64/qemu-nographic.sh create mode 100644 bsp/qemu-riscv-virt64/rtconfig.h create mode 100644 bsp/qemu-riscv-virt64/rtconfig.py create mode 100644 libcpu/risc-v/virt64/SConscript create mode 100644 libcpu/risc-v/virt64/context_gcc.S create mode 100644 libcpu/risc-v/virt64/cpuport.c create mode 100644 libcpu/risc-v/virt64/cpuport.h create mode 100644 libcpu/risc-v/virt64/interrupt_gcc.S create mode 100644 libcpu/risc-v/virt64/riscv.h create mode 100644 libcpu/risc-v/virt64/riscv_io.h create mode 100644 libcpu/risc-v/virt64/stack.h create mode 100644 libcpu/risc-v/virt64/stackframe.h create mode 100644 libcpu/risc-v/virt64/startup_gcc.S create mode 100644 libcpu/risc-v/virt64/tick.c create mode 100644 libcpu/risc-v/virt64/tick.h diff --git a/bsp/qemu-riscv-virt64/.config b/bsp/qemu-riscv-virt64/.config new file mode 100644 index 0000000000..8a61ab72eb --- /dev/null +++ b/bsp/qemu-riscv-virt64/.config @@ -0,0 +1,564 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Project Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=20 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=8 +# 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 is not set +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=16384 +CONFIG_RT_USING_TIMER_SOFT=y +CONFIG_RT_TIMER_THREAD_PRIO=4 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=16384 + +# +# 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 is not set +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set +CONFIG_RT_USING_MEMTRACE=y +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=256 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart" +CONFIG_RT_VER_NUM=0x40004 +CONFIG_ARCH_CPU_64BIT=y +# CONFIG_RT_USING_CPU_FFS is not set +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_RISCV64=y +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=16384 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_CMD_SIZE=80 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +CONFIG_FINSH_USING_MSH_ONLY=y +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_WORKDIR=y +CONFIG_DFS_FILESYSTEMS_MAX=2 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=2 +CONFIG_DFS_FD_MAX=32 +# CONFIG_RT_USING_DFS_MNTTABLE is not set +# CONFIG_RT_USING_DFS_ELMFAT is not set +CONFIG_RT_USING_DFS_DEVFS=y +CONFIG_RT_USING_DFS_ROMFS=y +# CONFIG_RT_USING_DFS_RAMFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# 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 is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set + +# +# RT-Thread 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 + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_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 +# +# CONFIG_PKG_USING_GUIENGINE 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 + +# +# 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_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# 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 +# 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_NUCLEI_SDK 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 + +# +# 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_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_BOARD_virt=y +CONFIG_RT_USING_USERSPACE=y + +# +# General Purpose UARTs +# +# CONFIG_BSP_USING_UART1 is not set +CONFIG___STACKSIZE__=16384 diff --git a/bsp/qemu-riscv-virt64/Kconfig b/bsp/qemu-riscv-virt64/Kconfig new file mode 100644 index 0000000000..c4fa63f0e1 --- /dev/null +++ b/bsp/qemu-riscv-virt64/Kconfig @@ -0,0 +1,36 @@ +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 BOARD_virt + bool + select ARCH_RISCV64 + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +config RT_USING_USERSPACE + bool + default y + +source "driver/Kconfig" + +config __STACKSIZE__ + int "stack size for interrupt" + default 4096 diff --git a/bsp/qemu-riscv-virt64/SConscript b/bsp/qemu-riscv-virt64/SConscript new file mode 100644 index 0000000000..c7ef7659ec --- /dev/null +++ b/bsp/qemu-riscv-virt64/SConscript @@ -0,0 +1,14 @@ +# for module compiling +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/qemu-riscv-virt64/SConstruct b/bsp/qemu-riscv-virt64/SConstruct new file mode 100644 index 0000000000..422e592ccd --- /dev/null +++ b/bsp/qemu-riscv-virt64/SConstruct @@ -0,0 +1,38 @@ +import os +import sys +import rtconfig + +from rtconfig import RTT_ROOT + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +from building import * + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) +env['ASCOM'] = env['ASPPCOM'] + +Export('RTT_ROOT') +Export('rtconfig') +rtconfig.CPU='virt64' +rtconfig.ARCH='risc-v' + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False) + +stack_size = 4096 + +stack_lds = open('link_stacksize.lds', 'w') +if GetDepend('__STACKSIZE__'): stack_size = GetDepend('__STACKSIZE__') +stack_lds.write('__STACKSIZE__ = %d;' % stack_size) +stack_lds.close() + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/qemu-riscv-virt64/applications/SConscript b/bsp/qemu-riscv-virt64/applications/SConscript new file mode 100644 index 0000000000..9ffdfd6d3a --- /dev/null +++ b/bsp/qemu-riscv-virt64/applications/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/qemu-riscv-virt64/applications/main.c b/bsp/qemu-riscv-virt64/applications/main.c new file mode 100644 index 0000000000..288d4f08ba --- /dev/null +++ b/bsp/qemu-riscv-virt64/applications/main.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +#include +#include +#include +#include + +int main(void) +{ + void rt_hw_uart_start_rx_thread(); + rt_hw_uart_start_rx_thread(); + printf("Hello RISC-V\n"); + + return 0; +} diff --git a/bsp/qemu-riscv-virt64/driver/Kconfig b/bsp/qemu-riscv-virt64/driver/Kconfig new file mode 100644 index 0000000000..5744c89702 --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/Kconfig @@ -0,0 +1,18 @@ + + +menu "General Purpose UARTs" + +menuconfig BSP_USING_UART1 + bool "Enable UART1" + default n + if BSP_USING_UART1 + config BSP_UART1_TXD_PIN + int "uart1 TXD pin number" + default 20 + config BSP_UART1_RXD_PIN + int "uart1 RXD pin number" + default 21 + endif + +endmenu + diff --git a/bsp/qemu-riscv-virt64/driver/SConscript b/bsp/qemu-riscv-virt64/driver/SConscript new file mode 100644 index 0000000000..faea9c1bd9 --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/SConscript @@ -0,0 +1,19 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) + +objs = [group] + +list = os.listdir(cwd) + +for item in list: + if os.path.isfile(os.path.join(cwd, item, 'SConscript')): + objs = objs + SConscript(os.path.join(item, 'SConscript')) + +Return('objs') diff --git a/bsp/qemu-riscv-virt64/driver/asm/sbiasm.h b/bsp/qemu-riscv-virt64/driver/asm/sbiasm.h new file mode 100644 index 0000000000..4639fba68c --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/asm/sbiasm.h @@ -0,0 +1,10 @@ +#ifndef _SBI_ASM_H +#define _SBI_ASM_H + +.macro SBI_CALL which + li a7, \which + ecall + nop +.endm + +#endif /* _SBI_ASM_H */ diff --git a/bsp/qemu-riscv-virt64/driver/asm/sbidef.h b/bsp/qemu-riscv-virt64/driver/asm/sbidef.h new file mode 100644 index 0000000000..5bcf58ade7 --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/asm/sbidef.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019-2020, Xim + * + * SPDX-License-Identifier: Apache-2.0 + * + */ +#ifndef _ASM_SBI_DEF_H +#define _ASM_SBI_DEF_H + +#define SBI_SET_TIMER 0 +#define SBI_CONSOLE_PUTCHAR 1 +#define SBI_CONSOLE_GETCHAR 2 +#define SBI_CLEAR_IPI 3 +#define SBI_SEND_IPI 4 +#define SBI_REMOTE_FENCE_I 5 +#define SBI_REMOTE_SFENCE_VMA 6 +#define SBI_REMOTE_SFENCE_VMA_ASID 7 +#define SBI_SHUTDOWN 8 + +#define SBI_CONSOLE_PUTSTR 9 + +#define SBI_SD_WRITE 10 +#define SBI_SD_READ 11 +#define SBI_NET_WRITE 12 +#define SBI_NET_READ 13 + +#endif /* _ASM_SBI_DEF_H */ diff --git a/bsp/qemu-riscv-virt64/driver/board.c b/bsp/qemu-riscv-virt64/driver/board.c new file mode 100644 index 0000000000..3ed4aab438 --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/board.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-30 lizhirui first version + */ + +#include +#include +#include + +#include "board.h" +#include "tick.h" + +#include "drv_uart.h" +#include "encoding.h" +#include "stack.h" +#include "sbi.h" +#include "riscv.h" +#include "stack.h" + +void init_bss(void) +{ + unsigned int *dst; + + dst = &__bss_start; + while (dst < &__bss_end) + { + *dst++ = 0; + } +} + +void primary_cpu_entry(void) +{ + extern void entry(void); + + /* disable global interrupt */ + init_bss(); + rt_hw_interrupt_disable(); + entry(); +} + +void rt_hw_interrupt_init() +{ + /* Enable machine external interrupts. */ + set_csr(sie, SIP_SEIP); +} + +void rt_hw_board_init(void) +{ + /* initalize interrupt */ + rt_hw_interrupt_init(); + /* initialize hardware interrupt */ + rt_hw_uart_init(); + + rt_hw_tick_init(); + + #ifdef RT_USING_HEAP + rt_kprintf("heap: [0x%08x - 0x%08x]\n", (rt_ubase_t) RT_HW_HEAP_BEGIN, (rt_ubase_t) RT_HW_HEAP_END); + /* initialize memory system */ + rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); + #endif + + #ifdef RT_USING_CONSOLE + /* set console device */ + rt_console_set_device("uart"); + #endif /* RT_USING_CONSOLE */ + + #ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); + #endif +} + +void rt_hw_cpu_reset(void) +{ + SBI_CALL_0(SBI_SHUTDOWN); + while(1); +} +MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine); + +void dump_regs(struct rt_hw_stack_frame *regs) +{ + rt_kprintf("--------------Dump Registers-----------------\n"); + + rt_kprintf("Function Registers:\n"); + rt_kprintf("\tra(x1) = 0x%p\tuser_sp = 0x%p\n",regs -> ra,regs -> user_sp_exc_stack); + rt_kprintf("\tgp(x3) = 0x%p\ttp(x4) = 0x%p\n",regs -> gp,regs -> tp); + rt_kprintf("Temporary Registers:\n"); + rt_kprintf("\tt0(x5) = 0x%p\tt1(x6) = 0x%p\n",regs -> t0,regs -> t1); + rt_kprintf("\tt2(x7) = 0x%p\n",regs -> t2); + rt_kprintf("\tt3(x28) = 0x%p\tt4(x29) = 0x%p\n",regs -> t3,regs -> t4); + rt_kprintf("\tt5(x30) = 0x%p\tt6(x31) = 0x%p\n",regs -> t5,regs -> t6); + rt_kprintf("Saved Registers:\n"); + rt_kprintf("\ts0/fp(x8) = 0x%p\ts1(x9) = 0x%p\n",regs -> s0_fp,regs -> s1); + rt_kprintf("\ts2(x18) = 0x%p\ts3(x19) = 0x%p\n",regs -> s2,regs -> s3); + rt_kprintf("\ts4(x20) = 0x%p\ts5(x21) = 0x%p\n",regs -> s4,regs -> s5); + rt_kprintf("\ts6(x22) = 0x%p\ts7(x23) = 0x%p\n",regs -> s6,regs -> s7); + rt_kprintf("\ts8(x24) = 0x%p\ts9(x25) = 0x%p\n",regs -> s8,regs -> s9); + rt_kprintf("\ts10(x26) = 0x%p\ts11(x27) = 0x%p\n",regs -> s10,regs -> s11); + rt_kprintf("Function Arguments Registers:\n"); + rt_kprintf("\ta0(x10) = 0x%p\ta1(x11) = 0x%p\n",regs -> a0,regs -> a1); + rt_kprintf("\ta2(x12) = 0x%p\ta3(x13) = 0x%p\n",regs -> a2,regs -> a3); + rt_kprintf("\ta4(x14) = 0x%p\ta5(x15) = 0x%p\n",regs -> a4,regs -> a5); + rt_kprintf("\ta6(x16) = 0x%p\ta7(x17) = 0x%p\n",regs -> a6,regs -> a7); + rt_kprintf("sstatus = 0x%p\n",regs -> sstatus); + rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled"); + rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled"); + rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode"); + rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_PUM) ? "Permit to Access User Page" : "Not Permit to Access User Page"); + rt_kprintf("\t%s\n",(regs -> sstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page"); + rt_size_t satp_v = read_csr(satp); + rt_kprintf("satp = 0x%p\n",satp_v); + const char *mode_str = "Unknown Address Translation/Protection Mode"; + + switch(__MASKVALUE(satp_v >> 60,__MASK(4))) + { + case 0: + mode_str = "No Address Translation/Protection Mode"; + break; + + case 8: + mode_str = "Page-based 39-bit Virtual Addressing Mode"; + break; + + case 9: + mode_str = "Page-based 48-bit Virtual Addressing Mode"; + break; + } + + rt_kprintf("\tMode = %s\n",mode_str); + rt_kprintf("-----------------Dump OK---------------------\n"); +} + +static const char *Exception_Name[] = + { + "Instruction Address Misaligned", + "Instruction Access Fault", + "Illegal Instruction", + "Breakpoint", + "Load Address Misaligned", + "Load Access Fault", + "Store/AMO Address Misaligned", + "Store/AMO Access Fault", + "Environment call from U-mode", + "Environment call from S-mode", + "Reserved-10", + "Reserved-11", + "Instruction Page Fault", + "Load Page Fault", + "Reserved-14", + "Store/AMO Page Fault" + }; + +static const char *Interrupt_Name[] = + { + "User Software Interrupt", + "Supervisor Software Interrupt", + "Reversed-2", + "Reversed-3", + "User Timer Interrupt", + "Supervisor Timer Interrupt", + "Reversed-6", + "Reversed-7", + "User External Interrupt", + "Supervisor External Interrupt", + "Reserved-10", + "Reserved-11", + }; + +void handle_trap(rt_size_t scause,rt_size_t stval,rt_size_t sepc,struct rt_hw_stack_frame *sp) +{ + if(scause == (uint64_t)(0x8000000000000005)) + { + rt_interrupt_enter(); + tick_isr(); + rt_interrupt_leave(); + } + else + { + rt_size_t id = __MASKVALUE(scause,__MASK(63UL)); + const char *msg; + + if(scause >> 63) + { + if(id < sizeof(Interrupt_Name) / sizeof(const char *)) + { + msg = Interrupt_Name[id]; + } + else + { + msg = "Unknown Interrupt"; + } + + rt_kprintf("Unhandled Interrupt %ld:%s\n",id,msg); + } + else + { + if(id < sizeof(Exception_Name) / sizeof(const char *)) + { + msg = Exception_Name[id]; + } + else + { + msg = "Unknown Exception"; + } + + rt_kprintf("Unhandled Exception %ld:%s\n",id,msg); + } + + rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n",scause,stval,sepc); + dump_regs(sp); + while(1); + } +} diff --git a/bsp/qemu-riscv-virt64/driver/board.h b/bsp/qemu-riscv-virt64/driver/board.h new file mode 100644 index 0000000000..3193346508 --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/board.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-30 lizhirui first version + */ + +#ifndef BOARD_H__ +#define BOARD_H__ + +#include + +extern unsigned int __bss_start; +extern unsigned int __bss_end; + +#define RT_HW_HEAP_BEGIN ((void *)&__bss_end) +#define RT_HW_HEAP_END ((void *)(((rt_size_t)RT_HW_HEAP_BEGIN) + 100 * 1024 * 1024)) +#define RT_HW_PAGE_START RT_HW_HEAP_END +#define RT_HW_PAGE_END ((void *)(((rt_size_t)RT_HW_PAGE_START) + 100 * 1024 * 1024)) + +void rt_hw_board_init(void); +void rt_init_user_mem(struct rt_thread *thread, const char *name, unsigned long *entry); + +#endif diff --git a/bsp/qemu-riscv-virt64/driver/drv_uart.c b/bsp/qemu-riscv-virt64/driver/drv_uart.c new file mode 100644 index 0000000000..8e0476321c --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/drv_uart.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2019-2020, Xim + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include +#include + +#include "board.h" +#include "drv_uart.h" + +#include +#include "sbi.h" + +#define UART_DEFAULT_BAUDRATE 115200 + +struct device_uart +{ + rt_ubase_t hw_base; + rt_uint32_t irqno; +}; + +static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg); +static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg); +static int drv_uart_putc(struct rt_serial_device *serial, char c); +static int drv_uart_getc(struct rt_serial_device *serial); + +const struct rt_uart_ops _uart_ops = +{ + rt_uart_configure, + uart_control, + drv_uart_putc, + drv_uart_getc, + //TODO: add DMA support + RT_NULL +}; + +void uart_init(void) +{ + return ; +} + +struct rt_serial_device serial1; +struct device_uart uart1; + +/* + * UART interface + */ +static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct device_uart *uart; + + RT_ASSERT(serial != RT_NULL); + serial->config = *cfg; + + return (RT_EOK); +} + +#define UART_LSR_DR 0x01 /* Data ready */ +#define UART_LSR_THRE 0x20 /* Xmit holding register empty */ + +#define UART_RBR(hw) HWREG32(hw + 0x00) +#define UART_IER(hw) HWREG32(hw + 0x04) +#define UART_LSR(hw) HWREG32(hw + 0x14) + +static volatile uint64_t uart_hwbase = 0x10000000; + +void uart_putc(char c) +{ + while ((UART_LSR(uart_hwbase) & UART_LSR_THRE) == 0); + + UART_RBR(uart_hwbase) = c; +} + +static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct device_uart *uart; + + uart = serial->parent.user_data; + rt_uint32_t channel = 1; + + RT_ASSERT(uart != RT_NULL); + RT_ASSERT(channel != 3); + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + break; + + case RT_DEVICE_CTRL_SET_INT: + break; + } + + return (RT_EOK); +} + +static int drv_uart_putc(struct rt_serial_device *serial, char c) +{ + SBI_CALL_1(SBI_CONSOLE_PUTCHAR, c); + return (1); +} + +static int drv_uart_getc(struct rt_serial_device *serial) +{ + return SBI_CALL_0(SBI_CONSOLE_GETCHAR); +} + +void drv_uart_puts(char *str) +{ + sbi_console_putstr(str); +} + +char rt_hw_console_getchar(void) +{ + return SBI_CALL_0(SBI_CONSOLE_GETCHAR); +} + +static void uart_rx(void *param) +{ + struct rt_serial_device *serial = (struct rt_serial_device *)param; + + while(1) + { + rt_hw_serial_isr((struct rt_serial_device *)serial,RT_SERIAL_EVENT_RX_IND); + rt_thread_mdelay(10); + } +} + +void rt_hw_uart_start_rx_thread() +{ + rt_thread_t th; + RT_ASSERT((th = rt_thread_create("uartrx",uart_rx,(void *)&serial1,8192,8,20)) != RT_NULL); + RT_ASSERT(rt_thread_startup(th) == RT_EOK); +} + +/* + * UART Initiation + */ +int rt_hw_uart_init(void) +{ + struct rt_serial_device *serial; + struct device_uart *uart; + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + + { + serial = &serial1; + uart = &uart1; + + serial->ops = &_uart_ops; + serial->config = config; + serial->config.baud_rate = UART_DEFAULT_BAUDRATE; + + uart->hw_base = 0x10000000; + uart->irqno = 0xa; + + rt_hw_serial_register(serial, + "uart", + RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + uart); + } + + return 0; +} + +/* WEAK for SDK 0.5.6 */ +RT_WEAK void uart_debug_init(int uart_channel) +{ +} diff --git a/bsp/qemu-riscv-virt64/driver/drv_uart.h b/bsp/qemu-riscv-virt64/driver/drv_uart.h new file mode 100644 index 0000000000..a7a18d0dde --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/drv_uart.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019-2020, Xim + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#ifndef __DRV_UART_H__ +#define __DRV_UART_H__ + +void rt_hw_uart_start_rx_thread(); +int rt_hw_uart_init(void); +void drv_uart_puts(char *str); // for syscall + +#endif /* __DRV_UART_H__ */ diff --git a/bsp/qemu-riscv-virt64/driver/encoding.h b/bsp/qemu-riscv-virt64/driver/encoding.h new file mode 100644 index 0000000000..d02c90cebb --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/encoding.h @@ -0,0 +1,1316 @@ +// See LICENSE for license details. + +#ifndef RISCV_CSR_ENCODING_H +#define RISCV_CSR_ENCODING_H + +#define MSTATUS_UIE 0x00000001 +#define MSTATUS_SIE 0x00000002 +#define MSTATUS_HIE 0x00000004 +#define MSTATUS_MIE 0x00000008 +#define MSTATUS_UPIE 0x00000010 +#define MSTATUS_SPIE 0x00000020 +#define MSTATUS_HPIE 0x00000040 +#define MSTATUS_MPIE 0x00000080 +#define MSTATUS_SPP 0x00000100 +#define MSTATUS_HPP 0x00000600 +#define MSTATUS_MPP 0x00001800 +#define MSTATUS_FS 0x00006000 +#define MSTATUS_XS 0x00018000 +#define MSTATUS_MPRV 0x00020000 +#define MSTATUS_PUM 0x00040000 +#define MSTATUS_MXR 0x00080000 +#define MSTATUS_VM 0x1F000000 +#define MSTATUS32_SD 0x80000000 +#define MSTATUS64_SD 0x8000000000000000 + +#define SSTATUS_UIE 0x00000001 +#define SSTATUS_SIE 0x00000002 +#define SSTATUS_UPIE 0x00000010 +#define SSTATUS_SPIE 0x00000020 +#define SSTATUS_SPP 0x00000100 +#define SSTATUS_FS 0x00006000 +#define SSTATUS_XS 0x00018000 +#define SSTATUS_PUM 0x00040000 +#define SSTATUS32_SD 0x80000000 +#define SSTATUS64_SD 0x8000000000000000 + +#define DCSR_XDEBUGVER (3U<<30) +#define DCSR_NDRESET (1<<29) +#define DCSR_FULLRESET (1<<28) +#define DCSR_EBREAKM (1<<15) +#define DCSR_EBREAKH (1<<14) +#define DCSR_EBREAKS (1<<13) +#define DCSR_EBREAKU (1<<12) +#define DCSR_STOPCYCLE (1<<10) +#define DCSR_STOPTIME (1<<9) +#define DCSR_CAUSE (7<<6) +#define DCSR_DEBUGINT (1<<5) +#define DCSR_HALT (1<<3) +#define DCSR_STEP (1<<2) +#define DCSR_PRV (3<<0) + +#define DCSR_CAUSE_NONE 0 +#define DCSR_CAUSE_SWBP 1 +#define DCSR_CAUSE_HWBP 2 +#define DCSR_CAUSE_DEBUGINT 3 +#define DCSR_CAUSE_STEP 4 +#define DCSR_CAUSE_HALT 5 + +#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4)) +#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5)) +#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11)) + +#define MCONTROL_SELECT (1<<19) +#define MCONTROL_TIMING (1<<18) +#define MCONTROL_ACTION (0x3f<<12) +#define MCONTROL_CHAIN (1<<11) +#define MCONTROL_MATCH (0xf<<7) +#define MCONTROL_M (1<<6) +#define MCONTROL_H (1<<5) +#define MCONTROL_S (1<<4) +#define MCONTROL_U (1<<3) +#define MCONTROL_EXECUTE (1<<2) +#define MCONTROL_STORE (1<<1) +#define MCONTROL_LOAD (1<<0) + +#define MCONTROL_TYPE_NONE 0 +#define MCONTROL_TYPE_MATCH 2 + +#define MCONTROL_ACTION_DEBUG_EXCEPTION 0 +#define MCONTROL_ACTION_DEBUG_MODE 1 +#define MCONTROL_ACTION_TRACE_START 2 +#define MCONTROL_ACTION_TRACE_STOP 3 +#define MCONTROL_ACTION_TRACE_EMIT 4 + +#define MCONTROL_MATCH_EQUAL 0 +#define MCONTROL_MATCH_NAPOT 1 +#define MCONTROL_MATCH_GE 2 +#define MCONTROL_MATCH_LT 3 +#define MCONTROL_MATCH_MASK_LOW 4 +#define MCONTROL_MATCH_MASK_HIGH 5 + +#define MIP_SSIP (1 << IRQ_S_SOFT) +#define MIP_HSIP (1 << IRQ_H_SOFT) +#define MIP_MSIP (1 << IRQ_M_SOFT) +#define MIP_STIP (1 << IRQ_S_TIMER) +#define MIP_HTIP (1 << IRQ_H_TIMER) +#define MIP_MTIP (1 << IRQ_M_TIMER) +#define MIP_SEIP (1 << IRQ_S_EXT) +#define MIP_HEIP (1 << IRQ_H_EXT) +#define MIP_MEIP (1 << IRQ_M_EXT) + +#define SIP_SSIP MIP_SSIP /* software interrupt */ +#define SIP_STIP MIP_STIP /* timer interrupt */ +#define SIP_SEIP MIP_SEIP /* ext interrupt */ + +#define PRV_U 0 +#define PRV_S 1 +#define PRV_H 2 +#define PRV_M 3 + +#define VM_MBARE 0 +#define VM_MBB 1 +#define VM_MBBID 2 +#define VM_SV32 8 +#define VM_SV39 9 +#define VM_SV48 10 + +#define IRQ_S_SOFT 1 +#define IRQ_H_SOFT 2 +#define IRQ_M_SOFT 3 +#define IRQ_S_TIMER 5 +#define IRQ_H_TIMER 6 +#define IRQ_M_TIMER 7 +#define IRQ_S_EXT 9 +#define IRQ_H_EXT 10 +#define IRQ_M_EXT 11 +#define IRQ_COP 12 +#define IRQ_HOST 13 + +#define DEFAULT_RSTVEC 0x00001000 +#define DEFAULT_NMIVEC 0x00001004 +#define DEFAULT_MTVEC 0x00001010 +#define CONFIG_STRING_ADDR 0x0000100C +#define EXT_IO_BASE 0x40000000 +#define DRAM_BASE 0x80000000 + +// page table entry (PTE) fields +#define PTE_V 0x001 // Valid +#define PTE_R 0x002 // Read +#define PTE_W 0x004 // Write +#define PTE_X 0x008 // Execute +#define PTE_U 0x010 // User +#define PTE_G 0x020 // Global +#define PTE_A 0x040 // Accessed +#define PTE_D 0x080 // Dirty +#define PTE_SOFT 0x300 // Reserved for Software + +#define PTE_PPN_SHIFT 10 + +#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V) + +#ifdef __riscv + +#ifdef __riscv64 +# define MSTATUS_SD MSTATUS64_SD +# define SSTATUS_SD SSTATUS64_SD +# define RISCV_PGLEVEL_BITS 9 +#else +# define MSTATUS_SD MSTATUS32_SD +# define SSTATUS_SD SSTATUS32_SD +# define RISCV_PGLEVEL_BITS 10 +#endif /* end of __riscv64 */ + +#define RISCV_PGSHIFT 12 +#define RISCV_PGSIZE (1 << RISCV_PGSHIFT) + +#ifndef __ASSEMBLER__ + +#ifdef __GNUC__ + +#define read_csr(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define write_csr(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ + else \ + asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + +#define swap_csr(reg, val) ({ unsigned long __tmp; \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \ + else \ + asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \ + __tmp; }) + +#define set_csr(reg, bit) ({ unsigned long __tmp; \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ + else \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + __tmp; }) + +#define clear_csr(reg, bit) ({ unsigned long __tmp; \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ + else \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + __tmp; }) + +#define rdtime() read_csr(time) +#define rdcycle() read_csr(cycle) +#define rdinstret() read_csr(instret) + +#endif /* end of __GNUC__ */ + +#endif /* end of __ASSEMBLER__ */ + +#endif /* end of __riscv */ + +#endif /* end of RISCV_CSR_ENCODING_H */ + +/* Automatically generated by parse-opcodes */ +#ifndef RISCV_ENCODING_H +#define RISCV_ENCODING_H +#define MATCH_BEQ 0x63 +#define MASK_BEQ 0x707f +#define MATCH_BNE 0x1063 +#define MASK_BNE 0x707f +#define MATCH_BLT 0x4063 +#define MASK_BLT 0x707f +#define MATCH_BGE 0x5063 +#define MASK_BGE 0x707f +#define MATCH_BLTU 0x6063 +#define MASK_BLTU 0x707f +#define MATCH_BGEU 0x7063 +#define MASK_BGEU 0x707f +#define MATCH_JALR 0x67 +#define MASK_JALR 0x707f +#define MATCH_JAL 0x6f +#define MASK_JAL 0x7f +#define MATCH_LUI 0x37 +#define MASK_LUI 0x7f +#define MATCH_AUIPC 0x17 +#define MASK_AUIPC 0x7f +#define MATCH_ADDI 0x13 +#define MASK_ADDI 0x707f +#define MATCH_SLLI 0x1013 +#define MASK_SLLI 0xfc00707f +#define MATCH_SLTI 0x2013 +#define MASK_SLTI 0x707f +#define MATCH_SLTIU 0x3013 +#define MASK_SLTIU 0x707f +#define MATCH_XORI 0x4013 +#define MASK_XORI 0x707f +#define MATCH_SRLI 0x5013 +#define MASK_SRLI 0xfc00707f +#define MATCH_SRAI 0x40005013 +#define MASK_SRAI 0xfc00707f +#define MATCH_ORI 0x6013 +#define MASK_ORI 0x707f +#define MATCH_ANDI 0x7013 +#define MASK_ANDI 0x707f +#define MATCH_ADD 0x33 +#define MASK_ADD 0xfe00707f +#define MATCH_SUB 0x40000033 +#define MASK_SUB 0xfe00707f +#define MATCH_SLL 0x1033 +#define MASK_SLL 0xfe00707f +#define MATCH_SLT 0x2033 +#define MASK_SLT 0xfe00707f +#define MATCH_SLTU 0x3033 +#define MASK_SLTU 0xfe00707f +#define MATCH_XOR 0x4033 +#define MASK_XOR 0xfe00707f +#define MATCH_SRL 0x5033 +#define MASK_SRL 0xfe00707f +#define MATCH_SRA 0x40005033 +#define MASK_SRA 0xfe00707f +#define MATCH_OR 0x6033 +#define MASK_OR 0xfe00707f +#define MATCH_AND 0x7033 +#define MASK_AND 0xfe00707f +#define MATCH_ADDIW 0x1b +#define MASK_ADDIW 0x707f +#define MATCH_SLLIW 0x101b +#define MASK_SLLIW 0xfe00707f +#define MATCH_SRLIW 0x501b +#define MASK_SRLIW 0xfe00707f +#define MATCH_SRAIW 0x4000501b +#define MASK_SRAIW 0xfe00707f +#define MATCH_ADDW 0x3b +#define MASK_ADDW 0xfe00707f +#define MATCH_SUBW 0x4000003b +#define MASK_SUBW 0xfe00707f +#define MATCH_SLLW 0x103b +#define MASK_SLLW 0xfe00707f +#define MATCH_SRLW 0x503b +#define MASK_SRLW 0xfe00707f +#define MATCH_SRAW 0x4000503b +#define MASK_SRAW 0xfe00707f +#define MATCH_LB 0x3 +#define MASK_LB 0x707f +#define MATCH_LH 0x1003 +#define MASK_LH 0x707f +#define MATCH_LW 0x2003 +#define MASK_LW 0x707f +#define MATCH_LD 0x3003 +#define MASK_LD 0x707f +#define MATCH_LBU 0x4003 +#define MASK_LBU 0x707f +#define MATCH_LHU 0x5003 +#define MASK_LHU 0x707f +#define MATCH_LWU 0x6003 +#define MASK_LWU 0x707f +#define MATCH_SB 0x23 +#define MASK_SB 0x707f +#define MATCH_SH 0x1023 +#define MASK_SH 0x707f +#define MATCH_SW 0x2023 +#define MASK_SW 0x707f +#define MATCH_SD 0x3023 +#define MASK_SD 0x707f +#define MATCH_FENCE 0xf +#define MASK_FENCE 0x707f +#define MATCH_FENCE_I 0x100f +#define MASK_FENCE_I 0x707f +#define MATCH_MUL 0x2000033 +#define MASK_MUL 0xfe00707f +#define MATCH_MULH 0x2001033 +#define MASK_MULH 0xfe00707f +#define MATCH_MULHSU 0x2002033 +#define MASK_MULHSU 0xfe00707f +#define MATCH_MULHU 0x2003033 +#define MASK_MULHU 0xfe00707f +#define MATCH_DIV 0x2004033 +#define MASK_DIV 0xfe00707f +#define MATCH_DIVU 0x2005033 +#define MASK_DIVU 0xfe00707f +#define MATCH_REM 0x2006033 +#define MASK_REM 0xfe00707f +#define MATCH_REMU 0x2007033 +#define MASK_REMU 0xfe00707f +#define MATCH_MULW 0x200003b +#define MASK_MULW 0xfe00707f +#define MATCH_DIVW 0x200403b +#define MASK_DIVW 0xfe00707f +#define MATCH_DIVUW 0x200503b +#define MASK_DIVUW 0xfe00707f +#define MATCH_REMW 0x200603b +#define MASK_REMW 0xfe00707f +#define MATCH_REMUW 0x200703b +#define MASK_REMUW 0xfe00707f +#define MATCH_AMOADD_W 0x202f +#define MASK_AMOADD_W 0xf800707f +#define MATCH_AMOXOR_W 0x2000202f +#define MASK_AMOXOR_W 0xf800707f +#define MATCH_AMOOR_W 0x4000202f +#define MASK_AMOOR_W 0xf800707f +#define MATCH_AMOAND_W 0x6000202f +#define MASK_AMOAND_W 0xf800707f +#define MATCH_AMOMIN_W 0x8000202f +#define MASK_AMOMIN_W 0xf800707f +#define MATCH_AMOMAX_W 0xa000202f +#define MASK_AMOMAX_W 0xf800707f +#define MATCH_AMOMINU_W 0xc000202f +#define MASK_AMOMINU_W 0xf800707f +#define MATCH_AMOMAXU_W 0xe000202f +#define MASK_AMOMAXU_W 0xf800707f +#define MATCH_AMOSWAP_W 0x800202f +#define MASK_AMOSWAP_W 0xf800707f +#define MATCH_LR_W 0x1000202f +#define MASK_LR_W 0xf9f0707f +#define MATCH_SC_W 0x1800202f +#define MASK_SC_W 0xf800707f +#define MATCH_AMOADD_D 0x302f +#define MASK_AMOADD_D 0xf800707f +#define MATCH_AMOXOR_D 0x2000302f +#define MASK_AMOXOR_D 0xf800707f +#define MATCH_AMOOR_D 0x4000302f +#define MASK_AMOOR_D 0xf800707f +#define MATCH_AMOAND_D 0x6000302f +#define MASK_AMOAND_D 0xf800707f +#define MATCH_AMOMIN_D 0x8000302f +#define MASK_AMOMIN_D 0xf800707f +#define MATCH_AMOMAX_D 0xa000302f +#define MASK_AMOMAX_D 0xf800707f +#define MATCH_AMOMINU_D 0xc000302f +#define MASK_AMOMINU_D 0xf800707f +#define MATCH_AMOMAXU_D 0xe000302f +#define MASK_AMOMAXU_D 0xf800707f +#define MATCH_AMOSWAP_D 0x800302f +#define MASK_AMOSWAP_D 0xf800707f +#define MATCH_LR_D 0x1000302f +#define MASK_LR_D 0xf9f0707f +#define MATCH_SC_D 0x1800302f +#define MASK_SC_D 0xf800707f +#define MATCH_ECALL 0x73 +#define MASK_ECALL 0xffffffff +#define MATCH_EBREAK 0x100073 +#define MASK_EBREAK 0xffffffff +#define MATCH_URET 0x200073 +#define MASK_URET 0xffffffff +#define MATCH_SRET 0x10200073 +#define MASK_SRET 0xffffffff +#define MATCH_HRET 0x20200073 +#define MASK_HRET 0xffffffff +#define MATCH_MRET 0x30200073 +#define MASK_MRET 0xffffffff +#define MATCH_DRET 0x7b200073 +#define MASK_DRET 0xffffffff +#define MATCH_SFENCE_VM 0x10400073 +#define MASK_SFENCE_VM 0xfff07fff +#define MATCH_WFI 0x10500073 +#define MASK_WFI 0xffffffff +#define MATCH_CSRRW 0x1073 +#define MASK_CSRRW 0x707f +#define MATCH_CSRRS 0x2073 +#define MASK_CSRRS 0x707f +#define MATCH_CSRRC 0x3073 +#define MASK_CSRRC 0x707f +#define MATCH_CSRRWI 0x5073 +#define MASK_CSRRWI 0x707f +#define MATCH_CSRRSI 0x6073 +#define MASK_CSRRSI 0x707f +#define MATCH_CSRRCI 0x7073 +#define MASK_CSRRCI 0x707f +#define MATCH_FADD_S 0x53 +#define MASK_FADD_S 0xfe00007f +#define MATCH_FSUB_S 0x8000053 +#define MASK_FSUB_S 0xfe00007f +#define MATCH_FMUL_S 0x10000053 +#define MASK_FMUL_S 0xfe00007f +#define MATCH_FDIV_S 0x18000053 +#define MASK_FDIV_S 0xfe00007f +#define MATCH_FSGNJ_S 0x20000053 +#define MASK_FSGNJ_S 0xfe00707f +#define MATCH_FSGNJN_S 0x20001053 +#define MASK_FSGNJN_S 0xfe00707f +#define MATCH_FSGNJX_S 0x20002053 +#define MASK_FSGNJX_S 0xfe00707f +#define MATCH_FMIN_S 0x28000053 +#define MASK_FMIN_S 0xfe00707f +#define MATCH_FMAX_S 0x28001053 +#define MASK_FMAX_S 0xfe00707f +#define MATCH_FSQRT_S 0x58000053 +#define MASK_FSQRT_S 0xfff0007f +#define MATCH_FADD_D 0x2000053 +#define MASK_FADD_D 0xfe00007f +#define MATCH_FSUB_D 0xa000053 +#define MASK_FSUB_D 0xfe00007f +#define MATCH_FMUL_D 0x12000053 +#define MASK_FMUL_D 0xfe00007f +#define MATCH_FDIV_D 0x1a000053 +#define MASK_FDIV_D 0xfe00007f +#define MATCH_FSGNJ_D 0x22000053 +#define MASK_FSGNJ_D 0xfe00707f +#define MATCH_FSGNJN_D 0x22001053 +#define MASK_FSGNJN_D 0xfe00707f +#define MATCH_FSGNJX_D 0x22002053 +#define MASK_FSGNJX_D 0xfe00707f +#define MATCH_FMIN_D 0x2a000053 +#define MASK_FMIN_D 0xfe00707f +#define MATCH_FMAX_D 0x2a001053 +#define MASK_FMAX_D 0xfe00707f +#define MATCH_FCVT_S_D 0x40100053 +#define MASK_FCVT_S_D 0xfff0007f +#define MATCH_FCVT_D_S 0x42000053 +#define MASK_FCVT_D_S 0xfff0007f +#define MATCH_FSQRT_D 0x5a000053 +#define MASK_FSQRT_D 0xfff0007f +#define MATCH_FLE_S 0xa0000053 +#define MASK_FLE_S 0xfe00707f +#define MATCH_FLT_S 0xa0001053 +#define MASK_FLT_S 0xfe00707f +#define MATCH_FEQ_S 0xa0002053 +#define MASK_FEQ_S 0xfe00707f +#define MATCH_FLE_D 0xa2000053 +#define MASK_FLE_D 0xfe00707f +#define MATCH_FLT_D 0xa2001053 +#define MASK_FLT_D 0xfe00707f +#define MATCH_FEQ_D 0xa2002053 +#define MASK_FEQ_D 0xfe00707f +#define MATCH_FCVT_W_S 0xc0000053 +#define MASK_FCVT_W_S 0xfff0007f +#define MATCH_FCVT_WU_S 0xc0100053 +#define MASK_FCVT_WU_S 0xfff0007f +#define MATCH_FCVT_L_S 0xc0200053 +#define MASK_FCVT_L_S 0xfff0007f +#define MATCH_FCVT_LU_S 0xc0300053 +#define MASK_FCVT_LU_S 0xfff0007f +#define MATCH_FMV_X_S 0xe0000053 +#define MASK_FMV_X_S 0xfff0707f +#define MATCH_FCLASS_S 0xe0001053 +#define MASK_FCLASS_S 0xfff0707f +#define MATCH_FCVT_W_D 0xc2000053 +#define MASK_FCVT_W_D 0xfff0007f +#define MATCH_FCVT_WU_D 0xc2100053 +#define MASK_FCVT_WU_D 0xfff0007f +#define MATCH_FCVT_L_D 0xc2200053 +#define MASK_FCVT_L_D 0xfff0007f +#define MATCH_FCVT_LU_D 0xc2300053 +#define MASK_FCVT_LU_D 0xfff0007f +#define MATCH_FMV_X_D 0xe2000053 +#define MASK_FMV_X_D 0xfff0707f +#define MATCH_FCLASS_D 0xe2001053 +#define MASK_FCLASS_D 0xfff0707f +#define MATCH_FCVT_S_W 0xd0000053 +#define MASK_FCVT_S_W 0xfff0007f +#define MATCH_FCVT_S_WU 0xd0100053 +#define MASK_FCVT_S_WU 0xfff0007f +#define MATCH_FCVT_S_L 0xd0200053 +#define MASK_FCVT_S_L 0xfff0007f +#define MATCH_FCVT_S_LU 0xd0300053 +#define MASK_FCVT_S_LU 0xfff0007f +#define MATCH_FMV_S_X 0xf0000053 +#define MASK_FMV_S_X 0xfff0707f +#define MATCH_FCVT_D_W 0xd2000053 +#define MASK_FCVT_D_W 0xfff0007f +#define MATCH_FCVT_D_WU 0xd2100053 +#define MASK_FCVT_D_WU 0xfff0007f +#define MATCH_FCVT_D_L 0xd2200053 +#define MASK_FCVT_D_L 0xfff0007f +#define MATCH_FCVT_D_LU 0xd2300053 +#define MASK_FCVT_D_LU 0xfff0007f +#define MATCH_FMV_D_X 0xf2000053 +#define MASK_FMV_D_X 0xfff0707f +#define MATCH_FLW 0x2007 +#define MASK_FLW 0x707f +#define MATCH_FLD 0x3007 +#define MASK_FLD 0x707f +#define MATCH_FSW 0x2027 +#define MASK_FSW 0x707f +#define MATCH_FSD 0x3027 +#define MASK_FSD 0x707f +#define MATCH_FMADD_S 0x43 +#define MASK_FMADD_S 0x600007f +#define MATCH_FMSUB_S 0x47 +#define MASK_FMSUB_S 0x600007f +#define MATCH_FNMSUB_S 0x4b +#define MASK_FNMSUB_S 0x600007f +#define MATCH_FNMADD_S 0x4f +#define MASK_FNMADD_S 0x600007f +#define MATCH_FMADD_D 0x2000043 +#define MASK_FMADD_D 0x600007f +#define MATCH_FMSUB_D 0x2000047 +#define MASK_FMSUB_D 0x600007f +#define MATCH_FNMSUB_D 0x200004b +#define MASK_FNMSUB_D 0x600007f +#define MATCH_FNMADD_D 0x200004f +#define MASK_FNMADD_D 0x600007f +#define MATCH_C_NOP 0x1 +#define MASK_C_NOP 0xffff +#define MATCH_C_ADDI16SP 0x6101 +#define MASK_C_ADDI16SP 0xef83 +#define MATCH_C_JR 0x8002 +#define MASK_C_JR 0xf07f +#define MATCH_C_JALR 0x9002 +#define MASK_C_JALR 0xf07f +#define MATCH_C_EBREAK 0x9002 +#define MASK_C_EBREAK 0xffff +#define MATCH_C_LD 0x6000 +#define MASK_C_LD 0xe003 +#define MATCH_C_SD 0xe000 +#define MASK_C_SD 0xe003 +#define MATCH_C_ADDIW 0x2001 +#define MASK_C_ADDIW 0xe003 +#define MATCH_C_LDSP 0x6002 +#define MASK_C_LDSP 0xe003 +#define MATCH_C_SDSP 0xe002 +#define MASK_C_SDSP 0xe003 +#define MATCH_C_ADDI4SPN 0x0 +#define MASK_C_ADDI4SPN 0xe003 +#define MATCH_C_FLD 0x2000 +#define MASK_C_FLD 0xe003 +#define MATCH_C_LW 0x4000 +#define MASK_C_LW 0xe003 +#define MATCH_C_FLW 0x6000 +#define MASK_C_FLW 0xe003 +#define MATCH_C_FSD 0xa000 +#define MASK_C_FSD 0xe003 +#define MATCH_C_SW 0xc000 +#define MASK_C_SW 0xe003 +#define MATCH_C_FSW 0xe000 +#define MASK_C_FSW 0xe003 +#define MATCH_C_ADDI 0x1 +#define MASK_C_ADDI 0xe003 +#define MATCH_C_JAL 0x2001 +#define MASK_C_JAL 0xe003 +#define MATCH_C_LI 0x4001 +#define MASK_C_LI 0xe003 +#define MATCH_C_LUI 0x6001 +#define MASK_C_LUI 0xe003 +#define MATCH_C_SRLI 0x8001 +#define MASK_C_SRLI 0xec03 +#define MATCH_C_SRAI 0x8401 +#define MASK_C_SRAI 0xec03 +#define MATCH_C_ANDI 0x8801 +#define MASK_C_ANDI 0xec03 +#define MATCH_C_SUB 0x8c01 +#define MASK_C_SUB 0xfc63 +#define MATCH_C_XOR 0x8c21 +#define MASK_C_XOR 0xfc63 +#define MATCH_C_OR 0x8c41 +#define MASK_C_OR 0xfc63 +#define MATCH_C_AND 0x8c61 +#define MASK_C_AND 0xfc63 +#define MATCH_C_SUBW 0x9c01 +#define MASK_C_SUBW 0xfc63 +#define MATCH_C_ADDW 0x9c21 +#define MASK_C_ADDW 0xfc63 +#define MATCH_C_J 0xa001 +#define MASK_C_J 0xe003 +#define MATCH_C_BEQZ 0xc001 +#define MASK_C_BEQZ 0xe003 +#define MATCH_C_BNEZ 0xe001 +#define MASK_C_BNEZ 0xe003 +#define MATCH_C_SLLI 0x2 +#define MASK_C_SLLI 0xe003 +#define MATCH_C_FLDSP 0x2002 +#define MASK_C_FLDSP 0xe003 +#define MATCH_C_LWSP 0x4002 +#define MASK_C_LWSP 0xe003 +#define MATCH_C_FLWSP 0x6002 +#define MASK_C_FLWSP 0xe003 +#define MATCH_C_MV 0x8002 +#define MASK_C_MV 0xf003 +#define MATCH_C_ADD 0x9002 +#define MASK_C_ADD 0xf003 +#define MATCH_C_FSDSP 0xa002 +#define MASK_C_FSDSP 0xe003 +#define MATCH_C_SWSP 0xc002 +#define MASK_C_SWSP 0xe003 +#define MATCH_C_FSWSP 0xe002 +#define MASK_C_FSWSP 0xe003 +#define MATCH_CUSTOM0 0xb +#define MASK_CUSTOM0 0x707f +#define MATCH_CUSTOM0_RS1 0x200b +#define MASK_CUSTOM0_RS1 0x707f +#define MATCH_CUSTOM0_RS1_RS2 0x300b +#define MASK_CUSTOM0_RS1_RS2 0x707f +#define MATCH_CUSTOM0_RD 0x400b +#define MASK_CUSTOM0_RD 0x707f +#define MATCH_CUSTOM0_RD_RS1 0x600b +#define MASK_CUSTOM0_RD_RS1 0x707f +#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b +#define MASK_CUSTOM0_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM1 0x2b +#define MASK_CUSTOM1 0x707f +#define MATCH_CUSTOM1_RS1 0x202b +#define MASK_CUSTOM1_RS1 0x707f +#define MATCH_CUSTOM1_RS1_RS2 0x302b +#define MASK_CUSTOM1_RS1_RS2 0x707f +#define MATCH_CUSTOM1_RD 0x402b +#define MASK_CUSTOM1_RD 0x707f +#define MATCH_CUSTOM1_RD_RS1 0x602b +#define MASK_CUSTOM1_RD_RS1 0x707f +#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b +#define MASK_CUSTOM1_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM2 0x5b +#define MASK_CUSTOM2 0x707f +#define MATCH_CUSTOM2_RS1 0x205b +#define MASK_CUSTOM2_RS1 0x707f +#define MATCH_CUSTOM2_RS1_RS2 0x305b +#define MASK_CUSTOM2_RS1_RS2 0x707f +#define MATCH_CUSTOM2_RD 0x405b +#define MASK_CUSTOM2_RD 0x707f +#define MATCH_CUSTOM2_RD_RS1 0x605b +#define MASK_CUSTOM2_RD_RS1 0x707f +#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b +#define MASK_CUSTOM2_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM3 0x7b +#define MASK_CUSTOM3 0x707f +#define MATCH_CUSTOM3_RS1 0x207b +#define MASK_CUSTOM3_RS1 0x707f +#define MATCH_CUSTOM3_RS1_RS2 0x307b +#define MASK_CUSTOM3_RS1_RS2 0x707f +#define MATCH_CUSTOM3_RD 0x407b +#define MASK_CUSTOM3_RD 0x707f +#define MATCH_CUSTOM3_RD_RS1 0x607b +#define MASK_CUSTOM3_RD_RS1 0x707f +#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b +#define MASK_CUSTOM3_RD_RS1_RS2 0x707f +#define CSR_FFLAGS 0x1 +#define CSR_FRM 0x2 +#define CSR_FCSR 0x3 +#define CSR_CYCLE 0xc00 +#define CSR_TIME 0xc01 +#define CSR_INSTRET 0xc02 +#define CSR_HPMCOUNTER3 0xc03 +#define CSR_HPMCOUNTER4 0xc04 +#define CSR_HPMCOUNTER5 0xc05 +#define CSR_HPMCOUNTER6 0xc06 +#define CSR_HPMCOUNTER7 0xc07 +#define CSR_HPMCOUNTER8 0xc08 +#define CSR_HPMCOUNTER9 0xc09 +#define CSR_HPMCOUNTER10 0xc0a +#define CSR_HPMCOUNTER11 0xc0b +#define CSR_HPMCOUNTER12 0xc0c +#define CSR_HPMCOUNTER13 0xc0d +#define CSR_HPMCOUNTER14 0xc0e +#define CSR_HPMCOUNTER15 0xc0f +#define CSR_HPMCOUNTER16 0xc10 +#define CSR_HPMCOUNTER17 0xc11 +#define CSR_HPMCOUNTER18 0xc12 +#define CSR_HPMCOUNTER19 0xc13 +#define CSR_HPMCOUNTER20 0xc14 +#define CSR_HPMCOUNTER21 0xc15 +#define CSR_HPMCOUNTER22 0xc16 +#define CSR_HPMCOUNTER23 0xc17 +#define CSR_HPMCOUNTER24 0xc18 +#define CSR_HPMCOUNTER25 0xc19 +#define CSR_HPMCOUNTER26 0xc1a +#define CSR_HPMCOUNTER27 0xc1b +#define CSR_HPMCOUNTER28 0xc1c +#define CSR_HPMCOUNTER29 0xc1d +#define CSR_HPMCOUNTER30 0xc1e +#define CSR_HPMCOUNTER31 0xc1f +#define CSR_SSTATUS 0x100 +#define CSR_SIE 0x104 +#define CSR_STVEC 0x105 +#define CSR_SSCRATCH 0x140 +#define CSR_SEPC 0x141 +#define CSR_SCAUSE 0x142 +#define CSR_SBADADDR 0x143 +#define CSR_SIP 0x144 +#define CSR_SPTBR 0x180 +#define CSR_MSTATUS 0x300 +#define CSR_MISA 0x301 +#define CSR_MEDELEG 0x302 +#define CSR_MIDELEG 0x303 +#define CSR_MIE 0x304 +#define CSR_MTVEC 0x305 +#define CSR_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MBADADDR 0x343 +#define CSR_MIP 0x344 +#define CSR_TSELECT 0x7a0 +#define CSR_TDATA1 0x7a1 +#define CSR_TDATA2 0x7a2 +#define CSR_TDATA3 0x7a3 +#define CSR_DCSR 0x7b0 +#define CSR_DPC 0x7b1 +#define CSR_DSCRATCH 0x7b2 +#define CSR_MCYCLE 0xb00 +#define CSR_MINSTRET 0xb02 +#define CSR_MHPMCOUNTER3 0xb03 +#define CSR_MHPMCOUNTER4 0xb04 +#define CSR_MHPMCOUNTER5 0xb05 +#define CSR_MHPMCOUNTER6 0xb06 +#define CSR_MHPMCOUNTER7 0xb07 +#define CSR_MHPMCOUNTER8 0xb08 +#define CSR_MHPMCOUNTER9 0xb09 +#define CSR_MHPMCOUNTER10 0xb0a +#define CSR_MHPMCOUNTER11 0xb0b +#define CSR_MHPMCOUNTER12 0xb0c +#define CSR_MHPMCOUNTER13 0xb0d +#define CSR_MHPMCOUNTER14 0xb0e +#define CSR_MHPMCOUNTER15 0xb0f +#define CSR_MHPMCOUNTER16 0xb10 +#define CSR_MHPMCOUNTER17 0xb11 +#define CSR_MHPMCOUNTER18 0xb12 +#define CSR_MHPMCOUNTER19 0xb13 +#define CSR_MHPMCOUNTER20 0xb14 +#define CSR_MHPMCOUNTER21 0xb15 +#define CSR_MHPMCOUNTER22 0xb16 +#define CSR_MHPMCOUNTER23 0xb17 +#define CSR_MHPMCOUNTER24 0xb18 +#define CSR_MHPMCOUNTER25 0xb19 +#define CSR_MHPMCOUNTER26 0xb1a +#define CSR_MHPMCOUNTER27 0xb1b +#define CSR_MHPMCOUNTER28 0xb1c +#define CSR_MHPMCOUNTER29 0xb1d +#define CSR_MHPMCOUNTER30 0xb1e +#define CSR_MHPMCOUNTER31 0xb1f +#define CSR_MUCOUNTEREN 0x320 +#define CSR_MSCOUNTEREN 0x321 +#define CSR_MHPMEVENT3 0x323 +#define CSR_MHPMEVENT4 0x324 +#define CSR_MHPMEVENT5 0x325 +#define CSR_MHPMEVENT6 0x326 +#define CSR_MHPMEVENT7 0x327 +#define CSR_MHPMEVENT8 0x328 +#define CSR_MHPMEVENT9 0x329 +#define CSR_MHPMEVENT10 0x32a +#define CSR_MHPMEVENT11 0x32b +#define CSR_MHPMEVENT12 0x32c +#define CSR_MHPMEVENT13 0x32d +#define CSR_MHPMEVENT14 0x32e +#define CSR_MHPMEVENT15 0x32f +#define CSR_MHPMEVENT16 0x330 +#define CSR_MHPMEVENT17 0x331 +#define CSR_MHPMEVENT18 0x332 +#define CSR_MHPMEVENT19 0x333 +#define CSR_MHPMEVENT20 0x334 +#define CSR_MHPMEVENT21 0x335 +#define CSR_MHPMEVENT22 0x336 +#define CSR_MHPMEVENT23 0x337 +#define CSR_MHPMEVENT24 0x338 +#define CSR_MHPMEVENT25 0x339 +#define CSR_MHPMEVENT26 0x33a +#define CSR_MHPMEVENT27 0x33b +#define CSR_MHPMEVENT28 0x33c +#define CSR_MHPMEVENT29 0x33d +#define CSR_MHPMEVENT30 0x33e +#define CSR_MHPMEVENT31 0x33f +#define CSR_MVENDORID 0xf11 +#define CSR_MARCHID 0xf12 +#define CSR_MIMPID 0xf13 +#define CSR_MHARTID 0xf14 +#define CSR_CYCLEH 0xc80 +#define CSR_TIMEH 0xc81 +#define CSR_INSTRETH 0xc82 +#define CSR_HPMCOUNTER3H 0xc83 +#define CSR_HPMCOUNTER4H 0xc84 +#define CSR_HPMCOUNTER5H 0xc85 +#define CSR_HPMCOUNTER6H 0xc86 +#define CSR_HPMCOUNTER7H 0xc87 +#define CSR_HPMCOUNTER8H 0xc88 +#define CSR_HPMCOUNTER9H 0xc89 +#define CSR_HPMCOUNTER10H 0xc8a +#define CSR_HPMCOUNTER11H 0xc8b +#define CSR_HPMCOUNTER12H 0xc8c +#define CSR_HPMCOUNTER13H 0xc8d +#define CSR_HPMCOUNTER14H 0xc8e +#define CSR_HPMCOUNTER15H 0xc8f +#define CSR_HPMCOUNTER16H 0xc90 +#define CSR_HPMCOUNTER17H 0xc91 +#define CSR_HPMCOUNTER18H 0xc92 +#define CSR_HPMCOUNTER19H 0xc93 +#define CSR_HPMCOUNTER20H 0xc94 +#define CSR_HPMCOUNTER21H 0xc95 +#define CSR_HPMCOUNTER22H 0xc96 +#define CSR_HPMCOUNTER23H 0xc97 +#define CSR_HPMCOUNTER24H 0xc98 +#define CSR_HPMCOUNTER25H 0xc99 +#define CSR_HPMCOUNTER26H 0xc9a +#define CSR_HPMCOUNTER27H 0xc9b +#define CSR_HPMCOUNTER28H 0xc9c +#define CSR_HPMCOUNTER29H 0xc9d +#define CSR_HPMCOUNTER30H 0xc9e +#define CSR_HPMCOUNTER31H 0xc9f +#define CSR_MCYCLEH 0xb80 +#define CSR_MINSTRETH 0xb82 +#define CSR_MHPMCOUNTER3H 0xb83 +#define CSR_MHPMCOUNTER4H 0xb84 +#define CSR_MHPMCOUNTER5H 0xb85 +#define CSR_MHPMCOUNTER6H 0xb86 +#define CSR_MHPMCOUNTER7H 0xb87 +#define CSR_MHPMCOUNTER8H 0xb88 +#define CSR_MHPMCOUNTER9H 0xb89 +#define CSR_MHPMCOUNTER10H 0xb8a +#define CSR_MHPMCOUNTER11H 0xb8b +#define CSR_MHPMCOUNTER12H 0xb8c +#define CSR_MHPMCOUNTER13H 0xb8d +#define CSR_MHPMCOUNTER14H 0xb8e +#define CSR_MHPMCOUNTER15H 0xb8f +#define CSR_MHPMCOUNTER16H 0xb90 +#define CSR_MHPMCOUNTER17H 0xb91 +#define CSR_MHPMCOUNTER18H 0xb92 +#define CSR_MHPMCOUNTER19H 0xb93 +#define CSR_MHPMCOUNTER20H 0xb94 +#define CSR_MHPMCOUNTER21H 0xb95 +#define CSR_MHPMCOUNTER22H 0xb96 +#define CSR_MHPMCOUNTER23H 0xb97 +#define CSR_MHPMCOUNTER24H 0xb98 +#define CSR_MHPMCOUNTER25H 0xb99 +#define CSR_MHPMCOUNTER26H 0xb9a +#define CSR_MHPMCOUNTER27H 0xb9b +#define CSR_MHPMCOUNTER28H 0xb9c +#define CSR_MHPMCOUNTER29H 0xb9d +#define CSR_MHPMCOUNTER30H 0xb9e +#define CSR_MHPMCOUNTER31H 0xb9f +#define CAUSE_MISALIGNED_FETCH 0x0 +#define CAUSE_FAULT_FETCH 0x1 +#define CAUSE_ILLEGAL_INSTRUCTION 0x2 +#define CAUSE_BREAKPOINT 0x3 +#define CAUSE_MISALIGNED_LOAD 0x4 +#define CAUSE_FAULT_LOAD 0x5 +#define CAUSE_MISALIGNED_STORE 0x6 +#define CAUSE_FAULT_STORE 0x7 +#define CAUSE_USER_ECALL 0x8 +#define CAUSE_SUPERVISOR_ECALL 0x9 +#define CAUSE_HYPERVISOR_ECALL 0xa +#define CAUSE_MACHINE_ECALL 0xb +#endif +#ifdef DECLARE_INSN +DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ) +DECLARE_INSN(bne, MATCH_BNE, MASK_BNE) +DECLARE_INSN(blt, MATCH_BLT, MASK_BLT) +DECLARE_INSN(bge, MATCH_BGE, MASK_BGE) +DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU) +DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU) +DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR) +DECLARE_INSN(jal, MATCH_JAL, MASK_JAL) +DECLARE_INSN(lui, MATCH_LUI, MASK_LUI) +DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC) +DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI) +DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI) +DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI) +DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU) +DECLARE_INSN(xori, MATCH_XORI, MASK_XORI) +DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI) +DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI) +DECLARE_INSN(ori, MATCH_ORI, MASK_ORI) +DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI) +DECLARE_INSN(add, MATCH_ADD, MASK_ADD) +DECLARE_INSN(sub, MATCH_SUB, MASK_SUB) +DECLARE_INSN(sll, MATCH_SLL, MASK_SLL) +DECLARE_INSN(slt, MATCH_SLT, MASK_SLT) +DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU) +DECLARE_INSN(xor, MATCH_XOR, MASK_XOR) +DECLARE_INSN(srl, MATCH_SRL, MASK_SRL) +DECLARE_INSN(sra, MATCH_SRA, MASK_SRA) +DECLARE_INSN(or, MATCH_OR, MASK_OR) +DECLARE_INSN(and, MATCH_AND, MASK_AND) +DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW) +DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW) +DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW) +DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW) +DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW) +DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW) +DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW) +DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW) +DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW) +DECLARE_INSN(lb, MATCH_LB, MASK_LB) +DECLARE_INSN(lh, MATCH_LH, MASK_LH) +DECLARE_INSN(lw, MATCH_LW, MASK_LW) +DECLARE_INSN(ld, MATCH_LD, MASK_LD) +DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU) +DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU) +DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU) +DECLARE_INSN(sb, MATCH_SB, MASK_SB) +DECLARE_INSN(sh, MATCH_SH, MASK_SH) +DECLARE_INSN(sw, MATCH_SW, MASK_SW) +DECLARE_INSN(sd, MATCH_SD, MASK_SD) +DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE) +DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I) +DECLARE_INSN(mul, MATCH_MUL, MASK_MUL) +DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH) +DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU) +DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU) +DECLARE_INSN(div, MATCH_DIV, MASK_DIV) +DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU) +DECLARE_INSN(rem, MATCH_REM, MASK_REM) +DECLARE_INSN(remu, MATCH_REMU, MASK_REMU) +DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW) +DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW) +DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW) +DECLARE_INSN(remw, MATCH_REMW, MASK_REMW) +DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW) +DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W) +DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W) +DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W) +DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W) +DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W) +DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W) +DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W) +DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W) +DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W) +DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W) +DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W) +DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D) +DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D) +DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D) +DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D) +DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D) +DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D) +DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D) +DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D) +DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D) +DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D) +DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D) +DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL) +DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK) +DECLARE_INSN(uret, MATCH_URET, MASK_URET) +DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) +DECLARE_INSN(hret, MATCH_HRET, MASK_HRET) +DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) +DECLARE_INSN(dret, MATCH_DRET, MASK_DRET) +DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM) +DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI) +DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) +DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS) +DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC) +DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI) +DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI) +DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI) +DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S) +DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S) +DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S) +DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S) +DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S) +DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S) +DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S) +DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S) +DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S) +DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S) +DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D) +DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D) +DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D) +DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D) +DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D) +DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D) +DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D) +DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D) +DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D) +DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D) +DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S) +DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D) +DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S) +DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S) +DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S) +DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D) +DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D) +DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D) +DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S) +DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S) +DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S) +DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S) +DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S) +DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S) +DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D) +DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D) +DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D) +DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D) +DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D) +DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D) +DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W) +DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU) +DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L) +DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU) +DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X) +DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W) +DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) +DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L) +DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU) +DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X) +DECLARE_INSN(flw, MATCH_FLW, MASK_FLW) +DECLARE_INSN(fld, MATCH_FLD, MASK_FLD) +DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW) +DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD) +DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S) +DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S) +DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S) +DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S) +DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D) +DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D) +DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D) +DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D) +DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP) +DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP) +DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR) +DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR) +DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK) +DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD) +DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD) +DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW) +DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP) +DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP) +DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN) +DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD) +DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW) +DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW) +DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD) +DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW) +DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW) +DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI) +DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL) +DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI) +DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI) +DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI) +DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI) +DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI) +DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB) +DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR) +DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR) +DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND) +DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW) +DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW) +DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J) +DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ) +DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ) +DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI) +DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP) +DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP) +DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP) +DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV) +DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD) +DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP) +DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP) +DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP) +DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0) +DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1) +DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2) +DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD) +DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1) +DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2) +DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1) +DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1) +DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2) +DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD) +DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1) +DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2) +DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2) +DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1) +DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2) +DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD) +DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1) +DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2) +DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3) +DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1) +DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2) +DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD) +DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1) +DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2) +#endif +#ifdef DECLARE_CSR +DECLARE_CSR(fflags, CSR_FFLAGS) +DECLARE_CSR(frm, CSR_FRM) +DECLARE_CSR(fcsr, CSR_FCSR) +DECLARE_CSR(cycle, CSR_CYCLE) +DECLARE_CSR(time, CSR_TIME) +DECLARE_CSR(instret, CSR_INSTRET) +DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3) +DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4) +DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5) +DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6) +DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7) +DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8) +DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9) +DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10) +DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11) +DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12) +DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13) +DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14) +DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15) +DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16) +DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17) +DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18) +DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19) +DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20) +DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21) +DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22) +DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23) +DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24) +DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25) +DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26) +DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27) +DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28) +DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29) +DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30) +DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31) +DECLARE_CSR(sstatus, CSR_SSTATUS) +DECLARE_CSR(sie, CSR_SIE) +DECLARE_CSR(stvec, CSR_STVEC) +DECLARE_CSR(sscratch, CSR_SSCRATCH) +DECLARE_CSR(sepc, CSR_SEPC) +DECLARE_CSR(scause, CSR_SCAUSE) +DECLARE_CSR(sbadaddr, CSR_SBADADDR) +DECLARE_CSR(sip, CSR_SIP) +DECLARE_CSR(sptbr, CSR_SPTBR) +DECLARE_CSR(mstatus, CSR_MSTATUS) +DECLARE_CSR(misa, CSR_MISA) +DECLARE_CSR(medeleg, CSR_MEDELEG) +DECLARE_CSR(mideleg, CSR_MIDELEG) +DECLARE_CSR(mie, CSR_MIE) +DECLARE_CSR(mtvec, CSR_MTVEC) +DECLARE_CSR(mscratch, CSR_MSCRATCH) +DECLARE_CSR(mepc, CSR_MEPC) +DECLARE_CSR(mcause, CSR_MCAUSE) +DECLARE_CSR(mbadaddr, CSR_MBADADDR) +DECLARE_CSR(mip, CSR_MIP) +DECLARE_CSR(tselect, CSR_TSELECT) +DECLARE_CSR(tdata1, CSR_TDATA1) +DECLARE_CSR(tdata2, CSR_TDATA2) +DECLARE_CSR(tdata3, CSR_TDATA3) +DECLARE_CSR(dcsr, CSR_DCSR) +DECLARE_CSR(dpc, CSR_DPC) +DECLARE_CSR(dscratch, CSR_DSCRATCH) +DECLARE_CSR(mcycle, CSR_MCYCLE) +DECLARE_CSR(minstret, CSR_MINSTRET) +DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3) +DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4) +DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5) +DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6) +DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7) +DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8) +DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9) +DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10) +DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11) +DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12) +DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13) +DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14) +DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15) +DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16) +DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17) +DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18) +DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19) +DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20) +DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21) +DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22) +DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23) +DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24) +DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25) +DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26) +DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27) +DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28) +DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29) +DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30) +DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31) +DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN) +DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN) +DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3) +DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4) +DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5) +DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6) +DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7) +DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8) +DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9) +DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10) +DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11) +DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12) +DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13) +DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14) +DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15) +DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16) +DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17) +DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18) +DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19) +DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20) +DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21) +DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22) +DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23) +DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24) +DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25) +DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26) +DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27) +DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28) +DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29) +DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30) +DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31) +DECLARE_CSR(mvendorid, CSR_MVENDORID) +DECLARE_CSR(marchid, CSR_MARCHID) +DECLARE_CSR(mimpid, CSR_MIMPID) +DECLARE_CSR(mhartid, CSR_MHARTID) +DECLARE_CSR(cycleh, CSR_CYCLEH) +DECLARE_CSR(timeh, CSR_TIMEH) +DECLARE_CSR(instreth, CSR_INSTRETH) +DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H) +DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H) +DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H) +DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H) +DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H) +DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H) +DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H) +DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H) +DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H) +DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H) +DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H) +DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H) +DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H) +DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H) +DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H) +DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H) +DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H) +DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H) +DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H) +DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H) +DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H) +DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H) +DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H) +DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H) +DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H) +DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H) +DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H) +DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H) +DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H) +DECLARE_CSR(mcycleh, CSR_MCYCLEH) +DECLARE_CSR(minstreth, CSR_MINSTRETH) +DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H) +DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H) +DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H) +DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H) +DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H) +DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H) +DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H) +DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H) +DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H) +DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H) +DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H) +DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H) +DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H) +DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H) +DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H) +DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H) +DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H) +DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H) +DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H) +DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H) +DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H) +DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H) +DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H) +DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H) +DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H) +DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H) +DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H) +DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H) +DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H) +#endif +#ifdef DECLARE_CAUSE +DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH) +DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH) +DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION) +DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT) +DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD) +DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD) +DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE) +DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE) +DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL) +DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL) +DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL) +DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL) +#endif diff --git a/bsp/qemu-riscv-virt64/driver/io.h b/bsp/qemu-riscv-virt64/driver/io.h new file mode 100644 index 0000000000..8915b55306 --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/io.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019-2020, Xim + * + * SPDX-License-Identifier: Apache-2.0 + * + */ +#ifndef ARCH_IO_H +#define ARCH_IO_H +#include +#define RISCV_FENCE(p, s) \ + __asm__ __volatile__ ("fence " #p "," #s : : : "memory") + +/* These barriers need to enforce ordering on both devices or memory. */ +#define mb() RISCV_FENCE(iorw,iorw) +#define rmb() RISCV_FENCE(ir,ir) +#define wmb() RISCV_FENCE(ow,ow) + +#define __arch_getl(a) (*(unsigned int *)(a)) +#define __arch_putl(v, a) (*(unsigned int *)(a) = (v)) + +#define dmb() mb() +#define __iormb() rmb() +#define __iowmb() wmb() + +static inline void writel(uint32_t val, volatile void *addr) +{ + __iowmb(); + __arch_putl(val, addr); +} + +static inline uint32_t readl(const volatile void *addr) +{ + uint32_t val; + + val = __arch_getl(addr); + __iormb(); + return val; +} + +static inline void write_reg( + uint32_t val, volatile void *addr, unsigned offset) +{ + writel(val, addr + offset); +} + +static inline uint32_t read_reg( + const volatile void *addr, unsigned offset) +{ + return readl(addr + offset); +} + +#endif // ARCH_IO_H \ No newline at end of file diff --git a/bsp/qemu-riscv-virt64/driver/sbi.h b/bsp/qemu-riscv-virt64/driver/sbi.h new file mode 100644 index 0000000000..18d2bb7ee0 --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/sbi.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2015 Regents of the University of California + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + */ + +#ifndef _ASM_RISCV_SBI_H +#define _ASM_RISCV_SBI_H + +#include +#include + +#define SBI_CALL(which, arg0, arg1, arg2) \ + ({ \ + register uintptr_t a0 asm("a0") = (uintptr_t)(arg0); \ + register uintptr_t a1 asm("a1") = (uintptr_t)(arg1); \ + register uintptr_t a2 asm("a2") = (uintptr_t)(arg2); \ + register uintptr_t a7 asm("a7") = (uintptr_t)(which); \ + asm volatile("ecall" \ + : "+r"(a0) \ + : "r"(a1), "r"(a2), "r"(a7) \ + : "memory"); \ + a0; \ + }) + +/* Lazy implementations until SBI is finalized */ +#define SBI_CALL_0(which) SBI_CALL(which, 0, 0, 0) +#define SBI_CALL_1(which, arg0) SBI_CALL(which, arg0, 0, 0) +#define SBI_CALL_2(which, arg0, arg1) \ + SBI_CALL(which, arg0, arg1, 0) +#define SBI_CALL_3(which, arg0, arg1, arg2) \ + SBI_CALL(which, arg0, arg1, arg2) + +static inline void sbi_console_putstr(char *str) +{ + // FIXME: machine mode cannot access `str` + // if `str` is a virtual address. So we use + // SBI_CONSOLE_PUTCHAR to implement this function. + while (*str != '\0') { + SBI_CALL_1(SBI_CONSOLE_PUTCHAR, *str++); + } +} + +static inline uintptr_t sbi_sd_write( + unsigned int mem_address, unsigned int num_of_blocks, + unsigned int block_id) +{ + return SBI_CALL_3( + SBI_SD_WRITE, mem_address, num_of_blocks, block_id); +} + +static inline uintptr_t sbi_sd_read( + unsigned int mem_address, unsigned int num_of_blocks, + unsigned int block_id) +{ + return SBI_CALL_3( + SBI_SD_READ, mem_address, num_of_blocks, block_id); +} + +static inline void sbi_console_putchar(int ch) +{ + SBI_CALL_1(SBI_CONSOLE_PUTCHAR, ch); +} + +static inline int sbi_console_getchar(void) +{ + return SBI_CALL_0(SBI_CONSOLE_GETCHAR); +} + +static inline void sbi_set_timer(uint64_t stime_value) +{ +#if __riscv_xlen == 32 + SBI_CALL_2(SBI_SET_TIMER, stime_value, stime_value >> 32); +#else + SBI_CALL_1(SBI_SET_TIMER, stime_value); +#endif +} + +static inline void sbi_shutdown(void) { SBI_CALL_0(SBI_SHUTDOWN); } + +static inline void sbi_clear_ipi(void) +{ + SBI_CALL_0(SBI_CLEAR_IPI); +} + +static inline void sbi_send_ipi(const unsigned long *hart_mask) +{ + SBI_CALL_1(SBI_SEND_IPI, hart_mask); +} + +static inline void sbi_remote_fence_i( + const unsigned long *hart_mask) +{ + SBI_CALL_1(SBI_REMOTE_FENCE_I, hart_mask); +} + +static inline void sbi_remote_sfence_vma( + const unsigned long *hart_mask, unsigned long start, + unsigned long size) +{ + SBI_CALL_1(SBI_REMOTE_SFENCE_VMA, hart_mask); +} + +static inline void sbi_remote_sfence_vma_asid( + const unsigned long *hart_mask, unsigned long start, + unsigned long size, unsigned long asid) +{ + SBI_CALL_1(SBI_REMOTE_SFENCE_VMA_ASID, hart_mask); +} + +static inline void sbi_net_write(char * buffer, int length) { + SBI_CALL_2(SBI_NET_WRITE, buffer, length); +} + +static inline void sbi_net_read() { + SBI_CALL_0(SBI_NET_READ); +} + +#endif diff --git a/bsp/qemu-riscv-virt64/link.lds b/bsp/qemu-riscv-virt64/link.lds new file mode 100644 index 0000000000..e8c0db9c24 --- /dev/null +++ b/bsp/qemu-riscv-virt64/link.lds @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020/12/12 bernard The first version + */ + +INCLUDE "link_stacksize.lds" + +OUTPUT_ARCH( "riscv" ) + +/* + * Memory layout: + * 0x10200000 - 0x10201000: Bootloader + * 0x10201000 - 0x10A00000: Kernel + * 0x10A00000 - 0x11200000: Heap + */ + +MEMORY +{ + SRAM : ORIGIN = 0x80200000, LENGTH = 0x7FF000 +} + +ENTRY(_start) +SECTIONS +{ + . = 0x80200000 ; + + /* __STACKSIZE__ = 4096; */ + + .start : + { + *(.start); + } > SRAM + + . = ALIGN(8); + + .text : + { + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(8); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(8); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(8); + + /* section information for initial. */ + . = ALIGN(8); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(8); + + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + + . = ALIGN(8); + _etext = .; + } > SRAM + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + *(.eh_frame_entry) + } > SRAM + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } > SRAM + + . = ALIGN(8); + + .data : + { + *(.data) + *(.data.*) + + *(.data1) + *(.data1.*) + + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + + *(.sdata) + *(.sdata.*) + } > SRAM + + /* stack for dual core */ + .stack : + { + . = ALIGN(64); + __stack_start__ = .; + + . += __STACKSIZE__; + __stack_cpu0 = .; + + . += __STACKSIZE__; + __stack_cpu1 = .; + } > SRAM + + .sbss : + { + __bss_start = .; + *(.sbss) + *(.sbss.*) + *(.dynsbss) + *(.scommon) + } > SRAM + + .bss : + { + *(.bss) + *(.bss.*) + *(.dynbss) + *(COMMON) + __bss_end = .; + } > SRAM + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/qemu-riscv-virt64/link_stacksize.lds b/bsp/qemu-riscv-virt64/link_stacksize.lds new file mode 100644 index 0000000000..8685bc0f1c --- /dev/null +++ b/bsp/qemu-riscv-virt64/link_stacksize.lds @@ -0,0 +1 @@ +__STACKSIZE__ = 16384; \ No newline at end of file diff --git a/bsp/qemu-riscv-virt64/qemu-dbg.sh b/bsp/qemu-riscv-virt64/qemu-dbg.sh new file mode 100644 index 0000000000..a47cae45ed --- /dev/null +++ b/bsp/qemu-riscv-virt64/qemu-dbg.sh @@ -0,0 +1 @@ +qemu-system-riscv64 -s -S -nographic -machine virt -m 256M -kernel rtthread.bin diff --git a/bsp/qemu-riscv-virt64/qemu-dumpdtb.sh b/bsp/qemu-riscv-virt64/qemu-dumpdtb.sh new file mode 100644 index 0000000000..12068b571a --- /dev/null +++ b/bsp/qemu-riscv-virt64/qemu-dumpdtb.sh @@ -0,0 +1 @@ +qemu-system-riscv64 -nographic -machine virt,dumpdtb=virt.dtb -m 256M -kernel rtthread.bin diff --git a/bsp/qemu-riscv-virt64/qemu-nographic.sh b/bsp/qemu-riscv-virt64/qemu-nographic.sh new file mode 100644 index 0000000000..934c4f935b --- /dev/null +++ b/bsp/qemu-riscv-virt64/qemu-nographic.sh @@ -0,0 +1 @@ +qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin diff --git a/bsp/qemu-riscv-virt64/rtconfig.h b/bsp/qemu-riscv-virt64/rtconfig.h new file mode 100644 index 0000000000..38d19a2265 --- /dev/null +++ b/bsp/qemu-riscv-virt64/rtconfig.h @@ -0,0 +1,184 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Project Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 20 +#define RT_ALIGN_SIZE 8 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 16384 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 16384 + +/* kservice optimization */ + +#define RT_DEBUG + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_MEMTRACE +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 256 +#define RT_CONSOLE_DEVICE_NAME "uart" +#define RT_VER_NUM 0x40004 +#define ARCH_CPU_64BIT +#define ARCH_RISCV +#define ARCH_RISCV64 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 16384 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_CMD_SIZE 80 +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +#define FINSH_USING_MSH_ONLY +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + +#define RT_USING_DFS +#define DFS_USING_WORKDIR +#define DFS_FILESYSTEMS_MAX 2 +#define DFS_FILESYSTEM_TYPES_MAX 2 +#define DFS_FD_MAX 32 +#define RT_USING_DFS_DEVFS +#define RT_USING_DFS_ROMFS + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SERIAL +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_USING_LIBC +#define RT_USING_POSIX +#define RT_LIBC_FIXED_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + + +/* tools packages */ + + +/* system packages */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + +#define BOARD_virt +#define RT_USING_USERSPACE + +/* General Purpose UARTs */ + +#define __STACKSIZE__ 16384 + +#endif diff --git a/bsp/qemu-riscv-virt64/rtconfig.py b/bsp/qemu-riscv-virt64/rtconfig.py new file mode 100644 index 0000000000..cf063f0e6a --- /dev/null +++ b/bsp/qemu-riscv-virt64/rtconfig.py @@ -0,0 +1,57 @@ +import os + +# toolchains options +ARCH ='risc-v' +CPU ='virt64' +CROSS_TOOL ='gcc' + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.join(os.getcwd(), '..', '..') + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'/home/lizhirui/workspace/riscv64-toolchains/bin' +else: + print('Please make sure your toolchains is GNU GCC!') + exit(0) + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'riscv64-unknown-elf-' + CC = PREFIX + 'gcc' + CXX = PREFIX + 'g++' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcmodel=medany -march=rv64imafdc -mabi=lp64d' + CFLAGS = DEVICE + ' -fvar-tracking -ffreestanding -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields ' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp' + LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,_start -T link.lds -lc -lm ' + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -ggdb' + AFLAGS += ' -ggdb' + else: + CFLAGS += ' -O2 -Os' + + CXXFLAGS = CFLAGS + +DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtthread.asm\n' +POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' diff --git a/libcpu/risc-v/SConscript b/libcpu/risc-v/SConscript index dece8b0423..18b4c2005d 100644 --- a/libcpu/risc-v/SConscript +++ b/libcpu/risc-v/SConscript @@ -14,6 +14,8 @@ if rtconfig.CPU == "e906" : group = group elif rtconfig.CPU == "nuclei" : group = group +elif rtconfig.CPU == "virt64" : + group = group else : group = group + SConscript(os.path.join(cwd, 'common', 'SConscript')) diff --git a/libcpu/risc-v/virt64/SConscript b/libcpu/risc-v/virt64/SConscript new file mode 100644 index 0000000000..b0ae20ba02 --- /dev/null +++ b/libcpu/risc-v/virt64/SConscript @@ -0,0 +1,14 @@ +# RT-Thread building script for component + +from building import * + +Import('rtconfig') + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S') +CPPPATH = [cwd] +ASFLAGS = '' + +group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS) + +Return('group') diff --git a/libcpu/risc-v/virt64/context_gcc.S b/libcpu/risc-v/virt64/context_gcc.S new file mode 100644 index 0000000000..881bcd162c --- /dev/null +++ b/libcpu/risc-v/virt64/context_gcc.S @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/10/28 Bernard The unify RISC-V porting implementation + * 2018/12/27 Jesven Add SMP support + * 2021/02/02 lizhirui Add userspace support + */ + +#include "cpuport.h" +#include "stackframe.h" + + .globl rt_hw_context_switch_to +rt_hw_context_switch_to: + LOAD sp, (a0) + + la s0, rt_current_thread + LOAD s1, (s0) + + RESTORE_ALL + sret + +/* + * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to); + * + * a0 --> from + * a1 --> to + */ + .globl rt_hw_context_switch +rt_hw_context_switch: + mv t2, sp + li t0, 0x120//set SPIE and SPP = 1 + csrs sstatus, t0//if enter here,caller must be in system thread + csrw sepc, ra//return address + //saved from thread context + SAVE_ALL + + STORE t2, 32 * REGBYTES(sp)//save user_sp + + STORE sp, (a0) + + //restore to thread context + LOAD sp, (a1) + + la s0, rt_current_thread + LOAD s1, (s0) + + RESTORE_ALL + sret diff --git a/libcpu/risc-v/virt64/cpuport.c b/libcpu/risc-v/virt64/cpuport.c new file mode 100644 index 0000000000..50929125ac --- /dev/null +++ b/libcpu/risc-v/virt64/cpuport.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/10/28 Bernard The unify RISC-V porting code. + * 2021-02-11 lizhirui add gp support + */ + +#include +#include + +#include "cpuport.h" +#include "stack.h" + + +/** + * @brief from thread used interrupt context switch + * + */ +volatile rt_ubase_t rt_interrupt_from_thread = 0; +/** + * @brief to thread used interrupt context switch + * + */ +volatile rt_ubase_t rt_interrupt_to_thread = 0; +/** + * @brief flag to indicate context switch in interrupt or not + * + */ +volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0; + + +/** + * This function will initialize thread stack + * + * @param tentry the entry of thread + * @param parameter the parameter of entry + * @param stack_addr the beginning stack address + * @param texit the function will be called when thread exit + * + * @return stack address + */ +rt_uint8_t *rt_hw_stack_init(void *tentry, + void *parameter, + rt_uint8_t *stack_addr, + void *texit) +{ + struct rt_hw_stack_frame *frame; + rt_uint8_t *stk; + int i; + extern int __global_pointer$; + + stk = stack_addr + sizeof(rt_ubase_t); + stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES); + stk -= sizeof(struct rt_hw_stack_frame); + + frame = (struct rt_hw_stack_frame *)stk; + + for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++) + { + ((rt_ubase_t *)frame)[i] = 0xdeadbeef; + } + + frame->ra = (rt_ubase_t)texit; + frame->gp = (rt_ubase_t)&__global_pointer$; + frame->a0 = (rt_ubase_t)parameter; + frame->epc = (rt_ubase_t)tentry; + frame->user_sp_exc_stack = (rt_ubase_t)(((rt_ubase_t)stk) + sizeof(struct rt_hw_stack_frame)); + + /* force to supervisor mode(SPP=1) and set SPIE and SUM to 1 */ + frame->sstatus = 0x00040120; + + return stk; +} + +/* + * #ifdef RT_USING_SMP + * void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread); + * #else + * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to); + * #endif + */ +#ifndef RT_USING_SMP +void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to) +{ + if (rt_thread_switch_interrupt_flag == 0) + rt_interrupt_from_thread = from; + + rt_interrupt_to_thread = to; + rt_thread_switch_interrupt_flag = 1; + + return ; +} +#endif /* end of RT_USING_SMP */ + +/** shutdown CPU */ +void rt_hw_cpu_shutdown() +{ + rt_uint32_t level; + rt_kprintf("shutdown...\n"); + + level = rt_hw_interrupt_disable(); + while (level) + { + RT_ASSERT(0); + } +} + +rt_thread_t rt_thread_sp_to_thread(void *spmember_addr) +{ + return (rt_thread_t)(((rt_ubase_t)spmember_addr) - (offsetof(struct rt_thread,sp))); +} + +void *get_thread_kernel_stack_top(rt_thread_t thread) +{ + return (void *)(((rt_size_t)thread -> stack_addr) + ((rt_size_t)thread -> stack_size)); +} diff --git a/libcpu/risc-v/virt64/cpuport.h b/libcpu/risc-v/virt64/cpuport.h new file mode 100644 index 0000000000..bb838def4a --- /dev/null +++ b/libcpu/risc-v/virt64/cpuport.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-03 Bernard The first version + */ + +#ifndef CPUPORT_H__ +#define CPUPORT_H__ + +#include + +/* bytes of register width */ +#ifdef ARCH_CPU_64BIT +#define STORE sd +#define LOAD ld +#define REGBYTES 8 +#else +// error here, not portable +#endif + +#endif +#ifdef RISCV_U_MODE +#define RISCV_USER_ENTRY 0xFFFFFFE000000000ULL +#endif \ No newline at end of file diff --git a/libcpu/risc-v/virt64/interrupt_gcc.S b/libcpu/risc-v/virt64/interrupt_gcc.S new file mode 100644 index 0000000000..338413866e --- /dev/null +++ b/libcpu/risc-v/virt64/interrupt_gcc.S @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/10/02 Bernard The first version + * 2018/12/27 Jesven Add SMP schedule + * 2021/02/02 lizhirui Add userspace support + */ + +#include "cpuport.h" +#include "encoding.h" +#include "stackframe.h" + + .section .text.entry + .align 2 + .global trap_entry + .extern __stack_cpu0 + .extern get_current_thread_kernel_stack_top +trap_entry: + //backup sp + csrrw sp, sscratch, sp + //load interrupt stack + la sp, __stack_cpu0 + //backup context + SAVE_ALL + + RESTORE_SYS_GP + + csrr a0, scause + csrrc a1, stval, zero + csrr a2, sepc + mv a3, sp + + /* scause, stval, sepc, sp */ + call handle_trap + + /* need to switch new thread */ + la s0, rt_thread_switch_interrupt_flag + lw s2, 0(s0) + beqz s2, spurious_interrupt + sw zero, 0(s0) + +.global rt_hw_context_switch_interrupt_do +rt_hw_context_switch_interrupt_do: + +//switch to thread kernel stack + csrr t0, sstatus + andi t0, t0, 0x100 + beqz t0, __restore_sp_from_tcb_interrupt + +__restore_sp_from_sscratch_interrupt: + csrr t0, sscratch + j __move_stack_context_interrupt + +__restore_sp_from_tcb_interrupt: + la s0, rt_interrupt_from_thread + LOAD a0, 0(s0) + jal rt_thread_sp_to_thread + jal get_thread_kernel_stack_top + mv t0, a0 + +__move_stack_context_interrupt: + mv t1, sp//src + mv sp, t0//switch stack + addi sp, sp, -33 * REGBYTES + //copy context + li s0, 33//cnt + mv t2, sp//dst + +copy_context_loop_interrupt: + LOAD t0, 0(t1) + STORE t0, 0(t2) + addi s0, s0, -1 + addi t1, t1, 8 + addi t2, t2, 8 + bnez s0, copy_context_loop_interrupt + + la s0, rt_interrupt_from_thread + LOAD s1, 0(s0) + STORE sp, 0(s1) + + la s0, rt_interrupt_to_thread + LOAD s1, 0(s0) + LOAD sp, 0(s1) + +spurious_interrupt: + RESTORE_ALL + sret + +.global rt_hw_interrupt_enable +rt_hw_interrupt_enable: + csrs sstatus, a0 + jr ra + +.global rt_hw_interrupt_disable +rt_hw_interrupt_disable: + csrrci a0, sstatus, 2 + jr ra diff --git a/libcpu/risc-v/virt64/riscv.h b/libcpu/risc-v/virt64/riscv.h new file mode 100644 index 0000000000..04ac4fea74 --- /dev/null +++ b/libcpu/risc-v/virt64/riscv.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-30 lizhirui first version + */ + +#ifndef __RISCV_H__ +#define __RISCV_H__ + +#include + +#define __SIZE(bit) (1UL << (bit)) +#define __MASK(bit) (__SIZE(bit) - 1UL) +#define __UMASK(bit) (~(__MASK(bit))) +#define __MASKVALUE(value,maskvalue) ((value) & (maskvalue)) +#define __UMASKVALUE(value,maskvalue) ((value) & (~(maskvalue))) +#define __CHECKUPBOUND(value,bit_count) (!(((rt_size_t)value) & (~__MASK(bit_count)))) +#define __CHECKALIGN(value,start_bit) (!(((rt_size_t)value) & (__MASK(start_bit)))) + +#define __PARTBIT(value,start_bit,length) (((value) >> (start_bit)) & __MASK(length)) + +#define __ALIGNUP(value,bit) (((value) + __MASK(bit)) & __UMASK(bit)) +#define __ALIGNDOWN(value,bit) ((value) & __UMASK(bit)) + +#endif \ No newline at end of file diff --git a/libcpu/risc-v/virt64/riscv_io.h b/libcpu/risc-v/virt64/riscv_io.h new file mode 100644 index 0000000000..8363ff23f8 --- /dev/null +++ b/libcpu/risc-v/virt64/riscv_io.h @@ -0,0 +1,109 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + */ + +#ifndef __RISCV_IO_H__ +#define __RISCV_IO_H__ + + static inline void __raw_writeb(rt_uint8_t val, volatile void *addr) + { + asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr)); + } + + static inline void __raw_writew(rt_uint16_t val, volatile void *addr) + { + asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr)); + } + + static inline void __raw_writel(rt_uint32_t val, volatile void *addr) + { + asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr)); + } + + #if __riscv_xlen != 32 + static inline void __raw_writeq(rt_uint64_t val, volatile void *addr) + { + asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr)); + } + #endif + + static inline rt_uint8_t __raw_readb(const volatile void *addr) + { + rt_uint8_t val; + + asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr)); + return val; + } + + static inline rt_uint16_t __raw_readw(const volatile void *addr) + { + rt_uint16_t val; + + asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr)); + return val; + } + + static inline rt_uint32_t __raw_readl(const volatile void *addr) + { + rt_uint32_t val; + + asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr)); + return val; + } + + #if __riscv_xlen != 32 + static inline rt_uint64_t __raw_readq(const volatile void *addr) + { + rt_uint64_t val; + + asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr)); + return val; + } + #endif + + /* FIXME: These are now the same as asm-generic */ + + /* clang-format off */ + + #define __io_rbr() do {} while (0) + #define __io_rar() do {} while (0) + #define __io_rbw() do {} while (0) + #define __io_raw() do {} while (0) + + #define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; }) + #define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; }) + #define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; }) + + #define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); }) + #define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); }) + #define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); }) + + #if __riscv_xlen != 32 + #define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; }) + #define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); }) + #endif + + #define __io_br() do {} while (0) + #define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory"); + #define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory"); + #define __io_aw() do {} while (0) + + #define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; }) + #define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; }) + #define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; }) + + #define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); }) + #define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); }) + #define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); }) + + #if __riscv_xlen != 32 + #define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; }) + #define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); }) + #endif + +#endif \ No newline at end of file diff --git a/libcpu/risc-v/virt64/stack.h b/libcpu/risc-v/virt64/stack.h new file mode 100644 index 0000000000..27e9cdf9fa --- /dev/null +++ b/libcpu/risc-v/virt64/stack.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-30 lizhirui first version + */ + +#ifndef __STACK_H__ +#define __STACK_H__ + +#include +struct rt_hw_stack_frame +{ + rt_ubase_t epc; /* epc - epc - program counter */ + rt_ubase_t ra; /* x1 - ra - return address for jumps */ + rt_ubase_t sstatus; /* - supervisor status register */ + rt_ubase_t gp; /* x3 - gp - global pointer */ + rt_ubase_t tp; /* x4 - tp - thread pointer */ + rt_ubase_t t0; /* x5 - t0 - temporary register 0 */ + rt_ubase_t t1; /* x6 - t1 - temporary register 1 */ + rt_ubase_t t2; /* x7 - t2 - temporary register 2 */ + rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */ + rt_ubase_t s1; /* x9 - s1 - saved register 1 */ + rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */ + rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */ + rt_ubase_t a2; /* x12 - a2 - function argument 2 */ + rt_ubase_t a3; /* x13 - a3 - function argument 3 */ + rt_ubase_t a4; /* x14 - a4 - function argument 4 */ + rt_ubase_t a5; /* x15 - a5 - function argument 5 */ + rt_ubase_t a6; /* x16 - a6 - function argument 6 */ + rt_ubase_t a7; /* x17 - s7 - function argument 7 */ + rt_ubase_t s2; /* x18 - s2 - saved register 2 */ + rt_ubase_t s3; /* x19 - s3 - saved register 3 */ + rt_ubase_t s4; /* x20 - s4 - saved register 4 */ + rt_ubase_t s5; /* x21 - s5 - saved register 5 */ + rt_ubase_t s6; /* x22 - s6 - saved register 6 */ + rt_ubase_t s7; /* x23 - s7 - saved register 7 */ + rt_ubase_t s8; /* x24 - s8 - saved register 8 */ + rt_ubase_t s9; /* x25 - s9 - saved register 9 */ + rt_ubase_t s10; /* x26 - s10 - saved register 10 */ + rt_ubase_t s11; /* x27 - s11 - saved register 11 */ + rt_ubase_t t3; /* x28 - t3 - temporary register 3 */ + rt_ubase_t t4; /* x29 - t4 - temporary register 4 */ + rt_ubase_t t5; /* x30 - t5 - temporary register 5 */ + rt_ubase_t t6; /* x31 - t6 - temporary register 6 */ + rt_ubase_t user_sp_exc_stack; /* sscratch - user mode sp/exception stack */ +}; + +#endif diff --git a/libcpu/risc-v/virt64/stackframe.h b/libcpu/risc-v/virt64/stackframe.h new file mode 100644 index 0000000000..e5a5271a7a --- /dev/null +++ b/libcpu/risc-v/virt64/stackframe.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-02 lizhirui first version + * 2021-02-11 lizhirui fixed gp save/store bug + */ + +#ifndef __STACKFRAME_H__ +#define __STACKFRAME_H__ + +#include "cpuport.h" + +.macro SAVE_ALL + addi sp, sp, -33 * REGBYTES + + STORE x1, 1 * REGBYTES(sp) + + csrr x1, sstatus + STORE x1, 2 * REGBYTES(sp) + + csrr x1, sepc + STORE x1, 0 * REGBYTES(sp) + + STORE x3, 3 * REGBYTES(sp) + STORE x4, 4 * REGBYTES(sp) + STORE x5, 5 * REGBYTES(sp) + STORE x6, 6 * REGBYTES(sp) + STORE x7, 7 * REGBYTES(sp) + STORE x8, 8 * REGBYTES(sp) + STORE x9, 9 * REGBYTES(sp) + STORE x10, 10 * REGBYTES(sp) + STORE x11, 11 * REGBYTES(sp) + STORE x12, 12 * REGBYTES(sp) + STORE x13, 13 * REGBYTES(sp) + STORE x14, 14 * REGBYTES(sp) + STORE x15, 15 * REGBYTES(sp) + STORE x16, 16 * REGBYTES(sp) + STORE x17, 17 * REGBYTES(sp) + STORE x18, 18 * REGBYTES(sp) + STORE x19, 19 * REGBYTES(sp) + STORE x20, 20 * REGBYTES(sp) + STORE x21, 21 * REGBYTES(sp) + STORE x22, 22 * REGBYTES(sp) + STORE x23, 23 * REGBYTES(sp) + STORE x24, 24 * REGBYTES(sp) + STORE x25, 25 * REGBYTES(sp) + STORE x26, 26 * REGBYTES(sp) + STORE x27, 27 * REGBYTES(sp) + STORE x28, 28 * REGBYTES(sp) + STORE x29, 29 * REGBYTES(sp) + STORE x30, 30 * REGBYTES(sp) + STORE x31, 31 * REGBYTES(sp) + csrr t0, sscratch + STORE t0, 32 * REGBYTES(sp) +.endm + +.macro RESTORE_ALL_ONLY + /* resw ra to sepc */ + LOAD x1, 0 * REGBYTES(sp) + csrw sepc, x1 + + LOAD x1, 2 * REGBYTES(sp) + csrw sstatus, x1 + + LOAD x1, 1 * REGBYTES(sp) + + LOAD x3, 3 * REGBYTES(sp) + LOAD x4, 4 * REGBYTES(sp) + LOAD x5, 5 * REGBYTES(sp) + LOAD x6, 6 * REGBYTES(sp) + LOAD x7, 7 * REGBYTES(sp) + LOAD x8, 8 * REGBYTES(sp) + LOAD x9, 9 * REGBYTES(sp) + LOAD x10, 10 * REGBYTES(sp) + LOAD x11, 11 * REGBYTES(sp) + LOAD x12, 12 * REGBYTES(sp) + LOAD x13, 13 * REGBYTES(sp) + LOAD x14, 14 * REGBYTES(sp) + LOAD x15, 15 * REGBYTES(sp) + LOAD x16, 16 * REGBYTES(sp) + LOAD x17, 17 * REGBYTES(sp) + LOAD x18, 18 * REGBYTES(sp) + LOAD x19, 19 * REGBYTES(sp) + LOAD x20, 20 * REGBYTES(sp) + LOAD x21, 21 * REGBYTES(sp) + LOAD x22, 22 * REGBYTES(sp) + LOAD x23, 23 * REGBYTES(sp) + LOAD x24, 24 * REGBYTES(sp) + LOAD x25, 25 * REGBYTES(sp) + LOAD x26, 26 * REGBYTES(sp) + LOAD x27, 27 * REGBYTES(sp) + LOAD x28, 28 * REGBYTES(sp) + LOAD x29, 29 * REGBYTES(sp) + LOAD x30, 30 * REGBYTES(sp) + LOAD x31, 31 * REGBYTES(sp) + + addi sp, sp, 33 * REGBYTES +.endm + +.macro RESTORE_ALL + /* resw ra to sepc */ + LOAD x1, 0 * REGBYTES(sp) + csrw sepc, x1 + + LOAD x1, 2 * REGBYTES(sp) + csrw sstatus, x1 + + LOAD x1, 1 * REGBYTES(sp) + + LOAD x3, 3 * REGBYTES(sp) + LOAD x4, 4 * REGBYTES(sp) + LOAD x5, 5 * REGBYTES(sp) + LOAD x6, 6 * REGBYTES(sp) + LOAD x7, 7 * REGBYTES(sp) + LOAD x8, 8 * REGBYTES(sp) + LOAD x9, 9 * REGBYTES(sp) + LOAD x10, 10 * REGBYTES(sp) + LOAD x11, 11 * REGBYTES(sp) + LOAD x12, 12 * REGBYTES(sp) + LOAD x13, 13 * REGBYTES(sp) + LOAD x14, 14 * REGBYTES(sp) + LOAD x15, 15 * REGBYTES(sp) + LOAD x16, 16 * REGBYTES(sp) + LOAD x17, 17 * REGBYTES(sp) + LOAD x18, 18 * REGBYTES(sp) + LOAD x19, 19 * REGBYTES(sp) + LOAD x20, 20 * REGBYTES(sp) + LOAD x21, 21 * REGBYTES(sp) + LOAD x22, 22 * REGBYTES(sp) + LOAD x23, 23 * REGBYTES(sp) + LOAD x24, 24 * REGBYTES(sp) + LOAD x25, 25 * REGBYTES(sp) + LOAD x26, 26 * REGBYTES(sp) + LOAD x27, 27 * REGBYTES(sp) + LOAD x28, 28 * REGBYTES(sp) + LOAD x29, 29 * REGBYTES(sp) + LOAD x30, 30 * REGBYTES(sp) + LOAD x31, 31 * REGBYTES(sp) + + //restore user sp + LOAD sp, 32 * REGBYTES(sp) +.endm + +.macro RESTORE_SYS_GP + .option push + .option norelax + la gp, __global_pointer$ + .option pop +.endm + +.macro OPEN_INTERRUPT + csrsi sstatus, 2 +.endm + +.macro CLOSE_INTERRUPT + csrci sstatus, 2 +.endm + +#endif \ No newline at end of file diff --git a/libcpu/risc-v/virt64/startup_gcc.S b/libcpu/risc-v/virt64/startup_gcc.S new file mode 100644 index 0000000000..9b1a27be9a --- /dev/null +++ b/libcpu/risc-v/virt64/startup_gcc.S @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/10/01 Bernard The first version + * 2018/12/27 Jesven Add SMP support + * 2020/6/12 Xim Port to QEMU and remove SMP support + */ + +#define SSTATUS_FS 0x00006000U /* initial state of FPU, clear to disable */ +#include + + .global _start + .section ".start", "ax" +_start: + j 1f + .word 0xdeadbeef + .align 3 + .global g_wake_up + g_wake_up: + .dword 1 + .dword 0 +1: + csrw sie, 0 + csrw sip, 0 + la t0, trap_entry + csrw stvec, t0 + + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10,0 + li x11,0 + li x12,0 + li x13,0 + li x14,0 + li x15,0 + li x16,0 + li x17,0 + li x18,0 + li x19,0 + li x20,0 + li x21,0 + li x22,0 + li x23,0 + li x24,0 + li x25,0 + li x26,0 + li x27,0 + li x28,0 + li x29,0 + li x30,0 + li x31,0 + + /* set to disable FPU */ + li t0, SSTATUS_FS + csrc sstatus, t0 + li t0, 0x40000 // SUM in sstatus + csrs sstatus, t0 + +.option push +.option norelax + la gp, __global_pointer$ +.option pop + + // removed SMP support here + la sp, __stack_start__ + li t0, __STACKSIZE__ + add sp, sp, t0 + csrw sscratch, sp + j primary_cpu_entry diff --git a/libcpu/risc-v/virt64/tick.c b/libcpu/risc-v/virt64/tick.c new file mode 100644 index 0000000000..4f340c544f --- /dev/null +++ b/libcpu/risc-v/virt64/tick.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/10/28 Bernard The unify RISC-V porting code. + */ + +#include +#include + +#include +#include "sbi.h" + +static volatile uint64_t time_elapsed = 0; +static volatile unsigned long tick_cycles = 0; + +static uint64_t get_ticks() +{ + __asm__ __volatile__( + "rdtime %0" + : "=r"(time_elapsed)); + return time_elapsed; +} + +int tick_isr(void) +{ + // uint64_t core_id = current_coreid(); + int tick_cycles = 40000; + // clint->mtimecmp[core_id] += tick_cycles; + rt_tick_increase(); + sbi_set_timer(get_ticks() + tick_cycles); + + return 0; +} + +/* Sets and enable the timer interrupt */ +int rt_hw_tick_init(void) +{ + /* Read core id */ + // unsigned long core_id = current_coreid(); + unsigned long interval = 1000/RT_TICK_PER_SECOND; + + /* Clear the Supervisor-Timer bit in SIE */ + clear_csr(sie, SIP_STIP); + + /* calculate the tick cycles */ + // tick_cycles = interval * sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV / 1000ULL - 1; + tick_cycles = 40000; + /* Set timer */ + sbi_set_timer(get_ticks() + tick_cycles); + + /* Enable the Supervisor-Timer bit in SIE */ + set_csr(sie, SIP_STIP); + + return 0; +} diff --git a/libcpu/risc-v/virt64/tick.h b/libcpu/risc-v/virt64/tick.h new file mode 100644 index 0000000000..0821004263 --- /dev/null +++ b/libcpu/risc-v/virt64/tick.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/10/28 Bernard The unify RISC-V porting code. + */ + +#ifndef TICK_H__ +#define TICK_H__ + +int tick_isr(void); +int rt_hw_tick_init(void); + +#endif From f07857324b89f820532ca62643a3980f9a32449d Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Tue, 18 May 2021 18:58:39 +0800 Subject: [PATCH 090/255] [bsp] Use sbi from freebsd --- bsp/qemu-riscv-virt64/driver/board.c | 5 +- bsp/qemu-riscv-virt64/driver/drv_uart.c | 8 +- bsp/qemu-riscv-virt64/driver/sbi.c | 265 ++++++++++++++++++++ bsp/qemu-riscv-virt64/driver/sbi.h | 314 ++++++++++++++++-------- 4 files changed, 488 insertions(+), 104 deletions(-) create mode 100644 bsp/qemu-riscv-virt64/driver/sbi.c diff --git a/bsp/qemu-riscv-virt64/driver/board.c b/bsp/qemu-riscv-virt64/driver/board.c index 3ed4aab438..ac021ed3c3 100644 --- a/bsp/qemu-riscv-virt64/driver/board.c +++ b/bsp/qemu-riscv-virt64/driver/board.c @@ -38,7 +38,8 @@ void primary_cpu_entry(void) extern void entry(void); /* disable global interrupt */ - init_bss(); + rt_memset(&__bss_start, 0x0, &__bss_end - &__bss_start); + // init_bss(); rt_hw_interrupt_disable(); entry(); } @@ -76,7 +77,7 @@ void rt_hw_board_init(void) void rt_hw_cpu_reset(void) { - SBI_CALL_0(SBI_SHUTDOWN); + sbi_shutdown(); while(1); } MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine); diff --git a/bsp/qemu-riscv-virt64/driver/drv_uart.c b/bsp/qemu-riscv-virt64/driver/drv_uart.c index 8e0476321c..63820175e3 100644 --- a/bsp/qemu-riscv-virt64/driver/drv_uart.c +++ b/bsp/qemu-riscv-virt64/driver/drv_uart.c @@ -98,23 +98,25 @@ static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg static int drv_uart_putc(struct rt_serial_device *serial, char c) { - SBI_CALL_1(SBI_CONSOLE_PUTCHAR, c); + sbi_console_putchar(c); return (1); } static int drv_uart_getc(struct rt_serial_device *serial) { - return SBI_CALL_0(SBI_CONSOLE_GETCHAR); + return sbi_console_getchar(); } +#if 0 void drv_uart_puts(char *str) { sbi_console_putstr(str); } +#endif char rt_hw_console_getchar(void) { - return SBI_CALL_0(SBI_CONSOLE_GETCHAR); + return sbi_console_getchar(); } static void uart_rx(void *param) diff --git a/bsp/qemu-riscv-virt64/driver/sbi.c b/bsp/qemu-riscv-virt64/driver/sbi.c new file mode 100644 index 0000000000..f848ec7810 --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/sbi.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-18 Bernard port from FreeBSD + */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2019 Mitchell Horne + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "sbi.h" +#include +#include + +/* SBI Implementation-Specific Definitions */ +#define OPENSBI_VERSION_MAJOR_OFFSET 16 +#define OPENSBI_VERSION_MINOR_MASK 0xFFFF + +unsigned long sbi_spec_version; +unsigned long sbi_impl_id; +unsigned long sbi_impl_version; + +static bool has_time_extension = false; +static bool has_ipi_extension = false; +static bool has_rfnc_extension = false; + +static struct sbi_ret +sbi_get_spec_version(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_SPEC_VERSION)); +} + +static struct sbi_ret +sbi_get_impl_id(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_ID)); +} + +static struct sbi_ret +sbi_get_impl_version(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_VERSION)); +} + +void +sbi_print_version(void) +{ + u_int major; + u_int minor; + + /* For legacy SBI implementations. */ + if (sbi_spec_version == 0) + { + rt_kprintf("SBI: Unknown (Legacy) Implementation\n"); + rt_kprintf("SBI Specification Version: 0.1\n"); + return; + } + + switch (sbi_impl_id) + { + case (SBI_IMPL_ID_BBL): + rt_kprintf("SBI: Berkely Boot Loader %lu\n", sbi_impl_version); + break; + case (SBI_IMPL_ID_XVISOR): + rt_kprintf("SBI: eXtensible Versatile hypervISOR %lu\n", sbi_impl_version); + break; + case (SBI_IMPL_ID_KVM): + rt_kprintf("SBI: Kernel-based Virtual Machine %lu\n", sbi_impl_version); + break; + case (SBI_IMPL_ID_RUSTSBI): + rt_kprintf("SBI: RustSBI %lu\n", sbi_impl_version); + break; + case (SBI_IMPL_ID_DIOSIX): + rt_kprintf("SBI: Diosix %lu\n", sbi_impl_version); + break; + case (SBI_IMPL_ID_OPENSBI): + major = sbi_impl_version >> OPENSBI_VERSION_MAJOR_OFFSET; + minor = sbi_impl_version & OPENSBI_VERSION_MINOR_MASK; + rt_kprintf("SBI: OpenSBI v%u.%u\n", major, minor); + break; + default: + rt_kprintf("SBI: Unrecognized Implementation: %lu\n", sbi_impl_id); + break; + } + + major = (sbi_spec_version & SBI_SPEC_VERS_MAJOR_MASK) >> + SBI_SPEC_VERS_MAJOR_OFFSET; + minor = (sbi_spec_version & SBI_SPEC_VERS_MINOR_MASK); + rt_kprintf("SBI Specification Version: %u.%u\n", major, minor); +} + +void +sbi_set_timer(uint64_t val) +{ + struct sbi_ret ret; + + /* Use the TIME legacy replacement extension, if available. */ + if (has_time_extension) + { + ret = SBI_CALL1(SBI_EXT_ID_TIME, SBI_TIME_SET_TIMER, val); + RT_ASSERT(ret.error == SBI_SUCCESS); + } + else + { + (void)SBI_CALL1(SBI_SET_TIMER, 0, val); + } +} + +void +sbi_send_ipi(const unsigned long *hart_mask) +{ + struct sbi_ret ret; + + /* Use the IPI legacy replacement extension, if available. */ + if (has_ipi_extension) + { + ret = SBI_CALL2(SBI_EXT_ID_IPI, SBI_IPI_SEND_IPI, + *hart_mask, 0); + RT_ASSERT(ret.error == SBI_SUCCESS); + } + else + { + (void)SBI_CALL1(SBI_SEND_IPI, 0, (uint64_t)hart_mask); + } +} + +void +sbi_remote_fence_i(const unsigned long *hart_mask) +{ + struct sbi_ret ret; + + /* Use the RFENCE legacy replacement extension, if available. */ + if (has_rfnc_extension) + { + ret = SBI_CALL2(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_FENCE_I, + *hart_mask, 0); + RT_ASSERT(ret.error == SBI_SUCCESS); + } + else + { + (void)SBI_CALL1(SBI_REMOTE_FENCE_I, 0, (uint64_t)hart_mask); + } +} + +void +sbi_remote_sfence_vma(const unsigned long *hart_mask, unsigned long start, unsigned long size) +{ + struct sbi_ret ret; + + /* Use the RFENCE legacy replacement extension, if available. */ + if (has_rfnc_extension) + { + ret = SBI_CALL4(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA, + *hart_mask, 0, start, size); + RT_ASSERT(ret.error == SBI_SUCCESS); + } + else + { + (void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask, + start, size); + } +} + +void +sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long start, unsigned long size, + unsigned long asid) +{ + struct sbi_ret ret; + + /* Use the RFENCE legacy replacement extension, if available. */ + if (has_rfnc_extension) + { + ret = SBI_CALL5(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA_ASID, + *hart_mask, 0, start, size, asid); + RT_ASSERT(ret.error == SBI_SUCCESS); + } + else + { + (void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0, + (uint64_t)hart_mask, start, size, asid); + } +} + +int +sbi_hsm_hart_start(unsigned long hart, unsigned long start_addr, unsigned long priv) +{ + struct sbi_ret ret; + + ret = SBI_CALL3(SBI_EXT_ID_HSM, SBI_HSM_HART_START, hart, start_addr, priv); + return (ret.error != 0 ? (int)ret.error : 0); +} + +void +sbi_hsm_hart_stop(void) +{ + (void)SBI_CALL0(SBI_EXT_ID_HSM, SBI_HSM_HART_STOP); +} + +int +sbi_hsm_hart_status(unsigned long hart) +{ + struct sbi_ret ret; + + ret = SBI_CALL1(SBI_EXT_ID_HSM, SBI_HSM_HART_STATUS, hart); + + return (ret.error != 0 ? (int)ret.error : (int)ret.value); +} + +void +sbi_init(void) +{ + struct sbi_ret sret; + + /* + * Get the spec version. For legacy SBI implementations this will + * return an error, otherwise it is guaranteed to succeed. + */ + sret = sbi_get_spec_version(); + if (sret.error != 0) + { + /* We are running a legacy SBI implementation. */ + sbi_spec_version = 0; + return; + } + + /* Set the SBI implementation info. */ + sbi_spec_version = sret.value; + sbi_impl_id = sbi_get_impl_id().value; + sbi_impl_version = sbi_get_impl_version().value; + + /* Probe for legacy replacement extensions. */ + if (sbi_probe_extension(SBI_EXT_ID_TIME) != 0) + has_time_extension = true; + if (sbi_probe_extension(SBI_EXT_ID_IPI) != 0) + has_ipi_extension = true; + if (sbi_probe_extension(SBI_EXT_ID_RFNC) != 0) + has_rfnc_extension = true; +} diff --git a/bsp/qemu-riscv-virt64/driver/sbi.h b/bsp/qemu-riscv-virt64/driver/sbi.h index 18d2bb7ee0..b42d558f53 100644 --- a/bsp/qemu-riscv-virt64/driver/sbi.h +++ b/bsp/qemu-riscv-virt64/driver/sbi.h @@ -1,126 +1,242 @@ /* - * Copyright (C) 2015 Regents of the University of California + * Copyright (c) 2006-2021, RT-Thread Development Team * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, version 2. + * SPDX-License-Identifier: Apache-2.0 * - * This program is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. + * Change Logs: + * Date Author Notes + * 2021-05-18 Bernard port from FreeBSD */ -#ifndef _ASM_RISCV_SBI_H -#define _ASM_RISCV_SBI_H +/*- + * Copyright (c) 2016-2017 Ruslan Bukin + * All rights reserved. + * Copyright (c) 2019 Mitchell Horne + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ -#include -#include +#ifndef _MACHINE_SBI_H_ +#define _MACHINE_SBI_H_ -#define SBI_CALL(which, arg0, arg1, arg2) \ - ({ \ - register uintptr_t a0 asm("a0") = (uintptr_t)(arg0); \ - register uintptr_t a1 asm("a1") = (uintptr_t)(arg1); \ - register uintptr_t a2 asm("a2") = (uintptr_t)(arg2); \ - register uintptr_t a7 asm("a7") = (uintptr_t)(which); \ - asm volatile("ecall" \ - : "+r"(a0) \ - : "r"(a1), "r"(a2), "r"(a7) \ - : "memory"); \ - a0; \ - }) +#include -/* Lazy implementations until SBI is finalized */ -#define SBI_CALL_0(which) SBI_CALL(which, 0, 0, 0) -#define SBI_CALL_1(which, arg0) SBI_CALL(which, arg0, 0, 0) -#define SBI_CALL_2(which, arg0, arg1) \ - SBI_CALL(which, arg0, arg1, 0) -#define SBI_CALL_3(which, arg0, arg1, arg2) \ - SBI_CALL(which, arg0, arg1, arg2) +/* SBI Specification Version */ +#define SBI_SPEC_VERS_MAJOR_OFFSET 24 +#define SBI_SPEC_VERS_MAJOR_MASK (0x7F << SBI_SPEC_VERS_MAJOR_OFFSET) +#define SBI_SPEC_VERS_MINOR_OFFSET 0 +#define SBI_SPEC_VERS_MINOR_MASK (0xFFFFFF << SBI_SPEC_VERS_MINOR_OFFSET) -static inline void sbi_console_putstr(char *str) +/* SBI Implementation IDs */ +#define SBI_IMPL_ID_BBL 0 +#define SBI_IMPL_ID_OPENSBI 1 +#define SBI_IMPL_ID_XVISOR 2 +#define SBI_IMPL_ID_KVM 3 +#define SBI_IMPL_ID_RUSTSBI 4 +#define SBI_IMPL_ID_DIOSIX 5 + +/* SBI Error Codes */ +#define SBI_SUCCESS 0 +#define SBI_ERR_FAILURE -1 +#define SBI_ERR_NOT_SUPPORTED -2 +#define SBI_ERR_INVALID_PARAM -3 +#define SBI_ERR_DENIED -4 +#define SBI_ERR_INVALID_ADDRESS -5 +#define SBI_ERR_ALREADY_AVAILABLE -6 + +/* SBI Base Extension */ +#define SBI_EXT_ID_BASE 0x10 +#define SBI_BASE_GET_SPEC_VERSION 0 +#define SBI_BASE_GET_IMPL_ID 1 +#define SBI_BASE_GET_IMPL_VERSION 2 +#define SBI_BASE_PROBE_EXTENSION 3 +#define SBI_BASE_GET_MVENDORID 4 +#define SBI_BASE_GET_MARCHID 5 +#define SBI_BASE_GET_MIMPID 6 + +/* Timer (TIME) Extension */ +#define SBI_EXT_ID_TIME 0x54494D45 +#define SBI_TIME_SET_TIMER 0 + +/* IPI (IPI) Extension */ +#define SBI_EXT_ID_IPI 0x735049 +#define SBI_IPI_SEND_IPI 0 + +/* RFENCE (RFNC) Extension */ +#define SBI_EXT_ID_RFNC 0x52464E43 +#define SBI_RFNC_REMOTE_FENCE_I 0 +#define SBI_RFNC_REMOTE_SFENCE_VMA 1 +#define SBI_RFNC_REMOTE_SFENCE_VMA_ASID 2 +#define SBI_RFNC_REMOTE_HFENCE_GVMA_VMID 3 +#define SBI_RFNC_REMOTE_HFENCE_GVMA 4 +#define SBI_RFNC_REMOTE_HFENCE_VVMA_ASID 5 +#define SBI_RFNC_REMOTE_HFENCE_VVMA 6 + +/* Hart State Management (HSM) Extension */ +#define SBI_EXT_ID_HSM 0x48534D +#define SBI_HSM_HART_START 0 +#define SBI_HSM_HART_STOP 1 +#define SBI_HSM_HART_STATUS 2 +#define SBI_HSM_STATUS_STARTED 0 +#define SBI_HSM_STATUS_STOPPED 1 +#define SBI_HSM_STATUS_START_PENDING 2 +#define SBI_HSM_STATUS_STOP_PENDING 3 + +/* Legacy Extensions */ +#define SBI_SET_TIMER 0 +#define SBI_CONSOLE_PUTCHAR 1 +#define SBI_CONSOLE_GETCHAR 2 +#define SBI_CLEAR_IPI 3 +#define SBI_SEND_IPI 4 +#define SBI_REMOTE_FENCE_I 5 +#define SBI_REMOTE_SFENCE_VMA 6 +#define SBI_REMOTE_SFENCE_VMA_ASID 7 +#define SBI_SHUTDOWN 8 + +#define SBI_CALL0(e, f) SBI_CALL5(e, f, 0, 0, 0, 0, 0) +#define SBI_CALL1(e, f, p1) SBI_CALL5(e, f, p1, 0, 0, 0, 0) +#define SBI_CALL2(e, f, p1, p2) SBI_CALL5(e, f, p1, p2, 0, 0, 0) +#define SBI_CALL3(e, f, p1, p2, p3) SBI_CALL5(e, f, p1, p2, p3, 0, 0) +#define SBI_CALL4(e, f, p1, p2, p3, p4) SBI_CALL5(e, f, p1, p2, p3, p4, 0) +#define SBI_CALL5(e, f, p1, p2, p3, p4, p5) sbi_call(e, f, p1, p2, p3, p4, p5) + +/* + * Documentation available at + * https://github.com/riscv/riscv-sbi-doc/blob/master/riscv-sbi.adoc + */ + +struct sbi_ret { - // FIXME: machine mode cannot access `str` - // if `str` is a virtual address. So we use - // SBI_CONSOLE_PUTCHAR to implement this function. - while (*str != '\0') { - SBI_CALL_1(SBI_CONSOLE_PUTCHAR, *str++); - } -} + long error; + long value; +}; -static inline uintptr_t sbi_sd_write( - unsigned int mem_address, unsigned int num_of_blocks, - unsigned int block_id) +static __inline struct sbi_ret +sbi_call(uint64_t arg7, uint64_t arg6, uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3, uint64_t arg4) { - return SBI_CALL_3( - SBI_SD_WRITE, mem_address, num_of_blocks, block_id); + struct sbi_ret ret; + + register uintptr_t a0 __asm("a0") = (uintptr_t)(arg0); + register uintptr_t a1 __asm("a1") = (uintptr_t)(arg1); + register uintptr_t a2 __asm("a2") = (uintptr_t)(arg2); + register uintptr_t a3 __asm("a3") = (uintptr_t)(arg3); + register uintptr_t a4 __asm("a4") = (uintptr_t)(arg4); + register uintptr_t a6 __asm("a6") = (uintptr_t)(arg6); + register uintptr_t a7 __asm("a7") = (uintptr_t)(arg7); + + __asm __volatile(\ + "ecall" \ + : "+r"(a0), "+r"(a1) \ + : "r"(a2), "r"(a3), "r"(a4), "r"(a6), "r"(a7) \ + : "memory"); + + ret.error = a0; + ret.value = a1; + return (ret); } -static inline uintptr_t sbi_sd_read( - unsigned int mem_address, unsigned int num_of_blocks, - unsigned int block_id) +/* Base extension functions and variables. */ +extern unsigned long sbi_spec_version; +extern unsigned long sbi_impl_id; +extern unsigned long sbi_impl_version; + +static __inline long +sbi_probe_extension(long id) { - return SBI_CALL_3( - SBI_SD_READ, mem_address, num_of_blocks, block_id); + return (SBI_CALL1(SBI_EXT_ID_BASE, SBI_BASE_PROBE_EXTENSION, id).value); } -static inline void sbi_console_putchar(int ch) +/* TIME extension functions. */ +void sbi_set_timer(uint64_t val); + +/* IPI extension functions. */ +void sbi_send_ipi(const unsigned long *hart_mask); + +/* RFENCE extension functions. */ +void sbi_remote_fence_i(const unsigned long *hart_mask); +void sbi_remote_sfence_vma(const unsigned long *hart_mask, unsigned long start, unsigned long size); +void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long start, + unsigned long size, unsigned long asid); + +/* Hart State Management extension functions. */ + +/* + * Start execution on the specified hart at physical address start_addr. The + * register a0 will contain the hart's ID, and a1 will contain the value of + * priv. + */ +int sbi_hsm_hart_start(unsigned long hart, unsigned long start_addr, unsigned long priv); + +/* + * Stop execution on the current hart. Interrupts should be disabled, or this + * function may return. + */ +void sbi_hsm_hart_stop(void); + +/* + * Get the execution status of the specified hart. The status will be one of: + * - SBI_HSM_STATUS_STARTED + * - SBI_HSM_STATUS_STOPPED + * - SBI_HSM_STATUS_START_PENDING + * - SBI_HSM_STATUS_STOP_PENDING + */ +int sbi_hsm_hart_status(unsigned long hart); + +/* Legacy extension functions. */ +static __inline void +sbi_console_putchar(int ch) { - SBI_CALL_1(SBI_CONSOLE_PUTCHAR, ch); + (void)SBI_CALL1(SBI_CONSOLE_PUTCHAR, 0, ch); } -static inline int sbi_console_getchar(void) +static __inline int +sbi_console_getchar(void) { - return SBI_CALL_0(SBI_CONSOLE_GETCHAR); + /* + * XXX: The "error" is returned here because legacy SBI functions + * continue to return their value in a0. + */ + return (SBI_CALL0(SBI_CONSOLE_GETCHAR, 0).error); } -static inline void sbi_set_timer(uint64_t stime_value) +static __inline void +sbi_shutdown(void) { -#if __riscv_xlen == 32 - SBI_CALL_2(SBI_SET_TIMER, stime_value, stime_value >> 32); -#else - SBI_CALL_1(SBI_SET_TIMER, stime_value); -#endif + + (void)SBI_CALL0(SBI_SHUTDOWN, 0); } -static inline void sbi_shutdown(void) { SBI_CALL_0(SBI_SHUTDOWN); } +void sbi_print_version(void); +void sbi_init(void); -static inline void sbi_clear_ipi(void) -{ - SBI_CALL_0(SBI_CLEAR_IPI); -} - -static inline void sbi_send_ipi(const unsigned long *hart_mask) -{ - SBI_CALL_1(SBI_SEND_IPI, hart_mask); -} - -static inline void sbi_remote_fence_i( - const unsigned long *hart_mask) -{ - SBI_CALL_1(SBI_REMOTE_FENCE_I, hart_mask); -} - -static inline void sbi_remote_sfence_vma( - const unsigned long *hart_mask, unsigned long start, - unsigned long size) -{ - SBI_CALL_1(SBI_REMOTE_SFENCE_VMA, hart_mask); -} - -static inline void sbi_remote_sfence_vma_asid( - const unsigned long *hart_mask, unsigned long start, - unsigned long size, unsigned long asid) -{ - SBI_CALL_1(SBI_REMOTE_SFENCE_VMA_ASID, hart_mask); -} - -static inline void sbi_net_write(char * buffer, int length) { - SBI_CALL_2(SBI_NET_WRITE, buffer, length); -} - -static inline void sbi_net_read() { - SBI_CALL_0(SBI_NET_READ); -} - -#endif +#endif /* !_MACHINE_SBI_H_ */ From f960128acf0996f2062e701c9b43d05a2c3d613f Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Tue, 18 May 2021 19:05:06 +0800 Subject: [PATCH 091/255] [BSP] remove the unnecessary code. --- bsp/qemu-riscv-virt64/driver/board.c | 15 ++------------- bsp/qemu-riscv-virt64/driver/drv_uart.c | 7 ------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/bsp/qemu-riscv-virt64/driver/board.c b/bsp/qemu-riscv-virt64/driver/board.c index ac021ed3c3..e723f49aca 100644 --- a/bsp/qemu-riscv-virt64/driver/board.c +++ b/bsp/qemu-riscv-virt64/driver/board.c @@ -22,24 +22,13 @@ #include "riscv.h" #include "stack.h" -void init_bss(void) -{ - unsigned int *dst; - - dst = &__bss_start; - while (dst < &__bss_end) - { - *dst++ = 0; - } -} - void primary_cpu_entry(void) { extern void entry(void); /* disable global interrupt */ - rt_memset(&__bss_start, 0x0, &__bss_end - &__bss_start); - // init_bss(); + rt_memset(&__bss_start, 0x0, (rt_uint8_t*)&__bss_end - (rt_uint8_t*)&__bss_start); + rt_hw_interrupt_disable(); entry(); } diff --git a/bsp/qemu-riscv-virt64/driver/drv_uart.c b/bsp/qemu-riscv-virt64/driver/drv_uart.c index 63820175e3..754a1fbfd1 100644 --- a/bsp/qemu-riscv-virt64/driver/drv_uart.c +++ b/bsp/qemu-riscv-virt64/driver/drv_uart.c @@ -107,13 +107,6 @@ static int drv_uart_getc(struct rt_serial_device *serial) return sbi_console_getchar(); } -#if 0 -void drv_uart_puts(char *str) -{ - sbi_console_putstr(str); -} -#endif - char rt_hw_console_getchar(void) { return sbi_console_getchar(); From 4aaf52ae9eccdbb6daa6634bb99c147186f0c01e Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 19 May 2021 12:56:27 +0800 Subject: [PATCH 092/255] =?UTF-8?q?[ymodem]=20=E4=BF=AE=E6=94=B9YMODEM=5FU?= =?UTF-8?q?SING=5FFILE=5FTRANSFER=E5=8A=9F=E8=83=BD=E7=9A=84=E5=BC=80?= =?UTF-8?q?=E5=90=AF=E6=9D=A1=E4=BB=B6=20=E7=9B=AE=E5=89=8D=E5=BC=80?= =?UTF-8?q?=E5=90=AF=E7=9A=84=E9=80=BB=E8=BE=91=E5=AD=98=E5=9C=A8=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=8Cymodem=E7=9A=84=E6=96=87=E4=BB=B6=E4=BC=A0?= =?UTF-8?q?=E8=BE=93=E5=8A=9F=E8=83=BD=E5=BC=80=E5=90=AF=E7=9A=84=E5=89=8D?= =?UTF-8?q?=E6=8F=90=E6=98=AF=E5=BE=97=E6=9C=89=E5=AE=8C=E6=95=B4=E7=9A=84?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=B3=BB=E7=BB=9F=EF=BC=8C=20=E4=BD=86?= =?UTF-8?q?=E6=98=AF=E7=9B=AE=E5=89=8D=EF=BC=8C=E8=BF=99=E4=B8=AA=E5=BC=80?= =?UTF-8?q?=E5=90=AF=E9=80=BB=E8=BE=91=E9=94=99=E4=BA=86=E3=80=82=20?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E9=80=89=E6=8B=A9YMODEM=5FUSING=5FFILE=5FTRA?= =?UTF-8?q?NSFER=E5=8A=9F=E8=83=BD=E5=90=8Eselect=20DFS=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E4=BB=BB=E4=BD=95=E6=84=8F=E4=B9=89=EF=BC=8C=E5=9B=A0=E4=B8=BA?= =?UTF-8?q?=E9=99=A4=E4=BA=86=E9=9C=80=E8=A6=81=E4=BE=9D=E8=B5=96DFS?= =?UTF-8?q?=E4=B9=8B=E5=A4=96=E8=BF=98=E8=A6=81=E4=BE=9D=E8=B5=96=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E7=9A=84=E4=BE=8B=E5=A6=82FATFS=EF=BC=8C=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E5=92=8CSDIO=E9=80=82=E9=85=8D=E7=AD=89=E7=AD=89?= =?UTF-8?q?=E7=AD=89=20=E6=AD=A3=E7=A1=AE=E7=9A=84=E5=81=9A=E6=B3=95?= =?UTF-8?q?=E5=BA=94=E8=AF=A5=E6=98=AF=E7=94=A8=E6=88=B7=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=A5=BD=E5=AE=8C=E6=95=B4=E7=9A=84=E6=96=87=E4=BB=B6=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=90=8E=EF=BC=8Cymodem=E6=96=87=E4=BB=B6=E4=BC=A0?= =?UTF-8?q?=E8=BE=93=E6=89=8D=E8=83=BD=E6=9C=89=E6=9C=BA=E4=BC=9A=E5=BC=80?= =?UTF-8?q?=E5=90=AF=EF=BC=8C=20=E5=9B=A0=E6=AD=A4=E6=98=AFdepends=20on=20?= =?UTF-8?q?DFS=20=E8=80=8C=E9=9D=9Eselect=20DFS=20=E6=9B=B4=E6=94=B9?= =?UTF-8?q?=E4=B9=8B=E5=90=8E=EF=BC=8C=E5=8F=AA=E8=A6=81=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=BC=80=E5=90=AF=E4=BA=86=E6=96=87=E4=BB=B6=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=EF=BC=8C=E5=9C=A8=E9=80=89=E5=AE=9AYMODEM=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E4=BC=9A=E8=87=AA=E5=8A=A8=E5=BC=80=E5=90=AF=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=BC=A0=E8=BE=93=E5=8A=9F=E8=83=BD=EF=BC=8C=E8=BF=99=E4=B9=9F?= =?UTF-8?q?=E6=98=AF=E7=94=A8=E6=88=B7=E5=B8=8C=E6=9C=9B=E7=9C=8B=E5=88=B0?= =?UTF-8?q?=E7=9A=84=EF=BC=8C=E7=9B=B4=E6=8E=A5=E4=B8=80=E9=94=AE=E6=90=9E?= =?UTF-8?q?=E5=AE=9A=EF=BC=8C=E4=B8=8D=E9=9C=80=E8=A6=81=E5=86=8D=E5=A4=9A?= =?UTF-8?q?=E7=82=B9=E4=B8=80=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/utilities/Kconfig | 4 ++-- components/utilities/ymodem/SConscript | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/utilities/Kconfig b/components/utilities/Kconfig index 8b733ecf5c..247986d579 100644 --- a/components/utilities/Kconfig +++ b/components/utilities/Kconfig @@ -11,8 +11,8 @@ config RT_USING_RYM config YMODEM_USING_FILE_TRANSFER bool "Enable file transfer feature" - select RT_USING_DFS - default n + depends on RT_USING_DFS + default y endif config RT_USING_ULOG diff --git a/components/utilities/ymodem/SConscript b/components/utilities/ymodem/SConscript index 5be32247d6..d75539fe2c 100644 --- a/components/utilities/ymodem/SConscript +++ b/components/utilities/ymodem/SConscript @@ -7,7 +7,7 @@ ymodem.c CPPPATH = [cwd] -if GetDepend('RT_USING_DFS') and GetDepend('YMODEM_USING_FILE_TRANSFER'): +if GetDepend('YMODEM_USING_FILE_TRANSFER'): src += ['ry_sy.c'] group = DefineGroup('Utilities', src, depend = ['RT_USING_RYM'], CPPPATH = CPPPATH) From e0b9987508e6c9daecee2af2a30f57ba82a49dbc Mon Sep 17 00:00:00 2001 From: armink Date: Wed, 19 May 2021 18:17:37 +0800 Subject: [PATCH 093/255] [ulog] Add output locker enabled API Signed-off-by: armink --- components/utilities/ulog/ulog.c | 13 +++++++++++++ components/utilities/ulog/ulog.h | 1 + 2 files changed, 14 insertions(+) diff --git a/components/utilities/ulog/ulog.c b/components/utilities/ulog/ulog.c index 9dd2ed2fd0..c36fc6ff26 100644 --- a/components/utilities/ulog/ulog.c +++ b/components/utilities/ulog/ulog.c @@ -77,6 +77,7 @@ struct rt_ulog { rt_bool_t init_ok; + rt_bool_t output_lock_enabled; struct rt_semaphore output_locker; /* all backends */ rt_slist_t backend_list; @@ -186,6 +187,9 @@ size_t ulog_ultoa(char *s, unsigned long int n) static void output_unlock(void) { + if (!ulog.output_lock_enabled) + return; + /* is in thread context */ if (rt_interrupt_get_nest() == 0) { @@ -201,6 +205,9 @@ static void output_unlock(void) static void output_lock(void) { + if (!ulog.output_lock_enabled) + return; + /* is in thread context */ if (rt_interrupt_get_nest() == 0) { @@ -214,6 +221,11 @@ static void output_lock(void) } } +void ulog_output_lock_enabled(rt_bool_t enabled) +{ + ulog.output_lock_enabled = enabled; +} + static char *get_log_buf(void) { /* is in thread context */ @@ -1392,6 +1404,7 @@ int ulog_init(void) return 0; rt_sem_init(&ulog.output_locker, "ulog lock", 1, RT_IPC_FLAG_FIFO); + ulog.output_lock_enabled = RT_TRUE; rt_slist_init(&ulog.backend_list); #ifdef ULOG_USING_FILTER diff --git a/components/utilities/ulog/ulog.h b/components/utilities/ulog/ulog.h index 3754828e56..1e139222aa 100644 --- a/components/utilities/ulog/ulog.h +++ b/components/utilities/ulog/ulog.h @@ -25,6 +25,7 @@ extern "C" { */ int ulog_init(void); int ulog_async_init(void); +void ulog_output_lock_enabled(rt_bool_t enabled); void ulog_deinit(void); /* From 5d333029924d2b467b3d5da24851132771a473b7 Mon Sep 17 00:00:00 2001 From: lizhirui Date: Thu, 20 May 2021 16:23:56 +0800 Subject: [PATCH 094/255] Revert "repair hard fault return bug" This reverts commit e7fc0c89d2367533dcd1b77e46acaeea7bc3f876. --- libcpu/arm/cortex-m7/context_rvds.S | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libcpu/arm/cortex-m7/context_rvds.S b/libcpu/arm/cortex-m7/context_rvds.S index 6caed09e38..d051f819c1 100644 --- a/libcpu/arm/cortex-m7/context_rvds.S +++ b/libcpu/arm/cortex-m7/context_rvds.S @@ -10,7 +10,6 @@ ; * 2013-06-18 aozima add restore MSP feature. ; * 2013-06-23 aozima support lazy stack optimized. ; * 2018-07-24 aozima enhancement hard fault exception handler. -; * 2021-02-15 lizhirui repair hard fault return bug ; */ ;/** @@ -236,6 +235,11 @@ MemManage_Handler ENDIF STMFD r0!, {lr} ; push exec_return register + TST lr, #0x04 ; if(!EXC_RETURN[2]) + ITE EQ + MSREQ msp, r0 ; [2]=0 ==> Z=1, update stack pointer to MSP. + MSRNE psp, r0 ; [2]=1 ==> Z=0, update stack pointer to PSP. + PUSH {lr} BL rt_hw_hard_fault_exception POP {lr} From 7ab3b4dedcef6fdffb17ede5028ccfd27cb15a3d Mon Sep 17 00:00:00 2001 From: Meco Jianting Man <920369182@qq.com> Date: Fri, 21 May 2021 10:09:26 +0800 Subject: [PATCH 095/255] =?UTF-8?q?=E7=A7=BB=E9=99=A4cmd.c=E9=A6=96?= =?UTF-8?q?=E8=A1=8C=E7=A9=BA=E7=99=BD=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/finsh/cmd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index 8b51896cde..4c76ab7395 100644 --- a/components/finsh/cmd.c +++ b/components/finsh/cmd.c @@ -1,4 +1,3 @@ - /* * Copyright (c) 2006-2021, RT-Thread Development Team * From b7c7c7f4dec7ec3708ff056b3d12c9750c835f38 Mon Sep 17 00:00:00 2001 From: bigmagic Date: Fri, 21 May 2021 17:03:30 +0800 Subject: [PATCH 096/255] Support for running with M-Mode --- bsp/qemu-riscv-virt64/.config | 7 +- bsp/qemu-riscv-virt64/SConstruct | 6 +- bsp/qemu-riscv-virt64/applications/main.c | 7 +- bsp/qemu-riscv-virt64/driver/Kconfig | 7 +- bsp/qemu-riscv-virt64/driver/board.c | 149 +-------- bsp/qemu-riscv-virt64/driver/drv_uart.c | 116 +++---- bsp/qemu-riscv-virt64/driver/drv_uart.h | 34 +- bsp/qemu-riscv-virt64/driver/plic.c | 98 ++++++ bsp/qemu-riscv-virt64/driver/plic.h | 61 ++++ bsp/qemu-riscv-virt64/link.lds | 4 +- bsp/qemu-riscv-virt64/link_stacksize.lds | 3 +- bsp/qemu-riscv-virt64/qemu-nographic-smode.sh | 1 + bsp/qemu-riscv-virt64/qemu-nographic.sh | 2 +- bsp/qemu-riscv-virt64/rtconfig.h | 2 +- libcpu/risc-v/virt64/context_gcc.S | 298 ++++++++++++++++-- libcpu/risc-v/virt64/cpuport.c | 7 +- libcpu/risc-v/virt64/cpuport.h | 31 +- libcpu/risc-v/virt64/interrupt.c | 274 ++++++++++++++++ libcpu/risc-v/virt64/interrupt.h | 27 ++ libcpu/risc-v/virt64/interrupt_gcc.S | 178 +++++++---- libcpu/risc-v/virt64/riscv_io.h | 176 ++++++----- libcpu/risc-v/virt64/stack.h | 2 +- libcpu/risc-v/virt64/stackframe.h | 22 +- libcpu/risc-v/virt64/startup_gcc.S | 77 ++--- libcpu/risc-v/virt64/tick.c | 30 +- libcpu/risc-v/virt64/tick.h | 5 + 26 files changed, 1162 insertions(+), 462 deletions(-) create mode 100644 bsp/qemu-riscv-virt64/driver/plic.c create mode 100644 bsp/qemu-riscv-virt64/driver/plic.h create mode 100755 bsp/qemu-riscv-virt64/qemu-nographic-smode.sh mode change 100644 => 100755 bsp/qemu-riscv-virt64/qemu-nographic.sh create mode 100644 libcpu/risc-v/virt64/interrupt.c create mode 100644 libcpu/risc-v/virt64/interrupt.h diff --git a/bsp/qemu-riscv-virt64/.config b/bsp/qemu-riscv-virt64/.config index 8a61ab72eb..49c8fff6b0 100644 --- a/bsp/qemu-riscv-virt64/.config +++ b/bsp/qemu-riscv-virt64/.config @@ -213,6 +213,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_RT_LINK is not set # # RT-Thread Utestcases @@ -335,6 +336,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # 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 @@ -492,6 +494,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # 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 @@ -519,6 +522,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # 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 @@ -558,7 +562,8 @@ CONFIG_BOARD_virt=y CONFIG_RT_USING_USERSPACE=y # -# General Purpose UARTs +# RISCV qemu virt64 configs # # CONFIG_BSP_USING_UART1 is not set +# CONFIG_RISCV_S_MODE is not set CONFIG___STACKSIZE__=16384 diff --git a/bsp/qemu-riscv-virt64/SConstruct b/bsp/qemu-riscv-virt64/SConstruct index 422e592ccd..770a62ccc2 100644 --- a/bsp/qemu-riscv-virt64/SConstruct +++ b/bsp/qemu-riscv-virt64/SConstruct @@ -31,7 +31,11 @@ stack_size = 4096 stack_lds = open('link_stacksize.lds', 'w') if GetDepend('__STACKSIZE__'): stack_size = GetDepend('__STACKSIZE__') -stack_lds.write('__STACKSIZE__ = %d;' % stack_size) +stack_lds.write('__STACKSIZE__ = %d;\r\n' % stack_size) +if GetDepend('RISCV_S_MODE'): start_addr = int(0x80200000) +else: start_addr = int(0x80000000) +stack_lds.write('__START_ADDR__ = 0x%x;' % start_addr) + stack_lds.close() # make a building diff --git a/bsp/qemu-riscv-virt64/applications/main.c b/bsp/qemu-riscv-virt64/applications/main.c index 288d4f08ba..50d2de7a22 100644 --- a/bsp/qemu-riscv-virt64/applications/main.c +++ b/bsp/qemu-riscv-virt64/applications/main.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes + * 2021-05-20 bigmagic first version */ #include @@ -14,9 +15,7 @@ int main(void) { - void rt_hw_uart_start_rx_thread(); - rt_hw_uart_start_rx_thread(); - printf("Hello RISC-V\n"); + printf("Hello RISC-V!\n"); return 0; } diff --git a/bsp/qemu-riscv-virt64/driver/Kconfig b/bsp/qemu-riscv-virt64/driver/Kconfig index 5744c89702..d6fca695ef 100644 --- a/bsp/qemu-riscv-virt64/driver/Kconfig +++ b/bsp/qemu-riscv-virt64/driver/Kconfig @@ -1,6 +1,6 @@ -menu "General Purpose UARTs" +menu "RISCV qemu virt64 configs" menuconfig BSP_USING_UART1 bool "Enable UART1" @@ -14,5 +14,8 @@ menuconfig BSP_USING_UART1 default 21 endif -endmenu +config RISCV_S_MODE + bool "RT-Thread run in riscv smode" + default y +endmenu diff --git a/bsp/qemu-riscv-virt64/driver/board.c b/bsp/qemu-riscv-virt64/driver/board.c index e723f49aca..1e567ea151 100644 --- a/bsp/qemu-riscv-virt64/driver/board.c +++ b/bsp/qemu-riscv-virt64/driver/board.c @@ -21,6 +21,9 @@ #include "sbi.h" #include "riscv.h" #include "stack.h" +#include "riscv_io.h" +#include "plic.h" +#include "interrupt.h" void primary_cpu_entry(void) { @@ -33,11 +36,6 @@ void primary_cpu_entry(void) entry(); } -void rt_hw_interrupt_init() -{ - /* Enable machine external interrupts. */ - set_csr(sie, SIP_SEIP); -} void rt_hw_board_init(void) { @@ -46,10 +44,7 @@ void rt_hw_board_init(void) /* initialize hardware interrupt */ rt_hw_uart_init(); - rt_hw_tick_init(); - #ifdef RT_USING_HEAP - rt_kprintf("heap: [0x%08x - 0x%08x]\n", (rt_ubase_t) RT_HW_HEAP_BEGIN, (rt_ubase_t) RT_HW_HEAP_END); /* initialize memory system */ rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); #endif @@ -58,7 +53,9 @@ void rt_hw_board_init(void) /* set console device */ rt_console_set_device("uart"); #endif /* RT_USING_CONSOLE */ - + rt_hw_tick_init(); + rt_kprintf("heap: [0x%08x - 0x%08x]\n", (rt_ubase_t) RT_HW_HEAP_BEGIN, (rt_ubase_t) RT_HW_HEAP_END); + #ifdef RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif @@ -71,137 +68,3 @@ void rt_hw_cpu_reset(void) } MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine); -void dump_regs(struct rt_hw_stack_frame *regs) -{ - rt_kprintf("--------------Dump Registers-----------------\n"); - - rt_kprintf("Function Registers:\n"); - rt_kprintf("\tra(x1) = 0x%p\tuser_sp = 0x%p\n",regs -> ra,regs -> user_sp_exc_stack); - rt_kprintf("\tgp(x3) = 0x%p\ttp(x4) = 0x%p\n",regs -> gp,regs -> tp); - rt_kprintf("Temporary Registers:\n"); - rt_kprintf("\tt0(x5) = 0x%p\tt1(x6) = 0x%p\n",regs -> t0,regs -> t1); - rt_kprintf("\tt2(x7) = 0x%p\n",regs -> t2); - rt_kprintf("\tt3(x28) = 0x%p\tt4(x29) = 0x%p\n",regs -> t3,regs -> t4); - rt_kprintf("\tt5(x30) = 0x%p\tt6(x31) = 0x%p\n",regs -> t5,regs -> t6); - rt_kprintf("Saved Registers:\n"); - rt_kprintf("\ts0/fp(x8) = 0x%p\ts1(x9) = 0x%p\n",regs -> s0_fp,regs -> s1); - rt_kprintf("\ts2(x18) = 0x%p\ts3(x19) = 0x%p\n",regs -> s2,regs -> s3); - rt_kprintf("\ts4(x20) = 0x%p\ts5(x21) = 0x%p\n",regs -> s4,regs -> s5); - rt_kprintf("\ts6(x22) = 0x%p\ts7(x23) = 0x%p\n",regs -> s6,regs -> s7); - rt_kprintf("\ts8(x24) = 0x%p\ts9(x25) = 0x%p\n",regs -> s8,regs -> s9); - rt_kprintf("\ts10(x26) = 0x%p\ts11(x27) = 0x%p\n",regs -> s10,regs -> s11); - rt_kprintf("Function Arguments Registers:\n"); - rt_kprintf("\ta0(x10) = 0x%p\ta1(x11) = 0x%p\n",regs -> a0,regs -> a1); - rt_kprintf("\ta2(x12) = 0x%p\ta3(x13) = 0x%p\n",regs -> a2,regs -> a3); - rt_kprintf("\ta4(x14) = 0x%p\ta5(x15) = 0x%p\n",regs -> a4,regs -> a5); - rt_kprintf("\ta6(x16) = 0x%p\ta7(x17) = 0x%p\n",regs -> a6,regs -> a7); - rt_kprintf("sstatus = 0x%p\n",regs -> sstatus); - rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled"); - rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled"); - rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode"); - rt_kprintf("\t%s\n",(regs -> sstatus & SSTATUS_PUM) ? "Permit to Access User Page" : "Not Permit to Access User Page"); - rt_kprintf("\t%s\n",(regs -> sstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page"); - rt_size_t satp_v = read_csr(satp); - rt_kprintf("satp = 0x%p\n",satp_v); - const char *mode_str = "Unknown Address Translation/Protection Mode"; - - switch(__MASKVALUE(satp_v >> 60,__MASK(4))) - { - case 0: - mode_str = "No Address Translation/Protection Mode"; - break; - - case 8: - mode_str = "Page-based 39-bit Virtual Addressing Mode"; - break; - - case 9: - mode_str = "Page-based 48-bit Virtual Addressing Mode"; - break; - } - - rt_kprintf("\tMode = %s\n",mode_str); - rt_kprintf("-----------------Dump OK---------------------\n"); -} - -static const char *Exception_Name[] = - { - "Instruction Address Misaligned", - "Instruction Access Fault", - "Illegal Instruction", - "Breakpoint", - "Load Address Misaligned", - "Load Access Fault", - "Store/AMO Address Misaligned", - "Store/AMO Access Fault", - "Environment call from U-mode", - "Environment call from S-mode", - "Reserved-10", - "Reserved-11", - "Instruction Page Fault", - "Load Page Fault", - "Reserved-14", - "Store/AMO Page Fault" - }; - -static const char *Interrupt_Name[] = - { - "User Software Interrupt", - "Supervisor Software Interrupt", - "Reversed-2", - "Reversed-3", - "User Timer Interrupt", - "Supervisor Timer Interrupt", - "Reversed-6", - "Reversed-7", - "User External Interrupt", - "Supervisor External Interrupt", - "Reserved-10", - "Reserved-11", - }; - -void handle_trap(rt_size_t scause,rt_size_t stval,rt_size_t sepc,struct rt_hw_stack_frame *sp) -{ - if(scause == (uint64_t)(0x8000000000000005)) - { - rt_interrupt_enter(); - tick_isr(); - rt_interrupt_leave(); - } - else - { - rt_size_t id = __MASKVALUE(scause,__MASK(63UL)); - const char *msg; - - if(scause >> 63) - { - if(id < sizeof(Interrupt_Name) / sizeof(const char *)) - { - msg = Interrupt_Name[id]; - } - else - { - msg = "Unknown Interrupt"; - } - - rt_kprintf("Unhandled Interrupt %ld:%s\n",id,msg); - } - else - { - if(id < sizeof(Exception_Name) / sizeof(const char *)) - { - msg = Exception_Name[id]; - } - else - { - msg = "Unknown Exception"; - } - - rt_kprintf("Unhandled Exception %ld:%s\n",id,msg); - } - - rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n",scause,stval,sepc); - dump_regs(sp); - while(1); - } -} diff --git a/bsp/qemu-riscv-virt64/driver/drv_uart.c b/bsp/qemu-riscv-virt64/driver/drv_uart.c index 754a1fbfd1..f6ee2e1c7f 100644 --- a/bsp/qemu-riscv-virt64/driver/drv_uart.c +++ b/bsp/qemu-riscv-virt64/driver/drv_uart.c @@ -1,10 +1,12 @@ /* - * Copyright (c) 2019-2020, Xim + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * + * Change Logs: + * Date Author Notes + * 2021-05-20 bigmagic first version */ - #include #include @@ -13,8 +15,7 @@ #include #include "sbi.h" - -#define UART_DEFAULT_BAUDRATE 115200 +#include "interrupt.h" struct device_uart { @@ -27,24 +28,26 @@ static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg static int drv_uart_putc(struct rt_serial_device *serial, char c); static int drv_uart_getc(struct rt_serial_device *serial); -const struct rt_uart_ops _uart_ops = +void virt_uart_init(void) { - rt_uart_configure, - uart_control, - drv_uart_putc, - drv_uart_getc, - //TODO: add DMA support - RT_NULL -}; + //http://byterunner.com/16550.html + uart_write_reg(IER, 0x00); -void uart_init(void) -{ - return ; + uint8_t lcr = uart_read_reg(LCR); + uart_write_reg(LCR, lcr | (1 << 7)); + uart_write_reg(DLL, 0x03); + uart_write_reg(DLM, 0x00); + + lcr = 0; + uart_write_reg(LCR, lcr | (3 << 0)); + + /* + * enable receive interrupts. + */ + uint8_t ier = uart_read_reg(IER); + uart_write_reg(IER, ier | (1 << 0)); } -struct rt_serial_device serial1; -struct device_uart uart1; - /* * UART interface */ @@ -58,22 +61,6 @@ static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial return (RT_EOK); } -#define UART_LSR_DR 0x01 /* Data ready */ -#define UART_LSR_THRE 0x20 /* Xmit holding register empty */ - -#define UART_RBR(hw) HWREG32(hw + 0x00) -#define UART_IER(hw) HWREG32(hw + 0x04) -#define UART_LSR(hw) HWREG32(hw + 0x14) - -static volatile uint64_t uart_hwbase = 0x10000000; - -void uart_putc(char c) -{ - while ((UART_LSR(uart_hwbase) & UART_LSR_THRE) == 0); - - UART_RBR(uart_hwbase) = c; -} - static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg) { struct device_uart *uart; @@ -97,39 +84,39 @@ static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg } static int drv_uart_putc(struct rt_serial_device *serial, char c) -{ - sbi_console_putchar(c); - return (1); +{ + while ((uart_read_reg(LSR) & LSR_TX_IDLE) == 0); + return uart_write_reg(THR, c); } static int drv_uart_getc(struct rt_serial_device *serial) { - return sbi_console_getchar(); -} - -char rt_hw_console_getchar(void) -{ - return sbi_console_getchar(); -} - -static void uart_rx(void *param) -{ - struct rt_serial_device *serial = (struct rt_serial_device *)param; - - while(1) - { - rt_hw_serial_isr((struct rt_serial_device *)serial,RT_SERIAL_EVENT_RX_IND); - rt_thread_mdelay(10); + if (uart_read_reg(LSR) & LSR_RX_READY){ + return uart_read_reg(RHR); + } else { + return -1; } + //return sbi_console_getchar(); } -void rt_hw_uart_start_rx_thread() +static void rt_hw_uart_isr(int irqno, void *param) { - rt_thread_t th; - RT_ASSERT((th = rt_thread_create("uartrx",uart_rx,(void *)&serial1,8192,8,20)) != RT_NULL); - RT_ASSERT(rt_thread_startup(th) == RT_EOK); + struct rt_serial_device *serial = (struct rt_serial_device*)param; + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); } +struct rt_serial_device serial1; +struct device_uart uart1; + +const struct rt_uart_ops _uart_ops = +{ + rt_uart_configure, + uart_control, + drv_uart_putc, + drv_uart_getc, + RT_NULL +}; + /* * UART Initiation */ @@ -138,7 +125,6 @@ int rt_hw_uart_init(void) struct rt_serial_device *serial; struct device_uart *uart; struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; - { serial = &serial1; uart = &uart1; @@ -147,19 +133,19 @@ int rt_hw_uart_init(void) serial->config = config; serial->config.baud_rate = UART_DEFAULT_BAUDRATE; - uart->hw_base = 0x10000000; - uart->irqno = 0xa; + uart->hw_base = UART_BASE; + uart->irqno = UART0_IRQ; + + virt_uart_init(); rt_hw_serial_register(serial, "uart", RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); + rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, "uart"); + + rt_hw_interrupt_umask(uart->irqno); } return 0; } - -/* WEAK for SDK 0.5.6 */ -RT_WEAK void uart_debug_init(int uart_channel) -{ -} diff --git a/bsp/qemu-riscv-virt64/driver/drv_uart.h b/bsp/qemu-riscv-virt64/driver/drv_uart.h index a7a18d0dde..1a590b83df 100644 --- a/bsp/qemu-riscv-virt64/driver/drv_uart.h +++ b/bsp/qemu-riscv-virt64/driver/drv_uart.h @@ -1,15 +1,43 @@ /* - * Copyright (c) 2019-2020, Xim + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * + * Change Logs: + * Date Author Notes + * 2021-05-20 bigmagic first version */ #ifndef __DRV_UART_H__ #define __DRV_UART_H__ -void rt_hw_uart_start_rx_thread(); +#define UART0_IRQ (10) + +#define UART_DEFAULT_BAUDRATE 115200 + +#define UART_BASE (0x10000000L) + +#define RHR 0 // Receive Holding Register (read mode) +#define THR 0 // Transmit Holding Register (write mode) +#define DLL 0 // LSB of Divisor Latch (write mode) +#define IER 1 // Interrupt Enable Register (write mode) +#define DLM 1 // MSB of Divisor Latch (write mode) +#define FCR 2 // FIFO Control Register (write mode) +#define ISR 2 // Interrupt Status Register (read mode) +#define LCR 3 // Line Control Register +#define MCR 4 // Modem Control Register +#define LSR 5 // Line Status Register +#define MSR 6 // Modem Status Register +#define SPR 7 // ScratchPad Register + +#define UART_REG(reg) ((volatile uint8_t *)(UART_BASE + reg)) + +#define LSR_RX_READY (1 << 0) +#define LSR_TX_IDLE (1 << 5) + +#define uart_read_reg(reg) (*(UART_REG(reg))) +#define uart_write_reg(reg, v) (*(UART_REG(reg)) = (v)) + int rt_hw_uart_init(void); -void drv_uart_puts(char *str); // for syscall #endif /* __DRV_UART_H__ */ diff --git a/bsp/qemu-riscv-virt64/driver/plic.c b/bsp/qemu-riscv-virt64/driver/plic.c new file mode 100644 index 0000000000..afd186933d --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/plic.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-20 bigmagic first version + */ +#include "rtthread.h" +#include "plic.h" +#include +#include "encoding.h" + +/* +* Each PLIC interrupt source can be assigned a priority by writing +* to its 32-bit memory-mapped priority register. +* The QEMU-virt (the same as FU540-C000) supports 7 levels of priority. +* A priority value of 0 is reserved to mean "never interrupt" and +* effectively disables the interrupt. +* Priority 1 is the lowest active priority, and priority 7 is the highest. +* Ties between global interrupts of the same priority are broken by +* the Interrupt ID; interrupts with the lowest ID have the highest +* effective priority. +*/ +void plic_set_priority(int irq, int priority) +{ + *(uint32_t*)PLIC_PRIORITY(irq) = priority; +} + +/* +* Each global interrupt can be enabled by setting the corresponding +* bit in the enables registers. +*/ +void plic_irq_enable(int irq) +{ + int hart = r_mhartid(); + *(uint32_t*)PLIC_ENABLE(hart) = ((*(uint32_t*)PLIC_ENABLE(hart)) | (1 << irq)); +#ifdef RISCV_S_MODE + set_csr(sie, read_csr(sie) | MIP_SEIP); +#else + set_csr(mie, read_csr(mie) | MIP_MEIP); +#endif +} + +void plic_irq_disable(int irq) +{ + int hart = r_mhartid(); + *(uint32_t*)PLIC_ENABLE(hart) = (((*(uint32_t*)PLIC_ENABLE(hart)) & (~(1 << irq)))); +} + +/* +* PLIC will mask all interrupts of a priority less than or equal to threshold. +* Maximum threshold is 7. +* For example, a threshold value of zero permits all interrupts with +* non-zero priority, whereas a value of 7 masks all interrupts. +* Notice, the threshold is global for PLIC, not for each interrupt source. +*/ +void plic_set_threshold(int threshold) +{ + int hart = r_mhartid(); + *(uint32_t*)PLIC_THRESHOLD(hart) = threshold; +} + +/* + * DESCRIPTION: + * Query the PLIC what interrupt we should serve. + * Perform an interrupt claim by reading the claim register, which + * returns the ID of the highest-priority pending interrupt or zero if there + * is no pending interrupt. + * A successful claim also atomically clears the corresponding pending bit + * on the interrupt source. + * RETURN VALUE: + * the ID of the highest-priority pending interrupt or zero if there + * is no pending interrupt. + */ +int plic_claim(void) +{ + int hart = r_mhartid(); + int irq = *(uint32_t*)PLIC_CLAIM(hart); + return irq; +} + +/* + * DESCRIPTION: + * Writing the interrupt ID it received from the claim (irq) to the + * complete register would signal the PLIC we've served this IRQ. + * The PLIC does not check whether the completion ID is the same as the + * last claim ID for that target. If the completion ID does not match an + * interrupt source that is currently enabled for the target, the completion + * is silently ignored. + * RETURN VALUE: none + */ +void plic_complete(int irq) +{ + int hart = r_mhartid(); + *(uint32_t*)PLIC_COMPLETE(hart) = irq; +} diff --git a/bsp/qemu-riscv-virt64/driver/plic.h b/bsp/qemu-riscv-virt64/driver/plic.h new file mode 100644 index 0000000000..79af90cbfb --- /dev/null +++ b/bsp/qemu-riscv-virt64/driver/plic.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-20 bigmagic first version + */ + +#ifndef PLIC_H +#define PLIC_H + +#include +/* + * This machine puts platform-level interrupt controller (PLIC) here. + * Here only list PLIC registers in Machine mode. + * + */ + +#define VIRT_PLIC_BASE 0x0c000000L + +#define PLIC_PRIORITY_OFFSET (0x0) +#define PLIC_PENDING_OFFSET (0x1000) + +#ifndef RISCV_S_MODE +#define PLIC_MENABLE_OFFSET (0x2000) +#define PLIC_MTHRESHOLD_OFFSET (0x200000) +#define PLIC_MCLAIM_OFFSET (0x200004) +#define PLIC_MCOMPLETE_OFFSET (0x200004) + +#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_MENABLE_OFFSET + (hart) * 0x80) +#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_MTHRESHOLD_OFFSET + (hart) * 0x1000) +#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_MCLAIM_OFFSET + (hart) * 0x1000) +#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_MCOMPLETE_OFFSET + (hart) * 0x1000) + +#else +#define PLIC_SENABLE_OFFSET (0x2080) +#define PLIC_STHRESHOLD_OFFSET (0x201000) +#define PLIC_SCLAIM_OFFSET (0x201004) +#define PLIC_SCOMPLETE_OFFSET (0x201004) + +#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_SENABLE_OFFSET + (hart) * 0x80) +#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_STHRESHOLD_OFFSET + (hart) * 0x1000) +#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_SCLAIM_OFFSET + (hart) * 0x1000) +#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_SCOMPLETE_OFFSET + (hart) * 0x1000) +#endif + +#define PLIC_PRIORITY(id) (VIRT_PLIC_BASE + PLIC_PRIORITY_OFFSET + (id) * 4) +#define PLIC_PENDING(id) (VIRT_PLIC_BASE + PLIC_PENDING_OFFSET + ((id) / 32)) + + + +void plic_set_priority(int irq, int priority); +void plic_irq_enable(int irq); +void plic_irq_disable(int irq); +void plic_set_threshold(int mthreshold); +int plic_claim(void); +void plic_complete(int irq); + +#endif diff --git a/bsp/qemu-riscv-virt64/link.lds b/bsp/qemu-riscv-virt64/link.lds index e8c0db9c24..2614e0eb36 100644 --- a/bsp/qemu-riscv-virt64/link.lds +++ b/bsp/qemu-riscv-virt64/link.lds @@ -21,13 +21,13 @@ OUTPUT_ARCH( "riscv" ) MEMORY { - SRAM : ORIGIN = 0x80200000, LENGTH = 0x7FF000 + SRAM : ORIGIN = __START_ADDR__, LENGTH = 0x7FF000 } ENTRY(_start) SECTIONS { - . = 0x80200000 ; + . = __START_ADDR__ ; /* __STACKSIZE__ = 4096; */ diff --git a/bsp/qemu-riscv-virt64/link_stacksize.lds b/bsp/qemu-riscv-virt64/link_stacksize.lds index 8685bc0f1c..4a0d736ae8 100644 --- a/bsp/qemu-riscv-virt64/link_stacksize.lds +++ b/bsp/qemu-riscv-virt64/link_stacksize.lds @@ -1 +1,2 @@ -__STACKSIZE__ = 16384; \ No newline at end of file +__STACKSIZE__ = 16384; +__START_ADDR__ = 0x80000000; \ No newline at end of file diff --git a/bsp/qemu-riscv-virt64/qemu-nographic-smode.sh b/bsp/qemu-riscv-virt64/qemu-nographic-smode.sh new file mode 100755 index 0000000000..750f6f0fcd --- /dev/null +++ b/bsp/qemu-riscv-virt64/qemu-nographic-smode.sh @@ -0,0 +1 @@ +qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin \ No newline at end of file diff --git a/bsp/qemu-riscv-virt64/qemu-nographic.sh b/bsp/qemu-riscv-virt64/qemu-nographic.sh old mode 100644 new mode 100755 index 934c4f935b..546e7a3d87 --- a/bsp/qemu-riscv-virt64/qemu-nographic.sh +++ b/bsp/qemu-riscv-virt64/qemu-nographic.sh @@ -1 +1 @@ -qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin +qemu-system-riscv64 -nographic -machine virt -m 256M -bios rtthread.bin diff --git a/bsp/qemu-riscv-virt64/rtconfig.h b/bsp/qemu-riscv-virt64/rtconfig.h index 38d19a2265..fab069701e 100644 --- a/bsp/qemu-riscv-virt64/rtconfig.h +++ b/bsp/qemu-riscv-virt64/rtconfig.h @@ -177,7 +177,7 @@ #define BOARD_virt #define RT_USING_USERSPACE -/* General Purpose UARTs */ +/* RISCV qemu virt64 configs */ #define __STACKSIZE__ 16384 diff --git a/libcpu/risc-v/virt64/context_gcc.S b/libcpu/risc-v/virt64/context_gcc.S index 881bcd162c..620559a8d0 100644 --- a/libcpu/risc-v/virt64/context_gcc.S +++ b/libcpu/risc-v/virt64/context_gcc.S @@ -9,44 +9,300 @@ * 2018/12/27 Jesven Add SMP support * 2021/02/02 lizhirui Add userspace support */ - #include "cpuport.h" -#include "stackframe.h" +#ifdef RT_USING_SMP +#define rt_hw_interrupt_disable rt_hw_local_irq_disable +#define rt_hw_interrupt_enable rt_hw_local_irq_enable +#endif + +/* + * rt_base_t rt_hw_interrupt_disable(void); + */ + .globl rt_hw_interrupt_disable +rt_hw_interrupt_disable: +#ifdef RISCV_S_MODE + csrrci a0, sstatus, 2 +#else + csrrci a0, mstatus, 8 +#endif + ret + + +/* + * void rt_hw_interrupt_enable(rt_base_t level); + */ + .globl rt_hw_interrupt_enable +rt_hw_interrupt_enable: + csrw SRC_XSTATUS, a0 + ret + +/* + * #ifdef RT_USING_SMP + * void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread); + * #else + * void rt_hw_context_switch_to(rt_ubase_t to); + * #endif + * a0 --> to + * a1 --> to_thread + */ .globl rt_hw_context_switch_to rt_hw_context_switch_to: LOAD sp, (a0) - la s0, rt_current_thread - LOAD s1, (s0) - - RESTORE_ALL - sret +#ifdef RT_USING_SMP + mv a0, a1 + call rt_cpus_lock_status_restore +#endif + LOAD a0, 2 * REGBYTES(sp) + csrw SRC_XSTATUS, a0 + j rt_hw_context_switch_exit /* + * #ifdef RT_USING_SMP + * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread); + * #else * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to); + * #endif * * a0 --> from * a1 --> to + * a2 --> to_thread */ .globl rt_hw_context_switch rt_hw_context_switch: - mv t2, sp - li t0, 0x120//set SPIE and SPP = 1 - csrs sstatus, t0//if enter here,caller must be in system thread - csrw sepc, ra//return address - //saved from thread context - SAVE_ALL + /* saved from thread context + * x1/ra -> sp(0) + * x1/ra -> sp(1) + * mstatus.mie -> sp(2) + * x(i) -> sp(i-4) + */ +#ifdef ARCH_RISCV_FPU + addi sp, sp, -32 * FREGBYTES - STORE t2, 32 * REGBYTES(sp)//save user_sp + FSTORE f0, 0 * FREGBYTES(sp) + FSTORE f1, 1 * FREGBYTES(sp) + FSTORE f2, 2 * FREGBYTES(sp) + FSTORE f3, 3 * FREGBYTES(sp) + FSTORE f4, 4 * FREGBYTES(sp) + FSTORE f5, 5 * FREGBYTES(sp) + FSTORE f6, 6 * FREGBYTES(sp) + FSTORE f7, 7 * FREGBYTES(sp) + FSTORE f8, 8 * FREGBYTES(sp) + FSTORE f9, 9 * FREGBYTES(sp) + FSTORE f10, 10 * FREGBYTES(sp) + FSTORE f11, 11 * FREGBYTES(sp) + FSTORE f12, 12 * FREGBYTES(sp) + FSTORE f13, 13 * FREGBYTES(sp) + FSTORE f14, 14 * FREGBYTES(sp) + FSTORE f15, 15 * FREGBYTES(sp) + FSTORE f16, 16 * FREGBYTES(sp) + FSTORE f17, 17 * FREGBYTES(sp) + FSTORE f18, 18 * FREGBYTES(sp) + FSTORE f19, 19 * FREGBYTES(sp) + FSTORE f20, 20 * FREGBYTES(sp) + FSTORE f21, 21 * FREGBYTES(sp) + FSTORE f22, 22 * FREGBYTES(sp) + FSTORE f23, 23 * FREGBYTES(sp) + FSTORE f24, 24 * FREGBYTES(sp) + FSTORE f25, 25 * FREGBYTES(sp) + FSTORE f26, 26 * FREGBYTES(sp) + FSTORE f27, 27 * FREGBYTES(sp) + FSTORE f28, 28 * FREGBYTES(sp) + FSTORE f29, 29 * FREGBYTES(sp) + FSTORE f30, 30 * FREGBYTES(sp) + FSTORE f31, 31 * FREGBYTES(sp) - STORE sp, (a0) +#endif + addi sp, sp, -32 * REGBYTES + STORE sp, (a0) - //restore to thread context - LOAD sp, (a1) + STORE x1, 0 * REGBYTES(sp) + STORE x1, 1 * REGBYTES(sp) - la s0, rt_current_thread - LOAD s1, (s0) - RESTORE_ALL - sret + csrr a0, SRC_XSTATUS +#ifdef RISCV_S_MODE + andi a0, a0, 2 + beqz a0, save_spie + li a0, 0x20 +save_spie: + STORE a0, 2 * REGBYTES(sp) +#else + andi a0, a0, 8 + beqz a0, save_mpie + li a0, 0x80 +save_mpie: + STORE a0, 2 * REGBYTES(sp) +#endif + + STORE x4, 4 * REGBYTES(sp) + STORE x5, 5 * REGBYTES(sp) + STORE x6, 6 * REGBYTES(sp) + STORE x7, 7 * REGBYTES(sp) + STORE x8, 8 * REGBYTES(sp) + STORE x9, 9 * REGBYTES(sp) + STORE x10, 10 * REGBYTES(sp) + STORE x11, 11 * REGBYTES(sp) + STORE x12, 12 * REGBYTES(sp) + STORE x13, 13 * REGBYTES(sp) + STORE x14, 14 * REGBYTES(sp) + STORE x15, 15 * REGBYTES(sp) + STORE x16, 16 * REGBYTES(sp) + STORE x17, 17 * REGBYTES(sp) + STORE x18, 18 * REGBYTES(sp) + STORE x19, 19 * REGBYTES(sp) + STORE x20, 20 * REGBYTES(sp) + STORE x21, 21 * REGBYTES(sp) + STORE x22, 22 * REGBYTES(sp) + STORE x23, 23 * REGBYTES(sp) + STORE x24, 24 * REGBYTES(sp) + STORE x25, 25 * REGBYTES(sp) + STORE x26, 26 * REGBYTES(sp) + STORE x27, 27 * REGBYTES(sp) + STORE x28, 28 * REGBYTES(sp) + STORE x29, 29 * REGBYTES(sp) + STORE x30, 30 * REGBYTES(sp) + STORE x31, 31 * REGBYTES(sp) + + /* restore to thread context + * sp(0) -> epc; + * sp(1) -> ra; + * sp(i) -> x(i+2) + */ + LOAD sp, (a1) + +#ifdef RT_USING_SMP + mv a0, a2 + call rt_cpus_lock_status_restore +#endif /*RT_USING_SMP*/ + + j rt_hw_context_switch_exit + +#ifdef RT_USING_SMP +/* + * void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread); + * + * a0 --> context + * a1 --> from + * a2 --> to + * a3 --> to_thread + */ + .globl rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: + + STORE a0, 0(a1) + + LOAD sp, 0(a2) + move a0, a3 + call rt_cpus_lock_status_restore + + j rt_hw_context_switch_exit + +#endif + +.global rt_hw_context_switch_exit +rt_hw_context_switch_exit: +#ifdef RT_USING_SMP +#ifdef RT_USING_SIGNALS + mv a0, sp + + csrr t0, mhartid + /* switch interrupt stack of current cpu */ + la sp, __stack_start__ + addi t1, t0, 1 + li t2, __STACKSIZE__ + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */ + + call rt_signal_check + mv sp, a0 +#endif +#endif + /* resw ra to mepc */ + LOAD a0, 0 * REGBYTES(sp) + csrw SRC_XEPC, a0 + + LOAD x1, 1 * REGBYTES(sp) + +#ifdef RISCV_S_MODE + li t0, 0x00000120 + csrw sstatus, t0 + LOAD a0, 2 * REGBYTES(sp) + csrs sstatus, a0 +#else + li t0, 0x00007800 + csrw mstatus, t0 + LOAD a0, 2 * REGBYTES(sp) + csrs mstatus, a0 +#endif + + LOAD x4, 4 * REGBYTES(sp) + LOAD x5, 5 * REGBYTES(sp) + LOAD x6, 6 * REGBYTES(sp) + LOAD x7, 7 * REGBYTES(sp) + LOAD x8, 8 * REGBYTES(sp) + LOAD x9, 9 * REGBYTES(sp) + LOAD x10, 10 * REGBYTES(sp) + LOAD x11, 11 * REGBYTES(sp) + LOAD x12, 12 * REGBYTES(sp) + LOAD x13, 13 * REGBYTES(sp) + LOAD x14, 14 * REGBYTES(sp) + LOAD x15, 15 * REGBYTES(sp) + LOAD x16, 16 * REGBYTES(sp) + LOAD x17, 17 * REGBYTES(sp) + LOAD x18, 18 * REGBYTES(sp) + LOAD x19, 19 * REGBYTES(sp) + LOAD x20, 20 * REGBYTES(sp) + LOAD x21, 21 * REGBYTES(sp) + LOAD x22, 22 * REGBYTES(sp) + LOAD x23, 23 * REGBYTES(sp) + LOAD x24, 24 * REGBYTES(sp) + LOAD x25, 25 * REGBYTES(sp) + LOAD x26, 26 * REGBYTES(sp) + LOAD x27, 27 * REGBYTES(sp) + LOAD x28, 28 * REGBYTES(sp) + LOAD x29, 29 * REGBYTES(sp) + LOAD x30, 30 * REGBYTES(sp) + LOAD x31, 31 * REGBYTES(sp) + + addi sp, sp, 32 * REGBYTES + +#ifdef ARCH_RISCV_FPU + FLOAD f0, 0 * FREGBYTES(sp) + FLOAD f1, 1 * FREGBYTES(sp) + FLOAD f2, 2 * FREGBYTES(sp) + FLOAD f3, 3 * FREGBYTES(sp) + FLOAD f4, 4 * FREGBYTES(sp) + FLOAD f5, 5 * FREGBYTES(sp) + FLOAD f6, 6 * FREGBYTES(sp) + FLOAD f7, 7 * FREGBYTES(sp) + FLOAD f8, 8 * FREGBYTES(sp) + FLOAD f9, 9 * FREGBYTES(sp) + FLOAD f10, 10 * FREGBYTES(sp) + FLOAD f11, 11 * FREGBYTES(sp) + FLOAD f12, 12 * FREGBYTES(sp) + FLOAD f13, 13 * FREGBYTES(sp) + FLOAD f14, 14 * FREGBYTES(sp) + FLOAD f15, 15 * FREGBYTES(sp) + FLOAD f16, 16 * FREGBYTES(sp) + FLOAD f17, 17 * FREGBYTES(sp) + FLOAD f18, 18 * FREGBYTES(sp) + FLOAD f19, 19 * FREGBYTES(sp) + FLOAD f20, 20 * FREGBYTES(sp) + FLOAD f21, 21 * FREGBYTES(sp) + FLOAD f22, 22 * FREGBYTES(sp) + FLOAD f23, 23 * FREGBYTES(sp) + FLOAD f24, 24 * FREGBYTES(sp) + FLOAD f25, 25 * FREGBYTES(sp) + FLOAD f26, 26 * FREGBYTES(sp) + FLOAD f27, 27 * FREGBYTES(sp) + FLOAD f28, 28 * FREGBYTES(sp) + FLOAD f29, 29 * FREGBYTES(sp) + FLOAD f30, 30 * FREGBYTES(sp) + FLOAD f31, 31 * FREGBYTES(sp) + + addi sp, sp, 32 * FREGBYTES +#endif + + XRET diff --git a/libcpu/risc-v/virt64/cpuport.c b/libcpu/risc-v/virt64/cpuport.c index 50929125ac..df98bfe1eb 100644 --- a/libcpu/risc-v/virt64/cpuport.c +++ b/libcpu/risc-v/virt64/cpuport.c @@ -70,8 +70,11 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, frame->epc = (rt_ubase_t)tentry; frame->user_sp_exc_stack = (rt_ubase_t)(((rt_ubase_t)stk) + sizeof(struct rt_hw_stack_frame)); - /* force to supervisor mode(SPP=1) and set SPIE and SUM to 1 */ - frame->sstatus = 0x00040120; +#ifndef RISCV_S_MODE + frame->xstatus = 0x00007880; +#else + frame->xstatus = 0x00040120; +#endif return stk; } diff --git a/libcpu/risc-v/virt64/cpuport.h b/libcpu/risc-v/virt64/cpuport.h index bb838def4a..378d8085bd 100644 --- a/libcpu/risc-v/virt64/cpuport.h +++ b/libcpu/risc-v/virt64/cpuport.h @@ -22,7 +22,34 @@ // error here, not portable #endif -#endif #ifdef RISCV_U_MODE #define RISCV_USER_ENTRY 0xFFFFFFE000000000ULL -#endif \ No newline at end of file +#endif + +#ifdef RISCV_S_MODE +//csr in s-mode +// M/U/S Interrupt Registers +#define SRC_XIE sie +#define SRC_XIP sip +#define SRC_XTVEC stvec +#define SRC_XSTATUS sstatus +#define SRC_XSCRATCH sscratch +#define SRC_XEPC sepc +#define SRC_XCAUSE scause +#define SRC_XTVAL stval +#define XRET sret +#else +//csr in m-mode +// M/U/S Interrupt Registers +#define SRC_XIE mie +#define SRC_XIP mip +#define SRC_XTVEC mtvec +#define SRC_XSTATUS mstatus +#define SRC_XSCRATCH mscratch +#define SRC_XEPC mepc +#define SRC_XCAUSE mcause +#define SRC_XTVAL mtval +#define XRET mret +#endif + +#endif diff --git a/libcpu/risc-v/virt64/interrupt.c b/libcpu/risc-v/virt64/interrupt.c new file mode 100644 index 0000000000..4280446198 --- /dev/null +++ b/libcpu/risc-v/virt64/interrupt.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/10/01 Bernard The first version + * 2018/12/27 Jesven Change irq enable/disable to cpu0 + */ +#include "tick.h" +#include +#include "encoding.h" +#include "riscv.h" +#include "interrupt.h" + +#define CPU_NUM 2 +#define MAX_HANDLERS 128 + +static struct rt_irq_desc irq_desc[MAX_HANDLERS]; + +static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param) +{ + rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector); + return RT_NULL; +} + +int rt_hw_clint_ipi_enable(void) +{ + /* Set the Machine-Software bit in MIE */ + set_csr(mie, MIP_MSIP); + return 0; +} + +int rt_hw_clint_ipi_disable(void) +{ + /* Clear the Machine-Software bit in MIE */ + clear_csr(mie, MIP_MSIP); + return 0; +} + +int rt_hw_plic_irq_enable(int irq_number) +{ + plic_irq_enable(irq_number); + return 0; +} + +int rt_hw_plic_irq_disable(int irq_number) +{ + plic_irq_disable(irq_number); + return 0; +} + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init(void) +{ + int idx = 0; + /* init exceptions table */ + for (idx = 0; idx < MAX_HANDLERS; idx++) + { + //rt_hw_interrupt_mask(idx); + irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle; + irq_desc[idx].param = RT_NULL; +#ifdef RT_USING_INTERRUPT_INFO + rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default"); + irq_desc[idx].counter = 0; +#endif + } +} + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + rt_hw_plic_irq_disable(vector); +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + plic_set_priority(vector, 1); + plic_set_threshold(0); + rt_hw_plic_irq_enable(vector); +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if(vector < MAX_HANDLERS) + { + old_handler = irq_desc[vector].handler; + if (handler != RT_NULL) + { + irq_desc[vector].handler = (rt_isr_handler_t)handler; + irq_desc[vector].param = param; +#ifdef RT_USING_INTERRUPT_INFO + rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name); + irq_desc[vector].counter = 0; +#endif + } + } + + return old_handler; +} + +RT_WEAK +void plic_irq_handle(int irq) +{ + rt_kprintf("UN-handled interrupt %d occurred!!!\n", irq); + return ; +} + +void dump_regs(struct rt_hw_stack_frame *regs) +{ + rt_kprintf("--------------Dump Registers-----------------\n"); + + rt_kprintf("Function Registers:\n"); + rt_kprintf("\tra(x1) = 0x%p\tuser_sp = 0x%p\n",regs -> ra,regs -> user_sp_exc_stack); + rt_kprintf("\tgp(x3) = 0x%p\ttp(x4) = 0x%p\n",regs -> gp,regs -> tp); + rt_kprintf("Temporary Registers:\n"); + rt_kprintf("\tt0(x5) = 0x%p\tt1(x6) = 0x%p\n",regs -> t0,regs -> t1); + rt_kprintf("\tt2(x7) = 0x%p\n",regs -> t2); + rt_kprintf("\tt3(x28) = 0x%p\tt4(x29) = 0x%p\n",regs -> t3,regs -> t4); + rt_kprintf("\tt5(x30) = 0x%p\tt6(x31) = 0x%p\n",regs -> t5,regs -> t6); + rt_kprintf("Saved Registers:\n"); + rt_kprintf("\ts0/fp(x8) = 0x%p\ts1(x9) = 0x%p\n",regs -> s0_fp,regs -> s1); + rt_kprintf("\ts2(x18) = 0x%p\ts3(x19) = 0x%p\n",regs -> s2,regs -> s3); + rt_kprintf("\ts4(x20) = 0x%p\ts5(x21) = 0x%p\n",regs -> s4,regs -> s5); + rt_kprintf("\ts6(x22) = 0x%p\ts7(x23) = 0x%p\n",regs -> s6,regs -> s7); + rt_kprintf("\ts8(x24) = 0x%p\ts9(x25) = 0x%p\n",regs -> s8,regs -> s9); + rt_kprintf("\ts10(x26) = 0x%p\ts11(x27) = 0x%p\n",regs -> s10,regs -> s11); + rt_kprintf("Function Arguments Registers:\n"); + rt_kprintf("\ta0(x10) = 0x%p\ta1(x11) = 0x%p\n",regs -> a0,regs -> a1); + rt_kprintf("\ta2(x12) = 0x%p\ta3(x13) = 0x%p\n",regs -> a2,regs -> a3); + rt_kprintf("\ta4(x14) = 0x%p\ta5(x15) = 0x%p\n",regs -> a4,regs -> a5); + rt_kprintf("\ta6(x16) = 0x%p\ta7(x17) = 0x%p\n",regs -> a6,regs -> a7); + rt_kprintf("xstatus = 0x%p\n",regs -> xstatus); + rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled"); + rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled"); + rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode"); + rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_PUM) ? "Permit to Access User Page" : "Not Permit to Access User Page"); + rt_kprintf("\t%s\n",(regs -> xstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page"); + rt_size_t satp_v = read_csr(satp); + rt_kprintf("satp = 0x%p\n",satp_v); + const char *mode_str = "Unknown Address Translation/Protection Mode"; + + switch(__MASKVALUE(satp_v >> 60,__MASK(4))) + { + case 0: + mode_str = "No Address Translation/Protection Mode"; + break; + + case 8: + mode_str = "Page-based 39-bit Virtual Addressing Mode"; + break; + + case 9: + mode_str = "Page-based 48-bit Virtual Addressing Mode"; + break; + } + + rt_kprintf("\tMode = %s\n",mode_str); + rt_kprintf("-----------------Dump OK---------------------\n"); +} + +void handle_trap(rt_size_t xcause,rt_size_t xtval,rt_size_t xepc,struct rt_hw_stack_frame *sp) +{ + int cause = (xcause & 0xFFFFFFFF); + int plic_irq = 0; + if (xcause & (1UL << 63)) + { + switch (cause) + { + case IRQ_M_SOFT: + { + + } + break; + case IRQ_M_TIMER: + tick_isr(); + break; + case IRQ_S_TIMER: + tick_isr(); + break; + case IRQ_S_EXT: + plic_irq = plic_claim(); + plic_complete(plic_irq); + irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param); + break; + case IRQ_M_EXT: + plic_irq = plic_claim(); + plic_complete(plic_irq); + irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param); + break; + } + } + else + { + rt_thread_t tid; + extern long list_thread(); + + rt_hw_interrupt_disable(); + + rt_kprintf("xcause = %08x,xtval = %08x,xepc = %08x\n", xcause, xtval, xepc); + tid = rt_thread_self(); + rt_kprintf("\nException:\n"); + switch (cause) + { + case CAUSE_MISALIGNED_FETCH: + rt_kprintf("Instruction address misaligned"); + break; + case CAUSE_FAULT_FETCH: + rt_kprintf("Instruction access fault"); + break; + case CAUSE_ILLEGAL_INSTRUCTION: + rt_kprintf("Illegal instruction"); + break; + case CAUSE_BREAKPOINT: + rt_kprintf("Breakpoint"); + break; + case CAUSE_MISALIGNED_LOAD: + rt_kprintf("Load address misaligned"); + break; + case CAUSE_FAULT_LOAD: + rt_kprintf("Load access fault"); + break; + case CAUSE_MISALIGNED_STORE: + rt_kprintf("Store address misaligned"); + break; + case CAUSE_FAULT_STORE: + rt_kprintf("Store access fault"); + break; + case CAUSE_USER_ECALL: + rt_kprintf("Environment call from U-mode"); + break; + case CAUSE_SUPERVISOR_ECALL: + rt_kprintf("Environment call from S-mode"); + break; + case CAUSE_HYPERVISOR_ECALL: + rt_kprintf("Environment call from H-mode"); + break; + case CAUSE_MACHINE_ECALL: + rt_kprintf("Environment call from M-mode"); + break; + default: + rt_kprintf("Uknown exception : %08lX", cause); + break; + } + rt_kprintf("\n"); + dump_regs(sp); + rt_kprintf("exception pc => 0x%08x\n", xepc); + rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, tid->name); +#ifdef RT_USING_FINSH + list_thread(); +#endif + while(1); + } + rt_hw_interrupt_enable(0); +} diff --git a/libcpu/risc-v/virt64/interrupt.h b/libcpu/risc-v/virt64/interrupt.h new file mode 100644 index 0000000000..01b26c78c8 --- /dev/null +++ b/libcpu/risc-v/virt64/interrupt.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-20 bigmagic The first version + */ + +#ifndef INTERRUPT_H__ +#define INTERRUPT_H__ + +#include +#include "stack.h" + +int rt_hw_clint_ipi_enable(void); +int rt_hw_clint_ipi_disable(void); +int rt_hw_plic_irq_enable(int irq_number); +int rt_hw_plic_irq_disable(int irq_number); +void rt_hw_interrupt_init(void); +void rt_hw_interrupt_mask(int vector); +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name); +void handle_trap(rt_size_t xcause,rt_size_t xtval,rt_size_t xepc,struct rt_hw_stack_frame *sp); + +#endif \ No newline at end of file diff --git a/libcpu/risc-v/virt64/interrupt_gcc.S b/libcpu/risc-v/virt64/interrupt_gcc.S index 338413866e..730fa10d61 100644 --- a/libcpu/risc-v/virt64/interrupt_gcc.S +++ b/libcpu/risc-v/virt64/interrupt_gcc.S @@ -11,31 +11,125 @@ */ #include "cpuport.h" -#include "encoding.h" -#include "stackframe.h" .section .text.entry .align 2 .global trap_entry - .extern __stack_cpu0 - .extern get_current_thread_kernel_stack_top trap_entry: - //backup sp - csrrw sp, sscratch, sp - //load interrupt stack - la sp, __stack_cpu0 - //backup context - SAVE_ALL - - RESTORE_SYS_GP +#ifdef ARCH_RISCV_FPU + addi sp, sp, -32 * FREGBYTES - csrr a0, scause - csrrc a1, stval, zero - csrr a2, sepc - mv a3, sp + FSTORE f0, 0 * FREGBYTES(sp) + FSTORE f1, 1 * FREGBYTES(sp) + FSTORE f2, 2 * FREGBYTES(sp) + FSTORE f3, 3 * FREGBYTES(sp) + FSTORE f4, 4 * FREGBYTES(sp) + FSTORE f5, 5 * FREGBYTES(sp) + FSTORE f6, 6 * FREGBYTES(sp) + FSTORE f7, 7 * FREGBYTES(sp) + FSTORE f8, 8 * FREGBYTES(sp) + FSTORE f9, 9 * FREGBYTES(sp) + FSTORE f10, 10 * FREGBYTES(sp) + FSTORE f11, 11 * FREGBYTES(sp) + FSTORE f12, 12 * FREGBYTES(sp) + FSTORE f13, 13 * FREGBYTES(sp) + FSTORE f14, 14 * FREGBYTES(sp) + FSTORE f15, 15 * FREGBYTES(sp) + FSTORE f16, 16 * FREGBYTES(sp) + FSTORE f17, 17 * FREGBYTES(sp) + FSTORE f18, 18 * FREGBYTES(sp) + FSTORE f19, 19 * FREGBYTES(sp) + FSTORE f20, 20 * FREGBYTES(sp) + FSTORE f21, 21 * FREGBYTES(sp) + FSTORE f22, 22 * FREGBYTES(sp) + FSTORE f23, 23 * FREGBYTES(sp) + FSTORE f24, 24 * FREGBYTES(sp) + FSTORE f25, 25 * FREGBYTES(sp) + FSTORE f26, 26 * FREGBYTES(sp) + FSTORE f27, 27 * FREGBYTES(sp) + FSTORE f28, 28 * FREGBYTES(sp) + FSTORE f29, 29 * FREGBYTES(sp) + FSTORE f30, 30 * FREGBYTES(sp) + FSTORE f31, 31 * FREGBYTES(sp) - /* scause, stval, sepc, sp */ +#endif + + /* save thread context to thread stack */ + addi sp, sp, -32 * REGBYTES + + STORE x1, 1 * REGBYTES(sp) + + csrr x1, SRC_XSTATUS + STORE x1, 2 * REGBYTES(sp) + + csrr x1, SRC_XEPC + STORE x1, 0 * REGBYTES(sp) + + STORE x4, 4 * REGBYTES(sp) + STORE x5, 5 * REGBYTES(sp) + STORE x6, 6 * REGBYTES(sp) + STORE x7, 7 * REGBYTES(sp) + STORE x8, 8 * REGBYTES(sp) + STORE x9, 9 * REGBYTES(sp) + STORE x10, 10 * REGBYTES(sp) + STORE x11, 11 * REGBYTES(sp) + STORE x12, 12 * REGBYTES(sp) + STORE x13, 13 * REGBYTES(sp) + STORE x14, 14 * REGBYTES(sp) + STORE x15, 15 * REGBYTES(sp) + STORE x16, 16 * REGBYTES(sp) + STORE x17, 17 * REGBYTES(sp) + STORE x18, 18 * REGBYTES(sp) + STORE x19, 19 * REGBYTES(sp) + STORE x20, 20 * REGBYTES(sp) + STORE x21, 21 * REGBYTES(sp) + STORE x22, 22 * REGBYTES(sp) + STORE x23, 23 * REGBYTES(sp) + STORE x24, 24 * REGBYTES(sp) + STORE x25, 25 * REGBYTES(sp) + STORE x26, 26 * REGBYTES(sp) + STORE x27, 27 * REGBYTES(sp) + STORE x28, 28 * REGBYTES(sp) + STORE x29, 29 * REGBYTES(sp) + STORE x30, 30 * REGBYTES(sp) + STORE x31, 31 * REGBYTES(sp) + + /* switch to interrupt stack */ + move s0, sp + +#ifndef RISCV_S_MODE + /* get cpu id */ + csrr t0, mhartid +#else + li t0, 0 +#endif + + /* switch interrupt stack of current cpu */ + la sp, __stack_start__ + addi t1, t0, 1 + li t2, __STACKSIZE__ + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */ + + /* handle interrupt */ + call rt_interrupt_enter + csrr a0, SRC_XCAUSE + csrr a1, SRC_XEPC + mv a2, s0 call handle_trap + call rt_interrupt_leave + +#ifdef RT_USING_SMP + /* s0 --> sp */ + mv sp, s0 + mv a0, s0 + call rt_scheduler_do_irq_switch + tail rt_hw_context_switch_exit + +#else + + /* switch to from_thread stack */ + move sp, s0 /* need to switch new thread */ la s0, rt_thread_switch_interrupt_flag @@ -43,41 +137,6 @@ trap_entry: beqz s2, spurious_interrupt sw zero, 0(s0) -.global rt_hw_context_switch_interrupt_do -rt_hw_context_switch_interrupt_do: - -//switch to thread kernel stack - csrr t0, sstatus - andi t0, t0, 0x100 - beqz t0, __restore_sp_from_tcb_interrupt - -__restore_sp_from_sscratch_interrupt: - csrr t0, sscratch - j __move_stack_context_interrupt - -__restore_sp_from_tcb_interrupt: - la s0, rt_interrupt_from_thread - LOAD a0, 0(s0) - jal rt_thread_sp_to_thread - jal get_thread_kernel_stack_top - mv t0, a0 - -__move_stack_context_interrupt: - mv t1, sp//src - mv sp, t0//switch stack - addi sp, sp, -33 * REGBYTES - //copy context - li s0, 33//cnt - mv t2, sp//dst - -copy_context_loop_interrupt: - LOAD t0, 0(t1) - STORE t0, 0(t2) - addi s0, s0, -1 - addi t1, t1, 8 - addi t2, t2, 8 - bnez s0, copy_context_loop_interrupt - la s0, rt_interrupt_from_thread LOAD s1, 0(s0) STORE sp, 0(s1) @@ -86,16 +145,7 @@ copy_context_loop_interrupt: LOAD s1, 0(s0) LOAD sp, 0(s1) +#endif + spurious_interrupt: - RESTORE_ALL - sret - -.global rt_hw_interrupt_enable -rt_hw_interrupt_enable: - csrs sstatus, a0 - jr ra - -.global rt_hw_interrupt_disable -rt_hw_interrupt_disable: - csrrci a0, sstatus, 2 - jr ra + tail rt_hw_context_switch_exit diff --git a/libcpu/risc-v/virt64/riscv_io.h b/libcpu/risc-v/virt64/riscv_io.h index 8363ff23f8..109f7297e5 100644 --- a/libcpu/risc-v/virt64/riscv_io.h +++ b/libcpu/risc-v/virt64/riscv_io.h @@ -10,100 +10,128 @@ #ifndef __RISCV_IO_H__ #define __RISCV_IO_H__ - static inline void __raw_writeb(rt_uint8_t val, volatile void *addr) - { - asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr)); - } +// which hart (core) is this? +static inline uint32_t r_mhartid() +{ +#ifndef RISCV_S_MODE + uint32_t x; + asm volatile("csrr %0, mhartid" : "=r" (x) ); + return x; +#else + return 0; +#endif +} - static inline void __raw_writew(rt_uint16_t val, volatile void *addr) - { - asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr)); - } +static inline void __raw_writeb(rt_uint8_t val, volatile void *addr) +{ + asm volatile("sb %0, 0(%1)" + : + : "r"(val), "r"(addr)); +} - static inline void __raw_writel(rt_uint32_t val, volatile void *addr) - { - asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr)); - } +static inline void __raw_writew(rt_uint16_t val, volatile void *addr) +{ + asm volatile("sh %0, 0(%1)" + : + : "r"(val), "r"(addr)); +} - #if __riscv_xlen != 32 - static inline void __raw_writeq(rt_uint64_t val, volatile void *addr) - { - asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr)); - } - #endif +static inline void __raw_writel(rt_uint32_t val, volatile void *addr) +{ + asm volatile("sw %0, 0(%1)" + : + : "r"(val), "r"(addr)); +} - static inline rt_uint8_t __raw_readb(const volatile void *addr) - { - rt_uint8_t val; +#if __riscv_xlen != 32 +static inline void __raw_writeq(rt_uint64_t val, volatile void *addr) +{ + asm volatile("sd %0, 0(%1)" + : + : "r"(val), "r"(addr)); +} +#endif - asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr)); - return val; - } +static inline rt_uint8_t __raw_readb(const volatile void *addr) +{ + rt_uint8_t val; - static inline rt_uint16_t __raw_readw(const volatile void *addr) - { - rt_uint16_t val; + asm volatile("lb %0, 0(%1)" + : "=r"(val) + : "r"(addr)); + return val; +} - asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr)); - return val; - } +static inline rt_uint16_t __raw_readw(const volatile void *addr) +{ + rt_uint16_t val; - static inline rt_uint32_t __raw_readl(const volatile void *addr) - { - rt_uint32_t val; + asm volatile("lh %0, 0(%1)" + : "=r"(val) + : "r"(addr)); + return val; +} - asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr)); - return val; - } +static inline rt_uint32_t __raw_readl(const volatile void *addr) +{ + rt_uint32_t val; - #if __riscv_xlen != 32 - static inline rt_uint64_t __raw_readq(const volatile void *addr) - { - rt_uint64_t val; + asm volatile("lw %0, 0(%1)" + : "=r"(val) + : "r"(addr)); + return val; +} - asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr)); - return val; - } - #endif +#if __riscv_xlen != 32 +static inline rt_uint64_t __raw_readq(const volatile void *addr) +{ + rt_uint64_t val; - /* FIXME: These are now the same as asm-generic */ + asm volatile("ld %0, 0(%1)" + : "=r"(val) + : "r"(addr)); + return val; +} +#endif - /* clang-format off */ +/* FIXME: These are now the same as asm-generic */ - #define __io_rbr() do {} while (0) - #define __io_rar() do {} while (0) - #define __io_rbw() do {} while (0) - #define __io_raw() do {} while (0) +/* clang-format off */ - #define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; }) - #define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; }) - #define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; }) +#define __io_rbr() do {} while (0) +#define __io_rar() do {} while (0) +#define __io_rbw() do {} while (0) +#define __io_raw() do {} while (0) - #define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); }) - #define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); }) - #define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); }) +#define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; }) +#define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; }) +#define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; }) - #if __riscv_xlen != 32 - #define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; }) - #define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); }) - #endif +#define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); }) +#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); }) +#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); }) - #define __io_br() do {} while (0) - #define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory"); - #define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory"); - #define __io_aw() do {} while (0) +#if __riscv_xlen != 32 +#define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; }) +#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); }) +#endif - #define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; }) - #define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; }) - #define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; }) +#define __io_br() do {} while (0) +#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory"); +#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory"); +#define __io_aw() do {} while (0) - #define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); }) - #define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); }) - #define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); }) +#define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; }) +#define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; }) +#define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; }) - #if __riscv_xlen != 32 - #define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; }) - #define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); }) - #endif +#define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); }) +#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); }) +#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); }) + +#if __riscv_xlen != 32 +#define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; }) +#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); }) +#endif #endif \ No newline at end of file diff --git a/libcpu/risc-v/virt64/stack.h b/libcpu/risc-v/virt64/stack.h index 27e9cdf9fa..09179238ea 100644 --- a/libcpu/risc-v/virt64/stack.h +++ b/libcpu/risc-v/virt64/stack.h @@ -16,7 +16,7 @@ struct rt_hw_stack_frame { rt_ubase_t epc; /* epc - epc - program counter */ rt_ubase_t ra; /* x1 - ra - return address for jumps */ - rt_ubase_t sstatus; /* - supervisor status register */ + rt_ubase_t xstatus; /* - supervisor/machine/user status register */ rt_ubase_t gp; /* x3 - gp - global pointer */ rt_ubase_t tp; /* x4 - tp - thread pointer */ rt_ubase_t t0; /* x5 - t0 - temporary register 0 */ diff --git a/libcpu/risc-v/virt64/stackframe.h b/libcpu/risc-v/virt64/stackframe.h index e5a5271a7a..835f03ee3a 100644 --- a/libcpu/risc-v/virt64/stackframe.h +++ b/libcpu/risc-v/virt64/stackframe.h @@ -19,10 +19,10 @@ STORE x1, 1 * REGBYTES(sp) - csrr x1, sstatus + csrr x1, SRC_XSTATUS STORE x1, 2 * REGBYTES(sp) - csrr x1, sepc + csrr x1, SRC_XEPC STORE x1, 0 * REGBYTES(sp) STORE x3, 3 * REGBYTES(sp) @@ -54,17 +54,17 @@ STORE x29, 29 * REGBYTES(sp) STORE x30, 30 * REGBYTES(sp) STORE x31, 31 * REGBYTES(sp) - csrr t0, sscratch + csrr t0, SRC_XSCRATCH STORE t0, 32 * REGBYTES(sp) .endm .macro RESTORE_ALL_ONLY /* resw ra to sepc */ LOAD x1, 0 * REGBYTES(sp) - csrw sepc, x1 + csrw SRC_XEPC, x1 LOAD x1, 2 * REGBYTES(sp) - csrw sstatus, x1 + csrw SRC_XSTATUS, x1 LOAD x1, 1 * REGBYTES(sp) @@ -104,10 +104,10 @@ .macro RESTORE_ALL /* resw ra to sepc */ LOAD x1, 0 * REGBYTES(sp) - csrw sepc, x1 + csrw SRC_XEPC, x1 LOAD x1, 2 * REGBYTES(sp) - csrw sstatus, x1 + csrw SRC_XSTATUS, x1 LOAD x1, 1 * REGBYTES(sp) @@ -152,12 +152,4 @@ .option pop .endm -.macro OPEN_INTERRUPT - csrsi sstatus, 2 -.endm - -.macro CLOSE_INTERRUPT - csrci sstatus, 2 -.endm - #endif \ No newline at end of file diff --git a/libcpu/risc-v/virt64/startup_gcc.S b/libcpu/risc-v/virt64/startup_gcc.S index 9b1a27be9a..ac980f6ed2 100644 --- a/libcpu/risc-v/virt64/startup_gcc.S +++ b/libcpu/risc-v/virt64/startup_gcc.S @@ -10,71 +10,48 @@ * 2020/6/12 Xim Port to QEMU and remove SMP support */ -#define SSTATUS_FS 0x00006000U /* initial state of FPU, clear to disable */ +#define XSTATUS_FS (3 << 13) /* initial state of FPU, clear to disable */ +#define XSTATUS_PUM (1 << 18) #include .global _start .section ".start", "ax" _start: - j 1f - .word 0xdeadbeef - .align 3 - .global g_wake_up - g_wake_up: - .dword 1 - .dword 0 -1: - csrw sie, 0 - csrw sip, 0 - la t0, trap_entry - csrw stvec, t0 +#ifndef RISCV_S_MODE + # setup stacks per hart + csrr t0, mhartid # read current hart id + slli t0, t0, 10 # shift left the hart id by 1024 - li x1, 0 - li x2, 0 - li x3, 0 - li x4, 0 - li x5, 0 - li x6, 0 - li x7, 0 - li x8, 0 - li x9, 0 - li x10,0 - li x11,0 - li x12,0 - li x13,0 - li x14,0 - li x15,0 - li x16,0 - li x17,0 - li x18,0 - li x19,0 - li x20,0 - li x21,0 - li x22,0 - li x23,0 - li x24,0 - li x25,0 - li x26,0 - li x27,0 - li x28,0 - li x29,0 - li x30,0 - li x31,0 + # park harts with id != 0 + csrr a0, mhartid # read current hart id + bnez a0, park # if we're not on the hart 0 +#endif + + csrw SRC_XIE, 0 # clear Interrupt Registers + csrw SRC_XIP, 0 + + la t0, trap_entry + csrw SRC_XTVEC, t0 # set Trap Vector Base Address Register /* set to disable FPU */ - li t0, SSTATUS_FS - csrc sstatus, t0 - li t0, 0x40000 // SUM in sstatus - csrs sstatus, t0 + li t0, XSTATUS_FS # close fpu + csrc SRC_XSTATUS, t0 +#ifdef RISCV_S_MODE + li t0, XSTATUS_PUM # PUM has no effect + csrs SRC_XSTATUS, t0 +#endif .option push .option norelax la gp, __global_pointer$ .option pop - // removed SMP support here la sp, __stack_start__ li t0, __STACKSIZE__ add sp, sp, t0 - csrw sscratch, sp + csrw SRC_XSCRATCH, sp j primary_cpu_entry + +park: + wfi + j park \ No newline at end of file diff --git a/libcpu/risc-v/virt64/tick.c b/libcpu/risc-v/virt64/tick.c index 4f340c544f..9647751b46 100644 --- a/libcpu/risc-v/virt64/tick.c +++ b/libcpu/risc-v/virt64/tick.c @@ -11,8 +11,12 @@ #include #include -#include #include "sbi.h" +#include "tick.h" +#include +#include + +#define VIRT_CLINT_TIMEBASE_FREQ (10000000) static volatile uint64_t time_elapsed = 0; static volatile unsigned long tick_cycles = 0; @@ -27,11 +31,14 @@ static uint64_t get_ticks() int tick_isr(void) { - // uint64_t core_id = current_coreid(); - int tick_cycles = 40000; - // clint->mtimecmp[core_id] += tick_cycles; + int tick_cycles = VIRT_CLINT_TIMEBASE_FREQ / RT_TICK_PER_SECOND; rt_tick_increase(); +#ifdef RISCV_S_MODE sbi_set_timer(get_ticks() + tick_cycles); +#else + int id = r_mhartid(); + *(uint64_t*)CLINT_MTIMECMP(id) = *(uint64_t*)CLINT_MTIME + tick_cycles; +#endif return 0; } @@ -39,10 +46,9 @@ int tick_isr(void) /* Sets and enable the timer interrupt */ int rt_hw_tick_init(void) { - /* Read core id */ - // unsigned long core_id = current_coreid(); - unsigned long interval = 1000/RT_TICK_PER_SECOND; + unsigned long interval = VIRT_CLINT_TIMEBASE_FREQ / RT_TICK_PER_SECOND; +#ifdef RISCV_S_MODE /* Clear the Supervisor-Timer bit in SIE */ clear_csr(sie, SIP_STIP); @@ -51,9 +57,15 @@ int rt_hw_tick_init(void) tick_cycles = 40000; /* Set timer */ sbi_set_timer(get_ticks() + tick_cycles); - + /* Enable the Supervisor-Timer bit in SIE */ set_csr(sie, SIP_STIP); - +#else + clear_csr(mie, MIP_MTIP); + clear_csr(mip, MIP_MTIP); + int id = r_mhartid(); + *(uint64_t*)CLINT_MTIMECMP(id) = *(uint64_t*)CLINT_MTIME + interval; + set_csr(mie, MIP_MTIP); +#endif return 0; } diff --git a/libcpu/risc-v/virt64/tick.h b/libcpu/risc-v/virt64/tick.h index 0821004263..1168e611e6 100644 --- a/libcpu/risc-v/virt64/tick.h +++ b/libcpu/risc-v/virt64/tick.h @@ -11,6 +11,11 @@ #ifndef TICK_H__ #define TICK_H__ +//ask the CLINT for a timer interrupt. +#define CLINT (0x2000000L) +#define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 4*(hartid)) +#define CLINT_MTIME (CLINT + 0xBFF8) // cycles since boot. + int tick_isr(void); int rt_hw_tick_init(void); From a5503a4a7127515032c0b3ecaaedaf49ee76dad4 Mon Sep 17 00:00:00 2001 From: bigmagic Date: Fri, 21 May 2021 17:47:43 +0800 Subject: [PATCH 097/255] add rv64 virt readme --- bsp/qemu-riscv-virt64/README.md | 136 ++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 bsp/qemu-riscv-virt64/README.md diff --git a/bsp/qemu-riscv-virt64/README.md b/bsp/qemu-riscv-virt64/README.md new file mode 100644 index 0000000000..01e1fa6444 --- /dev/null +++ b/bsp/qemu-riscv-virt64/README.md @@ -0,0 +1,136 @@ +# QEMU/RISCV64 VIRT板级支持包说明 + +## 1. 简介 + +RISC-V是一种开放和免费的指令集体系结构(ISA)。本工程是在QEMU的RISCV64 VIRT版本上进行的一份移植。 + +## 2. 编译说明 + +首先可以下载交叉编译工具链,建议采用sifive的工具链进行编译。 +``` +https://www.sifive.com/software +``` +选择对应的平台即可。 + +这里推荐在Ubuntu上进行开发工作。 + +解压工具链到指定的目录。 + +``` +export RTT_EXEC_PATH=~/gcc/bin +``` + +进入到`rt-thread/bsp/qemu-riscv-virt64`目录进行输入 +``` +scons +``` +可以看到正常生成`rtthread.elf`与`rtthread.bin`文件。 + +## 3. 执行 + +本工程提供了riscv64的两种可配置运行模式,默认运行在M-Mode下。 + +*M-Mode* + +首先安装`qemu-system-riscv64`。 + +``` +sudo apt install qemu-system-misc +``` +直接输入 +``` +./qemu-nographic.sh +``` +可以看到程序运行 + +``` +heap: [0x80035804 - 0x86435804] + + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build May 21 2021 + 2006 - 2021 Copyright by rt-thread team +Hello RISC-V! +msh /> +``` + +*S-Mode* + +如果运行在S-Mode下,那么需要通过menuconfig选择配置 + +``` +scons --menuconfig +``` +选择如下: +``` +RISCV qemu virt64 configs ---> + [*] RT-Thread run in riscv smode +``` +保存后,重新`scons`编译即可。 + +要让rt-thread运行在S-Mode,首先需要启动opensbi,然后通过opensbi启动rt-thread。 + +自行编译的qemu或者下载的高版本的qemu内置opensbi,执行`./qemu-nographic-smode.sh`即可正常运行。 + +通过`sudo apt install qemu-system-misc`安装的qemu版本较低,可自行编译opensbi。 + +``` +git clone git@github.com:riscv/opensbi.git +cd opensbi +make PLATFORM=generic CROSS_COMPILE=~/gcc/bin/riscv64-unknown-elf- +``` +最后生成的`/build/platform/generic/firmware/fw_jump.elf`则是需要的文件。 + +输入以下的命令即可运行: + +``` +qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin -bios ~/opensbi/build/platform/generic/firmware/fw_jump.elf +``` +可以看到如下的结果 +``` +OpenSBI v0.9 + ____ _____ ____ _____ + / __ \ / ____| _ \_ _| + | | | |_ __ ___ _ __ | (___ | |_) || | + | | | | '_ \ / _ \ '_ \ \___ \| _ < | | + | |__| | |_) | __/ | | |____) | |_) || |_ + \____/| .__/ \___|_| |_|_____/|____/_____| + | | + |_| + +Platform Name : riscv-virtio,qemu +Platform Features : timer,mfdeleg +. +. +. +Boot HART ISA : rv64imafdcsu +Boot HART Features : scounteren,mcounteren +Boot HART PMP Count : 16 +Boot HART PMP Granularity : 4 +Boot HART PMP Address Bits: 54 +Boot HART MHPM Count : 0 +Boot HART MHPM Count : 0 +Boot HART MIDELEG : 0x0000000000000222 +Boot HART MEDELEG : 0x000000000000b109 +heap: [0x80235a58 - 0x86635a58] + + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build May 21 2021 + 2006 - 2021 Copyright by rt-thread team +Hello RISC-V! +msh /> +``` +## 4. 支持情况 + +| 驱动 | 支持情况 | 备注 | +| ------ | ---- | :------: | +| UART | 支持 | UART0 | +| PLIC | 支持 | - | +| CLIC | 支持 | - | + +## 5. 联系人信息 + +维护人:[bernard][1] + +[1]: https://github.com/BernardXiong From 14c29063e83d0006399a41a73e56d5b36557af49 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Fri, 21 May 2021 17:50:57 +0800 Subject: [PATCH 098/255] =?UTF-8?q?[devfs]=20=5Fdevice=5Ffs=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/dfs/filesystems/devfs/devfs.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/components/dfs/filesystems/devfs/devfs.c b/components/dfs/filesystems/devfs/devfs.c index 2e2248d5cc..d615482452 100644 --- a/components/dfs/filesystems/devfs/devfs.c +++ b/components/dfs/filesystems/devfs/devfs.c @@ -313,15 +313,13 @@ static const struct dfs_filesystem_ops _device_fs = "devfs", DFS_FS_FLAG_DEFAULT, &_device_fops, - dfs_device_fs_mount, - RT_NULL, - RT_NULL, - RT_NULL, - - RT_NULL, + RT_NULL, /*unmount*/ + RT_NULL, /*mkfs*/ + RT_NULL, /*statfs*/ + RT_NULL, /*unlink*/ dfs_device_fs_stat, - RT_NULL, + RT_NULL, /*rename*/ }; int devfs_init(void) From 8676fd966ea3da8408e088fec39e8756ec3edf7e Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Fri, 21 May 2021 18:02:43 +0800 Subject: [PATCH 099/255] =?UTF-8?q?[dfs]=20=E5=B0=86=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E9=BB=98=E8=AE=A4=E6=9C=80=E5=A4=A7=E6=95=B0?= =?UTF-8?q?=E9=87=8F=E4=BB=A5=E5=8F=8A=E6=9C=80=E5=A4=A7=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=94=B9=E4=B8=BA4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/dfs/Kconfig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/components/dfs/Kconfig b/components/dfs/Kconfig index 39eca3c507..442c3bb260 100644 --- a/components/dfs/Kconfig +++ b/components/dfs/Kconfig @@ -14,13 +14,11 @@ if RT_USING_DFS config DFS_FILESYSTEMS_MAX int "The maximal number of mounted file system" - default 4 if RT_USING_DFS_NFS - default 2 + default 4 config DFS_FILESYSTEM_TYPES_MAX int "The maximal number of file system type" - default 4 if RT_USING_DFS_NFS - default 2 + default 4 config DFS_FD_MAX int "The maximal number of opened files" From d6f5fbcd5b4418c9762b957e9489b5dadb7bd13b Mon Sep 17 00:00:00 2001 From: bigmagic123 <57786250+bigmagic123@users.noreply.github.com> Date: Fri, 21 May 2021 18:39:41 +0800 Subject: [PATCH 100/255] format code --- bsp/qemu-riscv-virt64/driver/board.c | 4 +- bsp/qemu-riscv-virt64/driver/board.h | 2 +- bsp/qemu-riscv-virt64/driver/drv_uart.c | 6 +-- bsp/qemu-riscv-virt64/driver/io.h | 2 +- bsp/qemu-riscv-virt64/driver/plic.c | 36 +++++++++--------- bsp/qemu-riscv-virt64/driver/plic.h | 4 +- libcpu/risc-v/virt64/context_gcc.S | 1 - libcpu/risc-v/virt64/cpuport.c | 6 +-- libcpu/risc-v/virt64/cpuport.h | 2 +- libcpu/risc-v/virt64/interrupt.c | 4 +- libcpu/risc-v/virt64/interrupt.h | 2 +- libcpu/risc-v/virt64/riscv.h | 2 +- libcpu/risc-v/virt64/riscv_io.h | 50 ++++++++++++------------- libcpu/risc-v/virt64/stackframe.h | 2 +- libcpu/risc-v/virt64/tick.c | 10 ++--- libcpu/risc-v/virt64/tick.h | 2 +- 16 files changed, 65 insertions(+), 70 deletions(-) diff --git a/bsp/qemu-riscv-virt64/driver/board.c b/bsp/qemu-riscv-virt64/driver/board.c index 1e567ea151..91e8f25982 100644 --- a/bsp/qemu-riscv-virt64/driver/board.c +++ b/bsp/qemu-riscv-virt64/driver/board.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -55,7 +55,7 @@ void rt_hw_board_init(void) #endif /* RT_USING_CONSOLE */ rt_hw_tick_init(); rt_kprintf("heap: [0x%08x - 0x%08x]\n", (rt_ubase_t) RT_HW_HEAP_BEGIN, (rt_ubase_t) RT_HW_HEAP_END); - + #ifdef RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif diff --git a/bsp/qemu-riscv-virt64/driver/board.h b/bsp/qemu-riscv-virt64/driver/board.h index 3193346508..3445852e40 100644 --- a/bsp/qemu-riscv-virt64/driver/board.h +++ b/bsp/qemu-riscv-virt64/driver/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/bsp/qemu-riscv-virt64/driver/drv_uart.c b/bsp/qemu-riscv-virt64/driver/drv_uart.c index f6ee2e1c7f..c84ae6df7d 100644 --- a/bsp/qemu-riscv-virt64/driver/drv_uart.c +++ b/bsp/qemu-riscv-virt64/driver/drv_uart.c @@ -84,7 +84,7 @@ static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg } static int drv_uart_putc(struct rt_serial_device *serial, char c) -{ +{ while ((uart_read_reg(LSR) & LSR_TX_IDLE) == 0); return uart_write_reg(THR, c); } @@ -143,9 +143,9 @@ int rt_hw_uart_init(void) RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, "uart"); - + rt_hw_interrupt_umask(uart->irqno); } - + return 0; } diff --git a/bsp/qemu-riscv-virt64/driver/io.h b/bsp/qemu-riscv-virt64/driver/io.h index 8915b55306..1285d5955b 100644 --- a/bsp/qemu-riscv-virt64/driver/io.h +++ b/bsp/qemu-riscv-virt64/driver/io.h @@ -49,4 +49,4 @@ static inline uint32_t read_reg( return readl(addr + offset); } -#endif // ARCH_IO_H \ No newline at end of file +#endif // ARCH_IO_H diff --git a/bsp/qemu-riscv-virt64/driver/plic.c b/bsp/qemu-riscv-virt64/driver/plic.c index afd186933d..f502bc9da0 100644 --- a/bsp/qemu-riscv-virt64/driver/plic.c +++ b/bsp/qemu-riscv-virt64/driver/plic.c @@ -13,14 +13,14 @@ #include "encoding.h" /* -* Each PLIC interrupt source can be assigned a priority by writing +* Each PLIC interrupt source can be assigned a priority by writing * to its 32-bit memory-mapped priority register. -* The QEMU-virt (the same as FU540-C000) supports 7 levels of priority. -* A priority value of 0 is reserved to mean "never interrupt" and -* effectively disables the interrupt. -* Priority 1 is the lowest active priority, and priority 7 is the highest. -* Ties between global interrupts of the same priority are broken by -* the Interrupt ID; interrupts with the lowest ID have the highest +* The QEMU-virt (the same as FU540-C000) supports 7 levels of priority. +* A priority value of 0 is reserved to mean "never interrupt" and +* effectively disables the interrupt. +* Priority 1 is the lowest active priority, and priority 7 is the highest. +* Ties between global interrupts of the same priority are broken by +* the Interrupt ID; interrupts with the lowest ID have the highest * effective priority. */ void plic_set_priority(int irq, int priority) @@ -29,7 +29,7 @@ void plic_set_priority(int irq, int priority) } /* -* Each global interrupt can be enabled by setting the corresponding +* Each global interrupt can be enabled by setting the corresponding * bit in the enables registers. */ void plic_irq_enable(int irq) @@ -49,7 +49,7 @@ void plic_irq_disable(int irq) *(uint32_t*)PLIC_ENABLE(hart) = (((*(uint32_t*)PLIC_ENABLE(hart)) & (~(1 << irq)))); } -/* +/* * PLIC will mask all interrupts of a priority less than or equal to threshold. * Maximum threshold is 7. * For example, a threshold value of zero permits all interrupts with @@ -62,16 +62,16 @@ void plic_set_threshold(int threshold) *(uint32_t*)PLIC_THRESHOLD(hart) = threshold; } -/* +/* * DESCRIPTION: * Query the PLIC what interrupt we should serve. * Perform an interrupt claim by reading the claim register, which - * returns the ID of the highest-priority pending interrupt or zero if there - * is no pending interrupt. + * returns the ID of the highest-priority pending interrupt or zero if there + * is no pending interrupt. * A successful claim also atomically clears the corresponding pending bit * on the interrupt source. * RETURN VALUE: - * the ID of the highest-priority pending interrupt or zero if there + * the ID of the highest-priority pending interrupt or zero if there * is no pending interrupt. */ int plic_claim(void) @@ -81,12 +81,12 @@ int plic_claim(void) return irq; } -/* +/* * DESCRIPTION: - * Writing the interrupt ID it received from the claim (irq) to the - * complete register would signal the PLIC we've served this IRQ. - * The PLIC does not check whether the completion ID is the same as the - * last claim ID for that target. If the completion ID does not match an + * Writing the interrupt ID it received from the claim (irq) to the + * complete register would signal the PLIC we've served this IRQ. + * The PLIC does not check whether the completion ID is the same as the + * last claim ID for that target. If the completion ID does not match an * interrupt source that is currently enabled for the target, the completion * is silently ignored. * RETURN VALUE: none diff --git a/bsp/qemu-riscv-virt64/driver/plic.h b/bsp/qemu-riscv-virt64/driver/plic.h index 79af90cbfb..5d0fea6eb2 100644 --- a/bsp/qemu-riscv-virt64/driver/plic.h +++ b/bsp/qemu-riscv-virt64/driver/plic.h @@ -15,7 +15,7 @@ /* * This machine puts platform-level interrupt controller (PLIC) here. * Here only list PLIC registers in Machine mode. - * + * */ #define VIRT_PLIC_BASE 0x0c000000L @@ -49,8 +49,6 @@ #define PLIC_PRIORITY(id) (VIRT_PLIC_BASE + PLIC_PRIORITY_OFFSET + (id) * 4) #define PLIC_PENDING(id) (VIRT_PLIC_BASE + PLIC_PENDING_OFFSET + ((id) / 32)) - - void plic_set_priority(int irq, int priority); void plic_irq_enable(int irq); void plic_irq_disable(int irq); diff --git a/libcpu/risc-v/virt64/context_gcc.S b/libcpu/risc-v/virt64/context_gcc.S index 620559a8d0..40803148df 100644 --- a/libcpu/risc-v/virt64/context_gcc.S +++ b/libcpu/risc-v/virt64/context_gcc.S @@ -28,7 +28,6 @@ rt_hw_interrupt_disable: #endif ret - /* * void rt_hw_interrupt_enable(rt_base_t level); */ diff --git a/libcpu/risc-v/virt64/cpuport.c b/libcpu/risc-v/virt64/cpuport.c index df98bfe1eb..33cab19488 100644 --- a/libcpu/risc-v/virt64/cpuport.c +++ b/libcpu/risc-v/virt64/cpuport.c @@ -18,17 +18,17 @@ /** * @brief from thread used interrupt context switch - * + * */ volatile rt_ubase_t rt_interrupt_from_thread = 0; /** * @brief to thread used interrupt context switch - * + * */ volatile rt_ubase_t rt_interrupt_to_thread = 0; /** * @brief flag to indicate context switch in interrupt or not - * + * */ volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0; diff --git a/libcpu/risc-v/virt64/cpuport.h b/libcpu/risc-v/virt64/cpuport.h index 378d8085bd..fa0776b509 100644 --- a/libcpu/risc-v/virt64/cpuport.h +++ b/libcpu/risc-v/virt64/cpuport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/libcpu/risc-v/virt64/interrupt.c b/libcpu/risc-v/virt64/interrupt.c index 4280446198..7916be8f6f 100644 --- a/libcpu/risc-v/virt64/interrupt.c +++ b/libcpu/risc-v/virt64/interrupt.c @@ -158,7 +158,7 @@ void dump_regs(struct rt_hw_stack_frame *regs) rt_size_t satp_v = read_csr(satp); rt_kprintf("satp = 0x%p\n",satp_v); const char *mode_str = "Unknown Address Translation/Protection Mode"; - + switch(__MASKVALUE(satp_v >> 60,__MASK(4))) { case 0: @@ -188,7 +188,7 @@ void handle_trap(rt_size_t xcause,rt_size_t xtval,rt_size_t xepc,struct rt_hw_st { case IRQ_M_SOFT: { - + } break; case IRQ_M_TIMER: diff --git a/libcpu/risc-v/virt64/interrupt.h b/libcpu/risc-v/virt64/interrupt.h index 01b26c78c8..e49f0215bf 100644 --- a/libcpu/risc-v/virt64/interrupt.h +++ b/libcpu/risc-v/virt64/interrupt.h @@ -24,4 +24,4 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name); void handle_trap(rt_size_t xcause,rt_size_t xtval,rt_size_t xepc,struct rt_hw_stack_frame *sp); -#endif \ No newline at end of file +#endif diff --git a/libcpu/risc-v/virt64/riscv.h b/libcpu/risc-v/virt64/riscv.h index 04ac4fea74..d0c0cc4b38 100644 --- a/libcpu/risc-v/virt64/riscv.h +++ b/libcpu/risc-v/virt64/riscv.h @@ -26,4 +26,4 @@ #define __ALIGNUP(value,bit) (((value) + __MASK(bit)) & __UMASK(bit)) #define __ALIGNDOWN(value,bit) ((value) & __UMASK(bit)) -#endif \ No newline at end of file +#endif diff --git a/libcpu/risc-v/virt64/riscv_io.h b/libcpu/risc-v/virt64/riscv_io.h index 109f7297e5..391d7f5a41 100644 --- a/libcpu/risc-v/virt64/riscv_io.h +++ b/libcpu/risc-v/virt64/riscv_io.h @@ -98,40 +98,40 @@ static inline rt_uint64_t __raw_readq(const volatile void *addr) /* clang-format off */ -#define __io_rbr() do {} while (0) -#define __io_rar() do {} while (0) -#define __io_rbw() do {} while (0) -#define __io_raw() do {} while (0) +#define __io_rbr() do {} while (0) +#define __io_rar() do {} while (0) +#define __io_rbw() do {} while (0) +#define __io_raw() do {} while (0) -#define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; }) -#define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; }) -#define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; }) +#define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; }) +#define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; }) +#define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; }) -#define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); }) -#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); }) -#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); }) +#define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); }) +#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); }) +#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); }) #if __riscv_xlen != 32 -#define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; }) -#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); }) +#define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; }) +#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); }) #endif -#define __io_br() do {} while (0) -#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory"); -#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory"); -#define __io_aw() do {} while (0) +#define __io_br() do {} while (0) +#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory"); +#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory"); +#define __io_aw() do {} while (0) -#define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; }) -#define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; }) -#define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; }) +#define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; }) +#define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; }) +#define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; }) -#define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); }) -#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); }) -#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); }) +#define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); }) +#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); }) +#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); }) #if __riscv_xlen != 32 -#define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; }) -#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); }) +#define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; }) +#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); }) #endif -#endif \ No newline at end of file +#endif diff --git a/libcpu/risc-v/virt64/stackframe.h b/libcpu/risc-v/virt64/stackframe.h index 835f03ee3a..eb4e4f9d86 100644 --- a/libcpu/risc-v/virt64/stackframe.h +++ b/libcpu/risc-v/virt64/stackframe.h @@ -152,4 +152,4 @@ .option pop .endm -#endif \ No newline at end of file +#endif diff --git a/libcpu/risc-v/virt64/tick.c b/libcpu/risc-v/virt64/tick.c index 9647751b46..d6970ec417 100644 --- a/libcpu/risc-v/virt64/tick.c +++ b/libcpu/risc-v/virt64/tick.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -36,8 +36,7 @@ int tick_isr(void) #ifdef RISCV_S_MODE sbi_set_timer(get_ticks() + tick_cycles); #else - int id = r_mhartid(); - *(uint64_t*)CLINT_MTIMECMP(id) = *(uint64_t*)CLINT_MTIME + tick_cycles; + *(uint64_t*)CLINT_MTIMECMP(r_mhartid()) = *(uint64_t*)CLINT_MTIME + tick_cycles; #endif return 0; @@ -57,14 +56,13 @@ int rt_hw_tick_init(void) tick_cycles = 40000; /* Set timer */ sbi_set_timer(get_ticks() + tick_cycles); - + /* Enable the Supervisor-Timer bit in SIE */ set_csr(sie, SIP_STIP); #else clear_csr(mie, MIP_MTIP); clear_csr(mip, MIP_MTIP); - int id = r_mhartid(); - *(uint64_t*)CLINT_MTIMECMP(id) = *(uint64_t*)CLINT_MTIME + interval; + *(uint64_t*)CLINT_MTIMECMP(r_mhartid()) = *(uint64_t*)CLINT_MTIME + interval; set_csr(mie, MIP_MTIP); #endif return 0; diff --git a/libcpu/risc-v/virt64/tick.h b/libcpu/risc-v/virt64/tick.h index 1168e611e6..c5a55cf16f 100644 --- a/libcpu/risc-v/virt64/tick.h +++ b/libcpu/risc-v/virt64/tick.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * From a5f7635f31b237ad8ce09610ee76a75f4072e7d4 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 22 May 2021 02:50:35 +0800 Subject: [PATCH 101/255] remove libc_errno.h & libc_limits.h --- components/dfs/include/dfs_fs.h | 2 +- .../compilers/common/none-gcc/sys/errno.h | 21 ++++++---------- components/libc/compilers/common/time.c | 1 + components/libc/getline/posix_getline.c | 6 ++--- components/libc/pthreads/posix_types.h | 2 +- components/libc/termios/posix_termios.c | 2 +- .../net/lwip-1.4.1/src/arch/include/arch/cc.h | 2 +- .../net/lwip-2.0.2/src/arch/include/arch/cc.h | 2 +- components/net/lwip-2.0.2/src/lwipopts.h | 2 ++ .../net/lwip-2.1.2/src/arch/include/arch/cc.h | 2 +- .../net/lwip-2.1.2/src/include/lwip/errno.h | 2 +- components/net/lwip-2.1.2/src/lwipopts.h | 1 + .../net/sal_socket/socket/net_sockets.c | 2 +- examples/libc/ex3.c | 2 +- examples/libc/ex6.c | 2 +- examples/libc/ex7.c | 2 +- examples/libc/file.c | 2 +- examples/libc/memory.c | 2 +- include/libc/libc_limits.h | 25 ------------------- include/rtlibc.h | 2 -- 20 files changed, 27 insertions(+), 57 deletions(-) rename include/libc/libc_errno.h => components/libc/compilers/common/none-gcc/sys/errno.h (94%) delete mode 100644 include/libc/libc_limits.h diff --git a/components/dfs/include/dfs_fs.h b/components/dfs/include/dfs_fs.h index 828f15a0f5..3d194515df 100644 --- a/components/dfs/include/dfs_fs.h +++ b/components/dfs/include/dfs_fs.h @@ -15,7 +15,7 @@ #ifdef RT_USING_LIBC #include #endif - +#include #ifdef __cplusplus extern "C" { #endif diff --git a/include/libc/libc_errno.h b/components/libc/compilers/common/none-gcc/sys/errno.h similarity index 94% rename from include/libc/libc_errno.h rename to components/libc/compilers/common/none-gcc/sys/errno.h index 30d6092e33..bdc3a3c9da 100644 --- a/include/libc/libc_errno.h +++ b/components/libc/compilers/common/none-gcc/sys/errno.h @@ -5,18 +5,10 @@ * * Change Logs: * Date Author Notes - * 2016-11-12 Bernard The first version + * 2021-05-22 Meco Man The first version. */ - -#ifndef LIBC_ERRNO_H__ -#define LIBC_ERRNO_H__ - -#include - -#if defined(RT_USING_NEWLIB) || defined(_WIN32) || (defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) -/* use errno.h file in toolchains */ -#include -#endif +#ifndef _SYS_ERRNO_H +#define _SYS_ERRNO_H #if defined(__CC_ARM) /* @@ -29,6 +21,7 @@ defined in armcc/errno.h #define EINVAL 5 #define ENOMEM 6 */ + #define ERROR_BASE_NO 7 #elif defined(__IAR_SYSTEMS_ICC__) @@ -41,11 +34,12 @@ defined in armcc/errno.h #define ERROR_BASE_NO 36 #else - #define ERROR_BASE_NO 0 #endif -#if !defined(RT_USING_NEWLIB) && !defined(_WIN32) && !(defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) +#if !defined(_WIN32) + +#include #define EPERM (ERROR_BASE_NO + 1) #define ENOENT (ERROR_BASE_NO + 2) @@ -200,7 +194,6 @@ defined in armcc/errno.h #define ENOTRECOVERABLE (ERROR_BASE_NO + 131) #define ERFKILL (ERROR_BASE_NO + 132) #define EHWPOISON (ERROR_BASE_NO + 133) - #endif #endif diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c index 9996212444..4cdfe77343 100644 --- a/components/libc/compilers/common/time.c +++ b/components/libc/compilers/common/time.c @@ -21,6 +21,7 @@ */ #include "sys/time.h" +#include #include #ifdef RT_USING_DEVICE diff --git a/components/libc/getline/posix_getline.c b/components/libc/getline/posix_getline.c index 794ac3a07d..da80242ecc 100644 --- a/components/libc/getline/posix_getline.c +++ b/components/libc/getline/posix_getline.c @@ -11,8 +11,8 @@ #include "posix_getline.h" #include -#include -#include +#include +#include ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream) { char *cur_pos, *new_lineptr; @@ -43,7 +43,7 @@ ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream) { break; if ((*lineptr + *n - cur_pos) < 2) { - if (SSIZE_MAX / 2 < *n) { + if (LONG_MAX / 2 < *n) { #ifdef EOVERFLOW errno = EOVERFLOW; #else diff --git a/components/libc/pthreads/posix_types.h b/components/libc/pthreads/posix_types.h index 942657ef39..5838e8b370 100644 --- a/components/libc/pthreads/posix_types.h +++ b/components/libc/pthreads/posix_types.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #endif diff --git a/components/libc/termios/posix_termios.c b/components/libc/termios/posix_termios.c index 01ba010c86..10a1f466d6 100644 --- a/components/libc/termios/posix_termios.c +++ b/components/libc/termios/posix_termios.c @@ -11,7 +11,7 @@ #include #include #include - +#include #include int tcgetattr(int fd, struct termios *tio) diff --git a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h index 8dd59e8dee..880366d1f8 100644 --- a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h +++ b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h @@ -105,7 +105,7 @@ void sys_arch_assert(const char* file, int line); #define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) #define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) -#include "string.h" +#include #define SYS_ARCH_DECL_PROTECT(level) #define SYS_ARCH_PROTECT(level) rt_enter_critical() diff --git a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h index e3014f552c..a17b162805 100644 --- a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h @@ -84,7 +84,7 @@ void sys_arch_assert(const char* file, int line); #define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) #define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) -#include "string.h" +#include #define SYS_ARCH_DECL_PROTECT(level) #define SYS_ARCH_PROTECT(level) rt_enter_critical() diff --git a/components/net/lwip-2.0.2/src/lwipopts.h b/components/net/lwip-2.0.2/src/lwipopts.h index 09bd223aa4..b334c5ac17 100644 --- a/components/net/lwip-2.0.2/src/lwipopts.h +++ b/components/net/lwip-2.0.2/src/lwipopts.h @@ -5,6 +5,8 @@ #define ERRNO 1 +#define LWIP_ERRNO_STDINCLUDE + #define LWIP_IPV4 1 #ifdef RT_USING_LWIP_IPV6 diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h index 413fef65df..e85ca1d085 100644 --- a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h @@ -46,7 +46,7 @@ #define X32_F "lx" #ifdef RT_USING_LIBC -#include +#include #ifndef ENSRNOTFOUND #define ENSRNOTFOUND 163 /* Domain name not found */ #endif diff --git a/components/net/lwip-2.1.2/src/include/lwip/errno.h b/components/net/lwip-2.1.2/src/include/lwip/errno.h index 48d6b539d8..9fd88fc91a 100644 --- a/components/net/lwip-2.1.2/src/include/lwip/errno.h +++ b/components/net/lwip-2.1.2/src/include/lwip/errno.h @@ -181,7 +181,7 @@ extern int errno; /* Define LWIP_ERRNO_STDINCLUDE if you want to include here */ #ifdef LWIP_ERRNO_STDINCLUDE -#include +#include #else /* LWIP_ERRNO_STDINCLUDE */ /* Define LWIP_ERRNO_INCLUDE to an equivalent of to include the error defines here */ #ifdef LWIP_ERRNO_INCLUDE diff --git a/components/net/lwip-2.1.2/src/lwipopts.h b/components/net/lwip-2.1.2/src/lwipopts.h index 220bb6fa41..8c2bfbdd76 100644 --- a/components/net/lwip-2.1.2/src/lwipopts.h +++ b/components/net/lwip-2.1.2/src/lwipopts.h @@ -5,6 +5,7 @@ #define ERRNO 1 +#define LWIP_ERRNO_STDINCLUDE #define LWIP_SOCKET_SELECT 1 #define LWIP_SOCKET_POLL 1 diff --git a/components/net/sal_socket/socket/net_sockets.c b/components/net/sal_socket/socket/net_sockets.c index 3637635d50..7d4db34327 100644 --- a/components/net/sal_socket/socket/net_sockets.c +++ b/components/net/sal_socket/socket/net_sockets.c @@ -13,7 +13,7 @@ #include #include #include - +#include #include int accept(int s, struct sockaddr *addr, socklen_t *addrlen) diff --git a/examples/libc/ex3.c b/examples/libc/ex3.c index 1697e7145b..615ed8f35c 100644 --- a/examples/libc/ex3.c +++ b/examples/libc/ex3.c @@ -9,7 +9,7 @@ /* Multi-thread searching. Illustrates: thread cancellation, cleanup handlers. */ -#include +#include #include #include #include diff --git a/examples/libc/ex6.c b/examples/libc/ex6.c index ac6319d74c..ba687aa46f 100644 --- a/examples/libc/ex6.c +++ b/examples/libc/ex6.c @@ -6,7 +6,7 @@ * Change Logs: * Date Author Notes */ -#include +#include #include #include #include diff --git a/examples/libc/ex7.c b/examples/libc/ex7.c index e885f79c57..d1f05dbdcd 100644 --- a/examples/libc/ex7.c +++ b/examples/libc/ex7.c @@ -11,7 +11,7 @@ * Test case that illustrates a timed wait on a condition variable. */ -#include +#include #include #include #include diff --git a/examples/libc/file.c b/examples/libc/file.c index 79cdce3092..878d3a98d7 100644 --- a/examples/libc/file.c +++ b/examples/libc/file.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff --git a/examples/libc/memory.c b/examples/libc/memory.c index 063d90cfdc..4a31b69017 100644 --- a/examples/libc/memory.c +++ b/examples/libc/memory.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include static int errors = 0; static void merror(const char *msg) diff --git a/include/libc/libc_limits.h b/include/libc/libc_limits.h deleted file mode 100644 index 36b8dbb202..0000000000 --- a/include/libc/libc_limits.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-09-05 Meco Man the first version - */ - -#ifndef LIBC_LIMITS_H__ -#define LIBC_LIMITS_H__ - -#include -#include - -#ifdef RT_USING_POSIX - -#ifndef SSIZE_MAX -# define SSIZE_MAX LONG_MAX -#endif - -#endif - -#endif diff --git a/include/rtlibc.h b/include/rtlibc.h index 50bddc6ee8..a62051e157 100644 --- a/include/rtlibc.h +++ b/include/rtlibc.h @@ -13,14 +13,12 @@ /* definitions for libc if toolchain has no these definitions */ #include "libc/libc_stat.h" -#include "libc/libc_errno.h" #include "libc/libc_fcntl.h" #include "libc/libc_ioctl.h" #include "libc/libc_dirent.h" #include "libc/libc_signal.h" #include "libc/libc_fdset.h" -#include "libc/libc_limits.h" #include "libc/libc_stdio.h" #ifndef RT_USING_LIBC From 0e0e2a0f951ca3c8b5ff84137be369db6dab2922 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 22 May 2021 02:56:53 +0800 Subject: [PATCH 102/255] fix warning of posix_signal --- components/libc/signal/posix_signal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/libc/signal/posix_signal.c b/components/libc/signal/posix_signal.c index b06fe12685..1cb561d428 100644 --- a/components/libc/signal/posix_signal.c +++ b/components/libc/signal/posix_signal.c @@ -10,7 +10,8 @@ #include #include -#include +#include +#include #include "posix_signal.h" #define sig_valid(sig_no) (sig_no >= 0 && sig_no < RT_SIG_MAX) From b10bef6f241bfd9a6ecba3412351b20f3aa2eb13 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 22 May 2021 03:20:01 +0800 Subject: [PATCH 103/255] =?UTF-8?q?[sys/errno.h]=20=E4=BF=AE=E5=A4=8Dlwip?= =?UTF-8?q?=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../libc/compilers/common/none-gcc/sys/errno.h | 4 +--- components/net/lwip-1.4.1/src/arch/include/arch/cc.h | 8 ++++---- components/net/lwip-2.0.2/src/arch/include/arch/cc.h | 12 ++++++++++++ components/net/lwip-2.1.2/src/arch/include/arch/cc.h | 7 +++---- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/components/libc/compilers/common/none-gcc/sys/errno.h b/components/libc/compilers/common/none-gcc/sys/errno.h index bdc3a3c9da..773c2cd7d3 100644 --- a/components/libc/compilers/common/none-gcc/sys/errno.h +++ b/components/libc/compilers/common/none-gcc/sys/errno.h @@ -37,10 +37,8 @@ defined in armcc/errno.h #define ERROR_BASE_NO 0 #endif -#if !defined(_WIN32) - +#if defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) #include - #define EPERM (ERROR_BASE_NO + 1) #define ENOENT (ERROR_BASE_NO + 2) #define ESRCH (ERROR_BASE_NO + 3) diff --git a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h index 880366d1f8..23562703c3 100644 --- a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h +++ b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h @@ -54,16 +54,16 @@ typedef uintptr_t mem_ptr_t; #define S32_F "ld" #define X32_F "lx" -#ifdef RT_USING_LIBC -#if !defined(__CC_ARM) && !defined(__IAR_SYSTEMS_ICC__) - +#include /* some errno not defined in newlib */ +#ifndef ENSRNOTFOUND #define ENSRNOTFOUND 163 /* Domain name not found */ /* WARNING: ESHUTDOWN also not defined in newlib. We chose 180 here because the number "108" which is used in arch.h has been assigned to another error code. */ +#endif +#ifndef ESHUTDOWN #define ESHUTDOWN 180 -#endif /* __CC_ARM/__IAR_SYSTEMS_ICC__ */ #endif #if defined(RT_USING_LIBC) || defined(RT_LIBC_USING_TIME) || (defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) diff --git a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h index a17b162805..51662ae4a5 100644 --- a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h @@ -45,6 +45,18 @@ #define S32_F "ld" #define X32_F "lx" +#include +/* some errno not defined in newlib */ +#ifndef ENSRNOTFOUND +#define ENSRNOTFOUND 163 /* Domain name not found */ +/* WARNING: ESHUTDOWN also not defined in newlib. We chose + 180 here because the number "108" which is used + in arch.h has been assigned to another error code. */ +#endif +#ifndef ESHUTDOWN +#define ESHUTDOWN 180 +#endif + #if defined(RT_USING_LIBC) || defined(RT_LIBC_USING_TIME) || (defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) #include #define LWIP_TIMEVAL_PRIVATE 0 diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h index e85ca1d085..f4068c1d80 100644 --- a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h @@ -45,18 +45,17 @@ #define S32_F "ld" #define X32_F "lx" -#ifdef RT_USING_LIBC #include +/* some errno not defined in newlib */ #ifndef ENSRNOTFOUND #define ENSRNOTFOUND 163 /* Domain name not found */ -#endif -#ifndef ESHUTDOWN /* WARNING: ESHUTDOWN also not defined in newlib. We chose 180 here because the number "108" which is used in arch.h has been assigned to another error code. */ +#endif +#ifndef ESHUTDOWN #define ESHUTDOWN 180 #endif -#endif /* RT_USING_LIBC */ #if defined(RT_USING_LIBC) || defined(RT_LIBC_USING_TIME) || (defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) #include From 9352fdeba72678487dfb45ee55aabd08cb77b201 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 22 May 2021 12:04:30 +0800 Subject: [PATCH 104/255] =?UTF-8?q?=E4=BB=8ELWIP=E7=A7=BB=E9=99=A4ESHUTDOW?= =?UTF-8?q?N?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip-1.4.1/src/arch/include/arch/cc.h | 3 --- components/net/lwip-2.0.2/src/arch/include/arch/cc.h | 3 --- components/net/lwip-2.1.2/src/arch/include/arch/cc.h | 3 --- 3 files changed, 9 deletions(-) diff --git a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h index 23562703c3..2fc88da71b 100644 --- a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h +++ b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h @@ -62,9 +62,6 @@ typedef uintptr_t mem_ptr_t; 180 here because the number "108" which is used in arch.h has been assigned to another error code. */ #endif -#ifndef ESHUTDOWN -#define ESHUTDOWN 180 -#endif #if defined(RT_USING_LIBC) || defined(RT_LIBC_USING_TIME) || (defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) #include diff --git a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h index 51662ae4a5..09c436c53d 100644 --- a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h @@ -53,9 +53,6 @@ 180 here because the number "108" which is used in arch.h has been assigned to another error code. */ #endif -#ifndef ESHUTDOWN -#define ESHUTDOWN 180 -#endif #if defined(RT_USING_LIBC) || defined(RT_LIBC_USING_TIME) || (defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) #include diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h index f4068c1d80..b7ef3e370a 100644 --- a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h @@ -53,9 +53,6 @@ 180 here because the number "108" which is used in arch.h has been assigned to another error code. */ #endif -#ifndef ESHUTDOWN -#define ESHUTDOWN 180 -#endif #if defined(RT_USING_LIBC) || defined(RT_LIBC_USING_TIME) || (defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) #include From ac3b3d13dd690537eddc3aa1f0df9872178daab4 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 22 May 2021 12:13:31 +0800 Subject: [PATCH 105/255] =?UTF-8?q?LWIP2.0.2=202.1.2=20=E7=A7=BB=E9=99=A4E?= =?UTF-8?q?RRNO=20=E8=AF=A5=E5=AE=9A=E4=B9=89=E5=8F=AA=E5=BA=94=E8=AF=A5?= =?UTF-8?q?=E5=9C=A8141=E4=B8=AD=E4=BD=BF=E7=94=A8=E5=88=B0=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip-1.4.1/src/lwipopts.h | 2 +- components/net/lwip-2.0.2/src/lwipopts.h | 2 -- components/net/lwip-2.1.2/src/lwipopts.h | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/components/net/lwip-1.4.1/src/lwipopts.h b/components/net/lwip-1.4.1/src/lwipopts.h index a23a167970..0b7e092d6c 100644 --- a/components/net/lwip-1.4.1/src/lwipopts.h +++ b/components/net/lwip-1.4.1/src/lwipopts.h @@ -3,7 +3,7 @@ #include -#define ERRNO 1 +#define ERRNO #define NO_SYS 0 #define LWIP_SOCKET 1 diff --git a/components/net/lwip-2.0.2/src/lwipopts.h b/components/net/lwip-2.0.2/src/lwipopts.h index b334c5ac17..d559684c02 100644 --- a/components/net/lwip-2.0.2/src/lwipopts.h +++ b/components/net/lwip-2.0.2/src/lwipopts.h @@ -3,8 +3,6 @@ #include -#define ERRNO 1 - #define LWIP_ERRNO_STDINCLUDE #define LWIP_IPV4 1 diff --git a/components/net/lwip-2.1.2/src/lwipopts.h b/components/net/lwip-2.1.2/src/lwipopts.h index 8c2bfbdd76..2cd7cb023a 100644 --- a/components/net/lwip-2.1.2/src/lwipopts.h +++ b/components/net/lwip-2.1.2/src/lwipopts.h @@ -3,8 +3,6 @@ #include -#define ERRNO 1 - #define LWIP_ERRNO_STDINCLUDE #define LWIP_SOCKET_SELECT 1 #define LWIP_SOCKET_POLL 1 From c58d893c1add4e5a2495ff0726132958e3539854 Mon Sep 17 00:00:00 2001 From: Meco Jianting Man <920369182@qq.com> Date: Sat, 22 May 2021 17:21:42 +0800 Subject: [PATCH 106/255] =?UTF-8?q?[kernel][idle]=20=5Fhas=5Fdefunct=5Fthr?= =?UTF-8?q?ead=E5=87=BD=E6=95=B0=E5=A2=9E=E5=8A=A0=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?=E7=BC=96=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _has_defunct_thread函数增加条件编译,防止没有开启heap时报警 --- src/idle.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/idle.c b/src/idle.c index 24dfffbc6d..59868352d8 100644 --- a/src/idle.c +++ b/src/idle.c @@ -127,6 +127,7 @@ rt_err_t rt_thread_idle_delhook(void (*hook)(void)) #endif +#ifdef RT_USING_HEAP /* Return whether there is defunctional thread to be deleted. */ rt_inline int _has_defunct_thread(void) { @@ -140,6 +141,7 @@ rt_inline int _has_defunct_thread(void) return l->next != l; } +#endif /** * @ingroup Thread From 6c01083502936185a46ff6d7f8bf2732a68c51cf Mon Sep 17 00:00:00 2001 From: geniusgogo Date: Sat, 22 May 2021 19:50:49 +0800 Subject: [PATCH 107/255] fix shell msh_exec memory over-bound. --- components/finsh/msh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/finsh/msh.c b/components/finsh/msh.c index 73a5197dcd..ed12219c2e 100644 --- a/components/finsh/msh.c +++ b/components/finsh/msh.c @@ -374,7 +374,7 @@ int msh_exec(char *cmd, rt_size_t length) int cmd_ret; /* strim the beginning of command */ - while (*cmd == ' ' || *cmd == '\t') + while ((length > 0) && (*cmd == ' ' || *cmd == '\t')) { cmd++; length--; From 22e84516f4c11a347c40674ff80be270ed78b692 Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Sat, 22 May 2021 21:47:04 +0800 Subject: [PATCH 108/255] [BSP] Update imx6ul bsp for Kconfig and UART --- bsp/imx6ul/.config | 110 ++- bsp/imx6ul/SConstruct | 2 +- bsp/imx6ul/drivers/Kconfig | 3 + bsp/imx6ul/drivers/iomux/uart_iomux_config.c | 11 + bsp/imx6ul/drivers/serial.c | 24 - bsp/imx6ul/{imx6.lds => link.lds} | 0 .../platform/include/mx6ul/imx6ul-pinfunc.h | 915 ------------------ .../platform/include/mx6ul/iomux_register.h | 3 +- bsp/imx6ul/rtconfig.h | 18 +- bsp/imx6ul/rtconfig.py | 14 +- 10 files changed, 135 insertions(+), 965 deletions(-) rename bsp/imx6ul/{imx6.lds => link.lds} (100%) delete mode 100644 bsp/imx6ul/platform/include/mx6ul/imx6ul-pinfunc.h diff --git a/bsp/imx6ul/.config b/bsp/imx6ul/.config index 91e1e6fac2..4fa2072fb4 100644 --- a/bsp/imx6ul/.config +++ b/bsp/imx6ul/.config @@ -71,8 +71,8 @@ CONFIG_RT_USING_DEVICE=y # CONFIG_RT_USING_INTERRUPT_INFO is not set CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=128 -CONFIG_RT_CONSOLE_DEVICE_NAME="uart" -CONFIG_RT_VER_NUM=0x40003 +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 @@ -177,6 +177,7 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -213,8 +214,14 @@ CONFIG_RT_USING_POSIX=y # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_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 # @@ -282,8 +289,6 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_LIBRWS is not set # CONFIG_PKG_USING_TCPSERVER is not set # CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set # CONFIG_PKG_USING_DLT645 is not set # CONFIG_PKG_USING_QXWZ is not set # CONFIG_PKG_USING_SMTP_CLIENT is not set @@ -297,6 +302,13 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -322,7 +334,10 @@ CONFIG_RT_USING_POSIX=y # 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 # # tools packages @@ -334,9 +349,12 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -344,6 +362,22 @@ CONFIG_RT_USING_POSIX=y # 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 # # system packages @@ -352,7 +386,6 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set -# CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set # CONFIG_PKG_USING_FLASHDB is not set @@ -362,6 +395,9 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -371,7 +407,26 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_RAMDISK is not set # CONFIG_PKG_USING_MININI is not set # CONFIG_PKG_USING_QBOOT is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_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_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# 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 +# 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 @@ -380,6 +435,7 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -427,6 +483,30 @@ CONFIG_RT_USING_POSIX=y # 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 + +# +# 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 @@ -436,6 +516,7 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -456,17 +537,24 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set # CONFIG_PKG_USING_VI is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set # CONFIG_PKG_USING_VT100 is not set -# CONFIG_PKG_USING_TETRIS is not set -# CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set + +# +# 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_TENSORFLOWLITEMICRO 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_RT_USING_UART1=y CONFIG_SOC_MCIMX6X4=y diff --git a/bsp/imx6ul/SConstruct b/bsp/imx6ul/SConstruct index 8c9e4ee347..de15998d09 100644 --- a/bsp/imx6ul/SConstruct +++ b/bsp/imx6ul/SConstruct @@ -10,7 +10,7 @@ else: sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] from building import * -TARGET = 'rtthread-imx6.' + rtconfig.TARGET_EXT +TARGET = 'rtthread.' + rtconfig.TARGET_EXT DefaultEnvironment(tools=[]) env = Environment(tools = ['mingw'], diff --git a/bsp/imx6ul/drivers/Kconfig b/bsp/imx6ul/drivers/Kconfig index e69de29bb2..95c536178d 100644 --- a/bsp/imx6ul/drivers/Kconfig +++ b/bsp/imx6ul/drivers/Kconfig @@ -0,0 +1,3 @@ +config RT_USING_UART1 + bool "Enable UART1" + default y diff --git a/bsp/imx6ul/drivers/iomux/uart_iomux_config.c b/bsp/imx6ul/drivers/iomux/uart_iomux_config.c index bad8e945c3..0d180ff713 100644 --- a/bsp/imx6ul/drivers/iomux/uart_iomux_config.c +++ b/bsp/imx6ul/drivers/iomux/uart_iomux_config.c @@ -37,6 +37,17 @@ #define MX6UL_PAD_UART1_RX_DATA__UART1_RX1 (IOMUXC_BASE_ADDR+0x088) #define IOMUXC_UART1_UART_RXD_MUX_SELECT_INPUT1 (IOMUXC_BASE_ADDR+0x624) +#define PIN_CFG(mux_ctl_offset, pad_ctl_offset, select_input_offset, mux_mode, daisy, pad_setting) \ + do {\ + writel(mux_mode, IOMUXC_BASE_ADDR + mux_ctl_offset);\ + if (select_input_offset != 0)\ + writel(daisy, IOMUXC_BASE_ADDR + select_input_offset);\ + writel(pad_setting, IOMUXC_BASE_ADDR + pad_ctl_offset);\ + } while(0); + +#define MX6UL_PAD_UART1_TX_DATA__UART1_TX(p) PIN_CFG(0x0084, 0x0310, 0x0624, 0x0, 0x2, p) +#define MX6UL_PAD_UART1_RX_DATA__UART1_RX(p) PIN_CFG(0x0088, 0x0314, 0x0624, 0x0, 0x3, p) + void uart1_iomux_config(void) { /* UART1 TXD */ diff --git a/bsp/imx6ul/drivers/serial.c b/bsp/imx6ul/drivers/serial.c index ce46050c92..5764d088de 100644 --- a/bsp/imx6ul/drivers/serial.c +++ b/bsp/imx6ul/drivers/serial.c @@ -11,9 +11,7 @@ #include #include #include - #include - #include "serial.h" struct hw_uart_device @@ -123,16 +121,6 @@ static const struct rt_uart_ops _uart_ops = uart_getc, }; -#ifdef RT_USING_UART0 -/* UART device driver structure */ -static struct hw_uart_device _uart0_device = -{ - HW_UART0, - IMX_INT_UART0 -}; -static struct rt_serial_device _serial0; -#endif - #ifdef RT_USING_UART1 /* UART1 device driver structure */ static struct hw_uart_device _uart1_device = @@ -156,18 +144,6 @@ int rt_hw_uart_init(void) config.invert = NRZ_NORMAL; config.bufsz = RT_SERIAL_RB_BUFSZ; -#ifdef RT_USING_UART0 - uart = &_uart0_device; - - _serial0.ops = &_uart_ops; - _serial0.config = config; - - /* register UART1 device */ - rt_hw_serial_register(&_serial0, "uart0", - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, - uart); -#endif - #ifdef RT_USING_UART1 uart = &_uart1_device; _serial1.ops = &_uart_ops; diff --git a/bsp/imx6ul/imx6.lds b/bsp/imx6ul/link.lds similarity index 100% rename from bsp/imx6ul/imx6.lds rename to bsp/imx6ul/link.lds diff --git a/bsp/imx6ul/platform/include/mx6ul/imx6ul-pinfunc.h b/bsp/imx6ul/platform/include/mx6ul/imx6ul-pinfunc.h deleted file mode 100644 index dc66fe20ed..0000000000 --- a/bsp/imx6ul/platform/include/mx6ul/imx6ul-pinfunc.h +++ /dev/null @@ -1,915 +0,0 @@ -/* - * Copyright 2014 - 2015 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef __DTS_IMX6UL_PINFUNC_H -#define __DTS_IMX6UL_PINFUNC_H - -#define PIN_CFG(mux_ctl_offset, pad_ctl_offset, select_input_offset, mux_mode, daisy, pad_setting) \ - do {\ - writel(mux_mode, IOMUXC_BASE_ADDR + mux_ctl_offset);\ - if (select_input_offset != 0)\ - writel(daisy, IOMUXC_BASE_ADDR + select_input_offset);\ - writel(pad_setting, IOMUXC_BASE_ADDR + pad_ctl_offset);\ - } while(0); - -/* - * The pin function ID is a tuple of - * - */ -#define MX6UL_PAD_JTAG_MOD__SJC_MOD(p) PIN_CFG(0x0044, 0x02D0, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_JTAG_MOD__GPT2_CLK(p) PIN_CFG(0x0044, 0x02D0, 0x05A0, 0x1, 0x0, p) -#define MX6UL_PAD_JTAG_MOD__SPDIF_OUT(p) PIN_CFG(0x0044, 0x02D0, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_JTAG_MOD__ENET1_REF_CLK_25M(p) PIN_CFG(0x0044, 0x02D0, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_JTAG_MOD__CCM_PMIC_RDY(p) PIN_CFG(0x0044, 0x02D0, 0x04C0, 0x4, 0x0, p) -#define MX6UL_PAD_JTAG_MOD__GPIO1_IO10(p) PIN_CFG(0x0044, 0x02D0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_JTAG_MOD__SDMA_EXT_EVENT00(p) PIN_CFG(0x0044, 0x02D0, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_JTAG_TMS__SJC_TMS(p) PIN_CFG(0x0048, 0x02D4, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_JTAG_TMS__GPT2_CAPTURE1(p) PIN_CFG(0x0048, 0x02D4, 0x0598, 0x1, 0x0, p) -#define MX6UL_PAD_JTAG_TMS__SAI2_MCLK(p) PIN_CFG(0x0048, 0x02D4, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_JTAG_TMS__CCM_CLKO1(p) PIN_CFG(0x0048, 0x02D4, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_JTAG_TMS__CCM_WAIT(p) PIN_CFG(0x0048, 0x02D4, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_JTAG_TMS__GPIO1_IO11(p) PIN_CFG(0x0048, 0x02D4, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_JTAG_TMS__SDMA_EXT_EVENT01(p) PIN_CFG(0x0048, 0x02D4, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_JTAG_TMS__EPIT1_OUT(p) PIN_CFG(0x0048, 0x02D4, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_JTAG_TDO__SJC_TDO(p) PIN_CFG(0x004C, 0x02D8, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_JTAG_TDO__GPT2_CAPTURE2(p) PIN_CFG(0x004C, 0x02D8, 0x059C, 0x1, 0x0, p) -#define MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC(p) PIN_CFG(0x004C, 0x02D8, 0x05FC, 0x2, 0x0, p) -#define MX6UL_PAD_JTAG_TDO__CCM_CLKO2(p) PIN_CFG(0x004C, 0x02D8, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_JTAG_TDO__CCM_STOP(p) PIN_CFG(0x004C, 0x02D8, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_JTAG_TDO__GPIO1_IO12(p) PIN_CFG(0x004C, 0x02D8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_JTAG_TDO__MQS_RIGHT(p) PIN_CFG(0x004C, 0x02D8, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_JTAG_TDO__EPIT2_OUT(p) PIN_CFG(0x004C, 0x02D8, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_JTAG_TDI__SJC_TDI(p) PIN_CFG(0x0050, 0x02DC, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_JTAG_TDI__GPT2_COMPARE1(p) PIN_CFG(0x0050, 0x02DC, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK(p) PIN_CFG(0x0050, 0x02DC, 0x05F8, 0x2, 0x0, p) -#define MX6UL_PAD_JTAG_TDI__PWM6_OUT(p) PIN_CFG(0x0050, 0x02DC, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_JTAG_TDI__GPIO1_IO13(p) PIN_CFG(0x0050, 0x02DC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_JTAG_TDI__MQS_LEFT(p) PIN_CFG(0x0050, 0x02DC, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_JTAG_TDI__SIM1_POWER_FAIL(p) PIN_CFG(0x0050, 0x02DC, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_JTAG_TCK__SJC_TCK(p) PIN_CFG(0x0054, 0x02E0, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_JTAG_TCK__GPT2_COMPARE2(p) PIN_CFG(0x0054, 0x02E0, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA(p) PIN_CFG(0x0054, 0x02E0, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_JTAG_TCK__PWM7_OUT(p) PIN_CFG(0x0054, 0x02E0, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_JTAG_TCK__GPIO1_IO14(p) PIN_CFG(0x0054, 0x02E0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_JTAG_TCK__SIM2_POWER_FAIL(p) PIN_CFG(0x0054, 0x02E0, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_JTAG_TRST_B__SJC_TRSTB(p) PIN_CFG(0x0058, 0x02E4, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_JTAG_TRST_B__GPT2_COMPARE3(p) PIN_CFG(0x0058, 0x02E4, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA(p) PIN_CFG(0x0058, 0x02E4, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_JTAG_TRST_B__PWM8_OUT(p) PIN_CFG(0x0058, 0x02E4, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_JTAG_TRST_B__GPIO1_IO15(p) PIN_CFG(0x0058, 0x02E4, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_JTAG_TRST_B__CAAM_RNG_OSC_OBS(p) PIN_CFG(0x0058, 0x02E4, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO00__I2C2_SCL(p) PIN_CFG(0x005C, 0x02E8, 0x05AC, 0x0, 0x1, p) -#define MX6UL_PAD_GPIO1_IO00__GPT1_CAPTURE1(p) PIN_CFG(0x005C, 0x02E8, 0x058C, 0x1, 0x0, p) -#define MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID(p) PIN_CFG(0x005C, 0x02E8, 0x04B8, 0x2, 0x0, p) -#define MX6UL_PAD_GPIO1_IO00__ENET1_REF_CLK1(p) PIN_CFG(0x005C, 0x02E8, 0x0574, 0x3, 0x0, p) -#define MX6UL_PAD_GPIO1_IO00__MQS_RIGHT(p) PIN_CFG(0x005C, 0x02E8, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_GPIO1_IO00__GPIO1_IO00(p) PIN_CFG(0x005C, 0x02E8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_GPIO1_IO00__ENET1_1588_EVENT0_IN(p) PIN_CFG(0x005C, 0x02E8, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_GPIO1_IO00__SRC_SYSTEM_RESET(p) PIN_CFG(0x005C, 0x02E8, 0x0000, 0x7, 0x0, p) -#define MX6UL_PAD_GPIO1_IO00__WDOG3_WDOG_B(p) PIN_CFG(0x005C, 0x02E8, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO01__I2C2_SDA(p) PIN_CFG(0x0060, 0x02EC, 0x05B0, 0x0, 0x1, p) -#define MX6UL_PAD_GPIO1_IO01__GPT1_COMPARE1(p) PIN_CFG(0x0060, 0x02EC, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_GPIO1_IO01__USB_OTG1_OC(p) PIN_CFG(0x0060, 0x02EC, 0x0664, 0x2, 0x0, p) -#define MX6UL_PAD_GPIO1_IO01__ENET2_REF_CLK2(p) PIN_CFG(0x0060, 0x02EC, 0x057C, 0x3, 0x0, p) -#define MX6UL_PAD_GPIO1_IO01__MQS_LEFT(p) PIN_CFG(0x0060, 0x02EC, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_GPIO1_IO01__GPIO1_IO01(p) PIN_CFG(0x0060, 0x02EC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_GPIO1_IO01__ENET1_1588_EVENT0_OUT(p) PIN_CFG(0x0060, 0x02EC, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_GPIO1_IO01__SRC_EARLY_RESET(p) PIN_CFG(0x0060, 0x02EC, 0x0000, 0x7, 0x0, p) -#define MX6UL_PAD_GPIO1_IO01__WDOG1_WDOG_B(p) PIN_CFG(0x0060, 0x02EC, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO02__I2C1_SCL(p) PIN_CFG(0x0064, 0x02F0, 0x05A4, 0x0, 0x0, p) -#define MX6UL_PAD_GPIO1_IO02__GPT1_COMPARE2(p) PIN_CFG(0x0064, 0x02F0, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_GPIO1_IO02__USB_OTG2_PWR(p) PIN_CFG(0x0064, 0x02F0, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_GPIO1_IO02__ENET1_REF_CLK_25M(p) PIN_CFG(0x0064, 0x02F0, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_GPIO1_IO02__USDHC1_WP(p) PIN_CFG(0x0064, 0x02F0, 0x066C, 0x4, 0x0, p) -#define MX6UL_PAD_GPIO1_IO02__GPIO1_IO02(p) PIN_CFG(0x0064, 0x02F0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_GPIO1_IO02__SDMA_EXT_EVENT00(p) PIN_CFG(0x0064, 0x02F0, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_GPIO1_IO02__SRC_ANY_PU_RESET(p) PIN_CFG(0x0064, 0x02F0, 0x0000, 0x7, 0x0, p) -#define MX6UL_PAD_GPIO1_IO02__UART1_TX(p) PIN_CFG(0x0064, 0x02F0, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO03__I2C1_SDA(p) PIN_CFG(0x0068, 0x02F4, 0x05A8, 0x0, 0x1, p) -#define MX6UL_PAD_GPIO1_IO03__GPT1_COMPARE3(p) PIN_CFG(0x0068, 0x02F4, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_GPIO1_IO03__USB_OTG2_OC(p) PIN_CFG(0x0068, 0x02F4, 0x0660, 0x2, 0x0, p) -#define MX6UL_PAD_GPIO1_IO03__USDHC1_CD_B(p) PIN_CFG(0x0068, 0x02F4, 0x0668, 0x4, 0x0, p) -#define MX6UL_PAD_GPIO1_IO03__GPIO1_IO03(p) PIN_CFG(0x0068, 0x02F4, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_GPIO1_IO03__CCM_DI0_EXT_CLK(p) PIN_CFG(0x0068, 0x02F4, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_GPIO1_IO03__SRC_TESTER_ACK(p) PIN_CFG(0x0068, 0x02F4, 0x0000, 0x7, 0x0, p) -#define MX6UL_PAD_GPIO1_IO03__UART1_RX(p) PIN_CFG(0x0068, 0x02F4, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO04__ENET1_REF_CLK1(p) PIN_CFG(0x006C, 0x02F8, 0x0574, 0x0, 0x1, p) -#define MX6UL_PAD_GPIO1_IO04__PWM3_OUT(p) PIN_CFG(0x006C, 0x02F8, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_GPIO1_IO04__USB_OTG1_PWR(p) PIN_CFG(0x006C, 0x02F8, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_GPIO1_IO04__USDHC1_RESET_B(p) PIN_CFG(0x006C, 0x02F8, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_GPIO1_IO04__GPIO1_IO04(p) PIN_CFG(0x006C, 0x02F8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_GPIO1_IO04__ENET2_1588_EVENT0_IN(p) PIN_CFG(0x006C, 0x02F8, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_GPIO1_IO04__UART5_TX(p) PIN_CFG(0x006C, 0x02F8, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO05__ENET2_REF_CLK2(p) PIN_CFG(0x0070, 0x02FC, 0x057C, 0x0, 0x1, p) -#define MX6UL_PAD_GPIO1_IO05__PWM4_OUT(p) PIN_CFG(0x0070, 0x02FC, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_GPIO1_IO05__ANATOP_OTG2_ID(p) PIN_CFG(0x0070, 0x02FC, 0x04BC, 0x2, 0x0, p) -#define MX6UL_PAD_GPIO1_IO05__CSI_FIELD(p) PIN_CFG(0x0070, 0x02FC, 0x0530, 0x3, 0x0, p) -#define MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT(p) PIN_CFG(0x0070, 0x02FC, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_GPIO1_IO05__GPIO1_IO05(p) PIN_CFG(0x0070, 0x02FC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_GPIO1_IO05__ENET2_1588_EVENT0_OUT(p) PIN_CFG(0x0070, 0x02FC, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_GPIO1_IO05__UART5_RX(p) PIN_CFG(0x0070, 0x02FC, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO06__ENET1_MDIO(p) PIN_CFG(0x0074, 0x0300, 0x0578, 0x0, 0x0, p) -#define MX6UL_PAD_GPIO1_IO06__ENET2_MDIO(p) PIN_CFG(0x0074, 0x0300, 0x0580, 0x1, 0x0, p) -#define MX6UL_PAD_GPIO1_IO06__USB_OTG_PWR_WAKE(p) PIN_CFG(0x0074, 0x0300, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_GPIO1_IO06__CSI_MCLK(p) PIN_CFG(0x0074, 0x0300, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_GPIO1_IO06__USDHC2_WP(p) PIN_CFG(0x0074, 0x0300, 0x069C, 0x4, 0x0, p) -#define MX6UL_PAD_GPIO1_IO06__GPIO1_IO06(p) PIN_CFG(0x0074, 0x0300, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_GPIO1_IO06__CCM_WAIT(p) PIN_CFG(0x0074, 0x0300, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_GPIO1_IO06__CCM_REF_EN_B(p) PIN_CFG(0x0074, 0x0300, 0x0000, 0x7, 0x0, p) -#define MX6UL_PAD_GPIO1_IO06__UART1_DCE_CTS(p) PIN_CFG(0x0074, 0x0300, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO06__UART1_DTE_RTS(p) PIN_CFG(0x0074, 0x0300, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO07__ENET1_MDC(p) PIN_CFG(0x0078, 0x0304, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_GPIO1_IO07__ENET2_MDC(p) PIN_CFG(0x0078, 0x0304, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_GPIO1_IO07__USB_OTG_HOST_MODE(p) PIN_CFG(0x0078, 0x0304, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_GPIO1_IO07__CSI_PIXCLK(p) PIN_CFG(0x0078, 0x0304, 0x0528, 0x3, 0x0, p) -#define MX6UL_PAD_GPIO1_IO07__USDHC2_CD_B(p) PIN_CFG(0x0078, 0x0304, 0x0674, 0x4, 0x1, p) -#define MX6UL_PAD_GPIO1_IO07__GPIO1_IO07(p) PIN_CFG(0x0078, 0x0304, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_GPIO1_IO07__CCM_STOP(p) PIN_CFG(0x0078, 0x0304, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_GPIO1_IO07__UART1_DCE_RTS(p) PIN_CFG(0x0078, 0x0304, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO07__UART1_DTE_CTS(p) PIN_CFG(0x0078, 0x0304, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO08__PWM1_OUT(p) PIN_CFG(0x007C, 0x0308, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_GPIO1_IO08__WDOG1_WDOG_B(p) PIN_CFG(0x007C, 0x0308, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_GPIO1_IO08__SPDIF_OUT(p) PIN_CFG(0x007C, 0x0308, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_GPIO1_IO08__CSI_VSYNC(p) PIN_CFG(0x007C, 0x0308, 0x052C, 0x3, 0x1, p) -#define MX6UL_PAD_GPIO1_IO08__USDHC2_VSELECT(p) PIN_CFG(0x007C, 0x0308, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_GPIO1_IO08__GPIO1_IO08(p) PIN_CFG(0x007C, 0x0308, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_GPIO1_IO08__CCM_PMIC_RDY(p) PIN_CFG(0x007C, 0x0308, 0x04C0, 0x6, 0x1, p) -#define MX6UL_PAD_GPIO1_IO08__UART5_DCE_RTS(p) PIN_CFG(0x007C, 0x0308, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO08__UART5_DTE_CTS(p) PIN_CFG(0x007C, 0x0308, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO09__PWM2_OUT(p) PIN_CFG(0x0080, 0x030C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_GPIO1_IO09__WDOG1_WDOG_ANY(p) PIN_CFG(0x0080, 0x030C, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_GPIO1_IO09__SPDIF_IN(p) PIN_CFG(0x0080, 0x030C, 0x0618, 0x2, 0x0, p) -#define MX6UL_PAD_GPIO1_IO09__CSI_HSYNC(p) PIN_CFG(0x0080, 0x030C, 0x0524, 0x3, 0x1, p) -#define MX6UL_PAD_GPIO1_IO09__USDHC2_RESET_B(p) PIN_CFG(0x0080, 0x030C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_GPIO1_IO09__GPIO1_IO09(p) PIN_CFG(0x0080, 0x030C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_GPIO1_IO09__USDHC1_RESET_B(p) PIN_CFG(0x0080, 0x030C, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_GPIO1_IO09__UART5_DCE_CTS(p) PIN_CFG(0x0080, 0x030C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_GPIO1_IO09__UART5_DTE_RTS(p) PIN_CFG(0x0080, 0x030C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART1_TX_DATA__UART1_TX(p) PIN_CFG(0x0084, 0x0310, 0x0624, 0x0, 0x2, p) -#define MX6UL_PAD_UART1_TX_DATA__ENET1_RDATA02(p) PIN_CFG(0x0084, 0x0310, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART1_TX_DATA__I2C3_SCL(p) PIN_CFG(0x0084, 0x0310, 0x05B4, 0x2, 0x0, p) -#define MX6UL_PAD_UART1_TX_DATA__CSI_DATA02(p) PIN_CFG(0x0084, 0x0310, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART1_TX_DATA__GPT1_COMPARE1(p) PIN_CFG(0x0084, 0x0310, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART1_TX_DATA__GPIO1_IO16(p) PIN_CFG(0x0084, 0x0310, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART1_TX_DATA__SPDIF_OUT(p) PIN_CFG(0x0084, 0x0310, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART1_RX_DATA__UART1_RX(p) PIN_CFG(0x0088, 0x0314, 0x0624, 0x0, 0x3, p) -#define MX6UL_PAD_UART1_RX_DATA__ENET1_RDATA03(p) PIN_CFG(0x0088, 0x0314, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART1_RX_DATA__I2C3_SDA(p) PIN_CFG(0x0088, 0x0314, 0x05B8, 0x2, 0x0, p) -#define MX6UL_PAD_UART1_RX_DATA__CSI_DATA03(p) PIN_CFG(0x0088, 0x0314, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART1_RX_DATA__GPT1_CLK(p) PIN_CFG(0x0088, 0x0314, 0x0594, 0x4, 0x0, p) -#define MX6UL_PAD_UART1_RX_DATA__GPIO1_IO17(p) PIN_CFG(0x0088, 0x0314, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART1_RX_DATA__SPDIF_IN(p) PIN_CFG(0x0088, 0x0314, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART1_CTS_B__UART1_DCE_CTS(p) PIN_CFG(0x008C, 0x0318, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_UART1_CTS_B__UART1_DTE_RTS(p) PIN_CFG(0x008C, 0x0318, 0x0620, 0x0, 0x2, p) -#define MX6UL_PAD_UART1_CTS_B__ENET1_RX_CLK(p) PIN_CFG(0x008C, 0x0318, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART1_CTS_B__USDHC1_WP(p) PIN_CFG(0x008C, 0x0318, 0x066C, 0x2, 0x1, p) -#define MX6UL_PAD_UART1_CTS_B__CSI_DATA04(p) PIN_CFG(0x008C, 0x0318, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART1_CTS_B__ENET2_1588_EVENT1_IN(p) PIN_CFG(0x008C, 0x0318, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART1_CTS_B__GPIO1_IO18(p) PIN_CFG(0x008C, 0x0318, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART1_CTS_B__USDHC2_WP(p) PIN_CFG(0x008C, 0x0318, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART1_RTS_B__UART1_DCE_RTS(p) PIN_CFG(0x0090, 0x031C, 0x0620, 0x0, 0x3, p) -#define MX6UL_PAD_UART1_RTS_B__UART1_DTE_CTS(p) PIN_CFG(0x0090, 0x031C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_UART1_RTS_B__ENET1_TX_ER(p) PIN_CFG(0x0090, 0x031C, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART1_RTS_B__USDHC1_CD_B(p) PIN_CFG(0x0090, 0x031C, 0x0668, 0x2, 0x1, p) -#define MX6UL_PAD_UART1_RTS_B__CSI_DATA05(p) PIN_CFG(0x0090, 0x031C, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART1_RTS_B__ENET2_1588_EVENT1_OUT(p) PIN_CFG(0x0090, 0x031C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART1_RTS_B__GPIO1_IO19(p) PIN_CFG(0x0090, 0x031C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART1_RTS_B__USDHC2_CD_B(p) PIN_CFG(0x0090, 0x031C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART2_TX_DATA__UART2_TX(p) PIN_CFG(0x0094, 0x0320, 0x062C, 0x0, 0x0, p) -#define MX6UL_PAD_UART2_TX_DATA__ENET1_TDATA02(p) PIN_CFG(0x0094, 0x0320, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART2_TX_DATA__I2C4_SCL(p) PIN_CFG(0x0094, 0x0320, 0x05BC, 0x2, 0x0, p) -#define MX6UL_PAD_UART2_TX_DATA__CSI_DATA06(p) PIN_CFG(0x0094, 0x0320, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART2_TX_DATA__GPT1_CAPTURE1(p) PIN_CFG(0x0094, 0x0320, 0x058C, 0x4, 0x1, p) -#define MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20(p) PIN_CFG(0x0094, 0x0320, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART2_TX_DATA__ECSPI3_SS0(p) PIN_CFG(0x0094, 0x0320, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART2_RX_DATA__UART2_RX(p) PIN_CFG(0x0098, 0x0324, 0x062C, 0x0, 0x1, p) -#define MX6UL_PAD_UART2_RX_DATA__ENET1_TDATA03(p) PIN_CFG(0x0098, 0x0324, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART2_RX_DATA__I2C4_SDA(p) PIN_CFG(0x0098, 0x0324, 0x05C0, 0x2, 0x0, p) -#define MX6UL_PAD_UART2_RX_DATA__CSI_DATA07(p) PIN_CFG(0x0098, 0x0324, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART2_RX_DATA__GPT1_CAPTURE2(p) PIN_CFG(0x0098, 0x0324, 0x0590, 0x4, 0x0, p) -#define MX6UL_PAD_UART2_RX_DATA__GPIO1_IO21(p) PIN_CFG(0x0098, 0x0324, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART2_RX_DATA__SJC_DONE(p) PIN_CFG(0x0098, 0x0324, 0x0000, 0x7, 0x0, p) -#define MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK(p) PIN_CFG(0x0098, 0x0324, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART2_CTS_B__UART2_DCE_CTS(p) PIN_CFG(0x009C, 0x0328, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_UART2_CTS_B__UART2_DTE_RTS(p) PIN_CFG(0x009C, 0x0328, 0x0628, 0x0, 0x0, p) -#define MX6UL_PAD_UART2_CTS_B__ENET1_CRS(p) PIN_CFG(0x009C, 0x0328, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX(p) PIN_CFG(0x009C, 0x0328, 0x0000, 0x12, 0x0, p) -#define MX6UL_PAD_UART2_CTS_B__CSI_DATA08(p) PIN_CFG(0x009C, 0x0328, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART2_CTS_B__GPT1_COMPARE2(p) PIN_CFG(0x009C, 0x0328, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART2_CTS_B__GPIO1_IO22(p) PIN_CFG(0x009C, 0x0328, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART2_CTS_B__SJC_DE_B(p) PIN_CFG(0x009C, 0x0328, 0x0000, 0x7, 0x0, p) -#define MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI(p) PIN_CFG(0x009C, 0x0328, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART2_RTS_B__UART2_DCE_RTS(p) PIN_CFG(0x00A0, 0x032C, 0x0628, 0x0, 0x1, p) -#define MX6UL_PAD_UART2_RTS_B__UART2_DTE_CTS(p) PIN_CFG(0x00A0, 0x032C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_UART2_RTS_B__ENET1_COL(p) PIN_CFG(0x00A0, 0x032C, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX(p) PIN_CFG(0x00A0, 0x032C, 0x0588, 0x12, 0x0, p) -#define MX6UL_PAD_UART2_RTS_B__CSI_DATA09(p) PIN_CFG(0x00A0, 0x032C, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART2_RTS_B__GPT1_COMPARE3(p) PIN_CFG(0x00A0, 0x032C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART2_RTS_B__GPIO1_IO23(p) PIN_CFG(0x00A0, 0x032C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART2_RTS_B__SJC_FAIL(p) PIN_CFG(0x00A0, 0x032C, 0x0000, 0x7, 0x0, p) -#define MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO(p) PIN_CFG(0x00A0, 0x032C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART3_TX_DATA__UART3_TX(p) PIN_CFG(0x00A4, 0x0330, 0x0634, 0x0, 0x0, p) -#define MX6UL_PAD_UART3_TX_DATA__ENET2_RDATA02(p) PIN_CFG(0x00A4, 0x0330, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART3_TX_DATA__SIM1_PORT0_PD(p) PIN_CFG(0x00A4, 0x0330, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_UART3_TX_DATA__CSI_DATA01(p) PIN_CFG(0x00A4, 0x0330, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS(p) PIN_CFG(0x00A4, 0x0330, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART3_TX_DATA__UART2_DTE_RTS(p) PIN_CFG(0x00A4, 0x0330, 0x0628, 0x4, 0x2, p) -#define MX6UL_PAD_UART3_TX_DATA__GPIO1_IO24(p) PIN_CFG(0x00A4, 0x0330, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART3_TX_DATA__SJC_JTAG_ACT(p) PIN_CFG(0x00A4, 0x0330, 0x0000, 0x7, 0x0, p) -#define MX6UL_PAD_UART3_TX_DATA__ANATOP_OTG1_ID(p) PIN_CFG(0x00A4, 0x0330, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART3_RX_DATA__UART3_RX(p) PIN_CFG(0x00A8, 0x0334, 0x0634, 0x0, 0x1, p) -#define MX6UL_PAD_UART3_RX_DATA__ENET2_RDATA03(p) PIN_CFG(0x00A8, 0x0334, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART3_RX_DATA__SIM2_PORT0_PD(p) PIN_CFG(0x00A8, 0x0334, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_UART3_RX_DATA__CSI_DATA00(p) PIN_CFG(0x00A8, 0x0334, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS(p) PIN_CFG(0x00A8, 0x0334, 0x0628, 0x4, 0x3, p) -#define MX6UL_PAD_UART3_RX_DATA__UART2_DTE_CTS(p) PIN_CFG(0x00A8, 0x0334, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART3_RX_DATA__GPIO1_IO25(p) PIN_CFG(0x00A8, 0x0334, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART3_RX_DATA__EPIT1_OUT(p) PIN_CFG(0x00A8, 0x0334, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS(p) PIN_CFG(0x00AC, 0x0338, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_UART3_CTS_B__UART3_DTE_RTS(p) PIN_CFG(0x00AC, 0x0338, 0x0630, 0x0, 0x0, p) -#define MX6UL_PAD_UART3_CTS_B__ENET2_RX_CLK(p) PIN_CFG(0x00AC, 0x0338, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX(p) PIN_CFG(0x00AC, 0x0338, 0x0000, 0x12, 0x0, p) -#define MX6UL_PAD_UART3_CTS_B__CSI_DATA10(p) PIN_CFG(0x00AC, 0x0338, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART3_CTS_B__ENET1_1588_EVENT1_IN(p) PIN_CFG(0x00AC, 0x0338, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART3_CTS_B__GPIO1_IO26(p) PIN_CFG(0x00AC, 0x0338, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART3_CTS_B__EPIT2_OUT(p) PIN_CFG(0x00AC, 0x0338, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS(p) PIN_CFG(0x00B0, 0x033C, 0x0630, 0x0, 0x1, p) -#define MX6UL_PAD_UART3_RTS_B__UART3_DTE_CTS(p) PIN_CFG(0x00B0, 0x033C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_UART3_RTS_B__ENET2_TX_ER(p) PIN_CFG(0x00B0, 0x033C, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX(p) PIN_CFG(0x00B0, 0x033C, 0x0584, 0x12, 0x0, p) -#define MX6UL_PAD_UART3_RTS_B__CSI_DATA11(p) PIN_CFG(0x00B0, 0x033C, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART3_RTS_B__ENET1_1588_EVENT1_OUT(p) PIN_CFG(0x00B0, 0x033C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART3_RTS_B__GPIO1_IO27(p) PIN_CFG(0x00B0, 0x033C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART3_RTS_B__WDOG1_WDOG_B(p) PIN_CFG(0x00B0, 0x033C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART4_TX_DATA__UART4_TX(p) PIN_CFG(0x00B4, 0x0340, 0x063C, 0x0, 0x0, p) -#define MX6UL_PAD_UART4_TX_DATA__ENET2_TDATA02(p) PIN_CFG(0x00B4, 0x0340, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART4_TX_DATA__I2C1_SCL(p) PIN_CFG(0x00B4, 0x0340, 0x05A4, 0x12, 0x1, p) -#define MX6UL_PAD_UART4_TX_DATA__CSI_DATA12(p) PIN_CFG(0x00B4, 0x0340, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART4_TX_DATA__CSU_CSU_ALARM_AUT02(p) PIN_CFG(0x00B4, 0x0340, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART4_TX_DATA__GPIO1_IO28(p) PIN_CFG(0x00B4, 0x0340, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART4_TX_DATA__ECSPI2_SCLK(p) PIN_CFG(0x00B4, 0x0340, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART4_RX_DATA__UART4_RX(p) PIN_CFG(0x00B8, 0x0344, 0x063C, 0x0, 0x1, p) -#define MX6UL_PAD_UART4_RX_DATA__ENET2_TDATA03(p) PIN_CFG(0x00B8, 0x0344, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART4_RX_DATA__I2C1_SDA(p) PIN_CFG(0x00B8, 0x0344, 0x05A8, 0x12, 0x2, p) -#define MX6UL_PAD_UART4_RX_DATA__CSI_DATA13(p) PIN_CFG(0x00B8, 0x0344, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART4_RX_DATA__CSU_CSU_ALARM_AUT01(p) PIN_CFG(0x00B8, 0x0344, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART4_RX_DATA__GPIO1_IO29(p) PIN_CFG(0x00B8, 0x0344, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART4_RX_DATA__ECSPI2_SS0(p) PIN_CFG(0x00B8, 0x0344, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30(p) PIN_CFG(0x00BC, 0x0348, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART5_TX_DATA__ECSPI2_MOSI(p) PIN_CFG(0x00BC, 0x0348, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_UART5_TX_DATA__UART5_TX(p) PIN_CFG(0x00BC, 0x0348, 0x0644, 0x0, 0x4, p) -#define MX6UL_PAD_UART5_TX_DATA__ENET2_CRS(p) PIN_CFG(0x00BC, 0x0348, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART5_TX_DATA__I2C2_SCL(p) PIN_CFG(0x00BC, 0x0348, 0x05AC, 0x12, 0x2, p) -#define MX6UL_PAD_UART5_TX_DATA__CSI_DATA14(p) PIN_CFG(0x00BC, 0x0348, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART5_TX_DATA__CSU_CSU_ALARM_AUT00(p) PIN_CFG(0x00BC, 0x0348, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART5_RX_DATA__UART5_RX(p) PIN_CFG(0x00C0, 0x034C, 0x0644, 0x0, 0x5, p) -#define MX6UL_PAD_UART5_RX_DATA__ENET2_COL(p) PIN_CFG(0x00C0, 0x034C, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_UART5_RX_DATA__I2C2_SDA(p) PIN_CFG(0x00C0, 0x034C, 0x05B0, 0x12, 0x2, p) -#define MX6UL_PAD_UART5_RX_DATA__CSI_DATA15(p) PIN_CFG(0x00C0, 0x034C, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_UART5_RX_DATA__CSU_CSU_INT_DEB(p) PIN_CFG(0x00C0, 0x034C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_UART5_RX_DATA__GPIO1_IO31(p) PIN_CFG(0x00C0, 0x034C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_UART5_RX_DATA__ECSPI2_MISO(p) PIN_CFG(0x00C0, 0x034C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00(p) PIN_CFG(0x00C4, 0x0350, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA0__UART4_DCE_RTS(p) PIN_CFG(0x00C4, 0x0350, 0x0638, 0x1, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA0__UART4_DTE_CTS(p) PIN_CFG(0x00C4, 0x0350, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA0__PWM1_OUT(p) PIN_CFG(0x00C4, 0x0350, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA0__CSI_DATA16(p) PIN_CFG(0x00C4, 0x0350, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA0__FLEXCAN1_TX(p) PIN_CFG(0x00C4, 0x0350, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA0__GPIO2_IO00(p) PIN_CFG(0x00C4, 0x0350, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA0__KPP_ROW00(p) PIN_CFG(0x00C4, 0x0350, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA0__USDHC1_LCTL(p) PIN_CFG(0x00C4, 0x0350, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01(p) PIN_CFG(0x00C8, 0x0354, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA1__UART4_DCE_CTS(p) PIN_CFG(0x00C8, 0x0354, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA1__UART4_DTE_RTS(p) PIN_CFG(0x00C8, 0x0354, 0x0638, 0x1, 0x1, p) -#define MX6UL_PAD_ENET1_RX_DATA1__PWM2_OUT(p) PIN_CFG(0x00C8, 0x0354, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA1__CSI_DATA17(p) PIN_CFG(0x00C8, 0x0354, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA1__FLEXCAN1_RX(p) PIN_CFG(0x00C8, 0x0354, 0x0584, 0x4, 0x1, p) -#define MX6UL_PAD_ENET1_RX_DATA1__GPIO2_IO01(p) PIN_CFG(0x00C8, 0x0354, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA1__KPP_COL00(p) PIN_CFG(0x00C8, 0x0354, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET1_RX_DATA1__USDHC2_LCTL(p) PIN_CFG(0x00C8, 0x0354, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN(p) PIN_CFG(0x00CC, 0x0358, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET1_RX_EN__UART5_DCE_RTS(p) PIN_CFG(0x00CC, 0x0358, 0x0640, 0x1, 0x3, p) -#define MX6UL_PAD_ENET1_RX_EN__UART5_DTE_CTS(p) PIN_CFG(0x00CC, 0x0358, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_ENET1_RX_EN__CSI_DATA18(p) PIN_CFG(0x00CC, 0x0358, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_ENET1_RX_EN__FLEXCAN2_TX(p) PIN_CFG(0x00CC, 0x0358, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_ENET1_RX_EN__GPIO2_IO02(p) PIN_CFG(0x00CC, 0x0358, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET1_RX_EN__KPP_ROW01(p) PIN_CFG(0x00CC, 0x0358, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET1_RX_EN__USDHC1_VSELECT(p) PIN_CFG(0x00CC, 0x0358, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00(p) PIN_CFG(0x00D0, 0x035C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA0__UART5_DCE_CTS(p) PIN_CFG(0x00D0, 0x035C, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA0__UART5_DTE_RTS(p) PIN_CFG(0x00D0, 0x035C, 0x0640, 0x1, 0x4, p) -#define MX6UL_PAD_ENET1_TX_DATA0__CSI_DATA19(p) PIN_CFG(0x00D0, 0x035C, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA0__FLEXCAN2_RX(p) PIN_CFG(0x00D0, 0x035C, 0x0588, 0x4, 0x1, p) -#define MX6UL_PAD_ENET1_TX_DATA0__GPIO2_IO03(p) PIN_CFG(0x00D0, 0x035C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA0__KPP_COL01(p) PIN_CFG(0x00D0, 0x035C, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA0__USDHC2_VSELECT(p) PIN_CFG(0x00D0, 0x035C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01(p) PIN_CFG(0x00D4, 0x0360, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA1__UART6_DCE_CTS(p) PIN_CFG(0x00D4, 0x0360, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA1__UART6_DTE_RTS(p) PIN_CFG(0x00D4, 0x0360, 0x0648, 0x1, 0x2, p) -#define MX6UL_PAD_ENET1_TX_DATA1__PWM5_OUT(p) PIN_CFG(0x00D4, 0x0360, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA1__CSI_DATA20(p) PIN_CFG(0x00D4, 0x0360, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA1__ENET2_MDIO(p) PIN_CFG(0x00D4, 0x0360, 0x0580, 0x4, 0x1, p) -#define MX6UL_PAD_ENET1_TX_DATA1__GPIO2_IO04(p) PIN_CFG(0x00D4, 0x0360, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA1__KPP_ROW02(p) PIN_CFG(0x00D4, 0x0360, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET1_TX_DATA1__WDOG1_WDOG_RST_B_DEB(p) PIN_CFG(0x00D4, 0x0360, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN(p) PIN_CFG(0x00D8, 0x0364, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET1_TX_EN__UART6_DCE_RTS(p) PIN_CFG(0x00D8, 0x0364, 0x0648, 0x1, 0x3, p) -#define MX6UL_PAD_ENET1_TX_EN__UART6_DTE_CTS(p) PIN_CFG(0x00D8, 0x0364, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_ENET1_TX_EN__PWM6_OUT(p) PIN_CFG(0x00D8, 0x0364, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET1_TX_EN__CSI_DATA21(p) PIN_CFG(0x00D8, 0x0364, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_ENET1_TX_EN__ENET2_MDC(p) PIN_CFG(0x00D8, 0x0364, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_ENET1_TX_EN__GPIO2_IO05(p) PIN_CFG(0x00D8, 0x0364, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET1_TX_EN__KPP_COL02(p) PIN_CFG(0x00D8, 0x0364, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET1_TX_EN__WDOG2_WDOG_RST_B_DEB(p) PIN_CFG(0x00D8, 0x0364, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET1_TX_CLK__ENET1_TX_CLK(p) PIN_CFG(0x00DC, 0x0368, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET1_TX_CLK__UART7_DCE_CTS(p) PIN_CFG(0x00DC, 0x0368, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_ENET1_TX_CLK__UART7_DTE_RTS(p) PIN_CFG(0x00DC, 0x0368, 0x0650, 0x1, 0x0, p) -#define MX6UL_PAD_ENET1_TX_CLK__PWM7_OUT(p) PIN_CFG(0x00DC, 0x0368, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET1_TX_CLK__CSI_DATA22(p) PIN_CFG(0x00DC, 0x0368, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1(p) PIN_CFG(0x00DC, 0x0368, 0x0574, 0x14, 0x2, p) -#define MX6UL_PAD_ENET1_TX_CLK__GPIO2_IO06(p) PIN_CFG(0x00DC, 0x0368, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET1_TX_CLK__KPP_ROW03(p) PIN_CFG(0x00DC, 0x0368, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET1_TX_CLK__GPT1_CLK(p) PIN_CFG(0x00DC, 0x0368, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER(p) PIN_CFG(0x00E0, 0x036C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET1_RX_ER__UART7_DCE_RTS(p) PIN_CFG(0x00E0, 0x036C, 0x0650, 0x1, 0x1, p) -#define MX6UL_PAD_ENET1_RX_ER__UART7_DTE_CTS(p) PIN_CFG(0x00E0, 0x036C, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_ENET1_RX_ER__PWM8_OUT(p) PIN_CFG(0x00E0, 0x036C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET1_RX_ER__CSI_DATA23(p) PIN_CFG(0x00E0, 0x036C, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_ENET1_RX_ER__EIM_CRE(p) PIN_CFG(0x00E0, 0x036C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_ENET1_RX_ER__GPIO2_IO07(p) PIN_CFG(0x00E0, 0x036C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET1_RX_ER__KPP_COL03(p) PIN_CFG(0x00E0, 0x036C, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET1_RX_ER__GPT1_CAPTURE2(p) PIN_CFG(0x00E0, 0x036C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00(p) PIN_CFG(0x00E4, 0x0370, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET2_RX_DATA0__UART6_TX(p) PIN_CFG(0x00E4, 0x0370, 0x064C, 0x1, 0x1, p) -#define MX6UL_PAD_ENET2_RX_DATA0__SIM1_PORT0_TRXD(p) PIN_CFG(0x00E4, 0x0370, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET2_RX_DATA0__I2C3_SCL(p) PIN_CFG(0x00E4, 0x0370, 0x05B4, 0x3, 0x1, p) -#define MX6UL_PAD_ENET2_RX_DATA0__ENET1_MDIO(p) PIN_CFG(0x00E4, 0x0370, 0x0578, 0x4, 0x1, p) -#define MX6UL_PAD_ENET2_RX_DATA0__GPIO2_IO08(p) PIN_CFG(0x00E4, 0x0370, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET2_RX_DATA0__KPP_ROW04(p) PIN_CFG(0x00E4, 0x0370, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET2_RX_DATA0__USB_OTG1_PWR(p) PIN_CFG(0x00E4, 0x0370, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01(p) PIN_CFG(0x00E8, 0x0374, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET2_RX_DATA1__UART6_RX(p) PIN_CFG(0x00E8, 0x0374, 0x064C, 0x1, 0x2, p) -#define MX6UL_PAD_ENET2_RX_DATA1__SIM1_PORT0_CLK(p) PIN_CFG(0x00E8, 0x0374, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET2_RX_DATA1__I2C3_SDA(p) PIN_CFG(0x00E8, 0x0374, 0x05B8, 0x3, 0x1, p) -#define MX6UL_PAD_ENET2_RX_DATA1__ENET1_MDC(p) PIN_CFG(0x00E8, 0x0374, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_ENET2_RX_DATA1__GPIO2_IO09(p) PIN_CFG(0x00E8, 0x0374, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET2_RX_DATA1__KPP_COL04(p) PIN_CFG(0x00E8, 0x0374, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET2_RX_DATA1__USB_OTG1_OC(p) PIN_CFG(0x00E8, 0x0374, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN(p) PIN_CFG(0x00EC, 0x0378, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET2_RX_EN__UART7_TX(p) PIN_CFG(0x00EC, 0x0378, 0x0654, 0x1, 0x0, p) -#define MX6UL_PAD_ENET2_RX_EN__SIM1_PORT0_RST_B(p) PIN_CFG(0x00EC, 0x0378, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET2_RX_EN__I2C4_SCL(p) PIN_CFG(0x00EC, 0x0378, 0x05BC, 0x3, 0x1, p) -#define MX6UL_PAD_ENET2_RX_EN__EIM_ADDR26(p) PIN_CFG(0x00EC, 0x0378, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_ENET2_RX_EN__GPIO2_IO10(p) PIN_CFG(0x00EC, 0x0378, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET2_RX_EN__KPP_ROW05(p) PIN_CFG(0x00EC, 0x0378, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET2_RX_EN__ENET1_REF_CLK_25M(p) PIN_CFG(0x00EC, 0x0378, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00(p) PIN_CFG(0x00F0, 0x037C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA0__UART7_RX(p) PIN_CFG(0x00F0, 0x037C, 0x0654, 0x1, 0x1, p) -#define MX6UL_PAD_ENET2_TX_DATA0__SIM1_PORT0_SVEN(p) PIN_CFG(0x00F0, 0x037C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA0__I2C4_SDA(p) PIN_CFG(0x00F0, 0x037C, 0x05C0, 0x3, 0x1, p) -#define MX6UL_PAD_ENET2_TX_DATA0__EIM_EB_B02(p) PIN_CFG(0x00F0, 0x037C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA0__GPIO2_IO11(p) PIN_CFG(0x00F0, 0x037C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA0__KPP_COL05(p) PIN_CFG(0x00F0, 0x037C, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01(p) PIN_CFG(0x00F4, 0x0380, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA1__UART8_TX(p) PIN_CFG(0x00F4, 0x0380, 0x065C, 0x1, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA1__SIM2_PORT0_TRXD(p) PIN_CFG(0x00F4, 0x0380, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA1__ECSPI4_SCLK(p) PIN_CFG(0x00F4, 0x0380, 0x0564, 0x3, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA1__EIM_EB_B03(p) PIN_CFG(0x00F4, 0x0380, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA1__GPIO2_IO12(p) PIN_CFG(0x00F4, 0x0380, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA1__KPP_ROW06(p) PIN_CFG(0x00F4, 0x0380, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET2_TX_DATA1__USB_OTG2_PWR(p) PIN_CFG(0x00F4, 0x0380, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN(p) PIN_CFG(0x00F8, 0x0384, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET2_TX_EN__UART8_RX(p) PIN_CFG(0x00F8, 0x0384, 0x065C, 0x1, 0x1, p) -#define MX6UL_PAD_ENET2_TX_EN__SIM2_PORT0_CLK(p) PIN_CFG(0x00F8, 0x0384, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET2_TX_EN__ECSPI4_MOSI(p) PIN_CFG(0x00F8, 0x0384, 0x056C, 0x3, 0x0, p) -#define MX6UL_PAD_ENET2_TX_EN__EIM_ACLK_FREERUN(p) PIN_CFG(0x00F8, 0x0384, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_ENET2_TX_EN__GPIO2_IO13(p) PIN_CFG(0x00F8, 0x0384, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET2_TX_EN__KPP_COL06(p) PIN_CFG(0x00F8, 0x0384, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET2_TX_EN__USB_OTG2_OC(p) PIN_CFG(0x00F8, 0x0384, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET2_TX_CLK__ENET2_TX_CLK(p) PIN_CFG(0x00FC, 0x0388, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET2_TX_CLK__UART8_DCE_CTS(p) PIN_CFG(0x00FC, 0x0388, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_ENET2_TX_CLK__UART8_DTE_RTS(p) PIN_CFG(0x00FC, 0x0388, 0x0658, 0x1, 0x0, p) -#define MX6UL_PAD_ENET2_TX_CLK__SIM2_PORT0_RST_B(p) PIN_CFG(0x00FC, 0x0388, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET2_TX_CLK__ECSPI4_MISO(p) PIN_CFG(0x00FC, 0x0388, 0x0568, 0x3, 0x0, p) -#define MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2(p) PIN_CFG(0x00FC, 0x0388, 0x057C, 0x14, 0x2, p) -#define MX6UL_PAD_ENET2_TX_CLK__GPIO2_IO14(p) PIN_CFG(0x00FC, 0x0388, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET2_TX_CLK__KPP_ROW07(p) PIN_CFG(0x00FC, 0x0388, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET2_TX_CLK__ANATOP_OTG2_ID(p) PIN_CFG(0x00FC, 0x0388, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER(p) PIN_CFG(0x0100, 0x038C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_ENET2_RX_ER__UART8_DCE_RTS(p) PIN_CFG(0x0100, 0x038C, 0x0658, 0x1, 0x1, p) -#define MX6UL_PAD_ENET2_RX_ER__UART8_DTE_CTS(p) PIN_CFG(0x0100, 0x038C, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_ENET2_RX_ER__SIM2_PORT0_SVEN(p) PIN_CFG(0x0100, 0x038C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_ENET2_RX_ER__ECSPI4_SS0(p) PIN_CFG(0x0100, 0x038C, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_ENET2_RX_ER__EIM_ADDR25(p) PIN_CFG(0x0100, 0x038C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15(p) PIN_CFG(0x0100, 0x038C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_ENET2_RX_ER__KPP_COL07(p) PIN_CFG(0x0100, 0x038C, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_ENET2_RX_ER__WDOG1_WDOG_ANY(p) PIN_CFG(0x0100, 0x038C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_CLK__LCDIF_CLK(p) PIN_CFG(0x0104, 0x0390, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_CLK__LCDIF_WR_RWN(p) PIN_CFG(0x0104, 0x0390, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_CLK__UART4_TX(p) PIN_CFG(0x0104, 0x0390, 0x063C, 0x2, 0x2, p) -#define MX6UL_PAD_LCD_CLK__SAI3_MCLK(p) PIN_CFG(0x0104, 0x0390, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_CLK__EIM_CS2_B(p) PIN_CFG(0x0104, 0x0390, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_CLK__GPIO3_IO00(p) PIN_CFG(0x0104, 0x0390, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_CLK__WDOG1_WDOG_RST_B_DEB(p) PIN_CFG(0x0104, 0x0390, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE(p) PIN_CFG(0x0108, 0x0394, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_ENABLE__LCDIF_RD_E(p) PIN_CFG(0x0108, 0x0394, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_ENABLE__UART4_RX(p) PIN_CFG(0x0108, 0x0394, 0x063C, 0x2, 0x3, p) -#define MX6UL_PAD_LCD_ENABLE__SAI3_TX_SYNC(p) PIN_CFG(0x0108, 0x0394, 0x060C, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_ENABLE__EIM_CS3_B(p) PIN_CFG(0x0108, 0x0394, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_ENABLE__GPIO3_IO01(p) PIN_CFG(0x0108, 0x0394, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_ENABLE__ECSPI2_RDY(p) PIN_CFG(0x0108, 0x0394, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC(p) PIN_CFG(0x010C, 0x0398, 0x05DC, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_HSYNC__LCDIF_RS(p) PIN_CFG(0x010C, 0x0398, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_HSYNC__UART4_DCE_CTS(p) PIN_CFG(0x010C, 0x0398, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_LCD_HSYNC__UART4_DTE_RTS(p) PIN_CFG(0x010C, 0x0398, 0x0638, 0x2, 0x2, p) -#define MX6UL_PAD_LCD_HSYNC__SAI3_TX_BCLK(p) PIN_CFG(0x010C, 0x0398, 0x0608, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_HSYNC__WDOG3_WDOG_RST_B_DEB(p) PIN_CFG(0x010C, 0x0398, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_HSYNC__GPIO3_IO02(p) PIN_CFG(0x010C, 0x0398, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_HSYNC__ECSPI2_SS1(p) PIN_CFG(0x010C, 0x0398, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC(p) PIN_CFG(0x0110, 0x039C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_VSYNC__LCDIF_BUSY(p) PIN_CFG(0x0110, 0x039C, 0x05DC, 0x1, 0x1, p) -#define MX6UL_PAD_LCD_VSYNC__UART4_DCE_RTS(p) PIN_CFG(0x0110, 0x039C, 0x0638, 0x2, 0x3, p) -#define MX6UL_PAD_LCD_VSYNC__UART4_DTE_CTS(p) PIN_CFG(0x0110, 0x039C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_LCD_VSYNC__SAI3_RX_DATA(p) PIN_CFG(0x0110, 0x039C, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_VSYNC__WDOG2_WDOG_B(p) PIN_CFG(0x0110, 0x039C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_VSYNC__GPIO3_IO03(p) PIN_CFG(0x0110, 0x039C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_VSYNC__ECSPI2_SS2(p) PIN_CFG(0x0110, 0x039C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_RESET__LCDIF_RESET(p) PIN_CFG(0x0114, 0x03A0, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_RESET__LCDIF_CS(p) PIN_CFG(0x0114, 0x03A0, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_RESET__CA7_MX6UL_EVENTI(p) PIN_CFG(0x0114, 0x03A0, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_LCD_RESET__SAI3_TX_DATA(p) PIN_CFG(0x0114, 0x03A0, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY(p) PIN_CFG(0x0114, 0x03A0, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_RESET__GPIO3_IO04(p) PIN_CFG(0x0114, 0x03A0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_RESET__ECSPI2_SS3(p) PIN_CFG(0x0114, 0x03A0, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA00__LCDIF_DATA00(p) PIN_CFG(0x0118, 0x03A4, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA00__PWM1_OUT(p) PIN_CFG(0x0118, 0x03A4, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA00__ENET1_1588_EVENT2_IN(p) PIN_CFG(0x0118, 0x03A4, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA00__I2C3_SDA(p) PIN_CFG(0x0118, 0x03A4, 0x05B8, 0x4, 0x2, p) -#define MX6UL_PAD_LCD_DATA00__GPIO3_IO05(p) PIN_CFG(0x0118, 0x03A4, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA00__SRC_BT_CFG00(p) PIN_CFG(0x0118, 0x03A4, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA00__SAI1_MCLK(p) PIN_CFG(0x0118, 0x03A4, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA01__LCDIF_DATA01(p) PIN_CFG(0x011C, 0x03A8, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA01__PWM2_OUT(p) PIN_CFG(0x011C, 0x03A8, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA01__ENET1_1588_EVENT2_OUT(p) PIN_CFG(0x011C, 0x03A8, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA01__I2C3_SCL(p) PIN_CFG(0x011C, 0x03A8, 0x05B4, 0x4, 0x2, p) -#define MX6UL_PAD_LCD_DATA01__GPIO3_IO06(p) PIN_CFG(0x011C, 0x03A8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA01__SRC_BT_CFG01(p) PIN_CFG(0x011C, 0x03A8, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA01__SAI1_TX_SYNC(p) PIN_CFG(0x011C, 0x03A8, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA02__LCDIF_DATA02(p) PIN_CFG(0x0120, 0x03AC, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA02__PWM3_OUT(p) PIN_CFG(0x0120, 0x03AC, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA02__ENET1_1588_EVENT3_IN(p) PIN_CFG(0x0120, 0x03AC, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA02__I2C4_SDA(p) PIN_CFG(0x0120, 0x03AC, 0x05C0, 0x4, 0x2, p) -#define MX6UL_PAD_LCD_DATA02__GPIO3_IO07(p) PIN_CFG(0x0120, 0x03AC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA02__SRC_BT_CFG02(p) PIN_CFG(0x0120, 0x03AC, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA02__SAI1_TX_BCLK(p) PIN_CFG(0x0120, 0x03AC, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA03__LCDIF_DATA03(p) PIN_CFG(0x0124, 0x03B0, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA03__PWM4_OUT(p) PIN_CFG(0x0124, 0x03B0, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA03__ENET1_1588_EVENT3_OUT(p) PIN_CFG(0x0124, 0x03B0, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA03__I2C4_SCL(p) PIN_CFG(0x0124, 0x03B0, 0x05BC, 0x4, 0x2, p) -#define MX6UL_PAD_LCD_DATA03__GPIO3_IO08(p) PIN_CFG(0x0124, 0x03B0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA03__SRC_BT_CFG03(p) PIN_CFG(0x0124, 0x03B0, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA03__SAI1_RX_DATA(p) PIN_CFG(0x0124, 0x03B0, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA04__LCDIF_DATA04(p) PIN_CFG(0x0128, 0x03B4, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA04__UART8_DCE_CTS(p) PIN_CFG(0x0128, 0x03B4, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA04__UART8_DTE_RTS(p) PIN_CFG(0x0128, 0x03B4, 0x0658, 0x1, 0x2, p) -#define MX6UL_PAD_LCD_DATA04__ENET2_1588_EVENT2_IN(p) PIN_CFG(0x0128, 0x03B4, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA04__SPDIF_SR_CLK(p) PIN_CFG(0x0128, 0x03B4, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA04__GPIO3_IO09(p) PIN_CFG(0x0128, 0x03B4, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA04__SRC_BT_CFG04(p) PIN_CFG(0x0128, 0x03B4, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA04__SAI1_TX_DATA(p) PIN_CFG(0x0128, 0x03B4, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA05__LCDIF_DATA05(p) PIN_CFG(0x012C, 0x03B8, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA05__UART8_DCE_RTS(p) PIN_CFG(0x012C, 0x03B8, 0x0658, 0x1, 0x3, p) -#define MX6UL_PAD_LCD_DATA05__UART8_DTE_CTS(p) PIN_CFG(0x012C, 0x03B8, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA05__ENET2_1588_EVENT2_OUT(p) PIN_CFG(0x012C, 0x03B8, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA05__SPDIF_OUT(p) PIN_CFG(0x012C, 0x03B8, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA05__GPIO3_IO10(p) PIN_CFG(0x012C, 0x03B8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA05__SRC_BT_CFG05(p) PIN_CFG(0x012C, 0x03B8, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA05__ECSPI1_SS1(p) PIN_CFG(0x012C, 0x03B8, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA06__LCDIF_DATA06(p) PIN_CFG(0x0130, 0x03BC, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA06__UART7_DCE_CTS(p) PIN_CFG(0x0130, 0x03BC, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA06__UART7_DTE_RTS(p) PIN_CFG(0x0130, 0x03BC, 0x0650, 0x1, 0x2, p) -#define MX6UL_PAD_LCD_DATA06__ENET2_1588_EVENT3_IN(p) PIN_CFG(0x0130, 0x03BC, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA06__SPDIF_LOCK(p) PIN_CFG(0x0130, 0x03BC, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA06__GPIO3_IO11(p) PIN_CFG(0x0130, 0x03BC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA06__SRC_BT_CFG06(p) PIN_CFG(0x0130, 0x03BC, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA06__ECSPI1_SS2(p) PIN_CFG(0x0130, 0x03BC, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA07__LCDIF_DATA07(p) PIN_CFG(0x0134, 0x03C0, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA07__UART7_DCE_RTS(p) PIN_CFG(0x0134, 0x03C0, 0x0650, 0x1, 0x3, p) -#define MX6UL_PAD_LCD_DATA07__UART7_DTE_CTS(p) PIN_CFG(0x0134, 0x03C0, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA07__ENET2_1588_EVENT3_OUT(p) PIN_CFG(0x0134, 0x03C0, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA07__SPDIF_EXT_CLK(p) PIN_CFG(0x0134, 0x03C0, 0x061C, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA07__GPIO3_IO12(p) PIN_CFG(0x0134, 0x03C0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA07__SRC_BT_CFG07(p) PIN_CFG(0x0134, 0x03C0, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA07__ECSPI1_SS3(p) PIN_CFG(0x0134, 0x03C0, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA08__LCDIF_DATA08(p) PIN_CFG(0x0138, 0x03C4, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA08__SPDIF_IN(p) PIN_CFG(0x0138, 0x03C4, 0x0618, 0x1, 0x2, p) -#define MX6UL_PAD_LCD_DATA08__CSI_DATA16(p) PIN_CFG(0x0138, 0x03C4, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA08__EIM_DATA00(p) PIN_CFG(0x0138, 0x03C4, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA08__GPIO3_IO13(p) PIN_CFG(0x0138, 0x03C4, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA08__SRC_BT_CFG08(p) PIN_CFG(0x0138, 0x03C4, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA08__FLEXCAN1_TX(p) PIN_CFG(0x0138, 0x03C4, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA09__LCDIF_DATA09(p) PIN_CFG(0x013C, 0x03C8, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA09__SAI3_MCLK(p) PIN_CFG(0x013C, 0x03C8, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA09__CSI_DATA17(p) PIN_CFG(0x013C, 0x03C8, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA09__EIM_DATA01(p) PIN_CFG(0x013C, 0x03C8, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA09__GPIO3_IO14(p) PIN_CFG(0x013C, 0x03C8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA09__SRC_BT_CFG09(p) PIN_CFG(0x013C, 0x03C8, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA09__FLEXCAN1_RX(p) PIN_CFG(0x013C, 0x03C8, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA10__LCDIF_DATA10(p) PIN_CFG(0x0140, 0x03CC, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA10__SAI3_RX_SYNC(p) PIN_CFG(0x0140, 0x03CC, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA10__CSI_DATA18(p) PIN_CFG(0x0140, 0x03CC, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA10__EIM_DATA02(p) PIN_CFG(0x0140, 0x03CC, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA10__GPIO3_IO15(p) PIN_CFG(0x0140, 0x03CC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA10__SRC_BT_CFG10(p) PIN_CFG(0x0140, 0x03CC, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA10__FLEXCAN2_TX(p) PIN_CFG(0x0140, 0x03CC, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA11__LCDIF_DATA11(p) PIN_CFG(0x0144, 0x03D0, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA11__SAI3_RX_BCLK(p) PIN_CFG(0x0144, 0x03D0, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA11__CSI_DATA19(p) PIN_CFG(0x0144, 0x03D0, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA11__EIM_DATA03(p) PIN_CFG(0x0144, 0x03D0, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA11__GPIO3_IO16(p) PIN_CFG(0x0144, 0x03D0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA11__SRC_BT_CFG11(p) PIN_CFG(0x0144, 0x03D0, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA11__FLEXCAN2_RX(p) PIN_CFG(0x0144, 0x03D0, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA12__LCDIF_DATA12(p) PIN_CFG(0x0148, 0x03D4, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA12__SAI3_TX_SYNC(p) PIN_CFG(0x0148, 0x03D4, 0x060C, 0x1, 0x1, p) -#define MX6UL_PAD_LCD_DATA12__CSI_DATA20(p) PIN_CFG(0x0148, 0x03D4, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA12__EIM_DATA04(p) PIN_CFG(0x0148, 0x03D4, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA12__GPIO3_IO17(p) PIN_CFG(0x0148, 0x03D4, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA12__SRC_BT_CFG12(p) PIN_CFG(0x0148, 0x03D4, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA12__ECSPI1_RDY(p) PIN_CFG(0x0148, 0x03D4, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA13__LCDIF_DATA13(p) PIN_CFG(0x014C, 0x03D8, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA13__SAI3_TX_BCLK(p) PIN_CFG(0x014C, 0x03D8, 0x0608, 0x1, 0x1, p) -#define MX6UL_PAD_LCD_DATA13__CSI_DATA21(p) PIN_CFG(0x014C, 0x03D8, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA13__EIM_DATA05(p) PIN_CFG(0x014C, 0x03D8, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA13__GPIO3_IO18(p) PIN_CFG(0x014C, 0x03D8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA13__SRC_BT_CFG13(p) PIN_CFG(0x014C, 0x03D8, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA13__USDHC2_RESET_B(p) PIN_CFG(0x014C, 0x03D8, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA14__LCDIF_DATA14(p) PIN_CFG(0x0150, 0x03DC, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA14__SAI3_RX_DATA(p) PIN_CFG(0x0150, 0x03DC, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA14__CSI_DATA22(p) PIN_CFG(0x0150, 0x03DC, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA14__EIM_DATA06(p) PIN_CFG(0x0150, 0x03DC, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA14__GPIO3_IO19(p) PIN_CFG(0x0150, 0x03DC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA14__SRC_BT_CFG14(p) PIN_CFG(0x0150, 0x03DC, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA14__USDHC2_DATA4(p) PIN_CFG(0x0150, 0x03DC, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA15__LCDIF_DATA15(p) PIN_CFG(0x0154, 0x03E0, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA15__SAI3_TX_DATA(p) PIN_CFG(0x0154, 0x03E0, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA15__CSI_DATA23(p) PIN_CFG(0x0154, 0x03E0, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA15__EIM_DATA07(p) PIN_CFG(0x0154, 0x03E0, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA15__GPIO3_IO20(p) PIN_CFG(0x0154, 0x03E0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA15__SRC_BT_CFG15(p) PIN_CFG(0x0154, 0x03E0, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA15__USDHC2_DATA5(p) PIN_CFG(0x0154, 0x03E0, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA16__LCDIF_DATA16(p) PIN_CFG(0x0158, 0x03E4, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA16__UART7_TX(p) PIN_CFG(0x0158, 0x03E4, 0x0654, 0x1, 0x2, p) -#define MX6UL_PAD_LCD_DATA16__CSI_DATA01(p) PIN_CFG(0x0158, 0x03E4, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA16__EIM_DATA08(p) PIN_CFG(0x0158, 0x03E4, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA16__GPIO3_IO21(p) PIN_CFG(0x0158, 0x03E4, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA16__SRC_BT_CFG24(p) PIN_CFG(0x0158, 0x03E4, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA16__USDHC2_DATA6(p) PIN_CFG(0x0158, 0x03E4, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA17__LCDIF_DATA17(p) PIN_CFG(0x015C, 0x03E8, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA17__UART7_RX(p) PIN_CFG(0x015C, 0x03E8, 0x0654, 0x1, 0x3, p) -#define MX6UL_PAD_LCD_DATA17__CSI_DATA00(p) PIN_CFG(0x015C, 0x03E8, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA17__EIM_DATA09(p) PIN_CFG(0x015C, 0x03E8, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA17__GPIO3_IO22(p) PIN_CFG(0x015C, 0x03E8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA17__SRC_BT_CFG25(p) PIN_CFG(0x015C, 0x03E8, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA17__USDHC2_DATA7(p) PIN_CFG(0x015C, 0x03E8, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA18__LCDIF_DATA18(p) PIN_CFG(0x0160, 0x03EC, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA18__PWM5_OUT(p) PIN_CFG(0x0160, 0x03EC, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA18__CA7_MX6UL_EVENTO(p) PIN_CFG(0x0160, 0x03EC, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_LCD_DATA18__CSI_DATA10(p) PIN_CFG(0x0160, 0x03EC, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA18__EIM_DATA10(p) PIN_CFG(0x0160, 0x03EC, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA18__GPIO3_IO23(p) PIN_CFG(0x0160, 0x03EC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA18__SRC_BT_CFG26(p) PIN_CFG(0x0160, 0x03EC, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA18__USDHC2_CMD(p) PIN_CFG(0x0160, 0x03EC, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA19__EIM_DATA11(p) PIN_CFG(0x0164, 0x03F0, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA19__GPIO3_IO24(p) PIN_CFG(0x0164, 0x03F0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA19__SRC_BT_CFG27(p) PIN_CFG(0x0164, 0x03F0, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA19__USDHC2_CLK(p) PIN_CFG(0x0164, 0x03F0, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA19__LCDIF_DATA19(p) PIN_CFG(0x0164, 0x03F0, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA19__PWM6_OUT(p) PIN_CFG(0x0164, 0x03F0, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA19__WDOG1_WDOG_ANY(p) PIN_CFG(0x0164, 0x03F0, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_LCD_DATA19__CSI_DATA11(p) PIN_CFG(0x0164, 0x03F0, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA20__EIM_DATA12(p) PIN_CFG(0x0168, 0x03F4, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA20__GPIO3_IO25(p) PIN_CFG(0x0168, 0x03F4, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA20__SRC_BT_CFG28(p) PIN_CFG(0x0168, 0x03F4, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA20__USDHC2_DATA0(p) PIN_CFG(0x0168, 0x03F4, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA20__LCDIF_DATA20(p) PIN_CFG(0x0168, 0x03F4, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA20__UART8_TX(p) PIN_CFG(0x0168, 0x03F4, 0x065C, 0x1, 0x2, p) -#define MX6UL_PAD_LCD_DATA20__ECSPI1_SCLK(p) PIN_CFG(0x0168, 0x03F4, 0x0534, 0x2, 0x0, p) -#define MX6UL_PAD_LCD_DATA20__CSI_DATA12(p) PIN_CFG(0x0168, 0x03F4, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA21__LCDIF_DATA21(p) PIN_CFG(0x016C, 0x03F8, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA21__UART8_RX(p) PIN_CFG(0x016C, 0x03F8, 0x065C, 0x1, 0x3, p) -#define MX6UL_PAD_LCD_DATA21__ECSPI1_SS0(p) PIN_CFG(0x016C, 0x03F8, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_LCD_DATA21__CSI_DATA13(p) PIN_CFG(0x016C, 0x03F8, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA21__EIM_DATA13(p) PIN_CFG(0x016C, 0x03F8, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA21__GPIO3_IO26(p) PIN_CFG(0x016C, 0x03F8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA21__SRC_BT_CFG29(p) PIN_CFG(0x016C, 0x03F8, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA21__USDHC2_DATA1(p) PIN_CFG(0x016C, 0x03F8, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA22__LCDIF_DATA22(p) PIN_CFG(0x0170, 0x03FC, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA22__MQS_RIGHT(p) PIN_CFG(0x0170, 0x03FC, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA22__ECSPI1_MOSI(p) PIN_CFG(0x0170, 0x03FC, 0x053C, 0x2, 0x0, p) -#define MX6UL_PAD_LCD_DATA22__CSI_DATA14(p) PIN_CFG(0x0170, 0x03FC, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA22__EIM_DATA14(p) PIN_CFG(0x0170, 0x03FC, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA22__GPIO3_IO27(p) PIN_CFG(0x0170, 0x03FC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA22__SRC_BT_CFG30(p) PIN_CFG(0x0170, 0x03FC, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA22__USDHC2_DATA2(p) PIN_CFG(0x0170, 0x03FC, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_LCD_DATA23__LCDIF_DATA23(p) PIN_CFG(0x0174, 0x0400, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_LCD_DATA23__MQS_LEFT(p) PIN_CFG(0x0174, 0x0400, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_LCD_DATA23__ECSPI1_MISO(p) PIN_CFG(0x0174, 0x0400, 0x0538, 0x2, 0x0, p) -#define MX6UL_PAD_LCD_DATA23__CSI_DATA15(p) PIN_CFG(0x0174, 0x0400, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_LCD_DATA23__EIM_DATA15(p) PIN_CFG(0x0174, 0x0400, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_LCD_DATA23__GPIO3_IO28(p) PIN_CFG(0x0174, 0x0400, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_LCD_DATA23__SRC_BT_CFG31(p) PIN_CFG(0x0174, 0x0400, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_LCD_DATA23__USDHC2_DATA3(p) PIN_CFG(0x0174, 0x0400, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B(p) PIN_CFG(0x0178, 0x0404, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_RE_B__USDHC2_CLK(p) PIN_CFG(0x0178, 0x0404, 0x0670, 0x1, 0x2, p) -#define MX6UL_PAD_NAND_RE_B__QSPI_B_SCLK(p) PIN_CFG(0x0178, 0x0404, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_RE_B__KPP_ROW00(p) PIN_CFG(0x0178, 0x0404, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_NAND_RE_B__EIM_EB_B00(p) PIN_CFG(0x0178, 0x0404, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_RE_B__GPIO4_IO00(p) PIN_CFG(0x0178, 0x0404, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_RE_B__ECSPI3_SS2(p) PIN_CFG(0x0178, 0x0404, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B(p) PIN_CFG(0x017C, 0x0408, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_WE_B__USDHC2_CMD(p) PIN_CFG(0x017C, 0x0408, 0x0678, 0x1, 0x2, p) -#define MX6UL_PAD_NAND_WE_B__QSPI_B_SS0_B(p) PIN_CFG(0x017C, 0x0408, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_WE_B__KPP_COL00(p) PIN_CFG(0x017C, 0x0408, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_NAND_WE_B__EIM_EB_B01(p) PIN_CFG(0x017C, 0x0408, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_WE_B__GPIO4_IO01(p) PIN_CFG(0x017C, 0x0408, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_WE_B__ECSPI3_SS3(p) PIN_CFG(0x017C, 0x0408, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00(p) PIN_CFG(0x0180, 0x040C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_DATA00__USDHC2_DATA0(p) PIN_CFG(0x0180, 0x040C, 0x067C, 0x1, 0x2, p) -#define MX6UL_PAD_NAND_DATA00__QSPI_B_SS1_B(p) PIN_CFG(0x0180, 0x040C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_DATA00__KPP_ROW01(p) PIN_CFG(0x0180, 0x040C, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_NAND_DATA00__EIM_AD08(p) PIN_CFG(0x0180, 0x040C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_DATA00__GPIO4_IO02(p) PIN_CFG(0x0180, 0x040C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_DATA00__ECSPI4_RDY(p) PIN_CFG(0x0180, 0x040C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01(p) PIN_CFG(0x0184, 0x0410, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_DATA01__USDHC2_DATA1(p) PIN_CFG(0x0184, 0x0410, 0x0680, 0x1, 0x2, p) -#define MX6UL_PAD_NAND_DATA01__QSPI_B_DQS(p) PIN_CFG(0x0184, 0x0410, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_DATA01__KPP_COL01(p) PIN_CFG(0x0184, 0x0410, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_NAND_DATA01__EIM_AD09(p) PIN_CFG(0x0184, 0x0410, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_DATA01__GPIO4_IO03(p) PIN_CFG(0x0184, 0x0410, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_DATA01__ECSPI4_SS1(p) PIN_CFG(0x0184, 0x0410, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02(p) PIN_CFG(0x0188, 0x0414, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_DATA02__USDHC2_DATA2(p) PIN_CFG(0x0188, 0x0414, 0x0684, 0x1, 0x1, p) -#define MX6UL_PAD_NAND_DATA02__QSPI_B_DATA00(p) PIN_CFG(0x0188, 0x0414, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_DATA02__KPP_ROW02(p) PIN_CFG(0x0188, 0x0414, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_NAND_DATA02__EIM_AD10(p) PIN_CFG(0x0188, 0x0414, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_DATA02__GPIO4_IO04(p) PIN_CFG(0x0188, 0x0414, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_DATA02__ECSPI4_SS2(p) PIN_CFG(0x0188, 0x0414, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03(p) PIN_CFG(0x018C, 0x0418, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_DATA03__USDHC2_DATA3(p) PIN_CFG(0x018C, 0x0418, 0x0688, 0x1, 0x2, p) -#define MX6UL_PAD_NAND_DATA03__QSPI_B_DATA01(p) PIN_CFG(0x018C, 0x0418, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_DATA03__KPP_COL02(p) PIN_CFG(0x018C, 0x0418, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_NAND_DATA03__EIM_AD11(p) PIN_CFG(0x018C, 0x0418, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_DATA03__GPIO4_IO05(p) PIN_CFG(0x018C, 0x0418, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_DATA03__ECSPI4_SS3(p) PIN_CFG(0x018C, 0x0418, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04(p) PIN_CFG(0x0190, 0x041C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_DATA04__USDHC2_DATA4(p) PIN_CFG(0x0190, 0x041C, 0x068C, 0x1, 0x1, p) -#define MX6UL_PAD_NAND_DATA04__QSPI_B_DATA02(p) PIN_CFG(0x0190, 0x041C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_DATA04__ECSPI4_SCLK(p) PIN_CFG(0x0190, 0x041C, 0x0564, 0x3, 0x1, p) -#define MX6UL_PAD_NAND_DATA04__EIM_AD12(p) PIN_CFG(0x0190, 0x041C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_DATA04__GPIO4_IO06(p) PIN_CFG(0x0190, 0x041C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_DATA04__UART2_TX(p) PIN_CFG(0x0190, 0x041C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05(p) PIN_CFG(0x0194, 0x0420, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_DATA05__USDHC2_DATA5(p) PIN_CFG(0x0194, 0x0420, 0x0690, 0x1, 0x1, p) -#define MX6UL_PAD_NAND_DATA05__QSPI_B_DATA03(p) PIN_CFG(0x0194, 0x0420, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_DATA05__ECSPI4_MOSI(p) PIN_CFG(0x0194, 0x0420, 0x056C, 0x3, 0x1, p) -#define MX6UL_PAD_NAND_DATA05__EIM_AD13(p) PIN_CFG(0x0194, 0x0420, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_DATA05__GPIO4_IO07(p) PIN_CFG(0x0194, 0x0420, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_DATA05__UART2_RX(p) PIN_CFG(0x0194, 0x0420, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06(p) PIN_CFG(0x0198, 0x0424, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_DATA06__USDHC2_DATA6(p) PIN_CFG(0x0198, 0x0424, 0x0694, 0x1, 0x1, p) -#define MX6UL_PAD_NAND_DATA06__SAI2_RX_BCLK(p) PIN_CFG(0x0198, 0x0424, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_DATA06__ECSPI4_MISO(p) PIN_CFG(0x0198, 0x0424, 0x0568, 0x3, 0x1, p) -#define MX6UL_PAD_NAND_DATA06__EIM_AD14(p) PIN_CFG(0x0198, 0x0424, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_DATA06__GPIO4_IO08(p) PIN_CFG(0x0198, 0x0424, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_DATA06__UART2_DCE_CTS(p) PIN_CFG(0x0198, 0x0424, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_DATA06__UART2_DTE_RTS(p) PIN_CFG(0x0198, 0x0424, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07(p) PIN_CFG(0x019C, 0x0428, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_DATA07__USDHC2_DATA7(p) PIN_CFG(0x019C, 0x0428, 0x0698, 0x1, 0x1, p) -#define MX6UL_PAD_NAND_DATA07__QSPI_A_SS1_B(p) PIN_CFG(0x019C, 0x0428, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_DATA07__ECSPI4_SS0(p) PIN_CFG(0x019C, 0x0428, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_NAND_DATA07__EIM_AD15(p) PIN_CFG(0x019C, 0x0428, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_DATA07__GPIO4_IO09(p) PIN_CFG(0x019C, 0x0428, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_DATA07__UART2_DCE_RTS(p) PIN_CFG(0x019C, 0x0428, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_DATA07__UART2_DTE_CTS(p) PIN_CFG(0x019C, 0x0428, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_ALE__RAWNAND_ALE(p) PIN_CFG(0x01A0, 0x042C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_ALE__USDHC2_RESET_B(p) PIN_CFG(0x01A0, 0x042C, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_NAND_ALE__QSPI_A_DQS(p) PIN_CFG(0x01A0, 0x042C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_ALE__PWM3_OUT(p) PIN_CFG(0x01A0, 0x042C, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_NAND_ALE__EIM_ADDR17(p) PIN_CFG(0x01A0, 0x042C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_ALE__GPIO4_IO10(p) PIN_CFG(0x01A0, 0x042C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_ALE__ECSPI3_SS1(p) PIN_CFG(0x01A0, 0x042C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B(p) PIN_CFG(0x01A4, 0x0430, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_WP_B__USDHC1_RESET_B(p) PIN_CFG(0x01A4, 0x0430, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK(p) PIN_CFG(0x01A4, 0x0430, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_WP_B__PWM4_OUT(p) PIN_CFG(0x01A4, 0x0430, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_NAND_WP_B__EIM_BCLK(p) PIN_CFG(0x01A4, 0x0430, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_WP_B__GPIO4_IO11(p) PIN_CFG(0x01A4, 0x0430, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_WP_B__ECSPI3_RDY(p) PIN_CFG(0x01A4, 0x0430, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B(p) PIN_CFG(0x01A8, 0x0434, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_READY_B__USDHC1_DATA4(p) PIN_CFG(0x01A8, 0x0434, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00(p) PIN_CFG(0x01A8, 0x0434, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_READY_B__ECSPI3_SS0(p) PIN_CFG(0x01A8, 0x0434, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_NAND_READY_B__EIM_CS1_B(p) PIN_CFG(0x01A8, 0x0434, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_READY_B__GPIO4_IO12(p) PIN_CFG(0x01A8, 0x0434, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_READY_B__UART3_TX(p) PIN_CFG(0x01A8, 0x0434, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B(p) PIN_CFG(0x01AC, 0x0438, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5(p) PIN_CFG(0x01AC, 0x0438, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01(p) PIN_CFG(0x01AC, 0x0438, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_CE0_B__ECSPI3_SCLK(p) PIN_CFG(0x01AC, 0x0438, 0x0554, 0x3, 0x1, p) -#define MX6UL_PAD_NAND_CE0_B__EIM_DTACK_B(p) PIN_CFG(0x01AC, 0x0438, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_CE0_B__GPIO4_IO13(p) PIN_CFG(0x01AC, 0x0438, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_CE0_B__UART3_RX(p) PIN_CFG(0x01AC, 0x0438, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_CE1_B__RAWNAND_CE1_B(p) PIN_CFG(0x01B0, 0x043C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6(p) PIN_CFG(0x01B0, 0x043C, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02(p) PIN_CFG(0x01B0, 0x043C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_CE1_B__ECSPI3_MOSI(p) PIN_CFG(0x01B0, 0x043C, 0x055C, 0x3, 0x1, p) -#define MX6UL_PAD_NAND_CE1_B__EIM_ADDR18(p) PIN_CFG(0x01B0, 0x043C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_CE1_B__GPIO4_IO14(p) PIN_CFG(0x01B0, 0x043C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_CE1_B__UART3_DCE_CTS(p) PIN_CFG(0x01B0, 0x043C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_CE1_B__UART3_DTE_RTS(p) PIN_CFG(0x01B0, 0x043C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_CLE__RAWNAND_CLE(p) PIN_CFG(0x01B4, 0x0440, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_CLE__USDHC1_DATA7(p) PIN_CFG(0x01B4, 0x0440, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_NAND_CLE__QSPI_A_DATA03(p) PIN_CFG(0x01B4, 0x0440, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_CLE__ECSPI3_MISO(p) PIN_CFG(0x01B4, 0x0440, 0x0558, 0x3, 0x1, p) -#define MX6UL_PAD_NAND_CLE__EIM_ADDR16(p) PIN_CFG(0x01B4, 0x0440, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_CLE__GPIO4_IO15(p) PIN_CFG(0x01B4, 0x0440, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_CLE__UART3_DCE_RTS(p) PIN_CFG(0x01B4, 0x0440, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_CLE__UART3_DTE_CTS(p) PIN_CFG(0x01B4, 0x0440, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_NAND_DQS__RAWNAND_DQS(p) PIN_CFG(0x01B8, 0x0444, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_NAND_DQS__CSI_FIELD(p) PIN_CFG(0x01B8, 0x0444, 0x0530, 0x1, 0x1, p) -#define MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B(p) PIN_CFG(0x01B8, 0x0444, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_NAND_DQS__PWM5_OUT(p) PIN_CFG(0x01B8, 0x0444, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_NAND_DQS__EIM_WAIT(p) PIN_CFG(0x01B8, 0x0444, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_NAND_DQS__GPIO4_IO16(p) PIN_CFG(0x01B8, 0x0444, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_NAND_DQS__SDMA_EXT_EVENT01(p) PIN_CFG(0x01B8, 0x0444, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_NAND_DQS__SPDIF_EXT_CLK(p) PIN_CFG(0x01B8, 0x0444, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_SD1_CMD__USDHC1_CMD(p) PIN_CFG(0x01BC, 0x0448, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_SD1_CMD__GPT2_COMPARE1(p) PIN_CFG(0x01BC, 0x0448, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_SD1_CMD__SAI2_RX_SYNC(p) PIN_CFG(0x01BC, 0x0448, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_SD1_CMD__SPDIF_OUT(p) PIN_CFG(0x01BC, 0x0448, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_SD1_CMD__EIM_ADDR19(p) PIN_CFG(0x01BC, 0x0448, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_SD1_CMD__GPIO2_IO16(p) PIN_CFG(0x01BC, 0x0448, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SD1_CMD__SDMA_EXT_EVENT00(p) PIN_CFG(0x01BC, 0x0448, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_SD1_CMD__USB_OTG1_PWR(p) PIN_CFG(0x01BC, 0x0448, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_SD1_CLK__USDHC1_CLK(p) PIN_CFG(0x01C0, 0x044C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_SD1_CLK__GPT2_COMPARE2(p) PIN_CFG(0x01C0, 0x044C, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_SD1_CLK__SAI2_MCLK(p) PIN_CFG(0x01C0, 0x044C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_SD1_CLK__SPDIF_IN(p) PIN_CFG(0x01C0, 0x044C, 0x0618, 0x3, 0x3, p) -#define MX6UL_PAD_SD1_CLK__EIM_ADDR20(p) PIN_CFG(0x01C0, 0x044C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_SD1_CLK__GPIO2_IO17(p) PIN_CFG(0x01C0, 0x044C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SD1_CLK__USB_OTG1_OC(p) PIN_CFG(0x01C0, 0x044C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_SD1_DATA0__USDHC1_DATA0(p) PIN_CFG(0x01C4, 0x0450, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_SD1_DATA0__GPT2_COMPARE3(p) PIN_CFG(0x01C4, 0x0450, 0x0000, 0x1, 0x0, p) -#define MX6UL_PAD_SD1_DATA0__SAI2_TX_SYNC(p) PIN_CFG(0x01C4, 0x0450, 0x05FC, 0x2, 0x1, p) -#define MX6UL_PAD_SD1_DATA0__FLEXCAN1_TX(p) PIN_CFG(0x01C4, 0x0450, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_SD1_DATA0__EIM_ADDR21(p) PIN_CFG(0x01C4, 0x0450, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_SD1_DATA0__GPIO2_IO18(p) PIN_CFG(0x01C4, 0x0450, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SD1_DATA0__ANATOP_OTG1_ID(p) PIN_CFG(0x01C4, 0x0450, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_SD1_DATA1__USDHC1_DATA1(p) PIN_CFG(0x01C8, 0x0454, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_SD1_DATA1__GPT2_CLK(p) PIN_CFG(0x01C8, 0x0454, 0x05A0, 0x1, 0x1, p) -#define MX6UL_PAD_SD1_DATA1__SAI2_TX_BCLK(p) PIN_CFG(0x01C8, 0x0454, 0x05F8, 0x2, 0x1, p) -#define MX6UL_PAD_SD1_DATA1__FLEXCAN1_RX(p) PIN_CFG(0x01C8, 0x0454, 0x0584, 0x3, 0x3, p) -#define MX6UL_PAD_SD1_DATA1__EIM_ADDR22(p) PIN_CFG(0x01C8, 0x0454, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_SD1_DATA1__GPIO2_IO19(p) PIN_CFG(0x01C8, 0x0454, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SD1_DATA1__USB_OTG2_PWR(p) PIN_CFG(0x01C8, 0x0454, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_SD1_DATA2__USDHC1_DATA2(p) PIN_CFG(0x01CC, 0x0458, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_SD1_DATA2__GPT2_CAPTURE1(p) PIN_CFG(0x01CC, 0x0458, 0x0598, 0x1, 0x1, p) -#define MX6UL_PAD_SD1_DATA2__SAI2_RX_DATA(p) PIN_CFG(0x01CC, 0x0458, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_SD1_DATA2__FLEXCAN2_TX(p) PIN_CFG(0x01CC, 0x0458, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_SD1_DATA2__EIM_ADDR23(p) PIN_CFG(0x01CC, 0x0458, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_SD1_DATA2__GPIO2_IO20(p) PIN_CFG(0x01CC, 0x0458, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SD1_DATA2__CCM_CLKO1(p) PIN_CFG(0x01CC, 0x0458, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_SD1_DATA2__USB_OTG2_OC(p) PIN_CFG(0x01CC, 0x0458, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_SD1_DATA3__USDHC1_DATA3(p) PIN_CFG(0x01D0, 0x045C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_SD1_DATA3__GPT2_CAPTURE2(p) PIN_CFG(0x01D0, 0x045C, 0x059C, 0x1, 0x1, p) -#define MX6UL_PAD_SD1_DATA3__SAI2_TX_DATA(p) PIN_CFG(0x01D0, 0x045C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_SD1_DATA3__FLEXCAN2_RX(p) PIN_CFG(0x01D0, 0x045C, 0x0588, 0x3, 0x3, p) -#define MX6UL_PAD_SD1_DATA3__EIM_ADDR24(p) PIN_CFG(0x01D0, 0x045C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_SD1_DATA3__GPIO2_IO21(p) PIN_CFG(0x01D0, 0x045C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SD1_DATA3__CCM_CLKO2(p) PIN_CFG(0x01D0, 0x045C, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_SD1_DATA3__ANATOP_OTG2_ID(p) PIN_CFG(0x01D0, 0x045C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_MCLK__CSI_MCLK(p) PIN_CFG(0x01D4, 0x0460, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_CSI_MCLK__USDHC2_CD_B(p) PIN_CFG(0x01D4, 0x0460, 0x0674, 0x1, 0x0, p) -#define MX6UL_PAD_CSI_MCLK__RAWNAND_CE2_B(p) PIN_CFG(0x01D4, 0x0460, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_MCLK__I2C1_SDA(p) PIN_CFG(0x01D4, 0x0460, 0x05A8, 0x3, 0x0, p) -#define MX6UL_PAD_CSI_MCLK__EIM_CS0_B(p) PIN_CFG(0x01D4, 0x0460, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_MCLK__GPIO4_IO17(p) PIN_CFG(0x01D4, 0x0460, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_MCLK__SNVS_HP_VIO_5_CTL(p) PIN_CFG(0x01D4, 0x0460, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_CSI_MCLK__UART6_TX(p) PIN_CFG(0x01D4, 0x0460, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK(p) PIN_CFG(0x01D8, 0x0464, 0x0528, 0x0, 0x1, p) -#define MX6UL_PAD_CSI_PIXCLK__USDHC2_WP(p) PIN_CFG(0x01D8, 0x0464, 0x069C, 0x1, 0x2, p) -#define MX6UL_PAD_CSI_PIXCLK__RAWNAND_CE3_B(p) PIN_CFG(0x01D8, 0x0464, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_PIXCLK__I2C1_SCL(p) PIN_CFG(0x01D8, 0x0464, 0x05A4, 0x3, 0x2, p) -#define MX6UL_PAD_CSI_PIXCLK__EIM_OE(p) PIN_CFG(0x01D8, 0x0464, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_PIXCLK__GPIO4_IO18(p) PIN_CFG(0x01D8, 0x0464, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_PIXCLK__SNVS_HP_VIO_5(p) PIN_CFG(0x01D8, 0x0464, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_CSI_PIXCLK__UART6_RX(p) PIN_CFG(0x01D8, 0x0464, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_VSYNC__CSI_VSYNC(p) PIN_CFG(0x01DC, 0x0468, 0x052C, 0x0, 0x0, p) -#define MX6UL_PAD_CSI_VSYNC__USDHC2_CLK(p) PIN_CFG(0x01DC, 0x0468, 0x0670, 0x1, 0x0, p) -#define MX6UL_PAD_CSI_VSYNC__SIM1_PORT1_CLK(p) PIN_CFG(0x01DC, 0x0468, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_VSYNC__I2C2_SDA(p) PIN_CFG(0x01DC, 0x0468, 0x05B0, 0x3, 0x0, p) -#define MX6UL_PAD_CSI_VSYNC__EIM_RW(p) PIN_CFG(0x01DC, 0x0468, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_VSYNC__GPIO4_IO19(p) PIN_CFG(0x01DC, 0x0468, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_VSYNC__PWM7_OUT(p) PIN_CFG(0x01DC, 0x0468, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_CSI_VSYNC__UART6_DCE_RTS(p) PIN_CFG(0x01DC, 0x0468, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_VSYNC__UART6_DTE_CTS(p) PIN_CFG(0x01DC, 0x0468, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_HSYNC__CSI_HSYNC(p) PIN_CFG(0x01E0, 0x046C, 0x0524, 0x0, 0x0, p) -#define MX6UL_PAD_CSI_HSYNC__USDHC2_CMD(p) PIN_CFG(0x01E0, 0x046C, 0x0678, 0x1, 0x0, p) -#define MX6UL_PAD_CSI_HSYNC__SIM1_PORT1_PD(p) PIN_CFG(0x01E0, 0x046C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_HSYNC__I2C2_SCL(p) PIN_CFG(0x01E0, 0x046C, 0x05AC, 0x3, 0x0, p) -#define MX6UL_PAD_CSI_HSYNC__EIM_LBA_B(p) PIN_CFG(0x01E0, 0x046C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_HSYNC__GPIO4_IO20(p) PIN_CFG(0x01E0, 0x046C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_HSYNC__PWM8_OUT(p) PIN_CFG(0x01E0, 0x046C, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_CSI_HSYNC__UART6_DCE_CTS(p) PIN_CFG(0x01E0, 0x046C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_HSYNC__UART6_DTE_RTS(p) PIN_CFG(0x01E0, 0x046C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_DATA00__CSI_DATA02(p) PIN_CFG(0x01E4, 0x0470, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_CSI_DATA00__USDHC2_DATA0(p) PIN_CFG(0x01E4, 0x0470, 0x067C, 0x1, 0x0, p) -#define MX6UL_PAD_CSI_DATA00__SIM1_PORT1_RST_B(p) PIN_CFG(0x01E4, 0x0470, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_DATA00__ECSPI2_SCLK(p) PIN_CFG(0x01E4, 0x0470, 0x0544, 0x3, 0x0, p) -#define MX6UL_PAD_CSI_DATA00__EIM_AD00(p) PIN_CFG(0x01E4, 0x0470, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_DATA00__GPIO4_IO21(p) PIN_CFG(0x01E4, 0x0470, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_DATA00__SRC_INT_BOOT(p) PIN_CFG(0x01E4, 0x0470, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_CSI_DATA00__UART5_TX(p) PIN_CFG(0x01E4, 0x0470, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_DATA01__CSI_DATA03(p) PIN_CFG(0x01E8, 0x0474, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_CSI_DATA01__USDHC2_DATA1(p) PIN_CFG(0x01E8, 0x0474, 0x0680, 0x1, 0x0, p) -#define MX6UL_PAD_CSI_DATA01__SIM1_PORT1_SVEN(p) PIN_CFG(0x01E8, 0x0474, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_DATA01__ECSPI2_SS0(p) PIN_CFG(0x01E8, 0x0474, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_CSI_DATA01__EIM_AD01(p) PIN_CFG(0x01E8, 0x0474, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_DATA01__GPIO4_IO22(p) PIN_CFG(0x01E8, 0x0474, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_DATA01__SAI1_MCLK(p) PIN_CFG(0x01E8, 0x0474, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_CSI_DATA01__UART5_RX(p) PIN_CFG(0x01E8, 0x0474, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_DATA02__CSI_DATA04(p) PIN_CFG(0x01EC, 0x0478, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_CSI_DATA02__USDHC2_DATA2(p) PIN_CFG(0x01EC, 0x0478, 0x0684, 0x1, 0x2, p) -#define MX6UL_PAD_CSI_DATA02__SIM1_PORT1_TRXD(p) PIN_CFG(0x01EC, 0x0478, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_DATA02__ECSPI2_MOSI(p) PIN_CFG(0x01EC, 0x0478, 0x054C, 0x3, 0x1, p) -#define MX6UL_PAD_CSI_DATA02__EIM_AD02(p) PIN_CFG(0x01EC, 0x0478, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_DATA02__GPIO4_IO23(p) PIN_CFG(0x01EC, 0x0478, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_DATA02__SAI1_RX_SYNC(p) PIN_CFG(0x01EC, 0x0478, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_CSI_DATA02__UART5_DCE_RTS(p) PIN_CFG(0x01EC, 0x0478, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_DATA02__UART5_DTE_CTS(p) PIN_CFG(0x01EC, 0x0478, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_DATA03__CSI_DATA05(p) PIN_CFG(0x01F0, 0x047C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_CSI_DATA03__USDHC2_DATA3(p) PIN_CFG(0x01F0, 0x047C, 0x0688, 0x1, 0x0, p) -#define MX6UL_PAD_CSI_DATA03__SIM2_PORT1_PD(p) PIN_CFG(0x01F0, 0x047C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_DATA03__ECSPI2_MISO(p) PIN_CFG(0x01F0, 0x047C, 0x0548, 0x3, 0x0, p) -#define MX6UL_PAD_CSI_DATA03__EIM_AD03(p) PIN_CFG(0x01F0, 0x047C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_DATA03__GPIO4_IO24(p) PIN_CFG(0x01F0, 0x047C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_DATA03__SAI1_RX_BCLK(p) PIN_CFG(0x01F0, 0x047C, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_CSI_DATA03__UART5_DCE_CTS(p) PIN_CFG(0x01F0, 0x047C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_DATA03__UART5_DTE_RTS(p) PIN_CFG(0x01F0, 0x047C, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_DATA04__CSI_DATA06(p) PIN_CFG(0x01F4, 0x0480, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_CSI_DATA04__USDHC2_DATA4(p) PIN_CFG(0x01F4, 0x0480, 0x068C, 0x1, 0x2, p) -#define MX6UL_PAD_CSI_DATA04__SIM2_PORT1_CLK(p) PIN_CFG(0x01F4, 0x0480, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_DATA04__ECSPI1_SCLK(p) PIN_CFG(0x01F4, 0x0480, 0x0534, 0x3, 0x1, p) -#define MX6UL_PAD_CSI_DATA04__EIM_AD04(p) PIN_CFG(0x01F4, 0x0480, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_DATA04__GPIO4_IO25(p) PIN_CFG(0x01F4, 0x0480, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_DATA04__SAI1_TX_SYNC(p) PIN_CFG(0x01F4, 0x0480, 0x05EC, 0x6, 0x1, p) -#define MX6UL_PAD_CSI_DATA04__USDHC1_WP(p) PIN_CFG(0x01F4, 0x0480, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_DATA05__CSI_DATA07(p) PIN_CFG(0x01F8, 0x0484, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_CSI_DATA05__USDHC2_DATA5(p) PIN_CFG(0x01F8, 0x0484, 0x0690, 0x1, 0x2, p) -#define MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B(p) PIN_CFG(0x01F8, 0x0484, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_DATA05__ECSPI1_SS0(p) PIN_CFG(0x01F8, 0x0484, 0x0000, 0x3, 0x0, p) -#define MX6UL_PAD_CSI_DATA05__EIM_AD05(p) PIN_CFG(0x01F8, 0x0484, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_DATA05__GPIO4_IO26(p) PIN_CFG(0x01F8, 0x0484, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_DATA05__SAI1_TX_BCLK(p) PIN_CFG(0x01F8, 0x0484, 0x05E8, 0x6, 0x1, p) -#define MX6UL_PAD_CSI_DATA05__USDHC1_CD_B(p) PIN_CFG(0x01F8, 0x0484, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_DATA06__CSI_DATA08(p) PIN_CFG(0x01FC, 0x0488, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_CSI_DATA06__USDHC2_DATA6(p) PIN_CFG(0x01FC, 0x0488, 0x0694, 0x1, 0x2, p) -#define MX6UL_PAD_CSI_DATA06__SIM2_PORT1_SVEN(p) PIN_CFG(0x01FC, 0x0488, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI(p) PIN_CFG(0x01FC, 0x0488, 0x053C, 0x3, 0x1, p) -#define MX6UL_PAD_CSI_DATA06__EIM_AD06(p) PIN_CFG(0x01FC, 0x0488, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_DATA06__GPIO4_IO27(p) PIN_CFG(0x01FC, 0x0488, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_DATA06__SAI1_RX_DATA(p) PIN_CFG(0x01FC, 0x0488, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_CSI_DATA06__USDHC1_RESET_B(p) PIN_CFG(0x01FC, 0x0488, 0x0000, 0x8, 0x0, p) -#define MX6UL_PAD_CSI_DATA07__CSI_DATA09(p) PIN_CFG(0x0200, 0x048C, 0x0000, 0x0, 0x0, p) -#define MX6UL_PAD_CSI_DATA07__USDHC2_DATA7(p) PIN_CFG(0x0200, 0x048C, 0x0698, 0x1, 0x2, p) -#define MX6UL_PAD_CSI_DATA07__SIM2_PORT1_TRXD(p) PIN_CFG(0x0200, 0x048C, 0x0000, 0x2, 0x0, p) -#define MX6UL_PAD_CSI_DATA07__ECSPI1_MISO(p) PIN_CFG(0x0200, 0x048C, 0x0538, 0x3, 0x1, p) -#define MX6UL_PAD_CSI_DATA07__EIM_AD07(p) PIN_CFG(0x0200, 0x048C, 0x0000, 0x4, 0x0, p) -#define MX6UL_PAD_CSI_DATA07__GPIO4_IO28(p) PIN_CFG(0x0200, 0x048C, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_CSI_DATA07__SAI1_TX_DATA(p) PIN_CFG(0x0200, 0x048C, 0x0000, 0x6, 0x0, p) -#define MX6UL_PAD_CSI_DATA07__USDHC1_VSELECT(p) PIN_CFG(0x0200, 0x048C, 0x0000, 0x8, 0x0, p) - -/* - * The TAMPER Pin can be used for GPIO, which depends on - * TAMPER_PIN_DISABLE[1:0] settings. - */ -#define MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00(p) PIN_CFG(0x001C, 0x02A8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01(p) PIN_CFG(0x0020, 0x02AC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02(p) PIN_CFG(0x0024, 0x02B0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03(p) PIN_CFG(0x0028, 0x02B4, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04(p) PIN_CFG(0x002C, 0x02B8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05(p) PIN_CFG(0x0030, 0x02BC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06(p) PIN_CFG(0x0034, 0x02C0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07(p) PIN_CFG(0x0038, 0x02C4, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08(p) PIN_CFG(0x003C, 0x02C8, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09(p) PIN_CFG(0x0040, 0x02CC, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_BOOT_MODE0__GPIO5_IO10(p) PIN_CFG(0x0014, 0x02A0, 0x0000, 0x5, 0x0, p) -#define MX6UL_PAD_BOOT_MODE1__GPIO5_IO11(p) PIN_CFG(0x0018, 0x02A4, 0x0000, 0x5, 0x0, p) - -#endif /* __DTS_IMX6UL_PINFUNC_H */ diff --git a/bsp/imx6ul/platform/include/mx6ul/iomux_register.h b/bsp/imx6ul/platform/include/mx6ul/iomux_register.h index c75a6617c9..fe92524cfb 100644 --- a/bsp/imx6ul/platform/include/mx6ul/iomux_register.h +++ b/bsp/imx6ul/platform/include/mx6ul/iomux_register.h @@ -1,5 +1,4 @@ #ifndef _IOMUX_REGISTER_H_ #define _IOMUX_REGISTER_H_ -#include "imx6ul-pinfunc.h" -#endif +#endif diff --git a/bsp/imx6ul/rtconfig.h b/bsp/imx6ul/rtconfig.h index 5478603dcb..4cc1b24df0 100644 --- a/bsp/imx6ul/rtconfig.h +++ b/bsp/imx6ul/rtconfig.h @@ -42,8 +42,8 @@ #define RT_USING_DEVICE #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 -#define RT_CONSOLE_DEVICE_NAME "uart" -#define RT_VER_NUM 0x40003 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40004 #define ARCH_ARM #define ARCH_ARM_CORTEX_A #define RT_USING_GIC_V2 @@ -96,6 +96,7 @@ #define RT_USING_LIBC #define RT_USING_POSIX +#define RT_LIBC_FIXED_TIMEZONE 8 /* Network */ @@ -117,6 +118,9 @@ /* Utilities */ +/* RT-Thread Utestcases */ + + /* RT-Thread online packages */ /* IoT - internet of things */ @@ -148,14 +152,24 @@ /* system packages */ +/* Micrium: Micrium software products porting for RT-Thread */ + + /* peripheral libraries and drivers */ +/* AI packages */ + + /* miscellaneous packages */ /* samples: kernel and components samples */ + +/* entertainment: terminal games and other interesting software packages */ + +#define RT_USING_UART1 #define SOC_MCIMX6X4 #endif diff --git a/bsp/imx6ul/rtconfig.py b/bsp/imx6ul/rtconfig.py index 0a9ea3dce3..258e035e5a 100644 --- a/bsp/imx6ul/rtconfig.py +++ b/bsp/imx6ul/rtconfig.py @@ -3,17 +3,11 @@ import os # toolchains options ARCH='arm' CPU='cortex-a' -CROSS_TOOL='gcc' - -if os.getenv('RTT_CC'): - CROSS_TOOL = os.getenv('RTT_CC') +CROSS_TOOL=os.getenv('RTT_CC') or 'gcc' # only support GNU GCC compiler. PLATFORM = 'gcc' -EXEC_PATH = '/usr/bin' - -if os.getenv('RTT_EXEC_PATH'): - EXEC_PATH = os.getenv('RTT_EXEC_PATH') +EXEC_PATH = os.getenv('RTT_EXEC_PATH') or '/usr/bin' BUILD = 'debug' @@ -33,8 +27,8 @@ if PLATFORM == 'gcc': DEVICE = ' -march=armv7-a -mtune=cortex-a9 -mfpu=vfpv3-d16 -ftree-vectorize -ffast-math -mfloat-abi=softfp' CFLAGS = DEVICE + ' -Wall' AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__' - LINK_SCRIPT = 'imx6.lds' - LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-imx6.map,-cref,-u,system_vectors'+\ + LINK_SCRIPT = 'link.lds' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors'+\ ' -T %s' % LINK_SCRIPT CPATH = '' From 0e32728a5d688c51bc844617de7d89d7fdbe34d0 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 23 May 2021 00:14:22 +0800 Subject: [PATCH 109/255] [libc][rtlibc] remove libc_ioctl.h --- components/libc/compilers/common/sys/ioctl.h | 220 ++++++++++++++++++ include/libc/libc_ioctl.h | 229 ------------------- include/rtlibc.h | 1 - 3 files changed, 220 insertions(+), 230 deletions(-) delete mode 100644 include/libc/libc_ioctl.h diff --git a/components/libc/compilers/common/sys/ioctl.h b/components/libc/compilers/common/sys/ioctl.h index 648d90230d..51f51f2ea4 100644 --- a/components/libc/compilers/common/sys/ioctl.h +++ b/components/libc/compilers/common/sys/ioctl.h @@ -15,4 +15,224 @@ #include #endif +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define _IOC(a,b,c,d) ( ((a)<<30) | ((b)<<8) | (c) | ((d)<<16) ) +#define _IOC_NONE 0U +#define _IOC_WRITE 1U +#define _IOC_READ 2U + +#if !defined (_WIN32) && !defined (__TASKING__) +#define _IO(a,b) _IOC(_IOC_NONE,(a),(b),0) +#define _IOW(a,b,c) _IOC(_IOC_WRITE,(a),(b),sizeof(c)) +#define _IOR(a,b,c) _IOC(_IOC_READ,(a),(b),sizeof(c)) +#define _IOWR(a,b,c) _IOC(_IOC_READ|_IOC_WRITE,(a),(b),sizeof(c)) + +#define FIONREAD _IOR('f', 127, int) /* get # bytes to read */ +#define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */ +#define FIONWRITE _IOR('f', 121, int) /* get # bytes outstanding in send queue */ +#endif + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#ifndef FIONREAD +#define FIONREAD 0x541B +#endif +#define TIOCINQ FIONREAD +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +#ifndef FIONBIO +#define FIONBIO 0x5421 +#endif +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 +#define TIOCSBRK 0x5427 +#define TIOCCBRK 0x5428 +#define TIOCGSID 0x5429 +#define TIOCGRS485 0x542E +#define TIOCSRS485 0x542F +#define TIOCGPTN 0x80045430 +#define TIOCSPTLCK 0x40045431 +#define TIOCGDEV 0x80045432 +#define TCGETX 0x5432 +#define TCSETX 0x5433 +#define TCSETXF 0x5434 +#define TCSETXW 0x5435 +#define TIOCSIG 0x40045436 +#define TIOCVHANGUP 0x5437 +#define TIOCGPKT 0x80045438 +#define TIOCGPTLCK 0x80045439 +#define TIOCGEXCL 0x80045440 + +#define FIONCLEX 0x5450 +#define FIOCLEX 0x5451 + +#ifndef _WIN32 +#define FIOASYNC 0x5452 +#endif + +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 +#define TIOCSERGETLSR 0x5459 +#define TIOCSERGETMULTI 0x545A +#define TIOCSERSETMULTI 0x545B + +#define TIOCMIWAIT 0x545C +#define TIOCGICOUNT 0x545D +#define FIOQSIZE 0x5460 + +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64 + +#define TIOCSER_TEMT 0x01 + +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 + +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 +#define N_STRIP 4 +#define N_AX25 5 +#define N_X25 6 +#define N_6PACK 7 +#define N_MASC 8 +#define N_R3964 9 +#define N_PROFIBUS_FDL 10 +#define N_IRDA 11 +#define N_SMSBLOCK 12 +#define N_HDLC 13 +#define N_SYNC_PPP 14 +#define N_HCI 15 + +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#ifndef SIOCATMARK +#define SIOCATMARK 0x8905 +#endif +#define SIOCGSTAMP 0x8906 +#define SIOCGSTAMPNS 0x8907 + +#define SIOCADDRT 0x890B +#define SIOCDELRT 0x890C +#define SIOCRTMSG 0x890D + +#define SIOCGIFNAME 0x8910 +#define SIOCSIFLINK 0x8911 +#define SIOCGIFCONF 0x8912 +#define SIOCGIFFLAGS 0x8913 +#define SIOCSIFFLAGS 0x8914 +#define SIOCGIFADDR 0x8915 +#define SIOCSIFADDR 0x8916 +#define SIOCGIFDSTADDR 0x8917 +#define SIOCSIFDSTADDR 0x8918 +#define SIOCGIFBRDADDR 0x8919 +#define SIOCSIFBRDADDR 0x891a +#define SIOCGIFNETMASK 0x891b +#define SIOCSIFNETMASK 0x891c +#define SIOCGIFMETRIC 0x891d +#define SIOCSIFMETRIC 0x891e +#define SIOCGIFMEM 0x891f +#define SIOCSIFMEM 0x8920 +#define SIOCGIFMTU 0x8921 +#define SIOCSIFMTU 0x8922 +#define SIOCSIFNAME 0x8923 +#define SIOCSIFHWADDR 0x8924 +#define SIOCGIFENCAP 0x8925 +#define SIOCSIFENCAP 0x8926 +#define SIOCGIFHWADDR 0x8927 +#define SIOCGIFSLAVE 0x8929 +#define SIOCSIFSLAVE 0x8930 +#define SIOCADDMULTI 0x8931 +#define SIOCDELMULTI 0x8932 +#define SIOCGIFINDEX 0x8933 +#define SIOGIFINDEX SIOCGIFINDEX +#define SIOCSIFPFLAGS 0x8934 +#define SIOCGIFPFLAGS 0x8935 +#define SIOCDIFADDR 0x8936 +#define SIOCSIFHWBROADCAST 0x8937 +#define SIOCGIFCOUNT 0x8938 + +#define SIOCGIFBR 0x8940 +#define SIOCSIFBR 0x8941 + +#define SIOCGIFTXQLEN 0x8942 +#define SIOCSIFTXQLEN 0x8943 + +#define SIOCDARP 0x8953 +#define SIOCGARP 0x8954 +#define SIOCSARP 0x8955 + +#define SIOCDRARP 0x8960 +#define SIOCGRARP 0x8961 +#define SIOCSRARP 0x8962 + +#define SIOCGIFMAP 0x8970 +#define SIOCSIFMAP 0x8971 + +#define SIOCADDDLCI 0x8980 +#define SIOCDELDLCI 0x8981 + +#define SIOCDEVPRIVATE 0x89F0 +#define SIOCPROTOPRIVATE 0x89E0 + #endif diff --git a/include/libc/libc_ioctl.h b/include/libc/libc_ioctl.h deleted file mode 100644 index 05f0daa238..0000000000 --- a/include/libc/libc_ioctl.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017-01-21 Bernard the first version - */ - -#ifndef LIBC_IOCTL_H__ -#define LIBC_IOCTL_H__ - -#define _IOC(a,b,c,d) ( ((a)<<30) | ((b)<<8) | (c) | ((d)<<16) ) -#define _IOC_NONE 0U -#define _IOC_WRITE 1U -#define _IOC_READ 2U - -#if !defined (_WIN32) && !defined (__TASKING__) -#define _IO(a,b) _IOC(_IOC_NONE,(a),(b),0) -#define _IOW(a,b,c) _IOC(_IOC_WRITE,(a),(b),sizeof(c)) -#define _IOR(a,b,c) _IOC(_IOC_READ,(a),(b),sizeof(c)) -#define _IOWR(a,b,c) _IOC(_IOC_READ|_IOC_WRITE,(a),(b),sizeof(c)) - -#define FIONREAD _IOR('f', 127, int) /* get # bytes to read */ -#define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */ -#define FIONWRITE _IOR('f', 121, int) /* get # bytes outstanding - * in send queue. */ -#endif - -#define TCGETS 0x5401 -#define TCSETS 0x5402 -#define TCSETSW 0x5403 -#define TCSETSF 0x5404 -#define TCGETA 0x5405 -#define TCSETA 0x5406 -#define TCSETAW 0x5407 -#define TCSETAF 0x5408 -#define TCSBRK 0x5409 -#define TCXONC 0x540A -#define TCFLSH 0x540B -#define TIOCEXCL 0x540C -#define TIOCNXCL 0x540D -#define TIOCSCTTY 0x540E -#define TIOCGPGRP 0x540F -#define TIOCSPGRP 0x5410 -#define TIOCOUTQ 0x5411 -#define TIOCSTI 0x5412 -#define TIOCGWINSZ 0x5413 -#define TIOCSWINSZ 0x5414 -#define TIOCMGET 0x5415 -#define TIOCMBIS 0x5416 -#define TIOCMBIC 0x5417 -#define TIOCMSET 0x5418 -#define TIOCGSOFTCAR 0x5419 -#define TIOCSSOFTCAR 0x541A -// #define FIONREAD 0x541B -#define TIOCINQ FIONREAD -#define TIOCLINUX 0x541C -#define TIOCCONS 0x541D -#define TIOCGSERIAL 0x541E -#define TIOCSSERIAL 0x541F -#define TIOCPKT 0x5420 -// #define FIONBIO 0x5421 -#define TIOCNOTTY 0x5422 -#define TIOCSETD 0x5423 -#define TIOCGETD 0x5424 -#define TCSBRKP 0x5425 -#define TIOCSBRK 0x5427 -#define TIOCCBRK 0x5428 -#define TIOCGSID 0x5429 -#define TIOCGRS485 0x542E -#define TIOCSRS485 0x542F -#define TIOCGPTN 0x80045430 -#define TIOCSPTLCK 0x40045431 -#define TIOCGDEV 0x80045432 -#define TCGETX 0x5432 -#define TCSETX 0x5433 -#define TCSETXF 0x5434 -#define TCSETXW 0x5435 -#define TIOCSIG 0x40045436 -#define TIOCVHANGUP 0x5437 -#define TIOCGPKT 0x80045438 -#define TIOCGPTLCK 0x80045439 -#define TIOCGEXCL 0x80045440 - -#define FIONCLEX 0x5450 -#define FIOCLEX 0x5451 - -#ifndef _WIN32 -#define FIOASYNC 0x5452 -#endif - -#define TIOCSERCONFIG 0x5453 -#define TIOCSERGWILD 0x5454 -#define TIOCSERSWILD 0x5455 -#define TIOCGLCKTRMIOS 0x5456 -#define TIOCSLCKTRMIOS 0x5457 -#define TIOCSERGSTRUCT 0x5458 -#define TIOCSERGETLSR 0x5459 -#define TIOCSERGETMULTI 0x545A -#define TIOCSERSETMULTI 0x545B - -#define TIOCMIWAIT 0x545C -#define TIOCGICOUNT 0x545D -#define FIOQSIZE 0x5460 - -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 -#define TIOCPKT_IOCTL 64 - -#define TIOCSER_TEMT 0x01 - -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 - -#define N_TTY 0 -#define N_SLIP 1 -#define N_MOUSE 2 -#define N_PPP 3 -#define N_STRIP 4 -#define N_AX25 5 -#define N_X25 6 -#define N_6PACK 7 -#define N_MASC 8 -#define N_R3964 9 -#define N_PROFIBUS_FDL 10 -#define N_IRDA 11 -#define N_SMSBLOCK 12 -#define N_HDLC 13 -#define N_SYNC_PPP 14 -#define N_HCI 15 - -#define FIOSETOWN 0x8901 -#define SIOCSPGRP 0x8902 -#define FIOGETOWN 0x8903 -#define SIOCGPGRP 0x8904 -// #define SIOCATMARK 0x8905 -#define SIOCGSTAMP 0x8906 -#define SIOCGSTAMPNS 0x8907 - -#define SIOCADDRT 0x890B -#define SIOCDELRT 0x890C -#define SIOCRTMSG 0x890D - -#define SIOCGIFNAME 0x8910 -#define SIOCSIFLINK 0x8911 -#define SIOCGIFCONF 0x8912 -#define SIOCGIFFLAGS 0x8913 -#define SIOCSIFFLAGS 0x8914 -#define SIOCGIFADDR 0x8915 -#define SIOCSIFADDR 0x8916 -#define SIOCGIFDSTADDR 0x8917 -#define SIOCSIFDSTADDR 0x8918 -#define SIOCGIFBRDADDR 0x8919 -#define SIOCSIFBRDADDR 0x891a -#define SIOCGIFNETMASK 0x891b -#define SIOCSIFNETMASK 0x891c -#define SIOCGIFMETRIC 0x891d -#define SIOCSIFMETRIC 0x891e -#define SIOCGIFMEM 0x891f -#define SIOCSIFMEM 0x8920 -#define SIOCGIFMTU 0x8921 -#define SIOCSIFMTU 0x8922 -#define SIOCSIFNAME 0x8923 -#define SIOCSIFHWADDR 0x8924 -#define SIOCGIFENCAP 0x8925 -#define SIOCSIFENCAP 0x8926 -#define SIOCGIFHWADDR 0x8927 -#define SIOCGIFSLAVE 0x8929 -#define SIOCSIFSLAVE 0x8930 -#define SIOCADDMULTI 0x8931 -#define SIOCDELMULTI 0x8932 -#define SIOCGIFINDEX 0x8933 -#define SIOGIFINDEX SIOCGIFINDEX -#define SIOCSIFPFLAGS 0x8934 -#define SIOCGIFPFLAGS 0x8935 -#define SIOCDIFADDR 0x8936 -#define SIOCSIFHWBROADCAST 0x8937 -#define SIOCGIFCOUNT 0x8938 - -#define SIOCGIFBR 0x8940 -#define SIOCSIFBR 0x8941 - -#define SIOCGIFTXQLEN 0x8942 -#define SIOCSIFTXQLEN 0x8943 - -#define SIOCDARP 0x8953 -#define SIOCGARP 0x8954 -#define SIOCSARP 0x8955 - -#define SIOCDRARP 0x8960 -#define SIOCGRARP 0x8961 -#define SIOCSRARP 0x8962 - -#define SIOCGIFMAP 0x8970 -#define SIOCSIFMAP 0x8971 - -#define SIOCADDDLCI 0x8980 -#define SIOCDELDLCI 0x8981 - -#define SIOCDEVPRIVATE 0x89F0 -#define SIOCPROTOPRIVATE 0x89E0 - -#endif diff --git a/include/rtlibc.h b/include/rtlibc.h index 50bddc6ee8..d69f3ca185 100644 --- a/include/rtlibc.h +++ b/include/rtlibc.h @@ -16,7 +16,6 @@ #include "libc/libc_errno.h" #include "libc/libc_fcntl.h" -#include "libc/libc_ioctl.h" #include "libc/libc_dirent.h" #include "libc/libc_signal.h" #include "libc/libc_fdset.h" From 5bce56473857e9145b34c77b4355494744838e37 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 23 May 2021 00:25:49 +0800 Subject: [PATCH 110/255] add sys/ioctl.h for posix_termios.h --- components/libc/termios/posix_termios.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/libc/termios/posix_termios.h b/components/libc/termios/posix_termios.h index 5bd1999b0a..6dc5531955 100644 --- a/components/libc/termios/posix_termios.h +++ b/components/libc/termios/posix_termios.h @@ -10,8 +10,8 @@ #ifndef TERMIOS_H__ #define TERMIOS_H__ -#include #include +#include #ifdef __cplusplus extern "C" { From 07cab33b50107e71b9fb22230f07c33030e8fc82 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 23 May 2021 00:30:29 +0800 Subject: [PATCH 111/255] add sys/ioctl.h for pipe.c --- components/drivers/src/pipe.c | 1 + components/libc/termios/posix_termios.c | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 236c1ffec7..0e35248480 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -16,6 +16,7 @@ #include #include #include +#include static int pipe_fops_open(struct dfs_fd *fd) { diff --git a/components/libc/termios/posix_termios.c b/components/libc/termios/posix_termios.c index 01ba010c86..1816bbae57 100644 --- a/components/libc/termios/posix_termios.c +++ b/components/libc/termios/posix_termios.c @@ -9,9 +9,7 @@ */ #include #include -#include #include - #include int tcgetattr(int fd, struct termios *tio) @@ -128,4 +126,3 @@ int cfsetspeed(struct termios *tio, speed_t speed) return cfsetospeed(tio, speed); } #endif - From 66e54122fc0f6256845c722bb7c8ab5dbd3d84f1 Mon Sep 17 00:00:00 2001 From: BernardXiong Date: Sun, 23 May 2021 00:47:58 +0800 Subject: [PATCH 112/255] [BSP] fix space issue --- bsp/imx6ul/drivers/iomux/uart_iomux_config.c | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/bsp/imx6ul/drivers/iomux/uart_iomux_config.c b/bsp/imx6ul/drivers/iomux/uart_iomux_config.c index 0d180ff713..4da7598986 100644 --- a/bsp/imx6ul/drivers/iomux/uart_iomux_config.c +++ b/bsp/imx6ul/drivers/iomux/uart_iomux_config.c @@ -33,17 +33,17 @@ #include "io.h" #include -#define MX6UL_PAD_UART1_TX_DATA__UART1_TX1 (IOMUXC_BASE_ADDR+0x084) -#define MX6UL_PAD_UART1_RX_DATA__UART1_RX1 (IOMUXC_BASE_ADDR+0x088) +#define MX6UL_PAD_UART1_TX_DATA__UART1_TX1 (IOMUXC_BASE_ADDR+0x084) +#define MX6UL_PAD_UART1_RX_DATA__UART1_RX1 (IOMUXC_BASE_ADDR+0x088) #define IOMUXC_UART1_UART_RXD_MUX_SELECT_INPUT1 (IOMUXC_BASE_ADDR+0x624) #define PIN_CFG(mux_ctl_offset, pad_ctl_offset, select_input_offset, mux_mode, daisy, pad_setting) \ - do {\ - writel(mux_mode, IOMUXC_BASE_ADDR + mux_ctl_offset);\ - if (select_input_offset != 0)\ - writel(daisy, IOMUXC_BASE_ADDR + select_input_offset);\ - writel(pad_setting, IOMUXC_BASE_ADDR + pad_ctl_offset);\ - } while(0); + do {\ + writel(mux_mode, IOMUXC_BASE_ADDR + mux_ctl_offset);\ + if (select_input_offset != 0)\ + writel(daisy, IOMUXC_BASE_ADDR + select_input_offset);\ + writel(pad_setting, IOMUXC_BASE_ADDR + pad_ctl_offset);\ + } while(0); #define MX6UL_PAD_UART1_TX_DATA__UART1_TX(p) PIN_CFG(0x0084, 0x0310, 0x0624, 0x0, 0x2, p) #define MX6UL_PAD_UART1_RX_DATA__UART1_RX(p) PIN_CFG(0x0088, 0x0314, 0x0624, 0x0, 0x3, p) @@ -108,11 +108,11 @@ void uart_iomux_config(int instance) return uart5_iomux_config(); case HW_UART7: - return uart5_iomux_config(); + return uart5_iomux_config(); case HW_UART8: - return uart5_iomux_config(); - + return uart5_iomux_config(); + default: assert(false); } From 247943f1cd827431fdf8a38d38b75fe5e0b35ef5 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Mon, 24 May 2021 16:59:32 +0800 Subject: [PATCH 113/255] add usb audio for pandora. --- bsp/stm32/libraries/HAL_Drivers/drv_usbd.c | 5 +++ bsp/stm32/stm32l475-atk-pandora/board/Kconfig | 35 ++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usbd.c b/bsp/stm32/libraries/HAL_Drivers/drv_usbd.c index 4f8f08fef3..d0cb54ef0c 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_usbd.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usbd.c @@ -22,8 +22,13 @@ static struct udcd _stm_udc; static struct ep_id _ep_pool[] = { {0x0, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, 64, ID_ASSIGNED }, +#ifdef BSP_USBD_EP_ISOC + {0x1, USB_EP_ATTR_ISOC, USB_DIR_IN, 64, ID_UNASSIGNED}, + {0x1, USB_EP_ATTR_ISOC, USB_DIR_OUT, 64, ID_UNASSIGNED}, +#else {0x1, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED}, {0x1, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED}, +#endif {0x2, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED}, {0x2, USB_EP_ATTR_INT, USB_DIR_OUT, 64, ID_UNASSIGNED}, {0x3, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED}, diff --git a/bsp/stm32/stm32l475-atk-pandora/board/Kconfig b/bsp/stm32/stm32l475-atk-pandora/board/Kconfig index bb34e37366..bc71249fa0 100644 --- a/bsp/stm32/stm32l475-atk-pandora/board/Kconfig +++ b/bsp/stm32/stm32l475-atk-pandora/board/Kconfig @@ -78,7 +78,35 @@ menu "Onboard Peripheral Drivers" bool "Enable Audio Record" default n endif - + + menuconfig BSP_USING_USB_AUDIO + bool "Enable USB Audio" + select RT_USB_DEVICE_AUDIO + select BSP_USING_USBD + select BSP_USBD_EP_ISOC + select BSP_USING_AUDIO + default n + + if BSP_USING_USB_AUDIO + config BSP_USING_USB_AUDIO_SPEAKER + bool "Enable USB Audio Spearker" + select RT_USB_DEVICE_AUDIO_SPEAKER + select BSP_USING_AUDIO_PLAY + default y + + config BSP_USING_USB_AUDIO_MIC + bool "Enable USB Audio Mic" + select RT_USB_DEVICE_AUDIO_MIC + select BSP_USING_AUDIO_RECORD + default n + + config _BSP_USB_DEVICE_COMPOSITE + bool + select RT_USB_DEVICE_COMPOSITE + default y + depends on BSP_USING_USB_AUDIO_SPEAKER && BSP_USING_USB_AUDIO_MIC + endif + config BSP_USING_WIFI bool "Enable WiFi (AP6181)" select PKG_USING_WLAN_WICED @@ -352,6 +380,11 @@ menu "On-chip Peripheral Drivers" select RT_USING_USB_DEVICE default n + config BSP_USBD_EP_ISOC + bool + default n + depends on BSP_USING_USBD + config BSP_USING_STM32_SDIO bool "Enable SDIO" select RT_USING_SDIO From e455b18241c0d69f04e5aeb764f237a21a2810e8 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Tue, 25 May 2021 11:51:50 +0800 Subject: [PATCH 114/255] [bsp][qemu-riscv-virt64]add English README.md --- bsp/qemu-riscv-virt64/README.md | 80 +++++++++-------- bsp/qemu-riscv-virt64/README_ZH.md | 138 +++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+), 37 deletions(-) create mode 100644 bsp/qemu-riscv-virt64/README_ZH.md diff --git a/bsp/qemu-riscv-virt64/README.md b/bsp/qemu-riscv-virt64/README.md index 01e1fa6444..d665500846 100644 --- a/bsp/qemu-riscv-virt64/README.md +++ b/bsp/qemu-riscv-virt64/README.md @@ -1,47 +1,52 @@ -# QEMU/RISCV64 VIRT板级支持包说明 +# QEMU/RISCV64 VIRT BSP Introduction -## 1. 简介 +[中文页](README_ZH.md) | English -RISC-V是一种开放和免费的指令集体系结构(ISA)。本工程是在QEMU的RISCV64 VIRT版本上进行的一份移植。 +RISC-V is a free and open ISA enabling a new era of processor innovation through open standard collaboration. This project ported RT-Thread on QEMU RISCV64 VIRT machine. -## 2. 编译说明 +## 1. Compiling + +Download the cross compiler tool chain, it is recommended to use the sifive tool chain. -首先可以下载交叉编译工具链,建议采用sifive的工具链进行编译。 ``` https://www.sifive.com/software ``` -选择对应的平台即可。 -这里推荐在Ubuntu上进行开发工作。 +Select the fitting platform, we recommend Ubuntu. -解压工具链到指定的目录。 +Unzip the tool chain to the specified directory. ``` export RTT_EXEC_PATH=~/gcc/bin ``` -进入到`rt-thread/bsp/qemu-riscv-virt64`目录进行输入 +Enter `rt-thread/bsp/qemu-riscv-virt64` directory and input + ``` scons ``` -可以看到正常生成`rtthread.elf`与`rtthread.bin`文件。 -## 3. 执行 + `rtthread.elf` and `rtthread .bin` files are generated. -本工程提供了riscv64的两种可配置运行模式,默认运行在M-Mode下。 +## 2. Execution -*M-Mode* +The project provides two configurable operating modes for riscv64, defaults to run under M-Mode. -首先安装`qemu-system-riscv64`。 +***M-Mode*** + +Firstly, install the `qemu-system-riscv64`. ``` sudo apt install qemu-system-misc ``` -直接输入 + +Then enter + ``` ./qemu-nographic.sh ``` -可以看到程序运行 + +You'll see Project start running ``` heap: [0x80035804 - 0x86435804] @@ -54,39 +59,45 @@ Hello RISC-V! msh /> ``` -*S-Mode* +***S-Mode*** -如果运行在S-Mode下,那么需要通过menuconfig选择配置 +When running in S-Mode, configuration is via menuconfig ``` scons --menuconfig ``` -选择如下: + +Select: + ``` RISCV qemu virt64 configs ---> [*] RT-Thread run in riscv smode ``` -保存后,重新`scons`编译即可。 -要让rt-thread运行在S-Mode,首先需要启动opensbi,然后通过opensbi启动rt-thread。 +Save it and compile `scons`. -自行编译的qemu或者下载的高版本的qemu内置opensbi,执行`./qemu-nographic-smode.sh`即可正常运行。 +To get RT-Thread running in S-Mode, enable the opensbi, and then start up the RT-Thread through opensbi. -通过`sudo apt install qemu-system-misc`安装的qemu版本较低,可自行编译opensbi。 +Compile qemu or downloaded premiere-version qemu that built-in opensbi, then executing `./qemu-nographic-smode.sh` can get it successfully running. + +The qemu installed with `sudo apt install qemu-system-misc` is an ordinary-version and may compile the opensbi on its own. ``` git clone git@github.com:riscv/opensbi.git cd opensbi make PLATFORM=generic CROSS_COMPILE=~/gcc/bin/riscv64-unknown-elf- ``` -最后生成的`/build/platform/generic/firmware/fw_jump.elf`则是需要的文件。 -输入以下的命令即可运行: +`/build/platform/generic/firmware/fw_jump.elf` file is generated. + +Enter the following command to run: ``` qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin -bios ~/opensbi/build/platform/generic/firmware/fw_jump.elf ``` -可以看到如下的结果 + +Result is shown as follows: + ``` OpenSBI v0.9 ____ _____ ____ _____ @@ -121,16 +132,11 @@ heap: [0x80235a58 - 0x86635a58] Hello RISC-V! msh /> ``` -## 4. 支持情况 -| 驱动 | 支持情况 | 备注 | -| ------ | ---- | :------: | -| UART | 支持 | UART0 | -| PLIC | 支持 | - | -| CLIC | 支持 | - | +## 3. Condition -## 5. 联系人信息 - -维护人:[bernard][1] - -[1]: https://github.com/BernardXiong +| Driver | Condition | Remark | +| ------ | --------- | ------ | +| UART | Support | UART0 | +| PLIC | Support | - | +| CLIC | Support | - | \ No newline at end of file diff --git a/bsp/qemu-riscv-virt64/README_ZH.md b/bsp/qemu-riscv-virt64/README_ZH.md new file mode 100644 index 0000000000..a3631048e7 --- /dev/null +++ b/bsp/qemu-riscv-virt64/README_ZH.md @@ -0,0 +1,138 @@ +# QEMU/RISCV64 VIRT板级支持包说明 + +中文页 | [English](README.md) + +## 1. 简介 + +RISC-V是一种开放和免费的指令集体系结构(ISA)。本工程是在QEMU的RISCV64 VIRT版本上进行的一份移植。 + +## 2. 编译说明 + +首先可以下载交叉编译工具链,建议采用sifive的工具链进行编译。 +``` +https://www.sifive.com/software +``` +选择对应的平台即可。 + +这里推荐在Ubuntu上进行开发工作。 + +解压工具链到指定的目录。 + +``` +export RTT_EXEC_PATH=~/gcc/bin +``` + +进入到`rt-thread/bsp/qemu-riscv-virt64`目录进行输入 +``` +scons +``` +可以看到正常生成`rtthread.elf`与`rtthread.bin`文件。 + +## 3. 执行 + +本工程提供了riscv64的两种可配置运行模式,默认运行在M-Mode下。 + +*M-Mode* + +首先安装`qemu-system-riscv64`。 + +``` +sudo apt install qemu-system-misc +``` +直接输入 +``` +./qemu-nographic.sh +``` +可以看到程序运行 + +``` +heap: [0x80035804 - 0x86435804] + + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build May 21 2021 + 2006 - 2021 Copyright by rt-thread team +Hello RISC-V! +msh /> +``` + +*S-Mode* + +如果运行在S-Mode下,那么需要通过menuconfig选择配置 + +``` +scons --menuconfig +``` +选择如下: +``` +RISCV qemu virt64 configs ---> + [*] RT-Thread run in riscv smode +``` +保存后,重新`scons`编译即可。 + +要让rt-thread运行在S-Mode,首先需要启动opensbi,然后通过opensbi启动rt-thread。 + +自行编译的qemu或者下载的高版本的qemu内置opensbi,执行`./qemu-nographic-smode.sh`即可正常运行。 + +通过`sudo apt install qemu-system-misc`安装的qemu版本较低,可自行编译opensbi。 + +``` +git clone git@github.com:riscv/opensbi.git +cd opensbi +make PLATFORM=generic CROSS_COMPILE=~/gcc/bin/riscv64-unknown-elf- +``` +最后生成的`/build/platform/generic/firmware/fw_jump.elf`则是需要的文件。 + +输入以下的命令即可运行: + +``` +qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin -bios ~/opensbi/build/platform/generic/firmware/fw_jump.elf +``` +可以看到如下的结果 +``` +OpenSBI v0.9 + ____ _____ ____ _____ + / __ \ / ____| _ \_ _| + | | | |_ __ ___ _ __ | (___ | |_) || | + | | | | '_ \ / _ \ '_ \ \___ \| _ < | | + | |__| | |_) | __/ | | |____) | |_) || |_ + \____/| .__/ \___|_| |_|_____/|____/_____| + | | + |_| + +Platform Name : riscv-virtio,qemu +Platform Features : timer,mfdeleg +. +. +. +Boot HART ISA : rv64imafdcsu +Boot HART Features : scounteren,mcounteren +Boot HART PMP Count : 16 +Boot HART PMP Granularity : 4 +Boot HART PMP Address Bits: 54 +Boot HART MHPM Count : 0 +Boot HART MHPM Count : 0 +Boot HART MIDELEG : 0x0000000000000222 +Boot HART MEDELEG : 0x000000000000b109 +heap: [0x80235a58 - 0x86635a58] + + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build May 21 2021 + 2006 - 2021 Copyright by rt-thread team +Hello RISC-V! +msh /> +``` +## 4. 支持情况 + +| 驱动 | 支持情况 | 备注 | +| ------ | ---- | :------: | +| UART | 支持 | UART0 | +| PLIC | 支持 | - | +| CLIC | 支持 | - | + +## 5. 联系人信息 + +维护人:[bernard][1] + +[1]: https://github.com/BernardXiong From cd326d849a745c824c3ff2f0a22b25be4ba04d60 Mon Sep 17 00:00:00 2001 From: yangjie Date: Tue, 25 May 2021 18:28:30 +0800 Subject: [PATCH 115/255] =?UTF-8?q?[src]=E7=A7=BB=E9=99=A4=20C99=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/timer.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/timer.c b/src/timer.c index 836df51e06..9b0db6c6a5 100644 --- a/src/timer.c +++ b/src/timer.c @@ -531,7 +531,9 @@ void rt_timer_check(void) struct rt_timer *t; rt_tick_t current_tick; register rt_base_t level; - rt_list_t list = RT_LIST_OBJECT_INIT(list); + rt_list_t list; + + rt_list_init(&list); RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n")); @@ -613,7 +615,9 @@ void rt_soft_timer_check(void) rt_tick_t current_tick; struct rt_timer *t; register rt_base_t level; - rt_list_t list = RT_LIST_OBJECT_INIT(list); + rt_list_t list; + + rt_list_init(&list); RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n")); From 1ac2347e1df6cfd0465054b098be21faaff0aeb2 Mon Sep 17 00:00:00 2001 From: chenyaxing Date: Tue, 25 May 2021 21:17:35 +0800 Subject: [PATCH 116/255] dev:[tools] add default project name and project path while --dist-ide --- tools/building.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tools/building.py b/tools/building.py index bfdd1ff55a..32ce449622 100644 --- a/tools/building.py +++ b/tools/building.py @@ -925,14 +925,11 @@ def EndBuilding(target, program = None): project_name = GetOption('project-name') if not isinstance(project_path, str) or len(project_path) == 0 : - print("\nwarning : --project-path=your_project_path parameter is required.") - print("\nstop!") - exit(0) - + project_path = os.path.join(BSP_ROOT, 'dist_ide_project') + print("\nwarning : --project-path not specified, use default path: {0}.".format(project_path)) if not isinstance(project_name, str) or len(project_name) == 0: - print("\nwarning : --project-name=your_project_name parameter is required.") - print("\nstop!") - exit(0) + project_name = "dist_ide_project" + print("\nwarning : --project-name not specified, use default project name: {0}.".format(project_name)) rtt_ide = {'project_path' : project_path, 'project_name' : project_name} MkDist(program, BSP_ROOT, Rtt_Root, Env, rtt_ide) From 0c5692eecee7899071ba3454bd4854976770ebc7 Mon Sep 17 00:00:00 2001 From: huanghe Date: Fri, 21 May 2021 18:43:59 +0800 Subject: [PATCH 117/255] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [add] 增加ft2004 BSP --- bsp/ft2004/.config | 726 ++++++++++++++++++ bsp/ft2004/Kconfig | 30 + bsp/ft2004/README.md | 236 ++++++ bsp/ft2004/SConscript | 14 + bsp/ft2004/SConstruct | 32 + bsp/ft2004/applications/SConscript | 11 + bsp/ft2004/applications/main.c | 77 ++ bsp/ft2004/drivers/SConscript | 14 + bsp/ft2004/drivers/board.c | 155 ++++ bsp/ft2004/drivers/board.h | 29 + bsp/ft2004/drivers/drv_can.c | 270 +++++++ bsp/ft2004/drivers/drv_can.h | 38 + bsp/ft2004/drivers/drv_eth.c | 691 +++++++++++++++++ bsp/ft2004/drivers/drv_eth.h | 25 + bsp/ft2004/drivers/drv_log.h | 27 + bsp/ft2004/drivers/drv_qspi.c | 424 ++++++++++ bsp/ft2004/drivers/drv_qspi.h | 29 + bsp/ft2004/drivers/drv_qspi_flash.c | 39 + bsp/ft2004/drivers/drv_sdcard.c | 154 ++++ bsp/ft2004/drivers/drv_sdctrl.c | 659 ++++++++++++++++ bsp/ft2004/drivers/drv_sdctrl.h | 47 ++ bsp/ft2004/drivers/drv_spi.c | 449 +++++++++++ bsp/ft2004/drivers/drv_spi.h | 29 + bsp/ft2004/drivers/drv_spi_flash.c | 43 ++ bsp/ft2004/drivers/drv_usart.c | 192 +++++ bsp/ft2004/drivers/drv_usart.h | 25 + bsp/ft2004/drivers/ft2004.c | 88 +++ bsp/ft2004/drivers/ft2004.h | 25 + bsp/ft2004/drivers/ft2004_cpu.S | 44 ++ bsp/ft2004/drivers/secondary_cpu.c | 86 +++ bsp/ft2004/drivers/serial.h | 20 + bsp/ft2004/figures/onchipPeripheral.png | Bin 0 -> 22293 bytes bsp/ft2004/figures/rttPing通过界面.png | Bin 0 -> 10980 bytes bsp/ft2004/figures/rttsd调试.png | Bin 0 -> 22374 bytes bsp/ft2004/figures/启动演示图.png | Bin 0 -> 24488 bytes bsp/ft2004/ft_aarch32.lds | 110 +++ bsp/ft2004/libraries/.gitignore | 4 + bsp/ft2004/libraries/Kconfig | 146 ++++ bsp/ft2004/libraries/LICENSE | 202 +++++ bsp/ft2004/libraries/SConscript | 129 ++++ bsp/ft2004/libraries/bsp/ft_can/ft_can.c | 299 ++++++++ bsp/ft2004/libraries/bsp/ft_can/ft_can.h | 142 ++++ bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c | 269 +++++++ bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c | 39 + bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c | 55 ++ bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h | 161 ++++ bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c | 118 +++ .../libraries/bsp/ft_can/ft_can_sinit.c | 40 + bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c | 109 +++ bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h | 319 ++++++++ .../libraries/bsp/ft_gmac/ft_gmac_desc.c | 357 +++++++++ .../libraries/bsp/ft_gmac/ft_gmac_desc.h | 20 + bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c | 47 ++ bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c | 566 ++++++++++++++ bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h | 577 ++++++++++++++ .../libraries/bsp/ft_gmac/ft_gmac_intr.c | 174 +++++ .../libraries/bsp/ft_gmac/ft_gmac_sinit.c | 34 + bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c | 107 +++ bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h | 73 ++ bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h | 92 +++ bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c | 510 ++++++++++++ bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h | 197 +++++ bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c | 13 + bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h | 321 ++++++++ bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c | 182 +++++ .../libraries/bsp/ft_i2c/ft_i2c_selftest.c | 20 + bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c | 585 ++++++++++++++ bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h | 184 +++++ bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c | 26 + bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c | 25 + bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h | 199 +++++ bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c | 34 + bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c | 552 +++++++++++++ bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h | 235 ++++++ bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c | 31 + bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c | 41 + bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h | 210 +++++ .../libraries/bsp/ft_sd/ft_sdctrl_intr.c | 110 +++ .../libraries/bsp/ft_sd/ft_sdctrl_option.c | 61 ++ .../libraries/bsp/ft_sd/ft_sdctrl_sinit.c | 33 + bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c | 192 +++++ bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h | 95 +++ bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h | 330 ++++++++ bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c | 13 + bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c | 329 ++++++++ bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h | 120 +++ bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c | 34 + bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c | 46 ++ bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h | 221 ++++++ .../libraries/bsp/ft_uart/ft_uart_intr.c | 196 +++++ .../libraries/bsp/ft_uart/ft_uart_options.c | 102 +++ .../libraries/bsp/ft_uart/ft_uart_selftest.c | 13 + .../libraries/bsp/ft_uart/ft_uart_sinit.c | 41 + .../libraries/bsp/include/ft_parameters.h | 180 +++++ .../libraries/bsp/standlone/ft_assert.c | 43 ++ .../libraries/bsp/standlone/ft_assert.h | 154 ++++ bsp/ft2004/libraries/bsp/standlone/ft_cache.c | 86 +++ bsp/ft2004/libraries/bsp/standlone/ft_cache.h | 32 + bsp/ft2004/libraries/bsp/standlone/ft_cpu.c | 145 ++++ bsp/ft2004/libraries/bsp/standlone/ft_cpu.h | 26 + bsp/ft2004/libraries/bsp/standlone/ft_debug.c | 67 ++ bsp/ft2004/libraries/bsp/standlone/ft_debug.h | 78 ++ .../libraries/bsp/standlone/ft_error_code.h | 72 ++ .../bsp/standlone/ft_generic_timer.c | 327 ++++++++ .../bsp/standlone/ft_generic_timer.h | 57 ++ bsp/ft2004/libraries/bsp/standlone/ft_io.h | 164 ++++ bsp/ft2004/libraries/bsp/standlone/ft_list.h | 23 + bsp/ft2004/libraries/bsp/standlone/ft_math.c | 19 + bsp/ft2004/libraries/bsp/standlone/ft_math.h | 24 + bsp/ft2004/libraries/bsp/standlone/ft_mux.c | 90 +++ bsp/ft2004/libraries/bsp/standlone/ft_mux.h | 75 ++ .../libraries/bsp/standlone/ft_printf.c | 96 +++ .../libraries/bsp/standlone/ft_printf.h | 29 + bsp/ft2004/libraries/bsp/standlone/ft_psci.c | 78 ++ bsp/ft2004/libraries/bsp/standlone/ft_psci.h | 31 + bsp/ft2004/libraries/bsp/standlone/ft_smc.S | 36 + bsp/ft2004/libraries/bsp/standlone/ft_smc.h | 43 ++ .../libraries/bsp/standlone/ft_status.h | 82 ++ bsp/ft2004/libraries/bsp/standlone/ft_trace.c | 57 ++ bsp/ft2004/libraries/bsp/standlone/ft_trace.h | 52 ++ bsp/ft2004/libraries/bsp/standlone/ft_types.h | 75 ++ bsp/ft2004/libraries/bsp/standlone/inbyte.c | 21 + bsp/ft2004/libraries/bsp/standlone/outbyte.c | 21 + bsp/ft2004/libraries/cpu/ft_aarch32_asm.h | 319 ++++++++ bsp/ft2004/libraries/doc/ChangeLog.md | 90 +++ .../libraries/doc/figures/v0.3.0_add.png | Bin 0 -> 297513 bytes bsp/ft2004/libraries/include/asmArm.h | 37 + bsp/ft2004/libraries/readme.md | 69 ++ bsp/ft2004/make.sh | 16 + bsp/ft2004/rtconfig.h | 286 +++++++ bsp/ft2004/rtconfig.py | 59 ++ 131 files changed, 17377 insertions(+) create mode 100644 bsp/ft2004/.config create mode 100644 bsp/ft2004/Kconfig create mode 100644 bsp/ft2004/README.md create mode 100644 bsp/ft2004/SConscript create mode 100644 bsp/ft2004/SConstruct create mode 100644 bsp/ft2004/applications/SConscript create mode 100644 bsp/ft2004/applications/main.c create mode 100644 bsp/ft2004/drivers/SConscript create mode 100644 bsp/ft2004/drivers/board.c create mode 100644 bsp/ft2004/drivers/board.h create mode 100644 bsp/ft2004/drivers/drv_can.c create mode 100644 bsp/ft2004/drivers/drv_can.h create mode 100644 bsp/ft2004/drivers/drv_eth.c create mode 100644 bsp/ft2004/drivers/drv_eth.h create mode 100644 bsp/ft2004/drivers/drv_log.h create mode 100644 bsp/ft2004/drivers/drv_qspi.c create mode 100644 bsp/ft2004/drivers/drv_qspi.h create mode 100644 bsp/ft2004/drivers/drv_qspi_flash.c create mode 100644 bsp/ft2004/drivers/drv_sdcard.c create mode 100644 bsp/ft2004/drivers/drv_sdctrl.c create mode 100644 bsp/ft2004/drivers/drv_sdctrl.h create mode 100644 bsp/ft2004/drivers/drv_spi.c create mode 100644 bsp/ft2004/drivers/drv_spi.h create mode 100644 bsp/ft2004/drivers/drv_spi_flash.c create mode 100644 bsp/ft2004/drivers/drv_usart.c create mode 100644 bsp/ft2004/drivers/drv_usart.h create mode 100644 bsp/ft2004/drivers/ft2004.c create mode 100644 bsp/ft2004/drivers/ft2004.h create mode 100644 bsp/ft2004/drivers/ft2004_cpu.S create mode 100644 bsp/ft2004/drivers/secondary_cpu.c create mode 100644 bsp/ft2004/drivers/serial.h create mode 100644 bsp/ft2004/figures/onchipPeripheral.png create mode 100644 bsp/ft2004/figures/rttPing通过界面.png create mode 100644 bsp/ft2004/figures/rttsd调试.png create mode 100644 bsp/ft2004/figures/启动演示图.png create mode 100644 bsp/ft2004/ft_aarch32.lds create mode 100644 bsp/ft2004/libraries/.gitignore create mode 100644 bsp/ft2004/libraries/Kconfig create mode 100644 bsp/ft2004/libraries/LICENSE create mode 100644 bsp/ft2004/libraries/SConscript create mode 100644 bsp/ft2004/libraries/bsp/ft_can/ft_can.c create mode 100644 bsp/ft2004/libraries/bsp/ft_can/ft_can.h create mode 100644 bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c create mode 100644 bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c create mode 100644 bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c create mode 100644 bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h create mode 100644 bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c create mode 100644 bsp/ft2004/libraries/bsp/ft_can/ft_can_sinit.c create mode 100644 bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c create mode 100644 bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h create mode 100644 bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.c create mode 100644 bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.h create mode 100644 bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c create mode 100644 bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c create mode 100644 bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h create mode 100644 bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_intr.c create mode 100644 bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_sinit.c create mode 100644 bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c create mode 100644 bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h create mode 100644 bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h create mode 100644 bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c create mode 100644 bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h create mode 100644 bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c create mode 100644 bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h create mode 100644 bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c create mode 100644 bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_selftest.c create mode 100644 bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c create mode 100644 bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h create mode 100644 bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c create mode 100644 bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c create mode 100644 bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h create mode 100644 bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c create mode 100644 bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c create mode 100644 bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h create mode 100644 bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c create mode 100644 bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c create mode 100644 bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h create mode 100644 bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_intr.c create mode 100644 bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_option.c create mode 100644 bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_sinit.c create mode 100644 bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c create mode 100644 bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h create mode 100644 bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h create mode 100644 bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c create mode 100644 bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c create mode 100644 bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h create mode 100644 bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c create mode 100644 bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c create mode 100644 bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h create mode 100644 bsp/ft2004/libraries/bsp/ft_uart/ft_uart_intr.c create mode 100644 bsp/ft2004/libraries/bsp/ft_uart/ft_uart_options.c create mode 100644 bsp/ft2004/libraries/bsp/ft_uart/ft_uart_selftest.c create mode 100644 bsp/ft2004/libraries/bsp/ft_uart/ft_uart_sinit.c create mode 100644 bsp/ft2004/libraries/bsp/include/ft_parameters.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_assert.c create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_assert.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_cache.c create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_cache.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_cpu.c create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_cpu.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_debug.c create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_debug.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_error_code.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.c create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_io.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_list.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_math.c create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_math.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_mux.c create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_mux.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_printf.c create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_printf.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_psci.c create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_psci.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_smc.S create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_smc.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_status.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_trace.c create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_trace.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/ft_types.h create mode 100644 bsp/ft2004/libraries/bsp/standlone/inbyte.c create mode 100644 bsp/ft2004/libraries/bsp/standlone/outbyte.c create mode 100644 bsp/ft2004/libraries/cpu/ft_aarch32_asm.h create mode 100644 bsp/ft2004/libraries/doc/ChangeLog.md create mode 100644 bsp/ft2004/libraries/doc/figures/v0.3.0_add.png create mode 100644 bsp/ft2004/libraries/include/asmArm.h create mode 100644 bsp/ft2004/libraries/readme.md create mode 100644 bsp/ft2004/make.sh create mode 100644 bsp/ft2004/rtconfig.h create mode 100644 bsp/ft2004/rtconfig.py diff --git a/bsp/ft2004/.config b/bsp/ft2004/.config new file mode 100644 index 0000000000..1a27a6c8b4 --- /dev/null +++ b/bsp/ft2004/.config @@ -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 +# diff --git a/bsp/ft2004/Kconfig b/bsp/ft2004/Kconfig new file mode 100644 index 0000000000..1bee562e48 --- /dev/null +++ b/bsp/ft2004/Kconfig @@ -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" diff --git a/bsp/ft2004/README.md b/bsp/ft2004/README.md new file mode 100644 index 0000000000..e39a505b5d --- /dev/null +++ b/bsp/ft2004/README.md @@ -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 个 X8),2 个 X1 +- 集成 2 个 GMAC,RGMII 接口,支持 10/100/1000 自适应 +- 集成 1 个 SD 卡控制器,兼容 SD 2.0 规范 +- 集成 1 个 HDAudio,支持音频输出,可同时支持最多 4 个 Codec +- 集成 SM2、SM3、SM4 模块 +- 集成 4 个 UART,1 个 LPC,32 个 GPIO,4 个 I2C,1 个 QSPI,2 个通 + 用 SPI,2 个 WDT,16 个外部中断(和 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-2000/4 软件编程手册-V1.4 + +## 7. 联系人信息 + +请联系飞腾嵌入式软件部 + +huanghe@phytium.com.cn + +zhugengyu@phytium.com.cn diff --git a/bsp/ft2004/SConscript b/bsp/ft2004/SConscript new file mode 100644 index 0000000000..fe0ae941ae --- /dev/null +++ b/bsp/ft2004/SConscript @@ -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') diff --git a/bsp/ft2004/SConstruct b/bsp/ft2004/SConstruct new file mode 100644 index 0000000000..e3c1df26fa --- /dev/null +++ b/bsp/ft2004/SConstruct @@ -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) diff --git a/bsp/ft2004/applications/SConscript b/bsp/ft2004/applications/SConscript new file mode 100644 index 0000000000..a526af2c75 --- /dev/null +++ b/bsp/ft2004/applications/SConscript @@ -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') diff --git a/bsp/ft2004/applications/main.c b/bsp/ft2004/applications/main.c new file mode 100644 index 0000000000..95fad98370 --- /dev/null +++ b/bsp/ft2004/applications/main.c @@ -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 +#include +#include "ft_cpu.h" +#include "ft_generic_timer.h" + +#include + +#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; +} diff --git a/bsp/ft2004/drivers/SConscript b/bsp/ft2004/drivers/SConscript new file mode 100644 index 0000000000..b18c98833e --- /dev/null +++ b/bsp/ft2004/drivers/SConscript @@ -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') diff --git a/bsp/ft2004/drivers/board.c b/bsp/ft2004/drivers/board.c new file mode 100644 index 0000000000..408a58d344 --- /dev/null +++ b/bsp/ft2004/drivers/board.c @@ -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 +#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 + +#include "interrupt.h" +#include +#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, // + +#ifdef BSP_USE_CAN + +#define LOG_TAG "drv_can" +#include + +#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 diff --git a/bsp/ft2004/drivers/drv_can.h b/bsp/ft2004/drivers/drv_can.h new file mode 100644 index 0000000000..92e809eb1e --- /dev/null +++ b/bsp/ft2004/drivers/drv_can.h @@ -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 +#include +#include +#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 // ! diff --git a/bsp/ft2004/drivers/drv_eth.c b/bsp/ft2004/drivers/drv_eth.c new file mode 100644 index 0000000000..e7148631e4 --- /dev/null +++ b/bsp/ft2004/drivers/drv_eth.c @@ -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 +#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 + +#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 diff --git a/bsp/ft2004/drivers/drv_eth.h b/bsp/ft2004/drivers/drv_eth.h new file mode 100644 index 0000000000..ed68b71728 --- /dev/null +++ b/bsp/ft2004/drivers/drv_eth.h @@ -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 // ! diff --git a/bsp/ft2004/drivers/drv_log.h b/bsp/ft2004/drivers/drv_log.h new file mode 100644 index 0000000000..3fe511789b --- /dev/null +++ b/bsp/ft2004/drivers/drv_log.h @@ -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 diff --git a/bsp/ft2004/drivers/drv_qspi.c b/bsp/ft2004/drivers/drv_qspi.c new file mode 100644 index 0000000000..9c5cbf4a9f --- /dev/null +++ b/bsp/ft2004/drivers/drv_qspi.c @@ -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 +#include "rtdevice.h" +#include "ft_qspi.h" +#include "ft_parameters.h" + +#ifdef BSP_USE_QSPI + +#define DRV_DEBUG +#define LOG_TAG "drv.qspi" +#include + +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 diff --git a/bsp/ft2004/drivers/drv_qspi.h b/bsp/ft2004/drivers/drv_qspi.h new file mode 100644 index 0000000000..29566f9af6 --- /dev/null +++ b/bsp/ft2004/drivers/drv_qspi.h @@ -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 + +#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 diff --git a/bsp/ft2004/drivers/drv_qspi_flash.c b/bsp/ft2004/drivers/drv_qspi_flash.c new file mode 100644 index 0000000000..102cd5fc5b --- /dev/null +++ b/bsp/ft2004/drivers/drv_qspi_flash.c @@ -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 +#include +#include +#include +#include + +#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 */ diff --git a/bsp/ft2004/drivers/drv_sdcard.c b/bsp/ft2004/drivers/drv_sdcard.c new file mode 100644 index 0000000000..a6494089f6 --- /dev/null +++ b/bsp/ft2004/drivers/drv_sdcard.c @@ -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 + +#ifdef BSP_USING_SDC + +#include +#include +#include +#include "drv_sdctrl.h" + +#define DBG_TAG "app.card" +#define DBG_LVL DBG_INFO +#include + +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 */ diff --git a/bsp/ft2004/drivers/drv_sdctrl.c b/bsp/ft2004/drivers/drv_sdctrl.c new file mode 100644 index 0000000000..1f6a4df7e5 --- /dev/null +++ b/bsp/ft2004/drivers/drv_sdctrl.c @@ -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 +#include "interrupt.h" +#include "rtconfig.h" +#include "ft_cache.h" + +#ifdef BSP_USING_SDC + +#define LOG_TAG "drv.sdmmc" +#include + +#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 diff --git a/bsp/ft2004/drivers/drv_sdctrl.h b/bsp/ft2004/drivers/drv_sdctrl.h new file mode 100644 index 0000000000..dba34f2525 --- /dev/null +++ b/bsp/ft2004/drivers/drv_sdctrl.h @@ -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 + +#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 // ! diff --git a/bsp/ft2004/drivers/drv_spi.c b/bsp/ft2004/drivers/drv_spi.c new file mode 100644 index 0000000000..0ac38709e4 --- /dev/null +++ b/bsp/ft2004/drivers/drv_spi.c @@ -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 +#include +#include +#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 + +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 diff --git a/bsp/ft2004/drivers/drv_spi.h b/bsp/ft2004/drivers/drv_spi.h new file mode 100644 index 0000000000..5b31ab678c --- /dev/null +++ b/bsp/ft2004/drivers/drv_spi.h @@ -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 + +#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 diff --git a/bsp/ft2004/drivers/drv_spi_flash.c b/bsp/ft2004/drivers/drv_spi_flash.c new file mode 100644 index 0000000000..26d8b44712 --- /dev/null +++ b/bsp/ft2004/drivers/drv_spi_flash.c @@ -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 +#include +#include +#include +#include +#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 diff --git a/bsp/ft2004/drivers/drv_usart.c b/bsp/ft2004/drivers/drv_usart.c new file mode 100644 index 0000000000..96ac3c97eb --- /dev/null +++ b/bsp/ft2004/drivers/drv_usart.c @@ -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); + + //baud_rate); + RT_ASSERT(ret == FST_SUCCESS); + + //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 */ diff --git a/bsp/ft2004/drivers/drv_usart.h b/bsp/ft2004/drivers/drv_usart.h new file mode 100644 index 0000000000..aff47caa29 --- /dev/null +++ b/bsp/ft2004/drivers/drv_usart.h @@ -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 +#include "rtdevice.h" +#include "ft_uart.h" + +struct drv_usart +{ + Ft_Uart *handle; + + struct rt_serial_device serial; +}; + +#endif // ! diff --git a/bsp/ft2004/drivers/ft2004.c b/bsp/ft2004/drivers/ft2004.c new file mode 100644 index 0000000000..da04993276 --- /dev/null +++ b/bsp/ft2004/drivers/ft2004.c @@ -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 +#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 diff --git a/bsp/ft2004/drivers/ft2004.h b/bsp/ft2004/drivers/ft2004.h new file mode 100644 index 0000000000..fe3293ab94 --- /dev/null +++ b/bsp/ft2004/drivers/ft2004.h @@ -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 +#include + +#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 // ! diff --git a/bsp/ft2004/drivers/ft2004_cpu.S b/bsp/ft2004/drivers/ft2004_cpu.S new file mode 100644 index 0000000000..2e713a5b20 --- /dev/null +++ b/bsp/ft2004/drivers/ft2004_cpu.S @@ -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 + diff --git a/bsp/ft2004/drivers/secondary_cpu.c b/bsp/ft2004/drivers/secondary_cpu.c new file mode 100644 index 0000000000..5ffcadbefe --- /dev/null +++ b/bsp/ft2004/drivers/secondary_cpu.c @@ -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 +#include "board.h" +#include + +#ifdef RT_USING_SMP +#include +#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 diff --git a/bsp/ft2004/drivers/serial.h b/bsp/ft2004/drivers/serial.h new file mode 100644 index 0000000000..cf4e337a1f --- /dev/null +++ b/bsp/ft2004/drivers/serial.h @@ -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 + +int rt_hw_uart_init(void); + +#endif + diff --git a/bsp/ft2004/figures/onchipPeripheral.png b/bsp/ft2004/figures/onchipPeripheral.png new file mode 100644 index 0000000000000000000000000000000000000000..3b5833bccae8cbdbf191f50921bac2c94d15823b GIT binary patch literal 22293 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�d6wqLWvK$? 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 a!0@=QRKea$fQxo|=nQpDb&%TkBK{BNuKp+h literal 0 HcmV?d00001 diff --git a/bsp/ft2004/figures/rttsd调试.png b/bsp/ft2004/figures/rttsd调试.png new file mode 100644 index 0000000000000000000000000000000000000000..98d1b5fa2b1b8f6137584dad78699f48ae8e272a GIT binary patch literal 22374 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 BC|3Xg literal 0 HcmV?d00001 diff --git a/bsp/ft2004/figures/启动演示图.png b/bsp/ft2004/figures/启动演示图.png new file mode 100644 index 0000000000000000000000000000000000000000..46a117c96f43cc19da42c3b4e0ba72325eb3e204 GIT binary patch literal 24488 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 literal 0 HcmV?d00001 diff --git a/bsp/ft2004/ft_aarch32.lds b/bsp/ft2004/ft_aarch32.lds new file mode 100644 index 0000000000..d37332d97f --- /dev/null +++ b/bsp/ft2004/ft_aarch32.lds @@ -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 = .; +} diff --git a/bsp/ft2004/libraries/.gitignore b/bsp/ft2004/libraries/.gitignore new file mode 100644 index 0000000000..fcfda9fc84 --- /dev/null +++ b/bsp/ft2004/libraries/.gitignore @@ -0,0 +1,4 @@ +*.o +*.elf +*.bin +*.map diff --git a/bsp/ft2004/libraries/Kconfig b/bsp/ft2004/libraries/Kconfig new file mode 100644 index 0000000000..c544395596 --- /dev/null +++ b/bsp/ft2004/libraries/Kconfig @@ -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 diff --git a/bsp/ft2004/libraries/LICENSE b/bsp/ft2004/libraries/LICENSE new file mode 100644 index 0000000000..7a4a3ea242 --- /dev/null +++ b/bsp/ft2004/libraries/LICENSE @@ -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. \ No newline at end of file diff --git a/bsp/ft2004/libraries/SConscript b/bsp/ft2004/libraries/SConscript new file mode 100644 index 0000000000..e279d05ea1 --- /dev/null +++ b/bsp/ft2004/libraries/SConscript @@ -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') diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can.c new file mode 100644 index 0000000000..9546670715 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can.c @@ -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); +} diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can.h b/bsp/ft2004/libraries/bsp/ft_can/ft_can.h new file mode 100644 index 0000000000..35998daf05 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can.h @@ -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 diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c new file mode 100644 index 0000000000..c897b2e303 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c new file mode 100644 index 0000000000..77edbc84fc --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c @@ -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, + }}; diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c new file mode 100644 index 0000000000..1af32abf46 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c @@ -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); +} diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h new file mode 100644 index 0000000000..634a765774 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h @@ -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___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 */ /*don’t 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 // ! diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c new file mode 100644 index 0000000000..6fb4cdd074 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c @@ -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); + } +} diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_sinit.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_sinit.c new file mode 100644 index 0000000000..d9b3c816a8 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_sinit.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c new file mode 100644 index 0000000000..c4ed19b408 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h new file mode 100644 index 0000000000..332c431456 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h @@ -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 diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.c new file mode 100644 index 0000000000..6071e08df9 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.c @@ -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 + +#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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.h b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.h new file mode 100644 index 0000000000..91dd19bba2 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.h @@ -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 // ! diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c new file mode 100644 index 0000000000..48ca3ddbeb --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c @@ -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}}, +}; diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c new file mode 100644 index 0000000000..a46bad28b3 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c @@ -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); +} diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h new file mode 100644 index 0000000000..6556880863 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h @@ -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 // ! diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_intr.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_intr.c new file mode 100644 index 0000000000..0c57a118ee --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_intr.c @@ -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)); + } +} diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_sinit.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_sinit.c new file mode 100644 index 0000000000..909e05dc22 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_sinit.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c new file mode 100644 index 0000000000..37c442f39e --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h new file mode 100644 index 0000000000..b875470e53 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h @@ -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 diff --git a/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h new file mode 100644 index 0000000000..77d9071fd4 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h @@ -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 diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c new file mode 100644 index 0000000000..57985f906f --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c @@ -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 +#include +#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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h new file mode 100644 index 0000000000..20bab542b7 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h @@ -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 diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c new file mode 100644 index 0000000000..3d9bd40994 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c @@ -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 + * ----- ------     --------    -------------------------------------- + */ diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h new file mode 100644 index 0000000000..53f7de7bfe --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h @@ -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 diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c new file mode 100644 index 0000000000..85b39edf1b --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c @@ -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; + } +} diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_selftest.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_selftest.c new file mode 100644 index 0000000000..4a43df0ce4 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_selftest.c @@ -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 +#include +#include "ft_i2c_hw.h" +#include "ft_i2c.h" +#include "ft_status.h" +#include "ft_printf.h" diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c new file mode 100644 index 0000000000..3476e20333 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h new file mode 100644 index 0000000000..61aa626f63 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h @@ -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 instanceId, 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 diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c new file mode 100644 index 0000000000..18833f60d0 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c @@ -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}}; diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c new file mode 100644 index 0000000000..1fb8e05c0d --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c @@ -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)); +} diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h new file mode 100644 index 0000000000..c7b9cb9651 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h @@ -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 // ! diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c new file mode 100644 index 0000000000..36c1e313a2 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c new file mode 100644 index 0000000000..cf2eb5c7b0 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c @@ -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); +} diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h new file mode 100644 index 0000000000..88a0e9ee2b --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h @@ -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 // diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c new file mode 100644 index 0000000000..3492f89049 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c @@ -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*/ + }}; diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c new file mode 100644 index 0000000000..83a9c05dde --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h new file mode 100644 index 0000000000..931c3ad7db --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h @@ -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) /* 0:CMD 响应时,不执行索引检查 1:CMD 响应时,执行索引检查 */ +#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 // ! diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_intr.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_intr.c new file mode 100644 index 0000000000..88bbc41f53 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_intr.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_option.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_option.c new file mode 100644 index 0000000000..0799b0be4c --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_option.c @@ -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); +} diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_sinit.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_sinit.c new file mode 100644 index 0000000000..47827413d2 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_sinit.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c new file mode 100644 index 0000000000..cc2a74a045 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h new file mode 100644 index 0000000000..15893f0eaa --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h @@ -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 diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h new file mode 100644 index 0000000000..b4872e0de3 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h @@ -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 diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c new file mode 100644 index 0000000000..a3a0b7a429 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c @@ -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 + * ----- ------     --------    -------------------------------------- + */ diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c new file mode 100644 index 0000000000..a72c66841e --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c @@ -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; + //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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h new file mode 100644 index 0000000000..e342067030 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h @@ -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 // ! diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c new file mode 100644 index 0000000000..87e76f92d9 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c @@ -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}}; diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c new file mode 100644 index 0000000000..541f86a6a1 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h new file mode 100644 index 0000000000..8cadd40419 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h @@ -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 diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_intr.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_intr.c new file mode 100644 index 0000000000..de1e92649f --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_intr.c @@ -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) + { + //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 + { + } +} diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_options.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_options.c new file mode 100644 index 0000000000..0016f0c732 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_options.c @@ -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); + } +} diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_selftest.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_selftest.c new file mode 100644 index 0000000000..b31a0e2ed0 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_selftest.c @@ -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 + * ----- ------     --------    -------------------------------------- + */ diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_sinit.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_sinit.c new file mode 100644 index 0000000000..8c228db78c --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_sinit.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/include/ft_parameters.h b/bsp/ft2004/libraries/bsp/include/ft_parameters.h new file mode 100644 index 0000000000..9764bfae30 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/include/ft_parameters.h @@ -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 // ! diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_assert.c b/bsp/ft2004/libraries/bsp/standlone/ft_assert.c new file mode 100644 index 0000000000..7ec987b2be --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_assert.c @@ -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; +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_assert.h b/bsp/ft2004/libraries/bsp/standlone/ft_assert.h new file mode 100644 index 0000000000..09e685e4af --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_assert.h @@ -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 // ! diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cache.c b/bsp/ft2004/libraries/bsp/standlone/ft_cache.c new file mode 100644 index 0000000000..d99c8d3350 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_cache.c @@ -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"); +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cache.h b/bsp/ft2004/libraries/bsp/standlone/ft_cache.h new file mode 100644 index 0000000000..a0c78d7a9c --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_cache.h @@ -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 diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cpu.c b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.c new file mode 100644 index 0000000000..5162395c25 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.c @@ -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 diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cpu.h b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.h new file mode 100644 index 0000000000..7d941f00e1 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.h @@ -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 diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_debug.c b/bsp/ft2004/libraries/bsp/standlone/ft_debug.c new file mode 100644 index 0000000000..79628b7def --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_debug.c @@ -0,0 +1,67 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-25 16:44:23 + * @LastEditTime: 2021-04-25 16:44:23 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ +#include "ft_debug.h" + +#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') +void Ft_DumpHexByte(const u8 *ptr, ft_base_t buflen) +{ + unsigned char *buf = (unsigned char *)ptr; + int i, j; + + for (i = 0; i < buflen; i += 16) + { + Ft_printf("0x%08X: ", ptr + i); + + for (j = 0; j < 16; j++) + if (i + j < buflen) + Ft_printf("%02X ", buf[i + j]); + else + Ft_printf(" "); + Ft_printf(" "); + + for (j = 0; j < 16; j++) + if (i + j < buflen) + Ft_printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + Ft_printf("\r\n"); + } +} + +void Ft_DumpHexWord(const u32 *ptr, ft_base_t buflen) +{ + u32 *buf = (u32 *)ptr; + int i, j; + buflen = buflen / 4; + for (i = 0; i < buflen; i += 4) + { + Ft_printf("0x%08X: ", ptr + i); + + for (j = 0; j < 4; j++) + { + if (i + j < buflen) + { + Ft_printf("%08X ", buf[i + j]); + } + else + { + Ft_printf(" "); + } + } + + Ft_printf(" "); + + for (j = 0; j < 16; j++) + if (i + j < buflen) + Ft_printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + Ft_printf("\r\n"); + } +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_debug.h b/bsp/ft2004/libraries/bsp/standlone/ft_debug.h new file mode 100644 index 0000000000..ef11bd8d9b --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_debug.h @@ -0,0 +1,78 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-25 17:19:03 + * @Description:  This files is for debug functions + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_DEBUG_H +#define FT_DEBUG_H + +#include "ft_printf.h" + +typedef enum +{ + FT_LOG_NONE, /*!< No log output */ + FT_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */ + FT_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */ + FT_LOG_INFO, /*!< Information messages which describe normal flow of events */ + FT_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */ + FT_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */ +} ft_log_level_t; + +#define LOG_COLOR_BLACK "30" +#define LOG_COLOR_RED "31" +#define LOG_COLOR_GREEN "32" +#define LOG_COLOR_BROWN "33" +#define LOG_COLOR_BLUE "34" +#define LOG_COLOR_PURPLE "35" +#define LOG_COLOR_CYAN "36" +#define LOG_COLOR(COLOR) "\033[0;" COLOR "m" +#define LOG_BOLD(COLOR) "\033[1;" COLOR "m" +#define LOG_RESET_COLOR "\033[0m" +#define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED) +#define LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN) +#define LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN) +#define LOG_COLOR_D +#define LOG_COLOR_V + +#ifndef LOG_LOCAL_LEVEL +#define LOG_LOCAL_LEVEL FT_LOG_VERBOSE +#endif + +#define LOG_FORMAT(letter, format) LOG_COLOR_##letter " %s: " format LOG_RESET_COLOR "\r\n" + +#define PORT_KPRINTF Ft_printf + +#define LOG_EARLY_IMPL(tag, format, log_level, log_tag_letter, ...) \ + do \ + { \ + if (LOG_LOCAL_LEVEL < log_level) \ + break; \ + PORT_KPRINTF(LOG_FORMAT(log_tag_letter, format), tag, ##__VA_ARGS__); \ + } while (0) + +#define EARLY_LOGE(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_ERROR, E, ##__VA_ARGS__) +#define EARLY_LOGI(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_INFO, I, ##__VA_ARGS__) +#define EARLY_LOGD(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_DEBUG, D, ##__VA_ARGS__) +#define EARLY_LOGW(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_WARN, W, ##__VA_ARGS__) +#define EARLY_LOGV(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_VERBOSE, W, ##__VA_ARGS__) + +#define FT_DEBUG_PRINT_I(TAG, format, ...) EARLY_LOGI(TAG, format, ##__VA_ARGS__) +#define FT_DEBUG_PRINT_E(TAG, format, ...) EARLY_LOGE(TAG, format, ##__VA_ARGS__) +#define FT_DEBUG_PRINT_D(TAG, format, ...) EARLY_LOGD(TAG, format, ##__VA_ARGS__) +#define FT_DEBUG_PRINT_W(TAG, format, ...) EARLY_LOGW(TAG, format, ##__VA_ARGS__) +#define FT_DEBUG_PRINT_V(TAG, format, ...) EARLY_LOGV(TAG, format, ##__VA_ARGS__) + +#define FT_RAW_PRINTF(format, ...) PORT_KPRINTF(format, ##__VA_ARGS__) + +void Ft_DumpHexWord(const u32 *ptr, ft_base_t buflen); +void Ft_DumpHexByte(const u8 *ptr, ft_base_t buflen); +#endif // ! diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_error_code.h b/bsp/ft2004/libraries/bsp/standlone/ft_error_code.h new file mode 100644 index 0000000000..9c1a309367 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_error_code.h @@ -0,0 +1,72 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-07 09:53:30 + * @LastEditTime: 2021-05-24 10:12:07 + * @Description:  This files is for error code functions + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef _FT_ERROR_CODE_H +#define _FT_ERROR_CODE_H + +#include "ft_status.h" +#include "ft_types.h" + +typedef ft_base_t ft_error_t; + +/* 系统错误码模块定义 */ +typedef enum _ft_errcode_module_mask +{ + errModGeneral = 0, + errModBsp, + ERR_MODE_UART, + errModeI2c, + errModeGmac, + errModeSdCtrl, + errCan, + errGicV3, + errQspi, + ERR_MODE_SD_MMC, + ERR_MODE_SPI, + + errModMaxMask = 255, +} ft_errcode_module_mask_t; + +/* BSP模块的错误子模块定义 */ +typedef enum _ft_errcode_bsp_mask +{ + errBspGeneral = 0, + errBspClk, + errBspRtc, + errPort, + errBspModMaxMask = 255 +} ft_errcode_bsp_mask_t; + +#define FT_ERRCODE_SYS_MODULE_OFFSET 24 +#define FT_ERRCODE_SUB_MODULE_OFFSET 16 + +#define FT_ERRCODE_SYS_MODULE_MASK (0xff << FT_ERRCODE_SYS_MODULE_OFFSET) /* bit 24 .. 31 */ +#define FT_ERRCODE_SUB_MODULE_MASK (0xff << FT_ERRCODE_SUB_MODULE_OFFSET) /* bit 16 .. 23 */ +#define FT_ERRCODE_TAIL_VALUE_MASK (0xffff) /* bit 1 .. 15 */ + +/* Offset error code */ +#define FT_ERRCODE_OFFSET(code, offset, mask) \ + (((code) << offset) & mask) + +/* Assembly error code */ +#define FT_MAKE_ERRCODE(sys_mode, sub_mode, tail) \ + ((FT_ERRCODE_OFFSET(sys_mode, FT_ERRCODE_SYS_MODULE_OFFSET, FT_ERRCODE_SYS_MODULE_MASK)) | \ + (FT_ERRCODE_OFFSET(sub_mode, FT_ERRCODE_SUB_MODULE_OFFSET, FT_ERRCODE_SUB_MODULE_MASK)) | \ + (tail & FT_ERRCODE_TAIL_VALUE_MASK)) +#define FT_CODE_ERR FT_MAKE_ERRCODE + +#define ERR_SUCCESS FT_MAKE_ERRCODE(errModGeneral, errBspGeneral, FST_SUCCESS) /* 成功 */ +#define ERR_GENERAL FT_MAKE_ERRCODE(errModGeneral, errBspGeneral, FST_FAILURE) /* 一般错误 */ + +#endif diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.c b/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.c new file mode 100644 index 0000000000..e4e1ab6d5f --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.c @@ -0,0 +1,327 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-25 10:51:35 + * @Description:  This files is for generic timer functions + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_status.h" +#include "ft_types.h" +#include "ft_generic_timer.h" +#include "ft_printf.h" +#include "ft_assert.h" +#include "ft_aarch32_asm.h" +#include "ft_cpu.h" + +#define GENERICTIMER_ASM(x) __asm__ volatile(x) +#define USEVIRTUAL 0 +#define USE_ISRNUM GEN_TIMER_PHYSICAL_NOSECURE_IRQN + +static volatile u32 _TickCnt; +static volatile u32 _Tickms; + +typedef struct ft_Generictimer +{ + u64 Frequency; + u64 MaxCount; + u64 TicksPerUs; + u32 Isr_PeriodMsec; + u32 Isr_PeriodCnt; //member))) + +#endif // ! FT_LIST_H diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_math.c b/bsp/ft2004/libraries/bsp/standlone/ft_math.c new file mode 100644 index 0000000000..244ed1700e --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_math.c @@ -0,0 +1,19 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-28 22:15:48 + * @LastEditTime: 2021-04-28 22:15:48 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_math.h" + +u32 Ft_Abs(s32 num) +{ + return (num >= 0 ? num : -num); +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_math.h b/bsp/ft2004/libraries/bsp/standlone/ft_math.h new file mode 100644 index 0000000000..7456f18386 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_math.h @@ -0,0 +1,24 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-28 22:15:19 + * @LastEditTime: 2021-04-28 22:15:19 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_MATH_H +#define FT_MATH_H + +#include "ft_types.h" + +#define FT_INT_MAX 2147483647 +#define FT_UINT_MAX (FT_INT_MAX * 2U + 1) + +u32 Ft_Abs(s32 num); + +#endif // !FT_MATH_H diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_mux.c b/bsp/ft2004/libraries/bsp/standlone/ft_mux.c new file mode 100644 index 0000000000..7127b9e564 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_mux.c @@ -0,0 +1,90 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-25 10:51:59 + * @Description:  This files is for pin mux + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_mux.h" +#include "ft_io.h" +#include "ft_assert.h" +#include "ft_printf.h" + +/** + * Description: enable i2c 1 ~ 3 pin pad mux + * Date: 2021-03-24 13:34:06 + * Param: + * return {*} + * param {FT_IN u32} I2cId, i2c 0 ~ 3 + */ +void Ft_setI2cMux(FT_IN u32 I2cId) +{ + u32 RegValue; + + switch (I2cId) + { + case I2C0_ID: + /* i2c0 is by default enabled */ + break; + case I2C1_ID: + /* select i2c1 SCL, SDA mux */ + RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG200_OFFSET); + RegValue |= (I2C1_SCL_PIN_REG200_BIT | I2C1_SDA_PIN_REG200_BIT); + Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG200_OFFSET, RegValue); + break; + case I2C2_ID: + Ft_assertNoneReturn(0); + break; + case I2C3_ID: + Ft_assertNoneReturn(0); + break; + default: + Ft_assertNoneReturn(0); + break; + } + + return; +} + +void Ft_setSpiMux(FT_IN u32 SpiId) +{ + u32 RegValue; + + switch (SpiId) + { + case SPI0_ID: + /* spi0 is by default enabled */ + RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG208_OFFSET); + /* clear specific bits to choose Func 0 */ + RegValue |= SPI1_PORTA5_PIN_REG208_BIT; + Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG208_OFFSET, RegValue); + Ft_printf("bef reg 208 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG208_OFFSET)); + + break; + case SPI1_ID: + /* select spi cs, sck, so, si pin mux */ + Ft_printf("bef reg 210 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET)); + RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET); + RegValue |= SPI1_CSN0_PIN_REG210_BIT; + Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET, RegValue); + Ft_printf("aft reg 210 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET)); + + Ft_printf("bef reg 214 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET)); + RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET); + RegValue |= SPI1_SCK_PIN_REG214_BIT | SPI1_SO_PIN_REG214_BIT | SPI1_SI_PIN_REG214_BIT; + Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET, RegValue); + Ft_printf("aft reg 214 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET)); + break; + default: + break; + } + + return; +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_mux.h b/bsp/ft2004/libraries/bsp/standlone/ft_mux.h new file mode 100644 index 0000000000..c482154353 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_mux.h @@ -0,0 +1,75 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-26 15:39:16 + * @Description:  This files is for pin mux + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_BSP_MUX_H +#define FT_BSP_MUX_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" + +/* pad pin multi-function demu */ +#define FT_PIN_DEMUX_BASE 0x28180000 +#define FT_PIN_DEMUX_REG200_OFFSET 0x200 +#define FT_PIN_DEMUX_REG204_OFFSET 0x204 +#define FT_PIN_DEMUX_REG208_OFFSET 0x208 +#define FT_PIN_DEMUX_REG210_OFFSET 0x210 +#define FT_PIN_DEMUX_REG214_OFFSET 0x214 + +/* i2c mux function option */ +#define I2C1_SCL_PIN_REG200_MASK ((u32)0x3 << 28) /* all_pll_lock_pad [29:28] */ +#define I2C1_SCL_PIN_REG200_BIT ((u32)0x2 << 28) +#define I2C1_SDA_PIN_REG200_MASK ((u32)0x3 << 24) /* cru_clk_obv_pad [25:24] */ +#define I2C1_SDA_PIN_REG200_BIT ((u32)0x2 << 24) +#define I2C2_SCL_PIN_REG204_MASK ((u32)0x3 << 8) /* swdo_swj_pad [9: 8] */ +#define I2C2_SCL_PIN_REG204_BIT ((u32)0x2 << 8) +#define I2C2_SDA_PIN_REG204_MASK ((u32)0x3 << 6) /* tdo_swj_pad [7: 6] */ +#define I2C2_SDA_PIN_REG204_BIT ((u32)0x2 << 6) +#define I2C3_SCL_PIN_REG204_MASK ((u32)0x3 << 0) /* hdt_mb_done_state_pad [1 : 0] */ +#define I2C3_SCL_PIN_REG204_BIT ((u32)0x2 << 0) +#define I2C3_SDA_PIN_REG208_MASK ((u32)0x3 << 30) /* hdt_mb_fail_state_pad [31 : 30] */ +#define I2C3_SDA_PIN_REG208_BIT ((u32)0x2 << 30) + +#define SPI1_PORTA5_PIN_REG208_BIT ((u32)0x1 << 16) + +#define SPI1_CSN0_PIN_REG210_MASK ((u32)0x3 << 0) /* uart_2_rxd_pad [1 : 0] */ +#define SPI1_CSN0_PIN_REG210_BIT ((u32)0x1 << 0) +#define SPI1_SCK_PIN_REG214_MASK ((u32)0x3 << 28) /* uart_2_txd_pad [29 : 28] */ +#define SPI1_SCK_PIN_REG214_BIT ((u32)0x1 << 28) +#define SPI1_SO_PIN_REG214_MASK ((u32)0x3 << 24) /* uart_3_rxd_pad [25 : 24] */ +#define SPI1_SO_PIN_REG214_BIT ((u32)0x1 << 24) +#define SPI1_SI_PIN_REG214_MASK ((u32)0x3 << 20) /* uart_3_txd_pad [21 : 20] */ +#define SPI1_SI_PIN_REG214_BIT ((u32)0x1 << 20) + +/* i2c ctrl instance */ +#define I2C0_ID 0 +#define I2C1_ID 1 +#define I2C2_ID 2 +#define I2C3_ID 3 + +/* spi ctrl instance */ +#define SPI0_ID 0 +#define SPI1_ID 1 + + void Ft_setI2cMux(FT_IN u32 I2cId); + void Ft_setSpiMux(FT_IN u32 SpiId); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_printf.c b/bsp/ft2004/libraries/bsp/standlone/ft_printf.c new file mode 100644 index 0000000000..db6a50f532 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_printf.c @@ -0,0 +1,96 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-26 15:20:14 + * @Description:  This files is for printf function + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_printf.h" +#include "stdio.h" +#include "ft_aarch32_asm.h" + +static char print_buffer[PRINTF_BUFFER_LENGTH]; + +extern void outbyte(char byte); + +vsprintf_p Vsprintf_pFun = (vsprintf_p)vsprintf; + +void Ft_vsprintfRegister(vsprintf_p f) +{ + Vsprintf_pFun = f; +} + +void Ft_printf(const char *fmt, ...) +{ + va_list args; + size_t i; + size_t length; +#ifdef NEED_CLOSE_ISR + IRQ_DISABLE(); +#endif + va_start(args, fmt); + + length = Vsprintf_pFun(print_buffer, fmt, args); + va_end(args); + for (i = 0; i < length; i++) + { + outbyte(print_buffer[i]); + } + +#ifdef NEED_CLOSE_ISR + IRQ_ENABLE(); +#endif +} + +char *Ft_itoa(int num, char *str, int radix) +{ + char index[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + unsigned unum; + int i = 0; + int j; + int k; + char temp; + + if (radix == 10 && num < 0) + { + unum = (unsigned)-num; + str[i++] = '-'; + } + else + { + unum = (unsigned)num; + } + + do + { + str[i++] = index[unum % (unsigned)radix]; + unum /= radix; + } while (unum); + + str[i] = '\0'; + + if (str[0] == '-') + { + k = 1; + } + else + { + k = 0; + } + + for (j = k; j <= (i - 1) / 2; j++) + { + temp = str[j]; + str[j] = str[i - 1 + k - j]; + str[i - 1 + k - j] = temp; + } + + return str; +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_printf.h b/bsp/ft2004/libraries/bsp/standlone/ft_printf.h new file mode 100644 index 0000000000..4d1d3ea867 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_printf.h @@ -0,0 +1,29 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-26 15:39:25 + * @Description:  This files is for printf functions + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef Ft_printf_H +#define Ft_printf_H + +#include +#include "ft_types.h" + +#define PRINTF_BUFFER_LENGTH 4096 + +typedef s32 (*vsprintf_p)(char *buf, const char *format, va_list arg_ptr); + +void Ft_vsprintfRegister(vsprintf_p f); +void Ft_printf(const char *fmt, ...); +char *Ft_itoa(int num, char *str, int radix); + +#endif // ! diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_psci.c b/bsp/ft2004/libraries/bsp/standlone/ft_psci.c new file mode 100644 index 0000000000..1ca9e3379f --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_psci.c @@ -0,0 +1,78 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-21 10:43:52 + * @LastEditTime: 2021-04-21 10:43:53 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_psci.h" +#include "ft_smc.h" +#include "ft_cpu.h" +#include "ft_printf.h" + +#define PSCI_CPUON_NUM 0x84000003 +#define PSCI_RESET_NUM 0x84000009 + +/** + * @name: FPsci_CpuOn + * @msg: Power up a core + * @in param CpuList: Bits[24:31]: Must be zero. + * Bits[16:23] Aff2: Match Aff2 of target core MPIDR + * Bits[8:15] Aff1: Match Aff1 of target core MPIDR + * Bits[0:7] Aff0: Match Aff0 of target core MPIDR + * @in param BootAddr: a 32-bit entry point physical address (or IPA). + * @return {None} + */ +void FPsci_CpuOn(s32 CpuIdMask, u32 BootAddr) +{ + + FSmc_Data_t Input = {0}; + FSmc_Data_t Output = {0}; + Input.FunctionIdentifier = PSCI_CPUON_NUM; + + if ((1 << 0) == CpuIdMask) + { + Input.a1 = SoftAffiTable[0]; + } + else if ((1 << 1) == CpuIdMask) + { + Input.a1 = SoftAffiTable[1]; + } + else if ((1 << 2) == CpuIdMask) + { + Input.a1 = SoftAffiTable[2]; + } + else if ((1 << 3) == CpuIdMask) + { + Input.a1 = SoftAffiTable[3]; + } + else + { + return; + } + + /*input.a2 = (u32)(BootAddr >> 32);*/ + Input.a2 = (u32)(BootAddr & 0xFFFFFFFF); + FSmc_Call(&Input, &Output); + __asm__ volatile("NOP"); +} + +void FPsci_Reset(void) +{ + + FSmc_Data_t Input = {0}; + FSmc_Data_t Output = {0}; + + Input.FunctionIdentifier = PSCI_RESET_NUM; + FSmc_Call(&Input, &Output); + + __asm__ volatile("NOP"); + while (1) + ; +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_psci.h b/bsp/ft2004/libraries/bsp/standlone/ft_psci.h new file mode 100644 index 0000000000..b963c0092a --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_psci.h @@ -0,0 +1,31 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-21 10:43:59 + * @LastEditTime: 2021-04-21 10:44:00 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_PSCI_H +#define FT_PSCI_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" + + void FPsci_CpuOn(s32 CpuIdMask, u32 BootAddr); + void FPsci_Reset(void); + +#ifdef __cplusplus +} +#endif + +#endif // ! diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_smc.S b/bsp/ft2004/libraries/bsp/standlone/ft_smc.S new file mode 100644 index 0000000000..c610350eb5 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_smc.S @@ -0,0 +1,36 @@ + + +/******************************************************************************* +* +* FSmc_Call - initiate SMC call +* +* This routine initiates SMC call which traps the processor into Monitor Mode. +* The ARM SMC Call Convetion defines that up to eight registers can be exchanged +* during an SMC call. The input parameter contains eight INT32 valeus which are +* to be passed in the SMC call; similarily the output parameter also contains +* eight INT32 values which are returned from the SMC call. +* +* \NOMANUAL +* +* RETURNS: OK +* +* void FSmc_Call +* ( +* FSmc_Data_t * input, /@ r0 - input register values @/ +* FSmc_Data_t * output /@ r1 - output register values @/ +* ) +*/ + +.arm +.align 4 +.globl FSmc_Call +FSmc_Call: + STMDB sp!, {r0-r7} /* save clobbered registers to stack */ + ldr r12, [sp, #(4 * 0)] /* get 1st argument (ptr to input struct) */ + ldmia r12, {r0-r7} /* save input argument to r0-r7 */ + smc #0 + ldr r12, [sp, #(4 * 1)] /* get 2th argument (ptr to output result) */ + stmia r12, {r0-r7} /* get output argument from r0-r7 */ + ldmfd sp!, {r0-r7} /* restore clobbered registers from stack */ + bx lr +.size FSmc_Call, .- FSmc_Call diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_smc.h b/bsp/ft2004/libraries/bsp/standlone/ft_smc.h new file mode 100644 index 0000000000..c241c09eca --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_smc.h @@ -0,0 +1,43 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-21 11:53:38 + * @LastEditTime: 2021-04-21 11:53:38 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_SMC_H +#define FT_SMC_H + +#include "ft_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct + { + /* data */ + u32 FunctionIdentifier; + u32 a1; + u32 a2; + u32 a3; + u32 a4; + u32 a5; + u32 a6; + + } FSmc_Data_t; + + void FSmc_Call(FSmc_Data_t *Input, FSmc_Data_t *Output); + +#ifdef __cplusplus +} +#endif + +#endif // !FT_SMC_H diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_status.h b/bsp/ft2004/libraries/bsp/standlone/ft_status.h new file mode 100644 index 0000000000..a30ac32cf8 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_status.h @@ -0,0 +1,82 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 15:31:10 + * @Description:  This files is for definition of status + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_STATUS_H +#define FT_STATUS_H + +/** +@name Common Status Codes +*/ + +typedef enum +{ + FST_SUCCESS = 0L, + FST_FAILURE = 1L, + FST_INSTANCE_NOT_FOUND = 2L, + FST_DEVICE_BLOCK_NOT_FOUND = 3L, + FST_INVALID_VERSION = 4L, + FST_DEVICE_IS_STARTED = 5L, + FST_DEVICE_IS_STOPPED = 6L, + FST_FIFO_ERROR = 7L, /* An error occurred during an \ + operation with a FIFO such as \ + an underrun or overrun, this \ + error requires the device to \ + be reset */ + FST_RESET_ERROR = 8L, /* An error occurred which requires \ + the device to be reset */ + FST_DMA_ERROR = 9L, /* A DMA error occurred, this error \ + typically requires the device \ + using the DMA to be reset */ + FST_NOT_POLLED = 10L, /* The device is not configured for \ + polled mode operation */ + FST_FIFO_NO_ROOM = 11L, /* A FIFO did not have room to put \ + the specified data into */ + FST_BUFFER_TOO_SMALL = 12L, /* The buffer is not large enough \ + to hold the expected data */ + FST_NO_DATA = 13L, /* There was no data available */ + FST_REGISTER_ERROR = 14L, /* A register did not contain the \ + expected value */ + FST_INVALID_PARAM = 15L, /* An invalid parameter was passed \ + into the function */ + FST_NOT_SGDMA = 16L, /* The device is not configured for \ + scatter-gather DMA operation */ + FST_LOOPBACK_ERROR = 17L, /* A loopback test failed */ + FST_NO_CALLBACK = 18L, /* A callback has not yet been \ + registered */ + FST_NO_FEATURE = 19L, /* Device is not configured with \ + the requested feature */ + FST_NOT_INTERRUPT = 20L, /* Device is not configured for \ + interrupt mode operation */ + FST_DEVICE_BUSY = 21L, /* Device is busy */ + FST_ERROR_COUNT_MAX = 22L, /* The error counters of a device \ + have maxed out */ + FST_IS_STARTED = 23L, /* Used when part of device is \ + already started i.e. \ + sub channel */ + FST_IS_STOPPED = 24L, /* Used when part of device is \ + already stopped i.e. \ + sub channel */ + FST_DATA_LOST = 26L, /* Driver defined error */ + FST_RECV_ERROR = 27L, /* Generic receive error */ + FST_SEND_ERROR = 28L, /* Generic transmit error */ + FST_NOT_ENABLED = 29L, /* A requested service is not \ + available because it has not \ + been enabled */ + FST_ASSERT_RETURN = 30L, /* Assert occurs defined error */ + FST_TIMEOUT = 31L, + FST_EILSEQ = 32L, /* Illegal byte sequence. */ + FST_STATUS_MAX_VALUE = 0xffff /* Status max value */ +} Common_status; + +#endif // !FT_STATUS_H diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_trace.c b/bsp/ft2004/libraries/bsp/standlone/ft_trace.c new file mode 100644 index 0000000000..b3cc4d831d --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_trace.c @@ -0,0 +1,57 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-15 11:27:24 + * @LastEditTime: 2021-05-25 10:52:32 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#include "ft_trace.h" +#include "ft_printf.h" + + +void Sdmmc_TraceHeapAlloc(const char *tag) +{ + +} + +void dump_hex(const u8 *ptr, u32 buflen, const char *tag) +{ + unsigned char *buf = (unsigned char *)ptr; + u32 i, j; + + Ft_printf("dump hex for %s\r\n", tag); + for (i = 0; i < buflen; i += 16) + { + Ft_printf("%08X: ", ptr + i); + + for (j = 0; j < 16; j++) + { + if (i + j < buflen) + { + Ft_printf("%02X ", buf[i + j]); + } + else + { + Ft_printf(" "); + } + } + Ft_printf(" "); + + for (j = 0; j < 16; j++) + { + if (i + j < buflen) + { + Ft_printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + } + } + Ft_printf("\r\n"); + } +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_trace.h b/bsp/ft2004/libraries/bsp/standlone/ft_trace.h new file mode 100644 index 0000000000..1c2ac0cb2d --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_trace.h @@ -0,0 +1,52 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-15 11:27:14 + * @LastEditTime: 2021-04-16 13:40:55 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef _FT_TRACE_H_ +#define _FT_TRACE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_debug.h" + +/* define debug log function */ +#define FT_MEM_TRACE_ENABLED +#define FT_MEM_TRACE_TAG "FT_MEM" +#ifdef FT_MEM_TRACE_ENABLED +#define FT_MEM_TRACE(format, ...) FT_DEBUG_PRINT_I(FT_MEM_TRACE_TAG, format, ##__VA_ARGS__) +#else +#define FT_MEM_TRACE(format, ...) +#endif + +#define FT_LOGIC_TRACE_ENABLED +#define FT_LOGIC_TRACE_TAG "FT_LOGIC" +#ifdef FT_LOGIC_TRACE_ENABLED +#define FT_LOGIC_TRACE(format, ...) FT_DEBUG_PRINT_I(FT_LOGIC_TRACE_TAG, format, ##__VA_ARGS__) +#define FT_MEM_TRACE_DUMP(buf, buflen, tag) dump_hex((buf), (buflen), (tag)) +#else +#define FT_LOGIC_TRACE(format, ...) +#define FT_MEM_TRACE_DUMP(buf, buflen, tag) +#endif + +#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') + void dump_hex(const u8 *ptr, u32 buflen, const char *tag); + void Sdmmc_TraceHeapAlloc(const char *tag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_types.h b/bsp/ft2004/libraries/bsp/standlone/ft_types.h new file mode 100644 index 0000000000..970d3e4e06 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_types.h @@ -0,0 +1,75 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-11 10:18:14 + * @Description:  This files is for definition of system-level types + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_TYPES_H +#define FT_TYPES_H +#include +#include + +/* Constant Definitions */ + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#define FT_NULL NULL + +#define FT_COMPONENT_IS_READLY 0x11111111U +#define FT_COMPONENT_IS_STARTED 0x22222222U + +#define __STATIC_INLINE static inline + +#define FT_OUT /* 表示输出参数,指针指向的值会修改,且不会读 */ +#define FT_IN /* 表示输入参数,指针指向的值不会修改 */ +#define FT_INOUT /* 表示输入输出参数,指针指向的值会修改,且会读取 */ +#define FT_IO volatile + +typedef char s8; +typedef unsigned char u8; +typedef short s16; +typedef unsigned short u16; +typedef int s32; +typedef unsigned int u32; +typedef unsigned long long u64; +typedef long long s64; +typedef int ft_base_t; +typedef ft_base_t bool_t; + +typedef intptr_t INTPTR; +typedef uintptr_t UINTPTR; +typedef ptrdiff_t PTRDIFF; + +#define __STATIC_INLINE static inline +#define LOCAL static + +#define LLSB(x) ((x)&0xff) /* 32bit word byte/word swap macros */ +#define LNLSB(x) (((x) >> 8) & 0xff) +#define LNMSB(x) (((x) >> 16) & 0xff) +#define LMSB(x) (((x) >> 24) & 0xff) +#define U32SWAP(x) ((LLSB(x) << 24) | \ + (LNLSB(x) << 16) | \ + (LNMSB(x) << 8) | \ + (LMSB(x))) + +#define FT_SWAP32(x) U32SWAP((u32)x) + +#endif // diff --git a/bsp/ft2004/libraries/bsp/standlone/inbyte.c b/bsp/ft2004/libraries/bsp/standlone/inbyte.c new file mode 100644 index 0000000000..6eff625890 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/inbyte.c @@ -0,0 +1,21 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 15:31:34 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_parameters.h" +#include "ft_uart_hw.h" + +u8 inbyte(void) +{ + return FUart_RecvByte(FT_STDIN_BASEADDRESS); +} diff --git a/bsp/ft2004/libraries/bsp/standlone/outbyte.c b/bsp/ft2004/libraries/bsp/standlone/outbyte.c new file mode 100644 index 0000000000..3a9a1bb21c --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/outbyte.c @@ -0,0 +1,21 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 17:54:32 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_parameters.h" +#include "ft_uart_hw.h" + +void outbyte(char byte) +{ + FUart_SendByte(FT_STDOUT_BASEADDRESS, byte); +} diff --git a/bsp/ft2004/libraries/cpu/ft_aarch32_asm.h b/bsp/ft2004/libraries/cpu/ft_aarch32_asm.h new file mode 100644 index 0000000000..d39b221a2d --- /dev/null +++ b/bsp/ft2004/libraries/cpu/ft_aarch32_asm.h @@ -0,0 +1,319 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-01-22 16:30:56 + * @LastEditTime: 2021-05-24 14:35:53 + * @LastEditors: Please set LastEditors + * @Description: In User Settings Edit + * @FilePath: \project_freertos\devices\ft2004\bsp\core\ft_asm.h + */ + +#ifndef FT_AARCH32_ASM_H +#define FT_AARCH32_ASM_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" + +#define __ASM __asm +#define __STRINGIFY(x) #x +/* C语言实现MCR指令 */ +#define __MCR(coproc, opcode_1, src, CRn, CRm, opcode_2) \ + __ASM volatile("MCR " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \ + "%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " __STRINGIFY(opcode_2) \ + : \ + : "r"(src) \ + : "memory"); + +/* C语言实现MRC指令 */ +#define __MRC(coproc, opcode_1, CRn, CRm, opcode_2) \ + ({ \ + u32 __dst; \ + __ASM volatile("MRC " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \ + "%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " __STRINGIFY(opcode_2) \ + : "=r"(__dst)::"memory"); \ + __dst; \ + }) + + __attribute__((always_inline)) __STATIC_INLINE u32 __get_VBAR(void) + { + return __MRC(15, 0, 12, 0, 0); + } + + __attribute__((always_inline)) __STATIC_INLINE void __set_VBAR(u32 vbar) + { + __MCR(15, 0, vbar, 12, 0, 0); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_igrpen0_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 6); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_igrpen0_get(void) + { + return __MRC(15, 0, 12, 12, 6); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_igrpen1_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 7); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_igrpen1_get(void) + { + return __MRC(15, 0, 12, 12, 7); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_ctlr_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 4); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_ctlr_get(void) + { + return __MRC(15, 0, 12, 12, 4); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_hppir0_get(void) + { + return __MRC(15, 0, 12, 8, 2); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_bpr_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 3); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_bpr_get(void) + { + return __MRC(15, 0, 12, 12, 3); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_hppir1_get(void) + { + return __MRC(15, 0, 12, 12, 2); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_eoir0_set(u32 value) + { + __MCR(15, 0, value, 12, 8, 1); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_eoir1_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 1); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_pmr_set(u32 value) + { + __MCR(15, 0, value, 4, 6, 0); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_pmr_get(void) + { + return __MRC(15, 0, 4, 6, 0); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_iar1_get(void) + { + return __MRC(15, 0, 12, 12, 0); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_sre_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 5); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_sre_get(void) + { + return __MRC(15, 0, 12, 12, 5); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_rpr_get(void) + { + return __MRC(15, 0, 12, 11, 3); + } + + /* Generic Timer registers */ + /** + * @name: arm_aarch32_cntfrq_get + * @msg: This register is provided so that software can discover the frequency of the system counter. + * @return {__STATIC_INLINEu32}: frequency of the system counter + */ + __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntfrq_get(void) + { + return __MRC(15, 0, 14, 0, 0); + } + + /** + * @name: arm_aarch32_cnthv_tval_get + * @msg: Provides AArch32 access to the timer value for the EL2 virtual timer. + * @return {__STATIC_INLINEu32}: EL2 virtual timer Cnt. + */ + __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cnthv_tval_get(void) + { + return __MRC(15, 0, 14, 3, 0); + } + + /** + * @name: arm_aarch32_cnthv_ctl_set + * @msg: Provides AArch32 access to the control register for the EL2 virtual timer. + * @in param {u32}: RegValue;ENABLE: bit [0] 0 Timer disabled,1 Timer enabled. + * IMASK,bit [1]: 0 Timer interrupt is not masked by the IMASK bit. 1 Timer interrupt is masked by the IMASK bit. + * ISTATUS, bit [2]: 0 Timer condition is not met. 1 Timer condition is met. rea-only + */ + __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cnthv_ctl_set(u32 RegValue) + { + __MCR(15, 0, RegValue, 14, 3, 1); + } + + /** + * @name: arm_aarch32_cnthv_ctl_get + * @msg: Provides AArch32 access to the control register for the EL2 virtual timer. + * @return {__STATIC_INLINEu32}: RegValue;ENABLE: bit [0] 0 Timer disabled,1 Timer enabled. + * IMASK,bit [1]: 0 Timer interrupt is not masked by the IMASK bit. 1 Timer interrupt is masked by the IMASK bit. + * ISTATUS, bit [2]: 0 Timer condition is not met. 1 Timer condition is met. read-only + */ + __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cnthv_ctl_get(void) + { + return __MRC(15, 0, 14, 3, 1); + } + + /** + * @name: arm_aarch32_cnthv_tval_set + * @msg: Provides AArch32 access to the timer value for the EL2 virtual timer. + * @in param {u32}: TimerValue, bits [31:0] The TimerValue view of the EL2 virtual timer. + */ + __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cnthv_tval_set(u32 RegValue) + { + __MCR(15, 0, RegValue, 14, 3, 0); + } + + /** + * @name: arm_aarch32_cntvct_get + * @msg: Read the register that holds the 64-bit virtual count value. The virtual count value is equal to the physical count value visible in CNTPCT minus the virtual offset visible in CNTVOFF. + * @return {__STATIC_INLINEu64}Bits [63:0] Virtual count value. + */ + __attribute__((always_inline)) __STATIC_INLINE u64 arm_aarch32_cntvct_get(void) + { + /* "r0" --- low, + "r1" --- hi + */ + u32 low; + u32 hi; + __asm__ volatile( + ".word 0xec510f1e \n" /* mrrc p15, 1, r0, r1, c14 */ + "mov %0, r0 \n" + "mov %1, r1 \n" + : "=&r"(low), "=&r"(hi)); + return (((u64)hi) << 32) | low; + } + + /* physical */ + + /** + * @name: arm_aarch32_cntp_tval_get + * @msg: Read the register that holds the timer value for the EL1 physical timer. + * @return {__STATIC_INLINEu32}: TimerValue, bits [31:0] The TimerValue view of the EL1 physical timer. + */ + __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntp_tval_get(void) + { + return __MRC(15, 0, 14, 2, 0); + } + + /** + * @name: arm_aarch32_cntp_tval_set + * @msg: write the register that control register for the EL1 physical timer. + * @in param {u32}: TimerValue, bits [31:0] The TimerValue view of the EL1 physical timer. + */ + __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cntp_tval_set(u32 RegValue) + { + __MCR(15, 0, RegValue, 14, 2, 0); + } + + /** + * @name: arm_aarch32_cntp_ctl_set + * @msg: write the register that control register for the EL1 physical timer. + * @in param {u32}: ENABLE, bit[0] Enables the timer ; IMASK, bit [1] Timer interrupt mask bit; ISTATUS, bit [2] The status of the timer. + */ + __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cntp_ctl_set(u32 RegValue) + { + __MCR(15, 0, RegValue, 14, 2, 1); + } + + /** + * @name: arm_aarch32_cntp_ctl_get + * @msg: Read the register that control register for the EL1 physical timer. + * @return {__STATIC_INLINEu32}: ENABLE, bit[0] Enables the timer ; IMASK, bit [1] Timer interrupt mask bit; ISTATUS, bit [2] The status of the timer. + */ + __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntp_ctl_get(void) + { + return __MRC(15, 0, 14, 2, 1); + } + + /** + * @name: arm_aarch32_cntpct_get + * @msg: Read the register that holds the 64-bit physical count value. + * @return {__STATIC_INLINEu64} CompareValue, bits [63:0] Physical count value. + */ + __attribute__((always_inline)) __STATIC_INLINE u64 arm_aarch32_cntpct_get(void) + { + /* "r0" --- low, + "r1" --- hi + */ + u32 low; + u32 hi; + __asm__ volatile( + + ".word 0xec510f0e \n" /* mrrc p15, 0, r0, r1, c14 */ + "mov %0, r0 \n" + "mov %1, r1 \n" + : "=&r"(low), "=&r"(hi)); + return (((u64)hi) << 32) | low; + } + +#define IRQ_DISABLE() \ + __asm volatile("CPSID i" :: \ + : "memory"); \ + __asm volatile("DSB"); \ + __asm volatile("ISB"); + +#define IRQ_ENABLE() \ + __asm volatile("CPSIE i" :: \ + : "memory"); \ + __asm volatile("DSB"); \ + __asm volatile("ISB"); + + /* the exception stack without VFP registers */ + struct ft_hw_exp_stack + { + u32 r0; + u32 r1; + u32 r2; + u32 r3; + u32 r4; + u32 r5; + u32 r6; + u32 r7; + u32 r8; + u32 r9; + u32 r10; + u32 fp; + u32 ip; + u32 sp; + u32 lr; + u32 pc; + u32 cpsr; + }; + +#ifdef __cplusplus +} +#endif + +#endif // ! diff --git a/bsp/ft2004/libraries/doc/ChangeLog.md b/bsp/ft2004/libraries/doc/ChangeLog.md new file mode 100644 index 0000000000..b0d6bd9d11 --- /dev/null +++ b/bsp/ft2004/libraries/doc/ChangeLog.md @@ -0,0 +1,90 @@ +# FT2004-driver ChangeLog + +Change log since v0.1.0 + +# FT2004-driver V0.4.2 Change Log + +## bsp/ft_can + +1. support can controller + +## drivers/rtthread + +1. adapt can drivers to rt-thread + +# FT2004-driver V0.4.2 Change Log + +## bsp/ft_spi + +1. support spi ctrl to read and write spi flash in rt-thread +2. notes that spi chip select pin is ctrl in the way of gpio + +## bsp/ft_gpio + +1. support group A gpio ctrl, include w/r status, change direction + +## component/s25fsxx + +1. support s24fs serial spi flash operations + +## drivers/rtthread + +1. adapt spi drivers to rt-thread SFUD flash support component + +# FT2004-driver V0.4.1 Change Log + +## bsp/ft_i2c + +1. support irq read and write for i2c +2. delete unused rtc and eeprom component + +# FT2004-driver V0.4.0 Change Log + +## component/sdmmc + +1. add sd2.0 comand support +2. modify function and variable name by code convention + +# FT2004-driver V0.3.2 Change Log + +## Docs + +1. add ChangeLog.md + +## bsp/standlone + +1. Added ft_cache.c ft_cache.h + +## bsp/ft_gmac + +1. Added descriptor cache handling + +## drivers/rtthread + +1. Modify the bug for drv_qspi + +1. Added cache to drv_sdctrl + +# FT2004-driver V0.3.1 Change Log + +## Docs + +1. add ChangeLog.md + +## bsp/ft_qspi + +1. Complete the writing of QSPI driver + +2. Test bsp api in rtthread + +## drivers/rtthread + +1. add drv_qspi.c + +2. Access to the SUFD framework + +3. Test functions through the rtthread device management framework + +## exhibition + +![](./figures/v0.3.0_add.png) diff --git a/bsp/ft2004/libraries/doc/figures/v0.3.0_add.png b/bsp/ft2004/libraries/doc/figures/v0.3.0_add.png new file mode 100644 index 0000000000000000000000000000000000000000..d7e6b398490234df5adbf4ceffc91586da1621f5 GIT binary patch literal 297513 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 z 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
SB!G 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�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�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 Y>7MZ&AurM=yClG)t7)K7tY#DRFK=p8xc~qF literal 0 HcmV?d00001 diff --git a/bsp/ft2004/libraries/include/asmArm.h b/bsp/ft2004/libraries/include/asmArm.h new file mode 100644 index 0000000000..7dd7153690 --- /dev/null +++ b/bsp/ft2004/libraries/include/asmArm.h @@ -0,0 +1,37 @@ +/* + * @ : Copyright (c) 2021 Phytium Information Technology, Inc. + * + * SPDX-License-Identifier: Apache-2.0. + * + * @Date: 2021-01-20 10:07:04 + * @LastEditTime: 2021-05-24 14:36:34 + * @LastEditors: Please set LastEditors + * @Description: In User Settings Edit + * @FilePath: \project_freertos\devices\ft2004\gcc\asmArm.h + */ +#ifndef ASMARM_H +#define ASMARM_H + +#define FUNC_LABEL(func) \ + func: + +#if (defined __GNUC__) +#define FUNC_BEGIN(func) \ + .thumb; \ + .thumb_func; \ + .balign 4; \ + FUNC_LABEL(func) +#else /* !__GNUC__ */ +#define FUNC_BEGIN(func) \ + .thumb; \ + .balign 4; \ + FUNC_LABEL(func) +#endif /* __GNUC__ */ + +#define FUNC(sym) sym +#define FUNC_END(func) .size FUNC(func), .- FUNC(func) + +#define Swap64(var64) var64 +#define Swap32(var32) var32 + +#endif // !ASMARM_H diff --git a/bsp/ft2004/libraries/readme.md b/bsp/ft2004/libraries/readme.md new file mode 100644 index 0000000000..c8d372b5f2 --- /dev/null +++ b/bsp/ft2004/libraries/readme.md @@ -0,0 +1,69 @@ +# README + +- FT2004 rtos 驱动介绍 + +## 1. 当前版本 + +- V0.4.2 + +## 2. 关于此文档 + +- 本文档提供此项目框架性和基本功能介绍 + +- 详细的硬件 bsp 介绍请阅读 doc 文件中模块子文档。 + +## 3. 编译器版本 + +- gcc-arm-none-eabi-10-2020-q4-major + +## 4. 文件结构介绍 + +| 目录名 | 内容 | +| --------- | ---------------------------------------- | +| bsp | 存放芯片上的外设,例如网卡,i2c 和串口等 | +| component | 板载外设驱动 ,rtc、eeprom、sdmmc 等 | +| cpu | cpu 架构方面指令 | +| doc | 具体外设文档 | +| drivers | 与不同 rtos 进行耦合的驱动 | +| gcc | gcc 编译环境下的启动、链接文件 | +| include | 平台相关的包含 | + +## 5. 支持外设 + +| 外设名 | 备注 | +| -------- | ---------------------- | +| 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 控制器 | + +## 6. 使用实例 + +[freertos](https://gitee.com/phytium_embedded/ft2004-freertos) + +## 7. 参考资源 + +armv8 Architecture Reference Manual + +FT-2000/4 软件编程手册-V1.4 + +FT-2000/4 硬件设计指导手册 + +FT-2000 四核处理器数据手册 V1.6 + +## 8. 贡献方法 + +请联系飞腾嵌入式软件部 + +huanghe@phytium.com.cn + +zhugengyu@phytium.com.cn + +## 9. 许可协议 + +Apache License. diff --git a/bsp/ft2004/make.sh b/bsp/ft2004/make.sh new file mode 100644 index 0000000000..4fd5c685e0 --- /dev/null +++ b/bsp/ft2004/make.sh @@ -0,0 +1,16 @@ +### + # @Author: hh + # @Date: 2020-12-23 13:53:50 + # @LastEditTime: 2021-05-18 16:48:25 + # @LastEditors: Please set LastEditors + # @Description: In User Settings Edit + # @FilePath: \ft\bare\2_base\factory.sh +### +#/bin/sh +# scons --clean +# ./update.sh +scons -j8 +rm /mnt/d/project/tftp/rtthread.bin +cp ./rtthread.bin /mnt/d/project/tftp/ + +# arm-none-eabi-objdump -D -m arm ft2004.elf > rtt.dis \ No newline at end of file diff --git a/bsp/ft2004/rtconfig.h b/bsp/ft2004/rtconfig.h new file mode 100644 index 0000000000..20bba6a139 --- /dev/null +++ b/bsp/ft2004/rtconfig.h @@ -0,0 +1,286 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Project Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 32 +#define RT_USING_SMP +#define RT_CPUS_NR 4 +#define RT_ALIGN_SIZE 128 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 4096 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 512 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMHEAP +#define RT_USING_SLAB +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_INTERRUPT_INFO +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 4096 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40004 +#define ARCH_ARM +#define ARCH_ARM_CORTEX_A +#define RT_USING_GIC_V3 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_CMD_SIZE 128 +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + +#define RT_USING_DFS +#define DFS_USING_WORKDIR +#define DFS_FILESYSTEMS_MAX 2 +#define DFS_FILESYSTEM_TYPES_MAX 2 +#define DFS_FD_MAX 16 +#define RT_USING_DFS_ELMFAT + +/* elm-chan's FatFs, Generic FAT Filesystem Module */ + +#define RT_DFS_ELM_CODE_PAGE 437 +#define RT_DFS_ELM_WORD_ACCESS +#define RT_DFS_ELM_USE_LFN_3 +#define RT_DFS_ELM_USE_LFN 3 +#define RT_DFS_ELM_LFN_UNICODE_0 +#define RT_DFS_ELM_LFN_UNICODE 0 +#define RT_DFS_ELM_MAX_LFN 255 +#define RT_DFS_ELM_DRIVES 2 +#define RT_DFS_ELM_MAX_SECTOR_SIZE 512 +#define RT_DFS_ELM_REENTRANT +#define RT_USING_DFS_DEVFS + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SERIAL +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 256 +#define RT_USING_CAN +#define RT_USING_SDIO +#define RT_SDIO_STACK_SIZE 512 +#define RT_SDIO_THREAD_PRIORITY 15 +#define RT_MMCSD_STACK_SIZE 1024 +#define RT_MMCSD_THREAD_PREORITY 22 +#define RT_MMCSD_MAX_PARTITION 16 +#define RT_USING_SPI +#define RT_USING_QSPI +#define RT_USING_SFUD +#define RT_SFUD_USING_SFDP +#define RT_SFUD_USING_FLASH_INFO_TABLE +#define RT_SFUD_USING_QSPI +#define RT_SFUD_SPI_MAX_HZ 50000000 + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_USING_LIBC +#define RT_USING_POSIX +#define RT_LIBC_FIXED_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + +#define RT_USING_NETDEV +#define NETDEV_USING_IFCONFIG +#define NETDEV_USING_PING +#define NETDEV_USING_NETSTAT +#define NETDEV_USING_AUTO_DEFAULT +#define NETDEV_IPV4 1 +#define NETDEV_IPV6 0 + +/* light weight TCP/IP stack */ + +#define RT_USING_LWIP +#define RT_USING_LWIP212 +#define RT_LWIP_MEM_ALIGNMENT 4 +#define RT_LWIP_IGMP +#define RT_LWIP_ICMP +#define RT_LWIP_DNS + +/* Static IPv4 Address */ + +#define RT_LWIP_IPADDR "192.168.3.20" +#define RT_LWIP_GWADDR "192.168.3.1" +#define RT_LWIP_MSKADDR "255.255.255.0" +#define RT_LWIP_UDP +#define RT_LWIP_TCP +#define RT_LWIP_RAW +#define RT_MEMP_NUM_NETCONN 8 +#define RT_LWIP_PBUF_NUM 16 +#define RT_LWIP_RAW_PCB_NUM 4 +#define RT_LWIP_UDP_PCB_NUM 4 +#define RT_LWIP_TCP_PCB_NUM 4 +#define RT_LWIP_TCP_SEG_NUM 40 +#define RT_LWIP_TCP_SND_BUF 8196 +#define RT_LWIP_TCP_WND 8196 +#define RT_LWIP_TCPTHREAD_PRIORITY 10 +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 +#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_PRIORITY 12 +#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define SO_REUSE 1 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_RCVBUF 1 +#define LWIP_SO_LINGER 0 +#define LWIP_NETIF_LOOPBACK 0 +#define RT_LWIP_USING_PING + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + +#define RT_USING_ULOG +#define ULOG_OUTPUT_LVL_W +#define ULOG_OUTPUT_LVL 4 +#define ULOG_ASSERT_ENABLE +#define ULOG_LINE_BUF_SIZE 128 + +/* log format */ + +#define ULOG_USING_COLOR +#define ULOG_OUTPUT_TIME +#define ULOG_OUTPUT_LEVEL +#define ULOG_OUTPUT_TAG +#define ULOG_BACKEND_USING_CONSOLE + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + + +/* tools packages */ + + +/* system packages */ + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + +#define FT2004 + +/* Hardware Drivers Config */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_UART +#define RT_USING_UART1 +#define BSP_USING_SDC +#define BSP_USING_GMAC +#define BSP_USING_GMAC1 +#define RT_LWIP_ETH_PAD_SIZE 2 +#define BSP_USE_SPI +#define BSP_USE_GPIO +#define BSP_USE_CAN +#define BSP_USING_CAN0 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/ft2004/rtconfig.py b/bsp/ft2004/rtconfig.py new file mode 100644 index 0000000000..ea482b8282 --- /dev/null +++ b/bsp/ft2004/rtconfig.py @@ -0,0 +1,59 @@ +import os + + +# toolchains options +ARCH='arm' +CPU='cortex-a' +CROSS_TOOL='gcc' + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + +# only support GNU GCC compiler. +PLATFORM = 'gcc' +EXEC_PATH = '/usr/lib/arm-none-eabi/bin' +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +LIBPATH = '/usr/lib/arm-none-eabi/lib' + + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + CXX = PREFIX + 'g++' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + STRIP = PREFIX + 'strip' + + + DEVICE = ' -march=armv8-a -mfpu=vfpv4-d16 -ftree-vectorize -ffast-math -mfloat-abi=soft --specs=nano.specs --specs=nosys.specs -fno-builtin ' + # DEVICE = ' -march=armv7-a -mfpu=vfpv3-d16 -ftree-vectorize -ffast-math -mfloat-abi=hard' + CFLAGS = DEVICE + ' -Wall' + AFLAGS = ' -c'+ DEVICE + ' -fsingle-precision-constant -fno-builtin -x assembler-with-cpp -D__ASSEMBLY__' + LINK_SCRIPT = 'ft_aarch32.lds' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors'+\ + ' -T %s' % LINK_SCRIPT + + CPATH = '' + LPATH = LIBPATH + + # generate debug info in all cases + AFLAGS += ' -gdwarf-2' + CFLAGS += ' -g -gdwarf-2' + + if BUILD == 'debug': + CFLAGS += ' -O0' + else: + CFLAGS += ' -O2' + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' +\ + SIZE + ' $TARGET \n' From a1677a8f4cd635d032387fafe700855a116d7cb6 Mon Sep 17 00:00:00 2001 From: Bernard Xiong Date: Thu, 27 May 2021 17:07:57 +0800 Subject: [PATCH 118/255] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 5c8cd5d766..5b85dc2d0f 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,3 @@ - + - From d6e86a67bbf791d19d7637cdcca69de3904470af Mon Sep 17 00:00:00 2001 From: zhouji <956133287@qq.com> Date: Mon, 24 May 2021 17:09:29 +0800 Subject: [PATCH 119/255] =?UTF-8?q?[add]=20=E5=9C=A8cortex-a=E4=B8=AD?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=EF=BC=8C=E6=89=93=E5=BC=80RT=5FUSING=5FCPU?= =?UTF-8?q?=5FFFS=E5=AE=8F=E5=AE=9A=E4=B9=89=E6=97=B6=E7=9A=84=5Frt=5Fffs?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/arm/cortex-a/cpu.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libcpu/arm/cortex-a/cpu.c b/libcpu/arm/cortex-a/cpu.c index 7367bddd9f..c95c58a13c 100644 --- a/libcpu/arm/cortex-a/cpu.c +++ b/libcpu/arm/cortex-a/cpu.c @@ -75,4 +75,21 @@ RT_WEAK void rt_hw_cpu_shutdown() } } +#ifdef RT_USING_CPU_FFS +/** + * This function finds the first bit set (beginning with the least significant bit) + * in value and return the index of that bit. + * + * Bits are numbered starting at 1 (the least significant bit). A return value of + * zero from any of these functions means that the argument was zero. + * + * @return return the index of the first bit set. If value is 0, then this function + * shall return 0. + */ +int __rt_ffs(int value) +{ + return __builtin_ffs(value); +} +#endif + /*@}*/ From 3350b0ba4e091f21537c89ecc727a05d56d112be Mon Sep 17 00:00:00 2001 From: zhouji <956133287@qq.com> Date: Mon, 24 May 2021 17:19:05 +0800 Subject: [PATCH 120/255] =?UTF-8?q?[update]=20=E6=95=B4=E7=90=86cortex-a?= =?UTF-8?q?=20kconfig=E8=8F=9C=E5=8D=95=EF=BC=8C=E5=B9=B6=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=9B=B8=E5=85=B3BSP=E7=9A=84=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ft2004/.config | 3 +-- bsp/ft2004/Kconfig | 1 + bsp/ft2004/rtconfig.h | 1 + bsp/imx6ul/.config | 3 +-- bsp/imx6ul/Kconfig | 1 + bsp/imx6ul/rtconfig.h | 1 + bsp/qemu-vexpress-a9/.config | 3 +-- bsp/qemu-vexpress-a9/Kconfig | 1 + bsp/qemu-vexpress-a9/rtconfig.h | 1 + examples/utest/configs/utest_self/config.h | 1 + libcpu/Kconfig | 21 ++++++++++----------- 11 files changed, 20 insertions(+), 17 deletions(-) diff --git a/bsp/ft2004/.config b/bsp/ft2004/.config index 1a27a6c8b4..1bd8c76ede 100644 --- a/bsp/ft2004/.config +++ b/bsp/ft2004/.config @@ -77,12 +77,11 @@ 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_RT_USING_CPU_FFS=y 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 # diff --git a/bsp/ft2004/Kconfig b/bsp/ft2004/Kconfig index 1bee562e48..6470d41804 100644 --- a/bsp/ft2004/Kconfig +++ b/bsp/ft2004/Kconfig @@ -24,6 +24,7 @@ config FT2004 select ARCH_ARM_CORTEX_A select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN + select RT_USING_GIC_V3 default y diff --git a/bsp/ft2004/rtconfig.h b/bsp/ft2004/rtconfig.h index 20bba6a139..17f4dd20e8 100644 --- a/bsp/ft2004/rtconfig.h +++ b/bsp/ft2004/rtconfig.h @@ -50,6 +50,7 @@ #define RT_CONSOLE_DEVICE_NAME "uart1" #define RT_VER_NUM 0x40004 #define ARCH_ARM +#define RT_USING_CPU_FFS #define ARCH_ARM_CORTEX_A #define RT_USING_GIC_V3 diff --git a/bsp/imx6ul/.config b/bsp/imx6ul/.config index 4fa2072fb4..6d71016845 100644 --- a/bsp/imx6ul/.config +++ b/bsp/imx6ul/.config @@ -74,12 +74,11 @@ CONFIG_RT_CONSOLEBUF_SIZE=128 CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" CONFIG_RT_VER_NUM=0x40004 CONFIG_ARCH_ARM=y -# CONFIG_RT_USING_CPU_FFS is not set +CONFIG_RT_USING_CPU_FFS=y CONFIG_ARCH_ARM_CORTEX_A=y # CONFIG_RT_SMP_AUTO_BOOT is not set CONFIG_RT_USING_GIC_V2=y # CONFIG_RT_USING_GIC_V3 is not set -# CONFIG_RT_NO_USING_GIC is not set CONFIG_ARCH_ARM_CORTEX_A7=y # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set diff --git a/bsp/imx6ul/Kconfig b/bsp/imx6ul/Kconfig index 9fbc95e841..9cd9ab8dd5 100644 --- a/bsp/imx6ul/Kconfig +++ b/bsp/imx6ul/Kconfig @@ -18,6 +18,7 @@ config PKGS_DIR config BOARD_IMX6UL bool select ARCH_ARM_CORTEX_A7 + select RT_USING_GIC_V2 default y source "$RTT_DIR/Kconfig" diff --git a/bsp/imx6ul/rtconfig.h b/bsp/imx6ul/rtconfig.h index 4cc1b24df0..e48a4fe0aa 100644 --- a/bsp/imx6ul/rtconfig.h +++ b/bsp/imx6ul/rtconfig.h @@ -45,6 +45,7 @@ #define RT_CONSOLE_DEVICE_NAME "uart1" #define RT_VER_NUM 0x40004 #define ARCH_ARM +#define RT_USING_CPU_FFS #define ARCH_ARM_CORTEX_A #define RT_USING_GIC_V2 #define ARCH_ARM_CORTEX_A7 diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config index f9fa185ce7..290cddd947 100644 --- a/bsp/qemu-vexpress-a9/.config +++ b/bsp/qemu-vexpress-a9/.config @@ -77,12 +77,11 @@ CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" CONFIG_RT_VER_NUM=0x40004 CONFIG_ARCH_ARM=y -# CONFIG_RT_USING_CPU_FFS is not set +CONFIG_RT_USING_CPU_FFS=y CONFIG_ARCH_ARM_CORTEX_A=y # CONFIG_RT_SMP_AUTO_BOOT is not set CONFIG_RT_USING_GIC_V2=y # CONFIG_RT_USING_GIC_V3 is not set -# CONFIG_RT_NO_USING_GIC is not set CONFIG_ARCH_ARM_CORTEX_A9=y # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set diff --git a/bsp/qemu-vexpress-a9/Kconfig b/bsp/qemu-vexpress-a9/Kconfig index 25921e6e7c..b2bdfe704d 100644 --- a/bsp/qemu-vexpress-a9/Kconfig +++ b/bsp/qemu-vexpress-a9/Kconfig @@ -23,6 +23,7 @@ config SOC_VEXPRESS_A9 select ARCH_ARM_CORTEX_A9 select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN + select RT_USING_GIC_V2 default y source "$BSP_DIR/drivers/Kconfig" diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h index eb7b915d86..047e6f929c 100644 --- a/bsp/qemu-vexpress-a9/rtconfig.h +++ b/bsp/qemu-vexpress-a9/rtconfig.h @@ -54,6 +54,7 @@ #define RT_CONSOLE_DEVICE_NAME "uart0" #define RT_VER_NUM 0x40004 #define ARCH_ARM +#define RT_USING_CPU_FFS #define ARCH_ARM_CORTEX_A #define RT_USING_GIC_V2 #define ARCH_ARM_CORTEX_A9 diff --git a/examples/utest/configs/utest_self/config.h b/examples/utest/configs/utest_self/config.h index 2080a544b0..fa94023c42 100644 --- a/examples/utest/configs/utest_self/config.h +++ b/examples/utest/configs/utest_self/config.h @@ -54,6 +54,7 @@ #define RT_CONSOLE_DEVICE_NAME "uart0" #define RT_VER_NUM 0x40004 #define ARCH_ARM +#define RT_USING_CPU_FFS #define ARCH_ARM_CORTEX_A #define RT_USING_GIC_V2 #define ARCH_ARM_CORTEX_A9 diff --git a/libcpu/Kconfig b/libcpu/Kconfig index bb54b487c7..d0fa40d1bd 100644 --- a/libcpu/Kconfig +++ b/libcpu/Kconfig @@ -57,25 +57,24 @@ config ARCH_ARM_ARM11 config ARCH_ARM_CORTEX_A bool select ARCH_ARM + select RT_USING_CPU_FFS if ARCH_ARM_CORTEX_A config RT_SMP_AUTO_BOOT bool default n - choice - prompt "GIC controller selection" - default RT_USING_GIC_V2 + config RT_USING_GIC_V2 + bool + default n - config RT_USING_GIC_V2 - bool " Gic version 2 " + config RT_USING_GIC_V3 + bool + default n - config RT_USING_GIC_V3 - bool " Gic version 3 " - - config RT_NO_USING_GIC - bool " GIC controller is not used " - endchoice + config RT_NO_USING_GIC + bool + default y if !RT_USING_GIC_V2 && !RT_USING_GIC_V3 endif config ARCH_ARM_CORTEX_A5 From d9367468061113b31df5e3488dced157e1d0dabf Mon Sep 17 00:00:00 2001 From: tangyuxin Date: Fri, 28 May 2021 10:28:00 +0800 Subject: [PATCH 121/255] [kernel] Improve kernel stability --- src/ipc.c | 1 + src/thread.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/ipc.c b/src/ipc.c index 111d724c23..22e0f06bc6 100755 --- a/src/ipc.c +++ b/src/ipc.c @@ -124,6 +124,7 @@ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list, break; default: + RT_ASSERT(0); break; } diff --git a/src/thread.c b/src/thread.c index 34e96077d1..e03c027eff 100644 --- a/src/thread.c +++ b/src/thread.c @@ -358,6 +358,8 @@ RTM_EXPORT(rt_thread_startup); */ rt_err_t rt_thread_detach(rt_thread_t thread) { + rt_base_t lock; + /* thread check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); @@ -377,12 +379,18 @@ rt_err_t rt_thread_detach(rt_thread_t thread) /* release thread timer */ rt_timer_detach(&(thread->thread_timer)); + /* disable interrupt */ + lock = rt_hw_interrupt_disable(); + /* change stat */ thread->stat = RT_THREAD_CLOSE; /* detach thread object */ rt_object_detach((rt_object_t)thread); + /* enable interrupt */ + rt_hw_interrupt_enable(lock); + return RT_EOK; } RTM_EXPORT(rt_thread_detach); From fefaac854c03a2dfea4a1f13ac05e45a348f44f1 Mon Sep 17 00:00:00 2001 From: wangqiang Date: Fri, 28 May 2021 14:20:49 +0800 Subject: [PATCH 122/255] =?UTF-8?q?=E5=AE=8C=E5=96=84i2c,uart,LCD=E7=9A=84?= =?UTF-8?q?kconfig=EF=BC=8C=E4=BF=AE=E5=A4=8D=E4=BA=86I2C=E7=9A=84imxrt=5F?= =?UTF-8?q?i2c=5Fmst=5Fxfer=E5=87=BD=E6=95=B0=E8=AF=BB=E5=8F=96=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=89=8D=E4=BC=9A=E5=A4=9A=E8=BF=9B=E8=A1=8C=E4=B8=80?= =?UTF-8?q?=E6=AC=A1=E5=86=99=E5=9C=B0=E5=9D=80=E7=9A=84=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/imxrt/imxrt1064-nxp-evk/board/Kconfig | 75 ++++ bsp/imxrt/imxrt1064-nxp-evk/board/board.c | 413 ++++++++++++++++++++++ bsp/imxrt/libraries/drivers/drv_i2c.c | 8 +- 3 files changed, 489 insertions(+), 7 deletions(-) diff --git a/bsp/imxrt/imxrt1064-nxp-evk/board/Kconfig b/bsp/imxrt/imxrt1064-nxp-evk/board/Kconfig index 5c660b91c7..cd35ef35a3 100644 --- a/bsp/imxrt/imxrt1064-nxp-evk/board/Kconfig +++ b/bsp/imxrt/imxrt1064-nxp-evk/board/Kconfig @@ -32,6 +32,81 @@ menu "On-chip Peripheral Drivers" config BSP_USING_LPUART1 bool "Enable LPUART1" default y + config BSP_USING_LPUART2 + bool "Enable LPUART2" + default n + config BSP_USING_LPUART3 + bool "Enable LPUART3" + default n + config BSP_USING_LPUART4 + bool "Enable LPUART4" + default n + config BSP_USING_LPUART5 + bool "Enable LPUART5" + default n + config BSP_USING_LPUART6 + bool "Enable LPUART6" + default n + config BSP_USING_LPUART7 + bool "Enable LPUART7" + default n + config BSP_USING_LPUART8 + bool "Enable LPUART8" + default n + endif + + menuconfig BSP_USING_I2C + bool "Enable I2C" + select RT_USING_I2C + default n + if BSP_USING_I2C + config BSP_USING_I2C1 + bool "Enable LPI2C1" + default n + config BSP_USING_I2C3 + bool "Enable LPI2C3" + default n + config BSP_USING_I2C4 + bool "Enable LPI2C4" + default n + endif + + menuconfig BSP_USING_LCD + bool "Enable LCD" + default n + if BSP_USING_LCD + config LCD_WIDTH + int "width" + default 480 + + config LCD_HEIGHT + int "height" + default 272 + + config LCD_HFP + int "HFP" + default 4 + config LCD_VFP + int "VFP" + default 4 + config LCD_HBP + int "HBP" + default 8 + config LCD_VBP + int "VBP" + default 2 + config LCD_HSW + int "HSW" + default 40 + config LCD_VSW + int "VSW" + default 10 + config LCD_BL_PIN + int "Backlight ctrl pin" + default 63 + config LCD_RST_PIN + int "Reset pin" + default 2 endif endmenu diff --git a/bsp/imxrt/imxrt1064-nxp-evk/board/board.c b/bsp/imxrt/imxrt1064-nxp-evk/board/board.c index 603cd856c5..f4c0b7c05f 100644 --- a/bsp/imxrt/imxrt1064-nxp-evk/board/board.c +++ b/bsp/imxrt/imxrt1064-nxp-evk/board/board.c @@ -253,6 +253,411 @@ void imxrt_uart_pins_init(void) } #endif /* BSP_USING_LPUART */ +#ifdef BSP_USING_I2C +static void imxrt_i2c_pins_init(void) +{ +#ifdef BSP_USING_I2C1 + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL, /* GPIO_AD_B1_00 is configured as LPI2C1_SCL */ + 1U); /* Software Input On Field: Force input path of pad GPIO_AD_B1_00 */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA, /* GPIO_AD_B1_01 is configured as LPI2C1_SDA */ + 1U); /* Software Input On Field: Force input path of pad GPIO_AD_B1_01 */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL, /* GPIO_AD_B1_00 PAD functional properties : */ + 0xD8B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Enabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 22K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA, /* GPIO_AD_B1_01 PAD functional properties : */ + 0xD8B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Enabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 22K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ +#endif + +#ifdef BSP_USING_I2C3 + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL, /* GPIO_AD_B1_00 is configured as LPI2C1_SCL */ + 1U); /* Software Input On Field: Force input path of pad GPIO_AD_B1_00 */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA, /* GPIO_AD_B1_01 is configured as LPI2C1_SDA */ + 1U); /* Software Input On Field: Force input path of pad GPIO_AD_B1_01 */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL, /* GPIO_AD_B1_00 PAD functional properties : */ + 0xD8B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Enabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 22K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA, /* GPIO_AD_B1_01 PAD functional properties : */ + 0xD8B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Enabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 22K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ +#endif + +#ifdef BSP_USING_I2C4 + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_12_LPI2C4_SCL, /* GPIO_AD_B1_00 is configured as LPI2C1_SCL */ + 1U); /* Software Input On Field: Force input path of pad GPIO_AD_B1_00 */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_13_LPI2C4_SDA, /* GPIO_AD_B1_01 is configured as LPI2C1_SDA */ + 1U); /* Software Input On Field: Force input path of pad GPIO_AD_B1_01 */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_12_LPI2C4_SCL, /* GPIO_AD_B1_00 PAD functional properties : */ + 0xD8B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Enabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 22K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_13_LPI2C4_SDA, /* GPIO_AD_B1_01 PAD functional properties : */ + 0xD8B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Enabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 22K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ +#endif +} +#endif /* BSP_USING_I2C */ + +#ifdef BSP_USING_LCD +static void imxrt_lcd_pins_init(void) +{ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_02_GPIO1_IO02, /* GPIO_AD_B0_02 is configured as GPIO1_IO02 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_15_GPIO2_IO31, /* GPIO_B1_15 is configured as GPIO2_IO31 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_00_LCD_CLK, /* GPIO_B0_00 is configured as LCD_CLK */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_01_LCD_ENABLE, /* GPIO_B0_01 is configured as LCD_ENABLE */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_02_LCD_HSYNC, /* GPIO_B0_02 is configured as LCD_HSYNC */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_03_LCD_VSYNC, /* GPIO_B0_03 is configured as LCD_VSYNC */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_04_LCD_DATA00, /* GPIO_B0_04 is configured as LCD_DATA00 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_05_LCD_DATA01, /* GPIO_B0_05 is configured as LCD_DATA01 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_06_LCD_DATA02, /* GPIO_B0_06 is configured as LCD_DATA02 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_07_LCD_DATA03, /* GPIO_B0_07 is configured as LCD_DATA03 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_08_LCD_DATA04, /* GPIO_B0_08 is configured as LCD_DATA04 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_09_LCD_DATA05, /* GPIO_B0_09 is configured as LCD_DATA05 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_10_LCD_DATA06, /* GPIO_B0_10 is configured as LCD_DATA06 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_11_LCD_DATA07, /* GPIO_B0_11 is configured as LCD_DATA07 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_12_LCD_DATA08, /* GPIO_B0_12 is configured as LCD_DATA08 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_13_LCD_DATA09, /* GPIO_B0_13 is configured as LCD_DATA09 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_14_LCD_DATA10, /* GPIO_B0_14 is configured as LCD_DATA10 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B0_15_LCD_DATA11, /* GPIO_B0_15 is configured as LCD_DATA11 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_00_LCD_DATA12, /* GPIO_B1_00 is configured as LCD_DATA12 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_01_LCD_DATA13, /* GPIO_B1_01 is configured as LCD_DATA13 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_02_LCD_DATA14, /* GPIO_B1_02 is configured as LCD_DATA14 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_03_LCD_DATA15, /* GPIO_B1_03 is configured as LCD_DATA15 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */x + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_02_GPIO1_IO02, /* GPIO_AD_B0_02 PAD functional properties : */ + 0x10B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_15_GPIO2_IO31, /* GPIO_B1_15 PAD functional properties : */ + 0x10B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 PAD functional properties : */ + 0x10B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 PAD functional properties : */ + 0x10B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_00_LCD_CLK, /* GPIO_B0_00 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_01_LCD_ENABLE, /* GPIO_B0_01 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_02_LCD_HSYNC, /* GPIO_B0_02 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_03_LCD_VSYNC, /* GPIO_B0_03 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_04_LCD_DATA00, /* GPIO_B0_04 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_05_LCD_DATA01, /* GPIO_B0_05 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_06_LCD_DATA02, /* GPIO_B0_06 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_07_LCD_DATA03, /* GPIO_B0_07 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_08_LCD_DATA04, /* GPIO_B0_08 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_09_LCD_DATA05, /* GPIO_B0_09 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_10_LCD_DATA06, /* GPIO_B0_10 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_11_LCD_DATA07, /* GPIO_B0_11 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_12_LCD_DATA08, /* GPIO_B0_12 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_13_LCD_DATA09, /* GPIO_B0_13 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_14_LCD_DATA10, /* GPIO_B0_14 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B0_15_LCD_DATA11, /* GPIO_B0_15 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_00_LCD_DATA12, /* GPIO_B1_00 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_01_LCD_DATA13, /* GPIO_B1_01 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_02_LCD_DATA14, /* GPIO_B1_02 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_03_LCD_DATA15, /* GPIO_B1_03 PAD functional properties : */ + 0x01B0B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Enabled */ +} + +#endif + #ifdef BSP_USING_ETH void imxrt_enet_pins_init(void) { @@ -468,6 +873,10 @@ void rt_hw_board_init() imxrt_uart_pins_init(); #endif +#ifdef BSP_USING_I2C + imxrt_i2c_pins_init(); +#endif + #ifdef BSP_USING_ETH imxrt_enet_pins_init(); #endif @@ -476,6 +885,10 @@ void rt_hw_board_init() imxrt_phy_pins_init(); #endif +#ifdef BSP_USING_LCD + imxrt_lcd_pins_init(); +#endif + #ifdef BSP_USING_DMA imxrt_dma_init(); #endif diff --git a/bsp/imxrt/libraries/drivers/drv_i2c.c b/bsp/imxrt/libraries/drivers/drv_i2c.c index 117b29f3d3..1920c0d502 100644 --- a/bsp/imxrt/libraries/drivers/drv_i2c.c +++ b/bsp/imxrt/libraries/drivers/drv_i2c.c @@ -221,7 +221,7 @@ static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, { if (imxrt_i2c->msg[i].flags & RT_I2C_RD) { - if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Write) != kStatus_Success) + if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) { i = 0; break; @@ -231,12 +231,6 @@ static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, { } - if (LPI2C_MasterRepeatedStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) - { - i = 0; - break; - } - if (LPI2C_MasterReceive(imxrt_i2c->I2C, imxrt_i2c->msg[i].buf, imxrt_i2c->msg[i].len) != kStatus_Success) { i = 0; From 37960723b8fe6c91d14c7c4c1c30a97d17e0033b Mon Sep 17 00:00:00 2001 From: geniusgogo Date: Fri, 28 May 2021 09:43:06 +0800 Subject: [PATCH 123/255] fix rt_tick_increase critical code protection --- src/clock.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/clock.c b/src/clock.c index 0880d8d241..8746d463c1 100644 --- a/src/clock.c +++ b/src/clock.c @@ -76,10 +76,14 @@ void rt_tick_increase(void) -- thread->remaining_tick; if (thread->remaining_tick == 0) { + rt_base_t level; + /* change to initialized tick */ thread->remaining_tick = thread->init_tick; + level = rt_hw_interrupt_disable(); thread->stat |= RT_THREAD_STAT_YIELD; + rt_hw_interrupt_enable(level); rt_schedule(); } From 039d7979d83666e96d7f6efb84255de0047e3e67 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 29 May 2021 17:30:18 +0800 Subject: [PATCH 124/255] =?UTF-8?q?[kernel][thread.c]=20=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E5=86=85=E9=83=A8=E5=87=BD=E6=95=B0=E5=91=BD=E5=90=8D=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/thread.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/thread.c b/src/thread.c index e03c027eff..6304a4ebe6 100644 --- a/src/thread.c +++ b/src/thread.c @@ -79,7 +79,7 @@ void rt_thread_inited_sethook(void (*hook)(rt_thread_t thread)) #endif /* must be invoke witch rt_hw_interrupt_disable */ -static void _thread_cleanup_execute(rt_thread_t thread) +static void _rt_thread_cleanup_execute(rt_thread_t thread) { register rt_base_t level; #ifdef RT_USING_MODULE @@ -103,7 +103,7 @@ static void _thread_cleanup_execute(rt_thread_t thread) rt_hw_interrupt_enable(level); } -void rt_thread_exit(void) +static void _rt_thread_exit(void) { struct rt_thread *thread; register rt_base_t level; @@ -114,7 +114,7 @@ void rt_thread_exit(void) /* disable interrupt */ level = rt_hw_interrupt_disable(); - _thread_cleanup_execute(thread); + _rt_thread_cleanup_execute(thread); /* remove from schedule */ rt_schedule_remove_thread(thread); @@ -165,11 +165,11 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, #ifdef ARCH_CPU_STACK_GROWS_UPWARD thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter, (void *)((char *)thread->stack_addr), - (void *)rt_thread_exit); + (void *)_rt_thread_exit); #else thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter, (rt_uint8_t *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)), - (void *)rt_thread_exit); + (void *)_rt_thread_exit); #endif /* priority init */ @@ -374,7 +374,7 @@ rt_err_t rt_thread_detach(rt_thread_t thread) rt_schedule_remove_thread(thread); } - _thread_cleanup_execute(thread); + _rt_thread_cleanup_execute(thread); /* release thread timer */ rt_timer_detach(&(thread->thread_timer)); @@ -472,7 +472,7 @@ rt_err_t rt_thread_delete(rt_thread_t thread) rt_schedule_remove_thread(thread); } - _thread_cleanup_execute(thread); + _rt_thread_cleanup_execute(thread); /* release thread timer */ rt_timer_detach(&(thread->thread_timer)); From 2e11562772938ec253bb60123283d476da0bdd2e Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 29 May 2021 19:10:48 +0800 Subject: [PATCH 125/255] =?UTF-8?q?[kernel][=E6=B3=A8=E9=87=8A]=20?= =?UTF-8?q?=E6=98=8E=E7=A1=AErt=5Fschedule=E7=9A=84=E8=B0=83=E5=BA=A6?= =?UTF-8?q?=E6=97=B6=E5=88=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/scheduler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scheduler.c b/src/scheduler.c index c03c20d030..ed0f30fc81 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -404,7 +404,7 @@ __exit: #else /** * This function will perform one schedule. It will select one thread - * with the highest priority level, then switch to it. + * with the highest priority level, and switch to it immediately. */ void rt_schedule(void) { From 8b82b834826249dff299353da44188429d18dde2 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 30 May 2021 11:43:44 +0800 Subject: [PATCH 126/255] =?UTF-8?q?[kernel]=20=E5=A2=9E=E5=8A=A0rt=5Fmutex?= =?UTF-8?q?=5Ftrytake?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/rtthread.h | 1 + src/ipc.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/rtthread.h b/include/rtthread.h index 784b208a76..ccd2d147a8 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -322,6 +322,7 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag); rt_err_t rt_mutex_delete(rt_mutex_t mutex); rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time); +rt_err_t rt_mutex_trytake(rt_mutex_t mutex); rt_err_t rt_mutex_release(rt_mutex_t mutex); rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg); #endif diff --git a/src/ipc.c b/src/ipc.c index 22e0f06bc6..6cd38b74ab 100755 --- a/src/ipc.c +++ b/src/ipc.c @@ -37,7 +37,8 @@ * 2020-07-29 Meco Man fix thread->event_set/event_info when received an * event without pending * 2020-10-11 Meco Man add value overflow-check code - * 2021-01-03 Meco Man add rt_mb_urgent() + * 2021-01-03 Meco Man implement rt_mb_urgent() + * 2021-05-30 Meco Man implement rt_mutex_trytake() * 2021-01-20 hupu fix priority inversion bug of mutex */ @@ -452,7 +453,7 @@ RTM_EXPORT(rt_sem_take); */ rt_err_t rt_sem_trytake(rt_sem_t sem) { - return rt_sem_take(sem, 0); + return rt_sem_take(sem, RT_WAITING_NO); } RTM_EXPORT(rt_sem_trytake); @@ -843,6 +844,19 @@ __again: } RTM_EXPORT(rt_mutex_take); +/** + * This function will try to take a mutex and immediately return + * + * @param mutex the mutex object + * + * @return the error code + */ +rt_err_t rt_mutex_trytake(rt_mutex_t mutex) +{ + return rt_mutex_take(mutex, RT_WAITING_NO); +} +RTM_EXPORT(rt_mutex_trytake); + /** * This function will release a mutex, if there are threads suspended on mutex, * it will be waked up. From f34e9323b430813a6dbb62a609cfb3980aa645b0 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Tue, 1 Jun 2021 11:42:47 +0800 Subject: [PATCH 127/255] =?UTF-8?q?=E5=AF=B9rt=5Ftick=5Fincrease=E4=B8=B4?= =?UTF-8?q?=E7=95=8C=E5=8C=BA=E8=BF=9B=E8=A1=8C=E4=BF=9D=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/clock.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/clock.c b/src/clock.c index 8746d463c1..045555933d 100644 --- a/src/clock.c +++ b/src/clock.c @@ -62,6 +62,9 @@ void rt_tick_set(rt_tick_t tick) void rt_tick_increase(void) { struct rt_thread *thread; + rt_base_t level; + + level = rt_hw_interrupt_disable(); /* increase the global tick */ #ifdef RT_USING_SMP @@ -76,17 +79,17 @@ void rt_tick_increase(void) -- thread->remaining_tick; if (thread->remaining_tick == 0) { - rt_base_t level; - /* change to initialized tick */ thread->remaining_tick = thread->init_tick; - - level = rt_hw_interrupt_disable(); thread->stat |= RT_THREAD_STAT_YIELD; - rt_hw_interrupt_enable(level); + rt_hw_interrupt_enable(level); rt_schedule(); } + else + { + rt_hw_interrupt_enable(level); + } /* check timer */ rt_timer_check(); From 9d5ae107ee089abb728372266dc876f250fb483b Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Wed, 2 Jun 2021 09:14:59 +0800 Subject: [PATCH 128/255] [ci] update Arm ToolChains to 10-2020-q4. --- .github/workflows/action.yml | 8 ++++---- .github/workflows/action_utest.yml | 8 ++++---- bsp/gd32303e-eval/cconfig.h | 18 ------------------ 3 files changed, 8 insertions(+), 26 deletions(-) delete mode 100644 bsp/gd32303e-eval/cconfig.h diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index ecbc19cca9..bc9e7fe2a4 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -149,10 +149,10 @@ jobs: if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'sourcery-arm' && success() }} shell: bash run: | - wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/arm-2017q2-v6/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 - sudo tar xjf gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 -C /opt - /opt/gcc-arm-none-eabi-6-2017-q2-update/bin/arm-none-eabi-gcc --version - echo "RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-6-2017-q2-update/bin" >> $GITHUB_ENV + wget -q https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 + sudo tar xjf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C /opt + /opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc --version + echo "RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin" >> $GITHUB_ENV - name: Install Mips ToolChains if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'sourcery-mips' && success() }} diff --git a/.github/workflows/action_utest.yml b/.github/workflows/action_utest.yml index b8fea056e1..9b5b14f984 100644 --- a/.github/workflows/action_utest.yml +++ b/.github/workflows/action_utest.yml @@ -23,12 +23,12 @@ jobs: run: | sudo apt-get update > /dev/null sudo apt-get -yqq install scons qemu-system-arm git - wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/arm-2017q2-v6/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 - sudo tar xjf gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 -C /opt + wget -q https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 + sudo tar xjf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C /opt - name: Build bsp run: | - export RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-6-2017-q2-update/bin - /opt/gcc-arm-none-eabi-6-2017-q2-update/bin/arm-none-eabi-gcc --version + export RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin + /opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc --version cp $TEST_CONFIG_FILE $TEST_BSP_ROOT/rtconfig.h scons -j$(nproc) -C $TEST_BSP_ROOT - name: Start test diff --git a/bsp/gd32303e-eval/cconfig.h b/bsp/gd32303e-eval/cconfig.h deleted file mode 100644 index fb19b36e8e..0000000000 --- a/bsp/gd32303e-eval/cconfig.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef CCONFIG_H__ -#define CCONFIG_H__ -/* Automatically generated file; DO NOT EDIT. */ -/* compiler configure file for RT-Thread in GCC*/ - -#define HAVE_NEWLIB_H 1 -#define LIBC_VERSION "newlib 2.4.0" - -#define HAVE_SYS_SIGNAL_H 1 -#define HAVE_SYS_SELECT_H 1 -#define HAVE_PTHREAD_H 1 - -#define HAVE_FDSET 1 -#define HAVE_SIGACTION 1 -#define GCC_VERSION "5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496]" -#define STDC "2011" - -#endif From 2c119a5c481d16c416358f62bd5fde8210a96c46 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 3 Jun 2021 14:57:26 +0800 Subject: [PATCH 129/255] add memheap testcase for ac6 Oz optimization. --- examples/utest/testcases/Kconfig | 1 + examples/utest/testcases/kernel/Kconfig | 8 ++ examples/utest/testcases/kernel/SConscript | 15 +++ examples/utest/testcases/kernel/memheap_tc.c | 100 +++++++++++++++++++ examples/utest/testcases/utest/pass_tc.c | 2 +- 5 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 examples/utest/testcases/kernel/Kconfig create mode 100644 examples/utest/testcases/kernel/SConscript create mode 100644 examples/utest/testcases/kernel/memheap_tc.c diff --git a/examples/utest/testcases/Kconfig b/examples/utest/testcases/Kconfig index da80eb30ae..a9b556f1e3 100644 --- a/examples/utest/testcases/Kconfig +++ b/examples/utest/testcases/Kconfig @@ -8,6 +8,7 @@ config RT_USING_UTESTCASES if RT_USING_UTESTCASES source "$RTT_DIR/examples/utest/testcases/utest/Kconfig" +source "$RTT_DIR/examples/utest/testcases/kernel/Kconfig" endif diff --git a/examples/utest/testcases/kernel/Kconfig b/examples/utest/testcases/kernel/Kconfig new file mode 100644 index 0000000000..14334af16f --- /dev/null +++ b/examples/utest/testcases/kernel/Kconfig @@ -0,0 +1,8 @@ +menu "Kernel Testcase" + +config UTEST_MEMHEAP_TC + bool "memheap stability test" + default y + depends on RT_USING_MEMHEAP + +endmenu diff --git a/examples/utest/testcases/kernel/SConscript b/examples/utest/testcases/kernel/SConscript new file mode 100644 index 0000000000..9411cdd9a0 --- /dev/null +++ b/examples/utest/testcases/kernel/SConscript @@ -0,0 +1,15 @@ +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +src = Split(''' +''') + +if GetDepend(['UTEST_MEMHEAP_TC']): + src += ['memheap_tc.c'] + +CPPPATH = [cwd] + +group = DefineGroup('utestcases', src, depend = [], CPPPATH = CPPPATH) + +Return('group') diff --git a/examples/utest/testcases/kernel/memheap_tc.c b/examples/utest/testcases/kernel/memheap_tc.c new file mode 100644 index 0000000000..ee52bdb185 --- /dev/null +++ b/examples/utest/testcases/kernel/memheap_tc.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-01-16 flybreak the first version + */ + +#include +#include +#include "utest.h" + +#define HEAP_SIZE (64 * 1024) +#define HEAP_ALIGN (4) +#define SLICE_NUM (40) +#define TEST_TIMES (100000) +#define HEAP_NAME "heap1" +#define SLICE_SIZE_MAX (HEAP_SIZE/SLICE_NUM) + +static void memheap_test(void) +{ + struct rt_memheap heap1; + rt_uint32_t ptr_start; + void *ptr[SLICE_NUM]; + int i, cnt = 0; + + /* init heap */ + ptr_start = (rt_uint32_t)rt_malloc_align(HEAP_SIZE, HEAP_ALIGN); + if (ptr_start == RT_NULL) + { + rt_kprintf("totle size too big,can not malloc memory!"); + return; + } + + rt_memheap_init(&heap1, HEAP_NAME, (void *)ptr_start, HEAP_SIZE); + + /* test start */ + for (i = 0; i < SLICE_NUM; i++) + { + ptr[i] = 0; + } + /* test alloc */ + for (i = 0; i < SLICE_NUM; i++) + { + rt_uint32_t slice_size = rand() % SLICE_SIZE_MAX; + ptr[i] = rt_memheap_alloc(&heap1, slice_size); + } + /* test realloc */ + while (cnt < TEST_TIMES) + { + rt_uint32_t slice_size = rand() % SLICE_SIZE_MAX; + rt_uint32_t ptr_index = rand() % SLICE_NUM; + rt_uint32_t operation = rand() % 2; + + if (ptr[ptr_index]) + { + if (operation == 0) /* free and malloc */ + { + if (ptr[ptr_index]) + { + rt_memheap_free(ptr[ptr_index]); + } + ptr[ptr_index] = rt_memheap_alloc(&heap1, slice_size); + } + else /* realloc */ + { + ptr[ptr_index] = rt_memheap_realloc(&heap1, ptr[ptr_index], slice_size); + } + } + cnt ++; + if (cnt % (TEST_TIMES / 10) == 0) + { + rt_kprintf(">"); + } + } + + rt_kprintf("test OK!\n"); + + /* test end */ + rt_memheap_detach(&heap1); + rt_free_align((void *)ptr_start); +} + +static rt_err_t utest_tc_init(void) +{ + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(memheap_test); +} +UTEST_TC_EXPORT(testcase, "testcases.kernel.memheap_tc", utest_tc_init, utest_tc_cleanup, 10); diff --git a/examples/utest/testcases/utest/pass_tc.c b/examples/utest/testcases/utest/pass_tc.c index 8e93e35b9b..c9ee912fbf 100644 --- a/examples/utest/testcases/utest/pass_tc.c +++ b/examples/utest/testcases/utest/pass_tc.c @@ -43,4 +43,4 @@ static void testcase(void) { UTEST_UNIT_RUN(test_assert_pass); } -UTEST_TC_EXPORT(testcase, "testcases.utest.pass_tc", utest_tc_init, utest_tc_cleanup, 10); \ No newline at end of file +UTEST_TC_EXPORT(testcase, "testcases.utest.pass_tc", utest_tc_init, utest_tc_cleanup, 10); From 8e8ae9c95183c4b0c7bf02b9f79a0b0c151cd7c8 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 3 Jun 2021 15:02:00 +0800 Subject: [PATCH 130/255] [src][memheap] Fix the crash problem after opening Oz optimization on ac6. --- src/memheap.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/memheap.c b/src/memheap.c index 63327575cc..2cfdd73ad4 100644 --- a/src/memheap.c +++ b/src/memheap.c @@ -17,6 +17,7 @@ * 2013-05-24 Bernard fix the rt_memheap_realloc issue. * 2013-07-11 Grissiom fix the memory block splitting issue. * 2013-07-15 Grissiom optimize rt_memheap_realloc + * 2021-06-03 Flybreak Fix the crash problem after opening Oz optimization on ac6. */ #include @@ -369,7 +370,8 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize) if (newsize > oldsize) { void *new_ptr; - struct rt_memheap_item *next_ptr; + /* Fix the crash problem after opening Oz optimization on ac6 */ + volatile struct rt_memheap_item *next_ptr; /* lock memheap */ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER); @@ -441,14 +443,14 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize) next_ptr->prev = header_ptr; next_ptr->next = header_ptr->next; - header_ptr->next->prev = next_ptr; - header_ptr->next = next_ptr; + header_ptr->next->prev = (struct rt_memheap_item *)next_ptr; + header_ptr->next = (struct rt_memheap_item *)next_ptr; /* insert next_ptr to free list */ next_ptr->next_free = heap->free_list->next_free; next_ptr->prev_free = heap->free_list; - heap->free_list->next_free->prev_free = next_ptr; - heap->free_list->next_free = next_ptr; + heap->free_list->next_free->prev_free = (struct rt_memheap_item *)next_ptr; + heap->free_list->next_free = (struct rt_memheap_item *)next_ptr; RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x", next_ptr->next_free, next_ptr->prev_free)); From 4d213254c334e8c54f1b45edab47b77d22ca28b8 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 3 Jun 2021 15:06:33 +0800 Subject: [PATCH 131/255] [ci] add kernel/mem testcase. --- .github/workflows/action_utest.yml | 2 +- examples/utest/configs/kernel/config.h | 304 +++++++++++++++++++++++++ 2 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 examples/utest/configs/kernel/config.h diff --git a/.github/workflows/action_utest.yml b/.github/workflows/action_utest.yml index b8fea056e1..bfa9778554 100644 --- a/.github/workflows/action_utest.yml +++ b/.github/workflows/action_utest.yml @@ -11,7 +11,7 @@ jobs: fail-fast: false matrix: legs: - - {UTEST: "kernel/ipc", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"} + - {UTEST: "kernel/mem", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/kernel/config.h"} - {UTEST: "components/utest", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"} env: diff --git a/examples/utest/configs/kernel/config.h b/examples/utest/configs/kernel/config.h new file mode 100644 index 0000000000..c7fcb763fb --- /dev/null +++ b/examples/utest/configs/kernel/config.h @@ -0,0 +1,304 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Project Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_USING_SMP +#define RT_CPUS_NR 2 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 1024 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 1024 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE +#define RT_USING_SIGNALS + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_MEMHEAP +#define RT_USING_SMALL_MEM +#define RT_USING_MEMTRACE +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_DEVICE_OPS +#define RT_USING_INTERRUPT_INFO +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 256 +#define RT_CONSOLE_DEVICE_NAME "uart0" +#define RT_VER_NUM 0x40004 +#define ARCH_ARM +#define RT_USING_CPU_FFS +#define ARCH_ARM_CORTEX_A +#define RT_USING_GIC_V2 +#define ARCH_ARM_CORTEX_A9 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + +#define RT_USING_CPLUSPLUS + +/* Command shell */ + +#define RT_USING_FINSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_CMD_SIZE 80 +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + +#define RT_USING_DFS +#define DFS_USING_WORKDIR +#define DFS_FILESYSTEMS_MAX 4 +#define DFS_FILESYSTEM_TYPES_MAX 8 +#define DFS_FD_MAX 32 +#define RT_USING_DFS_ELMFAT + +/* elm-chan's FatFs, Generic FAT Filesystem Module */ + +#define RT_DFS_ELM_CODE_PAGE 437 +#define RT_DFS_ELM_WORD_ACCESS +#define RT_DFS_ELM_USE_LFN_3 +#define RT_DFS_ELM_USE_LFN 3 +#define RT_DFS_ELM_LFN_UNICODE_0 +#define RT_DFS_ELM_LFN_UNICODE 0 +#define RT_DFS_ELM_MAX_LFN 255 +#define RT_DFS_ELM_DRIVES 2 +#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 +#define RT_DFS_ELM_REENTRANT +#define RT_USING_DFS_DEVFS +#define RT_USING_DFS_ROMFS +#define RT_USING_DFS_RAMFS + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_I2C +#define RT_USING_I2C_BITOPS +#define RT_USING_PIN +#define RT_USING_MTD_NOR +#define RT_USING_MTD_NAND +#define RT_MTD_NAND_DEBUG +#define RT_USING_RTC +#define RT_USING_SOFT_RTC +#define RT_USING_SDIO +#define RT_SDIO_STACK_SIZE 512 +#define RT_SDIO_THREAD_PRIORITY 15 +#define RT_MMCSD_STACK_SIZE 1024 +#define RT_MMCSD_THREAD_PREORITY 22 +#define RT_MMCSD_MAX_PARTITION 16 +#define RT_USING_SPI +#define RT_USING_SPI_MSD +#define RT_USING_SFUD +#define RT_SFUD_USING_SFDP +#define RT_SFUD_USING_FLASH_INFO_TABLE +#define RT_SFUD_SPI_MAX_HZ 50000000 +#define RT_USING_WDT + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_USING_LIBC +#define RT_USING_PTHREADS +#define PTHREAD_NUM_MAX 8 +#define RT_USING_POSIX +#define RT_USING_POSIX_MMAP +#define RT_USING_POSIX_TERMIOS +#define RT_USING_POSIX_GETLINE +#define RT_USING_POSIX_AIO +#define RT_LIBC_FIXED_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + +#define RT_USING_SAL +#define SAL_INTERNET_CHECK + +/* protocol stack implement */ + +#define SAL_USING_LWIP +#define SAL_USING_POSIX + +/* Network interface device */ + +#define RT_USING_NETDEV +#define NETDEV_USING_IFCONFIG +#define NETDEV_USING_PING +#define NETDEV_USING_NETSTAT +#define NETDEV_USING_AUTO_DEFAULT +#define NETDEV_IPV4 1 +#define NETDEV_IPV6 0 + +/* light weight TCP/IP stack */ + +#define RT_USING_LWIP +#define RT_USING_LWIP202 +#define RT_LWIP_MEM_ALIGNMENT 4 +#define RT_LWIP_ICMP +#define RT_LWIP_DNS +#define RT_LWIP_DHCP +#define IP_SOF_BROADCAST 1 +#define IP_SOF_BROADCAST_RECV 1 + +/* Static IPv4 Address */ + +#define RT_LWIP_IPADDR "192.168.1.30" +#define RT_LWIP_GWADDR "192.168.1.1" +#define RT_LWIP_MSKADDR "255.255.255.0" +#define RT_LWIP_UDP +#define RT_LWIP_TCP +#define RT_LWIP_RAW +#define RT_MEMP_NUM_NETCONN 8 +#define RT_LWIP_PBUF_NUM 16 +#define RT_LWIP_RAW_PCB_NUM 4 +#define RT_LWIP_UDP_PCB_NUM 4 +#define RT_LWIP_TCP_PCB_NUM 4 +#define RT_LWIP_TCP_SEG_NUM 40 +#define RT_LWIP_TCP_SND_BUF 8196 +#define RT_LWIP_TCP_WND 8196 +#define RT_LWIP_TCPTHREAD_PRIORITY 10 +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 +#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_PRIORITY 12 +#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 +#define RT_LWIP_REASSEMBLY_FRAG +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define SO_REUSE 1 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_RCVBUF 1 +#define LWIP_SO_LINGER 0 +#define LWIP_NETIF_LOOPBACK 0 +#define RT_LWIP_USING_PING + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + +#define RT_USING_UTEST +#define UTEST_THR_STACK_SIZE 4096 +#define UTEST_THR_PRIORITY 20 +#define RT_USING_LWP + +/* RT-Thread Utestcases */ + +#define RT_USING_UTESTCASES + +/* Utest Self Testcase */ + +#define UTEST_SELF_PASS_TC + +/* Kernel memheap stability Testcase */ + +#define UTEST_MEMHEAP_TC + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + + +/* tools packages */ + + +/* system packages */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + +#define SOC_VEXPRESS_A9 +#define RT_USING_UART0 +#define RT_USING_UART1 +#define BSP_DRV_EMAC + +#endif From 51ec75f71d7a0a74bba0fe979cba79c9732ccad1 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 3 Jun 2021 15:13:47 +0800 Subject: [PATCH 132/255] [update]format memheap.c --- src/memheap.c | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/memheap.c b/src/memheap.c index 2cfdd73ad4..35a04c14b1 100644 --- a/src/memheap.c +++ b/src/memheap.c @@ -42,31 +42,31 @@ rt_inline void rt_memheap_setname(struct rt_memheap_item *item, const char *name) { int index; - rt_uint8_t* ptr; + rt_uint8_t *ptr; - ptr = (rt_uint8_t*)&(item->next_free); - for (index = 0; index < sizeof(void*); index ++) + ptr = (rt_uint8_t *) & (item->next_free); + for (index = 0; index < sizeof(void *); index ++) { if (name[index] == '\0') break; ptr[index] = name[index]; } if (name[index] == '\0') ptr[index] = '\0'; - else + else { - ptr = (rt_uint8_t*)&(item->prev_free); - for (index = 0; index < sizeof(void*) && (index + sizeof(void*))< RT_NAME_MAX; index ++) + ptr = (rt_uint8_t *) & (item->prev_free); + for (index = 0; index < sizeof(void *) && (index + sizeof(void *)) < RT_NAME_MAX; index ++) { - if (name[sizeof(void*) + index] == '\0') break; - ptr[index] = name[sizeof(void*) + index]; + if (name[sizeof(void *) + index] == '\0') break; + ptr[index] = name[sizeof(void *) + index]; } - if (name[sizeof(void*) + index] == '\0') ptr[index] = '\0'; + if (name[sizeof(void *) + index] == '\0') ptr[index] = '\0'; } } -void rt_mem_set_tag(void* ptr, const char* name) +void rt_mem_set_tag(void *ptr, const char *name) { - struct rt_memheap_item* item; + struct rt_memheap_item *item; if (ptr && name) { @@ -668,17 +668,17 @@ void rt_memheap_free(void *ptr) RTM_EXPORT(rt_memheap_free); #ifdef RT_USING_FINSH -static void _memheap_dump_tag(struct rt_memheap_item* item) +static void _memheap_dump_tag(struct rt_memheap_item *item) { - rt_uint8_t name[2 * sizeof(void*)]; - rt_uint8_t* ptr; + rt_uint8_t name[2 * sizeof(void *)]; + rt_uint8_t *ptr; - ptr = (rt_uint8_t*)&(item->next_free); - rt_memcpy(name, ptr, sizeof(void*)); - ptr = (rt_uint8_t*)&(item->prev_free); - rt_memcpy(&name[sizeof(void*)], ptr, sizeof(void*)); + ptr = (rt_uint8_t *) & (item->next_free); + rt_memcpy(name, ptr, sizeof(void *)); + ptr = (rt_uint8_t *) & (item->prev_free); + rt_memcpy(&name[sizeof(void *)], ptr, sizeof(void *)); - rt_kprintf("%.*s", 2 * sizeof(void*), name); + rt_kprintf("%.*s", 2 * sizeof(void *), name); } int rt_memheap_dump(struct rt_memheap *heap) @@ -688,15 +688,15 @@ int rt_memheap_dump(struct rt_memheap *heap) if (heap == RT_NULL) return 0; RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap); - rt_kprintf("\n[%.*s] [0x%08x - 0x%08x]->\n", RT_NAME_MAX, heap->parent.name, - (rt_ubase_t)heap->start_addr, (rt_ubase_t)heap->start_addr + heap->pool_size); + rt_kprintf("\n[%.*s] [0x%08x - 0x%08x]->\n", RT_NAME_MAX, heap->parent.name, + (rt_ubase_t)heap->start_addr, (rt_ubase_t)heap->start_addr + heap->pool_size); rt_kprintf("------------------------------\n"); /* lock memheap */ rt_sem_take(&(heap->lock), RT_WAITING_FOREVER); item = heap->block_list; - end = (struct rt_memheap_item *) ((rt_uint8_t *)heap->start_addr + heap->pool_size - RT_MEMHEAP_SIZE); + end = (struct rt_memheap_item *)((rt_uint8_t *)heap->start_addr + heap->pool_size - RT_MEMHEAP_SIZE); /* for each memory block */ while ((rt_ubase_t)item < ((rt_ubase_t)end)) @@ -732,13 +732,13 @@ int memheaptrace(void) int index; extern int list_memheap(void); - heaps = (struct rt_memheap**)rt_malloc(sizeof(struct rt_memheap*) * count); + heaps = (struct rt_memheap **)rt_malloc(sizeof(struct rt_memheap *) * count); if (heaps == RT_NULL) return 0; list_memheap(); rt_kprintf("memheap header size: %d\n", RT_MEMHEAP_SIZE); - count = rt_object_get_pointers(RT_Object_Class_MemHeap, (rt_object_t*)heaps, count); + count = rt_object_get_pointers(RT_Object_Class_MemHeap, (rt_object_t *)heaps, count); for (index = 0; index < count; index++) { rt_memheap_dump(heaps[index]); @@ -968,15 +968,15 @@ void dump_used_memheap(struct rt_memheap *mh) { /* dump information */ rt_kprintf("[0x%08x - %d - %c%c%c%c] used\n", header_ptr, block_size, - header_ptr->owner_thread_name[0], header_ptr->owner_thread_name[1], - header_ptr->owner_thread_name[2], header_ptr->owner_thread_name[3]); + header_ptr->owner_thread_name[0], header_ptr->owner_thread_name[1], + header_ptr->owner_thread_name[2], header_ptr->owner_thread_name[3]); } else { /* dump information */ rt_kprintf("[0x%08x - %d - %c%c%c%c] free\n", header_ptr, block_size, - header_ptr->owner_thread_name[0], header_ptr->owner_thread_name[1], - header_ptr->owner_thread_name[2], header_ptr->owner_thread_name[3]); + header_ptr->owner_thread_name[0], header_ptr->owner_thread_name[1], + header_ptr->owner_thread_name[2], header_ptr->owner_thread_name[3]); } /* move to next used memory block */ From 5a6bc9900689ba2d21850cc520c3621c57037025 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 2 Jun 2021 15:30:32 +0800 Subject: [PATCH 133/255] =?UTF-8?q?[bug][kernel]=20=E4=BF=9D=E6=8C=81?= =?UTF-8?q?=E7=A9=BA=E9=97=B2=E4=BB=BB=E5=8A=A1=E9=92=A9=E5=AD=90=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E8=B0=83=E7=94=A8=E7=9A=84=E5=8E=9F=E5=AD=90=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/clock.c | 3 ++- src/idle.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/clock.c b/src/clock.c index 045555933d..191525411a 100644 --- a/src/clock.c +++ b/src/clock.c @@ -13,7 +13,8 @@ * 2010-07-13 Bernard fix rt_tick_from_millisecond issue found by kuronca * 2011-06-26 Bernard add rt_tick_set function. * 2018-11-22 Jesven add per cpu tick - * 2020-12-29 Meco Man add function rt_tick_get_millisecond() + * 2020-12-29 Meco Man implement rt_tick_get_millisecond() + * 2021-06-01 Meco Man add critical section projection for rt_tick_increase() */ #include diff --git a/src/idle.c b/src/idle.c index 59868352d8..e73a78be9c 100644 --- a/src/idle.c +++ b/src/idle.c @@ -202,12 +202,14 @@ static void rt_thread_idle_entry(void *parameter) { #ifdef RT_USING_IDLE_HOOK rt_size_t i; + void (*idle_hook)(void); for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++) { - if (idle_hook_list[i] != RT_NULL) + idle_hook = idle_hook_list[i]; + if (idle_hook != RT_NULL) { - idle_hook_list[i](); + idle_hook(); } } #endif From e0b66ccab87bd5142769e0f4fd3f2b5ac14796ba Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Thu, 3 Jun 2021 20:09:26 +0800 Subject: [PATCH 134/255] =?UTF-8?q?[kernel]=20=E5=AF=B9rt=5Ftick=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E5=A2=9E=E5=8A=A0volatile=E4=BF=AE=E9=A5=B0=EF=BC=8C?= =?UTF-8?q?=E9=98=B2=E6=AD=A2=E7=BC=96=E8=AF=91=E5=99=A8=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=97=B6=E5=87=BA=E7=8E=B0=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clock.c b/src/clock.c index 045555933d..f02c524380 100644 --- a/src/clock.c +++ b/src/clock.c @@ -22,7 +22,7 @@ #ifdef RT_USING_SMP #define rt_tick rt_cpu_index(0)->tick #else -static rt_tick_t rt_tick = 0; +static volatile rt_tick_t rt_tick = 0; #endif /** From 9776fa5021b56f8847127138a37c7b5824305ba0 Mon Sep 17 00:00:00 2001 From: iysheng Date: Fri, 4 Jun 2021 23:53:29 +0800 Subject: [PATCH 135/255] [tools] Optimization the EXTERN_LIB variable use --- tools/makefile.py | 8 ++++++++ tools/rtthread.mk | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/makefile.py b/tools/makefile.py index 655e294575..97001892c9 100644 --- a/tools/makefile.py +++ b/tools/makefile.py @@ -51,6 +51,14 @@ def TargetMakefile(env): if 'CXXFLAGS' in dir(rtconfig): make.write('CXXFLAGS :=%s' % (rtconfig.CXXFLAGS)) make.write('\n') + if env.has_key('LIBS'): + make.write('EXTERN_LIB := ') + for tlib in env['LIBS']: + make.write('-l%s ' % (tlib)) + if env.has_key('LIBPATH'): + for tlibpath in env['LIBPATH']: + make.write('-L%s ' % (tlibpath)) + make.write('\n') make.write('\n') diff --git a/tools/rtthread.mk b/tools/rtthread.mk index 7cf018cb52..4bb3e2754d 100644 --- a/tools/rtthread.mk +++ b/tools/rtthread.mk @@ -122,10 +122,10 @@ $(TARGET): $(OBJS) @echo ar $(TARGET) @$(CROSS_COMPILE)ar -rv $@ $(OBJS) else -$(TARGET): $(OBJS) $(EXTERN_LIB) +$(TARGET): $(OBJS) @echo ------------------------------------------------ @echo link $(TARGET) - @$(CROSS_COMPILE)g++ -o $@ $(LFLAGS) $(OBJS) $(EXTERN_LIB) -lc -lm + @$(CROSS_COMPILE)g++ -o $@ $(LFLAGS) $(OBJS) $(EXTERN_LIB) @echo ------------------------------------------------ @$(CROSS_COMPILE)objcopy -O binary $@ rtthread.bin @$(CROSS_COMPILE)size $@ From 2b6762e85955a10e0150a3f32b869104a106acbd Mon Sep 17 00:00:00 2001 From: Meco Jianting Man <920369182@qq.com> Date: Sat, 5 Jun 2021 13:05:11 +0800 Subject: [PATCH 136/255] remove fix priority inversion bug of mutex --- src/ipc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ipc.c b/src/ipc.c index 74b47df3b6..bda32dbf26 100755 --- a/src/ipc.c +++ b/src/ipc.c @@ -39,7 +39,6 @@ * 2020-10-11 Meco Man add value overflow-check code * 2021-01-03 Meco Man implement rt_mb_urgent() * 2021-05-30 Meco Man implement rt_mutex_trytake() - * 2021-01-20 hupu fix priority inversion bug of mutex */ #include From 1e82e40c82925059e1cb0115bc28224bee038dda Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 7 Jun 2021 11:37:12 +0800 Subject: [PATCH 137/255] fixed bug of lcd_draw_line function when y1 == y2. need to consider user case when x1 >= x2 --- .../board/ports/drv_lcd.c | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/bsp/stm32/stm32l475-atk-pandora/board/ports/drv_lcd.c b/bsp/stm32/stm32l475-atk-pandora/board/ports/drv_lcd.c index f80ca3a4b2..6ec90f880c 100644 --- a/bsp/stm32/stm32l475-atk-pandora/board/ports/drv_lcd.c +++ b/bsp/stm32/stm32l475-atk-pandora/board/ports/drv_lcd.c @@ -446,18 +446,33 @@ void lcd_draw_line(rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y if (y1 == y2) { /* fast draw transverse line */ - lcd_address_set(x1, y1, x2, y2); + rt_uint32_t x_offset = 0; + if (x1 < x2) + { + x_offset = x2 - x1; + lcd_address_set(x1, y1, x2, y2); + } + else if (x1 > x2) + { + x_offset = x1 - x2; + lcd_address_set(x2, y2, x1, y1); + } + else + { + lcd_draw_point(x1, y1); + return; + } rt_uint8_t line_buf[480] = {0}; - for (i = 0; i < x2 - x1; i++) + for (i = 0; i < x_offset; i++) { line_buf[2 * i] = FORE_COLOR >> 8; line_buf[2 * i + 1] = FORE_COLOR; } rt_pin_write(LCD_DC_PIN, PIN_HIGH); - rt_spi_send(spi_dev_lcd, line_buf, (x2 - x1) * 2); + rt_spi_send(spi_dev_lcd, line_buf, x_offset * 2); return ; } From 115ec7cf49650e3206510b63e2a527d0ddc626ea Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 7 Jun 2021 12:58:17 +0800 Subject: [PATCH 138/255] [tools] remove formatting --- tools/formatting.py | 135 -------------------------------------------- 1 file changed, 135 deletions(-) delete mode 100644 tools/formatting.py diff --git a/tools/formatting.py b/tools/formatting.py deleted file mode 100644 index 0b63e031fa..0000000000 --- a/tools/formatting.py +++ /dev/null @@ -1,135 +0,0 @@ -# -# File : formatting.py -# This file is part of RT-Thread RTOS -# COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Change Logs: -# Date Author Notes -# 2021-03-02 Meco Man The first version -# 2021-03-04 Meco Man 增加统一转换成UTF-8编码格式功能 - - -#本文件会自动对指定路径下的所有文件包括子文件夹的文件(仅针对.c.h)进行扫描 -# 1)将源文件编码统一为UTF-8; -# 2)将TAB键替换为空格; -# 3)将每行末尾多余的空格删除,并统一换行符为'\n'; -#使用时只需要双击本文件,输入要扫描的文件夹路径即可 -#不能保证100%全部成功转换为UTF-8,有一些编码特殊或识别不准确会在终端打印信息,需人工转换 - -#欢迎对本文件的功能继续做出补充,欢迎提交PR - -import os -import chardet - -#用空格代替TAB键 -#这里并不是简单的将TAB替换成4个空格 -#空格个数到底是多少需要计算,因为TAB制表本身有自动对齐的功能 -def tab2spaces(line): - list_str = list(line) #字符串打散成列表,放边操作 - i = list_str.count('\t') - - while i > 0: - ptr = list_str.index('\t') - del list_str[ptr] - space_need_to_insert = 4 - (ptr%4) - j = 0 - while j < space_need_to_insert: - list_str.insert(ptr,' ') - j = j+1 - - i = i-1 - - line = ''.join(list_str) #列表恢复成字符串 - return line - -#删除每行末尾多余的空格 统一使用\n作为结尾 -def formattail(line): - line = line.rstrip() - line = line + '\n' - return line - -#对单个文件进行格式整理 -def format_codes(filename): - try: - file=open(filename,'r',encoding = 'utf-8') - file_temp=open('temp','w',encoding = 'utf-8') - for line in file: - line = tab2spaces(line) - line = formattail(line) - file_temp.write(line) - file_temp.close() - file.close() - os.remove(filename) - os.rename('temp',filename) - -def get_encode_info(file): - with open(file, 'rb') as f: - code = chardet.detect(f.read())['encoding'] - #charde库有一定几率对当前文件的编码识别不准确 - if code == 'EUC-JP': #容易将含着少量中文的英文字符文档识别为日语编码格式 - code = 'GB2312' - elif code == 'ISO-8859-1': #部分文件GB2312码会被识别成ISO-8859-1 - code = 'GB2312' - - if not (code == 'ascii' or code == 'utf-8' or code == 'GB2312' #编码识别正确 - or code == 'Windows-1252'): # Windows-1252 是由于意法半导体是法国企业's的'是法语的'导致的 - if code != None: - print('未处理,需人工确认:'+code+':'+file) #需要人工确认 - code = None - - return code - -#将单个文件转为UTF-8编码 -def conver_to_utf_8 (path): - try: - info = get_encode_info(path) - if info == None: - return 0 #0 失败 - - file=open(path,'rb+') - data = file.read() - string = data.decode(info) - utf = string.encode('utf-8') - file.seek(0) - file.write(utf) - file.close() - return 1 #1成功 - except UnicodeDecodeError: - print("UnicodeDecodeError未处理,需人工确认"+path) - return 0 - except UnicodeEncodeError: - print("UnicodeEncodeError未处理,需人工确认"+path) - return 0 - -# 递归扫描目录下的所有文件 -def traversalallfile(path): - filelist=os.listdir(path) - for file in filelist: - filepath=os.path.join(path,file) - if os.path.isdir(filepath): - traversalallfile(filepath) - elif os.path.isfile(filepath): - if filepath.endswith(".c") == True or filepath.endswith(".h") == True: #只处理.c和.h文件 - if conver_to_utf_8(filepath) == 1: #先把这个文件转为UTF-8编码,1成功 - format_codes(filepath) #再对这个文件进行格式整理 - -def formatfiles(): - workpath = input('enter work path: ') - traversalallfile(workpath) - -if __name__ == '__main__': - formatfiles() From b2dd3f00f0617abd5757ca75a5579d493dc8bd85 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 7 Jun 2021 16:45:39 +0800 Subject: [PATCH 139/255] =?UTF-8?q?[bug][kernel][heap]=20=E5=B0=86?= =?UTF-8?q?=E5=86=85=E5=AD=98=E5=A0=86=E4=BF=9D=E6=8A=A4=E6=9C=BA=E5=88=B6?= =?UTF-8?q?=E7=94=B1FIFO=E6=94=B9=E4=B8=BAPRIO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mem.c | 2 +- src/memheap.c | 2 +- src/slab.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mem.c b/src/mem.c index ac0d27f2c3..2b4d3a03be 100644 --- a/src/mem.c +++ b/src/mem.c @@ -250,7 +250,7 @@ void rt_system_heap_init(void *begin_addr, void *end_addr) rt_mem_setname(heap_end, "INIT"); #endif - rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_FIFO); + rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_PRIO); /* initialize the lowest-free pointer to the start of the heap */ lfree = (struct heap_mem *)heap_ptr; diff --git a/src/memheap.c b/src/memheap.c index 35a04c14b1..d3ad6d2c36 100644 --- a/src/memheap.c +++ b/src/memheap.c @@ -155,7 +155,7 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap, item->next_free = item->prev_free = RT_NULL; /* initialize semaphore lock */ - rt_sem_init(&(memheap->lock), name, 1, RT_IPC_FLAG_FIFO); + rt_sem_init(&(memheap->lock), name, 1, RT_IPC_FLAG_PRIO); RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("memory heap: start addr 0x%08x, size %d, free list header 0x%08x\n", diff --git a/src/slab.c b/src/slab.c index 114259002f..2769892b68 100644 --- a/src/slab.c +++ b/src/slab.c @@ -363,7 +363,7 @@ void rt_system_heap_init(void *begin_addr, void *end_addr) npages = limsize / RT_MM_PAGE_SIZE; /* initialize heap semaphore */ - rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_FIFO); + rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_PRIO); RT_DEBUG_LOG(RT_DEBUG_SLAB, ("heap[0x%x - 0x%x], size 0x%x, 0x%x pages\n", heap_start, heap_end, limsize, npages)); From d94be14df5cede07a99d6aeebcd4f8446ae80d7e Mon Sep 17 00:00:00 2001 From: chenjh Date: Sat, 5 Jun 2021 17:21:27 +0800 Subject: [PATCH 140/255] =?UTF-8?q?[serial]=20=E5=A2=9E=E5=8A=A0serial=5Fv?= =?UTF-8?q?2=E7=89=88=E6=9C=AC=E7=9A=84=E6=A1=86=E6=9E=B6=E5=92=8C?= =?UTF-8?q?=E5=9F=BA=E4=BA=8Estm32=E7=9A=84=E4=B8=B2=E5=8F=A3=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/libraries/HAL_Drivers/SConscript | 5 +- .../HAL_Drivers/config/l4/dma_config.h | 11 + bsp/stm32/libraries/HAL_Drivers/drv_common.c | 4 + .../libraries/HAL_Drivers/drv_usart_v2.c | 1137 ++++++++++++++++ .../libraries/HAL_Drivers/drv_usart_v2.h | 83 ++ bsp/stm32/stm32l475-atk-pandora/.config | 263 +++- bsp/stm32/stm32l475-atk-pandora/board/Kconfig | 58 +- bsp/stm32/stm32l475-atk-pandora/rtconfig.h | 43 +- components/drivers/Kconfig | 30 +- .../drivers/include/drivers/serial_v2.h | 193 +++ components/drivers/include/rtdevice.h | 4 + components/drivers/serial/SConscript | 11 +- components/drivers/serial/serial_v2.c | 1171 +++++++++++++++++ 13 files changed, 2971 insertions(+), 42 deletions(-) create mode 100644 bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c create mode 100644 bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h create mode 100644 components/drivers/include/drivers/serial_v2.h create mode 100644 components/drivers/serial/serial_v2.c diff --git a/bsp/stm32/libraries/HAL_Drivers/SConscript b/bsp/stm32/libraries/HAL_Drivers/SConscript index e41a1f0141..dabcc7002c 100644 --- a/bsp/stm32/libraries/HAL_Drivers/SConscript +++ b/bsp/stm32/libraries/HAL_Drivers/SConscript @@ -12,7 +12,10 @@ if GetDepend(['RT_USING_PIN']): src += ['drv_gpio.c'] if GetDepend(['RT_USING_SERIAL']): - src += ['drv_usart.c'] + if GetDepend(['RT_USING_SERIAL_V2']): + src += ['drv_usart_v2.c'] + else: + src += ['drv_usart.c'] if GetDepend(['RT_USING_HWTIMER']): src += ['drv_hwtimer.c'] diff --git a/bsp/stm32/libraries/HAL_Drivers/config/l4/dma_config.h b/bsp/stm32/libraries/HAL_Drivers/config/l4/dma_config.h index 0762f9048d..0064309f2e 100644 --- a/bsp/stm32/libraries/HAL_Drivers/config/l4/dma_config.h +++ b/bsp/stm32/libraries/HAL_Drivers/config/l4/dma_config.h @@ -127,6 +127,17 @@ extern "C" { #endif /* DMA1 channel7 */ +#if defined(BSP_UART2_TX_USING_DMA) && !defined(UART2_TX_DMA_INSTANCE) +#define UART2_DMA_TX_IRQHandler DMA1_Channel7_IRQHandler +#define UART2_TX_DMA_RCC RCC_AHB1ENR_DMA1EN +#define UART2_TX_DMA_INSTANCE DMA1_Channel7 +#if defined(DMAMUX1) /* for L4+ */ +#define UART2_TX_DMA_REQUEST DMA_REQUEST_USART2_TX +#else /* for L4 */ +#define UART2_TX_DMA_REQUEST DMA_REQUEST_2 +#endif /* DMAMUX1 */ +#define UART2_TX_DMA_IRQ DMA1_Channel7_IRQn +#endif /* DMA2 channel1 */ #if defined(BSP_UART5_TX_USING_DMA) && !defined(UART5_TX_DMA_INSTANCE) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_common.c b/bsp/stm32/libraries/HAL_Drivers/drv_common.c index 74007b6e88..134eb7b3df 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_common.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_common.c @@ -12,8 +12,12 @@ #include "board.h" #ifdef RT_USING_SERIAL +#ifdef RT_USING_SERIAL_V2 +#include "drv_usart_v2.h" +#else #include "drv_usart.h" #endif +#endif #ifdef RT_USING_FINSH #include diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c new file mode 100644 index 0000000000..51dfc425c4 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c @@ -0,0 +1,1137 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-01 KyleChan first version + */ + +#include "board.h" +#include "drv_usart_v2.h" + +#ifdef RT_USING_SERIAL_V2 + +//#define DRV_DEBUG +#define DBG_TAG "drv.usart" +#ifdef DRV_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif /* DRV_DEBUG */ +#include + +#if !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3) && \ + !defined(BSP_USING_UART4) && !defined(BSP_USING_UART5) && !defined(BSP_USING_UART6) && \ + !defined(BSP_USING_UART7) && !defined(BSP_USING_UART8) && !defined(BSP_USING_LPUART1) + #error "Please define at least one BSP_USING_UARTx" + /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ +#endif + +#ifdef RT_SERIAL_USING_DMA + static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag); +#endif + +enum +{ +#ifdef BSP_USING_UART1 + UART1_INDEX, +#endif + +#ifdef BSP_USING_UART2 + UART2_INDEX, +#endif + +#ifdef BSP_USING_UART3 + UART3_INDEX, +#endif + +#ifdef BSP_USING_UART4 + UART4_INDEX, +#endif + +#ifdef BSP_USING_UART5 + UART5_INDEX, +#endif + +#ifdef BSP_USING_UART6 + UART6_INDEX, +#endif + +#ifdef BSP_USING_UART7 + UART7_INDEX, +#endif + +#ifdef BSP_USING_UART8 + UART8_INDEX, +#endif + +#ifdef BSP_USING_LPUART1 + LPUART1_INDEX, +#endif +}; + +static struct stm32_uart_config uart_config[] = +{ +#ifdef BSP_USING_UART1 + UART1_CONFIG, +#endif + +#ifdef BSP_USING_UART2 + UART2_CONFIG, +#endif + +#ifdef BSP_USING_UART3 + UART3_CONFIG, +#endif + +#ifdef BSP_USING_UART4 + UART4_CONFIG, +#endif +#ifdef BSP_USING_UART5 + UART5_CONFIG, +#endif +#ifdef BSP_USING_UART6 + UART6_CONFIG, +#endif +#ifdef BSP_USING_UART7 + UART7_CONFIG, +#endif +#ifdef BSP_USING_UART8 + UART8_CONFIG, +#endif +#ifdef BSP_USING_LPUART1 + LPUART1_CONFIG, +#endif +}; + + +static struct stm32_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0}; + +static rt_err_t stm32_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct stm32_uart *uart; + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + uart = rt_container_of(serial, struct stm32_uart, serial); + + uart->handle.Instance = uart->config->Instance; + uart->handle.Init.BaudRate = cfg->baud_rate; + uart->handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + uart->handle.Init.Mode = UART_MODE_TX_RX; + uart->handle.Init.OverSampling = UART_OVERSAMPLING_16; + + if(uart->handle.Instance == USART3) + { + uart->handle.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS; + } + + switch (cfg->data_bits) + { + case DATA_BITS_8: + if (cfg->parity == PARITY_ODD || cfg->parity == PARITY_EVEN) + uart->handle.Init.WordLength = UART_WORDLENGTH_9B; + else + uart->handle.Init.WordLength = UART_WORDLENGTH_8B; + break; + case DATA_BITS_9: + uart->handle.Init.WordLength = UART_WORDLENGTH_9B; + break; + default: + uart->handle.Init.WordLength = UART_WORDLENGTH_8B; + break; + } + + switch (cfg->stop_bits) + { + case STOP_BITS_1: + uart->handle.Init.StopBits = UART_STOPBITS_1; + break; + case STOP_BITS_2: + uart->handle.Init.StopBits = UART_STOPBITS_2; + break; + default: + uart->handle.Init.StopBits = UART_STOPBITS_1; + break; + } + + switch (cfg->parity) + { + case PARITY_NONE: + uart->handle.Init.Parity = UART_PARITY_NONE; + break; + case PARITY_ODD: + uart->handle.Init.Parity = UART_PARITY_ODD; + break; + case PARITY_EVEN: + uart->handle.Init.Parity = UART_PARITY_EVEN; + break; + default: + uart->handle.Init.Parity = UART_PARITY_NONE; + break; + } + +#ifdef RT_SERIAL_USING_DMA + uart->dma_rx.remaining_cnt = serial->config.rx_bufsz; +#endif + + if (HAL_UART_Init(&uart->handle) != HAL_OK) + { + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t stm32_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct stm32_uart *uart; + + rt_ubase_t ctrl_arg = (rt_ubase_t)arg; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + + if(ctrl_arg & (RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_RX_NON_BLOCKING)) + { + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_RX) + ctrl_arg = RT_DEVICE_FLAG_DMA_RX; + else + ctrl_arg = RT_DEVICE_FLAG_INT_RX; + } + else if(ctrl_arg & (RT_DEVICE_FLAG_TX_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING)) + { + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_TX) + ctrl_arg = RT_DEVICE_FLAG_DMA_TX; + else + ctrl_arg = RT_DEVICE_FLAG_INT_TX; + } + + switch (cmd) + { + /* disable interrupt */ + case RT_DEVICE_CTRL_CLR_INT: + + NVIC_DisableIRQ(uart->config->irq_type); + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_RXNE); + else if (ctrl_arg == RT_DEVICE_FLAG_INT_TX) + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_TXE); +#ifdef RT_SERIAL_USING_DMA + else if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) + { + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_RXNE); + + HAL_NVIC_DisableIRQ(uart->config->dma_rx->dma_irq); + if (HAL_DMA_Abort(&(uart->dma_rx.handle)) != HAL_OK) + { + RT_ASSERT(0); + } + + if (HAL_DMA_DeInit(&(uart->dma_rx.handle)) != HAL_OK) + { + RT_ASSERT(0); + } + } + else if(ctrl_arg == RT_DEVICE_FLAG_DMA_TX) + { + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_TC); + + HAL_NVIC_DisableIRQ(uart->config->dma_tx->dma_irq); + if (HAL_DMA_DeInit(&(uart->dma_tx.handle)) != HAL_OK) + { + RT_ASSERT(0); + } + } +#endif + break; + + case RT_DEVICE_CTRL_SET_INT: + + HAL_NVIC_SetPriority(uart->config->irq_type, 1, 0); + HAL_NVIC_EnableIRQ(uart->config->irq_type); + + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) + __HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_RXNE); + else if (ctrl_arg == RT_DEVICE_FLAG_INT_TX) + __HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_TXE); + break; + + case RT_DEVICE_CTRL_CONFIG: + if (ctrl_arg & (RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX)) + { + +#ifdef RT_SERIAL_USING_DMA + stm32_dma_config(serial, ctrl_arg); +#endif + } + else + stm32_control(serial, RT_DEVICE_CTRL_SET_INT, (void *)ctrl_arg); + break; + + case RT_DEVICE_CHECK_OPTMODE: + { + if (ctrl_arg & RT_DEVICE_FLAG_DMA_TX) + return RT_SERIAL_TX_BLOCKING_NO_BUFFER; + else + return RT_SERIAL_TX_BLOCKING_BUFFER; + } + case RT_DEVICE_CTRL_CLOSE: + if (HAL_UART_DeInit(&(uart->handle)) != HAL_OK ) + { + RT_ASSERT(0) + } + break; + + } + return RT_EOK; +} + +static int stm32_putc(struct rt_serial_device *serial, char c) +{ + struct stm32_uart *uart; + RT_ASSERT(serial != RT_NULL); + + uart = rt_container_of(serial, struct stm32_uart, serial); + while (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) == RESET); + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TC); + UART_SET_TDR(&uart->handle, c); + + return 1; +} + +static int stm32_getc(struct rt_serial_device *serial) +{ + int ch; + struct stm32_uart *uart; + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + + ch = -1; + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_RXNE) != RESET) + ch = UART_GET_RDR(&uart->handle); + return ch; +} + +static rt_size_t stm32_transmit(struct rt_serial_device *serial, + rt_uint8_t *buf, + rt_size_t size, + rt_uint32_t tx_flag) +{ + struct stm32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(buf != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_TX) + { + HAL_UART_Transmit_DMA(&uart->handle, buf, size); + return size; + } + + stm32_control(serial, RT_DEVICE_CTRL_SET_INT, (void *)tx_flag); + + return size; +} + +#ifdef RT_SERIAL_USING_DMA +static void dma_recv_isr(struct rt_serial_device *serial, rt_uint8_t isr_flag) +{ + struct stm32_uart *uart; + rt_base_t level; + rt_uint16_t recv_len = 0; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + + struct rt_serial_rx_fifo *rx_fifo; + rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + + level = rt_hw_interrupt_disable(); + rt_uint16_t index = __HAL_DMA_GET_COUNTER(&(uart->dma_rx.handle)); + switch (isr_flag) + { + + case UART_RX_DMA_IT_TC_FLAG: + if(index >= uart->dma_rx.remaining_cnt) + recv_len = serial->config.rx_bufsz + uart->dma_rx.remaining_cnt - index; + break; + + case UART_RX_DMA_IT_HT_FLAG: + case UART_RX_DMA_IT_IDLE_FLAG: + if(index < uart->dma_rx.remaining_cnt) + recv_len = uart->dma_rx.remaining_cnt - index; + break; + + default: + break; + } + + uart->dma_rx.remaining_cnt = index; + rt_serial_update_write_index(&(rx_fifo->rb), recv_len); + rt_hw_interrupt_enable(level); + +} +#endif /* RT_SERIAL_USING_DMA */ + + +/** + * Uart common interrupt process. This need add to uart ISR. + * + * @param serial serial device + */ +static void uart_isr(struct rt_serial_device *serial) +{ + struct stm32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + /* If the Read data register is not empty and the RXNE interrupt is enabled (RDR) */ + if ((__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_RXNE) != RESET) && + (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_RXNE) != RESET)) + { + struct rt_serial_rx_fifo *rx_fifo; + rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + + rt_ringbuffer_putchar(&(rx_fifo->rb), UART_GET_RDR(&uart->handle)); + + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + } + /* If the Transmit data register is empty and the TXE interrupt enable is enabled (TDR)*/ + else if ((__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TXE) != RESET) && + (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_TXE)) != RESET) + { + struct rt_serial_tx_fifo *tx_fifo; + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + rt_uint8_t put_char = 0; + if (rt_ringbuffer_getchar(&(tx_fifo->rb), &put_char)) + { + UART_SET_TDR(&uart->handle, put_char); + } + else + { + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_TXE); + __HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_TC); + } + } + else if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) && + (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_TC) != RESET)) + { + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_TX) + { + /* The HAL_UART_TxCpltCallback will be triggered */ + HAL_UART_IRQHandler(&(uart->handle)); + } + else + { + /* Transmission complete interrupt disable ( CR1 Register) */ + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_TC); + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE); + } + /* Clear Transmission complete interrupt flag ( ISR Register ) */ + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TC); + } + +#ifdef RT_SERIAL_USING_DMA + else if ((uart->uart_dma_flag) && (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_IDLE) != RESET) + && (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_IDLE) != RESET)) + { + dma_recv_isr(serial, UART_RX_DMA_IT_IDLE_FLAG); + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + __HAL_UART_CLEAR_IDLEFLAG(&uart->handle); + } +#endif + else + { + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_ORE) != RESET) + { + __HAL_UART_CLEAR_OREFLAG(&uart->handle); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_NE) != RESET) + { + __HAL_UART_CLEAR_NEFLAG(&uart->handle); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_FE) != RESET) + { + __HAL_UART_CLEAR_FEFLAG(&uart->handle); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_PE) != RESET) + { + __HAL_UART_CLEAR_PEFLAG(&uart->handle); + } +#if !defined(SOC_SERIES_STM32L4) && !defined(SOC_SERIES_STM32WL) && !defined(SOC_SERIES_STM32F7) && !defined(SOC_SERIES_STM32F0) \ + && !defined(SOC_SERIES_STM32L0) && !defined(SOC_SERIES_STM32G0) && !defined(SOC_SERIES_STM32H7) \ + && !defined(SOC_SERIES_STM32G4) && !defined(SOC_SERIES_STM32MP1) && !defined(SOC_SERIES_STM32WB) + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_LBD) != RESET) + { + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_LBD); + } +#endif + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_CTS) != RESET) + { + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_CTS); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TXE) != RESET) + { + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TXE); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) != RESET) + { + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TC); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_RXNE) != RESET) + { + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_RXNE); + } + } +} + +#if defined(BSP_USING_UART1) +void USART1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART1_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_RX_USING_DMA) +void UART1_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART1_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_TX_USING_DMA) +void UART1_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART1_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_TX_USING_DMA) */ +#endif /* BSP_USING_UART1 */ + +#if defined(BSP_USING_UART2) +void USART2_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART2_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_RX_USING_DMA) +void UART2_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART2_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_TX_USING_DMA) +void UART2_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART2_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_TX_USING_DMA) */ +#endif /* BSP_USING_UART2 */ + +#if defined(BSP_USING_UART3) +void USART3_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART3_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART3_RX_USING_DMA) +void UART3_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART3_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_RX) && defined(BSP_UART3_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART3_TX_USING_DMA) +void UART3_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART3_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_TX) && defined(BSP_UART3_TX_USING_DMA) */ +#endif /* BSP_USING_UART3*/ + +#if defined(BSP_USING_UART4) +void UART4_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART4_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART4_RX_USING_DMA) +void UART4_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART4_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_RX) && defined(BSP_UART4_RX_USING_DMA) */ + +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART4_TX_USING_DMA) +void UART4_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART4_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_TX) && defined(BSP_UART4_TX_USING_DMA) */ +#endif /* BSP_USING_UART4*/ + +#if defined(BSP_USING_UART5) +void UART5_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART5_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_RX_USING_DMA) +void UART5_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART5_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_TX_USING_DMA) +void UART5_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART5_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_TX_USING_DMA) */ +#endif /* BSP_USING_UART5*/ + +#if defined(BSP_USING_UART6) +void USART6_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART6_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_RX_USING_DMA) +void UART6_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART6_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_TX_USING_DMA) +void UART6_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART6_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_TX_USING_DMA) */ +#endif /* BSP_USING_UART6*/ + +#if defined(BSP_USING_UART7) +void UART7_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART7_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_RX_USING_DMA) +void UART7_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART7_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_TX_USING_DMA) +void UART7_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART7_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_TX_USING_DMA) */ +#endif /* BSP_USING_UART7*/ + +#if defined(BSP_USING_UART8) +void UART8_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART8_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART8_RX_USING_DMA) +void UART8_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART8_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART8_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART8_TX_USING_DMA) +void UART8_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART8_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART8_TX_USING_DMA) */ +#endif /* BSP_USING_UART8*/ + +#if defined(BSP_USING_LPUART1) +void LPUART1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[LPUART1_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_LPUART1_RX_USING_DMA) +void LPUART1_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[LPUART1_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_LPUART1_RX_USING_DMA) */ +#endif /* BSP_USING_LPUART1*/ +static void stm32_uart_get_config(void) +{ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; +#ifdef BSP_USING_UART1 + uart_obj[UART1_INDEX].serial.config = config; + uart_obj[UART1_INDEX].uart_dma_flag = 0; + + uart_obj[UART1_INDEX].serial.config.rx_bufsz = BSP_UART1_RX_BUFSIZE; + uart_obj[UART1_INDEX].serial.config.tx_bufsz = BSP_UART1_TX_BUFSIZE; + +#ifdef BSP_UART1_RX_USING_DMA + uart_obj[UART1_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart1_dma_rx = UART1_DMA_RX_CONFIG; + uart_config[UART1_INDEX].dma_rx = &uart1_dma_rx; +#endif + +#ifdef BSP_UART1_TX_USING_DMA + uart_obj[UART1_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart1_dma_tx = UART1_DMA_TX_CONFIG; + uart_config[UART1_INDEX].dma_tx = &uart1_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART2 + uart_obj[UART2_INDEX].serial.config = config; + uart_obj[UART2_INDEX].uart_dma_flag = 0; + + uart_obj[UART2_INDEX].serial.config.rx_bufsz = BSP_UART2_RX_BUFSIZE; + uart_obj[UART2_INDEX].serial.config.tx_bufsz = BSP_UART2_TX_BUFSIZE; + +#ifdef BSP_UART2_RX_USING_DMA + uart_obj[UART2_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart2_dma_rx = UART2_DMA_RX_CONFIG; + uart_config[UART2_INDEX].dma_rx = &uart2_dma_rx; +#endif + +#ifdef BSP_UART2_TX_USING_DMA + uart_obj[UART2_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart2_dma_tx = UART2_DMA_TX_CONFIG; + uart_config[UART2_INDEX].dma_tx = &uart2_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART3 + uart_obj[UART3_INDEX].serial.config = config; + uart_obj[UART3_INDEX].uart_dma_flag = 0; + + uart_obj[UART3_INDEX].serial.config.rx_bufsz = BSP_UART3_RX_BUFSIZE; + uart_obj[UART3_INDEX].serial.config.tx_bufsz = BSP_UART3_TX_BUFSIZE; + +#ifdef BSP_UART3_RX_USING_DMA + uart_obj[UART3_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart3_dma_rx = UART3_DMA_RX_CONFIG; + uart_config[UART3_INDEX].dma_rx = &uart3_dma_rx; +#endif + +#ifdef BSP_UART3_TX_USING_DMA + uart_obj[UART3_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart3_dma_tx = UART3_DMA_TX_CONFIG; + uart_config[UART3_INDEX].dma_tx = &uart3_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART4 + uart_obj[UART4_INDEX].serial.config = config; + uart_obj[UART4_INDEX].uart_dma_flag = 0; + + uart_obj[UART4_INDEX].serial.config.rx_bufsz = BSP_UART4_RX_BUFSIZE; + uart_obj[UART4_INDEX].serial.config.tx_bufsz = BSP_UART4_TX_BUFSIZE; + +#ifdef BSP_UART4_RX_USING_DMA + uart_obj[UART4_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart4_dma_rx = UART4_DMA_RX_CONFIG; + uart_config[UART4_INDEX].dma_rx = &uart4_dma_rx; +#endif + +#ifdef BSP_UART4_TX_USING_DMA + uart_obj[UART4_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart4_dma_tx = UART4_DMA_TX_CONFIG; + uart_config[UART4_INDEX].dma_tx = &uart4_dma_tx; +#endif +#endif +} + +#ifdef RT_SERIAL_USING_DMA +static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag) +{ + struct rt_serial_rx_fifo *rx_fifo; + DMA_HandleTypeDef *DMA_Handle; + struct dma_config *dma_config; + struct stm32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + + if (RT_DEVICE_FLAG_DMA_RX == flag) + { + DMA_Handle = &uart->dma_rx.handle; + dma_config = uart->config->dma_rx; + } + else if (RT_DEVICE_FLAG_DMA_TX == flag) + { + DMA_Handle = &uart->dma_tx.handle; + dma_config = uart->config->dma_tx; + } + LOG_D("%s dma config start", uart->config->name); + + { + rt_uint32_t tmpreg = 0x00U; +#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0) \ + || defined(SOC_SERIES_STM32L0) + /* enable DMA clock && Delay after an RCC peripheral clock enabling*/ + SET_BIT(RCC->AHBENR, dma_config->dma_rcc); + tmpreg = READ_BIT(RCC->AHBENR, dma_config->dma_rcc); +#elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32WL) \ + || defined(SOC_SERIES_STM32G4)|| defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32WB) + /* enable DMA clock && Delay after an RCC peripheral clock enabling*/ + SET_BIT(RCC->AHB1ENR, dma_config->dma_rcc); + tmpreg = READ_BIT(RCC->AHB1ENR, dma_config->dma_rcc); +#elif defined(SOC_SERIES_STM32MP1) + /* enable DMA clock && Delay after an RCC peripheral clock enabling*/ + SET_BIT(RCC->MP_AHB2ENSETR, dma_config->dma_rcc); + tmpreg = READ_BIT(RCC->MP_AHB2ENSETR, dma_config->dma_rcc); +#endif + +#if defined(DMAMUX1) && (defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32WL) || defined(SOC_SERIES_STM32G4) || defined(SOC_SERIES_STM32WB)) + /* enable DMAMUX clock for L4+ and G4 */ + __HAL_RCC_DMAMUX1_CLK_ENABLE(); +#elif defined(SOC_SERIES_STM32MP1) + __HAL_RCC_DMAMUX_CLK_ENABLE(); +#endif + + UNUSED(tmpreg); /* To avoid compiler warnings */ + } + + if (RT_DEVICE_FLAG_DMA_RX == flag) + { + __HAL_LINKDMA(&(uart->handle), hdmarx, uart->dma_rx.handle); + } + else if (RT_DEVICE_FLAG_DMA_TX == flag) + { + __HAL_LINKDMA(&(uart->handle), hdmatx, uart->dma_tx.handle); + } + +#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32L0) + DMA_Handle->Instance = dma_config->Instance; +#elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) + DMA_Handle->Instance = dma_config->Instance; + DMA_Handle->Init.Channel = dma_config->channel; +#elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32WL) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32G4) || defined(SOC_SERIES_STM32WB)\ + || defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32MP1) + DMA_Handle->Instance = dma_config->Instance; + DMA_Handle->Init.Request = dma_config->request; +#endif + DMA_Handle->Init.PeriphInc = DMA_PINC_DISABLE; + DMA_Handle->Init.MemInc = DMA_MINC_ENABLE; + DMA_Handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + DMA_Handle->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + + if (RT_DEVICE_FLAG_DMA_RX == flag) + { + DMA_Handle->Init.Direction = DMA_PERIPH_TO_MEMORY; + DMA_Handle->Init.Mode = DMA_CIRCULAR; + } + else if (RT_DEVICE_FLAG_DMA_TX == flag) + { + DMA_Handle->Init.Direction = DMA_MEMORY_TO_PERIPH; + DMA_Handle->Init.Mode = DMA_NORMAL; + } + + DMA_Handle->Init.Priority = DMA_PRIORITY_MEDIUM; +#if defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32MP1) + DMA_Handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE; +#endif + if (HAL_DMA_DeInit(DMA_Handle) != HAL_OK) + { + RT_ASSERT(0); + } + + if (HAL_DMA_Init(DMA_Handle) != HAL_OK) + { + RT_ASSERT(0); + } + + /* enable interrupt */ + if (flag == RT_DEVICE_FLAG_DMA_RX) + { + rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + /* Start DMA transfer */ + if (HAL_UART_Receive_DMA(&(uart->handle), rx_fifo->buffer, serial->config.rx_bufsz) != HAL_OK) + { + /* Transfer error in reception process */ + RT_ASSERT(0); + } + CLEAR_BIT(uart->handle.Instance->CR3, USART_CR3_EIE); + __HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_IDLE); + } + + /* DMA irq should set in DMA TX mode, or HAL_UART_TxCpltCallback function will not be called */ + HAL_NVIC_SetPriority(dma_config->dma_irq, 0, 0); + HAL_NVIC_EnableIRQ(dma_config->dma_irq); + + HAL_NVIC_SetPriority(uart->config->irq_type, 1, 0); + HAL_NVIC_EnableIRQ(uart->config->irq_type); + + LOG_D("%s dma %s instance: %x", uart->config->name, flag == RT_DEVICE_FLAG_DMA_RX ? "RX" : "TX", DMA_Handle->Instance); + LOG_D("%s dma config done", uart->config->name); +} + +/** + * @brief UART error callbacks + * @param huart: UART handle + * @note This example shows a simple way to report transfer error, and you can + * add your own implementation. + * @retval None + */ +void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) +{ + RT_ASSERT(huart != NULL); + struct stm32_uart *uart = (struct stm32_uart *)huart; + LOG_D("%s: %s %d\n", __FUNCTION__, uart->config->name, huart->ErrorCode); + UNUSED(uart); +} + +/** + * @brief Rx Transfer completed callback + * @param huart: UART handle + * @note This example shows a simple way to report end of DMA Rx transfer, and + * you can add your own implementation. + * @retval None + */ +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) +{ + struct stm32_uart *uart; + RT_ASSERT(huart != NULL); + uart = (struct stm32_uart *)huart; + + dma_recv_isr(&uart->serial, UART_RX_DMA_IT_TC_FLAG); + rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_RX_DMADONE); +} + +/** + * @brief Rx Half transfer completed callback + * @param huart: UART handle + * @note This example shows a simple way to report end of DMA Rx Half transfer, + * and you can add your own implementation. + * @retval None + */ +void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) +{ + struct stm32_uart *uart; + RT_ASSERT(huart != NULL); + uart = (struct stm32_uart *)huart; + + dma_recv_isr(&uart->serial, UART_RX_DMA_IT_HT_FLAG); + rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_RX_DMADONE); +} + +/** + * @brief HAL_UART_TxCpltCallback + * @param huart: UART handle + * @note This callback can be called by two functions, first in UART_EndTransmit_IT when + * UART Tx complete and second in UART_DMATransmitCplt function in DMA Circular mode. + * @retval None + */ +void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) +{ + struct stm32_uart *uart; + struct rt_serial_device *serial; + rt_size_t trans_total_index; + rt_base_t level; + + RT_ASSERT(huart != NULL); + uart = (struct stm32_uart *)huart; + serial = &uart->serial; + RT_ASSERT(serial != RT_NULL); + + level = rt_hw_interrupt_disable(); + trans_total_index = __HAL_DMA_GET_COUNTER(&(uart->dma_tx.handle)); + rt_hw_interrupt_enable(level); + + if (trans_total_index) return; + + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DMADONE); + +} +#endif /* RT_SERIAL_USING_DMA */ + +static const struct rt_uart_ops stm32_uart_ops = +{ + .configure = stm32_configure, + .control = stm32_control, + .putc = stm32_putc, + .getc = stm32_getc, + .transmit = stm32_transmit +}; + +int rt_hw_usart_init(void) +{ + rt_err_t result = 0; + rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct stm32_uart); + + stm32_uart_get_config(); + for (int i = 0; i < obj_num; i++) + { + /* init UART object */ + uart_obj[i].config = &uart_config[i]; + uart_obj[i].serial.ops = &stm32_uart_ops; + /* register UART device */ + result = rt_hw_serial_register(&uart_obj[i].serial, + uart_obj[i].config->name, + RT_DEVICE_FLAG_RDWR, + NULL); + RT_ASSERT(result == RT_EOK); + } + + return result; +} + +#endif /* RT_USING_SERIAL_V2 */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h new file mode 100644 index 0000000000..3350b90864 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-01 KyleChan first version + */ + +#ifndef __DRV_USART_V2_H__ +#define __DRV_USART_V2_H__ + +#include +#include +#include +#include +#include +#include + +int rt_hw_usart_init(void); + +#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) \ + || defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32H7) \ + || defined(SOC_SERIES_STM32G4) +#define UART_SET_TDR(__HANDLE__, __DATA__) ((__HANDLE__)->Instance->TDR = (__DATA__)) +#define UART_GET_RDR(__HANDLE__) ((__HANDLE__)->Instance->RDR & 0xFF) + +#else +#define UART_SET_TDR(__HANDLE__, __DATA__) ((__HANDLE__)->Instance->DR = (__DATA__)) +#define UART_GET_RDR(__HANDLE__) (return (__HANDLE__)->Instance->DR & 0xFF)) +#endif + + +#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F2) \ + || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) \ + || defined(SOC_SERIES_STM32G4) || defined(SOC_SERIES_STM32WB) +#define UART_INSTANCE_CLEAR_FUNCTION __HAL_UART_CLEAR_FLAG +#elif defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32H7) \ + || defined(SOC_SERIES_STM32MP1) +#define UART_INSTANCE_CLEAR_FUNCTION __HAL_UART_CLEAR_IT +#endif + +#define UART_RX_DMA_IT_IDLE_FLAG 0x00 +#define UART_RX_DMA_IT_HT_FLAG 0x01 +#define UART_RX_DMA_IT_TC_FLAG 0x02 + + +/* stm32 config class */ +struct stm32_uart_config +{ + const char *name; + USART_TypeDef *Instance; + IRQn_Type irq_type; + +#ifdef RT_SERIAL_USING_DMA + struct dma_config *dma_rx; + struct dma_config *dma_tx; +#endif +}; + +/* stm32 uart dirver class */ +struct stm32_uart +{ + UART_HandleTypeDef handle; + struct stm32_uart_config *config; + +#ifdef RT_SERIAL_USING_DMA + struct + { + DMA_HandleTypeDef handle; + rt_size_t remaining_cnt; + } dma_rx; + struct + { + DMA_HandleTypeDef handle; + } dma_tx; +#endif + rt_uint16_t uart_dma_flag; + struct rt_serial_device serial; +}; + +#endif /* __DRV_USART_H__ */ diff --git a/bsp/stm32/stm32l475-atk-pandora/.config b/bsp/stm32/stm32l475-atk-pandora/.config index 18377e1e4e..365e154c17 100644 --- a/bsp/stm32/stm32l475-atk-pandora/.config +++ b/bsp/stm32/stm32l475-atk-pandora/.config @@ -21,6 +21,12 @@ CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 CONFIG_IDLE_THREAD_STACK_SIZE=256 # CONFIG_RT_USING_TIMER_SOFT is not set + +# +# 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 @@ -52,6 +58,7 @@ CONFIG_RT_USING_MEMPOOL=y # CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set CONFIG_RT_USING_HEAP=y @@ -64,7 +71,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" -CONFIG_RT_VER_NUM=0x40002 +CONFIG_RT_VER_NUM=0x40004 CONFIG_ARCH_ARM=y CONFIG_RT_USING_CPU_FFS=y CONFIG_ARCH_ARM_CORTEX_M=y @@ -115,14 +122,17 @@ 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_USING_SERIAL_V1 is not set +CONFIG_RT_USING_SERIAL_V2=y CONFIG_RT_SERIAL_USING_DMA=y -CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set # CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set # CONFIG_RT_USING_PWM is not set # CONFIG_RT_USING_MTD_NOR is not set # CONFIG_RT_USING_MTD_NAND is not set @@ -135,7 +145,7 @@ CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_SENSOR is not set # CONFIG_RT_USING_TOUCH is not set # CONFIG_RT_USING_HWCRYPTO is not set -# CONFIG_RT_USING_ENCODER 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 @@ -150,7 +160,7 @@ CONFIG_RT_USING_PIN=y # # CONFIG_RT_USING_LIBC is not set # CONFIG_RT_USING_PTHREADS is not set -CONFIG_RT_LIBC_USING_TIME=y +# CONFIG_RT_LIBC_USING_TIME is not set # # Network @@ -187,8 +197,28 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set +CONFIG_RT_USING_RT_LINK=y +CONFIG_RT_LINK_USING_SF_CRC=y +# CONFIG_RT_LINK_USING_HW_CRC is not set + +# +# rt-link hardware device configuration +# +CONFIG_RT_LINK_HW_DEVICE_NAME="uart2" +CONFIG_RT_LINK_USING_UART=y + +# +# rt link debug option +# +# CONFIG_USING_RT_LINK_DEBUG is not set +# CONFIG_USING_RT_LINK_HW_DEBUG is not set # CONFIG_RT_USING_LWP is not set +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + # # RT-Thread online packages # @@ -196,10 +226,15 @@ CONFIG_RT_LIBC_USING_TIME=y # # 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 @@ -226,6 +261,8 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 @@ -237,7 +274,10 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_GAGENT_CLOUD is not set # CONFIG_PKG_USING_ALI_IOTKIT is not set # CONFIG_PKG_USING_AZURE is not set -# CONFIG_PKG_USING_TENCENT_IOTHUB is not set +# CONFIG_PKG_USING_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 @@ -246,8 +286,23 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_LIBRWS is not set # CONFIG_PKG_USING_TCPSERVER is not set # CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# 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 # # security packages @@ -255,6 +310,8 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 @@ -270,6 +327,10 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set # CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set # # tools packages @@ -281,7 +342,31 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 # # system packages @@ -293,14 +378,43 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set # CONFIG_PKG_USING_CMSIS is not set # CONFIG_PKG_USING_DFS_YAFFS is not set # CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set # CONFIG_PKG_USING_THREAD_POOL is not set # CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_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_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# 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 +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set # # peripheral libraries and drivers @@ -308,6 +422,8 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 @@ -316,10 +432,16 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 @@ -327,7 +449,47 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_I2C_TOOLS is not set # CONFIG_PKG_USING_NRF24L01 is not set # CONFIG_PKG_USING_TOUCH_DRIVERS is not set -# CONFIG_PKG_USING_LCD_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# 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_RDA58XX 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 # # miscellaneous packages @@ -337,6 +499,7 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 @@ -345,6 +508,8 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 @@ -355,9 +520,69 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set # CONFIG_PKG_USING_VI is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_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 + +# +# games: games run on RT-Thread console +# +# 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_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 + +# +# Privated Packages of RealThread +# +# CONFIG_PKG_USING_CODEC is not set +# CONFIG_PKG_USING_PLAYER is not set +# CONFIG_PKG_USING_MPLAYER is not set +# CONFIG_PKG_USING_PERSIMMON_SRC is not set +# CONFIG_PKG_USING_JS_PERSIMMON is not set +# CONFIG_PKG_USING_JERRYSCRIPT_WIN32 is not set + +# +# Network Utilities +# +# CONFIG_PKG_USING_WICED is not set +# CONFIG_PKG_USING_CLOUDSDK is not set +# CONFIG_PKG_USING_POWER_MANAGER is not set +# CONFIG_PKG_USING_RT_OTA is not set +# CONFIG_PKG_USING_RTINSIGHT is not set +# CONFIG_PKG_USING_SMARTCONFIG is not set +# CONFIG_PKG_USING_RTX is not set +# CONFIG_RT_USING_TESTCASE is not set +# CONFIG_PKG_USING_NGHTTP2 is not set +# CONFIG_PKG_USING_AVS is not set +# CONFIG_PKG_USING_ALI_LINKKIT is not set +# CONFIG_PKG_USING_STS is not set +# CONFIG_PKG_USING_DLMS is not set +# CONFIG_PKG_USING_AUDIO_FRAMEWORK is not set +# CONFIG_PKG_USING_ZBAR is not set +# CONFIG_PKG_USING_MCF is not set +# CONFIG_PKG_USING_URPC is not set +# CONFIG_PKG_USING_DCM is not set +# CONFIG_PKG_USING_EMQ is not set +# CONFIG_PKG_USING_CFGM is not set +# CONFIG_PKG_USING_RT_CMSIS_DAP is not set +# CONFIG_PKG_USING_SMODULE is not set +# CONFIG_PKG_USING_SNFD is not set +# CONFIG_PKG_USING_UDBD is not set +# CONFIG_PKG_USING_BENCHMARK is not set +# CONFIG_PKG_USING_UBJSON is not set +# CONFIG_PKG_USING_DATATYPE is not set +# CONFIG_PKG_USING_FASTFS is not set +# CONFIG_PKG_USING_RIL is not set +# CONFIG_PKG_USING_WATCH_DCM_SVC is not set +# CONFIG_PKG_USING_GUI_TEST is not set +# CONFIG_PKG_USING_PMEM is not set CONFIG_SOC_FAMILY_STM32=y CONFIG_SOC_SERIES_STM32L4=y @@ -370,12 +595,15 @@ CONFIG_SOC_STM32L475VE=y # Onboard Peripheral Drivers # CONFIG_BSP_USING_STLINK_TO_USART=y +# CONFIG_BSP_USING_KEY is not set # CONFIG_BSP_USING_QSPI_FLASH is not set # CONFIG_BSP_USING_SPI_LCD is not set # CONFIG_BSP_USING_SDCARD is not set # CONFIG_BSP_USING_ICM20608 is not set # CONFIG_BSP_USING_AHT10 is not set # CONFIG_BSP_USING_AUDIO is not set +# CONFIG_BSP_USING_USB_AUDIO is not set +# CONFIG_BSP_USING_WIFI is not set # # On-chip Peripheral Drivers @@ -384,7 +612,14 @@ CONFIG_BSP_USING_GPIO=y CONFIG_BSP_USING_UART=y CONFIG_BSP_USING_UART1=y # CONFIG_BSP_UART1_RX_USING_DMA is not set -# CONFIG_BSP_USING_UART2 is not set +# CONFIG_BSP_UART1_TX_USING_DMA is not set +CONFIG_BSP_UART1_RX_BUFSIZE=256 +CONFIG_BSP_UART1_TX_BUFSIZE=0 +CONFIG_BSP_USING_UART2=y +CONFIG_BSP_UART2_RX_USING_DMA=y +CONFIG_BSP_UART2_TX_USING_DMA=y +CONFIG_BSP_UART2_RX_BUFSIZE=256 +CONFIG_BSP_UART2_TX_BUFSIZE=256 # CONFIG_BSP_USING_ON_CHIP_FLASH is not set # CONFIG_BSP_USING_SPI is not set # CONFIG_BSP_USING_QSPI is not set @@ -393,9 +628,11 @@ CONFIG_BSP_USING_UART1=y # CONFIG_BSP_USING_TIM is not set # CONFIG_BSP_USING_PWM is not set # CONFIG_BSP_USING_ADC is not set +# CONFIG_BSP_USING_DAC is not set # CONFIG_BSP_USING_ONCHIP_RTC is not set # CONFIG_BSP_USING_WDT is not set -# CONFIG_BSP_USING_USBD_FS is not set +# CONFIG_BSP_USING_USBD is not set +# CONFIG_BSP_USING_STM32_SDIO is not set # CONFIG_BSP_USING_CRC is not set # CONFIG_BSP_USING_RNG is not set # CONFIG_BSP_USING_UDID is not set diff --git a/bsp/stm32/stm32l475-atk-pandora/board/Kconfig b/bsp/stm32/stm32l475-atk-pandora/board/Kconfig index bc71249fa0..e8a0713647 100644 --- a/bsp/stm32/stm32l475-atk-pandora/board/Kconfig +++ b/bsp/stm32/stm32l475-atk-pandora/board/Kconfig @@ -152,23 +152,59 @@ menu "On-chip Peripheral Drivers" default y select RT_USING_SERIAL if BSP_USING_UART - config BSP_USING_UART1 - bool "Enable UART1" + menuconfig BSP_USING_UART1 + bool "Enable UART1 (Debugger)" default y + if BSP_USING_UART1 + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n - config BSP_UART1_RX_USING_DMA - bool "Enable UART1 RX DMA" - depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA - default n + config BSP_UART1_TX_USING_DMA + bool "Enable UART1 TX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n - config BSP_USING_UART2 + config BSP_UART1_RX_BUFSIZE + int "Set UART1 RX buffer size" + range 64 65535 + depends on RT_USING_SERIAL_V2 + default 256 + + config BSP_UART1_TX_BUFSIZE + int "Set UART1 TX buffer size" + range 0 65535 + depends on RT_USING_SERIAL_V2 + default 0 + endif + + menuconfig BSP_USING_UART2 bool "Enable UART2" default n + if BSP_USING_UART2 + config BSP_UART2_RX_USING_DMA + bool "Enable UART2 RX DMA" + depends on BSP_USING_UART2 && RT_SERIAL_USING_DMA + default n - config BSP_UART2_RX_USING_DMA - bool "Enable UART2 RX DMA" - depends on BSP_USING_UART2 && RT_SERIAL_USING_DMA - default n + config BSP_UART2_TX_USING_DMA + bool "Enable UART2 TX DMA" + depends on BSP_USING_UART2 && RT_SERIAL_USING_DMA + default n + + config BSP_UART2_RX_BUFSIZE + int "Set UART2 RX buffer size" + range 64 65535 + depends on RT_USING_SERIAL_V2 + default 256 + + config BSP_UART2_TX_BUFSIZE + int "Set UART2 TX buffer size" + range 0 65535 + depends on RT_USING_SERIAL_V2 + default 256 + endif endif config BSP_USING_ON_CHIP_FLASH diff --git a/bsp/stm32/stm32l475-atk-pandora/rtconfig.h b/bsp/stm32/stm32l475-atk-pandora/rtconfig.h index e18e51ae82..178f69b3ec 100644 --- a/bsp/stm32/stm32l475-atk-pandora/rtconfig.h +++ b/bsp/stm32/stm32l475-atk-pandora/rtconfig.h @@ -16,6 +16,9 @@ #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 #define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + #define RT_DEBUG #define RT_DEBUG_COLOR @@ -39,7 +42,7 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 256 #define RT_CONSOLE_DEVICE_NAME "uart1" -#define RT_VER_NUM 0x40002 +#define RT_VER_NUM 0x40004 #define ARCH_ARM #define RT_USING_CPU_FFS #define ARCH_ARM_CORTEX_M @@ -79,8 +82,8 @@ #define RT_USING_DEVICE_IPC #define RT_PIPE_BUFSZ 512 #define RT_USING_SERIAL +#define RT_USING_SERIAL_V2 #define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 64 #define RT_USING_PIN /* Using USB */ @@ -88,7 +91,6 @@ /* POSIX layer and C standard library */ -#define RT_LIBC_USING_TIME /* Network */ @@ -109,6 +111,19 @@ /* Utilities */ +#define RT_USING_RT_LINK +#define RT_LINK_USING_SF_CRC + +/* rt-link hardware device configuration */ + +#define RT_LINK_HW_DEVICE_NAME "uart2" +#define RT_LINK_USING_UART + +/* rt link debug option */ + + +/* RT-Thread Utestcases */ + /* RT-Thread online packages */ @@ -141,14 +156,29 @@ /* system packages */ +/* Micrium: Micrium software products porting for RT-Thread */ + + /* peripheral libraries and drivers */ +/* AI packages */ + + /* miscellaneous packages */ /* samples: kernel and components samples */ + +/* games: games run on RT-Thread console */ + + +/* Privated Packages of RealThread */ + + +/* Network Utilities */ + #define SOC_FAMILY_STM32 #define SOC_SERIES_STM32L4 @@ -165,6 +195,13 @@ #define BSP_USING_GPIO #define BSP_USING_UART #define BSP_USING_UART1 +#define BSP_UART1_RX_BUFSIZE 256 +#define BSP_UART1_TX_BUFSIZE 0 +#define BSP_USING_UART2 +#define BSP_UART2_RX_USING_DMA +#define BSP_UART2_TX_USING_DMA +#define BSP_UART2_RX_BUFSIZE 256 +#define BSP_UART2_TX_BUFSIZE 256 /* Board extended module Drivers */ diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index c7fec6cba9..d3fd14b52d 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -24,22 +24,30 @@ if RT_USING_DEVICE_IPC endif endif -config RT_USING_SERIAL - bool "Using serial device drivers" +menuconfig RT_USING_SERIAL + bool "USING Serial device drivers" select RT_USING_DEVICE_IPC select RT_USING_DEVICE default y -if RT_USING_SERIAL - config RT_SERIAL_USING_DMA - bool "Enable serial DMA mode" - default y + if RT_USING_SERIAL + choice + prompt "Choice Serial version" + default RT_USING_SERIAL_V1 + config RT_USING_SERIAL_V1 + bool "RT_USING_SERIAL_V1" + config RT_USING_SERIAL_V2 + bool "RT_USING_SERIAL_V2" + endchoice + config RT_SERIAL_USING_DMA + bool "Enable serial DMA mode" + default y - config RT_SERIAL_RB_BUFSZ - int "Set RX buffer size" - default 64 - -endif + config RT_SERIAL_RB_BUFSZ + int "Set RX buffer size" + depends on !RT_USING_SERIAL_V2 + default 64 + endif config RT_USING_CAN bool "Using CAN device drivers" diff --git a/components/drivers/include/drivers/serial_v2.h b/components/drivers/include/drivers/serial_v2.h new file mode 100644 index 0000000000..18187bc0f5 --- /dev/null +++ b/components/drivers/include/drivers/serial_v2.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-01 KyleChan first version + */ + +#ifndef __SERIAL_V2_H__ +#define __SERIAL_V2_H__ + +#include + +#define BAUD_RATE_2400 2400 +#define BAUD_RATE_4800 4800 +#define BAUD_RATE_9600 9600 +#define BAUD_RATE_19200 19200 +#define BAUD_RATE_38400 38400 +#define BAUD_RATE_57600 57600 +#define BAUD_RATE_115200 115200 +#define BAUD_RATE_230400 230400 +#define BAUD_RATE_460800 460800 +#define BAUD_RATE_921600 921600 +#define BAUD_RATE_2000000 2000000 +#define BAUD_RATE_3000000 3000000 + +#define DATA_BITS_5 5 +#define DATA_BITS_6 6 +#define DATA_BITS_7 7 +#define DATA_BITS_8 8 +#define DATA_BITS_9 9 + +#define STOP_BITS_1 0 +#define STOP_BITS_2 1 +#define STOP_BITS_3 2 +#define STOP_BITS_4 3 + +#ifdef _WIN32 +#include +#else +#define PARITY_NONE 0 +#define PARITY_ODD 1 +#define PARITY_EVEN 2 +#endif + +#define BIT_ORDER_LSB 0 +#define BIT_ORDER_MSB 1 + +#define NRZ_NORMAL 0 /* Non Return to Zero : normal mode */ +#define NRZ_INVERTED 1 /* Non Return to Zero : inverted mode */ + +#define RT_DEVICE_FLAG_RX_BLOCKING 0x1000 +#define RT_DEVICE_FLAG_RX_NON_BLOCKING 0x2000 + +#define RT_DEVICE_FLAG_TX_BLOCKING 0x4000 +#define RT_DEVICE_FLAG_TX_NON_BLOCKING 0x8000 + +#define RT_SERIAL_RX_BLOCKING RT_DEVICE_FLAG_RX_BLOCKING +#define RT_SERIAL_RX_NON_BLOCKING RT_DEVICE_FLAG_RX_NON_BLOCKING +#define RT_SERIAL_TX_BLOCKING RT_DEVICE_FLAG_TX_BLOCKING +#define RT_SERIAL_TX_NON_BLOCKING RT_DEVICE_FLAG_TX_NON_BLOCKING + +#define RT_DEVICE_CHECK_OPTMODE 0x20 + +#define RT_SERIAL_EVENT_RX_IND 0x01 /* Rx indication */ +#define RT_SERIAL_EVENT_TX_DONE 0x02 /* Tx complete */ +#define RT_SERIAL_EVENT_RX_DMADONE 0x03 /* Rx DMA transfer done */ +#define RT_SERIAL_EVENT_TX_DMADONE 0x04 /* Tx DMA transfer done */ +#define RT_SERIAL_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */ + +#define RT_SERIAL_ERR_OVERRUN 0x01 +#define RT_SERIAL_ERR_FRAMING 0x02 +#define RT_SERIAL_ERR_PARITY 0x03 + +#define RT_SERIAL_TX_DATAQUEUE_SIZE 2048 +#define RT_SERIAL_TX_DATAQUEUE_LWM 30 + +#define RT_SERIAL_RX_MINBUFSZ 64 +#define RT_SERIAL_TX_MINBUFSZ 64 + +#define RT_SERIAL_TX_BLOCKING_BUFFER 1 +#define RT_SERIAL_TX_BLOCKING_NO_BUFFER 0 + +/* Default config for serial_configure structure */ +#define RT_SERIAL_CONFIG_DEFAULT \ +{ \ + BAUD_RATE_115200, /* 115200 bits/s */ \ + DATA_BITS_8, /* 8 databits */ \ + STOP_BITS_1, /* 1 stopbit */ \ + PARITY_NONE, /* No parity */ \ + BIT_ORDER_LSB, /* LSB first sent */ \ + NRZ_NORMAL, /* Normal mode */ \ + RT_SERIAL_RX_MINBUFSZ, /* rxBuf size */ \ + RT_SERIAL_TX_MINBUFSZ, /* txBuf size */ \ + 0 \ +} + +struct serial_configure +{ + rt_uint32_t baud_rate; + + rt_uint32_t data_bits :4; + rt_uint32_t stop_bits :2; + rt_uint32_t parity :2; + rt_uint32_t bit_order :1; + rt_uint32_t invert :1; + rt_uint32_t rx_bufsz :16; + rt_uint32_t tx_bufsz :16; + rt_uint32_t reserved :6; +}; + +/* + * Serial FIFO mode + */ +struct rt_serial_rx_fifo +{ + struct rt_ringbuffer rb; + + rt_uint16_t rx_index; + + struct rt_completion rx_cpt; + + rt_uint16_t rx_cpt_index; + + /* software fifo */ + rt_uint8_t buffer[]; +}; + +struct rt_serial_tx_fifo +{ + struct rt_ringbuffer rb; + + rt_size_t put_size; + + rt_bool_t activated; + + struct rt_completion tx_cpt; + + /* software fifo */ + rt_uint8_t buffer[]; +}; + +struct rt_serial_device +{ + struct rt_device parent; + + const struct rt_uart_ops *ops; + struct serial_configure config; + + void *serial_rx; + void *serial_tx; +}; + +/** + * uart operators + */ +struct rt_uart_ops +{ + rt_err_t (*configure)(struct rt_serial_device *serial, + struct serial_configure *cfg); + + rt_err_t (*control)(struct rt_serial_device *serial, + int cmd, + void *arg); + + int (*putc)(struct rt_serial_device *serial, char c); + int (*getc)(struct rt_serial_device *serial); + + rt_size_t (*transmit)(struct rt_serial_device *serial, + rt_uint8_t *buf, + rt_size_t size, + rt_uint32_t tx_flag); +}; + +rt_size_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb, + rt_uint8_t **ptr); + +rt_size_t rt_serial_update_read_index(struct rt_ringbuffer *rb, + rt_uint16_t read_index); + +rt_size_t rt_serial_update_write_index(struct rt_ringbuffer *rb, + rt_uint16_t write_index); + +void rt_hw_serial_isr(struct rt_serial_device *serial, int event); + +rt_err_t rt_hw_serial_register(struct rt_serial_device *serial, + const char *name, + rt_uint32_t flag, + void *data); + +#endif diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index fbd3c9e7b2..07a2be361e 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -57,7 +57,11 @@ extern "C" { #endif /* RT_USING_USB_HOST */ #ifdef RT_USING_SERIAL +#ifdef RT_USING_SERIAL_V2 +#include "drivers/serial_v2.h" +#else #include "drivers/serial.h" +#endif #endif /* RT_USING_SERIAL */ #ifdef RT_USING_I2C diff --git a/components/drivers/serial/SConscript b/components/drivers/serial/SConscript index a6eb115919..f3f69991f5 100644 --- a/components/drivers/serial/SConscript +++ b/components/drivers/serial/SConscript @@ -1,8 +1,13 @@ from building import * -cwd = GetCurrentDir() -src = Glob('*.c') +cwd = GetCurrentDir() CPPPATH = [cwd + '/../include'] -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL'], CPPPATH = CPPPATH) +if GetDepend(['RT_USING_SERIAL']): + if GetDepend(['RT_USING_SERIAL_V2']): + src = Glob('serial_v2.c') + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL_V2'], CPPPATH = CPPPATH) + else: + src = Glob('serial.c') + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL'], CPPPATH = CPPPATH) Return('group') diff --git a/components/drivers/serial/serial_v2.c b/components/drivers/serial/serial_v2.c new file mode 100644 index 0000000000..f41cdcd8f9 --- /dev/null +++ b/components/drivers/serial/serial_v2.c @@ -0,0 +1,1171 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-01 KyleChan first version + */ + +#include +#include +#include + +#define DBG_TAG "UART" +#define DBG_LVL DBG_INFO +#include + +#ifdef RT_USING_POSIX +#include +#include + +#ifdef getc +#undef getc +#endif + +#ifdef putc +#undef putc +#endif + +static rt_err_t serial_fops_rx_ind(rt_device_t dev, rt_size_t size) +{ + rt_wqueue_wakeup(&(dev->wait_queue), (void*)POLLIN); + + return RT_EOK; +} + +/* fops for serial */ +static int serial_fops_open(struct dfs_fd *fd) +{ + rt_err_t ret = 0; + rt_uint16_t flags = 0; + rt_device_t device; + + device = (rt_device_t)fd->data; + RT_ASSERT(device != RT_NULL); + + switch (fd->flags & O_ACCMODE) + { + case O_RDONLY: + LOG_D("fops open: O_RDONLY!"); + flags = RT_DEVICE_FLAG_RDONLY; + break; + case O_WRONLY: + LOG_D("fops open: O_WRONLY!"); + flags = RT_DEVICE_FLAG_WRONLY; + break; + case O_RDWR: + LOG_D("fops open: O_RDWR!"); + flags = RT_DEVICE_FLAG_RDWR; + break; + default: + LOG_E("fops open: unknown mode - %d!", fd->flags & O_ACCMODE); + break; + } + + if ((fd->flags & O_ACCMODE) != O_WRONLY) + rt_device_set_rx_indicate(device, serial_fops_rx_ind); + ret = rt_device_open(device, flags); + if (ret == RT_EOK) return 0; + + return ret; +} + +static int serial_fops_close(struct dfs_fd *fd) +{ + rt_device_t device; + + device = (rt_device_t)fd->data; + + rt_device_set_rx_indicate(device, RT_NULL); + rt_device_close(device); + + return 0; +} + +static int serial_fops_ioctl(struct dfs_fd *fd, int cmd, void *args) +{ + rt_device_t device; + + device = (rt_device_t)fd->data; + switch (cmd) + { + case FIONREAD: + break; + case FIONWRITE: + break; + } + + return rt_device_control(device, cmd, args); +} + +static int serial_fops_read(struct dfs_fd *fd, void *buf, size_t count) +{ + int size = 0; + rt_device_t device; + + device = (rt_device_t)fd->data; + + do + { + size = rt_device_read(device, -1, buf, count); + if (size <= 0) + { + if (fd->flags & O_NONBLOCK) + { + size = -EAGAIN; + break; + } + + rt_wqueue_wait(&(device->wait_queue), 0, RT_WAITING_FOREVER); + } + }while (size <= 0); + + return size; +} + +static int serial_fops_write(struct dfs_fd *fd, const void *buf, size_t count) +{ + rt_device_t device; + + device = (rt_device_t)fd->data; + return rt_device_write(device, -1, buf, count); +} + +static int serial_fops_poll(struct dfs_fd *fd, struct rt_pollreq *req) +{ + int mask = 0; + int flags = 0; + rt_device_t device; + struct rt_serial_device *serial; + + device = (rt_device_t)fd->data; + RT_ASSERT(device != RT_NULL); + + serial = (struct rt_serial_device *)device; + + /* only support POLLIN */ + flags = fd->flags & O_ACCMODE; + if (flags == O_RDONLY || flags == O_RDWR) + { + rt_base_t level; + struct rt_serial_rx_fifo* rx_fifo; + + rt_poll_add(&(device->wait_queue), req); + + rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx; + + level = rt_hw_interrupt_disable(); + + if (rt_ringbuffer_data_len(&rx_fifo->rb)) + mask |= POLLIN; + rt_hw_interrupt_enable(level); + } + // mask|=POLLOUT; + return mask; +} + +const static struct dfs_file_ops _serial_fops = +{ + serial_fops_open, + serial_fops_close, + serial_fops_ioctl, + serial_fops_read, + serial_fops_write, + RT_NULL, /* flush */ + RT_NULL, /* lseek */ + RT_NULL, /* getdents */ + serial_fops_poll, +}; +#endif + +rt_size_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb, + rt_uint8_t **ptr) +{ + rt_size_t size; + + RT_ASSERT(rb != RT_NULL); + + *ptr = RT_NULL; + + /* whether has enough data */ + size = rt_ringbuffer_data_len(rb); + + /* no data */ + if (size == 0) + return 0; + + *ptr = &rb->buffer_ptr[rb->read_index]; + + if(rb->buffer_size - rb->read_index > size) + { + return size; + } + + return rb->buffer_size - rb->read_index; +} + +rt_size_t rt_serial_update_read_index(struct rt_ringbuffer *rb, + rt_uint16_t read_index) +{ + rt_size_t size; + + RT_ASSERT(rb != RT_NULL); + + /* whether has enough data */ + size = rt_ringbuffer_data_len(rb); + + /* no data */ + if (size == 0) + return 0; + + /* less data */ + if(size < read_index) + read_index = size; + + if(rb->buffer_size - rb->read_index > read_index) + { + rb->read_index += read_index; + return read_index; + } + + read_index = rb->buffer_size - rb->read_index; + + /* we are going into the other side of the mirror */ + rb->read_mirror = ~rb->read_mirror; + rb->read_index = 0; + + return read_index; +} + +rt_size_t rt_serial_update_write_index(struct rt_ringbuffer *rb, + rt_uint16_t write_index) +{ + rt_uint16_t size; + RT_ASSERT(rb != RT_NULL); + + /* whether has enough space */ + size = rt_ringbuffer_space_len(rb); + + /* no space */ + if (size == 0) + return 0; + + /* drop some data */ + if (size < write_index) + write_index = size; + + if (rb->buffer_size - rb->write_index > write_index) + { + /* this should not cause overflow because there is enough space for + * length of data in current mirror */ + rb->write_index += write_index; + return write_index; + } + + /* we are going into the other side of the mirror */ + rb->write_mirror = ~rb->write_mirror; + rb->write_index = write_index - (rb->buffer_size - rb->write_index); + + return write_index; +} + + +/** + * @brief Serial polling receive data routine, This function will receive data + * in a continuous loop by one by one byte. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Receive data buffer. + * @param size Receive data buffer length. + * @return Return the final length of data received. + */ +rt_size_t _serial_poll_rx(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + rt_size_t getc_size; + int getc_element; /* Gets one byte of data received */ + rt_uint8_t *getc_buffer; /* Pointer to the receive data buffer */ + + RT_ASSERT(dev != RT_NULL); + + serial = (struct rt_serial_device *)dev; + RT_ASSERT(serial != RT_NULL); + getc_buffer = (rt_uint8_t *)buffer; + getc_size = size; + + while(size) + { + getc_element = serial->ops->getc(serial); + if (getc_element == -1) break; + + *getc_buffer = getc_element; + + ++ getc_buffer; + -- size; + + if (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM) + { + /* If open_flag satisfies RT_DEVICE_FLAG_STREAM + * and the received character is '\n', exit the loop directly */ + if (getc_element == '\n') break; + } + } + + return getc_size - size; +} + +/** + * @brief Serial polling transmit data routines, This function will transmit + * data in a continuous loop by one by one byte. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data received. + */ +rt_size_t _serial_poll_tx(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + rt_size_t putc_size; + rt_uint8_t *putc_buffer; /* Pointer to the transmit data buffer */ + RT_ASSERT(dev != RT_NULL); + + serial = (struct rt_serial_device *)dev; + RT_ASSERT(serial != RT_NULL); + + putc_buffer = (rt_uint8_t *)buffer; + putc_size = size; + + while (size) + { + if (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM) + { + /* If open_flag satisfies RT_DEVICE_FLAG_STREAM and the received character is '\n', + * inserts '\r' character before '\n' character for the effect of carriage return newline */ + if (*putc_buffer == '\n') + serial->ops->putc(serial, '\r'); + } + serial->ops->putc(serial, *putc_buffer); + + ++ putc_buffer; + -- size; + } + + return putc_size - size; +} + +/** + * @brief Serial receive data routines, This function will receive + * data by using fifo + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Receive data buffer. + * @param size Receive data buffer length. + * @return Return the final length of data received. + */ +static rt_size_t _serial_fifo_rx(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_rx_fifo *rx_fifo; + rt_base_t level; + rt_size_t recv_len; /* The length of data from the ringbuffer */ + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + + rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; + + if (dev->open_flag & RT_SERIAL_RX_BLOCKING) + { + if (size > serial->config.rx_bufsz) + { + LOG_W("(%s) serial device received data:[%d] larger than " + "rx_bufsz:[%d], please increase the BSP_UARTx_RX_BUFSIZE option", + dev->parent.name, size, serial->config.rx_bufsz); + + return 0; + } + /* Get the length of the data from the ringbuffer */ + recv_len = rt_ringbuffer_data_len(&(rx_fifo->rb)); + + if (recv_len < size) + { + /* When recv_len is less than size, rx_cpt_index is updated to the size + * and rt_current_thread is suspend until rx_cpt_index is equal to 0 */ + rx_fifo->rx_cpt_index = size; + rt_completion_wait(&(rx_fifo->rx_cpt), RT_WAITING_FOREVER); + } + } + + /* This part of the code is open_flag as RT_SERIAL_RX_NON_BLOCKING */ + + level = rt_hw_interrupt_disable(); + /* When open_flag is RT_SERIAL_RX_NON_BLOCKING, + * the data is retrieved directly from the ringbuffer and returned */ + recv_len = rt_ringbuffer_get(&(rx_fifo->rb), buffer, size); + + rt_hw_interrupt_enable(level); + + return recv_len; +} + +/** + * @brief Serial transmit data routines, This function will transmit + * data by using blocking_nbuf. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data transmit. + */ +static rt_size_t _serial_fifo_tx_blocking_nbuf(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + /* When serial transmit in tx_blocking mode, + * if the activated mode is RT_TRUE, it will return directly */ + if (tx_fifo->activated == RT_TRUE) return 0; + + tx_fifo->activated = RT_TRUE; + /* Call the transmit interface for transmission */ + serial->ops->transmit(serial, + (rt_uint8_t *)buffer, + size, + RT_SERIAL_TX_BLOCKING); + /* Waiting for the transmission to complete */ + rt_completion_wait(&(tx_fifo->tx_cpt), RT_WAITING_FOREVER); + + return size; +} + +/** + * @brief Serial transmit data routines, This function will transmit + * data by using blocking_buf. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data transmit. + */ +static rt_size_t _serial_fifo_tx_blocking_buf(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + /* When serial transmit in tx_blocking mode, + * if the activated mode is RT_TRUE, it will return directly */ + if (tx_fifo->activated == RT_TRUE) return 0; + + tx_fifo->activated = RT_TRUE; + rt_size_t length = size; + rt_size_t offset = 0; + + while (size) + { + /* Copy one piece of data into the ringbuffer at a time + * until the length of the data is equal to size */ + tx_fifo->put_size = rt_ringbuffer_put(&(tx_fifo->rb), + (rt_uint8_t *)buffer + offset, + size); + + offset += tx_fifo->put_size; + size -= tx_fifo->put_size; + /* Call the transmit interface for transmission */ + serial->ops->transmit(serial, + (rt_uint8_t *)buffer + offset, + tx_fifo->put_size, + RT_SERIAL_TX_BLOCKING); + /* Waiting for the transmission to complete */ + rt_completion_wait(&(tx_fifo->tx_cpt), RT_WAITING_FOREVER); + } + + return length; +} + +/** + * @brief Serial transmit data routines, This function will transmit + * data by using nonblocking. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data transmit. + */ +static rt_size_t _serial_fifo_tx_nonblocking(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo; + rt_base_t level; + rt_size_t length; + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + + level = rt_hw_interrupt_disable(); + + if (tx_fifo->activated == RT_FALSE) + { + /* When serial transmit in tx_non_blocking mode, if the activated mode is RT_FALSE, + * start copying data into the ringbuffer */ + tx_fifo->activated = RT_TRUE; + /* Copying data into the ringbuffer */ + length = rt_ringbuffer_put(&(tx_fifo->rb), buffer, size); + + rt_hw_interrupt_enable(level); + + rt_uint8_t *put_ptr = RT_NULL; + /* Get the linear length buffer from rinbuffer */ + tx_fifo->put_size = rt_serial_get_linear_buffer(&(tx_fifo->rb), &put_ptr); + /* Call the transmit interface for transmission */ + serial->ops->transmit(serial, + put_ptr, + tx_fifo->put_size, + RT_SERIAL_TX_NON_BLOCKING); + /* In tx_nonblocking mode, there is no need to call rt_completion_wait() APIs to wait + * for the rt_current_thread to resume */ + return length; + } + + /* If the activated mode is RT_FALSE, it means that serial device is transmitting, + * where only the data in the ringbuffer and there is no need to call the transmit() API. + * Note that this part of the code requires disable interrupts + * to prevent multi thread reentrant */ + + /* Copying data into the ringbuffer */ + length = rt_ringbuffer_put(&(tx_fifo->rb), buffer, size); + + rt_hw_interrupt_enable(level); + + return length; +} + + +/** + * @brief Enable serial transmit mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_tx_enable(struct rt_device *dev, + rt_uint16_t tx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + if (serial->config.tx_bufsz == 0) + { + /* Cannot use RT_SERIAL_TX_NON_BLOCKING when tx_bufsz is 0 */ + if (tx_oflag == RT_SERIAL_TX_NON_BLOCKING) + { + LOG_E("(%s) serial device with misconfigure: tx_bufsz = 0", + dev->parent.name); + return -RT_EINVAL; + } + + dev->write = _serial_poll_tx; + dev->open_flag |= RT_SERIAL_TX_BLOCKING; + return RT_EOK; + } + /* Limits the minimum value of tx_bufsz */ + if (serial->config.tx_bufsz < RT_SERIAL_TX_MINBUFSZ) + serial->config.tx_bufsz = RT_SERIAL_TX_MINBUFSZ; + + if (tx_oflag == RT_SERIAL_TX_BLOCKING) + { + /* When using RT_SERIAL_TX_BLOCKING, it is necessary to determine + * whether serial device needs to use buffer */ + rt_err_t optmode; /* The operating mode used by serial device */ + /* Call the Control() API to get the operating mode */ + optmode = serial->ops->control(serial, + RT_DEVICE_CHECK_OPTMODE, + (void *)RT_DEVICE_FLAG_TX_BLOCKING); + if (optmode == RT_SERIAL_TX_BLOCKING_BUFFER) + { + /* If use RT_SERIAL_TX_BLOCKING_BUFFER, the ringbuffer is initialized */ + tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc + (sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz); + RT_ASSERT(tx_fifo != RT_NULL); + + rt_ringbuffer_init(&(tx_fifo->rb), + tx_fifo->buffer, + serial->config.tx_bufsz); + serial->serial_tx = tx_fifo; + dev->write = _serial_fifo_tx_blocking_buf; + } + else + { + /* If not use RT_SERIAL_TX_BLOCKING_BUFFER, + * the control() API is called to configure the serial device */ + tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc + (sizeof(struct rt_serial_tx_fifo)); + RT_ASSERT(tx_fifo != RT_NULL); + + serial->serial_tx = tx_fifo; + dev->write = _serial_fifo_tx_blocking_nbuf; + /* Call the control() API to configure the serial device by RT_SERIAL_TX_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *)RT_SERIAL_TX_BLOCKING); + } + + tx_fifo->activated = RT_FALSE; + tx_fifo->put_size = 0; + rt_completion_init(&(tx_fifo->tx_cpt)); + dev->open_flag |= RT_SERIAL_TX_BLOCKING; + + return RT_EOK; + } + /* When using RT_SERIAL_TX_NON_BLOCKING, ringbuffer needs to be initialized, + * and initialize the tx_fifo->activated value is RT_FALSE. + */ + tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc + (sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz); + RT_ASSERT(tx_fifo != RT_NULL); + + tx_fifo->activated = RT_FALSE; + tx_fifo->put_size = 0; + rt_ringbuffer_init(&(tx_fifo->rb), + tx_fifo->buffer, + serial->config.tx_bufsz); + serial->serial_tx = tx_fifo; + + dev->write = _serial_fifo_tx_nonblocking; + dev->open_flag |= RT_SERIAL_TX_NON_BLOCKING; + /* Call the control() API to configure the serial device by RT_SERIAL_TX_NON_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *)RT_SERIAL_TX_NON_BLOCKING); + + return RT_EOK; +} + + +/** + * @brief Enable serial receive mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_rx_enable(struct rt_device *dev, + rt_uint16_t rx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_rx_fifo *rx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + if (serial->config.rx_bufsz == 0) + { + /* Cannot use RT_SERIAL_RX_NON_BLOCKING when rx_bufsz is 0 */ + if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING) + { + LOG_E("(%s) serial device with misconfigure: rx_bufsz = 0", + dev->parent.name); + return -RT_EINVAL; + } + + dev->read = _serial_poll_rx; + dev->open_flag |= RT_SERIAL_RX_BLOCKING; + return RT_EOK; + } + /* Limits the minimum value of rx_bufsz */ + if (serial->config.rx_bufsz < RT_SERIAL_RX_MINBUFSZ) + serial->config.rx_bufsz = RT_SERIAL_RX_MINBUFSZ; + + rx_fifo = (struct rt_serial_rx_fifo *) rt_malloc + (sizeof(struct rt_serial_rx_fifo) + serial->config.rx_bufsz); + + RT_ASSERT(rx_fifo != RT_NULL); + rt_ringbuffer_init(&(rx_fifo->rb), rx_fifo->buffer, serial->config.rx_bufsz); + + rx_fifo->rx_index = serial->config.rx_bufsz; + serial->serial_rx = rx_fifo; + dev->read = _serial_fifo_rx; + + if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING) + { + dev->open_flag |= RT_SERIAL_RX_NON_BLOCKING; + /* Call the control() API to configure the serial device by RT_SERIAL_RX_NON_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *) RT_SERIAL_RX_NON_BLOCKING); + + return RT_EOK; + } + /* When using RT_SERIAL_RX_BLOCKING, rt_completion_init() and rx_cpt_index are initialized */ + rx_fifo->rx_cpt_index = 0; + rt_completion_init(&(rx_fifo->rx_cpt)); + dev->open_flag |= RT_SERIAL_RX_BLOCKING; + /* Call the control() API to configure the serial device by RT_SERIAL_RX_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *) RT_SERIAL_RX_BLOCKING); + + return RT_EOK; +} + +/** + * @brief Disable serial receive mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_rx_disable(struct rt_device *dev, + rt_uint16_t rx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_rx_fifo *rx_fifo; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + dev->read = RT_NULL; + if (serial->serial_rx == RT_NULL) return RT_EOK; + + do + { + if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING) + { + dev->open_flag &= ~ RT_SERIAL_RX_NON_BLOCKING; + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_RX_NON_BLOCKING); + break; + } + + dev->open_flag &= ~ RT_SERIAL_RX_BLOCKING; + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_RX_BLOCKING); + } while (0); + + rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + rt_free(rx_fifo); + serial->serial_rx = RT_NULL; + + return RT_EOK; +} + +/** + * @brief Disable serial tranmit mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_tx_disable(struct rt_device *dev, + rt_uint16_t tx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + dev->write = RT_NULL; + if (serial->serial_tx == RT_NULL) return RT_EOK; + + do + { + if (tx_oflag == RT_SERIAL_TX_NON_BLOCKING) + { + dev->open_flag &= ~ RT_SERIAL_TX_NON_BLOCKING; + + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_TX_NON_BLOCKING); + break; + } + + dev->open_flag &= ~ RT_SERIAL_TX_BLOCKING; + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_TX_BLOCKING); + } while (0); + + tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + rt_free(tx_fifo); + serial->serial_tx = RT_NULL; + + return RT_EOK; +} + +/** + * @brief Initialize the serial device. + * @param dev The pointer of device driver structure + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_init(struct rt_device *dev) +{ + rt_err_t result = RT_EOK; + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + /* initialize rx/tx */ + serial->serial_rx = RT_NULL; + serial->serial_tx = RT_NULL; + + /* apply configuration */ + if (serial->ops->configure) + result = serial->ops->configure(serial, &serial->config); + + return result; +} + +/** + * @brief Open the serial device. + * @param dev The pointer of device driver structure + * @param oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) +{ + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + LOG_D("open serial device: 0x%08x with open flag: 0x%04x", + dev, oflag); + + /* By default, the receive mode of a serial devide is RT_SERIAL_RX_NON_BLOCKING */ + if ((oflag & RT_SERIAL_RX_BLOCKING) == RT_SERIAL_RX_BLOCKING) + dev->open_flag |= RT_SERIAL_RX_BLOCKING; + else + dev->open_flag |= RT_SERIAL_RX_NON_BLOCKING; + + /* By default, the transmit mode of a serial devide is RT_SERIAL_TX_BLOCKING */ + if ((oflag & RT_SERIAL_TX_NON_BLOCKING) == RT_SERIAL_TX_NON_BLOCKING) + dev->open_flag |= RT_SERIAL_TX_NON_BLOCKING; + else + dev->open_flag |= RT_SERIAL_TX_BLOCKING; + + /* set steam flag */ + if ((oflag & RT_DEVICE_FLAG_STREAM) || + (dev->open_flag & RT_DEVICE_FLAG_STREAM)) + dev->open_flag |= RT_DEVICE_FLAG_STREAM; + + /* initialize the Rx structure according to open flag */ + if (serial->serial_rx == RT_NULL) + rt_serial_rx_enable(dev, dev->open_flag & + (RT_SERIAL_RX_BLOCKING | RT_SERIAL_RX_NON_BLOCKING)); + + /* initialize the Tx structure according to open flag */ + if (serial->serial_tx == RT_NULL) + rt_serial_tx_enable(dev, dev->open_flag & + (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING)); + + return RT_EOK; +} + + +/** + * @brief Close the serial device. + * @param dev The pointer of device driver structure + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_close(struct rt_device *dev) +{ + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + /* this device has more reference count */ + if (dev->ref_count > 1) return -RT_ERROR; + /* Disable serial receive mode. */ + rt_serial_rx_disable(dev, dev->open_flag & + (RT_SERIAL_RX_BLOCKING | RT_SERIAL_RX_NON_BLOCKING)); + /* Disable serial tranmit mode. */ + rt_serial_tx_disable(dev, dev->open_flag & + (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING)); + + /* Call the control() API to close the serial device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLOSE, RT_NULL); + dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED; + + return RT_EOK; +} + +/** + * @brief Control the serial device. + * @param dev The pointer of device driver structure + * @param cmd The command value that controls the serial device + * @param args The parameter value that controls the serial device + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_control(struct rt_device *dev, + int cmd, + void *args) +{ + rt_err_t ret = RT_EOK; + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + switch (cmd) + { + case RT_DEVICE_CTRL_SUSPEND: + /* suspend device */ + dev->flag |= RT_DEVICE_FLAG_SUSPENDED; + break; + + case RT_DEVICE_CTRL_RESUME: + /* resume device */ + dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED; + break; + + case RT_DEVICE_CTRL_CONFIG: + if (args != RT_NULL) + { + struct serial_configure *pconfig = (struct serial_configure *) args; + if (serial->parent.ref_count) + { + /*can not change buffer size*/ + return -RT_EBUSY; + } + /* set serial configure */ + serial->config = *pconfig; + serial->ops->configure(serial, + (struct serial_configure *) args); + } + + break; + + default : + /* control device */ + ret = serial->ops->control(serial, cmd, args); + break; + } + + return ret; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops serial_ops = +{ + rt_serial_init, + rt_serial_open, + rt_serial_close, + rt_serial_read, + rt_serial_write, + rt_serial_control +}; +#endif + +/** + * @brief Register the serial device. + * @param serial RT-thread serial device. + * @param name The device driver's name + * @param flag The capabilities flag of device. + * @param data The device driver's data. + * @return Return the status of the operation. + */ +rt_err_t rt_hw_serial_register(struct rt_serial_device *serial, + const char *name, + rt_uint32_t flag, + void *data) +{ + rt_err_t ret; + struct rt_device *device; + RT_ASSERT(serial != RT_NULL); + + device = &(serial->parent); + + device->type = RT_Device_Class_Char; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &serial_ops; +#else + device->init = rt_serial_init; + device->open = rt_serial_open; + device->close = rt_serial_close; + device->read = RT_NULL; + device->write = RT_NULL; + device->control = rt_serial_control; +#endif + device->user_data = data; + + /* register a character device */ + ret = rt_device_register(device, name, flag); + +#if defined(RT_USING_POSIX) + /* set fops */ + device->fops = &_serial_fops; +#endif + return ret; +} + +/** + * @brief ISR for serial interrupt + * @param serial RT-thread serial device. + * @param event ISR event type. + */ +void rt_hw_serial_isr(struct rt_serial_device *serial, int event) +{ + RT_ASSERT(serial != RT_NULL); + + switch (event & 0xff) + { + /* Interrupt receive event */ + case RT_SERIAL_EVENT_RX_IND: + case RT_SERIAL_EVENT_RX_DMADONE: + { + struct rt_serial_rx_fifo *rx_fifo; + rt_size_t rx_length = 0; + rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + + /* Get the length of the data from the ringbuffer */ + rx_length = rt_ringbuffer_data_len(&rx_fifo->rb); + + if (rx_length == 0) break; + + if (serial->parent.open_flag & RT_SERIAL_RX_BLOCKING) + { + if (rx_fifo->rx_cpt_index && rx_length >= rx_fifo->rx_cpt_index ) + { + rx_fifo->rx_cpt_index = 0; + rt_completion_done(&(rx_fifo->rx_cpt)); + } + } + /* Trigger the receiving completion callback */ + if (serial->parent.rx_indicate != RT_NULL) + serial->parent.rx_indicate(&(serial->parent), rx_length); + break; + } + + /* Interrupt transmit event */ + case RT_SERIAL_EVENT_TX_DONE: + { + struct rt_serial_tx_fifo *tx_fifo; + rt_size_t tx_length = 0; + tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + /* Get the length of the data from the ringbuffer */ + tx_length = rt_ringbuffer_data_len(&tx_fifo->rb); + /* If there is no data in tx_ringbuffer, + * then the transmit completion callback is triggered*/ + if (tx_length == 0) + { + tx_fifo->activated = RT_FALSE; + /* Trigger the transmit completion callback */ + if (serial->parent.tx_complete != RT_NULL) + serial->parent.tx_complete(&serial->parent, RT_NULL); + + if (serial->parent.open_flag & RT_SERIAL_TX_BLOCKING) + rt_completion_done(&(tx_fifo->tx_cpt)); + + break; + } + + /* Call the transmit interface for transmission again */ + /* Note that in interrupt mode, tx_fifo->buffer and tx_length + * are inactive parameters */ + serial->ops->transmit(serial, + tx_fifo->buffer, + tx_length, + serial->parent.open_flag & ( \ + RT_SERIAL_TX_BLOCKING | \ + RT_SERIAL_TX_NON_BLOCKING)); + break; + } + + case RT_SERIAL_EVENT_TX_DMADONE: + { + struct rt_serial_tx_fifo *tx_fifo; + tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + tx_fifo->activated = RT_FALSE; + + /* Trigger the transmit completion callback */ + if (serial->parent.tx_complete != RT_NULL) + serial->parent.tx_complete(&serial->parent, RT_NULL); + + if (serial->parent.open_flag & RT_SERIAL_TX_BLOCKING) + { + rt_completion_done(&(tx_fifo->tx_cpt)); + break; + } + + rt_serial_update_read_index(&tx_fifo->rb, tx_fifo->put_size); + /* Get the length of the data from the ringbuffer. + * If there is some data in tx_ringbuffer, + * then call the transmit interface for transmission again */ + if (rt_ringbuffer_data_len(&tx_fifo->rb)) + { + tx_fifo->activated = RT_TRUE; + + rt_uint8_t *put_ptr = RT_NULL; + /* Get the linear length buffer from rinbuffer */ + tx_fifo->put_size = rt_serial_get_linear_buffer(&(tx_fifo->rb), &put_ptr); + /* Call the transmit interface for transmission again */ + serial->ops->transmit(serial, + put_ptr, + tx_fifo->put_size, + RT_SERIAL_TX_NON_BLOCKING); + } + + break; + } + + default: + break; + } +} From fac3c5cda1c5a48c8a8d8c5c753e3a3886ac509e Mon Sep 17 00:00:00 2001 From: chenjh Date: Mon, 7 Jun 2021 22:46:02 +0800 Subject: [PATCH 141/255] =?UTF-8?q?[serial]=20=E4=BC=98=E5=8C=96dma?= =?UTF-8?q?=E6=8E=A5=E6=94=B6=E5=A4=84=E7=90=86=E6=B5=81=E7=A8=8B=EF=BC=8C?= =?UTF-8?q?=E8=A7=A3=E8=80=A6=E9=A9=B1=E5=8A=A8=E8=B0=83=E7=94=A8=E4=B8=B2?= =?UTF-8?q?=E5=8F=A3=E6=A1=86=E6=9E=B6=E7=9A=84API=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../libraries/HAL_Drivers/drv_usart_v2.c | 42 +- bsp/stm32/stm32l475-atk-pandora/.config | 16 +- .../stm32l475-atk-pandora/project.uvprojx | 538 +++++++----------- bsp/stm32/stm32l475-atk-pandora/rtconfig.h | 10 - .../drivers/include/drivers/serial_v2.h | 14 +- components/drivers/serial/serial_v2.c | 51 +- 6 files changed, 269 insertions(+), 402 deletions(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c index 51dfc425c4..b1b224005a 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c @@ -342,37 +342,42 @@ static void dma_recv_isr(struct rt_serial_device *serial, rt_uint8_t isr_flag) { struct stm32_uart *uart; rt_base_t level; - rt_uint16_t recv_len = 0; + rt_size_t recv_len, counter; RT_ASSERT(serial != RT_NULL); uart = rt_container_of(serial, struct stm32_uart, serial); - struct rt_serial_rx_fifo *rx_fifo; - rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; - RT_ASSERT(rx_fifo != RT_NULL); - level = rt_hw_interrupt_disable(); - rt_uint16_t index = __HAL_DMA_GET_COUNTER(&(uart->dma_rx.handle)); + recv_len = 0; + counter = __HAL_DMA_GET_COUNTER(&(uart->dma_rx.handle)); + switch (isr_flag) { - - case UART_RX_DMA_IT_TC_FLAG: - if(index >= uart->dma_rx.remaining_cnt) - recv_len = serial->config.rx_bufsz + uart->dma_rx.remaining_cnt - index; + case UART_RX_DMA_IT_IDLE_FLAG: + if (counter <= uart->dma_rx.remaining_cnt) + recv_len = uart->dma_rx.remaining_cnt - counter; + else + recv_len = serial->config.rx_bufsz + uart->dma_rx.remaining_cnt - counter; break; case UART_RX_DMA_IT_HT_FLAG: - case UART_RX_DMA_IT_IDLE_FLAG: - if(index < uart->dma_rx.remaining_cnt) - recv_len = uart->dma_rx.remaining_cnt - index; + if (counter < uart->dma_rx.remaining_cnt) + recv_len = uart->dma_rx.remaining_cnt - counter; break; + case UART_RX_DMA_IT_TC_FLAG: + if(counter >= uart->dma_rx.remaining_cnt) + recv_len = serial->config.rx_bufsz + uart->dma_rx.remaining_cnt - counter; + default: break; } - uart->dma_rx.remaining_cnt = index; - rt_serial_update_write_index(&(rx_fifo->rb), recv_len); + if (recv_len) + { + uart->dma_rx.remaining_cnt = counter; + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); + } rt_hw_interrupt_enable(level); } @@ -444,7 +449,6 @@ static void uart_isr(struct rt_serial_device *serial) && (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_IDLE) != RESET)) { dma_recv_isr(serial, UART_RX_DMA_IT_IDLE_FLAG); - rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); __HAL_UART_CLEAR_IDLEFLAG(&uart->handle); } #endif @@ -1051,9 +1055,7 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) struct stm32_uart *uart; RT_ASSERT(huart != NULL); uart = (struct stm32_uart *)huart; - dma_recv_isr(&uart->serial, UART_RX_DMA_IT_TC_FLAG); - rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_RX_DMADONE); } /** @@ -1068,15 +1070,13 @@ void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) struct stm32_uart *uart; RT_ASSERT(huart != NULL); uart = (struct stm32_uart *)huart; - dma_recv_isr(&uart->serial, UART_RX_DMA_IT_HT_FLAG); - rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_RX_DMADONE); } /** * @brief HAL_UART_TxCpltCallback * @param huart: UART handle - * @note This callback can be called by two functions, first in UART_EndTransmit_IT when + * @note This callback can be called by two functions, first in UART_EndTransmit_IT when * UART Tx complete and second in UART_DMATransmitCplt function in DMA Circular mode. * @retval None */ diff --git a/bsp/stm32/stm32l475-atk-pandora/.config b/bsp/stm32/stm32l475-atk-pandora/.config index 365e154c17..3420b2d793 100644 --- a/bsp/stm32/stm32l475-atk-pandora/.config +++ b/bsp/stm32/stm32l475-atk-pandora/.config @@ -197,21 +197,7 @@ CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set -CONFIG_RT_USING_RT_LINK=y -CONFIG_RT_LINK_USING_SF_CRC=y -# CONFIG_RT_LINK_USING_HW_CRC is not set - -# -# rt-link hardware device configuration -# -CONFIG_RT_LINK_HW_DEVICE_NAME="uart2" -CONFIG_RT_LINK_USING_UART=y - -# -# rt link debug option -# -# CONFIG_USING_RT_LINK_DEBUG is not set -# CONFIG_USING_RT_LINK_HW_DEBUG is not set +# CONFIG_RT_USING_RT_LINK is not set # CONFIG_RT_USING_LWP is not set # diff --git a/bsp/stm32/stm32l475-atk-pandora/project.uvprojx b/bsp/stm32/stm32l475-atk-pandora/project.uvprojx index 1a187748bd..6089d4c371 100644 --- a/bsp/stm32/stm32l475-atk-pandora/project.uvprojx +++ b/bsp/stm32/stm32l475-atk-pandora/project.uvprojx @@ -1,7 +1,10 @@ + 2.1 +
### uVision Project, (C) Keil Software
+ rt-thread @@ -13,31 +16,31 @@ STM32L475VETx STMicroelectronics - Keil.STM32L4xx_DFP.2.0.0 + Keil.STM32L4xx_DFP.2.2.0 http://www.keil.com/pack IRAM(0x20000000,0x00018000) IRAM2(0x10000000,0x00008000) IROM(0x08000000,0x00080000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE - - + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32L4xx_512 -FS08000000 -FL080000 -FP0($$Device:STM32L475VETx$CMSIS\Flash\STM32L4xx_512.FLM)) 0 $$Device:STM32L475VETx$Drivers\CMSIS\Device\ST\STM32L4xx\Include\stm32l4xx.h - - - - - - - - - + + + + + + + + + $$Device:STM32L475VETx$CMSIS\SVD\STM32L4x5.svd 0 0 - - - - - + + + + + 0 0 @@ -59,8 +62,8 @@ 0 0 - - + + 0 0 0 @@ -69,8 +72,8 @@ 0 0 - - + + 0 0 0 @@ -80,14 +83,14 @@ 1 0 fromelf --bin !L --output rtthread.bin - + 0 0 0 0 0 - + 0 @@ -101,8 +104,8 @@ 0 0 3 - - + + 1 @@ -136,10 +139,10 @@ 1 BIN\UL2CM3.DLL "" () - - - - + + + + 0 @@ -172,7 +175,7 @@ 0 0 "Cortex-M4" - + 0 0 0 @@ -181,6 +184,7 @@ 0 0 2 + 0 1 0 8 @@ -304,7 +308,7 @@ 0x8000 - + 1 @@ -331,10 +335,10 @@ 0 0 - + USE_HAL_DRIVER, __RTTHREAD__, STM32L475xx - - .;applications;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\CubeMX_Config\Inc;board\ports;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Inc;..\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Include;..\libraries\STM32L4xx_HAL\CMSIS\Include + + .;applications;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\CubeMX_Config\Inc;board\ports;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Inc;..\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Include;..\libraries\STM32L4xx_HAL\CMSIS\Include @@ -349,10 +353,10 @@ 0 0 - - - - + + + + @@ -364,13 +368,13 @@ 0 0x08000000 0x20000000 - + .\board\linker_scripts\link.sct - - - - - + + + + + @@ -383,39 +387,36 @@ 1 applications\main.c + + uart_sample.c + 1 + .\applications\uart_sample.c + CPU - backtrace.c + showmem.c 1 - ..\..\..\libcpu\arm\common\backtrace.c + ..\..\..\libcpu\arm\common\showmem.c - - div0.c 1 ..\..\..\libcpu\arm\common\div0.c - - - showmem.c + backtrace.c 1 - ..\..\..\libcpu\arm\common\showmem.c + ..\..\..\libcpu\arm\common\backtrace.c - - cpuport.c 1 ..\..\..\libcpu\arm\cortex-m4\cpuport.c - - context_rvds.S 2 @@ -431,57 +432,41 @@ 1 ..\..\..\components\drivers\misc\pin.c - - - serial.c + serial_v2.c 1 - ..\..\..\components\drivers\serial\serial.c + ..\..\..\components\drivers\serial\serial_v2.c - - completion.c 1 ..\..\..\components\drivers\src\completion.c - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - ringbuffer.c 1 ..\..\..\components\drivers\src\ringbuffer.c - - waitqueue.c 1 ..\..\..\components\drivers\src\waitqueue.c - - + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + workqueue.c 1 @@ -491,42 +476,32 @@ Drivers - - - board.c - 1 - board\board.c - - stm32l4xx_hal_msp.c 1 board\CubeMX_Config\Src\stm32l4xx_hal_msp.c - - + + board.c + 1 + board\board.c + startup_stm32l475xx.s 2 ..\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Source\Templates\arm\startup_stm32l475xx.s - - drv_gpio.c 1 ..\libraries\HAL_Drivers\drv_gpio.c - - - drv_usart.c + drv_usart_v2.c 1 - ..\libraries\HAL_Drivers\drv_usart.c + ..\libraries\HAL_Drivers\drv_usart_v2.c - - drv_common.c 1 @@ -542,116 +517,81 @@ 1 ..\..\..\components\finsh\shell.c - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - msh.c 1 ..\..\..\components\finsh\msh.c + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + Kernel - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - device.c - 1 - ..\..\..\src\device.c - - idle.c 1 ..\..\..\src\idle.c - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - kservice.c 1 ..\..\..\src\kservice.c - - - mem.c + device.c 1 - ..\..\..\src\mem.c + ..\..\..\src\device.c + + + clock.c + 1 + ..\..\..\src\clock.c - - mempool.c 1 ..\..\..\src\mempool.c - - - - object.c - 1 - ..\..\..\src\object.c - - - scheduler.c 1 ..\..\..\src\scheduler.c - - - signal.c + mem.c 1 - ..\..\..\src\signal.c + ..\..\..\src\mem.c + + + components.c + 1 + ..\..\..\src\components.c + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + irq.c + 1 + ..\..\..\src\irq.c + + + object.c + 1 + ..\..\..\src\object.c - - thread.c 1 ..\..\..\src\thread.c - - timer.c 1 @@ -659,172 +599,124 @@ - - libc - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - Libraries - - - system_stm32l4xx.c - 1 - ..\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Source\Templates\system_stm32l4xx.c - - - - - stm32l4xx_hal.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal.c - - - - - stm32l4xx_hal_comp.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_comp.c - - - - - stm32l4xx_hal_cortex.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_cortex.c - - - - - stm32l4xx_hal_crc.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_crc.c - - - - - stm32l4xx_hal_crc_ex.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_crc_ex.c - - stm32l4xx_hal_cryp.c 1 ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_cryp.c - - + + stm32l4xx_hal_uart.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart.c + + + stm32l4xx_hal_usart.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_usart.c + + + stm32l4xx_hal_cortex.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_cortex.c + + + stm32l4xx_hal_gpio.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_gpio.c + + + stm32l4xx_hal_dma.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma.c + + + stm32l4xx_hal_pwr.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr.c + + + stm32l4xx_hal_rcc_ex.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc_ex.c + + + stm32l4xx_hal_rcc.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc.c + + + stm32l4xx_hal_dma_ex.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma_ex.c + + + stm32l4xx_hal_exti.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_exti.c + + + stm32l4xx_hal_crc.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_crc.c + + + stm32l4xx_hal.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal.c + + + stm32l4xx_hal_usart_ex.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_usart_ex.c + + + stm32l4xx_hal_uart_ex.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart_ex.c + + + stm32l4xx_hal_crc_ex.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_crc_ex.c + + + stm32l4xx_hal_comp.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_comp.c + + + stm32l4xx_hal_pwr_ex.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr_ex.c + + + stm32l4xx_hal_rng.c + 1 + ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rng.c + + + system_stm32l4xx.c + 1 + ..\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Source\Templates\system_stm32l4xx.c + stm32l4xx_hal_cryp_ex.c 1 ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_cryp_ex.c - - - stm32l4xx_hal_dma.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma.c - - - - - stm32l4xx_hal_dma_ex.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma_ex.c - - - - - stm32l4xx_hal_exti.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_exti.c - - - - - stm32l4xx_hal_pwr.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr.c - - - - - stm32l4xx_hal_pwr_ex.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr_ex.c - - - - - stm32l4xx_hal_rcc.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc.c - - - - - stm32l4xx_hal_rcc_ex.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc_ex.c - - - - - stm32l4xx_hal_rng.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rng.c - - - - - stm32l4xx_hal_gpio.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_gpio.c - - - - - stm32l4xx_hal_uart.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart.c - - - - - stm32l4xx_hal_uart_ex.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart_ex.c - - - - - stm32l4xx_hal_usart.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_usart.c - - - - - stm32l4xx_hal_usart_ex.c - 1 - ..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_usart_ex.c - - + - - - + + + +
diff --git a/bsp/stm32/stm32l475-atk-pandora/rtconfig.h b/bsp/stm32/stm32l475-atk-pandora/rtconfig.h index 178f69b3ec..5f3f8a812b 100644 --- a/bsp/stm32/stm32l475-atk-pandora/rtconfig.h +++ b/bsp/stm32/stm32l475-atk-pandora/rtconfig.h @@ -111,16 +111,6 @@ /* Utilities */ -#define RT_USING_RT_LINK -#define RT_LINK_USING_SF_CRC - -/* rt-link hardware device configuration */ - -#define RT_LINK_HW_DEVICE_NAME "uart2" -#define RT_LINK_USING_UART - -/* rt link debug option */ - /* RT-Thread Utestcases */ diff --git a/components/drivers/include/drivers/serial_v2.h b/components/drivers/include/drivers/serial_v2.h index 18187bc0f5..51306a4bb4 100644 --- a/components/drivers/include/drivers/serial_v2.h +++ b/components/drivers/include/drivers/serial_v2.h @@ -112,7 +112,7 @@ struct serial_configure }; /* - * Serial FIFO mode + * Serial Receive FIFO mode */ struct rt_serial_rx_fifo { @@ -128,6 +128,9 @@ struct rt_serial_rx_fifo rt_uint8_t buffer[]; }; +/* + * Serial Transmit FIFO mode + */ struct rt_serial_tx_fifo { struct rt_ringbuffer rb; @@ -174,15 +177,6 @@ struct rt_uart_ops rt_uint32_t tx_flag); }; -rt_size_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb, - rt_uint8_t **ptr); - -rt_size_t rt_serial_update_read_index(struct rt_ringbuffer *rb, - rt_uint16_t read_index); - -rt_size_t rt_serial_update_write_index(struct rt_ringbuffer *rb, - rt_uint16_t write_index); - void rt_hw_serial_isr(struct rt_serial_device *serial, int event); rt_err_t rt_hw_serial_register(struct rt_serial_device *serial, diff --git a/components/drivers/serial/serial_v2.c b/components/drivers/serial/serial_v2.c index f41cdcd8f9..1019b73e67 100644 --- a/components/drivers/serial/serial_v2.c +++ b/components/drivers/serial/serial_v2.c @@ -157,7 +157,7 @@ static int serial_fops_poll(struct dfs_fd *fd, struct rt_pollreq *req) rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx; level = rt_hw_interrupt_disable(); - + if (rt_ringbuffer_data_len(&rx_fifo->rb)) mask |= POLLIN; rt_hw_interrupt_enable(level); @@ -180,8 +180,8 @@ const static struct dfs_file_ops _serial_fops = }; #endif -rt_size_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb, - rt_uint8_t **ptr) +static rt_size_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb, + rt_uint8_t **ptr) { rt_size_t size; @@ -206,8 +206,8 @@ rt_size_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb, return rb->buffer_size - rb->read_index; } -rt_size_t rt_serial_update_read_index(struct rt_ringbuffer *rb, - rt_uint16_t read_index) +static rt_size_t rt_serial_update_read_index(struct rt_ringbuffer *rb, + rt_uint16_t read_index) { rt_size_t size; @@ -219,7 +219,7 @@ rt_size_t rt_serial_update_read_index(struct rt_ringbuffer *rb, /* no data */ if (size == 0) return 0; - + /* less data */ if(size < read_index) read_index = size; @@ -239,8 +239,8 @@ rt_size_t rt_serial_update_read_index(struct rt_ringbuffer *rb, return read_index; } -rt_size_t rt_serial_update_write_index(struct rt_ringbuffer *rb, - rt_uint16_t write_index) +static rt_size_t rt_serial_update_write_index(struct rt_ringbuffer *rb, + rt_uint16_t write_index) { rt_uint16_t size; RT_ASSERT(rb != RT_NULL); @@ -499,7 +499,7 @@ static rt_size_t _serial_fifo_tx_blocking_buf(struct rt_device *dev, while (size) { - /* Copy one piece of data into the ringbuffer at a time + /* Copy one piece of data into the ringbuffer at a time * until the length of the data is equal to size */ tx_fifo->put_size = rt_ringbuffer_put(&(tx_fifo->rb), (rt_uint8_t *)buffer + offset, @@ -629,7 +629,7 @@ static rt_err_t rt_serial_tx_enable(struct rt_device *dev, if (optmode == RT_SERIAL_TX_BLOCKING_BUFFER) { /* If use RT_SERIAL_TX_BLOCKING_BUFFER, the ringbuffer is initialized */ - tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc + tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc (sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz); RT_ASSERT(tx_fifo != RT_NULL); @@ -641,9 +641,9 @@ static rt_err_t rt_serial_tx_enable(struct rt_device *dev, } else { - /* If not use RT_SERIAL_TX_BLOCKING_BUFFER, + /* If not use RT_SERIAL_TX_BLOCKING_BUFFER, * the control() API is called to configure the serial device */ - tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc + tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc (sizeof(struct rt_serial_tx_fifo)); RT_ASSERT(tx_fifo != RT_NULL); @@ -665,14 +665,14 @@ static rt_err_t rt_serial_tx_enable(struct rt_device *dev, /* When using RT_SERIAL_TX_NON_BLOCKING, ringbuffer needs to be initialized, * and initialize the tx_fifo->activated value is RT_FALSE. */ - tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc + tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc (sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz); RT_ASSERT(tx_fifo != RT_NULL); tx_fifo->activated = RT_FALSE; tx_fifo->put_size = 0; - rt_ringbuffer_init(&(tx_fifo->rb), - tx_fifo->buffer, + rt_ringbuffer_init(&(tx_fifo->rb), + tx_fifo->buffer, serial->config.tx_bufsz); serial->serial_tx = tx_fifo; @@ -712,7 +712,7 @@ static rt_err_t rt_serial_rx_enable(struct rt_device *dev, return -RT_EINVAL; } - dev->read = _serial_poll_rx; + dev->read = _serial_poll_rx; dev->open_flag |= RT_SERIAL_RX_BLOCKING; return RT_EOK; } @@ -892,7 +892,7 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) dev->open_flag |= RT_SERIAL_TX_BLOCKING; /* set steam flag */ - if ((oflag & RT_DEVICE_FLAG_STREAM) || + if ((oflag & RT_DEVICE_FLAG_STREAM) || (dev->open_flag & RT_DEVICE_FLAG_STREAM)) dev->open_flag |= RT_DEVICE_FLAG_STREAM; @@ -903,7 +903,7 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) /* initialize the Tx structure according to open flag */ if (serial->serial_tx == RT_NULL) - rt_serial_tx_enable(dev, dev->open_flag & + rt_serial_tx_enable(dev, dev->open_flag & (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING)); return RT_EOK; @@ -925,10 +925,10 @@ static rt_err_t rt_serial_close(struct rt_device *dev) /* this device has more reference count */ if (dev->ref_count > 1) return -RT_ERROR; /* Disable serial receive mode. */ - rt_serial_rx_disable(dev, dev->open_flag & + rt_serial_rx_disable(dev, dev->open_flag & (RT_SERIAL_RX_BLOCKING | RT_SERIAL_RX_NON_BLOCKING)); /* Disable serial tranmit mode. */ - rt_serial_tx_disable(dev, dev->open_flag & + rt_serial_tx_disable(dev, dev->open_flag & (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING)); /* Call the control() API to close the serial device */ @@ -978,7 +978,7 @@ static rt_err_t rt_serial_control(struct rt_device *dev, } /* set serial configure */ serial->config = *pconfig; - serial->ops->configure(serial, + serial->ops->configure(serial, (struct serial_configure *) args); } @@ -994,7 +994,7 @@ static rt_err_t rt_serial_control(struct rt_device *dev, } #ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops serial_ops = +const static struct rt_device_ops serial_ops = { rt_serial_init, rt_serial_open, @@ -1070,9 +1070,14 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; RT_ASSERT(rx_fifo != RT_NULL); + /* If the event is RT_SERIAL_EVENT_RX_IND, rx_length is equal to 0 */ + rx_length = (event & (~0xff)) >> 8; + + if (rx_length) + rt_serial_update_write_index(&(rx_fifo->rb), rx_length); + /* Get the length of the data from the ringbuffer */ rx_length = rt_ringbuffer_data_len(&rx_fifo->rb); - if (rx_length == 0) break; if (serial->parent.open_flag & RT_SERIAL_RX_BLOCKING) From e029953bc08a2a500878dbf035a7a4a7332180a1 Mon Sep 17 00:00:00 2001 From: Wang-Huachen Date: Tue, 8 Jun 2021 19:28:08 +0800 Subject: [PATCH 142/255] fixed possible errors when using xil_cache.h --- bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_cache.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_cache.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_cache.h index 1731e84850..2590ce096b 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_cache.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_cache.h @@ -1,6 +1,8 @@ #ifndef XIL_CACHE_H #define XIL_CACHE_H +#include + #ifdef __cplusplus extern "C" { #endif From 7fd22c95466366915e62f3417caa9068c304bc41 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 9 Jun 2021 16:43:14 +0800 Subject: [PATCH 143/255] [msh]implement tail command --- components/finsh/msh_file.c | 152 ++++++++++++++++++++++++++++++------ 1 file changed, 126 insertions(+), 26 deletions(-) diff --git a/components/finsh/msh_file.c b/components/finsh/msh_file.c index 459d77af4e..3f21cc6f34 100644 --- a/components/finsh/msh_file.c +++ b/components/finsh/msh_file.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2015-09-25 Bernard the first verion for FinSH + * 2021-06-09 Meco Man implement tail command */ #include @@ -146,7 +147,7 @@ int msh_exec_script(const char *cmd_line, int size) extern char working_directory[]; #endif -int cmd_ls(int argc, char **argv) +static int cmd_ls(int argc, char **argv) { extern void ls(const char *pathname); @@ -165,9 +166,9 @@ int cmd_ls(int argc, char **argv) return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_ls, __cmd_ls, List information about the FILEs.); +MSH_CMD_EXPORT_ALIAS(cmd_ls, ls, List information about the FILEs.); -int cmd_cp(int argc, char **argv) +static int cmd_cp(int argc, char **argv) { void copy(const char *src, const char *dst); @@ -183,9 +184,9 @@ int cmd_cp(int argc, char **argv) return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_cp, __cmd_cp, Copy SOURCE to DEST.); +MSH_CMD_EXPORT_ALIAS(cmd_cp, cp, Copy SOURCE to DEST.); -int cmd_mv(int argc, char **argv) +static int cmd_mv(int argc, char **argv) { if (argc != 3) { @@ -242,9 +243,9 @@ int cmd_mv(int argc, char **argv) return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_mv, __cmd_mv, Rename SOURCE to DEST.); +MSH_CMD_EXPORT_ALIAS(cmd_mv, mv, Rename SOURCE to DEST.); -int cmd_cat(int argc, char **argv) +static int cmd_cat(int argc, char **argv) { int index; extern void cat(const char *filename); @@ -263,7 +264,7 @@ int cmd_cat(int argc, char **argv) return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_cat, __cmd_cat, Concatenate FILE(s)); +MSH_CMD_EXPORT_ALIAS(cmd_cat, cat, Concatenate FILE(s)); static void directory_delete_for_msh(const char *pathname, char f, char v) { @@ -329,7 +330,7 @@ static void directory_delete_for_msh(const char *pathname, char f, char v) } } -int cmd_rm(int argc, char **argv) +static int cmd_rm(int argc, char **argv) { int index, n; char f = 0, r = 0, v = 0; @@ -399,10 +400,10 @@ int cmd_rm(int argc, char **argv) } return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_rm, __cmd_rm, Remove(unlink) the FILE(s).); +MSH_CMD_EXPORT_ALIAS(cmd_rm, rm, Remove(unlink) the FILE(s).); #ifdef DFS_USING_WORKDIR -int cmd_cd(int argc, char **argv) +static int cmd_cd(int argc, char **argv) { if (argc == 1) { @@ -418,17 +419,17 @@ int cmd_cd(int argc, char **argv) return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_cd, __cmd_cd, Change the shell working directory.); +MSH_CMD_EXPORT_ALIAS(cmd_cd, cd, Change the shell working directory.); -int cmd_pwd(int argc, char **argv) +static int cmd_pwd(int argc, char **argv) { rt_kprintf("%s\n", working_directory); return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_pwd, __cmd_pwd, Print the name of the current working directory.); +MSH_CMD_EXPORT_ALIAS(cmd_pwd, pwd, Print the name of the current working directory.); #endif -int cmd_mkdir(int argc, char **argv) +static int cmd_mkdir(int argc, char **argv) { if (argc == 1) { @@ -442,9 +443,9 @@ int cmd_mkdir(int argc, char **argv) return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_mkdir, __cmd_mkdir, Create the DIRECTORY.); +MSH_CMD_EXPORT_ALIAS(cmd_mkdir, mkdir, Create the DIRECTORY.); -int cmd_mkfs(int argc, char **argv) +static int cmd_mkfs(int argc, char **argv) { int result = 0; char *type = "elm"; /* use the default file system type as 'fatfs' */ @@ -474,10 +475,10 @@ int cmd_mkfs(int argc, char **argv) return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_mkfs, __cmd_mkfs, format disk with file system); +MSH_CMD_EXPORT_ALIAS(cmd_mkfs, mkfs, format disk with file system); extern struct dfs_filesystem filesystem_table[]; -int cmd_mount(int argc, char *argv[]) +static int cmd_mount(int argc, char **argv) { if (argc == 1) { @@ -522,10 +523,10 @@ int cmd_mount(int argc, char *argv[]) return -1; } } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_mount, __cmd_mount, mount ); +MSH_CMD_EXPORT_ALIAS(cmd_mount, mount, mount ); /* unmount the filesystem from the specified mountpoint */ -int cmd_umount(int argc, char *argv[]) +static int cmd_umount(int argc, char **argv) { char *path = argv[1]; @@ -547,10 +548,10 @@ int cmd_umount(int argc, char *argv[]) return 0; } } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_umount, __cmd_umount, Unmount device from file system); +MSH_CMD_EXPORT_ALIAS(cmd_umount, umount, Unmount device from file system); extern int df(const char *path); -int cmd_df(int argc, char **argv) +static int cmd_df(int argc, char **argv) { if (argc != 2) { @@ -570,9 +571,9 @@ int cmd_df(int argc, char **argv) return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_df, __cmd_df, disk free); +MSH_CMD_EXPORT_ALIAS(cmd_df, df, disk free); -int cmd_echo(int argc, char **argv) +static int cmd_echo(int argc, char **argv) { if (argc == 2) { @@ -600,7 +601,106 @@ int cmd_echo(int argc, char **argv) return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_echo, __cmd_echo, echo string to file); +MSH_CMD_EXPORT_ALIAS(cmd_echo, echo, echo string to file); + +static int cmd_tail(int argc, char **argv) +{ + int fd; + char c = RT_NULL; + char *file_name = RT_NULL; + rt_uint32_t total_lines = 0; + rt_uint32_t target_line = 0; + rt_uint32_t current_line = 0; + rt_uint32_t required_lines = 0; + rt_uint32_t after_xxx_line = 0; + + if(argc < 2) + { + rt_kprintf("Usage: tail [-n numbers] \n"); + return -1; + } + else if(argc == 2) + { + required_lines = 10; /* default: 10 lines from tail */ + file_name = argv[1]; + } + else if(rt_strcmp(argv[1], "-n") == 0) + { + if(argv[2][0] != '+') + { + required_lines = atoi(argv[2]); + } + else + { + after_xxx_line = atoi(&argv[2][1]); /* eg: +100, to get the 100 */ + } + file_name = argv[3]; + } + else + { + rt_kprintf("Usage: tail [-n numbers] \n"); + return -1; + } + + fd = open(file_name, O_RDONLY); + if (fd < 0) + { + rt_kprintf("File doesn't exist\n"); + return -1; + } + + while ((read(fd, &c, sizeof(char))) > 0) + { + if (c == '\n') + { + total_lines++; + } + } + + rt_kprintf("\nTotal Number of lines:%d\n", total_lines); + + if(after_xxx_line != 0) + { + if(total_lines > after_xxx_line) + { + required_lines = total_lines - after_xxx_line; + } + else + { + rt_kprintf("\nError:Required lines are more than total number of lines\n"); + close(fd); + return -1; + } + } + + if (required_lines > total_lines) + { + rt_kprintf("\nError:Required lines are more than total number of lines\n"); + close(fd); + return -1; + } + rt_kprintf("Required Number of lines:%d\n", required_lines); + + target_line = total_lines - required_lines; + lseek(fd, 0, SEEK_SET); /* back to head */ + + while ((read(fd, &c, sizeof(char))) > 0) + { + if (c == '\n') + { + current_line++; + } + if (current_line > target_line) + { + rt_kprintf("%c", c); + } + } + rt_kprintf("\n"); + + close(fd); + return 0; +} +MSH_CMD_EXPORT_ALIAS(cmd_tail, tail, print the last N-lines data of the given file); #endif /* defined(FINSH_USING_MSH) && defined(RT_USING_DFS) */ From d65ecb91f154cc3cc71df2a63cb36392e1e66bc1 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Wed, 9 Jun 2021 16:54:48 +0800 Subject: [PATCH 144/255] [tools] update eclipse project after dist. --- tools/mkdist.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/mkdist.py b/tools/mkdist.py index a29db7b080..e2c2b8da50 100644 --- a/tools/mkdist.py +++ b/tools/mkdist.py @@ -176,7 +176,8 @@ def bs_update_ide_project(bsp_root, rtt_root, rttide = None): 'iar':('iar', 'iar'), 'vs':('msvc', 'cl'), 'vs2012':('msvc', 'cl'), - 'cdk':('gcc', 'gcc')} + 'cdk':('gcc', 'gcc'), + 'eclipse':('eclipse', 'gcc')} else: item = 'eclipse --project-name=' + rttide['project_name'] tgt_dict = {item:('gcc', 'gcc')} From 7b5fd81d06ad928c1d5b94edbb1a868c0d8f876d Mon Sep 17 00:00:00 2001 From: iysheng Date: Wed, 9 Jun 2021 16:24:20 +0800 Subject: [PATCH 145/255] [bsp][gd32450z-eval] Update firmware library and delete usb relate library codes --- .../CMSIS/GD/GD32F4xx/Include/gd32f4xx.h | 277 ++- .../GD/GD32F4xx/Source/system_gd32f4xx.c | 157 +- .../Include/gd32f4xx_adc.h | 438 ++--- .../Include/gd32f4xx_can.h | 297 ++-- .../Include/gd32f4xx_crc.h | 45 +- .../Include/gd32f4xx_ctc.h | 110 +- .../Include/gd32f4xx_dac.h | 268 +-- .../Include/gd32f4xx_dbg.h | 92 +- .../Include/gd32f4xx_dci.h | 144 +- .../Include/gd32f4xx_dma.h | 144 +- .../Include/gd32f4xx_enet.h | 472 ++--- .../Include/gd32f4xx_exmc.h | 996 +++++------ .../Include/gd32f4xx_exti.h | 59 +- .../Include/gd32f4xx_fmc.h | 154 +- .../Include/gd32f4xx_fwdgt.h | 39 +- .../Include/gd32f4xx_gpio.h | 595 +++---- .../Include/gd32f4xx_i2c.h | 307 ++-- .../Include/gd32f4xx_ipa.h | 170 +- .../Include/gd32f4xx_iref.h | 41 +- .../Include/gd32f4xx_misc.h | 33 +- .../Include/gd32f4xx_pmu.h | 50 +- .../Include/gd32f4xx_rcu.h | 125 +- .../Include/gd32f4xx_rtc.h | 67 +- .../Include/gd32f4xx_sdio.h | 69 +- .../Include/gd32f4xx_spi.h | 248 +-- .../Include/gd32f4xx_syscfg.h | 61 +- .../Include/gd32f4xx_timer.h | 388 +++-- .../Include/gd32f4xx_tli.h | 276 +-- .../Include/gd32f4xx_trng.h | 56 +- .../Include/gd32f4xx_usart.h | 214 ++- .../Include/gd32f4xx_wwdgt.h | 33 +- .../Source/gd32f4xx_adc.c | 1520 +++++++++-------- .../Source/gd32f4xx_can.c | 648 ++++--- .../Source/gd32f4xx_crc.c | 63 +- .../Source/gd32f4xx_ctc.c | 259 +-- .../Source/gd32f4xx_dac.c | 435 ++--- .../Source/gd32f4xx_dbg.c | 112 +- .../Source/gd32f4xx_dci.c | 202 +-- .../Source/gd32f4xx_dma.c | 1097 ++++++------ .../Source/gd32f4xx_enet.c | 1156 +++++++------ .../Source/gd32f4xx_exmc.c | 1143 +++++++------ .../Source/gd32f4xx_exti.c | 196 ++- .../Source/gd32f4xx_fmc.c | 562 +++--- .../Source/gd32f4xx_fwdgt.c | 85 +- .../Source/gd32f4xx_gpio.c | 218 ++- .../Source/gd32f4xx_i2c.c | 733 ++++---- .../Source/gd32f4xx_ipa.c | 508 ++++-- .../Source/gd32f4xx_iref.c | 35 +- .../Source/gd32f4xx_misc.c | 46 +- .../Source/gd32f4xx_pmu.c | 127 +- .../Source/gd32f4xx_rcu.c | 264 +-- .../Source/gd32f4xx_rtc.c | 326 ++-- .../Source/gd32f4xx_sdio.c | 128 +- .../Source/gd32f4xx_spi.c | 703 ++++---- .../Source/gd32f4xx_syscfg.c | 50 +- .../Source/gd32f4xx_timer.c | 991 ++++++----- .../Source/gd32f4xx_tli.c | 637 ++++--- .../Source/gd32f4xx_trng.c | 91 +- .../Source/gd32f4xx_usart.c | 361 ++-- .../Source/gd32f4xx_wwdgt.c | 76 +- .../GD32F4xx_usb_driver/Include/usb_core.h | 287 ---- .../GD32F4xx_usb_driver/Include/usb_defines.h | 100 -- .../GD32F4xx_usb_driver/Include/usb_regs.h | 676 -------- .../GD32F4xx_usb_driver/Include/usb_std.h | 188 -- .../GD32F4xx_usb_driver/Include/usbd_core.h | 54 - .../GD32F4xx_usb_driver/Include/usbd_int.h | 31 - .../GD32F4xx_usb_driver/Include/usbd_std.h | 70 - .../GD32F4xx_usb_driver/Include/usbh_core.h | 283 --- .../GD32F4xx_usb_driver/Include/usbh_ctrl.h | 45 - .../GD32F4xx_usb_driver/Include/usbh_hcs.h | 46 - .../GD32F4xx_usb_driver/Include/usbh_int.h | 30 - .../GD32F4xx_usb_driver/Include/usbh_std.h | 74 - .../GD32F4xx_usb_driver/Source/usb_core.c | 1132 ------------ .../GD32F4xx_usb_driver/Source/usbd_core.c | 520 ------ .../GD32F4xx_usb_driver/Source/usbd_int.c | 758 -------- .../GD32F4xx_usb_driver/Source/usbd_std.c | 699 -------- .../GD32F4xx_usb_driver/Source/usbh_core.c | 710 -------- .../GD32F4xx_usb_driver/Source/usbh_ctrl.c | 620 ------- .../GD32F4xx_usb_driver/Source/usbh_hcs.c | 162 -- .../GD32F4xx_usb_driver/Source/usbh_int.c | 591 ------- .../GD32F4xx_usb_driver/Source/usbh_std.c | 808 --------- 81 files changed, 11216 insertions(+), 15865 deletions(-) delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usb_core.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usb_defines.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usb_regs.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usb_std.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_core.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_int.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_std.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_core.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_ctrl.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_hcs.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_int.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_std.h delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usb_core.c delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_core.c delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_int.c delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_std.c delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_core.c delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_ctrl.c delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_hcs.c delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_int.c delete mode 100644 bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_std.c diff --git a/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h b/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h index 722e943b88..6e704f8ed1 100644 --- a/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h +++ b/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h @@ -1,27 +1,55 @@ /*! - \file gd32f4xx.h - \brief general definitions for GD32F4xx + \file gd32f4xx.h + \brief general definitions for GD32F4xx + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware update for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_H #define GD32F4XX_H -#ifdef cplusplus +#ifdef __cplusplus extern "C" { #endif /* define GD32F4xx */ -#if !defined (GD32F4xx) - #define GD32F4xx +#if !defined (GD32F450) && !defined (GD32F405) && !defined (GD32F407) + /* #define GD32F450 */ + /* #define GD32F405 */ + /* #define GD32F407 */ #endif /* define GD32F4xx */ -#if !defined (GD32F4xx) - #error "Please select the target GD32F4xx device used in your application (in gd32f4xx.h file)" + +#if !defined (GD32F450) && !defined (GD32F405) && !defined (GD32F407) + #error "Please select the target GD32F4xx device in gd32f4xx.h file" #endif /* undefine GD32F4xx tip */ /* define value of high speed crystal oscillator (HXTAL) in Hz */ @@ -31,7 +59,7 @@ /* define startup timeout value of high speed crystal oscillator (HXTAL) */ #if !defined (HXTAL_STARTUP_TIMEOUT) -#define HXTAL_STARTUP_TIMEOUT ((uint16_t)0x0800) +#define HXTAL_STARTUP_TIMEOUT ((uint16_t)0xFFFF) #endif /* high speed crystal oscillator startup timeout */ /* define value of internal 16MHz RC oscillator (IRC16M) in Hz */ @@ -67,29 +95,29 @@ |(__GD32F4xx_STDPERIPH_VERSION_SUB2 << 8)\ |(__GD32F4xx_STDPERIPH_VERSION_RC)) -/* configuration of the Cortex-M4 processor and core peripherals */ -#define __CM4_REV 0x0001 /*!< Core revision r0p1 */ -#define __MPU_PRESENT 1 /*!< GD32F4xx do not provide MPU */ +/* configuration of the cortex-M4 processor and core peripherals */ +#define __CM4_REV 0x0001 /*!< core revision r0p1 */ +#define __MPU_PRESENT 1 /*!< GD32F4xx provide MPU */ #define __NVIC_PRIO_BITS 4 /*!< GD32F4xx uses 4 bits for the priority levels */ -#define __VENDOR_SYSTICKCONFIG 0 /*!< set to 1 if different sysTick config is used */ +#define __Vendor_SysTickConfig 0 /*!< set to 1 if different sysTick config is used */ #define __FPU_PRESENT 1 /*!< FPU present */ /* define interrupt number */ typedef enum IRQn { - /* Cortex-M4 processor exceptions numbers */ + /* cortex-M4 processor exceptions numbers */ NonMaskableInt_IRQn = -14, /*!< 2 non maskable interrupt */ - MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 memory management interrupt */ - BusFault_IRQn = -11, /*!< 5 Cortex-M4 bus fault interrupt */ - UsageFault_IRQn = -10, /*!< 6 Cortex-M4 usage fault interrupt */ - SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV call interrupt */ - DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 debug monitor interrupt */ - PendSV_IRQn = -2, /*!< 14 Cortex-M4 pend SV interrupt */ - SysTick_IRQn = -1, /*!< 15 Cortex-M4 system tick interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 cortex-M4 memory management interrupt */ + BusFault_IRQn = -11, /*!< 5 cortex-M4 bus fault interrupt */ + UsageFault_IRQn = -10, /*!< 6 cortex-M4 usage fault interrupt */ + SVCall_IRQn = -5, /*!< 11 cortex-M4 SV call interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 cortex-M4 debug monitor interrupt */ + PendSV_IRQn = -2, /*!< 14 cortex-M4 pend SV interrupt */ + SysTick_IRQn = -1, /*!< 15 cortex-M4 system tick interrupt */ /* interruput numbers */ - WWDGT_IRQn = 0, /*!< window watchDog timer interrupt */ + WWDGT_IRQn = 0, /*!< window watchdog timer interrupt */ LVD_IRQn = 1, /*!< LVD through EXTI line detect interrupt */ - TAMPER_STAMP_IRQn = 2, /*!< Tamper and TimeStamp through EXTI Line detect */ - RTC_WKUP_IRQn = 3, /*!< RTC Wakeup through EXTI line interrupt */ + TAMPER_STAMP_IRQn = 2, /*!< tamper and timestamp through EXTI line detect */ + RTC_WKUP_IRQn = 3, /*!< RTC wakeup through EXTI line interrupt */ FMC_IRQn = 4, /*!< FMC interrupt */ RCU_CTC_IRQn = 5, /*!< RCU and CTC interrupt */ EXTI0_IRQn = 6, /*!< EXTI line 0 interrupts */ @@ -97,23 +125,23 @@ typedef enum IRQn EXTI2_IRQn = 8, /*!< EXTI line 2 interrupts */ EXTI3_IRQn = 9, /*!< EXTI line 3 interrupts */ EXTI4_IRQn = 10, /*!< EXTI line 4 interrupts */ - DMA0_Channel0_IRQn = 11, /*!< DMA0 Channel0 Interrupt */ - DMA0_Channel1_IRQn = 12, /*!< DMA0 Channel1 Interrupt */ - DMA0_Channel2_IRQn = 13, /*!< DMA0 Channel2 Interrupt */ - DMA0_Channel3_IRQn = 14, /*!< DMA0 Channel3 Interrupt */ - DMA0_Channel4_IRQn = 15, /*!< DMA0 Channel4 Interrupt */ - DMA0_Channel5_IRQn = 16, /*!< DMA0 Channel5 Interrupt */ - DMA0_Channel6_IRQn = 17, /*!< DMA0 Channel6 Interrupt */ + DMA0_Channel0_IRQn = 11, /*!< DMA0 channel0 Interrupt */ + DMA0_Channel1_IRQn = 12, /*!< DMA0 channel1 Interrupt */ + DMA0_Channel2_IRQn = 13, /*!< DMA0 channel2 interrupt */ + DMA0_Channel3_IRQn = 14, /*!< DMA0 channel3 interrupt */ + DMA0_Channel4_IRQn = 15, /*!< DMA0 channel4 interrupt */ + DMA0_Channel5_IRQn = 16, /*!< DMA0 channel5 interrupt */ + DMA0_Channel6_IRQn = 17, /*!< DMA0 channel6 interrupt */ ADC_IRQn = 18, /*!< ADC interrupt */ - CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ - CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ - CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupts */ - CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupts */ + CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupt */ + CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupt */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupt */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupt */ EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ - TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 Break and TIMER8 interrupts */ - TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 Update and TIMER9 interrupts */ - TIMER0_TRG_CMT_TIMER10_IRQn = 26, /*!< TIMER0 Trigger and Commutation and TIMER10 interrupts */ - TIMER0_CC_IRQn = 27, /*!< TIMER0 Capture Compare interrupts */ + TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 break and TIMER8 interrupts */ + TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 update and TIMER9 interrupts */ + TIMER0_TRG_CMT_TIMER10_IRQn = 26, /*!< TIMER0 trigger and commutation and TIMER10 interrupts */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupt */ TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ TIMER3_IRQn = 30, /*!< TIMER3 interrupts */ @@ -127,54 +155,127 @@ typedef enum IRQn USART1_IRQn = 38, /*!< USART1 interrupt */ USART2_IRQn = 39, /*!< USART2 interrupt */ EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ - RTC_Alarm_IRQn = 41, /*!< RTC Alarm interrupt */ - USBFS_WKUP_IRQn = 42, /*!< USBFS Wakeup interrupt */ - TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 Break and TIMER11 interrupts */ - TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 Update and TIMER12 interrupts */ - TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 Trigger and Commutation and TIMER13 interrupts */ - TIMER7_CC_IRQn = 46, /*!< TIMER7 Capture Compare interrupts */ - DMA0_Channel7_IRQn = 47, /*!< DMA0 Channel7 Interrupt */ - EXMC_IRQn = 48, /*!< EXMC Interrupt */ - SDIO_IRQn = 49, /*!< SDIO Interrupt */ - TIMER4_IRQn = 50, /*!< TIMER4 Interrupt */ - SPI2_IRQn = 51, /*!< SPI2 Interrupt */ - UART3_IRQn = 52, /*!< UART3 Interrupt */ - UART4_IRQn = 53, /*!< UART4 Interrupt */ - TIMER5_DAC_IRQn = 54, /*!< TIMER5 and DAC0 DAC1 Underrun error Interrupt */ - TIMER6_IRQn = 55, /*!< TIMER6 Interrupt */ - DMA1_Channel0_IRQn = 56, /*!< DMA1 Channel0 Interrupt */ - DMA1_Channel1_IRQn = 57, /*!< DMA1 Channel1 Interrupt */ - DMA1_Channel2_IRQn = 58, /*!< DMA1 Channel2 Interrupt */ - DMA1_Channel3_IRQn = 59, /*!< DMA1 Channel3 Interrupt */ - DMA1_Channel4_IRQn = 60, /*!< DMA1 Channel4 Interrupt */ - ENET_IRQn = 61, /*!< Ethernet Interrupt */ - ENET_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI Line Interrupt */ - CAN1_TX_IRQn = 63, /*!< CAN1 TX Interrupt */ - CAN1_RX0_IRQn = 64, /*!< CAN1 RX0 Interrupt */ - CAN1_RX1_IRQn = 65, /*!< CAN1 RX1 Interrupt */ - CAN1_EWMC_IRQn = 66, /*!< CAN1 EWMC Interrupt */ - USBFS_IRQn = 67, /*!< USBFS Interrupt */ - DMA1_Channel5_IRQn = 68, /*!< DMA1 Channel5 Interrupt */ - DMA1_Channel6_IRQn = 69, /*!< DMA1 Channel6 Interrupt */ - DMA1_Channel7_IRQn = 70, /*!< DMA1 Channel7 Interrupt */ - USART5_IRQn = 71, /*!< USART5 Interrupt */ - I2C2_EV_IRQn = 72, /*!< I2C2 Event Interrupt */ - I2C2_ER_IRQn = 73, /*!< I2C2 Error Interrupt */ - USBHS_EP1_Out_IRQn = 74, /*!< USBHS Endpoint 1 Out Interrupt */ - USBHS_EP1_In_IRQn = 75, /*!< USBHS Endpoint 1 in Interrupt */ - USBHS_WKUP_IRQn = 76, /*!< USBHS Wakeup through EXTI Line Interrupt */ - USBHS_IRQn = 77, /*!< USBHS Interrupt */ - DCI_IRQn = 78, /*!< DCI Interrupt */ - TRNG_IRQn = 80, /*!< TRNG Interrupt */ - FPU_IRQn = 81, /*!< FPU Interrupt */ - UART6_IRQn = 82, /*!< UART6 Interrupt */ - UART7_IRQn = 83, /*!< UART7 Interrupt */ - SPI3_IRQn = 84, /*!< SPI3 Interrupt */ - SPI4_IRQn = 85, /*!< SPI4 Interrupt */ - SPI5_IRQn = 86, /*!< SPI5 Interrupt */ - TLI_IRQn = 88, /*!< TLI Interrupt */ - TLI_ER_IRQn = 89, /*!< TLI Error Interrupt */ - IPA_IRQn = 90, /*!< IPA Interrupt */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm interrupt */ + USBFS_WKUP_IRQn = 42, /*!< USBFS wakeup interrupt */ + TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 break and TIMER11 interrupts */ + TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 update and TIMER12 interrupts */ + TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 trigger and commutation and TIMER13 interrupts */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupt */ + DMA0_Channel7_IRQn = 47, /*!< DMA0 channel7 interrupt */ + +#if defined (GD32F450) + EXMC_IRQn = 48, /*!< EXMC interrupt */ + SDIO_IRQn = 49, /*!< SDIO interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 interrupt */ + SPI2_IRQn = 51, /*!< SPI2 interrupt */ + UART3_IRQn = 52, /*!< UART3 interrupt */ + UART4_IRQn = 53, /*!< UART4 interrupt */ + TIMER5_DAC_IRQn = 54, /*!< TIMER5 and DAC0 DAC1 underrun error interrupts */ + TIMER6_IRQn = 55, /*!< TIMER6 interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 interrupt */ + DMA1_Channel3_IRQn = 59, /*!< DMA1 channel3 interrupt */ + DMA1_Channel4_IRQn = 60, /*!< DMA1 channel4 interrupt */ + ENET_IRQn = 61, /*!< ENET interrupt */ + ENET_WKUP_IRQn = 62, /*!< ENET wakeup through EXTI line interrupt */ + CAN1_TX_IRQn = 63, /*!< CAN1 TX interrupt */ + CAN1_RX0_IRQn = 64, /*!< CAN1 RX0 interrupt */ + CAN1_RX1_IRQn = 65, /*!< CAN1 RX1 interrupt */ + CAN1_EWMC_IRQn = 66, /*!< CAN1 EWMC interrupt */ + USBFS_IRQn = 67, /*!< USBFS interrupt */ + DMA1_Channel5_IRQn = 68, /*!< DMA1 channel5 interrupt */ + DMA1_Channel6_IRQn = 69, /*!< DMA1 channel6 interrupt */ + DMA1_Channel7_IRQn = 70, /*!< DMA1 channel7 interrupt */ + USART5_IRQn = 71, /*!< USART5 interrupt */ + I2C2_EV_IRQn = 72, /*!< I2C2 event interrupt */ + I2C2_ER_IRQn = 73, /*!< I2C2 error interrupt */ + USBHS_EP1_Out_IRQn = 74, /*!< USBHS endpoint 1 out interrupt */ + USBHS_EP1_In_IRQn = 75, /*!< USBHS endpoint 1 in interrupt */ + USBHS_WKUP_IRQn = 76, /*!< USBHS wakeup through EXTI line interrupt */ + USBHS_IRQn = 77, /*!< USBHS interrupt */ + DCI_IRQn = 78, /*!< DCI interrupt */ + TRNG_IRQn = 80, /*!< TRNG interrupt */ + FPU_IRQn = 81, /*!< FPU interrupt */ + UART6_IRQn = 82, /*!< UART6 interrupt */ + UART7_IRQn = 83, /*!< UART7 interrupt */ + SPI3_IRQn = 84, /*!< SPI3 interrupt */ + SPI4_IRQn = 85, /*!< SPI4 interrupt */ + SPI5_IRQn = 86, /*!< SPI5 interrupt */ + TLI_IRQn = 88, /*!< TLI interrupt */ + TLI_ER_IRQn = 89, /*!< TLI error interrupt */ + IPA_IRQn = 90, /*!< IPA interrupt */ +#endif /* GD32F450 */ + +#if defined (GD32F405) + SDIO_IRQn = 49, /*!< SDIO interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 interrupt */ + SPI2_IRQn = 51, /*!< SPI2 interrupt */ + UART3_IRQn = 52, /*!< UART3 interrupt */ + UART4_IRQn = 53, /*!< UART4 interrupt */ + TIMER5_DAC_IRQn = 54, /*!< TIMER5 and DAC0 DAC1 underrun error interrupts */ + TIMER6_IRQn = 55, /*!< TIMER6 interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 interrupt */ + DMA1_Channel3_IRQn = 59, /*!< DMA1 channel3 interrupt */ + DMA1_Channel4_IRQn = 60, /*!< DMA1 channel4 interrupt */ + CAN1_TX_IRQn = 63, /*!< CAN1 TX interrupt */ + CAN1_RX0_IRQn = 64, /*!< CAN1 RX0 interrupt */ + CAN1_RX1_IRQn = 65, /*!< CAN1 RX1 interrupt */ + CAN1_EWMC_IRQn = 66, /*!< CAN1 EWMC interrupt */ + USBFS_IRQn = 67, /*!< USBFS interrupt */ + DMA1_Channel5_IRQn = 68, /*!< DMA1 channel5 interrupt */ + DMA1_Channel6_IRQn = 69, /*!< DMA1 channel6 interrupt */ + DMA1_Channel7_IRQn = 70, /*!< DMA1 channel7 interrupt */ + USART5_IRQn = 71, /*!< USART5 interrupt */ + I2C2_EV_IRQn = 72, /*!< I2C2 event interrupt */ + I2C2_ER_IRQn = 73, /*!< I2C2 error interrupt */ + USBHS_EP1_Out_IRQn = 74, /*!< USBHS endpoint 1 Out interrupt */ + USBHS_EP1_In_IRQn = 75, /*!< USBHS endpoint 1 in interrupt */ + USBHS_WKUP_IRQn = 76, /*!< USBHS wakeup through EXTI line interrupt */ + USBHS_IRQn = 77, /*!< USBHS interrupt */ + DCI_IRQn = 78, /*!< DCI interrupt */ + TRNG_IRQn = 80, /*!< TRNG interrupt */ + FPU_IRQn = 81, /*!< FPU interrupt */ +#endif /* GD32F405 */ + +#if defined (GD32F407) + EXMC_IRQn = 48, /*!< EXMC interrupt */ + SDIO_IRQn = 49, /*!< SDIO interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 interrupt */ + SPI2_IRQn = 51, /*!< SPI2 interrupt */ + UART3_IRQn = 52, /*!< UART3 interrupt */ + UART4_IRQn = 53, /*!< UART4 interrupt */ + TIMER5_DAC_IRQn = 54, /*!< TIMER5 and DAC0 DAC1 underrun error interrupts */ + TIMER6_IRQn = 55, /*!< TIMER6 interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 interrupt */ + DMA1_Channel3_IRQn = 59, /*!< DMA1 channel3 interrupt */ + DMA1_Channel4_IRQn = 60, /*!< DMA1 channel4 interrupt */ + ENET_IRQn = 61, /*!< ENET interrupt */ + ENET_WKUP_IRQn = 62, /*!< ENET wakeup through EXTI line interrupt */ + CAN1_TX_IRQn = 63, /*!< CAN1 TX interrupt */ + CAN1_RX0_IRQn = 64, /*!< CAN1 RX0 interrupt */ + CAN1_RX1_IRQn = 65, /*!< CAN1 RX1 interrupt */ + CAN1_EWMC_IRQn = 66, /*!< CAN1 EWMC interrupt */ + USBFS_IRQn = 67, /*!< USBFS interrupt */ + DMA1_Channel5_IRQn = 68, /*!< DMA1 channel5 interrupt */ + DMA1_Channel6_IRQn = 69, /*!< DMA1 channel6 interrupt */ + DMA1_Channel7_IRQn = 70, /*!< DMA1 channel7 interrupt */ + USART5_IRQn = 71, /*!< USART5 interrupt */ + I2C2_EV_IRQn = 72, /*!< I2C2 event interrupt */ + I2C2_ER_IRQn = 73, /*!< I2C2 error interrupt */ + USBHS_EP1_Out_IRQn = 74, /*!< USBHS endpoint 1 out interrupt */ + USBHS_EP1_In_IRQn = 75, /*!< USBHS endpoint 1 in interrupt */ + USBHS_WKUP_IRQn = 76, /*!< USBHS wakeup through EXTI line interrupt */ + USBHS_IRQn = 77, /*!< USBHS interrupt */ + DCI_IRQn = 78, /*!< DCI interrupt */ + TRNG_IRQn = 80, /*!< TRNG interrupt */ + FPU_IRQn = 81, /*!< FPU interrupt */ +#endif /* GD32F407 */ + } IRQn_Type; /* includes */ diff --git a/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c b/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c index 6da45fa40e..058dcadca2 100644 --- a/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c +++ b/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c @@ -56,7 +56,10 @@ #define SEL_IRC16M 0x00U #define SEL_HXTAL 0x01U #define SEL_PLLP 0x02U - +#define RCU_MODIFY {volatile uint32_t i; \ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV2; \ + for(i=0;i<50000;i++);} + /* set the system clock frequency and declare the system clock configuration function */ #ifdef __SYSTEM_CLOCK_IRC16M uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC16M; @@ -109,10 +112,12 @@ void SystemInit (void) #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ #endif - /* Reset the RCC clock configuration to the default reset state ------------*/ + /* Reset the RCU clock configuration to the default reset state ------------*/ /* Set IRC16MEN bit */ RCU_CTL |= RCU_CTL_IRC16MEN; + RCU_MODIFY + /* Reset CFG0 register */ RCU_CFG0 = 0x00000000U; @@ -131,8 +136,6 @@ void SystemInit (void) /* Configure the System clock source, PLL Multiplier and Divider factors, AHB/APBx prescalers and Flash settings ----------------------------------*/ system_clock_config(); - - } /*! \brief configure the system clock @@ -186,13 +189,12 @@ static void system_clock_16m_irc16m(void) do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_IRC16MSTB); - } - while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout)); + }while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout)); /* if fail */ if(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)){ - while(1){ - } + while(1){ + } } /* AHB = SYSCLK */ @@ -230,13 +232,12 @@ static void system_clock_hxtal(void) do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - } - while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } + while(1){ + } } /* AHB = SYSCLK */ @@ -274,13 +275,12 @@ static void system_clock_120m_irc16m(void) do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_IRC16MSTB); - } - while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout)); + }while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout)); /* if fail */ if(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)){ - while(1){ - } + while(1){ + } } RCU_APB1EN |= RCU_APB1EN_PMUEN; @@ -294,7 +294,7 @@ static void system_clock_120m_irc16m(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PLL_M = 16, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ + /* Configure the main PLL, PSC = 16, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ RCU_PLL = (16U | (240U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_IRC16M) | (5U << 24U)); @@ -307,14 +307,12 @@ static void system_clock_120m_irc16m(void) /* Enable the high-drive to extend the clock frequency to 120 Mhz */ PMU_CTL |= PMU_CTL_HDEN; - while(0U == (PMU_CS & PMU_CS_HDRF)) - { + while(0U == (PMU_CS & PMU_CS_HDRF)){ } /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; - while(0U == (PMU_CS & PMU_CS_HDSRF)) - { + while(0U == (PMU_CS & PMU_CS_HDSRF)){ } /* select PLL as system clock */ @@ -345,13 +343,12 @@ static void system_clock_120m_8m_hxtal(void) do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - } - while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } + while(1){ + } } RCU_APB1EN |= RCU_APB1EN_PMUEN; @@ -365,7 +362,7 @@ static void system_clock_120m_8m_hxtal(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PLL_M = 8, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ + /* Configure the main PLL, PSC = 8, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ RCU_PLL = (8U | (240U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_HXTAL) | (5U << 24U)); @@ -378,14 +375,12 @@ static void system_clock_120m_8m_hxtal(void) /* Enable the high-drive to extend the clock frequency to 120 Mhz */ PMU_CTL |= PMU_CTL_HDEN; - while(0U == (PMU_CS & PMU_CS_HDRF)) - { + while(0U == (PMU_CS & PMU_CS_HDRF)){ } /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; - while(0U == (PMU_CS & PMU_CS_HDSRF)) - { + while(0U == (PMU_CS & PMU_CS_HDSRF)){ } /* select PLL as system clock */ @@ -416,13 +411,12 @@ static void system_clock_120m_25m_hxtal(void) do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - } - while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } + while(1){ + } } RCU_APB1EN |= RCU_APB1EN_PMUEN; @@ -436,7 +430,7 @@ static void system_clock_120m_25m_hxtal(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PLL_M = 25, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ + /* Configure the main PLL, PSC = 25, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ RCU_PLL = (25U | (240U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_HXTAL) | (5U << 24U)); @@ -449,14 +443,12 @@ static void system_clock_120m_25m_hxtal(void) /* Enable the high-drive to extend the clock frequency to 120 Mhz */ PMU_CTL |= PMU_CTL_HDEN; - while(0U == (PMU_CS & PMU_CS_HDRF)) - { + while(0U == (PMU_CS & PMU_CS_HDRF)){ } /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; - while(0U == (PMU_CS & PMU_CS_HDSRF)) - { + while(0U == (PMU_CS & PMU_CS_HDSRF)){ } /* select PLL as system clock */ @@ -487,13 +479,12 @@ static void system_clock_168m_irc16m(void) do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_IRC16MSTB); - } - while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout)); + }while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout)); /* if fail */ if(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)){ - while(1){ - } + while(1){ + } } RCU_APB1EN |= RCU_APB1EN_PMUEN; @@ -507,7 +498,7 @@ static void system_clock_168m_irc16m(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PLL_M = 16, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ + /* Configure the main PLL, PSC = 16, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ RCU_PLL = (16U | (336U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_IRC16M) | (7U << 24U)); @@ -520,14 +511,12 @@ static void system_clock_168m_irc16m(void) /* Enable the high-drive to extend the clock frequency to 168 Mhz */ PMU_CTL |= PMU_CTL_HDEN; - while(0U == (PMU_CS & PMU_CS_HDRF)) - { + while(0U == (PMU_CS & PMU_CS_HDRF)){ } /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; - while(0U == (PMU_CS & PMU_CS_HDSRF)) - { + while(0U == (PMU_CS & PMU_CS_HDSRF)){ } /* select PLL as system clock */ @@ -559,8 +548,8 @@ static void system_clock_168m_8m_hxtal(void) /* if fail */ if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } + while(1){ + } } RCU_APB1EN |= RCU_APB1EN_PMUEN; @@ -573,7 +562,7 @@ static void system_clock_168m_8m_hxtal(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PLL_M = 8, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ + /* Configure the main PLL, PSC = 8, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ RCU_PLL = (8U | (336 << 6U) | (((2 >> 1U) -1U) << 16U) | (RCU_PLLSRC_HXTAL) | (7 << 24U)); @@ -586,14 +575,12 @@ static void system_clock_168m_8m_hxtal(void) /* Enable the high-drive to extend the clock frequency to 168 Mhz */ PMU_CTL |= PMU_CTL_HDEN; - while(0U == (PMU_CS & PMU_CS_HDRF)) - { + while(0U == (PMU_CS & PMU_CS_HDRF)){ } /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; - while(0U == (PMU_CS & PMU_CS_HDSRF)) - { + while(0U == (PMU_CS & PMU_CS_HDSRF)){ } /* select PLL as system clock */ @@ -624,13 +611,12 @@ static void system_clock_168m_25m_hxtal(void) do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - } - while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } + while(1){ + } } RCU_APB1EN |= RCU_APB1EN_PMUEN; @@ -644,7 +630,7 @@ static void system_clock_168m_25m_hxtal(void) /* APB1 = AHB */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PLL_M = 25, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ + /* Configure the main PLL, PSC = 25, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ RCU_PLL = (25U | (336U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_HXTAL) | (7U << 24U)); @@ -657,14 +643,12 @@ static void system_clock_168m_25m_hxtal(void) /* Enable the high-drive to extend the clock frequency to 168 Mhz */ PMU_CTL |= PMU_CTL_HDEN; - while(0U == (PMU_CS & PMU_CS_HDRF)) - { + while(0U == (PMU_CS & PMU_CS_HDRF)){ } /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; - while(0U == (PMU_CS & PMU_CS_HDSRF)) - { + while(0U == (PMU_CS & PMU_CS_HDSRF)){ } /* select PLL as system clock */ @@ -695,13 +679,12 @@ static void system_clock_200m_irc16m(void) do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_IRC16MSTB); - } - while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout)); + }while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout)); /* if fail */ if(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)){ - while(1){ - } + while(1){ + } } RCU_APB1EN |= RCU_APB1EN_PMUEN; @@ -715,7 +698,7 @@ static void system_clock_200m_irc16m(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PLL_M = 16, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ + /* Configure the main PLL, PSC = 16, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ RCU_PLL = (16U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_IRC16M) | (9U << 24U)); @@ -728,14 +711,12 @@ static void system_clock_200m_irc16m(void) /* Enable the high-drive to extend the clock frequency to 200 Mhz */ PMU_CTL |= PMU_CTL_HDEN; - while(0U == (PMU_CS & PMU_CS_HDRF)) - { + while(0U == (PMU_CS & PMU_CS_HDRF)){ } /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; - while(0U == (PMU_CS & PMU_CS_HDSRF)) - { + while(0U == (PMU_CS & PMU_CS_HDSRF)){ } /* select PLL as system clock */ @@ -766,13 +747,12 @@ static void system_clock_200m_8m_hxtal(void) do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - } - while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } + while(1){ + } } RCU_APB1EN |= RCU_APB1EN_PMUEN; @@ -786,7 +766,7 @@ static void system_clock_200m_8m_hxtal(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PLL_M = 8, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ + /* Configure the main PLL, PSC = 8, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ RCU_PLL = (8U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_HXTAL) | (9U << 24U)); @@ -799,14 +779,12 @@ static void system_clock_200m_8m_hxtal(void) /* Enable the high-drive to extend the clock frequency to 200 Mhz */ PMU_CTL |= PMU_CTL_HDEN; - while(0U == (PMU_CS & PMU_CS_HDRF)) - { + while(0U == (PMU_CS & PMU_CS_HDRF)){ } /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; - while(0U == (PMU_CS & PMU_CS_HDSRF)) - { + while(0U == (PMU_CS & PMU_CS_HDSRF)){ } /* select PLL as system clock */ @@ -837,13 +815,12 @@ static void system_clock_200m_25m_hxtal(void) do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - } - while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } + while(1){ + } } RCU_APB1EN |= RCU_APB1EN_PMUEN; @@ -857,7 +834,7 @@ static void system_clock_200m_25m_hxtal(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PLL_M = 25, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ + /* Configure the main PLL, PSC = 25, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ RCU_PLL = (25U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_HXTAL) | (9U << 24U)); @@ -870,14 +847,12 @@ static void system_clock_200m_25m_hxtal(void) /* Enable the high-drive to extend the clock frequency to 200 Mhz */ PMU_CTL |= PMU_CTL_HDEN; - while(0U == (PMU_CS & PMU_CS_HDRF)) - { + while(0U == (PMU_CS & PMU_CS_HDRF)){ } /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; - while(0U == (PMU_CS & PMU_CS_HDSRF)) - { + while(0U == (PMU_CS & PMU_CS_HDSRF)){ } /* select PLL as system clock */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h index 694428f07c..4f6020a50a 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_adc.h - \brief definitions for the ADC + \file gd32f4xx_adc.h + \brief definitions for the ADC + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_ADC_H @@ -68,7 +93,7 @@ #define ADC_CTL0_IWDEN BIT(22) /*!< analog watchdog enable on inserted channels */ #define ADC_CTL0_RWDEN BIT(23) /*!< analog watchdog enable on regular channels */ #define ADC_CTL0_DRES BITS(24,25) /*!< ADC data resolution */ -#define ADC_CTL0_ROVFIE BIT(26) /*!< interrupt enable for ROVF */ +#define ADC_CTL0_ROVFIE BIT(26) /*!< interrupt enable for ROVF */ /* ADC_CTL1 */ #define ADC_CTL1_ADCON BIT(0) /*!< ADC converter on */ @@ -152,65 +177,6 @@ #define ADC_SYNCDATA_SYNCDATA1 BITS(16,31) /*!< regular data2 in ADC synchronization mode */ /* constants definitions */ -/* ADC channel group definitions */ -#define ADC_REGULAR_CHANNEL ((uint8_t)0x00U) /*!< adc regular channel group */ -#define ADC_INSERTED_CHANNEL ((uint8_t)0x01U) /*!< adc inserted channel group */ -#define ADC_REGULAR_INSERTED_CHANNEL ((uint8_t)0x02U) /*!< both regular and inserted channel group */ - -/* external trigger mode for regular and inserted channel */ -#define EXTERNAL_TRIGGER_DISABLE ((uint32_t)0x00000000U) /*!< external trigger disable */ -#define EXTERNAL_TRIGGER_RISING ((uint32_t)0x00000001U) /*!< rising edge of external trigger */ -#define EXTERNAL_TRIGGER_FALLING ((uint32_t)0x00000002U) /*!< falling edge of external trigger */ -#define EXTERNAL_TRIGGER_RISING_FALLING ((uint32_t)0x00000003U) /*!< rising and falling edge of external trigger */ - -/* ADC inserted channel definitions */ -#define ADC_INSERTED_CHANNEL_0 ((uint8_t)0x00U) /*!< adc inserted channel 0 */ -#define ADC_INSERTED_CHANNEL_1 ((uint8_t)0x01U) /*!< adc inserted channel 1 */ -#define ADC_INSERTED_CHANNEL_2 ((uint8_t)0x02U) /*!< adc inserted channel 2 */ -#define ADC_INSERTED_CHANNEL_3 ((uint8_t)0x03U) /*!< adc inserted channel 3 */ - -/* ADC special function definitions */ -#define ADC_SCAN_MODE ((uint8_t)0x00U) /*!< scan mode */ -#define ADC_INSERTED_CHANNEL_AUTO ((uint8_t)0x01U) /*!< inserted channel group convert automatically */ -#define ADC_VBAT_CHANNEL_SWITCH ((uint8_t)0x02U) /*!< VBAT channel */ -#define ADC_TEMP_VREF_CHANNEL_SWITCH ((uint8_t)0x03U) /*!< Vref and Vtemp channel */ -#define ADC_CONTINUOUS_MODE ((uint8_t)0x04U) /*!< continuous mode */ - -/* ADC channel definitions */ -#define ADC_CHANNEL_0 ((uint8_t)0x00U) /*!< ADC channel 0 */ -#define ADC_CHANNEL_1 ((uint8_t)0x01U) /*!< ADC channel 1 */ -#define ADC_CHANNEL_2 ((uint8_t)0x02U) /*!< ADC channel 2 */ -#define ADC_CHANNEL_3 ((uint8_t)0x03U) /*!< ADC channel 3 */ -#define ADC_CHANNEL_4 ((uint8_t)0x04U) /*!< ADC channel 4 */ -#define ADC_CHANNEL_5 ((uint8_t)0x05U) /*!< ADC channel 5 */ -#define ADC_CHANNEL_6 ((uint8_t)0x06U) /*!< ADC channel 6 */ -#define ADC_CHANNEL_7 ((uint8_t)0x07U) /*!< ADC channel 7 */ -#define ADC_CHANNEL_8 ((uint8_t)0x08U) /*!< ADC channel 8 */ -#define ADC_CHANNEL_9 ((uint8_t)0x09U) /*!< ADC channel 9 */ -#define ADC_CHANNEL_10 ((uint8_t)0x0AU) /*!< ADC channel 10 */ -#define ADC_CHANNEL_11 ((uint8_t)0x0BU) /*!< ADC channel 11 */ -#define ADC_CHANNEL_12 ((uint8_t)0x0CU) /*!< ADC channel 12 */ -#define ADC_CHANNEL_13 ((uint8_t)0x0DU) /*!< ADC channel 13 */ -#define ADC_CHANNEL_14 ((uint8_t)0x0EU) /*!< ADC channel 14 */ -#define ADC_CHANNEL_15 ((uint8_t)0x0FU) /*!< ADC channel 15 */ -#define ADC_CHANNEL_16 ((uint8_t)0x10U) /*!< ADC channel 16 */ -#define ADC_CHANNEL_17 ((uint8_t)0x11U) /*!< ADC channel 17 */ -#define ADC_CHANNEL_18 ((uint8_t)0x12U) /*!< ADC channel 18 */ - -/* ADC channel sample time */ -#define ADC_SAMPLETIME_3 ((uint8_t)0x00U) /*!< 3 sampling cycles */ -#define ADC_SAMPLETIME_15 ((uint8_t)0x01U) /*!< 15 sampling cycles */ -#define ADC_SAMPLETIME_28 ((uint8_t)0x02U) /*!< 28 sampling cycles */ -#define ADC_SAMPLETIME_56 ((uint8_t)0x03U) /*!< 56 sampling cycles */ -#define ADC_SAMPLETIME_84 ((uint8_t)0x04U) /*!< 84 sampling cycles */ -#define ADC_SAMPLETIME_112 ((uint8_t)0x05U) /*!< 112 sampling cycles */ -#define ADC_SAMPLETIME_144 ((uint8_t)0x06U) /*!< 144 sampling cycles */ -#define ADC_SAMPLETIME_480 ((uint8_t)0x07U) /*!< 480 sampling cycles */ - -/* ADC data alignment */ -#define ADC_DATAALIGN_RIGHT ((uint8_t)0x00U) /*!< LSB alignment */ -#define ADC_DATAALIGN_LEFT ((uint8_t)0x01U) /*!< MSB alignment */ - /* ADC status flag */ #define ADC_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event flag */ #define ADC_FLAG_EOC ADC_STAT_EOC /*!< end of conversion */ @@ -219,18 +185,43 @@ #define ADC_FLAG_STRC ADC_STAT_STRC /*!< regular channel start flag */ #define ADC_FLAG_ROVF ADC_STAT_ROVF /*!< regular data register overflow */ -/* ADC interrupt flag */ -#define ADC_INT_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt */ -#define ADC_INT_EOC ADC_STAT_EOC /*!< end of group conversion interrupt */ -#define ADC_INT_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt */ -#define ADC_INT_ROVF ADC_STAT_ROVF /*!< regular data register overflow */ +/* adc_ctl0 register value */ +#define CTL0_DISNUM(regval) (BITS(13,15) & ((uint32_t)(regval) << 13)) /*!< write value to ADC_CTL0_DISNUM bit field */ -/* ADC resolution definitions */ -#define CTL0_DRES(regval) (BITS(24,25) & ((uint32_t)(regval) << 24)) -#define ADC_RESOLUTION_12B CTL0_DRES(0) /*!< 12-bit ADC resolution */ -#define ADC_RESOLUTION_10B CTL0_DRES(1) /*!< 10-bit ADC resolution */ -#define ADC_RESOLUTION_8B CTL0_DRES(2) /*!< 8-bit ADC resolution */ -#define ADC_RESOLUTION_6B CTL0_DRES(3) /*!< 6-bit ADC resolution */ +/* ADC special function definitions */ +#define ADC_SCAN_MODE ADC_CTL0_SM /*!< scan mode */ +#define ADC_INSERTED_CHANNEL_AUTO ADC_CTL0_ICA /*!< inserted channel group convert automatically */ +#define ADC_CONTINUOUS_MODE ADC_CTL1_CTN /*!< continuous mode */ + +/* temperature sensor channel, internal reference voltage channel, VBAT channel */ +#define ADC_VBAT_CHANNEL_SWITCH ADC_SYNCCTL_VBATEN /*!< VBAT channel */ +#define ADC_TEMP_VREF_CHANNEL_SWITCH ADC_SYNCCTL_TSVREN /*!< Vref and Vtemp channel */ + +/* ADC synchronization mode */ +#define SYNCCTL_SYNCM(regval) (BITS(0,4) & ((uint32_t)(regval))) /*!< write value to ADC_CTL0_SYNCM bit field */ +#define ADC_SYNC_MODE_INDEPENDENT SYNCCTL_SYNCM(0) /*!< ADC synchronization mode disabled.All the ADCs work independently */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL SYNCCTL_SYNCM(1) /*!< ADC0 and ADC1 work in combined regular parallel & inserted parallel mode. ADC2 works independently */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION SYNCCTL_SYNCM(2) /*!< ADC0 and ADC1 work in combined regular parallel & trigger rotation mode. ADC2 works independently */ +#define ADC_DAUL_INSERTED_PARALLEL SYNCCTL_SYNCM(5) /*!< ADC0 and ADC1 work in inserted parallel mode. ADC2 works independently */ +#define ADC_DAUL_REGULAL_PARALLEL SYNCCTL_SYNCM(6) /*!< ADC0 and ADC1 work in regular parallel mode. ADC2 works independently */ +#define ADC_DAUL_REGULAL_FOLLOW_UP SYNCCTL_SYNCM(7) /*!< ADC0 and ADC1 work in follow-up mode. ADC2 works independently */ +#define ADC_DAUL_INSERTED_TRRIGGER_ROTATION SYNCCTL_SYNCM(9) /*!< ADC0 and ADC1 work in trigger rotation mode. ADC2 works independently */ +#define ADC_ALL_REGULAL_PARALLEL_INSERTED_PARALLEL SYNCCTL_SYNCM(17) /*!< all ADCs work in combined regular parallel & inserted parallel mode */ +#define ADC_ALL_REGULAL_PARALLEL_INSERTED_ROTATION SYNCCTL_SYNCM(18) /*!< all ADCs work in combined regular parallel & trigger rotation mode */ +#define ADC_ALL_INSERTED_PARALLEL SYNCCTL_SYNCM(21) /*!< all ADCs work in inserted parallel mode */ +#define ADC_ALL_REGULAL_PARALLEL SYNCCTL_SYNCM(22) /*!< all ADCs work in regular parallel mode */ +#define ADC_ALL_REGULAL_FOLLOW_UP SYNCCTL_SYNCM(23) /*!< all ADCs work in follow-up mode */ +#define ADC_ALL_INSERTED_TRRIGGER_ROTATION SYNCCTL_SYNCM(25) /*!< all ADCs work in trigger rotation mode */ + +/* ADC data alignment */ +#define ADC_DATAALIGN_RIGHT ((uint32_t)0x00000000U) /*!< LSB alignment */ +#define ADC_DATAALIGN_LEFT ADC_CTL1_DAL /*!< MSB alignment */ + +/* external trigger mode for regular and inserted channel */ +#define EXTERNAL_TRIGGER_DISABLE ((uint32_t)0x00000000U) /*!< external trigger disable */ +#define EXTERNAL_TRIGGER_RISING ((uint32_t)0x00000001U) /*!< rising edge of external trigger */ +#define EXTERNAL_TRIGGER_FALLING ((uint32_t)0x00000002U) /*!< falling edge of external trigger */ +#define EXTERNAL_TRIGGER_RISING_FALLING ((uint32_t)0x00000003U) /*!< rising and falling edge of external trigger */ /* ADC external trigger select for regular channel */ #define CTL1_ETSRC(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) @@ -270,32 +261,111 @@ #define ADC_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(14) /*!< timer7 capture compare 3 */ #define ADC_EXTTRIG_INSERTED_EXTI_15 CTL1_ETSIC(15) /*!< external interrupt line 15 */ -/* ADC oversampling mode */ -#define ADC_OVERSAMPLING_ALL_CONVERT 0U /*!< all oversampled conversions for a channel are done consecutively after a trigger */ -#define ADC_OVERSAMPLING_ONE_CONVERT 1U /*!< each oversampled conversion for a channel needs a trigger */ +/* ADC channel sample time */ +#define SAMPTX_SPT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_SAMPTX_SPT bit field */ +#define ADC_SAMPLETIME_3 SAMPTX_SPT(0) /*!< 3 sampling cycles */ +#define ADC_SAMPLETIME_15 SAMPTX_SPT(1) /*!< 15 sampling cycles */ +#define ADC_SAMPLETIME_28 SAMPTX_SPT(2) /*!< 28 sampling cycles */ +#define ADC_SAMPLETIME_56 SAMPTX_SPT(3) /*!< 56 sampling cycles */ +#define ADC_SAMPLETIME_84 SAMPTX_SPT(4) /*!< 84 sampling cycles */ +#define ADC_SAMPLETIME_112 SAMPTX_SPT(5) /*!< 112 sampling cycles */ +#define ADC_SAMPLETIME_144 SAMPTX_SPT(6) /*!< 144 sampling cycles */ +#define ADC_SAMPLETIME_480 SAMPTX_SPT(7) /*!< 480 sampling cycles */ -/* ADC oversampling shift */ -#define OVCTL_OVSS(regval) (BITS(5,8) & ((uint32_t)(regval) << 5)) -#define ADC_OVERSAMPLING_SHIFT_NONE OVCTL_OVSS(0) /*!< no oversampling shift */ -#define ADC_OVERSAMPLING_SHIFT_1B OVCTL_OVSS(1) /*!< 1-bit oversampling shift */ -#define ADC_OVERSAMPLING_SHIFT_2B OVCTL_OVSS(2) /*!< 2-bit oversampling shift */ -#define ADC_OVERSAMPLING_SHIFT_3B OVCTL_OVSS(3) /*!< 3-bit oversampling shift */ -#define ADC_OVERSAMPLING_SHIFT_4B OVCTL_OVSS(4) /*!< 4-bit oversampling shift */ -#define ADC_OVERSAMPLING_SHIFT_5B OVCTL_OVSS(5) /*!< 5-bit oversampling shift */ -#define ADC_OVERSAMPLING_SHIFT_6B OVCTL_OVSS(6) /*!< 6-bit oversampling shift */ -#define ADC_OVERSAMPLING_SHIFT_7B OVCTL_OVSS(7) /*!< 7-bit oversampling shift */ -#define ADC_OVERSAMPLING_SHIFT_8B OVCTL_OVSS(8) /*!< 8-bit oversampling shift */ +/* adc_ioffx register value */ +#define IOFFX_IOFF(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_IOFFX_IOFF bit field */ -/* ADC oversampling ratio */ -#define OVCTL_OVSR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) -#define ADC_OVERSAMPLING_RATIO_MUL2 OVCTL_OVSR(0) /*!< oversampling ratio multiple 2 */ -#define ADC_OVERSAMPLING_RATIO_MUL4 OVCTL_OVSR(1) /*!< oversampling ratio multiple 4 */ -#define ADC_OVERSAMPLING_RATIO_MUL8 OVCTL_OVSR(2) /*!< oversampling ratio multiple 8 */ -#define ADC_OVERSAMPLING_RATIO_MUL16 OVCTL_OVSR(3) /*!< oversampling ratio multiple 16 */ -#define ADC_OVERSAMPLING_RATIO_MUL32 OVCTL_OVSR(4) /*!< oversampling ratio multiple 32 */ -#define ADC_OVERSAMPLING_RATIO_MUL64 OVCTL_OVSR(5) /*!< oversampling ratio multiple 64 */ -#define ADC_OVERSAMPLING_RATIO_MUL128 OVCTL_OVSR(6) /*!< oversampling ratio multiple 128 */ -#define ADC_OVERSAMPLING_RATIO_MUL256 OVCTL_OVSR(7) /*!< oversampling ratio multiple 256 */ +/* adc_wdht register value */ +#define WDHT_WDHT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDHT_WDHT bit field */ + +/* adc_wdlt register value */ +#define WDLT_WDLT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDLT_WDLT bit field */ + +/* adc_rsqx register value */ +#define RSQ0_RL(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_RSQ0_RL bit field */ + +/* adc_isq register value */ +#define ISQ_IL(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_ISQ_IL bit field */ + +/* adc_ovsampctl register value */ +/* ADC resolution */ +#define CTL0_DRES(regval) (BITS(24,25) & ((uint32_t)(regval) << 24)) /*!< write value to ADC_CTL0_DRES bit field */ +#define ADC_RESOLUTION_12B CTL0_DRES(0) /*!< 12-bit ADC resolution */ +#define ADC_RESOLUTION_10B CTL0_DRES(1) /*!< 10-bit ADC resolution */ +#define ADC_RESOLUTION_8B CTL0_DRES(2) /*!< 8-bit ADC resolution */ +#define ADC_RESOLUTION_6B CTL0_DRES(3) /*!< 6-bit ADC resolution */ + +/* oversampling shift */ +#define OVSAMPCTL_OVSS(regval) (BITS(5,8) & ((uint32_t)(regval) << 5)) /*!< write value to ADC_OVSAMPCTL_OVSS bit field */ +#define ADC_OVERSAMPLING_SHIFT_NONE OVSAMPCTL_OVSS(0) /*!< no oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_1B OVSAMPCTL_OVSS(1) /*!< 1-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_2B OVSAMPCTL_OVSS(2) /*!< 2-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_3B OVSAMPCTL_OVSS(3) /*!< 3-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_4B OVSAMPCTL_OVSS(4) /*!< 4-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_5B OVSAMPCTL_OVSS(5) /*!< 5-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_6B OVSAMPCTL_OVSS(6) /*!< 6-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_7B OVSAMPCTL_OVSS(7) /*!< 7-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_8B OVSAMPCTL_OVSS(8) /*!< 8-bit oversampling shift */ + +/* oversampling ratio */ +#define OVSAMPCTL_OVSR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ADC_OVSAMPCTL_OVSR bit field */ +#define ADC_OVERSAMPLING_RATIO_MUL2 OVSAMPCTL_OVSR(0) /*!< oversampling ratio multiple 2 */ +#define ADC_OVERSAMPLING_RATIO_MUL4 OVSAMPCTL_OVSR(1) /*!< oversampling ratio multiple 4 */ +#define ADC_OVERSAMPLING_RATIO_MUL8 OVSAMPCTL_OVSR(2) /*!< oversampling ratio multiple 8 */ +#define ADC_OVERSAMPLING_RATIO_MUL16 OVSAMPCTL_OVSR(3) /*!< oversampling ratio multiple 16 */ +#define ADC_OVERSAMPLING_RATIO_MUL32 OVSAMPCTL_OVSR(4) /*!< oversampling ratio multiple 32 */ +#define ADC_OVERSAMPLING_RATIO_MUL64 OVSAMPCTL_OVSR(5) /*!< oversampling ratio multiple 64 */ +#define ADC_OVERSAMPLING_RATIO_MUL128 OVSAMPCTL_OVSR(6) /*!< oversampling ratio multiple 128 */ +#define ADC_OVERSAMPLING_RATIO_MUL256 OVSAMPCTL_OVSR(7) /*!< oversampling ratio multiple 256 */ + +/* triggered Oversampling */ +#define ADC_OVERSAMPLING_ALL_CONVERT ((uint32_t)0x00000000U) /*!< all oversampled conversions for a channel are done consecutively after a trigger */ +#define ADC_OVERSAMPLING_ONE_CONVERT ADC_OVSAMPCTL_TOVS /*!< each oversampled conversion for a channel needs a trigger */ + +/* ADC channel group definitions */ +#define ADC_REGULAR_CHANNEL ((uint8_t)0x01U) /*!< adc regular channel group */ +#define ADC_INSERTED_CHANNEL ((uint8_t)0x02U) /*!< adc inserted channel group */ +#define ADC_REGULAR_INSERTED_CHANNEL ((uint8_t)0x03U) /*!< both regular and inserted channel group */ +#define ADC_CHANNEL_DISCON_DISABLE ((uint8_t)0x04U) /*!< disable discontinuous mode of regular & inserted channel */ + +/* ADC inserted channel definitions */ +#define ADC_INSERTED_CHANNEL_0 ((uint8_t)0x00U) /*!< adc inserted channel 0 */ +#define ADC_INSERTED_CHANNEL_1 ((uint8_t)0x01U) /*!< adc inserted channel 1 */ +#define ADC_INSERTED_CHANNEL_2 ((uint8_t)0x02U) /*!< adc inserted channel 2 */ +#define ADC_INSERTED_CHANNEL_3 ((uint8_t)0x03U) /*!< adc inserted channel 3 */ + +/* ADC channel definitions */ +#define ADC_CHANNEL_0 ((uint8_t)0x00U) /*!< ADC channel 0 */ +#define ADC_CHANNEL_1 ((uint8_t)0x01U) /*!< ADC channel 1 */ +#define ADC_CHANNEL_2 ((uint8_t)0x02U) /*!< ADC channel 2 */ +#define ADC_CHANNEL_3 ((uint8_t)0x03U) /*!< ADC channel 3 */ +#define ADC_CHANNEL_4 ((uint8_t)0x04U) /*!< ADC channel 4 */ +#define ADC_CHANNEL_5 ((uint8_t)0x05U) /*!< ADC channel 5 */ +#define ADC_CHANNEL_6 ((uint8_t)0x06U) /*!< ADC channel 6 */ +#define ADC_CHANNEL_7 ((uint8_t)0x07U) /*!< ADC channel 7 */ +#define ADC_CHANNEL_8 ((uint8_t)0x08U) /*!< ADC channel 8 */ +#define ADC_CHANNEL_9 ((uint8_t)0x09U) /*!< ADC channel 9 */ +#define ADC_CHANNEL_10 ((uint8_t)0x0AU) /*!< ADC channel 10 */ +#define ADC_CHANNEL_11 ((uint8_t)0x0BU) /*!< ADC channel 11 */ +#define ADC_CHANNEL_12 ((uint8_t)0x0CU) /*!< ADC channel 12 */ +#define ADC_CHANNEL_13 ((uint8_t)0x0DU) /*!< ADC channel 13 */ +#define ADC_CHANNEL_14 ((uint8_t)0x0EU) /*!< ADC channel 14 */ +#define ADC_CHANNEL_15 ((uint8_t)0x0FU) /*!< ADC channel 15 */ +#define ADC_CHANNEL_16 ((uint8_t)0x10U) /*!< ADC channel 16 */ +#define ADC_CHANNEL_17 ((uint8_t)0x11U) /*!< ADC channel 17 */ +#define ADC_CHANNEL_18 ((uint8_t)0x12U) /*!< ADC channel 18 */ + +/* ADC interrupt flag */ +#define ADC_INT_WDE ADC_CTL0_WDEIE /*!< analog watchdog event interrupt */ +#define ADC_INT_EOC ADC_CTL0_EOCIE /*!< end of group conversion interrupt */ +#define ADC_INT_EOIC ADC_CTL0_EOICIE /*!< end of inserted group conversion interrupt */ +#define ADC_INT_ROVF ADC_CTL0_ROVFIE /*!< regular data register overflow */ + +/* ADC interrupt flag */ +#define ADC_INT_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt */ +#define ADC_INT_FLAG_EOC ADC_STAT_EOC /*!< end of group conversion interrupt */ +#define ADC_INT_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt */ +#define ADC_INT_FLAG_ROVF ADC_STAT_ROVF /*!< regular data register overflow */ /* configure the ADC clock for all the ADCs */ #define SYNCCTL_ADCCK(regval) (BITS(16,18) & ((uint32_t)(regval) << 16)) @@ -308,21 +378,6 @@ #define ADC_ADCCK_HCLK_DIV10 SYNCCTL_ADCCK(6) /*!< HCLK div10 */ #define ADC_ADCCK_HCLK_DIV20 SYNCCTL_ADCCK(7) /*!< HCLK div20 */ -/* ADC synchronization mode */ -#define ADC_SYNC_MODE_INDEPENDENT ((uint32_t)0x00000000U) /*!< ADC synchronization mode disabled.All the ADCs work independently */ -#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL ((uint32_t)0x00000001U) /*!< ADC0 and ADC1 work in combined regular parallel & inserted parallel mode. ADC2 works independently */ -#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION ((uint32_t)0x00000002U) /*!< ADC0 and ADC1 work in combined regular parallel & trigger rotation mode. ADC2 works independently */ -#define ADC_DAUL_INSERTED_PARALLEL ((uint32_t)0x00000005U) /*!< ADC0 and ADC1 work in inserted parallel mode. ADC2 works independently */ -#define ADC_DAUL_REGULAL_PARALLEL ((uint32_t)0x00000006U) /*!< ADC0 and ADC1 work in regular parallel mode. ADC2 works independently */ -#define ADC_DAUL_REGULAL_FOLLOW_UP ((uint32_t)0x00000007U) /*!< ADC0 and ADC1 work in follow-up mode. ADC2 works independently */ -#define ADC_DAUL_INSERTED_TRRIGGER_ROTATION ((uint32_t)0x00000009U) /*!< ADC0 and ADC1 work in trigger rotation mode. ADC2 works independently */ -#define ADC_ALL_REGULAL_PARALLEL_INSERTED_PARALLEL ((uint32_t)0x00000011U) /*!< all ADCs work in combined regular parallel & inserted parallel mode */ -#define ADC_ALL_REGULAL_PARALLEL_INSERTED_ROTATION ((uint32_t)0x00000012U) /*!< all ADCs work in combined regular parallel & trigger rotation mode */ -#define ADC_ALL_INSERTED_PARALLEL ((uint32_t)0x00000015U) /*!< all ADCs work in inserted parallel mode */ -#define ADC_ALL_REGULAL_PARALLEL ((uint32_t)0x00000016U) /*!< all ADCs work in regular parallel mode */ -#define ADC_ALL_REGULAL_FOLLOW_UP ((uint32_t)0x00000017U) /*!< all ADCs work in follow-up mode */ -#define ADC_ALL_INSERTED_TRRIGGER_ROTATION ((uint32_t)0x00000019U) /*!< all ADCs work in trigger rotation mode */ - /* ADC synchronization delay */ #define ADC_SYNC_DELAY_5CYCLE ((uint32_t)0x00000000U) /*!< the delay between 2 sampling phases in ADC synchronization modes to 5 ADC clock cycles. */ #define ADC_SYNC_DELAY_6CYCLE ((uint32_t)0x00000100U) /*!< the delay between 2 sampling phases in ADC synchronization modes to 6 ADC clock cycles. */ @@ -351,98 +406,97 @@ #define ADC_EOC_SET_CONVERSION ((uint8_t)0x01U) /*!< at the end of each regular conversion, the EOC bit is set */ /* function declarations */ -/* ADC reset */ +/* initialization config */ +/* reset ADC */ void adc_deinit(void); +/* configure the ADC clock for all the ADCs */ +void adc_clock_config(uint32_t prescaler); +/* enable or disable ADC special function */ +void adc_special_function_config(uint32_t adc_periph , uint32_t function , ControlStatus newvalue); +/* configure ADC data alignment */ +void adc_data_alignment_config(uint32_t adc_periph , uint32_t data_alignment); /* enable ADC interface */ void adc_enable(uint32_t adc_periph); /* disable ADC interface */ void adc_disable(uint32_t adc_periph); -/* ADC data alignment config */ -void adc_data_alignment_config(uint32_t adc_periph , uint8_t data_alignment); -/* ADC resolution config */ -void adc_resolution_config(uint32_t adc_periph , uint32_t resolution); /* ADC calibration and reset calibration */ void adc_calibration_enable(uint32_t adc_periph); -/* ADC discontinuous mode config */ -void adc_discontinuous_mode_config(uint32_t adc_periph , uint8_t adc_channel_group , uint8_t length); -/* config end of conversion mode */ -void adc_end_of_conversion_config(uint32_t adc_periph , uint8_t end_selection); -/* ADC special function enable or disable */ -void adc_special_function_config(uint32_t adc_periph , uint8_t function , ControlStatus newvalue); -/* configure the ADC clock for all the ADCs */ -void adc_clock_config(uint32_t prescaler); +/* configure temperature sensor and internal reference voltage channel or VBAT channel function */ +void adc_channel_16_to_18(uint32_t function, ControlStatus newvalue); +/* configure ADC resolution */ +void adc_resolution_config(uint32_t adc_periph, uint32_t resolution); +/* configure ADC oversample mode */ +void adc_oversample_mode_config(uint32_t adc_periph, uint32_t mode, uint16_t shift, uint8_t ratio); +/* enable ADC oversample mode */ +void adc_oversample_mode_enable(uint32_t adc_periph); +/* disable ADC oversample mode */ +void adc_oversample_mode_disable(uint32_t adc_periph); -/* ADC channel */ -/* configure the ADC clock for all the ADCs */ -void adc_channel_16_to_18(uint8_t function,ControlStatus newvalue); -/* config the length of regular channel group or inserted channel group */ -void adc_channel_length_config(uint32_t adc_periph , uint8_t adc_channel_group , uint32_t length); - -/* ADC trigger */ -/* ADC external trigger enable */ -void adc_external_trigger_config(uint32_t adc_periph , uint8_t adc_channel_group , uint32_t trigger_mode); -/* ADC external trigger source config */ -void adc_external_trigger_source_config(uint32_t adc_periph , uint8_t adc_channel_group , uint32_t external_trigger_source); -/* ADC software trigger enable */ -void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group); - -/* ADC flag and interrupt */ -/* get the ADC flag bits */ -FlagStatus adc_flag_get(uint32_t adc_periph , uint32_t adc_flag); -/* clear the ADC flag bits */ -void adc_flag_clear(uint32_t adc_periph , uint32_t adc_flag); -/* get the ADC interrupt bits */ -FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t adc_interrupt); -/* clear the ADC flag */ -void adc_interrupt_flag_clear(uint32_t adc_periph , uint32_t adc_interrupt); -/* ADC interrupt enable */ -void adc_interrupt_enable(uint32_t adc_periph , uint32_t adc_interrupt); -/* ADC interrupt disable */ -void adc_interrupt_disable(uint32_t adc_periph , uint32_t adc_interrupt); - -/* ADC analog watchdog */ -/* ADC analog watchdog single channel disable */ -void adc_watchdog_single_channel_disable(uint32_t adc_periph ); -/* ADC analog watchdog single channel enable */ -void adc_watchdog_single_channel_enable(uint32_t adc_periph , uint8_t adc_channel); -/* adc analog watchdog group channel config */ -void adc_watchdog_enable(uint32_t adc_periph , uint8_t adc_channel_group); -/* ADC analog watchdog disable */ -void adc_watchdog_disable(uint32_t adc_periph , uint8_t adc_channel_group); -/* ADC analog watchdog threshold config */ -void adc_watchdog_threshold_config(uint32_t adc_periph , uint16_t low_threshold , uint16_t high_threshold); - -/* regular channel */ -/* ADC regular channel config */ -void adc_regular_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time); -/* ADC regular group data register read */ -uint16_t adc_regular_data_read(uint32_t adc_periph); - -/* inserted channel */ -/* ADC inserted channel config */ -void adc_inserted_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint8_t sample_time); -/* ADC inserted channel offset config */ -void adc_inserted_channel_offset_config(uint32_t adc_periph , uint8_t inserted_channel , uint16_t offset); -/* ADC inserted group data register read */ -uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel); - -/* ADC DMA */ -/* DMA request enable */ +/* DMA config */ +/* enable DMA request */ void adc_dma_mode_enable(uint32_t adc_periph); -/* DMA request disable */ +/* disable DMA request */ void adc_dma_mode_disable(uint32_t adc_periph); /* when DMA=1, the DMA engine issues a request at end of each regular conversion */ void adc_dma_request_after_last_enable(uint32_t adc_periph); /* the DMA engine is disabled after the end of transfer signal from DMA controller is detected */ void adc_dma_request_after_last_disable(uint32_t adc_periph); -/* ADC oversample */ -/* ADC oversample mode config */ -void adc_oversample_mode_config(uint32_t adc_periph , uint8_t mode , uint16_t shift , uint8_t ratio); -/* ADC oversample mode enable */ -void adc_oversample_mode_enable(uint32_t adc_periph ); -/* ADC oversample mode disable */ -void adc_oversample_mode_disable(uint32_t adc_periph ); +/* regular group and inserted group config */ +/* configure ADC discontinuous mode */ +void adc_discontinuous_mode_config(uint32_t adc_periph , uint8_t adc_channel_group , uint8_t length); +/* configure the length of regular channel group or inserted channel group */ +void adc_channel_length_config(uint32_t adc_periph , uint8_t adc_channel_group , uint32_t length); +/* configure ADC regular channel */ +void adc_regular_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time); +/* configure ADC inserted channel */ +void adc_inserted_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time); +/* configure ADC inserted channel offset */ +void adc_inserted_channel_offset_config(uint32_t adc_periph , uint8_t inserted_channel , uint16_t offset); +/* configure ADC external trigger source */ +void adc_external_trigger_source_config(uint32_t adc_periph , uint8_t adc_channel_group , uint32_t external_trigger_source); +/* enable ADC external trigger */ +void adc_external_trigger_config(uint32_t adc_periph , uint8_t adc_channel_group , uint32_t trigger_mode); +/* enable ADC software trigger */ +void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group); +/* configure end of conversion mode */ +void adc_end_of_conversion_config(uint32_t adc_periph , uint8_t end_selection); + +/* get channel data */ +/* read ADC regular group data register */ +uint16_t adc_regular_data_read(uint32_t adc_periph); +/* read ADC inserted group data register */ +uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel); + +/* watchdog config */ +/* disable ADC analog watchdog single channel */ +void adc_watchdog_single_channel_disable(uint32_t adc_periph ); +/* enable ADC analog watchdog single channel */ +void adc_watchdog_single_channel_enable(uint32_t adc_periph , uint8_t adc_channel); +/* configure ADC analog watchdog group channel */ +void adc_watchdog_group_channel_enable(uint32_t adc_periph , uint8_t adc_channel_group); +/* disable ADC analog watchdog */ +void adc_watchdog_disable(uint32_t adc_periph , uint8_t adc_channel_group); +/* configure ADC analog watchdog threshold */ +void adc_watchdog_threshold_config(uint32_t adc_periph , uint16_t low_threshold , uint16_t high_threshold); + +/* interrupt & flag functions */ +/* get the ADC flag bits */ +FlagStatus adc_flag_get(uint32_t adc_periph , uint32_t adc_flag); +/* clear the ADC flag bits */ +void adc_flag_clear(uint32_t adc_periph , uint32_t adc_flag); +/* get the bit state of ADCx software start conversion */ +FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph); +/* get the bit state of ADCx software inserted channel start conversion */ +FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph); +/* get the ADC interrupt bits */ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t adc_interrupt); +/* clear the ADC flag */ +void adc_interrupt_flag_clear(uint32_t adc_periph , uint32_t adc_interrupt); +/* enable ADC interrupt */ +void adc_interrupt_enable(uint32_t adc_periph , uint32_t adc_interrupt); +/* disable ADC interrupt */ +void adc_interrupt_disable(uint32_t adc_periph , uint32_t adc_interrupt); /* ADC synchronization */ /* configure the ADC sync mode */ @@ -455,7 +509,7 @@ void adc_sync_dma_config(uint32_t dma_mode ); void adc_sync_dma_request_after_last_enable(void); /* configure ADC sync DMA engine issues requests according to the SYNCDMA bits */ void adc_sync_dma_request_after_last_disable(void); -/* ADC sync regular data register read */ +/* read ADC sync regular data register */ uint32_t adc_sync_regular_data_read(void); #endif /* GD32F4XX_ADC_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h index 2be5832462..7310f63a75 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h @@ -1,12 +1,38 @@ /*! - \file gd32f4xx_can.h - \brief definitions for the CAN + \file gd32f4xx_can.h + \brief definitions for the CAN + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2019-11-27, V2.0.1, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_CAN_H @@ -42,7 +68,7 @@ #define CAN_RFIFOMI0(canx) REG32((canx) + 0x1B0U) /*!< CAN receive FIFO0 mailbox identifier register */ #define CAN_RFIFOMP0(canx) REG32((canx) + 0x1B4U) /*!< CAN receive FIFO0 mailbox property register */ #define CAN_RFIFOMDATA00(canx) REG32((canx) + 0x1B8U) /*!< CAN receive FIFO0 mailbox data0 register */ -#define CAN_RFIFOMDATA10(canx) REG32((canx) + 0x1CCU) /*!< CAN receive FIFO0 mailbox data1 register */ +#define CAN_RFIFOMDATA10(canx) REG32((canx) + 0x1BCU) /*!< CAN receive FIFO0 mailbox data1 register */ #define CAN_RFIFOMI1(canx) REG32((canx) + 0x1C0U) /*!< CAN receive FIFO1 mailbox identifier register */ #define CAN_RFIFOMP1(canx) REG32((canx) + 0x1C4U) /*!< CAN receive FIFO1 mailbox property register */ #define CAN_RFIFOMDATA01(canx) REG32((canx) + 0x1C8U) /*!< CAN receive FIFO1 mailbox data0 register */ @@ -110,20 +136,20 @@ #define CAN_F27DATA1(canx) REG32((canx) + 0x31CU) /*!< CAN filter 27 data 1 register */ /* CAN transmit mailbox bank */ -#define CAN_TMI(canx, bank) REG32((canx) + 0x180U + ((bank) * 0x10U)) /*!< CAN transmit mailbox identifier register */ -#define CAN_TMP(canx, bank) REG32((canx) + 0x184U + ((bank) * 0x10U)) /*!< CAN transmit mailbox property register */ -#define CAN_TMDATA0(canx, bank) REG32((canx) + 0x188U + ((bank) * 0x10U)) /*!< CAN transmit mailbox data0 register */ -#define CAN_TMDATA1(canx, bank) REG32((canx) + 0x18CU + ((bank) * 0x10U)) /*!< CAN transmit mailbox data1 register */ +#define CAN_TMI(canx, bank) REG32((canx) + 0x180U + ((bank) * 0x10U)) /*!< CAN transmit mailbox identifier register */ +#define CAN_TMP(canx, bank) REG32((canx) + 0x184U + ((bank) * 0x10U)) /*!< CAN transmit mailbox property register */ +#define CAN_TMDATA0(canx, bank) REG32((canx) + 0x188U + ((bank) * 0x10U)) /*!< CAN transmit mailbox data0 register */ +#define CAN_TMDATA1(canx, bank) REG32((canx) + 0x18CU + ((bank) * 0x10U)) /*!< CAN transmit mailbox data1 register */ /* CAN filter bank */ -#define CAN_FDATA0(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x0U) /*!< CAN filter data 0 register */ -#define CAN_FDATA1(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x4U) /*!< CAN filter data 1 register */ +#define CAN_FDATA0(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x0U) /*!< CAN filter data 0 register */ +#define CAN_FDATA1(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x4U) /*!< CAN filter data 1 register */ /* CAN receive fifo mailbox bank */ -#define CAN_RFIFOMI(canx, bank) REG32((canx) + 0x1B0U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox identifier register */ -#define CAN_RFIFOMP(canx, bank) REG32((canx) + 0x1B4U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox property register */ -#define CAN_RFIFOMDATA0(canx, bank) REG32((canx) + 0x1B8U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data0 register */ -#define CAN_RFIFOMDATA1(canx, bank) REG32((canx) + 0x1BCU + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data1 register */ +#define CAN_RFIFOMI(canx, bank) REG32((canx) + 0x1B0U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox identifier register */ +#define CAN_RFIFOMP(canx, bank) REG32((canx) + 0x1B4U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox property register */ +#define CAN_RFIFOMDATA0(canx, bank) REG32((canx) + 0x1B8U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data0 register */ +#define CAN_RFIFOMDATA1(canx, bank) REG32((canx) + 0x1BCU + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data1 register */ /* bits definitions */ /* CAN_CTL */ @@ -198,7 +224,7 @@ #define CAN_INTEN_BOIE BIT(10) /*!< bus-off interrupt enable */ #define CAN_INTEN_ERRNIE BIT(11) /*!< error number interrupt enable */ #define CAN_INTEN_ERRIE BIT(15) /*!< error interrupt enable */ -#define CAN_INTEN_WUIE BIT(16) /*!< wakeup interrupt enable */ +#define CAN_INTEN_WIE BIT(16) /*!< wakeup interrupt enable */ #define CAN_INTEN_SLPWIE BIT(17) /*!< sleep working interrupt enable */ /* CAN_ERR */ @@ -280,11 +306,19 @@ /* CAN_FW */ #define CAN_FW_FW(regval) BIT(regval) /*!< filter working */ +/* CAN_FxDATAy */ +#define CAN_FDATA_FD(regval) BIT(regval) /*!< filter data */ + /* consts definitions */ /* define the CAN bit position and its register index offset */ -#define CAN_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) -#define CAN_REG_VAL(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 6))) -#define CAN_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define CAN_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define CAN_REG_VAL(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 6))) +#define CAN_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +#define CAN_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define CAN_REG_VALS(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 12))) +#define CAN_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define CAN_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) /* register offset */ #define STAT_REG_OFFSET ((uint8_t)0x04U) /*!< STAT register offset */ @@ -296,45 +330,84 @@ /* CAN flags */ typedef enum { + /* flags in STAT register */ + CAN_FLAG_RXL = CAN_REGIDX_BIT(STAT_REG_OFFSET, 11U), /*!< RX level */ + CAN_FLAG_LASTRX = CAN_REGIDX_BIT(STAT_REG_OFFSET, 10U), /*!< last sample value of RX pin */ + CAN_FLAG_RS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 9U), /*!< receiving state */ + CAN_FLAG_TS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 8U), /*!< transmitting state */ + CAN_FLAG_SLPIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 4U), /*!< status change flag of entering sleep working mode */ + CAN_FLAG_WUIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 3U), /*!< status change flag of wakeup from sleep working mode */ + CAN_FLAG_ERRIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 2U), /*!< error flag */ + CAN_FLAG_SLPWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 1U), /*!< sleep working state */ + CAN_FLAG_IWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 0U), /*!< initial working state */ /* flags in TSTAT register */ - CAN_FLAG_MTE2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 19U), /*!< mailbox 2 transmit error */ - CAN_FLAG_MTE1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 11U), /*!< mailbox 1 transmit error */ - CAN_FLAG_MTE0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 3U), /*!< mailbox 0 transmit error */ - CAN_FLAG_MTF2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 16U), /*!< mailbox 2 transmit finished */ - CAN_FLAG_MTF1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 8U), /*!< mailbox 1 transmit finished */ - CAN_FLAG_MTF0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 0U), /*!< mailbox 0 transmit finished */ + CAN_FLAG_TMLS2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 31U), /*!< transmit mailbox 2 last sending in Tx FIFO */ + CAN_FLAG_TMLS1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 30U), /*!< transmit mailbox 1 last sending in Tx FIFO */ + CAN_FLAG_TMLS0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 29U), /*!< transmit mailbox 0 last sending in Tx FIFO */ + CAN_FLAG_TME2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 28U), /*!< transmit mailbox 2 empty */ + CAN_FLAG_TME1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 27U), /*!< transmit mailbox 1 empty */ + CAN_FLAG_TME0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 26U), /*!< transmit mailbox 0 empty */ + CAN_FLAG_MTE2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 19U), /*!< mailbox 2 transmit error */ + CAN_FLAG_MTE1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 11U), /*!< mailbox 1 transmit error */ + CAN_FLAG_MTE0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 3U), /*!< mailbox 0 transmit error */ + CAN_FLAG_MAL2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 18U), /*!< mailbox 2 arbitration lost */ + CAN_FLAG_MAL1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 10U), /*!< mailbox 1 arbitration lost */ + CAN_FLAG_MAL0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 2U), /*!< mailbox 0 arbitration lost */ + CAN_FLAG_MTFNERR2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 17U), /*!< mailbox 2 transmit finished with no error */ + CAN_FLAG_MTFNERR1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 9U), /*!< mailbox 1 transmit finished with no error */ + CAN_FLAG_MTFNERR0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 1U), /*!< mailbox 0 transmit finished with no error */ + CAN_FLAG_MTF2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 16U), /*!< mailbox 2 transmit finished */ + CAN_FLAG_MTF1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 8U), /*!< mailbox 1 transmit finished */ + CAN_FLAG_MTF0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 0U), /*!< mailbox 0 transmit finished */ /* flags in RFIFO0 register */ - CAN_FLAG_RFO0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 4U), /*!< receive FIFO0 overfull */ - CAN_FLAG_RFF0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 3U), /*!< receive FIFO0 full */ + CAN_FLAG_RFO0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 4U), /*!< receive FIFO0 overfull */ + CAN_FLAG_RFF0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 3U), /*!< receive FIFO0 full */ /* flags in RFIFO1 register */ - CAN_FLAG_RFO1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 4U), /*!< receive FIFO1 overfull */ - CAN_FLAG_RFF1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 3U), /*!< receive FIFO1 full */ + CAN_FLAG_RFO1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 4U), /*!< receive FIFO1 overfull */ + CAN_FLAG_RFF1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 3U), /*!< receive FIFO1 full */ /* flags in ERR register */ - CAN_FLAG_BOERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 2U), /*!< bus-off error */ - CAN_FLAG_PERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 1U), /*!< passive error */ - CAN_FLAG_WERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 0U), /*!< warning error */ + CAN_FLAG_BOERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 2U), /*!< bus-off error */ + CAN_FLAG_PERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 1U), /*!< passive error */ + CAN_FLAG_WERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 0U), /*!< warning error */ }can_flag_enum; /* CAN interrupt flags */ typedef enum { /* interrupt flags in STAT register */ - CAN_INT_SLPIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 4U), /*!< status change interrupt flag of sleep working mode entering */ - CAN_INT_WUIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 3U), /*!< status change interrupt flag of wakeup from sleep working mode */ - CAN_INT_ERRIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 2U), /*!< error interrupt flag */ + CAN_INT_FLAG_SLPIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 4U, 17U), /*!< status change interrupt flag of sleep working mode entering */ + CAN_INT_FLAG_WUIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 3U, 16), /*!< status change interrupt flag of wakeup from sleep working mode */ + CAN_INT_FLAG_ERRIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 2U, 15), /*!< error interrupt flag */ + /* interrupt flags in TSTAT register */ + CAN_INT_FLAG_MTF2 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 16U, 0U), /*!< mailbox 2 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF1 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 8U, 0U), /*!< mailbox 1 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF0 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 0U, 0U), /*!< mailbox 0 transmit finished interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 4U, 3U), /*!< receive FIFO0 overfull interrupt flag */ + CAN_INT_FLAG_RFF0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 3U, 2U), /*!< receive FIFO0 full interrupt flag */ + CAN_INT_FLAG_RFL0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 2U, 1U), /*!< receive FIFO0 not empty interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 4U, 6U), /*!< receive FIFO1 overfull interrupt flag */ + CAN_INT_FLAG_RFF1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 3U, 5U), /*!< receive FIFO1 full interrupt flag */ + CAN_INT_FLAG_RFL1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 2U, 4U), /*!< receive FIFO0 not empty interrupt flag */ + /* interrupt flags in ERR register */ + CAN_INT_FLAG_ERRN = CAN_REGIDX_BITS(ERR_REG_OFFSET, 3U, 11U), /*!< error number interrupt flag */ + CAN_INT_FLAG_BOERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 2U, 10U), /*!< bus-off error interrupt flag */ + CAN_INT_FLAG_PERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 1U, 9U), /*!< passive error interrupt flag */ + CAN_INT_FLAG_WERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 0U, 8U), /*!< warning error interrupt flag */ }can_interrupt_flag_enum; /* CAN initiliaze parameters struct */ typedef struct { - uint8_t working_mode; /*!< CAN working mode */ + uint8_t working_mode; /*!< CAN working mode */ uint8_t resync_jump_width; /*!< CAN resynchronization jump width */ uint8_t time_segment_1; /*!< time segment 1 */ uint8_t time_segment_2; /*!< time segment 2 */ ControlStatus time_triggered; /*!< time triggered communication mode */ ControlStatus auto_bus_off_recovery; /*!< automatic bus-off recovery */ ControlStatus auto_wake_up; /*!< automatic wake-up mode */ - ControlStatus auto_retrans; /*!< automatic retransmission mode */ + ControlStatus no_auto_retrans; /*!< automatic retransmission mode disable */ ControlStatus rec_fifo_overwrite; /*!< receive FIFO overwrite mode */ ControlStatus trans_fifo_order; /*!< transmit FIFO order */ uint16_t prescaler; /*!< baudrate prescaler */ @@ -387,18 +460,26 @@ typedef enum CAN_ERROR_BITRECESSIVE, /*!< bit recessive error */ CAN_ERROR_BITDOMINANTER, /*!< bit dominant error */ CAN_ERROR_CRC, /*!< CRC error */ - CAN_ERROR_SOFTWARECFG /*!< software configure */ + CAN_ERROR_SOFTWARECFG, /*!< software configure */ }can_error_enum; /* transmit states */ typedef enum { - CAN_TRANSMIT_FAILED = 0, /*!< CAN transmitted failure */ - CAN_TRANSMIT_OK = 1, /*!< CAN transmitted success */ - CAN_TRANSMIT_PENDING = 2, /*!< CAN transmitted pending */ - CAN_TRANSMIT_NOMAILBOX = 4, /*!< no empty mailbox to be used for CAN */ + CAN_TRANSMIT_FAILED = 0U, /*!< CAN transmitted failure */ + CAN_TRANSMIT_OK = 1U, /*!< CAN transmitted success */ + CAN_TRANSMIT_PENDING = 2U, /*!< CAN transmitted pending */ + CAN_TRANSMIT_NOMAILBOX = 4U, /*!< no empty mailbox to be used for CAN */ }can_transmit_state_enum; +typedef enum +{ + CAN_INIT_STRUCT = 0, /* CAN initiliaze parameters struct */ + CAN_FILTER_STRUCT, /* CAN filter parameters struct */ + CAN_TX_MESSAGE_STRUCT, /* CAN transmit message struct */ + CAN_RX_MESSAGE_STRUCT, /* CAN receive message struct */ +}can_struct_type_enum; + /* CAN baudrate prescaler*/ #define BT_BAUDPSC(regval) (BITS(0,9) & ((uint32_t)(regval) << 0)) @@ -438,66 +519,76 @@ typedef enum /* transmit data byte 2 */ #define TMDATA0_DB2(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) -/* transmit data byte 3 */ +/* transmit data byte 3 */ #define TMDATA0_DB3(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) -/* transmit data byte 4 */ +/* transmit data byte 4 */ #define TMDATA1_DB4(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) -/* transmit data byte 5 */ +/* transmit data byte 5 */ #define TMDATA1_DB5(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) -/* transmit data byte 6 */ +/* transmit data byte 6 */ #define TMDATA1_DB6(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) -/* transmit data byte 7 */ +/* transmit data byte 7 */ #define TMDATA1_DB7(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) /* receive mailbox extended identifier*/ -#define RFIFOMI_EFID(regval) GET_BITS((uint32_t)(regval), 3, 31) +#define GET_RFIFOMI_EFID(regval) GET_BITS((uint32_t)(regval), 3U, 31U) /* receive mailbox standrad identifier*/ -#define RFIFOMI_SFID(regval) GET_BITS((uint32_t)(regval), 21, 31) +#define GET_RFIFOMI_SFID(regval) GET_BITS((uint32_t)(regval), 21U, 31U) /* receive data length */ -#define RFIFOMP_DLENC(regval) GET_BITS((uint32_t)(regval), 0, 3) +#define GET_RFIFOMP_DLENC(regval) GET_BITS((uint32_t)(regval), 0U, 3U) -#define RFIFOMP_FI(regval) GET_BITS((uint32_t)(regval), 8, 15) +/* the index of the filter by which the frame is passed */ +#define GET_RFIFOMP_FI(regval) GET_BITS((uint32_t)(regval), 8U, 15U) /* receive data byte 0 */ -#define RFIFOMDATA0_DB0(regval) GET_BITS((uint32_t)(regval), 0, 7) +#define GET_RFIFOMDATA0_DB0(regval) GET_BITS((uint32_t)(regval), 0U, 7U) /* receive data byte 1 */ -#define RFIFOMDATA0_DB1(regval) GET_BITS((uint32_t)(regval), 8, 15) +#define GET_RFIFOMDATA0_DB1(regval) GET_BITS((uint32_t)(regval), 8U, 15U) /* receive data byte 2 */ -#define RFIFOMDATA0_DB2(regval) GET_BITS((uint32_t)(regval), 16, 23) +#define GET_RFIFOMDATA0_DB2(regval) GET_BITS((uint32_t)(regval), 16U, 23U) /* receive data byte 3 */ -#define RFIFOMDATA0_DB3(regval) GET_BITS((uint32_t)(regval), 24, 31) +#define GET_RFIFOMDATA0_DB3(regval) GET_BITS((uint32_t)(regval), 24U, 31U) /* receive data byte 4 */ -#define RFIFOMDATA1_DB4(regval) GET_BITS((uint32_t)(regval), 0, 7) +#define GET_RFIFOMDATA1_DB4(regval) GET_BITS((uint32_t)(regval), 0U, 7U) /* receive data byte 5 */ -#define RFIFOMDATA1_DB5(regval) GET_BITS((uint32_t)(regval), 8, 15) +#define GET_RFIFOMDATA1_DB5(regval) GET_BITS((uint32_t)(regval), 8U, 15U) /* receive data byte 6 */ -#define RFIFOMDATA1_DB6(regval) GET_BITS((uint32_t)(regval), 16, 23) +#define GET_RFIFOMDATA1_DB6(regval) GET_BITS((uint32_t)(regval), 16U, 23U) /* receive data byte 7 */ -#define RFIFOMDATA1_DB7(regval) GET_BITS((uint32_t)(regval), 24, 31) +#define GET_RFIFOMDATA1_DB7(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* error number */ +#define GET_ERR_ERRN(regval) GET_BITS((uint32_t)(regval), 4U, 6U) + +/* transmit error count */ +#define GET_ERR_TECNT(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive error count */ +#define GET_ERR_RECNT(regval) GET_BITS((uint32_t)(regval), 24U, 31U) /* CAN errors */ #define ERR_ERRN(regval) (BITS(4,6) & ((uint32_t)(regval) << 4)) -#define CAN_ERRN_0 ERR_ERRN(0) /* no error */ -#define CAN_ERRN_1 ERR_ERRN(1) /*!< fill error */ -#define CAN_ERRN_2 ERR_ERRN(2) /*!< format error */ -#define CAN_ERRN_3 ERR_ERRN(3) /*!< ACK error */ -#define CAN_ERRN_4 ERR_ERRN(4) /*!< bit recessive error */ -#define CAN_ERRN_5 ERR_ERRN(5) /*!< bit dominant error */ -#define CAN_ERRN_6 ERR_ERRN(6) /*!< CRC error */ -#define CAN_ERRN_7 ERR_ERRN(7) /*!< software error */ +#define CAN_ERRN_0 ERR_ERRN(0U) /* no error */ +#define CAN_ERRN_1 ERR_ERRN(1U) /*!< fill error */ +#define CAN_ERRN_2 ERR_ERRN(2U) /*!< format error */ +#define CAN_ERRN_3 ERR_ERRN(3U) /*!< ACK error */ +#define CAN_ERRN_4 ERR_ERRN(4U) /*!< bit recessive error */ +#define CAN_ERRN_5 ERR_ERRN(5U) /*!< bit dominant error */ +#define CAN_ERRN_6 ERR_ERRN(6U) /*!< CRC error */ +#define CAN_ERRN_7 ERR_ERRN(7U) /*!< software error */ #define CAN_STATE_PENDING ((uint32_t)0x00000000U) /*!< CAN pending */ @@ -556,7 +647,7 @@ typedef enum #define CAN_FIFO1 ((uint8_t)0x01U) /*!< receive FIFO1 */ /* frame number of receive fifo */ -#define CAN_RFIFO_RFL0_MASK ((uint32_t)0x00000003U) /*!< mask for frame number in receive FIFO0 */ +#define CAN_RFIF_RFL_MASK ((uint32_t)0x00000003U) /*!< mask for frame number in receive FIFOx */ #define CAN_SFID_MASK ((uint32_t)0x000007FFU) /*!< mask of standard identifier */ #define CAN_EFID_MASK ((uint32_t)0x1FFFFFFFU) /*!< mask of extended identifier */ @@ -575,7 +666,7 @@ typedef enum #define CAN_FILTERMODE_LIST ((uint8_t)0x01U) /*!< list mode */ /* filter 16 bits mask */ -#define CAN_FILTER_MASK_16BITS ((uint32_t)0x0000FFFFU) +#define CAN_FILTER_MASK_16BITS ((uint32_t)0x0000FFFFU) /*!< can filter 16 bits mask */ /* frame type */ #define CAN_FT_DATA ((uint32_t)0x00000000U) /*!< data frame */ @@ -584,62 +675,72 @@ typedef enum /* CAN timeout */ #define CAN_TIMEOUT ((uint32_t)0x0000FFFFU) /*!< timeout value */ +/* interrupt enable bits */ +#define CAN_INT_TME CAN_INTEN_TMEIE /*!< transmit mailbox empty interrupt enable */ +#define CAN_INT_RFNE0 CAN_INTEN_RFNEIE0 /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INT_RFF0 CAN_INTEN_RFFIE0 /*!< receive FIFO0 full interrupt enable */ +#define CAN_INT_RFO0 CAN_INTEN_RFOIE0 /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INT_RFNE1 CAN_INTEN_RFNEIE1 /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INT_RFF1 CAN_INTEN_RFFIE1 /*!< receive FIFO1 full interrupt enable */ +#define CAN_INT_RFO1 CAN_INTEN_RFOIE1 /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INT_WERR CAN_INTEN_WERRIE /*!< warning error interrupt enable */ +#define CAN_INT_PERR CAN_INTEN_PERRIE /*!< passive error interrupt enable */ +#define CAN_INT_BO CAN_INTEN_BOIE /*!< bus-off interrupt enable */ +#define CAN_INT_ERRN CAN_INTEN_ERRNIE /*!< error number interrupt enable */ +#define CAN_INT_ERR CAN_INTEN_ERRIE /*!< error interrupt enable */ +#define CAN_INT_WAKEUP CAN_INTEN_WIE /*!< wakeup interrupt enable */ +#define CAN_INT_SLPW CAN_INTEN_SLPWIE /*!< sleep working interrupt enable */ + /* function declarations */ -/* initialization functions */ -/* CAN deinit */ +/* deinitialize CAN */ void can_deinit(uint32_t can_periph); -/* CAN init */ +/* initialize CAN struct */ +void can_struct_para_init(can_struct_type_enum type, void* p_struct); +/* initialize CAN */ ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init); - -/* transmit functions */ -/* CAN transmit message */ -uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message); -/* CAN transmit state */ -can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number); -/* CAN stop transmission */ -void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number); -/* CAN transmit error number */ -uint8_t can_transmit_error_number(uint32_t can_periph); - -/* filter functions */ /* CAN filter init */ void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init); /* set can1 fliter start bank number */ void can1_filter_start_bank(uint8_t start_bank); - /* enable functions */ /* CAN debug freeze enable */ void can_debug_freeze_enable(uint32_t can_periph); /* CAN debug freeze disable */ void can_debug_freeze_disable(uint32_t can_periph); -/* CAN time triggle mode enable */ +/* CAN time trigger mode enable */ void can_time_trigger_mode_enable(uint32_t can_periph); -/* CAN time triggle mode disable */ +/* CAN time trigger mode disable */ void can_time_trigger_mode_disable(uint32_t can_periph); -/* CAN interrupt enable */ -void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt); -/* CAN interrupt disable */ -void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt); -/* receive functions */ +/* transmit functions */ +/* transmit CAN message */ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message); +/* get CAN transmit state */ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number); +/* stop CAN transmission */ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number); /* CAN receive message */ void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message); /* CAN release fifo */ void can_fifo_release(uint32_t can_periph, uint8_t fifo_number); /* CAN receive message length */ -uint8_t can_receive_message_length(uint32_t can_periph, uint8_t fifo_number); -/* CAN receive error number */ -uint8_t can_receive_error_number(uint32_t can_periph); - -/* mode functions */ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number); /* CAN working mode */ ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode); /* CAN wakeup from sleep mode */ ErrStatus can_wakeup(uint32_t can_periph); -/* flag functions */ /* CAN get error */ can_error_enum can_error_get(uint32_t can_periph); +/* get CAN receive error number */ +uint8_t can_receive_error_number_get(uint32_t can_periph); +/* get CAN transmit error number */ +uint8_t can_transmit_error_number_get(uint32_t can_periph); + +/* CAN interrupt enable */ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt); +/* CAN interrupt disable */ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt); /* CAN get flag state */ FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag); /* CAN clear flag state */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h index 983dd944a5..01f2c6bc3f 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_crc.h - \brief definitions for the CRC + \file gd32f4xx_crc.h + \brief definitions for the CRC + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_CRC_H @@ -37,19 +62,19 @@ /* deinit CRC calculation unit */ void crc_deinit(void); -/* reset data register to the value of initializaiton data register */ +/* reset data register(CRC_DATA) to the value of 0xFFFFFFFF */ void crc_data_register_reset(void); -/* read the data register */ +/* read the value of the data register */ uint32_t crc_data_register_read(void); -/* read the free data register */ +/* read the value of the free data register */ uint8_t crc_free_data_register_read(void); -/* write the free data register */ +/* write data to the free data register */ void crc_free_data_register_write(uint8_t free_data); -/* CRC calculate a 32-bit data */ +/* calculate the CRC value of a 32-bit data */ uint32_t crc_single_data_calculate(uint32_t sdata); -/* CRC calculate a 32-bit data array */ +/* calculate the CRC value of an array of 32-bit values */ uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size); #endif /* GD32F4XX_CRC_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h index 605d5530d5..00e4e7f298 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_ctc.h - \brief definitions for the CTC + \file gd32f4xx_ctc.h + \brief definitions for the CTC + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_CTC_H @@ -25,7 +50,7 @@ /* bits definitions */ /* CTC_CTL0 */ -#define CTC_CTL0_CKOKIE BIT(0) /*!< clock trim OK(CKOKIF) interrupt enable */ +#define CTC_CTL0_CKOKIE BIT(0) /*!< clock trim OK(CKOKIF) interrupt enable */ #define CTC_CTL0_CKWARNIE BIT(1) /*!< clock trim warning(CKWARNIF) interrupt enable */ #define CTC_CTL0_ERRIE BIT(2) /*!< error(ERRIF) interrupt enable */ #define CTC_CTL0_EREFIE BIT(3) /*!< EREFIF interrupt enable */ @@ -90,19 +115,19 @@ #define CTC_REFSOURCE_PSC_DIV128 CTL1_REFPSC(7) /*!< reference signal divided by 128 */ /* CTC interrupt enable definitions */ -#define CTC_INT_CKOKIE CTC_CTL0_CKOKIE /*!< clock trim OK interrupt enable */ -#define CTC_INT_CKWARNIE CTC_CTL0_CKWARNIE /*!< clock trim warning interrupt enable */ -#define CTC_INT_ERRIE CTC_CTL0_ERRIE /*!< error interrupt enable */ -#define CTC_INT_EREFIE CTC_CTL0_EREFIE /*!< expect reference interrupt enable */ +#define CTC_INT_CKOK CTC_CTL0_CKOKIE /*!< clock trim OK interrupt enable */ +#define CTC_INT_CKWARN CTC_CTL0_CKWARNIE /*!< clock trim warning interrupt enable */ +#define CTC_INT_ERR CTC_CTL0_ERRIE /*!< error interrupt enable */ +#define CTC_INT_EREF CTC_CTL0_EREFIE /*!< expect reference interrupt enable */ /* CTC interrupt source definitions */ -#define CTC_INT_CKOK CTC_STAT_CKOKIF /*!< clock trim OK interrupt flag */ -#define CTC_INT_CKWARN CTC_STAT_CKWARNIF /*!< clock trim warning interrupt flag */ -#define CTC_INT_ERR CTC_STAT_ERRIF /*!< error interrupt flag */ -#define CTC_INT_EREF CTC_STAT_EREFIF /*!< expect reference interrupt flag */ -#define CTC_INT_CKERR CTC_STAT_CKERR /*!< clock trim error bit */ -#define CTC_INT_REFMISS CTC_STAT_REFMISS /*!< reference sync pulse miss */ -#define CTC_INT_TRIMERR CTC_STAT_TRIMERR /*!< trim value error */ +#define CTC_INT_FLAG_CKOK CTC_STAT_CKOKIF /*!< clock trim OK interrupt flag */ +#define CTC_INT_FLAG_CKWARN CTC_STAT_CKWARNIF /*!< clock trim warning interrupt flag */ +#define CTC_INT_FLAG_ERR CTC_STAT_ERRIF /*!< error interrupt flag */ +#define CTC_INT_FLAG_EREF CTC_STAT_EREFIF /*!< expect reference interrupt flag */ +#define CTC_INT_FLAG_CKERR CTC_STAT_CKERR /*!< clock trim error bit */ +#define CTC_INT_FLAG_REFMISS CTC_STAT_REFMISS /*!< reference sync pulse miss */ +#define CTC_INT_FLAG_TRIMERR CTC_STAT_TRIMERR /*!< trim value error */ /* CTC flag definitions */ #define CTC_FLAG_CKOK CTC_STAT_CKOKIF /*!< clock trim OK flag */ @@ -116,45 +141,30 @@ /* function declarations */ /* reset ctc clock trim controller */ void ctc_deinit(void); - -/* enable the CTC interrupt */ -void ctc_interrupt_enable(uint32_t ctc_interrupt); -/* disable the CTC interrupt */ -void ctc_interrupt_disable(uint32_t ctc_interrupt); -/* get CTC interrupt flag */ -FlagStatus ctc_interrupt_flag_get(uint32_t ctc_interrupt); -/* clear CTC interrupt flag */ -void ctc_interrupt_flag_clear(uint32_t ctc_interrupt); - -/* get CTC flag */ -FlagStatus ctc_flag_get(uint32_t ctc_flag); -/* clear CTC flag */ -void ctc_flag_clear(uint32_t ctc_flag); +/* enable CTC trim counter */ +void ctc_counter_enable(void); +/* disable CTC trim counter */ +void ctc_counter_disable(void); /* configure the IRC48M trim value */ -void ctc_irc48m_trim_value_config(uint8_t ctc_trim_value); +void ctc_irc48m_trim_value_config(uint8_t trim_value); /* generate software reference source sync pulse */ void ctc_software_refsource_pulse_generate(void); /* configure hardware automatically trim mode */ -void ctc_hardware_trim_mode_config(uint32_t ctc_hardmode); - -/* enable CTC counter */ -void ctc_counter_enable(void); -/* disable CTC counter */ -void ctc_counter_disable(void); +void ctc_hardware_trim_mode_config(uint32_t hardmode); /* configure reference signal source polarity */ -void ctc_refsource_polarity_config(uint32_t ctc_polarity); +void ctc_refsource_polarity_config(uint32_t polarity); /* select USBFS or USBHS SOF signal */ -void ctc_usbsof_signal_select(uint32_t ctc_usbsof); +void ctc_usbsof_signal_select(uint32_t usbsof); /* select reference signal source */ -void ctc_refsource_signal_select(uint32_t ctc_refs); +void ctc_refsource_signal_select(uint32_t refs); /* configure reference signal source prescaler */ -void ctc_refsource_prescaler_config(uint32_t ctc_prescaler); +void ctc_refsource_prescaler_config(uint32_t prescaler); /* configure clock trim base limit value */ -void ctc_clock_limit_value_config(uint8_t ctc_limit_value); +void ctc_clock_limit_value_config(uint8_t limit_value); /* configure CTC counter reload value */ -void ctc_counter_reload_value_config(uint16_t ctc_reload_value); +void ctc_counter_reload_value_config(uint16_t reload_value); /* read CTC counter capture value when reference sync pulse occurred */ uint16_t ctc_counter_capture_value_read(void); @@ -165,4 +175,18 @@ uint16_t ctc_counter_reload_value_read(void); /* read the IRC48M trim value */ uint8_t ctc_irc48m_trim_value_read(void); +/* interrupt & flag functions */ +/* enable the CTC interrupt */ +void ctc_interrupt_enable(uint32_t interrupt); +/* disable the CTC interrupt */ +void ctc_interrupt_disable(uint32_t interrupt); +/* get CTC interrupt flag */ +FlagStatus ctc_interrupt_flag_get(uint32_t int_flag); +/* clear CTC interrupt flag */ +void ctc_interrupt_flag_clear(uint32_t int_flag); +/* get CTC flag */ +FlagStatus ctc_flag_get(uint32_t flag); +/* clear CTC flag */ +void ctc_flag_clear(uint32_t flag); + #endif /* GD32F4XX_CTC_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h index 8a668fcc0c..573fb31336 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_dac.h - \brief definitions for the DAC + \file gd32f4xx_dac.h + \brief definitions for the DAC + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_DAC_H @@ -20,152 +45,153 @@ #define DAC1 1U /* registers definitions */ -#define DAC_CTL REG32(DAC + 0x00U) /*!< DAC control register */ -#define DAC_SWT REG32(DAC + 0x04U) /*!< DAC software trigger register */ -#define DAC0_R12DH REG32(DAC + 0x08U) /*!< DAC0 12-bit right-aligned data holding register */ -#define DAC0_L12DH REG32(DAC + 0x0CU) /*!< DAC0 12-bit left-aligned data holding register */ -#define DAC0_R8DH REG32(DAC + 0x10U) /*!< DAC0 8-bit right-aligned data holding register */ -#define DAC1_R12DH REG32(DAC + 0x14U) /*!< DAC1 12-bit right-aligned data holding register */ -#define DAC1_L12DH REG32(DAC + 0x18U) /*!< DAC1 12-bit left-aligned data holding register */ -#define DAC1_R8DH REG32(DAC + 0x1CU) /*!< DAC1 8-bit right-aligned data holding register */ -#define DACC_R12DH REG32(DAC + 0x20U) /*!< DAC concurrent mode 12-bit right-aligned data holding register */ -#define DACC_L12DH REG32(DAC + 0x24U) /*!< DAC concurrent mode 12-bit left-aligned data holding register */ -#define DACC_R8DH REG32(DAC + 0x28U) /*!< DAC concurrent mode 8-bit right-aligned data holding register */ -#define DAC0_DO REG32(DAC + 0x2CU) /*!< DAC0 data output register */ -#define DAC1_DO REG32(DAC + 0x30U) /*!< DAC1 data output register */ -#define DAC_STAT REG32(DAC + 0x34U) /*!< DAC status register */ +#define DAC_CTL REG32(DAC + 0x00U) /*!< DAC control register */ +#define DAC_SWT REG32(DAC + 0x04U) /*!< DAC software trigger register */ +#define DAC0_R12DH REG32(DAC + 0x08U) /*!< DAC0 12-bit right-aligned data holding register */ +#define DAC0_L12DH REG32(DAC + 0x0CU) /*!< DAC0 12-bit left-aligned data holding register */ +#define DAC0_R8DH REG32(DAC + 0x10U) /*!< DAC0 8-bit right-aligned data holding register */ +#define DAC1_R12DH REG32(DAC + 0x14U) /*!< DAC1 12-bit right-aligned data holding register */ +#define DAC1_L12DH REG32(DAC + 0x18U) /*!< DAC1 12-bit left-aligned data holding register */ +#define DAC1_R8DH REG32(DAC + 0x1CU) /*!< DAC1 8-bit right-aligned data holding register */ +#define DACC_R12DH REG32(DAC + 0x20U) /*!< DAC concurrent mode 12-bit right-aligned data holding register */ +#define DACC_L12DH REG32(DAC + 0x24U) /*!< DAC concurrent mode 12-bit left-aligned data holding register */ +#define DACC_R8DH REG32(DAC + 0x28U) /*!< DAC concurrent mode 8-bit right-aligned data holding register */ +#define DAC0_DO REG32(DAC + 0x2CU) /*!< DAC0 data output register */ +#define DAC1_DO REG32(DAC + 0x30U) /*!< DAC1 data output register */ +#define DAC_STAT REG32(DAC + 0x34U) /*!< DAC status register */ /* bits definitions */ -/* DAC_CLT */ -#define DAC_CTL_DEN0 BIT(0) /*!< DAC0 enable/disable bit */ -#define DAC_CTL_DBOFF0 BIT(1) /*!< DAC0 output buffer turn on/turn off bit */ -#define DAC_CTL_DTEN0 BIT(2) /*!< DAC0 trigger enable/disable bit */ -#define DAC_CTL_DTSEL0 BITS(3,5) /*!< DAC0 trigger source selection enable/disable bits */ -#define DAC_CTL_DWM0 BITS(6,7) /*!< DAC0 noise wave mode */ -#define DAC_CTL_DWBW0 BITS(8,11) /*!< DAC0 noise wave bit width */ -#define DAC_CTL_DDMAEN0 BIT(12) /*!< DAC0 DMA enable/disanle bit */ -#define DAC_CTL_DDUDRIE0 BIT(13) /*!< DAC0 DMA underrun interrupt enable/disable bit */ -#define DAC_CTL_DEN1 BIT(16) /*!< DAC1 enable/disable bit */ -#define DAC_CTL_DBOFF1 BIT(17) /*!< DAC1 output buffer turn on/turn off bit */ -#define DAC_CTL_DTEN1 BIT(18) /*!< DAC1 trigger enable/disable bit */ -#define DAC_CTL_DTSEL1 BITS(19,21) /*!< DAC1 trigger source selection enable/disable bits */ -#define DAC_CTL_DWM1 BITS(22,23) /*!< DAC1 noise wave mode */ -#define DAC_CTL_DWBW1 BITS(24,27) /*!< DAC1 noise wave bit width */ -#define DAC_CTL_DDMAEN1 BIT(28) /*!< DAC1 DMA enable/disanle bit */ -#define DAC_CTL_DDUDRIE1 BIT(29) /*!< DAC1 DMA underrun interrupt enable/disable bit */ +/* DAC_CTL */ +#define DAC_CTL_DEN0 BIT(0) /*!< DAC0 enable/disable bit */ +#define DAC_CTL_DBOFF0 BIT(1) /*!< DAC0 output buffer turn on/turn off bit */ +#define DAC_CTL_DTEN0 BIT(2) /*!< DAC0 trigger enable/disable bit */ +#define DAC_CTL_DTSEL0 BITS(3,5) /*!< DAC0 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM0 BITS(6,7) /*!< DAC0 noise wave mode */ +#define DAC_CTL_DWBW0 BITS(8,11) /*!< DAC0 noise wave bit width */ +#define DAC_CTL_DDMAEN0 BIT(12) /*!< DAC0 DMA enable/disable bit */ +#define DAC_CTL_DDUDRIE0 BIT(13) /*!< DAC0 DMA underrun interrupt enable/disable bit */ +#define DAC_CTL_DEN1 BIT(16) /*!< DAC1 enable/disable bit */ +#define DAC_CTL_DBOFF1 BIT(17) /*!< DAC1 output buffer turn on/turn off bit */ +#define DAC_CTL_DTEN1 BIT(18) /*!< DAC1 trigger enable/disable bit */ +#define DAC_CTL_DTSEL1 BITS(19,21) /*!< DAC1 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM1 BITS(22,23) /*!< DAC1 noise wave mode */ +#define DAC_CTL_DWBW1 BITS(24,27) /*!< DAC1 noise wave bit width */ +#define DAC_CTL_DDMAEN1 BIT(28) /*!< DAC1 DMA enable/disable bit */ +#define DAC_CTL_DDUDRIE1 BIT(29) /*!< DAC1 DMA underrun interrupt enable/disable bit */ /* DAC_SWT */ -#define DAC_SWT_SWTR0 BIT(0) /*!< DAC0 software trigger bit, cleared by hardware */ -#define DAC_SWT_SWTR1 BIT(1) /*!< DAC1 software trigger bit, cleared by hardware */ +#define DAC_SWT_SWTR0 BIT(0) /*!< DAC0 software trigger bit, cleared by hardware */ +#define DAC_SWT_SWTR1 BIT(1) /*!< DAC1 software trigger bit, cleared by hardware */ /* DAC0_R12DH */ -#define DAC0_R12DH_DAC0_DH BITS(0,11) /*!< DAC0 12-bit right-aligned data bits */ +#define DAC0_R12DH_DAC0_DH BITS(0,11) /*!< DAC0 12-bit right-aligned data bits */ /* DAC0_L12DH */ -#define DAC0_L12DH_DAC0_DH BITS(4,15) /*!< DAC0 12-bit left-aligned data bits */ +#define DAC0_L12DH_DAC0_DH BITS(4,15) /*!< DAC0 12-bit left-aligned data bits */ /* DAC0_R8DH */ -#define DAC0_R8DH_DAC0_DH BITS(0,7) /*!< DAC0 8-bit right-aligned data bits */ +#define DAC0_R8DH_DAC0_DH BITS(0,7) /*!< DAC0 8-bit right-aligned data bits */ /* DAC1_R12DH */ -#define DAC1_R12DH_DAC1_DH BITS(0,11) /*!< DAC1 12-bit right-aligned data bits */ +#define DAC1_R12DH_DAC1_DH BITS(0,11) /*!< DAC1 12-bit right-aligned data bits */ /* DAC1_L12DH */ -#define DAC1_L12DH_DAC1_DH BITS(4,15) /*!< DAC1 12-bit left-aligned data bits */ +#define DAC1_L12DH_DAC1_DH BITS(4,15) /*!< DAC1 12-bit left-aligned data bits */ /* DAC1_R8DH */ -#define DAC1_R8DH_DAC1_DH BITS(0,7) /*!< DAC1 8-bit right-aligned data bits */ +#define DAC1_R8DH_DAC1_DH BITS(0,7) /*!< DAC1 8-bit right-aligned data bits */ /* DACC_R12DH */ -#define DACC_R12DH_DAC0_DH BITS(0,11) /*!< DAC concurrent mode DAC0 12-bit right-aligned data bits */ -#define DACC_R12DH_DAC1_DH BITS(16,27) /*!< DAC concurrent mode DAC1 12-bit right-aligned data bits */ +#define DACC_R12DH_DAC0_DH BITS(0,11) /*!< DAC concurrent mode DAC0 12-bit right-aligned data bits */ +#define DACC_R12DH_DAC1_DH BITS(16,27) /*!< DAC concurrent mode DAC1 12-bit right-aligned data bits */ /* DACC_L12DH */ -#define DACC_L12DH_DAC0_DH BITS(4,15) /*!< DAC concurrent mode DAC0 12-bit left-aligned data bits */ -#define DACC_L12DH_DAC1_DH BITS(20,31) /*!< DAC concurrent mode DAC1 12-bit left-aligned data bits */ +#define DACC_L12DH_DAC0_DH BITS(4,15) /*!< DAC concurrent mode DAC0 12-bit left-aligned data bits */ +#define DACC_L12DH_DAC1_DH BITS(20,31) /*!< DAC concurrent mode DAC1 12-bit left-aligned data bits */ /* DACC_R8DH */ -#define DACC_R8DH_DAC0_DH BITS(0,7) /*!< DAC concurrent mode DAC0 8-bit right-aligned data bits */ -#define DACC_R8DH_DAC1_DH BITS(16,23) /*!< DAC concurrent mode DAC1 8-bit right-aligned data bits */ +#define DACC_R8DH_DAC0_DH BITS(0,7) /*!< DAC concurrent mode DAC0 8-bit right-aligned data bits */ +#define DACC_R8DH_DAC1_DH BITS(8,15) /*!< DAC concurrent mode DAC1 8-bit right-aligned data bits */ /* DAC0_DO */ -#define DAC0_DO_DAC0_DO BITS(0,11) /*!< DAC0 12-bit output data bits */ +#define DAC0_DO_DAC0_DO BITS(0,11) /*!< DAC0 12-bit output data bits */ /* DAC1_DO */ -#define DAC1_DO_DAC1_DO BITS(0,11) /*!< DAC1 12-bit output data bits */ +#define DAC1_DO_DAC1_DO BITS(0,11) /*!< DAC1 12-bit output data bits */ /* DAC_STAT */ -#define DAC_STAT_DDUDR0 BIT(13) /*!< DAC0 DMA underrun flag */ -#define DAC_STAT_DDUDR1 BIT(29) /*!< DAC1 DMA underrun flag */ +#define DAC_STAT_DDUDR0 BIT(13) /*!< DAC0 DMA underrun flag */ +#define DAC_STAT_DDUDR1 BIT(29) /*!< DAC1 DMA underrun flag */ /* constants definitions */ /* DAC trigger source */ #define CTL_DTSEL(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) -#define DAC_TRIGGER_T5_TRGO CTL_DTSEL(0) /*!< TIMER5 TRGO */ -#define DAC_TRIGGER_T7_TRGO CTL_DTSEL(1) /*!< TIMER7 TRGO */ -#define DAC_TRIGGER_T6_TRGO CTL_DTSEL(2) /*!< TIMER6 TRGO */ -#define DAC_TRIGGER_T4_TRGO CTL_DTSEL(3) /*!< TIMER4 TRGO */ -#define DAC_TRIGGER_T1_TRGO CTL_DTSEL(4) /*!< TIMER1 TRGO */ -#define DAC_TRIGGER_T3_TRGO CTL_DTSEL(5) /*!< TIMER3 TRGO */ -#define DAC_TRIGGER_EXTI_9 CTL_DTSEL(6) /*!< EXTI interrupt line9 event */ -#define DAC_TRIGGER_SOFTWARE CTL_DTSEL(7) /*!< software trigger */ +#define DAC_TRIGGER_T5_TRGO CTL_DTSEL(0) /*!< TIMER5 TRGO */ +#define DAC_TRIGGER_T7_TRGO CTL_DTSEL(1) /*!< TIMER7 TRGO */ +#define DAC_TRIGGER_T6_TRGO CTL_DTSEL(2) /*!< TIMER6 TRGO */ +#define DAC_TRIGGER_T4_TRGO CTL_DTSEL(3) /*!< TIMER4 TRGO */ +#define DAC_TRIGGER_T1_TRGO CTL_DTSEL(4) /*!< TIMER1 TRGO */ +#define DAC_TRIGGER_T3_TRGO CTL_DTSEL(5) /*!< TIMER3 TRGO */ +#define DAC_TRIGGER_EXTI_9 CTL_DTSEL(6) /*!< EXTI interrupt line9 event */ +#define DAC_TRIGGER_SOFTWARE CTL_DTSEL(7) /*!< software trigger */ /* DAC noise wave mode */ #define CTL_DWM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) -#define DAC_WAVE_DISABLE CTL_DWM(0) /*!< wave disable */ -#define DAC_WAVE_MODE_LFSR CTL_DWM(1) /*!< LFSR noise mode */ -#define DAC_WAVE_MODE_TRIANGLE CTL_DWM(2) /*!< triangle noise mode */ +#define DAC_WAVE_DISABLE CTL_DWM(0) /*!< wave disable */ +#define DAC_WAVE_MODE_LFSR CTL_DWM(1) /*!< LFSR noise mode */ +#define DAC_WAVE_MODE_TRIANGLE CTL_DWM(2) /*!< triangle noise mode */ /* DAC noise wave bit width */ #define DWBW(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) -#define DAC_WAVE_BIT_WIDTH_1 DWBW(0) /*!< bit width of the wave signal is 1 */ -#define DAC_WAVE_BIT_WIDTH_2 DWBW(1) /*!< bit width of the wave signal is 2 */ -#define DAC_WAVE_BIT_WIDTH_3 DWBW(2) /*!< bit width of the wave signal is 3 */ -#define DAC_WAVE_BIT_WIDTH_4 DWBW(3) /*!< bit width of the wave signal is 4 */ -#define DAC_WAVE_BIT_WIDTH_5 DWBW(4) /*!< bit width of the wave signal is 5 */ -#define DAC_WAVE_BIT_WIDTH_6 DWBW(5) /*!< bit width of the wave signal is 6 */ -#define DAC_WAVE_BIT_WIDTH_7 DWBW(6) /*!< bit width of the wave signal is 7 */ -#define DAC_WAVE_BIT_WIDTH_8 DWBW(7) /*!< bit width of the wave signal is 8 */ -#define DAC_WAVE_BIT_WIDTH_9 DWBW(8) /*!< bit width of the wave signal is 9 */ -#define DAC_WAVE_BIT_WIDTH_10 DWBW(9) /*!< bit width of the wave signal is 10 */ -#define DAC_WAVE_BIT_WIDTH_11 DWBW(10) /*!< bit width of the wave signal is 11 */ -#define DAC_WAVE_BIT_WIDTH_12 DWBW(11) /*!< bit width of the wave signal is 12 */ +#define DAC_WAVE_BIT_WIDTH_1 DWBW(0) /*!< bit width of the wave signal is 1 */ +#define DAC_WAVE_BIT_WIDTH_2 DWBW(1) /*!< bit width of the wave signal is 2 */ +#define DAC_WAVE_BIT_WIDTH_3 DWBW(2) /*!< bit width of the wave signal is 3 */ +#define DAC_WAVE_BIT_WIDTH_4 DWBW(3) /*!< bit width of the wave signal is 4 */ +#define DAC_WAVE_BIT_WIDTH_5 DWBW(4) /*!< bit width of the wave signal is 5 */ +#define DAC_WAVE_BIT_WIDTH_6 DWBW(5) /*!< bit width of the wave signal is 6 */ +#define DAC_WAVE_BIT_WIDTH_7 DWBW(6) /*!< bit width of the wave signal is 7 */ +#define DAC_WAVE_BIT_WIDTH_8 DWBW(7) /*!< bit width of the wave signal is 8 */ +#define DAC_WAVE_BIT_WIDTH_9 DWBW(8) /*!< bit width of the wave signal is 9 */ +#define DAC_WAVE_BIT_WIDTH_10 DWBW(9) /*!< bit width of the wave signal is 10 */ +#define DAC_WAVE_BIT_WIDTH_11 DWBW(10) /*!< bit width of the wave signal is 11 */ +#define DAC_WAVE_BIT_WIDTH_12 DWBW(11) /*!< bit width of the wave signal is 12 */ /* unmask LFSR bits in DAC LFSR noise mode */ -#define DAC_LFSR_BIT0 DAC_WAVE_BIT_WIDTH_1 /*!< unmask the LFSR bit0 */ -#define DAC_LFSR_BITS1_0 DAC_WAVE_BIT_WIDTH_2 /*!< unmask the LFSR bits[1:0] */ -#define DAC_LFSR_BITS2_0 DAC_WAVE_BIT_WIDTH_3 /*!< unmask the LFSR bits[2:0] */ -#define DAC_LFSR_BITS3_0 DAC_WAVE_BIT_WIDTH_4 /*!< unmask the LFSR bits[3:0] */ -#define DAC_LFSR_BITS4_0 DAC_WAVE_BIT_WIDTH_5 /*!< unmask the LFSR bits[4:0] */ -#define DAC_LFSR_BITS5_0 DAC_WAVE_BIT_WIDTH_6 /*!< unmask the LFSR bits[5:0] */ -#define DAC_LFSR_BITS6_0 DAC_WAVE_BIT_WIDTH_7 /*!< unmask the LFSR bits[6:0] */ -#define DAC_LFSR_BITS7_0 DAC_WAVE_BIT_WIDTH_8 /*!< unmask the LFSR bits[7:0] */ -#define DAC_LFSR_BITS8_0 DAC_WAVE_BIT_WIDTH_9 /*!< unmask the LFSR bits[8:0] */ -#define DAC_LFSR_BITS9_0 DAC_WAVE_BIT_WIDTH_10 /*!< unmask the LFSR bits[9:0] */ -#define DAC_LFSR_BITS10_0 DAC_WAVE_BIT_WIDTH_11 /*!< unmask the LFSR bits[10:0] */ -#define DAC_LFSR_BITS11_0 DAC_WAVE_BIT_WIDTH_12 /*!< unmask the LFSR bits[11:0] */ - -/* triangle amplitude in DAC triangle noise mode */ -#define DAC_TRIANGLE_AMPLITUDE_1 DAC_WAVE_BIT_WIDTH_1 /*!< triangle amplitude is 1 */ -#define DAC_TRIANGLE_AMPLITUDE_3 DAC_WAVE_BIT_WIDTH_2 /*!< triangle amplitude is 3 */ -#define DAC_TRIANGLE_AMPLITUDE_7 DAC_WAVE_BIT_WIDTH_3 /*!< triangle amplitude is 7 */ -#define DAC_TRIANGLE_AMPLITUDE_15 DAC_WAVE_BIT_WIDTH_4 /*!< triangle amplitude is 15 */ -#define DAC_TRIANGLE_AMPLITUDE_31 DAC_WAVE_BIT_WIDTH_5 /*!< triangle amplitude is 31 */ -#define DAC_TRIANGLE_AMPLITUDE_63 DAC_WAVE_BIT_WIDTH_6 /*!< triangle amplitude is 63 */ -#define DAC_TRIANGLE_AMPLITUDE_127 DAC_WAVE_BIT_WIDTH_7 /*!< triangle amplitude is 127 */ -#define DAC_TRIANGLE_AMPLITUDE_255 DAC_WAVE_BIT_WIDTH_8 /*!< triangle amplitude is 255 */ -#define DAC_TRIANGLE_AMPLITUDE_511 DAC_WAVE_BIT_WIDTH_9 /*!< triangle amplitude is 511 */ -#define DAC_TRIANGLE_AMPLITUDE_1023 DAC_WAVE_BIT_WIDTH_10 /*!< triangle amplitude is 1023 */ -#define DAC_TRIANGLE_AMPLITUDE_2047 DAC_WAVE_BIT_WIDTH_11 /*!< triangle amplitude is 2047 */ -#define DAC_TRIANGLE_AMPLITUDE_4095 DAC_WAVE_BIT_WIDTH_12 /*!< triangle amplitude is 4095 */ +#define DAC_LFSR_BIT0 DAC_WAVE_BIT_WIDTH_1 /*!< unmask the LFSR bit0 */ +#define DAC_LFSR_BITS1_0 DAC_WAVE_BIT_WIDTH_2 /*!< unmask the LFSR bits[1:0] */ +#define DAC_LFSR_BITS2_0 DAC_WAVE_BIT_WIDTH_3 /*!< unmask the LFSR bits[2:0] */ +#define DAC_LFSR_BITS3_0 DAC_WAVE_BIT_WIDTH_4 /*!< unmask the LFSR bits[3:0] */ +#define DAC_LFSR_BITS4_0 DAC_WAVE_BIT_WIDTH_5 /*!< unmask the LFSR bits[4:0] */ +#define DAC_LFSR_BITS5_0 DAC_WAVE_BIT_WIDTH_6 /*!< unmask the LFSR bits[5:0] */ +#define DAC_LFSR_BITS6_0 DAC_WAVE_BIT_WIDTH_7 /*!< unmask the LFSR bits[6:0] */ +#define DAC_LFSR_BITS7_0 DAC_WAVE_BIT_WIDTH_8 /*!< unmask the LFSR bits[7:0] */ +#define DAC_LFSR_BITS8_0 DAC_WAVE_BIT_WIDTH_9 /*!< unmask the LFSR bits[8:0] */ +#define DAC_LFSR_BITS9_0 DAC_WAVE_BIT_WIDTH_10 /*!< unmask the LFSR bits[9:0] */ +#define DAC_LFSR_BITS10_0 DAC_WAVE_BIT_WIDTH_11 /*!< unmask the LFSR bits[10:0] */ +#define DAC_LFSR_BITS11_0 DAC_WAVE_BIT_WIDTH_12 /*!< unmask the LFSR bits[11:0] */ /* DAC data alignment */ #define DATA_ALIGN(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) -#define DAC_ALIGN_12B_R DATA_ALIGN(0) /*!< data right 12b alignment */ -#define DAC_ALIGN_12B_L DATA_ALIGN(1) /*!< data left 12b alignment */ -#define DAC_ALIGN_8B_R DATA_ALIGN(2) /*!< data right 8b alignment */ +#define DAC_ALIGN_12B_R DATA_ALIGN(0) /*!< data right 12 bit alignment */ +#define DAC_ALIGN_12B_L DATA_ALIGN(1) /*!< data left 12 bit alignment */ +#define DAC_ALIGN_8B_R DATA_ALIGN(2) /*!< data right 8 bit alignment */ + +/* triangle amplitude in DAC triangle noise mode */ +#define DAC_TRIANGLE_AMPLITUDE_1 DAC_WAVE_BIT_WIDTH_1 /*!< triangle amplitude is 1 */ +#define DAC_TRIANGLE_AMPLITUDE_3 DAC_WAVE_BIT_WIDTH_2 /*!< triangle amplitude is 3 */ +#define DAC_TRIANGLE_AMPLITUDE_7 DAC_WAVE_BIT_WIDTH_3 /*!< triangle amplitude is 7 */ +#define DAC_TRIANGLE_AMPLITUDE_15 DAC_WAVE_BIT_WIDTH_4 /*!< triangle amplitude is 15 */ +#define DAC_TRIANGLE_AMPLITUDE_31 DAC_WAVE_BIT_WIDTH_5 /*!< triangle amplitude is 31 */ +#define DAC_TRIANGLE_AMPLITUDE_63 DAC_WAVE_BIT_WIDTH_6 /*!< triangle amplitude is 63 */ +#define DAC_TRIANGLE_AMPLITUDE_127 DAC_WAVE_BIT_WIDTH_7 /*!< triangle amplitude is 127 */ +#define DAC_TRIANGLE_AMPLITUDE_255 DAC_WAVE_BIT_WIDTH_8 /*!< triangle amplitude is 255 */ +#define DAC_TRIANGLE_AMPLITUDE_511 DAC_WAVE_BIT_WIDTH_9 /*!< triangle amplitude is 511 */ +#define DAC_TRIANGLE_AMPLITUDE_1023 DAC_WAVE_BIT_WIDTH_10 /*!< triangle amplitude is 1023 */ +#define DAC_TRIANGLE_AMPLITUDE_2047 DAC_WAVE_BIT_WIDTH_11 /*!< triangle amplitude is 2047 */ +#define DAC_TRIANGLE_AMPLITUDE_4095 DAC_WAVE_BIT_WIDTH_12 /*!< triangle amplitude is 4095 */ /* function declarations */ +/* initialization functions */ /* deinitialize DAC */ void dac_deinit(void); /* enable DAC */ @@ -175,26 +201,29 @@ void dac_disable(uint32_t dac_periph); /* enable DAC DMA */ void dac_dma_enable(uint32_t dac_periph); /* disable DAC DMA */ -void dac_dma_disable(uint32_t dac_periph); +void dac_dma_disable(uint32_t dac_periph); /* enable DAC output buffer */ void dac_output_buffer_enable(uint32_t dac_periph); /* disable DAC output buffer */ void dac_output_buffer_disable(uint32_t dac_periph); +/* get the last data output value */ +uint16_t dac_output_value_get(uint32_t dac_periph); +/* set DAC data holding register value */ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data); + +/* DAC trigger configuration */ /* enable DAC trigger */ void dac_trigger_enable(uint32_t dac_periph); /* disable DAC trigger */ void dac_trigger_disable(uint32_t dac_periph); +/* configure DAC trigger source */ +void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource); /* enable DAC software trigger */ void dac_software_trigger_enable(uint32_t dac_periph); /* disable DAC software trigger */ void dac_software_trigger_disable(uint32_t dac_periph); -/* enable DAC interrupt(DAC0 DMA underrun interrupt) */ -void dac_interrupt_enable(uint32_t dac_periph); -/* disable DAC interrupt(DAC0 DMA underrun interrupt) */ -void dac_interrupt_disable(uint32_t dac_periph); -/* configure DAC trigger source */ -void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource); +/* DAC wave mode configuration */ /* configure DAC wave mode */ void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode); /* configure DAC wave bit width */ @@ -203,14 +232,8 @@ void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width); void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits); /* configure DAC triangle noise mode */ void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude); -/* get the last data output value */ -uint16_t dac_output_value_get(uint32_t dac_periph); - -/* set DAC data holding register value */ -void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data); -/* set DAC concurrent mode data holding register value */ -void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1); +/* DAC concurrent mode configuration */ /* enable DAC concurrent mode */ void dac_concurrent_enable(void); /* disable DAC concurrent mode */ @@ -223,11 +246,18 @@ void dac_concurrent_software_trigger_disable(void); void dac_concurrent_output_buffer_enable(void); /* disable DAC concurrent buffer function */ void dac_concurrent_output_buffer_disable(void); +/* set DAC concurrent mode data holding register value */ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1); /* enable DAC concurrent interrupt */ void dac_concurrent_interrupt_enable(void); /* disable DAC concurrent interrupt */ void dac_concurrent_interrupt_disable(void); +/* DAC interrupt configuration */ +/* enable DAC interrupt(DAC DMA underrun interrupt) */ +void dac_interrupt_enable(uint32_t dac_periph); +/* disable DAC interrupt(DAC DMA underrun interrupt) */ +void dac_interrupt_disable(uint32_t dac_periph); /* get the specified DAC flag(DAC DMA underrun flag) */ FlagStatus dac_flag_get(uint32_t dac_periph); /* clear the specified DAC flag(DAC DMA underrun flag) */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h index 273b13e7fb..fde91597f7 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_dbg.h - \brief definitions for the DBG + \file gd32f4xx_dbg.h + \brief definitions for the DBG + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_DBG_H @@ -65,30 +90,43 @@ #define DBG_LOW_POWER_DEEPSLEEP DBG_CTL0_DSLP_HOLD /*!< keep debugger connection during deepsleep mode */ #define DBG_LOW_POWER_STANDBY DBG_CTL0_STB_HOLD /*!< keep debugger connection during standby mode */ +/* define the peripheral debug hold bit position and its register index offset */ +#define DBG_REGIDX_BIT(regidx, bitpos) (((regidx) << 6) | (bitpos)) +#define DBG_REG_VAL(periph) (REG32(DBG + ((uint32_t)(periph) >> 6))) +#define DBG_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* register index */ +enum dbg_reg_idx +{ + DBG_IDX_CTL0 = 0x04U, + DBG_IDX_CTL1 = 0x08U, + DBG_IDX_CTL2 = 0x0CU +}; + typedef enum { - DBG_TIMER1_HOLD = BIT(0), /*!< hold TIMER1 counter when core is halted */ - DBG_TIMER2_HOLD = BIT(1), /*!< hold TIMER2 counter when core is halted */ - DBG_TIMER3_HOLD = BIT(2), /*!< hold TIMER3 counter when core is halted */ - DBG_TIMER4_HOLD = BIT(3), /*!< hold TIMER4 counter when core is halted */ - DBG_TIMER5_HOLD = BIT(4), /*!< hold TIMER5 counter when core is halted */ - DBG_TIMER6_HOLD = BIT(5), /*!< hold TIMER6 counter when core is halted */ - DBG_TIMER11_HOLD = BIT(6), /*!< hold TIMER11 counter when core is halted */ - DBG_TIMER12_HOLD = BIT(7), /*!< hold TIMER12 counter when core is halted */ - DBG_TIMER13_HOLD = BIT(8), /*!< hold TIMER13 counter when core is halted */ - DBG_RTC_HOLD = BIT(10), /*!< hold RTC calendar and wakeup counter when core is halted */ - DBG_WWDGT_HOLD = BIT(11), /*!< debug WWDGT kept when core is halted */ - DBG_FWDGT_HOLD = BIT(12), /*!< debug FWDGT kept when core is halted */ - DBG_I2C0_HOLD = BIT(21), /*!< hold I2C0 smbus when core is halted */ - DBG_I2C1_HOLD = BIT(22), /*!< hold I2C1 smbus when core is halted */ - DBG_I2C2_HOLD = BIT(23), /*!< hold I2C2 smbus when core is halted */ - DBG_CAN0_HOLD = BIT(25), /*!< debug CAN0 kept when core is halted */ - DBG_CAN1_HOLD = BIT(26), /*!< debug CAN1 kept when core is halted */ - DBG_TIMER0_HOLD = (BIT(0) | BIT(30)), /*!< hold TIMER0 counter when core is halted */ - DBG_TIMER7_HOLD = (BIT(1) | BIT(30)), /*!< hold TIMER7 counter when core is halted */ - DBG_TIMER8_HOLD = (BIT(16) | BIT(30)), /*!< hold TIMER8 counter when core is halted */ - DBG_TIMER9_HOLD = (BIT(17) | BIT(30)), /*!< hold TIMER9 counter when core is halted */ - DBG_TIMER10_HOLD = (BIT(18) | BIT(30)), /*!< hold TIMER10 counter when core is halted */ + DBG_TIMER1_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 0U), /*!< hold TIMER1 counter when core is halted */ + DBG_TIMER2_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 1U), /*!< hold TIMER2 counter when core is halted */ + DBG_TIMER3_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 2U), /*!< hold TIMER3 counter when core is halted */ + DBG_TIMER4_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 3U), /*!< hold TIMER4 counter when core is halted */ + DBG_TIMER5_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 4U), /*!< hold TIMER5 counter when core is halted */ + DBG_TIMER6_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 5U), /*!< hold TIMER6 counter when core is halted */ + DBG_TIMER11_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 6U), /*!< hold TIMER11 counter when core is halted */ + DBG_TIMER12_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 7U), /*!< hold TIMER12 counter when core is halted */ + DBG_TIMER13_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 8U), /*!< hold TIMER13 counter when core is halted */ + DBG_RTC_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 10U), /*!< hold RTC calendar and wakeup counter when core is halted */ + DBG_WWDGT_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 11U), /*!< debug WWDGT kept when core is halted */ + DBG_FWDGT_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 12U), /*!< debug FWDGT kept when core is halted */ + DBG_I2C0_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 21U), /*!< hold I2C0 smbus when core is halted */ + DBG_I2C1_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 22U), /*!< hold I2C1 smbus when core is halted */ + DBG_I2C2_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 23U), /*!< hold I2C2 smbus when core is halted */ + DBG_CAN0_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 25U), /*!< debug CAN0 kept when core is halted */ + DBG_CAN1_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL1, 26U), /*!< debug CAN1 kept when core is halted */ + DBG_TIMER0_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL2, 0U), /*!< hold TIMER0 counter when core is halted */ + DBG_TIMER7_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL2, 1U), /*!< hold TIMER7 counter when core is halted */ + DBG_TIMER8_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL2, 16U), /*!< hold TIMER8 counter when core is halted */ + DBG_TIMER9_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL2, 17U), /*!< hold TIMER9 counter when core is halted */ + DBG_TIMER10_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL2, 18U) /*!< hold TIMER10 counter when core is halted */ }dbg_periph_enum; #define CTL0_TRACE_MODE(regval) (BITS(6,7)&((uint32_t)(regval)<<6)) @@ -98,6 +136,8 @@ typedef enum #define TRACE_MODE_SYNC_DATASIZE_4 CTL0_TRACE_MODE(3) /*!< trace pin used for sync mode and data size is 4 */ /* function declarations */ +/* deinitialize the DBG */ +void dbg_deinit(void); /* read DBG_ID code register */ uint32_t dbg_id_get(void); diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h index 7c9b445138..4986d5afd4 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_dci.h - \brief definitions for the DCI + \file gd32f4xx_dci.h + \brief definitions for the DCI + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_DCI_H @@ -32,17 +57,17 @@ /* bits definitions */ /* DCI_CTL */ -#define DCI_CTL_CAP BIT(0) /*!< capture enable */ -#define DCI_CTL_SNAP BIT(1) /*!< snapshot mode */ -#define DCI_CTL_WDEN BIT(2) /*!< window enable */ -#define DCI_CTL_JM BIT(3) /*!< jpeg mode */ -#define DCI_CTL_ESM BIT(4) /*!< embedded synchronous mode */ -#define DCI_CTL_CKS BIT(5) /*!< clock polarity selection */ -#define DCI_CTL_HPS BIT(6) /*!< horizontal polarity selection */ -#define DCI_CTL_VPS BIT(7) /*!< vertical polarity selection */ -#define DCI_CTL_FR BITS(8,9) /*!< frame rate */ -#define DCI_CTL_DCIF BITS(10,11) /*!< digital camera interface format */ -#define DCI_CTL_DCIEN BIT(14) /*!< dci enable */ +#define DCI_CTL_CAP BIT(0) /*!< capture enable */ +#define DCI_CTL_SNAP BIT(1) /*!< snapshot mode */ +#define DCI_CTL_WDEN BIT(2) /*!< window enable */ +#define DCI_CTL_JM BIT(3) /*!< JPEG mode */ +#define DCI_CTL_ESM BIT(4) /*!< embedded synchronous mode */ +#define DCI_CTL_CKS BIT(5) /*!< clock polarity selection */ +#define DCI_CTL_HPS BIT(6) /*!< horizontal polarity selection */ +#define DCI_CTL_VPS BIT(7) /*!< vertical polarity selection */ +#define DCI_CTL_FR BITS(8,9) /*!< frame rate */ +#define DCI_CTL_DCIF BITS(10,11) /*!< digital camera interface format */ +#define DCI_CTL_DCIEN BIT(14) /*!< DCI enable */ /* DCI_STAT0 */ #define DCI_STAT0_HS BIT(0) /*!< HS line status */ @@ -98,16 +123,16 @@ #define DCI_CWSZ_WVSZ BITS(16,29) /*!< window vertical size */ /* constants definitions */ -/* DCI parameter struct definitions */ +/* DCI parameter structure definitions */ typedef struct -{ +{ uint32_t capture_mode; /*!< DCI capture mode: continuous or snapshot */ uint32_t clock_polarity; /*!< clock polarity selection */ uint32_t hsync_polarity; /*!< horizontal polarity selection */ uint32_t vsync_polarity; /*!< vertical polarity selection */ uint32_t frame_rate; /*!< frame capture rate */ uint32_t interface_format; /*!< digital camera interface format */ -}dci_parameter_struct; +}dci_parameter_struct; #define DCI_CAPTURE_MODE_CONTINUOUS ((uint32_t)0x00000000U) /*!< continuous capture mode */ #define DCI_CAPTURE_MODE_SNAPSHOT DCI_CTL_SNAP /*!< snapshot capture mode */ @@ -120,36 +145,44 @@ typedef struct #define DCI_VSYNC_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level during blanking period */ #define DCI_VSYNC_POLARITY_HIGH DCI_CTL_VPS /*!< high level during blanking period*/ - -#define CTL_FR(regval) (BITS(8,9)&((uint32_t)(regval) << 8U)) + +#define CTL_FR(regval) (BITS(8,9)&((uint32_t)(regval) << 8U)) #define DCI_FRAME_RATE_ALL CTL_FR(0) /*!< capture all frames */ #define DCI_FRAME_RATE_1_2 CTL_FR(1) /*!< capture one in 2 frames */ #define DCI_FRAME_RATE_1_4 CTL_FR(2) /*!< capture one in 4 frames */ -#define CTL_DCIF(regval) (BITS(10,11)&((uint32_t)(regval) << 10U)) +#define CTL_DCIF(regval) (BITS(10,11)&((uint32_t)(regval) << 10U)) #define DCI_INTERFACE_FORMAT_8BITS CTL_DCIF(0) /*!< 8-bit data on every pixel clock */ #define DCI_INTERFACE_FORMAT_10BITS CTL_DCIF(1) /*!< 10-bit data on every pixel clock */ #define DCI_INTERFACE_FORMAT_12BITS CTL_DCIF(2) /*!< 12-bit data on every pixel clock */ #define DCI_INTERFACE_FORMAT_14BITS CTL_DCIF(3) /*!< 14-bit data on every pixel clock */ /* DCI interrupt constants definitions */ -#define DCI_INT_EF ((uint32_t)0x00000001U) /*!< end of frame interrupt */ -#define DCI_INT_OVR ((uint32_t)0x00000002U) /*!< FIFO overrun interrupt */ -#define DCI_INT_ESE ((uint32_t)0x00000004U) /*!< embedded synchronous error interrupt */ -#define DCI_INT_VS ((uint32_t)0x00000008U) /*!< vsync interrupt */ -#define DCI_INT_EL ((uint32_t)0x00000010U) /*!< end of line interrupt */ +#define DCI_INT_EF BIT(0) /*!< end of frame interrupt */ +#define DCI_INT_OVR BIT(1) /*!< FIFO overrun interrupt */ +#define DCI_INT_ESE BIT(2) /*!< embedded synchronous error interrupt */ +#define DCI_INT_VSYNC BIT(3) /*!< vsync interrupt */ +#define DCI_INT_EL BIT(4) /*!< end of line interrupt */ -/* DCI flag definitions */ -#define DCI_FLAG_HS ((uint8_t)0x01U) /*!< HS line status */ -#define DCI_FLAG_VS ((uint8_t)0x02U) /*!< VS line status */ -#define DCI_FLAG_FV ((uint8_t)0x03U) /*!< FIFO valid */ -#define DCI_FLAG_EFF ((uint8_t)0x04U) /*!< end of frame flag */ -#define DCI_FLAG_OVRF ((uint8_t)0x05U) /*!< FIFO overrun flag */ -#define DCI_FLAG_ESEF ((uint8_t)0x06U) /*!< embedded synchronous error flag */ -#define DCI_FLAG_VSF ((uint8_t)0x07U) /*!< vsync flag */ -#define DCI_FLAG_ELF ((uint8_t)0x08U) /*!< end of line flag */ +/* DCI interrupt flag definitions */ +#define DCI_INT_FLAG_EF BIT(0) /*!< end of frame interrupt flag */ +#define DCI_INT_FLAG_OVR BIT(1) /*!< FIFO overrun interrupt flag */ +#define DCI_INT_FLAG_ESE BIT(2) /*!< embedded synchronous error interrupt flag */ +#define DCI_INT_FLAG_VSYNC BIT(3) /*!< vsync interrupt flag */ +#define DCI_INT_FLAG_EL BIT(4) /*!< end of line interrupt flag */ + +/* DCI flag definitions */ +#define DCI_FLAG_HS DCI_STAT0_HS /*!< HS line status */ +#define DCI_FLAG_VS DCI_STAT0_VS /*!< VS line status */ +#define DCI_FLAG_FV DCI_STAT0_FV /*!< FIFO valid */ +#define DCI_FLAG_EF (DCI_STAT1_EFF | BIT(31)) /*!< end of frame flag */ +#define DCI_FLAG_OVR (DCI_STAT1_OVRF | BIT(31)) /*!< FIFO overrun flag */ +#define DCI_FLAG_ESE (DCI_STAT1_ESEF | BIT(31)) /*!< embedded synchronous error flag */ +#define DCI_FLAG_VSYNC (DCI_STAT1_VSF | BIT(31)) /*!< vsync flag */ +#define DCI_FLAG_EL (DCI_STAT1_ELF | BIT(31)) /*!< end of line flag */ /* function declarations */ +/* initialization functions */ /* DCI deinit */ void dci_deinit(void); /* initialize DCI registers */ @@ -157,44 +190,49 @@ void dci_init(dci_parameter_struct* dci_struct); /* enable DCI function */ void dci_enable(void); -/* disble DCI function */ +/* disable DCI function */ void dci_disable(void); /* enable DCI capture */ void dci_capture_enable(void); -/* disble DCI capture */ +/* disable DCI capture */ void dci_capture_disable(void); /* enable DCI jpeg mode */ void dci_jpeg_enable(void); -/* disble DCI jpeg mode */ +/* disable DCI jpeg mode */ void dci_jpeg_disable(void); +/* function configuration */ /* enable cropping window function */ void dci_crop_window_enable(void); -/* disble cropping window function */ +/* disable cropping window function */ void dci_crop_window_disable(void); -/* config DCI cropping window */ +/* configure DCI cropping window */ void dci_crop_window_config(uint16_t start_x, uint16_t start_y, uint16_t size_width, uint16_t size_height); -/* enable sync codes function */ -void dci_sync_codes_enable(void); -/* disble sync codes function */ -void dci_sync_codes_disable(void); -/* config sync codes */ +/* enable embedded synchronous mode */ +void dci_embedded_sync_enable(void); +/* disable embedded synchronous mode */ +void dci_embedded_sync_disable(void); +/* configure synchronous codes in embedded synchronous mode */ void dci_sync_codes_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end); -/* config sync codes unmask */ +/* configure synchronous codes unmask in embedded synchronous mode */ void dci_sync_codes_unmask_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end); /* read DCI data register */ uint32_t dci_data_read(void); -/* enable specified DCI interrupt */ -void dci_interrupt_enable(uint32_t interrupt); -/* disble specified DCI interrupt */ -void dci_interrupt_disable(uint32_t interrupt); -/* clear specified interrupt */ -void dci_interrupt_clear(uint32_t interrupt); +/* interrupt & flag functions */ /* get specified flag */ FlagStatus dci_flag_get(uint32_t flag); +/* enable specified DCI interrupt */ +void dci_interrupt_enable(uint32_t interrupt); +/* disable specified DCI interrupt */ +void dci_interrupt_disable(uint32_t interrupt); + + /* get specified interrupt flag */ -FlagStatus dci_interrupt_flag_get(uint32_t interrupt); +FlagStatus dci_interrupt_flag_get(uint32_t int_flag); +/* clear specified interrupt flag */ +void dci_interrupt_flag_clear(uint32_t int_flag); + #endif /* GD32F4XX_DCI_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h index be59a229f6..cac70b85eb 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_dma.h - \brief definitions for the DMA + \file gd32f4xx_dma.c + \brief definitions for the DMA + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_DMA_H @@ -123,10 +148,10 @@ #define DMA_CHXPADDR_PADDR BITS(0,31) /*!< peripheral base address */ /* DMA_CHxM0ADDR,x=0..7 */ -#define DMA_CHXM0ADDR_PADDR BITS(0,31) /*!< memory 0 base address */ +#define DMA_CHXM0ADDR_M0ADDR BITS(0,31) /*!< memory 0 base address */ /* DMA_CHxM1ADDR,x=0..7 */ -#define DMA_CHXM1ADDR_PADDR BITS(0,31) /*!< memory 1 base address */ +#define DMA_CHXM1ADDR_M0ADDR BITS(0,31) /*!< memory 1 base address */ /* DMA_CHxFCTL,x=0..7 */ #define DMA_CHXFCTL_FCCV BITS(0,1) /*!< FIFO counter critical value */ @@ -136,7 +161,7 @@ /* constants definitions */ /* DMA channel select */ -typedef enum +typedef enum { DMA_CH0 = 0, /*!< DMA Channel 0 */ DMA_CH1, /*!< DMA Channel 1 */ @@ -149,7 +174,7 @@ typedef enum } dma_channel_enum; /* DMA peripheral select */ -typedef enum +typedef enum { DMA_SUBPERI0 = 0, /*!< DMA Peripheral 0 */ DMA_SUBPERI1, /*!< DMA Peripheral 1 */ @@ -166,7 +191,7 @@ typedef struct { uint32_t periph_addr; /*!< peripheral base address */ uint32_t periph_width; /*!< transfer data size of peripheral */ - uint32_t periph_inc; /*!< peripheral increasing mode */ + uint32_t periph_inc; /*!< peripheral increasing mode */ uint32_t memory0_addr; /*!< memory 0 base address */ uint32_t memory_width; /*!< transfer data size of memory */ @@ -176,7 +201,7 @@ typedef struct uint32_t periph_burst_width; /*!< multi data mode enable */ uint32_t critical_value; /*!< FIFO critical */ - uint32_t circular_mode; + uint32_t circular_mode; /*!< DMA circular mode */ uint32_t direction; /*!< channel data transfer direction */ uint32_t number; /*!< channel transfer number */ uint32_t priority; /*!< channel priority level */ @@ -186,7 +211,7 @@ typedef struct typedef struct { uint32_t periph_addr; /*!< peripheral base address */ - uint32_t periph_inc; /*!< peripheral increasing mode */ + uint32_t periph_inc; /*!< peripheral increasing mode */ uint32_t memory0_addr; /*!< memory 0 base address */ uint32_t memory_inc; /*!< memory increasing mode */ @@ -296,85 +321,108 @@ typedef struct #define DMA_FIFO_STATUS_FULL ((uint32_t)0x00000005U) /*!< the data in the FIFO is full */ /* DMA reset value */ -#define DMA_CHCTL_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCTL register */ -#define DMA_CHCNT_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCNT register */ -#define DMA_CHPADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXPADDR register */ -#define DMA_CHMADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXMADDR register */ -#define DMA_CHINTF_RESET_VALUE ((uint32_t)0x0000003DU) /*!< clear DMA channel CHXINTFS register */ -#define DMA_CHFCTL_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXFCTL register */ +#define DMA_CHCTL_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCTL register */ +#define DMA_CHCNT_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCNT register */ +#define DMA_CHPADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXPADDR register */ +#define DMA_CHMADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXMADDR register */ +#define DMA_CHINTF_RESET_VALUE ((uint32_t)0x0000003DU) /*!< clear DMA channel CHXINTFS register */ +#define DMA_CHFCTL_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXFCTL register */ + +/* DMA_INTF register */ +/* interrupt flag bits */ +#define DMA_INT_FLAG_FEE DMA_INTF_FEEIF /*!< FIFO error and exception flag */ +#define DMA_INT_FLAG_SDE DMA_INTF_SDEIF /*!< single data mode exception flag */ +#define DMA_INT_FLAG_TAE DMA_INTF_TAEIF /*!< transfer access error flag */ +#define DMA_INT_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish flag */ +#define DMA_INT_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish flag */ + +/* flag bits */ +#define DMA_FLAG_FEE DMA_INTF_FEEIF /*!< FIFO error and exception flag */ +#define DMA_FLAG_SDE DMA_INTF_SDEIF /*!< single data mode exception flag */ +#define DMA_FLAG_TAE DMA_INTF_TAEIF /*!< transfer access error flag */ +#define DMA_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish flag */ +#define DMA_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish flag */ + /* function declarations */ +/* DMA deinitialization and initialization functions */ /* deinitialize DMA a channel registers */ -void dma_deinit(uint32_t dma_periph,dma_channel_enum channelx); +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx); +/* initialize the DMA single data mode parameters struct with the default values */ +void dma_single_data_para_struct_init(dma_single_data_parameter_struct* init_struct); +/* initialize the DMA multi data mode parameters struct with the default values */ +void dma_multi_data_para_struct_init(dma_multi_data_parameter_struct* init_struct); /* DMA single data mode initialize */ -void dma_single_data_mode_init(uint32_t dma_periph,dma_channel_enum channelx,dma_single_data_parameter_struct init_struct); +void dma_single_data_mode_init(uint32_t dma_periph, dma_channel_enum channelx, dma_single_data_parameter_struct* init_struct); /* DMA multi data mode initialize */ -void dma_multi_data_mode_init(uint32_t dma_periph,dma_channel_enum channelx,dma_multi_data_parameter_struct init_struct); +void dma_multi_data_mode_init(uint32_t dma_periph, dma_channel_enum channelx, dma_multi_data_parameter_struct* init_struct); +/* DMA configuration functions */ /* set DMA peripheral base address */ -void dma_periph_address_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t address); +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); /* set DMA Memory base address */ -void dma_memory_address_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t memory_flag,uint32_t address); +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t memory_flag, uint32_t address); /* set the number of remaining data to be transferred by the DMA */ -void dma_transfer_number_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t number); +void dma_transfer_number_config(uint32_t dma_periph,dma_channel_enum channelx, uint32_t number); /* get the number of remaining data to be transferred by the DMA */ -uint32_t dma_transfer_number_get(uint32_t dma_periph,dma_channel_enum channelx); +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx); /* configure priority level of DMA channel */ -void dma_priority_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t priority); +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority); /* configure transfer burst beats of memory */ -void dma_memory_burst_beats_config (uint32_t dma_periph,dma_channel_enum channelx,uint32_t mbeat); +void dma_memory_burst_beats_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t mbeat); /* configure transfer burst beats of peripheral */ -void dma_periph_burst_beats_config (uint32_t dma_periph,dma_channel_enum channelx,uint32_t pbeat); +void dma_periph_burst_beats_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t pbeat); /* configure transfer data size of memory */ -void dma_memory_width_config (uint32_t dma_periph,dma_channel_enum channelx,uint32_t msize); +void dma_memory_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t msize); /* configure transfer data size of peripheral */ -void dma_periph_width_config (uint32_t dma_periph,dma_channel_enum channelx,uint32_t psize); +void dma_periph_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t psize); /* configure next address increasement algorithm of memory */ -void dma_memory_address_generation_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t generation_algorithm); +void dma_memory_address_generation_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t generation_algorithm); /* configure next address increasement algorithm of peripheral */ -void dma_peripheral_address_generation_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t generation_algorithm); +void dma_peripheral_address_generation_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t generation_algorithm); /* enable DMA circulation mode */ -void dma_circulation_enable(uint32_t dma_periph,dma_channel_enum channelx); +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx); /* disable DMA circulation mode */ -void dma_circulation_disable(uint32_t dma_periph,dma_channel_enum channelx); +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx); /* enable DMA channel */ -void dma_channel_enable(uint32_t dma_periph,dma_channel_enum channelx); +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx); /* disable DMA channel */ -void dma_channel_disable(uint32_t dma_periph,dma_channel_enum channelx); +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx); /* configure the direction of data transfer on the channel */ -void dma_transfer_direction_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t direction); +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction); /* DMA switch buffer mode config */ -void dma_switch_buffer_mode_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t memory1_addr,uint32_t memory_select); +void dma_switch_buffer_mode_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t memory1_addr, uint32_t memory_select); /* DMA using memory get */ -uint32_t dma_using_memory_get(uint32_t dma_periph,dma_channel_enum channelx); +uint32_t dma_using_memory_get(uint32_t dma_periph, dma_channel_enum channelx); /* DMA channel peripheral select */ -void dma_channel_subperipheral_select(uint32_t dma_periph,dma_channel_enum channelx,dma_subperipheral_enum sub_periph); +void dma_channel_subperipheral_select(uint32_t dma_periph, dma_channel_enum channelx, dma_subperipheral_enum sub_periph); /* DMA flow controller configure */ -void dma_flow_controller_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t controller); +void dma_flow_controller_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t controller); /* DMA flow controller enable */ -void dma_switch_buffer_mode_enable(uint32_t dma_periph,dma_channel_enum channelx,ControlStatus newvalue); +void dma_switch_buffer_mode_enable(uint32_t dma_periph, dma_channel_enum channelx, ControlStatus newvalue); /* DMA FIFO status get */ -uint32_t dma_fifo_status_get(uint32_t dma_periph,dma_channel_enum channelx); +uint32_t dma_fifo_status_get(uint32_t dma_periph, dma_channel_enum channelx); +/* flag and interrupt functions */ /* check DMA flag is set or not */ -FlagStatus dma_flag_get(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag); +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); /* clear DMA a channel flag */ -void dma_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag); +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); /* check DMA flag is set or not */ -FlagStatus dma_interrupt_flag_get(uint32_t dma_periph,dma_channel_enum channelx,uint32_t interrupt); +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t interrupt); /* clear DMA a channel flag */ -void dma_interrupt_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint32_t interrupt); +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t interrupt); /* enable DMA interrupt */ -void dma_interrupt_enable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t source); +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); /* disable DMA interrupt */ -void dma_interrupt_disable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t source); +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); #endif /* GD32F4XX_DMA_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h index 7a0de03860..1dfc880d37 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_enet.h - \brief definitions for the ENET + \file gd32f4xx_enet.h + \brief definitions for the ENET + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.1, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_ENET_H @@ -36,7 +61,7 @@ #define ENET_TXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet transmit buffer size */ #endif -//#define SELECT_DESCRIPTORS_ENHANCED_MODE +//#define SELECT_DESCRIPTORS_ENHANCED_MODE //#define USE_DELAY @@ -47,7 +72,7 @@ #define PHY_ADDRESS ((uint16_t)1U) /*!< phy address determined by the hardware */ -/* PHY read write timeouts */ +/* PHY read write timeouts */ #define PHY_READ_TO ((uint32_t)0x0004FFFFU) /*!< PHY read timeout */ #define PHY_WRITE_TO ((uint32_t)0x0004FFFFU) /*!< PHY write timeout */ @@ -55,7 +80,7 @@ #define PHY_RESETDELAY ((uint32_t)0x008FFFFFU) /*!< PHY reset delay */ #define PHY_CONFIGDELAY ((uint32_t)0x00FFFFFFU) /*!< PHY configure delay */ -/* PHY register address */ +/* PHY register address */ #define PHY_REG_BCR 0U /*!< tranceiver basic control register */ #define PHY_REG_BSR 1U /*!< tranceiver basic status register */ @@ -76,7 +101,7 @@ #define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< valid link established */ #define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< jabber condition detected */ -#if(PHY_TYPE == LAN8700) +#if(PHY_TYPE == LAN8700) #define PHY_SR 31U /*!< tranceiver status register */ #define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< configured information of speed: 10Mbit/s */ #define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< configured information of duplex: full-duplex */ @@ -93,55 +118,55 @@ #define ENET ENET_BASE /* registers definitions */ -#define ENET_MAC_CFG REG32((ENET) + 0x00U) /*!< ethernet MAC configuration register */ -#define ENET_MAC_FRMF REG32((ENET) + 0x04U) /*!< ethernet MAC frame filter register */ -#define ENET_MAC_HLH REG32((ENET) + 0x08U) /*!< ethernet MAC hash list high register */ -#define ENET_MAC_HLL REG32((ENET) + 0x0CU) /*!< ethernet MAC hash list low register */ -#define ENET_MAC_PHY_CTL REG32((ENET) + 0x10U) /*!< ethernet MAC PHY control register */ -#define ENET_MAC_PHY_DATA REG32((ENET) + 0x14U) /*!< ethernet MAC MII data register */ -#define ENET_MAC_FCTL REG32((ENET) + 0x18U) /*!< ethernet MAC flow control register */ -#define ENET_MAC_VLT REG32((ENET) + 0x1CU) /*!< ethernet MAC VLAN tag register */ -#define ENET_MAC_RWFF REG32((ENET) + 0x28U) /*!< ethernet MAC remote wakeup frame filter register */ -#define ENET_MAC_WUM REG32((ENET) + 0x2CU) /*!< ethernet MAC wakeup management register */ -#define ENET_MAC_DBG REG32((ENET) + 0x34U) /*!< ethernet MAC debug register */ -#define ENET_MAC_INTF REG32((ENET) + 0x38U) /*!< ethernet MAC interrupt flag register */ -#define ENET_MAC_INTMSK REG32((ENET) + 0x3CU) /*!< ethernet MAC interrupt mask register */ -#define ENET_MAC_ADDR0H REG32((ENET) + 0x40U) /*!< ethernet MAC address 0 high register */ -#define ENET_MAC_ADDR0L REG32((ENET) + 0x44U) /*!< ethernet MAC address 0 low register */ -#define ENET_MAC_ADDR1H REG32((ENET) + 0x48U) /*!< ethernet MAC address 1 high register */ -#define ENET_MAC_ADDR1L REG32((ENET) + 0x4CU) /*!< ethernet MAC address 1 low register */ -#define ENET_MAC_ADDT2H REG32((ENET) + 0x50U) /*!< ethernet MAC address 2 high register */ -#define ENET_MAC_ADDR2L REG32((ENET) + 0x54U) /*!< ethernet MAC address 2 low register */ -#define ENET_MAC_ADDR3H REG32((ENET) + 0x58U) /*!< ethernet MAC address 3 high register */ -#define ENET_MAC_ADDR3L REG32((ENET) + 0x5CU) /*!< ethernet MAC address 3 low register */ +#define ENET_MAC_CFG REG32((ENET) + 0x0000U) /*!< ethernet MAC configuration register */ +#define ENET_MAC_FRMF REG32((ENET) + 0x0004U) /*!< ethernet MAC frame filter register */ +#define ENET_MAC_HLH REG32((ENET) + 0x0008U) /*!< ethernet MAC hash list high register */ +#define ENET_MAC_HLL REG32((ENET) + 0x000CU) /*!< ethernet MAC hash list low register */ +#define ENET_MAC_PHY_CTL REG32((ENET) + 0x0010U) /*!< ethernet MAC PHY control register */ +#define ENET_MAC_PHY_DATA REG32((ENET) + 0x0014U) /*!< ethernet MAC MII data register */ +#define ENET_MAC_FCTL REG32((ENET) + 0x0018U) /*!< ethernet MAC flow control register */ +#define ENET_MAC_VLT REG32((ENET) + 0x001CU) /*!< ethernet MAC VLAN tag register */ +#define ENET_MAC_RWFF REG32((ENET) + 0x0028U) /*!< ethernet MAC remote wakeup frame filter register */ +#define ENET_MAC_WUM REG32((ENET) + 0x002CU) /*!< ethernet MAC wakeup management register */ +#define ENET_MAC_DBG REG32((ENET) + 0x0034U) /*!< ethernet MAC debug register */ +#define ENET_MAC_INTF REG32((ENET) + 0x0038U) /*!< ethernet MAC interrupt flag register */ +#define ENET_MAC_INTMSK REG32((ENET) + 0x003CU) /*!< ethernet MAC interrupt mask register */ +#define ENET_MAC_ADDR0H REG32((ENET) + 0x0040U) /*!< ethernet MAC address 0 high register */ +#define ENET_MAC_ADDR0L REG32((ENET) + 0x0044U) /*!< ethernet MAC address 0 low register */ +#define ENET_MAC_ADDR1H REG32((ENET) + 0x0048U) /*!< ethernet MAC address 1 high register */ +#define ENET_MAC_ADDR1L REG32((ENET) + 0x004CU) /*!< ethernet MAC address 1 low register */ +#define ENET_MAC_ADDT2H REG32((ENET) + 0x0050U) /*!< ethernet MAC address 2 high register */ +#define ENET_MAC_ADDR2L REG32((ENET) + 0x0054U) /*!< ethernet MAC address 2 low register */ +#define ENET_MAC_ADDR3H REG32((ENET) + 0x0058U) /*!< ethernet MAC address 3 high register */ +#define ENET_MAC_ADDR3L REG32((ENET) + 0x005CU) /*!< ethernet MAC address 3 low register */ #define ENET_MAC_FCTH REG32((ENET) + 0x1080U) /*!< ethernet MAC flow control threshold register */ -#define ENET_MSC_CTL REG32((ENET) + 0x100U) /*!< ethernet MSC control register */ -#define ENET_MSC_RINTF REG32((ENET) + 0x104U) /*!< ethernet MSC receive interrupt flag register */ -#define ENET_MSC_TINTF REG32((ENET) + 0x108U) /*!< ethernet MSC transmit interrupt flag register */ -#define ENET_MSC_RINTMSK REG32((ENET) + 0x10CU) /*!< ethernet MSC receive interrupt mask register */ -#define ENET_MSC_TINTMSK REG32((ENET) + 0x110U) /*!< ethernet MSC transmit interrupt mask register */ -#define ENET_MSC_SCCNT REG32((ENET) + 0x14CU) /*!< ethernet MSC transmitted good frames after a single collision counter register */ -#define ENET_MSC_MSCCNT REG32((ENET) + 0x150U) /*!< ethernet MSC transmitted good frames after more than a single collision counter register */ -#define ENET_MSC_TGFCNT REG32((ENET) + 0x168U) /*!< ethernet MSC transmitted good frames counter register */ -#define ENET_MSC_RFCECNT REG32((ENET) + 0x194U) /*!< ethernet MSC received frames with CRC error counter register */ -#define ENET_MSC_RFAECNT REG32((ENET) + 0x198U) /*!< ethernet MSC received frames with alignment error counter register */ -#define ENET_MSC_RGUFCNT REG32((ENET) + 0x1C4U) /*!< ethernet MSC received good unicast frames counter register */ +#define ENET_MSC_CTL REG32((ENET) + 0x0100U) /*!< ethernet MSC control register */ +#define ENET_MSC_RINTF REG32((ENET) + 0x0104U) /*!< ethernet MSC receive interrupt flag register */ +#define ENET_MSC_TINTF REG32((ENET) + 0x0108U) /*!< ethernet MSC transmit interrupt flag register */ +#define ENET_MSC_RINTMSK REG32((ENET) + 0x010CU) /*!< ethernet MSC receive interrupt mask register */ +#define ENET_MSC_TINTMSK REG32((ENET) + 0x0110U) /*!< ethernet MSC transmit interrupt mask register */ +#define ENET_MSC_SCCNT REG32((ENET) + 0x014CU) /*!< ethernet MSC transmitted good frames after a single collision counter register */ +#define ENET_MSC_MSCCNT REG32((ENET) + 0x0150U) /*!< ethernet MSC transmitted good frames after more than a single collision counter register */ +#define ENET_MSC_TGFCNT REG32((ENET) + 0x0168U) /*!< ethernet MSC transmitted good frames counter register */ +#define ENET_MSC_RFCECNT REG32((ENET) + 0x0194U) /*!< ethernet MSC received frames with CRC error counter register */ +#define ENET_MSC_RFAECNT REG32((ENET) + 0x0198U) /*!< ethernet MSC received frames with alignment error counter register */ +#define ENET_MSC_RGUFCNT REG32((ENET) + 0x01C4U) /*!< ethernet MSC received good unicast frames counter register */ -#define ENET_PTP_TSCTL REG32((ENET) + 0x700U) /*!< ethernet PTP time stamp control register */ -#define ENET_PTP_SSINC REG32((ENET) + 0x704U) /*!< ethernet PTP subsecond increment register */ -#define ENET_PTP_TSH REG32((ENET) + 0x708U) /*!< ethernet PTP time stamp high register */ -#define ENET_PTP_TSL REG32((ENET) + 0x70CU) /*!< ethernet PTP time stamp low register */ -#define ENET_PTP_TSUH REG32((ENET) + 0x710U) /*!< ethernet PTP time stamp update high register */ -#define ENET_PTP_TSUL REG32((ENET) + 0x714U) /*!< ethernet PTP time stamp update low register */ -#define ENET_PTP_TSADDEND REG32((ENET) + 0x718U) /*!< ethernet PTP time stamp addend register */ -#define ENET_PTP_ETH REG32((ENET) + 0x71CU) /*!< ethernet PTP expected time high register */ -#define ENET_PTP_ETL REG32((ENET) + 0x720U) /*!< ethernet PTP expected time low register */ -#define ENET_PTP_TSF REG32((ENET) + 0x728U) /*!< ethernet PTP time stamp flag register */ -#define ENET_PTP_PPSCTL REG32((ENET) + 0x72CU) /*!< ethernet PTP PPS control register */ +#define ENET_PTP_TSCTL REG32((ENET) + 0x0700U) /*!< ethernet PTP time stamp control register */ +#define ENET_PTP_SSINC REG32((ENET) + 0x0704U) /*!< ethernet PTP subsecond increment register */ +#define ENET_PTP_TSH REG32((ENET) + 0x0708U) /*!< ethernet PTP time stamp high register */ +#define ENET_PTP_TSL REG32((ENET) + 0x070CU) /*!< ethernet PTP time stamp low register */ +#define ENET_PTP_TSUH REG32((ENET) + 0x0710U) /*!< ethernet PTP time stamp update high register */ +#define ENET_PTP_TSUL REG32((ENET) + 0x0714U) /*!< ethernet PTP time stamp update low register */ +#define ENET_PTP_TSADDEND REG32((ENET) + 0x0718U) /*!< ethernet PTP time stamp addend register */ +#define ENET_PTP_ETH REG32((ENET) + 0x071CU) /*!< ethernet PTP expected time high register */ +#define ENET_PTP_ETL REG32((ENET) + 0x0720U) /*!< ethernet PTP expected time low register */ +#define ENET_PTP_TSF REG32((ENET) + 0x0728U) /*!< ethernet PTP time stamp flag register */ +#define ENET_PTP_PPSCTL REG32((ENET) + 0x072CU) /*!< ethernet PTP PPS control register */ #define ENET_DMA_BCTL REG32((ENET) + 0x1000U) /*!< ethernet DMA bus control register */ -#define ENET_DMA_TPEN REG32((ENET) + 0x1004U) /*!< ethernet DMA transmit poll enable register */ +#define ENET_DMA_TPEN REG32((ENET) + 0x1004U) /*!< ethernet DMA transmit poll enable register */ #define ENET_DMA_RPEN REG32((ENET) + 0x1008U) /*!< ethernet DMA receive poll enable register */ #define ENET_DMA_RDTADDR REG32((ENET) + 0x100CU) /*!< ethernet DMA receive descriptor table address register */ #define ENET_DMA_TDTADDR REG32((ENET) + 0x1010U) /*!< ethernet DMA transmit descriptor table address register */ @@ -150,7 +175,7 @@ #define ENET_DMA_INTEN REG32((ENET) + 0x101CU) /*!< ethernet DMA interrupt enable register */ #define ENET_DMA_MFBOCNT REG32((ENET) + 0x1020U) /*!< ethernet DMA missed frame and buffer overflow counter register */ #define ENET_DMA_RSWDC REG32((ENET) + 0x1024U) /*!< ethernet DMA receive state watchdog counter register */ -#define ENET_DMA_CTDADDR REG32((ENET) + 0x1048U) /*!< ethernet DMA current transmit descriptor address register */ +#define ENET_DMA_CTDADDR REG32((ENET) + 0x1048U) /*!< ethernet DMA current transmit descriptor address register */ #define ENET_DMA_CRDADDR REG32((ENET) + 0x104CU) /*!< ethernet DMA current receive descriptor address register */ #define ENET_DMA_CTBADDR REG32((ENET) + 0x1050U) /*!< ethernet DMA current transmit buffer address register */ #define ENET_DMA_CRBADDR REG32((ENET) + 0x1054U) /*!< ethernet DMA current receive buffer address register */ @@ -169,7 +194,7 @@ #define ENET_MAC_CFG_ROD BIT(13) /*!< receive own disable */ #define ENET_MAC_CFG_SPD BIT(14) /*!< fast eneternet speed */ #define ENET_MAC_CFG_CSD BIT(16) /*!< carrier sense disable */ -#define ENET_MAC_CFG_IGBS BITS(17,19) /*!< inter-frame gap bit selection */ +#define ENET_MAC_CFG_IGBS BITS(17,19) /*!< inter-frame gap bit selection */ #define ENET_MAC_CFG_JBD BIT(22) /*!< jabber disable */ #define ENET_MAC_CFG_WDD BIT(23) /*!< watchdog disable */ #define ENET_MAC_CFG_TFCD BIT(25) /*!< type frame CRC dropping */ @@ -177,49 +202,49 @@ /* ENET_MAC_FRMF */ #define ENET_MAC_FRMF_PM BIT(0) /*!< promiscuous mode */ #define ENET_MAC_FRMF_HUF BIT(1) /*!< hash unicast filter */ -#define ENET_MAC_FRMF_HMF BIT(2) /*!< hash multicast filter */ -#define ENET_MAC_FRMF_DAIFLT BIT(3) /*!< destination address inverse filtering enable */ -#define ENET_MAC_FRMF_MFD BIT(4) /*!< multicast filter disable */ -#define ENET_MAC_FRMF_BFRMD BIT(5) /*!< broadcast frame disable */ -#define ENET_MAC_FRMF_PCFRM BITS(6,7) /*!< pass control frames */ -#define ENET_MAC_FRMF_SAIFLT BIT(8) /*!< source address inverse filtering */ -#define ENET_MAC_FRMF_SAFLT BIT(9) /*!< source address filter */ -#define ENET_MAC_FRMF_HPFLT BIT(10) /*!< hash or perfect filter */ -#define ENET_MAC_FRMF_FAR BIT(31) /*!< frames all receive */ - +#define ENET_MAC_FRMF_HMF BIT(2) /*!< hash multicast filter */ +#define ENET_MAC_FRMF_DAIFLT BIT(3) /*!< destination address inverse filtering enable */ +#define ENET_MAC_FRMF_MFD BIT(4) /*!< multicast filter disable */ +#define ENET_MAC_FRMF_BFRMD BIT(5) /*!< broadcast frame disable */ +#define ENET_MAC_FRMF_PCFRM BITS(6,7) /*!< pass control frames */ +#define ENET_MAC_FRMF_SAIFLT BIT(8) /*!< source address inverse filtering */ +#define ENET_MAC_FRMF_SAFLT BIT(9) /*!< source address filter */ +#define ENET_MAC_FRMF_HPFLT BIT(10) /*!< hash or perfect filter */ +#define ENET_MAC_FRMF_FAR BIT(31) /*!< frames all receive */ + /* ENET_MAC_HLH */ #define ENET_MAC_HLH_HLH BITS(0,31) /*!< hash list high */ - + /* ENET_MAC_HLL */ #define ENET_MAC_HLL_HLL BITS(0,31) /*!< hash list low */ - + /* ENET_MAC_PHY_CTL */ -#define ENET_MAC_PHY_CTL_PB BIT(0) /*!< PHY busy */ -#define ENET_MAC_PHY_CTL_PW BIT(1) /*!< PHY write */ -#define ENET_MAC_PHY_CTL_CLR BITS(2,4) /*!< clock range */ -#define ENET_MAC_PHY_CTL_PR BITS(6,10) /*!< PHY register */ -#define ENET_MAC_PHY_CTL_PA BITS(11,15) /*!< PHY address */ - +#define ENET_MAC_PHY_CTL_PB BIT(0) /*!< PHY busy */ +#define ENET_MAC_PHY_CTL_PW BIT(1) /*!< PHY write */ +#define ENET_MAC_PHY_CTL_CLR BITS(2,4) /*!< clock range */ +#define ENET_MAC_PHY_CTL_PR BITS(6,10) /*!< PHY register */ +#define ENET_MAC_PHY_CTL_PA BITS(11,15) /*!< PHY address */ + /* ENET_MAC_PHY_DATA */ #define ENET_MAC_PHY_DATA_PD BITS(0,15) /*!< PHY data */ - + /* ENET_MAC_FCTL */ #define ENET_MAC_FCTL_FLCBBKPA BIT(0) /*!< flow control busy(in full duplex mode)/backpressure activate(in half duplex mode) */ #define ENET_MAC_FCTL_TFCEN BIT(1) /*!< transmit flow control enable */ #define ENET_MAC_FCTL_RFCEN BIT(2) /*!< receive flow control enable */ #define ENET_MAC_FCTL_UPFDT BIT(3) /*!< unicast pause frame detect */ -#define ENET_MAC_FCTL_PLTS BITS(4,5) /*!< pause low threshold */ +#define ENET_MAC_FCTL_PLTS BITS(4,5) /*!< pause low threshold */ #define ENET_MAC_FCTL_DZQP BIT(7) /*!< disable zero-quanta pause */ #define ENET_MAC_FCTL_PTM BITS(16,31) /*!< pause time */ - + /* ENET_MAC_VLT */ #define ENET_MAC_VLT_VLTI BITS(0,15) /*!< VLAN tag identifier(for receive frames) */ #define ENET_MAC_VLT_VLTC BIT(16) /*!< 12-bit VLAN tag comparison */ - + /* ENET_MAC_RWFF */ #define ENET_MAC_RWFF_DATA BITS(0,31) /*!< wakeup frame filter register data */ - -/* ENET_MAC_WUM */ + +/* ENET_MAC_WUM */ #define ENET_MAC_WUM_PWD BIT(0) /*!< power down */ #define ENET_MAC_WUM_MPEN BIT(1) /*!< magic packet enable */ #define ENET_MAC_WUM_WFEN BIT(2) /*!< wakeup frame enable */ @@ -228,7 +253,7 @@ #define ENET_MAC_WUM_GU BIT(9) /*!< global unicast */ #define ENET_MAC_WUM_WUFFRPR BIT(31) /*!< wakeup frame filter register pointer reset */ -/* ENET_MAC_DBG */ +/* ENET_MAC_DBG */ #define ENET_MAC_DBG_MRNI BIT(0) /*!< MAC receive state not idle */ #define ENET_MAC_DBG_RXAFS BITS(1,2) /*!< Rx asynchronous FIFO status */ #define ENET_MAC_DBG_RXFW BIT(4) /*!< RxFIFO is writing */ @@ -242,7 +267,7 @@ #define ENET_MAC_DBG_TXFNE BIT(24) /*!< TxFIFO not empty flag */ #define ENET_MAC_DBG_TXFF BIT(25) /*!< TxFIFO full flag */ -/* ENET_MAC_INTF */ +/* ENET_MAC_INTF */ #define ENET_MAC_INTF_WUM BIT(3) /*!< WUM status */ #define ENET_MAC_INTF_MSC BIT(4) /*!< MSC status */ #define ENET_MAC_INTF_MSCR BIT(5) /*!< MSC receive status */ @@ -256,28 +281,28 @@ /* ENET_MAC_ADDR0H */ #define ENET_MAC_ADDR0H_ADDR0H BITS(0,15) /*!< MAC address0 high */ #define ENET_MAC_ADDR0H_MO BIT(31) /*!< always read 1 and must be kept */ - + /* ENET_MAC_ADDR0L */ #define ENET_MAC_ADDR0L_ADDR0L BITS(0,31) /*!< MAC address0 low */ - + /* ENET_MAC_ADDR1H */ #define ENET_MAC_ADDR1H_ADDR1H BITS(0,15) /*!< MAC address1 high */ -#define ENET_MAC_ADDR1H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR1H_MB BITS(24,29) /*!< mask byte */ #define ENET_MAC_ADDR1H_SAF BIT(30) /*!< source address filter */ #define ENET_MAC_ADDR1H_AFE BIT(31) /*!< address filter enable */ - + /* ENET_MAC_ADDR1L */ #define ENET_MAC_ADDR1L_ADDR1L BITS(0,31) /*!< MAC address1 low */ - + /* ENET_MAC_ADDR2H */ #define ENET_MAC_ADDR2H_ADDR2H BITS(0,15) /*!< MAC address2 high */ #define ENET_MAC_ADDR2H_MB BITS(24,29) /*!< mask byte */ #define ENET_MAC_ADDR2H_SAF BIT(30) /*!< source address filter */ #define ENET_MAC_ADDR2H_AFE BIT(31) /*!< address filter enable */ - + /* ENET_MAC_ADDR2L */ #define ENET_MAC_ADDR2L_ADDR2L BITS(0,31) /*!< MAC address2 low */ - + /* ENET_MAC_ADDR3H */ #define ENET_MAC_ADDR3H_ADDR3H BITS(0,15) /*!< MAC address3 high */ #define ENET_MAC_ADDR3H_MB BITS(24,29) /*!< mask byte */ @@ -286,11 +311,11 @@ /* ENET_MAC_ADDR3L */ #define ENET_MAC_ADDR3L_ADDR3L BITS(0,31) /*!< MAC address3 low */ - + /* ENET_MAC_FCTH */ #define ENET_MAC_FCTH_RFA BITS(0,2) /*!< threshold of active flow control */ #define ENET_MAC_FCTH_RFD BITS(4,6) /*!< threshold of deactive flow control */ - + /* ENET_MSC_CTL */ #define ENET_MSC_CTL_CTR BIT(0) /*!< counter reset */ #define ENET_MSC_CTL_CTSR BIT(1) /*!< counter stop rollover */ @@ -303,7 +328,7 @@ #define ENET_MSC_RINTF_RFCE BIT(5) /*!< received frames CRC error */ #define ENET_MSC_RINTF_RFAE BIT(6) /*!< received frames alignment error */ #define ENET_MSC_RINTF_RGUF BIT(17) /*!< receive good unicast frames */ - + /* ENET_MSC_TINTF */ #define ENET_MSC_TINTF_TGFSC BIT(14) /*!< transmitted good frames single collision */ #define ENET_MSC_TINTF_TGFMSC BIT(15) /*!< transmitted good frames more single collision */ @@ -313,30 +338,30 @@ #define ENET_MSC_RINTMSK_RFCEIM BIT(5) /*!< received frame CRC error interrupt mask */ #define ENET_MSC_RINTMSK_RFAEIM BIT(6) /*!< received frames alignment error interrupt mask */ #define ENET_MSC_RINTMSK_RGUFIM BIT(17) /*!< received good unicast frames interrupt mask */ - + /* ENET_MSC_TINTMSK */ #define ENET_MSC_TINTMSK_TGFSCIM BIT(14) /*!< transmitted good frames single collision interrupt mask */ #define ENET_MSC_TINTMSK_TGFMSCIM BIT(15) /*!< transmitted good frames more single collision interrupt mask */ #define ENET_MSC_TINTMSK_TGFIM BIT(21) /*!< transmitted good frames interrupt mask */ - + /* ENET_MSC_SCCNT */ #define ENET_MSC_SCCNT_SCC BITS(0,31) /*!< transmitted good frames single collision counter */ - + /* ENET_MSC_MSCCNT */ #define ENET_MSC_MSCCNT_MSCC BITS(0,31) /*!< transmitted good frames more one single collision counter */ - + /* ENET_MSC_TGFCNT */ #define ENET_MSC_TGFCNT_TGF BITS(0,31) /*!< transmitted good frames counter */ - + /* ENET_MSC_RFCECNT */ #define ENET_MSC_RFCECNT_RFCER BITS(0,31) /*!< received frames with CRC error counter */ - + /* ENET_MSC_RFAECNT */ #define ENET_MSC_RFAECNT_RFAER BITS(0,31) /*!< received frames alignment error counter */ - + /* ENET_MSC_RGUFCNT */ #define ENET_MSC_RGUFCNT_RGUF BITS(0,31) /*!< received good unicast frames counter */ - + /* ENET_PTP_TSCTL */ #define PTP_TSCTL_CKNT(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) /*!< write value to ENET_PTP_TSCTL_CKNT bit field */ @@ -356,37 +381,37 @@ #define ENET_PTP_TSCTL_MNMSEN BIT(15) /*!< received master node message snapshot enable */ #define ENET_PTP_TSCTL_CKNT BITS(16,17) /*!< clock node type for time stamp */ #define ENET_PTP_TSCTL_MAFEN BIT(18) /*!< MAC address filter enable for PTP frame */ - + /* ENET_PTP_SSINC */ #define ENET_PTP_SSINC_STMSSI BITS(0,7) /*!< system time subsecond increment */ - + /* ENET_PTP_TSH */ #define ENET_PTP_TSH_STMS BITS(0,31) /*!< system time second */ - + /* ENET_PTP_TSL */ #define ENET_PTP_TSL_STMSS BITS(0,30) /*!< system time subseconds */ #define ENET_PTP_TSL_STS BIT(31) /*!< system time sign */ - + /* ENET_PTP_TSUH */ #define ENET_PTP_TSUH_TMSUS BITS(0,31) /*!< timestamp update seconds */ - + /* ENET_PTP_TSUL */ #define ENET_PTP_TSUL_TMSUSS BITS(0,30) /*!< timestamp update subseconds */ #define ENET_PTP_TSUL_TMSUPNS BIT(31) /*!< timestamp update positive or negative sign */ /* ENET_PTP_TSADDAND */ #define ENET_PTP_TSADDAND_TMSA BITS(0,31) /*!< timestamp addend */ - + /* ENET_PTP_ETH */ #define ENET_PTP_ETH_ETSH BITS(0,31) /*!< expected time high */ - + /* ENET_PTP_ETL */ #define ENET_PTP_ETL_ETSL BITS(0,31) /*!< expected time low */ - + /* ENET_PTP_TSF */ #define ENET_PTP_TSF_TSSCO BIT(0) /*!< timestamp second counter overflow */ #define ENET_PTP_TSF_TTM BIT(1) /*!< target time match */ - + /* ENET_PTP_PPSCTL */ #define ENET_PTP_PPSCTL_PPSOFC BITS(0,3) /*!< PPS output frequency configure */ @@ -403,19 +428,19 @@ #define ENET_DMA_BCTL_FPBL BIT(24) /*!< four times PGBL mode */ #define ENET_DMA_BCTL_AA BIT(25) /*!< address-aligned */ #define ENET_DMA_BCTL_MB BIT(26) /*!< mixed burst */ - + /* ENET_DMA_TPEN */ #define ENET_DMA_TPEN_TPE BITS(0,31) /*!< transmit poll enable */ - + /* ENET_DMA_RPEN */ #define ENET_DMA_RPEN_RPE BITS(0,31) /*!< receive poll enable */ /* ENET_DMA_RDTADDR */ #define ENET_DMA_RDTADDR_SRT BITS(0,31) /*!< start address of receive table */ - + /* ENET_DMA_TDTADDR */ #define ENET_DMA_TDTADDR_STT BITS(0,31) /*!< start address of transmit table */ - + /* ENET_DMA_STAT */ #define ENET_DMA_STAT_TS BIT(0) /*!< transmit status */ #define ENET_DMA_STAT_TPS BIT(1) /*!< transmit process stopped status */ @@ -438,7 +463,7 @@ #define ENET_DMA_STAT_MSC BIT(27) /*!< MSC status */ #define ENET_DMA_STAT_WUM BIT(28) /*!< WUM status */ #define ENET_DMA_STAT_TST BIT(29) /*!< timestamp trigger status */ - + /* ENET_DMA_CTL */ #define ENET_DMA_CTL_SRE BIT(1) /*!< start/stop receive enable */ #define ENET_DMA_CTL_OSF BIT(2) /*!< operate on second frame */ @@ -452,7 +477,7 @@ #define ENET_DMA_CTL_DAFRF BIT(24) /*!< disable flushing of received frames */ #define ENET_DMA_CTL_RSFD BIT(25) /*!< receive store-and-forward */ #define ENET_DMA_CTL_DTCERFD BIT(26) /*!< dropping of TCP/IP checksum error frames disable */ - + /* ENET_DMA_INTEN */ #define ENET_DMA_INTEN_TIE BIT(0) /*!< transmit interrupt enable */ #define ENET_DMA_INTEN_TPSIE BIT(1) /*!< transmit process stopped interrupt enable */ @@ -469,7 +494,7 @@ #define ENET_DMA_INTEN_ERIE BIT(14) /*!< early receive interrupt enable */ #define ENET_DMA_INTEN_AIE BIT(15) /*!< abnormal interrupt summary enable */ #define ENET_DMA_INTEN_NIE BIT(16) /*!< normal interrupt summary enable */ - + /* ENET_DMA_MFBOCNT */ #define ENET_DMA_MFBOCNT_MSFC BITS(0,15) /*!< missed frames by the controller */ #define ENET_DMA_MFBOCNT_MSFA BITS(17,27) /*!< missed frames by the application */ @@ -482,10 +507,10 @@ /* ENET_DMA_CRDADDR */ #define ENET_DMA_CRDADDR_RDAP BITS(0,31) /*!< receive descriptor address pointer */ - + /* ENET_DMA_CTBADDR */ #define ENET_DMA_CTBADDR_TBAP BITS(0,31) /*!< transmit buffer address pointer */ - + /* ENET_DMA_CRBADDR */ #define ENET_DMA_CRBADDR_RBAP BITS(0,31) /*!< receive buffer address pointer */ @@ -545,7 +570,7 @@ #define ENET_RDES0_LCO BIT(6) /*!< late collision */ #define ENET_RDES0_IPHERR BIT(7) /*!< IP frame header error */ #define ENET_RDES0_TSV BIT(7) /*!< timestamp valid */ -#define ENET_RDES0_LDES BIT(8) /*!< last descriptor */ +#define ENET_RDES0_LDES BIT(8) /*!< last descriptor */ #define ENET_RDES0_FDES BIT(9) /*!< first descriptor */ #define ENET_RDES0_VTAG BIT(10) /*!< VLAN tag */ #define ENET_RDES0_OERR BIT(11) /*!< overflow Error */ @@ -557,7 +582,7 @@ #define ENET_RDES0_DAFF BIT(30) /*!< destination address filter fail */ #define ENET_RDES0_DAV BIT(31) /*!< descriptor available */ -/* ENET DMA Rx descriptor RDES1 */ +/* ENET DMA Rx descriptor RDES1 */ #define ENET_RDES1_RB1S BITS(0,12) /*!< receive buffer 1 size */ #define ENET_RDES1_RCHM BIT(14) /*!< receive chained mode for second address */ #define ENET_RDES1_RERM BIT(15) /*!< receive end of ring mode*/ @@ -592,53 +617,53 @@ /* constants definitions */ /* define bit position and its register index offset */ #define ENET_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) -#define ENET_REG_VAL(periph) (REG32(ENET + ((uint32_t)(periph)>>6))) +#define ENET_REG_VAL(periph) (REG32(ENET + ((uint32_t)(periph) >> 6))) #define ENET_BIT_POS(val) ((uint32_t)(val) & 0x1FU) /* ENET clock range judgement */ #define ENET_RANGE(hclk, n, m) (((hclk) >= (n))&&((hclk) < (m))) /* define MAC address configuration and reference address */ -#define ENET_SET_MACADDRH(p) (((uint32_t)(p)[5] << 8) | (uint32_t)(p)[4]) +#define ENET_SET_MACADDRH(p) (((uint32_t)(p)[5] << 8) | (uint32_t)(p)[4]) #define ENET_SET_MACADDRL(p) (((uint32_t)(p)[3] << 24) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[1] << 8) | (uint32_t)(p)[0]) #define ENET_ADDRH_BASE ((ENET) + 0x40U) #define ENET_ADDRL_BASE ((ENET) + 0x44U) #define ENET_GET_MACADDR(offset, n) ((uint8_t)((REG32((ENET_ADDRL_BASE + (offset)) - (((n) / 4U) * 4U)) >> (8U * ((n) % 4U))) & 0xFFU)) /* register offset */ -#define MAC_FCTL_REG_OFFSET 0x0018U /*!< MAC flow control register offset */ -#define MAC_WUM_REG_OFFSET 0x002CU /*!< MAC wakeup management register offset */ -#define MAC_INTF_REG_OFFSET 0x0038U /*!< MAC interrupt flag register offset */ -#define MAC_INTMSK_REG_OFFSET 0x003CU /*!< MAC interrupt mask register offset */ +#define MAC_FCTL_REG_OFFSET ((uint16_t)0x0018U) /*!< MAC flow control register offset */ +#define MAC_WUM_REG_OFFSET ((uint16_t)0x002CU) /*!< MAC wakeup management register offset */ +#define MAC_INTF_REG_OFFSET ((uint16_t)0x0038U) /*!< MAC interrupt flag register offset */ +#define MAC_INTMSK_REG_OFFSET ((uint16_t)0x003CU) /*!< MAC interrupt mask register offset */ -#define MSC_RINTF_REG_OFFSET 0x0104U /*!< MSC receive interrupt flag register offset */ -#define MSC_TINTF_REG_OFFSET 0x0108U /*!< MSC transmit interrupt flag register offset */ -#define MSC_RINTMSK_REG_OFFSET 0x010CU /*!< MSC receive interrupt mask register offset */ -#define MSC_TINTMSK_REG_OFFSET 0x0110U /*!< MSC transmit interrupt mask register offset */ -#define MSC_SCCNT_REG_OFFSET 0x014CU /*!< MSC transmitted good frames after a single collision counter register offset */ -#define MSC_MSCCNT_REG_OFFSET 0x0150U /*!< MSC transmitted good frames after more than a single collision counter register offset */ -#define MSC_TGFCNT_REG_OFFSET 0x0168U /*!< MSC transmitted good frames counter register offset */ -#define MSC_RFCECNT_REG_OFFSET 0x0194U /*!< MSC received frames with CRC error counter register offset */ -#define MSC_RFAECNT_REG_OFFSET 0x0198U /*!< MSC received frames with alignment error counter register offset */ -#define MSC_RGUFCNT_REG_OFFSET 0x01C4U /*!< MSC received good unicast frames counter register offset */ - -#define PTP_TSF_REG_OFFSET 0x0728U /*!< PTP time stamp flag register offset */ +#define MSC_RINTF_REG_OFFSET ((uint16_t)0x0104U) /*!< MSC receive interrupt flag register offset */ +#define MSC_TINTF_REG_OFFSET ((uint16_t)0x0108U) /*!< MSC transmit interrupt flag register offset */ +#define MSC_RINTMSK_REG_OFFSET ((uint16_t)0x010CU) /*!< MSC receive interrupt mask register offset */ +#define MSC_TINTMSK_REG_OFFSET ((uint16_t)0x0110U) /*!< MSC transmit interrupt mask register offset */ +#define MSC_SCCNT_REG_OFFSET ((uint16_t)0x014CU) /*!< MSC transmitted good frames after a single collision counter register offset */ +#define MSC_MSCCNT_REG_OFFSET ((uint16_t)0x0150U) /*!< MSC transmitted good frames after more than a single collision counter register offset */ +#define MSC_TGFCNT_REG_OFFSET ((uint16_t)0x0168U) /*!< MSC transmitted good frames counter register offset */ +#define MSC_RFCECNT_REG_OFFSET ((uint16_t)0x0194U) /*!< MSC received frames with CRC error counter register offset */ +#define MSC_RFAECNT_REG_OFFSET ((uint16_t)0x0198U) /*!< MSC received frames with alignment error counter register offset */ +#define MSC_RGUFCNT_REG_OFFSET ((uint16_t)0x01C4U) /*!< MSC received good unicast frames counter register offset */ -#define DMA_STAT_REG_OFFSET 0x1014U /*!< DMA status register offset */ -#define DMA_INTEN_REG_OFFSET 0x101CU /*!< DMA interrupt enable register offset */ -#define DMA_TDTADDR_REG_OFFSET 0x1010U /*!< DMA transmit descriptor table address register offset */ -#define DMA_CTDADDR_REG_OFFSET 0x1048U /*!< DMA current transmit descriptor address register */ -#define DMA_CTBADDR_REG_OFFSET 0x1050U /*!< DMA current transmit buffer address register */ -#define DMA_RDTADDR_REG_OFFSET 0x100CU /*!< DMA receive descriptor table address register */ -#define DMA_CRDADDR_REG_OFFSET 0x104CU /*!< DMA current receive descriptor address register */ -#define DMA_CRBADDR_REG_OFFSET 0x1054U /*!< DMA current receive buffer address register */ +#define PTP_TSF_REG_OFFSET ((uint16_t)0x0728U) /*!< PTP time stamp flag register offset */ + +#define DMA_STAT_REG_OFFSET ((uint16_t)0x1014U) /*!< DMA status register offset */ +#define DMA_INTEN_REG_OFFSET ((uint16_t)0x101CU) /*!< DMA interrupt enable register offset */ +#define DMA_TDTADDR_REG_OFFSET ((uint16_t)0x1010U) /*!< DMA transmit descriptor table address register offset */ +#define DMA_CTDADDR_REG_OFFSET ((uint16_t)0x1048U) /*!< DMA current transmit descriptor address register */ +#define DMA_CTBADDR_REG_OFFSET ((uint16_t)0x1050U) /*!< DMA current transmit buffer address register */ +#define DMA_RDTADDR_REG_OFFSET ((uint16_t)0x100CU) /*!< DMA receive descriptor table address register */ +#define DMA_CRDADDR_REG_OFFSET ((uint16_t)0x104CU) /*!< DMA current receive descriptor address register */ +#define DMA_CRBADDR_REG_OFFSET ((uint16_t)0x1054U) /*!< DMA current receive buffer address register */ /* ENET status flag get */ typedef enum { /* ENET_MAC_WUM register */ ENET_MAC_FLAG_MPKR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 5U), /*!< magic packet received flag */ - ENET_MAC_FLAG_WUFR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 6U), /*!< wakeup frame received flag */ + ENET_MAC_FLAG_WUFR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 6U), /*!< wakeup frame received flag */ /* ENET_MAC_FCTL register */ ENET_MAC_FLAG_FLOWCONTROL = ENET_REGIDX_BIT(MAC_FCTL_REG_OFFSET, 0U), /*!< flow control status flag */ /* ENET_MAC_INTF register */ @@ -648,13 +673,13 @@ typedef enum ENET_MAC_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ ENET_MAC_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ /* ENET_PTP_TSF register */ - ENET_PTP_FLAG_TSSCO = ENET_REGIDX_BIT(PTP_TSF_REG_OFFSET, 0U), /*!< timestamp second counter overflow flag */ + ENET_PTP_FLAG_TSSCO = ENET_REGIDX_BIT(PTP_TSF_REG_OFFSET, 0U), /*!< timestamp second counter overflow flag */ ENET_PTP_FLAG_TTM = ENET_REGIDX_BIT(PTP_TSF_REG_OFFSET, 1U), /*!< target time match flag */ /* ENET_MSC_RINTF register */ ENET_MSC_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ ENET_MSC_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ ENET_MSC_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ - /* ENET_MSC_TINTF register */ + /* ENET_MSC_TINTF register */ ENET_MSC_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ ENET_MSC_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ ENET_MSC_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ @@ -679,7 +704,7 @@ typedef enum ENET_DMA_FLAG_EB_ACCESS_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 25U), /*!< error during data buffer/descriptor access flag */ ENET_DMA_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ ENET_DMA_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ - ENET_DMA_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ + ENET_DMA_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ }enet_flag_enum; /* ENET stutus flag clear */ @@ -700,7 +725,7 @@ typedef enum ENET_DMA_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ ENET_DMA_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ ENET_DMA_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ - ENET_DMA_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ }enet_flag_clear_enum; /* ENET interrupt enable/disable */ @@ -709,15 +734,15 @@ typedef enum /* ENET_MAC_INTMSK register */ ENET_MAC_INT_WUMIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 3U), /*!< WUM interrupt mask */ ENET_MAC_INT_TMSTIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 9U), /*!< timestamp trigger interrupt mask */ - /* ENET_MSC_RINTMSK register */ + /* ENET_MSC_RINTMSK register */ ENET_MSC_INT_RFCEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 5U), /*!< received frame CRC error interrupt mask */ ENET_MSC_INT_RFAEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 6U), /*!< received frames alignment error interrupt mask */ ENET_MSC_INT_RGUFIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 17U), /*!< received good unicast frames interrupt mask */ - /* ENET_MSC_TINTMSK register */ + /* ENET_MSC_TINTMSK register */ ENET_MSC_INT_TGFSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 14U), /*!< transmitted good frames single collision interrupt mask */ ENET_MSC_INT_TGFMSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 15U), /*!< transmitted good frames more single collision interrupt mask */ ENET_MSC_INT_TGFIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 21U), /*!< transmitted good frames interrupt mask */ - /* ENET_DMA_INTEN register */ + /* ENET_DMA_INTEN register */ ENET_DMA_INT_TIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 0U), /*!< transmit interrupt enable */ ENET_DMA_INT_TPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 1U), /*!< transmit process stopped interrupt enable */ ENET_DMA_INT_TBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 2U), /*!< transmit buffer unavailable interrupt enable */ @@ -734,7 +759,7 @@ typedef enum ENET_DMA_INT_AIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 15U), /*!< abnormal interrupt summary enable */ ENET_DMA_INT_NIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 16U), /*!< normal interrupt summary enable */ }enet_int_enum; - + /* ENET interrupt flag get */ typedef enum { @@ -770,7 +795,7 @@ typedef enum ENET_DMA_INT_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ ENET_DMA_INT_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ ENET_DMA_INT_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ - ENET_DMA_INT_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ + ENET_DMA_INT_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ }enet_int_flag_enum; /* ENET interrupt flag clear */ @@ -814,7 +839,7 @@ typedef enum ENET_MSC_RX_RFCECNT = MSC_RFCECNT_REG_OFFSET, /*!< MSC received frames with CRC error counter */ ENET_MSC_RX_RFAECNT = MSC_RFAECNT_REG_OFFSET, /*!< MSC received frames with alignment error counter */ ENET_MSC_RX_RGUFCNT = MSC_RGUFCNT_REG_OFFSET /*!< MSC received good unicast frames counter */ -}enet_msc_counter_enum; +}enet_msc_counter_enum; /* function option, used for ENET initialization */ typedef enum @@ -838,7 +863,7 @@ typedef enum /* phy mode and mac loopback configurations */ typedef enum { - ENET_AUTO_NEGOTIATION = 0x01u, /*!< PHY auto negotiation */ + ENET_AUTO_NEGOTIATION = 0x01U, /*!< PHY auto negotiation */ ENET_100M_FULLDUPLEX = (ENET_MAC_CFG_SPD | ENET_MAC_CFG_DPM), /*!< 100Mbit/s, full-duplex */ ENET_100M_HALFDUPLEX = ENET_MAC_CFG_SPD , /*!< 100Mbit/s, half-duplex */ ENET_10M_FULLDUPLEX = ENET_MAC_CFG_DPM, /*!< 10Mbit/s, full-duplex */ @@ -867,10 +892,10 @@ typedef enum /* register group value get */ typedef enum { - ALL_MAC_REG = 0, /*!< MAC register group */ - ALL_MSC_REG = 22, /*!< MSC register group */ - ALL_PTP_REG = 33, /*!< PTP register group */ - ALL_DMA_REG = 44, /*!< DMA register group */ + ALL_MAC_REG = 0U, /*!< MAC register group */ + ALL_MSC_REG = 22U, /*!< MSC register group */ + ALL_PTP_REG = 33U, /*!< PTP register group */ + ALL_DMA_REG = 44U, /*!< DMA register group */ }enet_registers_type_enum; /* dma direction select */ @@ -894,7 +919,7 @@ typedef enum ENET_REG_WRITE /*!< write register */ }enet_regdirection_enum; -/* ENET MAC addresses */ +/* ENET MAC addresses */ typedef enum { ENET_MAC_ADDRESS0 = ((uint32_t)0x00000000), /*!< MAC address0 */ @@ -928,7 +953,7 @@ typedef enum{ ENET_CKNT_END_TO_END = PTP_TSCTL_CKNT(2), /*!< type of end-to-end transparent clock node type for timestamp */ ENET_CKNT_PEER_TO_PEER = PTP_TSCTL_CKNT(3), /*!< type of peer-to-peer transparent clock node type for timestamp */ ENET_PTP_SYSTIME_INIT = ENET_PTP_TSCTL_TMSSTI, /*!< timestamp initialize */ - ENET_PTP_SYSTIME_UPDATE = ENET_PTP_TSCTL_TMSSTU, /*!< timestamp update */ + ENET_PTP_SYSTIME_UPDATE = ENET_PTP_TSCTL_TMSSTU, /*!< timestamp update */ ENET_PTP_ADDEND_UPDATE = ENET_PTP_TSCTL_TMSARU, /*!< addend register update */ ENET_PTP_FINEMODE = (int32_t)(ENET_PTP_TSCTL_TMSFCU| BIT(31)), /*!< the system timestamp uses the fine method for updating */ ENET_PTP_COARSEMODE = ENET_PTP_TSCTL_TMSFCU, /*!< the system timestamp uses the coarse method for updating */ @@ -946,24 +971,24 @@ typedef enum{ typedef struct { uint32_t option_enable; /*!< select which function to configure */ - uint32_t forward_frame; /*!< frame forward related parameters */ + uint32_t forward_frame; /*!< frame forward related parameters */ uint32_t dmabus_mode; /*!< DMA bus mode related parameters */ uint32_t dma_maxburst; /*!< DMA max burst related parameters */ uint32_t dma_arbitration; /*!< DMA Tx and Rx arbitration related parameters */ uint32_t store_forward_mode; /*!< store forward mode related parameters */ uint32_t dma_function; /*!< DMA control related parameters */ - uint32_t vlan_config; /*!< VLAN tag related parameters */ + uint32_t vlan_config; /*!< VLAN tag related parameters */ uint32_t flow_control; /*!< flow control related parameters */ uint32_t hashtable_high; /*!< hash list high 32-bit related parameters */ uint32_t hashtable_low; /*!< hash list low 32-bit related parameters */ uint32_t framesfilter_mode; /*!< frame filter control related parameters */ - uint32_t halfduplex_param; /*!< halfduplex related parameters */ + uint32_t halfduplex_param; /*!< halfduplex related parameters */ uint32_t timer_config; /*!< frame timer related parameters */ uint32_t interframegap; /*!< inter frame gap related parameters */ }enet_initpara_struct; -/* structure for ENET DMA desciptors */ -typedef struct +/* structure for ENET DMA desciptors */ +typedef struct { uint32_t status; /*!< status */ uint32_t control_buffer_size; /*!< control and buffer1, buffer2 lengths */ @@ -974,12 +999,12 @@ typedef struct uint32_t extended_status; /*!< extended status */ uint32_t reserved; /*!< reserved */ uint32_t timestamp_low; /*!< timestamp low */ - uint32_t timestamp_high; /*!< timestamp high */ -#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ - + uint32_t timestamp_high; /*!< timestamp high */ +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + } enet_descriptors_struct; -/* structure of PTP system time */ +/* structure of PTP system time */ typedef struct { uint32_t second; /*!< second of system time */ @@ -992,17 +1017,17 @@ typedef struct #define ENET_BACKOFFLIMIT_10 MAC_CFG_BOL(0) /*!< min (n, 10) */ #define ENET_BACKOFFLIMIT_8 MAC_CFG_BOL(1) /*!< min (n, 8) */ #define ENET_BACKOFFLIMIT_4 MAC_CFG_BOL(2) /*!< min (n, 4) */ -#define ENET_BACKOFFLIMIT_1 MAC_CFG_BOL(3) /*!< min (n, 1) */ +#define ENET_BACKOFFLIMIT_1 MAC_CFG_BOL(3) /*!< min (n, 1) */ #define MAC_CFG_IGBS(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_MAC_CFG_IGBS bit field */ -#define ENET_INTERFRAMEGAP_96BIT MAC_CFG_IGBS(0) /*!< minimum 96 bit times */ +#define ENET_INTERFRAMEGAP_96BIT MAC_CFG_IGBS(0) /*!< minimum 96 bit times */ #define ENET_INTERFRAMEGAP_88BIT MAC_CFG_IGBS(1) /*!< minimum 88 bit times */ #define ENET_INTERFRAMEGAP_80BIT MAC_CFG_IGBS(2) /*!< minimum 80 bit times */ #define ENET_INTERFRAMEGAP_72BIT MAC_CFG_IGBS(3) /*!< minimum 72 bit times */ -#define ENET_INTERFRAMEGAP_64BIT MAC_CFG_IGBS(4) /*!< minimum 64 bit times */ +#define ENET_INTERFRAMEGAP_64BIT MAC_CFG_IGBS(4) /*!< minimum 64 bit times */ #define ENET_INTERFRAMEGAP_56BIT MAC_CFG_IGBS(5) /*!< minimum 56 bit times */ #define ENET_INTERFRAMEGAP_48BIT MAC_CFG_IGBS(6) /*!< minimum 48 bit times */ -#define ENET_INTERFRAMEGAP_40BIT MAC_CFG_IGBS(7) /*!< minimum 40 bit times */ +#define ENET_INTERFRAMEGAP_40BIT MAC_CFG_IGBS(7) /*!< minimum 40 bit times */ #define ENET_TYPEFRAME_CRC_DROP_ENABLE ENET_MAC_CFG_TFCD /*!< FCS field(last 4 bytes) of frame will be dropped before forwarding */ #define ENET_TYPEFRAME_CRC_DROP_DISABLE ((uint32_t)0x00000000U) /*!< FCS field(last 4 bytes) of frame will not be dropped before forwarding */ @@ -1010,13 +1035,13 @@ typedef struct #define ENET_WATCHDOG_ENABLE ((uint32_t)0x00000000U) /*!< the MAC allows no more than 2048 bytes of the frame being received */ #define ENET_WATCHDOG_DISABLE ENET_MAC_CFG_WDD /*!< the MAC disables the watchdog timer on the receiver, and can receive frames of up to 16384 bytes */ - + #define ENET_JABBER_ENABLE ((uint32_t)0x00000000U) /*!< the maximum transmission byte is 2048 */ #define ENET_JABBER_DISABLE ENET_MAC_CFG_JBD /*!< the maximum transmission byte can be 16384 */ #define ENET_CARRIERSENSE_ENABLE ((uint32_t)0x00000000U) /*!< the MAC transmitter generates carrier sense error and aborts the transmission */ #define ENET_CARRIERSENSE_DISABLE ENET_MAC_CFG_CSD /*!< the MAC transmitter ignores the MII CRS signal during frame transmission in half-duplex mode */ - + #define ENET_SPEEDMODE_10M ((uint32_t)0x00000000U) /*!< 10 Mbit/s */ #define ENET_SPEEDMODE_100M ENET_MAC_CFG_SPD /*!< 100 Mbit/s */ @@ -1048,10 +1073,10 @@ typedef struct #define ENET_PCFRM_PREVENT_PAUSEFRAME MAC_FRMF_PCFRM(1) /*!< MAC only forwards all other control frames except pause control frame */ #define ENET_PCFRM_FORWARD_ALL MAC_FRMF_PCFRM(2) /*!< MAC forwards all control frames to application even if they fail the address filter */ #define ENET_PCFRM_FORWARD_FILTERED MAC_FRMF_PCFRM(3) /*!< MAC forwards control frames that only pass the address filter */ - + #define ENET_RX_FILTER_DISABLE ENET_MAC_FRMF_FAR /*!< all received frame are forwarded to application */ #define ENET_RX_FILTER_ENABLE ((uint32_t)0x00000000U) /*!< only the frame passed the filter can be forwarded to application */ - + #define ENET_SRC_FILTER_NORMAL_ENABLE ENET_MAC_FRMF_SAFLT /*!< filter source address */ #define ENET_SRC_FILTER_INVERSE_ENABLE (ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT) /*!< inverse source address filtering result */ #define ENET_SRC_FILTER_DISABLE ((uint32_t)0x00000000U) /*!< source address function in filter disable */ @@ -1060,14 +1085,14 @@ typedef struct #define ENET_BROADCASTFRAMES_ENABLE ((uint32_t)0x00000000U) /*!< the address filters pass all received broadcast frames */ #define ENET_BROADCASTFRAMES_DISABLE ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ - + #define ENET_DEST_FILTER_INVERSE_ENABLE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result */ #define ENET_DEST_FILTER_INVERSE_DISABLE ((uint32_t)0x00000000U) /*!< not inverse DA filtering result */ #define ENET_DEST_FILTER_INVERSE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result function */ #define ENET_PROMISCUOUS_ENABLE ENET_MAC_FRMF_PM /*!< promiscuous mode enabled */ #define ENET_PROMISCUOUS_DISABLE ((uint32_t)0x00000000U) /*!< promiscuous mode disabled */ - + #define ENET_MULTICAST_FILTER_HASH_OR_PERFECT (ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT) /*!< pass multicast frames that match either the perfect or the hash filtering */ #define ENET_MULTICAST_FILTER_HASH ENET_MAC_FRMF_HMF /*!< pass multicast frames that match the hash filtering */ #define ENET_MULTICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass multicast frames that match the perfect filtering */ @@ -1101,7 +1126,7 @@ typedef struct #define ENET_PAUSETIME_MINUS4 MAC_FCTL_PLTS(0) /*!< pause time minus 4 slot times */ #define ENET_PAUSETIME_MINUS28 MAC_FCTL_PLTS(1) /*!< pause time minus 28 slot times */ #define ENET_PAUSETIME_MINUS144 MAC_FCTL_PLTS(2) /*!< pause time minus 144 slot times */ -#define ENET_PAUSETIME_MINUS256 MAC_FCTL_PLTS(3) /*!< pause time minus 256 slot times */ +#define ENET_PAUSETIME_MINUS256 MAC_FCTL_PLTS(3) /*!< pause time minus 256 slot times */ #define ENET_ZERO_QUANTA_PAUSE_ENABLE ((uint32_t)0x00000000U) /*!< enable the automatic zero-quanta generation function */ #define ENET_ZERO_QUANTA_PAUSE_DISABLE ENET_MAC_FCTL_DZQP /*!< disable the automatic zero-quanta generation function */ @@ -1109,7 +1134,7 @@ typedef struct #define ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT ENET_MAC_FCTL_UPFDT /*!< besides the unique multicast address, MAC also use the MAC0 address to detect pause frame */ #define ENET_UNIQUE_PAUSEDETECT ((uint32_t)0x00000000U) /*!< only the unique multicast address for pause frame which is specified in IEEE802.3 can be detected */ - + #define ENET_RX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_RFCEN /*!< enable decoding function for the received pause frame and process it */ #define ENET_RX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< decode function for pause frame is disabled */ #define ENET_RX_FLOWCONTROL ENET_MAC_FCTL_RFCEN /*!< decoding function for the received pause frame and process it */ @@ -1121,33 +1146,34 @@ typedef struct #define ENET_BACK_PRESSURE_ENABLE ENET_MAC_FCTL_FLCBBKPA /*!< enable the back pressure operation in the MAC */ #define ENET_BACK_PRESSURE_DISABLE ((uint32_t)0x00000000U) /*!< disable the back pressure operation in the MAC */ #define ENET_BACK_PRESSURE ENET_MAC_FCTL_FLCBBKPA /*!< the back pressure operation in the MAC */ - + #define MAC_FCTL_PTM(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) /*!< write value to ENET_MAC_FCTL_PTM bit field */ /* mac_vlt register value */ #define MAC_VLT_VLTI(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_VLT_VLTI bit field */ - + #define ENET_VLANTAGCOMPARISON_12BIT ENET_MAC_VLT_VLTC /*!< only low 12 bits of the VLAN tag are used for comparison */ #define ENET_VLANTAGCOMPARISON_16BIT ((uint32_t)0x00000000U) /*!< all 16 bits of the VLAN tag are used for comparison */ -/* mac_wum register value */ +/* mac_wum register value */ #define ENET_WUM_FLAG_WUFFRPR ENET_MAC_WUM_WUFFRPR /*!< wakeup frame filter register poniter reset */ #define ENET_WUM_FLAG_WUFR ENET_MAC_WUM_WUFR /*!< wakeup frame received */ #define ENET_WUM_FLAG_MPKR ENET_MAC_WUM_MPKR /*!< magic packet received */ -#define ENET_WUM_POWER_DOWN ENET_MAC_WUM_PWD /*!< power down mode */ -#define ENET_WUM_MAGIC_PACKET_FRAME ENET_MAC_WUM_MPEN /*!< enable a wakeup event due to magic packet reception */ -#define ENET_WUM_WAKE_UP_FRAME ENET_MAC_WUM_WFEN /*!< enable a wakeup event due to wakeup frame reception */ +#define ENET_WUM_POWER_DOWN ENET_MAC_WUM_PWD /*!< power down mode */ +#define ENET_WUM_MAGIC_PACKET_FRAME ENET_MAC_WUM_MPEN /*!< enable a wakeup event due to magic packet reception */ +#define ENET_WUM_WAKE_UP_FRAME ENET_MAC_WUM_WFEN /*!< enable a wakeup event due to wakeup frame reception */ #define ENET_WUM_GLOBAL_UNICAST ENET_MAC_WUM_GU /*!< any received unicast frame passed filter is considered to be a wakeup frame */ + /* mac_dbg register value */ #define ENET_MAC_RECEIVER_NOT_IDLE ENET_MAC_DBG_MRNI /*!< MAC receiver is not in idle state */ #define ENET_RX_ASYNCHRONOUS_FIFO_STATE ENET_MAC_DBG_RXAFS /*!< Rx asynchronous FIFO status */ -#define ENET_RXFIFO_NOT_WRITING ENET_MAC_DBG_RXFW /*!< RxFIFO is not doing write operation */ +#define ENET_RXFIFO_WRITING ENET_MAC_DBG_RXFW /*!< RxFIFO is doing write operation */ #define ENET_RXFIFO_READ_STATUS ENET_MAC_DBG_RXFRS /*!< RxFIFO read operation status */ #define ENET_RXFIFO_STATE ENET_MAC_DBG_RXFS /*!< RxFIFO state */ #define ENET_MAC_TRANSMITTER_NOT_IDLE ENET_MAC_DBG_MTNI /*!< MAC transmitter is not in idle state */ #define ENET_MAC_TRANSMITTER_STATUS ENET_MAC_DBG_SOMT /*!< status of MAC transmitter */ #define ENET_PAUSE_CONDITION_STATUS ENET_MAC_DBG_PCS /*!< pause condition status */ #define ENET_TXFIFO_READ_STATUS ENET_MAC_DBG_TXFRS /*!< TxFIFO read operation status */ -#define ENET_TXFIFO_NOT_WRITING ENET_MAC_DBG_TXFW /*!< TxFIFO is not doing write operation */ +#define ENET_TXFIFO_WRITING ENET_MAC_DBG_TXFW /*!< TxFIFO is doing write operation */ #define ENET_TXFIFO_NOT_EMPTY ENET_MAC_DBG_TXFNE /*!< TxFIFO is not empty */ #define ENET_TXFIFO_FULL ENET_MAC_DBG_TXFF /*!< TxFIFO is full */ @@ -1176,7 +1202,7 @@ typedef struct #define ENET_ADDRESS_FILTER_SA BIT(30) /*!< use MAC address[47:0] is to compare with the SA fields of the received frame */ #define ENET_ADDRESS_FILTER_DA ((uint32_t)0x00000000) /*!< use MAC address[47:0] is to compare with the DA fields of the received frame */ - + /* mac_fcth register value */ #define MAC_FCTH_RFA(regval) ((BITS(0,2) & ((uint32_t)(regval) << 0))<<8) /*!< write value to ENET_MAC_FCTH_RFA bit field */ #define ENET_ACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFA(0) /*!< threshold level is 256 bytes */ @@ -1215,7 +1241,7 @@ typedef struct /* ptp_tsl register value */ #define GET_PTP_TSL_STMSS(regval) GET_BITS((uint32_t)(regval),0,30) /*!< get value of ENET_PTP_TSL_STMSS bit field */ - + #define ENET_PTP_TIME_POSITIVE ((uint32_t)0x00000000) /*!< time value is positive */ #define ENET_PTP_TIME_NEGATIVE ENET_PTP_TSL_STS /*!< time value is negative */ @@ -1259,7 +1285,7 @@ typedef struct #define ENET_PGBL_4BEAT DMA_BCTL_PGBL(4) /*!< maximum number of beats is 4 */ #define ENET_PGBL_8BEAT DMA_BCTL_PGBL(8) /*!< maximum number of beats is 8 */ #define ENET_PGBL_16BEAT DMA_BCTL_PGBL(16) /*!< maximum number of beats is 16 */ -#define ENET_PGBL_32BEAT DMA_BCTL_PGBL(32) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_32BEAT DMA_BCTL_PGBL(32) /*!< maximum number of beats is 32 */ #define ENET_PGBL_4xPGBL_4BEAT (DMA_BCTL_PGBL(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 4 */ #define ENET_PGBL_4xPGBL_8BEAT (DMA_BCTL_PGBL(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 8 */ #define ENET_PGBL_4xPGBL_16BEAT (DMA_BCTL_PGBL(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 16 */ @@ -1271,7 +1297,7 @@ typedef struct #define ENET_ARBITRATION_RXTX_1_1 DMA_BCTL_RTPR(0) /*!< receive and transmit priority ratio is 1:1*/ #define ENET_ARBITRATION_RXTX_2_1 DMA_BCTL_RTPR(1) /*!< receive and transmit priority ratio is 2:1*/ #define ENET_ARBITRATION_RXTX_3_1 DMA_BCTL_RTPR(2) /*!< receive and transmit priority ratio is 3:1 */ -#define ENET_ARBITRATION_RXTX_4_1 DMA_BCTL_RTPR(3) /*!< receive and transmit priority ratio is 4:1 */ +#define ENET_ARBITRATION_RXTX_4_1 DMA_BCTL_RTPR(3) /*!< receive and transmit priority ratio is 4:1 */ #define ENET_ARBITRATION_RXPRIORTX ENET_DMA_BCTL_DAB /*!< RxDMA has higher priority than TxDMA */ #define ENET_FIXED_BURST_ENABLE ENET_DMA_BCTL_FB /*!< AHB can only use SINGLE/INCR4/INCR8/INCR16 during start of normal burst transfers */ @@ -1283,13 +1309,13 @@ typedef struct #define ENET_RXDP_4BEAT DMA_BCTL_RXDP(4) /*!< maximum number of beats 4 */ #define ENET_RXDP_8BEAT DMA_BCTL_RXDP(8) /*!< maximum number of beats 8 */ #define ENET_RXDP_16BEAT DMA_BCTL_RXDP(16) /*!< maximum number of beats 16 */ -#define ENET_RXDP_32BEAT DMA_BCTL_RXDP(32) /*!< maximum number of beats 32 */ +#define ENET_RXDP_32BEAT DMA_BCTL_RXDP(32) /*!< maximum number of beats 32 */ #define ENET_RXDP_4xPGBL_4BEAT (DMA_BCTL_RXDP(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 4 */ #define ENET_RXDP_4xPGBL_8BEAT (DMA_BCTL_RXDP(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 8 */ #define ENET_RXDP_4xPGBL_16BEAT (DMA_BCTL_RXDP(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 16 */ #define ENET_RXDP_4xPGBL_32BEAT (DMA_BCTL_RXDP(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 32 */ #define ENET_RXDP_4xPGBL_64BEAT (DMA_BCTL_RXDP(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 64 */ -#define ENET_RXDP_4xPGBL_128BEAT (DMA_BCTL_RXDP(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 128 */ +#define ENET_RXDP_4xPGBL_128BEAT (DMA_BCTL_RXDP(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 128 */ #define ENET_RXTX_DIFFERENT_PGBL ENET_DMA_BCTL_UIP /*!< RxDMA uses the RXDP[5:0], while TxDMA uses the PGBL[5:0] */ #define ENET_RXTX_SAME_PGBL ((uint32_t)0x00000000) /*!< RxDMA/TxDMA uses PGBL[5:0] */ @@ -1347,7 +1373,7 @@ typedef struct #define ENET_FLUSH_RXFRAME_ENABLE ((uint32_t)0x00000000) /*!< RxDMA flushes all frames */ #define ENET_FLUSH_RXFRAME_DISABLE ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush any frames */ -#define ENET_FLUSH_RXFRAME ENET_DMA_CTL_DAFRF /*!< RxDMA flushes frames function */ +#define ENET_NO_FLUSH_RXFRAME ENET_DMA_CTL_DAFRF /*!< RxDMA flushes frames function */ #define ENET_TX_MODE_STOREFORWARD ENET_DMA_CTL_TSFD /*!< TxFIFO operates in store-and-forward mode */ #define ENET_TX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< TxFIFO operates in cut-through mode */ @@ -1357,7 +1383,7 @@ typedef struct #define ENET_FORWARD_ERRFRAMES (ENET_DMA_CTL_FERF<<2) /*!< the function that all frame received with error except runt error are forwarded to memory */ #define ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE (ENET_DMA_CTL_FUF<<2) /*!< forward undersized good frames */ -#define ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drops all frames whose length is less than 64 bytes */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drops all frames whose length is less than 64 bytes */ #define ENET_FORWARD_UNDERSZ_GOODFRAMES (ENET_DMA_CTL_FUF<<2) /*!< the function that forwarding undersized good frames */ #define ENET_SECONDFRAME_OPT_ENABLE ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame mode enable*/ @@ -1376,10 +1402,10 @@ typedef struct #define GET_TDES0_COCNT(regval) GET_BITS((regval),3,6) /*!< get value of ENET DMA TDES0 CONT bit field */ #define TDES0_CM(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) /*!< write value to ENET DMA TDES0 CM bit field */ -#define ENET_CHECKSUM_DISABLE TDES0_CM(0) /*!< checksum insertion disabled */ -#define ENET_CHECKSUM_IPV4HEADER TDES0_CM(1) /*!< only IP header checksum calculation and insertion are enabled */ -#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT TDES0_CM(2) /*!< TCP/UDP/ICMP checksum insertion calculated but pseudo-header */ -#define ENET_CHECKSUM_TCPUDPICMP_FULL TDES0_CM(3) /*!< TCP/UDP/ICMP checksum insertion fully calculated */ +#define ENET_CHECKSUM_DISABLE TDES0_CM(0) /*!< checksum insertion disabled */ +#define ENET_CHECKSUM_IPV4HEADER TDES0_CM(1) /*!< only IP header checksum calculation and insertion are enabled */ +#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT TDES0_CM(2) /*!< TCP/UDP/ICMP checksum insertion calculated but pseudo-header */ +#define ENET_CHECKSUM_TCPUDPICMP_FULL TDES0_CM(3) /*!< TCP/UDP/ICMP checksum insertion fully calculated */ /* dma tx descriptor tdes1 register value */ #define TDES1_TB1S(regval) (BITS(0,12) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA TDES1 TB1S bit field */ @@ -1413,18 +1439,18 @@ typedef struct #define ENET_MSC_PRESET_MASK (~(ENET_MSC_CTL_PMC | ENET_MSC_CTL_AFHPM)) /*!< ENET_MSC_CTL preset mask */ #ifdef SELECT_DESCRIPTORS_ENHANCED_MODE -#define ETH_DMATXDESC_SIZE 0x20U /*!< TxDMA enhanced descriptor size */ -#define ETH_DMARXDESC_SIZE 0x20U /*!< RxDMA enhanced descriptor size */ +#define ETH_DMATXDESC_SIZE ((uint32_t)0x00000020U) /*!< TxDMA enhanced descriptor size */ +#define ETH_DMARXDESC_SIZE ((uint32_t)0x00000020U) /*!< RxDMA enhanced descriptor size */ #else -#define ETH_DMATXDESC_SIZE 0x10U /*!< TxDMA descriptor size */ -#define ETH_DMARXDESC_SIZE 0x10U /*!< RxDMA descriptor size */ -#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ +#define ETH_DMATXDESC_SIZE ((uint32_t)0x00000010U) /*!< TxDMA descriptor size */ +#define ETH_DMARXDESC_SIZE ((uint32_t)0x00000010U) /*!< RxDMA descriptor size */ +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ /* ENET remote wake-up frame register length */ #define ETH_WAKEUP_REGISTER_LENGTH 8U /*!< remote wake-up frame register length */ -/* ENET frame size */ -#define ENET_MAX_FRAME_SIZE 1524U /*!< header + frame_extra + payload + CRC */ +/* ENET frame size */ +#define ENET_MAX_FRAME_SIZE 1524U /*!< header + frame_extra + payload + CRC */ /* ENET delay timeout */ #define ENET_DELAY_TO ((uint32_t)0x0004FFFFU) /*!< ENET delay timeout */ @@ -1459,12 +1485,12 @@ ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length); /* configure the transmit IP frame checksum offload calculation and insertion */ void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum); /* ENET Tx and Rx function enable (include MAC and DMA module) */ -void enet_enable(void); +void enet_enable(void); /* ENET Tx and Rx function disable (include MAC and DMA module) */ void enet_disable(void); /* configure MAC address */ void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]); -/* get MAC address */ +/* get MAC address */ void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]); /* get the ENET MAC/MSC/PTP/DMA status flag */ @@ -1532,7 +1558,7 @@ void enet_flowcontrol_feature_disable(uint32_t feature); /* DMA function */ /* get the dma transmit/receive process state */ -uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction); +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction); /* poll the dma transmission/reception enable */ void enet_dmaprocess_resume(enet_dmadirection_enum direction); /* check and recover the Rx process */ @@ -1552,7 +1578,7 @@ FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) /* set the bit flag of ENET dma tx descriptor */ void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag); /* clear the bit flag of ENET dma tx descriptor */ -void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag); +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag); /* when receiving the completed, set RS bit in ENET_DMA_STAT register will immediately set */ void enet_rx_desc_immediate_receive_complete_interrupt(enet_descriptors_struct *desc); /* when receiving the completed, set RS bit in ENET_DMA_STAT register will is set after a configurable delay time */ @@ -1616,13 +1642,13 @@ void enet_wum_feature_disable(uint32_t feature); /* MSC function */ /* reset the MAC statistics counters */ void enet_msc_counters_reset(void); -/* enable the MAC statistics counter features */ +/* enable the MAC statistics counter features */ void enet_msc_feature_enable(uint32_t feature); -/* disable the MAC statistics counter features */ +/* disable the MAC statistics counter features */ void enet_msc_feature_disable(uint32_t feature); /* configure MAC statistics counters preset mode */ void enet_msc_counters_preset_config(enet_msc_preset_enum mode); -/* get MAC statistics counter */ +/* get MAC statistics counter */ uint32_t enet_msc_counters_get(enet_msc_counter_enum counter); /* PTP function */ @@ -1649,16 +1675,6 @@ void enet_ptp_pps_output_frequency_config(uint32_t freq); /* internal function */ /* reset the ENET initpara struct, call it before using enet_initpara_config() */ void enet_initpara_reset(void); -/* initialize ENET peripheral with generally concerned parameters, call it by enet_init() */ -static void enet_default_init(void); -#ifdef USE_DELAY -/* user can provide more timing precise _ENET_DELAY_ function */ -#define _ENET_DELAY_ delay_ms -#else -/* insert a delay time */ -static void enet_delay(uint32_t ncount); -/* default _ENET_DELAY_ function with less precise timing */ -#define _ENET_DELAY_ enet_delay -#endif + #endif /* GD32F4XX_ENET_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h index 3844c699d2..94baf2f6f3 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_exmc.h - \brief definitions for the EXMC + \file gd32f4xx_exmc.h + \brief definitions for the EXMC + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_EXMC_H @@ -15,224 +40,224 @@ #include "gd32f4xx.h" /* EXMC definitions */ -#define EXMC (EXMC_BASE) /*!< EXMC register base address */ -#define EXMC_NOR_PSRAM (EXMC_BASE - 0x40000000) /*!< EXMC NOR/PSRAM base address */ -#define EXMC_NAND (EXMC_BASE - 0x30000000) /*!< EXMC NAND base address */ -#define EXMC_PCCARD (EXMC_BASE - 0x10000000) /*!< EXMC PC card base address */ -#define EXMC_SDRAM (EXMC_BASE + 0x20000000) /*!< EXMC SDRAM base address */ +#define EXMC (EXMC_BASE) /*!< EXMC register base address */ +#define EXMC_NOR_PSRAM (EXMC_BASE - 0x40000000) /*!< EXMC NOR/PSRAM base address */ +#define EXMC_NAND (EXMC_BASE - 0x30000000) /*!< EXMC NAND base address */ +#define EXMC_PCCARD (EXMC_BASE - 0x10000000) /*!< EXMC PC card base address */ +#define EXMC_SDRAM (EXMC_BASE + 0x20000000) /*!< EXMC SDRAM base address */ /* registers definitions */ /* NOR/PSRAM */ -#define EXMC_SNCTL0 REG32(EXMC + 0x00U) /*!< EXMC SRAM/NOR flash control register */ -#define EXMC_SNTCFG0 REG32(EXMC + 0x04U) /*!< EXMC SRAM/NOR flash timing configuration register */ -#define EXMC_SNWTCFG0 REG32(EXMC + 0x104U) /*!< EXMC SRAM/NOR flash write timing configuration register */ +#define EXMC_SNCTL0 REG32(EXMC + 0x00U) /*!< EXMC SRAM/NOR flash control register for region0 */ +#define EXMC_SNTCFG0 REG32(EXMC + 0x04U) /*!< EXMC SRAM/NOR flash timing configuration register for region0 */ +#define EXMC_SNWTCFG0 REG32(EXMC + 0x104U) /*!< EXMC SRAM/NOR flash write timing configuration register for region0 */ -#define EXMC_SNCTL1 REG32(EXMC + 0x08U) /*!< EXMC SRAM/NOR flash control register */ -#define EXMC_SNTCFG1 REG32(EXMC + 0x0CU) /*!< EXMC SRAM/NOR flash timing configuration register */ -#define EXMC_SNWTCFG1 REG32(EXMC + 0x10CU) /*!< EXMC SRAM/NOR flash write timing configuration register */ +#define EXMC_SNCTL1 REG32(EXMC + 0x08U) /*!< EXMC SRAM/NOR flash control register for region1 */ +#define EXMC_SNTCFG1 REG32(EXMC + 0x0CU) /*!< EXMC SRAM/NOR flash timing configuration register for region1 */ +#define EXMC_SNWTCFG1 REG32(EXMC + 0x10CU) /*!< EXMC SRAM/NOR flash write timing configuration register for region1 */ -#define EXMC_SNCTL2 REG32(EXMC + 0x10U) /*!< EXMC SRAM/NOR flash control register */ -#define EXMC_SNTCFG2 REG32(EXMC + 0x14U) /*!< EXMC SRAM/NOR flash timing configuration register */ -#define EXMC_SNWTCFG2 REG32(EXMC + 0x114U) /*!< EXMC SRAM/NOR flash write timing configuration register */ +#define EXMC_SNCTL2 REG32(EXMC + 0x10U) /*!< EXMC SRAM/NOR flash control register for region2 */ +#define EXMC_SNTCFG2 REG32(EXMC + 0x14U) /*!< EXMC SRAM/NOR flash timing configuration register for region2 */ +#define EXMC_SNWTCFG2 REG32(EXMC + 0x114U) /*!< EXMC SRAM/NOR flash write timing configuration register for region2 */ -#define EXMC_SNCTL3 REG32(EXMC + 0x18U) /*!< EXMC SRAM/NOR flash control register */ -#define EXMC_SNTCFG3 REG32(EXMC + 0x1CU) /*!< EXMC SRAM/NOR flash timing configuration register */ -#define EXMC_SNWTCFG3 REG32(EXMC + 0x11CU) /*!< EXMC SRAM/NOR flash write timing configuration register */ +#define EXMC_SNCTL3 REG32(EXMC + 0x18U) /*!< EXMC SRAM/NOR flash control register for region3 */ +#define EXMC_SNTCFG3 REG32(EXMC + 0x1CU) /*!< EXMC SRAM/NOR flash timing configuration register for region3 */ +#define EXMC_SNWTCFG3 REG32(EXMC + 0x11CU) /*!< EXMC SRAM/NOR flash write timing configuration register for region3 */ /* NAND/PC card */ -#define EXMC_NPCTL1 REG32(EXMC + 0x40U) /*!< EXMC NAND/PC card control register */ -#define EXMC_NPINTEN1 REG32(EXMC + 0x44U) /*!< EXMC NAND/PC card interrupt enable register */ -#define EXMC_NPCTCFG1 REG32(EXMC + 0x48U) /*!< EXMC NAND/PC card common space timing configuration register */ -#define EXMC_NPATCFG1 REG32(EXMC + 0x4CU) /*!< EXMC NAND/PC card attribute space timing configuration register */ -#define EXMC_NECC1 REG32(EXMC + 0x54U) /*!< EXMC NAND ECC register */ +#define EXMC_NPCTL1 REG32(EXMC + 0x60U) /*!< EXMC NAND/PC card control register for bank1 */ +#define EXMC_NPINTEN1 REG32(EXMC + 0x64U) /*!< EXMC NAND/PC card interrupt enable register for bank1 */ +#define EXMC_NPCTCFG1 REG32(EXMC + 0x68U) /*!< EXMC NAND/PC card common space timing configuration register for bank1 */ +#define EXMC_NPATCFG1 REG32(EXMC + 0x6CU) /*!< EXMC NAND/PC card attribute space timing configuration register for bank1 */ +#define EXMC_NECC1 REG32(EXMC + 0x74U) /*!< EXMC NAND ECC register */ -#define EXMC_NPCTL2 REG32(EXMC + 0x60U) /*!< EXMC NAND/PC card control register */ -#define EXMC_NPINTEN2 REG32(EXMC + 0x64U) /*!< EXMC NAND/PC card interrupt enable register */ -#define EXMC_NPCTCFG2 REG32(EXMC + 0x68U) /*!< EXMC NAND/PC card common space timing configuration register */ -#define EXMC_NPATCFG2 REG32(EXMC + 0x6CU) /*!< EXMC NAND/PC card attribute space timing configuration register */ -#define EXMC_NECC2 REG32(EXMC + 0x74U) /*!< EXMC NAND ECC register */ +#define EXMC_NPCTL2 REG32(EXMC + 0x80U) /*!< EXMC NAND/PC card control register for bank2 */ +#define EXMC_NPINTEN2 REG32(EXMC + 0x84U) /*!< EXMC NAND/PC card interrupt enable register for bank2 */ +#define EXMC_NPCTCFG2 REG32(EXMC + 0x88U) /*!< EXMC NAND/PC card common space timing configuration register for bank2 */ +#define EXMC_NPATCFG2 REG32(EXMC + 0x8CU) /*!< EXMC NAND/PC card attribute space timing configuration register for bank2 */ +#define EXMC_NECC2 REG32(EXMC + 0x94U) /*!< EXMC NAND ECC register */ -#define EXMC_NPCTL3 REG32(EXMC + 0x80U) /*!< EXMC NAND/PC card control register */ -#define EXMC_NPINTEN3 REG32(EXMC + 0x84U) /*!< EXMC NAND/PC card interrupt enable register */ -#define EXMC_NPCTCFG3 REG32(EXMC + 0x88U) /*!< EXMC NAND/PC card common space timing configuration register */ -#define EXMC_NPATCFG3 REG32(EXMC + 0x8CU) /*!< EXMC NAND/PC card attribute space timing configuration register */ -#define EXMC_PIOTCFG3 REG32(EXMC + 0xB0U) /*!< EXMC PC card I/O space timing configuration register */ +#define EXMC_NPCTL3 REG32(EXMC + 0xA0U) /*!< EXMC NAND/PC card control register for bank3 */ +#define EXMC_NPINTEN3 REG32(EXMC + 0xA4U) /*!< EXMC NAND/PC card interrupt enable register for bank3 */ +#define EXMC_NPCTCFG3 REG32(EXMC + 0xA8U) /*!< EXMC NAND/PC card common space timing configuration register for bank3 */ +#define EXMC_NPATCFG3 REG32(EXMC + 0xACU) /*!< EXMC NAND/PC card attribute space timing configuration register for bank3 */ +#define EXMC_PIOTCFG3 REG32(EXMC + 0xB0U) /*!< EXMC PC card I/O space timing configuration register for bank3 */ /* SDRAM */ -#define EXMC_SDCTL0 REG32(EXMC + 0x140U) /*!< EXMC SDRAM control register */ -#define EXMC_SDTCFG0 REG32(EXMC + 0x148U) /*!< EXMC SDRAM timing configuration register register */ +#define EXMC_SDCTL0 REG32(EXMC + 0x140U) /*!< EXMC SDRAM control register for device0 */ +#define EXMC_SDTCFG0 REG32(EXMC + 0x148U) /*!< EXMC SDRAM timing configuration register register for device0 */ -#define EXMC_SDCTL1 REG32(EXMC + 0x144U) /*!< EXMC SDRAM control register */ -#define EXMC_SDTCFG1 REG32(EXMC + 0x14CU) /*!< EXMC SDRAM timing configuration register register */ +#define EXMC_SDCTL1 REG32(EXMC + 0x144U) /*!< EXMC SDRAM control register for device1 */ +#define EXMC_SDTCFG1 REG32(EXMC + 0x14CU) /*!< EXMC SDRAM timing configuration register register for device1 */ -#define EXMC_SDCMD REG32(EXMC + 0x150U) /*!< EXMC SDRAM command register */ -#define EXMC_SDARI REG32(EXMC + 0x154U) /*!< EXMC SDRAM auto-refresh interval register */ -#define EXMC_SDSTAT REG32(EXMC + 0x158U) /*!< EXMC SDRAM status register */ -#define EXMC_SDRSCTL REG32(EXMC + 0x180U) /*!< EXMC SDRAM read sample control register */ +#define EXMC_SDCMD REG32(EXMC + 0x150U) /*!< EXMC SDRAM command register */ +#define EXMC_SDARI REG32(EXMC + 0x154U) /*!< EXMC SDRAM auto-refresh interval register */ +#define EXMC_SDSTAT REG32(EXMC + 0x158U) /*!< EXMC SDRAM status register */ +#define EXMC_SDRSCTL REG32(EXMC + 0x180U) /*!< EXMC SDRAM read sample control register */ /* SQPI PSRAM */ -#define EXMC_SINIT REG32(EXMC + 0x310U) /*!< EXMC SPI initialization register */ -#define EXMC_SRCMD REG32(EXMC + 0x320U) /*!< EXMC SPI read command register */ -#define EXMC_SWCMD REG32(EXMC + 0x330U) /*!< EXMC SPI write command register */ -#define EXMC_SIDL REG32(EXMC + 0x340U) /*!< EXMC SPI ID low register */ -#define EXMC_SIDH REG32(EXMC + 0x350U) /*!< EXMC SPI ID high register */ +#define EXMC_SINIT REG32(EXMC + 0x310U) /*!< EXMC SPI initialization register */ +#define EXMC_SRCMD REG32(EXMC + 0x320U) /*!< EXMC SPI read command register */ +#define EXMC_SWCMD REG32(EXMC + 0x330U) /*!< EXMC SPI write command register */ +#define EXMC_SIDL REG32(EXMC + 0x340U) /*!< EXMC SPI ID low register */ +#define EXMC_SIDH REG32(EXMC + 0x350U) /*!< EXMC SPI ID high register */ /* bits definitions */ /* EXMC_SNCTLx,x=0..3 */ -#define EXMC_SNCTL_NRBKEN BIT(0) /*!< NOR bank enable */ -#define EXMC_SNCTL_NRMUX BIT(1) /*!< NOR bank memory address/data multiplexing */ -#define EXMC_SNCTL_NRTP BITS(2,3) /*!< NOR bank memory type */ -#define EXMC_SNCTL_NRW BITS(4,5) /*!< NOR bank memory data bus width */ -#define EXMC_SNCTL_NREN BIT(6) /*!< NOR flash access enable */ -#define EXMC_SNCTL_SBRSTEN BIT(8) /*!< synchronous burst enable */ -#define EXMC_SNCTL_NRWTPOL BIT(9) /*!< NWAIT signal polarity */ -#define EXMC_SNCTL_WRAPEN BIT(10) /*!< wrapped burst mode enable */ -#define EXMC_SNCTL_NRWTCFG BIT(11) /*!< NWAIT signal configuration, only work in synchronous mode */ -#define EXMC_SNCTL_WREN BIT(12) /*!< write enable */ -#define EXMC_SNCTL_NRWTEN BIT(13) /*!< NWAIT signal enable */ -#define EXMC_SNCTL_EXMODEN BIT(14) /*!< extended mode enable */ -#define EXMC_SNCTL_ASYNCWAIT BIT(15) /*!< asynchronous wait */ -#define EXMC_SNCTL_CPS BITS(16,18) /*!< CRAM page size */ -#define EXMC_SNCTL_SYNCWR BIT(19) /*!< synchronous write */ -#define EXMC_SNCTL_CCK BIT(20) /*!< consecutive clock */ +#define EXMC_SNCTL_NRBKEN BIT(0) /*!< NOR bank enable */ +#define EXMC_SNCTL_NRMUX BIT(1) /*!< NOR bank memory address/data multiplexing enable */ +#define EXMC_SNCTL_NRTP BITS(2,3) /*!< NOR bank memory type */ +#define EXMC_SNCTL_NRW BITS(4,5) /*!< NOR bank memory data bus width */ +#define EXMC_SNCTL_NREN BIT(6) /*!< NOR flash access enable */ +#define EXMC_SNCTL_SBRSTEN BIT(8) /*!< synchronous burst enable */ +#define EXMC_SNCTL_NRWTPOL BIT(9) /*!< NWAIT signal polarity */ +#define EXMC_SNCTL_WRAPEN BIT(10) /*!< wrapped burst mode enable */ +#define EXMC_SNCTL_NRWTCFG BIT(11) /*!< NWAIT signal configuration, only work in synchronous mode */ +#define EXMC_SNCTL_WREN BIT(12) /*!< write enable */ +#define EXMC_SNCTL_NRWTEN BIT(13) /*!< NWAIT signal enable */ +#define EXMC_SNCTL_EXMODEN BIT(14) /*!< extended mode enable */ +#define EXMC_SNCTL_ASYNCWAIT BIT(15) /*!< asynchronous wait enable */ +#define EXMC_SNCTL_CPS BITS(16,18) /*!< CRAM page size */ +#define EXMC_SNCTL_SYNCWR BIT(19) /*!< synchronous write config */ +#define EXMC_SNCTL_CCK BIT(20) /*!< consecutive clock config */ /* EXMC_SNTCFGx,x=0..3 */ -#define EXMC_SNTCFG_ASET BITS(0,3) /*!< address setup time */ -#define EXMC_SNTCFG_AHLD BITS(4,7) /*!< address hold time */ -#define EXMC_SNTCFG_DSET BITS(8,15) /*!< data setup time */ -#define EXMC_SNTCFG_BUSLAT BITS(16,19) /*!< bus latency */ -#define EXMC_SNTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ -#define EXMC_SNTCFG_DLAT BITS(24,27) /*!< data latency for NOR flash */ -#define EXMC_SNTCFG_ASYNCMOD BITS(28,29) /*!< asynchronous access mode */ +#define EXMC_SNTCFG_ASET BITS(0,3) /*!< asynchronous address setup time */ +#define EXMC_SNTCFG_AHLD BITS(4,7) /*!< asynchronous address hold time */ +#define EXMC_SNTCFG_DSET BITS(8,15) /*!< asynchronous data setup time */ +#define EXMC_SNTCFG_BUSLAT BITS(16,19) /*!< bus latency */ +#define EXMC_SNTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ +#define EXMC_SNTCFG_DLAT BITS(24,27) /*!< synchronous data latency for NOR flash */ +#define EXMC_SNTCFG_ASYNCMOD BITS(28,29) /*!< asynchronous access mode */ /* EXMC_SNWTCFGx,x=0..3 */ -#define EXMC_SNWTCFG_WASET BITS(0,3) /*!< address setup time */ -#define EXMC_SNWTCFG_WAHLD BITS(4,7) /*!< address hold time */ -#define EXMC_SNWTCFG_WDSET BITS(8,15) /*!< data setup time */ -#define EXMC_SNWTCFG_WBUSLAT BITS(16,19) /*!< bus latency */ -#define EXMC_SNWTCFG_WASYNCMOD BITS(28,29) /*!< asynchronous access mode */ +#define EXMC_SNWTCFG_WASET BITS(0,3) /*!< asynchronous address setup time */ +#define EXMC_SNWTCFG_WAHLD BITS(4,7) /*!< asynchronous address hold time */ +#define EXMC_SNWTCFG_WDSET BITS(8,15) /*!< asynchronous data setup time */ +#define EXMC_SNWTCFG_WBUSLAT BITS(16,19) /*!< bus latency */ +#define EXMC_SNWTCFG_WASYNCMOD BITS(28,29) /*!< asynchronous access mode */ /* EXMC_NPCTLx,x=1..3 */ -#define EXMC_NPCTL_NDWTEN BIT(1) /*!< wait feature enable */ -#define EXMC_NPCTL_NDBKEN BIT(2) /*!< NAND bank enable */ -#define EXMC_NPCTL_NDTP BIT(3) /*!< NAND bank memory type */ -#define EXMC_NPCTL_NDW BITS(4,5) /*!< NAND bank memory data bus width */ -#define EXMC_NPCTL_ECCEN BIT(6) /*!< ECC enable */ -#define EXMC_NPCTL_CTR BITS(9,12) /*!< CLE to RE delay */ -#define EXMC_NPCTL_ATR BITS(13,16) /*!< ALE to RE delay */ -#define EXMC_NPCTL_ECCSZ BITS(17,19) /*!< ECC size */ +#define EXMC_NPCTL_NDWTEN BIT(1) /*!< wait feature enable */ +#define EXMC_NPCTL_NDBKEN BIT(2) /*!< NAND bank enable */ +#define EXMC_NPCTL_NDTP BIT(3) /*!< NAND bank memory type */ +#define EXMC_NPCTL_NDW BITS(4,5) /*!< NAND bank memory data bus width */ +#define EXMC_NPCTL_ECCEN BIT(6) /*!< ECC enable */ +#define EXMC_NPCTL_CTR BITS(9,12) /*!< CLE to RE delay */ +#define EXMC_NPCTL_ATR BITS(13,16) /*!< ALE to RE delay */ +#define EXMC_NPCTL_ECCSZ BITS(17,19) /*!< ECC size */ /* EXMC_NPINTENx,x=1..3 */ -#define EXMC_NPINTEN_INTRS BIT(0) /*!< interrupt rising edge status */ -#define EXMC_NPINTEN_INTHS BIT(1) /*!< interrupt high-level status */ -#define EXMC_NPINTEN_INTFS BIT(2) /*!< interrupt falling edge status */ -#define EXMC_NPINTEN_INTREN BIT(3) /*!< interrupt rising edge detection enable */ -#define EXMC_NPINTEN_INTHEN BIT(4) /*!< interrupt high-level detection enable */ -#define EXMC_NPINTEN_INTFEN BIT(5) /*!< interrupt falling edge detection enable */ -#define EXMC_NPINTEN_INTEPT BIT(6) /*!< FIFO empty flag */ +#define EXMC_NPINTEN_INTRS BIT(0) /*!< interrupt rising edge status */ +#define EXMC_NPINTEN_INTHS BIT(1) /*!< interrupt high-level status */ +#define EXMC_NPINTEN_INTFS BIT(2) /*!< interrupt falling edge status */ +#define EXMC_NPINTEN_INTREN BIT(3) /*!< interrupt rising edge detection enable */ +#define EXMC_NPINTEN_INTHEN BIT(4) /*!< interrupt high-level detection enable */ +#define EXMC_NPINTEN_INTFEN BIT(5) /*!< interrupt falling edge detection enable */ +#define EXMC_NPINTEN_FFEPT BIT(6) /*!< FIFO empty flag */ /* EXMC_NPCTCFGx,x=1..3 */ -#define EXMC_NPCTCFG_COMSET BITS(0,7) /*!< common memory data bus HiZ time */ -#define EXMC_NPCTCFG_COMWAIT BITS(8,15) /*!< common memory hold time */ -#define EXMC_NPCTCFG_COMHLD BITS(16,23) /*!< common memory wait time */ -#define EXMC_NPCTCFG_COMHIZ BITS(24,31) /*!< common memory setup time */ +#define EXMC_NPCTCFG_COMSET BITS(0,7) /*!< common memory setup time */ +#define EXMC_NPCTCFG_COMWAIT BITS(8,15) /*!< common memory wait time */ +#define EXMC_NPCTCFG_COMHLD BITS(16,23) /*!< common memory hold time */ +#define EXMC_NPCTCFG_COMHIZ BITS(24,31) /*!< common memory data bus HiZ time */ /* EXMC_NPATCFGx,x=1..3 */ -#define EXMC_NPATCFG_ATTSET BITS(0,7) /*!< attribute memory data bus HiZ time */ -#define EXMC_NPATCFG_ATTWAIT BITS(8,15) /*!< attribute memory hold time */ -#define EXMC_NPATCFG_ATTHLD BITS(16,23) /*!< attribute memory wait time */ -#define EXMC_NPATCFG_ATTHIZ BITS(24,31) /*!< attribute memory setup time */ +#define EXMC_NPATCFG_ATTSET BITS(0,7) /*!< attribute memory setup time */ +#define EXMC_NPATCFG_ATTWAIT BITS(8,15) /*!< attribute memory wait time */ +#define EXMC_NPATCFG_ATTHLD BITS(16,23) /*!< attribute memory hold time */ +#define EXMC_NPATCFG_ATTHIZ BITS(24,31) /*!< attribute memory data bus HiZ time */ /* EXMC_PIOTCFG3 */ -#define EXMC_PIOTCFG3_IOSET BITS(0,7) /*!< IO space data bus HiZ time */ -#define EXMC_PIOTCFG3_IOWAIT BITS(8,15) /*!< IO space hold time */ -#define EXMC_PIOTCFG3_IOHLD BITS(16,23) /*!< IO space wait time */ -#define EXMC_PIOTCFG3_IOHIZ BITS(24,31) /*!< IO space setup time */ +#define EXMC_PIOTCFG3_IOSET BITS(0,7) /*!< IO space setup time */ +#define EXMC_PIOTCFG3_IOWAIT BITS(8,15) /*!< IO space wait time */ +#define EXMC_PIOTCFG3_IOHLD BITS(16,23) /*!< IO space hold time */ +#define EXMC_PIOTCFG3_IOHIZ BITS(24,31) /*!< IO space data bus HiZ time */ /* EXMC_NECCx,x=1..2 */ -#define EXMC_NECC_ECC BITS(0,31) /*!< ECC result */ +#define EXMC_NECC_ECC BITS(0,31) /*!< ECC result */ /* EXMC_SDCTLx,x=0..1 */ -#define EXMC_SDCTL_CAW BITS(0,1) /*!< column address bit width */ -#define EXMC_SDCTL_RAW BITS(2,3) /*!< row address bit width */ -#define EXMC_SDCTL_SDW BITS(4,5) /*!< SDRAM data bus width */ -#define EXMC_SDCTL_NBK BIT(6) /*!< number of banks */ -#define EXMC_SDCTL_CL BIT(7,8) /*!< CAS Latency */ -#define EXMC_SDCTL_WPEN BIT(9) /*!< write protection enable */ -#define EXMC_SDCTL_SDCLK BITS(10,11) /*!< SDRAM clock configuration */ -#define EXMC_SDCTL_BRSTRD BIT(12) /*!< burst read */ -#define EXMC_SDCTL_PIPED BITS(13,14) /*!< pipeline delay */ +#define EXMC_SDCTL_CAW BITS(0,1) /*!< column address bit width */ +#define EXMC_SDCTL_RAW BITS(2,3) /*!< row address bit width */ +#define EXMC_SDCTL_SDW BITS(4,5) /*!< SDRAM data bus width */ +#define EXMC_SDCTL_NBK BIT(6) /*!< number of banks */ +#define EXMC_SDCTL_CL BIT(7,8) /*!< CAS Latency */ +#define EXMC_SDCTL_WPEN BIT(9) /*!< write protection enable */ +#define EXMC_SDCTL_SDCLK BITS(10,11) /*!< SDRAM clock configuration */ +#define EXMC_SDCTL_BRSTRD BIT(12) /*!< burst read enable */ +#define EXMC_SDCTL_PIPED BITS(13,14) /*!< pipeline delay */ /* EXMC_SDTCFGx,x=0..1 */ -#define EXMC_SDTCFG_LMRD BITS(0,3) /*!< load mode register delay */ -#define EXMC_SDTCFG_XSRD BITS(4,7) /*!< exit self-refresh delay */ -#define EXMC_SDTCFG_RASD BITS(8,11) /*!< row address select delay */ -#define EXMC_SDTCFG_ARFD BITS(12,15) /*!< auto refresh delay */ -#define EXMC_SDTCFG_WRD BITS(16,19) /*!< write recovery delay */ -#define EXMC_SDTCFG_RPD BITS(20,23) /*!< row precharge delay */ -#define EXMC_SDTCFG_RCD BITS(24,27) /*!< row to column delay */ +#define EXMC_SDTCFG_LMRD BITS(0,3) /*!< load mode register delay */ +#define EXMC_SDTCFG_XSRD BITS(4,7) /*!< exit self-refresh delay */ +#define EXMC_SDTCFG_RASD BITS(8,11) /*!< row address select delay */ +#define EXMC_SDTCFG_ARFD BITS(12,15) /*!< auto refresh delay */ +#define EXMC_SDTCFG_WRD BITS(16,19) /*!< write recovery delay */ +#define EXMC_SDTCFG_RPD BITS(20,23) /*!< row precharge delay */ +#define EXMC_SDTCFG_RCD BITS(24,27) /*!< row to column delay */ /* EXMC_SDCMD */ -#define EXMC_SDCMD_CMD BITS(0,2) /*!< command */ -#define EXMC_SDCMD_DS1 BIT(3) /*!< device select 1 */ -#define EXMC_SDCMD_DS0 BIT(4) /*!< device select 0 */ -#define EXMC_SDCMD_NARF BITS(5,8) /*!< number of successive auto-refresh */ -#define EXMC_SDCMD_MRC BITS(9,21) /*!< mode register content */ +#define EXMC_SDCMD_CMD BITS(0,2) /*!< command */ +#define EXMC_SDCMD_DS1 BIT(3) /*!< select device1 */ +#define EXMC_SDCMD_DS0 BIT(4) /*!< select device0 */ +#define EXMC_SDCMD_NARF BITS(5,8) /*!< number of successive auto-refresh */ +#define EXMC_SDCMD_MRC BITS(9,21) /*!< mode register content */ /* EXMC_SDARI */ -#define EXMC_SDARI_REC BIT(0) /*!< refresh error flag clear */ -#define EXMC_SDARI_ARINTV BITS(1,13) /*!< auto-refresh interval */ -#define EXMC_SDARI_REIE BIT(14) /*!< interrupt refresh error enable */ +#define EXMC_SDARI_REC BIT(0) /*!< refresh error flag clear */ +#define EXMC_SDARI_ARINTV BITS(1,13) /*!< auto-refresh interval */ +#define EXMC_SDARI_REIE BIT(14) /*!< interrupt refresh error enable */ /* EXMC_SDSTAT */ -#define EXMC_SDSDAT_REIF BIT(0) /*!< refresh error interrupt flag */ -#define EXMC_SDSDAT_STA0 BITS(1,2) /*!< device 0 status */ -#define EXMC_SDSDAT_STA1 BITS(3,4) /*!< device 1 status */ -#define EXMC_SDSDAT_NRDY BIT(5) /*!< not ready status */ +#define EXMC_SDSDAT_REIF BIT(0) /*!< refresh error interrupt flag */ +#define EXMC_SDSDAT_STA0 BITS(1,2) /*!< device0 status */ +#define EXMC_SDSDAT_STA1 BITS(3,4) /*!< device1 status */ +#define EXMC_SDSDAT_NRDY BIT(5) /*!< not ready status */ /* EXMC_SDRSCTL */ -#define EXMC_SDRSCTL_RSEN BIT(0) /*!< read sample enable */ -#define EXMC_SDRSCTL_SSCR BIT(1) /*!< select sample cycle of read data */ -#define EXMC_SDRSCTL_SDSC BITS(4,7) /*!< select the delayed sample clock of read data */ +#define EXMC_SDRSCTL_RSEN BIT(0) /*!< read sample enable */ +#define EXMC_SDRSCTL_SSCR BIT(1) /*!< select sample cycle of read data */ +#define EXMC_SDRSCTL_SDSC BITS(4,7) /*!< select the delayed sample clock of read data */ /* EXMC_SINIT */ -#define EXMC_SINIT_CMDBIT BITS(16,17) /*!< bit number of SPI PSRAM command phase */ -#define EXMC_SINIT_ARDBIT BITS(24,28) /*!< bit number of SPI PSRAM address phase */ -#define EXMC_SINIT_IDL BITS(29,30) /*!< SPI PSRAM ID length */ -#define EXMC_SINIT_POL BIT(31) /*!< read data sample polarity */ +#define EXMC_SINIT_CMDBIT BITS(16,17) /*!< bit number of SPI PSRAM command phase */ +#define EXMC_SINIT_ARDBIT BITS(24,28) /*!< bit number of SPI PSRAM address phase */ +#define EXMC_SINIT_IDL BITS(29,30) /*!< SPI PSRAM ID length */ +#define EXMC_SINIT_POL BIT(31) /*!< read data sample polarity */ /* EXMC_SRCMD */ -#define EXMC_SRCMD_RCMD BITS(0,15) /*!< SPI read command for AHB read transfer */ -#define EXMC_SRCMD_RWAITCYCLE BITS(16,19) /*!< SPI read wait cycle number after address phase */ -#define EXMC_SRCMD_RMODE BITS(20,21) /*!< SPI PSRAM read command mode */ -#define EXMC_SRCMD_RDID BIT(31) /*!< send SPI read ID command */ +#define EXMC_SRCMD_RCMD BITS(0,15) /*!< SPI read command for AHB read transfer */ +#define EXMC_SRCMD_RWAITCYCLE BITS(16,19) /*!< SPI read wait cycle number after address phase */ +#define EXMC_SRCMD_RMODE BITS(20,21) /*!< SPI PSRAM read command mode */ +#define EXMC_SRCMD_RDID BIT(31) /*!< send SPI read ID command */ /* EXMC_SWCMD */ -#define EXMC_SWCMD_WCMD BITS(0,15) /*!< send SPI special command */ -#define EXMC_SWCMD_WWAITCYCLE BITS(16,19) /*!< SPI PSRAM write command mode */ -#define EXMC_SWCMD_WMODE BITS(20,21) /*!< SPI write wait cycle number after address phase */ -#define EXMC_SWCMD_SC BIT(31) /*!< SPI write command for AHB write transfer */ +#define EXMC_SWCMD_WCMD BITS(0,15) /*!< SPI write command for AHB write transfer */ +#define EXMC_SWCMD_WWAITCYCLE BITS(16,19) /*!< SPI write wait cycle number after address phase */ +#define EXMC_SWCMD_WMODE BITS(20,21) /*!< SPI PSRAM write command mode */ +#define EXMC_SWCMD_SC BIT(31) /*!< send SPI special command */ /* EXMC_SIDL */ -#define EXMC_SIDL_SIDL BITS(0,31) /*!< ID low data saved for SPI read ID command */ +#define EXMC_SIDL_SIDL BITS(0,31) /*!< ID low data saved for SPI read ID command */ /* EXMC_SIDH */ -#define EXMC_SIDL_SIDH BITS(0,31) /*!< ID high Data saved for SPI read ID command */ +#define EXMC_SIDL_SIDH BITS(0,31) /*!< ID high Data saved for SPI read ID command */ /* constants definitions */ -/* EXMC NOR/SRAM timing initialize struct */ +/* EXMC NOR/SRAM timing initialize structure */ typedef struct { uint32_t asyn_access_mode; /*!< asynchronous access mode */ uint32_t syn_data_latency; /*!< configure the data latency */ uint32_t syn_clk_division; /*!< configure the clock divide ratio */ uint32_t bus_latency; /*!< configure the bus latency */ - uint32_t asyn_data_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ - uint32_t asyn_address_holdtime; /*!< configure the address hold time,asynchronous access mode valid */ - uint32_t asyn_address_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ + uint32_t asyn_data_setuptime; /*!< configure the data setup time, asynchronous access mode valid */ + uint32_t asyn_address_holdtime; /*!< configure the address hold time, asynchronous access mode valid */ + uint32_t asyn_address_setuptime; /*!< configure the address setup time, asynchronous access mode valid */ }exmc_norsram_timing_parameter_struct; -/* EXMC NOR/SRAM initialize struct */ +/* EXMC NOR/SRAM initialize structure */ typedef struct { uint32_t norsram_region; /*!< select the region of EXMC NOR/SRAM bank */ @@ -248,7 +273,7 @@ typedef struct uint32_t databus_width; /*!< specifies the databus width of external memory */ uint32_t memory_type; /*!< specifies the type of external memory */ uint32_t address_data_mux; /*!< specifies whether the data bus and address bus are multiplexed */ - exmc_norsram_timing_parameter_struct* read_write_timing; /*!< timing parameters for read and write if the extendedmode is not used or the timing + exmc_norsram_timing_parameter_struct* read_write_timing; /*!< timing parameters for read and write if the extendedmode is not used or the timing parameters for read if the extendedmode is used. */ exmc_norsram_timing_parameter_struct* write_timing; /*!< timing parameters for write when the extendedmode is used. */ }exmc_norsram_parameter_struct; @@ -265,15 +290,15 @@ typedef struct /* EXMC NAND initialize struct */ typedef struct { - uint32_t nand_bank; /*!< select the bank of NAND */ + uint32_t nand_bank; /*!< select the bank of NAND */ uint32_t ecc_size; /*!< the page size for the ECC calculation */ uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ uint32_t ecc_logic; /*!< enable or disable the ECC calculation logic */ uint32_t databus_width; /*!< the NAND flash databus width */ - uint32_t wait_feature; /*!< enables or disables the wait feature */ - exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash Common Space */ - exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash Attribute Space */ + uint32_t wait_feature; /*!< enable or disable the wait feature */ + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash common space */ + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash attribute space */ }exmc_nand_parameter_struct; /* EXMC PC card initialize struct */ @@ -281,11 +306,11 @@ typedef struct { uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ - uint32_t wait_feature; /*!< enables or disables the Wait feature */ - exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash Common Space */ - exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash Attribute Space */ - exmc_nand_pccard_timing_parameter_struct* io_space_timing; /*!< the timing parameters for NAND flash IO Space */ -}exmc_pccard_parameter_struct;; + uint32_t wait_feature; /*!< enable or disable the wait feature */ + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for PC card common space */ + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for PC card attribute space */ + exmc_nand_pccard_timing_parameter_struct* io_space_timing; /*!< the timing parameters for PC card IO space */ +}exmc_pccard_parameter_struct; /* EXMC SDRAM timing initialize struct */ typedef struct @@ -293,7 +318,7 @@ typedef struct uint32_t row_to_column_delay; /*!< configure the row to column delay */ uint32_t row_precharge_delay; /*!< configure the row precharge delay */ uint32_t write_recovery_delay; /*!< configure the write recovery delay */ - uint32_t auto_refresh_delay; /*!< configure the auto refresh delay */ + uint32_t auto_refresh_delay; /*!< configure the auto refresh delay */ uint32_t row_address_select_delay; /*!< configure the row address select delay */ uint32_t exit_selfrefresh_delay; /*!< configure the exit self-refresh delay */ uint32_t load_mode_register_delay; /*!< configure the load mode register delay */ @@ -308,7 +333,7 @@ typedef struct uint32_t sdclock_config; /*!< the SDCLK memory clock for both SDRAM banks */ uint32_t write_protection; /*!< enable or disable SDRAM bank write protection function */ uint32_t cas_latency; /*!< configure the SDRAM CAS latency */ - uint32_t internal_bank_number; /*!< the number internal banks */ + uint32_t internal_bank_number; /*!< the number of internal bank */ uint32_t data_width; /*!< the databus width of SDRAM memory */ uint32_t row_address_width; /*!< the bit width of a row address */ uint32_t column_address_width; /*!< the bit width of a column address */ @@ -333,400 +358,414 @@ typedef struct{ }exmc_sqpipsram_parameter_struct; /* EXMC_register address */ -#define EXMC_SNCTL(bank) REG32(EXMC + 0x08U*((uint32_t)(bank))) /*!< EXMC SRAM/NOR flash control register */ -#define EXMC_SNTCFG(bank) REG32(EXMC + 0x04U + 0x08U*(bank)) /*!< EXMC SRAM/NOR flash timing configuration register */ -#define EXMC_SNWTCFG(bank) REG32(EXMC + 0x104U + 0x08U*(bank)) /*!< EXMC SRAM/NOR flash write timing configuration register */ +#define EXMC_SNCTL(region) REG32(EXMC + 0x08U*((uint32_t)(region))) /*!< EXMC SRAM/NOR flash control registers, region = 0,1,2,3 */ +#define EXMC_SNTCFG(region) REG32(EXMC + 0x04U + 0x08U*((uint32_t)(region))) /*!< EXMC SRAM/NOR flash timing configuration registers, region = 0,1,2,3 */ +#define EXMC_SNWTCFG(region) REG32(EXMC + 0x104U + 0x08U*((uint32_t)(region))) /*!< EXMC SRAM/NOR flash write timing configuration registers, region = 0,1,2,3 */ -#define EXMC_NPCTL(bank) REG32(EXMC + 0x40U + 0x20U*(bank)) /*!< EXMC NAND/PC card control register */ -#define EXMC_NPINTEN(bank) REG32(EXMC + 0x44U + 0x20U*(bank)) /*!< EXMC NAND/PC card interrupt enable register */ -#define EXMC_NPCTCFG(bank) REG32(EXMC + 0x48U + 0x20U*(bank)) /*!< EXMC NAND/PC card common space timing configuration register */ -#define EXMC_NPATCFG(bank) REG32(EXMC + 0x4CU + 0x20U*(bank)) /*!< EXMC NAND/PC card attribute space timing configuration register */ -#define EXMC_NECC(bank) REG32(EXMC + 0x54U + 0x20U*(bank)) /*!< EXMC NAND ECC register */ +#define EXMC_NPCTL(bank) REG32(EXMC + 0x40U + 0x20U*((uint32_t)(bank))) /*!< EXMC NAND/PC card control registers, bank = 1,2,3 */ +#define EXMC_NPINTEN(bank) REG32(EXMC + 0x44U + 0x20U*((uint32_t)(bank))) /*!< EXMC NAND/PC card interrupt enable registers, bank = 1,2,3 */ +#define EXMC_NPCTCFG(bank) REG32(EXMC + 0x48U + 0x20U*((uint32_t)(bank))) /*!< EXMC NAND/PC card common space timing configuration registers, bank = 1,2,3 */ +#define EXMC_NPATCFG(bank) REG32(EXMC + 0x4CU + 0x20U*((uint32_t)(bank))) /*!< EXMC NAND/PC card attribute space timing configuration registers, bank = 1,2,3 */ +#define EXMC_NECC(bank) REG32(EXMC + 0x54U + 0x20U*((uint32_t)(bank))) /*!< EXMC NAND ECC registers, bank = 1,2 */ -#define EXMC_SDCTL(bank) REG32(EXMC + 0x140U + 0x4U*((bank) - 0x4U)) /*!< EXMC SDRAM control register */ -#define EXMC_SDTCFG(bank) REG32(EXMC + 0x148U + 0x4U*((bank) - 0x4U)) /*!< EXMC SDRAM timing configuration register */ +#define EXMC_SDCTL(device) REG32(EXMC + 0x140U + 0x4U*(((uint32_t)(device)) - 0x4U)) /*!< EXMC SDRAM control registers,device = 0,1 */ +#define EXMC_SDTCFG(device) REG32(EXMC + 0x148U + 0x4U*(((uint32_t)(device)) - 0x4U)) /*!< EXMC SDRAM timing configuration registers,device = 0,1 */ /* CRAM page size */ -#define SNCTL_CPS(regval) (BITS(16,18) & ((uint32_t)(regval) << 16)) -#define EXMC_CRAM_AUTO_SPLIT SNCTL_CPS(0) /*!< automatic burst split on page boundary crossing */ -#define EXMC_CRAM_PAGE_SIZE_128_BYTES SNCTL_CPS(1) /*!< page size is 128 bytes */ -#define EXMC_CRAM_PAGE_SIZE_256_BYTES SNCTL_CPS(2) /*!< page size is 256 bytes */ -#define EXMC_CRAM_PAGE_SIZE_512_BYTES SNCTL_CPS(3) /*!< page size is 512 bytes */ -#define EXMC_CRAM_PAGE_SIZE_1024_BYTES SNCTL_CPS(4) /*!< page size is 1024 bytes */ +#define SNCTL_CPS(regval) (BITS(16,18) & ((uint32_t)(regval) << 16)) +#define EXMC_CRAM_AUTO_SPLIT SNCTL_CPS(0) /*!< automatic burst split on page boundary crossing */ +#define EXMC_CRAM_PAGE_SIZE_128_BYTES SNCTL_CPS(1) /*!< page size is 128 bytes */ +#define EXMC_CRAM_PAGE_SIZE_256_BYTES SNCTL_CPS(2) /*!< page size is 256 bytes */ +#define EXMC_CRAM_PAGE_SIZE_512_BYTES SNCTL_CPS(3) /*!< page size is 512 bytes */ +#define EXMC_CRAM_PAGE_SIZE_1024_BYTES SNCTL_CPS(4) /*!< page size is 1024 bytes */ /* NOR bank memory data bus width */ -#define SNCTL_NRW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) -#define EXMC_NOR_DATABUS_WIDTH_8B SNCTL_NRW(0) /*!< NOR data width 8 bits */ -#define EXMC_NOR_DATABUS_WIDTH_16B SNCTL_NRW(1) /*!< NOR data width 16 bits */ +#define SNCTL_NRW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NOR_DATABUS_WIDTH_8B SNCTL_NRW(0) /*!< NOR data width is 8 bits */ +#define EXMC_NOR_DATABUS_WIDTH_16B SNCTL_NRW(1) /*!< NOR data width is 16 bits */ /* NOR bank memory type */ -#define SNCTL_NRTP(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) -#define EXMC_MEMORY_TYPE_SRAM SNCTL_NRTP(0) /*!< SRAM,ROM */ -#define EXMC_MEMORY_TYPE_PSRAM SNCTL_NRTP(1) /*!< PSRAM,CRAM */ -#define EXMC_MEMORY_TYPE_NOR SNCTL_NRTP(2) /*!< NOR flash */ +#define SNCTL_NRTP(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define EXMC_MEMORY_TYPE_SRAM SNCTL_NRTP(0) /*!< SRAM,ROM */ +#define EXMC_MEMORY_TYPE_PSRAM SNCTL_NRTP(1) /*!< PSRAM,CRAM */ +#define EXMC_MEMORY_TYPE_NOR SNCTL_NRTP(2) /*!< NOR flash */ /* asynchronous access mode */ -#define SNTCFG_ASYNCMOD(regval) (BITS(28,29) & ((uint32_t)(regval) << 28)) -#define EXMC_ACCESS_MODE_A SNTCFG_ASYNCMOD(0) /*!< mode A access */ -#define EXMC_ACCESS_MODE_B SNTCFG_ASYNCMOD(1) /*!< mode B access */ -#define EXMC_ACCESS_MODE_C SNTCFG_ASYNCMOD(2) /*!< mode C access */ -#define EXMC_ACCESS_MODE_D SNTCFG_ASYNCMOD(3) /*!< mode D access */ +#define SNTCFG_ASYNCMOD(regval) (BITS(28,29) & ((uint32_t)(regval) << 28)) +#define EXMC_ACCESS_MODE_A SNTCFG_ASYNCMOD(0) /*!< mode A access */ +#define EXMC_ACCESS_MODE_B SNTCFG_ASYNCMOD(1) /*!< mode B access */ +#define EXMC_ACCESS_MODE_C SNTCFG_ASYNCMOD(2) /*!< mode C access */ +#define EXMC_ACCESS_MODE_D SNTCFG_ASYNCMOD(3) /*!< mode D access */ /* data latency for NOR flash */ -#define SNTCFG_DLAT(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) -#define EXMC_DATALAT_2_CLK SNTCFG_DLAT(0) /*!< data latency 2 EXMC_CLK */ -#define EXMC_DATALAT_3_CLK SNTCFG_DLAT(1) /*!< data latency 3 EXMC_CLK */ -#define EXMC_DATALAT_4_CLK SNTCFG_DLAT(2) /*!< data latency 4 EXMC_CLK */ -#define EXMC_DATALAT_5_CLK SNTCFG_DLAT(3) /*!< data latency 5 EXMC_CLK */ -#define EXMC_DATALAT_6_CLK SNTCFG_DLAT(4) /*!< data latency 6 EXMC_CLK */ -#define EXMC_DATALAT_7_CLK SNTCFG_DLAT(5) /*!< data latency 7 EXMC_CLK */ -#define EXMC_DATALAT_8_CLK SNTCFG_DLAT(6) /*!< data latency 8 EXMC_CLK */ -#define EXMC_DATALAT_9_CLK SNTCFG_DLAT(7) /*!< data latency 9 EXMC_CLK */ -#define EXMC_DATALAT_10_CLK SNTCFG_DLAT(8) /*!< data latency 10 EXMC_CLK */ -#define EXMC_DATALAT_11_CLK SNTCFG_DLAT(9) /*!< data latency 11 EXMC_CLK */ -#define EXMC_DATALAT_12_CLK SNTCFG_DLAT(10) /*!< data latency 12 EXMC_CLK */ -#define EXMC_DATALAT_13_CLK SNTCFG_DLAT(11) /*!< data latency 13 EXMC_CLK */ -#define EXMC_DATALAT_14_CLK SNTCFG_DLAT(12) /*!< data latency 14 EXMC_CLK */ -#define EXMC_DATALAT_15_CLK SNTCFG_DLAT(13) /*!< data latency 15 EXMC_CLK */ -#define EXMC_DATALAT_16_CLK SNTCFG_DLAT(14) /*!< data latency 16 EXMC_CLK */ -#define EXMC_DATALAT_17_CLK SNTCFG_DLAT(15) /*!< data latency 17 EXMC_CLK */ +#define SNTCFG_DLAT(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define EXMC_DATALAT_2_CLK SNTCFG_DLAT(0) /*!< data latency of first burst access is 2 EXMC_CLK */ +#define EXMC_DATALAT_3_CLK SNTCFG_DLAT(1) /*!< data latency of first burst access is 3 EXMC_CLK */ +#define EXMC_DATALAT_4_CLK SNTCFG_DLAT(2) /*!< data latency of first burst access is 4 EXMC_CLK */ +#define EXMC_DATALAT_5_CLK SNTCFG_DLAT(3) /*!< data latency of first burst access is 5 EXMC_CLK */ +#define EXMC_DATALAT_6_CLK SNTCFG_DLAT(4) /*!< data latency of first burst access is 6 EXMC_CLK */ +#define EXMC_DATALAT_7_CLK SNTCFG_DLAT(5) /*!< data latency of first burst access is 7 EXMC_CLK */ +#define EXMC_DATALAT_8_CLK SNTCFG_DLAT(6) /*!< data latency of first burst access is 8 EXMC_CLK */ +#define EXMC_DATALAT_9_CLK SNTCFG_DLAT(7) /*!< data latency of first burst access is 9 EXMC_CLK */ +#define EXMC_DATALAT_10_CLK SNTCFG_DLAT(8) /*!< data latency of first burst access is 10 EXMC_CLK */ +#define EXMC_DATALAT_11_CLK SNTCFG_DLAT(9) /*!< data latency of first burst access is 11 EXMC_CLK */ +#define EXMC_DATALAT_12_CLK SNTCFG_DLAT(10) /*!< data latency of first burst access is 12 EXMC_CLK */ +#define EXMC_DATALAT_13_CLK SNTCFG_DLAT(11) /*!< data latency of first burst access is 13 EXMC_CLK */ +#define EXMC_DATALAT_14_CLK SNTCFG_DLAT(12) /*!< data latency of first burst access is 14 EXMC_CLK */ +#define EXMC_DATALAT_15_CLK SNTCFG_DLAT(13) /*!< data latency of first burst access is 15 EXMC_CLK */ +#define EXMC_DATALAT_16_CLK SNTCFG_DLAT(14) /*!< data latency of first burst access is 16 EXMC_CLK */ +#define EXMC_DATALAT_17_CLK SNTCFG_DLAT(15) /*!< data latency of first burst access is 17 EXMC_CLK */ /* synchronous clock divide ratio */ -#define SNTCFG_CKDIV(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) -#define EXMC_SYN_CLOCK_RATIO_DISABLE SNTCFG_CKDIV(0) /*!< EXMC_CLK disable */ -#define EXMC_SYN_CLOCK_RATIO_2_CLK SNTCFG_CKDIV(1) /*!< EXMC_CLK = 2*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_3_CLK SNTCFG_CKDIV(2) /*!< EXMC_CLK = 3*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_4_CLK SNTCFG_CKDIV(3) /*!< EXMC_CLK = 4*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_5_CLK SNTCFG_CKDIV(4) /*!< EXMC_CLK = 5*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_6_CLK SNTCFG_CKDIV(5) /*!< EXMC_CLK = 6*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_7_CLK SNTCFG_CKDIV(6) /*!< EXMC_CLK = 7*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_8_CLK SNTCFG_CKDIV(7) /*!< EXMC_CLK = 8*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_9_CLK SNTCFG_CKDIV(8) /*!< EXMC_CLK = 9*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_10_CLK SNTCFG_CKDIV(9) /*!< EXMC_CLK = 10*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_11_CLK SNTCFG_CKDIV(10) /*!< EXMC_CLK = 11*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_12_CLK SNTCFG_CKDIV(11) /*!< EXMC_CLK = 12*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_13_CLK SNTCFG_CKDIV(12) /*!< EXMC_CLK = 13*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_14_CLK SNTCFG_CKDIV(13) /*!< EXMC_CLK = 14*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_15_CLK SNTCFG_CKDIV(14) /*!< EXMC_CLK = 15*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_16_CLK SNTCFG_CKDIV(15) /*!< EXMC_CLK = 16*HCLK */ +#define SNTCFG_CKDIV(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) +#define EXMC_SYN_CLOCK_RATIO_2_CLK SNTCFG_CKDIV(1) /*!< EXMC_CLK = 2*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_3_CLK SNTCFG_CKDIV(2) /*!< EXMC_CLK = 3*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_4_CLK SNTCFG_CKDIV(3) /*!< EXMC_CLK = 4*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_5_CLK SNTCFG_CKDIV(4) /*!< EXMC_CLK = 5*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_6_CLK SNTCFG_CKDIV(5) /*!< EXMC_CLK = 6*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_7_CLK SNTCFG_CKDIV(6) /*!< EXMC_CLK = 7*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_8_CLK SNTCFG_CKDIV(7) /*!< EXMC_CLK = 8*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_9_CLK SNTCFG_CKDIV(8) /*!< EXMC_CLK = 9*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_10_CLK SNTCFG_CKDIV(9) /*!< EXMC_CLK = 10*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_11_CLK SNTCFG_CKDIV(10) /*!< EXMC_CLK = 11*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_12_CLK SNTCFG_CKDIV(11) /*!< EXMC_CLK = 12*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_13_CLK SNTCFG_CKDIV(12) /*!< EXMC_CLK = 13*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_14_CLK SNTCFG_CKDIV(13) /*!< EXMC_CLK = 14*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_15_CLK SNTCFG_CKDIV(14) /*!< EXMC_CLK = 15*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_16_CLK SNTCFG_CKDIV(15) /*!< EXMC_CLK = 16*HCLK */ /* ECC size */ -#define NPCTL_ECCSZ(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) -#define EXMC_ECC_SIZE_256BYTES NPCTL_ECCSZ(0) /* 256 bytes */ -#define EXMC_ECC_SIZE_512BYTES NPCTL_ECCSZ(1) /* 512 bytes */ -#define EXMC_ECC_SIZE_1024BYTES NPCTL_ECCSZ(2) /* 1024 bytes */ -#define EXMC_ECC_SIZE_2048BYTES NPCTL_ECCSZ(3) /* 2048 bytes */ -#define EXMC_ECC_SIZE_4096BYTES NPCTL_ECCSZ(4) /* 4096 bytes */ -#define EXMC_ECC_SIZE_8192BYTES NPCTL_ECCSZ(5) /* 8192 bytes */ +#define NPCTL_ECCSZ(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) +#define EXMC_ECC_SIZE_256BYTES NPCTL_ECCSZ(0) /* ECC size is 256 bytes */ +#define EXMC_ECC_SIZE_512BYTES NPCTL_ECCSZ(1) /* ECC size is 512 bytes */ +#define EXMC_ECC_SIZE_1024BYTES NPCTL_ECCSZ(2) /* ECC size is 1024 bytes */ +#define EXMC_ECC_SIZE_2048BYTES NPCTL_ECCSZ(3) /* ECC size is 2048 bytes */ +#define EXMC_ECC_SIZE_4096BYTES NPCTL_ECCSZ(4) /* ECC size is 4096 bytes */ +#define EXMC_ECC_SIZE_8192BYTES NPCTL_ECCSZ(5) /* ECC size is 8192 bytes */ /* ALE to RE delay */ -#define NPCTL_ATR(regval) (BITS(13,16) & ((uint32_t)(regval) << 13)) -#define EXMC_ALE_RE_DELAY_1_HCLK NPCTL_ATR(0) /* ALE to RE delay = 1*HCLK */ -#define EXMC_ALE_RE_DELAY_2_HCLK NPCTL_ATR(1) /* ALE to RE delay = 2*HCLK */ -#define EXMC_ALE_RE_DELAY_3_HCLK NPCTL_ATR(2) /* ALE to RE delay = 3*HCLK */ -#define EXMC_ALE_RE_DELAY_4_HCLK NPCTL_ATR(3) /* ALE to RE delay = 4*HCLK */ -#define EXMC_ALE_RE_DELAY_5_HCLK NPCTL_ATR(4) /* ALE to RE delay = 5*HCLK */ -#define EXMC_ALE_RE_DELAY_6_HCLK NPCTL_ATR(5) /* ALE to RE delay = 6*HCLK */ -#define EXMC_ALE_RE_DELAY_7_HCLK NPCTL_ATR(6) /* ALE to RE delay = 7*HCLK */ -#define EXMC_ALE_RE_DELAY_8_HCLK NPCTL_ATR(7) /* ALE to RE delay = 8*HCLK */ -#define EXMC_ALE_RE_DELAY_9_HCLK NPCTL_ATR(8) /* ALE to RE delay = 9*HCLK */ -#define EXMC_ALE_RE_DELAY_10_HCLK NPCTL_ATR(9) /* ALE to RE delay = 10*HCLK */ -#define EXMC_ALE_RE_DELAY_11_HCLK NPCTL_ATR(10) /* ALE to RE delay = 11*HCLK */ -#define EXMC_ALE_RE_DELAY_12_HCLK NPCTL_ATR(11) /* ALE to RE delay = 12*HCLK */ -#define EXMC_ALE_RE_DELAY_13_HCLK NPCTL_ATR(12) /* ALE to RE delay = 13*HCLK */ -#define EXMC_ALE_RE_DELAY_14_HCLK NPCTL_ATR(13) /* ALE to RE delay = 14*HCLK */ -#define EXMC_ALE_RE_DELAY_15_HCLK NPCTL_ATR(14) /* ALE to RE delay = 15*HCLK */ -#define EXMC_ALE_RE_DELAY_16_HCLK NPCTL_ATR(15) /* ALE to RE delay = 16*HCLK */ +#define NPCTL_ATR(regval) (BITS(13,16) & ((uint32_t)(regval) << 13)) +#define EXMC_ALE_RE_DELAY_1_HCLK NPCTL_ATR(0) /* ALE to RE delay = 1*HCLK */ +#define EXMC_ALE_RE_DELAY_2_HCLK NPCTL_ATR(1) /* ALE to RE delay = 2*HCLK */ +#define EXMC_ALE_RE_DELAY_3_HCLK NPCTL_ATR(2) /* ALE to RE delay = 3*HCLK */ +#define EXMC_ALE_RE_DELAY_4_HCLK NPCTL_ATR(3) /* ALE to RE delay = 4*HCLK */ +#define EXMC_ALE_RE_DELAY_5_HCLK NPCTL_ATR(4) /* ALE to RE delay = 5*HCLK */ +#define EXMC_ALE_RE_DELAY_6_HCLK NPCTL_ATR(5) /* ALE to RE delay = 6*HCLK */ +#define EXMC_ALE_RE_DELAY_7_HCLK NPCTL_ATR(6) /* ALE to RE delay = 7*HCLK */ +#define EXMC_ALE_RE_DELAY_8_HCLK NPCTL_ATR(7) /* ALE to RE delay = 8*HCLK */ +#define EXMC_ALE_RE_DELAY_9_HCLK NPCTL_ATR(8) /* ALE to RE delay = 9*HCLK */ +#define EXMC_ALE_RE_DELAY_10_HCLK NPCTL_ATR(9) /* ALE to RE delay = 10*HCLK */ +#define EXMC_ALE_RE_DELAY_11_HCLK NPCTL_ATR(10) /* ALE to RE delay = 11*HCLK */ +#define EXMC_ALE_RE_DELAY_12_HCLK NPCTL_ATR(11) /* ALE to RE delay = 12*HCLK */ +#define EXMC_ALE_RE_DELAY_13_HCLK NPCTL_ATR(12) /* ALE to RE delay = 13*HCLK */ +#define EXMC_ALE_RE_DELAY_14_HCLK NPCTL_ATR(13) /* ALE to RE delay = 14*HCLK */ +#define EXMC_ALE_RE_DELAY_15_HCLK NPCTL_ATR(14) /* ALE to RE delay = 15*HCLK */ +#define EXMC_ALE_RE_DELAY_16_HCLK NPCTL_ATR(15) /* ALE to RE delay = 16*HCLK */ /* CLE to RE delay */ -#define NPCTL_CTR(regval) (BITS(9,12) & ((uint32_t)(regval) << 9)) -#define EXMC_CLE_RE_DELAY_1_HCLK NPCTL_CTR(0) /* CLE to RE delay = 1*HCLK */ -#define EXMC_CLE_RE_DELAY_2_HCLK NPCTL_CTR(1) /* CLE to RE delay = 2*HCLK */ -#define EXMC_CLE_RE_DELAY_3_HCLK NPCTL_CTR(2) /* CLE to RE delay = 3*HCLK */ -#define EXMC_CLE_RE_DELAY_4_HCLK NPCTL_CTR(3) /* CLE to RE delay = 4*HCLK */ -#define EXMC_CLE_RE_DELAY_5_HCLK NPCTL_CTR(4) /* CLE to RE delay = 5*HCLK */ -#define EXMC_CLE_RE_DELAY_6_HCLK NPCTL_CTR(5) /* CLE to RE delay = 6*HCLK */ -#define EXMC_CLE_RE_DELAY_7_HCLK NPCTL_CTR(6) /* CLE to RE delay = 7*HCLK */ -#define EXMC_CLE_RE_DELAY_8_HCLK NPCTL_CTR(7) /* CLE to RE delay = 8*HCLK */ -#define EXMC_CLE_RE_DELAY_9_HCLK NPCTL_CTR(8) /* CLE to RE delay = 9*HCLK */ -#define EXMC_CLE_RE_DELAY_10_HCLK NPCTL_CTR(9) /* CLE to RE delay = 10*HCLK */ -#define EXMC_CLE_RE_DELAY_11_HCLK NPCTL_CTR(10) /* CLE to RE delay = 11*HCLK */ -#define EXMC_CLE_RE_DELAY_12_HCLK NPCTL_CTR(11) /* CLE to RE delay = 12*HCLK */ -#define EXMC_CLE_RE_DELAY_13_HCLK NPCTL_CTR(12) /* CLE to RE delay = 13*HCLK */ -#define EXMC_CLE_RE_DELAY_14_HCLK NPCTL_CTR(13) /* CLE to RE delay = 14*HCLK */ -#define EXMC_CLE_RE_DELAY_15_HCLK NPCTL_CTR(14) /* CLE to RE delay = 15*HCLK */ -#define EXMC_CLE_RE_DELAY_16_HCLK NPCTL_CTR(15) /* CLE to RE delay = 16*HCLK */ +#define NPCTL_CTR(regval) (BITS(9,12) & ((uint32_t)(regval) << 9)) +#define EXMC_CLE_RE_DELAY_1_HCLK NPCTL_CTR(0) /* CLE to RE delay = 1*HCLK */ +#define EXMC_CLE_RE_DELAY_2_HCLK NPCTL_CTR(1) /* CLE to RE delay = 2*HCLK */ +#define EXMC_CLE_RE_DELAY_3_HCLK NPCTL_CTR(2) /* CLE to RE delay = 3*HCLK */ +#define EXMC_CLE_RE_DELAY_4_HCLK NPCTL_CTR(3) /* CLE to RE delay = 4*HCLK */ +#define EXMC_CLE_RE_DELAY_5_HCLK NPCTL_CTR(4) /* CLE to RE delay = 5*HCLK */ +#define EXMC_CLE_RE_DELAY_6_HCLK NPCTL_CTR(5) /* CLE to RE delay = 6*HCLK */ +#define EXMC_CLE_RE_DELAY_7_HCLK NPCTL_CTR(6) /* CLE to RE delay = 7*HCLK */ +#define EXMC_CLE_RE_DELAY_8_HCLK NPCTL_CTR(7) /* CLE to RE delay = 8*HCLK */ +#define EXMC_CLE_RE_DELAY_9_HCLK NPCTL_CTR(8) /* CLE to RE delay = 9*HCLK */ +#define EXMC_CLE_RE_DELAY_10_HCLK NPCTL_CTR(9) /* CLE to RE delay = 10*HCLK */ +#define EXMC_CLE_RE_DELAY_11_HCLK NPCTL_CTR(10) /* CLE to RE delay = 11*HCLK */ +#define EXMC_CLE_RE_DELAY_12_HCLK NPCTL_CTR(11) /* CLE to RE delay = 12*HCLK */ +#define EXMC_CLE_RE_DELAY_13_HCLK NPCTL_CTR(12) /* CLE to RE delay = 13*HCLK */ +#define EXMC_CLE_RE_DELAY_14_HCLK NPCTL_CTR(13) /* CLE to RE delay = 14*HCLK */ +#define EXMC_CLE_RE_DELAY_15_HCLK NPCTL_CTR(14) /* CLE to RE delay = 15*HCLK */ +#define EXMC_CLE_RE_DELAY_16_HCLK NPCTL_CTR(15) /* CLE to RE delay = 16*HCLK */ /* NAND bank memory data bus width */ -#define NPCTL_NDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) -#define EXMC_NAND_DATABUS_WIDTH_8B NPCTL_NDW(0) /*!< NAND data width 8 bits */ -#define EXMC_NAND_DATABUS_WIDTH_16B NPCTL_NDW(1) /*!< NAND data width 16 bits */ +#define NPCTL_NDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NAND_DATABUS_WIDTH_8B NPCTL_NDW(0) /*!< NAND data width is 8 bits */ +#define EXMC_NAND_DATABUS_WIDTH_16B NPCTL_NDW(1) /*!< NAND data width is 16 bits */ /* SDRAM pipeline delay */ -#define SDCTL_PIPED(regval) (BITS(13,14) & ((uint32_t)(regval) << 13)) -#define EXMC_PIPELINE_DELAY_0_HCLK SDCTL_PIPED(0) /*!< 0 HCLK clock cycle delay */ -#define EXMC_PIPELINE_DELAY_1_HCLK SDCTL_PIPED(1) /*!< 1 HCLK clock cycle delay */ -#define EXMC_PIPELINE_DELAY_2_HCLK SDCTL_PIPED(2) /*!< 2 HCLK clock cycle delay */ +#define SDCTL_PIPED(regval) (BITS(13,14) & ((uint32_t)(regval) << 13)) +#define EXMC_PIPELINE_DELAY_0_HCLK SDCTL_PIPED(0) /*!< 0 HCLK clock cycle delay */ +#define EXMC_PIPELINE_DELAY_1_HCLK SDCTL_PIPED(1) /*!< 1 HCLK clock cycle delay */ +#define EXMC_PIPELINE_DELAY_2_HCLK SDCTL_PIPED(2) /*!< 2 HCLK clock cycle delay */ /* SDRAM clock configuration */ -#define SDCTL_SDCLK(regval) (BITS(10,11) & ((uint32_t)(regval) << 10)) -#define EXMC_SDCLK_DISABLE SDCTL_SDCLK(0) /*!< SDCLK memory clock disabled */ -#define EXMC_SDCLK_PERIODS_2_HCLK SDCTL_SDCLK(2) /*!< SDCLK memory period = 2*HCLK */ -#define EXMC_SDCLK_PERIODS_3_HCLK SDCTL_SDCLK(3) /*!< SDCLK memory period = 3*HCLK */ +#define SDCTL_SDCLK(regval) (BITS(10,11) & ((uint32_t)(regval) << 10)) +#define EXMC_SDCLK_DISABLE SDCTL_SDCLK(0) /*!< SDCLK memory clock disabled */ +#define EXMC_SDCLK_PERIODS_2_HCLK SDCTL_SDCLK(2) /*!< SDCLK memory period = 2*HCLK */ +#define EXMC_SDCLK_PERIODS_3_HCLK SDCTL_SDCLK(3) /*!< SDCLK memory period = 3*HCLK */ /* CAS latency */ -#define SDCTL_CL(regval) (BITS(7,8) & ((uint32_t)(regval) << 7)) -#define EXMC_CAS_LATENCY_1_SDCLK SDCTL_CL(1) /*!< CAS latency is 1 memory clock cycle */ -#define EXMC_CAS_LATENCY_2_SDCLK SDCTL_CL(2) /*!< CAS latency is 2 memory clock cycle */ -#define EXMC_CAS_LATENCY_3_SDCLK SDCTL_CL(3) /*!< CAS latency is 3 memory clock cycle */ +#define SDCTL_CL(regval) (BITS(7,8) & ((uint32_t)(regval) << 7)) +#define EXMC_CAS_LATENCY_1_SDCLK SDCTL_CL(1) /*!< CAS latency is 1 memory clock cycle */ +#define EXMC_CAS_LATENCY_2_SDCLK SDCTL_CL(2) /*!< CAS latency is 2 memory clock cycle */ +#define EXMC_CAS_LATENCY_3_SDCLK SDCTL_CL(3) /*!< CAS latency is 3 memory clock cycle */ /* SDRAM data bus width */ -#define SDCTL_SDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) -#define EXMC_SDRAM_DATABUS_WIDTH_8B SDCTL_SDW(0) /*!< SDRAM data width 8 bits */ -#define EXMC_SDRAM_DATABUS_WIDTH_16B SDCTL_SDW(1) /*!< SDRAM data width 16 bits */ -#define EXMC_SDRAM_DATABUS_WIDTH_32B SDCTL_SDW(2) /*!< SDRAM data width 32 bits */ +#define SDCTL_SDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_SDRAM_DATABUS_WIDTH_8B SDCTL_SDW(0) /*!< SDRAM data width 8 bits */ +#define EXMC_SDRAM_DATABUS_WIDTH_16B SDCTL_SDW(1) /*!< SDRAM data width 16 bits */ +#define EXMC_SDRAM_DATABUS_WIDTH_32B SDCTL_SDW(2) /*!< SDRAM data width 32 bits */ /* SDRAM row address bit width */ -#define SDCTL_RAW(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) -#define EXMC_SDRAM_ROW_ADDRESS_11 SDCTL_RAW(0) /*!< row address bit width is 11 bits */ -#define EXMC_SDRAM_ROW_ADDRESS_12 SDCTL_RAW(1) /*!< row address bit width is 12 bits */ -#define EXMC_SDRAM_ROW_ADDRESS_13 SDCTL_RAW(2) /*!< row address bit width is 13 bits */ +#define SDCTL_RAW(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define EXMC_SDRAM_ROW_ADDRESS_11 SDCTL_RAW(0) /*!< row address bit width is 11 bits */ +#define EXMC_SDRAM_ROW_ADDRESS_12 SDCTL_RAW(1) /*!< row address bit width is 12 bits */ +#define EXMC_SDRAM_ROW_ADDRESS_13 SDCTL_RAW(2) /*!< row address bit width is 13 bits */ /* SDRAM column address bit width */ -#define SDCTL_CAW(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) -#define EXMC_SDRAM_COW_ADDRESS_8 SDCTL_CAW(0) /*!< column address bit width is 8 bits */ -#define EXMC_SDRAM_COW_ADDRESS_9 SDCTL_CAW(1) /*!< column address bit width is 9 bits */ -#define EXMC_SDRAM_COW_ADDRESS_10 SDCTL_CAW(2) /*!< column address bit width is 10 bits */ -#define EXMC_SDRAM_COW_ADDRESS_11 SDCTL_CAW(3) /*!< column address bit width is 11 bits */ +#define SDCTL_CAW(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define EXMC_SDRAM_COW_ADDRESS_8 SDCTL_CAW(0) /*!< column address bit width is 8 bits */ +#define EXMC_SDRAM_COW_ADDRESS_9 SDCTL_CAW(1) /*!< column address bit width is 9 bits */ +#define EXMC_SDRAM_COW_ADDRESS_10 SDCTL_CAW(2) /*!< column address bit width is 10 bits */ +#define EXMC_SDRAM_COW_ADDRESS_11 SDCTL_CAW(3) /*!< column address bit width is 11 bits */ /* SDRAM number of successive auto-refresh */ -#define SDCMD_NARF(regval) (BITS(5,8) & ((uint32_t)(regval) << 5)) -#define EXMC_SDRAM_AUTO_REFLESH_1_SDCLK SDCMD_NARF(0) /*!< 1 auto-refresh cycle */ -#define EXMC_SDRAM_AUTO_REFLESH_2_SDCLK SDCMD_NARF(1) /*!< 2 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_3_SDCLK SDCMD_NARF(2) /*!< 3 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_4_SDCLK SDCMD_NARF(3) /*!< 4 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_5_SDCLK SDCMD_NARF(4) /*!< 5 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_6_SDCLK SDCMD_NARF(5) /*!< 6 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_7_SDCLK SDCMD_NARF(6) /*!< 7 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_8_SDCLK SDCMD_NARF(7) /*!< 8 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_9_SDCLK SDCMD_NARF(8) /*!< 9 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_10_SDCLK SDCMD_NARF(9) /*!< 10 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_11_SDCLK SDCMD_NARF(10) /*!< 11 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_12_SDCLK SDCMD_NARF(11) /*!< 12 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_13_SDCLK SDCMD_NARF(12) /*!< 13 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_14_SDCLK SDCMD_NARF(13) /*!< 14 auto-refresh cycles */ -#define EXMC_SDRAM_AUTO_REFLESH_15_SDCLK SDCMD_NARF(14) /*!< 15 auto-refresh cycles */ +#define SDCMD_NARF(regval) (BITS(5,8) & ((uint32_t)(regval) << 5)) +#define EXMC_SDRAM_AUTO_REFLESH_1_SDCLK SDCMD_NARF(0) /*!< 1 auto-refresh cycle */ +#define EXMC_SDRAM_AUTO_REFLESH_2_SDCLK SDCMD_NARF(1) /*!< 2 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_3_SDCLK SDCMD_NARF(2) /*!< 3 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_4_SDCLK SDCMD_NARF(3) /*!< 4 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_5_SDCLK SDCMD_NARF(4) /*!< 5 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_6_SDCLK SDCMD_NARF(5) /*!< 6 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_7_SDCLK SDCMD_NARF(6) /*!< 7 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_8_SDCLK SDCMD_NARF(7) /*!< 8 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_9_SDCLK SDCMD_NARF(8) /*!< 9 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_10_SDCLK SDCMD_NARF(9) /*!< 10 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_11_SDCLK SDCMD_NARF(10) /*!< 11 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_12_SDCLK SDCMD_NARF(11) /*!< 12 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_13_SDCLK SDCMD_NARF(12) /*!< 13 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_14_SDCLK SDCMD_NARF(13) /*!< 14 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_15_SDCLK SDCMD_NARF(14) /*!< 15 auto-refresh cycles */ /* SDRAM command select */ -#define SDCMD_CMD(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) -#define EXMC_SDRAM_NORMAL_OPERATION SDCMD_CMD(0) /*!< normal operation command */ -#define EXMC_SDRAM_CLOCK_ENABLE SDCMD_CMD(1) /*!< clock enable command */ -#define EXMC_SDRAM_PRECHARGE_ALL SDCMD_CMD(2) /*!< precharge all command */ -#define EXMC_SDRAM_AUTO_REFRESH SDCMD_CMD(3) /*!< auto-refresh command */ -#define EXMC_SDRAM_LOAD_MODE_REGISTER SDCMD_CMD(4) /*!< load mode register command */ -#define EXMC_SDRAM_SELF_REFRESH SDCMD_CMD(5) /*!< self-refresh command */ -#define EXMC_SDRAM_POWERDOWN_ENTRY SDCMD_CMD(6) /*!< power-down entry command */ +#define SDCMD_CMD(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define EXMC_SDRAM_NORMAL_OPERATION SDCMD_CMD(0) /*!< normal operation command */ +#define EXMC_SDRAM_CLOCK_ENABLE SDCMD_CMD(1) /*!< clock enable command */ +#define EXMC_SDRAM_PRECHARGE_ALL SDCMD_CMD(2) /*!< precharge all command */ +#define EXMC_SDRAM_AUTO_REFRESH SDCMD_CMD(3) /*!< auto-refresh command */ +#define EXMC_SDRAM_LOAD_MODE_REGISTER SDCMD_CMD(4) /*!< load mode register command */ +#define EXMC_SDRAM_SELF_REFRESH SDCMD_CMD(5) /*!< self-refresh command */ +#define EXMC_SDRAM_POWERDOWN_ENTRY SDCMD_CMD(6) /*!< power-down entry command */ /* SDRAM the delayed sample clock of read data */ -#define SDRSCTL_SDSC(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) -#define EXMC_SDRAM_0_DELAY_CELL SDRSCTL_SDSC(0) /*!< select the clock after 0 delay cell */ -#define EXMC_SDRAM_1_DELAY_CELL SDRSCTL_SDSC(1) /*!< select the clock after 1 delay cell */ -#define EXMC_SDRAM_2_DELAY_CELL SDRSCTL_SDSC(2) /*!< select the clock after 2 delay cell */ -#define EXMC_SDRAM_3_DELAY_CELL SDRSCTL_SDSC(3) /*!< select the clock after 3 delay cell */ -#define EXMC_SDRAM_4_DELAY_CELL SDRSCTL_SDSC(4) /*!< select the clock after 4 delay cell */ -#define EXMC_SDRAM_5_DELAY_CELL SDRSCTL_SDSC(5) /*!< select the clock after 5 delay cell */ -#define EXMC_SDRAM_6_DELAY_CELL SDRSCTL_SDSC(6) /*!< select the clock after 6 delay cell */ -#define EXMC_SDRAM_7_DELAY_CELL SDRSCTL_SDSC(7) /*!< select the clock after 7 delay cell */ -#define EXMC_SDRAM_8_DELAY_CELL SDRSCTL_SDSC(8) /*!< select the clock after 8 delay cell */ -#define EXMC_SDRAM_9_DELAY_CELL SDRSCTL_SDSC(9) /*!< select the clock after 9 delay cell */ -#define EXMC_SDRAM_10_DELAY_CELL SDRSCTL_SDSC(10) /*!< select the clock after 10 delay cell */ -#define EXMC_SDRAM_11_DELAY_CELL SDRSCTL_SDSC(11) /*!< select the clock after 11 delay cell */ -#define EXMC_SDRAM_12_DELAY_CELL SDRSCTL_SDSC(12) /*!< select the clock after 12 delay cell */ -#define EXMC_SDRAM_13_DELAY_CELL SDRSCTL_SDSC(13) /*!< select the clock after 13 delay cell */ -#define EXMC_SDRAM_14_DELAY_CELL SDRSCTL_SDSC(14) /*!< select the clock after 14 delay cell */ -#define EXMC_SDRAM_15_DELAY_CELL SDRSCTL_SDSC(15) /*!< select the clock after 15 delay cell */ +#define SDRSCTL_SDSC(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define EXMC_SDRAM_0_DELAY_CELL SDRSCTL_SDSC(0) /*!< select the clock after 0 delay cell */ +#define EXMC_SDRAM_1_DELAY_CELL SDRSCTL_SDSC(1) /*!< select the clock after 1 delay cell */ +#define EXMC_SDRAM_2_DELAY_CELL SDRSCTL_SDSC(2) /*!< select the clock after 2 delay cell */ +#define EXMC_SDRAM_3_DELAY_CELL SDRSCTL_SDSC(3) /*!< select the clock after 3 delay cell */ +#define EXMC_SDRAM_4_DELAY_CELL SDRSCTL_SDSC(4) /*!< select the clock after 4 delay cell */ +#define EXMC_SDRAM_5_DELAY_CELL SDRSCTL_SDSC(5) /*!< select the clock after 5 delay cell */ +#define EXMC_SDRAM_6_DELAY_CELL SDRSCTL_SDSC(6) /*!< select the clock after 6 delay cell */ +#define EXMC_SDRAM_7_DELAY_CELL SDRSCTL_SDSC(7) /*!< select the clock after 7 delay cell */ +#define EXMC_SDRAM_8_DELAY_CELL SDRSCTL_SDSC(8) /*!< select the clock after 8 delay cell */ +#define EXMC_SDRAM_9_DELAY_CELL SDRSCTL_SDSC(9) /*!< select the clock after 9 delay cell */ +#define EXMC_SDRAM_10_DELAY_CELL SDRSCTL_SDSC(10) /*!< select the clock after 10 delay cell */ +#define EXMC_SDRAM_11_DELAY_CELL SDRSCTL_SDSC(11) /*!< select the clock after 11 delay cell */ +#define EXMC_SDRAM_12_DELAY_CELL SDRSCTL_SDSC(12) /*!< select the clock after 12 delay cell */ +#define EXMC_SDRAM_13_DELAY_CELL SDRSCTL_SDSC(13) /*!< select the clock after 13 delay cell */ +#define EXMC_SDRAM_14_DELAY_CELL SDRSCTL_SDSC(14) /*!< select the clock after 14 delay cell */ +#define EXMC_SDRAM_15_DELAY_CELL SDRSCTL_SDSC(15) /*!< select the clock after 15 delay cell */ /* SPI PSRAM ID length */ -#define SINIT_IDL(regval) (BITS(29,30) & ((uint32_t)(regval) << 29)) -#define EXMC_SQPIPSRAM_ID_LENGTH_64B SINIT_IDL(0) /*!< SPI PSRAM ID length is 64 bits */ -#define EXMC_SQPIPSRAM_ID_LENGTH_32B SINIT_IDL(1) /*!< SPI PSRAM ID length is 32 bits */ -#define EXMC_SQPIPSRAM_ID_LENGTH_16B SINIT_IDL(2) /*!< SPI PSRAM ID length is 16 bits */ -#define EXMC_SQPIPSRAM_ID_LENGTH_8B SINIT_IDL(3) /*!< SPI PSRAM ID length is 8 bits */ +#define SINIT_IDL(regval) (BITS(29,30) & ((uint32_t)(regval) << 29)) +#define EXMC_SQPIPSRAM_ID_LENGTH_64B SINIT_IDL(0) /*!< SPI PSRAM ID length is 64 bits */ +#define EXMC_SQPIPSRAM_ID_LENGTH_32B SINIT_IDL(1) /*!< SPI PSRAM ID length is 32 bits */ +#define EXMC_SQPIPSRAM_ID_LENGTH_16B SINIT_IDL(2) /*!< SPI PSRAM ID length is 16 bits */ +#define EXMC_SQPIPSRAM_ID_LENGTH_8B SINIT_IDL(3) /*!< SPI PSRAM ID length is 8 bits */ /* SPI PSRAM bit number of address phase */ -#define SINIT_ADRBIT(regval) (BITS(24,28) & ((uint32_t)(regval) << 24)) -#define EXMC_SQPIPSRAM_ADDR_LENGTH_1B SINIT_ADRBIT(1) /*!< SPI PSRAM address is 1 bit */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_2B SINIT_ADRBIT(2) /*!< SPI PSRAM address is 2 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_3B SINIT_ADRBIT(3) /*!< SPI PSRAM address is 3 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_4B SINIT_ADRBIT(4) /*!< SPI PSRAM address is 4 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_5B SINIT_ADRBIT(5) /*!< SPI PSRAM address is 5 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_6B SINIT_ADRBIT(6) /*!< SPI PSRAM address is 6 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_7B SINIT_ADRBIT(7) /*!< SPI PSRAM address is 7 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_8B SINIT_ADRBIT(8) /*!< SPI PSRAM address is 8 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_9B SINIT_ADRBIT(9) /*!< SPI PSRAM address is 9 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_10B SINIT_ADRBIT(10) /*!< SPI PSRAM address is 10 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_11B SINIT_ADRBIT(11) /*!< SPI PSRAM address is 11 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_12B SINIT_ADRBIT(12) /*!< SPI PSRAM address is 12 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_13B SINIT_ADRBIT(13) /*!< SPI PSRAM address is 13 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_14B SINIT_ADRBIT(14) /*!< SPI PSRAM address is 14 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_15B SINIT_ADRBIT(15) /*!< SPI PSRAM address is 15 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_16B SINIT_ADRBIT(16) /*!< SPI PSRAM address is 16 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_17B SINIT_ADRBIT(17) /*!< SPI PSRAM address is 17 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_18B SINIT_ADRBIT(18) /*!< SPI PSRAM address is 18 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_19B SINIT_ADRBIT(19) /*!< SPI PSRAM address is 19 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_20B SINIT_ADRBIT(20) /*!< SPI PSRAM address is 20 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_21B SINIT_ADRBIT(21) /*!< SPI PSRAM address is 21 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_22B SINIT_ADRBIT(22) /*!< SPI PSRAM address is 22 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_23B SINIT_ADRBIT(23) /*!< SPI PSRAM address is 23 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_24B SINIT_ADRBIT(24) /*!< SPI PSRAM address is 24 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_25B SINIT_ADRBIT(25) /*!< SPI PSRAM address is 25 bits */ -#define EXMC_SQPIPSRAM_ADDR_LENGTH_26B SINIT_ADRBIT(26) /*!< SPI PSRAM address is 26 bits */ +#define SINIT_ADRBIT(regval) (BITS(24,28) & ((uint32_t)(regval) << 24)) +#define EXMC_SQPIPSRAM_ADDR_LENGTH_1B SINIT_ADRBIT(1) /*!< SPI PSRAM address is 1 bit */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_2B SINIT_ADRBIT(2) /*!< SPI PSRAM address is 2 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_3B SINIT_ADRBIT(3) /*!< SPI PSRAM address is 3 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_4B SINIT_ADRBIT(4) /*!< SPI PSRAM address is 4 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_5B SINIT_ADRBIT(5) /*!< SPI PSRAM address is 5 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_6B SINIT_ADRBIT(6) /*!< SPI PSRAM address is 6 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_7B SINIT_ADRBIT(7) /*!< SPI PSRAM address is 7 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_8B SINIT_ADRBIT(8) /*!< SPI PSRAM address is 8 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_9B SINIT_ADRBIT(9) /*!< SPI PSRAM address is 9 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_10B SINIT_ADRBIT(10) /*!< SPI PSRAM address is 10 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_11B SINIT_ADRBIT(11) /*!< SPI PSRAM address is 11 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_12B SINIT_ADRBIT(12) /*!< SPI PSRAM address is 12 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_13B SINIT_ADRBIT(13) /*!< SPI PSRAM address is 13 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_14B SINIT_ADRBIT(14) /*!< SPI PSRAM address is 14 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_15B SINIT_ADRBIT(15) /*!< SPI PSRAM address is 15 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_16B SINIT_ADRBIT(16) /*!< SPI PSRAM address is 16 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_17B SINIT_ADRBIT(17) /*!< SPI PSRAM address is 17 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_18B SINIT_ADRBIT(18) /*!< SPI PSRAM address is 18 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_19B SINIT_ADRBIT(19) /*!< SPI PSRAM address is 19 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_20B SINIT_ADRBIT(20) /*!< SPI PSRAM address is 20 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_21B SINIT_ADRBIT(21) /*!< SPI PSRAM address is 21 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_22B SINIT_ADRBIT(22) /*!< SPI PSRAM address is 22 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_23B SINIT_ADRBIT(23) /*!< SPI PSRAM address is 23 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_24B SINIT_ADRBIT(24) /*!< SPI PSRAM address is 24 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_25B SINIT_ADRBIT(25) /*!< SPI PSRAM address is 25 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_26B SINIT_ADRBIT(26) /*!< SPI PSRAM address is 26 bits */ /* SPI PSRAM bit number of command phase */ -#define SINIT_CMDBIT(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) -#define EXMC_SQPIPSRAM_COMMAND_LENGTH_4B SINIT_CMDBIT(0) /*!< SPI PSRAM command is 4 bits */ -#define EXMC_SQPIPSRAM_COMMAND_LENGTH_8B SINIT_CMDBIT(1) /*!< SPI PSRAM command is 8 bits */ -#define EXMC_SQPIPSRAM_COMMAND_LENGTH_16B SINIT_CMDBIT(2) /*!< SPI PSRAM command is 16 bits */ +#define SINIT_CMDBIT(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) +#define EXMC_SQPIPSRAM_COMMAND_LENGTH_4B SINIT_CMDBIT(0) /*!< SPI PSRAM command is 4 bits */ +#define EXMC_SQPIPSRAM_COMMAND_LENGTH_8B SINIT_CMDBIT(1) /*!< SPI PSRAM command is 8 bits */ +#define EXMC_SQPIPSRAM_COMMAND_LENGTH_16B SINIT_CMDBIT(2) /*!< SPI PSRAM command is 16 bits */ /* SPI PSRAM read command mode */ -#define SRCMD_RMODE(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) -#define EXMC_SQPIPSRAM_READ_MODE_DISABLE SRCMD_RMODE(0) /*!< not SPI mode */ -#define EXMC_SQPIPSRAM_READ_MODE_SPI SRCMD_RMODE(1) /*!< SPI mode */ -#define EXMC_SQPIPSRAM_READ_MODE_SQPI SRCMD_RMODE(2) /*!< SQPI mode */ -#define EXMC_SQPIPSRAM_READ_MODE_QPI SRCMD_RMODE(3) /*!< QPI mode */ +#define SRCMD_RMODE(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) +#define EXMC_SQPIPSRAM_READ_MODE_DISABLE SRCMD_RMODE(0) /*!< not SPI mode */ +#define EXMC_SQPIPSRAM_READ_MODE_SPI SRCMD_RMODE(1) /*!< SPI mode */ +#define EXMC_SQPIPSRAM_READ_MODE_SQPI SRCMD_RMODE(2) /*!< SQPI mode */ +#define EXMC_SQPIPSRAM_READ_MODE_QPI SRCMD_RMODE(3) /*!< QPI mode */ /* SPI PSRAM write command mode */ -#define SRCMD_WMODE(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) -#define EXMC_SQPIPSRAM_WRITE_MODE_DISABLE SRCMD_WMODE(0) /*!< not SPI mode */ -#define EXMC_SQPIPSRAM_WRITE_MODE_SPI SRCMD_WMODE(1) /*!< SPI mode */ -#define EXMC_SQPIPSRAM_WRITE_MODE_SQPI SRCMD_WMODE(2) /*!< SQPI mode */ -#define EXMC_SQPIPSRAM_WRITE_MODE_QPI SRCMD_WMODE(3) /*!< QPI mode */ +#define SRCMD_WMODE(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) +#define EXMC_SQPIPSRAM_WRITE_MODE_DISABLE SRCMD_WMODE(0) /*!< not SPI mode */ +#define EXMC_SQPIPSRAM_WRITE_MODE_SPI SRCMD_WMODE(1) /*!< SPI mode */ +#define EXMC_SQPIPSRAM_WRITE_MODE_SQPI SRCMD_WMODE(2) /*!< SQPI mode */ +#define EXMC_SQPIPSRAM_WRITE_MODE_QPI SRCMD_WMODE(3) /*!< QPI mode */ /* EXMC NOR/SRAM bank region definition */ -#define EXMC_BANK0_NORSRAM_REGION0 ((uint32_t)0x00000000U) /*!< bank0 NOR/SRAM region0 */ -#define EXMC_BANK0_NORSRAM_REGION1 ((uint32_t)0x00000001U) /*!< bank0 NOR/SRAM region1 */ -#define EXMC_BANK0_NORSRAM_REGION2 ((uint32_t)0x00000002U) /*!< bank0 NOR/SRAM region2 */ -#define EXMC_BANK0_NORSRAM_REGION3 ((uint32_t)0x00000003U) /*!< bank0 NOR/SRAM region3 */ +#define EXMC_BANK0_NORSRAM_REGION0 ((uint32_t)0x00000000U) /*!< bank0 NOR/SRAM region0 */ +#define EXMC_BANK0_NORSRAM_REGION1 ((uint32_t)0x00000001U) /*!< bank0 NOR/SRAM region1 */ +#define EXMC_BANK0_NORSRAM_REGION2 ((uint32_t)0x00000002U) /*!< bank0 NOR/SRAM region2 */ +#define EXMC_BANK0_NORSRAM_REGION3 ((uint32_t)0x00000003U) /*!< bank0 NOR/SRAM region3 */ /* EXMC consecutive clock */ -#define EXMC_CLOCK_SYN_MODE ((uint32_t)0x00000000U) /*!< EXMC_CLK is generated only during synchronous access */ -#define EXMC_CLOCK_UNCONDITIONALLY ((uint32_t)0x00010000U) /*!< EXMC_CLK is generated unconditionally */ +#define EXMC_CLOCK_SYN_MODE ((uint32_t)0x00000000U) /*!< EXMC_CLK is generated only during synchronous access */ +#define EXMC_CLOCK_UNCONDITIONALLY EXMC_SNCTL_CCK /*!< EXMC_CLK is generated unconditionally */ /* EXMC NOR/SRAM write mode */ -#define EXMC_ASYN_WRITE ((uint32_t)0x00000000U) /*!< asynchronous write mode */ -#define EXMC_SYN_WRITE ((uint32_t)0x00008000U) /*!< synchronous write mode */ +#define EXMC_ASYN_WRITE ((uint32_t)0x00000000U) /*!< asynchronous write mode */ +#define EXMC_SYN_WRITE EXMC_SNCTL_SYNCWR /*!< synchronous write mode */ /* EXMC NWAIT signal configuration */ -#define EXMC_NWAIT_CONFIG_BEFORE ((uint32_t)0x00000000U) /*!< NWAIT signal is active one data cycle before wait state */ -#define EXMC_NWAIT_CONFIG_DURING ((uint32_t)0x00000800U) /*!< NWAIT signal is active during wait state */ +#define EXMC_NWAIT_CONFIG_BEFORE ((uint32_t)0x00000000U) /*!< NWAIT signal is active one data cycle before wait state */ +#define EXMC_NWAIT_CONFIG_DURING EXMC_SNCTL_NRWTCFG /*!< NWAIT signal is active during wait state */ /* EXMC NWAIT signal polarity configuration */ -#define EXMC_NWAIT_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level is active of NWAIT */ -#define EXMC_NWAIT_POLARITY_HIGH ((uint32_t)0x00000200U) /*!< high level is active of NWAIT */ +#define EXMC_NWAIT_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level is active of NWAIT */ +#define EXMC_NWAIT_POLARITY_HIGH EXMC_SNCTL_NRWTPOL /*!< high level is active of NWAIT */ /* EXMC NAND/PC card bank definition */ -#define EXMC_BANK1_NAND ((uint32_t)0x00000001U) /*!< bank1 NAND flash */ -#define EXMC_BANK2_NAND ((uint32_t)0x00000002U) /*!< bank2 NAND flash */ -#define EXMC_BANK3_PCCARD ((uint32_t)0x00000003U) /*!< bank3 PC card */ +#define EXMC_BANK1_NAND ((uint32_t)0x00000001U) /*!< NAND flash bank1 */ +#define EXMC_BANK2_NAND ((uint32_t)0x00000002U) /*!< NAND flash bank2 */ +#define EXMC_BANK3_PCCARD ((uint32_t)0x00000003U) /*!< PC card bank3 */ /* EXMC SDRAM bank definition */ -#define EXMC_SDRAM_DEVICE0 ((uint32_t)0x00000004U) /*!< SDRAM device0 */ -#define EXMC_SDRAM_DEVICE1 ((uint32_t)0x00000005U) /*!< SDRAM device1 */ +#define EXMC_SDRAM_DEVICE0 ((uint32_t)0x00000004U) /*!< SDRAM device0 */ +#define EXMC_SDRAM_DEVICE1 ((uint32_t)0x00000005U) /*!< SDRAM device1 */ /* EXMC SDRAM internal banks */ -#define EXMC_SDRAM_2_INTER_BANK ((uint32_t)0x00000000U) /*!< 2 internal banks */ -#define EXMC_SDRAM_4_INTER_BANK ((uint32_t)0x00000040U) /*!< 4 internal banks */ +#define EXMC_SDRAM_2_INTER_BANK ((uint32_t)0x00000000U) /*!< 2 internal banks */ +#define EXMC_SDRAM_4_INTER_BANK EXMC_SDCTL_NBK /*!< 4 internal banks */ /* SDRAM device0 select */ -#define EXMC_SDRAM_DEVICE0_UNSELECT ((uint32_t)0x00000000U) /*!< NAND data width 8 bits */ -#define EXMC_SDRAM_DEVICE0_SELECT ((uint32_t)0x00000010U) /*!< NAND data width 16 bits */ +#define EXMC_SDRAM_DEVICE0_UNSELECT ((uint32_t)0x00000000U) /*!< SDRAM device0 unselect */ +#define EXMC_SDRAM_DEVICE0_SELECT EXMC_SDCMD_DS0 /*!< SDRAM device0 select */ /* SDRAM device1 select */ -#define EXMC_SDRAM_DEVICE1_UNSELECT ((uint32_t)0x00000000U) /*!< NAND data width 8 bits */ -#define EXMC_SDRAM_DEVICE1_SELECT ((uint32_t)0x00000008U) /*!< NAND data width 16 bits */ +#define EXMC_SDRAM_DEVICE1_UNSELECT ((uint32_t)0x00000000U) /*!< SDRAM device1 unselect */ +#define EXMC_SDRAM_DEVICE1_SELECT EXMC_SDCMD_DS1 /*!< SDRAM device1 select */ /* SDRAM device status */ -#define EXMC_SDRAM_DEVICE_NORMAL ((uint32_t)0x00000000U) /*!< normal status */ -#define EXMC_SDRAM_DEVICE_SELF_REFRESH ((uint32_t)0x00000001U) /*!< self refresh status */ -#define EXMC_SDRAM_DEVICE_POWER_DOWN ((uint32_t)0x00000002U) /*!< power down status */ +#define EXMC_SDRAM_DEVICE_NORMAL ((uint32_t)0x00000000U) /*!< normal status */ +#define EXMC_SDRAM_DEVICE_SELF_REFRESH ((uint32_t)0x00000001U) /*!< self refresh status */ +#define EXMC_SDRAM_DEVICE_POWER_DOWN ((uint32_t)0x00000002U) /*!< power down status */ /* sample cycle of read data */ -#define EXMC_SDRAM_READSAMPLE_0_EXTRAHCLK ((uint32_t)0x00000000U) /*!< add 0 extra HCLK cycle to the read data sample clock besides the delay chain */ -#define EXMC_SDRAM_READSAMPLE_1_EXTRAHCLK ((uint32_t)0x00000002U) /*!< add 1 extra HCLK cycle to the read data sample clock besides the delay chain */ +#define EXMC_SDRAM_READSAMPLE_0_EXTRAHCLK ((uint32_t)0x00000000U) /*!< add 0 extra HCLK cycle to the read data sample clock besides the delay chain */ +#define EXMC_SDRAM_READSAMPLE_1_EXTRAHCLK EXMC_SDRSCTL_SSCR /*!< add 1 extra HCLK cycle to the read data sample clock besides the delay chain */ /* read data sample polarity */ -#define EXMC_SDRAM_SAMPLE_RISING_EDGE ((uint32_t)0x00000000U) /*!< sample data at rising edge */ -#define EXMC_SDRAM_SAMPLE_FALLING_EDGE ((uint32_t)0x80000000U) /*!< sample data at falling edge */ +#define EXMC_SQPIPSRAM_SAMPLE_RISING_EDGE ((uint32_t)0x00000000U) /*!< sample data at rising edge */ +#define EXMC_SQPIPSRAM_SAMPLE_FALLING_EDGE EXMC_SINIT_POL /*!< sample data at falling edge */ /* SQPI SRAM command flag */ -#define EXMC_SEND_COMMAND_FLAG_RDID EXMC_SRCMD_RDID /*!< EXMC_SRCMD_RDID flag bit */ -#define EXMC_SEND_COMMAND_FLAG_SC EXMC_SWCMD_SC /*!< EXMC_SWCMD_SC flag bit */ +#define EXMC_SEND_COMMAND_FLAG_RDID EXMC_SRCMD_RDID /*!< EXMC_SRCMD_RDID flag bit */ +#define EXMC_SEND_COMMAND_FLAG_SC EXMC_SWCMD_SC /*!< EXMC_SWCMD_SC flag bit */ /* EXMC flag bits */ -#define EXMC_NAND_PCCARD_FLAG_RISE EXMC_NPINTENx_INTRS /*!< interrupt rising edge status */ -#define EXMC_NAND_PCCARD_FLAG_LEVEL EXMC_NPINTENx_INTHS /*!< interrupt high-level status */ -#define EXMC_NAND_PCCARD_FLAG_FALL EXMC_NPINTENx_INTFS /*!< interrupt falling edge status */ -#define EXMC_NAND_PCCARD_FLAG_FIFOE EXMC_NPINTENx_INTEPT /*!< FIFO empty flag */ -#define EXMC_SDRAM_FLAG_REFRESH EXMC_SDSDAT_REIF /*!< refresh error interrupt flag */ -#define EXMC_SDRAM_FLAG_NREADY EXMC_SDSDAT_NRDY /*!< not ready status */ +#define EXMC_NAND_PCCARD_FLAG_RISE EXMC_NPINTEN_INTRS /*!< interrupt rising edge status */ +#define EXMC_NAND_PCCARD_FLAG_LEVEL EXMC_NPINTEN_INTHS /*!< interrupt high-level status */ +#define EXMC_NAND_PCCARD_FLAG_FALL EXMC_NPINTEN_INTFS /*!< interrupt falling edge status */ +#define EXMC_NAND_PCCARD_FLAG_FIFOE EXMC_NPINTEN_FFEPT /*!< FIFO empty flag */ +#define EXMC_SDRAM_FLAG_REFRESH EXMC_SDSDAT_REIF /*!< refresh error interrupt flag */ +#define EXMC_SDRAM_FLAG_NREADY EXMC_SDSDAT_NRDY /*!< not ready status */ /* EXMC interrupt flag bits */ -#define EXMC_NAND_PCCARD_INT_RISE EXMC_NPINTENx_INTREN /*!< interrupt rising edge detection enable */ -#define EXMC_NAND_PCCARD_INT_LEVEL EXMC_NPINTENx_INTHEN /*!< interrupt high-level detection enable */ -#define EXMC_NAND_PCCARD_INT_FALL EXMC_NPINTENx_INTFEN /*!< interrupt falling edge detection enable */ -#define EXMC_SDRAM_INT_REFRESH EXMC_SDARI_REIE /*!< interrupt refresh error enable */ +#define EXMC_NAND_PCCARD_INT_FLAG_RISE EXMC_NPINTEN_INTREN /*!< rising edge interrupt and flag */ +#define EXMC_NAND_PCCARD_INT_FLAG_LEVEL EXMC_NPINTEN_INTHEN /*!< high-level interrupt and flag */ +#define EXMC_NAND_PCCARD_INT_FLAG_FALL EXMC_NPINTEN_INTFEN /*!< falling edge interrupt and flag */ +#define EXMC_SDRAM_INT_FLAG_REFRESH EXMC_SDARI_REIE /*!< refresh error interrupt and flag */ /* function declarations */ +/* initialization functions */ +/* NOR/SRAM */ /* deinitialize EXMC NOR/SRAM region */ void exmc_norsram_deinit(uint32_t exmc_norsram_region); +/* initialize exmc_norsram_parameter_struct with the default values */ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); /* initialize EXMC NOR/SRAM region */ void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); -/* exmc_norsram_parameter_struct parameter initialize */ -void exmc_norsram_parameter_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); -/* consecutive clock configure */ -void exmc_norsram_consecutive_clock_config(uint32_t clock_mode); -/* CRAM page size configure */ -void exmc_norsram_page_size_config(uint32_t page_size); -/* EXMC NOR/SRAM bank enable */ +/* enable EXMC NOR/SRAM region */ void exmc_norsram_enable(uint32_t exmc_norsram_region); -/* EXMC NOR/SRAM bank disable */ +/* disable EXMC NOR/SRAM region */ void exmc_norsram_disable(uint32_t exmc_norsram_region); - - +/* NAND */ /* deinitialize EXMC NAND bank */ void exmc_nand_deinit(uint32_t exmc_nand_bank); +/* initialize exmc_norsram_parameter_struct with the default values */ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct); /* initialize EXMC NAND bank */ void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct); -/* exmc_norsram_parameter_struct parameter initialize */ -void exmc_nand_parameter_init(exmc_nand_parameter_struct* exmc_nand_init_struct); -/* EXMC NAND bank enable */ +/* enable EXMC NAND bank */ void exmc_nand_enable(uint32_t exmc_nand_bank); -/* EXMC NAND bank disable */ +/* disable EXMC NAND bank */ void exmc_nand_disable(uint32_t exmc_nand_bank); +/* PC card */ +/* deinitialize EXMC PC card bank */ +void exmc_pccard_deinit(void); +/* initialize exmc_pccard_parameter_struct with the default values */ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* initialize EXMC PC card bank */ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* enable EXMC PC card bank */ +void exmc_pccard_enable(void); +/* disable EXMC PC card bank */ +void exmc_pccard_disable(void); +/* SDRAM */ +/* deinitialize EXMC SDRAM device */ +void exmc_sdram_deinit(uint32_t exmc_sdram_device); +/* initialize exmc_sdram_parameter_struct with the default values */ +void exmc_sdram_struct_para_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct); +/* initialize EXMC SDRAM device */ +void exmc_sdram_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct); +/* SQPIPSRAM */ +/* deinitialize EXMC SQPIPSRAM */ +void exmc_sqpipsram_deinit(void); +/* initialize exmc_sqpipsram_parameter_struct with the default values */ +void exmc_sqpipsram_struct_para_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct); +/* initialize EXMC SQPIPSRAM */ +void exmc_sqpipsram_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct); + +/* function configuration */ +/* NOR/SRAM */ +/* configure consecutive clock */ +void exmc_norsram_consecutive_clock_config(uint32_t clock_mode); +/* configure CRAM page size */ +void exmc_norsram_page_size_config(uint32_t exmc_norsram_region, uint32_t page_size); +/* NAND */ /* enable or disable the EXMC NAND ECC function */ void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue); /* get the EXMC ECC value */ uint32_t exmc_ecc_get(uint32_t exmc_nand_bank); - - -/* deinitialize EXMC PC card bank */ -void exmc_pccard_deinit(void); -/* initialize EXMC PC card bank */ -void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); -/* exmc_pccard_parameter_struct parameter initialize */ -void exmc_pccard_parameter_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); -/* EXMC PC card bank enable */ -void exmc_pccard_enable(void); -/* EXMC PC card bank disable */ -void exmc_pccard_disable(void); - - -/* deinitialize EXMC SDRAM device */ -void exmc_sdram_deinit(uint32_t exmc_sdram_device); -/* initialize EXMC SDRAM device */ -void exmc_sdram_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct); -/* exmc_sdram_parameter_struct parameter initialize */ -void exmc_sdram_parameter_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct); +/* SDRAM */ +/* enable or disable read sample */ +void exmc_sdram_readsample_enable(ControlStatus newvalue); +/* configure the delayed sample clock of read data */ +void exmc_sdram_readsample_config(uint32_t delay_cell, uint32_t extra_hclk); /* configure the SDRAM memory command */ void exmc_sdram_command_config(exmc_sdram_command_parameter_struct* exmc_sdram_command_init_struct); /* set auto-refresh interval */ @@ -737,18 +776,7 @@ void exmc_sdram_autorefresh_number_set(uint32_t exmc_number); void exmc_sdram_write_protection_config(uint32_t exmc_sdram_device, ControlStatus newvalue); /* get the status of SDRAM device0 or device1 */ uint32_t exmc_sdram_bankstatus_get(uint32_t exmc_sdram_device); -/* configure the delayed sample clock of read data */ -void exmc_sdram_readsample_config(uint32_t delay_cell, uint32_t extra_hclk); -/* enable or disable read sample */ -void exmc_sdram_readsample_enable(ControlStatus newvalue); - - -/* deinitialize EXMC SQPIPSRAM */ -void exmc_sqpipsram_deinit(void); -/* initialize EXMC SQPIPSRAM */ -void exmc_sqpipsram_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct); -/* exmc_sqpipsram_parameter_struct parameter initialize */ -void exmc_sqpipsram_parameter_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct); +/* SQPIPSRAM */ /* set the read command */ void exmc_sqpipsram_read_command_set(uint32_t read_command_mode,uint32_t read_wait_cycle,uint32_t read_command_code); /* set the write command */ @@ -764,18 +792,18 @@ uint32_t exmc_sqpipsram_high_id_get(void); /* get the bit value of EXMC send write command bit or read ID command */ FlagStatus exmc_sqpipsram_send_command_state_get(uint32_t send_command_flag); - -/* check EXMC flag is set or not */ -FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag); -/* clear EXMC flag */ -void exmc_flag_clear(uint32_t exmc_bank,uint32_t flag); -/* check EXMC flag is set or not */ -FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt_source); -/* clear EXMC one channel flag */ -void exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt_source); +/* interrupt & flag functions */ /* enable EXMC interrupt */ -void exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt_source); +void exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt); /* disable EXMC interrupt */ -void exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt_source); +void exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt); +/* get EXMC flag status */ +FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag); +/* clear EXMC flag status */ +void exmc_flag_clear(uint32_t exmc_bank,uint32_t flag); +/* get EXMC interrupt flag */ +FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt); +/* clear EXMC interrupt flag */ +void exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt); #endif /* GD32F4XX_EXMC_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h index a0ad59400a..3c2a27149d 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_exti.h - \brief definitions for the EXTI + \file gd32f4xx_exti.h + \brief definitions for the EXTI + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.1, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_EXTI_H @@ -97,6 +122,7 @@ #define EXTI_RTEN_RTEN17 BIT(17) /*!< rising edge from line 17 */ #define EXTI_RTEN_RTEN18 BIT(18) /*!< rising edge from line 18 */ #define EXTI_RTEN_RTEN19 BIT(19) /*!< rising edge from line 19 */ +#define EXTI_RTEN_RTEN20 BIT(20) /*!< rising edge from line 20 */ #define EXTI_RTEN_RTEN21 BIT(21) /*!< rising edge from line 21 */ #define EXTI_RTEN_RTEN22 BIT(22) /*!< rising edge from line 22 */ @@ -121,6 +147,7 @@ #define EXTI_FTEN_FTEN17 BIT(17) /*!< falling edge from line 17 */ #define EXTI_FTEN_FTEN18 BIT(18) /*!< falling edge from line 18 */ #define EXTI_FTEN_FTEN19 BIT(19) /*!< falling edge from line 19 */ +#define EXTI_FTEN_FTEN20 BIT(20) /*!< falling edge from line 20 */ #define EXTI_FTEN_FTEN21 BIT(21) /*!< falling edge from line 21 */ #define EXTI_FTEN_FTEN22 BIT(22) /*!< falling edge from line 22 */ @@ -145,6 +172,7 @@ #define EXTI_SWIEV_SWIEV17 BIT(17) /*!< software interrupt/event request from line 17 */ #define EXTI_SWIEV_SWIEV18 BIT(18) /*!< software interrupt/event request from line 18 */ #define EXTI_SWIEV_SWIEV19 BIT(19) /*!< software interrupt/event request from line 19 */ +#define EXTI_SWIEV_SWIEV20 BIT(20) /*!< software interrupt/event request from line 20 */ #define EXTI_SWIEV_SWIEV21 BIT(21) /*!< software interrupt/event request from line 21 */ #define EXTI_SWIEV_SWIEV22 BIT(22) /*!< software interrupt/event request from line 22 */ @@ -169,13 +197,14 @@ #define EXTI_PD_PD17 BIT(17) /*!< interrupt/event pending status from line 17 */ #define EXTI_PD_PD18 BIT(18) /*!< interrupt/event pending status from line 18 */ #define EXTI_PD_PD19 BIT(19) /*!< interrupt/event pending status from line 19 */ +#define EXTI_PD_PD20 BIT(20) /*!< interrupt/event pending status from line 20 */ #define EXTI_PD_PD21 BIT(21) /*!< interrupt/event pending status from line 21 */ #define EXTI_PD_PD22 BIT(22) /*!< interrupt/event pending status from line 22 */ /* constants definitions */ /* EXTI line number */ typedef enum -{ +{ EXTI_0 = BIT(0), /*!< EXTI line 0 */ EXTI_1 = BIT(1), /*!< EXTI line 1 */ EXTI_2 = BIT(2), /*!< EXTI line 2 */ @@ -196,7 +225,7 @@ typedef enum EXTI_17 = BIT(17), /*!< EXTI line 17 */ EXTI_18 = BIT(18), /*!< EXTI line 18 */ EXTI_19 = BIT(19), /*!< EXTI line 19 */ - EXTI_20 = BIT(20), /*!< EXTI line 20 */ + EXTI_20 = BIT(20), /*!< EXTI line 20 */ EXTI_21 = BIT(21), /*!< EXTI line 21 */ EXTI_22 = BIT(22), /*!< EXTI line 22 */ }exti_line_enum; @@ -210,10 +239,11 @@ typedef enum /* interrupt trigger mode */ typedef enum -{ +{ EXTI_TRIG_RISING = 0, /*!< EXTI rising edge trigger */ EXTI_TRIG_FALLING, /*!< EXTI falling edge trigger */ - EXTI_TRIG_BOTH /*!< EXTI rising and falling edge trigger */ + EXTI_TRIG_BOTH, /*!< EXTI rising and falling edge trigger */ + EXTI_TRIG_NONE /*!< none EXTI edge trigger */ }exti_trig_type_enum; /* function declarations */ @@ -223,13 +253,18 @@ void exti_deinit(void); void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type); /* enable the interrupts from EXTI line x */ void exti_interrupt_enable(exti_line_enum linex); -/* enable the events from EXTI line x */ -void exti_event_enable(exti_line_enum linex); /* disable the interrupts from EXTI line x */ void exti_interrupt_disable(exti_line_enum linex); +/* enable the events from EXTI line x */ +void exti_event_enable(exti_line_enum linex); /* disable the events from EXTI line x */ void exti_event_disable(exti_line_enum linex); +/* EXTI software interrupt event enable */ +void exti_software_interrupt_enable(exti_line_enum linex); +/* EXTI software interrupt event disable */ +void exti_software_interrupt_disable(exti_line_enum linex); +/* interrupt & flag functions */ /* get EXTI lines pending flag */ FlagStatus exti_flag_get(exti_line_enum linex); /* clear EXTI lines pending flag */ @@ -238,9 +273,5 @@ void exti_flag_clear(exti_line_enum linex); FlagStatus exti_interrupt_flag_get(exti_line_enum linex); /* clear EXTI lines pending flag */ void exti_interrupt_flag_clear(exti_line_enum linex); -/* EXTI software interrupt event enable */ -void exti_software_interrupt_enable(exti_line_enum linex); -/* EXTI software interrupt event disable */ -void exti_software_interrupt_disable(exti_line_enum linex); #endif /* GD32F4XX_EXTI_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h index c3b360ab02..9b1b82c083 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h @@ -1,13 +1,40 @@ /*! - \file gd32f4xx_fmc.h - \brief definitions for the FMC + \file gd32f4xx_fmc.h + \brief definitions for the FMC + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ + + #ifndef GD32F4XX_FMC_H #define GD32F4XX_FMC_H @@ -18,15 +45,15 @@ #define OB OB_BASE /*!< option byte base address */ /* registers definitions */ -#define FMC_WS REG32((FMC) + 0x00U) /*!< FMC wait state register */ -#define FMC_KEY REG32((FMC) + 0x04U) /*!< FMC unlock key register */ -#define FMC_OBKEY REG32((FMC) + 0x08U) /*!< FMC option byte unlock key register */ -#define FMC_STAT REG32((FMC) + 0x0CU) /*!< FMC status register */ -#define FMC_CTL REG32((FMC) + 0x10U) /*!< FMC control register */ -#define FMC_OBCTL0 REG32((FMC) + 0x14U) /*!< FMC option byte control register 0 */ -#define FMC_OBCTL1 REG32((FMC) + 0x18U) /*!< FMC option byte control register 1 */ -#define FMC_WSEN REG32((FMC) + 0xFCU) /*!< FMC wait state enable register */ -#define FMC_PID REG32((FMC) + 0x100U) /*!< FMC product ID register */ +#define FMC_WS REG32((FMC) + 0x0000U) /*!< FMC wait state register */ +#define FMC_KEY REG32((FMC) + 0x0004U) /*!< FMC unlock key register */ +#define FMC_OBKEY REG32((FMC) + 0x0008U) /*!< FMC option byte unlock key register */ +#define FMC_STAT REG32((FMC) + 0x000CU) /*!< FMC status register */ +#define FMC_CTL REG32((FMC) + 0x0010U) /*!< FMC control register */ +#define FMC_OBCTL0 REG32((FMC) + 0x0014U) /*!< FMC option byte control register 0 */ +#define FMC_OBCTL1 REG32((FMC) + 0x0018U) /*!< FMC option byte control register 1 */ +#define FMC_WSEN REG32((FMC) + 0x00FCU) /*!< FMC wait state enable register */ +#define FMC_PID REG32((FMC) + 0x0100U) /*!< FMC product ID register */ #define OB_WP1 REG32((OB) + 0x00000008U) /*!< option byte write protection 1 */ #define OB_USER REG32((OB) + 0x00010000U) /*!< option byte user value*/ @@ -98,7 +125,6 @@ typedef enum FMC_WPERR, /*!< erase/program protection error */ FMC_OPERR, /*!< operation error */ FMC_PGERR, /*!< program error */ - FMC_TOERR /*!< timeout error */ }fmc_state_enum; /* unlock key */ @@ -108,9 +134,6 @@ typedef enum #define OB_UNLOCK_KEY0 ((uint32_t)0x08192A3BU) /*!< ob unlock key 0 */ #define OB_UNLOCK_KEY1 ((uint32_t)0x4C5D6E7FU) /*!< ob unlock key 1 */ -/* FMC time out */ -#define FMC_TIMEOUT_COUNT ((uint32_t)0x000F0000) /*!< enable FMC error timeout */ - /* option byte write protection */ #define OB_LWP ((uint32_t)0x000000FFU) /*!< write protection low bits */ #define OB_HWP ((uint32_t)0x0000FF00U) /*!< write protection high bits */ @@ -146,7 +169,7 @@ typedef enum #define OB_BB_DISABLE OBCTL0_BB(0) /*!< boot from bank0 */ #define OB_BB_ENABLE OBCTL0_BB(1) /*!< boot from bank1 or bank0 if bank1 is void */ -/* option byte software/hardware free watch dog timer */ +/* option byte software/hardware free watch dog timer */ #define OBCTL0_NWDG_HW(regval) (BIT(5) & ((uint32_t)(regval))<< 5) #define OB_FWDGT_SW OBCTL0_NWDG_HW(1) /*!< software free watchdog */ #define OB_FWDGT_HW OBCTL0_NWDG_HW(0) /*!< hardware free watchdog */ @@ -179,19 +202,19 @@ typedef enum #define OB_WP_9 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 9 */ #define OB_WP_10 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 10 */ #define OB_WP_11 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 11 */ -#define OB_WP_12 ((uint32_t)0x00000001U) /*!< erase/program protection of sector 12 */ -#define OB_WP_13 ((uint32_t)0x00000002U) /*!< erase/program protection of sector 13 */ -#define OB_WP_14 ((uint32_t)0x00000004U) /*!< erase/program protection of sector 14 */ -#define OB_WP_15 ((uint32_t)0x00000008U) /*!< erase/program protection of sector 15 */ -#define OB_WP_16 ((uint32_t)0x00000010U) /*!< erase/program protection of sector 16 */ -#define OB_WP_17 ((uint32_t)0x00000020U) /*!< erase/program protection of sector 17 */ -#define OB_WP_18 ((uint32_t)0x00000040U) /*!< erase/program protection of sector 18 */ -#define OB_WP_19 ((uint32_t)0x00000080U) /*!< erase/program protection of sector 19 */ -#define OB_WP_20 ((uint32_t)0x00000100U) /*!< erase/program protection of sector 20 */ -#define OB_WP_21 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 21 */ -#define OB_WP_22 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 22 */ -#define OB_WP_23_30 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 23~30 */ -#define OB_WP_ALL ((uint32_t)0x00000FFFU) /*!< erase/program protection of all sectors */ +#define OB_WP_12 ((uint32_t)0x00010000U) /*!< erase/program protection of sector 12 */ +#define OB_WP_13 ((uint32_t)0x00020000U) /*!< erase/program protection of sector 13 */ +#define OB_WP_14 ((uint32_t)0x00040000U) /*!< erase/program protection of sector 14 */ +#define OB_WP_15 ((uint32_t)0x00080000U) /*!< erase/program protection of sector 15 */ +#define OB_WP_16 ((uint32_t)0x00100000U) /*!< erase/program protection of sector 16 */ +#define OB_WP_17 ((uint32_t)0x00200000U) /*!< erase/program protection of sector 17 */ +#define OB_WP_18 ((uint32_t)0x00400000U) /*!< erase/program protection of sector 18 */ +#define OB_WP_19 ((uint32_t)0x00800000U) /*!< erase/program protection of sector 19 */ +#define OB_WP_20 ((uint32_t)0x01000000U) /*!< erase/program protection of sector 20 */ +#define OB_WP_21 ((uint32_t)0x02000000U) /*!< erase/program protection of sector 21 */ +#define OB_WP_22 ((uint32_t)0x04000000U) /*!< erase/program protection of sector 22 */ +#define OB_WP_23_27 ((uint32_t)0x08000000U) /*!< erase/program protection of sector 23~27 */ +#define OB_WP_ALL ((uint32_t)0x0FFF0FFFU) /*!< erase/program protection of all sectors */ /* option bytes D-bus read protection */ #define OB_DRP_0 ((uint32_t)0x00000001U) /*!< D-bus read protection protection of sector 0 */ @@ -206,26 +229,25 @@ typedef enum #define OB_DRP_9 ((uint32_t)0x00000200U) /*!< D-bus read protection protection of sector 9 */ #define OB_DRP_10 ((uint32_t)0x00000400U) /*!< D-bus read protection protection of sector 10 */ #define OB_DRP_11 ((uint32_t)0x00000800U) /*!< D-bus read protection protection of sector 11 */ -#define OB_DRP_12 ((uint32_t)0x00000001U) /*!< D-bus read protection protection of sector 12 */ -#define OB_DRP_13 ((uint32_t)0x00000002U) /*!< D-bus read protection protection of sector 13 */ -#define OB_DRP_14 ((uint32_t)0x00000004U) /*!< D-bus read protection protection of sector 14 */ -#define OB_DRP_15 ((uint32_t)0x00000008U) /*!< D-bus read protection protection of sector 15 */ -#define OB_DRP_16 ((uint32_t)0x00000010U) /*!< D-bus read protection protection of sector 16 */ -#define OB_DRP_17 ((uint32_t)0x00000020U) /*!< D-bus read protection protection of sector 17 */ -#define OB_DRP_18 ((uint32_t)0x00000040U) /*!< D-bus read protection protection of sector 18 */ -#define OB_DRP_19 ((uint32_t)0x00000080U) /*!< D-bus read protection protection of sector 19 */ -#define OB_DRP_20 ((uint32_t)0x00000100U) /*!< D-bus read protection protection of sector 20 */ -#define OB_DRP_21 ((uint32_t)0x00000200U) /*!< D-bus read protection protection of sector 21 */ -#define OB_DRP_22 ((uint32_t)0x00000400U) /*!< D-bus read protection protection of sector 22 */ -#define OB_DRP_23_30 ((uint32_t)0x00000800U) /*!< D-bus read protection protection of sector 23~30 */ -#define OB_DRP_ALL ((uint32_t)0x00000FFFU) /*!< D-bus read protection protection of all sectors */ +#define OB_DRP_12 ((uint32_t)0x00010000U) /*!< D-bus read protection protection of sector 12 */ +#define OB_DRP_13 ((uint32_t)0x00020000U) /*!< D-bus read protection protection of sector 13 */ +#define OB_DRP_14 ((uint32_t)0x00040000U) /*!< D-bus read protection protection of sector 14 */ +#define OB_DRP_15 ((uint32_t)0x00080000U) /*!< D-bus read protection protection of sector 15 */ +#define OB_DRP_16 ((uint32_t)0x00100000U) /*!< D-bus read protection protection of sector 16 */ +#define OB_DRP_17 ((uint32_t)0x00200000U) /*!< D-bus read protection protection of sector 17 */ +#define OB_DRP_18 ((uint32_t)0x00400000U) /*!< D-bus read protection protection of sector 18 */ +#define OB_DRP_19 ((uint32_t)0x00800000U) /*!< D-bus read protection protection of sector 19 */ +#define OB_DRP_20 ((uint32_t)0x01000000U) /*!< D-bus read protection protection of sector 20 */ +#define OB_DRP_21 ((uint32_t)0x02000000U) /*!< D-bus read protection protection of sector 21 */ +#define OB_DRP_22 ((uint32_t)0x04000000U) /*!< D-bus read protection protection of sector 22 */ +#define OB_DRP_23_27 ((uint32_t)0x08000000U) /*!< D-bus read protection protection of sector 23~27 */ -/* double banks or single bank selection when flash size is 1M bytes */ +/* double banks or single bank selection when flash size is 1M bytes */ #define OBCTL0_DBS(regval) (BIT(30) & ((uint32_t)(regval)<<30)) #define OB_DBS_DISABLE OBCTL0_DBS(0) /*!< single bank when flash size is 1M bytes */ #define OB_DBS_ENABLE OBCTL0_DBS(1) /*!< double bank when flash size is 1M bytes */ -/* option bytes D-bus read protection mode */ +/* option bytes D-bus read protection mode */ #define OBCTL0_DRP(regval) (BIT(31) & ((uint32_t)(regval)<<31)) #define OB_DRP_DISABLE OBCTL0_DRP(0) /*!< the WPx bits used as erase/program protection of each sector */ #define OB_DRP_ENABLE OBCTL0_DRP(1) /*!< the WPx bits used as erase/program protection and D-bus read protection of each sector */ @@ -260,19 +282,17 @@ typedef enum #define CTL_SECTOR_NUMBER_21 CTL_SN(25) /*!< sector 21 */ #define CTL_SECTOR_NUMBER_22 CTL_SN(26) /*!< sector 22 */ #define CTL_SECTOR_NUMBER_23 CTL_SN(27) /*!< sector 23 */ -#define CTL_SECTOR_NUMBER_28 CTL_SN(28) /*!< sector 28 */ -#define CTL_SECTOR_NUMBER_29 CTL_SN(29) /*!< sector 29 */ -#define CTL_SECTOR_NUMBER_30 CTL_SN(30) /*!< sector 30 */ -/* FMC program size */ + +/* FMC program size */ #define CTL_PSZ(regval) (BITS(8,9) & ((uint32_t)(regval))<< 8) #define CTL_PSZ_BYTE CTL_PSZ(0) /*!< FMC program by byte access */ #define CTL_PSZ_HALF_WORD CTL_PSZ(1) /*!< FMC program by half-word access */ #define CTL_PSZ_WORD CTL_PSZ(2) /*!< FMC program by word access */ /* FMC interrupt enable */ -#define FMC_INTEN_END ((uint32_t)0x01000000U) /*!< enable FMC end of program interrupt */ -#define FMC_INTEN_ERR ((uint32_t)0x02000000U) /*!< enable FMC error interrupt */ +#define FMC_INT_END ((uint32_t)0x01000000U) /*!< enable FMC end of program interrupt */ +#define FMC_INT_ERR ((uint32_t)0x02000000U) /*!< enable FMC error interrupt */ /* FMC flags */ #define FMC_FLAG_END ((uint32_t)0x00000001U) /*!< FMC end of operation flag bit */ @@ -281,7 +301,7 @@ typedef enum #define FMC_FLAG_PGMERR ((uint32_t)0x00000040U) /*!< FMC program size not match error flag bit */ #define FMC_FLAG_PGSERR ((uint32_t)0x00000080U) /*!< FMC program sequence error flag bit */ #define FMC_FLAG_RDDERR ((uint32_t)0x00000100U) /*!< FMC read D-bus protection error flag bit */ -#define FMC_FLAG_BUSY ((uint32_t)0x00010000U) /*!< FMC busy flag */ +#define FMC_FLAG_BUSY ((uint32_t)0x00010000U) /*!< FMC busy flag */ /* function declarations */ /* FMC main memory programming functions */ @@ -313,25 +333,17 @@ void ob_unlock(void); void ob_lock(void); /* send option byte change command */ void ob_start(void); +/* erase option byte */ +void ob_erase(void); /* enable write protect */ -void ob_write_protection0_enable(uint32_t ob_wp); +void ob_write_protection_enable(uint32_t ob_wp); /* disable write protect */ -void ob_write_protection0_disable(uint32_t ob_wp); -/* enable write protect */ -void ob_write_protection1_enable(uint32_t ob_wp); -/* disable write protect */ -void ob_write_protection1_disable(uint32_t ob_wp); -/* configure the erase/program protection mode */ -void ob_drp_config(uint32_t ob_drp); -/* enable the erase/program protection mode */ -void ob_drp0_enable(uint32_t ob_drp); -/* disable the erase/program protection mode */ -void ob_drp0_disable(uint32_t ob_drp); -/* enable the erase/program protection mode */ -void ob_drp1_enable(uint32_t ob_drp); -/* disable the erase/program protection mode */ -void ob_drp1_disable(uint32_t ob_drp); -/* set the option byte security protection level */ +void ob_write_protection_disable(uint32_t ob_wp); +/* enable erase/program protection and D-bus read protection */ +void ob_drp_enable(uint32_t ob_drp); +/* disable erase/program protection and D-bus read protection */ +void ob_drp_disable(uint32_t ob_drp); +/* set the option byte security protection level */ void ob_security_protection_config(uint8_t ob_spc); /* write the FMC option byte user */ void ob_user_write(uint32_t ob_fwdgt, uint32_t ob_deepsleep, uint32_t ob_stdby); @@ -366,6 +378,6 @@ void fmc_flag_clear(uint32_t fmc_flag); /* return the FMC state */ fmc_state_enum fmc_state_get(void); /* check FMC ready or not */ -fmc_state_enum fmc_ready_wait(uint32_t count); +fmc_state_enum fmc_ready_wait(void); #endif /* GD32F4XX_FMC_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h index b63efc9293..ebee04b637 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_fwdgt.h - \brief definitions for the FWDGT + \file gd32f4xx_fwdgt.h + \brief definitions for the FWDGT + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_FWDGT_H @@ -58,7 +83,13 @@ #define FWDGT_PSC_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_PSC register write operation state flag timeout */ #define FWDGT_RLD_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_RLD register write operation state flag timeout */ +/* FWDGT flag definitions */ +#define FWDGT_FLAG_PUD FWDGT_STAT_PUD /*!< FWDGT prescaler divider value update flag */ +#define FWDGT_FLAG_RUD FWDGT_STAT_RUD /*!< FWDGT counter reload value update flag */ + /* function declarations */ +/* enable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_enable(void); /* disable write access to FWDGT_PSC and FWDGT_RLD */ void fwdgt_write_disable(void); /* start the free watchdog timer counter */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h index 257962d6de..81da899427 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_gpio.h - \brief definitions for the GPIO + \file gd32f4xx_gpio.h + \brief definitions for the GPIO + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_GPIO_H @@ -41,343 +66,343 @@ /* bits definitions */ /* GPIO_CTL */ -#define GPIO_CTL_CTL0 BITS(0,1) /*!< pin 0 configuration bits */ -#define GPIO_CTL_CTL1 BITS(2,3) /*!< pin 1 configuration bits */ -#define GPIO_CTL_CTL2 BITS(4,5) /*!< pin 2 configuration bits */ -#define GPIO_CTL_CTL3 BITS(6,7) /*!< pin 3 configuration bits */ -#define GPIO_CTL_CTL4 BITS(8,9) /*!< pin 4 configuration bits */ -#define GPIO_CTL_CTL5 BITS(10,11) /*!< pin 5 configuration bits */ -#define GPIO_CTL_CTL6 BITS(12,13) /*!< pin 6 configuration bits */ -#define GPIO_CTL_CTL7 BITS(14,15) /*!< pin 7 configuration bits */ -#define GPIO_CTL_CTL8 BITS(16,17) /*!< pin 8 configuration bits */ -#define GPIO_CTL_CTL9 BITS(18,19) /*!< pin 9 configuration bits */ -#define GPIO_CTL_CTL10 BITS(20,21) /*!< pin 10 configuration bits */ -#define GPIO_CTL_CTL11 BITS(22,23) /*!< pin 11 configuration bits */ -#define GPIO_CTL_CTL12 BITS(24,25) /*!< pin 12 configuration bits */ -#define GPIO_CTL_CTL13 BITS(26,27) /*!< pin 13 configuration bits */ -#define GPIO_CTL_CTL14 BITS(28,29) /*!< pin 14 configuration bits */ -#define GPIO_CTL_CTL15 BITS(30,31) /*!< pin 15 configuration bits */ +#define GPIO_CTL_CTL0 BITS(0,1) /*!< pin 0 configuration bits */ +#define GPIO_CTL_CTL1 BITS(2,3) /*!< pin 1 configuration bits */ +#define GPIO_CTL_CTL2 BITS(4,5) /*!< pin 2 configuration bits */ +#define GPIO_CTL_CTL3 BITS(6,7) /*!< pin 3 configuration bits */ +#define GPIO_CTL_CTL4 BITS(8,9) /*!< pin 4 configuration bits */ +#define GPIO_CTL_CTL5 BITS(10,11) /*!< pin 5 configuration bits */ +#define GPIO_CTL_CTL6 BITS(12,13) /*!< pin 6 configuration bits */ +#define GPIO_CTL_CTL7 BITS(14,15) /*!< pin 7 configuration bits */ +#define GPIO_CTL_CTL8 BITS(16,17) /*!< pin 8 configuration bits */ +#define GPIO_CTL_CTL9 BITS(18,19) /*!< pin 9 configuration bits */ +#define GPIO_CTL_CTL10 BITS(20,21) /*!< pin 10 configuration bits */ +#define GPIO_CTL_CTL11 BITS(22,23) /*!< pin 11 configuration bits */ +#define GPIO_CTL_CTL12 BITS(24,25) /*!< pin 12 configuration bits */ +#define GPIO_CTL_CTL13 BITS(26,27) /*!< pin 13 configuration bits */ +#define GPIO_CTL_CTL14 BITS(28,29) /*!< pin 14 configuration bits */ +#define GPIO_CTL_CTL15 BITS(30,31) /*!< pin 15 configuration bits */ /* GPIO_OMODE */ -#define GPIO_OMODE_OM0 BIT(0) /*!< pin 0 output mode bit */ -#define GPIO_OMODE_OM1 BIT(1) /*!< pin 1 output mode bit */ -#define GPIO_OMODE_OM2 BIT(2) /*!< pin 2 output mode bit */ -#define GPIO_OMODE_OM3 BIT(3) /*!< pin 3 output mode bit */ -#define GPIO_OMODE_OM4 BIT(4) /*!< pin 4 output mode bit */ -#define GPIO_OMODE_OM5 BIT(5) /*!< pin 5 output mode bit */ -#define GPIO_OMODE_OM6 BIT(6) /*!< pin 6 output mode bit */ -#define GPIO_OMODE_OM7 BIT(7) /*!< pin 7 output mode bit */ -#define GPIO_OMODE_OM8 BIT(8) /*!< pin 8 output mode bit */ -#define GPIO_OMODE_OM9 BIT(9) /*!< pin 9 output mode bit */ -#define GPIO_OMODE_OM10 BIT(10) /*!< pin 10 output mode bit */ -#define GPIO_OMODE_OM11 BIT(11) /*!< pin 11 output mode bit */ -#define GPIO_OMODE_OM12 BIT(12) /*!< pin 12 output mode bit */ -#define GPIO_OMODE_OM13 BIT(13) /*!< pin 13 output mode bit */ -#define GPIO_OMODE_OM14 BIT(14) /*!< pin 14 output mode bit */ -#define GPIO_OMODE_OM15 BIT(15) /*!< pin 15 output mode bit */ +#define GPIO_OMODE_OM0 BIT(0) /*!< pin 0 output mode bit */ +#define GPIO_OMODE_OM1 BIT(1) /*!< pin 1 output mode bit */ +#define GPIO_OMODE_OM2 BIT(2) /*!< pin 2 output mode bit */ +#define GPIO_OMODE_OM3 BIT(3) /*!< pin 3 output mode bit */ +#define GPIO_OMODE_OM4 BIT(4) /*!< pin 4 output mode bit */ +#define GPIO_OMODE_OM5 BIT(5) /*!< pin 5 output mode bit */ +#define GPIO_OMODE_OM6 BIT(6) /*!< pin 6 output mode bit */ +#define GPIO_OMODE_OM7 BIT(7) /*!< pin 7 output mode bit */ +#define GPIO_OMODE_OM8 BIT(8) /*!< pin 8 output mode bit */ +#define GPIO_OMODE_OM9 BIT(9) /*!< pin 9 output mode bit */ +#define GPIO_OMODE_OM10 BIT(10) /*!< pin 10 output mode bit */ +#define GPIO_OMODE_OM11 BIT(11) /*!< pin 11 output mode bit */ +#define GPIO_OMODE_OM12 BIT(12) /*!< pin 12 output mode bit */ +#define GPIO_OMODE_OM13 BIT(13) /*!< pin 13 output mode bit */ +#define GPIO_OMODE_OM14 BIT(14) /*!< pin 14 output mode bit */ +#define GPIO_OMODE_OM15 BIT(15) /*!< pin 15 output mode bit */ /* GPIO_OSPD */ -#define GPIO_OSPD_OSPD0 BITS(0,1) /*!< pin 0 output max speed bits */ -#define GPIO_OSPD_OSPD1 BITS(2,3) /*!< pin 1 output max speed bits */ -#define GPIO_OSPD_OSPD2 BITS(4,5) /*!< pin 2 output max speed bits */ -#define GPIO_OSPD_OSPD3 BITS(6,7) /*!< pin 3 output max speed bits */ -#define GPIO_OSPD_OSPD4 BITS(8,9) /*!< pin 4 output max speed bits */ -#define GPIO_OSPD_OSPD5 BITS(10,11) /*!< pin 5 output max speed bits */ -#define GPIO_OSPD_OSPD6 BITS(12,13) /*!< pin 6 output max speed bits */ -#define GPIO_OSPD_OSPD7 BITS(14,15) /*!< pin 7 output max speed bits */ -#define GPIO_OSPD_OSPD8 BITS(16,17) /*!< pin 8 output max speed bits */ -#define GPIO_OSPD_OSPD9 BITS(18,19) /*!< pin 9 output max speed bits */ -#define GPIO_OSPD_OSPD10 BITS(20,21) /*!< pin 10 output max speed bits */ -#define GPIO_OSPD_OSPD11 BITS(22,23) /*!< pin 11 output max speed bits */ -#define GPIO_OSPD_OSPD12 BITS(24,25) /*!< pin 12 output max speed bits */ -#define GPIO_OSPD_OSPD13 BITS(26,27) /*!< pin 13 output max speed bits */ -#define GPIO_OSPD_OSPD14 BITS(28,29) /*!< pin 14 output max speed bits */ -#define GPIO_OSPD_OSPD15 BITS(30,31) /*!< pin 15 output max speed bits */ +#define GPIO_OSPD_OSPD0 BITS(0,1) /*!< pin 0 output max speed bits */ +#define GPIO_OSPD_OSPD1 BITS(2,3) /*!< pin 1 output max speed bits */ +#define GPIO_OSPD_OSPD2 BITS(4,5) /*!< pin 2 output max speed bits */ +#define GPIO_OSPD_OSPD3 BITS(6,7) /*!< pin 3 output max speed bits */ +#define GPIO_OSPD_OSPD4 BITS(8,9) /*!< pin 4 output max speed bits */ +#define GPIO_OSPD_OSPD5 BITS(10,11) /*!< pin 5 output max speed bits */ +#define GPIO_OSPD_OSPD6 BITS(12,13) /*!< pin 6 output max speed bits */ +#define GPIO_OSPD_OSPD7 BITS(14,15) /*!< pin 7 output max speed bits */ +#define GPIO_OSPD_OSPD8 BITS(16,17) /*!< pin 8 output max speed bits */ +#define GPIO_OSPD_OSPD9 BITS(18,19) /*!< pin 9 output max speed bits */ +#define GPIO_OSPD_OSPD10 BITS(20,21) /*!< pin 10 output max speed bits */ +#define GPIO_OSPD_OSPD11 BITS(22,23) /*!< pin 11 output max speed bits */ +#define GPIO_OSPD_OSPD12 BITS(24,25) /*!< pin 12 output max speed bits */ +#define GPIO_OSPD_OSPD13 BITS(26,27) /*!< pin 13 output max speed bits */ +#define GPIO_OSPD_OSPD14 BITS(28,29) /*!< pin 14 output max speed bits */ +#define GPIO_OSPD_OSPD15 BITS(30,31) /*!< pin 15 output max speed bits */ /* GPIO_PUD */ -#define GPIO_PUD_PUD0 BITS(0,1) /*!< pin 0 pull-up or pull-down bits */ -#define GPIO_PUD_PUD1 BITS(2,3) /*!< pin 1 pull-up or pull-down bits */ -#define GPIO_PUD_PUD2 BITS(4,5) /*!< pin 2 pull-up or pull-down bits */ -#define GPIO_PUD_PUD3 BITS(6,7) /*!< pin 3 pull-up or pull-down bits */ -#define GPIO_PUD_PUD4 BITS(8,9) /*!< pin 4 pull-up or pull-down bits */ -#define GPIO_PUD_PUD5 BITS(10,11) /*!< pin 5 pull-up or pull-down bits */ -#define GPIO_PUD_PUD6 BITS(12,13) /*!< pin 6 pull-up or pull-down bits */ -#define GPIO_PUD_PUD7 BITS(14,15) /*!< pin 7 pull-up or pull-down bits */ -#define GPIO_PUD_PUD8 BITS(16,17) /*!< pin 8 pull-up or pull-down bits */ -#define GPIO_PUD_PUD9 BITS(18,19) /*!< pin 9 pull-up or pull-down bits */ -#define GPIO_PUD_PUD10 BITS(20,21) /*!< pin 10 pull-up or pull-down bits */ -#define GPIO_PUD_PUD11 BITS(22,23) /*!< pin 11 pull-up or pull-down bits */ -#define GPIO_PUD_PUD12 BITS(24,25) /*!< pin 12 pull-up or pull-down bits */ -#define GPIO_PUD_PUD13 BITS(26,27) /*!< pin 13 pull-up or pull-down bits */ -#define GPIO_PUD_PUD14 BITS(28,29) /*!< pin 14 pull-up or pull-down bits */ -#define GPIO_PUD_PUD15 BITS(30,31) /*!< pin 15 pull-up or pull-down bits */ +#define GPIO_PUD_PUD0 BITS(0,1) /*!< pin 0 pull-up or pull-down bits */ +#define GPIO_PUD_PUD1 BITS(2,3) /*!< pin 1 pull-up or pull-down bits */ +#define GPIO_PUD_PUD2 BITS(4,5) /*!< pin 2 pull-up or pull-down bits */ +#define GPIO_PUD_PUD3 BITS(6,7) /*!< pin 3 pull-up or pull-down bits */ +#define GPIO_PUD_PUD4 BITS(8,9) /*!< pin 4 pull-up or pull-down bits */ +#define GPIO_PUD_PUD5 BITS(10,11) /*!< pin 5 pull-up or pull-down bits */ +#define GPIO_PUD_PUD6 BITS(12,13) /*!< pin 6 pull-up or pull-down bits */ +#define GPIO_PUD_PUD7 BITS(14,15) /*!< pin 7 pull-up or pull-down bits */ +#define GPIO_PUD_PUD8 BITS(16,17) /*!< pin 8 pull-up or pull-down bits */ +#define GPIO_PUD_PUD9 BITS(18,19) /*!< pin 9 pull-up or pull-down bits */ +#define GPIO_PUD_PUD10 BITS(20,21) /*!< pin 10 pull-up or pull-down bits */ +#define GPIO_PUD_PUD11 BITS(22,23) /*!< pin 11 pull-up or pull-down bits */ +#define GPIO_PUD_PUD12 BITS(24,25) /*!< pin 12 pull-up or pull-down bits */ +#define GPIO_PUD_PUD13 BITS(26,27) /*!< pin 13 pull-up or pull-down bits */ +#define GPIO_PUD_PUD14 BITS(28,29) /*!< pin 14 pull-up or pull-down bits */ +#define GPIO_PUD_PUD15 BITS(30,31) /*!< pin 15 pull-up or pull-down bits */ /* GPIO_ISTAT */ -#define GPIO_ISTAT_ISTAT0 BIT(0) /*!< pin 0 input status */ -#define GPIO_ISTAT_ISTAT1 BIT(1) /*!< pin 1 input status */ -#define GPIO_ISTAT_ISTAT2 BIT(2) /*!< pin 2 input status */ -#define GPIO_ISTAT_ISTAT3 BIT(3) /*!< pin 3 input status */ -#define GPIO_ISTAT_ISTAT4 BIT(4) /*!< pin 4 input status */ -#define GPIO_ISTAT_ISTAT5 BIT(5) /*!< pin 5 input status */ -#define GPIO_ISTAT_ISTAT6 BIT(6) /*!< pin 6 input status */ -#define GPIO_ISTAT_ISTAT7 BIT(7) /*!< pin 7 input status */ -#define GPIO_ISTAT_ISTAT8 BIT(8) /*!< pin 8 input status */ -#define GPIO_ISTAT_ISTAT9 BIT(9) /*!< pin 9 input status */ -#define GPIO_ISTAT_ISTAT10 BIT(10) /*!< pin 10 input status */ -#define GPIO_ISTAT_ISTAT11 BIT(11) /*!< pin 11 input status */ -#define GPIO_ISTAT_ISTAT12 BIT(12) /*!< pin 12 input status */ -#define GPIO_ISTAT_ISTAT13 BIT(13) /*!< pin 13 input status */ -#define GPIO_ISTAT_ISTAT14 BIT(14) /*!< pin 14 input status */ -#define GPIO_ISTAT_ISTAT15 BIT(15) /*!< pin 15 input status */ +#define GPIO_ISTAT_ISTAT0 BIT(0) /*!< pin 0 input status */ +#define GPIO_ISTAT_ISTAT1 BIT(1) /*!< pin 1 input status */ +#define GPIO_ISTAT_ISTAT2 BIT(2) /*!< pin 2 input status */ +#define GPIO_ISTAT_ISTAT3 BIT(3) /*!< pin 3 input status */ +#define GPIO_ISTAT_ISTAT4 BIT(4) /*!< pin 4 input status */ +#define GPIO_ISTAT_ISTAT5 BIT(5) /*!< pin 5 input status */ +#define GPIO_ISTAT_ISTAT6 BIT(6) /*!< pin 6 input status */ +#define GPIO_ISTAT_ISTAT7 BIT(7) /*!< pin 7 input status */ +#define GPIO_ISTAT_ISTAT8 BIT(8) /*!< pin 8 input status */ +#define GPIO_ISTAT_ISTAT9 BIT(9) /*!< pin 9 input status */ +#define GPIO_ISTAT_ISTAT10 BIT(10) /*!< pin 10 input status */ +#define GPIO_ISTAT_ISTAT11 BIT(11) /*!< pin 11 input status */ +#define GPIO_ISTAT_ISTAT12 BIT(12) /*!< pin 12 input status */ +#define GPIO_ISTAT_ISTAT13 BIT(13) /*!< pin 13 input status */ +#define GPIO_ISTAT_ISTAT14 BIT(14) /*!< pin 14 input status */ +#define GPIO_ISTAT_ISTAT15 BIT(15) /*!< pin 15 input status */ /* GPIO_OCTL */ -#define GPIO_OCTL_OCTL0 BIT(0) /*!< pin 0 output bit */ -#define GPIO_OCTL_OCTL1 BIT(1) /*!< pin 1 output bit */ -#define GPIO_OCTL_OCTL2 BIT(2) /*!< pin 2 output bit */ -#define GPIO_OCTL_OCTL3 BIT(3) /*!< pin 3 output bit */ -#define GPIO_OCTL_OCTL4 BIT(4) /*!< pin 4 output bit */ -#define GPIO_OCTL_OCTL5 BIT(5) /*!< pin 5 output bit */ -#define GPIO_OCTL_OCTL6 BIT(6) /*!< pin 6 output bit */ -#define GPIO_OCTL_OCTL7 BIT(7) /*!< pin 7 output bit */ -#define GPIO_OCTL_OCTL8 BIT(8) /*!< pin 8 output bit */ -#define GPIO_OCTL_OCTL9 BIT(9) /*!< pin 9 output bit */ -#define GPIO_OCTL_OCTL10 BIT(10) /*!< pin 10 output bit */ -#define GPIO_OCTL_OCTL11 BIT(11) /*!< pin 11 output bit */ -#define GPIO_OCTL_OCTL12 BIT(12) /*!< pin 12 output bit */ -#define GPIO_OCTL_OCTL13 BIT(13) /*!< pin 13 output bit */ -#define GPIO_OCTL_OCTL14 BIT(14) /*!< pin 14 output bit */ -#define GPIO_OCTL_OCTL15 BIT(15) /*!< pin 15 output bit */ +#define GPIO_OCTL_OCTL0 BIT(0) /*!< pin 0 output bit */ +#define GPIO_OCTL_OCTL1 BIT(1) /*!< pin 1 output bit */ +#define GPIO_OCTL_OCTL2 BIT(2) /*!< pin 2 output bit */ +#define GPIO_OCTL_OCTL3 BIT(3) /*!< pin 3 output bit */ +#define GPIO_OCTL_OCTL4 BIT(4) /*!< pin 4 output bit */ +#define GPIO_OCTL_OCTL5 BIT(5) /*!< pin 5 output bit */ +#define GPIO_OCTL_OCTL6 BIT(6) /*!< pin 6 output bit */ +#define GPIO_OCTL_OCTL7 BIT(7) /*!< pin 7 output bit */ +#define GPIO_OCTL_OCTL8 BIT(8) /*!< pin 8 output bit */ +#define GPIO_OCTL_OCTL9 BIT(9) /*!< pin 9 output bit */ +#define GPIO_OCTL_OCTL10 BIT(10) /*!< pin 10 output bit */ +#define GPIO_OCTL_OCTL11 BIT(11) /*!< pin 11 output bit */ +#define GPIO_OCTL_OCTL12 BIT(12) /*!< pin 12 output bit */ +#define GPIO_OCTL_OCTL13 BIT(13) /*!< pin 13 output bit */ +#define GPIO_OCTL_OCTL14 BIT(14) /*!< pin 14 output bit */ +#define GPIO_OCTL_OCTL15 BIT(15) /*!< pin 15 output bit */ /* GPIO_BOP */ -#define GPIO_BOP_BOP0 BIT(0) /*!< pin 0 set bit */ -#define GPIO_BOP_BOP1 BIT(1) /*!< pin 1 set bit */ -#define GPIO_BOP_BOP2 BIT(2) /*!< pin 2 set bit */ -#define GPIO_BOP_BOP3 BIT(3) /*!< pin 3 set bit */ -#define GPIO_BOP_BOP4 BIT(4) /*!< pin 4 set bit */ -#define GPIO_BOP_BOP5 BIT(5) /*!< pin 5 set bit */ -#define GPIO_BOP_BOP6 BIT(6) /*!< pin 6 set bit */ -#define GPIO_BOP_BOP7 BIT(7) /*!< pin 7 set bit */ -#define GPIO_BOP_BOP8 BIT(8) /*!< pin 8 set bit */ -#define GPIO_BOP_BOP9 BIT(9) /*!< pin 9 set bit */ -#define GPIO_BOP_BOP10 BIT(10) /*!< pin 10 set bit */ -#define GPIO_BOP_BOP11 BIT(11) /*!< pin 11 set bit */ -#define GPIO_BOP_BOP12 BIT(12) /*!< pin 12 set bit */ -#define GPIO_BOP_BOP13 BIT(13) /*!< pin 13 set bit */ -#define GPIO_BOP_BOP14 BIT(14) /*!< pin 14 set bit */ -#define GPIO_BOP_BOP15 BIT(15) /*!< pin 15 set bit */ -#define GPIO_BOP_CR0 BIT(16) /*!< pin 0 clear bit */ -#define GPIO_BOP_CR1 BIT(17) /*!< pin 1 clear bit */ -#define GPIO_BOP_CR2 BIT(18) /*!< pin 2 clear bit */ -#define GPIO_BOP_CR3 BIT(19) /*!< pin 3 clear bit */ -#define GPIO_BOP_CR4 BIT(20) /*!< pin 4 clear bit */ -#define GPIO_BOP_CR5 BIT(21) /*!< pin 5 clear bit */ -#define GPIO_BOP_CR6 BIT(22) /*!< pin 6 clear bit */ -#define GPIO_BOP_CR7 BIT(23) /*!< pin 7 clear bit */ -#define GPIO_BOP_CR8 BIT(24) /*!< pin 8 clear bit */ -#define GPIO_BOP_CR9 BIT(25) /*!< pin 9 clear bit */ -#define GPIO_BOP_CR10 BIT(26) /*!< pin 10 clear bit */ -#define GPIO_BOP_CR11 BIT(27) /*!< pin 11 clear bit */ -#define GPIO_BOP_CR12 BIT(28) /*!< pin 12 clear bit */ -#define GPIO_BOP_CR13 BIT(29) /*!< pin 13 clear bit */ -#define GPIO_BOP_CR14 BIT(30) /*!< pin 14 clear bit */ -#define GPIO_BOP_CR15 BIT(31) /*!< pin 15 clear bit */ +#define GPIO_BOP_BOP0 BIT(0) /*!< pin 0 set bit */ +#define GPIO_BOP_BOP1 BIT(1) /*!< pin 1 set bit */ +#define GPIO_BOP_BOP2 BIT(2) /*!< pin 2 set bit */ +#define GPIO_BOP_BOP3 BIT(3) /*!< pin 3 set bit */ +#define GPIO_BOP_BOP4 BIT(4) /*!< pin 4 set bit */ +#define GPIO_BOP_BOP5 BIT(5) /*!< pin 5 set bit */ +#define GPIO_BOP_BOP6 BIT(6) /*!< pin 6 set bit */ +#define GPIO_BOP_BOP7 BIT(7) /*!< pin 7 set bit */ +#define GPIO_BOP_BOP8 BIT(8) /*!< pin 8 set bit */ +#define GPIO_BOP_BOP9 BIT(9) /*!< pin 9 set bit */ +#define GPIO_BOP_BOP10 BIT(10) /*!< pin 10 set bit */ +#define GPIO_BOP_BOP11 BIT(11) /*!< pin 11 set bit */ +#define GPIO_BOP_BOP12 BIT(12) /*!< pin 12 set bit */ +#define GPIO_BOP_BOP13 BIT(13) /*!< pin 13 set bit */ +#define GPIO_BOP_BOP14 BIT(14) /*!< pin 14 set bit */ +#define GPIO_BOP_BOP15 BIT(15) /*!< pin 15 set bit */ +#define GPIO_BOP_CR0 BIT(16) /*!< pin 0 clear bit */ +#define GPIO_BOP_CR1 BIT(17) /*!< pin 1 clear bit */ +#define GPIO_BOP_CR2 BIT(18) /*!< pin 2 clear bit */ +#define GPIO_BOP_CR3 BIT(19) /*!< pin 3 clear bit */ +#define GPIO_BOP_CR4 BIT(20) /*!< pin 4 clear bit */ +#define GPIO_BOP_CR5 BIT(21) /*!< pin 5 clear bit */ +#define GPIO_BOP_CR6 BIT(22) /*!< pin 6 clear bit */ +#define GPIO_BOP_CR7 BIT(23) /*!< pin 7 clear bit */ +#define GPIO_BOP_CR8 BIT(24) /*!< pin 8 clear bit */ +#define GPIO_BOP_CR9 BIT(25) /*!< pin 9 clear bit */ +#define GPIO_BOP_CR10 BIT(26) /*!< pin 10 clear bit */ +#define GPIO_BOP_CR11 BIT(27) /*!< pin 11 clear bit */ +#define GPIO_BOP_CR12 BIT(28) /*!< pin 12 clear bit */ +#define GPIO_BOP_CR13 BIT(29) /*!< pin 13 clear bit */ +#define GPIO_BOP_CR14 BIT(30) /*!< pin 14 clear bit */ +#define GPIO_BOP_CR15 BIT(31) /*!< pin 15 clear bit */ /* GPIO_LOCK */ -#define GPIO_LOCK_LK0 BIT(0) /*!< pin 0 lock bit */ -#define GPIO_LOCK_LK1 BIT(1) /*!< pin 1 lock bit */ -#define GPIO_LOCK_LK2 BIT(2) /*!< pin 2 lock bit */ -#define GPIO_LOCK_LK3 BIT(3) /*!< pin 3 lock bit */ -#define GPIO_LOCK_LK4 BIT(4) /*!< pin 4 lock bit */ -#define GPIO_LOCK_LK5 BIT(5) /*!< pin 5 lock bit */ -#define GPIO_LOCK_LK6 BIT(6) /*!< pin 6 lock bit */ -#define GPIO_LOCK_LK7 BIT(7) /*!< pin 7 lock bit */ -#define GPIO_LOCK_LK8 BIT(8) /*!< pin 8 lock bit */ -#define GPIO_LOCK_LK9 BIT(9) /*!< pin 9 lock bit */ -#define GPIO_LOCK_LK10 BIT(10) /*!< pin 10 lock bit */ -#define GPIO_LOCK_LK11 BIT(11) /*!< pin 11 lock bit */ -#define GPIO_LOCK_LK12 BIT(12) /*!< pin 12 lock bit */ -#define GPIO_LOCK_LK13 BIT(13) /*!< pin 13 lock bit */ -#define GPIO_LOCK_LK14 BIT(14) /*!< pin 14 lock bit */ -#define GPIO_LOCK_LK15 BIT(15) /*!< pin 15 lock bit */ -#define GPIO_LOCK_LKK BIT(16) /*!< pin sequence lock key */ +#define GPIO_LOCK_LK0 BIT(0) /*!< pin 0 lock bit */ +#define GPIO_LOCK_LK1 BIT(1) /*!< pin 1 lock bit */ +#define GPIO_LOCK_LK2 BIT(2) /*!< pin 2 lock bit */ +#define GPIO_LOCK_LK3 BIT(3) /*!< pin 3 lock bit */ +#define GPIO_LOCK_LK4 BIT(4) /*!< pin 4 lock bit */ +#define GPIO_LOCK_LK5 BIT(5) /*!< pin 5 lock bit */ +#define GPIO_LOCK_LK6 BIT(6) /*!< pin 6 lock bit */ +#define GPIO_LOCK_LK7 BIT(7) /*!< pin 7 lock bit */ +#define GPIO_LOCK_LK8 BIT(8) /*!< pin 8 lock bit */ +#define GPIO_LOCK_LK9 BIT(9) /*!< pin 9 lock bit */ +#define GPIO_LOCK_LK10 BIT(10) /*!< pin 10 lock bit */ +#define GPIO_LOCK_LK11 BIT(11) /*!< pin 11 lock bit */ +#define GPIO_LOCK_LK12 BIT(12) /*!< pin 12 lock bit */ +#define GPIO_LOCK_LK13 BIT(13) /*!< pin 13 lock bit */ +#define GPIO_LOCK_LK14 BIT(14) /*!< pin 14 lock bit */ +#define GPIO_LOCK_LK15 BIT(15) /*!< pin 15 lock bit */ +#define GPIO_LOCK_LKK BIT(16) /*!< pin sequence lock key */ /* GPIO_AFSEL0 */ -#define GPIO_AFSEL0_SEL0 BITS(0,3) /*!< pin 0 alternate function selected */ -#define GPIO_AFSEL0_SEL1 BITS(4,7) /*!< pin 1 alternate function selected */ -#define GPIO_AFSEL0_SEL2 BITS(8,11) /*!< pin 2 alternate function selected */ -#define GPIO_AFSEL0_SEL3 BITS(12,15) /*!< pin 3 alternate function selected */ -#define GPIO_AFSEL0_SEL4 BITS(16,19) /*!< pin 4 alternate function selected */ -#define GPIO_AFSEL0_SEL5 BITS(20,23) /*!< pin 5 alternate function selected */ -#define GPIO_AFSEL0_SEL6 BITS(24,27) /*!< pin 6 alternate function selected */ -#define GPIO_AFSEL0_SEL7 BITS(28,31) /*!< pin 7 alternate function selected */ +#define GPIO_AFSEL0_SEL0 BITS(0,3) /*!< pin 0 alternate function selected */ +#define GPIO_AFSEL0_SEL1 BITS(4,7) /*!< pin 1 alternate function selected */ +#define GPIO_AFSEL0_SEL2 BITS(8,11) /*!< pin 2 alternate function selected */ +#define GPIO_AFSEL0_SEL3 BITS(12,15) /*!< pin 3 alternate function selected */ +#define GPIO_AFSEL0_SEL4 BITS(16,19) /*!< pin 4 alternate function selected */ +#define GPIO_AFSEL0_SEL5 BITS(20,23) /*!< pin 5 alternate function selected */ +#define GPIO_AFSEL0_SEL6 BITS(24,27) /*!< pin 6 alternate function selected */ +#define GPIO_AFSEL0_SEL7 BITS(28,31) /*!< pin 7 alternate function selected */ /* GPIO_AFSEL1 */ -#define GPIO_AFSEL1_SEL8 BITS(0,3) /*!< pin 8 alternate function selected */ -#define GPIO_AFSEL1_SEL9 BITS(4,7) /*!< pin 9 alternate function selected */ -#define GPIO_AFSEL1_SEL10 BITS(8,11) /*!< pin 10 alternate function selected */ -#define GPIO_AFSEL1_SEL11 BITS(12,15) /*!< pin 11 alternate function selected */ -#define GPIO_AFSEL1_SEL12 BITS(16,19) /*!< pin 12 alternate function selected */ -#define GPIO_AFSEL1_SEL13 BITS(20,23) /*!< pin 13 alternate function selected */ -#define GPIO_AFSEL1_SEL14 BITS(24,27) /*!< pin 14 alternate function selected */ -#define GPIO_AFSEL1_SEL15 BITS(28,31) /*!< pin 15 alternate function selected */ +#define GPIO_AFSEL1_SEL8 BITS(0,3) /*!< pin 8 alternate function selected */ +#define GPIO_AFSEL1_SEL9 BITS(4,7) /*!< pin 9 alternate function selected */ +#define GPIO_AFSEL1_SEL10 BITS(8,11) /*!< pin 10 alternate function selected */ +#define GPIO_AFSEL1_SEL11 BITS(12,15) /*!< pin 11 alternate function selected */ +#define GPIO_AFSEL1_SEL12 BITS(16,19) /*!< pin 12 alternate function selected */ +#define GPIO_AFSEL1_SEL13 BITS(20,23) /*!< pin 13 alternate function selected */ +#define GPIO_AFSEL1_SEL14 BITS(24,27) /*!< pin 14 alternate function selected */ +#define GPIO_AFSEL1_SEL15 BITS(28,31) /*!< pin 15 alternate function selected */ /* GPIO_BC */ -#define GPIO_BC_CR0 BIT(0) /*!< pin 0 clear bit */ -#define GPIO_BC_CR1 BIT(1) /*!< pin 1 clear bit */ -#define GPIO_BC_CR2 BIT(2) /*!< pin 2 clear bit */ -#define GPIO_BC_CR3 BIT(3) /*!< pin 3 clear bit */ -#define GPIO_BC_CR4 BIT(4) /*!< pin 4 clear bit */ -#define GPIO_BC_CR5 BIT(5) /*!< pin 5 clear bit */ -#define GPIO_BC_CR6 BIT(6) /*!< pin 6 clear bit */ -#define GPIO_BC_CR7 BIT(7) /*!< pin 7 clear bit */ -#define GPIO_BC_CR8 BIT(8) /*!< pin 8 clear bit */ -#define GPIO_BC_CR9 BIT(9) /*!< pin 9 clear bit */ -#define GPIO_BC_CR10 BIT(10) /*!< pin 10 clear bit */ -#define GPIO_BC_CR11 BIT(11) /*!< pin 11 clear bit */ -#define GPIO_BC_CR12 BIT(12) /*!< pin 12 clear bit */ -#define GPIO_BC_CR13 BIT(13) /*!< pin 13 clear bit */ -#define GPIO_BC_CR14 BIT(14) /*!< pin 14 clear bit */ -#define GPIO_BC_CR15 BIT(15) /*!< pin 15 clear bit */ +#define GPIO_BC_CR0 BIT(0) /*!< pin 0 clear bit */ +#define GPIO_BC_CR1 BIT(1) /*!< pin 1 clear bit */ +#define GPIO_BC_CR2 BIT(2) /*!< pin 2 clear bit */ +#define GPIO_BC_CR3 BIT(3) /*!< pin 3 clear bit */ +#define GPIO_BC_CR4 BIT(4) /*!< pin 4 clear bit */ +#define GPIO_BC_CR5 BIT(5) /*!< pin 5 clear bit */ +#define GPIO_BC_CR6 BIT(6) /*!< pin 6 clear bit */ +#define GPIO_BC_CR7 BIT(7) /*!< pin 7 clear bit */ +#define GPIO_BC_CR8 BIT(8) /*!< pin 8 clear bit */ +#define GPIO_BC_CR9 BIT(9) /*!< pin 9 clear bit */ +#define GPIO_BC_CR10 BIT(10) /*!< pin 10 clear bit */ +#define GPIO_BC_CR11 BIT(11) /*!< pin 11 clear bit */ +#define GPIO_BC_CR12 BIT(12) /*!< pin 12 clear bit */ +#define GPIO_BC_CR13 BIT(13) /*!< pin 13 clear bit */ +#define GPIO_BC_CR14 BIT(14) /*!< pin 14 clear bit */ +#define GPIO_BC_CR15 BIT(15) /*!< pin 15 clear bit */ /* GPIO_TG */ -#define GPIO_TG_TG0 BIT(0) /*!< pin 0 toggle bit */ -#define GPIO_TG_TG1 BIT(1) /*!< pin 1 toggle bit */ -#define GPIO_TG_TG2 BIT(2) /*!< pin 2 toggle bit */ -#define GPIO_TG_TG3 BIT(3) /*!< pin 3 toggle bit */ -#define GPIO_TG_TG4 BIT(4) /*!< pin 4 toggle bit */ -#define GPIO_TG_TG5 BIT(5) /*!< pin 5 toggle bit */ -#define GPIO_TG_TG6 BIT(6) /*!< pin 6 toggle bit */ -#define GPIO_TG_TG7 BIT(7) /*!< pin 7 toggle bit */ -#define GPIO_TG_TG8 BIT(8) /*!< pin 8 toggle bit */ -#define GPIO_TG_TG9 BIT(9) /*!< pin 9 toggle bit */ -#define GPIO_TG_TG10 BIT(10) /*!< pin 10 toggle bit */ -#define GPIO_TG_TG11 BIT(11) /*!< pin 11 toggle bit */ -#define GPIO_TG_TG12 BIT(12) /*!< pin 12 toggle bit */ -#define GPIO_TG_TG13 BIT(13) /*!< pin 13 toggle bit */ -#define GPIO_TG_TG14 BIT(14) /*!< pin 14 toggle bit */ -#define GPIO_TG_TG15 BIT(15) /*!< pin 15 toggle bit */ +#define GPIO_TG_TG0 BIT(0) /*!< pin 0 toggle bit */ +#define GPIO_TG_TG1 BIT(1) /*!< pin 1 toggle bit */ +#define GPIO_TG_TG2 BIT(2) /*!< pin 2 toggle bit */ +#define GPIO_TG_TG3 BIT(3) /*!< pin 3 toggle bit */ +#define GPIO_TG_TG4 BIT(4) /*!< pin 4 toggle bit */ +#define GPIO_TG_TG5 BIT(5) /*!< pin 5 toggle bit */ +#define GPIO_TG_TG6 BIT(6) /*!< pin 6 toggle bit */ +#define GPIO_TG_TG7 BIT(7) /*!< pin 7 toggle bit */ +#define GPIO_TG_TG8 BIT(8) /*!< pin 8 toggle bit */ +#define GPIO_TG_TG9 BIT(9) /*!< pin 9 toggle bit */ +#define GPIO_TG_TG10 BIT(10) /*!< pin 10 toggle bit */ +#define GPIO_TG_TG11 BIT(11) /*!< pin 11 toggle bit */ +#define GPIO_TG_TG12 BIT(12) /*!< pin 12 toggle bit */ +#define GPIO_TG_TG13 BIT(13) /*!< pin 13 toggle bit */ +#define GPIO_TG_TG14 BIT(14) /*!< pin 14 toggle bit */ +#define GPIO_TG_TG15 BIT(15) /*!< pin 15 toggle bit */ /* constants definitions */ typedef FlagStatus bit_status; /* output mode definitions */ #define CTL_CLTR(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) -#define GPIO_MODE_INPUT CTL_CLTR(0) /*!< input mode */ -#define GPIO_MODE_OUTPUT CTL_CLTR(1) /*!< output mode */ -#define GPIO_MODE_AF CTL_CLTR(2) /*!< alternate function mode */ -#define GPIO_MODE_ANALOG CTL_CLTR(3) /*!< analog mode */ +#define GPIO_MODE_INPUT CTL_CLTR(0) /*!< input mode */ +#define GPIO_MODE_OUTPUT CTL_CLTR(1) /*!< output mode */ +#define GPIO_MODE_AF CTL_CLTR(2) /*!< alternate function mode */ +#define GPIO_MODE_ANALOG CTL_CLTR(3) /*!< analog mode */ -/* pull up pull down definitions */ +/* pull-up/ pull-down definitions */ #define PUD_PUPD(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) -#define GPIO_PUPD_NONE PUD_PUPD(0) /*!< without weak pull-up and pull-down resistors */ -#define GPIO_PUPD_PULLUP PUD_PUPD(1) /*!< with weak pull-up resistor */ -#define GPIO_PUPD_PULLDOWN PUD_PUPD(2) /*!< with weak pull-down resistor */ +#define GPIO_PUPD_NONE PUD_PUPD(0) /*!< floating mode, no pull-up and pull-down resistors */ +#define GPIO_PUPD_PULLUP PUD_PUPD(1) /*!< with pull-up resistor */ +#define GPIO_PUPD_PULLDOWN PUD_PUPD(2) /*!< with pull-down resistor */ -/* gpio pin definitions */ -#define GPIO_PIN_0 BIT(0) /*!< GPIO pin 0 */ -#define GPIO_PIN_1 BIT(1) /*!< GPIO pin 1 */ -#define GPIO_PIN_2 BIT(2) /*!< GPIO pin 2 */ -#define GPIO_PIN_3 BIT(3) /*!< GPIO pin 3 */ -#define GPIO_PIN_4 BIT(4) /*!< GPIO pin 4 */ -#define GPIO_PIN_5 BIT(5) /*!< GPIO pin 5 */ -#define GPIO_PIN_6 BIT(6) /*!< GPIO pin 6 */ -#define GPIO_PIN_7 BIT(7) /*!< GPIO pin 7 */ -#define GPIO_PIN_8 BIT(8) /*!< GPIO pin 8 */ -#define GPIO_PIN_9 BIT(9) /*!< GPIO pin 9 */ -#define GPIO_PIN_10 BIT(10) /*!< GPIO pin 10 */ -#define GPIO_PIN_11 BIT(11) /*!< GPIO pin 11 */ -#define GPIO_PIN_12 BIT(12) /*!< GPIO pin 12 */ -#define GPIO_PIN_13 BIT(13) /*!< GPIO pin 13 */ -#define GPIO_PIN_14 BIT(14) /*!< GPIO pin 14 */ -#define GPIO_PIN_15 BIT(15) /*!< GPIO pin 15 */ -#define GPIO_PIN_ALL ((uint32_t)(0xFFFF)) /*!< GPIO pin all */ +/* GPIO pin definitions */ +#define GPIO_PIN_0 BIT(0) /*!< GPIO pin 0 */ +#define GPIO_PIN_1 BIT(1) /*!< GPIO pin 1 */ +#define GPIO_PIN_2 BIT(2) /*!< GPIO pin 2 */ +#define GPIO_PIN_3 BIT(3) /*!< GPIO pin 3 */ +#define GPIO_PIN_4 BIT(4) /*!< GPIO pin 4 */ +#define GPIO_PIN_5 BIT(5) /*!< GPIO pin 5 */ +#define GPIO_PIN_6 BIT(6) /*!< GPIO pin 6 */ +#define GPIO_PIN_7 BIT(7) /*!< GPIO pin 7 */ +#define GPIO_PIN_8 BIT(8) /*!< GPIO pin 8 */ +#define GPIO_PIN_9 BIT(9) /*!< GPIO pin 9 */ +#define GPIO_PIN_10 BIT(10) /*!< GPIO pin 10 */ +#define GPIO_PIN_11 BIT(11) /*!< GPIO pin 11 */ +#define GPIO_PIN_12 BIT(12) /*!< GPIO pin 12 */ +#define GPIO_PIN_13 BIT(13) /*!< GPIO pin 13 */ +#define GPIO_PIN_14 BIT(14) /*!< GPIO pin 14 */ +#define GPIO_PIN_15 BIT(15) /*!< GPIO pin 15 */ +#define GPIO_PIN_ALL BITS(0,15) /*!< GPIO pin all */ -/* gpio ctlr values */ +/* GPIO mode configuration values */ #define GPIO_MODE_SET(n, mode) ((uint32_t)((uint32_t)(mode) << (2U * (n)))) #define GPIO_MODE_MASK(n) (0x3U << (2U * (n))) -/* gpio pull up pull down values */ +/* GPIO pull-up/ pull-down values */ #define GPIO_PUPD_SET(n, pupd) ((uint32_t)((uint32_t)(pupd) << (2U * (n)))) #define GPIO_PUPD_MASK(n) (0x3U << (2U * (n))) -/* gpio output speed values */ +/* GPIO output speed values */ #define GPIO_OSPEED_SET(n, speed) ((uint32_t)((uint32_t)(speed) << (2U * (n)))) #define GPIO_OSPEED_MASK(n) (0x3U << (2U * (n))) -/* gpio output type */ -#define GPIO_OTYPE_PP ((uint8_t)(0x00)) /*!< push pull mode */ -#define GPIO_OTYPE_OD ((uint8_t)(0x01)) /*!< open drain mode */ +/* GPIO output type */ +#define GPIO_OTYPE_PP ((uint8_t)(0x00U)) /*!< push pull mode */ +#define GPIO_OTYPE_OD ((uint8_t)(0x01U)) /*!< open drain mode */ -/* gpio output max speed level */ +/* GPIO output max speed level */ #define OSPD_OSPD(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) -#define GPIO_OSPEED_LEVEL0 OSPD_OSPD(0) /*!< output max speed level 0 */ -#define GPIO_OSPEED_LEVEL1 OSPD_OSPD(1) /*!< output max speed level 1 */ -#define GPIO_OSPEED_LEVEL2 OSPD_OSPD(2) /*!< output max speed level 2 */ -#define GPIO_OSPEED_LEVEL3 OSPD_OSPD(3) /*!< output max speed level 3 */ +#define GPIO_OSPEED_LEVEL0 OSPD_OSPD(0) /*!< output max speed level 0 */ +#define GPIO_OSPEED_LEVEL1 OSPD_OSPD(1) /*!< output max speed level 1 */ +#define GPIO_OSPEED_LEVEL2 OSPD_OSPD(2) /*!< output max speed level 2 */ +#define GPIO_OSPEED_LEVEL3 OSPD_OSPD(3) /*!< output max speed level 3 */ -/* gpio output max speed value */ -#define GPIO_OSPEED_2MHZ GPIO_OSPEED_LEVEL0 /*!< output max speed 2M */ -#define GPIO_OSPEED_25MHZ GPIO_OSPEED_LEVEL1 /*!< output max speed 25M */ -#define GPIO_OSPEED_50MHZ GPIO_OSPEED_LEVEL2 /*!< output max speed 50M */ -#define GPIO_OSPEED_200MHZ GPIO_OSPEED_LEVEL3 /*!< output max speed 200M */ +/* GPIO output max speed value */ +#define GPIO_OSPEED_2MHZ GPIO_OSPEED_LEVEL0 /*!< output max speed 2MHz */ +#define GPIO_OSPEED_25MHZ GPIO_OSPEED_LEVEL1 /*!< output max speed 25MHz */ +#define GPIO_OSPEED_50MHZ GPIO_OSPEED_LEVEL2 /*!< output max speed 50MHz */ +#define GPIO_OSPEED_200MHZ GPIO_OSPEED_LEVEL3 /*!< output max speed 200MHz */ -/* gpio alternate function values */ +/* GPIO alternate function values */ #define GPIO_AFR_SET(n, af) ((uint32_t)((uint32_t)(af) << (4U * (n)))) #define GPIO_AFR_MASK(n) (0xFU << (4U * (n))) - -/* gpio alternate function */ -#define AF(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) -#define GPIO_AF_0 AF(0) /*!< alternate function selected 0 */ -#define GPIO_AF_1 AF(1) /*!< alternate function selected 1 */ -#define GPIO_AF_2 AF(2) /*!< alternate function selected 2 */ -#define GPIO_AF_3 AF(3) /*!< alternate function selected 3 */ -#define GPIO_AF_4 AF(4) /*!< alternate function selected 4 */ -#define GPIO_AF_5 AF(5) /*!< alternate function selected 5 */ -#define GPIO_AF_6 AF(6) /*!< alternate function selected 6 */ -#define GPIO_AF_7 AF(7) /*!< alternate function selected 7 */ -#define GPIO_AF_8 AF(8) /*!< alternate function selected 8 */ -#define GPIO_AF_9 AF(9) /*!< alternate function selected 9 */ -#define GPIO_AF_10 AF(10) /*!< alternate function selected 10 */ -#define GPIO_AF_11 AF(11) /*!< alternate function selected 11 */ -#define GPIO_AF_12 AF(12) /*!< alternate function selected 12 */ -#define GPIO_AF_13 AF(13) /*!< alternate function selected 13 */ -#define GPIO_AF_14 AF(14) /*!< alternate function selected 14 */ -#define GPIO_AF_15 AF(15) /*!< alternate function selected 15 */ + +/* GPIO alternate function */ +#define AF(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) +#define GPIO_AF_0 AF(0) /*!< alternate function 0 selected */ +#define GPIO_AF_1 AF(1) /*!< alternate function 1 selected */ +#define GPIO_AF_2 AF(2) /*!< alternate function 2 selected */ +#define GPIO_AF_3 AF(3) /*!< alternate function 3 selected */ +#define GPIO_AF_4 AF(4) /*!< alternate function 4 selected */ +#define GPIO_AF_5 AF(5) /*!< alternate function 5 selected */ +#define GPIO_AF_6 AF(6) /*!< alternate function 6 selected */ +#define GPIO_AF_7 AF(7) /*!< alternate function 7 selected */ +#define GPIO_AF_8 AF(8) /*!< alternate function 8 selected */ +#define GPIO_AF_9 AF(9) /*!< alternate function 9 selected */ +#define GPIO_AF_10 AF(10) /*!< alternate function 10 selected */ +#define GPIO_AF_11 AF(11) /*!< alternate function 11 selected */ +#define GPIO_AF_12 AF(12) /*!< alternate function 12 selected */ +#define GPIO_AF_13 AF(13) /*!< alternate function 13 selected */ +#define GPIO_AF_14 AF(14) /*!< alternate function 14 selected */ +#define GPIO_AF_15 AF(15) /*!< alternate function 15 selected */ /* function declarations */ -/* reset gpio port */ +/* reset GPIO port */ void gpio_deinit(uint32_t gpio_periph); -/* set gpio mode */ -void gpio_mode_set(uint32_t gpio_periph,uint32_t mode,uint32_t pull_up_down,uint32_t pin); -/* set gpio output type and speed */ -void gpio_output_options_set(uint32_t gpio_periph,uint8_t otype,uint32_t speed,uint32_t pin); +/* set GPIO mode */ +void gpio_mode_set(uint32_t gpio_periph, uint32_t mode, uint32_t pull_up_down, uint32_t pin); +/* set GPIO output type and speed */ +void gpio_output_options_set(uint32_t gpio_periph, uint8_t otype, uint32_t speed, uint32_t pin); -/* set gpio pin bit */ -void gpio_bit_set(uint32_t gpio_periph,uint32_t pin); -/* reset gpio pin bit */ -void gpio_bit_reset(uint32_t gpio_periph,uint32_t pin); -/* write data to the specified gpio pin */ -void gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value); -/* write data to the specified gpio port */ -void gpio_port_write(uint32_t gpio_periph,uint16_t data); +/* set GPIO pin bit */ +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin); +/* reset GPIO pin bit */ +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin); +/* write data to the specified GPIO pin */ +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value); +/* write data to the specified GPIO port */ +void gpio_port_write(uint32_t gpio_periph, uint16_t data); -/* get gpio pin input status */ -FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin); -/* get gpio port input status */ +/* get GPIO pin input status */ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port input status */ uint16_t gpio_input_port_get(uint32_t gpio_periph); -/* get gpio pin output status */ -FlagStatus gpio_output_bit_get(uint32_t gpio_periph,uint32_t pin); -/* get gpio port output status */ +/* get GPIO pin output status */ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port output status */ uint16_t gpio_output_port_get(uint32_t gpio_periph); -/* set gpio alternate function */ -void gpio_af_set(uint32_t gpio_periph,uint32_t alt_func_num,uint32_t pin); -/* lock gpio pin bit */ -void gpio_pin_lock(uint32_t gpio_periph,uint32_t pin); +/* set GPIO alternate function */ +void gpio_af_set(uint32_t gpio_periph, uint32_t alt_func_num, uint32_t pin); +/* lock GPIO pin bit */ +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin); -/* toggle gpio pin status */ -void gpio_bit_toggle(uint32_t gpio_periph,uint32_t pin); -/* toggle gpio port status */ +/* toggle GPIO pin status */ +void gpio_bit_toggle(uint32_t gpio_periph, uint32_t pin); +/* toggle GPIO port status */ void gpio_port_toggle(uint32_t gpio_periph); #endif /* GD32F4XX_GPIO_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h index f7e93d3357..121e42f497 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h @@ -1,29 +1,56 @@ /*! - \file gd32f4xx_i2c.h - \brief definitions for the I2C + \file gd32f4xx_i2c.h + \brief definitions for the I2C + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2019-04-16, V2.0.1, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ + #ifndef GD32F4XX_I2C_H #define GD32F4XX_I2C_H #include "gd32f4xx.h" /* I2Cx(x=0,1,2) definitions */ -#define I2C0 I2C_BASE -#define I2C1 (I2C_BASE+0x400U) -#define I2C2 (I2C_BASE+0x800U) +#define I2C0 I2C_BASE /*!< I2C0 base address */ +#define I2C1 (I2C_BASE+0x400U) /*!< I2C1 base address */ +#define I2C2 (I2C_BASE+0x800U) /*!< I2C2 base address */ /* registers definitions */ #define I2C_CTL0(i2cx) REG32((i2cx) + 0x00U) /*!< I2C control register 0 */ #define I2C_CTL1(i2cx) REG32((i2cx) + 0x04U) /*!< I2C control register 1 */ -#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x08U) /*!< I2C slave address register 0*/ -#define I2C_SADDR1(i2cx) REG32((i2cx) + 0x0CU) /*!< I2C slave address register */ +#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x08U) /*!< I2C slave address register 0 */ +#define I2C_SADDR1(i2cx) REG32((i2cx) + 0x0CU) /*!< I2C slave address register 1 */ #define I2C_DATA(i2cx) REG32((i2cx) + 0x10U) /*!< I2C transfer buffer register */ #define I2C_STAT0(i2cx) REG32((i2cx) + 0x14U) /*!< I2C transfer status register 0 */ #define I2C_STAT1(i2cx) REG32((i2cx) + 0x18U) /*!< I2C transfer status register */ @@ -32,7 +59,6 @@ #define I2C_FCTL(i2cx) REG32((i2cx) + 0x24U) /*!< I2C filter control register */ #define I2C_SAMCS(i2cx) REG32((i2cx) + 0x80U) /*!< I2C SAM control and status register */ - /* bits definitions */ /* I2Cx_CTL0 */ #define I2C_CTL0_I2CEN BIT(0) /*!< peripheral enable */ @@ -41,7 +67,7 @@ #define I2C_CTL0_ARPEN BIT(4) /*!< ARP enable */ #define I2C_CTL0_PECEN BIT(5) /*!< PEC enable */ #define I2C_CTL0_GCEN BIT(6) /*!< general call enable */ -#define I2C_CTL0_DISSTRC BIT(7) /*!< clock stretching disable (slave mode) */ +#define I2C_CTL0_SS BIT(7) /*!< clock stretching disable (slave mode) */ #define I2C_CTL0_START BIT(8) /*!< start generation */ #define I2C_CTL0_STOP BIT(9) /*!< stop generation */ #define I2C_CTL0_ACKEN BIT(10) /*!< acknowledge enable */ @@ -52,7 +78,7 @@ /* I2Cx_CTL1 */ #define I2C_CTL1_I2CCLK BITS(0,5) /*!< I2CCLK[5:0] bits (peripheral clock frequency) */ -#define I2C_CTL1_ERRIE BIT(8) /*!< error interrupt inable */ +#define I2C_CTL1_ERRIE BIT(8) /*!< error interrupt enable */ #define I2C_CTL1_EVIE BIT(9) /*!< event interrupt enable */ #define I2C_CTL1_BUFIE BIT(10) /*!< buffer interrupt enable */ #define I2C_CTL1_DMAON BIT(11) /*!< DMA requests enable */ @@ -90,12 +116,12 @@ /* I2Cx_STAT1 */ #define I2C_STAT1_MASTER BIT(0) /*!< master/slave */ #define I2C_STAT1_I2CBSY BIT(1) /*!< bus busy */ -#define I2C_STAT1_TRS BIT(2) /*!< transmitter/receiver */ +#define I2C_STAT1_TR BIT(2) /*!< transmitter/receiver */ #define I2C_STAT1_RXGC BIT(4) /*!< general call address (slave mode) */ #define I2C_STAT1_DEFSMB BIT(5) /*!< SMBus device default address (slave mode) */ #define I2C_STAT1_HSTSMB BIT(6) /*!< SMBus host header (slave mode) */ #define I2C_STAT1_DUMODF BIT(7) /*!< dual flag (slave mode) */ -#define I2C_STAT1_ECV BITS(8,15) /*!< packet error checking register */ +#define I2C_STAT1_PECV BITS(8,15) /*!< packet error checking value */ /* I2Cx_CKCFG */ #define I2C_CKCFG_CLKC BITS(0,11) /*!< clock control register in fast/standard mode (master mode) */ @@ -123,7 +149,6 @@ #define I2C_SAMCS_RFF BIT(14) /*!< rxframe fall flag, cleared by software write 0 */ #define I2C_SAMCS_RFR BIT(15) /*!< rxframe rise flag, cleared by software write 0 */ - /* constants definitions */ /* the digital noise filter can filter spikes's length */ @@ -146,6 +171,94 @@ typedef enum { I2C_DF_15PCLKS /*!< enable digital noise filter and the maximum filtered spiker's length 15 PCLK1 */ }i2c_digital_filter_enum; +/* constants definitions */ +/* define the I2C bit position and its register index offset */ +#define I2C_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define I2C_REG_VAL(i2cx, offset) (REG32((i2cx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) +#define I2C_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define I2C_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define I2C_REG_VAL2(i2cx, offset) (REG32((i2cx) + ((uint32_t)(offset) >> 22))) +#define I2C_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) + +/* register offset */ +#define I2C_CTL1_REG_OFFSET 0x04U /*!< CTL1 register offset */ +#define I2C_STAT0_REG_OFFSET 0x14U /*!< STAT0 register offset */ +#define I2C_STAT1_REG_OFFSET 0x18U /*!< STAT1 register offset */ +#define I2C_SAMCS_REG_OFFSET 0x80U /*!< SAMCS register offset */ + +/* I2C flags */ +typedef enum +{ + /* flags in STAT0 register */ + I2C_FLAG_SBSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode */ + I2C_FLAG_ADDSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode */ + I2C_FLAG_BTC = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_FLAG_ADD10SEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode */ + I2C_FLAG_STPDET = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode */ + I2C_FLAG_RBNE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving */ + I2C_FLAG_TBE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting */ + I2C_FLAG_BERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */ + I2C_FLAG_LOSTARB = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode */ + I2C_FLAG_AERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error */ + I2C_FLAG_OUERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode */ + I2C_FLAG_PECERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data */ + I2C_FLAG_SMBTO = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode */ + I2C_FLAG_SMBALT = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus alert status */ + /* flags in STAT1 register */ + I2C_FLAG_MASTER = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 0U), /*!< a flag indicating whether I2C block is in master or slave mode */ + I2C_FLAG_I2CBSY = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 1U), /*!< busy flag */ + I2C_FLAG_TRS = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 2U), /*!< whether the I2C is a transmitter or a receiver */ + I2C_FLAG_RXGC = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 4U), /*!< general call address (00h) received */ + I2C_FLAG_DEFSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 5U), /*!< default address of SMBus device */ + I2C_FLAG_HSTSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 6U), /*!< SMBus host header detected in slave mode */ + I2C_FLAG_DUMOD = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 7U), /*!< dual flag in slave mode indicating which address is matched in dual-address mode */ + /* flags in SAMCS register */ + I2C_FLAG_TFF = I2C_REGIDX_BIT(I2C_SAMCS_REG_OFFSET, 12U), /*!< txframe fall flag */ + I2C_FLAG_TFR = I2C_REGIDX_BIT(I2C_SAMCS_REG_OFFSET, 13U), /*!< txframe rise flag */ + I2C_FLAG_RFF = I2C_REGIDX_BIT(I2C_SAMCS_REG_OFFSET, 14U), /*!< rxframe fall flag */ + I2C_FLAG_RFR = I2C_REGIDX_BIT(I2C_SAMCS_REG_OFFSET, 15U) /*!< rxframe rise flag */ +}i2c_flag_enum; + +/* I2C interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL1 register */ + I2C_INT_FLAG_SBSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode interrupt flag */ + I2C_INT_FLAG_ADDSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode interrupt flag */ + I2C_INT_FLAG_BTC = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_INT_FLAG_ADD10SEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode interrupt flag */ + I2C_INT_FLAG_STPDET = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode interrupt flag */ + I2C_INT_FLAG_RBNE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving interrupt flag */ + I2C_INT_FLAG_TBE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting interrupt flag */ + I2C_INT_FLAG_BERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag */ + I2C_INT_FLAG_LOSTARB = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode interrupt flag */ + I2C_INT_FLAG_AERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error interrupt flag */ + I2C_INT_FLAG_OUERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode interrupt flag */ + I2C_INT_FLAG_PECERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data interrupt flag */ + I2C_INT_FLAG_SMBTO = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode interrupt flag */ + I2C_INT_FLAG_SMBALT = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus Alert status interrupt flag */ + /* interrupt flags in SAMCS register */ + I2C_INT_FLAG_TFF = I2C_REGIDX_BIT2(I2C_SAMCS_REG_OFFSET, 4U, I2C_SAMCS_REG_OFFSET, 12U), /*!< txframe fall interrupt flag */ + I2C_INT_FLAG_TFR = I2C_REGIDX_BIT2(I2C_SAMCS_REG_OFFSET, 5U, I2C_SAMCS_REG_OFFSET, 13U), /*!< txframe rise interrupt flag */ + I2C_INT_FLAG_RFF = I2C_REGIDX_BIT2(I2C_SAMCS_REG_OFFSET, 6U, I2C_SAMCS_REG_OFFSET, 14U), /*!< rxframe fall interrupt flag */ + I2C_INT_FLAG_RFR = I2C_REGIDX_BIT2(I2C_SAMCS_REG_OFFSET, 7U, I2C_SAMCS_REG_OFFSET, 15U) /*!< rxframe rise interrupt flag */ +}i2c_interrupt_flag_enum; + +/* I2C interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL1 register */ + I2C_INT_ERR = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 8U), /*!< error interrupt enable */ + I2C_INT_EV = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 9U), /*!< event interrupt enable */ + I2C_INT_BUF = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 10U), /*!< buffer interrupt enable */ + /* interrupt in SAMCS register */ + I2C_INT_TFF = I2C_REGIDX_BIT(I2C_SAMCS_REG_OFFSET, 4U), /*!< txframe fall interrupt enable */ + I2C_INT_TFR = I2C_REGIDX_BIT(I2C_SAMCS_REG_OFFSET, 5U), /*!< txframe rise interrupt enable */ + I2C_INT_RFF = I2C_REGIDX_BIT(I2C_SAMCS_REG_OFFSET, 6U), /*!< rxframe fall interrupt enable */ + I2C_INT_RFR = I2C_REGIDX_BIT(I2C_SAMCS_REG_OFFSET, 7U) /*!< rxframe rise interrupt enable */ +}i2c_interrupt_enum; + /* SMBus/I2C mode switch and SMBus type selection */ #define I2C_I2CMODE_ENABLE ((uint32_t)0x00000000U) /*!< I2C mode */ #define I2C_SMBUSMODE_ENABLE I2C_CTL0_SMBEN /*!< SMBus mode */ @@ -153,27 +266,28 @@ typedef enum { /* SMBus/I2C mode switch and SMBus type selection */ #define I2C_SMBUS_DEVICE ((uint32_t)0x00000000U) /*!< SMBus mode device type */ #define I2C_SMBUS_HOST I2C_CTL0_SMBSEL /*!< SMBus mode host type */ + /* I2C transfer direction */ -#define I2C_TRANSMITTER (~BIT(0)) /*!< transmitter */ -#define I2C_RECEIVER BIT(0) /*!< receiver */ +#define I2C_RECEIVER ((uint32_t)0x00000001U) /*!< receiver */ +#define I2C_TRANSMITTER ((uint32_t)0xFFFFFFFEU) /*!< transmitter */ /* whether or not to send an ACK */ -#define I2C_ACK_ENABLE ((uint8_t)0x01U) /*!< ACK will be sent */ -#define I2C_ACK_DISABLE ((uint8_t)0x00U) /*!< ACK will be not sent */ +#define I2C_ACK_DISABLE ((uint32_t)0x00000000U) /*!< ACK will be not sent */ +#define I2C_ACK_ENABLE ((uint32_t)0x00000001U) /*!< ACK will be sent */ /* I2C POAP position*/ -#define I2C_ACKPOS_CURRENT ((uint8_t)0x01U) /*!< ACKEN bit decides whether to send ACK or not for the current */ -#define I2C_ACKPOS_NEXT ((uint8_t)0x00U) /*!< ACKEN bit decides whether to send ACK or not for the next byte */ +#define I2C_ACKPOS_NEXT ((uint32_t)0x00000000U) /*!< ACKEN bit decides whether or not to send ACK for the next byte */ +#define I2C_ACKPOS_CURRENT ((uint32_t)0x00000001U) /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */ /* I2C dual-address mode switch */ -#define I2C_DUADEN_DISABLE ((uint8_t)0x00U) /*!< dual-address mode disabled */ -#define I2C_DUADEN_ENABLE ((uint8_t)0x01U) /*!< dual-address mode enabled */ +#define I2C_DUADEN_DISABLE ((uint32_t)0x00000000U) /*!< dual-address mode disabled */ +#define I2C_DUADEN_ENABLE ((uint32_t)0x00000001U) /*!< dual-address mode enabled */ /* whether or not to stretch SCL low */ #define I2C_SCLSTRETCH_ENABLE ((uint32_t)0x00000000U) /*!< SCL stretching is enabled */ -#define I2C_SCLSTRETCH_DISABLE I2C_CTL0_DISSTRC /*!< SCL stretching is disabled */ +#define I2C_SCLSTRETCH_DISABLE I2C_CTL0_SS /*!< SCL stretching is disabled */ -/* whether or not to response to a General Call */ +/* whether or not to response to a general call */ #define I2C_GCEN_ENABLE I2C_CTL0_GCEN /*!< slave will response to a general call */ #define I2C_GCEN_DISABLE ((uint32_t)0x00000000U) /*!< slave will not response to a general call */ @@ -185,11 +299,11 @@ typedef enum { /* DMA mode switch */ #define I2C_DMA_ON I2C_CTL1_DMAON /*!< DMA mode enabled */ #define I2C_DMA_OFF ((uint32_t)0x00000000U) /*!< DMA mode disabled */ + /* flag indicating DMA last transfer */ #define I2C_DMALST_ON I2C_CTL1_DMALST /*!< next DMA EOT is the last transfer */ #define I2C_DMALST_OFF ((uint32_t)0x00000000U) /*!< next DMA EOT is not the last transfer */ - /* I2C PEC configure */ /* PEC enable */ #define I2C_PEC_ENABLE I2C_CTL0_PECEN /*!< PEC calculation on */ @@ -203,105 +317,78 @@ typedef enum { /* issue or not alert through SMBA pin */ #define I2C_SALTSEND_ENABLE I2C_CTL0_SALT /*!< issue alert through SMBA pin */ #define I2C_SALTSEND_DISABLE ((uint32_t)0x00000000U) /*!< not issue alert through SMBA */ + /* ARP protocol in SMBus switch */ #define I2C_ARP_ENABLE I2C_CTL0_ARPEN /*!< ARP is enabled */ #define I2C_ARP_DISABLE ((uint32_t)0x00000000U) /*!< ARP is disabled */ -/* I2C state */ -/* I2C bit state */ -#define I2C_SBSEND BIT(0) /*!< start condition sent out in master mode */ -#define I2C_ADDSEND BIT(1) /*!< address is sent in master mode or received and matches in slave mode */ -#define I2C_BTC BIT(2) /*!< byte transmission finishes */ -#define I2C_ADD10SEND BIT(3) /*!< header of 10-bit address is sent in master mode */ -#define I2C_STPDET BIT(4) /*!< etop condition detected in slave mode */ -#define I2C_RBNE BIT(6) /*!< I2C_DATA is not Empty during receiving */ -#define I2C_TBE BIT(7) /*!< I2C_DATA is empty during transmitting */ -#define I2C_BERR BIT(8) /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */ -#define I2C_LOSTARB BIT(9) /*!< arbitration lost in master mode */ -#define I2C_AERR BIT(10) /*!< acknowledge error */ -#define I2C_OUERR BIT(11) /*!< over-run or under-run situation occurs in slave mode */ -#define I2C_PECERR BIT(12) /*!< PEC error when receiving data */ -#define I2C_SMBTO BIT(14) /*!< timeout signal in SMBus mode */ -#define I2C_SMBALT BIT(15) /*!< SMBus alert status */ -#define I2C_MASTER (BIT(0)|BIT(31)) /*!< a flag indicating whether I2C block is in master or slave mode */ -#define I2C_I2CBSY (BIT(1)|BIT(31)) /*!< busy flag */ -#define I2C_TRS (BIT(2)|BIT(31)) /*!< whether the I2C is a transmitter or a receiver */ -#define I2C_RXGC (BIT(4)|BIT(31)) /*!< general call address (00h) received */ -#define I2C_DEFSMB (BIT(5)|BIT(31)) /*!< default address of SMBus device */ -#define I2C_HSTSMB (BIT(6)|BIT(31)) /*!< SMBus host header detected in slave mode */ -#define I2C_DUMODF (BIT(7)|BIT(31)) /*!< dual flag in slave mode indicating which address is matched in dual-address mode */ +/* transmit I2C data */ +#define DATA_TRANS(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* receive I2C data */ +#define DATA_RECV(regval) GET_BITS((uint32_t)(regval), 0, 7) /* I2C duty cycle in fast mode */ -#define CKCFG_DTCY(regval) (BIT(14) & ((uint32_t)(regval) << 14)) -#define I2C_DTCY_2 CKCFG_DTCY(0) /*!< I2C fast mode Tlow/Thigh = 2 */ -#define I2C_DTCY_16_9 CKCFG_DTCY(1) /*!< I2C fast mode Tlow/Thigh = 16/9 */ +#define I2C_DTCY_2 ((uint32_t)0x00000000U) /*!< I2C fast mode Tlow/Thigh = 2 */ +#define I2C_DTCY_16_9 I2C_CKCFG_DTCY /*!< I2C fast mode Tlow/Thigh = 16/9 */ /* address mode for the I2C slave */ -#define SADDR0_ADDFORMAT(regval) (BIT(15) & ((regval) << 15)) -#define I2C_ADDFORMAT_7BITS SADDR0_ADDFORMAT(0) /*!< address:7 bits */ -#define I2C_ADDFORMAT_10BITS SADDR0_ADDFORMAT(1) /*!< address:10 bits */ +#define I2C_ADDFORMAT_7BITS ((uint32_t)0x00000000U) /*!< address:7 bits */ +#define I2C_ADDFORMAT_10BITS I2C_SADDR0_ADDFORMAT /*!< address:10 bits */ /* function declarations */ /* reset I2C */ void i2c_deinit(uint32_t i2c_periph); -/* I2C clock configure */ -void i2c_clock_config(uint32_t i2c_periph,uint32_t clkspeed,uint32_t dutycyc); -/* I2C address configure */ -void i2c_mode_addr_config(uint32_t i2c_periph,uint32_t i2cmod,uint32_t addformat,uint32_t addr); +/* configure I2C clock */ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc); +/* configure I2C address */ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr); /* SMBus type selection */ -void i2c_smbus_type_config(uint32_t i2c_periph,uint32_t type); +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type); /* whether or not to send an ACK */ -void i2c_ack_config(uint32_t i2c_periph,uint8_t ack); -/* I2C POAP position configure */ -void i2c_ackpos_config(uint32_t i2c_periph,uint8_t pos); -/* master send slave address */ -void i2c_master_addressing(uint32_t i2c_periph,uint8_t addr,uint32_t trandirection); -/* dual-address mode switch */ -void i2c_dualaddr_enable(uint32_t i2c_periph, uint8_t dualaddr); - -/* enable i2c */ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack); +/* configure I2C POAP position */ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos); +/* master sends slave address */ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection); +/* enable dual-address mode */ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr); +/* disable dual-address mode */ +void i2c_dualaddr_disable(uint32_t i2c_periph); +/* enable I2C */ void i2c_enable(uint32_t i2c_periph); -/* disable i2c */ +/* disable I2C */ void i2c_disable(uint32_t i2c_periph); + /* generate a START condition on I2C bus */ void i2c_start_on_bus(uint32_t i2c_periph); /* generate a STOP condition on I2C bus */ void i2c_stop_on_bus(uint32_t i2c_periph); -/* i2c transmit data function */ -void i2c_transmit_data(uint32_t i2c_periph,uint8_t data); -/* i2c receive data function */ -uint8_t i2c_receive_data(uint32_t i2c_periph); -/* I2C DMA mode enable */ -void i2c_dma_enable(uint32_t i2c_periph,uint32_t dmastste); -/* flag indicating DMA last transfer */ -void i2c_dma_last_transfer_enable(uint32_t i2c_periph,uint32_t dmalast); -/* whether to stretch SCL low when data is not ready in slave mode */ -void i2c_stretch_scl_low_config(uint32_t i2c_periph,uint32_t stretchpara ); -/* whether or not to response to a general call */ -void i2c_slave_response_to_gcall_config(uint32_t i2c_periph,uint32_t gcallpara); -/* software reset I2C */ +/* I2C transmit data function */ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data); +/* I2C receive data function */ +uint8_t i2c_data_receive(uint32_t i2c_periph); +/* enable I2C DMA mode */ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate); +/* configure whether next DMA EOT is DMA last transfer or not */ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast); +/* whether to stretch SCL low when data is not ready in slave mode */ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara); +/* whether or not to response to a general call */ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara); +/* software reset I2C */ void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset); -/* check i2c state */ -FlagStatus i2c_flag_get(uint32_t i2c_periph,uint32_t state); -/* clear i2c state */ -void i2c_flag_clear(uint32_t i2c_periph,uint32_t state); -/* enable i2c interrupt */ -void i2c_interrupt_enable(uint32_t i2c_periph,uint32_t inttype); -/* disable i2c interrupt */ -void i2c_interrupt_disable(uint32_t i2c_periph,uint32_t inttype); - /* I2C PEC calculation on or off */ -void i2c_pec_enable(uint32_t i2c_periph,uint32_t pecstate); +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate); /* I2C whether to transfer PEC value */ -void i2c_pec_transfer_enable(uint32_t i2c_periph,uint32_t pecpara); -/* packet error checking value */ -uint8_t i2c_pec_value(uint32_t i2c_periph); - +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara); +/* packet error checking value */ +uint8_t i2c_pec_value_get(uint32_t i2c_periph); /* I2C issue alert through SMBA pin */ -void i2c_smbus_alert_issue(uint32_t i2c_periph,uint32_t smbuspara); -/* I2C ARP protocol in SMBus switch */ -void i2c_smbus_arp_enable(uint32_t i2c_periph,uint32_t arpstate); +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara); +/* I2C ARP protocol in SMBus switch */ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate); /* I2C analog noise filter disable */ void i2c_analog_noise_filter_disable(uint32_t i2c_periph); @@ -318,14 +405,18 @@ void i2c_sam_disable(uint32_t i2c_periph); void i2c_sam_timeout_enable(uint32_t i2c_periph); /* disable SAM_V interface timeout detect */ void i2c_sam_timeout_disable(uint32_t i2c_periph); -/* enable the specified I2C SAM interrupt */ -void i2c_sam_interrupt_enable(uint32_t i2c_periph,uint32_t inttype); -/* disable the specified I2C SAM interrupt */ -void i2c_sam_interrupt_disable(uint32_t i2c_periph,uint32_t inttype); -/* check i2c SAM state */ -FlagStatus i2c_sam_flag_get(uint32_t i2c_periph,uint32_t samstate); -/* clear i2c SAM state */ -void i2c_sam_flag_clear(uint32_t i2c_periph,uint32_t samstate); +/* check I2C flag is set or not */ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag); +/* clear I2C flag */ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag); +/* enable I2C interrupt */ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* disable I2C interrupt */ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* check I2C interrupt flag */ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); +/* clear I2C interrupt flag */ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); #endif /* GD32F4XX_I2C_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h index d356ac8c3d..d9ae8ce33a 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_ipa.h - \brief definitions for the IPA + \file gd32f4xx_ipa.h + \brief definitions for the IPA + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_IPA_H @@ -24,7 +49,7 @@ #define IPA_INTC REG32(IPA + 0x08U) /*!< IPA interrupt flag clear register */ #define IPA_FMADDR REG32(IPA + 0x0CU) /*!< IPA foreground memory base address register */ #define IPA_FLOFF REG32(IPA + 0x10U) /*!< IPA foreground line offset register */ -#define IPA_BMADDR REG32(IPA + 0x14U) /*!< IPA background memory base address register */ +#define IPA_BMADDR REG32(IPA + 0x14U) /*!< IPA background memory base address register */ #define IPA_BLOFF REG32(IPA + 0x18U) /*!< IPA background line offset register */ #define IPA_FPCTL REG32(IPA + 0x1CU) /*!< IPA foreground pixel control register */ #define IPA_FPV REG32(IPA + 0x20U) /*!< IPA foreground pixel value register */ @@ -33,11 +58,11 @@ #define IPA_FLMADDR REG32(IPA + 0x2CU) /*!< IPA foreground LUT memory base address register */ #define IPA_BLMADDR REG32(IPA + 0x30U) /*!< IPA background LUT memory base address register */ #define IPA_DPCTL REG32(IPA + 0x34U) /*!< IPA destination pixel control register */ -#define IPA_DPV REG32(IPA + 0x38U) /*!< IPA destination pixel value register */ +#define IPA_DPV REG32(IPA + 0x38U) /*!< IPA destination pixel value register */ #define IPA_DMADDR REG32(IPA + 0x3CU) /*!< IPA destination memory base address register */ #define IPA_DLOFF REG32(IPA + 0x40U) /*!< IPA destination line offset register */ #define IPA_IMS REG32(IPA + 0x44U) /*!< IPA image size register */ -#define IPA_LM REG32(IPA + 0x48U) /*!< IPA line mark register */ +#define IPA_LM REG32(IPA + 0x48U) /*!< IPA line mark register */ #define IPA_ITCTL REG32(IPA + 0x4CU) /*!< IPA inter-timer control register */ /* IPA_CTL */ @@ -113,7 +138,7 @@ #define IPA_BLMADDR_BLMADDR BITS(0,31) /*!< background LUT memory base address */ /* IPA_DPCTL */ -#define IPA_DPCTL_DPF BITS(0,2) /*!< destination pixel control register */ +#define IPA_DPCTL_DPF BITS(0,2) /*!< destination pixel control register */ /* IPA_DPV */ /* destination pixel format ARGB8888 */ @@ -165,7 +190,7 @@ /* constants definitions */ /* IPA foreground parameter struct definitions */ typedef struct -{ +{ uint32_t foreground_memaddr; /*!< foreground memory base address */ uint32_t foreground_lineoff; /*!< foreground line offset */ uint32_t foreground_prealpha; /*!< foreground pre-defined alpha value */ @@ -174,25 +199,25 @@ typedef struct uint32_t foreground_prered; /*!< foreground pre-defined red value */ uint32_t foreground_pregreen; /*!< foreground pre-defined green value */ uint32_t foreground_preblue; /*!< foreground pre-defined blue value */ -}ipa_foreground_parameter_struct; +}ipa_foreground_parameter_struct; /* IPA background parameter struct definitions */ typedef struct -{ +{ uint32_t background_memaddr; /*!< background memory base address */ uint32_t background_lineoff; /*!< background line offset */ uint32_t background_prealpha; /*!< background pre-defined alpha value */ - uint32_t background_alpha_algorithm; /*!< background alpha value calculation algorithm */ + uint32_t background_alpha_algorithm; /*!< background alpha value calculation algorithm */ uint32_t background_pf; /*!< background pixel format */ uint32_t background_prered; /*!< background pre-defined red value */ uint32_t background_pregreen; /*!< background pre-defined green value */ uint32_t background_preblue; /*!< background pre-defined blue value */ -}ipa_background_parameter_struct; +}ipa_background_parameter_struct; /* IPA destination parameter struct definitions */ typedef struct { - uint32_t destination_memaddr; /*!< destination memory base address */ + uint32_t destination_memaddr; /*!< destination memory base address */ uint32_t destination_lineoff; /*!< destination line offset */ uint32_t destination_prealpha; /*!< destination pre-defined alpha value */ uint32_t destination_pf; /*!< destination pixel format */ @@ -200,17 +225,17 @@ typedef struct uint32_t destination_pregreen; /*!< destination pre-defined green value */ uint32_t destination_preblue; /*!< destination pre-defined blue value */ uint32_t image_width; /*!< width of the image to be processed */ - uint32_t image_height; /*!< height of the image to be processed */ -}ipa_destination_parameter_struct; + uint32_t image_height; /*!< height of the image to be processed */ +}ipa_destination_parameter_struct; /* destination pixel format */ -typedef enum +typedef enum { - IPA_DPF_ARGB8888, /*!< destination pixel format ARGB8888 */ - IPA_DPF_RGB888, /*!< destination pixel format RGB888 */ - IPA_DPF_RGB565, /*!< destination pixel format RGB565 */ - IPA_DPF_ARGB1555, /*!< destination pixel format ARGB1555 */ - IPA_DPF_ARGB4444 /*!< destination pixel format ARGB4444 */ + IPA_DPF_ARGB8888, /*!< destination pixel format ARGB8888 */ + IPA_DPF_RGB888, /*!< destination pixel format RGB888 */ + IPA_DPF_RGB565, /*!< destination pixel format RGB565 */ + IPA_DPF_ARGB1555, /*!< destination pixel format ARGB1555 */ + IPA_DPF_ARGB4444 /*!< destination pixel format ARGB4444 */ } ipa_dpf_enum; /* LUT pixel format */ @@ -218,30 +243,30 @@ typedef enum #define IPA_LUT_PF_RGB888 ((uint8_t)0x01U) /*!< LUT pixel format RGB888 */ /* Inter-timer */ -#define IPA_INTER_TIMER_DISABLE ((uint8_t)0x00U) /*!< Inter-timer disable */ -#define IPA_INTER_TIMER_ENABLE ((uint8_t)0x01U) /*!< Inter-timer enable */ +#define IPA_INTER_TIMER_DISABLE ((uint8_t)0x00U) /*!< inter-timer disable */ +#define IPA_INTER_TIMER_ENABLE ((uint8_t)0x01U) /*!< inter-timer enable */ /* IPA pixel format convert mode */ -#define CTL_PFCM(regval) (BITS(16,17) & ((regval) << 16)) +#define CTL_PFCM(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) #define IPA_FGTODE CTL_PFCM(0) /*!< foreground memory to destination memory without pixel format convert */ #define IPA_FGTODE_PF_CONVERT CTL_PFCM(1) /*!< foreground memory to destination memory with pixel format convert */ #define IPA_FGBGTODE CTL_PFCM(2) /*!< blending foreground and background memory to destination memory */ #define IPA_FILL_UP_DE CTL_PFCM(3) /*!< fill up destination memory with specific color */ /* foreground alpha value calculation algorithm */ -#define FPCTL_FAVCA(regval) (BITS(16,17) & ((regval) << 16)) +#define FPCTL_FAVCA(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) #define IPA_FG_ALPHA_MODE_0 FPCTL_FAVCA(0) /*!< no effect */ #define IPA_FG_ALPHA_MODE_1 FPCTL_FAVCA(1) /*!< FPDAV[7:0] is selected as the foreground alpha value */ #define IPA_FG_ALPHA_MODE_2 FPCTL_FAVCA(2) /*!< FPDAV[7:0] multiplied by read alpha value */ /* background alpha value calculation algorithm */ -#define BPCTL_BAVCA(regval) (BITS(16,17) & ((regval) << 16)) +#define BPCTL_BAVCA(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) #define IPA_BG_ALPHA_MODE_0 BPCTL_BAVCA(0) /*!< no effect */ #define IPA_BG_ALPHA_MODE_1 BPCTL_BAVCA(1) /*!< BPDAV[7:0] is selected as the background alpha value */ #define IPA_BG_ALPHA_MODE_2 BPCTL_BAVCA(2) /*!< BPDAV[7:0] multiplied by read alpha value */ /* foreground pixel format */ -#define FPCTL_PPF(regval) (BITS(0,3) & ((regval))) +#define FPCTL_PPF(regval) (BITS(0,3) & ((uint32_t)(regval))) #define FOREGROUND_PPF_ARGB8888 FPCTL_PPF(0) /*!< foreground pixel format ARGB8888 */ #define FOREGROUND_PPF_RGB888 FPCTL_PPF(1) /*!< foreground pixel format RGB888 */ #define FOREGROUND_PPF_RGB565 FPCTL_PPF(2) /*!< foreground pixel format RGB565 */ @@ -255,7 +280,7 @@ typedef enum #define FOREGROUND_PPF_A4 FPCTL_PPF(10) /*!< foreground pixel format A4 */ /* background pixel format */ -#define BPCTL_PPF(regval) (BITS(0,3) & ((regval))) +#define BPCTL_PPF(regval) (BITS(0,3) & ((uint32_t)(regval))) #define BACKGROUND_PPF_ARGB8888 BPCTL_PPF(0) /*!< background pixel format ARGB8888 */ #define BACKGROUND_PPF_RGB888 BPCTL_PPF(1) /*!< background pixel format RGB888 */ #define BACKGROUND_PPF_RGB565 BPCTL_PPF(2) /*!< background pixel format RGB565 */ @@ -268,53 +293,92 @@ typedef enum #define BACKGROUND_PPF_A8 BPCTL_PPF(9) /*!< background pixel format A8 */ #define BACKGROUND_PPF_A4 BPCTL_PPF(10) /*!< background pixel format A4 */ +/* IPA flags */ +#define IPA_FLAG_TAE IPA_INTF_TAEIF /*!< transfer access error interrupt flag */ +#define IPA_FLAG_FTF IPA_INTF_FTFIF /*!< full transfer finish interrupt flag */ +#define IPA_FLAG_TLM IPA_INTF_TLMIF /*!< transfer line mark interrupt flag */ +#define IPA_FLAG_LAC IPA_INTF_LACIF /*!< LUT access conflict interrupt flag */ +#define IPA_FLAG_LLF IPA_INTF_LLFIF /*!< LUT loading finish interrupt flag */ +#define IPA_FLAG_WCF IPA_INTF_WCFIF /*!< wrong configuration interrupt flag */ + +/* IPA interrupt enable or disable */ +#define IPA_INT_TAE IPA_CTL_TAEIE /*!< transfer access error interrupt */ +#define IPA_INT_FTF IPA_CTL_FTFIE /*!< full transfer finish interrupt */ +#define IPA_INT_TLM IPA_CTL_TLMIE /*!< transfer line mark interrupt */ +#define IPA_INT_LAC IPA_CTL_LACIE /*!< LUT access conflict interrupt */ +#define IPA_INT_LLF IPA_CTL_LLFIE /*!< LUT loading finish interrupt */ +#define IPA_INT_WCF IPA_CTL_WCFIE /*!< wrong configuration interrupt */ + +/* IPA interrupt flags */ +#define IPA_INT_FLAG_TAE IPA_INTF_TAEIF /*!< transfer access error interrupt flag */ +#define IPA_INT_FLAG_FTF IPA_INTF_FTFIF /*!< full transfer finish interrupt flag */ +#define IPA_INT_FLAG_TLM IPA_INTF_TLMIF /*!< transfer line mark interrupt flag */ +#define IPA_INT_FLAG_LAC IPA_INTF_LACIF /*!< LUT access conflict interrupt flag */ +#define IPA_INT_FLAG_LLF IPA_INTF_LLFIF /*!< LUT loading finish interrupt flag */ +#define IPA_INT_FLAG_WCF IPA_INTF_WCFIF /*!< wrong configuration interrupt flag */ /* function declarations */ - +/* functions enable or disable, pixel format convert mode set */ /* deinitialize IPA */ void ipa_deinit(void); -/* IPA transfer enable */ +/* enable IPA transfer */ void ipa_transfer_enable(void); -/* IPA transfer hang up enable */ +/* enable IPA transfer hang up */ void ipa_transfer_hangup_enable(void); -/* IPA transfer hang up disable */ +/* disable IPA transfer hang up */ void ipa_transfer_hangup_disable(void); -/* IPA transfer stop enable */ +/* enable IPA transfer stop */ void ipa_transfer_stop_enable(void); -/* IPA transfer stop disable */ +/* disable IPA transfer stop */ void ipa_transfer_stop_disable(void); -/* IPA foreground LUT loading enable */ +/* enable IPA foreground LUT loading */ void ipa_foreground_lut_loading_enable(void); -/* IPA background LUT loading enable */ +/* enable IPA background LUT loading */ void ipa_background_lut_loading_enable(void); -/* IPA transfer enable */ -void ipa_pixel_format_convert_mod(uint32_t pfcm); +/* set pixel format convert mode, the function is invalid when the IPA transfer is enabled */ +void ipa_pixel_format_convert_mode_set(uint32_t pfcm); +/* structure initialization, foreground, background, destination and LUT initialization */ +/* initialize the structure of IPA foreground parameter struct with the default values, it is + suggested that call this function after an ipa_foreground_parameter_struct structure is defined */ +void ipa_foreground_struct_para_init(ipa_foreground_parameter_struct* foreground_struct); /* initialize foreground parameters */ void ipa_foreground_init(ipa_foreground_parameter_struct* foreground_struct); +/* initialize the structure of IPA background parameter struct with the default values, it is + suggested that call this function after an ipa_background_parameter_struct structure is defined */ +void ipa_background_struct_para_init(ipa_background_parameter_struct* background_struct); /* initialize background parameters */ void ipa_background_init(ipa_background_parameter_struct* background_struct); +/* initialize the structure of IPA destination parameter struct with the default values, it is + suggested that call this function after an ipa_destination_parameter_struct structure is defined */ +void ipa_destination_struct_para_init(ipa_destination_parameter_struct* destination_struct); /* initialize destination parameters */ void ipa_destination_init(ipa_destination_parameter_struct* destination_struct); /* initialize IPA foreground LUT parameters */ -void ipa_foreground_lut_init(uint32_t fg_lut_num,uint8_t fg_lut_pf, uint32_t fg_lut_addr); +void ipa_foreground_lut_init(uint8_t fg_lut_num, uint8_t fg_lut_pf, uint32_t fg_lut_addr); /* initialize IPA background LUT parameters */ -void ipa_background_lut_init(uint32_t bg_lut_num,uint8_t bg_lut_pf, uint32_t bg_lut_addr); +void ipa_background_lut_init(uint8_t bg_lut_num, uint8_t bg_lut_pf, uint32_t bg_lut_addr); -/* configure line mark */ -void ipa_line_mark_config(uint32_t linenum); -/* Inter-timer enable or disable */ -void ipa_inter_timer_config(uint8_t timercfg); -/* number of clock cycles interval set */ -void ipa_interval_clock_num_config(uint32_t clk_num ); +/* configuration functions */ +/* configure IPA line mark */ +void ipa_line_mark_config(uint16_t line_num); +/* inter-timer enable or disable */ +void ipa_inter_timer_config(uint8_t timer_cfg); +/* configure the number of clock cycles interval */ +void ipa_interval_clock_num_config(uint8_t clk_num); -/* IPA interrupt enable */ -void ipa_interrupt_enable(uint32_t inttype); -/* IPA interrupt disable */ -void ipa_interrupt_disable(uint32_t inttype); +/* flag and interrupt functions */ +/* get IPA flag status in IPA_INTF register */ +FlagStatus ipa_flag_get(uint32_t flag); +/* clear IPA flag in IPA_INTF register */ +void ipa_flag_clear(uint32_t flag); +/* enable IPA interrupt */ +void ipa_interrupt_enable(uint32_t int_flag); +/* disable IPA interrupt */ +void ipa_interrupt_disable(uint32_t int_flag); /* get IPA interrupt flag */ -FlagStatus ipa_interrupt_flag_get(uint32_t intflag); +FlagStatus ipa_interrupt_flag_get(uint32_t int_flag); /* clear IPA interrupt flag */ -void ipa_interrupt_flag_clear(uint32_t intflag); +void ipa_interrupt_flag_clear(uint32_t int_flag); #endif /* GD32F4XX_IPA_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h index 0b7b3224d9..4be9181ed8 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_iref.h - \brief definitions for the IREF + \file gd32f4xx_iref.h + \brief definitions for the IREF + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_IREF_H @@ -25,7 +50,7 @@ #define IREF_CTL_CSDT BITS(0,5) /*!< current step data */ #define IREF_CTL_SCMOD BIT(7) /*!< sink current mode */ #define IREF_CTL_CPT BITS(8,12) /*!< current precision trim */ -#define IREF_CTL_SSEL BIT(14) /*!< step selection */ +#define IREF_CTL_SSEL BIT(14) /*!< step selection */ #define IREF_CTL_CREN BIT(15) /*!< current reference enable */ /* constants definitions */ @@ -130,13 +155,13 @@ #define IREF_CUR_STEP_DATA_61 CTL_CSDT(61) /*!< IREF current step data 61 */ #define IREF_CUR_STEP_DATA_62 CTL_CSDT(62) /*!< IREF current step data 62 */ #define IREF_CUR_STEP_DATA_63 CTL_CSDT(63) /*!< IREF current step data 63 */ - + /* IREF mode selection */ #define IREF_STEP(regval) (BIT(14) & ((uint32_t)(regval) << 14)) #define IREF_MODE_LOW_POWER IREF_STEP(0) /*!< low power, 1uA step */ #define IREF_MODE_HIGH_CURRENT IREF_STEP(1) /*!< high current, 8uA step */ - -/* IREF sink current mode*/ + +/* IREF sink current mode*/ #define IREF_CURRENT(regval) (BIT(7) & ((uint32_t)(regval) << 7)) #define IREF_SOURCE_CURRENT IREF_CURRENT(0) /*!< IREF source current */ #define IREF_SINK_CURRENT IREF_CURRENT(1) /*!< IREF sink current */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h index 2052abe9a0..21ae664c14 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_misc.h - \brief definitions for the MISC + \file gd32f4xx_misc.h + \brief definitions for the MISC + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_MISC_H diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h index 74a857e96c..f19b1cb2ec 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h @@ -1,14 +1,40 @@ /*! - \file gd32f4xx_pmu.h - \brief definitions for the PMU + \file gd32f4xx_pmu.h + \brief definitions for the PMU + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ + #ifndef GD32F4XX_PMU_H #define GD32F4XX_PMU_H @@ -52,14 +78,14 @@ /* constants definitions */ /* PMU low voltage detector threshold definitions */ #define CTL_LVDT(regval) (BITS(5,7)&((uint32_t)(regval)<<5)) -#define PMU_LVDT_0 CTL_LVDT(0) /*!< voltage threshold is 2.2V */ +#define PMU_LVDT_0 CTL_LVDT(0) /*!< voltage threshold is 2.1V */ #define PMU_LVDT_1 CTL_LVDT(1) /*!< voltage threshold is 2.3V */ #define PMU_LVDT_2 CTL_LVDT(2) /*!< voltage threshold is 2.4V */ -#define PMU_LVDT_3 CTL_LVDT(3) /*!< voltage threshold is 2.5V */ -#define PMU_LVDT_4 CTL_LVDT(4) /*!< voltage threshold is 2.6V */ -#define PMU_LVDT_5 CTL_LVDT(5) /*!< voltage threshold is 2.7V */ -#define PMU_LVDT_6 CTL_LVDT(6) /*!< voltage threshold is 2.8V */ -#define PMU_LVDT_7 CTL_LVDT(7) /*!< voltage threshold is 2.9V */ +#define PMU_LVDT_3 CTL_LVDT(3) /*!< voltage threshold is 2.6V */ +#define PMU_LVDT_4 CTL_LVDT(4) /*!< voltage threshold is 2.7V */ +#define PMU_LVDT_5 CTL_LVDT(5) /*!< voltage threshold is 2.9V */ +#define PMU_LVDT_6 CTL_LVDT(6) /*!< voltage threshold is 3.0V */ +#define PMU_LVDT_7 CTL_LVDT(7) /*!< voltage threshold is 3.1V */ /* PMU LDO output voltage select definitions */ #define CTL_LDOVS(regval) (BITS(14,15)&((uint32_t)(regval)<<14)) @@ -124,7 +150,7 @@ void pmu_deinit(void); /* select low voltage detector threshold */ -void pmu_lvd_select(uint32_t pmu_lvdt_n); +void pmu_lvd_select(uint32_t lvdt_n); /* LDO output voltage select */ void pmu_ldo_output_select(uint32_t ldo_output); /* PMU lvd disable */ @@ -148,7 +174,7 @@ void pmu_lowdriver_normalpower_config(uint32_t mode); /* PMU work at sleep mode */ void pmu_to_sleepmode(uint8_t sleepmodecmd); /* PMU work at deepsleep mode */ -void pmu_to_deepsleepmode(uint32_t pmu_ldo, uint8_t deepsleepmodecmd); +void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd); /* PMU work at standby mode */ void pmu_to_standbymode(uint8_t standbymodecmd); /* PMU wakeup pin enable */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h index 6851c2e22f..0445df4eb0 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_rcu.h - \brief definitions for the RCU + \file gd32f4xx_rcu.h + \brief definitions for the RCU + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_RCU_H @@ -34,14 +59,14 @@ #define RCU_APB2EN REG32(RCU + 0x44U) /*!< APB2 enable register */ #define RCU_AHB1SPEN REG32(RCU + 0x50U) /*!< AHB1 sleep mode enable register */ #define RCU_AHB2SPEN REG32(RCU + 0x54U) /*!< AHB2 sleep mode enable register */ -#define RCU_AHB3SPEN REG32(RCU + 0x58U) /*!< AHB3 sleep mode enable register */ +#define RCU_AHB3SPEN REG32(RCU + 0x58U) /*!< AHB3 sleep mode enable register */ #define RCU_APB1SPEN REG32(RCU + 0x60U) /*!< APB1 sleep mode enable register */ #define RCU_APB2SPEN REG32(RCU + 0x64U) /*!< APB2 sleep mode enable register */ #define RCU_BDCTL REG32(RCU + 0x70U) /*!< backup domain control register */ #define RCU_RSTSCK REG32(RCU + 0x74U) /*!< reset source / clock register */ #define RCU_PLLSSCTL REG32(RCU + 0x80U) /*!< PLL clock spread spectrum control register */ -#define RCU_PLLI2S REG32(RCU + 0x84U) /*!< PLLI2S register */ -#define RCU_PLLSAI REG32(RCU + 0x88U) /*!< PLLSAI register */ +#define RCU_PLLI2S REG32(RCU + 0x84U) /*!< PLLI2S register */ +#define RCU_PLLSAI REG32(RCU + 0x88U) /*!< PLLSAI register */ #define RCU_CFG1 REG32(RCU + 0x8CU) /*!< clock configuration register 1 */ #define RCU_ADDCTL REG32(RCU + 0xC0U) /*!< Additional clock control register */ #define RCU_ADDINT REG32(RCU + 0xCCU) /*!< Additional clock interrupt register */ @@ -54,7 +79,7 @@ /* bits definitions */ /* RCU_CTL */ #define RCU_CTL_IRC16MEN BIT(0) /*!< internal high speed oscillator enable */ -#define RCU_CTL_IRC16MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC16MSTB BIT(1) /*!< IRC16M high speed internal oscillator stabilization flag */ #define RCU_CTL_IRC16MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ #define RCU_CTL_IRC16MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ #define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ @@ -64,7 +89,7 @@ #define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ #define RCU_CTL_PLLSTB BIT(25) /*!< PLL Clock Stabilization Flag */ #define RCU_CTL_PLLI2SEN BIT(26) /*!< PLLI2S enable */ -#define RCU_CTL_PLLI2STB BIT(27) /*!< PLLI2S Clock Stabilization Flag */ +#define RCU_CTL_PLLI2SSTB BIT(27) /*!< PLLI2S Clock Stabilization Flag */ #define RCU_CTL_PLLSAIEN BIT(28) /*!< PLLSAI enable */ #define RCU_CTL_PLLSAISTB BIT(29) /*!< PLLSAI Clock Stabilization Flag */ @@ -123,7 +148,7 @@ #define RCU_AHB1RST_PGRST BIT(6) /*!< GPIO port G reset */ #define RCU_AHB1RST_PHRST BIT(7) /*!< GPIO port H reset */ #define RCU_AHB1RST_PIRST BIT(8) /*!< GPIO port I reset */ -#define RCU_AHB1RST_CRCRST BIT(12) /*!< CRC reset */ +#define RCU_AHB1RST_CRCRST BIT(12) /*!< CRC reset */ #define RCU_AHB1RST_DMA0RST BIT(21) /*!< DMA0 reset */ #define RCU_AHB1RST_DMA1RST BIT(22) /*!< DMA1 reset */ #define RCU_AHB1RST_IPARST BIT(23) /*!< IPA reset */ @@ -134,7 +159,7 @@ #define RCU_AHB2RST_DCIRST BIT(0) /*!< DCI reset */ #define RCU_AHB2RST_TRNGRST BIT(6) /*!< TRNG reset */ #define RCU_AHB2RST_USBFSRST BIT(7) /*!< USBFS reset */ - + /* RCU_AHB3RST */ #define RCU_AHB3RST_EXMCRST BIT(0) /*!< EXMC reset */ @@ -167,9 +192,9 @@ /* RCU_APB2RST */ #define RCU_APB2RST_TIMER0RST BIT(0) /*!< TIMER0 reset */ -#define RCU_APB2RST_TIMER7RST BIT(1) /*!< TIMER7 reset */ +#define RCU_APB2RST_TIMER7RST BIT(1) /*!< TIMER7 reset */ #define RCU_APB2RST_USART0RST BIT(4) /*!< USART0 reset */ -#define RCU_APB2RST_USART5RST BIT(5) /*!< USART5 reset */ +#define RCU_APB2RST_USART5RST BIT(5) /*!< USART5 reset */ #define RCU_APB2RST_ADCRST BIT(8) /*!< ADC reset */ #define RCU_APB2RST_SDIORST BIT(11) /*!< SDIO reset */ #define RCU_APB2RST_SPI0RST BIT(12) /*!< SPI0 reset */ @@ -361,11 +386,11 @@ #define RCU_RSTSCK_LPRSTF BIT(31) /*!< low-power reset flag */ /* RCU_PLLSSCTL */ -#define RCU_PLLSSCTL_MODCNT BITS(0,12) /*!< these bits configure PLL spread spectrum modulation - profile amplitude and frequency. the following criteria +#define RCU_PLLSSCTL_MODCNT BITS(0,12) /*!< these bits configure PLL spread spectrum modulation + profile amplitude and frequency. the following criteria must be met: MODSTEP*MODCNT=215-1 */ -#define RCU_PLLSSCTL_MODSTEP BITS(13,27) /*!< these bits configure PLL spread spectrum modulation - profile amplitude and frequency. the following criteria +#define RCU_PLLSSCTL_MODSTEP BITS(13,27) /*!< these bits configure PLL spread spectrum modulation + profile amplitude and frequency. the following criteria must be met: MODSTEP*MODCNT=215-1 */ #define RCU_PLLSSCTL_SS_TYPE BIT(30) /*!< PLL spread spectrum modulation type select */ #define RCU_PLLSSCTL_SSCGON BIT(31) /*!< PLL spread spectrum modulation enable */ @@ -438,7 +463,7 @@ #define ADD_APB1EN_REG_OFFSET 0xE4U /*!< APB1 additional enable register offset */ #define ADD_APB1SPEN_REG_OFFSET 0xE8U /*!< APB1 additional sleep mode enable register offset */ -/* peripherals reset */ +/* peripherals reset */ #define AHB1RST_REG_OFFSET 0x10U /*!< AHB1 reset register offset */ #define AHB2RST_REG_OFFSET 0x14U /*!< AHB2 reset register offset */ #define AHB3RST_REG_OFFSET 0x18U /*!< AHB3 reset register offset */ @@ -504,7 +529,7 @@ typedef enum RCU_TIMER6 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 5U), /*!< TIMER6 clock */ RCU_TIMER11 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 6U), /*!< TIMER11 clock */ RCU_TIMER12 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 7U), /*!< TIMER12 clock */ - RCU_TIMER13 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 8U), /*!< TIMER13 clock */ + RCU_TIMER13 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 8U), /*!< TIMER13 clock */ RCU_WWDGT = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 11U), /*!< WWDGT clock */ RCU_SPI1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 14U), /*!< SPI1 clock */ RCU_SPI2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 15U), /*!< SPI2 clock */ @@ -514,7 +539,7 @@ typedef enum RCU_UART4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 20U), /*!< UART4 clock */ RCU_I2C0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 21U), /*!< I2C0 clock */ RCU_I2C1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 22U), /*!< I2C1 clock */ - RCU_I2C2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 23U), /*!< I2C2 clock */ + RCU_I2C2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 23U), /*!< I2C2 clock */ RCU_CAN0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 25U), /*!< CAN0 clock */ RCU_CAN1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 26U), /*!< CAN1 clock */ RCU_PMU = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U), /*!< PMU clock */ @@ -540,7 +565,7 @@ typedef enum RCU_SPI4 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 20U), /*!< SPI4 clock */ RCU_SPI5 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 21U), /*!< SPI5 clock */ RCU_TLI = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 26U), /*!< TLI clock */ - /* APB2 additional peripherals */ + /* APB1 additional peripherals */ RCU_CTC = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 27U), /*!< CTC clock */ RCU_IREF = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 31U), /*!< IREF clock */ }rcu_periph_enum; @@ -588,7 +613,7 @@ typedef enum RCU_TIMER6_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 5U), /*!< TIMER6 clock */ RCU_TIMER11_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 6U), /*!< TIMER11 clock */ RCU_TIMER12_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 7U), /*!< TIMER12 clock */ - RCU_TIMER13_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 8U), /*!< TIMER13 clock */ + RCU_TIMER13_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 8U), /*!< TIMER13 clock */ RCU_WWDGT_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 11U), /*!< WWDGT clock */ RCU_SPI1_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 14U), /*!< SPI1 clock */ RCU_SPI2_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 15U), /*!< SPI2 clock */ @@ -598,7 +623,7 @@ typedef enum RCU_UART4_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 20U), /*!< UART4 clock */ RCU_I2C0_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 21U), /*!< I2C0 clock */ RCU_I2C1_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 22U), /*!< I2C1 clock */ - RCU_I2C2_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 23U), /*!< I2C2 clock */ + RCU_I2C2_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 23U), /*!< I2C2 clock */ RCU_CAN0_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 25U), /*!< CAN0 clock */ RCU_CAN1_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 26U), /*!< CAN1 clock */ RCU_PMU_SLP = RCU_REGIDX_BIT(APB1SPEN_REG_OFFSET, 28U), /*!< PMU clock */ @@ -644,8 +669,8 @@ typedef enum RCU_CRCRST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 12U), /*!< CRC clock reset */ RCU_DMA0RST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 21U), /*!< DMA0 clock reset */ RCU_DMA1RST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 22U), /*!< DMA1 clock reset */ - RCU_IPAENRST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 23U), /*!< IPA clock reset */ - RCU_ENETRST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 25U), /*!< ENET clock reset */ + RCU_IPARST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 23U), /*!< IPA clock reset */ + RCU_ENETRST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 25U), /*!< ENET clock reset */ RCU_USBHSRST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 29U), /*!< USBHS clock reset */ /* AHB2 peripherals */ RCU_DCIRST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 0U), /*!< DCI clock reset */ @@ -662,7 +687,7 @@ typedef enum RCU_TIMER6RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 5U), /*!< TIMER6 clock reset */ RCU_TIMER11RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 6U), /*!< TIMER11 clock reset */ RCU_TIMER12RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 7U), /*!< TIMER12 clock reset */ - RCU_TIMER13RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 8U), /*!< TIMER13 clock reset */ + RCU_TIMER13RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 8U), /*!< TIMER13 clock reset */ RCU_WWDGTRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 11U), /*!< WWDGT clock reset */ RCU_SPI1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 14U), /*!< SPI1 clock reset */ RCU_SPI2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 15U), /*!< SPI2 clock reset */ @@ -672,7 +697,7 @@ typedef enum RCU_UART4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 20U), /*!< UART4 clock reset */ RCU_I2C0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 21U), /*!< I2C0 clock reset */ RCU_I2C1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 22U), /*!< I2C1 clock reset */ - RCU_I2C2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 23U), /*!< I2C2 clock reset */ + RCU_I2C2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 23U), /*!< I2C2 clock reset */ RCU_CAN0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 25U), /*!< CAN0 clock reset */ RCU_CAN1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 26U), /*!< CAN1 clock reset */ RCU_PMURST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 28U), /*!< PMU clock reset */ @@ -695,7 +720,7 @@ typedef enum RCU_SPI4RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 20U), /*!< SPI4 clock reset */ RCU_SPI5RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 21U), /*!< SPI5 clock reset */ RCU_TLIRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 26U), /*!< TLI clock reset */ - /* APB2 additional peripherals */ + /* APB1 additional peripherals */ RCU_CTCRST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 27U), /*!< CTC clock reset */ RCU_IREFRST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 31U) /*!< IREF clock reset */ }rcu_periph_reset_enum; @@ -727,7 +752,7 @@ typedef enum { RCU_INT_FLAG_IRC32KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 0U), /*!< IRC32K stabilization interrupt flag */ RCU_INT_FLAG_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 1U), /*!< LXTAL stabilization interrupt flag */ - RCU_INT_FLAG_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U), /*!< IRC8M stabilization interrupt flag */ + RCU_INT_FLAG_IRC16MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U), /*!< IRC16M stabilization interrupt flag */ RCU_INT_FLAG_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 3U), /*!< HXTAL stabilization interrupt flag */ RCU_INT_FLAG_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 4U), /*!< PLL stabilization interrupt flag */ RCU_INT_FLAG_PLLI2SSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 5U), /*!< PLLI2S stabilization interrupt flag */ @@ -755,7 +780,7 @@ typedef enum { RCU_INT_IRC32KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 8U), /*!< IRC32K stabilization interrupt */ RCU_INT_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 9U), /*!< LXTAL stabilization interrupt */ - RCU_INT_IRC16MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U), /*!< IRC8M stabilization interrupt */ + RCU_INT_IRC16MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U), /*!< IRC16M stabilization interrupt */ RCU_INT_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 11U), /*!< HXTAL stabilization interrupt */ RCU_INT_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 12U), /*!< PLL stabilization interrupt */ RCU_INT_PLLI2SSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 13U), /*!< PLLI2S stabilization interrupt */ @@ -890,7 +915,7 @@ typedef enum /* CKOUT1 Clock source selection */ #define CFG0_CKOUT1SEL(regval) (BITS(30,31) & ((uint32_t)(regval) << 30)) #define RCU_CKOUT1SRC_SYSTEMCLOCK CFG0_CKOUT1SEL(0) /*!< system clock selected */ -#define RCU_CKOUT1SRC_PLLI2SR CFG0_CKOUT1SEL(1) /*!< low speed crystal oscillator clock (LXTAL) selected */ +#define RCU_CKOUT1SRC_PLLI2SR CFG0_CKOUT1SEL(1) /*!< CK_PLLI2SR clock selected */ #define RCU_CKOUT1SRC_HXTAL CFG0_CKOUT1SEL(2) /*!< high speed crystal oscillator clock (HXTAL) selected */ #define RCU_CKOUT1SRC_PLLP CFG0_CKOUT1SEL(3) /*!< CK_PLLP clock selected */ @@ -938,13 +963,13 @@ typedef enum #define RCU_PLLSAIR_DIV16 CFG1_PLLSAIRDIV(3) /*!< CK_PLLSAIRDIV clock select CK_PLLSAIR/16 */ /* TIMER clock selection */ -#define RCU_TIMER_PSC_MUL2 ~RCU_CFG1_TIMERSEL /*!< if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB) +#define RCU_TIMER_PSC_MUL2 ~RCU_CFG1_TIMERSEL /*!< if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB) or 0b100(CK_APBx = CK_AHB/2), the TIMER clock is equal to CK_AHB(CK_TIMERx = CK_AHB). - or else, the TIMER clock is twice the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 2 x CK_APB1; + or else, the TIMER clock is twice the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 2 x CK_APB1; TIMER in APB2 domain: CK_TIMERx = 2 x CK_APB2) */ -#define RCU_TIMER_PSC_MUL4 RCU_CFG1_TIMERSEL /*!< if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB), - 0b100(CK_APBx = CK_AHB/2), or 0b101(CK_APBx = CK_AHB/4), the TIMER clock is equal to CK_AHB(CK_TIMERx = CK_AHB). - or else, the TIMER clock is four timers the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 4 x CK_APB1; +#define RCU_TIMER_PSC_MUL4 RCU_CFG1_TIMERSEL /*!< if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB), + 0b100(CK_APBx = CK_AHB/2), or 0b101(CK_APBx = CK_AHB/4), the TIMER clock is equal to CK_AHB(CK_TIMERx = CK_AHB). + or else, the TIMER clock is four timers the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 4 x CK_APB1; TIMER in APB2 domain: CK_TIMERx = 4 x CK_APB2) */ /* RCU_PLLSSCTL register bit define */ @@ -966,7 +991,7 @@ typedef enum /* The PLLP output frequency division factor from PLL VCO clock */ #define RCU_PLLP_DIV_MIN ((uint32_t)2U) /*!< PLLP_DIV min value */ #define RCU_PLLP_DIV_MAX ((uint32_t)8U) /*!< PLLP_DIV max value */ - + /* PLL Clock Source Selection */ #define RCU_PLLSRC_IRC16M ((uint32_t)0x00000000U) /*!< IRC16M clock selected as source clock of PLL, PLLSAI, PLLI2S */ #define RCU_PLLSRC_HXTAL RCU_PLL_PLLSEL /*!< HXTAL clock selected as source clock of PLL, PLLSAI, PLLI2S */ @@ -975,10 +1000,10 @@ typedef enum #define RCU_PLLQ_DIV_MIN ((uint32_t)2U) /*!< PLLQ_DIV min value */ #define RCU_PLLQ_DIV_MAX ((uint32_t)15U) /*!< PLLQ_DIV max value */ -#define CHECK_PLL_PSC_VALID(val) (((val) >= RCU_PLLPSC_DIV_MIN)&&((val) <= RCU_PLLPSC_DIV_MAX)) -#define CHECK_PLL_N_VALID(val, inc) (((val) >= (RCU_PLLN_MUL_MIN + (inc)))&&((val) <= RCU_PLLN_MUL_MAX)) -#define CHECK_PLL_P_VALID(val) (((val) == 2U) || ((val) == 4U) || ((val) == 6U) || ((val) == 8U)) -#define CHECK_PLL_Q_VALID(val) (((val) >= RCU_PLLQ_DIV_MIN)&&((val) <= RCU_PLLQ_DIV_MAX)) +#define CHECK_PLL_PSC_VALID(val) (((val) >= RCU_PLLPSC_DIV_MIN)&&((val) <= RCU_PLLPSC_DIV_MAX)) +#define CHECK_PLL_N_VALID(val, inc) (((val) >= (RCU_PLLN_MUL_MIN + (inc)))&&((val) <= RCU_PLLN_MUL_MAX)) +#define CHECK_PLL_P_VALID(val) (((val) == 2U) || ((val) == 4U) || ((val) == 6U) || ((val) == 8U)) +#define CHECK_PLL_Q_VALID(val) (((val) >= RCU_PLLQ_DIV_MIN)&&((val) <= RCU_PLLQ_DIV_MAX)) /* RCU_BDCTL register bit define */ /* LXTAL drive capability */ @@ -1033,7 +1058,7 @@ typedef enum #define CHECK_PLLSAI_R_VALID(val) (((val) >= RCU_PLLSAIR_DIV_MIN)&&((val) <= RCU_PLLSAIR_DIV_MAX)) /* RCU_ADDCTL register bit define */ -/* 48MHz clock selection */ +/* 48MHz clock selection */ #define RCU_CK48MSRC_PLL48M ((uint32_t)0x00000000U) /*!< CK48M source clock select PLL48M */ #define RCU_CK48MSRC_IRC48M RCU_ADDCTL_CK48MSEL /*!< CK48M source clock select IRC48M */ @@ -1086,11 +1111,13 @@ void rcu_ckout1_config(uint32_t ckout1_src, uint32_t ckout1_div); /* configure the PLL clock source selection and PLL multiply factor */ ErrStatus rcu_pll_config(uint32_t pll_src, uint32_t pll_psc, uint32_t pll_n, uint32_t pll_p, uint32_t pll_q); /* configure the PLLI2S clock */ -ErrStatus rcu_plli2s_config(uint32_t plli2s_n, uint32_t plli2s_q, uint32_t plli2s_r); +ErrStatus rcu_plli2s_config(uint32_t plli2s_n, uint32_t plli2s_r); /* configure the PLLSAI clock */ -ErrStatus rcu_pllsai_config(uint32_t pllsai_n, uint32_t pllsai_p, uint32_t pllsai_q, uint32_t pllsai_r); +ErrStatus rcu_pllsai_config(uint32_t pllsai_n, uint32_t pllsai_p, uint32_t pllsai_r); /* configure the RTC clock source selection */ void rcu_rtc_clock_config(uint32_t rtc_clock_source); +/* cconfigure the frequency division of RTC clock when HXTAL was selected as its clock source */ +void rcu_rtc_div_config(uint32_t rtc_div); /* configure the I2S clock source selection */ void rcu_i2s_clock_config(uint32_t i2s_clock_source); /* configure the CK48M clock selection */ @@ -1098,7 +1125,7 @@ void rcu_ck48m_clock_config(uint32_t ck48m_clock_source); /* configure the PLL48M clock selection */ void rcu_pll48m_clock_config(uint32_t pll48m_clock_source); /* configure the TIMER clock prescaler selection */ -void rcu_timer_clock_prescaler_config(uint32_t timer_clock_prescaler); +void rcu_timer_clock_prescaler_config(uint32_t timer_clock_prescaler); /* configure the TLI clock division selection */ void rcu_tli_clock_div_config(uint32_t pllsai_r_div); @@ -1110,11 +1137,11 @@ void rcu_all_reset_flag_clear(void); /* get the clock stabilization interrupt and ckm flags */ FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag); /* clear the interrupt flags */ -void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear); +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag); /* enable the stabilization interrupt */ -void rcu_interrupt_enable(rcu_int_enum stab_int); +void rcu_interrupt_enable(rcu_int_enum interrupt); /* disable the stabilization interrupt */ -void rcu_interrupt_disable(rcu_int_enum stab_int); +void rcu_interrupt_disable(rcu_int_enum interrupt); /* configure the LXTAL drive capability */ void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap); @@ -1140,7 +1167,7 @@ void rcu_spread_spectrum_config(uint32_t spread_spectrum_type, uint32_t modstep, /* enable the spread spectrum modulation for the main PLL clock */ void rcu_spread_spectrum_enable(void); /* disable the spread spectrum modulation for the main PLL clock */ -void rcu_spread_spectrum_disable(void); +void rcu_spread_spectrum_disable(void); /* unlock the voltage key */ void rcu_voltage_key_unlock(void); /* set the deep sleep mode voltage */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h index 27155a3076..75e66f236e 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h @@ -1,14 +1,40 @@ /*! - \file gd32f4xx_rtc.h - \brief definitions for the RTC + \file gd32f4xx_rtc.c + \brief definitions for the RTC + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ + #ifndef GD32F4XX_RTC_H #define GD32F4XX_RTC_H @@ -254,7 +280,7 @@ typedef struct ControlStatus tamper_precharge_enable; /*!< RTC tamper precharge feature during a voltage level detection */ uint32_t tamper_precharge_time; /*!< RTC tamper precharge duration if precharge feature is enabled */ ControlStatus tamper_with_timestamp; /*!< RTC tamper time-stamp feature */ -}rtc_tamper_struct; +}rtc_tamper_struct; /* time register value */ #define TIME_SC(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) /*!< write value to RTC_TIME_SC bit field */ @@ -380,7 +406,7 @@ typedef struct #define GET_DTS_DAY(regval) GET_BITS((regval),0,5) /*!< get value of RTC_DTS_DAY bit field */ #define DTS_MON(regval) (BITS(8,12) & ((uint32_t)(regval) << 8)) /*!< write value to RTC_DTS_MON bit field */ -#define GET_DTS_MON(regval) GET_BITS((regval),8,11) /*!< get value of RTC_DTS_MON bit field */ +#define GET_DTS_MON(regval) GET_BITS((regval),8,12) /*!< get value of RTC_DTS_MON bit field */ #define DTS_DOW(regval) (BITS(13,15) & ((uint32_t)(regval) << 13)) /*!< write value to RTC_DTS_DOW bit field */ #define GET_DTS_DOW(regval) GET_BITS((regval),13,15) /*!< get value of RTC_DTS_DOW bit field */ @@ -399,7 +425,7 @@ typedef struct #define RTC_CALIBRATION_PLUS_RESET ((uint32_t)0x00000000U) /*!< no effect */ /* tamp register value */ -#define TAMP_FREQ(regval) (BITS(8,10) & ((uint32_t)(regval) << 10)) /*!< write value to RTC_TAMP_FREQ bit field */ +#define TAMP_FREQ(regval) (BITS(8,10) & ((uint32_t)(regval) << 8)) /*!< write value to RTC_TAMP_FREQ bit field */ #define RTC_FREQ_DIV32768 TAMP_FREQ(0) /*!< sample once every 32768 RTCCLK(1Hz if RTCCLK=32.768KHz) */ #define RTC_FREQ_DIV16384 TAMP_FREQ(1) /*!< sample once every 16384 RTCCLK(2Hz if RTCCLK=32.768KHz) */ #define RTC_FREQ_DIV8192 TAMP_FREQ(2) /*!< sample once every 8192 RTCCLK(4Hz if RTCCLK=32.768KHz) */ @@ -475,12 +501,12 @@ typedef struct #define RTC_WUT_RESET ((uint32_t)0x0000FFFFU) /*!< RTC_WUT register reset value */ /* RTC alarm */ -#define RTC_ALARM0 ((uint8_t)0x01U) /*!< RTC alarm 0 */ -#define RTC_ALARM1 ((uint8_t)0x02U) /*!< RTC alarm 1 */ +#define RTC_ALARM0 ((uint8_t)0x01U) /*!< RTC alarm 0 */ +#define RTC_ALARM1 ((uint8_t)0x02U) /*!< RTC alarm 1 */ /* RTC coarse calibration direction */ -#define CALIB_INCREASE ((uint8_t)0x01U) /*!< RTC coarse calibration increase */ -#define CALIB_DECREASE ((uint8_t)0x02U) /*!< RTC coarse calibration decrease */ +#define CALIB_INCREASE ((uint8_t)0x01U) /*!< RTC coarse calibration increase */ +#define CALIB_DECREASE ((uint8_t)0x02U) /*!< RTC coarse calibration decrease */ /* RTC wakeup timer clock */ #define CTL_WTCS(regval) (BITS(0,2) & ((regval)<< 0)) @@ -490,13 +516,30 @@ typedef struct #define WAKEUP_RTCCK_DIV2 CTL_WTCS(3) /*!< wakeup timer clock is RTC clock divided by 2 */ #define WAKEUP_CKSPRE CTL_WTCS(4) /*!< wakeup timer clock is ckapre */ #define WAKEUP_CKSPRE_2EXP16 CTL_WTCS(6) /*!< wakeup timer clock is ckapre and wakeup timer add 2exp16 */ - + /* RTC_AF pin */ #define RTC_AF0_TIMESTAMP ((uint32_t)0x00000000) /*!< RTC_AF0 use for timestamp */ #define RTC_AF1_TIMESTAMP RTC_TAMP_TSSEL /*!< RTC_AF1 use for timestamp */ #define RTC_AF0_TAMPER0 ((uint32_t)0x00000000) /*!< RTC_AF0 use for tamper0 */ #define RTC_AF1_TAMPER0 RTC_TAMP_TP0SEL /*!< RTC_AF1 use for tamper0 */ +/* RTC flags */ +#define RTC_FLAG_ALRM0W RTC_STAT_ALRM0WF /*!< alarm0 configuration can be write flag */ +#define RTC_FLAG_ALRM1W RTC_STAT_ALRM1WF /*!< alarm1 configuration can be write flag */ +#define RTC_FLAG_WTW RTC_STAT_WTWF /*!< wakeup timer can be write flag */ +#define RTC_FLAG_SOP RTC_STAT_SOPF /*!< shift function operation pending flag */ +#define RTC_FLAG_YCM RTC_STAT_YCM /*!< year configuration mark status flag */ +#define RTC_FLAG_RSYN RTC_STAT_RSYNF /*!< register synchronization flag */ +#define RTC_FLAG_INIT RTC_STAT_INITF /*!< initialization state flag */ +#define RTC_FLAG_ALRM0 RTC_STAT_ALRM0F /*!< alarm0 occurs flag */ +#define RTC_FLAG_ALRM1 RTC_STAT_ALRM1F /*!< alarm1 occurs flag */ +#define RTC_FLAG_WT RTC_STAT_WTF /*!< wakeup timer occurs flag */ +#define RTC_FLAG_TS RTC_STAT_TSF /*!< time-stamp flag */ +#define RTC_FLAG_TSOVR RTC_STAT_TSOVRF /*!< time-stamp overflow flag */ +#define RTC_FLAG_TP0 RTC_STAT_TP0F /*!< RTC tamper 0 detected flag */ +#define RTC_FLAG_TP1 RTC_STAT_TP1F /*!< RTC tamper 1 detected flag */ +#define RTC_STAT_SCP RTC_STAT_SCPF /*!< smooth calibration pending flag */ + /* function declarations */ /* reset most of the RTC registers */ ErrStatus rtc_deinit(void); diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h index bd3b2c8fc6..a18214c023 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_sdio.h - \brief definitions for the SDIO + \file gd32f4xx_sdio.h + \brief definitions for the SDIO + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_SDIO_H @@ -179,7 +204,7 @@ #define SDIO_FLAG_SDIOINT BIT(22) /*!< SD I/O interrupt received flag */ #define SDIO_FLAG_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) flag */ -/* SDIO interrupt flags */ +/* SDIO interrupt enable or disable */ #define SDIO_INT_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt */ #define SDIO_INT_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt */ #define SDIO_INT_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt */ @@ -205,6 +230,32 @@ #define SDIO_INT_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt */ #define SDIO_INT_ATAEND BIT(23) /*!< SDIO ATAEND interrupt */ +/* SDIO interrupt flags */ +#define SDIO_INT_FLAG_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt flag */ +#define SDIO_INT_FLAG_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt flag */ +#define SDIO_INT_FLAG_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt flag */ +#define SDIO_INT_FLAG_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt flag */ +#define SDIO_INT_FLAG_TXURE BIT(4) /*!< SDIO TXURE interrupt flag */ +#define SDIO_INT_FLAG_RXORE BIT(5) /*!< SDIO RXORE interrupt flag */ +#define SDIO_INT_FLAG_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt flag */ +#define SDIO_INT_FLAG_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt flag */ +#define SDIO_INT_FLAG_DTEND BIT(8) /*!< SDIO DTEND interrupt flag */ +#define SDIO_INT_FLAG_STBITE BIT(9) /*!< SDIO STBITE interrupt flag */ +#define SDIO_INT_FLAG_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt flag */ +#define SDIO_INT_FLAG_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt flag */ +#define SDIO_INT_FLAG_TXRUN BIT(12) /*!< SDIO TXRUN interrupt flag */ +#define SDIO_INT_FLAG_RXRUN BIT(13) /*!< SDIO RXRUN interrupt flag */ +#define SDIO_INT_FLAG_TFH BIT(14) /*!< SDIO TFH interrupt flag */ +#define SDIO_INT_FLAG_RFH BIT(15) /*!< SDIO RFH interrupt flag */ +#define SDIO_INT_FLAG_TFF BIT(16) /*!< SDIO TFF interrupt flag */ +#define SDIO_INT_FLAG_RFF BIT(17) /*!< SDIO RFF interrupt flag */ +#define SDIO_INT_FLAG_TFE BIT(18) /*!< SDIO TFE interrupt flag */ +#define SDIO_INT_FLAG_RFE BIT(19) /*!< SDIO RFE interrupt flag */ +#define SDIO_INT_FLAG_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt flag */ +#define SDIO_INT_FLAG_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt flag */ +#define SDIO_INT_FLAG_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt flag */ +#define SDIO_INT_FLAG_ATAEND BIT(23) /*!< SDIO ATAEND interrupt flag */ + /* SDIO power control */ #define PWRCTL_PWRCTL(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) #define SDIO_POWER_OFF PWRCTL_PWRCTL(0) /*!< SDIO power off */ @@ -275,6 +326,7 @@ #define SDIO_READWAITTYPE_CLK SDIO_DATACTL_RWTYPE /*!< read wait control by stopping SDIO_CLK */ /* function declarations */ +/* de/initialization functions, hardware clock, bus mode, power_state and SDIO clock configuration */ /* deinitialize the SDIO */ void sdio_deinit(void); /* configure the SDIO clock */ @@ -294,7 +346,7 @@ void sdio_clock_enable(void); /* disable SDIO_CLK clock output */ void sdio_clock_disable(void); -/* configure the command index, argument, response type, wait type and CSM to send command */ +/* configure the command index, argument, response type, wait type and CSM to send command functions */ /* configure the command and response */ void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type); /* set the command state machine wait type */ @@ -308,7 +360,7 @@ uint8_t sdio_command_index_get(void); /* get the response for the last received command */ uint32_t sdio_response_get(uint32_t sdio_responsex); -/* configure the data timeout, length, block size, transfer mode, direction and DSM for data transfer */ +/* configure the data timeout, length, block size, transfer mode, direction and DSM for data transfer functions */ /* configure the data timeout, data length and data block size */ void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize); /* configure the data transfer mode and direction */ @@ -330,6 +382,7 @@ void sdio_dma_enable(void); /* disable the DMA request for SDIO */ void sdio_dma_disable(void); +/* flag and interrupt functions */ /* get the flags state of SDIO */ FlagStatus sdio_flag_get(uint32_t flag); /* clear the pending flags of SDIO */ @@ -343,6 +396,7 @@ FlagStatus sdio_interrupt_flag_get(uint32_t int_flag); /* clear the interrupt pending flags of SDIO */ void sdio_interrupt_flag_clear(uint32_t int_flag); +/* SD I/O card functions */ /* enable the read wait mode(SD I/O only) */ void sdio_readwait_enable(void); /* disable the read wait mode(SD I/O only) */ @@ -362,6 +416,7 @@ void sdio_suspend_enable(void); /* disable the SD I/O suspend operation(SD I/O only) */ void sdio_suspend_disable(void); +/* CE-ATA functions */ /* enable the CE-ATA command(CE-ATA only) */ void sdio_ceata_command_enable(void); /* disable the CE-ATA command(CE-ATA only) */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h index 422df94a6f..61bf8b1af2 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h @@ -1,14 +1,40 @@ /*! - \file gd32f4xx_spi.h - \brief definitions for the SPI + \file gd32f4xx_spi.h + \brief definitions for the SPI + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ + #ifndef GD32F4XX_SPI_H #define GD32F4XX_SPI_H @@ -50,7 +76,7 @@ #define I2S_ADD_I2SPSC(i2sx_add) REG32((i2sx_add) + 0x20U) /*!< I2S_ADD I2S clock prescaler register */ /* bits definitions */ -/* SPIx_CTL0 */ +/* SPI_CTL0 */ #define SPI_CTL0_CKPH BIT(0) /*!< clock phase selection*/ #define SPI_CTL0_CKPL BIT(1) /*!< clock polarity selection */ #define SPI_CTL0_MSTMOD BIT(2) /*!< master mode enable */ @@ -66,7 +92,7 @@ #define SPI_CTL0_BDOEN BIT(14) /*!< bidirectional transmit output enable*/ #define SPI_CTL0_BDEN BIT(15) /*!< bidirectional enable */ -/* SPIx_CTL1 */ +/* SPI_CTL1 */ #define SPI_CTL1_DMAREN BIT(0) /*!< receive buffer dma enable */ #define SPI_CTL1_DMATEN BIT(1) /*!< transmit buffer dma enable */ #define SPI_CTL1_NSSDRV BIT(2) /*!< drive nss output */ @@ -75,16 +101,16 @@ #define SPI_CTL1_RBNEIE BIT(6) /*!< receive buffer not empty interrupt enable */ #define SPI_CTL1_TBEIE BIT(7) /*!< transmit buffer empty interrupt enable */ -/* SPIx_STAT */ +/* SPI_STAT */ #define SPI_STAT_RBNE BIT(0) /*!< receive buffer not empty */ #define SPI_STAT_TBE BIT(1) /*!< transmit buffer empty */ #define SPI_STAT_I2SCH BIT(2) /*!< I2S channel side */ #define SPI_STAT_TXURERR BIT(3) /*!< I2S transmission underrun error bit */ #define SPI_STAT_CRCERR BIT(4) /*!< SPI CRC error bit */ -#define SPI_STAT_CONFERR BIT(5) /*!< SPI configuration error */ -#define SPI_STAT_RXORERR BIT(6) /*!< SPI reception overrun error Bit */ -#define SPI_STAT_TRANS BIT(7) /*!< transmitting on-going Bit */ -#define SPI_STAT_FERR BIT(8) /*!< format error */ +#define SPI_STAT_CONFERR BIT(5) /*!< SPI configuration error bit */ +#define SPI_STAT_RXORERR BIT(6) /*!< SPI reception overrun error bit */ +#define SPI_STAT_TRANS BIT(7) /*!< transmitting on-going bit */ +#define SPI_STAT_FERR BIT(8) /*!< format error bit */ /* SPI_DATA */ #define SPI_DATA_DATA BITS(0,15) /*!< data transfer register */ @@ -96,9 +122,9 @@ #define SPI_RCRC_RCR BITS(0,15) /*!< RX CRC register */ /* SPI_TCRC */ -#define SPI_TCRC_TCR BITS(0,15) /*!< RX CRC register */ +#define SPI_TCRC_TCR BITS(0,15) /*!< TX CRC register */ -/* SPIx_I2SCTL */ +/* SPI_I2SCTL */ #define SPI_I2SCTL_CHLEN BIT(0) /*!< channel length */ #define SPI_I2SCTL_DTLEN BITS(1,2) /*!< data length */ #define SPI_I2SCTL_CKPL BIT(3) /*!< idle state clock polarity */ @@ -108,12 +134,12 @@ #define SPI_I2SCTL_I2SEN BIT(10) /*!< I2S enable */ #define SPI_I2SCTL_I2SSEL BIT(11) /*!< I2S mode selection */ -/* SPIx_I2S_PSC */ +/* SPI_I2S_PSC */ #define SPI_I2SPSC_DIV BITS(0,7) /*!< dividing factor for the prescaler */ #define SPI_I2SPSC_OF BIT(8) /*!< odd factor for the prescaler */ #define SPI_I2SPSC_MCKOEN BIT(9) /*!< I2S MCK output enable */ -/* SPIx_SPI_QCTL(only SPI5) */ +/* SPI_SPI_QCTL(only SPI5) */ #define SPI_QCTL_QMOD BIT(0) /*!< quad-SPI mode enable */ #define SPI_QCTL_QRD BIT(1) /*!< quad-SPI mode read select */ #define SPI_QCTL_IO23_DRV BIT(2) /*!< drive SPI_IO2 and SPI_IO3 enable */ @@ -121,7 +147,7 @@ /* constants definitions */ /* SPI and I2S parameter struct definitions */ typedef struct -{ +{ uint32_t device_mode; /*!< SPI master or slave */ uint32_t trans_mode; /*!< SPI transtype */ uint32_t frame_size; /*!< SPI frame size */ @@ -131,32 +157,39 @@ typedef struct uint32_t prescale; /*!< SPI prescale factor */ }spi_parameter_struct; -/* SPI struct parameter options */ +/* SPI mode definitions */ #define SPI_MASTER (SPI_CTL0_MSTMOD | SPI_CTL0_SWNSS) /*!< SPI as master */ #define SPI_SLAVE ((uint32_t)0x00000000U) /*!< SPI as slave */ -#define SPI_BIDIRECTIONAL_TEANSMIT SPI_CTL0_BDOEN /*!< SPI work in transmit-only mode */ -#define SPI_BIDIRECTIONAL_RECEIVE ~SPI_CTL0_BDOEN /*!< SPI work in receive-only mode */ +/* SPI bidirectional transfer direction */ +#define SPI_BIDIRECTIONAL_TRANSMIT SPI_CTL0_BDOEN /*!< SPI work in transmit-only mode */ +#define SPI_BIDIRECTIONAL_RECEIVE (~SPI_CTL0_BDOEN) /*!< SPI work in receive-only mode */ +/* SPI transmit type */ #define SPI_TRANSMODE_FULLDUPLEX ((uint32_t)0x00000000U) /*!< SPI receive and send data at fullduplex communication */ #define SPI_TRANSMODE_RECEIVEONLY SPI_CTL0_RO /*!< SPI only receive data */ #define SPI_TRANSMODE_BDRECEIVE SPI_CTL0_BDEN /*!< bidirectional receive data */ #define SPI_TRANSMODE_BDTRANSMIT (SPI_CTL0_BDEN | SPI_CTL0_BDOEN) /*!< bidirectional transmit data*/ +/* SPI frame size */ #define SPI_FRAMESIZE_16BIT SPI_CTL0_FF16 /*!< SPI frame size is 16 bits */ #define SPI_FRAMESIZE_8BIT ((uint32_t)0x00000000U) /*!< SPI frame size is 8 bits */ +/* SPI NSS control mode */ #define SPI_NSS_SOFT SPI_CTL0_SWNSSEN /*!< SPI nss control by sofrware */ #define SPI_NSS_HARD ((uint32_t)0x00000000U) /*!< SPI nss control by hardware */ -#define SPI_ENDIAN_MSB ((uint32_t)0x00000000U) /*!< SPI transmit way is big endian:transmit MSB first */ -#define SPI_ENDIAN_LSB SPI_CTL0_LF /*!< SPI transmit way is little endian:transmit LSB first */ +/* SPI transmit way */ +#define SPI_ENDIAN_MSB ((uint32_t)0x00000000U) /*!< SPI transmit way is big endian: transmit MSB first */ +#define SPI_ENDIAN_LSB SPI_CTL0_LF /*!< SPI transmit way is little endian: transmit LSB first */ +/* SPI clock polarity and phase */ #define SPI_CK_PL_LOW_PH_1EDGE ((uint32_t)0x00000000U) /*!< SPI clock polarity is low level and phase is first edge */ #define SPI_CK_PL_HIGH_PH_1EDGE SPI_CTL0_CKPL /*!< SPI clock polarity is high level and phase is first edge */ #define SPI_CK_PL_LOW_PH_2EDGE SPI_CTL0_CKPH /*!< SPI clock polarity is low level and phase is second edge */ #define SPI_CK_PL_HIGH_PH_2EDGE (SPI_CTL0_CKPL|SPI_CTL0_CKPH) /*!< SPI clock polarity is high level and phase is second edge */ +/* SPI clock prescale factor */ #define CTL0_PSC(regval) (BITS(3,5)&((uint32_t)(regval)<<3)) #define SPI_PSC_2 CTL0_PSC(0) /*!< SPI clock prescale factor is 2 */ #define SPI_PSC_4 CTL0_PSC(1) /*!< SPI clock prescale factor is 4 */ @@ -167,118 +200,171 @@ typedef struct #define SPI_PSC_128 CTL0_PSC(6) /*!< SPI clock prescale factor is 128 */ #define SPI_PSC_256 CTL0_PSC(7) /*!< SPI clock prescale factor is 256 */ -/* I2S parameter options */ -#define I2S_AUDIOSAMPLE_8K ((uint32_t)8000U) /*!< I2S audio sample rate is 8khz */ -#define I2S_AUDIOSAMPLE_11K ((uint32_t)11025U) /*!< I2S audio sample rate is 11khz */ -#define I2S_AUDIOSAMPLE_16K ((uint32_t)16000U) /*!< I2S audio sample rate is 16khz */ -#define I2S_AUDIOSAMPLE_22K ((uint32_t)22050U) /*!< I2S audio sample rate is 22khz */ -#define I2S_AUDIOSAMPLE_32K ((uint32_t)32000U) /*!< I2S audio sample rate is 32khz */ -#define I2S_AUDIOSAMPLE_44K ((uint32_t)44100U) /*!< I2S audio sample rate is 44khz */ -#define I2S_AUDIOSAMPLE_48K ((uint32_t)48000U) /*!< I2S audio sample rate is 48khz */ -#define I2S_AUDIOSAMPLE_96K ((uint32_t)96000U) /*!< I2S audio sample rate is 96khz */ -#define I2S_AUDIOSAMPLE_192K ((uint32_t)192000U) /*!< I2S audio sample rate is 192khz */ +/* I2S audio sample rate */ +#define I2S_AUDIOSAMPLE_8K ((uint32_t)8000U) /*!< I2S audio sample rate is 8KHz */ +#define I2S_AUDIOSAMPLE_11K ((uint32_t)11025U) /*!< I2S audio sample rate is 11KHz */ +#define I2S_AUDIOSAMPLE_16K ((uint32_t)16000U) /*!< I2S audio sample rate is 16KHz */ +#define I2S_AUDIOSAMPLE_22K ((uint32_t)22050U) /*!< I2S audio sample rate is 22KHz */ +#define I2S_AUDIOSAMPLE_32K ((uint32_t)32000U) /*!< I2S audio sample rate is 32KHz */ +#define I2S_AUDIOSAMPLE_44K ((uint32_t)44100U) /*!< I2S audio sample rate is 44KHz */ +#define I2S_AUDIOSAMPLE_48K ((uint32_t)48000U) /*!< I2S audio sample rate is 48KHz */ +#define I2S_AUDIOSAMPLE_96K ((uint32_t)96000U) /*!< I2S audio sample rate is 96KHz */ +#define I2S_AUDIOSAMPLE_192K ((uint32_t)192000U) /*!< I2S audio sample rate is 192KHz */ +/* I2S frame format */ #define I2SCTL_DTLEN(regval) (BITS(1,2)&((uint32_t)(regval)<<1)) #define I2S_FRAMEFORMAT_DT16B_CH16B I2SCTL_DTLEN(0) /*!< I2S data length is 16 bit and channel length is 16 bit */ #define I2S_FRAMEFORMAT_DT16B_CH32B (I2SCTL_DTLEN(0)|SPI_I2SCTL_CHLEN) /*!< I2S data length is 16 bit and channel length is 32 bit */ #define I2S_FRAMEFORMAT_DT24B_CH32B (I2SCTL_DTLEN(1)|SPI_I2SCTL_CHLEN) /*!< I2S data length is 24 bit and channel length is 32 bit */ #define I2S_FRAMEFORMAT_DT32B_CH32B (I2SCTL_DTLEN(2)|SPI_I2SCTL_CHLEN) /*!< I2S data length is 32 bit and channel length is 32 bit */ - + +/* I2S master clock output */ #define I2S_MCKOUT_DISABLE ((uint32_t)0x00000000U) /*!< I2S master clock output disable */ #define I2S_MCKOUT_ENABLE SPI_I2SPSC_MCKOEN /*!< I2S master clock output enable */ - + +/* I2S operation mode */ #define I2SCTL_I2SOPMOD(regval) (BITS(8,9)&((uint32_t)(regval)<<8)) #define I2S_MODE_SLAVETX I2SCTL_I2SOPMOD(0) /*!< I2S slave transmit mode */ #define I2S_MODE_SLAVERX I2SCTL_I2SOPMOD(1) /*!< I2S slave receive mode */ #define I2S_MODE_MASTERTX I2SCTL_I2SOPMOD(2) /*!< I2S master transmit mode */ #define I2S_MODE_MASTERRX I2SCTL_I2SOPMOD(3) /*!< I2S master receive mode */ +/* I2S standard */ #define I2SCTL_I2SSTD(regval) (BITS(4,5)&((uint32_t)(regval)<<4)) #define I2S_STD_PHILLIPS I2SCTL_I2SSTD(0) /*!< I2S phillips standard */ #define I2S_STD_MSB I2SCTL_I2SSTD(1) /*!< I2S MSB standard */ #define I2S_STD_LSB I2SCTL_I2SSTD(2) /*!< I2S LSB standard */ #define I2S_STD_PCMSHORT I2SCTL_I2SSTD(3) /*!< I2S PCM short standard */ -#define I2S_STD_PCMLONG (I2SCTL_I2SSTD(3)|SPI_I2SCTL_PCMSMOD) /*!< I2S PCM long standard */ +#define I2S_STD_PCMLONG (I2SCTL_I2SSTD(3) | SPI_I2SCTL_PCMSMOD) /*!< I2S PCM long standard */ +/* I2S clock polarity */ #define I2S_CKPL_LOW ((uint32_t)0x00000000U) /*!< I2S clock polarity low level */ #define I2S_CKPL_HIGH SPI_I2SCTL_CKPL /*!< I2S clock polarity high level */ -/* SPI dma constants definitions */ -#define SPI_DMA_TRANSMIT ((uint8_t)0x00U) /*!< SPI transmit data DMA */ -#define SPI_DMA_RECEIVE ((uint8_t)0x01U) /*!< SPI receive data DMA */ +/* SPI DMA constants definitions */ +#define SPI_DMA_TRANSMIT ((uint8_t)0x00U) /*!< SPI transmit data use DMA */ +#define SPI_DMA_RECEIVE ((uint8_t)0x01U) /*!< SPI receive data use DMA */ /* SPI CRC constants definitions */ #define SPI_CRC_TX ((uint8_t)0x00U) /*!< SPI transmit CRC value */ #define SPI_CRC_RX ((uint8_t)0x01U) /*!< SPI receive CRC value */ -/* SPI interrupt constants definitions */ +/* SPI/I2S interrupt enable/disable constants definitions */ #define SPI_I2S_INT_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt */ #define SPI_I2S_INT_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt */ -#define SPI_I2S_INT_RXORERR ((uint8_t)0x02U) /*!< overrun interrupt */ -#define SPI_INT_CONFERR ((uint8_t)0x03U) /*!< config error interrupt */ -#define SPI_INT_CRCERR ((uint8_t)0x04U) /*!< CRC error interrupt */ -#define I2S_INT_TXURERR ((uint8_t)0x05U) /*!< underrun error interrupt */ -#define SPI_I2S_INT_ERR ((uint8_t)0x06U) /*!< error interrupt */ -#define SPI_I2S_INT_FERR ((uint8_t)0x07U) /*!< format error interrupt */ +#define SPI_I2S_INT_ERR ((uint8_t)0x02U) /*!< error interrupt */ -/* SPI flag definitions */ +/* SPI/I2S interrupt flag constants definitions */ +#define SPI_I2S_INT_FLAG_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RXORERR ((uint8_t)0x02U) /*!< overrun interrupt flag */ +#define SPI_INT_FLAG_CONFERR ((uint8_t)0x03U) /*!< config error interrupt flag */ +#define SPI_INT_FLAG_CRCERR ((uint8_t)0x04U) /*!< CRC error interrupt flag */ +#define I2S_INT_FLAG_TXURERR ((uint8_t)0x05U) /*!< underrun error interrupt flag */ +#define SPI_I2S_INT_FLAG_FERR ((uint8_t)0x06U) /*!< format error interrupt flag */ + +/* SPI/I2S flag definitions */ #define SPI_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ #define SPI_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ #define SPI_FLAG_CRCERR SPI_STAT_CRCERR /*!< CRC error flag */ #define SPI_FLAG_CONFERR SPI_STAT_CONFERR /*!< mode config error flag */ -#define SPI_FLAG_RXORERR SPI_STAT_RXORERR /*!< receive overrun flag */ +#define SPI_FLAG_RXORERR SPI_STAT_RXORERR /*!< receive overrun error flag */ #define SPI_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ -#define SPI_FLAG_FERR SPI_STAT_FERR /*!< format error interrupt flag */ +#define SPI_FLAG_FERR SPI_STAT_FERR /*!< format error flag */ #define I2S_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ #define I2S_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ -#define I2S_FLAG_CH SPI_STAT_I2SCH /*!< transmit buffer empty interrupt */ +#define I2S_FLAG_CH SPI_STAT_I2SCH /*!< channel side flag */ #define I2S_FLAG_TXURERR SPI_STAT_TXURERR /*!< underrun error flag */ -#define I2S_FLAG_RXORERR SPI_STAT_RXORERR /*!< overrun flag */ +#define I2S_FLAG_RXORERR SPI_STAT_RXORERR /*!< overrun error flag */ #define I2S_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ -#define I2S_FLAG_FERR SPI_STAT_FERR /*!< format error interrupt flag */ +#define I2S_FLAG_FERR SPI_STAT_FERR /*!< format error flag */ /* function declarations */ -/* SPI and I2S reset */ +/* initialization functions */ +/* deinitialize SPI and I2S */ void spi_i2s_deinit(uint32_t spi_periph); -/* SPI parameter initialization */ +/* initialize the parameters of SPI struct with the default values */ +void spi_struct_para_init(spi_parameter_struct* spi_struct); +/* initialize SPI parameter */ void spi_init(uint32_t spi_periph,spi_parameter_struct* spi_struct); -/* SPI enable */ +/* enable SPI */ void spi_enable(uint32_t spi_periph); -/* SPI disable */ +/* disable SPI */ void spi_disable(uint32_t spi_periph); -/* I2S parameter initialization */ +/* initialize I2S parameter */ void i2s_init(uint32_t spi_periph,uint32_t i2s_mode,uint32_t i2s_standard,uint32_t i2s_ckpl); -/* I2S prescale configuration */ +/* configure I2S prescale */ void i2s_psc_config(uint32_t spi_periph,uint32_t i2s_audiosample,uint32_t i2s_frameformat,uint32_t i2s_mckout); -/* I2S enable */ +/* enable I2S */ void i2s_enable(uint32_t spi_periph); -/* I2S disable */ +/* disable I2S */ void i2s_disable(uint32_t spi_periph); -/* SPI nss output enable */ +/* NSS functions */ +/* enable SPI nss output */ void spi_nss_output_enable(uint32_t spi_periph); -/* SPI nss output disable */ +/* disable SPI nss output */ void spi_nss_output_disable(uint32_t spi_periph); /* SPI nss pin high level in software mode */ void spi_nss_internal_high(uint32_t spi_periph); /* SPI nss pin low level in software mode */ void spi_nss_internal_low(uint32_t spi_periph); -/* SPI dma enable */ +/* SPI DMA functions */ +/* enable SPI DMA */ void spi_dma_enable(uint32_t spi_periph,uint8_t spi_dma); -/* SPI dma disable */ +/* disable SPI DMA */ void spi_dma_disable(uint32_t spi_periph,uint8_t spi_dma); +/* SPI/I2S transfer configure functions */ /* configure SPI/I2S data frame format */ void spi_i2s_data_frame_format_config(uint32_t spi_periph,uint16_t frame_format); -/* transmit data */ +/* SPI transmit data */ void spi_i2s_data_transmit(uint32_t spi_periph,uint16_t data); -/* receive data */ +/* SPI receive data */ uint16_t spi_i2s_data_receive(uint32_t spi_periph); /* configure SPI bidirectional transfer direction */ void spi_bidirectional_transfer_config(uint32_t spi_periph,uint32_t transfer_direction); +/* SPI CRC functions */ +/* set SPI CRC polynomial */ +void spi_crc_polynomial_set(uint32_t spi_periph,uint16_t crc_poly); +/* get SPI CRC polynomial */ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph); +/* turn on SPI CRC function */ +void spi_crc_on(uint32_t spi_periph); +/* turn off SPI CRC function */ +void spi_crc_off(uint32_t spi_periph); +/* SPI next data is CRC value */ +void spi_crc_next(uint32_t spi_periph); +/* get SPI CRC send value or receive value */ +uint16_t spi_crc_get(uint32_t spi_periph,uint8_t spi_crc); + +/* SPI TI mode functions */ +/* enable SPI TI mode */ +void spi_ti_mode_enable(uint32_t spi_periph); +/* disable SPI TI mode */ +void spi_ti_mode_disable(uint32_t spi_periph); + +/* configure i2s full duplex mode */ +void i2s_full_duplex_mode_config(uint32_t i2s_add_periph,uint32_t i2s_mode,uint32_t i2s_standard,uint32_t i2s_ckpl,uint32_t i2s_frameformat); + +/* quad wire SPI functions */ +/* enable quad wire SPI */ +void qspi_enable(uint32_t spi_periph); +/* disable quad wire SPI */ +void qspi_disable(uint32_t spi_periph); +/* enable quad wire SPI write */ +void qspi_write_enable(uint32_t spi_periph); +/* enable quad wire SPI read */ +void qspi_read_enable(uint32_t spi_periph); +/* enable quad wire SPI_IO2 and SPI_IO3 pin output */ +void qspi_io23_output_enable(uint32_t spi_periph); +/* disable quad wire SPI_IO2 and SPI_IO3 pin output */ +void qspi_io23_output_disable(uint32_t spi_periph); + +/* flag & interrupt functions */ /* enable SPI interrupt */ void spi_i2s_interrupt_enable(uint32_t spi_periph,uint8_t spi_i2s_int); /* disable SPI interrupt */ @@ -290,38 +376,4 @@ FlagStatus spi_i2s_flag_get(uint32_t spi_periph,uint32_t spi_i2s_flag); /* clear SPI CRC error flag status */ void spi_crc_error_clear(uint32_t spi_periph); -/* SPI CRC polynomial set */ -void spi_crc_polynomial_set(uint32_t spi_periph,uint16_t crc_poly); -/* SPI CRC polynomial get */ -uint16_t spi_crc_polynomial_get(uint32_t spi_periph); -/* SPI CRC function turn on */ -void spi_crc_on(uint32_t spi_periph); -/* SPI CRC function turn off */ -void spi_crc_off(uint32_t spi_periph); -/* SPI next data is CRC value */ -void spi_crc_next(uint32_t spi_periph); -/* get SPI CRC send value or receive value */ -uint16_t spi_crc_get(uint32_t spi_periph,uint8_t spi_crc); - -/* SPI TI mode enable */ -void spi_ti_mode_enable(uint32_t spi_periph); -/* SPI TI mode disable */ -void spi_ti_mode_disable(uint32_t spi_periph); - -/* configure i2s full duplex mode */ -void i2s_full_duplex_mode_config(uint32_t i2s_add_periph,uint32_t i2s_mode,uint32_t i2s_standard,uint32_t i2s_ckpl,uint32_t i2s_frameformat); - -/* quad wire SPI enable */ -void qspi_enable(uint32_t spi_periph); -/* quad wire SPI disable */ -void qspi_disable(uint32_t spi_periph); -/* quad wire SPI write enable */ -void qspi_write_enable(uint32_t spi_periph); -/* quad wire SPI read enable */ -void qspi_read_enable(uint32_t spi_periph); -/* quad wire SPI_IO2 and SPI_IO3 pin output enable */ -void qspi_io23_output_enable(uint32_t spi_periph); -/* quad wire SPI_IO2 and SPI_IO3 pin output disable */ -void qspi_io23_output_disable(uint32_t spi_periph); - #endif /* GD32F4XX_SPI_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h index 42ae5599c7..047910478a 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_syscfg.h - \brief definitions for the SYSCFG + \file gd32f4xx_syscfg.h + \brief definitions for the SYSCFG + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_SYSCFG_H @@ -85,13 +110,13 @@ #define EXTISS3 ((uint8_t)0x03U) /*!< EXTI source select GPIOx pin 12~15 */ /* EXTI source select mask bits definition */ -#define EXTI_SS_MASK BITS(0,3) +#define EXTI_SS_MASK BITS(0,3) /*!< EXTI source select mask */ /* EXTI source select jumping step definition */ -#define EXTI_SS_JSTEP ((uint8_t)(0x04U)) +#define EXTI_SS_JSTEP ((uint8_t)(0x04U)) /*!< EXTI source select jumping step */ /* EXTI source select moving step definition */ -#define EXTI_SS_MSTEP(pin) (EXTI_SS_JSTEP*((pin)%EXTI_SS_JSTEP)) +#define EXTI_SS_MSTEP(pin) (EXTI_SS_JSTEP*((pin)%EXTI_SS_JSTEP)) /*!< EXTI source select moving step */ /* EXTI source port definitions */ #define EXTI_SOURCE_GPIOA ((uint8_t)0x00U) /*!< EXTI GPIOA configuration */ @@ -123,35 +148,33 @@ #define EXTI_SOURCE_PIN15 ((uint8_t)0x0FU) /*!< EXTI GPIO pin15 configuration */ /* ethernet PHY selection */ -#define SYSCFG_ENET_PHY_MII ((uint32_t)0x00000000U) -#define SYSCFG_ENET_PHY_RMII ((uint32_t)0x00800000U) +#define SYSCFG_ENET_PHY_MII ((uint32_t)0x00000000U) /*!< MII is selected for the Ethernet MAC */ +#define SYSCFG_ENET_PHY_RMII ((uint32_t)0x00800000U) /*!< RMII is selected for the Ethernet MAC */ /* I/O compensation cell enable/disable */ -#define SYSCFG_COMPENSATION_ENABLE ((uint32_t)0x00000001U) -#define SYSCFG_COMPENSATION_DISABLE ((uint32_t)0x00000000U) +#define SYSCFG_COMPENSATION_ENABLE ((uint32_t)0x00000001U) /*!< I/O compensation cell enable */ +#define SYSCFG_COMPENSATION_DISABLE ((uint32_t)0x00000000U) /*!< I/O compensation cell disable */ /* function declarations */ +/* initialization functions */ /* deinit syscfg module */ void syscfg_deinit(void); +/* function configuration */ /* configure the boot mode */ void syscfg_bootmode_config(uint8_t syscfg_bootmode); - -/* FMC memory mapping swap */ +/* configure FMC memory mapping swap */ void syscfg_fmc_swap_config(uint32_t syscfg_fmc_swap); - /* configure the EXMC swap */ -void syscfg_exmc_swap_config(uint32_t syscfg_exmc_swap); - +void syscfg_exmc_swap_config(uint32_t syscfg_exmc_swap); /* configure the GPIO pin as EXTI Line */ void syscfg_exti_line_config(uint8_t exti_port, uint8_t exti_pin); - /* configure the PHY interface for the ethernet MAC */ void syscfg_enet_phy_interface_config(uint32_t syscfg_enet_phy_interface); - /* configure the I/O compensation cell */ -void syscfg_compensation_config(uint32_t syscfg_compensation); +void syscfg_compensation_config(uint32_t syscfg_compensation); +/* interrupt & flag functions */ /* check the I/O compensation cell is ready or not */ FlagStatus syscfg_flag_get(void); diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h index e856ec03ac..9da6e12bdd 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h @@ -1,12 +1,38 @@ /*! - \file gd32f4xx_timer.h - \brief definitions for the TIMER + \file gd32f4xx_timer.h + \brief definitions for the TIMER + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. + All rights reserved. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_TIMER_H @@ -66,8 +92,8 @@ #define TIMER_CTL0_CKDIV BITS(8,9) /*!< clock division */ /* TIMER_CTL1 */ -#define TIMER_CTL1_CCSE BIT(0) /*!< capture/compare control shadow register enable */ -#define TIMER_CTL1_CCUC BIT(2) /*!< capture/compare control shadow register update control */ +#define TIMER_CTL1_CCSE BIT(0) /*!< commutation control shadow enable */ +#define TIMER_CTL1_CCUC BIT(2) /*!< commutation control shadow register update control */ #define TIMER_CTL1_DMAS BIT(3) /*!< DMA request source selection */ #define TIMER_CTL1_MMC BITS(4,6) /*!< master mode control */ #define TIMER_CTL1_TI0S BIT(7) /*!< channel 0 trigger input selection(hall mode selection) */ @@ -87,30 +113,30 @@ #define TIMER_SMCFG_ETPSC BITS(12,13) /*!< external trigger prescaler */ #define TIMER_SMCFG_SMC1 BIT(14) /*!< part of SMC for enable external clock mode 1 */ #define TIMER_SMCFG_ETP BIT(15) /*!< external trigger polarity */ - + /* TIMER_DMAINTEN */ #define TIMER_DMAINTEN_UPIE BIT(0) /*!< update interrupt enable */ -#define TIMER_DMAINTEN_CH0IE BIT(1) /*!< channel 0 interrupt enable */ -#define TIMER_DMAINTEN_CH1IE BIT(2) /*!< channel 1 interrupt enable */ -#define TIMER_DMAINTEN_CH2IE BIT(3) /*!< channel 2 interrupt enable */ -#define TIMER_DMAINTEN_CH3IE BIT(4) /*!< channel 3 interrupt enable */ -#define TIMER_DMAINTEN_CMTIE BIT(5) /*!< commutation DMA request enable */ +#define TIMER_DMAINTEN_CH0IE BIT(1) /*!< channel 0 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH1IE BIT(2) /*!< channel 1 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH2IE BIT(3) /*!< channel 2 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH3IE BIT(4) /*!< channel 3 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CMTIE BIT(5) /*!< commutation interrupt request enable */ #define TIMER_DMAINTEN_TRGIE BIT(6) /*!< trigger interrupt enable */ #define TIMER_DMAINTEN_BRKIE BIT(7) /*!< break interrupt enable */ #define TIMER_DMAINTEN_UPDEN BIT(8) /*!< update DMA request enable */ -#define TIMER_DMAINTEN_CH0DEN BIT(8) /*!< channel 0 DMA request enable */ +#define TIMER_DMAINTEN_CH0DEN BIT(9) /*!< channel 0 DMA request enable */ #define TIMER_DMAINTEN_CH1DEN BIT(10) /*!< channel 1 DMA request enable */ #define TIMER_DMAINTEN_CH2DEN BIT(11) /*!< channel 2 DMA request enable */ #define TIMER_DMAINTEN_CH3DEN BIT(12) /*!< channel 3 DMA request enable */ -#define TIMER_DMAINTEN_CMTDEN BIT(13) /*!< channel control update DMA request enable */ +#define TIMER_DMAINTEN_CMTDEN BIT(13) /*!< commutation DMA request enable */ #define TIMER_DMAINTEN_TRGDEN BIT(14) /*!< trigger DMA request enable */ /* TIMER_INTF */ #define TIMER_INTF_UPIF BIT(0) /*!< update interrupt flag */ -#define TIMER_INTF_CH0IF BIT(1) /*!< channel 0 interrupt flag */ -#define TIMER_INTF_CH1IF BIT(2) /*!< channel 1 interrupt flag */ -#define TIMER_INTF_CH2IF BIT(3) /*!< channel 2 interrupt flag */ -#define TIMER_INTF_CH3IF BIT(4) /*!< channel 3 interrupt flag */ +#define TIMER_INTF_CH0IF BIT(1) /*!< channel 0 capture/compare interrupt flag */ +#define TIMER_INTF_CH1IF BIT(2) /*!< channel 1 capture/compare interrupt flag */ +#define TIMER_INTF_CH2IF BIT(3) /*!< channel 2 capture/compare interrupt flag */ +#define TIMER_INTF_CH3IF BIT(4) /*!< channel 3 capture/compare interrupt flag */ #define TIMER_INTF_CMTIF BIT(5) /*!< channel commutation interrupt flag */ #define TIMER_INTF_TRGIF BIT(6) /*!< trigger interrupt flag */ #define TIMER_INTF_BRKIF BIT(7) /*!< break interrupt flag */ @@ -166,20 +192,20 @@ #define TIMER_CHCTL1_CH3CAPFLT BITS(12,15) /*!< channel 3 input capture filter control */ /* TIMER_CHCTL2 */ -#define TIMER_CHCTL2_CH0EN BIT(0) /*!< channel 0 enable */ -#define TIMER_CHCTL2_CH0P BIT(1) /*!< channel 0 polarity */ +#define TIMER_CHCTL2_CH0EN BIT(0) /*!< channel 0 capture/compare function enable */ +#define TIMER_CHCTL2_CH0P BIT(1) /*!< channel 0 capture/compare function polarity */ #define TIMER_CHCTL2_CH0NEN BIT(2) /*!< channel 0 complementary output enable */ #define TIMER_CHCTL2_CH0NP BIT(3) /*!< channel 0 complementary output polarity */ -#define TIMER_CHCTL2_CH1EN BIT(4) /*!< channel 1 enable */ -#define TIMER_CHCTL2_CH1P BIT(5) /*!< channel 1 polarity */ +#define TIMER_CHCTL2_CH1EN BIT(4) /*!< channel 1 capture/compare function enable */ +#define TIMER_CHCTL2_CH1P BIT(5) /*!< channel 1 capture/compare function polarity */ #define TIMER_CHCTL2_CH1NEN BIT(6) /*!< channel 1 complementary output enable */ #define TIMER_CHCTL2_CH1NP BIT(7) /*!< channel 1 complementary output polarity */ -#define TIMER_CHCTL2_CH2EN BIT(8) /*!< channel 2 enable */ -#define TIMER_CHCTL2_CH2P BIT(9) /*!< channel 2 polarity */ +#define TIMER_CHCTL2_CH2EN BIT(8) /*!< channel 2 capture/compare function enable */ +#define TIMER_CHCTL2_CH2P BIT(9) /*!< channel 2 capture/compare function polarity */ #define TIMER_CHCTL2_CH2NEN BIT(10) /*!< channel 2 complementary output enable */ #define TIMER_CHCTL2_CH2NP BIT(11) /*!< channel 2 complementary output polarity */ -#define TIMER_CHCTL2_CH3EN BIT(12) /*!< channel 3 enable */ -#define TIMER_CHCTL2_CH3P BIT(13) /*!< channel 3 polarity */ +#define TIMER_CHCTL2_CH3EN BIT(12) /*!< channel 3 capture/compare function enable */ +#define TIMER_CHCTL2_CH3P BIT(13) /*!< channel 3 capture/compare function polarity */ /* TIMER_CNT */ #define TIMER_CNT_CNT16 BITS(0,15) /*!< 16 bit timer counter */ @@ -200,16 +226,16 @@ #define TIMER_CH0CV_CH0VAL32 BITS(0,31) /*!< 32 bit(TIMER1,TIMER4) capture/compare value of channel 0 */ /* TIMER_CH1CV */ -#define TIMER_CH1CV_CH0VAL16 BITS(0,15) /*!< 16 bit capture/compare value of channel 1 */ -#define TIMER_CH1CV_CH0VAL32 BITS(0,31) /*!< 32 bit(TIMER1,TIMER4) capture/compare value of channel 1 */ +#define TIMER_CH1CV_CH1VAL16 BITS(0,15) /*!< 16 bit capture/compare value of channel 1 */ +#define TIMER_CH1CV_CH1VAL32 BITS(0,31) /*!< 32 bit(TIMER1,TIMER4) capture/compare value of channel 1 */ /* TIMER_CH2CV */ -#define TIMER_CH2CV_CH0VAL16 BITS(0,15) /*!< 16 bit capture/compare value of channel 2 */ -#define TIMER_CH2CV_CH0VAL32 BITS(0,31) /*!< 32 bit(TIMER1,TIMER4) capture/compare value of channel 2 */ +#define TIMER_CH2CV_CH2VAL16 BITS(0,15) /*!< 16 bit capture/compare value of channel 2 */ +#define TIMER_CH2CV_CH2VAL32 BITS(0,31) /*!< 32 bit(TIMER1,TIMER4) capture/compare value of channel 2 */ /* TIMER_CH3CV */ -#define TIMER_CH3CV_CH0VAL16 BITS(0,15) /*!< 16 bit capture/compare value of channel 3 */ -#define TIMER_CH3CV_CH0VAL32 BITS(0,31) /*!< 32 bit(TIMER1,TIMER4) capture/compare value of channel 3 */ +#define TIMER_CH3CV_CH3VAL16 BITS(0,15) /*!< 16 bit capture/compare value of channel 3 */ +#define TIMER_CH3CV_CH3VAL32 BITS(0,31) /*!< 32 bit(TIMER1,TIMER4) capture/compare value of channel 3 */ /* TIMER_CCHP */ #define TIMER_CCHP_DTCFG BITS(0,7) /*!< dead time configure */ @@ -240,31 +266,31 @@ /* constants definitions */ /* TIMER init parameter struct definitions*/ typedef struct -{ +{ uint16_t prescaler; /*!< prescaler value */ uint16_t alignedmode; /*!< aligned mode */ uint16_t counterdirection; /*!< counter direction */ - uint32_t period; /*!< period value */ uint16_t clockdivision; /*!< clock division value */ + uint32_t period; /*!< period value */ uint8_t repetitioncounter; /*!< the counter repetition value */ }timer_parameter_struct; /* break parameter struct definitions*/ typedef struct -{ - uint16_t runoffstate; /*!< run mode off-state */ - uint32_t ideloffstate; /*!< idle mode off-state */ - uint16_t deadtime; /*!< delay time between the switching off and on of the outputs */ +{ + uint16_t runoffstate; /*!< run mode off-state */ + uint16_t ideloffstate; /*!< idle mode off-state */ + uint16_t deadtime; /*!< dead time */ uint16_t breakpolarity; /*!< break polarity */ - uint16_t outputautostate; /*!< output automatic enable */ - uint16_t protectmode; /*!< complementary register protect control */ - uint16_t breakstate; /*!< break enable */ + uint16_t outputautostate; /*!< output automatic enable */ + uint16_t protectmode; /*!< complementary register protect control */ + uint16_t breakstate; /*!< break enable */ }timer_break_parameter_struct; /* channel output parameter struct definitions */ typedef struct -{ - uint32_t outputstate; /*!< channel output state */ +{ + uint16_t outputstate; /*!< channel output state */ uint16_t outputnstate; /*!< channel complementary output state */ uint16_t ocpolarity; /*!< channel output polarity */ uint16_t ocnpolarity; /*!< channel complementary output polarity */ @@ -274,47 +300,59 @@ typedef struct /* channel input parameter struct definitions */ typedef struct -{ +{ uint16_t icpolarity; /*!< channel input polarity */ uint16_t icselection; /*!< channel input mode selection */ uint16_t icprescaler; /*!< channel input capture prescaler */ uint16_t icfilter; /*!< channel input capture filter control */ }timer_ic_parameter_struct; -/* TIMER interrupt source */ -#define TIMER_INT_UP ((uint32_t)0x00000001U) /*!< update interrupt */ -#define TIMER_INT_CH0 ((uint32_t)0x00000002U) /*!< channel 0 interrupt */ -#define TIMER_INT_CH1 ((uint32_t)0x00000004U) /*!< channel 1 interrupt */ -#define TIMER_INT_CH2 ((uint32_t)0x00000008U) /*!< channel 2 interrupt */ -#define TIMER_INT_CH3 ((uint32_t)0x00000010U) /*!< channel 3 interrupt */ -#define TIMER_INT_CMT ((uint32_t)0x00000020U) /*!< channel commutation interrupt flag */ -#define TIMER_INT_TRG ((uint32_t)0x00000040U) /*!< trigger interrupt */ -#define TIMER_INT_BRK ((uint32_t)0x00000080U) /*!< break interrupt */ +/* TIMER interrupt enable or disable */ +#define TIMER_INT_UP TIMER_DMAINTEN_UPIE /*!< update interrupt */ +#define TIMER_INT_CH0 TIMER_DMAINTEN_CH0IE /*!< channel 0 interrupt */ +#define TIMER_INT_CH1 TIMER_DMAINTEN_CH1IE /*!< channel 1 interrupt */ +#define TIMER_INT_CH2 TIMER_DMAINTEN_CH2IE /*!< channel 2 interrupt */ +#define TIMER_INT_CH3 TIMER_DMAINTEN_CH3IE /*!< channel 3 interrupt */ +#define TIMER_INT_CMT TIMER_DMAINTEN_CMTIE /*!< channel commutation interrupt flag */ +#define TIMER_INT_TRG TIMER_DMAINTEN_TRGIE /*!< trigger interrupt */ +#define TIMER_INT_BRK TIMER_DMAINTEN_BRKIE /*!< break interrupt */ /* TIMER flag */ -#define TIMER_FLAG_UP ((uint32_t)0x00000001U) /*!< update flag */ -#define TIMER_FLAG_CH0 ((uint32_t)0x00000002U) /*!< channel 0 flag */ -#define TIMER_FLAG_CH1 ((uint32_t)0x00000004U) /*!< channel 1 flag */ -#define TIMER_FLAG_CH2 ((uint32_t)0x00000008U) /*!< channel 2 flag */ -#define TIMER_FLAG_CH3 ((uint32_t)0x00000010U) /*!< channel 3 flag */ -#define TIMER_FLAG_CMT ((uint32_t)0x00000020U) /*!< channel control update flag */ -#define TIMER_FLAG_TRG ((uint32_t)0x00000040U) /*!< trigger flag */ -#define TIMER_FLAG_BRK ((uint32_t)0x00000080U) /*!< break flag */ -#define TIMER_FLAG_CH0OF ((uint32_t)0x00000200U) /*!< channel 0 overcapture flag */ -#define TIMER_FLAG_CH1OF ((uint32_t)0x00000400U) /*!< channel 1 overcapture flag */ -#define TIMER_FLAG_CH2OF ((uint32_t)0x00000800U) /*!< channel 2 overcapture flag */ -#define TIMER_FLAG_CH3OF ((uint32_t)0x00001000U) /*!< channel 3 overcapture flag */ +#define TIMER_FLAG_UP TIMER_INTF_UPIF /*!< update flag */ +#define TIMER_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 flag */ +#define TIMER_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 flag */ +#define TIMER_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 flag */ +#define TIMER_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 flag */ +#define TIMER_FLAG_CMT TIMER_INTF_CMTIF /*!< channel commutation flag */ +#define TIMER_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger flag */ +#define TIMER_FLAG_BRK TIMER_INTF_BRKIF /*!< break flag */ +#define TIMER_FLAG_CH0O TIMER_INTF_CH0OF /*!< channel 0 overcapture flag */ +#define TIMER_FLAG_CH1O TIMER_INTF_CH1OF /*!< channel 1 overcapture flag */ +#define TIMER_FLAG_CH2O TIMER_INTF_CH2OF /*!< channel 2 overcapture flag */ +#define TIMER_FLAG_CH3O TIMER_INTF_CH3OF /*!< channel 3 overcapture flag */ + +/* TIMER interrupt flag */ +#define TIMER_INT_FLAG_UP TIMER_INTF_UPIF /*!< update interrupt flag */ +#define TIMER_INT_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 interrupt flag */ +#define TIMER_INT_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 interrupt flag */ +#define TIMER_INT_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 interrupt flag */ +#define TIMER_INT_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 interrupt flag */ +#define TIMER_INT_FLAG_CMT TIMER_INTF_CMTIF /*!< channel commutation interrupt flag */ +#define TIMER_INT_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger interrupt flag */ +#define TIMER_INT_FLAG_BRK TIMER_INTF_BRKIF + + /* TIMER DMA source enable */ -#define TIMER_DMA_UPD ((uint16_t)0x0100U) /*!< update DMA enable */ -#define TIMER_DMA_CH0D ((uint16_t)0x0200U) /*!< channel 0 DMA enable */ -#define TIMER_DMA_CH1D ((uint16_t)0x0400U) /*!< channel 1 DMA enable */ -#define TIMER_DMA_CH2D ((uint16_t)0x0800U) /*!< channel 2 DMA enable */ -#define TIMER_DMA_CH3D ((uint16_t)0x1000U) /*!< channel 3 DMA enable */ -#define TIMER_DMA_CMTD ((uint16_t)0x2000U) /*!< commutation DMA request enable */ -#define TIMER_DMA_TRGD ((uint16_t)0x4000U) /*!< trigger DMA enable */ +#define TIMER_DMA_UPD ((uint16_t)TIMER_DMAINTEN_UPDEN) /*!< update DMA enable */ +#define TIMER_DMA_CH0D ((uint16_t)TIMER_DMAINTEN_CH0DEN) /*!< channel 0 DMA enable */ +#define TIMER_DMA_CH1D ((uint16_t)TIMER_DMAINTEN_CH1DEN) /*!< channel 1 DMA enable */ +#define TIMER_DMA_CH2D ((uint16_t)TIMER_DMAINTEN_CH2DEN) /*!< channel 2 DMA enable */ +#define TIMER_DMA_CH3D ((uint16_t)TIMER_DMAINTEN_CH3DEN) /*!< channel 3 DMA enable */ +#define TIMER_DMA_CMTD ((uint16_t)TIMER_DMAINTEN_CMTDEN) /*!< commutation DMA request enable */ +#define TIMER_DMA_TRGD ((uint16_t)TIMER_DMAINTEN_TRGDEN) /*!< trigger DMA enable */ -/* channel DMA request source selection */ +/* channel DMA request source selection */ #define TIMER_DMAREQUEST_UPDATEEVENT ((uint8_t)0x00U) /*!< DMA request of channel y is sent when update event occurs */ #define TIMER_DMAREQUEST_CHANNELEVENT ((uint8_t)0x01U) /*!< DMA request of channel y is sent when channel y event occurs */ @@ -380,12 +418,12 @@ typedef struct #define TIMER_COUNTER_CENTER_BOTH CTL0_CAM(3) /*!< center-aligned and counting up/down assert mode */ /* TIMER prescaler reload mode */ -#define TIMER_PSC_RELOAD_NOW ((uint8_t)0x00U) /*!< the prescaler is loaded right now */ -#define TIMER_PSC_RELOAD_UPDATE ((uint8_t)0x01U) /*!< the prescaler is loaded at the next update event */ +#define TIMER_PSC_RELOAD_NOW ((uint32_t)0x00000000U) /*!< the prescaler is loaded right now */ +#define TIMER_PSC_RELOAD_UPDATE ((uint32_t)0x00000001U) /*!< the prescaler is loaded at the next update event */ /* count direction */ #define TIMER_COUNTER_UP ((uint16_t)0x0000U) /*!< counter up direction */ -#define TIMER_COUNTER_DOWN ((uint16_t)0x0010U) /*!< counter down direction */ +#define TIMER_COUNTER_DOWN ((uint16_t)TIMER_CTL0_DIR) /*!< counter down direction */ /* specify division ratio between TIMER clock and dead-time and sampling clock */ #define CTL0_CKDIV(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) @@ -394,27 +432,27 @@ typedef struct #define TIMER_CKDIV_DIV4 CTL0_CKDIV(2) /*!< clock division value is 4, fDTS= fTIMER_CK/4 */ /* single pulse mode */ -#define TIMER_SP_MODE_SINGLE ((uint8_t)0x00U) /*!< single pulse mode */ -#define TIMER_SP_MODE_REPETITIVE ((uint8_t)0x01U) /*!< repetitive pulse mode */ +#define TIMER_SP_MODE_SINGLE ((uint32_t)0x00000000U) /*!< single pulse mode */ +#define TIMER_SP_MODE_REPETITIVE ((uint32_t)0x00000001U) /*!< repetitive pulse mode */ /* update source */ -#define TIMER_UPDATE_SRC_REGULAR ((uint8_t)0x00U) /*!< update generate only by counter overflow/underflow */ -#define TIMER_UPDATE_SRC_GLOBAL ((uint8_t)0x01U) /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */ +#define TIMER_UPDATE_SRC_REGULAR ((uint32_t)0x00000000U) /*!< update generate only by counter overflow/underflow */ +#define TIMER_UPDATE_SRC_GLOBAL ((uint32_t)0x00000001U) /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */ /* run mode off-state configure */ -#define TIMER_ROS_STATE_ENABLE ((uint32_t)0x00000800U) /*!< when POEN bit is set, the channel output signals (CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ -#define TIMER_ROS_STATE_DISABLE ((uint32_t)0x00000000U) /*!< when POEN bit is set, the channel output signals (CHx_O/CHx_ON) are disabled */ +#define TIMER_ROS_STATE_ENABLE ((uint16_t)TIMER_CCHP_ROS) /*!< when POEN bit is set, the channel output signals (CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_ROS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is set, the channel output signals (CHx_O/CHx_ON) are disabled */ -/* idle mode off-state configure */ -#define TIMER_IOS_STATE_ENABLE ((uint16_t)0x0400U) /*!< when POEN bit is reset, he channel output signals (CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +/* idle mode off-state configure */ +#define TIMER_IOS_STATE_ENABLE ((uint16_t)TIMER_CCHP_IOS) /*!< when POEN bit is reset, the channel output signals (CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ #define TIMER_IOS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is reset, the channel output signals (CHx_O/CHx_ON) are disabled */ /* break input polarity */ #define TIMER_BREAK_POLARITY_LOW ((uint16_t)0x0000U) /*!< break input polarity is low */ -#define TIMER_BREAK_POLARITY_HIGH ((uint16_t)0x2000U) /*!< break input polarity is high */ +#define TIMER_BREAK_POLARITY_HIGH ((uint16_t)TIMER_CCHP_BRKP) /*!< break input polarity is high */ /* output automatic enable */ -#define TIMER_OUTAUTO_ENABLE ((uint16_t)0x4000U) /*!< output automatic enable */ +#define TIMER_OUTAUTO_ENABLE ((uint16_t)TIMER_CCHP_OAEN) /*!< output automatic enable */ #define TIMER_OUTAUTO_DISABLE ((uint16_t)0x0000U) /*!< output automatic disable */ /* complementary register protect control */ @@ -425,10 +463,10 @@ typedef struct #define TIMER_CCHP_PROT_2 CCHP_PROT(3) /*!< PROT mode 2 */ /* break input enable */ -#define TIMER_BREAK_ENABLE ((uint16_t)0x1000U) /*!< break input enable */ +#define TIMER_BREAK_ENABLE ((uint16_t)TIMER_CCHP_BRKEN) /*!< break input enable */ #define TIMER_BREAK_DISABLE ((uint16_t)0x0000U) /*!< break input disable */ -/* TIMER channel y(y=0,1,2,3) */ +/* TIMER channel n(n=0,1,2,3) */ #define TIMER_CH_0 ((uint16_t)0x0000U) /*!< TIMER channel 0(TIMERx(x=0..4,7..13)) */ #define TIMER_CH_1 ((uint16_t)0x0001U) /*!< TIMER channel 1(TIMERx(x=0..4,7,8,11)) */ #define TIMER_CH_2 ((uint16_t)0x0002U) /*!< TIMER channel 2(TIMERx(x=0..4,7)) */ @@ -450,11 +488,11 @@ typedef struct #define TIMER_OCN_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel complementary output polarity is high */ #define TIMER_OCN_POLARITY_LOW ((uint16_t)0x0008U) /*!< channel complementary output polarity is low */ -/* idle state of channel output */ +/* idle state of channel output */ #define TIMER_OC_IDLE_STATE_HIGH ((uint16_t)0x0100) /*!< idle state of channel output is high */ #define TIMER_OC_IDLE_STATE_LOW ((uint16_t)0x0000) /*!< idle state of channel output is low */ -/* idle state of channel complementary output */ +/* idle state of channel complementary output */ #define TIMER_OCN_IDLE_STATE_HIGH ((uint16_t)0x0200U) /*!< idle state of channel complementary output is high */ #define TIMER_OCN_IDLE_STATE_LOW ((uint16_t)0x0000U) /*!< idle state of channel complementary output is low */ @@ -476,20 +514,20 @@ typedef struct #define TIMER_OC_FAST_ENABLE ((uint16_t)0x0004) /*!< channel output fast function enable */ #define TIMER_OC_FAST_DISABLE ((uint16_t)0x0000) /*!< channel output fast function disable */ -/* channel output compare clear enable. */ +/* channel output compare clear enable */ #define TIMER_OC_CLEAR_ENABLE ((uint16_t)0x0080U) /*!< channel output clear function enable */ #define TIMER_OC_CLEAR_DISABLE ((uint16_t)0x0000U) /*!< channel output clear function disable */ -/* channel control shadow register update control */ -#define TIMER_UPDATECTL_CCU ((uint8_t)0x00U) /*!< the shadow registers update by when CMTG bit is set */ -#define TIMER_UPDATECTL_CCUTRI ((uint8_t)0x01U) /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */ +/* channel control shadow register update control */ +#define TIMER_UPDATECTL_CCU ((uint32_t)0x00000000U) /*!< the shadow registers are updated when CMTG bit is set */ +#define TIMER_UPDATECTL_CCUTRI ((uint32_t)0x00000001U) /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */ /* channel input capture polarity */ #define TIMER_IC_POLARITY_RISING ((uint16_t)0x0000U) /*!< input capture rising edge */ #define TIMER_IC_POLARITY_FALLING ((uint16_t)0x0002U) /*!< input capture falling edge */ #define TIMER_IC_POLARITY_BOTH_EDGE ((uint16_t)0x000AU) /*!< input capture both edge */ -/* timer input capture selection */ +/* TIMER input capture selection */ #define TIMER_IC_SELECTION_DIRECTTI ((uint16_t)0x0001U) /*!< channel y is configured as input and icy is mapped on CIy */ #define TIMER_IC_SELECTION_INDIRECTTI ((uint16_t)0x0002U) /*!< channel y is configured as input and icy is mapped on opposite input */ #define TIMER_IC_SELECTION_ITS ((uint16_t)0x0003U) /*!< channel y is configured as input and icy is mapped on ITS */ @@ -502,28 +540,28 @@ typedef struct /* trigger selection */ #define SMCFG_TRGSEL(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) -#define TIMER_SMCFG_TRGSEL_ITI0 SMCFG_TRGSEL(0) /*!< internal trigger 0 */ -#define TIMER_SMCFG_TRGSEL_ITI1 SMCFG_TRGSEL(1) /*!< internal trigger 1 */ -#define TIMER_SMCFG_TRGSEL_ITI2 SMCFG_TRGSEL(2) /*!< internal trigger 2 */ -#define TIMER_SMCFG_TRGSEL_ITI3 SMCFG_TRGSEL(3) /*!< internal trigger 3 */ -#define TIMER_SMCFG_TRGSEL_CI0F_ED SMCFG_TRGSEL(4) /*!< TI0 Edge Detector */ -#define TIMER_SMCFG_TRGSEL_CI0FE0 SMCFG_TRGSEL(5) /*!< filtered TIMER input 0 */ -#define TIMER_SMCFG_TRGSEL_CI1FE1 SMCFG_TRGSEL(6) /*!< filtered TIMER input 1 */ -#define TIMER_SMCFG_TRGSEL_ETIFP SMCFG_TRGSEL(7) /*!< external trigger */ +#define TIMER_SMCFG_TRGSEL_ITI0 SMCFG_TRGSEL(0) /*!< internal trigger 0 */ +#define TIMER_SMCFG_TRGSEL_ITI1 SMCFG_TRGSEL(1) /*!< internal trigger 1 */ +#define TIMER_SMCFG_TRGSEL_ITI2 SMCFG_TRGSEL(2) /*!< internal trigger 2 */ +#define TIMER_SMCFG_TRGSEL_ITI3 SMCFG_TRGSEL(3) /*!< internal trigger 3 */ +#define TIMER_SMCFG_TRGSEL_CI0F_ED SMCFG_TRGSEL(4) /*!< TI0 Edge Detector */ +#define TIMER_SMCFG_TRGSEL_CI0FE0 SMCFG_TRGSEL(5) /*!< filtered TIMER input 0 */ +#define TIMER_SMCFG_TRGSEL_CI1FE1 SMCFG_TRGSEL(6) /*!< filtered TIMER input 1 */ +#define TIMER_SMCFG_TRGSEL_ETIFP SMCFG_TRGSEL(7) /*!< external trigger */ /* master mode control */ #define CTL1_MMC(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) #define TIMER_TRI_OUT_SRC_RESET CTL1_MMC(0) /*!< the UPG bit as trigger output */ #define TIMER_TRI_OUT_SRC_ENABLE CTL1_MMC(1) /*!< the counter enable signal TIMER_CTL0_CEN as trigger output */ #define TIMER_TRI_OUT_SRC_UPDATE CTL1_MMC(2) /*!< update event as trigger output */ -#define TIMER_TRI_OUT_SRC_CC0 CTL1_MMC(3) /*!< a capture or a compare match occurred in channal0 as trigger output TRGO */ +#define TIMER_TRI_OUT_SRC_CH0 CTL1_MMC(3) /*!< a capture or a compare match occurred in channal0 as trigger output TRGO */ #define TIMER_TRI_OUT_SRC_O0CPRE CTL1_MMC(4) /*!< O0CPRE as trigger output */ #define TIMER_TRI_OUT_SRC_O1CPRE CTL1_MMC(5) /*!< O1CPRE as trigger output */ #define TIMER_TRI_OUT_SRC_O2CPRE CTL1_MMC(6) /*!< O2CPRE as trigger output */ #define TIMER_TRI_OUT_SRC_O3CPRE CTL1_MMC(7) /*!< O3CPRE as trigger output */ /* slave mode control */ -#define SMCFG_SMC(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0U)) +#define SMCFG_SMC(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0U)) #define TIMER_SLAVE_MODE_DISABLE SMCFG_SMC(0) /*!< slave mode disable */ #define TIMER_ENCODER_MODE0 SMCFG_SMC(1) /*!< encoder mode 0 */ #define TIMER_ENCODER_MODE1 SMCFG_SMC(2) /*!< encoder mode 1 */ @@ -533,9 +571,9 @@ typedef struct #define TIMER_SLAVE_MODE_EVENT SMCFG_SMC(6) /*!< event mode */ #define TIMER_SLAVE_MODE_EXTERNAL0 SMCFG_SMC(7) /*!< external clock mode 0 */ -/* master slave mode selection */ -#define TIMER_MASTER_SLAVE_MODE_ENABLE ((uint8_t)0x00U) /*!< master slave mode enable */ -#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint8_t)0x01U) /*!< master slave mode disable */ +/* master slave mode selection */ +#define TIMER_MASTER_SLAVE_MODE_ENABLE ((uint32_t)0x00000000U) /*!< master slave mode enable */ +#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint32_t)0x00000001U) /*!< master slave mode disable */ /* external trigger prescaler */ #define SMCFG_ETPSC(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12U)) @@ -548,19 +586,19 @@ typedef struct #define TIMER_ETP_FALLING TIMER_SMCFG_ETP /*!< active low or falling edge active */ #define TIMER_ETP_RISING ((uint32_t)0x00000000U) /*!< active high or rising edge active */ -/* channel 0 trigger input selection */ -#define TIMER_HALLINTERFACE_ENABLE ((uint8_t)0x00U) /*!< TIMER hall sensor mode enable */ -#define TIMER_HALLINTERFACE_DISABLE ((uint8_t)0x01U) /*!< TIMER hall sensor mode disable */ +/* channel 0 trigger input selection */ +#define TIMER_HALLINTERFACE_ENABLE ((uint32_t)0x00000000U) /*!< TIMER hall sensor mode enable */ +#define TIMER_HALLINTERFACE_DISABLE ((uint32_t)0x00000001U) /*!< TIMER hall sensor mode disable */ /* timer1 internal trigger input1 remap */ -#define TIMER1_IRMP(regval) (BITS(10, 11) & ((uint32_t)(regval) << 10U)) +#define TIMER1_IRMP(regval) (BITS(10, 11) & ((uint32_t)(regval) << 10U)) #define TIMER1_ITI1_RMP_TIMER7_TRGO TIMER1_IRMP(0) /*!< timer1 internal trigger input 1 remap to TIMER7_TRGO */ #define TIMER1_ITI1_RMP_ETHERNET_PTP TIMER1_IRMP(1) /*!< timer1 internal trigger input 1 remap to ethernet PTP */ #define TIMER1_ITI1_RMP_USB_FS_SOF TIMER1_IRMP(2) /*!< timer1 internal trigger input 1 remap to USB FS SOF */ #define TIMER1_ITI1_RMP_USB_HS_SOF TIMER1_IRMP(3) /*!< timer1 internal trigger input 1 remap to USB HS SOF */ /* timer4 channel 3 input remap */ -#define TIMER4_IRMP(regval) (BITS(6, 7) & ((uint32_t)(regval) << 6U)) +#define TIMER4_IRMP(regval) (BITS(6, 7) & ((uint32_t)(regval) << 6U)) #define TIMER4_CI3_RMP_GPIO TIMER4_IRMP(0) /*!< timer4 channel 3 input remap to GPIO pin */ #define TIMER4_CI3_RMP_IRC32K TIMER4_IRMP(1) /*!< timer4 channel 3 input remap to IRC32K */ #define TIMER4_CI3_RMP_LXTAL TIMER4_IRMP(2) /*!< timer4 channel 3 input remap to LXTAL */ @@ -572,19 +610,21 @@ typedef struct #define TIMER10_ITI1_RMP_RTC_HXTAL_DIV TIMER10_IRMP(2) /*!< timer10 internal trigger input1 remap HXTAL _DIV(clock used for RTC which is HXTAL clock divided by RTCDIV bits in RCU_CFG0 register) */ /* timerx(x=0,1,2,13,14,15,16) write cc register selection */ -#define TIMER_CCSEL_DISABLE ((uint16_t)0x0000U) /*!< write CC register selection disable */ -#define TIMER_CCSEL_ENABLE ((uint16_t)0x0002U) /*!< write CC register selection enable */ +#define TIMER_CHVSEL_ENABLE ((uint16_t)0x0002U) /*!< write CHxVAL register selection enable */ +#define TIMER_CHVSEL_DISABLE ((uint16_t)0x0000U) /*!< write CHxVAL register selection disable */ /* the output value selection */ -#define TIMER_OUTSEL_DISABLE ((uint16_t)0x0000U) /*!< output value selection disable */ #define TIMER_OUTSEL_ENABLE ((uint16_t)0x0001U) /*!< output value selection enable */ +#define TIMER_OUTSEL_DISABLE ((uint16_t)0x0000U) /*!< output value selection disable */ /* function declarations */ /* TIMER timebase*/ /* deinit a TIMER */ void timer_deinit(uint32_t timer_periph); +/* initialize TIMER init parameter struct */ +void timer_struct_para_init(timer_parameter_struct* initpara); /* initialize TIMER counter */ -void timer_init(uint32_t timer_periph, timer_parameter_struct* timer_initpara); +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara); /* enable a TIMER */ void timer_enable(uint32_t timer_periph); /* disable a TIMER */ @@ -598,57 +638,59 @@ void timer_update_event_enable(uint32_t timer_periph); /* disable the update event */ void timer_update_event_disable(uint32_t timer_periph); /* set TIMER counter alignment mode */ -void timer_counter_alignment(uint32_t timer_periph,uint16_t timer_aligned); +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned); /* set TIMER counter up direction */ void timer_counter_up_direction(uint32_t timer_periph); /* set TIMER counter down direction */ void timer_counter_down_direction(uint32_t timer_periph); /* configure TIMER prescaler */ -void timer_prescaler_config(uint32_t timer_periph,uint16_t timer_prescaler,uint8_t timer_pscreload); +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint8_t pscreload); /* configure TIMER repetition register value */ -void timer_repetition_value_config(uint32_t timer_periph,uint16_t timer_repetition); +void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition); /* configure TIMER autoreload register value */ -void timer_autoreload_value_config(uint32_t timer_periph,uint32_t timer_autoreload); +void timer_autoreload_value_config(uint32_t timer_periph,uint32_t autoreload); /* configure TIMER counter register value */ -void timer_counter_value_config(uint32_t timer_periph , uint32_t timer_counter); +void timer_counter_value_config(uint32_t timer_periph , uint32_t counter); /* read TIMER counter value */ uint32_t timer_counter_read(uint32_t timer_periph); /* read TIMER prescaler value */ uint16_t timer_prescaler_read(uint32_t timer_periph); /* configure TIMER single pulse mode */ -void timer_single_pulse_mode_config(uint32_t timer_periph,uint8_t timer_spmode); +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode); /* configure TIMER update source */ -void timer_update_source_config(uint32_t timer_periph,uint8_t timer_update); +void timer_update_source_config(uint32_t timer_periph, uint32_t update); /* TIMER interrupt and flag*/ /* enable the TIMER interrupt */ -void timer_interrupt_enable(uint32_t timer_periph,uint32_t timer_interrupt); +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt); /* disable the TIMER interrupt */ -void timer_interrupt_disable(uint32_t timer_periph,uint32_t timer_interrupt); +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt); /* get timer interrupt flag */ -FlagStatus timer_interrupt_flag_get(uint32_t timer_periph,uint32_t timer_interrupt); +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt); /* clear TIMER interrupt flag */ -void timer_interrupt_flag_clear(uint32_t timer_periph,uint32_t timer_interrupt); +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt); /* get TIMER flags */ -FlagStatus timer_flag_get(uint32_t timer_periph , uint32_t timer_flag); +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag); /* clear TIMER flags */ -void timer_flag_clear(uint32_t timer_periph , uint32_t timer_flag); +void timer_flag_clear(uint32_t timer_periph, uint32_t flag); /* timer DMA and event*/ /* enable the TIMER DMA */ -void timer_dma_enable(uint32_t timer_periph,uint16_t timer_dma); +void timer_dma_enable(uint32_t timer_periph, uint16_t dma); /* disable the TIMER DMA */ -void timer_dma_disable(uint32_t timer_periph,uint16_t timer_dma); +void timer_dma_disable(uint32_t timer_periph, uint16_t dma); /* channel DMA request source selection */ -void timer_channel_dma_request_source_select(uint32_t timer_periph,uint8_t dma_request); +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint8_t dma_request); /* configure the TIMER DMA transfer */ -void timer_dma_transfer_config(uint32_t timer_periph,uint32_t dma_baseaddr,uint32_t dma_lenth); +void timer_dma_transfer_config(uint32_t timer_periph,uint32_t dma_baseaddr, uint32_t dma_lenth); /* software generate events */ -void timer_event_software_generate(uint32_t timer_periph,uint16_t timer_event); +void timer_event_software_generate(uint32_t timer_periph, uint16_t event); -/* timer channel complementary protection */ +/* TIMER channel complementary protection */ +/* initialize TIMER break parameter struct */ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara); /* configure TIMER break function */ -void timer_break_config(uint32_t timer_periph,timer_break_parameter_struct* timer_bkdtpara); +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara); /* enable TIMER break function */ void timer_break_enable(uint32_t timer_periph); /* disable TIMER break function */ @@ -657,79 +699,83 @@ void timer_break_disable(uint32_t timer_periph); void timer_automatic_output_enable(uint32_t timer_periph); /* disable TIMER output automatic function */ void timer_automatic_output_disable(uint32_t timer_periph); -/* configure TIMER primary output function */ -void timer_primary_output_config(uint32_t timer_periph,ControlStatus newvalue); -/* channel capture/compare control shadow register enable */ -void timer_channel_control_shadow_config(uint32_t timer_periph,ControlStatus newvalue); +/* enable or disable TIMER primary output function */ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue); +/* enable or disable channel capture/compare control shadow register */ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue); /* configure TIMER channel control shadow register update control */ -void timer_channel_control_shadow_update_config(uint32_t timer_periph,uint8_t timer_ccuctl); +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint8_t ccuctl); /* TIMER channel output */ +/* initialize TIMER channel output parameter struct */ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara); /* configure TIMER channel output function */ -void timer_channel_output_config(uint32_t timer_periph,uint16_t timer_channel,timer_oc_parameter_struct* timer_ocpara); +void timer_channel_output_config(uint32_t timer_periph,uint16_t channel, timer_oc_parameter_struct* ocpara); /* configure TIMER channel output compare mode */ -void timer_channel_output_mode_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocmode); +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel,uint16_t ocmode); /* configure TIMER channel output pulse value */ -void timer_channel_output_pulse_value_config(uint32_t timer_periph,uint16_t timer_channel,uint32_t timer_pluse); +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse); /* configure TIMER channel output shadow function */ -void timer_channel_output_shadow_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocshadow); +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow); /* configure TIMER channel output fast function */ -void timer_channel_output_fast_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocfast); +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast); /* configure TIMER channel output clear function */ -void timer_channel_output_clear_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_occlear); +void timer_channel_output_clear_config(uint32_t timer_periph,uint16_t channel,uint16_t occlear); /* configure TIMER channel output polarity */ -void timer_channel_output_polarity_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocpolarity); +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity); /* configure TIMER channel complementary output polarity */ -void timer_channel_complementary_output_polarity_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocnpolarity); +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity); /* configure TIMER channel enable state */ -void timer_channel_output_state_config(uint32_t timer_periph,uint16_t timer_channel,uint32_t timer_state); +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state); /* configure TIMER channel complementary output enable state */ -void timer_channel_complementary_output_state_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocnstate); +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate); /* TIMER channel input */ +/* initialize TIMER channel input parameter struct */ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara); /* configure TIMER input capture parameter */ -void timer_input_capture_config(uint32_t timer_periph,uint16_t timer_channel,timer_ic_parameter_struct* timer_icpara); +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara); /* configure TIMER channel input capture prescaler value */ -void timer_channel_input_capture_prescaler_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_prescaler); +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler); /* read TIMER channel capture compare register value */ -uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph,uint16_t timer_channel); +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel); /* configure TIMER input pwm capture function */ -void timer_input_pwm_capture_config(uint32_t timer_periph,uint16_t timer_channel,timer_ic_parameter_struct* timer_icpwm); +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm); /* configure TIMER hall sensor mode */ -void timer_hall_mode_config(uint32_t timer_periph,uint8_t timer_hallmode); +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode); /* TIMER master and slave */ /* select TIMER input trigger source */ -void timer_input_trigger_source_select(uint32_t timer_periph,uint32_t timer_intrigger); +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger); /* select TIMER master mode output trigger source */ -void timer_master_output_trigger_source_select(uint32_t timer_periph,uint32_t timer_outrigger); +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger); /* select TIMER slave mode */ -void timer_slave_mode_select(uint32_t timer_periph,uint32_t timer_slavemode); +void timer_slave_mode_select(uint32_t timer_periph,uint32_t slavemode); /* configure TIMER master slave mode */ -void timer_master_slave_mode_config(uint32_t timer_periph,uint8_t timer_masterslave); +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave); /* configure TIMER external trigger input */ -void timer_external_trigger_config(uint32_t timer_periph,uint32_t timer_extprescaler,uint32_t timer_expolarity,uint32_t timer_extfilter); +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); /* configure TIMER quadrature decoder mode */ -void timer_quadrature_decoder_mode_config(uint32_t timer_periph,uint32_t timer_decomode,uint16_t timer_ic0polarity,uint16_t timer_ic1polarity); +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity); /* configure TIMER internal clock mode */ void timer_internal_clock_config(uint32_t timer_periph); /* configure TIMER the internal trigger as external clock input */ -void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t timer_intrigger); +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger); /* configure TIMER the external trigger as external clock input */ -void timer_external_trigger_as_external_clock_config(uint32_t timer_periph,uint32_t timer_extrigger,uint16_t timer_expolarity,uint32_t timer_extfilter); +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity,uint32_t extfilter); /* configure TIMER the external clock mode 0 */ -void timer_external_clock_mode0_config(uint32_t timer_periph,uint32_t timer_extprescaler,uint32_t timer_expolarity,uint32_t timer_extfilter); +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); /* configure TIMER the external clock mode 1 */ -void timer_external_clock_mode1_config(uint32_t timer_periph,uint32_t timer_extprescaler,uint32_t timer_expolarity,uint32_t timer_extfilter); +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); /* disable TIMER the external clock mode 1 */ void timer_external_clock_mode1_disable(uint32_t timer_periph); -/* configure TIMER1 channel 0 remap function */ -void timer_channel_remap_config(uint32_t timer_periph,uint32_t timer_remap); +/* configure TIMER channel remap function */ +void timer_channel_remap_config(uint32_t timer_periph,uint32_t remap); /* TIMER configure */ /* configure TIMER write CHxVAL register selection */ -void timer_write_cc_register_config(uint32_t timer_periph, uint16_t timer_ccsel); +void timer_write_chxval_register_config(uint32_t timer_periph, uint16_t ccsel); /* configure TIMER output value selection */ -void timer_output_value_selection_config(uint32_t timer_periph, uint16_t timer_outsel); +void timer_output_value_selection_config(uint32_t timer_periph, uint16_t outsel); #endif /* GD32F4XX_TIMER_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h index f2f8f9d71e..8b1232fa17 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_tli.h - \brief definitions for the TLI + \file gd32f4xx_tli.h + \brief definitions for the TLI + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.1, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_TLI_H @@ -17,8 +42,8 @@ /* TLI definitions */ #define TLI TLI_BASE /*!< TLI base address */ /* TLI layer definitions */ -#define LAYER0 TLI_BASE /*!< Layer0 base address */ -#define LAYER1 (TLI_BASE+0x80) /*!< Layer1 base address */ +#define LAYER0 TLI_BASE /*!< TLI layer0 base address */ +#define LAYER1 (TLI_BASE+0x80) /*!< TLI layer1 base address */ /* registers definitions */ #define TLI_SPSZ REG32(TLI + 0x08U) /*!< TLI synchronous pulse size register */ @@ -45,8 +70,7 @@ #define TLI_LxFBADDR(layerx) REG32((layerx) + 0xACU) /*!< TLI layer x frame base address register */ #define TLI_LxFLLEN(layerx) REG32((layerx) + 0xB0U) /*!< TLI layer x frame line length register */ #define TLI_LxFTLN(layerx) REG32((layerx) + 0xB4U) /*!< TLI layer x frame total line number register */ -#define TLI_LxLUT(layerx) REG32((layerx) + 0xC4U) /*!< TLI ayer x Look Up Table register */ - +#define TLI_LxLUT(layerx) REG32((layerx) + 0xC4U) /*!< TLI layer x look up table register */ /* bits definitions */ /* TLI_SPSZ */ @@ -154,8 +178,8 @@ #define TLI_LxFBADDR_FBADD BITS(0,31) /*!< frame buffer base address */ /* TLI_LxFLLEN */ -#define TLI_LxFLLEN_FLL BITS(0,12) /*!< frame line length */ -#define TLI_LxFLLEN_STDOFF BITS(16,28) /*!< frame buffer stride offset */ +#define TLI_LxFLLEN_FLL BITS(0,13) /*!< frame line length */ +#define TLI_LxFLLEN_STDOFF BITS(16,29) /*!< frame buffer stride offset */ /* TLI_LxFTLN */ #define TLI_LxFTLN_FTLN BITS(0,10) /*!< frame total line number */ @@ -167,14 +191,13 @@ #define TLI_LxLUT_TADD BITS(24,31) /*!< look up table write address */ /* constants definitions */ - /* TLI parameter struct definitions */ typedef struct -{ - uint32_t synpsz_vpsz; /*!< size of the vertical synchronous pulse */ - uint32_t synpsz_hpsz; /*!< size of the horizontal synchronous pulse */ - uint32_t backpsz_vbpsz; /*!< size of the vertical back porch plus synchronous pulse */ - uint32_t backpsz_hbpsz; /*!< size of the horizontal back porch plus synchronous pulse */ +{ + uint16_t synpsz_vpsz; /*!< size of the vertical synchronous pulse */ + uint16_t synpsz_hpsz; /*!< size of the horizontal synchronous pulse */ + uint16_t backpsz_vbpsz; /*!< size of the vertical back porch plus synchronous pulse */ + uint16_t backpsz_hbpsz; /*!< size of the horizontal back porch plus synchronous pulse */ uint32_t activesz_vasz; /*!< size of the vertical active area width plus back porch and synchronous pulse */ uint32_t activesz_hasz; /*!< size of the horizontal active area width plus back porch and synchronous pulse */ uint32_t totalsz_vtsz; /*!< vertical total size of the display */ @@ -186,141 +209,168 @@ typedef struct uint32_t signalpolarity_vs; /*!< vertical pulse polarity selection */ uint32_t signalpolarity_de; /*!< data enable polarity selection */ uint32_t signalpolarity_pixelck; /*!< pixel clock polarity selection */ -}tli_parameter_struct; +}tli_parameter_struct; -/* TLI Layer parameter struct definitions */ +/* TLI layer parameter struct definitions */ typedef struct -{ - uint32_t layer_window_rightpos; /*!< window right position */ - uint32_t layer_window_leftpos; /*!< window left position */ - uint32_t layer_window_bottompos; /*!< window bottom position */ - uint32_t layer_window_toppos; /*!< window top position */ +{ + uint16_t layer_window_rightpos; /*!< window right position */ + uint16_t layer_window_leftpos; /*!< window left position */ + uint16_t layer_window_bottompos; /*!< window bottom position */ + uint16_t layer_window_toppos; /*!< window top position */ uint32_t layer_ppf; /*!< packeted pixel format */ - uint32_t layer_sa; /*!< specified alpha */ - uint32_t layer_default_alpha; /*!< the default color alpha */ - uint32_t layer_default_red; /*!< the default color red */ - uint32_t layer_default_green; /*!< the default color green */ - uint32_t layer_default_blue; /*!< the default color blue */ + uint8_t layer_sa; /*!< specified alpha */ + uint8_t layer_default_alpha; /*!< the default color alpha */ + uint8_t layer_default_red; /*!< the default color red */ + uint8_t layer_default_green; /*!< the default color green */ + uint8_t layer_default_blue; /*!< the default color blue */ uint32_t layer_acf1; /*!< alpha calculation factor 1 of blending method */ uint32_t layer_acf2; /*!< alpha calculation factor 2 of blending method */ uint32_t layer_frame_bufaddr; /*!< frame buffer base address */ - uint32_t layer_frame_buf_stride_offset; /*!< frame buffer stride offset */ - uint32_t layer_frame_line_length; /*!< frame line length */ - uint32_t layer_frame_total_line_number; /*!< frame total line number */ -}tli_layer_parameter_struct; + uint16_t layer_frame_buf_stride_offset; /*!< frame buffer stride offset */ + uint16_t layer_frame_line_length; /*!< frame line length */ + uint16_t layer_frame_total_line_number; /*!< frame total line number */ +}tli_layer_parameter_struct; /* TLI layer LUT parameter struct definitions */ typedef struct -{ +{ uint32_t layer_table_addr; /*!< look up table write address */ - uint32_t layer_lut_channel_red; /*!< red channel of a LUT entry */ - uint32_t layer_lut_channel_green; /*!< green channel of a LUT entry */ - uint32_t layer_lut_channel_blue; /*!< blue channel of a LUT entry */ -}tli_layer_lut_parameter_struct; + uint8_t layer_lut_channel_red; /*!< red channel of a LUT entry */ + uint8_t layer_lut_channel_green; /*!< green channel of a LUT entry */ + uint8_t layer_lut_channel_blue; /*!< blue channel of a LUT entry */ +}tli_layer_lut_parameter_struct; /* packeted pixel format */ -typedef enum +typedef enum { - LAYER_PPF_ARGB8888, /*!< layerx pixel format ARGB8888 */ - LAYER_PPF_RGB888, /*!< layerx pixel format RGB888 */ - LAYER_PPF_RGB565, /*!< layerx pixel format RGB565 */ - LAYER_PPF_ARGB1555, /*!< layerx pixel format ARGB1555 */ - LAYER_PPF_ARGB4444, /*!< layerx pixel format ARGB4444 */ - LAYER_PPF_L8, /*!< layerx pixel format L8 */ - LAYER_PPF_AL44, /*!< layerx pixel format AL44 */ - LAYER_PPF_AL88 /*!< layerx pixel format AL88 */ -} tli_layer_ppf_enum; + LAYER_PPF_ARGB8888, /*!< layerx pixel format ARGB8888 */ + LAYER_PPF_RGB888, /*!< layerx pixel format RGB888 */ + LAYER_PPF_RGB565, /*!< layerx pixel format RGB565 */ + LAYER_PPF_ARGB1555, /*!< layerx pixel format ARGB1555 */ + LAYER_PPF_ARGB4444, /*!< layerx pixel format ARGB4444 */ + LAYER_PPF_L8, /*!< layerx pixel format L8 */ + LAYER_PPF_AL44, /*!< layerx pixel format AL44 */ + LAYER_PPF_AL88 /*!< layerx pixel format AL88 */ +}tli_layer_ppf_enum; + +/* TLI flags */ +#define TLI_FLAG_VDE TLI_STAT_VDE /*!< current VDE status */ +#define TLI_FLAG_HDE TLI_STAT_HDE /*!< current HDE status */ +#define TLI_FLAG_VS TLI_STAT_VS /*!< current VS status of the TLI */ +#define TLI_FLAG_HS TLI_STAT_HS /*!< current HS status of the TLI */ +#define TLI_FLAG_LM BIT(0) | BIT(31) /*!< line mark interrupt flag */ +#define TLI_FLAG_FE BIT(1) | BIT(31) /*!< FIFO error interrupt flag */ +#define TLI_FLAG_TE BIT(2) | BIT(31) /*!< transaction error interrupt flag */ +#define TLI_FLAG_LCR BIT(3) | BIT(31) /*!< layer configuration reloaded interrupt flag */ + +/* TLI interrupt enable or disable */ +#define TLI_INT_LM BIT(0) /*!< line mark interrupt */ +#define TLI_INT_FE BIT(1) /*!< FIFO error interrupt */ +#define TLI_INT_TE BIT(2) /*!< transaction error interrupt */ +#define TLI_INT_LCR BIT(3) /*!< layer configuration reloaded interrupt */ + +/* TLI interrupt flag */ +#define TLI_INT_FLAG_LM BIT(0) /*!< line mark interrupt flag */ +#define TLI_INT_FLAG_FE BIT(1) /*!< FIFO error interrupt flag */ +#define TLI_INT_FLAG_TE BIT(2) /*!< transaction error interrupt flag */ +#define TLI_INT_FLAG_LCR BIT(3) /*!< layer configuration reloaded interrupt flag */ /* layer reload configure */ -#define TLI_FRAME_BLANK_RELOAD_EN ((uint8_t)0x00U) /*!< the layer configuration will be reloaded at frame blank */ -#define TLI_REQUEST_RELOAD_EN ((uint8_t)0x01U) /*!< the layer configuration will be reloaded after this bit sets */ +#define TLI_FRAME_BLANK_RELOAD_EN ((uint8_t)0x00U) /*!< the layer configuration will be reloaded at frame blank */ +#define TLI_REQUEST_RELOAD_EN ((uint8_t)0x01U) /*!< the layer configuration will be reloaded after this bit sets */ -/* dither Function */ -#define TLI_DITHER_DISABLE ((uint8_t)0x00U) /*!< dither function disable */ -#define TLI_DITHER_ENABLE ((uint8_t)0x01U) /*!< dither function enable */ +/* dither function */ +#define TLI_DITHER_DISABLE ((uint8_t)0x00U) /*!< dither function disable */ +#define TLI_DITHER_ENABLE ((uint8_t)0x01U) /*!< dither function enable */ /* horizontal pulse polarity selection */ - -#define TLI_HSYN_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< horizontal synchronous pulse active low */ -#define TLI_HSYN_ACTLIVE_HIGHT TLI_CTL_HPPS /*!< horizontal synchronous pulse active high */ - +#define TLI_HSYN_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< horizontal synchronous pulse active low */ +#define TLI_HSYN_ACTLIVE_HIGHT TLI_CTL_HPPS /*!< horizontal synchronous pulse active high */ /* vertical pulse polarity selection */ +#define TLI_VSYN_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< vertical synchronous pulse active low */ +#define TLI_VSYN_ACTLIVE_HIGHT TLI_CTL_VPPS /*!< vertical synchronous pulse active high */ -#define TLI_VSYN_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< vertical synchronous pulse active low */ -#define TLI_VSYN_ACTLIVE_HIGHT TLI_CTL_VPPS /*!< vertical synchronous pulse active high */ +/* pixel clock polarity selection */ +#define TLI_PIXEL_CLOCK_TLI ((uint32_t)0x00000000U) /*!< pixel clock is TLI clock */ +#define TLI_PIXEL_CLOCK_INVERTEDTLI TLI_CTL_CLKPS /*!< pixel clock is inverted TLI clock */ - -/* pixel Clock Polarity Selection */ - -#define TLI_PIXEL_CLOCK_TLI ((uint32_t)0x00000000U) /*!< pixel clock is TLI clock */ -#define TLI_PIXEL_CLOCK_INVERTEDTLI TLI_CTL_CLKPS /*!< pixel clock is inverted TLI clock */ - - -/* data Enable Polarity Selection */ - -#define TLI_DE_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< data enable active low */ -#define TLI_DE_ACTLIVE_HIGHT TLI_CTL_DEPS /*!< data enable active high */ +/* data enable polarity selection */ +#define TLI_DE_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< data enable active low */ +#define TLI_DE_ACTLIVE_HIGHT TLI_CTL_DEPS /*!< data enable active high */ /* alpha calculation factor 1 of blending method */ -#define LxBLEND_ACF1(regval) (BITS(8,10) & ((regval)<<8)) -#define LAYER_ACF1_SA LxBLEND_ACF1(4) /*!< normalization specified alpha */ -#define LAYER_ACF1_PASA LxBLEND_ACF1(6) /*!< normalization pixel alpha * normalization specified alpha */ +#define LxBLEND_ACF1(regval) (BITS(8,10) & ((uint32_t)(regval)<<8)) +#define LAYER_ACF1_SA LxBLEND_ACF1(4) /*!< normalization specified alpha */ +#define LAYER_ACF1_PASA LxBLEND_ACF1(6) /*!< normalization pixel alpha * normalization specified alpha */ + +/* alpha calculation factor 2 of blending method */ +#define LxBLEND_ACF2(regval) (BITS(0,2) & ((uint32_t)(regval))) +#define LAYER_ACF2_SA LxBLEND_ACF2(5) /*!< normalization specified alpha */ +#define LAYER_ACF2_PASA LxBLEND_ACF2(7) /*!< normalization pixel alpha * normalization specified alpha */ -/* alpha calculation factor 2 of blending method*/ -#define LxBLEND_ACF2(regval) (BITS(0,2) & ((regval))) -#define LAYER_ACF2_SA LxBLEND_ACF2(5) /*!< normalization specified alpha */ -#define LAYER_ACF2_PASA LxBLEND_ACF2(7) /*!< normalization pixel alpha x normalization specified alpha */ /* function declarations */ - -/* deinitialize TLI */ +/* initialization functions, TLI enable or disable, TLI reload mode configuration */ +/* deinitialize TLI registers */ void tli_deinit(void); +/* initialize the parameters of TLI parameter structure with the default values, it is suggested + that call this function after a tli_parameter_struct structure is defined */ +void tli_struct_para_init(tli_parameter_struct *tli_struct); /* initialize TLI */ void tli_init(tli_parameter_struct *tli_struct); -/* TLI dither function enable */ -void tli_dither_config(uint8_t ditherstat); +/* configure TLI dither function */ +void tli_dither_config(uint8_t dither_stat); /* enable TLI */ void tli_enable(void); /* disable TLI */ void tli_disable(void); -/* TLI reload mode config*/ -void tli_reload_config(uint8_t reloadmod); +/* configurate TLI reload mode */ +void tli_reload_config(uint8_t reload_mod); -/* TLI interrupt enable */ -void tli_interrupt_enable(uint32_t inttype); -/* TLI interrupt disable */ -void tli_interrupt_disable(uint32_t inttype); -/* get TLI interrupt flag */ -FlagStatus tli_interrupt_flag_get(uint32_t intflag); -/* clear TLI interrupt flag */ -void tli_interrupt_flag_clear(uint32_t intflag); +/* TLI layer configuration functions */ +/* initialize the parameters of TLI layer structure with the default values, it is suggested + that call this function after a tli_layer_parameter_struct structure is defined */ +void tli_layer_struct_para_init(tli_layer_parameter_struct *layer_struct); +/* initialize TLI layer */ +void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct); +/* reconfigure window position */ +void tli_layer_window_offset_modify(uint32_t layerx,uint16_t offset_x,uint16_t offset_y); +/* initialize the parameters of TLI layer LUT structure with the default values, it is suggested + that call this function after a tli_layer_lut_parameter_struct structure is defined */ +void tli_lut_struct_para_init(tli_layer_lut_parameter_struct *lut_struct); +/* initialize TLI layer LUT */ +void tli_lut_init(uint32_t layerx,tli_layer_lut_parameter_struct *lut_struct); +/* initialize TLI layer color key */ +void tli_color_key_init(uint32_t layerx,uint8_t redkey,uint8_t greenkey,uint8_t bluekey); +/* enable TLI layer */ +void tli_layer_enable(uint32_t layerx); +/* disable TLI layer */ +void tli_layer_disable(uint32_t layerx); +/* enable TLI layer color keying */ +void tli_color_key_enable(uint32_t layerx); +/* disable TLI layer color keying */ +void tli_color_key_disable(uint32_t layerx); +/* enable TLI layer LUT */ +void tli_lut_enable(uint32_t layerx); +/* disable TLI layer LUT */ +void tli_lut_disable(uint32_t layerx); /* set line mark value */ -void tli_line_mark_set(uint32_t linenum); +void tli_line_mark_set(uint16_t line_num); /* get current displayed position */ uint32_t tli_current_pos_get(void); -/* get TLI state */ -FlagStatus tli_flag_get(uint32_t state); -/* TLI layer enable */ -void tli_layer_enable(uint32_t layerx); -/* TLI layer disable */ -void tli_layer_disable(uint32_t layerx); -/* TLI layer color keying enable */ -void tli_color_key_enable(uint32_t layerx); -/* TLI layer color keying disable */ -void tli_color_key_disable(uint32_t layerx); -/* TLI layer LUT enable */ -void tli_lut_enable(uint32_t layerx); -/* TLI layer LUT disable */ -void tli_lut_disable(uint32_t layerx); -/* TLI layer initialize */ -void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct); -/* TLI layer initialize */ -void tli_layer_window_offset_modify(uint32_t layerx,uint32_t offset_x,uint32_t offset_y); -/* TLI layer lut initialize */ -void tli_lut_init(uint32_t layerx,tli_layer_lut_parameter_struct *lut_struct); -/* TLI layer key initialize */ -void tli_ckey_init(uint32_t layerx,uint32_t redkey,uint32_t greenkey,uint32_t bluekey); +/* flag and interrupt functions */ +/* enable TLI interrupt */ +void tli_interrupt_enable(uint32_t int_flag); +/* disable TLI interrupt */ +void tli_interrupt_disable(uint32_t int_flag); +/* get TLI interrupt flag */ +FlagStatus tli_interrupt_flag_get(uint32_t int_flag); +/* clear TLI interrupt flag */ +void tli_interrupt_flag_clear(uint32_t int_flag); +/* get TLI flag or state in TLI_INTF register or TLI_STAT register */ +FlagStatus tli_flag_get(uint32_t flag); #endif /* GD32F4XX_TLI_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h index 7925b91af3..f321b15d28 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_trng.h - \brief definitions for the TRNG + \file gd32f4xx_trng.h + \brief definitions for the TRNG + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_TRNG_H @@ -14,13 +39,13 @@ #include "gd32f4xx.h" -/* EXTI definitions */ +/* TRNG definitions */ #define TRNG TRNG_BASE /* registers definitions */ -#define TRNG_CTL REG32(TRNG + 0x00U) /*!< interrupt enable register */ -#define TRNG_STAT REG32(TRNG + 0x04U) /*!< event enable register */ -#define TRNG_DATA REG32(TRNG + 0x08U) /*!< rising edge trigger enable register */ +#define TRNG_CTL REG32(TRNG + 0x00U) /*!< control register */ +#define TRNG_STAT REG32(TRNG + 0x04U) /*!< status register */ +#define TRNG_DATA REG32(TRNG + 0x08U) /*!< data register */ /* bits definitions */ /* TRNG_CTL */ @@ -40,7 +65,7 @@ /* constants definitions */ /* trng status flag */ typedef enum -{ +{ TRNG_FLAG_DRDY = TRNG_STAT_DRDY, /*!< random Data ready status */ TRNG_FLAG_CECS = TRNG_STAT_CECS, /*!< clock error current status */ TRNG_FLAG_SECS = TRNG_STAT_SECS /*!< seed error current status */ @@ -54,6 +79,7 @@ typedef enum }trng_int_flag_enum; /* function declarations */ +/* initialization functions */ /* deinitialize the TRNG */ void trng_deinit(void); /* enable the TRNG interface */ @@ -62,14 +88,14 @@ void trng_enable(void); void trng_disable(void); /* get the true random data */ uint32_t trng_get_true_random_data(void); + +/* flag & interrupt functions */ +/* trng interrupt enable */ +void trng_interrupt_enable(void); +/* trng interrupt disable */ +void trng_interrupt_disable(void); /* get the trng status flags */ FlagStatus trng_flag_get(trng_flag_enum flag); -/* clear the trng status flags */ -void trng_flag_clear(trng_flag_enum flag); -/* the trng interrupt enable */ -void trng_interrupt_enable(void); -/* the trng interrupt disable */ -void trng_interrupt_disable(void); /* get the trng interrupt flags */ FlagStatus trng_interrupt_flag_get(trng_int_flag_enum int_flag); /* clear the trng interrupt flags */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h index 5350f5e5b5..3cd49d827f 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_usart.h - \brief definitions for the USART + \file gd32f4xx_usart.h + \brief definitions for the USART + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_USART_H @@ -14,8 +39,8 @@ #include "gd32f4xx.h" -/* USARTx(x=0,1) definitions */ -#define USART1 USART_BASE +/* USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) definitions */ +#define USART1 USART_BASE /*!< USART1 base address */ #define USART2 (USART_BASE+0x00000400U) /*!< USART2 base address */ #define UART3 (USART_BASE+0x00000800U) /*!< UART3 base address */ #define UART4 (USART_BASE+0x00000C00U) /*!< UART4 base address */ @@ -102,7 +127,7 @@ /* USARTx_GP */ #define USART_GP_PSC BITS(0,7) /*!< prescaler value for dividing the system clock */ #define USART_GP_GUAT BITS(8,15) /*!< guard time value in smartcard mode */ - + /* USARTx_CTL3 */ #define USART_CTL3_RTEN BIT(0) /*!< receiver timeout enable */ #define USART_CTL3_SCRTNUM BITS(1,3) /*!< smartcard auto-retry number */ @@ -131,59 +156,85 @@ /* constants definitions */ /* define the USART bit position and its register index offset */ #define USART_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) -#define USART_REG_VAL(usartx, offset) (REG32((usartx) + ((uint32_t)(offset) >> 6))) +#define USART_REG_VAL(usartx, offset) (REG32((usartx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) #define USART_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define USART_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define USART_REG_VAL2(usartx, offset) (REG32((usartx) + ((uint32_t)(offset) >> 22))) +#define USART_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) /* register offset */ -#define STAT0_REG_OFFSET 0x00U /*!< STAT0 register offset */ -#define STAT1_REG_OFFSET 0x88U /*!< STAT1 register offset */ -#define CHC_REG_OFFSET 0xC0U /*!< CHC register offset */ -#define CTL0_REG_OFFSET 0x0CU /*!< CTL0 register offset */ -#define CTL1_REG_OFFSET 0x10U /*!< CTL1 register offset */ -#define CTL2_REG_OFFSET 0x14U /*!< CTL2 register offset */ -#define CTL3_REG_OFFSET 0x80U /*!< CTL2 register offset */ +#define USART_STAT0_REG_OFFSET 0x00U /*!< STAT0 register offset */ +#define USART_STAT1_REG_OFFSET 0x88U /*!< STAT1 register offset */ +#define USART_CTL0_REG_OFFSET 0x0CU /*!< CTL0 register offset */ +#define USART_CTL1_REG_OFFSET 0x10U /*!< CTL1 register offset */ +#define USART_CTL2_REG_OFFSET 0x14U /*!< CTL2 register offset */ +#define USART_CTL3_REG_OFFSET 0x80U /*!< CTL3 register offset */ +#define USART_CHC_REG_OFFSET 0xC0U /*!< CHC register offset */ /* USART flags */ typedef enum { /* flags in STAT0 register */ - USART_FLAG_CTSF = USART_REGIDX_BIT(STAT0_REG_OFFSET, 9U), /*!< CTS change flag */ - USART_FLAG_LBDF = USART_REGIDX_BIT(STAT0_REG_OFFSET, 8U), /*!< LIN break detected flag */ - USART_FLAG_TBE = USART_REGIDX_BIT(STAT0_REG_OFFSET, 7U), /*!< transmit data buffer empty */ - USART_FLAG_TC = USART_REGIDX_BIT(STAT0_REG_OFFSET, 6U), /*!< transmission complete */ - USART_FLAG_RBNE = USART_REGIDX_BIT(STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty */ - USART_FLAG_IDLEF = USART_REGIDX_BIT(STAT0_REG_OFFSET, 4U), /*!< IDLE frame detected flag */ - USART_FLAG_ORERR = USART_REGIDX_BIT(STAT0_REG_OFFSET, 3U), /*!< overrun error */ - USART_FLAG_NERR = USART_REGIDX_BIT(STAT0_REG_OFFSET, 2U), /*!< noise error flag */ - USART_FLAG_FERR = USART_REGIDX_BIT(STAT0_REG_OFFSET, 1U), /*!< frame error flag */ - USART_FLAG_PERR = USART_REGIDX_BIT(STAT0_REG_OFFSET, 0U), /*!< parity error flag */ + USART_FLAG_CTS = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 9U), /*!< CTS change flag */ + USART_FLAG_LBD = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected flag */ + USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 7U), /*!< transmit data buffer empty */ + USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete */ + USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty */ + USART_FLAG_IDLE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 4U), /*!< IDLE frame detected flag */ + USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 3U), /*!< overrun error */ + USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 2U), /*!< noise error flag */ + USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 1U), /*!< frame error flag */ + USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 0U), /*!< parity error flag */ /* flags in STAT1 register */ - USART_FLAG_BSY = USART_REGIDX_BIT(STAT1_REG_OFFSET, 16U), /*!< busy flag */ - USART_FLAG_EBF = USART_REGIDX_BIT(STAT1_REG_OFFSET, 12U), /*!< end of block flag */ - USART_FLAG_RTF = USART_REGIDX_BIT(STAT1_REG_OFFSET, 11U), /*!< receiver timeout flag */ + USART_FLAG_BSY = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 16U), /*!< busy flag */ + USART_FLAG_EB = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 12U), /*!< end of block flag */ + USART_FLAG_RT = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 11U), /*!< receiver timeout flag */ /* flags in CHC register */ - USART_FLAG_EPERR = USART_REGIDX_BIT(CHC_REG_OFFSET, 8U), /*!< early parity error flag */ + USART_FLAG_EPERR = USART_REGIDX_BIT(USART_CHC_REG_OFFSET, 8U), /*!< early parity error flag */ }usart_flag_enum; /* USART interrupt flags */ typedef enum { /* interrupt flags in CTL0 register */ - USART_INT_PERRIE = USART_REGIDX_BIT(CTL0_REG_OFFSET, 8U), /*!< parity error interrupt */ - USART_INT_TBEIE = USART_REGIDX_BIT(CTL0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt */ - USART_INT_TCIE = USART_REGIDX_BIT(CTL0_REG_OFFSET, 6U), /*!< transmission complete interrupt */ - USART_INT_RBNEIE = USART_REGIDX_BIT(CTL0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and overrun error interrupt */ - USART_INT_IDLEIE = USART_REGIDX_BIT(CTL0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt */ + USART_INT_FLAG_PERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 8U, USART_STAT0_REG_OFFSET, 0U), /*!< parity error interrupt and flag */ + USART_INT_FLAG_TBE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 7U, USART_STAT0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt and flag */ + USART_INT_FLAG_TC = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 6U, USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete interrupt and flag */ + USART_INT_FLAG_RBNE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and flag */ + USART_INT_FLAG_RBNE_ORERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT0_REG_OFFSET, 3U), /*!< read data buffer not empty interrupt and overrun error flag */ + USART_INT_FLAG_IDLE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 4U, USART_STAT0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt and flag */ /* interrupt flags in CTL1 register */ - USART_INT_LBDIE = USART_REGIDX_BIT(CTL1_REG_OFFSET, 6U), /*!< LIN break detected interrupt */ + USART_INT_FLAG_LBD = USART_REGIDX_BIT2(USART_CTL1_REG_OFFSET, 6U, USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected interrupt and flag */ /* interrupt flags in CTL2 register */ - USART_INT_CTSIE = USART_REGIDX_BIT(CTL2_REG_OFFSET, 10U), /*!< CTS interrupt */ - USART_INT_ERRIE = USART_REGIDX_BIT(CTL2_REG_OFFSET, 0U), /*!< error interrupt */ + USART_INT_FLAG_CTS = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 10U, USART_STAT0_REG_OFFSET, 9U), /*!< CTS interrupt and flag */ + USART_INT_FLAG_ERR_ORERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 3U), /*!< error interrupt and overrun error */ + USART_INT_FLAG_ERR_NERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 2U), /*!< error interrupt and noise error flag */ + USART_INT_FLAG_ERR_FERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 1U), /*!< error interrupt and frame error flag */ /* interrupt flags in CTL3 register */ - USART_INT_EBIE = USART_REGIDX_BIT(CTL3_REG_OFFSET, 5U), /*!< interrupt enable bit of end of block event */ - USART_INT_RTIE = USART_REGIDX_BIT(CTL3_REG_OFFSET, 4U), /*!< interrupt enable bit of receive timeout event */ + USART_INT_FLAG_EB = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 5U, USART_STAT1_REG_OFFSET, 12U), /*!< interrupt enable bit of end of block event and flag */ + USART_INT_FLAG_RT = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 4U, USART_STAT1_REG_OFFSET, 11U), /*!< interrupt enable bit of receive timeout event and flag */ }usart_interrupt_flag_enum; +/* USART interrupt flags */ +typedef enum +{ + /* interrupt in CTL0 register */ + USART_INT_PERR = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 8U), /*!< parity error interrupt */ + USART_INT_TBE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt */ + USART_INT_TC = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 6U), /*!< transmission complete interrupt */ + USART_INT_RBNE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and overrun error interrupt */ + USART_INT_IDLE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt */ + /* interrupt in CTL1 register */ + USART_INT_LBD = USART_REGIDX_BIT(USART_CTL1_REG_OFFSET, 6U), /*!< LIN break detected interrupt */ + /* interrupt in CTL2 register */ + USART_INT_CTS = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 10U), /*!< CTS interrupt */ + USART_INT_ERR = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 0U), /*!< error interrupt */ + /* interrupt in CTL3 register */ + USART_INT_EB = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 5U), /*!< interrupt enable bit of end of block event */ + USART_INT_RT = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 4U), /*!< interrupt enable bit of receive timeout event */ +}usart_interrupt_enum; + /* USART invert configure */ typedef enum { @@ -211,8 +262,8 @@ typedef enum /* USART parity bits definitions */ #define CTL0_PM(regval) (BITS(9,10) & ((uint32_t)(regval) << 9)) #define USART_PM_NONE CTL0_PM(0) /*!< no parity */ -#define USART_PM_ODD CTL0_PM(2) /*!< odd parity */ -#define USART_PM_EVEN CTL0_PM(3) /*!< even parity */ +#define USART_PM_EVEN CTL0_PM(2) /*!< even parity */ +#define USART_PM_ODD CTL0_PM(3) /*!< odd parity */ /* USART wakeup method in mute mode */ #define CTL0_WM(regval) (BIT(11) & ((uint32_t)(regval) << 11)) @@ -306,30 +357,6 @@ typedef enum #define USART_HCM_NONE CHC_HCM(0) /*!< nRTS signal equals to the rxne status register */ #define USART_HCM_EN CHC_HCM(1) /*!< nRTS signal is set when the last data bit has been sampled */ -/* interrupt enable in USART_CTL0 */ -#define USART_INTEN_PERRIE ((uint32_t)0x10000100U) /*!< parity error interrupt */ -#define USART_INTEN_TBEIE ((uint32_t)0x10000080U) /*!< transmitter buffer empty interrupt */ -#define USART_INTEN_TCIE ((uint32_t)0x10000040U) /*!< transmission complete interrupt */ -#define USART_INTEN_RBNEIE ((uint32_t)0x10000020U) /*!< read data buffer not empty interrupt and overrun error interrupt */ -#define USART_INTEN_IDLEIE ((uint32_t)0x10000010U) /*!< IDLE line detected interrupt */ - -/* interrupt enable flag in USART_CTL1 */ -#define USART_INTEN_LBDIE ((uint32_t)0x20000040U) /*!< LIN break detected interrupt */ - -/* interrupt enable flag in USART_CTL2 */ -#define USART_INTEN_ERRIE ((uint32_t)0x40000001U) /*!< error interrupt */ -#define USART_INTEN_CTSIE ((uint32_t)0x40000400U) /*!< CTS interrupt*/ - -/* interrupt enable flag in USART_CTL3 */ -#define USART_INTEN_RTIE ((uint32_t)0x80000010U) /*!< interrupt enable bit of receive timeout event */ -#define USART_INTEN_EBIE ((uint32_t)0x80000020U) /*!< interrupt enable bit of end of block event */ - -#define USART_INTEN_MASK ((uint32_t)0x00000FFFU) /*!< USART interrupt mask */ -#define USART_INTS_CTL0 ((uint32_t)0x10000000U) /*!< interrupt in USART_CTL0 */ -#define USART_INTS_CTL1 ((uint32_t)0x20000000U) /*!< interrupt in USART_CTL1 */ -#define USART_INTS_CTL2 ((uint32_t)0x40000000U) /*!< interrupt in USART_CTL2 */ -#define USART_INTS_CTL3 ((uint32_t)0x80000000U) /*!< interrupt in USART_CTL3 */ - /* function declarations */ /* initialization functions */ /* reset USART */ @@ -342,8 +369,6 @@ void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg); void usart_word_length_set(uint32_t usart_periph, uint32_t wlen); /* configure usart stop bit length */ void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen); - -/* USART normal mode communication */ /* enable usart */ void usart_enable(uint32_t usart_periph); /* disable usart */ @@ -352,6 +377,8 @@ void usart_disable(uint32_t usart_periph); void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig); /* configure USART receiver */ void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig); + +/* USART normal mode communication */ /* data is transmitted/received with the LSB/MSB first */ void usart_data_first_config(uint32_t usart_periph, uint32_t msbf); /* configure USART inverted */ @@ -382,43 +409,43 @@ void usart_mute_mode_disable(uint32_t usart_periph); void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmehtod); /* LIN mode communication */ -/* LIN mode enable */ +/* enable LIN mode */ void usart_lin_mode_enable(uint32_t usart_periph); -/* LIN mode disable */ +/* disable LIN mode */ void usart_lin_mode_disable(uint32_t usart_periph); /* LIN break detection length */ -void usart_lin_break_dection_length_config(uint32_t usart_periph, uint32_t lblen); +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen); /* send break frame */ void usart_send_break(uint32_t usart_periph); /* half-duplex communication */ -/* half-duplex enable */ +/* enable half-duplex mode */ void usart_halfduplex_enable(uint32_t usart_periph); -/* half-duplex disable */ +/* disable half-duplex mode */ void usart_halfduplex_disable(uint32_t usart_periph); /* synchronous communication */ -/* clock enable */ +/* enable CK pin in synchronous mode */ void usart_synchronous_clock_enable(uint32_t usart_periph); -/* clock disable */ +/* disable CK pin in synchronous mode */ void usart_synchronous_clock_disable(uint32_t usart_periph); /* configure usart synchronous mode parameters */ void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl); /* smartcard communication */ -/* guard time value configure in smartcard mode */ -void usart_guard_time_config(uint32_t usart_periph,uint32_t gaut); -/* smartcard mode enable */ +/* configure guard time value in smartcard mode */ +void usart_guard_time_config(uint32_t usart_periph, uint32_t guat); +/* enable smartcard mode */ void usart_smartcard_mode_enable(uint32_t usart_periph); -/* smartcard mode disable */ +/* disable smartcard mode */ void usart_smartcard_mode_disable(uint32_t usart_periph); -/* NACK enable in smartcard mode */ +/* enable NACK in smartcard mode */ void usart_smartcard_mode_nack_enable(uint32_t usart_periph); -/* NACK disable in smartcard mode */ +/* disable NACK in smartcard mode */ void usart_smartcard_mode_nack_disable(uint32_t usart_periph); -/* smartcard auto-retry number configure */ +/* configure smartcard auto-retry number */ void usart_smartcard_autoretry_config(uint32_t usart_periph, uint32_t scrtnum); -/* block length configure */ +/* configure block length */ void usart_block_length_config(uint32_t usart_periph, uint32_t bl); /* IrDA communication */ @@ -427,7 +454,7 @@ void usart_irda_mode_enable(uint32_t usart_periph); /* disable IrDA mode */ void usart_irda_mode_disable(uint32_t usart_periph); /* configure the peripheral clock prescaler */ -void usart_prescaler_config(uint32_t usart_periph, uint32_t psc); +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc); /* configure IrDA low-power */ void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp); @@ -445,23 +472,24 @@ void usart_parity_check_coherence_config(uint32_t usart_periph, uint32_t pcm); /* configure hardware flow control coherence mode */ void usart_hardware_flow_coherence_config(uint32_t usart_periph, uint32_t hcm); +/* DMA communication */ /* configure USART DMA for reception */ void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd); /* configure USART DMA for transmission */ void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd); -/* flag functions */ -/* get flag in STAT0/STAT1/CHC register */ +/* flag & interrupt functions */ +/* get flag in STAT0/STAT1 register */ FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag); -/* clear flag in STAT0/STAT1/CHC register */ +/* clear flag in STAT0/STAT1 register */ void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag); - -/* interrupt functions */ /* enable USART interrupt */ -void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag); +void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt); /* disable USART interrupt */ -void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag); -/* get USART interrupt enable flag */ -FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag); +void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt); +/* get USART interrupt and flag status */ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag); +/* clear interrupt flag in STAT0/STAT1 register */ +void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag); -#endif /* GD32F4XX_USART_H */ +#endif /* GD32F4XX_USART_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h index d76cbce32c..525b9a6e5a 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_wwdgt.h - \brief definitions for the WWDGT + \file gd32f4xx_wwdgt.h + \brief definitions for the WWDGT + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #ifndef GD32F4XX_WWDGT_H diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c index 73f89207ba..f249e6c840 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c @@ -1,24 +1,67 @@ /*! - \file gd32f4xx_adc.c - \brief ADC driver + \file gd32f4xx_adc.c + \brief ADC driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_adc.h" -#define REGULAR_CHANNEL_LENGTH_OFFSET ((uint32_t)20U) -#define INSERTED_CHANNEL_LENGTH_OFFSET ((uint32_t)20U) -#define REGULAR_DISCONTINUOUS_NUMBER ((uint32_t)13U) #define REGULAR_TRIGGER_MODE ((uint32_t)28U) #define INSERTED_TRIGGER_MODE ((uint32_t)20U) +/* discontinuous mode macro*/ +#define ADC_CHANNEL_LENGTH_SUBTRACT_ONE ((uint8_t)1U) + +/* ADC regular channel macro */ +#define ADC_REGULAR_CHANNEL_RANK_SIX ((uint8_t)6U) +#define ADC_REGULAR_CHANNEL_RANK_TWELVE ((uint8_t)12U) +#define ADC_REGULAR_CHANNEL_RANK_SIXTEEN ((uint8_t)16U) +#define ADC_REGULAR_CHANNEL_RANK_LENGTH ((uint8_t)5U) + +/* ADC sampling time macro */ +#define ADC_CHANNEL_SAMPLE_TEN ((uint8_t)10U) +#define ADC_CHANNEL_SAMPLE_EIGHTEEN ((uint8_t)18U) +#define ADC_CHANNEL_SAMPLE_LENGTH ((uint8_t)3U) + +/* ADC inserted channel macro */ +#define ADC_INSERTED_CHANNEL_RANK_LENGTH ((uint8_t)5U) +#define ADC_INSERTED_CHANNEL_SHIFT_LENGTH ((uint8_t)15U) + +/* ADC inserted channel offset macro */ +#define ADC_OFFSET_LENGTH ((uint8_t)3U) +#define ADC_OFFSET_SHIFT_LENGTH ((uint8_t)4U) /*! - \brief ADC reset + \brief reset ADC \param[in] none \param[out] none \retval none @@ -29,189 +72,10 @@ void adc_deinit(void) rcu_periph_reset_disable(RCU_ADCRST); } -/*! - \brief enable ADC interface - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] none - \param[out] none - \retval none -*/ -void adc_enable(uint32_t adc_periph) -{ - if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; - } -} - -/*! - \brief disable ADC interface - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] none - \param[out] none - \retval none -*/ -void adc_disable(uint32_t adc_periph) -{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON); -} - -/*! - \brief ADC data alignment config - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] inserted_channel : insert channel select - \arg ADC_DATAALIGN_RIGHT: LSB alignment - \arg ADC_DATAALIGN_LEFT: MSB alignment - \param[out] none - \retval none -*/ -void adc_data_alignment_config(uint32_t adc_periph , uint8_t data_alignment) -{ - if(data_alignment){ - ADC_CTL1(adc_periph) |= ADC_CTL1_DAL; - }else{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); - } -} - -/*! - \brief ADC resolution config - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] resolution: ADC resolution - \arg ADC_RESOLUTION_12B: 12-bit ADC resolution - \arg ADC_RESOLUTION_10B: 10-bit ADC resolution - \arg ADC_RESOLUTION_8B: 8-bit ADC resolution - \arg ADC_RESOLUTION_6B: 6-bit ADC resolution - \param[out] none - \retval none -*/ -void adc_resolution_config(uint32_t adc_periph , uint32_t resolution) -{ - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DRES); - ADC_CTL0(adc_periph) |= (uint32_t)resolution; -} - -/*! - \brief ADC calibration and reset calibration - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] none - \param[out] none - \retval none -*/ -void adc_calibration_enable(uint32_t adc_periph) -{ - /* reset the selected ADC1 calibration registers */ - ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; - /* check the RSTCLB bit state */ - while((ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ - } - /* enable ADC calibration process */ - ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; - /* check the CLB bit state */ - while((ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ - } -} - -/*! - \brief ADC discontinuous mode config - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] adc_channel_group: select the channel group - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \param[in] length: number of conversions in discontinuous mode,the number can be 1..8 - for regular channel ,the number is no effect for inserted channel - \param[out] none - \retval none -*/ -void adc_discontinuous_mode_config(uint32_t adc_periph , uint8_t adc_channel_group , uint8_t length) -{ - ADC_CTL0(adc_periph) &= ~((uint32_t)( ADC_CTL0_DISRC | ADC_CTL0_DISIC )); - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - /* config the number of conversions in discontinuous mode */ - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); - if((length <= 8U) && (length >= 1U)){ - ADC_CTL0(adc_periph) |= ((uint32_t)length - 1U) << REGULAR_DISCONTINUOUS_NUMBER; - } - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC; - break; - case ADC_INSERTED_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; - break; - default: - break; - } -} - -/*! - \brief config end of conversion mode - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] end_selection: end of conversion mode - \arg ADC_EOC_SET_SEQUENCE: only at the end of a sequence of regular conversions, the EOC bit is set - \arg ADC_EOC_SET_CONVERSION: at the end of each regular conversion, the EOC bit is set. - \param[out] none - \retval none -*/ -void adc_end_of_conversion_config(uint32_t adc_periph , uint8_t end_selection) -{ - switch(end_selection){ - case ADC_EOC_SET_SEQUENCE: - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_EOCM); - break; - case ADC_EOC_SET_CONVERSION: - ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_EOCM); - break; - default: - break; - } -} - -/*! - \brief ADC special function enable or disable - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] function: select the function to config - \arg ADC_SCAN_MODE: scan mode select - \arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically - \arg ADC_CONTINUOUS_MODE: continuous mode select - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void adc_special_function_config(uint32_t adc_periph , uint8_t function , ControlStatus newvalue) -{ - if(newvalue){ - switch(function){ - case ADC_SCAN_MODE: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_SM; - break; - case ADC_INSERTED_CHANNEL_AUTO: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_ICA; - break; - case ADC_CONTINUOUS_MODE: - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_CTN; - break; - default: - break; - } - }else{ - switch(function){ - case ADC_SCAN_MODE: - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_SM); - break; - case ADC_INSERTED_CHANNEL_AUTO: - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_ICA); - break; - case ADC_CONTINUOUS_MODE: - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_CTN); - break; - default: - break; - } - } -} - /*! \brief configure the ADC clock for all the ADCs \param[in] prescaler: configure ADCs prescaler ratio + only one parameter can be selected which is shown as below: \arg ADC_ADCCK_PCLK2_DIV2: PCLK2 div2 \arg ADC_ADCCK_PCLK2_DIV4: PCLK2 div4 \arg ADC_ADCCK_PCLK2_DIV6: PCLK2 div6 @@ -230,45 +94,320 @@ void adc_clock_config(uint32_t prescaler) } /*! - \brief configure the ADC clock for all the ADCs - \param[in] function: temperature sensor and internal reference voltage channel or VBAT channel + \brief enable or disable ADC special function + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] function: the function to config + only one parameter can be selected which is shown as below: + \arg ADC_SCAN_MODE: scan mode select + \arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically + \arg ADC_CONTINUOUS_MODE: continuous mode select + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_special_function_config(uint32_t adc_periph , uint32_t function , ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (function & ADC_SCAN_MODE)){ + /* enable scan mode */ + ADC_CTL0(adc_periph) |= ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* enable inserted channel group convert automatically */ + ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* enable continuous mode */ + ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE; + } + }else{ + if(0U != (function & ADC_SCAN_MODE)){ + /* disable scan mode */ + ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* disable inserted channel group convert automatically */ + ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* disable continuous mode */ + ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE; + } + } +} + +/*! + \brief configure ADC data alignment + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] data_alignment: data alignment select + only one parameter can be selected which is shown as below: + \arg ADC_DATAALIGN_RIGHT: LSB alignment + \arg ADC_DATAALIGN_LEFT: MSB alignment + \param[out] none + \retval none +*/ +void adc_data_alignment_config(uint32_t adc_periph , uint32_t data_alignment) +{ + if(ADC_DATAALIGN_RIGHT != data_alignment){ + /* MSB alignment */ + ADC_CTL1(adc_periph) |= ADC_CTL1_DAL; + }else{ + /* LSB alignment */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); + } +} + +/*! + \brief enable ADC interface + \param[in] adc_periph: ADCx,x=0,1,2 + \param[out] none + \retval none +*/ +void adc_enable(uint32_t adc_periph) +{ + if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ + /* enable ADC */ + ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; + } +} + +/*! + \brief disable ADC interface + \param[in] adc_periph: ADCx,x=0,1,2 + \param[out] none + \retval none +*/ +void adc_disable(uint32_t adc_periph) +{ + /* disable ADC */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON); +} + +/*! + \brief ADC calibration and reset calibration + \param[in] adc_periph: ADCx,x=0,1,2 + \param[out] none + \retval none +*/ +void adc_calibration_enable(uint32_t adc_periph) +{ + /* reset the selected ADC calibration registers */ + ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; + /* check the RSTCLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ + } + /* enable ADC calibration process */ + ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; + /* check the CLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ + } +} + +/*! + \brief configure temperature sensor and internal reference voltage channel or VBAT channel function + \param[in] function: temperature sensor and internal reference voltage channel or VBAT channel + only one parameter can be selected which is shown as below: \arg ADC_VBAT_CHANNEL_SWITCH: channel 18 (1/4 voltate of external battery) switch of ADC0 \arg ADC_TEMP_VREF_CHANNEL_SWITCH: channel 16 (temperature sensor) and 17 (internal reference voltage) switch of ADC0 \param[in] newvalue: ENABLE or DISABLE \param[out] none \retval none */ -void adc_channel_16_to_18(uint8_t function,ControlStatus newvalue) +void adc_channel_16_to_18(uint32_t function, ControlStatus newvalue) { if(newvalue){ - switch(function){ - case ADC_VBAT_CHANNEL_SWITCH: - ADC_SYNCCTL |= (uint32_t)ADC_SYNCCTL_VBATEN; - break; - case ADC_TEMP_VREF_CHANNEL_SWITCH: - ADC_SYNCCTL |= (uint32_t)ADC_SYNCCTL_TSVREN; - break; - default: - break; + if(RESET != (function & ADC_VBAT_CHANNEL_SWITCH)){ + /* enable ADC0 Vbat channel */ + ADC_SYNCCTL |= ADC_VBAT_CHANNEL_SWITCH; + } + if(RESET != (function & ADC_TEMP_VREF_CHANNEL_SWITCH)){ + /* enable ADC0 Vref and Temperature channel */ + ADC_SYNCCTL |= ADC_TEMP_VREF_CHANNEL_SWITCH; } }else{ - switch(function){ - case ADC_VBAT_CHANNEL_SWITCH: - ADC_SYNCCTL &= ~((uint32_t)ADC_SYNCCTL_VBATEN); - break; - case ADC_TEMP_VREF_CHANNEL_SWITCH: - ADC_SYNCCTL &= ~((uint32_t)ADC_SYNCCTL_TSVREN); - break; - default: - break; + if(RESET != (function & ADC_VBAT_CHANNEL_SWITCH)){ + /* disable ADC0 Vbat channel */ + ADC_SYNCCTL &= ~ADC_VBAT_CHANNEL_SWITCH; + } + if(RESET != (function & ADC_TEMP_VREF_CHANNEL_SWITCH)){ + /* disable ADC0 Vref and Temperature channel */ + ADC_SYNCCTL &= ~ADC_TEMP_VREF_CHANNEL_SWITCH; } } } /*! - \brief config the length of regular channel group or inserted channel group + \brief configure ADC resolution + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] resolution: ADC resolution + only one parameter can be selected which is shown as below: + \arg ADC_RESOLUTION_12B: 12-bit ADC resolution + \arg ADC_RESOLUTION_10B: 10-bit ADC resolution + \arg ADC_RESOLUTION_8B: 8-bit ADC resolution + \arg ADC_RESOLUTION_6B: 6-bit ADC resolution + \param[out] none + \retval none +*/ +void adc_resolution_config(uint32_t adc_periph , uint32_t resolution) +{ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DRES); + ADC_CTL0(adc_periph) |= (uint32_t)resolution; +} + +/*! + \brief configure ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] mode: ADC oversampling mode + only one parameter can be selected which is shown as below: + \arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger + \arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger + \param[in] shift: ADC oversampling shift + only one parameter can be selected which is shown as below: + \arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift + \param[in] ratio: ADC oversampling ratio + only one parameter can be selected which is shown as below: + \arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2 + \arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4 + \arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8 + \arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16 + \arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32 + \arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64 + \arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128 + \arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256 + \param[out] none + \retval none +*/ +void adc_oversample_mode_config(uint32_t adc_periph , uint32_t mode , uint16_t shift , uint8_t ratio) +{ + if(ADC_OVERSAMPLING_ONE_CONVERT == mode){ + ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS; + }else{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS); + } + /* config the shift and ratio */ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS)); + ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio); +} + +/*! + \brief enable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + \param[out] none + \retval none +*/ +void adc_oversample_mode_enable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) |= ADC_OVSAMPCTL_OVSEN; +} + +/*! + \brief disable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + \param[out] none + \retval none +*/ +void adc_oversample_mode_disable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN); +} + +/*! + \brief enable DMA request + \param[in] adc_periph: ADCx,x=0,1,2 + \param[out] none + \retval none +*/ +void adc_dma_mode_enable(uint32_t adc_periph) +{ + /* enable DMA request */ + ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA); +} + +/*! + \brief disable DMA request + \param[in] adc_periph: ADCx,x=0,1,2 + \param[out] none + \retval none +*/ +void adc_dma_mode_disable(uint32_t adc_periph) +{ + /* disable DMA request */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA); +} + +/*! + \brief when DMA=1, the DMA engine issues a request at end of each regular conversion + \param[in] adc_periph: ADCx,x=0,1,2 + \param[out] none + \retval none +*/ +void adc_dma_request_after_last_enable(uint32_t adc_periph) +{ + ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DDM); +} + +/*! + \brief the DMA engine is disabled after the end of transfer signal from DMA controller is detected + \param[in] adc_periph: ADCx,x=0,1,2 + \param[out] none + \retval none +*/ +void adc_dma_request_after_last_disable(uint32_t adc_periph) +{ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DDM); +} + +/*! + \brief configure ADC discontinuous mode \param[in] adc_periph: ADCx,x=0,1,2 \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular & inserted channel + \param[in] length: number of conversions in discontinuous mode,the number can be 1..8 + for regular channel ,the number has no effect for inserted channel + \param[out] none + \retval none +*/ +void adc_discontinuous_mode_config(uint32_t adc_periph , uint8_t adc_channel_group , uint8_t length) +{ + /* disable discontinuous mode of regular & inserted channel */ + ADC_CTL0(adc_periph) &= ~((uint32_t)( ADC_CTL0_DISRC | ADC_CTL0_DISIC )); + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* config the number of conversions in discontinuous mode */ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); + if((length <= 8U) && (length >= 1U)){ + ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + } + /* enable regular channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC; + break; + case ADC_INSERTED_CHANNEL: + /* enable inserted channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; + break; + case ADC_CHANNEL_DISCON_DISABLE: + /* disable discontinuous mode of regular & inserted channel */ + default: + break; + } +} + +/*! + \brief configure the length of regular channel group or inserted channel group + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: \arg ADC_REGULAR_CHANNEL: regular channel group \arg ADC_INSERTED_CHANNEL: inserted channel group \param[in] length: the length of the channel @@ -282,14 +421,14 @@ void adc_channel_length_config(uint32_t adc_periph , uint8_t adc_channel_group , switch(adc_channel_group){ case ADC_REGULAR_CHANNEL: if((length >= 1U) && (length <= 16U)){ - ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); - ADC_RSQ0(adc_periph) |= (uint32_t)((length-1U) << REGULAR_CHANNEL_LENGTH_OFFSET); + ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); + ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); } break; case ADC_INSERTED_CHANNEL: if((length >= 1U) && (length <= 4U)){ - ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL); - ADC_ISQ(adc_periph) |= (uint32_t)((length-1U) << INSERTED_CHANNEL_LENGTH_OFFSET); + ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL); + ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); } break; default: @@ -298,12 +437,230 @@ void adc_channel_length_config(uint32_t adc_periph , uint8_t adc_channel_group , } /*! - \brief ADC external trigger enable + \brief configure ADC regular channel + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] rank: the regular group sequencer rank,this parameter must be between 0 to 15 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..18): ADC Channelx + \param[in] sample_time: the sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_3: 3 cycles + \arg ADC_SAMPLETIME_15: 15 cycles + \arg ADC_SAMPLETIME_28: 28 cycles + \arg ADC_SAMPLETIME_56: 56 cycles + \arg ADC_SAMPLETIME_84: 84 cycles + \arg ADC_SAMPLETIME_112: 112 cycles + \arg ADC_SAMPLETIME_144: 144 cycles + \arg ADC_SAMPLETIME_480: 480 cycles + \param[out] none + \retval none +*/ +void adc_regular_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time) +{ + uint32_t rsq,sampt; + + /* ADC regular sequence config */ + if(rank < ADC_REGULAR_CHANNEL_RANK_SIX){ + /* the regular group sequence rank is smaller than six */ + rsq = ADC_RSQ2(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank)); + ADC_RSQ2(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_TWELVE){ + /* the regular group sequence rank is smaller than twelve */ + rsq = ADC_RSQ1(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX))); + ADC_RSQ1(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_SIXTEEN){ + /* the regular group sequence rank is smaller than sixteen */ + rsq = ADC_RSQ0(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE))); + ADC_RSQ0(adc_periph) = rsq; + }else{ + } + + /* ADC sampling time config */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the regular group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel)); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel <= ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the regular group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..18): ADC Channelx + \param[in] sample_time: The sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_3: 3 cycles + \arg ADC_SAMPLETIME_15: 15 cycles + \arg ADC_SAMPLETIME_28: 28 cycles + \arg ADC_SAMPLETIME_56: 56 cycles + \arg ADC_SAMPLETIME_84: 84 cycles + \arg ADC_SAMPLETIME_112: 112 cycles + \arg ADC_SAMPLETIME_144: 144 cycles + \arg ADC_SAMPLETIME_480: 480 cycles + \param[out] none + \retval none +*/ +void adc_inserted_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time) +{ + uint8_t inserted_length; + uint32_t isq,sampt; + + /* get inserted channel group length */ + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + /* the channel number is written to these bits to select a channel as the nth conversion in the inserted channel group */ + if(rank < 4U){ + isq = ADC_ISQ(adc_periph); + isq &= ~((uint32_t)(ADC_ISQ_ISQN << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH-(inserted_length-rank)*ADC_INSERTED_CHANNEL_RANK_LENGTH))); + isq |= ((uint32_t)adc_channel << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH-(inserted_length-rank)*ADC_INSERTED_CHANNEL_RANK_LENGTH)); + ADC_ISQ(adc_periph) = isq; + } + + /* ADC sampling time config */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the inserted group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t) sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel <= ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the inserted group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel - ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= ((uint32_t)sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel - ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel offset + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] inserted_channel : insert channel select + only one parameter can be selected which is shown as below: + \arg ADC_INSERTED_CHANNEL_0: inserted channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted channel3 + \param[in] offset : the offset data + \param[out] none + \retval none +*/ +void adc_inserted_channel_offset_config(uint32_t adc_periph , uint8_t inserted_channel , uint16_t offset) +{ + uint8_t inserted_length; + uint32_t num = 0U; + + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + num = ((uint32_t)ADC_OFFSET_LENGTH - ((uint32_t)inserted_length - (uint32_t)inserted_channel)); + + if(num <= ADC_OFFSET_LENGTH){ + /* calculate the offset of the register */ + num = num * ADC_OFFSET_SHIFT_LENGTH; + /* config the offset of the selected channels */ + REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset); + } +} + +/*! + \brief configure ADC external trigger source \param[in] adc_periph: ADCx,x=0,1,2 \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] external_trigger_source: regular or inserted group trigger source + for regular channel: + only one parameter can be selected which is shown as below: + \arg ADC_EXTTRIG_REGULAR_T0_CH0: external trigger timer 0 CC0 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T0_CH1: external trigger timer 0 CC1 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T0_CH2: external trigger timer 0 CC2 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T1_CH1: external trigger timer 1 CC1 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T1_CH2: external trigger timer 1 CC2 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T1_CH3: external trigger timer 1 CC3 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T1_TRGO: external trigger timer 1 TRGO event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T2_CH0 : external trigger timer 2 CC0 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T2_TRGO : external trigger timer 2 TRGO event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T3_CH3: external trigger timer 3 CC3 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T4_CH0: external trigger timer 4 CC0 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T4_CH1: external trigger timer 4 CC1 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T4_CH2: external trigger timer 4 CC2 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T7_CH0: external trigger timer 7 CC0 event select for regular channel + \arg ADC_EXTTRIG_REGULAR_T7_TRGO: external trigger timer 7 TRGO event select for regular channel + \arg ADC_EXTTRIG_REGULAR_EXTI_11: external trigger extiline 11 select for regular channel + for inserted channel: + only one parameter can be selected which is shown as below: + \arg ADC_EXTTRIG_INSERTED_T0_CH3: timer0 capture compare 3 + \arg ADC_EXTTRIG_INSERTED_T0_TRGO: timer0 TRGO event + \arg ADC_EXTTRIG_INSERTED_T1_CH0: timer1 capture compare 0 + \arg ADC_EXTTRIG_INSERTED_T1_TRGO: timer1 TRGO event + \arg ADC_EXTTRIG_INSERTED_T2_CH1: timer2 capture compare 1 + \arg ADC_EXTTRIG_INSERTED_T2_CH3: timer2 capture compare 3 + \arg ADC_EXTTRIG_INSERTED_T3_CH0: timer3 capture compare 0 + \arg ADC_EXTTRIG_INSERTED_T3_CH1: timer3 capture compare 1 + \arg ADC_EXTTRIG_INSERTED_T3_CH2: timer3 capture compare 2 + \arg ADC_EXTTRIG_INSERTED_T3_TRGO: timer3 capture compare TRGO + \arg ADC_EXTTRIG_INSERTED_T4_CH3: timer4 capture compare 3 + \arg ADC_EXTTRIG_INSERTED_T4_TRGO: timer4 capture compare TRGO + \arg ADC_EXTTRIG_INSERTED_T7_CH1: timer7 capture compare 1 + \arg ADC_EXTTRIG_INSERTED_T7_CH2: timer7 capture compare 2 + \arg ADC_EXTTRIG_INSERTED_T7_CH3: timer7 capture compare 3 + \arg ADC_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 + \param[out] none + \retval none +*/ +void adc_external_trigger_source_config(uint32_t adc_periph , uint8_t adc_channel_group , uint32_t external_trigger_source) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure ADC regular group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + case ADC_INSERTED_CHANNEL: + /* configure ADC inserted group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + default: + break; + } +} + +/*! + \brief enable ADC external trigger + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: \arg ADC_REGULAR_CHANNEL: regular channel group \arg ADC_INSERTED_CHANNEL: inserted channel group \param[in] trigger_mode: external trigger mode + only one parameter can be selected which is shown as below: \arg EXTERNAL_TRIGGER_DISABLE: external trigger disable \arg EXTERNAL_TRIGGER_RISING: rising edge of external trigger \arg EXTERNAL_TRIGGER_FALLING: falling edge of external trigger @@ -315,10 +672,12 @@ void adc_external_trigger_config(uint32_t adc_periph , uint8_t adc_channel_group { switch(adc_channel_group){ case ADC_REGULAR_CHANNEL: + /* configure ADC regular channel group external trigger mode */ ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETMRC); ADC_CTL1(adc_periph) |= (uint32_t) (trigger_mode << REGULAR_TRIGGER_MODE); break; case ADC_INSERTED_CHANNEL: + /* configure ADC inserted channel group external trigger mode */ ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETMIC); ADC_CTL1(adc_periph) |= (uint32_t) (trigger_mode << INSERTED_TRIGGER_MODE); break; @@ -328,69 +687,10 @@ void adc_external_trigger_config(uint32_t adc_periph , uint8_t adc_channel_group } /*! - \brief ADC external trigger source config - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] adc_channel_group: select the channel group - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \param[in] external_trigger_source: regular or inserted group trigger source - for regular channel: - \arg ADC_EXTTRIG_REGULAR_T0_CH0: external trigger timer 0 CC0 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T0_CH1: external trigger timer 0 CC1 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T0_CH2: external trigger timer 0 CC2 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T1_CH1: external trigger timer 1 CC1 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T1_CH2: external trigger timer 1 CC2 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T1_CH3: external trigger timer 1 CC3 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T1_TRGO: external trigger timer 1 TRGO event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T2_CH0 : external trigger timer 2 CC0 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T2_TRGO : external trigger timer 2 TRGO event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T3_CH3: external trigger timer 3 CC3 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T4_CH0: external trigger timer 4 CC0 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T4_CH1: external trigger timer 4 CC1 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T4_CH2: external trigger timer 4 CC2 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T7_CH0: external trigger timer 7 CC0 event select for regular channel - \arg ADC_EXTTRIG_REGULAR_T7_TRGO: external trigger timer 7 TRGO event select for regular channel - \arg ADC_EXTTRIG_REGULAR_EXTI_11: external trigger extiline 11 select for regular channel - for inserted channel: - \arg ADC_EXTTRIG_INSERTED_T0_CH3: timer0 capture compare 3 - \arg ADC_EXTTRIG_INSERTED_T0_TRGO: timer0 TRGO event - \arg ADC_EXTTRIG_INSERTED_T1_CH0: timer1 capture compare 0 - \arg ADC_EXTTRIG_INSERTED_T1_TRGO: timer1 TRGO event - \arg ADC_EXTTRIG_INSERTED_T2_CH1: timer2 capture compare 1 - \arg ADC_EXTTRIG_INSERTED_T2_CH3: timer2 capture compare 3 - \arg ADC_EXTTRIG_INSERTED_T3_CH0: timer3 capture compare 0 - \arg ADC_EXTTRIG_INSERTED_T3_CH1: timer3 capture compare 1 - \arg ADC_EXTTRIG_INSERTED_T3_CH2: timer3 capture compare 2 - \arg ADC_EXTTRIG_INSERTED_T3_TRGO: timer3 capture compare TRGO - \arg ADC_EXTTRIG_INSERTED_T4_CH3: timer4 capture compare 3 - \arg ADC_EXTTRIG_INSERTED_T4_TRGO: timer4 capture compare TRGO - \arg ADC_EXTTRIG_INSERTED_T7_CH1: timer7 capture compare 1 - \arg ADC_EXTTRIG_INSERTED_T7_CH2: timer7 capture compare 2 - \arg ADC_EXTTRIG_INSERTED_T7_CH3: timer7 capture compare 3 - \arg ADC_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 - \param[out] none - \retval none -*/ -void adc_external_trigger_source_config(uint32_t adc_periph , uint8_t adc_channel_group , uint32_t external_trigger_source) -{ - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); - ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; - break; - case ADC_INSERTED_CHANNEL: - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC); - ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; - break; - default: - break; - } -} - -/*! - \brief ADC software trigger enable + \brief enable ADC software trigger \param[in] adc_periph: ADCx,x=0,1,2 \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: \arg ADC_REGULAR_CHANNEL: regular channel group \arg ADC_INSERTED_CHANNEL: inserted channel group \param[out] none @@ -400,9 +700,11 @@ void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group { switch(adc_channel_group){ case ADC_REGULAR_CHANNEL: + /* enable ADC regular channel group software trigger */ ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_SWRCST; break; case ADC_INSERTED_CHANNEL: + /* enable ADC inserted channel group software trigger */ ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_SWICST; break; default: @@ -410,10 +712,199 @@ void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group } } +/*! + \brief configure end of conversion mode + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] end_selection: end of conversion mode + only one parameter can be selected which is shown as below: + \arg ADC_EOC_SET_SEQUENCE: only at the end of a sequence of regular conversions, the EOC bit is set.Overflow detection is disabled unless DMA=1. + \arg ADC_EOC_SET_CONVERSION: at the end of each regular conversion, the EOC bit is set.Overflow is detected automatically. + \param[out] none + \retval none +*/ +void adc_end_of_conversion_config(uint32_t adc_periph , uint8_t end_selection) +{ + switch(end_selection){ + case ADC_EOC_SET_SEQUENCE: + /* only at the end of a sequence of regular conversions, the EOC bit is set */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_EOCM); + break; + case ADC_EOC_SET_CONVERSION: + /* at the end of each regular conversion, the EOC bit is set.Overflow is detected automatically */ + ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_EOCM); + break; + default: + break; + } +} + +/*! + \brief read ADC regular group data register + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint16_t adc_regular_data_read(uint32_t adc_periph) +{ + return (uint16_t)(ADC_RDATA(adc_periph)); +} + +/*! + \brief read ADC inserted group data register + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] inserted_channel : insert channel select + only one parameter can be selected which is shown as below: + \arg ADC_INSERTED_CHANNEL_0: inserted Channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted Channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted Channel3 + \param[out] none + \retval the conversion value +*/ +uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel) +{ + uint32_t idata; + /* read the data of the selected channel */ + switch(inserted_channel){ + case ADC_INSERTED_CHANNEL_0: + /* read the data of channel 0 */ + idata = ADC_IDATA0(adc_periph); + break; + case ADC_INSERTED_CHANNEL_1: + /* read the data of channel 1 */ + idata = ADC_IDATA1(adc_periph); + break; + case ADC_INSERTED_CHANNEL_2: + /* read the data of channel 2 */ + idata = ADC_IDATA2(adc_periph); + break; + case ADC_INSERTED_CHANNEL_3: + /* read the data of channel 3 */ + idata = ADC_IDATA3(adc_periph); + break; + default: + idata = 0U; + break; + } + return (uint16_t)idata; +} + +/*! + \brief disable ADC analog watchdog single channel + \param[in] adc_periph: ADCx,x=0,1,2 + \param[out] none + \retval none +*/ +void adc_watchdog_single_channel_disable(uint32_t adc_periph ) +{ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_WDSC); +} + +/*! + \brief enable ADC analog watchdog single channel + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x: ADC Channelx(x=0..18) + \param[out] none + \retval none +*/ +void adc_watchdog_single_channel_enable(uint32_t adc_periph , uint8_t adc_channel) +{ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_WDCHSEL); + + /* analog watchdog channel select */ + ADC_CTL0(adc_periph) |= (uint32_t)adc_channel; + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDSC; +} + +/*! + \brief configure ADC analog watchdog group channel + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] adc_channel_group: the channel group use analog watchdog + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group + \param[out] none + \retval none +*/ +void adc_watchdog_group_channel_enable(uint32_t adc_periph , uint8_t adc_channel_group) +{ + ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC)); + /* select the group */ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* regular channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN; + break; + case ADC_INSERTED_CHANNEL: + /* inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN; + break; + case ADC_REGULAR_INSERTED_CHANNEL: + /* regular and inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN); + break; + default: + break; + } +} + +/*! + \brief disable ADC analog watchdog + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] adc_channel_group: the channel group use analog watchdog + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group + \param[out] none + \retval none +*/ +void adc_watchdog_disable(uint32_t adc_periph , uint8_t adc_channel_group) +{ + /* select the group */ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* disable ADC analog watchdog regular channel group */ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_RWDEN); + break; + case ADC_INSERTED_CHANNEL: + /* disable ADC analog watchdog inserted channel group */ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_IWDEN); + break; + case ADC_REGULAR_INSERTED_CHANNEL: + /* disable ADC analog watchdog regular and inserted channel group */ + ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN)); + break; + default: + break; + } +} + +/*! + \brief configure ADC analog watchdog threshold + \param[in] adc_periph: ADCx,x=0,1,2 + \param[in] low_threshold: analog watchdog low threshold,0..4095 + \param[in] high_threshold: analog watchdog high threshold,0..4095 + \param[out] none + \retval none +*/ +void adc_watchdog_threshold_config(uint32_t adc_periph , uint16_t low_threshold , uint16_t high_threshold) +{ + /* configure ADC analog watchdog low threshold */ + ADC_WDLT(adc_periph) = (uint32_t)WDLT_WDLT(low_threshold); + /* configure ADC analog watchdog high threshold */ + ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold); +} + /*! \brief get the ADC flag bits \param[in] adc_periph: ADCx,x=0,1,2 \param[in] adc_flag: the adc flag bits + only one parameter can be selected which is shown as below: \arg ADC_FLAG_WDE: analog watchdog event flag \arg ADC_FLAG_EOC: end of group conversion flag \arg ADC_FLAG_EOIC: end of inserted group conversion flag @@ -425,10 +916,11 @@ void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group */ FlagStatus adc_flag_get(uint32_t adc_periph , uint32_t adc_flag) { - if(ADC_STAT(adc_periph) & adc_flag){ - return SET; - } - return RESET; + FlagStatus reval = RESET; + if(ADC_STAT(adc_periph) & adc_flag){ + reval = SET; + } + return reval; } @@ -436,6 +928,7 @@ FlagStatus adc_flag_get(uint32_t adc_periph , uint32_t adc_flag) \brief clear the ADC flag bits \param[in] adc_periph: ADCx,x=0,1,2 \param[in] adc_flag: the adc flag bits + only one parameter can be selected which is shown as below: \arg ADC_FLAG_WDE: analog watchdog event flag \arg ADC_FLAG_EOC: end of group conversion flag \arg ADC_FLAG_EOIC: end of inserted group conversion flag @@ -450,14 +943,47 @@ void adc_flag_clear(uint32_t adc_periph , uint32_t adc_flag) ADC_STAT(adc_periph) &= ~((uint32_t)adc_flag); } +/*! + \brief get the bit state of ADCx software start conversion + \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph) +{ + FlagStatus reval = RESET; + if((uint32_t)RESET != (ADC_STAT(adc_periph) & ADC_STAT_STRC)){ + reval = SET; + } + return reval; +} + +/*! + \brief get the bit state of ADCx software inserted channel start conversion + \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph) +{ + FlagStatus reval = RESET; + if((uint32_t)RESET != (ADC_STAT(adc_periph) & ADC_STAT_STIC)){ + reval = SET; + } + return reval; +} + /*! \brief get the ADC interrupt bits \param[in] adc_periph: ADCx,x=0,1,2 \param[in] adc_interrupt: the adc interrupt bits - \arg ADC_INT_WDE: analog watchdog interrupt - \arg ADC_INT_EOC: end of group conversion interrupt - \arg ADC_INT_EOIC: end of inserted group conversion interrupt - \arg ADC_INT_ROVF: regular data register overflow interrupt + only one parameter can be selected which is shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \arg ADC_INT_FLAG_ROVF: regular data register overflow interrupt \param[out] none \retval FlagStatus: SET or RESET */ @@ -467,25 +993,29 @@ FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t adc_interrupt) uint32_t state; /* check the interrupt bits */ switch(adc_interrupt){ - case ADC_INT_WDE: + case ADC_INT_FLAG_WDE: + /* get the ADC analog watchdog interrupt bits */ state = ADC_STAT(adc_periph) & ADC_STAT_WDE; if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){ interrupt_flag = SET; } break; - case ADC_INT_EOC: + case ADC_INT_FLAG_EOC: + /* get the ADC end of group conversion interrupt bits */ state = ADC_STAT(adc_periph) & ADC_STAT_EOC; if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){ interrupt_flag = SET; } break; - case ADC_INT_EOIC: + case ADC_INT_FLAG_EOIC: + /* get the ADC end of inserted group conversion interrupt bits */ state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){ interrupt_flag = SET; } break; - case ADC_INT_ROVF: + case ADC_INT_FLAG_ROVF: + /* get the ADC regular data register overflow interrupt bits */ state = ADC_STAT(adc_periph) & ADC_STAT_ROVF; if((ADC_CTL0(adc_periph) & ADC_CTL0_ROVFIE) && state){ interrupt_flag = SET; @@ -500,11 +1030,12 @@ FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t adc_interrupt) /*! \brief clear the ADC flag \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] adc_flag: the adc status flag - \arg ADC_INT_WDE: analog watchdog interrupt - \arg ADC_INT_EOC: end of group conversion interrupt - \arg ADC_INT_EOIC: end of inserted group conversion interrupt - \arg ADC_INT_ROVF: regular data register overflow interrupt + \param[in] adc_interrupt: the adc status flag + only one parameter can be selected which is shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \arg ADC_INT_FLAG_ROVF: regular data register overflow interrupt \param[out] none \retval none */ @@ -514,9 +1045,10 @@ void adc_interrupt_flag_clear(uint32_t adc_periph , uint32_t adc_interrupt) } /*! - \brief ADC interrupt enable + \brief enable ADC interrupt \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] adc_flag: the adc interrupt flag + \param[in] adc_interrupt: the adc interrupt flag + only one parameter can be selected which is shown as below: \arg ADC_INT_WDE: analog watchdog interrupt flag \arg ADC_INT_EOC: end of group conversion interrupt flag \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag @@ -528,12 +1060,15 @@ void adc_interrupt_enable(uint32_t adc_periph , uint32_t adc_interrupt) { switch(adc_interrupt){ case ADC_INT_WDE: + /* enable analog watchdog interrupt */ ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE; break; case ADC_INT_EOC: + /* enable end of group conversion interrupt */ ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE; break; case ADC_INT_EOIC: + /* enable end of inserted group conversion interrupt */ ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE; break; case ADC_INT_ROVF: @@ -545,9 +1080,10 @@ void adc_interrupt_enable(uint32_t adc_periph , uint32_t adc_interrupt) } /*! - \brief ADC interrupt disable + \brief disable ADC interrupt \param[in] adc_periph: ADCx,x=0,1,2 \param[in] adc_flag: the adc interrupt flag + only one parameter can be selected which is shown as below: \arg ADC_INT_WDE: analog watchdog interrupt flag \arg ADC_INT_EOC: end of group conversion interrupt flag \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag @@ -576,388 +1112,10 @@ void adc_interrupt_disable(uint32_t adc_periph , uint32_t adc_interrupt) } } -/*! - \brief ADC analog watchdog single channel disable - \param[in] adc_periph: ADCx,x=0,1,2 - \param[out] none - \retval none -*/ -void adc_watchdog_single_channel_disable(uint32_t adc_periph ) -{ - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_WDSC); -} - -/*! - \brief ADC analog watchdog single channel enable - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] adc_channel: the selected ADC channel - \arg ADC_CHANNEL_x: ADC Channelx(x=0..18) - \param[out] none - \retval none -*/ -void adc_watchdog_single_channel_enable(uint32_t adc_periph , uint8_t adc_channel) -{ - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_WDCHSEL); - - ADC_CTL0(adc_periph) |= (uint32_t)adc_channel; - ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDSC; -} - -/*! - \brief adc analog watchdog group channel config - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] adc_channel_group: the channel group use analog watchdog - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group - \param[out] none - \retval none -*/ -void adc_watchdog_enable(uint32_t adc_periph , uint8_t adc_channel_group) -{ - ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC)); - /* select the group */ - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN; - break; - case ADC_INSERTED_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN; - break; - case ADC_REGULAR_INSERTED_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN); - break; - default: - break; - } -} - -/*! - \brief ADC analog watchdog disable - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] adc_channel_group: the channel group use analog watchdog - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group - \param[out] none - \retval none -*/ -void adc_watchdog_disable(uint32_t adc_periph , uint8_t adc_channel_group) -{ - /* select the group */ - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_RWDEN); - break; - case ADC_INSERTED_CHANNEL: - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_IWDEN); - break; - case ADC_REGULAR_INSERTED_CHANNEL: - ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN)); - break; - default: - break; - } -} - -/*! - \brief ADC analog watchdog threshold config - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] low_threshold: analog watchdog low threshold,0..4095 - \param[in] high_threshold: analog watchdog high threshold,0..4095 - \param[out] none - \retval none -*/ -void adc_watchdog_threshold_config(uint32_t adc_periph , uint16_t low_threshold , uint16_t high_threshold) -{ - ADC_WDLT(adc_periph) = (uint32_t)low_threshold; - ADC_WDHT(adc_periph) = (uint32_t)high_threshold; -} - -/*! - \brief ADC regular channel config - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] rank: the regular group sequencer rank,this parameter must be between 0 to 15 - \param[in] adc_channel: the selected ADC channel - \arg ADC_CHANNEL_x(x=0..18): ADC Channelx - \param[in] sample_time: the sample time value - \arg ADC_SAMPLETIME_3: 3 cycles - \arg ADC_SAMPLETIME_15: 15 cycles - \arg ADC_SAMPLETIME_28: 28 cycles - \arg ADC_SAMPLETIME_56: 56 cycles - \arg ADC_SAMPLETIME_84: 84 cycles - \arg ADC_SAMPLETIME_112: 112 cycles - \arg ADC_SAMPLETIME_144: 144 cycles - \arg ADC_SAMPLETIME_480: 480 cycles - \param[out] none - \retval none -*/ -void adc_regular_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time) -{ - uint32_t rsq,sampt; - - /* ADC regular sequence config */ - if(rank < 6U){ - rsq = ADC_RSQ2(adc_periph); - rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*rank))); - rsq |= ((uint32_t)adc_channel << (5U*rank)); - ADC_RSQ2(adc_periph) = rsq; - }else if(rank < 12U){ - rsq = ADC_RSQ1(adc_periph); - rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-6U)))); - rsq |= ((uint32_t)adc_channel << (5U*(rank-6U))); - ADC_RSQ1(adc_periph) = rsq; - }else if(rank < 16U){ - rsq = ADC_RSQ0(adc_periph); - rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-12U)))); - rsq |= ((uint32_t)adc_channel << (5U*(rank-12U))); - ADC_RSQ0(adc_periph) = rsq; - }else{ - } - - /* ADC sampling time config */ - if(adc_channel < 10U){ - sampt = ADC_SAMPT1(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel))); - sampt |= (uint32_t)(sample_time << (3U*adc_channel)); - ADC_SAMPT1(adc_periph) = sampt; - }else if(adc_channel < 19U){ - sampt = ADC_SAMPT0(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U)))); - sampt |= (uint32_t)(sample_time << (3U*(adc_channel-10U))); - ADC_SAMPT0(adc_periph) = sampt; - }else{ - } -} - -/*! - \brief ADC regular group data register read - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] none - \param[out] none - \retval the conversion value -*/ -uint16_t adc_regular_data_read(uint32_t adc_periph) -{ - return (uint16_t)(ADC_RDATA(adc_periph)); -} - -/*! - \brief ADC inserted channel config - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 - \param[in] adc_channel: the selected ADC channel - \arg ADC_CHANNEL_x(x=0..18): ADC Channelx - \param[in] sample_time: The sample time value - \arg ADC_SAMPLETIME_3: 3 cycles - \arg ADC_SAMPLETIME_15: 15 cycles - \arg ADC_SAMPLETIME_28: 28 cycles - \arg ADC_SAMPLETIME_56: 56 cycles - \arg ADC_SAMPLETIME_84: 84 cycles - \arg ADC_SAMPLETIME_112: 112 cycles - \arg ADC_SAMPLETIME_144: 144 cycles - \arg ADC_SAMPLETIME_480: 480 cycles - \param[out] none - \retval none -*/ -void adc_inserted_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint8_t sample_time) -{ - uint8_t inserted_length; - uint32_t isq,sampt; - - inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); - if(rank < 4U){ - isq = ADC_ISQ(adc_periph); - isq &= ~((uint32_t)(ADC_ISQ_ISQN << (15U-(inserted_length-rank)*5U))); - isq |= ((uint32_t)adc_channel << (15U-(inserted_length-rank)*5U)); - ADC_ISQ(adc_periph) = isq; - } - - if(adc_channel < 10U){ - sampt = ADC_SAMPT1(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel))); - sampt |= (uint32_t) sample_time << (3U*adc_channel); - ADC_SAMPT1(adc_periph) = sampt; - }else if(adc_channel < 19U){ - sampt = ADC_SAMPT0(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U)))); - sampt |= ((uint32_t)sample_time << (3U*(adc_channel-10U))); - ADC_SAMPT0(adc_periph) = sampt; - }else{ - } -} - -/*! - \brief ADC inserted channel offset config - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] inserted_channel : insert channel select - \arg ADC_INSERTED_CHANNEL_0: inserted channel0 - \arg ADC_INSERTED_CHANNEL_1: inserted channel1 - \arg ADC_INSERTED_CHANNEL_2: inserted channel2 - \arg ADC_INSERTED_CHANNEL_3: inserted channel3 - \param[in] offset : the offset data - \param[out] none - \retval the conversion value -*/ -void adc_inserted_channel_offset_config(uint32_t adc_periph , uint8_t inserted_channel , uint16_t offset) -{ - /* config the offset of the selected channels */ - if(ADC_INSERTED_CHANNEL_0 == inserted_channel){ - ADC_IOFF0(adc_periph) = (uint32_t)offset; - }else if(ADC_INSERTED_CHANNEL_1 == inserted_channel){ - ADC_IOFF1(adc_periph) = (uint32_t)offset; - }else if(ADC_INSERTED_CHANNEL_2 == inserted_channel){ - ADC_IOFF2(adc_periph) = (uint32_t)offset; - }else if(ADC_INSERTED_CHANNEL_3 == inserted_channel){ - ADC_IOFF3(adc_periph) = (uint32_t)offset; - }else{ - } -} - -/*! - \brief ADC inserted group data register read - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] inserted_channel : insert channel select - \arg ADC_INSERTED_CHANNEL_0: inserted Channel0 - \arg ADC_INSERTED_CHANNEL_1: inserted channel1 - \arg ADC_INSERTED_CHANNEL_2: inserted Channel2 - \arg ADC_INSERTED_CHANNEL_3: inserted Channel3 - \param[out] none - \retval the conversion value -*/ -uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel) -{ - uint32_t idata; - /* read the data of the selected channel */ - switch(inserted_channel){ - case ADC_INSERTED_CHANNEL_0: - idata = ADC_IDATA0(adc_periph); - break; - case ADC_INSERTED_CHANNEL_1: - idata = ADC_IDATA1(adc_periph); - break; - case ADC_INSERTED_CHANNEL_2: - idata = ADC_IDATA2(adc_periph); - break; - case ADC_INSERTED_CHANNEL_3: - idata = ADC_IDATA3(adc_periph); - break; - default: - idata = 0U; - break; - } - return (uint16_t)idata; -} - -/*! - \brief DMA request enable - \param[in] adc_periph: ADCx,x=0,1,2 - \param[out] none - \retval none -*/ -void adc_dma_mode_enable(uint32_t adc_periph) -{ - ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA); -} - -/*! - \brief DMA request disable - \param[in] adc_periph: ADCx,x=0,1,2 - \param[out] none - \retval none -*/ -void adc_dma_mode_disable(uint32_t adc_periph) -{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA); -} - -/*! - \brief when DMA=1, the DMA engine issues a request at end of each regular conversion - \param[in] adc_periph: ADCx,x=0,1,2 - \param[out] none - \retval none -*/ -void adc_dma_request_after_last_enable(uint32_t adc_periph) -{ - ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DDM); -} - -/*! - \brief the DMA engine is disabled after the end of transfer signal from DMA controller is detected - \param[in] adc_periph: ADCx,x=0,1,2 - \param[out] none - \retval none -*/ -void adc_dma_request_after_last_disable(uint32_t adc_periph) -{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DDM); -} - -/*! - \brief ADC oversample mode config - \param[in] adc_periph: ADCx,x=0,1,2 - \param[in] mode: ADC oversampling mode - \arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger - \arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger - \param[in] shift: ADC oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift - \param[in] ratio: ADC oversampling ratio - \arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2 - \arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4 - \arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8 - \arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16 - \arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32 - \arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64 - \arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128 - \arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256 - \param[out] none - \retval none -*/ -void adc_oversample_mode_config(uint32_t adc_periph , uint8_t mode , uint16_t shift , uint8_t ratio) -{ - if(ADC_OVERSAMPLING_ONE_CONVERT == mode){ - ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS; - }else{ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS); - } - /* config the shift and ratio */ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS)); - ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio); -} - -/*! - \brief ADC oversample mode enable - \param[in] adc_periph: ADCx,x=0,1,2 - \param[out] none - \retval none -*/ -void adc_oversample_mode_enable(uint32_t adc_periph) -{ - ADC_OVSAMPCTL(adc_periph) |= ADC_OVSAMPCTL_OVSEN; -} - -/*! - \brief ADC oversample mode disable - \param[in] adc_periph: ADCx,x=0,1,2 - \param[out] none - \retval none -*/ -void adc_oversample_mode_disable(uint32_t adc_periph) -{ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN); -} - /*! \brief configure the ADC sync mode - \param[in] sync_mode: ADC sync mode + \param[in] sync_mode: ADC sync mode + only one parameter can be selected which is shown as below: \arg ADC_SYNC_MODE_INDEPENDENT: all the ADCs work independently \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel & inserted parallel mode \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel & trigger rotation mode @@ -982,7 +1140,8 @@ void adc_sync_mode_config(uint32_t sync_mode) /*! \brief configure the delay between 2 sampling phases in ADC sync modes - \param[in] sample_delay: the delay between 2 sampling phases in ADC sync modes + \param[in] sample_delay: the delay between 2 sampling phases in ADC sync modes + only one parameter can be selected which is shown as below: \arg ADC_SYNC_DELAY_xCYCLE: x=5..20,the delay between 2 sampling phases in ADC sync modes is x ADC clock cycles \param[out] none \retval none @@ -996,9 +1155,10 @@ void adc_sync_delay_config(uint32_t sample_delay) /*! \brief configure ADC sync DMA mode selection \param[in] dma_mode: ADC sync DMA mode + only one parameter can be selected which is shown as below: \arg ADC_SYNC_DMA_DISABLE: ADC sync DMA disabled - \arg ADC_SYNC_DMA_MODE0: ADC sync DMA disabled - \arg ADC_SYNC_DMA_MODE1: ADC sync DMA disabled + \arg ADC_SYNC_DMA_MODE0: ADC sync DMA mode 0 + \arg ADC_SYNC_DMA_MODE1: ADC sync DMA mode 1 \param[out] none \retval none */ @@ -1031,7 +1191,7 @@ void adc_sync_dma_request_after_last_disable(void) } /*! - \brief ADC sync regular data register read + \brief read ADC sync regular data register \param[in] none \param[out] none \retval sync regular data diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c index eb03822acf..5eb2974739 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c @@ -1,18 +1,47 @@ /*! - \file gd32f4xx_can.c - \brief CAN driver + \file gd32f4xx_can.c + \brief CAN driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2019-11-27, V2.0.1, firmware for GD32F4xx + \version 2020-07-14, V2.0.2, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_can.h" +#define CAN_ERROR_HANDLE(s) do{}while(1) + /*! - \brief deinitialize CAN + \brief deinitialize CAN \param[in] can_periph \arg CANx(x=0,1) \param[out] none @@ -29,22 +58,101 @@ void can_deinit(uint32_t can_periph) } } +/*! + \brief initialize CAN parameter struct with a default value + \param[in] type: the type of CAN parameter struct + only one parameter can be selected which is shown as below: + \arg CAN_INIT_STRUCT: the CAN initial struct + \arg CAN_FILTER_STRUCT: the CAN filter struct + \arg CAN_TX_MESSAGE_STRUCT: the CAN TX message struct + \arg CAN_RX_MESSAGE_STRUCT: the CAN RX message struct + \param[in] p_struct: the pointer of the specific struct + \param[out] none + \retval none +*/ +void can_struct_para_init(can_struct_type_enum type, void* p_struct) +{ + uint8_t i; + + /* get type of the struct */ + switch(type){ + /* used for can_init() */ + case CAN_INIT_STRUCT: + ((can_parameter_struct*)p_struct)->auto_bus_off_recovery = DISABLE; + ((can_parameter_struct*)p_struct)->no_auto_retrans = DISABLE; + ((can_parameter_struct*)p_struct)->auto_wake_up = DISABLE; + ((can_parameter_struct*)p_struct)->prescaler = 0x03FFU; + ((can_parameter_struct*)p_struct)->rec_fifo_overwrite = DISABLE; + ((can_parameter_struct*)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ; + ((can_parameter_struct*)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ; + ((can_parameter_struct*)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ; + ((can_parameter_struct*)p_struct)->time_triggered = DISABLE; + ((can_parameter_struct*)p_struct)->trans_fifo_order = DISABLE; + ((can_parameter_struct*)p_struct)->working_mode = CAN_NORMAL_MODE; + + break; + /* used for can_filter_init() */ + case CAN_FILTER_STRUCT: + ((can_filter_parameter_struct*)p_struct)->filter_bits = CAN_FILTERBITS_32BIT; + ((can_filter_parameter_struct*)p_struct)->filter_enable = DISABLE; + ((can_filter_parameter_struct*)p_struct)->filter_fifo_number = CAN_FIFO0; + ((can_filter_parameter_struct*)p_struct)->filter_list_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_list_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mode = CAN_FILTERMODE_MASK; + ((can_filter_parameter_struct*)p_struct)->filter_number = 0U; + + break; + /* used for can_message_transmit() */ + case CAN_TX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_trasnmit_message_struct*)p_struct)->tx_data[i] = 0U; + } + + ((can_trasnmit_message_struct*)p_struct)->tx_dlen = 0u; + ((can_trasnmit_message_struct*)p_struct)->tx_efid = 0U; + ((can_trasnmit_message_struct*)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_trasnmit_message_struct*)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; + ((can_trasnmit_message_struct*)p_struct)->tx_sfid = 0U; + + break; + /* used for can_message_receive() */ + case CAN_RX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_receive_message_struct*)p_struct)->rx_data[i] = 0U; + } + + ((can_receive_message_struct*)p_struct)->rx_dlen = 0U; + ((can_receive_message_struct*)p_struct)->rx_efid = 0U; + ((can_receive_message_struct*)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_receive_message_struct*)p_struct)->rx_fi = 0U; + ((can_receive_message_struct*)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; + ((can_receive_message_struct*)p_struct)->rx_sfid = 0U; + + break; + + default: + CAN_ERROR_HANDLE("parameter is invalid \r\n"); + } +} + /*! \brief initialize CAN \param[in] can_periph \arg CANx(x=0,1) - \param[in] can_parameter_struct: parameters for CAN initializtion - can_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE - can_sjw: CAN_BT_SJW_xTQ(x=1, 2, 3, 4) - can_bs1: CAN_BT_BS1_xTQ(1..16) - can_bs2: CAN_BT_BS2_xTQ(1..8) - can_ttc: ENABLE or DISABLE - can_abor: ENABLE or DISABLE - can_awu: ENABLE or DISABLE - can_ard: ENABLE or DISABLE - can_rfod: ENABLE or DISABLE - can_tfo: ENABLE or DISABLE - can_psc: 0x0001 - 0x03FF + \param[in] can_parameter_init: parameters for CAN initializtion + \arg working_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE + \arg resync_jump_width: CAN_BT_SJW_xTQ(x=1, 2, 3, 4) + \arg time_segment_1: CAN_BT_BS1_xTQ(1..16) + \arg time_segment_2: CAN_BT_BS2_xTQ(1..8) + \arg time_triggered: ENABLE or DISABLE + \arg auto_bus_off_recovery: ENABLE or DISABLE + \arg auto_wake_up: ENABLE or DISABLE + \arg no_auto_retrans: ENABLE or DISABLE + \arg rec_fifo_overwrite: ENABLE or DISABLE + \arg trans_fifo_order: ENABLE or DISABLE + \arg prescaler: 0x0001 - 0x0400 \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -52,19 +160,19 @@ ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init { uint32_t timeout = CAN_TIMEOUT; ErrStatus flag = ERROR; - + /* disable sleep mode */ CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; /* enable initialize mode */ CAN_CTL(can_periph) |= CAN_CTL_IWMOD; /* wait ACK */ - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (timeout)){ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ timeout--; } /* check initialize working success */ if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ flag = ERROR; - } else { + }else{ /* set the bit timing register */ CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ @@ -89,64 +197,64 @@ ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init }else{ CAN_CTL(can_periph) &= ~CAN_CTL_AWU; } - /* automatic retransmission mode */ - if(ENABLE == can_parameter_init->auto_retrans){ + /* automatic retransmission mode disable*/ + if(ENABLE == can_parameter_init->no_auto_retrans){ CAN_CTL(can_periph) |= CAN_CTL_ARD; }else{ CAN_CTL(can_periph) &= ~CAN_CTL_ARD; } - /* receive fifo overwrite mode */ + /* receive fifo overwrite mode */ if(ENABLE == can_parameter_init->rec_fifo_overwrite){ CAN_CTL(can_periph) |= CAN_CTL_RFOD; }else{ CAN_CTL(can_periph) &= ~CAN_CTL_RFOD; - } + } /* transmit fifo order */ if(ENABLE == can_parameter_init->trans_fifo_order){ CAN_CTL(can_periph) |= CAN_CTL_TFO; }else{ CAN_CTL(can_periph) &= ~CAN_CTL_TFO; - } + } /* disable initialize mode */ CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; timeout = CAN_TIMEOUT; /* wait the ACK */ - while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (timeout)){ + while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ timeout--; } /* check exit initialize mode */ if(CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)){ flag = SUCCESS; } - } + } return flag; } /*! - \brief initialize CAN filter - \param[in] can_filter_parameter_struct: struct for CAN filter initialization - can_filter_list_high: 0x0000 - 0xFFFF - can_filter_list_low: 0x0000 - 0xFFFF - can_filter_mask_high: 0x0000 - 0xFFFF - can_filter_mask_low: 0x0000 - 0xFFFF - can_filter_fifo_number: CAN_FIFO0, CAN_FIFO1 - can_filter_number: 0 - 27 - can_filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST - can_filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT - can_filter_enable: ENABLE or DISABLE + \brief initialize CAN filter + \param[in] can_filter_parameter_init: struct for CAN filter initialization + \arg filter_list_high: 0x0000 - 0xFFFF + \arg filter_list_low: 0x0000 - 0xFFFF + \arg filter_mask_high: 0x0000 - 0xFFFF + \arg filter_mask_low: 0x0000 - 0xFFFF + \arg filter_fifo_number: CAN_FIFO0, CAN_FIFO1 + \arg filter_number: 0 - 27 + \arg filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST + \arg filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT + \arg filter_enable: ENABLE or DISABLE \param[out] none \retval none */ void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init) { uint32_t val = 0U; - + val = ((uint32_t)1) << (can_filter_parameter_init->filter_number); /* filter lock disable */ CAN_FCTL(CAN0) |= CAN_FCTL_FLD; /* disable filter */ CAN_FW(CAN0) &= ~(uint32_t)val; - + /* filter 16 bits */ if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits){ /* set filter 16 bits */ @@ -173,7 +281,7 @@ void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init) FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS); } - + /* filter mode */ if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode){ /* mask mode */ @@ -182,24 +290,24 @@ void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init) /* list mode */ CAN_FMCFG(CAN0) |= (uint32_t)val; } - + /* filter FIFO */ if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)){ /* FIFO0 */ CAN_FAFIFO(CAN0) &= ~(uint32_t)val; } - + if(CAN_FIFO1 == can_filter_parameter_init->filter_fifo_number){ /* FIFO1 */ CAN_FAFIFO(CAN0) |= (uint32_t)val; } - + /* filter working */ if(ENABLE == can_filter_parameter_init->filter_enable){ - + CAN_FW(CAN0) |= (uint32_t)val; } - + /* filter lock enable */ CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; } @@ -266,11 +374,11 @@ void can_debug_freeze_disable(uint32_t can_periph) void can_time_trigger_mode_enable(uint32_t can_periph) { uint8_t mailbox_number; - + /* enable the tcc mode */ CAN_CTL(can_periph) |= CAN_CTL_TTC; /* enable time stamp */ - for(mailbox_number=0U; mailbox_number<3U; mailbox_number++){ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){ CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN; } } @@ -284,29 +392,29 @@ void can_time_trigger_mode_enable(uint32_t can_periph) */ void can_time_trigger_mode_disable(uint32_t can_periph) { - uint8_t mailbox_number; - + uint8_t mailbox_number; + /* disable the TCC mode */ CAN_CTL(can_periph) &= ~CAN_CTL_TTC; /* reset TSEN bits */ - for(mailbox_number=0U; mailbox_number<3U; mailbox_number++){ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){ CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN; } } /*! - \brief CAN transmit message + \brief transmit CAN message \param[in] can_periph \arg CANx(x=0,1) - \param[in] can_trasnmit_message_struct: struct for CAN transmit message - can_rx_sfid: 0x00000000 - 0x000007FF - can_rx_efid: 0x00000000 - 0x1FFFFFFF - can_rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED - can_rx_ft: CAN_FT_DATA, CAN_FT_REMOTE - can_rx_dlenc: 1 - 7 - can_rx_data[]: 0x00 - 0xFF + \param[in] transmit_message: struct for CAN transmit message + \arg tx_sfid: 0x00000000 - 0x000007FF + \arg tx_efid: 0x00000000 - 0x1FFFFFFF + \arg tx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg tx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg tx_dlen: 0 - 8 + \arg tx_data[]: 0x00 - 0xFF \param[out] none - \retval none + \retval mailbox_number */ uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message) { @@ -322,10 +430,11 @@ uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* t }else{ mailbox_number = CAN_NOMAILBOX; } + /* return no mailbox empty */ if(CAN_NOMAILBOX == mailbox_number){ return CAN_NOMAILBOX; } - + CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN; if(CAN_FF_STANDARD == transmit_message->tx_ff){ /* set transmit mailbox standard identifier */ @@ -357,10 +466,11 @@ uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* t } /*! - \brief CAN transmit state + \brief get CAN transmit state \param[in] can_periph \arg CANx(x=0,1) \param[in] mailbox_number + only one parameter can be selected which is shown as below: \arg CAN_MAILBOX(x=0,1,2) \param[out] none \retval can_transmit_state_enum @@ -369,14 +479,18 @@ can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox { can_transmit_state_enum state = CAN_TRANSMIT_FAILED; uint32_t val = 0U; - + + /* check selected mailbox state */ switch(mailbox_number){ + /* mailbox0 */ case CAN_MAILBOX0: val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0); break; + /* mailbox1 */ case CAN_MAILBOX1: val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1); break; + /* mailbox2 */ case CAN_MAILBOX2: val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2); break; @@ -384,32 +498,36 @@ can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox val = CAN_TRANSMIT_FAILED; break; } + switch(val){ - /* transmit pending */ - case (CAN_STATE_PENDING): + /* transmit pending */ + case (CAN_STATE_PENDING): state = CAN_TRANSMIT_PENDING; break; /* transmit failed */ - case (CAN_TSTAT_MTF0 | CAN_TSTAT_TME0): + case (CAN_TSTAT_MTF0 | CAN_TSTAT_TME0): state = CAN_TRANSMIT_FAILED; break; - case (CAN_TSTAT_MTF1 | CAN_TSTAT_TME1): + case (CAN_TSTAT_MTF1 | CAN_TSTAT_TME1): state = CAN_TRANSMIT_FAILED; break; - case (CAN_TSTAT_MTF2 | CAN_TSTAT_TME2): + case (CAN_TSTAT_MTF2 | CAN_TSTAT_TME2): state = CAN_TRANSMIT_FAILED; break; /* transmit succeeded */ case (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0): state = CAN_TRANSMIT_OK; break; + /* mailbox1 transmit succeeded */ case (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1): state = CAN_TRANSMIT_OK; break; + /* mailbox2 transmit succeeded */ case (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2): state = CAN_TRANSMIT_OK; break; - default: + /* transmit failed */ + default: state = CAN_TRANSMIT_FAILED; break; } @@ -417,10 +535,11 @@ can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox } /*! - \brief CAN stop transmission + \brief stop CAN transmission \param[in] can_periph \arg CANx(x=0,1) \param[in] mailbox_number + only one parameter can be selected which is shown as below: \arg CAN_MAILBOXx(x=0,1,2) \param[out] none \retval none @@ -429,12 +548,18 @@ void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) { if(CAN_MAILBOX0 == mailbox_number){ CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0; + while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){ + } }else if(CAN_MAILBOX1 == mailbox_number){ CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1; + while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){ + } }else if(CAN_MAILBOX2 == mailbox_number){ CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2; + while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){ + } }else{ - /* illegal parameter*/ + /* illegal parameters */ } } @@ -443,15 +568,15 @@ void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) \param[in] can_periph \arg CANx(x=0,1) \param[in] fifo_number - \arg CAN_FIFO0x(x=0,1) - \param[out] can_receive_message_struct: struct for CAN receive message - can_rx_sfid: 0x00000000 - 0x000007FF - can_rx_efid: 0x00000000 - 0x1FFFFFFF - can_rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED - can_rx_ft: CAN_FT_DATA, CAN_FT_REMOTE - can_rx_dlenc: 1 - 7 - can_rx_data[]: 0x00 - 0xFF - can_rx_fi: 0 - 27 + \arg CAN_FIFOx(x=0,1) + \param[out] receive_message: struct for CAN receive message + \arg rx_sfid: 0x00000000 - 0x000007FF + \arg rx_efid: 0x00000000 - 0x1FFFFFFF + \arg rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg rx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg rx_dlen: 0 - 8 + \arg rx_data[]: 0x00 - 0xFF + \arg rx_fi: 0 - 27 \retval none */ void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message) @@ -460,29 +585,29 @@ void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_m receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number)); if(CAN_FF_STANDARD == receive_message->rx_ff){ /* get standard identifier */ - receive_message -> rx_sfid = (uint32_t)(RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); + receive_message->rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); }else{ /* get extended identifier */ - receive_message -> rx_efid = (uint32_t)(RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); + receive_message->rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); } - + /* get frame type */ - receive_message -> rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); - /* get recevie data length */ - receive_message -> rx_dlen = (uint8_t)(RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); + receive_message->rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); /* filtering index */ - receive_message -> rx_fi = (uint8_t)(RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); - + receive_message->rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); + /* get recevie data length */ + receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); + /* receive data */ - receive_message -> rx_data[0] = (uint8_t)(RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[1] = (uint8_t)(RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[2] = (uint8_t)(RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[3] = (uint8_t)(RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[4] = (uint8_t)(RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message -> rx_data[5] = (uint8_t)(RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message -> rx_data[6] = (uint8_t)(RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message -> rx_data[7] = (uint8_t)(RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); - + receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); + /* release FIFO */ if(CAN_FIFO0 == fifo_number){ CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; @@ -495,7 +620,9 @@ void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_m \brief release FIFO0 \param[in] can_periph \arg CANx(x=0,1) - \arg CAN_FIFO0x(x=0,1) + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) \param[out] none \retval none */ @@ -506,7 +633,8 @@ void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) }else if(CAN_FIFO1 == fifo_number){ CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; }else{ - /* illegal parameter */ + /* illegal parameters */ + CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n"); } } @@ -514,20 +642,24 @@ void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) \brief CAN receive message length \param[in] can_periph \arg CANx(x=0,1) - \arg CAN_FIFO0x(x=0,1) + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) \param[out] none \retval message length */ -uint8_t can_receive_message_length(uint32_t can_periph, uint8_t fifo_number) +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number) { uint8_t val = 0U; - + if(CAN_FIFO0 == fifo_number){ - val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIFO_RFL0_MASK); - }else if(CAN_FIFO0 == fifo_number){ - val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIFO_RFL0_MASK); + /* FIFO0 */ + val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK); + }else if(CAN_FIFO1 == fifo_number){ + /* FIFO1 */ + val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK); }else{ - /* illegal parameter */ + /* illegal parameters */ } return val; } @@ -537,25 +669,26 @@ uint8_t can_receive_message_length(uint32_t can_periph, uint8_t fifo_number) \param[in] can_periph \arg CANx(x=0,1) \param[in] can_working_mode - \arg CAN_INITIALIZE_MODE - \arg CAN_NORMAL_MODE - \arg CAN_SLEEP_MODE + only one parameter can be selected which is shown as below: + \arg CAN_MODE_INITIALIZE + \arg CAN_MODE_NORMAL + \arg CAN_MODE_SLEEP \param[out] none \retval ErrStatus: SUCCESS or ERROR */ ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) { ErrStatus flag = ERROR; - /* timeout for IWS or also for SLPWS bits*/ - uint32_t timeout = CAN_TIMEOUT; - + /* timeout for IWS or also for SLPWS bits */ + uint32_t timeout = CAN_TIMEOUT; + if(CAN_MODE_INITIALIZE == working_mode){ /* disable sleep mode */ CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); /* set initialize mode */ CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; /* wait the acknowledge */ - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (timeout != 0U)){ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ timeout--; } if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ @@ -567,7 +700,7 @@ ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) /* enter normal mode */ CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); /* wait the acknowledge */ - while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (timeout != 0U)){ + while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)){ timeout--; } if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))){ @@ -581,10 +714,10 @@ ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) /* set sleep mode */ CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD; /* wait the acknowledge */ - while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (timeout != 0U)){ + while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)){ timeout--; } - if (CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ flag = ERROR; }else{ flag = SUCCESS; @@ -592,7 +725,7 @@ ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) }else{ flag = ERROR; } - return flag; + return flag; } /*! @@ -606,13 +739,14 @@ ErrStatus can_wakeup(uint32_t can_periph) { ErrStatus flag = ERROR; uint32_t timeout = CAN_TIMEOUT; - + /* wakeup */ CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; - - while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (timeout != 0x00U)){ + + while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)){ timeout--; } + /* check state */ if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ flag = ERROR; }else{ @@ -627,66 +761,76 @@ ErrStatus can_wakeup(uint32_t can_periph) \arg CANx(x=0,1) \param[out] none \retval can_error_enum + \arg CAN_ERROR_NONE: no error + \arg CAN_ERROR_FILL: fill error + \arg CAN_ERROR_FORMATE: format error + \arg CAN_ERROR_ACK: ACK error + \arg CAN_ERROR_BITRECESSIVE: bit recessive + \arg CAN_ERROR_BITDOMINANTER: bit dominant error + \arg CAN_ERROR_CRC: CRC error + \arg CAN_ERROR_SOFTWARECFG: software configure */ can_error_enum can_error_get(uint32_t can_periph) { can_error_enum error; error = CAN_ERROR_NONE; - + /* get error type */ - error = (can_error_enum)((CAN_ERR(can_periph) & CAN_ERR_ERRN) >> 4U); + error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph))); return error; } /*! - \brief CAN receive error number + \brief get CAN receive error number \param[in] can_periph \arg CANx(x=0,1) \param[out] none \retval error number */ -uint8_t can_receive_error_number(uint32_t can_periph) +uint8_t can_receive_error_number_get(uint32_t can_periph) { uint8_t val; - - val = (uint8_t)((CAN_ERR(can_periph) & CAN_ERR_RECNT) >> 24U); + + /* get error count */ + val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph))); return val; } /*! - \brief CAN transmit error number + \brief get CAN transmit error number \param[in] can_periph \arg CANx(x=0,1) \param[out] none \retval error number */ -uint8_t can_transmit_error_number(uint32_t can_periph) +uint8_t can_transmit_error_number_get(uint32_t can_periph) { uint8_t val; - - val = (uint8_t)((CAN_ERR(can_periph) & CAN_ERR_TECNT) >> 16U); + + val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph))); return val; } /*! - \brief enable CAN interrupt + \brief enable CAN interrupt \param[in] can_periph \arg CANx(x=0,1) - \param[in] interrupt - \arg CAN_INTEN_TMEIE - \arg CAN_INTEN_RFNEIE0 - \arg CAN_INTEN_RFFIE0 - \arg CAN_INTEN_RFOIE0 - \arg CAN_INTEN_RFNEIE1 - \arg CAN_INTEN_RFFIE1 - \arg CAN_INTEN_RFOIE1 - \arg CAN_INTEN_WERRIE - \arg CAN_INTEN_PERRIE - \arg CAN_INTEN_BOIE - \arg CAN_INTEN_ERRNIE - \arg CAN_INTEN_ERRIE - \arg CAN_INTEN_WUIE - \arg CAN_INTEN_SLPWIE + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WU: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable \param[out] none \retval none */ @@ -696,24 +840,25 @@ void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt) } /*! - \brief disable CAN interrupt + \brief disable CAN interrupt \param[in] can_periph \arg CANx(x=0,1) \param[in] interrupt - \arg CAN_INTEN_TMEIE - \arg CAN_INTEN_RFNEIE0 - \arg CAN_INTEN_RFFIE0 - \arg CAN_INTEN_RFOIE0 - \arg CAN_INTEN_RFNEIE1 - \arg CAN_INTEN_RFFIE1 - \arg CAN_INTEN_RFOIE1 - \arg CAN_INTEN_WERRIE - \arg CAN_INTEN_PERRIE - \arg CAN_INTEN_BOIE - \arg CAN_INTEN_ERRNIE - \arg CAN_INTEN_ERRIE - \arg CAN_INTEN_WUIE - \arg CAN_INTEN_SLPWIE + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WU: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable \param[out] none \retval none */ @@ -728,24 +873,46 @@ void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) \arg CANx(x=0,1) \param[in] flag: CAN flags, refer to can_flag_enum only one parameter can be selected which is shown as below: - \arg CAN_FLAG_MTE2 - \arg CAN_FLAG_MTE1 - \arg CAN_FLAG_MTE0 - \arg CAN_FLAG_MTF2 - \arg CAN_FLAG_MTF1 - \arg CAN_FLAG_MTF0 - \arg CAN_FLAG_RFO0 - \arg CAN_FLAG_RFF0 - \arg CAN_FLAG_RFO1 - \arg CAN_FLAG_RFF1 - \arg CAN_FLAG_BOERR - \arg CAN_FLAG_PERR - \arg CAN_FLAG_WERR + \arg CAN_FLAG_RXL: RX level + \arg CAN_FLAG_LASTRX: last sample value of RX pin + \arg CAN_FLAG_RS: receiving state + \arg CAN_FLAG_TS: transmitting state + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_SLPWS: sleep working state + \arg CAN_FLAG_IWS: initial working state + \arg CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO + \arg CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO + \arg CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO + \arg CAN_FLAG_TME2: transmit mailbox 2 empty + \arg CAN_FLAG_TME1: transmit mailbox 1 empty + \arg CAN_FLAG_TME0: transmit mailbox 0 empty + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \arg CAN_FLAG_BOERR: bus-off error + \arg CAN_FLAG_PERR: passive error + \arg CAN_FLAG_WERR: warning error \param[out] none \retval FlagStatus: SET or RESET */ FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) -{ +{ + /* get flag and interrupt enable state */ if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))){ return SET; }else{ @@ -755,26 +922,35 @@ FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) /*! \brief clear CAN flag state - \param[in] can_periph + \param[in] can_periph \arg CANx(x=0,1) \param[in] flag: CAN flags, refer to can_flag_enum only one parameter can be selected which is shown as below: - \arg CAN_FLAG_MTE2 - \arg CAN_FLAG_MTE1 - \arg CAN_FLAG_MTE0 - \arg CAN_FLAG_MTF2 - \arg CAN_FLAG_MTF1 - \arg CAN_FLAG_MTF0 - \arg CAN_FLAG_RFO0 - \arg CAN_FLAG_RFF0 - \arg CAN_FLAG_RFO1 - \arg CAN_FLAG_RFF1 + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full \param[out] none \retval none */ void can_flag_clear(uint32_t can_periph, can_flag_enum flag) { - CAN_REG_VAL(can_periph, flag) |= BIT(CAN_BIT_POS(flag)); + CAN_REG_VAL(can_periph, flag) = BIT(CAN_BIT_POS(flag)); } /*! @@ -783,62 +959,43 @@ void can_flag_clear(uint32_t can_periph, can_flag_enum flag) \arg CANx(x=0,1) \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum only one parameter can be selected which is shown as below: - \arg CAN_INT_SLPIF - \arg CAN_INT_WUIF - \arg CAN_INT_ERRIF + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFL0: receive FIFO0 not empty interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \arg CAN_INT_FLAG_RFL1: receive FIFO1 not empty interrupt flag + \arg CAN_INT_FLAG_ERRN: error number interrupt flag + \arg CAN_INT_FLAG_BOERR: bus-off error interrupt flag + \arg CAN_INT_FLAG_PERR: passive error interrupt flag + \arg CAN_INT_FLAG_WERR: warning error interrupt flag \param[out] none \retval FlagStatus: SET or RESET */ FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag) -{ - FlagStatus inten = RESET; - FlagStatus temp = RESET; - FlagStatus status1 = RESET; - FlagStatus status2 = RESET; - - switch(flag){ - /* get the status of sleep working interrupt enable bit */ - case CAN_INT_SLPIF: - inten = (FlagStatus)(CAN_INTEN(can_periph) & CAN_INTEN_SLPWIE); - break; - /* get the status of wakeup interrupt enable bit */ - case CAN_INT_WUIF: - inten = (FlagStatus)(CAN_INTEN(can_periph) & CAN_INTEN_WUIE); - break; - /* get the status of error falgs and its enable bit */ - case CAN_INT_ERRIF: - /* check if the BOERR bit in CAN_ERR register and BOIE bit in CAN_INTEN register are set */ - status1 = (FlagStatus)(CAN_INTEN(can_periph) & CAN_INTEN_BOIE); - status2 = (FlagStatus)(CAN_ERR(can_periph) & CAN_ERR_BOERR); - if((RESET != status1) && (RESET != status2)){ - inten = SET; - } - /* check if the WERR bit in CAN_ERR register and WERRIE bit in CAN_INTEN register are set */ - status1 = (FlagStatus)(CAN_INTEN(can_periph) & CAN_INTEN_WERRIE); - status2 = (FlagStatus)(CAN_ERR(can_periph) & CAN_ERR_WERR); - if((RESET != status1) && (RESET != status2)){ - inten = SET; - } - /* check if the PERR bit in CAN_ERR register and PERRIE bit in CAN_INTEN register are set */ - status1 = (FlagStatus)(CAN_INTEN(can_periph) & CAN_INTEN_PERRIE); - status2 = (FlagStatus)(CAN_ERR(can_periph) & CAN_ERR_PERR); - if((RESET != status1) && (RESET != status2)){ - inten = SET; - } - /* check if the ERRN bit in CAN_ERR register and ERRNIE bit in CAN_INTEN register are set */ - status1 = (FlagStatus)(CAN_INTEN(can_periph) & CAN_INTEN_ERRNIE); - status2 = (FlagStatus)(CAN_ERR(can_periph) & CAN_ERR_ERRN); - if((RESET != status1) && (RESET != status2)){ - inten = SET; - } - break; - default: - break; +{ + uint32_t ret1 = RESET; + uint32_t ret2 = RESET; + + /* get the staus of interrupt flag */ + if (flag == CAN_INT_FLAG_RFF0) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0); + } else if (flag == CAN_INT_FLAG_RFF1) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1); + } else if (flag == CAN_INT_FLAG_ERRN) { + ret1 = can_error_get(can_periph); + } else { + ret1 = CAN_REG_VALS(can_periph, flag) & BIT(CAN_BIT_POS0(flag)); } - /* get the interrupt flag */ - temp = (FlagStatus)(CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag))); - /* check the interrupt enable bit and corresponding flag bit are set */ - if((RESET != inten) && (RESET != temp)){ + /* get the staus of interrupt enale bit */ + ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(flag)); + if(ret1 && ret2){ return SET; }else{ return RESET; @@ -851,13 +1008,20 @@ FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum f \arg CANx(x=0,1) \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum only one parameter can be selected which is shown as below: - \arg CAN_INT_SLPIF - \arg CAN_INT_WUIF - \arg CAN_INT_ERRIF + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag \param[out] none \retval none */ void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag) { - CAN_REG_VAL(can_periph, flag) |= BIT(CAN_BIT_POS(flag)); + CAN_REG_VALS(can_periph, flag) = BIT(CAN_BIT_POS0(flag)); } diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c index e51d8dc483..bfe79cb9aa 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c @@ -1,16 +1,43 @@ /*! - \file gd32f4xx_crc.c - \brief CRC driver + \file gd32f4xx_crc.c + \brief CRC driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_crc.h" +#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU) +#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U) /*! \brief deinit CRC calculation unit \param[in] none @@ -19,13 +46,13 @@ */ void crc_deinit(void) { - CRC_DATA = (uint32_t)0xFFFFFFFFU; - CRC_FDATA = (uint32_t)0x00000000U; - CRC_CTL = CRC_CTL_RST; + CRC_DATA = CRC_DATA_RESET_VALUE; + CRC_FDATA = CRC_FDATA_RESET_VALUE; + CRC_CTL = (uint32_t)CRC_CTL_RST; } /*! - \brief reset data register to the value of initializaiton data register + \brief reset data register(CRC_DATA) to the value of 0xFFFFFFFF \param[in] none \param[out] none \retval none @@ -36,7 +63,7 @@ void crc_data_register_reset(void) } /*! - \brief read the data register + \brief read the value of the data register \param[in] none \param[out] none \retval 32-bit value of the data register @@ -49,7 +76,7 @@ uint32_t crc_data_register_read(void) } /*! - \brief read the free data register + \brief read the value of the free data register \param[in] none \param[out] none \retval 8-bit value of the free data register @@ -62,8 +89,8 @@ uint8_t crc_free_data_register_read(void) } /*! - \brief write the free data register - \param[in] free_data: specify 8-bit data + \brief write data to the free data register + \param[in] free_data: specified 8-bit data \param[out] none \retval none */ @@ -73,10 +100,10 @@ void crc_free_data_register_write(uint8_t free_data) } /*! - \brief CRC calculate a 32-bit data - \param[in] sdata: specify 32-bit data + \brief calculate the CRC value of a 32-bit data + \param[in] sdata: specified 32-bit data \param[out] none - \retval 32-bit CRC calculate value + \retval 32-bit value calculated by CRC */ uint32_t crc_single_data_calculate(uint32_t sdata) { @@ -85,11 +112,11 @@ uint32_t crc_single_data_calculate(uint32_t sdata) } /*! - \brief CRC calculate a 32-bit data array - \param[in] array: pointer to an array of 32 bit data words + \brief calculate the CRC value of an array of 32-bit values + \param[in] array: pointer to an array of 32-bit values \param[in] size: size of the array \param[out] none - \retval 32-bit CRC calculate value + \retval 32-bit value calculated by CRC */ uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size) { diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c index 34431164a3..ab67c4ad73 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c @@ -1,18 +1,49 @@ /*! - \file gd32f4xx_ctc.c - \brief CTC driver + \file gd32f4xx_ctc.c + \brief CTC driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_ctc.h" #define CTC_FLAG_MASK ((uint32_t)0x00000700U) +/* CTC register bit offset */ +#define CTC_TRIMVALUE_OFFSET ((uint32_t)8U) +#define CTC_TRIM_VALUE_OFFSET ((uint32_t)8U) +#define CTC_REFCAP_OFFSET ((uint32_t)16U) +#define CTC_LIMIT_VALUE_OFFSET ((uint32_t)16U) + /*! \brief reset CTC clock trim controller \param[in] none @@ -27,17 +58,40 @@ void ctc_deinit(void) } /*! - \brief configure the IRC48M trim value - \param[in] ctc_trim_value: 8-bit IRC48M trim value + \brief enable CTC trim counter + \param[in] none \param[out] none \retval none */ -void ctc_irc48m_trim_value_config(uint8_t ctc_trim_value) +void ctc_counter_enable(void) +{ + CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN; +} + +/*! + \brief disable CTC trim counter + \param[in] none + \param[out] none + \retval none +*/ +void ctc_counter_disable(void) +{ + CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN); +} + +/*! + \brief configure the IRC48M trim value + \param[in] ctc_trim_value: 8-bit IRC48M trim value + \arg 0x00 - 0x3F + \param[out] none + \retval none +*/ +void ctc_irc48m_trim_value_config(uint8_t trim_value) { /* clear TRIMVALUE bits */ CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE); /* set TRIMVALUE bits */ - CTC_CTL0 |= ((uint32_t)ctc_trim_value << 8); + CTC_CTL0 |= ((uint32_t)trim_value << CTC_TRIM_VALUE_OFFSET); } /*! @@ -53,86 +107,68 @@ void ctc_software_refsource_pulse_generate(void) /*! \brief configure hardware automatically trim mode - \param[in] ctc_hardmode: + \param[in] hardmode: + only one parameter can be selected which is shown as below: \arg CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable \arg CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable \param[out] none \retval none */ -void ctc_hardware_trim_mode_config(uint32_t ctc_hardmode) +void ctc_hardware_trim_mode_config(uint32_t hardmode) { CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM); - CTC_CTL0 |= (uint32_t)ctc_hardmode; -} - -/*! - \brief enable CTC counter - \param[in] none - \param[out] none - \retval none -*/ -void ctc_counter_enable(void) -{ - CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN; -} - -/*! - \brief disable CTC counter - \param[in] none - \param[out] none - \retval none -*/ -void ctc_counter_disable(void) -{ - CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN); + CTC_CTL0 |= (uint32_t)hardmode; } /*! \brief configure reference signal source polarity - \param[in] ctc_polarity: + \param[in] polarity: + only one parameter can be selected which is shown as below: \arg CTC_REFSOURCE_POLARITY_FALLING: reference signal source polarity is falling edge \arg CTC_REFSOURCE_POLARITY_RISING: reference signal source polarity is rising edge \param[out] none \retval none */ -void ctc_refsource_polarity_config(uint32_t ctc_polarity) +void ctc_refsource_polarity_config(uint32_t polarity) { CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL); - CTC_CTL1 |= (uint32_t)ctc_polarity; + CTC_CTL1 |= (uint32_t)polarity; } /*! \brief select USBFS or USBHS SOF signal - \param[in] ctc_usbsof: + \param[in] usbsof: \arg CTC_USBSOFSEL_USBHS: USBHS SOF signal is selected \arg CTC_USBSOFSEL_USBFS: USBFS SOF signal is selected \param[out] none \retval none */ -void ctc_usbsof_signal_select(uint32_t ctc_usbsof) +void ctc_usbsof_signal_select(uint32_t usbsof) { CTC_CTL1 &= (uint32_t)(~CTC_CTL1_USBSOFSEL); - CTC_CTL1 |= (uint32_t)ctc_usbsof; + CTC_CTL1 |= (uint32_t)usbsof; } /*! \brief select reference signal source - \param[in] ctc_refs: + \param[in] refs: + only one parameter can be selected which is shown as below: \arg CTC_REFSOURCE_GPIO: GPIO is selected - \arg CTC_REFSOURCE_LXTAL: LXTAL is clock selected + \arg CTC_REFSOURCE_LXTAL: LXTAL is selected \arg CTC_REFSOURCE_USBSOF: USBSOF is selected \param[out] none \retval none */ -void ctc_refsource_signal_select(uint32_t ctc_refs) +void ctc_refsource_signal_select(uint32_t refs) { CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL); - CTC_CTL1 |= (uint32_t)ctc_refs; + CTC_CTL1 |= (uint32_t)refs; } /*! \brief configure reference signal source prescaler - \param[in] ctc_prescaler: + \param[in] prescaler: + only one parameter can be selected which is shown as below: \arg CTC_REFSOURCE_PSC_OFF: reference signal not divided \arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2 \arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4 @@ -144,34 +180,36 @@ void ctc_refsource_signal_select(uint32_t ctc_refs) \param[out] none \retval none */ -void ctc_refsource_prescaler_config(uint32_t ctc_prescaler) +void ctc_refsource_prescaler_config(uint32_t prescaler) { CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC); - CTC_CTL1 |= (uint32_t)ctc_prescaler; + CTC_CTL1 |= (uint32_t)prescaler; } /*! \brief configure clock trim base limit value - \param[in] ctc_limit_value: 8-bit clock trim base limit value + \param[in] limit_value: 8-bit clock trim base limit value + \arg 0x00 - 0xFF \param[out] none \retval none */ -void ctc_clock_limit_value_config(uint8_t ctc_limit_value) +void ctc_clock_limit_value_config(uint8_t limit_value) { CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM); - CTC_CTL1 |= (uint32_t)((uint32_t)ctc_limit_value << 16); + CTC_CTL1 |= (uint32_t)((uint32_t)limit_value << CTC_LIMIT_VALUE_OFFSET); } /*! \brief configure CTC counter reload value - \param[in] ctc_reload_value: 16-bit CTC counter reload value + \param[in] reload_value: 16-bit CTC counter reload value + \arg 0x0000 - 0xFFFF \param[out] none \retval none */ -void ctc_counter_reload_value_config(uint16_t ctc_reload_value) +void ctc_counter_reload_value_config(uint16_t reload_value) { CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE); - CTC_CTL1 |= (uint32_t)ctc_reload_value; + CTC_CTL1 |= (uint32_t)reload_value; } /*! @@ -183,7 +221,7 @@ void ctc_counter_reload_value_config(uint16_t ctc_reload_value) uint16_t ctc_counter_capture_value_read(void) { uint16_t capture_value = 0U; - capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> 16); + capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> CTC_REFCAP_OFFSET); return (capture_value); } @@ -226,65 +264,71 @@ uint16_t ctc_counter_reload_value_read(void) uint8_t ctc_irc48m_trim_value_read(void) { uint8_t trim_value = 0U; - trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> 8); + trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> CTC_TRIMVALUE_OFFSET); return (trim_value); } /*! \brief enable the CTC interrupt - \param[in] ctc_interrupt: CTC interrupt enable - \arg CTC_INT_CKOKIE: clock trim OK interrupt enable - \arg CTC_INT_CKWARNIE: clock trim warning interrupt enable - \arg CTC_INT_ERRIE: error interrupt enable - \arg CTC_INT_EREFIE: expect reference interrupt enable + \param[in] interrupt: CTC interrupt enable + one or more parameters can be selected which are shown as below: + \arg CTC_INT_CKOK: clock trim OK interrupt enable + \arg CTC_INT_CKWARN: clock trim warning interrupt enable + \arg CTC_INT_ERR: error interrupt enable + \arg CTC_INT_EREF: expect reference interrupt enable \param[out] none \retval none */ -void ctc_interrupt_enable(uint32_t ctc_interrupt) +void ctc_interrupt_enable(uint32_t interrupt) { - CTC_CTL0 |= (uint32_t)ctc_interrupt; + CTC_CTL0 |= (uint32_t)interrupt; } /*! \brief disable the CTC interrupt - \param[in] ctc_interrupt: CTC interrupt enable source - \arg CTC_INT_CKOKIE: clock trim OK interrupt enable - \arg CTC_INT_CKWARNIE: clock trim warning interrupt enable - \arg CTC_INT_ERRIE: error interrupt enable - \arg CTC_INT_EREFIE: expect reference interrupt enable + \param[in] interrupt: CTC interrupt enable source + one or more parameters can be selected which are shown as below: + \arg CTC_INT_CKOK: clock trim OK interrupt enable + \arg CTC_INT_CKWARN: clock trim warning interrupt enable + \arg CTC_INT_ERR: error interrupt enable + \arg CTC_INT_EREF: expect reference interrupt enable \param[out] none \retval none */ -void ctc_interrupt_disable(uint32_t ctc_interrupt) +void ctc_interrupt_disable(uint32_t interrupt) { - CTC_CTL0 &= (uint32_t)(~ctc_interrupt); + CTC_CTL0 &= (uint32_t)(~interrupt); } /*! \brief get CTC interrupt flag - \param[in] ctc_interrupt: the CTC interrupt flag - \arg CTC_INT_CKOK: clock trim OK interrupt - \arg CTC_INT_CKWARN: clock trim warning interrupt - \arg CTC_INT_ERR: error interrupt - \arg CTC_INT_EREF: expect reference interrupt - \arg CTC_INT_CKERR: clock trim error bit interrupt - \arg CTC_INT_REFMISS: reference sync pulse miss interrupt - \arg CTC_INT_TRIMERR: trim value error interrupt + \param[in] int_flag: the CTC interrupt flag + only one parameter can be selected which is shown as below: + \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt + \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt + \arg CTC_INT_FLAG_ERR: error interrupt + \arg CTC_INT_FLAG_EREF: expect reference interrupt + \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt + \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt + \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt \param[out] none \retval FlagStatus: SET or RESET */ -FlagStatus ctc_interrupt_flag_get(uint32_t ctc_interrupt) +FlagStatus ctc_interrupt_flag_get(uint32_t int_flag) { - uint32_t interrupt = 0U, intenable = 0U; + uint32_t interrupt_flag = 0U, intenable = 0U; - if(ctc_interrupt & CTC_FLAG_MASK){ - intenable = CTC_CTL0 & CTC_INT_ERRIE; + /* check whether the interrupt is enabled */ + if(RESET != (int_flag & CTC_FLAG_MASK)){ + intenable = CTC_CTL0 & CTC_CTL0_ERRIE; }else{ - intenable = CTC_CTL0 & ctc_interrupt; + intenable = CTC_CTL0 & int_flag; } - interrupt = CTC_STAT & ctc_interrupt; - if(interrupt && intenable){ + /* get interrupt flag status */ + interrupt_flag = CTC_STAT & int_flag; + + if(interrupt_flag && intenable){ return SET; }else{ return RESET; @@ -293,32 +337,34 @@ FlagStatus ctc_interrupt_flag_get(uint32_t ctc_interrupt) /*! \brief clear CTC interrupt flag - \param[in] ctc_interrupt: the CTC interrupt flag - \arg CTC_INT_CKOK: clock trim OK interrupt - \arg CTC_INT_CKWARN: clock trim warning interrupt - \arg CTC_INT_ERR: error interrupt - \arg CTC_INT_EREF: expect reference interrupt - \arg CTC_INT_CKERR: clock trim error bit interrupt - \arg CTC_INT_REFMISS: reference sync pulse miss interrupt - \arg CTC_INT_TRIMERR: trim value error interrupt + \param[in] int_flag: the CTC interrupt flag + only one parameter can be selected which is shown as below: + \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt + \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt + \arg CTC_INT_FLAG_ERR: error interrupt + \arg CTC_INT_FLAG_EREF: expect reference interrupt + \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt + \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt + \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt \param[out] none \retval none -*/ -void ctc_interrupt_flag_clear(uint32_t ctc_interrupt) +*/ +void ctc_interrupt_flag_clear(uint32_t int_flag) { - if(ctc_interrupt & CTC_FLAG_MASK){ + if(RESET != (int_flag & CTC_FLAG_MASK)){ CTC_INTC |= CTC_INTC_ERRIC; }else{ - CTC_INTC |= ctc_interrupt; + CTC_INTC |= int_flag; } } /*! \brief get CTC flag - \param[in] ctc_flag: the CTC flag + \param[in] flag: the CTC flag + only one parameter can be selected which is shown as below: \arg CTC_FLAG_CKOK: clock trim OK flag - \arg CTC_FLAG_CKWARN: clock trim warning flag - \arg CTC_FLAG_ERR: error flag + \arg CTC_FLAG_CKWARN: clock trim warning flag + \arg CTC_FLAG_ERR: error flag \arg CTC_FLAG_EREF: expect reference flag \arg CTC_FLAG_CKERR: clock trim error bit \arg CTC_FLAG_REFMISS: reference sync pulse miss @@ -326,9 +372,9 @@ void ctc_interrupt_flag_clear(uint32_t ctc_interrupt) \param[out] none \retval FlagStatus: SET or RESET */ -FlagStatus ctc_flag_get(uint32_t ctc_flag) +FlagStatus ctc_flag_get(uint32_t flag) { - if(RESET != (CTC_STAT & ctc_flag)){ + if(RESET != (CTC_STAT & flag)){ return SET; }else{ return RESET; @@ -337,10 +383,11 @@ FlagStatus ctc_flag_get(uint32_t ctc_flag) /*! \brief clear CTC flag - \param[in] ctc_flag: the CTC flag + \param[in] flag: the CTC flag + only one parameter can be selected which is shown as below: \arg CTC_FLAG_CKOK: clock trim OK flag - \arg CTC_FLAG_CKWARN: clock trim warning flag - \arg CTC_FLAG_ERR: error flag + \arg CTC_FLAG_CKWARN: clock trim warning flag + \arg CTC_FLAG_ERR: error flag \arg CTC_FLAG_EREF: expect reference flag \arg CTC_FLAG_CKERR: clock trim error bit \arg CTC_FLAG_REFMISS: reference sync pulse miss @@ -348,11 +395,11 @@ FlagStatus ctc_flag_get(uint32_t ctc_flag) \param[out] none \retval none */ -void ctc_flag_clear(uint32_t ctc_flag) +void ctc_flag_clear(uint32_t flag) { - if(ctc_flag & CTC_FLAG_MASK){ + if(RESET != (flag & CTC_FLAG_MASK)){ CTC_INTC |= CTC_INTC_ERRIC; }else{ - CTC_INTC |= ctc_flag; + CTC_INTC |= flag; } } diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c index 2204d08c21..3a5dd52cdd 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c @@ -1,16 +1,46 @@ /*! - \file gd32f4xx_dac.c - \brief DAC driver + \file gd32f4xx_dac.c + \brief DAC driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_dac.h" +/* DAC register bit offset */ +#define DAC1_REG_OFFSET ((uint32_t)16U) +#define DH_12BIT_OFFSET ((uint32_t)16U) +#define DH_8BIT_OFFSET ((uint32_t)8U) + /*! \brief deinitialize DAC \param[in] none @@ -25,8 +55,7 @@ void dac_deinit(void) /*! \brief enable DAC - \param[in] dac_periph - \arg DACx(x =0,1) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ @@ -37,12 +66,11 @@ void dac_enable(uint32_t dac_periph) }else{ DAC_CTL |= DAC_CTL_DEN1; } -} +} /*! \brief disable DAC - \param[in] dac_periph - \arg DACx(x =0,1) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ @@ -57,8 +85,7 @@ void dac_disable(uint32_t dac_periph) /*! \brief enable DAC DMA function - \param[in] dac_periph - \arg DACx(x=0,1) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ @@ -73,8 +100,7 @@ void dac_dma_enable(uint32_t dac_periph) /*! \brief disable DAC DMA function - \param[in] dac_periph - \arg DACx(x=0,1) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ @@ -89,8 +115,7 @@ void dac_dma_disable(uint32_t dac_periph) /*! \brief enable DAC output buffer - \param[in] dac_periph - \arg DACx(x =0,1) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ @@ -105,8 +130,7 @@ void dac_output_buffer_enable(uint32_t dac_periph) /*! \brief disable DAC output buffer - \param[in] dac_periph - \arg DACx(x =0,1) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ @@ -119,10 +143,79 @@ void dac_output_buffer_disable(uint32_t dac_periph) } } +/*! + \brief get DAC output value + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval DAC output data +*/ +uint16_t dac_output_value_get(uint32_t dac_periph) +{ + uint16_t data = 0U; + if(DAC0 == dac_periph){ + /* store the DAC0 output value */ + data = (uint16_t)DAC0_DO; + }else{ + /* store the DAC1 output value */ + data = (uint16_t)DAC1_DO; + } + return data; +} + +/*! + \brief set the DAC specified data holding register value + \param[in] dac_periph: DACx(x = 0,1) + \param[in] dac_align: data alignment + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8 bit alignment + \arg DAC_ALIGN_12B_R: data right 12 bit alignment + \arg DAC_ALIGN_12B_L: data left 12 bit alignment + \param[in] data: data to be loaded + \param[out] none + \retval none +*/ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) +{ + if(DAC0 == dac_periph){ + switch(dac_align){ + /* data right 12 bit alignment */ + case DAC_ALIGN_12B_R: + DAC0_R12DH = data; + break; + /* data left 12 bit alignment */ + case DAC_ALIGN_12B_L: + DAC0_L12DH = data; + break; + /* data right 8 bit alignment */ + case DAC_ALIGN_8B_R: + DAC0_R8DH = data; + break; + default: + break; + } + }else{ + switch(dac_align){ + /* data right 12 bit alignment */ + case DAC_ALIGN_12B_R: + DAC1_R12DH = data; + break; + /* data left 12 bit alignment */ + case DAC_ALIGN_12B_L: + DAC1_L12DH = data; + break; + /* data right 8 bit alignment */ + case DAC_ALIGN_8B_R: + DAC1_R8DH = data; + break; + default: + break; + } + } +} + /*! \brief enable DAC trigger - \param[in] dac_periph - \arg DACx(x =0,1) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ @@ -137,8 +230,7 @@ void dac_trigger_enable(uint32_t dac_periph) /*! \brief disable DAC trigger - \param[in] dac_periph - \arg DACx(x =0,1) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ @@ -151,74 +243,11 @@ void dac_trigger_disable(uint32_t dac_periph) } } -/*! - \brief enable DAC software trigger - \param[in] dac_periph - \arg DACx(x =0,1) - \retval none -*/ -void dac_software_trigger_enable(uint32_t dac_periph) -{ - if(DAC0 == dac_periph){ - DAC_SWT |= DAC_SWT_SWTR0; - }else{ - DAC_SWT |= DAC_SWT_SWTR1; - } -} - -/*! - \brief disable DAC software trigger - \param[in] dac_periph - \arg DACx(x =0,1) - \param[out] none - \retval none -*/ -void dac_software_trigger_disable(uint32_t dac_periph) -{ - if(DAC0 == dac_periph){ - DAC_SWT &= ~DAC_SWT_SWTR0; - }else{ - DAC_SWT &= ~DAC_SWT_SWTR1; - } -} - -/*! - \brief enable DAC interrupt(DAC0 DMA underrun interrupt) - \param[in] dac_periph - \arg DACx(x=0,1) - \param[out] none - \retval none -*/ -void dac_interrupt_enable(uint32_t dac_periph) -{ - if(DAC0 == dac_periph){ - DAC_CTL |= DAC_CTL_DDUDRIE0; - }else{ - DAC_CTL |= DAC_CTL_DDUDRIE1; - } -} - -/*! - \brief disable DAC interrupt(DAC0 DMA underrun interrupt) - \param[in] dac_periph - \arg DACx(x=0,1) - \param[out] none - \retval none -*/ -void dac_interrupt_disable(uint32_t dac_periph) -{ - if(DAC0 == dac_periph){ - DAC_CTL &= ~DAC_CTL_DDUDRIE0; - }else{ - DAC_CTL &= ~DAC_CTL_DDUDRIE1; - } -} - /*! \brief set DAC trigger source - \param[in] dac_periph - \arg DACx(x =0,1) + \param[in] dac_periph: DACx(x = 0,1) \param[in] triggersource: external triggers of DAC + only one parameter can be selected which is shown as below: \arg DAC_TRIGGER_T1_TRGO: TIMER1 TRGO \arg DAC_TRIGGER_T3_TRGO: TIMER3 TRGO \arg DAC_TRIGGER_T4_TRGO: TIMER4 TRGO @@ -233,19 +262,50 @@ void dac_interrupt_disable(uint32_t dac_periph) void dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource) { if(DAC0 == dac_periph){ + /* configure DAC0 trigger source */ DAC_CTL &= ~DAC_CTL_DTSEL0; DAC_CTL |= triggersource; }else{ + /* configure DAC1 trigger source */ DAC_CTL &= ~DAC_CTL_DTSEL1; - DAC_CTL |= (triggersource << 16); + DAC_CTL |= (triggersource << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC software trigger + \param[in] dac_periph: DACx(x = 0,1) + \retval none +*/ +void dac_software_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT |= DAC_SWT_SWTR0; + }else{ + DAC_SWT |= DAC_SWT_SWTR1; + } +} + +/*! + \brief disable DAC software trigger + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_software_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT &= ~DAC_SWT_SWTR0; + }else{ + DAC_SWT &= ~DAC_SWT_SWTR1; } } /*! \brief configure DAC wave mode - \param[in] dac_periph - \arg DACx(x=0,1) - \param[in] wave_mode + \param[in] dac_periph: DACx(x = 0,1) + \param[in] wave_mode: noise wave mode + only one parameter can be selected which is shown as below: \arg DAC_WAVE_DISABLE: wave disable \arg DAC_WAVE_MODE_LFSR: LFSR noise mode \arg DAC_WAVE_MODE_TRIANGLE: triangle noise mode @@ -255,19 +315,21 @@ void dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource) void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode) { if(DAC0 == dac_periph){ + /* configure DAC0 wave mode */ DAC_CTL &= ~DAC_CTL_DWM0; DAC_CTL |= wave_mode; }else{ + /* configure DAC1 wave mode */ DAC_CTL &= ~DAC_CTL_DWM1; - DAC_CTL |= wave_mode << 16; + DAC_CTL |= (wave_mode << DAC1_REG_OFFSET); } } /*! \brief configure DAC wave bit width - \param[in] dac_periph - \arg DACx(x=0,1) - \param[in] bit_width + \param[in] dac_periph: DACx(x = 0,1) + \param[in] bit_width: noise wave bit width + only one parameter can be selected which is shown as below: \arg DAC_WAVE_BIT_WIDTH_1: bit width of the wave signal is 1 \arg DAC_WAVE_BIT_WIDTH_2: bit width of the wave signal is 2 \arg DAC_WAVE_BIT_WIDTH_3: bit width of the wave signal is 3 @@ -286,19 +348,21 @@ void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode) void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width) { if(DAC0 == dac_periph){ + /* configure DAC0 wave bit width */ DAC_CTL &= ~DAC_CTL_DWBW0; DAC_CTL |= bit_width; }else{ + /* configure DAC1 wave bit width */ DAC_CTL &= ~DAC_CTL_DWBW1; - DAC_CTL |= bit_width << 16; + DAC_CTL |= (bit_width << DAC1_REG_OFFSET); } } /*! \brief configure DAC LFSR noise mode - \param[in] dac_periph - \arg DACx(x=0,1) - \param[in] unmask_bits + \param[in] dac_periph: DACx(x = 0,1) + \param[in] unmask_bits: unmask LFSR bits in DAC LFSR noise mode + only one parameter can be selected which is shown as below: \arg DAC_LFSR_BIT0: unmask the LFSR bit0 \arg DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0] \arg DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0] @@ -317,19 +381,21 @@ void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width) void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits) { if(DAC0 == dac_periph){ + /* configure DAC0 LFSR noise mode */ DAC_CTL &= ~DAC_CTL_DWBW0; DAC_CTL |= unmask_bits; }else{ + /* configure DAC1 LFSR noise mode */ DAC_CTL &= ~DAC_CTL_DWBW1; - DAC_CTL |= unmask_bits << 16; + DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET); } } /*! \brief configure DAC triangle noise mode - \param[in] dac_periph - \arg DACx(x=0,1) - \param[in] amplitude + \param[in] dac_periph: DACx(x = 0,1) + \param[in] amplitude: triangle amplitude in DAC triangle noise mode + only one parameter can be selected which is shown as below: \arg DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1 \arg DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3 \arg DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7 @@ -348,32 +414,16 @@ void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits) void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude) { if(DAC0 == dac_periph){ + /* configure DAC0 triangle noise mode */ DAC_CTL &= ~DAC_CTL_DWBW0; DAC_CTL |= amplitude; }else{ + /* configure DAC1 triangle noise mode */ DAC_CTL &= ~DAC_CTL_DWBW1; - DAC_CTL |= amplitude << 16; + DAC_CTL |= (amplitude << DAC1_REG_OFFSET); } } -/*! - \brief get DAC output value - \param[in] dac_periph - \arg DACx(x=0,1) - \param[out] none - \retval DAC output data -*/ -uint16_t dac_output_value_get(uint32_t dac_periph) -{ - uint16_t data = 0U; - if(DAC0 == dac_periph){ - data = (uint16_t)DAC0_DO; - }else{ - data = (uint16_t)DAC1_DO; - } - return data; -} - /*! \brief enable DAC concurrent mode \param[in] none @@ -410,7 +460,7 @@ void dac_concurrent_software_trigger_enable(void) { uint32_t swt = 0U; swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; - DAC_SWT |= (swt); + DAC_SWT |= (swt); } /*! @@ -452,6 +502,42 @@ void dac_concurrent_output_buffer_disable(void) DAC_CTL |= (ctl); } +/*! + \brief set DAC concurrent mode data holding register value + \param[in] dac_align: data alignment + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8b alignment + \arg DAC_ALIGN_12B_R: data right 12b alignment + \arg DAC_ALIGN_12B_L: data left 12b alignment + \param[in] data0: data to be loaded + \param[in] data1: data to be loaded + \param[out] none + \retval none +*/ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1) +{ + uint32_t data = 0U; + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0; + DACC_R8DH = data; + break; + default: + break; + } +} + /*! \brief enable DAC concurrent interrupt funcution \param[in] none @@ -479,97 +565,40 @@ void dac_concurrent_interrupt_disable(void) } /*! - \brief set the DAC specified data holding register value - \param[in] dac_periph - \arg DACx(x=0,1) - \param[in] dac_align - \arg DAC_ALIGN_8B_R: data right 8b alignment - \arg DAC_ALIGN_12B_R: data right 12b alignment - \arg DAC_ALIGN_12B_L: data left 12b alignment - \param[in] data: data to be loaded + \brief enable DAC interrupt(DAC DMA underrun interrupt) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ -void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) +void dac_interrupt_enable(uint32_t dac_periph) { if(DAC0 == dac_periph){ - switch(dac_align){ - /* data right 12b alignment */ - case DAC_ALIGN_12B_R: - DAC0_R12DH = data; - break; - /* data left 12b alignment */ - case DAC_ALIGN_12B_L: - DAC0_L12DH = data; - break; - /* data right 8b alignment */ - case DAC_ALIGN_8B_R: - DAC0_R8DH = data; - break; - default: - break; - } + DAC_CTL |= DAC_CTL_DDUDRIE0; }else{ - switch(dac_align){ - /* data right 12b alignment */ - case DAC_ALIGN_12B_R: - DAC1_R12DH = data; - break; - /* data left 12b alignment */ - case DAC_ALIGN_12B_L: - DAC1_L12DH = data; - break; - /* data right 8b alignment */ - case DAC_ALIGN_8B_R: - DAC1_R8DH = data; - break; - default: - break; - } + DAC_CTL |= DAC_CTL_DDUDRIE1; } } /*! - \brief set DAC concurrent mode data holding register value - \param[in] dac_align - \arg DAC_ALIGN_8B_R: data right 8b alignment - \arg DAC_ALIGN_12B_R: data right 12b alignment - \arg DAC_ALIGN_12B_L: data left 12b alignment - \param[in] data0: data to be loaded - \param[in] data1: data to be loaded + \brief disable DAC interrupt(DAC DMA underrun interrupt) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ -void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1) +void dac_interrupt_disable(uint32_t dac_periph) { - uint32_t data = 0U; - switch(dac_align){ - /* data right 12b alignment */ - case DAC_ALIGN_12B_R: - data = ((uint32_t)data1 << 16) | data0; - DACC_R12DH = data; - break; - /* data left 12b alignment */ - case DAC_ALIGN_12B_L: - data = ((uint32_t)data1 << 16) | data0; - DACC_L12DH = data; - break; - /* data right 8b alignment */ - case DAC_ALIGN_8B_R: - data = ((uint32_t)data1 << 8) | data0; - DACC_R8DH = data; - break; - default: - break; + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DDUDRIE0; + }else{ + DAC_CTL &= ~DAC_CTL_DDUDRIE1; } } /*! - \brief get the specified DAC flag(DAC DMA underrun flag) - \param[in] dac_periph - \arg DACx(x=0,1) + \brief get the specified DAC flag (DAC DMA underrun flag) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none - \retval the state of dac bit(SET or RESET) + \retval FlagStatus: SET or RESET */ FlagStatus dac_flag_get(uint32_t dac_periph) { @@ -589,9 +618,8 @@ FlagStatus dac_flag_get(uint32_t dac_periph) } /*! - \brief clear the specified DAC flag(DAC DMA underrun flag) - \param[in] dac_periph - \arg DACx(x=0,1) + \brief clear the specified DAC flag (DAC DMA underrun flag) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ @@ -605,16 +633,16 @@ void dac_flag_clear(uint32_t dac_periph) } /*! - \brief get the specified DAC interrupt flag(DAC DMA underrun interrupt flag) - \param[in] dac_periph - \arg DACx(x=0,1) + \brief get the specified DAC interrupt flag (DAC DMA underrun interrupt flag) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none - \retval the state of DAC interrupt flag(SET or RESET) + \retval FlagStatus: SET or RESET */ FlagStatus dac_interrupt_flag_get(uint32_t dac_periph) { FlagStatus temp_flag = RESET; uint32_t ddudr_flag = 0U, ddudrie_flag = 0U; + if(DAC0 == dac_periph){ /* check the DMA underrun flag and DAC DMA underrun interrupt enable flag */ ddudr_flag = DAC_STAT & DAC_STAT_DDUDR0; @@ -634,9 +662,8 @@ FlagStatus dac_interrupt_flag_get(uint32_t dac_periph) } /*! - \brief clear the specified DAC interrupt flag(DAC DMA underrun interrupt flag) - \param[in] dac_periph - \arg DACx(x=0,1) + \brief clear the specified DAC interrupt flag (DAC DMA underrun interrupt flag) + \param[in] dac_periph: DACx(x = 0,1) \param[out] none \retval none */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c index a017c7e3e5..a408136ea4 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c @@ -1,16 +1,55 @@ /*! - \file gd32f4xx_dbg.c - \brief DBG driver + \file gd32f4xx_dbg.c + \brief DBG driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_dbg.h" +#define DBG_RESET_VAL 0x00000000U + +/*! + \brief deinitialize the DBG + \param[in] none + \param[out] none + \retval none +*/ +void dbg_deinit(void) +{ + DBG_CTL0 = DBG_RESET_VAL; + DBG_CTL1 = DBG_RESET_VAL; +} + /*! \brief read DBG_ID code register \param[in] none @@ -55,32 +94,69 @@ void dbg_low_power_disable(uint32_t dbg_low_power) /*! \brief enable peripheral behavior when the mcu is in debug mode \param[in] dbg_periph: dbg_periph_enum - \param[out] none + only one parameter can be selected which is shown as below: + \arg DBG_TIMER1_HOLD: hold TIMER1 counter when core is halted + \arg DBG_TIMER2_HOLD: hold TIMER2 counter when core is halted + \arg DBG_TIMER3_HOLD: hold TIMER3 counter when core is halted + \arg DBG_TIMER4_HOLD: hold TIMER4 counter when core is halted + \arg DBG_TIMER5_HOLD: hold TIMER5 counter when core is halted + \arg DBG_TIMER6_HOLD: hold TIMER6 counter when core is halted + \arg DBG_TIMER11_HOLD: hold TIMER11 counter when core is halted + \arg DBG_TIMER12_HOLD: hold TIMER12 counter when core is halted + \arg DBG_TIMER13_HOLD: hold TIMER13 counter when core is halted + \arg DBG_RTC_HOLD: hold RTC calendar and wakeup counter when core is halted + \arg DBG_WWDGT_HOLD: debug WWDGT kept when core is halted + \arg DBG_FWDGT_HOLD: debug FWDGT kept when core is halted + \arg DBG_I2C0_HOLD: hold I2C0 smbus when core is halted + \arg DBG_I2C1_HOLD: hold I2C1 smbus when core is halted + \arg DBG_I2C2_HOLD: hold I2C2 smbus when core is halted + \arg DBG_CAN0_HOLD: debug CAN0 kept when core is halted + \arg DBG_CAN1_HOLD: debug CAN1 kept when core is halted + \arg DBG_TIMER0_HOLD: hold TIMER0 counter when core is halted + \arg DBG_TIMER7_HOLD: hold TIMER7 counter when core is halted + \arg DBG_TIMER8_HOLD: hold TIMER8 counter when core is halted + \arg DBG_TIMER9_HOLD: hold TIMER9 counter when core is halted + \arg DBG_TIMER10_HOLD: hold TIMER10 counter when core is halted + \arg \param[out] none \retval none */ void dbg_periph_enable(dbg_periph_enum dbg_periph) { - if(RESET == ((uint32_t)dbg_periph & BIT(30))){ - DBG_CTL1 |= (uint32_t)dbg_periph; - }else{ - DBG_CTL2 |= ((uint32_t)dbg_periph & (~BIT(30))); - } - + DBG_REG_VAL(dbg_periph) |= BIT(DBG_BIT_POS(dbg_periph)); } /*! \brief disable peripheral behavior when the mcu is in debug mode \param[in] dbg_periph: dbg_periph_enum + only one parameter can be selected which is shown as below: + \arg DBG_TIMER1_HOLD: hold TIMER1 counter when core is halted + \arg DBG_TIMER2_HOLD: hold TIMER2 counter when core is halted + \arg DBG_TIMER3_HOLD: hold TIMER3 counter when core is halted + \arg DBG_TIMER4_HOLD: hold TIMER4 counter when core is halted + \arg DBG_TIMER5_HOLD: hold TIMER5 counter when core is halted + \arg DBG_TIMER6_HOLD: hold TIMER6 counter when core is halted + \arg DBG_TIMER11_HOLD: hold TIMER11 counter when core is halted + \arg DBG_TIMER12_HOLD: hold TIMER12 counter when core is halted + \arg DBG_TIMER13_HOLD: hold TIMER13 counter when core is halted + \arg DBG_RTC_HOLD: hold RTC calendar and wakeup counter when core is halted + \arg DBG_WWDGT_HOLD: debug WWDGT kept when core is halted + \arg DBG_FWDGT_HOLD: debug FWDGT kept when core is halted + \arg DBG_I2C0_HOLD: hold I2C0 smbus when core is halted + \arg DBG_I2C1_HOLD: hold I2C1 smbus when core is halted + \arg DBG_I2C2_HOLD: hold I2C2 smbus when core is halted + \arg DBG_CAN0_HOLD: debug CAN0 kept when core is halted + \arg DBG_CAN1_HOLD: debug CAN1 kept when core is halted + \arg DBG_TIMER0_HOLD: hold TIMER0 counter when core is halted + \arg DBG_TIMER7_HOLD: hold TIMER7 counter when core is halted + \arg DBG_TIMER8_HOLD: hold TIMER8 counter when core is halted + \arg DBG_TIMER9_HOLD: hold TIMER9 counter when core is halted + \arg DBG_TIMER10_HOLD: hold TIMER10 counter when core is halted \param[out] none \retval none */ void dbg_periph_disable(dbg_periph_enum dbg_periph) { - if(RESET == ((uint32_t)dbg_periph & BIT(30))){ - DBG_CTL1 &= ~(uint32_t)dbg_periph; - }else{ - DBG_CTL2 &= ~((uint32_t)dbg_periph & (~BIT(30))); - } + DBG_REG_VAL(dbg_periph) &= ~BIT(DBG_BIT_POS(dbg_periph)); } /*! @@ -106,9 +182,9 @@ void dbg_trace_pin_disable(void) } /*! - \brief trace pin mode selection + \brief trace pin mode selection \param[in] trace_mode: - \arg TRACE_MODE_ASYNC: trace pin used for async mode + \arg TRACE_MODE_ASYNC: trace pin used for async mode \arg TRACE_MODE_SYNC_DATASIZE_1: trace pin used for sync mode and data size is 1 \arg TRACE_MODE_SYNC_DATASIZE_2: trace pin used for sync mode and data size is 2 \arg TRACE_MODE_SYNC_DATASIZE_4: trace pin used for sync mode and data size is 4 diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c index 2984ff11f7..a1ddcab384 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_dci.c - \brief DCI driver + \file gd32f4xx_dci.c + \brief DCI driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_dci.h" @@ -25,11 +50,11 @@ void dci_deinit(void) /*! \brief initialize DCI registers - \param[in] dci_struct: DCI parameter initialization stuct + \param[in] dci_struct: DCI parameter initialization structure members of the structure and the member values are shown as below: capture_mode : DCI_CAPTURE_MODE_CONTINUOUS, DCI_CAPTURE_MODE_SNAPSHOT colck_polarity : DCI_CK_POLARITY_FALLING, DCI_CK_POLARITY_RISING - hsync_polarity : DCI_HSYNC_POLARITY_LOW, DCI_HSYNC_POLARITY_HIGH + hsync_polarity : DCI_HSYNC_POLARITY_LOW, DCI_HSYNC_POLARITY_HIGH vsync_polarity : DCI_VSYNC_POLARITY_LOW, DCI_VSYNC_POLARITY_HIGH frame_rate : DCI_FRAME_RATE_ALL, DCI_FRAME_RATE_1_2, DCI_FRAME_RATE_1_4 interface_format: DCI_INTERFACE_FORMAT_8BITS, DCI_INTERFACE_FORMAT_10BITS, @@ -39,10 +64,10 @@ void dci_deinit(void) */ void dci_init(dci_parameter_struct* dci_struct) { - uint32_t reg =0U; + uint32_t reg = 0U; /* disable capture function and DCI */ DCI_CTL &= ~(DCI_CTL_CAP | DCI_CTL_DCIEN); - /* config DCI parameter */ + /* configure DCI parameter */ reg |= dci_struct->capture_mode; reg |= dci_struct->clock_polarity; reg |= dci_struct->hsync_polarity; @@ -54,18 +79,18 @@ void dci_init(dci_parameter_struct* dci_struct) } /*! - \brief enable DCI function + \brief enable DCI function \param[in] none \param[out] none \retval none */ void dci_enable(void) { - DCI_CTL |= DCI_CTL_DCIEN; + DCI_CTL |= DCI_CTL_DCIEN; } /*! - \brief disable DCI function + \brief disable DCI function \param[in] none \param[out] none \retval none @@ -76,7 +101,7 @@ void dci_disable(void) } /*! - \brief enable DCI capture + \brief enable DCI capture \param[in] none \param[out] none \retval none @@ -87,7 +112,7 @@ void dci_capture_enable(void) } /*! - \brief disable DCI capture + \brief disable DCI capture \param[in] none \param[out] none \retval none @@ -98,7 +123,7 @@ void dci_capture_disable(void) } /*! - \brief enable DCI jpeg mode + \brief enable DCI jpeg mode \param[in] none \param[out] none \retval none @@ -109,7 +134,7 @@ void dci_jpeg_enable(void) } /*! - \brief disable DCI jpeg mode + \brief disable DCI jpeg mode \param[in] none \param[out] none \retval none @@ -142,11 +167,11 @@ void dci_crop_window_disable(void) } /*! - \brief config DCI cropping window + \brief configure DCI cropping window \param[in] start_x: window horizontal start position \param[in] start_y: window vertical start position - \param[in] size_height: window horizontal size - \param[in] size_width: window vertical size + \param[in] size_width: window horizontal size + \param[in] size_height: window vertical size \param[out] none \retval none */ @@ -157,28 +182,28 @@ void dci_crop_window_config(uint16_t start_x, uint16_t start_y, uint16_t size_wi } /*! - \brief enable sync codes function + \brief enable embedded synchronous mode \param[in] none \param[out] none \retval none */ -void dci_sync_codes_enable(void) +void dci_embedded_sync_enable(void) { DCI_CTL |= DCI_CTL_ESM; } /*! - \brief disable sync codes function + \brief disble embedded synchronous mode \param[in] none \param[out] none \retval none */ -void dci_sync_codes_disable(void) +void dci_embedded_sync_disable(void) { DCI_CTL &= ~DCI_CTL_ESM; } /*! - \brief config sync codes + \brief config synchronous codes in embedded synchronous mode \param[in] frame_start: frame start code in embedded synchronous mode \param[in] line_start: line start code in embedded synchronous mode \param[in] line_end: line end code in embedded synchronous mode @@ -192,7 +217,7 @@ void dci_sync_codes_config(uint8_t frame_start, uint8_t line_start, uint8_t line } /*! - \brief config sync codes unmask + \brief config synchronous codes unmask in embedded synchronous mode \param[in] frame_start: frame start code unmask bits in embedded synchronous mode \param[in] line_start: line start code unmask bits in embedded synchronous mode \param[in] line_end: line end code unmask bits in embedded synchronous mode @@ -202,7 +227,7 @@ void dci_sync_codes_config(uint8_t frame_start, uint8_t line_start, uint8_t line */ void dci_sync_codes_unmask_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end) { - DCI_SCUMSK = ((uint32_t)frame_start | ((uint32_t)line_start<<8) | ((uint32_t)line_end<<16) | ((uint32_t)frame_end<<24)); + DCI_SCUMSK = ((uint32_t)frame_start | ((uint32_t)line_start<<8) | ((uint32_t)line_end<<16) | ((uint32_t)frame_end<<24)); } /*! @@ -216,13 +241,46 @@ uint32_t dci_data_read(void) return DCI_DATA; } +/*! + \brief get specified flag + \param[in] flag: + \arg DCI_FLAG_HS: HS line status + \arg DCI_FLAG_VS: VS line status + \arg DCI_FLAG_FV:FIFO valid + \arg DCI_FLAG_EF: end of frame flag + \arg DCI_FLAG_OVR: FIFO overrun flag + \arg DCI_FLAG_ESE: embedded synchronous error flag + \arg DCI_FLAG_VSYNC: vsync flag + \arg DCI_FLAG_EL: end of line flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dci_flag_get(uint32_t flag) +{ + uint32_t stat = 0U; + + if(flag >> 31){ + /* get flag status from DCI_STAT1 register */ + stat = DCI_STAT1; + }else{ + /* get flag status from DCI_STAT0 register */ + stat = DCI_STAT0; + } + + if(flag & stat){ + return SET; + }else{ + return RESET; + } +} + /*! \brief enable specified DCI interrupt \param[in] interrupt: \arg DCI_INT_EF: end of frame interrupt \arg DCI_INT_OVR: FIFO overrun interrupt - \arg DCI_INT_ESE: embedded synchronous error interrupt - \arg DCI_INT_VS: vsync interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_VSYNC: vsync interrupt \arg DCI_INT_EL: end of line interrupt \param[out] none \retval none @@ -237,8 +295,8 @@ void dci_interrupt_enable(uint32_t interrupt) \param[in] interrupt: \arg DCI_INT_EF: end of frame interrupt \arg DCI_INT_OVR: FIFO overrun interrupt - \arg DCI_INT_ESE: embedded synchronous error interrupt - \arg DCI_INT_VS: vsync interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_VSYNC: vsync interrupt \arg DCI_INT_EL: end of line interrupt \param[out] none \retval none @@ -249,93 +307,39 @@ void dci_interrupt_disable(uint32_t interrupt) } /*! - \brief clear specified interrupt - \param[in] interrupt: + \brief clear specified interrupt flag + \param[in] int_flag: \arg DCI_INT_EF: end of frame interrupt \arg DCI_INT_OVR: FIFO overrun interrupt - \arg DCI_INT_ESE: embedded synchronous error interrupt - \arg DCI_INT_VS: vsync interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_VSYNC: vsync interrupt \arg DCI_INT_EL: end of line interrupt \param[out] none \retval none */ -void dci_interrupt_clear(uint32_t interrupt) +void dci_interrupt_flag_clear(uint32_t int_flag) { - DCI_INTC |= interrupt; -} - -/*! - \brief get specified flag - \param[in] flag: - \arg DCI_FLAG_HS: HS line status - \arg DCI_FLAG_VS: VS line status - \arg DCI_FLAG_FV:FIFO valid - \arg DCI_FLAG_EFF: end of frame flag - \arg DCI_FLAG_OVRF: FIFO overrun flag - \arg DCI_FLAG_ESEF: embedded synchronous error flag - \arg DCI_FLAG_VSF: vsync flag - \arg DCI_FLAG_ELF: end of line flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus dci_flag_get(uint32_t flag) -{ - uint32_t ret = 0U; - - switch(flag){ - /* get flag status from DCI_STAT0 register */ - case DCI_FLAG_HS: - ret = (DCI_STAT0 & DCI_STAT0_HS); - break; - case DCI_FLAG_VS: - ret = (DCI_STAT0 & DCI_STAT0_VS); - break; - case DCI_FLAG_FV: - ret = (DCI_STAT0 & DCI_STAT0_FV); - break; - /* get flag status from DCI_STAT1 register */ - case DCI_FLAG_EFF: - ret = (DCI_STAT1 & DCI_STAT1_EFF); - break; - case DCI_FLAG_OVRF: - ret = (DCI_STAT1 & DCI_STAT1_OVRF); - break; - case DCI_FLAG_ESEF: - ret = (DCI_STAT1 & DCI_STAT1_ESEF); - break; - case DCI_FLAG_VSF: - ret = (DCI_STAT1 & DCI_STAT1_VSF); - break; - case DCI_FLAG_ELF: - ret = (DCI_STAT1 & DCI_STAT1_ELF); - break; - default : - break; - } - - if(RESET == ret){ - return RESET; - }else{ - return SET; - } + DCI_INTC |= int_flag; } /*! \brief get specified interrupt flag - \param[in] interrupt: - \arg DCI_INT_EF: end of frame interrupt - \arg DCI_INT_OVR: FIFO overrun interrupt - \arg DCI_INT_ESE: embedded synchronous error interrupt - \arg DCI_INT_VS: vsync interrupt - \arg DCI_INT_EL: end of line interrupt + \param[in] int_flag: + \arg DCI_INT_FLAG_EF: end of frame interrupt flag + \arg DCI_INT_FLAG_OVR: FIFO overrun interrupt flag + \arg DCI_INT_FLAG_ESE: embedded synchronous error interrupt flag + \arg DCI_INT_FLAG_VSYNC: vsync interrupt flag + \arg DCI_INT_FLAG_EL: end of line interrupt flag \param[out] none \retval FlagStatus: SET or RESET */ -FlagStatus dci_interrupt_flag_get(uint32_t interrupt) +FlagStatus dci_interrupt_flag_get(uint32_t int_flag) { - if(RESET == (DCI_INTF & interrupt)){ + if(RESET == (DCI_INTF & int_flag)){ return RESET; }else{ return SET; } } + + diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c index c7f5ce9a70..d8bd7be2d7 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c @@ -1,14 +1,40 @@ /*! - \file gd32f4xx_dma.c - \brief DMA driver + \file gd32f4xx_dma.c + \brief DMA driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ + #include "gd32f4xx_dma.h" /* DMA register bit offset */ @@ -23,7 +49,7 @@ \param[out] none \retval none */ -void dma_deinit(uint32_t dma_periph,dma_channel_enum channelx) +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx) { /* disable DMA a channel */ DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CHEN; @@ -37,10 +63,54 @@ void dma_deinit(uint32_t dma_periph,dma_channel_enum channelx) if(channelx < DMA_CH4){ DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE,channelx); }else{ + channelx -= (dma_channel_enum)4; DMA_INTC1(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE,channelx); } } +/*! + \brief initialize the DMA single data mode parameters struct with the default values + \param[in] init_struct: the initialization data needed to initialize DMA channel + \param[out] none + \retval none +*/ +void dma_single_data_para_struct_init(dma_single_data_parameter_struct* init_struct) +{ + /* set the DMA struct with the default values */ + init_struct->periph_addr = 0U; + init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE; + init_struct->memory0_addr = 0U; + init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE; + init_struct->periph_memory_width = 0U; + init_struct->circular_mode = DMA_CIRCULAR_MODE_DISABLE; + init_struct->direction = DMA_PERIPH_TO_MEMORY; + init_struct->number = 0U; + init_struct->priority = DMA_PRIORITY_LOW; +} + +/*! + \brief initialize the DMA multi data mode parameters struct with the default values + \param[in] init_struct: the initialization data needed to initialize DMA channel + \param[out] none + \retval none +*/ +void dma_multi_data_para_struct_init(dma_multi_data_parameter_struct* init_struct) +{ + /* set the DMA struct with the default values */ + init_struct->periph_addr = 0U; + init_struct->periph_width = 0U; + init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE; + init_struct->memory0_addr = 0U; + init_struct->memory_width = 0U; + init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE; + init_struct->memory_burst_width = 0U; + init_struct->periph_burst_width = 0U; + init_struct->circular_mode = DMA_CIRCULAR_MODE_DISABLE; + init_struct->direction = DMA_PERIPH_TO_MEMORY; + init_struct->number = 0U; + init_struct->priority = DMA_PRIORITY_LOW; +} + /*! \brief initialize DMA single data mode \param[in] dma_periph: DMAx(x=0,1) @@ -49,57 +119,57 @@ void dma_deinit(uint32_t dma_periph,dma_channel_enum channelx) \arg DMA_CHx(x=0..7) \param[in] init_struct: the data needed to initialize DMA single data mode periph_addr: peripheral base address - periph_memory_width: DMA_PERIPH_WIDTH_8BIT,DMA_PERIPH_WIDTH_16BIT,DMA_PERIPH_WIDTH_32BIT - periph_inc: DMA_PERIPH_INCREASE_ENABLE,DMA_PERIPH_INCREASE_DISABLE,DMA_PERIPH_INCREASE_FIX + periph_inc: DMA_PERIPH_INCREASE_ENABLE,DMA_PERIPH_INCREASE_DISABLE,DMA_PERIPH_INCREASE_FIX memory0_addr: memory base address memory_inc: DMA_MEMORY_INCREASE_ENABLE,DMA_MEMORY_INCREASE_DISABLE + periph_memory_width: DMA_PERIPH_WIDTH_8BIT,DMA_PERIPH_WIDTH_16BIT,DMA_PERIPH_WIDTH_32BIT + circular_mode: DMA_CIRCULAR_MODE_ENABLE,DMA_CIRCULAR_MODE_DISABLE direction: DMA_PERIPH_TO_MEMORY,DMA_MEMORY_TO_PERIPH,DMA_MEMORY_TO_MEMORY number: the number of remaining data to be transferred by the DMA priority: DMA_PRIORITY_LOW,DMA_PRIORITY_MEDIUM,DMA_PRIORITY_HIGH,DMA_PRIORITY_ULTRA_HIGH - circular_mode: DMA_CIRCULAR_MODE_ENABLE,DMA_CIRCULAR_MODE_DISABLE \param[out] none \retval none */ -void dma_single_data_mode_init(uint32_t dma_periph,dma_channel_enum channelx,dma_single_data_parameter_struct init_struct) +void dma_single_data_mode_init(uint32_t dma_periph, dma_channel_enum channelx, dma_single_data_parameter_struct* init_struct) { uint32_t ctl; - + /* select single data mode */ DMA_CHFCTL(dma_periph,channelx) &= ~DMA_CHXFCTL_MDMEN; - + /* configure peripheral base address */ - DMA_CHPADDR(dma_periph,channelx) = init_struct.periph_addr; - + DMA_CHPADDR(dma_periph,channelx) = init_struct->periph_addr; + /* configure memory base address */ - DMA_CHM0ADDR(dma_periph,channelx) = init_struct.memory0_addr; - + DMA_CHM0ADDR(dma_periph,channelx) = init_struct->memory0_addr; + /* configure the number of remaining data to be transferred */ - DMA_CHCNT(dma_periph,channelx) = init_struct.number; - + DMA_CHCNT(dma_periph,channelx) = init_struct->number; + /* configure peripheral and memory transfer width,channel priotity,transfer mode */ ctl = DMA_CHCTL(dma_periph,channelx); ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO | DMA_CHXCTL_TM); - ctl |= (init_struct.periph_memory_width | (init_struct.periph_memory_width << 2) | init_struct.priority | init_struct.direction); + ctl |= (init_struct->periph_memory_width | (init_struct->periph_memory_width << 2) | init_struct->priority | init_struct->direction); DMA_CHCTL(dma_periph,channelx) = ctl; /* configure peripheral increasing mode */ - if(DMA_PERIPH_INCREASE_ENABLE == init_struct.periph_inc){ + if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){ DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PNAGA; - }else if(DMA_PERIPH_INCREASE_DISABLE == init_struct.periph_inc){ + }else if(DMA_PERIPH_INCREASE_DISABLE == init_struct->periph_inc){ DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_PNAGA; }else{ DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PAIF; } /* configure memory increasing mode */ - if(DMA_MEMORY_INCREASE_ENABLE == init_struct.memory_inc){ + if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){ DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_MNAGA; }else{ DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_MNAGA; } /* configure DMA circular mode */ - if(DMA_CIRCULAR_MODE_ENABLE == init_struct.circular_mode){ + if(DMA_CIRCULAR_MODE_ENABLE == init_struct->circular_mode){ DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_CMEN; }else{ DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CMEN; @@ -115,60 +185,60 @@ void dma_single_data_mode_init(uint32_t dma_periph,dma_channel_enum channelx,dma \param[in] dma_multi_data_parameter_struct: the data needed to initialize DMA multi data mode periph_addr: peripheral base address periph_width: DMA_PERIPH_WIDTH_8BIT,DMA_PERIPH_WIDTH_16BIT,DMA_PERIPH_WIDTH_32BIT - periph_inc: DMA_PERIPH_INCREASE_ENABLE,DMA_PERIPH_INCREASE_DISABLE,DMA_PERIPH_INCREASE_FIX + periph_inc: DMA_PERIPH_INCREASE_ENABLE,DMA_PERIPH_INCREASE_DISABLE,DMA_PERIPH_INCREASE_FIX memory0_addr: memory0 base address memory_width: DMA_MEMORY_WIDTH_8BIT,DMA_MEMORY_WIDTH_16BIT,DMA_MEMORY_WIDTH_32BIT memory_inc: DMA_MEMORY_INCREASE_ENABLE,DMA_MEMORY_INCREASE_DISABLE - direction: DMA_PERIPH_TO_MEMORY,DMA_MEMORY_TO_PERIPH,DMA_MEMORY_TO_MEMORY - number: the number of remaining data to be transferred by the DMA - priority: DMA_PRIORITY_LOW,DMA_PRIORITY_MEDIUM,DMA_PRIORITY_HIGH,DMA_PRIORITY_ULTRA_HIGH - circular_mode: DMA_CIRCULAR_MODE_ENABLE,DMA_CIRCULAR_MODE_DISABLE memory_burst_width: DMA_MEMORY_BURST_SINGLE,DMA_MEMORY_BURST_4_BEAT,DMA_MEMORY_BURST_8_BEAT,DMA_MEMORY_BURST_16_BEAT periph_burst_width: DMA_PERIPH_BURST_SINGLE,DMA_PERIPH_BURST_4_BEAT,DMA_PERIPH_BURST_8_BEAT,DMA_PERIPH_BURST_16_BEAT critical_value: DMA_FIFO_1_WORD,DMA_FIFO_2_WORD,DMA_FIFO_3_WORD,DMA_FIFO_4_WORD + circular_mode: DMA_CIRCULAR_MODE_ENABLE,DMA_CIRCULAR_MODE_DISABLE + direction: DMA_PERIPH_TO_MEMORY,DMA_MEMORY_TO_PERIPH,DMA_MEMORY_TO_MEMORY + number: the number of remaining data to be transferred by the DMA + priority: DMA_PRIORITY_LOW,DMA_PRIORITY_MEDIUM,DMA_PRIORITY_HIGH,DMA_PRIORITY_ULTRA_HIGH \param[out] none \retval none */ -void dma_multi_data_mode_init(uint32_t dma_periph,dma_channel_enum channelx,dma_multi_data_parameter_struct init_struct) +void dma_multi_data_mode_init(uint32_t dma_periph, dma_channel_enum channelx, dma_multi_data_parameter_struct* init_struct) { uint32_t ctl; - + /* select multi data mode and configure FIFO critical value */ - DMA_CHFCTL(dma_periph,channelx) |= (DMA_CHXFCTL_MDMEN | init_struct.critical_value); - + DMA_CHFCTL(dma_periph,channelx) |= (DMA_CHXFCTL_MDMEN | init_struct->critical_value); + /* configure peripheral base address */ - DMA_CHPADDR(dma_periph,channelx) = init_struct.periph_addr; - + DMA_CHPADDR(dma_periph,channelx) = init_struct->periph_addr; + /* configure memory base address */ - DMA_CHM0ADDR(dma_periph,channelx) = init_struct.memory0_addr; - + DMA_CHM0ADDR(dma_periph,channelx) = init_struct->memory0_addr; + /* configure the number of remaining data to be transferred */ - DMA_CHCNT(dma_periph,channelx) = init_struct.number; - + DMA_CHCNT(dma_periph,channelx) = init_struct->number; + /* configure peripheral and memory transfer width,channel priotity,transfer mode,peripheral and memory burst transfer width */ ctl = DMA_CHCTL(dma_periph,channelx); ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO | DMA_CHXCTL_TM | DMA_CHXCTL_PBURST | DMA_CHXCTL_MBURST); - ctl |= (init_struct.periph_width | (init_struct.memory_width ) | init_struct.priority | init_struct.direction | init_struct.memory_burst_width | init_struct.periph_burst_width); + ctl |= (init_struct->periph_width | (init_struct->memory_width ) | init_struct->priority | init_struct->direction | init_struct->memory_burst_width | init_struct->periph_burst_width); DMA_CHCTL(dma_periph,channelx) = ctl; /* configure peripheral increasing mode */ - if(DMA_PERIPH_INCREASE_ENABLE == init_struct.periph_inc){ + if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){ DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PNAGA; - }else if(DMA_PERIPH_INCREASE_DISABLE == init_struct.periph_inc){ + }else if(DMA_PERIPH_INCREASE_DISABLE == init_struct->periph_inc){ DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_PNAGA; }else{ DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PAIF; } /* configure memory increasing mode */ - if(DMA_MEMORY_INCREASE_ENABLE == init_struct.memory_inc){ + if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){ DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_MNAGA; }else{ DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_MNAGA; } /* configure DMA circular mode */ - if(DMA_CIRCULAR_MODE_ENABLE == init_struct.circular_mode){ + if(DMA_CIRCULAR_MODE_ENABLE == init_struct->circular_mode){ DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_CMEN; }else{ DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CMEN; @@ -176,21 +246,464 @@ void dma_multi_data_mode_init(uint32_t dma_periph,dma_channel_enum channelx,dma_ } /*! - \brief get DMA flag is set or not + \brief set DMA peripheral base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set peripheral base address + \arg DMA_CHx(x=0..7) + \param[in] address: peripheral base address + \param[out] none + \retval none +*/ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + DMA_CHPADDR(dma_periph,channelx) = address; +} + +/*! + \brief set DMA Memory0 base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set Memory base address + \arg DMA_CHx(x=0..7) + \param[in] memory_flag: DMA_MEMORY_x(x=0,1) + \param[in] address: Memory base address + \param[out] none + \retval none +*/ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t memory_flag, uint32_t address) +{ + if(memory_flag){ + DMA_CHM1ADDR(dma_periph,channelx) = address; + }else{ + DMA_CHM0ADDR(dma_periph,channelx) = address; + } +} + +/*! + \brief set the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + \arg DMA_CHx(x=0..7) + \param[in] number: the number of remaining data to be transferred by the DMA + \param[out] none + \retval none +*/ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number) +{ + DMA_CHCNT(dma_periph,channelx) = number; +} + +/*! + \brief get the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + \arg DMA_CHx(x=0..7) + \param[out] none + \retval uint32_t: the number of remaining data to be transferred by the DMA +*/ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) +{ + return (uint32_t)DMA_CHCNT(dma_periph,channelx); +} + +/*! + \brief configure priority level of DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] priority: priority Level of this channel + only one parameter can be selected which is shown as below: + \arg DMA_PRIORITY_LOW: low priority + \arg DMA_PRIORITY_MEDIUM: medium priority + \arg DMA_PRIORITY_HIGH: high priority + \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority + \param[out] none + \retval none +*/ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority) +{ + uint32_t ctl; + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph,channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PRIO; + ctl |= priority; + DMA_CHCTL(dma_periph,channelx) = ctl; +} + +/*! + \brief configure transfer burst beats of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] mbeat: transfer burst beats + \arg DMA_MEMORY_BURST_SINGLE: memory transfer single burst + \arg DMA_MEMORY_BURST_4_BEAT: memory transfer 4-beat burst + \arg DMA_MEMORY_BURST_8_BEAT: memory transfer 8-beat burst + \arg DMA_MEMORY_BURST_16_BEAT: memory transfer 16-beat burst + \param[out] none + \retval none +*/ +void dma_memory_burst_beats_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t mbeat) +{ + uint32_t ctl; + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph,channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_MBURST; + ctl |= mbeat; + DMA_CHCTL(dma_periph,channelx) = ctl; +} + +/*! + \brief configure transfer burst beats of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] pbeat: transfer burst beats + only one parameter can be selected which is shown as below: + \arg DMA_PERIPH_BURST_SINGLE: peripheral transfer single burst + \arg DMA_PERIPH_BURST_4_BEAT: peripheral transfer 4-beat burst + \arg DMA_PERIPH_BURST_8_BEAT: peripheral transfer 8-beat burst + \arg DMA_PERIPH_BURST_16_BEAT: peripheral transfer 16-beat burst + \param[out] none + \retval none +*/ +void dma_periph_burst_beats_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t pbeat) +{ + uint32_t ctl; + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph,channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PBURST; + ctl |= pbeat; + DMA_CHCTL(dma_periph,channelx) = ctl; +} + +/*! + \brief configure transfer data size of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] msize: transfer data size of memory + only one parameter can be selected which is shown as below: + \arg DMA_MEMORY_WIDTH_8BIT: transfer data size of memory is 8-bit + \arg DMA_MEMORY_WIDTH_16BIT: transfer data size of memory is 16-bit + \arg DMA_MEMORY_WIDTH_32BIT: transfer data size of memory is 32-bit + \param[out] none + \retval none +*/ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t msize) +{ + uint32_t ctl; + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph,channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_MWIDTH; + ctl |= msize; + DMA_CHCTL(dma_periph,channelx) = ctl; +} + +/*! + \brief configure transfer data size of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] msize: transfer data size of peripheral + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data size of peripheral is 8-bit + \arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data size of peripheral is 16-bit + \arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data size of peripheral is 32-bit + \param[out] none + \retval none +*/ +void dma_periph_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t psize) +{ + uint32_t ctl; + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph,channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PWIDTH; + ctl |= psize; + DMA_CHCTL(dma_periph,channelx) = ctl; +} + +/*! + \brief configure memory address generation generation_algorithm + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] generation_algorithm: the address generation algorithm + only one parameter can be selected which is shown as below: + \arg DMA_MEMORY_INCREASE_ENABLE: next address of memory is increasing address mode + \arg DMA_MEMORY_INCREASE_DISABLE: next address of memory is fixed address mode + \param[out] none + \retval none +*/ +void dma_memory_address_generation_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t generation_algorithm) +{ + if(DMA_MEMORY_INCREASE_ENABLE == generation_algorithm){ + DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_MNAGA; + }else{ + DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_MNAGA; + } +} + +/*! + \brief configure peripheral address generation_algorithm + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] generation_algorithm: the address generation algorithm + only one parameter can be selected which is shown as below: + \arg DMA_PERIPH_INCREASE_ENABLE: next address of peripheral is increasing address mode + \arg DMA_PERIPH_INCREASE_DISABLE: next address of peripheral is fixed address mode + \arg DMA_PERIPH_INCREASE_FIX: increasing steps of peripheral address is fixed + \param[out] none + \retval none +*/ +void dma_peripheral_address_generation_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t generation_algorithm) +{ + if(DMA_PERIPH_INCREASE_ENABLE == generation_algorithm){ + DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PNAGA; + }else if(DMA_PERIPH_INCREASE_DISABLE == generation_algorithm){ + DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_PNAGA; + }else{ + DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PNAGA; + DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PAIF; + } +} + +/*! + \brief enable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[out] none + \retval none +*/ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_CMEN; +} + +/*! + \brief disable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[out] none + \retval none +*/ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CMEN; +} + +/*! + \brief enable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[out] none + \retval none +*/ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_CHEN; +} + +/*! + \brief disable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[out] none + \retval none +*/ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CHEN; +} + +/*! + \brief configure the direction of data transfer on the channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] direction: specify the direction of data transfer + only one parameter can be selected which is shown as below: + \arg DMA_PERIPH_TO_MEMORY: read from peripheral and write to memory + \arg DMA_MEMORY_TO_PERIPH: read from memory and write to peripheral + \arg DMA_MEMORY_TO_MEMORY: read from memory and write to memory + \param[out] none + \retval none +*/ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction) +{ + uint32_t ctl; + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph,channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_TM; + ctl |= direction; + + DMA_CHCTL(dma_periph,channelx) = ctl; +} + +/*! + \brief DMA switch buffer mode config + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] memory1_addr: memory1 base address + \param[in] memory_select: DMA_MEMORY_0 or DMA_MEMORY_1 + \param[out] none + \retval none +*/ +void dma_switch_buffer_mode_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t memory1_addr, uint32_t memory_select) +{ + /* configure memory1 base address */ + DMA_CHM1ADDR(dma_periph,channelx) = memory1_addr; + + if(DMA_MEMORY_0 == memory_select){ + DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_MBS; + }else{ + DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_MBS; + } +} + +/*! + \brief DMA using memory get + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[out] none + \retval the using memory +*/ +uint32_t dma_using_memory_get(uint32_t dma_periph, dma_channel_enum channelx) +{ + if((DMA_CHCTL(dma_periph,channelx)) & DMA_CHXCTL_MBS){ + return DMA_MEMORY_1; + }else{ + return DMA_MEMORY_0; + } +} + +/*! + \brief DMA channel peripheral select + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] sub_periph: specify DMA channel peripheral + \arg DMA_SUBPERIx(x=0..7) + \param[out] none + \retval none +*/ +void dma_channel_subperipheral_select(uint32_t dma_periph, dma_channel_enum channelx, dma_subperipheral_enum sub_periph) +{ + uint32_t ctl; + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph,channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PERIEN; + ctl |= ((uint32_t)sub_periph << CHXCTL_PERIEN_OFFSET); + + DMA_CHCTL(dma_periph,channelx) = ctl; +} + +/*! + \brief DMA flow controller configure + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] controller: specify DMA flow controler + only one parameter can be selected which is shown as below: + \arg DMA_FLOW_CONTROLLER_DMA: DMA is the flow controller + \arg DMA_FLOW_CONTROLLER_PERI: peripheral is the flow controller + \param[out] none + \retval none +*/ +void dma_flow_controller_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t controller) +{ + if(DMA_FLOW_CONTROLLER_DMA == controller){ + DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_TFCS; + }else{ + DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_TFCS; + } +} + +/*! + \brief DMA switch buffer mode enable + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void dma_switch_buffer_mode_enable(uint32_t dma_periph, dma_channel_enum channelx, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + /* switch buffer mode enable */ + DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_SBMEN; + }else{ + /* switch buffer mode disable */ + DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_SBMEN; + } +} + +/*! + \brief DMA FIFO status get + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + \arg DMA_CHx(x=0..7) + \param[out] none + \retval the using memory +*/ +uint32_t dma_fifo_status_get(uint32_t dma_periph, dma_channel_enum channelx) +{ + return (DMA_CHFCTL(dma_periph,channelx) & DMA_CHXFCTL_FCNT); +} + +/*! + \brief get DMA flag is set or not \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) \param[in] channelx: specify which DMA channel to get flag \arg DMA_CHx(x=0..7) \param[in] flag: specify get which flag - \arg DMA_INTF_FEEIF: FIFO error and exception flag - \arg DMA_INTF_SDEIF: single data mode exception flag - \arg DMA_INTF_TAEIF: transfer access error flag - \arg DMA_INTF_HTFIF: half transfer finish flag - \arg DMA_INTF_FTFIF: full transger finish flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_FEE: FIFO error and exception flag + \arg DMA_FLAG_SDE: single data mode exception flag + \arg DMA_FLAG_TAE: transfer access error flag + \arg DMA_FLAG_HTF: half transfer finish flag + \arg DMA_FLAG_FTF: full transger finish flag \param[out] none \retval FlagStatus: SET or RESET */ -FlagStatus dma_flag_get(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag) +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) { if(channelx < DMA_CH4){ if(DMA_INTF0(dma_periph) & DMA_FLAG_ADD(flag,channelx)){ @@ -215,15 +728,16 @@ FlagStatus dma_flag_get(uint32_t dma_periph,dma_channel_enum channelx,uint32_t f \param[in] channelx: specify which DMA channel to get flag \arg DMA_CHx(x=0..7) \param[in] flag: specify get which flag - \arg DMA_INTF_FEEIF: FIFO error and exception flag - \arg DMA_INTF_SDEIF: single data mode exception flag - \arg DMA_INTF_TAEIF: transfer access error flag - \arg DMA_INTF_HTFIF: half transfer finish flag - \arg DMA_INTF_FTFIF: full transger finish flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_FEE: FIFO error and exception flag + \arg DMA_FLAG_SDE: single data mode exception flag + \arg DMA_FLAG_TAE: transfer access error flag + \arg DMA_FLAG_HTF: half transfer finish flag + \arg DMA_FLAG_FTF: full transger finish flag \param[out] none \retval none */ -void dma_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag) +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) { if(channelx < DMA_CH4){ DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(flag,channelx); @@ -234,21 +748,22 @@ void dma_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint32_t flag) } /*! - \brief get DMA interrupt flag is set or not + \brief get DMA interrupt flag is set or not \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) \param[in] channelx: specify which DMA channel to get interrupt flag \arg DMA_CHx(x=0..7) \param[in] interrupt: specify get which flag - \arg DMA_INTF_FEEIF: FIFO error and exception flag - \arg DMA_INTF_SDEIF: single data mode exception flag - \arg DMA_INTF_TAEIF: transfer access error flag - \arg DMA_INTF_HTFIF: half transfer finish flag - \arg DMA_INTF_FTFIF: full transger finish flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_FEE: FIFO error and exception flag + \arg DMA_INT_FLAG_SDE: single data mode exception flag + \arg DMA_INT_FLAG_TAE: transfer access error flag + \arg DMA_INT_FLAG_HTF: half transfer finish flag + \arg DMA_INT_FLAG_FTF: full transger finish flag \param[out] none \retval FlagStatus: SET or RESET */ -FlagStatus dma_interrupt_flag_get(uint32_t dma_periph,dma_channel_enum channelx,uint32_t interrupt) +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t interrupt) { uint32_t interrupt_enable = 0U,interrupt_flag = 0U; dma_channel_enum channel_flag_offset = channelx; @@ -304,7 +819,7 @@ FlagStatus dma_interrupt_flag_get(uint32_t dma_periph,dma_channel_enum channelx, break; } } - + if(interrupt_flag && interrupt_enable){ return SET; }else{ @@ -319,15 +834,16 @@ FlagStatus dma_interrupt_flag_get(uint32_t dma_periph,dma_channel_enum channelx, \param[in] channelx: specify which DMA channel to clear interrupt flag \arg DMA_CHx(x=0..7) \param[in] interrupt: specify get which flag - \arg DMA_INTC_FEEIFC: clear FIFO error and exception flag - \arg DMA_INTC_SDEIFC: clear single data mode exception flag - \arg DMA_INTC_TAEIFC: clear transfer access error flag - \arg DMA_INTC_HTFIFC: clear half transfer finish flag - \arg DMA_INTC_FTFIFC: clear full transger finish flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_FEE: FIFO error and exception flag + \arg DMA_INT_FLAG_SDE: single data mode exception flag + \arg DMA_INT_FLAG_TAE: transfer access error flag + \arg DMA_INT_FLAG_HTF: half transfer finish flag + \arg DMA_INT_FLAG_FTF: full transger finish flag \param[out] none \retval none */ -void dma_interrupt_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint32_t interrupt) +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t interrupt) { if(channelx < DMA_CH4){ DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(interrupt,channelx); @@ -341,9 +857,10 @@ void dma_interrupt_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint \brief enable DMA interrupt \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel \arg DMA_CHx(x=0..7) \param[in] source: specify which interrupt to enbale + one or more parameters can be selected which are shown as below: \arg DMA_CHXCTL_SDEIE: single data mode exception interrupt enable \arg DMA_CHXCTL_TAEIE: tranfer access error interrupt enable \arg DMA_CHXCTL_HTFIE: half transfer finish interrupt enable @@ -352,7 +869,7 @@ void dma_interrupt_flag_clear(uint32_t dma_periph,dma_channel_enum channelx,uint \param[out] none \retval none */ -void dma_interrupt_enable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t source) +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) { if(DMA_CHXFCTL_FEEIE != source){ DMA_CHCTL(dma_periph,channelx) |= source; @@ -365,9 +882,10 @@ void dma_interrupt_enable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t \brief disable DMA interrupt \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel \arg DMA_CHx(x=0..7) \param[in] source: specify which interrupt to disbale + one or more parameters can be selected which are shown as below: \arg DMA_CHXCTL_SDEIE: single data mode exception interrupt enable \arg DMA_CHXCTL_TAEIE: tranfer access error interrupt enable \arg DMA_CHXCTL_HTFIE: half transfer finish interrupt enable @@ -376,7 +894,7 @@ void dma_interrupt_enable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t \param[out] none \retval none */ -void dma_interrupt_disable(uint32_t dma_periph,dma_channel_enum channelx,uint32_t source) +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) { if(DMA_CHXFCTL_FEEIE != source){ DMA_CHCTL(dma_periph,channelx) &= ~source; @@ -385,436 +903,3 @@ void dma_interrupt_disable(uint32_t dma_periph,dma_channel_enum channelx,uint32_ } } -/*! - \brief set DMA peripheral base address - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel to set peripheral base address - \arg DMA_CHx(x=0..7) - \param[in] address: peripheral base address - \param[out] none - \retval none -*/ -void dma_periph_address_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t address) -{ - DMA_CHPADDR(dma_periph,channelx) = address; -} - -/*! - \brief set DMA Memory0 base address - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel to set Memory base address - \arg DMA_CHx(x=0..7) - \param[in] memory_flag: DMA_MEMORY_x(x=0,1) - \param[in] address: Memory base address - \param[out] none - \retval none -*/ -void dma_memory_address_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t memory_flag,uint32_t address) -{ - if(memory_flag){ - DMA_CHM1ADDR(dma_periph,channelx) = address; - }else{ - DMA_CHM0ADDR(dma_periph,channelx) = address; - } -} - -/*! - \brief set the number of remaining data to be transferred by the DMA - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel to set number - \arg DMA_CHx(x=0..7) - \param[in] number: the number of remaining data to be transferred by the DMA - \param[out] none - \retval none -*/ -void dma_transfer_number_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t number) -{ - DMA_CHCNT(dma_periph,channelx) = number; -} - -/*! - \brief get the number of remaining data to be transferred by the DMA - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel to set number - \arg DMA_CHx(x=0..7) - \param[out] none - \retval uint32_t: the number of remaining data to be transferred by the DMA -*/ -uint32_t dma_transfer_number_get(uint32_t dma_periph,dma_channel_enum channelx) -{ - return (uint32_t)DMA_CHCNT(dma_periph,channelx); -} - -/*! - \brief configure priority level of DMA channel - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] priority: priority Level of this channel - \arg DMA_PRIORITY_LOW: low priority - \arg DMA_PRIORITY_MEDIUM: medium priority - \arg DMA_PRIORITY_HIGH: high priority - \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority - \param[out] none - \retval none -*/ -void dma_priority_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t priority) -{ - uint32_t ctl; - /* acquire DMA_CHxCTL register */ - ctl = DMA_CHCTL(dma_periph,channelx); - /* assign regiser */ - ctl &= ~DMA_CHXCTL_PRIO; - ctl |= priority; - DMA_CHCTL(dma_periph,channelx) = ctl; -} - -/*! - \brief configure transfer burst beats of memory - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] mbeat: transfer burst beats - \arg DMA_MEMORY_BURST_SINGLE: memory transfer single burst - \arg DMA_MEMORY_BURST_4_BEAT: memory transfer 4-beat burst - \arg DMA_MEMORY_BURST_8_BEAT: memory transfer 8-beat burst - \arg DMA_MEMORY_BURST_16_BEAT: memory transfer 16-beat burst - \param[out] none - \retval none -*/ -void dma_memory_burst_beats_config (uint32_t dma_periph,dma_channel_enum channelx,uint32_t mbeat) -{ - uint32_t ctl; - /* acquire DMA_CHxCTL register */ - ctl = DMA_CHCTL(dma_periph,channelx); - /* assign regiser */ - ctl &= ~DMA_CHXCTL_MBURST; - ctl |= mbeat; - DMA_CHCTL(dma_periph,channelx) = ctl; -} - -/*! - \brief configure transfer burst beats of peripheral - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] pbeat: transfer burst beats - \arg DMA_PERIPH_BURST_SINGLE: peripheral transfer single burst - \arg DMA_PERIPH_BURST_4_BEAT: peripheral transfer 4-beat burst - \arg DMA_PERIPH_BURST_8_BEAT: peripheral transfer 8-beat burst - \arg DMA_PERIPH_BURST_16_BEAT: peripheral transfer 16-beat burst - \param[out] none - \retval none -*/ -void dma_periph_burst_beats_config (uint32_t dma_periph,dma_channel_enum channelx,uint32_t pbeat) -{ - uint32_t ctl; - /* acquire DMA_CHxCTL register */ - ctl = DMA_CHCTL(dma_periph,channelx); - /* assign regiser */ - ctl &= ~DMA_CHXCTL_PBURST; - ctl |= pbeat; - DMA_CHCTL(dma_periph,channelx) = ctl; -} - -/*! - \brief configure transfer data size of memory - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] msize: transfer data size of memory - \arg DMA_MEMORY_WIDTH_8BIT: transfer data size of memory is 8-bit - \arg DMA_MEMORY_WIDTH_16BIT: transfer data size of memory is 16-bit - \arg DMA_MEMORY_WIDTH_32BIT: transfer data size of memory is 32-bit - \param[out] none - \retval none -*/ -void dma_memory_width_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t msize) -{ - uint32_t ctl; - /* acquire DMA_CHxCTL register */ - ctl = DMA_CHCTL(dma_periph,channelx); - /* assign regiser */ - ctl &= ~DMA_CHXCTL_MWIDTH; - ctl |= msize; - DMA_CHCTL(dma_periph,channelx) = ctl; -} - -/*! - \brief configure transfer data size of peripheral - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] msize: transfer data size of peripheral - \arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data size of peripheral is 8-bit - \arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data size of peripheral is 16-bit - \arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data size of peripheral is 32-bit - \param[out] none - \retval none -*/ -void dma_periph_width_config (uint32_t dma_periph,dma_channel_enum channelx,uint32_t psize) -{ - uint32_t ctl; - /* acquire DMA_CHxCTL register */ - ctl = DMA_CHCTL(dma_periph,channelx); - /* assign regiser */ - ctl &= ~DMA_CHXCTL_PWIDTH; - ctl |= psize; - DMA_CHCTL(dma_periph,channelx) = ctl; -} - -/*! - \brief configure memory address generation generation_algorithm - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] generation_algorithm: the address generation algorithm - \arg DMA_MEMORY_INCREASE_ENABLE: next address of memory is increasing address mode - \arg DMA_MEMORY_INCREASE_DISABLE: next address of memory is fixed address mode - \param[out] none - \retval none -*/ -void dma_memory_address_generation_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t generation_algorithm) -{ - if(DMA_MEMORY_INCREASE_ENABLE == generation_algorithm){ - DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_MNAGA; - }else{ - DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_MNAGA; - } -} - -/*! - \brief configure peripheral address generation generation_algorithm - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] generation_algorithm: the address generation algorithm - \arg DMA_PERIPH_INCREASE_ENABLE: next address of peripheral is increasing address mode - \arg DMA_PERIPH_INCREASE_DISABLE: next address of peripheral is fixed address mode - \arg DMA_PERIPH_INCREASE_FIX: increasing steps of peripheral address is fixed - \param[out] none - \retval none -*/ -void dma_peripheral_address_generation_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t generation_algorithm) -{ - if(DMA_PERIPH_INCREASE_ENABLE == generation_algorithm){ - DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PNAGA; - }else if(DMA_PERIPH_INCREASE_DISABLE == generation_algorithm){ - DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_PNAGA; - }else{ - DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PNAGA; - DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PAIF; - } -} - -/*! - \brief enable DMA circulation mode - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[out] none - \retval none -*/ -void dma_circulation_enable(uint32_t dma_periph,dma_channel_enum channelx) -{ - DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_CMEN; -} - -/*! - \brief disable DMA circulation mode - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[out] none - \retval none -*/ -void dma_circulation_disable(uint32_t dma_periph,dma_channel_enum channelx) -{ - DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CMEN; -} - -/*! - \brief configure the direction of data transfer on the channel - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] direction: specify the direction of data transfer - \arg DMA_PERIPH_TO_MEMORY: read from peripheral and write to memory - \arg DMA_MEMORY_TO_PERIPH: read from memory and write to peripheral - \arg DMA_MEMORY_TO_MEMORY: read from memory and write to memory - \param[out] none - \retval none -*/ -void dma_transfer_direction_config(uint32_t dma_periph,dma_channel_enum channelx,uint8_t direction) -{ - uint32_t ctl; - /* acquire DMA_CHxCTL register */ - ctl = DMA_CHCTL(dma_periph,channelx); - /* assign regiser */ - ctl &= ~DMA_CHXCTL_TM; - ctl |= direction; - - DMA_CHCTL(dma_periph,channelx) = ctl; -} - -/*! - \brief enable DMA channel - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[out] none - \retval none -*/ -void dma_channel_enable(uint32_t dma_periph,dma_channel_enum channelx) -{ - DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_CHEN; -} - -/*! - \brief disable DMA channel - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[out] none - \retval none -*/ -void dma_channel_disable(uint32_t dma_periph,dma_channel_enum channelx) -{ - DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CHEN; -} - -/*! - \brief DMA channel peripheral select - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] sub_periph: specify DMA channel peripheral - \arg DMA_SUBPERIx(x=0..7) - \param[out] none - \retval none -*/ -void dma_channel_subperipheral_select(uint32_t dma_periph,dma_channel_enum channelx,dma_subperipheral_enum sub_periph) -{ - uint32_t ctl; - /* acquire DMA_CHxCTL register */ - ctl = DMA_CHCTL(dma_periph,channelx); - /* assign regiser */ - ctl &= ~DMA_CHXCTL_PERIEN; - ctl |= ((uint32_t)sub_periph << CHXCTL_PERIEN_OFFSET); - - DMA_CHCTL(dma_periph,channelx) = ctl; -} - -/*! - \brief DMA switch buffer mode config - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] memory1_addr: memory1 base address - \param[in] memory_select: DMA_MEMORY_0 or DMA_MEMORY_1 - \param[out] none - \retval none -*/ -void dma_switch_buffer_mode_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t memory1_addr,uint32_t memory_select) -{ - /* configure memory1 base address */ - DMA_CHM1ADDR(dma_periph,channelx) = memory1_addr; - - if(DMA_MEMORY_0 == memory_select){ - DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_MBS; - }else{ - DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_MBS; - } -} - -/*! - \brief DMA switch buffer mode enable - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void dma_switch_buffer_mode_enable(uint32_t dma_periph,dma_channel_enum channelx,ControlStatus newvalue) -{ - if(ENABLE == newvalue){ - /* switch buffer mode enable */ - DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_SBMEN; - }else{ - /* switch buffer mode disable */ - DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_SBMEN; - } -} - -/*! - \brief DMA using memory get - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[out] none - \retval the using memory -*/ -uint32_t dma_using_memory_get(uint32_t dma_periph,dma_channel_enum channelx) -{ - if((DMA_CHCTL(dma_periph,channelx)) & DMA_CHXCTL_MBS){ - return DMA_MEMORY_1; - }else{ - return DMA_MEMORY_0; - } -} - -/*! - \brief DMA flow controller configure - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[in] controller: specify DMA flow controler - \arg DMA_FLOW_CONTROLLER_DMA: DMA is the flow controller - \arg DMA_FLOW_CONTROLLER_PERI: peripheral is the flow controller - \param[out] none - \retval none -*/ -void dma_flow_controller_config(uint32_t dma_periph,dma_channel_enum channelx,uint32_t controller) -{ - if(DMA_FLOW_CONTROLLER_DMA == controller){ - DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_TFCS; - }else{ - DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_TFCS; - } -} - -/*! - \brief DMA FIFO status get - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel - \arg DMA_CHx(x=0..7) - \param[out] none - \retval the using memory -*/ -uint32_t dma_fifo_status_get(uint32_t dma_periph,dma_channel_enum channelx) -{ - return (DMA_CHFCTL(dma_periph,channelx) & DMA_CHXFCTL_FCNT); -} diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c index 55ed8a9145..456e476fd8 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c @@ -1,24 +1,49 @@ /*! - \file gd32f4xx_enet.c - \brief ENET driver + \file gd32f4xx_enet.c + \brief ENET driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.1, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_enet.h" #if defined (__CC_ARM) /*!< ARM compiler */ -__align(4) +__align(4) enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ -__align(4) +__align(4) enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ -__align(4) +__align(4) uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ -__align(4) +__align(4) uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ #elif defined ( __ICCARM__ ) /*!< IAR compiler */ @@ -31,15 +56,11 @@ uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive bu #pragma data_alignment=4 uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ -#elif defined ( __GNUC__ ) -__attribute__((aligned(4))) -enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ -__attribute__((aligned(4))) -enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ -__attribute__((aligned(4))) -uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ -__attribute__((aligned(4))) -uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ +#elif defined (__GNUC__) /* GNU Compiler */ +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET RxDMA descriptor */ +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET TxDMA descriptor */ +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET receive buffer */ +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET transmit buffer */ #endif /* __CC_ARM */ @@ -53,19 +74,31 @@ enet_descriptors_struct *dma_current_ptp_rxdesc = NULL; /* init structure parameters for ENET initialization */ static enet_initpara_struct enet_initpara ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - +static uint32_t enet_unknow_err = 0U; /* array of register offset for debug information get */ static const uint16_t enet_reg_tab[] = { 0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, 0x0028, 0x002C, 0x0034, 0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, 0x1080, - -0x0100, 0x0104, 0x0108, 0x010C, 0x0110, 0x014C, 0x0150, 0x0168, 0x0194, 0x0198, 0x01C4, - -0x0700, 0x0704,0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, 0x0728, 0x072C, - + +0x0100, 0x0104, 0x0108, 0x010C, 0x0110, 0x014C, 0x0150, 0x0168, 0x0194, 0x0198, 0x01C4, + +0x0700, 0x0704,0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, 0x0728, 0x072C, + 0x1000, 0x1004, 0x1008, 0x100C, 0x1010, 0x1014, 0x1018, 0x101C, 0x1020, 0x1024, 0x1048, 0x104C, 0x1050, 0x1054}; +/* initialize ENET peripheral with generally concerned parameters, call it by enet_init() */ +static void enet_default_init(void); +#ifdef USE_DELAY +/* user can provide more timing precise _ENET_DELAY_ function */ +#define _ENET_DELAY_ delay_ms +#else +/* insert a delay time */ +static void enet_delay(uint32_t ncount); +/* default _ENET_DELAY_ function with less precise timing */ +#define _ENET_DELAY_ enet_delay +#endif + /*! \brief deinitialize the ENET, and reset structure parameters for ENET initialization @@ -82,16 +115,16 @@ void enet_deinit(void) /*! \brief configure the parameters which are usually less cared for initialization - note -- this function must be called before enet_init(), otherwise + note -- this function must be called before enet_init(), otherwise configuration will be no effect - \param[in] option: different function option, which is related to several parameters, - only one parameter can be selected which is shown as below, refer to enet_option_enum + \param[in] option: different function option, which is related to several parameters, refer to enet_option_enum + only one parameter can be selected which is shown as below \arg FORWARD_OPTION: choose to configure the frame forward related parameters \arg DMABUS_OPTION: choose to configure the DMA bus mode related parameters \arg DMA_MAXBURST_OPTION: choose to configure the DMA max burst related parameters \arg DMA_ARBITRATION_OPTION: choose to configure the DMA arbitration related parameters \arg STORE_OPTION: choose to configure the store forward mode related parameters - \arg DMA_OPTION: choose to configure the DMA descriptor related parameters + \arg DMA_OPTION: choose to configure the DMA descriptor related parameters \arg VLAN_OPTION: choose to configure vlan related parameters \arg FLOWCTL_OPTION: choose to configure flow control related parameters \arg HASHH_OPTION: choose to configure hash high @@ -100,8 +133,8 @@ void enet_deinit(void) \arg HALFDUPLEX_OPTION: choose to configure halfduplex mode related parameters \arg TIMER_OPTION: choose to configure time counter related parameters \arg INTERFRAMEGAP_OPTION: choose to configure the inter frame gap related parameters - \param[in] para: the related parameters according to the option - all the related parameters should be configured which are shown as below + \param[in] para: the related parameters according to the option + all the related parameters should be configured which are shown as below FORWARD_OPTION related parameters: - ENET_AUTO_PADCRC_DROP_ENABLE/ ENET_AUTO_PADCRC_DROP_DISABLE ; - ENET_TYPEFRAME_CRC_DROP_ENABLE/ ENET_TYPEFRAME_CRC_DROP_DISABLE ; @@ -110,7 +143,7 @@ void enet_deinit(void) DMABUS_OPTION related parameters: - ENET_ADDRESS_ALIGN_ENABLE/ ENET_ADDRESS_ALIGN_DISABLE ; - ENET_FIXED_BURST_ENABLE/ ENET_FIXED_BURST_DISABLE ; - - ENET_MIXED_BURST_ENABLE/ ENET_MIXED_BURST_DISABLE ; + - ENET_MIXED_BURST_ENABLE/ ENET_MIXED_BURST_DISABLE ; DMA_MAXBURST_OPTION related parameters: - ENET_RXDP_1BEAT/ ENET_RXDP_2BEAT/ ENET_RXDP_4BEAT/ ENET_RXDP_8BEAT/ ENET_RXDP_16BEAT/ ENET_RXDP_32BEAT/ @@ -146,7 +179,7 @@ void enet_deinit(void) FLOWCTL_OPTION related parameters: - MAC_FCTL_PTM(regval) ; - ENET_ZERO_QUANTA_PAUSE_ENABLE/ ENET_ZERO_QUANTA_PAUSE_DISABLE ; - - ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/ + - ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/ ENET_PAUSETIME_MINUS144/ENET_PAUSETIME_MINUS256 ; - ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT/ ENET_UNIQUE_PAUSEDETECT ; - ENET_RX_FLOWCONTROL_ENABLE/ ENET_RX_FLOWCONTROL_DISABLE ; @@ -180,7 +213,7 @@ void enet_deinit(void) ENET_INTERFRAMEGAP_80BIT/ ENET_INTERFRAMEGAP_72BIT/ ENET_INTERFRAMEGAP_64BIT/ ENET_INTERFRAMEGAP_56BIT/ ENET_INTERFRAMEGAP_48BIT/ ENET_INTERFRAMEGAP_40BIT . - \param[out] none + \param[out] none \retval none */ void enet_initpara_config(enet_option_enum option, uint32_t para) @@ -214,11 +247,11 @@ void enet_initpara_config(enet_option_enum option, uint32_t para) case DMA_OPTION: /* choose to configure dma_function, and save the configuration parameters */ enet_initpara.option_enable |= (uint32_t)DMA_OPTION; - + #ifndef SELECT_DESCRIPTORS_ENHANCED_MODE para &= ~ENET_ENHANCED_DESCRIPTOR; -#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ - +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + enet_initpara.dma_function = para; break; case VLAN_OPTION: @@ -254,7 +287,7 @@ void enet_initpara_config(enet_option_enum option, uint32_t para) case TIMER_OPTION: /* choose to configure timer_config, and save the configuration parameters */ enet_initpara.option_enable |= (uint32_t)TIMER_OPTION; - enet_initpara.timer_config = para; + enet_initpara.timer_config = para; break; case INTERFRAMEGAP_OPTION: /* choose to configure interframegap, and save the configuration parameters */ @@ -262,34 +295,34 @@ void enet_initpara_config(enet_option_enum option, uint32_t para) enet_initpara.interframegap = para; break; default: - break; - } -} + break; + } +} /*! - \brief initialize ENET peripheral with generally concerned parameters and the less cared + \brief initialize ENET peripheral with generally concerned parameters and the less cared parameters - \param[in] mediamode: PHY mode and mac loopback configurations, only one parameter can be selected - which is shown as below, refer to enet_mediamode_enum + \param[in] mediamode: PHY mode and mac loopback configurations, refer to enet_mediamode_enum + only one parameter can be selected which is shown as below \arg ENET_AUTO_NEGOTIATION: PHY auto negotiation \arg ENET_100M_FULLDUPLEX: 100Mbit/s, full-duplex \arg ENET_100M_HALFDUPLEX: 100Mbit/s, half-duplex \arg ENET_10M_FULLDUPLEX: 10Mbit/s, full-duplex \arg ENET_10M_HALFDUPLEX: 10Mbit/s, half-duplex \arg ENET_LOOPBACKMODE: MAC in loopback mode at the MII - \param[in] checksum: IP frame checksum offload function, only one parameter can be selected - which is shown as below, refer to enet_mediamode_enum + \param[in] checksum: IP frame checksum offload function, refer to enet_mediamode_enum + only one parameter can be selected which is shown as below \arg ENET_NO_AUTOCHECKSUM: disable IP frame checksum function \arg ENET_AUTOCHECKSUM_DROP_FAILFRAMES: enable IP frame checksum function \arg ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES: enable IP frame checksum function, and the received frame with only payload error but no other errors will not be dropped - \param[in] recept: frame filter function, only one parameter can be selected - which is shown as below, refer to enet_frmrecept_enum + \param[in] recept: frame filter function, refer to enet_frmrecept_enum + only one parameter can be selected which is shown as below \arg ENET_PROMISCUOUS_MODE: promiscuous mode enabled \arg ENET_RECEIVEALL: all received frame are forwarded to application \arg ENET_BROADCAST_FRAMES_PASS: the address filters pass all received broadcast frames \arg ENET_BROADCAST_FRAMES_DROP: the address filters filter all incoming broadcast frames - \param[out] none + \param[out] none \retval ErrStatus: ERROR or SUCCESS */ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept) @@ -297,19 +330,19 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum uint32_t reg_value=0U, reg_temp = 0U, temp = 0U; uint32_t media_temp = 0U; uint32_t timeout = 0U; - uint16_t phy_value = 0U; + uint16_t phy_value = 0U; ErrStatus phy_state= ERROR, enet_state = ERROR; - + /* PHY interface configuration, configure SMI clock and reset PHY chip */ if(ERROR == enet_phy_config()){ _ENET_DELAY_(PHY_RESETDELAY); if(ERROR == enet_phy_config()){ return enet_state; - } + } } /* initialize ENET peripheral with generally concerned parameters */ enet_default_init(); - + /* 1st, configure mediamode */ media_temp = (uint32_t)mediamode; /* if is PHY auto negotiation */ @@ -317,7 +350,7 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum /* wait for PHY_LINKED_STATUS bit be set */ do{ enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); - phy_value &= PHY_LINKED_STATUS; + phy_value &= PHY_LINKED_STATUS; timeout++; }while((RESET == phy_value) && (timeout < PHY_READ_TO)); /* return ERROR due to timeout */ @@ -326,7 +359,7 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum } /* reset timeout counter */ timeout = 0U; - + /* enable auto-negotiation */ phy_value = PHY_AUTONEGOTIATION; phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); @@ -334,22 +367,22 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum /* return ERROR due to write timeout */ return enet_state; } - + /* wait for the PHY_AUTONEGO_COMPLETE bit be set */ do{ enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); phy_value &= PHY_AUTONEGO_COMPLETE; timeout++; - }while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO)); + }while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO)); /* return ERROR due to timeout */ if(PHY_READ_TO == timeout){ return enet_state; } /* reset timeout counter */ timeout = 0U; - + /* read the result of the auto-negotiation */ - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value); + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value); /* configure the duplex mode of MAC following the auto-negotiation result */ if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)){ media_temp = ENET_MODE_FULLDUPLEX; @@ -361,7 +394,7 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum media_temp |= ENET_SPEEDMODE_10M; }else{ media_temp |= ENET_SPEEDMODE_100M; - } + } }else{ phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3); phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1); @@ -371,7 +404,7 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum return enet_state; } /* PHY configuration need some time */ - _ENET_DELAY_(PHY_CONFIGDELAY); + _ENET_DELAY_(PHY_CONFIGDELAY); } /* after configuring the PHY, use mediamode to configure registers */ reg_value = ENET_MAC_CFG; @@ -379,27 +412,27 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum reg_value &= (~(ENET_MAC_CFG_SPD |ENET_MAC_CFG_DPM |ENET_MAC_CFG_LBM)); reg_value |= media_temp; ENET_MAC_CFG = reg_value; - - + + /* 2st, configure checksum */ if(RESET != ((uint32_t)checksum & ENET_CHECKSUMOFFLOAD_ENABLE)){ ENET_MAC_CFG |= ENET_CHECKSUMOFFLOAD_ENABLE; - + reg_value = ENET_DMA_CTL; /* configure ENET_DMA_CTL register */ reg_value &= ~ENET_DMA_CTL_DTCERFD; reg_value |= ((uint32_t)checksum & ENET_DMA_CTL_DTCERFD); ENET_DMA_CTL = reg_value; } - + /* 3rd, configure recept */ ENET_MAC_FRMF |= (uint32_t)recept; - + /* 4th, configure different function options */ /* configure forward_frame related registers */ if(RESET != (enet_initpara.option_enable & (uint32_t)FORWARD_OPTION)){ reg_temp = enet_initpara.forward_frame; - + reg_value = ENET_MAC_CFG; temp = reg_temp; /* configure ENET_MAC_CFG register */ @@ -407,7 +440,7 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum temp &= (ENET_MAC_CFG_TFCD | ENET_MAC_CFG_APCD); reg_value |= temp; ENET_MAC_CFG = reg_value; - + reg_value = ENET_DMA_CTL; temp = reg_temp; /* configure ENET_DMA_CTL register */ @@ -420,7 +453,7 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum /* configure dmabus_mode related registers */ if(RESET != (enet_initpara.option_enable & (uint32_t)DMABUS_OPTION)){ temp = enet_initpara.dmabus_mode; - + reg_value = ENET_DMA_BCTL; /* configure ENET_DMA_BCTL register */ reg_value &= ~(ENET_DMA_BCTL_AA | ENET_DMA_BCTL_FB \ @@ -430,31 +463,31 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum } /* configure dma_maxburst related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)){ temp = enet_initpara.dma_maxburst; - + reg_value = ENET_DMA_BCTL; /* configure ENET_DMA_BCTL register */ - reg_value &= ~(ENET_DMA_BCTL_RXDP| ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP); + reg_value &= ~(ENET_DMA_BCTL_RXDP| ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP); reg_value |= temp; ENET_DMA_BCTL = reg_value; } /* configure dma_arbitration related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)){ temp = enet_initpara.dma_arbitration; - + reg_value = ENET_DMA_BCTL; /* configure ENET_DMA_BCTL register */ reg_value &= ~(ENET_DMA_BCTL_RTPR | ENET_DMA_BCTL_DAB); reg_value |= temp; ENET_DMA_BCTL = reg_value; } - + /* configure store_forward_mode related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)){ temp = enet_initpara.store_forward_mode; - + reg_value = ENET_DMA_CTL; /* configure ENET_DMA_CTL register */ reg_value &= ~(ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD| ENET_DMA_CTL_RTHC| ENET_DMA_CTL_TTHC); @@ -463,9 +496,9 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum } /* configure dma_function related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)){ reg_temp = enet_initpara.dma_function; - + reg_value = ENET_DMA_CTL; temp = reg_temp; /* configure ENET_DMA_CTL register */ @@ -473,7 +506,7 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum temp &= (ENET_DMA_CTL_DAFRF | ENET_DMA_CTL_OSF); reg_value |= temp; ENET_DMA_CTL = reg_value; - + reg_value = ENET_DMA_BCTL; temp = reg_temp; /* configure ENET_DMA_BCTL register */ @@ -484,9 +517,9 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum } /* configure vlan_config related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)){ reg_temp = enet_initpara.vlan_config; - + reg_value = ENET_MAC_VLT; /* configure ENET_MAC_VLT register */ reg_value &= ~(ENET_MAC_VLT_VLTI | ENET_MAC_VLT_VLTC); @@ -495,9 +528,9 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum } /* configure flow_control related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)){ reg_temp = enet_initpara.flow_control; - + reg_value = ENET_MAC_FCTL; temp = reg_temp; /* configure ENET_MAC_FCTL register */ @@ -507,7 +540,7 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); reg_value |= temp; ENET_MAC_FCTL = reg_value; - + reg_value = ENET_MAC_FCTH; temp = reg_temp; /* configure ENET_MAC_FCTH register */ @@ -515,22 +548,22 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum temp &= ((ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD )<<8); reg_value |= (temp >> 8); ENET_MAC_FCTH = reg_value; - } - + } + /* configure hashtable_high related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)){ ENET_MAC_HLH = enet_initpara.hashtable_high; - } + } /* configure hashtable_low related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)){ ENET_MAC_HLL = enet_initpara.hashtable_low; - } + } /* configure framesfilter_mode related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)){ reg_temp = enet_initpara.framesfilter_mode; - + reg_value = ENET_MAC_FRMF; /* configure ENET_MAC_FRMF register */ reg_value &= ~(ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT | ENET_MAC_FRMF_DAIFLT \ @@ -538,41 +571,41 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum | ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_PCFRM); reg_value |= reg_temp; ENET_MAC_FRMF = reg_value; - } + } /* configure halfduplex_param related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)){ reg_temp = enet_initpara.halfduplex_param; - + reg_value = ENET_MAC_CFG; /* configure ENET_MAC_CFG register */ reg_value &= ~(ENET_MAC_CFG_CSD | ENET_MAC_CFG_ROD | ENET_MAC_CFG_RTD \ | ENET_MAC_CFG_BOL | ENET_MAC_CFG_DFC); reg_value |= reg_temp; ENET_MAC_CFG = reg_value; - } + } /* configure timer_config related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)){ reg_temp = enet_initpara.timer_config; - + reg_value = ENET_MAC_CFG; /* configure ENET_MAC_CFG register */ reg_value &= ~(ENET_MAC_CFG_WDD | ENET_MAC_CFG_JBD); reg_value |= reg_temp; ENET_MAC_CFG = reg_value; - } - + } + /* configure interframegap related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)){ reg_temp = enet_initpara.interframegap; - + reg_value = ENET_MAC_CFG; /* configure ENET_MAC_CFG register */ reg_value &= ~ENET_MAC_CFG_IGBS; reg_value |= reg_temp; ENET_MAC_CFG = reg_value; - } + } enet_state = SUCCESS; return enet_state; @@ -589,21 +622,21 @@ ErrStatus enet_software_reset(void) uint32_t timeout = 0U; ErrStatus enet_state = ERROR; uint32_t dma_flag; - + /* reset all core internal registers located in CLK_TX and CLK_RX */ ENET_DMA_BCTL |= ENET_DMA_BCTL_SWR; - + /* wait for reset operation complete */ do{ dma_flag = (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR); timeout++; }while((RESET != dma_flag) && (ENET_DELAY_TO != timeout)); - /* reset operation complete */ + /* reset operation complete */ if(RESET == (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR)){ enet_state = SUCCESS; } - + return enet_state; } @@ -617,15 +650,15 @@ uint32_t enet_rxframe_size_get(void) { uint32_t size = 0U; uint32_t status; - + /* get rdes0 information of current RxDMA descriptor */ status = dma_current_rxdesc->status; - + /* if the desciptor is owned by DMA */ if((uint32_t)RESET != (status & ENET_RDES0_DAV)){ return 0U; } - + /* if has any error, or the frame uses two or more descriptors */ if((((uint32_t)RESET) != (status & ENET_RDES0_ERRS)) || (((uint32_t)RESET) == (status & ENET_RDES0_LDES)) || @@ -633,7 +666,7 @@ uint32_t enet_rxframe_size_get(void) /* drop current receive frame */ enet_rxframe_drop(); - return 0U; + return 1U; } #ifdef SELECT_DESCRIPTORS_ENHANCED_MODE /* if is an ethernet-type frame, and IP frame payload error occurred */ @@ -642,18 +675,18 @@ uint32_t enet_rxframe_size_get(void) /* drop current receive frame */ enet_rxframe_drop(); - return 0U; + return 1U; } -#else +#else /* if is an ethernet-type frame, and IP frame payload error occurred */ if((((uint32_t)RESET) != (status & ENET_RDES0_FRMT)) && (((uint32_t)RESET) != (status & ENET_RDES0_PCERR))){ /* drop current receive frame */ enet_rxframe_drop(); - return 0U; - } -#endif + return 1U; + } +#endif /* if CPU owns current descriptor, no error occured, the frame uses only one descriptor */ if((((uint32_t)RESET) == (status & ENET_RDES0_DAV)) && (((uint32_t)RESET) == (status & ENET_RDES0_ERRS)) && @@ -661,22 +694,27 @@ uint32_t enet_rxframe_size_get(void) (((uint32_t)RESET) != (status & ENET_RDES0_FDES))){ /* get the size of the received data including CRC */ size = GET_RDES0_FRML(status); - /* substract the CRC size */ + /* substract the CRC size */ size = size - 4U; - - /* if is a type frame, and CRC is not included in forwarding frame */ + + /* if is a type frame, and CRC is not included in forwarding frame */ if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (status & ENET_RDES0_FRMT))){ size = size + 4U; } + }else{ + enet_unknow_err++; + enet_rxframe_drop(); + + return 1U; } - - /* return packet size */ + + /* return packet size */ return size; } /*! \brief initialize the DMA Tx/Rx descriptors's parameters in chain mode - \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum only one parameter can be selected which is shown as below \arg ENET_DMA_TX: DMA Tx descriptors \arg ENET_DMA_RX: DMA Rx descriptors @@ -688,7 +726,7 @@ void enet_descriptors_chain_init(enet_dmadirection_enum direction) uint32_t num = 0U, count = 0U, maxsize = 0U; uint32_t desc_status = 0U, desc_bufsize = 0U; enet_descriptors_struct *desc, *desc_tab; - uint8_t *buf; + uint8_t *buf; /* if want to initialize DMA Tx descriptors */ if (ENET_DMA_TX == direction){ @@ -697,58 +735,58 @@ void enet_descriptors_chain_init(enet_dmadirection_enum direction) buf = &tx_buff[0][0]; count = ENET_TXBUF_NUM; maxsize = ENET_TXBUF_SIZE; - + /* select chain mode */ desc_status = ENET_TDES0_TCHM; - + /* configure DMA Tx descriptor table address register */ ENET_DMA_TDTADDR = (uint32_t)desc_tab; dma_current_txdesc = desc_tab; - }else{ + }else{ /* if want to initialize DMA Rx descriptors */ /* save a copy of the DMA Rx descriptors */ desc_tab = rxdesc_tab; buf = &rx_buff[0][0]; count = ENET_RXBUF_NUM; maxsize = ENET_RXBUF_SIZE; - + /* enable receiving */ desc_status = ENET_RDES0_DAV; /* select receive chained mode and set buffer1 size */ desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; - + /* configure DMA Rx descriptor table address register */ ENET_DMA_RDTADDR = (uint32_t)desc_tab; - dma_current_rxdesc = desc_tab; + dma_current_rxdesc = desc_tab; } dma_current_ptp_rxdesc = NULL; dma_current_ptp_txdesc = NULL; - - /* configure each descriptor */ + + /* configure each descriptor */ for(num=0U; num < count; num++){ /* get the pointer to the next descriptor of the descriptor table */ desc = desc_tab + num; /* configure descriptors */ - desc->status = desc_status; + desc->status = desc_status; desc->control_buffer_size = desc_bufsize; desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); - + /* if is not the last descriptor */ if(num < (count - 1U)){ /* configure the next descriptor address */ desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); }else{ - /* when it is the last descriptor, the next descriptor address - equals to first descriptor address in descriptor table */ - desc->buffer2_next_desc_addr = (uint32_t) desc_tab; + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t) desc_tab; } - } + } } /*! \brief initialize the DMA Tx/Rx descriptors's parameters in ring mode - \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum only one parameter can be selected which is shown as below \arg ENET_DMA_TX: DMA Tx descriptors \arg ENET_DMA_RX: DMA Rx descriptors @@ -761,20 +799,20 @@ void enet_descriptors_ring_init(enet_dmadirection_enum direction) uint32_t desc_status = 0U, desc_bufsize = 0U; enet_descriptors_struct *desc; enet_descriptors_struct *desc_tab; - uint8_t *buf; - + uint8_t *buf; + /* configure descriptor skip length */ ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); - + /* if want to initialize DMA Tx descriptors */ if (ENET_DMA_TX == direction){ /* save a copy of the DMA Tx descriptors */ desc_tab = txdesc_tab; buf = &tx_buff[0][0]; count = ENET_TXBUF_NUM; - maxsize = ENET_TXBUF_SIZE; - + maxsize = ENET_TXBUF_SIZE; + /* configure DMA Tx descriptor table address register */ ENET_DMA_TDTADDR = (uint32_t)desc_tab; dma_current_txdesc = desc_tab; @@ -784,41 +822,41 @@ void enet_descriptors_ring_init(enet_dmadirection_enum direction) desc_tab = rxdesc_tab; buf = &rx_buff[0][0]; count = ENET_RXBUF_NUM; - maxsize = ENET_RXBUF_SIZE; - + maxsize = ENET_RXBUF_SIZE; + /* enable receiving */ desc_status = ENET_RDES0_DAV; /* set buffer1 size */ desc_bufsize = ENET_RXBUF_SIZE; - + /* configure DMA Rx descriptor table address register */ ENET_DMA_RDTADDR = (uint32_t)desc_tab; - dma_current_rxdesc = desc_tab; + dma_current_rxdesc = desc_tab; } dma_current_ptp_rxdesc = NULL; dma_current_ptp_txdesc = NULL; - - /* configure each descriptor */ + + /* configure each descriptor */ for(num=0U; num < count; num++){ /* get the pointer to the next descriptor of the descriptor table */ desc = desc_tab + num; /* configure descriptors */ - desc->status = desc_status; - desc->control_buffer_size = desc_bufsize; - desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); - + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + /* when it is the last descriptor */ if(num == (count - 1U)){ if (ENET_DMA_TX == direction){ - /* configure transmit end of ring mode */ + /* configure transmit end of ring mode */ desc->status |= ENET_TDES0_TERM; }else{ /* configure receive end of ring mode */ desc->control_buffer_size |= ENET_RDES1_RERM; } } - } + } } /*! @@ -831,46 +869,46 @@ void enet_descriptors_ring_init(enet_dmadirection_enum direction) ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize) { uint32_t offset = 0U, size = 0U; - + /* the descriptor is busy due to own by the DMA */ if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ - return ERROR; + return ERROR; } - + /* if buffer pointer is null, indicates that users has copied data in application */ if(NULL != buffer){ /* if no error occurs, and the frame uses only one descriptor */ - if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && - (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && - (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ /* get the frame length except CRC */ size = GET_RDES0_FRML(dma_current_rxdesc->status); size = size - 4U; - - /* if is a type frame, and CRC is not included in forwarding frame */ + + /* if is a type frame, and CRC is not included in forwarding frame */ if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))){ size = size + 4U; } - + /* to avoid situation that the frame size exceeds the buffer length */ if(size > bufsize){ return ERROR; } - + /* copy data from Rx buffer to application buffer */ for(offset = 0U; offsetbuffer1_addr) + offset)); } - + }else{ /* return ERROR */ return ERROR; } } /* enable reception, descriptor is owned by DMA */ - dma_current_rxdesc->status = ENET_RDES0_DAV; - + dma_current_rxdesc->status = ENET_RDES0_DAV; + /* check Rx buffer unavailable flag status */ if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ /* clear RBU flag */ @@ -878,22 +916,22 @@ ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize) /* resume DMA reception by writing to the RPEN register*/ ENET_DMA_RPEN = 0U; } - - /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ /* chained mode */ - if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ - dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); - }else{ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + }else{ /* ring mode */ if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ /* if is the last descriptor in table, the next descriptor is the table header */ - dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); - }else{ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + }else{ /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ - dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); } } - + return SUCCESS; } @@ -909,52 +947,52 @@ ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length) { uint32_t offset = 0U; uint32_t dma_tbu_flag, dma_tu_flag; - + /* the descriptor is busy due to own by the DMA */ if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ return ERROR; } - + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ if(length > ENET_MAX_FRAME_SIZE){ return ERROR; - } - + } + /* if buffer pointer is null, indicates that users has handled data in application */ - if(NULL != buffer){ + if(NULL != buffer){ /* copy frame data from application buffer to Tx buffer */ for(offset = 0U; offset < length; offset++){ (*(__IO uint8_t *) (uint32_t)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); } } - + /* set the frame length */ dma_current_txdesc->control_buffer_size = length; - /* set the segment of frame, frame is transmitted in one descriptor */ + /* set the segment of frame, frame is transmitted in one descriptor */ dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; /* enable the DMA transmission */ dma_current_txdesc->status |= ENET_TDES0_DAV; - + /* check Tx buffer unavailable flag status */ - dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); - + if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ /* clear TBU and TU flag */ ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); /* resume DMA transmission by writing to the TPEN register*/ ENET_DMA_TPEN = 0U; } - - /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ /* chained mode */ - if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ - dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); - }else{ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); + }else{ /* ring mode */ if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ /* if is the last descriptor in table, the next descriptor is the table header */ - dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); }else{ /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); @@ -966,7 +1004,7 @@ ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length) /*! \brief configure the transmit IP frame checksum offload calculation and insertion - \param[in] desc: the descriptor pointer which users want to configure + \param[in] desc: the descriptor pointer which users want to configure, refer to enet_descriptors_struct \param[in] checksum: IP frame checksum configuration only one parameter can be selected which is shown as below \arg ENET_CHECKSUM_DISABLE: checksum insertion disabled @@ -1007,18 +1045,18 @@ void enet_disable(void) } /*! - \brief configure MAC address - \param[in] mac_addr: select which MAC address will be set, - only one parameter can be selected which is shown as below + \brief configure MAC address + \param[in] mac_addr: select which MAC address will be set, refer to enet_macaddress_enum + only one parameter can be selected which is shown as below \arg ENET_MAC_ADDRESS0: set MAC address 0 filter \arg ENET_MAC_ADDRESS1: set MAC address 1 filter \arg ENET_MAC_ADDRESS2: set MAC address 2 filter \arg ENET_MAC_ADDRESS3: set MAC address 3 filter \param[in] paddr: the buffer pointer which stores the MAC address - (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) \param[out] none \retval none -*/ +*/ void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]) { REG32(ENET_ADDRH_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRH(paddr); @@ -1026,17 +1064,17 @@ void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]) } /*! - \brief get MAC address - \param[in] mac_addr: select which MAC address will be get, + \brief get MAC address + \param[in] mac_addr: select which MAC address will be get, refer to enet_macaddress_enum only one parameter can be selected which is shown as below \arg ENET_MAC_ADDRESS0: get MAC address 0 filter \arg ENET_MAC_ADDRESS1: get MAC address 1 filter \arg ENET_MAC_ADDRESS2: get MAC address 2 filter \arg ENET_MAC_ADDRESS3: get MAC address 3 filter \param[out] paddr: the buffer pointer which is stored the MAC address - (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) \retval none -*/ +*/ void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]) { paddr[0] = ENET_GET_MACADDR(mac_addr, 0U); @@ -1048,12 +1086,12 @@ void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]) } /*! - \brief get the ENET MAC/MSC/PTP/DMA status flag + \brief get the ENET MAC/MSC/PTP/DMA status flag \param[in] enet_flag: ENET status flag, refer to enet_flag_enum, only one parameter can be selected which is shown as below - \arg ENET_MAC_FLAG_MPKR: magic packet received flag + \arg ENET_MAC_FLAG_MPKR: magic packet received flag \arg ENET_MAC_FLAG_WUFR: wakeup frame received flag - \arg ENET_MAC_FLAG_FLOWCONTROL: flow control status flag + \arg ENET_MAC_FLAG_FLOWCONTROL: flow control status flag \arg ENET_MAC_FLAG_WUM: WUM status flag \arg ENET_MAC_FLAG_MSC: MSC status flag \arg ENET_MAC_FLAG_MSCR: MSC receive status flag @@ -1101,7 +1139,7 @@ FlagStatus enet_flag_get(enet_flag_enum enet_flag) } /*! - \brief clear the ENET DMA status flag + \brief clear the ENET DMA status flag \param[in] enet_flag: ENET DMA flag clear, refer to enet_flag_clear_enum only one parameter can be selected which is shown as below \arg ENET_DMA_FLAG_TS_CLR: transmit status flag clear @@ -1129,8 +1167,8 @@ void enet_flag_clear(enet_flag_clear_enum enet_flag) } /*! - \brief enable ENET MAC/MSC/DMA interrupt - \param[in] enet_int: ENET interrupt, + \brief enable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt,, refer to enet_int_enum only one parameter can be selected which is shown as below \arg ENET_MAC_INT_WUMIM: WUM interrupt mask \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask @@ -1170,8 +1208,8 @@ void enet_interrupt_enable(enet_int_enum enet_int) } /*! - \brief disable ENET MAC/MSC/DMA interrupt - \param[in] enet_int: ENET interrupt, + \brief disable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, refer to enet_int_enum only one parameter can be selected which is shown as below \arg ENET_MAC_INT_WUMIM: WUM interrupt mask \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask @@ -1211,8 +1249,8 @@ void enet_interrupt_disable(enet_int_enum enet_int) } /*! - \brief get ENET MAC/MSC/DMA interrupt flag - \param[in] int_flag: ENET interrupt flag, + \brief get ENET MAC/MSC/DMA interrupt flag + \param[in] int_flag: ENET interrupt flag, refer to enet_int_flag_enum only one parameter can be selected which is shown as below \arg ENET_MAC_INT_FLAG_WUM: WUM status flag \arg ENET_MAC_INT_FLAG_MSC: MSC status flag @@ -1256,8 +1294,8 @@ FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag) } /*! - \brief clear ENET DMA interrupt flag - \param[in] int_flag_clear: clear ENET interrupt flag, + \brief clear ENET DMA interrupt flag + \param[in] int_flag_clear: clear ENET interrupt flag, refer to enet_int_flag_clear_enum only one parameter can be selected which is shown as below \arg ENET_DMA_INT_FLAG_TS_CLR: transmit status flag \arg ENET_DMA_INT_FLAG_TPS_CLR: transmit process stopped status flag @@ -1303,7 +1341,7 @@ void enet_tx_enable(void) \retval none */ void enet_tx_disable(void) -{ +{ ENET_DMA_CTL &= ~ENET_DMA_CTL_STE; enet_txfifo_flush(); ENET_MAC_CFG &= ~ENET_MAC_CFG_TEN; @@ -1334,10 +1372,10 @@ void enet_rx_disable(void) } /*! - \brief put registers value into the application buffer + \brief put registers value into the application buffer \param[in] type: register type which will be get, refer to enet_registers_type_enum, only one parameter can be selected which is shown as below - \arg ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH + \arg ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH \arg ALL_MSC_REG: get the registers within the offset scope between ENET_MSC_CTL and ENET_MSC_RGUFCNT \arg ALL_PTP_REG: get the registers within the offset scope between ENET_PTP_TSCTL and ENET_PTP_PPSCTL \arg ALL_DMA_REG: get the registers within the offset scope between ENET_DMA_BCTL and ENET_DMA_CRBADDR @@ -1348,37 +1386,37 @@ void enet_rx_disable(void) void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num) { uint32_t offset = 0U, max = 0U, limit = 0U; - + offset = (uint32_t)type; max = (uint32_t)type + num; limit = sizeof(enet_reg_tab)/sizeof(uint16_t); - + /* prevent element in this array is out of range */ - if(max > limit){ + if(max > limit){ max = limit; } - + for(; offset < max; offset++){ /* get value of the corresponding register */ - *preg = REG32((ENET) + enet_reg_tab[offset]); + *preg = REG32((ENET) + enet_reg_tab[offset]); preg++; } -} +} /*! \brief get the enet debug status from the debug register - \param[in] mac_debug: enet debug status, + \param[in] mac_debug: enet debug status only one parameter can be selected which is shown as below \arg ENET_MAC_RECEIVER_NOT_IDLE: MAC receiver is not in idle state \arg ENET_RX_ASYNCHRONOUS_FIFO_STATE: Rx asynchronous FIFO status - \arg ENET_RXFIFO_NOT_WRITING: RxFIFO is not doing write operation + \arg ENET_RXFIFO_WRITING: RxFIFO is doing write operation \arg ENET_RXFIFO_READ_STATUS: RxFIFO read operation status \arg ENET_RXFIFO_STATE: RxFIFO state \arg ENET_MAC_TRANSMITTER_NOT_IDLE: MAC transmitter is not in idle state \arg ENET_MAC_TRANSMITTER_STATUS: status of MAC transmitter \arg ENET_PAUSE_CONDITION_STATUS: pause condition status \arg ENET_TXFIFO_READ_STATUS: TxFIFO read operation status - \arg ENET_TXFIFO_NOT_WRITING: TxFIFO is not doing write operation + \arg ENET_TXFIFO_WRITING: TxFIFO is doing write operation \arg ENET_TXFIFO_NOT_EMPTY: TxFIFO is not empty \arg ENET_TXFIFO_FULL: TxFIFO is full \param[out] none @@ -1387,7 +1425,7 @@ void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t uint32_t enet_debug_status_get(uint32_t mac_debug) { uint32_t temp_state = 0U; - + switch(mac_debug){ case ENET_RX_ASYNCHRONOUS_FIFO_STATE: temp_state = GET_MAC_DBG_RXAFS(ENET_MAC_DBG); @@ -1408,14 +1446,14 @@ uint32_t enet_debug_status_get(uint32_t mac_debug) if(RESET != (ENET_MAC_DBG & mac_debug)){ temp_state = 0x1U; } - break; + break; } return temp_state; } /*! - \brief enable the MAC address filter - \param[in] mac_addr: select which MAC address will be enable + \brief enable the MAC address filter + \param[in] mac_addr: select which MAC address will be enable, refer to enet_macaddress_enum \arg ENET_MAC_ADDRESS1: enable MAC address 1 filter \arg ENET_MAC_ADDRESS2: enable MAC address 2 filter \arg ENET_MAC_ADDRESS3: enable MAC address 3 filter @@ -1428,8 +1466,8 @@ void enet_address_filter_enable(enet_macaddress_enum mac_addr) } /*! - \brief disable the MAC address filter - \param[in] mac_addr: select which MAC address will be disable, + \brief disable the MAC address filter + \param[in] mac_addr: select which MAC address will be disable, refer to enet_macaddress_enum only one parameter can be selected which is shown as below \arg ENET_MAC_ADDRESS1: disable MAC address 1 filter \arg ENET_MAC_ADDRESS2: disable MAC address 2 filter @@ -1443,21 +1481,21 @@ void enet_address_filter_disable(enet_macaddress_enum mac_addr) } /*! - \brief configure the MAC address filter - \param[in] mac_addr: select which MAC address will be configured, + \brief configure the MAC address filter + \param[in] mac_addr: select which MAC address will be configured, refer to enet_macaddress_enum only one parameter can be selected which is shown as below \arg ENET_MAC_ADDRESS1: configure MAC address 1 filter \arg ENET_MAC_ADDRESS2: configure MAC address 2 filter \arg ENET_MAC_ADDRESS3: configure MAC address 3 filter - \param[in] addr_mask: select which MAC address bytes will be mask, + \param[in] addr_mask: select which MAC address bytes will be mask one or more parameters can be selected which are shown as below \arg ENET_ADDRESS_MASK_BYTE0: mask ENET_MAC_ADDR1L[7:0] bits - \arg ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits + \arg ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits \arg ENET_ADDRESS_MASK_BYTE2: mask ENET_MAC_ADDR1L[23:16] bits \arg ENET_ADDRESS_MASK_BYTE3: mask ENET_MAC_ADDR1L [31:24] bits \arg ENET_ADDRESS_MASK_BYTE4: mask ENET_MAC_ADDR1H [7:0] bits \arg ENET_ADDRESS_MASK_BYTE5: mask ENET_MAC_ADDR1H [15:8] bits - \param[in] filter_type: select which MAC address filter type will be selected, + \param[in] filter_type: select which MAC address filter type will be selected only one parameter can be selected which is shown as below \arg ENET_ADDRESS_FILTER_SA: The MAC address is used to compared with the SA field of the received frame \arg ENET_ADDRESS_FILTER_DA: The MAC address is used to compared with the DA field of the received frame @@ -1467,7 +1505,7 @@ void enet_address_filter_disable(enet_macaddress_enum mac_addr) void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type) { uint32_t reg; - + /* get the address filter register value which is to be configured */ reg = REG32(ENET_ADDRH_BASE + mac_addr); @@ -1482,21 +1520,21 @@ void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mas \param[in] none \param[out] none \retval ErrStatus: SUCCESS or ERROR -*/ +*/ ErrStatus enet_phy_config(void) { uint32_t ahbclk; uint32_t reg; uint16_t phy_value; ErrStatus enet_state = ERROR; - + /* clear the previous MDC clock */ reg = ENET_MAC_PHY_CTL; reg &= ~ENET_MAC_PHY_CTL_CLR; /* get the HCLK frequency */ ahbclk = rcu_clock_freq_get(CK_AHB); - + /* configure MDC clock according to HCLK frequency range */ if(ENET_RANGE(ahbclk, 20000000U, 35000000U)){ reg |= ENET_MDC_HCLK_DIV16; @@ -1507,7 +1545,7 @@ ErrStatus enet_phy_config(void) }else if(ENET_RANGE(ahbclk, 100000000U, 150000000U)){ reg |= ENET_MDC_HCLK_DIV62; }else if((ENET_RANGE(ahbclk, 150000000U, 200000000U))||(200000000U == ahbclk)){ - reg |= ENET_MDC_HCLK_DIV102; + reg |= ENET_MDC_HCLK_DIV102; }else{ return enet_state; } @@ -1518,9 +1556,9 @@ ErrStatus enet_phy_config(void) if(ERROR == (enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ return enet_state; } - /* PHY reset need some time */ + /* PHY reset need some time */ _ENET_DELAY_(ENET_DELAY_TO); - + /* check whether PHY reset is complete */ if(ERROR == (enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ return enet_state; @@ -1530,18 +1568,18 @@ ErrStatus enet_phy_config(void) if(RESET == (phy_value & PHY_RESET)){ enet_state = SUCCESS; } - + return enet_state; } /*! \brief write to / read from a PHY register - \param[in] direction: only one parameter can be selected which is shown as below + \param[in] direction: only one parameter can be selected which is shown as below, refer to enet_phydirection_enum \arg ENET_PHY_WRITE: write data to phy register \arg ENET_PHY_READ: read data from phy register - \param[in] phy_address: 0x0 - 0x1F - \param[in] phy_reg: 0x0 - 0x1F - \param[in] pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction + \param[in] phy_address: 0x0000 - 0x001F + \param[in] phy_reg: 0x0000 - 0x001F + \param[in] pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction \param[out] pvalue: the value will be read from the PHY register in ENET_PHY_READ direction \retval ErrStatus: SUCCESS or ERROR */ @@ -1551,16 +1589,16 @@ ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_add uint32_t timeout = 0U; ErrStatus enet_state = ERROR; - /* configure ENET_MAC_PHY_CTL with write/read operation */ + /* configure ENET_MAC_PHY_CTL with write/read operation */ reg = ENET_MAC_PHY_CTL; reg &= ~(ENET_MAC_PHY_CTL_PB | ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PR | ENET_MAC_PHY_CTL_PA); - reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB); + reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB); /* if do the write operation, write value to the register */ if(ENET_PHY_WRITE == direction){ - ENET_MAC_PHY_DATA = *pvalue; + ENET_MAC_PHY_DATA = *pvalue; } - + /* do PHY write/read operation, and wait the operation complete */ ENET_MAC_PHY_CTL = reg; do{ @@ -1569,16 +1607,16 @@ ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_add } while((RESET != phy_flag) && (ENET_DELAY_TO != timeout)); - /* write/read operation complete */ + /* write/read operation complete */ if(RESET == (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)){ enet_state = SUCCESS; } - /* if do the read operation, get value from the register */ + /* if do the read operation, get value from the register */ if(ENET_PHY_READ == direction){ - *pvalue = (uint16_t)ENET_MAC_PHY_DATA; + *pvalue = (uint16_t)ENET_MAC_PHY_DATA; } - + return enet_state; } @@ -1594,7 +1632,7 @@ ErrStatus enet_phyloopback_enable(void) ErrStatus phy_state = ERROR; /* get the PHY configuration to update it */ - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); /* enable the PHY loopback mode */ temp_phy |= PHY_LOOPBACK; @@ -1617,7 +1655,7 @@ ErrStatus enet_phyloopback_disable(void) ErrStatus phy_state = ERROR; /* get the PHY configuration to update it */ - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); /* disable the PHY loopback mode */ temp_phy &= (uint16_t)~PHY_LOOPBACK; @@ -1630,7 +1668,7 @@ ErrStatus enet_phyloopback_disable(void) /*! \brief enable ENET forward feature - \param[in] feature: the feature of ENET forward mode, + \param[in] feature: the feature of ENET forward mode one or more parameters can be selected which are shown as below \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames \arg ENET_TYPEFRAME_CRC_DROP: the function that FCS field(last 4 bytes) of frame will be dropped before forwarding @@ -1642,17 +1680,17 @@ ErrStatus enet_phyloopback_disable(void) void enet_forward_feature_enable(uint32_t feature) { uint32_t mask; - + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); ENET_MAC_CFG |= mask; - + mask = (feature & (~(ENET_AUTO_PADCRC_DROP | ENET_TYPEFRAME_CRC_DROP))); ENET_DMA_CTL |= (mask >> 2); } /*! \brief disable ENET forward feature - \param[in] feature: the feature of ENET forward mode, + \param[in] feature: the feature of ENET forward mode one or more parameters can be selected which are shown as below \arg ENET_AUTO_PADCRC_DROP: the automatic zero-quanta generation function \arg ENET_TYPEFRAME_CRC_DROP: the flow control operation in the MAC @@ -1664,17 +1702,17 @@ void enet_forward_feature_enable(uint32_t feature) void enet_forward_feature_disable(uint32_t feature) { uint32_t mask; - + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); ENET_MAC_CFG &= ~mask; - + mask = (feature & (~(ENET_AUTO_PADCRC_DROP | ENET_TYPEFRAME_CRC_DROP))); ENET_DMA_CTL &= ~(mask >> 2); } - -/*! + +/*! \brief enable ENET fliter feature - \param[in] feature: the feature of ENET fliter mode, + \param[in] feature: the feature of ENET fliter mode one or more parameters can be selected which are shown as below \arg ENET_SRC_FILTER: filter source address function \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function @@ -1693,7 +1731,7 @@ void enet_fliter_feature_enable(uint32_t feature) /*! \brief disable ENET fliter feature - \param[in] feature: the feature of ENET fliter mode, + \param[in] feature: the feature of ENET fliter mode one or more parameters can be selected which are shown as below \arg ENET_SRC_FILTER: filter source address function \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function @@ -1717,8 +1755,8 @@ void enet_fliter_feature_disable(uint32_t feature) \param[out] none \retval ErrStatus: ERROR or SUCCESS */ -ErrStatus enet_pauseframe_generate(void) -{ +ErrStatus enet_pauseframe_generate(void) +{ ErrStatus enet_state =ERROR; uint32_t temp = 0U; @@ -1728,16 +1766,16 @@ ErrStatus enet_pauseframe_generate(void) ENET_MAC_FCTL |= ENET_MAC_FCTL_FLCBBKPA; enet_state = SUCCESS; } - return enet_state; + return enet_state; } /*! \brief configure the pause frame detect type - \param[in] detect: pause frame detect type, + \param[in] detect: pause frame detect type only one parameter can be selected which is shown as below \arg ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT: besides the unique multicast address, MAC can also use the MAC0 address to detecting pause frame - \arg ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified + \arg ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified in IEEE802.3 can be detected \param[out] none \retval none @@ -1751,9 +1789,9 @@ void enet_pauseframe_detect_config(uint32_t detect) /*! \brief configure the pause frame parameters \param[in] pausetime: pause time in transmit pause control frame - \param[in] pause_threshold: the threshold of the pause timer for retransmitting frames automatically, - this value must make sure to be less than configured pause time, only one parameter can be - selected which is shown as below + \param[in] pause_threshold: the threshold of the pause timer for retransmitting frames automatically + this value must make sure to be less than configured pause time + only one parameter can be selected which is shown as below \arg ENET_PAUSETIME_MINUS4: pause time minus 4 slot times \arg ENET_PAUSETIME_MINUS28: pause time minus 28 slot times \arg ENET_PAUSETIME_MINUS144: pause time minus 144 slot times @@ -1769,9 +1807,9 @@ void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold) /*! \brief configure the threshold of the flow control(deactive and active threshold) - \param[in] deactive: the threshold of the deactive flow control, this value - should always be less than active flow control value, only one - parameter can be selected which is shown as below + \param[in] deactive: the threshold of the deactive flow control + this value should always be less than active flow control value + only one parameter can be selected which is shown as below \arg ENET_DEACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes \arg ENET_DEACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes \arg ENET_DEACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes @@ -1779,8 +1817,8 @@ void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold) \arg ENET_DEACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes \arg ENET_DEACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes \arg ENET_DEACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes - \param[in] active: the threshold of the active flow control, only one parameter - can be selected which is shown as below + \param[in] active: the threshold of the active flow control + only one parameter can be selected which is shown as below \arg ENET_ACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes \arg ENET_ACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes \arg ENET_ACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes @@ -1793,7 +1831,7 @@ void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold) */ void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active) { - ENET_MAC_FCTH = ((deactive | active) >> 8); + ENET_MAC_FCTH = ((deactive | active) >> 8); } /*! @@ -1838,8 +1876,8 @@ void enet_flowcontrol_feature_disable(uint32_t feature) /*! \brief get the dma transmit/receive process state - \param[in] direction: choose the direction of dma process which users want to check, - refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \param[in] direction: choose the direction of dma process which users want to check, refer to enet_dmadirection_enum + only one parameter can be selected which is shown as below \arg ENET_DMA_TX: dma transmit process \arg ENET_DMA_RX: dma receive process \param[out] none @@ -1857,10 +1895,10 @@ uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction) } /*! - \brief poll the DMA transmission/reception enable by writing any value to the + \brief poll the DMA transmission/reception enable by writing any value to the ENET_DMA_TPEN/ENET_DMA_RPEN register, this will make the DMA to resume transmission/reception - \param[in] direction: choose the direction of DMA process which users want to resume, - refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \param[in] direction: choose the direction of DMA process which users want to resume, refer to enet_dmadirection_enum + only one parameter can be selected which is shown as below \arg ENET_DMA_TX: DMA transmit process \arg ENET_DMA_RX: DMA receive process \param[out] none @@ -1876,7 +1914,7 @@ void enet_dmaprocess_resume(enet_dmadirection_enum direction) } /*! - \brief check and recover the Rx process + \brief check and recover the Rx process \param[in] none \param[out] none \retval none @@ -1885,11 +1923,11 @@ void enet_rxprocess_check_recovery(void) { uint32_t status; - /* get DAV information of current RxDMA descriptor */ + /* get DAV information of current RxDMA descriptor */ status = dma_current_rxdesc->status; status &= ENET_RDES0_DAV; - - /* if current descriptor is owned by DMA, but the descriptor address mismatches with + + /* if current descriptor is owned by DMA, but the descriptor address mismatches with receive descriptor address pointer updated by RxDMA controller */ if((ENET_DMA_CRDADDR != ((uint32_t)dma_current_rxdesc)) && (ENET_RDES0_DAV == status)){ @@ -1908,25 +1946,25 @@ ErrStatus enet_txfifo_flush(void) uint32_t flush_state; uint32_t timeout = 0U; ErrStatus enet_state = ERROR; - + /* set the FTF bit for flushing transmit FIFO */ - ENET_DMA_CTL |= ENET_DMA_CTL_FTF; + ENET_DMA_CTL |= ENET_DMA_CTL_FTF; /* wait until the flush operation completes */ do{ - flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF; + flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF; timeout++; }while((RESET != flush_state) && (timeout < ENET_DELAY_TO)); /* return ERROR due to timeout */ if(RESET == flush_state){ enet_state = SUCCESS; } - + return enet_state; } /*! \brief get the transmit/receive address of current descriptor, or current buffer, or descriptor table - \param[in] addr_get: choose the address which users want to get, refer to enet_desc_reg_enum, + \param[in] addr_get: choose the address which users want to get, refer to enet_desc_reg_enum only one parameter can be selected which is shown as below \arg ENET_RX_DESC_TABLE: the start address of the receive descriptor table \arg ENET_RX_CURRENT_DESC: the start descriptor address of the current receive descriptor read by @@ -1936,7 +1974,7 @@ ErrStatus enet_txfifo_flush(void) \arg ENET_TX_CURRENT_DESC: the start descriptor address of the current transmit descriptor read by the TxDMA controller \arg ENET_TX_CURRENT_BUFFER: the current transmit buffer address being read by the TxDMA controller - \param[out] none + \param[out] none \retval address value */ uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get) @@ -1950,7 +1988,7 @@ uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get) /*! \brief get the Tx or Rx descriptor information \param[in] desc: the descriptor pointer which users want to get information - \param[in] info_get: the descriptor information type which is selected, + \param[in] info_get: the descriptor information type which is selected, refer to enet_descstate_enum only one parameter can be selected which is shown as below \arg RXDESC_BUFFER_1_SIZE: receive buffer 1 size \arg RXDESC_BUFFER_2_SIZE: receive buffer 2 size @@ -1971,25 +2009,30 @@ uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate break; case RXDESC_BUFFER_2_SIZE: reval = GET_RDES1_RB2S(desc->control_buffer_size); - break; - case RXDESC_FRAME_LENGTH: + break; + case RXDESC_FRAME_LENGTH: reval = GET_RDES0_FRML(desc->status); - reval = reval - 4U; - - /* if is a type frame, and CRC is not included in forwarding frame */ - if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (desc->status & ENET_RDES0_FRMT))){ - reval = reval + 4U; - } + if(reval > 4U){ + reval = reval - 4U; + + /* if is a type frame, and CRC is not included in forwarding frame */ + if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (desc->status & ENET_RDES0_FRMT))){ + reval = reval + 4U; + } + }else{ + reval = 0U; + } + break; - case RXDESC_BUFFER_1_ADDR: - reval = desc->buffer1_addr; + case RXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; break; - case TXDESC_BUFFER_1_ADDR: - reval = desc->buffer1_addr; + case TXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; break; - case TXDESC_COLLISION_COUNT: + case TXDESC_COLLISION_COUNT: reval = GET_TDES0_COCNT(desc->status); - break; + break; default: break; } @@ -2006,7 +2049,7 @@ uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) { uint32_t temp_counter = 0U; - + temp_counter = ENET_DMA_MFBOCNT; *rxfifo_drop = GET_DMA_MFBOCNT_MSFA(temp_counter); *rxdma_drop = GET_DMA_MFBOCNT_MSFC(temp_counter); @@ -2015,9 +2058,9 @@ void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) /*! \brief get the bit flag of ENET DMA descriptor \param[in] desc: the descriptor pointer which users want to get flag - \param[in] desc_flag: the bit flag of ENET DMA descriptor, + \param[in] desc_flag: the bit flag of ENET DMA descriptor only one parameter can be selected which is shown as below - \arg ENET_TDES0_DB: deferred + \arg ENET_TDES0_DB: deferred \arg ENET_TDES0_UFE: underflow error \arg ENET_TDES0_EXD: excessive deferral \arg ENET_TDES0_VFRM: VLAN frame @@ -2030,18 +2073,18 @@ void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) \arg ENET_TDES0_JT: jabber timeout \arg ENET_TDES0_ES: error summary \arg ENET_TDES0_IPHE: IP header error - \arg ENET_TDES0_TTMSS: transmit timestamp status + \arg ENET_TDES0_TTMSS: transmit timestamp status \arg ENET_TDES0_TCHM: the second address chained mode \arg ENET_TDES0_TERM: transmit end of ring mode \arg ENET_TDES0_TTSEN: transmit timestamp function enable - \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DPAD: disable adding pad \arg ENET_TDES0_DCRC: disable CRC \arg ENET_TDES0_FSG: first segment \arg ENET_TDES0_LSG: last segment \arg ENET_TDES0_INTC: interrupt on completion \arg ENET_TDES0_DAV: DAV bit - - \arg ENET_RDES0_PCERR: payload checksum error + + \arg ENET_RDES0_PCERR: payload checksum error \arg ENET_RDES0_EXSV: extended status valid \arg ENET_RDES0_CERR: CRC error \arg ENET_RDES0_DBERR: dribble bit error @@ -2054,11 +2097,11 @@ void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) \arg ENET_RDES0_LDES: last descriptor \arg ENET_RDES0_FDES: first descriptor \arg ENET_RDES0_VTAG: VLAN tag - \arg ENET_RDES0_OERR: overflow error + \arg ENET_RDES0_OERR: overflow error \arg ENET_RDES0_LERR: length error \arg ENET_RDES0_SAFF: SA filter fail \arg ENET_RDES0_DERR: descriptor error - \arg ENET_RDES0_ERRS: error summary + \arg ENET_RDES0_ERRS: error summary \arg ENET_RDES0_DAFF: destination address filter fail \arg ENET_RDES0_DAV: descriptor available \param[out] none @@ -2067,7 +2110,7 @@ void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) { FlagStatus enet_flag = RESET; - + if ((uint32_t)RESET != (desc->status & desc_flag)){ enet_flag = SET; } @@ -2078,20 +2121,20 @@ FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) /*! \brief set the bit flag of ENET DMA descriptor \param[in] desc: the descriptor pointer which users want to set flag - \param[in] desc_flag: the bit flag of ENET DMA descriptor, + \param[in] desc_flag: the bit flag of ENET DMA descriptor only one parameter can be selected which is shown as below \arg ENET_TDES0_VFRM: VLAN frame \arg ENET_TDES0_FRMF: frame flushed \arg ENET_TDES0_TCHM: the second address chained mode \arg ENET_TDES0_TERM: transmit end of ring mode \arg ENET_TDES0_TTSEN: transmit timestamp function enable - \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DPAD: disable adding pad \arg ENET_TDES0_DCRC: disable CRC \arg ENET_TDES0_FSG: first segment \arg ENET_TDES0_LSG: last segment \arg ENET_TDES0_INTC: interrupt on completion \arg ENET_TDES0_DAV: DAV bit - \arg ENET_RDES0_DAV: descriptor available + \arg ENET_RDES0_DAV: descriptor available \param[out] none \retval none */ @@ -2103,20 +2146,20 @@ void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag) /*! \brief clear the bit flag of ENET DMA descriptor \param[in] desc: the descriptor pointer which users want to clear flag - \param[in] desc_flag: the bit flag of ENET DMA descriptor, + \param[in] desc_flag: the bit flag of ENET DMA descriptor only one parameter can be selected which is shown as below \arg ENET_TDES0_VFRM: VLAN frame \arg ENET_TDES0_FRMF: frame flushed \arg ENET_TDES0_TCHM: the second address chained mode \arg ENET_TDES0_TERM: transmit end of ring mode \arg ENET_TDES0_TTSEN: transmit timestamp function enable - \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DPAD: disable adding pad \arg ENET_TDES0_DCRC: disable CRC \arg ENET_TDES0_FSG: first segment \arg ENET_TDES0_LSG: last segment \arg ENET_TDES0_INTC: interrupt on completion \arg ENET_TDES0_DAV: DAV bit - \arg ENET_RDES0_DAV: descriptor available + \arg ENET_RDES0_DAV: descriptor available \param[out] none \retval none */ @@ -2126,7 +2169,7 @@ void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag) } /*! - \brief when receiving completed, set RS bit in ENET_DMA_STAT register will immediately set + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will immediately set \param[in] desc: the descriptor pointer which users want to configure \param[out] none \retval none @@ -2137,9 +2180,9 @@ void enet_rx_desc_immediate_receive_complete_interrupt(enet_descriptors_struct * } /*! - \brief when receiving completed, set RS bit in ENET_DMA_STAT register will is set after a configurable delay time + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will is set after a configurable delay time \param[in] desc: the descriptor pointer which users want to configure - \param[in] delay_time: delay a time of 256*delay_time HCLK, this value must be between 0 and 0xFF + \param[in] delay_time: delay a time of 256*delay_time HCLK(0x00000000 - 0x000000FF) \param[out] none \retval none */ @@ -2158,10 +2201,10 @@ void enet_rx_desc_delay_receive_complete_interrupt(enet_descriptors_struct *desc void enet_rxframe_drop(void) { /* enable reception, descriptor is owned by DMA */ - dma_current_rxdesc->status = ENET_RDES0_DAV; - + dma_current_rxdesc->status = ENET_RDES0_DAV; + /* chained mode */ - if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ if(NULL != dma_current_ptp_rxdesc){ dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); /* if it is the last ptp descriptor */ @@ -2175,9 +2218,9 @@ void enet_rxframe_drop(void) }else{ dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); } - + }else{ - /* ring mode */ + /* ring mode */ if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ /* if is the last descriptor in table, the next descriptor is the table header */ dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); @@ -2196,9 +2239,9 @@ void enet_rxframe_drop(void) /*! \brief enable DMA feature - \param[in] feature: the feature of DMA mode, + \param[in] feature: the feature of DMA mode one or more parameters can be selected which are shown as below - \arg ENET_FLUSH_RXFRAME: RxDMA flushes frames function + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function \param[out] none \retval none @@ -2210,9 +2253,9 @@ void enet_dma_feature_enable(uint32_t feature) /*! \brief disable DMA feature - \param[in] feature: the feature of DMA mode, + \param[in] feature: the feature of DMA mode one or more parameters can be selected which are shown as below - \arg ENET_FLUSH_RXFRAME: RxDMA flushes frames function + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function \param[out] none \retval none @@ -2226,7 +2269,7 @@ void enet_dma_feature_disable(uint32_t feature) /*! \brief get the bit of extended status flag in ENET DMA descriptor \param[in] desc: the descriptor pointer which users want to get the extended status flag - \param[in] desc_status: the extended status want to get, + \param[in] desc_status: the extended status want to get only one parameter can be selected which is shown as below \arg ENET_RDES4_IPPLDT: IP frame payload type \arg ENET_RDES4_IPHERR: IP frame header error @@ -2243,7 +2286,7 @@ void enet_dma_feature_disable(uint32_t feature) uint32_t enet_rx_desc_enhanced_status_get(enet_descriptors_struct *desc, uint32_t desc_status) { uint32_t reval = 0xFFFFFFFFU; - + switch (desc_status){ case ENET_RDES4_IPPLDT: reval = GET_RDES4_IPPLDT(desc->extended_status); @@ -2256,9 +2299,9 @@ uint32_t enet_rx_desc_enhanced_status_get(enet_descriptors_struct *desc, uint32_ reval = 1U; }else{ reval = 0U; - } + } } - + return reval; } @@ -2275,7 +2318,7 @@ void enet_desc_select_enhanced_mode(void) /*! \brief initialize the DMA Tx/Rx descriptors's parameters in enhanced chain mode with ptp function - \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum only one parameter can be selected which is shown as below \arg ENET_DMA_TX: DMA Tx descriptors \arg ENET_DMA_RX: DMA Rx descriptors @@ -2288,18 +2331,18 @@ void enet_ptp_enhanced_descriptors_chain_init(enet_dmadirection_enum direction) uint32_t desc_status = 0U, desc_bufsize = 0U; enet_descriptors_struct *desc, *desc_tab; uint8_t *buf; - + /* if want to initialize DMA Tx descriptors */ if (ENET_DMA_TX == direction){ /* save a copy of the DMA Tx descriptors */ desc_tab = txdesc_tab; buf = &tx_buff[0][0]; count = ENET_TXBUF_NUM; - maxsize = ENET_TXBUF_SIZE; - + maxsize = ENET_TXBUF_SIZE; + /* select chain mode, and enable transmit timestamp function */ desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN; - + /* configure DMA Tx descriptor table address register */ ENET_DMA_TDTADDR = (uint32_t)desc_tab; dma_current_txdesc = desc_tab; @@ -2309,43 +2352,43 @@ void enet_ptp_enhanced_descriptors_chain_init(enet_dmadirection_enum direction) desc_tab = rxdesc_tab; buf = &rx_buff[0][0]; count = ENET_RXBUF_NUM; - maxsize = ENET_RXBUF_SIZE; - + maxsize = ENET_RXBUF_SIZE; + /* enable receiving */ desc_status = ENET_RDES0_DAV; /* select receive chained mode and set buffer1 size */ desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; - + /* configure DMA Rx descriptor table address register */ ENET_DMA_RDTADDR = (uint32_t)desc_tab; - dma_current_rxdesc = desc_tab; + dma_current_rxdesc = desc_tab; } - - /* configuration each descriptor */ + + /* configuration each descriptor */ for(num = 0U; num < count; num++){ /* get the pointer to the next descriptor of the descriptor table */ desc = desc_tab + num; /* configure descriptors */ - desc->status = desc_status; + desc->status = desc_status; desc->control_buffer_size = desc_bufsize; desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); - + /* if is not the last descriptor */ if(num < (count - 1U)){ /* configure the next descriptor address */ desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); }else{ - /* when it is the last descriptor, the next descriptor address - equals to first descriptor address in descriptor table */ - desc->buffer2_next_desc_addr = (uint32_t)desc_tab; + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t)desc_tab; } - } + } } /*! \brief initialize the DMA Tx/Rx descriptors's parameters in enhanced ring mode with ptp function - \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum only one parameter can be selected which is shown as below \arg ENET_DMA_TX: DMA Tx descriptors \arg ENET_DMA_RX: DMA Rx descriptors @@ -2358,23 +2401,23 @@ void enet_ptp_enhanced_descriptors_ring_init(enet_dmadirection_enum direction) uint32_t desc_status = 0U, desc_bufsize = 0U; enet_descriptors_struct *desc; enet_descriptors_struct *desc_tab; - uint8_t *buf; - + uint8_t *buf; + /* configure descriptor skip length */ ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); - + /* if want to initialize DMA Tx descriptors */ if (ENET_DMA_TX == direction){ /* save a copy of the DMA Tx descriptors */ desc_tab = txdesc_tab; buf = &tx_buff[0][0]; count = ENET_TXBUF_NUM; - maxsize = ENET_TXBUF_SIZE; + maxsize = ENET_TXBUF_SIZE; /* select ring mode, and enable transmit timestamp function */ desc_status = ENET_TDES0_TTSEN; - + /* configure DMA Tx descriptor table address register */ ENET_DMA_TDTADDR = (uint32_t)desc_tab; dma_current_txdesc = desc_tab; @@ -2384,43 +2427,43 @@ void enet_ptp_enhanced_descriptors_ring_init(enet_dmadirection_enum direction) desc_tab = rxdesc_tab; buf = &rx_buff[0][0]; count = ENET_RXBUF_NUM; - maxsize = ENET_RXBUF_SIZE; - + maxsize = ENET_RXBUF_SIZE; + /* enable receiving */ desc_status = ENET_RDES0_DAV; /* set buffer1 size */ desc_bufsize = ENET_RXBUF_SIZE; - + /* configure DMA Rx descriptor table address register */ ENET_DMA_RDTADDR = (uint32_t)desc_tab; - dma_current_rxdesc = desc_tab; + dma_current_rxdesc = desc_tab; } - - /* configure each descriptor */ + + /* configure each descriptor */ for(num=0U; num < count; num++){ /* get the pointer to the next descriptor of the descriptor table */ desc = desc_tab + num; /* configure descriptors */ - desc->status = desc_status; - desc->control_buffer_size = desc_bufsize; - desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); - + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + /* when it is the last descriptor */ if(num == (count - 1U)){ if (ENET_DMA_TX == direction){ - /* configure transmit end of ring mode */ + /* configure transmit end of ring mode */ desc->status |= ENET_TDES0_TERM; }else{ /* configure receive end of ring mode */ desc->control_buffer_size |= ENET_RDES1_RERM; } } - } + } } /*! - \brief receive a packet data with timestamp values to application buffer, when the DMA is in enhanced mode + \brief receive a packet data with timestamp values to application buffer, when the DMA is in enhanced mode \param[in] bufsize: the size of buffer which is the parameter in function \param[out] buffer: pointer to the application buffer note -- if the input is NULL, user should copy data in application by himself @@ -2433,26 +2476,26 @@ ErrStatus enet_ptpframe_receive_enhanced_mode(uint8_t *buffer, uint32_t bufsize, uint32_t offset = 0U, size = 0U; uint32_t timeout = 0U; uint32_t rdes0_tsv_flag; - + /* the descriptor is busy due to own by the DMA */ if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ - return ERROR; + return ERROR; } - + /* if buffer pointer is null, indicates that users has copied data in application */ if(NULL != buffer){ - /* if no error occurs, and the frame uses only one descriptor */ - if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && - ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && - ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + /* if no error occurs, and the frame uses only one descriptor */ + if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ /* get the frame length except CRC */ size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U; - /* if is a type frame, and CRC is not included in forwarding frame */ + /* if is a type frame, and CRC is not included in forwarding frame */ if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))){ size = size + 4U; } - + /* to avoid situation that the frame size exceeds the buffer length */ if(size > bufsize){ return ERROR; @@ -2465,22 +2508,22 @@ ErrStatus enet_ptpframe_receive_enhanced_mode(uint8_t *buffer, uint32_t bufsize, }else{ return ERROR; } - } - + } + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ if(NULL != timestamp){ /* wait for ENET_RDES0_TSV flag to be set, the timestamp value is taken and write to the RDES6 and RDES7 */ - do{ + do{ rdes0_tsv_flag = (dma_current_rxdesc->status & ENET_RDES0_TSV); timeout++; }while ((RESET == rdes0_tsv_flag) && (timeout < ENET_DELAY_TO)); - + /* return ERROR due to timeout */ if(ENET_DELAY_TO == timeout){ return ERROR; } - + /* clear the ENET_RDES0_TSV flag */ dma_current_rxdesc->status &= ~ENET_RDES0_TSV; /* get the timestamp value of the received frame */ @@ -2490,7 +2533,7 @@ ErrStatus enet_ptpframe_receive_enhanced_mode(uint8_t *buffer, uint32_t bufsize, /* enable reception, descriptor is owned by DMA */ dma_current_rxdesc->status = ENET_RDES0_DAV; - + /* check Rx buffer unavailable flag status */ if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ /* Clear RBU flag */ @@ -2498,33 +2541,32 @@ ErrStatus enet_ptpframe_receive_enhanced_mode(uint8_t *buffer, uint32_t bufsize, /* resume DMA reception by writing to the RPEN register*/ ENET_DMA_RPEN = 0; } - - /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ /* chained mode */ - if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ - dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); - }else{ - /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ /* if is the last descriptor in table, the next descriptor is the table header */ - dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); - }else{ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + }else{ /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ - dma_current_rxdesc = (enet_descriptors_struct*) ((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_rxdesc = (enet_descriptors_struct*) ((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); } } - + return SUCCESS; } /*! - \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in enhanced mode + \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in enhanced mode \param[in] buffer: pointer on the application buffer note -- if the input is NULL, user should copy data in application by himself \param[in] length: the length of frame data to be transmitted \param[out] timestamp: pointer to the table which stores the timestamp high and low note -- if the input is NULL, timestamp is ignored - \param[out] none \retval ErrStatus: SUCCESS or ERROR */ ErrStatus enet_ptpframe_transmit_enhanced_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]) @@ -2532,17 +2574,17 @@ ErrStatus enet_ptpframe_transmit_enhanced_mode(uint8_t *buffer, uint32_t length, uint32_t offset = 0; uint32_t dma_tbu_flag, dma_tu_flag; uint32_t tdes0_ttmss_flag; - uint32_t timeout = 0; - + uint32_t timeout = 0; + /* the descriptor is busy due to own by the DMA */ if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ return ERROR; } - + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ if(length > ENET_MAX_FRAME_SIZE){ return ERROR; - } + } /* if buffer pointer is null, indicates that users has handled data in application */ if(NULL != buffer){ @@ -2553,22 +2595,22 @@ ErrStatus enet_ptpframe_transmit_enhanced_mode(uint8_t *buffer, uint32_t length, } /* set the frame length */ dma_current_txdesc->control_buffer_size = length; - /* set the segment of frame, frame is transmitted in one descriptor */ + /* set the segment of frame, frame is transmitted in one descriptor */ dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; /* enable the DMA transmission */ dma_current_txdesc->status |= ENET_TDES0_DAV; /* check Tx buffer unavailable flag status */ - dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); - + if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ /* Clear TBU and TU flag */ ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); /* resume DMA transmission by writing to the TPEN register*/ ENET_DMA_TPEN = 0; } - + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ if(NULL != timestamp){ /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */ @@ -2576,12 +2618,12 @@ ErrStatus enet_ptpframe_transmit_enhanced_mode(uint8_t *buffer, uint32_t length, tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); timeout++; }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); - + /* return ERROR due to timeout */ if(ENET_DELAY_TO == timeout){ return ERROR; } - + /* clear the ENET_TDES0_TTMSS flag */ dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; /* get the timestamp value of the transmit frame */ @@ -2589,16 +2631,16 @@ ErrStatus enet_ptpframe_transmit_enhanced_mode(uint8_t *buffer, uint32_t length, timestamp[1] = dma_current_txdesc->timestamp_high; } - /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ /* chained mode */ - if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ - dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); }else{ - /* ring mode */ + /* ring mode */ if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ /* if is the last descriptor in table, the next descriptor is the table header */ - dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); - }else{ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + }else{ /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ dma_current_txdesc = (enet_descriptors_struct*) ((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); } @@ -2622,7 +2664,7 @@ void enet_desc_select_normal_mode(void) /*! \brief initialize the DMA Tx/Rx descriptors's parameters in normal chain mode with PTP function - \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum only one parameter can be selected which is shown as below \arg ENET_DMA_TX: DMA Tx descriptors \arg ENET_DMA_RX: DMA Rx descriptors @@ -2636,18 +2678,18 @@ void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, en uint32_t desc_status = 0U, desc_bufsize = 0U; enet_descriptors_struct *desc, *desc_tab; uint8_t *buf; - + /* if want to initialize DMA Tx descriptors */ if (ENET_DMA_TX == direction){ /* save a copy of the DMA Tx descriptors */ desc_tab = txdesc_tab; buf = &tx_buff[0][0]; count = ENET_TXBUF_NUM; - maxsize = ENET_TXBUF_SIZE; - + maxsize = ENET_TXBUF_SIZE; + /* select chain mode, and enable transmit timestamp function */ desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN; - + /* configure DMA Tx descriptor table address register */ ENET_DMA_TDTADDR = (uint32_t)desc_tab; dma_current_txdesc = desc_tab; @@ -2658,50 +2700,50 @@ void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, en desc_tab = rxdesc_tab; buf = &rx_buff[0][0]; count = ENET_RXBUF_NUM; - maxsize = ENET_RXBUF_SIZE; - + maxsize = ENET_RXBUF_SIZE; + /* enable receiving */ desc_status = ENET_RDES0_DAV; /* select receive chained mode and set buffer1 size */ desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; - + /* configure DMA Rx descriptor table address register */ ENET_DMA_RDTADDR = (uint32_t)desc_tab; dma_current_rxdesc = desc_tab; - dma_current_ptp_rxdesc = desc_ptptab; + dma_current_ptp_rxdesc = desc_ptptab; } - - /* configure each descriptor */ + + /* configure each descriptor */ for(num = 0U; num < count; num++){ /* get the pointer to the next descriptor of the descriptor table */ desc = desc_tab + num; /* configure descriptors */ - desc->status = desc_status; + desc->status = desc_status; desc->control_buffer_size = desc_bufsize; desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); - + /* if is not the last descriptor */ if(num < (count - 1U)){ /* configure the next descriptor address */ desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); }else{ - /* when it is the last descriptor, the next descriptor address - equals to first descriptor address in descriptor table */ - desc->buffer2_next_desc_addr = (uint32_t)desc_tab; + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t)desc_tab; } /* set desc_ptptab equal to desc_tab */ (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; - } - /* when it is the last ptp descriptor, preserve the first descriptor + } + /* when it is the last ptp descriptor, preserve the first descriptor address of desc_ptptab in ptp descriptor status */ (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; } /*! \brief initialize the DMA Tx/Rx descriptors's parameters in normal ring mode with PTP function - \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum only one parameter can be selected which is shown as below \arg ENET_DMA_TX: DMA Tx descriptors \arg ENET_DMA_RX: DMA Rx descriptors @@ -2719,18 +2761,18 @@ void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, ene /* configure descriptor skip length */ ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); - + /* if want to initialize DMA Tx descriptors */ if (ENET_DMA_TX == direction){ /* save a copy of the DMA Tx descriptors */ desc_tab = txdesc_tab; buf = &tx_buff[0][0]; count = ENET_TXBUF_NUM; - maxsize = ENET_TXBUF_SIZE; - + maxsize = ENET_TXBUF_SIZE; + /* select ring mode, and enable transmit timestamp function */ desc_status = ENET_TDES0_TTSEN; - + /* configure DMA Tx descriptor table address register */ ENET_DMA_TDTADDR = (uint32_t)desc_tab; dma_current_txdesc = desc_tab; @@ -2741,33 +2783,33 @@ void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, ene desc_tab = rxdesc_tab; buf = &rx_buff[0][0]; count = ENET_RXBUF_NUM; - maxsize = ENET_RXBUF_SIZE; - + maxsize = ENET_RXBUF_SIZE; + /* enable receiving */ desc_status = ENET_RDES0_DAV; /* select receive ring mode and set buffer1 size */ desc_bufsize = (uint32_t)ENET_RXBUF_SIZE; - + /* configure DMA Rx descriptor table address register */ ENET_DMA_RDTADDR = (uint32_t)desc_tab; dma_current_rxdesc = desc_tab; - dma_current_ptp_rxdesc = desc_ptptab; + dma_current_ptp_rxdesc = desc_ptptab; } - - /* configure each descriptor */ + + /* configure each descriptor */ for(num = 0U; num < count; num++){ /* get the pointer to the next descriptor of the descriptor table */ desc = desc_tab + num; /* configure descriptors */ - desc->status = desc_status; + desc->status = desc_status; desc->control_buffer_size = desc_bufsize; desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); - + /* when it is the last descriptor */ if(num == (count - 1U)){ if (ENET_DMA_TX == direction){ - /* configure transmit end of ring mode */ + /* configure transmit end of ring mode */ desc->status |= ENET_TDES0_TERM; }else{ /* configure receive end of ring mode */ @@ -2777,43 +2819,43 @@ void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, ene /* set desc_ptptab equal to desc_tab */ (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; - } - /* when it is the last ptp descriptor, preserve the first descriptor + } + /* when it is the last ptp descriptor, preserve the first descriptor address of desc_ptptab in ptp descriptor status */ (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; } /*! - \brief receive a packet data with timestamp values to application buffer, when the DMA is in normal mode + \brief receive a packet data with timestamp values to application buffer, when the DMA is in normal mode \param[in] bufsize: the size of buffer which is the parameter in function - \param[out] timestamp: pointer to the table which stores the timestamp high and low \param[out] buffer: pointer to the application buffer note -- if the input is NULL, user should copy data in application by himself + \param[out] timestamp: pointer to the table which stores the timestamp high and low \retval ErrStatus: SUCCESS or ERROR */ ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]) { uint32_t offset = 0U, size = 0U; - + /* the descriptor is busy due to own by the DMA */ if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ return ERROR; } - + /* if buffer pointer is null, indicates that users has copied data in application */ if(NULL != buffer){ /* if no error occurs, and the frame uses only one descriptor */ if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ - + /* get the frame length except CRC */ size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U; /* if is a type frame, and CRC is not included in forwarding frame */ if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))){ size = size + 4U; } - + /* to avoid situation that the frame size exceeds the buffer length */ if(size > bufsize){ return ERROR; @@ -2823,7 +2865,7 @@ ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, u for(offset = 0U; offset < size; offset++){ (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_rxdesc->buffer1_addr) + offset)); } - + }else{ return ERROR; } @@ -2834,10 +2876,10 @@ ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, u dma_current_rxdesc->buffer1_addr = dma_current_ptp_rxdesc ->buffer1_addr ; dma_current_rxdesc->buffer2_next_desc_addr = dma_current_ptp_rxdesc ->buffer2_next_desc_addr; - + /* enable reception, descriptor is owned by DMA */ dma_current_rxdesc->status = ENET_RDES0_DAV; - + /* check Rx buffer unavailable flag status */ if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ /* clear RBU flag */ @@ -2845,9 +2887,9 @@ ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, u /* resume DMA reception by writing to the RPEN register*/ ENET_DMA_RPEN = 0U; } - - /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ /* chained mode */ if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); @@ -2860,16 +2902,16 @@ ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, u dma_current_ptp_rxdesc++; } }else{ - /* ring mode */ + /* ring mode */ if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ /* if is the last descriptor in table, the next descriptor is the table header */ dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); /* RDES2 and RDES3 will not be covered by buffer address, so do not need to preserve a new table, use the same table with RxDMA descriptor */ - dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); }else{ /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ - dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); dma_current_ptp_rxdesc ++; } } @@ -2878,7 +2920,7 @@ ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, u } /*! - \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode + \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode \param[in] buffer: pointer on the application buffer note -- if the input is NULL, user should copy data in application by himself \param[in] length: the length of frame data to be transmitted @@ -2889,8 +2931,8 @@ ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, u ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]) { uint32_t offset = 0U, timeout = 0U; - uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag; - + uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag; + /* the descriptor is busy due to own by the DMA */ if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ return ERROR; @@ -2900,7 +2942,7 @@ ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, u if(length > ENET_MAX_FRAME_SIZE){ return ERROR; } - + /* if buffer pointer is null, indicates that users has handled data in application */ if(NULL != buffer){ /* copy frame data from application buffer to Tx buffer */ @@ -2914,31 +2956,31 @@ ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, u dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; /* enable the DMA transmission */ dma_current_txdesc->status |= ENET_TDES0_DAV; - + /* check Tx buffer unavailable flag status */ - dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); - + if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ /* clear TBU and TU flag */ ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); /* resume DMA transmission by writing to the TPEN register*/ ENET_DMA_TPEN = 0U; } - + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ if(NULL != timestamp){ /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */ - do{ + do{ tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); timeout++; }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); - + /* return ERROR due to timeout */ if(ENET_DELAY_TO == timeout){ return ERROR; - } - + } + /* clear the ENET_TDES0_TTMSS flag */ dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; /* get the timestamp value of the transmit frame */ @@ -2948,12 +2990,12 @@ ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, u dma_current_txdesc->buffer1_addr = dma_current_ptp_txdesc ->buffer1_addr ; dma_current_txdesc->buffer2_next_desc_addr = dma_current_ptp_txdesc ->buffer2_next_desc_addr; - /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table */ + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table */ /* chained mode */ - if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ dma_current_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->buffer2_next_desc_addr); /* if it is the last ptp descriptor */ - if(0U != dma_current_ptp_txdesc->status){ + if(0U != dma_current_ptp_txdesc->status){ /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); }else{ @@ -2961,17 +3003,17 @@ ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, u dma_current_ptp_txdesc++; } }else{ - /* ring mode */ + /* ring mode */ if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ /* if is the last descriptor in table, the next descriptor is the table header */ - dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); /* TDES2 and TDES3 will not be covered by buffer address, so do not need to preserve a new table, use the same table with TxDMA descriptor */ dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); }else{ /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ - dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); - dma_current_ptp_txdesc ++; + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_txdesc ++; } } return SUCCESS; @@ -2980,7 +3022,7 @@ ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, u #endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ /*! - \brief wakeup frame filter register pointer reset + \brief wakeup frame filter register pointer reset \param[in] none \param[out] none \retval none @@ -2991,7 +3033,7 @@ void enet_wum_filter_register_pointer_reset(void) } /*! - \brief set the remote wakeup frame registers + \brief set the remote wakeup frame registers \param[in] pdata: pointer to buffer data which is written to remote wakeup frame registers (8 words total) \param[out] none \retval none @@ -2999,7 +3041,7 @@ void enet_wum_filter_register_pointer_reset(void) void enet_wum_filter_config(uint32_t pdata[]) { uint32_t num = 0U; - + /* configure ENET_MAC_RWFF register */ for(num = 0U; num < ETH_WAKEUP_REGISTER_LENGTH; num++){ ENET_MAC_RWFF = pdata[num]; @@ -3007,8 +3049,9 @@ void enet_wum_filter_config(uint32_t pdata[]) } /*! - \brief enable wakeup management features - \param[in] feature: one or more parameters can be selected which are shown as below + \brief enable wakeup management features + \param[in] feature: the wake up type which is selected + one or more parameters can be selected which are shown as below \arg ENET_WUM_POWER_DOWN: power down mode \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception @@ -3022,8 +3065,9 @@ void enet_wum_feature_enable(uint32_t feature) } /*! - \brief disable wakeup management features - \param[in] feature: one or more parameters can be selected which are shown as below + \brief disable wakeup management features + \param[in] feature: the wake up type which is selected + one or more parameters can be selected which are shown as below \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame @@ -3036,8 +3080,8 @@ void enet_wum_feature_disable(uint32_t feature) } /*! - \brief reset the MAC statistics counters - \param[in] none + \brief reset the MAC statistics counters + \param[in] none \param[out] none \retval none */ @@ -3049,7 +3093,8 @@ void enet_msc_counters_reset(void) /*! \brief enable the MAC statistics counter features - \param[in] feature: one or more parameters can be selected which are shown as below + \param[in] feature: the feature of MAC statistics counter + one or more parameters can be selected which are shown as below \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover \arg ENET_MSC_RESET_ON_READ: reset on read \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze @@ -3063,7 +3108,8 @@ void enet_msc_feature_enable(uint32_t feature) /*! \brief disable the MAC statistics counter features - \param[in] feature: one or more parameters can be selected which are shown as below + \param[in] feature: the feature of MAC statistics counter + one or more parameters can be selected which are shown as below \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover \arg ENET_MSC_RESET_ON_READ: reset on read \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze @@ -3076,8 +3122,8 @@ void enet_msc_feature_disable(uint32_t feature) } /*! - \brief configure MAC statistics counters preset mode - \param[in] mode: MSC counters preset mode, refer to enet_msc_preset_enum, + \brief configure MAC statistics counters preset mode + \param[in] mode: MSC counters preset mode, refer to enet_msc_preset_enum only one parameter can be selected which is shown as below \arg ENET_MSC_PRESET_NONE: do not preset MSC counter \arg ENET_MSC_PRESET_HALF: preset all MSC counters to almost-half(0x7FFF FFF0) value @@ -3092,8 +3138,8 @@ void enet_msc_counters_preset_config(enet_msc_preset_enum mode) } /*! - \brief get MAC statistics counter - \param[in] counter: MSC counters which is selected, refer to enet_msc_counter_enum, + \brief get MAC statistics counter + \param[in] counter: MSC counters which is selected, refer to enet_msc_counter_enum only one parameter can be selected which is shown as below \arg ENET_MSC_TX_SCCNT: MSC transmitted good frames after a single collision counter \arg ENET_MSC_TX_MSCCNT: MSC transmitted good frames after more than a single collision counter @@ -3107,9 +3153,9 @@ void enet_msc_counters_preset_config(enet_msc_preset_enum mode) uint32_t enet_msc_counters_get(enet_msc_counter_enum counter) { uint32_t reval; - + reval = REG32((ENET + (uint32_t)counter)); - + return reval; } @@ -3153,7 +3199,8 @@ void enet_ptp_feature_disable(uint32_t feature) /*! \brief configure the PTP timestamp function - \param[in] func: only one parameter can be selected which is shown as below + \param[in] func: the function of PTP timestamp + only one parameter can be selected which is shown as below \arg ENET_CKNT_ORDINARY: type of ordinary clock node type for timestamp \arg ENET_CKNT_BOUNDARY: type of boundary clock node type for timestamp \arg ENET_CKNT_END_TO_END: type of end-to-end transparent clock node type for timestamp @@ -3168,7 +3215,7 @@ void enet_ptp_feature_disable(uint32_t feature) \arg ENET_SNOOPING_PTP_VERSION_2: version 2 \arg ENET_SNOOPING_PTP_VERSION_1: version 1 \arg ENET_EVENT_TYPE_MESSAGES_SNAPSHOT: only event type messages are taken snapshot - \arg ENET_ALL_TYPE_MESSAGES_SNAPSHOT: all type messages are taken snapshot except announce, + \arg ENET_ALL_TYPE_MESSAGES_SNAPSHOT: all type messages are taken snapshot except announce, management and signaling message \arg ENET_MASTER_NODE_MESSAGE_SNAPSHOT: snapshot is only take for master node message \arg ENET_SLAVE_NODE_MESSAGE_SNAPSHOT: snapshot is only taken for slave node message @@ -3189,10 +3236,10 @@ ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) ENET_PTP_TSCTL &= ~ENET_PTP_TSCTL_CKNT; ENET_PTP_TSCTL |= (uint32_t)func; break; - case ENET_PTP_ADDEND_UPDATE: + case ENET_PTP_ADDEND_UPDATE: /* this bit must be read as zero before application set it */ do{ - temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU; + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU; timeout++; }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); /* return ERROR due to timeout */ @@ -3200,12 +3247,12 @@ ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) enet_state = ERROR; }else{ ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSARU; - } + } break; case ENET_PTP_SYSTIME_UPDATE: /* both the TMSSTU and TMSSTI bits must be read as zero before application set this bit */ do{ - temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI); + temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI); timeout++; }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); /* return ERROR due to timeout */ @@ -3213,12 +3260,12 @@ ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) enet_state = ERROR; }else{ ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTU; - } - break; + } + break; case ENET_PTP_SYSTIME_INIT: /* this bit must be read as zero before application set it */ do{ - temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI; + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI; timeout++; }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); /* return ERROR due to timeout */ @@ -3226,16 +3273,16 @@ ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) enet_state = ERROR; }else{ ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTI; - } - break; - default: - temp_config = (uint32_t)func & (~BIT(31)); - if(RESET != ((uint32_t)func & BIT(31))){ - ENET_PTP_TSCTL |= temp_config; - }else{ - ENET_PTP_TSCTL &= ~temp_config; } - break; + break; + default: + temp_config = (uint32_t)func & (~BIT(31)); + if(RESET != ((uint32_t)func & BIT(31))){ + ENET_PTP_TSCTL |= temp_config; + }else{ + ENET_PTP_TSCTL &= ~temp_config; + } + break; } return enet_state; @@ -3243,8 +3290,7 @@ ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) /*! \brief configure system time subsecond increment value - \param[in] subsecond: the value will be added to the subsecond value of system time, - this value must be between 0 and 0xFF + \param[in] subsecond: the value will be added to the subsecond value of system time(0x00000000 - 0x000000FF) \param[out] none \retval none */ @@ -3266,12 +3312,12 @@ void enet_ptp_timestamp_addend_config(uint32_t add) /*! \brief initialize or add/subtract to second of the system time - \param[in] sign: timestamp update positive or negative sign, + \param[in] sign: timestamp update positive or negative sign only one parameter can be selected which is shown as below \arg ENET_PTP_ADD_TO_TIME: timestamp update value is added to system time \arg ENET_PTP_SUBSTRACT_FROM_TIME: timestamp update value is subtracted from system time \param[in] second: initializing or adding/subtracting to second of the system time - \param[in] subsecond: the current subsecond of the system time + \param[in] subsecond: the current subsecond of the system time with 0.46 ns accuracy if required accuracy is 20 ns \param[out] none \retval none @@ -3279,7 +3325,7 @@ void enet_ptp_timestamp_addend_config(uint32_t add) void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond) { ENET_PTP_TSUH = second; - ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond); + ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond); } /*! @@ -3298,7 +3344,7 @@ void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond) /*! \brief get the current system time \param[in] none - \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains parameters of PTP system time members of the structure and the member values are shown as below: second: 0x0 - 0xFFFF FFFF @@ -3311,9 +3357,9 @@ void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct) uint32_t temp_sec = 0U, temp_subs = 0U; /* get the value of sysytem time registers */ - temp_sec = (uint32_t)ENET_PTP_TSH; + temp_sec = (uint32_t)ENET_PTP_TSH; temp_subs = (uint32_t)ENET_PTP_TSL; - + /* get sysytem time and construct the enet_ptp_systime_struct structure */ systime_struct->second = temp_sec; systime_struct->subsecond = GET_PTP_TSL_STMSS(temp_subs); @@ -3322,18 +3368,18 @@ void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct) /*! \brief configure the PPS output frequency - \param[in] freq: PPS output frequency, + \param[in] freq: PPS output frequency only one parameter can be selected which is shown as below \arg ENET_PPSOFC_1HZ: PPS output 1Hz frequency - \arg ENET_PPSOFC_2HZ: PPS output 2Hz frequency - \arg ENET_PPSOFC_4HZ: PPS output 4Hz frequency - \arg ENET_PPSOFC_8HZ: PPS output 8Hz frequency - \arg ENET_PPSOFC_16HZ: PPS output 16Hz frequency - \arg ENET_PPSOFC_32HZ: PPS output 32Hz frequency + \arg ENET_PPSOFC_2HZ: PPS output 2Hz frequency + \arg ENET_PPSOFC_4HZ: PPS output 4Hz frequency + \arg ENET_PPSOFC_8HZ: PPS output 8Hz frequency + \arg ENET_PPSOFC_16HZ: PPS output 16Hz frequency + \arg ENET_PPSOFC_32HZ: PPS output 32Hz frequency \arg ENET_PPSOFC_64HZ: PPS output 64Hz frequency \arg ENET_PPSOFC_128HZ: PPS output 128Hz frequency \arg ENET_PPSOFC_256HZ: PPS output 256Hz frequency - \arg ENET_PPSOFC_512HZ: PPS output 512Hz frequency + \arg ENET_PPSOFC_512HZ: PPS output 512Hz frequency \arg ENET_PPSOFC_1024HZ: PPS output 1024Hz frequency \arg ENET_PPSOFC_2048HZ: PPS output 2048Hz frequency \arg ENET_PPSOFC_4096HZ: PPS output 4096Hz frequency @@ -3362,7 +3408,7 @@ void enet_initpara_reset(void) enet_initpara.dma_maxburst = 0U; enet_initpara.dma_arbitration = 0U; enet_initpara.store_forward_mode = 0U; - enet_initpara.dma_function = 0U; + enet_initpara.dma_function = 0U; enet_initpara.vlan_config = 0U; enet_initpara.flow_control = 0U; enet_initpara.hashtable_high = 0U; @@ -3371,10 +3417,10 @@ void enet_initpara_reset(void) enet_initpara.halfduplex_param = 0U; enet_initpara.timer_config = 0U; enet_initpara.interframegap = 0U; -} +} /*! - \brief initialize ENET peripheral with generally concerned parameters, call it by enet_init() + \brief initialize ENET peripheral with generally concerned parameters, call it by enet_init() \param[in] none \param[out] none \retval none @@ -3396,7 +3442,7 @@ static void enet_default_init(void) | ENET_AUTO_PADCRC_DROP_DISABLE \ | ENET_CHECKSUMOFFLOAD_DISABLE; ENET_MAC_CFG = reg_value; - + /* configure ENET_MAC_FRMF register */ ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE |ENET_DEST_FILTER_INVERSE_DISABLE \ |ENET_MULTICAST_FILTER_PERFECT |ENET_UNICAST_FILTER_PERFECT \ @@ -3405,7 +3451,7 @@ static void enet_default_init(void) /* configure ENET_MAC_HLH, ENET_MAC_HLL register */ ENET_MAC_HLH = 0x0U; - + ENET_MAC_HLL = 0x0U; /* configure ENET_MAC_FCTL, ENET_MAC_FCTH register */ @@ -3414,13 +3460,13 @@ static void enet_default_init(void) reg_value |= MAC_FCTL_PTM(0) |ENET_ZERO_QUANTA_PAUSE_DISABLE \ |ENET_PAUSETIME_MINUS4 |ENET_UNIQUE_PAUSEDETECT \ |ENET_RX_FLOWCONTROL_DISABLE |ENET_TX_FLOWCONTROL_DISABLE; - ENET_MAC_FCTL = reg_value; - + ENET_MAC_FCTL = reg_value; + ENET_MAC_FCTH = ENET_DEACTIVE_THRESHOLD_512BYTES |ENET_ACTIVE_THRESHOLD_1536BYTES; - + /* configure ENET_MAC_VLT register */ ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT |MAC_VLT_VLTI(0); - + /* DMA */ /* configure ENET_DMA_CTL register */ reg_value = ENET_DMA_CTL; @@ -3429,8 +3475,8 @@ static void enet_default_init(void) |ENET_FLUSH_RXFRAME_ENABLE |ENET_TX_MODE_STOREFORWARD \ |ENET_TX_THRESHOLD_64BYTES |ENET_RX_THRESHOLD_64BYTES \ |ENET_FORWARD_ERRFRAMES_DISABLE |ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE \ - |ENET_SECONDFRAME_OPT_DISABLE; - ENET_DMA_CTL = reg_value; + |ENET_SECONDFRAME_OPT_DISABLE; + ENET_DMA_CTL = reg_value; /* configure ENET_DMA_BCTL register */ reg_value = ENET_DMA_BCTL; @@ -3439,7 +3485,7 @@ static void enet_default_init(void) |ENET_RXDP_32BEAT |ENET_PGBL_32BEAT |ENET_RXTX_DIFFERENT_PGBL \ |ENET_FIXED_BURST_ENABLE |ENET_MIXED_BURST_DISABLE \ |ENET_NORMAL_DESCRIPTOR; - ENET_DMA_BCTL = reg_value; + ENET_DMA_BCTL = reg_value; } #ifndef USE_DELAY @@ -3451,8 +3497,8 @@ static void enet_default_init(void) */ static void enet_delay(uint32_t ncount) { - uint32_t delay_time = 0U; - + __IO uint32_t delay_time = 0U; + for(delay_time = ncount; delay_time != 0U; delay_time--){ } } diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c index a3049a7448..e225258eb5 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c @@ -1,33 +1,58 @@ /*! - \file gd32f4xx_exmc.c - \brief EXMC driver + \file gd32f4xx_exmc.c + \brief EXMC driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_exmc.h" /* EXMC bank0 register reset value */ -#define BANK0_SNCTL_REGION_RESET ((uint32_t)0x000030DAU) +#define BANK0_SNCTL_RESET ((uint32_t)0x000030DAU) #define BANK0_SNTCFG_RESET ((uint32_t)0x0FFFFFFFU) #define BANK0_SNWTCFG_RESET ((uint32_t)0x0FFFFFFFU) -/* EXMC bank1/2 register reset mask*/ -#define BANK1_2_NPCTL_RESET ((uint32_t)0x00000018U) -#define BANK1_2_NPINTEN_RESET ((uint32_t)0x00000040U) -#define BANK1_2_NPCTCFG_RESET ((uint32_t)0xFCFCFCFCU) -#define BANK1_2_NPATCFG_RESET ((uint32_t)0xFCFCFCFCU) +/* EXMC bank1/2 register reset mask */ +#define BANK1_2_NPCTL_RESET ((uint32_t)0x00000008U) +#define BANK1_2_NPINTEN_RESET ((uint32_t)0x00000042U) +#define BANK1_2_NPCTCFG_RESET ((uint32_t)0xFFFFFFFFU) +#define BANK1_2_NPATCFG_RESET ((uint32_t)0xFFFFFFFFU) -/* EXMC bank3 register reset mask*/ -#define BANK3_NPCTL_RESET ((uint32_t)0x00000018U) -#define BANK3_NPINTEN_RESET ((uint32_t)0x00000000U) -#define BANK3_NPCTCFG_RESET ((uint32_t)0xFCFCFCFCU) -#define BANK3_NPATCFG_RESET ((uint32_t)0xFCFCFCFCU) -#define BANK3_PIOTCFG3_RESET ((uint32_t)0xFCFCFCFCU) +/* EXMC bank3 register reset mask */ +#define BANK3_NPCTL_RESET ((uint32_t)0x00000008U) +#define BANK3_NPINTEN_RESET ((uint32_t)0x00000040U) +#define BANK3_NPCTCFG_RESET ((uint32_t)0xFFFFFFFFU) +#define BANK3_NPATCFG_RESET ((uint32_t)0xFFFFFFFFU) +#define BANK3_PIOTCFG3_RESET ((uint32_t)0xFFFFFFFFU) /* EXMC SDRAM device register reset mask */ #define SDRAM_DEVICE_SDCTL_RESET ((uint32_t)0x000002D0U) @@ -64,13 +89,13 @@ #define NPCTCFG_COMHLD_OFFSET ((uint32_t)16U) #define NPCTCFG_COMHIZ_OFFSET ((uint32_t)24U) -#define NPATCFG_COMWAIT_OFFSET ((uint32_t)8U) -#define NPATCFG_COMHLD_OFFSET ((uint32_t)16U) -#define NPATCFG_COMHIZ_OFFSET ((uint32_t)24U) +#define NPATCFG_ATTWAIT_OFFSET ((uint32_t)8U) +#define NPATCFG_ATTHLD_OFFSET ((uint32_t)16U) +#define NPATCFG_ATTHIZ_OFFSET ((uint32_t)24U) -#define PIOTCFG_COMWAIT_OFFSET ((uint32_t)8U) -#define PIOTCFG_COMHLD_OFFSET ((uint32_t)16U) -#define PIOTCFG_COMHIZ_OFFSET ((uint32_t)24U) +#define PIOTCFG_IOWAIT_OFFSET ((uint32_t)8U) +#define PIOTCFG_IOHLD_OFFSET ((uint32_t)16U) +#define PIOTCFG_IOHIZ_OFFSET ((uint32_t)24U) #define SDCTL_WPEN_OFFSET ((uint32_t)9U) #define SDCTL_BRSTRD_OFFSET ((uint32_t)12U) @@ -96,11 +121,12 @@ #define SRCMD_RWAITCYCLE_OFFSET ((uint32_t)16U) #define SWCMD_WWAITCYCLE_OFFSET ((uint32_t)16U) -#define INTEN_INTEN_OFFSET ((uint32_t)3U) +#define INTEN_INTS_OFFSET ((uint32_t)3U) /*! \brief deinitialize EXMC NOR/SRAM region \param[in] exmc_norsram_region: select the region of bank0 + only one parameter can be selected which is shown as below: \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) \param[out] none \retval none @@ -108,101 +134,20 @@ void exmc_norsram_deinit(uint32_t exmc_norsram_region) { /* reset the registers */ - EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_REGION_RESET; + EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_RESET; EXMC_SNTCFG(exmc_norsram_region) = BANK0_SNTCFG_RESET; EXMC_SNWTCFG(exmc_norsram_region) = BANK0_SNWTCFG_RESET; } /*! - \brief initialize EXMC NOR/SRAM region - \param[in] exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter - norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 - write_mode: EXMC_ASYN_WRITE,EXMC_SYN_WRITE - extended_mode: ENABLE or DISABLE - asyn_wait: ENABLE or DISABLE - nwait_signal: ENABLE or DISABLE - memory_write: ENABLE or DISABLE - nwait_config: EXMC_NWAIT_CONFIG_BEFORE,EXMC_NWAIT_CONFIG_DURING - wrap_burst_mode: ENABLE or DISABLE - nwait_polarity: EXMC_NWAIT_POLARITY_LOW,EXMC_NWAIT_POLARITY_HIGH - burst_mode: ENABLE or DISABLE - databus_width: EXMC_NOR_DATABUS_WIDTH_8B,EXMC_NOR_DATABUS_WIDTH_16B - memory_type: EXMC_MEMORY_TYPE_SRAM,EXMC_MEMORY_TYPE_PSRAM,EXMC_MEMORY_TYPE_NOR - address_data_mux: ENABLE or DISABLE - read_write_timing: struct exmc_norsram_timing_parameter_struct set the time - write_timing: struct exmc_norsram_timing_parameter_struct set the time - \param[out] none - \retval none -*/ -void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) -{ - uint32_t snctl = 0x00000000U,sntcfg = 0x00000000U,snwtcfg = 0x00000000U; - - /* get the register value */ - snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region); - - /* clear relative bits */ - snctl &= ((uint32_t)~(EXMC_SNCTL_EXMODEN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | - EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | EXMC_SNCTL_WREN | - EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_SYNCWR | - EXMC_SNCTL_NRBKEN)); - - snctl = (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) | - exmc_norsram_init_struct->memory_type | - exmc_norsram_init_struct->databus_width | - (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) | - exmc_norsram_init_struct->nwait_polarity | - (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) | - exmc_norsram_init_struct->nwait_config | - (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) | - (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) | - (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) | - (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) | - exmc_norsram_init_struct->write_mode; - - sntcfg = (uint32_t)exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime | - (exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime << SNTCFG_AHLD_OFFSET) | - (exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime << SNTCFG_DSET_OFFSET) | - (exmc_norsram_init_struct->read_write_timing->bus_latency << SNTCFG_BUSLAT_OFFSET) | - exmc_norsram_init_struct->read_write_timing->syn_clk_division | - exmc_norsram_init_struct->read_write_timing->syn_data_latency | - exmc_norsram_init_struct->read_write_timing->asyn_access_mode; - - /* nor flash access enable */ - if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type) - { - snctl |= (uint32_t)EXMC_SNCTL_NREN; - } - - /* extended mode configure */ - if(ENABLE == exmc_norsram_init_struct->extended_mode) - { - snwtcfg = (uint32_t)exmc_norsram_init_struct->write_timing->asyn_address_setuptime | - (exmc_norsram_init_struct->write_timing->asyn_address_holdtime << SNTCFG_AHLD_OFFSET )| - (exmc_norsram_init_struct->write_timing->asyn_data_setuptime << SNTCFG_DSET_OFFSET) | - (exmc_norsram_init_struct->write_timing->bus_latency << SNTCFG_BUSLAT_OFFSET) | - exmc_norsram_init_struct->write_timing->asyn_access_mode; - } - else - { - snwtcfg = BANK0_SNWTCFG_RESET; - } - - /* configure the registers */ - EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl; - EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg; - EXMC_SNWTCFG(exmc_norsram_init_struct->norsram_region) = snwtcfg; -} - -/*! - \brief initialize the struct exmc_norsram_parameter_struct + \brief initialize exmc_norsram_parameter_struct with the default values \param[in] none \param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer \retval none */ -void exmc_norsram_parameter_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) { - /* configure the structure with default value */ + /* configure the structure with default values */ exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0; exmc_norsram_init_struct->address_data_mux = ENABLE; exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM; @@ -217,7 +162,7 @@ void exmc_norsram_parameter_init(exmc_norsram_parameter_struct* exmc_norsram_ini exmc_norsram_init_struct->asyn_wait = DISABLE; exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE; - /* read/write timing configure */ + /* configure read/write timing */ exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU; exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU; exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU; @@ -235,45 +180,100 @@ void exmc_norsram_parameter_init(exmc_norsram_parameter_struct* exmc_norsram_ini } /*! - \brief consecutive clock configure - \param[in] clock_mode: specifie when the clock is generated - \arg EXMC_CLOCK_SYN_MODE: the clock is generated only during synchronous access - \arg EXMC_CLOCK_UNCONDITIONALLY: the clock is generated unconditionally + \brief initialize EXMC NOR/SRAM region + \param[in] exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter + norsram_region: EXMC_BANK0_NORSRAM_REGIONx, x=0..3 + write_mode: EXMC_ASYN_WRITE, EXMC_SYN_WRITE + extended_mode: ENABLE or DISABLE + asyn_wait: ENABLE or DISABLE + nwait_signal: ENABLE or DISABLE + memory_write: ENABLE or DISABLE + nwait_config: EXMC_NWAIT_CONFIG_BEFORE, EXMC_NWAIT_CONFIG_DURING + wrap_burst_mode: ENABLE or DISABLE + nwait_polarity: EXMC_NWAIT_POLARITY_LOW, EXMC_NWAIT_POLARITY_HIGH + burst_mode: ENABLE or DISABLE + databus_width: EXMC_NOR_DATABUS_WIDTH_8B, EXMC_NOR_DATABUS_WIDTH_16B + memory_type: EXMC_MEMORY_TYPE_SRAM, EXMC_MEMORY_TYPE_PSRAM, EXMC_MEMORY_TYPE_NOR + address_data_mux: ENABLE or DISABLE + read_write_timing: struct exmc_norsram_timing_parameter_struct set the time + asyn_access_mode: EXMC_ACCESS_MODE_A, EXMC_ACCESS_MODE_B, EXMC_ACCESS_MODE_C, EXMC_ACCESS_MODE_D + syn_data_latency: EXMC_DATALAT_x_CLK, x=2..17 + syn_clk_division: EXMC_SYN_CLOCK_RATIO_x_CLK, x=2..16 + bus_latency: 0x0U~0xFU + asyn_data_setuptime: 0x01U~0xFFU + asyn_address_holdtime: 0x1U~0xFU + asyn_address_setuptime: 0x0U~0xFU + write_timing: struct exmc_norsram_timing_parameter_struct set the time + asyn_access_mode: EXMC_ACCESS_MODE_A, EXMC_ACCESS_MODE_B, EXMC_ACCESS_MODE_C, EXMC_ACCESS_MODE_D + syn_data_latency: EXMC_DATALAT_x_CLK, x=2..17 + syn_clk_division: EXMC_SYN_CLOCK_RATIO_x_CLK, x=2..16 + bus_latency: 0x0U~0xFU + asyn_data_setuptime: 0x01U~0xFFU + asyn_address_holdtime: 0x1U~0xFU + asyn_address_setuptime: 0x0U~0xFU \param[out] none \retval none */ -void exmc_norsram_consecutive_clock_config(uint32_t clock_mode) +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) { - if (EXMC_CLOCK_UNCONDITIONALLY == clock_mode){ - EXMC_SNCTL(EXMC_BANK0_NORSRAM_REGION0) |= EXMC_CLOCK_UNCONDITIONALLY; - }else{ - EXMC_SNCTL(EXMC_BANK0_NORSRAM_REGION0) &= ~EXMC_CLOCK_UNCONDITIONALLY; + uint32_t snctl = 0x00000000U,sntcfg = 0x00000000U,snwtcfg = 0x00000000U; + + /* get the register value */ + snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region); + + /* clear relative bits */ + snctl &= ((uint32_t)~(EXMC_SNCTL_NREN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | + EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | EXMC_SNCTL_WREN | + EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_SYNCWR | + EXMC_SNCTL_NRMUX )); + + snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) | + exmc_norsram_init_struct->memory_type | + exmc_norsram_init_struct->databus_width | + (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) | + exmc_norsram_init_struct->nwait_polarity | + (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) | + exmc_norsram_init_struct->nwait_config | + (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) | + (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) | + (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) | + (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) | + exmc_norsram_init_struct->write_mode; + + sntcfg = (uint32_t)exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime | + (exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime << SNTCFG_AHLD_OFFSET) | + (exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime << SNTCFG_DSET_OFFSET) | + (exmc_norsram_init_struct->read_write_timing->bus_latency << SNTCFG_BUSLAT_OFFSET) | + exmc_norsram_init_struct->read_write_timing->syn_clk_division | + exmc_norsram_init_struct->read_write_timing->syn_data_latency | + exmc_norsram_init_struct->read_write_timing->asyn_access_mode; + + /* nor flash access enable */ + if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){ + snctl |= (uint32_t)EXMC_SNCTL_NREN; } -} -/*! - \brief CRAM page size configure - \param[in] page_size: CRAM page size - \arg EXMC_CRAM_AUTO_SPLIT: the clock is generated only during synchronous access - \arg EXMC_CRAM_PAGE_SIZE_128_BYTES: page size is 128 bytes - \arg EXMC_CRAM_PAGE_SIZE_256_BYTES: page size is 256 bytes - \arg EXMC_CRAM_PAGE_SIZE_512_BYTES: page size is 512 bytes - \arg EXMC_CRAM_PAGE_SIZE_1024_BYTES: page size is 1024 bytes - \param[out] none - \retval none -*/ -void exmc_norsram_page_size_config(uint32_t page_size) -{ - /* reset the bits */ - EXMC_SNCTL(EXMC_BANK0_NORSRAM_REGION0) &= ~EXMC_SNCTL_CPS; + /* extended mode configure */ + if(ENABLE == exmc_norsram_init_struct->extended_mode){ + snwtcfg = (uint32_t)exmc_norsram_init_struct->write_timing->asyn_address_setuptime | + (exmc_norsram_init_struct->write_timing->asyn_address_holdtime << SNTCFG_AHLD_OFFSET )| + (exmc_norsram_init_struct->write_timing->asyn_data_setuptime << SNTCFG_DSET_OFFSET) | + (exmc_norsram_init_struct->write_timing->bus_latency << SNTCFG_BUSLAT_OFFSET) | + exmc_norsram_init_struct->write_timing->asyn_access_mode; + }else{ + snwtcfg = BANK0_SNWTCFG_RESET; + } - /* set the CPS bits */ - EXMC_SNCTL(EXMC_BANK0_NORSRAM_REGION0) |= page_size; + /* configure the registers */ + EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl; + EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg; + EXMC_SNWTCFG(exmc_norsram_init_struct->norsram_region) = snwtcfg; } /*! \brief enable EXMC NOR/PSRAM bank region \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM bank + only one parameter can be selected which is shown as below: \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) \param[out] none \retval none @@ -286,6 +286,7 @@ void exmc_norsram_enable(uint32_t exmc_norsram_region) /*! \brief disable EXMC NOR/PSRAM bank region \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM Bank + only one parameter can be selected which is shown as below: \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) \param[out] none \retval none @@ -298,6 +299,7 @@ void exmc_norsram_disable(uint32_t exmc_norsram_region) /*! \brief deinitialize EXMC NAND bank \param[in] exmc_nand_bank: select the bank of NAND + only one parameter can be selected which is shown as below: \arg EXMC_BANKx_NAND(x=1..2) \param[out] none \retval none @@ -311,6 +313,32 @@ void exmc_nand_deinit(uint32_t exmc_nand_bank) EXMC_NPATCFG(exmc_nand_bank) = BANK1_2_NPATCFG_RESET; } +/*! + \brief initialize exmc_norsram_parameter_struct with the default values + \param[in] none + \param[out] the initialized struct exmc_norsram_parameter_struct pointer + \retval none +*/ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + /* configure the structure with default values */ + exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND; + exmc_nand_init_struct->wait_feature = DISABLE; + exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B; + exmc_nand_init_struct->ecc_logic = DISABLE; + exmc_nand_init_struct->ecc_size = EXMC_ECC_SIZE_256BYTES; + exmc_nand_init_struct->ctr_latency = 0x0U; + exmc_nand_init_struct->atr_latency = 0x0U; + exmc_nand_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->common_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; +} + /*! \brief initialize EXMC NAND bank \param[in] exmc_nand_parameter_struct: configure the EXMC NAND parameter @@ -322,14 +350,22 @@ void exmc_nand_deinit(uint32_t exmc_nand_bank) databus_width: EXMC_NAND_DATABUS_WIDTH_8B,EXMC_NAND_DATABUS_WIDTH_16B wait_feature: ENABLE or DISABLE common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x01U~0xFFU + holdtime: 0x01U~0xFEU + waittime: 0x02U~0xFFU + setuptime: 0x01U~0xFFU attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x00U~0xFEU + holdtime: 0x01U~0xFEU + waittime: 0x02U~0xFFU + setuptime: 0x01U~0xFFU \param[out] none \retval none */ void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct) { uint32_t npctl = 0x00000000U, npctcfg = 0x00000000U, npatcfg = 0x00000000U; - + npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET)| EXMC_NPCTL_NDTP | exmc_nand_init_struct->databus_width | @@ -338,15 +374,15 @@ void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct) exmc_nand_init_struct->ctr_latency | exmc_nand_init_struct->atr_latency; - npctcfg = (uint32_t)(exmc_nand_init_struct->common_space_timing->setuptime - 1U) | - ((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) | - (exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET)| - ((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET); + npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | + (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); - npatcfg = (uint32_t)(exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) | - ((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_COMWAIT_OFFSET) | - (exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_COMHLD_OFFSET)| - (exmc_nand_init_struct->attribute_space_timing->databus_hiztime << NPATCFG_COMHIZ_OFFSET); + npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | + ((exmc_nand_init_struct->attribute_space_timing->databus_hiztime << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); /* EXMC_BANK1_NAND or EXMC_BANK2_NAND initialize */ EXMC_NPCTL(exmc_nand_init_struct->nand_bank) = npctl; @@ -354,35 +390,10 @@ void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct) EXMC_NPATCFG(exmc_nand_init_struct->nand_bank) = npatcfg; } -/*! - \brief initialize the struct exmc_norsram_parameter_struct - \param[in] none - \param[out] the initialized struct exmc_norsram_parameter_struct pointer - \retval none -*/ -void exmc_nand_parameter_init(exmc_nand_parameter_struct* exmc_nand_init_struct) -{ - /* configure the structure with default value */ - exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND; - exmc_nand_init_struct->wait_feature = DISABLE; - exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B; - exmc_nand_init_struct->ecc_logic = DISABLE; - exmc_nand_init_struct->ecc_size = EXMC_ECC_SIZE_256BYTES; - exmc_nand_init_struct->ctr_latency = 0x0U; - exmc_nand_init_struct->atr_latency = 0x0U; - exmc_nand_init_struct->common_space_timing->setuptime = 0xfcU; - exmc_nand_init_struct->common_space_timing->waittime = 0xfcU; - exmc_nand_init_struct->common_space_timing->holdtime = 0xfcU; - exmc_nand_init_struct->common_space_timing->databus_hiztime = 0xfcU; - exmc_nand_init_struct->attribute_space_timing->setuptime = 0xfcU; - exmc_nand_init_struct->attribute_space_timing->waittime = 0xfcU; - exmc_nand_init_struct->attribute_space_timing->holdtime = 0xfcU; - exmc_nand_init_struct->attribute_space_timing->databus_hiztime = 0xfcU; -} - /*! \brief enable NAND bank \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: \arg EXMC_BANKx_NAND(x=1,2) \param[out] none \retval none @@ -395,6 +406,7 @@ void exmc_nand_enable(uint32_t exmc_nand_bank) /*! \brief disable NAND bank \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: \arg EXMC_BANKx_NAND(x=1,2) \param[out] none \retval none @@ -404,40 +416,6 @@ void exmc_nand_disable(uint32_t exmc_nand_bank) EXMC_NPCTL(exmc_nand_bank) &= ~EXMC_NPCTL_NDBKEN; } -/*! - \brief enable or disable the EXMC NAND ECC function - \param[in] exmc_nand_bank: specifie the NAND bank - \arg EXMC_BANKx_NAND(x=1,2) - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue) -{ - if (ENABLE == newvalue) - { - /* enable the selected NAND bank ECC function */ - EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_ECCEN; - } - else - { - /* disable the selected NAND bank ECC function */ - EXMC_NPCTL(exmc_nand_bank) &= ~EXMC_NPCTL_ECCEN; - } -} - -/*! - \brief get the EXMC ECC value - \param[in] exmc_nand_bank: specifie the NAND bank - \arg EXMC_BANKx_NAND(x=1,2) - \param[out] none - \retval the error correction code(ECC) value -*/ -uint32_t exmc_ecc_get(uint32_t exmc_nand_bank) -{ - return(EXMC_NECC(exmc_nand_bank)); -} - /*! \brief deinitialize EXMC PC card bank \param[in] none @@ -455,53 +433,14 @@ void exmc_pccard_deinit(void) } /*! - \brief initialize EXMC PC card bank - \param[in] exmc_pccard_parameter_struct: configure the EXMC NAND parameter - atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 - ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 - wait_feature: ENABLE or DISABLE - common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time - attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time - io_space_timing: exmc_nand_pccard_timing_parameter_struct set the time - \param[out] none - \retval none -*/ -void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) -{ - /* configure the EXMC bank3 PC card control register */ - EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) | - EXMC_NAND_DATABUS_WIDTH_16B | - exmc_pccard_init_struct->ctr_latency | - exmc_pccard_init_struct->atr_latency ; - - /* configure the EXMC bank3 PC card common space timing configuration register */ - EXMC_NPCTCFG3 = (uint32_t)(exmc_pccard_init_struct->common_space_timing->setuptime - 1U) | - ((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) | - (exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET)| - ((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET); - - /* configure the EXMC bank3 PC card attribute space timing configuration register */ - EXMC_NPATCFG3 = (uint32_t)(exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) | - ((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_COMWAIT_OFFSET) | - (exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_COMHLD_OFFSET)| - (exmc_pccard_init_struct->attribute_space_timing->databus_hiztime << NPATCFG_COMHIZ_OFFSET); - - /* configure the EXMC bank3 PC card io space timing configuration register */ - EXMC_PIOTCFG3 = (uint32_t)(exmc_pccard_init_struct->io_space_timing->setuptime - 1U) | - ((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_COMWAIT_OFFSET) | - (exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_COMHLD_OFFSET)| - (exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_COMHIZ_OFFSET); -} - -/*! - \brief initialize the struct exmc_pccard_parameter_struct + \brief initialize exmc_pccard_parameter_struct with the default values \param[in] none \param[out] the initialized struct exmc_pccard_parameter_struct pointer \retval none */ -void exmc_pccard_parameter_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) { - /* configure the structure with default value */ + /* configure the structure with default values */ exmc_pccard_init_struct->wait_feature = DISABLE; exmc_pccard_init_struct->ctr_latency = 0x0U; exmc_pccard_init_struct->atr_latency = 0x0U; @@ -519,6 +458,57 @@ void exmc_pccard_parameter_init(exmc_pccard_parameter_struct* exmc_pccard_init_s exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU; } +/*! + \brief initialize EXMC PC card bank + \param[in] exmc_pccard_parameter_struct: configure the EXMC NAND parameter + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x01U~0xFFU + holdtime: 0x01U~0xFEU + waittime: 0x02U~0xFFU + setuptime: 0x01U~0xFFU + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x00U~0xFEU + holdtime: 0x01U~0xFEU + waittime: 0x02U~0xFFU + setuptime: 0x01U~0xFFU + io_space_timing: exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x00U~0xFFU + holdtime: 0x01U~0xFFU + waittime: 0x02U~0x100U + setuptime: 0x01U~0x100U + \param[out] none + \retval none +*/ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the EXMC bank3 PC card control register */ + EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) | + EXMC_NAND_DATABUS_WIDTH_16B | + exmc_pccard_init_struct->ctr_latency | + exmc_pccard_init_struct->atr_latency ; + + /* configure the EXMC bank3 PC card common space timing configuration register */ + EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | + (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + /* configure the EXMC bank3 PC card attribute space timing configuration register */ + EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | + ((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ); + + /* configure the EXMC bank3 PC card io space timing configuration register */ + EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET ) | + (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT ) | + ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD ) | + ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ ); +} + /*! \brief enable PC Card Bank \param[in] none @@ -543,6 +533,9 @@ void exmc_pccard_disable(void) /*! \brief deinitialize EXMC SDRAM device + \param[in] exmc_sdram_device: select the SRAM device + only one parameter can be selected which is shown as below: + \arg EXMC_SDRAM_DEVICEx(x=0, 1) \param[in] none \param[out] none \retval none @@ -558,93 +551,14 @@ void exmc_sdram_deinit(uint32_t exmc_sdram_device) } /*! - \brief initialize EXMC SDRAM device - \param[in] exmc_sdram_parameter_struct: configure the EXMC SDRAM parameter - sdram_device: EXMC_SDRAM_DEVICE0,EXMC_SDRAM_DEVICE1 - pipeline_read_delay: EXMC_PIPELINE_DELAY_x_HCLK,x=0..2 - brust_read_switch: ENABLE or DISABLE - sdclock_config: EXMC_SDCLK_DISABLE,EXMC_SDCLK_PERIODS_2_HCLK,EXMC_SDCLK_PERIODS_3_HCLK - write_protection: ENABLE or DISABLE - cas_latency: EXMC_CAS_LATENCY_x_SDCLK,x=1..3 - internal_bank_number: EXMC_SDRAM_2_INTER_BANK,EXMC_SDRAM_4_INTER_BANK - data_width: EXMC_SDRAM_DATABUS_WIDTH_8B,EXMC_SDRAM_DATABUS_WIDTH_16B,EXMC_SDRAM_DATABUS_WIDTH_32B - row_address_width: EXMC_SDRAM_ROW_ADDRESS_x,x=11..13 - column_address_width: EXMC_SDRAM_COW_ADDRESS_x,x=8..11 - timing: exmc_sdram_timing_parameter_struct set the time - \param[out] none - \retval none -*/ -void exmc_sdram_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct) -{ - uint32_t sdctl0, sdctl1, sdtcfg0, sdtcfg1; - - /* configuration EXMC_SDCTL0 or EXMC_SDCTL1 */ - if(EXMC_SDRAM_DEVICE0 == exmc_sdram_init_struct->sdram_device){ - /* configuration EXMC_SDCTL0 */ - EXMC_SDCTL(EXMC_SDRAM_DEVICE0) = (uint32_t)exmc_sdram_init_struct->column_address_width | - exmc_sdram_init_struct->row_address_width | - exmc_sdram_init_struct->data_width | - exmc_sdram_init_struct->internal_bank_number | - exmc_sdram_init_struct->cas_latency | - (exmc_sdram_init_struct->write_protection << SDCTL_WPEN_OFFSET)| - exmc_sdram_init_struct->sdclock_config | - (exmc_sdram_init_struct->brust_read_switch << SDCTL_BRSTRD_OFFSET)| - exmc_sdram_init_struct->pipeline_read_delay; - - /* configuration EXMC_SDTCFG0 */ - EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay)-1U) | - (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay)-1U) << SDTCFG_XSRD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_address_select_delay)-1U) << SDTCFG_RASD_OFFSET) | - (((exmc_sdram_init_struct->timing->auto_refresh_delay)-1U) << SDTCFG_ARFD_OFFSET) | - (((exmc_sdram_init_struct->timing->write_recovery_delay)-1U) << SDTCFG_WRD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_precharge_delay)-1U) << SDTCFG_RPD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_to_column_delay)-1U) << SDTCFG_RCD_OFFSET); - }else{ - /* configuration EXMC_SDCTL0 and EXMC_SDCTL1 */ - /* some bits in the EXMC_SDCTL1 register are reserved */ - sdctl0 = EXMC_SDCTL(EXMC_SDRAM_DEVICE0) & (~( EXMC_SDCTL_PIPED | EXMC_SDCTL_BRSTRD | EXMC_SDCTL_SDCLK )); - - sdctl0 |= (uint32_t)exmc_sdram_init_struct->sdclock_config | - exmc_sdram_init_struct->brust_read_switch | - exmc_sdram_init_struct->pipeline_read_delay; - - sdctl1 = (uint32_t)exmc_sdram_init_struct->column_address_width | - exmc_sdram_init_struct->row_address_width | - exmc_sdram_init_struct->data_width | - exmc_sdram_init_struct->internal_bank_number | - exmc_sdram_init_struct->cas_latency | - exmc_sdram_init_struct->write_protection ; - - EXMC_SDCTL(EXMC_SDRAM_DEVICE0) = sdctl0; - EXMC_SDCTL(EXMC_SDRAM_DEVICE1) = sdctl1; - - /* configuration EXMC_SDTCFG0 and EXMC_SDTCFG1 */ - /* some bits in the EXMC_SDTCFG1 register are reserved */ - sdtcfg0 = EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) & (~(EXMC_SDTCFG_RPD | EXMC_SDTCFG_WRD | EXMC_SDTCFG_ARFD)); - - sdtcfg0 |= (uint32_t)(((exmc_sdram_init_struct->timing->auto_refresh_delay)-1U) << SDTCFG_ARFD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_precharge_delay)-1U) << SDTCFG_RPD_OFFSET) | - (((exmc_sdram_init_struct->timing->write_recovery_delay)-1U) << SDTCFG_WRD_OFFSET); - - sdtcfg1 = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay)-1U) | - (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay)-1U) << SDTCFG_XSRD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_address_select_delay)-1U) << SDTCFG_RASD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_to_column_delay)-1U) << SDTCFG_RCD_OFFSET); - - EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) = sdtcfg0; - EXMC_SDTCFG(EXMC_SDRAM_DEVICE1) = sdtcfg1; - } -} - -/*! - \brief initialize the struct exmc_pccard_parameter_struct + \brief initialize exmc_sdram_parameter_struct with the default values \param[in] none \param[out] the initialized struct exmc_pccard_parameter_struct pointer \retval none */ -void exmc_sdram_parameter_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct) +void exmc_sdram_struct_para_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct) { - /* configure the structure with default value */ + /* configure the structure with default values */ exmc_sdram_init_struct->sdram_device = EXMC_SDRAM_DEVICE0; exmc_sdram_init_struct->column_address_width = EXMC_SDRAM_COW_ADDRESS_8; exmc_sdram_init_struct->row_address_width = EXMC_SDRAM_ROW_ADDRESS_11; @@ -666,118 +580,88 @@ void exmc_sdram_parameter_init(exmc_sdram_parameter_struct* exmc_sdram_init_stru } /*! - \brief configure the SDRAM memory command - \param[in] the struct exmc_sdram_command_parameter_struct pointer + \brief initialize EXMC SDRAM device + \param[in] exmc_sdram_parameter_struct: configure the EXMC SDRAM parameter + sdram_device: EXMC_SDRAM_DEVICE0,EXMC_SDRAM_DEVICE1 + pipeline_read_delay: EXMC_PIPELINE_DELAY_x_HCLK,x=0..2 + brust_read_switch: ENABLE or DISABLE + sdclock_config: EXMC_SDCLK_DISABLE,EXMC_SDCLK_PERIODS_2_HCLK,EXMC_SDCLK_PERIODS_3_HCLK + write_protection: ENABLE or DISABLE + cas_latency: EXMC_CAS_LATENCY_x_SDCLK,x=1..3 + internal_bank_number: EXMC_SDRAM_2_INTER_BANK,EXMC_SDRAM_4_INTER_BANK + data_width: EXMC_SDRAM_DATABUS_WIDTH_8B,EXMC_SDRAM_DATABUS_WIDTH_16B,EXMC_SDRAM_DATABUS_WIDTH_32B + row_address_width: EXMC_SDRAM_ROW_ADDRESS_x,x=11..13 + column_address_width: EXMC_SDRAM_COW_ADDRESS_x,x=8..11 + timing: exmc_sdram_timing_parameter_struct set the time + row_to_column_delay: 1U~16U + row_precharge_delay: 1U~16U + write_recovery_delay: 1U~16U + auto_refresh_delay: 1U~16U + row_address_select_delay: 1U~16U + exit_selfrefresh_delay: 1U~16U + load_mode_register_delay: 1U~16U \param[out] none \retval none */ -void exmc_sdram_command_config(exmc_sdram_command_parameter_struct* exmc_sdram_command_init_struct) +void exmc_sdram_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct) { - /* configure command register */ - EXMC_SDCMD = (uint32_t)((exmc_sdram_command_init_struct->command) | - (exmc_sdram_command_init_struct->bank_select) | - ((exmc_sdram_command_init_struct->auto_refresh_number)) | - ((exmc_sdram_command_init_struct->mode_register_content)<sdram_device){ + /* configuration EXMC_SDCTL0 */ + EXMC_SDCTL(EXMC_SDRAM_DEVICE0) = (uint32_t)exmc_sdram_init_struct->column_address_width | + exmc_sdram_init_struct->row_address_width | + exmc_sdram_init_struct->data_width | + exmc_sdram_init_struct->internal_bank_number | + exmc_sdram_init_struct->cas_latency | + (exmc_sdram_init_struct->write_protection << SDCTL_WPEN_OFFSET)| + exmc_sdram_init_struct->sdclock_config | + (exmc_sdram_init_struct->brust_read_switch << SDCTL_BRSTRD_OFFSET)| + exmc_sdram_init_struct->pipeline_read_delay; -/*! - \brief set the number of successive auto-refresh command - \param[in] exmc_number: the number SDRAM clock cycles unit between two successive auto-refresh commands - \param[out] none - \retval none -*/ -void exmc_sdram_autorefresh_number_set(uint32_t exmc_number) -{ - uint32_t sdcmd; - sdcmd = EXMC_SDCMD & (~EXMC_SDCMD_NARF); - EXMC_SDCMD = sdcmd | (uint32_t)((exmc_number << SDCMD_NARF_OFFSET) & EXMC_SDCMD_NARF) ; -} - -/*! - \brief config the write protection function - \param[in] exmc_sdram_device: specifie the SDRAM device - \arg EXMC_SDRAM_DEVICEx(x=0,1) - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void exmc_sdram_write_protection_config(uint32_t exmc_sdram_device, ControlStatus newvalue) -{ - if (ENABLE == newvalue){ - EXMC_SDCTL(exmc_sdram_device) |= (uint32_t)EXMC_SDCTL_WPEN; + /* configuration EXMC_SDTCFG0 */ + EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay)-1U) | + (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay)-1U) << SDTCFG_XSRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_address_select_delay)-1U) << SDTCFG_RASD_OFFSET) | + (((exmc_sdram_init_struct->timing->auto_refresh_delay)-1U) << SDTCFG_ARFD_OFFSET) | + (((exmc_sdram_init_struct->timing->write_recovery_delay)-1U) << SDTCFG_WRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_precharge_delay)-1U) << SDTCFG_RPD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_to_column_delay)-1U) << SDTCFG_RCD_OFFSET); }else{ - EXMC_SDCTL(exmc_sdram_device) &= ~((uint32_t)EXMC_SDCTL_WPEN); - } + /* configuration EXMC_SDCTL0 and EXMC_SDCTL1 */ + /* some bits in the EXMC_SDCTL1 register are reserved */ + sdctl0 = EXMC_SDCTL(EXMC_SDRAM_DEVICE0) & (~( EXMC_SDCTL_PIPED | EXMC_SDCTL_BRSTRD | EXMC_SDCTL_SDCLK )); -} + sdctl0 |= (uint32_t)exmc_sdram_init_struct->sdclock_config | + exmc_sdram_init_struct->brust_read_switch | + exmc_sdram_init_struct->pipeline_read_delay; -/*! - \brief get the status of SDRAM device0 or device1 - \param[in] exmc_sdram_device: specifie the SDRAM device - \arg EXMC_SDRAM_DEVICEx(x=0,1) - \param[out] none - \retval the status of SDRAM device -*/ -uint32_t exmc_sdram_bankstatus_get(uint32_t exmc_sdram_device) -{ - uint32_t sdstat = 0U; + sdctl1 = (uint32_t)exmc_sdram_init_struct->column_address_width | + exmc_sdram_init_struct->row_address_width | + exmc_sdram_init_struct->data_width | + exmc_sdram_init_struct->internal_bank_number | + exmc_sdram_init_struct->cas_latency | + exmc_sdram_init_struct->write_protection ; - if(EXMC_SDRAM_DEVICE0 == exmc_sdram_device) - { - sdstat = ((uint32_t)(EXMC_SDSTAT & EXMC_SDSDAT_STA0) >> SDSTAT_STA0_OFFSET); - } - else - { - sdstat = ((uint32_t)(EXMC_SDSTAT & EXMC_SDSDAT_STA1) >> SDSTAT_STA1_OFFSET); - } + EXMC_SDCTL(EXMC_SDRAM_DEVICE0) = sdctl0; + EXMC_SDCTL(EXMC_SDRAM_DEVICE1) = sdctl1; - return sdstat; -} + /* configuration EXMC_SDTCFG0 and EXMC_SDTCFG1 */ + /* some bits in the EXMC_SDTCFG1 register are reserved */ + sdtcfg0 = EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) & (~(EXMC_SDTCFG_RPD | EXMC_SDTCFG_WRD | EXMC_SDTCFG_ARFD)); -/*! - \brief configure the delayed sample clock of read data - \param[in] delay_cell: SDRAM the delayed sample clock of read data - \arg EXMC_SDRAM_x_DELAY_CELL(x=0..15) - \param[in] extra_hclk: sample cycle of read data - \arg EXMC_SDRAM_READSAMPLE_x_EXTRAHCLK(x=0,1) - \param[out] none - \retval none -*/ -void exmc_sdram_readsample_config(uint32_t delay_cell, uint32_t extra_hclk) -{ - uint32_t sdrsctl = 0U; - - sdrsctl = EXMC_SDRSCTL & (~(EXMC_SDRSCTL_SDSC | EXMC_SDRSCTL_SSCR)); - sdrsctl |= (uint32_t)(delay_cell & EXMC_SDRSCTL_SDSC) | - ((extra_hclk << SDRSCTL_SSCR_OFFSET) & EXMC_SDRSCTL_SSCR); - EXMC_SDRSCTL = sdrsctl; -} + sdtcfg0 |= (uint32_t)(((exmc_sdram_init_struct->timing->auto_refresh_delay)-1U) << SDTCFG_ARFD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_precharge_delay)-1U) << SDTCFG_RPD_OFFSET) | + (((exmc_sdram_init_struct->timing->write_recovery_delay)-1U) << SDTCFG_WRD_OFFSET); -/*! - \brief enable or disable read sample - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void exmc_sdram_readsample_enable(ControlStatus newvalue) -{ - if (ENABLE == newvalue){ - EXMC_SDRSCTL |= EXMC_SDRSCTL_RSEN; - }else{ - EXMC_SDRSCTL &= (uint32_t)(~EXMC_SDRSCTL_RSEN); + sdtcfg1 = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay)-1U) | + (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay)-1U) << SDTCFG_XSRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_address_select_delay)-1U) << SDTCFG_RASD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_to_column_delay)-1U) << SDTCFG_RCD_OFFSET); + + EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) = sdtcfg0; + EXMC_SDTCFG(EXMC_SDRAM_DEVICE1) = sdtcfg1; } } @@ -797,10 +681,25 @@ void exmc_sqpipsram_deinit(void) EXMC_SIDH = BANK0_SQPI_SIDH_RESET; } +/*! + \brief initialize exmc_sqpipsram_parameter_struct with the default values + \param[in] the struct exmc_sqpipsram_parameter_struct pointer + \param[out] none + \retval none +*/ +void exmc_sqpipsram_struct_para_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct) +{ + /* configure the structure with default values */ + exmc_sqpipsram_init_struct->sample_polarity = EXMC_SQPIPSRAM_SAMPLE_RISING_EDGE; + exmc_sqpipsram_init_struct->id_length = EXMC_SQPIPSRAM_ID_LENGTH_64B; + exmc_sqpipsram_init_struct->address_bits = EXMC_SQPIPSRAM_ADDR_LENGTH_24B; + exmc_sqpipsram_init_struct->command_bits = EXMC_SQPIPSRAM_COMMAND_LENGTH_8B; +} + /*! \brief initialize EXMC SQPIPSRAM \param[in] exmc_sqpipsram_parameter_struct: configure the EXMC SQPIPSRAM parameter - sample_polarity: EXMC_SDRAM_SAMPLE_RISING_EDGE,EXMC_SDRAM_SAMPLE_FALLING_EDGE + sample_polarity: EXMC_SQPIPSRAM_SAMPLE_RISING_EDGE,EXMC_SQPIPSRAM_SAMPLE_FALLING_EDGE id_length: EXMC_SQPIPSRAM_ID_LENGTH_xB,x=8,16,32,64 address_bits: EXMC_SQPIPSRAM_ADDR_LENGTH_xB,x=1..26 command_bits: EXMC_SQPIPSRAM_COMMAND_LENGTH_xB,x=4,8,16 @@ -817,23 +716,209 @@ void exmc_sqpipsram_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_st } /*! - \brief initialize the struct exmc_sqpipsram_parameter_struct - \param[in] the struct exmc_sqpipsram_parameter_struct pointer + \brief configure consecutive clock + \param[in] clock_mode: specifie when the clock is generated + only one parameter can be selected which is shown as below: + \arg EXMC_CLOCK_SYN_MODE: the clock is generated only during synchronous access + \arg EXMC_CLOCK_UNCONDITIONALLY: the clock is generated unconditionally \param[out] none \retval none */ -void exmc_sqpipsram_parameter_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct) +void exmc_norsram_consecutive_clock_config(uint32_t clock_mode) { - /* configure the structure with default value */ - exmc_sqpipsram_init_struct->sample_polarity = EXMC_SDRAM_SAMPLE_RISING_EDGE; - exmc_sqpipsram_init_struct->id_length = EXMC_SQPIPSRAM_ID_LENGTH_64B; - exmc_sqpipsram_init_struct->address_bits = EXMC_SQPIPSRAM_ADDR_LENGTH_24B; - exmc_sqpipsram_init_struct->command_bits = EXMC_SQPIPSRAM_COMMAND_LENGTH_8B; + if (EXMC_CLOCK_UNCONDITIONALLY == clock_mode){ + EXMC_SNCTL(EXMC_BANK0_NORSRAM_REGION0) |= EXMC_CLOCK_UNCONDITIONALLY; + }else{ + EXMC_SNCTL(EXMC_BANK0_NORSRAM_REGION0) &= ~EXMC_CLOCK_UNCONDITIONALLY; + } +} + +/*! + \brief configure CRAM page size + \param[in] exmc_norsram_region: select the region of bank0 + only one parameter can be selected which is shown as below: + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[in] page_size: CRAM page size + only one parameter can be selected which is shown as below: + \arg EXMC_CRAM_AUTO_SPLIT: the clock is generated only during synchronous access + \arg EXMC_CRAM_PAGE_SIZE_128_BYTES: page size is 128 bytes + \arg EXMC_CRAM_PAGE_SIZE_256_BYTES: page size is 256 bytes + \arg EXMC_CRAM_PAGE_SIZE_512_BYTES: page size is 512 bytes + \arg EXMC_CRAM_PAGE_SIZE_1024_BYTES: page size is 1024 bytes + \param[out] none + \retval none +*/ +void exmc_norsram_page_size_config(uint32_t exmc_norsram_region, uint32_t page_size) +{ + /* reset the bits */ + EXMC_SNCTL(exmc_norsram_region) &= ~EXMC_SNCTL_CPS; + + /* set the CPS bits */ + EXMC_SNCTL(exmc_norsram_region) |= page_size; +} + +/*! + \brief enable or disable the EXMC NAND ECC function + \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1,2) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue) +{ + if (ENABLE == newvalue){ + /* enable the selected NAND bank ECC function */ + EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_ECCEN; + }else{ + /* disable the selected NAND bank ECC function */ + EXMC_NPCTL(exmc_nand_bank) &= ~EXMC_NPCTL_ECCEN; + } +} + +/*! + \brief get the EXMC ECC value + \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval the error correction code(ECC) value +*/ +uint32_t exmc_ecc_get(uint32_t exmc_nand_bank) +{ + return(EXMC_NECC(exmc_nand_bank)); +} + +/*! + \brief enable or disable read sample + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void exmc_sdram_readsample_enable(ControlStatus newvalue) +{ + if (ENABLE == newvalue){ + EXMC_SDRSCTL |= EXMC_SDRSCTL_RSEN; + }else{ + EXMC_SDRSCTL &= (uint32_t)(~EXMC_SDRSCTL_RSEN); + } +} + +/*! + \brief configure the delayed sample clock of read data + \param[in] delay_cell: SDRAM the delayed sample clock of read data + only one parameter can be selected which is shown as below: + \arg EXMC_SDRAM_x_DELAY_CELL(x=0..15) + \param[in] extra_hclk: sample cycle of read data + only one parameter can be selected which is shown as below: + \arg EXMC_SDRAM_READSAMPLE_x_EXTRAHCLK(x=0,1) + \param[out] none + \retval none +*/ +void exmc_sdram_readsample_config(uint32_t delay_cell, uint32_t extra_hclk) +{ + uint32_t sdrsctl = 0U; + + /* reset the bits */ + sdrsctl = EXMC_SDRSCTL & (~(EXMC_SDRSCTL_SDSC | EXMC_SDRSCTL_SSCR)); + /* set the bits */ + sdrsctl |= (uint32_t)(delay_cell & EXMC_SDRSCTL_SDSC) | + ((extra_hclk << SDRSCTL_SSCR_OFFSET) & EXMC_SDRSCTL_SSCR); + EXMC_SDRSCTL = sdrsctl; +} + +/*! + \brief configure the SDRAM memory command + \param[in] exmc_sdram_command_init_struct: initialize EXMC SDRAM command + mode_register_content: + auto_refresh_number: EXMC_SDRAM_AUTO_REFLESH_x_SDCLK, x=1..15 + bank_select: EXMC_SDRAM_DEVICE0_SELECT, EXMC_SDRAM_DEVICE1_SELECT, EXMC_SDRAM_DEVICE0_1_SELECT + command: EXMC_SDRAM_NORMAL_OPERATION, EXMC_SDRAM_CLOCK_ENABLE, EXMC_SDRAM_PRECHARGE_ALL, + EXMC_SDRAM_AUTO_REFRESH, EXMC_SDRAM_LOAD_MODE_REGISTER, EXMC_SDRAM_SELF_REFRESH, + EXMC_SDRAM_POWERDOWN_ENTRY + \param[out] none + \retval none +*/ +void exmc_sdram_command_config(exmc_sdram_command_parameter_struct* exmc_sdram_command_init_struct) +{ + /* configure command register */ + EXMC_SDCMD = (uint32_t)((exmc_sdram_command_init_struct->command) | + (exmc_sdram_command_init_struct->bank_select) | + ((exmc_sdram_command_init_struct->auto_refresh_number)) | + ((exmc_sdram_command_init_struct->mode_register_content)<> SDSTAT_STA0_OFFSET); + }else{ + sdstat = ((uint32_t)(EXMC_SDSTAT & EXMC_SDSDAT_STA1) >> SDSTAT_STA1_OFFSET); + } + + return sdstat; } /*! \brief set the read command \param[in] read_command_mode: configure SPI PSRAM read command mode + only one parameter can be selected which is shown as below: \arg EXMC_SQPIPSRAM_READ_MODE_DISABLE: not SPI mode \arg EXMC_SQPIPSRAM_READ_MODE_SPI: SPI mode \arg EXMC_SQPIPSRAM_READ_MODE_SQPI: SQPI mode @@ -843,10 +928,10 @@ void exmc_sqpipsram_parameter_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsr \param[out] none \retval none */ -void exmc_sqpipsram_read_command_set(uint32_t read_command_mode,uint32_t read_wait_cycle,uint32_t read_command_code) +void exmc_sqpipsram_read_command_set(uint32_t read_command_mode,uint32_t read_wait_cycle, uint32_t read_command_code) { uint32_t srcmd; - + srcmd = (uint32_t) read_command_mode | ((read_wait_cycle << SRCMD_RWAITCYCLE_OFFSET) & EXMC_SRCMD_RWAITCYCLE) | ((read_command_code & EXMC_SRCMD_RCMD)); @@ -856,6 +941,7 @@ void exmc_sqpipsram_read_command_set(uint32_t read_command_mode,uint32_t read_wa /*! \brief set the write command \param[in] write_command_mode: configure SPI PSRAM write command mode + only one parameter can be selected which is shown as below: \arg EXMC_SQPIPSRAM_WRITE_MODE_DISABLE: not SPI mode \arg EXMC_SQPIPSRAM_WRITE_MODE_SPI: SPI mode \arg EXMC_SQPIPSRAM_WRITE_MODE_SQPI: SQPI mode @@ -865,10 +951,10 @@ void exmc_sqpipsram_read_command_set(uint32_t read_command_mode,uint32_t read_wa \param[out] none \retval none */ -void exmc_sqpipsram_write_command_set(uint32_t write_command_mode,uint32_t write_wait_cycle,uint32_t write_command_code) +void exmc_sqpipsram_write_command_set(uint32_t write_command_mode,uint32_t write_wait_cycle, uint32_t write_command_code) { uint32_t swcmd; - + swcmd = (uint32_t) write_command_mode | ((write_wait_cycle << SWCMD_WWAITCYCLE_OFFSET) & EXMC_SWCMD_WWAITCYCLE) | ((write_command_code & EXMC_SWCMD_WCMD)); @@ -922,6 +1008,7 @@ uint32_t exmc_sqpipsram_high_id_get(void) /*! \brief get the bit value of EXMC send write command bit or read ID command \param[in] send_command_flag: the send command flag + only one parameter can be selected which is shown as below: \arg EXMC_SEND_COMMAND_FLAG_RDID: EXMC_SRCMD_RDID flag bit \arg EXMC_SEND_COMMAND_FLAG_SC: EXMC_SWCMD_SC flag bit \param[out] none @@ -930,14 +1017,14 @@ uint32_t exmc_sqpipsram_high_id_get(void) FlagStatus exmc_sqpipsram_send_command_state_get(uint32_t send_command_flag) { uint32_t flag = 0x00000000U; - + if(EXMC_SEND_COMMAND_FLAG_RDID == send_command_flag){ flag = EXMC_SRCMD; }else if(EXMC_SEND_COMMAND_FLAG_SC == send_command_flag){ flag = EXMC_SWCMD; }else{ } - + if (flag & send_command_flag){ /* flag is set */ return SET; @@ -948,14 +1035,74 @@ FlagStatus exmc_sqpipsram_send_command_state_get(uint32_t send_command_flag) } /*! - \brief check EXMC flag is set or not + \brief enable EXMC interrupt + \param[in] exmc_bank: specifies the NAND bank,PC card bank or SDRAM device + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] interrupt: specify get which interrupt flag + only one parameter can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \arg EXMC_SDRAM_INT_FLAG_REFRESH: refresh error interrupt and flag + \param[out] none + \retval none +*/ +void exmc_interrupt_enable(uint32_t exmc_bank, uint32_t interrupt) +{ + if((EXMC_BANK1_NAND == exmc_bank) || (EXMC_BANK2_NAND == exmc_bank) || (EXMC_BANK3_PCCARD == exmc_bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(exmc_bank) |= interrupt; + }else{ + /* SDRAM device0 or device1 */ + EXMC_SDARI |= EXMC_SDARI_REIE; + } +} + +/*! + \brief disable EXMC interrupt \param[in] exmc_bank: specifies the NAND bank , PC card bank or SDRAM device + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] interrupt: specify get which interrupt flag + only one parameter can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \arg EXMC_SDRAM_INT_FLAG_REFRESH: refresh error interrupt and flag + \param[out] none + \retval none +*/ +void exmc_interrupt_disable(uint32_t exmc_bank, uint32_t interrupt) +{ + if((EXMC_BANK1_NAND == exmc_bank) || (EXMC_BANK2_NAND == exmc_bank) || (EXMC_BANK3_PCCARD == exmc_bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(exmc_bank) &= ~interrupt; + }else{ + /* SDRAM device0 or device1 */ + EXMC_SDARI &= ~EXMC_SDARI_REIE; + } +} + +/*! + \brief get EXMC flag status + \param[in] exmc_bank: specifies the NAND bank , PC card bank or SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_BANK1_NAND: the NAND bank1 \arg EXMC_BANK2_NAND: the NAND bank2 \arg EXMC_BANK3_PCCARD: the PC Card bank \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] flag: specify get which flag + \param[in] flag: EXMC status and flag + only one parameter can be selected which is shown as below: \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status @@ -976,7 +1123,7 @@ FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag) /* SDRAM device0 or device1 */ status = EXMC_SDSTAT; } - + if ((status & flag) != (uint32_t)flag ){ /* flag is reset */ return RESET; @@ -987,14 +1134,16 @@ FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag) } /*! - \brief clear EXMC a channel flag + \brief clear EXMC flag status \param[in] exmc_bank: specifie the NAND bank , PCCARD bank or SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_BANK1_NAND: the NAND bank1 \arg EXMC_BANK2_NAND: the NAND bank2 \arg EXMC_BANK3_PCCARD: the PC card bank \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] flag: specify get which flag + \param[in] flag: EXMC status and flag + only one parameter can be selected which is shown as below: \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status @@ -1004,7 +1153,7 @@ FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag) \param[out] none \retval none */ -void exmc_flag_clear(uint32_t exmc_bank,uint32_t flag) +void exmc_flag_clear(uint32_t exmc_bank, uint32_t flag) { if((EXMC_BANK1_NAND == exmc_bank) || (EXMC_BANK2_NAND == exmc_bank) || (EXMC_BANK3_PCCARD == exmc_bank)){ /* NAND bank1,bank2 or PC card bank3 */ @@ -1012,40 +1161,42 @@ void exmc_flag_clear(uint32_t exmc_bank,uint32_t flag) }else{ /* SDRAM device0 or device1 */ EXMC_SDSTAT &= ~flag; - } + } } /*! - \brief check EXMC interrupt flag is set or not + \brief get EXMC interrupt flag \param[in] exmc_bank: specifies the NAND bank , PC card bank or SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_BANK1_NAND: the NAND bank1 \arg EXMC_BANK2_NAND: the NAND bank2 \arg EXMC_BANK3_PCCARD: the PC card bank \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] interrupt_source: specify get which interrupt flag - \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge - \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level - \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge - \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error + \param[in] interrupt: EXMC interrupt flag + only one parameter can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \arg EXMC_SDRAM_INT_FLAG_REFRESH: refresh error interrupt and flag \param[out] none \retval FlagStatus: SET or RESET */ -FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt_source) +FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank, uint32_t interrupt) { uint32_t status = 0x00000000U,interrupt_enable = 0x00000000U,interrupt_state = 0x00000000U; if((EXMC_BANK1_NAND == exmc_bank) || (EXMC_BANK2_NAND == exmc_bank) || (EXMC_BANK3_PCCARD == exmc_bank)){ /* NAND bank1,bank2 or PC card bank3 */ status = EXMC_NPINTEN(exmc_bank); - interrupt_enable = (status & (interrupt_source >> INTEN_INTEN_OFFSET)); + interrupt_state = (status & (interrupt >> INTEN_INTS_OFFSET)); }else{ /* SDRAM device0 or device1 */ status = EXMC_SDARI; - interrupt_enable = (EXMC_SDSTAT & EXMC_SDSDAT_REIF); + interrupt_state = (EXMC_SDSTAT & EXMC_SDSDAT_REIF); } - interrupt_state = (status & interrupt_source); + interrupt_enable = (status & interrupt); if ((interrupt_enable) && (interrupt_state)){ /* interrupt flag is set */ @@ -1057,82 +1208,30 @@ FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt_source) } /*! - \brief clear EXMC one channel interrupt flag + \brief clear EXMC interrupt flag \param[in] exmc_bank: specifies the NAND bank , PC card bank or SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_BANK1_NAND: the NAND bank1 \arg EXMC_BANK2_NAND: the NAND bank2 \arg EXMC_BANK3_PCCARD: the PC card bank \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] interrupt_source: specify get which interrupt flag - \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge - \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level - \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge - \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error + \param[in] interrupt: EXMC interrupt flag + only one parameter can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \arg EXMC_SDRAM_INT_FLAG_REFRESH: refresh error interrupt and flag \param[out] none \retval none */ -void exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt_source) +void exmc_interrupt_flag_clear(uint32_t exmc_bank, uint32_t interrupt) { if((EXMC_BANK1_NAND == exmc_bank) || (EXMC_BANK2_NAND == exmc_bank) || (EXMC_BANK3_PCCARD == exmc_bank)){ /* NAND bank1,bank2 or PC card bank3 */ - EXMC_NPINTEN(exmc_bank) &= ~(interrupt_source >> INTEN_INTEN_OFFSET); + EXMC_NPINTEN(exmc_bank) &= ~(interrupt >> INTEN_INTS_OFFSET); }else{ /* SDRAM device0 or device1 */ EXMC_SDARI |= EXMC_SDARI_REC; } } - -/*! - \brief enable EXMC interrupt - \param[in] exmc_bank: specifies the NAND bank,PC card bank or SDRAM device - \arg EXMC_BANK1_NAND: the NAND bank1 - \arg EXMC_BANK2_NAND: the NAND bank2 - \arg EXMC_BANK3_PCCARD: the PC card bank - \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 - \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] interrupt_source: specify get which interrupt flag - \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge - \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level - \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge - \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error - \param[out] none - \retval none -*/ -void exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt_source) -{ - if((EXMC_BANK1_NAND == exmc_bank) || (EXMC_BANK2_NAND == exmc_bank) || (EXMC_BANK3_PCCARD == exmc_bank)){ - /* NAND bank1,bank2 or PC card bank3 */ - EXMC_NPINTEN(exmc_bank) |= interrupt_source; - }else{ - /* SDRAM device0 or device1 */ - EXMC_SDARI |= EXMC_SDARI_REIE; - } -} - -/*! - \brief disable EXMC interrupt - \param[in] exmc_bank: specifies the NAND bank , PC card bank or SDRAM device - \arg EXMC_BANK1_NAND: the NAND bank1 - \arg EXMC_BANK2_NAND: the NAND bank2 - \arg EXMC_BANK3_PCCARD: the PC card bank - \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 - \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] interrupt_source: specify get which interrupt flag - \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge - \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level - \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge - \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error - \param[out] none - \retval none -*/ -void exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt_source) -{ - if((EXMC_BANK1_NAND == exmc_bank) || (EXMC_BANK2_NAND == exmc_bank) || (EXMC_BANK3_PCCARD == exmc_bank)){ - /* NAND bank1,bank2 or PC card bank3 */ - EXMC_NPINTEN(exmc_bank) &= ~interrupt_source; - }else{ - /* SDRAM device0 or device1 */ - EXMC_SDARI &= ~EXMC_SDARI_REIE; - } -} diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c index 24bffea316..a3eacb0202 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_exti.c - \brief EXTI driver + \file gd32f4xx_exti.c + \brief EXTI driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.1, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_exti.h" @@ -41,6 +66,7 @@ void exti_deinit(void) \arg EXTI_TRIG_RISING: rising edge trigger \arg EXTI_TRIG_FALLING: falling trigger \arg EXTI_TRIG_BOTH: rising and falling trigger + \arg EXTI_TRIG_NONE: without rising edge or falling edge trigger \param[out] none \retval none */ @@ -53,7 +79,7 @@ void exti_init(exti_line_enum linex, \ EXTI_EVEN &= ~(uint32_t)linex; EXTI_RTEN &= ~(uint32_t)linex; EXTI_FTEN &= ~(uint32_t)linex; - + /* set the EXTI mode and enable the interrupts or events from EXTI line x */ switch(mode){ case EXTI_INTERRUPT: @@ -65,7 +91,7 @@ void exti_init(exti_line_enum linex, \ default: break; } - + /* set the EXTI trigger type */ switch(trig_type){ case EXTI_TRIG_RISING: @@ -80,6 +106,7 @@ void exti_init(exti_line_enum linex, \ EXTI_RTEN |= (uint32_t)linex; EXTI_FTEN |= (uint32_t)linex; break; + case EXTI_TRIG_NONE: default: break; } @@ -98,19 +125,6 @@ void exti_interrupt_enable(exti_line_enum linex) EXTI_INTEN |= (uint32_t)linex; } -/*! - \brief enable the events from EXTI line x - \param[in] linex: EXTI line number, refer to exti_line_enum - only one parameter can be selected which is shown as below: - \arg EXTI_x (x=0..22): EXTI line x - \param[out] none - \retval none -*/ -void exti_event_enable(exti_line_enum linex) -{ - EXTI_EVEN |= (uint32_t)linex; -} - /*! \brief disable the interrupt from EXTI line x \param[in] linex: EXTI line number, refer to exti_line_enum @@ -124,6 +138,19 @@ void exti_interrupt_disable(exti_line_enum linex) EXTI_INTEN &= ~(uint32_t)linex; } +/*! + \brief enable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..22): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_enable(exti_line_enum linex) +{ + EXTI_EVEN |= (uint32_t)linex; +} + /*! \brief disable the events from EXTI line x \param[in] linex: EXTI line number, refer to exti_line_enum @@ -137,71 +164,6 @@ void exti_event_disable(exti_line_enum linex) EXTI_EVEN &= ~(uint32_t)linex; } -/*! - \brief get EXTI lines flag - \param[in] linex: EXTI line number, refer to exti_line_enum - only one parameter can be selected which is shown as below: - \arg EXTI_x (x=0..22): EXTI line x - \param[out] none - \retval FlagStatus: status of flag (RESET or SET) -*/ -FlagStatus exti_flag_get(exti_line_enum linex) -{ - if(RESET != (EXTI_PD & (uint32_t)linex)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear EXTI lines pending flag - \param[in] linex: EXTI line number, refer to exti_line_enum - only one parameter can be selected which is shown as below: - \arg EXTI_x (x=0..22): EXTI line x - \param[out] none - \retval none -*/ -void exti_flag_clear(exti_line_enum linex) -{ - EXTI_PD = (uint32_t)linex; -} - -/*! - \brief get EXTI lines flag when the interrupt flag is set - \param[in] linex: EXTI line number, refer to exti_line_enum - only one parameter can be selected which is shown as below: - \arg EXTI_x (x=0..22): EXTI line x - \param[out] none - \retval FlagStatus: status of flag (RESET or SET) -*/ -FlagStatus exti_interrupt_flag_get(exti_line_enum linex) -{ - uint32_t flag_left, flag_right; - - flag_left = EXTI_PD & (uint32_t)linex; - flag_right = EXTI_INTEN & (uint32_t)linex; - - if((RESET != flag_left) && (RESET != flag_right)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear EXTI lines pending flag - \param[in] linex: EXTI line number, refer to exti_line_enum - only one parameter can be selected which is shown as below: - \arg EXTI_x (x=0..22): EXTI line x - \param[out] none - \retval none -*/ -void exti_interrupt_flag_clear(exti_line_enum linex) -{ - EXTI_PD = (uint32_t)linex; -} - /*! \brief enable EXTI software interrupt event \param[in] linex: EXTI line number, refer to exti_line_enum @@ -227,3 +189,69 @@ void exti_software_interrupt_disable(exti_line_enum linex) { EXTI_SWIEV &= ~(uint32_t)linex; } + +/*! + \brief get EXTI lines flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..22): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_flag_get(exti_line_enum linex) +{ + if(RESET != (EXTI_PD & (uint32_t)linex)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..22): EXTI line x + \param[out] none + \retval none +*/ +void exti_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief get EXTI lines flag when the interrupt flag is set + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..22): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex) +{ + uint32_t flag_left, flag_right; + + flag_left = EXTI_PD & (uint32_t)linex; + flag_right = EXTI_INTEN & (uint32_t)linex; + + if((RESET != flag_left) && (RESET != flag_right)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..22): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c index 2bfc2f1caa..4e2b0db9a5 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c @@ -1,19 +1,46 @@ /*! - \file gd32f4xx_fmc.c - \brief FMC driver + \file gd32f4xx_fmc.c + \brief FMC driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ + #include "gd32f4xx_fmc.h" /*! \brief set the wait state counter value - \param[in] wscntwait state counter value + \param[in] wscnt: wait state counter value + only one parameter can be selected which is shown as below: \arg WS_WSCNT_0: FMC 0 wait \arg WS_WSCNT_1: FMC 1 wait \arg WS_WSCNT_2: FMC 2 wait @@ -36,7 +63,7 @@ void fmc_wscnt_set(uint32_t wscnt) { uint32_t reg; - + reg = FMC_WS; /* set the wait state counter value */ reg &= ~FMC_WC_WSCNT; @@ -73,58 +100,64 @@ void fmc_lock(void) /*! \brief erase sector \param[in] fmc_sector: select the sector to erase - \arg CTL_SECTOR_NUMBER_0: sector 0 - \arg CTL_SECTOR_NUMBER_1: sector 1 - \arg CTL_SECTOR_NUMBER_2: sector 2 - \arg CTL_SECTOR_NUMBER_3: sector 3 - \arg CTL_SECTOR_NUMBER_4: sector 4 - \arg CTL_SECTOR_NUMBER_5: sector 5 - \arg CTL_SECTOR_NUMBER_6: sector 6 - \arg CTL_SECTOR_NUMBER_7: sector 7 - \arg CTL_SECTOR_NUMBER_8: sector 8 - \arg CTL_SECTOR_NUMBER_9: sector 9 - \arg CTL_SECTOR_NUMBER_10: sector 10 - \arg CTL_SECTOR_NUMBER_11: sector 11 - \arg CTL_SECTOR_NUMBER_12: sector 12 - \arg CTL_SECTOR_NUMBER_13: sector 13 - \arg CTL_SECTOR_NUMBER_14: sector 14 - \arg CTL_SECTOR_NUMBER_15: sector 15 - \arg CTL_SECTOR_NUMBER_16: sector 16 - \arg CTL_SECTOR_NUMBER_17: sector 17 - \arg CTL_SECTOR_NUMBER_18: sector 18 - \arg CTL_SECTOR_NUMBER_19: sector 19 - \arg CTL_SECTOR_NUMBER_20: sector 20 - \arg CTL_SECTOR_NUMBER_21: sector 21 - \arg CTL_SECTOR_NUMBER_22: sector 22 - \arg CTL_SECTOR_NUMBER_23: sector 23 - \arg CTL_SECTOR_NUMBER_24: sector 24 - \arg CTL_SECTOR_NUMBER_25: sector 25 - \arg CTL_SECTOR_NUMBER_26: sector 26 - \arg CTL_SECTOR_NUMBER_27: sector 27 - \arg CTL_SECTOR_NUMBER_28: sector 28 - \arg CTL_SECTOR_NUMBER_29: sector 29 - \arg CTL_SECTOR_NUMBER_30: sector 30 + only one parameter can be selected which is shown as below: + \arg CTL_SECTOR_NUMBER_0: sector 0 + \arg CTL_SECTOR_NUMBER_1: sector 1 + \arg CTL_SECTOR_NUMBER_2: sector 2 + \arg CTL_SECTOR_NUMBER_3: sector 3 + \arg CTL_SECTOR_NUMBER_4: sector 4 + \arg CTL_SECTOR_NUMBER_5: sector 5 + \arg CTL_SECTOR_NUMBER_6: sector 6 + \arg CTL_SECTOR_NUMBER_7: sector 7 + \arg CTL_SECTOR_NUMBER_8: sector 8 + \arg CTL_SECTOR_NUMBER_9: sector 9 + \arg CTL_SECTOR_NUMBER_10: sector 10 + \arg CTL_SECTOR_NUMBER_11: sector 11 + \arg CTL_SECTOR_NUMBER_12: sector 12 + \arg CTL_SECTOR_NUMBER_13: sector 13 + \arg CTL_SECTOR_NUMBER_14: sector 14 + \arg CTL_SECTOR_NUMBER_15: sector 15 + \arg CTL_SECTOR_NUMBER_16: sector 16 + \arg CTL_SECTOR_NUMBER_17: sector 17 + \arg CTL_SECTOR_NUMBER_18: sector 18 + \arg CTL_SECTOR_NUMBER_19: sector 19 + \arg CTL_SECTOR_NUMBER_20: sector 20 + \arg CTL_SECTOR_NUMBER_21: sector 21 + \arg CTL_SECTOR_NUMBER_22: sector 22 + \arg CTL_SECTOR_NUMBER_23: sector 23 + \arg CTL_SECTOR_NUMBER_24: sector 24 + \arg CTL_SECTOR_NUMBER_25: sector 25 + \arg CTL_SECTOR_NUMBER_26: sector 26 + \arg CTL_SECTOR_NUMBER_27: sector 27 \param[out] none - \retval fmc_state_enum + \retval state of FMC + \arg FMC_READY: the operation has been completed + \arg FMC_BUSY: the operation is in progress + \arg FMC_RDDERR: read D-bus protection error + \arg FMC_PGSERR: program sequence error + \arg FMC_PGMERR: program size not match error + \arg FMC_WPERR: erase/program protection error + \arg FMC_OPERR: operation error + \arg FMC_PGERR: program error */ fmc_state_enum fmc_sector_erase(uint32_t fmc_sector) { fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + fmc_state = fmc_ready_wait(); + + if(FMC_READY == fmc_state){ /* start sector erase */ FMC_CTL &= ~FMC_CTL_SN; FMC_CTL |= (FMC_CTL_SER | fmc_sector); FMC_CTL |= FMC_CTL_START; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - + fmc_state = fmc_ready_wait(); + /* reset the SER bit */ FMC_CTL &= (~FMC_CTL_SER); - FMC_CTL &= ~FMC_CTL_SN; + FMC_CTL &= ~FMC_CTL_SN; } /* return the FMC state */ @@ -135,21 +168,29 @@ fmc_state_enum fmc_sector_erase(uint32_t fmc_sector) \brief erase whole chip \param[in] none \param[out] none - \retval fmc_state_enum + \retval state of FMC + \arg FMC_READY: the operation has been completed + \arg FMC_BUSY: the operation is in progress + \arg FMC_RDDERR: read D-bus protection error + \arg FMC_PGSERR: program sequence error + \arg FMC_PGMERR: program size not match error + \arg FMC_WPERR: erase/program protection error + \arg FMC_OPERR: operation error + \arg FMC_PGERR: program error */ fmc_state_enum fmc_mass_erase(void) { fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + fmc_state = fmc_ready_wait(); - if(FMC_READY == fmc_state){ - /* start whole chip erase */ + if(FMC_READY == fmc_state){ + /* start whole chip erase */ FMC_CTL |= (FMC_CTL_MER0 | FMC_CTL_MER1); FMC_CTL |= FMC_CTL_START; - + /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + fmc_state = fmc_ready_wait(); /* reset the MER bits */ FMC_CTL &= ~(FMC_CTL_MER0 | FMC_CTL_MER1); @@ -163,21 +204,29 @@ fmc_state_enum fmc_mass_erase(void) \brief erase all FMC sectors in bank0 \param[in] none \param[out] none - \retval fmc_state_enum + \retval state of FMC + \arg FMC_READY: the operation has been completed + \arg FMC_BUSY: the operation is in progress + \arg FMC_RDDERR: read D-bus protection error + \arg FMC_PGSERR: program sequence error + \arg FMC_PGMERR: program size not match error + \arg FMC_WPERR: erase/program protection error + \arg FMC_OPERR: operation error + \arg FMC_PGERR: program error */ fmc_state_enum fmc_bank0_erase(void) { fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + fmc_state = fmc_ready_wait(); if(FMC_READY == fmc_state){ /* start FMC bank0 erase */ FMC_CTL |= FMC_CTL_MER0; FMC_CTL |= FMC_CTL_START; - + /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + fmc_state = fmc_ready_wait(); /* reset the MER0 bit */ FMC_CTL &= (~FMC_CTL_MER0); @@ -191,21 +240,29 @@ fmc_state_enum fmc_bank0_erase(void) \brief erase all FMC sectors in bank1 \param[in] none \param[out] none - \retval fmc_state_enum + \retval state of FMC + \arg FMC_READY: the operation has been completed + \arg FMC_BUSY: the operation is in progress + \arg FMC_RDDERR: read D-bus protection error + \arg FMC_PGSERR: program sequence error + \arg FMC_PGMERR: program size not match error + \arg FMC_WPERR: erase/program protection error + \arg FMC_OPERR: operation error + \arg FMC_PGERR: program error */ fmc_state_enum fmc_bank1_erase(void) { fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - + fmc_state = fmc_ready_wait(); + if(FMC_READY == fmc_state){ /* start FMC bank1 erase */ FMC_CTL |= FMC_CTL_MER1; FMC_CTL |= FMC_CTL_START; - + /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + fmc_state = fmc_ready_wait(); /* reset the MER1 bit */ FMC_CTL &= (~FMC_CTL_MER1); @@ -218,31 +275,39 @@ fmc_state_enum fmc_bank1_erase(void) /*! \brief program a word at the corresponding address \param[in] address: address to program - \param[in] data: word to program + \param[in] data: word to program(0x00000000 - 0xFFFFFFFF) \param[out] none - \retval fmc_state_enum + \retval state of FMC + \arg FMC_READY: the operation has been completed + \arg FMC_BUSY: the operation is in progress + \arg FMC_RDDERR: read D-bus protection error + \arg FMC_PGSERR: program sequence error + \arg FMC_PGMERR: program size not match error + \arg FMC_WPERR: erase/program protection error + \arg FMC_OPERR: operation error + \arg FMC_PGERR: program error */ fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) { fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - + fmc_state = fmc_ready_wait(); + if(FMC_READY == fmc_state){ /* set the PG bit to start program */ FMC_CTL &= ~FMC_CTL_PSZ; FMC_CTL |= CTL_PSZ_WORD; - FMC_CTL |= FMC_CTL_PG; - + FMC_CTL |= FMC_CTL_PG; + REG32(address) = data; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - + fmc_state = fmc_ready_wait(); + /* reset the PG bit */ - FMC_CTL &= ~FMC_CTL_PG; - } - + FMC_CTL &= ~FMC_CTL_PG; + } + /* return the FMC state */ return fmc_state; } @@ -250,31 +315,39 @@ fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) /*! \brief program a half word at the corresponding address \param[in] address: address to program - \param[in] data: halfword to program + \param[in] data: halfword to program(0x0000 - 0xFFFF) \param[out] none - \retval fmc_state_enum + \retval state of FMC + \arg FMC_READY: the operation has been completed + \arg FMC_BUSY: the operation is in progress + \arg FMC_RDDERR: read D-bus protection error + \arg FMC_PGSERR: program sequence error + \arg FMC_PGMERR: program size not match error + \arg FMC_WPERR: erase/program protection error + \arg FMC_OPERR: operation error + \arg FMC_PGERR: program error */ fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) { fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + fmc_state = fmc_ready_wait(); + + if(FMC_READY == fmc_state){ /* set the PG bit to start program */ FMC_CTL &= ~FMC_CTL_PSZ; FMC_CTL |= CTL_PSZ_HALF_WORD; - FMC_CTL |= FMC_CTL_PG; - + FMC_CTL |= FMC_CTL_PG; + REG16(address) = data; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - + fmc_state = fmc_ready_wait(); + /* reset the PG bit */ - FMC_CTL &= ~FMC_CTL_PG; - } - + FMC_CTL &= ~FMC_CTL_PG; + } + /* return the FMC state */ return fmc_state; } @@ -282,31 +355,39 @@ fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) /*! \brief program a byte at the corresponding address \param[in] address: address to program - \param[in] data: byte to program + \param[in] data: byte to program(0x00 - 0xFF) \param[out] none - \retval fmc_state_enum + \retval state of FMC + \arg FMC_READY: the operation has been completed + \arg FMC_BUSY: the operation is in progress + \arg FMC_RDDERR: read D-bus protection error + \arg FMC_PGSERR: program sequence error + \arg FMC_PGMERR: program size not match error + \arg FMC_WPERR: erase/program protection error + \arg FMC_OPERR: operation error + \arg FMC_PGERR: program error */ fmc_state_enum fmc_byte_program(uint32_t address, uint8_t data) { fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - + fmc_state = fmc_ready_wait(); + if(FMC_READY == fmc_state){ /* set the PG bit to start program */ FMC_CTL &= ~FMC_CTL_PSZ; FMC_CTL |= CTL_PSZ_BYTE; FMC_CTL |= FMC_CTL_PG; - + REG8(address) = data; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - + fmc_state = fmc_ready_wait(); + /* reset the PG bit */ - FMC_CTL &= ~FMC_CTL_PG; - } - + FMC_CTL &= ~FMC_CTL_PG; + } + /* return the FMC state */ return fmc_state; } @@ -335,7 +416,7 @@ void ob_unlock(void) void ob_lock(void) { /* reset the OB_LK bit */ - FMC_OBCTL0 &= ~FMC_OBCTL0_OB_LK; + FMC_OBCTL0 |= FMC_OBCTL0_OB_LK; } /*! @@ -346,178 +427,183 @@ void ob_lock(void) */ void ob_start(void) { + fmc_state_enum fmc_state = FMC_READY; /* set the OB_START bit in OBCTL0 register */ FMC_OBCTL0 |= FMC_OBCTL0_OB_START; + fmc_state = fmc_ready_wait(); + if(FMC_READY != fmc_state){ + while(1){ + } + } } /*! - \brief enable write protection - \param[in] ob_wp: specify sector to be write protected - \arg OB_WPx(x=0..11): write protect specify sector - \arg OB_WP_ALL: write protect all sector + \brief erase option byte + \param[in] none \param[out] none \retval none */ -void ob_write_protection0_enable(uint32_t ob_wp) +void ob_erase(void) { + uint32_t reg, reg1; fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + fmc_state = fmc_ready_wait(); if(FMC_READY == fmc_state){ - FMC_OBCTL0 &= (~((uint32_t)ob_wp << 16)); - } -} + reg = FMC_OBCTL0; + reg1 = FMC_OBCTL1; -/*! - \brief disable write protection - \param[in] ob_wp: specify sector to be write protected - \arg OB_WPx(x=0..11): write protect specify sector - \arg OB_WP_ALL: write protect all sector - \param[out] none - \retval none -*/ -void ob_write_protection0_disable(uint32_t ob_wp) -{ - fmc_state_enum fmc_state = FMC_READY; - /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the OB_FWDGT, OB_DEEPSLEEP and OB_STDBY, set according to ob_fwdgt ,ob_deepsleep and ob_stdby */ + reg |= (FMC_OBCTL0_NWDG_HW | FMC_OBCTL0_NRST_DPSLP | FMC_OBCTL0_NRST_STDBY); + /* reset the BOR level */ + reg |= FMC_OBCTL0_BOR_TH; + /* reset option byte boot bank value */ + reg &= ~FMC_OBCTL0_BB; + /* reset option byte dbs value */ + reg &= ~FMC_OBCTL0_DBS; - if(FMC_READY == fmc_state){ - FMC_OBCTL0 |= ((uint32_t)ob_wp << 16); + /* reset drp and wp value */ + reg |= FMC_OBCTL0_WP0; + reg &= (~FMC_OBCTL0_DRP); + FMC_OBCTL0 = reg; + + reg1 |= FMC_OBCTL1_WP1; + FMC_OBCTL1 = reg1; + + FMC_OBCTL0 = reg; } } /*! \brief enable write protection \param[in] ob_wp: specify sector to be write protected - \arg OB_WPx(x=12..30): write protect specify sector - \arg OB_WP_ALL: write protect all sector + one or more parameters can be selected which are shown as below: + \arg OB_WP_x(x=0..22):sector x(x = 0,1,2...22) + \arg OB_WP_23_27: sector23~27 + \arg OB_WP_ALL: all sector \param[out] none \retval none */ -void ob_write_protection1_enable(uint32_t ob_wp) +void ob_write_protection_enable(uint32_t ob_wp) { + uint32_t reg0 = FMC_OBCTL0; + uint32_t reg1 = FMC_OBCTL1; fmc_state_enum fmc_state = FMC_READY; + if(RESET != (FMC_OBCTL0 & FMC_OBCTL0_DRP)){ + while(1){ + } + } /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + fmc_state = fmc_ready_wait(); if(FMC_READY == fmc_state){ - FMC_OBCTL1 &= (~((uint32_t)ob_wp << 16)); + reg0 &= (~((uint32_t)ob_wp << 16)); + reg1 &= (~(ob_wp & 0xFFFF0000U)); + FMC_OBCTL0 = reg0; + FMC_OBCTL1 = reg1; } } /*! \brief disable write protection \param[in] ob_wp: specify sector to be write protected - \arg OB_WPx(x=12..30): write protect specify sector - \arg OB_WP_ALL: write protect all sector + one or more parameters can be selected which are shown as below: + \arg OB_WP_x(x=0..22):sector x(x = 0,1,2...22) + \arg OB_WP_23_27: sector23~27 + \arg OB_WP_ALL: all sector \param[out] none \retval none */ -void ob_write_protection1_disable(uint32_t ob_wp) +void ob_write_protection_disable(uint32_t ob_wp) { + uint32_t reg0 = FMC_OBCTL0; + uint32_t reg1 = FMC_OBCTL1; fmc_state_enum fmc_state = FMC_READY; + if(RESET != (FMC_OBCTL0 & FMC_OBCTL0_DRP)){ + while(1){ + } + } /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + fmc_state = fmc_ready_wait(); if(FMC_READY == fmc_state){ - FMC_OBCTL1 |= ((uint32_t)ob_wp << 16); + reg0 |= ((uint32_t)ob_wp << 16); + reg1 |= (ob_wp & 0xFFFF0000U); + FMC_OBCTL0 = reg0; + FMC_OBCTL1 = reg1; } } -/*! - \brief configure the protection mode - \param[in] ob_drp: configure the protection mode of WPx bits - \arg OB_DRP_DISABLE: the WPx bits used as erase/program protection of each sector - \arg OB_DRP_ENABLE: the WPx bits used as erase/program protection and D-bus read protection of each sector - \param[out] none - \retval none -*/ -void ob_drp_config(uint32_t ob_drp) -{ - FMC_OBCTL0 &= ~FMC_OBCTL0_DRP; - FMC_OBCTL0 |= ob_drp; -} /*! \brief enable erase/program protection and D-bus read protection - \param[in] ob_drp: enable the WPx bits used as erase/program protection and D-bus read protection of each sector - \arg OB_DRPx(x=0..11): erase/program protection and D-bus read protection of specify sector - \arg OB_DRP_ALL: erase/program protection and D-bus read protection of all sector + \param[in] ob_drp: enable the WPx bits used as erase/program protection and D-bus read protection of each sector + one or more parameters can be selected which are shown as below: + \arg OB_DRP_x(x=0..22): sector x(x = 0,1,2...22) + \arg OB_DRP_23_27: sector23~27 + \arg OB_DRP_ALL: all sector \param[out] none \retval none */ -void ob_drp0_enable(uint32_t ob_drp) +void ob_drp_enable(uint32_t ob_drp) { + uint32_t reg0 = FMC_OBCTL0; + uint32_t reg1 = FMC_OBCTL1; fmc_state_enum fmc_state = FMC_READY; + uint32_t drp_state = FMC_OBCTL0 & FMC_OBCTL0_DRP; + uint32_t wp0_state = FMC_OBCTL0 & FMC_OBCTL0_WP0; + uint32_t wp1_state = FMC_OBCTL1 & FMC_OBCTL1_WP1; + /*disable write protection before enable D-bus read protection*/ + if((RESET != drp_state) && ((FMC_OBCTL0_WP0 != wp0_state) && (FMC_OBCTL1_WP1 != wp1_state))){ + while(1){ + } + } /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + fmc_state = fmc_ready_wait(); if(FMC_READY == fmc_state){ - FMC_OBCTL0 |= ((uint32_t)ob_drp << 16); + reg0 &= ~FMC_OBCTL0_WP0; + reg1 &= ~FMC_OBCTL1_WP1; + reg0 |= ((uint32_t)ob_drp << 16); + reg1 |= ((uint32_t)ob_drp & 0xFFFF0000U); + FMC_OBCTL0 = reg0; + FMC_OBCTL1 = reg1; + FMC_OBCTL0 |= FMC_OBCTL0_DRP; } } /*! \brief disable erase/program protection and D-bus read protection \param[in] ob_drp: disable the WPx bits used as erase/program protection and D-bus read protection of each sector - \arg OB_DRPx(x=0..11): erase/program protection and D-bus read protection of specify sector - \arg OB_DRP_ALL: erase/program protection and D-bus read protection of all sector + one or more parameters can be selected which are shown as below: + \arg OB_DRP_x(x=0..22): sector x(x = 0,1,2...22) + \arg OB_DRP_23_27: sector23~27 + \arg OB_DRP_ALL: all sector \param[out] none \retval none */ -void ob_drp0_disable(uint32_t ob_drp) +void ob_drp_disable(uint32_t ob_drp) { + uint32_t reg0 = FMC_OBCTL0; + uint32_t reg1 = FMC_OBCTL1; fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + fmc_state = fmc_ready_wait(); if(FMC_READY == fmc_state){ - FMC_OBCTL0 &= (~((uint32_t)ob_drp << 16)); - } -} + reg0 |= FMC_OBCTL0_WP0; + reg0 &= (~FMC_OBCTL0_DRP); + FMC_OBCTL0 = reg0; -/*! - \brief enable erase/program protection and D-bus read protection - \param[in] ob_drp: enable the WPx bits used as erase/program protection and D-bus read protection of each sector - \arg OB_DRPx(x=12..30): erase/program protection and D-bus read protection of specify sector - \arg OB_DRP_ALL: erase/program protection and D-bus read protection of all sector - \param[out] none - \retval none -*/ -void ob_drp1_enable(uint32_t ob_drp) -{ - fmc_state_enum fmc_state = FMC_READY; - /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ - FMC_OBCTL1 |= ((uint32_t)ob_drp << 16); - } -} - -/*! - \brief disable erase/program protection and D-bus read protection - \param[in] ob_drp: disable the WPx bits used as erase/program protection and D-bus read protection of each sector - \arg OB_DRPx(x=12..30): erase/program protection and D-bus read protection of specify sector - \arg OB_DRP_ALL: erase/program protection and D-bus read protection of all sector - \param[out] none - \retval none -*/ -void ob_drp1_disable(uint32_t ob_drp) -{ - fmc_state_enum fmc_state = FMC_READY; - /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ - FMC_OBCTL1 &= (~((uint32_t)ob_drp << 16)); + reg1 |= FMC_OBCTL1_WP1; + FMC_OBCTL1 = reg1; } } /*! \brief configure security protection level \param[in] ob_spc: specify security protection level + only one parameter can be selected which is shown as below: \arg FMC_NSPC: no security protection \arg FMC_LSPC: low security protection \arg FMC_HSPC: high security protection @@ -528,29 +614,33 @@ void ob_security_protection_config(uint8_t ob_spc) { fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + fmc_state = fmc_ready_wait(); if(FMC_READY == fmc_state){ uint32_t reg; - + reg = FMC_OBCTL0; /* reset the OBCTL0_SPC, set according to ob_spc */ reg &= ~FMC_OBCTL0_SPC; - FMC_OBCTL0 |= ((uint32_t)ob_spc << 8); + reg |= ((uint32_t)ob_spc << 8); + FMC_OBCTL0 = reg; } } /*! - \brief program the FMC user option byte + \brief program the FMC user option byte \param[in] ob_fwdgt: option byte watchdog value + only one parameter can be selected which is shown as below: \arg OB_FWDGT_SW: software free watchdog \arg OB_FWDGT_HW: hardware free watchdog \param[in] ob_deepsleep: option byte deepsleep reset value + only one parameter can be selected which is shown as below: \arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode - \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode + \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode \param[in] ob_stdby:option byte standby reset value + only one parameter can be selected which is shown as below: \arg OB_STDBY_NRST: no reset when entering standby mode - \arg OB_STDBY_RST: generate a reset instead of entering standby mode + \arg OB_STDBY_RST: generate a reset instead of entering standby mode \param[out] none \retval none */ @@ -559,11 +649,11 @@ void ob_user_write(uint32_t ob_fwdgt, uint32_t ob_deepsleep, uint32_t ob_stdby) fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ - fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); - + fmc_state = fmc_ready_wait(); + if(FMC_READY == fmc_state){ uint32_t reg; - + reg = FMC_OBCTL0; /* reset the OB_FWDGT, OB_DEEPSLEEP and OB_STDBY, set according to ob_fwdgt ,ob_deepsleep and ob_stdby */ reg &= ~(FMC_OBCTL0_NWDG_HW | FMC_OBCTL0_NRST_DPSLP | FMC_OBCTL0_NRST_STDBY); @@ -574,17 +664,18 @@ void ob_user_write(uint32_t ob_fwdgt, uint32_t ob_deepsleep, uint32_t ob_stdby) /*! \brief program the option byte BOR threshold value \param[in] ob_bor_th: user option byte + only one parameter can be selected which is shown as below: \arg OB_BOR_TH_VALUE3: BOR threshold value 3 \arg OB_BOR_TH_VALUE2: BOR threshold value 2 \arg OB_BOR_TH_VALUE1: BOR threshold value 1 - \arg OB_BOR_TH_OFF: no BOR function. + \arg OB_BOR_TH_OFF: no BOR function \param[out] none \retval none */ void ob_user_bor_threshold(uint32_t ob_bor_th) { uint32_t reg; - + reg = FMC_OBCTL0; /* set the BOR level */ reg &= ~FMC_OBCTL0_BOR_TH; @@ -594,6 +685,7 @@ void ob_user_bor_threshold(uint32_t ob_bor_th) /*! \brief configure the option byte boot bank value \param[in] boot_mode: specifies the option byte boot bank value + only one parameter can be selected which is shown as below: \arg OB_BB_DISABLE: boot from bank0 \arg OB_BB_ENABLE: boot from bank1 or bank0 if bank1 is void \param[out] none @@ -602,7 +694,7 @@ void ob_user_bor_threshold(uint32_t ob_bor_th) void ob_boot_mode_config(uint32_t boot_mode) { uint32_t reg; - + reg = FMC_OBCTL0; /* set option byte boot bank value */ reg &= ~FMC_OBCTL0_BB; @@ -613,7 +705,7 @@ void ob_boot_mode_config(uint32_t boot_mode) \brief get the FMC user option byte \param[in] none \param[out] none - \retval the FMC user option byte values: ob_fwdgt(Bit0), ob_deepsleep(Bit1), ob_stdby(Bit2). + \retval the FMC user option byte values: ob_fwdgt(Bit0), ob_deepsleep(Bit1), ob_stdby(Bit2) */ uint8_t ob_user_get(void) { @@ -677,7 +769,7 @@ uint16_t ob_drp1_get(void) FlagStatus ob_spc_get(void) { FlagStatus spc_state = RESET; - + if (((uint8_t)(FMC_OBCTL0 >> 8)) != (uint8_t)FMC_NSPC){ spc_state = SET; }else{ @@ -700,9 +792,10 @@ uint8_t ob_user_bor_threshold_get(void) /*! \brief enable FMC interrupt - \param[in] the FMC interrupt source - \arg FMC_INTEN_END: enable FMC end of program interrupt - \arg FMC_INTEN_ERR: enable FMC error interrupt + \param[in] fmc_int: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_END: enable FMC end of program interrupt + \arg FMC_INT_ERR: enable FMC error interrupt \param[out] none \retval none */ @@ -713,9 +806,10 @@ void fmc_interrupt_enable(uint32_t fmc_int) /*! \brief disable FMC interrupt - \param[in] the FMC interrupt source - \arg FMC_INTEN_END: disable FMC end of program interrupt - \arg FMC_INTEN_ERR: disable FMC error interrupt + \param[in] fmc_int: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_END: disable FMC end of program interrupt + \arg FMC_INT_ERR: disable FMC error interrupt \param[out] none \retval none */ @@ -727,12 +821,13 @@ void fmc_interrupt_disable(uint32_t fmc_int) /*! \brief get flag set or reset \param[in] fmc_flag: check FMC flag - \arg FMC_FLAG_BUSY: FMC busy flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BUSY: FMC busy flag bit \arg FMC_FLAG_RDDERR: FMC read D-bus protection error flag bit \arg FMC_FLAG_PGSERR: FMC program sequence error flag bit \arg FMC_FLAG_PGMERR: FMC program size not match error flag bit \arg FMC_FLAG_WPERR: FMC Erase/Program protection error flag bit - \arg FMC_FLAG_OPERR: FMC operation error flag bit + \arg FMC_FLAG_OPERR: FMC operation error flag bit \arg FMC_FLAG_END: FMC end of operation flag bit \param[out] none \retval FlagStatus: SET or RESET @@ -743,17 +838,18 @@ FlagStatus fmc_flag_get(uint32_t fmc_flag) return SET; } /* return the state of corresponding FMC flag */ - return RESET; + return RESET; } /*! \brief clear the FMC pending flag \param[in] FMC_flag: clear FMC flag + only one parameter can be selected which is shown as below: \arg FMC_FLAG_RDDERR: FMC read D-bus protection error flag bit \arg FMC_FLAG_PGSERR: FMC program sequence error flag bit \arg FMC_FLAG_PGMERR: FMC program size not match error flag bit \arg FMC_FLAG_WPERR: FMC erase/program protection error flag bit - \arg FMC_FLAG_OPERR: FMC operation error flag bit + \arg FMC_FLAG_OPERR: FMC operation error flag bit \arg FMC_FLAG_END: FMC end of operation flag bit \param[out] none \retval none @@ -768,23 +864,31 @@ void fmc_flag_clear(uint32_t fmc_flag) \brief get the FMC state \param[in] none \param[out] none - \retval fmc_state_enum + \retval state of FMC + \arg FMC_READY: the operation has been completed + \arg FMC_BUSY: the operation is in progress + \arg FMC_RDDERR: read D-bus protection error + \arg FMC_PGSERR: program sequence error + \arg FMC_PGMERR: program size not match error + \arg FMC_WPERR: erase/program protection error + \arg FMC_OPERR: operation error + \arg FMC_PGERR: program error */ fmc_state_enum fmc_state_get(void) { fmc_state_enum fmc_state = FMC_READY; - + if((FMC_STAT & FMC_FLAG_BUSY) == FMC_FLAG_BUSY){ fmc_state = FMC_BUSY; }else{ - if((FMC_STAT & FMC_FLAG_WPERR) != (uint32_t)0x00){ + if((FMC_STAT & FMC_FLAG_WPERR) != (uint32_t)0x00){ fmc_state = FMC_WPERR; }else{ - if((FMC_STAT & FMC_FLAG_RDDERR) != (uint32_t)0x00){ + if((FMC_STAT & FMC_FLAG_RDDERR) != (uint32_t)0x00){ fmc_state = FMC_RDDERR; }else{ if((FMC_STAT & (uint32_t)0xEF) != (uint32_t)0x00){ - fmc_state = FMC_PGERR; + fmc_state = FMC_PGERR; }else{ if((FMC_STAT & FMC_FLAG_OPERR) != (uint32_t)0x00){ fmc_state = FMC_OPERR; @@ -801,24 +905,28 @@ fmc_state_enum fmc_state_get(void) /*! \brief check whether FMC is ready or not - \param[in] count: FMC_TIMEOUT_COUNT + \param[in] none \param[out] none - \retval fmc_state_enum + \retval state of FMC + \arg FMC_READY: the operation has been completed + \arg FMC_BUSY: the operation is in progress + \arg FMC_RDDERR: read D-bus protection error + \arg FMC_PGSERR: program sequence error + \arg FMC_PGMERR: program size not match error + \arg FMC_WPERR: erase/program protection error + \arg FMC_OPERR: operation error + \arg FMC_PGERR: program error */ -fmc_state_enum fmc_ready_wait(uint32_t count) +fmc_state_enum fmc_ready_wait(void) { fmc_state_enum fmc_state = FMC_BUSY; - + /* wait for FMC ready */ do{ /* get FMC state */ fmc_state = fmc_state_get(); - count--; - }while((FMC_BUSY == fmc_state) && ((uint32_t)RESET != count)); - - if(FMC_BUSY == fmc_state){ - fmc_state = FMC_TOERR; - } + }while(FMC_BUSY == fmc_state); + /* return the FMC state */ return fmc_state; } diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c index 4762344417..04e2c5b99d 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_fwdgt.c - \brief FWDGT driver + \file gd32f4xx_fwdgt.c + \brief FWDGT driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_fwdgt.h" @@ -16,6 +41,17 @@ /* write value to FWDGT_RLD_RLD bit field */ #define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) +/*! + \brief enable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_enable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; +} + /*! \brief disable write access to FWDGT_PSC and FWDGT_RLD \param[in] none @@ -27,6 +63,17 @@ void fwdgt_write_disable(void) FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; } +/*! + \brief start the free watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_enable(void) +{ + FWDGT_CTL = FWDGT_KEY_ENABLE; +} + /*! \brief reload the counter of FWDGT \param[in] none @@ -38,22 +85,11 @@ void fwdgt_counter_reload(void) FWDGT_CTL = FWDGT_KEY_RELOAD; } -/*! - \brief start the free watchdog timer counter - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_enable(void) -{ - FWDGT_CTL = FWDGT_KEY_ENABLE; -} - - /*! \brief configure counter reload value, and prescaler divider value \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) \param[in] prescaler_div: FWDGT prescaler value + only one parameter can be selected which is shown as below: \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 @@ -68,15 +104,15 @@ ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) { uint32_t timeout = FWDGT_PSC_TIMEOUT; uint32_t flag_status = RESET; - + /* enable write access to FWDGT_PSC,and FWDGT_RLD */ FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - + /* wait until the PUD flag to be reset */ do{ flag_status = FWDGT_STAT & FWDGT_STAT_PUD; }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - + if ((uint32_t)RESET != flag_status){ return ERROR; } @@ -89,13 +125,13 @@ ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) do{ flag_status = FWDGT_STAT & FWDGT_STAT_RUD; }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - + if ((uint32_t)RESET != flag_status){ return ERROR; } - + FWDGT_RLD = RLD_RLD(reload_value); - + /* reload the counter */ FWDGT_CTL = FWDGT_KEY_RELOAD; @@ -104,7 +140,8 @@ ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) /*! \brief get flag state of FWDGT - \param[in] flag: flag to get + \param[in] flag: flag to get + only one parameter can be selected which is shown as below: \arg FWDGT_STAT_PUD: a write operation to FWDGT_PSC register is on going \arg FWDGT_STAT_RUD: a write operation to FWDGT_RLD register is on going \param[out] none @@ -112,7 +149,7 @@ ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) */ FlagStatus fwdgt_flag_get(uint16_t flag) { - if(FWDGT_STAT & flag){ + if(RESET != (FWDGT_STAT & flag)){ return SET; } diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c index ccce538926..d3693abb17 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c @@ -1,19 +1,46 @@ /*! - \file gd32f4xx_gpio.c - \brief GPIO driver + \file gd32f4xx_gpio.c + \brief GPIO driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_gpio.h" /*! \brief reset GPIO port - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) \param[out] none \retval none */ @@ -71,22 +98,26 @@ void gpio_deinit(uint32_t gpio_periph) } /*! - \brief set GPIO output mode - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) - \param[in] mode: gpio pin mode + \brief set GPIO mode + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] mode: GPIO pin mode \arg GPIO_MODE_INPUT: input mode \arg GPIO_MODE_OUTPUT: output mode \arg GPIO_MODE_AF: alternate function mode \arg GPIO_MODE_ANALOG: analog mode - \param[in] pull_up_down: gpio pin with pull-up or pull-down resistor - \arg GPIO_PUPD_NONE: without weak pull-up and pull-down resistors - \arg GPIO_PUPD_PULLUP: with weak pull-up resistor - \arg GPIO_PUPD_PULLDOWN:with weak pull-down resistor - \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] pull_up_down: GPIO pin with pull-up or pull-down resistor + \arg GPIO_PUPD_NONE: floating mode, no pull-up and pull-down resistors + \arg GPIO_PUPD_PULLUP: with pull-up resistor + \arg GPIO_PUPD_PULLDOWN:with pull-down resistor + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none \retval none */ -void gpio_mode_set(uint32_t gpio_periph,uint32_t mode,uint32_t pull_up_down,uint32_t pin) +void gpio_mode_set(uint32_t gpio_periph, uint32_t mode, uint32_t pull_up_down, uint32_t pin) { uint16_t i; uint32_t ctl, pupd; @@ -114,25 +145,29 @@ void gpio_mode_set(uint32_t gpio_periph,uint32_t mode,uint32_t pull_up_down,uint /*! \brief set GPIO output type and speed - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) - \param[in] otype: gpio pin output mode + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] otype: GPIO pin output mode \arg GPIO_OTYPE_PP: push pull mode \arg GPIO_OTYPE_OD: open drain mode - \param[in] speed: gpio pin output max speed - \arg GPIO_OSPEED_2MHZ: output max speed 2M - \arg GPIO_OSPEED_25MHZ: output max speed 25M - \arg GPIO_OSPEED_50MHZ: output max speed 50M - \arg GPIO_OSPEED_200MHZ: output max speed 200M - \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] speed: GPIO pin output max speed + \arg GPIO_OSPEED_2MHZ: output max speed 2MHz + \arg GPIO_OSPEED_25MHZ: output max speed 25MHz + \arg GPIO_OSPEED_50MHZ: output max speed 50MHz + \arg GPIO_OSPEED_200MHZ: output max speed 200MHz + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none \retval none */ -void gpio_output_options_set(uint32_t gpio_periph,uint8_t otype,uint32_t speed,uint32_t pin) +void gpio_output_options_set(uint32_t gpio_periph, uint8_t otype, uint32_t speed, uint32_t pin) { uint16_t i; uint32_t ospeedr; - if(0x1U == otype){ + if(GPIO_OTYPE_OD == otype){ GPIO_OMODE(gpio_periph) |= (uint32_t)pin; }else{ GPIO_OMODE(gpio_periph) &= (uint32_t)(~pin); @@ -153,40 +188,52 @@ void gpio_output_options_set(uint32_t gpio_periph,uint8_t otype,uint32_t speed,u } /*! - \brief set GPIO pin - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) - \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \brief set GPIO pin bit + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none \retval none */ -void gpio_bit_set(uint32_t gpio_periph,uint32_t pin) +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin) { GPIO_BOP(gpio_periph) = (uint32_t)pin; } /*! - \brief reset GPIO pin - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) - \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \brief reset GPIO pin bit + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none \retval none */ -void gpio_bit_reset(uint32_t gpio_periph,uint32_t pin) +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin) { GPIO_BC(gpio_periph) = (uint32_t)pin; } /*! \brief write data to the specified GPIO pin - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) - \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL - \param[in] bitvalue: SET or RESET + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] bit_value: SET or RESET \arg RESET: clear the port pin \arg SET: set the port pin \param[out] none \retval none */ -void gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value) +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value) { if(RESET != bit_value){ GPIO_BOP(gpio_periph) = (uint32_t)pin; @@ -197,27 +244,33 @@ void gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value) /*! \brief write data to the specified GPIO port - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) - \param[in] data: specify the value to be written to the port output data register + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] data: specify the value to be written to the port output control register \param[out] none \retval none */ -void gpio_port_write(uint32_t gpio_periph,uint16_t data) +void gpio_port_write(uint32_t gpio_periph, uint16_t data) { GPIO_OCTL(gpio_periph) = (uint32_t)data; } /*! \brief get GPIO pin input status - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) - \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none - \retval input state of gpio pin: SET or RESET + \retval input status of GPIO pin: SET or RESET */ -FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin) +FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin) { if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){ - return SET; + return SET; }else{ return RESET; } @@ -225,23 +278,29 @@ FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin) /*! \brief get GPIO all pins input status - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) \param[out] none - \retval input state of gpio all pins + \retval input status of GPIO all pins */ uint16_t gpio_input_port_get(uint32_t gpio_periph) { - return (uint16_t)(GPIO_ISTAT(gpio_periph)); + return ((uint16_t)GPIO_ISTAT(gpio_periph)); } /*! \brief get GPIO pin output status - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) - \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none - \retval output state of gpio pin: SET or RESET + \retval output status of GPIO pin: SET or RESET */ -FlagStatus gpio_output_bit_get(uint32_t gpio_periph,uint32_t pin) +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin) { if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){ return SET; @@ -252,9 +311,11 @@ FlagStatus gpio_output_bit_get(uint32_t gpio_periph,uint32_t pin) /*! \brief get GPIO all pins output status - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) \param[out] none - \retval output state of gpio all pins + \retval output status of GPIO all pins */ uint16_t gpio_output_port_get(uint32_t gpio_periph) { @@ -263,29 +324,33 @@ uint16_t gpio_output_port_get(uint32_t gpio_periph) /*! \brief set GPIO alternate function - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) - \param[in] alt_func_num: gpio pin af function + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] alt_func_num: GPIO pin af function \arg GPIO_AF_0: SYSTEM \arg GPIO_AF_1: TIMER0, TIMER1 \arg GPIO_AF_2: TIMER2, TIMER3, TIMER4 \arg GPIO_AF_3: TIMER7, TIMER8, TIMER9, TIMER10 \arg GPIO_AF_4: I2C0, I2C1, I2C2 \arg GPIO_AF_5: SPI0, SPI1, SPI2, SPI3, SPI4, SPI5 - \arg GPIO_AF_6: SPI1, SPI2, SAI0 + \arg GPIO_AF_6: SPI1, SPI2, SAI0 \arg GPIO_AF_7: USART0, USART1, USART2 \arg GPIO_AF_8: UART3, UART4, USART5, UART6, UART7 - \arg GPIO_AF_9: CAN0,CAN1, TLI, TIMER11, TIMER12, TIMER13 + \arg GPIO_AF_9: CAN0, CAN1, TLI, TIMER11, TIMER12, TIMER13 \arg GPIO_AF_10: USB_FS, USB_HS \arg GPIO_AF_11: ENET - \arg GPIO_AF_12: FMC, SDIO, USB_HS + \arg GPIO_AF_12: EXMC, SDIO, USB_HS \arg GPIO_AF_13: DCI \arg GPIO_AF_14: TLI \arg GPIO_AF_15: EVENTOUT - \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none \retval none */ -void gpio_af_set(uint32_t gpio_periph,uint32_t alt_func_num,uint32_t pin) +void gpio_af_set(uint32_t gpio_periph, uint32_t alt_func_num, uint32_t pin) { uint16_t i; uint32_t afrl, afrh; @@ -314,18 +379,22 @@ void gpio_af_set(uint32_t gpio_periph,uint32_t alt_func_num,uint32_t pin) } /*! - \brief lock GPIO pin - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) - \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \brief lock GPIO pin bit + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none \retval none */ -void gpio_pin_lock(uint32_t gpio_periph,uint32_t pin) +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin) { uint32_t lock = 0x00010000U; lock |= pin; - /* lock key writing sequence: write 1->write 0->write 1-> read 0-> read 1 */ + /* lock key writing sequence: write 1->write 0->write 1->read 0->read 1 */ GPIO_LOCK(gpio_periph) = (uint32_t)lock; GPIO_LOCK(gpio_periph) = (uint32_t)pin; GPIO_LOCK(gpio_periph) = (uint32_t)lock; @@ -334,20 +403,27 @@ void gpio_pin_lock(uint32_t gpio_periph,uint32_t pin) } /*! - \brief toggle GPIO pin - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) - \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \brief toggle GPIO pin status + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none \retval none */ -void gpio_bit_toggle(uint32_t gpio_periph,uint32_t pin) +void gpio_bit_toggle(uint32_t gpio_periph, uint32_t pin) { GPIO_TG(gpio_periph) = (uint32_t)pin; } /*! - \brief toggle GPIO port - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \brief toggle GPIO port status + \param[in] gpio_periph: GPIO port + only one parameter can be selected which is shown as below: + \arg GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[out] none \retval none */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c index 79480b63e5..c3ac50c178 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c @@ -1,19 +1,51 @@ /*! - \file gd32f4xx_i2c.c - \brief I2C driver + \file gd32f4xx_i2c.c + \brief I2C driver + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2019-04-16, V2.0.2, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_i2c.h" -#define I2CCLK_MAX 0x3fU /*!< i2cclk max value */ -#define I2C_STATE_MASK 0x0000FFFFU /*!< i2c state mask */ +/* I2C register bit mask */ +#define I2CCLK_MAX ((uint32_t)0x00000032U) /*!< i2cclk maximum value */ +#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */ +#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */ +#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */ +#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */ + +/* I2C register bit offset */ +#define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */ /*! \brief reset I2C @@ -25,202 +57,229 @@ void i2c_deinit(uint32_t i2c_periph) { switch(i2c_periph){ case I2C0: + /* reset I2C0 */ rcu_periph_reset_enable(RCU_I2C0RST); rcu_periph_reset_disable(RCU_I2C0RST); break; case I2C1: + /* reset I2C1 */ rcu_periph_reset_enable(RCU_I2C1RST); rcu_periph_reset_disable(RCU_I2C1RST); break; case I2C2: + /* reset I2C2 */ rcu_periph_reset_enable(RCU_I2C2RST); rcu_periph_reset_disable(RCU_I2C2RST); break; default: break; - } } /*! - \brief I2C clock configure + \brief configure I2C clock \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] clkspeed: i2c clock speed + \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) \param[in] dutycyc: duty cycle in fast mode - \arg I2C_DTCY_2: T_low/T_high=2 + only one parameter can be selected which is shown as below: + \arg I2C_DTCY_2: T_low/T_high=2 \arg I2C_DTCY_16_9: T_low/T_high=16/9 \param[out] none \retval none */ -void i2c_clock_config(uint32_t i2c_periph,uint32_t clkspeed,uint32_t dutycyc) +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) { - uint32_t pclk1,clkc,i2cclk,risetime; + uint32_t pclk1, clkc, freq, risetime; + uint32_t temp; + pclk1 = rcu_clock_freq_get(CK_APB1); - /* I2C Peripheral clock frequency */ - i2cclk=((pclk1)/(uint32_t)(1000000)); - if(i2cclk >= I2CCLK_MAX){ - i2cclk = I2CCLK_MAX; + /* I2C peripheral clock frequency */ + freq = (uint32_t)(pclk1/1000000U); + if(freq >= I2CCLK_MAX){ + freq = I2CCLK_MAX; } - - I2C_CTL1(i2c_periph) |= (I2C_CTL1_I2CCLK & i2cclk) ; - + temp = I2C_CTL1(i2c_periph); + temp &= ~I2C_CTL1_I2CCLK; + temp |= freq; + + I2C_CTL1(i2c_periph) = temp; + if(100000U >= clkspeed){ - /* standard mode the maximum SCL rise time in standard mode is 1000ns */ + /* the maximum SCL rise time is 1000ns in standard mode */ risetime = (uint32_t)((pclk1/1000000U)+1U); if(risetime >= I2CCLK_MAX){ - I2C_RT(i2c_periph) |= I2CCLK_MAX; + I2C_RT(i2c_periph) = I2CCLK_MAX; }else{ - I2C_RT(i2c_periph) |= (uint32_t)((pclk1/1000000U)+1U); + I2C_RT(i2c_periph) = risetime; } clkc = (uint32_t)(pclk1/(clkspeed*2U)); if(clkc < 0x04U){ - /* The CLKC in standard mode minmum value is 4*/ + /* the CLKC in standard mode minmum value is 4 */ clkc = 0x04U; } - I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); - }else{ - /* fast mode the maximum SCL rise time in standard mode is 300ns */ - I2C_RT(i2c_periph) |= (uint16_t)(((i2cclk*(uint16_t)300)/(uint16_t)1000)+(uint16_t)1); + I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); + + }else if(400000U >= clkspeed){ + /* the maximum SCL rise time is 300ns in fast mode */ + I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)300U)/(uint32_t)1000U)+(uint32_t)1U); if(I2C_DTCY_2 == dutycyc){ - /* I2C_DutyCycle == 2 */ - clkc = (uint16_t)(pclk1/(clkspeed*3U)); - } else{ - /* I2C_DutyCycle == 16/9 */ - clkc = (uint16_t)(pclk1/(clkspeed*25U)); + /* I2C duty cycle is 2 */ + clkc = (uint32_t)(pclk1/(clkspeed*3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + }else{ + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t)(pclk1/(clkspeed*25U)); I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; } - if((clkc & I2C_CKCFG_CLKC) == 0U){ - /* The CLKC in standard mode minmum value is 1*/ - clkc |= (uint16_t)0x0001; + if(0U == (clkc & I2C_CKCFG_CLKC)){ + /* the CLKC in fast mode minmum value is 1 */ + clkc |= 0x0001U; } + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; I2C_CKCFG(i2c_periph) |= clkc; + }else{ } } /*! - \brief I2C address configure + \brief configure I2C address \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] i2cmod: - \arg I2C_I2CMODE_ENABLE: I2C mode + \param[in] mode: + only one parameter can be selected which is shown as below: + \arg I2C_I2CMODE_ENABLE: I2C mode \arg I2C_SMBUSMODE_ENABLE: SMBus mode \param[in] addformat: 7bits or 10bits - \arg I2C_ADDFORMAT_7BITS: 7bits + only one parameter can be selected which is shown as below: + \arg I2C_ADDFORMAT_7BITS: 7bits \arg I2C_ADDFORMAT_10BITS: 10bits \param[in] addr: I2C address \param[out] none \retval none */ -void i2c_mode_addr_config(uint32_t i2c_periph,uint32_t i2cmod,uint32_t addformat,uint32_t addr) +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr) { /* SMBus/I2C mode selected */ uint32_t ctl = 0U; + ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SMBEN); - ctl |= i2cmod; + ctl &= ~(I2C_CTL0_SMBEN); + ctl |= mode; I2C_CTL0(i2c_periph) = ctl; /* configure address */ - I2C_SADDR0(i2c_periph) = (addformat|addr); - + addr = addr & I2C_ADDRESS_MASK; + I2C_SADDR0(i2c_periph) = (addformat | addr); } /*! \brief SMBus type selection \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] ack: + \param[in] type: + only one parameter can be selected which is shown as below: \arg I2C_SMBUS_DEVICE: device \arg I2C_SMBUS_HOST: host \param[out] none \retval none */ -void i2c_smbus_type_config(uint32_t i2c_periph,uint32_t type) +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) { if(I2C_SMBUS_HOST == type){ - I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; + I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; }else{ - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); - } + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); + } } /*! \brief whether or not to send an ACK \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] ack: - \arg I2C_ACK_ENABLE: ACK will be sent - \arg I2C_ACK_DISABLE: ACK will not be sent - \param[out] none - \retval none -*/ -void i2c_ack_config(uint32_t i2c_periph,uint8_t ack) -{ - if(I2C_ACK_ENABLE == ack){ - I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; - }else{ - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); - } -} - -/*! - \brief I2C POAP position configure - \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] pos: - \arg I2C_ACK_ENABLE: ACK will be sent + only one parameter can be selected which is shown as below: + \arg I2C_ACK_ENABLE: ACK will be sent \arg I2C_ACK_DISABLE: ACK will not be sent \param[out] none \retval none */ -void i2c_ackpos_config(uint32_t i2c_periph,uint8_t pos) +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) { - /* configure i2c POAP position */ - if(I2C_ACKPOS_NEXT == pos){ - I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; + if(I2C_ACK_ENABLE == ack){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; }else{ - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); - } - + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); + } } /*! - \brief master send slave address + \brief configure I2C POAP position \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] addr: slave address - \param[in] trandirection: transmitter or receiver - \arg I2C_TRANSMITTER: transmitter - \arg I2C_RECEIVER: receiver + \param[in] pos: + only one parameter can be selected which is shown as below: + \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current + \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte \param[out] none \retval none */ -void i2c_master_addressing(uint32_t i2c_periph,uint8_t addr,uint32_t trandirection) +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) { - if(I2C_TRANSMITTER==trandirection){ - addr = (uint8_t)((uint32_t)addr & I2C_TRANSMITTER); + /* configure I2C POAP position */ + if(I2C_ACKPOS_NEXT == pos){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; }else{ - addr = (uint8_t)((uint32_t)addr|I2C_RECEIVER); + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); } +} + +/*! + \brief master sends slave address + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] addr: slave address + \param[in] trandirection: transmitter or receiver + only one parameter can be selected which is shown as below: + \arg I2C_TRANSMITTER: transmitter + \arg I2C_RECEIVER: receiver + \param[out] none + \retval none +*/ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection) +{ + /* master is a transmitter or a receiver */ + if(I2C_TRANSMITTER == trandirection){ + addr = addr & I2C_TRANSMITTER; + }else{ + addr = addr | I2C_RECEIVER; + } + /* send slave address */ I2C_DATA(i2c_periph) = addr; } /*! - \brief dual-address mode switch + \brief enable dual-address mode \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] dualaddr: - \arg I2C_DUADEN_DISABLE: dual-address mode disabled - \arg I2C_DUADEN_ENABLE: dual-address mode enabled + \param[in] addr: the second address in dual-address mode \param[out] none \retval none */ -void i2c_dualaddr_enable(uint32_t i2c_periph,uint8_t dualaddr) +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) { - if(I2C_DUADEN_ENABLE == dualaddr){ - I2C_SADDR1(i2c_periph) |= I2C_SADDR1_DUADEN; - }else{ - I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); - } + /* configure address */ + addr = addr & I2C_ADDRESS2_MASK; + I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr); } /*! - \brief enable i2c - \param[in] i2c_periph: I2Cx(x=0,1,2) + \brief disable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval none +*/ +void i2c_dualaddr_disable(uint32_t i2c_periph) +{ + I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); +} + +/*! + \brief enable I2C + \param[in] i2c_periph: I2Cx(x=0,1,2) \param[out] none \retval none */ @@ -230,15 +289,14 @@ void i2c_enable(uint32_t i2c_periph) } /*! - \brief disable i2c - \param[in] i2c_periph: I2Cx(x=0,1,2) + \brief disable I2C + \param[in] i2c_periph: I2Cx(x=0,1,2) \param[out] none \retval none */ void i2c_disable(uint32_t i2c_periph) { I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); - } /*! @@ -264,91 +322,96 @@ void i2c_stop_on_bus(uint32_t i2c_periph) } /*! - \brief i2c transmit data function + \brief I2C transmit data function \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] data: data of transmission + \param[in] data: data of transmission \param[out] none \retval none */ -void i2c_transmit_data(uint32_t i2c_periph,uint8_t data) +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) { - I2C_DATA(i2c_periph) = data; + I2C_DATA(i2c_periph) = DATA_TRANS(data); } /*! - \brief i2c receive data function + \brief I2C receive data function \param[in] i2c_periph: I2Cx(x=0,1,2) \param[out] none \retval data of received */ -uint8_t i2c_receive_data(uint32_t i2c_periph) +uint8_t i2c_data_receive(uint32_t i2c_periph) { - return (uint8_t)I2C_DATA(i2c_periph); + return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph)); } /*! - \brief I2C DMA mode enable + \brief enable I2C DMA mode \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] dmastste: - \arg I2C_DMA_ON: DMA mode enabled - \arg I2C_DMA_OFF: DMA mode disabled + \param[in] dmastate: + only one parameter can be selected which is shown as below: + \arg I2C_DMA_ON: DMA mode enable + \arg I2C_DMA_OFF: DMA mode disable \param[out] none \retval none */ -void i2c_dma_enable(uint32_t i2c_periph,uint32_t dmastste) +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) { - /* configure i2c DMA function */ + /* configure I2C DMA function */ uint32_t ctl = 0U; - ctl = I2C_CTL1(i2c_periph); - ctl &= ~(I2C_CTL1_DMAON); - ctl |= dmastste; - I2C_CTL1(i2c_periph) = ctl; + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMAON); + ctl |= dmastate; + I2C_CTL1(i2c_periph) = ctl; } /*! - \brief flag indicating DMA last transfer + \brief configure whether next DMA EOT is DMA last transfer or not \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] dmastste: + \param[in] dmalast: + only one parameter can be selected which is shown as below: \arg I2C_DMALST_ON: next DMA EOT is the last transfer \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer \param[out] none \retval none */ -void i2c_dma_last_transfer_enable(uint32_t i2c_periph,uint32_t dmalast) +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) { /* configure DMA last transfer */ uint32_t ctl = 0U; + ctl = I2C_CTL1(i2c_periph); - ctl &= ~(I2C_CTL1_DMALST); + ctl &= ~(I2C_CTL1_DMALST); ctl |= dmalast; I2C_CTL1(i2c_periph) = ctl; - } /*! - \brief whether to stretch SCL low when data is not ready in slave mode + \brief whether to stretch SCL low when data is not ready in slave mode \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] stretchpara: + only one parameter can be selected which is shown as below: \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled \param[out] none \retval none */ -void i2c_stretch_scl_low_config(uint32_t i2c_periph,uint32_t stretchpara) +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) { /* configure I2C SCL strerching enable or disable */ uint32_t ctl = 0U; + ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_DISSTRC); + ctl &= ~(I2C_CTL0_SS); ctl |= stretchpara; I2C_CTL0(i2c_periph) = ctl; } /*! - \brief whether or not to response to a general Cal + \brief whether or not to response to a general call \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] gcallpara: + only one parameter can be selected which is shown as below: \arg I2C_GCEN_ENABLE: slave will response to a general call \arg I2C_GCEN_DISABLE: slave will not response to a general call \param[out] none @@ -358,16 +421,18 @@ void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) { /* configure slave response to a general call enable or disable */ uint32_t ctl = 0U; + ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_GCEN); + ctl &= ~(I2C_CTL0_GCEN); ctl |= gcallpara; I2C_CTL0(i2c_periph) = ctl; } /*! - \brief software reset I2C + \brief software reset I2C \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] sreset: + only one parameter can be selected which is shown as below: \arg I2C_SRESET_SET: I2C is under reset \arg I2C_SRESET_RESET: I2C is not under reset \param[out] none @@ -377,134 +442,30 @@ void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) { /* modify CTL0 and configure software reset I2C state */ uint32_t ctl = 0U; + ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SRESET); + ctl &= ~(I2C_CTL0_SRESET); ctl |= sreset; I2C_CTL0(i2c_periph) = ctl; } -/*! - \brief check i2c state - \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] state: - \arg I2C_SBSEND: start condition send out - \arg I2C_ADDSEND: address is sent in master mode or received and matches in slave mode - \arg I2C_BTC: byte transmission finishes - \arg I2C_ADD10SEND: header of 10-bit address is sent in master mode - \arg I2C_STPDET: etop condition detected in slave mode - \arg I2C_RBNE: I2C_DATA is not Empty during receiving - \arg I2C_TBE: I2C_DATA is empty during transmitting - \arg I2C_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus - \arg I2C_LOSTARB: arbitration lost in master mode - \arg I2C_AERR: acknowledge error - \arg I2C_OUERR: over-run or under-run situation occurs in slave mode - \arg I2C_PECERR: PEC error when receiving data - \arg I2C_SMBTO: timeout signal in SMBus mode - \arg I2C_SMBALT: SMBus alert status - \arg I2C_MASTER: a flag indicating whether I2C block is in master or slave mode - \arg I2C_I2CBSY: busy flag - \arg I2C_TRS: whether the I2C is a transmitter or a receiver - \arg I2C_RXGC: general call address (00h) received - \arg I2C_DEFSMB: default address of SMBus device - \arg I2C_HSTSMB: SMBus host header detected in slave mode - \arg I2C_DUMODF: dual flag in slave mode indicating which address is matched in dual-address mode - \param[out] none - \retval state of i2c -*/ -FlagStatus i2c_flag_get(uint32_t i2c_periph,uint32_t state ) -{ - uint32_t reg = 0U; - FlagStatus regstate = RESET; - /* get the state in which register */ - reg = (BIT(31) & state); - if((BIT(31) == reg)){ - if((I2C_STAT1(i2c_periph)&(state & I2C_STATE_MASK))){ - regstate = SET; - }else{ - regstate = RESET; - } - }else{ - if((I2C_STAT0(i2c_periph)&(state & I2C_STATE_MASK))){ - regstate = SET; - }else{ - regstate = RESET; - } - } - /* return the state */ - return regstate; -} - -/*! - \brief clear i2c state - \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] state: state type - \@arg I2C_STAT0_SMBALT: SMBus Alert status - \@arg I2C_STAT0_SMBTO: timeout signal in SMBus mode - \@arg I2C_STAT0_PECERR: PEC error when receiving data - \@arg I2C_STAT0_OUERR: over-run or under-run situation occurs in slave mode - \@arg I2C_STAT0_AERR: acknowledge error - \@arg I2C_STAT0_LOSTARB: arbitration lost in master mode - \@arg I2C_STAT0_BERR: a bus error - \@arg I2C_STAT0_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 - \param[out] none - \retval none -*/ -void i2c_flag_clear(uint32_t i2c_periph,uint32_t state) -{ - if(I2C_STAT0_ADDSEND == state){ - /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ - I2C_STAT0(i2c_periph); - I2C_STAT1(i2c_periph); - }else{ - I2C_STAT0(i2c_periph) &= ~(state); - } -} - -/*! - \brief enable i2c interrupt - \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] inttype: interrupt type - \arg I2C_CTL1_ERRIE: error interrupt enable - \arg I2C_CTL1_EVIE: event interrupt enable - \arg I2C_CTL1_BUFIE: buffer interrupt enable - \param[out] none - \retval none -*/ -void i2c_interrupt_enable(uint32_t i2c_periph,uint32_t inttype) -{ - I2C_CTL1(i2c_periph) |= (inttype); -} - -/*! - \brief disable i2c interrupt - \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] inttype: interrupt type - \arg I2C_CTL1_ERRIE: error interrupt enable - \arg I2C_CTL1_EVIE: event interrupt enable - \arg I2C_CTL1_BUFIE: buffer interrupt enable - \param[out] none - \retval none -*/ -void i2c_interrupt_disable(uint32_t i2c_periph,uint32_t inttype) -{ - I2C_CTL1(i2c_periph) &= ~(inttype); -} - /*! \brief I2C PEC calculation on or off \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] pecpara: - \arg I2C_PEC_ENABLE: PEC calculation on - \arg I2C_PEC_DISABLE: PEC calculation off + \param[in] pecstate: + only one parameter can be selected which is shown as below: + \arg I2C_PEC_ENABLE: PEC calculation on + \arg I2C_PEC_DISABLE: PEC calculation off \param[out] none \retval none */ -void i2c_pec_enable(uint32_t i2c_periph,uint32_t pecstate) +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate) { /* on/off PEC calculation */ uint32_t ctl = 0U; + ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_PECEN); + ctl &= ~(I2C_CTL0_PECEN); ctl |= pecstate; I2C_CTL0(i2c_periph) = ctl; } @@ -513,66 +474,72 @@ void i2c_pec_enable(uint32_t i2c_periph,uint32_t pecstate) \brief I2C whether to transfer PEC value \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] pecpara: - \arg I2C_PECTRANS_ENABLE: transfer PEC - \arg I2C_PECTRANS_DISABLE: not transfer PEC + only one parameter can be selected which is shown as below: + \arg I2C_PECTRANS_ENABLE: transfer PEC + \arg I2C_PECTRANS_DISABLE: not transfer PEC \param[out] none \retval none */ -void i2c_pec_transfer_enable(uint32_t i2c_periph,uint32_t pecpara) +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara) { /* whether to transfer PEC */ uint32_t ctl = 0U; + ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_PECTRANS); + ctl &= ~(I2C_CTL0_PECTRANS); ctl |= pecpara; I2C_CTL0(i2c_periph) = ctl; } /*! - \brief packet error checking value + \brief get packet error checking value \param[in] i2c_periph: I2Cx(x=0,1,2) \param[out] none \retval PEC value */ -uint8_t i2c_pec_value(uint32_t i2c_periph) +uint8_t i2c_pec_value_get(uint32_t i2c_periph) { - return (uint8_t)((I2C_STAT1(i2c_periph) &I2C_STAT1_ECV)>>8); + return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV)>>STAT1_PECV_OFFSET); } /*! - \brief I2C issue alert through SMBA pin + \brief I2C issue alert through SMBA pin \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] smbuspara: - \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin - \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin + only one parameter can be selected which is shown as below: + \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin + \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin \param[out] none \retval none */ -void i2c_smbus_alert_issue(uint32_t i2c_periph,uint32_t smbuspara) +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) { /* issue alert through SMBA pin configure*/ uint32_t ctl = 0U; + ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SALT); + ctl &= ~(I2C_CTL0_SALT); ctl |= smbuspara; I2C_CTL0(i2c_periph) = ctl; } /*! - \brief I2C ARP protocol in SMBus switch enable or disable + \brief enable or disable I2C ARP protocol in SMBus switch \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] smbuspara: - \arg I2C_ARP_ENABLE: ARP is enabled - \arg I2C_ARP_DISABLE: ARP is disabled + \param[in] arpstate: + only one parameter can be selected which is shown as below: + \arg I2C_ARP_ENABLE: enable ARP + \arg I2C_ARP_DISABLE: disable ARP \param[out] none \retval none */ -void i2c_smbus_arp_enable(uint32_t i2c_periph,uint32_t arpstate) +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate) { /* enable or disable I2C ARP protocol*/ uint32_t ctl = 0U; + ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_ARPEN); + ctl &= ~(I2C_CTL0_ARPEN); ctl |= arpstate; I2C_CTL0(i2c_periph) = ctl; } @@ -585,7 +552,7 @@ void i2c_smbus_arp_enable(uint32_t i2c_periph,uint32_t arpstate) */ void i2c_analog_noise_filter_disable(uint32_t i2c_periph) { - I2C_FCTL(i2c_periph) |= I2C_FCTL_AFD; + I2C_FCTL(i2c_periph) |= I2C_FCTL_AFD; } /*! @@ -596,19 +563,19 @@ void i2c_analog_noise_filter_disable(uint32_t i2c_periph) */ void i2c_analog_noise_filter_enable(uint32_t i2c_periph) { - I2C_FCTL(i2c_periph) &= ~(I2C_FCTL_AFD); + I2C_FCTL(i2c_periph) &= ~(I2C_FCTL_AFD); } /*! \brief digital noise filter configuration \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] dfilterpara: refer to enum i2c_gcall_config_enum + \param[in] dfilterpara: refer to enum i2c_digital_filter_enum \param[out] none \retval none */ void i2c_digital_noise_filter_config(uint32_t i2c_periph,i2c_digital_filter_enum dfilterpara) { - I2C_FCTL(i2c_periph) |= dfilterpara; + I2C_FCTL(i2c_periph) |= dfilterpara; } /*! @@ -619,7 +586,7 @@ void i2c_digital_noise_filter_config(uint32_t i2c_periph,i2c_digital_filter_enum */ void i2c_sam_enable(uint32_t i2c_periph) { - I2C_SAMCS(i2c_periph) |= I2C_SAMCS_SAMEN; + I2C_SAMCS(i2c_periph) |= I2C_SAMCS_SAMEN; } /*! @@ -630,7 +597,7 @@ void i2c_sam_enable(uint32_t i2c_periph) */ void i2c_sam_disable(uint32_t i2c_periph) { - I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_SAMEN); + I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_SAMEN); } /*! @@ -641,7 +608,7 @@ void i2c_sam_disable(uint32_t i2c_periph) */ void i2c_sam_timeout_enable(uint32_t i2c_periph) { - I2C_SAMCS(i2c_periph) |= I2C_SAMCS_STOEN; + I2C_SAMCS(i2c_periph) |= I2C_SAMCS_STOEN; } /*! @@ -652,79 +619,201 @@ void i2c_sam_timeout_enable(uint32_t i2c_periph) */ void i2c_sam_timeout_disable(uint32_t i2c_periph) { - I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_STOEN); + I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_STOEN); } /*! - \brief enable the specified I2C SAM interrupt + \brief check I2C flag is set or not \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] inttype: interrupt type - \@arg I2C_SAMCS_TFFIE: txframe fall interrupt - \@arg I2C_SAMCS_TFRIE: txframe rise interrupt - \@arg I2C_SAMCS_RFFIE: rxframe fall interrupt - \@arg I2C_SAMCS_RFRIE: rxframe rise interrupt - \param[out] none - \retval none -*/ -void i2c_sam_interrupt_enable(uint32_t i2c_periph,uint32_t inttype) -{ - I2C_SAMCS(i2c_periph) |= (inttype); -} - -/*! - \brief disable i2c interrupt - \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] inttype: interrupt type - \@arg I2C_SAMCS_TFFIE: txframe fall interrupt - \@arg I2C_SAMCS_TFRIE: txframe rise interrupt - \@arg I2C_SAMCS_RFFIE: rxframe fall interrupt - \@arg I2C_SAMCS_RFRIE: rxframe rise interrupt + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SBSEND: start condition send out + \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode + \arg I2C_FLAG_BTC: byte transmission finishes + \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode + \arg I2C_FLAG_STPDET: stop condition detected in slave mode + \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving + \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting + \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_SMBALT: SMBus alert status + \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode + \arg I2C_FLAG_I2CBSY: busy flag + \arg I2C_FLAG_TRS: whether the I2C is a transmitter or a receiver + \arg I2C_FLAG_RXGC: general call address (00h) received + \arg I2C_FLAG_DEFSMB: default address of SMBus device + \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode + \arg I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode + \arg I2C_FLAG_TFF: txframe fall flag + \arg I2C_FLAG_TFR: txframe rise flag + \arg I2C_FLAG_RFF: rxframe fall flag + \arg I2C_FLAG_RFR: rxframe rise flag \param[out] none - \retval none + \retval FlagStatus: SET or RESET */ -void i2c_sam_interrupt_disable(uint32_t i2c_periph,uint32_t inttype) +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) { - I2C_SAMCS(i2c_periph) &= ~(inttype); -} - -/*! - \brief check i2c SAM state - \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] samstate: state type - \@arg I2C_SAMCS_TXF: level of txframe signal - \@arg I2C_SAMCS_RXF: level of rxframe signal - \@arg I2C_SAMCS_TFF: txframe fall flag - \@arg I2C_SAMCS_TFR: txframe rise flag - \@arg I2C_SAMCS_RFF: rxframe fall flag - \@arg I2C_SAMCS_RFR: rxframe rise flag - \param[out] none - \retval state of i2c SAM -*/ -FlagStatus i2c_sam_flag_get(uint32_t i2c_periph,uint32_t samstate) -{ - FlagStatus reg = RESET; - if(I2C_SAMCS(i2c_periph)&samstate){ - reg =SET; + if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){ + return SET; }else{ - reg =RESET; + return RESET; } - return reg; } /*! - \brief clear i2c SAM state + \brief clear I2C flag \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] samstate: state type - \@arg I2C_SAMCS_TFF: txframe fall flag - \@arg I2C_SAMCS_TFR: txframe rise flag - \@arg I2C_SAMCS_RFF: rxframe fall flag - \@arg I2C_SAMCS_RFR: rxframe rise flag + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SMBALT: SMBus Alert status + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_BERR: a bus error + \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 + \arg I2C_FLAG_TFF: txframe fall flag + \arg I2C_FLAG_TFR: txframe rise flag + \arg I2C_FLAG_RFF: rxframe fall flag + \arg I2C_FLAG_RFR: rxframe rise flag \param[out] none \retval none */ -void i2c_sam_flag_clear(uint32_t i2c_periph,uint32_t samstate) +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) { - I2C_SAMCS(i2c_periph) &= ~(samstate); - + if(I2C_FLAG_ADDSEND == flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); + } } +/*! + \brief enable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \arg I2C_INT_TFF: txframe fall interrupt enable + \arg I2C_INT_TFR: txframe rise interrupt enable + \arg I2C_INT_RFF: rxframe fall interrupt enable + \arg I2C_INT_RFR: rxframe rise interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief disable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \arg I2C_INT_TFF: txframe fall interrupt enable + \arg I2C_INT_TFR: txframe rise interrupt enable + \arg I2C_INT_RFF: rxframe fall interrupt enable + \arg I2C_INT_RFR: rxframe rise interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief check I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BTC: byte transmission finishes + \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag + \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag + \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag + \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \arg I2C_INT_FLAG_TFF: txframe fall interrupt flag + \arg I2C_INT_FLAG_TFR: txframe rise interrupt flag + \arg I2C_INT_FLAG_RFF: rxframe fall interrupt flag + \arg I2C_INT_FLAG_RFR: rxframe rise interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U, bufie; + + /* check BUFIE */ + bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE; + + /* get the interrupt enable bit status */ + intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag))); + + if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){ + if(intenable && bufie){ + intenable = 1U; + }else{ + intenable = 0U; + } + } + if((0U != flagstatus) && (0U != intenable)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \arg I2C_INT_FLAG_TFF: txframe fall interrupt flag + \arg I2C_INT_FLAG_TFR: txframe rise interrupt flag + \arg I2C_INT_FLAG_RFF: rxframe fall interrupt flag + \arg I2C_INT_FLAG_RFR: rxframe rise interrupt flag + \param[out] none + \retval none +*/ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + if(I2C_INT_FLAG_ADDSEND == int_flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); + } +} diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c index d50b473ab9..5afcc48e0d 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c @@ -1,30 +1,57 @@ /*! - \file gd32f4xx_ipa.c - \brief IPA driver + \file gd32f4xx_ipa.c + \brief IPA driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_ipa.h" +#define IPA_DEFAULT_VALUE 0x00000000U + /*! - \brief deinitialize IPA registers + \brief deinitialize IPA registers \param[in] none \param[out] none \retval none */ void ipa_deinit(void) { - rcu_periph_reset_enable(RCU_IPAENRST); - rcu_periph_reset_disable(RCU_IPAENRST); + rcu_periph_reset_enable(RCU_IPARST); + rcu_periph_reset_disable(RCU_IPARST); } /*! - \brief IPA transfer enable + \brief enable IPA transfer \param[in] none \param[out] none \retval none @@ -35,8 +62,8 @@ void ipa_transfer_enable(void) } /*! - \brief IPA transfer hang up enable - \param[in] none. + \brief enable IPA transfer hang up + \param[in] none \param[out] none \retval none */ @@ -46,8 +73,8 @@ void ipa_transfer_hangup_enable(void) } /*! - \brief IPA transfer hang up disable - \param[in] none. + \brief disable IPA transfer hang up + \param[in] none \param[out] none \retval none */ @@ -57,8 +84,8 @@ void ipa_transfer_hangup_disable(void) } /*! - \brief IPA transfer stop enable - \param[in] none. + \brief enable IPA transfer stop + \param[in] none \param[out] none \retval none */ @@ -68,8 +95,8 @@ void ipa_transfer_stop_enable(void) } /*! - \brief IPA transfer stop disable - \param[in] none. + \brief disable IPA transfer stop + \param[in] none \param[out] none \retval none */ @@ -78,8 +105,8 @@ void ipa_transfer_stop_disable(void) IPA_CTL &= ~(IPA_CTL_TST); } /*! - \brief IPA foreground LUT loading enable - \param[in] none. + \brief enable IPA foreground LUT loading + \param[in] none \param[out] none \retval none */ @@ -89,8 +116,8 @@ void ipa_foreground_lut_loading_enable(void) } /*! - \brief IPA background LUT loading enable - \param[in] none. + \brief enable IPA background LUT loading + \param[in] none \param[out] none \retval none */ @@ -100,94 +127,217 @@ void ipa_background_lut_loading_enable(void) } /*! - \brief Pixel format convert mode - \param[in] pfcm: - \arg IPA_FGTODE: foreground memory to destination memory without pixel format convert - \arg IPA_FGTODE_PF_CONVERT: foreground memory to destination memory with pixel format convert - \arg IPA_FGBGTODE: blending foreground and background memory to destination memory - \arg IPA_FILL_UP_DE: fill up destination memory with specific color + \brief set pixel format convert mode, the function is invalid when the IPA transfer is enabled + \param[in] pfcm: pixel format convert mode + only one parameter can be selected which is shown as below: + \arg IPA_FGTODE: foreground memory to destination memory without pixel format convert + \arg IPA_FGTODE_PF_CONVERT: foreground memory to destination memory with pixel format convert + \arg IPA_FGBGTODE: blending foreground and background memory to destination memory + \arg IPA_FILL_UP_DE: fill up destination memory with specific color \param[out] none \retval none */ -void ipa_pixel_format_convert_mod(uint32_t pfcm) +void ipa_pixel_format_convert_mode_set(uint32_t pfcm) { IPA_CTL |= pfcm; } /*! - \brief initialize foreground parameters - \param[in] foreground_struct: the data needed to initialize fore. + \brief initialize the structure of IPA foreground parameter struct with the default values, it is + suggested that call this function after an ipa_foreground_parameter_struct structure is defined + \param[in] none + \param[out] foreground_struct: the data needed to initialize foreground foreground_memaddr: foreground memory base address foreground_lineoff: foreground line offset - foreground_prealpha: foreground pre-defined alpha value + foreground_prealpha: foreground pre-defined alpha value foreground_alpha_algorithm: IPA_FG_ALPHA_MODE_0,IPA_FG_ALPHA_MODE_1,IPA_FG_ALPHA_MODE_2 - foreground_pf: foreground pixel format + foreground_pf: foreground pixel format(FOREGROUND_PPF_ARGB8888,FOREGROUND_PPF_RGB888,FOREGROUND_PPF_RGB565, + FOREGROUND_PPF_ARG1555,FOREGROUND_PPF_ARGB4444,FOREGROUND_PPF_L8,FOREGROUND_PPF_AL44, + FOREGROUND_PPF_AL88,FOREGROUND_PPF_L4,FOREGROUND_PPF_A8,FOREGROUND_PPF_A4) foreground_prered: foreground pre-defined red value - foreground_pregreen: foreground pre-defined green value + foreground_pregreen: foreground pre-defined green value + foreground_preblue: foreground pre-defined blue value + \retval none +*/ +void ipa_foreground_struct_para_init(ipa_foreground_parameter_struct* foreground_struct) +{ + /* initialize the struct parameters with default values */ + foreground_struct->foreground_memaddr = IPA_DEFAULT_VALUE; + foreground_struct->foreground_lineoff = IPA_DEFAULT_VALUE; + foreground_struct->foreground_prealpha = IPA_DEFAULT_VALUE; + foreground_struct->foreground_alpha_algorithm = IPA_FG_ALPHA_MODE_0; + foreground_struct->foreground_pf = FOREGROUND_PPF_ARGB8888; + foreground_struct->foreground_prered = IPA_DEFAULT_VALUE; + foreground_struct->foreground_pregreen = IPA_DEFAULT_VALUE; + foreground_struct->foreground_preblue = IPA_DEFAULT_VALUE; +} + +/*! + \brief initialize foreground parameters + \param[in] foreground_struct: the data needed to initialize foreground + foreground_memaddr: foreground memory base address + foreground_lineoff: foreground line offset + foreground_prealpha: foreground pre-defined alpha value + foreground_alpha_algorithm: IPA_FG_ALPHA_MODE_0,IPA_FG_ALPHA_MODE_1,IPA_FG_ALPHA_MODE_2 + foreground_pf: foreground pixel format(FOREGROUND_PPF_ARGB8888,FOREGROUND_PPF_RGB888,FOREGROUND_PPF_RGB565, + FOREGROUND_PPF_ARG1555,FOREGROUND_PPF_ARGB4444,FOREGROUND_PPF_L8,FOREGROUND_PPF_AL44, + FOREGROUND_PPF_AL88,FOREGROUND_PPF_L4,FOREGROUND_PPF_A8,FOREGROUND_PPF_A4) + foreground_prered: foreground pre-defined red value + foreground_pregreen: foreground pre-defined green value foreground_preblue: foreground pre-defined blue value \param[out] none \retval none */ void ipa_foreground_init(ipa_foreground_parameter_struct* foreground_struct) { + FlagStatus tempflag = RESET; + if(RESET != (IPA_CTL & IPA_CTL_TEN)){ + tempflag = SET; + /* reset the TEN in order to configure the following bits */ + IPA_CTL &= ~IPA_CTL_TEN; + } + /* foreground memory base address configuration */ IPA_FMADDR &= ~(IPA_FMADDR_FMADDR); IPA_FMADDR = foreground_struct->foreground_memaddr; /* foreground line offset configuration */ IPA_FLOFF &= ~(IPA_FLOFF_FLOFF); IPA_FLOFF = foreground_struct->foreground_lineoff; - /* foreground pixel format pre-defined alpha, alpha calculation algorithm configuration */ - IPA_FPCTL &= ~(IPA_FPCTL_FAVCA|IPA_FPCTL_FAVCA|IPA_FPCTL_FPF); + /* foreground pixel format pre-defined alpha, alpha calculation algorithm configuration */ + IPA_FPCTL &= ~(IPA_FPCTL_FPDAV|IPA_FPCTL_FAVCA|IPA_FPCTL_FPF); IPA_FPCTL |= (foreground_struct->foreground_prealpha<<24U); IPA_FPCTL |= foreground_struct->foreground_alpha_algorithm; IPA_FPCTL |= foreground_struct->foreground_pf; - /* foreground pre-defined red green blue configuration */ + /* foreground pre-defined red green blue configuration */ IPA_FPV &= ~(IPA_FPV_FPDRV|IPA_FPV_FPDGV|IPA_FPV_FPDBV); - IPA_FPV |= ((foreground_struct->foreground_prered<<16U)|(foreground_struct->foreground_pregreen<<8U)|(foreground_struct->foreground_preblue)); + IPA_FPV |= ((foreground_struct->foreground_prered<<16U)|(foreground_struct->foreground_pregreen<<8U) + |(foreground_struct->foreground_preblue)); + + if(SET == tempflag){ + /* restore the state of TEN */ + IPA_CTL |= IPA_CTL_TEN; + } } /*! - \brief initialize background parameters - \param[in] background_struct: the data needed to initialize fore. + \brief initialize the structure of IPA background parameter struct with the default values, it is + suggested that call this function after an ipa_background_parameter_struct structure is defined + \param[in] none + \param[out] background_struct: the data needed to initialize background background_memaddr: background memory base address background_lineoff: background line offset - background_prealpha: background pre-defined alpha value - background_alpha_algorithm: IPA_BG_ALPHA_MODE_0,IPA_FG_ALPHA_MODE_1,IPA_FG_ALPHA_MODE_2 - background_pf: background pixel format + background_prealpha: background pre-defined alpha value + background_alpha_algorithm: IPA_BG_ALPHA_MODE_0,IPA_BG_ALPHA_MODE_1,IPA_BG_ALPHA_MODE_2 + background_pf: background pixel format(BACKGROUND_PPF_ARGB8888,BACKGROUND_PPF_RGB888,BACKGROUND_PPF_RGB565, + BACKGROUND_PPF_ARG1555,BACKGROUND_PPF_ARGB4444,BACKGROUND_PPF_L8,BACKGROUND_PPF_AL44, + BACKGROUND_PPF_AL88,BACKGROUND_PPF_L4,BACKGROUND_PPF_A8,BACKGROUND_PPF_A4) background_prered: background pre-defined red value - background_pregreen: background pre-defined green value + background_pregreen: background pre-defined green value + background_preblue: background pre-defined blue value + \retval none +*/ +void ipa_background_struct_para_init(ipa_background_parameter_struct* background_struct) +{ + /* initialize the struct parameters with default values */ + background_struct->background_memaddr = IPA_DEFAULT_VALUE; + background_struct->background_lineoff = IPA_DEFAULT_VALUE; + background_struct->background_prealpha = IPA_DEFAULT_VALUE; + background_struct->background_alpha_algorithm = IPA_BG_ALPHA_MODE_0; + background_struct->background_pf = BACKGROUND_PPF_ARGB8888; + background_struct->background_prered = IPA_DEFAULT_VALUE; + background_struct->background_pregreen = IPA_DEFAULT_VALUE; + background_struct->background_preblue = IPA_DEFAULT_VALUE; +} + +/*! + \brief initialize background parameters + \param[in] background_struct: the data needed to initialize background + background_memaddr: background memory base address + background_lineoff: background line offset + background_prealpha: background pre-defined alpha value + background_alpha_algorithm: IPA_BG_ALPHA_MODE_0,IPA_FG_ALPHA_MODE_1,IPA_FG_ALPHA_MODE_2 + background_pf: background pixel format(BACKGROUND_PPF_ARGB8888,BACKGROUND_PPF_RGB888,BACKGROUND_PPF_RGB565, + BACKGROUND_PPF_ARG1555,BACKGROUND_PPF_ARGB4444,BACKGROUND_PPF_L8,BACKGROUND_PPF_AL44, + BACKGROUND_PPF_AL88,BACKGROUND_PPF_L4,BACKGROUND_PPF_A8,BACKGROUND_PPF_A4) + background_prered: background pre-defined red value + background_pregreen: background pre-defined green value background_preblue: background pre-defined blue value \param[out] none \retval none */ void ipa_background_init(ipa_background_parameter_struct* background_struct) { + FlagStatus tempflag = RESET; + if(RESET != (IPA_CTL & IPA_CTL_TEN)){ + tempflag = SET; + /* reset the TEN in order to configure the following bits */ + IPA_CTL &= ~IPA_CTL_TEN; + } + /* background memory base address configuration */ IPA_BMADDR &= ~(IPA_BMADDR_BMADDR); IPA_BMADDR = background_struct->background_memaddr; /* background line offset configuration */ IPA_BLOFF &= ~(IPA_BLOFF_BLOFF); - IPA_BLOFF =background_struct->background_lineoff; - /* background pixel format pre-defined alpha, alpha calculation algorithm configuration */ - IPA_BPCTL &= ~(IPA_BPCTL_BAVCA|IPA_BPCTL_BAVCA|IPA_BPCTL_BPF); + IPA_BLOFF = background_struct->background_lineoff; + /* background pixel format pre-defined alpha, alpha calculation algorithm configuration */ + IPA_BPCTL &= ~(IPA_BPCTL_BPDAV|IPA_BPCTL_BAVCA|IPA_BPCTL_BPF); IPA_BPCTL |= (background_struct->background_prealpha<<24U); IPA_BPCTL |= background_struct->background_alpha_algorithm; - IPA_BPCTL |= background_struct->background_pf; - /* background pre-defined red green blue configuration */ + IPA_BPCTL |= background_struct->background_pf; + /* background pre-defined red green blue configuration */ IPA_BPV &= ~(IPA_BPV_BPDRV|IPA_BPV_BPDGV|IPA_BPV_BPDBV); - IPA_BPV |= ((background_struct->background_prered<<16U)|(background_struct->background_pregreen<<8U)|(background_struct->background_preblue)); + IPA_BPV |= ((background_struct->background_prered<<16U)|(background_struct->background_pregreen<<8U) + |(background_struct->background_preblue)); + + if(SET == tempflag){ + /* restore the state of TEN */ + IPA_CTL |= IPA_CTL_TEN; + } } /*! - \brief initialize destination parameters - \param[in] destination_struct: the data needed to initialize tli. - destination_pf: refer to ipa_dpf_enum + \brief initialize the structure of IPA destination parameter struct with the default values, it is + suggested that call this function after an ipa_destination_parameter_struct structure is defined + \param[in] none + \param[out] destination_struct: the data needed to initialize destination parameter + destination_pf: IPA_DPF_ARGB8888,IPA_DPF_RGB888,IPA_DPF_RGB565,IPA_DPF_ARGB1555, + IPA_DPF_ARGB4444,refer to ipa_dpf_enum destination_lineoff: destination line offset - destination_prealpha: destination pre-defined alpha value + destination_prealpha: destination pre-defined alpha value destination_prered: destination pre-defined red value destination_pregreen: destination pre-defined green value destination_preblue: destination pre-defined blue value - destination_memaddr: destination memory base address + destination_memaddr: destination memory base address + image_width: width of the image to be processed + image_height: height of the image to be processed + \retval none +*/ +void ipa_destination_struct_para_init(ipa_destination_parameter_struct* destination_struct) +{ + /* initialize the struct parameters with default values */ + destination_struct->destination_pf = IPA_DPF_ARGB8888; + destination_struct->destination_lineoff = IPA_DEFAULT_VALUE; + destination_struct->destination_prealpha = IPA_DEFAULT_VALUE; + destination_struct->destination_prered = IPA_DEFAULT_VALUE; + destination_struct->destination_pregreen = IPA_DEFAULT_VALUE; + destination_struct->destination_preblue = IPA_DEFAULT_VALUE; + destination_struct->destination_memaddr = IPA_DEFAULT_VALUE; + destination_struct->image_width = IPA_DEFAULT_VALUE; + destination_struct->image_height = IPA_DEFAULT_VALUE; +} + +/*! + \brief initialize destination parameters + \param[in] destination_struct: the data needed to initialize destination parameters + destination_pf: IPA_DPF_ARGB8888,IPA_DPF_RGB888,IPA_DPF_RGB565,IPA_DPF_ARGB1555, + IPA_DPF_ARGB4444,refer to ipa_dpf_enum + destination_lineoff: destination line offset + destination_prealpha: destination pre-defined alpha value + destination_prered: destination pre-defined red value + destination_pregreen: destination pre-defined green value + destination_preblue: destination pre-defined blue value + destination_memaddr: destination memory base address image_width: width of the image to be processed image_height: height of the image to be processed \param[out] none @@ -196,6 +346,13 @@ void ipa_background_init(ipa_background_parameter_struct* background_struct) void ipa_destination_init(ipa_destination_parameter_struct* destination_struct) { uint32_t destination_pixelformat; + FlagStatus tempflag = RESET; + if(RESET != (IPA_CTL & IPA_CTL_TEN)){ + tempflag = SET; + /* reset the TEN in order to configure the following bits */ + IPA_CTL &= ~IPA_CTL_TEN; + } + /* destination pixel format configuration */ IPA_DPCTL &= ~(IPA_DPCTL_DPF); IPA_DPCTL = destination_struct->destination_pf; @@ -230,36 +387,48 @@ void ipa_destination_init(ipa_destination_parameter_struct* destination_struct) /* destination pixel format ARGB4444 */ case IPA_DPF_ARGB4444: IPA_DPV &= ~(IPA_DPV_DPDBV_4|(IPA_DPV_DPDGV_4)|(IPA_DPV_DPDRV_4)|(IPA_DPV_DPDAV_4)); - IPA_DPV = (destination_struct->destination_preblue|(destination_struct->destination_pregreen<<5U) - |(destination_struct->destination_prered<<10U) - |(destination_struct->destination_prealpha<<15U)); + IPA_DPV = (destination_struct->destination_preblue|(destination_struct->destination_pregreen<<4U) + |(destination_struct->destination_prered<<8U) + |(destination_struct->destination_prealpha<<12U)); break; default: break; } /* destination memory base address configuration */ IPA_DMADDR &= ~(IPA_DMADDR_DMADDR); - IPA_DMADDR =destination_struct->destination_memaddr; - /* destination line offset configuration */ + IPA_DMADDR = destination_struct->destination_memaddr; + /* destination line offset configuration */ IPA_DLOFF &= ~(IPA_DLOFF_DLOFF); IPA_DLOFF =destination_struct->destination_lineoff; - /* image size configuration */ + /* image size configuration */ IPA_IMS &= ~(IPA_IMS_HEIGHT|IPA_IMS_WIDTH); - IPA_IMS |= ((destination_struct->image_width<<16)|(destination_struct->image_height)); + IPA_IMS |= ((destination_struct->image_width<<16U)|(destination_struct->image_height)); + + if(SET == tempflag){ + /* restore the state of TEN */ + IPA_CTL |= IPA_CTL_TEN; + } } /*! - \brief initialize IPA foreground LUT parameters - \param[in] fg_lut_num: foreground LUT number of pixel. - \param[in] fg_lut_pf: foreground LUT pixel format,IPA_LUT_PF_ARGB8888,IPA_LUT_PF_RGB888. - \param[in] fg_lut_addr: foreground LUT memory base address. + \brief initialize IPA foreground LUT parameters + \param[in] fg_lut_num: foreground LUT number of pixel + \param[in] fg_lut_pf: foreground LUT pixel format(IPA_LUT_PF_ARGB8888, IPA_LUT_PF_RGB888) + \param[in] fg_lut_addr: foreground LUT memory base address \param[out] none \retval none */ -void ipa_foreground_lut_init(uint32_t fg_lut_num,uint8_t fg_lut_pf, uint32_t fg_lut_addr) +void ipa_foreground_lut_init(uint8_t fg_lut_num, uint8_t fg_lut_pf, uint32_t fg_lut_addr) { + FlagStatus tempflag = RESET; + if(RESET != (IPA_FPCTL & IPA_FPCTL_FLLEN)){ + tempflag = SET; + /* reset the FLLEN in order to configure the following bits */ + IPA_FPCTL &= ~IPA_FPCTL_FLLEN; + } + /* foreground LUT number of pixel configuration */ - IPA_FPCTL |= (fg_lut_num<<8U); + IPA_FPCTL |= ((uint32_t)fg_lut_num<<8U); /* foreground LUT pixel format configuration */ if(IPA_LUT_PF_RGB888 == fg_lut_pf){ IPA_FPCTL |= IPA_FPCTL_FLPF; @@ -269,20 +438,32 @@ void ipa_foreground_lut_init(uint32_t fg_lut_num,uint8_t fg_lut_pf, uint32_t fg_ /* foreground LUT memory base address configuration */ IPA_FLMADDR &= ~(IPA_FLMADDR_FLMADDR); IPA_FLMADDR = fg_lut_addr; + + if(SET == tempflag){ + /* restore the state of FLLEN */ + IPA_FPCTL |= IPA_FPCTL_FLLEN; + } } /*! - \brief initialize IPA background LUT parameters - \param[in] bg_lut_num: background LUT number of pixel. - \param[in] bg_lut_pf: background LUT pixel format, IPA_LUT_PF_ARGB8888,IPA_LUT_PF_RGB888. - \param[in] bg_lut_addr: background LUT memory base address. + \brief initialize IPA background LUT parameters + \param[in] bg_lut_num: background LUT number of pixel + \param[in] bg_lut_pf: background LUT pixel format(IPA_LUT_PF_ARGB8888, IPA_LUT_PF_RGB888) + \param[in] bg_lut_addr: background LUT memory base address \param[out] none \retval none */ -void ipa_background_lut_init(uint32_t bg_lut_num,uint8_t bg_lut_pf, uint32_t bg_lut_addr) +void ipa_background_lut_init(uint8_t bg_lut_num, uint8_t bg_lut_pf, uint32_t bg_lut_addr) { + FlagStatus tempflag = RESET; + if(RESET != (IPA_BPCTL & IPA_BPCTL_BLLEN)){ + tempflag = SET; + /* reset the BLLEN in order to configure the following bits */ + IPA_BPCTL &= ~IPA_BPCTL_BLLEN; + } + /* background LUT number of pixel configuration */ - IPA_BPCTL|=(bg_lut_num<<8U); + IPA_BPCTL |= ((uint32_t)bg_lut_num<<8U); /* background LUT pixel format configuration */ if(IPA_LUT_PF_RGB888 == bg_lut_pf){ IPA_BPCTL |= IPA_BPCTL_BLPF; @@ -292,29 +473,34 @@ void ipa_background_lut_init(uint32_t bg_lut_num,uint8_t bg_lut_pf, uint32_t bg_ /* background LUT memory base address configuration */ IPA_BLMADDR &= ~(IPA_BLMADDR_BLMADDR); IPA_BLMADDR = bg_lut_addr; + + if(SET == tempflag){ + /* restore the state of BLLEN */ + IPA_BPCTL |= IPA_BPCTL_BLLEN; + } } /*! - \brief configure line mark - \param[in] linenum: line number. + \brief configure IPA line mark + \param[in] line_num: line number \param[out] none \retval none */ -void ipa_line_mark_config(uint32_t linenum) +void ipa_line_mark_config(uint16_t line_num) { IPA_LM &= ~(IPA_LM_LM); - IPA_LM = linenum; + IPA_LM = line_num; } /*! - \brief Inter-timer enable or disable - \param[in] timercfg: IPA_INTER_TIMER_ENABLE,IPA_INTER_TIMER_DISABLE + \brief inter-timer enable or disable + \param[in] timer_cfg: IPA_INTER_TIMER_ENABLE,IPA_INTER_TIMER_DISABLE \param[out] none \retval none */ -void ipa_inter_timer_config(uint8_t timercfg) +void ipa_inter_timer_config(uint8_t timer_cfg) { - if(IPA_INTER_TIMER_ENABLE == timercfg){ + if(IPA_INTER_TIMER_ENABLE == timer_cfg){ IPA_ITCTL |= IPA_ITCTL_ITEN; }else{ IPA_ITCTL &= ~(IPA_ITCTL_ITEN); @@ -322,68 +508,34 @@ void ipa_inter_timer_config(uint8_t timercfg) } /*! - \brief number of clock cycles interval set - \param[in] clk_num: the number of clock cycles. + \brief configure the number of clock cycles interval + \param[in] clk_num: the number of clock cycles \param[out] none \retval none */ -void ipa_interval_clock_num_config(uint32_t clk_num ) +void ipa_interval_clock_num_config(uint8_t clk_num) { + /* NCCI[7:0] bits have no meaning if ITEN is '0' */ IPA_ITCTL &= ~(IPA_ITCTL_NCCI); - IPA_ITCTL |= (clk_num<<8U); + IPA_ITCTL |= ((uint32_t)clk_num<<8U); } /*! - \brief IPA interrupt enable - \param[in] inttype: IPA interrupt bits. - \arg IPA_CTL_TAEIE: transfer access error interrupt - \arg IPA_CTL_FTFIE: full transfer finish interrupt - \arg IPA_CTL_TLMIE: transfer line mark interrupt - \arg IPA_CTL_LACIE: LUT access conflict interrupt - \arg IPA_CTL_LLFIE: LUT loading finish interrupt - \arg IPA_CTL_WCFIE: wrong configuration interrupt + \brief get IPA flag status in IPA_INTF register + \param[in] flag: IPA flags + one or more parameters can be selected which are shown as below: + \arg IPA_FLAG_TAE: transfer access error interrupt flag + \arg IPA_FLAG_FTF: full transfer finish interrupt flag + \arg IPA_FLAG_TLM: transfer line mark interrupt flag + \arg IPA_FLAG_LAC: LUT access conflict interrupt flag + \arg IPA_FLAG_LLF: LUT loading finish interrupt flag + \arg IPA_FLAG_WCF: wrong configuration interrupt flag \param[out] none \retval none */ -void ipa_interrupt_enable(uint32_t inttype) +FlagStatus ipa_flag_get(uint32_t flag) { - IPA_CTL |= (inttype); -} - -/*! - \brief IPA interrupt disable - \param[in] inttype: IPA interrupt bits. - \arg IPA_CTL_TAEIE: transfer access error interrupt - \arg IPA_CTL_FTFIE: full transfer finish interrupt - \arg IPA_CTL_TLMIE: transfer line mark interrupt - \arg IPA_CTL_LACIE: LUT access conflict interrupt - \arg IPA_CTL_LLFIE: LUT loading finish interrupt - \arg IPA_CTL_WCFIE: wrong configuration interrupt - \param[out] none - \retval none -*/ -void ipa_interrupt_disable(uint32_t inttype) -{ - IPA_CTL &= ~(inttype); -} - -/*! - \brief get IPA interrupt flag - \param[in] intflag: tli interrupt flag bits. - \arg IPA_INTF_TAEIF: transfer access error interrupt flag - \arg IPA_INTF_FTFIF: full transfer finish interrupt flag - \arg IPA_INTF_TLMIF: transfer line mark interrupt flag - \arg IPA_INTF_LACIF: LUT access conflict interrupt flag - \arg IPA_INTF_LLFIF: LUT loading finish interrupt flag - \arg IPA_INTF_WCFIF: wrong configuration interrupt flag - \param[out] none - \retval none -*/ -FlagStatus ipa_interrupt_flag_get(uint32_t intflag) -{ - uint32_t state; - state = IPA_INTF; - if(state & intflag){ + if(RESET != (IPA_INTF & flag)){ return SET; }else{ return RESET; @@ -391,19 +543,95 @@ FlagStatus ipa_interrupt_flag_get(uint32_t intflag) } /*! - \brief clear IPA interrupt flag - \param[in] intflag: tli interrupt flag bits. - \arg IPA_INTC_TAEIFC: transfer access error interrupt flag - \arg IPA_INTC_FTFIFC: full transfer finish interrupt flag - \arg IPA_INTC_TLMIFC: transfer line mark interrupt flag - \arg IPA_INTC_LACIFC: LUT access conflict interrupt flag - \arg IPA_INTC_LLFIFC: LUT loading finish interrupt flag - \arg IPA_INTC_WCFIFC: wrong configuration interrupt flag + \brief clear IPA flag in IPA_INTF register + \param[in] flag: IPA flags + one or more parameters can be selected which are shown as below: + \arg IPA_FLAG_TAE: transfer access error interrupt flag + \arg IPA_FLAG_FTF: full transfer finish interrupt flag + \arg IPA_FLAG_TLM: transfer line mark interrupt flag + \arg IPA_FLAG_LAC: LUT access conflict interrupt flag + \arg IPA_FLAG_LLF: LUT loading finish interrupt flag + \arg IPA_FLAG_WCF: wrong configuration interrupt flag \param[out] none \retval none */ -void ipa_interrupt_flag_clear(uint32_t intflag) +void ipa_flag_clear(uint32_t flag) { - IPA_INTC |= (intflag); + IPA_INTC |= (flag); } +/*! + \brief enable IPA interrupt + \param[in] int_flag: IPA interrupt flags + one or more parameters can be selected which are shown as below: + \arg IPA_INT_TAE: transfer access error interrupt + \arg IPA_INT_FTF: full transfer finish interrupt + \arg IPA_INT_TLM: transfer line mark interrupt + \arg IPA_INT_LAC: LUT access conflict interrupt + \arg IPA_INT_LLF: LUT loading finish interrupt + \arg IPA_INT_WCF: wrong configuration interrupt + \param[out] none + \retval none +*/ +void ipa_interrupt_enable(uint32_t int_flag) +{ + IPA_CTL |= (int_flag); +} + +/*! + \brief disable IPA interrupt + \param[in] int_flag: IPA interrupt flags + one or more parameters can be selected which are shown as below: + \arg IPA_INT_TAE: transfer access error interrupt + \arg IPA_INT_FTF: full transfer finish interrupt + \arg IPA_INT_TLM: transfer line mark interrupt + \arg IPA_INT_LAC: LUT access conflict interrupt + \arg IPA_INT_LLF: LUT loading finish interrupt + \arg IPA_INT_WCF: wrong configuration interrupt + \param[out] none + \retval none +*/ +void ipa_interrupt_disable(uint32_t int_flag) +{ + IPA_CTL &= ~(int_flag); +} + +/*! + \brief get IPA interrupt flag + \param[in] int_flag: IPA interrupt flag flags + one or more parameters can be selected which are shown as below: + \arg IPA_INT_FLAG_TAE: transfer access error interrupt flag + \arg IPA_INT_FLAG_FTF: full transfer finish interrupt flag + \arg IPA_INT_FLAG_TLM: transfer line mark interrupt flag + \arg IPA_INT_FLAG_LAC: LUT access conflict interrupt flag + \arg IPA_INT_FLAG_LLF: LUT loading finish interrupt flag + \arg IPA_INT_FLAG_WCF: wrong configuration interrupt flag + \param[out] none + \retval none +*/ +FlagStatus ipa_interrupt_flag_get(uint32_t int_flag) +{ + if(0U != (IPA_INTF & int_flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear IPA interrupt flag + \param[in] int_flag: IPA interrupt flag flags + one or more parameters can be selected which are shown as below: + \arg IPA_INT_FLAG_TAE: transfer access error interrupt flag + \arg IPA_INT_FLAG_FTF: full transfer finish interrupt flag + \arg IPA_INT_FLAG_TLM: transfer line mark interrupt flag + \arg IPA_INT_FLAG_LAC: LUT access conflict interrupt flag + \arg IPA_INT_FLAG_LLF: LUT loading finish interrupt flag + \arg IPA_INT_FLAG_WCF: wrong configuration interrupt flag + \param[out] none + \retval none +*/ +void ipa_interrupt_flag_clear(uint32_t int_flag) +{ + IPA_INTC |= (int_flag); +} diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c index 237fc2ee75..218a070ef4 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_iref.c - \brief IREF driver + \file gd32f4xx_iref.c + \brief IREF driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_iref.h" @@ -87,7 +112,7 @@ void iref_sink_set(uint32_t sinkmode) } /*! - \brief set IREF step data + \brief set IREF step data \param[in] stepdata \arg IREF_CUR_STEP_DATA_X:(x=0..63): step*x \param[out] none diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c index 1649929a4b..c826722f13 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_misc.c - \brief MISC driver + \file gd32f4xx_misc.c + \brief MISC driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_misc.h" @@ -36,7 +61,7 @@ void nvic_priority_group_set(uint32_t nvic_prigroup) \param[out] none \retval none */ -void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, +void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority) { uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U; @@ -57,6 +82,9 @@ void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, temp_pre=4U; temp_sub=0x0U; }else{ + nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); + temp_pre=2U; + temp_sub=0x2U; } /* get the temp_priority to fill the NVIC->IP register */ temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre); @@ -96,10 +124,10 @@ void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset) /*! \brief set the state of the low power mode \param[in] lowpower_mode: the low power mode state - \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power mode by exiting from ISR \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode - \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode can be woke up + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode can be woke up by all the enable and disable interrupts \param[out] none \retval none @@ -112,10 +140,10 @@ void system_lowpower_set(uint8_t lowpower_mode) /*! \brief reset the state of the low power mode \param[in] lowpower_mode: the low power mode state - \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power mode by exiting from ISR \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode - \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode only can be + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode only can be woke up by the enable interrupts \param[out] none \retval none diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c index 267e4c32fd..05f4cd7c3a 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_pmu.c - \brief PMU driver + \file gd32f4xx_pmu.c + \brief PMU driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_pmu.h" @@ -26,37 +51,37 @@ void pmu_deinit(void) /*! \brief select low voltage detector threshold - \param[in] pmu_lvdt_n: - \arg PMU_LVDT_0: voltage threshold is 2.2V + \param[in] lvdt_n: + \arg PMU_LVDT_0: voltage threshold is 2.1V \arg PMU_LVDT_1: voltage threshold is 2.3V \arg PMU_LVDT_2: voltage threshold is 2.4V - \arg PMU_LVDT_3: voltage threshold is 2.5V - \arg PMU_LVDT_4: voltage threshold is 2.6V - \arg PMU_LVDT_5: voltage threshold is 2.7V - \arg PMU_LVDT_6: voltage threshold is 2.8V - \arg PMU_LVDT_7: voltage threshold is 2.9V + \arg PMU_LVDT_3: voltage threshold is 2.6V + \arg PMU_LVDT_4: voltage threshold is 2.7V + \arg PMU_LVDT_5: voltage threshold is 2.9V + \arg PMU_LVDT_6: voltage threshold is 3.0V + \arg PMU_LVDT_7: voltage threshold is 3.1V \param[out] none \retval none */ -void pmu_lvd_select(uint32_t pmu_lvdt_n) +void pmu_lvd_select(uint32_t lvdt_n) { /* disable LVD */ PMU_CTL &= ~PMU_CTL_LVDEN; /* clear LVDT bits */ PMU_CTL &= ~PMU_CTL_LVDT; /* set LVDT bits according to pmu_lvdt_n */ - PMU_CTL |= pmu_lvdt_n; + PMU_CTL |= lvdt_n; /* enable LVD */ PMU_CTL |= PMU_CTL_LVDEN; } /*! - \brief LDO output voltage select + \brief select LDO output voltage this bit set by software when the main PLL closed, before closing PLL, change the system clock to IRC16M or HXTAL \param[in] ldo_output: \arg PMU_LDOVS_LOW: low-driver mode enable in deep-sleep mode - \arg PMU_LDOVS_MID: low-driver mode disable in deep-sleep mode - \arg PMU_LDOVS_HIGH: low-driver mode disable in deep-sleep mode + \arg PMU_LDOVS_MID: mid-driver mode disable in deep-sleep mode + \arg PMU_LDOVS_HIGH: high-driver mode disable in deep-sleep mode \param[out] none \retval none */ @@ -67,10 +92,10 @@ void pmu_ldo_output_select(uint32_t ldo_output) } /*! - \brief low-driver mode enable in deep-sleep mode + \brief enable low-driver mode in deep-sleep mode \param[in] lowdr_mode: - \arg PMU_LOWDRIVER_ENABLE: low-driver mode enable in deep-sleep mode - \arg PMU_LOWDRIVER_DISABLE: low-driver mode disable in deep-sleep mode + \arg PMU_LOWDRIVER_ENABLE: enable low-driver mode in deep-sleep mode + \arg PMU_LOWDRIVER_DISABLE: disable low-driver mode in deep-sleep mode \param[out] none \retval none */ @@ -81,11 +106,11 @@ void pmu_low_driver_mode_enable(uint32_t lowdr_mode) } /*! - \brief high-driver mode switch + \brief switch high-driver mode this bit set by software only when IRC16M or HXTAL used as system clock \param[in] highdr_switch: - \arg PMU_HIGHDR_SWITCH_NONE: no high-driver mode switch - \arg PMU_HIGHDR_SWITCH_EN: high-driver mode switch + \arg PMU_HIGHDR_SWITCH_NONE: disable high-driver mode switch + \arg PMU_HIGHDR_SWITCH_EN: enable high-driver mode switch \param[out] none \retval none */ @@ -150,8 +175,8 @@ void pmu_lowdriver_lowpower_config(uint32_t mode) /*! \brief low-driver mode when use normal power LDO \param[in] mode: - \arg PMU_NORMALDR_NORMALPWR: normal driver when use low power LDO - \arg PMU_LOWDR_NORMALPWR: low-driver mode enabled when LDEN is 11 and use low power LDO + \arg PMU_NORMALDR_NORMALPWR: normal driver when use normal power LDO + \arg PMU_LOWDR_NORMALPWR: low-driver mode enabled when LDEN is 11 and use normal power LDO \param[out] none \retval none */ @@ -173,7 +198,7 @@ void pmu_to_sleepmode(uint8_t sleepmodecmd) { /* clear sleepdeep bit of Cortex-M4 system control register */ SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); - + /* select WFI or WFE command to enter sleep mode */ if(WFI_CMD == sleepmodecmd){ __WFI(); @@ -184,26 +209,37 @@ void pmu_to_sleepmode(uint8_t sleepmodecmd) /*! \brief PMU work at deepsleep mode - \param[in] pmu_ldo + \param[in] ldo \arg PMU_LDO_NORMAL: LDO normal work when pmu enter deepsleep mode \arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode - \param[in] deepsleepmodecmd: + \param[in] deepsleepmodecmd: \arg WFI_CMD: use WFI command \arg WFE_CMD: use WFE command \param[out] none \retval none */ -void pmu_to_deepsleepmode(uint32_t pmu_ldo,uint8_t deepsleepmodecmd) +void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd) { + static uint32_t reg_snap[ 4 ]; /* clear stbmod and ldolp bits */ PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP)); - + /* set ldolp bit according to pmu_ldo */ - PMU_CTL |= pmu_ldo; - + PMU_CTL |= ldo; + /* set sleepdeep bit of Cortex-M4 system control register */ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; - + + reg_snap[ 0 ] = REG32( 0xE000E010U ); + reg_snap[ 1 ] = REG32( 0xE000E100U ); + reg_snap[ 2 ] = REG32( 0xE000E104U ); + reg_snap[ 3 ] = REG32( 0xE000E108U ); + + REG32( 0xE000E010U ) &= 0x00010004U; + REG32( 0xE000E180U ) = 0XFF7FF831U; + REG32( 0xE000E184U ) = 0XBFFFF8FFU; + REG32( 0xE000E188U ) = 0xFFFFEFFFU; + /* select WFI or WFE command to enter deepsleep mode */ if(WFI_CMD == deepsleepmodecmd){ __WFI(); @@ -212,6 +248,12 @@ void pmu_to_deepsleepmode(uint32_t pmu_ldo,uint8_t deepsleepmodecmd) __WFE(); __WFE(); } + + REG32( 0xE000E010U ) = reg_snap[ 0 ] ; + REG32( 0xE000E100U ) = reg_snap[ 1 ] ; + REG32( 0xE000E104U ) = reg_snap[ 2 ] ; + REG32( 0xE000E108U ) = reg_snap[ 3 ] ; + /* reset sleepdeep bit of Cortex-M4 system control register */ SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); } @@ -231,10 +273,10 @@ void pmu_to_standbymode(uint8_t standbymodecmd) /* set stbmod bit */ PMU_CTL |= PMU_CTL_STBMOD; - + /* reset wakeup flag */ PMU_CTL |= PMU_CTL_WURST; - + /* select WFI or WFE command to enter standby mode */ if(WFI_CMD == standbymodecmd){ __WFI(); @@ -282,25 +324,26 @@ void pmu_flag_reset(uint32_t flag_reset) } /*! - \brief get flag status + \brief get flag state \param[in] pmu_flag: - \arg PMU_FLAG_WAKEUP: wakeup flag status - \arg PMU_FLAG_STANDBY: standby flag status - \arg PMU_FLAG_LVD: lvd flag status + \arg PMU_FLAG_WAKEUP: wakeup flag + \arg PMU_FLAG_STANDBY: standby flag + \arg PMU_FLAG_LVD: lvd flag \arg PMU_FLAG_BLDORF: backup SRAM LDO ready flag \arg PMU_FLAG_LDOVSRF: LDO voltage select ready flag \arg PMU_FLAG_HDRF: high-driver ready flag \arg PMU_FLAG_HDSRF: high-driver switch ready flag - \arg PMU_FLAG_LDRF: low-driver mode ready flag + \arg PMU_FLAG_LDRF: low-driver mode ready flag \param[out] none - \retval FlagStatus SET or RESET + \retval FlagStatus: SET or RESET */ -FlagStatus pmu_flag_get(uint32_t pmu_flag ) +FlagStatus pmu_flag_get(uint32_t pmu_flag) { if(PMU_CS & pmu_flag){ return SET; + }else{ + return RESET; } - return RESET; } /*! diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c index e37b9f9808..aecc895a09 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c @@ -1,21 +1,52 @@ /*! - \file gd32f4xx_rcu.c - \brief RCU driver + \file gd32f4xx_rcu.c + \brief RCU driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.1, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_rcu.h" -#define SEL_IRC16M 0U -#define SEL_HXTAL 1U -#define SEL_PLLP 2U -#define OSC_STARTUP_TIMEOUT ((uint16_t)0xfffffU) -#define LXTAL_STARTUP_TIMEOUT ((uint16_t)0x3ffffffU) +/* define clock source */ +#define SEL_IRC16M ((uint16_t)0U) /* IRC16M is selected as CK_SYS */ +#define SEL_HXTAL ((uint16_t)1U) /* HXTAL is selected as CK_SYS */ +#define SEL_PLLP ((uint16_t)2U) /* PLLP is selected as CK_SYS */ +/* define startup timeout count */ +#define OSC_STARTUP_TIMEOUT ((uint32_t)0x000fffffU) +#define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x0fffffffU) + +/* RCU IRC16M adjust value mask and offset*/ +#define RCU_IRC16M_ADJUST_MASK ((uint8_t)0x1FU) +#define RCU_IRC16M_ADJUST_OFFSET ((uint32_t)3U) /*! \brief deinitialize the RCU @@ -33,8 +64,9 @@ void rcu_deinit(void) RCU_CFG0_RTCDIV | RCU_CFG0_CKOUT0SEL | RCU_CFG0_I2SSEL | RCU_CFG0_CKOUT0DIV | RCU_CFG0_CKOUT1DIV | RCU_CFG0_CKOUT1SEL); /* reset CTL register */ - RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN | RCU_CTL_PLLI2SEN | - RCU_CTL_PLLSAIEN | RCU_CTL_HXTALBPS); + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN | RCU_CTL_PLLI2SEN + | RCU_CTL_PLLSAIEN); + RCU_CTL &= ~(RCU_CTL_HXTALBPS); /* reset PLL register */ RCU_PLL = 0x24003010U; /* reset PLLI2S register */ @@ -44,7 +76,7 @@ void rcu_deinit(void) /* reset INT register */ RCU_INT = 0x00000000U; /* reset CFG1 register */ - RCU_CFG1 &= ~(RCU_CFG1_PLLSAIRDIV | RCU_CFG1_TIMERSEL); + RCU_CFG1 &= ~(RCU_CFG1_PLLSAIRDIV | RCU_CFG1_TIMERSEL); } /*! @@ -236,7 +268,7 @@ void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G,H,I): reset GPIO ports \arg RCU_CRCRST: reset CRC \arg RCU_DMAxRST (x=0,1): reset DMA - \arg RCU_IPAENRST: reset IPA + \arg RCU_IPARST: reset IPA \arg RCU_ENETRST: reset ENET \arg RCU_USBHSRST: reset USBHS \arg RCU_DCIRST: reset DCI @@ -273,7 +305,7 @@ void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G,H,I): reset GPIO ports \arg RCU_CRCRST: reset CRC \arg RCU_DMAxRST (x=0,1): reset DMA - \arg RCU_IPAENRST: reset IPA + \arg RCU_IPARST: reset IPA \arg RCU_ENETRST: reset ENET \arg RCU_USBHSRST: reset USBHS \arg RCU_DCIRST: reset DCI @@ -338,7 +370,7 @@ void rcu_bkp_reset_disable(void) void rcu_system_clock_source_config(uint32_t ck_sys) { uint32_t reg; - + reg = RCU_CFG0; /* reset the SCS bits and set according to ck_sys */ reg &= ~RCU_CFG0_SCS; @@ -370,9 +402,9 @@ uint32_t rcu_system_clock_source_get(void) void rcu_ahb_clock_config(uint32_t ck_ahb) { uint32_t reg; - + reg = RCU_CFG0; - /* reset the AHBPS bits and set according to ck_ahb */ + /* reset the AHBPSC bits and set according to ck_ahb */ reg &= ~RCU_CFG0_AHBPSC; RCU_CFG0 = (reg | ck_ahb); } @@ -392,9 +424,9 @@ void rcu_ahb_clock_config(uint32_t ck_ahb) void rcu_apb1_clock_config(uint32_t ck_apb1) { uint32_t reg; - + reg = RCU_CFG0; - /* reset the APB1PS and set according to ck_apb1 */ + /* reset the APB1PSC and set according to ck_apb1 */ reg &= ~RCU_CFG0_APB1PSC; RCU_CFG0 = (reg | ck_apb1); } @@ -414,9 +446,9 @@ void rcu_apb1_clock_config(uint32_t ck_apb1) void rcu_apb2_clock_config(uint32_t ck_apb2) { uint32_t reg; - + reg = RCU_CFG0; - /* reset the APB2PS and set according to ck_apb2 */ + /* reset the APB2PSC and set according to ck_apb2 */ reg &= ~RCU_CFG0_APB2PSC; RCU_CFG0 = (reg | ck_apb2); } @@ -429,7 +461,7 @@ void rcu_apb2_clock_config(uint32_t ck_apb2) \arg RCU_CKOUT0SRC_LXTAL: LXTAL selected \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected \arg RCU_CKOUT0SRC_PLLP: PLLP selected - \param[in] ckout0_div: CK_OUT0 divider + \param[in] ckout0_div: CK_OUT0 divider \arg RCU_CKOUT0_DIVx(x=1,2,3,4,5): CK_OUT0 is divided by x \param[out] none \retval none @@ -437,7 +469,7 @@ void rcu_apb2_clock_config(uint32_t ck_apb2) void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div) { uint32_t reg; - + reg = RCU_CFG0; /* reset the CKOUT0SRC, CKOUT0DIV and set according to ckout0_src and ckout0_div */ reg &= ~(RCU_CFG0_CKOUT0SEL | RCU_CFG0_CKOUT0DIV ); @@ -451,8 +483,8 @@ void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div) \arg RCU_CKOUT1SRC_SYSTEMCLOCK: system clock selected \arg RCU_CKOUT1SRC_PLLI2SR: PLLI2SR selected \arg RCU_CKOUT1SRC_HXTAL: HXTAL selected - \arg RCU_CKOUT1SRC_PLLP: PLLP selected - \param[in] ckout1_div: CK_OUT1 divider + \arg RCU_CKOUT1SRC_PLLP: PLLP selected + \param[in] ckout1_div: CK_OUT1 divider \arg RCU_CKOUT1_DIVx(x=1,2,3,4,5): CK_OUT1 is divided by x \param[out] none \retval none @@ -460,7 +492,7 @@ void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div) void rcu_ckout1_config(uint32_t ckout1_src, uint32_t ckout1_div) { uint32_t reg; - + reg = RCU_CFG0; /* reset the CKOUT1SRC, CKOUT1DIV and set according to ckout1_src and ckout1_div */ reg &= ~(RCU_CFG0_CKOUT1SEL | RCU_CFG0_CKOUT1DIV); @@ -468,7 +500,7 @@ void rcu_ckout1_config(uint32_t ckout1_src, uint32_t ckout1_div) } /*! - \brief configure the main PLL clock + \brief configure the main PLL clock \param[in] pll_src: PLL clock source selection \arg RCU_PLLSRC_IRC16M: select IRC16M as PLL source clock \arg RCU_PLLSRC_HXTAL: select HXTAL as PLL source clock @@ -487,7 +519,7 @@ ErrStatus rcu_pll_config(uint32_t pll_src, uint32_t pll_psc, uint32_t pll_n, uin { uint32_t ss_modulation_inc; uint32_t ss_modulation_reg; - + ss_modulation_inc = 0U; ss_modulation_reg = RCU_PLLSSCTL; @@ -499,9 +531,9 @@ ErrStatus rcu_pll_config(uint32_t pll_src, uint32_t pll_psc, uint32_t pll_n, uin ss_modulation_inc += RCU_SS_MODULATION_CENTER_INC; } } - + /* check the function parameter */ - if(CHECK_PLL_PSC_VALID(pll_psc) && CHECK_PLL_N_VALID(pll_n,ss_modulation_inc) && + if(CHECK_PLL_PSC_VALID(pll_psc) && CHECK_PLL_N_VALID(pll_n,ss_modulation_inc) && CHECK_PLL_P_VALID(pll_p) && CHECK_PLL_Q_VALID(pll_q)){ RCU_PLL = pll_psc | (pll_n << 6) | (((pll_p >> 1) - 1U) << 16) | (pll_src) | (pll_q << 24); @@ -509,60 +541,55 @@ ErrStatus rcu_pll_config(uint32_t pll_src, uint32_t pll_psc, uint32_t pll_n, uin /* return status */ return ERROR; } - + /* return status */ return SUCCESS; } /*! - \brief configure the PLLI2S clock + \brief configure the PLLI2S clock \param[in] plli2s_n: the PLLI2S VCO clock multi factor \arg this parameter should be selected between 50 and 500 - \param[in] plli2s_q: the PLLI2S Q output frequency division factor from PLLI2S VCO clock - \arg this parameter should be selected between 2 and 15 \param[in] plli2s_r: the PLLI2S R output frequency division factor from PLLI2S VCO clock \arg this parameter should be selected between 2 and 7 \param[out] none \retval ErrStatus: SUCCESS or ERROR */ -ErrStatus rcu_plli2s_config(uint32_t plli2s_n, uint32_t plli2s_q, uint32_t plli2s_r) +ErrStatus rcu_plli2s_config(uint32_t plli2s_n, uint32_t plli2s_r) { /* check the function parameter */ - if(CHECK_PLLI2S_N_VALID(plli2s_n) && CHECK_PLLI2S_Q_VALID(plli2s_q) && CHECK_PLLI2S_R_VALID(plli2s_r)){ - RCU_PLLI2S = (plli2s_n << 6) | (plli2s_q << 24) | (plli2s_r << 28); + if(CHECK_PLLI2S_N_VALID(plli2s_n) && CHECK_PLLI2S_R_VALID(plli2s_r)){ + RCU_PLLI2S = (plli2s_n << 6) | (plli2s_r << 28); }else{ /* return status */ return ERROR; } - + /* return status */ - return SUCCESS; + return SUCCESS; } /*! - \brief configure the PLLSAI clock + \brief configure the PLLSAI clock \param[in] pllsai_n: the PLLSAI VCO clock multi factor \arg this parameter should be selected between 50 and 500 \param[in] pllsai_p: the PLLSAI P output frequency division factor from PLL VCO clock \arg this parameter should be selected 2,4,6,8 - \param[in] pllsai_q: the PLLSAI Q output frequency division factor from PLL VCO clock - \arg this parameter should be selected between 2 and 15 \param[in] pllsai_r: the PLLSAI R output frequency division factor from PLL VCO clock \arg this parameter should be selected between 2 and 7 \param[out] none \retval ErrStatus: SUCCESS or ERROR */ -ErrStatus rcu_pllsai_config(uint32_t pllsai_n, uint32_t pllsai_p, uint32_t pllsai_q, uint32_t pllsai_r) +ErrStatus rcu_pllsai_config(uint32_t pllsai_n, uint32_t pllsai_p, uint32_t pllsai_r) { /* check the function parameter */ - if(CHECK_PLLSAI_N_VALID(pllsai_n) && CHECK_PLLSAI_P_VALID(pllsai_p) && - CHECK_PLLSAI_Q_VALID(pllsai_q) && CHECK_PLLSAI_R_VALID(pllsai_r)){ - RCU_PLLSAI = (pllsai_n << 6U) | (((pllsai_p >> 1U) - 1U) << 16U) | (pllsai_q << 24U) | (pllsai_r << 28U); + if(CHECK_PLLSAI_N_VALID(pllsai_n) && CHECK_PLLSAI_P_VALID(pllsai_p) && CHECK_PLLSAI_R_VALID(pllsai_r)){ + RCU_PLLSAI = (pllsai_n << 6U) | (((pllsai_p >> 1U) - 1U) << 16U) | (pllsai_r << 28U); }else{ /* return status */ return ERROR; } - + /* return status */ return SUCCESS; } @@ -581,13 +608,33 @@ ErrStatus rcu_pllsai_config(uint32_t pllsai_n, uint32_t pllsai_p, uint32_t pllsa void rcu_rtc_clock_config(uint32_t rtc_clock_source) { uint32_t reg; - - reg = RCU_BDCTL; + + reg = RCU_BDCTL; /* reset the RTCSRC bits and set according to rtc_clock_source */ reg &= ~RCU_BDCTL_RTCSRC; RCU_BDCTL = (reg | rtc_clock_source); } +/*! + \brief configure the frequency division of RTC clock when HXTAL was selected as its clock source + \param[in] rtc_div: RTC clock frequency division + only one parameter can be selected which is shown as below: + \arg RCU_RTC_HXTAL_NONE: no clock for RTC + \arg RCU_RTC_HXTAL_DIVx: RTCDIV clock select CK_HXTAL/x, x = 2....31 + \param[out] none + \retval none +*/ +void rcu_rtc_div_config(uint32_t rtc_div) +{ + uint32_t reg; + + reg = RCU_CFG0; + /* reset the RTCDIV bits and set according to rtc_div value */ + reg &= ~RCU_CFG0_RTCDIV; + RCU_CFG0 = (reg | rtc_div); +} + + /*! \brief configure the I2S clock source selection \param[in] i2s_clock_source: I2S clock source selection @@ -600,8 +647,8 @@ void rcu_rtc_clock_config(uint32_t rtc_clock_source) void rcu_i2s_clock_config(uint32_t i2s_clock_source) { uint32_t reg; - - reg = RCU_CFG0; + + reg = RCU_CFG0; /* reset the I2SSEL bit and set according to i2s_clock_source */ reg &= ~RCU_CFG0_I2SSEL; RCU_CFG0 = (reg | i2s_clock_source); @@ -619,9 +666,9 @@ void rcu_i2s_clock_config(uint32_t i2s_clock_source) void rcu_ck48m_clock_config(uint32_t ck48m_clock_source) { uint32_t reg; - + reg = RCU_ADDCTL; - /* reset the I2SSEL bit and set according to i2s_clock_source */ + /* reset the CK48MSEL bit and set according to i2s_clock_source */ reg &= ~RCU_ADDCTL_CK48MSEL; RCU_ADDCTL = (reg | ck48m_clock_source); } @@ -638,7 +685,7 @@ void rcu_ck48m_clock_config(uint32_t ck48m_clock_source) void rcu_pll48m_clock_config(uint32_t pll48m_clock_source) { uint32_t reg; - + reg = RCU_ADDCTL; /* reset the PLL48MSEL bit and set according to pll48m_clock_source */ reg &= ~RCU_ADDCTL_PLL48MSEL; @@ -649,13 +696,13 @@ void rcu_pll48m_clock_config(uint32_t pll48m_clock_source) \brief configure the TIMER clock prescaler selection \param[in] timer_clock_prescaler: TIMER clock selection only one parameter can be selected which is shown as below: - \arg RCU_TIMER_PSC_MUL2: if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB) + \arg RCU_TIMER_PSC_MUL2: if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB) or 0b100(CK_APBx = CK_AHB/2), the TIMER clock is equal to CK_AHB(CK_TIMERx = CK_AHB). - or else, the TIMER clock is twice the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 2 x CK_APB1; + or else, the TIMER clock is twice the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 2 x CK_APB1; TIMER in APB2 domain: CK_TIMERx = 2 x CK_APB2) - \arg RCU_TIMER_PSC_MUL4: if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB), - 0b100(CK_APBx = CK_AHB/2), or 0b101(CK_APBx = CK_AHB/4), the TIMER clock is equal to CK_AHB(CK_TIMERx = CK_AHB). - or else, the TIMER clock is four timers the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 4 x CK_APB1; + \arg RCU_TIMER_PSC_MUL4: if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB), + 0b100(CK_APBx = CK_AHB/2), or 0b101(CK_APBx = CK_AHB/4), the TIMER clock is equal to CK_AHB(CK_TIMERx = CK_AHB). + or else, the TIMER clock is four timers the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 4 x CK_APB1; TIMER in APB2 domain: CK_TIMERx = 4 x CK_APB2) \param[out] none \retval none @@ -681,7 +728,7 @@ void rcu_timer_clock_prescaler_config(uint32_t timer_clock_prescaler) void rcu_tli_clock_div_config(uint32_t pllsai_r_div) { uint32_t reg; - + reg = RCU_CFG1; /* reset the PLLSAIRDIV bit and set according to pllsai_r_div */ reg &= ~RCU_CFG1_PLLSAIRDIV; @@ -735,9 +782,9 @@ void rcu_all_reset_flag_clear(void) \brief get the clock stabilization interrupt and ckm flags \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum only one parameter can be selected which is shown as below: - \arg RCU_INT_FLAG_IRC32KSTB: IRC40K stabilization interrupt flag + \arg RCU_INT_FLAG_IRC32KSTB: IRC32K stabilization interrupt flag \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag - \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag + \arg RCU_INT_FLAG_IRC16MSTB: IRC16M stabilization interrupt flag \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag \arg RCU_INT_FLAG_PLLI2SSTB: PLLI2S stabilization interrupt flag @@ -759,7 +806,7 @@ FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) /*! \brief clear the interrupt flags - \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum + \param[in] int_flag: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum only one parameter can be selected which is shown as below: \arg RCU_INT_FLAG_IRC32KSTB_CLR: IRC32K stabilization interrupt flag clear \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear @@ -773,14 +820,14 @@ FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) \param[out] none \retval none */ -void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear) +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag) { - RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear)); + RCU_REG_VAL(int_flag) |= BIT(RCU_BIT_POS(int_flag)); } /*! \brief enable the stabilization interrupt - \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + \param[in] interrupt: clock stabilization interrupt, refer to rcu_int_enum Only one parameter can be selected which is shown as below: \arg RCU_INT_IRC32KSTB: IRC32K stabilization interrupt enable \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable @@ -793,15 +840,15 @@ void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear) \param[out] none \retval none */ -void rcu_interrupt_enable(rcu_int_enum stab_int) +void rcu_interrupt_enable(rcu_int_enum interrupt) { - RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int)); + RCU_REG_VAL(interrupt) |= BIT(RCU_BIT_POS(interrupt)); } /*! \brief disable the stabilization interrupt - \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + \param[in] interrupt: clock stabilization interrupt, refer to rcu_int_enum only one parameter can be selected which is shown as below: \arg RCU_INT_IRC32KSTB: IRC32K stabilization interrupt disable \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt disable @@ -814,9 +861,9 @@ void rcu_interrupt_enable(rcu_int_enum stab_int) \param[out] none \retval none */ -void rcu_interrupt_disable(rcu_int_enum stab_int) +void rcu_interrupt_disable(rcu_int_enum interrupt) { - RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int)); + RCU_REG_VAL(interrupt) &= ~BIT(RCU_BIT_POS(interrupt)); } /*! @@ -831,9 +878,9 @@ void rcu_interrupt_disable(rcu_int_enum stab_int) void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap) { uint32_t reg; - + reg = RCU_BDCTL; - + /* reset the LXTALDRI bits and set according to lxtal_dricap */ reg &= ~RCU_BDCTL_LXTALDRI; RCU_BDCTL = (reg | lxtal_dricap); @@ -859,7 +906,7 @@ ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) uint32_t stb_cnt = 0U; ErrStatus reval = ERROR; FlagStatus osci_stat = RESET; - + switch(osci){ /* wait HXTAL stable */ case RCU_HXTAL: @@ -867,7 +914,7 @@ ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); stb_cnt++; } - + /* check whether flag is set */ if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){ reval = SUCCESS; @@ -879,31 +926,31 @@ ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); stb_cnt++; } - + /* check whether flag is set */ if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){ reval = SUCCESS; } break; - /* wait IRC16M stable */ + /* wait IRC16M stable */ case RCU_IRC16M: while((RESET == osci_stat) && (IRC16M_STARTUP_TIMEOUT != stb_cnt)){ osci_stat = rcu_flag_get(RCU_FLAG_IRC16MSTB); stb_cnt++; } - + /* check whether flag is set */ if(RESET != rcu_flag_get(RCU_FLAG_IRC16MSTB)){ reval = SUCCESS; } break; - /* wait IRC48M stable */ + /* wait IRC48M stable */ case RCU_IRC48M: while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB); stb_cnt++; } - + /* check whether flag is set */ if (RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)){ reval = SUCCESS; @@ -915,19 +962,19 @@ ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) osci_stat = rcu_flag_get(RCU_FLAG_IRC32KSTB); stb_cnt++; } - + /* check whether flag is set */ if(RESET != rcu_flag_get(RCU_FLAG_IRC32KSTB)){ reval = SUCCESS; } break; - /* wait PLL stable */ + /* wait PLL stable */ case RCU_PLL_CK: while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); stb_cnt++; } - + /* check whether flag is set */ if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){ reval = SUCCESS; @@ -939,29 +986,29 @@ ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) osci_stat = rcu_flag_get(RCU_FLAG_PLLI2SSTB); stb_cnt++; } - + /* check whether flag is set */ if(RESET != rcu_flag_get(RCU_FLAG_PLLI2SSTB)){ reval = SUCCESS; } break; - /* wait PLLSAI stable */ + /* wait PLLSAI stable */ case RCU_PLLSAI_CK: while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ osci_stat = rcu_flag_get(RCU_FLAG_PLLSAISTB); stb_cnt++; } - + /* check whether flag is set */ if(RESET != rcu_flag_get(RCU_FLAG_PLLSAISTB)){ reval = SUCCESS; } break; - + default: break; } - + /* return value */ return reval; } @@ -1010,8 +1057,8 @@ void rcu_osci_off(rcu_osci_type_enum osci) \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it \param[in] osci: oscillator types, refer to rcu_osci_type_enum only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: HXTAL - \arg RCU_LXTAL: LXTAL + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) \param[out] none \retval none */ @@ -1020,7 +1067,7 @@ void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) uint32_t reg; switch(osci){ - /* enable HXTAL to bypass mode */ + /* enable HXTAL to bypass mode */ case RCU_HXTAL: reg = RCU_CTL; RCU_CTL &= ~RCU_CTL_HXTALEN; @@ -1037,7 +1084,7 @@ void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) case RCU_IRC32K: case RCU_PLL_CK: case RCU_PLLI2S_CK: - case RCU_PLLSAI_CK: + case RCU_PLLSAI_CK: break; default: break; @@ -1048,17 +1095,17 @@ void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it \param[in] osci: oscillator types, refer to rcu_osci_type_enum only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: HXTAL - \arg RCU_LXTAL: LXTAL + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) \param[out] none \retval none */ void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) { uint32_t reg; - + switch(osci){ - /* disable HXTAL to bypass mode */ + /* disable HXTAL to bypass mode */ case RCU_HXTAL: reg = RCU_CTL; RCU_CTL &= ~RCU_CTL_HXTALEN; @@ -1075,7 +1122,7 @@ void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) case RCU_IRC32K: case RCU_PLL_CK: case RCU_PLLI2S_CK: - case RCU_PLLSAI_CK: + case RCU_PLLSAI_CK: break; default: break; @@ -1108,17 +1155,18 @@ void rcu_hxtal_clock_monitor_disable(void) /*! \brief set the IRC16M adjust value \param[in] irc16m_adjval: IRC16M adjust value, must be between 0 and 0x1F + \arg 0x00 - 0x1F \param[out] none \retval none */ void rcu_irc16m_adjust_value_set(uint32_t irc16m_adjval) { uint32_t reg; - + reg = RCU_CTL; /* reset the IRC16MADJ bits and set according to irc16m_adjval */ reg &= ~RCU_CTL_IRC16MADJ; - RCU_CTL = (reg | ((irc16m_adjval & 0x1FU) << 3)); + RCU_CTL = (reg | ((irc16m_adjval & RCU_IRC16M_ADJUST_MASK) << RCU_IRC16M_ADJUST_OFFSET)); } /*! @@ -1144,7 +1192,7 @@ void rcu_voltage_key_unlock(void) \retval none */ void rcu_deepsleep_voltage_set(uint32_t dsvol) -{ +{ dsvol &= RCU_DSV_DSLPVS; RCU_DSV = dsvol; } @@ -1155,16 +1203,16 @@ void rcu_deepsleep_voltage_set(uint32_t dsvol) \arg RCU_SS_TYPE_CENTER: center spread type is selected \arg RCU_SS_TYPE_DOWN: down spread type is selected \param[in] modstep: configure PLL spread spectrum modulation profile amplitude and frequency - \arg This parameter should be selected between 0 and 7FFF.The following criteria must be met: MODSTEP*MODCNT=215-1 + \arg This parameter should be selected between 0 and 7FFF.The following criteria must be met: MODSTEP*MODCNT <=2^15-1 \param[in] modcnt: configure PLL spread spectrum modulation profile amplitude and frequency - \arg This parameter should be selected between 0 and 1FFF.The following criteria must be met: MODSTEP*MODCNT=215-1 + \arg This parameter should be selected between 0 and 1FFF.The following criteria must be met: MODSTEP*MODCNT <=2^15-1 \param[out] none \retval none */ void rcu_spread_spectrum_config(uint32_t spread_spectrum_type, uint32_t modstep, uint32_t modcnt) { uint32_t reg; - + reg = RCU_PLLSSCTL; /* reset the RCU_PLLSSCTL register bits */ reg &= ~(RCU_PLLSSCTL_MODCNT | RCU_PLLSSCTL_MODSTEP | RCU_PLLSSCTL_SS_TYPE); @@ -1209,7 +1257,7 @@ uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) uint32_t sws, ck_freq = 0U; uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; uint32_t pllpsc, plln, pllsel, pllp, ck_src, idx, clk_exp; - + /* exponent of AHB, APB1 and APB2 clock divider */ const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; const uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; @@ -1231,7 +1279,7 @@ uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) pllpsc = GET_BITS(RCU_PLL, 0U, 5U); plln = GET_BITS(RCU_PLL, 6U, 14U); pllp = (GET_BITS(RCU_PLL, 16U, 17U) + 1U) * 2U; - /* PLL clock source selection, HXTAL or IRC8M/2 */ + /* PLL clock source selection, HXTAL or IRC16M/2 */ pllsel = (RCU_PLL & RCU_PLL_PLLSEL); if (RCU_PLLSRC_HXTAL == pllsel) { ck_src = HXTAL_VALUE; @@ -1249,17 +1297,17 @@ uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) idx = GET_BITS(RCU_CFG0, 4, 7); clk_exp = ahb_exp[idx]; ahb_freq = cksys_freq >> clk_exp; - + /* calculate APB1 clock frequency */ idx = GET_BITS(RCU_CFG0, 10, 12); clk_exp = apb1_exp[idx]; apb1_freq = ahb_freq >> clk_exp; - + /* calculate APB2 clock frequency */ idx = GET_BITS(RCU_CFG0, 13, 15); clk_exp = apb2_exp[idx]; apb2_freq = ahb_freq >> clk_exp; - + /* return the clocks frequency */ switch(clock){ case CK_SYS: diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c index 8e2713ceb1..12ee6c3207 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c @@ -1,14 +1,40 @@ /*! - \file gd32f4xx_rtc.c - \brief RTC driver + \file gd32f4xx_rtc.c + \brief RTC driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ + #include "gd32f4xx_rtc.h" /* RTC timeout value */ @@ -42,7 +68,7 @@ ErrStatus rtc_deinit(void) error_status = rtc_init_mode_enter(); if(ERROR != error_status){ - /* reset RTC_CTL register, but RTC_CTL[20] */ + /* reset RTC_CTL register, but RTC_CTL[2��0] */ RTC_CTL &= (RTC_REGISTER_RESET | RTC_CTL_WTCS); /* before reset RTC_TIME and RTC_DATE, BPSHAD bit in RTC_CTL should be reset as the condition. in order to read calendar from shadow register, not the real registers being reset */ @@ -50,7 +76,7 @@ ErrStatus rtc_deinit(void) RTC_DATE = RTC_DATE_RESET; RTC_PSC = RTC_PSC_RESET; - /* only when RTC_CTL_WTEN=0 and RTC_STAT_WTWF=1 can write RTC_CTL[20] */ + /* only when RTC_CTL_WTEN=0 and RTC_STAT_WTWF=1 can write RTC_CTL[2��0] */ /* wait until the WTWF flag to be set */ do{ flag_status = RTC_STAT & RTC_STAT_WTWF; @@ -63,7 +89,7 @@ ErrStatus rtc_deinit(void) RTC_WUT = RTC_WUT_RESET; RTC_COSC = RTC_REGISTER_RESET; /* to write RTC_ALRMxSS register, ALRMxEN bit in RTC_CTL register should be reset as the condition */ - RTC_ALRM0TD = RTC_REGISTER_RESET; + RTC_ALRM0TD = RTC_REGISTER_RESET; RTC_ALRM1TD = RTC_REGISTER_RESET; RTC_ALRM0SS = RTC_REGISTER_RESET; RTC_ALRM1SS = RTC_REGISTER_RESET; @@ -71,9 +97,9 @@ ErrStatus rtc_deinit(void) at the same time, RTC_STAT_SOPF bit is reset, as the condition to reset RTC_SHIFTCTL register later */ RTC_STAT = RTC_STAT_RESET; /* reset RTC_SHIFTCTL and RTC_HRFC register, this can be done without the init mode */ - RTC_SHIFTCTL = RTC_REGISTER_RESET; + RTC_SHIFTCTL = RTC_REGISTER_RESET; RTC_HRFC = RTC_REGISTER_RESET; - error_status = rtc_register_sync_wait(); + error_status = rtc_register_sync_wait(); } } @@ -85,7 +111,7 @@ ErrStatus rtc_deinit(void) /*! \brief initialize RTC registers - \param[in] rtc_initpara_struct: pointer to a rtc_parameter_struct structure which contains + \param[in] rtc_initpara_struct: pointer to a rtc_parameter_struct structure which contains parameters for initialization of the rtc peripheral members of the structure and the member values are shown as below: year: 0x0 - 0x99(BCD format) @@ -112,13 +138,13 @@ ErrStatus rtc_init(rtc_parameter_struct* rtc_initpara_struct) reg_date = (DATE_YR(rtc_initpara_struct->year) | \ DATE_DOW(rtc_initpara_struct->day_of_week) | \ DATE_MON(rtc_initpara_struct->month) | \ - DATE_DAY(rtc_initpara_struct->date)); - + DATE_DAY(rtc_initpara_struct->date)); + reg_time = (rtc_initpara_struct->am_pm| \ TIME_HR(rtc_initpara_struct->hour) | \ TIME_MN(rtc_initpara_struct->minute) | \ - TIME_SC(rtc_initpara_struct->second)); - + TIME_SC(rtc_initpara_struct->second)); + /* 1st: disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; @@ -126,7 +152,7 @@ ErrStatus rtc_init(rtc_parameter_struct* rtc_initpara_struct) /* 2nd: enter init mode */ error_status = rtc_init_mode_enter(); - if(ERROR != error_status){ + if(ERROR != error_status){ RTC_PSC = (uint32_t)(PSC_FACTOR_A(rtc_initpara_struct->factor_asyn)| \ PSC_FACTOR_S(rtc_initpara_struct->factor_syn)); @@ -135,11 +161,11 @@ ErrStatus rtc_init(rtc_parameter_struct* rtc_initpara_struct) RTC_CTL &= (uint32_t)(~RTC_CTL_CS); RTC_CTL |= rtc_initpara_struct->display_format; - - /* 3rd: exit init mode */ + + /* 3rd: exit init mode */ rtc_init_mode_exit(); - - /* 4th: wait the RSYNF flag to set */ + + /* 4th: wait the RSYNF flag to set */ error_status = rtc_register_sync_wait(); } @@ -162,15 +188,15 @@ ErrStatus rtc_init_mode_enter(void) ErrStatus error_status = ERROR; /* check whether it has been in init mode */ - if ((uint32_t)RESET == (RTC_STAT & RTC_STAT_INITF)){ + if ((uint32_t)RESET == (RTC_STAT & RTC_STAT_INITF)){ RTC_STAT |= RTC_STAT_INITM; - + /* wait until the INITF flag to be set */ do{ flag_status = RTC_STAT & RTC_STAT_INITF; }while((--time_index > 0U) && ((uint32_t)RESET == flag_status)); - if ((uint32_t)RESET != flag_status){ + if ((uint32_t)RESET != flag_status){ error_status = SUCCESS; } }else{ @@ -191,7 +217,7 @@ void rtc_init_mode_exit(void) } /*! - \brief wait until RTC_TIME and RTC_DATE registers are synchronized with APB clock, and the shadow + \brief wait until RTC_TIME and RTC_DATE registers are synchronized with APB clock, and the shadow registers are updated \param[in] none \param[out] none @@ -216,13 +242,13 @@ ErrStatus rtc_register_sync_wait(void) flag_status = RTC_STAT & RTC_STAT_RSYNF; }while((--time_index > 0U) && ((uint32_t)RESET == flag_status)); - if ((uint32_t)RESET != flag_status){ + if ((uint32_t)RESET != flag_status){ error_status = SUCCESS; } - + /* enable the write protection */ RTC_WPK = RTC_LOCK_KEY; - }else{ + }else{ error_status = SUCCESS; } @@ -232,7 +258,7 @@ ErrStatus rtc_register_sync_wait(void) /*! \brief get current time and date \param[in] none - \param[out] rtc_initpara_struct: pointer to a rtc_parameter_struct structure which contains + \param[out] rtc_initpara_struct: pointer to a rtc_parameter_struct structure which contains parameters for initialization of the rtc peripheral members of the structure and the member values are shown as below: year: 0x0 - 0x99(BCD format) @@ -254,22 +280,22 @@ void rtc_current_time_get(rtc_parameter_struct* rtc_initpara_struct) { uint32_t temp_tr = 0U, temp_dr = 0U, temp_pscr = 0U, temp_ctlr = 0U; - temp_tr = (uint32_t)RTC_TIME; + temp_tr = (uint32_t)RTC_TIME; temp_dr = (uint32_t)RTC_DATE; temp_pscr = (uint32_t)RTC_PSC; temp_ctlr = (uint32_t)RTC_CTL; - + /* get current time and construct rtc_parameter_struct structure */ rtc_initpara_struct->year = (uint8_t)GET_DATE_YR(temp_dr); rtc_initpara_struct->month = (uint8_t)GET_DATE_MON(temp_dr); rtc_initpara_struct->date = (uint8_t)GET_DATE_DAY(temp_dr); - rtc_initpara_struct->day_of_week = (uint8_t)GET_DATE_DOW(temp_dr); + rtc_initpara_struct->day_of_week = (uint8_t)GET_DATE_DOW(temp_dr); rtc_initpara_struct->hour = (uint8_t)GET_TIME_HR(temp_tr); rtc_initpara_struct->minute = (uint8_t)GET_TIME_MN(temp_tr); rtc_initpara_struct->second = (uint8_t)GET_TIME_SC(temp_tr); rtc_initpara_struct->factor_asyn = (uint16_t)GET_PSC_FACTOR_A(temp_pscr); rtc_initpara_struct->factor_syn = (uint16_t)GET_PSC_FACTOR_S(temp_pscr); - rtc_initpara_struct->am_pm = (uint32_t)(temp_pscr & RTC_TIME_PM); + rtc_initpara_struct->am_pm = (uint32_t)(temp_pscr & RTC_TIME_PM); rtc_initpara_struct->display_format = (uint32_t)(temp_ctlr & RTC_CTL_CS); } @@ -293,7 +319,7 @@ uint32_t rtc_subsecond_get(void) /*! \brief configure RTC alarm \param[in] rtc_alarm: RTC_ALARM0 or RTC_ALARM1 - \param[in] rtc_alarm_time: pointer to a rtc_alarm_struct structure which contains + \param[in] rtc_alarm_time: pointer to a rtc_alarm_struct structure which contains parameters for RTC alarm configuration members of the structure and the member values are shown as below: alarm_mask: RTC_ALARM_NONE_MASK, RTC_ALARM_DATE_MASK, RTC_ALARM_HOUR_MASK @@ -327,7 +353,7 @@ void rtc_alarm_config(uint8_t rtc_alarm, rtc_alarm_struct* rtc_alarm_time) if(RTC_ALARM0 == rtc_alarm){ RTC_ALRM0TD = (uint32_t)reg_alrmtd; - + }else{ RTC_ALRM1TD = (uint32_t)reg_alrmtd; } @@ -363,12 +389,12 @@ void rtc_alarm_subsecond_config(uint8_t rtc_alarm, uint32_t mask_subsecond, uint { /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; - RTC_WPK = RTC_UNLOCK_KEY2; + RTC_WPK = RTC_UNLOCK_KEY2; if(RTC_ALARM0 == rtc_alarm){ - RTC_ALRM0SS = mask_subsecond | subsecond; + RTC_ALRM0SS = mask_subsecond | subsecond; }else{ - RTC_ALRM1SS = mask_subsecond | subsecond; + RTC_ALRM1SS = mask_subsecond | subsecond; } /* enable the write protection */ RTC_WPK = RTC_LOCK_KEY; @@ -377,7 +403,7 @@ void rtc_alarm_subsecond_config(uint8_t rtc_alarm, uint32_t mask_subsecond, uint /*! \brief get RTC alarm \param[in] rtc_alarm: RTC_ALARM0 or RTC_ALARM1 - \param[out] rtc_alarm_time: pointer to a rtc_alarm_struct structure which contains + \param[out] rtc_alarm_time: pointer to a rtc_alarm_struct structure which contains parameters for RTC alarm configuration members of the structure and the member values are shown as below: alarm_mask: RTC_ALARM_NONE_MASK, RTC_ALARM_DATE_MASK, RTC_ALARM_HOUR_MASK @@ -403,13 +429,13 @@ void rtc_alarm_get(uint8_t rtc_alarm, rtc_alarm_struct* rtc_alarm_time) reg_alrmtd = RTC_ALRM1TD; } /* get alarm parameters and construct the rtc_alarm_struct structure */ - rtc_alarm_time->alarm_mask = reg_alrmtd & RTC_ALARM_ALL_MASK; + rtc_alarm_time->alarm_mask = reg_alrmtd & RTC_ALARM_ALL_MASK; rtc_alarm_time->am_pm = (uint32_t)(reg_alrmtd & RTC_ALRMXTD_PM); rtc_alarm_time->weekday_or_date = (uint32_t)(reg_alrmtd & RTC_ALRMXTD_DOWS); rtc_alarm_time->alarm_day = (uint8_t)GET_ALRMTD_DAY(reg_alrmtd); rtc_alarm_time->alarm_hour = (uint8_t)GET_ALRMTD_HR(reg_alrmtd); rtc_alarm_time->alarm_minute = (uint8_t)GET_ALRMTD_MN(reg_alrmtd); - rtc_alarm_time->alarm_second = (uint8_t)GET_ALRMTD_SC(reg_alrmtd); + rtc_alarm_time->alarm_second = (uint8_t)GET_ALRMTD_SC(reg_alrmtd); } /*! @@ -463,23 +489,23 @@ ErrStatus rtc_alarm_disable(uint8_t rtc_alarm) /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; - + /* clear the state of alarm */ if(RTC_ALARM0 == rtc_alarm){ - RTC_CTL &= (uint32_t)(~RTC_CTL_ALRM0EN); + RTC_CTL &= (uint32_t)(~RTC_CTL_ALRM0EN); /* wait until ALRM0WF flag to be set after the alarm is disabled */ do{ flag_status = RTC_STAT & RTC_STAT_ALRM0WF; - }while((--time_index > 0U) && ((uint32_t)RESET == flag_status)); + }while((--time_index > 0U) && ((uint32_t)RESET == flag_status)); }else{ - RTC_CTL &= (uint32_t)(~RTC_CTL_ALRM1EN); + RTC_CTL &= (uint32_t)(~RTC_CTL_ALRM1EN); /* wait until ALRM1WF flag to be set after the alarm is disabled */ do{ flag_status = RTC_STAT & RTC_STAT_ALRM1WF; }while((--time_index > 0U) && ((uint32_t)RESET == flag_status)); } - - if ((uint32_t)RESET != flag_status){ + + if ((uint32_t)RESET != flag_status){ error_status = SUCCESS; } @@ -506,7 +532,7 @@ void rtc_timestamp_enable(uint32_t edge) /* new configuration */ reg_ctl |= (uint32_t)(edge | RTC_CTL_TSEN); - + /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; @@ -528,7 +554,7 @@ void rtc_timestamp_disable(void) /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; - + /* clear the TSEN bit */ RTC_CTL &= (uint32_t)(~ RTC_CTL_TSEN); @@ -539,7 +565,7 @@ void rtc_timestamp_disable(void) /*! \brief get RTC timestamp time and date \param[in] none - \param[out] rtc_timestamp: pointer to a rtc_timestamp_struct structure which contains + \param[out] rtc_timestamp: pointer to a rtc_timestamp_struct structure which contains parameters for RTC time-stamp configuration members of the structure and the member values are shown as below: timestamp_month: RTC_JAN, RTC_FEB, RTC_MAR, RTC_APR, RTC_MAY, RTC_JUN, @@ -560,7 +586,7 @@ void rtc_timestamp_get(rtc_timestamp_struct* rtc_timestamp) /* get the value of time_stamp registers */ temp_tts = (uint32_t)RTC_TTS; temp_dts = (uint32_t)RTC_DTS; - + /* get timestamp time and construct the rtc_timestamp_struct structure */ rtc_timestamp->am_pm = (uint32_t)(temp_tts & RTC_TTS_PM); rtc_timestamp->timestamp_month = (uint8_t)GET_DTS_MON(temp_dts); @@ -583,7 +609,7 @@ uint32_t rtc_timestamp_subsecond_get(void) } /*! - \brief RTC time-stamp mapping + \brief RTC time-stamp mapping \param[in] rtc_af: \arg RTC_AF0_TIMESTAMP: RTC_AF0 use for timestamp \arg RTC_AF1_TIMESTAMP: RTC_AF1 use for timestamp @@ -598,13 +624,19 @@ void rtc_timestamp_pin_map(uint32_t rtc_af) /*! \brief enable RTC tamper - \param[in] rtc_tamper: pointer to a rtc_tamper_struct structure which contains + \param[in] rtc_tamper: pointer to a rtc_tamper_struct structure which contains parameters for RTC tamper configuration members of the structure and the member values are shown as below: + detecting tamper event can using edge mode or level mode + (1) using edge mode configuration: tamper_source: RTC_TAMPER0, RTC_TAMPER1 tamper_trigger: RTC_TAMPER_TRIGGER_EDGE_RISING, RTC_TAMPER_TRIGGER_EDGE_FALLING - RTC_TAMPER_TRIGGER_LEVEL_LOW, RTC_TAMPER_TRIGGER_LEVEL_HIGH - tamper_filter: RTC_FLT_EDGE, RTC_FLT_2S, RTC_FLT_4S, RTC_FLT_8S + tamper_filter: RTC_FLT_EDGE + tamper_with_timestamp: DISABLE, ENABLE + (2) using level mode configuration: + tamper_source: RTC_TAMPER0, RTC_TAMPER1 + tamper_trigger:RTC_TAMPER_TRIGGER_LEVEL_LOW, RTC_TAMPER_TRIGGER_LEVEL_HIGH + tamper_filter: RTC_FLT_2S, RTC_FLT_4S, RTC_FLT_8S tamper_sample_frequency: RTC_FREQ_DIV32768, RTC_FREQ_DIV16384, RTC_FREQ_DIV8192, RTC_FREQ_DIV4096, RTC_FREQ_DIV2048, RTC_FREQ_DIV1024, RTC_FREQ_DIV512, RTC_FREQ_DIV256 @@ -617,40 +649,46 @@ void rtc_timestamp_pin_map(uint32_t rtc_af) void rtc_tamper_enable(rtc_tamper_struct* rtc_tamper) { /* disable tamper */ - RTC_TAMP &= (uint32_t)~(rtc_tamper->tamper_source); + RTC_TAMP &= (uint32_t)~(rtc_tamper->tamper_source); /* tamper filter must be used when the tamper source is voltage level detection */ RTC_TAMP &= (uint32_t)~RTC_TAMP_FLT; - + /* the tamper source is voltage level detection */ - if((uint32_t)(rtc_tamper->tamper_filter) != RTC_FLT_EDGE ){ + if((uint32_t)(rtc_tamper->tamper_filter) != RTC_FLT_EDGE ){ RTC_TAMP &= (uint32_t)~(RTC_TAMP_DISPU | RTC_TAMP_PRCH | RTC_TAMP_FREQ | RTC_TAMP_FLT); /* check if the tamper pin need precharge, if need, then configure the precharge time */ if(DISABLE == rtc_tamper->tamper_precharge_enable){ - RTC_TAMP |= (uint32_t)RTC_TAMP_DISPU; + RTC_TAMP |= (uint32_t)RTC_TAMP_DISPU; }else{ RTC_TAMP |= (uint32_t)(rtc_tamper->tamper_precharge_time); } RTC_TAMP |= (uint32_t)(rtc_tamper->tamper_sample_frequency); RTC_TAMP |= (uint32_t)(rtc_tamper->tamper_filter); + + /* configure the tamper trigger */ + RTC_TAMP &= ((uint32_t)~((rtc_tamper->tamper_source) << RTC_TAMPER_TRIGGER_POS)); + if(RTC_TAMPER_TRIGGER_LEVEL_LOW != rtc_tamper->tamper_trigger){ + RTC_TAMP |= (uint32_t)((rtc_tamper->tamper_source)<< RTC_TAMPER_TRIGGER_POS); + } + }else{ + + /* configure the tamper trigger */ + RTC_TAMP &= ((uint32_t)~((rtc_tamper->tamper_source) << RTC_TAMPER_TRIGGER_POS)); + if(RTC_TAMPER_TRIGGER_EDGE_RISING != rtc_tamper->tamper_trigger){ + RTC_TAMP |= (uint32_t)((rtc_tamper->tamper_source)<< RTC_TAMPER_TRIGGER_POS); + } } - - RTC_TAMP &= (uint32_t)~RTC_TAMP_TPTS; - - if(DISABLE != rtc_tamper->tamper_with_timestamp){ + + RTC_TAMP &= (uint32_t)~RTC_TAMP_TPTS; + if(DISABLE != rtc_tamper->tamper_with_timestamp){ /* the tamper event also cause a time-stamp event */ RTC_TAMP |= (uint32_t)RTC_TAMP_TPTS; - } - - /* configure the tamper trigger */ - RTC_TAMP &= ((uint32_t)~((rtc_tamper->tamper_source) << RTC_TAMPER_TRIGGER_POS)); - if(RTC_TAMPER_TRIGGER_EDGE_RISING != rtc_tamper->tamper_trigger){ - RTC_TAMP |= (uint32_t)((rtc_tamper->tamper_source)<< RTC_TAMPER_TRIGGER_POS); - } + } /* enable tamper */ - RTC_TAMP |= (uint32_t)(rtc_tamper->tamper_source); + RTC_TAMP |= (uint32_t)(rtc_tamper->tamper_source); } /*! @@ -664,12 +702,12 @@ void rtc_tamper_enable(rtc_tamper_struct* rtc_tamper) void rtc_tamper_disable(uint32_t source) { /* disable tamper */ - RTC_TAMP &= (uint32_t)~source; + RTC_TAMP &= (uint32_t)~source; } /*! - \brief RTC tamper0 mapping + \brief RTC tamper0 mapping \param[in] rtc_af: \arg RTC_AF0_TAMPER0: RTC_AF0 use for tamper0 \arg RTC_AF1_TAMPER0: RTC_AF1 use for tamper0 @@ -681,30 +719,31 @@ void rtc_tamper0_pin_map(uint32_t rtc_af) RTC_TAMP &= ~(RTC_TAMP_TP0EN | RTC_TAMP_TP0SEL); RTC_TAMP |= rtc_af; } + /*! \brief enable specified RTC interrupt \param[in] interrupt: specify which interrupt source to be enabled \arg RTC_INT_TIMESTAMP: timestamp interrupt \arg RTC_INT_ALARM0: alarm0 interrupt \arg RTC_INT_ALARM1: alarm1 interrupt - \arg RTC_INT_TAMP: tamp interrupt + \arg RTC_INT_TAMP: tamper detection interrupt \arg RTC_INT_WAKEUP: wakeup timer interrupt \param[out] none \retval none */ void rtc_interrupt_enable(uint32_t interrupt) -{ +{ /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; - + /* enable the interrupts in RTC_CTL register */ RTC_CTL |= (uint32_t)(interrupt & (uint32_t)~RTC_TAMP_TPIE); /* enable the interrupts in RTC_TAMP register */ RTC_TAMP |= (uint32_t)(interrupt & RTC_TAMP_TPIE); - + /* enable the write protection */ - RTC_WPK = RTC_LOCK_KEY; + RTC_WPK = RTC_LOCK_KEY; } /*! @@ -713,17 +752,17 @@ void rtc_interrupt_enable(uint32_t interrupt) \arg RTC_INT_TIMESTAMP: timestamp interrupt \arg RTC_INT_ALARM0: alarm interrupt \arg RTC_INT_ALARM1: alarm interrupt - \arg RTC_INT_TAMP: tamp interrupt + \arg RTC_INT_TAMP: tamper detection interrupt \arg RTC_INT_WAKEUP: wakeup timer interrupt \param[out] none \retval none */ void rtc_interrupt_disable(uint32_t interrupt) -{ +{ /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; - + /* disable the interrupts in RTC_CTL register */ RTC_CTL &= (uint32_t)~(interrupt & (uint32_t)~RTC_TAMP_TPIE); /* disable the interrupts in RTC_TAMP register */ @@ -736,28 +775,28 @@ void rtc_interrupt_disable(uint32_t interrupt) /*! \brief check specified flag \param[in] flag: specify which flag to check - \arg RTC_STAT_RECPF: recalibration pending flag - \arg RTC_STAT_TP1F: tamper 1 event flag - \arg RTC_STAT_TP0F: tamper 0 event flag - \arg RTC_STAT_TSOVRF: time-stamp overflow event flag - \arg RTC_STAT_TSF: time-stamp event flag - \arg RTC_STAT_ALRM0F: alarm0 event flag - \arg RTC_STAT_ALRM1F: alarm1 event flag - \arg RTC_STAT_WTF: wakeup timer event flag - \arg RTC_STAT_INITF: init mode event flag - \arg RTC_STAT_RSYNF: time and date registers synchronized event flag - \arg RTC_STAT_YCM: year parameter configured event flag - \arg RTC_STAT_SOPF: shift operation pending flag - \arg RTC_STAT_ALRM0WF: alarm0 writen available flag - \arg RTC_STAT_ALRM1WF: alarm1 writen available flag - \arg RTC_STAT_WTWF: wakeup timer writen available flag + \arg RTC_STAT_SCP: smooth calibration pending flag + \arg RTC_FLAG_TP1: RTC tamper 1 detected flag + \arg RTC_FLAG_TP0: RTC tamper 0 detected flag + \arg RTC_FLAG_TSOVR: time-stamp overflow flag + \arg RTC_FLAG_TS: time-stamp flag + \arg RTC_FLAG_ALARM0: alarm0 occurs flag + \arg RTC_FLAG_ALARM1: alarm1 occurs flag + \arg RTC_FLAG_WT: wakeup timer occurs flag + \arg RTC_FLAG_INIT: initialization state flag + \arg RTC_FLAG_RSYN: register synchronization flag + \arg RTC_FLAG_YCM: year configuration mark status flag + \arg RTC_FLAG_SOP: shift function operation pending flag + \arg RTC_FLAG_ALRM0W: alarm0 configuration can be write flag + \arg RTC_FLAG_ALRM1W: alarm1 configuration can be write flag + \arg RTC_FLAG_WTW: wakeup timer can be write flag \param[out] none \retval FlagStatus: SET or RESET */ FlagStatus rtc_flag_get(uint32_t flag) { FlagStatus flag_state = RESET; - + if ((uint32_t)RESET != (RTC_STAT & flag)){ flag_state = SET; } @@ -766,21 +805,20 @@ FlagStatus rtc_flag_get(uint32_t flag) /*! \brief clear specified flag - \param[in] flag: specify which flag to clear - \arg RTC_STAT_TP1F: tamper 1 event flag - \arg RTC_STAT_TP0F: tamper 0 event flag - \arg RTC_STAT_TSOVRF: time-stamp overflow event flag - \arg RTC_STAT_TSF: time-stamp event flag - \arg RTC_STAT_WTF: time-stamp event flag - \arg RTC_STAT_ALRM0F: alarm0 event flag - \arg RTC_STAT_ALRM1F: alarm1 event flag - \arg RTC_STAT_RSYNF: time and date registers synchronized event flag + \arg RTC_FLAG_TP1: RTC tamper 1 detected flag + \arg RTC_FLAG_TP0: RTC tamper 0 detected flag + \arg RTC_FLAG_TSOVR: time-stamp overflow flag + \arg RTC_FLAG_TS: time-stamp flag + \arg RTC_FLAG_WT: wakeup timer occurs flag + \arg RTC_FLAG_ALARM0: alarm0 occurs flag + \arg RTC_FLAG_ALARM1: alarm1 occurs flag + \arg RTC_FLAG_RSYN: register synchronization flag \param[out] none \retval none */ void rtc_flag_clear(uint32_t flag) { - RTC_STAT &= (uint32_t)(~flag); + RTC_STAT &= (uint32_t)(~flag); } /*! @@ -818,10 +856,10 @@ void rtc_alarm_output_config(uint32_t source, uint32_t mode) /*! \brief configure rtc calibration output source \param[in] source: specify signal to output - \arg RTC_CALIBRATION_512HZ: when the LSE freqency is 32768Hz and the RTC_PSC + \arg RTC_CALIBRATION_512HZ: when the LSE freqency is 32768Hz and the RTC_PSC is the default value, output 512Hz signal - \arg RTC_CALIBRATION_1HZ: when the LSE freqency is 32768Hz and the RTC_PSC - is the default value, output 512Hz signal + \arg RTC_CALIBRATION_1HZ: when the LSE freqency is 32768Hz and the RTC_PSC + is the default value, output 1Hz signal \param[out] none \retval none */ @@ -852,7 +890,7 @@ void rtc_hour_adjust(uint32_t operation) /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; - + RTC_CTL |= (uint32_t)(operation); /* enable the write protection */ @@ -877,17 +915,17 @@ ErrStatus rtc_second_adjust(uint32_t add, uint32_t minus) /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; - - /* check if a shift operation is ongoing */ + + /* check if a shift operation is ongoing */ do{ flag_status = RTC_STAT & RTC_STAT_SOPF; }while((--time_index > 0U) && ((uint32_t)RESET != flag_status)); - + /* check if the function of reference clock detection is disabled */ temp = RTC_CTL & RTC_CTL_REFEN; - if((RESET == flag_status) && (RESET == temp)){ + if((RESET == flag_status) && (RESET == temp)){ RTC_SHIFTCTL = (uint32_t)(add | SHIFTCTL_SFS(minus)); - error_status = rtc_register_sync_wait(); + error_status = rtc_register_sync_wait(); } /* enable the write protection */ @@ -903,7 +941,7 @@ ErrStatus rtc_second_adjust(uint32_t add, uint32_t minus) \retval none */ void rtc_bypass_shadow_enable(void) -{ +{ /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; @@ -921,7 +959,7 @@ void rtc_bypass_shadow_enable(void) \retval none */ void rtc_bypass_shadow_disable(void) -{ +{ /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; @@ -941,7 +979,7 @@ void rtc_bypass_shadow_disable(void) ErrStatus rtc_refclock_detection_enable(void) { ErrStatus error_status = ERROR; - + /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; @@ -970,7 +1008,7 @@ ErrStatus rtc_refclock_detection_enable(void) ErrStatus rtc_refclock_detection_disable(void) { ErrStatus error_status = ERROR; - + /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; @@ -978,7 +1016,7 @@ ErrStatus rtc_refclock_detection_disable(void) /* enter init mode */ error_status = rtc_init_mode_enter(); - if(ERROR != error_status){ + if(ERROR != error_status){ RTC_CTL &= (uint32_t)~RTC_CTL_REFEN; /* exit init mode */ rtc_init_mode_exit(); @@ -1000,7 +1038,7 @@ void rtc_wakeup_enable(void) { /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; - RTC_WPK = RTC_UNLOCK_KEY2; + RTC_WPK = RTC_UNLOCK_KEY2; RTC_CTL |= RTC_CTL_WTEN; @@ -1041,12 +1079,12 @@ ErrStatus rtc_wakeup_disable(void) /*! \brief set RTC auto wakeup timer clock \param[in] wakeup_clock: - \arg WAKEUP_RTCCK_DIV16: RTC auto wakeup timer clock is RTC clock divided by 16 - \arg WAKEUP_RTCCK_DIV8: RTC auto wakeup timer clock is RTC clock divided by 8 - \arg WAKEUP_RTCCK_DIV4: RTC auto wakeup timer clock is RTC clock divided by 4 - \arg WAKEUP_RTCCK_DIV2: RTC auto wakeup timer clock is RTC clock divided by 2 + \arg WAKEUP_RTCCK_DIV16: RTC auto wakeup timer clock is RTC clock divided by 16 + \arg WAKEUP_RTCCK_DIV8: RTC auto wakeup timer clock is RTC clock divided by 8 + \arg WAKEUP_RTCCK_DIV4: RTC auto wakeup timer clock is RTC clock divided by 4 + \arg WAKEUP_RTCCK_DIV2: RTC auto wakeup timer clock is RTC clock divided by 2 \arg WAKEUP_CKSPRE: RTC auto wakeup timer clock is ckspre - \arg WAKEUP_CKSPRE_2EXP16: RTC auto wakeup timer clock is ckspre and wakeup timer add 2exp16 + \arg WAKEUP_CKSPRE_2EXP16: RTC auto wakeup timer clock is ckspre and wakeup timer add 2exp16 \param[out] none \retval ErrStatus: ERROR or SUCCESS */ @@ -1057,8 +1095,8 @@ ErrStatus rtc_wakeup_clock_set(uint8_t wakeup_clock) uint32_t flag_status = RESET; /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; - RTC_WPK = RTC_UNLOCK_KEY2; - /* only when RTC_CTL_WTEN=0 and RTC_STAT_WTWF=1 can write RTC_CTL[20] */ + RTC_WPK = RTC_UNLOCK_KEY2; + /* only when RTC_CTL_WTEN=0 and RTC_STAT_WTWF=1 can write RTC_CTL[2��0] */ /* wait until the WTWF flag to be set */ do{ flag_status = RTC_STAT & RTC_STAT_WTWF; @@ -1073,7 +1111,7 @@ ErrStatus rtc_wakeup_clock_set(uint8_t wakeup_clock) } /* enable the write protection */ RTC_WPK = RTC_LOCK_KEY; - + return error_status; } @@ -1136,16 +1174,16 @@ ErrStatus rtc_smooth_calibration_config(uint32_t window, uint32_t plus, uint32_t volatile uint32_t time_index = RTC_HRFC_TIMEOUT; ErrStatus error_status = ERROR; uint32_t flag_status = RESET; - + /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; - RTC_WPK = RTC_UNLOCK_KEY2; - - /* check if a smooth calibration operation is ongoing */ + RTC_WPK = RTC_UNLOCK_KEY2; + + /* check if a smooth calibration operation is ongoing */ do{ flag_status = RTC_STAT & RTC_STAT_SCPF; }while((--time_index > 0U) && ((uint32_t)RESET != flag_status)); - + if((uint32_t)RESET == flag_status){ RTC_HRFC = (uint32_t)(window | plus | HRFC_CMSK(minus)); error_status = SUCCESS; @@ -1172,12 +1210,12 @@ ErrStatus rtc_coarse_calibration_enable(void) /* enter init mode */ error_status = rtc_init_mode_enter(); - if(ERROR != error_status){ + if(ERROR != error_status){ RTC_CTL |= (uint32_t)RTC_CTL_CCEN; /* exit init mode */ rtc_init_mode_exit(); } - + /* enable the write protection */ RTC_WPK = RTC_LOCK_KEY; return error_status; @@ -1194,24 +1232,24 @@ ErrStatus rtc_coarse_calibration_disable(void) ErrStatus error_status = ERROR; /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; - RTC_WPK = RTC_UNLOCK_KEY2; + RTC_WPK = RTC_UNLOCK_KEY2; /* enter init mode */ error_status = rtc_init_mode_enter(); - if(ERROR != error_status){ + if(ERROR != error_status){ RTC_CTL &= (uint32_t)~RTC_CTL_CCEN; /* exit init mode */ rtc_init_mode_exit(); } - + /* enable the write protection */ - RTC_WPK = RTC_LOCK_KEY; + RTC_WPK = RTC_LOCK_KEY; return error_status; } /*! \brief config coarse calibration direction and step - \param[in] direction: CALIB_INCREASE or CALIB_DECREASE + \param[in] direction: CALIB_INCREASE or CALIB_DECREASE \param[in] step: 0x00-0x1F COSD=0: 0x00:+0 PPM @@ -1234,11 +1272,11 @@ ErrStatus rtc_coarse_calibration_config(uint8_t direction, uint8_t step) /* disable the write protection */ RTC_WPK = RTC_UNLOCK_KEY1; RTC_WPK = RTC_UNLOCK_KEY2; - + /* enter init mode */ error_status = rtc_init_mode_enter(); - if(ERROR != error_status){ + if(ERROR != error_status){ if(CALIB_DECREASE == direction){ RTC_COSC |= (uint32_t)RTC_COSC_COSD; }else{ @@ -1249,9 +1287,9 @@ ErrStatus rtc_coarse_calibration_config(uint8_t direction, uint8_t step) /* exit init mode */ rtc_init_mode_exit(); } - + /* enable the write protection */ RTC_WPK = RTC_LOCK_KEY; - + return error_status; } diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c index f7b26358b5..d1d0a0be32 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_sdio.c - \brief SDIO driver + \file gd32f4xx_sdio.c + \brief SDIO driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.1, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_sdio.h" @@ -26,12 +51,15 @@ void sdio_deinit(void) /*! \brief configure the SDIO clock \param[in] clock_edge: SDIO_CLK clock edge + only one parameter can be selected which is shown as below: \arg SDIO_SDIOCLKEDGE_RISING: select the rising edge of the SDIOCLK to generate SDIO_CLK \arg SDIO_SDIOCLKEDGE_FALLING: select the falling edge of the SDIOCLK to generate SDIO_CLK \param[in] clock_bypass: clock bypass + only one parameter can be selected which is shown as below: \arg SDIO_CLOCKBYPASS_ENABLE: clock bypass \arg SDIO_CLOCKBYPASS_DISABLE: no bypass \param[in] clock_powersave: SDIO_CLK clock dynamic switch on/off for power saving + only one parameter can be selected which is shown as below: \arg SDIO_CLOCKPWRSAVE_ENABLE: SDIO_CLK closed when bus is idle \arg SDIO_CLOCKPWRSAVE_DISABLE: SDIO_CLK clock is always on \param[in] clock_division: clock division, less than 512 @@ -79,6 +107,7 @@ void sdio_hardware_clock_disable(void) /*! \brief set different SDIO card bus mode \param[in] bus_mode: SDIO card bus mode + only one parameter can be selected which is shown as below: \arg SDIO_BUSMODE_1BIT: 1-bit SDIO card bus mode \arg SDIO_BUSMODE_4BIT: 4-bit SDIO card bus mode \arg SDIO_BUSMODE_8BIT: 8-bit SDIO card bus mode @@ -95,6 +124,7 @@ void sdio_bus_mode_set(uint32_t bus_mode) /*! \brief set the SDIO power state \param[in] power_state: SDIO power state + only one parameter can be selected which is shown as below: \arg SDIO_POWER_ON: SDIO power on \arg SDIO_POWER_OFF: SDIO power off \param[out] none @@ -105,7 +135,6 @@ void sdio_power_state_set(uint32_t power_state) SDIO_PWRCTL = power_state; } -/* get the SDIO power state */ /*! \brief get the SDIO power state \param[in] none @@ -146,6 +175,7 @@ void sdio_clock_disable(void) \param[in] cmd_index: command index, refer to the related specifications \param[in] cmd_argument: command argument, refer to the related specifications \param[in] response_type: response type + only one parameter can be selected which is shown as below: \arg SDIO_RESPONSETYPE_NO: no response \arg SDIO_RESPONSETYPE_SHORT: short response \arg SDIO_RESPONSETYPE_LONG: long response @@ -155,6 +185,8 @@ void sdio_clock_disable(void) void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type) { uint32_t cmd_config = 0U; + /* disable the CSM */ + SDIO_CMDCTL &= ~SDIO_CMDCTL_CSMEN; /* reset the command index, command argument and response type */ SDIO_CMDAGMT &= ~SDIO_CMDAGMT_CMDAGMT; SDIO_CMDAGMT = cmd_argument; @@ -168,6 +200,7 @@ void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uin /*! \brief set the command state machine wait type \param[in] wait_type: wait type + only one parameter can be selected which is shown as below: \arg SDIO_WAITTYPE_NO: not wait interrupt \arg SDIO_WAITTYPE_INTERRUPT: wait interrupt \arg SDIO_WAITTYPE_DATAEND: wait the end of data transfer @@ -218,6 +251,7 @@ uint8_t sdio_command_index_get(void) /*! \brief get the response for the last received command \param[in] sdio_responsex: SDIO response + only one parameter can be selected which is shown as below: \arg SDIO_RESPONSE0: card response[31:0]/card response[127:96] \arg SDIO_RESPONSE1: card response[95:64] \arg SDIO_RESPONSE2: card response[63:32] @@ -252,6 +286,7 @@ uint32_t sdio_response_get(uint32_t sdio_responsex) \param[in] data_timeout: data timeout period in card bus clock periods \param[in] data_length: number of data bytes to be transferred \param[in] data_blocksize: size of data block for block transfer + only one parameter can be selected which is shown as below: \arg SDIO_DATABLOCKSIZE_1BYTE: block size = 1 byte \arg SDIO_DATABLOCKSIZE_2BYTES: block size = 2 bytes \arg SDIO_DATABLOCKSIZE_4BYTES: block size = 4 bytes @@ -285,9 +320,11 @@ void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data /*! \brief configure the data transfer mode and direction \param[in] transfer_mode: mode of data transfer + only one parameter can be selected which is shown as below: \arg SDIO_TRANSMODE_BLOCK: block transfer \arg SDIO_TRANSMODE_STREAM: stream transfer or SDIO multibyte transfer \param[in] transfer_direction: data transfer direction, read or write + only one parameter can be selected which is shown as below: \arg SDIO_TRANSDIRECTION_TOCARD: write data to card \arg SDIO_TRANSDIRECTION_TOSDIO: read data from card \param[out] none @@ -394,6 +431,7 @@ void sdio_dma_disable(void) /*! \brief get the flags state of SDIO \param[in] flag: flags state of SDIO + one or more parameters can be selected which are shown as below: \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag \arg SDIO_FLAG_CMDTMOUT: command response timeout flag @@ -433,6 +471,7 @@ FlagStatus sdio_flag_get(uint32_t flag) /*! \brief clear the pending flags of SDIO \param[in] flag: flags state of SDIO + one or more parameters can be selected which are shown as below: \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag \arg SDIO_FLAG_CMDTMOUT: command response timeout flag @@ -457,6 +496,7 @@ void sdio_flag_clear(uint32_t flag) /*! \brief enable the SDIO interrupt \param[in] int_flag: interrupt flags state of SDIO + one or more parameters can be selected which are shown as below: \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt @@ -492,6 +532,7 @@ void sdio_interrupt_enable(uint32_t int_flag) /*! \brief disable the SDIO interrupt \param[in] int_flag: interrupt flags state of SDIO + one or more parameters can be selected which are shown as below: \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt @@ -527,30 +568,31 @@ void sdio_interrupt_disable(uint32_t int_flag) /*! \brief get the interrupt flags state of SDIO \param[in] int_flag: interrupt flags state of SDIO - \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt - \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt - \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt - \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt - \arg SDIO_INT_TXURE: SDIO TXURE interrupt - \arg SDIO_INT_RXORE: SDIO RXORE interrupt - \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt - \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt - \arg SDIO_INT_DTEND: SDIO DTEND interrupt - \arg SDIO_INT_STBITE: SDIO STBITE interrupt - \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt - \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt - \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt - \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt - \arg SDIO_INT_TFH: SDIO TFH interrupt - \arg SDIO_INT_RFH: SDIO RFH interrupt - \arg SDIO_INT_TFF: SDIO TFF interrupt - \arg SDIO_INT_RFF: SDIO RFF interrupt - \arg SDIO_INT_TFE: SDIO TFE interrupt - \arg SDIO_INT_RFE: SDIO RFE interrupt - \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt - \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt - \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt - \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + one or more parameters can be selected which are shown as below: + \arg SDIO_INT_FLAG_CCRCERR: SDIO CCRCERR interrupt flag + \arg SDIO_INT_FLAG_DTCRCERR: SDIO DTCRCERR interrupt flag + \arg SDIO_INT_FLAG_CMDTMOUT: SDIO CMDTMOUT interrupt flag + \arg SDIO_INT_FLAG_DTTMOUT: SDIO DTTMOUT interrupt flag + \arg SDIO_INT_FLAG_TXURE: SDIO TXURE interrupt flag + \arg SDIO_INT_FLAG_RXORE: SDIO RXORE interrupt flag + \arg SDIO_INT_FLAG_CMDRECV: SDIO CMDRECV interrupt flag + \arg SDIO_INT_FLAG_CMDSEND: SDIO CMDSEND interrupt flag + \arg SDIO_INT_FLAG_DTEND: SDIO DTEND interrupt flag + \arg SDIO_INT_FLAG_STBITE: SDIO STBITE interrupt flag + \arg SDIO_INT_FLAG_DTBLKEND: SDIO DTBLKEND interrupt flag + \arg SDIO_INT_FLAG_CMDRUN: SDIO CMDRUN interrupt flag + \arg SDIO_INT_FLAG_TXRUN: SDIO TXRUN interrupt flag + \arg SDIO_INT_FLAG_RXRUN: SDIO RXRUN interrupt flag + \arg SDIO_INT_FLAG_TFH: SDIO TFH interrupt flag + \arg SDIO_INT_FLAG_RFH: SDIO RFH interrupt flag + \arg SDIO_INT_FLAG_TFF: SDIO TFF interrupt flag + \arg SDIO_INT_FLAG_RFF: SDIO RFF interrupt flag + \arg SDIO_INT_FLAG_TFE: SDIO TFE interrupt flag + \arg SDIO_INT_FLAG_RFE: SDIO RFE interrupt flag + \arg SDIO_INT_FLAG_TXDTVAL: SDIO TXDTVAL interrupt flag + \arg SDIO_INT_FLAG_RXDTVAL: SDIO RXDTVAL interrupt flag + \arg SDIO_INT_FLAG_SDIOINT: SDIO SDIOINT interrupt flag + \arg SDIO_INT_FLAG_ATAEND: SDIO ATAEND interrupt flag \param[out] none \retval FlagStatus: SET or RESET */ @@ -566,19 +608,20 @@ FlagStatus sdio_interrupt_flag_get(uint32_t int_flag) /*! \brief clear the interrupt pending flags of SDIO \param[in] int_flag: interrupt flags state of SDIO - \arg SDIO_INT_CCRCERR: command response received (CRC check failed) flag - \arg SDIO_INT_DTCRCERR: data block sent/received (CRC check failed) flag - \arg SDIO_INT_CMDTMOUT: command response timeout flag - \arg SDIO_INT_DTTMOUT: data timeout flag - \arg SDIO_INT_TXURE: transmit FIFO underrun error occurs flag - \arg SDIO_INT_RXORE: received FIFO overrun error occurs flag - \arg SDIO_INT_CMDRECV: command response received (CRC check passed) flag - \arg SDIO_INT_CMDSEND: command sent (no response required) flag - \arg SDIO_INT_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag - \arg SDIO_INT_STBITE: start bit error in the bus flag - \arg SDIO_INT_DTBLKEND: data block sent/received (CRC check passed) flag - \arg SDIO_INT_SDIOINT: SD I/O interrupt received flag - \arg SDIO_INT_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + one or more parameters can be selected which are shown as below: + \arg SDIO_INT_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_INT_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_INT_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_INT_FLAG_DTTMOUT: data timeout flag + \arg SDIO_INT_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_INT_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_INT_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_INT_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_INT_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_INT_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_INT_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_INT_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_INT_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag \param[out] none \retval none */ @@ -634,6 +677,7 @@ void sdio_stop_readwait_disable(void) /*! \brief set the read wait type(SD I/O only) \param[in] readwait_type: SD I/O read wait type + only one parameter can be selected which is shown as below: \arg SDIO_READWAITTYPE_CLK: read wait control by stopping SDIO_CLK \arg SDIO_READWAITTYPE_DAT2: read wait control using SDIO_DAT[2] \param[out] none diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c index c5947cf174..3f842251fc 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c @@ -1,23 +1,53 @@ /*! - \file gd32f4xx_spi.c - \brief SPI driver + \file gd32f4xx_spi.c + \brief SPI driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.1, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ + #include "gd32f4xx_spi.h" #include "gd32f4xx_rcu.h" -#define SPI_INIT_MASK ((uint32_t)0x00003040U) -#define I2S_INIT_MASK ((uint32_t)0x0000F047U) -#define I2S_FULL_DUPLEX_MASK ((uint32_t)0x0000F040U) +/* SPI/I2S parameter initialization mask */ +#define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */ +#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */ +#define I2S_FULL_DUPLEX_MASK ((uint32_t)0x00000480U) /*!< I2S full duples mode configure parameter initialization mask */ + +/* default value */ +#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /*!< default value of SPI_I2SPSC register */ /*! - \brief SPI and I2S reset + \brief deinitialize SPI and I2S \param[in] spi_periph: SPIx(x=0,1,2,3,4,5),include I2S1_ADD and I2S2_ADD \param[out] none \retval none @@ -26,7 +56,7 @@ void spi_i2s_deinit(uint32_t spi_periph) { switch(spi_periph){ case SPI0: - /* reset SPI0 and I2S0 */ + /* reset SPI0 */ rcu_periph_reset_enable(RCU_SPI0RST); rcu_periph_reset_disable(RCU_SPI0RST); break; @@ -41,12 +71,12 @@ void spi_i2s_deinit(uint32_t spi_periph) rcu_periph_reset_disable(RCU_SPI2RST); break; case SPI3: - /* reset SPI3 and I2S3 */ + /* reset SPI3 */ rcu_periph_reset_enable(RCU_SPI3RST); rcu_periph_reset_disable(RCU_SPI3RST); break; case SPI4: - /* reset SPI4 and I2S4 */ + /* reset SPI4 */ rcu_periph_reset_enable(RCU_SPI4RST); rcu_periph_reset_disable(RCU_SPI4RST); break; @@ -61,41 +91,58 @@ void spi_i2s_deinit(uint32_t spi_periph) } /*! - \brief SPI parameter initialization + \brief initialize the parameters of SPI struct with default values + \param[in] none + \param[out] spi_parameter_struct: the initialized struct spi_parameter_struct pointer + \retval none +*/ +void spi_struct_para_init(spi_parameter_struct *spi_struct) +{ + /* configure the structure with default value */ + spi_struct->device_mode = SPI_SLAVE; + spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_struct->frame_size = SPI_FRAMESIZE_8BIT; + spi_struct->nss = SPI_NSS_HARD; + spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + spi_struct->prescale = SPI_PSC_2; + spi_struct->endian = SPI_ENDIAN_MSB; +} +/*! + \brief initialize SPI parameter \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[in] spi_struct: SPI parameter initialization stuct - members of the structure and the member values are shown as below: - device_mode : SPI_MASTER, SPI_SLAVE. - trans_mode : SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY, - SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT - frame_size : SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT - nss: : SPI_NSS_SOFT, SPI_NSS_HARD - endian : SPI_ENDIAN_MSB, SPI_ENDIAN_LSB - clock_polarity_phase : SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE - SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE - prescale : SPI_PSC_n (n=2,4,8,16,32,64,128,256) + \param[in] spi_struct: SPI parameter initialization stuct members of the structure + and the member values are shown as below: + device_mode: SPI_MASTER, SPI_SLAVE. + trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY, + SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT + frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT + nss: SPI_NSS_SOFT, SPI_NSS_HARD + endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB + clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE + SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE + prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256) \param[out] none \retval none */ void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct) -{ +{ uint32_t reg = 0U; reg = SPI_CTL0(spi_periph); reg &= SPI_INIT_MASK; - /* (1) select SPI as master or slave */ + /* select SPI as master or slave */ reg |= spi_struct->device_mode; - /* (2) select SPI transfer mode */ + /* select SPI transfer mode */ reg |= spi_struct->trans_mode; - /* (3) select SPI frame size */ + /* select SPI frame size */ reg |= spi_struct->frame_size; - /* (4) select SPI nss use hardware or software */ + /* select SPI nss use hardware or software */ reg |= spi_struct->nss; - /* (5) select SPI LSB or MSB */ + /* select SPI LSB or MSB */ reg |= spi_struct->endian; - /* (6) select SPI polarity and phase */ + /* select SPI polarity and phase */ reg |= spi_struct->clock_polarity_phase; - /* (7) select SPI prescale to adjust transmit speed */ + /* select SPI prescale to adjust transmit speed */ reg |= spi_struct->prescale; /* write to SPI_CTL0 register */ @@ -105,7 +152,7 @@ void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct) } /*! - \brief SPI enable + \brief enable SPI \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) \param[out] none \retval none @@ -116,7 +163,7 @@ void spi_enable(uint32_t spi_periph) } /*! - \brief SPI disable + \brief disable SPI \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) \param[out] none \retval none @@ -127,24 +174,69 @@ void spi_disable(uint32_t spi_periph) } /*! - \brief I2S prescale config - \param[in] spi_periph: SPIx(x=0,1,2,3,4) - \param[in] audiosample: - \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8khz - \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11khz - \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16khz - \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22khz - \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32khz - \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44khz - \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48khz - \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96khz - \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192khz - \param[in] frameformat: + \brief initialize I2S parameter + \param[in] spi_periph: SPIx(x=1,2) + \param[in] i2s_mode: I2S operation mode + only one parameter can be selected which is shown as below: + \arg I2S_MODE_SLAVETX : I2S slave transmit mode + \arg I2S_MODE_SLAVERX : I2S slave receive mode + \arg I2S_MODE_MASTERTX : I2S master transmit mode + \arg I2S_MODE_MASTERRX : I2S master receive mode + \param[in] i2s_standard: I2S standard + only one parameter can be selected which is shown as below: + \arg I2S_STD_PHILLIPS : I2S phillips standard + \arg I2S_STD_MSB : I2S MSB standard + \arg I2S_STD_LSB : I2S LSB standard + \arg I2S_STD_PCMSHORT : I2S PCM short standard + \arg I2S_STD_PCMLONG : I2S PCM long standard + \param[in] i2s_ckpl: I2S idle state clock polarity + only one parameter can be selected which is shown as below: + \arg I2S_CKPL_LOW : I2S clock polarity low level + \arg I2S_CKPL_HIGH : I2S clock polarity high level + \param[out] none + \retval none +*/ +void i2s_init(uint32_t spi_periph, uint32_t i2s_mode, uint32_t i2s_standard, uint32_t i2s_ckpl) +{ + uint32_t reg= 0U; + reg = SPI_I2SCTL(spi_periph); + reg &= I2S_INIT_MASK; + + /* enable I2S mode */ + reg |= (uint32_t)SPI_I2SCTL_I2SSEL; + /* select I2S mode */ + reg |= (uint32_t)i2s_mode; + /* select I2S standard */ + reg |= (uint32_t)i2s_standard; + /* select I2S polarity */ + reg |= (uint32_t)i2s_ckpl; + + /* write to SPI_I2SCTL register */ + SPI_I2SCTL(spi_periph) = (uint32_t)reg; +} + +/*! + \brief configure I2S prescale + \param[in] spi_periph: SPIx(x=1,2) + \param[in] i2s_audiosample: I2S audio sample rate + only one parameter can be selected which is shown as below: + \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz + \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz + \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz + \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz + \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz + \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz + \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz + \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz + \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz + \param[in] i2s_frameformat: I2S data length and channel length + only one parameter can be selected which is shown as below: \arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit \arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit \arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit - \param[in] mckout: + \param[in] i2s_mckout: I2S master clock output + only one parameter can be selected which is shown as below: \arg I2S_MCKOUT_ENABLE: I2S master clock output enable \arg I2S_MCKOUT_DISABLE: I2S master clock output disable \param[out] none @@ -152,8 +244,8 @@ void spi_disable(uint32_t spi_periph) */ void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_frameformat, uint32_t i2s_mckout) { - uint32_t temp_div = 2U, temp_of = 0U; - uint32_t temp = 0U; + uint32_t i2sdiv = 2U, i2sof = 0U; + uint32_t clks = 0U; uint32_t i2sclock = 0U; #ifndef I2S_EXTERNAL_CLOCK_IN @@ -161,7 +253,7 @@ void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_ #endif /* I2S_EXTERNAL_CLOCK_IN */ /* deinit SPI_I2SPSC register */ - SPI_I2SPSC(spi_periph) = 0x0002U; + SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE; #ifdef I2S_EXTERNAL_CLOCK_IN rcu_i2s_clock_config(RCU_I2SSRC_I2S_CKIN); @@ -201,28 +293,28 @@ void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_ /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */ if(I2S_MCKOUT_ENABLE == i2s_mckout){ - temp = (uint32_t)(((i2sclock / 256U) * 10U) / i2s_audiosample); + clks = (uint32_t)(((i2sclock / 256U) * 10U) / i2s_audiosample); }else{ if(I2S_FRAMEFORMAT_DT16B_CH16B == i2s_frameformat){ - temp = (uint32_t)(((i2sclock / 32U) *10U ) / i2s_audiosample); + clks = (uint32_t)(((i2sclock / 32U) *10U ) / i2s_audiosample); }else{ - temp = (uint32_t)(((i2sclock / 64U) *10U ) / i2s_audiosample); + clks = (uint32_t)(((i2sclock / 64U) *10U ) / i2s_audiosample); } } /* remove the floating point */ - temp = (temp + 5U) / 10U; - temp_of = (temp & 0x00000001U); - temp_div = ((temp - temp_of) / 2U); - temp_of = (temp_of << 8); + clks = (clks + 5U) / 10U; + i2sof = (clks & 0x00000001U); + i2sdiv = ((clks - i2sof) / 2U); + i2sof = (i2sof << 8U); /* set the default values */ - if((temp_div< 2U) || (temp_div > 255U)){ - temp_div = 2U; - temp_of = 0U; + if((i2sdiv< 2U) || (i2sdiv > 255U)){ + i2sdiv = 2U; + i2sof = 0U; } /* configure SPI_I2SPSC */ - SPI_I2SPSC(spi_periph) = (uint32_t)(temp_div | temp_of | i2s_mckout); + SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | i2s_mckout); /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */ SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN|SPI_I2SCTL_CHLEN)); @@ -231,47 +323,8 @@ void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_ } /*! - \brief I2S parameter configuration - \param[in] spi_periph: SPIx(x=0,1,2,3,4) - \param[in] i2s_mode: - \arg I2S_MODE_SLAVETX : I2S slave transmit mode - \arg I2S_MODE_SLAVERX : I2S slave receive mode - \arg I2S_MODE_MASTERTX : I2S master transmit mode - \arg I2S_MODE_MASTERRX : I2S master receive mode - \param[in] i2s_std: - \arg I2S_STD_PHILLIPS : I2S phillips standard - \arg I2S_STD_MSB : I2S MSB standard - \arg I2S_STD_LSB : I2S LSB standard - \arg I2S_STD_PCMSHORT : I2S PCM short standard - \arg I2S_STD_PCMLONG : I2S PCM long standard - \param[in] i2s_ckpl: - \arg I2S_CKPL_LOW : I2S clock polarity low level - \arg I2S_CKPL_HIGH : I2S clock polarity high level - \param[out] none - \retval none -*/ -void i2s_init(uint32_t spi_periph, uint32_t i2s_mode, uint32_t i2s_standard, uint32_t i2s_ckpl) -{ - uint32_t reg= 0U; - reg = SPI_I2SCTL(spi_periph); - reg &= I2S_INIT_MASK; - - /* enable I2S mode */ - reg |= (uint32_t)SPI_I2SCTL_I2SSEL; - /* select I2S mode */ - reg |= (uint32_t)i2s_mode; - /* select I2S standard */ - reg |= (uint32_t)i2s_standard; - /* select I2S polarity */ - reg |= (uint32_t)i2s_ckpl; - - /* write to SPI_I2SCTL register */ - SPI_I2SCTL(spi_periph) = (uint32_t)reg; -} - -/*! - \brief I2S enable - \param[in] spi_periph: SPIx(x=0,1,2,3,4) + \brief enable I2S + \param[in] spi_periph: SPIx(x=1,2) \param[out] none \retval none */ @@ -281,8 +334,8 @@ void i2s_enable(uint32_t spi_periph) } /*! - \brief I2S disable - \param[in] spi_periph: SPIx(x=0,1,2,3,4) + \brief disable I2S + \param[in] spi_periph: SPIx(x=1,2) \param[out] none \retval none */ @@ -292,7 +345,7 @@ void i2s_disable(uint32_t spi_periph) } /*! - \brief SPI nss output enable + \brief enable SPI nss output \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) \param[out] none \retval none @@ -303,7 +356,7 @@ void spi_nss_output_enable(uint32_t spi_periph) } /*! - \brief SPI nss output disable + \brief disable SPI nss output \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) \param[out] none \retval none @@ -336,11 +389,12 @@ void spi_nss_internal_low(uint32_t spi_periph) } /*! - \brief SPI dma send or receive enable + \brief enable SPI DMA send or receive \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[in] spi_dma: - \arg SPI_DMA_TRANSMIT: enable DMA transmit - \arg SPI_DMA_RECEIVE: enable DMA receive + \param[in] spi_dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data use DMA + \arg SPI_DMA_RECEIVE: SPI receive data use DMA \param[out] none \retval none */ @@ -354,11 +408,12 @@ void spi_dma_enable(uint32_t spi_periph, uint8_t spi_dma) } /*! - \brief SPI dma send or receive diable + \brief diable SPI DMA send or receive \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[in] spi_dma: - \arg SPI_DMA_TRANSMIT: disable DMA transmit - \arg SPI_DMA_RECEIVE: disable DMA receive + \param[in] spi_dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data use DMA + \arg SPI_DMA_RECEIVE: SPI receive data use DMA \param[out] none \retval none */ @@ -374,7 +429,8 @@ void spi_dma_disable(uint32_t spi_periph, uint8_t spi_dma) /*! \brief configure SPI/I2S data frame format \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[in] frame_format: + \param[in] frame_format: SPI frame size + only one parameter can be selected which is shown as below: \arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits \arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits \param[out] none @@ -384,7 +440,7 @@ void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format { /* clear SPI_CTL0_FF16 bit */ SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16); - /* confige SPI_CTL0_FF16 bit */ + /* configure SPI_CTL0_FF16 bit */ SPI_CTL0(spi_periph) |= (uint32_t)frame_format; } @@ -401,7 +457,7 @@ void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data) } /*! - \brief receive data + \brief SPI receive data \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) \param[out] none \retval 16-bit data @@ -414,16 +470,17 @@ uint16_t spi_i2s_data_receive(uint32_t spi_periph) /*! \brief configure SPI bidirectional transfer direction \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[in] transfer_direction: - \arg SPI_BIDIRECTIONAL_TEANSMIT: SPI work in transmit-only mode + \param[in] transfer_direction: SPI transfer direction + only one parameter can be selected which is shown as below: + \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode \retval none */ void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction) { - if(SPI_BIDIRECTIONAL_TEANSMIT == transfer_direction){ + if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){ /* set the transmit only mode */ - SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TEANSMIT; + SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT; }else{ /* set the receive only mode */ SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE; @@ -431,188 +488,7 @@ void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_di } /*! - \brief SPI and I2S interrupt enable - \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[in] spi_i2s_int: - \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt - \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt - \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, - transmission underrun error and format error interrupt - \param[out] none - \retval none -*/ -void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t spi_i2s_int) -{ - switch(spi_i2s_int){ - case SPI_I2S_INT_TBE: - SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE; - break; - case SPI_I2S_INT_RBNE: - SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE; - break; - case SPI_I2S_INT_ERR: - SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE; - break; - default: - break; - } -} - -/*! - \brief SPI and I2S interrupt disable - \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[in] spi_i2s_int: - \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt - \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt - \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, - transmission underrun error and format error interrupt - \param[out] none - \retval none -*/ -void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t spi_i2s_int) -{ - switch(spi_i2s_int){ - case SPI_I2S_INT_TBE : - SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE); - break; - case SPI_I2S_INT_RBNE : - SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE); - break; - case SPI_I2S_INT_ERR : - SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE); - break; - default : - break; - } -} - -/*! - \brief get interrupt flag status - \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[in] spi_i2s_int: - \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt - \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt - \arg SPI_I2S_INT_RXORERR: overrun interrupt - \arg SPI_INT_CONFERR: config error interrupt - \arg SPI_INT_CRCERR: CRC error interrupt - \arg I2S_INT_TXURERR: underrun error interrupt - \arg SPI_I2S_INT_FERR: format error interrupt - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t spi_i2s_int) -{ - uint32_t reg1 = SPI_STAT(spi_periph); - uint32_t reg2 = SPI_CTL1(spi_periph); - - uint32_t temp1 = 0U; - uint32_t temp2 = 0U; - - switch(spi_i2s_int){ - case SPI_I2S_INT_TBE : - temp1 = reg1 & SPI_STAT_TBE; - temp2 = reg2 & SPI_CTL1_TBEIE; - break; - case SPI_I2S_INT_RBNE : - temp1 = reg1 & SPI_STAT_RBNE; - temp2 = reg2 & SPI_CTL1_RBNEIE; - break; - case SPI_I2S_INT_RXORERR : - temp1 = reg1 & SPI_STAT_RXORERR; - temp2 = reg2 & SPI_CTL1_ERRIE; - break; - case SPI_INT_CONFERR : - temp1 = reg1 & SPI_STAT_CONFERR; - temp2 = reg2 & SPI_CTL1_ERRIE; - break; - case SPI_INT_CRCERR : - temp1 = reg1 & SPI_STAT_CRCERR; - temp2 = reg2 & SPI_CTL1_ERRIE; - break; - case I2S_INT_TXURERR : - temp1 = reg1 & SPI_STAT_TXURERR; - temp2 = reg2 & SPI_CTL1_ERRIE; - break; - case SPI_I2S_INT_FERR : - temp1 = reg1 & SPI_STAT_FERR; - temp2 = reg2 & SPI_CTL1_ERRIE; - break; - default : - break; - } - - if(temp1 && temp2){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief get flag status - \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[in] spi_i2s_flag: - \arg SPI_FLAG_TBE: transmit buffer empty flag - \arg SPI_FLAG_RBNE: receive buffer not empty flag - \arg SPI_FLAG_TRANS: transmit on-going flag - \arg SPI_FLAG_RXORERR: receive Overrun flag - \arg SPI_FLAG_CONFERR: mode config error flag - \arg SPI_FLAG_CRCERR: CRC error flag - \arg SPI_FLAG_FERR: format error interrupt flag - \arg I2S_FLAG_TBE: transmit buffer empty flag - \arg I2S_FLAG_RBNE: receive buffer not empty flag - \arg I2S_FLAG_TRANS: transmit on-going flag - \arg I2S_FLAG_RXORERR: overrun flag - \arg I2S_FLAG_TXURERR: underrun error flag - \arg I2S_FLAG_CH: channel side flag - \arg I2S_FLAG_FERR: format error interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t spi_i2s_flag) -{ - if(SPI_STAT(spi_periph) & spi_i2s_flag){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear SPI CRC error flag status - \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[out] none - \retval none -*/ -void spi_crc_error_clear(uint32_t spi_periph) -{ - SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR); -} - -/*! - \brief CRC function turn on - \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[out] none - \retval none -*/ -void spi_crc_on(uint32_t spi_periph) -{ - SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; -} - -/*! - \brief CRC function turn off - \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[out] none - \retval none -*/ -void spi_crc_off(uint32_t spi_periph) -{ - SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN); -} - -/*! - \brief CRC polynomial set + \brief set SPI CRC polynomial \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) \param[in] crc_poly: CRC polynomial value \param[out] none @@ -628,7 +504,7 @@ void spi_crc_polynomial_set(uint32_t spi_periph,uint16_t crc_poly) } /*! - \brief get SPI CRC polynomial + \brief get SPI CRC polynomial \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) \param[out] none \retval 16-bit CRC polynomial @@ -638,6 +514,28 @@ uint16_t spi_crc_polynomial_get(uint32_t spi_periph) return ((uint16_t)SPI_CRCPOLY(spi_periph)); } +/*! + \brief turn on CRC function + \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) + \param[out] none + \retval none +*/ +void spi_crc_on(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; +} + +/*! + \brief turn off CRC function + \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) + \param[out] none + \retval none +*/ +void spi_crc_off(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN); +} + /*! \brief SPI next data is CRC value \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) @@ -652,7 +550,8 @@ void spi_crc_next(uint32_t spi_periph) /*! \brief get SPI CRC send value or receive value \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) - \param[in] spi_crc: + \param[in] spi_crc: SPI crc value + only one parameter can be selected which is shown as below: \arg SPI_CRC_TX: get transmit crc value \arg SPI_CRC_RX: get receive crc value \param[out] none @@ -692,18 +591,18 @@ void spi_ti_mode_disable(uint32_t spi_periph) /*! \brief configure i2s full duplex mode \param[in] i2s_add_periph: I2Sx_ADD(x=1,2) - \param[in] i2s_mode: + \param[in] i2s_mode: \arg I2S_MODE_SLAVETX : I2S slave transmit mode \arg I2S_MODE_SLAVERX : I2S slave receive mode \arg I2S_MODE_MASTERTX : I2S master transmit mode \arg I2S_MODE_MASTERRX : I2S master receive mode - \param[in] i2s_standard: + \param[in] i2s_standard: \arg I2S_STD_PHILLIPS : I2S phillips standard \arg I2S_STD_MSB : I2S MSB standard \arg I2S_STD_LSB : I2S LSB standard \arg I2S_STD_PCMSHORT : I2S PCM short standard \arg I2S_STD_PCMLONG : I2S PCM long standard - \param[in] i2s_ckpl: + \param[in] i2s_ckpl: \arg I2S_CKPL_LOW : I2S clock polarity low level \arg I2S_CKPL_HIGH : I2S clock polarity high level \param[in] i2s_frameformat: @@ -720,7 +619,7 @@ void i2s_full_duplex_mode_config(uint32_t i2s_add_periph, uint32_t i2s_mode, uin uint32_t reg = 0U, tmp = 0U; reg = I2S_ADD_I2SCTL(i2s_add_periph); - reg &= I2S_FULL_DUPLEX_MASK; + reg &= I2S_FULL_DUPLEX_MASK; /* get the mode of the extra I2S module I2Sx_ADD */ if((I2S_MODE_MASTERTX == i2s_mode) || (I2S_MODE_SLAVETX == i2s_mode)){ @@ -730,7 +629,7 @@ void i2s_full_duplex_mode_config(uint32_t i2s_add_periph, uint32_t i2s_mode, uin } /* enable I2S mode */ - reg |= (uint32_t)SPI_I2SCTL_I2SSEL; + reg |= (uint32_t)SPI_I2SCTL_I2SSEL; /* select I2S mode */ reg |= (uint32_t)tmp; /* select I2S standard */ @@ -745,7 +644,7 @@ void i2s_full_duplex_mode_config(uint32_t i2s_add_periph, uint32_t i2s_mode, uin } /*! - \brief quad wire SPI enable + \brief enable quad wire SPI \param[in] spi_periph: SPIx(only x=5) \param[out] none \retval none @@ -756,7 +655,7 @@ void qspi_enable(uint32_t spi_periph) } /*! - \brief quad wire SPI disable + \brief disable quad wire SPI \param[in] spi_periph: SPIx(only x=5) \param[out] none \retval none @@ -767,7 +666,7 @@ void qspi_disable(uint32_t spi_periph) } /*! - \brief quad wire SPI write enable + \brief enable quad wire SPI write \param[in] spi_periph: SPIx(only x=5) \param[out] none \retval none @@ -778,7 +677,7 @@ void qspi_write_enable(uint32_t spi_periph) } /*! - \brief quad wire SPI read enable + \brief enable quad wire SPI read \param[in] spi_periph: SPIx(only x=5) \param[out] none \retval none @@ -789,7 +688,7 @@ void qspi_read_enable(uint32_t spi_periph) } /*! - \brief SPI_IO2 and SPI_IO3 pin output enable + \brief enable SPI_IO2 and SPI_IO3 pin output \param[in] spi_periph: SPIx(only x=5) \param[out] none \retval none @@ -800,7 +699,7 @@ void qspi_io23_output_enable(uint32_t spi_periph) } /*! - \brief SPI_IO2 and SPI_IO3 pin output disable + \brief disable SPI_IO2 and SPI_IO3 pin output \param[in] spi_periph: SPIx(only x=5) \param[out] none \retval none @@ -809,3 +708,175 @@ void qspi_io23_output_enable(uint32_t spi_periph) { SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV); } + +/*! + \brief enable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) + \param[in] spi_i2s_int: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t spi_i2s_int) +{ + switch(spi_i2s_int){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE; + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE; + break; + default: + break; + } +} + +/*! + \brief disable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) + \param[in] spi_i2s_int: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t spi_i2s_int) +{ + switch(spi_i2s_int){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE : + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE); + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE : + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE); + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR : + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE); + break; + default : + break; + } +} + +/*! + \brief get SPI and I2S interrupt flag status + \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) + \param[in] spi_i2s_int: SPI/I2S interrupt flag status + \arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag + \arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag + \arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag + \arg SPI_INT_FLAG_CONFERR: config error interrupt flag + \arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag + \arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag + \arg SPI_I2S_INT_FLAG_FERR: format error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t spi_i2s_int) +{ + uint32_t reg1 = SPI_STAT(spi_periph); + uint32_t reg2 = SPI_CTL1(spi_periph); + + switch(spi_i2s_int){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_FLAG_TBE : + reg1 = reg1 & SPI_STAT_TBE; + reg2 = reg2 & SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_FLAG_RBNE : + reg1 = reg1 & SPI_STAT_RBNE; + reg2 = reg2 & SPI_CTL1_RBNEIE; + break; + /* SPI/I2S overrun interrupt */ + case SPI_I2S_INT_FLAG_RXORERR : + reg1 = reg1 & SPI_STAT_RXORERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI config error interrupt */ + case SPI_INT_FLAG_CONFERR : + reg1 = reg1 & SPI_STAT_CONFERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI CRC error interrupt */ + case SPI_INT_FLAG_CRCERR : + reg1 = reg1 & SPI_STAT_CRCERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* I2S underrun error interrupt */ + case I2S_INT_FLAG_TXURERR : + reg1 = reg1 & SPI_STAT_TXURERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI/I2S format error interrupt */ + case SPI_I2S_INT_FLAG_FERR : + reg1 = reg1 & SPI_STAT_FERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + default : + break; + } + /*get SPI/I2S interrupt flag status */ + if(reg1 && reg2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get SPI and I2S flag status + \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) + \param[in] spi_i2s_flag: SPI/I2S flag status + \arg SPI_FLAG_TBE: transmit buffer empty flag + \arg SPI_FLAG_RBNE: receive buffer not empty flag + \arg SPI_FLAG_TRANS: transmit on-going flag + \arg SPI_FLAG_RXORERR: receive overrun error flag + \arg SPI_FLAG_CONFERR: mode config error flag + \arg SPI_FLAG_CRCERR: CRC error flag + \arg SPI_FLAG_FERR: format error flag + \arg I2S_FLAG_TBE: transmit buffer empty flag + \arg I2S_FLAG_RBNE: receive buffer not empty flag + \arg I2S_FLAG_TRANS: transmit on-going flag + \arg I2S_FLAG_RXORERR: overrun error flag + \arg I2S_FLAG_TXURERR: underrun error flag + \arg I2S_FLAG_CH: channel side flag + \arg I2S_FLAG_FERR: format error flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t spi_i2s_flag) +{ + if(SPI_STAT(spi_periph) & spi_i2s_flag){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear SPI CRC error flag status + \param[in] spi_periph: SPIx(x=0,1,2,3,4,5) + \param[out] none + \retval none +*/ +void spi_crc_error_clear(uint32_t spi_periph) +{ + SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR); +} + diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c index d834462aba..6fa0a776d0 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_syscfg.c - \brief SYSCFG driver + \file gd32f4xx_syscfg.c + \brief SYSCFG driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_syscfg.h" @@ -24,8 +49,9 @@ void syscfg_deinit(void) } /*! - \brief configure the boot mode + \brief configure the boot mode \param[in] syscfg_bootmode: selects the memory remapping + only one parameter can be selected which is shown as below: \arg SYSCFG_BOOTMODE_FLASH: main flash memory (0x08000000~0x083BFFFF) is mapped at address 0x00000000 \arg SYSCFG_BOOTMODE_BOOTLOADER: boot loader (0x1FFF0000 - 0x1FFF77FF) is mapped at address 0x00000000 \arg SYSCFG_BOOTMODE_EXMC_SRAM: SRAM/NOR 0 and 1 of EXMC (0x60000000~0x67FFFFFF) is mapped at address 0x00000000 @@ -44,6 +70,7 @@ void syscfg_bootmode_config(uint8_t syscfg_bootmode) /*! \brief FMC memory mapping swap \param[in] syscfg_fmc_swap: selects the interal flash bank swapping + only one parameter can be selected which is shown as below: \arg SYSCFG_FMC_SWP_BANK0: bank 0 is mapped at address 0x08000000 and bank 1 is mapped at address 0x08100000 \arg SYSCFG_FMC_SWP_BANK1: bank 1 is mapped at address 0x08000000 and bank 0 is mapped at address 0x08100000 \param[out] none @@ -61,6 +88,7 @@ void syscfg_fmc_swap_config(uint32_t syscfg_fmc_swap) /*! \brief EXMC memory mapping swap \param[in] syscfg_exmc_swap: selects the memories in EXMC swapping + only one parameter can be selected which is shown as below: \arg SYSCFG_EXMC_SWP_ENABLE: SDRAM bank 0 and bank 1 are swapped with NAND bank 1 and PC card \arg SYSCFG_EXMC_SWP_DISABLE: no memory mapping swap \param[out] none @@ -79,8 +107,10 @@ void syscfg_exmc_swap_config(uint32_t syscfg_exmc_swap) /*! \brief configure the GPIO pin as EXTI Line \param[in] exti_port: specify the GPIO port used in EXTI + only one parameter can be selected which is shown as below: \arg EXTI_SOURCE_GPIOx(x = A,B,C,D,E,F,G,H,I): EXTI GPIO port \param[in] exti_pin: specify the EXTI line + only one parameter can be selected which is shown as below: \arg EXTI_SOURCE_PINx(x = 0..15): EXTI GPIO pin \param[out] none \retval none @@ -123,15 +153,16 @@ void syscfg_exti_line_config(uint8_t exti_port, uint8_t exti_pin) /*! \brief configure the PHY interface for the ethernet MAC \param[in] syscfg_enet_phy_interface: specifies the media interface mode. + only one parameter can be selected which is shown as below: \arg SYSCFG_ENET_PHY_MII: MII mode is selected - \arg SYSCFG_ENET_PHY_RMII: RMII mode is selected + \arg SYSCFG_ENET_PHY_RMII: RMII mode is selected \param[out] none \retval none */ void syscfg_enet_phy_interface_config(uint32_t syscfg_enet_phy_interface) -{ +{ uint32_t reg; - + reg = SYSCFG_CFG1; /* reset the ENET_PHY_SEL bit and set according to syscfg_enet_phy_interface */ reg &= ~SYSCFG_CFG1_ENET_PHY_SEL; @@ -141,12 +172,13 @@ void syscfg_enet_phy_interface_config(uint32_t syscfg_enet_phy_interface) /*! \brief configure the I/O compensation cell \param[in] syscfg_compensation: specifies the I/O compensation cell mode + only one parameter can be selected which is shown as below: \arg SYSCFG_COMPENSATION_ENABLE: I/O compensation cell is enabled \arg SYSCFG_COMPENSATION_DISABLE: I/O compensation cell is disabled \param[out] none \retval none */ -void syscfg_compensation_config(uint32_t syscfg_compensation) +void syscfg_compensation_config(uint32_t syscfg_compensation) { uint32_t reg; diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c index 04c8fab0d3..e312680222 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c @@ -1,14 +1,40 @@ /*! - \file gd32f4xx_timer.c - \brief TIMER driver + \file gd32f4xx_timer.c + \brief TIMER driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ + #include "gd32f4xx_timer.h" /*! @@ -95,10 +121,27 @@ void timer_deinit(uint32_t timer_periph) } } +/*! + \brief initialize TIMER init parameter struct with a default value + \param[in] initpara: init parameter struct + \param[out] none + \retval none +*/ +void timer_struct_para_init(timer_parameter_struct* initpara) +{ + /* initialize the init parameter struct member with the default value */ + initpara->prescaler = 0U; + initpara->alignedmode = TIMER_COUNTER_EDGE; + initpara->counterdirection = TIMER_COUNTER_UP; + initpara->period = 65535U; + initpara->clockdivision = TIMER_CKDIV_DIV1; + initpara->repetitioncounter = 0U; +} + /*! \brief initialize TIMER counter \param[in] timer_periph: TIMERx(x=0..13) - \param[in] timer_initpara: init parameter struct + \param[in] initpara: init parameter struct prescaler: prescaler value of the counter clock,0~65535 alignedmode: TIMER_COUNTER_EDGE,TIMER_COUNTER_CENTER_DOWN,TIMER_COUNTER_CENTER_UP,TIMER_COUNTER_CENTER_BOTH counterdirection: TIMER_COUNTER_UP,TIMER_COUNTER_DOWN @@ -108,31 +151,31 @@ void timer_deinit(uint32_t timer_periph) \param[out] none \retval none */ -void timer_init(uint32_t timer_periph, timer_parameter_struct* timer_initpara) +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) { /* configure the counter prescaler value */ - TIMER_PSC(timer_periph) = (uint16_t)timer_initpara->prescaler; + TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler; /* configure the counter direction and aligned mode */ if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) || (TIMER3 == timer_periph) || (TIMER4 == timer_periph) || (TIMER7 == timer_periph)){ TIMER_CTL0(timer_periph) &= ~(uint32_t)(TIMER_CTL0_DIR|TIMER_CTL0_CAM); - TIMER_CTL0(timer_periph) |= (uint32_t)timer_initpara->alignedmode; - TIMER_CTL0(timer_periph) |= (uint32_t)timer_initpara->counterdirection; + TIMER_CTL0(timer_periph) |= (uint32_t)initpara->alignedmode; + TIMER_CTL0(timer_periph) |= (uint32_t)initpara->counterdirection; } /* configure the autoreload value */ - TIMER_CAR(timer_periph) = (uint32_t)timer_initpara->period; + TIMER_CAR(timer_periph) = (uint32_t)initpara->period; if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){ /* reset the CKDIV bit */ TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CKDIV; - TIMER_CTL0(timer_periph) |= (uint32_t)timer_initpara->clockdivision; + TIMER_CTL0(timer_periph) |= (uint32_t)initpara->clockdivision; } if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ /* configure the repetition counter value */ - TIMER_CREP(timer_periph) = (uint32_t)timer_initpara->repetitioncounter; + TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter; } /* generate an update event */ @@ -208,7 +251,8 @@ void timer_update_event_disable(uint32_t timer_periph) /*! \brief set TIMER counter alignment mode \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] timer_aligned: + \param[in] aligned: + only one parameter can be selected which is shown as below: \arg TIMER_COUNTER_EDGE: edge-aligned mode \arg TIMER_COUNTER_CENTER_DOWN: center-aligned and counting down assert mode \arg TIMER_COUNTER_CENTER_UP: center-aligned and counting up assert mode @@ -216,10 +260,10 @@ void timer_update_event_disable(uint32_t timer_periph) \param[out] none \retval none */ -void timer_counter_alignment(uint32_t timer_periph,uint16_t timer_aligned) +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned) { TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CAM; - TIMER_CTL0(timer_periph) |= (uint32_t)timer_aligned; + TIMER_CTL0(timer_periph) |= (uint32_t)aligned; } /*! @@ -247,18 +291,19 @@ void timer_counter_down_direction(uint32_t timer_periph) /*! \brief configure TIMER prescaler \param[in] timer_periph: TIMERx(x=0..13) - \param[in] timer_prescaler: prescaler value - \param[in] timer_pscreload: prescaler reload mode + \param[in] prescaler: prescaler value,0~65535 + \param[in] pscreload: prescaler reload mode + only one parameter can be selected which is shown as below: \arg TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now \arg TIMER_PSC_RELOAD_UPDATE: the prescaler is loaded at the next update event \param[out] none \retval none */ -void timer_prescaler_config(uint32_t timer_periph,uint16_t timer_prescaler,uint8_t timer_pscreload) +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint8_t pscreload) { - TIMER_PSC(timer_periph) = (uint32_t)timer_prescaler; - - if(TIMER_PSC_RELOAD_NOW == timer_pscreload){ + TIMER_PSC(timer_periph) = (uint32_t)prescaler; + + if(TIMER_PSC_RELOAD_NOW == pscreload){ TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; } } @@ -266,37 +311,37 @@ void timer_prescaler_config(uint32_t timer_periph,uint16_t timer_prescaler,uint8 /*! \brief configure TIMER repetition register value \param[in] timer_periph: TIMERx(x=0,7) - \param[in] timer_repetition: the counter repetition value,0~255 + \param[in] repetition: the counter repetition value,0~255 \param[out] none \retval none */ -void timer_repetition_value_config(uint32_t timer_periph,uint16_t timer_repetition) +void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition) { - TIMER_CREP(timer_periph) = (uint32_t)timer_repetition; -} - + TIMER_CREP(timer_periph) = (uint32_t)repetition; +} + /*! \brief configure TIMER autoreload register value \param[in] timer_periph: TIMERx(x=0..13) - \param[in] timer_autoreload: the counter auto-reload value + \param[in] autoreload: the counter auto-reload value \param[out] none \retval none -*/ -void timer_autoreload_value_config(uint32_t timer_periph,uint32_t timer_autoreload) +*/ +void timer_autoreload_value_config(uint32_t timer_periph,uint32_t autoreload) { - TIMER_CAR(timer_periph) = (uint32_t)timer_autoreload; + TIMER_CAR(timer_periph) = (uint32_t)autoreload; } /*! \brief configure TIMER counter register value \param[in] timer_periph: TIMERx(x=0..13) - \param[in] timer_counter: the counter value + \param[in] counter: the counter value,0~65535 \param[out] none \retval none -*/ -void timer_counter_value_config(uint32_t timer_periph , uint32_t timer_counter) +*/ +void timer_counter_value_config(uint32_t timer_periph , uint32_t counter) { - TIMER_CNT(timer_periph) = (uint32_t)timer_counter; + TIMER_CNT(timer_periph) = (uint32_t)counter; } /*! @@ -304,7 +349,7 @@ void timer_counter_value_config(uint32_t timer_periph , uint32_t timer_counter) \param[in] timer_periph: TIMERx(x=0..13) \param[out] none \retval counter value -*/ +*/ uint32_t timer_counter_read(uint32_t timer_periph) { uint32_t count_value = 0U; @@ -317,56 +362,61 @@ uint32_t timer_counter_read(uint32_t timer_periph) \param[in] timer_periph: TIMERx(x=0..13) \param[out] none \retval prescaler register value -*/ +*/ uint16_t timer_prescaler_read(uint32_t timer_periph) { uint16_t prescaler_value = 0U; - prescaler_value = (uint16_t)(TIMER_CAR(timer_periph)); + prescaler_value = (uint16_t)(TIMER_PSC(timer_periph)); return (prescaler_value); } /*! \brief configure TIMER single pulse mode \param[in] timer_periph: TIMERx(x=0..8,11) - \param[in] timer_spmode: + \param[in] spmode: + only one parameter can be selected which is shown as below: \arg TIMER_SP_MODE_SINGLE: single pulse mode \arg TIMER_SP_MODE_REPETITIVE: repetitive pulse mode \param[out] none \retval none */ -void timer_single_pulse_mode_config(uint32_t timer_periph,uint8_t timer_spmode) +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) { - if(TIMER_SP_MODE_SINGLE == timer_spmode){ + if(TIMER_SP_MODE_SINGLE == spmode){ TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM; - }else if(TIMER_SP_MODE_REPETITIVE == timer_spmode){ + }else if(TIMER_SP_MODE_REPETITIVE == spmode){ TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM); }else{ + /* illegal parameters */ } } /*! - \brief configure TIMER update source + \brief configure TIMER update source \param[in] timer_periph: TIMERx(x=0..13) - \param[in] timer_update: + \param[in] update: + only one parameter can be selected which is shown as below: \arg TIMER_UPDATE_SRC_GLOBAL: update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger \arg TIMER_UPDATE_SRC_REGULAR: update generate only by counter overflow/underflow \param[out] none \retval none */ -void timer_update_source_config(uint32_t timer_periph,uint8_t timer_update) +void timer_update_source_config(uint32_t timer_periph, uint32_t update) { - if(TIMER_UPDATE_SRC_REGULAR == timer_update){ + if(TIMER_UPDATE_SRC_REGULAR == update){ TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS; - }else if(timer_update == TIMER_UPDATE_SRC_GLOBAL){ + }else if(TIMER_UPDATE_SRC_GLOBAL == update){ TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS; }else{ + /* illegal parameters */ } } /*! \brief enable the TIMER interrupt - \param[in] timer_periph: please refer to the following parameters - \param[in] timer_interrupt: timer interrupt enable source + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt enable source + only one parameter can be selected which is shown as below: \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13) \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4,7..13) \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4,7,8,11) @@ -378,15 +428,16 @@ void timer_update_source_config(uint32_t timer_periph,uint8_t timer_update) \param[out] none \retval none */ -void timer_interrupt_enable(uint32_t timer_periph,uint32_t timer_interrupt) +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) { - TIMER_DMAINTEN(timer_periph) |= (uint32_t) timer_interrupt; + TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; } /*! \brief disable the TIMER interrupt \param[in] timer_periph: please refer to the following parameters - \param[in] timer_interrupt: timer interrupt source enable + \param[in] interrupt: timer interrupt source enable + only one parameter can be selected which is shown as below: \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13) \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4,7..13) \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4,7,8,11) @@ -398,31 +449,32 @@ void timer_interrupt_enable(uint32_t timer_periph,uint32_t timer_interrupt) \param[out] none \retval none */ -void timer_interrupt_disable(uint32_t timer_periph,uint32_t timer_interrupt) +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt) { - TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)timer_interrupt); + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); } /*! \brief get timer interrupt flag \param[in] timer_periph: please refer to the following parameters - \param[in] timer_interrupt: the timer interrupt bits - \arg TIMER_INT_UP: update interrupt flag,TIMERx(x=0..13) - \arg TIMER_INT_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) - \arg TIMER_INT_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_CMT: channel commutation interrupt flag,TIMERx(x=0,7) - \arg TIMER_INT_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) - \arg TIMER_INT_BRK: break interrupt flag,TIMERx(x=0,7) + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) \param[out] none \retval FlagStatus: SET or RESET */ -FlagStatus timer_interrupt_flag_get(uint32_t timer_periph,uint32_t timer_interrupt) +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt) { uint32_t val; - val = (TIMER_DMAINTEN(timer_periph) & timer_interrupt); - if((RESET != (TIMER_INTF(timer_periph) & timer_interrupt) ) && (RESET != val)){ + val = (TIMER_DMAINTEN(timer_periph) & interrupt); + if((RESET != (TIMER_INTF(timer_periph) & interrupt) ) && (RESET != val)){ return SET; }else{ return RESET; @@ -432,34 +484,36 @@ FlagStatus timer_interrupt_flag_get(uint32_t timer_periph,uint32_t timer_interru /*! \brief clear TIMER interrupt flag \param[in] timer_periph: please refer to the following parameters - \param[in] timer_interrupt: the timer interrupt bits - \arg TIMER_INT_UP: update interrupt flag,TIMERx(x=0..13) - \arg TIMER_INT_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) - \arg TIMER_INT_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_CMT: channel commutation interrupt flag,TIMERx(x=0,7) - \arg TIMER_INT_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) - \arg TIMER_INT_BRK: break interrupt flag,TIMERx(x=0,7) + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) \param[out] none \retval none */ -void timer_interrupt_flag_clear(uint32_t timer_periph,uint32_t timer_interrupt) +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt) { - TIMER_INTF(timer_periph) &= (~(uint32_t)timer_interrupt); + TIMER_INTF(timer_periph) = (~(uint32_t)interrupt); } /*! \brief get TIMER flags \param[in] timer_periph: please refer to the following parameters - \param[in] timer_flag: the timer interrupt flags + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) - \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) \arg TIMER_FLAG_CH0OF: channel 0 overcapture flag,TIMERx(x=0..4,7..11) \arg TIMER_FLAG_CH1OF: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) @@ -468,9 +522,9 @@ void timer_interrupt_flag_clear(uint32_t timer_periph,uint32_t timer_interrupt) \param[out] none \retval FlagStatus: SET or RESET */ -FlagStatus timer_flag_get(uint32_t timer_periph , uint32_t timer_flag) +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) { - if(RESET != (TIMER_INTF(timer_periph) & timer_flag)){ + if(RESET != (TIMER_INTF(timer_periph) & flag)){ return SET; }else{ return RESET; @@ -480,14 +534,15 @@ FlagStatus timer_flag_get(uint32_t timer_periph , uint32_t timer_flag) /*! \brief clear TIMER flags \param[in] timer_periph: please refer to the following parameters - \param[in] timer_flag: the timer interrupt flags + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) - \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) \arg TIMER_FLAG_CH0OF: channel 0 overcapture flag,TIMERx(x=0..4,7..11) \arg TIMER_FLAG_CH1OF: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) @@ -496,72 +551,77 @@ FlagStatus timer_flag_get(uint32_t timer_periph , uint32_t timer_flag) \param[out] none \retval none */ -void timer_flag_clear(uint32_t timer_periph , uint32_t timer_flag) +void timer_flag_clear(uint32_t timer_periph, uint32_t flag) { - TIMER_INTF(timer_periph) &= (~(uint32_t)timer_flag); + TIMER_INTF(timer_periph) = (~(uint32_t)flag); } /*! \brief enable the TIMER DMA - \param[in] timer_periph: TIMERx(x=0,1,2,5,14,15,16) - \param[in] timer_dma: timer DMA source enable - \arg TIMER_DMA_UPD: update DMA enable,TIMERx(x=0..7) - \arg TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH1D: channel 1 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH2D: channel 2 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH3D: channel 3 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CMTD: commutation DMA request enable,TIMERx(x=0,7) - \arg TIMER_DMA_TRGD: trigger DMA enable,TIMERx(x=0..4,7) + \param[in] timer_periph: please refer to the following parameters + \param[in] dma: specify which DMA to enable + one or more parameters can be selected which is shown as below: + \arg TIMER_DMA_UPD: update DMA,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA request,TIMERx(x=0..4,7) \param[out] none \retval none */ -void timer_dma_enable(uint32_t timer_periph,uint16_t timer_dma) +void timer_dma_enable(uint32_t timer_periph, uint16_t dma) { - TIMER_DMAINTEN(timer_periph) |= (uint32_t) timer_dma; + TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; } /*! \brief disable the TIMER DMA \param[in] timer_periph: please refer to the following parameters - \param[in] timer_dma: timer DMA source enable - \arg TIMER_DMA_UPD: update DMA enable,TIMERx(x=0..7) - \arg TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH1D: channel 1 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH2D: channel 2 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH3D: channel 3 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CMTD: commutation DMA request enable,TIMERx(x=0,7) - \arg TIMER_DMA_TRGD: trigger DMA enable,TIMERx(x=0..4,7) + \param[in] dma: specify which DMA to disable + one or more parameters can be selected which are shown as below: + \arg TIMER_DMA_UPD: update DMA,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request ,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA request,TIMERx(x=0..4,7) \param[out] none \retval none */ -void timer_dma_disable(uint32_t timer_periph,uint16_t timer_dma) +void timer_dma_disable(uint32_t timer_periph, uint16_t dma) { - TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(timer_dma)); + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); } /*! \brief channel DMA request source selection \param[in] timer_periph: TIMERx(x=0..4,7) \param[in] dma_request: channel DMA request source selection + only one parameter can be selected which is shown as below: \arg TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel y is sent when channel y event occurs - \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs + \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs \param[out] none \retval none */ -void timer_channel_dma_request_source_select(uint32_t timer_periph,uint8_t dma_request) +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint8_t dma_request) { if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){ TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS; }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){ TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS; }else{ + /* illegal parameters */ } } /*! \brief configure the TIMER DMA transfer \param[in] timer_periph: please refer to the following parameters - \param[in] dma_baseaddr: + \param[in] dma_baseaddr: + only one parameter can be selected which is shown as below: \arg TIMER_DMACFG_DMATA_CTL0: DMA transfer address is TIMER_CTL0,TIMERx(x=0..4,7) \arg TIMER_DMACFG_DMATA_CTL1: DMA transfer address is TIMER_CTL1,TIMERx(x=0..4,7) \arg TIMER_DMACFG_DMATA_SMCFG: DMA transfer address is TIMER_SMCFG,TIMERx(x=0..4,7) @@ -579,44 +639,64 @@ void timer_channel_dma_request_source_select(uint32_t timer_periph,uint8_t dma_r \arg TIMER_DMACFG_DMATA_CH1CV: DMA transfer address is TIMER_CH1CV,TIMERx(x=0..4,7) \arg TIMER_DMACFG_DMATA_CH2CV: DMA transfer address is TIMER_CH2CV,TIMERx(x=0..4,7) \arg TIMER_DMACFG_DMATA_CH3CV: DMA transfer address is TIMER_CH3CV,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP,TIMERx(x=0..4,7) \arg TIMER_DMACFG_DMATA_DMACFG: DMA transfer address is TIMER_DMACFG,TIMERx(x=0..4,7) \arg TIMER_DMACFG_DMATA_DMATB: DMA transfer address is TIMER_DMATB,TIMERx(x=0..4,7) \param[in] dma_lenth: + only one parameter can be selected which is shown as below: \arg TIMER_DMACFG_DMATC_xTRANSFER(x=1..18): DMA transfer x time \param[out] none \retval none */ -void timer_dma_transfer_config(uint32_t timer_periph,uint32_t dma_baseaddr,uint32_t dma_lenth) +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth) { TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth); } /*! - \brief software generate events + \brief software generate events \param[in] timer_periph: please refer to the following parameters - \param[in] timer_event: the timer software event generation sources + \param[in] event: the timer software event generation sources + one or more parameters can be selected which are shown as below: \arg TIMER_EVENT_SRC_UPG: update event,TIMERx(x=0..13) - \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation,TIMERx(x=0..4,7..13) + \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation,TIMERx(x=0..4,7..13) \arg TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation,TIMERx(x=0..4,7,8,11) - \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation,TIMERx(x=0..4,7) - \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation,TIMERx(x=0..4,7) - \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation,TIMERx(x=0,7) + \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation,TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation,TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation,TIMERx(x=0,7) \arg TIMER_EVENT_SRC_TRGG: trigger event generation,TIMERx(x=0..4,7,8,11) \arg TIMER_EVENT_SRC_BRKG: break event generation,TIMERx(x=0,7) \param[out] none \retval none */ -void timer_event_software_generate(uint32_t timer_periph,uint16_t timer_event) +void timer_event_software_generate(uint32_t timer_periph, uint16_t event) { - TIMER_SWEVG(timer_periph) |= (uint32_t)timer_event; + TIMER_SWEVG(timer_periph) |= (uint32_t)event; } /*! - \brief configure TIMER break function + \brief initialize TIMER break parameter struct with a default value + \param[in] breakpara: TIMER break parameter struct + \param[out] none + \retval none +*/ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) +{ + /* initialize the break parameter struct member with the default value */ + breakpara->runoffstate = TIMER_ROS_STATE_DISABLE; + breakpara->ideloffstate = TIMER_IOS_STATE_DISABLE; + breakpara->deadtime = 0U; + breakpara->breakpolarity = TIMER_BREAK_POLARITY_LOW; + breakpara->outputautostate = TIMER_OUTAUTO_DISABLE; + breakpara->protectmode = TIMER_CCHP_PROT_OFF; + breakpara->breakstate = TIMER_BREAK_DISABLE; +} + +/*! + \brief configure TIMER break function \param[in] timer_periph: TIMERx(x=0,7) - \param[in] timer_bkdtpara: TIMER break parameter struct + \param[in] breakpara: TIMER break parameter struct runoffstate: TIMER_ROS_STATE_ENABLE,TIMER_ROS_STATE_DISABLE ideloffstate: TIMER_IOS_STATE_ENABLE,TIMER_IOS_STATE_DISABLE deadtime: 0~255 @@ -627,15 +707,15 @@ void timer_event_software_generate(uint32_t timer_periph,uint16_t timer_event) \param[out] none \retval none */ -void timer_break_config(uint32_t timer_periph,timer_break_parameter_struct* timer_bkdtpara) +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara) { - TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(timer_bkdtpara->runoffstate))| - ((uint32_t)(timer_bkdtpara->ideloffstate))| - ((uint32_t)(timer_bkdtpara->deadtime))| - ((uint32_t)(timer_bkdtpara->breakpolarity))| - ((uint32_t)(timer_bkdtpara->outputautostate)) | - ((uint32_t)(timer_bkdtpara->protectmode))| - ((uint32_t)(timer_bkdtpara->breakstate))) ; + TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate))| + ((uint32_t)(breakpara->ideloffstate))| + ((uint32_t)(breakpara->deadtime))| + ((uint32_t)(breakpara->breakpolarity))| + ((uint32_t)(breakpara->outputautostate)) | + ((uint32_t)(breakpara->protectmode))| + ((uint32_t)(breakpara->breakstate))) ; } /*! @@ -689,7 +769,7 @@ void timer_automatic_output_disable(uint32_t timer_periph) \param[out] none \retval none */ -void timer_primary_output_config(uint32_t timer_periph,ControlStatus newvalue) +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue) { if(ENABLE == newvalue){ TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN; @@ -699,13 +779,13 @@ void timer_primary_output_config(uint32_t timer_periph,ControlStatus newvalue) } /*! - \brief channel capture/compare control shadow register enable + \brief enable or disable channel capture/compare control shadow register \param[in] timer_periph: TIMERx(x=0,7) - \param[in] newvalue: ENABLE or DISABLE + \param[in] newvalue: ENABLE or DISABLE \param[out] none \retval none */ -void timer_channel_control_shadow_config(uint32_t timer_periph,ControlStatus newvalue) +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue) { if(ENABLE == newvalue){ TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE; @@ -717,31 +797,51 @@ void timer_channel_control_shadow_config(uint32_t timer_periph,ControlStatus new /*! \brief configure TIMER channel control shadow register update control \param[in] timer_periph: TIMERx(x=0,7) - \param[in] timer_ccuctl: channel control shadow register update control + \param[in] ccuctl: channel control shadow register update control + only one parameter can be selected which is shown as below: \arg TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set - \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs + \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs \param[out] none \retval none -*/ -void timer_channel_control_shadow_update_config(uint32_t timer_periph,uint8_t timer_ccuctl) +*/ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint8_t ccuctl) { - if(TIMER_UPDATECTL_CCU == timer_ccuctl){ + if(TIMER_UPDATECTL_CCU == ccuctl){ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC); - }else if(TIMER_UPDATECTL_CCUTRI == timer_ccuctl){ + }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){ TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC; }else{ + /* illegal parameters */ } } +/*! + \brief initialize TIMER channel output parameter struct with a default value + \param[in] ocpara: TIMER channel n output parameter struct + \param[out] none + \retval none +*/ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) +{ + /* initialize the channel output parameter struct member with the default value */ + ocpara->outputstate = (uint16_t)TIMER_CCX_DISABLE; + ocpara->outputnstate = TIMER_CCXN_DISABLE; + ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH; + ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH; + ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW; + ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; +} + /*! \brief configure TIMER channel output function \param[in] timer_periph: please refer to the following parameters - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) - \param[in] timer_ocpara: TIMER channeln output parameter struct + \param[in] ocpara: TIMER channeln output parameter struct outputstate: TIMER_CCX_ENABLE,TIMER_CCX_DISABLE outputnstate: TIMER_CCXN_ENABLE,TIMER_CCXN_DISABLE ocpolarity: TIMER_OC_POLARITY_HIGH,TIMER_OC_POLARITY_LOW @@ -751,120 +851,120 @@ void timer_channel_control_shadow_update_config(uint32_t timer_periph,uint8_t ti \param[out] none \retval none */ -void timer_channel_output_config(uint32_t timer_periph,uint16_t timer_channel,timer_oc_parameter_struct* timer_ocpara) +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara) { - switch(timer_channel){ + switch(channel){ /* configure TIMER_CH_0 */ case TIMER_CH_0: /* reset the CH0EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS; /* set the CH0EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)timer_ocpara->outputstate; + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputstate; /* reset the CH0P bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); /* set the CH0P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)timer_ocpara->ocpolarity; + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity; if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ /* reset the CH0NEN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); /* set the CH0NEN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)timer_ocpara->outputnstate; + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputnstate; /* reset the CH0NP bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); /* set the CH0NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)timer_ocpara->ocnpolarity; + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocnpolarity; /* reset the ISO0 bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0); /* set the ISO0 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)timer_ocpara->ocidlestate; + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocidlestate; /* reset the ISO0N bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0N); /* set the ISO0N bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)timer_ocpara->ocnidlestate; + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocnidlestate; } - TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS; break; /* configure TIMER_CH_1 */ case TIMER_CH_1: /* reset the CH1EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS; /* set the CH1EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)(timer_ocpara->outputstate<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpara->outputstate << 4U); /* reset the CH1P bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); /* set the CH1P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->ocpolarity)<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 4U); if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ /* reset the CH1NEN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); /* set the CH1NEN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->outputnstate)<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 4U); /* reset the CH1NP bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); /* set the CH1NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->ocnpolarity)<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 4U); /* reset the ISO1 bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1); /* set the ISO1 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->ocidlestate)<< 2U); + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 2U); /* reset the ISO1N bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N); /* set the ISO1N bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->ocnidlestate)<< 2U); + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 2U); } - TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS; break; /* configure TIMER_CH_2 */ case TIMER_CH_2: /* reset the CH2EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS; /* set the CH2EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)(timer_ocpara->outputstate<< 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpara->outputstate << 8U); /* reset the CH2P bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); /* set the CH2P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->ocpolarity)<< 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 8U); if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ /* reset the CH2NEN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); /* set the CH2NEN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->outputnstate)<< 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 8U); /* reset the CH2NP bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); /* set the CH2NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->ocnpolarity)<< 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 8U); /* reset the ISO2 bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2); /* set the ISO2 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->ocidlestate)<< 4U); + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 4U); /* reset the ISO2N bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N); /* set the ISO2N bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->ocnidlestate)<< 4U); + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 4U); } - TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS; break; /* configure TIMER_CH_3 */ case TIMER_CH_3: /* reset the CH3EN bit */ TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; /* set the CH3EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)(timer_ocpara->outputstate<< 12U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpara->outputstate << 12U); /* reset the CH3P bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); /* set the CH3P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->ocpolarity)<< 12U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 12U); if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ /* reset the ISO3 bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3); /* set the ISO3 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(timer_ocpara->ocidlestate)<< 6U); + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 6U); } - TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; break; default: break; @@ -874,12 +974,14 @@ void timer_channel_output_config(uint32_t timer_periph,uint16_t timer_channel,ti /*! \brief configure TIMER channel output compare mode \param[in] timer_periph: please refer to the following parameters - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] timer_ocmode: channel output compare mode + \param[in] ocmode: channel output compare mode + only one parameter can be selected which is shown as below: \arg TIMER_OC_MODE_TIMING: timing mode \arg TIMER_OC_MODE_ACTIVE: active mode \arg TIMER_OC_MODE_INACTIVE: inactive mode @@ -891,28 +993,28 @@ void timer_channel_output_config(uint32_t timer_periph,uint16_t timer_channel,ti \param[out] none \retval none */ -void timer_channel_output_mode_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocmode) +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode) { - switch(timer_channel){ + switch(channel){ /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL); - TIMER_CHCTL0(timer_periph) |= (uint32_t)timer_ocmode; + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocmode; break; /* configure TIMER_CH_1 */ case TIMER_CH_1: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(timer_ocmode)<< 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); break; /* configure TIMER_CH_2 */ case TIMER_CH_2: TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCTL); - TIMER_CHCTL1(timer_periph) |= (uint32_t)timer_ocmode; + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocmode; break; /* configure TIMER_CH_3 */ case TIMER_CH_3: TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(timer_ocmode)<< 8U); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); break; default: break; @@ -922,29 +1024,34 @@ void timer_channel_output_mode_config(uint32_t timer_periph,uint16_t timer_chann /*! \brief configure TIMER channel output pulse value \param[in] timer_periph: please refer to the following parameters - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] timer_pluse: channel output pulse value + \param[in] pulse: channel output pulse value,0~65535 \param[out] none \retval none */ -void timer_channel_output_pulse_value_config(uint32_t timer_periph,uint16_t timer_channel,uint32_t timer_pluse) +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse) { - switch(timer_channel){ + switch(channel){ + /* configure TIMER_CH_0 */ case TIMER_CH_0: - TIMER_CH0CV(timer_periph) = (uint32_t)timer_pluse; + TIMER_CH0CV(timer_periph) = (uint32_t)pulse; break; + /* configure TIMER_CH_1 */ case TIMER_CH_1: - TIMER_CH1CV(timer_periph) = (uint32_t)timer_pluse; + TIMER_CH1CV(timer_periph) = (uint32_t)pulse; break; + /* configure TIMER_CH_2 */ case TIMER_CH_2: - TIMER_CH2CV(timer_periph) = (uint32_t)timer_pluse; + TIMER_CH2CV(timer_periph) = (uint32_t)pulse; break; + /* configure TIMER_CH_3 */ case TIMER_CH_3: - TIMER_CH3CV(timer_periph) = (uint32_t)timer_pluse; + TIMER_CH3CV(timer_periph) = (uint32_t)pulse; break; default: break; @@ -954,39 +1061,41 @@ void timer_channel_output_pulse_value_config(uint32_t timer_periph,uint16_t time /*! \brief configure TIMER channel output shadow function \param[in] timer_periph: please refer to the following parameters - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] timer_ocshadow: channel output shadow state + \param[in] ocshadow: channel output shadow state + only one parameter can be selected which is shown as below: \arg TIMER_OC_SHADOW_ENABLE: channel output shadow state enable \arg TIMER_OC_SHADOW_DISABLE: channel output shadow state disable \param[out] none \retval none */ -void timer_channel_output_shadow_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocshadow) +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow) { - switch(timer_channel){ + switch(channel){ /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)timer_ocshadow; + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocshadow; break; /* configure TIMER_CH_1 */ case TIMER_CH_1: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMSEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(timer_ocshadow) << 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); break; /* configure TIMER_CH_2 */ case TIMER_CH_2: TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMSEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)timer_ocshadow; + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocshadow; break; /* configure TIMER_CH_3 */ case TIMER_CH_3: TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMSEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(timer_ocshadow) << 8U); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); break; default: break; @@ -996,39 +1105,41 @@ void timer_channel_output_shadow_config(uint32_t timer_periph,uint16_t timer_cha /*! \brief configure TIMER channel output fast function \param[in] timer_periph: please refer to the following parameters - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] timer_ocfast: channel output fast function + \param[in] ocfast: channel output fast function + only one parameter can be selected which is shown as below: \arg TIMER_OC_FAST_ENABLE: channel output fast function enable \arg TIMER_OC_FAST_DISABLE: channel output fast function disable \param[out] none \retval none */ -void timer_channel_output_fast_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocfast) +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast) { - switch(timer_channel){ + switch(channel){ /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)timer_ocfast; + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocfast; break; /* configure TIMER_CH_1 */ case TIMER_CH_1: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMFEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)timer_ocfast << 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); break; /* configure TIMER_CH_2 */ case TIMER_CH_2: TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMFEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)timer_ocfast; + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocfast; break; /* configure TIMER_CH_3 */ case TIMER_CH_3: TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMFEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)timer_ocfast << 8U); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); break; default: break; @@ -1037,40 +1148,42 @@ void timer_channel_output_fast_config(uint32_t timer_periph,uint16_t timer_chann /*! \brief configure TIMER channel output clear function - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] timer_channel: - \arg TIMER_CH_0: TIMER channel0 - \arg TIMER_CH_1: TIMER channel1 - \arg TIMER_CH_2: TIMER channel2 - \arg TIMER_CH_3: TIMER channel3 - \param[in] timer_occlear: channel output clear function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] occlear: channel output clear function + only one parameter can be selected which is shown as below: \arg TIMER_OC_CLEAR_ENABLE: channel output clear function enable \arg TIMER_OC_CLEAR_DISABLE: channel output clear function disable \param[out] none \retval none */ -void timer_channel_output_clear_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_occlear) +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear) { - switch(timer_channel){ + switch(channel){ /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)timer_occlear; + TIMER_CHCTL0(timer_periph) |= (uint32_t)occlear; break; /* configure TIMER_CH_1 */ case TIMER_CH_1: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)timer_occlear << 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); break; /* configure TIMER_CH_2 */ case TIMER_CH_2: TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)timer_occlear; + TIMER_CHCTL1(timer_periph) |= (uint32_t)occlear; break; /* configure TIMER_CH_3 */ case TIMER_CH_3: TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)timer_occlear << 8U); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); break; default: break; @@ -1078,41 +1191,43 @@ void timer_channel_output_clear_config(uint32_t timer_periph,uint16_t timer_chan } /*! - \brief configure TIMER channel output polarity + \brief configure TIMER channel output polarity \param[in] timer_periph: please refer to the following parameters - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] timer_ocpolarity: channel output polarity + \param[in] ocpolarity: channel output polarity + only one parameter can be selected which is shown as below: \arg TIMER_OC_POLARITY_HIGH: channel output polarity is high \arg TIMER_OC_POLARITY_LOW: channel output polarity is low \param[out] none \retval none */ -void timer_channel_output_polarity_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocpolarity) +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity) { - switch(timer_channel){ + switch(channel){ /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)timer_ocpolarity; + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpolarity; break; /* configure TIMER_CH_1 */ case TIMER_CH_1: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)timer_ocpolarity << 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 4U); break; /* configure TIMER_CH_2 */ case TIMER_CH_2: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)timer_ocpolarity << 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 8U); break; /* configure TIMER_CH_3 */ case TIMER_CH_3: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)timer_ocpolarity << 12U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 12U); break; default: break; @@ -1120,35 +1235,37 @@ void timer_channel_output_polarity_config(uint32_t timer_periph,uint16_t timer_c } /*! - \brief configure TIMER channel complementary output polarity - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] timer_channel: + \brief configure TIMER channel complementary output polarity + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \param[in] timer_ocnpolarity: channel complementary output polarity + \param[in] ocnpolarity: channel complementary output polarity + only one parameter can be selected which is shown as below: \arg TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high \arg TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low \param[out] none \retval none */ -void timer_channel_complementary_output_polarity_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocnpolarity) +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity) { - switch(timer_channel){ + switch(channel){ /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); - TIMER_CHCTL2(timer_periph) |= (uint32_t)timer_ocnpolarity; + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnpolarity; break; /* configure TIMER_CH_1 */ case TIMER_CH_1: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)timer_ocnpolarity << 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 4U); break; /* configure TIMER_CH_2 */ case TIMER_CH_2: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)timer_ocnpolarity << 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 8U); break; default: break; @@ -1158,39 +1275,41 @@ void timer_channel_complementary_output_polarity_config(uint32_t timer_periph,ui /*! \brief configure TIMER channel enable state \param[in] timer_periph: please refer to the following parameters - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] timer_state: TIMER channel enable state - \arg TIMER_CCX_ENABLE: channel enable - \arg TIMER_CCX_DISABLE: channel disable + \param[in] state: TIMER channel enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCX_ENABLE: channel enable + \arg TIMER_CCX_DISABLE: channel disable \param[out] none \retval none */ -void timer_channel_output_state_config(uint32_t timer_periph,uint16_t timer_channel,uint32_t timer_state) +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state) { - switch(timer_channel){ + switch(channel){ /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)timer_state; + TIMER_CHCTL2(timer_periph) |= (uint32_t)state; break; /* configure TIMER_CH_1 */ case TIMER_CH_1: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)timer_state << 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 4U); break; /* configure TIMER_CH_2 */ case TIMER_CH_2: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)timer_state << 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 8U); break; /* configure TIMER_CH_3 */ case TIMER_CH_3: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)timer_state << 12U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 12U); break; default: break; @@ -1200,33 +1319,35 @@ void timer_channel_output_state_config(uint32_t timer_periph,uint16_t timer_chan /*! \brief configure TIMER channel complementary output enable state \param[in] timer_periph: TIMERx(x=0,7) - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0 \arg TIMER_CH_1: TIMER channel1 \arg TIMER_CH_2: TIMER channel2 - \param[in] timer_ocnstate: TIMER channel complementary output enable state - \arg TIMER_CCXN_ENABLE: channel complementary enable - \arg TIMER_CCXN_DISABLE: channel complementary disable + \param[in] ocnstate: TIMER channel complementary output enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCXN_ENABLE: channel complementary enable + \arg TIMER_CCXN_DISABLE: channel complementary disable \param[out] none \retval none */ -void timer_channel_complementary_output_state_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_ocnstate) +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate) { - switch(timer_channel){ + switch(channel){ /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)timer_ocnstate; + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnstate; break; /* configure TIMER_CH_1 */ case TIMER_CH_1: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)timer_ocnstate << 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 4U); break; /* configure TIMER_CH_2 */ case TIMER_CH_2: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)timer_ocnstate << 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 8U); break; default: break; @@ -1234,14 +1355,30 @@ void timer_channel_complementary_output_state_config(uint32_t timer_periph,uint1 } /*! - \brief configure TIMER input capture parameter + \brief initialize TIMER channel input parameter struct with a default value + \param[in] icpara: TIMER channel intput parameter struct + \param[out] none + \retval none +*/ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) +{ + /* initialize the channel input parameter struct member with the default value */ + icpara->icpolarity = TIMER_IC_POLARITY_RISING; + icpara->icselection = TIMER_IC_SELECTION_DIRECTTI; + icpara->icprescaler = TIMER_IC_PSC_DIV1; + icpara->icfilter = 0U; +} + +/*! + \brief configure TIMER input capture parameter \param[in] timer_periph: please refer to the following parameters - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] timer_icpara: TIMER channel intput parameter struct + \param[in] icpara: TIMER channel intput parameter struct icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING,TIMER_IC_POLARITY_BOTH_EDGE icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI,TIMER_IC_SELECTION_ITS icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 @@ -1249,9 +1386,9 @@ void timer_channel_complementary_output_state_config(uint32_t timer_periph,uint1 \param[out] none \retval none */ -void timer_input_capture_config(uint32_t timer_periph,uint16_t timer_channel,timer_ic_parameter_struct* timer_icpara) +void timer_input_capture_config(uint32_t timer_periph,uint16_t channel, timer_ic_parameter_struct* icpara) { - switch(timer_channel){ + switch(channel){ /* configure TIMER_CH_0 */ case TIMER_CH_0: /* reset the CH0EN bit */ @@ -1259,18 +1396,18 @@ void timer_input_capture_config(uint32_t timer_periph,uint16_t timer_channel,tim /* reset the CH0P and CH0NP bits */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)(timer_icpara->icpolarity); + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpara->icpolarity); /* reset the CH0MS bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); - TIMER_CHCTL0(timer_periph) |= (uint32_t)(timer_icpara->icselection); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpara->icselection); /* reset the CH0CAPFLT bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(timer_icpara->icfilter) << 4U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); /* set the CH0EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; break; - + /* configure TIMER_CH_1 */ case TIMER_CH_1: /* reset the CH1EN bit */ @@ -1278,13 +1415,13 @@ void timer_input_capture_config(uint32_t timer_periph,uint16_t timer_channel,tim /* reset the CH1P and CH1NP bits */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(timer_icpara->icpolarity)<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 4U); /* reset the CH1MS bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(timer_icpara->icselection)<< 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); /* reset the CH1CAPFLT bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(timer_icpara->icfilter)<< 12U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); /* set the CH1EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; @@ -1296,15 +1433,15 @@ void timer_input_capture_config(uint32_t timer_periph,uint16_t timer_channel,tim /* reset the CH2P and CH2NP bits */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH2P|TIMER_CHCTL2_CH2NP)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(timer_icpara->icpolarity)<< 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 8U); /* reset the CH2MS bit */ TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2MS); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(timer_icpara->icselection)); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection)); /* reset the CH2CAPFLT bit */ TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPFLT); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(timer_icpara->icfilter)<< 4U); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); /* set the CH2EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH2EN; @@ -1316,15 +1453,15 @@ void timer_input_capture_config(uint32_t timer_periph,uint16_t timer_channel,tim /* reset the CH3P bits */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH3P)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(timer_icpara->icpolarity)<< 12U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 12U); /* reset the CH3MS bit */ TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3MS); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(timer_icpara->icselection)<< 8U); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); /* reset the CH3CAPFLT bit */ TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPFLT); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(timer_icpara->icfilter)<< 12U); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); /* set the CH3EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH3EN; @@ -1333,18 +1470,20 @@ void timer_input_capture_config(uint32_t timer_periph,uint16_t timer_channel,tim break; } /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph,timer_channel,(uint16_t)(timer_icpara->icprescaler)); + timer_channel_input_capture_prescaler_config(timer_periph, channel, (uint16_t)(icpara->icprescaler)); } /*! \brief configure TIMER channel input capture prescaler value \param[in] timer_periph: please refer to the following parameters - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] timer_prescaler: channel input capture prescaler value + \param[in] prescaler: channel input capture prescaler value + only one parameter can be selected which is shown as below: \arg TIMER_IC_PSC_DIV1: no prescaler \arg TIMER_IC_PSC_DIV2: divided by 2 \arg TIMER_IC_PSC_DIV4: divided by 4 @@ -1352,28 +1491,28 @@ void timer_input_capture_config(uint32_t timer_periph,uint16_t timer_channel,tim \param[out] none \retval none */ -void timer_channel_input_capture_prescaler_config(uint32_t timer_periph,uint16_t timer_channel,uint16_t timer_prescaler) +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler) { - switch(timer_channel){ + switch(channel){ /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC); - TIMER_CHCTL0(timer_periph) |= (uint32_t)timer_prescaler; + TIMER_CHCTL0(timer_periph) |= (uint32_t)prescaler; break; /* configure TIMER_CH_1 */ case TIMER_CH_1: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPPSC); - TIMER_CHCTL0(timer_periph) |= ((uint32_t)timer_prescaler << 8U); + TIMER_CHCTL0(timer_periph) |= ((uint32_t)prescaler << 8U); break; /* configure TIMER_CH_2 */ case TIMER_CH_2: TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPPSC); - TIMER_CHCTL1(timer_periph) |= (uint32_t)timer_prescaler; + TIMER_CHCTL1(timer_periph) |= (uint32_t)prescaler; break; /* configure TIMER_CH_3 */ case TIMER_CH_3: TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPPSC); - TIMER_CHCTL1(timer_periph) |= ((uint32_t)timer_prescaler << 8U); + TIMER_CHCTL1(timer_periph) |= ((uint32_t)prescaler << 8U); break; default: break; @@ -1383,7 +1522,8 @@ void timer_channel_input_capture_prescaler_config(uint32_t timer_periph,uint16_t /*! \brief read TIMER channel capture compare register value \param[in] timer_periph: please refer to the following parameters - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) @@ -1391,20 +1531,24 @@ void timer_channel_input_capture_prescaler_config(uint32_t timer_periph,uint16_t \param[out] none \retval channel capture compare register value */ -uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph,uint16_t timer_channel) +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel) { uint32_t count_value = 0U; - switch(timer_channel){ + switch(channel){ + /* read TIMER channel 0 capture compare register value */ case TIMER_CH_0: count_value = TIMER_CH0CV(timer_periph); break; + /* read TIMER channel 1 capture compare register value */ case TIMER_CH_1: count_value = TIMER_CH1CV(timer_periph); break; + /* read TIMER channel 2 capture compare register value */ case TIMER_CH_2: count_value = TIMER_CH2CV(timer_periph); break; + /* read TIMER channel 3 capture compare register value */ case TIMER_CH_3: count_value = TIMER_CH3CV(timer_periph); break; @@ -1415,12 +1559,13 @@ uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph,uint16_ } /*! - \brief configure TIMER input pwm capture function + \brief configure TIMER input pwm capture function \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] timer_channel: + \param[in] channel: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0 \arg TIMER_CH_1: TIMER channel1 - \param[in] timer_icpwm:TIMER channel intput pwm parameter struct + \param[in] icpwm:TIMER channel intput pwm parameter struct icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 @@ -1428,80 +1573,82 @@ uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph,uint16_ \param[out] none \retval none */ -void timer_input_pwm_capture_config(uint32_t timer_periph,uint16_t timer_channel,timer_ic_parameter_struct* timer_icpwm) +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm) { uint16_t icpolarity = 0x0U; uint16_t icselection = 0x0U; - if(TIMER_IC_POLARITY_RISING == timer_icpwm->icpolarity){ + /* Set channel input polarity */ + if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){ icpolarity = TIMER_IC_POLARITY_FALLING; }else{ icpolarity = TIMER_IC_POLARITY_RISING; } - if(TIMER_IC_SELECTION_DIRECTTI == timer_icpwm->icselection){ + /* Set channel input mode selection */ + if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){ icselection = TIMER_IC_SELECTION_INDIRECTTI; }else{ icselection = TIMER_IC_SELECTION_DIRECTTI; } - if(TIMER_CH_0 == timer_channel){ + if(TIMER_CH_0 == channel){ /* reset the CH0EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); /* reset the CH0P and CH0NP bits */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); /* set the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)(timer_icpwm->icpolarity); + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpwm->icpolarity); /* reset the CH0MS bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); /* set the CH0MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)(timer_icpwm->icselection); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpwm->icselection); /* reset the CH0CAPFLT bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); /* set the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= ((uint32_t)(timer_icpwm->icfilter) << 4U); + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); /* set the CH0EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(timer_icpwm->icprescaler)); + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); /* reset the CH1EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); /* reset the CH1P and CH1NP bits */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); /* set the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity << 4U); /* reset the CH1MS bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection<< 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection << 8U); /* reset the CH1CAPFLT bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); /* set the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(timer_icpwm->icfilter)<< 12U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); /* set the CH1EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(timer_icpwm->icprescaler)); + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); }else{ /* reset the CH1EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); /* reset the CH1P and CH1NP bits */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); /* set the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(timer_icpwm->icpolarity)<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity) << 4U); /* reset the CH1MS bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(timer_icpwm->icselection)<< 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection) << 8U); /* reset the CH1CAPFLT bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); /* set the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(timer_icpwm->icfilter)<< 12U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); /* set the CH1EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(timer_icpwm->icprescaler)); + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_1, (uint16_t)(icpwm->icprescaler)); /* reset the CH0EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); @@ -1516,168 +1663,180 @@ void timer_input_pwm_capture_config(uint32_t timer_periph,uint16_t timer_channel /* reset the CH0CAPFLT bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); /* set the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= ((uint32_t)(timer_icpwm->icfilter) << 4U); + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); /* set the CH0EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(timer_icpwm->icprescaler)); + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_0, (uint16_t)(icpwm->icprescaler)); } } /*! \brief configure TIMER hall sensor mode \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] timer_hallmode: + \param[in] hallmode: + only one parameter can be selected which is shown as below: \arg TIMER_HALLINTERFACE_ENABLE: TIMER hall sensor mode enable \arg TIMER_HALLINTERFACE_DISABLE: TIMER hall sensor mode disable \param[out] none \retval none */ -void timer_hall_mode_config(uint32_t timer_periph,uint8_t timer_hallmode) +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) { - if(TIMER_HALLINTERFACE_ENABLE == timer_hallmode){ + if(TIMER_HALLINTERFACE_ENABLE == hallmode){ TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S; - }else if(TIMER_HALLINTERFACE_DISABLE == timer_hallmode){ + }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){ TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S; }else{ + /* illegal parameters */ } } /*! - \brief select TIMER input trigger source - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] timer_intrigger: - \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 - \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 - \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 - \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 - \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 Edge Detector - \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 - \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 - \arg TIMER_SMCFG_TRGSEL_ETIFP: external trigger + \brief select TIMER input trigger source + \param[in] timer_periph: please refer to the following parameters + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0(TIMERx(x=0..4,7,8,11)) + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2(TIMERx(x=0..4,7,8,11)) + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3(TIMERx(x=0..4,7,8,11)) + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector(TIMERx(x=0..4,7,8,11)) + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0(TIMERx(x=0..4,7,8,11)) + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_SMCFG_TRGSEL_ETIFP: external trigger(TIMERx(x=0..4,7,8,11)) \param[out] none \retval none */ -void timer_input_trigger_source_select(uint32_t timer_periph,uint32_t timer_intrigger) +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger) { TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS); - TIMER_SMCFG(timer_periph) |= (uint32_t)timer_intrigger; + TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger; } /*! - \brief select TIMER master mode output trigger source + \brief select TIMER master mode output trigger source \param[in] timer_periph: TIMERx(x=0..7) - \param[in] timer_outrigger: - \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output - \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output - \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output - \arg TIMER_TRI_OUT_SRC_CC0: a capture or a compare match occurred in channal0 as trigger output TRGO - \arg TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output - \arg TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output - \arg TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output - \arg TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output + \param[in] outrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output(TIMERx(x=0..7,9,10,12,13)) + \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output(TIMERx(x=0..7,9,10,12,13)) + \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output(TIMERx(x=0..7,9,10,12,13)) + \arg TIMER_TRI_OUT_SRC_CH0: a capture or a compare match occurred in channal0 as trigger output TRGO(TIMERx(x=0..4,7,9,10,12,13)) + \arg TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output(TIMERx(x=0..4,7,9,10,12,13)) + \arg TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output(TIMERx(x=0..4,7)) \param[out] none \retval none */ -void timer_master_output_trigger_source_select(uint32_t timer_periph,uint32_t timer_outrigger) +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger) { TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_MMC); - TIMER_CTL1(timer_periph) |= (uint32_t)timer_outrigger; + TIMER_CTL1(timer_periph) |= (uint32_t)outrigger; } /*! - \brief select TIMER slave mode + \brief select TIMER slave mode \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] timer_slavemode: - \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable - \arg TIMER_ENCODER_MODE0: encoder mode 0 - \arg TIMER_ENCODER_MODE1: encoder mode 1 - \arg TIMER_ENCODER_MODE2: encoder mode 2 - \arg TIMER_SLAVE_MODE_RESTART: restart mode - \arg TIMER_SLAVE_MODE_PAUSE: pause mode - \arg TIMER_SLAVE_MODE_EVENT: event mode - \arg TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0. + \param[in] slavemode: + only one parameter can be selected which is shown as below: + \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable(TIMERx(x=0..4,7,8,11)) + \arg TIMER_ENCODER_MODE0: encoder mode 0(TIMERx(x=0..4,7)) + \arg TIMER_ENCODER_MODE1: encoder mode 1(TIMERx(x=0..4,7)) + \arg TIMER_ENCODER_MODE2: encoder mode 2(TIMERx(x=0..4,7)) + \arg TIMER_SLAVE_MODE_RESTART: restart mode(TIMERx(x=0..4,7,8,11)) + \arg TIMER_SLAVE_MODE_PAUSE: pause mode(TIMERx(x=0..4,7,8,11)) + \arg TIMER_SLAVE_MODE_EVENT: event mode(TIMERx(x=0..4,7,8,11)) + \arg TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0.(TIMERx(x=0..4,7,8,11)) \param[out] none \retval none */ -void timer_slave_mode_select(uint32_t timer_periph,uint32_t timer_slavemode) +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) { TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); - TIMER_SMCFG(timer_periph) |= (uint32_t)timer_slavemode; + TIMER_SMCFG(timer_periph) |= (uint32_t)slavemode; } /*! - \brief configure TIMER master slave mode + \brief configure TIMER master slave mode \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] timer_masterslave: + \param[in] masterslave: + only one parameter can be selected which is shown as below: \arg TIMER_MASTER_SLAVE_MODE_ENABLE: master slave mode enable \arg TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable \param[out] none \retval none -*/ -void timer_master_slave_mode_config(uint32_t timer_periph,uint8_t timer_masterslave) +*/ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) { - if(TIMER_MASTER_SLAVE_MODE_ENABLE == timer_masterslave){ + if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){ TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM; - }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == timer_masterslave){ + }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){ TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM; }else{ + /* illegal parameters */ } } /*! \brief configure TIMER external trigger input \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] timer_extprescaler: + \param[in] extprescaler: + only one parameter can be selected which is shown as below: \arg TIMER_EXT_TRI_PSC_OFF: no divided \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 - \param[in] timer_expolarity: + \param[in] extpolarity: + only one parameter can be selected which is shown as below: \arg TIMER_ETP_FALLING: active low or falling edge active \arg TIMER_ETP_RISING: active high or rising edge active - \param[in] timer_extfilter: a value between 0 and 15 + \param[in] extfilter: a value between 0 and 15 \param[out] none \retval none */ -void timer_external_trigger_config(uint32_t timer_periph,uint32_t timer_extprescaler, - uint32_t timer_expolarity,uint32_t timer_extfilter) +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, + uint32_t extpolarity, uint32_t extfilter) { - TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP|TIMER_SMCFG_ETPSC|TIMER_SMCFG_ETFC)); - TIMER_SMCFG(timer_periph) |= (uint32_t)(timer_extprescaler|timer_expolarity); - TIMER_SMCFG(timer_periph) |= (uint32_t)(timer_extfilter<< 8U); + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC)); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extfilter << 8U); } /*! \brief configure TIMER quadrature decoder mode \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] timer_decomode: + \param[in] decomode: + only one parameter can be selected which is shown as below: \arg TIMER_ENCODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level \arg TIMER_ENCODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level \arg TIMER_ENCODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input - \param[in] timer_ic0polarity: + \param[in] ic0polarity: + only one parameter can be selected which is shown as below: \arg TIMER_IC_POLARITY_RISING: capture rising edge \arg TIMER_IC_POLARITY_FALLING: capture falling edge - \param[in] timer_ic1polarity: + \param[in] ic1polarity: + only one parameter can be selected which is shown as below: \arg TIMER_IC_POLARITY_RISING: capture rising edge \arg TIMER_IC_POLARITY_FALLING: capture falling edge \param[out] none \retval none */ -void timer_quadrature_decoder_mode_config(uint32_t timer_periph,uint32_t timer_decomode, - uint16_t timer_ic0polarity,uint16_t timer_ic1polarity) +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, + uint16_t ic0polarity, uint16_t ic1polarity) { TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); - TIMER_SMCFG(timer_periph) |= (uint32_t)timer_decomode; + TIMER_SMCFG(timer_periph) |= (uint32_t)decomode; TIMER_CHCTL0(timer_periph) &= (uint32_t)(((~(uint32_t)TIMER_CHCTL0_CH0MS))&((~(uint32_t)TIMER_CHCTL0_CH1MS))); - TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI|((uint32_t)TIMER_IC_SELECTION_DIRECTTI<< 8U)); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI|((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U)); TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); - TIMER_CHCTL2(timer_periph) |= ((uint32_t)timer_ic0polarity|((uint32_t)timer_ic1polarity<< 4U)); + TIMER_CHCTL2(timer_periph) |= ((uint32_t)ic0polarity|((uint32_t)ic1polarity << 4U)); } /*! @@ -1694,7 +1853,8 @@ void timer_internal_clock_config(uint32_t timer_periph) /*! \brief configure TIMER the internal trigger as external clock input \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] timer_intrigger: + \param[in] intrigger: + only one parameter can be selected which is shown as below: \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 @@ -1702,9 +1862,9 @@ void timer_internal_clock_config(uint32_t timer_periph) \param[out] none \retval none */ -void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t timer_intrigger) +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger) { - timer_input_trigger_source_select(timer_periph,timer_intrigger); + timer_input_trigger_source_select(timer_periph, intrigger); TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; } @@ -1712,35 +1872,37 @@ void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint /*! \brief configure TIMER the external trigger as external clock input \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] timer_extrigger: - \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 Edge Detector + \param[in] extrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 - \param[in] timer_expolarity: - \arg TIMER_IC_POLARITY_RISING: active low or falling edge active - \arg TIMER_IC_POLARITY_FALLING: active high or rising edge active - \param[in] timer_extfilter: a value between 0 and 15 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: active high or rising edge active + \arg TIMER_IC_POLARITY_FALLING: active low or falling edge active + \param[in] extfilter: a value between 0 and 15 \param[out] none \retval none */ -void timer_external_trigger_as_external_clock_config(uint32_t timer_periph,uint32_t timer_extrigger, - uint16_t timer_expolarity,uint32_t timer_extfilter) +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, + uint16_t extpolarity, uint32_t extfilter) { - if(TIMER_SMCFG_TRGSEL_CI1FE1 == timer_extrigger){ + if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){ /* reset the CH1EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); /* reset the CH1NP bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); /* set the CH1NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)timer_expolarity << 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U); /* reset the CH1MS bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI<< 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U); /* reset the CH1CAPFLT bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); /* set the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)(timer_extfilter<< 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U); /* set the CH1EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; }else{ @@ -1749,7 +1911,7 @@ void timer_external_trigger_as_external_clock_config(uint32_t timer_periph,uint3 /* reset the CH0P and CH0NP bits */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); /* set the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)timer_expolarity; + TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity; /* reset the CH0MS bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); /* set the CH0MS bit */ @@ -1757,12 +1919,12 @@ void timer_external_trigger_as_external_clock_config(uint32_t timer_periph,uint3 /* reset the CH0CAPFLT bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); /* reset the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)timer_extfilter; + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 4U); /* set the CH0EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; } /* select TIMER input trigger source */ - timer_input_trigger_source_select(timer_periph,timer_extrigger); + timer_input_trigger_source_select(timer_periph,extrigger); /* reset the SMC bit */ TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); /* set the SMC bit */ @@ -1772,23 +1934,25 @@ void timer_external_trigger_as_external_clock_config(uint32_t timer_periph,uint3 /*! \brief configure TIMER the external clock mode0 \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] timer_extprescaler: + \param[in] extprescaler: + only one parameter can be selected which is shown as below: \arg TIMER_EXT_TRI_PSC_OFF: no divided \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 - \param[in] timer_expolarity: + \param[in] extpolarity: + only one parameter can be selected which is shown as below: \arg TIMER_ETP_FALLING: active low or falling edge active \arg TIMER_ETP_RISING: active high or rising edge active - \param[in] timer_extfilter: a value between 0 and 15 + \param[in] extfilter: a value between 0 and 15 \param[out] none \retval none */ -void timer_external_clock_mode0_config(uint32_t timer_periph,uint32_t timer_extprescaler, - uint32_t timer_expolarity,uint32_t timer_extfilter) +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, + uint32_t extpolarity, uint32_t extfilter) { /* configure TIMER external trigger input */ - timer_external_trigger_config(timer_periph,timer_extprescaler,timer_expolarity,timer_extfilter); + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); /* reset the SMC bit,TRGS bit */ TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); @@ -1799,23 +1963,25 @@ void timer_external_clock_mode0_config(uint32_t timer_periph,uint32_t timer_extp /*! \brief configure TIMER the external clock mode1 \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] timer_extprescaler: + \param[in] extprescaler: + only one parameter can be selected which is shown as below: \arg TIMER_EXT_TRI_PSC_OFF: no divided \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 - \param[in] timer_expolarity: + \param[in] extpolarity: + only one parameter can be selected which is shown as below: \arg TIMER_ETP_FALLING: active low or falling edge active \arg TIMER_ETP_RISING: active high or rising edge active - \param[in] timer_extfilter: a value between 0 and 15 + \param[in] extfilter: a value between 0 and 15 \param[out] none \retval none */ -void timer_external_clock_mode1_config(uint32_t timer_periph,uint32_t timer_extprescaler, - uint32_t timer_expolarity,uint32_t timer_extfilter) +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, + uint32_t extpolarity, uint32_t extfilter) { /* configure TIMER external trigger input */ - timer_external_trigger_config(timer_periph,timer_extprescaler,timer_expolarity,timer_extfilter); + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_SMC1; } @@ -1832,9 +1998,10 @@ void timer_external_clock_mode1_disable(uint32_t timer_periph) } /*! - \brief configure TIMER1 channel0 remap function + \brief configure TIMER channel remap function \param[in] timer_periph: TIMERx(x=1,4,10) - \param[in] timer_remap: + \param[in] remap: + only one parameter can be selected which is shown as below: \arg TIMER1_ITI1_RMP_TIMER7_TRGO: timer1 internal trigger input1 remap to TIMER7_TRGO \arg TIMER1_ITI1_RMP_ETHERNET_PTP: timer1 internal trigger input1 remap to ethernet PTP \arg TIMER1_ITI1_RMP_USB_FS_SOF: timer1 internal trigger input1 remap to USB FS SOF @@ -1842,51 +2009,55 @@ void timer_external_clock_mode1_disable(uint32_t timer_periph) \arg TIMER4_CI3_RMP_GPIO: timer4 channel 3 input remap to GPIO pin \arg TIMER4_CI3_RMP_IRC32K: timer4 channel 3 input remap to IRC32K \arg TIMER4_CI3_RMP_LXTAL: timer4 channel 3 input remap to LXTAL - \arg TIMER4_CI3_RMP_RTC_WAKEUP_INT: timer4 channel 3 input remap to RTC wakeup interrupt + \arg TIMER4_CI3_RMP_RTC_WAKEUP_INT: timer4 channel 3 input remap to RTC wakeup interrupt \arg TIMER10_ITI1_RMP_GPIO: timer10 internal trigger input1 remap based on GPIO setting \arg TIMER10_ITI1_RMP_RTC_HXTAL_DIV: timer10 internal trigger input1 remap HXTAL _DIV(clock used for RTC which is HXTAL clock divided by RTCDIV bits in RCU_CFG0 register) \param[out] none \retval none */ -void timer_channel_remap_config(uint32_t timer_periph,uint32_t timer_remap) +void timer_channel_remap_config(uint32_t timer_periph, uint32_t remap) { - TIMER_IRMP(timer_periph) = (uint32_t)timer_remap; + TIMER_IRMP(timer_periph) = (uint32_t)remap; } /*! \brief configure TIMER write CHxVAL register selection \param[in] timer_periph: TIMERx(x=0,1,2,13,14,15,16) - \param[in] timer_ccsel: - \arg TIMER_CCSEL_DISABLE: no effect - \arg TIMER_CCSEL_ENABLE: if write the CHxVAL register, the write value is same as the CHxVAL value, the write access ignored + \param[in] ccsel: + only one parameter can be selected which is shown as below: + \arg TIMER_CHVSEL_DISABLE: no effect + \arg TIMER_CHVSEL_ENABLE: when write the CHxVAL register, if the write value is same as the CHxVAL value, the write access is ignored \param[out] none \retval none */ -void timer_write_cc_register_config(uint32_t timer_periph, uint16_t timer_ccsel) +void timer_write_chxval_register_config(uint32_t timer_periph, uint16_t ccsel) { - if(TIMER_CCSEL_ENABLE == timer_ccsel){ + if(TIMER_CHVSEL_ENABLE == ccsel){ TIMER_CFG(timer_periph) |= (uint32_t)TIMER_CFG_CHVSEL; - }else if(TIMER_CCSEL_DISABLE == timer_ccsel){ + }else if(TIMER_CHVSEL_DISABLE == ccsel){ TIMER_CFG(timer_periph) &= ~(uint32_t)TIMER_CFG_CHVSEL; }else{ + /* illegal parameters */ } } /*! \brief configure TIMER output value selection \param[in] timer_periph: TIMERx(x=0,7) - \param[in] timer_outsel: + \param[in] outsel: + only one parameter can be selected which is shown as below: \arg TIMER_OUTSEL_DISABLE: no effect \arg TIMER_OUTSEL_ENABLE: if POEN and IOS is 0, the output disabled \param[out] none \retval none */ -void timer_output_value_selection_config(uint32_t timer_periph, uint16_t timer_outsel) +void timer_output_value_selection_config(uint32_t timer_periph, uint16_t outsel) { - if(TIMER_OUTSEL_ENABLE == timer_outsel){ + if(TIMER_OUTSEL_ENABLE == outsel){ TIMER_CFG(timer_periph) |= (uint32_t)TIMER_CFG_OUTSEL; - }else if(TIMER_OUTSEL_DISABLE == timer_outsel){ + }else if(TIMER_OUTSEL_DISABLE == outsel){ TIMER_CFG(timer_periph) &= ~(uint32_t)TIMER_CFG_OUTSEL; }else{ + /* illegal parameters */ } } diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c index dfa65744ba..9d719bb29b 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c @@ -1,18 +1,46 @@ /*! - \file gd32f4xx_tli.c - \brief TLI driver + \file gd32f4xx_tli.c + \brief TLI driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.1, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_tli.h" +#define TLI_DEFAULT_VALUE 0x00000000U +#define TLI_OPAQUE_VALUE 0x000000FFU + /*! - \brief deinitialize TLI registers + \brief deinitialize TLI registers \param[in] none \param[out] none \retval none @@ -24,15 +52,57 @@ void tli_deinit(void) } /*! - \brief initialize TLI display timing parameters - \param[in] tli_struct: the data needed to initialize tli. + \brief initialize the parameters of TLI parameter structure with the default values, it is suggested + that call this function after a tli_parameter_struct structure is defined + \param[in] none + \param[out] tli_struct: the data needed to initialize TLI synpsz_vpsz: size of the vertical synchronous pulse synpsz_hpsz: size of the horizontal synchronous pulse - backpsz_vbpsz: size of the vertical back porch plus synchronous pulse + backpsz_vbpsz: size of the vertical back porch plus synchronous pulse backpsz_hbpsz: size of the horizontal back porch plus synchronous pulse activesz_vasz: size of the vertical active area width plus back porch and synchronous pulse activesz_hasz: size of the horizontal active area width plus back porch and synchronous pulse - totalsz_vtsz: vertical total size of the display, including active area, back porch, synchronous + totalsz_vtsz: vertical total size of the display, including active area, back porch, synchronous + totalsz_htsz: vorizontal total size of the display, including active area, back porch, synchronous + backcolor_red: background value red + backcolor_green: background value green + backcolor_blue: background value blue + signalpolarity_hs: TLI_HSYN_ACTLIVE_LOW,TLI_HSYN_ACTLIVE_HIGHT + signalpolarity_vs: TLI_VSYN_ACTLIVE_LOW,TLI_VSYN_ACTLIVE_HIGHT + signalpolarity_de: TLI_DE_ACTLIVE_LOW,TLI_DE_ACTLIVE_HIGHT + signalpolarity_pixelck: TLI_PIXEL_CLOCK_TLI,TLI_PIXEL_CLOCK_INVERTEDTLI + \retval none +*/ +void tli_struct_para_init(tli_parameter_struct *tli_struct) +{ + /* initialize the struct parameters with default values */ + tli_struct->synpsz_vpsz = TLI_DEFAULT_VALUE; + tli_struct->synpsz_hpsz = TLI_DEFAULT_VALUE; + tli_struct->backpsz_vbpsz = TLI_DEFAULT_VALUE; + tli_struct->backpsz_hbpsz = TLI_DEFAULT_VALUE; + tli_struct->activesz_vasz = TLI_DEFAULT_VALUE; + tli_struct->activesz_hasz = TLI_DEFAULT_VALUE; + tli_struct->totalsz_vtsz = TLI_DEFAULT_VALUE; + tli_struct->totalsz_htsz = TLI_DEFAULT_VALUE; + tli_struct->backcolor_red = TLI_DEFAULT_VALUE; + tli_struct->backcolor_green = TLI_DEFAULT_VALUE; + tli_struct->backcolor_blue = TLI_DEFAULT_VALUE; + tli_struct->signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW; + tli_struct->signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW; + tli_struct->signalpolarity_de = TLI_DE_ACTLIVE_LOW; + tli_struct->signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI; +} + +/*! + \brief initialize TLI display timing parameters + \param[in] tli_struct: the data needed to initialize TLI + synpsz_vpsz: size of the vertical synchronous pulse + synpsz_hpsz: size of the horizontal synchronous pulse + backpsz_vbpsz: size of the vertical back porch plus synchronous pulse + backpsz_hbpsz: size of the horizontal back porch plus synchronous pulse + activesz_vasz: size of the vertical active area width plus back porch and synchronous pulse + activesz_hasz: size of the horizontal active area width plus back porch and synchronous pulse + totalsz_vtsz: vertical total size of the display, including active area, back porch, synchronous totalsz_htsz: vorizontal total size of the display, including active area, back porch, synchronous backcolor_red: background value red backcolor_green: background value green @@ -48,19 +118,19 @@ void tli_init(tli_parameter_struct *tli_struct) { /* synchronous pulse size configuration */ TLI_SPSZ &= ~(TLI_SPSZ_VPSZ|TLI_SPSZ_HPSZ); - TLI_SPSZ = (tli_struct->synpsz_vpsz|(tli_struct->synpsz_hpsz<<16U)); + TLI_SPSZ = (uint32_t)((uint32_t)tli_struct->synpsz_vpsz|((uint32_t)tli_struct->synpsz_hpsz<<16U)); /* back-porch size configuration */ TLI_BPSZ &= ~(TLI_BPSZ_VBPSZ|TLI_BPSZ_HBPSZ); - TLI_BPSZ = (tli_struct->backpsz_vbpsz|(tli_struct->backpsz_hbpsz<<16U)); - /* active size configuration */ + TLI_BPSZ = (uint32_t)((uint32_t)tli_struct->backpsz_vbpsz|((uint32_t)tli_struct->backpsz_hbpsz<<16U)); + /* active size configuration */ TLI_ASZ &= ~(TLI_ASZ_VASZ|TLI_ASZ_HASZ); TLI_ASZ = (tli_struct->activesz_vasz|(tli_struct->activesz_hasz<<16U)); - /* total size configuration */ + /* total size configuration */ TLI_TSZ &= ~(TLI_TSZ_VTSZ|TLI_TSZ_HTSZ); TLI_TSZ = (tli_struct->totalsz_vtsz|(tli_struct->totalsz_htsz<<16U)); - /* background color configuration */ + /* background color configuration */ TLI_BGC &= ~(TLI_BGC_BVB|(TLI_BGC_BVG)|(TLI_BGC_BVR)); - TLI_BGC = (tli_struct->backcolor_blue|(tli_struct->backcolor_green<<8U)|(tli_struct->backcolor_red<<16U)); + TLI_BGC = (tli_struct->backcolor_blue|(tli_struct->backcolor_green<<8U)|(tli_struct->backcolor_red<<16U)); TLI_CTL &= ~(TLI_CTL_HPPS|TLI_CTL_VPPS|TLI_CTL_DEPS|TLI_CTL_CLKPS); TLI_CTL |= (tli_struct->signalpolarity_hs|tli_struct->signalpolarity_vs|\ tli_struct->signalpolarity_de|tli_struct->signalpolarity_pixelck); @@ -68,14 +138,17 @@ void tli_init(tli_parameter_struct *tli_struct) } /*! - \brief dither function configure - \param[in] ditherstat: TLI_DITHER_ENABLE,TLI_DITHER_DISABLE + \brief configure TLI dither function + \param[in] dither_stat + only one parameter can be selected which is shown as below: + \arg TLI_DITHER_ENABLE + \arg TLI_DITHER_DISABLE \param[out] none \retval none */ -void tli_dither_config(uint8_t ditherstat) +void tli_dither_config(uint8_t dither_stat) { - if(TLI_DITHER_ENABLE == ditherstat){ + if(TLI_DITHER_ENABLE == dither_stat){ TLI_CTL |= TLI_CTL_DFEN; }else{ TLI_CTL &= ~(TLI_CTL_DFEN); @@ -83,8 +156,8 @@ void tli_dither_config(uint8_t ditherstat) } /*! - \brief TLI enable - \param[in] none. + \brief enable TLI + \param[in] none \param[out] none \retval none */ @@ -94,215 +167,89 @@ void tli_enable(void) } /*! - \brief TLI disable - \param[in] none. + \brief disable TLI + \param[in] none \param[out] none \retval none */ void tli_disable(void) { - TLI_CTL &= ~(TLI_CTL_DFEN); + TLI_CTL &= ~(TLI_CTL_TLIEN); } /*! - \brief TLI reload layer configure - \param[in] reloadmod: TLI_FRAME_BLANK_RELOAD_EN,TLI_REQUEST_RELOAD_EN + \brief configure TLI reload mode + \param[in] reload_mod + only one parameter can be selected which is shown as below: + \arg TLI_FRAME_BLANK_RELOAD_EN + \arg TLI_REQUEST_RELOAD_EN \param[out] none \retval none */ -void tli_reload_config(uint8_t reloadmod) +void tli_reload_config(uint8_t reload_mod) { - if(TLI_FRAME_BLANK_RELOAD_EN == reloadmod){ + if(TLI_FRAME_BLANK_RELOAD_EN == reload_mod){ + /* the layer configuration will be reloaded at frame blank */ TLI_RL |= TLI_RL_FBR; }else{ + /* the layer configuration will be reloaded after this bit sets */ TLI_RL |= TLI_RL_RQR; } } /*! - \brief TLI interrupt enable - \param[in] inttype: TLI interrupt bits. - \arg TLI_INTEN_LMIE: line mark interrupt - \arg TLI_INTEN_FEIE: FIFO error interrupt - \arg TLI_INTEN_TEIE: transaction error interrupt - \arg TLI_INTEN_LCRIE: layer configuration reloaded interrupt - \param[out] none + \brief initialize the parameters of TLI layer structure with the default values, it is suggested + that call this function after a tli_layer_parameter_struct structure is defined + \param[in] none + \param[out] layer_struct: TLI Layer parameter struct + layer_window_rightpos: window right position + layer_window_leftpos: window left position + layer_window_bottompos: window bottom position + layer_window_toppos: window top position + layer_ppf: LAYER_PPF_ARGB8888,LAYER_PPF_RGB888,LAYER_PPF_RGB565, + LAYER_PPF_ARG1555,LAYER_PPF_ARGB4444,LAYER_PPF_L8, + LAYER_PPF_AL44,LAYER_PPF_AL88 + layer_sa: specified alpha + layer_default_alpha: the default color alpha + layer_default_red: the default color red + layer_default_green: the default color green + layer_default_blue: the default color blue + layer_acf1: LAYER_ACF1_SA,LAYER_ACF1_PASA + layer_acf2: LAYER_ACF2_SA,LAYER_ACF2_PASA + layer_frame_bufaddr: frame buffer base address + layer_frame_buf_stride_offset: frame buffer stride offset + layer_frame_line_length: frame line length + layer_frame_total_line_number: frame total line number \retval none */ -void tli_interrupt_enable(uint32_t inttype) +void tli_layer_struct_para_init(tli_layer_parameter_struct *layer_struct) { - TLI_INTEN |= (inttype); + /* initialize the struct parameters with default values */ + layer_struct->layer_window_rightpos = TLI_DEFAULT_VALUE; + layer_struct->layer_window_leftpos = TLI_DEFAULT_VALUE; + layer_struct->layer_window_bottompos = TLI_DEFAULT_VALUE; + layer_struct->layer_window_toppos = TLI_DEFAULT_VALUE; + layer_struct->layer_ppf = LAYER_PPF_ARGB8888; + layer_struct->layer_sa = TLI_OPAQUE_VALUE; + layer_struct->layer_default_alpha = TLI_DEFAULT_VALUE; + layer_struct->layer_default_red = TLI_DEFAULT_VALUE; + layer_struct->layer_default_green = TLI_DEFAULT_VALUE; + layer_struct->layer_default_blue = TLI_DEFAULT_VALUE; + layer_struct->layer_acf1 = LAYER_ACF1_PASA; + layer_struct->layer_acf2 = LAYER_ACF2_PASA; + layer_struct->layer_frame_bufaddr = TLI_DEFAULT_VALUE; + layer_struct->layer_frame_buf_stride_offset = TLI_DEFAULT_VALUE; + layer_struct->layer_frame_line_length = TLI_DEFAULT_VALUE; + layer_struct->layer_frame_total_line_number = TLI_DEFAULT_VALUE; } /*! - \brief TLI interrupt disable - \param[in] inttype: TLI interrupt bits. - \arg TLI_INTEN_LMIE: line mark interrupt - \arg TLI_INTEN_FEIE: FIFO error interrupt - \arg TLI_INTEN_TEIE: transaction error interrupt - \arg TLI_INTEN_LCRIE: layer configuration reloaded interrupt - \param[out] none - \retval none -*/ -void tli_interrupt_disable(uint32_t inttype) -{ - TLI_INTEN &= ~(inttype); -} - -/*! - \brief get TLI interrupt flag - \param[in] intflag: TLI interrupt flag bits. - \arg TLI_INTF_LMF: line mark flag - \arg TLI_INTF_FEF: FIFO error flag - \arg TLI_INTF_TEF: transaction error flag - \arg TLI_INTF_LCRF: layer configuration reloaded flag - \param[out] none - \retval none -*/ -FlagStatus tli_interrupt_flag_get(uint32_t intflag) -{ - uint32_t state; - state = TLI_INTF; - if(state & intflag){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear TLI interrupt flag - \param[in] intflag: TLI interrupt flag bits. - \arg TLI_INTC_LMC: line mark flag - \arg TLI_INTC_FEC: FIFO error flag - \arg TLI_INTC_TEC: transaction error flag - \arg TLI_INTC_LCRC: layer configuration reloaded flag - \param[out] none - \retval none -*/ -void tli_interrupt_flag_clear(uint32_t intflag) -{ - TLI_INTC |= (intflag); -} - -/*! - \brief set line mark value - \param[in] linenum: line number. - \param[out] none - \retval none -*/ -void tli_line_mark_set(uint32_t linenum) -{ - TLI_LM &= ~(TLI_LM_LM); - TLI_LM = linenum; -} - -/*! - \brief get current displayed position - \param[in] none - \param[out] none - \retval none -*/ -uint32_t tli_current_pos_get(void) -{ - return TLI_CPPOS; -} - - -/*! - \brief get TLI state - \param[in] state: TLI state. - \arg TLI_STAT_VDE: current VDE state - \arg TLI_STAT_HDE: current HDE state - \arg TLI_STAT_VS: current vs state - \arg TLI_STAT_HS: current hs state - \param[out] none - \retval none -*/ -FlagStatus tli_flag_get(uint32_t state) -{ - uint32_t stat; - stat = TLI_STAT; - if(state & stat){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief TLI layer enable - \param[in] layerx: LAYERx(x=0,1). - \param[out] none - \retval none -*/ -void tli_layer_enable(uint32_t layerx) -{ - TLI_LxCTL(layerx) |= TLI_LxCTL_LEN; -} - -/*! - \brief TLI layer disable - \param[in] layerx: LAYERx(x=0,1). - \param[out] none - \retval none -*/ -void tli_layer_disable(uint32_t layerx) -{ - TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LEN); -} - -/*! - \brief TLI layer color keying enable - \param[in] layerx: LAYERx(x=0,1). - \param[out] none - \retval none -*/ -void tli_color_key_enable(uint32_t layerx) -{ - TLI_LxCTL(layerx) |= TLI_LxCTL_CKEYEN; -} - -/*! - \brief TLI layer color keying disable - \param[in] layerx: LAYERx(x=0,1). - \param[out] none - \retval none -*/ -void tli_color_key_disable(uint32_t layerx) -{ - TLI_LxCTL(layerx) &= ~(TLI_LxCTL_CKEYEN); -} - -/*! - \brief TLI layer LUT enable - \param[in] layerx: LAYERx(x=0,1). - \param[out] none - \retval none -*/ -void tli_lut_enable(uint32_t layerx) -{ - TLI_LxCTL(layerx) |= TLI_LxCTL_LUTEN; -} - -/*! - \brief TLI layer LUT disable - \param[in] layerx: LAYERx(x=0,1). - \param[out] none - \retval none -*/ -void tli_lut_disable(uint32_t layerx) -{ - TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LUTEN); -} - -/*! - \brief TLI layer initialize + \brief initialize TLI layer \param[in] layerx: LAYERx(x=0,1) \param[in] layer_struct: TLI Layer parameter struct layer_window_rightpos: window right position layer_window_leftpos: window left position - layer_window_bottompos: window bottom position + layer_window_bottompos: window bottom position layer_window_toppos: window top position layer_ppf: LAYER_PPF_ARGB8888,LAYER_PPF_RGB888,LAYER_PPF_RGB565, LAYER_PPF_ARG1555,LAYER_PPF_ARGB4444,LAYER_PPF_L8, @@ -325,10 +272,10 @@ void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct) { /* configure layer window horizontal position */ TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP|(TLI_LxHPOS_WRP)); - TLI_LxHPOS(layerx) = (layer_struct->layer_window_leftpos | (layer_struct->layer_window_rightpos<<16U)); + TLI_LxHPOS(layerx) = (uint32_t)((uint32_t)layer_struct->layer_window_leftpos|((uint32_t)layer_struct->layer_window_rightpos<<16U)); /* configure layer window vertical position */ TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP|(TLI_LxVPOS_WBP)); - TLI_LxVPOS(layerx) = (layer_struct->layer_window_toppos |(layer_struct->layer_window_bottompos<<16U)); + TLI_LxVPOS(layerx) = (uint32_t)((uint32_t)layer_struct->layer_window_toppos|((uint32_t)layer_struct->layer_window_bottompos<<16U)); /* configure layer packeted pixel format */ TLI_LxPPF(layerx) &= ~(TLI_LxPPF_PPF); TLI_LxPPF(layerx) = layer_struct->layer_ppf; @@ -337,9 +284,9 @@ void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct) TLI_LxSA(layerx) = layer_struct->layer_sa; /* configure layer default color */ TLI_LxDC(layerx) &= ~(TLI_LxDC_DCB|(TLI_LxDC_DCG)|(TLI_LxDC_DCR)|(TLI_LxDC_DCA)); - TLI_LxDC(layerx) = (layer_struct->layer_default_blue |(layer_struct->layer_default_green<<8U) - |(layer_struct->layer_default_red<<16U) - |(layer_struct->layer_default_alpha<<24U)); + TLI_LxDC(layerx) = (uint32_t)((uint32_t)layer_struct->layer_default_blue|((uint32_t)layer_struct->layer_default_green<<8U) + |((uint32_t)layer_struct->layer_default_red<<16U) + |((uint32_t)layer_struct->layer_default_alpha<<24U)); /* configure layer alpha calculation factors */ TLI_LxBLEND(layerx) &= ~(TLI_LxBLEND_ACF2|(TLI_LxBLEND_ACF1)); @@ -349,54 +296,52 @@ void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct) TLI_LxFBADDR(layerx) = (layer_struct->layer_frame_bufaddr); /* configure layer frame line length */ TLI_LxFLLEN(layerx) &= ~(TLI_LxFLLEN_FLL|(TLI_LxFLLEN_STDOFF)); - TLI_LxFLLEN(layerx) = (layer_struct->layer_frame_line_length|(layer_struct->layer_frame_buf_stride_offset<<16U)); - /* configure layer frame buffer base address */ - TLI_LxFBADDR(layerx) &= ~(TLI_LxFBADDR_FBADD); - TLI_LxFBADDR(layerx) = (layer_struct->layer_frame_bufaddr); + TLI_LxFLLEN(layerx) = (uint32_t)((uint32_t)layer_struct->layer_frame_line_length|((uint32_t)layer_struct->layer_frame_buf_stride_offset<<16U)); /* configure layer frame total line number */ - TLI_LxFTLN(layerx) &= ~(TLI_LxFTLN_FTLN); - TLI_LxFTLN(layerx) = (layer_struct->layer_frame_total_line_number); + TLI_LxFTLN(layerx) &= ~(TLI_LxFTLN_FTLN); + TLI_LxFTLN(layerx) = (uint32_t)(layer_struct->layer_frame_total_line_number); } /*! - \brief reconfigure window position - \param[in] layerx: LAYERx(x=0,1). - \param[in] offset_x: new horizontal offset . - \param[in] offset_y: new vertical offset. + \brief reconfigure window position + \param[in] layerx: LAYERx(x=0,1) + \param[in] offset_x: new horizontal offset + \param[in] offset_y: new vertical offset \param[out] none \retval none */ -void tli_layer_window_offset_modify(uint32_t layerx,uint32_t offset_x,uint32_t offset_y) +void tli_layer_window_offset_modify(uint32_t layerx,uint16_t offset_x,uint16_t offset_y) { /* configure window start position */ - uint32_t layer_ppf,line_length,line_num,hstart,vstart; + uint32_t layer_ppf, line_num, hstart, vstart; + uint32_t line_length = 0U; TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP|(TLI_LxHPOS_WRP)); TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP|(TLI_LxVPOS_WBP)); - hstart = offset_x+(((TLI_BPSZ & TLI_BPSZ_HBPSZ)>>16U)+1U); - vstart = offset_y+((TLI_BPSZ & TLI_BPSZ_VBPSZ)+1U); + hstart = (uint32_t)offset_x+(((TLI_BPSZ & TLI_BPSZ_HBPSZ)>>16U)+1U); + vstart = (uint32_t)offset_y+((TLI_BPSZ & TLI_BPSZ_VBPSZ)+1U); line_num = (TLI_LxFTLN(layerx) & TLI_LxFTLN_FTLN); layer_ppf = (TLI_LxPPF(layerx) & TLI_LxPPF_PPF); /* the bytes of a line equal TLI_LxFLLEN_FLL bits value minus 3 */ switch(layer_ppf){ case LAYER_PPF_ARGB8888: - /* each pixel includes 4bytes,when pixel format is ARGB8888 */ + /* each pixel includes 4bytes, when pixel format is ARGB8888 */ line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/4U); break; case LAYER_PPF_RGB888: - /* each pixel includes 3bytes,when pixel format is RGB888 */ + /* each pixel includes 3bytes, when pixel format is RGB888 */ line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/3U); break; case LAYER_PPF_RGB565: case LAYER_PPF_ARGB1555: case LAYER_PPF_ARGB4444: case LAYER_PPF_AL88: - /* each pixel includes 2bytes,when pixel format is RGB565,ARG1555,ARGB4444 or AL88 */ + /* each pixel includes 2bytes, when pixel format is RGB565,ARG1555,ARGB4444 or AL88 */ line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/2U); break; case LAYER_PPF_L8: case LAYER_PPF_AL44: - /* each pixel includes 1byte,when pixel format is L8 or AL44 */ + /* each pixel includes 1byte, when pixel format is L8 or AL44 */ line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)); break; default: @@ -405,39 +350,249 @@ void tli_layer_window_offset_modify(uint32_t layerx,uint32_t offset_x,uint32_t o /* reconfigure window position */ TLI_LxHPOS(layerx) = (hstart|((hstart+line_length-1U)<<16U)); TLI_LxVPOS(layerx) = (vstart|((vstart+line_num-1U)<<16U)); - - } /*! - \brief TLI layer lut initialize + \brief initialize the parameters of TLI layer LUT structure with the default values, it is suggested + that call this function after a tli_layer_lut_parameter_struct structure is defined + \param[in] none + \param[out] lut_struct: TLI layer LUT parameter struct + layer_table_addr: look up table write address + layer_lut_channel_red: red channel of a LUT entry + layer_lut_channel_green: green channel of a LUT entry + layer_lut_channel_blue: blue channel of a LUT entry + \retval none +*/ +void tli_lut_struct_para_init(tli_layer_lut_parameter_struct *lut_struct) +{ + /* initialize the struct parameters with default values */ + lut_struct->layer_table_addr = TLI_DEFAULT_VALUE; + lut_struct->layer_lut_channel_red = TLI_DEFAULT_VALUE; + lut_struct->layer_lut_channel_green = TLI_DEFAULT_VALUE; + lut_struct->layer_lut_channel_blue = TLI_DEFAULT_VALUE; +} + +/*! + \brief initialize TLI layer LUT \param[in] layerx: LAYERx(x=0,1) \param[in] lut_struct: TLI layer LUT parameter struct - layer_table_addr: window right position - layer_lut_channel_red: window left position - layer_window_bottompos: window bottom position - layer_window_toppos: window top position + layer_table_addr: look up table write address + layer_lut_channel_red: red channel of a LUT entry + layer_lut_channel_green: green channel of a LUT entry + layer_lut_channel_blue: blue channel of a LUT entry \param[out] none \retval none */ void tli_lut_init(uint32_t layerx,tli_layer_lut_parameter_struct *lut_struct) { TLI_LxLUT(layerx) &= ~(TLI_LxLUT_TB|TLI_LxLUT_TG|TLI_LxLUT_TR|TLI_LxLUT_TADD); - TLI_LxLUT(layerx) = ((lut_struct->layer_lut_channel_blue)|(lut_struct->layer_lut_channel_green<<8) - |(lut_struct->layer_lut_channel_red<<16 - |(lut_struct->layer_table_addr<<24))); + TLI_LxLUT(layerx) = (uint32_t)(((uint32_t)lut_struct->layer_lut_channel_blue)|((uint32_t)lut_struct->layer_lut_channel_green<<8U) + |((uint32_t)lut_struct->layer_lut_channel_red<<16U + |((uint32_t)lut_struct->layer_table_addr<<24U))); } /*! - \brief TLI layer key initialize - \param[in] layerx: LAYERx(x=0,1). - \param[in] redkey: color key red. - \param[in] greenkey: color key green - \param[in] bluekey: color key blue. + \brief initialize TLI layer color key + \param[in] layerx: LAYERx(x=0,1) + \param[in] redkey: color key red + \param[in] greenkey: color key green + \param[in] bluekey: color key blue \param[out] none \retval none */ -void tli_ckey_init(uint32_t layerx,uint32_t redkey,uint32_t greenkey,uint32_t bluekey) +void tli_color_key_init(uint32_t layerx,uint8_t redkey,uint8_t greenkey,uint8_t bluekey) { - TLI_LxCKEY(layerx) = ((bluekey)|(greenkey<<8U)|(redkey<<16U)); + TLI_LxCKEY(layerx) = (((uint32_t)bluekey)|((uint32_t)greenkey<<8U)|((uint32_t)redkey<<16U)); +} + +/*! + \brief enable TLI layer + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_layer_enable(uint32_t layerx) +{ + TLI_LxCTL(layerx) |= TLI_LxCTL_LEN; +} + +/*! + \brief disable TLI layer + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_layer_disable(uint32_t layerx) +{ + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LEN); +} + +/*! + \brief enable TLI layer color keying + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_color_key_enable(uint32_t layerx) +{ + TLI_LxCTL(layerx) |= TLI_LxCTL_CKEYEN; +} + +/*! + \brief disable TLI layer color keying + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_color_key_disable(uint32_t layerx) +{ + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_CKEYEN); +} + +/*! + \brief enable TLI layer LUT + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_lut_enable(uint32_t layerx) +{ + TLI_LxCTL(layerx) |= TLI_LxCTL_LUTEN; +} + +/*! + \brief disable TLI layer LUT + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_lut_disable(uint32_t layerx) +{ + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LUTEN); +} + +/*! + \brief set line mark value + \param[in] line_num: line number + \param[out] none + \retval none +*/ +void tli_line_mark_set(uint16_t line_num) +{ + TLI_LM &= ~(TLI_LM_LM); + TLI_LM = (uint32_t)line_num; +} + +/*! + \brief get current displayed position + \param[in] none + \param[out] none + \retval position of current pixel +*/ +uint32_t tli_current_pos_get(void) +{ + return TLI_CPPOS; +} + +/*! + \brief enable TLI interrupt + \param[in] int_flag: TLI interrupt flags + one or more parameters can be selected which are shown as below: + \arg TLI_INT_LM: line mark interrupt + \arg TLI_INT_FE: FIFO error interrupt + \arg TLI_INT_TE: transaction error interrupt + \arg TLI_INT_LCR: layer configuration reloaded interrupt + \param[out] none + \retval none +*/ +void tli_interrupt_enable(uint32_t int_flag) +{ + TLI_INTEN |= (int_flag); +} + +/*! + \brief disable TLI interrupt + \param[in] int_flag: TLI interrupt flags + one or more parameters can be selected which are shown as below: + \arg TLI_INT_LM: line mark interrupt + \arg TLI_INT_FE: FIFO error interrupt + \arg TLI_INT_TE: transaction error interrupt + \arg TLI_INT_LCR: layer configuration reloaded interrupt + \param[out] none + \retval none +*/ +void tli_interrupt_disable(uint32_t int_flag) +{ + TLI_INTEN &= ~(int_flag); +} + +/*! + \brief get TLI interrupt flag + \param[in] int_flag: TLI interrupt flags + one or more parameters can be selected which are shown as below: + \arg TLI_INT_FLAG_LM: line mark interrupt flag + \arg TLI_INT_FLAG_FE: FIFO error interrupt flag + \arg TLI_INT_FLAG_TE: transaction error interrupt flag + \arg TLI_INT_FLAG_LCR: layer configuration reloaded interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus tli_interrupt_flag_get(uint32_t int_flag) +{ + uint32_t state; + state = TLI_INTF; + if(state & int_flag){ + state = TLI_INTEN; + if(state & int_flag){ + return SET; + } + } + return RESET; +} + +/*! + \brief clear TLI interrupt flag + \param[in] int_flag: TLI interrupt flags + one or more parameters can be selected which are shown as below: + \arg TLI_INT_FLAG_LM: line mark interrupt flag + \arg TLI_INT_FLAG_FE: FIFO error interrupt flag + \arg TLI_INT_FLAG_TE: transaction error interrupt flag + \arg TLI_INT_FLAG_LCR: layer configuration reloaded interrupt flag + \param[out] none + \retval none +*/ +void tli_interrupt_flag_clear(uint32_t int_flag) +{ + TLI_INTC |= (int_flag); +} + +/*! + \brief get TLI flag or state in TLI_INTF register or TLI_STAT register + \param[in] flag: TLI flags or states + only one parameter can be selected which is shown as below: + \arg TLI_FLAG_VDE: current VDE state + \arg TLI_FLAG_HDE: current HDE state + \arg TLI_FLAG_VS: current VS status of the TLI + \arg TLI_FLAG_HS: current HS status of the TLI + \arg TLI_FLAG_LM: line mark interrupt flag + \arg TLI_FLAG_FE: FIFO error interrupt flag + \arg TLI_FLAG_TE: transaction error interrupt flag + \arg TLI_FLAG_LCR: layer configuration reloaded interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus tli_flag_get(uint32_t flag) +{ + uint32_t stat; + /* choose which register to get flag or state */ + if(flag >> 31U){ + stat = TLI_INTF; + }else{ + stat = TLI_STAT; + } + if(flag & stat){ + return SET; + }else{ + return RESET; + } } diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c index f0defdcd51..8c86bb832e 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c @@ -1,12 +1,37 @@ /*! - \file gd32f4xx_trng.c - \brief TRNG driver + \file gd32f4xx_trng.c + \brief TRNG driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ #include "gd32f4xx_trng.h" @@ -56,6 +81,28 @@ uint32_t trng_get_true_random_data(void) return (TRNG_DATA); } +/*! + \brief enable the TRNG interrupt + \param[in] none + \param[out] none + \retval none +*/ +void trng_interrupt_enable(void) +{ + TRNG_CTL |= TRNG_CTL_IE; +} + +/*! + \brief disable the TRNG interrupt + \param[in] none + \param[out] none + \retval none +*/ +void trng_interrupt_disable(void) +{ + TRNG_CTL &= ~TRNG_CTL_IE; +} + /*! \brief get the trng status flags \param[in] flag: trng status flag, refer to trng_flag_enum @@ -75,42 +122,6 @@ FlagStatus trng_flag_get(trng_flag_enum flag) } } -/*! - \brief clear the trng status flags - \param[in] flag: the special status flag - only one parameter can be selected which is shown as below: - \arg TRNG_FLAG_CECS: Clock error current status - \arg TRNG_FLAG_SECS: Seed error current status - \param[out] none - \retval none -*/ -void trng_flag_clear(trng_flag_enum flag) -{ - TRNG_STAT &= ~(uint32_t)flag; -} - -/*! - \brief enable the TRNG interrupt - \param[in] none - \param[out] none - \retval none -*/ -void trng_interrupt_enable(void) -{ - TRNG_CTL |= TRNG_CTL_IE; -} - -/*! - \brief disable the TRNG interrupt - \param[in] none - \param[out] none - \retval none -*/ -void trng_interrupt_disable(void) -{ - TRNG_CTL &= ~TRNG_CTL_IE; -} - /*! \brief get the trng interrupt flags \param[in] int_flag: trng interrupt flag, refer to trng_int_flag_enum diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c index 945e60bc73..1b864e3b96 100644 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c +++ b/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c @@ -1,18 +1,49 @@ /*! - \file gd32f4xx_usart.c - \brief USART driver + \file gd32f4xx_usart.c + \brief USART driver + + \version 2016-08-15, V1.0.0, firmware for GD32F4xx + \version 2018-12-12, V2.0.0, firmware for GD32F4xx + \version 2020-09-30, V2.1.0, firmware for GD32F4xx */ /* - Copyright (C) 2016 GigaDevice + Copyright (c) 2020, GigaDevice Semiconductor Inc. - 2016-08-15, V1.0.0, firmware for GD32F4xx + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. */ + #include "gd32f4xx_usart.h" +/* USART register bit offset */ +#define GP_GUAT_OFFSET ((uint32_t)8U) /* bit offset of GUAT in USART_GP */ +#define CTL3_SCRTNUM_OFFSET ((uint32_t)1U) /* bit offset of SCRTNUM in USART_CTL3 */ +#define RT_BL_OFFSET ((uint32_t)24U) /* bit offset of BL in USART_RT */ + /*! - \brief reset USART/UART + \brief reset USART/UART \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[out] none \retval none @@ -63,7 +94,7 @@ void usart_deinit(uint32_t usart_periph) \param[in] baudval: baud rate value \param[out] none \retval none -*/ +*/ void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) { uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U; @@ -100,24 +131,25 @@ void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) /* when oversampling by 8, configure the value of USART_BAUD */ udiv = ((2U*uclk) + baudval/2U)/baudval; intdiv = udiv & 0xfff0U; - fradiv = udiv & 0x7U; - USART_BAUD(usart_periph) |= ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); + fradiv = (udiv>>1U) & 0x7U; + USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); }else{ /* when oversampling by 16, configure the value of USART_BAUD */ udiv = (uclk+baudval/2U)/baudval; intdiv = udiv & 0xfff0U; fradiv = udiv & 0xfU; - USART_BAUD(usart_periph) |= ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); - } + USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); + } } /*! \brief configure USART parity function \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[in] paritycfg: configure USART parity + only one parameter can be selected which is shown as below: \arg USART_PM_NONE: no parity + \arg USART_PM_EVEN: even parity \arg USART_PM_ODD: odd parity - \arg USART_PM_EVEN: even parity \param[out] none \retval none */ @@ -133,6 +165,7 @@ void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) \brief configure USART word length \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[in] wlen: USART word length configure + only one parameter can be selected which is shown as below: \arg USART_WL_8BIT: 8 bits \arg USART_WL_9BIT: 9 bits \param[out] none @@ -150,17 +183,18 @@ void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) \brief configure USART stop bit length \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[in] stblen: USART stop bit configure + only one parameter can be selected which is shown as below: \arg USART_STB_1BIT: 1 bit - \arg USART_STB_0_5BIT: 0.5 bit + \arg USART_STB_0_5BIT: 0.5 bit(not available for UARTx(x=3,4,6,7)) \arg USART_STB_2BIT: 2 bits - \arg USART_STB_1_5BIT: 1.5 bits + \arg USART_STB_1_5BIT: 1.5 bits(not available for UARTx(x=3,4,6,7)) \param[out] none \retval none */ void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) { /* clear USART_CTL1 STB bits */ - USART_CTL1(usart_periph) &= ~USART_CTL1_STB; + USART_CTL1(usart_periph) &= ~USART_CTL1_STB; /* configure USART stop bits */ USART_CTL1(usart_periph) |= stblen; } @@ -189,7 +223,8 @@ void usart_disable(uint32_t usart_periph) /*! \brief configure USART transmitter \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] rtconfig: enable or disable USART transmitter + \param[in] txconfig: enable or disable USART transmitter + only one parameter can be selected which is shown as below: \arg USART_TRANSMIT_ENABLE: enable USART transmission \arg USART_TRANSMIT_DISABLE: enable USART transmission \param[out] none @@ -198,7 +233,7 @@ void usart_disable(uint32_t usart_periph) void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) { uint32_t ctl = 0U; - + ctl = USART_CTL0(usart_periph); ctl &= ~USART_CTL0_TEN; ctl |= txconfig; @@ -209,7 +244,8 @@ void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) /*! \brief configure USART receiver \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] rtconfig: enable or disable USART receiver + \param[in] rxconfig: enable or disable USART receiver + only one parameter can be selected which is shown as below: \arg USART_RECEIVE_ENABLE: enable USART reception \arg USART_RECEIVE_DISABLE: disable USART reception \param[out] none @@ -218,7 +254,7 @@ void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) { uint32_t ctl = 0U; - + ctl = USART_CTL0(usart_periph); ctl &= ~USART_CTL0_REN; ctl |= rxconfig; @@ -230,6 +266,7 @@ void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) \brief data is transmitted/received with the LSB/MSB first \param[in] usart_periph: USARTx(x=0,1,2,5) \param[in] msbf: LSB/MSB + only one parameter can be selected which is shown as below: \arg USART_MSBF_LSB: LSB first \arg USART_MSBF_MSB: MSB first \param[out] none @@ -237,14 +274,20 @@ void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) */ void usart_data_first_config(uint32_t usart_periph, uint32_t msbf) { - USART_CTL3(usart_periph) &= ~(USART_CTL3_MSBF); - USART_CTL3(usart_periph) |= msbf; + uint32_t ctl = 0U; + + ctl = USART_CTL3(usart_periph); + ctl &= ~(USART_CTL3_MSBF); + ctl |= msbf; + /* configure data transmitted/received mode */ + USART_CTL3(usart_periph) = ctl; } /*! \brief configure USART inversion \param[in] usart_periph: USARTx(x=0,1,2,5) \param[in] invertpara: refer to enum USART_INVERT_CONFIG + only one parameter can be selected which is shown as below: \arg USART_DINV_ENABLE: data bit level inversion \arg USART_DINV_DISABLE: data bit level not inversion \arg USART_TXPIN_ENABLE: TX pin level inversion @@ -256,7 +299,7 @@ void usart_data_first_config(uint32_t usart_periph, uint32_t msbf) */ void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara) { - /* inverted or not the specified siginal */ + /* inverted or not the specified siginal */ switch(invertpara){ case USART_DINV_ENABLE: USART_CTL3(usart_periph) |= USART_CTL3_DINV; @@ -282,9 +325,10 @@ void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara) } /*! - \brief configure the USART oversample mode + \brief configure the USART oversample mode \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[in] oversamp: oversample value + only one parameter can be selected which is shown as below: \arg USART_OVSMOD_8: 8 bits \arg USART_OVSMOD_16: 16 bits \param[out] none @@ -301,6 +345,7 @@ void usart_oversample_config(uint32_t usart_periph, uint32_t oversamp) \brief configure sample bit method \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[in] obsm: sample bit + only one parameter can be selected which is shown as below: \arg USART_OSB_1bit: 1 bit \arg USART_OSB_3bit: 3 bits \param[out] none @@ -308,7 +353,7 @@ void usart_oversample_config(uint32_t usart_periph, uint32_t oversamp) */ void usart_sample_bit_config(uint32_t usart_periph, uint32_t obsm) { - USART_CTL2(usart_periph) &= ~(USART_CTL2_OSB); + USART_CTL2(usart_periph) &= ~(USART_CTL2_OSB); USART_CTL2(usart_periph) |= obsm; } @@ -350,7 +395,7 @@ void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rti /*! \brief USART transmit data function \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] data: data of transmission + \param[in] data: data of transmission \param[out] none \retval none */ @@ -367,7 +412,7 @@ void usart_data_transmit(uint32_t usart_periph, uint32_t data) */ uint16_t usart_data_receive(uint32_t usart_periph) { - return (uint16_t)(USART_DATA(usart_periph) & (uint16_t)USART_DATA_DATA); + return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U)); } /*! @@ -384,7 +429,7 @@ void usart_address_config(uint32_t usart_periph, uint8_t addr) } /*! - \brief receiver in mute mode + \brief enable mute mode \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[out] none \retval none @@ -395,7 +440,7 @@ void usart_mute_mode_enable(uint32_t usart_periph) } /*! - \brief receiver in active mode + \brief disable mute mode \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[out] none \retval none @@ -409,6 +454,7 @@ void usart_mute_mode_disable(uint32_t usart_periph) \brief configure wakeup method in mute mode \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[in] wmehtod: two method be used to enter or exit the mute mode + only one parameter can be selected which is shown as below: \arg USART_WM_IDLE: idle line \arg USART_WM_ADDR: address mask \param[out] none @@ -427,7 +473,7 @@ void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmehtod) \retval none */ void usart_lin_mode_enable(uint32_t usart_periph) -{ +{ USART_CTL1(usart_periph) |= USART_CTL1_LMEN; } @@ -438,7 +484,7 @@ void usart_lin_mode_enable(uint32_t usart_periph) \retval none */ void usart_lin_mode_disable(uint32_t usart_periph) -{ +{ USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); } @@ -446,12 +492,13 @@ void usart_lin_mode_disable(uint32_t usart_periph) \brief configure lin break frame length \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[in] lblen: lin break frame length + only one parameter can be selected which is shown as below: \arg USART_LBLEN_10B: 10 bits \arg USART_LBLEN_11B: 11 bits \param[out] none \retval none */ -void usart_lin_break_dection_length_config(uint32_t usart_periph, uint32_t lblen) +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen) { USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN); USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen); @@ -475,7 +522,7 @@ void usart_send_break(uint32_t usart_periph) \retval none */ void usart_halfduplex_enable(uint32_t usart_periph) -{ +{ USART_CTL2(usart_periph) |= USART_CTL2_HDEN; } @@ -486,7 +533,7 @@ void usart_halfduplex_enable(uint32_t usart_periph) \retval none */ void usart_halfduplex_disable(uint32_t usart_periph) -{ +{ USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN); } @@ -516,13 +563,16 @@ void usart_synchronous_clock_disable(uint32_t usart_periph) \brief configure USART synchronous mode parameters \param[in] usart_periph: USARTx(x=0,1,2,5) \param[in] clen: CK length - \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame + only one parameter can be selected which is shown as below: + \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame \arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame \param[in] cph: clock phase - \arg USART_CPH_1CK: first clock transition is the first data capture edge + only one parameter can be selected which is shown as below: + \arg USART_CPH_1CK: first clock transition is the first data capture edge \arg USART_CPH_2CK: second clock transition is the first data capture edge - \param[in] cpl: clock polarity - \arg USART_CPL_LOW: steady low value on CK pin + \param[in] cpl: clock polarity + only one parameter can be selected which is shown as below: + \arg USART_CPL_LOW: steady low value on CK pin \arg USART_CPL_HIGH: steady high value on CK pin \param[out] none \retval none @@ -530,26 +580,27 @@ void usart_synchronous_clock_disable(uint32_t usart_periph) void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) { uint32_t ctl = 0U; - + /* read USART_CTL1 register */ ctl = USART_CTL1(usart_periph); + ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); /* set CK length, CK phase, CK polarity */ ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); - USART_CTL1(usart_periph) |= ctl; + USART_CTL1(usart_periph) = ctl; } /*! \brief configure guard time value in smartcard mode \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] gaut: guard time value + \param[in] guat: guard time value, 0-0xFF \param[out] none \retval none */ -void usart_guard_time_config(uint32_t usart_periph,uint32_t gaut) +void usart_guard_time_config(uint32_t usart_periph,uint32_t guat) { USART_GP(usart_periph) &= ~(USART_GP_GUAT); - USART_GP(usart_periph) |= (USART_GP_GUAT & ((gaut)<<8)); + USART_GP(usart_periph) |= (USART_GP_GUAT & ((guat)<> 16; \ -} while(0) - -/* read out endpoint-x interrupt flag */ -#define USB_DOEP_INTR_READ(x, EpID) \ -do { \ - uint32_t out_epintf = USB_DOEPxINTF(EpID); \ - (x) = out_epintf & USB_DOEPINTEN; \ -} while(0) - -/* read all in endpoint interrupt flag */ -#define USB_DAIEP_INTR_READ(x) \ -do { \ - uint32_t dev_all_ep_inten = USB_DAEPINTEN; \ - uint32_t dev_all_ep_int = USB_DAEPINT; \ - uint32_t in_ep_intb = DAEPINT_IEPITB; \ - (x) = dev_all_ep_inten & dev_all_ep_int & in_ep_intb; \ -} while(0) - - -/* read in endpoint-x interrupt flag */ -#define USB_DIEP_INTR_READ(x, EpID) \ -do { \ - uint32_t dev_ep_intf = USB_DIEPxINTF(EpID); \ - uint32_t dev_ep_fifoempty_intf = (((USB_DIEPFEINTEN >> (EpID)) & 0x1U) << 7U); \ - uint32_t dev_inep_inten = USB_DIEPINTEN; \ - (x) = dev_ep_intf & (dev_ep_fifoempty_intf | dev_inep_inten); \ -} while(0) - -/* generate remote wakup signal */ -#define USB_REMOTE_WAKEUP_SET() (USB_DCTL |= DCTL_RWKUP) - -/* no remote wakup signal generate */ -#define USB_REMOTE_WAKEUP_RESET() (USB_DCTL &= ~DCTL_RWKUP) - -/* generate soft disconnect */ -#define USB_SOFT_DISCONNECT_ENABLE() (USB_DCTL |= DCTL_SD) - -/* no soft disconnect generate */ -#define USB_SOFT_DISCONNECT_DISABLE() (USB_DCTL &= ~DCTL_SD) - -/* set device address */ -#define USB_SET_DEVADDR(DevAddr) (USB_DCFG |= (DevAddr) << 4U) - -/* check whether frame is even */ -#define USB_EVEN_FRAME() (!(USB_HFINFR & 0x01U)) - -/* read port status */ -#define USB_PORT_READ() (USB_HPCS & (~HPCS_PE) & (~HPCS_PCD) & (~HPCS_PEDC)) - -/* usb clock initialize */ -#define USB_FSLSCLOCK_INIT(ClockFreq) (USB_HCTL &= ~HCTL_CLKSEL | (ClockFreq)) - -/* get usb current speed */ -#define USB_CURRENT_SPEED_GET() ((USB_HPCS & HPCS_PS) >> 17) - -/* get usb current frame */ -#define USB_CURRENT_FRAME_GET() (USB_HFINFR & 0xFFFFU) - -#endif /* USB_REGS_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usb_std.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usb_std.h deleted file mode 100644 index b7fa5d8e9a..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usb_std.h +++ /dev/null @@ -1,188 +0,0 @@ -/*! - \file usb_std.h - \brief USB 2.0 standard defines -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - -#ifndef USB_STD_H -#define USB_STD_H - -#include "usb_conf.h" - -#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ -#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ -#define USB_CFG_DESC_LEN 0x09U /*!< USB device configuration descriptor length */ -#define USB_IF_DESC_LEN 0x09U /*!< USB device interface descriptor length */ -#define USB_EP_DESC_LEN 0x07U /*!< USB device endpoint descriptor length */ -#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ - -/* bit 7 of bmRequestType: data phase transfer direction */ -#define USB_DIR_MASK 0x80U /*!< USB transfer direction mask */ -#define USB_DIR_OUT 0x00U /*!< USB transfer OUT direction */ -#define USB_DIR_IN 0x80U /*!< USB transfer IN direction */ - -/* bit 6..5 of bmRequestType: request type */ -#define USB_STANDARD_REQ 0x00U /*!< USB standard request */ -#define USB_CLASS_REQ 0x20U /*!< USB class request */ -#define USB_VENDOR_REQ 0x40U /*!< USB vebdor request */ -#define USB_REQ_MASK 0x60U /*!< USB request mask */ - -/* bit 4..0 of bmRequestType: recipient type */ -#define USB_REQTYPE_DEVICE 0x00U /*!< USB device request type */ -#define USB_REQTYPE_INTERFACE 0x01U /*!< USB interface request type*/ -#define USB_REQTYPE_ENDPOINT 0x02U /*!< USB endpoint request type*/ -#define USB_REQTYPE_MASK 0x03U /*!< USB request type mask*/ - -/* bRequest value */ -#define USBREQ_GET_STATUS 0x00U /*!< USB get status request*/ -#define USBREQ_CLEAR_FEATURE 0x01U /*!< USB clear feature request*/ -#define USBREQ_SET_FEATURE 0x03U /*!< USB set feature request*/ -#define USBREQ_SET_ADDRESS 0x05U /*!< USB set address request*/ -#define USBREQ_GET_DESCRIPTOR 0x06U /*!< USB get descriptor request*/ -#define USBREQ_SET_DESCRIPTOR 0x07U /*!< USB set descriptor request*/ -#define USBREQ_GET_CONFIGURATION 0x08U /*!< USB get configuration request*/ -#define USBREQ_SET_CONFIGURATION 0x09U /*!< USB set configuration request*/ -#define USBREQ_GET_INTERFACE 0x0AU /*!< USB get interface request*/ -#define USBREQ_SET_INTERFACE 0x0BU /*!< USB set interface request*/ -#define USBREQ_SYNCH_FRAME 0x0CU /*!< USB synchronize frame request*/ - -/* descriptor types of usb specifications */ -#define USB_DESCTYPE_DEVICE 0x01U /*!< USB device descriptor type*/ -#define USB_DESCTYPE_CONFIGURATION 0x02U /*!< USB configuration descriptor type*/ -#define USB_DESCTYPE_STRING 0x03U /*!< USB string descriptor type*/ -#define USB_DESCTYPE_INTERFACE 0x04U /*!< USB interface descriptor type*/ -#define USB_DESCTYPE_ENDPOINT 0x05U /*!< USB endpoint descriptor type*/ -#define USB_DESCTYPE_DEVICE_QUALIFIER 0x06U /*!< USB device qualtfier descriptor type*/ -#define USB_DESCTYPE_OTHER_SPEED_CONFIGURATION 0x07U /*!< USB other speed configuration descriptor type*/ -#define USB_DESCTYPE_INTERFACE_POWER 0x08U /*!< USB interface power descriptor type*/ - -#define USB_DESCTYPE_HID 0x21U /*!< USB HID descriptor type*/ -#define USB_DESCTYPE_HID_REPORT 0x22U /*!< USB HID report descriptor type*/ - -#define USB_DEVDESC_SIZE 18U /*!< USB device descriptor size*/ -#define USB_CFGDESC_SIZE 9U /*!< USB configure descriptor size*/ -#define USB_INTDESC_SIZE 9U /*!< USB interface descriptor size*/ -#define USB_EPDESC_SIZE 7U /*!< USB endpoint descriptor size*/ - -/* descriptor type and descriptor index */ -/* use the following values when USB host need to get descriptor */ -#define USB_DEVDESC ((USB_DESCTYPE_DEVICE << 8U) & 0xFF00U) /*!< USB device operation marco */ -#define USB_CFGDESC ((USB_DESCTYPE_CONFIGURATION << 8U) & 0xFF00U) /*!< USB configuration operation marco */ -#define USB_STRDESC ((USB_DESCTYPE_STRING << 8U) & 0xFF00U) /*!< USB string operation marco */ -#define USB_INTDESC ((USB_DESCTYPE_INTERFACE << 8U) & 0xFF00U) /*!< USB interface operation marco */ -#define USB_EPDESC ((USB_DESCTYPE_INTERFACE << 8U) & 0xFF00U) /*!< USB endpoint operation marco */ -#define USB_DEVQUADESC ((USB_DESCTYPE_DEVICE_QUALIFIER << 8U) & 0xFF00U) /*!< USB device qualifier operation marco */ -#define USB_OSPCFGDESC ((USB_DESCTYPE_OTHER_SPEED_CONFIGURATION << 8U) & 0xFF00U) /*!< USB other speed configuration operation marco */ -#define USB_INTPWRDESC ((USB_DESCTYPE_INTERFACE_POWER << 8U) & 0xFF00U) /*!< USB interface power operation marco */ -#define USB_HIDREPDESC ((USB_DESCTYPE_HID_REPORT << 8U) & 0xFF00U) /*!< USB HID report operation marco */ -#define USB_HIDDESC ((USB_DESCTYPE_HID << 8U) & 0xFF00U) /*!< USB HID operation marco */ - -#define SWAPBYTE(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ - (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) - -/* supported classes */ -#define USB_MSC_CLASS 0x08U /*!< USB MSC class*/ -#define USB_HID_CLASS 0x03U /*!< USB HID class*/ - -/* interface descriptor field values for hid boot protocol */ -#define HID_BOOT_CODE 0x01U /*!< USB HID boot code*/ -#define HID_KEYBRD_BOOT_CODE 0x01U /*!< USB HID keyboard boot code*/ -#define HID_MOUSE_BOOT_CODE 0x02U /*!< USB HID mouse boot code*/ - -/* as per usb specs 9.2.6.4 :standard request with data request timeout: 5sec - standard request with no data stage timeout : 50ms */ -#define DATA_STAGE_TIMEOUT 5000U /*!< USB data stage timeout*/ -#define NODATA_STAGE_TIMEOUT 50U /*!< USB no data stage timeout*/ - -#define USBH_CFG_DESC_SET_SIZE (USB_CFGDESC_SIZE + USB_INTDESC_SIZE \ - + (USBH_MAX_EP_NUM * USB_EPDESC_SIZE)) /*!< USB host set configuration descriptor size */ - -#pragma pack(1) - -typedef union -{ - uint8_t data[8]; - - struct _setup_packet_struct - { - uint8_t bmRequestType; /*!< type of request */ - uint8_t bRequest; /*!< request of setup packet */ - uint16_t wValue; /*!< value of setup packet */ - uint16_t wIndex; /*!< index of setup packet */ - uint16_t wLength; /*!< length of setup packet */ - } b; -}usb_setup_union; - -typedef struct -{ - uint8_t bLength; /*!< size of the descriptor */ - uint8_t bDescriptorType; /*!< type of the descriptor */ -} usb_descriptor_header_struct; - -typedef struct -{ - usb_descriptor_header_struct Header; /*!< descriptor header, including type and size */ - - uint16_t bcdUSB; /*!< BCD of the supported USB specification */ - uint8_t bDeviceClass; /*!< USB device class */ - uint8_t bDeviceSubClass; /*!< USB device subclass */ - uint8_t bDeviceProtocol; /*!< USB device protocol */ - uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ - uint16_t idVendor; /*!< vendor ID for the USB product */ - uint16_t idProduct; /*!< unique product ID for the USB product */ - uint16_t bcdDevice; /*!< product release (version) number */ - uint8_t iManufacturer; /*!< string index for the manufacturer's name */ - uint8_t iProduct; /*!< string index for the product name/details */ - uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ - uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ -} usb_descriptor_device_struct; - -typedef struct -{ - usb_descriptor_header_struct Header; /*!< descriptor header, including type and size */ - - uint16_t wTotalLength; /*!< size of the configuration descriptor header,and all sub descriptors inside the configuration */ - uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ - uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ - uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ - uint8_t bmAttributes; /*!< configuration attributes */ - uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ -} usb_descriptor_configuration_struct; - -typedef struct -{ - usb_descriptor_header_struct Header; /*!< descriptor header, including type and size */ - - uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ - uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ - uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ - uint8_t bInterfaceClass; /*!< interface class ID */ - uint8_t bInterfaceSubClass; /*!< interface subclass ID */ - uint8_t bInterfaceProtocol; /*!< interface protocol ID */ - uint8_t iInterface; /*!< index of the string descriptor describing the interface */ -} usb_descriptor_interface_struct; - -typedef struct -{ - usb_descriptor_header_struct Header; /*!< descriptor header, including type and size. */ - - uint8_t bEndpointAddress; /*!< logical address of the endpoint */ - uint8_t bmAttributes; /*!< endpoint attributes */ - uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ - uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ -} usb_descriptor_endpoint_struct; - -typedef struct -{ - usb_descriptor_header_struct Header; /*!< descriptor header, including type and size. */ - uint16_t wLANGID; /*!< LANGID code */ -}usb_descriptor_language_id_struct; - -#pragma pack() - -#endif /* USB_STD_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_core.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_core.h deleted file mode 100644 index 8b79c2ed5a..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_core.h +++ /dev/null @@ -1,54 +0,0 @@ -/*! - \file usbd_core.h - \brief USB device-mode core driver header file -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - - -#ifndef USBD_CORE_H -#define USBD_CORE_H - -#include "usbd_conf.h" -#include "usb_core.h" -#include "usbd_std.h" - -/* device status */ -#define USB_STATUS_DEFAULT 1U /* default status */ -#define USB_STATUS_ADDRESSED 2U /* addressed status */ -#define USB_STATUS_CONFIGURED 3U /* configured status */ -#define USB_STATUS_SUSPENDED 4U /* suspended status */ - -/* function declarations */ -/* initailizes the USB device-mode handler stack */ -void usbd_init (usb_core_handle_struct *pudev, usb_core_id_enum core_id); -/* endpoint initialization */ -void usbd_ep_init (usb_core_handle_struct *pudev, const usb_descriptor_endpoint_struct *pep_desc); -/* endpoint deinitialize */ -void usbd_ep_deinit (usb_core_handle_struct *pudev, uint8_t ep_addr); -/* endpoint prepare to receive data */ -void usbd_ep_rx (usb_core_handle_struct *pudev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len); -/* endpoint prepare to transmit data */ -void usbd_ep_tx (usb_core_handle_struct *pudev, uint8_t ep_addr, uint8_t *pbuf, uint32_t buf_len); -/* transmit data on the control channel */ -usbd_status_enum usbd_ctltx (usb_core_handle_struct *pudev, uint8_t *pbuf, uint16_t len); -/* receive data on the control channel */ -usbd_status_enum usbd_ctlrx (usb_core_handle_struct *pudev, uint8_t *pbuf, uint16_t len); -/* transmit status on the control channel */ -usbd_status_enum usbd_ctlstatus_tx (usb_core_handle_struct *pudev); -/* receive status on the control channel */ -usbd_status_enum usbd_ctlstatus_rx (usb_core_handle_struct *pudev); -/* set an endpoint to STALL status */ -void usbd_ep_stall (usb_core_handle_struct *pudev, uint8_t ep_addr); -/* clear endpoint stalled status */ -void usbd_ep_clear_stall (usb_core_handle_struct *pudev, uint8_t ep_addr); -/* flushes the FIFOs */ -void usbd_ep_fifo_flush (usb_core_handle_struct *pudev, uint8_t ep_addr); -/* get the received data length */ -uint16_t usbd_rxcount_get (usb_core_handle_struct *pudev, uint8_t ep_id); - -#endif /* USBD_CORE_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_int.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_int.h deleted file mode 100644 index 3247853be5..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_int.h +++ /dev/null @@ -1,31 +0,0 @@ -/*! - \file usbd_int.h - \brief USB device-mode interrupt handler header file -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - -#ifndef USBD_INT_H -#define USBD_INT_H - -#include "usbd_core.h" - -/* function declarations */ -/* USB device-mode interrupts global service routine handler */ -uint32_t usbd_isr (usb_core_handle_struct *pudev); - -#ifdef USBHS_DEDICATED_EP1_ENABLED - -/* USB dedicated OUT endpoint 1 interrupt service routine handler */ -uint32_t USBD_EP1OUT_ISR_Handler (usb_core_handle_struct *pudev); -/* USB dedicated IN endpoint 1 interrupt service routine handler */ -uint32_t USBD_EP1IN_ISR_Handler (usb_core_handle_struct *pudev); - -#endif /* USBHS_DEDICATED_EP1_ENABLED */ - -#endif /* USBD_INT_H */ - diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_std.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_std.h deleted file mode 100644 index 494f0ec3aa..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbd_std.h +++ /dev/null @@ -1,70 +0,0 @@ -/*! - \file usbd_std.h - \brief USB 2.0 standard driver -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-06-30, V1.0.0, firmware for GD32F4xx -*/ - -#ifndef USBD_STD_H -#define USBD_STD_H - -#include "usb_std.h" -#include "usbd_core.h" -#include "usbd_conf.h" -#include - -#define USBD_LANGID_STR_IDX 0x00U /*!< USB language ID string index*/ -#define USBD_MFC_STR_IDX 0x01U /*!< USB manufacturer string index*/ -#define USBD_PRODUCT_STR_IDX 0x02U /*!< USB product string index*/ -#define USBD_SERIAL_STR_IDX 0x03U /*!< USB serial string index*/ -#define USBD_CONFIG_STR_IDX 0x04U /*!< USB configuration string index*/ -#define USBD_INTERFACE_STR_IDX 0x05U /*!< USB interface string index*/ - -#define USB_STATUS_REMOTE_WAKEUP 0x02U /*!< USB remote wakeup status*/ -#define USB_STATUS_SELF_POWERED 0x01U /*!< USB self power status*/ - -#define USB_FEATURE_ENDP_HALT 0x00U /*!< USB halt endpoint feature*/ -#define USB_FEATURE_REMOTE_WAKEUP 0x01U /*!< USB remote wakeup feature*/ -#define USB_FEATURE_TEST_MODE 0x02U /*!< USB test mode feature*/ - -#define ENG_LANGID 0x0409U /*!< USB english language id*/ -#define CHN_LANGID 0x0804U /*!< USB chinese language id*/ - -#define USB_DEVICE_DESC_SIZE 0x12U /*!< USB device descriptor size*/ - -#define LOWBYTE(x) ((uint8_t)((x) & 0x00FFU)) /*!< USB lowbyte operation marco*/ -#define HIGHBYTE(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) /*!< USB highbyte operation marco*/ - -#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) /*!< USB minimum operation marco*/ - -#define WIDE_STRING(string) _WIDE_STRING(string) -#define _WIDE_STRING(string) L##string - -#define USBD_STRING_DESC(string) \ - (uint8_t *)&(struct { \ - uint8_t _len; \ - uint8_t _type; \ - wchar_t _data[sizeof(string)]; \ - }) { \ - sizeof(WIDE_STRING(string)) + 2U - 2U, \ - USB_DESCTYPE_STRING, \ - WIDE_STRING(string) \ - } - -#define IS_NOT_EP0(ep_addr) (((ep_addr) != 0x00U) && ((ep_addr) != 0x80U)) - -/* function declarations */ -/* USB device setup transaction*/ -usbd_status_enum usbd_setup_transaction (usb_core_handle_struct *pudev); -/* USB device out transaction*/ -usbd_status_enum usbd_out_transaction (usb_core_handle_struct *pudev, uint8_t endp_num); -/* USB device in transaction*/ -usbd_status_enum usbd_in_transaction (usb_core_handle_struct *pudev, uint8_t endp_num); -/* USB device enum error handle*/ -void usbd_enum_error (usb_core_handle_struct *pudev, usb_device_req_struct *req); - -#endif /* USBD_STD_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_core.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_core.h deleted file mode 100644 index f4e8739687..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_core.h +++ /dev/null @@ -1,283 +0,0 @@ -/*! - \file usbh_core.h - \brief header file for usbh_core.c -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.1, firmware for GD32F4xx -*/ - -#ifndef USBH_CORE_H -#define USBH_CORE_H - -#include "usbh_conf.h" -#include "usb_std.h" -#include "usb_core.h" - -#define MSC_CLASS 0x08 /*!< the MSC class define */ -#define HID_CLASS 0x03 /*!< the HID class define */ -#define MSC_PROTOCOL 0x50 /*!< the MSC protocal define */ -#define CBI_PROTOCOL 0x01 /*!< the CBI protocal define */ - -#define USBH_DEVICE_ADDRESS_DEFAULT 0U /*!< the default device address define */ -#define USBH_DEVICE_ADDRESS 1U /*!< the device address define */ -#define USBH_MAX_ERROR_COUNT 2U /*!< the max error count define */ - -#define HOST_USER_SELECT_CONFIGURATION 1U /*!< the user select configuration define */ -#define HOST_USER_CLASS_ACTIVE 2U /*!< the user class active define */ -#define HOST_USER_CLASS_SELECTED 3U /*!< the user class selected define */ -#define HOST_USER_CONNECTION 4U /*!< the user connecttion define */ -#define HOST_USER_DISCONNECTION 5U /*!< the user disconnection define */ -#define HOST_USER_UNRECOVERED_ERROR 6U /*!< the user unrecovered error define */ - -#define MAX_USBH_STATE_STACK_DEEP 4 /*!< the max state stack deep define */ -#define MAX_USBH_STATE_TABLE_NUM 10U /*!< the max state table number */ - -#define HOST_FSM_ID 0U /*!< the host state table id */ -#define ENUM_FSM_ID 1U /*!< the enum state table id */ -#define CMD_FSM_ID 2U /*!< the cmd state table id */ -#define CTRL_FSM_ID 3U /*!< the ctrl state table id */ -#define CLASS_REQ_FSM_ID 4U /*!< the class req state table id */ -#define CLASS_FSM_ID 5U /*!< the class state table id */ - -#define UP_STATE 100U /*!< up state define */ -#define GO_TO_UP_STATE_EVENT 100U /*!< go to up state event define */ - -#define HOST_HANDLE_TABLE_SIZE 9U /*!< the host handle table size define */ - -/* the enum of host state */ -typedef enum -{ - HOST_IDLE = 0, /* the host idle state definition */ - HOST_DEV_ATTACHED, /* the host device attached state definition */ - HOST_DEV_DETACHED, /* the host device detached state definition */ - HOST_DETECT_DEV_SPEED, /* the host detect device speed state definition */ - HOST_ENUMERATION, /* the host enumeration state definition */ - HOST_CLASS_REQUEST, /* the host class request state definition */ - HOST_CLASS, /* the host class state definition */ - HOST_USER_INPUT, /* the host user input state definition */ - HOST_SUSPENDED, /* the host suspended state definition */ - HOST_ERROR /* the host error state definition */ -}host_state_enum; - -/* the enum of host event */ -typedef enum -{ - HOST_EVENT_ATTACHED = 0, /* the host attached event */ - HOST_EVENT_ENUM, /* the host enum event */ - HOST_EVENT_USER_INPUT, /* the host user input event */ - HOST_EVENT_CLASS_REQ, /* the host class request event */ - HOST_EVENT_CLASS, /* the host class event */ - HOST_EVENT_ERROR, /* the host error event */ - HOST_EVENT_DEV_DETACHED, /* the host device detached event */ - HOST_EVENT_IDLE /* the host idle event */ -}host_event_enum; - -/* the enum of enum state */ -typedef enum -{ - ENUM_IDLE = 0, /* the enum idle state definition */ - ENUM_SET_ADDR, /* the enum set address state definition */ - ENUM_GET_FULL_DEV_DESC, /* the enum get full device descripter state definition */ - ENUM_GET_CFG_DESC, /* the enum get configuration descripter state definition */ - ENUM_GET_FULL_CFG_DESC, /* the enum get full configuration descripter state definition */ - ENUM_GET_MFC_STRING_DESC, /* the enum get MFC string descripter state definition */ - ENUM_GET_PRODUCT_STRING_DESC, /* the enum get product string descripter state definition */ - ENUM_GET_SERIALNUM_STRING_DESC, /* the enum get serialnum string descripter state definition */ - ENUM_SET_CONFIGURATION, /* the enum set congiguration state definition */ - ENUM_DEV_CONFIGURED /* the enum device configuration state definition */ -}enum_state_enum; - -/* the enum of ctrl state */ -typedef enum -{ - CTRL_IDLE = 0, /* the ctrl idle state definition */ - CTRL_SETUP, /* the ctrl setup state definition */ - CTRL_DATA, /* the ctrl data state definition */ - CTRL_STATUS, /* the ctrl status state definition */ - CTRL_ERROR, /* the ctrl error state definition */ - CTRL_STALLED, /* the ctrl stalled state definition */ - CTRL_COMPLETE /* the ctrl complete state definition */ -}ctrl_state_enum; - -/* the enum of host status */ -typedef enum -{ - USBH_OK = 0, /* the usbh ok status definition */ - USBH_BUSY, /* the usbh busy status definition */ - USBH_FAIL, /* the usbh fail status definition */ - USBH_NOT_SUPPORTED, /* the usbh not supported status definition */ - USBH_UNRECOVERED_ERROR, /* the usbh unrecovered error status definition */ - USBH_SPEED_UNKNOWN_ERROR, /* the usbh speed unknown error status definition */ - USBH_APPLY_DEINIT /* the usbh apply deinit status definition */ -}usbh_status_enum; - -/* the state of user action */ -typedef enum -{ - USBH_USER_NO_RESP = 0, /* the user no response */ - USBH_USER_RESP_OK = 1, /* the user response ok */ -}usbh_user_status_enum; - -/* control transfer information */ -typedef struct -{ - uint8_t hc_in_num; /* the host in channel number */ - uint8_t hc_out_num; /* the host out channel number */ - uint8_t ep0_size; /* the endpoint 0 max packet size */ - uint8_t error_count; /* the error count */ - uint16_t length; /* the length */ - uint16_t timer; /* the timer */ - uint8_t *buff; /* the buffer */ - usb_setup_union setup; /* the setup packet */ -}usbh_ctrl_struct; - -/* device property */ -typedef struct -{ - uint8_t address; /* the device address */ - uint8_t speed; /* the device speed */ - usb_descriptor_device_struct dev_desc; /* the device descripter */ - usb_descriptor_configuration_struct cfg_desc; /* the configuration descripter */ - usb_descriptor_interface_struct itf_desc[USBH_MAX_INTERFACES_NUM]; /* the interface descripter */ - usb_descriptor_endpoint_struct ep_desc[USBH_MAX_INTERFACES_NUM][USBH_MAX_EP_NUM]; /* the endpoint descripter */ -}usbh_device_struct; - -/* user callbacks */ -typedef struct -{ - void (*init) (void); /* the user callback init function */ - void (*deinit) (void); /* the user callback deinit function */ - void (*device_connected) (void); /* the user callback device connected function */ - void (*device_reset) (void); /* the user callback device reset function */ - void (*device_disconnected) (void); /* the user callback device disconnected function */ - void (*over_current_detected) (void); /* the user callback over current detected function */ - void (*device_speed_detected) (uint8_t device_speed); /* the user callback device speed detected function */ - void (*device_desc_available) (void *devDesc); /* the user callback device descrpiter available function */ - void (*device_address_set) (void); /* the user callback set device address function */ - - void (*configuration_desc_available)(usb_descriptor_configuration_struct *cfg_desc, - usb_descriptor_interface_struct *itf_desc, - usb_descriptor_endpoint_struct *ep_desc); - /* the configuration descripter available function */ - - void (*manufacturer_string) (void *mfc_string); /* the user callback manufacturer string function */ - void (*product_string) (void *prod_string); /* the user callback product string function */ - void (*serial_num_string) (void *serial_string); /* the user callback serial number string function */ - void (*enumeration_finish) (void); /* the user callback enumeration finish function */ - usbh_user_status_enum (*user_input) (void); /* the user callback user input function */ - int (*user_application) (usb_core_handle_struct *pudev, uint8_t id); - /* the user callback user appliction function */ - void (*device_not_supported) (void); /* the user callback device not supported function */ - void (*unrecovered_error) (void); /* the user callback unrecovered error function */ -}usbh_user_callback_struct; - -/* the backup state struct */ -typedef struct -{ - host_state_enum host_backup_state; /* the host backup state */ - enum_state_enum enum_backup_state; /* the enum backup state */ - ctrl_state_enum ctrl_backup_state; /* the ctrl backup state */ - uint8_t class_req_backup_state;/* the class request backup state */ - uint8_t class_backup_state; /* the class backup state */ -} backup_state_struct; - -/* host information */ -typedef struct -{ - backup_state_struct usbh_backup_state; /* the usbh backup state variable */ - usbh_ctrl_struct control; /* the control struct variable */ - usbh_device_struct device; /* the device struct variable */ - usbh_user_callback_struct *usr_cb; /* the user callback function */ - usbh_status_enum (*class_init) (usb_core_handle_struct *pudev, void *phost); /* the class init function */ - void (*class_deinit) (usb_core_handle_struct *pudev, void *phost); /* the class deinit function */ -}usbh_host_struct; - -/* the action function definition */ -typedef usbh_status_enum (*ACT_FUN) (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void* pustate); - -/* the state table struct */ -typedef struct -{ - uint8_t cur_state; /* the current state */ - uint8_t cur_event; /* the current event */ - uint8_t next_state; /* the next state */ - ACT_FUN event_action_fun; /* the event action function entry */ -} state_table_struct; - -/* the state stack struct */ -typedef struct -{ - uint8_t state; /* the state in state stack */ - state_table_struct* table; /* the table in state stack */ - uint8_t table_size; /* the table size in state stack */ -} usbh_state_stack_struct; - -/* the state regist table struct */ -typedef struct -{ - uint8_t id; /* the id of the state table */ - state_table_struct* table; /* the table entry to regist */ - uint8_t table_size; /* the table size to regist */ -} usbh_state_regist_table_struct; - -/* the state handle struct */ -typedef struct -{ - uint8_t usbh_current_state; /* current state */ - uint8_t usbh_current_state_table_size; /* current state table size */ - state_table_struct* usbh_current_state_table; /* current state table */ - - usbh_state_stack_struct stack[MAX_USBH_STATE_STACK_DEEP]; /* the stack of state table */ - int8_t usbh_current_state_stack_top; /* the current state top */ - - usbh_state_regist_table_struct usbh_regist_state_table[MAX_USBH_STATE_TABLE_NUM]; /* the array of regist state table */ - uint8_t usbh_regist_state_table_num; /* the number of regist state table */ -} usbh_state_handle_struct; - -/* function declarations */ -/* the host core driver function */ -usbh_status_enum host_state_polling_fun (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate); -/* initialize the host portion of the driver */ -uint32_t hcd_init (usb_core_handle_struct *pudev, usb_core_id_enum core_id); -/* check if the device is connected */ -uint32_t hcd_is_device_connected (usb_core_handle_struct *pudev); -/* this function returns the last URBstate */ -urb_state_enum hcd_urb_state_get (usb_core_handle_struct *pudev, uint8_t channel_num); -/* this function returns the last URBstate */ -uint32_t hcd_xfer_count_get (usb_core_handle_struct *pudev, uint8_t channel_num); -/* de-initialize host */ -usbh_status_enum usbh_deinit (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct* pustate); - -/* the state core driver function */ -/* state core driver init */ -void scd_init (usbh_state_handle_struct* pustate); -/* state core driver table regist */ -void scd_table_regist (usbh_state_handle_struct* pustate, - state_table_struct* pstate_table, - uint8_t table_id, - uint8_t current_table_size); -/* state core driver begin */ -void scd_begin (usbh_state_handle_struct* pustate, uint8_t table_id); -/* state core driver move state */ -void scd_state_move (usbh_state_handle_struct* pustate, uint8_t state); -/* state core driver event handle */ -usbh_status_enum scd_event_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct* pustate, - uint8_t event, - uint8_t state); -/* state core driver table push */ -void scd_table_push (usbh_state_handle_struct* pustate); -/* state core driver table pop */ -void scd_table_pop (usbh_state_handle_struct* pustate); -/* the function is only used to state move */ -usbh_status_enum only_state_move (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate); -/* the function to the up state */ -usbh_status_enum goto_up_state_fun (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate); - -#endif /* USBH_CORE_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_ctrl.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_ctrl.h deleted file mode 100644 index 4b30c64d1a..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_ctrl.h +++ /dev/null @@ -1,45 +0,0 @@ -/*! - \file usbh_ctrl.h - \brief header file for usbh_ctrl.c -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - -#ifndef USBH_CTRL_H -#define USBH_CTRL_H - -#include "usbh_core.h" -#include "usbh_usr.h" - -#define CTRL_HANDLE_TABLE_SIZE 13U /*!< the ctrl handle table size define */ - -extern state_table_struct ctrl_handle_table[CTRL_HANDLE_TABLE_SIZE]; -extern uint8_t ctrl_polling_handle_flag; - -/* the enum of CTRL event */ -typedef enum -{ - CTRL_EVENT_IDLE = 0, /* the ctrl idle event */ - CTRL_EVENT_SETUP, /* the ctrl setup event */ - CTRL_EVENT_DATA, /* the ctrl data event */ - CTRL_EVENT_STATUS, /* the ctrl status event */ - CTRL_EVENT_COMPLETE, /* the ctrl complete event */ - CTRL_EVENT_ERROR, /* the ctrl error event */ - CTRL_EVENT_STALLED, /* the ctrl stalled event */ -}ctrl_event_enum; - -/* function declarations */ -/* the polling function of control transfer state handle */ -usbh_status_enum ctrl_state_polling_fun (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate); -/* send datas from the host channel */ -usbh_status_enum usbh_xfer (usb_core_handle_struct *pudev, uint8_t *buf, uint8_t hc_num, uint16_t len); -/* send the setup packet to the device */ -usbh_status_enum usbh_ctltx_setup (usb_core_handle_struct *pudev, uint8_t *buf, uint8_t hc_num); -/* this function prepare a hc and start a transfer */ -uint32_t hcd_submit_request (usb_core_handle_struct *pudev, uint8_t channel_num); - -#endif /* USBH_CTRL_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_hcs.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_hcs.h deleted file mode 100644 index 34bdff55b7..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_hcs.h +++ /dev/null @@ -1,46 +0,0 @@ -/*! - \file usbh_hcs.h - \brief header file for usbh_hcs.c -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - -#ifndef USBH_HCS_H -#define USBH_HCS_H - -#include "usbh_core.h" - -#define HC_MAX 8U - -#define HC_OK 0x0000U -#define HC_USED 0x8000U -#define HC_ERROR 0xFFFFU -#define HC_USED_MASK 0x7FFFU - -/* function declarations */ -/* allocate a new channel for the pipe */ -uint8_t usbh_channel_alloc (usb_core_handle_struct *pudev, uint8_t ep_addr); -/* free all usb host channel */ -uint8_t usbh_allchannel_dealloc (usb_core_handle_struct *pudev); -/* free the usb host channel */ -uint8_t usbh_channel_free (usb_core_handle_struct *pudev, uint8_t index); -/* open a channel */ -uint8_t usbh_channel_open (usb_core_handle_struct *pudev, - uint8_t channel_num, - uint8_t dev_addr, - uint8_t dev_speed, - uint8_t ep_type, - uint16_t ep_mps); -/* modify a channel */ -uint8_t usbh_channel_modify (usb_core_handle_struct *pudev, - uint8_t channel_num, - uint8_t dev_addr, - uint8_t dev_speed, - uint8_t ep_type, - uint16_t ep_mps); - -#endif /* USBH_HCS_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_int.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_int.h deleted file mode 100644 index 9fac257295..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_int.h +++ /dev/null @@ -1,30 +0,0 @@ -/*! - \file usbh_int.h - \brief USB host mode interrupt handler header file -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.1, firmware for GD32F4xx -*/ - -#ifndef USBH_INT_H -#define USBH_INT_H - -#include "usb_core.h" - -typedef struct -{ - uint8_t (*sof) (usb_core_handle_struct *pudev); - uint8_t (*device_connected) (usb_core_handle_struct *pudev); - uint8_t (*device_disconnected) (usb_core_handle_struct *pudev); -}usbh_hcd_int_cb_struct; - -extern usbh_hcd_int_cb_struct *usbh_hcd_int_fops; - -/* function declarations */ -/* handle global host interrupt */ -uint32_t usbh_isr (usb_core_handle_struct *pudev); - -#endif /* USBH_INT_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_std.h b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_std.h deleted file mode 100644 index 2dbc45ee30..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Include/usbh_std.h +++ /dev/null @@ -1,74 +0,0 @@ -/*! - \file usbh_std.h - \brief header file for usbh_std.c -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - -#ifndef USBH_STD_H -#define USBH_STD_H - -#include "usbh_core.h" -#include "usbh_usr.h" - -/* standard feature selector for clear feature command */ -#define FEATURE_SELECTOR_ENDPOINT 0x00U -#define FEATURE_SELECTOR_DEVICE 0x01U - -#define USBH_SETUP_PACKET_SIZE 8U /* setup packet size */ -#define ENUM_HANDLE_TABLE_SIZE 10U /* enumerate handle table size */ - -extern uint8_t usbh_cfg_desc[512]; -extern uint8_t enum_polling_handle_flag; -extern state_table_struct enum_handle_table[ENUM_HANDLE_TABLE_SIZE]; - -typedef enum -{ - ENUN_EVENT_IDLE = 0, /* the enum idle event */ - ENUM_EVENT_SET_ADDR, /* the enum set address event */ - ENUN_EVENT_GET_FULL_DEV_DESC, /* the enum get full device descripter event */ - ENUN_EVENT_GET_CFG_DESC, /* the enum get congiguration descripter event */ - ENUN_EVENT_GET_FULL_CFG_DESC, /* the enum get full configuration descripter event */ - ENUN_EVENT_GET_MFC_STRING_DESC, /* the enum get MFC string descripter event */ - ENUN_EVENT_GET_PRODUCT_STRING_DESC, /* the enum get product string event */ - ENUN_EVENT_GET_SERIALNUM_STRING_DESC, /* the enum get serialnum string event */ - ENUN_EVENT_SET_CONFIGURATION, /* the enum set configuration event */ - ENUN_EVENT_DEV_CONFIGURED /* the enum device configured event */ -}enum_event_enum; - -/* function declarations */ -/* the polling function of enumeration state */ -usbh_status_enum enum_state_polling_fun (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate); -/* get descriptor in usb host enumeration stage */ -void usbh_enum_desc_get (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - uint8_t *buf, - uint8_t req_type, - uint16_t value_idx, - uint16_t len); -/* set address in usb host enumeration stage */ -void usbh_enum_addr_set (usb_core_handle_struct *pudev, usbh_host_struct *puhost, uint8_t device_address); -/* set configuration in usb host enumeration stage */ -void usbh_enum_cfg_set (usb_core_handle_struct *pudev, usbh_host_struct *puhost, uint16_t cfg_idx); -/* parse the device descriptor */ -void usbh_device_desc_parse (usb_descriptor_device_struct *dev_desc, uint8_t *buf, uint16_t len); -/* parse the configuration descriptor */ -void usbh_cfg_desc_parse (usb_descriptor_configuration_struct *cfg_desc, - usb_descriptor_interface_struct *itf_desc, - usb_descriptor_endpoint_struct ep_desc[][USBH_MAX_EP_NUM], - uint8_t *buf, - uint16_t len); -/* parse the interface descriptor */ -void usbh_interface_desc_parse (usb_descriptor_interface_struct *itf_desc, uint8_t *buf); -/* parse the endpoint descriptor */ -void usbh_endpoint_desc_parse (usb_descriptor_endpoint_struct *ep_desc, uint8_t *buf); -/* parse the string descriptor */ -void usbh_string_desc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len); -/* get the next descriptor header */ -usb_descriptor_header_struct *usbh_next_desc_get (uint8_t *pbuf, uint16_t *ptr); - -#endif /* USBH_STD_H */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usb_core.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usb_core.c deleted file mode 100644 index 18834acd9e..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usb_core.c +++ /dev/null @@ -1,1132 +0,0 @@ -/*! - \file usb_core.c - \brief USB core driver which can operate in host-mode and device-mode -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - -#include "usb_core.h" - -static void usb_commonint_enable (usb_core_handle_struct *pudev); -static usb_status_enum usb_core_reset (usb_core_handle_struct *pudev); - -/*! - \brief enable the commmon interrupts which are used in both device and host modes - \param[in] pudev: pointer to selected usb device - \param[out] none - \retval none -*/ -static void usb_commonint_enable (usb_core_handle_struct *pudev) -{ -#ifndef USE_OTG_MODE - - /* clear any pending USB interrupts */ - USB_GOTGINTF = 0xFFFFFFFFU; - -#endif /* USE_OTG_MODE */ - - /* enable the usb wakeup and suspend interrupts */ - USB_GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; - -#ifdef USE_OTG_MODE - - /* enable the OTG interrupts, session interrrupts and connector ID pin interrupt */ - USB_GINTEN |= GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE; - -#endif /* USE_OTG_MODE */ -} - -/*! - \brief soft reset of the OTG_FS core - \param[in] pudev: pointer to usb device - \param[out] none - \retval operation status -*/ -static usb_status_enum usb_core_reset (usb_core_handle_struct *pudev) -{ - uint32_t count = 0U; - - /* enable core soft reset */ - USB_GRSTCTL |= GRSTCTL_CSRST; - - /* wait for the core to be soft reset */ - do { - if (++count > 200000U) { - break; - } - } while (1U == (USB_GRSTCTL & GRSTCTL_CSRST)); - - /* wait for addtional 3 PHY clocks */ - if (NULL != pudev->udelay) { - pudev->udelay(3U); - } - - return USB_OK; -} - -/*! - \brief write a packet into the Tx FIFO associated with the endpoint - \param[in] src: pointer to source buffer - \param[in] ep_id: endpoint identifier which is in (0..3) - \param[in] len: packet length - \param[out] none - \retval operation status -*/ -usb_status_enum usb_fifo_write (uint8_t *src, uint8_t ep_id, uint16_t len) -{ - uint32_t count32b = 0U, i = 0U; - __IO uint32_t *fifo = USB_FIFO(ep_id); - - count32b = (len + 3U) / 4U; - - for (i = 0U; i < count32b; i++) { - *fifo = *((__packed uint32_t *)src); - - src += 4U; - } - - return USB_OK; -} - -/*! - \brief read a packet from the Rx FIFO associated with the endpoint - \param[in] dest: pointer to destination buffer - \param[in] len: packet length - \param[out] none - \retval void type pointer -*/ -void *usb_fifo_read (uint8_t *dest, uint16_t len) -{ - uint32_t i = 0U; - uint32_t count32b = (len + 3U) / 4U; - - __IO uint32_t *fifo = USB_FIFO(0U); - - for (i = 0U; i < count32b; i++) { - *(__packed uint32_t *)dest = *fifo; - - dest += 4U; - } - - return ((void *)dest); -} - -/*! - \brief initialize core parameters - \param[in] pudev: pointer to usb device - \param[in] core_id: USB core id - \param[out] none - \retval operation status -*/ -usb_status_enum usb_core_select (usb_core_handle_struct *pudev, usb_core_id_enum core_id) -{ - /* at startup the core is in FS mode */ - pudev->cfg.core_speed = USB_CORE_SPEED_FULL; - pudev->cfg.max_packet_size = USBFS_MAX_PACKET_SIZE; - - pudev->cfg.dma_enable = 0U; - - /* initialize the core parameters */ - if (USB_FS_CORE_ID == core_id) { - pudev->cfg.core_id = USB_FS_CORE_ID; - - /* set the host channel numbers */ - pudev->cfg.host_channel_num = USBFS_MAX_HOST_CHANNELCOUNT; - - /* set the device endpoint numbers */ - pudev->cfg.dev_endp_num = USBFS_MAX_DEV_EPCOUNT; - - /* fifo size is in terms of DWORD */ - pudev->cfg.max_fifo_size = USBFS_MAX_FIFO_WORDLEN; - - /* OTG_FS core use embedded physical layer */ - pudev->cfg.phy_interface = USB_CORE_EMBEDDED_PHY; - -#ifdef USBFS_SOF_OUTPUT_ENABLED - pudev->cfg.sof_output = 1U; -#endif /* USBFS_SOF_OUTPUT_ENABLED */ - -#ifdef USBFS_LOW_PWR_MGMT_SUPPORT - pudev->cfg.low_power = 1U; -#endif /* USBFS_LOW_PWR_MGMT_SUPPORT */ - - } else if (USB_HS_CORE_ID == core_id) { - pudev->cfg.core_id = USB_HS_CORE_ID; - - /* set the host channel numbers */ - pudev->cfg.host_channel_num = USBHS_MAX_HOST_CHANNELCOUNT; - - /* set the device endpoint numbers */ - pudev->cfg.dev_endp_num = USBHS_MAX_DEV_EPCOUNT; - - /* fifo size is in terms of DWORD */ - pudev->cfg.max_fifo_size = USBHS_MAX_FIFO_WORDLEN; - -#ifdef USB_ULPI_PHY_ENABLED - pudev->cfg.phy_interface = USB_CORE_ULPI_PHY; -#elif defined(USB_EMBEDDED_PHY_ENABLED) - pudev->cfg.phy_interface = USB_CORE_EMBEDDED_PHY; -#endif /* USB_ULPI_PHY_ENABLED */ - -#ifdef USBHS_INTERNAL_DMA_ENABLED - pudev->cfg.dma_enable = 1U; -#endif /* USBHS_INTERNAL_DMA_ENABLED */ - -#ifdef USBHS_SOF_OUTPUT_ENABLED - pudev->cfg.sof_output = 1U; -#endif /* USBHS_SOF_OUTPUT_ENABLED */ - -#ifdef USBHS_LOW_PWR_MGMT_SUPPORT - pudev->cfg.low_power = 1U; -#endif /* USBHS_LOW_PWR_MGMT_SUPPORT */ - } else { - /* no operation */ - } - - return USB_OK; -} - -/*! - \brief initializes the USB controller registers and - prepares the core device mode or host mode operation - \param[in] pudev: pointer to usb device - \param[out] none - \retval operation status -*/ -usb_status_enum usb_core_init (usb_core_handle_struct *pudev) -{ - if (USB_CORE_ULPI_PHY == pudev->cfg.phy_interface) { - USB_GCCFG &= ~GCCFG_PWRON; - - if (pudev->cfg.sof_output) { - USB_GCCFG |= GCCFG_SOFOEN; - } - - /* use high-speed interface */ - USB_GUSBCS &= ~GUSBCS_EMBPHY; - - /* use internal over-current indicator */ - USB_GUSBCS &= ~GUSBCS_ULPIEOI; - -#ifdef USBHS_EXTERNAL_VBUS_ENABLED - /* use external VBUS driver */ - USB_GUSBCS |= GUSBCS_ULPIEVD; -#else - /* use internal VBUS driver */ - USB_GUSBCS &= ~GUSBCS_ULPIEVD; -#endif - - /* soft reset the core */ - usb_core_reset(pudev); - } else if (USB_CORE_EMBEDDED_PHY == pudev->cfg.phy_interface) { - if (USB_HS_CORE_ID == pudev->cfg.core_id) { - USB_GUSBCS |= GUSBCS_EMBPHY; - } - - /* soft reset the core */ - usb_core_reset(pudev); - - /* active the transceiver and enable vbus sensing */ - USB_GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; - - /* set Tx FIFO empty level to half empty mode */ - USB_GAHBCS &= ~GAHBCS_TXFTH | TXFIFO_EMPTY_HALF; - -#ifndef VBUS_SENSING_ENABLED - USB_GCCFG |= GCCFG_VBUSIG; -#endif /* VBUS_SENSING_ENABLED */ - - if(pudev->cfg.sof_output){ - USB_GCCFG |= GCCFG_SOFOEN; - } - - if (NULL != pudev->mdelay) { - pudev->mdelay(20U); - } - } else { - /* no operation */ - } - - if (1U == pudev->cfg.dma_enable) { - USB_GAHBCS = DMA_INCR8 | GAHBCS_DMAEN; - } - -#ifdef USE_OTG_MODE - /* enable OTG features */ - USB_GUSBCS |= GUSBCS_HNPCAP | GUSBCS_SRPCAP; - USB_OTG_EnableCommonInt(pudev); - -#endif /* USE_OTG_MODE */ - - return USB_OK; -} - -/*! - \brief flush a Tx FIFO or all Tx FIFOs - \param[in] pudev: pointer to usb device - \param[in] fifo_num: FIFO number which is in (0..3) - \param[out] none - \retval operation status -*/ -usb_status_enum usb_txfifo_flush (usb_core_handle_struct *pudev, uint8_t fifo_num) -{ - uint32_t count = 0U; - - USB_GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF; - - /* wait for Tx FIFO flush bit is set */ - do { - if (++count > 200000U) { - break; - } - } while (USB_GRSTCTL & GRSTCTL_TXFF); - - /* wait for 3 PHY clocks */ - if (NULL != pudev->udelay) { - pudev->udelay(3U); - } - - return USB_OK; -} - -/*! - \brief flush the entire Rx FIFO - \param[in] pudev: pointer to usb device - \param[out] none - \retval operation status -*/ -usb_status_enum usb_rxfifo_flush (usb_core_handle_struct *pudev) -{ - uint32_t count = 0U; - - USB_GRSTCTL = GRSTCTL_RXFF; - - /* wait for Rx FIFO flush bit is set */ - do { - if (++count > 200000U) { - break; - } - } while (USB_GRSTCTL & GRSTCTL_RXFF); - - /* wait for 3 PHY clocks */ - if (NULL != pudev->udelay) { - pudev->udelay(3U); - } - - return USB_OK; -} - -/*! - \brief set operation mode (host or device) - \param[in] pudev: pointer to usb device - \param[in] mode: operation mode which need to set - \arg HOST_MODE - \arg DEVICE_MODE - \param[out] none - \retval operation status -*/ -usb_status_enum usb_mode_set (usb_core_handle_struct *pudev, uint8_t mode) -{ - if (HOST_MODE == mode) { - USB_GUSBCS &= ~GUSBCS_FDM; - USB_GUSBCS |= GUSBCS_FHM; - } else if (DEVICE_MODE == mode) { - USB_GUSBCS &= ~GUSBCS_FHM; - USB_GUSBCS |= GUSBCS_FDM; - } else { - /* no operation */ - } - - if (NULL != pudev->mdelay) { - pudev->mdelay(50U); - } - - return USB_OK; -} - -#ifdef USE_HOST_MODE - -/*! - \brief initializes USB core for host mode - \param[in] pudev: pointer to selected usb host - \param[out] none - \retval operation status -*/ -usb_status_enum usb_hostcore_init (usb_core_handle_struct *pudev) -{ - uint32_t i = 0U; - __IO uint32_t host_nptxfifo_size = 0U; - __IO uint32_t host_ptxfifo_size = 0U; - -#ifdef USE_OTG_MODE - __IO uint32_t OtgCtrl = 0; -#endif /* USE_OTG_MODE */ - - /* restart the PHY clock */ - USB_PWRCLKCTL = 0U; - - /* initialize host configuration register */ - if (USB_CORE_ULPI_PHY == pudev->cfg.phy_interface) { - USB_FSLSCLOCK_INIT(HCTLR_30_60_MHZ); - } else { - USB_FSLSCLOCK_INIT(HCTLR_48_MHZ); - } - - /* configure data FIFO sizes */ -#ifdef USBFS_CORE - if (USB_FS_CORE_ID == pudev->cfg.core_id) { - /* set Rx FIFO size */ - USB_GRFLEN = USBFS_RX_FIFO_SIZE; - - /* set non-periodic Tx FIFO size and address */ - host_nptxfifo_size &= ~HNPTFLEN_HNPTXRSAR; - host_nptxfifo_size |= USBFS_RX_FIFO_SIZE; - host_nptxfifo_size &= ~HNPTFLEN_HNPTXFD; - host_nptxfifo_size |= USBFS_HTX_NPFIFO_SIZE << 16; - USB_HNPTFLEN = host_nptxfifo_size; - - /* set periodic Tx FIFO size and address */ - host_ptxfifo_size &= ~HPTFLEN_HPTXFSAR; - host_ptxfifo_size |= USBFS_RX_FIFO_SIZE + USBFS_HTX_PFIFO_SIZE; - host_ptxfifo_size &= ~HPTFLEN_HPTXFD; - host_ptxfifo_size |= USBFS_HTX_PFIFO_SIZE << 16; - USB_HPTFLEN = host_ptxfifo_size; - } -#endif /* USBFS_CORE */ - -#ifdef USBHS_CORE - if (USB_HS_CORE_ID == pudev->cfg.core_id) { - /* set Rx FIFO size */ - USB_GRFLEN = USBHS_RX_FIFO_SIZE; - - /* set non-periodic Tx FIFO size and address */ - host_nptxfifo_size &= ~HNPTFLEN_HNPTXRSAR; - host_nptxfifo_size |= USBHS_RX_FIFO_SIZE; - host_nptxfifo_size &= ~HNPTFLEN_HNPTXFD; - host_nptxfifo_size |= USBHS_HTX_NPFIFO_SIZE << 16; - USB_HNPTFLEN = host_nptxfifo_size; - - /* set periodic Tx FIFO size and address */ - host_ptxfifo_size &= ~HPTFLEN_HPTXFSAR; - host_ptxfifo_size |= USBHS_RX_FIFO_SIZE + USBHS_HTX_PFIFO_SIZE; - host_ptxfifo_size &= ~HPTFLEN_HPTXFD; - host_ptxfifo_size |= USBHS_HTX_PFIFO_SIZE << 16; - USB_HPTFLEN = host_ptxfifo_size; - } -#endif /* USBHS_CORE */ - -#ifdef USE_OTG_MODE - - /* clear Host Set HNP Enable bit in the USB OTG Control Register */ - OtgCtrl |= GOTGCS_HHNPEN; - USB_GOTGCS &= ~OtgCtrl; - USB_GOTGCS |= 0; - -#endif /* USE_OTG_MODE */ - - /* make sure the FIFOs are flushed */ - - /* flush all Tx FIFOs in device or host mode */ - usb_txfifo_flush(pudev, 0x10U); - - /* flush the entire Rx FIFO */ - usb_rxfifo_flush(pudev); - - /* clear all pending host channel interrupts */ - USB_HACHINTEN &= ~HACHINTEN_CINTEN; - - for (i = 0U; i < pudev->cfg.host_channel_num; i++) { - USB_HCHxINTEN(i) = 0U; - USB_HCHxINTF(i) = 0xFFFFFFFFU; - } - -#ifndef USE_OTG_MODE - usb_vbus_drive(pudev, 1U); -#endif /* USE_OTG_MODE */ - - usb_hostint_enable(pudev); - - return USB_OK; -} - -/*! - \brief control the VBUS to power - \param[in] pudev: pointer to selected usb host - \param[in] state: VBUS state - \param[out] none - \retval none -*/ -void usb_vbus_drive (usb_core_handle_struct *pudev, uint8_t state) -{ - __IO uint32_t host_port = 0U; - - /* enable or disable the external charge pump */ - if ((void *)0 != pudev->host.vbus_drive) { - pudev->host.vbus_drive(pudev, state); - } - - /* turn on the host port power. */ - host_port = USB_PORT_READ(); - - if ((0U == (host_port & HPCS_PP)) && (1U == state)) { - host_port |= HPCS_PP; - } else if ((1U == (host_port & HPCS_PP)) && (0U == state)) { - host_port &= ~HPCS_PP; - } else { - /* no operation */ - } - - USB_HPCS = host_port; - - if (NULL != pudev->mdelay) { - pudev->mdelay(200U); - } -} - -/*! - \brief enables the host mode interrupts - \param[in] pudev: pointer to selected usb host - \param[out] none - \retval operation status -*/ -usb_status_enum usb_hostint_enable (usb_core_handle_struct *pudev) -{ - uint32_t global_int_flag = 0U; - - /* disable all interrupts */ - USB_GINTEN = 0U; - - /* clear any pending interrupts */ - USB_GINTF = 0xFFFFFFFFU; - - /* enable the common interrupts */ - usb_commonint_enable(pudev); - - if (0U == pudev->cfg.dma_enable) { - global_int_flag |= GINTF_RXFNEIF; - } - - /* enable host_mode-related interrupts */ - global_int_flag |= GINTF_HPIF | GINTF_HCIF | GINTF_DISCIF \ - | GINTF_SOF | GINTF_ISOONCIF; - - USB_GINTEN &= ~global_int_flag; - USB_GINTEN |= global_int_flag; - - return USB_OK; -} - -/*! - \brief reset host port - \param[in] pudev: pointer to usb device - \param[out] none - \retval operation status -*/ -uint32_t usb_port_reset (usb_core_handle_struct *pudev) -{ - USB_HPCS = USB_PORT_READ() | HPCS_PRST; - - if (NULL != pudev->mdelay) { - pudev->mdelay(10U); - } - - USB_HPCS &= ~HPCS_PRST; - - if (NULL != pudev->mdelay) { - pudev->mdelay(20U); - } - - return USB_OK; -} - -/*! - \brief initialize host channel - \param[in] pudev: pointer to usb device - \param[in] hc_num: host channel number which is in (0..7) - \param[out] none - \retval operation status -*/ -usb_status_enum usb_hostchannel_init(usb_core_handle_struct *pudev, uint8_t hc_num) -{ - usb_status_enum status = USB_OK; - uint8_t is_low_speed = 0U; - __IO uint32_t host_channel_inten = 0U; - __IO uint32_t host_channel_ctlr = 0U; - - usb_hostchannel_struct *puhc = &pudev->host.host_channel[hc_num]; - - /* clear old interrupt conditions for this host channel */ - USB_HCHxINTF((uint16_t)hc_num) = 0xFFFFFFFFU; - - if (1U == pudev->cfg.dma_enable) { - host_channel_inten |= HCHINTEN_DMAERIE; - } - - /* enable channel interrupts required for this transfer */ - switch (puhc->endp_type) { - case USB_EPTYPE_CTRL: - case USB_EPTYPE_BULK: - host_channel_inten |= HCHINTEN_TFIE | HCHINTEN_STALLIE | HCHINTEN_USBERIE \ - | HCHINTEN_DTERIE | HCHINTEN_NAKIE; - - if (puhc->endp_in) { - host_channel_inten |= HCHINTEN_BBERIE; - } else { - host_channel_inten |= HCHINTEN_NYETIE; - - if (puhc->do_ping) { - host_channel_inten |= HCHINTEN_ACKIE; - } - } - break; - - case USB_EPTYPE_INTR: - host_channel_inten |= HCHINTEN_TFIE | HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \ - | HCHINTEN_NAKIE | HCHINTEN_REQOVRIE; - - if (puhc->endp_in) { - host_channel_inten |= HCHINTEN_BBERIE; - } - break; - - case USB_EPTYPE_ISOC: - host_channel_inten |= HCHINTEN_TFIE | HCHINTEN_REQOVRIE | HCHINTEN_ACKIE; - - if (puhc->endp_in) { - host_channel_inten |= HCHINTEN_USBERIE | HCHINTEN_BBERIE; - } - break; - - default: - break; - } - - USB_HCHxINTEN((uint16_t)hc_num) = host_channel_inten; - - /* enable the top level host channel interrupt */ - USB_HACHINTEN |= 1U << hc_num; - - /* make sure host channel interrupts are enabled */ - USB_GINTEN |= GINTEN_HCIE; - - /* program the hcctlr register */ - host_channel_ctlr = 0U; - - if (HPRT_PRTSPD_LOW_SPEED == puhc->dev_speed) { - is_low_speed = 1U; - } - - host_channel_ctlr |= (uint32_t)puhc->dev_addr << 22U; - host_channel_ctlr |= (uint32_t)puhc->endp_type << 18U; - host_channel_ctlr |= (uint32_t)puhc->endp_id << 11U; - host_channel_ctlr |= (uint32_t)puhc->endp_in << 15U; - host_channel_ctlr |= (uint32_t)is_low_speed << 17U; - host_channel_ctlr |= puhc->endp_mps; - - if (HCCHAR_INTR == puhc->endp_type) { - host_channel_ctlr |= HCHCTL_ODDFRM; - } - - USB_HCHxCTL((uint16_t)hc_num) = host_channel_ctlr; - - return status; -} - -/*! - \brief prepare host channel for transferring packets - \param[in] pudev: pointer to usb device - \param[in] hc_num: host channel number which is in (0..7) - \param[out] none - \retval operation status -*/ -usb_status_enum usb_hostchannel_startxfer(usb_core_handle_struct *pudev, uint8_t hc_num) -{ - usb_status_enum status = USB_OK; - - uint16_t dword_len = 0U; - uint16_t packet_num = 0U; - - __IO uint32_t host_channel_xlen = 0U; - __IO uint32_t host_channel_ctlr = 0U; - - usb_hostchannel_struct *puhc = &pudev->host.host_channel[hc_num]; - - /* compute the expected number of packets associated to the transfer */ - if (puhc->xfer_len > 0U) { - packet_num = ((uint16_t)puhc->xfer_len + puhc->endp_mps - 1U) / puhc->endp_mps; - - if (packet_num > HC_MAX_PACKET_COUNT) { - packet_num = HC_MAX_PACKET_COUNT; - puhc->xfer_len = (uint32_t)(packet_num) * (uint32_t)(puhc->endp_mps); - } - } else { - packet_num = 1U; - } - - if (puhc->endp_in) { - puhc->xfer_len = (uint32_t)(packet_num) * (uint32_t)(puhc->endp_mps); - } - - /* initialize the host channel length register */ - host_channel_xlen &= ~HCHLEN_TLEN; - host_channel_xlen |= puhc->xfer_len; - host_channel_xlen &= ~HCHLEN_PCNT; - host_channel_xlen |= (uint32_t)packet_num << 19U; - host_channel_xlen &= ~HCHLEN_DPID; - host_channel_xlen |= (uint32_t)(puhc->DPID) << 29U; - USB_HCHxLEN((uint16_t)hc_num) = (uint32_t)host_channel_xlen; - - if (1U == pudev->cfg.dma_enable) { - USB_HCHxDMAADDR((uint16_t)hc_num) = (uint32_t)puhc->xfer_buff; - } - - /* set host channel enable */ - host_channel_ctlr = USB_HCHxCTL((uint16_t)hc_num); - - if (1U == USB_EVEN_FRAME()) { - host_channel_ctlr |= HCHCTL_ODDFRM; - } else { - host_channel_ctlr &= ~HCHCTL_ODDFRM; - } - - host_channel_ctlr |= HCHCTL_CEN; - host_channel_ctlr &= ~HCHCTL_CDIS; - USB_HCHxCTL((uint16_t)hc_num) = host_channel_ctlr; - - if (0U == pudev->cfg.dma_enable) { - if ((0U == puhc->endp_in) && (puhc->xfer_len > 0U)) { - dword_len = (uint16_t)(puhc->xfer_len + 3U) / 4U; - - switch (puhc->endp_type) { - /* non-periodic transfer */ - case USB_EPTYPE_CTRL: - case USB_EPTYPE_BULK: - /* check if there is enough space in fifo space */ - if (dword_len > (USB_HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { - /* need to process data in non-periodic transfer fifo empty interrupt */ - USB_GINTEN |= GINTEN_NPTXFEIE; - } - break; - - /* periodic transfer */ - case USB_EPTYPE_INTR: - case USB_EPTYPE_ISOC: - /* check if there is enough space in FIFO space */ - if (dword_len > (USB_HPTFQSTAT & HPTFQSTAT_PTXFS)) { - /* need to process data in periodic transfer fifo empty interrupt */ - USB_GINTEN |= GINTEN_PTXFEIE; - } - break; - - default: - break; - } - - /* write packet into the Tx FIFO. */ - usb_fifo_write(puhc->xfer_buff, hc_num, (uint16_t)puhc->xfer_len); - } - } - - return status; -} - -/*! - \brief halt channel - \param[in] pudev: pointer to usb device - \param[in] hc_num: host channel number which is in (0..7) - \param[out] none - \retval operation status -*/ -usb_status_enum usb_hostchannel_halt(usb_core_handle_struct *pudev, uint8_t hc_num) -{ - uint8_t endp_type = 0U; - __IO uint32_t host_channel_ctrl = USB_HCHxCTL((uint16_t)hc_num); - - host_channel_ctrl |= HCHCTL_CEN | HCHCTL_CDIS; - - endp_type = (uint8_t)((host_channel_ctrl & HCHCTL_EPTYPE) >> 18U); - - /* check for space in the request queue to issue the halt. */ - if ((HCCHAR_CTRL == endp_type) || (HCCHAR_BULK == endp_type)) { - if (0U == (USB_HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { - host_channel_ctrl |= HCHCTL_CDIS; - } - } else { - if (0U == (USB_HPTFQSTAT & HPTFQSTAT_PTXFS)) { - host_channel_ctrl |= HCHCTL_CEN; - } - } - - USB_HCHxCTL((uint16_t)hc_num) = host_channel_ctrl; - - return USB_OK; -} - -/*! - \brief issue a ping token - \param[in] pudev: pointer to usb device - \param[in] hc_num: host channel number which is in (0..7) - \param[out] none - \retval operation status -*/ -usb_status_enum usb_hostchannel_ping(usb_core_handle_struct *pudev, uint8_t hc_num) -{ - uint32_t host_channel_ctrl = 0U; - - USB_HCHxLEN((uint16_t)hc_num) = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U)); - - host_channel_ctrl = USB_HCHxCTL((uint16_t)hc_num); - host_channel_ctrl |= HCHCTL_CEN; - host_channel_ctrl &= ~HCHCTL_CDIS; - - USB_HCHxCTL((uint16_t)hc_num) = host_channel_ctrl; - - return USB_OK; -} - -/*! - \brief stop the USB host and clean up fifos - \param[in] none - \param[out] none - \retval none -*/ -void usb_host_stop(usb_core_handle_struct *pudev) -{ - uint32_t i; - - /* disable all host channel interrupt */ - USB_HACHINTEN = 0U; - USB_HACHINT = 0xFFFFFFFFU; - - /* flush out any leftover queued requests */ - for (i = 0U; i < pudev->cfg.host_channel_num; i++) { - USB_HCHxCTL(i) |= HCHCTL_CEN | HCHCTL_CDIS | HCHCTL_EPDIR; - } - - /* flush the FIFO */ - usb_rxfifo_flush(pudev); - usb_txfifo_flush(pudev, 0x10U); -} - -#endif /* USE_HOST_MODE */ - - -#ifdef USE_DEVICE_MODE - -#ifdef USBFS_CORE - -/* USB endpoint Tx FIFO size */ -static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_DEV_EPCOUNT] = -{ - (uint16_t)TX0_FIFO_FS_SIZE, - (uint16_t)TX1_FIFO_FS_SIZE, - (uint16_t)TX2_FIFO_FS_SIZE, - (uint16_t)TX3_FIFO_FS_SIZE -}; - -#elif defined(USBHS_CORE) - -uint16_t USBHS_TX_FIFO_SIZE[USBHS_MAX_DEV_EPCOUNT] = -{ - (uint16_t)TX0_FIFO_HS_SIZE, - (uint16_t)TX1_FIFO_HS_SIZE, - (uint16_t)TX2_FIFO_HS_SIZE, - (uint16_t)TX3_FIFO_HS_SIZE, - (uint16_t)TX4_FIFO_HS_SIZE, - (uint16_t)TX5_FIFO_HS_SIZE -}; - -#endif /* USBFS_CORE */ - -static usb_status_enum usb_devint_enable(usb_core_handle_struct *pudev); - -/*! - \brief initialize USB core registers for device mode - \param[in] pudev: pointer to usb device - \param[out] none - \retval operation status -*/ -usb_status_enum usb_devcore_init (usb_core_handle_struct *pudev) -{ - uint32_t i, ram_address = 0U; - __IO uint32_t dev_in_ep0_inf = USB_DIEP0TFLEN; - __IO uint32_t dev_in_ep_inf = 0U; - - /* restart the Phy Clock (Maybe don't need to...) */ - USB_PWRCLKCTL = 0U; - - /* config periodic frmae interval to default */ - USB_DCFG &= ~DCFG_EOPFT; - USB_DCFG |= FRAME_INTERVAL_80; - -#ifdef USBFS_CORE - if (USB_FS_CORE_ID == pudev->cfg.core_id) { - /* set full speed PHY */ - USB_DCFG &= ~DCFG_DS; - USB_DCFG |= USB_SPEED_INP_FULL; - - /* set Rx FIFO size */ - USB_GRFLEN &= ~GRFLEN_RXFD; - USB_GRFLEN |= RX_FIFO_FS_SIZE; - - /* set endpoint 0 Tx FIFO length and RAM address */ - dev_in_ep0_inf &= ~DIEP0TFLEN_IEP0TXFD; - dev_in_ep0_inf |= TX0_FIFO_FS_SIZE << 16; - dev_in_ep0_inf &= ~DIEP0TFLEN_IEP0TXRSAR; - dev_in_ep0_inf |= RX_FIFO_FS_SIZE; - - USB_DIEP0TFLEN = dev_in_ep0_inf; - - ram_address = RX_FIFO_FS_SIZE; - - /* set endpoint 1 to 3's Tx FIFO length and RAM address */ - for (i = 1U; i < USBFS_MAX_DEV_EPCOUNT; i++) { - ram_address += USBFS_TX_FIFO_SIZE[i - 1U]; - - dev_in_ep_inf &= ~DIEPTFLEN_IEPTXFD; - dev_in_ep_inf |= (uint32_t)USBFS_TX_FIFO_SIZE[i] << 16U; - dev_in_ep_inf &= ~DIEPTFLEN_IEPTXRSAR; - dev_in_ep_inf |= ram_address; - - USB_DIEPxTFLEN(i) = dev_in_ep_inf; - } - } -#endif /* USBFS_CORE */ - -#ifdef USBHS_CORE - if (USB_HS_CORE_ID == pudev->cfg.core_id) { - USB_DCFG &= ~DCFG_DS; - - if (USB_CORE_EMBEDDED_PHY == pudev->cfg.phy_interface) { - /* set full speed PHY in USB high speed core */ - USB_DCFG |= USB_SPEED_INP_FULL; - } else if (USB_CORE_ULPI_PHY == pudev->cfg.phy_interface) { - USB_DCFG |= USB_SPEED_EXP_HIGH; - } - - /* set Rx FIFO size */ - USB_GRFLEN &= ~GRFLEN_RXFD; - USB_GRFLEN |= RX_FIFO_HS_SIZE; - - /* set endpoint 0 Tx FIFO length and RAM address */ - dev_in_ep0_inf &= ~DIEP0TFLEN_IEP0TXFD; - dev_in_ep0_inf |= TX0_FIFO_HS_SIZE << 16; - dev_in_ep0_inf &= ~DIEP0TFLEN_IEP0TXRSAR; - dev_in_ep0_inf |= RX_FIFO_HS_SIZE; - - USB_DIEP0TFLEN = dev_in_ep0_inf; - - ram_address = RX_FIFO_HS_SIZE; - - /* set endpoint 1 to 3's Tx FIFO length and RAM address */ - for (i = 1; i < USBHS_MAX_DEV_EPCOUNT; i++) { - ram_address += USBHS_TX_FIFO_SIZE[i - 1]; - - dev_in_ep_inf &= ~DIEPTFLEN_IEPTXFD; - dev_in_ep_inf |= USBHS_TX_FIFO_SIZE[i] << 16; - dev_in_ep_inf &= ~DIEPTFLEN_IEPTXRSAR; - dev_in_ep_inf |= ram_address; - - USB_DIEPxTFLEN(i) = dev_in_ep_inf; - } - } -#endif /* USBHS_CORE */ - - /* make sure all FIFOs are flushed */ - - /* flush all Tx FIFOs */ - usb_txfifo_flush(pudev, 0x10U); - - /* flush entire Rx FIFO */ - usb_rxfifo_flush(pudev); - - /* clear all pending device interrupts */ - USB_DIEPINTEN = 0U; - USB_DOEPINTEN = 0U; - USB_DAEPINT = 0xFFFFFFFF; - USB_DAEPINTEN = 0U; - - /* configure all IN/OUT endpoints */ - for (i = 0U; i < pudev->cfg.dev_endp_num; i++) { - if (USB_DIEPxCTL(i) & DIEPCTL_EPEN) { - USB_DIEPxCTL(i) |= DIEPCTL_EPD | DIEPCTL_SNAK; - } else { - USB_DIEPxCTL(i) = 0U; - } - - if (USB_DOEPxCTL(i) & DOEPCTL_EPEN) { - USB_DOEPxCTL(i) |= DOEPCTL_EPD | DOEPCTL_SNAK; - } else { - USB_DOEPxCTL(i) = 0U; - } - - /* set IN/OUT endpoint transfer length to 0 */ - USB_DIEPxLEN(i) = 0U; - USB_DOEPxLEN(i) = 0U; - - /* clear all pending IN/OUT endpoints interrupts */ - USB_DIEPxINTF(i) = 0xFFU; - USB_DOEPxINTF(i) = 0xFFU; - } - - USB_DIEPINTEN |= DIEPINTEN_EPTXFUDEN; - usb_devint_enable(pudev); - - return USB_OK; -} - -/*! - \brief enable the device mode interrupts - \param[in] pudev: pointer to usb device - \param[out] none - \retval status -*/ -static usb_status_enum usb_devint_enable(usb_core_handle_struct *pudev) -{ - uint32_t int_mask = 0U; - - /* disable all interrupts */ - USB_GINTEN = 0U; - - /* clear any pending interrupts */ - USB_GINTF = 0xBFFFFFFFU; - - /* enable the common interrupts */ - usb_commonint_enable(pudev); - - if (0U == pudev->cfg.dma_enable) { - int_mask = GINTEN_RXFNEIE; - } - - /* enable device_mode-related interrupts */ - int_mask |= GINTEN_SPIE | GINTEN_RSTIE | GINTEN_ENUMFIE \ - | GINTEN_IEPIE | GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_ISOONCIE \ - | GINTEN_ISOINCIE; - -#ifdef VBUS_SENSING_ENABLED - int_mask |= GINTEN_SESIE | GINTEN_OTGIE; -#endif /* VBUS_SENSING_ENABLED */ - - USB_GINTEN &= ~int_mask; - USB_GINTEN |= int_mask; - - return USB_OK; -} - -/*! - \brief configures endpoint 0 to receive SETUP packets - \param[in] pudev: pointer to usb device - \param[out] none - \retval none -*/ -void usb_ep0_startout(usb_core_handle_struct *pudev) -{ - __IO uint32_t ep0_xlen = 0U; - - /* set OUT endpoint 0 receive length to 24 bytes */ - ep0_xlen &= ~DOEP0LEN_TLEN; - ep0_xlen |= 8U * 3U; - - /* set OUT endpoint 0 receive length to 1 packet */ - ep0_xlen &= ~DOEP0LEN_PCNT; - ep0_xlen |= 1U << 19; - - /* set SETUP packet count to 3 */ - ep0_xlen &= ~DOEP0LEN_STPCNT; - ep0_xlen |= 3U << 29; - - USB_DOEPxLEN(0U) = ep0_xlen; - - if (1U == pudev->cfg.dma_enable) { - USB_DOEPxDMAADDR(0U) = (uint32_t)&pudev->dev.setup_packet; - - USB_DOEPxCTL(0U) = DOEPCTL_EPEN | DOEPCTL_EPACT; - } -} - -/*! - \brief active remote wakeup signalling - \param[in] pudev: pointer to usb device - \param[out] none - \retval none -*/ -void usb_remotewakeup_active(usb_core_handle_struct *pudev) -{ - __IO uint32_t power_clock; - - if (pudev->dev.remote_wakeup) { - if (1U == (USB_DSTAT & DSTAT_SPST)) { - if (pudev->cfg.low_power) { - /* ungate USB core clock */ - power_clock = USB_PWRCLKCTL; - power_clock &= ~PWRCLKCTL_SHCLK; - power_clock &= ~PWRCLKCTL_SUCLK; - - USB_PWRCLKCTL = power_clock; - } - - /* active remote wakeup signaling */ - USB_DCTL |= DCTL_RWKUP; - - if (pudev->mdelay != (void *)0) { - pudev->mdelay(5U); - } - - USB_DCTL &= ~DCTL_RWKUP; - } - } -} - -/*! - \brief active USB core clock - \param[in] pudev: pointer to usb device - \param[out] none - \retval none -*/ -void usb_clock_ungate(usb_core_handle_struct *pudev) -{ - if (pudev->cfg.low_power) { - __IO uint32_t power_clock; - - if (1U == (USB_DSTAT & DSTAT_SPST)) { - /* un-gate USB core clock */ - power_clock = USB_PWRCLKCTL; - power_clock &= ~PWRCLKCTL_SHCLK; - power_clock &= ~PWRCLKCTL_SUCLK; - - USB_PWRCLKCTL = power_clock; - } - } -} - -/*! - \brief stop the device and clean up fifos - \param[in] pudev: pointer to usb device - \param[out] none - \retval none -*/ -void usb_device_stop (usb_core_handle_struct *pudev) -{ - uint32_t i; - - pudev->dev.status = 1U; - - for (i = 0U; i < pudev->cfg.dev_endp_num; i++) { - USB_DIEPxINTF(i) = 0xFFU; - USB_DOEPxINTF(i) = 0xFFU; - } - - USB_DIEPINTEN = 0U; - USB_DOEPINTEN = 0U; - USB_DAEPINTEN = 0U; - USB_DAEPINT = 0xFFFFFFFFU; - - /* flush the FIFO */ - usb_rxfifo_flush(pudev); - usb_txfifo_flush(pudev, 0x10U); -} -#endif /* USE_DEVICE_MODE */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_core.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_core.c deleted file mode 100644 index 0d15a7950f..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_core.c +++ /dev/null @@ -1,520 +0,0 @@ -/*! - \file usbd_core.c - \brief USB device-mode core driver -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - -#include "usbd_core.h" -#include "usbd_std.h" - -/*! - \brief initailizes the USB device-mode handler stack - \param[in] pudev: pointer to usb device instance - \param[in] core_id: USB core ID - \param[out] none - \retval none -*/ -void usbd_init (usb_core_handle_struct *pudev, usb_core_id_enum core_id) -{ - /* select USB core */ - usb_core_select (pudev, core_id); - - pudev->dev.status = USB_STATUS_DEFAULT; - - /* disable USB global interrupt */ - USB_GLOBAL_INT_DISABLE(); - - /* init the core (common init.) */ - usb_core_init(pudev); - - /* force device mode*/ - usb_mode_set(pudev, DEVICE_MODE); - - /* set device disconnect */ - USB_SOFT_DISCONNECT_ENABLE(); - - if ((void *)0 != pudev->mdelay) { - pudev->mdelay(3U); - } - - /* init device */ - usb_devcore_init(pudev); - - /* set device Connect */ - USB_SOFT_DISCONNECT_DISABLE(); - - if ((void *)0 != pudev->mdelay) { - pudev->mdelay(3U); - } - - /* enable USB global interrupt */ - USB_GLOBAL_INT_ENABLE(); -} - -/*! - \brief endpoint initialization - \param[in] pudev: pointer to usb device instance - \param[in] pep_desc: pointer to usb endpoint descriptor - \param[out] none - \retval none -*/ -void usbd_ep_init (usb_core_handle_struct *pudev, const usb_descriptor_endpoint_struct *pep_desc) -{ - usb_ep_struct *ep; - - uint32_t dev_all_ep_int_en = 0U; - uint32_t dev_ep_ctlr = 0U; - - uint8_t ep_id = pep_desc->bEndpointAddress & 0x7FU; - uint8_t ep_type = pep_desc->bmAttributes & USB_EPTYPE_MASK; - uint16_t ep_mps = pep_desc->wMaxPacketSize; - - if (pep_desc->bEndpointAddress >> 7) { - ep = &pudev->dev.in_ep[ep_id]; - - dev_all_ep_int_en |= 1U << ep_id; - dev_ep_ctlr = USB_DIEPxCTL((uint16_t)ep_id); - - /* if the endpoint is not active, need change the endpoint control register */ - if (!(dev_ep_ctlr & DIEPCTL_EPACT)) { - if (0U == ep_id) { - dev_ep_ctlr &= ~DIEP0CTL_MPL; - } else { - dev_ep_ctlr &= ~DIEPCTL_MPL; - } - dev_ep_ctlr |= ep_mps; - - dev_ep_ctlr &= ~DIEPCTL_EPTYPE; - dev_ep_ctlr |= (uint32_t)ep_type << 18; - - dev_ep_ctlr &= ~DIEPCTL_TXFNUM; - dev_ep_ctlr |= (uint32_t)ep_id << 22; - - if (0U != ep_id) { - dev_ep_ctlr |= DIEPCTL_SD0PID; - dev_ep_ctlr |= DIEPCTL_EPACT; - } - - USB_DIEPxCTL((uint16_t)ep_id) = dev_ep_ctlr; - } - } else { - ep = &pudev->dev.out_ep[ep_id]; - - dev_all_ep_int_en |= (1U << ep_id) << 16; - dev_ep_ctlr = USB_DOEPxCTL((uint16_t)ep_id); - - /* if the endpoint is not active, need change the endpoint control register */ - if (!(dev_ep_ctlr & DOEPCTL_EPACT)) { - if (0U == ep_id) { - dev_ep_ctlr &= ~DOEP0CTL_MPL; - } else { - dev_ep_ctlr &= ~DOEPCTL_MPL; - } - dev_ep_ctlr |= ep_mps; - - dev_ep_ctlr &= ~DOEPCTL_EPTYPE; - dev_ep_ctlr |= (uint32_t)ep_type << 18; - - if (0U != ep_id) { - dev_ep_ctlr |= DOEPCTL_SD0PID; - dev_ep_ctlr |= DOEPCTL_EPACT; - } - - USB_DOEPxCTL((uint16_t)ep_id) = dev_ep_ctlr; - } - } - - ep->endp_mps = ep_mps; - ep->endp_type = ep_type; - - /* enable the interrupts for this endpoint */ -#ifdef USBHS_DEDICATED_EP1_ENABLED - if ((1 == ep_id) && (USB_HS_CORE_ID == pudev->cfg.core_id)) { - USB_DEP1INTEN |= dev_all_ep_int_en; - } else -#endif /* USBHS_DEDICATED_EP1_ENABLED */ - { - USB_DAEPINTEN |= dev_all_ep_int_en; - } -} - -/*! - \brief endpoint deinitialize - \param[in] pudev: pointer to usb device instance - \param[in] ep_addr: endpoint address - \param[out] none - \retval none -*/ -void usbd_ep_deinit (usb_core_handle_struct *pudev, uint8_t ep_addr) -{ - uint32_t dev_all_ep_int_en = 0U; - uint8_t ep_id = ep_addr & 0x7FU; - - if (ep_addr >> 7) { - dev_all_ep_int_en |= 1U << ep_id; - - USB_DIEPxCTL((uint16_t)ep_id) &= ~DIEPCTL_EPACT; - } else { - dev_all_ep_int_en |= (1U << ep_id) << 16U; - - USB_DOEPxCTL((uint16_t)ep_id) &= ~DOEPCTL_EPACT; - } - - /* disable the interrupts for this endpoint */ -#ifdef USBHS_DEDICATED_EP1_ENABLED - if ((1U == ep_id) && (USB_HS_CORE_ID == pudev->cfg.core_id)) { - USB_DEP1INTEN &= ~dev_all_ep_int_en; - } else -#endif /* USBHS_DEDICATED_EP1_ENABLED */ - { - USB_DAEPINTEN &= ~dev_all_ep_int_en; - } -} - -/*! - \brief endpoint prepare to receive data - \param[in] pudev: pointer to usb device instance - \param[in] ep_addr: endpoint address - \param[in] pbuf: pointer to buffer - \param[in] buf_len: buffer length - \param[out] none - \retval none -*/ -void usbd_ep_rx (usb_core_handle_struct *pudev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len) -{ - usb_ep_struct *ep; - uint8_t ep_id = ep_addr & 0x7FU; - uint32_t dev_ep_ctlr = 0U, dev_ep_xlen = 0U; - - ep = &pudev->dev.out_ep[ep_id]; - - /* setup and start the Xfer */ - ep->xfer_buff = pbuf; - ep->xfer_len = buf_len; - ep->xfer_count = 0U; - - if (1U == pudev->cfg.dma_enable) { - ep->dma_addr = (uint32_t)pbuf; - } - - dev_ep_ctlr = USB_DOEPxCTL((uint16_t)ep_id); - dev_ep_xlen = USB_DOEPxLEN((uint16_t)ep_id); - - dev_ep_xlen &= ~DOEPLEN_TLEN; - dev_ep_xlen &= ~DOEPLEN_PCNT; - - /* zero length packet */ - if (0U == ep->xfer_len) { - /* set the transfer length to max packet size */ - dev_ep_xlen |= ep->endp_mps; - - /* set the transfer packet count to 1 */ - dev_ep_xlen |= 1U << 19U; - } else { - if (0U == ep_id) { - /* set the transfer length to max packet size */ - dev_ep_xlen |= ep->endp_mps; - - /* set the transfer packet count to 1 */ - dev_ep_xlen |= 1U << 19U; - } else { - /* configure the transfer size and packet count as follows: - * pktcnt = N - * xfersize = N * maxpacket - */ - dev_ep_xlen |= ((ep->xfer_len + ep->endp_mps - 1U) / ep->endp_mps) << 19U; - dev_ep_xlen |= ((dev_ep_xlen & DOEPLEN_PCNT) >> 19U) * ep->endp_mps; - } - } - - USB_DOEPxLEN((uint16_t)ep_id) = dev_ep_xlen; - - if (1U == pudev->cfg.dma_enable) { - USB_DOEPxDMAADDR((uint16_t)ep_id) = ep->dma_addr; - } - - if (USB_EPTYPE_ISOC == ep->endp_type) { - if (ep->endp_frame) { - dev_ep_ctlr |= DOEPCTL_SODDFRM; - } else { - dev_ep_ctlr |= DOEPCTL_SEVNFRM; - } - } - - /* enable the endpoint and clear the NAK */ - dev_ep_ctlr |= DOEPCTL_EPEN | DOEPCTL_CNAK; - - USB_DOEPxCTL((uint16_t)ep_id) = dev_ep_ctlr; -} - -/*! - \brief endpoint prepare to transmit data - \param[in] pudev: pointer to usb device instance - \param[in] ep_addr: endpoint address - \param[in] pbuf: pointer to buffer - \param[in] len: buffer length - \param[out] none - \retval none -*/ -void usbd_ep_tx (usb_core_handle_struct *pudev, uint8_t ep_addr, uint8_t *pbuf, uint32_t buf_len) -{ - usb_ep_struct *ep; - uint8_t ep_id = ep_addr & 0x7FU; - __IO uint32_t dev_ep_ctlr = 0U; - __IO uint32_t dev_ep_xlen = 0U; - - ep = &pudev->dev.in_ep[ep_id]; - - /* setup and start the transfer */ - ep->xfer_buff = pbuf; - ep->xfer_len = buf_len; - ep->xfer_count = 0U; - - if (1U == pudev->cfg.dma_enable) { - ep->dma_addr = (uint32_t)pbuf; - } - - dev_ep_ctlr = USB_DIEPxCTL((uint16_t)ep_id); - dev_ep_xlen = USB_DIEPxLEN((uint16_t)ep_id); - - /* clear transfer length to 0 */ - dev_ep_xlen &= ~DIEPLEN_TLEN; - - /* clear transfer packet to 0 */ - dev_ep_xlen &= ~DIEPLEN_PCNT; - - /* zero length packet */ - if (0U == ep->xfer_len) { - /* set transfer packet count to 1 */ - dev_ep_xlen |= 1U << 19U; - } else { - if (0U == ep_id) { - if (ep->xfer_len > ep->endp_mps) { - ep->xfer_len = ep->endp_mps; - } - - dev_ep_xlen |= 1U << 19U; - } else { - dev_ep_xlen |= ((ep->xfer_len - 1U + ep->endp_mps) / ep->endp_mps) << 19U; - } - - /* configure the transfer size and packet count as follows: - * xfersize = N * maxpacket + short_packet - * pktcnt = N + (short_packet exist ? 1 : 0) - */ - dev_ep_xlen |= ep->xfer_len; - - if (USB_EPTYPE_ISOC == ep->endp_type) { - dev_ep_xlen |= DIEPLEN_MCNT & (1U << 29U); - } - } - - USB_DIEPxLEN((uint16_t)ep_id) = dev_ep_xlen; - - if (USB_EPTYPE_ISOC == ep->endp_type) { - if (0U == (((USB_DSTAT & DSTAT_FNRSOF) >> 8U) & 0x1U)) { - dev_ep_ctlr |= DIEPCTL_SODDFRM; - } else { - dev_ep_ctlr |= DIEPCTL_SEVNFRM; - } - } - - if (1U == pudev->cfg.dma_enable) { - USB_DIEPxDMAADDR((uint16_t)ep_id) = ep->dma_addr; - } - - /* enable the endpoint and clear the NAK */ - dev_ep_ctlr |= DIEPCTL_EPEN | DIEPCTL_CNAK; - - USB_DIEPxCTL((uint16_t)ep_id) = dev_ep_ctlr; - - if (0U == pudev->cfg.dma_enable) { - if (USB_EPTYPE_ISOC != ep->endp_type) { - /* enable the Tx FIFO empty interrupt for this endpoint */ - if (ep->xfer_len > 0U) { - USB_DIEPFEINTEN |= 1U << ep_id; - } - } else { - usb_fifo_write(ep->xfer_buff, ep_id, (uint16_t)ep->xfer_len); - } - } -} - -/*! - \brief transmit data on the control channel - \param[in] pudev: pointer to usb device instance - \param[in] pbuf: pointer to buffer - \param[in] len: buffer length - \param[out] none - \retval usb device operation status -*/ -usbd_status_enum usbd_ctltx (usb_core_handle_struct *pudev, uint8_t *pbuf, uint16_t len) -{ - usbd_status_enum ret = USBD_OK; - - pudev->dev.sum_len = len; - pudev->dev.remain_len = len; - pudev->dev.ctl_status = USB_CTRL_DATA_IN; - - usbd_ep_tx (pudev, 0U, pbuf, (uint32_t)len); - - return ret; -} - -/*! - \brief receive data on the control channel - \param[in] pudev: pointer to usb device instance - \param[in] pbuf: pointer to buffer - \param[in] len: buffer length - \param[out] none - \retval usb device operation status -*/ -usbd_status_enum usbd_ctlrx (usb_core_handle_struct *pudev, uint8_t *pbuf, uint16_t len) -{ - pudev->dev.sum_len = len; - pudev->dev.remain_len = len; - pudev->dev.ctl_status = USB_CTRL_DATA_OUT; - - usbd_ep_rx (pudev, 0U, pbuf, len); - - return USBD_OK; -} - -/*! - \brief transmit status on the control channel - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval usb device operation status -*/ -usbd_status_enum usbd_ctlstatus_tx (usb_core_handle_struct *pudev) -{ - pudev->dev.ctl_status = USB_CTRL_STATUS_IN; - - usbd_ep_tx (pudev, 0U, NULL, 0U); - - usb_ep0_startout(pudev); - - return USBD_OK; -} - -/*! - \brief receive status on the control channel - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval usb device operation status -*/ -usbd_status_enum usbd_ctlstatus_rx (usb_core_handle_struct *pudev) -{ - pudev->dev.ctl_status = USB_CTRL_STATUS_OUT; - - usbd_ep_rx (pudev, 0U, NULL, 0U); - - usb_ep0_startout(pudev); - - return USBD_OK; -} - -/*! - \brief set an endpoint to STALL status - \param[in] pudev: pointer to usb device instance - \param[in] ep_addr: endpoint address - \param[out] none - \retval none -*/ -void usbd_ep_stall (usb_core_handle_struct *pudev, uint8_t ep_addr) -{ - uint8_t ep_id = ep_addr & 0x7FU; - __IO uint32_t dev_ep_ctlr = 0U; - - if (ep_addr >> 7U) { - dev_ep_ctlr = USB_DIEPxCTL((uint16_t)ep_id); - - /* set the endpoint disable bit */ - if (dev_ep_ctlr & DIEPCTL_EPEN) { - dev_ep_ctlr |= DIEPCTL_EPD; - } - - /* set the endpoint stall bit */ - dev_ep_ctlr |= DIEPCTL_STALL; - - USB_DIEPxCTL((uint16_t)ep_id) = dev_ep_ctlr; - } else { - /* set the endpoint stall bit */ - USB_DOEPxCTL((uint16_t)ep_id) |= DOEPCTL_STALL; - } -} - -/*! - \brief clear endpoint stalled status - \param[in] pudev: pointer to usb device instance - \param[in] ep_addr: endpoint address - \param[out] none - \retval none -*/ -void usbd_ep_clear_stall (usb_core_handle_struct *pudev, uint8_t ep_addr) -{ - usb_ep_struct *ep; - uint8_t ep_id = ep_addr & 0x7FU; - __IO uint32_t dev_ep_ctlr = 0U; - - if(ep_addr >> 7){ - ep = &pudev->dev.in_ep[ep_id]; - - dev_ep_ctlr = USB_DIEPxCTL((uint16_t)ep_id); - - /* clear the IN endpoint stall bits */ - dev_ep_ctlr &= ~DIEPCTL_STALL; - - if ((USB_EPTYPE_INTR == ep->endp_type) || (USB_EPTYPE_BULK == ep->endp_type)) { - dev_ep_ctlr |= DIEPCTL_SEVNFRM; - } - - USB_DIEPxCTL((uint16_t)ep_id) = dev_ep_ctlr; - } else { - ep = &pudev->dev.out_ep[ep_id]; - - dev_ep_ctlr = USB_DOEPxCTL((uint16_t)ep_id); - - /* clear the OUT endpoint stall bits */ - dev_ep_ctlr &= ~DOEPCTL_STALL; - - if ((USB_EPTYPE_INTR == ep->endp_type) || (USB_EPTYPE_BULK == ep->endp_type)) { - dev_ep_ctlr |= DOEPCTL_SEVNFRM; - } - - USB_DOEPxCTL((uint16_t)ep_id) = dev_ep_ctlr; - } -} - -/*! - \brief flushes the FIFOs - \param[in] pudev: pointer to usb device instance - \param[in] ep_addr: endpoint address - \param[out] none - \retval none -*/ -void usbd_ep_fifo_flush (usb_core_handle_struct *pudev, uint8_t ep_addr) -{ - if (ep_addr >> 7) { - usb_txfifo_flush(pudev, ep_addr & 0x7FU); - } else { - usb_rxfifo_flush(pudev); - } -} - -/*! - \brief get the received data length - \param[in] pudev: pointer to usb device instance - \param[in] ep_id: endpoint identifier which is in (0..3) - \param[out] none - \retval received data length -*/ -uint16_t usbd_rxcount_get (usb_core_handle_struct *pudev, uint8_t ep_id) -{ - return (uint16_t)pudev->dev.out_ep[ep_id].xfer_count; -} diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_int.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_int.c deleted file mode 100644 index 01338e2e9b..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_int.c +++ /dev/null @@ -1,758 +0,0 @@ -/*! - \file usbd_int.c - \brief USB device mode interrupt routines -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - -#include "usbd_int.h" -#include "usbd_std.h" - -/* interrupt handlers */ -static uint32_t usbd_intf_outep (usb_core_handle_struct *pudev); -static uint32_t usbd_intf_inep (usb_core_handle_struct *pudev); -static uint32_t usbd_intf_earlysuspend (usb_core_handle_struct *pudev); -static uint32_t usbd_intf_suspend (usb_core_handle_struct *pudev); -static uint32_t usbd_intf_resume (usb_core_handle_struct *pudev); -static uint32_t usbd_intf_sof (usb_core_handle_struct *pudev); -static uint32_t usbd_intf_rxfifo (usb_core_handle_struct *pudev); -static uint32_t usbd_intf_reset (usb_core_handle_struct *pudev); -static uint32_t usbd_intf_enumfinish (usb_core_handle_struct *pudev); -static uint32_t usbd_intf_isoinincomplete (usb_core_handle_struct *pudev); -static uint32_t usbd_intf_isooutincomplete (usb_core_handle_struct *pudev); - -static uint32_t usbd_emptytxfifo_write (usb_core_handle_struct *pudev, uint8_t ep_num); - -#ifdef VBUS_SENSING_ENABLED - - static uint32_t usbd_intf_otg (usb_core_handle_struct *pudev); - static uint32_t usbd_intf_sessionrequest (usb_core_handle_struct *pudev); - -#endif - -static usb_speed_enum USB_SPEED[4] = { - [DSTAT_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ] = USB_SPEED_HIGH, - [DSTAT_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ] = USB_SPEED_FULL, - [DSTAT_ENUMSPD_FS_PHY_48MHZ] = USB_SPEED_FULL, - [DSTAT_ENUMSPD_LS_PHY_6MHZ] = USB_SPEED_LOW -}; - -static const uint8_t EP0_MAXLEN[4] = { - [DSTAT_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ] = EP0MPL_64, - [DSTAT_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ] = EP0MPL_64, - [DSTAT_ENUMSPD_FS_PHY_48MHZ] = EP0MPL_64, - [DSTAT_ENUMSPD_LS_PHY_6MHZ] = EP0MPL_8 -}; - -#ifdef USBHS_DEDICATED_EP1_ENABLED - -/*! - \brief USB dedicated OUT endpoint 1 interrupt service routine handler - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -uint32_t USBD_EP1OUT_ISR_Handler (usb_core_handle_struct *pudev) -{ - uint32_t out_endp_int = 0; - uint32_t out_endp_size = 0; - - out_endp_int = USB_DOEPxINTF(1); - out_endp_int &= USB_DOEP1INTEN; - - /* transfer complete */ - if (out_endp_int & DOEPINTF_TF) { - /* clear the interrupt bit */ - USB_DOEPxINTF(1) = DOEPINTF_TF; - - if (1U == pudev->cfg.dma_enable) { - out_endp_size = USB_DOEPxLEN(1); - - /* handle more than one single MPS size packet */ - pudev->dev.out_ep[1].xfer_count = pudev->dev.out_ep[1].endp_mps - \ - (out_endp_size & DOEPLEN_TLEN); - } - - /* inform upper layer: data ready */ - - /* receive complete */ - usbd_out_transaction(pudev, 1); - } - - /* endpoint disable interrupt */ - if (out_endp_int & DOEPINTF_EPDIS) { - /* clear the interrupt bit */ - USB_DOEPxINTF(1) = DOEPINTF_EPDIS; - } - - return 1; -} - -/*! - \brief USB dedicated IN endpoint 1 interrupt service routine handler - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -uint32_t USBD_EP1IN_ISR_Handler (usb_core_handle_struct *pudev) -{ - uint32_t fifoemptymask = 0, mask = 0; - uint32_t in_endp_int = 0; - - mask = USB_DIEP1INTEN; - mask |= ((USB_DIEPFEINTEN >> 1) & 0x01) << 7; - in_endp_int = USB_DIEPxINTF(1) & mask; - - if (in_endp_int & DIEPINTF_TF) { - fifoemptymask = 0x01 << 1; - USB_DIEPFEINTEN &= ~fifoemptymask; - - USB_DIEPxINTF(1) = DIEPINTF_TF; - - /* transmit complete */ - usbd_in_transaction(pudev , 1); - } - - if (in_endp_int & DIEPINTF_EPDIS) { - USB_DIEPxINTF(1) = DIEPINTF_EPDIS; - } - - if (in_endp_int & DIEPINTF_CITO) { - USB_DIEPxINTF(1) = DIEPINTF_CITO; - } - - if (in_endp_int & DIEPINTF_EPTXFUD) { - USB_DIEPxINTF(1) = DIEPINTF_EPTXFUD; - } - - if (in_endp_int & DIEPINTF_IEPNE) { - USB_DIEPxINTF(1) = DIEPINTF_IEPNE; - } - - if (in_endp_int & DIEPINTF_TXFE) { - usbd_emptytxfifo_write(pudev, 1); - - USB_DIEPxINTF(1) = DIEPINTF_IEPNE; - } - - return 1; -} - -#endif - - -/*! - \brief USB device-mode interrupts global service routine handler - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -uint32_t usbd_isr (usb_core_handle_struct *pudev) -{ - uint32_t retval = 0U; - uint32_t int_status = 0U, gintf = USB_GINTF, ginten = USB_GINTEN; - - /* ensure the core is in device mode */ - if (DEVICE_MODE == USB_CURRENT_MODE_GET()) { - int_status = gintf & ginten; - - /* there are no interrupts, avoid spurious interrupt */ - if (!int_status) { - return 0U; - } - - /* OUT endpoints interrupts */ - if (int_status & GINTF_OEPIF) { - retval |= usbd_intf_outep(pudev); - } - - /* IN endpoints interrupts */ - if (int_status & GINTF_IEPIF) { - retval |= usbd_intf_inep(pudev); - } - - /* mode mismatch interrupt */ - if (int_status & GINTF_MFIF) { - /* clear interrupt */ - USB_GINTF = GINTF_MFIF; - } - - /* early suspend interrupt */ - if (int_status & GINTF_ESP) { - retval |= usbd_intf_earlysuspend(pudev); - } - - /* suspend interrupt */ - if (int_status & GINTF_SP) { - retval |= usbd_intf_suspend(pudev); - } - - /* wakeup interrupt */ - if (int_status & GINTF_WKUPIF) { - retval |= usbd_intf_resume(pudev); - } - - /* start of frame interrupt */ - if (int_status & GINTF_SOF) { - retval |= usbd_intf_sof(pudev); - } - - /* reveive fifo not empty interrupt */ - if (int_status & GINTF_RXFNEIF) { - retval |= usbd_intf_rxfifo(pudev); - } - - /* USB reset interrupt */ - if (int_status & GINTF_RST) { - retval |= usbd_intf_reset(pudev); - } - - /* enumeration has been finished interrupt */ - if (int_status & GINTF_ENUMFIF) { - retval |= usbd_intf_enumfinish(pudev); - } - - /* incomplete synchronization in transfer interrupt*/ - if (int_status & GINTF_ISOINCIF) { - retval |= usbd_intf_isoinincomplete(pudev); - } - - /* incomplete synchronization out transfer interrupt*/ - if (int_status & GINTF_ISOONCIF) { - retval |= usbd_intf_isooutincomplete(pudev); - } - -#ifdef VBUS_SENSING_ENABLED - - /* session request interrupt */ - if (int_status & GINTF_SESIF) { - retval |= usbd_intf_sessionrequest(pudev); - } - - /* OTG mode interrupt */ - if (int_status & GINTF_OTGIF) { - retval |= usbd_intf_otg(pudev); - } -#endif /* VBUS_SENSING_ENABLED */ - } - - return retval; -} - -/*! - \brief indicates that an OUT endpoint has a pending interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbd_intf_outep (usb_core_handle_struct *pudev) -{ - uint8_t endp_num = 0U; - uint32_t endp_intr = 0U; - - __IO uint32_t out_endp_intr = 0U; - - /* read in the device interrupt bits */ - USB_DAOEP_INTR_READ(endp_intr); - - while (endp_intr) { - if (endp_intr & 0x1U) { - USB_DOEP_INTR_READ(out_endp_intr, (uint16_t)endp_num); - - /* transfer complete interrupt */ - if (out_endp_intr & DOEPINTF_TF) { - USB_DOEPxINTF((uint16_t)endp_num) = DOEPINTF_TF; - - if (1U == pudev->cfg.dma_enable) { - uint32_t xfer_size = USB_DOEPxLEN((uint16_t)endp_num) & DOEPLEN_TLEN; - - pudev->dev.out_ep[endp_num].xfer_count = pudev->dev.out_ep[endp_num].endp_mps - \ - xfer_size; - } - - /* data receive is completed */ - usbd_out_transaction(pudev, endp_num); - - if (1U == pudev->cfg.dma_enable) { - if ((0U == endp_num) && (USB_CTRL_STATUS_OUT == pudev->dev.ctl_status)) { - /* prepare to receive more setup packets */ - usb_ep0_startout(pudev); - } - } - } - - /* endpoint disable interrupt */ - if (out_endp_intr & DOEPINTF_EPDIS) { - USB_DOEPxINTF((uint16_t)endp_num) = DOEPINTF_EPDIS; - } - - /* setup phase finished interrupt (just for control endpoints) */ - if (out_endp_intr & DOEPINTF_STPF) { - /* setup phase is completed */ - usbd_setup_transaction(pudev); - - USB_DOEPxINTF((uint16_t)endp_num) = DOEPINTF_STPF; - } - - /* back to back setup packets received */ - if (out_endp_intr & DOEPINTF_BTBSTP) { - USB_DOEPxINTF((uint16_t)endp_num) = DOEPINTF_BTBSTP; - } - } - - endp_num ++; - endp_intr >>= 1; - } - - return 1U; -} - -/*! - \brief indicates that an IN endpoint has a pending interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbd_intf_inep(usb_core_handle_struct *pudev) -{ - uint8_t endp_num = 0U; - uint32_t endp_intr = 0U; - - __IO uint32_t in_endp_intr = 0U; - - /* get all in endpoints which have interrupts */ - USB_DAIEP_INTR_READ(endp_intr); - - while (endp_intr) { - if (endp_intr & 0x1U) { - USB_DIEP_INTR_READ(in_endp_intr, (uint16_t)endp_num); - - if (in_endp_intr & DIEPINTF_TF) { - /* disable the fifo empty interrupt for the endpoint */ - USB_DIEPFEINTEN &= ~(0x1U << endp_num); - - USB_DIEPxINTF((uint16_t)endp_num) = DIEPINTF_TF; - - /* data transmittion is completed */ - usbd_in_transaction(pudev, endp_num); - - if (1U == pudev->cfg.dma_enable) { - if ((0U == endp_num) && (USB_CTRL_STATUS_IN == pudev->dev.ctl_status)) { - /* prepare to receive more setup packets */ - usb_ep0_startout(pudev); - } - } - } - - if (in_endp_intr & DIEPINTF_CITO) { - USB_DIEPxINTF((uint16_t)endp_num) = DIEPINTF_CITO; - } - - if (in_endp_intr & DIEPINTF_IEPNE) { - USB_DIEPxINTF((uint16_t)endp_num) = DIEPINTF_IEPNE; - } - - if (in_endp_intr & DIEPINTF_EPDIS) { - USB_DIEPxINTF((uint16_t)endp_num) = DIEPINTF_EPDIS; - } - - if (in_endp_intr & DIEPINTF_TXFE) { - usbd_emptytxfifo_write(pudev, endp_num); - USB_DIEPxINTF((uint16_t)endp_num) = DIEPINTF_TXFE; - } - } - - endp_num ++; - endp_intr >>= 1; - } - - return 1U; -} - -/*! - \brief indicates that early SUSPEND state has been detected on the USB - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbd_intf_earlysuspend (usb_core_handle_struct *pudev) -{ - USB_GINTEN &= ~GINTEN_ESPIE; - USB_GINTF = GINTF_ESP; - - return 1U; -} - -/*! - \brief indicates that SUSPEND state has been detected on the USB - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbd_intf_suspend(usb_core_handle_struct *pudev) -{ - __IO uint8_t low_power = pudev->cfg.low_power; - __IO uint8_t suspend = (uint8_t)(USB_DSTAT & DSTAT_SPST); - __IO uint8_t is_configured = (pudev->dev.status == USB_STATUS_CONFIGURED)? 1U : 0U; - - pudev->dev.prev_status = pudev->dev.status; - pudev->dev.status = USB_STATUS_SUSPENDED; - - if (low_power && suspend && is_configured) { - /* switch-off the otg clocks */ - USB_PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK; - - /* enter DEEP_SLEEP mode with LDO in low power mode */ - pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); - } - - /* clear interrupt */ - USB_GINTF = GINTF_SP; - - return 1U; -} - -/*! - \brief indicates that the USB controller has detected a resume or remote Wake-up sequence - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbd_intf_resume (usb_core_handle_struct *pudev) -{ - pudev->dev.status = pudev->dev.prev_status; - pudev->dev.status = USB_STATUS_CONFIGURED; - - /* clear interrupt */ - USB_GINTF = GINTF_WKUPIF; - - return 1U; -} - -/*! - \brief handle the SOF interrupts - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbd_intf_sof(usb_core_handle_struct *pudev) -{ -// USBD_DCD_INT_fops->SOF(pudev); - - USB_GINTF = GINTF_SOF; - - return 1U; -} - -/*! - \brief handle the Rx status queue level interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbd_intf_rxfifo (usb_core_handle_struct *pudev) -{ - usb_ep_struct *ep; - uint8_t data_pid = 0U, endp_num = 0U; - uint32_t bcount = 0U; - - /* get the status from the top of the fifo (must be read to a variable) */ - __IO uint32_t rx_status = USB_GRSTATP; - - /* disable the rx fifo non-empty interrupt */ - USB_GINTEN &= ~GINTEN_RXFNEIE; - - endp_num = (uint8_t)(rx_status & GRSTATP_EPNUM); - bcount = (rx_status & GRSTATP_BCOUNT) >> 4U; - data_pid = (uint8_t)((rx_status & GRSTATP_DPID) >> 15U); - - if ((endp_num == 1) && ((*(uint32_t *)0x40040B30 & 0x1FF80000) == 0)) { - *(uint32_t *)0x40040B20 = ((*(uint32_t *)0x40040B20 | 0x08000000) & 0x3FFFFFFF); - } - - ep = &pudev->dev.out_ep[endp_num]; - - switch ((rx_status & GRSTATP_RPCKST) >> 17U) { - case RXSTAT_GOUT_NAK: - if(0U != bcount) { - return 0U; - } - break; - case RXSTAT_DATA_UPDT: - if (bcount > 0U) { - usb_fifo_read(ep->xfer_buff, (uint16_t)bcount); - ep->xfer_buff += bcount; - ep->xfer_count += bcount; - } - break; - case RXSTAT_XFER_COMP: - if (0U != bcount) { - return 0U; - } - break; - case RXSTAT_SETUP_COMP: - if(0U != bcount) { - return 0U; - } - break; - case RXSTAT_SETUP_UPDT: - if ((0U == endp_num) && (8U == bcount) && (DPID_DATA0 == data_pid)) { - /* copy the setup packet received in fifo into the setup buffer in ram */ - usb_fifo_read(pudev->dev.setup_packet, 8U); - - ep->xfer_count += bcount; - } - break; - default: - break; - } - - /* enable the Rx fifo non-empty interrupt */ - USB_GINTEN |= GINTEN_RXFNEIE; - - return 1U; -} - -/*! - \brief handle USB reset interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval status -*/ -static uint32_t usbd_intf_reset(usb_core_handle_struct *pudev) -{ - uint8_t i = 0U; - usb_ep_struct *ep; - - /* clear the remote wakeup signaling */ - USB_DCTL &= ~DCTL_RWKUP; - - /* flush the tx fifo */ - usb_txfifo_flush(pudev, 0U); - - for (i = 0U; i < pudev->cfg.dev_endp_num; i++) { - USB_DIEPxINTF((uint16_t)i) = 0xFFU; - USB_DOEPxINTF((uint16_t)i) = 0xFFU; - } - - /* clear all pending device endpoint interrupts */ - USB_DAEPINT = 0xFFFFFFFF; - - /* enable endpoint 0 interrupts */ - USB_DAEPINTEN &= ~DAEPINTEN_OEPIE; - USB_DAEPINTEN &= ~DAEPINTEN_IEPIE; - USB_DAEPINTEN = (1U << 16) | 1U; - - /* enable out endpoint interrupts */ - USB_DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN | DOEPINTEN_EPDISEN; - -#ifdef USBHS_DEDICATED_EP1_ENABLED - USB_DOEP1INTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN | DOEPINTEN_EPDISEN; -#endif - - /* enable in endpoint interrupts */ - USB_DIEPINTEN = DIEPINTEN_TFEN | DIEPINTEN_CITOEN | DIEPINTEN_EPDISEN; - -#ifdef USBHS_DEDICATED_EP1_ENABLED - USB_DIEP1INTEN = DIEPINTEN_TFEN | DIEPINTEN_CITOEN | DIEPINTEN_EPDISEN; -#endif - - /* reset device address */ - USB_DCFG &= ~DCFG_DAR; - USB_DCFG |= 0U << 4U; - - /* configure endpoint 0 to receive setup packets */ - usb_ep0_startout(pudev); - - /* clear usb reset interrupt */ - USB_GINTF = GINTF_RST; - - /* open EP0 IN */ - ep = &pudev->dev.in_ep[0]; - - USB_DIEPxCTL(0U) &= ~DIEP0CTL_MPL; - USB_DIEPxCTL(0U) &= ~DIEPCTL_EPTYPE; - USB_DIEPxCTL(0U) &= ~DIEPCTL_TXFNUM; - - if (!(USB_DIEPxCTL(0U) & DIEPCTL_EPACT)) { - USB_DIEPxCTL(0U) |= USB_MAX_EP0_SIZE; - USB_DIEPxCTL(0U) |= (USB_EPTYPE_CTRL << 18U); - USB_DIEPxCTL(0U) |= DIEP0CTL_EPACT; - } - - ep->endp_mps = USB_MAX_EP0_SIZE; - ep->endp_type = USB_EPTYPE_CTRL; - - /* open EP0 OUT */ - ep = &pudev->dev.out_ep[0]; - - USB_DOEPxCTL(0U) &= ~DOEP0CTL_MPL; - USB_DOEPxCTL(0U) &= ~DOEPCTL_EPTYPE; - - if (!(USB_DOEPxCTL(0U) & DOEPCTL_EPACT)) { - USB_DOEPxCTL(0U) |= USB_MAX_EP0_SIZE; - USB_DOEPxCTL(0U) |= (USB_EPTYPE_CTRL << 18U); - USB_DOEPxCTL(0U) |= DOEP0CTL_EPACT; - } - - ep->endp_mps = USB_MAX_EP0_SIZE; - ep->endp_type = USB_EPTYPE_CTRL; - - pudev->dev.status = USB_STATUS_DEFAULT; - - return 1U; -} - -/*! - \brief handle enumeration finish interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval status -*/ -static uint32_t usbd_intf_enumfinish(usb_core_handle_struct *pudev) -{ - uint8_t enum_speed = (uint8_t)((USB_DSTAT & DSTAT_ES) >> 1U); - - /* set the max packet size of devie in endpoint based on the enumeration speed */ - USB_DIEPxCTL(0U) |= EP0_MAXLEN[enum_speed]; - - /* clear global IN NAK */ - USB_DCTL &= ~DCTL_CGINAK; - USB_DCTL |= DCTL_CGINAK; - - /* set USB turn-around time based on device speed and PHY interface */ - if (USB_SPEED_HIGH == USB_SPEED[enum_speed]) { - pudev->cfg.core_speed = USB_CORE_SPEED_HIGH; - pudev->cfg.max_packet_size = USBHS_MAX_PACKET_SIZE; - - USB_GUSBCS &= ~GUSBCS_UTT; - USB_GUSBCS |= 0x09U << 10; - } else { - pudev->cfg.core_speed = USB_CORE_SPEED_FULL; - pudev->cfg.max_packet_size = USBFS_MAX_PACKET_SIZE; - - USB_GUSBCS &= ~GUSBCS_UTT; - USB_GUSBCS |= 0x05U << 10; - } - - /* clear interrupt */ - USB_GINTF = GINTF_ENUMFIF; - - return 1U; -} - -/*! - \brief handle the ISO IN incomplete interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval status -*/ -static uint32_t usbd_intf_isoinincomplete(usb_core_handle_struct *pudev) -{ -// USBD_DCD_INT_fops->IsoINIncomplete (pudev); - - /* clear interrupt */ - USB_GINTF = GINTF_ISOINCIF; - - return 1U; -} - -/*! - \brief handle the ISO OUT incomplete interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval status -*/ -static uint32_t usbd_intf_isooutincomplete(usb_core_handle_struct *pudev) -{ -// USBD_DCD_INT_fops->IsoOUTIncomplete (pudev); - - /* clear interrupt */ - USB_GINTF = GINTF_ISOONCIF; - - return 1U; -} - -/*! - \brief check FIFO for the next packet to be loaded - \param[in] pudev: pointer to usb device instance - \param[in] ep_id: endpoint identifier which is in (0..3) - \param[out] none - \retval status -*/ -static uint32_t usbd_emptytxfifo_write(usb_core_handle_struct *pudev, uint8_t ep_num) -{ - uint32_t len = 0U, word_len = 0U; - usb_ep_struct *ep; - - ep = &pudev->dev.in_ep[ep_num]; - len = ep->xfer_len - ep->xfer_count; - - if (len > ep->endp_mps) { - len = ep->endp_mps; - } - - word_len = (len + 3U) / 4U; - - while (((USB_DIEPxTFSTAT((uint16_t)ep_num) & DIEPTFSTAT_IEPTFS) > word_len) && - (ep->xfer_count < ep->xfer_len)) { - /* write the FIFO */ - len = ep->xfer_len - ep->xfer_count; - - if (len > ep->endp_mps) { - len = ep->endp_mps; - } - - word_len = (len + 3U) / 4U; - - usb_fifo_write (ep->xfer_buff, ep_num, (uint16_t)len); - - ep->xfer_buff += len; - ep->xfer_count += len; - } - - return 1U; -} - -#ifdef VBUS_SENSING_ENABLED - -/*! - \brief indicates that the USB_OTG controller has detected a connection - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval status -*/ -static uint32_t usbd_intf_sessionrequest(usb_core_handle_struct *pudev) -{ - pudev->dev.connection_status = 1U; - - /* clear the interrupt bit */ - USB_GINTF = GINTF_SESIF; - - return 1; -} - -/*! - \brief indicates that the USB_OTG controller has detected an OTG event - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval status -*/ -static uint32_t usbd_intf_otg(usb_core_handle_struct *pudev) -{ - if (USB_GOTGINTF & GOTGINTF_SESEND) { - pudev->dev.class_deinit(pudev, 0); - pudev->dev.connection_status = 0; - } - - /* clear OTG interrupt */ - USB_GOTGINTF |= GOTGINTF_SESEND; - - return 1; -} - -#endif /* VBUS_SENSING_ENABLED */ diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_std.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_std.c deleted file mode 100644 index 0ae93e4472..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbd_std.c +++ /dev/null @@ -1,699 +0,0 @@ -/*! - \file usbd_std.c - \brief USB 2.0 standard handler driver -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - -#include "usbd_std.h" -#include "usb_core.h" - -static usbd_status_enum usbd_standard_request (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static usbd_status_enum usbd_device_class_request (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static usbd_status_enum usbd_vendor_request (usb_core_handle_struct *pudev, usb_device_req_struct *req); - -static void usbd_setup_request_parse(usb_core_handle_struct *pudev, usb_device_req_struct *req); - -static void usbd_getdescriptor (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static void usbd_setaddress (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static void usbd_setconfig (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static void usbd_getconfig (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static void usbd_getstatus (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static void usbd_setfeature (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static void usbd_clrfeature (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static void usbd_reserved (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static void usbd_setdescriptor (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static void usbd_getinterface (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static void usbd_setinterface (usb_core_handle_struct *pudev, usb_device_req_struct *req); -static void usbd_synchframe (usb_core_handle_struct *pudev, usb_device_req_struct *req); - -static uint8_t* usbd_device_descriptor_get (usb_core_handle_struct *pudev, uint8_t index, uint16_t *pLen); -static uint8_t* usbd_configuration_descriptor_get (usb_core_handle_struct *pudev, uint8_t index, uint16_t *pLen); -static uint8_t* usbd_string_descriptor_get (usb_core_handle_struct *pudev, uint8_t index, uint16_t *pLen); - -static void (*StandardDeviceRequest[])(usb_core_handle_struct *pudev, usb_device_req_struct *req) = -{ - usbd_getstatus, - usbd_clrfeature, - usbd_reserved, - usbd_setfeature, - usbd_reserved, - usbd_setaddress, - usbd_getdescriptor, - usbd_setdescriptor, - usbd_getconfig, - usbd_setconfig, - usbd_getinterface, - usbd_setinterface, - usbd_synchframe, -}; - -/* get standard descriptor handler */ -static uint8_t* (*standard_descriptor_get[])(usb_core_handle_struct *pudev, uint8_t index, uint16_t *pLen) = -{ - usbd_device_descriptor_get, - usbd_configuration_descriptor_get, - usbd_string_descriptor_get -}; - -/*! - \brief USB setup stage processing - \param[in] pudev: pointer to USB device instance - \param[out] none - \retval USB device operation status -*/ -usbd_status_enum usbd_setup_transaction(usb_core_handle_struct *pudev) -{ - usb_device_req_struct req; - - usbd_setup_request_parse(pudev, &req); - - switch (req.bmRequestType & USB_REQ_MASK) { - /* standard device request */ - case USB_STANDARD_REQ: - usbd_standard_request(pudev, &req); - break; - /* device class request */ - case USB_CLASS_REQ: - usbd_device_class_request(pudev, &req); - break; - /* vendor defined request */ - case USB_VENDOR_REQ: - usbd_vendor_request(pudev, &req); - break; - default: - usbd_ep_stall(pudev, req.bmRequestType & 0x80U); - break; - } - - return USBD_OK; -} - -/*! - \brief data out stage processing - \param[in] pudev: pointer to USB device instance - \param[in] ep_id: endpoint identifier(0..7) - \param[out] none - \retval USB device operation status -*/ -usbd_status_enum usbd_out_transaction (usb_core_handle_struct *pudev, uint8_t endp_num) -{ - usb_ep_struct *ep; - - if (0U == endp_num) { - ep = &pudev->dev.out_ep[0]; - - if (USB_CTRL_DATA_OUT == pudev->dev.ctl_status) { - if (pudev->dev.remain_len > ep->endp_mps) { - pudev->dev.remain_len -= ep->endp_mps; - - if (1U == pudev->cfg.dma_enable) { - /* update buffer location */ - ep->xfer_buff += ep->endp_mps; - } - - usbd_ep_rx (pudev, - 0U, - ep->xfer_buff, - (uint16_t)USB_MIN(pudev->dev.remain_len, ep->endp_mps)); - } else { - if (USB_STATUS_CONFIGURED == pudev->dev.status) { - pudev->dev.class_data_handler(pudev, USBD_RX, 0U); - } - - usbd_ctlstatus_tx(pudev); - } - } - } else if (USB_STATUS_CONFIGURED == pudev->dev.status) { - pudev->dev.class_data_handler(pudev, USBD_RX, endp_num); - } else { - /* no operation */ - } - - return USBD_OK; -} - -/*! - \brief data in stage processing - \param[in] pudev: pointer to USB device instance - \param[in] ep_id: endpoint identifier(0..7) - \param[out] none - \retval USB device operation status -*/ -usbd_status_enum usbd_in_transaction (usb_core_handle_struct *pudev, uint8_t endp_num) -{ - usb_ep_struct *ep; - - if (0U == endp_num) { - ep = &pudev->dev.in_ep[0]; - - if (USB_CTRL_DATA_IN == pudev->dev.ctl_status) { - if (pudev->dev.remain_len > ep->endp_mps) { - pudev->dev.remain_len -= ep->endp_mps; - - if (1U == pudev->cfg.dma_enable) { - /* update buffer location */ - ep->xfer_buff += ep->endp_mps; - } - - usbd_ep_tx (pudev, 0U, ep->xfer_buff, pudev->dev.remain_len); - } else { - /* last packet is MPS multiple, so send ZLP packet */ - if ((pudev->dev.sum_len % ep->endp_mps == 0U) && - (pudev->dev.sum_len >= ep->endp_mps) && - (pudev->dev.sum_len < pudev->dev.ctl_len)) { - usbd_ep_tx (pudev, 0U, NULL, 0U); - pudev->dev.ctl_len = 0U; - } else { - if (USB_STATUS_CONFIGURED == pudev->dev.status) { - pudev->dev.class_data_handler(pudev, USBD_TX, 0U); - } - - usbd_ctlstatus_rx(pudev); - } - } - } - } else if (USB_STATUS_CONFIGURED == pudev->dev.status) { - pudev->dev.class_data_handler(pudev, USBD_TX, endp_num); - } else { - /* no operation */ - } - - return USBD_OK; -} - -/*! - \brief handle USB standard device request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval USB device operation status -*/ -static usbd_status_enum usbd_standard_request (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - /* call device request handle function */ - (*StandardDeviceRequest[req->bRequest])(pudev, req); - - return USBD_OK; -} - -/*! - \brief handle USB device class request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device class request - \param[out] none - \retval USB device operation status -*/ -static usbd_status_enum usbd_device_class_request (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - usbd_status_enum ret = USBD_OK; - - switch (pudev->dev.status) { - case USB_STATUS_CONFIGURED: - if (LOWBYTE(req->wIndex) <= USBD_ITF_MAX_NUM) { - ret = (usbd_status_enum)(pudev->dev.class_req_handler(pudev, req)); - - if ((0U == req->wLength) && (USBD_OK == ret)) { - /* no data stage */ - usbd_ctlstatus_tx(pudev); - } - } else { - usbd_enum_error(pudev, req); - } - break; - - default: - usbd_enum_error(pudev, req); - break; - } - - return ret; -} - -/*! - \brief handle USB vendor request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB vendor request - \param[out] none - \retval USB device operation status -*/ -static usbd_status_enum usbd_vendor_request (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - /* added by user... */ - - return USBD_OK; -} - -/*! - \brief no operation, just for reserved - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_reserved (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - /* no operation... */ -} - -/*! - \brief get the device descriptor - \brief[in] index: no use - \param[in] none - \param[out] pLen: data length pointer - \retval descriptor buffer pointer -*/ -static uint8_t* usbd_device_descriptor_get (usb_core_handle_struct *pudev, uint8_t index, uint16_t *pLen) -{ - *pLen = pudev->dev.dev_desc[0]; - - return pudev->dev.dev_desc; -} - -/*! - \brief get the configuration descriptor - \brief[in] index: no use - \param[in] none - \param[out] pLen: data length pointer - \retval descriptor buffer pointer -*/ -static uint8_t* usbd_configuration_descriptor_get (usb_core_handle_struct *pudev, uint8_t index, uint16_t *pLen) -{ - *pLen = pudev->dev.config_desc[2]; - - return pudev->dev.config_desc; -} - -/*! - \brief get string descriptor - \param[in] index: string descriptor index - \param[in] pLen: pointer to string length - \param[out] none - \retval none -*/ -static uint8_t* usbd_string_descriptor_get (usb_core_handle_struct *pudev, uint8_t index, uint16_t *pLen) -{ - uint8_t *desc = pudev->dev.strings[index]; - - *pLen = desc[0]; - - return desc; -} - -/*! - \brief handle Get_Status request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_getstatus (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ -} - -/*! - \brief handle USB Clear_Feature request - \param[in] pudev: pointer to USB device instance - \param[in] req: USB device request - \param[out] none - \retval none -*/ -static void usbd_clrfeature (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - uint8_t ep_addr = 0U; - - switch (req->bmRequestType & USB_REQTYPE_MASK) { - case USB_REQTYPE_DEVICE: - switch (pudev->dev.status) { - case USB_STATUS_ADDRESSED: - case USB_STATUS_CONFIGURED: - if (USB_FEATURE_REMOTE_WAKEUP == req->wValue) { - pudev->dev.remote_wakeup = 0U; - pudev->dev.class_req_handler(pudev, req); - - usbd_ctlstatus_tx(pudev); - } - break; - - default: - usbd_enum_error(pudev, req); - break; - } - break; - case USB_REQTYPE_INTERFACE: - switch (pudev->dev.status) { - case USB_STATUS_ADDRESSED: - usbd_enum_error(pudev, req); - break; - case USB_STATUS_CONFIGURED: - if (LOWBYTE(req->wIndex) <= USBD_ITF_MAX_NUM) { - /* no operation */ - } else { - usbd_enum_error(pudev, req); - } - break; - default: - break; - } - break; - case USB_REQTYPE_ENDPOINT: - ep_addr = LOWBYTE(req->wIndex); - - switch (pudev->dev.status) { - case USB_STATUS_ADDRESSED: - if (IS_NOT_EP0(ep_addr)) { - usbd_ep_stall(pudev, ep_addr); - } - break; - case USB_STATUS_CONFIGURED: - if (USB_FEATURE_ENDP_HALT == req->wValue) { - if (IS_NOT_EP0(ep_addr)) { - usbd_ep_clear_stall(pudev, ep_addr); - - pudev->dev.class_req_handler(pudev, req); - } - } - usbd_ctlstatus_tx(pudev); - break; - default: - break; - } - break; - default: - usbd_enum_error(pudev, req); - break; - } -} - -/*! - \brief handle USB Set_Feature request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_setfeature (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - uint8_t ep_addr = 0U; - __IO uint32_t DctlrStatus; - - switch (req->bmRequestType & USB_REQ_MASK) { - case USB_REQTYPE_DEVICE: - switch (pudev->dev.status) { - case USB_STATUS_ADDRESSED: - case USB_STATUS_CONFIGURED: - if (USB_FEATURE_REMOTE_WAKEUP == req->wValue) { - pudev->dev.remote_wakeup = 1U; - pudev->dev.class_req_handler(pudev, req); - - usbd_ctlstatus_tx(pudev); - } else if ((req->wValue == USB_FEATURE_TEST_MODE) && - (0U == (req->wIndex & 0xFFU))) { - DctlrStatus = USB_DCTL; - - usbd_ctlstatus_tx(pudev); - } else { - /* no operation */ - } - break; - default: - break; - } - break; - case USB_REQTYPE_INTERFACE: - switch (pudev->dev.status) { - case USB_STATUS_ADDRESSED: - usbd_enum_error(pudev, req); - break; - case USB_STATUS_CONFIGURED: - if (LOWBYTE(req->wIndex) <= USBD_ITF_MAX_NUM) { - /* no operation */ - } else { - usbd_enum_error(pudev, req); - } - break; - default: - break; - } - break; - case USB_REQTYPE_ENDPOINT: - switch (pudev->dev.status) { - case USB_STATUS_ADDRESSED: - if (IS_NOT_EP0(ep_addr)) { - usbd_ep_stall(pudev, ep_addr); - } - break; - case USB_STATUS_CONFIGURED: - if (USB_FEATURE_ENDP_HALT == req->wValue) { - if (IS_NOT_EP0(ep_addr)) { - usbd_ep_stall(pudev, ep_addr); - } - } - pudev->dev.class_req_handler(pudev, req); - - usbd_ctlstatus_tx(pudev); - break; - default: - break; - } - break; - default: - usbd_enum_error(pudev, req); - break; - } -} - -/*! - \brief handle USB Set_Address request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_setaddress (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - uint8_t DevAddr; - - if ((0U == req->wIndex) && (0U == req->wLength)) { - DevAddr = (uint8_t)(req->wValue) & 0x7FU; - - if (USB_STATUS_CONFIGURED == pudev->dev.status) { - usbd_enum_error(pudev, req); - } else { - USB_SET_DEVADDR((uint32_t)DevAddr); - - usbd_ctlstatus_tx(pudev); - - if (0U != DevAddr) { - pudev->dev.status = USB_STATUS_ADDRESSED; - } else { - pudev->dev.status = USB_STATUS_DEFAULT; - } - } - } else { - usbd_enum_error(pudev, req); - } -} - -/*! - \brief handle USB Get_Descriptor request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_getdescriptor (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - if (USB_REQTYPE_DEVICE == (req->bmRequestType & USB_REQTYPE_MASK)) { - uint8_t desc_index = (uint8_t)(req->wValue >> 8U); - - if (desc_index <= 0x03U) { - uint16_t len; - uint8_t *pbuf; - - /* call corresponding descriptor get function */ - pbuf = standard_descriptor_get[desc_index - 1U](pudev, (uint8_t)(req->wValue) & 0xFFU, &len); - - if ((0U != len) && (0U != req->wLength)) { - len = USB_MIN(len, req->wLength); - - if ((1U == desc_index) && (64U == req->wLength)) { - len = 8U; - } - - usbd_ctltx(pudev, pbuf, len); - } - } else { - usbd_enum_error(pudev, req); - } - } else if (USB_REQTYPE_INTERFACE == (req->bmRequestType & USB_REQTYPE_MASK)) { - pudev->dev.class_req_handler(pudev, req); - } else { - /* no operation */ - } -} - -/*! - \brief handle USB Set_Descriptor request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_setdescriptor (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - /* no handle... */ -} - -/*! - \brief handle USB Get_Configuration request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_getconfig (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - uint32_t USBD_default_config = 0U; - - if (1U != req->wLength) { - usbd_enum_error(pudev, req); - } else { - switch (pudev->dev.status) { - case USB_STATUS_ADDRESSED: - usbd_ctltx(pudev, (uint8_t *)&USBD_default_config, 1U); - break; - case USB_STATUS_CONFIGURED: - usbd_ctltx(pudev, &pudev->dev.config_num, 1U); - break; - default: - usbd_enum_error(pudev, req); - break; - } - } -} - -/*! - \brief handle USB Set_Configuration request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_setconfig (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - static uint8_t cfgidx; - - cfgidx = (uint8_t)(req->wValue); - - if (cfgidx > USBD_CFG_MAX_NUM) { - usbd_enum_error(pudev, req); - } else { - switch (pudev->dev.status) { - case USB_STATUS_ADDRESSED: - if (cfgidx) { - pudev->dev.config_num = cfgidx; - pudev->dev.status = USB_STATUS_CONFIGURED; - pudev->dev.class_init(pudev, cfgidx); - } - - usbd_ctlstatus_tx(pudev); - break; - case USB_STATUS_CONFIGURED: - if (0U == cfgidx) { - pudev->dev.status = USB_STATUS_ADDRESSED; - pudev->dev.config_num = cfgidx; - pudev->dev.class_deinit(pudev, cfgidx); - } else if (cfgidx != pudev->dev.config_num) { - /* clear old configuration */ - pudev->dev.class_deinit(pudev, pudev->dev.config_num); - - /* set new configuration */ - pudev->dev.config_num = cfgidx; - pudev->dev.class_init(pudev, cfgidx); - } else { - /* no operation */ - } - - usbd_ctlstatus_tx(pudev); - break; - default: - usbd_enum_error(pudev, req); - break; - } - } -} - -/*! - \brief handle USB Get_Interface request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_getinterface (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - pudev->dev.class_req_handler(pudev, req); -} - -/*! - \brief handle USB Set_Interface request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_setinterface (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - pudev->dev.class_req_handler(pudev, req); -} - -/*! - \brief handle USB SynchFrame request - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_synchframe (usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - /* no handle... */ -} - -/*! - \brief decode setup data packet - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -static void usbd_setup_request_parse(usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - uint8_t *psetup = pudev->dev.setup_packet; - - req->bmRequestType = *psetup; - req->bRequest = *(uint8_t *)(psetup + 1U); - req->wValue = SWAPBYTE (psetup + 2U); - req->wIndex = SWAPBYTE (psetup + 4U); - req->wLength = SWAPBYTE (psetup + 6U); - - pudev->dev.ctl_len = req->wLength; -} - -/*! - \brief handle USB low level error event - \param[in] pudev: pointer to USB device instance - \param[in] req: pointer to USB device request - \param[out] none - \retval none -*/ -void usbd_enum_error(usb_core_handle_struct *pudev, usb_device_req_struct *req) -{ - usbd_ep_stall(pudev, 0x80U); - usbd_ep_stall(pudev, 0x00U); - usb_ep0_startout(pudev); -} diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_core.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_core.c deleted file mode 100644 index 1c90b55187..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_core.c +++ /dev/null @@ -1,710 +0,0 @@ -/*! - \file usbh_core.c - \brief this file implements the functions for the core state machine process -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - -#include "usbh_hcs.h" -#include "usbh_core.h" -#include "usbh_int.h" -#include "stdio.h" -#include "usbh_std.h" -#include "usbh_ctrl.h" -#include "usb_core.h" - -extern class_polling_fun_cb_struct class_polling_cb; - -uint8_t usbh_sof (usb_core_handle_struct *pudev); -uint8_t usbh_connected (usb_core_handle_struct *pudev); -uint8_t usbh_disconnected (usb_core_handle_struct *pudev); - -usbh_hcd_int_cb_struct usbh_hcd_int_cb = -{ - usbh_sof, - usbh_connected, - usbh_disconnected, -}; - -usbh_hcd_int_cb_struct *usbh_hcd_int_fops = &usbh_hcd_int_cb; -extern usbh_state_handle_struct usbh_state_core; - -static void host_idle_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void host_dev_attached_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void host_dev_detached_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void host_detect_dev_speed_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void host_enum_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void host_class_request_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void host_class_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void host_user_input_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void host_suspended_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void host_error_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); - -static usbh_status_enum class_req_state_polling_fun (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate); -static usbh_status_enum class_state_polling_fun (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate); - -/* the host state handle function array */ -void (*host_state_handle[]) (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate) = -{ - host_idle_handle, - host_dev_attached_handle, - host_dev_detached_handle, - host_detect_dev_speed_handle, - host_enum_handle, - host_class_request_handle, - host_class_handle, - host_user_input_handle, - host_suspended_handle, - host_error_handle, -}; - -/* the host state handle table */ -state_table_struct host_handle_table[HOST_HANDLE_TABLE_SIZE] = -{ - /* the current state the current event the next state the event function */ - {HOST_IDLE, HOST_EVENT_ATTACHED, HOST_DEV_ATTACHED, only_state_move }, - {HOST_DEV_ATTACHED, HOST_EVENT_ENUM, HOST_ENUMERATION, only_state_move }, - {HOST_ENUMERATION, HOST_EVENT_USER_INPUT, HOST_USER_INPUT, only_state_move }, - {HOST_USER_INPUT, HOST_EVENT_CLASS_REQ, HOST_CLASS_REQUEST, only_state_move }, - {HOST_CLASS_REQUEST, HOST_EVENT_CLASS, HOST_CLASS, only_state_move }, - {HOST_CLASS, HOST_EVENT_ERROR, HOST_ERROR, only_state_move }, - {HOST_ERROR, HOST_EVENT_IDLE, HOST_IDLE, only_state_move }, - {HOST_DEV_DETACHED, HOST_EVENT_IDLE, HOST_IDLE, only_state_move }, - {HOST_CLASS_REQUEST, HOST_EVENT_ERROR, HOST_ERROR, only_state_move }, -}; - -/*! - \brief the polling function of HOST state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -usbh_status_enum host_state_polling_fun (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - void *pustate) -{ - usbh_state_handle_struct *p_state = (usbh_state_handle_struct *)pustate; - - scd_begin(p_state, HOST_FSM_ID); - - if (-1 == p_state->usbh_current_state_stack_top) { - uint8_t cur_state = p_state->usbh_current_state; - - if ((0U == hcd_is_device_connected(pudev)) && (HOST_IDLE != cur_state)) { - if (HOST_DEV_DETACHED != cur_state) { - p_state->usbh_current_state = HOST_DEV_DETACHED; - cur_state = HOST_DEV_DETACHED; - } - } - - host_state_handle[cur_state](pudev, puhost, p_state); - } else { - uint8_t stack0_state = p_state->stack[0].state; - - if ((0U == hcd_is_device_connected(pudev)) && (HOST_IDLE != stack0_state)) { - if (HOST_DEV_DETACHED != stack0_state) { - p_state->stack[0].state = HOST_DEV_DETACHED; - stack0_state = HOST_DEV_DETACHED; - p_state->usbh_current_state = HOST_DEV_DETACHED; - } - } - - host_state_handle[stack0_state](pudev, puhost, p_state); - } - - return USBH_OK; -} - -/*! - \brief the handle function of HOST_IDLE state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void host_idle_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - if (hcd_is_device_connected(pudev)) { - scd_event_handle(pudev, puhost, pustate, HOST_EVENT_ATTACHED, pustate->usbh_current_state); - - if ((void *)0 != pudev->mdelay) { - pudev->mdelay(100U); - } - } -} - -/*! - \brief the handle function of HOST_DEV_ATTACHED state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void host_dev_attached_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usr_cb->device_connected(); - puhost->control.hc_out_num = usbh_channel_alloc(pudev, 0x00U); - puhost->control.hc_in_num = usbh_channel_alloc(pudev, 0x80U); - - /* reset usb device */ - if (0U == usb_port_reset(pudev)) { - puhost->usr_cb->device_reset(); - - /* wait for USB USBH_ISR_PrtEnDisableChange() - * host is now ready to start the enumeration - */ - puhost->device.speed = (uint8_t)USB_CURRENT_SPEED_GET(); - puhost->usr_cb->device_speed_detected(puhost->device.speed); - - /* open IN control pipes */ - usbh_channel_open (pudev, - puhost->control.hc_in_num, - puhost->device.address, - puhost->device.speed, - USB_EPTYPE_CTRL, - (uint16_t)puhost->control.ep0_size); - - /* open OUT control pipes */ - usbh_channel_open (pudev, - puhost->control.hc_out_num, - puhost->device.address, - puhost->device.speed, - USB_EPTYPE_CTRL, - (uint16_t)puhost->control.ep0_size); - - scd_event_handle(pudev, puhost, pustate, HOST_EVENT_ENUM, pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of HOST_ENUMERATION state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void host_enum_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - if (USBH_OK == enum_state_polling_fun(pudev, puhost, pustate)) { - puhost->usr_cb->enumeration_finish(); - scd_event_handle(pudev, - puhost, - pustate, - HOST_EVENT_USER_INPUT, - pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of HOST_USER_INPUT state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void host_user_input_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - if (USBH_USER_RESP_OK == puhost->usr_cb->user_input()) { - if (USBH_OK == (puhost->class_init(pudev, puhost))) { - scd_event_handle(pudev, - puhost, - pustate, - HOST_EVENT_CLASS_REQ, - pustate->usbh_current_state); - } - } -} - -/*! - \brief the handle function of HOST_CLASS_REQUEST state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void host_class_request_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - if (USBH_OK == class_req_state_polling_fun(pudev, puhost, pustate)) { - scd_event_handle(pudev, puhost, pustate, HOST_EVENT_CLASS, pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of HOST_CLASS state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void host_class_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - class_state_polling_fun(pudev, puhost, pustate); -} - -/*! - \brief the handle function of HOST_SUSPENDED state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void host_suspended_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - /* no operation */ -} - -/*! - \brief the handle function of HOST_ERROR state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void host_error_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - /* re-initilaize host for new enumeration */ - usbh_deinit (pudev, puhost,&usbh_state_core); - puhost->usr_cb->deinit(); - puhost->class_deinit(pudev, &puhost->device); - scd_event_handle(pudev, puhost, pustate, HOST_EVENT_IDLE, pustate->usbh_current_state); -} - -/*! - \brief the handle function of HOST_DEV_DETACHED state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void host_dev_detached_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - /* manage user disconnect operations*/ - puhost->usr_cb->device_disconnected(); - - /* re-initilaize host for new enumeration */ - usbh_deinit(pudev, puhost,&usbh_state_core); - puhost->usr_cb->deinit(); - puhost->class_deinit(pudev, &puhost->device); - usbh_allchannel_dealloc(pudev); - scd_event_handle(pudev, puhost, pustate, HOST_EVENT_IDLE, pustate->usbh_current_state); -} - -/*! - \brief the handle function of HOST_DETECT_DEV_SPEED state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void host_detect_dev_speed_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - /* no operation */ -} - -/*! - \brief usb connect callback function from the interrupt. - \param[in] pudev: pointer to usb device - \param[out] none - \retval operation status -*/ -uint8_t usbh_connected (usb_core_handle_struct *pudev) -{ - pudev->host.connect_status = 1U; - - return 0U; -} - -/*! - \brief usb disconnect callback function from the interrupt. - \param[in] pudev: pointer to usb device - \param[out] none - \retval operation status -*/ -uint8_t usbh_disconnected (usb_core_handle_struct *pudev) -{ - pudev->host.connect_status = 0U; - - return 0U; -} - -/*! - \brief usb sof callback function from the interrupt. - \param[in] pudev: pointer to usb device - \param[out] none - \retval operation status -*/ -uint8_t usbh_sof (usb_core_handle_struct *pudev) -{ - /* this callback could be used to implement a scheduler process */ - return 0U; -} - -/*! - \brief initialize the host portion of the driver. - \param[in] pudev: pointer to usb device - \param[in] core_id: usb otg core identifier(high-speed or full-speed) - \param[out] none - \retval operation status -*/ -uint32_t hcd_init(usb_core_handle_struct *pudev, usb_core_id_enum core_id) -{ - pudev->host.connect_status = 0U; - - pudev->host.host_channel[0].endp_mps = 8U; - - usb_core_select(pudev, core_id); - -#ifndef DUAL_ROLE_MODE_ENABLED - - USB_GLOBAL_INT_DISABLE(); - - usb_core_init(pudev); - - /* force host mode*/ - usb_mode_set(pudev, HOST_MODE); - - usb_hostcore_init(pudev); - - USB_GLOBAL_INT_ENABLE(); - -#endif - - return 0U; -} - -/*! - \brief check if the device is connected. - \param[in] pudev: pointer to usb device - \param[out] none - \retval device connection status. 1 -> connected and 0 -> disconnected -*/ -uint32_t hcd_is_device_connected(usb_core_handle_struct *pudev) -{ - return (uint32_t)(pudev->host.connect_status); -} - -/*! - \brief this function returns the last URBstate - \param[in] pudev: pointer to usb device - \param[in] channel_num: host channel number which is in (0..7) - \param[out] none - \retval urb_state_enum -*/ -urb_state_enum hcd_urb_state_get (usb_core_handle_struct *pudev, uint8_t channel_num) -{ - return pudev->host.host_channel[channel_num].urb_state; -} - -/*! - \brief this function returns the last URBstate - \param[in] pudev: pointer to usb device - \param[in] channel_num: host channel number which is in (0..7) - \param[out] none - \retval No. of data bytes transferred -*/ -uint32_t hcd_xfer_count_get (usb_core_handle_struct *pudev, uint8_t channel_num) -{ - return pudev->host.host_channel[channel_num].xfer_count; -} - -/*! - \brief de-initialize host - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[out] none - \retval host status -*/ -usbh_status_enum usbh_deinit(usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct* pustate) -{ - /* software init */ - - puhost->control.ep0_size = USB_MAX_EP0_SIZE; - - puhost->device.address = USBH_DEVICE_ADDRESS_DEFAULT; - puhost->device.speed = HPRT_PRTSPD_FULL_SPEED; - - usbh_channel_free(pudev, puhost->control.hc_in_num); - usbh_channel_free(pudev, puhost->control.hc_out_num); - - scd_init(pustate); - scd_table_regist(pustate, host_handle_table, HOST_FSM_ID, HOST_HANDLE_TABLE_SIZE); - scd_table_regist(pustate, enum_handle_table, ENUM_FSM_ID, ENUM_HANDLE_TABLE_SIZE); - scd_table_regist(pustate, ctrl_handle_table, CTRL_FSM_ID, CTRL_HANDLE_TABLE_SIZE); - - scd_begin(pustate,HOST_FSM_ID); - scd_state_move(pustate, HOST_IDLE); - - return USBH_OK; -} - -/*! - \brief state core driver init - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -void scd_init(usbh_state_handle_struct* pustate) -{ - /* init the state core */ - pustate->usbh_current_state = 0U; - pustate->usbh_current_state_table = NULL; - pustate->usbh_current_state_table_size = 0U; - - pustate->usbh_current_state_stack_top = -1; - pustate->stack->state = 0U; - pustate->stack->table_size = 0U; - pustate->stack->table = NULL; - - pustate->usbh_regist_state_table_num = 0U; - pustate->usbh_regist_state_table->table = NULL; - pustate->usbh_regist_state_table->table_size = 0U; - pustate->usbh_regist_state_table->id = 0U; - - /* init the control and the enumeration polling handle flag */ - ctrl_polling_handle_flag = 0U; - enum_polling_handle_flag = 0U; -} - -/*! - \brief state core driver table regist - \param[in] pustate: pointer to usb state driver - \param[in] pstate_table: pointer to the table to regist - \param[in] table_id: the id of the table to regist - \param[in] current_table_size: the size of the current table to regist - \param[out] none - \retval none -*/ -void scd_table_regist (usbh_state_handle_struct* pustate, - state_table_struct* pstate_table, - uint8_t table_id, - uint8_t current_table_size) -{ - usbh_state_regist_table_struct *cur_state_reg_table; - - cur_state_reg_table = &pustate->usbh_regist_state_table[pustate->usbh_regist_state_table_num]; - - cur_state_reg_table->id = table_id; - cur_state_reg_table->table = pstate_table; - cur_state_reg_table->table_size = current_table_size; - - pustate->usbh_regist_state_table_num++; -} - -/*! - \brief state core driver begin - \param[in] pustate: pointer to usb state driver - \param[in] table_id: the id of the table to begin - \param[out] none - \retval none -*/ -void scd_begin(usbh_state_handle_struct* pustate, uint8_t table_id) -{ - uint8_t i = 0, table_num = pustate->usbh_regist_state_table_num; - usbh_state_regist_table_struct *cur_state_reg_table; - - for (i = 0; i < table_num; i++) { - cur_state_reg_table = &pustate->usbh_regist_state_table[i]; - - if (table_id == cur_state_reg_table->id) { - pustate->usbh_current_state_table = cur_state_reg_table->table; - pustate->usbh_current_state_table_size = cur_state_reg_table->table_size; - break; - } - } -} - -/*! - \brief state core driver move state - \param[in] pustate: pointer to usb state driver - \param[in] state: the state to move - \param[out] none - \retval none -*/ -void scd_state_move(usbh_state_handle_struct* pustate, uint8_t state) -{ - pustate->usbh_current_state = state; -} - -/*! - \brief state core driver event handle - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[in] event: the current event - \param[in] state: the current state - \param[out] none - \retval host status -*/ -usbh_status_enum scd_event_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct* pustate, - uint8_t event, - uint8_t state) -{ - uint8_t i = 0; - ACT_FUN event_act_fun = NULL; - state_table_struct *backup_state_t = pustate->usbh_current_state_table; - state_table_struct *executive_state_table = pustate->usbh_current_state_table; - - /* look up the table to find the action function */ - for (i = 0; i < pustate->usbh_current_state_table_size; i++) { - if (state == executive_state_table->cur_state) { - if (event == executive_state_table->cur_event) { - state = executive_state_table->next_state; - event_act_fun = executive_state_table->event_action_fun; - break; - } else { - executive_state_table++; - } - } else { - executive_state_table++; - } - } - - pustate->usbh_current_state_table = backup_state_t; - - /* if the action function is not NULL, execute the action function */ - if (event_act_fun) { - if (event_act_fun == &only_state_move) { - pustate->usbh_current_state = state; - } else { - return event_act_fun(pudev, puhost, pustate); - } - } - - return USBH_BUSY; -} - -/*! - \brief state core driver table push - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -void scd_table_push(usbh_state_handle_struct* pustate) -{ - usbh_state_stack_struct *top_state_element; - - if (pustate->usbh_current_state_stack_top < MAX_USBH_STATE_STACK_DEEP) { - pustate->usbh_current_state_stack_top++; - - top_state_element = &pustate->stack[pustate->usbh_current_state_stack_top]; - - /* put the current state table into the state stack */ - top_state_element->state = pustate->usbh_current_state; - top_state_element->table = pustate->usbh_current_state_table; - top_state_element->table_size = pustate->usbh_current_state_table_size; - } -} - -/*! - \brief state core driver table pop - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -void scd_table_pop (usbh_state_handle_struct* pustate) -{ - usbh_state_stack_struct *top_state_element; - - top_state_element = &pustate->stack[pustate->usbh_current_state_stack_top]; - - if (pustate->usbh_current_state_stack_top > -1) { - /* get the current state table from the state stack */ - pustate->usbh_current_state = top_state_element->state; - pustate->usbh_current_state_table = top_state_element->table; - pustate->usbh_current_state_table_size = top_state_element->table_size; - pustate->usbh_current_state_stack_top--; - } -} -/*! - \brief the polling function of class req state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval host status -*/ -static usbh_status_enum class_req_state_polling_fun (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate) -{ - return class_polling_cb.class_req_polling(pudev, puhost, pustate); -} - -/*! - \brief the polling function of class state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval host status -*/ -static usbh_status_enum class_state_polling_fun (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate) -{ - return class_polling_cb.class_polling(pudev, puhost, pustate); -} - -/*! - \brief the function is only used to state move - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -usbh_status_enum only_state_move (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate) -{ - return USBH_OK; -} - -/*! - \brief the function to the up state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -usbh_status_enum goto_up_state_fun (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate) -{ - scd_table_pop((usbh_state_handle_struct *)pustate); - - return USBH_OK; -} diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_ctrl.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_ctrl.c deleted file mode 100644 index b61484053e..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_ctrl.c +++ /dev/null @@ -1,620 +0,0 @@ -/*! - \file usbh_ctrl.c - \brief this file implements the functions for the control transmit process -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ -#include "usbh_core.h" -#include "usbh_std.h" -#include "usbh_ctrl.h" - -uint8_t ctrl_polling_handle_flag = 0U; -uint8_t ctrl_setup_wait_flag = 0U; -uint8_t ctrl_data_wait_flag = 0U; -uint8_t ctrl_status_wait_flag = 0U; - -static uint16_t timeout = 0U; - -static void ctrl_idle_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void ctrl_setup_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void ctrl_data_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void ctrl_status_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void ctrl_error_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void ctrl_stalled_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void ctrl_complete_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); - -/* the ctrl state handle function array */ -void (*ctrl_state_handle[]) (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) = -{ - ctrl_idle_handle, - ctrl_setup_handle, - ctrl_data_handle, - ctrl_status_handle, - ctrl_error_handle, - ctrl_stalled_handle, - ctrl_complete_handle, -}; - -/* the ctrl state handle table */ -state_table_struct ctrl_handle_table[CTRL_HANDLE_TABLE_SIZE] = -{ - /* the current state the current event the next state the event function */ - {CTRL_IDLE, CTRL_EVENT_SETUP, CTRL_SETUP, only_state_move }, - {CTRL_SETUP, CTRL_EVENT_DATA, CTRL_DATA, only_state_move }, - {CTRL_SETUP, CTRL_EVENT_STATUS, CTRL_STATUS, only_state_move }, - {CTRL_SETUP, CTRL_EVENT_ERROR, CTRL_ERROR, only_state_move }, - {CTRL_DATA, CTRL_EVENT_STATUS, CTRL_STATUS, only_state_move }, - {CTRL_DATA, CTRL_EVENT_ERROR, CTRL_ERROR, only_state_move }, - {CTRL_DATA, CTRL_EVENT_STALLED, CTRL_STALLED, only_state_move }, - {CTRL_STATUS, CTRL_EVENT_COMPLETE, CTRL_COMPLETE, only_state_move }, - {CTRL_STATUS, CTRL_EVENT_ERROR, CTRL_ERROR, only_state_move }, - {CTRL_STATUS, CTRL_EVENT_STALLED, CTRL_STALLED, only_state_move }, - {CTRL_ERROR, GO_TO_UP_STATE_EVENT, UP_STATE, goto_up_state_fun }, - {CTRL_STALLED, GO_TO_UP_STATE_EVENT, UP_STATE, goto_up_state_fun }, - {CTRL_COMPLETE, GO_TO_UP_STATE_EVENT, UP_STATE, goto_up_state_fun }, -}; - -/*! - \brief the polling function of CTRL state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -usbh_status_enum ctrl_state_polling_fun (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - void *pustate) -{ - usbh_status_enum exe_state = USBH_BUSY; - usbh_state_handle_struct *p_state; - - p_state = (usbh_state_handle_struct *)pustate; - - /* if first enter this function, begin the ctrl state */ - if (0U == ctrl_polling_handle_flag) { - ctrl_polling_handle_flag = 1U; - scd_table_push(p_state); - scd_state_move(p_state, CTRL_IDLE); - } - - /* base on the current state to handle the ctrl state */ - scd_begin(p_state, CTRL_FSM_ID); - ctrl_state_handle[p_state->usbh_current_state](pudev, puhost, p_state); - - /* determine the control transfer whether to complete */ - switch (puhost->usbh_backup_state.ctrl_backup_state) { - case CTRL_COMPLETE: - ctrl_polling_handle_flag = 0U; - puhost->usbh_backup_state.ctrl_backup_state = CTRL_IDLE; - exe_state = USBH_OK; - break; - case CTRL_STALLED: - ctrl_polling_handle_flag = 0U; - puhost->usbh_backup_state.ctrl_backup_state = CTRL_IDLE; - exe_state = USBH_NOT_SUPPORTED; - break; - case CTRL_ERROR: - ctrl_polling_handle_flag = 0U; - puhost->usbh_backup_state.ctrl_backup_state = CTRL_IDLE; - exe_state = USBH_FAIL; - break; - default: - exe_state = USBH_BUSY; - break; - } - - return exe_state; -} - -/*! - \brief the handle function of CTRL_IDLE state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void ctrl_idle_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.ctrl_backup_state = CTRL_IDLE; - scd_event_handle(pudev, puhost, pustate, CTRL_EVENT_SETUP, pustate->usbh_current_state); -} - -/*! - \brief the handle function of CTRL_SETUP state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void ctrl_setup_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - urb_state_enum urb_status = URB_IDLE; - puhost->usbh_backup_state.ctrl_backup_state = CTRL_SETUP; - - if (0U == ctrl_setup_wait_flag) { - ctrl_setup_wait_flag = 1U; - - /* send a setup packet */ - usbh_ctltx_setup (pudev, - puhost->control.setup.data, - puhost->control.hc_out_num); - } else { - urb_status = hcd_urb_state_get(pudev, puhost->control.hc_out_num); - - /* case setup packet sent successfully */ - if (URB_DONE == urb_status) { - /* check if there is a data stage */ - if (0U != puhost->control.setup.b.wLength) { - ctrl_setup_wait_flag = 0U; - timeout = DATA_STAGE_TIMEOUT; - scd_event_handle(pudev, puhost, pustate, CTRL_EVENT_DATA, pustate->usbh_current_state); - /* no data stage */ - } else { - timeout = NODATA_STAGE_TIMEOUT; - ctrl_setup_wait_flag = 0U; - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_STATUS, - pustate->usbh_current_state); - } - - /* set the delay timer to enable timeout for data stage completion */ - puhost->control.timer = (uint16_t)USB_CURRENT_FRAME_GET(); - } else if (URB_ERROR == urb_status) { - ctrl_setup_wait_flag = 0U; - scd_event_handle(pudev, puhost, pustate, CTRL_EVENT_ERROR, pustate->usbh_current_state); - } else { - /* no operation */ - } - } -} - -/*! - \brief the handle function of CTRL_DATA state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void ctrl_data_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - uint8_t direction; - urb_state_enum urb_status = URB_IDLE; - puhost->usbh_backup_state.ctrl_backup_state = CTRL_DATA; - - direction = (puhost->control.setup.b.bmRequestType & USB_DIR_MASK); - - if (USB_DIR_IN == direction) { - if (0U == ctrl_data_wait_flag) { - ctrl_data_wait_flag = 1U; - - /* issue an IN token */ - usbh_xfer(pudev, - puhost->control.buff, - puhost->control.hc_in_num, - puhost->control.length); - } else { - urb_status = hcd_urb_state_get(pudev, puhost->control.hc_in_num); - - /* check is data packet transfered successfully */ - switch (urb_status) { - case URB_DONE: - ctrl_data_wait_flag = 0U; - - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_STATUS, - pustate->usbh_current_state); - break; - case URB_STALL: - ctrl_data_wait_flag = 0U; - - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_STALLED, - pustate->usbh_current_state); - break; - case URB_ERROR: - ctrl_data_wait_flag = 0U; - - /* device error */ - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_ERROR, - pustate->usbh_current_state); - break; - default: - if (((uint16_t)USB_CURRENT_FRAME_GET() - puhost->control.timer) > timeout) { - ctrl_data_wait_flag = 0U; - - /* timeout for IN transfer */ - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_ERROR, - pustate->usbh_current_state); - } - break; - } - } - } else { - if (0U == ctrl_data_wait_flag) { - ctrl_data_wait_flag = 1U; - - /* start DATA out transfer (only one DATA packet)*/ - pudev->host.host_channel[puhost->control.hc_out_num].data_tg_out = 1U; - - usbh_xfer(pudev, - puhost->control.buff, - puhost->control.hc_out_num, - puhost->control.length); - } else { - urb_status = hcd_urb_state_get(pudev, puhost->control.hc_out_num); - - switch (urb_status) { - case URB_DONE: - ctrl_data_wait_flag = 0U; - - /* if the setup pkt is sent successful, then change the state */ - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_STATUS, - pustate->usbh_current_state); - break; - case URB_STALL: - ctrl_data_wait_flag = 0U; - - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_STALLED, - pustate->usbh_current_state); - break; - case URB_NOTREADY: - /* nack received from device */ - ctrl_data_wait_flag = 0U; - break; - case URB_ERROR: - ctrl_data_wait_flag = 0U; - - /* device error */ - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_ERROR, - pustate->usbh_current_state); - break; - default: - break; - } - } - } -} - -/*! - \brief the handle function of CTRL_STATUS state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void ctrl_status_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - uint8_t direction; - urb_state_enum urb_status = URB_IDLE; - - puhost->usbh_backup_state.ctrl_backup_state = CTRL_STATUS; - - /* get the transfer direction in the data state, but the transfer direction in the status state is opposite */ - direction = (puhost->control.setup.b.bmRequestType & USB_DIR_MASK); - - if (USB_DIR_OUT == direction) { - /* handle status in */ - if (0U == ctrl_status_wait_flag) { - ctrl_status_wait_flag = 1U; - usbh_xfer (pudev, 0U, puhost->control.hc_in_num, 0U); - } else { - urb_status = hcd_urb_state_get(pudev, puhost->control.hc_in_num); - - switch (urb_status) { - case URB_DONE: - ctrl_status_wait_flag = 0U; - - /* handle URB_DONE status */ - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_COMPLETE, - pustate->usbh_current_state); - break; - case URB_ERROR: - ctrl_status_wait_flag = 0U; - - /* handle URB_STALL status*/ - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_ERROR, - pustate->usbh_current_state); - break; - case URB_STALL: - ctrl_status_wait_flag = 0U; - - /* handle URB_STALL status */ - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_STALLED, - pustate->usbh_current_state); - break; - default: - if (((uint16_t)USB_CURRENT_FRAME_GET() - puhost->control.timer) > timeout) { - ctrl_status_wait_flag = 0U; - - /* handle timeout */ - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_ERROR, - pustate->usbh_current_state); - } - break; - } - } - } else { - /* handle status out */ - if (0U == ctrl_status_wait_flag) { - ctrl_status_wait_flag = 1U; - pudev->host.host_channel[puhost->control.hc_out_num].data_tg_out ^= 1U; - usbh_xfer (pudev, 0U, puhost->control.hc_out_num, 0U); - - { - uint32_t host_ctlr = 0; - - host_ctlr = USB_HCHxLEN(puhost->control.hc_out_num); - USB_HCHxLEN(puhost->control.hc_out_num) = host_ctlr | 1; - host_ctlr = USB_HCHxCTL(puhost->control.hc_out_num); - USB_HCHxCTL(puhost->control.hc_out_num) = (host_ctlr & 0x3FFFFFFF) | 0x80000000; - } - } else { - urb_status = hcd_urb_state_get(pudev, puhost->control.hc_out_num); - - switch (urb_status) { - case URB_DONE: - ctrl_status_wait_flag = 0U; - - /* handle URB_DONE status */ - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_COMPLETE, - pustate->usbh_current_state); - break; - case URB_NOTREADY: - /* handle URB_NOTREADY status */ - ctrl_status_wait_flag = 0U; - break; - case URB_ERROR: - ctrl_status_wait_flag = 0U; - - /* handle URB_ERROR status */ - scd_event_handle(pudev, - puhost, - pustate, - CTRL_EVENT_ERROR, - pustate->usbh_current_state); - break; - default: - break; - } - } - } -} - -/*! - \brief the handle function of CTRL_ERROR state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void ctrl_error_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.ctrl_backup_state = CTRL_ERROR; - - if (++puhost->control.error_count <= USBH_MAX_ERROR_COUNT) { - /* do the transmission again, starting from SETUP Packet */ - scd_event_handle(pudev, puhost, pustate, CTRL_EVENT_SETUP, pustate->usbh_current_state); - } else { - scd_event_handle(pudev, puhost, pustate, GO_TO_UP_STATE_EVENT, pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of CTRL_STALLED state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void ctrl_stalled_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.ctrl_backup_state = CTRL_STALLED; - scd_event_handle(pudev, puhost, pustate, GO_TO_UP_STATE_EVENT, pustate->usbh_current_state); -} - -/*! - \brief the handle function of CTRL_COMPLETE state - \param[in] pudev: pointer to usb device - \param[in] puhost: pointer to usb host - \param[in] pustate: pointer to usb state driver - \param[out] none - \retval none -*/ -static void ctrl_complete_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.ctrl_backup_state = CTRL_COMPLETE; - scd_event_handle(pudev, puhost, pustate, GO_TO_UP_STATE_EVENT, pustate->usbh_current_state); -} - -/*! - \brief send datas from the host channel - \param[in] pudev: pointer to usb device - \param[in] buf: data buffer address to send datas - \param[in] hc_num: the number of the host channel - \param[in] len: length of the send data - \param[out] none - \retval host operation status -*/ -usbh_status_enum usbh_xfer (usb_core_handle_struct *pudev, - uint8_t *buf, - uint8_t hc_num, - uint16_t len) -{ - usb_hostchannel_struct *puhc = &pudev->host.host_channel[hc_num]; - - puhc->xfer_buff = buf; - puhc->xfer_len = len; - - switch (puhc->endp_type) { - case USB_EPTYPE_CTRL: - if (0U == puhc->endp_in) { - if (0U == len) { - /* for status out stage, length = 0, status out pid = 1 */ - puhc->data_tg_out = 1U; - } - - /* set the data toggle bit as per the flag */ - if (0U == puhc->data_tg_out) { - /* put the pid 0 */ - puhc->DPID = HC_PID_DATA0; - } else { - /* put the pid 1 */ - puhc->DPID = HC_PID_DATA1; - } - } else { - puhc->DPID = HC_PID_DATA1; - } - break; - - case USB_EPTYPE_ISOC: - puhc->DPID = HC_PID_DATA0; - break; - - case USB_EPTYPE_BULK: - if (0U == puhc->endp_in) { - /* set the data toggle bit as per the flag */ - if (0U == puhc->data_tg_out) { - /* put the pid 0 */ - puhc->DPID = HC_PID_DATA0; - } else { - /* put the pid 1 */ - puhc->DPID = HC_PID_DATA1; - } - } else { - if (0U == puhc->data_tg_in) { - puhc->DPID = HC_PID_DATA0; - } else { - puhc->DPID = HC_PID_DATA1; - } - } - break; - - case USB_EPTYPE_INTR: - if (0U == puhc->endp_in) { - if (0U == puhc->data_tg_out) { - puhc->DPID = HC_PID_DATA0; - } else { - puhc->DPID = HC_PID_DATA1; - } - - /* toggle data pid */ - puhc->data_tg_out ^= 1U; - } else { - if (0U == puhc->data_tg_in) { - puhc->DPID = HC_PID_DATA0; - } else { - puhc->DPID = HC_PID_DATA1; - } - - /* toggle data pid */ - puhc->data_tg_in ^= 1U; - } - break; - - default: - break; - } - - hcd_submit_request (pudev, hc_num); - - return USBH_OK; -} - -/*! - \brief send the setup packet to the device - \param[in] pudev: pointer to usb device - \param[in] buf: buffer pointer from which the data will be send to device - \param[in] hc_num: host channel number - \param[out] none - \retval host operation status -*/ -usbh_status_enum usbh_ctltx_setup (usb_core_handle_struct *pudev, uint8_t *buf, uint8_t hc_num) -{ - usb_hostchannel_struct *puhc = &pudev->host.host_channel[hc_num]; - - puhc->DPID = HC_PID_SETUP; - puhc->xfer_buff = buf; - puhc->xfer_len = USBH_SETUP_PACKET_SIZE; - - return (usbh_status_enum)hcd_submit_request (pudev, hc_num); -} - -/*! - \brief this function prepare a hc and start a transfer - \param[in] pudev: pointer to usb device - \param[in] channel_num: host channel number which is in (0..7) - \param[out] none - \retval host operation status -*/ -uint32_t hcd_submit_request (usb_core_handle_struct *pudev, uint8_t channel_num) -{ - usb_hostchannel_struct *puhc = &pudev->host.host_channel[channel_num]; - - puhc->urb_state = URB_IDLE; - puhc->xfer_count = 0U; - - return (uint32_t)usb_hostchannel_startxfer(pudev, channel_num); -} diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_hcs.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_hcs.c deleted file mode 100644 index 035459d195..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_hcs.c +++ /dev/null @@ -1,162 +0,0 @@ -/*! - \file usbh_hcs.c - \brief this file implements functions for opening and closing host channels -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.0, firmware for GD32F4xx -*/ - -#include "usbh_hcs.h" - -static uint16_t usbh_freechannel_get (usb_core_handle_struct *pudev); - -/*! - \brief open a channel - \param[in] pudev: pointer to usb device - \param[in] channel_num: host channel number which is in (0..7) - \param[in] dev_addr: USB device address allocated to attached device - \param[in] dev_speed: USB device speed (Full speed/Low speed) - \param[in] ep_type: endpoint type (bulk/int/ctl) - \param[in] ep_mps: max packet size - \param[out] none - \retval operation status -*/ -uint8_t usbh_channel_open (usb_core_handle_struct *pudev, - uint8_t channel_num, - uint8_t dev_addr, - uint8_t dev_speed, - uint8_t ep_type, - uint16_t ep_mps) -{ - usb_hostchannel_struct *puhc = &pudev->host.host_channel[channel_num]; - uint16_t channel_info = puhc->info; - - puhc->endp_id = (uint8_t)channel_info & 0x7FU; - puhc->endp_in = (uint8_t)(channel_info & 0x80U) >> 7; - puhc->endp_type = ep_type; - puhc->endp_mps = ep_mps; - puhc->dev_addr = dev_addr; - puhc->dev_speed = dev_speed; - - puhc->data_tg_in = 0U; - puhc->data_tg_out = 0U; - - if (HPRT_PRTSPD_HIGH_SPEED == dev_speed) { - puhc->do_ping = 1U; - } - - usb_hostchannel_init(pudev, channel_num); - - return (uint8_t)HC_OK; -} - -/*! - \brief modify a channel - \param[in] pudev: pointer to usb device - \param[in] channel_num: host channel number which is in (0..7) - \param[in] dev_addr: USB Device address allocated to attached device - \param[in] dev_speed: USB device speed (Full speed/Low speed) - \param[in] ep_type: endpoint type (bulk/int/ctl) - \param[in] ep_mps: max packet size - \param[out] none - \retval operation status -*/ -uint8_t usbh_channel_modify (usb_core_handle_struct *pudev, - uint8_t channel_num, - uint8_t dev_addr, - uint8_t dev_speed, - uint8_t ep_type, - uint16_t ep_mps) -{ - usb_hostchannel_struct *puhc = &pudev->host.host_channel[channel_num]; - - if (0U != dev_addr) { - puhc->dev_addr = dev_addr; - } - - if ((puhc->endp_mps != ep_mps) && (0U != ep_mps)) { - puhc->endp_mps = ep_mps; - } - - if ((puhc->dev_speed != dev_speed) && (0U != dev_speed)) { - puhc->dev_speed = dev_speed; - } - - usb_hostchannel_init(pudev, channel_num); - - return (uint8_t)HC_OK; -} - -/*! - \brief allocate a new channel for the pipe - \param[in] pudev: pointer to usb device - \param[in] ep_addr: endpoint for which the channel to be allocated - \param[out] none - \retval host channel number -*/ -uint8_t usbh_channel_alloc (usb_core_handle_struct *pudev, uint8_t ep_addr) -{ - uint16_t hc_num = usbh_freechannel_get(pudev); - - if ((uint16_t)HC_ERROR != hc_num) { - pudev->host.host_channel[hc_num].info = HC_USED | ep_addr; - } - - return (uint8_t)hc_num; -} - -/*! - \brief free the usb host channel - \param[in] pudev: pointer to usb device - \param[in] index: channel number to be freed which is in (0..7) - \param[out] none - \retval host operation status -*/ -uint8_t usbh_channel_free (usb_core_handle_struct *pudev, uint8_t index) -{ - if (index < HC_MAX) { - pudev->host.host_channel[index].info &= HC_USED_MASK; - } - - return USBH_OK; -} - -/*! - \brief free all usb host channel - \param[in] pudev: pointer to usb device - \param[out] none - \retval host operation status -*/ -uint8_t usbh_allchannel_dealloc (usb_core_handle_struct *pudev) -{ - uint8_t index; - - for (index = 2U; index < HC_MAX; index ++) { - pudev->host.host_channel[index].info = 0U; - } - - return USBH_OK; -} - -/*! - \brief get a free channel number for allocation to a device endpoint - \param[in] pudev: pointer to usb device - \param[out] none - \retval free channel number -*/ -static uint16_t usbh_freechannel_get (usb_core_handle_struct *pudev) -{ - uint8_t index = 0U; - - for (index = 0U; index < HC_MAX; index++) { - if (0U == (pudev->host.host_channel[index].info & HC_USED)) { - return (uint16_t)index; - } - } - - return HC_ERROR; -} - diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_int.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_int.c deleted file mode 100644 index a386d185ed..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_int.c +++ /dev/null @@ -1,591 +0,0 @@ -/*! - \file usbh_int.c - \brief USB host mode interrupt handler file -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.1, firmware for GD32F4xx -*/ - -#include "usb_core.h" -#include "usb_defines.h" -#include "usbh_int.h" - -static uint32_t usbh_intf_sof (usb_core_handle_struct *pudev); -static uint32_t usbh_intf_port (usb_core_handle_struct *pudev); -static uint32_t usbh_intf_hc (usb_core_handle_struct *pudev); -static uint32_t usbh_intf_hc_in (usb_core_handle_struct *pudev, uint8_t channel_num); -static uint32_t usbh_intf_hc_out (usb_core_handle_struct *pudev, uint8_t channel_num); -static uint32_t usbh_intf_rxfifo_noempty (usb_core_handle_struct *pudev); -static uint32_t usbh_intf_nptxfifo_empty (usb_core_handle_struct *pudev); -static uint32_t usbh_intf_ptxfifo_empty (usb_core_handle_struct *pudev); -static uint32_t usbh_intf_disconnect (usb_core_handle_struct *pudev); -static uint32_t usbh_intf_iso_incomplete_xfer (usb_core_handle_struct *pudev); - -/*! - \brief handle global host interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -uint32_t usbh_isr (usb_core_handle_struct *pudev) -{ - uint32_t retval = 0U; - uint32_t int_flag = 0U; - - /* check if host mode */ - if (USB_CURRENT_MODE_GET() == HOST_MODE) { - USB_CORE_INTR_READ(int_flag); - - if (!int_flag) { - return 0U; - } - - /* start of frame interrupt handle */ - if (int_flag & GINTF_SOF) { - retval |= usbh_intf_sof (pudev); - } - - /* Rx FIFO non-empty interrupt handle */ - if (int_flag & GINTF_RXFNEIF) { - retval |= usbh_intf_rxfifo_noempty (pudev); - } - - /* Non-Periodic Tx FIFO empty interrupt hanlde */ - if (int_flag & GINTF_NPTXFEIF) { - retval |= usbh_intf_nptxfifo_empty (pudev); - } - - /* periodic Tx FIFO empty interrupt handle */ - if (int_flag & GINTF_PTXFEIF) { - retval |= usbh_intf_ptxfifo_empty (pudev); - } - - /* host channels interrupt handle */ - if (int_flag & GINTF_HCIF) { - retval |= usbh_intf_hc (pudev); - } - - /* host port interrupt handle */ - if (int_flag & GINTF_HPIF) { - retval |= usbh_intf_port (pudev); - } - - /* disconnect interrupt handle */ - if (int_flag & GINTF_DISCIF) { - retval |= usbh_intf_disconnect (pudev); - } - - /* isochronous IN transfer not complete interrupt handle */ - if (int_flag & GINTF_ISOONCIF) { - retval |= usbh_intf_iso_incomplete_xfer (pudev); - } - } - - return retval; -} - -/*! - \brief handle the start-of-frame interrupt in host mode - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbh_intf_sof (usb_core_handle_struct *pudev) -{ - usbh_hcd_int_fops->sof(pudev); - - /* clear interrupt */ - USB_GINTF = GINTF_SOF; - - return 1U; -} - -/*! - \brief handle all host channels interrupt in host mode - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbh_intf_hc (usb_core_handle_struct *pudev) -{ - uint8_t i = 0U; - uint32_t retval = 0U; - - for (i = 0U; i < pudev->cfg.host_channel_num; i++) { - if ((USB_HACHINT & HACHINT_HACHINT) & ((uint32_t)1U << i)) { - if ((USB_HCHxCTL((uint16_t)i) & HCHCTL_EPDIR) >> 15U) { - retval |= usbh_intf_hc_in (pudev, i); - } else { - retval |= usbh_intf_hc_out (pudev, i); - } - } - } - - return retval; -} - -/*! - \brief handle the disconnect interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbh_intf_disconnect (usb_core_handle_struct *pudev) -{ - usbh_hcd_int_fops->device_disconnected(pudev); - - /* clear interrupt */ - USB_GINTF = GINTF_DISCIF; - - return 1U; -} - -/*! - \brief handle the non-periodic tx fifo empty interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbh_intf_nptxfifo_empty (usb_core_handle_struct *pudev) -{ - uint8_t channel_num = 0U; - uint32_t dword_len = 0U, len = 0U; - usb_hostchannel_struct *puhc; - - channel_num = (uint8_t)((USB_HNPTFQSTAT & HNPTFQSTAT_CNUM) >> 27U); - puhc = &pudev->host.host_channel[channel_num]; - dword_len = (puhc->xfer_len + 3U) / 4U; - - while (((USB_HNPTFQSTAT & HNPTFQSTAT_NPTXFS) > dword_len) && (0U != puhc->xfer_len)) { - len = (USB_HNPTFQSTAT & HNPTFQSTAT_NPTXFS) * 4U; - - if (len > puhc->xfer_len) { - /* last packet */ - len = (uint16_t)puhc->xfer_len; - - USB_GINTEN &= ~GINTF_NPTXFEIF; - - } - - dword_len = (puhc->xfer_len + 3U) / 4U; - usb_fifo_write (puhc->xfer_buff, channel_num, (uint16_t)len); - - puhc->xfer_buff += len; - puhc->xfer_len -= len; - puhc->xfer_count += len; - } - - return 1U; -} - -/*! - \brief handle the periodic tx fifo empty interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbh_intf_ptxfifo_empty (usb_core_handle_struct *pudev) -{ - uint8_t channel_num = 0U; - uint32_t dword_len = 0U, len = 0U; - usb_hostchannel_struct *puhc; - - channel_num = (uint8_t)((USB_HPTFQSTAT & HPTFQSTAT_CNUM) >> 27U); - puhc = &pudev->host.host_channel[channel_num]; - dword_len = (puhc->xfer_len + 3U) / 4U; - - while (((USB_HPTFQSTAT & HPTFQSTAT_PTXFS) > dword_len) && (0U != puhc->xfer_len)) { - len = (USB_HPTFQSTAT & HPTFQSTAT_PTXFS) * 4U; - - if (len > puhc->xfer_len) { - len = puhc->xfer_len; - - /* last packet */ - USB_GINTEN &= ~GINTF_PTXFEIF; - } - - dword_len = (puhc->xfer_len + 3U) / 4U; - usb_fifo_write (puhc->xfer_buff, channel_num, (uint16_t)len); - - puhc->xfer_buff += len; - puhc->xfer_len -= len; - puhc->xfer_count += len; - } - - return 1U; -} - -/*! - \brief handle the host port interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbh_intf_port (usb_core_handle_struct *pudev) -{ - uint8_t port_speed = 0U; - uint8_t port_reset = 0U; - uint32_t retval = 0U; - __IO uint32_t hostportdup = USB_HPCS; - - /* clear the interrupt bits in gintsts */ - hostportdup &= ~HPCS_PE; - hostportdup &= ~HPCS_PCD; - hostportdup &= ~HPCS_PEDC; - - /* port connect detected */ - if (USB_HPCS & HPCS_PCD) { - hostportdup |= HPCS_PCD; - usbh_hcd_int_fops->device_connected(pudev); - retval |= 1U; - } - - /* port enable changed */ - if (USB_HPCS & HPCS_PEDC) { - hostportdup |= HPCS_PEDC; - - if (USB_HPCS & HPCS_PE) { - port_speed = (uint8_t)((USB_HPCS & HPCS_PS) >> 17U); - - if (HPRT_PRTSPD_LOW_SPEED == port_speed) { - USB_HFT = 6000U; - - if (HCTLR_6_MHZ != (USB_HCTL & HCTL_CLKSEL)) { - if (USB_CORE_EMBEDDED_PHY == pudev->cfg.phy_interface) { - USB_FSLSCLOCK_INIT(HCTLR_6_MHZ); - } - port_reset = 1U; - } - } else if(HPRT_PRTSPD_FULL_SPEED == port_speed) { - USB_HFT = 48000U; - - if (HCTLR_48_MHZ != (USB_HCTL & HCTL_CLKSEL)) { - if (USB_CORE_EMBEDDED_PHY == pudev->cfg.phy_interface) { - USB_FSLSCLOCK_INIT(HCTLR_48_MHZ); - } - port_reset = 1U; - } - } else { - /* for high speed device and others */ - port_reset = 1U; - } - - - } - } - - if (port_reset) { - usb_port_reset(pudev); - } - - /* clear port interrupts */ - USB_HPCS = hostportdup; - - return retval; -} - -/*! - \brief handle the OUT channel interrupt - \param[in] pudev: pointer to usb device instance - \param[in] channel_num: host channel number which is in (0..7) - \param[out] none - \retval operation status -*/ -static uint32_t usbh_intf_hc_out (usb_core_handle_struct *pudev, uint8_t channel_num) -{ - uint32_t channel_intr = USB_HCHxINTF((uint16_t)channel_num); - usb_hostchannel_struct *puhc = &pudev->host.host_channel[channel_num]; - - channel_intr &= USB_HCHxINTEN((uint16_t)channel_num); - - if (channel_intr & HCHINTF_ACK) { - if (URB_PING == puhc->urb_state) { - puhc->err_count = 0U; - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - usb_hostchannel_halt(pudev, channel_num); - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_TF; - puhc->status = HC_XF; - } - - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_ACK; - } else if (channel_intr & HCHINTF_REQOVR) { - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - usb_hostchannel_halt(pudev, channel_num); - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_REQOVR; - } else if (channel_intr & HCHINTF_TF) { - puhc->err_count = 0U; - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - usb_hostchannel_halt(pudev, channel_num); - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_TF; - puhc->status = HC_XF; - } else if (channel_intr & HCHINTF_STALL) { - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_STALL; - usb_hostchannel_halt(pudev, channel_num); - puhc->status = HC_STALL; - } else if (channel_intr & HCHINTF_NAK) { - puhc->err_count = 0U; - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - usb_hostchannel_halt(pudev, channel_num); - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_NAK; - puhc->status = HC_NAK; - } else if (channel_intr & HCHINTF_USBER) { - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - usb_hostchannel_halt(pudev, channel_num); - puhc->err_count ++; - puhc->status = HC_TRACERR; - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_USBER; - } else if (channel_intr & HCHINTF_NYET) { - puhc->err_count = 0U; - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - puhc->status = HC_NYET; - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_NYET; - } else if (channel_intr & HCHINTF_DTER) { - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - usb_hostchannel_halt(pudev, channel_num); - puhc->status= HC_DTGERR; - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_DTER; - } else if (channel_intr & HCHINTF_CH) { - USB_HCHxINTEN((uint16_t)channel_num) &= ~HCHINTEN_CHIE; - - switch (puhc->status) { - case HC_XF: - puhc->urb_state = URB_DONE; - - if (USB_EPTYPE_BULK == ((USB_HCHxCTL((uint16_t)channel_num) & HCHCTL_EPTYPE) >> 18)) { - puhc->data_tg_out ^= 1U; - } - break; - case HC_NAK: - if (URB_PING == puhc->urb_state) { - usb_hostchannel_ping(pudev, channel_num); - } else { - puhc->urb_state = URB_NOTREADY; - } - break; - case HC_NYET: - if (1U == puhc->do_ping) { - usb_hostchannel_ping(pudev, channel_num); - puhc->urb_state = URB_PING; - } - break; - case HC_STALL: - puhc->urb_state = URB_STALL; - break; - case HC_TRACERR: - if (3U == puhc->err_count) { - puhc->urb_state = URB_ERROR; - puhc->err_count = 0U; - } - break; - default: - break; - } - - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_CH; - } else { - /* no operation */ - } - - return 1U; -} - -/*! - \brief handle the IN channel interrupt - \param[in] pudev: pointer to usb device instance - \param[in] channel_num: host channel number which is in (0..7) - \param[out] none - \retval operation status -*/ -static uint32_t usbh_intf_hc_in (usb_core_handle_struct *pudev, uint8_t channel_num) -{ - uint8_t endp_type = 0U; - usb_hostchannel_struct *puhc = &pudev->host.host_channel[channel_num]; - - uint32_t channle_intf = USB_HCHxINTF((uint16_t)channel_num); - __IO uint32_t channel_ctrl = USB_HCHxCTL((uint16_t)channel_num); - - channle_intf &= USB_HCHxINTEN((uint16_t)channel_num); - - endp_type = (uint8_t)((channel_ctrl & HCHCTL_EPTYPE) >> 18U); - - if (channle_intf & HCHINTF_ACK) { - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_ACK; - } else if (channle_intf & HCHINTF_STALL) { - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - puhc->status = HC_STALL; - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_NAK; - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_STALL; - - /* NOTE: When there is a 'stall', reset also nak, - else, the pudev->host.status = HC_STALL - will be overwritten by 'nak' in code below */ - channle_intf &= ~HCHINTF_NAK; - - usb_hostchannel_halt(pudev, channel_num); - } else if (channle_intf & HCHINTF_DTER) { - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - usb_hostchannel_halt(pudev, channel_num); - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_NAK; - puhc->status = HC_DTGERR; - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_DTER; - } else { - /* no operation */ - } - - if (channle_intf & HCHINTF_REQOVR) { - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - usb_hostchannel_halt(pudev, channel_num); - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_REQOVR; - } else if (channle_intf & HCHINTF_TF) { - if (pudev->cfg.dma_enable == 1U) { - uint32_t xfer_size = USB_HCHxLEN((uint16_t)channel_num) & HCHLEN_TLEN; - puhc->xfer_count = puhc->xfer_len - xfer_size; - } - - puhc->status = HC_XF; - puhc->err_count = 0U; - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_TF; - - if ((USB_EPTYPE_CTRL == endp_type) || (USB_EPTYPE_BULK == endp_type)) { - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - usb_hostchannel_halt(pudev, channel_num); - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_NAK; - puhc->data_tg_in ^= 1U; - } else if (USB_EPTYPE_INTR == endp_type) { - channel_ctrl |= HCHCTL_ODDFRM; - USB_HCHxCTL((uint16_t)channel_num) = channel_ctrl; - puhc->urb_state = URB_DONE; - } else { - /* no operation */ - } - } else if (channle_intf & HCHINTF_CH) { - USB_HCHxINTEN((uint16_t)channel_num) &= ~HCHINTEN_CHIE; - - switch (puhc->status) { - case HC_XF: - puhc->urb_state = URB_DONE; - break; - case HC_TRACERR: - case HC_DTGERR: - puhc->err_count = 0U; - puhc->urb_state = URB_ERROR; - break; - case HC_STALL: - puhc->urb_state = URB_STALL; - break; - default: - if (USB_EPTYPE_INTR == endp_type) { - puhc->data_tg_in ^= 1U; - } - break; - } - - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_CH; - } else if (channle_intf & HCHINTF_USBER) { - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - (puhc->err_count)++; - puhc->status = HC_TRACERR; - usb_hostchannel_halt(pudev, channel_num); - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_USBER; - } else if (channle_intf & HCHINTF_NAK) { - if (USB_EPTYPE_INTR == endp_type) { - USB_HCHxINTEN((uint16_t)channel_num) |= HCHINTEN_CHIE; - usb_hostchannel_halt(pudev, channel_num); - } else if ((USB_EPTYPE_CTRL == endp_type) || (USB_EPTYPE_BULK == endp_type)) { - /* re-activate the channel */ - channel_ctrl |= HCHCTL_CEN; - channel_ctrl &= ~HCHCTL_CDIS; - USB_HCHxCTL((uint16_t)channel_num) = channel_ctrl; - } else { - /* no operation */ - } - - puhc->status = HC_NAK; - USB_HCHxINTF((uint16_t)channel_num) = HCHINTF_NAK; - } else { - /* no operation */ - } - - return 1U; -} - -/*! - \brief handle the rx fifo non-empty interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbh_intf_rxfifo_noempty (usb_core_handle_struct *pudev) -{ - uint32_t count = 0U; - __IO uint8_t channel_num = 0U; - __IO uint32_t rx_status = 0U; - uint32_t usbh_ch_ctl_reg = 0U; - usb_hostchannel_struct *puhc; - - /* disable the Rx status queue level interrupt */ - USB_GINTEN &= ~GINTF_RXFNEIF; - - rx_status = USB_GRSTATP; - channel_num = (uint8_t)(rx_status & GRSTATR_CNUM); - puhc = &pudev->host.host_channel[channel_num]; - - switch ((rx_status & GRSTATR_RPCKST) >> 17) { - case GRSTATR_RPCKST_IN: - count = (rx_status & GRSTATR_BCOUNT) >> 4; - - /* read the data into the host buffer. */ - if ((count > 0U) && (puhc->xfer_buff != (void *)0)) { - usb_fifo_read(puhc->xfer_buff, (uint16_t)count); - - /* manage multiple Xfer */ - puhc->xfer_buff += count; - puhc->xfer_count += count; - - if (USB_HCHxLEN((uint16_t)channel_num) & HCHLEN_PCNT) { - /* re-activate the channel when more packets are expected */ - usbh_ch_ctl_reg = USB_HCHxCTL((uint16_t)channel_num); - usbh_ch_ctl_reg |= HCHCTL_CEN; - usbh_ch_ctl_reg &= ~HCHCTL_CDIS; - USB_HCHxCTL((uint16_t)channel_num) = usbh_ch_ctl_reg; - } - } - break; - case GRSTATR_RPCKST_IN_XFER_COMP: - case GRSTATR_RPCKST_DATA_TOGGLE_ERR: - case GRSTATR_RPCKST_CH_HALTED: - default: - break; - } - - /* enable the Rx status queue level interrupt */ - USB_GINTEN |= GINTF_RXFNEIF; - - return 1U; -} - -/*! - \brief handle the incomplete periodic transfer interrupt - \param[in] pudev: pointer to usb device instance - \param[out] none - \retval operation status -*/ -static uint32_t usbh_intf_iso_incomplete_xfer (usb_core_handle_struct *pudev) -{ - __IO uint32_t gint_flag = 0U; - - gint_flag = USB_HCHxCTL(0U); - USB_HCHxCTL(0U) = 0U; - - gint_flag = 0U; - - /* clear interrupt */ - gint_flag |= GINTF_ISOONCIF; - USB_GINTF = gint_flag; - - return 1U; -} diff --git a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_std.c b/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_std.c deleted file mode 100644 index 57f9e996a4..0000000000 --- a/bsp/gd32450z-eval/Libraries/GD32F4xx_usb_driver/Source/usbh_std.c +++ /dev/null @@ -1,808 +0,0 @@ -/*! - \file usbh_std.c - \brief USB 2.0 standard function definition -*/ - -/* - Copyright (C) 2016 GigaDevice - - 2016-08-15, V1.0.1, firmware for GD32F4xx -*/ - -#include "usbh_core.h" -#include "usbh_usr.h" -#include "usbh_std.h" -#include "usbh_ctrl.h" - -uint8_t local_buffer[64]; -uint8_t usbh_cfg_desc[512]; -uint8_t enum_polling_handle_flag = 0U; - -static void enum_idle_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void enum_get_full_dev_desc_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void enum_set_addr_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void enum_get_cfg_desc_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void enum_get_full_cfg_desc_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void enum_get_mfc_string_desc_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void enum_get_product_string_desc_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void enum_get_serialnum_string_desc_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void enum_set_configuration_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); -static void enum_dev_configured_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate); - -/* the enumeration state handle function array */ -void (*enum_state_handle[]) (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate) = -{ - enum_idle_handle, - enum_set_addr_handle, - enum_get_full_dev_desc_handle, - enum_get_cfg_desc_handle, - enum_get_full_cfg_desc_handle, - enum_get_mfc_string_desc_handle, - enum_get_product_string_desc_handle, - enum_get_serialnum_string_desc_handle, - enum_set_configuration_handle, - enum_dev_configured_handle, -}; - -/* the enumeration state handle table */ -state_table_struct enum_handle_table[ENUM_HANDLE_TABLE_SIZE] = -{ - /* the current state the current event the next state the event function */ - {ENUM_IDLE, ENUM_EVENT_SET_ADDR, ENUM_SET_ADDR, only_state_move }, - {ENUM_SET_ADDR, ENUN_EVENT_GET_FULL_DEV_DESC, ENUM_GET_FULL_DEV_DESC, only_state_move }, - {ENUM_GET_FULL_DEV_DESC, ENUN_EVENT_GET_CFG_DESC, ENUM_GET_CFG_DESC, only_state_move }, - {ENUM_GET_CFG_DESC, ENUN_EVENT_GET_FULL_CFG_DESC, ENUM_GET_FULL_CFG_DESC, only_state_move }, - {ENUM_GET_FULL_CFG_DESC, ENUN_EVENT_GET_MFC_STRING_DESC, ENUM_GET_MFC_STRING_DESC, only_state_move }, - {ENUM_GET_MFC_STRING_DESC, ENUN_EVENT_GET_PRODUCT_STRING_DESC, ENUM_GET_PRODUCT_STRING_DESC, only_state_move }, - {ENUM_GET_PRODUCT_STRING_DESC, ENUN_EVENT_GET_SERIALNUM_STRING_DESC, ENUM_GET_SERIALNUM_STRING_DESC, only_state_move }, - {ENUM_GET_SERIALNUM_STRING_DESC, ENUN_EVENT_SET_CONFIGURATION, ENUM_SET_CONFIGURATION, only_state_move }, - {ENUM_SET_CONFIGURATION, ENUN_EVENT_DEV_CONFIGURED, ENUM_DEV_CONFIGURED, only_state_move }, - {ENUM_DEV_CONFIGURED, GO_TO_UP_STATE_EVENT, UP_STATE, goto_up_state_fun }, -}; - -/*! - \brief the polling function of enumeration state - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] pustate: pointer to USB state driver - \param[out] none - \retval usb host status -*/ -usbh_status_enum enum_state_polling_fun (usb_core_handle_struct *pudev, usbh_host_struct *puhost, void *pustate) -{ - usbh_status_enum exe_state = USBH_BUSY; - usbh_state_handle_struct *p_state; - p_state = (usbh_state_handle_struct *)pustate; - - if (0U == enum_polling_handle_flag) { - enum_polling_handle_flag = 1U; - scd_table_push(p_state); - scd_state_move(p_state, ENUM_IDLE); - } - - /* start the enumeration state handle */ - scd_begin(p_state,ENUM_FSM_ID); - - if (0U == p_state->usbh_current_state_stack_top) { - enum_state_handle[p_state->usbh_current_state](pudev, puhost, p_state); - } else { - enum_state_handle[p_state->stack[1].state](pudev, puhost, p_state); - } - - /* determine the enumeration whether to complete */ - if (ENUM_DEV_CONFIGURED == puhost->usbh_backup_state.enum_backup_state) { - puhost->usbh_backup_state.enum_backup_state = ENUM_IDLE; - enum_polling_handle_flag = 0U; - exe_state = USBH_OK; - } - - return exe_state; -} - -/*! - \brief the handle function of ENUM_IDLE state - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] pustate: pointer to USB state driver - \param[out] none - \retval none -*/ -static void enum_idle_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.enum_backup_state = ENUM_IDLE; - - if (CTRL_IDLE == puhost->usbh_backup_state.ctrl_backup_state) { - usbh_enum_desc_get(pudev, - puhost, - pudev->host.rx_buffer, - USB_REQTYPE_DEVICE | USB_STANDARD_REQ, - USB_DEVDESC, - 8U); - if ((void *)0 != pudev->mdelay) { - pudev->mdelay(100U); - } - } - - if (USBH_OK == ctrl_state_polling_fun(pudev, puhost, pustate)) { - usbh_device_desc_parse(&puhost->device.dev_desc, pudev->host.rx_buffer, 8U); - puhost->control.ep0_size = puhost->device.dev_desc.bMaxPacketSize0; - - /* issue reset */ - usb_port_reset(pudev); - - /* modify control channels configuration for maxpacket size */ - usbh_channel_modify (pudev, - puhost->control.hc_out_num, - 0U, - 0U, - 0U, - (uint16_t)puhost->control.ep0_size); - - usbh_channel_modify (pudev, - puhost->control.hc_in_num, - 0U, - 0U, - 0U, - (uint16_t)puhost->control.ep0_size); - - scd_event_handle(pudev, - puhost, - pustate, - ENUM_EVENT_SET_ADDR, - pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of ENUM_GET_FULL_DEV_DESC state - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] pustate: pointer to USB state driver - \param[out] none - \retval none -*/ -static void enum_get_full_dev_desc_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.enum_backup_state = ENUM_GET_FULL_DEV_DESC; - - if (CTRL_IDLE == puhost->usbh_backup_state.ctrl_backup_state) { - usbh_enum_desc_get(pudev, - puhost, - pudev->host.rx_buffer, - USB_REQTYPE_DEVICE | USB_STANDARD_REQ, - USB_DEVDESC, - USB_DEVDESC_SIZE); - } - - if(USBH_OK == ctrl_state_polling_fun(pudev, puhost, pustate)){ - usbh_device_desc_parse(&puhost->device.dev_desc, pudev->host.rx_buffer, USB_DEVDESC_SIZE); - puhost->usr_cb->device_desc_available(&puhost->device.dev_desc); - - scd_event_handle(pudev, - puhost, - pustate, - ENUN_EVENT_GET_CFG_DESC, - pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of ENUM_SET_ADDR state - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] pustate: pointer to USB state driver - \param[out] none - \retval none -*/ -static void enum_set_addr_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.enum_backup_state = ENUM_SET_ADDR; - - if (CTRL_IDLE == puhost->usbh_backup_state.ctrl_backup_state) { - usbh_enum_addr_set(pudev, puhost,USBH_DEVICE_ADDRESS); - if ((void *)0 != pudev->mdelay) { - pudev->mdelay(100U); - } - } - - if (USBH_OK == ctrl_state_polling_fun(pudev, puhost, pustate)) { - if ((void *)0 != pudev->mdelay) { - pudev->mdelay(2U); - } - puhost->device.address = USBH_DEVICE_ADDRESS; - - /* user callback for device address assigned */ - puhost->usr_cb->device_address_set(); - - /* modify control channels to update device address */ - usbh_channel_modify (pudev, - puhost->control.hc_in_num, - puhost->device.address, - 0U, - 0U, - 0U); - - usbh_channel_modify (pudev, - puhost->control.hc_out_num, - puhost->device.address, - 0U, - 0U, - 0U); - - scd_event_handle(pudev, - puhost, - pustate, - ENUN_EVENT_GET_FULL_DEV_DESC, - pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of ENUM_GET_CFG_DESC state - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] pustate: pointer to USB state driver - \param[out] none - \retval none -*/ -static void enum_get_cfg_desc_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - uint16_t index = 0U; - - puhost->usbh_backup_state.enum_backup_state = ENUM_GET_CFG_DESC; - - if (CTRL_IDLE == puhost->usbh_backup_state.ctrl_backup_state) { - usbh_enum_desc_get(pudev, - puhost, - pudev->host.rx_buffer, - USB_REQTYPE_DEVICE | USB_STANDARD_REQ, - USB_CFGDESC, - USB_CFGDESC_SIZE); - } - - if (USBH_OK == ctrl_state_polling_fun(pudev, puhost, pustate)) { - /* save configuration descriptor for class parsing usage */ - for (; index < USB_CFGDESC_SIZE; index ++) { - usbh_cfg_desc[index] = pudev->host.rx_buffer[index]; - } - - /* commands successfully sent and response received */ - usbh_cfg_desc_parse (&puhost->device.cfg_desc, - puhost->device.itf_desc, - puhost->device.ep_desc, - pudev->host.rx_buffer, - USB_CFGDESC_SIZE); - - scd_event_handle(pudev, - puhost, - pustate, - ENUN_EVENT_GET_FULL_CFG_DESC, - pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of ENUM_GET_FULL_CFG_DESC state - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] pustate: pointer to USB state driver - \param[out] none - \retval none -*/ -static void enum_get_full_cfg_desc_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - - uint16_t index = 0U; - - puhost->usbh_backup_state.enum_backup_state = ENUM_GET_FULL_CFG_DESC; - - if (CTRL_IDLE == puhost->usbh_backup_state.ctrl_backup_state) { - usbh_enum_desc_get (pudev, puhost, pudev->host.rx_buffer, - USB_REQTYPE_DEVICE | USB_STANDARD_REQ, - USB_CFGDESC, puhost->device.cfg_desc.wTotalLength); - } - - - if (USBH_OK == ctrl_state_polling_fun(pudev, puhost, pustate)) { - /* save configuration descriptor for class parsing usage */ - for (; index < puhost->device.cfg_desc.wTotalLength; index ++) { - usbh_cfg_desc[index] = pudev->host.rx_buffer[index]; - } - - /* commands successfully sent and response received */ - usbh_cfg_desc_parse (&puhost->device.cfg_desc, - puhost->device.itf_desc, - puhost->device.ep_desc, - pudev->host.rx_buffer, - puhost->device.cfg_desc.wTotalLength); - - /* User callback for configuration descriptors available */ - puhost->usr_cb->configuration_desc_available(&puhost->device.cfg_desc, - puhost->device.itf_desc, - puhost->device.ep_desc[0]); - - scd_event_handle(pudev, - puhost, - pustate, - ENUN_EVENT_GET_MFC_STRING_DESC, - pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of ENUM_GET_MFC_STRING_DESC state - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] pustate: pointer to USB state driver - \param[out] none - \retval none -*/ -static void enum_get_mfc_string_desc_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.enum_backup_state = ENUM_GET_MFC_STRING_DESC; - - if (0U != puhost->device.dev_desc.iManufacturer) { - if(CTRL_IDLE == puhost->usbh_backup_state.ctrl_backup_state) { - usbh_enum_desc_get(pudev, - puhost, - pudev->host.rx_buffer, - USB_REQTYPE_DEVICE | USB_STANDARD_REQ, - USB_STRDESC | puhost->device.dev_desc.iManufacturer, - 0xffU); - } - - if (USBH_OK == ctrl_state_polling_fun(pudev, puhost, pustate)) { - usbh_string_desc_parse(pudev->host.rx_buffer, local_buffer, 0xffU); - puhost->usr_cb->manufacturer_string(local_buffer); - - scd_event_handle(pudev, - puhost, - pustate, - ENUN_EVENT_GET_PRODUCT_STRING_DESC, - pustate->usbh_current_state); - } - } else { - puhost->usr_cb->manufacturer_string("N/A"); - scd_state_move((usbh_state_handle_struct *)pustate, ENUM_GET_PRODUCT_STRING_DESC); - } -} - -/*! - \brief the handle function of ENUM_GET_PRODUCT_STRING_DESC state - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] pustate: pointer to USB state driver - \param[out] none - \retval none -*/ -static void enum_get_product_string_desc_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.enum_backup_state = ENUM_GET_PRODUCT_STRING_DESC; - - if (0U != puhost->device.dev_desc.iProduct) { - if (CTRL_IDLE == puhost->usbh_backup_state.ctrl_backup_state) { - usbh_enum_desc_get(pudev, - puhost, - pudev->host.rx_buffer, - USB_REQTYPE_DEVICE | USB_STANDARD_REQ, - USB_STRDESC | puhost->device.dev_desc.iProduct, - 0xffU); - } - - if (USBH_OK == ctrl_state_polling_fun(pudev, puhost, pustate)) { - usbh_string_desc_parse(pudev->host.rx_buffer, local_buffer, 0xffU); - - /* User callback for Product string */ - puhost->usr_cb->product_string(local_buffer); - - scd_event_handle(pudev, - puhost, - pustate, - ENUN_EVENT_GET_SERIALNUM_STRING_DESC, - pustate->usbh_current_state); - } - - } else { - puhost->usr_cb->product_string("N/A"); - scd_event_handle(pudev, - puhost, - pustate, - ENUN_EVENT_GET_SERIALNUM_STRING_DESC, - pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of ENUM_GET_SERIALNUM_STRING_DESC state - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] pustate: pointer to USB state driver - \param[out] none - \retval none -*/ -static void enum_get_serialnum_string_desc_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.enum_backup_state = ENUM_GET_SERIALNUM_STRING_DESC; - - if (0U != puhost->device.dev_desc.iSerialNumber) { - if (CTRL_IDLE == puhost->usbh_backup_state.ctrl_backup_state) { - usbh_enum_desc_get(pudev, - puhost, - pudev->host.rx_buffer, - USB_REQTYPE_DEVICE | USB_STANDARD_REQ, - USB_STRDESC | puhost->device.dev_desc.iSerialNumber, - 0xffU); - } - - if (USBH_OK == ctrl_state_polling_fun(pudev, puhost, pustate)){ - usbh_string_desc_parse(pudev->host.rx_buffer, local_buffer, 0xffU); - - /* user callback for product string */ - puhost->usr_cb->serial_num_string(local_buffer); - scd_event_handle(pudev, - puhost, - pustate, - ENUN_EVENT_SET_CONFIGURATION, - pustate->usbh_current_state); - } - } else { - puhost->usr_cb->serial_num_string("N/A"); - scd_event_handle(pudev, - puhost, - pustate, - ENUN_EVENT_SET_CONFIGURATION, - pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of ENUM_SET_CONFIGURATION state - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] pustate: pointer to USB state driver - \param[out] none - \retval none -*/ -static void enum_set_configuration_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.enum_backup_state = ENUM_SET_CONFIGURATION; - - if (CTRL_IDLE == puhost->usbh_backup_state.ctrl_backup_state ) { - usbh_enum_cfg_set(pudev, puhost, (uint16_t)puhost->device.cfg_desc.bConfigurationValue); - } - - if (USBH_OK == ctrl_state_polling_fun(pudev, puhost, pustate)) { - scd_event_handle(pudev, - puhost, - pustate, - ENUN_EVENT_DEV_CONFIGURED, - pustate->usbh_current_state); - } -} - -/*! - \brief the handle function of ENUM_DEV_CONFIGURED state - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] pustate: pointer to USB state driver - \param[out] none - \retval none -*/ -static void enum_dev_configured_handle (usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - usbh_state_handle_struct *pustate) -{ - puhost->usbh_backup_state.enum_backup_state = ENUM_DEV_CONFIGURED; - scd_event_handle(pudev, puhost, pustate, GO_TO_UP_STATE_EVENT, pustate->usbh_current_state); -} - -/*! - \brief get descriptor in usb host enumeration stage - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] buf: buffer to store the descriptor - \param[in] ReqType: descriptor type - \param[in] ValueIdx: wValue for the GetDescriptr request - \param[in] Len: length of the descriptor - \param[out] none - \retval none -*/ -void usbh_enum_desc_get(usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - uint8_t *buf, - uint8_t req_type, - uint16_t value_idx, - uint16_t len) -{ - usb_setup_union *pSetup = &(puhost->control.setup); - - pSetup->b.bmRequestType = USB_DIR_IN | req_type; - pSetup->b.bRequest = USBREQ_GET_DESCRIPTOR; - pSetup->b.wValue = value_idx; - - if (USB_STRDESC == (value_idx & 0xff00U)){ - pSetup->b.wIndex = 0x0409U; - } else { - pSetup->b.wIndex = 0U; - } - - pSetup->b.wLength = len; - - puhost->control.buff = buf; - puhost->control.length = len; - -} - -/*! - \brief set address in usb host enumeration stage - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] device_address: the device address - \param[out] none - \retval none -*/ -void usbh_enum_addr_set(usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - uint8_t device_address) -{ - usb_setup_union *p_setup = &(puhost->control.setup); - - p_setup->b.bmRequestType = USB_DIR_OUT | USB_REQTYPE_DEVICE | USB_STANDARD_REQ; - p_setup->b.bRequest = USBREQ_SET_ADDRESS; - p_setup->b.wValue = (uint16_t)device_address; - p_setup->b.wIndex = 0U; - p_setup->b.wLength = 0U; - puhost->control.buff = 0U; - puhost->control.length = 0U; -} - -/*! - \brief set configuration in usb host enumeration stage - \param[in] pudev: pointer to USB device - \param[in] puhost: pointer to USB host - \param[in] cfg_idx: the index of the configuration - \param[out] none - \retval none -*/ -void usbh_enum_cfg_set(usb_core_handle_struct *pudev, - usbh_host_struct *puhost, - uint16_t cfg_idx) -{ - usb_setup_union *p_setup = &(puhost->control.setup); - - p_setup->b.bmRequestType = USB_DIR_OUT | USB_REQTYPE_DEVICE | USB_STANDARD_REQ; - p_setup->b.bRequest = USBREQ_SET_CONFIGURATION; - p_setup->b.wValue = cfg_idx; - p_setup->b.wIndex = 0U; - p_setup->b.wLength = 0U; - puhost->control.buff = 0; - puhost->control.length = 0U; -} - -/*! - \brief parse the device descriptor - \param[in] dev_desc: device_descriptor destinaton address - \param[in] buf: buffer where the source descriptor is available - \param[in] len: length of the descriptor - \param[out] none - \retval none -*/ -void usbh_device_desc_parse (usb_descriptor_device_struct *dev_desc, uint8_t *buf, uint16_t len) -{ - dev_desc->Header.bLength = *(uint8_t *)(buf + 0); - dev_desc->Header.bDescriptorType = *(uint8_t *)(buf + 1); - dev_desc->bcdUSB = SWAPBYTE(buf + 2); - dev_desc->bDeviceClass = *(uint8_t *)(buf + 4); - dev_desc->bDeviceSubClass = *(uint8_t *)(buf + 5); - dev_desc->bDeviceProtocol = *(uint8_t *)(buf + 6); - dev_desc->bMaxPacketSize0 = *(uint8_t *)(buf + 7); - - if (len > 8U){ - /* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */ - dev_desc->idVendor = SWAPBYTE(buf + 8); - dev_desc->idProduct = SWAPBYTE(buf + 10); - dev_desc->bcdDevice = SWAPBYTE(buf + 12); - dev_desc->iManufacturer = *(uint8_t *)(buf + 14); - dev_desc->iProduct = *(uint8_t *)(buf + 15); - dev_desc->iSerialNumber = *(uint8_t *)(buf + 16); - dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17); - } -} - -/*! - \brief parse the configuration descriptor - \param[in] cfg_desc: configuration descriptor address - \param[in] itf_desc: interface descriptor address - \param[in] ep_desc: endpoint descriptor address - \param[in] buf: buffer where the source descriptor is available - \param[in] len: length of the descriptor - \param[out] none - \retval none -*/ -void usbh_cfg_desc_parse (usb_descriptor_configuration_struct *cfg_desc, - usb_descriptor_interface_struct *itf_desc, - usb_descriptor_endpoint_struct ep_desc[][USBH_MAX_EP_NUM], - uint8_t *buf, - uint16_t len) -{ - usb_descriptor_interface_struct *pitf = NULL; - usb_descriptor_interface_struct temp_pitf; - usb_descriptor_endpoint_struct *pep = NULL; - usb_descriptor_header_struct *pdesc = (usb_descriptor_header_struct *)buf; - - uint8_t itf_ix = 0U; - uint8_t ep_ix = 0U; - uint16_t ptr = 0U; - static uint8_t prev_itf = 0U; - static uint16_t prev_ep_size = 0U; - - /* parse configuration descriptor */ - cfg_desc->Header.bLength = *(uint8_t *)(buf + 0); - cfg_desc->Header.bDescriptorType = *(uint8_t *)(buf + 1); - cfg_desc->wTotalLength = SWAPBYTE(buf + 2); - cfg_desc->bNumInterfaces = *(uint8_t *)(buf + 4); - cfg_desc->bConfigurationValue = *(uint8_t *)(buf + 5); - cfg_desc->iConfiguration = *(uint8_t *)(buf + 6); - cfg_desc->bmAttributes = *(uint8_t *)(buf + 7); - cfg_desc->bMaxPower = *(uint8_t *)(buf + 8); - - if (len > USB_CFGDESC_SIZE) { - ptr = USB_CFG_DESC_LEN; - - if (cfg_desc->bNumInterfaces <= USBH_MAX_INTERFACES_NUM) { - pitf = (usb_descriptor_interface_struct *)0; - - for (; ptr < cfg_desc->wTotalLength; ) { - pdesc = usbh_next_desc_get((uint8_t *)pdesc, &ptr); - - if (USB_DESCTYPE_INTERFACE == pdesc->bDescriptorType) { - itf_ix = *((uint8_t *)pdesc + 2U); - pitf = &itf_desc[itf_ix]; - - if (*((uint8_t *)pdesc + 3U) < 3U) { - usbh_interface_desc_parse (&temp_pitf, (uint8_t *)pdesc); - - /* parse endpoint descriptors relative to the current interface */ - if (temp_pitf.bNumEndpoints <= USBH_MAX_EP_NUM) { - for (ep_ix = 0U; ep_ix < temp_pitf.bNumEndpoints;) { - pdesc = usbh_next_desc_get((void* )pdesc, &ptr); - - if (USB_DESCTYPE_ENDPOINT == pdesc->bDescriptorType) { - pep = &ep_desc[itf_ix][ep_ix]; - - if (prev_itf != itf_ix) { - prev_itf = itf_ix; - usbh_interface_desc_parse (pitf, (uint8_t *)&temp_pitf); - } else { - if (prev_ep_size > SWAPBYTE((uint8_t *)pdesc + 4)) { - break; - } else { - usbh_interface_desc_parse (pitf, (uint8_t *)&temp_pitf); - } - } - - usbh_endpoint_desc_parse (pep, (uint8_t *)pdesc); - prev_ep_size = SWAPBYTE((uint8_t *)pdesc + 4); - ep_ix++; - } - } - } - } - } - } - } - - prev_ep_size = 0U; - prev_itf = 0U; - } -} - -/*! - \brief parse the interface descriptor - \param[in] itf_desc: interface descriptor destination - \param[in] buf: buffer where the descriptor data is available - \param[out] none - \retval none -*/ -void usbh_interface_desc_parse (usb_descriptor_interface_struct *itf_desc, uint8_t *buf) -{ - itf_desc->Header.bLength = *(uint8_t *)(buf + 0); - itf_desc->Header.bDescriptorType = *(uint8_t *)(buf + 1); - itf_desc->bInterfaceNumber = *(uint8_t *)(buf + 2); - itf_desc->bAlternateSetting = *(uint8_t *)(buf + 3); - itf_desc->bNumEndpoints = *(uint8_t *)(buf + 4); - itf_desc->bInterfaceClass = *(uint8_t *)(buf + 5); - itf_desc->bInterfaceSubClass = *(uint8_t *)(buf + 6); - itf_desc->bInterfaceProtocol = *(uint8_t *)(buf + 7); - itf_desc->iInterface = *(uint8_t *)(buf + 8); -} - -/*! - \brief parse the endpoint descriptor - \param[in] ep_desc: endpoint descriptor destination address - \param[in] buf: buffer where the parsed descriptor stored - \param[out] none - \retval none -*/ -void usbh_endpoint_desc_parse (usb_descriptor_endpoint_struct *ep_desc, uint8_t *buf) -{ - ep_desc->Header.bLength = *(uint8_t *)(buf + 0); - ep_desc->Header.bDescriptorType = *(uint8_t *)(buf + 1); - ep_desc->bEndpointAddress = *(uint8_t *)(buf + 2); - ep_desc->bmAttributes = *(uint8_t *)(buf + 3); - ep_desc->wMaxPacketSize = SWAPBYTE(buf + 4); - ep_desc->bInterval = *(uint8_t *)(buf + 6); -} - -/*! - \brief parse the string descriptor - \param[in] psrc: source pointer containing the descriptor data - \param[in] pdest: destination address pointer - \param[in] len: length of the descriptor - \param[out] none - \retval none -*/ -void usbh_string_desc_parse (uint8_t* psrc, uint8_t* pdest, uint16_t len) -{ - uint16_t strlength; - uint16_t idx; - - /* the unicode string descriptor is not null-terminated. the string length is - computed by substracting two from the value of the first byte of the descriptor. - */ - - /* check which is lower size, the size of string or the length of bytes read from the device */ - - if (USB_DESCTYPE_STRING == psrc[1]){ - /* make sure the descriptor is string type */ - - /* psrc[0] contains size of descriptor, subtract 2 to get the length of string */ - strlength = ((((uint16_t)psrc[0] - 2U) <= len) ? ((uint16_t)psrc[0] - 2U) : len); - psrc += 2; /* adjust the offset ignoring the string len and descriptor type */ - - for (idx = 0U; idx < strlength; idx += 2U) { - /* copy only the string and ignore the unicode id, hence add the src */ - *pdest = psrc[idx]; - pdest++; - } - - *pdest = 0U; /* mark end of string */ - } -} - -/*! - \brief get the next descriptor header - \param[in] pbuf: pointer to buffer where the cfg descriptor is available - \param[in] ptr: data popinter inside the configuration descriptor - \param[out] none - \retval next descriptor header -*/ -usb_descriptor_header_struct *usbh_next_desc_get (uint8_t *pbuf, uint16_t *ptr) -{ - uint8_t len = ((usb_descriptor_header_struct *)pbuf)->bLength; - - usb_descriptor_header_struct *pnext; - - *ptr += len; - - pnext = (usb_descriptor_header_struct *)((uint8_t *)pbuf + len); - - return(pnext); -} - From f070d640215d718673f5ffe90c88d43dede8a349 Mon Sep 17 00:00:00 2001 From: iysheng Date: Wed, 9 Jun 2021 23:51:25 +0800 Subject: [PATCH 146/255] [bsp][gd32450z-eval] Synchronize firmware library updates --- bsp/gd32450z-eval/Libraries/SConscript | 4 ++-- bsp/gd32450z-eval/drivers/drv_usart.c | 6 +++--- bsp/gd32450z-eval/rtconfig.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bsp/gd32450z-eval/Libraries/SConscript b/bsp/gd32450z-eval/Libraries/SConscript index 75df263b3e..e9d6e45aae 100644 --- a/bsp/gd32450z-eval/Libraries/SConscript +++ b/bsp/gd32450z-eval/Libraries/SConscript @@ -21,12 +21,12 @@ path = [ cwd + '/CMSIS/GD/GD32F4xx/Include', cwd + '/CMSIS', cwd + '/GD32F4xx_standard_peripheral/Include',] - + if GetDepend(['RT_USING_BSP_USB']): path += [cwd + '/GD32F4xx_usb_driver/Include'] src += [cwd + '/GD32F4xx_usb_driver/Source'] -CPPDEFINES = ['USE_STDPERIPH_DRIVER', 'GD32F4XX'] +CPPDEFINES = ['USE_STDPERIPH_DRIVER'] group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) diff --git a/bsp/gd32450z-eval/drivers/drv_usart.c b/bsp/gd32450z-eval/drivers/drv_usart.c index fa691a42b9..423befbc93 100644 --- a/bsp/gd32450z-eval/drivers/drv_usart.c +++ b/bsp/gd32450z-eval/drivers/drv_usart.c @@ -377,14 +377,14 @@ static rt_err_t gd32_control(struct rt_serial_device *serial, int cmd, void *arg /* disable rx irq */ NVIC_DisableIRQ(uart->irqn); /* disable interrupt */ - usart_interrupt_disable(uart->uart_periph, USART_INTEN_RBNEIE); + usart_interrupt_disable(uart->uart_periph, USART_INT_RBNE); break; case RT_DEVICE_CTRL_SET_INT: /* enable rx irq */ NVIC_EnableIRQ(uart->irqn); /* enable interrupt */ - usart_interrupt_enable(uart->uart_periph, USART_INTEN_RBNEIE); + usart_interrupt_enable(uart->uart_periph, USART_INT_RBNE); break; } @@ -430,7 +430,7 @@ static void uart_isr(struct rt_serial_device *serial) RT_ASSERT(uart != RT_NULL); /* UART in mode Receiver -------------------------------------------------*/ - if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_RBNEIE) != RESET) && + if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_FLAG_RBNE) != RESET) && (usart_flag_get(uart->uart_periph, USART_FLAG_RBNE) != RESET)) { rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); diff --git a/bsp/gd32450z-eval/rtconfig.py b/bsp/gd32450z-eval/rtconfig.py index f137cf5a65..1f01ffe88b 100644 --- a/bsp/gd32450z-eval/rtconfig.py +++ b/bsp/gd32450z-eval/rtconfig.py @@ -38,7 +38,7 @@ if PLATFORM == 'gcc': OBJDUMP = PREFIX + 'objdump' OBJCPY = PREFIX + 'objcopy' - DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' + DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -DGD32F450' CFLAGS = DEVICE + ' -Dgcc' # -D' + PART_TYPE AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-gd32.map,-cref,-u,Reset_Handler -T gd32_rom.ld' From f2734c0a5438c57590217fbf7461c01a26eef9b2 Mon Sep 17 00:00:00 2001 From: iysheng Date: Thu, 10 Jun 2021 00:01:28 +0800 Subject: [PATCH 147/255] [bsp][gd32450z-eval] Formating files to pass the CI check --- .../CMSIS/GD/GD32F4xx/Include/gd32f4xx.h | 52 +++--- .../GD/GD32F4xx/Source/system_gd32f4xx.c | 156 +++++++++--------- bsp/gd32450z-eval/Libraries/CMSIS/core_cm4.h | 6 +- .../Libraries/CMSIS/core_cmFunc.h | 2 +- 4 files changed, 108 insertions(+), 108 deletions(-) diff --git a/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h b/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h index 6e704f8ed1..a901975bbd 100644 --- a/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h +++ b/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h @@ -1,7 +1,7 @@ /*! \file gd32f4xx.h \brief general definitions for GD32F4xx - + \version 2016-08-15, V1.0.0, firmware for GD32F4xx \version 2018-12-12, V2.0.0, firmware for GD32F4xx \version 2020-09-30, V2.1.0, firmware for GD32F4xx @@ -10,27 +10,27 @@ /* Copyright (c) 2020, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -39,7 +39,7 @@ OF SUCH DAMAGE. #ifdef __cplusplus extern "C" { -#endif +#endif /* define GD32F4xx */ #if !defined (GD32F450) && !defined (GD32F405) && !defined (GD32F407) @@ -47,7 +47,7 @@ OF SUCH DAMAGE. /* #define GD32F405 */ /* #define GD32F407 */ #endif /* define GD32F4xx */ - + #if !defined (GD32F450) && !defined (GD32F405) && !defined (GD32F407) #error "Please select the target GD32F4xx device in gd32f4xx.h file" #endif /* undefine GD32F4xx tip */ @@ -63,7 +63,7 @@ OF SUCH DAMAGE. #endif /* high speed crystal oscillator startup timeout */ /* define value of internal 16MHz RC oscillator (IRC16M) in Hz */ -#if !defined (IRC16M_VALUE) +#if !defined (IRC16M_VALUE) #define IRC16M_VALUE ((uint32_t)16000000) #endif /* internal 16MHz RC oscillator value */ @@ -73,12 +73,12 @@ OF SUCH DAMAGE. #endif /* internal 16MHz RC oscillator startup timeout */ /* define value of internal 32KHz RC oscillator(IRC32K) in Hz */ -#if !defined (IRC32K_VALUE) +#if !defined (IRC32K_VALUE) #define IRC32K_VALUE ((uint32_t)32000) #endif /* internal 32KHz RC oscillator value */ /* define value of low speed crystal oscillator (LXTAL)in Hz */ -#if !defined (LXTAL_VALUE) +#if !defined (LXTAL_VALUE) #define LXTAL_VALUE ((uint32_t)32768) #endif /* low speed crystal oscillator value */ @@ -89,7 +89,7 @@ OF SUCH DAMAGE. #define __GD32F4xx_STDPERIPH_VERSION_MAIN (0x03) /*!< [31:24] main version */ #define __GD32F4xx_STDPERIPH_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ #define __GD32F4xx_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ -#define __GD32F4xx_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __GD32F4xx_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ #define __GD32F4xx_STDPERIPH_VERSION ((__GD32F4xx_STDPERIPH_VERSION_MAIN << 24)\ |(__GD32F4xx_STDPERIPH_VERSION_SUB1 << 16)\ |(__GD32F4xx_STDPERIPH_VERSION_SUB2 << 8)\ @@ -162,7 +162,7 @@ typedef enum IRQn TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 trigger and commutation and TIMER13 interrupts */ TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupt */ DMA0_Channel7_IRQn = 47, /*!< DMA0 channel7 interrupt */ - + #if defined (GD32F450) EXMC_IRQn = 48, /*!< EXMC interrupt */ SDIO_IRQn = 49, /*!< SDIO interrupt */ @@ -294,7 +294,7 @@ typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; #define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr)) #define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr)) #define BIT(x) ((uint32_t)((uint32_t)0x01U<<(x))) -#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) +#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) #define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start)) /* main flash and SRAM memory map */ @@ -355,7 +355,7 @@ typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; /* define marco USE_STDPERIPH_DRIVER */ #if !defined USE_STDPERIPH_DRIVER #define USE_STDPERIPH_DRIVER -#endif +#endif #ifdef USE_STDPERIPH_DRIVER #include "gd32f4xx_libopt.h" #endif /* USE_STDPERIPH_DRIVER */ @@ -363,4 +363,4 @@ typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; #ifdef cplusplus } #endif -#endif +#endif diff --git a/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c b/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c index 058dcadca2..2ea97ae3f8 100644 --- a/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c +++ b/bsp/gd32450z-eval/Libraries/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c @@ -59,7 +59,7 @@ #define RCU_MODIFY {volatile uint32_t i; \ RCU_CFG0 |= RCU_AHB_CKSYS_DIV2; \ for(i=0;i<50000;i++);} - + /* set the system clock frequency and declare the system clock configuration function */ #ifdef __SYSTEM_CLOCK_IRC16M uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC16M; @@ -117,7 +117,7 @@ void SystemInit (void) RCU_CTL |= RCU_CTL_IRC16MEN; RCU_MODIFY - + /* Reset CFG0 register */ RCU_CFG0 = 0x00000000U; @@ -132,8 +132,8 @@ void SystemInit (void) /* Disable all interrupts */ RCU_INT = 0x00000000U; - - /* Configure the System clock source, PLL Multiplier and Divider factors, + + /* Configure the System clock source, PLL Multiplier and Divider factors, AHB/APBx prescalers and Flash settings ----------------------------------*/ system_clock_config(); } @@ -167,7 +167,7 @@ static void system_clock_config(void) system_clock_200m_8m_hxtal(); #elif defined (__SYSTEM_CLOCK_200M_PLL_25M_HXTAL) system_clock_200m_25m_hxtal(); -#endif /* __SYSTEM_CLOCK_IRC16M */ +#endif /* __SYSTEM_CLOCK_IRC16M */ } #ifdef __SYSTEM_CLOCK_IRC16M @@ -181,33 +181,33 @@ static void system_clock_16m_irc16m(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable IRC16M */ RCU_CTL |= RCU_CTL_IRC16MEN; - + /* wait until IRC16M is stable or the startup time is longer than IRC16M_STARTUP_TIMEOUT */ do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_IRC16MSTB); }while((0U == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout)); - + /* if fail */ if(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)){ while(1){ } } - + /* AHB = SYSCLK */ RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; /* APB2 = AHB */ RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; /* APB1 = AHB */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV1; - + /* select IRC16M as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_IRC16M; - + /* wait until IRC16M is selected as system clock */ while(0 != (RCU_CFG0 & RCU_SCSS_IRC16M)){ } @@ -224,33 +224,33 @@ static void system_clock_hxtal(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable HXTAL */ RCU_CTL |= RCU_CTL_HXTALEN; - + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - + /* if fail */ if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ while(1){ } } - + /* AHB = SYSCLK */ RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; /* APB2 = AHB */ RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; /* APB1 = AHB */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV1; - + /* select HXTAL as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_HXTAL; - + /* wait until HXTAL is selected as system clock */ while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){ } @@ -267,7 +267,7 @@ static void system_clock_120m_irc16m(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable IRC16M */ RCU_CTL |= RCU_CTL_IRC16MEN; @@ -282,7 +282,7 @@ static void system_clock_120m_irc16m(void) while(1){ } } - + RCU_APB1EN |= RCU_APB1EN_PMUEN; PMU_CTL |= PMU_CTL_LDOVS; @@ -294,7 +294,7 @@ static void system_clock_120m_irc16m(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PSC = 16, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ + /* Configure the main PLL, PSC = 16, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ RCU_PLL = (16U | (240U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_IRC16M) | (5U << 24U)); @@ -304,17 +304,17 @@ static void system_clock_120m_irc16m(void) /* wait until PLL is stable */ while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ } - + /* Enable the high-drive to extend the clock frequency to 120 Mhz */ PMU_CTL |= PMU_CTL_HDEN; while(0U == (PMU_CS & PMU_CS_HDRF)){ } - + /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; while(0U == (PMU_CS & PMU_CS_HDSRF)){ - } - + } + /* select PLL as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_PLLP; @@ -335,7 +335,7 @@ static void system_clock_120m_8m_hxtal(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable HXTAL */ RCU_CTL |= RCU_CTL_HXTALEN; @@ -350,7 +350,7 @@ static void system_clock_120m_8m_hxtal(void) while(1){ } } - + RCU_APB1EN |= RCU_APB1EN_PMUEN; PMU_CTL |= PMU_CTL_LDOVS; @@ -362,7 +362,7 @@ static void system_clock_120m_8m_hxtal(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PSC = 8, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ + /* Configure the main PLL, PSC = 8, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ RCU_PLL = (8U | (240U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_HXTAL) | (5U << 24U)); @@ -372,17 +372,17 @@ static void system_clock_120m_8m_hxtal(void) /* wait until PLL is stable */ while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ } - + /* Enable the high-drive to extend the clock frequency to 120 Mhz */ PMU_CTL |= PMU_CTL_HDEN; while(0U == (PMU_CS & PMU_CS_HDRF)){ } - + /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; while(0U == (PMU_CS & PMU_CS_HDSRF)){ - } - + } + /* select PLL as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_PLLP; @@ -403,7 +403,7 @@ static void system_clock_120m_25m_hxtal(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable HXTAL */ RCU_CTL |= RCU_CTL_HXTALEN; @@ -418,7 +418,7 @@ static void system_clock_120m_25m_hxtal(void) while(1){ } } - + RCU_APB1EN |= RCU_APB1EN_PMUEN; PMU_CTL |= PMU_CTL_LDOVS; @@ -430,7 +430,7 @@ static void system_clock_120m_25m_hxtal(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PSC = 25, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ + /* Configure the main PLL, PSC = 25, PLL_N = 240, PLL_P = 2, PLL_Q = 5 */ RCU_PLL = (25U | (240U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_HXTAL) | (5U << 24U)); @@ -440,17 +440,17 @@ static void system_clock_120m_25m_hxtal(void) /* wait until PLL is stable */ while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ } - + /* Enable the high-drive to extend the clock frequency to 120 Mhz */ PMU_CTL |= PMU_CTL_HDEN; while(0U == (PMU_CS & PMU_CS_HDRF)){ } - + /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; while(0U == (PMU_CS & PMU_CS_HDSRF)){ - } - + } + /* select PLL as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_PLLP; @@ -471,7 +471,7 @@ static void system_clock_168m_irc16m(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable IRC16M */ RCU_CTL |= RCU_CTL_IRC16MEN; @@ -486,7 +486,7 @@ static void system_clock_168m_irc16m(void) while(1){ } } - + RCU_APB1EN |= RCU_APB1EN_PMUEN; PMU_CTL |= PMU_CTL_LDOVS; @@ -498,7 +498,7 @@ static void system_clock_168m_irc16m(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PSC = 16, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ + /* Configure the main PLL, PSC = 16, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ RCU_PLL = (16U | (336U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_IRC16M) | (7U << 24U)); @@ -508,17 +508,17 @@ static void system_clock_168m_irc16m(void) /* wait until PLL is stable */ while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ } - + /* Enable the high-drive to extend the clock frequency to 168 Mhz */ PMU_CTL |= PMU_CTL_HDEN; while(0U == (PMU_CS & PMU_CS_HDRF)){ } - + /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; while(0U == (PMU_CS & PMU_CS_HDSRF)){ - } - + } + /* select PLL as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_PLLP; @@ -538,7 +538,7 @@ static void system_clock_168m_irc16m(void) static void system_clock_168m_8m_hxtal(void) { uint32_t timeout = 0U; - + /* enable HXTAL */ RCU_CTL |= RCU_CTL_HXTALEN; @@ -562,7 +562,7 @@ static void system_clock_168m_8m_hxtal(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PSC = 8, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ + /* Configure the main PLL, PSC = 8, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ RCU_PLL = (8U | (336 << 6U) | (((2 >> 1U) -1U) << 16U) | (RCU_PLLSRC_HXTAL) | (7 << 24U)); @@ -572,12 +572,12 @@ static void system_clock_168m_8m_hxtal(void) /* wait until PLL is stable */ while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ } - + /* Enable the high-drive to extend the clock frequency to 168 Mhz */ PMU_CTL |= PMU_CTL_HDEN; while(0U == (PMU_CS & PMU_CS_HDRF)){ } - + /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; while(0U == (PMU_CS & PMU_CS_HDSRF)){ @@ -603,7 +603,7 @@ static void system_clock_168m_25m_hxtal(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable HXTAL */ RCU_CTL |= RCU_CTL_HXTALEN; @@ -618,7 +618,7 @@ static void system_clock_168m_25m_hxtal(void) while(1){ } } - + RCU_APB1EN |= RCU_APB1EN_PMUEN; PMU_CTL |= PMU_CTL_LDOVS; @@ -630,7 +630,7 @@ static void system_clock_168m_25m_hxtal(void) /* APB1 = AHB */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PSC = 25, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ + /* Configure the main PLL, PSC = 25, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */ RCU_PLL = (25U | (336U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_HXTAL) | (7U << 24U)); @@ -640,17 +640,17 @@ static void system_clock_168m_25m_hxtal(void) /* wait until PLL is stable */ while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ } - + /* Enable the high-drive to extend the clock frequency to 168 Mhz */ PMU_CTL |= PMU_CTL_HDEN; while(0U == (PMU_CS & PMU_CS_HDRF)){ } - + /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; while(0U == (PMU_CS & PMU_CS_HDSRF)){ - } - + } + /* select PLL as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_PLLP; @@ -671,7 +671,7 @@ static void system_clock_200m_irc16m(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable IRC16M */ RCU_CTL |= RCU_CTL_IRC16MEN; @@ -686,7 +686,7 @@ static void system_clock_200m_irc16m(void) while(1){ } } - + RCU_APB1EN |= RCU_APB1EN_PMUEN; PMU_CTL |= PMU_CTL_LDOVS; @@ -698,7 +698,7 @@ static void system_clock_200m_irc16m(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PSC = 16, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ + /* Configure the main PLL, PSC = 16, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ RCU_PLL = (16U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_IRC16M) | (9U << 24U)); @@ -708,17 +708,17 @@ static void system_clock_200m_irc16m(void) /* wait until PLL is stable */ while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ } - + /* Enable the high-drive to extend the clock frequency to 200 Mhz */ PMU_CTL |= PMU_CTL_HDEN; while(0U == (PMU_CS & PMU_CS_HDRF)){ } - + /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; while(0U == (PMU_CS & PMU_CS_HDSRF)){ - } - + } + /* select PLL as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_PLLP; @@ -739,7 +739,7 @@ static void system_clock_200m_8m_hxtal(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable HXTAL */ RCU_CTL |= RCU_CTL_HXTALEN; @@ -754,7 +754,7 @@ static void system_clock_200m_8m_hxtal(void) while(1){ } } - + RCU_APB1EN |= RCU_APB1EN_PMUEN; PMU_CTL |= PMU_CTL_LDOVS; @@ -766,7 +766,7 @@ static void system_clock_200m_8m_hxtal(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PSC = 8, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ + /* Configure the main PLL, PSC = 8, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ RCU_PLL = (8U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_HXTAL) | (9U << 24U)); @@ -776,17 +776,17 @@ static void system_clock_200m_8m_hxtal(void) /* wait until PLL is stable */ while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ } - + /* Enable the high-drive to extend the clock frequency to 200 Mhz */ PMU_CTL |= PMU_CTL_HDEN; while(0U == (PMU_CS & PMU_CS_HDRF)){ } - + /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; while(0U == (PMU_CS & PMU_CS_HDSRF)){ - } - + } + /* select PLL as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_PLLP; @@ -807,7 +807,7 @@ static void system_clock_200m_25m_hxtal(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable HXTAL */ RCU_CTL |= RCU_CTL_HXTALEN; @@ -822,7 +822,7 @@ static void system_clock_200m_25m_hxtal(void) while(1){ } } - + RCU_APB1EN |= RCU_APB1EN_PMUEN; PMU_CTL |= PMU_CTL_LDOVS; @@ -834,7 +834,7 @@ static void system_clock_200m_25m_hxtal(void) /* APB1 = AHB/4 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; - /* Configure the main PLL, PSC = 25, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ + /* Configure the main PLL, PSC = 25, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */ RCU_PLL = (25U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) | (RCU_PLLSRC_HXTAL) | (9U << 24U)); @@ -844,17 +844,17 @@ static void system_clock_200m_25m_hxtal(void) /* wait until PLL is stable */ while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ } - + /* Enable the high-drive to extend the clock frequency to 200 Mhz */ PMU_CTL |= PMU_CTL_HDEN; while(0U == (PMU_CS & PMU_CS_HDRF)){ } - + /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; while(0U == (PMU_CS & PMU_CS_HDSRF)){ - } - + } + /* select PLL as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_PLLP; @@ -875,7 +875,7 @@ void SystemCoreClockUpdate (void) { uint32_t sws; uint32_t pllpsc, plln, pllsel, pllp, ck_src, idx, clk_exp; - + /* exponent of AHB, APB1 and APB2 clock divider */ const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; diff --git a/bsp/gd32450z-eval/Libraries/CMSIS/core_cm4.h b/bsp/gd32450z-eval/Libraries/CMSIS/core_cm4.h index d82841442c..e3cd89f728 100644 --- a/bsp/gd32450z-eval/Libraries/CMSIS/core_cm4.h +++ b/bsp/gd32450z-eval/Libraries/CMSIS/core_cm4.h @@ -100,7 +100,7 @@ #define __INLINE inline /*!< inline keyword for TASKING Compiler */ #define __STATIC_INLINE static inline -#elif defined ( __CSMC__ ) /* Cosmic */ +#elif defined ( __CSMC__ ) /* Cosmic */ #define __packed #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ #define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */ @@ -170,8 +170,8 @@ #define __FPU_USED 0 #endif -#elif defined ( __CSMC__ ) /* Cosmic */ - #if ( __CSMC__ & 0x400) // FPU present for parser +#elif defined ( __CSMC__ ) /* Cosmic */ + #if ( __CSMC__ & 0x400) // FPU present for parser #if (__FPU_PRESENT == 1) #define __FPU_USED 1 #else diff --git a/bsp/gd32450z-eval/Libraries/CMSIS/core_cmFunc.h b/bsp/gd32450z-eval/Libraries/CMSIS/core_cmFunc.h index b6ad0a4c5f..834bd17645 100644 --- a/bsp/gd32450z-eval/Libraries/CMSIS/core_cmFunc.h +++ b/bsp/gd32450z-eval/Libraries/CMSIS/core_cmFunc.h @@ -552,7 +552,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t v /** \brief Set Base Priority with condition This function assigns the given value to the Base Priority register only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. + or the new value increases the BASEPRI priority level. \param [in] basePri Base Priority value to set */ From 24b4b6cbb9d4b646ed52f1fc996e90f638a7aba6 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 9 Jun 2021 19:50:03 +0800 Subject: [PATCH 148/255] =?UTF-8?q?[kernel]=E8=A1=A5=E5=85=85endif?= =?UTF-8?q?=E5=90=8E=E7=BC=80=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/clock.c | 6 +++--- src/components.c | 26 +++++++++++++------------- src/cpu.c | 2 +- src/device.c | 14 +++++++------- src/idle.c | 32 ++++++++++++++++---------------- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/clock.c b/src/clock.c index 7df13775b2..77516b3775 100644 --- a/src/clock.c +++ b/src/clock.c @@ -24,7 +24,7 @@ #define rt_tick rt_cpu_index(0)->tick #else static volatile rt_tick_t rt_tick = 0; -#endif +#endif /* RT_USING_SMP */ /** * @addtogroup Clock @@ -72,7 +72,7 @@ void rt_tick_increase(void) rt_cpu_self()->tick ++; #else ++ rt_tick; -#endif +#endif /* RT_USING_SMP */ /* check time slice */ thread = rt_thread_self(); @@ -138,7 +138,7 @@ RT_WEAK rt_tick_t rt_tick_get_millisecond(void) #warning "rt-thread cannot provide a correct 1ms-based tick any longer,\ please redefine this function in another file by using a high-precision hard-timer." return 0; -#endif +#endif /* 1000 % RT_TICK_PER_SECOND == 0u */ } /**@}*/ diff --git a/src/components.c b/src/components.c index 9709d0aae2..d684d5e6fd 100644 --- a/src/components.c +++ b/src/components.c @@ -23,11 +23,11 @@ #ifdef RT_USING_USER_MAIN #ifndef RT_MAIN_THREAD_STACK_SIZE #define RT_MAIN_THREAD_STACK_SIZE 2048 -#endif +#endif /* RT_MAIN_THREAD_STACK_SIZE */ #ifndef RT_MAIN_THREAD_PRIORITY #define RT_MAIN_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 3) -#endif -#endif +#endif /* RT_MAIN_THREAD_PRIORITY */ +#endif /* RT_USING_USER_MAIN */ #ifdef RT_USING_COMPONENTS_INIT /* @@ -98,7 +98,7 @@ void rt_components_board_init(void) { (*fn_ptr)(); } -#endif +#endif /* RT_DEBUG_INIT */ } /** @@ -124,9 +124,9 @@ void rt_components_init(void) { (*fn_ptr)(); } -#endif +#endif /* RT_DEBUG_INIT */ } -#endif /* RT_USING_COMPONENTS_INIT */ +#endif /* RT_USING_COMPONENTS_INIT */ #ifdef RT_USING_USER_MAIN @@ -167,7 +167,7 @@ int entry(void) ALIGN(8) static rt_uint8_t main_stack[RT_MAIN_THREAD_STACK_SIZE]; struct rt_thread main_thread; -#endif +#endif /* RT_USING_HEAP */ /* the system main thread */ void main_thread_entry(void *parameter) @@ -177,11 +177,11 @@ void main_thread_entry(void *parameter) #ifdef RT_USING_COMPONENTS_INIT /* RT-Thread components initialization */ rt_components_init(); -#endif +#endif /* RT_USING_COMPONENTS_INIT */ #ifdef RT_USING_SMP rt_hw_secondary_cpu_up(); -#endif +#endif /* RT_USING_SMP */ /* invoke system main function */ #if defined(__CC_ARM) || defined(__CLANG_ARM) { @@ -211,7 +211,7 @@ void rt_application_init(void) /* if not define RT_USING_HEAP, using to eliminate the warning */ (void)result; -#endif +#endif /* RT_USING_HEAP */ rt_thread_startup(tid); } @@ -237,7 +237,7 @@ int rtthread_startup(void) #ifdef RT_USING_SIGNALS /* signal system initialization */ rt_system_signal_init(); -#endif +#endif /* RT_USING_SIGNALS */ /* create init_thread */ rt_application_init(); @@ -250,7 +250,7 @@ int rtthread_startup(void) #ifdef RT_USING_SMP rt_hw_spin_lock(&_cpus_lock); -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* start scheduler */ rt_system_scheduler_start(); @@ -258,4 +258,4 @@ int rtthread_startup(void) /* never reach here */ return 0; } -#endif +#endif /* RT_USING_USER_MAIN */ diff --git a/src/cpu.c b/src/cpu.c index 48ddb12c46..a7d56ba999 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -185,4 +185,4 @@ void rt_cpus_lock_status_restore(struct rt_thread *thread) } RTM_EXPORT(rt_cpus_lock_status_restore); -#endif +#endif /* RT_USING_SMP */ diff --git a/src/device.c b/src/device.c index 50b83c7692..a9c244d306 100644 --- a/src/device.c +++ b/src/device.c @@ -16,9 +16,9 @@ */ #include -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX #include /* for wqueue_init */ -#endif +#endif /* RT_USING_POSIX */ #ifdef RT_USING_DEVICE @@ -36,7 +36,7 @@ #define device_read (dev->read) #define device_write (dev->write) #define device_control (dev->control) -#endif +#endif /* RT_USING_DEVICE_OPS */ /** * This function registers a device driver with specified name. @@ -62,10 +62,10 @@ rt_err_t rt_device_register(rt_device_t dev, dev->ref_count = 0; dev->open_flag = 0; -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX dev->fops = RT_NULL; rt_wqueue_init(&(dev->wait_queue)); -#endif +#endif /* RT_USING_POSIX */ return RT_EOK; } @@ -150,7 +150,7 @@ void rt_device_destroy(rt_device_t dev) rt_free(dev); } RTM_EXPORT(rt_device_destroy); -#endif +#endif /* RT_USING_HEAP */ /** * This function will initialize the specified device @@ -434,4 +434,4 @@ rt_device_set_tx_complete(rt_device_t dev, } RTM_EXPORT(rt_device_set_tx_complete); -#endif +#endif /* RT_USING_DEVICE */ diff --git a/src/idle.c b/src/idle.c index e73a78be9c..db256a6010 100644 --- a/src/idle.c +++ b/src/idle.c @@ -22,27 +22,27 @@ #ifdef RT_USING_MODULE #include -#endif +#endif /* RT_USING_MODULE */ -#if defined (RT_USING_HOOK) +#ifdef RT_USING_HOOK #ifndef RT_USING_IDLE_HOOK #define RT_USING_IDLE_HOOK -#endif -#endif +#endif /* RT_USING_IDLE_HOOK */ +#endif /* RT_USING_HOOK */ #ifndef IDLE_THREAD_STACK_SIZE #if defined (RT_USING_IDLE_HOOK) || defined(RT_USING_HEAP) #define IDLE_THREAD_STACK_SIZE 256 #else #define IDLE_THREAD_STACK_SIZE 128 -#endif -#endif +#endif /* (RT_USING_IDLE_HOOK) || defined(RT_USING_HEAP) */ +#endif /* IDLE_THREAD_STACK_SIZE */ #ifdef RT_USING_SMP #define _CPUS_NR RT_CPUS_NR #else #define _CPUS_NR 1 -#endif +#endif /* RT_USING_SMP */ extern rt_list_t rt_thread_defunct; @@ -53,7 +53,7 @@ static rt_uint8_t rt_thread_stack[_CPUS_NR][IDLE_THREAD_STACK_SIZE]; #ifdef RT_USING_IDLE_HOOK #ifndef RT_IDLE_HOOK_LIST_SIZE #define RT_IDLE_HOOK_LIST_SIZE 4 -#endif +#endif /* RT_IDLE_HOOK_LIST_SIZE */ static void (*idle_hook_list[RT_IDLE_HOOK_LIST_SIZE])(void); @@ -125,7 +125,7 @@ rt_err_t rt_thread_idle_delhook(void (*hook)(void)) return ret; } -#endif +#endif /* RT_USING_IDLE_HOOK */ #ifdef RT_USING_HEAP /* Return whether there is defunctional thread to be deleted. */ @@ -141,7 +141,7 @@ rt_inline int _has_defunct_thread(void) return l->next != l; } -#endif +#endif /* RT_USING_HEAP */ /** * @ingroup Thread @@ -182,7 +182,7 @@ void rt_thread_idle_excute(void) rt_object_delete((rt_object_t)thread); rt_hw_interrupt_enable(lock); } -#endif +#endif /* RT_USING_HEAP */ } extern void rt_system_power_manager(void); @@ -196,7 +196,7 @@ static void rt_thread_idle_entry(void *parameter) rt_hw_secondary_cpu_idle_exec(); } } -#endif +#endif /* RT_USING_SMP */ while (1) { @@ -212,12 +212,12 @@ static void rt_thread_idle_entry(void *parameter) idle_hook(); } } -#endif +#endif /* RT_USING_IDLE_HOOK */ rt_thread_idle_excute(); #ifdef RT_USING_PM rt_system_power_manager(); -#endif +#endif /* RT_USING_PM */ } } @@ -246,7 +246,7 @@ void rt_thread_idle_init(void) 32); #ifdef RT_USING_SMP rt_thread_control(&idle[i], RT_THREAD_CTRL_BIND_CPU, (void*)i); -#endif +#endif /* RT_USING_SMP */ /* startup */ rt_thread_startup(&idle[i]); } @@ -264,7 +264,7 @@ rt_thread_t rt_thread_idle_gethandler(void) register int id = rt_hw_cpu_id(); #else register int id = 0; -#endif +#endif /* RT_USING_SMP */ return (rt_thread_t)(&idle[id]); } From e019a57ff30b9fda5aa43fdc97eac5cca80bbc3b Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Thu, 10 Jun 2021 17:58:31 +0800 Subject: [PATCH 149/255] =?UTF-8?q?[kernel]=20=E8=A1=A5=E5=85=85endif?= =?UTF-8?q?=E5=90=8E=E7=BC=80=E6=B3=A8=E9=87=8A(2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ipc.c | 30 ++++++++++++------------- src/irq.c | 6 ++--- src/kservice.c | 60 +++++++++++++++++++++++++------------------------- 3 files changed, 47 insertions(+), 49 deletions(-) diff --git a/src/ipc.c b/src/ipc.c index bda32dbf26..c981aabe43 100755 --- a/src/ipc.c +++ b/src/ipc.c @@ -48,7 +48,7 @@ extern void (*rt_object_trytake_hook)(struct rt_object *object); extern void (*rt_object_take_hook)(struct rt_object *object); extern void (*rt_object_put_hook)(struct rt_object *object); -#endif +#endif /* RT_USING_HOOK */ /** * @addtogroup IPC @@ -93,7 +93,7 @@ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list, { case RT_IPC_FLAG_FIFO: rt_list_insert_before(list, &(thread->tlist)); - break; + break; /* RT_IPC_FLAG_FIFO */ case RT_IPC_FLAG_PRIO: { @@ -121,7 +121,7 @@ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list, if (n == list) rt_list_insert_before(list, &(thread->tlist)); } - break; + break;/* RT_IPC_FLAG_PRIO */ default: RT_ASSERT(0); @@ -319,7 +319,7 @@ rt_err_t rt_sem_delete(rt_sem_t sem) return RT_EOK; } RTM_EXPORT(rt_sem_delete); -#endif +#endif /* RT_USING_HEAP */ /** * This function will take a semaphore, if the semaphore is unavailable, the @@ -533,7 +533,7 @@ rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_sem_control); -#endif /* end of RT_USING_SEMAPHORE */ +#endif /* RT_USING_SEMAPHORE */ #ifdef RT_USING_MUTEX /** @@ -659,7 +659,7 @@ rt_err_t rt_mutex_delete(rt_mutex_t mutex) return RT_EOK; } RTM_EXPORT(rt_mutex_delete); -#endif +#endif /* RT_USING_HEAP */ /** * This function will take a mutex, if the mutex is unavailable, the @@ -714,7 +714,7 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time) { #ifdef RT_USING_SIGNALS __again: -#endif /* end of RT_USING_SIGNALS */ +#endif /* RT_USING_SIGNALS */ /* The value of mutex is 1 in initial status. Therefore, if the * value is great than 0, it indicates the mutex is avaible. */ @@ -794,7 +794,7 @@ __again: #ifdef RT_USING_SIGNALS /* interrupt by signal, try it again */ if (thread->error == -RT_EINTR) goto __again; -#endif /* end of RT_USING_SIGNALS */ +#endif /* RT_USING_SIGNALS */ /* return error */ return thread->error; @@ -968,7 +968,7 @@ rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_mutex_control); -#endif /* end of RT_USING_MUTEX */ +#endif /* RT_USING_MUTEX */ #ifdef RT_USING_EVENT /** @@ -1084,7 +1084,7 @@ rt_err_t rt_event_delete(rt_event_t event) return RT_EOK; } RTM_EXPORT(rt_event_delete); -#endif +#endif /* RT_USING_HEAP */ /** * This function will send an event to the event object, if there are threads @@ -1361,7 +1361,7 @@ rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_event_control); -#endif /* end of RT_USING_EVENT */ +#endif /* RT_USING_EVENT */ #ifdef RT_USING_MAILBOX /** @@ -1512,7 +1512,7 @@ rt_err_t rt_mb_delete(rt_mailbox_t mb) return RT_EOK; } RTM_EXPORT(rt_mb_delete); -#endif +#endif /* RT_USING_HEAP */ /** * This function will send a mail to mailbox object. If the mailbox is full, @@ -1919,7 +1919,7 @@ rt_err_t rt_mb_control(rt_mailbox_t mb, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_mb_control); -#endif /* end of RT_USING_MAILBOX */ +#endif /* RT_USING_MAILBOX */ #ifdef RT_USING_MESSAGEQUEUE struct rt_mq_message @@ -2121,7 +2121,7 @@ rt_err_t rt_mq_delete(rt_mq_t mq) return RT_EOK; } RTM_EXPORT(rt_mq_delete); -#endif +#endif /* RT_USING_HEAP */ /** * This function will send a message to message queue object. If the message queue is full, @@ -2625,6 +2625,6 @@ rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_mq_control); -#endif /* end of RT_USING_MESSAGEQUEUE */ +#endif /* RT_USING_MESSAGEQUEUE */ /**@}*/ diff --git a/src/irq.c b/src/irq.c index 65fc2ea5e0..e89b8504dc 100644 --- a/src/irq.c +++ b/src/irq.c @@ -39,9 +39,7 @@ void rt_interrupt_leave_sethook(void (*hook)(void)) { rt_interrupt_leave_hook = hook; } -#endif - -/* #define IRQ_DEBUG */ +#endif /* RT_USING_HOOK */ /** * @addtogroup Kernel @@ -53,7 +51,7 @@ void rt_interrupt_leave_sethook(void (*hook)(void)) #define rt_interrupt_nest rt_cpu_self()->irq_nest #else volatile rt_uint8_t rt_interrupt_nest = 0; -#endif +#endif /* RT_USING_SMP */ /** * This function will be invoked by BSP, when enter interrupt service routine diff --git a/src/kservice.c b/src/kservice.c index 7ed05b6651..c4bbdd9151 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -25,7 +25,7 @@ #ifdef RT_USING_MODULE #include -#endif +#endif /* RT_USING_MODULE */ /* use precision */ #define RT_PRINTF_PRECISION @@ -194,7 +194,7 @@ RT_WEAK void *rt_memset(void *s, int c, rt_ubase_t count) #undef LBLOCKSIZE #undef UNALIGNED #undef TOO_SMALL -#endif +#endif /* RT_KSERVICE_USING_TINY_SIZE */ } RTM_EXPORT(rt_memset); @@ -277,7 +277,7 @@ RT_WEAK void *rt_memcpy(void *dst, const void *src, rt_ubase_t count) #undef BIGBLOCKSIZE #undef LITTLEBLOCKSIZE #undef TOO_SMALL -#endif +#endif /* RT_KSERVICE_USING_TINY_SIZE */ } RTM_EXPORT(rt_memcpy); @@ -509,7 +509,7 @@ rt_size_t rt_strlen(const char *s) } RTM_EXPORT(rt_strlen); -#endif /*RT_KSERVICE_USING_STDLIB*/ +#endif /* RT_KSERVICE_USING_STDLIB */ #ifdef RT_USING_HEAP /** @@ -535,7 +535,7 @@ RTM_EXPORT(rt_strdup); #if defined(__CC_ARM) || defined(__CLANG_ARM) char *strdup(const char *s) __attribute__((alias("rt_strdup"))); #endif -#endif +#endif /* RT_USING_HEAP */ /** * This function will show the version of rt-thread rtos @@ -591,7 +591,7 @@ rt_inline int divide(long *n, int base) return res; } -#endif +#endif /* RT_PRINTF_LONGLONG */ rt_inline int skip_atoi(const char **s) { @@ -617,7 +617,7 @@ static char *print_number(char *buf, long long num, #else long num, -#endif +#endif /* RT_PRINTF_LONGLONG */ int base, int s, int precision, @@ -629,18 +629,18 @@ static char *print_number(char *buf, long long num, #else long num, -#endif +#endif /* RT_PRINTF_LONGLONG */ int base, int s, int type) -#endif +#endif /* RT_PRINTF_PRECISION */ { char c, sign; #ifdef RT_PRINTF_LONGLONG char tmp[32]; #else char tmp[16]; -#endif +#endif /* RT_PRINTF_LONGLONG */ int precision_bak = precision; const char *digits; static const char small_digits[] = "0123456789abcdef"; @@ -679,7 +679,7 @@ static char *print_number(char *buf, else if (base == 8) size--; } -#endif +#endif /* RT_PRINTF_SPECIAL */ i = 0; if (num == 0) @@ -696,7 +696,7 @@ static char *print_number(char *buf, size -= precision; #else size -= i; -#endif +#endif /* RT_PRINTF_PRECISION */ if (!(type & (ZEROPAD | LEFT))) { @@ -742,7 +742,7 @@ static char *print_number(char *buf, ++ buf; } } -#endif +#endif /* RT_PRINTF_SPECIAL */ /* no align to the left */ if (!(type & LEFT)) @@ -762,7 +762,7 @@ static char *print_number(char *buf, *buf = '0'; ++ buf; } -#endif +#endif /* RT_PRINTF_PRECISION */ /* put number in the temporary buffer */ while (i-- > 0 && (precision_bak != 0)) @@ -791,7 +791,7 @@ rt_int32_t rt_vsnprintf(char *buf, unsigned long long num; #else rt_uint32_t num; -#endif +#endif /* RT_PRINTF_LONGLONG */ int i, len; char *str, *end, c; const char *s; @@ -803,7 +803,7 @@ rt_int32_t rt_vsnprintf(char *buf, #ifdef RT_PRINTF_PRECISION int precision; /* min. # of digits for integers and max for a string */ -#endif +#endif /* RT_PRINTF_PRECISION */ str = buf; end = buf + size; @@ -870,14 +870,14 @@ rt_int32_t rt_vsnprintf(char *buf, } if (precision < 0) precision = 0; } -#endif +#endif /* RT_PRINTF_PRECISION */ /* get the conversion qualifier */ qualifier = 0; #ifdef RT_PRINTF_LONGLONG if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') #else if (*fmt == 'h' || *fmt == 'l') -#endif +#endif /* RT_PRINTF_LONGLONG */ { qualifier = *fmt; ++ fmt; @@ -887,7 +887,7 @@ rt_int32_t rt_vsnprintf(char *buf, qualifier = 'L'; ++ fmt; } -#endif +#endif /* RT_PRINTF_LONGLONG */ } /* the default base */ @@ -925,7 +925,7 @@ rt_int32_t rt_vsnprintf(char *buf, for (len = 0; (len != field_width) && (s[len] != '\0'); len++); #ifdef RT_PRINTF_PRECISION if (precision > 0 && len > precision) len = precision; -#endif +#endif /* RT_PRINTF_PRECISION */ if (!(flags & LEFT)) { @@ -964,7 +964,7 @@ rt_int32_t rt_vsnprintf(char *buf, str = print_number(str, end, (long)va_arg(args, void *), 16, field_width, flags); -#endif +#endif /* RT_PRINTF_PRECISION */ continue; case '%': @@ -1010,7 +1010,7 @@ rt_int32_t rt_vsnprintf(char *buf, else if (qualifier == 'l') #else if (qualifier == 'l') -#endif +#endif /* RT_PRINTF_LONGLONG */ { num = va_arg(args, rt_uint32_t); if (flags & SIGN) num = (rt_int32_t)num; @@ -1029,7 +1029,7 @@ rt_int32_t rt_vsnprintf(char *buf, str = print_number(str, end, num, base, field_width, precision, flags); #else str = print_number(str, end, num, base, field_width, flags); -#endif +#endif /* RT_PRINTF_PRECISION */ } if (size > 0) @@ -1152,7 +1152,7 @@ rt_device_t rt_console_set_device(const char *name) return old_device; } RTM_EXPORT(rt_console_set_device); -#endif +#endif /* RT_USING_DEVICE */ RT_WEAK void rt_hw_console_output(const char *str) { @@ -1184,7 +1184,7 @@ void rt_kputs(const char *str) } #else rt_hw_console_output(str); -#endif +#endif /* RT_USING_DEVICE */ } /** @@ -1222,11 +1222,11 @@ RT_WEAK void rt_kprintf(const char *fmt, ...) } #else rt_hw_console_output(rt_log_buf); -#endif +#endif /* RT_USING_DEVICE */ va_end(args); } RTM_EXPORT(rt_kprintf); -#endif +#endif /* RT_USING_CONSOLE */ #ifdef RT_USING_HEAP /** @@ -1292,7 +1292,7 @@ void rt_free_align(void *ptr) rt_free(real_ptr); } RTM_EXPORT(rt_free_align); -#endif +#endif /* RT_USING_HEAP */ #ifndef RT_USING_CPU_FFS const rt_uint8_t __lowest_bit_bitmap[] = @@ -1340,7 +1340,7 @@ int __rt_ffs(int value) return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25; } -#endif +#endif /* RT_USING_CPU_FFS */ #ifdef RT_DEBUG /* RT_ASSERT(EX)'s hook */ @@ -1377,7 +1377,7 @@ void rt_assert_handler(const char *ex_string, const char *func, rt_size_t line) dlmodule_exit(-1); } else -#endif +#endif /*RT_USING_MODULE*/ { rt_kprintf("(%s) assertion failed at function:%s, line number:%d \n", ex_string, func, line); while (dummy == 0); From 8b53609f574209b11f649f946466fd0e0244eb60 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Thu, 10 Jun 2021 18:33:47 +0800 Subject: [PATCH 150/255] =?UTF-8?q?[kernel]=20=E8=A1=A5=E5=85=85endif?= =?UTF-8?q?=E5=90=8E=E7=BC=80=E6=B3=A8=E9=87=8A(3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/memheap.c | 30 +++++++++---------- src/mempool.c | 7 ++--- src/object.c | 14 ++++----- src/scheduler.c | 76 ++++++++++++++++++++++++------------------------- src/signal.c | 12 ++++---- src/slab.c | 22 +++++++------- src/thread.c | 34 +++++++++++----------- src/timer.c | 20 ++++++------- 8 files changed, 107 insertions(+), 108 deletions(-) diff --git a/src/memheap.c b/src/memheap.c index 35a04c14b1..feac8bb4aa 100644 --- a/src/memheap.c +++ b/src/memheap.c @@ -74,7 +74,7 @@ void rt_mem_set_tag(void *ptr, const char *name) rt_memheap_setname(item, name); } } -#endif +#endif /* RT_USING_MEMTRACE */ /* * The initialized memory pool will be: @@ -127,7 +127,7 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap, #ifdef RT_USING_MEMTRACE rt_memset(item->owner_thread_name, ' ', sizeof(item->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ item->next = (struct rt_memheap_item *) ((rt_uint8_t *)item + memheap->available_size + RT_MEMHEAP_SIZE); @@ -252,7 +252,7 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size) #ifdef RT_USING_MEMTRACE rt_memset(new_ptr->owner_thread_name, ' ', sizeof(new_ptr->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ /* break down the block list */ new_ptr->prev = header_ptr; @@ -310,7 +310,7 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size) rt_memcpy(header_ptr->owner_thread_name, rt_thread_self()->name, sizeof(header_ptr->owner_thread_name)); else rt_memcpy(header_ptr->owner_thread_name, "NONE", sizeof(header_ptr->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ /* release lock */ rt_sem_release(&(heap->lock)); @@ -439,7 +439,7 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize) #ifdef RT_USING_MEMTRACE rt_memset(next_ptr->owner_thread_name, ' ', sizeof(next_ptr->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ next_ptr->prev = header_ptr; next_ptr->next = header_ptr->next; @@ -507,7 +507,7 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize) #ifdef RT_USING_MEMTRACE rt_memset(new_ptr->owner_thread_name, ' ', sizeof(new_ptr->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ /* break down the block list */ new_ptr->prev = header_ptr; @@ -660,7 +660,7 @@ void rt_memheap_free(void *ptr) #ifdef RT_USING_MEMTRACE rt_memset(header_ptr->owner_thread_name, ' ', sizeof(header_ptr->owner_thread_name)); -#endif +#endif /* RT_USING_MEMTRACE */ /* release lock */ rt_sem_release(&(heap->lock)); @@ -750,7 +750,7 @@ int memheaptrace(void) return 0; } MSH_CMD_EXPORT(memheaptrace, dump memory trace information); -#endif +#endif /* RT_USING_FINSH */ #ifdef RT_USING_MEMHEAP_AS_HEAP static struct rt_memheap _heap; @@ -816,7 +816,7 @@ void *rt_malloc(rt_size_t size) RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("malloc => 0x%08x : %d", ptr, size)); } -#endif +#endif /* RT_USING_MEMTRACE */ return ptr; } @@ -882,7 +882,7 @@ void *rt_realloc(void *rmem, rt_size_t newsize) RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("realloc => 0x%08x : %d", new_ptr, newsize)); } -#endif +#endif /* RT_USING_MEMTRACE */ return new_ptr; } @@ -912,7 +912,7 @@ void *rt_calloc(rt_size_t count, rt_size_t size) RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("calloc => 0x%08x : %d", ptr, count * size)); } -#endif +#endif /* RT_USING_MEMTRACE */ return ptr; } @@ -932,7 +932,7 @@ void rt_memory_info(rt_uint32_t *total, *max_used = _heap.max_used_size; } -#endif +#endif /* RT_USING_MEMHEAP_AS_HEAP */ #ifdef RT_USING_MEMTRACE @@ -1004,8 +1004,8 @@ void memtrace_heap() #ifdef RT_USING_FINSH #include MSH_CMD_EXPORT(memtrace_heap, dump memory trace for heap); -#endif /* end of RT_USING_FINSH */ +#endif /* RT_USING_FINSH */ -#endif /* end of RT_USING_MEMTRACE */ +#endif /* RT_USING_MEMTRACE */ -#endif /* end of RT_USING_MEMHEAP */ +#endif /* RT_USING_MEMHEAP */ diff --git a/src/mempool.c b/src/mempool.c index 1de48940d7..5ac87d2bc8 100644 --- a/src/mempool.c +++ b/src/mempool.c @@ -54,7 +54,7 @@ void rt_mp_free_sethook(void (*hook)(struct rt_mempool *mp, void *block)) } /**@}*/ -#endif +#endif /* RT_USING_HOOK */ /** * @addtogroup MM @@ -290,7 +290,7 @@ rt_err_t rt_mp_delete(rt_mp_t mp) return RT_EOK; } RTM_EXPORT(rt_mp_delete); -#endif +#endif /* RT_USING_HEAP */ /** * This function will allocate a block from memory pool @@ -451,5 +451,4 @@ RTM_EXPORT(rt_mp_free); /**@}*/ -#endif - +#endif /* RT_USING_MEMPOOL */ diff --git a/src/object.c b/src/object.c index 013e2d1e33..ff96037c52 100644 --- a/src/object.c +++ b/src/object.c @@ -20,7 +20,7 @@ #ifdef RT_USING_MODULE #include -#endif +#endif /* RT_USING_MODULE */ /* * define object_info for the number of rt_object_container items. @@ -189,7 +189,7 @@ void rt_object_put_sethook(void (*hook)(struct rt_object *object)) } /**@}*/ -#endif +#endif /* RT_USING_HOOK */ /** * @addtogroup KernelObject @@ -305,7 +305,7 @@ void rt_object_init(struct rt_object *object, struct rt_object_information *information; #ifdef RT_USING_MODULE struct rt_dlmodule *module = dlmodule_self(); -#endif +#endif /* RT_USING_MODULE */ /* get object information */ information = rt_object_get_information(type); @@ -349,7 +349,7 @@ void rt_object_init(struct rt_object *object, object->module_id = (void *)module; } else -#endif +#endif /* RT_USING_MODULE */ { /* insert object into information object list */ rt_list_insert_after(&(information->object_list), &(object->list)); @@ -403,7 +403,7 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) struct rt_object_information *information; #ifdef RT_USING_MODULE struct rt_dlmodule *module = dlmodule_self(); -#endif +#endif /* RT_USING_MODULE */ RT_DEBUG_NOT_IN_INTERRUPT; @@ -444,7 +444,7 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) object->module_id = (void *)module; } else -#endif +#endif /* RT_USING_MODULE */ { /* insert object into information object list */ rt_list_insert_after(&(information->object_list), &(object->list)); @@ -487,7 +487,7 @@ void rt_object_delete(rt_object_t object) /* free the memory of object */ RT_KERNEL_FREE(object); } -#endif +#endif /* RT_USING_HEAP */ /** * This function will judge the object is system object or not. diff --git a/src/scheduler.c b/src/scheduler.c index ed0f30fc81..eec660a8aa 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -38,14 +38,14 @@ rt_uint32_t rt_thread_ready_priority_group; #if RT_THREAD_PRIORITY_MAX > 32 /* Maximum priority level, 256 */ rt_uint8_t rt_thread_ready_table[32]; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ #ifndef RT_USING_SMP extern volatile rt_uint8_t rt_interrupt_nest; static rt_int16_t rt_scheduler_lock_nest; struct rt_thread *rt_current_thread = RT_NULL; rt_uint8_t rt_current_priority; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ rt_list_t rt_thread_defunct; @@ -71,18 +71,18 @@ rt_scheduler_sethook(void (*hook)(struct rt_thread *from, struct rt_thread *to)) } /**@}*/ -#endif +#endif /* RT_USING_HOOK */ #ifdef RT_USING_OVERFLOW_CHECK static void _rt_scheduler_stack_check(struct rt_thread *thread) { RT_ASSERT(thread != RT_NULL); -#if defined(ARCH_CPU_STACK_GROWS_UPWARD) +#ifdef ARCH_CPU_STACK_GROWS_UPWARD if (*((rt_uint8_t *)((rt_ubase_t)thread->stack_addr + thread->stack_size - 1)) != '#' || #else if (*((rt_uint8_t *)thread->stack_addr) != '#' || -#endif +#endif /* ARCH_CPU_STACK_GROWS_UPWARD */ (rt_ubase_t)thread->sp <= (rt_ubase_t)thread->stack_addr || (rt_ubase_t)thread->sp > (rt_ubase_t)thread->stack_addr + (rt_ubase_t)thread->stack_size) @@ -94,7 +94,7 @@ static void _rt_scheduler_stack_check(struct rt_thread *thread) level = rt_hw_interrupt_disable(); while (level); } -#if defined(ARCH_CPU_STACK_GROWS_UPWARD) +#ifdef ARCH_CPU_STACK_GROWS_UPWARD else if ((rt_ubase_t)thread->sp > ((rt_ubase_t)thread->stack_addr + thread->stack_size)) { rt_kprintf("warning: %s stack is close to the top of stack address.\n", @@ -106,9 +106,9 @@ static void _rt_scheduler_stack_check(struct rt_thread *thread) rt_kprintf("warning: %s stack is close to end of stack address.\n", thread->name); } -#endif +#endif /* ARCH_CPU_STACK_GROWS_UPWARD */ } -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ /* * get the highest priority thread in ready queue @@ -129,7 +129,7 @@ static struct rt_thread* _get_highest_priority_thread(rt_ubase_t *highest_prio) #else highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1; local_highest_ready_priority = __rt_ffs(pcpu->priority_group) - 1; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* get highest ready priority thread */ if (highest_ready_priority < local_highest_ready_priority) @@ -162,7 +162,7 @@ static struct rt_thread* _get_highest_priority_thread(rt_ubase_t *highest_prio) highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1; #else highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* get highest ready priority thread */ highest_priority_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next, @@ -173,7 +173,7 @@ static struct rt_thread* _get_highest_priority_thread(rt_ubase_t *highest_prio) return highest_priority_thread; } -#endif +#endif /* RT_USING_SMP */ /** * @ingroup SystemInit @@ -183,12 +183,12 @@ void rt_system_scheduler_init(void) { #ifdef RT_USING_SMP int cpu; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ register rt_base_t offset; #ifndef RT_USING_SMP rt_scheduler_lock_nest = 0; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("start scheduler: max priority 0x%02x\n", RT_THREAD_PRIORITY_MAX)); @@ -213,9 +213,9 @@ void rt_system_scheduler_init(void) #if RT_THREAD_PRIORITY_MAX > 32 rt_memset(pcpu->ready_table, 0, sizeof(pcpu->ready_table)); -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* initialize ready priority group */ rt_thread_ready_priority_group = 0; @@ -223,7 +223,7 @@ void rt_system_scheduler_init(void) #if RT_THREAD_PRIORITY_MAX > 32 /* initialize ready table */ rt_memset(rt_thread_ready_table, 0, sizeof(rt_thread_ready_table)); -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* initialize thread defunct */ rt_list_init(&rt_thread_defunct); @@ -245,7 +245,7 @@ void rt_system_scheduler_start(void) to_thread->oncpu = rt_hw_cpu_id(); #else rt_current_thread = to_thread; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ rt_schedule_remove_thread(to_thread); to_thread->stat = RT_THREAD_RUNNING; @@ -255,7 +255,7 @@ void rt_system_scheduler_start(void) rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp, to_thread); #else rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp); -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* never come back */ } @@ -319,7 +319,7 @@ void rt_schedule(void) rt_thread_resume(current_thread); } } -#endif +#endif /* RT_USING_SIGNALS */ if (current_thread->scheduler_lock_nest == 1) /* whether lock scheduler */ { @@ -367,7 +367,7 @@ void rt_schedule(void) #ifdef RT_USING_OVERFLOW_CHECK _rt_scheduler_stack_check(to_thread); -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ rt_hw_context_switch((rt_ubase_t)¤t_thread->sp, (rt_ubase_t)&to_thread->sp, to_thread); @@ -396,7 +396,7 @@ void rt_schedule(void) { rt_hw_interrupt_enable(level); } -#endif +#endif /* RT_USING_SIGNALS */ __exit: return ; @@ -472,7 +472,7 @@ void rt_schedule(void) #ifdef RT_USING_OVERFLOW_CHECK _rt_scheduler_stack_check(to_thread); -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ if (rt_interrupt_nest == 0) { @@ -502,7 +502,7 @@ void rt_schedule(void) { rt_hw_interrupt_enable(level); } -#endif +#endif /* RT_USING_SIGNALS */ goto __exit; } else @@ -527,7 +527,7 @@ void rt_schedule(void) __exit: return; } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /** * This function checks if a scheduling is needed after IRQ context. If yes, @@ -559,7 +559,7 @@ void rt_scheduler_do_irq_switch(void *context) rt_thread_resume(current_thread); } } -#endif +#endif /* RT_USING_SIGNALS */ if (pcpu->irq_switch_flag == 0) { @@ -608,7 +608,7 @@ void rt_scheduler_do_irq_switch(void *context) #ifdef RT_USING_OVERFLOW_CHECK _rt_scheduler_stack_check(to_thread); -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("switch in interrupt\n")); current_thread->cpus_lock_nest--; @@ -621,7 +621,7 @@ void rt_scheduler_do_irq_switch(void *context) } rt_hw_interrupt_enable(level); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* * This function will insert a thread to system ready queue. The state of @@ -661,7 +661,7 @@ void rt_schedule_insert_thread(struct rt_thread *thread) { #if RT_THREAD_PRIORITY_MAX > 32 rt_thread_ready_table[thread->number] |= thread->high_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ rt_thread_ready_priority_group |= thread->number_mask; rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]), @@ -675,7 +675,7 @@ void rt_schedule_insert_thread(struct rt_thread *thread) #if RT_THREAD_PRIORITY_MAX > 32 pcpu->ready_table[thread->number] |= thread->high_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ pcpu->priority_group |= thread->number_mask; rt_list_insert_before(&(rt_cpu_index(bind_cpu)->priority_table[thread->current_priority]), @@ -724,14 +724,14 @@ void rt_schedule_insert_thread(struct rt_thread *thread) /* set priority mask */ #if RT_THREAD_PRIORITY_MAX > 32 rt_thread_ready_table[thread->number] |= thread->high_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ rt_thread_ready_priority_group |= thread->number_mask; __exit: /* enable interrupt */ rt_hw_interrupt_enable(temp); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* * This function will remove a thread from system ready queue. @@ -768,7 +768,7 @@ void rt_schedule_remove_thread(struct rt_thread *thread) } #else rt_thread_ready_priority_group &= ~thread->number_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } } else @@ -785,7 +785,7 @@ void rt_schedule_remove_thread(struct rt_thread *thread) } #else pcpu->priority_group &= ~thread->number_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } } @@ -818,13 +818,13 @@ void rt_schedule_remove_thread(struct rt_thread *thread) } #else rt_thread_ready_priority_group &= ~thread->number_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } /* enable interrupt */ rt_hw_interrupt_enable(level); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /** * This function will lock the thread scheduler. @@ -885,7 +885,7 @@ void rt_enter_critical(void) /* enable interrupt */ rt_hw_interrupt_enable(level); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ RTM_EXPORT(rt_enter_critical); /** @@ -959,7 +959,7 @@ void rt_exit_critical(void) rt_hw_interrupt_enable(level); } } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ RTM_EXPORT(rt_exit_critical); /** @@ -975,7 +975,7 @@ rt_uint16_t rt_critical_level(void) return current_thread->critical_lock_nest; #else return rt_scheduler_lock_nest; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ } RTM_EXPORT(rt_critical_level); diff --git a/src/signal.c b/src/signal.c index c2c3e975cb..bb7706d9ef 100644 --- a/src/signal.c +++ b/src/signal.c @@ -20,7 +20,7 @@ #ifndef RT_SIG_INFO_MAX #define RT_SIG_INFO_MAX 32 -#endif +#endif /* RT_SIG_INFO_MAX */ #define DBG_TAG "SIGN" #define DBG_LVL DBG_WARNING @@ -67,7 +67,7 @@ static void _signal_entry(void *parameter) /* return to thread */ tid->sp = tid->sig_ret; tid->sig_ret = RT_NULL; -#endif +#endif /* RT_USING_SMP */ LOG_D("switch back to: 0x%08x\n", tid->sp); tid->stat &= ~RT_THREAD_STAT_SIGNAL; @@ -76,7 +76,7 @@ static void _signal_entry(void *parameter) rt_hw_context_switch_to((rt_base_t)¶meter, tid); #else rt_hw_context_switch_to((rt_ubase_t)&(tid->sp)); -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ } /* @@ -153,7 +153,7 @@ static void _signal_deliver(rt_thread_t tid) tid->sig_ret = tid->sp; tid->sp = rt_hw_stack_init((void *)_signal_entry, RT_NULL, (void *)((char *)tid->sig_ret - 32), RT_NULL); -#endif +#endif /* RT_USING_SMP */ rt_hw_interrupt_enable(level); LOG_D("signal stack pointer @ 0x%08x", tid->sp); @@ -204,7 +204,7 @@ void *rt_signal_check(void* context) rt_hw_interrupt_enable(level); return context; } -#endif +#endif /* RT_USING_SMP */ rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler) { @@ -586,4 +586,4 @@ int rt_system_signal_init(void) return 0; } -#endif +#endif /* RT_USING_SIGNALS */ diff --git a/src/slab.c b/src/slab.c index 114259002f..bec826ef18 100644 --- a/src/slab.c +++ b/src/slab.c @@ -61,7 +61,7 @@ /* some statistical variable */ #ifdef RT_MEM_STATS static rt_size_t used_mem, max_mem; -#endif +#endif /* RT_MEM_STATS */ #ifdef RT_USING_HOOK static void (*rt_malloc_hook)(void *ptr, rt_size_t size); @@ -99,7 +99,7 @@ RTM_EXPORT(rt_free_sethook); /**@}*/ -#endif +#endif /* RT_USING_HOOK */ /* * slab allocator implementation @@ -516,7 +516,7 @@ void *rt_malloc(rt_size_t size) used_mem += size; if (used_mem > max_mem) max_mem = used_mem; -#endif +#endif /* RT_MEM_STATS */ goto done; } @@ -571,7 +571,7 @@ void *rt_malloc(rt_size_t size) used_mem += z->z_chunksize; if (used_mem > max_mem) max_mem = used_mem; -#endif +#endif /* RT_MEM_STATS */ goto done; } @@ -655,7 +655,7 @@ void *rt_malloc(rt_size_t size) used_mem += z->z_chunksize; if (used_mem > max_mem) max_mem = used_mem; -#endif +#endif /* RT_MEM_STATS */ } done: @@ -790,7 +790,7 @@ void rt_free(void *ptr) (rt_ubase_t)addr, ((rt_ubase_t)(addr) - heap_start) >> RT_MM_PAGE_BITS)); } -#endif +#endif /* RT_DEBUG_SLAB */ kup = btokup((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK); /* release large allocation */ @@ -806,7 +806,7 @@ void rt_free(void *ptr) #ifdef RT_MEM_STATS used_mem -= size * RT_MM_PAGE_SIZE; -#endif +#endif /* RT_MEM_STATS */ rt_sem_release(&heap_sem); RT_DEBUG_LOG(RT_DEBUG_SLAB, @@ -833,7 +833,7 @@ void rt_free(void *ptr) #ifdef RT_MEM_STATS used_mem -= z->z_chunksize; -#endif +#endif /* RT_MEM_STATS */ /* * Bump the number of free chunks. If it becomes non-zero the zone @@ -929,9 +929,9 @@ void list_mem(void) rt_kprintf("maximum allocated memory: %d\n", max_mem); } FINSH_FUNCTION_EXPORT(list_mem, list memory usage information) -#endif -#endif +#endif /* RT_USING_FINSH */ +#endif /* RT_MEM_STATS */ /**@}*/ -#endif +#endif /* defined (RT_USING_HEAP) && defined (RT_USING_SLAB) */ diff --git a/src/thread.c b/src/thread.c index 6304a4ebe6..c0a8f0ee74 100644 --- a/src/thread.c +++ b/src/thread.c @@ -76,7 +76,7 @@ void rt_thread_inited_sethook(void (*hook)(rt_thread_t thread)) rt_thread_inited_hook = hook; } -#endif +#endif /* RT_USING_HOOK */ /* must be invoke witch rt_hw_interrupt_disable */ static void _rt_thread_cleanup_execute(rt_thread_t thread) @@ -84,7 +84,7 @@ static void _rt_thread_cleanup_execute(rt_thread_t thread) register rt_base_t level; #ifdef RT_USING_MODULE struct rt_dlmodule *module = RT_NULL; -#endif +#endif /* RT_USING_MODULE */ level = rt_hw_interrupt_disable(); #ifdef RT_USING_MODULE module = (struct rt_dlmodule*)thread->module_id; @@ -92,14 +92,14 @@ static void _rt_thread_cleanup_execute(rt_thread_t thread) { dlmodule_destroy(module); } -#endif +#endif /* RT_USING_MODULE */ /* invoke thread cleanup */ if (thread->cleanup != RT_NULL) thread->cleanup(thread); #ifdef RT_USING_SIGNALS rt_thread_free_sig(thread); -#endif +#endif /* RT_USING_SIGNALS */ rt_hw_interrupt_enable(level); } @@ -170,7 +170,7 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter, (rt_uint8_t *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)), (void *)_rt_thread_exit); -#endif +#endif /* ARCH_CPU_STACK_GROWS_UPWARD */ /* priority init */ RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX); @@ -181,7 +181,7 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, #if RT_THREAD_PRIORITY_MAX > 32 thread->number = 0; thread->high_mask = 0; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* tick init */ thread->init_tick = tick; @@ -200,7 +200,7 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, thread->scheduler_lock_nest = 0; thread->cpus_lock_nest = 0; thread->critical_lock_nest = 0; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* initialize cleanup function and user data */ thread->cleanup = 0; @@ -221,14 +221,14 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, #ifndef RT_USING_SMP thread->sig_ret = RT_NULL; -#endif +#endif /* RT_USING_SMP */ thread->sig_vectors = RT_NULL; thread->si_list = RT_NULL; -#endif +#endif /* RT_USING_SIGNALS */ #ifdef RT_USING_LWP thread->lwp = RT_NULL; -#endif +#endif /* RT_USING_LWP */ RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread)); @@ -302,7 +302,7 @@ rt_thread_t rt_thread_self(void) extern rt_thread_t rt_current_thread; return rt_current_thread; -#endif +#endif /* RT_USING_SMP */ } RTM_EXPORT(rt_thread_self); @@ -330,7 +330,7 @@ rt_err_t rt_thread_startup(rt_thread_t thread) thread->high_mask = 1L << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1L << thread->current_priority; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n", thread->name, thread->init_priority)); @@ -492,7 +492,7 @@ rt_err_t rt_thread_delete(rt_thread_t thread) return RT_EOK; } RTM_EXPORT(rt_thread_delete); -#endif +#endif /* RT_USING_HEAP */ /** * This function will let current thread yield processor, and scheduler will @@ -690,7 +690,7 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1 << thread->current_priority; - #endif + #endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* insert thread to schedule queue again */ rt_schedule_insert_thread(thread); @@ -706,7 +706,7 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1 << thread->current_priority; - #endif + #endif /* RT_THREAD_PRIORITY_MAX > 32 */ } /* enable interrupt */ @@ -732,7 +732,7 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) { rt_err = rt_thread_delete(thread); } - #endif + #endif /* RT_USING_HEAP */ rt_schedule(); return rt_err; } @@ -752,7 +752,7 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) thread->bind_cpu = cpu > RT_CPUS_NR? RT_CPUS_NR : cpu; break; } - #endif /*RT_USING_SMP*/ + #endif /* RT_USING_SMP */ default: break; diff --git a/src/timer.c b/src/timer.c index 9b0db6c6a5..1c8e70fccc 100644 --- a/src/timer.c +++ b/src/timer.c @@ -31,11 +31,11 @@ static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL]; #ifndef RT_TIMER_THREAD_STACK_SIZE #define RT_TIMER_THREAD_STACK_SIZE 512 -#endif +#endif /* RT_TIMER_THREAD_STACK_SIZE */ #ifndef RT_TIMER_THREAD_PRIO #define RT_TIMER_THREAD_PRIO 0 -#endif +#endif /* RT_TIMER_THREAD_PRIO */ /* soft timer status */ static rt_uint8_t soft_timer_status = RT_SOFT_TIMER_IDLE; @@ -44,7 +44,7 @@ static rt_list_t rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL]; static struct rt_thread timer_thread; ALIGN(RT_ALIGN_SIZE) static rt_uint8_t timer_thread_stack[RT_TIMER_THREAD_STACK_SIZE]; -#endif +#endif /* RT_USING_TIMER_SOFT */ #ifdef RT_USING_HOOK extern void (*rt_object_take_hook)(struct rt_object *object); @@ -81,7 +81,7 @@ void rt_timer_exit_sethook(void (*hook)(struct rt_timer *timer)) } /**@}*/ -#endif +#endif /* RT_USING_HOOK */ static void _rt_timer_init(rt_timer_t timer, void (*timeout)(void *parameter), @@ -171,7 +171,7 @@ void rt_timer_dump(rt_list_t timer_heads[]) } rt_kprintf("\n"); } -#endif +#endif /* RT_DEBUG_TIMER */ /** * @addtogroup Clock @@ -303,7 +303,7 @@ rt_err_t rt_timer_delete(rt_timer_t timer) return RT_EOK; } RTM_EXPORT(rt_timer_delete); -#endif +#endif /* RT_USING_HEAP */ /** * This function will start the timer @@ -348,7 +348,7 @@ rt_err_t rt_timer_start(rt_timer_t timer) timer_list = rt_soft_timer_list; } else -#endif +#endif /* RT_USING_TIMER_SOFT */ { /* insert timer to system timer list */ timer_list = rt_timer_list; @@ -422,7 +422,7 @@ rt_err_t rt_timer_start(rt_timer_t timer) rt_schedule(); } } -#endif +#endif /* RT_USING_TIMER_SOFT */ return RT_EOK; } @@ -718,7 +718,7 @@ static void rt_thread_timer_entry(void *parameter) rt_soft_timer_check(); } } -#endif +#endif /* RT_USING_TIMER_SOFT */ /** * @ingroup SystemInit @@ -764,7 +764,7 @@ void rt_system_timer_thread_init(void) /* startup */ rt_thread_startup(&timer_thread); -#endif +#endif /* RT_USING_TIMER_SOFT */ } /**@}*/ From b9b5a32da429037dd17b3ab4c4356b2aa3df4772 Mon Sep 17 00:00:00 2001 From: Wang-Huachen Date: Thu, 10 Jun 2021 20:46:13 +0800 Subject: [PATCH 151/255] add copyright notice and permission notice --- .../drivers/Zynq_HAL_Driver/sleep.h | 9 +++++ .../drivers/Zynq_HAL_Driver/xil_assert.h | 9 +++++ .../drivers/Zynq_HAL_Driver/xil_cache.h | 9 +++++ .../drivers/Zynq_HAL_Driver/xil_printf.h | 13 +++++-- .../drivers/Zynq_HAL_Driver/xil_types.h | 34 +++++++++++++++++++ .../drivers/Zynq_HAL_Driver/xplatform_info.h | 10 ++++++ bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c | 2 -- bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h | 9 +++++ 8 files changed, 91 insertions(+), 4 deletions(-) diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h index 7e8c778295..ca6e56a7ec 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h @@ -1,3 +1,12 @@ +/* + * Copyright (c) 2020-2021, WangHuachen + * + * SPDX-License-Identifier: MIT + * + * Change Logs: + * Date Author Notes + * 2020-11-30 WangHuachen the first version + */ #ifndef XLI_SLEEP_H #define XLI_SLEEP_H diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_assert.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_assert.h index de095f1f4c..7abe853e29 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_assert.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_assert.h @@ -1,3 +1,12 @@ +/* + * Copyright (c) 2020-2021, WangHuachen + * + * SPDX-License-Identifier: MIT + * + * Change Logs: + * Date Author Notes + * 2020-11-30 WangHuachen the first version + */ #ifndef XIL_ASSERT_H /* prevent circular inclusions */ #define XIL_ASSERT_H /* by using protection macros */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_cache.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_cache.h index 2590ce096b..575157e6d2 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_cache.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_cache.h @@ -1,3 +1,12 @@ +/* + * Copyright (c) 2020-2021, WangHuachen + * + * SPDX-License-Identifier: MIT + * + * Change Logs: + * Date Author Notes + * 2020-11-30 WangHuachen the first version + */ #ifndef XIL_CACHE_H #define XIL_CACHE_H diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_printf.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_printf.h index b6983a5d7e..29de8c2441 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_printf.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_printf.h @@ -1,5 +1,14 @@ - #ifndef XIL_PRINTF_H - #define XIL_PRINTF_H +/* + * Copyright (c) 2020-2021, WangHuachen + * + * SPDX-License-Identifier: MIT + * + * Change Logs: + * Date Author Notes + * 2020-11-30 WangHuachen the first version + */ +#ifndef XIL_PRINTF_H +#define XIL_PRINTF_H #include diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h index a6988a20a5..cebdbcd56e 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h @@ -1,3 +1,13 @@ +/* + * Copyright (C) 2010-2020 Xilinx, Inc. + * Copyright (c) 2020-2021, WangHuachen + * All rights reserved. + * SPDX-License-Identifier: MIT + * + * Change Logs: + * Date Author Notes + * 2020-11-30 WangHuachen the first version + */ #ifndef XIL_TYPES_H /* prevent circular inclusions */ #define XIL_TYPES_H /* by using protection macros */ @@ -70,6 +80,30 @@ typedef void (*XInterruptHandler) (void *InstancePtr); */ typedef void (*XExceptionHandler) (void *InstancePtr); +/** + * @brief Returns 32-63 bits of a number. + * @param n : Number being accessed. + * @return Bits 32-63 of number. + * + * @note A basic shift-right of a 64- or 32-bit quantity. + * Use this to suppress the "right shift count >= width of type" + * warning when that quantity is 32-bits. + */ +#if defined (__aarch64__) || defined (__arch64__) +#define UPPER_32_BITS(n) ((u32)(((n) >> 16) >> 16)) +#else +#define UPPER_32_BITS(n) 0U +#endif +/** + * @brief Returns 0-31 bits of a number + * @param n : Number being accessed. + * @return Bits 0-31 of number + */ +#define LOWER_32_BITS(n) ((u32)(n)) + + + + /************************** Constant Definitions *****************************/ #ifndef TRUE diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h index 4213736270..e995d4a589 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h @@ -1,3 +1,13 @@ +/* + * Copyright (C) 2014-2020 Xilinx, Inc. + * Copyright (c) 2020-2021, WangHuachen + * All rights reserved. + * SPDX-License-Identifier: MIT + * + * Change Logs: + * Date Author Notes + * 2020-11-30 WangHuachen the first version + */ #ifndef XPLATFORM_INFO_H /* prevent circular inclusions */ #define XPLATFORM_INFO_H /* by using protection macros */ diff --git a/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c b/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c index e3e1884cf2..05c29305fc 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c +++ b/bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c @@ -7,8 +7,6 @@ * Date Author Notes * 2021-5-10 WangHuachen the first version */ - - #include "board.h" #include #include "lwipopts.h" diff --git a/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h b/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h index 3192942b57..fc8cfb0f97 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h @@ -1,3 +1,12 @@ +/* + * Copyright (c) 2020-2021, WangHuachen + * + * SPDX-License-Identifier: MIT + * + * Change Logs: + * Date Author Notes + * 2020-11-30 WangHuachen the first version + */ #ifndef __ZYNQMP_R5_H__ #define __ZYNQMP_R5_H__ From 788203117a10efa24c205bfe5d6b63e6135e0e4c Mon Sep 17 00:00:00 2001 From: Wang-Huachen Date: Thu, 10 Jun 2021 20:49:54 +0800 Subject: [PATCH 152/255] delete extra space at the end of line --- bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h index e995d4a589..0024b53f6c 100644 --- a/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h +++ b/bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2020 Xilinx, Inc. + * Copyright (C) 2014-2020 Xilinx, Inc. * Copyright (c) 2020-2021, WangHuachen * All rights reserved. * SPDX-License-Identifier: MIT From 4e66a20fbf9824dd01331e9f381de97f658969c5 Mon Sep 17 00:00:00 2001 From: leton-tian <65377215+leton-tian@users.noreply.github.com> Date: Thu, 10 Jun 2021 22:23:06 +0800 Subject: [PATCH 153/255] Update drv_rtc.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将rt_int32_t改为time_t。 --- bsp/bluetrum/libraries/hal_drivers/drv_rtc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bsp/bluetrum/libraries/hal_drivers/drv_rtc.c b/bsp/bluetrum/libraries/hal_drivers/drv_rtc.c index ccbaac1909..9107107ab0 100644 --- a/bsp/bluetrum/libraries/hal_drivers/drv_rtc.c +++ b/bsp/bluetrum/libraries/hal_drivers/drv_rtc.c @@ -189,27 +189,27 @@ static rt_err_t ab32_rtc_control(rt_device_t dev, int cmd, void *args) switch (cmd) { case RT_DEVICE_CTRL_RTC_GET_TIME: - *(rt_uint32_t *)args = get_rtc_time_stamp(); - LOG_D("RTC: get rtc_time %x", *(rt_uint32_t *)args); + *(time_t *)args = get_rtc_time_stamp(); + LOG_D("RTC: get rtc_time %x", *(time_t *)args); break; case RT_DEVICE_CTRL_RTC_SET_TIME: - if (set_rtc_time_stamp(*(rt_uint32_t *)args)) + if (set_rtc_time_stamp(*(time_t *)args)) { result = -RT_ERROR; } - LOG_D("RTC: set rtc_time %x", *(rt_uint32_t *)args); + LOG_D("RTC: set rtc_time %x", *(time_t *)args); break; case RT_DEVICE_CTRL_RTC_SET_ALARM: - if (set_rtc_alarm_stamp(*(rt_uint32_t *)args)) + if (set_rtc_alarm_stamp(*(time_t *)args)) { result = -RT_ERROR; } - LOG_D("RTC: set alarm_stamp %x", *(rt_uint32_t *)args); + LOG_D("RTC: set alarm_stamp %x", *(time_t *)args); break; case RT_DEVICE_CTRL_RTC_GET_ALARM: - *(rt_uint32_t *)args = get_rtc_alarm_stamp(); - LOG_D("RTC: get alarm_stamp %x", *(rt_uint32_t *)args); + *(time_t *)args = get_rtc_alarm_stamp(); + LOG_D("RTC: get alarm_stamp %x", *(time_t *)args); break; } From fa1f1ef485734d990f9a5aecb001d3a0aa0eb59a Mon Sep 17 00:00:00 2001 From: yangjie Date: Fri, 11 Jun 2021 10:00:23 +0800 Subject: [PATCH 154/255] [src] add RT_WEAK for rt_malloc_align,rt_free_align --- src/kservice.c | 4 ++-- src/memheap.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/kservice.c b/src/kservice.c index 7ed05b6651..40040f7885 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -1238,7 +1238,7 @@ RTM_EXPORT(rt_kprintf); * * @return the allocated memory block on successful, otherwise returns RT_NULL */ -void *rt_malloc_align(rt_size_t size, rt_size_t align) +RT_WEAK void *rt_malloc_align(rt_size_t size, rt_size_t align) { void *ptr; void *align_ptr; @@ -1284,7 +1284,7 @@ RTM_EXPORT(rt_malloc_align); * * @param ptr the memory block pointer */ -void rt_free_align(void *ptr) +RT_WEAK void rt_free_align(void *ptr) { void *real_ptr; diff --git a/src/memheap.c b/src/memheap.c index 35a04c14b1..80f27a461f 100644 --- a/src/memheap.c +++ b/src/memheap.c @@ -757,6 +757,8 @@ static struct rt_memheap _heap; void rt_system_heap_init(void *begin_addr, void *end_addr) { + RT_ASSERT((rt_uint32_t)end_addr > (rt_uint32_t)begin_addr); + /* initialize a default heap in the system */ rt_memheap_init(&_heap, "heap", From 4e545551201fa301cc238a898e07021f970735d9 Mon Sep 17 00:00:00 2001 From: chunyexixiaoyu <834670833@qq.com> Date: Thu, 10 Jun 2021 18:37:14 +0800 Subject: [PATCH 155/255] /bsp/k210:add delay us function in board.c ,when using posix interface ,rt_hw_us_delay this function will be called in unistd.c file --- bsp/k210/driver/board.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/bsp/k210/driver/board.c b/bsp/k210/driver/board.c index 3343da0fb7..d9c9279dca 100644 --- a/bsp/k210/driver/board.c +++ b/bsp/k210/driver/board.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes + *2021-06-10 xiaoyu implement rt_hw_us_delay() */ #include @@ -117,3 +118,19 @@ void rt_hw_cpu_reset(void) } MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine); + +/** + * This function will delay for some us. + * + * @param us the delay time of us + */ +void rt_hw_us_delay(rt_uint32_t usec) +{ + rt_uint32_t cycle = read_cycle(); + rt_uint32_t nop_all = usec * sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / 1000000UL; + while (1) + { + if(read_cycle() - cycle >= nop_all) + break; + } +} From 4fa92ae3f6766863035238da9ae2b46622abb8a9 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Fri, 11 Jun 2021 13:07:29 +0800 Subject: [PATCH 156/255] =?UTF-8?q?[kernel]=20=E8=A1=A5=E5=85=85endif?= =?UTF-8?q?=E5=90=8E=E7=BC=80=E6=B3=A8=E9=87=8A(4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mem.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/mem.c b/src/mem.c index ac0d27f2c3..e2328cc234 100644 --- a/src/mem.c +++ b/src/mem.c @@ -52,7 +52,6 @@ #ifndef RT_USING_MEMHEAP_AS_HEAP -/* #define RT_MEM_DEBUG */ #define RT_MEM_STATS #if defined (RT_USING_HEAP) && defined (RT_USING_SMALL_MEM) @@ -90,7 +89,7 @@ void rt_free_sethook(void (*hook)(void *ptr)) /**@}*/ -#endif +#endif /* RT_USING_HOOK */ #define HEAP_MAGIC 0x1ea0 struct heap_mem @@ -100,7 +99,7 @@ struct heap_mem rt_uint16_t used; #ifdef ARCH_CPU_64BIT rt_uint32_t resv; -#endif +#endif /* ARCH_CPU_64BIT */ rt_size_t next, prev; @@ -109,8 +108,8 @@ struct heap_mem rt_uint8_t thread[8]; #else rt_uint8_t thread[4]; /* thread name */ -#endif -#endif +#endif /* ARCH_CPU_64BIT */ +#endif /* RT_USING_MEMTRACE */ }; /** pointer to the heap: for alignment, heap_ptr is now a pointer instead of an array */ @@ -123,7 +122,7 @@ static struct heap_mem *heap_end; #define MIN_SIZE 24 #else #define MIN_SIZE 12 -#endif +#endif /* ARCH_CPU_64BIT */ #define MIN_SIZE_ALIGNED RT_ALIGN(MIN_SIZE, RT_ALIGN_SIZE) #define SIZEOF_STRUCT_MEM RT_ALIGN(sizeof(struct heap_mem), RT_ALIGN_SIZE) @@ -135,7 +134,8 @@ static rt_size_t mem_size_aligned; #ifdef RT_MEM_STATS static rt_size_t used_mem, max_mem; -#endif +#endif /* RT_MEM_STATS */ + #ifdef RT_USING_MEMTRACE rt_inline void rt_mem_setname(struct heap_mem *mem, const char *name) { @@ -151,7 +151,7 @@ rt_inline void rt_mem_setname(struct heap_mem *mem, const char *name) mem->thread[index] = ' '; } } -#endif +#endif /* RT_USING_MEMTRACE */ static void plug_holes(struct heap_mem *mem) { @@ -238,7 +238,7 @@ void rt_system_heap_init(void *begin_addr, void *end_addr) mem->used = 0; #ifdef RT_USING_MEMTRACE rt_mem_setname(mem, "INIT"); -#endif +#endif /* RT_USING_MEMTRACE */ /* initialize the end of the heap */ heap_end = (struct heap_mem *)&heap_ptr[mem->next]; @@ -248,7 +248,7 @@ void rt_system_heap_init(void *begin_addr, void *end_addr) heap_end->prev = mem_size_aligned + SIZEOF_STRUCT_MEM; #ifdef RT_USING_MEMTRACE rt_mem_setname(heap_end, "INIT"); -#endif +#endif /* RT_USING_MEMTRACE */ rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_FIFO); @@ -336,7 +336,7 @@ void *rt_malloc(rt_size_t size) mem2->prev = ptr; #ifdef RT_USING_MEMTRACE rt_mem_setname(mem2, " "); -#endif +#endif /* RT_USING_MEMTRACE */ /* and insert it between mem and mem->next */ mem->next = ptr2; @@ -350,7 +350,7 @@ void *rt_malloc(rt_size_t size) used_mem += (size + SIZEOF_STRUCT_MEM); if (max_mem < used_mem) max_mem = used_mem; -#endif +#endif /* RT_MEM_STATS */ } else { @@ -366,7 +366,7 @@ void *rt_malloc(rt_size_t size) used_mem += mem->next - ((rt_uint8_t *)mem - heap_ptr); if (max_mem < used_mem) max_mem = used_mem; -#endif +#endif /* RT_MEM_STATS */ } /* set memory block magic */ mem->magic = HEAP_MAGIC; @@ -375,7 +375,7 @@ void *rt_malloc(rt_size_t size) rt_mem_setname(mem, rt_thread_self()->name); else rt_mem_setname(mem, "NONE"); -#endif +#endif /* RT_USING_MEMTRACE */ if (mem == lfree) { @@ -473,7 +473,7 @@ void *rt_realloc(void *rmem, rt_size_t newsize) /* split memory block */ #ifdef RT_MEM_STATS used_mem -= (size - newsize); -#endif +#endif /* RT_MEM_STATS */ ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; mem2 = (struct heap_mem *)&heap_ptr[ptr2]; @@ -483,7 +483,7 @@ void *rt_realloc(void *rmem, rt_size_t newsize) mem2->prev = ptr; #ifdef RT_USING_MEMTRACE rt_mem_setname(mem2, " "); -#endif +#endif /* RT_USING_MEMTRACE */ mem->next = ptr2; if (mem2->next != mem_size_aligned + SIZEOF_STRUCT_MEM) { @@ -597,7 +597,7 @@ void rt_free(void *rmem) mem->magic = HEAP_MAGIC; #ifdef RT_USING_MEMTRACE rt_mem_setname(mem, " "); -#endif +#endif /* RT_USING_MEMTRACE */ if (mem < lfree) { @@ -607,7 +607,7 @@ void rt_free(void *rmem) #ifdef RT_MEM_STATS used_mem -= (mem->next - ((rt_uint8_t *)mem - heap_ptr)); -#endif +#endif /* RT_MEM_STATS */ /* finally, see if prev or next are free also */ plug_holes(mem); @@ -706,12 +706,12 @@ int memtrace(int argc, char **argv) return 0; } MSH_CMD_EXPORT(memtrace, dump memory trace information); -#endif /* end of RT_USING_MEMTRACE */ -#endif /* end of RT_USING_FINSH */ +#endif /* RT_USING_MEMTRACE */ +#endif /* RT_USING_FINSH */ -#endif +#endif /* defined (RT_USING_HEAP) && defined (RT_USING_SMALL_MEM) */ /**@}*/ -#endif /* end of RT_USING_HEAP */ -#endif /* end of RT_USING_MEMHEAP_AS_HEAP */ +#endif /* RT_MEM_STATS */ +#endif /* RT_USING_MEMHEAP_AS_HEAP */ From a3b1caf952717fc79a589a870a0caf50538bc76d Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 12 Jun 2021 16:08:22 +0800 Subject: [PATCH 157/255] =?UTF-8?q?[example]=20=E8=A7=A3=E5=86=B3=E6=BD=9C?= =?UTF-8?q?=E5=9C=A8=E5=86=85=E5=AD=98=E6=B3=84=E6=BC=8F=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20=E9=87=8D=E6=96=B0=E8=A7=A3=E5=86=B3=E5=86=B2=E7=AA=81?= =?UTF-8?q?=EF=BC=8C=E6=BA=90=E8=87=AA=EF=BC=9Ahttps://gitee.com/rtthread/?= =?UTF-8?q?rt-thread/pulls/48/files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/file/listdir.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/file/listdir.c b/examples/file/listdir.c index 98fbc5ea2c..06c746a642 100644 --- a/examples/file/listdir.c +++ b/examples/file/listdir.c @@ -13,7 +13,7 @@ void list_dir(const char* path) { - char * fullpath; + char * fullpath = RT_NULL; DIR *dir; dir = opendir(path); @@ -57,7 +57,10 @@ void list_dir(const char* path) rt_kprintf("open %s directory failed\n", path); } - rt_free(fullpath); + if (RT_NULL != fullpath) + { + rt_free(fullpath); + } } #ifdef RT_USING_FINSH @@ -80,6 +83,6 @@ static void cmd_list_dir(int argc, char *argv[]) } list_dir(filename); } -FINSH_FUNCTION_EXPORT_ALIAS(cmd_list_dir, __cmd_list_dir, list directory); +MSH_CMD_EXPORT_ALIAS(cmd_list_dir, list_dir, list directory); #endif /* FINSH_USING_MSH */ #endif /* RT_USING_FINSH */ From 740a810274b9b9ccd74c4163fa9b11b5ee7f7926 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 12 Jun 2021 18:11:51 +0800 Subject: [PATCH 158/255] =?UTF-8?q?[errno][libc]=20=E8=A7=A3=E5=86=B3sys?= =?UTF-8?q?=E5=A4=B4=E6=96=87=E4=BB=B6=E5=9C=A8libc=E6=9C=AA=E5=BC=80?= =?UTF-8?q?=E5=90=AF=E6=97=B6=E7=9A=84=E5=BC=95=E5=85=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/drivers/src/pipe.c | 11 ++++++----- components/finsh/shell.c | 2 +- components/libc/compilers/common/SConscript | 13 +++++-------- .../libc/compilers/common/none-gcc/SConscript | 6 ++++-- components/libc/compilers/newlib/minilib.c | 14 ++++++-------- 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 236c1ffec7..09448a8e9e 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -11,8 +11,9 @@ #include #include #include +#include -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX #include #include #include @@ -374,7 +375,7 @@ rt_size_t rt_pipe_read(rt_device_t device, rt_off_t pos, void *buffer, rt_size_t if (device == RT_NULL) { - rt_set_errno(-EINVAL); + rt_set_errno(EINVAL); return 0; } if (count == 0) return 0; @@ -402,7 +403,7 @@ rt_size_t rt_pipe_write(rt_device_t device, rt_off_t pos, const void *buffer, rt if (device == RT_NULL) { - rt_set_errno(-EINVAL); + rt_set_errno(EINVAL); return 0; } if (count == 0) return 0; @@ -516,12 +517,12 @@ int rt_pipe_delete(const char *name) } else { - result = -ENODEV; + result = -RT_EINVAL; } } else { - result = -ENODEV; + result = -RT_EINVAL; } return result; diff --git a/components/finsh/shell.c b/components/finsh/shell.c index 6f1133bf3b..a749660629 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -97,7 +97,7 @@ int finsh_set_prompt(const char * prompt) } #endif /* RT_USING_HEAP */ -#if defined(RT_USING_DFS) +#ifdef RT_USING_DFS #include #endif /* RT_USING_DFS */ diff --git a/components/libc/compilers/common/SConscript b/components/libc/compilers/common/SConscript index 039e53a0b3..2ebfc36c4e 100644 --- a/components/libc/compilers/common/SConscript +++ b/components/libc/compilers/common/SConscript @@ -9,20 +9,17 @@ CPPPATH = [cwd] if GetDepend('RT_USING_LIBC'): src += Glob('*.c') -else: - if GetDepend('RT_LIBC_USING_TIME'): - src += ['time.c'] - -if GetDepend('RT_USING_POSIX') == False: - SrcRemove(src, ['unistd.c']) + if GetDepend('RT_USING_POSIX') == False: + SrcRemove(src, ['unistd.c']) +elif GetDepend('RT_LIBC_USING_TIME'): + src += ['time.c'] if rtconfig.CROSS_TOOL == 'keil': CPPDEFINES = ['__CLK_TCK=RT_TICK_PER_SECOND'] else: CPPDEFINES = [] -if GetDepend('RT_USING_LIBC') or GetDepend('RT_LIBC_USING_TIME'): - group = DefineGroup('libc', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES) +group = DefineGroup('libc', src, depend = [], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES) list = os.listdir(cwd) for d in list: diff --git a/components/libc/compilers/common/none-gcc/SConscript b/components/libc/compilers/common/none-gcc/SConscript index c5838f8949..c766c8f82d 100644 --- a/components/libc/compilers/common/none-gcc/SConscript +++ b/components/libc/compilers/common/none-gcc/SConscript @@ -6,8 +6,10 @@ src = [] cwd = GetCurrentDir() CPPPATH = [cwd] group = [] -src += Glob('*.c') + +if GetDepend('RT_USING_LIBC'): + src += Glob('*.c') if rtconfig.PLATFORM != 'gcc' or rtconfig.ARCH == 'sim': - group = DefineGroup('libc', src, depend = ['RT_USING_LIBC'], CPPPATH = CPPPATH) + group = DefineGroup('libc', src, depend = [], CPPPATH = CPPPATH) Return('group') diff --git a/components/libc/compilers/newlib/minilib.c b/components/libc/compilers/newlib/minilib.c index f6df38f67b..612554ca66 100644 --- a/components/libc/compilers/newlib/minilib.c +++ b/components/libc/compilers/newlib/minilib.c @@ -12,8 +12,9 @@ #include #ifdef RT_USING_HEAP /* Memory routine */ -void * -_malloc_r (struct _reent *ptr, size_t size) +#include + +void * _malloc_r (struct _reent *ptr, size_t size) { void* result; @@ -26,8 +27,7 @@ _malloc_r (struct _reent *ptr, size_t size) return result; } -void * -_realloc_r (struct _reent *ptr, void *old, size_t newlen) +void * _realloc_r (struct _reent *ptr, void *old, size_t newlen) { void* result; @@ -53,15 +53,13 @@ void *_calloc_r (struct _reent *ptr, size_t size, size_t len) return result; } -void -_free_r (struct _reent *ptr, void *addr) +void _free_r (struct _reent *ptr, void *addr) { rt_free (addr); } #else -void * -_sbrk_r(struct _reent *ptr, ptrdiff_t incr) +void * _sbrk_r(struct _reent *ptr, ptrdiff_t incr) { return RT_NULL; } From ae0e0bdad47e827d17281dbf52f321dd6173a32b Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 12 Jun 2021 18:17:18 +0800 Subject: [PATCH 159/255] [cputime] add sys/errno.h --- components/drivers/cputime/cputime.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/drivers/cputime/cputime.c b/components/drivers/cputime/cputime.c index 4a9eee3a71..750733f366 100644 --- a/components/drivers/cputime/cputime.c +++ b/components/drivers/cputime/cputime.c @@ -10,6 +10,7 @@ #include #include +#include static const struct rt_clock_cputime_ops *_cputime_ops = RT_NULL; @@ -24,7 +25,7 @@ float clock_cpu_getres(void) if (_cputime_ops) return _cputime_ops->cputime_getres(); - rt_set_errno(-ENOSYS); + rt_set_errno(ENOSYS); return 0; } @@ -38,7 +39,7 @@ uint32_t clock_cpu_gettime(void) if (_cputime_ops) return _cputime_ops->cputime_gettime(); - rt_set_errno(-ENOSYS); + rt_set_errno(ENOSYS); return 0; } From 4c625fcb2fd03823e29dc975cde4d8fe88f48145 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 12 Jun 2021 18:40:15 +0800 Subject: [PATCH 160/255] =?UTF-8?q?[lwip][cc]=20LWIP=5FTIMEVAL=5FPRIVATE:?= =?UTF-8?q?=20provided=20by=20=20=E4=B8=8D=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E5=86=8D=E5=88=A4=E6=96=AD=E6=98=AF=E5=90=A6=E5=BC=80=E5=90=AF?= =?UTF-8?q?libc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip-1.4.1/src/arch/include/arch/cc.h | 5 +---- components/net/lwip-2.0.2/src/arch/include/arch/cc.h | 5 +---- components/net/lwip-2.1.2/src/arch/include/arch/cc.h | 5 +---- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h index 2fc88da71b..c312f50df5 100644 --- a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h +++ b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h @@ -63,12 +63,9 @@ typedef uintptr_t mem_ptr_t; in arch.h has been assigned to another error code. */ #endif -#if defined(RT_USING_LIBC) || defined(RT_LIBC_USING_TIME) || (defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) +/* LWIP_TIMEVAL_PRIVATE: provided by */ #include #define LWIP_TIMEVAL_PRIVATE 0 -#else -#define LWIP_TIMEVAL_PRIVATE 1 -#endif #if defined(__CC_ARM) /* ARMCC compiler */ #define PACK_STRUCT_FIELD(x) x diff --git a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h index 09c436c53d..4829f5b2e5 100644 --- a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h @@ -54,12 +54,9 @@ in arch.h has been assigned to another error code. */ #endif -#if defined(RT_USING_LIBC) || defined(RT_LIBC_USING_TIME) || (defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) +/* LWIP_TIMEVAL_PRIVATE: provided by */ #include #define LWIP_TIMEVAL_PRIVATE 0 -#else -#define LWIP_TIMEVAL_PRIVATE 1 -#endif #if defined(__CC_ARM) /* ARMCC compiler */ #define PACK_STRUCT_FIELD(x) x diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h index b7ef3e370a..8e98013412 100644 --- a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h @@ -54,12 +54,9 @@ in arch.h has been assigned to another error code. */ #endif -#if defined(RT_USING_LIBC) || defined(RT_LIBC_USING_TIME) || (defined( __GNUC__ ) && !defined(__ARMCC_VERSION)) +/* LWIP_TIMEVAL_PRIVATE: provided by */ #include #define LWIP_TIMEVAL_PRIVATE 0 -#else -#define LWIP_TIMEVAL_PRIVATE 1 -#endif #if defined(__CC_ARM) /* ARMCC compiler */ #define PACK_STRUCT_FIELD(x) x From f94980af34bc9b1e86a4db393af034ea0707fa83 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 13 Jun 2021 12:45:04 +0800 Subject: [PATCH 161/255] solve conflict --- components/libc/termios/posix_termios.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/libc/termios/posix_termios.c b/components/libc/termios/posix_termios.c index 1816bbae57..9f33c857e6 100644 --- a/components/libc/termios/posix_termios.c +++ b/components/libc/termios/posix_termios.c @@ -10,6 +10,7 @@ #include #include #include +#include #include int tcgetattr(int fd, struct termios *tio) From fbcaa667f87be5c5a3e1502d12facd24ca5b2234 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 13 Jun 2021 12:51:07 +0800 Subject: [PATCH 162/255] add sys/ioctl for serial --- components/drivers/serial/serial.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index 2736ceed66..5cd44f3771 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -38,6 +38,7 @@ #ifdef RT_USING_POSIX #include #include +#include #ifdef RT_USING_POSIX_TERMIOS #include From 3b74f44d10bef52d22a4e931374328339bdc88c6 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 13 Jun 2021 13:01:15 +0800 Subject: [PATCH 163/255] =?UTF-8?q?[lwip][cc]=E8=B0=83=E6=95=B4string.h?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip-1.4.1/src/arch/include/arch/cc.h | 6 ++---- components/net/lwip-2.0.2/src/arch/include/arch/cc.h | 4 +--- components/net/lwip-2.1.2/src/arch/include/arch/cc.h | 4 +--- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h index c312f50df5..a153658d27 100644 --- a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h +++ b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h @@ -37,8 +37,9 @@ #include #include - +#include #include + typedef uint8_t u8_t; typedef int8_t s8_t; typedef uint16_t u16_t; @@ -99,11 +100,8 @@ void sys_arch_assert(const char* file, int line); #define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) #define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) -#include - #define SYS_ARCH_DECL_PROTECT(level) #define SYS_ARCH_PROTECT(level) rt_enter_critical() #define SYS_ARCH_UNPROTECT(level) rt_exit_critical() #endif /* __ARCH_CC_H__ */ - diff --git a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h index 4829f5b2e5..95062441cf 100644 --- a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h @@ -37,6 +37,7 @@ #include #include +#include #define U16_F "hu" #define S16_F "hd" @@ -90,11 +91,8 @@ void sys_arch_assert(const char* file, int line); #define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) #define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) -#include - #define SYS_ARCH_DECL_PROTECT(level) #define SYS_ARCH_PROTECT(level) rt_enter_critical() #define SYS_ARCH_UNPROTECT(level) rt_exit_critical() #endif /* __ARCH_CC_H__ */ - diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h index 8e98013412..95062441cf 100644 --- a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h @@ -37,6 +37,7 @@ #include #include +#include #define U16_F "hu" #define S16_F "hd" @@ -90,11 +91,8 @@ void sys_arch_assert(const char* file, int line); #define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) #define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) -#include "string.h" - #define SYS_ARCH_DECL_PROTECT(level) #define SYS_ARCH_PROTECT(level) rt_enter_critical() #define SYS_ARCH_UNPROTECT(level) rt_exit_critical() #endif /* __ARCH_CC_H__ */ - From ce06e5e160f8c307da742d77c1d80361d7c9aeb1 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 13 Jun 2021 13:15:59 +0800 Subject: [PATCH 164/255] adjust drv_eth.c's head files --- bsp/stm32/libraries/HAL_Drivers/drv_eth.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_eth.c b/bsp/stm32/libraries/HAL_Drivers/drv_eth.c index 0506f6495c..41e86b5134 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_eth.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_eth.c @@ -11,11 +11,10 @@ * 2019-09-03 xiaofan optimize link change detection process */ -#include "board.h" #include "drv_config.h" -#include -#include "lwipopts.h" #include "drv_eth.h" +#include +#include /* * Emac driver uses CubeMX tool to generate emac and phy's configuration, From 485df7a1f444a440d297a19e2c12e1b5ad9612ce Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 13 Jun 2021 15:43:44 +0800 Subject: [PATCH 165/255] =?UTF-8?q?[bug][lwip]=20=E4=BF=AE=E5=A4=8Dlwip?= =?UTF-8?q?=E4=B8=B4=E7=95=8C=E5=8C=BA=E4=BF=9D=E6=8A=A4=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip-1.4.1/src/arch/include/arch/cc.h | 6 +++--- components/net/lwip-2.0.2/src/arch/include/arch/cc.h | 6 +++--- components/net/lwip-2.1.2/src/arch/include/arch/cc.h | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h index a153658d27..82387b432d 100644 --- a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h +++ b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h @@ -100,8 +100,8 @@ void sys_arch_assert(const char* file, int line); #define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) #define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) -#define SYS_ARCH_DECL_PROTECT(level) -#define SYS_ARCH_PROTECT(level) rt_enter_critical() -#define SYS_ARCH_UNPROTECT(level) rt_exit_critical() +#define SYS_ARCH_DECL_PROTECT(level) register rt_base_t level +#define SYS_ARCH_PROTECT(level) do {level = rt_hw_interrupt_disable();} while(0) +#define SYS_ARCH_UNPROTECT(level) do {rt_hw_interrupt_enable(level);} while(0) #endif /* __ARCH_CC_H__ */ diff --git a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h index 95062441cf..28f86d257e 100644 --- a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h @@ -91,8 +91,8 @@ void sys_arch_assert(const char* file, int line); #define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) #define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) -#define SYS_ARCH_DECL_PROTECT(level) -#define SYS_ARCH_PROTECT(level) rt_enter_critical() -#define SYS_ARCH_UNPROTECT(level) rt_exit_critical() +#define SYS_ARCH_DECL_PROTECT(level) register rt_base_t level +#define SYS_ARCH_PROTECT(level) do {level = rt_hw_interrupt_disable();} while(0) +#define SYS_ARCH_UNPROTECT(level) do {rt_hw_interrupt_enable(level);} while(0) #endif /* __ARCH_CC_H__ */ diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h index 95062441cf..28f86d257e 100644 --- a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h @@ -91,8 +91,8 @@ void sys_arch_assert(const char* file, int line); #define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) #define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) -#define SYS_ARCH_DECL_PROTECT(level) -#define SYS_ARCH_PROTECT(level) rt_enter_critical() -#define SYS_ARCH_UNPROTECT(level) rt_exit_critical() +#define SYS_ARCH_DECL_PROTECT(level) register rt_base_t level +#define SYS_ARCH_PROTECT(level) do {level = rt_hw_interrupt_disable();} while(0) +#define SYS_ARCH_UNPROTECT(level) do {rt_hw_interrupt_enable(level);} while(0) #endif /* __ARCH_CC_H__ */ From 5bb6e86cf5573eac5395b2c31f7fb0650382605e Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 13 Jun 2021 17:16:03 +0800 Subject: [PATCH 166/255] =?UTF-8?q?[sys/errno.h]=20=E4=BF=AE=E5=A4=8Darmcl?= =?UTF-8?q?ang=E6=94=AF=E6=8C=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/libc/compilers/common/none-gcc/sys/errno.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/libc/compilers/common/none-gcc/sys/errno.h b/components/libc/compilers/common/none-gcc/sys/errno.h index 773c2cd7d3..ad3614024d 100644 --- a/components/libc/compilers/common/none-gcc/sys/errno.h +++ b/components/libc/compilers/common/none-gcc/sys/errno.h @@ -10,7 +10,7 @@ #ifndef _SYS_ERRNO_H #define _SYS_ERRNO_H -#if defined(__CC_ARM) +#if defined(__ARMCC_VERSION) /* defined in armcc/errno.h @@ -37,7 +37,7 @@ defined in armcc/errno.h #define ERROR_BASE_NO 0 #endif -#if defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) +#if defined(__ARMCC_VERSION) || defined(__IAR_SYSTEMS_ICC__) #include #define EPERM (ERROR_BASE_NO + 1) #define ENOENT (ERROR_BASE_NO + 2) From 921e6064260f7afa80f3d10424bd49526241a3ee Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 13 Jun 2021 17:36:42 +0800 Subject: [PATCH 167/255] =?UTF-8?q?=E5=B0=86defined(=5F=5FCC=5FARM)=20||?= =?UTF-8?q?=20defined(=5F=5FCLANG=5FARM)=20=E6=94=B9=E4=B8=BA=20ifdef=20?= =?UTF-8?q?=5F=5FARMCC=5FVERSION?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/finsh/shell.c | 2 +- include/libc/libc_signal.h | 2 +- include/rtlibc.h | 2 +- include/rtthread.h | 2 +- src/components.c | 4 ++-- src/kservice.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/components/finsh/shell.c b/components/finsh/shell.c index a749660629..c89139c0ed 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -817,7 +817,7 @@ int finsh_system_init(void) rt_thread_t tid; #ifdef FINSH_USING_SYMTAB -#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM C Compiler */ +#ifdef __ARMCC_VERSION /* ARM C Compiler */ extern const int FSymTab$$Base; extern const int FSymTab$$Limit; extern const int VSymTab$$Base; diff --git a/include/libc/libc_signal.h b/include/libc/libc_signal.h index 8a4cc0d738..1fb8194643 100644 --- a/include/libc/libc_signal.h +++ b/include/libc/libc_signal.h @@ -71,7 +71,7 @@ typedef unsigned long sigset_t; #include -#if defined(__CC_ARM) || defined(__CLANG_ARM) +#ifdef __ARMCC_VERSION #define SIGHUP 1 /* #define SIGINT 2 */ diff --git a/include/rtlibc.h b/include/rtlibc.h index a62051e157..4e7caa81fc 100644 --- a/include/rtlibc.h +++ b/include/rtlibc.h @@ -22,7 +22,7 @@ #include "libc/libc_stdio.h" #ifndef RT_USING_LIBC -#if defined(__CC_ARM) || defined(__CLANG_ARM) || defined(__IAR_SYSTEMS_ICC__) +#if defined(__ARMCC_VERSION) || defined(__IAR_SYSTEMS_ICC__) typedef signed long off_t; typedef int mode_t; #endif diff --git a/include/rtthread.h b/include/rtthread.h index ccd2d147a8..cf897b0e5e 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -567,7 +567,7 @@ rt_size_t rt_strlen(const char *src); #endif /*RT_KSERVICE_USING_STDLIB*/ char *rt_strdup(const char *s); -#if defined(__CC_ARM) || defined(__CLANG_ARM) +#ifdef __ARMCC_VERSION /* lack strdup interface */ char* strdup(const char* str); #endif diff --git a/src/components.c b/src/components.c index d684d5e6fd..e156b783e4 100644 --- a/src/components.c +++ b/src/components.c @@ -134,7 +134,7 @@ void rt_application_init(void); void rt_hw_board_init(void); int rtthread_startup(void); -#if defined(__CC_ARM) || defined(__CLANG_ARM) +#ifdef __ARMCC_VERSION extern int $Super$$main(void); /* re-define main function */ int $Sub$$main(void) @@ -183,7 +183,7 @@ void main_thread_entry(void *parameter) rt_hw_secondary_cpu_up(); #endif /* RT_USING_SMP */ /* invoke system main function */ -#if defined(__CC_ARM) || defined(__CLANG_ARM) +#ifdef __ARMCC_VERSION { extern int $Super$$main(void); $Super$$main(); /* for ARMCC. */ diff --git a/src/kservice.c b/src/kservice.c index 448b2d717d..49e1486078 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -532,7 +532,7 @@ char *rt_strdup(const char *s) return tmp; } RTM_EXPORT(rt_strdup); -#if defined(__CC_ARM) || defined(__CLANG_ARM) +#ifdef __ARMCC_VERSION char *strdup(const char *s) __attribute__((alias("rt_strdup"))); #endif #endif /* RT_USING_HEAP */ From 66b7289ee75653f6024ca3b9c0bdff96fe0bc046 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Tue, 15 Jun 2021 18:29:58 +0800 Subject: [PATCH 168/255] [update] usleep supports calling in interrupts. --- components/libc/compilers/common/unistd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/components/libc/compilers/common/unistd.c b/components/libc/compilers/common/unistd.c index 6c81fc7662..4385643f31 100644 --- a/components/libc/compilers/common/unistd.c +++ b/components/libc/compilers/common/unistd.c @@ -55,7 +55,14 @@ RTM_EXPORT(sleep); int usleep(useconds_t usec) { - rt_thread_mdelay(usec / 1000u); + if (rt_thread_self() != RT_NULL) + { + rt_thread_mdelay(usec / 1000u); + } + else + { + rt_hw_us_delay(usec / 1000u); + } rt_hw_us_delay(usec % 1000u); return 0; } From 6697fa0ff54219b6d0b4f65dd28cdcdd22e0158c Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 16 Jun 2021 12:15:24 +0800 Subject: [PATCH 169/255] =?UTF-8?q?[sleep]=20=E5=8A=A0=E5=85=A5=E8=B0=83?= =?UTF-8?q?=E5=BA=A6=E5=99=A8=E5=B0=9A=E6=9C=AA=E8=BF=90=E8=A1=8C=E6=97=B6?= =?UTF-8?q?=E7=9A=84=E5=BB=B6=E6=97=B6=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/libc/compilers/common/unistd.c | 24 +++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/components/libc/compilers/common/unistd.c b/components/libc/compilers/common/unistd.c index 4385643f31..9a457c4200 100644 --- a/components/libc/compilers/common/unistd.c +++ b/components/libc/compilers/common/unistd.c @@ -37,19 +37,26 @@ RTM_EXPORT(isatty); char *ttyname(int fd) { - return "/dev/tty"; /*TODO: need to add more specific*/ + return "/dev/tty"; /* TODO: need to add more specific */ } RTM_EXPORT(ttyname); unsigned int sleep(unsigned int seconds) { - rt_tick_t delta_tick; + if (rt_thread_self() != RT_NULL) + { + rt_thread_delay(seconds * RT_TICK_PER_SECOND); + } + else /* scheduler has not run yet */ + { + while(seconds > 0) + { + rt_hw_us_delay(1000000u); + seconds --; + } + } - delta_tick = rt_tick_get(); - rt_thread_delay(seconds * RT_TICK_PER_SECOND); - delta_tick = rt_tick_get() - delta_tick; - - return seconds - delta_tick/RT_TICK_PER_SECOND; + return 0; } RTM_EXPORT(sleep); @@ -59,11 +66,12 @@ int usleep(useconds_t usec) { rt_thread_mdelay(usec / 1000u); } - else + else /* scheduler has not run yet */ { rt_hw_us_delay(usec / 1000u); } rt_hw_us_delay(usec % 1000u); + return 0; } RTM_EXPORT(usleep); From 56e3571e8a8ede72b9aec00c968ace7b2bbe548c Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 16 Jun 2021 14:02:43 +0800 Subject: [PATCH 170/255] implement delay.c/.h --- bsp/qemu-vexpress-a9/drivers/board.c | 5 +++ bsp/qemu-vexpress-a9/drivers/drv_smc911x.c | 10 ----- components/libc/compilers/common/SConscript | 2 +- components/libc/compilers/common/delay.c | 41 +++++++++++++++++++++ components/libc/compilers/common/delay.h | 19 ++++++++++ 5 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 components/libc/compilers/common/delay.c create mode 100644 components/libc/compilers/common/delay.h diff --git a/bsp/qemu-vexpress-a9/drivers/board.c b/bsp/qemu-vexpress-a9/drivers/board.c index e236c68b80..84af3c1ccd 100644 --- a/bsp/qemu-vexpress-a9/drivers/board.c +++ b/bsp/qemu-vexpress-a9/drivers/board.c @@ -55,3 +55,8 @@ void rt_hw_board_init(void) rt_hw_ipi_handler_install(RT_SCHEDULE_IPI, rt_scheduler_ipi_handler); #endif } + +void rt_hw_us_delay(rt_uint32_t us) +{ + +} diff --git a/bsp/qemu-vexpress-a9/drivers/drv_smc911x.c b/bsp/qemu-vexpress-a9/drivers/drv_smc911x.c index 2b2253328d..9d52b258af 100644 --- a/bsp/qemu-vexpress-a9/drivers/drv_smc911x.c +++ b/bsp/qemu-vexpress-a9/drivers/drv_smc911x.c @@ -33,16 +33,6 @@ struct eth_device_smc911x }; static struct eth_device_smc911x _emac; -int udelay(int value) -{ - return 0; -} - -int mdelay(int value) -{ - return 0; -} - #if defined (CONFIG_SMC911X_32_BIT) rt_inline uint32_t smc911x_reg_read(struct eth_device_smc911x *dev, uint32_t offset) { diff --git a/components/libc/compilers/common/SConscript b/components/libc/compilers/common/SConscript index 2ebfc36c4e..b1982aa329 100644 --- a/components/libc/compilers/common/SConscript +++ b/components/libc/compilers/common/SConscript @@ -10,7 +10,7 @@ CPPPATH = [cwd] if GetDepend('RT_USING_LIBC'): src += Glob('*.c') if GetDepend('RT_USING_POSIX') == False: - SrcRemove(src, ['unistd.c']) + SrcRemove(src, ['unistd.c', 'delay.c']) elif GetDepend('RT_LIBC_USING_TIME'): src += ['time.c'] diff --git a/components/libc/compilers/common/delay.c b/components/libc/compilers/common/delay.c new file mode 100644 index 0000000000..4666258d3b --- /dev/null +++ b/components/libc/compilers/common/delay.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-07 Meco Man first Version + */ +#include +#include + +void msleep(unsigned int msecs) +{ + rt_thread_mdelay(msecs); +} +RTM_EXPORT(msleep); + +void ssleep(unsigned int seconds) +{ + msleep(seconds * 1000); +} +RTM_EXPORT(ssleep); + +void mdelay(unsigned long msecs) +{ + rt_hw_us_delay(msecs * 1000); +} +RTM_EXPORT(mdelay); + +void udelay(unsigned long usecs) +{ + rt_hw_us_delay(usecs); +} +RTM_EXPORT(udelay); + +void ndelay(unsigned long nsecs) +{ + rt_hw_us_delay(1); +} +RTM_EXPORT(ndelay); diff --git a/components/libc/compilers/common/delay.h b/components/libc/compilers/common/delay.h new file mode 100644 index 0000000000..f32708af55 --- /dev/null +++ b/components/libc/compilers/common/delay.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-07 Meco Man first Version + */ +#ifndef __DELAY_H__ +#define __DELAY_H__ + +void msleep(unsigned int msecs); +void ssleep(unsigned int seconds); +void mdelay(unsigned long msecs); +void udelay(unsigned long usecs); +void ndelay(unsigned long nsecs); + +#endif From 5ac5d92cbb6b00f50c9f91c2f7de038419453398 Mon Sep 17 00:00:00 2001 From: chenjh Date: Wed, 16 Jun 2021 16:55:33 +0800 Subject: [PATCH 171/255] =?UTF-8?q?[serial]=20=E4=BC=98=E5=8C=96=E5=8F=91?= =?UTF-8?q?=E9=80=81=E9=9D=9E=E9=98=BB=E5=A1=9E=E6=97=B6=EF=BC=8Cserial=5F?= =?UTF-8?q?close=E6=9C=AA=E6=89=A7=E8=A1=8Crt=5Fcompletion=5Fdone=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../libraries/HAL_Drivers/drv_usart_v2.c | 1 + .../stm32l475-atk-pandora/project.uvprojx | 118 ++++++++++-------- .../drivers/include/drivers/serial_v2.h | 2 - components/drivers/serial/SConscript | 1 + components/drivers/serial/serial_v2.c | 14 ++- 5 files changed, 77 insertions(+), 59 deletions(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c index b1b224005a..1f84d848a0 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c @@ -456,6 +456,7 @@ static void uart_isr(struct rt_serial_device *serial) { if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_ORE) != RESET) { + LOG_E("(%s) serial device Overrun error!", serial->parent.parent.name); __HAL_UART_CLEAR_OREFLAG(&uart->handle); } if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_NE) != RESET) diff --git a/bsp/stm32/stm32l475-atk-pandora/project.uvprojx b/bsp/stm32/stm32l475-atk-pandora/project.uvprojx index 6089d4c371..a41acfebf1 100644 --- a/bsp/stm32/stm32l475-atk-pandora/project.uvprojx +++ b/bsp/stm32/stm32l475-atk-pandora/project.uvprojx @@ -338,7 +338,7 @@ USE_HAL_DRIVER, __RTTHREAD__, STM32L475xx - .;applications;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\CubeMX_Config\Inc;board\ports;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Inc;..\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Include;..\libraries\STM32L4xx_HAL\CMSIS\Include + .;applications;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\CubeMX_Config\Inc;board\ports;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Inc;..\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Include;..\libraries\STM32L4xx_HAL\CMSIS\Include;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel @@ -388,15 +388,20 @@ applications\main.c - uart_sample.c + uart_rxblocking_txblocking.c 1 - .\applications\uart_sample.c + .\applications\uart_rxblocking_txblocking.c CPU + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + showmem.c 1 @@ -408,20 +413,15 @@ ..\..\..\libcpu\arm\common\div0.c - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S cpuport.c 1 ..\..\..\libcpu\arm\cortex-m4\cpuport.c - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - @@ -438,14 +438,9 @@ ..\..\..\components\drivers\serial\serial_v2.c - completion.c + ringblk_buf.c 1 - ..\..\..\components\drivers\src\completion.c - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c + ..\..\..\components\drivers\src\ringblk_buf.c waitqueue.c @@ -453,14 +448,14 @@ ..\..\..\components\drivers\src\waitqueue.c - ringblk_buf.c + workqueue.c 1 - ..\..\..\components\drivers\src\ringblk_buf.c + ..\..\..\components\drivers\src\workqueue.c - dataqueue.c + ringbuffer.c 1 - ..\..\..\components\drivers\src\dataqueue.c + ..\..\..\components\drivers\src\ringbuffer.c pipe.c @@ -468,9 +463,14 @@ ..\..\..\components\drivers\src\pipe.c - workqueue.c + completion.c 1 - ..\..\..\components\drivers\src\workqueue.c + ..\..\..\components\drivers\src\completion.c + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c @@ -533,9 +533,14 @@ Kernel - idle.c + device.c 1 - ..\..\..\src\idle.c + ..\..\..\src\device.c + + + timer.c + 1 + ..\..\..\src\timer.c kservice.c @@ -543,14 +548,19 @@ ..\..\..\src\kservice.c - device.c + irq.c 1 - ..\..\..\src\device.c + ..\..\..\src\irq.c - clock.c + ipc.c 1 - ..\..\..\src\clock.c + ..\..\..\src\ipc.c + + + idle.c + 1 + ..\..\..\src\idle.c mempool.c @@ -563,29 +573,9 @@ ..\..\..\src\scheduler.c - mem.c + clock.c 1 - ..\..\..\src\mem.c - - - components.c - 1 - ..\..\..\src\components.c - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - irq.c - 1 - ..\..\..\src\irq.c - - - object.c - 1 - ..\..\..\src\object.c + ..\..\..\src\clock.c thread.c @@ -593,9 +583,19 @@ ..\..\..\src\thread.c - timer.c + mem.c 1 - ..\..\..\src\timer.c + ..\..\..\src\mem.c + + + object.c + 1 + ..\..\..\src\object.c + + + components.c + 1 + ..\..\..\src\components.c @@ -709,6 +709,16 @@ + + UTest + + + utest.c + 1 + ..\..\..\components\utilities\utest\utest.c + + + diff --git a/components/drivers/include/drivers/serial_v2.h b/components/drivers/include/drivers/serial_v2.h index 51306a4bb4..3ba46bdcdd 100644 --- a/components/drivers/include/drivers/serial_v2.h +++ b/components/drivers/include/drivers/serial_v2.h @@ -118,8 +118,6 @@ struct rt_serial_rx_fifo { struct rt_ringbuffer rb; - rt_uint16_t rx_index; - struct rt_completion rx_cpt; rt_uint16_t rx_cpt_index; diff --git a/components/drivers/serial/SConscript b/components/drivers/serial/SConscript index f3f69991f5..81d791803a 100644 --- a/components/drivers/serial/SConscript +++ b/components/drivers/serial/SConscript @@ -2,6 +2,7 @@ from building import * cwd = GetCurrentDir() CPPPATH = [cwd + '/../include'] +group = [] if GetDepend(['RT_USING_SERIAL']): if GetDepend(['RT_USING_SERIAL_V2']): src = Glob('serial_v2.c') diff --git a/components/drivers/serial/serial_v2.c b/components/drivers/serial/serial_v2.c index 1019b73e67..8670a99aa8 100644 --- a/components/drivers/serial/serial_v2.c +++ b/components/drivers/serial/serial_v2.c @@ -726,7 +726,6 @@ static rt_err_t rt_serial_rx_enable(struct rt_device *dev, RT_ASSERT(rx_fifo != RT_NULL); rt_ringbuffer_init(&(rx_fifo->rb), rx_fifo->buffer, serial->config.rx_bufsz); - rx_fifo->rx_index = serial->config.rx_bufsz; serial->serial_rx = rx_fifo; dev->read = _serial_fifo_rx; @@ -813,6 +812,9 @@ static rt_err_t rt_serial_tx_disable(struct rt_device *dev, dev->write = RT_NULL; if (serial->serial_tx == RT_NULL) return RT_EOK; + tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + do { if (tx_oflag == RT_SERIAL_TX_NON_BLOCKING) @@ -825,14 +827,13 @@ static rt_err_t rt_serial_tx_disable(struct rt_device *dev, break; } + rt_completion_done(&(tx_fifo->tx_cpt)); dev->open_flag &= ~ RT_SERIAL_TX_BLOCKING; serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_SERIAL_TX_BLOCKING); } while (0); - tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx; - RT_ASSERT(tx_fifo != RT_NULL); rt_free(tx_fifo); serial->serial_tx = RT_NULL; @@ -876,6 +877,13 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) RT_ASSERT(dev != RT_NULL); serial = (struct rt_serial_device *)dev; + /* Check that the device has been turned on */ + if ((dev->open_flag) & (15 << 12)) + { + LOG_D("(%s) serial device has already been opened, it will run in its original configuration", dev->parent.name); + return RT_EOK; + } + LOG_D("open serial device: 0x%08x with open flag: 0x%04x", dev, oflag); From 6f36fdf177975c3185d38b6cce98712276d8a60a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E8=BF=8E=E6=98=A5?= <44871523+chenyingchun0312@users.noreply.github.com> Date: Wed, 16 Jun 2021 23:52:30 +0800 Subject: [PATCH 172/255] [bsp/nrf5x] modify nrf52832 default memory config --- bsp/nrf5x/nrf52832/board/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsp/nrf5x/nrf52832/board/Kconfig b/bsp/nrf5x/nrf52832/board/Kconfig index 98cf53014b..e62e762509 100644 --- a/bsp/nrf5x/nrf52832/board/Kconfig +++ b/bsp/nrf5x/nrf52832/board/Kconfig @@ -351,7 +351,7 @@ menu "On-chip Peripheral Drivers" config MCU_FLASH_SIZE_KB int "MCU FLASH SIZE, MAX size 1024 KB" range 1 1024 - default 1024 + default 512 config MCU_SRAM_START_ADDRESS hex "MCU RAM START ADDRESS" @@ -360,7 +360,7 @@ menu "On-chip Peripheral Drivers" config MCU_SRAM_SIZE_KB int "MCU RAM SIZE, MAX size 256 KB" range 1 256 - default 256 + default 64 config MCU_FLASH_PAGE_SIZE hex "MCU FLASH PAGE SIZE, please not change,nrfx default is 0x1000" From 5b889d05acb2833d9741f7c657b062008d1814a2 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Thu, 17 Jun 2021 06:15:39 +0800 Subject: [PATCH 173/255] =?UTF-8?q?[w60x]=20=E4=BF=AE=E5=A4=8DUART1?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E6=97=A0=E6=B3=95=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/w60x/drivers/pin_config.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bsp/w60x/drivers/pin_config.h b/bsp/w60x/drivers/pin_config.h index c704fafb22..130c81ea1c 100644 --- a/bsp/w60x/drivers/pin_config.h +++ b/bsp/w60x/drivers/pin_config.h @@ -14,8 +14,13 @@ #define WM_UART2_RX_PIN 1 // PB19 : UART2_RX (W601) #define WM_UART2_TX_PIN 2 // PB20 : UART2_TX (W601) +#if defined(SOC_W600_A8xx) #define WM_UART1_RX_PIN 31 // PB11 : UART1_RX (W600) #define WM_UART1_TX_PIN 32 // PB12 : UART1_TX (W600) +#elif defined(SOC_W601_A8xx) +#define WM_UART1_RX_PIN 66 // PB11 : UART1_RX (W601) +#define WM_UART1_TX_PIN 67 // PB12 : UART1_TX (W601) +#endif // spi #define WM_SPI_CK_PIN 53 // PB27 : SPI_SCK From 7a52944051338961e671f078cfbf5971ffc70887 Mon Sep 17 00:00:00 2001 From: thread-liu Date: Thu, 17 Jun 2021 14:42:54 +0800 Subject: [PATCH 174/255] [update] support windows cmake tool. --- tools/cmake.py | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/tools/cmake.py b/tools/cmake.py index 645bdbb229..5b43c39409 100644 --- a/tools/cmake.py +++ b/tools/cmake.py @@ -4,6 +4,7 @@ Author: https://github.com/klivelinux """ import os +import sys import re import utils import rtconfig @@ -13,17 +14,26 @@ def GenerateCFiles(env,project): """ Generate CMakeLists.txt files """ - info = utils.ProjectInfo(env) - - CC = os.path.join(rtconfig.EXEC_PATH, rtconfig.CC) - CXX = os.path.join(rtconfig.EXEC_PATH, rtconfig.CXX) - AS = os.path.join(rtconfig.EXEC_PATH, rtconfig.AS) - AR = os.path.join(rtconfig.EXEC_PATH, rtconfig.AR) - LINK = os.path.join(rtconfig.EXEC_PATH, rtconfig.LINK) - SIZE = os.path.join(rtconfig.EXEC_PATH, rtconfig.SIZE) - OBJDUMP = os.path.join(rtconfig.EXEC_PATH, rtconfig.OBJDUMP) - OBJCOPY = os.path.join(rtconfig.EXEC_PATH, rtconfig.OBJCPY) + + CC = os.path.join(rtconfig.EXEC_PATH, rtconfig.CC).replace('\\', "/") + CXX = os.path.join(rtconfig.EXEC_PATH, rtconfig.CXX).replace('\\', "/") + AS = os.path.join(rtconfig.EXEC_PATH, rtconfig.AS).replace('\\', "/") + AR = os.path.join(rtconfig.EXEC_PATH, rtconfig.AR).replace('\\', "/") + LINK = os.path.join(rtconfig.EXEC_PATH, rtconfig.LINK).replace('\\', "/") + SIZE = os.path.join(rtconfig.EXEC_PATH, rtconfig.SIZE).replace('\\', "/") + OBJDUMP = os.path.join(rtconfig.EXEC_PATH, rtconfig.OBJDUMP).replace('\\', "/") + OBJCOPY = os.path.join(rtconfig.EXEC_PATH, rtconfig.OBJCPY).replace('\\', "/") + + if "win32" in sys.platform: + CC += ".exe" + CXX += ".exe" + AS += ".exe" + AR += ".exe" + LINK += ".exe" + SIZE += ".exe" + OBJDUMP += ".exe" + OBJCOPY += ".exe" cm_file = open('CMakeLists.txt', 'w') if cm_file: @@ -49,7 +59,7 @@ def GenerateCFiles(env,project): cm_file.write("INCLUDE_DIRECTORIES(\n") for i in info['CPPPATH']: - cm_file.write( "\t" +i + "\n") + cm_file.write( "\t" + i.replace("\\", "/") + "\n") cm_file.write(")\n\n") @@ -61,21 +71,21 @@ def GenerateCFiles(env,project): cm_file.write("SET(PROJECT_SOURCES\n") for group in project: for f in group['src']: - cm_file.write( "\t"+os.path.normpath(f.rfile().abspath)+"\n" ) + cm_file.write( "\t" + os.path.normpath(f.rfile().abspath).replace("\\", "/") + "\n" ) cm_file.write(")\n\n") cm_file.write("LINK_DIRECTORIES(\n") for group in project: if 'LIBPATH' in group.keys(): for f in group['LIBPATH']: - cm_file.write( "\t"+ f + "\n" ) + cm_file.write( "\t"+ f.replace("\\", "/") + "\n" ) cm_file.write(")\n\n") cm_file.write("LINK_LIBRARIES(\n") for group in project: if 'LIBS' in group.keys(): for f in group['LIBS']: - cm_file.write( "\t"+ "{}\n".format(f)) + cm_file.write( "\t"+ "{}\n".format(f.replace("\\", "/"))) cm_file.write(")\n\n") cm_file.write("ADD_EXECUTABLE(${CMAKE_PROJECT_NAME}.elf ${PROJECT_SOURCES})\n") From 89717a4546fc3c03d930b96640677e2e51621234 Mon Sep 17 00:00:00 2001 From: Henson Date: Thu, 17 Jun 2021 21:50:46 +0800 Subject: [PATCH 175/255] [ci] add riscv64 autotest. --- .github/workflows/action_utest.yml | 51 +++-- .../utest/configs/kernel/config_riscv64.h | 200 ++++++++++++++++++ 2 files changed, 238 insertions(+), 13 deletions(-) create mode 100644 examples/utest/configs/kernel/config_riscv64.h diff --git a/.github/workflows/action_utest.yml b/.github/workflows/action_utest.yml index 22e4505177..d8a6cae754 100644 --- a/.github/workflows/action_utest.yml +++ b/.github/workflows/action_utest.yml @@ -11,33 +11,58 @@ jobs: fail-fast: false matrix: legs: - - {UTEST: "kernel/mem", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/kernel/config.h"} - - {UTEST: "components/utest", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"} - + - {UTEST: "kernel/mem", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "kernel/config.h", SD_FILE: "sd.bin"} + - {UTEST: "components/utest", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "utest_self/config.h", SD_FILE: "sd.bin"} + - {UTEST: "kernel/mem/riscv64", RTT_BSP: "bsp/qemu-riscv-virt64", QEMU_ARCH: "riscv64", QEMU_MACHINE: "virt", CONFIG_FILE: "kernel/config_riscv64.h", SD_FILE: "None"} env: + TEST_QEMU_ARCH: ${{ matrix.legs.QEMU_ARCH }} + TEST_QEMU_MACHINE: ${{ matrix.legs.QEMU_MACHINE }} TEST_BSP_ROOT: ${{ matrix.legs.RTT_BSP }} TEST_CONFIG_FILE: ${{ matrix.legs.CONFIG_FILE }} + TEST_SD_FILE: ${{ matrix.legs.SD_FILE }} steps: - uses: actions/checkout@v1 - - name: Prepare env + + - name: Install Tools + shell: bash + run: | + sudo apt-get update + sudo apt-get -yqq install scons qemu-system git + + - name: Install Arm ToolChains + if: ${{ matrix.legs.QEMU_ARCH == 'arm' && success() }} + shell: bash run: | - sudo apt-get update > /dev/null - sudo apt-get -yqq install scons qemu-system-arm git wget -q https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 sudo tar xjf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C /opt - - name: Build bsp - run: | - export RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin /opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc --version - cp $TEST_CONFIG_FILE $TEST_BSP_ROOT/rtconfig.h + echo "RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin" >> $GITHUB_ENV + + - name: Install RISC-V ToolChains + if: ${{ matrix.legs.QEMU_ARCH == 'riscv64' && success() }} + run: | + wget -q https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz + sudo tar zxvf riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz -C /opt + /opt/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc --version + echo "RTT_EXEC_PATH=/opt/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin" >> $GITHUB_ENV + + - name: Build BSP + run: | + cp examples/utest/configs/$TEST_CONFIG_FILE $TEST_BSP_ROOT/rtconfig.h scons -j$(nproc) -C $TEST_BSP_ROOT - - name: Start test + + - name: Start Test + if: ${{ success() }} run: | git clone https://github.com/armink/UtestRunner.git pushd $TEST_BSP_ROOT dd if=/dev/zero of=sd.bin bs=1024 count=65536 popd pushd UtestRunner - python3 qemu_runner.py --elf ../$TEST_BSP_ROOT/rtthread.elf --sd ../$TEST_BSP_ROOT/sd.bin + if [ $TEST_SD_FILE != "None" ]; then + python3 qemu_runner.py --system $TEST_QEMU_ARCH --machine $TEST_QEMU_MACHINE --elf ../$TEST_BSP_ROOT/rtthread.elf --sd ../$TEST_BSP_ROOT/$TEST_SD_FILE + else + python3 qemu_runner.py --system $TEST_QEMU_ARCH --machine $TEST_QEMU_MACHINE --elf ../$TEST_BSP_ROOT/rtthread.elf + fi cat rtt_console.log - popd + popd \ No newline at end of file diff --git a/examples/utest/configs/kernel/config_riscv64.h b/examples/utest/configs/kernel/config_riscv64.h new file mode 100644 index 0000000000..c166beefec --- /dev/null +++ b/examples/utest/configs/kernel/config_riscv64.h @@ -0,0 +1,200 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Project Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 20 +#define RT_ALIGN_SIZE 8 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 16384 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 16384 + +/* kservice optimization */ + +#define RT_DEBUG + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_MEMHEAP +#define RT_USING_SMALL_MEM +#define RT_USING_MEMTRACE +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 256 +#define RT_CONSOLE_DEVICE_NAME "uart" +#define RT_VER_NUM 0x40004 +#define ARCH_CPU_64BIT +#define ARCH_RISCV +#define ARCH_RISCV64 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 16384 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_CMD_SIZE 80 +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +#define FINSH_USING_MSH_ONLY +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + +#define RT_USING_DFS +#define DFS_USING_WORKDIR +#define DFS_FILESYSTEMS_MAX 2 +#define DFS_FILESYSTEM_TYPES_MAX 2 +#define DFS_FD_MAX 32 +#define RT_USING_DFS_DEVFS +#define RT_USING_DFS_ROMFS + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SERIAL +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_USING_LIBC +#define RT_USING_POSIX +#define RT_LIBC_FIXED_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + +#define RT_USING_UTEST +#define UTEST_THR_STACK_SIZE 4096 +#define UTEST_THR_PRIORITY 20 + +/* RT-Thread Utestcases */ + +#define RT_USING_UTESTCASES + +/* Utest Self Testcase */ + +#define UTEST_SELF_PASS_TC + +/* Kernel Testcase */ + +#define UTEST_MEMHEAP_TC + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + + +/* tools packages */ + + +/* system packages */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + +#define BOARD_virt +#define RT_USING_USERSPACE + +/* RISCV qemu virt64 configs */ + +#define BSP_USING_UART1 +#define BSP_UART1_TXD_PIN 20 +#define BSP_UART1_RXD_PIN 21 +#define __STACKSIZE__ 16384 + +#endif From 41875c17ff3ec878f18920f67cbebb73a0447f7a Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Thu, 17 Jun 2021 23:20:44 +0800 Subject: [PATCH 176/255] =?UTF-8?q?[rtthread.h]=20=E7=A7=BB=E9=99=A4rt=5Fs?= =?UTF-8?q?scanf=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/rtthread.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/rtthread.h b/include/rtthread.h index ccd2d147a8..980c4771b3 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -522,7 +522,6 @@ rt_int32_t rt_vsprintf(char *dest, const char *format, va_list arg_ptr); rt_int32_t rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args); rt_int32_t rt_sprintf(char *buf, const char *format, ...); rt_int32_t rt_snprintf(char *buf, rt_size_t size, const char *format, ...); -rt_int32_t rt_sscanf(const char *buf, const char *fmt, ...); #if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE) rt_device_t rt_console_set_device(const char *name); From 0613cf8ca2aa8df16fe3b67e648b67fa33890414 Mon Sep 17 00:00:00 2001 From: chenjh Date: Thu, 17 Jun 2021 10:32:17 +0800 Subject: [PATCH 177/255] =?UTF-8?q?[serial]=20=E8=A7=A3=E5=86=B3serial=5Fc?= =?UTF-8?q?lose=E6=9C=AA=E6=B8=85=E9=99=A4=E5=9B=9E=E8=B0=83=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h | 2 +- components/drivers/serial/serial_v2.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h index 3350b90864..9cab81bbff 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h @@ -28,7 +28,7 @@ int rt_hw_usart_init(void); #else #define UART_SET_TDR(__HANDLE__, __DATA__) ((__HANDLE__)->Instance->DR = (__DATA__)) -#define UART_GET_RDR(__HANDLE__) (return (__HANDLE__)->Instance->DR & 0xFF)) +#define UART_GET_RDR(__HANDLE__) ((__HANDLE__)->Instance->DR & 0xFF) #endif diff --git a/components/drivers/serial/serial_v2.c b/components/drivers/serial/serial_v2.c index 8670a99aa8..d6ae508cab 100644 --- a/components/drivers/serial/serial_v2.c +++ b/components/drivers/serial/serial_v2.c @@ -939,6 +939,10 @@ static rt_err_t rt_serial_close(struct rt_device *dev) rt_serial_tx_disable(dev, dev->open_flag & (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING)); + /* Clear the callback function */ + serial->parent.rx_indicate = RT_NULL; + serial->parent.tx_complete = RT_NULL; + /* Call the control() API to close the serial device */ serial->ops->control(serial, RT_DEVICE_CTRL_CLOSE, RT_NULL); dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED; From cc5fa682cde2f3c5cbd264e18ebc13be52cc8418 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Fri, 18 Jun 2021 19:25:29 +0800 Subject: [PATCH 178/255] [ci] Simplified configuration files. --- .github/workflows/action_utest.yml | 10 +- examples/utest/configs/kernel/config.h | 304 ------------------ .../utest/configs/kernel/config_riscv64.h | 200 ------------ examples/utest/configs/kernel/mem.conf | 2 + examples/utest/configs/utest_self/config.h | 299 ----------------- examples/utest/configs/utest_self/self.conf | 1 + 6 files changed, 9 insertions(+), 807 deletions(-) delete mode 100644 examples/utest/configs/kernel/config.h delete mode 100644 examples/utest/configs/kernel/config_riscv64.h create mode 100644 examples/utest/configs/kernel/mem.conf delete mode 100644 examples/utest/configs/utest_self/config.h create mode 100644 examples/utest/configs/utest_self/self.conf diff --git a/.github/workflows/action_utest.yml b/.github/workflows/action_utest.yml index d8a6cae754..7d0e2c44d8 100644 --- a/.github/workflows/action_utest.yml +++ b/.github/workflows/action_utest.yml @@ -11,9 +11,9 @@ jobs: fail-fast: false matrix: legs: - - {UTEST: "kernel/mem", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "kernel/config.h", SD_FILE: "sd.bin"} - - {UTEST: "components/utest", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "utest_self/config.h", SD_FILE: "sd.bin"} - - {UTEST: "kernel/mem/riscv64", RTT_BSP: "bsp/qemu-riscv-virt64", QEMU_ARCH: "riscv64", QEMU_MACHINE: "virt", CONFIG_FILE: "kernel/config_riscv64.h", SD_FILE: "None"} + - {UTEST: "kernel/mem", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "kernel/mem.conf", SD_FILE: "sd.bin"} + - {UTEST: "components/utest", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "utest_self/self.conf", SD_FILE: "sd.bin"} + - {UTEST: "kernel/mem/riscv64", RTT_BSP: "bsp/qemu-riscv-virt64", QEMU_ARCH: "riscv64", QEMU_MACHINE: "virt", CONFIG_FILE: "kernel/mem.conf", SD_FILE: "None"} env: TEST_QEMU_ARCH: ${{ matrix.legs.QEMU_ARCH }} TEST_QEMU_MACHINE: ${{ matrix.legs.QEMU_MACHINE }} @@ -48,7 +48,9 @@ jobs: - name: Build BSP run: | - cp examples/utest/configs/$TEST_CONFIG_FILE $TEST_BSP_ROOT/rtconfig.h + echo CONFIG_RT_USING_UTESTCASES=y >> $TEST_BSP_ROOT/.config + cat examples/utest/configs/$TEST_CONFIG_FILE >> $TEST_BSP_ROOT/.config + scons --pyconfig-silent -C $TEST_BSP_ROOT scons -j$(nproc) -C $TEST_BSP_ROOT - name: Start Test diff --git a/examples/utest/configs/kernel/config.h b/examples/utest/configs/kernel/config.h deleted file mode 100644 index c7fcb763fb..0000000000 --- a/examples/utest/configs/kernel/config.h +++ /dev/null @@ -1,304 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Project Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 8 -#define RT_USING_SMP -#define RT_CPUS_NR 2 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 100 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 1024 -#define RT_USING_TIMER_SOFT -#define RT_TIMER_THREAD_PRIO 4 -#define RT_TIMER_THREAD_STACK_SIZE 1024 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_MEMHEAP -#define RT_USING_SMALL_MEM -#define RT_USING_MEMTRACE -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_DEVICE_OPS -#define RT_USING_INTERRUPT_INFO -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40004 -#define ARCH_ARM -#define RT_USING_CPU_FFS -#define ARCH_ARM_CORTEX_A -#define RT_USING_GIC_V2 -#define ARCH_ARM_CORTEX_A9 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - -#define RT_USING_CPLUSPLUS - -/* Command shell */ - -#define RT_USING_FINSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_USING_DESCRIPTION -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_CMD_SIZE 80 -#define FINSH_USING_MSH -#define FINSH_USING_MSH_DEFAULT -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 4 -#define DFS_FILESYSTEM_TYPES_MAX 8 -#define DFS_FD_MAX 32 -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 2 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_USING_DFS_DEVFS -#define RT_USING_DFS_ROMFS -#define RT_USING_DFS_RAMFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_PIPE_BUFSZ 512 -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 64 -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_MTD_NOR -#define RT_USING_MTD_NAND -#define RT_MTD_NAND_DEBUG -#define RT_USING_RTC -#define RT_USING_SOFT_RTC -#define RT_USING_SDIO -#define RT_SDIO_STACK_SIZE 512 -#define RT_SDIO_THREAD_PRIORITY 15 -#define RT_MMCSD_STACK_SIZE 1024 -#define RT_MMCSD_THREAD_PREORITY 22 -#define RT_MMCSD_MAX_PARTITION 16 -#define RT_USING_SPI -#define RT_USING_SPI_MSD -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_USING_WDT - -/* Using USB */ - - -/* POSIX layer and C standard library */ - -#define RT_USING_LIBC -#define RT_USING_PTHREADS -#define PTHREAD_NUM_MAX 8 -#define RT_USING_POSIX -#define RT_USING_POSIX_MMAP -#define RT_USING_POSIX_TERMIOS -#define RT_USING_POSIX_GETLINE -#define RT_USING_POSIX_AIO -#define RT_LIBC_FIXED_TIMEZONE 8 - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL -#define SAL_INTERNET_CHECK - -/* protocol stack implement */ - -#define SAL_USING_LWIP -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - -#define RT_USING_LWIP -#define RT_USING_LWIP202 -#define RT_LWIP_MEM_ALIGNMENT 4 -#define RT_LWIP_ICMP -#define RT_LWIP_DNS -#define RT_LWIP_DHCP -#define IP_SOF_BROADCAST 1 -#define IP_SOF_BROADCAST_RECV 1 - -/* Static IPv4 Address */ - -#define RT_LWIP_IPADDR "192.168.1.30" -#define RT_LWIP_GWADDR "192.168.1.1" -#define RT_LWIP_MSKADDR "255.255.255.0" -#define RT_LWIP_UDP -#define RT_LWIP_TCP -#define RT_LWIP_RAW -#define RT_MEMP_NUM_NETCONN 8 -#define RT_LWIP_PBUF_NUM 16 -#define RT_LWIP_RAW_PCB_NUM 4 -#define RT_LWIP_UDP_PCB_NUM 4 -#define RT_LWIP_TCP_PCB_NUM 4 -#define RT_LWIP_TCP_SEG_NUM 40 -#define RT_LWIP_TCP_SND_BUF 8196 -#define RT_LWIP_TCP_WND 8196 -#define RT_LWIP_TCPTHREAD_PRIORITY 10 -#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 -#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 -#define RT_LWIP_ETHTHREAD_PRIORITY 12 -#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 -#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 -#define RT_LWIP_REASSEMBLY_FRAG -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define SO_REUSE 1 -#define LWIP_SO_RCVTIMEO 1 -#define LWIP_SO_SNDTIMEO 1 -#define LWIP_SO_RCVBUF 1 -#define LWIP_SO_LINGER 0 -#define LWIP_NETIF_LOOPBACK 0 -#define RT_LWIP_USING_PING - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 -#define RT_USING_LWP - -/* RT-Thread Utestcases */ - -#define RT_USING_UTESTCASES - -/* Utest Self Testcase */ - -#define UTEST_SELF_PASS_TC - -/* Kernel memheap stability Testcase */ - -#define UTEST_MEMHEAP_TC - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - - -/* tools packages */ - - -/* system packages */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - -#define SOC_VEXPRESS_A9 -#define RT_USING_UART0 -#define RT_USING_UART1 -#define BSP_DRV_EMAC - -#endif diff --git a/examples/utest/configs/kernel/config_riscv64.h b/examples/utest/configs/kernel/config_riscv64.h deleted file mode 100644 index c166beefec..0000000000 --- a/examples/utest/configs/kernel/config_riscv64.h +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Project Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 20 -#define RT_ALIGN_SIZE 8 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 100 -#define RT_USING_HOOK -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 16384 -#define RT_USING_TIMER_SOFT -#define RT_TIMER_THREAD_PRIO 4 -#define RT_TIMER_THREAD_STACK_SIZE 16384 - -/* kservice optimization */ - -#define RT_DEBUG - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_MEMHEAP -#define RT_USING_SMALL_MEM -#define RT_USING_MEMTRACE -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart" -#define RT_VER_NUM 0x40004 -#define ARCH_CPU_64BIT -#define ARCH_RISCV -#define ARCH_RISCV64 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 16384 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_USING_DESCRIPTION -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_CMD_SIZE 80 -#define FINSH_USING_MSH -#define FINSH_USING_MSH_DEFAULT -#define FINSH_USING_MSH_ONLY -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 2 -#define DFS_FILESYSTEM_TYPES_MAX 2 -#define DFS_FD_MAX 32 -#define RT_USING_DFS_DEVFS -#define RT_USING_DFS_ROMFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_PIPE_BUFSZ 512 -#define RT_USING_SERIAL -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 64 -#define RT_USING_PIN - -/* Using USB */ - - -/* POSIX layer and C standard library */ - -#define RT_USING_LIBC -#define RT_USING_POSIX -#define RT_LIBC_FIXED_TIMEZONE 8 - -/* Network */ - -/* Socket abstraction layer */ - - -/* Network interface device */ - - -/* light weight TCP/IP stack */ - - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - -#define RT_USING_UTESTCASES - -/* Utest Self Testcase */ - -#define UTEST_SELF_PASS_TC - -/* Kernel Testcase */ - -#define UTEST_MEMHEAP_TC - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - - -/* tools packages */ - - -/* system packages */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - -#define BOARD_virt -#define RT_USING_USERSPACE - -/* RISCV qemu virt64 configs */ - -#define BSP_USING_UART1 -#define BSP_UART1_TXD_PIN 20 -#define BSP_UART1_RXD_PIN 21 -#define __STACKSIZE__ 16384 - -#endif diff --git a/examples/utest/configs/kernel/mem.conf b/examples/utest/configs/kernel/mem.conf new file mode 100644 index 0000000000..80a0259a4c --- /dev/null +++ b/examples/utest/configs/kernel/mem.conf @@ -0,0 +1,2 @@ +CONFIG_RT_USING_MEMHEAP=y +CONFIG_UTEST_MEMHEAP_TC=y diff --git a/examples/utest/configs/utest_self/config.h b/examples/utest/configs/utest_self/config.h deleted file mode 100644 index fa94023c42..0000000000 --- a/examples/utest/configs/utest_self/config.h +++ /dev/null @@ -1,299 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Project Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 8 -#define RT_USING_SMP -#define RT_CPUS_NR 2 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 100 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 1024 -#define RT_USING_TIMER_SOFT -#define RT_TIMER_THREAD_PRIO 4 -#define RT_TIMER_THREAD_STACK_SIZE 1024 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_MEMHEAP -#define RT_USING_SMALL_MEM -#define RT_USING_MEMTRACE -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_DEVICE_OPS -#define RT_USING_INTERRUPT_INFO -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40004 -#define ARCH_ARM -#define RT_USING_CPU_FFS -#define ARCH_ARM_CORTEX_A -#define RT_USING_GIC_V2 -#define ARCH_ARM_CORTEX_A9 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - -#define RT_USING_CPLUSPLUS - -/* Command shell */ - -#define RT_USING_FINSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_USING_DESCRIPTION -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_CMD_SIZE 80 -#define FINSH_USING_MSH -#define FINSH_USING_MSH_DEFAULT -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 2 -#define DFS_FILESYSTEM_TYPES_MAX 8 -#define DFS_FD_MAX 16 -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 2 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_USING_DFS_DEVFS -#define RT_USING_DFS_ROMFS -#define RT_USING_DFS_RAMFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_PIPE_BUFSZ 512 -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 64 -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_MTD_NOR -#define RT_USING_MTD_NAND -#define RT_MTD_NAND_DEBUG -#define RT_USING_RTC -#define RT_USING_SOFT_RTC -#define RT_USING_SDIO -#define RT_SDIO_STACK_SIZE 512 -#define RT_SDIO_THREAD_PRIORITY 15 -#define RT_MMCSD_STACK_SIZE 1024 -#define RT_MMCSD_THREAD_PREORITY 22 -#define RT_MMCSD_MAX_PARTITION 16 -#define RT_USING_SPI -#define RT_USING_SPI_MSD -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_USING_WDT - -/* Using USB */ - - -/* POSIX layer and C standard library */ - -#define RT_USING_LIBC -#define RT_USING_PTHREADS -#define PTHREAD_NUM_MAX 8 -#define RT_USING_POSIX -#define RT_USING_POSIX_MMAP -#define RT_USING_POSIX_TERMIOS -#define RT_USING_POSIX_AIO -#define RT_LIBC_FIXED_TIMEZONE 8 - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL -#define SAL_INTERNET_CHECK - -/* protocol stack implement */ - -#define SAL_USING_LWIP -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - -#define RT_USING_LWIP -#define RT_USING_LWIP202 -#define RT_LWIP_MEM_ALIGNMENT 4 -#define RT_LWIP_ICMP -#define RT_LWIP_DNS -#define RT_LWIP_DHCP -#define IP_SOF_BROADCAST 1 -#define IP_SOF_BROADCAST_RECV 1 - -/* Static IPv4 Address */ - -#define RT_LWIP_IPADDR "192.168.1.30" -#define RT_LWIP_GWADDR "192.168.1.1" -#define RT_LWIP_MSKADDR "255.255.255.0" -#define RT_LWIP_UDP -#define RT_LWIP_TCP -#define RT_LWIP_RAW -#define RT_MEMP_NUM_NETCONN 8 -#define RT_LWIP_PBUF_NUM 16 -#define RT_LWIP_RAW_PCB_NUM 4 -#define RT_LWIP_UDP_PCB_NUM 4 -#define RT_LWIP_TCP_PCB_NUM 4 -#define RT_LWIP_TCP_SEG_NUM 40 -#define RT_LWIP_TCP_SND_BUF 8196 -#define RT_LWIP_TCP_WND 8196 -#define RT_LWIP_TCPTHREAD_PRIORITY 10 -#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 -#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 -#define RT_LWIP_ETHTHREAD_PRIORITY 12 -#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 -#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 -#define RT_LWIP_REASSEMBLY_FRAG -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define SO_REUSE 1 -#define LWIP_SO_RCVTIMEO 1 -#define LWIP_SO_SNDTIMEO 1 -#define LWIP_SO_RCVBUF 1 -#define LWIP_SO_LINGER 0 -#define LWIP_NETIF_LOOPBACK 0 -#define RT_LWIP_USING_PING - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 -#define RT_USING_LWP - -/* RT-Thread Utestcases */ - -#define RT_USING_UTESTCASES - -/* Utest Self Testcase */ - -#define UTEST_SELF_PASS_TC - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - - -/* tools packages */ - - -/* system packages */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - -#define SOC_VEXPRESS_A9 -#define RT_USING_UART0 -#define RT_USING_UART1 -#define BSP_DRV_EMAC - -#endif diff --git a/examples/utest/configs/utest_self/self.conf b/examples/utest/configs/utest_self/self.conf new file mode 100644 index 0000000000..b155a551d2 --- /dev/null +++ b/examples/utest/configs/utest_self/self.conf @@ -0,0 +1 @@ +CONFIG_UTEST_SELF_PASS_TC=y From 0849a6061d6dddf26775a0bd649c77eacce3e3d5 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Mon, 21 Jun 2021 17:05:03 +0800 Subject: [PATCH 179/255] [bsp][stm32] fix LTDC_IRQHandler irq enter bug. --- bsp/stm32/libraries/HAL_Drivers/drv_lcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_lcd.c b/bsp/stm32/libraries/HAL_Drivers/drv_lcd.c index 5d170016b8..96c61835e6 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_lcd.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_lcd.c @@ -108,11 +108,11 @@ void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef *hltdc) void LTDC_IRQHandler(void) { - rt_enter_critical(); + rt_interrupt_enter(); HAL_LTDC_IRQHandler(&LtdcHandle); - rt_exit_critical(); + rt_interrupt_leave(); } rt_err_t stm32_lcd_init(struct drv_lcd_device *lcd) From 8c5fed62c1963907473426f92ed6283216139074 Mon Sep 17 00:00:00 2001 From: greedyhao Date: Mon, 21 Jun 2021 21:00:41 +0800 Subject: [PATCH 180/255] =?UTF-8?q?[bsp][bluetrum]=20stream=20close=20?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/bluetrum/ab32vg1-ab-prougen/.config | 42 ++++++++++++------- .../board/ports/audio/drv_sound.c | 4 +- bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h | 3 ++ 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/.config b/bsp/bluetrum/ab32vg1-ab-prougen/.config index 097f9df54c..898a04fc6b 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/.config +++ b/bsp/bluetrum/ab32vg1-ab-prougen/.config @@ -122,6 +122,8 @@ 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_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set # CONFIG_RT_SERIAL_USING_DMA is not set CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set @@ -197,6 +199,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_RT_LINK is not set # # RT-Thread Utestcases @@ -320,6 +323,8 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # CONFIG_PKG_USING_AZUREGUIX is not set # CONFIG_PKG_USING_TOUCHGFX2RTT is not set # CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set # # tools packages @@ -328,6 +333,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # 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 @@ -365,6 +371,24 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # # 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_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set @@ -389,23 +413,9 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # CONFIG_PKG_USING_RAMDISK is not set # CONFIG_PKG_USING_MININI is not set # CONFIG_PKG_USING_QBOOT is not set - -# -# Micrium: Micrium software products porting for RT-Thread -# -# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set -# CONFIG_PKG_USING_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_PPOOL is not set # CONFIG_PKG_USING_OPENAMP is not set # CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set -# 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 # CONFIG_PKG_USING_LPM is not set # CONFIG_PKG_USING_TLSF is not set # CONFIG_PKG_USING_EVENT_RECORDER is not set @@ -433,7 +443,6 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # 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 @@ -477,6 +486,9 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # CONFIG_PKG_USING_MFOC is not set # CONFIG_PKG_USING_TMC51XX is not set # CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set # # AI packages diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c b/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c index e2ba236512..0703b5c902 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c +++ b/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c @@ -388,8 +388,8 @@ static rt_err_t sound_stop(struct rt_audio_device *audio, int stream) if (stream == AUDIO_STREAM_REPLAY) { - DACDIGCON0 = 0; - AUBUFCON &= ~BIT(4); + // DACDIGCON0 = 0; + // AUBUFCON &= ~BIT(4); LOG_D("close sound device"); } diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h b/bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h index 7451b8f1c0..4d37e2598b 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h +++ b/bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h @@ -81,6 +81,7 @@ #define RT_USING_DEVICE_IPC #define RT_PIPE_BUFSZ 512 #define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 #define RT_SERIAL_RB_BUFSZ 64 #define RT_USING_PIN @@ -145,6 +146,8 @@ /* system packages */ +/* acceleration: Assembly language or algorithmic acceleration packages */ + /* Micrium: Micrium software products porting for RT-Thread */ From 9d08e9fb1243aff1d23ff0da1fec4d5a13f765e6 Mon Sep 17 00:00:00 2001 From: greedyhao Date: Mon, 21 Jun 2021 21:01:05 +0800 Subject: [PATCH 181/255] [bsp][bluetrum] update link.lds --- bsp/bluetrum/ab32vg1-ab-prougen/link.lds | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/link.lds b/bsp/bluetrum/ab32vg1-ab-prougen/link.lds index 82e8906080..bdb1b9d2cc 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/link.lds +++ b/bsp/bluetrum/ab32vg1-ab-prougen/link.lds @@ -75,7 +75,7 @@ SECTIONS KEEP(*(.vector)) *(.irq.cache) *(.irq*) - *components*src**.o (.text* .rodata*) + /* *components*src**.o (.text* .rodata*) */ *ab32vg1_hal**.o (.text* .rodata*) *drv_gpio.o (.text* .rodata*) *drv_usart.o (.rodata*) From 7c259a05c2a07d800135b2da701071e2d577b6d8 Mon Sep 17 00:00:00 2001 From: greedyhao Date: Mon, 21 Jun 2021 21:07:58 +0800 Subject: [PATCH 182/255] [bsp][bluetrum] Compatible romfs --- .../ab32vg1-ab-prougen/applications/mnt.c | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c b/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c index 18793cb967..e719cd6c52 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c +++ b/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c @@ -10,7 +10,7 @@ #include -#ifdef BSP_USING_SDIO +#if defined (BSP_USING_SDCARD) #include #include @@ -58,4 +58,23 @@ int ab32_sdcard_mount(void) return RT_EOK; } INIT_APP_EXPORT(ab32_sdcard_mount); +#elif defined (RT_USING_DFS_ROMFS) + +#include +#include "dfs_romfs.h" + +int ab32_romfs_mount(void) +{ + if (dfs_mount(RT_NULL, "/", "rom", 0, &(romfs_root)) == 0) + { + rt_kprintf("ROM file system initializated!\n"); + } + else + { + rt_kprintf("ROM file system initializate failed!\n"); + } + + return 0; +} +INIT_ENV_EXPORT(ab32_romfs_mount); #endif From 43a80193c4d959c8dd150bfc0a52650a357244bf Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 21 Jun 2021 21:55:25 +0800 Subject: [PATCH 183/255] [rtlibc] remove libc_stdio.h --- include/libc/libc_stdio.h | 22 ---------------------- include/rtlibc.h | 1 - 2 files changed, 23 deletions(-) delete mode 100644 include/libc/libc_stdio.h diff --git a/include/libc/libc_stdio.h b/include/libc/libc_stdio.h deleted file mode 100644 index 565e1bfd32..0000000000 --- a/include/libc/libc_stdio.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-09-05 Meco Man the first version - */ - -#ifndef LIBC_STDIO_H__ -#define LIBC_STDIO_H__ - -#include - -#ifdef RT_USING_POSIX_GETLINE - -#include - -#endif - -#endif diff --git a/include/rtlibc.h b/include/rtlibc.h index 1fd6053deb..d78ec8046f 100644 --- a/include/rtlibc.h +++ b/include/rtlibc.h @@ -18,7 +18,6 @@ #include "libc/libc_dirent.h" #include "libc/libc_signal.h" #include "libc/libc_fdset.h" -#include "libc/libc_stdio.h" #ifndef RT_USING_LIBC #if defined(__CC_ARM) || defined(__CLANG_ARM) || defined(__IAR_SYSTEMS_ICC__) From d0a9402583f33037723405b5e6ad7e39b51b128c Mon Sep 17 00:00:00 2001 From: ZHU Hao Date: Tue, 22 Jun 2021 14:12:05 +0800 Subject: [PATCH 184/255] Update drv_sound.c --- bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c b/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c index 0703b5c902..e9b4496894 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c +++ b/bsp/bluetrum/ab32vg1-ab-prougen/board/ports/audio/drv_sound.c @@ -388,8 +388,6 @@ static rt_err_t sound_stop(struct rt_audio_device *audio, int stream) if (stream == AUDIO_STREAM_REPLAY) { - // DACDIGCON0 = 0; - // AUBUFCON &= ~BIT(4); LOG_D("close sound device"); } From a3db13b0a251c2143ac7b12f75ff32adbed319c1 Mon Sep 17 00:00:00 2001 From: ZHU Hao Date: Tue, 22 Jun 2021 14:15:06 +0800 Subject: [PATCH 185/255] Update link.lds --- bsp/bluetrum/ab32vg1-ab-prougen/link.lds | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/link.lds b/bsp/bluetrum/ab32vg1-ab-prougen/link.lds index bdb1b9d2cc..b12f648d48 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/link.lds +++ b/bsp/bluetrum/ab32vg1-ab-prougen/link.lds @@ -34,8 +34,8 @@ SECTIONS } > init .ram1 __ram1_vma : { - . = ALIGN(4); /* section information for initial */ + . = ALIGN(4); __rt_init_start = .; KEEP(*(SORT(.rti_fn*))) __rt_init_end = .; @@ -75,7 +75,6 @@ SECTIONS KEEP(*(.vector)) *(.irq.cache) *(.irq*) - /* *components*src**.o (.text* .rodata*) */ *ab32vg1_hal**.o (.text* .rodata*) *drv_gpio.o (.text* .rodata*) *drv_usart.o (.rodata*) From 5d4260ab6df4faa1d829e164ffb95aeabd9aa4e5 Mon Sep 17 00:00:00 2001 From: wanghaijing Date: Tue, 22 Jun 2021 23:54:54 +0800 Subject: [PATCH 186/255] [pm] index should be less than PM_MODLUE_MAX_ID --- components/drivers/pm/pm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/components/drivers/pm/pm.c b/components/drivers/pm/pm.c index 80ed101498..cf488a9ce1 100644 --- a/components/drivers/pm/pm.c +++ b/components/drivers/pm/pm.c @@ -836,12 +836,10 @@ rt_uint32_t rt_pm_module_get_status(void) rt_uint32_t req_status = 0x00; pm = &_pm; - for (index = 0; index < 32; index ++) + for (index = 0; index < PM_MODULE_MAX_ID; index ++) { if (pm->module_status[index].req_status == 0x01) req_status |= 1<= PM_MODULE_MAX_ID) - break; } return req_status; From fa3d95bb1c46c36023341e43f6c328c9a2077606 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 21 Jun 2021 21:15:22 +0800 Subject: [PATCH 187/255] =?UTF-8?q?[libc][syscall]=E6=95=B4=E7=90=86?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/libc/compilers/newlib/syscalls.c | 72 +++++++-------------- 1 file changed, 24 insertions(+), 48 deletions(-) diff --git a/components/libc/compilers/newlib/syscalls.c b/components/libc/compilers/newlib/syscalls.c index 7c5d51eca6..e01dc59eb6 100644 --- a/components/libc/compilers/newlib/syscalls.c +++ b/components/libc/compilers/newlib/syscalls.c @@ -29,21 +29,18 @@ /* Reentrant versions of system calls. */ #ifndef _REENT_ONLY -int * -__errno () +int *__errno () { return _rt_errno(); } #endif -int -_getpid_r(struct _reent *ptr) +int _getpid_r(struct _reent *ptr) { return 0; } -int -_close_r(struct _reent *ptr, int fd) +int _close_r(struct _reent *ptr, int fd) { #ifndef RT_USING_DFS /* return "not supported" */ @@ -54,40 +51,35 @@ _close_r(struct _reent *ptr, int fd) #endif } -int -_execve_r(struct _reent *ptr, const char * name, char *const *argv, char *const *env) +int _execve_r(struct _reent *ptr, const char * name, char *const *argv, char *const *env) { /* return "not supported" */ ptr->_errno = ENOTSUP; return -1; } -int -_fcntl_r(struct _reent *ptr, int fd, int cmd, int arg) +int _fcntl_r(struct _reent *ptr, int fd, int cmd, int arg) { /* return "not supported" */ ptr->_errno = ENOTSUP; return -1; } -int -_fork_r(struct _reent *ptr) +int _fork_r(struct _reent *ptr) { /* return "not supported" */ ptr->_errno = ENOTSUP; return -1; } -int -_fstat_r(struct _reent *ptr, int fd, struct stat *pstat) +int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat) { /* return "not supported" */ ptr->_errno = ENOTSUP; return -1; } -int -_isatty_r(struct _reent *ptr, int fd) +int _isatty_r(struct _reent *ptr, int fd) { if (fd >=0 && fd < 3) { @@ -99,24 +91,21 @@ _isatty_r(struct _reent *ptr, int fd) } } -int -_kill_r(struct _reent *ptr, int pid, int sig) +int _kill_r(struct _reent *ptr, int pid, int sig) { /* return "not supported" */ ptr->_errno = ENOTSUP; return -1; } -int -_link_r(struct _reent *ptr, const char *old, const char *new) +int _link_r(struct _reent *ptr, const char *old, const char *new) { /* return "not supported" */ ptr->_errno = ENOTSUP; return -1; } -_off_t -_lseek_r(struct _reent *ptr, int fd, _off_t pos, int whence) +_off_t _lseek_r(struct _reent *ptr, int fd, _off_t pos, int whence) { #ifndef RT_USING_DFS /* return "not supported" */ @@ -130,8 +119,7 @@ _lseek_r(struct _reent *ptr, int fd, _off_t pos, int whence) #endif } -int -_mkdir_r(struct _reent *ptr, const char *name, int mode) +int _mkdir_r(struct _reent *ptr, const char *name, int mode) { #ifndef RT_USING_DFS /* return "not supported" */ @@ -145,8 +133,7 @@ _mkdir_r(struct _reent *ptr, const char *name, int mode) #endif } -int -_open_r(struct _reent *ptr, const char *file, int flags, int mode) +int _open_r(struct _reent *ptr, const char *file, int flags, int mode) { #ifndef RT_USING_DFS /* return "not supported" */ @@ -160,8 +147,7 @@ _open_r(struct _reent *ptr, const char *file, int flags, int mode) #endif } -_ssize_t -_read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes) +_ssize_t _read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes) { #ifndef RT_USING_DFS /* return "not supported" */ @@ -175,8 +161,7 @@ _read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes) #endif } -int -_rename_r(struct _reent *ptr, const char *old, const char *new) +int _rename_r(struct _reent *ptr, const char *old, const char *new) { #ifndef RT_USING_DFS /* return "not supported" */ @@ -190,8 +175,7 @@ _rename_r(struct _reent *ptr, const char *old, const char *new) #endif } -int -_stat_r(struct _reent *ptr, const char *file, struct stat *pstat) +int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat) { #ifndef RT_USING_DFS /* return "not supported" */ @@ -205,8 +189,7 @@ _stat_r(struct _reent *ptr, const char *file, struct stat *pstat) #endif } -int -_unlink_r(struct _reent *ptr, const char *file) +int _unlink_r(struct _reent *ptr, const char *file) { #ifndef RT_USING_DFS /* return "not supported" */ @@ -217,16 +200,14 @@ _unlink_r(struct _reent *ptr, const char *file) #endif } -int -_wait_r(struct _reent *ptr, int *status) +int _wait_r(struct _reent *ptr, int *status) { /* return "not supported" */ ptr->_errno = ENOTSUP; return -1; } -_ssize_t -_write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes) +_ssize_t _write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes) { #ifndef RT_USING_DFS #ifdef RT_USING_DEVICE @@ -253,8 +234,7 @@ _write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes) } #ifdef RT_USING_HEAP /* Memory routine */ -void * -_malloc_r (struct _reent *ptr, size_t size) +void *_malloc_r (struct _reent *ptr, size_t size) { void* result; @@ -267,8 +247,7 @@ _malloc_r (struct _reent *ptr, size_t size) return result; } -void * -_realloc_r (struct _reent *ptr, void *old, size_t newlen) +void *_realloc_r (struct _reent *ptr, void *old, size_t newlen) { void* result; @@ -294,8 +273,7 @@ void *_calloc_r (struct _reent *ptr, size_t size, size_t len) return result; } -void -_free_r (struct _reent *ptr, void *addr) +void _free_r (struct _reent *ptr, void *addr) { rt_free (addr); } @@ -309,16 +287,14 @@ _sbrk_r(struct _reent *ptr, ptrdiff_t incr) #endif /*RT_USING_HEAP*/ /* for exit() and abort() */ -__attribute__ ((noreturn)) void -_exit (int status) +__attribute__ ((noreturn)) void _exit (int status) { extern void __rt_libc_exit(int status); __rt_libc_exit(status); while(1); } -void -_system(const char *s) +void _system(const char *s) { extern int __rt_libc_system(const char *string); __rt_libc_system(s); From 312753686b7c64dfabf02d38ecca28c59ebc2810 Mon Sep 17 00:00:00 2001 From: chenjh Date: Thu, 17 Jun 2021 15:56:04 +0800 Subject: [PATCH 188/255] =?UTF-8?q?[testcase]=20=E5=A2=9E=E5=8A=A0serial?= =?UTF-8?q?=5Fv2=E7=9A=84=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/utest/testcases/Kconfig | 1 + examples/utest/testcases/drivers/SConscript | 15 + .../utest/testcases/drivers/serial_v2/Kconfig | 7 + .../testcases/drivers/serial_v2/README.md | 120 +++++++ .../testcases/drivers/serial_v2/SConscript | 16 + .../drivers/serial_v2/uart_rxb_txb.c | 230 ++++++++++++++ .../drivers/serial_v2/uart_rxb_txnb.c | 263 ++++++++++++++++ .../drivers/serial_v2/uart_rxnb_txb.c | 266 ++++++++++++++++ .../drivers/serial_v2/uart_rxnb_txnb.c | 294 ++++++++++++++++++ 9 files changed, 1212 insertions(+) create mode 100644 examples/utest/testcases/drivers/SConscript create mode 100644 examples/utest/testcases/drivers/serial_v2/Kconfig create mode 100644 examples/utest/testcases/drivers/serial_v2/README.md create mode 100644 examples/utest/testcases/drivers/serial_v2/SConscript create mode 100644 examples/utest/testcases/drivers/serial_v2/uart_rxb_txb.c create mode 100644 examples/utest/testcases/drivers/serial_v2/uart_rxb_txnb.c create mode 100644 examples/utest/testcases/drivers/serial_v2/uart_rxnb_txb.c create mode 100644 examples/utest/testcases/drivers/serial_v2/uart_rxnb_txnb.c diff --git a/examples/utest/testcases/Kconfig b/examples/utest/testcases/Kconfig index a9b556f1e3..5dc1c6c420 100644 --- a/examples/utest/testcases/Kconfig +++ b/examples/utest/testcases/Kconfig @@ -9,6 +9,7 @@ if RT_USING_UTESTCASES source "$RTT_DIR/examples/utest/testcases/utest/Kconfig" source "$RTT_DIR/examples/utest/testcases/kernel/Kconfig" +source "$RTT_DIR/examples/utest/testcases/drivers/serial_v2/Kconfig" endif diff --git a/examples/utest/testcases/drivers/SConscript b/examples/utest/testcases/drivers/SConscript new file mode 100644 index 0000000000..4c815c49b8 --- /dev/null +++ b/examples/utest/testcases/drivers/SConscript @@ -0,0 +1,15 @@ +# RT-Thread building script for bridge + +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/examples/utest/testcases/drivers/serial_v2/Kconfig b/examples/utest/testcases/drivers/serial_v2/Kconfig new file mode 100644 index 0000000000..3c8d480b3a --- /dev/null +++ b/examples/utest/testcases/drivers/serial_v2/Kconfig @@ -0,0 +1,7 @@ +menu "Utest Serial Testcase" + +config UTEST_SERIAL_TC + bool "Serial testcase" + default n + +endmenu diff --git a/examples/utest/testcases/drivers/serial_v2/README.md b/examples/utest/testcases/drivers/serial_v2/README.md new file mode 100644 index 0000000000..38d71ce8e8 --- /dev/null +++ b/examples/utest/testcases/drivers/serial_v2/README.md @@ -0,0 +1,120 @@ +## 1、介绍 + +该目录下 c 文件是新版本串口的测试用例,在 `examples/utest/testcases/drivers/serial_v2` 目录结构里,该测试用例用来测试串口的各个操作模式是否正常工作。 + +## 2、 文件说明 + +| 文件 | 描述 | +| ---------------- | ----------------------------------------- | +| uart_rxb_txb.c | 串口接收阻塞和发送阻塞模式 的测试用例 | +| uart_rxb_txnb.c | 串口接收阻塞和发送非阻塞模式 的测试用例 | +| uart_rxnb_txb.c | 串口接收非阻塞和发送阻塞模式 的测试用例 | +| uart_rxnb_txnb.c | 串口接收非阻塞和发送非阻塞模式 的测试用例 | + +## 3、软硬件环境 + +硬件上需要支持 RT-Thread 的完整版操作系统,版本为4.0.4及以上,且硬件有串口硬件外设,软件上需要支持 内核接口、IPC 、Device 框架。 + +## 4、测试项 + +### 4.1 测试说明 + +上文所提及的模式是指串口使用时的操作模式,不涉及硬件的工作模式的配置情况(硬件工作模式一般有轮询POLL、中断INT、DMA),因此使用时需要结合具体的硬件工作模式去配置使用。例如 发送阻塞和接收非阻塞模式 ,这个测试有很多种硬件配置,配置情况例如:DMA发送阻塞和DMA接收非阻塞,INT发送阻塞和DMA接收非阻塞,POLL发送阻塞和DMA接收非阻塞等等。因此通过排列组合后的测试场景有4*9=36种,有意义的组合方式为20种。如下表: + + +| 接收非阻塞 | 发送阻塞 | 组合 | 有意义的组合方式 | +| ---------- | -------- | ----------------- | ---------------- | +| POLL | POLL | RX_POLL + TX_POLL | | +| | INT | RX_POLL + TX_INT | | +| | DMA | RX_POLL + TX_DMA | | +| INT | POLL | RX_INT + TX_POLL | ✔ | +| | INT | RX_INT + TX_INT | ✔ | +| | DMA | RX_INT + TX_DMA | ✔ | +| DMA | POLL | RX_DMA + TX_POLL | ✔ | +| | INT | RX_DMA + TX_INT | ✔ | +| | DMA | RX_DMA + TX_DMA | ✔ | + +| 接收非阻塞 | 发送非阻塞 | 组合 | 有意义的组合方式 | +| ---------- | ---------- | ----------------- | ---------------- | +| POLL | POLL | RX_POLL + TX_POLL | | +| | INT | RX_POLL + TX_INT | | +| | DMA | RX_POLL + TX_DMA | | +| INT | POLL | RX_INT + TX_POLL | | +| | INT | RX_INT + TX_INT | ✔ | +| | DMA | RX_INT + TX_DMA | ✔ | +| DMA | POLL | RX_DMA + TX_POLL | | +| | INT | RX_DMA + TX_INT | ✔ | +| | DMA | RX_DMA + TX_DMA | ✔ | + +| 接收阻塞 | 发送阻塞 | 组合 | 有意义的组合方式 | +| -------- | -------- | ----------------- | ---------------- | +| POLL | POLL | RX_POLL + TX_POLL | | +| | INT | RX_POLL + TX_INT | | +| | DMA | RX_POLL + TX_DMA | | +| INT | POLL | RX_INT + TX_POLL | ✔ | +| | INT | RX_INT + TX_INT | ✔ | +| | DMA | RX_INT + TX_DMA | ✔ | +| DMA | POLL | RX_DMA + TX_POLL | ✔ | +| | INT | RX_DMA + TX_INT | ✔ | +| | DMA | RX_DMA + TX_DMA | ✔ | + +| 接收阻塞 | 发送非阻塞 | 组合 | 有意义的组合方式 | +| -------- | ---------- | ----------------- | ---------------- | +| POLL | POLL | RX_POLL + TX_POLL | | +| | INT | RX_POLL + TX_INT | | +| | DMA | RX_POLL + TX_DMA | | +| INT | POLL | RX_INT + TX_POLL | | +| | INT | RX_INT + TX_INT | ✔ | +| | DMA | RX_INT + TX_DMA | ✔ | +| DMA | POLL | RX_DMA + TX_POLL | | +| | INT | RX_DMA + TX_INT | ✔ | +| | DMA | RX_DMA + TX_DMA | ✔ | + +需要解释的是,为什么会存在无意义的组合模式,举个例子,非阻塞模式下,肯定是不会出现POLL(轮询)方式的,因为POLL方式已经表明是阻塞方式了。 +该测试用例在测试多种组合时,需要通过更改`rtconfig.h`文件对硬件模式进行静态配置。 + +### 4.2 测试思路 + +这四个测试用例的测试思路基本一致。 + +硬件上:**短接串口的发送TX引脚和接收RX引脚,完成自发自收的回路**。 + +软件上:创建两个线程A和B,A为接收线程,B为发送线程,设置A线程优先级比B线程优先级高。发送线程发送随机长度(长度范围是 0 到 1000)的数据,接收线程接收到数据进行校验,数据正确则测试通过,默认测试100次。 + +## 5、配置 + +使用该测试用例需要在 `env` 工具的 `menuconfig` 中做相关配置,配置如下所示(使用 RT-Thread-Studio 的配置路径一致 ): + +``` +RT-Thread Utestcases ---> + [*] RT-Thread Utestcases ---> + Utest Serial Testcase ---> + [*] Serial testcase +``` + +## 6、使用 + +\- 编译下载。 + +\- 在 MSH 中输入 `utest_run testcases.drivers.uart_rxb_txb` 运行串口接收阻塞和发送阻塞测试用例。 + +\- 在 MSH 中输入 `utest_run testcases.drivers.uart_rxb_txb` 运行串口接收阻塞和发送阻塞测试用例。 + +\- 在 MSH 中输入 `utest_run testcases.drivers.uart_rxb_txb` 运行串口接收阻塞和发送阻塞测试用例。 + +\- 在 MSH 中输入 `utest_run testcases.drivers.uart_rxb_txb` 运行串口接收阻塞和发送阻塞测试用例。 + +如果仅仅配置了 `Serial testcase` 相关的测试用例,则直接输入 `utest_run` 运行即可将上述测试用例按序测试。 + +## 7、注意事项 + +\- 需配置正确的测试用例。 + +\- 如有需要,可开启 ULOG 查看测试用例日志信息。 + +\- 需在 MSH 中输入正确的命令行。 + +\- 测试用例默认的测试数据长度范围最大为1000字节,如果接收端的缓冲区大小配置为小于1000字节时,那么在测试接收阻塞模式时,将会由于获取不了1000字节长度导致线程持续阻塞(因为测试用例是按 `recv_len` 长度去接收的,而不是按照单字节去接收的),因此建议接收端的缓冲区大小 (对应宏例如为 `BSP_UART2_RX_BUFSIZE`)设置为1024即可;当然也可按需减小测试的最大数据长度。 + +\- 该测试用例需要结合硬件具体的工作模式(POLL 、INT、DMA)进行测试,而硬件工作模式只能选择一种,因此需要在 `rtconfig.h` 中对串口相应的宏进行配置,来选择不同的工作模式去进行测试。 + diff --git a/examples/utest/testcases/drivers/serial_v2/SConscript b/examples/utest/testcases/drivers/serial_v2/SConscript new file mode 100644 index 0000000000..a7a46e656a --- /dev/null +++ b/examples/utest/testcases/drivers/serial_v2/SConscript @@ -0,0 +1,16 @@ +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +src = Split(''' +uart_rxb_txnb.c +uart_rxb_txb.c +uart_rxnb_txb.c +uart_rxnb_txnb.c +''') + +CPPPATH = [cwd] + +group = DefineGroup('utestcases', src, depend = ['UTEST_SERIAL_TC'], CPPPATH = CPPPATH) + +Return('group') diff --git a/examples/utest/testcases/drivers/serial_v2/uart_rxb_txb.c b/examples/utest/testcases/drivers/serial_v2/uart_rxb_txb.c new file mode 100644 index 0000000000..8b2205ee1a --- /dev/null +++ b/examples/utest/testcases/drivers/serial_v2/uart_rxb_txb.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-16 KyleChan the first version + */ + +#include +#include "utest.h" +#include +#include + +#define TC_UART_DEVICE_NAME "uart2" +#define TC_UART_SEND_TIMES 100 + + +#ifdef UTEST_SERIAL_TC + +#define TEST_UART_NAME TC_UART_DEVICE_NAME + +static struct rt_serial_device *serial; +static rt_uint8_t uart_over_flag; +static rt_bool_t uart_result = RT_TRUE; + +static rt_err_t uart_find(void) +{ + serial = (struct rt_serial_device *)rt_device_find(TEST_UART_NAME); + + if (serial == RT_NULL) + { + LOG_E("find %s device failed!\n", TEST_UART_NAME); + return -RT_ERROR; + } + + return RT_EOK; +} + +static void uart_send_entry(void *parameter) +{ + rt_uint8_t *uart_write_buffer; + rt_uint16_t send_len; + + rt_uint32_t i = 0; + send_len = *(rt_uint16_t *)parameter; + /* assign send buffer */ + uart_write_buffer = (rt_uint8_t *)rt_malloc(send_len); + if (uart_write_buffer == RT_NULL) + { + LOG_E("Without spare memory for uart dma!"); + uart_result = RT_FALSE; + return; + } + + rt_memset(uart_write_buffer, 0, send_len); + + for (i = 0; i < send_len; i++) + { + uart_write_buffer[i] = (rt_uint8_t)i; + } + /* send buffer */ + if (rt_device_write(&serial->parent, 0, uart_write_buffer, send_len) != send_len) + { + LOG_E("device write failed\r\n"); + } + rt_free(uart_write_buffer); + +} + +static void uart_rec_entry(void *parameter) +{ + rt_uint16_t rev_len; + + rev_len = *(rt_uint16_t *)parameter; + rt_uint8_t *ch; + ch = (rt_uint8_t *)rt_calloc(1, sizeof(rt_uint8_t) * (rev_len + 1)); + rt_int32_t cnt, i; + rt_uint8_t last_old_data; + rt_bool_t fisrt_flag = RT_TRUE; + rt_uint32_t all_receive_length = 0; + + + while (1) + { + cnt = rt_device_read(&serial->parent, 0, (void *)ch, rev_len); + if (cnt == 0) + { + continue; + } + + if (fisrt_flag != RT_TRUE) + { + if ((rt_uint8_t)(last_old_data + 1) != ch[0]) + { + LOG_E("_Read Different data -> former data: %x, current data: %x.", last_old_data, ch[0]); + uart_result = RT_FALSE; + rt_free(ch); + return; + } + } + else + { + fisrt_flag = RT_FALSE; + } + + for (i = 0; i < cnt - 1; i++) + { + if ((rt_uint8_t)(ch[i] + 1) != ch[i + 1]) + { + LOG_E("Read Different data -> former data: %x, current data: %x.", ch[i], ch[i + 1]); + + uart_result = RT_FALSE; + rt_free(ch); + return; + } + } + all_receive_length += cnt; + if (all_receive_length >= rev_len) + break; + else + last_old_data = ch[cnt - 1]; + } + rt_free(ch); + uart_over_flag = RT_TRUE; +} + +static rt_err_t uart_api(rt_uint16_t length) +{ + rt_thread_t thread_send = RT_NULL; + rt_thread_t thread_recv = RT_NULL; + rt_err_t result = RT_EOK; + uart_over_flag = RT_FALSE; + + result = uart_find(); + if (result != RT_EOK) + { + return -RT_ERROR; + } + + /* Reinitialize */ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + config.baud_rate = BAUD_RATE_115200; + config.rx_bufsz = BSP_UART2_RX_BUFSIZE; + config.tx_bufsz = BSP_UART2_TX_BUFSIZE; + rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config); + + result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING); + + if (result != RT_EOK) + { + LOG_E("Open uart device failed."); + uart_result = RT_FALSE; + return -RT_ERROR; + } + + thread_send = rt_thread_create("uart_send", uart_send_entry, &length, 1024, RT_THREAD_PRIORITY_MAX - 4, 10); + thread_recv = rt_thread_create("uart_recv", uart_rec_entry, &length, 1024, RT_THREAD_PRIORITY_MAX - 5, 10); + if ((thread_send != RT_NULL) && (thread_recv != RT_NULL)) + { + rt_thread_startup(thread_send); + rt_thread_startup(thread_recv); + } + else + { + result = -RT_ERROR; + goto __exit; + } + + while (1) + { + if (uart_result != RT_TRUE) + { + LOG_E("The test for uart dma is failure."); + result = -RT_ERROR; + goto __exit; + } + if (uart_over_flag == RT_TRUE) + { + goto __exit; + } + /* waiting for test over */ + rt_thread_mdelay(5); + } +__exit: + rt_device_close(&serial->parent); + return result; +} + +static void tc_uart_api(void) +{ + rt_uint32_t times = 0; + rt_uint16_t num = 0; + while (TC_UART_SEND_TIMES - times) + { + num = (rand() % 1000) + 1; + if(uart_api(num) == RT_EOK) + LOG_I("data_lens [%3d], it is correct to read and write data. [%d] times testing.", num, ++times); + else + { + LOG_E("uart test error"); + break; + } + } + uassert_true(uart_over_flag == RT_TRUE); +} + +static rt_err_t utest_tc_init(void) +{ + LOG_I("UART TEST: Please connect Tx and Rx directly for self testing."); + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + uart_result = RT_TRUE; + uart_over_flag = RT_FALSE; + + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(tc_uart_api); +} + +UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_rxb_txb", utest_tc_init, utest_tc_cleanup, 30); + +#endif /* TC_UART_USING_TC */ diff --git a/examples/utest/testcases/drivers/serial_v2/uart_rxb_txnb.c b/examples/utest/testcases/drivers/serial_v2/uart_rxb_txnb.c new file mode 100644 index 0000000000..f03a24fe13 --- /dev/null +++ b/examples/utest/testcases/drivers/serial_v2/uart_rxb_txnb.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-16 KyleChan the first version + */ + +#include +#include "utest.h" +#include +#include + +#define TC_UART_DEVICE_NAME "uart2" +#define TC_UART_SEND_TIMES 100 + + +#ifdef UTEST_SERIAL_TC + +#define TEST_UART_NAME TC_UART_DEVICE_NAME + +static struct rt_serial_device *serial; +static rt_sem_t tx_sem; +static rt_uint8_t uart_over_flag; +static rt_bool_t uart_result = RT_TRUE; + +static rt_err_t uart_find(void) +{ + serial = (struct rt_serial_device *)rt_device_find(TEST_UART_NAME); + + if (serial == RT_NULL) + { + LOG_E("find %s device failed!\n", TEST_UART_NAME); + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t uart_tx_completion(rt_device_t device, void *buffer) +{ + rt_sem_release(tx_sem); + + return RT_EOK; +} + +static void uart_send_entry(void *parameter) +{ + rt_uint8_t *uart_write_buffer; + rt_uint16_t send_len, len = 0; + rt_err_t result; + + rt_uint32_t i = 0; + send_len = *(rt_uint16_t *)parameter; + /* assign send buffer */ + uart_write_buffer = (rt_uint8_t *)rt_malloc(send_len); + if (uart_write_buffer == RT_NULL) + { + LOG_E("Without spare memory for uart dma!"); + uart_result = RT_FALSE; + return; + } + + rt_memset(uart_write_buffer, 0, send_len); + + for (i = 0; i < send_len; i++) + { + uart_write_buffer[i] = (rt_uint8_t)i; + } + /* send buffer */ + while (send_len - len) + { + len += rt_device_write(&serial->parent, 0, uart_write_buffer + len, send_len - len); + result = rt_sem_take(tx_sem, RT_WAITING_FOREVER); + if (result != RT_EOK) + { + LOG_E("take sem err in send."); + } + } + rt_free(uart_write_buffer); + +} + +static void uart_rec_entry(void *parameter) +{ + rt_uint16_t rev_len; + + rev_len = *(rt_uint16_t *)parameter; + rt_uint8_t *ch; + ch = (rt_uint8_t *)rt_calloc(1, sizeof(rt_uint8_t) * (rev_len + 1)); + rt_int32_t cnt, i; + rt_uint8_t last_old_data; + rt_bool_t fisrt_flag = RT_TRUE; + rt_uint32_t all_receive_length = 0; + + while (1) + { + cnt = rt_device_read(&serial->parent, 0, (void *)ch, rev_len); + if (cnt != rev_len) + { + continue; + } + + if (fisrt_flag != RT_TRUE) + { + if ((rt_uint8_t)(last_old_data + 1) != ch[0]) + { + LOG_E("_Read Different data -> former data: %x, current data: %x.", last_old_data, ch[0]); + uart_result = RT_FALSE; + rt_free(ch); + return; + } + } + else + { + fisrt_flag = RT_FALSE; + } + + for (i = 0; i < cnt - 1; i++) + { + if ((rt_uint8_t)(ch[i] + 1) != ch[i + 1]) + { + LOG_E("Read Different data -> former data: %x, current data: %x.", ch[i], ch[i + 1]); + + uart_result = RT_FALSE; + rt_free(ch); + return; + } + } + all_receive_length += cnt; + if (all_receive_length >= rev_len) + break; + else + last_old_data = ch[cnt - 1]; + } + rt_free(ch); + uart_over_flag = RT_TRUE; +} + +static rt_err_t uart_api(rt_uint16_t test_buf) +{ + rt_thread_t thread_send = RT_NULL; + rt_thread_t thread_recv = RT_NULL; + rt_err_t result = RT_EOK; + uart_over_flag = RT_FALSE; + + result = uart_find(); + if (result != RT_EOK) + { + return -RT_ERROR; + } + + tx_sem = rt_sem_create("tx_sem", 0, RT_IPC_FLAG_PRIO); + if (tx_sem == RT_NULL) + { + LOG_E("Init sem failed."); + uart_result = RT_FALSE; + return -RT_ERROR; + } + + /* Reinitialize */ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + config.baud_rate = BAUD_RATE_115200; + config.rx_bufsz = BSP_UART2_RX_BUFSIZE; + config.tx_bufsz = BSP_UART2_TX_BUFSIZE; + rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config); + + result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING); + + if (result != RT_EOK) + { + LOG_E("Open uart device failed."); + uart_result = RT_FALSE; + return -RT_ERROR; + } + + /* set receive callback function */ + result = rt_device_set_tx_complete(&serial->parent, uart_tx_completion); + if (result != RT_EOK) + { + goto __exit; + } + + thread_recv = rt_thread_create("uart_recv", uart_rec_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 5, 10); + thread_send = rt_thread_create("uart_send", uart_send_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 4, 10); + + if (thread_send != RT_NULL && thread_recv != RT_NULL) + { + rt_thread_startup(thread_recv); + rt_thread_startup(thread_send); + } + else + { + result = -RT_ERROR; + goto __exit; + } + + while (1) + { + if (uart_result != RT_TRUE) + { + LOG_E("The test for uart dma is failure."); + result = -RT_ERROR; + goto __exit; + } + if (uart_over_flag == RT_TRUE) + { + goto __exit; + } + /* waiting for test over */ + rt_thread_mdelay(5); + } +__exit: + if (tx_sem) + rt_sem_delete(tx_sem); + + rt_device_close(&serial->parent); + return result; +} + +static void tc_uart_api(void) +{ + rt_uint32_t times = 0; + rt_uint16_t num = 0; + while (TC_UART_SEND_TIMES - times) + { + num = (rand() % 1000) + 1; + if(uart_api(num) == RT_EOK) + LOG_I("data_lens [%3d], it is correct to read and write data. [%d] times testing.", num, ++times); + else + { + LOG_E("uart test error"); + break; + } + } + uassert_true(uart_over_flag == RT_TRUE); +} + +static rt_err_t utest_tc_init(void) +{ + LOG_I("UART TEST: Please connect Tx and Rx directly for self testing."); + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + tx_sem = RT_NULL; + uart_result = RT_TRUE; + uart_over_flag = RT_FALSE; + + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(tc_uart_api); +} + +UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_rxb_txnb", utest_tc_init, utest_tc_cleanup, 30); + +#endif diff --git a/examples/utest/testcases/drivers/serial_v2/uart_rxnb_txb.c b/examples/utest/testcases/drivers/serial_v2/uart_rxnb_txb.c new file mode 100644 index 0000000000..c1c88ddc9f --- /dev/null +++ b/examples/utest/testcases/drivers/serial_v2/uart_rxnb_txb.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-16 KyleChan the first version + */ + +#include +#include "utest.h" +#include +#include + +#define TC_UART_DEVICE_NAME "uart2" +#define TC_UART_SEND_TIMES 100 + + +#ifdef UTEST_SERIAL_TC + +#define TEST_UART_NAME TC_UART_DEVICE_NAME + +static struct rt_serial_device *serial; +static rt_sem_t rx_sem; +static rt_uint8_t uart_over_flag; +static rt_bool_t uart_result = RT_TRUE; + +static rt_err_t uart_find(void) +{ + serial = (struct rt_serial_device *)rt_device_find(TEST_UART_NAME); + + if (serial == RT_NULL) + { + LOG_E("find %s device failed!\n", TEST_UART_NAME); + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t uart_rx_indicate(rt_device_t device, rt_size_t size) +{ + rt_sem_release(rx_sem); + + return RT_EOK; +} + +static void uart_send_entry(void *parameter) +{ + rt_uint8_t *uart_write_buffer; + rt_uint16_t send_len; + + rt_uint32_t i = 0; + send_len = *(rt_uint16_t *)parameter; + + /* assign send buffer */ + uart_write_buffer = (rt_uint8_t *)rt_malloc(send_len); + if (uart_write_buffer == RT_NULL) + { + LOG_E("Without spare memory for uart dma!"); + uart_result = RT_FALSE; + return; + } + + rt_memset(uart_write_buffer, 0, send_len); + + for (i = 0; i < send_len; i++) + { + uart_write_buffer[i] = (rt_uint8_t)i; + } + + /* send buffer */ + if (rt_device_write(&serial->parent, 0, uart_write_buffer, send_len) != send_len) + { + LOG_E("device write failed\r\n"); + } + rt_free(uart_write_buffer); +} + +static void uart_rec_entry(void *parameter) +{ + rt_uint16_t rev_len; + + rev_len = *(rt_uint16_t *)parameter; + rt_uint8_t *ch; + ch = (rt_uint8_t *)rt_calloc(1, sizeof(rt_uint8_t) * (rev_len + 1)); + rt_int32_t cnt, i; + rt_uint8_t last_old_data; + rt_bool_t fisrt_flag = RT_TRUE; + rt_uint32_t all_receive_length = 0; + + while (1) + { + rt_err_t result; + + result = rt_sem_take(rx_sem, RT_WAITING_FOREVER); + if (result != RT_EOK) + { + LOG_E("take sem err in recv."); + } + + cnt = rt_device_read(&serial->parent, 0, (void *)ch, rev_len); + if (cnt == 0) + { + continue; + } + + if (fisrt_flag != RT_TRUE) + { + if ((rt_uint8_t)(last_old_data + 1) != ch[0]) + { + LOG_E("_Read Different data -> former data: %x, current data: %x.", last_old_data, ch[0]); + uart_result = RT_FALSE; + rt_free(ch); + return; + } + } + else + { + fisrt_flag = RT_FALSE; + } + + for (i = 0; i < cnt - 1; i++) + { + if ((rt_uint8_t)(ch[i] + 1) != ch[i + 1]) + { + LOG_E("Read Different data -> former data: %x, current data: %x.", ch[i], ch[i + 1]); + + uart_result = RT_FALSE; + rt_free(ch); + return; + } + } + all_receive_length += cnt; + if (all_receive_length >= rev_len) + break; + else + last_old_data = ch[cnt - 1]; + } + rt_free(ch); + uart_over_flag = RT_TRUE; +} + +static rt_err_t uart_api(rt_uint16_t test_buf) +{ + rt_thread_t thread_send = RT_NULL; + rt_thread_t thread_recv = RT_NULL; + rt_err_t result = RT_EOK; + + result = uart_find(); + if (result != RT_EOK) + { + return -RT_ERROR; + } + + rx_sem = rt_sem_create("rx_sem", 0, RT_IPC_FLAG_PRIO); + if (rx_sem == RT_NULL) + { + LOG_E("Init sem failed."); + uart_result = RT_FALSE; + return -RT_ERROR; + } + + /* reinitialize */ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + config.baud_rate = BAUD_RATE_115200; + config.rx_bufsz = BSP_UART2_RX_BUFSIZE; + config.tx_bufsz = BSP_UART2_TX_BUFSIZE; + rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config); + + result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING); + + if (result != RT_EOK) + { + LOG_E("Open uart device failed."); + uart_result = RT_FALSE; + rt_sem_delete(rx_sem); + return -RT_ERROR; + } + + /* set receive callback function */ + result = rt_device_set_rx_indicate(&serial->parent, uart_rx_indicate); + if (result != RT_EOK) + { + goto __exit; + } + + thread_recv = rt_thread_create("uart_recv", uart_rec_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 5, 10); + thread_send = rt_thread_create("uart_send", uart_send_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 4, 10); + + if (thread_send != RT_NULL && thread_recv != RT_NULL) + { + rt_thread_startup(thread_recv); + rt_thread_startup(thread_send); + } + else + { + result = -RT_ERROR; + goto __exit; + } + + while (1) + { + if (uart_result != RT_TRUE) + { + LOG_E("The test for uart dma is failure."); + result = -RT_ERROR; + goto __exit; + } + if (uart_over_flag == RT_TRUE) + { + goto __exit; + } + /* waiting for test over */ + rt_thread_mdelay(5); + } +__exit: + if (rx_sem) + rt_sem_delete(rx_sem); + rt_device_close(&serial->parent); + uart_over_flag = RT_FALSE; + return result; +} + +static void tc_uart_api(void) +{ + rt_uint32_t times = 0; + rt_uint16_t num = 0; + while (TC_UART_SEND_TIMES - times) + { + num = (rand() % 1000) + 1; + if(uart_api(num) == RT_EOK) + LOG_I("data_lens [%3d], it is correct to read and write data. [%d] times testing.", num, ++times); + else + { + LOG_E("uart test error"); + break; + } + } + uassert_true(uart_result == RT_TRUE); +} + +static rt_err_t utest_tc_init(void) +{ + LOG_I("UART TEST: Please connect Tx and Rx directly for self testing."); + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + rx_sem = RT_NULL; + uart_result = RT_TRUE; + uart_over_flag = RT_FALSE; + + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(tc_uart_api); +} + +UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_rxnb_txb", utest_tc_init, utest_tc_cleanup, 30); + +#endif /* TC_UART_USING_TC */ diff --git a/examples/utest/testcases/drivers/serial_v2/uart_rxnb_txnb.c b/examples/utest/testcases/drivers/serial_v2/uart_rxnb_txnb.c new file mode 100644 index 0000000000..ad8d20b8cf --- /dev/null +++ b/examples/utest/testcases/drivers/serial_v2/uart_rxnb_txnb.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-16 KyleChan the first version + */ + +#include +#include "utest.h" +#include +#include + +#define TC_UART_DEVICE_NAME "uart2" +#define TC_UART_SEND_TIMES 100 + + +#ifdef UTEST_SERIAL_TC + +#define TEST_UART_NAME TC_UART_DEVICE_NAME + +static struct rt_serial_device *serial; +static rt_sem_t tx_sem; +static rt_sem_t rx_sem; +static rt_uint8_t uart_over_flag; +static rt_bool_t uart_result = RT_TRUE; + +static rt_err_t uart_find(void) +{ + serial = (struct rt_serial_device *)rt_device_find(TEST_UART_NAME); + + if (serial == RT_NULL) + { + LOG_E("find %s device failed!\n", TEST_UART_NAME); + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t uart_tx_completion(rt_device_t device, void *buffer) +{ + rt_sem_release(tx_sem); + return RT_EOK; +} + +static rt_err_t uart_rx_indicate(rt_device_t device, rt_size_t size) +{ + rt_sem_release(rx_sem); + return RT_EOK; +} + +static void uart_send_entry(void *parameter) +{ + rt_uint8_t *uart_write_buffer; + rt_uint16_t send_len, len = 0; + rt_err_t result; + + rt_uint32_t i = 0; + send_len = *(rt_uint16_t *)parameter; + /* assign send buffer */ + uart_write_buffer = (rt_uint8_t *)rt_malloc(send_len); + if (uart_write_buffer == RT_NULL) + { + LOG_E("Without spare memory for uart dma!"); + uart_result = RT_FALSE; + return; + } + + rt_memset(uart_write_buffer, 0, send_len); + + for (i = 0; i < send_len; i++) + { + uart_write_buffer[i] = (rt_uint8_t)i; + } + /* send buffer */ + while (send_len - len) + { + len += rt_device_write(&serial->parent, 0, uart_write_buffer + len, send_len - len); + result = rt_sem_take(tx_sem, RT_WAITING_FOREVER); + if (result != RT_EOK) + { + LOG_E("take sem err in send."); + } + } + rt_free(uart_write_buffer); + +} + +static void uart_rec_entry(void *parameter) +{ + rt_uint16_t rev_len; + + rev_len = *(rt_uint16_t *)parameter; + rt_uint8_t *ch; + ch = (rt_uint8_t *)rt_calloc(1, sizeof(rt_uint8_t) * (rev_len + 1)); + rt_int32_t cnt, i; + rt_uint8_t last_old_data; + rt_bool_t fisrt_flag = RT_TRUE; + rt_uint32_t all_receive_length = 0; + + while (1) + { + rt_err_t result; + + result = rt_sem_take(rx_sem, RT_WAITING_FOREVER); + if (result != RT_EOK) + { + LOG_E("take sem err in recv."); + } + + cnt = rt_device_read(&serial->parent, 0, (void *)ch, rev_len); + if (cnt == 0) + { + continue; + } + + if (fisrt_flag != RT_TRUE) + { + if ((rt_uint8_t)(last_old_data + 1) != ch[0]) + { + LOG_E("_Read Different data -> former data: %x, current data: %x.", last_old_data, ch[0]); + uart_result = RT_FALSE; + rt_free(ch); + return; + } + } + else + { + fisrt_flag = RT_FALSE; + } + + for (i = 0; i < cnt - 1; i++) + { + if ((rt_uint8_t)(ch[i] + 1) != ch[i + 1]) + { + LOG_E("Read Different data -> former data: %x, current data: %x.", ch[i], ch[i + 1]); + + uart_result = RT_FALSE; + rt_free(ch); + return; + } + } + all_receive_length += cnt; + if (all_receive_length >= rev_len) + break; + else + last_old_data = ch[cnt - 1]; + } + rt_free(ch); + uart_over_flag = RT_TRUE; +} + +static rt_err_t uart_api(rt_uint16_t test_buf) +{ + rt_thread_t thread_send = RT_NULL; + rt_thread_t thread_recv = RT_NULL; + rt_err_t result = RT_EOK; + uart_over_flag = RT_FALSE; + + result = uart_find(); + if (result != RT_EOK) + { + return -RT_ERROR; + } + + rx_sem = rt_sem_create("rx_sem", 0, RT_IPC_FLAG_PRIO); + if (rx_sem == RT_NULL) + { + LOG_E("Init rx_sem failed."); + uart_result = RT_FALSE; + return -RT_ERROR; + } + + tx_sem = rt_sem_create("tx_sem", 0, RT_IPC_FLAG_PRIO); + if (tx_sem == RT_NULL) + { + LOG_E("Init tx_sem failed."); + uart_result = RT_FALSE; + return -RT_ERROR; + } + + /* reinitialize */ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + config.baud_rate = BAUD_RATE_115200; + config.rx_bufsz = BSP_UART2_RX_BUFSIZE; + config.tx_bufsz = BSP_UART2_TX_BUFSIZE; + rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config); + + result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING); + + if (result != RT_EOK) + { + LOG_E("Open uart device failed."); + uart_result = RT_FALSE; + return -RT_ERROR; + } + + /* set receive callback function */ + result = rt_device_set_tx_complete(&serial->parent, uart_tx_completion); + if (result != RT_EOK) + { + goto __exit; + } + + result = rt_device_set_rx_indicate(&serial->parent, uart_rx_indicate); + if (result != RT_EOK) + { + goto __exit; + } + + thread_recv = rt_thread_create("uart_recv", uart_rec_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 5, 10); + thread_send = rt_thread_create("uart_send", uart_send_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 4, 10); + + if (thread_send != RT_NULL && thread_recv != RT_NULL) + { + rt_thread_startup(thread_recv); + rt_thread_startup(thread_send); + } + else + { + result = -RT_ERROR; + goto __exit; + } + + while (1) + { + if (uart_result != RT_TRUE) + { + LOG_E("The test for uart dma is failure."); + result = -RT_ERROR; + goto __exit; + } + if (uart_over_flag == RT_TRUE) + { + goto __exit; + } + /* waiting for test over */ + rt_thread_mdelay(5); + } +__exit: + if (tx_sem) + rt_sem_delete(tx_sem); + + if (rx_sem) + rt_sem_delete(rx_sem); + + rt_device_close(&serial->parent); + return result; +} + +static void tc_uart_api(void) +{ + rt_uint32_t times = 0; + rt_uint16_t num = 0; + while (TC_UART_SEND_TIMES - times) + { + num = (rand() % 1000) + 1; + if(uart_api(num) == RT_EOK) + LOG_I("data_lens [%3d], it is correct to read and write data. [%d] times testing.", num, ++times); + else + { + LOG_E("uart test error"); + break; + } + } + uassert_true(uart_over_flag == RT_TRUE); +} + +static rt_err_t utest_tc_init(void) +{ + LOG_I("UART TEST: Please connect Tx and Rx directly for self testing."); + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + tx_sem = RT_NULL; + uart_result = RT_TRUE; + uart_over_flag = RT_FALSE; + + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(tc_uart_api); +} + +UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_rxnb_txnb", utest_tc_init, utest_tc_cleanup, 30); + +#endif From 109efcbcd5fe63429534aaf9a06a4fb30f76241f Mon Sep 17 00:00:00 2001 From: DavidLin1577 Date: Wed, 23 Jun 2021 14:40:02 +0800 Subject: [PATCH 189/255] [components/drivers] added function declaration --- components/drivers/sensors/sensor.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/components/drivers/sensors/sensor.h b/components/drivers/sensors/sensor.h index 761ee49b4c..df70e96690 100755 --- a/components/drivers/sensors/sensor.h +++ b/components/drivers/sensors/sensor.h @@ -6,9 +6,26 @@ * Change Logs: * Date Author Notes * 2019-01-31 flybreak first version + * 2021-06-23 linpeng added function declaration */ +#ifndef __SENSOR_H__ +#define __SENSOR_H__ #include -#include +#ifdef __cplusplus +extern "C" +{ +#endif + +int rt_hw_sensor_register(rt_sensor_t sensor, + const char *name, + rt_uint32_t flag, + void *data); + +#ifdef __cplusplus +} +#endif + +#endif /*__SENSOR_H__*/ From ec3c1d4d0085c57d996a5c6acc21e7dbde85b30f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=BE=84?= <36236188+Eureka1024@users.noreply.github.com> Date: Wed, 23 Jun 2021 21:23:07 +0800 Subject: [PATCH 190/255] [kernel] Fix comment error for rt_mutex_detach(). --- src/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ipc.c b/src/ipc.c index c981aabe43..959f0fb522 100755 --- a/src/ipc.c +++ b/src/ipc.c @@ -588,7 +588,7 @@ rt_err_t rt_mutex_detach(rt_mutex_t mutex) /* wakeup all suspended threads */ rt_ipc_list_resume_all(&(mutex->parent.suspend_thread)); - /* detach semaphore object */ + /* detach mutex object */ rt_object_detach(&(mutex->parent.parent)); return RT_EOK; From ff4a936812676d826cd09bd0b0ea3c5771f8dc48 Mon Sep 17 00:00:00 2001 From: liuxianliang Date: Fri, 25 Jun 2021 15:58:43 +0800 Subject: [PATCH 191/255] [add] the support of lwip 2.0.3. --- components/net/Kconfig | 7 +- components/net/SConscript | 2 +- components/net/lwip-2.0.3/CHANGELOG | 4295 +++++++++++++++++ components/net/lwip-2.0.3/COPYING | 33 + components/net/lwip-2.0.3/FILES | 5 + components/net/lwip-2.0.3/README | 100 + components/net/lwip-2.0.3/READTEST.md | 29 + components/net/lwip-2.0.3/SConscript | 89 + components/net/lwip-2.0.3/UPGRADING | 243 + components/net/lwip-2.0.3/doc/FILES | 9 + .../net/lwip-2.0.3/doc/NO_SYS_SampleCode.c | 122 + components/net/lwip-2.0.3/doc/contrib.txt | 58 + .../net/lwip-2.0.3/doc/doxygen/generate.bat | 1 + .../net/lwip-2.0.3/doc/doxygen/generate.sh | 3 + .../net/lwip-2.0.3/doc/doxygen/lwip.Doxyfile | 2505 ++++++++++ .../net/lwip-2.0.3/doc/doxygen/main_page.h | 132 + .../lwip-2.0.3/doc/doxygen/output/index.html | 10 + components/net/lwip-2.0.3/doc/mdns.txt | 113 + components/net/lwip-2.0.3/doc/mqtt_client.txt | 162 + components/net/lwip-2.0.3/doc/ppp.txt | 529 ++ components/net/lwip-2.0.3/doc/rawapi.txt | 499 ++ components/net/lwip-2.0.3/doc/savannah.txt | 120 + components/net/lwip-2.0.3/doc/sys_arch.txt | 303 ++ components/net/lwip-2.0.3/src/FILES | 15 + components/net/lwip-2.0.3/src/Filelists.mk | 181 + components/net/lwip-2.0.3/src/api/api_lib.c | 1010 ++++ components/net/lwip-2.0.3/src/api/api_msg.c | 1953 ++++++++ components/net/lwip-2.0.3/src/api/err.c | 115 + components/net/lwip-2.0.3/src/api/netbuf.c | 246 + components/net/lwip-2.0.3/src/api/netdb.c | 413 ++ components/net/lwip-2.0.3/src/api/netifapi.c | 221 + components/net/lwip-2.0.3/src/api/sockets.c | 2851 +++++++++++ components/net/lwip-2.0.3/src/api/tcpip.c | 518 ++ components/net/lwip-2.0.3/src/apps/README.md | 6 + components/net/lwip-2.0.3/src/apps/httpd/fs.c | 179 + .../net/lwip-2.0.3/src/apps/httpd/fs/404.html | 21 + .../lwip-2.0.3/src/apps/httpd/fs/img/sics.gif | Bin 0 -> 724 bytes .../lwip-2.0.3/src/apps/httpd/fs/index.html | 47 + .../net/lwip-2.0.3/src/apps/httpd/fsdata.c | 298 ++ .../net/lwip-2.0.3/src/apps/httpd/fsdata.h | 50 + .../net/lwip-2.0.3/src/apps/httpd/httpd.c | 2629 ++++++++++ .../lwip-2.0.3/src/apps/httpd/httpd_structs.h | 114 + .../src/apps/httpd/makefsdata/makefsdata | 97 + .../src/apps/httpd/makefsdata/makefsdata.c | 1033 ++++ .../src/apps/httpd/makefsdata/readme.txt | 13 + .../net/lwip-2.0.3/src/apps/lwiperf/lwiperf.c | 661 +++ .../net/lwip-2.0.3/src/apps/mdns/mdns.c | 2028 ++++++++ .../net/lwip-2.0.3/src/apps/mqtt/mqtt.c | 1342 +++++ .../lwip-2.0.3/src/apps/netbiosns/netbiosns.c | 367 ++ .../net/lwip-2.0.3/src/apps/ping/ping.c | 245 + .../net/lwip-2.0.3/src/apps/snmp/snmp_asn1.c | 749 +++ .../net/lwip-2.0.3/src/apps/snmp/snmp_asn1.h | 108 + .../net/lwip-2.0.3/src/apps/snmp/snmp_core.c | 1349 ++++++ .../lwip-2.0.3/src/apps/snmp/snmp_core_priv.h | 76 + .../net/lwip-2.0.3/src/apps/snmp/snmp_mib2.c | 116 + .../lwip-2.0.3/src/apps/snmp/snmp_mib2_icmp.c | 182 + .../src/apps/snmp/snmp_mib2_interfaces.c | 375 ++ .../lwip-2.0.3/src/apps/snmp/snmp_mib2_ip.c | 743 +++ .../lwip-2.0.3/src/apps/snmp/snmp_mib2_snmp.c | 227 + .../src/apps/snmp/snmp_mib2_system.c | 377 ++ .../lwip-2.0.3/src/apps/snmp/snmp_mib2_tcp.c | 594 +++ .../lwip-2.0.3/src/apps/snmp/snmp_mib2_udp.c | 357 ++ .../net/lwip-2.0.3/src/apps/snmp/snmp_msg.c | 1668 +++++++ .../net/lwip-2.0.3/src/apps/snmp/snmp_msg.h | 194 + .../lwip-2.0.3/src/apps/snmp/snmp_netconn.c | 121 + .../src/apps/snmp/snmp_pbuf_stream.c | 156 + .../src/apps/snmp/snmp_pbuf_stream.h | 73 + .../net/lwip-2.0.3/src/apps/snmp/snmp_raw.c | 100 + .../lwip-2.0.3/src/apps/snmp/snmp_scalar.c | 220 + .../net/lwip-2.0.3/src/apps/snmp/snmp_table.c | 343 ++ .../src/apps/snmp/snmp_threadsync.c | 219 + .../net/lwip-2.0.3/src/apps/snmp/snmp_traps.c | 445 ++ .../net/lwip-2.0.3/src/apps/snmp/snmpv3.c | 136 + .../lwip-2.0.3/src/apps/snmp/snmpv3_dummy.c | 145 + .../lwip-2.0.3/src/apps/snmp/snmpv3_mbedtls.c | 331 ++ .../lwip-2.0.3/src/apps/snmp/snmpv3_priv.h | 66 + .../net/lwip-2.0.3/src/apps/sntp/sntp.c | 727 +++ .../net/lwip-2.0.3/src/apps/tftp/tftp_port.c | 73 + .../lwip-2.0.3/src/apps/tftp/tftp_server.c | 417 ++ .../src/arch/include/arch/bpstruct.h | 35 + .../net/lwip-2.0.3/src/arch/include/arch/cc.h | 105 + .../src/arch/include/arch/epstruct.h | 35 + .../lwip-2.0.3/src/arch/include/arch/perf.h | 52 + .../src/arch/include/arch/sys_arch.h | 62 + components/net/lwip-2.0.3/src/arch/sys_arch.c | 764 +++ components/net/lwip-2.0.3/src/core/def.c | 222 + components/net/lwip-2.0.3/src/core/dns.c | 1587 ++++++ .../net/lwip-2.0.3/src/core/inet_chksum.c | 609 +++ components/net/lwip-2.0.3/src/core/init.c | 385 ++ components/net/lwip-2.0.3/src/core/ip.c | 124 + .../net/lwip-2.0.3/src/core/ipv4/autoip.c | 527 ++ .../net/lwip-2.0.3/src/core/ipv4/dhcp.c | 1951 ++++++++ .../net/lwip-2.0.3/src/core/ipv4/etharp.c | 1206 +++++ .../net/lwip-2.0.3/src/core/ipv4/icmp.c | 397 ++ .../net/lwip-2.0.3/src/core/ipv4/igmp.c | 800 +++ components/net/lwip-2.0.3/src/core/ipv4/ip4.c | 1086 +++++ .../net/lwip-2.0.3/src/core/ipv4/ip4_addr.c | 331 ++ .../net/lwip-2.0.3/src/core/ipv4/ip4_frag.c | 864 ++++ .../net/lwip-2.0.3/src/core/ipv6/dhcp6.c | 50 + .../net/lwip-2.0.3/src/core/ipv6/ethip6.c | 118 + .../net/lwip-2.0.3/src/core/ipv6/icmp6.c | 350 ++ .../net/lwip-2.0.3/src/core/ipv6/inet6.c | 53 + components/net/lwip-2.0.3/src/core/ipv6/ip6.c | 1122 +++++ .../net/lwip-2.0.3/src/core/ipv6/ip6_addr.c | 292 ++ .../net/lwip-2.0.3/src/core/ipv6/ip6_frag.c | 805 +++ .../net/lwip-2.0.3/src/core/ipv6/mld6.c | 588 +++ components/net/lwip-2.0.3/src/core/ipv6/nd6.c | 2102 ++++++++ components/net/lwip-2.0.3/src/core/mem.c | 777 +++ components/net/lwip-2.0.3/src/core/memp.c | 496 ++ components/net/lwip-2.0.3/src/core/netif.c | 1318 +++++ components/net/lwip-2.0.3/src/core/pbuf.c | 1442 ++++++ components/net/lwip-2.0.3/src/core/raw.c | 521 ++ components/net/lwip-2.0.3/src/core/stats.c | 169 + components/net/lwip-2.0.3/src/core/sys.c | 106 + components/net/lwip-2.0.3/src/core/tcp.c | 2169 +++++++++ components/net/lwip-2.0.3/src/core/tcp_in.c | 1837 +++++++ components/net/lwip-2.0.3/src/core/tcp_out.c | 1671 +++++++ components/net/lwip-2.0.3/src/core/timeouts.c | 433 ++ components/net/lwip-2.0.3/src/core/udp.c | 1191 +++++ .../net/lwip-2.0.3/src/include/lwip/api.h | 400 ++ .../lwip-2.0.3/src/include/lwip/apps/FILES | 2 + .../net/lwip-2.0.3/src/include/lwip/apps/fs.h | 103 + .../lwip-2.0.3/src/include/lwip/apps/httpd.h | 236 + .../src/include/lwip/apps/httpd_opts.h | 323 ++ .../src/include/lwip/apps/lwiperf.h | 84 + .../lwip-2.0.3/src/include/lwip/apps/mdns.h | 69 + .../src/include/lwip/apps/mdns_opts.h | 74 + .../src/include/lwip/apps/mdns_priv.h | 66 + .../lwip-2.0.3/src/include/lwip/apps/mqtt.h | 244 + .../src/include/lwip/apps/mqtt_opts.h | 103 + .../src/include/lwip/apps/netbiosns.h | 43 + .../src/include/lwip/apps/netbiosns_opts.h | 59 + .../lwip-2.0.3/src/include/lwip/apps/snmp.h | 128 + .../src/include/lwip/apps/snmp_core.h | 364 ++ .../src/include/lwip/apps/snmp_mib2.h | 78 + .../src/include/lwip/apps/snmp_opts.h | 293 ++ .../src/include/lwip/apps/snmp_scalar.h | 113 + .../src/include/lwip/apps/snmp_table.h | 134 + .../src/include/lwip/apps/snmp_threadsync.h | 114 + .../lwip-2.0.3/src/include/lwip/apps/snmpv3.h | 90 + .../lwip-2.0.3/src/include/lwip/apps/sntp.h | 76 + .../src/include/lwip/apps/sntp_opts.h | 173 + .../src/include/lwip/apps/tftp_opts.h | 105 + .../src/include/lwip/apps/tftp_server.h | 94 + .../net/lwip-2.0.3/src/include/lwip/arch.h | 319 ++ .../net/lwip-2.0.3/src/include/lwip/autoip.h | 99 + .../net/lwip-2.0.3/src/include/lwip/debug.h | 167 + .../net/lwip-2.0.3/src/include/lwip/def.h | 141 + .../net/lwip-2.0.3/src/include/lwip/dhcp.h | 143 + .../net/lwip-2.0.3/src/include/lwip/dhcp6.h | 58 + .../net/lwip-2.0.3/src/include/lwip/dns.h | 130 + .../net/lwip-2.0.3/src/include/lwip/err.h | 119 + .../net/lwip-2.0.3/src/include/lwip/errno.h | 193 + .../net/lwip-2.0.3/src/include/lwip/etharp.h | 106 + .../net/lwip-2.0.3/src/include/lwip/ethip6.h | 68 + .../net/lwip-2.0.3/src/include/lwip/icmp.h | 110 + .../net/lwip-2.0.3/src/include/lwip/icmp6.h | 70 + .../net/lwip-2.0.3/src/include/lwip/igmp.h | 115 + .../net/lwip-2.0.3/src/include/lwip/inet.h | 172 + .../lwip-2.0.3/src/include/lwip/inet_chksum.h | 105 + .../net/lwip-2.0.3/src/include/lwip/init.h | 100 + .../net/lwip-2.0.3/src/include/lwip/ip.h | 319 ++ .../net/lwip-2.0.3/src/include/lwip/ip4.h | 111 + .../lwip-2.0.3/src/include/lwip/ip4_addr.h | 227 + .../lwip-2.0.3/src/include/lwip/ip4_frag.h | 100 + .../net/lwip-2.0.3/src/include/lwip/ip6.h | 93 + .../lwip-2.0.3/src/include/lwip/ip6_addr.h | 285 ++ .../lwip-2.0.3/src/include/lwip/ip6_frag.h | 120 + .../net/lwip-2.0.3/src/include/lwip/ip_addr.h | 407 ++ .../net/lwip-2.0.3/src/include/lwip/mem.h | 82 + .../net/lwip-2.0.3/src/include/lwip/memp.h | 155 + .../net/lwip-2.0.3/src/include/lwip/mld6.h | 99 + .../net/lwip-2.0.3/src/include/lwip/nd6.h | 84 + .../net/lwip-2.0.3/src/include/lwip/netbuf.h | 118 + .../net/lwip-2.0.3/src/include/lwip/netdb.h | 150 + .../net/lwip-2.0.3/src/include/lwip/netif.h | 474 ++ .../lwip-2.0.3/src/include/lwip/netifapi.h | 140 + .../net/lwip-2.0.3/src/include/lwip/opt.h | 2876 +++++++++++ .../net/lwip-2.0.3/src/include/lwip/pbuf.h | 263 + .../src/include/lwip/priv/api_msg.h | 216 + .../src/include/lwip/priv/memp_priv.h | 183 + .../src/include/lwip/priv/memp_std.h | 146 + .../src/include/lwip/priv/nd6_priv.h | 144 + .../src/include/lwip/priv/tcp_priv.h | 507 ++ .../src/include/lwip/priv/tcpip_priv.h | 160 + .../lwip-2.0.3/src/include/lwip/prot/autoip.h | 78 + .../lwip-2.0.3/src/include/lwip/prot/dhcp.h | 183 + .../lwip-2.0.3/src/include/lwip/prot/dns.h | 140 + .../lwip-2.0.3/src/include/lwip/prot/etharp.h | 91 + .../src/include/lwip/prot/ethernet.h | 172 + .../lwip-2.0.3/src/include/lwip/prot/icmp.h | 91 + .../lwip-2.0.3/src/include/lwip/prot/icmp6.h | 170 + .../lwip-2.0.3/src/include/lwip/prot/igmp.h | 90 + .../net/lwip-2.0.3/src/include/lwip/prot/ip.h | 51 + .../lwip-2.0.3/src/include/lwip/prot/ip4.h | 127 + .../lwip-2.0.3/src/include/lwip/prot/ip6.h | 169 + .../lwip-2.0.3/src/include/lwip/prot/mld6.h | 70 + .../lwip-2.0.3/src/include/lwip/prot/nd6.h | 277 ++ .../lwip-2.0.3/src/include/lwip/prot/tcp.h | 97 + .../lwip-2.0.3/src/include/lwip/prot/udp.h | 68 + .../net/lwip-2.0.3/src/include/lwip/raw.h | 118 + .../net/lwip-2.0.3/src/include/lwip/sio.h | 142 + .../net/lwip-2.0.3/src/include/lwip/snmp.h | 213 + .../net/lwip-2.0.3/src/include/lwip/sockets.h | 593 +++ .../net/lwip-2.0.3/src/include/lwip/stats.h | 491 ++ .../net/lwip-2.0.3/src/include/lwip/sys.h | 455 ++ .../net/lwip-2.0.3/src/include/lwip/tcp.h | 433 ++ .../net/lwip-2.0.3/src/include/lwip/tcpip.h | 106 + .../lwip-2.0.3/src/include/lwip/timeouts.h | 121 + .../net/lwip-2.0.3/src/include/lwip/udp.h | 182 + .../net/lwip-2.0.3/src/include/netif/etharp.h | 3 + .../lwip-2.0.3/src/include/netif/ethernet.h | 77 + .../lwip-2.0.3/src/include/netif/ethernetif.h | 53 + .../lwip-2.0.3/src/include/netif/lowpan6.h | 86 + .../src/include/netif/lowpan6_opts.h | 70 + .../lwip-2.0.3/src/include/netif/ppp/ccp.h | 156 + .../src/include/netif/ppp/chap-md5.h | 36 + .../src/include/netif/ppp/chap-new.h | 192 + .../src/include/netif/ppp/chap_ms.h | 44 + .../lwip-2.0.3/src/include/netif/ppp/eap.h | 169 + .../lwip-2.0.3/src/include/netif/ppp/ecp.h | 50 + .../lwip-2.0.3/src/include/netif/ppp/eui64.h | 94 + .../lwip-2.0.3/src/include/netif/ppp/fsm.h | 175 + .../lwip-2.0.3/src/include/netif/ppp/ipcp.h | 126 + .../lwip-2.0.3/src/include/netif/ppp/ipv6cp.h | 183 + .../lwip-2.0.3/src/include/netif/ppp/lcp.h | 171 + .../lwip-2.0.3/src/include/netif/ppp/magic.h | 122 + .../lwip-2.0.3/src/include/netif/ppp/mppe.h | 173 + .../src/include/netif/ppp/polarssl/arc4.h | 81 + .../src/include/netif/ppp/polarssl/des.h | 92 + .../src/include/netif/ppp/polarssl/md4.h | 97 + .../src/include/netif/ppp/polarssl/md5.h | 96 + .../src/include/netif/ppp/polarssl/sha1.h | 96 + .../lwip-2.0.3/src/include/netif/ppp/ppp.h | 690 +++ .../src/include/netif/ppp/ppp_impl.h | 629 +++ .../src/include/netif/ppp/ppp_opts.h | 593 +++ .../lwip-2.0.3/src/include/netif/ppp/pppapi.h | 137 + .../src/include/netif/ppp/pppcrypt.h | 136 + .../src/include/netif/ppp/pppdebug.h | 80 + .../lwip-2.0.3/src/include/netif/ppp/pppoe.h | 179 + .../src/include/netif/ppp/pppol2tp.h | 201 + .../lwip-2.0.3/src/include/netif/ppp/pppos.h | 118 + .../lwip-2.0.3/src/include/netif/ppp/upap.h | 123 + .../net/lwip-2.0.3/src/include/netif/ppp/vj.h | 161 + .../net/lwip-2.0.3/src/include/netif/slipif.h | 87 + .../net/lwip-2.0.3/src/include/posix/errno.h | 33 + .../net/lwip-2.0.3/src/include/posix/netdb.h | 33 + .../lwip-2.0.3/src/include/posix/sys/socket.h | 33 + components/net/lwip-2.0.3/src/lwipopts.h | 636 +++ components/net/lwip-2.0.3/src/lwippools.h | 10 + components/net/lwip-2.0.3/src/netif/FILES | 24 + .../net/lwip-2.0.3/src/netif/ethernet.c | 314 ++ .../net/lwip-2.0.3/src/netif/ethernetif.c | 1022 ++++ components/net/lwip-2.0.3/src/netif/lowpan6.c | 1193 +++++ .../lwip-2.0.3/src/netif/ppp/PPPD_FOLLOWUP | 473 ++ .../net/lwip-2.0.3/src/netif/ppp/auth.c | 2510 ++++++++++ components/net/lwip-2.0.3/src/netif/ppp/ccp.c | 1740 +++++++ .../net/lwip-2.0.3/src/netif/ppp/chap-md5.c | 126 + .../net/lwip-2.0.3/src/netif/ppp/chap-new.c | 677 +++ .../net/lwip-2.0.3/src/netif/ppp/chap_ms.c | 962 ++++ .../net/lwip-2.0.3/src/netif/ppp/demand.c | 465 ++ components/net/lwip-2.0.3/src/netif/ppp/eap.c | 2423 ++++++++++ components/net/lwip-2.0.3/src/netif/ppp/ecp.c | 191 + .../net/lwip-2.0.3/src/netif/ppp/eui64.c | 56 + components/net/lwip-2.0.3/src/netif/ppp/fsm.c | 799 +++ .../net/lwip-2.0.3/src/netif/ppp/ipcp.c | 2418 ++++++++++ .../net/lwip-2.0.3/src/netif/ppp/ipv6cp.c | 1533 ++++++ components/net/lwip-2.0.3/src/netif/ppp/lcp.c | 2790 +++++++++++ .../net/lwip-2.0.3/src/netif/ppp/magic.c | 294 ++ .../net/lwip-2.0.3/src/netif/ppp/mppe.c | 412 ++ .../net/lwip-2.0.3/src/netif/ppp/multilink.c | 609 +++ .../lwip-2.0.3/src/netif/ppp/polarssl/README | 22 + .../lwip-2.0.3/src/netif/ppp/polarssl/arc4.c | 101 + .../lwip-2.0.3/src/netif/ppp/polarssl/des.c | 422 ++ .../lwip-2.0.3/src/netif/ppp/polarssl/md4.c | 281 ++ .../lwip-2.0.3/src/netif/ppp/polarssl/md5.c | 300 ++ .../lwip-2.0.3/src/netif/ppp/polarssl/sha1.c | 335 ++ components/net/lwip-2.0.3/src/netif/ppp/ppp.c | 1647 +++++++ .../net/lwip-2.0.3/src/netif/ppp/pppapi.c | 427 ++ .../net/lwip-2.0.3/src/netif/ppp/pppcrypt.c | 66 + .../net/lwip-2.0.3/src/netif/ppp/pppoe.c | 1191 +++++ .../net/lwip-2.0.3/src/netif/ppp/pppol2tp.c | 1131 +++++ .../net/lwip-2.0.3/src/netif/ppp/pppos.c | 875 ++++ .../net/lwip-2.0.3/src/netif/ppp/upap.c | 677 +++ .../net/lwip-2.0.3/src/netif/ppp/utils.c | 959 ++++ components/net/lwip-2.0.3/src/netif/ppp/vj.c | 695 +++ components/net/lwip-2.0.3/src/netif/slipif.c | 555 +++ components/net/lwip-2.0.3/test/fuzz/Makefile | 53 + components/net/lwip-2.0.3/test/fuzz/README | 34 + components/net/lwip-2.0.3/test/fuzz/config.h | 0 components/net/lwip-2.0.3/test/fuzz/fuzz.c | 136 + .../net/lwip-2.0.3/test/fuzz/lwipopts.h | 68 + .../lwip-2.0.3/test/fuzz/output_to_pcap.sh | 31 + .../net/lwip-2.0.3/test/unit/core/test_mem.c | 121 + .../net/lwip-2.0.3/test/unit/core/test_mem.h | 8 + .../net/lwip-2.0.3/test/unit/core/test_pbuf.c | 239 + .../net/lwip-2.0.3/test/unit/core/test_pbuf.h | 8 + .../net/lwip-2.0.3/test/unit/dhcp/test_dhcp.c | 1024 ++++ .../net/lwip-2.0.3/test/unit/dhcp/test_dhcp.h | 8 + .../lwip-2.0.3/test/unit/etharp/test_etharp.c | 269 ++ .../lwip-2.0.3/test/unit/etharp/test_etharp.h | 8 + .../net/lwip-2.0.3/test/unit/ip4/test_ip4.c | 154 + .../net/lwip-2.0.3/test/unit/ip4/test_ip4.h | 8 + .../net/lwip-2.0.3/test/unit/lwip_check.h | 37 + .../net/lwip-2.0.3/test/unit/lwip_unittests.c | 72 + .../net/lwip-2.0.3/test/unit/lwipopts.h | 65 + .../net/lwip-2.0.3/test/unit/mdns/test_mdns.c | 915 ++++ .../net/lwip-2.0.3/test/unit/mdns/test_mdns.h | 8 + .../net/lwip-2.0.3/test/unit/tcp/tcp_helper.c | 314 ++ .../net/lwip-2.0.3/test/unit/tcp/tcp_helper.h | 52 + .../net/lwip-2.0.3/test/unit/tcp/test_tcp.c | 744 +++ .../net/lwip-2.0.3/test/unit/tcp/test_tcp.h | 8 + .../lwip-2.0.3/test/unit/tcp/test_tcp_oos.c | 1049 ++++ .../lwip-2.0.3/test/unit/tcp/test_tcp_oos.h | 8 + .../net/lwip-2.0.3/test/unit/udp/test_udp.c | 68 + .../net/lwip-2.0.3/test/unit/udp/test_udp.h | 8 + 316 files changed, 125981 insertions(+), 3 deletions(-) create mode 100644 components/net/lwip-2.0.3/CHANGELOG create mode 100644 components/net/lwip-2.0.3/COPYING create mode 100644 components/net/lwip-2.0.3/FILES create mode 100644 components/net/lwip-2.0.3/README create mode 100644 components/net/lwip-2.0.3/READTEST.md create mode 100644 components/net/lwip-2.0.3/SConscript create mode 100644 components/net/lwip-2.0.3/UPGRADING create mode 100644 components/net/lwip-2.0.3/doc/FILES create mode 100644 components/net/lwip-2.0.3/doc/NO_SYS_SampleCode.c create mode 100644 components/net/lwip-2.0.3/doc/contrib.txt create mode 100644 components/net/lwip-2.0.3/doc/doxygen/generate.bat create mode 100644 components/net/lwip-2.0.3/doc/doxygen/generate.sh create mode 100644 components/net/lwip-2.0.3/doc/doxygen/lwip.Doxyfile create mode 100644 components/net/lwip-2.0.3/doc/doxygen/main_page.h create mode 100644 components/net/lwip-2.0.3/doc/doxygen/output/index.html create mode 100644 components/net/lwip-2.0.3/doc/mdns.txt create mode 100644 components/net/lwip-2.0.3/doc/mqtt_client.txt create mode 100644 components/net/lwip-2.0.3/doc/ppp.txt create mode 100644 components/net/lwip-2.0.3/doc/rawapi.txt create mode 100644 components/net/lwip-2.0.3/doc/savannah.txt create mode 100644 components/net/lwip-2.0.3/doc/sys_arch.txt create mode 100644 components/net/lwip-2.0.3/src/FILES create mode 100644 components/net/lwip-2.0.3/src/Filelists.mk create mode 100644 components/net/lwip-2.0.3/src/api/api_lib.c create mode 100644 components/net/lwip-2.0.3/src/api/api_msg.c create mode 100644 components/net/lwip-2.0.3/src/api/err.c create mode 100644 components/net/lwip-2.0.3/src/api/netbuf.c create mode 100644 components/net/lwip-2.0.3/src/api/netdb.c create mode 100644 components/net/lwip-2.0.3/src/api/netifapi.c create mode 100644 components/net/lwip-2.0.3/src/api/sockets.c create mode 100644 components/net/lwip-2.0.3/src/api/tcpip.c create mode 100644 components/net/lwip-2.0.3/src/apps/README.md create mode 100644 components/net/lwip-2.0.3/src/apps/httpd/fs.c create mode 100644 components/net/lwip-2.0.3/src/apps/httpd/fs/404.html create mode 100644 components/net/lwip-2.0.3/src/apps/httpd/fs/img/sics.gif create mode 100644 components/net/lwip-2.0.3/src/apps/httpd/fs/index.html create mode 100644 components/net/lwip-2.0.3/src/apps/httpd/fsdata.c create mode 100644 components/net/lwip-2.0.3/src/apps/httpd/fsdata.h create mode 100644 components/net/lwip-2.0.3/src/apps/httpd/httpd.c create mode 100644 components/net/lwip-2.0.3/src/apps/httpd/httpd_structs.h create mode 100644 components/net/lwip-2.0.3/src/apps/httpd/makefsdata/makefsdata create mode 100644 components/net/lwip-2.0.3/src/apps/httpd/makefsdata/makefsdata.c create mode 100644 components/net/lwip-2.0.3/src/apps/httpd/makefsdata/readme.txt create mode 100644 components/net/lwip-2.0.3/src/apps/lwiperf/lwiperf.c create mode 100644 components/net/lwip-2.0.3/src/apps/mdns/mdns.c create mode 100644 components/net/lwip-2.0.3/src/apps/mqtt/mqtt.c create mode 100644 components/net/lwip-2.0.3/src/apps/netbiosns/netbiosns.c create mode 100644 components/net/lwip-2.0.3/src/apps/ping/ping.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_asn1.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_asn1.h create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_core.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_core_priv.h create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_icmp.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_interfaces.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_ip.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_snmp.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_system.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_tcp.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_udp.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_msg.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_msg.h create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_netconn.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_pbuf_stream.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_pbuf_stream.h create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_raw.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_scalar.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_table.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_threadsync.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmp_traps.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmpv3.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmpv3_dummy.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmpv3_mbedtls.c create mode 100644 components/net/lwip-2.0.3/src/apps/snmp/snmpv3_priv.h create mode 100644 components/net/lwip-2.0.3/src/apps/sntp/sntp.c create mode 100644 components/net/lwip-2.0.3/src/apps/tftp/tftp_port.c create mode 100644 components/net/lwip-2.0.3/src/apps/tftp/tftp_server.c create mode 100644 components/net/lwip-2.0.3/src/arch/include/arch/bpstruct.h create mode 100644 components/net/lwip-2.0.3/src/arch/include/arch/cc.h create mode 100644 components/net/lwip-2.0.3/src/arch/include/arch/epstruct.h create mode 100644 components/net/lwip-2.0.3/src/arch/include/arch/perf.h create mode 100644 components/net/lwip-2.0.3/src/arch/include/arch/sys_arch.h create mode 100644 components/net/lwip-2.0.3/src/arch/sys_arch.c create mode 100644 components/net/lwip-2.0.3/src/core/def.c create mode 100644 components/net/lwip-2.0.3/src/core/dns.c create mode 100644 components/net/lwip-2.0.3/src/core/inet_chksum.c create mode 100644 components/net/lwip-2.0.3/src/core/init.c create mode 100644 components/net/lwip-2.0.3/src/core/ip.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv4/autoip.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv4/dhcp.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv4/etharp.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv4/icmp.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv4/igmp.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv4/ip4.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv4/ip4_addr.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv4/ip4_frag.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv6/dhcp6.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv6/ethip6.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv6/icmp6.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv6/inet6.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv6/ip6.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv6/ip6_addr.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv6/ip6_frag.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv6/mld6.c create mode 100644 components/net/lwip-2.0.3/src/core/ipv6/nd6.c create mode 100644 components/net/lwip-2.0.3/src/core/mem.c create mode 100644 components/net/lwip-2.0.3/src/core/memp.c create mode 100644 components/net/lwip-2.0.3/src/core/netif.c create mode 100644 components/net/lwip-2.0.3/src/core/pbuf.c create mode 100644 components/net/lwip-2.0.3/src/core/raw.c create mode 100644 components/net/lwip-2.0.3/src/core/stats.c create mode 100644 components/net/lwip-2.0.3/src/core/sys.c create mode 100644 components/net/lwip-2.0.3/src/core/tcp.c create mode 100644 components/net/lwip-2.0.3/src/core/tcp_in.c create mode 100644 components/net/lwip-2.0.3/src/core/tcp_out.c create mode 100644 components/net/lwip-2.0.3/src/core/timeouts.c create mode 100644 components/net/lwip-2.0.3/src/core/udp.c create mode 100644 components/net/lwip-2.0.3/src/include/lwip/api.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/FILES create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/fs.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/httpd.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/httpd_opts.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/lwiperf.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/mdns.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/mdns_opts.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/mdns_priv.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/mqtt.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/mqtt_opts.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/netbiosns.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/netbiosns_opts.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/snmp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/snmp_core.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/snmp_mib2.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/snmp_opts.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/snmp_scalar.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/snmp_table.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/snmp_threadsync.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/snmpv3.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/sntp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/sntp_opts.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/tftp_opts.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/apps/tftp_server.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/arch.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/autoip.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/debug.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/def.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/dhcp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/dhcp6.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/dns.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/err.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/errno.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/etharp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/ethip6.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/icmp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/icmp6.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/igmp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/inet.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/inet_chksum.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/init.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/ip.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/ip4.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/ip4_addr.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/ip4_frag.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/ip6.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/ip6_addr.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/ip6_frag.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/ip_addr.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/mem.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/memp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/mld6.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/nd6.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/netbuf.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/netdb.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/netif.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/netifapi.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/opt.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/pbuf.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/priv/api_msg.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/priv/memp_priv.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/priv/memp_std.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/priv/nd6_priv.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/priv/tcp_priv.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/priv/tcpip_priv.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/autoip.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/dhcp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/dns.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/etharp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/ethernet.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/icmp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/icmp6.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/igmp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/ip.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/ip4.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/ip6.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/mld6.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/nd6.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/tcp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/prot/udp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/raw.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/sio.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/snmp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/sockets.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/stats.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/sys.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/tcp.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/tcpip.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/timeouts.h create mode 100644 components/net/lwip-2.0.3/src/include/lwip/udp.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/etharp.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ethernet.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ethernetif.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/lowpan6.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/lowpan6_opts.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/ccp.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/chap-md5.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/chap-new.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/chap_ms.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/eap.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/ecp.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/eui64.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/fsm.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/ipcp.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/ipv6cp.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/lcp.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/magic.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/mppe.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/arc4.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/des.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/md4.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/md5.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/sha1.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/ppp.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/ppp_impl.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/ppp_opts.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/pppapi.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/pppcrypt.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/pppdebug.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/pppoe.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/pppol2tp.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/pppos.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/upap.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/ppp/vj.h create mode 100644 components/net/lwip-2.0.3/src/include/netif/slipif.h create mode 100644 components/net/lwip-2.0.3/src/include/posix/errno.h create mode 100644 components/net/lwip-2.0.3/src/include/posix/netdb.h create mode 100644 components/net/lwip-2.0.3/src/include/posix/sys/socket.h create mode 100644 components/net/lwip-2.0.3/src/lwipopts.h create mode 100644 components/net/lwip-2.0.3/src/lwippools.h create mode 100644 components/net/lwip-2.0.3/src/netif/FILES create mode 100644 components/net/lwip-2.0.3/src/netif/ethernet.c create mode 100644 components/net/lwip-2.0.3/src/netif/ethernetif.c create mode 100644 components/net/lwip-2.0.3/src/netif/lowpan6.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/PPPD_FOLLOWUP create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/auth.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/ccp.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/chap-md5.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/chap-new.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/chap_ms.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/demand.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/eap.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/ecp.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/eui64.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/fsm.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/ipcp.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/ipv6cp.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/lcp.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/magic.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/mppe.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/multilink.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/polarssl/README create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/polarssl/arc4.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/polarssl/des.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/polarssl/md4.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/polarssl/md5.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/polarssl/sha1.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/ppp.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/pppapi.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/pppcrypt.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/pppoe.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/pppol2tp.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/pppos.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/upap.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/utils.c create mode 100644 components/net/lwip-2.0.3/src/netif/ppp/vj.c create mode 100644 components/net/lwip-2.0.3/src/netif/slipif.c create mode 100644 components/net/lwip-2.0.3/test/fuzz/Makefile create mode 100644 components/net/lwip-2.0.3/test/fuzz/README create mode 100644 components/net/lwip-2.0.3/test/fuzz/config.h create mode 100644 components/net/lwip-2.0.3/test/fuzz/fuzz.c create mode 100644 components/net/lwip-2.0.3/test/fuzz/lwipopts.h create mode 100644 components/net/lwip-2.0.3/test/fuzz/output_to_pcap.sh create mode 100644 components/net/lwip-2.0.3/test/unit/core/test_mem.c create mode 100644 components/net/lwip-2.0.3/test/unit/core/test_mem.h create mode 100644 components/net/lwip-2.0.3/test/unit/core/test_pbuf.c create mode 100644 components/net/lwip-2.0.3/test/unit/core/test_pbuf.h create mode 100644 components/net/lwip-2.0.3/test/unit/dhcp/test_dhcp.c create mode 100644 components/net/lwip-2.0.3/test/unit/dhcp/test_dhcp.h create mode 100644 components/net/lwip-2.0.3/test/unit/etharp/test_etharp.c create mode 100644 components/net/lwip-2.0.3/test/unit/etharp/test_etharp.h create mode 100644 components/net/lwip-2.0.3/test/unit/ip4/test_ip4.c create mode 100644 components/net/lwip-2.0.3/test/unit/ip4/test_ip4.h create mode 100644 components/net/lwip-2.0.3/test/unit/lwip_check.h create mode 100644 components/net/lwip-2.0.3/test/unit/lwip_unittests.c create mode 100644 components/net/lwip-2.0.3/test/unit/lwipopts.h create mode 100644 components/net/lwip-2.0.3/test/unit/mdns/test_mdns.c create mode 100644 components/net/lwip-2.0.3/test/unit/mdns/test_mdns.h create mode 100644 components/net/lwip-2.0.3/test/unit/tcp/tcp_helper.c create mode 100644 components/net/lwip-2.0.3/test/unit/tcp/tcp_helper.h create mode 100644 components/net/lwip-2.0.3/test/unit/tcp/test_tcp.c create mode 100644 components/net/lwip-2.0.3/test/unit/tcp/test_tcp.h create mode 100644 components/net/lwip-2.0.3/test/unit/tcp/test_tcp_oos.c create mode 100644 components/net/lwip-2.0.3/test/unit/tcp/test_tcp_oos.h create mode 100644 components/net/lwip-2.0.3/test/unit/udp/test_udp.c create mode 100644 components/net/lwip-2.0.3/test/unit/udp/test_udp.h diff --git a/components/net/Kconfig b/components/net/Kconfig index ad1db0c0fc..467002ac2e 100644 --- a/components/net/Kconfig +++ b/components/net/Kconfig @@ -124,12 +124,15 @@ config RT_USING_LWIP config RT_USING_LWIP202 bool "lwIP v2.0.2" - config RT_USING_LWIP212 + config RT_USING_LWIP203 + bool "lwIP v2.0.3" + + config RT_USING_LWIP212 bool "lwIP v2.1.2" endchoice - if (RT_USING_LWIP202 || RT_USING_LWIP212) + if (RT_USING_LWIP202 || RT_USING_LWIP212 || RT_USING_LWIP203) config RT_USING_LWIP_IPV6 bool "IPV6 protocol" default n diff --git a/components/net/SConscript b/components/net/SConscript index 2012e6fbfe..e3b6fef89f 100644 --- a/components/net/SConscript +++ b/components/net/SConscript @@ -8,7 +8,7 @@ cwd = GetCurrentDir() list = os.listdir(cwd) # the default version of LWIP is 2.0.2 -if not GetDepend('RT_USING_LWIP141') and not GetDepend('RT_USING_LWIP202') and not GetDepend('RT_USING_LWIP212'): +if not GetDepend('RT_USING_LWIP141') and not GetDepend('RT_USING_LWIP202') and not GetDepend('RT_USING_LWIP203') and not GetDepend('RT_USING_LWIP212'): AddDepend('RT_USING_LWIP202') for d in list: diff --git a/components/net/lwip-2.0.3/CHANGELOG b/components/net/lwip-2.0.3/CHANGELOG new file mode 100644 index 0000000000..306217fe5a --- /dev/null +++ b/components/net/lwip-2.0.3/CHANGELOG @@ -0,0 +1,4295 @@ +HISTORY + +(git master) + + * [Enter new changes just after this line - do not remove this line] + +(STABLE-2.0.3) + + ++ Bugfixes: + + 2017-09-11: Simon Goldschmidt + * tcp_in.c: fix bug #51937 (leaking tcp_pcbs on passive close with unacked data) + + 2017-08-02: Abroz Bizjak/Simon Goldschmidt + * multiple fixes in IPv4 reassembly (leading to corrupted datagrams received) + + 2017-03-30: Simon Goldschmidt + * dhcp.c: return ERR_VAL instead of asserting on offset-out-of-pbuf + + 2017-03-23: Dirk Ziegelmeier + * dhcp.h: fix bug #50618 (dhcp_remove_struct() macro does not work) + +(STABLE-2.0.2) + + ++ New features: + + 2017-02-10: Dirk Ziegelmeier + * Implement task #14367: Hooks need a better place to be defined: + We now have a #define for a header file name that is #included in every .c + file that provides hooks. + + 2017-02-10: Simon Goldschmidt + * tcp_close does not fail on memory error (instead, FIN is sent from tcp_tmr) + + ++ Bugfixes: + + 2017-03-08 + * tcp: do not keep sending SYNs when getting ACKs + + 2017-03-08: Joel Cunningham + * tcp: Initialize ssthresh to TCP_SND_BUF (bug #50476) + + 2017-03-01: Simon Goldschmidt + * httpd: LWIP_HTTPD_POST_MANUAL_WND: fixed double-free when httpd_post_data_recved + is called nested from httpd_post_receive_data() (bug #50424) + + 2017-02-28: David van Moolenbroek/Simon Goldschmidt + * tcp: fixed bug #50418: LWIP_EVENT_API: fix invalid calbacks for SYN_RCVD pcb + + 2017-02-17: Simon Goldschmidt + * dns: Improved DNS_LOCAL_HOSTLIST interface (bug #50325) + + 2017-02-16: Simon Goldschmidt + * LWIP_NETCONN_FULLDUPLEX: fixed shutdown during write (bug #50274) + + 2017-02-13: Simon Goldschmidt/Dirk Ziegelmeier + * For tiny targtes, LWIP_RAND is optional (fix compile time checks) + + 2017-02-10: Simon Goldschmidt + * tcp: Fixed bug #47485 (tcp_close() should not fail on memory error) by retrying + to send FIN from tcp_fasttmr + + 2017-02-09: Simon Goldschmidt + * sockets: Fixed bug #44032 (LWIP_NETCONN_FULLDUPLEX: select might work on + invalid/reused socket) by not allowing to reallocate a socket that has + "select_waiting != 0" + + 2017-02-09: Simon Goldschmidt + * httpd: Fixed bug #50059 (httpd LWIP_HTTPD_SUPPORT_11_KEEPALIVE vs. + LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED) + + 2017-02-08: Dirk Ziegelmeier + * Rename "IPv6 mapped IPv4 addresses" to their correct name from RFC4191: + "IPv4-mapped IPv6 address" + + 2017-02-08: Luc Revardel + * mld6.c: Fix bug #50220 (mld6_leavegroup does not send ICMP6_TYPE_MLD, even + if last reporter) + + 2017-02-08: David van Moolenbroek + * ip6.c: Patch #9250: fix source substitution in ip6_output_if() + + 2017-02-08: Simon Goldschmidt + * tcp_out.c: Fixed bug #50090 (last_unsent->oversize_left can become wrong value + in tcp_write error path) + + 2017-02-02: Dirk Ziegelmeier + * Fix bug #50206: UDP Netconn bind to IP6_ADDR_ANY fails + + 2017-01-18: Dirk Ziegelmeier + * Fix zero-copy RX, see bug bug #50064. PBUF_REFs were not supported as ARP requests. + + 2017-01-15: Axel Lin, Dirk Ziegelmeier + * minor bug fixes in mqtt + + 2017-01-11: Knut Andre Tidemann + * sockets/netconn: fix broken default ICMPv6 handling of checksums + +(STABLE-2.0.1) + + ++ New features: + + 2016-12-31: Simon Goldschmidt + * tcp.h/.c: added function tcp_listen_with_backlog_and_err() to get the error + reason when listening fails (bug #49861) + + 2016-12-20: Erik Andersen + * Add MQTT client + + 2016-12-14: Jan Breuer: + * opt.h, ndc.h/.c: add support for RDNSS option (as per RFC 6106) + + 2016-12-14: David van Moolenbroek + * opt.h, nd6.c: Added LWIP_HOOK_ND6_GET_GW() + + 2016-12-09: Dirk Ziegelmeier + * ip6_frag.c: Implemented support for LWIP_NETIF_TX_SINGLE_PBUF + + 2016-12-09: Simon Goldschmidt + * dns.c: added one-shot multicast DNS queries + + 2016-11-24: Ambroz Bizjak, David van Moolenbroek + * tcp_out.c: Optimize passing contiguous nocopy buffers to tcp_write (bug #46290) + + 2016-11-16: Dirk Ziegelmeier + * sockets.c: added support for IPv6 mapped IPv4 addresses + + ++ Bugfixes: + + 2016-12-16: Thomas Mueller + * api_lib.c: fixed race condition in return value of netconn_gethostbyname() + (and thus also lwip_gethostbyname/_r() and lwip_getaddrinfo()) + + 2016-12-15: David van Moolenbroek + * opt.h, tcp: added LWIP_HOOK_TCP_ISN() to implement less predictable initial + sequence numbers (see contrib/addons/tcp_isn for an example implementation) + + 2016-12-05: Dirk Ziegelmeier + * fixed compiling with IPv4 disabled (IPv6 only case) + + 2016-11-28: Simon Goldschmidt + * api_lib.c: fixed bug #49725 (send-timeout: netconn_write() can return + ERR_OK without all bytes being written) + + 2016-11-28: Ambroz Bizjak + * tcpi_in.c: fixed bug #49717 (window size in received SYN and SYN-ACK + assumed scaled) + + 2016-11-25: Simon Goldschmidt + * dhcp.c: fixed bug #49676 (Possible endless loop when parsing dhcp options) + + 2016-11-23: Dirk Ziegelmeier + * udp.c: fixed bug #49662: multicast traffic is now only received on a UDP PCB + (and therefore on a UDP socket/netconn) when the PCB is bound to IP_ADDR_ANY + + 2016-11-16: Dirk Ziegelmeier + * *: Fixed dual-stack behaviour, IPv6 mapped IPv4 support in socket API + + 2016-11-14: Joel Cunningham + * tcp_out.c: fixed bug #49533 (start persist timer when unsent seg can't fit + in window) + + 2016-11-16: Roberto Barbieri Carrera + * autoip.c: fixed bug #49610 (sometimes AutoIP fails to reuse the same address) + + 2016-11-11: Dirk Ziegelmeier + * sockets.c: fixed bug #49578 (dropping multicast membership does not work + with LWIP_SOCKET_OFFSET) + +(STABLE-2.0.0) + + ++ New features: + + 2016-07-27: Simon Goldschmidt + * opt.h, timeouts.h/.c: added LWIP_TIMERS_CUSTOM to override the default + implementation of timeouts + + 2016-07-xx: Dirk Ziegelmeier + * Large overhaul of doxygen documentation + + 2016-04-05: Simon Goldschmidt + * timers.h/.c: prepare for overriding current timeout implementation: all + stack-internal caclic timers are avaliable in the lwip_cyclic_timers array + + 2016-03-23: Simon Goldschmidt + * tcp: call accept-callback with ERR_MEM when allocating a pcb fails on + passive open to inform the application about this error + ATTENTION: applications have to handle NULL pcb in accept callback! + + 2016-02-22: Ivan Delamer + * Initial 6LoWPAN support + + 2016-02-XX to 2016-03-XX: Dirk Ziegelmeier + * Cleanup TCPIP thread sync methods in a way that it is possibe to use them + in arbitrary code that needs things to be done in TCPIP thread. Used to + decouple netconn, netif, ppp and 6LoWPAN from LWIP core. + + 2016-02-XX: Dirk Ziegelmeier + * Implement dual-stack support in RAW, UDP and TCP. Add new IP address + type IPADDR_ANY_TYPE for this. Netconn/Socket API: Dual-stack is + automatically supported when an IPv6 netconn/socket is created. + + 2015-12-26: Martin Hentschel and Dirk Ziegelmeier + * Rewrite SNMP agent. SNMPv2c + MIB compiler. + + 2015-11-12: Dirk Ziegelmeier + * Decouple SNMP stack from lwIP core and move stack to apps/ directory. + Breaking change: Users have to call snmp_init() now! + + 2015-11-12: Dirk Ziegelmeier + * Implement possibility to declare private memory pools. This is useful to + decouple some apps from the core (SNMP stack) or make contrib app usage + simpler (httpserver_raw) + + 2015-10-09: Simon Goldschmidt + * started to move "private" header files containing implementation details to + "lwip/priv/" include directory to seperate the API from the implementation. + + 2015-10-07: Simon Goldschmidt + * added sntp client as first "supported" application layer protocol implementation + added 'apps' folder + + 2015-09-30: Dirk Ziegelmeier + * snmp_structs.h, mib_structs.c, mib2.c: snmp: fixed ugly inheritance + implementation by aggregating the "base class" (struct mib_node) in all + derived node classes to get more type-safe code + + 2015-09-23: Simon Goldschmidt + * netif.h/.c, nd6.c: task #13729: Convert netif addresses (IPv4 & IPv6) to + ip_addr_t (so they can be used without conversion/temporary storage) + + 2015-09-08: Dirk Ziegelmeier + * snmp: Separate mib2 counter/table callbacks from snmp agent. This both cleans + up the code and should allow integration of a 3rd party agent/mib2. Simple + counters are kept in MIB2_STATS, tree/table change function prototypes moved to + snmp_mib2.h. + + 2015-09-03: Simon Goldschmidt + * opt.h, dns.h/.c: DNS/IPv6: added support for AAAA records + + 2015-09-01: Simon Goldschmidt + * task #12178: hardware checksum capabilities can be configured per netif + (use NETIF_SET_CHECKSUM_CTRL() in your netif's init function) + + 2015-08-30: Simon Goldschmidt + * PBUF_REF with "custom" pbufs is now supported for RX pbufs (see pcapif in + contrib for an example, LWIP_SUPPORT_CUSTOM_PBUF is required) + + 2015-08-30: Simon Goldschmidt + * support IPv4 source based routing: define LWIP_HOOK_IP4_ROUTE_SRC to point + to a routing function + + 2015-08-05: Simon Goldschmidt + * many files: allow multicast socket options IP_MULTICAST_TTL, IP_MULTICAST_IF + and IP_MULTICAST_LOOP to be used without IGMP + + 2015-04-24: Simon Goldschmidt + * dhcp.h/c, autoip.h/.c: added functions dhcp/autoip_supplied_address() to + check for the source of address assignment (replacement for NETIF_FLAG_DHCP) + + 2015-04-10: Simon Goldschmidt + * many files: task #13480: added LWIP_IPV4 define - IPv4 can be disabled, + leaving an IPv6-only stack + + 2015-04-09: Simon Goldschmidt + * nearly all files: task #12722 (improve IPv4/v6 address handling): renamed + ip_addr_t to ip4_addr_t, renamed ipX_addr_t to ip_addr_t and added IP + version; ip_addr_t is used for all generic IP addresses for the API, + ip(4/6)_addr_t are only used internally or when initializing netifs or when + calling version-related functions + + 2015-03-24: Simon Goldschmidt + * opt.h, ip4_addr.h, ip4.c, ip6.c: loopif is not required for loopback traffic + any more but passed through any netif (ENABLE_LOOPBACK has to be enabled) + + 2015-03-23: Simon Goldschmidt + * opt.h, etharp.c: with ETHARP_TABLE_MATCH_NETIF== 1, duplicate (Auto)-IP + addresses on multiple netifs should now be working correctly (if correctly + addressed by routing, that is) + + 2015-03-23: Simon Goldschmidt + * etharp.c: Stable etharp entries that are about to expire are now refreshed + using unicast to prevent unnecessary broadcast. Only if no answer is received + after 15 seconds, broadcast is used. + + 2015-03-06: Philip Gladstone + * netif.h/.c: patch #8359 (Provide utility function to add an IPv6 address to + an interface) + + 2015-03-05: Simon Goldschmidt + * netif.c, ip4.c, dhcp.c, autoip.c: fixed bug #37068 (netif up/down handling + is unclear): correclty separated administrative status of a netif (up/down) + from 'valid address' status + ATTENTION: netif_set_up() now always has to be called, even when dhcp/autoip + is used! + + 2015-02-26: patch by TabascoEye + * netif.c, udp.h/.c: fixed bug #40753 (re-bind UDP pcbs on change of IP address) + + 2015-02-22: chrysn, Simon Goldschmidt + * *.*: Changed nearly all functions taking 'ip(X)_addr_t' pointer to take + const pointers (changed user callbacks: raw_recv_fn, udp_recv_fn; changed + port callbacks: netif_output_fn, netif_igmp_mac_filter_fn) + + 2015-02-19: Ivan Delamer + * netif.h, dhcp.c: Removed unused netif flag for DHCP. The preferred way to evaluate + if DHCP is active is through netif->dhcp field. + + 2015-02-19: Ivan Delamer + * netif.h, slipif.c, ppp.c: Removed unused netif flag for point to point connections + + 2015-02-18: Simon Goldschmidt + * api_lib.c: fixed bug #37958 "netconn API doesn't handle correctly + connections half-closed by peer" + + 2015-02-18: Simon Goldschmidt + * tcp.c: tcp_alloc() prefers killing CLOSING/LAST_ACK over active connections + (see bug #39565) + + 2015-02-16: Claudius Zingerli, Sergio Caprile + * opt.h, dhcp.h/.c: patch #8361 "Add support for NTP option in DHCP" + + 2015-02-14: Simon Goldschmidt + * opt.h, snmp*: added support for write-access community and dedicated + community for sending traps + + 2015-02-13: Simon Goldschmidt + * opt.h, memp.c: added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when + a memp pool was empty and an item is now available + + 2015-02-13: Simon Goldschmidt + * opt.h, pbuf.h/.c, etharp.c: Added the option PBUF_LINK_ENCAPSULATION_HLEN to + allocate additional header space for TX on netifs requiring additional headers + + 2015-02-12: chrysn + * timers.h/.c: introduce sys_timeouts_sleeptime (returns the time left before + the next timeout is due, for NO_SYS==1) + + 2015-02-11: Nick van Ijzendoorn + * opt.h, sockets.h/c: patch #7702 "Include ability to increase the socket number + with defined offset" + + 2015-02-11: Frederick Baksik + * opt.h, def.h, others: patch #8423 "arch/perf.h" should be made an optional item + + 2015-02-11: Simon Goldschmidt + * api_msg.c, opt.h: started to implement fullduplex sockets/netconns + (note that this is highly unstable yet!) + + 2015-01-17: Simon Goldschmidt + * api: allow enabling socket API without (public) netconn API - netconn API is + still used by sockets, but keeping it private (static) should allow better + compiler optimizations + + 2015-01-16: Simon Goldschmidt + * tcp_in.c: fixed bug #20506 "Initial congestion window is very small" again + by implementing the calculation formula from RFC3390 + + 2014-12-10: Simon Goldschmidt + * api: added option LWIP_NETCONN_SEM_PER_THREAD to use a semaphore per thread + instead of using one per netconn and per select call + + 2014-12-08: Simon Goldschmidt + * ip6.h: fixed bug #43778: IPv6 header version not set on 16-bit platform + (macro IP6H_VTCFL_SET()) + + 2014-12-08: Simon Goldschmidt + * icmp.c, ip4.c, pbuf.c, udp.c, pbuf.h: task #11472 Support PBUF_REF for RX + (IPv6 and IPv4/v6 reassembly might not work yet) + + 2014-11-06: Simon Goldschmidt + * sockets.c/.h, init.c: lwip_socket_init() is not needed any more + -> compatibility define + + 2014-09-16: Simon Goldschmidt + * dns.c, opt.h: reduced ram usage by parsing DNS responses in place + + 2014-09-16: Simon Goldschmidt + * pbuf.h/.c: added pbuf_take_at() and pbuf_put_at() + + 2014-09-15: Simon Goldschmidt + * dns.c: added source port randomization to make the DNS client more robust + (see bug #43144) + + 2013-09-02: Simon Goldschmidt + * arch.h and many other files: added optional macros PACK_STRUCT_FLD_8() and + PACK_STRUCT_FLD_S() to prevent gcc 4 from warning about struct members that + do not need packing + + 2013-08-19: Simon Goldschmidt + * netif.h: bug #42998: made NETIF_MAX_HWADDR_LEN overridable for some special + networks + + 2013-03-17: Simon Goldschmidt (patch by Ghobad Emadi) + * opt.h, etharp.c: Added LWIP_HOOK_ETHARP_GET_GW to implement IPv4 routing with + multiple gateways + + 2013-04-20: Fatih Asici + * opt.h, etharp.h/.c: patch #7993: Added support for transmitting packets + with VLAN headers via hook function LWIP_HOOK_VLAN_SET and to check them + via hook function LWIP_HOOK_VLAN_CHECK + + 2014-02-20: Simon Goldschmidt (based on patch by Artem Pisarenko) + * patch #7885: modification of api modules to support FreeRTOS-MPU + (don't pass stack-pointers to other threads) + + 2014-02-05: Simon Goldschmidt (patch by "xtian" and "alex_ab") + * patch #6537/#7858: TCP window scaling support + + 2014-01-17: Jiri Engelthaler + * icmp, icmp6, opt.h: patch #8027: Completed HW checksuming for IPv4 and + IPv6 ICMP's + + 2012-08-22: Sylvain Rochet + * New PPP stack for lwIP, developed in ppp-new branch. + Based from pppd 2.4.5, released 2009-11-17, with huge changes to match + code size and memory requirements for embedded devices, including: + - Gluing together the previous low-level PPP code in lwIP to pppd 2.4.5, which + is more or less what pppd sys-* files are, so that we get something working + using the unix port. + - Merged some patchs from lwIP Git repository which add interesting features + or fix bugs. + - Merged some patchs from Debian pppd package which add interesting features + or fix bugs. + - Ported PPP timeout handling to the lwIP timers system + - Disabled all the PPP code using filesystem access, replaced in necessary cases + to configuration variables. + - Disabled all the PPP code forking processes. + - Removed IPX support, lwIP does not support IPX. + - Ported and improved random module from the previous PPP port. + - Removed samba TDB (file-driven database) usage, because it needs a filesystem. + - MS-CHAP required a DES implementation, we added the latest PolarSSL DES + implementation which is under a BSD-ish license. + - Also switched to PolarSSL MD4,MD5,SHA1 implementations, which are meant to be + used in embedded devices with reduced memory footprint. + - Removed PPP configuration file parsing support. + - Added macro definition EAP_SUPPORT to make EAP support optional. + - Added macro definition CHAP_SUPPORT to make CHAP support optional. + - Added macro definition MSCHAP_SUPPORT to make MSCHAP support optional. + - Added macro definition PAP_SUPPORT to make PAP support optional. + - Cleared all Linux syscall calls. + - Disabled demand support using a macro, so that it can be ported later. + - Disabled ECP support using a macro, so that it can be ported later. + - Disabled CCP support using a macro, so that it can be ported later. + - Disabled CBCP support using a macro, so that it can be ported later. + - Disabled LQR support using a macro, so that it can be ported later. + - Print packet debug feature optional, through PRINTPKT_SUPPORT + - Removed POSIX signal usage. + - Fully ported PPPoS code from the previous port. + - Fully ported PPPoE code from the previous port. + - Fully ported VJ compression protocol code from the previous port. + - Removed all malloc()/free() use from PPP, replaced by stack usage or PBUF. + - Disabled PPP server support using a macro, so that it can be ported later. + - Switched all PPP debug to lwIP debug system. + - Created PPP Control Block (PPP PCB), removed PPP unit integer everywhere, + removed all global variables everywhere, did everything necessary for + the PPP stack to support more than one PPP session (pppd only support + one session per process). + - Removed the statically allocated output buffer, now using PBUF. + - Improved structure size of all PPP modules, deep analyze of code to reduce + variables size to the bare minimum. Switched all boolean type (char type in + most architecture) to compiler generated bitfields. + - Added PPP IPv6 support, glued lwIP IPv6 support to PPP. + - Now using a persistent netif interface which can then be used in lwIP + functions requiring a netif. + - Now initializing PPP in lwip_init() function. + - Reworked completely the PPP state machine, so that we don't end up in + anymore in inconsistent state, especially with PPPoE. + - Improved the way we handle PPP reconnection after disconnect, cleaning + everything required so that we start the PPP connection again from a + clean state. + - Added PPP holdoff support, allow the lwIP user to wait a little bit before + reconnecting, prevents connection flood, especially when using PPPoL2TP. + - Added PPPoL2TP LAC support (a.k.a. UDP tunnels), adding a VPN client + feature to lwIP, L2TP being a widely used tunnel protocol. + - Switched all used PPP types to lwIP types (u8t, u16t, u32t, ...) + - Added PPP API "sequential" thread-safe API, based from NETIFAPI. + + 2011-07-21: Simon Goldschmidt + * sockets.c, opt.h: (bug #30185): added LWIP_FIONREAD_LINUXMODE that makes + ioctl/FIONREAD return the size of the next pending datagram. + + 2011-05-25: Simon Goldschmidt + * again nearly the whole stack, renamed ip.c to ip4.c, ip_addr.c to ip4_addr.c, + combined ipv4/ipv6 inet_chksum.c, added ip.h, ip_addr.h: Combined IPv4 + and IPv6 code where possible, added defines to access IPv4/IPv6 in non-IP + code so that the code is more readable. + + 2011-05-17: Patch by Ivan Delamer (only checked in by Simon Goldschmidt) + * nearly the whole stack: Finally, we got decent IPv6 support, big thanks to + Ivan! (this is work in progress: we're just post release anyway :-) + + + ++ Bugfixes: + + 2016-08-23: Simon Goldschmidt + * etharp: removed ETHARP_TRUST_IP_MAC since it is insecure and we don't need + it any more after implementing unicast ARP renewal towards arp entry timeout + + 2016-07-20: Simon Goldschmidt + * memp.h/.c: fixed bug #48442 (memp stats don't work for MEMP_MEM_MALLOC) + + 2016-07-21: Simon Goldschmidt (patch by Ambroz Bizjak) + * tcp_in.c, tcp_out.c: fixed bug #48543 (TCP sent callback may prematurely + report sent data when only part of a segment is acked) and don't include + SYN/FIN in snd_buf counter + + 2016-07-19: Simon Goldschmidt + * etharp.c: fixed bug #48477 (ARP input packet might update static entry) + + 2016-07-11: Simon Goldschmidt + * tcp_in.c: fixed bug #48476 (TCP sent callback called wrongly due to picking + up old pcb->acked + + 2016-06-30: Simon Goldschmidt (original patch by Fabian Koch) + * tcp_in.c: fixed bug #48170 (Vulnerable to TCP RST spoofing) + + 2016-05-20: Dirk Ziegelmeier + * sntp.h/.c: Fix return value of sntp_getserver() call to return a pointer + + 2016-04-05: Simon Goldschmidt (patch by Philip Gladstone) + * udp.c: patch #8358: allow more combinations of listening PCB for IPv6 + + 2016-04-05: Simon Goldschmidt + * netconn/socket API: fixed bug# 43739 (Accept not reporting errors about + aborted connections): netconn_accept() returns ERR_ABRT (sockets: ECONNABORTED) + for aborted connections, ERR_CLSD (sockets: EINVAL) if the listening netconn + is closed, which better seems to follow the standard. + + 2016-03-23: Florent Matignon + * dhcp.c: fixed bug #38203: DHCP options are not recorded in all DHCP ack messages + + 2016-03-22: Simon Goldschmidt + * tcp: changed accept handling to be done internally: the application does not + have to call tcp_accepted() any more. Instead, when delaying accept (e.g. sockets + do), call tcp_backlog_delayed()/tcp_backlog_accepted() (fixes bug #46696) + + 2016-03-22: Simon Goldschmidt + * dns.c: ignore dns response parsing errors, only abort resolving for correct + responses or error responses from correct server (bug #47459) + + 2016-03-17: Simon Goldschmidt + * api_msg.c: fixed bug #47448 (netconn/socket leak if RST is received during close) + + 2016-03-17: Joel Cunningham + * api_msg.c: don't fail closing a socket/netconn when failing to allocate the + FIN segment; blocking the calling thread for a while is better than risking + leaking a netconn/socket (see bug #46701) + + 2016-03-16: Joel Cunningham + * tcp_out.c: reset rto timer on fast retransmission + + 2016-03-16: Deomid Ryabkov + * tcp_out.c: fixed bug #46384 Segment size calculation bug with MSS != TCP_MSS + + 2016-03-05: Simon Goldschmidt + * err.h/.c, sockets.c: ERR_IF is not necessarily a fatal error + + 2015-11-19: fix by Kerem Hadimli + * sockets.c: fixed bug #46471: lwip_accept() leaks socket descriptors if new + netconn was already closed because of peer behavior + + 2015-11-12: fix by Valery Ushakov + * tcp_in.c: fixed bug #46365 tcp_accept_null() should call tcp_abort() + + 2015-10-02: Dirk Ziegelmeier/Simon Goldschmidt + * snmp: cleaned up snmp structs API (fixed race conditions from bug #46089, + reduce ram/rom usage of tables): incompatible change for private MIBs + + 2015-09-30: Simon Goldschmidt + * ip4_addr.c: fixed bug #46072: ip4addr_aton() does not check the number range + of all address parts + + 2015-08-28: Simon Goldschmidt + * tcp.c, tcp_in.c: fixed bug #44023: TCP ssthresh value is unclear: ssthresh + is set to the full send window for active open, too, and is updated once + after SYN to ensure the correct send window is used + + 2015-08-28: Simon Goldschmidt + * tcp: fixed bug #45559: Window scaling casts u32_t to u16_t without checks + + 2015-08-26: Simon Goldschmidt + * ip6_frag.h/.c: fixed bug bug #41009: IPv6 reassembly broken on 64-bit platforms: + define IPV6_FRAG_COPYHEADER==1 on these platforms to copy the IPv6 header + instead of referencing it, which gives more room for struct ip6_reass_helper + + 2015-08-25: Simon Goldschmidt + * sockets.c: fixed bug #45827: recvfrom: TCP window is updated with MSG_PEEK + + 2015-08-20: Manoj Kumar + * snmp_msg.h, msg_in.c: fixed bug #43790: Sending octet string of Length >255 + from SNMP agent + + 2015-08-19: Jens Nielsen + * icmp.c, ip4.c, tcp_in.c, udp.c, raw.c: fixed bug #45120: Broadcast & multiple + interfaces handling + + 2015-08-19: Simon Goldschmidt (patch by "Sandra") + * dns.c: fixed bug #45004: dns response without answer might be discarded + + 2015-08-18: Chrysn + * timers.c: patch #8704 fix sys_timeouts_sleeptime function + + 2015-07-01: Erik Ekman + * puf.c: fixed bug #45454 (pbuf_take_at() skips write and returns OK if offset + is at start of pbuf in chain) + + 2015-05-19: Simon Goldschmidt + * dhcp.h/.c: fixed bugs #45140 and #45141 (dhcp was not stopped correctly after + fixing bug #38204) + + 2015-03-21: Simon Goldschmidt (patch by Homyak) + * tcp_in.c: fixed bug #44766 (LWIP_WND_SCALE: tcphdr->wnd was not scaled in + two places) + + 2015-03-21: Simon Goldschmidt + * tcp_impl.h, tcp.c, tcp_in.c: fixed bug #41318 (Bad memory ref in tcp_input() + after tcp_close()) + + 2015-03-21: Simon Goldschmidt + * tcp_in.c: fixed bug #38468 (tcp_sent() not called on half-open connection for + data ACKed with the same ack as FIN) + + 2015-03-21: Simon Goldschmidt (patch by Christoffer Lind) + * dhcp.h/.c: fixed bug #38204 (DHCP lease time not handled correctly) + + 2015-03-20: Simon Goldschmidt + * dhcp.c: fixed bug #38714 (Missing option and client address in DHCPRELEASE message) + + 2015-03-19: Simon Goldschmidt + * api.h, tcpip.h, api_lib.c, api_msg.c: fixed race conditions in assigning + netconn->last_err (fixed bugs #38121 and #37676) + + 2015-03-09: Simon Goldschmidt + * ip4.c: fixed the IPv4 part of bug #43904 (ip_route() must detect linkup status) + + 2015-03-04: Simon Goldschmidt + * nd6.c: fixed bug #43784 (a host should send at least one Router Solicitation) + + 2015-03-04: Valery Ushakov + * ip6.c: fixed bug #41094 (Byte-order bug in IPv6 fragmentation header test) + + 2015-03-04: Zach Smith + * nd6.c: fixed bug #38153 (nd6_input() byte order issues) + + 2015-02-26: Simon Goldschmidt + * netif.c, tcp.h/.c: fixed bug #44378 (TCP connections are not aborted on netif + remove) + + 2015-02-25: Simon Goldschmidt + * ip4.c, etharp.c: fixed bug #40177 (System hangs when dealing with corrupted + packets), implemented task #12357 (Ensure that malicious packets don't + assert-fail): improved some pbuf_header calls to not assert-fail. + + 2015-02-25: patch by Joel Cunningham + * udp.h/.c, sockets.c: fixed bug #43028 (IP_MULTICAST_TTL affects unicast + datagrams) + + 2015-02-25: patch by Greg Renda + * ip4_frag.c: fixed bug #38210 (ip reassembly while remove oldest datagram) + + 2015-02-25: Simon Goldschmidt + * sockets.c: fixed bug #38165 (socket with mulicast): ensure igmp membership + are dropped when socket (not netconn!) is closed. + + 2015-02-25: Simon Goldschmidt + * ip4.h/.c, udp.c: fixed bug #38061 (wrong multicast routing in IPv4) by + adding an optional default netif for multicast routing + + 2015-02-25: Simon Goldschmidt + * netconn API: fixed that netconn_connect still used message passing for + LWIP_TCPIP_CORE_LOCKING==1 + + 2015-02-22: patch by Jens Nielsen + * icmp.c: fixed bug #38803 (Source address in broadcast ping reply) + + 2015-02-22: Simon Goldschmidt + * udp.h, sockets.c: added proper accessor functions for pcb->multicast_ip + (previously used by get/setsockopt only) + + 2015-02-18: Simon Goldschmidt + * sockets.c: Fixed select not reporting received FIN as 'readable' in certain + rare cases (bug #43779: select(), close(), and TCP retransmission error) + + 2015-02-17: Simon Goldschmidt + * err.h, sockets.c, api_msg.c: fixed bug #38853 "connect() use a wrong errno": + return ERR_ALREADY/EALRADY during connect, ERR_ISCONN/EISCONN when already + connected + + 2015-02-17: Simon Goldschmidt + * tcp_impl.h, tcp_out.c, tcp.c, api_msg.c: fixed bug #37614 "Errors from + ipX_output are not processed". Now tcp_output(_segment) checks for the return + value of ipX_output and does not try to send more on error. A netif driver + can call tcp_txnow() (from tcpip_thread!) to try to send again if TX buffers + are available again. + + 2015-02-14: patches by Freddie Chopin + * snmp*: made community writable, fixed some const pointers + + 2015-02-13: Simon Goldschmidt + * msg_in.c: fixed bug #22070 "MIB_OBJECT_WRITE_ONLY not implemented in SNMP" + + 2015-02-12: Simon Goldschmidt + * ip.h, ip4.c, ip6.c: fixed bug #36403 "ip4_input() and ip6_input() always pass + inp to higher layers": now the accepting netif is passed up, but the input + netif is available through ip_current_input_netif() if required. + + 2015-02-11: patch by hichard + * tcpip.c: fixed bug #43094 "The function tcpip_input() forget to handle IPv6" + + 2015-02-10: Simon Goldschmidt + * netconn API: fixed that netconn_close/netconn_delete still used message passing + for LWIP_TCPIP_CORE_LOCKING==1 + + 2015-02-10: Simon Goldschmidt + * netconn/socket api: fixed bug #44225 "closing TCP socket should time out + eventually", implemented task #6930 "Implement SO_LINGER": closing TCP sockets + times out after 20 seconds or after the configured SND_TIMEOUT or depending + on the linger settings. + + 2015-01-27: Simon Goldschmidt + * api_msg.c: fixed that SHUT_RD followed by SHUT_WR was different to SHUT_RDWR, + fixed return value of lwip_netconn_do_close on unconnected netconns + + 2015-01-17: Simon Goldschmidt + * sockets.c: fixed bug #43361 select() crashes with stale FDs + + 2015-01-17: Simon Goldschmidt + * sockets.c/.h, memp_std.h: fixed bug #40788 "lwip_setsockopt_internal() crashes" + by rewriting set/getsockopt functions to combine checks with the actual code + and add more NULL checks; this also fixes that CORE_LOCKING used message + passing for set/getsockopt. + + 2014-12-19: Simon Goldschmidt + * opt.h, dhcp.h/.c: prevent dhcp from starting when netif link is down (only + when LWIP_DHCP_CHECK_LINK_UP==1, which is disabled by default for + compatibility reasons) + + 2014-12-17: Simon Goldschmidt + * tcp_out.c: fixed bug #43840 Checksum error for TCP_CHECKSUM_ON_COPY==1 for + no-copy data with odd length + + 2014-12-10: Simon Goldschmidt + * sockets.c, tcp.c, others: fixed bug #43797 set/getsockopt: SO_SNDTIMEO/SO_RCVTIMEO + take int as option but should take timeval (LWIP_SO_SNDRCVTIMEO_STANDARD==0 can + be used to revert to the old 'winsock' style behaviour) + Fixed implementation of SO_ACCEPTCONN to just look at the pcb state + + 2014-12-09: Simon Goldschmidt + * ip4.c: fixed bug #43596 IGMP queries from 0.0.0.0 are discarded + + 2014-10-21: Simon Goldschmidt (patch by Joel Cunningham and Albert Huitsing) + * sockts.c: fixed bugs #41495 Possible threading issue in select() and #43278 + event_callback() handle context switch when calling sys_sem_signal() + + 2014-10-21: Simon Goldschmidt + * api_msg.c: fixed bug #38219 Assert on TCP netconn_write with sndtimeout set + + 2014-09-16: Kevin Cernekee + * dns.c: patch #8480 Fix handling of dns_seqno wraparound + + 2014-09-16: Simon Goldschmidt + * tcp_out.c: fixed bug #43192 tcp_enqueue_flags() should not check TCP_SND_QUEUELEN + when sending FIN + + 2014-09-03: Simon Goldschmidt + * msg_in.c: fixed bug #39355 SNMP Memory Leak in case of error + + 2014-09-02: Simon Goldschmidt + * err.h/.c, sockets.c, api_msg.c: fixed bug #43110 call getpeername() before + listen() will cause a error + + 2014-09-02: Simon Goldschmidt + * sockets.c: fixed bug #42117 lwip_fcntl does not set errno + + 2014-09-02: Simon Goldschmidt + * tcp.c: fixed bug #42299 tcp_abort() leaves freed pcb on tcp_bound_pcbs list + + 2014-08-20: Simon Goldschmidt + * dns.c: fixed bug #42987 lwIP is vulnerable to DNS cache poisoning due to + non-randomized TXIDs + + 2014-06-03: Simon Goldschmidt + * tcp_impl.h, tcp_in.c: fixed bug #37969 SYN packet dropped as short packet in + tcp_input function + + 2014-05-20: Simon Goldschmidt + * tcp_out.c: fixed bug #37184 tcp_write problem for pcbs in the SYN_SENT state + + 2014-05-19: Simon Goldschmidt + * *.h: Fixed bug #35874 reserved identifier violation (removed leading underscores + from header include guards) + + 2014-04-08: Simon Goldschmidt + * tcp.c: Fixed bug #36167 tcp server crash when client closes (maximum window) + + 2014-04-06: Simon Goldschmidt + * tcp_in.c: Fixed bug #36210 lwIP does not elicit an empty ACK when received + unacceptable ACK + + 2014-04-06: Simon Goldschmidt + * dhcp.c, ip4.c/.h, ip6.c/.h, udp.c/.h, ip.h: Fixed bug #41787 DHCP Discovery + is invalid when an IP is set to thet netif. + + 2014-03-14: Simon Goldschmidt + * tcp_out.c: Fixed bug #36153 TCP Cheksum error if LWIP_CHECKSUM_ON_COPY=1 + + 2014-03-11: Simon Goldschmidt (patch by Mason) + * opt.h, sockets.c: fixed bug #35928 BSD sockets functions must set errno for + POSIX-compliance + + 2014-02-27: Simon Goldschmidt + * dhcp.c: fixed bug #40303 DHCP xid renewed when sending a DHCPREQUEST + + 2014-02-27: Simon Goldschmidt + * raw.c: fixed bug #41680 raw socket can not receive IPv6 packet when + IP_SOF_BROADCAST_RECV==1 + + 2014-02-27: Simon Goldschmidt + * api_msg.c, sockets.c: fixed bug #38404 getpeeraddr returns success on + unconnected/listening TCP sockets + + 2014-02-27: Simon Goldschmidt + * sockets.c: fixed bug #41729 Some socket functions return Exyz instead of -1 + + 2014-02-25: Simon Goldschmidt + * ip4.c: fixed bug #39514 ip_route() may return an IPv6-only interface + + 2014-02-25: Simon Goldschmidt, patch by Fatih Asici + * pbuf.c: fixed bug #39356 Wrong increment in pbuf_memfind() + + 2014-02-25: Simon Goldschmidt + * netif.c/.h, udp.c: fixed bug #39225 udp.c uses netif_matches_ip6_addr() incorrectly; + renamed function netif_matches_ip6_addr() to netif_get_ip6_addr_match() + + 2014-02-25: Simon Goldschmidt + * igmp.c: fixed bug #39145 IGMP membership report for 224.0.0.1 + + 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) + * etharp.c, opt.h: fixed bug #34681 Limit ARP queue length by ARP_QUEUE_LEN (=3) + + 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) + * etharp.h/.c: fixed bug #34682 Limit ARP request flood for unresolved entry + + 2014-02-20: Simon Goldschmidt + * tcp_out.c: fixed bug #39683 Assertion "seg->tcphdr not aligned" failed with + MEM_ALIGNMENT = 8 + + 2014-02-20: Simon Goldschmidt + * sockets.c: fixed bug #39882 No function shall set errno to 0 + + 2014-02-20: Simon Goldschmidt + * mib_structs.c: fixed bug #40050 SNMP problem with MIB arrays > 255 + + 2014-02-20: Simon Goldschmidt + * api.h, sockets.c: fixed bug #41499 netconn::recv_avail can overflow + + 2014-01-08: Stathis Voukelatos + * memp_std.h: patch #7928 Fixed size calculation in MALLOC memory pool + creation macro + + 2014-01-18: Brian Fahs + * tcp_out.c: patch #8237: tcp_rexmit_rto fails to update pcb->unsent_oversize + when necessary + + 2014-01-17: Grant Erickson, Jay Logue, Simon Goldschmidt + * ipv6.c, netif.c: patch #7913 Enable Support for IPv6 Loopback + + 2014-01-16: Stathis Voukelatos + * netif.c: patch #7902 Fixed netif_poll() operation when LWIP_LOOPBACK_MAX_PBUFS > 0 + + 2014-01-14: "Freddie Chopin" + * snmp.h, mib2.c: fixed constness and spelling of sysdescr + + 2014-01-14: Simon Goldschmidt (patch by Thomas Faber) + * tcpip.c: patch #8241: Fix implicit declaration of ip_input with + LWIP_TCPIP_CORE_LOCKING_INPUT disabled + + 2014-01-14: chrysn + * timers.c: patch #8244 make timeouts usable reliably from outside of the + timeout routine + + 2014-01-10: Simon Goldschmidt + * ip_frag.c, ip6_frag.c: fixed bug #41041 Potential use-after-free in IPv6 reassembly + + 2014-01-10: Simon Goldschmidt + * memp.c: fixed bug #41188 Alignment error in memp_init() when MEMP_SEPARATE_POOLS==1 + + 2014-01-10: Simon Goldschmidt + * tcp.c: fixed bug #39898 tcp_fasttmr() possible lock due to infinte queue process loop + + 2013-06-29: Simon Goldschmidt + * inet.h, sockets.h: partially fixed bug #37585: IPv6 compatibility (in socket structs) + + 2013-06-29: Simon Goldschmidt + * inet6.h: bug #37585/task #12600: fixed struct in6_addr.s6_addr to conform to spec + + 2013-04-24: patch by Liam + * api_msg.c: patch #8008 Fix a potential null pointer dereference in assert + + 2013-04-24: Simon Goldschmidt + * igmp.c: fixed possible division by zero + + 2013-04-24: Simon Goldschmidt + * ip6.h, some ipv6 C files: fixed bug #38526 Coverity: Recursive Header Inclusion in ip6.h + + 2013-04-24: Simon Goldschmidt (patch by Emil Ljungdahl): + * netif.c: fixed bug #38586 netif_loop_output() "deadlocks" + + 2013-01-15: Simon Goldschmidt + * ip4.c: fixed bug #37665 ip_canforward operates on address in wrong byte order + + 2013-01-15: Simon Goldschmidt + * pbuf.h: fixed bug #38097 pbuf_free_ooseq() warning + + 2013-01-14: Simon Goldschmidt + * dns.c: fixed bug #37705 Possible memory corruption in DNS query + + 2013-01-11: Simon Goldschmidt + * raw.c: fixed bug #38066 Raw pcbs can alter packet without eating it + + 2012-08-22: Simon Goldschmidt + * memp.c: fixed bug #37166: memp_sanity check loops itself + + 2012-08-13: Simon Goldschmidt + * dhcp.c: fixed bug #36645: Calling dhcp_release before dhcp_start + dereferences NULL + + 2012-08-13: Simon Goldschmidt + * msg_out.c: fixed bug #36840 snmp_send_trap() NULL de-reference if traps + configured but no interfaces available + + 2012-08-13: Simon Goldschmidt + * dns.c: fixed bug #36899 DNS TTL 0 is cached for a long time + + 2012-05-11: Simon Goldschmidt (patch by Marty) + * memp.c: fixed bug #36412: memp.c does not compile when + MEMP_OVERFLOW_CHECK > zero and MEMP_SEPARATE_POOLS == 1 + + 2012-05-03: Simon Goldschmidt (patch by Sylvain Rochet) + * ppp.c: fixed bug #36283 (PPP struct used on header size computation and + not packed) + + 2012-05-03: Simon Goldschmidt (patch by David Empson) + * ppp.c: fixed bug #36388 (PPP: checksum-only in last pbuf leads to pbuf with + zero length) + + 2012-03-25: Simon Goldschmidt + * api_msg.c: Fixed bug #35817: do_connect() invalidly signals op_completed + for UDP/RAW with LWIP_TCPIP_CORE_LOCKING==1 + + 2012-03-25: Simon Goldschmidt + * api_msg.h, api_lib.c, api_msg.c, netifapi.c: fixed bug #35931: Name space + pollution in api_msg.c and netifapi.c + + 2011-08-24: Simon Goldschmidt + * inet6.h: fixed bug #34124 struct in6_addr does not conform to the standard + + + +(STABLE-1.4.1) + + ++ New features: + + 2012-03-25: Simon Goldschmidt (idea by Mason) + * posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h + which are a simple wrapper to the correct lwIP include files. + + 2012-01-16: Simon Goldschmidt + * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP + + 2011-12-17: Simon Goldschmidt + * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW) + (fixes bug #35061) + + 2011-09-27: Simon Goldschmidt + * opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989) + (define TCP_OOSEQ_MAX_BYTES / TCP_OOSEQ_MAX_PBUFS in lwipopts.h) + + 2011-09-21: Simon Goldschmidt + * opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on + send (TCP only, bug #33820) + + 2011-09-21: Simon Goldschmidt + * init.c: Converted runtime-sanity-checks into compile-time checks that can + be disabled (since runtime checks can often not be seen on embedded targets) + + 2011-09-11: Simon Goldschmidt + * ppp.h, ppp_impl.h: splitted ppp.h to an internal and external header file + to get a clear separation of which functions an application or port may use + (task #11281) + + 2011-09-11: Simon Goldschmidt + * opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize + initial local TCP/UDP ports (so that different port ranges are used after + a reboot; bug #33818; this one added tcp_init/udp_init functions again) + + 2011-09-03: Simon Goldschmidt + * dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302) + + 2011-08-24: Simon Goldschmidt + * opt.h, netif.h/.c: added netif remove callback (bug #32397) + + 2011-07-26: Simon Goldschmidt + * etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter + function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN) + + 2011-07-21: Simon Goldschmidt (patch by hanhui) + * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: + Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. + Also added code to allow ip_forward() to forward non-broadcast packets to + the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1). + + 2011-06-26: Simon Goldschmidt (patch by Cameron Gutman) + * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that + pcb->state != LISTEN + + 2011-05-14: Simon Goldschmidt (patch by Stéphane Lesage) + * tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static + memory message + + + ++ Bugfixes: + + 2012-09-26: Simon Goldschmidt + * api_msg.c: fixed bug #37405 'err_tcp()' uses already freed 'netconn' object + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7843 Fix corner case with dhcp timeouts + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7840 Segfault in dhcp_parse_reply if no end marker in dhcp packet + + 2012-08-22: Simon Goldschmidt + * memp.c: fixed bug #37166: memp_sanity check loops itself + + 2012-05-08: Simon Goldschmidt + * tcp_out.c: fixed bug: #36380 unsent_oversize mismatch in 1.4.1RC1 (this was + a debug-check issue only) + + 2012-03-27: Simon Goldschmidt + * vj.c: fixed bug #35756 header length calculation problem in ppp/vj.c + + 2012-03-27: Simon Goldschmidt (patch by Mason) + * tcp_out.c: fixed bug #35945: SYN packet should provide the recv MSS not the + send MSS + + 2012-03-22: Simon Goldschmidt + * ip4.c: fixed bug #35927: missing refragmentaion in ip_forward + + 2012-03-20: Simon Goldschmidt (patch by Mason) + * netdb.c: fixed bug #35907: lwip_gethostbyname_r returns an invalid h_addr_list + + 2012-03-12: Simon Goldschmidt (patch by Bostjan Meglic) + * ppp.c: fixed bug #35809: PPP GetMask(): Compiler warning on big endian, + possible bug on little endian system + + 2012-02-23: Simon Goldschmidt + * etharp.c: fixed bug #35595: Impossible to send broadcast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt + * ppp.c: fixed pbuf leak when PPP session is aborted through pppSigHUP() + (bug #35541: PPP Memory Leak) + + 2012-02-16: Simon Goldschmidt + * etharp.c: fixed bug #35531: Impossible to send multicast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt (patch by Stéphane Lesage) + * msg_in.c, msg_out.c: fixed bug #35536 SNMP: error too big response is malformed + + 2012-02-15: Simon Goldschmidt + * init.c: fixed bug #35537: MEMP_NUM_* sanity checks should be disabled with + MEMP_MEM_MALLOC==1 + + 2012-02-12: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: partly fixed bug #25882: TCP hangs on + MSS > pcb->snd_wnd (by not creating segments bigger than half the window) + + 2012-02-11: Simon Goldschmidt + * tcp.c: fixed bug #35435: No pcb state check before adding it to time-wait + queue while closing + + 2012-01-22: Simon Goldschmidt + * tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR) + + 2012-01-21: Simon Goldschmidt + * tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb + + 2012-01-20: Simon Goldschmidt + * dhcp.c: fixed bug #35151: DHCP asserts on incoming option lengths + + 2012-01-20: Simon Goldschmidt + * pbuf.c: fixed bug #35291: NULL pointer in pbuf_copy + + 2011-11-25: Simon Goldschmidt + * tcp.h/.c, tcp_impl.h, tcp_in.c: fixed bug #31177: tcp timers can corrupt + tcp_active_pcbs in some cases + + 2011-11-23: Simon Goldschmidt + * sys.c: fixed bug #34884: sys_msleep() body needs to be surrounded with + '#ifndef sys_msleep' + + 2011-11-22: Simon Goldschmidt + * netif.c, etharp.h/.c: fixed bug #34684: Clear the arp table cache when + netif is brought down + + 2011-10-28: Simon Goldschmidt + * tcp_in.c: fixed bug #34638: Dead code in tcp_receive - pcb->dupacks + + 2011-10-23: Simon Goldschmidt + * mem.c: fixed bug #34429: possible memory corruption with + LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT set to 1 + + 2011-10-18: Simon Goldschmidt + * arch.h, netdb.c: fixed bug #34592: lwip_gethostbyname_r uses nonstandard + error value + + 2011-10-18: Simon Goldschmidt + * opt.h: fixed default values of TCP_SNDLOWAT and TCP_SNDQUEUELOWAT for small + windows (bug #34176 select after non-blocking send times out) + + 2011-10-18: Simon Goldschmidt + * tcp_impl.h, tcp_out.c: fixed bug #34587: TCP_BUILD_MSS_OPTION doesn't + consider netif->mtu, causes slow network + + 2011-10-18: Simon Goldschmidt + * sockets.c: fixed bug #34581 missing parentheses in udplite sockets code + + 2011-10-18: Simon Goldschmidt + * sockets.h: fixed bug #34580 fcntl() is missing in LWIP_COMPAT_SOCKETS + + 2011-10-17: Simon Goldschmidt + * api_msg.c: fixed bug #34569: shutdown(SHUT_WR) crashes netconn/socket api + + 2011-10-13: Simon Goldschmidt + * tcp_in.c, tcp_out.c: fixed bug #34517 (persist timer is started although no + zero window is received) by starting the persist timer when a zero window is + received, not when we have more data queued for sending than fits into the + window + + 2011-10-13: Simon Goldschmidt + * def.h, timers.c: fixed bug #34541: LWIP_U32_DIFF is unnecessarily complex + + 2011-10-13: Simon Goldschmidt + * sockets.c, api_lib.c: fixed bug #34540: compiler error when CORE_LOCKING is + used and not all protocols are enabled + + 2011-10-12: Simon Goldschmidt + * pbuf.c: fixed bug #34534: Error in sending fragmented IP if MEM_ALIGNMENT > 4 + + 2011-10-09: Simon Goldschmidt + * tcp_out.c: fixed bug #34426: tcp_zero_window_probe() transmits incorrect + byte value when pcb->unacked != NULL + + 2011-10-09: Simon Goldschmidt + * ip4.c: fixed bug #34447 LWIP_IP_ACCEPT_UDP_PORT(dst_port) wrong + + 2011-09-27: Simon Goldschmidt + * tcp_in.c, tcp_out.c: Reset pcb->unsent_oversize in 2 more places... + + 2011-09-27: Simon Goldschmidt + * tcp_in.c: fixed bug #28288: Data after FIN in oos queue + + 2011-09-27: Simon Goldschmidt + * dhcp.c: fixed bug #34406 dhcp_option_hostname() can overflow the pbuf + + 2011-09-24: Simon Goldschmidt + * mem.h: fixed bug #34377 MEM_SIZE_F is not defined if MEM_LIBC_MALLOC==1 + + 2011-09-23: Simon Goldschmidt + * pbuf.h, tcp.c, tcp_in.c: fixed bug #33871: rejecting TCP_EVENT_RECV() for + the last packet including FIN can lose data + + 2011-09-22: Simon Goldschmidt + * tcp_impl.h: fixed bug #34355: nagle does not take snd_buf/snd_queuelen into + account + + 2011-09-21: Simon Goldschmidt + * opt.h: fixed default value of TCP_SND_BUF to not violate the sanity checks + in init.c + + 2011-09-20: Simon Goldschmidt + * timers.c: fixed bug #34337 (possible NULL pointer in sys_check_timeouts) + + 2011-09-11: Simon Goldschmidt + * tcp_out.c: use pcb->mss instead of TCP_MSS for preallocate mss-sized pbufs + (bug #34019) + + 2011-09-09: Simon Goldschmidt + * udp.c: fixed bug #34072: UDP broadcast is received from wrong UDP pcb if + udp port matches + + 2011-09-03: Simon Goldschmidt + * tcp_in.c: fixed bug #33952 PUSH flag in incoming packet is lost when packet + is aggregated and sent to application + + 2011-09-01: Simon Goldschmidt + * opt.h: fixed bug #31809 LWIP_EVENT_API in opts.h is inconsistent compared + to other options + + 2011-09-01: Simon Goldschmidt + * tcp_in.c: fixed bug #34111 RST for ACK to listening pcb has wrong seqno + + 2011-08-24: Simon Goldschmidt + * api_msg.c, sockets.c: fixed bug #33956 Wrong error returned when calling + accept() on UDP connections + + 2011-08-24: Simon Goldschmidt + * sockets.h: fixed bug #34057 socklen_t should be a typedef + + 2011-08-24: Simon Goldschmidt + * pbuf.c: fixed bug #34112 Odd check in pbuf_alloced_custom (typo) + + 2011-08-24: Simon Goldschmidt + * dhcp.c: fixed bug #34122 dhcp: hostname can overflow + + 2011-08-24: Simon Goldschmidt + * netif.c: fixed bug #34121 netif_add/netif_set_ipaddr fail on NULL ipaddr + + 2011-08-22: Simon Goldschmidt + * tcp_out.c: fixed bug #33962 TF_FIN not always set after FIN is sent. (This + merely prevents nagle from not transmitting fast after closing.) + + 2011-07-22: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h: fixed bug #31084 (socket API returns + always EMSGSIZE on non-blocking sockets if data size > send buffers) -> now + lwip_send() sends as much as possible for non-blocking sockets + + 2011-07-22: Simon Goldschmidt + * pbuf.c/.h, timers.c: freeing ooseq pbufs when the pbuf pool is empty implemented + for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level. + + 2011-07-21: Simon Goldschmidt + * etharp.c: fixed bug #33551 (ARP entries may time out although in use) by + sending an ARP request when an ARP entry is used in the last minute before + it would time out. + + 2011-07-04: Simon Goldschmidt + * sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0. + + 2011-06-26: Simon Goldschmidt + * tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by + updating its documentation only. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an + unaligned pointer. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1" + + 2011-05-25: Simon Goldschmidt + * tcp.c: fixed bug #33398 (pointless conversion when checking TCP port range) + + + +(STABLE-1.4.0) + + ++ New features: + + 2011-03-27: Simon Goldschmidt + * tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and + calculate it in tcp_zero_window_probe (the only place where it was used). + + 2010-11-21: Simon Goldschmidt + * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif + (fixes bug #31525). + + 2010-07-12: Simon Goldschmidt (patch by Stephane Lesage) + * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for + IP_MULTICAST_LOOP at socket- and raw-API level. + + 2010-06-16: Simon Goldschmidt + * ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow + link-layer-addressed UDP traffic to be received while a netif is down (just + like DHCP during configuration) + + 2010-05-22: Simon Goldschmidt + * many many files: bug #27352: removed packing from ip_addr_t, the packed + version is now only used in protocol headers. Added global storage for + current src/dest IP address while in input functions. + + 2010-05-16: Simon Goldschmidt + * def.h: task #10391: Add preprocessor-macros for compile-time htonl + calculation (and use them throughout the stack where applicable) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool + instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own + MEMP pool instead of the heap + + 2010-05-13: Simon Goldschmidt + * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added + new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast + packets to more than one pcb. + + 2010-05-02: Simon Goldschmidt + * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending + UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-04-30: Simon Goldschmidt + * udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that + take a precalculated checksum, added pbuf_fill_chksum() to copy data + into a pbuf and at the same time calculating the checksum for that data + + 2010-04-29: Simon Goldschmidt + * ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying + 2-byte-aligned IP addresses and MAC addresses + + 2010-04-28: Patch by Bill Auerbach + * ip.c: Inline generating IP checksum to save a function call + + 2010-04-14: Simon Goldschmidt + * tcpip.h/.c, timers.c: Added an overridable define to get informed when the + tcpip_thread processes messages or timeouts to implement a watchdog. + + 2010-03-28: Simon Goldschmidt + * ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing + fragment if LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-03-27: Simon Goldschmidt + * etharp.c: Speedup TX by moving code from find_entry to etharp_output/ + etharp_query to prevent unnecessary function calls (inspired by + patch #7135). + + 2010-03-20: Simon Goldschmidt + * opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code + since the linker cannot do this automatically to save space. + + 2010-03-20: Simon Goldschmidt + * opt.h, etharp.c/.h: Added support for static ARP table entries + + 2010-03-14: Simon Goldschmidt + * tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum + when creating TCP segments, not when (re-)transmitting them. + + 2010-03-07: Simon Goldschmidt + * sockets.c: bug #28775 (select/event_callback: only check select_cb_list + on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code. + This should speed up receiving data on sockets as the select code in + event_callback is only executed when select is waiting. + + 2010-03-06: Simon Goldschmidt + * tcp_out.c: task #7013 (Create option to have all packets delivered to + netif->output in one piece): Always copy to try to create single pbufs + in tcp_write. + + 2010-03-06: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv + by not allocating a netbuf): added function netconn_recv_tcp_pbuf() + for tcp netconns to receive pbufs, not netbufs; use that function + for tcp sockets. + + 2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt + * opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040: + Work on tcp_enqueue: Don't waste memory when chaining segments, + added option TCP_OVERSIZE to prevent creating many small pbufs when + calling tcp_write with many small blocks of data. Instead, pbufs are + allocated larger than needed and the space is used for later calls to + tcp_write. + + 2010-02-21: Simon Goldschmidt + * stats.c/.h: Added const char* name to mem- and memp-stats for easier + debugging. + + 2010-02-21: Simon Goldschmidt + * tcp.h (and usages), added tcp_impl.h: Splitted API and internal + implementation of tcp to make API usage cleare to application programmers + + 2010-02-14: Simon Goldschmidt/Stephane Lesage + * ip_addr.h: Improved some defines working on ip addresses, added faster + macro to copy addresses that cannot be NULL + + 2010-02-13: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non- + blocking send operation) + + 2010-02-12: Simon Goldschmidt + * sockets.c/.h: Added a minimal version of posix fctl() to have a + standardised way to set O_NONBLOCK for nonblocking sockets. + + 2010-02-12: Simon Goldschmidt + * dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated + memory): added autoip_set_struct() and dhcp_set_struct() to let autoip + and dhcp work with user-allocated structs instead of callin mem_malloc + + 2010-02-12: Simon Goldschmidt/Jeff Barber + * tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has + SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT + + 2010-02-12: Simon Goldschmidt + * sys layer: task #10139 (Prefer statically allocated memory): converted + mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t; + converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX + to let sys.h use binary semaphores instead of mutexes - as before) + + 2010-02-09: Simon Goldschmidt (Simon Kallweit) + * timers.c/.h: Added function sys_restart_timeouts() from patch #7085 + (Restart system timeout handling) + + 2010-02-09: Simon Goldschmidt + * netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into + netif.c) - loopif does not have to be created by the port any more, + just define LWIP_HAVE_LOOPIF to 1. + + 2010-02-08: Simon Goldschmidt + * inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa + inet_ntoa_r/ipaddr_ntoa_r + + 2010-02-08: Simon Goldschmidt + * netif.h: Added netif_s/get_igmp_mac_filter() macros + + 2010-02-05: Simon Goldschmidt + * netif.h: Added function-like macros to get/set the hostname on a netif + + 2010-02-04: Simon Goldschmidt + * nearly every file: Replaced struct ip_addr by typedef ip_addr_t to + make changing the actual implementation behind the typedef easier. + + 2010-02-01: Simon Goldschmidt + * opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool + for allocating memory when getaddrinfo() is called. + + 2010-01-31: Simon Goldschmidt + * dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse + them once instead of parsing for every option. This also removes + the need for mem_malloc from dhcp_recv and makes it possible to + correctly retrieve the BOOTP file. + + 2010-01-30: simon Goldschmidt + * sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect + the sockets array. + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, api_msg.c, sockets.c: Added except set support in select + (patch #6860) + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c: + Add non-blocking support for connect (partly from patch #6860), + plus many cleanups in socket & netconn API. + + 2010-01-27: Simon Goldschmidt + * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding + to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605 + + 2010-01-26: Simon Goldschmidt + * snmp: Use memp pools for snmp instead of the heap; added 4 new pools. + + 2010-01-14: Simon Goldschmidt + * ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback + by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback() + + 2010-01-13: Simon Goldschmidt + * mem.c: The heap now may be moved to user-defined memory by defining + LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address + (patch #6966 and bug #26133) + + 2010-01-10: Simon Goldschmidt (Bill Auerbach) + * opt.h, memp.c: patch #6822 (Add option to place memory pools in + separate arrays) + + 2010-01-10: Simon Goldschmidt + * init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define + LWIP_RAND() for lwip-wide randomization (to be defined in cc.h) + + 2009-12-31: Simon Goldschmidt + * tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h + added timers.c/.h: Separated timer implementation from semaphore/mbox + implementation, moved timer implementation to timers.c/.h, timers are + now only called from tcpip_thread or by explicitly checking them. + (TASK#7235) + + 2009-12-27: Simon Goldschmidt + * opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option + LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE) + + + ++ Bugfixes: + + 2011-04-20: Simon Goldschmidt + * sys_arch.txt: sys_arch_timeouts() is not needed any more. + + 2011-04-13: Simon Goldschmidt + * tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by + using ports in the IANA private/dynamic range (49152 through 65535). + + 2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl: + * etharp.h/.c: Fixed broken VLAN support. + + 2011-03-27: Simon Goldschmidt + * tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp + pcbs) by checking if the pcb was bound (local_port != 0). + + 2011-03-27: Simon Goldschmidt + * ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice) + + 2011-03-27: Simon Goldschmidt + * sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and + raw pcbs with LWIP_TCPIP_CORE_LOCKING==1. + + 2011-03-27: Simon Goldschmidt + * tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route + is present never times out) by starting retransmission timer before checking + route. + + 2011-03-22: Simon Goldschmidt + * ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only + calling sio_read_abort() if the file descriptor is valid. + + 2011-03-14: Simon Goldschmidt + * err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect + more than once can render a socket useless) since it mainly involves changing + "FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal. + + 2011-03-13: Simon Goldschmidt + * sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing + err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN: + use EALRADY instead of -1 + + 2011-03-13: Simon Goldschmidt + * api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the + connection has been aborted by err_tcp (since this is not a normal closing + procedure). + + 2011-03-13: Simon Goldschmidt + * tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind + with pcb->state != CLOSED + + 2011-02-17: Simon Goldschmidt + * rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in + documentation + + 2011-02-17: Simon Goldschmidt + * many files: Added missing U/UL modifiers to fix 16-bit-arch portability. + + 2011-01-24: Simon Goldschmidt + * sockets.c: Fixed bug #31741: lwip_select seems to have threading problems + + 2010-12-02: Simon Goldschmidt + * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal. + + 2010-11-23: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for + LWIP_SO_RCVBUF and ioctl/FIONREAD. + + 2010-11-23: Simon Goldschmidt + * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at + least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet. + + 2010-11-23: Simon Goldschmidt + * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after + refusing 'refused_data' again. + + 2010-11-22: Simon Goldschmidt + * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS + after a successful nonblocking connection. + + 2010-11-22: Simon Goldschmidt + * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr + must be sent link-local + + 2010-11-22: Simon Goldschmidt + * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for + LWIP_TIMERS==0 + + 2010-11-20: Simon Goldschmidt + * sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number + + 2010-11-20: Simon Goldschmidt + * sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to + resemble other stacks. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else + no-copy TCP writes will never succeed. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does + not match documentation: return ERR_ARG instead of ERR_VAL if not + initialized or wrong argument. + + 2010-10-20: Simon Goldschmidt + * sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16 + + 2010-10-05: Simon Goldschmidt + * dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when + replugging the network cable after an AutoIP address was assigned. + + 2010-08-10: Simon Goldschmidt + * tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs + + 2010-08-03: Simon Goldschmidt + * udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625) + + 2010-08-01: Simon Goldschmidt (patch by Greg Renda) + * ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big + endian architectures) + + 2010-07-28: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP + disabled. + + 2010-07-27: Simon Goldschmidt + * tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no + harm but never did anything + + 2010-07-21: Simon Goldschmidt + * ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not + add IP options) + + 2010-07-16: Kieran Mansley + * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator + + 2010-07-10: Simon Goldschmidt + * ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options + + 2010-06-30: Simon Goldschmidt + * api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in + netconn_delete) + + 2010-06-28: Kieran Mansley + * timers.c remove unportable printing of C function pointers + + 2010-06-24: Simon Goldschmidt + * init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag + NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading + + 2010-06-24: Simon Goldschmidt + * api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly + implemented shutdown at socket level. + + 2010-06-21: Simon Goldschmidt + * pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has + problems with zero-copy DMA MACs) by adding custom pbufs and implementing + custom pbufs that reference other (original) pbufs. Additionally set + IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side. + + 2010-06-15: Simon Goldschmidt + * dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses + + 2010-06-14: Simon Goldschmidt + * autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses + + 2010-06-12: Simon Goldschmidt + * dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop + state + + 2010-05-17: Simon Goldschmidt + * netdb.c: Correctly NULL-terminate h_addr_list + + 2010-05-16: Simon Goldschmidt + * def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent + "symbol already defined" i.e. when linking to winsock + + 2010-05-05: Simon Goldschmidt + * def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may + overflow) + + 2010-04-21: Simon Goldschmidt + * api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening + connection) + + 2010-03-28: Luca Ceresoli + * ip_addr.c/.h: patch #7143: Add a few missing const qualifiers + + 2010-03-27: Luca Ceresoli + * mib2.c: patch #7130: remove meaningless const qualifiers + + 2010-03-26: Simon Goldschmidt + * tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too + + 2010-03-26: Simon Goldschmidt + * various files: Fixed compiling with different options disabled (TCP/UDP), + triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled + + 2010-03-25: Simon Goldschmidt + * sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly + + 2010-03-25: Simon Goldschmidt + * tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side + overrunning our rcv_wnd in ooseq case. + + 2010-03-22: Simon Goldschmidt + * tcp.c: tcp_listen() did not copy the pcb's prio. + + 2010-03-19: Simon Goldschmidt + * snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set + + 2010-03-14: Simon Goldschmidt + * opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports + where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h + and basing PBUF_LINK_HLEN on it. + + 2010-03-08: Simon Goldschmidt + * netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections + when assiging routable address): when checking incoming packets and + aborting existing connection on address change, filter out link-local + addresses. + + 2010-03-06: Simon Goldschmidt + * sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING + + 2010-03-06: Simon Goldschmidt + * ipv4/ip.c: Don't try to forward link-local addresses + + 2010-03-06: Simon Goldschmidt + * etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal- + addresses to gw + + 2010-03-05: Simon Goldschmidt + * dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type + and state. + + 2010-03-05: Simon Goldschmidt + * api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split + into multiple calls to tcp_write. + + 2010-02-21: Simon Goldschmidt + * opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep + the implementation of DNS_USES_STATIC_BUF==1) + + 2010-02-20: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement + close() vs. shutdown(). Now the application does not get any more + recv callbacks after calling tcp_close(). Added tcp_shutdown(). + + 2010-02-19: Simon Goldschmidt + * mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent + confusion with realloc() + + 2010-02-15: Simon Goldschmidt/Stephane Lesage + * netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK + (fixes bug #28899) + + 2010-02-14: Simon Goldschmidt + * netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with + LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and + admin-status of a netif are up + + 2010-02-14: Simon Goldschmidt + * opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet + reception and is not really necessary + + 2010-02-14: Simon Goldschmidt + * etharp.c/.h: Fixed ARP input processing: only add a new entry if a + request was directed as us (RFC 826, Packet Reception), otherwise + only update existing entries; internalized some functions + + 2010-02-14: Simon Goldschmidt + * netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be + disabled on netif used for PPPoE) by adding a new netif flag + (NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet + device but prevents usage of ARP (so that ethernet_input can be used + for PPPoE). + + 2010-02-12: Simon Goldschmidt + * netif.c: netif_set_link_up/down: only do something if the link state + actually changes + + 2010-02-12: Simon Goldschmidt/Stephane Lesage + * api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking + connect) + + 2010-02-12: Simon Goldschmidt + * mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h) + + 2010-02-09: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110 + (recv() makes receive window update for data that wasn't received by + application) + + 2010-02-09: Simon Goldschmidt/Stephane Lesage + * sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out + or any netconn_recv() error) + + 2010-02-09: Simon Goldschmidt + * ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets) + + 2010-02-09: Simon Goldschmidt + * netif.c: For loopback packets, adjust the stats- and snmp-counters + for the loopback netif. + + 2010-02-08: Simon Goldschmidt + * igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity + since they are not used anywhere else. + + 2010-02-08: Simon Goldschmidt (Stéphane Lesage) + * igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats + (patch from bug #28798) + + 2010-02-08: Simon Goldschmidt (Stéphane Lesage) + * igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and + another bug when LWIP_RAND() returns zero. + + 2010-02-04: Simon Goldschmidt + * nearly every file: Use macros defined in ip_addr.h (some of them new) + to work with IP addresses (preparation for bug #27352 - Change ip_addr + from struct to typedef (u32_t) - and better code). + + 2010-01-31: Simon Goldschmidt + * netif.c: Don't call the link-callback from netif_set_up/down() since + this invalidly retriggers DHCP. + + 2010-01-29: Simon Goldschmidt + * ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the + portability file inet.h and its contents from the stack: moved htonX- + functions to def.h (and the new def.c - they are not ipv4 dependent), + let inet.h depend on ip_addr.h and not the other way round. + This fixes bug #28732. + + 2010-01-28: Kieran Mansley + * tcp.c: Ensure ssthresh >= 2*MSS + + 2010-01-27: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv + callback can lead to accessing unallocated memory. As a consequence, + ERR_ABRT means the application has called tcp_abort()! + + 2010-01-25: Simon Goldschmidt + * snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY + not implemented in SNMP): write-only or not-accessible are still + returned by getnext (though not by get) + + 2010-01-24: Simon Goldschmidt + * snmp: Renamed the private mib node from 'private' to 'mib_private' to + not use reserved C/C++ keywords + + 2010-01-23: Simon Goldschmidt + * sockets.c: Fixed bug #28716: select() returns 0 after waiting for less + than 1 ms + + 2010-01-21: Simon Goldschmidt + * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called + if tcp_enqueue fails) both in raw- and netconn-API + + 2010-01-19: Simon Goldschmidt + * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp + + 2010-01-18: Iordan Neshev/Simon Goldschmidt + * src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some + bugfix backports from 2.4.x. + + 2010-01-18: Simon Goldschmidt + * mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong + + 2010-01-17: Simon Goldschmidt + * api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c): + task #10102: "netconn: clean up conn->err threading issues" by adding + error return value to struct api_msg_msg + + 2010-01-17: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept() + to return err_t (bugs #27709 and #28087) + + 2010-01-14: Simon Goldschmidt + * ...: Use typedef for function prototypes throughout the stack. + + 2010-01-13: Simon Goldschmidt + * api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive + window = 0) by correctly draining recvmbox/acceptmbox + + 2010-01-11: Simon Goldschmidt + * pap.c: Fixed bug #13315 (PPP PAP authentication can result in + erroneous callbacks) by copying the code from recent pppd + + 2010-01-10: Simon Goldschmidt + * raw.c: Fixed bug #28506 (raw_bind should filter received packets) + + 2010-01-10: Simon Goldschmidt + * tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)()) + + 2010-01-08: Simon Goldschmidt + * sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535) + + 2010-01-08: Simon Goldschmidt + * dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string + passed to dns_local_addhost() might be volatile + + 2010-01-07: Simon Goldschmidt + * timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too + + 2010-01-06: Simon Goldschmidt + * netdb.h: Fixed bug #28496: missing include guards in netdb.h + + 2009-12-31: Simon Goldschmidt + * many ppp files: Reorganised PPP source code from ucip structure to pppd + structure to easily compare our code against the pppd code (around v2.3.1) + + 2009-12-27: Simon Goldschmidt + * tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted + unit test + + +(STABLE-1.3.2) + + ++ New features: + + 2009-10-27 Simon Goldschmidt/Stephan Lesage + * netifapi.c/.h: Added netifapi_netif_set_addr() + + 2009-10-07 Simon Goldschmidt/Fabian Koch + * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to + support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO) + + 2009-08-26 Simon Goldschmidt/Simon Kallweit + * slipif.c/.h: bug #26397: SLIP polling support + + 2009-08-25 Simon Goldschmidt + * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN), + New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK. + + 2009-08-25 Simon Goldschmidt + * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*) + + 2009-08-24 Jakob Stoklund Olesen + * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond + to netif_set_link_up(). + + 2009-08-23 Simon Goldschmidt + * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state + to a human-readable string. + + ++ Bugfixes: + + 2009-12-24: Kieran Mansley + * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing + (BUG#28241) + + 2009-12-06: Simon Goldschmidt + * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can + be statically allocated (like in ucip) + + 2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev) + * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT + + 2009-12-03: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit + could have non-zero length + + 2009-12-02: Simon Goldschmidt + * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting + tcp_input_pcb until after calling the pcb's callbacks + + 2009-11-29: Simon Goldschmidt + * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of- + sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code + + 2009-11-29: Simon Goldschmidt + * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by + queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty + + 2009-11-26: Simon Goldschmidt + * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending + segment + + 2009-11-26: Simon Goldschmidt + * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle + algorithm at PCB level + + 2009-11-22: Simon Goldschmidt + * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent + + 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach) + * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when + reusing time-wait pcb + + 2009-11-20: Simon Goldschmidt (patch by Albert Bartel) + * sockets.c: Fixed bug #28062: Data received directly after accepting + does not wake up select + + 2009-11-11: Simon Goldschmidt + * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo) + + 2009-10-30: Simon Goldschmidt + * opt.h: Increased default value for TCP_MSS to 536, updated default + value for TCP_WND to 4*TCP_MSS to keep delayed ACK working. + + 2009-10-28: Kieran Mansley + * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code + to follow algorithm from TCP/IP Illustrated + + 2009-10-27: Kieran Mansley + * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK + + 2009-10-25: Simon Goldschmidt + * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if + pcb->recv is NULL to keep rcv_wnd correct) + + 2009-10-25: Simon Goldschmidt + * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state + + 2009-10-23: Simon Goldschmidt (David Empson) + * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes + + 2009-10-21: Simon Goldschmidt + * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and + trailing 1 byte len (SYN/FIN) + + 2009-10-21: Simon Goldschmidt + * tcp_out.c: Fixed bug #27315: zero window probe and FIN + + 2009-10-19: Simon Goldschmidt + * dhcp.c/.h: Minor code simplification (don't store received pbuf, change + conditional code to assert where applicable), check pbuf length before + testing for valid reply + + 2009-10-19: Simon Goldschmidt + * dhcp.c: Removed most calls to udp_connect since they aren't necessary + when using udp_sendto_if() - always stay connected to IP_ADDR_ANY. + + 2009-10-16: Simon Goldschmidt + * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop + valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is + enabled + + 2009-10-15: Simon Goldschmidt (Oleg Tyshev) + * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit + + 2009-10-15: Simon Goldschmidt + * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv() + timeout + + 2009-10-15: Simon Goldschmidt + * autoip.c: Fixed bug #27704: autoip starts with wrong address + LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead + of network byte order + + 2009-10-11 Simon Goldschmidt (Jörg Kesten) + * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments + which are not consecutive when retransmitting unacked segments + + 2009-10-09 Simon Goldschmidt + * opt.h: Fixed default values of some stats to only be enabled if used + Fixes bug #27338: sys_stats is defined when NO_SYS = 1 + + 2009-08-30 Simon Goldschmidt + * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK + function" by checking for loopback before calling ip_frag + + 2009-08-25 Simon Goldschmidt + * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0 + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27078: Possible memory leak in pppInit() + + 2009-08-23 Simon Goldschmidt + * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result + is error. + + 2009-08-23 Simon Goldschmidt + * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF + Fixed wrong parenthesis, added check in init.c + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms + + 2009-08-23 Simon Goldschmidt + * many ppp files: bug #27267: Added include to string.h where needed + + 2009-08-23 Simon Goldschmidt + * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian) + + +(STABLE-1.3.1) + + ++ New features: + + 2009-05-10 Simon Goldschmidt + * opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option + LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only + one pbuf to help MACs that don't support scatter-gather DMA. + + 2009-05-09 Simon Goldschmidt + * icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming + ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + + 2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen + * ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive + extended info about the currently received packet. + + 2009-04-27 Simon Goldschmidt + * sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1 + + 2009-04-25 Simon Goldschmidt + * mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next + bigger malloc pool if one is empty (only usable with MEM_USE_POOLS). + + 2009-04-21 Simon Goldschmidt + * dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static + hosts table. New configuration options DNS_LOCAL_HOSTLIST and + DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined + as an external function for lookup. + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for + TCP timestamp options, off by default. Rework tcp_enqueue() to + take option flags rather than specified option data + + 2009-02-18 Simon Goldschmidt + * cc.h: Added printf formatter for size_t: SZT_F + + 2009-02-16 Simon Goldschmidt (patch by Rishi Khan) + * icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast + pings + + 2009-02-12 Simon Goldschmidt + * init.h: Added LWIP_VERSION to get the current version of the stack + + 2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler) + * opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead + of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc + is otherwise used) + + 2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach) + * ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial() + is only used by UDPLITE at present, so conditionalise it. + + 2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli) + * autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP + "seed" address. This should reduce AUTOIP conflicts if + LWIP_AUTOIP_CREATE_SEED_ADDR is overridden. + + 2008-10-02 Jonathan Larmour and Rishi Khan + * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking + socket. + + 2008-06-30 Simon Goldschmidt + * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from + interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows + mem_free to run between mem_malloc iterations. Added illegal counter for + mem stats. + + 2008-06-27 Simon Goldschmidt + * stats.h/.c, some other files: patch #6483: stats module improvement: + Added defines to display each module's statistic individually, added stats + defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter. + + 2008-06-17 Simon Goldschmidt + * err.h: patch #6459: Made err_t overridable to use a more efficient type + (define LWIP_ERR_T in cc.h) + + 2008-06-17 Simon Goldschmidt + * slipif.c: patch #6480: Added a configuration option for slipif for symmetry + to loopif + + 2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli) + * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly + modified version of patch # 6370: Moved loopif code to netif.c so that + loopback traffic is supported on all netifs (all local IPs). + Added option to limit loopback packets for each netifs. + + + ++ Bugfixes: + 2009-08-12 Kieran Mansley + * tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when + out of window or out of order properly + + 2009-08-12 Kieran Mansley + * tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1 + + 2009-07-28 Simon Goldschmidt + * mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s + + 2009-07-27 Kieran Mansley + * api.h api_msg.h netdb.h sockets.h: add missing #include directives + + 2009-07-09 Kieran Mansley + * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for + recv_avail and don't increment counters until message successfully + sent to mbox + + 2009-06-25 Kieran Mansley + * api_msg.c api.h: BUG26722: initialise netconn write variables + in netconn_alloc + + 2009-06-25 Kieran Mansley + * tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set + + 2009-06-25 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct + simultaneous close behaviour, and make snd_nxt have the same meaning + as in the RFCs. + + 2009-05-12 Simon Goldschmidt + * etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on + arp_table / uses etharp_query" by adding etharp_gratuitous() + + 2009-05-12 Simon Goldschmidt + * ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options + to the IP header (used by igmp_ip_output_if) + + 2009-05-06 Simon Goldschmidt + * inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if + defined) for SWAP_BYTES_IN_WORD to speed up checksumming. + + 2009-05-05 Simon Goldschmidt + * sockets.c: bug #26405: Prematurely released semaphore causes lwip_select() + to crash + + 2009-05-04 Simon Goldschmidt + * init.c: snmp was not initialized in lwip_init() + + 2009-05-04 Frédéric Bernon + * dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled. + + 2009-05-03 Simon Goldschmidt + * tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full + (and unsent->next == NULL) + + 2009-05-02 Simon Goldschmidt + * tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after + 1.3.0 in CVS only) - fixes compilation of ppp_oe.c + + 2009-05-02 Simon Goldschmidt + * msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields + + 2009-05-01 Simon Goldschmidt + * pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets + + 2009-05-01 Simon Goldschmidt + * ppp.c: bug #24228: Memory corruption with PPP and DHCP + + 2009-04-29 Frédéric Bernon + * raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the + SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception + of broadcast packets even when this option wasn't set. Port maintainers + which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h. + If you want this option also filter broadcast on recv operations, you also + have to set IP_SOF_BROADCAST_RECV=1 in opt.h. + + 2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen + * dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and + DHCP/AUTOIP cooperation + + 2009-04-25 Simon Goldschmidt, Oleg Tyshev + * tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd + Fixed by sorting the unsent and unacked queues (segments are inserted at the + right place in tcp_output and tcp_rexmit). + + 2009-04-25 Simon Goldschmidt + * memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation + when debugging": memp_sizes contained the wrong sizes (including sanity + regions); memp pools for MEM_USE_POOLS were too small + + 2009-04-24 Simon Goldschmidt, Frédéric Bernon + * inet.c: patch #6765: Fix a small problem with the last changes (incorrect + behavior, with with ip address string not ended by a '\0', a space or a + end of line) + + 2009-04-19 Simon Goldschmidt + * rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails, + pcb->err is called, not pcb->connected (with an error code). + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with + no-copy-tcpwrite": deallocate option data, only concat segments with same flags + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated + in the header pbuf, not the data pbuf) + + 2009-04-18 Simon Goldschmidt + * api_msg.c: fixed bug #25695: Segmentation fault in do_writemore() + + 2009-04-15 Simon Goldschmidt + * sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp + + 2009-04-15 Simon Goldschmidt + * dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in + + 2009-04-15 Simon Goldschmidt + * ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function + ip_hinted_output() (for smaller code mainly) + + 2009-04-15 Simon Goldschmidt + * inet.c: patch #6765: Supporting new line characters in inet_aton() + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option; + Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu + is big enough in dhcp_start + + 2009-04-15 Simon Goldschmidt + * netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak + + 2009-04-15 Simon Goldschmidt + * sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY + + 2009-04-15 Simon Goldschmidt + * sockets.c: bug #26121: set_errno can be overridden + + 2009-04-09 Kieran Mansley (patch from Luca Ceresoli ) + * init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when + LWIP_TCP==0 + + 2009-04-09 Kieran Mansley (patch from Roy Lee ) + * tcp.h: Patch#6802 Add do-while-clauses to those function like + macros in tcp.h + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window + updates are calculated and sent (BUG20515) + + * tcp_in.c: cope with SYN packets received during established states, + and retransmission of initial SYN. + + * tcp_out.c: set push bit correctly when tcp segments are merged + + 2009-03-27 Kieran Mansley + * tcp_out.c set window correctly on probes (correcting change made + yesterday) + + 2009-03-26 Kieran Mansley + * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping + connections where no reset required (bug #25622) + + * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes + (bug #20779) + + 2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach) + * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be + too small depending on MEM_ALIGNMENT + + 2009-02-16 Simon Goldschmidt + * sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard; + converted size argument of netconn_write to 'size_t' + + 2009-02-16 Simon Goldschmidt + * tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host + by moving accept callback function pointer to TCP_PCB_COMMON + + 2009-02-12 Simon Goldschmidt + * dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size" + option) + + 2009-02-11 Simon Goldschmidt + * dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start) + + 2009-02-11 Simon Goldschmidt + * opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize: + RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv()) + + 2009-02-10 Simon Goldschmidt + * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD: + Accepts_pending is decrease on a corresponding listen pcb when a connection + in state SYN_RCVD is close. + + 2009-01-28 Jonathan Larmour + * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run + out of pool pbufs. + + 2008-12-19 Simon Goldschmidt + * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 + + 2008-12-10 Tamas Somogyi, Frédéric Bernon + * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and + port uses deleted netbuf. + + 2008-10-18 Simon Goldschmidt + * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length + in tcp_parseopt + + 2008-10-15 Simon Goldschmidt + * ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers + by packing the struct ip_reass_helper. + + 2008-10-03 David Woodhouse, Jonathan Larmour + * etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address. + + 2008-10-02 Jonathan Larmour + * dns.c: Hard-code structure sizes, to avoid issues on some compilers where + padding is included. + + 2008-09-30 Jonathan Larmour + * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an + assertion check that addrlen isn't NULL. + + 2008-09-30 Jonathan Larmour + * tcp.c: Fix bug #24227, wrong error message in tcp_bind. + + 2008-08-26 Simon Goldschmidt + * inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and + inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h + + 2008-08-14 Simon Goldschmidt + * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when + tcp_close returns != ERR_OK) + + 2008-07-08 Frédéric Bernon + * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters + in macros, mainly if MEM_STATS=0 and MEMP_STATS=0). + + 2008-06-24 Jonathan Larmour + * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused + if tcp_seg_copy fails. + + 2008-06-17 Simon Goldschmidt + * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations) + and created defines for swapping bytes and folding u32 to u16. + + 2008-05-30 Kieran Mansley + * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd + rather than rcv_ann_wnd when deciding if packets are in-window. + Contributed by + + 2008-05-30 Kieran Mansley + * mem.h: Fix BUG#23254. Change macro definition of mem_* to allow + passing as function pointers when MEM_LIBC_MALLOC is defined. + + 2008-05-09 Jonathan Larmour + * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to + stop it being treated as a fatal error. + + 2008-04-15 Simon Goldschmidt + * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP + (flag now cleared) + + 2008-03-27 Simon Goldschmidt + * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free + from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1 + in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs + or heap memory from interrupt context + + 2008-03-26 Simon Goldschmidt + * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote + host sent a zero mss as TCP option. + + +(STABLE-1.3.0) + + ++ New features: + + 2008-03-10 Jonathan Larmour + * inet_chksum.c: Allow choice of one of the sample algorithms to be + made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM. + + 2008-01-22 Frédéric Bernon + * tcp.c, tcp_in.c, tcp.h, opt.h: Rename LWIP_CALCULATE_EFF_SEND_MSS in + TCP_CALCULATE_EFF_SEND_MSS to have coherent TCP options names. + + 2008-01-14 Frédéric Bernon + * rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable + to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the + tcp_recv callback (see rawapi.txt). + + 2008-01-14 Frédéric Bernon, Marc Chaland + * ip.c: Integrate patch #6369" ip_input : checking before realloc". + + 2008-01-12 Frédéric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::sem per netconn::op_completed like suggested for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-12 Frédéric Bernon + * api_msg.c, opt.h: replace DEFAULT_RECVMBOX_SIZE per DEFAULT_TCP_RECVMBOX_SIZE, + DEFAULT_UDP_RECVMBOX_SIZE and DEFAULT_RAW_RECVMBOX_SIZE (to optimize queues + sizes), like suggested for the task #7490 "Add return value to sys_mbox_post". + + 2008-01-10 Frédéric Bernon + * tcpip.h, tcpip.c: add tcpip_callback_with_block function for the task #7490 + "Add return value to sys_mbox_post". tcpip_callback is always defined as + "blocking" ("block" parameter = 1). + + 2008-01-10 Frédéric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::mbox (sys_mbox_t) per netconn::sem (sys_sem_t) for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-05 Frédéric Bernon + * sys_arch.txt, api.h, api_lib.c, api_msg.h, api_msg.c, tcpip.c, sys.h, opt.h: + Introduce changes for task #7490 "Add return value to sys_mbox_post" with some + modifications in the sys_mbox api: sys_mbox_new take a "size" parameters which + indicate the number of pointers query by the mailbox. There is three defines + in opt.h to indicate sizes for tcpip::mbox, netconn::recvmbox, and for the + netconn::acceptmbox. Port maintainers, you can decide to just add this new + parameter in your implementation, but to ignore it to keep the previous behavior. + The new sys_mbox_trypost function return a value to know if the mailbox is + full or if the message is posted. Take a look to sys_arch.txt for more details. + This new function is used in tcpip_input (so, can be called in an interrupt + context since the function is not blocking), and in recv_udp and recv_raw. + + 2008-01-04 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour + * rawapi.txt, api.h, api_lib.c, api_msg.h, api_msg.c, sockets.c, tcp.h, tcp.c, + tcp_in.c, init.c, opt.h: rename backlog options with TCP_ prefix, limit the + "backlog" parameter in an u8_t, 0 is interpreted as "smallest queue", add + documentation in the rawapi.txt file. + + 2007-12-31 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Add TCP persist timer + + 2007-12-31 Frédéric Bernon, Luca Ceresoli + * autoip.c, etharp.c: ip_addr.h: Integrate patch #6348: "Broadcast ARP packets + in autoip". The change in etharp_raw could be removed, since all calls to + etharp_raw use ethbroadcast for the "ethdst_addr" parameter. But it could be + wrong in the future. + + 2007-12-30 Frédéric Bernon, Tom Evans + * ip.c: Fix bug #21846 "LwIP doesn't appear to perform any IP Source Address + Filtering" reported by Tom Evans. + + 2007-12-21 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour + * tcp.h, opt.h, api.h, api_msg.h, tcp.c, tcp_in.c, api_lib.c, api_msg.c, + sockets.c, init.c: task #7252: Implement TCP listen backlog: Warning: raw API + applications have to call 'tcp_accepted(pcb)' in their accept callback to + keep accepting new connections. + + 2007-12-13 Frédéric Bernon + * api_msg.c, err.h, err.c, sockets.c, dns.c, dns.h: replace "enum dns_result" + by err_t type. Add a new err_t code "ERR_INPROGRESS". + + 2007-12-12 Frédéric Bernon + * dns.h, dns.c, opt.h: move DNS options to the "right" place. Most visibles + are the one which have ram usage. + + 2007-12-05 Frédéric Bernon + * netdb.c: add a LWIP_DNS_API_HOSTENT_STORAGE option to decide to use a static + set of variables (=0) or a local one (=1). In this last case, your port should + provide a function "struct hostent* sys_thread_hostent( struct hostent* h)" + which have to do a copy of "h" and return a pointer ont the "per-thread" copy. + + 2007-12-03 Simon Goldschmidt + * ip.c: ip_input: check if a packet is for inp first before checking all other + netifs on netif_list (speeds up packet receiving in most cases) + + 2007-11-30 Simon Goldschmidt + * udp.c, raw.c: task #7497: Sort lists (pcb, netif, ...) for faster access + UDP: move a (connected) pcb selected for input to the front of the list of + pcbs so that it is found faster next time. Same for RAW pcbs that have eaten + a packet. + + 2007-11-28 Simon Goldschmidt + * etharp.c, stats.c, stats.h, opt.h: Introduced ETHARP_STATS + + 2007-11-25 Simon Goldschmidt + * dhcp.c: dhcp_unfold_reply() uses pbuf_copy_partial instead of its own copy + algorithm. + + 2007-11-24 Simon Goldschmidt + * netdb.h, netdb.c, sockets.h/.c: Moved lwip_gethostbyname from sockets.c + to the new file netdb.c; included lwip_getaddrinfo. + + 2007-11-21 Simon Goldschmidt + * tcp.h, opt.h, tcp.c, tcp_in.c: implemented calculating the effective send-mss + based on the MTU of the netif used to send. Enabled by default. Disable by + setting LWIP_CALCULATE_EFF_SEND_MSS to 0. This fixes bug #21492. + + 2007-11-19 Frédéric Bernon + * api_msg.c, dns.h, dns.c: Implement DNS_DOES_NAME_CHECK option (check if name + received match the name query), implement DNS_USES_STATIC_BUF (the place where + copy dns payload to parse the response), return an error if there is no place + for a new query, and fix some minor problems. + + 2007-11-16 Simon Goldschmidt + * new files: ipv4/inet.c, ipv4/inet_chksum.c, ipv6/inet6.c + removed files: core/inet.c, core/inet6.c + Moved inet files into ipv4/ipv6 directory; splitted inet.c/inet.h into + inet and chksum part; changed includes in all lwIP files as appropriate + + 2007-11-16 Simon Goldschmidt + * api.h, api_msg.h, api_lib.c, api_msg.c, socket.h, socket.c: Added sequential + dns resolver function for netconn api (netconn_gethostbyname) and socket api + (gethostbyname/gethostbyname_r). + + 2007-11-15 Jim Pettinato, Frédéric Bernon + * opt.h, init.c, tcpip.c, dhcp.c, dns.h, dns.c: add DNS client for simple name + requests with RAW api interface. Initialization is done in lwip_init() with + build time options. DNS timer is added in tcpip_thread context. DHCP can set + DNS server ip addresses when options are received. You need to set LWIP_DNS=1 + in your lwipopts.h file (LWIP_DNS=0 in opt.h). DNS_DEBUG can be set to get + some traces with LWIP_DEBUGF. Sanity check have been added. There is a "todo" + list with points to improve. + + 2007-11-06 Simon Goldschmidt + * opt.h, mib2.c: Patch #6215: added ifAdminStatus write support (if explicitly + enabled by defining SNMP_SAFE_REQUESTS to 0); added code to check link status + for ifOperStatus if LWIP_NETIF_LINK_CALLBACK is defined. + + 2007-11-06 Simon Goldschmidt + * api.h, api_msg.h and dependent files: Task #7410: Removed the need to include + core header files in api.h (ip/tcp/udp/raw.h) to hide the internal + implementation from netconn api applications. + + 2007-11-03 Frédéric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c, opt.h: add SO_RCVBUF option for UDP & + RAW netconn. You need to set LWIP_SO_RCVBUF=1 in your lwipopts.h (it's disabled + by default). Netconn API users can use the netconn_recv_bufsize macro to access + it. This is a first release which have to be improve for TCP. Note it used the + netconn::recv_avail which need to be more "thread-safe" (note there is already + the problem for FIONREAD with lwip_ioctl/ioctlsocket). + + 2007-11-01 Frédéric Bernon, Marc Chaland + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, tcp.h, tcp_out.c: + Integrate "patch #6250 : MSG_MORE flag for send". MSG_MORE is used at socket api + layer, NETCONN_MORE at netconn api layer, and TCP_WRITE_FLAG_MORE at raw api + layer. This option enable to delayed TCP PUSH flag on multiple "write" calls. + Note that previous "copy" parameter for "write" APIs is now called "apiflags". + + 2007-10-24 Frédéric Bernon + * api.h, api_lib.c, api_msg.c: Add macro API_EVENT in the same spirit than + TCP_EVENT_xxx macros to get a code more readable. It could also help to remove + some code (like we have talk in "patch #5919 : Create compile switch to remove + select code"), but it could be done later. + + 2007-10-08 Simon Goldschmidt + * many files: Changed initialization: many init functions are not needed any + more since we now rely on the compiler initializing global and static + variables to zero! + + 2007-10-06 Simon Goldschmidt + * ip_frag.c, memp.c, mib2.c, ip_frag.h, memp_std.h, opt.h: Changed IP_REASSEMBLY + to enqueue the received pbufs so that multiple packets can be reassembled + simultaneously and no static reassembly buffer is needed. + + 2007-10-05 Simon Goldschmidt + * tcpip.c, etharp.h, etharp.c: moved ethernet_input from tcpip.c to etharp.c so + all netifs (or ports) can use it. + + 2007-10-05 Frédéric Bernon + * netifapi.h, netifapi.c: add function netifapi_netif_set_default. Change the + common function to reduce a little bit the footprint (for all functions using + only the "netif" parameter). + + 2007-10-03 Frédéric Bernon + * netifapi.h, netifapi.c: add functions netifapi_netif_set_up, netifapi_netif_set_down, + netifapi_autoip_start and netifapi_autoip_stop. Use a common function to reduce + a little bit the footprint (for all functions using only the "netif" parameter). + + 2007-09-15 Frédéric Bernon + * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF + option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for + netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for + IP_MULTICAST_TTL and IP_MULTICAST_IF. + + 2007-09-10 Frédéric Bernon + * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles + even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime() + each 10ms (but, it's intrusive if you use sys_timeout feature). Now, you can + decide to call snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but + call to a lower frequency). Or, you can decide to not call snmp_inc_sysuptime() + or snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. + This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside + snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only + when it's queried (any direct call to "sysuptime" is changed by a call to + snmp_get_sysuptime). + + 2007-09-09 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, + and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags + if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). + igmp_report_groups() is now called inside netif_set_link_up() (need to have + LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait + the next query message to receive the matching multicast streams). + + 2007-09-08 Frédéric Bernon + * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains + IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change). + Use this new field to access to common pcb fields (ttl, tos, so_options, etc...). + Enable to access to these fields with LWIP_TCP=0. + + 2007-09-05 Frédéric Bernon + * udp.c, ipv4/icmp.c, ipv4/ip.c, ipv6/icmp.c, ipv6/ip6.c, ipv4/icmp.h, + ipv6/icmp.h, opt.h: Integrate "task #7272 : LWIP_ICMP option". The new option + LWIP_ICMP enable/disable ICMP module inside the IP stack (enable per default). + Be careful, disabling ICMP make your product non-compliant to RFC1122, but + help to reduce footprint, and to reduce "visibility" on the Internet. + + 2007-09-05 Frédéric Bernon, Bill Florac + * opt.h, sys.h, tcpip.c, slipif.c, ppp.c, sys_arch.txt: Change parameters list + for sys_thread_new (see "task #7252 : Create sys_thread_new_ex()"). Two new + parameters have to be provided: a task name, and a task stack size. For this + one, since it's platform dependant, you could define the best one for you in + your lwipopts.h. For port maintainers, you can just add these new parameters + in your sys_arch.c file, and but it's not mandatory, use them in your OS + specific functions. + + 2007-09-05 Frédéric Bernon + * inet.c, autoip.c, msg_in.c, msg_out.c, init.c: Move some build time checkings + inside init.c for task #7142 "Sanity check user-configurable values". + + 2007-09-04 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, memp_std.h, memp.c, init.c, opt.h: Replace mem_malloc call by + memp_malloc, and use a new MEMP_NUM_IGMP_GROUP option (see opt.h to define the + value). It will avoid potential fragmentation problems, use a counter to know + how many times a group is used on an netif, and free it when all applications + leave it. MEMP_NUM_IGMP_GROUP got 8 as default value (and init.c got a sanity + check if LWIP_IGMP!=0). + + 2007-09-03 Frédéric Bernon + * igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement". + Initialize igmp_mac_filter to NULL in netif_add (this field should be set in + the netif's "init" function). Use the "imr_interface" field (for socket layer) + and/or the "interface" field (for netconn layer), for join/leave operations. + The igmp_join/leavegroup first parameter change from a netif to an ipaddr. + This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany). + + 2007-08-30 Frédéric Bernon + * Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions + from api/api_lib". Now netbuf API is independant of netconn, and can be used + with other API (application based on raw API, or future "socket2" API). Ports + maintainers just have to add src/api/netbuf.c in their makefile/projects. + + 2007-08-30 Frédéric Bernon, Jonathan Larmour + * init.c: Add first version of lwip_sanity_check for task #7142 "Sanity check + user-configurable values". + + 2007-08-29 Frédéric Bernon + * igmp.h, igmp.c, tcpip.c, init.c, netif.c: change igmp_init and add igmp_start. + igmp_start is call inside netif_add. Now, igmp initialization is in the same + spirit than the others modules. Modify some IGMP debug traces. + + 2007-08-29 Frédéric Bernon + * Add init.h, init.c, Change opt.h, tcpip.c: Task #7213 "Add a lwip_init function" + Add lwip_init function to regroup all modules initializations, and to provide + a place to add code for task #7142 "Sanity check user-configurable values". + Ports maintainers should remove direct initializations calls from their code, + and add init.c in their makefiles. Note that lwip_init() function is called + inside tcpip_init, but can also be used by raw api users since all calls are + disabled when matching options are disabled. Also note that their is new options + in opt.h, you should configure in your lwipopts.h (they are enabled per default). + + 2007-08-26 Marc Boucher + * api_msg.c: do_close_internal(): Reset the callbacks and arg (conn) to NULL + since they can under certain circumstances be called with an invalid conn + pointer after the connection has been closed (and conn has been freed). + + 2007-08-25 Frédéric Bernon (Artem Migaev's Patch) + * netif.h, netif.c: Integrate "patch #6163 : Function to check if link layer is up". + Add a netif_is_link_up() function if LWIP_NETIF_LINK_CALLBACK option is set. + + 2007-08-22 Frédéric Bernon + * netif.h, netif.c, opt.h: Rename LWIP_NETIF_CALLBACK in LWIP_NETIF_STATUS_CALLBACK + to be coherent with new LWIP_NETIF_LINK_CALLBACK option before next release. + + 2007-08-22 Frédéric Bernon + * tcpip.h, tcpip.c, ethernetif.c, opt.h: remove options ETHARP_TCPIP_INPUT & + ETHARP_TCPIP_ETHINPUT, now, only "ethinput" code is supported, even if the + name is tcpip_input (we keep the name of 1.2.0 function). + + 2007-08-17 Jared Grubb + * memp_std.h, memp.h, memp.c, mem.c, stats.c: (Task #7136) Centralize mempool + settings into new memp_std.h and optional user file lwippools.h. This adds + more dynamic mempools, and allows the user to create an arbitrary number of + mempools for mem_malloc. + + 2007-08-16 Marc Boucher + * api_msg.c: Initialize newconn->state to NETCONN_NONE in accept_function; + otherwise it was left to NETCONN_CLOSE and sent_tcp() could prematurely + close the connection. + + 2007-08-16 Marc Boucher + * sockets.c: lwip_accept(): check netconn_peer() error return. + + 2007-08-16 Marc Boucher + * mem.c, mem.h: Added mem_calloc(). + + 2007-08-16 Marc Boucher + * tcpip.c, tcpip.h memp.c, memp.h: Added distinct memp (MEMP_TCPIP_MSG_INPKT) + for input packets to prevent floods from consuming all of MEMP_TCPIP_MSG + and starving other message types. + Renamed MEMP_TCPIP_MSG to MEMP_TCPIP_MSG_API + + 2007-08-16 Marc Boucher + * pbuf.c, pbuf.h, etharp.c, tcp_in.c, sockets.c: Split pbuf flags in pbuf + type and flgs (later renamed to flags). + Use enum pbuf_flag as pbuf_type. Renumber PBUF_FLAG_*. + Improved lwip_recvfrom(). TCP push now propagated. + + 2007-08-16 Marc Boucher + * ethernetif.c, contrib/ports/various: ethbroadcast now a shared global + provided by etharp. + + 2007-08-16 Marc Boucher + * ppp_oe.c ppp_oe.h, auth.c chap.c fsm.c lcp.c ppp.c ppp.h, + etharp.c ethernetif.c, etharp.h, opt.h tcpip.h, tcpip.c: + Added PPPoE support and various PPP improvements. + + 2007-07-25 Simon Goldschmidt + * api_lib.c, ip_frag.c, pbuf.c, api.h, pbuf.h: Introduced pbuf_copy_partial, + making netbuf_copy_partial use this function. + + 2007-07-25 Simon Goldschmidt + * tcp_in.c: Fix bug #20506: Slow start / initial congestion window starts with + 2 * mss (instead of 1 * mss previously) to comply with some newer RFCs and + other stacks. + + 2007-07-13 Jared Grubb (integrated by Frédéric Bernon) + * opt.h, netif.h, netif.c, ethernetif.c: Add new configuration option to add + a link callback in the netif struct, and functions to handle it. Be carefull + for port maintainers to add the NETIF_FLAG_LINK_UP flag (like in ethernetif.c) + if you want to be sure to be compatible with future changes... + + 2007-06-30 Frédéric Bernon + * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions. + + 2007-06-21 Simon Goldschmidt + * etharp.h, etharp.c: Combined etharp_request with etharp_raw for both + LWIP_AUTOIP =0 and =1 to remove redundant code. + + 2007-06-21 Simon Goldschmidt + * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option + MEM_USE_POOLS to use 4 pools with different sized elements instead of a + heap. This both prevents memory fragmentation and gives a higher speed + at the cost of more memory consumption. Turned off by default. + + 2007-06-21 Simon Goldschmidt + * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of + netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into + int to be able to send a bigger buffer than 64K with one time (mainly + used from lwip_send). + + 2007-06-21 Simon Goldschmidt + * tcp.h, api_msg.c: Moved the nagle algorithm from netconn_write/do_write + into a define (tcp_output_nagle) in tcp.h to provide it to raw api users, too. + + 2007-06-21 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Fixed bug #20021: Moved sendbuf-processing in + netconn_write from api_lib.c to api_msg.c to also prevent multiple context- + changes on low memory or empty send-buffer. + + 2007-06-18 Simon Goldschmidt + * etharp.c, etharp.h: Changed etharp to use a defined hardware address length + of 6 to avoid loading netif->hwaddr_len every time (since this file is only + used for ethernet and struct eth_addr already had a defined length of 6). + + 2007-06-17 Simon Goldschmidt + * sockets.c, sockets.h: Implemented socket options SO_NO_CHECK for UDP sockets + to disable UDP checksum generation on transmit. + + 2007-06-13 Frédéric Bernon, Simon Goldschmidt + * debug.h, api_msg.c: change LWIP_ERROR to use it to check errors like invalid + pointers or parameters, and let the possibility to redefined it in cc.h. Use + this macro to check "conn" parameter in api_msg.c functions. + + 2007-06-11 Simon Goldschmidt + * sockets.c, sockets.h: Added UDP lite support for sockets + + 2007-06-10 Simon Goldschmidt + * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled + by default) to switch off UDP-Lite support if not needed (reduces udp.c code + size) + + 2007-06-09 Dominik Spies (integrated by Frédéric Bernon) + * autoip.h, autoip.c, dhcp.h, dhcp.c, netif.h, netif.c, etharp.h, etharp.c, opt.h: + AutoIP implementation available for IPv4, with new options LWIP_AUTOIP and + LWIP_DHCP_AUTOIP_COOP if you want to cooperate with DHCP. Some tips to adapt + (see TODO mark in the source code). + + 2007-06-09 Simon Goldschmidt + * etharp.h, etharp.c, ethernetif.c: Modified order of parameters for + etharp_output() to match netif->output so etharp_output() can be used + directly as netif->output to save one function call. + + 2007-06-08 Simon Goldschmidt + * netif.h, ethernetif.c, slipif.c, loopif.c: Added define + NETIF_INIT_SNMP(netif, type, speed) to initialize per-netif snmp variables, + added initialization of those to ethernetif, slipif and loopif. + + 2007-05-18 Simon Goldschmidt + * opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF + (defaulting to off for now) that can be set to 0 to send fragmented + packets by passing PBUF_REFs down the stack. + + 2007-05-23 Frédéric Bernon + * api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP + connections, such present in patch #5959. + + 2007-05-23 Frédéric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c: group the different NETCONN_UDPxxx + code in only one part... + + 2007-05-18 Simon Goldschmidt + * opt.h, memp.h, memp.c: Added option MEMP_OVERFLOW_CHECK to check for memp + elements to overflow. This is achieved by adding some bytes before and after + each pool element (increasing their size, of course), filling them with a + prominent value and checking them on freeing the element. + Set it to 2 to also check every element in every pool each time memp_malloc() + or memp_free() is called (slower but more helpful). + + 2007-05-10 Simon Goldschmidt + * opt.h, memp.h, memp.c, pbuf.c (see task #6831): use a new memp pool for + PBUF_POOL pbufs instead of the old pool implementation in pbuf.c to reduce + code size. + + 2007-05-11 Frédéric Bernon + * sockets.c, api_lib.c, api_msg.h, api_msg.c, netifapi.h, netifapi.c, tcpip.c: + Include a function pointer instead of a table index in the message to reduce + footprint. Disable some part of lwip_send and lwip_sendto if some options are + not set (LWIP_TCP, LWIP_UDP, LWIP_RAW). + + 2007-05-10 Simon Goldschmidt + * *.h (except netif/ppp/*.h): Included patch #5448: include '#ifdef __cplusplus + \ extern "C" {' in all header files. Now you can write your application using + the lwIP stack in C++ and simply #include the core files. Note I have left + out the netif/ppp/*h header files for now, since I don't know which files are + included by applications and which are for internal use only. + + 2007-05-09 Simon Goldschmidt + * opt.h, *.c/*.h: Included patch #5920: Create define to override C-library + memcpy. 2 Defines are created: MEMCPY() for normal memcpy, SMEMCPY() for + situations where some compilers might inline the copy and save a function + call. Also replaced all calls to memcpy() with calls to (S)MEMCPY(). + + 2007-05-08 Simon Goldschmidt + * mem.h: If MEM_LIBC_MALLOC==1, allow the defines (e.g. mem_malloc() -> malloc()) + to be overriden in case the C-library malloc implementation is not protected + against concurrent access. + + 2007-05-04 Simon Goldschmidt (Atte Kojo) + * etharp.c: Introduced fast one-entry-cache to speed up ARP lookup when sending + multiple packets to the same host. + + 2007-05-04 Frédéric Bernon, Jonathan Larmour + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible + to corrupt remote addr/port connection state". Reduce problems "not enought memory" with + netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between + sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. + Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct, + these fields are now renamed "addr" & "port". + + 2007-04-11 Jonathan Larmour + * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new + sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return + with SYS_MBOX_EMPTY. sys_arch_mbox_tryfetch can be implemented as a function-like macro + by the port in sys_arch.h if desired. + + 2007-04-06 Frédéric Bernon, Simon Goldschmidt + * opt.h, tcpip.h, tcpip.c, netifapi.h, netifapi.c: New configuration option LWIP_NETIF_API + allow to use thread-safe functions to add/remove netif in list, and to start/stop dhcp + clients, using new functions from netifapi.h. Disable as default (no port change to do). + + 2007-04-05 Frédéric Bernon + * sockets.c: remplace ENOBUFS errors on alloc_socket by ENFILE to be more BSD compliant. + + 2007-04-04 Simon Goldschmidt + * arch.h, api_msg.c, dhcp.c, msg_in.c, sockets.c: Introduced #define LWIP_UNUSED_ARG(x) + use this for and architecture-independent form to tell the compiler you intentionally + are not using this variable. Can be overriden in cc.h. + + 2007-03-28 Frédéric Bernon + * opt.h, netif.h, dhcp.h, dhcp.c: New configuration option LWIP_NETIF_HOSTNAME allow to + define a hostname in netif struct (this is just a pointer, so, you can use a hardcoded + string, point on one of your's ethernetif field, or alloc a string you will free yourself). + It will be used by DHCP to register a client hostname, but can also be use when you call + snmp_set_sysname. + + 2007-03-28 Frédéric Bernon + * netif.h, netif.c: A new NETIF_FLAG_ETHARP flag is defined in netif.h, to allow to + initialize a network interface's flag with. It tell this interface is an ethernet + device, and we can use ARP with it to do a "gratuitous ARP" (RFC 3220 "IP Mobility + Support for IPv4" section 4.6) when interface is "up" with netif_set_up(). + + 2007-03-26 Frédéric Bernon, Jonathan Larmour + * opt.h, tcpip.c: New configuration option LWIP_ARP allow to disable ARP init at build + time if you only use PPP or SLIP. The default is enable. Note we don't have to call + etharp_init in your port's initilization sequence if you use tcpip.c, because this call + is done in tcpip_init function. + + 2007-03-22 Frédéric Bernon + * stats.h, stats.c, msg_in.c: Stats counters can be change to u32_t if necessary with the + new option LWIP_STATS_LARGE. If you need this option, define LWIP_STATS_LARGE to 1 in + your lwipopts.h. More, unused counters are not defined in the stats structs, and not + display by stats_display(). Note that some options (SYS_STATS and RAW_STATS) are defined + but never used. Fix msg_in.c with the correct #if test for a stat display. + + 2007-03-21 Kieran Mansley + * netif.c, netif.h: Apply patch#4197 with some changes (originator: rireland@hmgsl.com). + Provides callback on netif up/down state change. + + 2007-03-11 Frédéric Bernon, Mace Gael, Steve Reynolds + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c, + ip.c, netif.h, tcpip.c, opt.h: + New configuration option LWIP_IGMP to enable IGMP processing. Based on only one + filter per all network interfaces. Declare a new function in netif to enable to + control the MAC filter (to reduce lwIP traffic processing). + + 2007-03-11 Frédéric Bernon + * tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can + be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this + unless you know what you're doing (default are RFC1122 compliant). Note + that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds. + + 2007-03-08 Frédéric Bernon + * tcp.h: Keepalive values can be configured at compile time, but don't change + this unless you know what you're doing (default are RFC1122 compliant). + + 2007-03-08 Frédéric Bernon + * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h: + Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO + on UDP sockets/netconn. + + 2007-03-08 Simon Goldschmidt + * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. + + 2007-03-06 Frédéric Bernon + * api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h: + Implement SO_RCVTIMEO on UDP sockets/netconn. + + 2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt) + * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated + on the stack and remove the API msg type from memp + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * sockets.h, sockets.c: Move socket initialization to new + lwip_socket_init() function. + NOTE: this changes the API with ports. Ports will have to be + updated to call lwip_socket_init() now. + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * api_lib.c: Use memcpy in netbuf_copy_partial. + + + ++ Bug fixes: + + 2008-03-17 Frédéric Bernon, Ed Kerekes + * igmp.h, igmp.c: Fix bug #22613 "IGMP iphdr problem" (could have + some problems to fill the IP header on some targets, use now the + ip.h macros to do it). + + 2008-03-13 Frédéric Bernon + * sockets.c: Fix bug #22435 "lwip_recvfrom with TCP break;". Using + (lwip_)recvfrom with valid "from" and "fromlen" parameters, on a + TCP connection caused a crash. Note that using (lwip_)recvfrom + like this is a bit slow and that using (lwip)getpeername is the + good lwip way to do it (so, using recv is faster on tcp sockets). + + 2008-03-12 Frédéric Bernon, Jonathan Larmour + * api_msg.c, contrib/apps/ping.c: Fix bug #22530 "api_msg.c's + recv_raw() does not consume data", and the ping sample (with + LWIP_SOCKET=1, the code did the wrong supposition that lwip_recvfrom + returned the IP payload, without the IP header). + + 2008-03-04 Jonathan Larmour + * mem.c, stats.c, mem.h: apply patch #6414 to avoid compiler errors + and/or warnings on some systems where mem_size_t and size_t differ. + * pbuf.c, ppp.c: Fix warnings on some systems with mem_malloc. + + 2008-03-04 Kieran Mansley (contributions by others) + * Numerous small compiler error/warning fixes from contributions to + mailing list after 1.3.0 release candidate made. + + 2008-01-25 Cui hengbin (integrated by Frédéric Bernon) + * dns.c: Fix bug #22108 "DNS problem" caused by unaligned structures. + + 2008-01-15 Kieran Mansley + * tcp_out.c: BUG20511. Modify persist timer to start when we are + prevented from sending by a small send window, not just a zero + send window. + + 2008-01-09 Jonathan Larmour + * opt.h, ip.c: Rename IP_OPTIONS define to IP_OPTIONS_ALLOWED to avoid + conflict with Linux system headers. + + 2008-01-06 Jonathan Larmour + * dhcp.c: fix bug #19927: "DHCP NACK problem" by clearing any existing set IP + address entirely on receiving a DHCPNAK, and restarting discovery. + + 2007-12-21 Simon Goldschmidt + * sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail + is not protected" by using new macros for interlocked access to modify/test + netconn->recv_avail. + + 2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev) + * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state) + + 2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling + of silly window avoidance and prevent lwIP from shrinking the window) + + 2007-12-04 Simon Goldschmidt + * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last + data packet was lost): add assert that all segment lists are empty in + tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED + state from LAST_ACK in tcp_process + + 2007-12-02 Simon Goldschmidt + * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET + If including for system-struct timeval, LWIP_TIMEVAL_PRIVATE now + has to be set to 0 in lwipopts.h + + 2007-12-02 Simon Goldschmidt + * api_msg.c, api_lib.c: fix bug #21656 (recvmbox problem in netconn API): always + allocate a recvmbox in netconn_new_with_proto_and_callback. For a tcp-listen + netconn, this recvmbox is later freed and a new mbox is allocated for acceptmbox. + This is a fix for thread-safety and allocates all items needed for a netconn + when the netconn is created. + + 2007-11-30 Simon Goldschmidt + * udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple + netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed + to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same + port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address) + + 2007-11-27 Simon Goldschmidt + * ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by + letting ip_route only use netifs that are up. + + 2007-11-27 Simon Goldschmidt + * err.h, api_lib.c, api_msg.c, sockets.c: Changed error handling: ERR_MEM, ERR_BUF + and ERR_RTE are seen as non-fatal, all other errors are fatal. netconns and + sockets block most operations once they have seen a fatal error. + + 2007-11-27 Simon Goldschmidt + * udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the + netif to send as an argument (to be able to send on netifs that are down). + + 2007-11-26 Simon Goldschmidt + * tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs + arrive out-of-order + + 2007-11-21 Simon Goldschmidt + * tcp.h, tcp_out.c, api_msg.c: Fixed bug #20287: tcp_output_nagle sends too early + Fixed the nagle algorithm; nagle now also works for all raw API applications + and has to be explicitly disabled with 'tcp_pcb->flags |= TF_NODELAY' + + 2007-11-12 Frédéric Bernon + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most + of the netconn_peer and netconn_addr processing is done inside tcpip_thread + context in do_getaddr. + + 2007-11-10 Simon Goldschmidt + * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can + happen any time). Now the packet simply isn't enqueued when out of memory. + + 2007-11-01 Simon Goldschmidt + * tcp.c, tcp_in.c: Fixed bug #21494: The send mss (pcb->mss) is set to 536 (or + TCP_MSS if that is smaller) as long as no MSS option is received from the + remote host. + + 2007-11-01 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #21491: The MSS option sent (with SYN) + is now based on TCP_MSS instead of pcb->mss (on passive open now effectively + sending our configured TCP_MSS instead of the one received). + + 2007-11-01 Simon Goldschmidt + * tcp_in.c: Fixed bug #21181: On active open, the initial congestion window was + calculated based on the configured TCP_MSS, not on the MSS option received + with SYN+ACK. + + 2007-10-09 Simon Goldschmidt + * udp.c, inet.c, inet.h: Fixed UDPLite: send: Checksum was always generated too + short and also was generated wrong if checksum coverage != tot_len; + receive: checksum was calculated wrong if checksum coverage != tot_len + + 2007-10-08 Simon Goldschmidt + * mem.c: lfree was not updated in mem_realloc! + + 2007-10-07 Frédéric Bernon + * sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential + crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT: + this change cause an API breakage for netconn_addr, since a parameter + type change. Any compiler should cause an error without any changes in + yours netconn_peer calls (so, it can't be a "silent change"). It also + reduce a little bit the footprint for socket layer (lwip_getpeername & + lwip_getsockname use now a common lwip_getaddrname function since + netconn_peer & netconn_addr have the same parameters). + + 2007-09-20 Simon Goldschmidt + * tcp.c: Fixed bug #21080 (tcp_bind without check pcbs in TIME_WAIT state) + by checking tcp_tw_pcbs also + + 2007-09-19 Simon Goldschmidt + * icmp.c: Fixed bug #21107 (didn't reset IP TTL in ICMP echo replies) + + 2007-09-15 Mike Kleshov + * mem.c: Fixed bug #21077 (inaccuracy in calculation of lwip_stat.mem.used) + + 2007-09-06 Frédéric Bernon + * several-files: replace some #include "arch/cc.h" by "lwip/arch.h", or simply remove + it as long as "lwip/opt.h" is included before (this one include "lwip/debug.h" which + already include "lwip/arch.h"). Like that, default defines are provided by "lwip/arch.h" + if they are not defined in cc.h, in the same spirit than "lwip/opt.h" for lwipopts.h. + + 2007-08-30 Frédéric Bernon + * igmp.h, igmp.c: Some changes to remove some redundant code, add some traces, + and fix some coding style. + + 2007-08-28 Frédéric Bernon + * tcpip.c: Fix TCPIP_MSG_INPKT processing: now, tcpip_input can be used for any + kind of packets. These packets are considered like Ethernet packets (payload + pointing to ethhdr) if the netif got the NETIF_FLAG_ETHARP flag. Else, packets + are considered like IP packets (payload pointing to iphdr). + + 2007-08-27 Frédéric Bernon + * api.h, api_lib.c, api_msg.c: First fix for "bug #20900 : Potential crash error + problem with netconn_peer & netconn_addr". Introduce NETCONN_LISTEN netconn_state + and remove obsolete ones (NETCONN_RECV & NETCONN_ACCEPT). + + 2007-08-24 Kieran Mansley + * inet.c Modify (acc >> 16) test to ((acc >> 16) != 0) to help buggy + compiler (Paradigm C++) + + 2007-08-09 Frédéric Bernon, Bill Florac + * stats.h, stats.c, igmp.h, igmp.c, opt.h: Fix for bug #20503 : IGMP Improvement. + Introduce IGMP_STATS to centralize statistics management. + + 2007-08-09 Frédéric Bernon, Bill Florac + * udp.c: Fix for bug #20503 : IGMP Improvement. Enable to receive a multicast + packet on a udp pcb binded on an netif's IP address, and not on "any". + + 2007-08-09 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, ip.c: Fix minor changes from bug #20503 : IGMP Improvement. + This is mainly on using lookup/lookfor, and some coding styles... + + 2007-07-26 Frédéric Bernon (and "thedoctor") + * igmp.c: Fix bug #20595 to accept IGMPv3 "Query" messages. + + 2007-07-25 Simon Goldschmidt + * api_msg.c, tcp.c: Another fix for bug #20021: by not returning an error if + tcp_output fails in tcp_close, the code in do_close_internal gets simpler + (tcp_output is called again later from tcp timers). + + 2007-07-25 Simon Goldschmidt + * ip_frag.c: Fixed bug #20429: use the new pbuf_copy_partial instead of the old + copy_from_pbuf, which illegally modified the given pbuf. + + 2007-07-25 Simon Goldschmidt + * tcp_out.c: tcp_enqueue: pcb->snd_queuelen didn't work for chaine PBUF_RAMs: + changed snd_queuelen++ to snd_queuelen += pbuf_clen(p). + + 2007-07-24 Simon Goldschmidt + * api_msg.c, tcp.c: Fix bug #20480: Check the pcb passed to tcp_listen() for the + correct state (must be CLOSED). + + 2007-07-13 Thomas Taranowski (commited by Jared Grubb) + * memp.c: Fix bug #20478: memp_malloc returned NULL+MEMP_SIZE on failed + allocation. It now returns NULL. + + 2007-07-13 Frédéric Bernon + * api_msg.c: Fix bug #20318: api_msg "recv" callbacks don't call pbuf_free in + all error cases. + + 2007-07-13 Frédéric Bernon + * api_msg.c: Fix bug #20315: possible memory leak problem if tcp_listen failed, + because current code doesn't follow rawapi.txt documentation. + + 2007-07-13 Kieran Mansley + * src/core/tcp_in.c Apply patch#5741 from Oleg Tyshev to fix bug in + out of sequence processing of received packets + + 2007-07-03 Simon Goldschmidt + * nearly-all-files: Added assertions where PBUF_RAM pbufs are used and an + assumption is made that this pbuf is in one piece (i.e. not chained). These + assumptions clash with the possibility of converting to fully pool-based + pbuf implementations, where PBUF_RAM pbufs might be chained. + + 2007-07-03 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Final fix for bug #20021 and some other problems + when closing tcp netconns: removed conn->sem, less context switches when + closing, both netconn_close and netconn_delete should safely close tcp + connections. + + 2007-07-02 Simon Goldschmidt + * ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c, + tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off) + to cache ARP table indices with each pcb instead of single-entry cache for + the complete stack. + + 2007-07-02 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent + warnings when assigning to smaller types. + + 2007-06-28 Simon Goldschmidt + * tcp_out.c: Added check to prevent tcp_pcb->snd_queuelen from overflowing. + + 2007-06-28 Simon Goldschmidt + * tcp.h: Fixed bug #20287: Fixed nagle algorithm (sending was done too early if + a segment contained chained pbufs) + + 2007-06-28 Frédéric Bernon + * autoip.c: replace most of rand() calls by a macro LWIP_AUTOIP_RAND which compute + a "pseudo-random" value based on netif's MAC and some autoip fields. It's always + possible to define this macro in your own lwipopts.h to always use C library's + rand(). Note that autoip_create_rand_addr doesn't use this macro. + + 2007-06-28 Frédéric Bernon + * netifapi.h, netifapi.c, tcpip.h, tcpip.c: Update code to handle the option + LWIP_TCPIP_CORE_LOCKING, and do some changes to be coherent with last modifications + in api_lib/api_msg (use pointers and not type with table, etc...) + + 2007-06-26 Simon Goldschmidt + * udp.h: Fixed bug #20259: struct udp_hdr was lacking the packin defines. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20253: icmp_dest_unreach was called with a wrong p->payload + for udp packets with no matching pcb. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20220: UDP PCB search in udp_input(): a non-local match + could get udp input packets if the remote side matched. + + 2007-06-13 Simon Goldschmidt + * netif.c: Fixed bug #20180 (TCP pcbs listening on IP_ADDR_ANY could get + changed in netif_set_ipaddr if previous netif->ip_addr.addr was 0. + + 2007-06-13 Simon Goldschmidt + * api_msg.c: pcb_new sets conn->err if protocol is not implemented + -> netconn_new_..() does not allocate a new connection for unsupported + protocols. + + 2007-06-13 Frédéric Bernon, Simon Goldschmidt + * api_lib.c: change return expression in netconn_addr and netconn_peer, because + conn->err was reset to ERR_OK without any reasons (and error was lost)... + + 2007-06-13 Frédéric Bernon, Matthias Weisser + * opt.h, mem.h, mem.c, memp.c, pbuf.c, ip_frag.c, vj.c: Fix bug #20162. Rename + MEM_ALIGN in LWIP_MEM_ALIGN and MEM_ALIGN_SIZE in LWIP_MEM_ALIGN_SIZE to avoid + some macro names collision with some OS macros. + + 2007-06-11 Simon Goldschmidt + * udp.c: UDP Lite: corrected the use of chksum_len (based on RFC3828: if it's 0, + create checksum over the complete packet. On RX, if it's < 8 (and not 0), + discard the packet. Also removed the duplicate 'udphdr->chksum = 0' for both + UDP & UDP Lite. + + 2007-06-11 Srinivas Gollakota & Oleg Tyshev + * tcp_out.c: Fix for bug #20075 : "A problem with keep-alive timer and TCP flags" + where TCP flags wasn't initialized in tcp_keepalive. + + 2007-06-03 Simon Goldschmidt + * udp.c: udp_input(): Input pbuf was not freed if pcb had no recv function + registered, p->payload was modified without modifying p->len if sending + icmp_dest_unreach() (had no negative effect but was definitively wrong). + + 2007-06-03 Simon Goldschmidt + * icmp.c: Corrected bug #19937: For responding to an icmp echo request, icmp + re-used the input pbuf even if that didn't have enough space to include the + link headers. Now the space is tested and a new pbuf is allocated for the + echo response packet if the echo request pbuf isn't big enough. + + 2007-06-01 Simon Goldschmidt + * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread. + + 2007-05-23 Frédéric Bernon + * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only + allocated by do_listen if success) and netconn_accept errors handling. In + most of api_lib functions, we replace some errors checkings like "if (conn==NULL)" + by ASSERT, except for netconn_delete. + + 2007-05-23 Frédéric Bernon + * api_lib.c: Fixed bug #5957 "Safe-thread problem inside netconn_recv" to return + an error code if it's impossible to fetch a pbuf on a TCP connection (and not + directly close the recvmbox). + + 2007-05-22 Simon Goldschmidt + * tcp.c: Fixed bug #1895 (tcp_bind not correct) by introducing a list of + bound but unconnected (and non-listening) tcp_pcbs. + + 2007-05-22 Frédéric Bernon + * sys.h, sys.c, api_lib.c, tcpip.c: remove sys_mbox_fetch_timeout() (was only + used for LWIP_SO_RCVTIMEO option) and use sys_arch_mbox_fetch() instead of + sys_mbox_fetch() in api files. Now, users SHOULD NOT use internal lwIP features + like "sys_timeout" in their application threads. + + 2007-05-22 Frédéric Bernon + * api.h, api_lib.c, api_msg.h, api_msg.c: change the struct api_msg_msg to see + which parameters are used by which do_xxx function, and to avoid "misusing" + parameters (patch #5938). + + 2007-05-22 Simon Goldschmidt + * api_lib.c, api_msg.c, raw.c, api.h, api_msg.h, raw.h: Included patch #5938: + changed raw_pcb.protocol from u16_t to u8_t since for IPv4 and IPv6, proto + is only 8 bits wide. This affects the api, as there, the protocol was + u16_t, too. + + 2007-05-18 Simon Goldschmidt + * memp.c: addition to patch #5913: smaller pointer was returned but + memp_memory was the same size -> did not save memory. + + 2007-05-16 Simon Goldschmidt + * loopif.c, slipif.c: Fix bug #19729: free pbuf if netif->input() returns + != ERR_OK. + + 2007-05-16 Simon Goldschmidt + * api_msg.c, udp.c: If a udp_pcb has a local_ip set, check if it is the same + as the one of the netif used for sending to prevent sending from old + addresses after a netif address gets changed (partly fixes bug #3168). + + 2007-05-16 Frédéric Bernon + * tcpip.c, igmp.h, igmp.c: Fixed bug "#19800 : IGMP: igmp_tick() will not work + with NO_SYS=1". Note that igmp_init is always in tcpip_thread (and not in + tcpip_init) because we have to be sure that network interfaces are already + added (mac filter is updated only in igmp_init for the moment). + + 2007-05-16 Simon Goldschmidt + * mem.c, memp.c: Removed semaphores from memp, changed sys_sem_wait calls + into sys_arch_sem_wait calls to prevent timers from running while waiting + for the heap. This fixes bug #19167. + + 2007-05-13 Simon Goldschmidt + * tcp.h, sockets.h, sockets.c: Fixed bug from patch #5865 by moving the defines + for socket options (lwip_set/-getsockopt) used with level IPPROTO_TCP from + tcp.h to sockets.h. + + 2007-05-07 Simon Goldschmidt + * mem.c: Another attempt to fix bug #17922. + + 2007-05-04 Simon Goldschmidt + * pbuf.c, pbuf.h, etharp.c: Further update to ARP queueing: Changed pbuf_copy() + implementation so that it can be reused (don't allocate the target + pbuf inside pbuf_copy()). + + 2007-05-04 Simon Goldschmidt + * memp.c: checked in patch #5913: in memp_malloc() we can return memp as mem + to save a little RAM (next pointer of memp is not used while not in pool). + + 2007-05-03 "maq" + * sockets.c: Fix ioctl FIONREAD when some data remains from last recv. + (patch #3574). + + 2007-04-23 Simon Goldschmidt + * loopif.c, loopif.h, opt.h, src/netif/FILES: fix bug #2595: "loopif results + in NULL reference for incoming TCP packets". Loopif has to be configured + (using LWIP_LOOPIF_MULTITHREADING) to directly call netif->input() + (multithreading environments, e.g. netif->input() = tcpip_input()) or + putting packets on a list that is fed to the stack by calling loopif_poll() + (single-thread / NO_SYS / polling environment where e.g. + netif->input() = ip_input). + + 2007-04-17 Jonathan Larmour + * pbuf.c: Use s32_t in pbuf_realloc(), as an s16_t can't reliably hold + the difference between two u16_t's. + * sockets.h: FD_SETSIZE needs to match number of sockets, which is + MEMP_NUM_NETCONN in sockets.c right now. + + 2007-04-12 Jonathan Larmour + * icmp.c: Reset IP header TTL in ICMP ECHO responses (bug #19580). + + 2007-04-12 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission + timer is reset to fix bug#19434, with help from Oleg Tyshev. + + 2007-04-11 Simon Goldschmidt + * etharp.c, pbuf.c, pbuf.h: 3rd fix for bug #11400 (arp-queuing): More pbufs than + previously thought need to be copied (everything but PBUF_ROM!). Cleaned up + pbuf.c: removed functions no needed any more (by etharp). + + 2007-04-11 Kieran Mansley + * inet.c, ip_addr.h, sockets.h, sys.h, tcp.h: Apply patch #5745: Fix + "Constant is long" warnings with 16bit compilers. Contributed by + avatar@mmlab.cse.yzu.edu.tw + + 2007-04-05 Frédéric Bernon, Jonathan Larmour + * api_msg.c: Fix bug #16830: "err_tcp() posts to connection mailbox when no pend on + the mailbox is active". Now, the post is only done during a connect, and do_send, + do_write and do_join_leave_group don't do anything if a previous error was signaled. + + 2007-04-03 Frédéric Bernon + * ip.c: Don't set the IP_DF ("Don't fragment") flag in the IP header in IP output + packets. See patch #5834. + + 2007-03-30 Frédéric Bernon + * api_msg.c: add a "pcb_new" helper function to avoid redundant code, and to add + missing pcb allocations checking (in do_bind, and for each raw_new). Fix style. + + 2007-03-30 Frédéric Bernon + * most of files: prefix all debug.h define with "LWIP_" to avoid any conflict with + others environment defines (these were too "generic"). + + 2007-03-28 Frédéric Bernon + * api.h, api_lib.c, sockets.c: netbuf_ref doesn't check its internal pbuf_alloc call + result and can cause a crash. lwip_send now check netbuf_ref result. + + 2007-03-28 Simon Goldschmidt + * sockets.c Remove "#include " from sockets.c to avoid multiple + definition of macros (in errno.h and lwip/arch.h) if LWIP_PROVIDE_ERRNO is + defined. This is the way it should have been already (looking at + doc/sys_arch.txt) + + 2007-03-28 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE (again) to accomodate default MSS + + IP and TCP headers *and* physical link headers + + 2007-03-26 Frédéric Bernon (based on patch from Dmitry Potapov) + * api_lib.c: patch for netconn_write(), fixes a possible race condition which cause + to send some garbage. It is not a definitive solution, but the patch does solve + the problem for most cases. + + 2007-03-22 Frédéric Bernon + * api_msg.h, api_msg.c: Remove obsolete API_MSG_ACCEPT and do_accept (never used). + + 2007-03-22 Frédéric Bernon + * api_lib.c: somes resources couldn't be freed if there was errors during + netconn_new_with_proto_and_callback. + + 2007-03-22 Frédéric Bernon + * ethernetif.c: update netif->input calls to check return value. In older ports, + it's a good idea to upgrade them, even if before, there could be another problem + (access to an uninitialized mailbox). + + 2007-03-21 Simon Goldschmidt + * sockets.c: fixed bug #5067 (essentialy a signed/unsigned warning fixed + by casting to unsigned). + + 2007-03-21 Frédéric Bernon + * api_lib.c, api_msg.c, tcpip.c: integrate sys_mbox_fetch(conn->mbox, NULL) calls from + api_lib.c to tcpip.c's tcpip_apimsg(). Now, use a local variable and not a + dynamic one from memp to send tcpip_msg to tcpip_thread in a synchrone call. + Free tcpip_msg from tcpip_apimsg is not done in tcpip_thread. This give a + faster and more reliable communication between api_lib and tcpip. + + 2007-03-21 Frédéric Bernon + * opt.h: Add LWIP_NETIF_CALLBACK (to avoid compiler warning) and set it to 0. + + 2007-03-21 Frédéric Bernon + * api_msg.c, igmp.c, igmp.h: Fix C++ style comments + + 2007-03-21 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE to accomodate default MSS + + IP and TCP headers + + 2007-03-21 Kieran Mansley + * Fix all uses of pbuf_header to check the return value. In some + cases just assert if it fails as I'm not sure how to fix them, but + this is no worse than before when they would carry on regardless + of the failure. + + 2007-03-21 Kieran Mansley + * sockets.c, igmp.c, igmp.h, memp.h: Fix C++ style comments and + comment out missing header include in icmp.c + + 2007-03-20 Frédéric Bernon + * memp.h, stats.c: Fix stats_display function where memp_names table wasn't + synchronized with memp.h. + + 2007-03-20 Frédéric Bernon + * tcpip.c: Initialize tcpip's mbox, and verify if initialized in tcpip_input, + tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with + network interfaces. Also fix a compiler warning. + + 2007-03-20 Kieran Mansley + * udp.c: Only try and use pbuf_header() to make space for headers if + not a ROM or REF pbuf. + + 2007-03-19 Frédéric Bernon + * api_msg.h, api_msg.c, tcpip.h, tcpip.c: Add return types to tcpip_apimsg() + and api_msg_post(). + + 2007-03-19 Frédéric Bernon + * Remove unimplemented "memp_realloc" function from memp.h. + + 2007-03-11 Simon Goldschmidt + * pbuf.c: checked in patch #5796: pbuf_alloc: len field claculation caused + memory corruption. + + 2007-03-11 Simon Goldschmidt (based on patch from Dmitry Potapov) + * api_lib.c, sockets.c, api.h, api_msg.h, sockets.h: Fixed bug #19251 + (missing `const' qualifier in socket functions), to get more compatible to + standard POSIX sockets. + + 2007-03-11 Frédéric Bernon (based on patch from Dmitry Potapov) + * sockets.c: Add asserts inside bind, connect and sendto to check input + parameters. Remove excessive set_errno() calls after get_socket(), because + errno is set inside of get_socket(). Move last sock_set_errno() inside + lwip_close. + + 2007-03-09 Simon Goldschmidt + * memp.c: Fixed bug #11400: New etharp queueing introduced bug: memp_memory + was allocated too small. + + 2007-03-06 Simon Goldschmidt + * tcpip.c: Initialize dhcp timers in tcpip_thread (if LWIP_DHCP) to protect + the stack from concurrent access. + + 2007-03-06 Frédéric Bernon, Dmitry Potapov + * tcpip.c, ip_frag.c, ethernetif.c: Fix some build problems, and a redundancy + call to "lwip_stats.link.recv++;" in low_level_input() & ethernetif_input(). + + 2007-03-06 Simon Goldschmidt + * ip_frag.c, ip_frag.h: Reduce code size: don't include code in those files + if IP_FRAG == 0 and IP_REASSEMBLY == 0 + + 2007-03-06 Frédéric Bernon, Simon Goldschmidt + * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration + option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. + Allow to do ARP processing for incoming packets inside tcpip_thread + (protecting ARP layer against concurrent access). You can also disable + old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. + Older ports have to use tcpip_ethinput. + + 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov) + * err.h, err.c: fixed compiler warning "initialization dircards qualifiers + from pointer target type" + + 2007-03-05 Frédéric Bernon + * opt.h, sockets.h: add new configuration options (LWIP_POSIX_SOCKETS_IO_NAMES, + ETHARP_TRUST_IP_MAC, review SO_REUSE) + + 2007-03-04 Frédéric Bernon + * api_msg.c: Remove some compiler warnings : parameter "pcb" was never + referenced. + + 2007-03-04 Frédéric Bernon + * api_lib.c: Fix "[patch #5764] api_lib.c cleanup: after patch #5687" (from + Dmitry Potapov). + The api_msg struct stay on the stack (not moved to netconn struct). + + 2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov) + * pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if + SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available) + Also fixed cast warning in pbuf_alloc() + + 2007-03-04 Simon Goldschmidt + * etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt + existing pbuf chain when enqueuing multiple pbufs to a pending ARP request + + 2007-03-03 Frédéric Bernon + * udp.c: remove obsolete line "static struct udp_pcb *pcb_cache = NULL;" + It is static, and never used in udp.c except udp_init(). + + 2007-03-02 Simon Goldschmidt + * tcpip.c: Moved call to ip_init(), udp_init() and tcp_init() from + tcpip_thread() to tcpip_init(). This way, raw API connections can be + initialized before tcpip_thread is running (e.g. before OS is started) + + 2007-03-02 Frédéric Bernon + * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call + interval. + + 2007-02-28 Kieran Mansley + * pbuf.c: Fix BUG#17645 - ensure pbuf payload pointer is not moved + outside the region of the pbuf by pbuf_header() + + 2007-02-28 Kieran Mansley + * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero + when supplied timeout is also non-zero + +(STABLE-1.2.0) + + 2006-12-05 Leon Woestenberg + * CHANGELOG: Mention STABLE-1.2.0 release. + + ++ New features: + + 2006-12-01 Christiaan Simons + * mem.h, opt.h: Added MEM_LIBC_MALLOC option. + Note this is a workaround. Currently I have no other options left. + + 2006-10-26 Christiaan Simons (accepted patch by Jonathan Larmour) + * ipv4/ip_frag.c: rename MAX_MTU to IP_FRAG_MAX_MTU and move define + to include/lwip/opt.h. + * ipv4/lwip/ip_frag.h: Remove unused IP_REASS_INTERVAL. + Move IP_REASS_MAXAGE and IP_REASS_BUFSIZE to include/lwip/opt.h. + * opt.h: Add above new options. + + 2006-08-18 Christiaan Simons + * tcp_{in,out}.c: added SNMP counters. + * ipv4/ip.c: added SNMP counters. + * ipv4/ip_frag.c: added SNMP counters. + + 2006-08-08 Christiaan Simons + * etharp.{c,h}: added etharp_find_addr() to read + (stable) ethernet/IP address pair from ARP table + + 2006-07-14 Christiaan Simons + * mib_structs.c: added + * include/lwip/snmp_structs.h: added + * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct + + 2006-07-06 Christiaan Simons + * snmp/asn1_{enc,dec}.c added + * snmp/mib2.c added + * snmp/msg_{in,out}.c added + * include/lwip/snmp_asn1.h added + * include/lwip/snmp_msg.h added + * doc/snmp_agent.txt added + + 2006-03-29 Christiaan Simons + * inet.c, inet.h: Added platform byteswap support. + Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and + optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. + + ++ Bug fixes: + + 2006-11-30 Christiaan Simons + * dhcp.c: Fixed false triggers of request_timeout. + + 2006-11-28 Christiaan Simons + * netif.c: In netif_add() fixed missing clear of ip_addr, netmask, gw and flags. + + 2006-10-11 Christiaan Simons + * api_lib.c etharp.c, ip.c, memp.c, stats.c, sys.{c,h} tcp.h: + Partially accepted patch #5449 for ANSI C compatibility / build fixes. + * ipv4/lwip/ip.h ipv6/lwip/ip.h: Corrected UDP-Lite protocol + identifier from 170 to 136 (bug #17574). + + 2006-10-10 Christiaan Simons + * api_msg.c: Fixed Nagle algorithm as reported by Bob Grice. + + 2006-08-17 Christiaan Simons + * udp.c: Fixed bug #17200, added check for broadcast + destinations for PCBs bound to a unicast address. + + 2006-08-07 Christiaan Simons + * api_msg.c: Flushing TCP output in do_close() (bug #15926). + + 2006-06-27 Christiaan Simons + * api_msg.c: Applied patch for cold case (bug #11135). + In accept_function() ensure newconn->callback is always initialized. + + 2006-06-15 Christiaan Simons + * mem.h: added MEM_SIZE_F alias to fix an ancient cold case (bug #1748), + facilitate printing of mem_size_t and u16_t statistics. + + 2006-06-14 Christiaan Simons + * api_msg.c: Applied patch #5146 to handle allocation failures + in accept() by Kevin Lawson. + + 2006-05-26 Christiaan Simons + * api_lib.c: Removed conn->sem creation and destruction + from netconn_write() and added sys_sem_new to netconn_new_*. + +(STABLE-1_1_1) + + 2006-03-03 Christiaan Simons + * ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap + access and added pbuf_alloc() return value checks. + + 2006-01-01 Leon Woestenberg + * tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is + now handled by the checksum routine properly. + + 2006-02-27 Leon Woestenberg + * pbuf.c: Fix alignment; pbuf_init() would not work unless + pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.) + + 2005-12-20 Leon Woestenberg + * tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch + submitted by Mitrani Hiroshi. + + 2005-12-15 Christiaan Simons + * inet.c: Disabled the added summing routine to preserve code space. + + 2005-12-14 Leon Woestenberg + * tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson. + Added Curt McDowell's optimized checksumming routine for future + inclusion. Need to create test case for unaliged, aligned, odd, + even length combination of cases on various endianess machines. + + 2005-12-09 Christiaan Simons + * inet.c: Rewrote standard checksum routine in proper portable C. + + 2005-11-25 Christiaan Simons + * udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only. + * *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t, + u32_t, s32_t typedefs. This solves most debug word-length assumes. + + 2005-07-17 Leon Woestenberg + * inet.c: Fixed unaligned 16-bit access in the standard checksum + routine by Peter Jolasson. + * slipif.c: Fixed implementation assumption of single-pbuf datagrams. + + 2005-02-04 Leon Woestenberg + * tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch. + * tcp_{out|in}.c: Applied patch fixing unaligned access. + + 2005-01-04 Leon Woestenberg + * pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement. + + 2005-01-03 Leon Woestenberg + * udp.c: UDP pcb->recv() was called even when it was NULL. + +(STABLE-1_1_0) + + 2004-12-28 Leon Woestenberg + * etharp.*: Disabled multiple packets on the ARP queue. + This clashes with TCP queueing. + + 2004-11-28 Leon Woestenberg + * etharp.*: Fixed race condition from ARP request to ARP timeout. + Halved the ARP period, doubled the period counts. + ETHARP_MAX_PENDING now should be at least 2. This prevents + the counter from reaching 0 right away (which would allow + too little time for ARP responses to be received). + + 2004-11-25 Leon Woestenberg + * dhcp.c: Decline messages were not multicast but unicast. + * etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD. + Do not try hard to insert arbitrary packet's source address, + etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD. + etharp_query() now always DOES call ETHARP_TRY_HARD so that users + querying an address will see it appear in the cache (DHCP could + suffer from this when a server invalidly gave an in-use address.) + * ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are + comparing network addresses (identifiers), not the network masks + themselves. + * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given + IP address actually belongs to the network of the given interface. + + 2004-11-24 Kieran Mansley + * tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state. + +(STABLE-1_1_0-RC1) + + 2004-10-16 Kieran Mansley + * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, + even if one is already pending, if the rcv_wnd is above a threshold + (currently TCP_WND/2). This avoids waiting for a timer to expire to send a + delayed ACK in order to open the window if the stack is only receiving data. + + 2004-09-12 Kieran Mansley + * tcp*.*: Retransmit time-out handling improvement by Sam Jansen. + + 2004-08-20 Tony Mountifield + * etharp.c: Make sure the first pbuf queued on an ARP entry + is properly ref counted. + + 2004-07-27 Tony Mountifield + * debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler + warnings about comparison. + * pbuf.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. Closed an unclosed comment. + * tcp.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. + * ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons(). + * inet.c: Added a couple of casts to quiet the compiler. + No need to test isascii(c) before isdigit(c) or isxdigit(c). + + 2004-07-22 Tony Mountifield + * inet.c: Made data types consistent in inet_ntoa(). + Added casts for return values of checksum routines, to pacify compiler. + * ip_frag.c, tcp_out.c, sockets.c, pbuf.c + Small corrections to some debugging statements, to pacify compiler. + + 2004-07-21 Tony Mountifield + * etharp.c: Removed spurious semicolon and added missing end-of-comment. + * ethernetif.c Updated low_level_output() to match prototype for + netif->linkoutput and changed low_level_input() similarly for consistency. + * api_msg.c: Changed recv_raw() from int to u8_t, to match prototype + of raw_recv() in raw.h and so avoid compiler error. + * sockets.c: Added trivial (int) cast to keep compiler happier. + * ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros. + +(STABLE-1_0_0) + + ++ Changes: + + 2004-07-05 Leon Woestenberg + * sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure + your cc.h file defines this either 1 or 0. If non-defined, + defaults to 1. + * .c: Added and includes where used. + * etharp.c: Made some array indices unsigned. + + 2004-06-27 Leon Woestenberg + * netif.*: Added netif_set_up()/down(). + * dhcp.c: Changes to restart program flow. + + 2004-05-07 Leon Woestenberg + * etharp.c: In find_entry(), instead of a list traversal per candidate, do a + single-pass lookup for different candidates. Should exploit locality. + + 2004-04-29 Leon Woestenberg + * tcp*.c: Cleaned up source comment documentation for Doxygen processing. + * opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC. + * etharp.c: update_arp_entry() only adds new ARP entries when adviced to by + the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option. + + ++ Bug fixes: + + 2004-04-27 Leon Woestenberg + * etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution + suggested by Timmy Brolin. Fix for 32-bit processors that cannot access + non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix + is to prefix the 14-bit Ethernet headers with two padding bytes. + + 2004-04-23 Leon Woestenberg + * ip_addr.c: Fix in the ip_addr_isbroadcast() check. + * etharp.c: Fixed the case where the packet that initiates the ARP request + is not queued, and gets lost. Fixed the case where the packets destination + address is already known; we now always queue the packet and perform an ARP + request. + +(STABLE-0_7_0) + + ++ Bug fixes: + + * Fixed TCP bug for SYN_SENT to ESTABLISHED state transition. + * Fixed TCP bug in dequeueing of FIN from out of order segment queue. + * Fixed two possible NULL references in rare cases. + +(STABLE-0_6_6) + + ++ Bug fixes: + + * Fixed DHCP which did not include the IP address in DECLINE messages. + + ++ Changes: + + * etharp.c has been hauled over a bit. + +(STABLE-0_6_5) + + ++ Bug fixes: + + * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic. + * Packets sent from ARP queue had invalid source hardware address. + + ++ Changes: + + * Pass-by ARP requests do now update the cache. + + ++ New features: + + * No longer dependent on ctype.h. + * New socket options. + * Raw IP pcb support. + +(STABLE-0_6_4) + + ++ Bug fixes: + + * Some debug formatters and casts fixed. + * Numereous fixes in PPP. + + ++ Changes: + + * DEBUGF now is LWIP_DEBUGF + * pbuf_dechain() has been re-enabled. + * Mentioned the changed use of CVS branches in README. + +(STABLE-0_6_3) + + ++ Bug fixes: + + * Fixed pool pbuf memory leak in pbuf_alloc(). + Occured if not enough PBUF_POOL pbufs for a packet pbuf chain. + Reported by Savin Zlobec. + + * PBUF_POOL chains had their tot_len field not set for non-first + pbufs. Fixed in pbuf_alloc(). + + ++ New features: + + * Added PPP stack contributed by Marc Boucher + + ++ Changes: + + * Now drops short packets for ICMP/UDP/TCP protocols. More robust. + + * ARP queueuing now queues the latest packet instead of the first. + This is the RFC recommended behaviour, but can be overridden in + lwipopts.h. + +(0.6.2) + + ++ Bugfixes: + + * TCP has been fixed to deal with the new use of the pbuf->ref + counter. + + * DHCP dhcp_inform() crash bug fixed. + + ++ Changes: + + * Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed + pbuf_refresh(). This has sped up pbuf pool operations considerably. + Implemented by David Haas. + +(0.6.1) + + ++ New features: + + * The packet buffer implementation has been enhanced to support + zero-copy and copy-on-demand for packet buffers which have their + payloads in application-managed memory. + Implemented by David Haas. + + Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy + if an outgoing packet can be directly sent on the link, or perform + a copy-on-demand when necessary. + + The application can safely assume the packet is sent, and the RAM + is available to the application directly after calling udp_send() + or similar function. + + ++ Bugfixes: + + * ARP_QUEUEING should now correctly work for all cases, including + PBUF_REF. + Implemented by Leon Woestenberg. + + ++ Changes: + + * IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer + to a '0.0.0.0' IP address. + + * The packet buffer implementation is changed. The pbuf->ref counter + meaning has changed, and several pbuf functions have been + adapted accordingly. + + * netif drivers have to be changed to set the hardware address length field + that must be initialized correctly by the driver (hint: 6 for Ethernet MAC). + See the contrib/ports/c16x cs8900 driver as a driver example. + + * netif's have a dhcp field that must be initialized to NULL by the driver. + See the contrib/ports/c16x cs8900 driver as a driver example. + +(0.5.x) This file has been unmaintained up to 0.6.1. All changes are + logged in CVS but have not been explained here. + +(0.5.3) Changes since version 0.5.2 + + ++ Bugfixes: + + * memp_malloc(MEMP_API_MSG) could fail with multiple application + threads because it wasn't protected by semaphores. + + ++ Other changes: + + * struct ip_addr now packed. + + * The name of the time variable in arp.c has been changed to ctime + to avoid conflicts with the time() function. + +(0.5.2) Changes since version 0.5.1 + + ++ New features: + + * A new TCP function, tcp_tmr(), now handles both TCP timers. + + ++ Bugfixes: + + * A bug in tcp_parseopt() could cause the stack to hang because of a + malformed TCP option. + + * The address of new connections in the accept() function in the BSD + socket library was not handled correctly. + + * pbuf_dechain() did not update the ->tot_len field of the tail. + + * Aborted TCP connections were not handled correctly in all + situations. + + ++ Other changes: + + * All protocol header structs are now packed. + + * The ->len field in the tcp_seg structure now counts the actual + amount of data, and does not add one for SYN and FIN segments. + +(0.5.1) Changes since version 0.5.0 + + ++ New features: + + * Possible to run as a user process under Linux. + + * Preliminary support for cross platform packed structs. + + * ARP timer now implemented. + + ++ Bugfixes: + + * TCP output queue length was badly initialized when opening + connections. + + * TCP delayed ACKs were not sent correctly. + + * Explicit initialization of BSS segment variables. + + * read() in BSD socket library could drop data. + + * Problems with memory alignment. + + * Situations when all TCP buffers were used could lead to + starvation. + + * TCP MSS option wasn't parsed correctly. + + * Problems with UDP checksum calculation. + + * IP multicast address tests had endianess problems. + + * ARP requests had wrong destination hardware address. + + ++ Other changes: + + * struct eth_addr changed from u16_t[3] array to u8_t[6]. + + * A ->linkoutput() member was added to struct netif. + + * TCP and UDP ->dest_* struct members where changed to ->remote_*. + + * ntoh* macros are now null definitions for big endian CPUs. + +(0.5.0) Changes since version 0.4.2 + + ++ New features: + + * Redesigned operating system emulation layer to make porting easier. + + * Better control over TCP output buffers. + + * Documenation added. + + ++ Bugfixes: + + * Locking issues in buffer management. + + * Bugfixes in the sequential API. + + * IP forwarding could cause memory leakage. This has been fixed. + + ++ Other changes: + + * Directory structure somewhat changed; the core/ tree has been + collapsed. + +(0.4.2) Changes since version 0.4.1 + + ++ New features: + + * Experimental ARP implementation added. + + * Skeleton Ethernet driver added. + + * Experimental BSD socket API library added. + + ++ Bugfixes: + + * In very intense situations, memory leakage could occur. This has + been fixed. + + ++ Other changes: + + * Variables named "data" and "code" have been renamed in order to + avoid name conflicts in certain compilers. + + * Variable++ have in appliciable cases been translated to ++variable + since some compilers generate better code in the latter case. + +(0.4.1) Changes since version 0.4 + + ++ New features: + + * TCP: Connection attempts time out earlier than data + transmissions. Nagle algorithm implemented. Push flag set on the + last segment in a burst. + + * UDP: experimental support for UDP-Lite extensions. + + ++ Bugfixes: + + * TCP: out of order segments were in some cases handled incorrectly, + and this has now been fixed. Delayed acknowledgements was broken + in 0.4, has now been fixed. Binding to an address that is in use + now results in an error. Reset connections sometimes hung an + application; this has been fixed. + + * Checksum calculation sometimes failed for chained pbufs with odd + lengths. This has been fixed. + + * API: a lot of bug fixes in the API. The UDP API has been improved + and tested. Error reporting and handling has been + improved. Logical flaws and race conditions for incoming TCP + connections has been found and removed. + + * Memory manager: alignment issues. Reallocating memory sometimes + failed, this has been fixed. + + * Generic library: bcopy was flawed and has been fixed. + + ++ Other changes: + + * API: all datatypes has been changed from generic ones such as + ints, to specified ones such as u16_t. Functions that return + errors now have the correct type (err_t). + + * General: A lot of code cleaned up and debugging code removed. Many + portability issues have been fixed. + + * The license was changed; the advertising clause was removed. + + * C64 port added. + + * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri + Kosunen, Mikael Caleres, and Frits Wilmink for reporting and + fixing bugs! + +(0.4) Changes since version 0.3.1 + + * Memory management has been radically changed; instead of + allocating memory from a shared heap, memory for objects that are + rapidly allocated and deallocated is now kept in pools. Allocation + and deallocation from those memory pools is very fast. The shared + heap is still present but is used less frequently. + + * The memory, memory pool, and packet buffer subsystems now support + 4-, 2-, or 1-byte alignment. + + * "Out of memory" situations are handled in a more robust way. + + * Stack usage has been reduced. + + * Easier configuration of lwIP parameters such as memory usage, + TTLs, statistics gathering, etc. All configuration parameters are + now kept in a single header file "lwipopts.h". + + * The directory structure has been changed slightly so that all + architecture specific files are kept under the src/arch + hierarchy. + + * Error propagation has been improved, both in the protocol modules + and in the API. + + * The code for the RTXC architecture has been implemented, tested + and put to use. + + * Bugs have been found and corrected in the TCP, UDP, IP, API, and + the Internet checksum modules. + + * Bugs related to porting between a 32-bit and a 16-bit architecture + have been found and corrected. + + * The license has been changed slightly to conform more with the + original BSD license, including the advertisement clause. + +(0.3.1) Changes since version 0.3 + + * Fix of a fatal bug in the buffer management. Pbufs with allocated + RAM never returned the RAM when the pbuf was deallocated. + + * TCP congestion control, window updates and retransmissions did not + work correctly. This has now been fixed. + + * Bugfixes in the API. + +(0.3) Changes since version 0.2 + + * New and improved directory structure. All include files are now + kept in a dedicated include/ directory. + + * The API now has proper error handling. A new function, + netconn_err(), now returns an error code for the connection in + case of errors. + + * Improvements in the memory management subsystem. The system now + keeps a pointer to the lowest free memory block. A new function, + mem_malloc2() tries to allocate memory once, and if it fails tries + to free some memory and retry the allocation. + + * Much testing has been done with limited memory + configurations. lwIP now does a better job when overloaded. + + * Some bugfixes and improvements to the buffer (pbuf) subsystem. + + * Many bugfixes in the TCP code: + + - Fixed a bug in tcp_close(). + + - The TCP receive window was incorrectly closed when out of + sequence segments was received. This has been fixed. + + - Connections are now timed-out of the FIN-WAIT-2 state. + + - The initial congestion window could in some cases be too + large. This has been fixed. + + - The retransmission queue could in some cases be screwed up. This + has been fixed. + + - TCP RST flag now handled correctly. + + - Out of sequence data was in some cases never delivered to the + application. This has been fixed. + + - Retransmitted segments now contain the correct acknowledgment + number and advertised window. + + - TCP retransmission timeout backoffs are not correctly computed + (ala BSD). After a number of retransmissions, TCP now gives up + the connection. + + * TCP connections now are kept on three lists, one for active + connections, one for listening connections, and one for + connections that are in TIME-WAIT. This greatly speeds up the fast + timeout processing for sending delayed ACKs. + + * TCP now provides proper feedback to the application when a + connection has been successfully set up. + + * More comments have been added to the code. The code has also been + somewhat cleaned up. + +(0.2) Initial public release. diff --git a/components/net/lwip-2.0.3/COPYING b/components/net/lwip-2.0.3/COPYING new file mode 100644 index 0000000000..e23898b5e8 --- /dev/null +++ b/components/net/lwip-2.0.3/COPYING @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + diff --git a/components/net/lwip-2.0.3/FILES b/components/net/lwip-2.0.3/FILES new file mode 100644 index 0000000000..e6e09989d9 --- /dev/null +++ b/components/net/lwip-2.0.3/FILES @@ -0,0 +1,5 @@ +src/ - The source code for the lwIP TCP/IP stack. +doc/ - The documentation for lwIP. +test/ - Some code to test whether the sources do what they should. + +See also the FILES file in each subdirectory. diff --git a/components/net/lwip-2.0.3/README b/components/net/lwip-2.0.3/README new file mode 100644 index 0000000000..0884d27bea --- /dev/null +++ b/components/net/lwip-2.0.3/README @@ -0,0 +1,100 @@ +INTRODUCTION + +lwIP is a small independent implementation of the TCP/IP protocol +suite that has been developed by Adam Dunkels at the Computer and +Networks Architectures (CNA) lab at the Swedish Institute of Computer +Science (SICS). + +The focus of the lwIP TCP/IP implementation is to reduce the RAM usage +while still having a full scale TCP. This making lwIP suitable for use +in embedded systems with tens of kilobytes of free RAM and room for +around 40 kilobytes of code ROM. + + +FEATURES + + * IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over + multiple network interfaces + * ICMP (Internet Control Message Protocol) for network maintenance and debugging + * IGMP (Internet Group Management Protocol) for multicast traffic management + * MLD (Multicast listener discovery for IPv6). Aims to be compliant with + RFC 2710. No support for MLDv2 + * ND (Neighbor discovery and stateless address autoconfiguration for IPv6). + Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + (Address autoconfiguration) + * UDP (User Datagram Protocol) including experimental UDP-lite extensions + * TCP (Transmission Control Protocol) with congestion control, RTT estimation + and fast recovery/fast retransmit + * raw/native API for enhanced performance + * Optional Berkeley-like socket API + * DNS (Domain names resolver) + + +APPLICATIONS + + * HTTP server with SSI and CGI + * SNMPv2c agent with MIB compiler (Simple Network Management Protocol) + * SNTP (Simple network time protocol) + * NetBIOS name service responder + * MDNS (Multicast DNS) responder + * iPerf server implementation + + +LICENSE + +lwIP is freely available under a BSD license. + + +DEVELOPMENT + +lwIP has grown into an excellent TCP/IP stack for embedded devices, +and developers using the stack often submit bug fixes, improvements, +and additions to the stack to further increase its usefulness. + +Development of lwIP is hosted on Savannah, a central point for +software development, maintenance and distribution. Everyone can +help improve lwIP by use of Savannah's interface, Git and the +mailing list. A core team of developers will commit changes to the +Git source tree. + +The lwIP TCP/IP stack is maintained in the 'lwip' Git module and +contributions (such as platform ports) are in the 'contrib' Git module. + +See doc/savannah.txt for details on Git server access for users and +developers. + +The current Git trees are web-browsable: + http://git.savannah.gnu.org/cgit/lwip.git + http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git + +Submit patches and bugs via the lwIP project page: + http://savannah.nongnu.org/projects/lwip/ + +Continuous integration builds (GCC, clang): + https://travis-ci.org/yarrick/lwip-merged + + +DOCUMENTATION + +Self documentation of the source code is regularly extracted from the current +Git sources and is available from this web page: + http://www.nongnu.org/lwip/ + +There is now a constantly growing wiki about lwIP at + http://lwip.wikia.com/wiki/LwIP_Wiki + +Also, there are mailing lists you can subscribe at + http://savannah.nongnu.org/mail/?group=lwip +plus searchable archives: + http://lists.nongnu.org/archive/html/lwip-users/ + http://lists.nongnu.org/archive/html/lwip-devel/ + +lwIP was originally written by Adam Dunkels: + http://dunkels.com/adam/ + +Reading Adam's papers, the files in docs/, browsing the source code +documentation and browsing the mailing list archives is a good way to +become familiar with the design of lwIP. + +Adam Dunkels +Leon Woestenberg diff --git a/components/net/lwip-2.0.3/READTEST.md b/components/net/lwip-2.0.3/READTEST.md new file mode 100644 index 0000000000..a407a1db52 --- /dev/null +++ b/components/net/lwip-2.0.3/READTEST.md @@ -0,0 +1,29 @@ +Porting network interface device for RT-Thread in lwIP. + +The major jobs following RT-Thread Team. Only update the origin code of lwip 2.0.2 to lwip 2.0.3. +And keep the difference between on the change of RT-Thread Team. + +by xiangxistu 2021/06/21 17:00 PM +liuxianliang@rt-thread.com + +The major jobs following RT-Thread Team. The RT-Thread network interface device need to synchronize some network status and address information in lwIP, so it need to make some changes in the lwIP netwrok status and address operations function. +The specific changes are as follows: + + - netif.c: add RT-Thread netdev header file , status synchronize(UP, LINK_UP), address synchronize(IP, netmask, gateway); + + - dns.c: add RT-Thread header file, dns servers synchronize; + + - sockets.c: custom 'select' function implementation in RT-Thread by the wait queue mode. + +by ChenYong 2019/3/26 10:00 AM +chenyong@rt-thread.com + + +Porting lwip 2.0.2 running on RT-Thread. +The major jobs following RT-Thread Team. The RT-Thread team already port the lwip 2.0.0, so I only do some move code and test jobs. +I use the memory pools to test lwip 2.0.2, I use the iperf tool to test it about more than 20 hours, It is running normal. +I don't test it working on memory heap. +... +Good Luck. +by Hans.Huang 2017/3/27 10:52 AM +huangxi_hans@163.com diff --git a/components/net/lwip-2.0.3/SConscript b/components/net/lwip-2.0.3/SConscript new file mode 100644 index 0000000000..36d8e92dc6 --- /dev/null +++ b/components/net/lwip-2.0.3/SConscript @@ -0,0 +1,89 @@ +from building import * + +src = Split(""" +src/arch/sys_arch.c +src/api/api_lib.c +src/api/api_msg.c +src/api/err.c +src/api/netbuf.c +src/api/netdb.c +src/api/netifapi.c +src/api/sockets.c +src/api/tcpip.c +src/core/def.c +src/core/dns.c +src/core/inet_chksum.c +src/core/init.c +src/core/ip.c +src/core/memp.c +src/core/netif.c +src/core/pbuf.c +src/core/raw.c +src/core/stats.c +src/core/sys.c +src/core/tcp.c +src/core/tcp_in.c +src/core/tcp_out.c +src/core/timeouts.c +src/core/udp.c +src/netif/ethernet.c +src/netif/ethernetif.c +src/netif/lowpan6.c +""") + +ipv4_src = Split(""" +src/core/ipv4/autoip.c +src/core/ipv4/dhcp.c +src/core/ipv4/etharp.c +src/core/ipv4/icmp.c +src/core/ipv4/igmp.c +src/core/ipv4/ip4.c +src/core/ipv4/ip4_addr.c +src/core/ipv4/ip4_frag.c +""") + +ipv6_src = Split(""" +src/core/ipv6/dhcp6.c +src/core/ipv6/ethip6.c +src/core/ipv6/icmp6.c +src/core/ipv6/inet6.c +src/core/ipv6/ip6.c +src/core/ipv6/ip6_addr.c +src/core/ipv6/ip6_frag.c +src/core/ipv6/mld6.c +src/core/ipv6/nd6.c +""") + +snmp_src = Glob("src/apps/snmp/*.c") + +ppp_src = Glob("src/netif/ppp/*.c") + Glob("src/netif/ppp/polarssl/*c") + +src = src + ipv4_src + +# The set of source files associated with this SConscript file. +path = [GetCurrentDir() + '/src', + GetCurrentDir() + '/src/include', + GetCurrentDir() + '/src/include/ipv4', + GetCurrentDir() + '/src/arch/include', + GetCurrentDir() + '/src/include/netif'] + +if not GetDepend('RT_USING_SAL'): + path += [GetCurrentDir() + '/src/include/posix'] + +if GetDepend(['RT_LWIP_SNMP']): + src += snmp_src + path += [GetCurrentDir() + '/src/apps/snmp'] + +if GetDepend(['RT_LWIP_PPP']): + src += ppp_src + path += [GetCurrentDir() + '/src/netif/ppp'] + +if GetDepend(['RT_USING_LWIP_IPV6']): + src += ipv6_src + +if GetDepend(['RT_LWIP_USING_PING']): + src += Glob('src/apps/ping/ping.c') + +group = DefineGroup('lwIP', src, depend = ['RT_USING_LWIP', 'RT_USING_LWIP203'], CPPPATH = path) + +Return('group') diff --git a/components/net/lwip-2.0.3/UPGRADING b/components/net/lwip-2.0.3/UPGRADING new file mode 100644 index 0000000000..60a04385d3 --- /dev/null +++ b/components/net/lwip-2.0.3/UPGRADING @@ -0,0 +1,243 @@ +This file lists major changes between release versions that require +ports or applications to be changed. Use it to update a port or an +application written for an older version of lwIP to correctly work +with newer versions. + + +(git master) + + * [Enter new changes just after this line - do not remove this line] + +(2.0.2) + + ++ Application changes: + + * slipif: The way to pass serial port number has changed. netif->num is not + supported any more, netif->state is interpreted as an u8_t port number now + (it's not a POINTER to an u8_t any more!) + +(2.0.1) + + ++ Application changes: + + * UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific + netif any more. Users need to bind to IP_ADDR_ANY to receive multicast traffic and compare + ip_current_netif() to the desired netif for every packet. + See bug #49662 for an explanation. + +(2.0.0) + + ++ Application changes: + + * Changed netif "up" flag handling to be an administrative flag (as opposed to the previous meaning of + "ip4-address-valid", a netif will now not be used for transmission if not up) -> even a DHCP netif + has to be set "up" before starting the DHCP client + * Added IPv6 support (dual-stack or IPv4/IPv6 only) + * Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only). + * Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs); + supports SNMPv2c (experimental v3 support) + * Moved some core applications from contrib repository to src/apps (and include/lwip/apps) + + +++ Raw API: + * Changed TCP listen backlog: removed tcp_accepted(), added the function pair tcp_backlog_delayed()/ + tcp_backlog_accepted() to explicitly delay backlog handling on a connection pcb + + +++ Socket API: + * Added an implementation for posix sendmsg() + * Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram + + ++ Port changes + + +++ new files: + * MANY new and moved files! + * Added src/Filelists.mk for use in Makefile projects + * Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv" + to let abc.h only contain the actual application programmer's API + + +++ sys layer: + * Made LWIP_TCPIP_CORE_LOCKING==1 the default as it usually performs better than + the traditional message passing (although with LWIP_COMPAT_MUTEX you are still + open to priority inversion, so this is not recommended any more) + * Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread + instead of using one per netconn (these semaphores are used even with core locking + enabled as some longer lasting functions like big writes still need to delay) + * Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr() + in def.h (to be overridden in cc.h) instead of config + options for netbiosns, httpd, dns, etc. ... + * New abstraction for hton* and ntoh* functions in def.h. + To override them, use the following in cc.h: + #define lwip_htons(x) + #define lwip_htonl(x) + + +++ new options: + * TODO + + +++ new pools: + * Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools + that share memp.c code but do not have to be made global via lwippools.h + * Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc. + * added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item + is now available + + * Signature of LWIP_HOOK_VLAN_SET macro was changed + + * LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp) + or to move buffers to dedicated memory using compiler attributes + + * Standard C headers are used to define sized types and printf formatters + (disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler + does not support these) + + + ++ Major bugfixes/improvements + + * Added IPv6 support (dual-stack or IPv4/IPv6 only) + * Major rewrite of PPP (incl. keep-up with apache pppd) + see doc/ppp.txt for an upgrading how-to + * Major rewrite of SNMP (incl. MIB parser) + * Fixed timing issues that might have lead to losing a DHCP lease + * Made rx processing path more robust against crafted errors + * TCP window scaling support + * modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads) + * made DNS client more robust + * support PBUF_REF for RX packets + * LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate + threads each (needs LWIP_NETCONN_SEM_PER_THREAD) + * Moved and reordered stats (mainly memp/mib2) + +(1.4.0) + + ++ Application changes: + + * Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for + compatibility to old applications, but will be removed in the future). + + * Renamed mem_realloc() to mem_trim() to prevent confusion with realloc() + + +++ Raw API: + * Changed the semantics of tcp_close() (since it was rather a + shutdown before): Now the application does *NOT* get any calls to the recv + callback (aside from NULL/closed) after calling tcp_close() + + * When calling tcp_abort() from a raw API TCP callback function, + make sure you return ERR_ABRT to prevent accessing unallocated memory. + (ERR_ABRT now means the applicaiton has called tcp_abort!) + + +++ Netconn API: + * Changed netconn_receive() and netconn_accept() to return + err_t, not a pointer to new data/netconn. + + +++ Socket API: + * LWIP_SO_RCVTIMEO: when accept() or recv() time out, they + now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT. + + * Added a minimal version of posix fctl() to have a + standardised way to set O_NONBLOCK for nonblocking sockets. + + +++ all APIs: + * correctly implemented SO(F)_REUSEADDR + + ++ Port changes + + +++ new files: + + * Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h: + + * Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains + the actual application programmer's API + + * Separated timer implementation from sys.h/.c, moved to timers.h/.c; + Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you + still want to use your own timer implementation for NO_SYS==0 (as before). + + +++ sys layer: + + * Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/ + sys_sem_t; + + * Converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + + * Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use + binary semaphores instead of mutexes - as before) + + +++ new options: + + * Don't waste memory when chaining segments, added option TCP_OVERSIZE to + prevent creating many small pbufs when calling tcp_write with many small + blocks of data. Instead, pbufs are allocated larger than needed and the + space is used for later calls to tcp_write. + + * Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs + in tcp_write/udp_send. + + * Added an additional option LWIP_ETHERNET to support ethernet without ARP + (necessary for pure PPPoE) + + * Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may + be used to place these pools into user-defined memory by using external + declaration. + + * Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT + + +++ new pools: + + * Netdb uses a memp pool for allocating memory when getaddrinfo() is called, + so MEMP_NUM_NETDB has to be set accordingly. + + * DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so + MEMP_NUM_LOCALHOSTLIST has to be set accordingly. + + * Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have + to be set accordingly. + + * PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES + has to be set accordingly + + * Integrated loopif into netif.c - loopif does not have to be created by the + port any more, just define LWIP_HAVE_LOOPIF to 1. + + * Added define LWIP_RAND() for lwip-wide randomization (needs to be defined + in cc.h, e.g. used by igmp) + + * Added printf-formatter X8_F to printf u8_t as hex + + * The heap now may be moved to user-defined memory by defining + LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address + + * added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work + with user-allocated structs instead of calling mem_malloc + + * Added const char* name to mem- and memp-stats for easier debugging. + + * Calculate the TCP/UDP checksum while copying to only fetch data once: + Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum + + * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to + more than one pcb. + + * Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned + off any more, if this is set to 0, only one packet (the most recent one) is + queued (like demanded by RFC 1122). + + + ++ Major bugfixes/improvements + + * Implemented tcp_shutdown() to only shut down one end of a connection + * Implemented shutdown() at socket- and netconn-level + * Added errorset support to select() + improved select speed overhead + * Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x) + * Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1 + * Use macros defined in ip_addr.h to work with IP addresses + * Implemented many nonblocking socket/netconn functions + * Fixed ARP input processing: only add a new entry if a request was directed as us + * mem_realloc() to mem_trim() to prevent confusion with realloc() + * Some improvements for AutoIP (don't route/forward link-local addresses, don't break + existing connections when assigning a routable address) + * Correctly handle remote side overrunning our rcv_wnd in ooseq case + * Removed packing from ip_addr_t, the packed version is now only used in protocol headers + * Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0 + * Added support for static ARP table entries + +(STABLE-1.3.2) + + * initial version of this file diff --git a/components/net/lwip-2.0.3/doc/FILES b/components/net/lwip-2.0.3/doc/FILES new file mode 100644 index 0000000000..e588575085 --- /dev/null +++ b/components/net/lwip-2.0.3/doc/FILES @@ -0,0 +1,9 @@ +doxygen/ - Configuration files and scripts to create the lwIP doxygen source + documentation (found at http://www.nongnu.org/lwip/) + +savannah.txt - How to obtain the current development source code. +contrib.txt - How to contribute to lwIP as a developer. +rawapi.txt - The documentation for the core API of lwIP. + Also provides an overview about the other APIs and multithreading. +sys_arch.txt - The documentation for a system abstraction layer of lwIP. +ppp.txt - Documentation of the PPP interface for lwIP. diff --git a/components/net/lwip-2.0.3/doc/NO_SYS_SampleCode.c b/components/net/lwip-2.0.3/doc/NO_SYS_SampleCode.c new file mode 100644 index 0000000000..f0af6600b7 --- /dev/null +++ b/components/net/lwip-2.0.3/doc/NO_SYS_SampleCode.c @@ -0,0 +1,122 @@ +void +eth_mac_irq() +{ + /* Service MAC IRQ here */ + + /* Allocate pbuf from pool (avoid using heap in interrupts) */ + struct pbuf* p = pbuf_alloc(PBUF_RAW, eth_data_count, PBUF_POOL); + + if(p != NULL) { + /* Copy ethernet frame into pbuf */ + pbuf_take(p, eth_data, eth_data_count); + + /* Put in a queue which is processed in main loop */ + if(!queue_try_put(&queue, p)) { + /* queue is full -> packet loss */ + pbuf_free(p); + } + } +} + +static err_t +netif_output(struct netif *netif, struct pbuf *p) +{ + LINK_STATS_INC(link.xmit); + + /* Update SNMP stats (only if you use SNMP) */ + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len); + int unicast = ((p->payload[0] & 0x01) == 0); + if (unicast) { + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + } else { + MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); + } + + lock_interrupts(); + pbuf_copy_partial(p, mac_send_buffer, p->tot_len, 0); + /* Start MAC transmit here */ + unlock_interrupts(); + + return ERR_OK; +} + +static void +netif_status_callback(struct netif *netif) +{ + printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif))); +} + +static err_t +netif_init(struct netif *netif) +{ + netif->linkoutput = netif_output; + netif->output = etharp_output; + netif->output_ip6 = ethip6_output; + netif->mtu = ETHERNET_MTU; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6; + MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, 100000000); + + SMEMCPY(netif->hwaddr, your_mac_address_goes_here, sizeof(netif->hwaddr)); + netif->hwaddr_len = sizeof(netif->hwaddr); + + return ERR_OK; +} + +void +main(void) +{ + struct netif netif; + + lwip_init(); + + netif_add(&netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY, NULL, netif_init, netif_input); + netif.name[0] = 'e'; + netif.name[1] = '0'; + netif_create_ip6_linklocal_address(&netif, 1); + netif.ip6_autoconfig_enabled = 1; + netif_set_status_callback(&netif, netif_status_callback); + netif_set_default(&netif); + netif_set_up(&netif); + + /* Start DHCP and HTTPD */ + dhcp_start(&netif ); + httpd_init(); + + while(1) { + /* Check link state, e.g. via MDIO communication with PHY */ + if(link_state_changed()) { + if(link_is_up()) { + netif_set_link_up(&netif); + } else { + netif_set_link_down(&netif); + } + } + + /* Check for received frames, feed them to lwIP */ + lock_interrupts(); + struct pbuf* p = queue_try_get(&queue); + unlock_interrupts(); + + if(p != NULL) { + LINK_STATS_INC(link.recv); + + /* Update SNMP stats (only if you use SNMP) */ + MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); + int unicast = ((p->payload[0] & 0x01) == 0); + if (unicast) { + MIB2_STATS_NETIF_INC(netif, ifinucastpkts); + } else { + MIB2_STATS_NETIF_INC(netif, ifinnucastpkts); + } + + if(netif.input(p, &netif) != ERR_OK) { + pbuf_free(p); + } + } + + /* Cyclic lwIP timers check */ + sys_check_timeouts(); + + /* your application goes here */ + } +} diff --git a/components/net/lwip-2.0.3/doc/contrib.txt b/components/net/lwip-2.0.3/doc/contrib.txt new file mode 100644 index 0000000000..6f0d7bc516 --- /dev/null +++ b/components/net/lwip-2.0.3/doc/contrib.txt @@ -0,0 +1,58 @@ +1 Introduction + +This document describes some guidelines for people participating +in lwIP development. + +2 How to contribute to lwIP + +Here is a short list of suggestions to anybody working with lwIP and +trying to contribute bug reports, fixes, enhancements, platform ports etc. +First of all as you may already know lwIP is a volunteer project so feedback +to fixes or questions might often come late. Hopefully the bug and patch tracking +features of Savannah help us not lose users' input. + +2.1 Source code style: + +1. do not use tabs. +2. indentation is two spaces per level (i.e. per tab). +3. end debug messages with a trailing newline (\n). +4. one space between keyword and opening bracket. +5. no space between function and opening bracket. +6. one space and no newline before opening curly braces of a block. +7. closing curly brace on a single line. +8. spaces surrounding assignment and comparisons. +9. don't initialize static and/or global variables to zero, the compiler takes care of that. +10. use current source code style as further reference. + +2.2 Source code documentation style: + +1. JavaDoc compliant and Doxygen compatible. +2. Function documentation above functions in .c files, not .h files. + (This forces you to synchronize documentation and implementation.) +3. Use current documentation style as further reference. + +2.3 Bug reports and patches: + +1. Make sure you are reporting bugs or send patches against the latest + sources. (From the latest release and/or the current Git sources.) +2. If you think you found a bug make sure it's not already filed in the + bugtracker at Savannah. +3. If you have a fix put the patch on Savannah. If it is a patch that affects + both core and arch specific stuff please separate them so that the core can + be applied separately while leaving the other patch 'open'. The preferred way + is to NOT touch archs you can't test and let maintainers take care of them. + This is a good way to see if they are used at all - the same goes for unix + netifs except tapif. +4. Do not file a bug and post a fix to it to the patch area. Either a bug report + or a patch will be enough. + If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area. +5. Patches should be specific to a single change or to related changes. Do not mix bugfixes with spelling and other + trivial fixes unless the bugfix is trivial too. Do not reorganize code and rename identifiers in the same patch you + change behaviour if not necessary. A patch is easier to read and understand if it's to the point and short than + if it's not to the point and long :) so the chances for it to be applied are greater. + +2.4 Platform porters: + +1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and + you think it could benefit others[1] you might want discuss this on the mailing list. You + can also ask for Git access to submit and maintain your port in the contrib Git module. diff --git a/components/net/lwip-2.0.3/doc/doxygen/generate.bat b/components/net/lwip-2.0.3/doc/doxygen/generate.bat new file mode 100644 index 0000000000..4eab18c7f4 --- /dev/null +++ b/components/net/lwip-2.0.3/doc/doxygen/generate.bat @@ -0,0 +1 @@ +doxygen lwip.Doxyfile diff --git a/components/net/lwip-2.0.3/doc/doxygen/generate.sh b/components/net/lwip-2.0.3/doc/doxygen/generate.sh new file mode 100644 index 0000000000..89344b0e81 --- /dev/null +++ b/components/net/lwip-2.0.3/doc/doxygen/generate.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +doxygen lwip.Doxyfile diff --git a/components/net/lwip-2.0.3/doc/doxygen/lwip.Doxyfile b/components/net/lwip-2.0.3/doc/doxygen/lwip.Doxyfile new file mode 100644 index 0000000000..95fa363b41 --- /dev/null +++ b/components/net/lwip-2.0.3/doc/doxygen/lwip.Doxyfile @@ -0,0 +1,2505 @@ +# Doxyfile 1.8.11 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "lwIP" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = "2.0.3" + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "Lightweight IP stack" + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = output + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class " \ + "The $name widget " \ + "The $name file " \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = ../../ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = main_page.h ../../src + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, +# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.inc \ + *.m \ + *.mm \ + *.dox + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = ../../src/include/netif/ppp/polarssl + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = ../ ../../ + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = main_page.h + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = NO + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = lwip.chm + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /
index.html + + diff --git a/components/net/lwip-2.0.3/doc/mdns.txt b/components/net/lwip-2.0.3/doc/mdns.txt new file mode 100644 index 0000000000..c322843217 --- /dev/null +++ b/components/net/lwip-2.0.3/doc/mdns.txt @@ -0,0 +1,113 @@ +Multicast DNS for lwIP + +Author: Erik Ekman + + +Note! The MDNS responder does not have all features required by the standards. +See notes in src/apps/mdns/mdns.c for what is left. It is however usable in normal +cases - but watch out if many devices on the same network try to use the same +host/service instance names. + + +How to enable: +============== + +MDNS support does not depend on DNS. +MDNS supports using IPv4 only, v6 only, or v4+v6. + +To enable MDNS responder, set + LWIP_MDNS_RESPONDER = 1 +in lwipopts.h and add src/apps/mdns/mdns.c to your list of files to build. + +The max number of services supported per netif is defined by MDNS_MAX_SERVICES, +default is 1. + +Increase MEMP_NUM_UDP_PCB by 1. MDNS needs one PCB. +Increase LWIP_NUM_NETIF_CLIENT_DATA by 1 (MDNS needs one entry on netif). + +MDNS with IPv4 requires LWIP_IGMP = 1, and preferably LWIP_AUTOIP = 1. +MDNS with IPv6 requires LWIP_IPV6_MLD = 1, and that a link-local address is +generated. + +The MDNS code puts its structs on the stack where suitable to reduce dynamic +memory allocation. It may use up to 1kB of stack. + +MDNS needs a strncasecmp() implementation. If you have one, define +LWIP_MDNS_STRNCASECMP to it. Otherwise the code will provide an implementation +for you. + + +How to use: +=========== + +Call mdns_resp_init() during system initialization. +This opens UDP sockets on port 5353 for IPv4 and IPv6. + + +To start responding on a netif, run + mdns_resp_add_netif(struct netif *netif, char *hostname, u32_t dns_ttl) + +The hostname will be copied. If this returns successfully, the netif will join +the multicast groups and any MDNS/legacy DNS requests sent unicast or multicast +to port 5353 will be handled: +- .local type A, AAAA or ANY returns relevant IP addresses +- Reverse lookups (PTR in-addr.arpa, ip6.arpa) of netif addresses + returns .local +Answers will use the supplied TTL (in seconds) +MDNS allows UTF-8 names, but it is recommended to stay within ASCII, +since the default case-insensitive comparison assumes this. + +It is recommended to call this function after an IPv4 address has been set, +since there is currently no check if the v4 address is valid. + +Call mdns_resp_netif_settings_changed() every time the IP address +on the netif has changed. + +To stop responding on a netif, run + mdns_resp_remove_netif(struct netif *netif) + + +Adding services: +================ + +The netif first needs to be registered. Then run + mdns_resp_add_service(struct netif *netif, char *name, char *service, + u16_t proto, u16_t port, u32_t dns_ttl, + service_get_txt_fn_t txt_fn, void *txt_userdata); + +The name and service pointers will be copied. Name refers to the name of the +service instance, and service is the type of service, like _http +proto can be DNSSD_PROTO_UDP or DNSSD_PROTO_TCP which represent _udp and _tcp. +If this call returns successfully, the following queries will be answered: +- _services._dns-sd._udp.local type PTR returns ..local +- ..local type PTR returns ...local +- ...local type SRV returns hostname and port of service +- ...local type TXT builds text strings by calling txt_fn + with the supplied userdata. The callback adds strings to the reply by calling + mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt, + int txt_len). Example callback method: + + static void srv_txt(struct mdns_service *service, void *txt_userdata) + { + res = mdns_resp_add_service_txtitem(service, "path=/", 6); + LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return); + } + + Since a hostname struct is used for TXT storage each single item can be max + 63 bytes long, and the total max length (including length bytes for each + item) is 255 bytes. + +If your device runs a webserver on port 80, an example call might be: + + mdns_resp_add_service(netif, "myweb", "_http" + DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL); + +which will publish myweb._http._tcp.local for any hosts looking for web servers, +and point them to .local:80 + +Relevant information will be sent as additional records to reduce number of +requests required from a client. + +Removing services is currently not supported. Services are removed when the +netif is removed. + diff --git a/components/net/lwip-2.0.3/doc/mqtt_client.txt b/components/net/lwip-2.0.3/doc/mqtt_client.txt new file mode 100644 index 0000000000..3e67defdc5 --- /dev/null +++ b/components/net/lwip-2.0.3/doc/mqtt_client.txt @@ -0,0 +1,162 @@ +MQTT client for lwIP + +Author: Erik Andersson + +Details of the MQTT protocol can be found at: +http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html + +----------------------------------------------------------------- +1. Initial steps, reserve memory and make connection to server: + +1.1: Provide storage + +Static allocation: + mqtt_client_t static_client; + example_do_connect(&static_client); + +Dynamic allocation: + mqtt_client_t *client = mqtt_client_new(); + if(client != NULL) { + example_do_connect(&client); + } + +1.2: Establish Connection with server + +void example_do_connect(mqtt_client_t *client) +{ + struct mqtt_connect_client_info_t ci; + err_t err; + + /* Setup an empty client info structure */ + memset(&ci, 0, sizeof(ci)); + + /* Minimal amount of information required is client identifier, so set it here */ + ci.client_id = "lwip_test"; + + /* Initiate client and connect to server, if this fails immediately an error code is returned + otherwise mqtt_connection_cb will be called with connection result after attempting + to establish a connection with the server. + For now MQTT version 3.1.1 is always used */ + + err = mqtt_client_connect(client, ip_addr, MQTT_PORT, mqtt_connection_cb, 0, &ci); + + /* For now just print the result code if something goes wrong + if(err != ERR_OK) { + printf("mqtt_connect return %d\n", err); + } +} + +Connection to server can also be probed by calling mqtt_client_is_connected(client) + +----------------------------------------------------------------- +2. Implementing the connection status callback + + +static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) +{ + err_t err; + if(status == MQTT_CONNECT_ACCEPTED) { + printf("mqtt_connection_cb: Successfully connected\n"); + + /* Setup callback for incoming publish requests */ + mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg); + + /* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */ + err = mqtt_subscribe(client, "subtopic", 1, mqtt_sub_request_cb, arg); + + if(err != ERR_OK) { + printf("mqtt_subscribe return: %d\n", err); + } + } else { + printf("mqtt_connection_cb: Disconnected, reason: %d\n", status); + + /* Its more nice to be connected, so try to reconnect */ + example_do_connect(client); + } +} + +static void mqtt_sub_request_cb(void *arg, err_t result) +{ + /* Just print the result code here for simplicity, + normal behaviour would be to take some action if subscribe fails like + notifying user, retry subscribe or disconnect from server */ + printf("Subscribe result: %d\n", result); +} + +----------------------------------------------------------------- +3. Implementing callbacks for incoming publish and data + +/* The idea is to demultiplex topic and create some reference to be used in data callbacks + Example here uses a global variable, better would be to use a member in arg + If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of + the topic string and use it in mqtt_incoming_data_cb +*/ +static int inpub_id; +static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len) +{ + printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len); + + /* Decode topic string into a user defined reference */ + if(strcmp(topic, "print_payload") == 0) { + inpub_id = 0; + } else if(topic[0] == 'A') { + /* All topics starting with 'A' might be handled at the same way */ + inpub_id = 1; + } else { + /* For all other topics */ + inpub_id = 2; + } +} + +static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags) +{ + printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags); + + if(flags & MQTT_DATA_FLAG_LAST) { + /* Last fragment of payload received (or whole part if payload fits receive buffer + See MQTT_VAR_HEADER_BUFFER_LEN) */ + + /* Call function or do action depending on reference, in this case inpub_id */ + if(inpub_id == 0) { + /* Don't trust the publisher, check zero termination */ + if(data[len-1] == 0) { + printf("mqtt_incoming_data_cb: %s\n", (const char *)data); + } + } else if(inpub_id == 1) { + /* Call an 'A' function... */ + } else { + printf("mqtt_incoming_data_cb: Ignoring payload...\n"); + } + } else { + /* Handle fragmented payload, store in buffer, write to file or whatever */ + } +} + +----------------------------------------------------------------- +4. Using outgoing publish + + +void example_publish(mqtt_client_t *client, void *arg) +{ + const char *pub_payload= "PubSubHubLubJub"; + err_t err; + u8_t qos = 2; /* 0 1 or 2, see MQTT specification */ + u8_t retain = 0; /* No don't retain such crappy payload... */ + err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg); + if(err != ERR_OK) { + printf("Publish err: %d\n", err); + } +} + +/* Called when publish is complete either with sucess or failure */ +static void mqtt_pub_request_cb(void *arg, err_t result) +{ + if(result != ERR_OK) { + printf("Publish result: %d\n", result); + } +} + +----------------------------------------------------------------- +5. Disconnecting + +Simply call mqtt_disconnect(client) diff --git a/components/net/lwip-2.0.3/doc/ppp.txt b/components/net/lwip-2.0.3/doc/ppp.txt new file mode 100644 index 0000000000..8b88b3a671 --- /dev/null +++ b/components/net/lwip-2.0.3/doc/ppp.txt @@ -0,0 +1,529 @@ +PPP interface for lwIP + +Author: Sylvain Rochet + +Table of Contents: + +1 - Supported PPP protocols and features +2 - Raw API PPP example for all protocols +3 - PPPoS input path (raw API, IRQ safe API, TCPIP API) +4 - Thread safe PPP API (PPPAPI) +5 - Notify phase callback (PPP_NOTIFY_PHASE) +6 - Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x + + + +1 Supported PPP protocols and features +====================================== + +Supported Low level protocols: +* PPP over serial using HDLC-like framing, such as wired dialup modems + or mobile telecommunications GPRS/EDGE/UMTS/HSPA+/LTE modems +* PPP over Ethernet, such as xDSL modems +* PPP over L2TP (Layer 2 Tunneling Protocol) LAC (L2TP Access Concentrator), + IP tunnel over UDP, such as VPN access + +Supported auth protocols: +* PAP, Password Authentication Protocol +* CHAP, Challenge-Handshake Authentication Protocol, also known as CHAP-MD5 +* MSCHAPv1, Microsoft version of CHAP, version 1 +* MSCHAPv2, Microsoft version of CHAP, version 2 +* EAP, Extensible Authentication Protocol + +Supported address protocols: +* IPCP, IP Control Protocol, IPv4 addresses negotiation +* IP6CP, IPv6 Control Protocol, IPv6 link-local addresses negotiation + +Supported encryption protocols: +* MPPE, Microsoft Point-to-Point Encryption + +Supported compression or miscellaneous protocols, for serial links only: +* PFC, Protocol Field Compression +* ACFC, Address-and-Control-Field-Compression +* ACCM, Asynchronous-Control-Character-Map +* VJ, Van Jacobson TCP/IP Header Compression + + + +2 Raw API PPP example for all protocols +======================================= + +As usual, raw API for lwIP means the lightweight API which *MUST* only be used +for NO_SYS=1 systems or called inside lwIP core thread for NO_SYS=0 systems. + +/* + * Globals + * ======= + */ + +/* The PPP control block */ +ppp_pcb *ppp; + +/* The PPP IP interface */ +struct netif ppp_netif; + + +/* + * PPP status callback + * =================== + * + * PPP status callback is called on PPP status change (up, down, …) from lwIP + * core thread + */ + +/* PPP status callback example */ +static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) { + struct netif *pppif = ppp_netif(pcb); + LWIP_UNUSED_ARG(ctx); + + switch(err_code) { + case PPPERR_NONE: { +#if LWIP_DNS + const ip_addr_t *ns; +#endif /* LWIP_DNS */ + printf("status_cb: Connected\n"); +#if PPP_IPV4_SUPPORT + printf(" our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr)); + printf(" his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw)); + printf(" netmask = %s\n", ipaddr_ntoa(&pppif->netmask)); +#if LWIP_DNS + ns = dns_getserver(0); + printf(" dns1 = %s\n", ipaddr_ntoa(ns)); + ns = dns_getserver(1); + printf(" dns2 = %s\n", ipaddr_ntoa(ns)); +#endif /* LWIP_DNS */ +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + printf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0))); +#endif /* PPP_IPV6_SUPPORT */ + break; + } + case PPPERR_PARAM: { + printf("status_cb: Invalid parameter\n"); + break; + } + case PPPERR_OPEN: { + printf("status_cb: Unable to open PPP session\n"); + break; + } + case PPPERR_DEVICE: { + printf("status_cb: Invalid I/O device for PPP\n"); + break; + } + case PPPERR_ALLOC: { + printf("status_cb: Unable to allocate resources\n"); + break; + } + case PPPERR_USER: { + printf("status_cb: User interrupt\n"); + break; + } + case PPPERR_CONNECT: { + printf("status_cb: Connection lost\n"); + break; + } + case PPPERR_AUTHFAIL: { + printf("status_cb: Failed authentication challenge\n"); + break; + } + case PPPERR_PROTOCOL: { + printf("status_cb: Failed to meet protocol\n"); + break; + } + case PPPERR_PEERDEAD: { + printf("status_cb: Connection timeout\n"); + break; + } + case PPPERR_IDLETIMEOUT: { + printf("status_cb: Idle Timeout\n"); + break; + } + case PPPERR_CONNECTTIME: { + printf("status_cb: Max connect time reached\n"); + break; + } + case PPPERR_LOOPBACK: { + printf("status_cb: Loopback detected\n"); + break; + } + default: { + printf("status_cb: Unknown error code %d\n", err_code); + break; + } + } + +/* + * This should be in the switch case, this is put outside of the switch + * case for example readability. + */ + + if (err_code == PPPERR_NONE) { + return; + } + + /* ppp_close() was previously called, don't reconnect */ + if (err_code == PPPERR_USER) { + /* ppp_free(); -- can be called here */ + return; + } + + /* + * Try to reconnect in 30 seconds, if you need a modem chatscript you have + * to do a much better signaling here ;-) + */ + ppp_connect(pcb, 30); + /* OR ppp_listen(pcb); */ +} + + +/* + * Creating a new PPPoS session + * ============================ + * + * In lwIP, PPPoS is not PPPoSONET, in lwIP PPPoS is PPPoSerial. + */ + +#include "netif/ppp/pppos.h" + +/* + * PPPoS serial output callback + * + * ppp_pcb, PPP control block + * data, buffer to write to serial port + * len, length of the data buffer + * ctx, optional user-provided callback context pointer + * + * Return value: len if write succeed + */ +static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) { + return uart_write(UART, data, len); +} + +/* + * Create a new PPPoS interface + * + * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface + * output_cb, PPPoS serial output callback + * status_cb, PPP status callback, called on PPP status change (up, down, …) + * ctx_cb, optional user-provided callback context pointer + */ +ppp = pppos_create(&ppp_netif, + output_cb, status_cb, ctx_cb); + + +/* + * Creating a new PPPoE session + * ============================ + */ + +#include "netif/ppp/pppoe.h" + +/* + * Create a new PPPoE interface + * + * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface + * ethif, already existing and setup Ethernet interface to use + * service_name, PPPoE service name discriminator (not supported yet) + * concentrator_name, PPPoE concentrator name discriminator (not supported yet) + * status_cb, PPP status callback, called on PPP status change (up, down, …) + * ctx_cb, optional user-provided callback context pointer + */ +ppp = pppoe_create(&ppp_netif, + ðif, + service_name, concentrator_name, + status_cb, ctx_cb); + + +/* + * Creating a new PPPoL2TP session + * =============================== + */ + +#include "netif/ppp/pppol2tp.h" + +/* + * Create a new PPPoL2TP interface + * + * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface + * netif, optional already existing and setup output netif, necessary if you + * want to set this interface as default route to settle the chicken + * and egg problem with VPN links + * ipaddr, IP to connect to + * port, UDP port to connect to (usually 1701) + * secret, L2TP secret to use + * secret_len, size in bytes of the L2TP secret + * status_cb, PPP status callback, called on PPP status change (up, down, …) + * ctx_cb, optional user-provided callback context pointer + */ +ppp = pppol2tp_create(&ppp_netif, + struct netif *netif, ip_addr_t *ipaddr, u16_t port, + u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + + +/* + * Initiate PPP client connection + * ============================== + */ + +/* Set this interface as default route */ +ppp_set_default(ppp); + +/* + * Basic PPP client configuration. Can only be set if PPP session is in the + * dead state (i.e. disconnected). We don't need to provide thread-safe + * equivalents through PPPAPI because those helpers are only changing + * structure members while session is inactive for lwIP core. Configuration + * only need to be done once. + */ + +/* Ask the peer for up to 2 DNS server addresses. */ +ppp_set_usepeerdns(ppp, 1); + +/* Auth configuration, this is pretty self-explanatory */ +ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password"); + +/* + * Initiate PPP negotiation, without waiting (holdoff=0), can only be called + * if PPP session is in the dead state (i.e. disconnected). + */ +u16_t holdoff = 0; +ppp_connect(ppp, holdoff); + + +/* + * Initiate PPP server listener + * ============================ + */ + +/* + * Basic PPP server configuration. Can only be set if PPP session is in the + * dead state (i.e. disconnected). We don't need to provide thread-safe + * equivalents through PPPAPI because those helpers are only changing + * structure members while session is inactive for lwIP core. Configuration + * only need to be done once. + */ +ip4_addr_t addr; + +/* Set our address */ +IP4_ADDR(&addr, 192,168,0,1); +ppp_set_ipcp_ouraddr(ppp, &addr); + +/* Set peer(his) address */ +IP4_ADDR(&addr, 192,168,0,2); +ppp_set_ipcp_hisaddr(ppp, &addr); + +/* Set primary DNS server */ +IP4_ADDR(&addr, 192,168,10,20); +ppp_set_ipcp_dnsaddr(ppp, 0, &addr); + +/* Set secondary DNS server */ +IP4_ADDR(&addr, 192,168,10,21); +ppp_set_ipcp_dnsaddr(ppp, 1, &addr); + +/* Auth configuration, this is pretty self-explanatory */ +ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password"); + +/* Require peer to authenticate */ +ppp_set_auth_required(ppp, 1); + +/* + * Only for PPPoS, the PPP session should be up and waiting for input. + * + * Note: for PPPoS, ppp_connect() and ppp_listen() are actually the same thing. + * The listen call is meant for future support of PPPoE and PPPoL2TP server + * mode, where we will need to negotiate the incoming PPPoE session or L2TP + * session before initiating PPP itself. We need this call because there is + * two passive modes for PPPoS, ppp_set_passive and ppp_set_silent. + */ +ppp_set_silent(pppos, 1); + +/* + * Initiate PPP listener (i.e. wait for an incoming connection), can only + * be called if PPP session is in the dead state (i.e. disconnected). + */ +ppp_listen(ppp); + + +/* + * Closing PPP connection + * ====================== + */ + +/* + * Initiate the end of the PPP session, without carrier lost signal + * (nocarrier=0), meaning a clean shutdown of PPP protocols. + * You can call this function at anytime. + */ +u8_t nocarrier = 0; +ppp_close(ppp, nocarrier); +/* + * Then you must wait your status_cb() to be called, it may takes from a few + * seconds to several tens of seconds depending on the current PPP state. + */ + +/* + * Freeing a PPP connection + * ======================== + */ + +/* + * Free the PPP control block, can only be called if PPP session is in the + * dead state (i.e. disconnected). You need to call ppp_close() before. + */ +ppp_free(ppp); + + + +3 PPPoS input path (raw API, IRQ safe API, TCPIP API) +===================================================== + +Received data on serial port should be sent to lwIP using the pppos_input() +function or the pppos_input_tcpip() function. + +If NO_SYS is 1 and if PPP_INPROC_IRQ_SAFE is 0 (the default), pppos_input() +is not IRQ safe and then *MUST* only be called inside your main loop. + +Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQ +safe and can be safely called from an interrupt context, using that is going +to reduce your need of buffer if pppos_input() is called byte after byte in +your rx serial interrupt. + +if NO_SYS is 0, the thread safe way outside an interrupt context is to use +the pppos_input_tcpip() function to pass input data to the lwIP core thread +using the TCPIP API. This is thread safe in all cases but you should avoid +passing data byte after byte because it uses heavy locking (mailbox) and it +allocates pbuf, better fill them ! + +if NO_SYS is 0 and if PPP_INPROC_IRQ_SAFE is 1, you may also use pppos_input() +from an RX thread, however pppos_input() is not thread safe by itself. You can +do that *BUT* you should NEVER call pppos_connect(), pppos_listen() and +ppp_free() if pppos_input() can still be running, doing this is NOT thread safe +at all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless you +really know what you are doing, your move ;-) + + +/* + * Fonction to call for received data + * + * ppp, PPP control block + * buffer, input buffer + * buffer_len, buffer length in bytes + */ +void pppos_input(ppp, buffer, buffer_len); + +or + +void pppos_input_tcpip(ppp, buffer, buffer_len); + + + +4 Thread safe PPP API (PPPAPI) +============================== + +There is a thread safe API for all corresponding ppp_* functions, you have to +enable LWIP_PPP_API in your lwipopts.h file, then see +include/netif/ppp/pppapi.h, this is actually pretty obvious. + + + +5 Notify phase callback (PPP_NOTIFY_PHASE) +========================================== + +Notify phase callback, enabled using the PPP_NOTIFY_PHASE config option, let +you configure a callback that is called on each PPP internal state change. +This is different from the status callback which only warns you about +up(running) and down(dead) events. + +Notify phase callback can be used, for example, to set a LED pattern depending +on the current phase of the PPP session. Here is a callback example which +tries to mimic what we usually see on xDSL modems while they are negotiating +the link, which should be self-explanatory: + +static void ppp_notify_phase_cb(ppp_pcb *pcb, u8_t phase, void *ctx) { + switch (phase) { + + /* Session is down (either permanently or briefly) */ + case PPP_PHASE_DEAD: + led_set(PPP_LED, LED_OFF); + break; + + /* We are between two sessions */ + case PPP_PHASE_HOLDOFF: + led_set(PPP_LED, LED_SLOW_BLINK); + break; + + /* Session just started */ + case PPP_PHASE_INITIALIZE: + led_set(PPP_LED, LED_FAST_BLINK); + break; + + /* Session is running */ + case PPP_PHASE_RUNNING: + led_set(PPP_LED, LED_ON); + break; + + default: + break; + } +} + + + +6 Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x +=============================================== + +PPP API was fully reworked between 1.4.x and 2.0.x releases. However porting +from previous lwIP version is pretty easy: + +* Previous PPP API used an integer to identify PPP sessions, we are now + using ppp_pcb* control block, therefore all functions changed from "int ppp" + to "ppp_pcb *ppp" + +* struct netif was moved outside the PPP structure, you have to provide a netif + for PPP interface in pppoX_create() functions + +* PPP session are not started automatically after you created them anymore, + you have to call ppp_connect(), this way you can configure the session before + starting it. + +* Previous PPP API used CamelCase, we are now using snake_case. + +* Previous PPP API mixed PPPoS and PPPoE calls, this isn't the case anymore, + PPPoS functions are now prefixed pppos_ and PPPoE functions are now prefixed + pppoe_, common functions are now prefixed ppp_. + +* New PPPERR_ error codes added, check you have all of them in your status + callback function + +* Only the following include files should now be used in user application: + #include "netif/ppp/pppapi.h" + #include "netif/ppp/pppos.h" + #include "netif/ppp/pppoe.h" + #include "netif/ppp/pppol2tp.h" + + Functions from ppp.h can be used, but you don't need to include this header + file as it is already included by above header files. + +* PPP_INPROC_OWNTHREAD was broken by design and was removed, you have to create + your own serial rx thread + +* PPP_INPROC_MULTITHREADED option was misnamed and confusing and was renamed + PPP_INPROC_IRQ_SAFE, please read the "PPPoS input path" documentation above + because you might have been fooled by that + +* If you used tcpip_callback_with_block() on ppp_ functions you may wish to use + the PPPAPI API instead. + +* ppp_sighup and ppp_close functions were merged using an optional argument + "nocarrier" on ppp_close. + +* DNS servers are now only remotely asked if LWIP_DNS is set and if + ppp_set_usepeerdns() is set to true, they are now automatically registered + using the dns_setserver() function so you don't need to do that in the PPP + callback anymore. + +* PPPoS does not use the SIO API anymore, as such it now requires a serial + output callback in place of sio_write + +* PPP_MAXIDLEFLAG is now in ms instead of jiffies diff --git a/components/net/lwip-2.0.3/doc/rawapi.txt b/components/net/lwip-2.0.3/doc/rawapi.txt new file mode 100644 index 0000000000..0cdfdcead1 --- /dev/null +++ b/components/net/lwip-2.0.3/doc/rawapi.txt @@ -0,0 +1,499 @@ +Raw TCP/IP interface for lwIP + +Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons + +lwIP provides three Application Program's Interfaces (APIs) for programs +to use for communication with the TCP/IP code: +* low-level "core" / "callback" or "raw" API. +* higher-level "sequential" API. +* BSD-style socket API. + +The raw API (sometimes called native API) is an event-driven API designed +to be used without an operating system that implements zero-copy send and +receive. This API is also used by the core stack for interaction between +the various protocols. It is the only API available when running lwIP +without an operating system. + +The sequential API provides a way for ordinary, sequential, programs +to use the lwIP stack. It is quite similar to the BSD socket API. The +model of execution is based on the blocking open-read-write-close +paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP +code and the application program must reside in different execution +contexts (threads). + +The socket API is a compatibility API for existing applications, +currently it is built on top of the sequential API. It is meant to +provide all functions needed to run socket API applications running +on other platforms (e.g. unix / windows etc.). However, due to limitations +in the specification of this API, there might be incompatibilities +that require small modifications of existing programs. + +** Multithreading + +lwIP started targeting single-threaded environments. When adding multi- +threading support, instead of making the core thread-safe, another +approach was chosen: there is one main thread running the lwIP core +(also known as the "tcpip_thread"). When running in a multithreaded +environment, raw API functions MUST only be called from the core thread +since raw API functions are not protected from concurrent access (aside +from pbuf- and memory management functions). Application threads using +the sequential- or socket API communicate with this main thread through +message passing. + + As such, the list of functions that may be called from + other threads or an ISR is very limited! Only functions + from these API header files are thread-safe: + - api.h + - netbuf.h + - netdb.h + - netifapi.h + - pppapi.h + - sockets.h + - sys.h + + Additionaly, memory (de-)allocation functions may be + called from multiple threads (not ISR!) with NO_SYS=0 + since they are protected by SYS_LIGHTWEIGHT_PROT and/or + semaphores. + + Netconn or Socket API functions are thread safe against the + core thread but they are not reentrant at the control block + granularity level. That is, a UDP or TCP control block must + not be shared among multiple threads without proper locking. + + If SYS_LIGHTWEIGHT_PROT is set to 1 and + LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1, + pbuf_free() may also be called from another thread or + an ISR (since only then, mem_free - for PBUF_RAM - may + be called from an ISR: otherwise, the HEAP is only + protected by semaphores). + + +** The remainder of this document discusses the "raw" API. ** + +The raw TCP/IP interface allows the application program to integrate +better with the TCP/IP code. Program execution is event based by +having callback functions being called from within the TCP/IP +code. The TCP/IP code and the application program both run in the same +thread. The sequential API has a much higher overhead and is not very +well suited for small systems since it forces a multithreaded paradigm +on the application. + +The raw TCP/IP interface is not only faster in terms of code execution +time but is also less memory intensive. The drawback is that program +development is somewhat harder and application programs written for +the raw TCP/IP interface are more difficult to understand. Still, this +is the preferred way of writing applications that should be small in +code size and memory usage. + +All APIs can be used simultaneously by different application +programs. In fact, the sequential API is implemented as an application +program using the raw TCP/IP interface. + +Do not confuse the lwIP raw API with raw Ethernet or IP sockets. +The former is a way of interfacing the lwIP network stack (including +TCP and UDP), the later refers to processing raw Ethernet or IP data +instead of TCP connections or UDP packets. + +Raw API applications may never block since all packet processing +(input and output) as well as timer processing (TCP mainly) is done +in a single execution context. + +--- Callbacks + +Program execution is driven by callbacks functions, which are then +invoked by the lwIP core when activity related to that application +occurs. A particular application may register to be notified via a +callback function for events such as incoming data available, outgoing +data sent, error notifications, poll timer expiration, connection +closed, etc. An application can provide a callback function to perform +processing for any or all of these events. Each callback is an ordinary +C function that is called from within the TCP/IP code. Every callback +function is passed the current TCP or UDP connection state as an +argument. Also, in order to be able to keep program specific state, +the callback functions are called with a program specified argument +that is independent of the TCP/IP state. + +The function for setting the application connection state is: + +- void tcp_arg(struct tcp_pcb *pcb, void *arg) + + Specifies the program specific state that should be passed to all + other callback functions. The "pcb" argument is the current TCP + connection control block, and the "arg" argument is the argument + that will be passed to the callbacks. + + +--- TCP connection setup + +The functions used for setting up connections is similar to that of +the sequential API and of the BSD socket API. A new TCP connection +identifier (i.e., a protocol control block - PCB) is created with the +tcp_new() function. This PCB can then be either set to listen for new +incoming connections or be explicitly connected to another host. + +- struct tcp_pcb *tcp_new(void) + + Creates a new connection identifier (PCB). If memory is not + available for creating the new pcb, NULL is returned. + +- err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Binds the pcb to a local IP address and port number. The IP address + can be specified as IP_ADDR_ANY in order to bind the connection to + all local IP addresses. + + If another connection is bound to the same port, the function will + return ERR_USE, otherwise ERR_OK is returned. + +- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb) + + Commands a pcb to start listening for incoming connections. When an + incoming connection is accepted, the function specified with the + tcp_accept() function will be called. The pcb will have to be bound + to a local port with the tcp_bind() function. + + The tcp_listen() function returns a new connection identifier, and + the one passed as an argument to the function will be + deallocated. The reason for this behavior is that less memory is + needed for a connection that is listening, so tcp_listen() will + reclaim the memory needed for the original connection and allocate a + new smaller memory block for the listening connection. + + tcp_listen() may return NULL if no memory was available for the + listening connection. If so, the memory associated with the pcb + passed as an argument to tcp_listen() will not be deallocated. + +- struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) + + Same as tcp_listen, but limits the number of outstanding connections + in the listen queue to the value specified by the backlog argument. + To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h. + +- void tcp_accept(struct tcp_pcb *pcb, + err_t (* accept)(void *arg, struct tcp_pcb *newpcb, + err_t err)) + + Specified the callback function that should be called when a new + connection arrives on a listening connection. + +- err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port, err_t (* connected)(void *arg, + struct tcp_pcb *tpcb, + err_t err)); + + Sets up the pcb to connect to the remote host and sends the + initial SYN segment which opens the connection. + + The tcp_connect() function returns immediately; it does not wait for + the connection to be properly setup. Instead, it will call the + function specified as the fourth argument (the "connected" argument) + when the connection is established. If the connection could not be + properly established, either because the other host refused the + connection or because the other host didn't answer, the "err" + callback function of this pcb (registered with tcp_err, see below) + will be called. + + The tcp_connect() function can return ERR_MEM if no memory is + available for enqueueing the SYN segment. If the SYN indeed was + enqueued successfully, the tcp_connect() function returns ERR_OK. + + +--- Sending TCP data + +TCP data is sent by enqueueing the data with a call to +tcp_write(). When the data is successfully transmitted to the remote +host, the application will be notified with a call to a specified +callback function. + +- err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags) + + Enqueues the data pointed to by the argument dataptr. The length of + the data is passed as the len parameter. The apiflags can be one or more of: + - TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated + for the data to be copied into. If this flag is not given, no new memory + should be allocated and the data should only be referenced by pointer. This + also means that the memory behind dataptr must not change until the data is + ACKed by the remote host + - TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is omitted, + the PSH flag is set in the last segment created by this call to tcp_write. + If this flag is given, the PSH flag is not set. + + The tcp_write() function will fail and return ERR_MEM if the length + of the data exceeds the current send buffer size or if the length of + the queue of outgoing segment is larger than the upper limit defined + in lwipopts.h. The number of bytes available in the output queue can + be retrieved with the tcp_sndbuf() function. + + The proper way to use this function is to call the function with at + most tcp_sndbuf() bytes of data. If the function returns ERR_MEM, + the application should wait until some of the currently enqueued + data has been successfully received by the other host and try again. + +- void tcp_sent(struct tcp_pcb *pcb, + err_t (* sent)(void *arg, struct tcp_pcb *tpcb, + u16_t len)) + + Specifies the callback function that should be called when data has + successfully been received (i.e., acknowledged) by the remote + host. The len argument passed to the callback function gives the + amount bytes that was acknowledged by the last acknowledgment. + + +--- Receiving TCP data + +TCP data reception is callback based - an application specified +callback function is called when new data arrives. When the +application has taken the data, it has to call the tcp_recved() +function to indicate that TCP can advertise increase the receive +window. + +- void tcp_recv(struct tcp_pcb *pcb, + err_t (* recv)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err)) + + Sets the callback function that will be called when new data + arrives. The callback function will be passed a NULL pbuf to + indicate that the remote host has closed the connection. If + there are no errors and the callback function is to return + ERR_OK, then it must free the pbuf. Otherwise, it must not + free the pbuf so that lwIP core code can store it. + +- void tcp_recved(struct tcp_pcb *pcb, u16_t len) + + Must be called when the application has received the data. The len + argument indicates the length of the received data. + + +--- Application polling + +When a connection is idle (i.e., no data is either transmitted or +received), lwIP will repeatedly poll the application by calling a +specified callback function. This can be used either as a watchdog +timer for killing connections that have stayed idle for too long, or +as a method of waiting for memory to become available. For instance, +if a call to tcp_write() has failed because memory wasn't available, +the application may use the polling functionality to call tcp_write() +again when the connection has been idle for a while. + +- void tcp_poll(struct tcp_pcb *pcb, + err_t (* poll)(void *arg, struct tcp_pcb *tpcb), + u8_t interval) + + Specifies the polling interval and the callback function that should + be called to poll the application. The interval is specified in + number of TCP coarse grained timer shots, which typically occurs + twice a second. An interval of 10 means that the application would + be polled every 5 seconds. + + +--- Closing and aborting connections + +- err_t tcp_close(struct tcp_pcb *pcb) + + Closes the connection. The function may return ERR_MEM if no memory + was available for closing the connection. If so, the application + should wait and try again either by using the acknowledgment + callback or the polling functionality. If the close succeeds, the + function returns ERR_OK. + + The pcb is deallocated by the TCP code after a call to tcp_close(). + +- void tcp_abort(struct tcp_pcb *pcb) + + Aborts the connection by sending a RST (reset) segment to the remote + host. The pcb is deallocated. This function never fails. + + ATTENTION: When calling this from one of the TCP callbacks, make + sure you always return ERR_ABRT (and never return ERR_ABRT otherwise + or you will risk accessing deallocated memory or memory leaks! + + +If a connection is aborted because of an error, the application is +alerted of this event by the err callback. Errors that might abort a +connection are when there is a shortage of memory. The callback +function to be called is set using the tcp_err() function. + +- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, + err_t err)) + + The error callback function does not get the pcb passed to it as a + parameter since the pcb may already have been deallocated. + + +--- UDP interface + +The UDP interface is similar to that of TCP, but due to the lower +level of complexity of UDP, the interface is significantly simpler. + +- struct udp_pcb *udp_new(void) + + Creates a new UDP pcb which can be used for UDP communication. The + pcb is not active until it has either been bound to a local address + or connected to a remote address. + +- void udp_remove(struct udp_pcb *pcb) + + Removes and deallocates the pcb. + +- err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Binds the pcb to a local address. The IP-address argument "ipaddr" + can be IP_ADDR_ANY to indicate that it should listen to any local IP + address. The function currently always return ERR_OK. + +- err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Sets the remote end of the pcb. This function does not generate any + network traffic, but only set the remote address of the pcb. + +- err_t udp_disconnect(struct udp_pcb *pcb) + + Remove the remote end of the pcb. This function does not generate + any network traffic, but only removes the remote address of the pcb. + +- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p) + + Sends the pbuf p. The pbuf is not deallocated. + +- void udp_recv(struct udp_pcb *pcb, + void (* recv)(void *arg, struct udp_pcb *upcb, + struct pbuf *p, + ip_addr_t *addr, + u16_t port), + void *recv_arg) + + Specifies a callback function that should be called when a UDP + datagram is received. + + +--- System initalization + +A truly complete and generic sequence for initializing the lwIP stack +cannot be given because it depends on additional initializations for +your runtime environment (e.g. timers). + +We can give you some idea on how to proceed when using the raw API. +We assume a configuration using a single Ethernet netif and the +UDP and TCP transport layers, IPv4 and the DHCP client. + +Call these functions in the order of appearance: + +- lwip_init() + + Initialize the lwIP stack and all of its subsystems. + +- netif_add(struct netif *netif, const ip4_addr_t *ipaddr, + const ip4_addr_t *netmask, const ip4_addr_t *gw, + void *state, netif_init_fn init, netif_input_fn input) + + Adds your network interface to the netif_list. Allocate a struct + netif and pass a pointer to this structure as the first argument. + Give pointers to cleared ip_addr structures when using DHCP, + or fill them with sane numbers otherwise. The state pointer may be NULL. + + The init function pointer must point to a initialization function for + your Ethernet netif interface. The following code illustrates its use. + + err_t netif_if_init(struct netif *netif) + { + u8_t i; + + for (i = 0; i < ETHARP_HWADDR_LEN; i++) { + netif->hwaddr[i] = some_eth_addr[i]; + } + init_my_eth_device(); + return ERR_OK; + } + + For Ethernet drivers, the input function pointer must point to the lwIP + function ethernet_input() declared in "netif/etharp.h". Other drivers + must use ip_input() declared in "lwip/ip.h". + +- netif_set_default(struct netif *netif) + + Registers the default network interface. + +- netif_set_link_up(struct netif *netif) + + This is the hardware link state; e.g. whether cable is plugged for wired + Ethernet interface. This function must be called even if you don't know + the current state. Having link up and link down events is optional but + DHCP and IPv6 discover benefit well from those events. + +- netif_set_up(struct netif *netif) + + This is the administrative (= software) state of the netif, when the + netif is fully configured this function must be called. + +- dhcp_start(struct netif *netif) + + Creates a new DHCP client for this interface on the first call. + + You can peek in the netif->dhcp struct for the actual DHCP status. + +- sys_check_timeouts() + + When the system is running, you have to periodically call + sys_check_timeouts() which will handle all timers for all protocols in + the stack; add this to your main loop or equivalent. + + +--- Optimalization hints + +The first thing you want to optimize is the lwip_standard_checksum() +routine from src/core/inet.c. You can override this standard +function with the #define LWIP_CHKSUM . + +There are C examples given in inet.c or you might want to +craft an assembly function for this. RFC1071 is a good +introduction to this subject. + +Other significant improvements can be made by supplying +assembly or inline replacements for htons() and htonl() +if you're using a little-endian architecture. +#define lwip_htons(x) +#define lwip_htonl(x) +If you #define them to htons() and htonl(), you should +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from +defining hton*/ntoh* compatibility macros. + +Check your network interface driver if it reads at +a higher speed than the maximum wire-speed. If the +hardware isn't serviced frequently and fast enough +buffer overflows are likely to occur. + +E.g. when using the cs8900 driver, call cs8900if_service(ethif) +as frequently as possible. When using an RTOS let the cs8900 interrupt +wake a high priority task that services your driver using a binary +semaphore or event flag. Some drivers might allow additional tuning +to match your application and network. + +For a production release it is recommended to set LWIP_STATS to 0. +Note that speed performance isn't influenced much by simply setting +high values to the memory options. + +For more optimization hints take a look at the lwIP wiki. + +--- Zero-copy MACs + +To achieve zero-copy on transmit, the data passed to the raw API must +remain unchanged until sent. Because the send- (or write-)functions return +when the packets have been enqueued for sending, data must be kept stable +after that, too. + +This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions +must *not* be reused by the application unless their ref-count is 1. + +For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too, +but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while +PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change). + +Also, data passed to tcp_write without the copy-flag must not be changed! + +Therefore, be careful which type of PBUF you use and if you copy TCP data +or not! diff --git a/components/net/lwip-2.0.3/doc/savannah.txt b/components/net/lwip-2.0.3/doc/savannah.txt new file mode 100644 index 0000000000..d7d19eb6eb --- /dev/null +++ b/components/net/lwip-2.0.3/doc/savannah.txt @@ -0,0 +1,120 @@ +Daily Use Guide for using Savannah for lwIP + +Table of Contents: + +1 - Obtaining lwIP from the Git repository +2 - Committers/developers Git access using SSH +3 - Merging a development branch to master branch +4 - How to release lwIP + + + +1 Obtaining lwIP from the Git repository +---------------------------------------- + +To perform an anonymous Git clone of the master branch (this is where +bug fixes and incremental enhancements occur), do this: + git clone git://git.savannah.nongnu.org/lwip.git + +Or, obtain a stable branch (updated with bug fixes only) as follows: + git clone --branch DEVEL-1_4_1 git://git.savannah.nongnu.org/lwip.git + +Or, obtain a specific (fixed) release as follows: + git clone --branch STABLE-1_4_1 git://git.savannah.nongnu.org/lwip.git + + +2 Committers/developers Git access using SSH +-------------------------------------------- + +The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption. +As such, Git commits to the server occur through a SSH tunnel for project members. +To create a SSH2 key pair in UNIX-like environments, do this: + ssh-keygen -t dsa + +Under Windows, a recommended SSH client is "PuTTY", freely available with good +documentation and a graphic user interface. Use its key generator. + +Now paste the id_dsa.pub contents into your Savannah account public key list. Wait +a while so that Savannah can update its configuration (This can take minutes). + +Try to login using SSH: + ssh -v your_login@git.sv.gnu.org + +If it tells you: + Linux vcs.savannah.gnu.org 2.6.32-5-xen-686 #1 SMP Wed Jun 17 17:10:03 UTC 2015 i686 + + Interactive shell login is not possible for security reasons. + VCS commands are allowed. + Last login: Tue May 15 23:10:12 2012 from 82.245.102.129 + You tried to execute: + Sorry, you are not allowed to execute that command. + Shared connection to git.sv.gnu.org closed. + +then you could login; Savannah refuses to give you a shell - which is OK, as we +are allowed to use SSH for Git only. Now, you should be able to do this: + git clone your_login@git.sv.gnu.org:/srv/git/lwip.git + +After which you can edit your local files with bug fixes or new features and +commit them. Make sure you know what you are doing when using Git to make +changes on the repository. If in doubt, ask on the lwip-members mailing list. + +(If SSH asks about authenticity of the host, you can check the key +fingerprint against https://savannah.nongnu.org/git/?group=lwip + + +3 - Merging a development branch to master branch +------------------------------------------------- + +Merging is a straightforward process in Git. How to merge all changes in a +development branch since our last merge from main: + +Checkout the master branch: + git checkout master + +Merge the development branch to master: + git merge your-development-branch + +Resolve any conflict. + +Commit the merge result. + git commit -a + +Push your commits: + git push + + +4 How to release lwIP +--------------------- + +First, tag the release using Git: (I use release number 1.4.1 throughout +this example). + git tag -a STABLE-1_4_1 + +Share the tag reference by pushing it to remote: + git push origin STABLE-1_4_1 + +Prepare the release: + cp -r lwip lwip-1.4.1 + rm -rf lwip-1.4.1/.git lwip-1.4.1/.gitattributes + +Archive the current directory using tar, gzip'd, bzip2'd and zip'd. + tar czvf lwip-1.4.1.tar.gz lwip-1.4.1 + tar cjvf lwip-1.4.1.tar.bz2 lwip-1.4.1 + zip -r lwip-1.4.1.zip lwip-1.4.1 + +Now, sign the archives with a detached GPG binary signature as follows: + gpg -b lwip-1.4.1.tar.gz + gpg -b lwip-1.4.1.tar.bz2 + gpg -b lwip-1.4.1.zip + +Upload these files using anonymous FTP: + ncftp ftp://savannah.gnu.org/incoming/savannah/lwip + ncftp> mput *1.4.1.* + +Additionally, you may post a news item on Savannah, like this: + +A new 1.4.1 release is now available here: +http://savannah.nongnu.org/files/?group=lwip&highlight=1.4.1 + +You will have to submit this via the user News interface, then approve +this via the Administrator News interface. diff --git a/components/net/lwip-2.0.3/doc/sys_arch.txt b/components/net/lwip-2.0.3/doc/sys_arch.txt new file mode 100644 index 0000000000..4dc727b657 --- /dev/null +++ b/components/net/lwip-2.0.3/doc/sys_arch.txt @@ -0,0 +1,303 @@ +sys_arch interface for lwIP + +Author: Adam Dunkels + Simon Goldschmidt + +The operating system emulation layer provides a common interface +between the lwIP code and the underlying operating system kernel. The +general idea is that porting lwIP to new architectures requires only +small changes to a few header files and a new sys_arch +implementation. It is also possible to do a sys_arch implementation +that does not rely on any underlying operating system. + +The sys_arch provides semaphores, mailboxes and mutexes to lwIP. For the full +lwIP functionality, multiple threads support can be implemented in the +sys_arch, but this is not required for the basic lwIP +functionality. Timer scheduling is implemented in lwIP, but can be implemented +by the sys_arch port (LWIP_TIMERS_CUSTOM==1). + +In addition to the source file providing the functionality of sys_arch, +the OS emulation layer must provide several header files defining +macros used throughout lwip. The files required and the macros they +must define are listed below the sys_arch description. + +Semaphores can be either counting or binary - lwIP works with both +kinds. Mailboxes should be implemented as a queue which allows multiple messages +to be posted (implementing as a rendez-vous point where only one message can be +posted at a time can have a highly negative impact on performance). A message +in a mailbox is just a pointer, nothing more. + +Semaphores are represented by the type "sys_sem_t" which is typedef'd +in the sys_arch.h file. Mailboxes are equivalently represented by the +type "sys_mbox_t". Mutexes are represented by the type "sys_mutex_t". +lwIP does not place any restrictions on how these types are represented +internally. + +Since lwIP 1.4.0, semaphore, mutexes and mailbox functions are prototyped in a way that +allows both using pointers or actual OS structures to be used. This way, memory +required for such types can be either allocated in place (globally or on the +stack) or on the heap (allocated internally in the "*_new()" functions). + +The following functions must be implemented by the sys_arch: + +- void sys_init(void) + + Is called to initialize the sys_arch layer. + +- err_t sys_sem_new(sys_sem_t *sem, u8_t count) + + Creates a new semaphore. The semaphore is allocated to the memory that 'sem' + points to (which can be both a pointer or the actual OS structure). + The "count" argument specifies the initial state of the semaphore (which is + either 0 or 1). + If the semaphore has been created, ERR_OK should be returned. Returning any + other error will provide a hint what went wrong, but except for assertions, + no real error handling is implemented. + +- void sys_sem_free(sys_sem_t *sem) + + Deallocates a semaphore. + +- void sys_sem_signal(sys_sem_t *sem) + + Signals a semaphore. + +- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) + + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). If the "timeout" argument is zero, the thread should be + blocked until the semaphore is signalled. + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. + +- int sys_sem_valid(sys_sem_t *sem) + + Returns 1 if the semaphore is valid, 0 if it is not valid. + When using pointers, a simple way is to check the pointer for != NULL. + When directly using OS structures, implementing this may be more complex. + This may also be a define, in which case the function is not prototyped. + +- void sys_sem_set_invalid(sys_sem_t *sem) + + Invalidate a semaphore so that sys_sem_valid() returns 0. + ATTENTION: This does NOT mean that the semaphore shall be deallocated: + sys_sem_free() is always called before calling this function! + This may also be a define, in which case the function is not prototyped. + +- void sys_mutex_new(sys_mutex_t *mutex) + + Creates a new mutex. The mutex is allocated to the memory that 'mutex' + points to (which can be both a pointer or the actual OS structure). + If the mutex has been created, ERR_OK should be returned. Returning any + other error will provide a hint what went wrong, but except for assertions, + no real error handling is implemented. + +- void sys_mutex_free(sys_mutex_t *mutex) + + Deallocates a mutex. + +- void sys_mutex_lock(sys_mutex_t *mutex) + + Blocks the thread until the mutex can be grabbed. + +- void sys_mutex_unlock(sys_mutex_t *mutex) + + Releases the mutex previously locked through 'sys_mutex_lock()'. + +- void sys_mutex_valid(sys_mutex_t *mutex) + + Returns 1 if the mutes is valid, 0 if it is not valid. + When using pointers, a simple way is to check the pointer for != NULL. + When directly using OS structures, implementing this may be more complex. + This may also be a define, in which case the function is not prototyped. + +- void sys_mutex_set_invalid(sys_mutex_t *mutex) + + Invalidate a mutex so that sys_mutex_valid() returns 0. + ATTENTION: This does NOT mean that the mutex shall be deallocated: + sys_mutex_free() is always called before calling this function! + This may also be a define, in which case the function is not prototyped. + +- err_t sys_mbox_new(sys_mbox_t *mbox, int size) + + Creates an empty mailbox for maximum "size" elements. Elements stored + in mailboxes are pointers. You have to define macros "_MBOX_SIZE" + in your lwipopts.h, or ignore this parameter in your implementation + and use a default size. + If the mailbox has been created, ERR_OK should be returned. Returning any + other error will provide a hint what went wrong, but except for assertions, + no real error handling is implemented. + +- void sys_mbox_free(sys_mbox_t *mbox) + + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. + +- void sys_mbox_post(sys_mbox_t *mbox, void *msg) + + Posts the "msg" to the mailbox. This function have to block until + the "msg" is really posted. + +- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) + + Try to post the "msg" to the mailbox. Returns ERR_MEM if this one + is full, else, ERR_OK if the "msg" is posted. + +- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) + + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). If "timeout" is 0, the thread should + be blocked until a message arrives. The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. + +- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) + + This is similar to sys_arch_mbox_fetch, however if a message is not + present in the mailbox, it immediately returns with the code + SYS_MBOX_EMPTY. On success 0 is returned. + + To allow for efficient implementations, this can be defined as a + function-like macro in sys_arch.h instead of a normal function. For + example, a naive implementation could be: + #define sys_arch_mbox_tryfetch(mbox,msg) \ + sys_arch_mbox_fetch(mbox,msg,1) + although this would introduce unnecessary delays. + +- int sys_mbox_valid(sys_mbox_t *mbox) + + Returns 1 if the mailbox is valid, 0 if it is not valid. + When using pointers, a simple way is to check the pointer for != NULL. + When directly using OS structures, implementing this may be more complex. + This may also be a define, in which case the function is not prototyped. + +- void sys_mbox_set_invalid(sys_mbox_t *mbox) + + Invalidate a mailbox so that sys_mbox_valid() returns 0. + ATTENTION: This does NOT mean that the mailbox shall be deallocated: + sys_mbox_free() is always called before calling this function! + This may also be a define, in which case the function is not prototyped. + +If threads are supported by the underlying operating system and if +such functionality is needed in lwIP, the following function will have +to be implemented as well: + +- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) + + Starts a new thread named "name" with priority "prio" that will begin its + execution in the function "thread()". The "arg" argument will be passed as an + argument to the thread() function. The stack size to used for this thread is + the "stacksize" parameter. The id of the new thread is returned. Both the id + and the priority are system dependent. + +When lwIP is used from more than one context (e.g. from multiple threads OR from +main-loop and from interrupts), the SYS_LIGHTWEIGHT_PROT protection SHOULD be enabled! + +- sys_prot_t sys_arch_protect(void) + + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. + +- void sys_arch_unprotect(sys_prot_t pval) + + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. + +For some configurations, you also need: + +- u32_t sys_now(void) + + This optional function returns the current time in milliseconds (don't care + for wraparound, this is only used for time diffs). + Not implementing this function means you cannot use some modules (e.g. TCP + timestamps, internal timeouts for NO_SYS==1). + + +Note: + +Be careful with using mem_malloc() in sys_arch. When malloc() refers to +mem_malloc() you can run into a circular function call problem. In mem.c +mem_init() tries to allcate a semaphore using mem_malloc, which of course +can't be performed when sys_arch uses mem_malloc. + +------------------------------------------------------------------------------- +Additional files required for the "OS support" emulation layer: +------------------------------------------------------------------------------- + +cc.h - Architecture environment, some compiler specific, some + environment specific (probably should move env stuff + to sys_arch.h.) + + Typedefs for the types used by lwip - + u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t + + Compiler hints for packing lwip's structures - + PACK_STRUCT_FIELD(x) + PACK_STRUCT_STRUCT + PACK_STRUCT_BEGIN + PACK_STRUCT_END + + Platform specific diagnostic output - + LWIP_PLATFORM_DIAG(x) - non-fatal, print a message. + LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution. + Portability defines for printf formatters: + U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F + + "lightweight" synchronization mechanisms - + SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. + SYS_ARCH_PROTECT(x) - enter protection mode. + SYS_ARCH_UNPROTECT(x) - leave protection mode. + + If the compiler does not provide memset() this file must include a + definition of it, or include a file which defines it. + + This file must either include a system-local which defines + the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO + to make lwip/arch.h define the codes which are used throughout. + + +perf.h - Architecture specific performance measurement. + Measurement calls made throughout lwip, these can be defined to nothing. + PERF_START - start measuring something. + PERF_STOP(x) - stop measuring something, and record the result. + +sys_arch.h - Tied to sys_arch.c + + Arch dependent types for the following objects: + sys_sem_t, sys_mbox_t, sys_thread_t, + And, optionally: + sys_prot_t + + Defines to set vars of sys_mbox_t and sys_sem_t to NULL. + SYS_MBOX_NULL NULL + SYS_SEM_NULL NULL diff --git a/components/net/lwip-2.0.3/src/FILES b/components/net/lwip-2.0.3/src/FILES new file mode 100644 index 0000000000..0be0741d08 --- /dev/null +++ b/components/net/lwip-2.0.3/src/FILES @@ -0,0 +1,15 @@ +api/ - The code for the high-level wrapper API. Not needed if + you use the lowel-level call-back/raw API. + +apps/ - Higher layer applications that are specifically programmed + with the lwIP low-level raw API. + +core/ - The core of the TPC/IP stack; protocol implementations, + memory and buffer management, and the low-level raw API. + +include/ - lwIP include files. + +netif/ - Generic network interface device drivers are kept here. + +For more information on the various subdirectories, check the FILES +file in each directory. diff --git a/components/net/lwip-2.0.3/src/Filelists.mk b/components/net/lwip-2.0.3/src/Filelists.mk new file mode 100644 index 0000000000..7d30bb8f53 --- /dev/null +++ b/components/net/lwip-2.0.3/src/Filelists.mk @@ -0,0 +1,181 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +# OF SUCH DAMAGE. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +# COREFILES, CORE4FILES: The minimum set of files needed for lwIP. +COREFILES=$(LWIPDIR)/core/init.c \ + $(LWIPDIR)/core/def.c \ + $(LWIPDIR)/core/dns.c \ + $(LWIPDIR)/core/inet_chksum.c \ + $(LWIPDIR)/core/ip.c \ + $(LWIPDIR)/core/mem.c \ + $(LWIPDIR)/core/memp.c \ + $(LWIPDIR)/core/netif.c \ + $(LWIPDIR)/core/pbuf.c \ + $(LWIPDIR)/core/raw.c \ + $(LWIPDIR)/core/stats.c \ + $(LWIPDIR)/core/sys.c \ + $(LWIPDIR)/core/tcp.c \ + $(LWIPDIR)/core/tcp_in.c \ + $(LWIPDIR)/core/tcp_out.c \ + $(LWIPDIR)/core/timeouts.c \ + $(LWIPDIR)/core/udp.c + +CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.c \ + $(LWIPDIR)/core/ipv4/dhcp.c \ + $(LWIPDIR)/core/ipv4/etharp.c \ + $(LWIPDIR)/core/ipv4/icmp.c \ + $(LWIPDIR)/core/ipv4/igmp.c \ + $(LWIPDIR)/core/ipv4/ip4_frag.c \ + $(LWIPDIR)/core/ipv4/ip4.c \ + $(LWIPDIR)/core/ipv4/ip4_addr.c + +CORE6FILES=$(LWIPDIR)/core/ipv6/dhcp6.c \ + $(LWIPDIR)/core/ipv6/ethip6.c \ + $(LWIPDIR)/core/ipv6/icmp6.c \ + $(LWIPDIR)/core/ipv6/inet6.c \ + $(LWIPDIR)/core/ipv6/ip6.c \ + $(LWIPDIR)/core/ipv6/ip6_addr.c \ + $(LWIPDIR)/core/ipv6/ip6_frag.c \ + $(LWIPDIR)/core/ipv6/mld6.c \ + $(LWIPDIR)/core/ipv6/nd6.c + +# APIFILES: The files which implement the sequential and socket APIs. +APIFILES=$(LWIPDIR)/api/api_lib.c \ + $(LWIPDIR)/api/api_msg.c \ + $(LWIPDIR)/api/err.c \ + $(LWIPDIR)/api/netbuf.c \ + $(LWIPDIR)/api/netdb.c \ + $(LWIPDIR)/api/netifapi.c \ + $(LWIPDIR)/api/sockets.c \ + $(LWIPDIR)/api/tcpip.c + +# NETIFFILES: Files implementing various generic network interface functions +NETIFFILES=$(LWIPDIR)/netif/ethernet.c \ + $(LWIPDIR)/netif/slipif.c + +# SIXLOWPAN: 6LoWPAN +SIXLOWPAN=$(LWIPDIR)/netif/lowpan6.c \ + +# PPPFILES: PPP +PPPFILES=$(LWIPDIR)/netif/ppp/auth.c \ + $(LWIPDIR)/netif/ppp/ccp.c \ + $(LWIPDIR)/netif/ppp/chap-md5.c \ + $(LWIPDIR)/netif/ppp/chap_ms.c \ + $(LWIPDIR)/netif/ppp/chap-new.c \ + $(LWIPDIR)/netif/ppp/demand.c \ + $(LWIPDIR)/netif/ppp/eap.c \ + $(LWIPDIR)/netif/ppp/ecp.c \ + $(LWIPDIR)/netif/ppp/eui64.c \ + $(LWIPDIR)/netif/ppp/fsm.c \ + $(LWIPDIR)/netif/ppp/ipcp.c \ + $(LWIPDIR)/netif/ppp/ipv6cp.c \ + $(LWIPDIR)/netif/ppp/lcp.c \ + $(LWIPDIR)/netif/ppp/magic.c \ + $(LWIPDIR)/netif/ppp/mppe.c \ + $(LWIPDIR)/netif/ppp/multilink.c \ + $(LWIPDIR)/netif/ppp/ppp.c \ + $(LWIPDIR)/netif/ppp/pppapi.c \ + $(LWIPDIR)/netif/ppp/pppcrypt.c \ + $(LWIPDIR)/netif/ppp/pppoe.c \ + $(LWIPDIR)/netif/ppp/pppol2tp.c \ + $(LWIPDIR)/netif/ppp/pppos.c \ + $(LWIPDIR)/netif/ppp/upap.c \ + $(LWIPDIR)/netif/ppp/utils.c \ + $(LWIPDIR)/netif/ppp/vj.c \ + $(LWIPDIR)/netif/ppp/polarssl/arc4.c \ + $(LWIPDIR)/netif/ppp/polarssl/des.c \ + $(LWIPDIR)/netif/ppp/polarssl/md4.c \ + $(LWIPDIR)/netif/ppp/polarssl/md5.c \ + $(LWIPDIR)/netif/ppp/polarssl/sha1.c + +# LWIPNOAPPSFILES: All LWIP files without apps +LWIPNOAPPSFILES=$(COREFILES) \ + $(CORE4FILES) \ + $(CORE6FILES) \ + $(APIFILES) \ + $(NETIFFILES) \ + $(PPPFILES) \ + $(SIXLOWPAN) + +# SNMPFILES: SNMPv2c agent +SNMPFILES=$(LWIPDIR)/apps/snmp/snmp_asn1.c \ + $(LWIPDIR)/apps/snmp/snmp_core.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_icmp.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_interfaces.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_ip.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_snmp.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_system.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_tcp.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_udp.c \ + $(LWIPDIR)/apps/snmp/snmp_msg.c \ + $(LWIPDIR)/apps/snmp/snmpv3.c \ + $(LWIPDIR)/apps/snmp/snmp_netconn.c \ + $(LWIPDIR)/apps/snmp/snmp_pbuf_stream.c \ + $(LWIPDIR)/apps/snmp/snmp_raw.c \ + $(LWIPDIR)/apps/snmp/snmp_scalar.c \ + $(LWIPDIR)/apps/snmp/snmp_table.c \ + $(LWIPDIR)/apps/snmp/snmp_threadsync.c \ + $(LWIPDIR)/apps/snmp/snmp_traps.c \ + $(LWIPDIR)/apps/snmp/snmpv3_mbedtls.c \ + $(LWIPDIR)/apps/snmp/snmpv3_dummy.c + +# HTTPDFILES: HTTP server +HTTPDFILES=$(LWIPDIR)/apps/httpd/fs.c \ + $(LWIPDIR)/apps/httpd/httpd.c + +# LWIPERFFILES: IPERF server +LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c + +# SNTPFILES: SNTP client +SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c + +# MDNSFILES: MDNS responder +MDNSFILES=$(LWIPDIR)/apps/mdns/mdns.c + +# NETBIOSNSFILES: NetBIOS name server +NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c + +# TFTPFILES: TFTP server files +TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c + +# MQTTFILES: MQTT client files +MQTTFILES=$(LWIPDIR)/apps/mqtt/mqtt.c + +# LWIPAPPFILES: All LWIP APPs +LWIPAPPFILES=$(SNMPFILES) \ + $(HTTPDFILES) \ + $(LWIPERFFILES) \ + $(SNTPFILES) \ + $(MDNSFILES) \ + $(NETBIOSNSFILES) \ + $(TFTPFILES) \ + $(MQTTFILES) diff --git a/components/net/lwip-2.0.3/src/api/api_lib.c b/components/net/lwip-2.0.3/src/api/api_lib.c new file mode 100644 index 0000000000..3c1d6a6c27 --- /dev/null +++ b/components/net/lwip-2.0.3/src/api/api_lib.c @@ -0,0 +1,1010 @@ +/** + * @file + * Sequential API External module + * + * @defgroup netconn Netconn API + * @ingroup sequential_api + * Thread-safe, to be called from non-TCPIP threads only. + * TX/RX handling based on @ref netbuf (containing @ref pbuf) + * to avoid copying data around. + * + * @defgroup netconn_common Common functions + * @ingroup netconn + * For use with TCP and UDP + * + * @defgroup netconn_tcp TCP only + * @ingroup netconn + * TCP only functions + * + * @defgroup netconn_udp UDP only + * @ingroup netconn + * UDP only functions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +/* This is the part of the API that is linked with + the application */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api.h" +#include "lwip/memp.h" + +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/api_msg.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/priv/tcpip_priv.h" + +#include + +#define API_MSG_VAR_REF(name) API_VAR_REF(name) +#define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name) +#define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, ERR_MEM) +#define API_MSG_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, NULL) +#define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name) + +static err_t netconn_close_shutdown(struct netconn *conn, u8_t how); + +/** + * Call the lower part of a netconn_* function + * This function is then running in the thread context + * of tcpip_thread and has exclusive access to lwIP core code. + * + * @param fn function to call + * @param apimsg a struct containing the function to call and its parameters + * @return ERR_OK if the function was called, another err_t if not + */ +static err_t +netconn_apimsg(tcpip_callback_fn fn, struct api_msg *apimsg) +{ + err_t err; + +#ifdef LWIP_DEBUG + /* catch functions that don't set err */ + apimsg->err = ERR_VAL; +#endif /* LWIP_DEBUG */ + +#if LWIP_NETCONN_SEM_PER_THREAD + apimsg->op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg)); + if (err == ERR_OK) { + return apimsg->err; + } + return err; +} + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is also created. + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) +{ + struct netconn *conn; + API_MSG_VAR_DECLARE(msg); + API_MSG_VAR_ALLOC_RETURN_NULL(msg); + + conn = netconn_alloc(t, callback); + if (conn != NULL) { + err_t err; + + API_MSG_VAR_REF(msg).msg.n.proto = proto; + API_MSG_VAR_REF(msg).conn = conn; + err = netconn_apimsg(lwip_netconn_do_newconn, &API_MSG_VAR_REF(msg)); + if (err != ERR_OK) { + LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); + LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ +#if !LWIP_NETCONN_SEM_PER_THREAD + LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); + sys_sem_free(&conn->op_completed); +#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ + sys_mbox_free(&conn->recvmbox); + memp_free(MEMP_NETCONN, conn); + API_MSG_VAR_FREE(msg); + return NULL; + } + } + API_MSG_VAR_FREE(msg); + return conn; +} + +/** + * @ingroup netconn_common + * Close a netconn 'connection' and free its resources. + * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate + * after this returns. + * + * @param conn the netconn to delete + * @return ERR_OK if the connection was deleted + */ +err_t +netconn_delete(struct netconn *conn) +{ + err_t err; + API_MSG_VAR_DECLARE(msg); + + /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ + if (conn == NULL) { + return ERR_OK; + } + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now(); +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ +#if LWIP_TCP + API_MSG_VAR_REF(msg).msg.sd.polls_left = + ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; +#endif /* LWIP_TCP */ +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + err = netconn_apimsg(lwip_netconn_do_delconn, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + if (err != ERR_OK) { + return err; + } + + netconn_free(conn); + + return ERR_OK; +} + +/** + * Get the local or remote IP address and port of a netconn. + * For RAW netconns, this returns the protocol instead of a port! + * + * @param conn the netconn to query + * @param addr a pointer to which to save the IP address + * @param port a pointer to which to save the port (or protocol for RAW) + * @param local 1 to get the local IP address, 0 to get the remote one + * @return ERR_CONN for invalid connections + * ERR_OK if the information was retrieved + */ +err_t +netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.ad.local = local; +#if LWIP_MPU_COMPATIBLE + err = netconn_apimsg(lwip_netconn_do_getaddr, &API_MSG_VAR_REF(msg)); + *addr = msg->msg.ad.ipaddr; + *port = msg->msg.ad.port; +#else /* LWIP_MPU_COMPATIBLE */ + msg.msg.ad.ipaddr = addr; + msg.msg.ad.port = port; + err = netconn_apimsg(lwip_netconn_do_getaddr, &msg); +#endif /* LWIP_MPU_COMPATIBLE */ + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_common + * Bind a netconn to a specific local IP address and port. + * Binding one netconn twice might not always be checked correctly! + * + * @param conn the netconn to bind + * @param addr the local IP address to bind the netconn to + * (use IP4_ADDR_ANY/IP6_ADDR_ANY to bind to all addresses) + * @param port the local port to bind the netconn to (not used for RAW) + * @return ERR_OK if bound, any other err_t on failure + */ +err_t +netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ + if (addr == NULL) { + addr = IP4_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV4 && LWIP_IPV6 + /* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY, + * and NETCONN_FLAG_IPV6_V6ONLY is 0, use IP_ANY_TYPE to bind + */ + if ((netconn_get_ipv6only(conn) == 0) && + ip_addr_cmp(addr, IP6_ADDR_ANY)) { + addr = IP_ANY_TYPE; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.bc.port = port; + err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_common + * Connect a netconn to a specific remote IP address and port. + * + * @param conn the netconn to connect + * @param addr the remote IP address to connect to + * @param port the remote port to connect to (no used for RAW) + * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise + */ +err_t +netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ + if (addr == NULL) { + addr = IP4_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.bc.port = port; + err = netconn_apimsg(lwip_netconn_do_connect, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_udp + * Disconnect a netconn from its current peer (only valid for UDP netconns). + * + * @param conn the netconn to disconnect + * @return See @ref err_t + */ +err_t +netconn_disconnect(struct netconn *conn) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; + err = netconn_apimsg(lwip_netconn_do_disconnect, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_tcp + * Set a TCP netconn into listen mode + * + * @param conn the tcp netconn to set to listen mode + * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 + * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns + * don't return any error (yet?)) + */ +err_t +netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) +{ +#if LWIP_TCP + API_MSG_VAR_DECLARE(msg); + err_t err; + + /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ + LWIP_UNUSED_ARG(backlog); + + LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_REF(msg).msg.lb.backlog = backlog; +#endif /* TCP_LISTEN_BACKLOG */ + err = netconn_apimsg(lwip_netconn_do_listen, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(backlog); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * @ingroup netconn_tcp + * Accept a new connection on a TCP listening netconn. + * + * @param conn the TCP listen netconn + * @param new_conn pointer where the new connection is stored + * @return ERR_OK if a new connection has been received or an error + * code otherwise + */ +err_t +netconn_accept(struct netconn *conn, struct netconn **new_conn) +{ +#if LWIP_TCP + void *accept_ptr; + struct netconn *newconn; +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_DECLARE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + + LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); + *new_conn = NULL; + LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); + + if (ERR_IS_FATAL(conn->last_err)) { + /* don't recv on fatal errors: this might block the application task + waiting on acceptmbox forever! */ + return conn->last_err; + } + if (!sys_mbox_valid(&conn->acceptmbox)) { + return ERR_CLSD; + } + +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_ALLOC(msg); +#endif /* TCP_LISTEN_BACKLOG */ + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_FREE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + newconn = (struct netconn *)accept_ptr; + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + + if (accept_ptr == &netconn_aborted) { + /* a connection has been aborted: out of pcbs or out of netconns during accept */ + /* @todo: set netconn error, but this would be fatal and thus block further accepts */ +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_FREE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + return ERR_ABRT; + } + if (newconn == NULL) { + /* connection has been aborted */ + /* in this special case, we set the netconn error from application thread, as + on a ready-to-accept listening netconn, there should not be anything running + in tcpip_thread */ + NETCONN_SET_SAFE_ERR(conn, ERR_CLSD); +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_FREE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + return ERR_CLSD; + } +#if TCP_LISTEN_BACKLOG + /* Let the stack know that we have accepted the connection. */ + API_MSG_VAR_REF(msg).conn = newconn; + /* don't care for the return value of lwip_netconn_do_recv */ + netconn_apimsg(lwip_netconn_do_accepted, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + + *new_conn = newconn; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(new_conn); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * @ingroup netconn_common + * Receive data: actual implementation that doesn't care whether pbuf or netbuf + * is received + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf/netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +static err_t +netconn_recv_data(struct netconn *conn, void **new_buf) +{ + void *buf = NULL; + u16_t len; +#if LWIP_TCP + API_MSG_VAR_DECLARE(msg); +#if LWIP_MPU_COMPATIBLE + msg = NULL; +#endif +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + if (!sys_mbox_valid(&conn->recvmbox)) { + /* This happens when calling this function after receiving FIN */ + return sys_mbox_valid(&conn->acceptmbox) ? ERR_CONN : ERR_CLSD; + } + } +#endif /* LWIP_TCP */ + LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); + + if (ERR_IS_FATAL(conn->last_err)) { + /* don't recv on fatal errors: this might block the application task + waiting on recvmbox forever! */ + /* @todo: this does not allow us to fetch data that has been put into recvmbox + before the fatal error occurred - is that a problem? */ + return conn->last_err; + } +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + API_MSG_VAR_ALLOC(msg); + } +#endif /* LWIP_TCP */ + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + API_MSG_VAR_FREE(msg); + } +#endif /* LWIP_TCP */ + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + /* Let the stack know that we have taken the data. */ + /* @todo: Speedup: Don't block and wait for the answer here + (to prevent multiple thread-switches). */ + API_MSG_VAR_REF(msg).conn = conn; + if (buf != NULL) { + API_MSG_VAR_REF(msg).msg.r.len = ((struct pbuf *)buf)->tot_len; + } else { + API_MSG_VAR_REF(msg).msg.r.len = 1; + } + + /* don't care for the return value of lwip_netconn_do_recv */ + netconn_apimsg(lwip_netconn_do_recv, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + /* If we are closed, we indicate that we no longer wish to use the socket */ + if (buf == NULL) { + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + if (conn->pcb.ip == NULL) { + /* race condition: RST during recv */ + return conn->last_err == ERR_OK ? ERR_RST : conn->last_err; + } + /* RX side is closed, so deallocate the recvmbox */ + netconn_close_shutdown(conn, NETCONN_SHUT_RD); + /* Don' store ERR_CLSD as conn->err since we are only half-closed */ + return ERR_CLSD; + } + len = ((struct pbuf *)buf)->tot_len; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ +#if (LWIP_UDP || LWIP_RAW) + { + LWIP_ASSERT("buf != NULL", buf != NULL); + len = netbuf_len((struct netbuf*)buf); + } +#endif /* (LWIP_UDP || LWIP_RAW) */ + +#if LWIP_SO_RCVBUF + SYS_ARCH_DEC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); + + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +} + +/** + * @ingroup netconn_tcp + * Receive data (in form of a pbuf) from a TCP netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + * ERR_ARG if conn is not a TCP netconn + */ +err_t +netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) +{ + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) && + NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;); + + return netconn_recv_data(conn, (void **)new_buf); +} + +/** + * @ingroup netconn_common + * Receive data (in form of a netbuf containing a packet buffer) from a netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +err_t +netconn_recv(struct netconn *conn, struct netbuf **new_buf) +{ +#if LWIP_TCP + struct netbuf *buf = NULL; + err_t err; +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + struct pbuf *p = NULL; + /* This is not a listening netconn, since recvmbox is set */ + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + return ERR_MEM; + } + + err = netconn_recv_data(conn, (void **)&p); + if (err != ERR_OK) { + memp_free(MEMP_NETBUF, buf); + return err; + } + LWIP_ASSERT("p != NULL", p != NULL); + + buf->p = p; + buf->ptr = p; + buf->port = 0; + ip_addr_set_zero(&buf->addr); + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ + { +#if (LWIP_UDP || LWIP_RAW) + return netconn_recv_data(conn, (void **)new_buf); +#endif /* (LWIP_UDP || LWIP_RAW) */ + } +} + +/** + * @ingroup netconn_udp + * Send data (in form of a netbuf) to a specific remote IP address and port. + * Only to be used for UDP and RAW netconns (not TCP). + * + * @param conn the netconn over which to send data + * @param buf a netbuf containing the data to send + * @param addr the remote IP address to which to send the data + * @param port the remote port to which to send the data + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_sendto(struct netconn *conn, struct netbuf *buf, const ip_addr_t *addr, u16_t port) +{ + if (buf != NULL) { + ip_addr_set(&buf->addr, addr); + buf->port = port; + return netconn_send(conn, buf); + } + return ERR_VAL; +} + +/** + * @ingroup netconn_udp + * Send data over a UDP or RAW netconn (that is already connected). + * + * @param conn the UDP or RAW netconn over which to send data + * @param buf a netbuf containing the data to send + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_send(struct netconn *conn, struct netbuf *buf) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.b = buf; + err = netconn_apimsg(lwip_netconn_do_send, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_tcp + * Send data over a TCP netconn. + * + * @param conn the TCP netconn over which to send data + * @param dataptr pointer to the application buffer that contains the data to send + * @param size size of the application data to send + * @param apiflags combination of following flags : + * - NETCONN_COPY: data will be copied into memory belonging to the stack + * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent + * - NETCONN_DONTBLOCK: only write the data if all data can be written at once + * @param bytes_written pointer to a location that receives the number of written bytes + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + u8_t dontblock; + + LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;); + if (size == 0) { + return ERR_OK; + } + dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout != 0) { + dontblock = 1; + } +#endif /* LWIP_SO_SNDTIMEO */ + if (dontblock && !bytes_written) { + /* This implies netconn_write() cannot be used for non-blocking send, since + it has no way to return the number of bytes written. */ + return ERR_VAL; + } + + API_MSG_VAR_ALLOC(msg); + /* non-blocking write sends as much */ + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.w.dataptr = dataptr; + API_MSG_VAR_REF(msg).msg.w.apiflags = apiflags; + API_MSG_VAR_REF(msg).msg.w.len = size; +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout != 0) { + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + API_MSG_VAR_REF(msg).msg.w.time_started = sys_now(); + } else { + API_MSG_VAR_REF(msg).msg.w.time_started = 0; + } +#endif /* LWIP_SO_SNDTIMEO */ + + /* For locking the core: this _can_ be delayed on low memory/low send buffer, + but if it is, this is done inside api_msg.c:do_write(), so we can use the + non-blocking version here. */ + err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg)); + if ((err == ERR_OK) && (bytes_written != NULL)) { + if (dontblock) { + /* nonblocking write: maybe the data has been sent partly */ + *bytes_written = API_MSG_VAR_REF(msg).msg.w.len; + } else { + /* blocking call succeeded: all data has been sent if it */ + *bytes_written = size; + } + } + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_tcp + * Close or shutdown a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close or shutdown + * @param how fully close or only shutdown one side? + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +static err_t +netconn_close_shutdown(struct netconn *conn, u8_t how) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + LWIP_UNUSED_ARG(how); + + LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; +#if LWIP_TCP + /* shutting down both ends is the same as closing */ + API_MSG_VAR_REF(msg).msg.sd.shut = how; +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now(); +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + API_MSG_VAR_REF(msg).msg.sd.polls_left = + ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ +#endif /* LWIP_TCP */ + err = netconn_apimsg(lwip_netconn_do_close, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_tcp + * Close a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_close(struct netconn *conn) +{ + /* shutting down both ends is the same as closing */ + return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); +} + +/** + * @ingroup netconn_tcp + * Shut down one or both sides of a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to shut down + * @param shut_rx shut down the RX side (no more read possible after this) + * @param shut_tx shut down the TX side (no more write possible after this) + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) +{ + return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)); +} + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** + * @ingroup netconn_udp + * Join multicast groups for UDP netconns. + * + * @param conn the UDP netconn for which to change multicast addresses + * @param multiaddr IP address of the multicast group to join or leave + * @param netif_addr the IP address of the network interface on which to send + * the igmp message + * @param join_or_leave flag whether to send a join- or leave-message + * @return ERR_OK if the action was taken, any err_t on error + */ +err_t +netconn_join_leave_group(struct netconn *conn, + const ip_addr_t *multiaddr, + const ip_addr_t *netif_addr, + enum netconn_igmp join_or_leave) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ + if (multiaddr == NULL) { + multiaddr = IP4_ADDR_ANY; + } + if (netif_addr == NULL) { + netif_addr = IP4_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr); + API_MSG_VAR_REF(msg).msg.jl.netif_addr = API_MSG_VAR_REF(netif_addr); + API_MSG_VAR_REF(msg).msg.jl.join_or_leave = join_or_leave; + err = netconn_apimsg(lwip_netconn_do_join_leave_group, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/** + * @ingroup netconn_common + * Execute a DNS query, only one IP address is returned + * + * @param name a string representation of the DNS host name to query + * @param addr a preallocated ip_addr_t where to store the resolved IP address + * @param dns_addrtype IP address type (IPv4 / IPv6) + * @return ERR_OK: resolving succeeded + * ERR_MEM: memory error, try again later + * ERR_ARG: dns client not initialized or invalid hostname + * ERR_VAL: dns server response was invalid + */ +#if LWIP_IPV4 && LWIP_IPV6 +err_t +netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype) +#else +err_t +netconn_gethostbyname(const char *name, ip_addr_t *addr) +#endif +{ + API_VAR_DECLARE(struct dns_api_msg, msg); +#if !LWIP_MPU_COMPATIBLE + sys_sem_t sem; +#endif /* LWIP_MPU_COMPATIBLE */ + err_t err; + err_t cberr; + + LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); +#if LWIP_MPU_COMPATIBLE + if (strlen(name) >= DNS_MAX_NAME_LENGTH) { + return ERR_ARG; + } +#endif + + API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg, ERR_MEM); +#if LWIP_MPU_COMPATIBLE + strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH-1); + API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH-1] = 0; +#else /* LWIP_MPU_COMPATIBLE */ + msg.err = &err; + msg.sem = &sem; + API_VAR_REF(msg).addr = API_VAR_REF(addr); + API_VAR_REF(msg).name = name; +#endif /* LWIP_MPU_COMPATIBLE */ +#if LWIP_IPV4 && LWIP_IPV6 + API_VAR_REF(msg).dns_addrtype = dns_addrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_NETCONN_SEM_PER_THREAD + API_VAR_REF(msg).sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD*/ + err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0); + if (err != ERR_OK) { + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + return err; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + cberr = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg)); + if (cberr != ERR_OK) { +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); +#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + return cberr; + } + sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem)); +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); +#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ + +#if LWIP_MPU_COMPATIBLE + *addr = msg->addr; + err = msg->err; +#endif /* LWIP_MPU_COMPATIBLE */ + + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + return err; +} +#endif /* LWIP_DNS*/ + +#if LWIP_NETCONN_SEM_PER_THREAD +void +netconn_thread_init(void) +{ + sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); + if ((sem == NULL) || !sys_sem_valid(sem)) { + /* call alloc only once */ + LWIP_NETCONN_THREAD_SEM_ALLOC(); + LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET())); + } +} + +void +netconn_thread_cleanup(void) +{ + sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); + if ((sem != NULL) && sys_sem_valid(sem)) { + /* call free only once */ + LWIP_NETCONN_THREAD_SEM_FREE(); + } +} +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +#endif /* LWIP_NETCONN */ diff --git a/components/net/lwip-2.0.3/src/api/api_msg.c b/components/net/lwip-2.0.3/src/api/api_msg.c new file mode 100644 index 0000000000..5a8dad9bca --- /dev/null +++ b/components/net/lwip-2.0.3/src/api/api_msg.c @@ -0,0 +1,1953 @@ +/** + * @file + * Sequential API Internal module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/api_msg.h" + +#include "lwip/ip.h" +#include "lwip/ip_addr.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" + +#include "lwip/memp.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/mld6.h" +#include "lwip/priv/tcpip_priv.h" + +#include + +/* netconns are polled once per second (e.g. continue write on memory error) */ +#define NETCONN_TCP_POLL_INTERVAL 2 + +#define SET_NONBLOCKING_CONNECT(conn, val) do { if (val) { \ + (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0) +#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) + +/* forward declarations */ +#if LWIP_TCP +#if LWIP_TCPIP_CORE_LOCKING +#define WRITE_DELAYED , 1 +#define WRITE_DELAYED_PARAM , u8_t delayed +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define WRITE_DELAYED +#define WRITE_DELAYED_PARAM +#endif /* LWIP_TCPIP_CORE_LOCKING */ +static err_t lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM); +static err_t lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM); +#endif + +#if LWIP_TCPIP_CORE_LOCKING +#define TCPIP_APIMSG_ACK(m) NETCONN_SET_SAFE_ERR((m)->conn, (m)->err) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define TCPIP_APIMSG_ACK(m) do { NETCONN_SET_SAFE_ERR((m)->conn, (m)->err); sys_sem_signal(LWIP_API_MSG_SEM(m)); } while(0) +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_TCP +u8_t netconn_aborted; +#endif /* LWIP_TCP */ + +#if LWIP_RAW +/** + * Receive callback function for RAW netconns. + * Doesn't 'eat' the packet, only copies it and sends it to + * conn->recvmbox + * + * @see raw.h (struct raw_pcb.recv) for parameters and return value + */ +static u8_t +recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr) +{ + struct pbuf *q; + struct netbuf *buf; + struct netconn *conn; + + LWIP_UNUSED_ARG(addr); + conn = (struct netconn *)arg; + + if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { +#if LWIP_SO_RCVBUF + int recv_avail; + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { + return 0; + } +#endif /* LWIP_SO_RCVBUF */ + /* copy the whole packet into new pbufs */ + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + if (pbuf_copy(q, p) != ERR_OK) { + pbuf_free(q); + q = NULL; + } + } + + if (q != NULL) { + u16_t len; + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(q); + return 0; + } + + buf->p = q; + buf->ptr = q; + ip_addr_copy(buf->addr, *ip_current_src_addr()); + buf->port = pcb->protocol; + + len = q->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return 0; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + } + } + + return 0; /* do not eat the packet */ +} +#endif /* LWIP_RAW*/ + +#if LWIP_UDP +/** + * Receive callback function for UDP netconns. + * Posts the packet to conn->recvmbox or deletes it on memory error. + * + * @see udp.h (struct udp_pcb.recv) for parameters + */ +static void +recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr, u16_t port) +{ + struct netbuf *buf; + struct netconn *conn; + u16_t len; +#if LWIP_SO_RCVBUF + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ + LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_udp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + + if (conn == NULL) { + pbuf_free(p); + return; + } + + LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); + +#if LWIP_SO_RCVBUF + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if (!sys_mbox_valid(&conn->recvmbox) || + ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { +#else /* LWIP_SO_RCVBUF */ + if (!sys_mbox_valid(&conn->recvmbox)) { +#endif /* LWIP_SO_RCVBUF */ + pbuf_free(p); + return; + } + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(p); + return; + } else { + buf->p = p; + buf->ptr = p; + ip_addr_set(&buf->addr, addr); + buf->port = port; +#if LWIP_NETBUF_RECVINFO + { + /* get the UDP header - always in the first pbuf, ensured by udp_input */ + const struct udp_hdr* udphdr = (const struct udp_hdr*)ip_next_header_ptr(); +#if LWIP_CHECKSUM_ON_COPY + buf->flags = NETBUF_FLAG_DESTADDR; +#endif /* LWIP_CHECKSUM_ON_COPY */ + ip_addr_set(&buf->toaddr, ip_current_dest_addr()); + buf->toport_chksum = udphdr->dest; + } +#endif /* LWIP_NETBUF_RECVINFO */ + } + + len = p->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } +} +#endif /* LWIP_UDP */ + +#if LWIP_TCP +/** + * Receive callback function for TCP netconns. + * Posts the packet to conn->recvmbox, but doesn't delete it on errors. + * + * @see tcp.h (struct tcp_pcb.recv) for parameters and return value + */ +static err_t +recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netconn *conn; + u16_t len; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); + + if (!sys_mbox_valid(&conn->recvmbox)) { + /* recvmbox already deleted */ + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + return ERR_OK; + } + /* Unlike for UDP or RAW pcbs, don't check for available space + using recv_avail since that could break the connection + (data is already ACKed) */ + + /* don't overwrite fatal errors! */ + if (err != ERR_OK) { + NETCONN_SET_SAFE_ERR(conn, err); + } + + if (p != NULL) { + len = p->tot_len; + } else { + len = 0; + } + + if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { + /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ + return ERR_MEM; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + + return ERR_OK; +} + +/** + * Poll callback function for TCP netconns. + * Wakes up an application thread that waits for a connection to close + * or data to be sent. The application thread then takes the + * appropriate action to go on. + * + * Signals the conn->sem. + * netconn_close waits for conn->sem if closing failed. + * + * @see tcp.h (struct tcp_pcb.poll) for parameters and return value + */ +static err_t +poll_tcp(void *arg, struct tcp_pcb *pcb) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn WRITE_DELAYED); + } else if (conn->state == NETCONN_CLOSE) { +#if !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER + if (conn->current_msg && conn->current_msg->msg.sd.polls_left) { + conn->current_msg->msg.sd.polls_left--; + } +#endif /* !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER */ + lwip_netconn_do_close_internal(conn WRITE_DELAYED); + } + /* @todo: implement connect timeout here? */ + + /* Did a nonblocking write fail before? Then check available write-space. */ + if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + + return ERR_OK; +} + +/** + * Sent callback function for TCP netconns. + * Signals the conn->sem and calls API_EVENT. + * netconn_write waits for conn->sem if send buffer is low. + * + * @see tcp.h (struct tcp_pcb.sent) for parameters and return value + */ +static err_t +sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn) { + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn WRITE_DELAYED); + } else if (conn->state == NETCONN_CLOSE) { + lwip_netconn_do_close_internal(conn WRITE_DELAYED); + } + + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); + } + } + + return ERR_OK; +} + +/** + * Error callback function for TCP netconns. + * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. + * The application thread has then to decide what to do. + * + * @see tcp.h (struct tcp_pcb.err) for parameters + */ +static void +err_tcp(void *arg, err_t err) +{ + struct netconn *conn; + enum netconn_state old_state; + + conn = (struct netconn *)arg; + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + conn->pcb.tcp = NULL; + + /* reset conn->state now before waking up other threads */ + old_state = conn->state; + conn->state = NETCONN_NONE; + + if (old_state == NETCONN_CLOSE) { + /* RST during close: let close return success & dealloc the netconn */ + err = ERR_OK; + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + } else { + /* no check since this is always fatal! */ + SYS_ARCH_SET(conn->last_err, err); + } + + /* @todo: the type of NETCONN_EVT created should depend on 'old_state' */ + + /* Notify the user layer about a connection error. Used to signal select. */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + /* Try to release selects pending on 'read' or 'write', too. + They will get an error if they actually try to read or write. */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + /* pass NULL-message to recvmbox to wake up pending recv */ + if (sys_mbox_valid(&conn->recvmbox)) { + /* use trypost to prevent deadlock */ + sys_mbox_trypost(&conn->recvmbox, NULL); + } + /* pass NULL-message to acceptmbox to wake up pending accept */ + if (sys_mbox_valid(&conn->acceptmbox)) { + /* use trypost to preven deadlock */ + sys_mbox_trypost(&conn->acceptmbox, NULL); + } + + if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || + (old_state == NETCONN_CONNECT)) { + /* calling lwip_netconn_do_writemore/lwip_netconn_do_close_internal is not necessary + since the pcb has already been deleted! */ + int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + + if (!was_nonblocking_connect) { + sys_sem_t* op_completed_sem; + /* set error return code */ + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + LWIP_ASSERT("inavlid op_completed_sem", sys_sem_valid(op_completed_sem)); + conn->current_msg = NULL; + /* wake up the waiting task */ + NETCONN_SET_SAFE_ERR(conn, err); + sys_sem_signal(op_completed_sem); + } + } else { + LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); + } +} + +/** + * Setup a tcp_pcb with the correct callback function pointers + * and their arguments. + * + * @param conn the TCP netconn to setup + */ +static void +setup_tcp(struct netconn *conn) +{ + struct tcp_pcb *pcb; + + pcb = conn->pcb.tcp; + tcp_arg(pcb, conn); + tcp_recv(pcb, recv_tcp); + tcp_sent(pcb, sent_tcp); + tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL); + tcp_err(pcb, err_tcp); +} + +/** + * Accept callback function for TCP netconns. + * Allocates a new netconn and posts that to conn->acceptmbox. + * + * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value + */ +static err_t +accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + struct netconn *newconn; + struct netconn *conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + if (!sys_mbox_valid(&conn->acceptmbox)) { + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); + return ERR_VAL; + } + + if (newpcb == NULL) { + /* out-of-pcbs during connect: pass on this error to the application */ + if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + return ERR_VAL; + } + + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); + + /* We have to set the callback here even though + * the new socket is unknown. newconn->socket is marked as -1. */ + newconn = netconn_alloc(conn->type, conn->callback); + if (newconn == NULL) { + /* outof netconns: pass on this error to the application */ + if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + return ERR_MEM; + } + newconn->pcb.tcp = newpcb; + setup_tcp(newconn); + /* no protection: when creating the pcb, the netconn is not yet known + to the application thread */ + newconn->last_err = err; + + /* handle backlog counter */ + tcp_backlog_delayed(newpcb); + + if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { + /* When returning != ERR_OK, the pcb is aborted in tcp_process(), + so do nothing here! */ + /* remove all references to this netconn from the pcb */ + struct tcp_pcb* pcb = newconn->pcb.tcp; + tcp_arg(pcb, NULL); + tcp_recv(pcb, NULL); + tcp_sent(pcb, NULL); + tcp_poll(pcb, NULL, 0); + tcp_err(pcb, NULL); + /* remove reference from to the pcb from this netconn */ + newconn->pcb.tcp = NULL; + /* no need to drain since we know the recvmbox is empty. */ + sys_mbox_free(&newconn->recvmbox); + sys_mbox_set_invalid(&newconn->recvmbox); + netconn_free(newconn); + return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Create a new pcb of a specific type. + * Called from lwip_netconn_do_newconn(). + * + * @param msg the api_msg_msg describing the connection type + */ +static void +pcb_new(struct api_msg *msg) +{ + enum lwip_ip_addr_type iptype = IPADDR_TYPE_V4; + + LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); + +#if LWIP_IPV6 && LWIP_IPV4 + /* IPv6: Dual-stack by default, unless netconn_set_ipv6only() is called */ + if(NETCONNTYPE_ISIPV6(netconn_type(msg->conn))) { + iptype = IPADDR_TYPE_ANY; + } +#endif + + /* Allocate a PCB for this connection */ + switch(NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto); + if (msg->conn->pcb.raw != NULL) { +#if LWIP_IPV6 + /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ + if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { + msg->conn->pcb.raw->chksum_reqd = 1; + msg->conn->pcb.raw->chksum_offset = 2; + } +#endif /* LWIP_IPV6 */ + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp = udp_new_ip_type(iptype); + if (msg->conn->pcb.udp != NULL) { +#if LWIP_UDPLITE + if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); + } +#endif /* LWIP_UDPLITE */ + if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); + } + udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->pcb.tcp = tcp_new_ip_type(iptype); + if (msg->conn->pcb.tcp != NULL) { + setup_tcp(msg->conn); + } + break; +#endif /* LWIP_TCP */ + default: + /* Unsupported netconn type, e.g. protocol disabled */ + msg->err = ERR_VAL; + return; + } + if (msg->conn->pcb.ip == NULL) { + msg->err = ERR_MEM; + } +} + +/** + * Create a new pcb of a specific type inside a netconn. + * Called from netconn_new_with_proto_and_callback. + * + * @param m the api_msg_msg describing the connection type + */ +void +lwip_netconn_do_newconn(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp == NULL) { + pcb_new(msg); + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ + /* We currently just are happy and return. */ + + TCPIP_APIMSG_ACK(msg); +} + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is NOT created! + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_alloc(enum netconn_type t, netconn_callback callback) +{ + struct netconn *conn; + int size; + + conn = (struct netconn *)memp_malloc(MEMP_NETCONN); + if (conn == NULL) { + return NULL; + } + + conn->last_err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + + /* If all sizes are the same, every compiler should optimize this switch to nothing */ + switch(NETCONNTYPE_GROUP(t)) { +#if LWIP_RAW + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + size = DEFAULT_UDP_RECVMBOX_SIZE; + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + size = DEFAULT_TCP_RECVMBOX_SIZE; + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); + goto free_and_return; + } + + if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { + goto free_and_return; + } +#if !LWIP_NETCONN_SEM_PER_THREAD + if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { + sys_mbox_free(&conn->recvmbox); + goto free_and_return; + } +#endif + +#if LWIP_TCP + sys_mbox_set_invalid(&conn->acceptmbox); +#endif + conn->state = NETCONN_NONE; +#if LWIP_SOCKET + /* initialize socket to -1 since 0 is a valid socket */ + conn->socket = -1; +#endif /* LWIP_SOCKET */ + conn->callback = callback; +#if LWIP_TCP + conn->current_msg = NULL; + conn->write_offset = 0; +#endif /* LWIP_TCP */ +#if LWIP_SO_SNDTIMEO + conn->send_timeout = 0; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + conn->recv_timeout = 0; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; + conn->recv_avail = 0; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + conn->linger = -1; +#endif /* LWIP_SO_LINGER */ + conn->flags = 0; + return conn; +free_and_return: + memp_free(MEMP_NETCONN, conn); + return NULL; +} + +/** + * Delete a netconn and all its resources. + * The pcb is NOT freed (since we might not be in the right thread context do this). + * + * @param conn the netconn to free + */ +void +netconn_free(struct netconn *conn) +{ + LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); + LWIP_ASSERT("recvmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("acceptmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ + +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(&conn->op_completed); + sys_sem_set_invalid(&conn->op_completed); +#endif + + memp_free(MEMP_NETCONN, conn); +} + +/** + * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in + * these mboxes + * + * @param conn the netconn to free + * @bytes_drained bytes drained from recvmbox + * @accepts_drained pending connections drained from acceptmbox + */ +static void +netconn_drain(struct netconn *conn) +{ + void *mem; +#if LWIP_TCP + struct pbuf *p; +#endif /* LWIP_TCP */ + + /* This runs in tcpip_thread, so we don't need to lock against rx packets */ + + /* Delete and drain the recvmbox. */ + if (sys_mbox_valid(&conn->recvmbox)) { + while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { +#if LWIP_TCP + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) { + if (mem != NULL) { + p = (struct pbuf*)mem; + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_recved(conn->pcb.tcp, p->tot_len); + } + pbuf_free(p); + } + } else +#endif /* LWIP_TCP */ + { + netbuf_delete((struct netbuf *)mem); + } + } + sys_mbox_free(&conn->recvmbox); + sys_mbox_set_invalid(&conn->recvmbox); + } + + /* Delete and drain the acceptmbox. */ +#if LWIP_TCP + if (sys_mbox_valid(&conn->acceptmbox)) { + while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { + if (mem != &netconn_aborted) { + struct netconn *newconn = (struct netconn *)mem; + /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ + /* pcb might be set to NULL already by err_tcp() */ + /* drain recvmbox */ + netconn_drain(newconn); + if (newconn->pcb.tcp != NULL) { + tcp_abort(newconn->pcb.tcp); + newconn->pcb.tcp = NULL; + } + netconn_free(newconn); + } + } + sys_mbox_free(&conn->acceptmbox); + sys_mbox_set_invalid(&conn->acceptmbox); + } +#endif /* LWIP_TCP */ +} + +#if LWIP_TCP +/** + * Internal helper function to close a TCP netconn: since this sometimes + * doesn't work at the first attempt, this function is called from multiple + * places. + * + * @param conn the TCP netconn to close + */ +static err_t +lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM) +{ + err_t err; + u8_t shut, shut_rx, shut_tx, close; + u8_t close_finished = 0; + struct tcp_pcb* tpcb; +#if LWIP_SO_LINGER + u8_t linger_wait_required = 0; +#endif /* LWIP_SO_LINGER */ + + LWIP_ASSERT("invalid conn", (conn != NULL)); + LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)); + LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); + LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + + tpcb = conn->pcb.tcp; + shut = conn->current_msg->msg.sd.shut; + shut_rx = shut & NETCONN_SHUT_RD; + shut_tx = shut & NETCONN_SHUT_WR; + /* shutting down both ends is the same as closing + (also if RD or WR side was shut down before already) */ + if (shut == NETCONN_SHUT_RDWR) { + close = 1; + } else if (shut_rx && + ((tpcb->state == FIN_WAIT_1) || + (tpcb->state == FIN_WAIT_2) || + (tpcb->state == CLOSING))) { + close = 1; + } else if (shut_tx && ((tpcb->flags & TF_RXCLOSED) != 0)) { + close = 1; + } else { + close = 0; + } + + /* Set back some callback pointers */ + if (close) { + tcp_arg(tpcb, NULL); + } + if (tpcb->state == LISTEN) { + tcp_accept(tpcb, NULL); + } else { + /* some callbacks have to be reset if tcp_close is not successful */ + if (shut_rx) { + tcp_recv(tpcb, NULL); + tcp_accept(tpcb, NULL); + } + if (shut_tx) { + tcp_sent(tpcb, NULL); + } + if (close) { + tcp_poll(tpcb, NULL, 0); + tcp_err(tpcb, NULL); + } + } + /* Try to close the connection */ + if (close) { +#if LWIP_SO_LINGER + /* check linger possibilites before calling tcp_close */ + err = ERR_OK; + /* linger enabled/required at all? (i.e. is there untransmitted data left?) */ + if ((conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) { + if ((conn->linger == 0)) { + /* data left but linger prevents waiting */ + tcp_abort(tpcb); + tpcb = NULL; + } else if (conn->linger > 0) { + /* data left and linger says we should wait */ + if (netconn_is_nonblocking(conn)) { + /* data left on a nonblocking netconn -> cannot linger */ + err = ERR_WOULDBLOCK; + } else if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= + (conn->linger * 1000)) { + /* data left but linger timeout has expired (this happens on further + calls to this function through poll_tcp */ + tcp_abort(tpcb); + tpcb = NULL; + } else { + /* data left -> need to wait for ACK after successful close */ + linger_wait_required = 1; + } + } + } + if ((err == ERR_OK) && (tpcb != NULL)) +#endif /* LWIP_SO_LINGER */ + { + err = tcp_close(tpcb); + } + } else { + err = tcp_shutdown(tpcb, shut_rx, shut_tx); + } + if (err == ERR_OK) { + close_finished = 1; +#if LWIP_SO_LINGER + if (linger_wait_required) { + /* wait for ACK of all unsent/unacked data by just getting called again */ + close_finished = 0; + err = ERR_INPROGRESS; + } +#endif /* LWIP_SO_LINGER */ + } else { + if (err == ERR_MEM) { + /* Closing failed because of memory shortage, try again later. Even for + nonblocking netconns, we have to wait since no standard socket application + is prepared for close failing because of resource shortage. + Check the timeout: this is kind of an lwip addition to the standard sockets: + we wait for some time when failing to allocate a segment for the FIN */ +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT; +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout > 0) { + close_timeout = conn->send_timeout; + } +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_LINGER + if (conn->linger >= 0) { + /* use linger timeout (seconds) */ + close_timeout = conn->linger * 1000U; + } +#endif + if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) { +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + if (conn->current_msg->msg.sd.polls_left == 0) { +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + close_finished = 1; + if (close) { + /* in this case, we want to RST the connection */ + tcp_abort(tpcb); + err = ERR_OK; + } + } + } else { + /* Closing failed for a non-memory error: give up */ + close_finished = 1; + } + } + if (close_finished) { + /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + if (err == ERR_OK) { + if (close) { + /* Set back some callback pointers as conn is going away */ + conn->pcb.tcp = NULL; + /* Trigger select() in socket layer. Make sure everybody notices activity + on the connection, error first! */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + } + if (shut_rx) { + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + if (shut_tx) { + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + NETCONN_SET_SAFE_ERR(conn, err); +#if LWIP_TCPIP_CORE_LOCKING + if (delayed) +#endif + { + /* wake up the application task */ + sys_sem_signal(op_completed_sem); + } + return ERR_OK; + } + if (!close_finished) { + /* Closing failed and we want to wait: restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + LWIP_ASSERT("Closing a listen pcb may not fail!", (tpcb->state != LISTEN)); + if (shut_tx) { + tcp_sent(tpcb, sent_tcp); + } + /* when waiting for close, set up poll interval to 500ms */ + tcp_poll(tpcb, poll_tcp, 1); + tcp_err(tpcb, err_tcp); + tcp_arg(tpcb, conn); + /* don't restore recv callback: we don't want to receive any more data */ + } + /* If closing didn't succeed, we get called again either + from poll_tcp or from sent_tcp */ + LWIP_ASSERT("err != ERR_OK", err != ERR_OK); + return err; +} +#endif /* LWIP_TCP */ + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_delconn(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + enum netconn_state state = msg->conn->state; + LWIP_ASSERT("netconn state error", /* this only happens for TCP netconns */ + (state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)); +#if LWIP_NETCONN_FULLDUPLEX + /* In full duplex mode, blocking write/connect is aborted with ERR_CLSD */ + if (state != NETCONN_NONE) { + if ((state == NETCONN_WRITE) || + ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { + /* close requested, abort running write/connect */ + sys_sem_t* op_completed_sem; + LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); + op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); + msg->conn->current_msg->err = ERR_CLSD; + msg->conn->current_msg = NULL; + msg->conn->write_offset = 0; + msg->conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); + sys_sem_signal(op_completed_sem); + } + } +#else /* LWIP_NETCONN_FULLDUPLEX */ + if (((state != NETCONN_NONE) && + (state != NETCONN_LISTEN) && + (state != NETCONN_CONNECT)) || + ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { + /* This means either a blocking write or blocking connect is running + (nonblocking write returns and sets state to NONE) */ + msg->err = ERR_INPROGRESS; + } else +#endif /* LWIP_NETCONN_FULLDUPLEX */ + { + LWIP_ASSERT("blocking connect in progress", + (state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); + msg->err = ERR_OK; + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + + if (msg->conn->pcb.tcp != NULL) { + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp->recv_arg = NULL; + udp_remove(msg->conn->pcb.udp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->msg.sd.shut = NETCONN_SHUT_RDWR; + msg->conn->current_msg = msg; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_close_internal(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing + the application thread, so we can return at this point! */ + return; +#endif /* LWIP_TCP */ + default: + break; + } + msg->conn->pcb.tcp = NULL; + } + /* tcp netconns don't come here! */ + + /* @todo: this lets select make the socket readable and writable, + which is wrong! errfd instead? */ + API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); + } + if (sys_sem_valid(LWIP_API_MSG_SEM(msg))) { + TCPIP_APIMSG_ACK(msg); + } +} + +/** + * Bind a pcb contained in a netconn + * Called from netconn_bind. + * + * @param m the api_msg_msg pointing to the connection and containing + * the IP address and port to bind to + */ +void +lwip_netconn_do_bind(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_VAL; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_TCP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * TCP callback function if a connection (opened by tcp_connect/lwip_netconn_do_connect) has + * been established (or reset by the remote host). + * + * @see tcp.h (struct tcp_pcb.connected) for parameters and return values + */ +static err_t +lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netconn *conn; + int was_blocking; + sys_sem_t* op_completed_sem = NULL; + + LWIP_UNUSED_ARG(pcb); + + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + + LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT); + LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect", + (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn)); + + if (conn->current_msg != NULL) { + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + } + if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) { + setup_tcp(conn); + } + was_blocking = !IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + LWIP_ASSERT("blocking connect state error", + (was_blocking && op_completed_sem != NULL) || + (!was_blocking && op_completed_sem == NULL)); + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + if (was_blocking) { + sys_sem_signal(op_completed_sem); + } + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Connect a pcb contained inside a netconn + * Called from netconn_connect. + * + * @param m the api_msg_msg pointing to the connection and containing + * the IP address and port to connect to + */ +void +lwip_netconn_do_connect(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (msg->conn->pcb.tcp == NULL) { + /* This may happen when calling netconn_connect() a second time */ + msg->err = ERR_CLSD; + } else { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + /* Prevent connect while doing any other action. */ + if (msg->conn->state == NETCONN_CONNECT) { + msg->err = ERR_ALREADY; + } else if (msg->conn->state != NETCONN_NONE) { + msg->err = ERR_ISCONN; + } else { + setup_tcp(msg->conn); + msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), + msg->msg.bc.port, lwip_netconn_do_connected); + if (msg->err == ERR_OK) { + u8_t non_blocking = netconn_is_nonblocking(msg->conn); + msg->conn->state = NETCONN_CONNECT; + SET_NONBLOCKING_CONNECT(msg->conn, non_blocking); + if (non_blocking) { + msg->err = ERR_INPROGRESS; + } else { + msg->conn->current_msg = msg; + /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()), + when the connection is established! */ +#if LWIP_TCPIP_CORE_LOCKING + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CONNECT); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state != NETCONN_CONNECT); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + return; + } + } + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0)); + break; + } + } + /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(), + so use TCPIP_APIMSG_ACK() here. */ + TCPIP_APIMSG_ACK(msg); +} + +/** + * Disconnect a pcb contained inside a netconn + * Only used for UDP netconns. + * Called from netconn_disconnect. + * + * @param m the api_msg_msg pointing to the connection to disconnect + */ +void +lwip_netconn_do_disconnect(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + +#if LWIP_UDP + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { + udp_disconnect(msg->conn->pcb.udp); + msg->err = ERR_OK; + } else +#endif /* LWIP_UDP */ + { + msg->err = ERR_VAL; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Set a TCP pcb contained in a netconn into listen mode + * Called from netconn_listen. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_listen(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + if (msg->conn->state == NETCONN_NONE) { + struct tcp_pcb* lpcb; + if (msg->conn->pcb.tcp->state != CLOSED) { + /* connection is not closed, cannot listen */ + msg->err = ERR_VAL; + } else { + err_t err; + u8_t backlog; +#if TCP_LISTEN_BACKLOG + backlog = msg->msg.lb.backlog; +#else /* TCP_LISTEN_BACKLOG */ + backlog = TCP_DEFAULT_LISTEN_BACKLOG; +#endif /* TCP_LISTEN_BACKLOG */ +#if LWIP_IPV4 && LWIP_IPV6 + /* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY, + * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen + */ + if (ip_addr_cmp(&msg->conn->pcb.ip->local_ip, IP6_ADDR_ANY) && + (netconn_get_ipv6only(msg->conn) == 0)) { + /* change PCB type to IPADDR_TYPE_ANY */ + IP_SET_TYPE_VAL(msg->conn->pcb.tcp->local_ip, IPADDR_TYPE_ANY); + IP_SET_TYPE_VAL(msg->conn->pcb.tcp->remote_ip, IPADDR_TYPE_ANY); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + lpcb = tcp_listen_with_backlog_and_err(msg->conn->pcb.tcp, backlog, &err); + + if (lpcb == NULL) { + /* in this case, the old pcb is still allocated */ + msg->err = err; + } else { + /* delete the recvmbox and allocate the acceptmbox */ + if (sys_mbox_valid(&msg->conn->recvmbox)) { + /** @todo: should we drain the recvmbox here? */ + sys_mbox_free(&msg->conn->recvmbox); + sys_mbox_set_invalid(&msg->conn->recvmbox); + } + msg->err = ERR_OK; + if (!sys_mbox_valid(&msg->conn->acceptmbox)) { + msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); + } + if (msg->err == ERR_OK) { + msg->conn->state = NETCONN_LISTEN; + msg->conn->pcb.tcp = lpcb; + tcp_arg(msg->conn->pcb.tcp, msg->conn); + tcp_accept(msg->conn->pcb.tcp, accept_function); + } else { + /* since the old pcb is already deallocated, free lpcb now */ + tcp_close(lpcb); + msg->conn->pcb.tcp = NULL; + } + } + } + } else if (msg->conn->state == NETCONN_LISTEN) { + /* already listening, allow updating of the backlog */ + msg->err = ERR_OK; + tcp_backlog_set(msg->conn->pcb.tcp, msg->msg.lb.backlog); + } + } else { + msg->err = ERR_ARG; + } + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a RAW or UDP pcb contained in a netconn + * Called from netconn_send + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_send(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); + } + break; +#endif +#if LWIP_UDP + case NETCONN_UDP: +#if LWIP_CHECKSUM_ON_COPY + if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } else { + msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p, + &msg->msg.b->addr, msg->msg.b->port, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } +#else /* LWIP_CHECKSUM_ON_COPY */ + if (ip_addr_isany_val(msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); + } else { + msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + break; +#endif /* LWIP_UDP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Indicate data has been received from a TCP pcb contained in a netconn + * Called from netconn_recv + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_recv(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + u32_t remaining = msg->msg.r.len; + do { + u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; + tcp_recved(msg->conn->pcb.tcp, recved); + remaining -= recved; + } while (remaining != 0); + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if TCP_LISTEN_BACKLOG +/** Indicate that a TCP pcb has been accepted + * Called from netconn_accept + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_accepted(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + tcp_backlog_accepted(msg->conn->pcb.tcp); + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* TCP_LISTEN_BACKLOG */ + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from lwip_netconn_do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ +static err_t +lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) +{ + err_t err; + const void *dataptr; + u16_t len, available; + u8_t write_finished = 0; + size_t diff; + u8_t dontblock; + u8_t apiflags; + + LWIP_ASSERT("conn != NULL", conn != NULL); + LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); + LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", + conn->write_offset < conn->current_msg->msg.w.len); + + apiflags = conn->current_msg->msg.w.apiflags; + dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); + +#if LWIP_SO_SNDTIMEO + if ((conn->send_timeout != 0) && + ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { + write_finished = 1; + if (conn->write_offset == 0) { + /* nothing has been written */ + err = ERR_WOULDBLOCK; + conn->current_msg->msg.w.len = 0; + } else { + /* partial write */ + err = ERR_OK; + conn->current_msg->msg.w.len = conn->write_offset; + conn->write_offset = 0; + } + } else +#endif /* LWIP_SO_SNDTIMEO */ + { + dataptr = (const u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; + diff = conn->current_msg->msg.w.len - conn->write_offset; + if (diff > 0xffffUL) { /* max_u16_t */ + len = 0xffff; + apiflags |= TCP_WRITE_FLAG_MORE; + } else { + len = (u16_t)diff; + } + available = tcp_sndbuf(conn->pcb.tcp); + if (available < len) { + /* don't try to write more than sendbuf */ + len = available; + if (dontblock) { + if (!len) { + err = ERR_WOULDBLOCK; + goto err_mem; + } + } else { + apiflags |= TCP_WRITE_FLAG_MORE; + } + } + LWIP_ASSERT("lwip_netconn_do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); + err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); + /* if OK or memory error, check available space */ + if ((err == ERR_OK) || (err == ERR_MEM)) { +err_mem: + if (dontblock && (len < conn->current_msg->msg.w.len)) { + /* non-blocking write did not write everything: mark the pcb non-writable + and let poll_tcp check writable space to mark the pcb writable again */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; + } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || + (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { + /* The queued byte- or pbuf-count exceeds the configured low-water limit, + let select mark this pcb as non-writable. */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + } + } + + if (err == ERR_OK) { + err_t out_err; + conn->write_offset += len; + if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { + /* return sent length */ + conn->current_msg->msg.w.len = conn->write_offset; + /* everything was written */ + write_finished = 1; + } + out_err = tcp_output(conn->pcb.tcp); + if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { + /* If tcp_output fails with fatal error or no route is found, + don't try writing any more but return the error + to the application thread. */ + err = out_err; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } else if (err == ERR_MEM) { + /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called. + For blocking sockets, we do NOT return to the application + thread, since ERR_MEM is only a temporary error! Non-blocking + will remain non-writable until sent_tcp/poll_tcp is called */ + + /* tcp_write returned ERR_MEM, try tcp_output anyway */ + err_t out_err = tcp_output(conn->pcb.tcp); + if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { + /* If tcp_output fails with fatal error or no route is found, + don't try writing any more but return the error + to the application thread. */ + err = out_err; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } else if (dontblock) { + /* non-blocking write is done on ERR_MEM */ + err = ERR_WOULDBLOCK; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } else { + /* On errors != ERR_MEM, we don't try writing any more but return + the error to the application thread. */ + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } + if (write_finished) { + /* everything was written: set back connection state + and back to application task */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->write_offset = 0; + conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(conn, err); +#if LWIP_TCPIP_CORE_LOCKING + if (delayed) +#endif + { + sys_sem_signal(op_completed_sem); + } + } +#if LWIP_TCPIP_CORE_LOCKING + else { + return ERR_MEM; + } +#endif + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a TCP pcb contained in a netconn + * Called from netconn_write + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_write(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { +#if LWIP_TCP + if (msg->conn->state != NETCONN_NONE) { + /* netconn is connecting, closing or in blocking write */ + msg->err = ERR_INPROGRESS; + } else if (msg->conn->pcb.tcp != NULL) { + msg->conn->state = NETCONN_WRITE; + /* set all the variables used by lwip_netconn_do_writemore */ + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); + msg->conn->current_msg = msg; + msg->conn->write_offset = 0; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_writemore(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_writemore(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for both cases: if lwip_netconn_do_writemore was called, don't ACK the APIMSG + since lwip_netconn_do_writemore ACKs it! */ + return; + } else { + msg->err = ERR_CONN; + } +#else /* LWIP_TCP */ + msg->err = ERR_VAL; +#endif /* LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Return a connection's local or remote address + * Called from netconn_getaddr + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_getaddr(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (msg->conn->pcb.ip != NULL) { + if (msg->msg.ad.local) { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->local_ip); + } else { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->remote_ip); + } + + msg->err = ERR_OK; + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; + } else { + /* return an error as connecting is only a helper for upper layers */ + msg->err = ERR_CONN; + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; + } else { + if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; + } + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + if ((msg->msg.ad.local == 0) && + ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) { + /* pcb is not connected and remote name is requested */ + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port); + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("invalid netconn_type", 0); + break; + } + } else { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Close or half-shutdown a TCP pcb contained in a netconn + * Called from netconn_close + * In contrast to closing sockets, the netconn is not deallocated. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_close(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + +#if LWIP_TCP + enum netconn_state state = msg->conn->state; + /* First check if this is a TCP netconn and if it is in a correct state + (LISTEN doesn't support half shutdown) */ + if ((msg->conn->pcb.tcp != NULL) && + (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) && + ((msg->msg.sd.shut == NETCONN_SHUT_RDWR) || (state != NETCONN_LISTEN))) { + /* Check if we are in a connected state */ + if (state == NETCONN_CONNECT) { + /* TCP connect in progress: cannot shutdown */ + msg->err = ERR_CONN; + } else if (state == NETCONN_WRITE) { +#if LWIP_NETCONN_FULLDUPLEX + if (msg->msg.sd.shut & NETCONN_SHUT_WR) { + /* close requested, abort running write */ + sys_sem_t* write_completed_sem; + LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); + write_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); + msg->conn->current_msg->err = ERR_CLSD; + msg->conn->current_msg = NULL; + msg->conn->write_offset = 0; + msg->conn->state = NETCONN_NONE; + state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); + sys_sem_signal(write_completed_sem); + } else { + LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD); + /* In this case, let the write continue and do not interfere with + conn->current_msg or conn->state! */ + msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0); + } + } + if (state == NETCONN_NONE) { +#else /* LWIP_NETCONN_FULLDUPLEX */ + msg->err = ERR_INPROGRESS; + } else { +#endif /* LWIP_NETCONN_FULLDUPLEX */ + if (msg->msg.sd.shut & NETCONN_SHUT_RD) { + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + } + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->conn->current_msg = msg; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_close_internal(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for tcp netconns, lwip_netconn_do_close_internal ACKs the message */ + return; + } + } else +#endif /* LWIP_TCP */ + { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** + * Join multicast groups for UDP netconns. + * Called from netconn_join_leave_group + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_join_leave_group(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { +#if LWIP_UDP +#if LWIP_IPV6 && LWIP_IPV6_MLD + if (NETCONNTYPE_ISIPV6(msg->conn->type)) { + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = mld6_joingroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = mld6_leavegroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } + } + else +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + { +#if LWIP_IGMP + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = igmp_joingroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = igmp_leavegroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } +#endif /* LWIP_IGMP */ + } +#endif /* LWIP_UDP */ +#if (LWIP_TCP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_TCP || LWIP_RAW) */ + } + } else { + msg->err = ERR_CONN; + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/** + * Callback function that is called when DNS name is resolved + * (or on timeout). A waiting application thread is waked up by + * signaling the semaphore. + */ +static void +lwip_netconn_do_dns_found(const char *name, const ip_addr_t *ipaddr, void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + /* we trust the internal implementation to be correct :-) */ + LWIP_UNUSED_ARG(name); + + if (ipaddr == NULL) { + /* timeout or memory error */ + API_EXPR_DEREF(msg->err) = ERR_VAL; + } else { + /* address was resolved */ + API_EXPR_DEREF(msg->err) = ERR_OK; + API_EXPR_DEREF(msg->addr) = *ipaddr; + } + /* wake up the application task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); +} + +/** + * Execute a DNS query + * Called from netconn_gethostbyname + * + * @param arg the dns_api_msg pointing to the query + */ +void +lwip_netconn_do_gethostbyname(void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + u8_t addrtype = +#if LWIP_IPV4 && LWIP_IPV6 + msg->dns_addrtype; +#else + LWIP_DNS_ADDRTYPE_DEFAULT; +#endif + + API_EXPR_DEREF(msg->err) = dns_gethostbyname_addrtype(msg->name, + API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg, addrtype); + if (API_EXPR_DEREF(msg->err) != ERR_INPROGRESS) { + /* on error or immediate success, wake up the application + * task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); + } +} +#endif /* LWIP_DNS */ + +#endif /* LWIP_NETCONN */ diff --git a/components/net/lwip-2.0.3/src/api/err.c b/components/net/lwip-2.0.3/src/api/err.c new file mode 100644 index 0000000000..35e9c025ea --- /dev/null +++ b/components/net/lwip-2.0.3/src/api/err.c @@ -0,0 +1,115 @@ +/** + * @file + * Error Management module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/err.h" +#include "lwip/def.h" +#include "lwip/sys.h" + +#include "lwip/errno.h" + +#if !NO_SYS +/** Table to quickly map an lwIP error (err_t) to a socket error + * by using -err as an index */ +static const int err_to_errno_table[] = { + 0, /* ERR_OK 0 No error, everything OK. */ + ENOMEM, /* ERR_MEM -1 Out of memory error. */ + ENOBUFS, /* ERR_BUF -2 Buffer error. */ + EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ + EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ + EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ + EINVAL, /* ERR_VAL -6 Illegal value. */ + EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ + EADDRINUSE, /* ERR_USE -8 Address in use. */ + EALREADY, /* ERR_ALREADY -9 Already connecting. */ + EISCONN, /* ERR_ISCONN -10 Conn already established.*/ + ENOTCONN, /* ERR_CONN -11 Not connected. */ + -1, /* ERR_IF -12 Low-level netif error */ + ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */ + ECONNRESET, /* ERR_RST -14 Connection reset. */ + ENOTCONN, /* ERR_CLSD -15 Connection closed. */ + EIO /* ERR_ARG -16 Illegal argument. */ +}; + +int +err_to_errno(err_t err) +{ + if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) { + return EIO; + } + return err_to_errno_table[-err]; +} +#endif /* !NO_SYS */ + +#ifdef LWIP_DEBUG + +static const char *err_strerr[] = { + "Ok.", /* ERR_OK 0 */ + "Out of memory error.", /* ERR_MEM -1 */ + "Buffer error.", /* ERR_BUF -2 */ + "Timeout.", /* ERR_TIMEOUT -3 */ + "Routing problem.", /* ERR_RTE -4 */ + "Operation in progress.", /* ERR_INPROGRESS -5 */ + "Illegal value.", /* ERR_VAL -6 */ + "Operation would block.", /* ERR_WOULDBLOCK -7 */ + "Address in use.", /* ERR_USE -8 */ + "Already connecting.", /* ERR_ALREADY -9 */ + "Already connected.", /* ERR_ISCONN -10 */ + "Not connected.", /* ERR_CONN -11 */ + "Low-level netif error.", /* ERR_IF -12 */ + "Connection aborted.", /* ERR_ABRT -13 */ + "Connection reset.", /* ERR_RST -14 */ + "Connection closed.", /* ERR_CLSD -15 */ + "Illegal argument." /* ERR_ARG -16 */ +}; + +/** + * Convert an lwip internal error to a string representation. + * + * @param err an lwip internal err_t + * @return a string representation for err + */ +const char * +lwip_strerr(err_t err) +{ + if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_strerr))) { + return "Unknown error."; + } + return err_strerr[-err]; +} + +#endif /* LWIP_DEBUG */ diff --git a/components/net/lwip-2.0.3/src/api/netbuf.c b/components/net/lwip-2.0.3/src/api/netbuf.c new file mode 100644 index 0000000000..eb250115ff --- /dev/null +++ b/components/net/lwip-2.0.3/src/api/netbuf.c @@ -0,0 +1,246 @@ +/** + * @file + * Network buffer management + * + * @defgroup netbuf Network buffers + * @ingroup netconn + * Network buffer descriptor for @ref netconn. Based on @ref pbuf internally + * to avoid copying data around.\n + * Buffers must not be shared accross multiple threads, all functions except + * netbuf_new() and netbuf_delete() are not thread-safe. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netbuf.h" +#include "lwip/memp.h" + +#include + +/** + * @ingroup netbuf + * Create (allocate) and initialize a new netbuf. + * The netbuf doesn't yet contain a packet buffer! + * + * @return a pointer to a new netbuf + * NULL on lack of memory + */ +struct +netbuf *netbuf_new(void) +{ + struct netbuf *buf; + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf != NULL) { + memset(buf, 0, sizeof(struct netbuf)); + } + return buf; +} + +/** + * @ingroup netbuf + * Deallocate a netbuf allocated by netbuf_new(). + * + * @param buf pointer to a netbuf allocated by netbuf_new() + */ +void +netbuf_delete(struct netbuf *buf) +{ + if (buf != NULL) { + if (buf->p != NULL) { + pbuf_free(buf->p); + buf->p = buf->ptr = NULL; + } + memp_free(MEMP_NETBUF, buf); + } +} + +/** + * @ingroup netbuf + * Allocate memory for a packet buffer for a given netbuf. + * + * @param buf the netbuf for which to allocate a packet buffer + * @param size the size of the packet buffer to allocate + * @return pointer to the allocated memory + * NULL if no memory could be allocated + */ +void * +netbuf_alloc(struct netbuf *buf, u16_t size) +{ + LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); + + /* Deallocate any previously allocated memory. */ + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); + if (buf->p == NULL) { + return NULL; + } + LWIP_ASSERT("check that first pbuf can hold size", + (buf->p->len >= size)); + buf->ptr = buf->p; + return buf->p->payload; +} + +/** + * @ingroup netbuf + * Free the packet buffer included in a netbuf + * + * @param buf pointer to the netbuf which contains the packet buffer to free + */ +void +netbuf_free(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = buf->ptr = NULL; +} + +/** + * @ingroup netbuf + * Let a netbuf reference existing (non-volatile) data. + * + * @param buf netbuf which should reference the data + * @param dataptr pointer to the data to reference + * @param size size of the data + * @return ERR_OK if data is referenced + * ERR_MEM if data couldn't be referenced due to lack of memory + */ +err_t +netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) +{ + LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (buf->p == NULL) { + buf->ptr = NULL; + return ERR_MEM; + } + ((struct pbuf_rom*)buf->p)->payload = dataptr; + buf->p->len = buf->p->tot_len = size; + buf->ptr = buf->p; + return ERR_OK; +} + +/** + * @ingroup netbuf + * Chain one netbuf to another (@see pbuf_chain) + * + * @param head the first netbuf + * @param tail netbuf to chain after head, freed by this function, may not be reference after returning + */ +void +netbuf_chain(struct netbuf *head, struct netbuf *tail) +{ + LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;); + LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); + pbuf_cat(head->p, tail->p); + head->ptr = head->p; + memp_free(MEMP_NETBUF, tail); +} + +/** + * @ingroup netbuf + * Get the data pointer and length of the data inside a netbuf. + * + * @param buf netbuf to get the data from + * @param dataptr pointer to a void pointer where to store the data pointer + * @param len pointer to an u16_t where the length of the data is stored + * @return ERR_OK if the information was retrieved, + * ERR_BUF on error. + */ +err_t +netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) +{ + LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;); + + if (buf->ptr == NULL) { + return ERR_BUF; + } + *dataptr = buf->ptr->payload; + *len = buf->ptr->len; + return ERR_OK; +} + +/** + * @ingroup netbuf + * Move the current data pointer of a packet buffer contained in a netbuf + * to the next part. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + * @return -1 if there is no next part + * 1 if moved to the next part but now there is no next part + * 0 if moved to the next part and there are still more parts + */ +s8_t +netbuf_next(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;); + if (buf->ptr->next == NULL) { + return -1; + } + buf->ptr = buf->ptr->next; + if (buf->ptr->next == NULL) { + return 1; + } + return 0; +} + +/** + * @ingroup netbuf + * Move the current data pointer of a packet buffer contained in a netbuf + * to the beginning of the packet. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + */ +void +netbuf_first(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;); + buf->ptr = buf->p; +} + +#endif /* LWIP_NETCONN */ diff --git a/components/net/lwip-2.0.3/src/api/netdb.c b/components/net/lwip-2.0.3/src/api/netdb.c new file mode 100644 index 0000000000..ccd9586fda --- /dev/null +++ b/components/net/lwip-2.0.3/src/api/netdb.c @@ -0,0 +1,413 @@ +/** + * @file + * API functions for name resolving + * + * @defgroup netdbapi NETDB API + * @ingroup socket + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/netdb.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include "lwip/err.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/api.h" +#include "lwip/dns.h" + +#include /* memset */ +#include /* atoi */ + +/** helper struct for gethostbyname_r to access the char* buffer */ +struct gethostbyname_r_helper { + ip_addr_t *addr_list[2]; + ip_addr_t addr; + char *aliases; +}; + +/** h_errno is exported in netdb.h for access by applications. */ +#if LWIP_DNS_API_DECLARE_H_ERRNO +int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ + +/** define "hostent" variables storage: 0 if we use a static (but unprotected) + * set of variables for lwip_gethostbyname, 1 if we use a local storage */ +#ifndef LWIP_DNS_API_HOSTENT_STORAGE +#define LWIP_DNS_API_HOSTENT_STORAGE 0 +#endif + +/** define "hostent" variables storage */ +#if LWIP_DNS_API_HOSTENT_STORAGE +#define HOSTENT_STORAGE +#else +#define HOSTENT_STORAGE static +#endif /* LWIP_DNS_API_STATIC_HOSTENT */ + +/** + * Returns an entry containing addresses of address family AF_INET + * for the host with name name. + * Due to dns_gethostbyname limitations, only one address is returned. + * + * @param name the hostname to resolve + * @return an entry containing addresses of address family AF_INET + * for the host with name name + */ +struct hostent* +lwip_gethostbyname(const char *name) +{ + err_t err; + ip_addr_t addr; + + /* buffer variables for lwip_gethostbyname() */ + HOSTENT_STORAGE struct hostent s_hostent; + HOSTENT_STORAGE char *s_aliases; + HOSTENT_STORAGE ip_addr_t s_hostent_addr; + HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2]; + HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1]; + + /* query host IP address */ + err = netconn_gethostbyname(name, &addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + h_errno = HOST_NOT_FOUND; + return NULL; + } + + /* fill hostent */ + s_hostent_addr = addr; + s_phostent_addr[0] = &s_hostent_addr; + s_phostent_addr[1] = NULL; + strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH); + s_hostname[DNS_MAX_NAME_LENGTH] = 0; + s_hostent.h_name = s_hostname; + s_aliases = NULL; + s_hostent.h_aliases = &s_aliases; + s_hostent.h_addrtype = AF_INET; + s_hostent.h_length = sizeof(ip_addr_t); + s_hostent.h_addr_list = (char**)&s_phostent_addr; + +#if DNS_DEBUG + /* dump hostent */ + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", (void*)s_hostent.h_aliases)); + /* h_aliases are always empty */ + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", (void*)s_hostent.h_addr_list)); + if (s_hostent.h_addr_list != NULL) { + u8_t idx; + for (idx=0; s_hostent.h_addr_list[idx]; idx++) { + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx])); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx]))); + } + } +#endif /* DNS_DEBUG */ + +#if LWIP_DNS_API_HOSTENT_STORAGE + /* this function should return the "per-thread" hostent after copy from s_hostent */ + return sys_thread_hostent(&s_hostent); +#else + return &s_hostent; +#endif /* LWIP_DNS_API_HOSTENT_STORAGE */ +} + +/** + * Thread-safe variant of lwip_gethostbyname: instead of using a static + * buffer, this function takes buffer and errno pointers as arguments + * and uses these for the result. + * + * @param name the hostname to resolve + * @param ret pre-allocated struct where to store the result + * @param buf pre-allocated buffer where to store additional data + * @param buflen the size of buf + * @param result pointer to a hostent pointer that is set to ret on success + * and set to zero on error + * @param h_errnop pointer to an int where to store errors (instead of modifying + * the global h_errno) + * @return 0 on success, non-zero on error, additional error information + * is stored in *h_errnop instead of h_errno to be thread-safe + */ +int +lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop) +{ + err_t err; + struct gethostbyname_r_helper *h; + char *hostname; + size_t namelen; + int lh_errno; + + if (h_errnop == NULL) { + /* ensure h_errnop is never NULL */ + h_errnop = &lh_errno; + } + + if (result == NULL) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + /* first thing to do: set *result to nothing */ + *result = NULL; + if ((name == NULL) || (ret == NULL) || (buf == NULL)) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + + namelen = strlen(name); + if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) { + /* buf can't hold the data needed + a copy of name */ + *h_errnop = ERANGE; + return -1; + } + + h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf); + hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper); + + /* query host IP address */ + err = netconn_gethostbyname(name, &h->addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + *h_errnop = HOST_NOT_FOUND; + return -1; + } + + /* copy the hostname into buf */ + MEMCPY(hostname, name, namelen); + hostname[namelen] = 0; + + /* fill hostent */ + h->addr_list[0] = &h->addr; + h->addr_list[1] = NULL; + h->aliases = NULL; + ret->h_name = hostname; + ret->h_aliases = &h->aliases; + ret->h_addrtype = AF_INET; + ret->h_length = sizeof(ip_addr_t); + ret->h_addr_list = (char**)&h->addr_list; + + /* set result != NULL */ + *result = ret; + + /* return success */ + return 0; +} + +/** + * Frees one or more addrinfo structures returned by getaddrinfo(), along with + * any additional storage associated with those structures. If the ai_next field + * of the structure is not null, the entire list of structures is freed. + * + * @param ai struct addrinfo to free + */ +void +lwip_freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + while (ai != NULL) { + next = ai->ai_next; + memp_free(MEMP_NETDB, ai); + ai = next; + } +} + +/** + * Translates the name of a service location (for example, a host name) and/or + * a service name and returns a set of socket addresses and associated + * information to be used in creating a socket with which to address the + * specified service. + * Memory for the result is allocated internally and must be freed by calling + * lwip_freeaddrinfo()! + * + * Due to a limitation in dns_gethostbyname, only the first address of a + * host is returned. + * Also, service names are not supported (only port numbers)! + * + * @param nodename descriptive name or address string of the host + * (may be NULL -> local address) + * @param servname port number as string of NULL + * @param hints structure containing input values that set socktype and protocol + * @param res pointer to a pointer where to store the result (set to NULL on failure) + * @return 0 on success, non-zero on failure + * + * @todo: implement AI_V4MAPPED, AI_ADDRCONFIG + */ +int +lwip_getaddrinfo(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + err_t err; + ip_addr_t addr; + struct addrinfo *ai; + struct sockaddr_storage *sa = NULL; + int port_nr = 0; + size_t total_size; + size_t namelen = 0; + int ai_family; + + if (res == NULL) { + return EAI_FAIL; + } + *res = NULL; + if ((nodename == NULL) && (servname == NULL)) { + return EAI_NONAME; + } + + if (hints != NULL) { + ai_family = hints->ai_family; + if ((ai_family != AF_UNSPEC) +#if LWIP_IPV4 + && (ai_family != AF_INET) +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + && (ai_family != AF_INET6) +#endif /* LWIP_IPV6 */ + ) { + return EAI_FAMILY; + } + } else { + ai_family = AF_UNSPEC; + } + + if (servname != NULL) { + /* service name specified: convert to port number + * @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */ + port_nr = atoi(servname); + if ((port_nr <= 0) || (port_nr > 0xffff)) { + return EAI_SERVICE; + } + } + + if (nodename != NULL) { + /* service location specified, try to resolve */ + if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) { + /* no DNS lookup, just parse for an address string */ + if (!ipaddr_aton(nodename, &addr)) { + return EAI_NONAME; + } +#if LWIP_IPV4 && LWIP_IPV6 + if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) || + (IP_IS_V4_VAL(addr) && ai_family == AF_INET6)) { + return EAI_NONAME; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + } else { +#if LWIP_IPV4 && LWIP_IPV6 + /* AF_UNSPEC: prefer IPv4 */ + u8_t type = NETCONN_DNS_IPV4_IPV6; + if (ai_family == AF_INET) { + type = NETCONN_DNS_IPV4; + } else if (ai_family == AF_INET6) { + type = NETCONN_DNS_IPV6; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + err = netconn_gethostbyname_addrtype(nodename, &addr, type); + if (err != ERR_OK) { + return EAI_FAIL; + } + } + } else { + /* service location specified, use loopback address */ + if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) { + ip_addr_set_any(ai_family == AF_INET6, &addr); + } else { + ip_addr_set_loopback(ai_family == AF_INET6, &addr); + } + } + + total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage); + if (nodename != NULL) { + namelen = strlen(nodename); + if (namelen > DNS_MAX_NAME_LENGTH) { + /* invalid name length */ + return EAI_FAIL; + } + LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size); + total_size += namelen + 1; + } + /* If this fails, please report to lwip-devel! :-) */ + LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!", + total_size <= NETDB_ELEM_SIZE); + ai = (struct addrinfo *)memp_malloc(MEMP_NETDB); + if (ai == NULL) { + return EAI_MEMORY; + } + memset(ai, 0, total_size); + /* cast through void* to get rid of alignment warnings */ + sa = (struct sockaddr_storage *)(void*)((u8_t*)ai + sizeof(struct addrinfo)); + if (IP_IS_V6_VAL(addr)) { +#if LWIP_IPV6 + struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa; + /* set up sockaddr */ + inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); + sa6->sin6_family = AF_INET6; + sa6->sin6_len = sizeof(struct sockaddr_in6); + sa6->sin6_port = lwip_htons((u16_t)port_nr); + ai->ai_family = AF_INET6; +#endif /* LWIP_IPV6 */ + } else { +#if LWIP_IPV4 + struct sockaddr_in *sa4 = (struct sockaddr_in*)sa; + /* set up sockaddr */ + inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); + sa4->sin_family = AF_INET; + sa4->sin_len = sizeof(struct sockaddr_in); + sa4->sin_port = lwip_htons((u16_t)port_nr); + ai->ai_family = AF_INET; +#endif /* LWIP_IPV4 */ + } + + /* set up addrinfo */ + if (hints != NULL) { + /* copy socktype & protocol from hints if specified */ + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + if (nodename != NULL) { + /* copy nodename to canonname if specified */ + ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage)); + MEMCPY(ai->ai_canonname, nodename, namelen); + ai->ai_canonname[namelen] = 0; + } + ai->ai_addrlen = sizeof(struct sockaddr_storage); + ai->ai_addr = (struct sockaddr*)sa; + + *res = ai; + + return 0; +} + +#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/components/net/lwip-2.0.3/src/api/netifapi.c b/components/net/lwip-2.0.3/src/api/netifapi.c new file mode 100644 index 0000000000..fef05a34dc --- /dev/null +++ b/components/net/lwip-2.0.3/src/api/netifapi.c @@ -0,0 +1,221 @@ +/** + * @file + * Network Interface Sequential API module + * + * @defgroup netifapi NETIF API + * @ingroup sequential_api + * Thread-safe functions to be called from non-TCPIP threads + * + * @defgroup netifapi_netif NETIF related + * @ingroup netifapi + * To be called from non-TCPIP threads + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netifapi.h" +#include "lwip/memp.h" +#include "lwip/priv/tcpip_priv.h" + +#define NETIFAPI_VAR_REF(name) API_VAR_REF(name) +#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) +#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM) +#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) + +/** + * Call netif_add() inside the tcpip_thread context. + */ +static err_t +netifapi_do_netif_add(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct netifapi_msg */ + struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; + + if (!netif_add( msg->netif, +#if LWIP_IPV4 + API_EXPR_REF(msg->msg.add.ipaddr), + API_EXPR_REF(msg->msg.add.netmask), + API_EXPR_REF(msg->msg.add.gw), +#endif /* LWIP_IPV4 */ + msg->msg.add.state, + msg->msg.add.init, + msg->msg.add.input)) { + return ERR_IF; + } else { + return ERR_OK; + } +} + +#if LWIP_IPV4 +/** + * Call netif_set_addr() inside the tcpip_thread context. + */ +static err_t +netifapi_do_netif_set_addr(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct netifapi_msg */ + struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; + + netif_set_addr( msg->netif, + API_EXPR_REF(msg->msg.add.ipaddr), + API_EXPR_REF(msg->msg.add.netmask), + API_EXPR_REF(msg->msg.add.gw)); + return ERR_OK; +} +#endif /* LWIP_IPV4 */ + +/** + * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the + * tcpip_thread context. + */ +static err_t +netifapi_do_netif_common(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct netifapi_msg */ + struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; + + if (msg->msg.common.errtfunc != NULL) { + return msg->msg.common.errtfunc(msg->netif); + } else { + msg->msg.common.voidfunc(msg->netif); + return ERR_OK; + } +} + +/** + * @ingroup netifapi_netif + * Call netif_add() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_add() + */ +err_t +netifapi_netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); + +#if LWIP_IPV4 + if (ipaddr == NULL) { + ipaddr = IP4_ADDR_ANY4; + } + if (netmask == NULL) { + netmask = IP4_ADDR_ANY4; + } + if (gw == NULL) { + gw = IP4_ADDR_ANY4; + } +#endif /* LWIP_IPV4 */ + + NETIFAPI_VAR_REF(msg).netif = netif; +#if LWIP_IPV4 + NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); + NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); + NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); +#endif /* LWIP_IPV4 */ + NETIFAPI_VAR_REF(msg).msg.add.state = state; + NETIFAPI_VAR_REF(msg).msg.add.init = init; + NETIFAPI_VAR_REF(msg).msg.add.input = input; + err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +} + +#if LWIP_IPV4 +/** + * @ingroup netifapi_netif + * Call netif_set_addr() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_set_addr() + */ +err_t +netifapi_netif_set_addr(struct netif *netif, + const ip4_addr_t *ipaddr, + const ip4_addr_t *netmask, + const ip4_addr_t *gw) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); + + if (ipaddr == NULL) { + ipaddr = IP4_ADDR_ANY4; + } + if (netmask == NULL) { + netmask = IP4_ADDR_ANY4; + } + if (gw == NULL) { + gw = IP4_ADDR_ANY4; + } + + NETIFAPI_VAR_REF(msg).netif = netif; + NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); + NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); + NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); + err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +} +#endif /* LWIP_IPV4 */ + +/** + * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe + * way by running that function inside the tcpip_thread context. + * + * @note use only for functions where there is only "netif" parameter. + */ +err_t +netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); + + NETIFAPI_VAR_REF(msg).netif = netif; + NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc; + NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc; + err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +} + +#endif /* LWIP_NETIF_API */ diff --git a/components/net/lwip-2.0.3/src/api/sockets.c b/components/net/lwip-2.0.3/src/api/sockets.c new file mode 100644 index 0000000000..d2be138be6 --- /dev/null +++ b/components/net/lwip-2.0.3/src/api/sockets.c @@ -0,0 +1,2851 @@ +/** + * @file + * Sockets BSD-Like API module + * + * @defgroup socket Socket API + * @ingroup sequential_api + * BSD-style socket API.\n + * Thread-safe, to be called from non-TCPIP threads only.\n + * Can be activated by defining @ref LWIP_SOCKET to 1.\n + * Header is in posix/sys/socket.h\b + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * Improved by Marc Boucher and David Haas + * + */ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sockets.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/inet.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/priv/tcpip_priv.h" +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +/* If the netconn API is not required publicly, then we include the necessary + files here to get the implementation */ +#if !LWIP_NETCONN +#undef LWIP_NETCONN +#define LWIP_NETCONN 1 +#include "api_msg.c" +#include "api_lib.c" +#include "netbuf.c" +#undef LWIP_NETCONN +#define LWIP_NETCONN 0 +#endif + +#if LWIP_IPV4 +#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ + (sin)->sin_len = sizeof(struct sockaddr_in); \ + (sin)->sin_family = AF_INET; \ + (sin)->sin_port = lwip_htons((port)); \ + inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ + memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0) +#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \ + inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \ + (port) = lwip_ntohs((sin)->sin_port); }while(0) +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ + (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ + (sin6)->sin6_family = AF_INET6; \ + (sin6)->sin6_port = lwip_htons((port)); \ + (sin6)->sin6_flowinfo = 0; \ + inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \ + (sin6)->sin6_scope_id = 0; }while(0) +#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \ + inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \ + (port) = lwip_ntohs((sin6)->sin6_port); }while(0) +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV4 && LWIP_IPV6 +static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port); + +#define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \ + ((namelen) == sizeof(struct sockaddr_in6))) +#define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \ + ((name)->sa_family == AF_INET6)) +#define SOCK_ADDR_TYPE_MATCH(name, sock) \ + ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \ + (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type)))) +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \ + if (IP_IS_V6(ipaddr)) { \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \ + } else { \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \ + } } while(0) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port)) +#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \ + (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6)) +#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ +#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6)) +#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6) +#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ + SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port) +#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */ +#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) +#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET) +#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ + SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port) +#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#endif /* LWIP_IPV6 */ + +#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \ + IS_SOCK_ADDR_TYPE_VALID(name)) +#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \ + SOCK_ADDR_TYPE_MATCH(name, sock)) +#define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0) + + +#define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if ((sock)->conn == NULL) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \ + if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0) + + +#define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name) +#if LWIP_MPU_COMPATIBLE +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \ + name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \ + if (name == NULL) { \ + sock_set_errno(sock, ENOMEM); \ + return -1; \ + } }while(0) +#else /* LWIP_MPU_COMPATIBLE */ +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) +#endif /* LWIP_MPU_COMPATIBLE */ + +#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE int +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val)) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(const int*)(optval)) +#else +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \ + s32_t loc = (val); \ + ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \ + ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U)) +#endif + +#define NUM_SOCKETS MEMP_NUM_NETCONN + +/** This is overridable for the rare case where more than 255 threads + * select on the same socket... + */ +#ifndef SELWAIT_T +#define SELWAIT_T u8_t +#endif + +#include +#ifdef SAL_USING_POSIX +#include +#endif + +/** Contains all internal pointers and states used for a socket */ +struct lwip_sock { + /** sockets currently are built on netconns, each socket has one netconn */ + struct netconn *conn; + /** data that was left from the previous read */ + void *lastdata; + /** offset in the data that was left from the previous read */ + u16_t lastoffset; + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ + s16_t rcvevent; + /** number of times data was ACKed (free send buffer), set by event_callback(), + tested by select */ + u16_t sendevent; + /** error happened for this socket, set by event_callback(), tested by select */ + u16_t errevent; + /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */ + u8_t err; + /** counter of how many threads are waiting for this socket using select */ + SELWAIT_T select_waiting; + +#ifdef SAL_USING_POSIX + rt_wqueue_t wait_head; +#endif +}; + +#if LWIP_NETCONN_SEM_PER_THREAD +#define SELECT_SEM_T sys_sem_t* +#define SELECT_SEM_PTR(sem) (sem) +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define SELECT_SEM_T sys_sem_t +#define SELECT_SEM_PTR(sem) (&(sem)) +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +/** Description for a task waiting in select */ +struct lwip_select_cb { + /** Pointer to the next waiting task */ + struct lwip_select_cb *next; + /** Pointer to the previous waiting task */ + struct lwip_select_cb *prev; + /** readset passed to select */ + fd_set *readset; + /** writeset passed to select */ + fd_set *writeset; + /** unimplemented: exceptset passed to select */ + fd_set *exceptset; + /** don't signal the same semaphore twice: set to 1 when signalled */ + int sem_signalled; + /** semaphore to wake up a task waiting for select */ + SELECT_SEM_T sem; +}; + +/** A struct sockaddr replacement that has the same alignment as sockaddr_in/ + * sockaddr_in6 if instantiated. + */ +union sockaddr_aligned { + struct sockaddr sa; +#if LWIP_IPV6 + struct sockaddr_in6 sin6; +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + struct sockaddr_in sin; +#endif /* LWIP_IPV4 */ +}; + +#if LWIP_IGMP +/* Define the number of IPv4 multicast memberships, default is one per socket */ +#ifndef LWIP_SOCKET_MAX_MEMBERSHIPS +#define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS +#endif + +/* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when + a socket is closed */ +struct lwip_socket_multicast_pair { + /** the socket */ + struct lwip_sock* sock; + /** the interface address */ + ip4_addr_t if_addr; + /** the group address */ + ip4_addr_t multi_addr; +}; + +struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS]; + +static int lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); +static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); +static void lwip_socket_drop_registered_memberships(int s); +#endif /* LWIP_IGMP */ + +/** The global array of available sockets */ +static struct lwip_sock sockets[NUM_SOCKETS]; +/** The global list of tasks waiting for select */ +static struct lwip_select_cb *select_cb_list; +/** This counter is increased from lwip_select when the list is changed + and checked in event_callback to see if it has changed. */ +static volatile int select_cb_ctr; + +#if LWIP_SOCKET_SET_ERRNO +#ifndef set_errno +#define set_errno(err) do { if (err) { errno = (err); } } while(0) +#endif +#else /* LWIP_SOCKET_SET_ERRNO */ +#define set_errno(err) +#endif /* LWIP_SOCKET_SET_ERRNO */ + +#define sock_set_errno(sk, e) do { \ + const int sockerr = (e); \ + sk->err = (u8_t)sockerr; \ + set_errno(sockerr); \ +} while (0) + +/* Forward declaration of some functions */ +static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); +#if !LWIP_TCPIP_CORE_LOCKING +static void lwip_getsockopt_callback(void *arg); +static void lwip_setsockopt_callback(void *arg); +#endif +static u8_t lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen); +static u8_t lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen); + +#if LWIP_IPV4 && LWIP_IPV6 +static void +sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port) +{ + if ((sockaddr->sa_family) == AF_INET6) { + SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, *port); + ipaddr->type = IPADDR_TYPE_V6; + } else { + SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, *port); + ipaddr->type = IPADDR_TYPE_V4; + } +} +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +/** LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ +void +lwip_socket_thread_init(void) +{ + netconn_thread_init(); +} + +/** LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ +void +lwip_socket_thread_cleanup(void) +{ + netconn_thread_cleanup(); +} + +/** + * Map a externally used socket index to the internal socket representation. + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +get_socket(int s) +{ + struct lwip_sock *sock; + + s -= LWIP_SOCKET_OFFSET; + + if ((s < 0) || (s >= NUM_SOCKETS)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s + LWIP_SOCKET_OFFSET)); + set_errno(EBADF); + return NULL; + } + + sock = &sockets[s]; + + if (!sock->conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET)); + set_errno(EBADF); + return NULL; + } + + return sock; +} + +/** + * Same as get_socket but doesn't set errno + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +tryget_socket(int s) +{ + s -= LWIP_SOCKET_OFFSET; + if ((s < 0) || (s >= NUM_SOCKETS)) { + return NULL; + } + if (!sockets[s].conn) { + return NULL; + } + return &sockets[s]; +} + +/** + * Same as tryget_socket but a global routine. + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +struct lwip_sock * +lwip_tryget_socket(int s) +{ + return tryget_socket(s); +} + +/** + * Allocate a new socket for a given netconn. + * + * @param newconn the netconn for which to allocate a socket + * @param accepted 1 if socket has been created by accept(), + * 0 if socket has been created by socket() + * @return the index of the new socket; -1 on error + */ +static int +alloc_socket(struct netconn *newconn, int accepted) +{ + int i; + SYS_ARCH_DECL_PROTECT(lev); + + /* allocate a new socket identifier */ + for (i = 0; i < NUM_SOCKETS; ++i) { + /* Protect socket array */ + SYS_ARCH_PROTECT(lev); + if (!sockets[i].conn && (sockets[i].select_waiting == 0)) { + sockets[i].conn = newconn; + /* The socket is not yet known to anyone, so no need to protect + after having marked it as used. */ + SYS_ARCH_UNPROTECT(lev); + sockets[i].lastdata = NULL; + sockets[i].lastoffset = 0; + sockets[i].rcvevent = 0; + /* TCP sendbuf is empty, but the socket is not yet writable until connected + * (unless it has been created by accept()). */ + sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); + sockets[i].errevent = 0; + sockets[i].err = 0; +#ifdef SAL_USING_POSIX + rt_wqueue_init(&sockets[i].wait_head); +#endif + return i + LWIP_SOCKET_OFFSET; + } + SYS_ARCH_UNPROTECT(lev); + } + return -1; +} + +/** Free a socket. The socket's netconn must have been + * delete before! + * + * @param sock the socket to free + * @param is_tcp != 0 for TCP sockets, used to free lastdata + */ +static void +free_socket(struct lwip_sock *sock, int is_tcp) +{ + void *lastdata; + + lastdata = sock->lastdata; + sock->lastdata = NULL; + sock->lastoffset = 0; + sock->err = 0; + + /* Protect socket array */ + SYS_ARCH_SET(sock->conn, NULL); + /* don't use 'sock' after this line, as another task might have allocated it */ + + if (lastdata != NULL) { + if (is_tcp) { + pbuf_free((struct pbuf *)lastdata); + } else { + netbuf_delete((struct netbuf *)lastdata); + } + } +} + +/* Below this, the well-known socket functions are implemented. + * Use google.com or opengroup.org to get a good description :-) + * + * Exceptions are documented! + */ + +int +lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct lwip_sock *sock, *nsock; + struct netconn *newconn; + ip_addr_t naddr; + u16_t port = 0; + int newsock; + err_t err; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); + set_errno(EWOULDBLOCK); + return -1; + } + + /* wait for a new connection */ + err = netconn_accept(sock->conn, &newconn); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + } else if (err == ERR_CLSD) { + sock_set_errno(sock, EINVAL); + } else { + sock_set_errno(sock, err_to_errno(err)); + } + return -1; + } + LWIP_ASSERT("newconn != NULL", newconn != NULL); + + newsock = alloc_socket(newconn, 1); + if (newsock == -1) { + netconn_delete(newconn); + sock_set_errno(sock, ENFILE); + return -1; + } + LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); + LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); + nsock = &sockets[newsock - LWIP_SOCKET_OFFSET]; + + /* See event_callback: If data comes in right away after an accept, even + * though the server task might not have created a new socket yet. + * In that case, newconn->socket is counted down (newconn->socket--), + * so nsock->rcvevent is >= 1 here! + */ + SYS_ARCH_PROTECT(lev); + nsock->rcvevent += (s16_t)(-1 - newconn->socket); + newconn->socket = newsock; + SYS_ARCH_UNPROTECT(lev); + + /* Note that POSIX only requires us to check addr is non-NULL. addrlen must + * not be NULL if addr is valid. + */ + if (addr != NULL) { + union sockaddr_aligned tempaddr; + /* get the IP address and port of the remote host */ + err = netconn_peer(newconn, &naddr, &port); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); + netconn_delete(newconn); + free_socket(nsock, 1); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); + + IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); + if (*addrlen > tempaddr.sa.sa_len) { + *addrlen = tempaddr.sa.sa_len; + } + MEMCPY(addr, &tempaddr, *addrlen); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); + ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); + } else { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock)); + } + + sock_set_errno(sock, 0); + return newsock; +} + +int +lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + ip_addr_t local_addr; + u16_t local_port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(namelen); + + SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr)); + IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + err = netconn_bind(sock->conn, &local_addr, local_port); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_close(int s) +{ + struct lwip_sock *sock; + int is_tcp = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP; + } else { + LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL); + } + +#if LWIP_IGMP + /* drop all possibly joined IGMP memberships */ + lwip_socket_drop_registered_memberships(s); +#endif /* LWIP_IGMP */ + + err = netconn_delete(sock->conn); + if (err != ERR_OK) { + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + free_socket(sock, is_tcp); + set_errno(0); + return 0; +} + +int +lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + LWIP_UNUSED_ARG(namelen); + if (name->sa_family == AF_UNSPEC) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); + err = netconn_disconnect(sock->conn); + } else { + ip_addr_t remote_addr; + u16_t remote_port; + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port)); + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&remote_addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr)); + IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + err = netconn_connect(sock->conn, &remote_addr, remote_port); + } + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +/** + * Set a socket into listen mode. + * The socket may not have been used for another connection previously. + * + * @param s the socket to set to listening mode + * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) + * @return 0 on success, non-zero on failure + */ +int +lwip_listen(int s, int backlog) +{ + struct lwip_sock *sock; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* limit the "backlog" parameter to fit in an u8_t */ + backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff); + + err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + struct lwip_sock *sock; + void *buf = NULL; + struct pbuf *p; + u16_t buflen, copylen; + int off = 0; + u8_t done = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + do { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); + /* Check if there is data left from the last recv operation. */ + if (sock->lastdata) { + buf = sock->lastdata; + } else { + /* If this is non-blocking call, then check first */ + if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) && + (sock->rcvevent <= 0)) { + if (off > 0) { + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); + set_errno(EWOULDBLOCK); + return -1; + } + + /* No data was left from the previous operation, so we try to get + some from the network. */ + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf); + } else { + err = netconn_recv(sock->conn, (struct netbuf **)&buf); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n", + err, buf)); + + if (err != ERR_OK) { + if (off > 0) { + if (err == ERR_CLSD) { + /* closed but already received data, ensure select gets the FIN, too */ + event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0); + } + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + /* We should really do some error checking here. */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n", + s, lwip_strerr(err))); + sock_set_errno(sock, err_to_errno(err)); + if (err == ERR_CLSD) { + return 0; + } else { + return -1; + } + } + LWIP_ASSERT("buf != NULL", buf != NULL); + sock->lastdata = buf; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + p = (struct pbuf *)buf; + } else { + p = ((struct netbuf *)buf)->p; + } + buflen = p->tot_len; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n", + buflen, len, off, sock->lastoffset)); + + buflen -= sock->lastoffset; + + if (len > buflen) { + copylen = buflen; + } else { + copylen = (u16_t)len; + } + + /* copy the contents of the received buffer into + the supplied memory pointer mem */ + pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset); + + off += copylen; + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); + len -= copylen; + if ((len <= 0) || + (p->flags & PBUF_FLAG_PUSH) || + (sock->rcvevent <= 0) || + ((flags & MSG_PEEK) != 0)) { + done = 1; + } + } else { + done = 1; + } + + /* Check to see from where the data was.*/ + if (done) { +#if !SOCKETS_DEBUG + if (from && fromlen) +#endif /* !SOCKETS_DEBUG */ + { + u16_t port; + ip_addr_t tmpaddr; + ip_addr_t *fromaddr; + union sockaddr_aligned saddr; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + fromaddr = &tmpaddr; + netconn_getaddr(sock->conn, fromaddr, &port, 0); + } else { + port = netbuf_fromport((struct netbuf *)buf); + fromaddr = netbuf_fromaddr((struct netbuf *)buf); + } + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ + if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) { + ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr)); + IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); + ip_addr_debug_print(SOCKETS_DEBUG, fromaddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); +#if SOCKETS_DEBUG + if (from && fromlen) +#endif /* SOCKETS_DEBUG */ + { + if (*fromlen > saddr.sa.sa_len) { + *fromlen = saddr.sa.sa_len; + } + MEMCPY(from, &saddr, *fromlen); + } + } + } + + /* If we don't peek the incoming message... */ + if ((flags & MSG_PEEK) == 0) { + /* If this is a TCP socket, check if there is data left in the + buffer. If so, it should be saved in the sock structure for next + time around. */ + if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) { + sock->lastdata = buf; + sock->lastoffset += copylen; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); + } else { + sock->lastdata = NULL; + sock->lastoffset = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + pbuf_free((struct pbuf *)buf); + } else { + netbuf_delete((struct netbuf *)buf); + } + buf = NULL; + } + } + } while (!done); + + sock_set_errno(sock, 0); + return off; +} + +int +lwip_read(int s, void *mem, size_t len) +{ + return lwip_recvfrom(s, mem, len, 0, NULL, NULL); +} + +int +lwip_recv(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom(s, mem, len, flags, NULL, NULL); +} + +int +lwip_send(int s, const void *data, size_t size, int flags) +{ + struct lwip_sock *sock; + err_t err; + u8_t write_flags; + size_t written; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", + s, data, size, flags)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { +#if (LWIP_UDP || LWIP_RAW) + return lwip_sendto(s, data, size, flags, NULL, 0); +#else /* (LWIP_UDP || LWIP_RAW) */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + written = 0; + err = netconn_write_partly(sock->conn, data, size, write_flags, &written); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written)); + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? (int)written : -1); +} + +int +lwip_sendmsg(int s, const struct msghdr *msg, int flags) +{ + struct lwip_sock *sock; + int i; +#if LWIP_TCP + u8_t write_flags; + size_t written; +#endif + int size = 0; + err_t err = ERR_OK; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + LWIP_ERROR("lwip_sendmsg: invalid msghdr", msg != NULL, + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + LWIP_UNUSED_ARG(msg->msg_control); + LWIP_UNUSED_ARG(msg->msg_controllen); + LWIP_UNUSED_ARG(msg->msg_flags); + LWIP_ERROR("lwip_sendmsg: invalid msghdr iov", (msg->msg_iov != NULL && msg->msg_iovlen != 0), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +#if LWIP_TCP + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + + for (i = 0; i < msg->msg_iovlen; i++) { + u8_t apiflags = write_flags; + if (i + 1 < msg->msg_iovlen) { + apiflags |= NETCONN_MORE; + } + written = 0; + err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written); + if (err == ERR_OK) { + size += written; + /* check that the entire IO vector was accepected, if not return a partial write */ + if (written != msg->msg_iov[i].iov_len) + break; + } + /* none of this IO vector was accepted, but previous was, return partial write and conceal ERR_WOULDBLOCK */ + else if (err == ERR_WOULDBLOCK && size > 0) { + err = ERR_OK; + /* let ERR_WOULDBLOCK persist on the netconn since we are returning ERR_OK */ + break; + } else { + size = -1; + break; + } + } + sock_set_errno(sock, err_to_errno(err)); + return size; +#else /* LWIP_TCP */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + /* else, UDP and RAW NETCONNs */ +#if LWIP_UDP || LWIP_RAW + { + struct netbuf *chain_buf; + + LWIP_UNUSED_ARG(flags); + LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) || + IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) , + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + /* initialize chain buffer with destination */ + chain_buf = netbuf_new(); + if (!chain_buf) { + sock_set_errno(sock, err_to_errno(ERR_MEM)); + return -1; + } + if (msg->msg_name) { + u16_t remote_port; + SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port); + netbuf_fromport(chain_buf) = remote_port; + } +#if LWIP_NETIF_TX_SINGLE_PBUF + for (i = 0; i < msg->msg_iovlen; i++) { + size += msg->msg_iov[i].iov_len; + } + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) { + err = ERR_MEM; + } else { + /* flatten the IO vectors */ + size_t offset = 0; + for (i = 0; i < msg->msg_iovlen; i++) { + MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); + offset += msg->msg_iov[i].iov_len; + } +#if LWIP_CHECKSUM_ON_COPY + { + /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */ + u16_t chksum = ~inet_chksum_pbuf(chain_buf->p); + netbuf_set_chksum(chain_buf, chksum); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + err = ERR_OK; + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain + manually to avoid having to allocate, chain, and delete a netbuf for each iov */ + for (i = 0; i < msg->msg_iovlen; i++) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (p == NULL) { + err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */ + break; + } + p->payload = msg->msg_iov[i].iov_base; + LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF); + p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len; + /* netbuf empty, add new pbuf */ + if (chain_buf->p == NULL) { + chain_buf->p = chain_buf->ptr = p; + /* add pbuf to existing pbuf chain */ + } else { + pbuf_cat(chain_buf->p, p); + } + } + /* save size of total chain */ + if (err == ERR_OK) { + size = netbuf_len(chain_buf); + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + if (err == ERR_OK) { +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&chain_buf->addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr)); + IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + /* send the data */ + err = netconn_send(sock->conn, chain_buf); + } + + /* deallocated the buffer */ + netbuf_delete(chain_buf); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? size : -1); + } +#else /* LWIP_UDP || LWIP_RAW */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_UDP || LWIP_RAW */ +} + +int +lwip_sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + struct lwip_sock *sock; + err_t err; + u16_t short_size; + u16_t remote_port; + struct netbuf buf; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +#if LWIP_TCP + return lwip_send(s, data, size, flags); +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(flags); + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + + /* @todo: split into multiple sendto's? */ + LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || + (IS_SOCK_ADDR_LEN_VALID(tolen) && + IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(tolen); + + /* initialize a buffer */ + buf.p = buf.ptr = NULL; +#if LWIP_CHECKSUM_ON_COPY + buf.flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + if (to) { + SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); + } else { + remote_port = 0; + ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr); + } + netbuf_fromport(&buf) = remote_port; + + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", + s, data, short_size, flags)); + ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); + + /* make the buffer point to the data that should be sent */ +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(&buf, short_size) == NULL) { + err = ERR_MEM; + } else { +#if LWIP_CHECKSUM_ON_COPY + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { + u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); + netbuf_set_chksum(&buf, chksum); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + MEMCPY(buf.p->payload, data, short_size); + } + err = ERR_OK; + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + err = netbuf_ref(&buf, data, short_size); +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (err == ERR_OK) { +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&buf.addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr)); + IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + /* send the data */ + err = netconn_send(sock->conn, &buf); + } + + /* deallocated the buffer */ + netbuf_free(&buf); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? short_size : -1); +} + +int +lwip_socket(int domain, int type, int protocol) +{ + struct netconn *conn; + int i; + + LWIP_UNUSED_ARG(domain); /* @todo: check this */ + + /* create a netconn */ + switch (type) { + case SOCK_RAW: + conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), + (u8_t)protocol, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, + ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) , + event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_STREAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", + domain, type, protocol)); + set_errno(EINVAL); + return -1; + } + + if (!conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); + set_errno(ENOBUFS); + return -1; + } + + i = alloc_socket(conn, 0); + + if (i == -1) { + netconn_delete(conn); + set_errno(ENFILE); + return -1; + } + conn->socket = i; + LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); + set_errno(0); + return i; +} + +int +lwip_write(int s, const void *data, size_t size) +{ + return lwip_send(s, data, size, 0); +} + +int +lwip_writev(int s, const struct iovec *iov, int iovcnt) +{ + struct msghdr msg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + /* Hack: we have to cast via number to cast from 'const' pointer to non-const. + Blame the opengroup standard for this inconsistency. */ + msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); + msg.msg_iovlen = iovcnt; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return lwip_sendmsg(s, &msg, 0); +} + +/** + * Go through the readset and writeset lists and see which socket of the sockets + * set in the sets has events. On return, readset, writeset and exceptset have + * the sockets enabled that had events. + * + * @param maxfdp1 the highest socket index in the sets + * @param readset_in set of sockets to check for read events + * @param writeset_in set of sockets to check for write events + * @param exceptset_in set of sockets to check for error events + * @param readset_out set of sockets that had read events + * @param writeset_out set of sockets that had write events + * @param exceptset_out set os sockets that had error events + * @return number of sockets that had events (read/write/exception) (>= 0) + */ +static int +lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, + fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) +{ + int i, nready = 0; + fd_set lreadset, lwriteset, lexceptset; + struct lwip_sock *sock; + SYS_ARCH_DECL_PROTECT(lev); + + FD_ZERO(&lreadset); + FD_ZERO(&lwriteset); + FD_ZERO(&lexceptset); + + /* Go through each socket in each list to count number of sockets which + currently match */ + for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { + /* if this FD is not in the set, continue */ + if (!(readset_in && FD_ISSET(i, readset_in)) && + !(writeset_in && FD_ISSET(i, writeset_in)) && + !(exceptset_in && FD_ISSET(i, exceptset_in))) { + continue; + } + /* First get the socket's status (protected)... */ + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + void* lastdata = sock->lastdata; + s16_t rcvevent = sock->rcvevent; + u16_t sendevent = sock->sendevent; + u16_t errevent = sock->errevent; + SYS_ARCH_UNPROTECT(lev); + + /* ... then examine it: */ + /* See if netconn of this socket is ready for read */ + if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { + FD_SET(i, &lreadset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); + nready++; + } + /* See if netconn of this socket is ready for write */ + if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { + FD_SET(i, &lwriteset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); + nready++; + } + /* See if netconn of this socket had an error */ + if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { + FD_SET(i, &lexceptset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); + nready++; + } + } else { + SYS_ARCH_UNPROTECT(lev); + /* continue on to next FD in list */ + } + } + /* copy local sets to the ones provided as arguments */ + *readset_out = lreadset; + *writeset_out = lwriteset; + *exceptset_out = lexceptset; + + LWIP_ASSERT("nready >= 0", nready >= 0); + return nready; +} + +int +lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) +{ + u32_t waitres = 0; + int nready; + fd_set lreadset, lwriteset, lexceptset; + u32_t msectimeout; + struct lwip_select_cb select_cb; + int i; + int maxfdp2; +#if LWIP_NETCONN_SEM_PER_THREAD + int waited = 0; +#endif + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", + maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, + timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, + timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); + + /* Go through each socket in each list to count number of sockets which + currently match */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + + /* If we don't have any current events, then suspend if we are supposed to */ + if (!nready) { + if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* None ready: add our semaphore to list: + We don't actually need any dynamic memory. Our entry on the + list is only valid while we are in this function, so it's ok + to use local variables. */ + + select_cb.next = NULL; + select_cb.prev = NULL; + select_cb.readset = readset; + select_cb.writeset = writeset; + select_cb.exceptset = exceptset; + select_cb.sem_signalled = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) { + /* failed to create semaphore */ + set_errno(ENOMEM); + return -1; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + /* Protect the select_cb_list */ + SYS_ARCH_PROTECT(lev); + + /* Put this select_cb on top of list */ + select_cb.next = select_cb_list; + if (select_cb_list != NULL) { + select_cb_list->prev = &select_cb; + } + select_cb_list = &select_cb; + /* Increasing this counter tells event_callback that the list has changed. */ + select_cb_ctr++; + + /* Now we can safely unprotect */ + SYS_ARCH_UNPROTECT(lev); + + /* Increase select_waiting for each socket we are interested in */ + maxfdp2 = maxfdp1; + for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + sock->select_waiting++; + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + } else { + /* Not a valid socket */ + nready = -1; + maxfdp2 = i; + SYS_ARCH_UNPROTECT(lev); + break; + } + SYS_ARCH_UNPROTECT(lev); + } + } + + if (nready >= 0) { + /* Call lwip_selscan again: there could have been events between + the last scan (without us on the list) and putting us on the list! */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + if (!nready) { + /* Still none ready, just wait to be woken */ + if (timeout == 0) { + /* Wait forever */ + msectimeout = 0; + } else { + msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); + if (msectimeout == 0) { + /* Wait 1ms at least (0 means wait forever) */ + msectimeout = 1; + } + } + + waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout); +#if LWIP_NETCONN_SEM_PER_THREAD + waited = 1; +#endif + } + } + + /* Decrease select_waiting for each socket we are interested in */ + for (i = LWIP_SOCKET_OFFSET; i < maxfdp2; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + /* for now, handle select_waiting==0... */ + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + if (sock->select_waiting > 0) { + sock->select_waiting--; + } + } else { + /* Not a valid socket */ + nready = -1; + } + SYS_ARCH_UNPROTECT(lev); + } + } + /* Take us off the list */ + SYS_ARCH_PROTECT(lev); + if (select_cb.next != NULL) { + select_cb.next->prev = select_cb.prev; + } + if (select_cb_list == &select_cb) { + LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); + select_cb_list = select_cb.next; + } else { + LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); + select_cb.prev->next = select_cb.next; + } + /* Increasing this counter tells event_callback that the list has changed. */ + select_cb_ctr++; + SYS_ARCH_UNPROTECT(lev); + +#if LWIP_NETCONN_SEM_PER_THREAD + if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) { + /* don't leave the thread-local semaphore signalled */ + sys_arch_sem_wait(select_cb.sem, 1); + } +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + sys_sem_free(&select_cb.sem); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + if (nready < 0) { + /* This happens when a socket got closed while waiting */ + set_errno(EBADF); + return -1; + } + + if (waitres == SYS_ARCH_TIMEOUT) { + /* Timeout */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* See what's set */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); +return_copy_fdsets: + set_errno(0); + if (readset) { + *readset = lreadset; + } + if (writeset) { + *writeset = lwriteset; + } + if (exceptset) { + *exceptset = lexceptset; + } + return nready; +} + +/** + * Callback registered in the netconn layer for each socket-netconn. + * Processes recvevent (data available) and wakes up tasks waiting for select. + */ +static void +event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) +{ + int s; + struct lwip_sock *sock; + struct lwip_select_cb *scb; + int last_select_cb_ctr; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(len); + + /* Get socket */ + if (conn) { + s = conn->socket; + if (s < 0) { + /* Data comes in right away after an accept, even though + * the server task might not have created a new socket yet. + * Just count down (or up) if that's the case and we + * will use the data later. Note that only receive events + * can happen before the new socket is set up. */ + SYS_ARCH_PROTECT(lev); + if (conn->socket < 0) { + if (evt == NETCONN_EVT_RCVPLUS) { + conn->socket--; + } + SYS_ARCH_UNPROTECT(lev); + return; + } + s = conn->socket; + SYS_ARCH_UNPROTECT(lev); + } + + sock = get_socket(s); + if (!sock) { + return; + } + } else { + return; + } + + SYS_ARCH_PROTECT(lev); + /* Set event as required */ + switch (evt) { + case NETCONN_EVT_RCVPLUS: + sock->rcvevent++; + break; + case NETCONN_EVT_RCVMINUS: + sock->rcvevent--; + break; + case NETCONN_EVT_SENDPLUS: + sock->sendevent = 1; + break; + case NETCONN_EVT_SENDMINUS: + sock->sendevent = 0; + break; + case NETCONN_EVT_ERROR: + sock->errevent = 1; + break; + default: + LWIP_ASSERT("unknown event", 0); + break; + } + + if (sock->select_waiting == 0) { + /* noone is waiting for this socket, no need to check select_cb_list */ + SYS_ARCH_UNPROTECT(lev); + return; + } + + /* Now decide if anyone is waiting for this socket */ + /* NOTE: This code goes through the select_cb_list list multiple times + ONLY IF a select was actually waiting. We go through the list the number + of waiting select calls + 1. This list is expected to be small. */ + + /* At this point, SYS_ARCH is still protected! */ +again: + for (scb = select_cb_list; scb != NULL; scb = scb->next) { + /* remember the state of select_cb_list to detect changes */ + last_select_cb_ctr = select_cb_ctr; + if (scb->sem_signalled == 0) { + /* semaphore not signalled yet */ + int do_signal = 0; + /* Test this select call for our socket */ + if (sock->rcvevent > 0) { + if (scb->readset && FD_ISSET(s, scb->readset)) { + do_signal = 1; + } + } + if (sock->sendevent != 0) { + if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { + do_signal = 1; + } + } + if (sock->errevent != 0) { + if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { + do_signal = 1; + } + } + if (do_signal) { + scb->sem_signalled = 1; + /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might + lead to the select thread taking itself off the list, invalidating the semaphore. */ + sys_sem_signal(SELECT_SEM_PTR(scb->sem)); + } + } + /* unlock interrupts with each step */ + SYS_ARCH_UNPROTECT(lev); + /* this makes sure interrupt protection time is short */ + SYS_ARCH_PROTECT(lev); + if (last_select_cb_ctr != select_cb_ctr) { + /* someone has changed select_cb_list, restart at the beginning */ + goto again; + } + } + SYS_ARCH_UNPROTECT(lev); +} + +/** + * Close one end of a full-duplex connection. + */ +int +lwip_shutdown(int s, int how) +{ + struct lwip_sock *sock; + err_t err; + u8_t shut_rx = 0, shut_tx = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + } else { + sock_set_errno(sock, ENOTCONN); + return -1; + } + + if (how == SHUT_RD) { + shut_rx = 1; + } else if (how == SHUT_WR) { + shut_tx = 1; + } else if (how == SHUT_RDWR) { + shut_rx = 1; + shut_tx = 1; + } else { + sock_set_errno(sock, EINVAL); + return -1; + } + err = netconn_shutdown(sock->conn, shut_rx, shut_tx); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? 0 : -1); +} + +static int +lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) +{ + struct lwip_sock *sock; + union sockaddr_aligned saddr; + ip_addr_t naddr; + u16_t port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* get the IP address and port */ + err = netconn_getaddr(sock->conn, &naddr, &port, local); + if (err != ERR_OK) { + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ + if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && + IP_IS_V4_VAL(naddr)) { + ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&naddr), ip_2_ip4(&naddr)); + IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); + + if (*namelen > saddr.sa.sa_len) { + *namelen = saddr.sa.sa_len; + } + MEMCPY(name, &saddr, *namelen); + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 0); +} + +int +lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 1); +} + +int +lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if ((NULL == optval) || (NULL == optlen)) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_getsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen; +#if !LWIP_MPU_COMPATIBLE + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval; +#endif /* !LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + err = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + if (err != ERR_OK) { + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* write back optlen and optval */ + *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen; +#if LWIP_MPU_COMPATIBLE + MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen); +#endif /* LWIP_MPU_COMPATIBLE */ + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_getsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_getsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_getsockopt_impl(data->s, data->level, data->optname, +#if LWIP_MPU_COMPATIBLE + data->optval, +#else /* LWIP_MPU_COMPATIBLE */ + data->optval.p, +#endif /* LWIP_MPU_COMPATIBLE */ + &data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_getsockopt_impl: the actual implementation of getsockopt: + * same argument as lwip_getsockopt, either called directly or through callback + */ +static u8_t +lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + +#if LWIP_TCP + case SO_ACCEPTCONN: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) { + return ENOPROTOOPT; + } + if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) { + *(int*)optval = 1; + } else { + *(int*)optval = 0; + } + break; +#endif /* LWIP_TCP */ + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; + + case SO_TYPE: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { + case NETCONN_RAW: + *(int*)optval = SOCK_RAW; + break; + case NETCONN_TCP: + *(int*)optval = SOCK_STREAM; + break; + case NETCONN_UDP: + *(int*)optval = SOCK_DGRAM; + break; + default: /* unrecognized socket type */ + *(int*)optval = netconn_type(sock->conn); + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); + } /* switch (netconn_type(sock->conn)) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); + break; + + case SO_ERROR: + LWIP_SOCKOPT_CHECK_OPTLEN(*optlen, int); + /* only overwrite ERR_OK or temporary errors */ + if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) { + sock_set_errno(sock, err_to_errno(sock->conn->last_err)); + } + *(int *)optval = (sock->err == 0xFF ? (int)-1 : (int)sock->err); + sock->err = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + *(int *)optval = netconn_get_recvbufsize(sock->conn); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + case SO_LINGER: + { + s16_t conn_linger; + struct linger* linger = (struct linger*)optval; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, struct linger); + conn_linger = sock->conn->linger; + if (conn_linger >= 0) { + linger->l_onoff = 1; + linger->l_linger = (int)conn_linger; + } else { + linger->l_onoff = 0; + linger->l_linger = 0; + } + } + break; +#endif /* LWIP_SO_LINGER */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; + break; +#endif /* LWIP_UDP*/ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->tos; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", + s, *(int *)optval)); + break; +#if LWIP_MULTICAST_TX_OPTIONS + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + *(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_MULTICAST_IF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in_addr); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + inet_addr_from_ip4addr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp)); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", + s, *(u32_t *)optval)); + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { + *(u8_t*)optval = 1; + } else { + *(u8_t*)optval = 0; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP); + if (sock->conn->pcb.tcp->state == LISTEN) { + return EINVAL; + } + switch (optname) { + case TCP_NODELAY: + *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", + s, (*(int*)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPINTVL: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPCNT: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + *(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n", + s, *(int *)optval)); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW); + if (sock->conn->pcb.raw->chksum_reqd == 0) { + *(int *)optval = -1; + } else { + *(int *)optval = sock->conn->pcb.raw->chksum_offset; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n", + s, (*(int*)optval)) ); + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if (NULL == optval) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_setsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen; +#if LWIP_MPU_COMPATIBLE + MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen); +#else /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval; +#endif /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + err = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + if (err != ERR_OK) { + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_setsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_setsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_setsockopt_impl(data->s, data->level, data->optname, +#if LWIP_MPU_COMPATIBLE + data->optval, +#else /* LWIP_MPU_COMPATIBLE */ + data->optval.pc, +#endif /* LWIP_MPU_COMPATIBLE */ + data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_setsockopt_impl: the actual implementation of setsockopt: + * same argument as lwip_setsockopt, either called directly or through callback + */ +static u8_t +lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* SO_ACCEPTCONN is get-only */ + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + if (*(const int*)optval) { + ip_set_option(sock->conn->pcb.ip, optname); + } else { + ip_reset_option(sock->conn->pcb.ip, optname); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", + s, optname, (*(const int*)optval?"on":"off"))); + break; + + /* SO_TYPE is get-only */ + /* SO_ERROR is get-only */ + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_recvtimeout(sock->conn, (int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int); + netconn_set_recvbufsize(sock->conn, *(const int*)optval); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + case SO_LINGER: + { + const struct linger* linger = (const struct linger*)optval; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, struct linger); + if (linger->l_onoff) { + int lingersec = linger->l_linger; + if (lingersec < 0) { + return EINVAL; + } + if (lingersec > 0xFFFF) { + lingersec = 0xFFFF; + } + sock->conn->linger = (s16_t)lingersec; + } else { + sock->conn->linger = -1; + } + } + break; +#endif /* LWIP_SO_LINGER */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + if (*(const int*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); + } + break; +#endif /* LWIP_UDP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->ttl = (u8_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", + s, sock->conn->pcb.ip->ttl)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->tos = (u8_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", + s, sock->conn->pcb.ip->tos)); + break; +#if LWIP_MULTICAST_TX_OPTIONS + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval)); + break; + case IP_MULTICAST_IF: + { + ip4_addr_t if_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP); + inet_addr_to_ip4addr(&if_addr, (const struct in_addr*)optval); + udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr); + } + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + if (*(const u8_t*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); + } + break; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ +#if LWIP_IGMP + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + { + /* If this is a TCP or a RAW socket, ignore these options. */ + /* @todo: assign membership to this socket so that it is dropped when closing the socket */ + err_t igmp_err; + const struct ip_mreq *imr = (const struct ip_mreq *)optval; + ip4_addr_t if_addr; + ip4_addr_t multi_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP); + inet_addr_to_ip4addr(&if_addr, &imr->imr_interface); + inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr); + if (optname == IP_ADD_MEMBERSHIP) { + if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) { + /* cannot track membership (out of memory) */ + err = ENOMEM; + igmp_err = ERR_OK; + } else { + igmp_err = igmp_joingroup(&if_addr, &multi_addr); + } + } else { + igmp_err = igmp_leavegroup(&if_addr, &multi_addr); + lwip_socket_unregister_membership(s, &if_addr, &multi_addr); + } + if (igmp_err != ERR_OK) { + err = EADDRNOTAVAIL; + } + } + break; +#endif /* LWIP_IGMP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); + if (sock->conn->pcb.tcp->state == LISTEN) { + return EINVAL; + } + switch (optname) { + case TCP_NODELAY: + if (*(const int*)optval) { + tcp_nagle_disable(sock->conn->pcb.tcp); + } else { + tcp_nagle_enable(sock->conn->pcb.tcp); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", + s, (*(const int *)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + case TCP_KEEPINTVL: + sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_intvl)); + break; + case TCP_KEEPCNT: + sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_cnt)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP*/ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); + if (*(const int*)optval) { + netconn_set_ipv6only(sock->conn, 1); + } else { + netconn_set_ipv6only(sock->conn, 0); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n", + s, (netconn_get_ipv6only(sock->conn) ? 1 : 0))); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_tx = 8; + } else { + sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(const int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", + s, (*(const int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_rx = 8; + } else { + sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(const int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", + s, (*(const int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + /* It should not be possible to disable the checksum generation with ICMPv6 + * as per RFC 3542 chapter 3.1 */ + if(sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) { + return EINVAL; + } + + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW); + if (*(const int *)optval < 0) { + sock->conn->pcb.raw->chksum_reqd = 0; + } else if (*(const int *)optval & 1) { + /* Per RFC3542, odd offsets are not allowed */ + return EINVAL; + } else { + sock->conn->pcb.raw->chksum_reqd = 1; + sock->conn->pcb.raw->chksum_offset = (u16_t)*(const int *)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n", + s, sock->conn->pcb.raw->chksum_reqd)); + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_ioctl(int s, long cmd, void *argp) +{ + struct lwip_sock *sock = get_socket(s); + u8_t val; +#if LWIP_SO_RCVBUF + u16_t buflen = 0; + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + if (!sock) { + return -1; + } + + switch (cmd) { +#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE + case FIONREAD: + if (!argp) { + sock_set_errno(sock, EINVAL); + return -1; + } +#if LWIP_FIONREAD_LINUXMODE + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + struct pbuf *p; + if (sock->lastdata) { + p = ((struct netbuf *)sock->lastdata)->p; + *((int*)argp) = p->tot_len - sock->lastoffset; + } else { + struct netbuf *rxbuf; + err_t err; + if (sock->rcvevent <= 0) { + *((int*)argp) = 0; + } else { + err = netconn_recv(sock->conn, &rxbuf); + if (err != ERR_OK) { + *((int*)argp) = 0; + } else { + sock->lastdata = rxbuf; + sock->lastoffset = 0; + *((int*)argp) = rxbuf->p->tot_len; + } + } + } + return 0; + } +#endif /* LWIP_FIONREAD_LINUXMODE */ + +#if LWIP_SO_RCVBUF + /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ + SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); + if (recv_avail < 0) { + recv_avail = 0; + } + *((int*)argp) = recv_avail; + + /* Check if there is data left from the last recv operation. /maq 041215 */ + if (sock->lastdata) { + struct pbuf *p = (struct pbuf *)sock->lastdata; + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + p = ((struct netbuf *)p)->p; + } + buflen = p->tot_len; + buflen -= sock->lastoffset; + + *((int*)argp) += buflen; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); + sock_set_errno(sock, 0); + return 0; +#else /* LWIP_SO_RCVBUF */ + break; +#endif /* LWIP_SO_RCVBUF */ +#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + + case (long)FIONBIO: + val = 0; + if (argp && *(u32_t*)argp) { + val = 1; + } + netconn_set_nonblocking(sock->conn, val); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); + sock_set_errno(sock, 0); + return 0; + + default: + break; + } /* switch (cmd) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + return -1; +} + +/** A minimal implementation of fcntl. + * Currently only the commands F_GETFL and F_SETFL are implemented. + * Only the flag O_NONBLOCK is implemented. + */ +int +lwip_fcntl(int s, int cmd, int val) +{ + struct lwip_sock *sock = get_socket(s); + int ret = -1; + + if (!sock) { + return -1; + } + + switch (cmd) { + case F_GETFL: + ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; + sock_set_errno(sock, 0); + break; + case F_SETFL: + if ((val & ~O_NONBLOCK) == 0) { + /* only O_NONBLOCK, all other bits are zero */ + netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); + ret = 0; + sock_set_errno(sock, 0); + } else { + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + break; + } + return ret; +} + +#if LWIP_IGMP +/** Register a new IGMP membership. On socket close, the membership is dropped automatically. + * + * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). + * + * @return 1 on success, 0 on failure + */ +static int +lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return 0; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_ipv4_multicast_memberships[i].sock == NULL) { + socket_ipv4_multicast_memberships[i].sock = sock; + ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr); + ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr); + return 1; + } + } + return 0; +} + +/** Unregister a previously registered membership. This prevents dropping the membership + * on socket close. + * + * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). + */ +static void +lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if ((socket_ipv4_multicast_memberships[i].sock == sock) && + ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) && + ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) { + socket_ipv4_multicast_memberships[i].sock = NULL; + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); + return; + } + } +} + +/** Drop all memberships of a socket that were not dropped explicitly via setsockopt. + * + * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK). + */ +static void +lwip_socket_drop_registered_memberships(int s) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_ipv4_multicast_memberships[i].sock == sock) { + ip_addr_t multi_addr, if_addr; + ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr); + ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr); + socket_ipv4_multicast_memberships[i].sock = NULL; + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); + + netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE); + } + } +} +#endif /* LWIP_IGMP */ +#endif /* LWIP_SOCKET */ diff --git a/components/net/lwip-2.0.3/src/api/tcpip.c b/components/net/lwip-2.0.3/src/api/tcpip.c new file mode 100644 index 0000000000..07b2f98434 --- /dev/null +++ b/components/net/lwip-2.0.3/src/api/tcpip.c @@ -0,0 +1,518 @@ +/** + * @file + * Sequential API Main thread module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/tcpip_priv.h" +#include "lwip/sys.h" +#include "lwip/memp.h" +#include "lwip/mem.h" +#include "lwip/init.h" +#include "lwip/ip.h" +#include "lwip/pbuf.h" +#include "lwip/etharp.h" +#include "netif/ethernet.h" + +#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name) +#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name) +#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM) +#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name) + +/* global variables */ +static tcpip_init_done_fn tcpip_init_done; +static void *tcpip_init_done_arg; +static sys_mbox_t mbox; + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +sys_mutex_t lock_tcpip_core; +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_TIMERS +/* wait for a message, timeouts are processed while waiting */ +#define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg) +#else /* LWIP_TIMERS */ +/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */ +#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg) +#endif /* LWIP_TIMERS */ + +/** + * The main lwIP thread. This thread has exclusive access to lwIP core functions + * (unless access to them is not locked). Other threads communicate with this + * thread using message boxes. + * + * It also starts all the timers to make sure they are running in the right + * thread context. + * + * @param arg unused argument + */ +static void +tcpip_thread(void *arg) +{ + struct tcpip_msg *msg; + LWIP_UNUSED_ARG(arg); + + if (tcpip_init_done != NULL) { + tcpip_init_done(tcpip_init_done_arg); + } + + LOCK_TCPIP_CORE(); + while (1) { /* MAIN Loop */ + UNLOCK_TCPIP_CORE(); + LWIP_TCPIP_THREAD_ALIVE(); + /* wait for a message, timeouts are processed while waiting */ + TCPIP_MBOX_FETCH(&mbox, (void **)&msg); + LOCK_TCPIP_CORE(); + if (msg == NULL) { + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); + LWIP_ASSERT("tcpip_thread: invalid message", 0); + continue; + } + switch (msg->type) { +#if !LWIP_TCPIP_CORE_LOCKING + case TCPIP_MSG_API: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); + msg->msg.api_msg.function(msg->msg.api_msg.msg); + break; + case TCPIP_MSG_API_CALL: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg)); + msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg); + sys_sem_signal(msg->msg.api_call.sem); + break; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + +#if !LWIP_TCPIP_CORE_LOCKING_INPUT + case TCPIP_MSG_INPKT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); + msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif); + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + break; +#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ + +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS + case TCPIP_MSG_TIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); + sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + case TCPIP_MSG_UNTIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); + sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ + + case TCPIP_MSG_CALLBACK: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + + case TCPIP_MSG_CALLBACK_STATIC: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + break; + + default: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); + LWIP_ASSERT("tcpip_thread: invalid message", 0); + break; + } + } +} + +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet + * @param inp the network interface on which the packet was received + * @param input_fn input function to call + */ +err_t +tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn) +{ +#if LWIP_TCPIP_CORE_LOCKING_INPUT + err_t ret; + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp)); + LOCK_TCPIP_CORE(); + ret = input_fn(p, inp); + UNLOCK_TCPIP_CORE(); + return ret; +#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ + struct tcpip_msg *msg; + + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_INPKT; + msg->msg.inp.p = p; + msg->msg.inp.netif = inp; + msg->msg.inp.input_fn = input_fn; + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + return ERR_MEM; + } + return ERR_OK; +#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ +} + +/** + * @ingroup lwip_os + * Pass a received packet to tcpip_thread for input processing with + * ethernet_input or ip_input. Don't call directly, pass to netif_add() + * and call netif->input(). + * + * @param p the received packet, p->payload pointing to the Ethernet header or + * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or + * NETIF_FLAG_ETHERNET flags) + * @param inp the network interface on which the packet was received + */ +err_t +tcpip_input(struct pbuf *p, struct netif *inp) +{ +#if LWIP_ETHERNET + if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { + return tcpip_inpkt(p, inp, ethernet_input); + } else +#endif /* LWIP_ETHERNET */ + return tcpip_inpkt(p, inp, ip_input); +} + +/** + * Call a specific function in the thread context of + * tcpip_thread for easy access synchronization. + * A function called in that way may access lwIP core code + * without fearing concurrent access. + * + * @param function the function to call + * @param ctx parameter passed to f + * @param block 1 to block until the request is posted, 0 to non-blocking mode + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) +{ + struct tcpip_msg *msg; + + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_CALLBACK; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + if (block) { + sys_mbox_post(&mbox, msg); + } else { + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_API, msg); + return ERR_MEM; + } + } + return ERR_OK; +} + +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS +/** + * call sys_timeout in tcpip_thread + * + * @param msecs time in milliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_TIMEOUT; + msg->msg.tmo.msecs = msecs; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; +} + +/** + * call sys_untimeout in tcpip_thread + * + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_untimeout(sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_UNTIMEOUT; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; +} +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ + + +/** + * Sends a message to TCPIP thread to call a function. Caller thread blocks on + * on a provided semaphore, which ist NOT automatically signalled by TCPIP thread, + * this has to be done by the user. + * It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way + * with least runtime overhead. + * + * @param fn function to be called from TCPIP thread + * @param apimsg argument to API function + * @param sem semaphore to wait on + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem) +{ +#if LWIP_TCPIP_CORE_LOCKING + LWIP_UNUSED_ARG(sem); + LOCK_TCPIP_CORE(); + fn(apimsg); + UNLOCK_TCPIP_CORE(); + return ERR_OK; +#else /* LWIP_TCPIP_CORE_LOCKING */ + TCPIP_MSG_VAR_DECLARE(msg); + + LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem)); + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + TCPIP_MSG_VAR_ALLOC(msg); + TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API; + TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn; + TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg; + sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); + sys_arch_sem_wait(sem, 0); + TCPIP_MSG_VAR_FREE(msg); + return ERR_OK; +#endif /* LWIP_TCPIP_CORE_LOCKING */ +} + +/** + * Synchronously calls function in TCPIP thread and waits for its completion. + * It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or + * LWIP_NETCONN_SEM_PER_THREAD. + * If not, a semaphore is created and destroyed on every call which is usually + * an expensive/slow operation. + * @param fn Function to call + * @param call Call parameters + * @return Return value from tcpip_api_call_fn + */ +err_t +tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call) +{ +#if LWIP_TCPIP_CORE_LOCKING + err_t err; + LOCK_TCPIP_CORE(); + err = fn(call); + UNLOCK_TCPIP_CORE(); + return err; +#else /* LWIP_TCPIP_CORE_LOCKING */ + TCPIP_MSG_VAR_DECLARE(msg); + +#if !LWIP_NETCONN_SEM_PER_THREAD + err_t err = sys_sem_new(&call->sem, 0); + if (err != ERR_OK) { + return err; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + TCPIP_MSG_VAR_ALLOC(msg); + TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL; + TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call; + TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn; +#if LWIP_NETCONN_SEM_PER_THREAD + TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem; +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); + sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0); + TCPIP_MSG_VAR_FREE(msg); + +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(&call->sem); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + return call->err; +#endif /* LWIP_TCPIP_CORE_LOCKING */ +} + +/** + * Allocate a structure for a static callback message and initialize it. + * This is intended to be used to send "static" messages from interrupt context. + * + * @param function the function to call + * @param ctx parameter passed to function + * @return a struct pointer to pass to tcpip_trycallback(). + */ +struct tcpip_callback_msg* +tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx) +{ + struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return NULL; + } + msg->type = TCPIP_MSG_CALLBACK_STATIC; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + return (struct tcpip_callback_msg*)msg; +} + +/** + * Free a callback message allocated by tcpip_callbackmsg_new(). + * + * @param msg the message to free + */ +void +tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg) +{ + memp_free(MEMP_TCPIP_MSG_API, msg); +} + +/** + * Try to post a callback-message to the tcpip_thread mbox + * This is intended to be used to send "static" messages from interrupt context. + * + * @param msg pointer to the message to post + * @return sys_mbox_trypost() return code + */ +err_t +tcpip_trycallback(struct tcpip_callback_msg* msg) +{ + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + return sys_mbox_trypost(&mbox, msg); +} + +/** + * @ingroup lwip_os + * Initialize this module: + * - initialize all sub modules + * - start the tcpip_thread + * + * @param initfunc a function to call when tcpip_thread is running and finished initializing + * @param arg argument to pass to initfunc + */ +void +tcpip_init(tcpip_init_done_fn initfunc, void *arg) +{ + lwip_init(); + + tcpip_init_done = initfunc; + tcpip_init_done_arg = arg; + if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { + LWIP_ASSERT("failed to create tcpip_thread mbox", 0); + } +#if LWIP_TCPIP_CORE_LOCKING + if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) { + LWIP_ASSERT("failed to create lock_tcpip_core", 0); + } +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); +} + +/** + * Simple callback function used with tcpip_callback to free a pbuf + * (pbuf_free has a wrong signature for tcpip_callback) + * + * @param p The pbuf (chain) to be dereferenced. + */ +static void +pbuf_free_int(void *p) +{ + struct pbuf *q = (struct pbuf *)p; + pbuf_free(q); +} + +/** + * A simple wrapper function that allows you to free a pbuf from interrupt context. + * + * @param p The pbuf (chain) to be dereferenced. + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +pbuf_free_callback(struct pbuf *p) +{ + return tcpip_callback_with_block(pbuf_free_int, p, 0); +} + +/** + * A simple wrapper function that allows you to free heap memory from + * interrupt context. + * + * @param m the heap memory to free + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +mem_free_callback(void *m) +{ + return tcpip_callback_with_block(mem_free, m, 0); +} + +#endif /* !NO_SYS */ diff --git a/components/net/lwip-2.0.3/src/apps/README.md b/components/net/lwip-2.0.3/src/apps/README.md new file mode 100644 index 0000000000..26670858c5 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/README.md @@ -0,0 +1,6 @@ +Some net apps for current version LwIP. + +The RT-Thread develop team ported apps. It's easy to use it on finsh/msh. + +- ping +- tftp diff --git a/components/net/lwip-2.0.3/src/apps/httpd/fs.c b/components/net/lwip-2.0.3/src/apps/httpd/fs.c new file mode 100644 index 0000000000..35b5e31038 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/httpd/fs.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/apps/httpd_opts.h" +#include "lwip/def.h" +#include "lwip/apps/fs.h" +#include "fsdata.h" +#include + + +#if HTTPD_USE_CUSTOM_FSDATA +#include "fsdata_custom.c" +#else /* HTTPD_USE_CUSTOM_FSDATA */ +#include "fsdata.c" +#endif /* HTTPD_USE_CUSTOM_FSDATA */ + +/*-----------------------------------------------------------------------------------*/ + +#if LWIP_HTTPD_CUSTOM_FILES +int fs_open_custom(struct fs_file *file, const char *name); +void fs_close_custom(struct fs_file *file); +#if LWIP_HTTPD_FS_ASYNC_READ +u8_t fs_canread_custom(struct fs_file *file); +u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg); +int fs_read_async_custom(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg); +#else /* LWIP_HTTPD_FS_ASYNC_READ */ +int fs_read_custom(struct fs_file *file, char *buffer, int count); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +#endif /* LWIP_HTTPD_CUSTOM_FILES */ + +/*-----------------------------------------------------------------------------------*/ +err_t +fs_open(struct fs_file *file, const char *name) +{ + const struct fsdata_file *f; + + if ((file == NULL) || (name == NULL)) { + return ERR_ARG; + } + +#if LWIP_HTTPD_CUSTOM_FILES + if (fs_open_custom(file, name)) { + file->is_custom_file = 1; + return ERR_OK; + } + file->is_custom_file = 0; +#endif /* LWIP_HTTPD_CUSTOM_FILES */ + + for (f = FS_ROOT; f != NULL; f = f->next) { + if (!strcmp(name, (const char *)f->name)) { + file->data = (const char *)f->data; + file->len = f->len; + file->index = f->len; + file->pextension = NULL; + file->flags = f->flags; +#if HTTPD_PRECALCULATED_CHECKSUM + file->chksum_count = f->chksum_count; + file->chksum = f->chksum; +#endif /* HTTPD_PRECALCULATED_CHECKSUM */ +#if LWIP_HTTPD_FILE_STATE + file->state = fs_state_init(file, name); +#endif /* #if LWIP_HTTPD_FILE_STATE */ + return ERR_OK; + } + } + /* file not found */ + return ERR_VAL; +} + +/*-----------------------------------------------------------------------------------*/ +void +fs_close(struct fs_file *file) +{ +#if LWIP_HTTPD_CUSTOM_FILES + if (file->is_custom_file) { + fs_close_custom(file); + } +#endif /* LWIP_HTTPD_CUSTOM_FILES */ +#if LWIP_HTTPD_FILE_STATE + fs_state_free(file, file->state); +#endif /* #if LWIP_HTTPD_FILE_STATE */ + LWIP_UNUSED_ARG(file); +} +/*-----------------------------------------------------------------------------------*/ +#if LWIP_HTTPD_DYNAMIC_FILE_READ +#if LWIP_HTTPD_FS_ASYNC_READ +int +fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg) +#else /* LWIP_HTTPD_FS_ASYNC_READ */ +int +fs_read(struct fs_file *file, char *buffer, int count) +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +{ + int read; + if(file->index == file->len) { + return FS_READ_EOF; + } +#if LWIP_HTTPD_FS_ASYNC_READ + LWIP_UNUSED_ARG(callback_fn); + LWIP_UNUSED_ARG(callback_arg); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +#if LWIP_HTTPD_CUSTOM_FILES + if (file->is_custom_file) { +#if LWIP_HTTPD_FS_ASYNC_READ + return fs_read_async_custom(file, buffer, count, callback_fn, callback_arg); +#else /* LWIP_HTTPD_FS_ASYNC_READ */ + return fs_read_custom(file, buffer, count); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + } +#endif /* LWIP_HTTPD_CUSTOM_FILES */ + + read = file->len - file->index; + if(read > count) { + read = count; + } + + MEMCPY(buffer, (file->data + file->index), read); + file->index += read; + + return(read); +} +#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ +/*-----------------------------------------------------------------------------------*/ +#if LWIP_HTTPD_FS_ASYNC_READ +int +fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg) +{ + if (file != NULL) { +#if LWIP_HTTPD_FS_ASYNC_READ +#if LWIP_HTTPD_CUSTOM_FILES + if (!fs_canread_custom(file)) { + if (fs_wait_read_custom(file, callback_fn, callback_arg)) { + return 0; + } + } +#else /* LWIP_HTTPD_CUSTOM_FILES */ + LWIP_UNUSED_ARG(callback_fn); + LWIP_UNUSED_ARG(callback_arg); +#endif /* LWIP_HTTPD_CUSTOM_FILES */ +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + } + return 1; +} +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +/*-----------------------------------------------------------------------------------*/ +int +fs_bytes_left(struct fs_file *file) +{ + return file->len - file->index; +} diff --git a/components/net/lwip-2.0.3/src/apps/httpd/fs/404.html b/components/net/lwip-2.0.3/src/apps/httpd/fs/404.html new file mode 100644 index 0000000000..40b343a91e --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/httpd/fs/404.html @@ -0,0 +1,21 @@ + +lwIP - A Lightweight TCP/IP Stack + + + + +
+ SICS logo + +

lwIP - A Lightweight TCP/IP Stack

+

404 - Page not found

+

+ Sorry, the page you are requesting was not found on this + server. +

+
+   +
+ + diff --git a/components/net/lwip-2.0.3/src/apps/httpd/fs/img/sics.gif b/components/net/lwip-2.0.3/src/apps/httpd/fs/img/sics.gif new file mode 100644 index 0000000000000000000000000000000000000000..0a4fc7bb07050eec9226ca93bc9ad237f35502c8 GIT binary patch literal 724 zcmZ?wbhEHbbYoCrSjxa~Q`<5tD{KG${gWq8=I7_%uwlcpWy=~G8p_Jb4zT=SA;^3z!7uBu>UZ()&> z+r1;Oh0mFly?klC)5cAV$sD}98F{LBUHERS_hGGKac5`W-mvIltqUt73*&`X?UVf< z%Uqmm^}K~z9MaFS-jwgVGIUF9Z77P_s7Vc}y?@_XT+GT)AcZF$6%$qQsA+Q0bF z!Mss%ktc&>+n*qp2aIzy6-8A8zNf3ovHkU%wPnH@(O;*7g5`QX{a~M@%VFg!JaWkVUk6yFE1wL^V{({yi?^s!by^W;pXIz%mY}~L;uBR^JK|)kW|Avap zVzxyL+2N;b1q1f77^T<4c)gUoN8c;6;F^+^0^VN o#HPS7gPr3^SVM!%(d|c@c+6frXclnOc-SHmma$O4k%7S)08~d;ZvX%Q literal 0 HcmV?d00001 diff --git a/components/net/lwip-2.0.3/src/apps/httpd/fs/index.html b/components/net/lwip-2.0.3/src/apps/httpd/fs/index.html new file mode 100644 index 0000000000..ab575ef089 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/httpd/fs/index.html @@ -0,0 +1,47 @@ + +lwIP - A Lightweight TCP/IP Stack + + + + +
+ SICS logo + +

lwIP - A Lightweight TCP/IP Stack

+

+ The web page you are watching was served by a simple web + server running on top of the lightweight TCP/IP stack lwIP. +

+

+ lwIP is an open source implementation of the TCP/IP + protocol suite that was originally written by Adam Dunkels + of the Swedish Institute of Computer Science but now is + being actively developed by a team of developers + distributed world-wide. Since it's release, lwIP has + spurred a lot of interest and has been ported to several + platforms and operating systems. lwIP can be used either + with or without an underlying OS. +

+

+ The focus of the lwIP TCP/IP implementation is to reduce + the RAM usage while still having a full scale TCP. This + makes lwIP suitable for use in embedded systems with tens + of kilobytes of free RAM and room for around 40 kilobytes + of code ROM. +

+

+ More information about lwIP can be found at the lwIP + homepage at http://savannah.nongnu.org/projects/lwip/ + or at the lwIP wiki at http://lwip.wikia.com/. +

+
+   +
+ + + diff --git a/components/net/lwip-2.0.3/src/apps/httpd/fsdata.c b/components/net/lwip-2.0.3/src/apps/httpd/fsdata.c new file mode 100644 index 0000000000..6170ce6326 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/httpd/fsdata.c @@ -0,0 +1,298 @@ +#include "lwip/apps/fs.h" +#include "lwip/def.h" +#include "fsdata.h" + + +#define file_NULL (struct fsdata_file *) NULL + + +static const unsigned int dummy_align__img_sics_gif = 0; +static const unsigned char data__img_sics_gif[] = { +/* /img/sics.gif (14 chars) */ +0x2f,0x69,0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x00,0x00,0x00, + +/* HTTP header */ +/* "HTTP/1.0 200 OK +" (17 bytes) */ +0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, +0x0a, +/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) +" (63 bytes) */ +0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, +0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, +0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, +0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, +/* "Content-type: image/gif + +" (27 bytes) */ +0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x69,0x6d, +0x61,0x67,0x65,0x2f,0x67,0x69,0x66,0x0d,0x0a,0x0d,0x0a, +/* raw file data (724 bytes) */ +0x47,0x49,0x46,0x38,0x39,0x61,0x46,0x00,0x22,0x00,0xa5,0x00,0x00,0xd9,0x2b,0x39, +0x6a,0x6a,0x6a,0xbf,0xbf,0xbf,0x93,0x93,0x93,0x0f,0x0f,0x0f,0xb0,0xb0,0xb0,0xa6, +0xa6,0xa6,0x80,0x80,0x80,0x76,0x76,0x76,0x1e,0x1e,0x1e,0x9d,0x9d,0x9d,0x2e,0x2e, +0x2e,0x49,0x49,0x49,0x54,0x54,0x54,0x8a,0x8a,0x8a,0x60,0x60,0x60,0xc6,0xa6,0x99, +0xbd,0xb5,0xb2,0xc2,0xab,0xa1,0xd9,0x41,0x40,0xd5,0x67,0x55,0xc0,0xb0,0xaa,0xd5, +0x5e,0x4e,0xd6,0x50,0x45,0xcc,0x93,0x7d,0xc8,0xa1,0x90,0xce,0x8b,0x76,0xd2,0x7b, +0x65,0xd1,0x84,0x6d,0xc9,0x99,0x86,0x3a,0x3a,0x3a,0x00,0x00,0x00,0xb8,0xb8,0xb8, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2c,0x00,0x00, +0x00,0x00,0x46,0x00,0x22,0x00,0x00,0x06,0xfe,0x40,0x90,0x70,0x48,0x2c,0x1a,0x8f, +0xc8,0xa4,0x72,0xc9,0x6c,0x3a,0x9f,0xd0,0xa8,0x74,0x4a,0xad,0x5a,0xaf,0xd8,0xac, +0x76,0xa9,0x40,0x04,0xbe,0x83,0xe2,0x60,0x3c,0x50,0x20,0x0d,0x8e,0x6f,0x00,0x31, +0x28,0x1c,0x0d,0x07,0xb5,0xc3,0x60,0x75,0x24,0x3e,0xf8,0xfc,0x87,0x11,0x06,0xe9, +0x3d,0x46,0x07,0x0b,0x7a,0x7a,0x7c,0x43,0x06,0x1e,0x84,0x78,0x0b,0x07,0x6e,0x51, +0x01,0x8a,0x84,0x08,0x7e,0x79,0x80,0x87,0x89,0x91,0x7a,0x93,0x0a,0x04,0x99,0x78, +0x96,0x4f,0x03,0x9e,0x79,0x01,0x94,0x9f,0x43,0x9c,0xa3,0xa4,0x05,0x77,0xa3,0xa0, +0x4e,0x98,0x79,0x0b,0x1e,0x83,0xa4,0xa6,0x1f,0x96,0x05,0x9d,0xaa,0x78,0x01,0x07, +0x84,0x04,0x1e,0x1e,0xbb,0xb8,0x51,0x84,0x0e,0x43,0x05,0x07,0x77,0xa5,0x7f,0x42, +0xb1,0xb2,0x01,0x63,0x08,0x0d,0xbb,0x01,0x0c,0x7a,0x0d,0x44,0x0e,0xd8,0xaf,0x4c, +0x05,0x7a,0x04,0x47,0x07,0x07,0xb7,0x80,0xa2,0xe1,0x7d,0x44,0x05,0x01,0x04,0x01, +0xd0,0xea,0x87,0x93,0x4f,0xe0,0x9a,0x49,0xce,0xd8,0x79,0x04,0x66,0x20,0x15,0x10, +0x10,0x11,0x92,0x29,0x80,0xb6,0xc0,0x91,0x15,0x45,0x1e,0x90,0x19,0x71,0x46,0xa8, +0x5c,0x04,0x0e,0x00,0x22,0x4e,0xe8,0x40,0x24,0x9f,0x3e,0x04,0x06,0xa7,0x58,0xd4, +0x93,0xa0,0x1c,0x91,0x3f,0xe8,0xf0,0x88,0x03,0xb1,0x21,0xa2,0x49,0x00,0x19,0x86, +0xfc,0x52,0x44,0xe0,0x01,0x9d,0x29,0x21,0x15,0x25,0x50,0xf7,0x67,0x25,0x1e,0x06, +0xfd,0x4e,0x9a,0xb4,0x90,0xac,0x15,0xfa,0xcb,0x52,0x53,0x1e,0x8c,0xf2,0xf8,0x07, +0x92,0x2d,0x08,0x3a,0x4d,0x12,0x49,0x95,0x49,0xdb,0x14,0x04,0xc4,0x14,0x85,0x29, +0xaa,0xe7,0x01,0x08,0xa4,0x49,0x01,0x14,0x51,0xe0,0x53,0x91,0xd5,0x29,0x06,0x1a, +0x64,0x02,0xf4,0xc7,0x81,0x9e,0x05,0x20,0x22,0x64,0xa5,0x30,0xae,0xab,0x9e,0x97, +0x53,0xd8,0xb9,0xfd,0x50,0xef,0x93,0x02,0x42,0x74,0x34,0xe8,0x9c,0x20,0x21,0xc9, +0x01,0x68,0x78,0xe6,0x55,0x29,0x20,0x56,0x4f,0x4c,0x40,0x51,0x71,0x82,0xc0,0x70, +0x21,0x22,0x85,0xbe,0x4b,0x1c,0x44,0x05,0xea,0xa4,0x01,0xbf,0x22,0xb5,0xf0,0x1c, +0x06,0x51,0x38,0x8f,0xe0,0x22,0xec,0x18,0xac,0x39,0x22,0xd4,0xd6,0x93,0x44,0x01, +0x32,0x82,0xc8,0xfc,0x61,0xb3,0x01,0x45,0x0c,0x2e,0x83,0x30,0xd0,0x0e,0x17,0x24, +0x0f,0x70,0x85,0x94,0xee,0x05,0x05,0x53,0x4b,0x32,0x1b,0x3f,0x98,0xd3,0x1d,0x29, +0x81,0xb0,0xae,0x1e,0x8c,0x7e,0x68,0xe0,0x60,0x5a,0x54,0x8f,0xb0,0x78,0x69,0x73, +0x06,0xa2,0x00,0x6b,0x57,0xca,0x3d,0x11,0x50,0xbd,0x04,0x30,0x4b,0x3a,0xd4,0xab, +0x5f,0x1f,0x9b,0x3d,0x13,0x74,0x27,0x88,0x3c,0x25,0xe0,0x17,0xbe,0x7a,0x79,0x45, +0x0d,0x0c,0xb0,0x8b,0xda,0x90,0xca,0x80,0x06,0x5d,0x17,0x60,0x1c,0x22,0x4c,0xd8, +0x57,0x22,0x06,0x20,0x00,0x98,0x07,0x08,0xe4,0x56,0x80,0x80,0x1c,0xc5,0xb7,0xc5, +0x82,0x0c,0x36,0xe8,0xe0,0x83,0x10,0x46,0x28,0xe1,0x84,0x14,0x56,0x68,0xa1,0x10, +0x41,0x00,0x00,0x3b,}; + +static const unsigned int dummy_align__404_html = 1; +static const unsigned char data__404_html[] = { +/* /404.html (10 chars) */ +0x2f,0x34,0x30,0x34,0x2e,0x68,0x74,0x6d,0x6c,0x00,0x00,0x00, + +/* HTTP header */ +/* "HTTP/1.0 404 File not found +" (29 bytes) */ +0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x34,0x30,0x34,0x20,0x46,0x69,0x6c, +0x65,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x0d,0x0a, +/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) +" (63 bytes) */ +0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, +0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, +0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, +0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, +/* "Content-type: text/html + +" (27 bytes) */ +0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, +0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, +/* raw file data (565 bytes) */ +0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, +0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, +0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, +0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, +0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, +0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, +0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, +0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, +0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, +0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, +0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, +0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, +0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, +0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, +0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, +0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, +0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, +0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, +0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, +0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, +0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, +0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, +0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, +0x20,0x3c,0x68,0x32,0x3e,0x34,0x30,0x34,0x20,0x2d,0x20,0x50,0x61,0x67,0x65,0x20, +0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x3c,0x2f,0x68,0x32,0x3e,0x0d,0x0a, +0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x53,0x6f,0x72, +0x72,0x79,0x2c,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75, +0x20,0x61,0x72,0x65,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x69,0x6e,0x67,0x20, +0x77,0x61,0x73,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x6f,0x6e, +0x20,0x74,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76, +0x65,0x72,0x2e,0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, +0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, +0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, +0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, +0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, +0x6d,0x6c,0x3e,0x0d,0x0a,}; + +static const unsigned int dummy_align__index_html = 2; +static const unsigned char data__index_html[] = { +/* /index.html (12 chars) */ +0x2f,0x69,0x6e,0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,0x00, + +/* HTTP header */ +/* "HTTP/1.0 200 OK +" (17 bytes) */ +0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, +0x0a, +/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) +" (63 bytes) */ +0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, +0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, +0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, +0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, +/* "Content-type: text/html + +" (27 bytes) */ +0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, +0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, +/* raw file data (1751 bytes) */ +0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, +0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, +0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, +0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, +0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, +0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, +0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, +0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, +0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, +0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, +0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, +0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, +0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, +0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, +0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, +0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, +0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, +0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, +0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, +0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, +0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, +0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, +0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, +0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x77, +0x65,0x62,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,0x20,0x61,0x72,0x65,0x20, +0x77,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x77,0x61,0x73,0x20,0x73,0x65,0x72, +0x76,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x73,0x69,0x6d,0x70,0x6c,0x65,0x20, +0x77,0x65,0x62,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,0x65,0x72, +0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x6f,0x6e,0x20,0x74,0x6f,0x70,0x20, +0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67, +0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,0x20,0x73,0x74,0x61,0x63,0x6b,0x20, +0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, +0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, +0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x6c, +0x77,0x49,0x50,0x3c,0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70, +0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20, +0x6c,0x77,0x49,0x50,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x6f,0x70,0x65,0x6e,0x20, +0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, +0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x54,0x43,0x50, +0x2f,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x74,0x6f,0x63, +0x6f,0x6c,0x20,0x73,0x75,0x69,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x77,0x61, +0x73,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x77,0x72,0x69, +0x74,0x74,0x65,0x6e,0x20,0x62,0x79,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20, +0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77, +0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f, +0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x41,0x64,0x61,0x6d,0x20,0x44,0x75,0x6e,0x6b, +0x65,0x6c,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x66,0x20,0x74,0x68,0x65, +0x20,0x53,0x77,0x65,0x64,0x69,0x73,0x68,0x20,0x49,0x6e,0x73,0x74,0x69,0x74,0x75, +0x74,0x65,0x20,0x6f,0x66,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x20,0x53, +0x63,0x69,0x65,0x6e,0x63,0x65,0x3c,0x2f,0x61,0x3e,0x20,0x62,0x75,0x74,0x20,0x6e, +0x6f,0x77,0x20,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x62,0x65,0x69,0x6e, +0x67,0x20,0x61,0x63,0x74,0x69,0x76,0x65,0x6c,0x79,0x20,0x64,0x65,0x76,0x65,0x6c, +0x6f,0x70,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x74,0x65,0x61,0x6d,0x20,0x6f, +0x66,0x20,0x64,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x73,0x0d,0x0a,0x09,0x20, +0x20,0x20,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x77, +0x6f,0x72,0x6c,0x64,0x2d,0x77,0x69,0x64,0x65,0x2e,0x20,0x53,0x69,0x6e,0x63,0x65, +0x20,0x69,0x74,0x27,0x73,0x20,0x72,0x65,0x6c,0x65,0x61,0x73,0x65,0x2c,0x20,0x6c, +0x77,0x49,0x50,0x20,0x68,0x61,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x70, +0x75,0x72,0x72,0x65,0x64,0x20,0x61,0x20,0x6c,0x6f,0x74,0x20,0x6f,0x66,0x20,0x69, +0x6e,0x74,0x65,0x72,0x65,0x73,0x74,0x20,0x61,0x6e,0x64,0x20,0x68,0x61,0x73,0x20, +0x62,0x65,0x65,0x6e,0x20,0x70,0x6f,0x72,0x74,0x65,0x64,0x20,0x74,0x6f,0x20,0x73, +0x65,0x76,0x65,0x72,0x61,0x6c,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x6c,0x61, +0x74,0x66,0x6f,0x72,0x6d,0x73,0x20,0x61,0x6e,0x64,0x20,0x6f,0x70,0x65,0x72,0x61, +0x74,0x69,0x6e,0x67,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x73,0x2e,0x20,0x6c,0x77, +0x49,0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,0x65, +0x69,0x74,0x68,0x65,0x72,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68, +0x20,0x6f,0x72,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x61,0x6e,0x20,0x75, +0x6e,0x64,0x65,0x72,0x6c,0x79,0x69,0x6e,0x67,0x20,0x4f,0x53,0x2e,0x0d,0x0a,0x09, +0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a, +0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x66,0x6f,0x63,0x75,0x73,0x20,0x6f, +0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x54,0x43,0x50,0x2f,0x49, +0x50,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e, +0x20,0x69,0x73,0x20,0x74,0x6f,0x20,0x72,0x65,0x64,0x75,0x63,0x65,0x0d,0x0a,0x09, +0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x52,0x41,0x4d,0x20,0x75,0x73,0x61,0x67, +0x65,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x73,0x74,0x69,0x6c,0x6c,0x20,0x68,0x61, +0x76,0x69,0x6e,0x67,0x20,0x61,0x20,0x66,0x75,0x6c,0x6c,0x20,0x73,0x63,0x61,0x6c, +0x65,0x20,0x54,0x43,0x50,0x2e,0x20,0x54,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20, +0x20,0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x6c,0x77,0x49,0x50,0x20,0x73,0x75,0x69, +0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x75,0x73,0x65,0x20,0x69,0x6e, +0x20,0x65,0x6d,0x62,0x65,0x64,0x64,0x65,0x64,0x20,0x73,0x79,0x73,0x74,0x65,0x6d, +0x73,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x65,0x6e,0x73,0x0d,0x0a,0x09,0x20,0x20, +0x20,0x20,0x6f,0x66,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x20,0x6f, +0x66,0x20,0x66,0x72,0x65,0x65,0x20,0x52,0x41,0x4d,0x20,0x61,0x6e,0x64,0x20,0x72, +0x6f,0x6f,0x6d,0x20,0x66,0x6f,0x72,0x20,0x61,0x72,0x6f,0x75,0x6e,0x64,0x20,0x34, +0x30,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x0d,0x0a,0x09,0x20,0x20, +0x20,0x20,0x6f,0x66,0x20,0x63,0x6f,0x64,0x65,0x20,0x52,0x4f,0x4d,0x2e,0x0d,0x0a, +0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d, +0x0a,0x09,0x20,0x20,0x20,0x20,0x4d,0x6f,0x72,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72, +0x6d,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x62,0x6f,0x75,0x74,0x20,0x6c,0x77,0x49, +0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x61, +0x74,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20, +0x20,0x68,0x6f,0x6d,0x65,0x70,0x61,0x67,0x65,0x20,0x61,0x74,0x20,0x3c,0x61,0x0d, +0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70, +0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67, +0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f, +0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61, +0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72, +0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x2f, +0x3c,0x2f,0x61,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x72,0x20,0x61,0x74, +0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x77,0x69,0x6b,0x69,0x20,0x61, +0x74,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d, +0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b, +0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, +0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x3c, +0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, +0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, +0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, +0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, +0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, +0x6d,0x6c,0x3e,0x0d,0x0a,0x0d,0x0a,}; + + + +const struct fsdata_file file__img_sics_gif[] = { { +file_NULL, +data__img_sics_gif, +data__img_sics_gif + 16, +sizeof(data__img_sics_gif) - 16, +1, +}}; + +const struct fsdata_file file__404_html[] = { { +file__img_sics_gif, +data__404_html, +data__404_html + 12, +sizeof(data__404_html) - 12, +1, +}}; + +const struct fsdata_file file__index_html[] = { { +file__404_html, +data__index_html, +data__index_html + 12, +sizeof(data__index_html) - 12, +1, +}}; + +#define FS_ROOT file__index_html +#define FS_NUMFILES 3 + diff --git a/components/net/lwip-2.0.3/src/apps/httpd/fsdata.h b/components/net/lwip-2.0.3/src/apps/httpd/fsdata.h new file mode 100644 index 0000000000..ac4548c785 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/httpd/fsdata.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_FSDATA_H +#define LWIP_FSDATA_H + +#include "lwip/apps/httpd_opts.h" +#include "lwip/apps/fs.h" + +struct fsdata_file { + const struct fsdata_file *next; + const unsigned char *name; + const unsigned char *data; + int len; + u8_t flags; +#if HTTPD_PRECALCULATED_CHECKSUM + u16_t chksum_count; + const struct fsdata_chksum *chksum; +#endif /* HTTPD_PRECALCULATED_CHECKSUM */ +}; + +#endif /* LWIP_FSDATA_H */ diff --git a/components/net/lwip-2.0.3/src/apps/httpd/httpd.c b/components/net/lwip-2.0.3/src/apps/httpd/httpd.c new file mode 100644 index 0000000000..43195d7c54 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/httpd/httpd.c @@ -0,0 +1,2629 @@ +/** + * @file + * LWIP HTTP server implementation + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +/** + * @defgroup httpd HTTP server + * @ingroup apps + * + * This httpd supports for a + * rudimentary server-side-include facility which will replace tags of the form + * in any file whose extension is .shtml, .shtm or .ssi with + * strings provided by an include handler whose pointer is provided to the + * module via function http_set_ssi_handler(). + * Additionally, a simple common + * gateway interface (CGI) handling mechanism has been added to allow clients + * to hook functions to particular request URIs. + * + * To enable SSI support, define label LWIP_HTTPD_SSI in lwipopts.h. + * To enable CGI support, define label LWIP_HTTPD_CGI in lwipopts.h. + * + * By default, the server assumes that HTTP headers are already present in + * each file stored in the file system. By defining LWIP_HTTPD_DYNAMIC_HEADERS in + * lwipopts.h, this behavior can be changed such that the server inserts the + * headers automatically based on the extension of the file being served. If + * this mode is used, be careful to ensure that the file system image used + * does not already contain the header information. + * + * File system images without headers can be created using the makefsfile + * tool with the -h command line option. + * + * + * Notes about valid SSI tags + * -------------------------- + * + * The following assumptions are made about tags used in SSI markers: + * + * 1. No tag may contain '-' or whitespace characters within the tag name. + * 2. Whitespace is allowed between the tag leadin "". + * 3. The maximum tag name length is LWIP_HTTPD_MAX_TAG_NAME_LEN, currently 8 characters. + * + * Notes on CGI usage + * ------------------ + * + * The simple CGI support offered here works with GET method requests only + * and can handle up to 16 parameters encoded into the URI. The handler + * function may not write directly to the HTTP output but must return a + * filename that the HTTP server will send to the browser as a response to + * the incoming CGI request. + * + * + * + * The list of supported file types is quite short, so if makefsdata complains + * about an unknown extension, make sure to add it (and its doctype) to + * the 'g_psHTTPHeaders' list. + */ +#include "lwip/init.h" +#include "lwip/apps/httpd.h" +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/apps/fs.h" +#include "httpd_structs.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/tcp.h" + +#include /* memset */ +#include /* atoi */ +#include + +#if LWIP_TCP && LWIP_CALLBACK_API + +/** Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes */ +#define MIN_REQ_LEN 7 + +#define CRLF "\r\n" +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE +#define HTTP11_CONNECTIONKEEPALIVE "Connection: keep-alive" +#define HTTP11_CONNECTIONKEEPALIVE2 "Connection: Keep-Alive" +#endif + +/** These defines check whether tcp_write has to copy data or not */ + +/** This was TI's check whether to let TCP copy data or not + * \#define HTTP_IS_DATA_VOLATILE(hs) ((hs->file < (char *)0x20000000) ? 0 : TCP_WRITE_FLAG_COPY) + */ +#ifndef HTTP_IS_DATA_VOLATILE +#if LWIP_HTTPD_SSI +/* Copy for SSI files, no copy for non-SSI files */ +#define HTTP_IS_DATA_VOLATILE(hs) ((hs)->ssi ? TCP_WRITE_FLAG_COPY : 0) +#else /* LWIP_HTTPD_SSI */ +/** Default: don't copy if the data is sent from file-system directly */ +#define HTTP_IS_DATA_VOLATILE(hs) (((hs->file != NULL) && (hs->handle != NULL) && (hs->file == \ + (const char*)hs->handle->data + hs->handle->len - hs->left)) \ + ? 0 : TCP_WRITE_FLAG_COPY) +#endif /* LWIP_HTTPD_SSI */ +#endif + +/** Default: headers are sent from ROM */ +#ifndef HTTP_IS_HDR_VOLATILE +#define HTTP_IS_HDR_VOLATILE(hs, ptr) 0 +#endif + +/* Return values for http_send_*() */ +#define HTTP_DATA_TO_SEND_BREAK 2 +#define HTTP_DATA_TO_SEND_CONTINUE 1 +#define HTTP_NO_DATA_TO_SEND 0 + +typedef struct +{ + const char *name; + u8_t shtml; +} default_filename; + +const default_filename g_psDefaultFilenames[] = { + {"/index.shtml", 1 }, + {"/index.ssi", 1 }, + {"/index.shtm", 1 }, + {"/index.html", 0 }, + {"/index.htm", 0 } +}; + +#define NUM_DEFAULT_FILENAMES (sizeof(g_psDefaultFilenames) / \ + sizeof(default_filename)) + +#if LWIP_HTTPD_SUPPORT_REQUESTLIST +/** HTTP request is copied here from pbufs for simple parsing */ +static char httpd_req_buf[LWIP_HTTPD_MAX_REQ_LENGTH+1]; +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + +#if LWIP_HTTPD_SUPPORT_POST +#if LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN > LWIP_HTTPD_MAX_REQUEST_URI_LEN +#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN +#endif +#endif +#ifndef LWIP_HTTPD_URI_BUF_LEN +#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_MAX_REQUEST_URI_LEN +#endif +#if LWIP_HTTPD_URI_BUF_LEN +/* Filename for response file to send when POST is finished or + * search for default files when a directory is requested. */ +static char http_uri_buf[LWIP_HTTPD_URI_BUF_LEN+1]; +#endif + +#if LWIP_HTTPD_DYNAMIC_HEADERS +/* The number of individual strings that comprise the headers sent before each + * requested file. + */ +#define NUM_FILE_HDR_STRINGS 5 +#define HDR_STRINGS_IDX_HTTP_STATUS 0 /* e.g. "HTTP/1.0 200 OK\r\n" */ +#define HDR_STRINGS_IDX_SERVER_NAME 1 /* e.g. "Server: "HTTPD_SERVER_AGENT"\r\n" */ +#define HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE 2 /* e.g. "Content-Length: xy\r\n" and/or "Connection: keep-alive\r\n" */ +#define HDR_STRINGS_IDX_CONTENT_LEN_NR 3 /* the byte count, when content-length is used */ +#define HDR_STRINGS_IDX_CONTENT_TYPE 4 /* the content type (or default answer content type including default document) */ + +/* The dynamically generated Content-Length buffer needs space for CRLF + NULL */ +#define LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET 3 +#ifndef LWIP_HTTPD_MAX_CONTENT_LEN_SIZE +/* The dynamically generated Content-Length buffer shall be able to work with + ~953 MB (9 digits) */ +#define LWIP_HTTPD_MAX_CONTENT_LEN_SIZE (9 + LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) +#endif +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ + +#if LWIP_HTTPD_SSI + +#define HTTPD_LAST_TAG_PART 0xFFFF + +enum tag_check_state { + TAG_NONE, /* Not processing an SSI tag */ + TAG_LEADIN, /* Tag lead in "" being processed */ + TAG_SENDING /* Sending tag replacement string */ +}; + +struct http_ssi_state { + const char *parsed; /* Pointer to the first unparsed byte in buf. */ +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + const char *tag_started;/* Pointer to the first opening '<' of the tag. */ +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */ + const char *tag_end; /* Pointer to char after the closing '>' of the tag. */ + u32_t parse_left; /* Number of unparsed bytes in buf. */ + u16_t tag_index; /* Counter used by tag parsing state machine */ + u16_t tag_insert_len; /* Length of insert in string tag_insert */ +#if LWIP_HTTPD_SSI_MULTIPART + u16_t tag_part; /* Counter passed to and changed by tag insertion function to insert multiple times */ +#endif /* LWIP_HTTPD_SSI_MULTIPART */ + u8_t tag_name_len; /* Length of the tag name in string tag_name */ + char tag_name[LWIP_HTTPD_MAX_TAG_NAME_LEN + 1]; /* Last tag name extracted */ + char tag_insert[LWIP_HTTPD_MAX_TAG_INSERT_LEN + 1]; /* Insert string for tag_name */ + enum tag_check_state tag_state; /* State of the tag processor */ +}; +#endif /* LWIP_HTTPD_SSI */ + +struct http_state { +#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED + struct http_state *next; +#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ + struct fs_file file_handle; + struct fs_file *handle; + const char *file; /* Pointer to first unsent byte in buf. */ + + struct tcp_pcb *pcb; +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + struct pbuf *req; +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + +#if LWIP_HTTPD_DYNAMIC_FILE_READ + char *buf; /* File read buffer. */ + int buf_len; /* Size of file read buffer, buf. */ +#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ + u32_t left; /* Number of unsent bytes in buf. */ + u8_t retries; +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + u8_t keepalive; +#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ +#if LWIP_HTTPD_SSI + struct http_ssi_state *ssi; +#endif /* LWIP_HTTPD_SSI */ +#if LWIP_HTTPD_CGI + char *params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */ + char *param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */ +#endif /* LWIP_HTTPD_CGI */ +#if LWIP_HTTPD_DYNAMIC_HEADERS + const char *hdrs[NUM_FILE_HDR_STRINGS]; /* HTTP headers to be sent. */ + char hdr_content_len[LWIP_HTTPD_MAX_CONTENT_LEN_SIZE]; + u16_t hdr_pos; /* The position of the first unsent header byte in the + current string */ + u16_t hdr_index; /* The index of the hdr string currently being sent. */ +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ +#if LWIP_HTTPD_TIMING + u32_t time_started; +#endif /* LWIP_HTTPD_TIMING */ +#if LWIP_HTTPD_SUPPORT_POST + u32_t post_content_len_left; +#if LWIP_HTTPD_POST_MANUAL_WND + u32_t unrecved_bytes; + u8_t no_auto_wnd; + u8_t post_finished; +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ +#endif /* LWIP_HTTPD_SUPPORT_POST*/ +}; + +#if HTTPD_USE_MEM_POOL +LWIP_MEMPOOL_DECLARE(HTTPD_STATE, MEMP_NUM_PARALLEL_HTTPD_CONNS, sizeof(struct http_state), "HTTPD_STATE") +#if LWIP_HTTPD_SSI +LWIP_MEMPOOL_DECLARE(HTTPD_SSI_STATE, MEMP_NUM_PARALLEL_HTTPD_SSI_CONNS, sizeof(struct http_ssi_state), "HTTPD_SSI_STATE") +#define HTTP_FREE_SSI_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_SSI_STATE, (x)) +#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)LWIP_MEMPOOL_ALLOC(HTTPD_SSI_STATE) +#endif /* LWIP_HTTPD_SSI */ +#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)LWIP_MEMPOOL_ALLOC(HTTPD_STATE) +#define HTTP_FREE_HTTP_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_STATE, (x)) +#else /* HTTPD_USE_MEM_POOL */ +#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)mem_malloc(sizeof(struct http_state)) +#define HTTP_FREE_HTTP_STATE(x) mem_free(x) +#if LWIP_HTTPD_SSI +#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)mem_malloc(sizeof(struct http_ssi_state)) +#define HTTP_FREE_SSI_STATE(x) mem_free(x) +#endif /* LWIP_HTTPD_SSI */ +#endif /* HTTPD_USE_MEM_POOL */ + +static err_t http_close_conn(struct tcp_pcb *pcb, struct http_state *hs); +static err_t http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn); +static err_t http_find_file(struct http_state *hs, const char *uri, int is_09); +static err_t http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, u8_t tag_check, char* params); +static err_t http_poll(void *arg, struct tcp_pcb *pcb); +static u8_t http_check_eof(struct tcp_pcb *pcb, struct http_state *hs); +#if LWIP_HTTPD_FS_ASYNC_READ +static void http_continue(void *connection); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + +#if LWIP_HTTPD_SSI +/* SSI insert handler function pointer. */ +tSSIHandler g_pfnSSIHandler; +#if !LWIP_HTTPD_SSI_RAW +int g_iNumTags; +const char **g_ppcTags; +#endif /* !LWIP_HTTPD_SSI_RAW */ + +#define LEN_TAG_LEAD_IN 5 +const char * const g_pcTagLeadIn = ""; +#endif /* LWIP_HTTPD_SSI */ + +#if LWIP_HTTPD_CGI +/* CGI handler information */ +const tCGI *g_pCGIs; +int g_iNumCGIs; +int http_cgi_paramcount; +#define http_cgi_params hs->params +#define http_cgi_param_vals hs->param_vals +#elif LWIP_HTTPD_CGI_SSI +char *http_cgi_params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */ +char *http_cgi_param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */ +#endif /* LWIP_HTTPD_CGI */ + +#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED +/** global list of active HTTP connections, use to kill the oldest when + running out of memory */ +static struct http_state *http_connections; + +static void +http_add_connection(struct http_state *hs) +{ + /* add the connection to the list */ + hs->next = http_connections; + http_connections = hs; +} + +static void +http_remove_connection(struct http_state *hs) +{ + /* take the connection off the list */ + if (http_connections) { + if (http_connections == hs) { + http_connections = hs->next; + } else { + struct http_state *last; + for(last = http_connections; last->next != NULL; last = last->next) { + if (last->next == hs) { + last->next = hs->next; + break; + } + } + } + } +} + +static void +http_kill_oldest_connection(u8_t ssi_required) +{ + struct http_state *hs = http_connections; + struct http_state *hs_free_next = NULL; + while(hs && hs->next) { +#if LWIP_HTTPD_SSI + if (ssi_required) { + if (hs->next->ssi != NULL) { + hs_free_next = hs; + } + } else +#else /* LWIP_HTTPD_SSI */ + LWIP_UNUSED_ARG(ssi_required); +#endif /* LWIP_HTTPD_SSI */ + { + hs_free_next = hs; + } + LWIP_ASSERT("broken list", hs != hs->next); + hs = hs->next; + } + if (hs_free_next != NULL) { + LWIP_ASSERT("hs_free_next->next != NULL", hs_free_next->next != NULL); + LWIP_ASSERT("hs_free_next->next->pcb != NULL", hs_free_next->next->pcb != NULL); + /* send RST when killing a connection because of memory shortage */ + http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */ + } +} +#else /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ + +#define http_add_connection(hs) +#define http_remove_connection(hs) + +#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ + +#if LWIP_HTTPD_SSI +/** Allocate as struct http_ssi_state. */ +static struct http_ssi_state* +http_ssi_state_alloc(void) +{ + struct http_ssi_state *ret = HTTP_ALLOC_SSI_STATE(); +#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED + if (ret == NULL) { + http_kill_oldest_connection(1); + ret = HTTP_ALLOC_SSI_STATE(); + } +#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ + if (ret != NULL) { + memset(ret, 0, sizeof(struct http_ssi_state)); + } + return ret; +} + +/** Free a struct http_ssi_state. */ +static void +http_ssi_state_free(struct http_ssi_state *ssi) +{ + if (ssi != NULL) { + HTTP_FREE_SSI_STATE(ssi); + } +} +#endif /* LWIP_HTTPD_SSI */ + +/** Initialize a struct http_state. + */ +static void +http_state_init(struct http_state* hs) +{ + /* Initialize the structure. */ + memset(hs, 0, sizeof(struct http_state)); +#if LWIP_HTTPD_DYNAMIC_HEADERS + /* Indicate that the headers are not yet valid */ + hs->hdr_index = NUM_FILE_HDR_STRINGS; +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ +} + +/** Allocate a struct http_state. */ +static struct http_state* +http_state_alloc(void) +{ + struct http_state *ret = HTTP_ALLOC_HTTP_STATE(); +#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED + if (ret == NULL) { + http_kill_oldest_connection(0); + ret = HTTP_ALLOC_HTTP_STATE(); + } +#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ + if (ret != NULL) { + http_state_init(ret); + http_add_connection(ret); + } + return ret; +} + +/** Free a struct http_state. + * Also frees the file data if dynamic. + */ +static void +http_state_eof(struct http_state *hs) +{ + if(hs->handle) { +#if LWIP_HTTPD_TIMING + u32_t ms_needed = sys_now() - hs->time_started; + u32_t needed = LWIP_MAX(1, (ms_needed/100)); + LWIP_DEBUGF(HTTPD_DEBUG_TIMING, ("httpd: needed %"U32_F" ms to send file of %d bytes -> %"U32_F" bytes/sec\n", + ms_needed, hs->handle->len, ((((u32_t)hs->handle->len) * 10) / needed))); +#endif /* LWIP_HTTPD_TIMING */ + fs_close(hs->handle); + hs->handle = NULL; + } +#if LWIP_HTTPD_DYNAMIC_FILE_READ + if (hs->buf != NULL) { + mem_free(hs->buf); + hs->buf = NULL; + } +#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ +#if LWIP_HTTPD_SSI + if (hs->ssi) { + http_ssi_state_free(hs->ssi); + hs->ssi = NULL; + } +#endif /* LWIP_HTTPD_SSI */ +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + if (hs->req) { + pbuf_free(hs->req); + hs->req = NULL; + } +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ +} + +/** Free a struct http_state. + * Also frees the file data if dynamic. + */ +static void +http_state_free(struct http_state *hs) +{ + if (hs != NULL) { + http_state_eof(hs); + http_remove_connection(hs); + HTTP_FREE_HTTP_STATE(hs); + } +} + +/** Call tcp_write() in a loop trying smaller and smaller length + * + * @param pcb tcp_pcb to send + * @param ptr Data to send + * @param length Length of data to send (in/out: on return, contains the + * amount of data sent) + * @param apiflags directly passed to tcp_write + * @return the return value of tcp_write + */ +static err_t +http_write(struct tcp_pcb *pcb, const void* ptr, u16_t *length, u8_t apiflags) +{ + u16_t len, max_len; + err_t err; + LWIP_ASSERT("length != NULL", length != NULL); + len = *length; + if (len == 0) { + return ERR_OK; + } + /* We cannot send more data than space available in the send buffer. */ + max_len = tcp_sndbuf(pcb); + if (max_len < len) { + len = max_len; + } +#ifdef HTTPD_MAX_WRITE_LEN + /* Additional limitation: e.g. don't enqueue more than 2*mss at once */ + max_len = HTTPD_MAX_WRITE_LEN(pcb); + if(len > max_len) { + len = max_len; + } +#endif /* HTTPD_MAX_WRITE_LEN */ + do { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Trying go send %d bytes\n", len)); + err = tcp_write(pcb, ptr, len, apiflags); + if (err == ERR_MEM) { + if ((tcp_sndbuf(pcb) == 0) || + (tcp_sndqueuelen(pcb) >= TCP_SND_QUEUELEN)) { + /* no need to try smaller sizes */ + len = 1; + } else { + len /= 2; + } + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, + ("Send failed, trying less (%d bytes)\n", len)); + } + } while ((err == ERR_MEM) && (len > 1)); + + if (err == ERR_OK) { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Sent %d bytes\n", len)); + *length = len; + } else { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Send failed with err %d (\"%s\")\n", err, lwip_strerr(err))); + *length = 0; + } + +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + /* ensure nagle is normally enabled (only disabled for persistent connections + when all data has been enqueued but the connection stays open for the next + request */ + tcp_nagle_enable(pcb); +#endif + + return err; +} + +/** + * The connection shall be actively closed (using RST to close from fault states). + * Reset the sent- and recv-callbacks. + * + * @param pcb the tcp pcb to reset callbacks + * @param hs connection state to free + */ +static err_t +http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn) +{ + err_t err; + LWIP_DEBUGF(HTTPD_DEBUG, ("Closing connection %p\n", (void*)pcb)); + +#if LWIP_HTTPD_SUPPORT_POST + if (hs != NULL) { + if ((hs->post_content_len_left != 0) +#if LWIP_HTTPD_POST_MANUAL_WND + || ((hs->no_auto_wnd != 0) && (hs->unrecved_bytes != 0)) +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + ) { + /* make sure the post code knows that the connection is closed */ + http_uri_buf[0] = 0; + httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN); + } + } +#endif /* LWIP_HTTPD_SUPPORT_POST*/ + + + tcp_arg(pcb, NULL); + tcp_recv(pcb, NULL); + tcp_err(pcb, NULL); + tcp_poll(pcb, NULL, 0); + tcp_sent(pcb, NULL); + if (hs != NULL) { + http_state_free(hs); + } + + if (abort_conn) { + tcp_abort(pcb); + return ERR_OK; + } + err = tcp_close(pcb); + if (err != ERR_OK) { + LWIP_DEBUGF(HTTPD_DEBUG, ("Error %d closing %p\n", err, (void*)pcb)); + /* error closing, try again later in poll */ + tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL); + } + return err; +} + +/** + * The connection shall be actively closed. + * Reset the sent- and recv-callbacks. + * + * @param pcb the tcp pcb to reset callbacks + * @param hs connection state to free + */ +static err_t +http_close_conn(struct tcp_pcb *pcb, struct http_state *hs) +{ + return http_close_or_abort_conn(pcb, hs, 0); +} + +/** End of file: either close the connection (Connection: close) or + * close the file (Connection: keep-alive) + */ +static void +http_eof(struct tcp_pcb *pcb, struct http_state *hs) +{ + /* HTTP/1.1 persistent connection? (Not supported for SSI) */ +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + if (hs->keepalive) { + http_remove_connection(hs); + + http_state_eof(hs); + http_state_init(hs); + /* restore state: */ + hs->pcb = pcb; + hs->keepalive = 1; + http_add_connection(hs); + /* ensure nagle doesn't interfere with sending all data as fast as possible: */ + tcp_nagle_disable(pcb); + } else +#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ + { + http_close_conn(pcb, hs); + } +} + +#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI +/** + * Extract URI parameters from the parameter-part of an URI in the form + * "test.cgi?x=y" @todo: better explanation! + * Pointers to the parameters are stored in hs->param_vals. + * + * @param hs http connection state + * @param params pointer to the NULL-terminated parameter string from the URI + * @return number of parameters extracted + */ +static int +extract_uri_parameters(struct http_state *hs, char *params) +{ + char *pair; + char *equals; + int loop; + + LWIP_UNUSED_ARG(hs); + + /* If we have no parameters at all, return immediately. */ + if(!params || (params[0] == '\0')) { + return(0); + } + + /* Get a pointer to our first parameter */ + pair = params; + + /* Parse up to LWIP_HTTPD_MAX_CGI_PARAMETERS from the passed string and ignore the + * remainder (if any) */ + for(loop = 0; (loop < LWIP_HTTPD_MAX_CGI_PARAMETERS) && pair; loop++) { + + /* Save the name of the parameter */ + http_cgi_params[loop] = pair; + + /* Remember the start of this name=value pair */ + equals = pair; + + /* Find the start of the next name=value pair and replace the delimiter + * with a 0 to terminate the previous pair string. */ + pair = strchr(pair, '&'); + if(pair) { + *pair = '\0'; + pair++; + } else { + /* We didn't find a new parameter so find the end of the URI and + * replace the space with a '\0' */ + pair = strchr(equals, ' '); + if(pair) { + *pair = '\0'; + } + + /* Revert to NULL so that we exit the loop as expected. */ + pair = NULL; + } + + /* Now find the '=' in the previous pair, replace it with '\0' and save + * the parameter value string. */ + equals = strchr(equals, '='); + if(equals) { + *equals = '\0'; + http_cgi_param_vals[loop] = equals + 1; + } else { + http_cgi_param_vals[loop] = NULL; + } + } + + return loop; +} +#endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */ + +#if LWIP_HTTPD_SSI +/** + * Insert a tag (found in an shtml in the form of "" into the file. + * The tag's name is stored in ssi->tag_name (NULL-terminated), the replacement + * should be written to hs->tag_insert (up to a length of LWIP_HTTPD_MAX_TAG_INSERT_LEN). + * The amount of data written is stored to ssi->tag_insert_len. + * + * @todo: return tag_insert_len - maybe it can be removed from struct http_state? + * + * @param hs http connection state + */ +static void +get_tag_insert(struct http_state *hs) +{ +#if LWIP_HTTPD_SSI_RAW + const char* tag; +#else /* LWIP_HTTPD_SSI_RAW */ + int tag; +#endif /* LWIP_HTTPD_SSI_RAW */ + size_t len; + struct http_ssi_state *ssi; +#if LWIP_HTTPD_SSI_MULTIPART + u16_t current_tag_part; +#endif /* LWIP_HTTPD_SSI_MULTIPART */ + + LWIP_ASSERT("hs != NULL", hs != NULL); + ssi = hs->ssi; + LWIP_ASSERT("ssi != NULL", ssi != NULL); +#if LWIP_HTTPD_SSI_MULTIPART + current_tag_part = ssi->tag_part; + ssi->tag_part = HTTPD_LAST_TAG_PART; +#endif /* LWIP_HTTPD_SSI_MULTIPART */ +#if LWIP_HTTPD_SSI_RAW + tag = ssi->tag_name; +#endif + + if(g_pfnSSIHandler +#if !LWIP_HTTPD_SSI_RAW + && g_ppcTags && g_iNumTags +#endif /* !LWIP_HTTPD_SSI_RAW */ + ) { + + /* Find this tag in the list we have been provided. */ +#if LWIP_HTTPD_SSI_RAW + { +#else /* LWIP_HTTPD_SSI_RAW */ + for(tag = 0; tag < g_iNumTags; tag++) { + if(strcmp(ssi->tag_name, g_ppcTags[tag]) == 0) +#endif /* LWIP_HTTPD_SSI_RAW */ + { + ssi->tag_insert_len = g_pfnSSIHandler(tag, ssi->tag_insert, + LWIP_HTTPD_MAX_TAG_INSERT_LEN +#if LWIP_HTTPD_SSI_MULTIPART + , current_tag_part, &ssi->tag_part +#endif /* LWIP_HTTPD_SSI_MULTIPART */ +#if LWIP_HTTPD_FILE_STATE + , (hs->handle ? hs->handle->state : NULL) +#endif /* LWIP_HTTPD_FILE_STATE */ + ); +#if LWIP_HTTPD_SSI_RAW + if (ssi->tag_insert_len != HTTPD_SSI_TAG_UNKNOWN) +#endif /* LWIP_HTTPD_SSI_RAW */ + { + return; + } + } + } + } + + /* If we drop out, we were asked to serve a page which contains tags that + * we don't have a handler for. Merely echo back the tags with an error + * marker. */ +#define UNKNOWN_TAG1_TEXT "***UNKNOWN TAG " +#define UNKNOWN_TAG1_LEN 18 +#define UNKNOWN_TAG2_TEXT "***" +#define UNKNOWN_TAG2_LEN 7 + len = LWIP_MIN(sizeof(ssi->tag_name), LWIP_MIN(strlen(ssi->tag_name), + LWIP_HTTPD_MAX_TAG_INSERT_LEN - (UNKNOWN_TAG1_LEN + UNKNOWN_TAG2_LEN))); + MEMCPY(ssi->tag_insert, UNKNOWN_TAG1_TEXT, UNKNOWN_TAG1_LEN); + MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN], ssi->tag_name, len); + MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN + len], UNKNOWN_TAG2_TEXT, UNKNOWN_TAG2_LEN); + ssi->tag_insert[UNKNOWN_TAG1_LEN + len + UNKNOWN_TAG2_LEN] = 0; + + len = strlen(ssi->tag_insert); + LWIP_ASSERT("len <= 0xffff", len <= 0xffff); + ssi->tag_insert_len = (u16_t)len; +} +#endif /* LWIP_HTTPD_SSI */ + +#if LWIP_HTTPD_DYNAMIC_HEADERS +/** + * Generate the relevant HTTP headers for the given filename and write + * them into the supplied buffer. + */ +static void +get_http_headers(struct http_state *hs, const char *uri) +{ + size_t content_type; + char *tmp; + char *ext; + char *vars; + u8_t add_content_len; + + /* In all cases, the second header we send is the server identification + so set it here. */ + hs->hdrs[HDR_STRINGS_IDX_SERVER_NAME] = g_psHTTPHeaderStrings[HTTP_HDR_SERVER]; + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = NULL; + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = NULL; + + /* Is this a normal file or the special case we use to send back the + default "404: Page not found" response? */ + if (uri == NULL) { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND]; +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + if (hs->keepalive) { + hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML_PERSISTENT]; + } else +#endif + { + hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML]; + } + + /* Set up to send the first header string. */ + hs->hdr_index = 0; + hs->hdr_pos = 0; + return; + } + /* We are dealing with a particular filename. Look for one other + special case. We assume that any filename with "404" in it must be + indicative of a 404 server error whereas all other files require + the 200 OK header. */ + if (strstr(uri, "404")) { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND]; + } else if (strstr(uri, "400")) { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_BAD_REQUEST]; + } else if (strstr(uri, "501")) { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_IMPL]; + } else { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_OK]; + } + + /* Determine if the URI has any variables and, if so, temporarily remove + them. */ + vars = strchr(uri, '?'); + if(vars) { + *vars = '\0'; + } + + /* Get a pointer to the file extension. We find this by looking for the + last occurrence of "." in the filename passed. */ + ext = NULL; + tmp = strchr(uri, '.'); + while (tmp) { + ext = tmp + 1; + tmp = strchr(ext, '.'); + } + if (ext != NULL) { + /* Now determine the content type and add the relevant header for that. */ + for (content_type = 0; content_type < NUM_HTTP_HEADERS; content_type++) { + /* Have we found a matching extension? */ + if(!lwip_stricmp(g_psHTTPHeaders[content_type].extension, ext)) { + break; + } + } + } else { + content_type = NUM_HTTP_HEADERS; + } + + /* Reinstate the parameter marker if there was one in the original URI. */ + if (vars) { + *vars = '?'; + } + +#if LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI + /* Does the URL passed have any file extension? If not, we assume it + is a special-case URL used for control state notification and we do + not send any HTTP headers with the response. */ + if (!ext) { + /* Force the header index to a value indicating that all headers + have already been sent. */ + hs->hdr_index = NUM_FILE_HDR_STRINGS; + return; + } +#endif /* LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI */ + add_content_len = 1; + /* Did we find a matching extension? */ + if(content_type < NUM_HTTP_HEADERS) { + /* yes, store it */ + hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaders[content_type].content_type; + } else if (!ext) { + /* no, no extension found -> use binary transfer to prevent the browser adding '.txt' on save */ + hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_APP; + } else { + /* No - use the default, plain text file type. */ + hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_DEFAULT_TYPE; + } + /* Add content-length header? */ +#if LWIP_HTTPD_SSI + if (hs->ssi != NULL) { + add_content_len = 0; /* @todo: get maximum file length from SSI */ + } else +#endif /* LWIP_HTTPD_SSI */ + if ((hs->handle == NULL) || + ((hs->handle->flags & (FS_FILE_FLAGS_HEADER_INCLUDED|FS_FILE_FLAGS_HEADER_PERSISTENT)) == FS_FILE_FLAGS_HEADER_INCLUDED)) { + add_content_len = 0; + } + if (add_content_len) { + size_t len; + lwip_itoa(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE, + hs->handle->len); + len = strlen(hs->hdr_content_len); + if (len <= LWIP_HTTPD_MAX_CONTENT_LEN_SIZE - LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) { + SMEMCPY(&hs->hdr_content_len[len], CRLF "\0", 3); + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = hs->hdr_content_len; + } else { + add_content_len = 0; + } + } +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + if (add_content_len) { + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_KEEPALIVE_LEN]; + } else { + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; + } +#else /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ + if (add_content_len) { + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; + } +#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ + + /* Set up to send the first header string. */ + hs->hdr_index = 0; + hs->hdr_pos = 0; +} + +/** Sub-function of http_send(): send dynamic headers + * + * @returns: - HTTP_NO_DATA_TO_SEND: no new data has been enqueued + * - HTTP_DATA_TO_SEND_CONTINUE: continue with sending HTTP body + * - HTTP_DATA_TO_SEND_BREAK: data has been enqueued, headers pending, + * so don't send HTTP body yet + */ +static u8_t +http_send_headers(struct tcp_pcb *pcb, struct http_state *hs) +{ + err_t err; + u16_t len; + u8_t data_to_send = HTTP_NO_DATA_TO_SEND; + u16_t hdrlen, sendlen; + + /* How much data can we send? */ + len = tcp_sndbuf(pcb); + sendlen = len; + + while(len && (hs->hdr_index < NUM_FILE_HDR_STRINGS) && sendlen) { + const void *ptr; + u16_t old_sendlen; + u8_t apiflags; + /* How much do we have to send from the current header? */ + hdrlen = (u16_t)strlen(hs->hdrs[hs->hdr_index]); + + /* How much of this can we send? */ + sendlen = (len < (hdrlen - hs->hdr_pos)) ? len : (hdrlen - hs->hdr_pos); + + /* Send this amount of data or as much as we can given memory + * constraints. */ + ptr = (const void *)(hs->hdrs[hs->hdr_index] + hs->hdr_pos); + old_sendlen = sendlen; + apiflags = HTTP_IS_HDR_VOLATILE(hs, ptr); + if (hs->hdr_index == HDR_STRINGS_IDX_CONTENT_LEN_NR) { + /* content-length is always volatile */ + apiflags |= TCP_WRITE_FLAG_COPY; + } + if (hs->hdr_index < NUM_FILE_HDR_STRINGS - 1) { + apiflags |= TCP_WRITE_FLAG_MORE; + } + err = http_write(pcb, ptr, &sendlen, apiflags); + if ((err == ERR_OK) && (old_sendlen != sendlen)) { + /* Remember that we added some more data to be transmitted. */ + data_to_send = HTTP_DATA_TO_SEND_CONTINUE; + } else if (err != ERR_OK) { + /* special case: http_write does not try to send 1 byte */ + sendlen = 0; + } + + /* Fix up the header position for the next time round. */ + hs->hdr_pos += sendlen; + len -= sendlen; + + /* Have we finished sending this string? */ + if(hs->hdr_pos == hdrlen) { + /* Yes - move on to the next one */ + hs->hdr_index++; + /* skip headers that are NULL (not all headers are required) */ + while ((hs->hdr_index < NUM_FILE_HDR_STRINGS) && + (hs->hdrs[hs->hdr_index] == NULL)) { + hs->hdr_index++; + } + hs->hdr_pos = 0; + } + } + + if ((hs->hdr_index >= NUM_FILE_HDR_STRINGS) && (hs->file == NULL)) { + /* When we are at the end of the headers, check for data to send + * instead of waiting for ACK from remote side to continue + * (which would happen when sending files from async read). */ + if(http_check_eof(pcb, hs)) { + data_to_send = HTTP_DATA_TO_SEND_CONTINUE; + } + } + /* If we get here and there are still header bytes to send, we send + * the header information we just wrote immediately. If there are no + * more headers to send, but we do have file data to send, drop through + * to try to send some file data too. */ + if((hs->hdr_index < NUM_FILE_HDR_STRINGS) || !hs->file) { + LWIP_DEBUGF(HTTPD_DEBUG, ("tcp_output\n")); + return HTTP_DATA_TO_SEND_BREAK; + } + return data_to_send; +} +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ + +/** Sub-function of http_send(): end-of-file (or block) is reached, + * either close the file or read the next block (if supported). + * + * @returns: 0 if the file is finished or no data has been read + * 1 if the file is not finished and data has been read + */ +static u8_t +http_check_eof(struct tcp_pcb *pcb, struct http_state *hs) +{ + int bytes_left; +#if LWIP_HTTPD_DYNAMIC_FILE_READ + int count; +#ifdef HTTPD_MAX_WRITE_LEN + int max_write_len; +#endif /* HTTPD_MAX_WRITE_LEN */ +#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ + + /* Do we have a valid file handle? */ + if (hs->handle == NULL) { + /* No - close the connection. */ + http_eof(pcb, hs); + return 0; + } + bytes_left = fs_bytes_left(hs->handle); + if (bytes_left <= 0) { + /* We reached the end of the file so this request is done. */ + LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); + http_eof(pcb, hs); + return 0; + } +#if LWIP_HTTPD_DYNAMIC_FILE_READ + /* Do we already have a send buffer allocated? */ + if(hs->buf) { + /* Yes - get the length of the buffer */ + count = LWIP_MIN(hs->buf_len, bytes_left); + } else { + /* We don't have a send buffer so allocate one now */ + count = tcp_sndbuf(pcb); + if(bytes_left < count) { + count = bytes_left; + } +#ifdef HTTPD_MAX_WRITE_LEN + /* Additional limitation: e.g. don't enqueue more than 2*mss at once */ + max_write_len = HTTPD_MAX_WRITE_LEN(pcb); + if (count > max_write_len) { + count = max_write_len; + } +#endif /* HTTPD_MAX_WRITE_LEN */ + do { + hs->buf = (char*)mem_malloc((mem_size_t)count); + if (hs->buf != NULL) { + hs->buf_len = count; + break; + } + count = count / 2; + } while (count > 100); + + /* Did we get a send buffer? If not, return immediately. */ + if (hs->buf == NULL) { + LWIP_DEBUGF(HTTPD_DEBUG, ("No buff\n")); + return 0; + } + } + + /* Read a block of data from the file. */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Trying to read %d bytes.\n", count)); + +#if LWIP_HTTPD_FS_ASYNC_READ + count = fs_read_async(hs->handle, hs->buf, count, http_continue, hs); +#else /* LWIP_HTTPD_FS_ASYNC_READ */ + count = fs_read(hs->handle, hs->buf, count); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + if (count < 0) { + if (count == FS_READ_DELAYED) { + /* Delayed read, wait for FS to unblock us */ + return 0; + } + /* We reached the end of the file so this request is done. + * @todo: close here for HTTP/1.1 when reading file fails */ + LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); + http_eof(pcb, hs); + return 0; + } + + /* Set up to send the block of data we just read */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Read %d bytes.\n", count)); + hs->left = count; + hs->file = hs->buf; +#if LWIP_HTTPD_SSI + if (hs->ssi) { + hs->ssi->parse_left = count; + hs->ssi->parsed = hs->buf; + } +#endif /* LWIP_HTTPD_SSI */ +#else /* LWIP_HTTPD_DYNAMIC_FILE_READ */ + LWIP_ASSERT("SSI and DYNAMIC_HEADERS turned off but eof not reached", 0); +#endif /* LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS */ + return 1; +} + +/** Sub-function of http_send(): This is the normal send-routine for non-ssi files + * + * @returns: - 1: data has been written (so call tcp_ouput) + * - 0: no data has been written (no need to call tcp_output) + */ +static u8_t +http_send_data_nonssi(struct tcp_pcb *pcb, struct http_state *hs) +{ + err_t err; + u16_t len; + u8_t data_to_send = 0; + + /* We are not processing an SHTML file so no tag checking is necessary. + * Just send the data as we received it from the file. */ + len = (u16_t)LWIP_MIN(hs->left, 0xffff); + + err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); + if (err == ERR_OK) { + data_to_send = 1; + hs->file += len; + hs->left -= len; + } + + return data_to_send; +} + +#if LWIP_HTTPD_SSI +/** Sub-function of http_send(): This is the send-routine for ssi files + * + * @returns: - 1: data has been written (so call tcp_ouput) + * - 0: no data has been written (no need to call tcp_output) + */ +static u8_t +http_send_data_ssi(struct tcp_pcb *pcb, struct http_state *hs) +{ + err_t err = ERR_OK; + u16_t len; + u8_t data_to_send = 0; + + struct http_ssi_state *ssi = hs->ssi; + LWIP_ASSERT("ssi != NULL", ssi != NULL); + /* We are processing an SHTML file so need to scan for tags and replace + * them with insert strings. We need to be careful here since a tag may + * straddle the boundary of two blocks read from the file and we may also + * have to split the insert string between two tcp_write operations. */ + + /* How much data could we send? */ + len = tcp_sndbuf(pcb); + + /* Do we have remaining data to send before parsing more? */ + if(ssi->parsed > hs->file) { + len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff); + + err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); + if (err == ERR_OK) { + data_to_send = 1; + hs->file += len; + hs->left -= len; + } + + /* If the send buffer is full, return now. */ + if(tcp_sndbuf(pcb) == 0) { + return data_to_send; + } + } + + LWIP_DEBUGF(HTTPD_DEBUG, ("State %d, %d left\n", ssi->tag_state, (int)ssi->parse_left)); + + /* We have sent all the data that was already parsed so continue parsing + * the buffer contents looking for SSI tags. */ + while((ssi->parse_left) && (err == ERR_OK)) { + if (len == 0) { + return data_to_send; + } + switch(ssi->tag_state) { + case TAG_NONE: + /* We are not currently processing an SSI tag so scan for the + * start of the lead-in marker. */ + if(*ssi->parsed == g_pcTagLeadIn[0]) { + /* We found what could be the lead-in for a new tag so change + * state appropriately. */ + ssi->tag_state = TAG_LEADIN; + ssi->tag_index = 1; +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + ssi->tag_started = ssi->parsed; +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */ + } + + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + break; + + case TAG_LEADIN: + /* We are processing the lead-in marker, looking for the start of + * the tag name. */ + + /* Have we reached the end of the leadin? */ + if(ssi->tag_index == LEN_TAG_LEAD_IN) { + ssi->tag_index = 0; + ssi->tag_state = TAG_FOUND; + } else { + /* Have we found the next character we expect for the tag leadin? */ + if(*ssi->parsed == g_pcTagLeadIn[ssi->tag_index]) { + /* Yes - move to the next one unless we have found the complete + * leadin, in which case we start looking for the tag itself */ + ssi->tag_index++; + } else { + /* We found an unexpected character so this is not a tag. Move + * back to idle state. */ + ssi->tag_state = TAG_NONE; + } + + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + } + break; + + case TAG_FOUND: + /* We are reading the tag name, looking for the start of the + * lead-out marker and removing any whitespace found. */ + + /* Remove leading whitespace between the tag leading and the first + * tag name character. */ + if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') || + (*ssi->parsed == '\t') || (*ssi->parsed == '\n') || + (*ssi->parsed == '\r'))) { + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + break; + } + + /* Have we found the end of the tag name? This is signalled by + * us finding the first leadout character or whitespace */ + if((*ssi->parsed == g_pcTagLeadOut[0]) || + (*ssi->parsed == ' ') || (*ssi->parsed == '\t') || + (*ssi->parsed == '\n') || (*ssi->parsed == '\r')) { + + if(ssi->tag_index == 0) { + /* We read a zero length tag so ignore it. */ + ssi->tag_state = TAG_NONE; + } else { + /* We read a non-empty tag so go ahead and look for the + * leadout string. */ + ssi->tag_state = TAG_LEADOUT; + LWIP_ASSERT("ssi->tag_index <= 0xff", ssi->tag_index <= 0xff); + ssi->tag_name_len = (u8_t)ssi->tag_index; + ssi->tag_name[ssi->tag_index] = '\0'; + if(*ssi->parsed == g_pcTagLeadOut[0]) { + ssi->tag_index = 1; + } else { + ssi->tag_index = 0; + } + } + } else { + /* This character is part of the tag name so save it */ + if(ssi->tag_index < LWIP_HTTPD_MAX_TAG_NAME_LEN) { + ssi->tag_name[ssi->tag_index++] = *ssi->parsed; + } else { + /* The tag was too long so ignore it. */ + ssi->tag_state = TAG_NONE; + } + } + + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + + break; + + /* We are looking for the end of the lead-out marker. */ + case TAG_LEADOUT: + /* Remove leading whitespace between the tag leading and the first + * tag leadout character. */ + if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') || + (*ssi->parsed == '\t') || (*ssi->parsed == '\n') || + (*ssi->parsed == '\r'))) { + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + break; + } + + /* Have we found the next character we expect for the tag leadout? */ + if(*ssi->parsed == g_pcTagLeadOut[ssi->tag_index]) { + /* Yes - move to the next one unless we have found the complete + * leadout, in which case we need to call the client to process + * the tag. */ + + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + + if(ssi->tag_index == (LEN_TAG_LEAD_OUT - 1)) { + /* Call the client to ask for the insert string for the + * tag we just found. */ +#if LWIP_HTTPD_SSI_MULTIPART + ssi->tag_part = 0; /* start with tag part 0 */ +#endif /* LWIP_HTTPD_SSI_MULTIPART */ + get_tag_insert(hs); + + /* Next time through, we are going to be sending data + * immediately, either the end of the block we start + * sending here or the insert string. */ + ssi->tag_index = 0; + ssi->tag_state = TAG_SENDING; + ssi->tag_end = ssi->parsed; +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + ssi->parsed = ssi->tag_started; +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ + + /* If there is any unsent data in the buffer prior to the + * tag, we need to send it now. */ + if (ssi->tag_end > hs->file) { + /* How much of the data can we send? */ +#if LWIP_HTTPD_SSI_INCLUDE_TAG + len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff); +#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ + /* we would include the tag in sending */ + len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff); +#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ + + err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); + if (err == ERR_OK) { + data_to_send = 1; +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + if(ssi->tag_started <= hs->file) { + /* pretend to have sent the tag, too */ + len += ssi->tag_end - ssi->tag_started; + } +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ + hs->file += len; + hs->left -= len; + } + } + } else { + ssi->tag_index++; + } + } else { + /* We found an unexpected character so this is not a tag. Move + * back to idle state. */ + ssi->parse_left--; + ssi->parsed++; + ssi->tag_state = TAG_NONE; + } + break; + + /* + * We have found a valid tag and are in the process of sending + * data as a result of that discovery. We send either remaining data + * from the file prior to the insert point or the insert string itself. + */ + case TAG_SENDING: + /* Do we have any remaining file data to send from the buffer prior + * to the tag? */ + if(ssi->tag_end > hs->file) { + /* How much of the data can we send? */ +#if LWIP_HTTPD_SSI_INCLUDE_TAG + len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff); +#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ + LWIP_ASSERT("hs->started >= hs->file", ssi->tag_started >= hs->file); + /* we would include the tag in sending */ + len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff); +#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ + if (len != 0) { + err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); + } else { + err = ERR_OK; + } + if (err == ERR_OK) { + data_to_send = 1; +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + if(ssi->tag_started <= hs->file) { + /* pretend to have sent the tag, too */ + len += ssi->tag_end - ssi->tag_started; + } +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ + hs->file += len; + hs->left -= len; + } + } else { +#if LWIP_HTTPD_SSI_MULTIPART + if(ssi->tag_index >= ssi->tag_insert_len) { + /* Did the last SSIHandler have more to send? */ + if (ssi->tag_part != HTTPD_LAST_TAG_PART) { + /* If so, call it again */ + ssi->tag_index = 0; + get_tag_insert(hs); + } + } +#endif /* LWIP_HTTPD_SSI_MULTIPART */ + + /* Do we still have insert data left to send? */ + if(ssi->tag_index < ssi->tag_insert_len) { + /* We are sending the insert string itself. How much of the + * insert can we send? */ + len = (ssi->tag_insert_len - ssi->tag_index); + + /* Note that we set the copy flag here since we only have a + * single tag insert buffer per connection. If we don't do + * this, insert corruption can occur if more than one insert + * is processed before we call tcp_output. */ + err = http_write(pcb, &(ssi->tag_insert[ssi->tag_index]), &len, + HTTP_IS_TAG_VOLATILE(hs)); + if (err == ERR_OK) { + data_to_send = 1; + ssi->tag_index += len; + /* Don't return here: keep on sending data */ + } + } else { +#if LWIP_HTTPD_SSI_MULTIPART + if (ssi->tag_part == HTTPD_LAST_TAG_PART) +#endif /* LWIP_HTTPD_SSI_MULTIPART */ + { + /* We have sent all the insert data so go back to looking for + * a new tag. */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Everything sent.\n")); + ssi->tag_index = 0; + ssi->tag_state = TAG_NONE; +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + ssi->parsed = ssi->tag_end; +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ + } + } + break; + default: + break; + } + } + } + + /* If we drop out of the end of the for loop, this implies we must have + * file data to send so send it now. In TAG_SENDING state, we've already + * handled this so skip the send if that's the case. */ + if((ssi->tag_state != TAG_SENDING) && (ssi->parsed > hs->file)) { + len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff); + + err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); + if (err == ERR_OK) { + data_to_send = 1; + hs->file += len; + hs->left -= len; + } + } + return data_to_send; +} +#endif /* LWIP_HTTPD_SSI */ + +/** + * Try to send more data on this pcb. + * + * @param pcb the pcb to send data + * @param hs connection state + */ +static u8_t +http_send(struct tcp_pcb *pcb, struct http_state *hs) +{ + u8_t data_to_send = HTTP_NO_DATA_TO_SEND; + + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_send: pcb=%p hs=%p left=%d\n", (void*)pcb, + (void*)hs, hs != NULL ? (int)hs->left : 0)); + +#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND + if (hs->unrecved_bytes != 0) { + return 0; + } +#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ + + /* If we were passed a NULL state structure pointer, ignore the call. */ + if (hs == NULL) { + return 0; + } + +#if LWIP_HTTPD_FS_ASYNC_READ + /* Check if we are allowed to read from this file. + (e.g. SSI might want to delay sending until data is available) */ + if (!fs_is_file_ready(hs->handle, http_continue, hs)) { + return 0; + } +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + +#if LWIP_HTTPD_DYNAMIC_HEADERS + /* Do we have any more header data to send for this file? */ + if (hs->hdr_index < NUM_FILE_HDR_STRINGS) { + data_to_send = http_send_headers(pcb, hs); + if ((data_to_send != HTTP_DATA_TO_SEND_CONTINUE) && + (hs->hdr_index < NUM_FILE_HDR_STRINGS)) { + return data_to_send; + } + } +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ + + /* Have we run out of file data to send? If so, we need to read the next + * block from the file. */ + if (hs->left == 0) { + if (!http_check_eof(pcb, hs)) { + return 0; + } + } + +#if LWIP_HTTPD_SSI + if(hs->ssi) { + data_to_send = http_send_data_ssi(pcb, hs); + } else +#endif /* LWIP_HTTPD_SSI */ + { + data_to_send = http_send_data_nonssi(pcb, hs); + } + + if((hs->left == 0) && (fs_bytes_left(hs->handle) <= 0)) { + /* We reached the end of the file so this request is done. + * This adds the FIN flag right into the last data segment. */ + LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); + http_eof(pcb, hs); + return 0; + } + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("send_data end.\n")); + return data_to_send; +} + +#if LWIP_HTTPD_SUPPORT_EXTSTATUS +/** Initialize a http connection with a file to send for an error message + * + * @param hs http connection state + * @param error_nr HTTP error number + * @return ERR_OK if file was found and hs has been initialized correctly + * another err_t otherwise + */ +static err_t +http_find_error_file(struct http_state *hs, u16_t error_nr) +{ + const char *uri1, *uri2, *uri3; + err_t err; + + if (error_nr == 501) { + uri1 = "/501.html"; + uri2 = "/501.htm"; + uri3 = "/501.shtml"; + } else { + /* 400 (bad request is the default) */ + uri1 = "/400.html"; + uri2 = "/400.htm"; + uri3 = "/400.shtml"; + } + err = fs_open(&hs->file_handle, uri1); + if (err != ERR_OK) { + err = fs_open(&hs->file_handle, uri2); + if (err != ERR_OK) { + err = fs_open(&hs->file_handle, uri3); + if (err != ERR_OK) { + LWIP_DEBUGF(HTTPD_DEBUG, ("Error page for error %"U16_F" not found\n", + error_nr)); + return ERR_ARG; + } + } + } + return http_init_file(hs, &hs->file_handle, 0, NULL, 0, NULL); +} +#else /* LWIP_HTTPD_SUPPORT_EXTSTATUS */ +#define http_find_error_file(hs, error_nr) ERR_ARG +#endif /* LWIP_HTTPD_SUPPORT_EXTSTATUS */ + +/** + * Get the file struct for a 404 error page. + * Tries some file names and returns NULL if none found. + * + * @param uri pointer that receives the actual file name URI + * @return file struct for the error page or NULL no matching file was found + */ +static struct fs_file * +http_get_404_file(struct http_state *hs, const char **uri) +{ + err_t err; + + *uri = "/404.html"; + err = fs_open(&hs->file_handle, *uri); + if (err != ERR_OK) { + /* 404.html doesn't exist. Try 404.htm instead. */ + *uri = "/404.htm"; + err = fs_open(&hs->file_handle, *uri); + if (err != ERR_OK) { + /* 404.htm doesn't exist either. Try 404.shtml instead. */ + *uri = "/404.shtml"; + err = fs_open(&hs->file_handle, *uri); + if (err != ERR_OK) { + /* 404.htm doesn't exist either. Indicate to the caller that it should + * send back a default 404 page. + */ + *uri = NULL; + return NULL; + } + } + } + + return &hs->file_handle; +} + +#if LWIP_HTTPD_SUPPORT_POST +static err_t +http_handle_post_finished(struct http_state *hs) +{ +#if LWIP_HTTPD_POST_MANUAL_WND + /* Prevent multiple calls to httpd_post_finished, since it might have already + been called before from httpd_post_data_recved(). */ + if (hs->post_finished) { + return ERR_OK; + } + hs->post_finished = 1; +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + /* application error or POST finished */ + /* NULL-terminate the buffer */ + http_uri_buf[0] = 0; + httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN); + return http_find_file(hs, http_uri_buf, 0); +} + +/** Pass received POST body data to the application and correctly handle + * returning a response document or closing the connection. + * ATTENTION: The application is responsible for the pbuf now, so don't free it! + * + * @param hs http connection state + * @param p pbuf to pass to the application + * @return ERR_OK if passed successfully, another err_t if the response file + * hasn't been found (after POST finished) + */ +static err_t +http_post_rxpbuf(struct http_state *hs, struct pbuf *p) +{ + err_t err; + + if (p != NULL) { + /* adjust remaining Content-Length */ + if (hs->post_content_len_left < p->tot_len) { + hs->post_content_len_left = 0; + } else { + hs->post_content_len_left -= p->tot_len; + } + } +#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND + /* prevent connection being closed if httpd_post_data_recved() is called nested */ + hs->unrecved_bytes++; +#endif + err = httpd_post_receive_data(hs, p); +#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND + hs->unrecved_bytes--; +#endif + if (err != ERR_OK) { + /* Ignore remaining content in case of application error */ + hs->post_content_len_left = 0; + } + if (hs->post_content_len_left == 0) { +#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND + if (hs->unrecved_bytes != 0) { + return ERR_OK; + } +#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ + /* application error or POST finished */ + return http_handle_post_finished(hs); + } + + return ERR_OK; +} + +/** Handle a post request. Called from http_parse_request when method 'POST' + * is found. + * + * @param p The input pbuf (containing the POST header and body). + * @param hs The http connection state. + * @param data HTTP request (header and part of body) from input pbuf(s). + * @param data_len Size of 'data'. + * @param uri The HTTP URI parsed from input pbuf(s). + * @param uri_end Pointer to the end of 'uri' (here, the rest of the HTTP + * header starts). + * @return ERR_OK: POST correctly parsed and accepted by the application. + * ERR_INPROGRESS: POST not completely parsed (no error yet) + * another err_t: Error parsing POST or denied by the application + */ +static err_t +http_post_request(struct pbuf *inp, struct http_state *hs, + char *data, u16_t data_len, char *uri, char *uri_end) +{ + err_t err; + /* search for end-of-header (first double-CRLF) */ + char* crlfcrlf = lwip_strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data)); + + if (crlfcrlf != NULL) { + /* search for "Content-Length: " */ +#define HTTP_HDR_CONTENT_LEN "Content-Length: " +#define HTTP_HDR_CONTENT_LEN_LEN 16 +#define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN 10 + char *scontent_len = lwip_strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1)); + if (scontent_len != NULL) { + char *scontent_len_end = lwip_strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN); + if (scontent_len_end != NULL) { + int content_len; + char *content_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN; + content_len = atoi(content_len_num); + if (content_len == 0) { + /* if atoi returns 0 on error, fix this */ + if ((content_len_num[0] != '0') || (content_len_num[1] != '\r')) { + content_len = -1; + } + } + if (content_len >= 0) { + /* adjust length of HTTP header passed to application */ + const char *hdr_start_after_uri = uri_end + 1; + u16_t hdr_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - data); + u16_t hdr_data_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri); + u8_t post_auto_wnd = 1; + http_uri_buf[0] = 0; + /* trim http header */ + *crlfcrlf = 0; + err = httpd_post_begin(hs, uri, hdr_start_after_uri, hdr_data_len, content_len, + http_uri_buf, LWIP_HTTPD_URI_BUF_LEN, &post_auto_wnd); + if (err == ERR_OK) { + /* try to pass in data of the first pbuf(s) */ + struct pbuf *q = inp; + u16_t start_offset = hdr_len; +#if LWIP_HTTPD_POST_MANUAL_WND + hs->no_auto_wnd = !post_auto_wnd; +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + /* set the Content-Length to be received for this POST */ + hs->post_content_len_left = (u32_t)content_len; + + /* get to the pbuf where the body starts */ + while((q != NULL) && (q->len <= start_offset)) { + start_offset -= q->len; + q = q->next; + } + if (q != NULL) { + /* hide the remaining HTTP header */ + pbuf_header(q, -(s16_t)start_offset); +#if LWIP_HTTPD_POST_MANUAL_WND + if (!post_auto_wnd) { + /* already tcp_recved() this data... */ + hs->unrecved_bytes = q->tot_len; + } +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + pbuf_ref(q); + return http_post_rxpbuf(hs, q); + } else if (hs->post_content_len_left == 0) { + q = pbuf_alloc(PBUF_RAW, 0, PBUF_REF); + return http_post_rxpbuf(hs, q); + } else { + return ERR_OK; + } + } else { + /* return file passed from application */ + return http_find_file(hs, http_uri_buf, 0); + } + } else { + LWIP_DEBUGF(HTTPD_DEBUG, ("POST received invalid Content-Length: %s\n", + content_len_num)); + return ERR_ARG; + } + } + } + /* If we come here, headers are fully received (double-crlf), but Content-Length + was not included. Since this is currently the only supported method, we have + to fail in this case! */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Error when parsing Content-Length\n")); + return ERR_ARG; + } + /* if we come here, the POST is incomplete */ +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + return ERR_INPROGRESS; +#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + return ERR_ARG; +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ +} + +#if LWIP_HTTPD_POST_MANUAL_WND +/** A POST implementation can call this function to update the TCP window. + * This can be used to throttle data reception (e.g. when received data is + * programmed to flash and data is received faster than programmed). + * + * @param connection A connection handle passed to httpd_post_begin for which + * httpd_post_finished has *NOT* been called yet! + * @param recved_len Length of data received (for window update) + */ +void httpd_post_data_recved(void *connection, u16_t recved_len) +{ + struct http_state *hs = (struct http_state*)connection; + if (hs != NULL) { + if (hs->no_auto_wnd) { + u16_t len = recved_len; + if (hs->unrecved_bytes >= recved_len) { + hs->unrecved_bytes -= recved_len; + } else { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_LEVEL_WARNING, ("httpd_post_data_recved: recved_len too big\n")); + len = (u16_t)hs->unrecved_bytes; + hs->unrecved_bytes = 0; + } + if (hs->pcb != NULL) { + if (len != 0) { + tcp_recved(hs->pcb, len); + } + if ((hs->post_content_len_left == 0) && (hs->unrecved_bytes == 0)) { + /* finished handling POST */ + http_handle_post_finished(hs); + http_send(hs->pcb, hs); + } + } + } + } +} +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + +#endif /* LWIP_HTTPD_SUPPORT_POST */ + +#if LWIP_HTTPD_FS_ASYNC_READ +/** Try to send more data if file has been blocked before + * This is a callback function passed to fs_read_async(). + */ +static void +http_continue(void *connection) +{ + struct http_state *hs = (struct http_state*)connection; + if (hs && (hs->pcb) && (hs->handle)) { + LWIP_ASSERT("hs->pcb != NULL", hs->pcb != NULL); + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("httpd_continue: try to send more data\n")); + if (http_send(hs->pcb, hs)) { + /* If we wrote anything to be sent, go ahead and send it now. */ + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n")); + tcp_output(hs->pcb); + } + } +} +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + +/** + * When data has been received in the correct state, try to parse it + * as a HTTP request. + * + * @param inp the received pbuf + * @param hs the connection state + * @param pcb the tcp_pcb which received this packet + * @return ERR_OK if request was OK and hs has been initialized correctly + * ERR_INPROGRESS if request was OK so far but not fully received + * another err_t otherwise + */ +static err_t +http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb) +{ + char *data; + char *crlf; + u16_t data_len; + struct pbuf *p = inp; +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + u16_t clen; +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ +#if LWIP_HTTPD_SUPPORT_POST + err_t err; +#endif /* LWIP_HTTPD_SUPPORT_POST */ + + LWIP_UNUSED_ARG(pcb); /* only used for post */ + LWIP_ASSERT("p != NULL", p != NULL); + LWIP_ASSERT("hs != NULL", hs != NULL); + + if ((hs->handle != NULL) || (hs->file != NULL)) { + LWIP_DEBUGF(HTTPD_DEBUG, ("Received data while sending a file\n")); + /* already sending a file */ + /* @todo: abort? */ + return ERR_USE; + } + +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + + LWIP_DEBUGF(HTTPD_DEBUG, ("Received %"U16_F" bytes\n", p->tot_len)); + + /* first check allowed characters in this pbuf? */ + + /* enqueue the pbuf */ + if (hs->req == NULL) { + LWIP_DEBUGF(HTTPD_DEBUG, ("First pbuf\n")); + hs->req = p; + } else { + LWIP_DEBUGF(HTTPD_DEBUG, ("pbuf enqueued\n")); + pbuf_cat(hs->req, p); + } + /* increase pbuf ref counter as it is freed when we return but we want to + keep it on the req list */ + pbuf_ref(p); + + if (hs->req->next != NULL) { + data_len = LWIP_MIN(hs->req->tot_len, LWIP_HTTPD_MAX_REQ_LENGTH); + pbuf_copy_partial(hs->req, httpd_req_buf, data_len, 0); + data = httpd_req_buf; + } else +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + { + data = (char *)p->payload; + data_len = p->len; + if (p->len != p->tot_len) { + LWIP_DEBUGF(HTTPD_DEBUG, ("Warning: incomplete header due to chained pbufs\n")); + } + } + + /* received enough data for minimal request? */ + if (data_len >= MIN_REQ_LEN) { + /* wait for CRLF before parsing anything */ + crlf = lwip_strnstr(data, CRLF, data_len); + if (crlf != NULL) { +#if LWIP_HTTPD_SUPPORT_POST + int is_post = 0; +#endif /* LWIP_HTTPD_SUPPORT_POST */ + int is_09 = 0; + char *sp1, *sp2; + u16_t left_len, uri_len; + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("CRLF received, parsing request\n")); + /* parse method */ + if (!strncmp(data, "GET ", 4)) { + sp1 = data + 3; + /* received GET request */ + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received GET request\"\n")); +#if LWIP_HTTPD_SUPPORT_POST + } else if (!strncmp(data, "POST ", 5)) { + /* store request type */ + is_post = 1; + sp1 = data + 4; + /* received GET request */ + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received POST request\n")); +#endif /* LWIP_HTTPD_SUPPORT_POST */ + } else { + /* null-terminate the METHOD (pbuf is freed anyway wen returning) */ + data[4] = 0; + /* unsupported method! */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Unsupported request method (not implemented): \"%s\"\n", + data)); + return http_find_error_file(hs, 501); + } + /* if we come here, method is OK, parse URI */ + left_len = (u16_t)(data_len - ((sp1 +1) - data)); + sp2 = lwip_strnstr(sp1 + 1, " ", left_len); +#if LWIP_HTTPD_SUPPORT_V09 + if (sp2 == NULL) { + /* HTTP 0.9: respond with correct protocol version */ + sp2 = lwip_strnstr(sp1 + 1, CRLF, left_len); + is_09 = 1; +#if LWIP_HTTPD_SUPPORT_POST + if (is_post) { + /* HTTP/0.9 does not support POST */ + goto badrequest; + } +#endif /* LWIP_HTTPD_SUPPORT_POST */ + } +#endif /* LWIP_HTTPD_SUPPORT_V09 */ + uri_len = (u16_t)(sp2 - (sp1 + 1)); + if ((sp2 != 0) && (sp2 > sp1)) { + /* wait for CRLFCRLF (indicating end of HTTP headers) before parsing anything */ + if (lwip_strnstr(data, CRLF CRLF, data_len) != NULL) { + char *uri = sp1 + 1; +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + /* This is HTTP/1.0 compatible: for strict 1.1, a connection + would always be persistent unless "close" was specified. */ + if (!is_09 && (lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) || + lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) { + hs->keepalive = 1; + } else { + hs->keepalive = 0; + } +#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ + /* null-terminate the METHOD (pbuf is freed anyway wen returning) */ + *sp1 = 0; + uri[uri_len] = 0; + LWIP_DEBUGF(HTTPD_DEBUG, ("Received \"%s\" request for URI: \"%s\"\n", + data, uri)); +#if LWIP_HTTPD_SUPPORT_POST + if (is_post) { +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + struct pbuf *q = hs->req; +#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + struct pbuf *q = inp; +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + err = http_post_request(q, hs, data, data_len, uri, sp2); + if (err != ERR_OK) { + /* restore header for next try */ + *sp1 = ' '; + *sp2 = ' '; + uri[uri_len] = ' '; + } + if (err == ERR_ARG) { + goto badrequest; + } + return err; + } else +#endif /* LWIP_HTTPD_SUPPORT_POST */ + { + return http_find_file(hs, uri, is_09); + } + } + } else { + LWIP_DEBUGF(HTTPD_DEBUG, ("invalid URI\n")); + } + } + } + +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + clen = pbuf_clen(hs->req); + if ((hs->req->tot_len <= LWIP_HTTPD_REQ_BUFSIZE) && + (clen <= LWIP_HTTPD_REQ_QUEUELEN)) { + /* request not fully received (too short or CRLF is missing) */ + return ERR_INPROGRESS; + } else +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + { +#if LWIP_HTTPD_SUPPORT_POST +badrequest: +#endif /* LWIP_HTTPD_SUPPORT_POST */ + LWIP_DEBUGF(HTTPD_DEBUG, ("bad request\n")); + /* could not parse request */ + return http_find_error_file(hs, 400); + } +} + +/** Try to find the file specified by uri and, if found, initialize hs + * accordingly. + * + * @param hs the connection state + * @param uri the HTTP header URI + * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) + * @return ERR_OK if file was found and hs has been initialized correctly + * another err_t otherwise + */ +static err_t +http_find_file(struct http_state *hs, const char *uri, int is_09) +{ + size_t loop; + struct fs_file *file = NULL; + char *params = NULL; + err_t err; +#if LWIP_HTTPD_CGI + int i; +#endif /* LWIP_HTTPD_CGI */ +#if !LWIP_HTTPD_SSI + const +#endif /* !LWIP_HTTPD_SSI */ + /* By default, assume we will not be processing server-side-includes tags */ + u8_t tag_check = 0; + + /* Have we been asked for the default file (in root or a directory) ? */ +#if LWIP_HTTPD_MAX_REQUEST_URI_LEN + size_t uri_len = strlen(uri); + if ((uri_len > 0) && (uri[uri_len-1] == '/') && + ((uri != http_uri_buf) || (uri_len == 1))) { + size_t copy_len = LWIP_MIN(sizeof(http_uri_buf) - 1, uri_len - 1); + if (copy_len > 0) { + MEMCPY(http_uri_buf, uri, copy_len); + http_uri_buf[copy_len] = 0; + } +#else /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ + if ((uri[0] == '/') && (uri[1] == 0)) { +#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ + /* Try each of the configured default filenames until we find one + that exists. */ + for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) { + const char* file_name; +#if LWIP_HTTPD_MAX_REQUEST_URI_LEN + if (copy_len > 0) { + size_t len_left = sizeof(http_uri_buf) - copy_len - 1; + if (len_left > 0) { + size_t name_len = strlen(g_psDefaultFilenames[loop].name); + size_t name_copy_len = LWIP_MIN(len_left, name_len); + MEMCPY(&http_uri_buf[copy_len], g_psDefaultFilenames[loop].name, name_copy_len); + } + file_name = http_uri_buf; + } else +#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ + { + file_name = g_psDefaultFilenames[loop].name; + } + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Looking for %s...\n", file_name)); + err = fs_open(&hs->file_handle, file_name); + if(err == ERR_OK) { + uri = file_name; + file = &hs->file_handle; + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opened.\n")); +#if LWIP_HTTPD_SSI + tag_check = g_psDefaultFilenames[loop].shtml; +#endif /* LWIP_HTTPD_SSI */ + break; + } + } + } + if (file == NULL) { + /* No - we've been asked for a specific file. */ + /* First, isolate the base URI (without any parameters) */ + params = (char *)strchr(uri, '?'); + if (params != NULL) { + /* URI contains parameters. NULL-terminate the base URI */ + *params = '\0'; + params++; + } + +#if LWIP_HTTPD_CGI + http_cgi_paramcount = -1; + /* Does the base URI we have isolated correspond to a CGI handler? */ + if (g_iNumCGIs && g_pCGIs) { + for (i = 0; i < g_iNumCGIs; i++) { + if (strcmp(uri, g_pCGIs[i].pcCGIName) == 0) { + /* + * We found a CGI that handles this URI so extract the + * parameters and call the handler. + */ + http_cgi_paramcount = extract_uri_parameters(hs, params); + uri = g_pCGIs[i].pfnCGIHandler(i, http_cgi_paramcount, hs->params, + hs->param_vals); + break; + } + } + } +#endif /* LWIP_HTTPD_CGI */ + + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opening %s\n", uri)); + + err = fs_open(&hs->file_handle, uri); + if (err == ERR_OK) { + file = &hs->file_handle; + } else { + file = http_get_404_file(hs, &uri); + } +#if LWIP_HTTPD_SSI + if (file != NULL) { + /* See if we have been asked for an shtml file and, if so, + enable tag checking. */ + const char* ext = NULL, *sub; + char* param = (char*)strstr(uri, "?"); + if (param != NULL) { + /* separate uri from parameters for now, set back later */ + *param = 0; + } + sub = uri; + ext = uri; + for (sub = strstr(sub, "."); sub != NULL; sub = strstr(sub, ".")) + { + ext = sub; + sub++; + } + tag_check = 0; + for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { + if (!lwip_stricmp(ext, g_pcSSIExtensions[loop])) { + tag_check = 1; + break; + } + } + if (param != NULL) { + *param = '?'; + } + } +#endif /* LWIP_HTTPD_SSI */ + } + if (file == NULL) { + /* None of the default filenames exist so send back a 404 page */ + file = http_get_404_file(hs, &uri); + } + return http_init_file(hs, file, is_09, uri, tag_check, params); +} + +/** Initialize a http connection with a file to send (if found). + * Called by http_find_file and http_find_error_file. + * + * @param hs http connection state + * @param file file structure to send (or NULL if not found) + * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) + * @param uri the HTTP header URI + * @param tag_check enable SSI tag checking + * @param params != NULL if URI has parameters (separated by '?') + * @return ERR_OK if file was found and hs has been initialized correctly + * another err_t otherwise + */ +static err_t +http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, + u8_t tag_check, char* params) +{ + if (file != NULL) { + /* file opened, initialise struct http_state */ +#if LWIP_HTTPD_SSI + if (tag_check) { + struct http_ssi_state *ssi = http_ssi_state_alloc(); + if (ssi != NULL) { + ssi->tag_index = 0; + ssi->tag_state = TAG_NONE; + ssi->parsed = file->data; + ssi->parse_left = file->len; + ssi->tag_end = file->data; + hs->ssi = ssi; + } + } +#else /* LWIP_HTTPD_SSI */ + LWIP_UNUSED_ARG(tag_check); +#endif /* LWIP_HTTPD_SSI */ + hs->handle = file; + hs->file = file->data; + LWIP_ASSERT("File length must be positive!", (file->len >= 0)); +#if LWIP_HTTPD_CUSTOM_FILES + if (file->is_custom_file && (file->data == NULL)) { + /* custom file, need to read data first (via fs_read_custom) */ + hs->left = 0; + } else +#endif /* LWIP_HTTPD_CUSTOM_FILES */ + { + hs->left = file->len; + } + hs->retries = 0; +#if LWIP_HTTPD_TIMING + hs->time_started = sys_now(); +#endif /* LWIP_HTTPD_TIMING */ +#if !LWIP_HTTPD_DYNAMIC_HEADERS + LWIP_ASSERT("HTTP headers not included in file system", + (hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0); +#endif /* !LWIP_HTTPD_DYNAMIC_HEADERS */ +#if LWIP_HTTPD_SUPPORT_V09 + if (is_09 && ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0)) { + /* HTTP/0.9 responses are sent without HTTP header, + search for the end of the header. */ + char *file_start = lwip_strnstr(hs->file, CRLF CRLF, hs->left); + if (file_start != NULL) { + size_t diff = file_start + 4 - hs->file; + hs->file += diff; + hs->left -= (u32_t)diff; + } + } +#endif /* LWIP_HTTPD_SUPPORT_V09*/ +#if LWIP_HTTPD_CGI_SSI + if (params != NULL) { + /* URI contains parameters, call generic CGI handler */ + int count; +#if LWIP_HTTPD_CGI + if (http_cgi_paramcount >= 0) { + count = http_cgi_paramcount; + } else +#endif + { + count = extract_uri_parameters(hs, params); + } + httpd_cgi_handler(uri, count, http_cgi_params, http_cgi_param_vals +#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE + , hs->handle->state +#endif /* LWIP_HTTPD_FILE_STATE */ + ); + } +#else /* LWIP_HTTPD_CGI_SSI */ + LWIP_UNUSED_ARG(params); +#endif /* LWIP_HTTPD_CGI_SSI */ + } else { + hs->handle = NULL; + hs->file = NULL; + hs->left = 0; + hs->retries = 0; + } +#if LWIP_HTTPD_DYNAMIC_HEADERS + /* Determine the HTTP headers to send based on the file extension of + * the requested URI. */ + if ((hs->handle == NULL) || ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) == 0)) { + get_http_headers(hs, uri); + } +#else /* LWIP_HTTPD_DYNAMIC_HEADERS */ + LWIP_UNUSED_ARG(uri); +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + if (hs->keepalive) { +#if LWIP_HTTPD_SSI + if (hs->ssi != NULL) { + hs->keepalive = 0; + } else +#endif /* LWIP_HTTPD_SSI */ + { + if ((hs->handle != NULL) && + ((hs->handle->flags & (FS_FILE_FLAGS_HEADER_INCLUDED|FS_FILE_FLAGS_HEADER_PERSISTENT)) == FS_FILE_FLAGS_HEADER_INCLUDED)) { + hs->keepalive = 0; + } + } + } +#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ + return ERR_OK; +} + +/** + * The pcb had an error and is already deallocated. + * The argument might still be valid (if != NULL). + */ +static void +http_err(void *arg, err_t err) +{ + struct http_state *hs = (struct http_state *)arg; + LWIP_UNUSED_ARG(err); + + LWIP_DEBUGF(HTTPD_DEBUG, ("http_err: %s", lwip_strerr(err))); + + if (hs != NULL) { + http_state_free(hs); + } +} + +/** + * Data has been sent and acknowledged by the remote host. + * This means that more data can be sent. + */ +static err_t +http_sent(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct http_state *hs = (struct http_state *)arg; + + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_sent %p\n", (void*)pcb)); + + LWIP_UNUSED_ARG(len); + + if (hs == NULL) { + return ERR_OK; + } + + hs->retries = 0; + + http_send(pcb, hs); + + return ERR_OK; +} + +/** + * The poll function is called every 2nd second. + * If there has been no data sent (which resets the retries) in 8 seconds, close. + * If the last portion of a file has not been sent in 2 seconds, close. + * + * This could be increased, but we don't want to waste resources for bad connections. + */ +static err_t +http_poll(void *arg, struct tcp_pcb *pcb) +{ + struct http_state *hs = (struct http_state *)arg; + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: pcb=%p hs=%p pcb_state=%s\n", + (void*)pcb, (void*)hs, tcp_debug_state_str(pcb->state))); + + if (hs == NULL) { + err_t closed; + /* arg is null, close. */ + LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: arg is NULL, close\n")); + closed = http_close_conn(pcb, NULL); + LWIP_UNUSED_ARG(closed); +#if LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR + if (closed == ERR_MEM) { + tcp_abort(pcb); + return ERR_ABRT; + } +#endif /* LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR */ + return ERR_OK; + } else { + hs->retries++; + if (hs->retries == HTTPD_MAX_RETRIES) { + LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: too many retries, close\n")); + http_close_conn(pcb, hs); + return ERR_OK; + } + + /* If this connection has a file open, try to send some more data. If + * it has not yet received a GET request, don't do this since it will + * cause the connection to close immediately. */ + if(hs && (hs->handle)) { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: try to send more data\n")); + if(http_send(pcb, hs)) { + /* If we wrote anything to be sent, go ahead and send it now. */ + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n")); + tcp_output(pcb); + } + } + } + + return ERR_OK; +} + +/** + * Data has been received on this pcb. + * For HTTP 1.0, this should normally only happen once (if the request fits in one packet). + */ +static err_t +http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct http_state *hs = (struct http_state *)arg; + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: pcb=%p pbuf=%p err=%s\n", (void*)pcb, + (void*)p, lwip_strerr(err))); + + if ((err != ERR_OK) || (p == NULL) || (hs == NULL)) { + /* error or closed by other side? */ + if (p != NULL) { + /* Inform TCP that we have taken the data. */ + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + if (hs == NULL) { + /* this should not happen, only to be robust */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Error, http_recv: hs is NULL, close\n")); + } + http_close_conn(pcb, hs); + return ERR_OK; + } + +#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND + if (hs->no_auto_wnd) { + hs->unrecved_bytes += p->tot_len; + } else +#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ + { + /* Inform TCP that we have taken the data. */ + tcp_recved(pcb, p->tot_len); + } + +#if LWIP_HTTPD_SUPPORT_POST + if (hs->post_content_len_left > 0) { + /* reset idle counter when POST data is received */ + hs->retries = 0; + /* this is data for a POST, pass the complete pbuf to the application */ + http_post_rxpbuf(hs, p); + /* pbuf is passed to the application, don't free it! */ + if (hs->post_content_len_left == 0) { + /* all data received, send response or close connection */ + http_send(pcb, hs); + } + return ERR_OK; + } else +#endif /* LWIP_HTTPD_SUPPORT_POST */ + { + if (hs->handle == NULL) { + err_t parsed = http_parse_request(p, hs, pcb); + LWIP_ASSERT("http_parse_request: unexpected return value", parsed == ERR_OK + || parsed == ERR_INPROGRESS ||parsed == ERR_ARG || parsed == ERR_USE); +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + if (parsed != ERR_INPROGRESS) { + /* request fully parsed or error */ + if (hs->req != NULL) { + pbuf_free(hs->req); + hs->req = NULL; + } + } +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + pbuf_free(p); + if (parsed == ERR_OK) { +#if LWIP_HTTPD_SUPPORT_POST + if (hs->post_content_len_left == 0) +#endif /* LWIP_HTTPD_SUPPORT_POST */ + { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: data %p len %"S32_F"\n", (const void*)hs->file, hs->left)); + http_send(pcb, hs); + } + } else if (parsed == ERR_ARG) { + /* @todo: close on ERR_USE? */ + http_close_conn(pcb, hs); + } + } else { + LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: already sending data\n")); + /* already sending but still receiving data, we might want to RST here? */ + pbuf_free(p); + } + } + return ERR_OK; +} + +/** + * A new incoming connection has been accepted. + */ +static err_t +http_accept(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct http_state *hs; + LWIP_UNUSED_ARG(err); + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept %p / %p\n", (void*)pcb, arg)); + + if ((err != ERR_OK) || (pcb == NULL)) { + return ERR_VAL; + } + + /* Set priority */ + tcp_setprio(pcb, HTTPD_TCP_PRIO); + + /* Allocate memory for the structure that holds the state of the + connection - initialized by that function. */ + hs = http_state_alloc(); + if (hs == NULL) { + LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept: Out of memory, RST\n")); + return ERR_MEM; + } + hs->pcb = pcb; + + /* Tell TCP that this is the structure we wish to be passed for our + callbacks. */ + tcp_arg(pcb, hs); + + /* Set up the various callback functions */ + tcp_recv(pcb, http_recv); + tcp_err(pcb, http_err); + tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL); + tcp_sent(pcb, http_sent); + + return ERR_OK; +} + +/** + * @ingroup httpd + * Initialize the httpd: set up a listening PCB and bind it to the defined port + */ +void +httpd_init(void) +{ + struct tcp_pcb *pcb; + err_t err; + +#if HTTPD_USE_MEM_POOL + LWIP_MEMPOOL_INIT(HTTPD_STATE); +#if LWIP_HTTPD_SSI + LWIP_MEMPOOL_INIT(HTTPD_SSI_STATE); +#endif +#endif + LWIP_DEBUGF(HTTPD_DEBUG, ("httpd_init\n")); + + pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ASSERT("httpd_init: tcp_new failed", pcb != NULL); + tcp_setprio(pcb, HTTPD_TCP_PRIO); + /* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */ + err = tcp_bind(pcb, IP_ANY_TYPE, HTTPD_SERVER_PORT); + LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK); + pcb = tcp_listen(pcb); + LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL); + tcp_accept(pcb, http_accept); +} + +#if LWIP_HTTPD_SSI +/** + * Set the SSI handler function. + * + * @param ssi_handler the SSI handler function + * @param tags an array of SSI tag strings to search for in SSI-enabled files + * @param num_tags number of tags in the 'tags' array + */ +void +http_set_ssi_handler(tSSIHandler ssi_handler, const char **tags, int num_tags) +{ + LWIP_DEBUGF(HTTPD_DEBUG, ("http_set_ssi_handler\n")); + + LWIP_ASSERT("no ssi_handler given", ssi_handler != NULL); + g_pfnSSIHandler = ssi_handler; + +#if LWIP_HTTPD_SSI_RAW + LWIP_UNUSED_ARG(tags); + LWIP_UNUSED_ARG(num_tags); +#else /* LWIP_HTTPD_SSI_RAW */ + LWIP_ASSERT("no tags given", tags != NULL); + LWIP_ASSERT("invalid number of tags", num_tags > 0); + + g_ppcTags = tags; + g_iNumTags = num_tags; +#endif /* !LWIP_HTTPD_SSI_RAW */ +} +#endif /* LWIP_HTTPD_SSI */ + +#if LWIP_HTTPD_CGI +/** + * Set an array of CGI filenames/handler functions + * + * @param cgis an array of CGI filenames/handler functions + * @param num_handlers number of elements in the 'cgis' array + */ +void +http_set_cgi_handlers(const tCGI *cgis, int num_handlers) +{ + LWIP_ASSERT("no cgis given", cgis != NULL); + LWIP_ASSERT("invalid number of handlers", num_handlers > 0); + + g_pCGIs = cgis; + g_iNumCGIs = num_handlers; +} +#endif /* LWIP_HTTPD_CGI */ + +#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/components/net/lwip-2.0.3/src/apps/httpd/httpd_structs.h b/components/net/lwip-2.0.3/src/apps/httpd/httpd_structs.h new file mode 100644 index 0000000000..fbd135a8c6 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/httpd/httpd_structs.h @@ -0,0 +1,114 @@ +#ifndef LWIP_HTTPD_STRUCTS_H +#define LWIP_HTTPD_STRUCTS_H + +#include "lwip/apps/httpd.h" + +#if LWIP_HTTPD_DYNAMIC_HEADERS +/** This struct is used for a list of HTTP header strings for various + * filename extensions. */ +typedef struct +{ + const char *extension; + const char *content_type; +} tHTTPHeader; + +/** A list of strings used in HTTP headers (see RFC 1945 HTTP/1.0 and + * RFC 2616 HTTP/1.1 for header field definitions) */ +static const char * const g_psHTTPHeaderStrings[] = +{ + "HTTP/1.0 200 OK\r\n", + "HTTP/1.0 404 File not found\r\n", + "HTTP/1.0 400 Bad Request\r\n", + "HTTP/1.0 501 Not Implemented\r\n", + "HTTP/1.1 200 OK\r\n", + "HTTP/1.1 404 File not found\r\n", + "HTTP/1.1 400 Bad Request\r\n", + "HTTP/1.1 501 Not Implemented\r\n", + "Content-Length: ", + "Connection: Close\r\n", + "Connection: keep-alive\r\n", + "Connection: keep-alive\r\nContent-Length: ", + "Server: "HTTPD_SERVER_AGENT"\r\n", + "\r\n

404: The requested file cannot be found.

\r\n" +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + ,"Connection: keep-alive\r\nContent-Length: 77\r\n\r\n

404: The requested file cannot be found.

\r\n" +#endif +}; + +/* Indexes into the g_psHTTPHeaderStrings array */ +#define HTTP_HDR_OK 0 /* 200 OK */ +#define HTTP_HDR_NOT_FOUND 1 /* 404 File not found */ +#define HTTP_HDR_BAD_REQUEST 2 /* 400 Bad request */ +#define HTTP_HDR_NOT_IMPL 3 /* 501 Not Implemented */ +#define HTTP_HDR_OK_11 4 /* 200 OK */ +#define HTTP_HDR_NOT_FOUND_11 5 /* 404 File not found */ +#define HTTP_HDR_BAD_REQUEST_11 6 /* 400 Bad request */ +#define HTTP_HDR_NOT_IMPL_11 7 /* 501 Not Implemented */ +#define HTTP_HDR_CONTENT_LENGTH 8 /* Content-Length: (HTTP 1.0)*/ +#define HTTP_HDR_CONN_CLOSE 9 /* Connection: Close (HTTP 1.1) */ +#define HTTP_HDR_CONN_KEEPALIVE 10 /* Connection: keep-alive (HTTP 1.1) */ +#define HTTP_HDR_KEEPALIVE_LEN 11 /* Connection: keep-alive + Content-Length: (HTTP 1.1)*/ +#define HTTP_HDR_SERVER 12 /* Server: HTTPD_SERVER_AGENT */ +#define DEFAULT_404_HTML 13 /* default 404 body */ +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE +#define DEFAULT_404_HTML_PERSISTENT 14 /* default 404 body, but including Connection: keep-alive */ +#endif + + +#define HTTP_HDR_HTML "Content-type: text/html\r\n\r\n" +#define HTTP_HDR_SSI "Content-type: text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n" +#define HTTP_HDR_GIF "Content-type: image/gif\r\n\r\n" +#define HTTP_HDR_PNG "Content-type: image/png\r\n\r\n" +#define HTTP_HDR_JPG "Content-type: image/jpeg\r\n\r\n" +#define HTTP_HDR_BMP "Content-type: image/bmp\r\n\r\n" +#define HTTP_HDR_ICO "Content-type: image/x-icon\r\n\r\n" +#define HTTP_HDR_APP "Content-type: application/octet-stream\r\n\r\n" +#define HTTP_HDR_JS "Content-type: application/javascript\r\n\r\n" +#define HTTP_HDR_RA "Content-type: application/javascript\r\n\r\n" +#define HTTP_HDR_CSS "Content-type: text/css\r\n\r\n" +#define HTTP_HDR_SWF "Content-type: application/x-shockwave-flash\r\n\r\n" +#define HTTP_HDR_XML "Content-type: text/xml\r\n\r\n" +#define HTTP_HDR_PDF "Content-type: application/pdf\r\n\r\n" +#define HTTP_HDR_JSON "Content-type: application/json\r\n\r\n" + +#define HTTP_HDR_DEFAULT_TYPE "Content-type: text/plain\r\n\r\n" + +/** A list of extension-to-HTTP header strings (see outdated RFC 1700 MEDIA TYPES + * and http://www.iana.org/assignments/media-types for registered content types + * and subtypes) */ +static const tHTTPHeader g_psHTTPHeaders[] = +{ + { "html", HTTP_HDR_HTML}, + { "htm", HTTP_HDR_HTML}, + { "shtml",HTTP_HDR_SSI}, + { "shtm", HTTP_HDR_SSI}, + { "ssi", HTTP_HDR_SSI}, + { "gif", HTTP_HDR_GIF}, + { "png", HTTP_HDR_PNG}, + { "jpg", HTTP_HDR_JPG}, + { "bmp", HTTP_HDR_BMP}, + { "ico", HTTP_HDR_ICO}, + { "class",HTTP_HDR_APP}, + { "cls", HTTP_HDR_APP}, + { "js", HTTP_HDR_JS}, + { "ram", HTTP_HDR_RA}, + { "css", HTTP_HDR_CSS}, + { "swf", HTTP_HDR_SWF}, + { "xml", HTTP_HDR_XML}, + { "xsl", HTTP_HDR_XML}, + { "pdf", HTTP_HDR_PDF}, + { "json", HTTP_HDR_JSON} +}; + +#define NUM_HTTP_HEADERS (sizeof(g_psHTTPHeaders) / sizeof(tHTTPHeader)) + +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ + +#if LWIP_HTTPD_SSI +static const char * const g_pcSSIExtensions[] = { + ".shtml", ".shtm", ".ssi", ".xml" +}; +#define NUM_SHTML_EXTENSIONS (sizeof(g_pcSSIExtensions) / sizeof(const char *)) +#endif /* LWIP_HTTPD_SSI */ + +#endif /* LWIP_HTTPD_STRUCTS_H */ diff --git a/components/net/lwip-2.0.3/src/apps/httpd/makefsdata/makefsdata b/components/net/lwip-2.0.3/src/apps/httpd/makefsdata/makefsdata new file mode 100644 index 0000000000..37b4203e6e --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/httpd/makefsdata/makefsdata @@ -0,0 +1,97 @@ +#!/usr/bin/perl + +open(OUTPUT, "> fsdata.c"); + +chdir("fs"); +open(FILES, "find . -type f |"); + +while($file = ) { + + # Do not include files in CVS directories nor backup files. + if($file =~ /(CVS|~)/) { + next; + } + + chop($file); + + open(HEADER, "> /tmp/header") || die $!; + if($file =~ /404/) { + print(HEADER "HTTP/1.0 404 File not found\r\n"); + } else { + print(HEADER "HTTP/1.0 200 OK\r\n"); + } + print(HEADER "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n"); + if($file =~ /\.html$/) { + print(HEADER "Content-type: text/html\r\n"); + } elsif($file =~ /\.gif$/) { + print(HEADER "Content-type: image/gif\r\n"); + } elsif($file =~ /\.png$/) { + print(HEADER "Content-type: image/png\r\n"); + } elsif($file =~ /\.jpg$/) { + print(HEADER "Content-type: image/jpeg\r\n"); + } elsif($file =~ /\.class$/) { + print(HEADER "Content-type: application/octet-stream\r\n"); + } elsif($file =~ /\.ram$/) { + print(HEADER "Content-type: audio/x-pn-realaudio\r\n"); + } else { + print(HEADER "Content-type: text/plain\r\n"); + } + print(HEADER "\r\n"); + close(HEADER); + + unless($file =~ /\.plain$/ || $file =~ /cgi/) { + system("cat /tmp/header $file > /tmp/file"); + } else { + system("cp $file /tmp/file"); + } + + open(FILE, "/tmp/file"); + unlink("/tmp/file"); + unlink("/tmp/header"); + + $file =~ s/\.//; + $fvar = $file; + $fvar =~ s-/-_-g; + $fvar =~ s-\.-_-g; + print(OUTPUT "static const unsigned char data".$fvar."[] = {\n"); + print(OUTPUT "\t/* $file */\n\t"); + for($j = 0; $j < length($file); $j++) { + printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1))); + } + printf(OUTPUT "0,\n"); + + + $i = 0; + while(read(FILE, $data, 1)) { + if($i == 0) { + print(OUTPUT "\t"); + } + printf(OUTPUT "%#02x, ", unpack("C", $data)); + $i++; + if($i == 10) { + print(OUTPUT "\n"); + $i = 0; + } + } + print(OUTPUT "};\n\n"); + close(FILE); + push(@fvars, $fvar); + push(@files, $file); +} + +for($i = 0; $i < @fvars; $i++) { + $file = $files[$i]; + $fvar = $fvars[$i]; + + if($i == 0) { + $prevfile = "NULL"; + } else { + $prevfile = "file" . $fvars[$i - 1]; + } + print(OUTPUT "const struct fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, "); + print(OUTPUT "data$fvar + ". (length($file) + 1) .", "); + print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n"); +} + +print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n"); +print(OUTPUT "#define FS_NUMFILES $i\n"); diff --git a/components/net/lwip-2.0.3/src/apps/httpd/makefsdata/makefsdata.c b/components/net/lwip-2.0.3/src/apps/httpd/makefsdata/makefsdata.c new file mode 100644 index 0000000000..934e721948 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/httpd/makefsdata/makefsdata.c @@ -0,0 +1,1033 @@ +/** + * makefsdata: Converts a directory structure for use with the lwIP httpd. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jim Pettinato + * Simon Goldschmidt + * + * @todo: + * - take TCP_MSS, LWIP_TCP_TIMESTAMPS and + * PAYLOAD_ALIGN_TYPE/PAYLOAD_ALIGNMENT as arguments + */ + +#include +#include +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include "windows.h" +#else +#include +#endif +#include +#include +#include +#include + +/** Makefsdata can generate *all* files deflate-compressed (where file size shrinks). + * Since nearly all browsers support this, this is a good way to reduce ROM size. + * To compress the files, "miniz.c" must be downloaded seperately. + */ +#ifndef MAKEFS_SUPPORT_DEFLATE +#define MAKEFS_SUPPORT_DEFLATE 0 +#endif + +#define COPY_BUFSIZE (1024*1024) /* 1 MByte */ + +#if MAKEFS_SUPPORT_DEFLATE +#include "../miniz.c" + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint; + +#define my_max(a,b) (((a) > (b)) ? (a) : (b)) +#define my_min(a,b) (((a) < (b)) ? (a) : (b)) + +/* COMP_OUT_BUF_SIZE is the size of the output buffer used during compression. + COMP_OUT_BUF_SIZE must be >= 1 and <= OUT_BUF_SIZE */ +#define COMP_OUT_BUF_SIZE COPY_BUFSIZE + +/* OUT_BUF_SIZE is the size of the output buffer used during decompression. + OUT_BUF_SIZE must be a power of 2 >= TINFL_LZ_DICT_SIZE (because the low-level decompressor not only writes, but reads from the output buffer as it decompresses) */ +#define OUT_BUF_SIZE COPY_BUFSIZE +static uint8 s_outbuf[OUT_BUF_SIZE]; +static uint8 s_checkbuf[OUT_BUF_SIZE]; + +/* tdefl_compressor contains all the state needed by the low-level compressor so it's a pretty big struct (~300k). + This example makes it a global vs. putting it on the stack, of course in real-world usage you'll probably malloc() or new it. */ +tdefl_compressor g_deflator; +tinfl_decompressor g_inflator; + +int deflate_level = 10; /* default compression level, can be changed via command line */ +#define USAGE_ARG_DEFLATE " [-defl<:compr_level>]" +#else /* MAKEFS_SUPPORT_DEFLATE */ +#define USAGE_ARG_DEFLATE "" +#endif /* MAKEFS_SUPPORT_DEFLATE */ + +/* Compatibility defines Win32 vs. DOS */ +#ifdef WIN32 + +#define FIND_T WIN32_FIND_DATAA +#define FIND_T_FILENAME(fInfo) (fInfo.cFileName) +#define FIND_T_IS_DIR(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) +#define FIND_T_IS_FILE(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) +#define FIND_RET_T HANDLE +#define FINDFIRST_FILE(path, result) FindFirstFileA(path, result) +#define FINDFIRST_DIR(path, result) FindFirstFileA(path, result) +#define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result) +#define FINDFIRST_SUCCEEDED(ret) (ret != INVALID_HANDLE_VALUE) +#define FINDNEXT_SUCCEEDED(ret) (ret == TRUE) + +#define GETCWD(path, len) GetCurrentDirectoryA(len, path) +#define CHDIR(path) SetCurrentDirectoryA(path) +#define CHDIR_SUCCEEDED(ret) (ret == TRUE) + +#else + +#define FIND_T struct ffblk +#define FIND_T_FILENAME(fInfo) (fInfo.ff_name) +#define FIND_T_IS_DIR(fInfo) ((fInfo.ff_attrib & FA_DIREC) == FA_DIREC) +#define FIND_T_IS_FILE(fInfo) (1) +#define FIND_RET_T int +#define FINDFIRST_FILE(path, result) findfirst(path, result, FA_ARCH) +#define FINDFIRST_DIR(path, result) findfirst(path, result, FA_DIREC) +#define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result) +#define FINDFIRST_SUCCEEDED(ret) (ret == 0) +#define FINDNEXT_SUCCEEDED(ret) (ret == 0) + +#define GETCWD(path, len) getcwd(path, len) +#define CHDIR(path) chdir(path) +#define CHDIR_SUCCEEDED(ret) (ret == 0) + +#endif + +#define NEWLINE "\r\n" +#define NEWLINE_LEN 2 + +/* define this to get the header variables we use to build HTTP headers */ +#define LWIP_HTTPD_DYNAMIC_HEADERS 1 +#define LWIP_HTTPD_SSI 1 +#include "lwip/init.h" +#include "../httpd_structs.h" +#include "lwip/apps/fs.h" + +#include "../core/inet_chksum.c" +#include "../core/def.c" + +/** (Your server name here) */ +const char *serverID = "Server: "HTTPD_SERVER_AGENT"\r\n"; +char serverIDBuffer[1024]; + +/* change this to suit your MEM_ALIGNMENT */ +#define PAYLOAD_ALIGNMENT 4 +/* set this to 0 to prevent aligning payload */ +#define ALIGN_PAYLOAD 1 +/* define this to a type that has the required alignment */ +#define PAYLOAD_ALIGN_TYPE "unsigned int" +static int payload_alingment_dummy_counter = 0; + +#define HEX_BYTES_PER_LINE 16 + +#define MAX_PATH_LEN 256 + +struct file_entry +{ + struct file_entry* next; + const char* filename_c; +}; + +int process_sub(FILE *data_file, FILE *struct_file); +int process_file(FILE *data_file, FILE *struct_file, const char *filename); +int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len, + u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed); +int file_put_ascii(FILE *file, const char *ascii_string, int len, int *i); +int s_put_ascii(char *buf, const char *ascii_string, int len, int *i); +void concat_files(const char *file1, const char *file2, const char *targetfile); +int check_path(char* path, size_t size); + +/* 5 bytes per char + 3 bytes per line */ +static char file_buffer_c[COPY_BUFSIZE * 5 + ((COPY_BUFSIZE / HEX_BYTES_PER_LINE) * 3)]; + +char curSubdir[MAX_PATH_LEN]; +char lastFileVar[MAX_PATH_LEN]; +char hdr_buf[4096]; + +unsigned char processSubs = 1; +unsigned char includeHttpHeader = 1; +unsigned char useHttp11 = 0; +unsigned char supportSsi = 1; +unsigned char precalcChksum = 0; +unsigned char includeLastModified = 0; +#if MAKEFS_SUPPORT_DEFLATE +unsigned char deflateNonSsiFiles = 0; +size_t deflatedBytesReduced = 0; +size_t overallDataBytes = 0; +#endif + +struct file_entry* first_file = NULL; +struct file_entry* last_file = NULL; + +static void print_usage(void) +{ + printf(" Usage: htmlgen [targetdir] [-s] [-e] [-i] [-11] [-nossi] [-c] [-f:] [-m] [-svr:]" USAGE_ARG_DEFLATE NEWLINE NEWLINE); + printf(" targetdir: relative or absolute path to files to convert" NEWLINE); + printf(" switch -s: toggle processing of subdirectories (default is on)" NEWLINE); + printf(" switch -e: exclude HTTP header from file (header is created at runtime, default is off)" NEWLINE); + printf(" switch -11: include HTTP 1.1 header (1.0 is default)" NEWLINE); + printf(" switch -nossi: no support for SSI (cannot calculate Content-Length for SSI)" NEWLINE); + printf(" switch -c: precalculate checksums for all pages (default is off)" NEWLINE); + printf(" switch -f: target filename (default is \"fsdata.c\")" NEWLINE); + printf(" switch -m: include \"Last-Modified\" header based on file time" NEWLINE); + printf(" switch -svr: server identifier sent in HTTP response header ('Server' field)" NEWLINE); +#if MAKEFS_SUPPORT_DEFLATE + printf(" switch -defl: deflate-compress all non-SSI files (with opt. compr.-level, default=10)" NEWLINE); + printf(" ATTENTION: browser has to support \"Content-Encoding: deflate\"!" NEWLINE); +#endif + printf(" if targetdir not specified, htmlgen will attempt to" NEWLINE); + printf(" process files in subdirectory 'fs'" NEWLINE); +} + +int main(int argc, char *argv[]) +{ + char path[MAX_PATH_LEN]; + char appPath[MAX_PATH_LEN]; + FILE *data_file; + FILE *struct_file; + int filesProcessed; + int i; + char targetfile[MAX_PATH_LEN]; + strcpy(targetfile, "fsdata.c"); + + memset(path, 0, sizeof(path)); + memset(appPath, 0, sizeof(appPath)); + + printf(NEWLINE " makefsdata - HTML to C source converter" NEWLINE); + printf(" by Jim Pettinato - circa 2003 " NEWLINE); + printf(" extended by Simon Goldschmidt - 2009 " NEWLINE NEWLINE); + + strcpy(path, "fs"); + for (i = 1; i < argc; i++) { + if (argv[i] == NULL) { + continue; + } + if (argv[i][0] == '-') { + if (strstr(argv[i], "-svr:") == argv[i]) { + snprintf(serverIDBuffer, sizeof(serverIDBuffer), "Server: %s\r\n", &argv[i][5]); + serverID = serverIDBuffer; + printf("Using Server-ID: \"%s\"\n", serverID); + } else if (strstr(argv[i], "-s") == argv[i]) { + processSubs = 0; + } else if (strstr(argv[i], "-e") == argv[i]) { + includeHttpHeader = 0; + } else if (strstr(argv[i], "-11") == argv[i]) { + useHttp11 = 1; + } else if (strstr(argv[i], "-nossi") == argv[i]) { + supportSsi = 0; + } else if (strstr(argv[i], "-c") == argv[i]) { + precalcChksum = 1; + } else if (strstr(argv[i], "-f:") == argv[i]) { + strncpy(targetfile, &argv[i][3], sizeof(targetfile) - 1); + targetfile[sizeof(targetfile) - 1] = 0; + printf("Writing to file \"%s\"\n", targetfile); + } else if (strstr(argv[i], "-m") == argv[i]) { + includeLastModified = 1; + } else if (strstr(argv[i], "-defl") == argv[i]) { +#if MAKEFS_SUPPORT_DEFLATE + char* colon = strstr(argv[i], ":"); + if (colon) { + if (colon[1] != 0) { + int defl_level = atoi(&colon[1]); + if ((defl_level >= 0) && (defl_level <= 10)) { + deflate_level = defl_level; + } else { + printf("ERROR: deflate level must be [0..10]" NEWLINE); + exit(0); + } + } + } + deflateNonSsiFiles = 1; + printf("Deflating all non-SSI files with level %d (but only if size is reduced)" NEWLINE, deflate_level); +#else + printf("WARNING: Deflate support is disabled\n"); +#endif + } else if ((strstr(argv[i], "-?")) || (strstr(argv[i], "-h"))) { + print_usage(); + exit(0); + } + } else if ((argv[i][0] == '/') && (argv[i][1] == '?') && (argv[i][2] == 0)) { + print_usage(); + exit(0); + } else { + strncpy(path, argv[i], sizeof(path)-1); + path[sizeof(path)-1] = 0; + } + } + + if (!check_path(path, sizeof(path))) { + printf("Invalid path: \"%s\"." NEWLINE, path); + exit(-1); + } + + GETCWD(appPath, MAX_PATH_LEN); + /* if command line param or subdir named 'fs' not found spout usage verbiage */ + if (!CHDIR_SUCCEEDED(CHDIR(path))) { + /* if no subdir named 'fs' (or the one which was given) exists, spout usage verbiage */ + printf(" Failed to open directory \"%s\"." NEWLINE NEWLINE, path); + print_usage(); + exit(-1); + } + CHDIR(appPath); + + printf("HTTP %sheader will %s statically included." NEWLINE, + (includeHttpHeader ? (useHttp11 ? "1.1 " : "1.0 ") : ""), + (includeHttpHeader ? "be" : "not be")); + + sprintf(curSubdir, ""); /* start off in web page's root directory - relative paths */ + printf(" Processing all files in directory %s", path); + if (processSubs) { + printf(" and subdirectories..." NEWLINE NEWLINE); + } else { + printf("..." NEWLINE NEWLINE); + } + + data_file = fopen("fsdata.tmp", "wb"); + if (data_file == NULL) { + printf("Failed to create file \"fsdata.tmp\"\n"); + exit(-1); + } + struct_file = fopen("fshdr.tmp", "wb"); + if (struct_file == NULL) { + printf("Failed to create file \"fshdr.tmp\"\n"); + fclose(data_file); + exit(-1); + } + + CHDIR(path); + + fprintf(data_file, "#include \"lwip/apps/fs.h\"" NEWLINE); + fprintf(data_file, "#include \"lwip/def.h\"" NEWLINE); + fprintf(data_file, "#include \"fsdata.h\"" NEWLINE NEWLINE NEWLINE); + + fprintf(data_file, "#define file_NULL (struct fsdata_file *) NULL" NEWLINE NEWLINE NEWLINE); + /* define FS_FILE_FLAGS_HEADER_INCLUDED to 1 if not defined (compatibility with older httpd/fs) */ + fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_INCLUDED" NEWLINE "#define FS_FILE_FLAGS_HEADER_INCLUDED 1" NEWLINE "#endif" NEWLINE); + /* define FS_FILE_FLAGS_HEADER_PERSISTENT to 0 if not defined (compatibility with older httpd/fs: wasn't supported back then) */ + fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_PERSISTENT" NEWLINE "#define FS_FILE_FLAGS_HEADER_PERSISTENT 0" NEWLINE "#endif" NEWLINE); + + /* define alignment defines */ +#if ALIGN_PAYLOAD + fprintf(data_file, "/* FSDATA_FILE_ALIGNMENT: 0=off, 1=by variable, 2=by include */" NEWLINE "#ifndef FSDATA_FILE_ALIGNMENT" NEWLINE "#define FSDATA_FILE_ALIGNMENT 0" NEWLINE "#endif" NEWLINE); +#endif + fprintf(data_file, "#ifndef FSDATA_ALIGN_PRE" NEWLINE "#define FSDATA_ALIGN_PRE" NEWLINE "#endif" NEWLINE); + fprintf(data_file, "#ifndef FSDATA_ALIGN_POST" NEWLINE "#define FSDATA_ALIGN_POST" NEWLINE "#endif" NEWLINE); +#if ALIGN_PAYLOAD + fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==2" NEWLINE "#include \"fsdata_alignment.h\"" NEWLINE "#endif" NEWLINE); +#endif + + sprintf(lastFileVar, "NULL"); + + filesProcessed = process_sub(data_file, struct_file); + + /* data_file now contains all of the raw data.. now append linked list of + * file header structs to allow embedded app to search for a file name */ + fprintf(data_file, NEWLINE NEWLINE); + fprintf(struct_file, "#define FS_ROOT file_%s" NEWLINE, lastFileVar); + fprintf(struct_file, "#define FS_NUMFILES %d" NEWLINE NEWLINE, filesProcessed); + + fclose(data_file); + fclose(struct_file); + + CHDIR(appPath); + /* append struct_file to data_file */ + printf(NEWLINE "Creating target file..." NEWLINE NEWLINE); + concat_files("fsdata.tmp", "fshdr.tmp", targetfile); + + /* if succeeded, delete the temporary files */ + if (remove("fsdata.tmp") != 0) { + printf("Warning: failed to delete fsdata.tmp\n"); + } + if (remove("fshdr.tmp") != 0) { + printf("Warning: failed to delete fshdr.tmp\n"); + } + + printf(NEWLINE "Processed %d files - done." NEWLINE, filesProcessed); +#if MAKEFS_SUPPORT_DEFLATE + if (deflateNonSsiFiles) { + printf("(Deflated total byte reduction: %d bytes -> %d bytes (%.02f%%)" NEWLINE, + (int)overallDataBytes, (int)deflatedBytesReduced, (float)((deflatedBytesReduced*100.0)/overallDataBytes)); + } +#endif + printf(NEWLINE); + + while (first_file != NULL) { + struct file_entry* fe = first_file; + first_file = fe->next; + free(fe); + } + + return 0; +} + +int check_path(char* path, size_t size) +{ + size_t slen; + if (path[0] == 0) { + /* empty */ + return 0; + } + slen = strlen(path); + if (slen >= size) { + /* not NULL-terminated */ + return 0; + } + while ((slen > 0) && ((path[slen] == '\\') || (path[slen] == '/'))) { + /* path should not end with trailing backslash */ + path[slen] = 0; + slen--; + } + if (slen == 0) { + return 0; + } + return 1; +} + +static void copy_file(const char *filename_in, FILE *fout) +{ + FILE *fin; + size_t len; + void* buf; + fin = fopen(filename_in, "rb"); + if (fin == NULL) { + printf("Failed to open file \"%s\"\n", filename_in); + exit(-1); + } + buf = malloc(COPY_BUFSIZE); + while ((len = fread(buf, 1, COPY_BUFSIZE, fin)) > 0) { + fwrite(buf, 1, len, fout); + } + free(buf); + fclose(fin); +} + +void concat_files(const char *file1, const char *file2, const char *targetfile) +{ + FILE *fout; + fout = fopen(targetfile, "wb"); + if (fout == NULL) { + printf("Failed to open file \"%s\"\n", targetfile); + exit(-1); + } + copy_file(file1, fout); + copy_file(file2, fout); + fclose(fout); +} + +int process_sub(FILE *data_file, FILE *struct_file) +{ + FIND_T fInfo; + FIND_RET_T fret; + int filesProcessed = 0; + + if (processSubs) { + /* process subs recursively */ + size_t sublen = strlen(curSubdir); + size_t freelen = sizeof(curSubdir) - sublen - 1; + LWIP_ASSERT("sublen < sizeof(curSubdir)", sublen < sizeof(curSubdir)); + fret = FINDFIRST_DIR("*", &fInfo); + if (FINDFIRST_SUCCEEDED(fret)) { + do { + const char *curName = FIND_T_FILENAME(fInfo); + if ((curName[0] == '.') || (strcmp(curName, "CVS") == 0)) { + continue; + } + if (!FIND_T_IS_DIR(fInfo)) { + continue; + } + if (freelen > 0) { + CHDIR(curName); + strncat(curSubdir, "/", freelen); + strncat(curSubdir, curName, freelen - 1); + curSubdir[sizeof(curSubdir) - 1] = 0; + printf("processing subdirectory %s/..." NEWLINE, curSubdir); + filesProcessed += process_sub(data_file, struct_file); + CHDIR(".."); + curSubdir[sublen] = 0; + } else { + printf("WARNING: cannot process sub due to path length restrictions: \"%s/%s\"\n", curSubdir, curName); + } + } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo))); + } + } + + fret = FINDFIRST_FILE("*.*", &fInfo); + if (FINDFIRST_SUCCEEDED(fret)) { + /* at least one file in directory */ + do { + if (FIND_T_IS_FILE(fInfo)) { + const char *curName = FIND_T_FILENAME(fInfo); + printf("processing %s/%s..." NEWLINE, curSubdir, curName); + if (process_file(data_file, struct_file, curName) < 0) { + printf(NEWLINE "Error... aborting" NEWLINE); + return -1; + } + filesProcessed++; + } + } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo))); + } + return filesProcessed; +} + +u8_t* get_file_data(const char* filename, int* file_size, int can_be_compressed, int* is_compressed) +{ + FILE *inFile; + size_t fsize = 0; + u8_t* buf; + size_t r; + int rs; + inFile = fopen(filename, "rb"); + if (inFile == NULL) { + printf("Failed to open file \"%s\"\n", filename); + exit(-1); + } + fseek(inFile, 0, SEEK_END); + rs = ftell(inFile); + if (rs < 0) { + printf("ftell failed with %d\n", errno); + exit(-1); + } + fsize = (size_t)rs; + fseek(inFile, 0, SEEK_SET); + buf = (u8_t*)malloc(fsize); + LWIP_ASSERT("buf != NULL", buf != NULL); + r = fread(buf, 1, fsize, inFile); + *file_size = fsize; + *is_compressed = 0; +#if MAKEFS_SUPPORT_DEFLATE + overallDataBytes += fsize; + if (deflateNonSsiFiles) { + if (can_be_compressed) { + if (fsize < OUT_BUF_SIZE) { + u8_t* ret_buf; + tdefl_status status; + size_t in_bytes = fsize; + size_t out_bytes = OUT_BUF_SIZE; + const void *next_in = buf; + void *next_out = s_outbuf; + /* create tdefl() compatible flags (we have to compose the low-level flags ourselves, or use tdefl_create_comp_flags_from_zip_params() but that means MINIZ_NO_ZLIB_APIS can't be defined). */ + mz_uint comp_flags = s_tdefl_num_probes[MZ_MIN(10, deflate_level)] | ((deflate_level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); + if (!deflate_level) { + comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; + } + status = tdefl_init(&g_deflator, NULL, NULL, comp_flags); + if (status != TDEFL_STATUS_OKAY) { + printf("tdefl_init() failed!\n"); + exit(-1); + } + memset(s_outbuf, 0, sizeof(s_outbuf)); + status = tdefl_compress(&g_deflator, next_in, &in_bytes, next_out, &out_bytes, TDEFL_FINISH); + if (status != TDEFL_STATUS_DONE) { + printf("deflate failed: %d\n", status); + exit(-1); + } + LWIP_ASSERT("out_bytes <= COPY_BUFSIZE", out_bytes <= OUT_BUF_SIZE); + if (out_bytes < fsize) { + ret_buf = (u8_t*)malloc(out_bytes); + LWIP_ASSERT("ret_buf != NULL", ret_buf != NULL); + memcpy(ret_buf, s_outbuf, out_bytes); + { + /* sanity-check compression be inflating and comparing to the original */ + tinfl_status dec_status; + tinfl_decompressor inflator; + size_t dec_in_bytes = out_bytes; + size_t dec_out_bytes = OUT_BUF_SIZE; + next_out = s_checkbuf; + + tinfl_init(&inflator); + memset(s_checkbuf, 0, sizeof(s_checkbuf)); + dec_status = tinfl_decompress(&inflator, (const mz_uint8 *)ret_buf, &dec_in_bytes, s_checkbuf, (mz_uint8 *)next_out, &dec_out_bytes, 0); + LWIP_ASSERT("tinfl_decompress failed", dec_status == TINFL_STATUS_DONE); + LWIP_ASSERT("tinfl_decompress size mismatch", fsize == dec_out_bytes); + LWIP_ASSERT("decompressed memcmp failed", !memcmp(s_checkbuf, buf, fsize)); + } + /* free original buffer, use compressed data + size */ + free(buf); + buf = ret_buf; + *file_size = out_bytes; + printf(" - deflate: %d bytes -> %d bytes (%.02f%%)" NEWLINE, (int)fsize, (int)out_bytes, (float)((out_bytes*100.0)/fsize)); + deflatedBytesReduced += (size_t)(fsize - out_bytes); + *is_compressed = 1; + } else { + printf(" - uncompressed: (would be %d bytes larger using deflate)" NEWLINE, (int)(out_bytes - fsize)); + } + } else { + printf(" - uncompressed: (file is larger than deflate bufer)" NEWLINE); + } + } else { + printf(" - SSI file, cannot be compressed" NEWLINE); + } + } +#else + LWIP_UNUSED_ARG(can_be_compressed); +#endif + fclose(inFile); + return buf; +} + +void process_file_data(FILE* data_file, u8_t* file_data, size_t file_size) +{ + size_t written, i, src_off=0; + + size_t off = 0; + for (i = 0; i < file_size; i++) { + LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - 5); + sprintf(&file_buffer_c[off], "0x%02.2x,", file_data[i]); + off += 5; + if ((++src_off % HEX_BYTES_PER_LINE) == 0) { + LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - NEWLINE_LEN); + memcpy(&file_buffer_c[off], NEWLINE, NEWLINE_LEN); + off += NEWLINE_LEN; + } + if (off + 20 >= sizeof(file_buffer_c)) { + written = fwrite(file_buffer_c, 1, off, data_file); + LWIP_ASSERT("written == off", written == off); + off = 0; + } + } + written = fwrite(file_buffer_c, 1, off, data_file); + LWIP_ASSERT("written == off", written == off); +} + +int write_checksums(FILE *struct_file, const char *varname, + u16_t hdr_len, u16_t hdr_chksum, const u8_t* file_data, size_t file_size) +{ + int chunk_size = TCP_MSS; + int offset, src_offset; + size_t len; + int i = 0; +#if LWIP_TCP_TIMESTAMPS + /* when timestamps are used, usable space is 12 bytes less per segment */ + chunk_size -= 12; +#endif + + fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); + fprintf(struct_file, "const struct fsdata_chksum chksums_%s[] = {" NEWLINE, varname); + + if (hdr_len > 0) { + /* add checksum for HTTP header */ + fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, 0, hdr_chksum, hdr_len); + i++; + } + src_offset = 0; + for (offset = hdr_len; ; offset += len) { + unsigned short chksum; + void* data = (void*)&file_data[src_offset]; + len = LWIP_MIN(chunk_size, (int)file_size - src_offset); + if (len == 0) { + break; + } + chksum = ~inet_chksum(data, (u16_t)len); + /* add checksum for data */ + fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, offset, chksum, len); + i++; + } + fprintf(struct_file, "};" NEWLINE); + fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); + return i; +} + +static int is_valid_char_for_c_var(char x) +{ + if (((x >= 'A') && (x <= 'Z')) || + ((x >= 'a') && (x <= 'z')) || + ((x >= '0') && (x <= '9')) || + (x == '_')) { + return 1; + } + return 0; +} + +static void fix_filename_for_c(char* qualifiedName, size_t max_len) +{ + struct file_entry* f; + size_t len = strlen(qualifiedName); + char *new_name = (char*)malloc(len + 2); + int filename_ok; + int cnt = 0; + size_t i; + if (len + 3 == max_len) { + printf("File name too long: \"%s\"\n", qualifiedName); + exit(-1); + } + strcpy(new_name, qualifiedName); + for (i = 0; i < len; i++) { + if (!is_valid_char_for_c_var(new_name[i])) { + new_name[i] = '_'; + } + } + do { + filename_ok = 1; + for (f = first_file; f != NULL; f = f->next) { + if (!strcmp(f->filename_c, new_name)) { + filename_ok = 0; + cnt++; + /* try next unique file name */ + sprintf(&new_name[len], "%d", cnt); + break; + } + } + } while (!filename_ok && (cnt < 999)); + if (!filename_ok) { + printf("Failed to get unique file name: \"%s\"\n", qualifiedName); + exit(-1); + } + strcpy(qualifiedName, new_name); + free(new_name); +} + +static void register_filename(const char* qualifiedName) +{ + struct file_entry* fe = (struct file_entry*)malloc(sizeof(struct file_entry)); + fe->filename_c = strdup(qualifiedName); + fe->next = NULL; + if (first_file == NULL) { + first_file = last_file = fe; + } else { + last_file->next = fe; + last_file = fe; + } +} + +int is_ssi_file(const char* filename) +{ + size_t loop; + for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { + if (strstr(filename, g_pcSSIExtensions[loop])) { + return 1; + } + } + return 0; +} + +int process_file(FILE *data_file, FILE *struct_file, const char *filename) +{ + char varname[MAX_PATH_LEN]; + int i = 0; + char qualifiedName[MAX_PATH_LEN]; + int file_size; + u16_t http_hdr_chksum = 0; + u16_t http_hdr_len = 0; + int chksum_count = 0; + u8_t flags = 0; + const char* flags_str; + u8_t has_content_len; + u8_t* file_data; + int is_compressed = 0; + + /* create qualified name (@todo: prepend slash or not?) */ + sprintf(qualifiedName,"%s/%s", curSubdir, filename); + /* create C variable name */ + strcpy(varname, qualifiedName); + /* convert slashes & dots to underscores */ + fix_filename_for_c(varname, MAX_PATH_LEN); + register_filename(varname); +#if ALIGN_PAYLOAD + /* to force even alignment of array, type 1 */ + fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==1" NEWLINE); + fprintf(data_file, "static const " PAYLOAD_ALIGN_TYPE " dummy_align_%s = %d;" NEWLINE, varname, payload_alingment_dummy_counter++); + fprintf(data_file, "#endif" NEWLINE); +#endif /* ALIGN_PAYLOAD */ + fprintf(data_file, "static const unsigned char FSDATA_ALIGN_PRE data_%s[] FSDATA_ALIGN_POST = {" NEWLINE, varname); + /* encode source file name (used by file system, not returned to browser) */ + fprintf(data_file, "/* %s (%d chars) */" NEWLINE, qualifiedName, strlen(qualifiedName)+1); + file_put_ascii(data_file, qualifiedName, strlen(qualifiedName)+1, &i); +#if ALIGN_PAYLOAD + /* pad to even number of bytes to assure payload is on aligned boundary */ + while(i % PAYLOAD_ALIGNMENT != 0) { + fprintf(data_file, "0x%02.2x,", 0); + i++; + } +#endif /* ALIGN_PAYLOAD */ + fprintf(data_file, NEWLINE); + + has_content_len = !is_ssi_file(filename); + file_data = get_file_data(filename, &file_size, includeHttpHeader && has_content_len, &is_compressed); + if (includeHttpHeader) { + file_write_http_header(data_file, filename, file_size, &http_hdr_len, &http_hdr_chksum, has_content_len, is_compressed); + flags = FS_FILE_FLAGS_HEADER_INCLUDED; + if (has_content_len) { + flags |= FS_FILE_FLAGS_HEADER_PERSISTENT; + } + } + if (precalcChksum) { + chksum_count = write_checksums(struct_file, varname, http_hdr_len, http_hdr_chksum, file_data, file_size); + } + + /* build declaration of struct fsdata_file in temp file */ + fprintf(struct_file, "const struct fsdata_file file_%s[] = { {" NEWLINE, varname); + fprintf(struct_file, "file_%s," NEWLINE, lastFileVar); + fprintf(struct_file, "data_%s," NEWLINE, varname); + fprintf(struct_file, "data_%s + %d," NEWLINE, varname, i); + fprintf(struct_file, "sizeof(data_%s) - %d," NEWLINE, varname, i); + switch(flags) + { + case(FS_FILE_FLAGS_HEADER_INCLUDED): + flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED"; + break; + case(FS_FILE_FLAGS_HEADER_PERSISTENT): + flags_str = "FS_FILE_FLAGS_HEADER_PERSISTENT"; + break; + case(FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT): + flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT"; + break; + default: + flags_str = "0"; + break; + } + fprintf(struct_file, "%s," NEWLINE, flags_str); + if (precalcChksum) { + fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); + fprintf(struct_file, "%d, chksums_%s," NEWLINE, chksum_count, varname); + fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); + } + fprintf(struct_file, "}};" NEWLINE NEWLINE); + strcpy(lastFileVar, varname); + + /* write actual file contents */ + i = 0; + fprintf(data_file, NEWLINE "/* raw file data (%d bytes) */" NEWLINE, file_size); + process_file_data(data_file, file_data, file_size); + fprintf(data_file, "};" NEWLINE NEWLINE); + free(file_data); + return 0; +} + +int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len, + u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed) +{ + int i = 0; + int response_type = HTTP_HDR_OK; + const char* file_type; + const char *cur_string; + size_t cur_len; + int written = 0; + size_t hdr_len = 0; + u16_t acc; + const char *file_ext; + int j; + u8_t provide_last_modified = includeLastModified; + + memset(hdr_buf, 0, sizeof(hdr_buf)); + + if (useHttp11) { + response_type = HTTP_HDR_OK_11; + } + + fprintf(data_file, NEWLINE "/* HTTP header */"); + if (strstr(filename, "404") == filename) { + response_type = HTTP_HDR_NOT_FOUND; + if (useHttp11) { + response_type = HTTP_HDR_NOT_FOUND_11; + } + } else if (strstr(filename, "400") == filename) { + response_type = HTTP_HDR_BAD_REQUEST; + if (useHttp11) { + response_type = HTTP_HDR_BAD_REQUEST_11; + } + } else if (strstr(filename, "501") == filename) { + response_type = HTTP_HDR_NOT_IMPL; + if (useHttp11) { + response_type = HTTP_HDR_NOT_IMPL_11; + } + } + cur_string = g_psHTTPHeaderStrings[response_type]; + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + i = 0; + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + } + + cur_string = serverID; + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + i = 0; + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + } + + file_ext = filename; + if (file_ext != NULL) { + while(strstr(file_ext, ".") != NULL) { + file_ext = strstr(file_ext, "."); + file_ext++; + } + } + if ((file_ext == NULL) || (*file_ext == 0)) { + printf("failed to get extension for file \"%s\", using default.\n", filename); + file_type = HTTP_HDR_DEFAULT_TYPE; + } else { + file_type = NULL; + for (j = 0; j < NUM_HTTP_HEADERS; j++) { + if (!strcmp(file_ext, g_psHTTPHeaders[j].extension)) { + file_type = g_psHTTPHeaders[j].content_type; + break; + } + } + if (file_type == NULL) { + printf("failed to get file type for extension \"%s\", using default.\n", file_ext); + file_type = HTTP_HDR_DEFAULT_TYPE; + } + } + + /* Content-Length is used for persistent connections in HTTP/1.1 but also for + download progress in older versions + @todo: just use a big-enough buffer and let the HTTPD send spaces? */ + if (provide_content_len) { + char intbuf[MAX_PATH_LEN]; + int content_len = file_size; + memset(intbuf, 0, sizeof(intbuf)); + cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%d+ bytes) */" NEWLINE, cur_string, content_len, cur_len+2); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + } + + _itoa(content_len, intbuf, 10); + strcat(intbuf, "\r\n"); + cur_len = strlen(intbuf); + written += file_put_ascii(data_file, intbuf, cur_len, &i); + i = 0; + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], intbuf, cur_len); + hdr_len += cur_len; + } + } + if (provide_last_modified) { + char modbuf[256]; + struct stat stat_data; + struct tm* t; + memset(modbuf, 0, sizeof(modbuf)); + memset(&stat_data, 0, sizeof(stat_data)); + cur_string = modbuf; + strcpy(modbuf, "Last-Modified: "); + if (stat(filename, &stat_data) != 0) { + printf("stat(%s) failed with error %d\n", filename, errno); + exit(-1); + } + t = gmtime(&stat_data.st_mtime); + if (t == NULL) { + printf("gmtime() failed with error %d\n", errno); + exit(-1); + } + strftime(&modbuf[15], sizeof(modbuf)-15, "%a, %d %b %Y %H:%M:%S GMT", t); + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\"\r\n\" (%d+ bytes) */" NEWLINE, cur_string, cur_len+2); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + } + + modbuf[0] = 0; + strcat(modbuf, "\r\n"); + cur_len = strlen(modbuf); + written += file_put_ascii(data_file, modbuf, cur_len, &i); + i = 0; + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], modbuf, cur_len); + hdr_len += cur_len; + } + } + + /* HTTP/1.1 implements persistent connections */ + if (useHttp11) { + if (provide_content_len) { + cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_KEEPALIVE]; + } else { + /* no Content-Length available, so a persistent connection is no possible + because the client does not know the data length */ + cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; + } + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + i = 0; + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + } + } + +#if MAKEFS_SUPPORT_DEFLATE + if (is_compressed) { + /* tell the client about the deflate encoding */ + LWIP_ASSERT("error", deflateNonSsiFiles); + cur_string = "Content-Encoding: deflate\r\n"; + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + i = 0; + } +#else + LWIP_UNUSED_ARG(is_compressed); +#endif + + /* write content-type, ATTENTION: this includes the double-CRLF! */ + cur_string = file_type; + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + i = 0; + + /* ATTENTION: headers are done now (double-CRLF has been written!) */ + + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + + LWIP_ASSERT("hdr_len <= 0xffff", hdr_len <= 0xffff); + LWIP_ASSERT("strlen(hdr_buf) == hdr_len", strlen(hdr_buf) == hdr_len); + acc = ~inet_chksum(hdr_buf, (u16_t)hdr_len); + *http_hdr_len = (u16_t)hdr_len; + *http_hdr_chksum = acc; + } + + return written; +} + +int file_put_ascii(FILE *file, const char* ascii_string, int len, int *i) +{ + int x; + for (x = 0; x < len; x++) { + unsigned char cur = ascii_string[x]; + fprintf(file, "0x%02.2x,", cur); + if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { + fprintf(file, NEWLINE); + } + } + return len; +} + +int s_put_ascii(char *buf, const char *ascii_string, int len, int *i) +{ + int x; + int idx = 0; + for (x = 0; x < len; x++) { + unsigned char cur = ascii_string[x]; + sprintf(&buf[idx], "0x%02.2x,", cur); + idx += 5; + if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { + sprintf(&buf[idx], NEWLINE); + idx += NEWLINE_LEN; + } + } + return len; +} diff --git a/components/net/lwip-2.0.3/src/apps/httpd/makefsdata/readme.txt b/components/net/lwip-2.0.3/src/apps/httpd/makefsdata/readme.txt new file mode 100644 index 0000000000..3768585ef9 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/httpd/makefsdata/readme.txt @@ -0,0 +1,13 @@ +This directory contains a script ('makefsdata') to create C code suitable for +httpd for given html pages (or other files) in a directory. + +There is also a plain C console application doing the same and extended a bit. + +Usage: htmlgen [targetdir] [-s] [-i]s + targetdir: relative or absolute path to files to convert + switch -s: toggle processing of subdirectories (default is on) + switch -e: exclude HTTP header from file (header is created at runtime, default is on) + switch -11: include HTTP 1.1 header (1.0 is default) + + if targetdir not specified, makefsdata will attempt to + process files in subdirectory 'fs'. diff --git a/components/net/lwip-2.0.3/src/apps/lwiperf/lwiperf.c b/components/net/lwip-2.0.3/src/apps/lwiperf/lwiperf.c new file mode 100644 index 0000000000..efabe478e3 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/lwiperf/lwiperf.c @@ -0,0 +1,661 @@ +/** + * @file + * lwIP iPerf server implementation + */ + +/** + * @defgroup iperf Iperf server + * @ingroup apps + * + * This is a simple performance measuring server to check your bandwith using + * iPerf2 on a PC as client. + * It is currently a minimal implementation providing an IPv4 TCP server only. + * + * @todo: implement UDP mode and IPv6 + */ + +/* + * Copyright (c) 2014 Simon Goldschmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + */ + +#include "lwip/apps/lwiperf.h" + +#include "lwip/tcp.h" +#include "lwip/sys.h" + +#include + +/* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */ +#if LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API + +/** Specify the idle timeout (in seconds) after that the test fails */ +#ifndef LWIPERF_TCP_MAX_IDLE_SEC +#define LWIPERF_TCP_MAX_IDLE_SEC 10U +#endif +#if LWIPERF_TCP_MAX_IDLE_SEC > 255 +#error LWIPERF_TCP_MAX_IDLE_SEC must fit into an u8_t +#endif + +/* File internal memory allocation (struct lwiperf_*): this defaults to + the heap */ +#ifndef LWIPERF_ALLOC +#define LWIPERF_ALLOC(type) mem_malloc(sizeof(type)) +#define LWIPERF_FREE(type, item) mem_free(item) +#endif + +/** If this is 1, check that received data has the correct format */ +#ifndef LWIPERF_CHECK_RX_DATA +#define LWIPERF_CHECK_RX_DATA 0 +#endif + +/** This is the Iperf settings struct sent from the client */ +typedef struct _lwiperf_settings { +#define LWIPERF_FLAGS_ANSWER_TEST 0x80000000 +#define LWIPERF_FLAGS_ANSWER_NOW 0x00000001 + u32_t flags; + u32_t num_threads; /* unused for now */ + u32_t remote_port; + u32_t buffer_len; /* unused for now */ + u32_t win_band; /* TCP window / UDP rate: unused for now */ + u32_t amount; /* pos. value: bytes?; neg. values: time (unit is 10ms: 1/100 second) */ +} lwiperf_settings_t; + +/** Basic connection handle */ +struct _lwiperf_state_base; +typedef struct _lwiperf_state_base lwiperf_state_base_t; +struct _lwiperf_state_base { + /* 1=tcp, 0=udp */ + u8_t tcp; + /* 1=server, 0=client */ + u8_t server; + lwiperf_state_base_t* next; + lwiperf_state_base_t* related_server_state; +}; + +/** Connection handle for a TCP iperf session */ +typedef struct _lwiperf_state_tcp { + lwiperf_state_base_t base; + struct tcp_pcb* server_pcb; + struct tcp_pcb* conn_pcb; + u32_t time_started; + lwiperf_report_fn report_fn; + void* report_arg; + u8_t poll_count; + u8_t next_num; + u32_t bytes_transferred; + lwiperf_settings_t settings; + u8_t have_settings_buf; +} lwiperf_state_tcp_t; + +/** List of active iperf sessions */ +static lwiperf_state_base_t* lwiperf_all_connections; +/** A const buffer to send from: we want to measure sending, not copying! */ +static const u8_t lwiperf_txbuf_const[1600] = { + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', +}; + +static err_t lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb); +static void lwiperf_tcp_err(void *arg, err_t err); + +/** Add an iperf session to the 'active' list */ +static void +lwiperf_list_add(lwiperf_state_base_t* item) +{ + if (lwiperf_all_connections == NULL) { + lwiperf_all_connections = item; + } else { + item = lwiperf_all_connections; + } +} + +/** Remove an iperf session from the 'active' list */ +static void +lwiperf_list_remove(lwiperf_state_base_t* item) +{ + lwiperf_state_base_t* prev = NULL; + lwiperf_state_base_t* iter; + for (iter = lwiperf_all_connections; iter != NULL; prev = iter, iter = iter->next) { + if (iter == item) { + if (prev == NULL) { + lwiperf_all_connections = iter->next; + } else { + prev->next = item; + } + /* @debug: ensure this item is listed only once */ + for (iter = iter->next; iter != NULL; iter = iter->next) { + LWIP_ASSERT("duplicate entry", iter != item); + } + break; + } + } +} + +/** Call the report function of an iperf tcp session */ +static void +lwip_tcp_conn_report(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type) +{ + if ((conn != NULL) && (conn->report_fn != NULL)) { + u32_t now, duration_ms, bandwidth_kbitpsec; + now = sys_now(); + duration_ms = now - conn->time_started; + if (duration_ms == 0) { + bandwidth_kbitpsec = 0; + } else { + bandwidth_kbitpsec = (conn->bytes_transferred / duration_ms) * 8U; + } + conn->report_fn(conn->report_arg, report_type, + &conn->conn_pcb->local_ip, conn->conn_pcb->local_port, + &conn->conn_pcb->remote_ip, conn->conn_pcb->remote_port, + conn->bytes_transferred, duration_ms, bandwidth_kbitpsec); + } +} + +/** Close an iperf tcp session */ +static void +lwiperf_tcp_close(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type) +{ + err_t err; + + lwip_tcp_conn_report(conn, report_type); + lwiperf_list_remove(&conn->base); + if (conn->conn_pcb != NULL) { + tcp_arg(conn->conn_pcb, NULL); + tcp_poll(conn->conn_pcb, NULL, 0); + tcp_sent(conn->conn_pcb, NULL); + tcp_recv(conn->conn_pcb, NULL); + tcp_err(conn->conn_pcb, NULL); + err = tcp_close(conn->conn_pcb); + if (err != ERR_OK) { + /* don't want to wait for free memory here... */ + tcp_abort(conn->conn_pcb); + } + } else { + /* no conn pcb, this is the server pcb */ + err = tcp_close(conn->server_pcb); + LWIP_ASSERT("error", err != ERR_OK); + } + LWIPERF_FREE(lwiperf_state_tcp_t, conn); +} + +/** Try to send more data on an iperf tcp session */ +static err_t +lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn) +{ + int send_more; + err_t err; + u16_t txlen; + u16_t txlen_max; + void* txptr; + u8_t apiflags; + + LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0)); + + do { + send_more = 0; + if (conn->settings.amount & PP_HTONL(0x80000000)) { + /* this session is time-limited */ + u32_t now = sys_now(); + u32_t diff_ms = now - conn->time_started; + u32_t time = (u32_t)-(s32_t)lwip_htonl(conn->settings.amount); + u32_t time_ms = time * 10; + if (diff_ms >= time_ms) { + /* time specified by the client is over -> close the connection */ + lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); + return ERR_OK; + } + } else { + /* this session is byte-limited */ + u32_t amount_bytes = lwip_htonl(conn->settings.amount); + /* @todo: this can send up to 1*MSS more than requested... */ + if (amount_bytes >= conn->bytes_transferred) { + /* all requested bytes transferred -> close the connection */ + lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); + return ERR_OK; + } + } + + if (conn->bytes_transferred < 24) { + /* transmit the settings a first time */ + txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred]; + txlen_max = (u16_t)(24 - conn->bytes_transferred); + apiflags = TCP_WRITE_FLAG_COPY; + } else if (conn->bytes_transferred < 48) { + /* transmit the settings a second time */ + txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred - 24]; + txlen_max = (u16_t)(48 - conn->bytes_transferred); + apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE; + send_more = 1; + } else { + /* transmit data */ + /* @todo: every x bytes, transmit the settings again */ + txptr = LWIP_CONST_CAST(void*, &lwiperf_txbuf_const[conn->bytes_transferred % 10]); + txlen_max = TCP_MSS; + if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */ + txlen_max = TCP_MSS - 24; + } + apiflags = 0; /* no copying needed */ + send_more = 1; + } + txlen = txlen_max; + do { + err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags); + if (err == ERR_MEM) { + txlen /= 2; + } + } while ((err == ERR_MEM) && (txlen >= (TCP_MSS/2))); + + if (err == ERR_OK) { + conn->bytes_transferred += txlen; + } else { + send_more = 0; + } + } while(send_more); + + tcp_output(conn->conn_pcb); + return ERR_OK; +} + +/** TCP sent callback, try to send more data */ +static err_t +lwiperf_tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) +{ + lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; + /* @todo: check 'len' (e.g. to time ACK of all data)? for now, we just send more... */ + LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); + LWIP_UNUSED_ARG(tpcb); + LWIP_UNUSED_ARG(len); + + conn->poll_count = 0; + + return lwiperf_tcp_client_send_more(conn); +} + +/** TCP connected callback (active connection), send data now */ +static err_t +lwiperf_tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err) +{ + lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; + LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); + LWIP_UNUSED_ARG(tpcb); + if (err != ERR_OK) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); + return ERR_OK; + } + conn->poll_count = 0; + conn->time_started = sys_now(); + return lwiperf_tcp_client_send_more(conn); +} + +/** Start TCP connection back to the client (either parallel or after the + * receive test has finished. + */ +static err_t +lwiperf_tx_start(lwiperf_state_tcp_t* conn) +{ + err_t err; + lwiperf_state_tcp_t* client_conn; + struct tcp_pcb* newpcb; + ip_addr_t remote_addr; + u16_t remote_port; + + client_conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); + if (client_conn == NULL) { + return ERR_MEM; + } + newpcb = tcp_new(); + if (newpcb == NULL) { + LWIPERF_FREE(lwiperf_state_tcp_t, client_conn); + return ERR_MEM; + } + + MEMCPY(client_conn, conn, sizeof(lwiperf_state_tcp_t)); + client_conn->base.server = 0; + client_conn->server_pcb = NULL; + client_conn->conn_pcb = newpcb; + client_conn->time_started = sys_now(); /* @todo: set this again on 'connected' */ + client_conn->poll_count = 0; + client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */ + client_conn->bytes_transferred = 0; + client_conn->settings.flags = 0; /* prevent the remote side starting back as client again */ + + tcp_arg(newpcb, client_conn); + tcp_sent(newpcb, lwiperf_tcp_client_sent); + tcp_poll(newpcb, lwiperf_tcp_poll, 2U); + tcp_err(newpcb, lwiperf_tcp_err); + + ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip); + remote_port = (u16_t)lwip_htonl(client_conn->settings.remote_port); + + err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected); + if (err != ERR_OK) { + lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL); + return err; + } + lwiperf_list_add(&client_conn->base); + return ERR_OK; +} + +/** Receive data on an iperf tcp session */ +static err_t +lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) +{ + u8_t tmp; + u16_t tot_len; + u32_t packet_idx; + struct pbuf* q; + lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; + + LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); + LWIP_UNUSED_ARG(tpcb); + + if (err != ERR_OK) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); + return ERR_OK; + } + if (p == NULL) { + /* connection closed -> test done */ + if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == + PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) { + /* client requested transmission after end of test */ + lwiperf_tx_start(conn); + } + lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER); + return ERR_OK; + } + tot_len = p->tot_len; + + conn->poll_count = 0; + + if ((!conn->have_settings_buf) || ((conn->bytes_transferred -24) % (1024*128) == 0)) { + /* wait for 24-byte header */ + if (p->tot_len < sizeof(lwiperf_settings_t)) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); + pbuf_free(p); + return ERR_VAL; + } + if (!conn->have_settings_buf) { + if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); + pbuf_free(p); + return ERR_VAL; + } + conn->have_settings_buf = 1; + if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == + PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) { + /* client requested parallel transmission test */ + err_t err2 = lwiperf_tx_start(conn); + if (err2 != ERR_OK) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR); + pbuf_free(p); + return err2; + } + } + } else { + if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); + pbuf_free(p); + return ERR_VAL; + } + } + conn->bytes_transferred += sizeof(lwiperf_settings_t); + if (conn->bytes_transferred <= 24) { + conn->time_started = sys_now(); + tcp_recved(tpcb, p->tot_len); + pbuf_free(p); + return ERR_OK; + } + conn->next_num = 4; /* 24 bytes received... */ + tmp = pbuf_header(p, -24); + LWIP_ASSERT("pbuf_header failed", tmp == 0); + } + + packet_idx = 0; + for (q = p; q != NULL; q = q->next) { +#if LWIPERF_CHECK_RX_DATA + const u8_t* payload = (const u8_t*)q->payload; + u16_t i; + for (i = 0; i < q->len; i++) { + u8_t val = payload[i]; + u8_t num = val - '0'; + if (num == conn->next_num) { + conn->next_num++; + if (conn->next_num == 10) { + conn->next_num = 0; + } + } else { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); + pbuf_free(p); + return ERR_VAL; + } + } +#endif + packet_idx += q->len; + } + LWIP_ASSERT("count mismatch", packet_idx == p->tot_len); + conn->bytes_transferred += packet_idx; + tcp_recved(tpcb, tot_len); + pbuf_free(p); + return ERR_OK; +} + +/** Error callback, iperf tcp session aborted */ +static void +lwiperf_tcp_err(void *arg, err_t err) +{ + lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; + LWIP_UNUSED_ARG(err); + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); +} + +/** TCP poll callback, try to send more data */ +static err_t +lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb) +{ + lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; + LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); + LWIP_UNUSED_ARG(tpcb); + if (++conn->poll_count >= LWIPERF_TCP_MAX_IDLE_SEC) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); + return ERR_OK; /* lwiperf_tcp_close frees conn */ + } + + if (!conn->base.server) { + lwiperf_tcp_client_send_more(conn); + } + + return ERR_OK; +} + +/** This is called when a new client connects for an iperf tcp session */ +static err_t +lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + lwiperf_state_tcp_t *s, *conn; + if ((err != ERR_OK) || (newpcb == NULL) || (arg == NULL)) { + return ERR_VAL; + } + + s = (lwiperf_state_tcp_t*)arg; + conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); + if (conn == NULL) { + return ERR_MEM; + } + memset(conn, 0, sizeof(lwiperf_state_tcp_t)); + conn->base.tcp = 1; + conn->base.server = 1; + conn->base.related_server_state = &s->base; + conn->server_pcb = s->server_pcb; + conn->conn_pcb = newpcb; + conn->time_started = sys_now(); + conn->report_fn = s->report_fn; + conn->report_arg = s->report_arg; + + /* setup the tcp rx connection */ + tcp_arg(newpcb, conn); + tcp_recv(newpcb, lwiperf_tcp_recv); + tcp_poll(newpcb, lwiperf_tcp_poll, 2U); + tcp_err(conn->conn_pcb, lwiperf_tcp_err); + + lwiperf_list_add(&conn->base); + return ERR_OK; +} + +/** + * @ingroup iperf + * Start a TCP iperf server on the default TCP port (5001) and listen for + * incoming connections from iperf clients. + * + * @returns a connection handle that can be used to abort the server + * by calling @ref lwiperf_abort() + */ +void* +lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg) +{ + return lwiperf_start_tcp_server(IP_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT, + report_fn, report_arg); +} + +/** + * @ingroup iperf + * Start a TCP iperf server on a specific IP address and port and listen for + * incoming connections from iperf clients. + * + * @returns a connection handle that can be used to abort the server + * by calling @ref lwiperf_abort() + */ +void* +lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port, + lwiperf_report_fn report_fn, void* report_arg) +{ + err_t err; + struct tcp_pcb* pcb; + lwiperf_state_tcp_t* s; + + if (local_addr == NULL) { + return NULL; + } + + s = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); + if (s == NULL) { + return NULL; + } + memset(s, 0, sizeof(lwiperf_state_tcp_t)); + s->base.tcp = 1; + s->base.server = 1; + s->report_fn = report_fn; + s->report_arg = report_arg; + + pcb = tcp_new(); + if (pcb != NULL) { + err = tcp_bind(pcb, local_addr, local_port); + if (err == ERR_OK) { + s->server_pcb = tcp_listen_with_backlog(pcb, 1); + } + } + if (s->server_pcb == NULL) { + if (pcb != NULL) { + tcp_close(pcb); + } + LWIPERF_FREE(lwiperf_state_tcp_t, s); + return NULL; + } + pcb = NULL; + + tcp_arg(s->server_pcb, s); + tcp_accept(s->server_pcb, lwiperf_tcp_accept); + + lwiperf_list_add(&s->base); + return s; +} + +/** + * @ingroup iperf + * Abort an iperf session (handle returned by lwiperf_start_tcp_server*()) + */ +void +lwiperf_abort(void* lwiperf_session) +{ + lwiperf_state_base_t* i, *dealloc, *last = NULL; + + for (i = lwiperf_all_connections; i != NULL; ) { + if ((i == lwiperf_session) || (i->related_server_state == lwiperf_session)) { + dealloc = i; + i = i->next; + if (last != NULL) { + last->next = i; + } + LWIPERF_FREE(lwiperf_state_tcp_t, dealloc); /* @todo: type? */ + } else { + last = i; + i = i->next; + } + } +} + +#endif /* LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/components/net/lwip-2.0.3/src/apps/mdns/mdns.c b/components/net/lwip-2.0.3/src/apps/mdns/mdns.c new file mode 100644 index 0000000000..14334fc856 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/mdns/mdns.c @@ -0,0 +1,2028 @@ +/** + * @file + * MDNS responder implementation + * + * @defgroup mdns MDNS + * @ingroup apps + * + * RFC 6762 - Multicast DNS\n + * RFC 6763 - DNS-Based Service Discovery\n + * + * @verbinclude mdns.txt + * + * Things left to implement: + * ------------------------- + * + * - Probing/conflict resolution + * - Sending goodbye messages (zero ttl) - shutdown, DHCP lease about to expire, DHCP turned off... + * - Checking that source address of unicast requests are on the same network + * - Limiting multicast responses to 1 per second per resource record + * - Fragmenting replies if required + * - Subscribe to netif address/link change events and act on them (currently needs to be done manually) + * - Handling multi-packet known answers + * - Individual known answer detection for all local IPv6 addresses + * - Dynamic size of outgoing packet + */ + +/* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ + +#include "lwip/apps/mdns.h" +#include "lwip/apps/mdns_priv.h" +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/mem.h" +#include "lwip/prot/dns.h" + +#include + +#if LWIP_MDNS_RESPONDER + +#if (LWIP_IPV4 && !LWIP_IGMP) + #error "If you want to use MDNS with IPv4, you have to define LWIP_IGMP=1 in your lwipopts.h" +#endif +#if (LWIP_IPV6 && !LWIP_IPV6_MLD) +#error "If you want to use MDNS with IPv6, you have to define LWIP_IPV6_MLD=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP) + #error "If you want to use MDNS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif + +#if LWIP_IPV4 +#include "lwip/igmp.h" +/* IPv4 multicast group 224.0.0.251 */ +static const ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT; +#endif + +#if LWIP_IPV6 +#include "lwip/mld6.h" +/* IPv6 multicast group FF02::FB */ +static const ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT; +#endif + +#define MDNS_PORT 5353 +#define MDNS_TTL 255 + +/* Stored offsets to beginning of domain names + * Used for compression. + */ +#define NUM_DOMAIN_OFFSETS 10 +#define DOMAIN_JUMP_SIZE 2 +#define DOMAIN_JUMP 0xc000 + +static u8_t mdns_netif_client_id; +static struct udp_pcb *mdns_pcb; + +#define NETIF_TO_HOST(netif) (struct mdns_host*)(netif_get_client_data(netif, mdns_netif_client_id)) + +#define TOPDOMAIN_LOCAL "local" + +#define REVERSE_PTR_TOPDOMAIN "arpa" +#define REVERSE_PTR_V4_DOMAIN "in-addr" +#define REVERSE_PTR_V6_DOMAIN "ip6" + +#define SRV_PRIORITY 0 +#define SRV_WEIGHT 0 + +/* Payload size allocated for each outgoing UDP packet */ +#define OUTPACKET_SIZE 500 + +/* Lookup from hostname -> IPv4 */ +#define REPLY_HOST_A 0x01 +/* Lookup from IPv4/v6 -> hostname */ +#define REPLY_HOST_PTR_V4 0x02 +/* Lookup from hostname -> IPv6 */ +#define REPLY_HOST_AAAA 0x04 +/* Lookup from hostname -> IPv6 */ +#define REPLY_HOST_PTR_V6 0x08 + +/* Lookup for service types */ +#define REPLY_SERVICE_TYPE_PTR 0x10 +/* Lookup for instances of service */ +#define REPLY_SERVICE_NAME_PTR 0x20 +/* Lookup for location of service instance */ +#define REPLY_SERVICE_SRV 0x40 +/* Lookup for text info on service instance */ +#define REPLY_SERVICE_TXT 0x80 + +static const char *dnssd_protos[] = { + "_udp", /* DNSSD_PROTO_UDP */ + "_tcp", /* DNSSD_PROTO_TCP */ +}; + +/** Description of a service */ +struct mdns_service { + /** TXT record to answer with */ + struct mdns_domain txtdata; + /** Name of service, like 'myweb' */ + char name[MDNS_LABEL_MAXLEN + 1]; + /** Type of service, like '_http' */ + char service[MDNS_LABEL_MAXLEN + 1]; + /** Callback function and userdata + * to update txtdata buffer */ + service_get_txt_fn_t txt_fn; + void *txt_userdata; + /** TTL in seconds of SRV/TXT replies */ + u32_t dns_ttl; + /** Protocol, TCP or UDP */ + u16_t proto; + /** Port of the service */ + u16_t port; +}; + +/** Description of a host/netif */ +struct mdns_host { + /** Hostname */ + char name[MDNS_LABEL_MAXLEN + 1]; + /** Pointer to services */ + struct mdns_service *services[MDNS_MAX_SERVICES]; + /** TTL in seconds of A/AAAA/PTR replies */ + u32_t dns_ttl; +}; + +/** Information about received packet */ +struct mdns_packet { + /** Sender IP/port */ + ip_addr_t source_addr; + u16_t source_port; + /** If packet was received unicast */ + u16_t recv_unicast; + /** Netif that received the packet */ + struct netif *netif; + /** Packet data */ + struct pbuf *pbuf; + /** Current parsing offset in packet */ + u16_t parse_offset; + /** Identifier. Used in legacy queries */ + u16_t tx_id; + /** Number of questions in packet, + * read from packet header */ + u16_t questions; + /** Number of unparsed questions */ + u16_t questions_left; + /** Number of answers in packet, + * (sum of normal, authorative and additional answers) + * read from packet header */ + u16_t answers; + /** Number of unparsed answers */ + u16_t answers_left; +}; + +/** Information about outgoing packet */ +struct mdns_outpacket { + /** Netif to send the packet on */ + struct netif *netif; + /** Packet data */ + struct pbuf *pbuf; + /** Current write offset in packet */ + u16_t write_offset; + /** Identifier. Used in legacy queries */ + u16_t tx_id; + /** Destination IP/port if sent unicast */ + ip_addr_t dest_addr; + u16_t dest_port; + /** Number of questions written */ + u16_t questions; + /** Number of normal answers written */ + u16_t answers; + /** Number of additional answers written */ + u16_t additional; + /** Offsets for written domain names in packet. + * Used for compression */ + u16_t domain_offsets[NUM_DOMAIN_OFFSETS]; + /** If all answers in packet should set cache_flush bit */ + u8_t cache_flush; + /** If reply should be sent unicast */ + u8_t unicast_reply; + /** If legacy query. (tx_id needed, and write + * question again in reply before answer) */ + u8_t legacy_query; + /* Reply bitmask for host information */ + u8_t host_replies; + /* Bitmask for which reverse IPv6 hosts to answer */ + u8_t host_reverse_v6_replies; + /* Reply bitmask per service */ + u8_t serv_replies[MDNS_MAX_SERVICES]; +}; + +/** Domain, type and class. + * Shared between questions and answers */ +struct mdns_rr_info { + struct mdns_domain domain; + u16_t type; + u16_t klass; +}; + +struct mdns_question { + struct mdns_rr_info info; + /** unicast reply requested */ + u16_t unicast; +}; + +struct mdns_answer { + struct mdns_rr_info info; + /** cache flush command bit */ + u16_t cache_flush; + /* Validity time in seconds */ + u32_t ttl; + /** Length of variable answer */ + u16_t rd_length; + /** Offset of start of variable answer in packet */ + u16_t rd_offset; +}; + +/** + * Add a label part to a domain + * @param domain The domain to add a label to + * @param label The label to add, like <hostname>, 'local', 'com' or '' + * @param len The length of the label + * @return ERR_OK on success, an err_t otherwise if label too long + */ +err_t +mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len) +{ + if (len > MDNS_LABEL_MAXLEN) { + return ERR_VAL; + } + if (len > 0 && (1 + len + domain->length >= MDNS_DOMAIN_MAXLEN)) { + return ERR_VAL; + } + /* Allow only zero marker on last byte */ + if (len == 0 && (1 + domain->length > MDNS_DOMAIN_MAXLEN)) { + return ERR_VAL; + } + domain->name[domain->length] = len; + domain->length++; + if (len) { + MEMCPY(&domain->name[domain->length], label, len); + domain->length += len; + } + return ERR_OK; +} + +/** + * Internal readname function with max 6 levels of recursion following jumps + * while decompressing name + */ +static u16_t +mdns_readname_loop(struct pbuf *p, u16_t offset, struct mdns_domain *domain, unsigned depth) +{ + u8_t c; + + do { + if (depth > 5) { + /* Too many jumps */ + return MDNS_READNAME_ERROR; + } + + c = pbuf_get_at(p, offset); + offset++; + + /* is this a compressed label? */ + if((c & 0xc0) == 0xc0) { + u16_t jumpaddr; + if (offset >= p->tot_len) { + /* Make sure both jump bytes fit in the packet */ + return MDNS_READNAME_ERROR; + } + jumpaddr = (((c & 0x3f) << 8) | (pbuf_get_at(p, offset) & 0xff)); + offset++; + if (jumpaddr >= SIZEOF_DNS_HDR && jumpaddr < p->tot_len) { + u16_t res; + /* Recursive call, maximum depth will be checked */ + res = mdns_readname_loop(p, jumpaddr, domain, depth + 1); + /* Dont return offset since new bytes were not read (jumped to somewhere in packet) */ + if (res == MDNS_READNAME_ERROR) { + return res; + } + } else { + return MDNS_READNAME_ERROR; + } + break; + } + + /* normal label */ + if (c <= MDNS_LABEL_MAXLEN) { + u8_t label[MDNS_LABEL_MAXLEN]; + err_t res; + + if (c + domain->length >= MDNS_DOMAIN_MAXLEN) { + return MDNS_READNAME_ERROR; + } + if (c != 0) { + if (pbuf_copy_partial(p, label, c, offset) != c) { + return MDNS_READNAME_ERROR; + } + offset += c; + } + res = mdns_domain_add_label(domain, (char *) label, c); + if (res != ERR_OK) { + return MDNS_READNAME_ERROR; + } + } else { + /* bad length byte */ + return MDNS_READNAME_ERROR; + } + } while (c != 0); + + return offset; +} + +/** + * Read possibly compressed domain name from packet buffer + * @param p The packet + * @param offset start position of domain name in packet + * @param domain The domain name destination + * @return The new offset after the domain, or MDNS_READNAME_ERROR + * if reading failed + */ +u16_t +mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain) +{ + memset(domain, 0, sizeof(struct mdns_domain)); + return mdns_readname_loop(p, offset, domain, 0); +} + +/** + * Print domain name to debug output + * @param domain The domain name + */ +static void +mdns_domain_debug_print(struct mdns_domain *domain) +{ + u8_t *src = domain->name; + u8_t i; + + while (*src) { + u8_t label_len = *src; + src++; + for (i = 0; i < label_len; i++) { + LWIP_DEBUGF(MDNS_DEBUG, ("%c", src[i])); + } + src += label_len; + LWIP_DEBUGF(MDNS_DEBUG, (".")); + } +} + +/** + * Return 1 if contents of domains match (case-insensitive) + * @param a Domain name to compare 1 + * @param b Domain name to compare 2 + * @return 1 if domains are equal ignoring case, 0 otherwise + */ +int +mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b) +{ + u8_t *ptra, *ptrb; + u8_t len; + int res; + + if (a->length != b->length) { + return 0; + } + + ptra = a->name; + ptrb = b->name; + while (*ptra && *ptrb && ptra < &a->name[a->length]) { + if (*ptra != *ptrb) { + return 0; + } + len = *ptra; + ptra++; + ptrb++; + res = lwip_strnicmp((char *) ptra, (char *) ptrb, len); + if (res != 0) { + return 0; + } + ptra += len; + ptrb += len; + } + if (*ptra != *ptrb && ptra < &a->name[a->length]) { + return 0; + } + return 1; +} + +/** + * Call user supplied function to setup TXT data + * @param service The service to build TXT record for + */ +static void +mdns_prepare_txtdata(struct mdns_service *service) +{ + memset(&service->txtdata, 0, sizeof(struct mdns_domain)); + if (service->txt_fn) { + service->txt_fn(service, service->txt_userdata); + } +} + +#if LWIP_IPV4 +/** + * Build domain for reverse lookup of IPv4 address + * like 12.0.168.192.in-addr.arpa. for 192.168.0.12 + * @param domain Where to write the domain name + * @param addr Pointer to an IPv4 address to encode + * @return ERR_OK if domain was written, an err_t otherwise + */ +static err_t +mdns_build_reverse_v4_domain(struct mdns_domain *domain, const ip4_addr_t *addr) +{ + int i; + err_t res; + const u8_t *ptr; + if (!domain || !addr) { + return ERR_ARG; + } + memset(domain, 0, sizeof(struct mdns_domain)); + ptr = (const u8_t *) addr; + for (i = sizeof(ip4_addr_t) - 1; i >= 0; i--) { + char buf[4]; + u8_t val = ptr[i]; + + lwip_itoa(buf, sizeof(buf), val); + res = mdns_domain_add_label(domain, buf, (u8_t)strlen(buf)); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + } + res = mdns_domain_add_label(domain, REVERSE_PTR_V4_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V4_DOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, NULL, 0); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + + return ERR_OK; +} +#endif + +#if LWIP_IPV6 +/** + * Build domain for reverse lookup of IP address + * like b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. for 2001:db8::567:89ab + * @param domain Where to write the domain name + * @param addr Pointer to an IPv6 address to encode + * @return ERR_OK if domain was written, an err_t otherwise + */ +static err_t +mdns_build_reverse_v6_domain(struct mdns_domain *domain, const ip6_addr_t *addr) +{ + int i; + err_t res; + const u8_t *ptr; + if (!domain || !addr) { + return ERR_ARG; + } + memset(domain, 0, sizeof(struct mdns_domain)); + ptr = (const u8_t *) addr; + for (i = sizeof(ip6_addr_t) - 1; i >= 0; i--) { + char buf; + u8_t byte = ptr[i]; + int j; + for (j = 0; j < 2; j++) { + if ((byte & 0x0F) < 0xA) { + buf = '0' + (byte & 0x0F); + } else { + buf = 'a' + (byte & 0x0F) - 0xA; + } + res = mdns_domain_add_label(domain, &buf, sizeof(buf)); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + byte >>= 4; + } + } + res = mdns_domain_add_label(domain, REVERSE_PTR_V6_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V6_DOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, NULL, 0); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + + return ERR_OK; +} +#endif + +/* Add .local. to domain */ +static err_t +mdns_add_dotlocal(struct mdns_domain *domain) +{ + err_t res = mdns_domain_add_label(domain, TOPDOMAIN_LOCAL, (u8_t)(sizeof(TOPDOMAIN_LOCAL)-1)); + LWIP_ERROR("mdns_add_dotlocal: Failed to add label", (res == ERR_OK), return res); + return mdns_domain_add_label(domain, NULL, 0); +} + +/** + * Build the .local. domain name + * @param domain Where to write the domain name + * @param mdns TMDNS netif descriptor. + * @return ERR_OK if domain .local. was written, an err_t otherwise + */ +static err_t +mdns_build_host_domain(struct mdns_domain *domain, struct mdns_host *mdns) +{ + err_t res; + memset(domain, 0, sizeof(struct mdns_domain)); + LWIP_ERROR("mdns_build_host_domain: mdns != NULL", (mdns != NULL), return ERR_VAL); + res = mdns_domain_add_label(domain, mdns->name, (u8_t)strlen(mdns->name)); + LWIP_ERROR("mdns_build_host_domain: Failed to add label", (res == ERR_OK), return res); + return mdns_add_dotlocal(domain); +} + +/** + * Build the lookup-all-services special DNS-SD domain name + * @param domain Where to write the domain name + * @return ERR_OK if domain _services._dns-sd._udp.local. was written, an err_t otherwise + */ +static err_t +mdns_build_dnssd_domain(struct mdns_domain *domain) +{ + err_t res; + memset(domain, 0, sizeof(struct mdns_domain)); + res = mdns_domain_add_label(domain, "_services", (u8_t)(sizeof("_services")-1)); + LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, "_dns-sd", (u8_t)(sizeof("_dns-sd")-1)); + LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)strlen(dnssd_protos[DNSSD_PROTO_UDP])); + LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); + return mdns_add_dotlocal(domain); +} + +/** + * Build domain name for a service + * @param domain Where to write the domain name + * @param service The service struct, containing service name, type and protocol + * @param include_name Whether to include the service name in the domain + * @return ERR_OK if domain was written. If service name is included, + * ...local. will be written, otherwise ..local. + * An err_t is returned on error. + */ +static err_t +mdns_build_service_domain(struct mdns_domain *domain, struct mdns_service *service, int include_name) +{ + err_t res; + memset(domain, 0, sizeof(struct mdns_domain)); + if (include_name) { + res = mdns_domain_add_label(domain, service->name, (u8_t)strlen(service->name)); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + } + res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service)); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)strlen(dnssd_protos[service->proto])); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + return mdns_add_dotlocal(domain); +} + +/** + * Check which replies we should send for a host/netif based on question + * @param netif The network interface that received the question + * @param rr Domain/type/class from a question + * @param reverse_v6_reply Bitmask of which IPv6 addresses to send reverse PTRs for + * if reply bit has REPLY_HOST_PTR_V6 set + * @return Bitmask of which replies to send + */ +static int +check_host(struct netif *netif, struct mdns_rr_info *rr, u8_t *reverse_v6_reply) +{ + err_t res; + int replies = 0; + struct mdns_domain mydomain; + + LWIP_UNUSED_ARG(reverse_v6_reply); /* if ipv6 is disabled */ + + if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { + /* Invalid class */ + return replies; + } + + /* Handle PTR for our addresses */ + if (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY) { +#if LWIP_IPV6 + int i; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { + res = mdns_build_reverse_v6_domain(&mydomain, netif_ip6_addr(netif, i)); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + replies |= REPLY_HOST_PTR_V6; + /* Mark which addresses where requested */ + if (reverse_v6_reply) { + *reverse_v6_reply |= (1 << i); + } + } + } + } +#endif +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { + res = mdns_build_reverse_v4_domain(&mydomain, netif_ip4_addr(netif)); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + replies |= REPLY_HOST_PTR_V4; + } + } +#endif + } + + res = mdns_build_host_domain(&mydomain, NETIF_TO_HOST(netif)); + /* Handle requests for our hostname */ + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + /* TODO return NSEC if unsupported protocol requested */ +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) + && (rr->type == DNS_RRTYPE_A || rr->type == DNS_RRTYPE_ANY)) { + replies |= REPLY_HOST_A; + } +#endif +#if LWIP_IPV6 + if (rr->type == DNS_RRTYPE_AAAA || rr->type == DNS_RRTYPE_ANY) { + replies |= REPLY_HOST_AAAA; + } +#endif + } + + return replies; +} + +/** + * Check which replies we should send for a service based on question + * @param service A registered MDNS service + * @param rr Domain/type/class from a question + * @return Bitmask of which replies to send + */ +static int +check_service(struct mdns_service *service, struct mdns_rr_info *rr) +{ + err_t res; + int replies = 0; + struct mdns_domain mydomain; + + if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { + /* Invalid class */ + return 0; + } + + res = mdns_build_dnssd_domain(&mydomain); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && + (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { + /* Request for all service types */ + replies |= REPLY_SERVICE_TYPE_PTR; + } + + res = mdns_build_service_domain(&mydomain, service, 0); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && + (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { + /* Request for the instance of my service */ + replies |= REPLY_SERVICE_NAME_PTR; + } + + res = mdns_build_service_domain(&mydomain, service, 1); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + /* Request for info about my service */ + if (rr->type == DNS_RRTYPE_SRV || rr->type == DNS_RRTYPE_ANY) { + replies |= REPLY_SERVICE_SRV; + } + if (rr->type == DNS_RRTYPE_TXT || rr->type == DNS_RRTYPE_ANY) { + replies |= REPLY_SERVICE_TXT; + } + } + + return replies; +} + +/** + * Return bytes needed to write before jump for best result of compressing supplied domain + * against domain in outpacket starting at specified offset. + * If a match is found, offset is updated to where to jump to + * @param pbuf Pointer to pbuf with the partially constructed DNS packet + * @param offset Start position of a domain written earlier. If this location is suitable + * for compression, the pointer is updated to where in the domain to jump to. + * @param domain The domain to write + * @return Number of bytes to write of the new domain before writing a jump to the offset. + * If compression can not be done against this previous domain name, the full new + * domain length is returned. + */ +u16_t +mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain) +{ + struct mdns_domain target; + u16_t target_end; + u8_t target_len; + u8_t writelen = 0; + u8_t *ptr; + if (pbuf == NULL) { + return domain->length; + } + target_end = mdns_readname(pbuf, *offset, &target); + if (target_end == MDNS_READNAME_ERROR) { + return domain->length; + } + target_len = (u8_t)(target_end - *offset); + ptr = domain->name; + while (writelen < domain->length) { + u8_t domainlen = (u8_t)(domain->length - writelen); + u8_t labellen; + if (domainlen <= target.length && domainlen > DOMAIN_JUMP_SIZE) { + /* Compare domains if target is long enough, and we have enough left of the domain */ + u8_t targetpos = (u8_t)(target.length - domainlen); + if ((targetpos + DOMAIN_JUMP_SIZE) >= target_len) { + /* We are checking at or beyond a jump in the original, stop looking */ + break; + } + if (target.length >= domainlen && + memcmp(&domain->name[writelen], &target.name[targetpos], domainlen) == 0) { + *offset += targetpos; + return writelen; + } + } + /* Skip to next label in domain */ + labellen = *ptr; + writelen += 1 + labellen; + ptr += 1 + labellen; + } + /* Nothing found */ + return domain->length; +} + +/** + * Write domain to outpacket. Compression will be attempted, + * unless domain->skip_compression is set. + * @param outpkt The outpacket to write to + * @param domain The domain name to write + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_write_domain(struct mdns_outpacket *outpkt, struct mdns_domain *domain) +{ + int i; + err_t res; + u16_t writelen = domain->length; + u16_t jump_offset = 0; + u16_t jump; + + if (!domain->skip_compression) { + for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) { + u16_t offset = outpkt->domain_offsets[i]; + if (offset) { + u16_t len = mdns_compress_domain(outpkt->pbuf, &offset, domain); + if (len < writelen) { + writelen = len; + jump_offset = offset; + } + } + } + } + + if (writelen) { + /* Write uncompressed part of name */ + res = pbuf_take_at(outpkt->pbuf, domain->name, writelen, outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + + /* Store offset of this new domain */ + for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) { + if (outpkt->domain_offsets[i] == 0) { + outpkt->domain_offsets[i] = outpkt->write_offset; + break; + } + } + + outpkt->write_offset += writelen; + } + if (jump_offset) { + /* Write jump */ + jump = lwip_htons(DOMAIN_JUMP | jump_offset); + res = pbuf_take_at(outpkt->pbuf, &jump, DOMAIN_JUMP_SIZE, outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + outpkt->write_offset += DOMAIN_JUMP_SIZE; + } + return ERR_OK; +} + +/** + * Write a question to an outpacket + * A question contains domain, type and class. Since an answer also starts with these fields this function is also + * called from mdns_add_answer(). + * @param outpkt The outpacket to write to + * @param domain The domain name the answer is for + * @param type The DNS type of the answer (like 'AAAA', 'SRV') + * @param klass The DNS type of the answer (like 'IN') + * @param unicast If highest bit in class should be set, to instruct the responder to + * reply with a unicast packet + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_add_question(struct mdns_outpacket *outpkt, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t unicast) +{ + u16_t question_len; + u16_t field16; + err_t res; + + if (!outpkt->pbuf) { + /* If no pbuf is active, allocate one */ + outpkt->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); + if (!outpkt->pbuf) { + return ERR_MEM; + } + outpkt->write_offset = SIZEOF_DNS_HDR; + } + + /* Worst case calculation. Domain string might be compressed */ + question_len = domain->length + sizeof(type) + sizeof(klass); + if (outpkt->write_offset + question_len > outpkt->pbuf->tot_len) { + /* No space */ + return ERR_MEM; + } + + /* Write name */ + res = mdns_write_domain(outpkt, domain); + if (res != ERR_OK) { + return res; + } + + /* Write type */ + field16 = lwip_htons(type); + res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + outpkt->write_offset += sizeof(field16); + + /* Write class */ + if (unicast) { + klass |= 0x8000; + } + field16 = lwip_htons(klass); + res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + outpkt->write_offset += sizeof(field16); + + return ERR_OK; +} + +/** + * Write answer to reply packet. + * buf or answer_domain can be null. The rd_length written will be buf_length + + * size of (compressed) domain. Most uses will need either buf or answer_domain, + * special case is SRV that starts with 3 u16 and then a domain name. + * @param reply The outpacket to write to + * @param domain The domain name the answer is for + * @param type The DNS type of the answer (like 'AAAA', 'SRV') + * @param klass The DNS type of the answer (like 'IN') + * @param cache_flush If highest bit in class should be set, to instruct receiver that + * this reply replaces any earlier answer for this domain/type/class + * @param ttl Validity time in seconds to send out for IP address data in DNS replies + * @param buf Pointer to buffer of answer data + * @param buf_length Length of variable data + * @param answer_domain A domain to write after any buffer data as answer + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_add_answer(struct mdns_outpacket *reply, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t cache_flush, + u32_t ttl, const u8_t *buf, size_t buf_length, struct mdns_domain *answer_domain) +{ + u16_t answer_len; + u16_t field16; + u16_t rdlen_offset; + u16_t answer_offset; + u32_t field32; + err_t res; + + if (!reply->pbuf) { + /* If no pbuf is active, allocate one */ + reply->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); + if (!reply->pbuf) { + return ERR_MEM; + } + reply->write_offset = SIZEOF_DNS_HDR; + } + + /* Worst case calculation. Domain strings might be compressed */ + answer_len = domain->length + sizeof(type) + sizeof(klass) + sizeof(ttl) + sizeof(field16)/*rd_length*/; + if (buf) { + answer_len += (u16_t)buf_length; + } + if (answer_domain) { + answer_len += answer_domain->length; + } + if (reply->write_offset + answer_len > reply->pbuf->tot_len) { + /* No space */ + return ERR_MEM; + } + + /* Answer starts with same data as question, then more fields */ + mdns_add_question(reply, domain, type, klass, cache_flush); + + /* Write TTL */ + field32 = lwip_htonl(ttl); + res = pbuf_take_at(reply->pbuf, &field32, sizeof(field32), reply->write_offset); + if (res != ERR_OK) { + return res; + } + reply->write_offset += sizeof(field32); + + /* Store offsets and skip forward to the data */ + rdlen_offset = reply->write_offset; + reply->write_offset += sizeof(field16); + answer_offset = reply->write_offset; + + if (buf) { + /* Write static data */ + res = pbuf_take_at(reply->pbuf, buf, (u16_t)buf_length, reply->write_offset); + if (res != ERR_OK) { + return res; + } + reply->write_offset += (u16_t)buf_length; + } + + if (answer_domain) { + /* Write name answer (compressed if possible) */ + res = mdns_write_domain(reply, answer_domain); + if (res != ERR_OK) { + return res; + } + } + + /* Write rd_length after when we know the answer size */ + field16 = lwip_htons(reply->write_offset - answer_offset); + res = pbuf_take_at(reply->pbuf, &field16, sizeof(field16), rdlen_offset); + + return res; +} + +/** + * Helper function for mdns_read_question/mdns_read_answer + * Reads a domain, type and class from the packet + * @param pkt The MDNS packet to read from. The parse_offset field will be + * incremented to point to the next unparsed byte. + * @param info The struct to fill with domain, type and class + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_read_rr_info(struct mdns_packet *pkt, struct mdns_rr_info *info) +{ + u16_t field16, copied; + pkt->parse_offset = mdns_readname(pkt->pbuf, pkt->parse_offset, &info->domain); + if (pkt->parse_offset == MDNS_READNAME_ERROR) { + return ERR_VAL; + } + + copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); + if (copied != sizeof(field16)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + info->type = lwip_ntohs(field16); + + copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); + if (copied != sizeof(field16)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + info->klass = lwip_ntohs(field16); + + return ERR_OK; +} + +/** + * Read a question from the packet. + * All questions have to be read before the answers. + * @param pkt The MDNS packet to read from. The questions_left field will be decremented + * and the parse_offset will be updated. + * @param question The struct to fill with question data + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_read_question(struct mdns_packet *pkt, struct mdns_question *question) +{ + /* Safety check */ + if (pkt->pbuf->tot_len < pkt->parse_offset) { + return ERR_VAL; + } + + if (pkt->questions_left) { + err_t res; + pkt->questions_left--; + + memset(question, 0, sizeof(struct mdns_question)); + res = mdns_read_rr_info(pkt, &question->info); + if (res != ERR_OK) { + return res; + } + + /* Extract unicast flag from class field */ + question->unicast = question->info.klass & 0x8000; + question->info.klass &= 0x7FFF; + + return ERR_OK; + } + return ERR_VAL; +} + +/** + * Read an answer from the packet + * The variable length reply is not copied, its pbuf offset and length is stored instead. + * @param pkt The MDNS packet to read. The answers_left field will be decremented and + * the parse_offset will be updated. + * @param answer The struct to fill with answer data + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_read_answer(struct mdns_packet *pkt, struct mdns_answer *answer) +{ + /* Read questions first */ + if (pkt->questions_left) { + return ERR_VAL; + } + + /* Safety check */ + if (pkt->pbuf->tot_len < pkt->parse_offset) { + return ERR_VAL; + } + + if (pkt->answers_left) { + u16_t copied, field16; + u32_t ttl; + err_t res; + pkt->answers_left--; + + memset(answer, 0, sizeof(struct mdns_answer)); + res = mdns_read_rr_info(pkt, &answer->info); + if (res != ERR_OK) { + return res; + } + + /* Extract cache_flush flag from class field */ + answer->cache_flush = answer->info.klass & 0x8000; + answer->info.klass &= 0x7FFF; + + copied = pbuf_copy_partial(pkt->pbuf, &ttl, sizeof(ttl), pkt->parse_offset); + if (copied != sizeof(ttl)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + answer->ttl = lwip_ntohl(ttl); + + copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); + if (copied != sizeof(field16)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + answer->rd_length = lwip_ntohs(field16); + + answer->rd_offset = pkt->parse_offset; + pkt->parse_offset += answer->rd_length; + + return ERR_OK; + } + return ERR_VAL; +} + +#if LWIP_IPV4 +/** Write an IPv4 address (A) RR to outpacket */ +static err_t +mdns_add_a_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) +{ + struct mdns_domain host; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with A record\n")); + return mdns_add_answer(reply, &host, DNS_RRTYPE_A, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip4_addr(netif), sizeof(ip4_addr_t), NULL); +} + +/** Write a 4.3.2.1.in-addr.arpa -> hostname.local PTR RR to outpacket */ +static err_t +mdns_add_hostv4_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) +{ + struct mdns_domain host, revhost; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + mdns_build_reverse_v4_domain(&revhost, netif_ip4_addr(netif)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v4 PTR record\n")); + return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); +} +#endif + +#if LWIP_IPV6 +/** Write an IPv6 address (AAAA) RR to outpacket */ +static err_t +mdns_add_aaaa_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) +{ + struct mdns_domain host; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with AAAA record\n")); + return mdns_add_answer(reply, &host, DNS_RRTYPE_AAAA, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip6_addr(netif, addrindex), sizeof(ip6_addr_t), NULL); +} + +/** Write a x.y.z.ip6.arpa -> hostname.local PTR RR to outpacket */ +static err_t +mdns_add_hostv6_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) +{ + struct mdns_domain host, revhost; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + mdns_build_reverse_v6_domain(&revhost, netif_ip6_addr(netif, addrindex)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v6 PTR record\n")); + return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); +} +#endif + +/** Write an all-services -> servicetype PTR RR to outpacket */ +static err_t +mdns_add_servicetype_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) +{ + struct mdns_domain service_type, service_dnssd; + mdns_build_service_domain(&service_type, service, 0); + mdns_build_dnssd_domain(&service_dnssd); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service type PTR record\n")); + return mdns_add_answer(reply, &service_dnssd, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_type); +} + +/** Write a servicetype -> servicename PTR RR to outpacket */ +static err_t +mdns_add_servicename_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) +{ + struct mdns_domain service_type, service_instance; + mdns_build_service_domain(&service_type, service, 0); + mdns_build_service_domain(&service_instance, service, 1); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service name PTR record\n")); + return mdns_add_answer(reply, &service_type, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_instance); +} + +/** Write a SRV RR to outpacket */ +static err_t +mdns_add_srv_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_host *mdns, struct mdns_service *service) +{ + struct mdns_domain service_instance, srvhost; + u16_t srvdata[3]; + mdns_build_service_domain(&service_instance, service, 1); + mdns_build_host_domain(&srvhost, mdns); + if (reply->legacy_query) { + /* RFC 6762 section 18.14: + * In legacy unicast responses generated to answer legacy queries, + * name compression MUST NOT be performed on SRV records. + */ + srvhost.skip_compression = 1; + } + srvdata[0] = lwip_htons(SRV_PRIORITY); + srvdata[1] = lwip_htons(SRV_WEIGHT); + srvdata[2] = lwip_htons(service->port); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with SRV record\n")); + return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_SRV, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, + (const u8_t *) &srvdata, sizeof(srvdata), &srvhost); +} + +/** Write a TXT RR to outpacket */ +static err_t +mdns_add_txt_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_service *service) +{ + struct mdns_domain service_instance; + mdns_build_service_domain(&service_instance, service, 1); + mdns_prepare_txtdata(service); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with TXT record\n")); + return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_TXT, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, + (u8_t *) &service->txtdata.name, service->txtdata.length, NULL); +} + +/** + * Setup outpacket as a reply to the incoming packet + */ +static void +mdns_init_outpacket(struct mdns_outpacket *out, struct mdns_packet *in) +{ + memset(out, 0, sizeof(struct mdns_outpacket)); + out->cache_flush = 1; + out->netif = in->netif; + + /* Copy source IP/port to use when responding unicast, or to choose + * which pcb to use for multicast (IPv4/IPv6) + */ + SMEMCPY(&out->dest_addr, &in->source_addr, sizeof(ip_addr_t)); + out->dest_port = in->source_port; + + if (in->source_port != MDNS_PORT) { + out->unicast_reply = 1; + out->cache_flush = 0; + if (in->questions == 1) { + out->legacy_query = 1; + out->tx_id = in->tx_id; + } + } + + if (in->recv_unicast) { + out->unicast_reply = 1; + } +} + +/** + * Send chosen answers as a reply + * + * Add all selected answers (first write will allocate pbuf) + * Add additional answers based on the selected answers + * Send the packet + */ +static void +mdns_send_outpacket(struct mdns_outpacket *outpkt) +{ + struct mdns_service *service; + err_t res; + int i; + struct mdns_host* mdns = NETIF_TO_HOST(outpkt->netif); + + /* Write answers to host questions */ +#if LWIP_IPV4 + if (outpkt->host_replies & REPLY_HOST_A) { + res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + if (outpkt->host_replies & REPLY_HOST_PTR_V4) { + res = mdns_add_hostv4_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } +#endif +#if LWIP_IPV6 + if (outpkt->host_replies & REPLY_HOST_AAAA) { + int addrindex; + for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) { + if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { + res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + } + } + if (outpkt->host_replies & REPLY_HOST_PTR_V6) { + u8_t rev_addrs = outpkt->host_reverse_v6_replies; + int addrindex = 0; + while (rev_addrs) { + if (rev_addrs & 1) { + res = mdns_add_hostv6_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + addrindex++; + rev_addrs >>= 1; + } + } +#endif + + /* Write answers to service questions */ + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_TYPE_PTR) { + res = mdns_add_servicetype_ptr_answer(outpkt, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { + res = mdns_add_servicename_ptr_answer(outpkt, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_SRV) { + res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_TXT) { + res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + } + + /* All answers written, add additional RRs */ + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { + /* Our service instance requested, include SRV & TXT + * if they are already not requested. */ + if (!(outpkt->serv_replies[i] & REPLY_SERVICE_SRV)) { + res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } + + if (!(outpkt->serv_replies[i] & REPLY_SERVICE_TXT)) { + res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } + } + + /* If service instance, SRV, record or an IP address is requested, + * supply all addresses for the host + */ + if ((outpkt->serv_replies[i] & (REPLY_SERVICE_NAME_PTR | REPLY_SERVICE_SRV)) || + (outpkt->host_replies & (REPLY_HOST_A | REPLY_HOST_AAAA))) { +#if LWIP_IPV6 + if (!(outpkt->host_replies & REPLY_HOST_AAAA)) { + int addrindex; + for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) { + if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { + res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } + } + } +#endif +#if LWIP_IPV4 + if (!(outpkt->host_replies & REPLY_HOST_A)) { + res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } +#endif + } + } + + if (outpkt->pbuf) { + const ip_addr_t *mcast_destaddr; + struct dns_hdr hdr; + + /* Write header */ + memset(&hdr, 0, sizeof(hdr)); + hdr.flags1 = DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE; + hdr.numanswers = lwip_htons(outpkt->answers); + hdr.numextrarr = lwip_htons(outpkt->additional); + if (outpkt->legacy_query) { + hdr.numquestions = lwip_htons(1); + hdr.id = lwip_htons(outpkt->tx_id); + } + pbuf_take(outpkt->pbuf, &hdr, sizeof(hdr)); + + /* Shrink packet */ + pbuf_realloc(outpkt->pbuf, outpkt->write_offset); + + if (IP_IS_V6_VAL(outpkt->dest_addr)) { +#if LWIP_IPV6 + mcast_destaddr = &v6group; +#endif + } else { +#if LWIP_IPV4 + mcast_destaddr = &v4group; +#endif + } + /* Send created packet */ + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Sending packet, len=%d, unicast=%d\n", outpkt->write_offset, outpkt->unicast_reply)); + if (outpkt->unicast_reply) { + udp_sendto_if(mdns_pcb, outpkt->pbuf, &outpkt->dest_addr, outpkt->dest_port, outpkt->netif); + } else { + udp_sendto_if(mdns_pcb, outpkt->pbuf, mcast_destaddr, MDNS_PORT, outpkt->netif); + } + } + +cleanup: + if (outpkt->pbuf) { + pbuf_free(outpkt->pbuf); + outpkt->pbuf = NULL; + } +} + +/** + * Send unsolicited answer containing all our known data + * @param netif The network interface to send on + * @param destination The target address to send to (usually multicast address) + */ +static void +mdns_announce(struct netif *netif, const ip_addr_t *destination) +{ + struct mdns_outpacket announce; + int i; + struct mdns_host* mdns = NETIF_TO_HOST(netif); + + memset(&announce, 0, sizeof(announce)); + announce.netif = netif; + announce.cache_flush = 1; +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) + announce.host_replies = REPLY_HOST_A | REPLY_HOST_PTR_V4; +#endif +#if LWIP_IPV6 + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { + announce.host_replies |= REPLY_HOST_AAAA | REPLY_HOST_PTR_V6; + announce.host_reverse_v6_replies |= (1 << i); + } + } +#endif + + for (i = 0; i < MDNS_MAX_SERVICES; i++) { + struct mdns_service *serv = mdns->services[i]; + if (serv) { + announce.serv_replies[i] = REPLY_SERVICE_TYPE_PTR | REPLY_SERVICE_NAME_PTR | + REPLY_SERVICE_SRV | REPLY_SERVICE_TXT; + } + } + + announce.dest_port = MDNS_PORT; + SMEMCPY(&announce.dest_addr, destination, sizeof(announce.dest_addr)); + mdns_send_outpacket(&announce); +} + +/** + * Handle question MDNS packet + * 1. Parse all questions and set bits what answers to send + * 2. Clear pending answers if known answers are supplied + * 3. Put chosen answers in new packet and send as reply + */ +static void +mdns_handle_question(struct mdns_packet *pkt) +{ + struct mdns_service *service; + struct mdns_outpacket reply; + int replies = 0; + int i; + err_t res; + struct mdns_host* mdns = NETIF_TO_HOST(pkt->netif); + + mdns_init_outpacket(&reply, pkt); + + while (pkt->questions_left) { + struct mdns_question q; + + res = mdns_read_question(pkt, &q); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping query packet\n")); + return; + } + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Query for domain ")); + mdns_domain_debug_print(&q.info.domain); + LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", q.info.type, q.info.klass)); + + if (q.unicast) { + /* Reply unicast if any question is unicast */ + reply.unicast_reply = 1; + } + + reply.host_replies |= check_host(pkt->netif, &q.info, &reply.host_reverse_v6_replies); + replies |= reply.host_replies; + + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + reply.serv_replies[i] |= check_service(service, &q.info); + replies |= reply.serv_replies[i]; + } + + if (replies && reply.legacy_query) { + /* Add question to reply packet (legacy packet only has 1 question) */ + res = mdns_add_question(&reply, &q.info.domain, q.info.type, q.info.klass, 0); + if (res != ERR_OK) { + goto cleanup; + } + } + } + + /* Handle known answers */ + while (pkt->answers_left) { + struct mdns_answer ans; + u8_t rev_v6; + int match; + + res = mdns_read_answer(pkt, &ans); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping query packet\n")); + goto cleanup; + } + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Known answer for domain ")); + mdns_domain_debug_print(&ans.info.domain); + LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); + + + if (ans.info.type == DNS_RRTYPE_ANY || ans.info.klass == DNS_RRCLASS_ANY) { + /* Skip known answers for ANY type & class */ + continue; + } + + rev_v6 = 0; + match = reply.host_replies & check_host(pkt->netif, &ans.info, &rev_v6); + if (match && (ans.ttl > (mdns->dns_ttl / 2))) { + /* The RR in the known answer matches an RR we are planning to send, + * and the TTL is less than half gone. + * If the payload matches we should not send that answer. + */ + if (ans.info.type == DNS_RRTYPE_PTR) { + /* Read domain and compare */ + struct mdns_domain known_ans, my_ans; + u16_t len; + len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); + res = mdns_build_host_domain(&my_ans, mdns); + if (len != MDNS_READNAME_ERROR && res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { +#if LWIP_IPV4 + if (match & REPLY_HOST_PTR_V4) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v4 PTR\n")); + reply.host_replies &= ~REPLY_HOST_PTR_V4; + } +#endif +#if LWIP_IPV6 + if (match & REPLY_HOST_PTR_V6) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v6 PTR\n")); + reply.host_reverse_v6_replies &= ~rev_v6; + if (reply.host_reverse_v6_replies == 0) { + reply.host_replies &= ~REPLY_HOST_PTR_V6; + } + } +#endif + } + } else if (match & REPLY_HOST_A) { +#if LWIP_IPV4 + if (ans.rd_length == sizeof(ip4_addr_t) && + pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip4_addr(pkt->netif), ans.rd_length) == 0) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: A\n")); + reply.host_replies &= ~REPLY_HOST_A; + } +#endif + } else if (match & REPLY_HOST_AAAA) { +#if LWIP_IPV6 + if (ans.rd_length == sizeof(ip6_addr_t) && + /* TODO this clears all AAAA responses if first addr is set as known */ + pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip6_addr(pkt->netif, 0), ans.rd_length) == 0) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: AAAA\n")); + reply.host_replies &= ~REPLY_HOST_AAAA; + } +#endif + } + } + + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + match = reply.serv_replies[i] & check_service(service, &ans.info); + if (match && (ans.ttl > (service->dns_ttl / 2))) { + /* The RR in the known answer matches an RR we are planning to send, + * and the TTL is less than half gone. + * If the payload matches we should not send that answer. + */ + if (ans.info.type == DNS_RRTYPE_PTR) { + /* Read domain and compare */ + struct mdns_domain known_ans, my_ans; + u16_t len; + len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); + if (len != MDNS_READNAME_ERROR) { + if (match & REPLY_SERVICE_TYPE_PTR) { + res = mdns_build_service_domain(&my_ans, service, 0); + if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service type PTR\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_TYPE_PTR; + } + } + if (match & REPLY_SERVICE_NAME_PTR) { + res = mdns_build_service_domain(&my_ans, service, 1); + if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service name PTR\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_NAME_PTR; + } + } + } + } else if (match & REPLY_SERVICE_SRV) { + /* Read and compare to my SRV record */ + u16_t field16, len, read_pos; + struct mdns_domain known_ans, my_ans; + read_pos = ans.rd_offset; + do { + /* Check priority field */ + len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); + if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_PRIORITY) { + break; + } + read_pos += len; + /* Check weight field */ + len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); + if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_WEIGHT) { + break; + } + read_pos += len; + /* Check port field */ + len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); + if (len != sizeof(field16) || lwip_ntohs(field16) != service->port) { + break; + } + read_pos += len; + /* Check host field */ + len = mdns_readname(pkt->pbuf, read_pos, &known_ans); + mdns_build_host_domain(&my_ans, mdns); + if (len == MDNS_READNAME_ERROR || !mdns_domain_eq(&known_ans, &my_ans)) { + break; + } + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: SRV\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_SRV; + } while (0); + } else if (match & REPLY_SERVICE_TXT) { + mdns_prepare_txtdata(service); + if (service->txtdata.length == ans.rd_length && + pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: TXT\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_TXT; + } + } + } + } + } + + mdns_send_outpacket(&reply); + +cleanup: + if (reply.pbuf) { + /* This should only happen if we fail to alloc/write question for legacy query */ + pbuf_free(reply.pbuf); + reply.pbuf = NULL; + } +} + +/** + * Handle response MDNS packet + * Only prints debug for now. Will need more code to do conflict resolution. + */ +static void +mdns_handle_response(struct mdns_packet *pkt) +{ + /* Ignore all questions */ + while (pkt->questions_left) { + struct mdns_question q; + err_t res; + + res = mdns_read_question(pkt, &q); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping response packet\n")); + return; + } + } + + while (pkt->answers_left) { + struct mdns_answer ans; + err_t res; + + res = mdns_read_answer(pkt, &ans); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping response packet\n")); + return; + } + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Answer for domain ")); + mdns_domain_debug_print(&ans.info.domain); + LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); + } +} + +/** + * Receive input function for MDNS packets. + * Handles both IPv4 and IPv6 UDP pcbs. + */ +static void +mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + struct dns_hdr hdr; + struct mdns_packet packet; + struct netif *recv_netif = ip_current_input_netif(); + u16_t offset = 0; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Received IPv%d MDNS packet, len %d\n", IP_IS_V6(addr)? 6 : 4, p->tot_len)); + + if (NETIF_TO_HOST(recv_netif) == NULL) { + /* From netif not configured for MDNS */ + goto dealloc; + } + + if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, offset) < SIZEOF_DNS_HDR) { + /* Too small */ + goto dealloc; + } + offset += SIZEOF_DNS_HDR; + + if (DNS_HDR_GET_OPCODE(&hdr)) { + /* Ignore non-standard queries in multicast packets (RFC 6762, section 18.3) */ + goto dealloc; + } + + memset(&packet, 0, sizeof(packet)); + SMEMCPY(&packet.source_addr, addr, sizeof(packet.source_addr)); + packet.source_port = port; + packet.netif = recv_netif; + packet.pbuf = p; + packet.parse_offset = offset; + packet.tx_id = lwip_ntohs(hdr.id); + packet.questions = packet.questions_left = lwip_ntohs(hdr.numquestions); + packet.answers = packet.answers_left = lwip_ntohs(hdr.numanswers) + lwip_ntohs(hdr.numauthrr) + lwip_ntohs(hdr.numextrarr); + +#if LWIP_IPV6 + if (IP_IS_V6(ip_current_dest_addr())) { + if (!ip_addr_cmp(ip_current_dest_addr(), &v6group)) { + packet.recv_unicast = 1; + } + } +#endif +#if LWIP_IPV4 + if (!IP_IS_V6(ip_current_dest_addr())) { + if (!ip_addr_cmp(ip_current_dest_addr(), &v4group)) { + packet.recv_unicast = 1; + } + } +#endif + + if (hdr.flags1 & DNS_FLAG1_RESPONSE) { + mdns_handle_response(&packet); + } else { + mdns_handle_question(&packet); + } + +dealloc: + pbuf_free(p); +} + +/** + * @ingroup mdns + * Initiate MDNS responder. Will open UDP sockets on port 5353 + */ +void +mdns_resp_init(void) +{ + err_t res; + + mdns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ASSERT("Failed to allocate pcb", mdns_pcb != NULL); +#if LWIP_MULTICAST_TX_OPTIONS + udp_set_multicast_ttl(mdns_pcb, MDNS_TTL); +#else + mdns_pcb->ttl = MDNS_TTL; +#endif + res = udp_bind(mdns_pcb, IP_ANY_TYPE, MDNS_PORT); + LWIP_UNUSED_ARG(res); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("Failed to bind pcb", res == ERR_OK); + udp_recv(mdns_pcb, mdns_recv, NULL); + + mdns_netif_client_id = netif_alloc_client_data_id(); +} + +/** + * @ingroup mdns + * Announce IP settings have changed on netif. + * Call this in your callback registered by netif_set_status_callback(). + * This function may go away in the future when netif supports registering + * multiple callback functions. + * @param netif The network interface where settings have changed. + */ +void +mdns_resp_netif_settings_changed(struct netif *netif) +{ + LWIP_ERROR("mdns_resp_netif_ip_changed: netif != NULL", (netif != NULL), return); + + if (NETIF_TO_HOST(netif) == NULL) { + return; + } + + /* Announce on IPv6 and IPv4 */ +#if LWIP_IPV6 + mdns_announce(netif, IP6_ADDR_ANY); +#endif +#if LWIP_IPV4 + mdns_announce(netif, IP4_ADDR_ANY); +#endif +} + +/** + * @ingroup mdns + * Activate MDNS responder for a network interface and send announce packets. + * @param netif The network interface to activate. + * @param hostname Name to use. Queries for <hostname>.local will be answered + * with the IP addresses of the netif. The hostname will be copied, the + * given pointer can be on the stack. + * @param dns_ttl Validity time in seconds to send out for IP address data in DNS replies + * @return ERR_OK if netif was added, an err_t otherwise + */ +err_t +mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl) +{ + err_t res; + struct mdns_host* mdns; + + LWIP_ERROR("mdns_resp_add_netif: netif != NULL", (netif != NULL), return ERR_VAL); + LWIP_ERROR("mdns_resp_add_netif: Hostname too long", (strlen(hostname) <= MDNS_LABEL_MAXLEN), return ERR_VAL); + + LWIP_ASSERT("mdns_resp_add_netif: Double add", NETIF_TO_HOST(netif) == NULL); + mdns = (struct mdns_host *) mem_malloc(sizeof(struct mdns_host)); + LWIP_ERROR("mdns_resp_add_netif: Alloc failed", (mdns != NULL), return ERR_MEM); + + netif_set_client_data(netif, mdns_netif_client_id, mdns); + + memset(mdns, 0, sizeof(struct mdns_host)); + MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(hostname))); + mdns->dns_ttl = dns_ttl; + + /* Join multicast groups */ +#if LWIP_IPV4 + res = igmp_joingroup_netif(netif, ip_2_ip4(&v4group)); + if (res != ERR_OK) { + goto cleanup; + } +#endif +#if LWIP_IPV6 + res = mld6_joingroup_netif(netif, ip_2_ip6(&v6group)); + if (res != ERR_OK) { + goto cleanup; + } +#endif + + mdns_resp_netif_settings_changed(netif); + return ERR_OK; + +cleanup: + mem_free(mdns); + netif_set_client_data(netif, mdns_netif_client_id, NULL); + return res; +} + +/** + * @ingroup mdns + * Stop responding to MDNS queries on this interface, leave multicast groups, + * and free the helper structure and any of its services. + * @param netif The network interface to remove. + * @return ERR_OK if netif was removed, an err_t otherwise + */ +err_t +mdns_resp_remove_netif(struct netif *netif) +{ + int i; + struct mdns_host* mdns; + + LWIP_ASSERT("mdns_resp_remove_netif: Null pointer", netif); + mdns = NETIF_TO_HOST(netif); + LWIP_ERROR("mdns_resp_remove_netif: Not an active netif", (mdns != NULL), return ERR_VAL); + + for (i = 0; i < MDNS_MAX_SERVICES; i++) { + struct mdns_service *service = mdns->services[i]; + if (service) { + mem_free(service); + } + } + + /* Leave multicast groups */ +#if LWIP_IPV4 + igmp_leavegroup_netif(netif, ip_2_ip4(&v4group)); +#endif +#if LWIP_IPV6 + mld6_leavegroup_netif(netif, ip_2_ip6(&v6group)); +#endif + + mem_free(mdns); + netif_set_client_data(netif, mdns_netif_client_id, NULL); + return ERR_OK; +} + +/** + * @ingroup mdns + * Add a service to the selected network interface. + * @param netif The network interface to publish this service on + * @param name The name of the service + * @param service The service type, like "_http" + * @param proto The service protocol, DNSSD_PROTO_TCP for TCP ("_tcp") and DNSSD_PROTO_UDP + * for others ("_udp") + * @param port The port the service listens to + * @param dns_ttl Validity time in seconds to send out for service data in DNS replies + * @param txt_fn Callback to get TXT data. Will be called each time a TXT reply is created to + * allow dynamic replies. + * @param txt_data Userdata pointer for txt_fn + * @return ERR_OK if the service was added to the netif, an err_t otherwise + */ +err_t +mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_data) +{ + int i; + int slot = -1; + struct mdns_service *srv; + struct mdns_host* mdns; + + LWIP_ASSERT("mdns_resp_add_service: netif != NULL", netif); + mdns = NETIF_TO_HOST(netif); + LWIP_ERROR("mdns_resp_add_service: Not an mdns netif", (mdns != NULL), return ERR_VAL); + + LWIP_ERROR("mdns_resp_add_service: Name too long", (strlen(name) <= MDNS_LABEL_MAXLEN), return ERR_VAL); + LWIP_ERROR("mdns_resp_add_service: Service too long", (strlen(service) <= MDNS_LABEL_MAXLEN), return ERR_VAL); + LWIP_ERROR("mdns_resp_add_service: Bad proto (need TCP or UDP)", (proto == DNSSD_PROTO_TCP || proto == DNSSD_PROTO_UDP), return ERR_VAL); + + for (i = 0; i < MDNS_MAX_SERVICES; i++) { + if (mdns->services[i] == NULL) { + slot = i; + break; + } + } + LWIP_ERROR("mdns_resp_add_service: Service list full (increase MDNS_MAX_SERVICES)", (slot >= 0), return ERR_MEM); + + srv = (struct mdns_service*)mem_malloc(sizeof(struct mdns_service)); + LWIP_ERROR("mdns_resp_add_service: Alloc failed", (srv != NULL), return ERR_MEM); + + memset(srv, 0, sizeof(struct mdns_service)); + + MEMCPY(&srv->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(name))); + MEMCPY(&srv->service, service, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(service))); + srv->txt_fn = txt_fn; + srv->txt_userdata = txt_data; + srv->proto = (u16_t)proto; + srv->port = port; + srv->dns_ttl = dns_ttl; + + mdns->services[slot] = srv; + + /* Announce on IPv6 and IPv4 */ +#if LWIP_IPV6 + mdns_announce(netif, IP6_ADDR_ANY); +#endif +#if LWIP_IPV4 + mdns_announce(netif, IP4_ADDR_ANY); +#endif + + return ERR_OK; +} + +/** + * @ingroup mdns + * Call this function from inside the service_get_txt_fn_t callback to add text data. + * Buffer for TXT data is 256 bytes, and each field is prefixed with a length byte. + * @param service The service provided to the get_txt callback + * @param txt String to add to the TXT field. + * @param txt_len Length of string + * @return ERR_OK if the string was added to the reply, an err_t otherwise + */ +err_t +mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len) +{ + LWIP_ASSERT("mdns_resp_add_service_txtitem: service != NULL", service); + + /* Use a mdns_domain struct to store txt chunks since it is the same encoding */ + return mdns_domain_add_label(&service->txtdata, txt, txt_len); +} + +#endif /* LWIP_MDNS_RESPONDER */ diff --git a/components/net/lwip-2.0.3/src/apps/mqtt/mqtt.c b/components/net/lwip-2.0.3/src/apps/mqtt/mqtt.c new file mode 100644 index 0000000000..899e2cbff9 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/mqtt/mqtt.c @@ -0,0 +1,1342 @@ +/** + * @file + * MQTT client + * + * @defgroup mqtt MQTT client + * @ingroup apps + * @verbinclude mqtt_client.txt + */ + +/* + * Copyright (c) 2016 Erik Andersson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack + * + * Author: Erik Andersson + * + * + * @todo: + * - Handle large outgoing payloads for PUBLISH messages + * - Fix restriction of a single topic in each (UN)SUBSCRIBE message (protocol has support for multiple topics) + * - Add support for legacy MQTT protocol version + * + * Please coordinate changes and requests with Erik Andersson + * Erik Andersson + * + */ +#include "lwip/apps/mqtt.h" +#include "lwip/timeouts.h" +#include "lwip/ip_addr.h" +#include "lwip/mem.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/tcp.h" +#include + +#if LWIP_TCP && LWIP_CALLBACK_API + +/** + * MQTT_DEBUG: Default is off. + */ +#if !defined MQTT_DEBUG || defined __DOXYGEN__ +#define MQTT_DEBUG LWIP_DBG_OFF +#endif + +#define MQTT_DEBUG_TRACE (MQTT_DEBUG | LWIP_DBG_TRACE) +#define MQTT_DEBUG_STATE (MQTT_DEBUG | LWIP_DBG_STATE) +#define MQTT_DEBUG_WARN (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define MQTT_DEBUG_WARN_STATE (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) +#define MQTT_DEBUG_SERIOUS (MQTT_DEBUG | LWIP_DBG_LEVEL_SERIOUS) + +static void mqtt_cyclic_timer(void *arg); + +/** + * MQTT client connection states + */ +enum { + TCP_DISCONNECTED, + TCP_CONNECTING, + MQTT_CONNECTING, + MQTT_CONNECTED +}; + +/** + * MQTT control message types + */ +enum mqtt_message_type { + MQTT_MSG_TYPE_CONNECT = 1, + MQTT_MSG_TYPE_CONNACK = 2, + MQTT_MSG_TYPE_PUBLISH = 3, + MQTT_MSG_TYPE_PUBACK = 4, + MQTT_MSG_TYPE_PUBREC = 5, + MQTT_MSG_TYPE_PUBREL = 6, + MQTT_MSG_TYPE_PUBCOMP = 7, + MQTT_MSG_TYPE_SUBSCRIBE = 8, + MQTT_MSG_TYPE_SUBACK = 9, + MQTT_MSG_TYPE_UNSUBSCRIBE = 10, + MQTT_MSG_TYPE_UNSUBACK = 11, + MQTT_MSG_TYPE_PINGREQ = 12, + MQTT_MSG_TYPE_PINGRESP = 13, + MQTT_MSG_TYPE_DISCONNECT = 14 +}; + +/** Helpers to extract control packet type and qos from first byte in fixed header */ +#define MQTT_CTL_PACKET_TYPE(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0xf0) >> 4) +#define MQTT_CTL_PACKET_QOS(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0x6) >> 1) + +/** + * MQTT connect flags, only used in CONNECT message + */ +enum mqtt_connect_flag { + MQTT_CONNECT_FLAG_USERNAME = 1 << 7, + MQTT_CONNECT_FLAG_PASSWORD = 1 << 6, + MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5, + MQTT_CONNECT_FLAG_WILL = 1 << 2, + MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1 +}; + + +#if defined(LWIP_DEBUG) +static const char * const mqtt_message_type_str[15] = +{ + "UNDEFINED", + "CONNECT", + "CONNACK", + "PUBLISH", + "PUBACK", + "PUBREC", + "PUBREL", + "PUBCOMP", + "SUBSCRIBE", + "SUBACK", + "UNSUBSCRIBE", + "UNSUBACK", + "PINGREQ", + "PINGRESP", + "DISCONNECT" +}; + +/** + * Message type value to string + * @param msg_type see enum mqtt_message_type + * + * @return Control message type text string + */ +static const char * +mqtt_msg_type_to_str(u8_t msg_type) +{ + if (msg_type >= LWIP_ARRAYSIZE(mqtt_message_type_str)) { + msg_type = 0; + } + return mqtt_message_type_str[msg_type]; +} + +#endif + + +/** + * Generate MQTT packet identifier + * @param client MQTT client + * @return New packet identifier, range 1 to 65535 + */ +static u16_t +msg_generate_packet_id(mqtt_client_t *client) +{ + client->pkt_id_seq++; + if (client->pkt_id_seq == 0) { + client->pkt_id_seq++; + } + return client->pkt_id_seq; +} + +/*--------------------------------------------------------------------------------------------------------------------- */ +/* Output ring buffer */ + + +#define MQTT_RINGBUF_IDX_MASK ((MQTT_OUTPUT_RINGBUF_SIZE) - 1) + +/** Add single item to ring buffer */ +#define mqtt_ringbuf_put(rb, item) ((rb)->buf)[(rb)->put++ & MQTT_RINGBUF_IDX_MASK] = (item) + +/** Return number of bytes in ring buffer */ +#define mqtt_ringbuf_len(rb) ((u16_t)((rb)->put - (rb)->get)) + +/** Return number of bytes free in ring buffer */ +#define mqtt_ringbuf_free(rb) (MQTT_OUTPUT_RINGBUF_SIZE - mqtt_ringbuf_len(rb)) + +/** Return number of bytes possible to read without wrapping around */ +#define mqtt_ringbuf_linear_read_length(rb) LWIP_MIN(mqtt_ringbuf_len(rb), (MQTT_OUTPUT_RINGBUF_SIZE - ((rb)->get & MQTT_RINGBUF_IDX_MASK))) + +/** Return pointer to ring buffer get position */ +#define mqtt_ringbuf_get_ptr(rb) (&(rb)->buf[(rb)->get & MQTT_RINGBUF_IDX_MASK]) + +#define mqtt_ringbuf_advance_get_idx(rb, len) ((rb)->get += (len)) + + +/** + * Try send as many bytes as possible from output ring buffer + * @param rb Output ring buffer + * @param tpcb TCP connection handle + */ +static void +mqtt_output_send(struct mqtt_ringbuf_t *rb, struct tcp_pcb *tpcb) +{ + err_t err; + u8_t wrap = 0; + u16_t ringbuf_lin_len = mqtt_ringbuf_linear_read_length(rb); + u16_t send_len = tcp_sndbuf(tpcb); + LWIP_ASSERT("mqtt_output_send: tpcb != NULL", tpcb != NULL); + + if (send_len == 0 || ringbuf_lin_len == 0) { + return; + } + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_output_send: tcp_sndbuf: %d bytes, ringbuf_linear_available: %d, get %d, put %d\n", + send_len, ringbuf_lin_len, ((rb)->get & MQTT_RINGBUF_IDX_MASK), ((rb)->put & MQTT_RINGBUF_IDX_MASK))); + + if (send_len > ringbuf_lin_len) { + /* Space in TCP output buffer is larger than available in ring buffer linear portion */ + send_len = ringbuf_lin_len; + /* Wrap around if more data in ring buffer after linear portion */ + wrap = (mqtt_ringbuf_len(rb) > ringbuf_lin_len); + } + err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY | (wrap ? TCP_WRITE_FLAG_MORE : 0)); + if ((err == ERR_OK) && wrap) { + mqtt_ringbuf_advance_get_idx(rb, send_len); + /* Use the lesser one of ring buffer linear length and TCP send buffer size */ + send_len = LWIP_MIN(tcp_sndbuf(tpcb), mqtt_ringbuf_linear_read_length(rb)); + err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY); + } + + if (err == ERR_OK) { + mqtt_ringbuf_advance_get_idx(rb, send_len); + /* Flush */ + tcp_output(tpcb); + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_output_send: Send failed with err %d (\"%s\")\n", err, lwip_strerr(err))); + } +} + + + +/*--------------------------------------------------------------------------------------------------------------------- */ +/* Request queue */ + +/** + * Create request item + * @param r_objs Pointer to request objects + * @param pkt_id Packet identifier of request + * @param cb Packet callback to call when requests lifetime ends + * @param arg Parameter following callback + * @return Request or NULL if failed to create + */ +static struct mqtt_request_t * +mqtt_create_request(struct mqtt_request_t *r_objs, u16_t pkt_id, mqtt_request_cb_t cb, void *arg) +{ + struct mqtt_request_t *r = NULL; + u8_t n; + LWIP_ASSERT("mqtt_create_request: r_objs != NULL", r_objs != NULL); + for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT; n++) { + /* Item point to itself if not in use */ + if (r_objs[n].next == &r_objs[n]) { + r = &r_objs[n]; + r->next = NULL; + r->cb = cb; + r->arg = arg; + r->pkt_id = pkt_id; + break; + } + } + return r; +} + + +/** + * Append request to pending request queue + * @param tail Pointer to request queue tail pointer + * @param r Request to append + */ +static void +mqtt_append_request(struct mqtt_request_t **tail, struct mqtt_request_t *r) +{ + struct mqtt_request_t *head = NULL; + s16_t time_before = 0; + struct mqtt_request_t *iter; + + LWIP_ASSERT("mqtt_append_request: tail != NULL", tail != NULL); + + /* Iterate trough queue to find head, and count total timeout time */ + for (iter = *tail; iter != NULL; iter = iter->next) { + time_before += iter->timeout_diff; + head = iter; + } + + LWIP_ASSERT("mqtt_append_request: time_before <= MQTT_REQ_TIMEOUT", time_before <= MQTT_REQ_TIMEOUT); + r->timeout_diff = MQTT_REQ_TIMEOUT - time_before; + if (head == NULL) { + *tail = r; + } else { + head->next = r; + } +} + + +/** + * Delete request item + * @param r Request item to delete + */ +static void +mqtt_delete_request(struct mqtt_request_t *r) +{ + if (r != NULL) { + r->next = r; + } +} + +/** + * Remove a request item with a specific packet identifier from request queue + * @param tail Pointer to request queue tail pointer + * @param pkt_id Packet identifier of request to take + * @return Request item if found, NULL if not + */ +static struct mqtt_request_t * +mqtt_take_request(struct mqtt_request_t **tail, u16_t pkt_id) +{ + struct mqtt_request_t *iter = NULL, *prev = NULL; + LWIP_ASSERT("mqtt_take_request: tail != NULL", tail != NULL); + /* Search all request for pkt_id */ + for (iter = *tail; iter != NULL; iter = iter->next) { + if (iter->pkt_id == pkt_id) { + break; + } + prev = iter; + } + + /* If request was found */ + if (iter != NULL) { + /* unchain */ + if (prev == NULL) { + *tail= iter->next; + } else { + prev->next = iter->next; + } + /* If exists, add remaining timeout time for the request to next */ + if (iter->next != NULL) { + iter->next->timeout_diff += iter->timeout_diff; + } + iter->next = NULL; + } + return iter; +} + +/** + * Handle requests timeout + * @param tail Pointer to request queue tail pointer + * @param t Time since last call in seconds + */ +static void +mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t) +{ + struct mqtt_request_t *r; + LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL); + r = *tail; + while (t > 0 && r != NULL) { + if (t >= r->timeout_diff) { + t -= (u8_t)r->timeout_diff; + /* Unchain */ + *tail = r->next; + /* Notify upper layer about timeout */ + if (r->cb != NULL) { + r->cb(r->arg, ERR_TIMEOUT); + } + mqtt_delete_request(r); + /* Tail might be be modified in callback, so re-read it in every iteration */ + r = *(struct mqtt_request_t * const volatile *)tail; + } else { + r->timeout_diff -= t; + t = 0; + } + } +} + +/** + * Free all request items + * @param tail Pointer to request queue tail pointer + */ +static void +mqtt_clear_requests(struct mqtt_request_t **tail) +{ + struct mqtt_request_t *iter, *next; + LWIP_ASSERT("mqtt_clear_requests: tail != NULL", tail != NULL); + for (iter = *tail; iter != NULL; iter = next) { + next = iter->next; + mqtt_delete_request(iter); + } + *tail = NULL; +} +/** + * Initialize all request items + * @param r_objs Pointer to request objects + */ +static void +mqtt_init_requests(struct mqtt_request_t *r_objs) +{ + u8_t n; + LWIP_ASSERT("mqtt_init_requests: r_objs != NULL", r_objs != NULL); + for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT; n++) { + /* Item pointing to itself indicates unused */ + r_objs[n].next = &r_objs[n]; + } +} + +/*--------------------------------------------------------------------------------------------------------------------- */ +/* Output message build helpers */ + + +static void +mqtt_output_append_u8(struct mqtt_ringbuf_t *rb, u8_t value) +{ + mqtt_ringbuf_put(rb, value); +} + +static +void mqtt_output_append_u16(struct mqtt_ringbuf_t *rb, u16_t value) +{ + mqtt_ringbuf_put(rb, value >> 8); + mqtt_ringbuf_put(rb, value & 0xff); +} + +static void +mqtt_output_append_buf(struct mqtt_ringbuf_t *rb, const void *data, u16_t length) +{ + u16_t n; + for (n = 0; n < length; n++) { + mqtt_ringbuf_put(rb, ((const u8_t *)data)[n]); + } +} + +static void +mqtt_output_append_string(struct mqtt_ringbuf_t *rb, const char *str, u16_t length) +{ + u16_t n; + mqtt_ringbuf_put(rb, length >> 8); + mqtt_ringbuf_put(rb, length & 0xff); + for (n = 0; n < length; n++) { + mqtt_ringbuf_put(rb, str[n]); + } +} + +/** + * Append fixed header + * @param rb Output ring buffer + * @param msg_type see enum mqtt_message_type + * @param dup MQTT DUP flag + * @param qos MQTT QoS field + * @param retain MQTT retain flag + * @param r_length Remaining length after fixed header + */ + +static void +mqtt_output_append_fixed_header(struct mqtt_ringbuf_t *rb, u8_t msg_type, u8_t dup, + u8_t qos, u8_t retain, u16_t r_length) +{ + /* Start with control byte */ + mqtt_output_append_u8(rb, (((msg_type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1))); + /* Encode remaining length field */ + do { + mqtt_output_append_u8(rb, (r_length & 0x7f) | (r_length >= 128 ? 0x80 : 0)); + r_length >>= 7; + } while (r_length > 0); +} + + +/** + * Check output buffer space + * @param rb Output ring buffer + * @param r_length Remaining length after fixed header + * @return 1 if message will fit, 0 if not enough buffer space + */ +static u8_t +mqtt_output_check_space(struct mqtt_ringbuf_t *rb, u16_t r_length) +{ + /* Start with length of type byte + remaining length */ + u16_t total_len = 1 + r_length; + + LWIP_ASSERT("mqtt_output_check_space: rb != NULL", rb != NULL); + + /* Calculate number of required bytes to contain the remaining bytes field and add to total*/ + do { + total_len++; + r_length >>= 7; + } while (r_length > 0); + + return (total_len <= mqtt_ringbuf_free(rb)); +} + + +/** + * Close connection to server + * @param client MQTT client + * @param reason Reason for disconnection + */ +static void +mqtt_close(mqtt_client_t *client, mqtt_connection_status_t reason) +{ + LWIP_ASSERT("mqtt_close: client != NULL", client != NULL); + + /* Bring down TCP connection if not already done */ + if (client->conn != NULL) { + err_t res; + tcp_recv(client->conn, NULL); + tcp_err(client->conn, NULL); + tcp_sent(client->conn, NULL); + res = tcp_close(client->conn); + if (res != ERR_OK) { + tcp_abort(client->conn); + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_close: Close err=%s\n", lwip_strerr(res))); + } + client->conn = NULL; + } + + /* Remove all pending requests */ + mqtt_clear_requests(&client->pend_req_queue); + /* Stop cyclic timer */ + sys_untimeout(mqtt_cyclic_timer, client); + + /* Notify upper layer of disconnection if changed state */ + if (client->conn_state != TCP_DISCONNECTED) { + + client->conn_state = TCP_DISCONNECTED; + if (client->connect_cb != NULL) { + client->connect_cb(client, client->connect_arg, reason); + } + } +} + + +/** + * Interval timer, called every MQTT_CYCLIC_TIMER_INTERVAL seconds in MQTT_CONNECTING and MQTT_CONNECTED states + * @param arg MQTT client + */ +static void +mqtt_cyclic_timer(void *arg) +{ + u8_t restart_timer = 1; + mqtt_client_t *client = (mqtt_client_t *)arg; + LWIP_ASSERT("mqtt_cyclic_timer: client != NULL", client != NULL); + + if (client->conn_state == MQTT_CONNECTING) { + client->cyclic_tick++; + if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= MQTT_CONNECT_TIMOUT) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_cyclic_timer: CONNECT attempt to server timed out\n")); + /* Disconnect TCP */ + mqtt_close(client, MQTT_CONNECT_TIMEOUT); + restart_timer = 0; + } + } else if (client->conn_state == MQTT_CONNECTED) { + /* Handle timeout for pending requests */ + mqtt_request_time_elapsed(&client->pend_req_queue, MQTT_CYCLIC_TIMER_INTERVAL); + + /* keep_alive > 0 means keep alive functionality shall be used */ + if (client->keep_alive > 0) { + + client->server_watchdog++; + /* If reception from server has been idle for 1.5*keep_alive time, server is considered unresponsive */ + if ((client->server_watchdog * MQTT_CYCLIC_TIMER_INTERVAL) > (client->keep_alive + client->keep_alive/2)) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_cyclic_timer: Server incoming keep-alive timeout\n")); + mqtt_close(client, MQTT_CONNECT_TIMEOUT); + restart_timer = 0; + } + + /* If time for a keep alive message to be sent, transmission has been idle for keep_alive time */ + if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= client->keep_alive) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_cyclic_timer: Sending keep-alive message to server\n")); + if (mqtt_output_check_space(&client->output, 0) != 0) { + mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0, 0); + client->cyclic_tick = 0; + } + } else { + client->cyclic_tick++; + } + } + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_cyclic_timer: Timer should not be running in state %d\n", client->conn_state)); + restart_timer = 0; + } + if (restart_timer) { + sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, arg); + } +} + + +/** + * Send PUBACK, PUBREC or PUBREL response message + * @param client MQTT client + * @param msg PUBACK, PUBREC or PUBREL + * @param pkt_id Packet identifier + * @param qos QoS value + * @return ERR_OK if successful, ERR_MEM if out of memory + */ +static err_t +pub_ack_rec_rel_response(mqtt_client_t *client, u8_t msg, u16_t pkt_id, u8_t qos) +{ + err_t err = ERR_OK; + if (mqtt_output_check_space(&client->output, 2)) { + mqtt_output_append_fixed_header(&client->output, msg, 0, qos, 0, 2); + mqtt_output_append_u16(&client->output, pkt_id); + mqtt_output_send(&client->output, client->conn); + } else { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("pub_ack_rec_rel_response: OOM creating response: %s with pkt_id: %d\n", + mqtt_msg_type_to_str(msg), pkt_id)); + err = ERR_MEM; + } + return err; +} + +/** + * Subscribe response from server + * @param r Matching request + * @param result Result code from server + */ +static void +mqtt_incomming_suback(struct mqtt_request_t *r, u8_t result) +{ + if (r->cb != NULL) { + r->cb(r->arg, result < 3 ? ERR_OK : ERR_ABRT); + } +} + + +/** + * Complete MQTT message received or buffer full + * @param client MQTT client + * @param fixed_hdr_idx header index + * @param length length received part + * @param remaining_length Remaining length of complete message + */ +static mqtt_connection_status_t + mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u32_t remaining_length) +{ + mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED; + + u8_t *var_hdr_payload = client->rx_buffer + fixed_hdr_idx; + + /* Control packet type */ + u8_t pkt_type = MQTT_CTL_PACKET_TYPE(client->rx_buffer[0]); + u16_t pkt_id = 0; + + if (pkt_type == MQTT_MSG_TYPE_CONNACK) { + if (client->conn_state == MQTT_CONNECTING) { + /* Get result code from CONNACK */ + res = (mqtt_connection_status_t)var_hdr_payload[1]; + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: Connect response code %d\n", res)); + if (res == MQTT_CONNECT_ACCEPTED) { + /* Reset cyclic_tick when changing to connected state */ + client->cyclic_tick = 0; + client->conn_state = MQTT_CONNECTED; + /* Notify upper layer */ + if (client->connect_cb != 0) { + client->connect_cb(client, client->connect_arg, res); + } + } + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Received CONNACK in connected state\n")); + } + } else if (pkt_type == MQTT_MSG_TYPE_PINGRESP) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,( "mqtt_message_received: Received PINGRESP from server\n")); + + } else if (pkt_type == MQTT_MSG_TYPE_PUBLISH) { + u16_t payload_offset = 0; + u16_t payload_length = length; + u8_t qos = MQTT_CTL_PACKET_QOS(client->rx_buffer[0]); + + if (client->msg_idx <= MQTT_VAR_HEADER_BUFFER_LEN) { + /* Should have topic and pkt id*/ + uint8_t *topic; + uint16_t after_topic; + u8_t bkp; + u16_t topic_len = var_hdr_payload[0]; + topic_len = (topic_len << 8) + (u16_t)(var_hdr_payload[1]); + + topic = var_hdr_payload + 2; + after_topic = 2 + topic_len; + /* Check length, add one byte even for QoS 0 so that zero termination will fit */ + if ((after_topic + (qos? 2 : 1)) > length) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Receive buffer can not fit topic + pkt_id\n")); + goto out_disconnect; + } + + /* id for QoS 1 and 2 */ + if (qos > 0) { + client->inpub_pkt_id = ((u16_t)var_hdr_payload[after_topic] << 8) + (u16_t)var_hdr_payload[after_topic + 1]; + after_topic += 2; + } else { + client->inpub_pkt_id = 0; + } + /* Take backup of byte after topic */ + bkp = topic[topic_len]; + /* Zero terminate string */ + topic[topic_len] = 0; + /* Payload data remaining in receive buffer */ + payload_length = length - after_topic; + payload_offset = after_topic; + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_incomming_publish: Received message with QoS %d at topic: %s, payload length %d\n", + qos, topic, remaining_length + payload_length)); + if (client->pub_cb != NULL) { + client->pub_cb(client->inpub_arg, (const char *)topic, remaining_length + payload_length); + } + /* Restore byte after topic */ + topic[topic_len] = bkp; + } + if (payload_length > 0 || remaining_length == 0) { + client->data_cb(client->inpub_arg, var_hdr_payload + payload_offset, payload_length, remaining_length == 0 ? MQTT_DATA_FLAG_LAST : 0); + /* Reply if QoS > 0 */ + if (remaining_length == 0 && qos > 0) { + /* Send PUBACK for QoS 1 or PUBREC for QoS 2 */ + u8_t resp_msg = (qos == 1) ? MQTT_MSG_TYPE_PUBACK : MQTT_MSG_TYPE_PUBREC; + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_incomming_publish: Sending publish response: %s with pkt_id: %d\n", + mqtt_msg_type_to_str(resp_msg), client->inpub_pkt_id)); + pub_ack_rec_rel_response(client, resp_msg, client->inpub_pkt_id, 0); + } + } + } else { + /* Get packet identifier */ + pkt_id = (u16_t)var_hdr_payload[0] << 8; + pkt_id |= (u16_t)var_hdr_payload[1]; + if (pkt_id == 0) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Got message with illegal packet identifier: 0\n")); + goto out_disconnect; + } + if (pkt_type == MQTT_MSG_TYPE_PUBREC) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: PUBREC, sending PUBREL with pkt_id: %d\n",pkt_id)); + pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBREL, pkt_id, 1); + + } else if (pkt_type == MQTT_MSG_TYPE_PUBREL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: PUBREL, sending PUBCOMP response with pkt_id: %d\n",pkt_id)); + pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBCOMP, pkt_id, 0); + + } else if (pkt_type == MQTT_MSG_TYPE_SUBACK || pkt_type == MQTT_MSG_TYPE_UNSUBACK || + pkt_type == MQTT_MSG_TYPE_PUBCOMP || pkt_type == MQTT_MSG_TYPE_PUBACK) { + struct mqtt_request_t *r = mqtt_take_request(&client->pend_req_queue, pkt_id); + if (r != NULL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: %s response with id %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); + if (pkt_type == MQTT_MSG_TYPE_SUBACK) { + if (length < 3) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: To small SUBACK packet\n")); + goto out_disconnect; + } else { + mqtt_incomming_suback(r, var_hdr_payload[2]); + } + } else if (r->cb != NULL) { + r->cb(r->arg, ERR_OK); + } + mqtt_delete_request(r); + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received %s reply, with wrong pkt_id: %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); + } + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received unknown message type: %d\n", pkt_type)); + goto out_disconnect; + } + } + return res; +out_disconnect: + return MQTT_CONNECT_DISCONNECTED; +} + + +/** + * MQTT incoming message parser + * @param client MQTT client + * @param p PBUF chain of received data + * @return Connection status + */ +static mqtt_connection_status_t +mqtt_parse_incoming(mqtt_client_t *client, struct pbuf *p) +{ + u16_t in_offset = 0; + u32_t msg_rem_len = 0; + u8_t fixed_hdr_idx = 0; + u8_t b = 0; + + while (p->tot_len > in_offset) { + if ((fixed_hdr_idx < 2) || ((b & 0x80) != 0)) { + + if (fixed_hdr_idx < client->msg_idx) { + b = client->rx_buffer[fixed_hdr_idx]; + } else { + b = pbuf_get_at(p, in_offset++); + client->rx_buffer[client->msg_idx++] = b; + } + fixed_hdr_idx++; + + if (fixed_hdr_idx >= 2) { + msg_rem_len |= (u32_t)(b & 0x7f) << ((fixed_hdr_idx - 2) * 7); + if ((b & 0x80) == 0) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_parse_incoming: Remaining length after fixed header: %d\n", msg_rem_len)); + if (msg_rem_len == 0) { + /* Complete message with no extra headers of payload received */ + mqtt_message_received(client, fixed_hdr_idx, 0, 0); + client->msg_idx = 0; + fixed_hdr_idx = 0; + } else { + /* Bytes remaining in message */ + msg_rem_len = (msg_rem_len + fixed_hdr_idx) - client->msg_idx; + } + } + } + } else { + u16_t cpy_len, cpy_start, buffer_space; + + cpy_start = (client->msg_idx - fixed_hdr_idx) % (MQTT_VAR_HEADER_BUFFER_LEN - fixed_hdr_idx) + fixed_hdr_idx; + + /* Allow to copy the lesser one of available length in input data or bytes remaining in message */ + cpy_len = (u16_t)LWIP_MIN((u16_t)(p->tot_len - in_offset), msg_rem_len); + + /* Limit to available space in buffer */ + buffer_space = MQTT_VAR_HEADER_BUFFER_LEN - cpy_start; + if (cpy_len > buffer_space) { + cpy_len = buffer_space; + } + pbuf_copy_partial(p, client->rx_buffer+cpy_start, cpy_len, in_offset); + + /* Advance get and put indexes */ + client->msg_idx += cpy_len; + in_offset += cpy_len; + msg_rem_len -= cpy_len; + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_parse_incoming: msg_idx: %d, cpy_len: %d, remaining %d\n", client->msg_idx, cpy_len, msg_rem_len)); + if (msg_rem_len == 0 || cpy_len == buffer_space) { + /* Whole message received or buffer is full */ + mqtt_connection_status_t res = mqtt_message_received(client, fixed_hdr_idx, (cpy_start + cpy_len) - fixed_hdr_idx, msg_rem_len); + if (res != MQTT_CONNECT_ACCEPTED) { + return res; + } + if (msg_rem_len == 0) { + /* Reset parser state */ + client->msg_idx = 0; + /* msg_tot_len = 0; */ + fixed_hdr_idx = 0; + } + } + } + } + return MQTT_CONNECT_ACCEPTED; +} + + +/** + * TCP received callback function. @see tcp_recv_fn + * @param arg MQTT client + * @param p PBUF chain of received data + * @param err Passed as return value if not ERR_OK + * @return ERR_OK or err passed into callback + */ +static err_t +mqtt_tcp_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + LWIP_ASSERT("mqtt_tcp_recv_cb: client != NULL", client != NULL); + LWIP_ASSERT("mqtt_tcp_recv_cb: client->conn == pcb", client->conn == pcb); + + if (p == NULL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_recv_cb: Recv pbuf=NULL, remote has closed connection\n")); + mqtt_close(client, MQTT_CONNECT_DISCONNECTED); + } else { + mqtt_connection_status_t res; + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_tcp_recv_cb: Recv err=%d\n", err)); + pbuf_free(p); + return err; + } + + /* Tell remote that data has been received */ + tcp_recved(pcb, p->tot_len); + res = mqtt_parse_incoming(client, p); + pbuf_free(p); + + if (res != MQTT_CONNECT_ACCEPTED) { + mqtt_close(client, res); + } + /* If keep alive functionality is used */ + if (client->keep_alive != 0) { + /* Reset server alive watchdog */ + client->server_watchdog = 0; + } + + } + return ERR_OK; +} + + +/** + * TCP data sent callback function. @see tcp_sent_fn + * @param arg MQTT client + * @param tpcb TCP connection handle + * @param len Number of bytes sent + * @return ERR_OK + */ +static err_t +mqtt_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + + LWIP_UNUSED_ARG(tpcb); + LWIP_UNUSED_ARG(len); + + if (client->conn_state == MQTT_CONNECTED) { + struct mqtt_request_t *r; + + /* Reset keep-alive send timer and server watchdog */ + client->cyclic_tick = 0; + client->server_watchdog = 0; + /* QoS 0 publish has no response from server, so call its callbacks here */ + while ((r = mqtt_take_request(&client->pend_req_queue, 0)) != NULL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_sent_cb: Calling QoS 0 publish complete callback\n")); + if (r->cb != NULL) { + r->cb(r->arg, ERR_OK); + } + mqtt_delete_request(r); + } + /* Try send any remaining buffers from output queue */ + mqtt_output_send(&client->output, client->conn); + } + return ERR_OK; +} + +/** + * TCP error callback function. @see tcp_err_fn + * @param arg MQTT client + * @param err Error encountered + */ +static void +mqtt_tcp_err_cb(void *arg, err_t err) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + LWIP_UNUSED_ARG(err); /* only used for debug output */ + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_err_cb: TCP error callback: error %d, arg: %p\n", err, arg)); + LWIP_ASSERT("mqtt_tcp_err_cb: client != NULL", client != NULL); + /* Set conn to null before calling close as pcb is already deallocated*/ + client->conn = 0; + mqtt_close(client, MQTT_CONNECT_DISCONNECTED); +} + +/** + * TCP poll callback function. @see tcp_poll_fn + * @param arg MQTT client + * @param tpcb TCP connection handle + * @return err ERR_OK + */ +static err_t +mqtt_tcp_poll_cb(void *arg, struct tcp_pcb *tpcb) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + if (client->conn_state == MQTT_CONNECTED) { + /* Try send any remaining buffers from output queue */ + mqtt_output_send(&client->output, tpcb); + } + return ERR_OK; +} + +/** + * TCP connect callback function. @see tcp_connected_fn + * @param arg MQTT client + * @param err Always ERR_OK, mqtt_tcp_err_cb is called in case of error + * @return ERR_OK + */ +static err_t +mqtt_tcp_connect_cb(void *arg, struct tcp_pcb *tpcb, err_t err) +{ + mqtt_client_t* client = (mqtt_client_t *)arg; + + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_tcp_connect_cb: TCP connect error %d\n", err)); + return err; + } + + /* Initiate receiver state */ + client->msg_idx = 0; + + /* Setup TCP callbacks */ + tcp_recv(tpcb, mqtt_tcp_recv_cb); + tcp_sent(tpcb, mqtt_tcp_sent_cb); + tcp_poll(tpcb, mqtt_tcp_poll_cb, 2); + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_connect_cb: TCP connection established to server\n")); + /* Enter MQTT connect state */ + client->conn_state = MQTT_CONNECTING; + + /* Start cyclic timer */ + sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, client); + client->cyclic_tick = 0; + + /* Start transmission from output queue, connect message is the first one out*/ + mqtt_output_send(&client->output, client->conn); + + return ERR_OK; +} + + + +/*---------------------------------------------------------------------------------------------------- */ +/* Public API */ + + +/** + * @ingroup mqtt + * MQTT publish function. + * @param client MQTT client + * @param topic Publish topic string + * @param payload Data to publish (NULL is allowed) + * @param payload_length: Length of payload (0 is allowed) + * @param qos Quality of service, 0 1 or 2 + * @param retain MQTT retain flag + * @param cb Callback to call when publish is complete or has timed out + * @param arg User supplied argument to publish callback + * @return ERR_OK if successful + * ERR_CONN if client is disconnected + * ERR_MEM if short on memory + */ +err_t +mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, + mqtt_request_cb_t cb, void *arg) +{ + struct mqtt_request_t *r; + u16_t pkt_id; + size_t topic_strlen; + size_t total_len; + u16_t topic_len; + u16_t remaining_length; + + LWIP_ASSERT("mqtt_publish: client != NULL", client); + LWIP_ASSERT("mqtt_publish: topic != NULL", topic); + LWIP_ERROR("mqtt_publish: TCP disconnected", (client->conn_state != TCP_DISCONNECTED), return ERR_CONN); + + topic_strlen = strlen(topic); + LWIP_ERROR("mqtt_publish: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); + topic_len = (u16_t)topic_strlen; + total_len = 2 + topic_len + payload_length; + LWIP_ERROR("mqtt_publish: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); + remaining_length = (u16_t)total_len; + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_publish: Publish with payload length %d to topic \"%s\"\n", payload_length, topic)); + + if (qos > 0) { + remaining_length += 2; + /* Generate pkt_id id for QoS1 and 2 */ + pkt_id = msg_generate_packet_id(client); + } else { + /* Use reserved value pkt_id 0 for QoS 0 in request handle */ + pkt_id = 0; + } + + r = mqtt_create_request(client->req_list, pkt_id, cb, arg); + if (r == NULL) { + return ERR_MEM; + } + + if (mqtt_output_check_space(&client->output, remaining_length) == 0) { + mqtt_delete_request(r); + return ERR_MEM; + } + /* Append fixed header */ + mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain, remaining_length); + + /* Append Topic */ + mqtt_output_append_string(&client->output, topic, topic_len); + + /* Append packet if for QoS 1 and 2*/ + if (qos > 0) { + mqtt_output_append_u16(&client->output, pkt_id); + } + + /* Append optional publish payload */ + if ((payload != NULL) && (payload_length > 0)) { + mqtt_output_append_buf(&client->output, payload, payload_length); + } + + mqtt_append_request(&client->pend_req_queue, r); + mqtt_output_send(&client->output, client->conn); + return ERR_OK; +} + + +/** + * @ingroup mqtt + * MQTT subscribe/unsubscribe function. + * @param client MQTT client + * @param topic topic to subscribe to + * @param qos Quality of service, 0 1 or 2 (only used for subscribe) + * @param cb Callback to call when subscribe/unsubscribe reponse is received + * @param arg User supplied argument to publish callback + * @param sub 1 for subscribe, 0 for unsubscribe + * @return ERR_OK if successful, @see err_t enum for other results + */ +err_t +mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub) +{ + size_t topic_strlen; + size_t total_len; + u16_t topic_len; + u16_t remaining_length; + u16_t pkt_id; + struct mqtt_request_t *r; + + LWIP_ASSERT("mqtt_sub_unsub: client != NULL", client); + LWIP_ASSERT("mqtt_sub_unsub: topic != NULL", topic); + + topic_strlen = strlen(topic); + LWIP_ERROR("mqtt_sub_unsub: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); + topic_len = (u16_t)topic_strlen; + /* Topic string, pkt_id, qos for subscribe */ + total_len = topic_len + 2 + 2 + (sub != 0); + LWIP_ERROR("mqtt_sub_unsub: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); + remaining_length = (u16_t)total_len; + + LWIP_ASSERT("mqtt_sub_unsub: qos < 3", qos < 3); + if (client->conn_state == TCP_DISCONNECTED) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_sub_unsub: Can not (un)subscribe in disconnected state\n")); + return ERR_CONN; + } + + pkt_id = msg_generate_packet_id(client); + r = mqtt_create_request(client->req_list, pkt_id, cb, arg); + if (r == NULL) { + return ERR_MEM; + } + + if (mqtt_output_check_space(&client->output, remaining_length) == 0) { + mqtt_delete_request(r); + return ERR_MEM; + } + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_sub_unsub: Client (un)subscribe to topic \"%s\", id: %d\n", topic, pkt_id)); + + mqtt_output_append_fixed_header(&client->output, sub ? MQTT_MSG_TYPE_SUBSCRIBE : MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0, remaining_length); + /* Packet id */ + mqtt_output_append_u16(&client->output, pkt_id); + /* Topic */ + mqtt_output_append_string(&client->output, topic, topic_len); + /* QoS */ + if (sub != 0) { + mqtt_output_append_u8(&client->output, LWIP_MIN(qos, 2)); + } + + mqtt_append_request(&client->pend_req_queue, r); + mqtt_output_send(&client->output, client->conn); + return ERR_OK; +} + + +/** + * @ingroup mqtt + * Set callback to handle incoming publish requests from server + * @param client MQTT client + * @param pub_cb Callback invoked when publish starts, contain topic and total length of payload + * @param data_cb Callback for each fragment of payload that arrives + * @param arg User supplied argument to both callbacks + */ +void +mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t pub_cb, + mqtt_incoming_data_cb_t data_cb, void *arg) +{ + LWIP_ASSERT("mqtt_set_inpub_callback: client != NULL", client != NULL); + client->data_cb = data_cb; + client->pub_cb = pub_cb; + client->inpub_arg = arg; +} + +/** + * @ingroup mqtt + * Create a new MQTT client instance + * @return Pointer to instance on success, NULL otherwise + */ +mqtt_client_t * +mqtt_client_new(void) +{ + mqtt_client_t *client = (mqtt_client_t *)mem_malloc(sizeof(mqtt_client_t)); + if (client != NULL) { + memset(client, 0, sizeof(mqtt_client_t)); + } + return client; +} + + +/** + * @ingroup mqtt + * Connect to MQTT server + * @param client MQTT client + * @param ip_addr Server IP + * @param port Server port + * @param cb Connection state change callback + * @param arg User supplied argument to connection callback + * @param client_info Client identification and connection options + * @return ERR_OK if successful, @see err_t enum for other results + */ +err_t +mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port, mqtt_connection_cb_t cb, void *arg, + const struct mqtt_connect_client_info_t *client_info) +{ + err_t err; + size_t len; + u16_t client_id_length; + /* Length is the sum of 2+"MQTT", protocol level, flags and keep alive */ + u16_t remaining_length = 2 + 4 + 1 + 1 + 2; + u8_t flags = 0, will_topic_len = 0, will_msg_len = 0; + + LWIP_ASSERT("mqtt_client_connect: client != NULL", client != NULL); + LWIP_ASSERT("mqtt_client_connect: ip_addr != NULL", ip_addr != NULL); + LWIP_ASSERT("mqtt_client_connect: client_info != NULL", client_info != NULL); + LWIP_ASSERT("mqtt_client_connect: client_info->client_id != NULL", client_info->client_id != NULL); + + if (client->conn_state != TCP_DISCONNECTED) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Already connected\n")); + return ERR_ISCONN; + } + + /* Wipe clean */ + memset(client, 0, sizeof(mqtt_client_t)); + client->connect_arg = arg; + client->connect_cb = cb; + client->keep_alive = client_info->keep_alive; + mqtt_init_requests(client->req_list); + + /* Build connect message */ + if (client_info->will_topic != NULL && client_info->will_msg != NULL) { + flags |= MQTT_CONNECT_FLAG_WILL; + flags |= (client_info->will_qos & 3) << 3; + if (client_info->will_retain) { + flags |= MQTT_CONNECT_FLAG_WILL_RETAIN; + } + len = strlen(client_info->will_topic); + LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL); + LWIP_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return ERR_VAL); + will_topic_len = (u8_t)len; + len = strlen(client_info->will_msg); + LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL); + will_msg_len = (u8_t)len; + len = remaining_length + 2 + will_topic_len + 2 + will_msg_len; + LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); + remaining_length = (u16_t)len; + } + + /* Don't complicate things, always connect using clean session */ + flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; + + len = strlen(client_info->client_id); + LWIP_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return ERR_VAL); + client_id_length = (u16_t)len; + len = remaining_length + 2 + client_id_length; + LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); + remaining_length = (u16_t)len; + + if (mqtt_output_check_space(&client->output, remaining_length) == 0) { + return ERR_MEM; + } + + client->conn = tcp_new(); + if (client->conn == NULL) { + return ERR_MEM; + } + + /* Set arg pointer for callbacks */ + tcp_arg(client->conn, client); + /* Any local address, pick random local port number */ + err = tcp_bind(client->conn, IP_ADDR_ANY, 0); + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Error binding to local ip/port, %d\n", err)); + goto tcp_fail; + } + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Connecting to host: %s at port:%"U16_F"\n", ipaddr_ntoa(ip_addr), port)); + + /* Connect to server */ + err = tcp_connect(client->conn, ip_addr, port, mqtt_tcp_connect_cb); + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Error connecting to remote ip/port, %d\n", err)); + goto tcp_fail; + } + /* Set error callback */ + tcp_err(client->conn, mqtt_tcp_err_cb); + client->conn_state = TCP_CONNECTING; + + /* Append fixed header */ + mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_CONNECT, 0, 0, 0, remaining_length); + /* Append Protocol string */ + mqtt_output_append_string(&client->output, "MQTT", 4); + /* Append Protocol level */ + mqtt_output_append_u8(&client->output, 4); + /* Append connect flags */ + mqtt_output_append_u8(&client->output, flags); + /* Append keep-alive */ + mqtt_output_append_u16(&client->output, client_info->keep_alive); + /* Append client id */ + mqtt_output_append_string(&client->output, client_info->client_id, client_id_length); + /* Append will message if used */ + if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) { + mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len); + mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len); + } + return ERR_OK; + +tcp_fail: + tcp_abort(client->conn); + client->conn = NULL; + return err; +} + + +/** + * @ingroup mqtt + * Disconnect from MQTT server + * @param client MQTT client + */ +void +mqtt_disconnect(mqtt_client_t *client) +{ + LWIP_ASSERT("mqtt_disconnect: client != NULL", client); + /* If connection in not already closed */ + if (client->conn_state != TCP_DISCONNECTED) { + /* Set conn_state before calling mqtt_close to prevent callback from being called */ + client->conn_state = TCP_DISCONNECTED; + mqtt_close(client, (mqtt_connection_status_t)0); + } +} + +/** + * @ingroup mqtt + * Check connection with server + * @param client MQTT client + * @return 1 if connected to server, 0 otherwise + */ +u8_t +mqtt_client_is_connected(mqtt_client_t *client) +{ + LWIP_ASSERT("mqtt_client_is_connected: client != NULL", client); + return client->conn_state == MQTT_CONNECTED; +} + +#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/components/net/lwip-2.0.3/src/apps/netbiosns/netbiosns.c b/components/net/lwip-2.0.3/src/apps/netbiosns/netbiosns.c new file mode 100644 index 0000000000..2dfbe65901 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/netbiosns/netbiosns.c @@ -0,0 +1,367 @@ +/** + * @file + * NetBIOS name service responder + */ + +/** + * @defgroup netbiosns NETBIOS responder + * @ingroup apps + * + * This is an example implementation of a NetBIOS name server. + * It responds to name queries for a configurable name. + * Name resolving is not supported. + * + * Note that the device doesn't broadcast it's own name so can't + * detect duplicate names! + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/apps/netbiosns.h" + +#if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/udp.h" +#include "lwip/netif.h" + +#include + +/** default port number for "NetBIOS Name service */ +#define NETBIOS_PORT 137 + +/** size of a NetBIOS name */ +#define NETBIOS_NAME_LEN 16 + +/** The Time-To-Live for NetBIOS name responds (in seconds) + * Default is 300000 seconds (3 days, 11 hours, 20 minutes) */ +#define NETBIOS_NAME_TTL 300000u + +/** NetBIOS header flags */ +#define NETB_HFLAG_RESPONSE 0x8000U +#define NETB_HFLAG_OPCODE 0x7800U +#define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U +#define NETB_HFLAG_AUTHORATIVE 0x0400U +#define NETB_HFLAG_TRUNCATED 0x0200U +#define NETB_HFLAG_RECURS_DESIRED 0x0100U +#define NETB_HFLAG_RECURS_AVAILABLE 0x0080U +#define NETB_HFLAG_BROADCAST 0x0010U +#define NETB_HFLAG_REPLYCODE 0x0008U +#define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U + +/** NetBIOS name flags */ +#define NETB_NFLAG_UNIQUE 0x8000U +#define NETB_NFLAG_NODETYPE 0x6000U +#define NETB_NFLAG_NODETYPE_HNODE 0x6000U +#define NETB_NFLAG_NODETYPE_MNODE 0x4000U +#define NETB_NFLAG_NODETYPE_PNODE 0x2000U +#define NETB_NFLAG_NODETYPE_BNODE 0x0000U + +/** NetBIOS message header */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct netbios_hdr { + PACK_STRUCT_FIELD(u16_t trans_id); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FIELD(u16_t questions); + PACK_STRUCT_FIELD(u16_t answerRRs); + PACK_STRUCT_FIELD(u16_t authorityRRs); + PACK_STRUCT_FIELD(u16_t additionalRRs); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** NetBIOS message name part */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct netbios_name_hdr { + PACK_STRUCT_FLD_8(u8_t nametype); + PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN*2)+1]); + PACK_STRUCT_FIELD(u16_t type); + PACK_STRUCT_FIELD(u16_t cls); + PACK_STRUCT_FIELD(u32_t ttl); + PACK_STRUCT_FIELD(u16_t datalen); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FLD_S(ip4_addr_p_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** NetBIOS message */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct netbios_resp +{ + struct netbios_hdr resp_hdr; + struct netbios_name_hdr resp_name; +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef NETBIOS_LWIP_NAME +#define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME +#else +static char netbiosns_local_name[NETBIOS_NAME_LEN]; +#define NETBIOS_LOCAL_NAME netbiosns_local_name +#endif + +struct udp_pcb *netbiosns_pcb; + +/** Decode a NetBIOS name (from packet to string) */ +static int +netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len) +{ + char *pname; + char cname; + char cnbname; + int idx = 0; + + LWIP_UNUSED_ARG(name_dec_len); + + /* Start decoding netbios name. */ + pname = name_enc; + for (;;) { + /* Every two characters of the first level-encoded name + * turn into one character in the decoded name. */ + cname = *pname; + if (cname == '\0') + break; /* no more characters */ + if (cname == '.') + break; /* scope ID follows */ + if (cname < 'A' || cname > 'Z') { + /* Not legal. */ + return -1; + } + cname -= 'A'; + cnbname = cname << 4; + pname++; + + cname = *pname; + if (cname == '\0' || cname == '.') { + /* No more characters in the name - but we're in + * the middle of a pair. Not legal. */ + return -1; + } + if (cname < 'A' || cname > 'Z') { + /* Not legal. */ + return -1; + } + cname -= 'A'; + cnbname |= cname; + pname++; + + /* Do we have room to store the character? */ + if (idx < NETBIOS_NAME_LEN) { + /* Yes - store the character. */ + name_dec[idx++] = (cnbname!=' '?cnbname:'\0'); + } + } + + return 0; +} + +#if 0 /* function currently unused */ +/** Encode a NetBIOS name (from string to packet) - currently unused because + we don't ask for names. */ +static int +netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len) +{ + char *pname; + char cname; + unsigned char ucname; + int idx = 0; + + /* Start encoding netbios name. */ + pname = name_enc; + + for (;;) { + /* Every two characters of the first level-encoded name + * turn into one character in the decoded name. */ + cname = *pname; + if (cname == '\0') + break; /* no more characters */ + if (cname == '.') + break; /* scope ID follows */ + if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) { + /* Not legal. */ + return -1; + } + + /* Do we have room to store the character? */ + if (idx >= name_dec_len) { + return -1; + } + + /* Yes - store the character. */ + ucname = cname; + name_dec[idx++] = ('A'+((ucname>>4) & 0x0F)); + name_dec[idx++] = ('A'+( ucname & 0x0F)); + pname++; + } + + /* Fill with "space" coding */ + for (;idx < name_dec_len - 1;) { + name_dec[idx++] = 'C'; + name_dec[idx++] = 'A'; + } + + /* Terminate string */ + name_dec[idx] = '\0'; + + return 0; +} +#endif /* 0 */ + +/** NetBIOS Name service recv callback */ +static void +netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + LWIP_UNUSED_ARG(arg); + + /* if packet is valid */ + if (p != NULL) { + char netbios_name[NETBIOS_NAME_LEN+1]; + struct netbios_hdr* netbios_hdr = (struct netbios_hdr*)p->payload; + struct netbios_name_hdr* netbios_name_hdr = (struct netbios_name_hdr*)(netbios_hdr+1); + + /* we only answer if we got a default interface */ + if (netif_default != NULL) { + /* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */ + /* if the packet is a NetBIOS name query question */ + if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) && + ((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) && + (netbios_hdr->questions == PP_NTOHS(1))) { + /* decode the NetBIOS name */ + netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name)); + /* if the packet is for us */ + if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) { + struct pbuf *q; + struct netbios_resp *resp; + + q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM); + if (q != NULL) { + resp = (struct netbios_resp*)q->payload; + + /* prepare NetBIOS header response */ + resp->resp_hdr.trans_id = netbios_hdr->trans_id; + resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE | + NETB_HFLAG_OPCODE_NAME_QUERY | + NETB_HFLAG_AUTHORATIVE | + NETB_HFLAG_RECURS_DESIRED); + resp->resp_hdr.questions = 0; + resp->resp_hdr.answerRRs = PP_HTONS(1); + resp->resp_hdr.authorityRRs = 0; + resp->resp_hdr.additionalRRs = 0; + + /* prepare NetBIOS header datas */ + MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname)); + resp->resp_name.nametype = netbios_name_hdr->nametype; + resp->resp_name.type = netbios_name_hdr->type; + resp->resp_name.cls = netbios_name_hdr->cls; + resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL); + resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags)+sizeof(resp->resp_name.addr)); + resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE); + ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default)); + + /* send the NetBIOS response */ + udp_sendto(upcb, q, addr, port); + + /* free the "reference" pbuf */ + pbuf_free(q); + } + } + } + } + /* free the pbuf */ + pbuf_free(p); + } +} + +/** + * @ingroup netbiosns + * Init netbios responder + */ +void +netbiosns_init(void) +{ +#ifdef NETBIOS_LWIP_NAME + LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN); +#endif + + netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + if (netbiosns_pcb != NULL) { + /* we have to be allowed to send broadcast packets! */ + ip_set_option(netbiosns_pcb, SOF_BROADCAST); + udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT); + udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb); + } +} + +#ifndef NETBIOS_LWIP_NAME +/** + * @ingroup netbiosns + * Set netbios name. ATTENTION: the hostname must be less than 15 characters! + */ +void +netbiosns_set_name(const char* hostname) +{ + size_t copy_len = strlen(hostname); + LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN); + if (copy_len >= NETBIOS_NAME_LEN) { + copy_len = NETBIOS_NAME_LEN - 1; + } + MEMCPY(netbiosns_local_name, hostname, copy_len + 1); +} +#endif + +/** + * @ingroup netbiosns + * Stop netbios responder + */ +void +netbiosns_stop(void) +{ + if (netbiosns_pcb != NULL) { + udp_remove(netbiosns_pcb); + netbiosns_pcb = NULL; + } +} + +#endif /* LWIP_IPV4 && LWIP_UDP */ diff --git a/components/net/lwip-2.0.3/src/apps/ping/ping.c b/components/net/lwip-2.0.3/src/apps/ping/ping.c new file mode 100644 index 0000000000..6d3cfe0fc3 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/ping/ping.c @@ -0,0 +1,245 @@ +/* + * netutils: ping implementation + */ + +#include + +#ifdef RT_LWIP_ICMP /* don't build if not configured for use in rtconfig.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * PING_DEBUG: Enable debugging for PING. + */ +#ifndef PING_DEBUG +#define PING_DEBUG LWIP_DBG_ON +#endif + +/** ping receive timeout - in milliseconds */ +#define PING_RCV_TIMEO (2 * RT_TICK_PER_SECOND) +/** ping delay - in milliseconds */ +#define PING_DELAY (1 * RT_TICK_PER_SECOND) + +/** ping identifier - must fit on a u16_t */ +#ifndef PING_ID +#define PING_ID 0xAFAF +#endif + +/** ping additional data size to include in the packet */ +#ifndef PING_DATA_SIZE +#define PING_DATA_SIZE 32 +#endif + +/* ping variables */ +static u16_t ping_seq_num; +struct _ip_addr +{ + rt_uint8_t addr0, addr1, addr2, addr3; +}; + +/** Prepare a echo ICMP request */ +static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) +{ + size_t i; + size_t data_len = len - sizeof(struct icmp_echo_hdr); + + ICMPH_TYPE_SET(iecho, ICMP_ECHO); + ICMPH_CODE_SET(iecho, 0); + iecho->chksum = 0; + iecho->id = PING_ID; + iecho->seqno = htons(++ping_seq_num); + + /* fill the additional data buffer with some data */ + for (i = 0; i < data_len; i++) + { + ((char*) iecho)[sizeof(struct icmp_echo_hdr) + i] = (char) i; + } + +#ifdef RT_LWIP_USING_HW_CHECKSUM + iecho->chksum = 0; +#else + iecho->chksum = inet_chksum(iecho, len); +#endif + +} + +/* Ping using the socket ip */ +err_t lwip_ping_send(int s, ip_addr_t *addr, int size) +{ + int err; + struct icmp_echo_hdr *iecho; + struct sockaddr_in to; + int ping_size = sizeof(struct icmp_echo_hdr) + size; + LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff); + + iecho = rt_malloc(ping_size); + if (iecho == RT_NULL) + { + return ERR_MEM; + } + + ping_prepare_echo(iecho, (u16_t) ping_size); + + to.sin_len = sizeof(to); + to.sin_family = AF_INET; +#if LWIP_IPV4 && LWIP_IPV6 + to.sin_addr.s_addr = addr->u_addr.ip4.addr; +#elif LWIP_IPV4 + to.sin_addr.s_addr = addr->addr; +#elif LWIP_IPV6 +#error Not supported IPv6. +#endif + + err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*) &to, sizeof(to)); + rt_free(iecho); + + return (err == ping_size ? ERR_OK : ERR_VAL); +} + +int lwip_ping_recv(int s, int *ttl) +{ + char buf[64]; + int fromlen = sizeof(struct sockaddr_in), len; + struct sockaddr_in from; + struct ip_hdr *iphdr; + struct icmp_echo_hdr *iecho; + + while ((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*) &from, (socklen_t*) &fromlen)) > 0) + { + if (len >= (int)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr))) + { + iphdr = (struct ip_hdr *) buf; + iecho = (struct icmp_echo_hdr *) (buf + (IPH_HL(iphdr) * 4)); + if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) + { + *ttl = iphdr->_ttl; + return len; + } + } + } + + return len; +} + +#ifndef RT_USING_NETDEV + +/* using the lwIP custom ping */ +rt_err_t ping(char* target_name, rt_uint32_t times, rt_size_t size) +{ +#if LWIP_VERSION_MAJOR >= 2U + struct timeval timeout = { PING_RCV_TIMEO / RT_TICK_PER_SECOND, PING_RCV_TIMEO % RT_TICK_PER_SECOND }; +#else + int timeout = PING_RCV_TIMEO * 1000UL / RT_TICK_PER_SECOND; +#endif + + int s, ttl, recv_len; + ip_addr_t target_addr; + rt_uint32_t send_times; + rt_tick_t recv_start_tick; + struct addrinfo hint, *res = NULL; + struct sockaddr_in *h = NULL; + struct in_addr ina; + + send_times = 0; + ping_seq_num = 0; + + if (size == 0) + { + size = PING_DATA_SIZE; + } + + memset(&hint, 0, sizeof(hint)); + /* convert URL to IP */ + if (lwip_getaddrinfo(target_name, NULL, &hint, &res) != 0) + { + rt_kprintf("ping: unknown host %s\n", target_name); + return -RT_ERROR; + } + memcpy(&h, &res->ai_addr, sizeof(struct sockaddr_in *)); + memcpy(&ina, &h->sin_addr, sizeof(ina)); + lwip_freeaddrinfo(res); + if (inet_aton(inet_ntoa(ina), &target_addr) == 0) + { + rt_kprintf("ping: unknown host %s\n", target_name); + return -RT_ERROR; + } + /* new a socket */ + if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) + { + rt_kprintf("ping: create socket failed\n"); + return -RT_ERROR; + } + + lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + + while (1) + { + int elapsed_time; + + if (lwip_ping_send(s, &target_addr, size) == ERR_OK) + { + recv_start_tick = rt_tick_get(); + if ((recv_len = lwip_ping_recv(s, &ttl)) >= 0) + { + elapsed_time = (rt_tick_get() - recv_start_tick) * 1000UL / RT_TICK_PER_SECOND; + rt_kprintf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n", recv_len, inet_ntoa(ina), send_times, + ttl, elapsed_time); + } + else + { + rt_kprintf("From %s icmp_seq=%d timeout\n", inet_ntoa(ina), send_times); + } + } + else + { + rt_kprintf("Send %s - error\n", inet_ntoa(ina)); + } + + send_times++; + if (send_times >= times) + { + /* send ping times reached, stop */ + break; + } + + rt_thread_delay(PING_DELAY); /* take a delay */ + } + + lwip_close(s); + + return RT_EOK; +} +#ifdef RT_USING_FINSH +#include + +FINSH_FUNCTION_EXPORT(ping, ping network host); + +int cmd_ping(int argc, char **argv) +{ + if (argc == 1) + { + rt_kprintf("Please input: ping \n"); + } + else + { + ping(argv[1], 4, 0); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_ping, __cmd_ping, ping network host); +#endif /* RT_USING_FINSH */ + +#endif /* RT_USING_NETDEV */ + +#endif /* RT_LWIP_ICMP */ + diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_asn1.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_asn1.c new file mode 100644 index 0000000000..f35b760462 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_asn1.c @@ -0,0 +1,749 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) encoding + * + * @todo not optimised (yet), favor correctness over speed, favor speed over size + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "snmp_asn1.h" + +#define PBUF_OP_EXEC(code) \ + if ((code) != ERR_OK) { \ + return ERR_BUF; \ + } + +/** + * Encodes a TLV into a pbuf stream. + * + * @param pbuf_stream points to a pbuf stream + * @param tlv TLV to encode + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv) +{ + u8_t data; + u8_t length_bytes_required; + + /* write type */ + if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { + /* extended format is not used by SNMP so we do not accept those values */ + return ERR_ARG; + } + if (tlv->type_len != 0) { + /* any other value as auto is not accepted for type (we always use one byte because extended syntax is prohibited) */ + return ERR_ARG; + } + + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, tlv->type)); + tlv->type_len = 1; + + /* write length */ + if (tlv->value_len <= 127) { + length_bytes_required = 1; + } else if (tlv->value_len <= 255) { + length_bytes_required = 2; + } else { + length_bytes_required = 3; + } + + /* check for forced min length */ + if (tlv->length_len > 0) { + if (tlv->length_len < length_bytes_required) { + /* unable to code requested length in requested number of bytes */ + return ERR_ARG; + } + + length_bytes_required = tlv->length_len; + } else { + tlv->length_len = length_bytes_required; + } + + if (length_bytes_required > 1) { + /* multi byte representation required */ + length_bytes_required--; + data = 0x80 | length_bytes_required; /* extended length definition, 1 length byte follows */ + + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); + + while (length_bytes_required > 1) { + if (length_bytes_required == 2) { + /* append high byte */ + data = (u8_t)(tlv->value_len >> 8); + } else { + /* append leading 0x00 */ + data = 0x00; + } + + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); + length_bytes_required--; + } + } + + /* append low byte */ + data = (u8_t)(tlv->value_len & 0xFF); + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); + + return ERR_OK; +} + +/** + * Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg. + * + * @param pbuf_stream points to a pbuf stream + * @param raw_len raw data length + * @param raw points raw data + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len) +{ + PBUF_OP_EXEC(snmp_pbuf_stream_writebuf(pbuf_stream, raw, raw_len)); + + return ERR_OK; +} + +/** + * Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg. + * + * @param pbuf_stream points to a pbuf stream + * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) + * @param value is the host order u32_t value to be encoded + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_u32t_cnt() + */ +err_t +snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value) +{ + if (octets_needed > 5) { + return ERR_ARG; + } + if (octets_needed == 5) { + /* not enough bits in 'value' add leading 0x00 */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); + octets_needed--; + } + + while (octets_needed > 1) { + octets_needed--; + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); + } + + /* (only) one least significant octet */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); + + return ERR_OK; +} + +/** + * Encodes u64_t (counter64) into a pbuf chained ASN1 msg. + * + * @param pbuf_stream points to a pbuf stream + * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) + * @param value is the host order u32_t value to be encoded + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_u64t_cnt() + */ +err_t +snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value) +{ + if (octets_needed > 9) { + return ERR_ARG; + } + if (octets_needed == 9) { + /* not enough bits in 'value' add leading 0x00 */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); + octets_needed--; + } + + while (octets_needed > 4) { + octets_needed--; + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> ((octets_needed-4) << 3)))); + } + + /* skip to low u32 */ + value++; + + while (octets_needed > 1) { + octets_needed--; + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> (octets_needed << 3)))); + } + + /* always write at least one octet (also in case of value == 0) */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value))); + + return ERR_OK; +} + +/** + * Encodes s32_t integer into a pbuf chained ASN1 msg. + * + * @param pbuf_stream points to a pbuf stream + * @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt()) + * @param value is the host order s32_t value to be encoded + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_s32t_cnt() + */ +err_t +snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value) +{ + while (octets_needed > 1) { + octets_needed--; + + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); + } + + /* (only) one least significant octet */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); + + return ERR_OK; +} + +/** + * Encodes object identifier into a pbuf chained ASN1 msg. + * + * @param pbuf_stream points to a pbuf stream + * @param oid points to object identifier array + * @param oid_len object identifier array length + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len) +{ + if (oid_len > 1) { + /* write compressed first two sub id's */ + u32_t compressed_byte = ((oid[0] * 40) + oid[1]); + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)compressed_byte)); + oid_len -= 2; + oid += 2; + } else { + /* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */ + /* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */ + return ERR_ARG; + } + + while (oid_len > 0) { + u32_t sub_id; + u8_t shift, tail; + + oid_len--; + sub_id = *oid; + tail = 0; + shift = 28; + while (shift > 0) { + u8_t code; + + code = (u8_t)(sub_id >> shift); + if ((code != 0) || (tail != 0)) { + tail = 1; + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, code | 0x80)); + } + shift -= 7; + } + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)sub_id & 0x7F)); + + /* proceed to next sub-identifier */ + oid++; + } + return ERR_OK; +} + +/** + * Returns octet count for length. + * + * @param length parameter length + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) +{ + if (length < 0x80U) { + *octets_needed = 1; + } else if (length < 0x100U) { + *octets_needed = 2; + } else { + *octets_needed = 3; + } +} + +/** + * Returns octet count for an u32_t. + * + * @param value value to be encoded + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +void +snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) +{ + if (value < 0x80UL) { + *octets_needed = 1; + } else if (value < 0x8000UL) { + *octets_needed = 2; + } else if (value < 0x800000UL) { + *octets_needed = 3; + } else if (value < 0x80000000UL) { + *octets_needed = 4; + } else { + *octets_needed = 5; + } +} + +/** + * Returns octet count for an u64_t. + * + * @param value value to be encoded + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +void +snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed) +{ + /* check if high u32 is 0 */ + if (*value == 0x00) { + /* only low u32 is important */ + value++; + snmp_asn1_enc_u32t_cnt(*value, octets_needed); + } else { + /* low u32 does not matter for length determination */ + snmp_asn1_enc_u32t_cnt(*value, octets_needed); + *octets_needed = *octets_needed + 4; /* add the 4 bytes of low u32 */ + } +} + +/** + * Returns octet count for an s32_t. + * + * @param value value to be encoded + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. + */ +void +snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) +{ + if (value < 0) { + value = ~value; + } + if (value < 0x80L) { + *octets_needed = 1; + } else if (value < 0x8000L) { + *octets_needed = 2; + } else if (value < 0x800000L) { + *octets_needed = 3; + } else { + *octets_needed = 4; + } +} + +/** + * Returns octet count for an object identifier. + * + * @param oid points to object identifier array + * @param oid_len object identifier array length + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed) +{ + u32_t sub_id; + + *octets_needed = 0; + if (oid_len > 1) { + /* compressed prefix in one octet */ + (*octets_needed)++; + oid_len -= 2; + oid += 2; + } + while (oid_len > 0) { + oid_len--; + sub_id = *oid; + + sub_id >>= 7; + (*octets_needed)++; + while (sub_id > 0) { + sub_id >>= 7; + (*octets_needed)++; + } + oid++; + } +} + +/** + * Decodes a TLV from a pbuf stream. + * + * @param pbuf_stream points to a pbuf stream + * @param tlv returns decoded TLV + * @return ERR_OK if successful, ERR_VAL if we can't decode + */ +err_t +snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv) +{ + u8_t data; + + /* decode type first */ + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + tlv->type = data; + + if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { + /* extended format is not used by SNMP so we do not accept those values */ + return ERR_VAL; + } + tlv->type_len = 1; + + /* now, decode length */ + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + + if (data < 0x80) { /* short form */ + tlv->length_len = 1; + tlv->value_len = data; + } else if (data > 0x80) { /* long form */ + u8_t length_bytes = data - 0x80; + tlv->length_len = length_bytes + 1; /* this byte + defined number of length bytes following */ + tlv->value_len = 0; + + while (length_bytes > 0) { + /* we only support up to u16.maxvalue-1 (2 bytes) but have to accept leading zero bytes */ + if (tlv->value_len > 0xFF) { + return ERR_VAL; + } + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + tlv->value_len <<= 8; + tlv->value_len |= data; + + /* take care for special value used for indefinite length */ + if (tlv->value_len == 0xFFFF) { + return ERR_VAL; + } + + length_bytes--; + } + } else { /* data == 0x80 indefinite length form */ + /* (not allowed for SNMP; RFC 1157, 3.2.2) */ + return ERR_VAL; + } + + return ERR_OK; +} + +/** + * Decodes positive integer (counter, gauge, timeticks) into u32_t. + * + * @param pbuf_stream points to a pbuf stream + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +err_t +snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) +{ + u8_t data; + + if ((len > 0) && (len <= 5)) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + + /* expecting sign bit to be zero, only unsigned please! */ + if (((len == 5) && (data == 0x00)) || ((len < 5) && ((data & 0x80) == 0))) { + *value = data; + len--; + + while (len > 0) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + + *value <<= 8; + *value |= data; + } + + return ERR_OK; + } + } + + return ERR_VAL; +} + +/** + * Decodes large positive integer (counter64) into 2x u32_t. + * + * @param pbuf_stream points to a pbuf stream + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +err_t +snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) +{ + u8_t data; + + if (len <= 4) { + /* high u32 is 0 */ + *value = 0; + /* directly skip to low u32 */ + value++; + } + + if ((len > 0) && (len <= 9)) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + + /* expecting sign bit to be zero, only unsigned please! */ + if (((len == 9) && (data == 0x00)) || ((len < 9) && ((data & 0x80) == 0))) { + *value = data; + len--; + + while (len > 0) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + + if (len == 4) { + /* skip to low u32 */ + value++; + *value = 0; + } else { + *value <<= 8; + } + + *value |= data; + len--; + } + + return ERR_OK; + } + } + + return ERR_VAL; +} + +/** + * Decodes integer into s32_t. + * + * @param pbuf_stream points to a pbuf stream + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed! + */ +err_t +snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value) +{ +#if BYTE_ORDER == LITTLE_ENDIAN + u8_t *lsb_ptr = (u8_t*)value; +#endif +#if BYTE_ORDER == BIG_ENDIAN + u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1; +#endif + u8_t sign; + u8_t data; + + if ((len > 0) && (len < 5)) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + + if (data & 0x80) { + /* negative, start from -1 */ + *value = -1; + sign = 1; + *lsb_ptr &= data; + } else { + /* positive, start from 0 */ + *value = 0; + sign = 0; + *lsb_ptr |= data; + } + + /* OR/AND octets with value */ + while (len > 0) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + +#if BYTE_ORDER == LITTLE_ENDIAN + *value <<= 8; +#endif +#if BYTE_ORDER == BIG_ENDIAN + *value >>= 8; +#endif + + if (sign) { + *lsb_ptr |= 255; + *lsb_ptr &= data; + } else { + *lsb_ptr |= data; + } + } + + return ERR_OK; + } + + return ERR_VAL; +} + +/** + * Decodes object identifier from incoming message into array of u32_t. + * + * @param pbuf_stream points to a pbuf stream + * @param len length of the coded object identifier + * @param oid return decoded object identifier + * @param oid_len return decoded object identifier length + * @param oid_max_len size of oid buffer + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len) +{ + u32_t *oid_ptr; + u8_t data; + + *oid_len = 0; + oid_ptr = oid; + if (len > 0) { + if (oid_max_len < 2) { + return ERR_MEM; + } + + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + + /* first compressed octet */ + if (data == 0x2B) { + /* (most) common case 1.3 (iso.org) */ + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = 3; + oid_ptr++; + } else if (data < 40) { + *oid_ptr = 0; + oid_ptr++; + *oid_ptr = data; + oid_ptr++; + } else if (data < 80) { + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = data - 40; + oid_ptr++; + } else { + *oid_ptr = 2; + oid_ptr++; + *oid_ptr = data - 80; + oid_ptr++; + } + *oid_len = 2; + } else { + /* accepting zero length identifiers e.g. for getnext operation. uncommon but valid */ + return ERR_OK; + } + + while ((len > 0) && (*oid_len < oid_max_len)) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + + if ((data & 0x80) == 0x00) { + /* sub-identifier uses single octet */ + *oid_ptr = data; + } else { + /* sub-identifier uses multiple octets */ + u32_t sub_id = (data & ~0x80); + while ((len > 0) && ((data & 0x80) != 0)) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + + sub_id = (sub_id << 7) + (data & ~0x80); + } + + if ((data & 0x80) != 0) { + /* "more bytes following" bit still set at end of len */ + return ERR_VAL; + } + *oid_ptr = sub_id; + } + oid_ptr++; + (*oid_len)++; + } + + if (len > 0) { + /* OID to long to fit in our buffer */ + return ERR_MEM; + } + + return ERR_OK; +} + +/** + * Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding) + * from incoming message into array. + * + * @param pbuf_stream points to a pbuf stream + * @param len length of the coded raw data (zero is valid, e.g. empty string!) + * @param buf return raw bytes + * @param buf_len returns length of the raw return value + * @param buf_max_len buffer size + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len) +{ + if (len > buf_max_len) { + /* not enough dst space */ + return ERR_MEM; + } + *buf_len = len; + + while (len > 0) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, buf)); + buf++; + len--; + } + + return ERR_OK; +} + +#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_asn1.h b/components/net/lwip-2.0.3/src/apps/snmp/snmp_asn1.h new file mode 100644 index 0000000000..ec50d8c9e3 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_asn1.h @@ -0,0 +1,108 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) codec. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel + * Elias Oenal + */ + +#ifndef LWIP_HDR_APPS_SNMP_ASN1_H +#define LWIP_HDR_APPS_SNMP_ASN1_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP + +#include "lwip/err.h" +#include "lwip/apps/snmp_core.h" +#include "snmp_pbuf_stream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SNMP_ASN1_TLV_INDEFINITE_LENGTH 0x80 + +#define SNMP_ASN1_CLASS_MASK 0xC0 +#define SNMP_ASN1_CONTENTTYPE_MASK 0x20 +#define SNMP_ASN1_DATATYPE_MASK 0x1F +#define SNMP_ASN1_DATATYPE_EXTENDED 0x1F /* DataType indicating that datatype is encoded in following bytes */ + +/* context specific (SNMP) tags (from SNMP spec. RFC1157) */ +#define SNMP_ASN1_CONTEXT_PDU_GET_REQ 0 +#define SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ 1 +#define SNMP_ASN1_CONTEXT_PDU_GET_RESP 2 +#define SNMP_ASN1_CONTEXT_PDU_SET_REQ 3 +#define SNMP_ASN1_CONTEXT_PDU_TRAP 4 +#define SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ 5 + +#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT 0 +#define SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW 2 + +struct snmp_asn1_tlv +{ + u8_t type; /* only U8 because extended types are not specified by SNMP */ + u8_t type_len; /* encoded length of 'type' field (normally 1) */ + u8_t length_len; /* indicates how many bytes are required to encode the 'value_len' field */ + u16_t value_len; /* encoded length of the value */ +}; +#define SNMP_ASN1_TLV_HDR_LENGTH(tlv) ((tlv).type_len + (tlv).length_len) +#define SNMP_ASN1_TLV_LENGTH(tlv) ((tlv).type_len + (tlv).length_len + (tlv).value_len) +#define SNMP_ASN1_SET_TLV_PARAMS(tlv, type_, length_len_, value_len_) do { (tlv).type = (type_); (tlv).type_len = 0; (tlv).length_len = (length_len_); (tlv).value_len = (value_len_); } while (0); + +err_t snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv); +err_t snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); +err_t snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); +err_t snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value); +err_t snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len); +err_t snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len); + +err_t snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv); + +void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); +void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); +void snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed); +void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); +void snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed); +err_t snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len); +err_t snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value); +err_t snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value); +err_t snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value); +err_t snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_APPS_SNMP_ASN1_H */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_core.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_core.c new file mode 100644 index 0000000000..c041833617 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_core.c @@ -0,0 +1,1349 @@ +/** + * @file + * MIB tree access/construction functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel +*/ + +/** + * @defgroup snmp SNMPv2c agent + * @ingroup apps + * SNMPv2c compatible agent\n + * There is also a MIB compiler and a MIB viewer in lwIP contrib repository + * (lwip-contrib/apps/LwipMibCompiler).\n + * The agent implements the most important MIB2 MIBs including IPv6 support + * (interfaces, UDP, TCP, SNMP, ICMP, SYSTEM). IP MIB is an older version + * whithout IPv6 statistics (TODO).\n + * Rewritten by Martin Hentschel and + * Dirk Ziegelmeier \n + * Work on SNMPv3 has started, but is not finished.\n + * + * 0 Agent Capabilities + * ==================== + * + * Features: + * --------- + * - SNMPv2c support. + * - Low RAM usage - no memory pools, stack only. + * - MIB2 implementation is separated from SNMP stack. + * - Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB. + * - Simple and generic API for MIB implementation. + * - Comfortable node types and helper functions for scalar arrays and tables. + * - Counter64, bit and truthvalue datatype support. + * - Callbacks for SNMP writes e.g. to implement persistency. + * - Runs on two APIs: RAW and netconn. + * - Async API is gone - the stack now supports netconn API instead, + * so blocking operations can be done in MIB calls. + * SNMP runs in a worker thread when netconn API is used. + * - Simplified thread sync support for MIBs - useful when MIBs + * need to access variables shared with other threads where no locking is + * possible. Used in MIB2 to access lwIP stats from lwIP thread. + * + * MIB compiler (code generator): + * ------------------------------ + * - Provided in lwIP contrib repository. + * - Written in C#. MIB viewer used Windows Forms. + * - Developed on Windows with Visual Studio 2010. + * - Can be compiled and used on all platforms with http://www.monodevelop.com/. + * - Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4) + * (https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate). + * - MIB parser, C file generation framework and LWIP code generation are cleanly + * separated, which means the code may be useful as a base for code generation + * of other SNMP agents. + * + * Notes: + * ------ + * - Stack and MIB compiler were used to implement a Profinet device. + * Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB. + * + * SNMPv1 per RFC1157 and SNMPv2c per RFC 3416 + * ------------------------------------------- + * Note the S in SNMP stands for "Simple". Note that "Simple" is + * relative. SNMP is simple compared to the complex ISO network + * management protocols CMIP (Common Management Information Protocol) + * and CMOT (CMip Over Tcp). + * + * MIB II + * ------ + * The standard lwIP stack management information base. + * This is a required MIB, so this is always enabled. + * The groups EGP, CMOT and transmission are disabled by default. + * + * Most mib-2 objects are not writable except: + * sysName, sysLocation, sysContact, snmpEnableAuthenTraps. + * Writing to or changing the ARP and IP address and route + * tables is not possible. + * + * Note lwIP has a very limited notion of IP routing. It currently + * doen't have a route table and doesn't have a notion of the U,G,H flags. + * Instead lwIP uses the interface list with only one default interface + * acting as a single gateway interface (G) for the default route. + * + * The agent returns a "virtual table" with the default route 0.0.0.0 + * for the default interface and network routes (no H) for each + * network interface in the netif_list. + * All routes are considered to be up (U). + * + * Loading additional MIBs + * ----------------------- + * MIBs can only be added in compile-time, not in run-time. + * + * + * 1 Building the Agent + * ==================== + * First of all you'll need to add the following define + * to your local lwipopts.h: + * \#define LWIP_SNMP 1 + * + * and add the source files your makefile. + * + * Note you'll might need to adapt you network driver to update + * the mib2 variables for your interface. + * + * 2 Running the Agent + * =================== + * The following function calls must be made in your program to + * actually get the SNMP agent running. + * + * Before starting the agent you should supply pointers + * for sysContact, sysLocation, and snmpEnableAuthenTraps. + * You can do this by calling + * + * - snmp_mib2_set_syscontact() + * - snmp_mib2_set_syslocation() + * - snmp_set_auth_traps_enabled() + * + * You can register a callback which is called on successful write access: + * snmp_set_write_callback(). + * + * Additionally you may want to set + * + * - snmp_mib2_set_sysdescr() + * - snmp_set_device_enterprise_oid() + * - snmp_mib2_set_sysname() + * + * Also before starting the agent you need to setup + * one or more trap destinations using these calls: + * + * - snmp_trap_dst_enable() + * - snmp_trap_dst_ip_set() + * + * If you need more than MIB2, set the MIBs you want to use + * by snmp_set_mibs(). + * + * Finally, enable the agent by calling snmp_init() + * + * @defgroup snmp_core Core + * @ingroup snmp + * + * @defgroup snmp_traps Traps + * @ingroup snmp + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "snmp_core_priv.h" +#include "lwip/netif.h" +#include + + +#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) + #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_SNMP) + #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif + +struct snmp_statistics snmp_stats; +static const struct snmp_obj_id snmp_device_enterprise_oid_default = {SNMP_DEVICE_ENTERPRISE_OID_LEN, SNMP_DEVICE_ENTERPRISE_OID}; +static const struct snmp_obj_id* snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default; + +const u32_t snmp_zero_dot_zero_values[] = { 0, 0 }; +const struct snmp_obj_id_const_ref snmp_zero_dot_zero = { LWIP_ARRAYSIZE(snmp_zero_dot_zero_values), snmp_zero_dot_zero_values }; + + +#if SNMP_LWIP_MIB2 +#include "lwip/apps/snmp_mib2.h" +static const struct snmp_mib* const default_mibs[] = { &mib2 }; +static u8_t snmp_num_mibs = 1; +#else +static const struct snmp_mib* const default_mibs[] = { NULL }; +static u8_t snmp_num_mibs = 0; +#endif + +/* List of known mibs */ +static struct snmp_mib const * const *snmp_mibs = default_mibs; + +/** + * @ingroup snmp_core + * Sets the MIBs to use. + * Example: call snmp_set_mibs() as follows: + * static const struct snmp_mib *my_snmp_mibs[] = { + * &mib2, + * &private_mib + * }; + * snmp_set_mibs(my_snmp_mibs, LWIP_ARRAYSIZE(my_snmp_mibs)); + */ +void +snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs) +{ + LWIP_ASSERT("mibs pointer must be != NULL", (mibs != NULL)); + LWIP_ASSERT("num_mibs pointer must be != 0", (num_mibs != 0)); + snmp_mibs = mibs; + snmp_num_mibs = num_mibs; +} + +/** + * @ingroup snmp_core + * 'device enterprise oid' is used for 'device OID' field in trap PDU's (for identification of generating device) + * as well as for value returned by MIB-2 'sysObjectID' field (if internal MIB2 implementation is used). + * The 'device enterprise oid' shall point to an OID located under 'private-enterprises' branch (1.3.6.1.4.1.XXX). If a vendor + * wants to provide a custom object there, he has to get its own enterprise oid from IANA (http://www.iana.org). It + * is not allowed to use LWIP enterprise ID! + * In order to identify a specific device it is recommended to create a dedicated OID for each device type under its own + * enterprise oid. + * e.g. + * device a > 1.3.6.1.4.1.XXX(ent-oid).1(devices).1(device a) + * device b > 1.3.6.1.4.1.XXX(ent-oid).1(devices).2(device b) + * for more details see description of 'sysObjectID' field in RFC1213-MIB + */ +void snmp_set_device_enterprise_oid(const struct snmp_obj_id* device_enterprise_oid) +{ + if (device_enterprise_oid == NULL) { + snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default; + } else { + snmp_device_enterprise_oid = device_enterprise_oid; + } +} + +/** + * @ingroup snmp_core + * Get 'device enterprise oid' + */ +const struct snmp_obj_id* snmp_get_device_enterprise_oid(void) +{ + return snmp_device_enterprise_oid; +} + +#if LWIP_IPV4 +/** + * Conversion from InetAddressIPv4 oid to lwIP ip4_addr + * @param oid points to u32_t ident[4] input + * @param ip points to output struct + */ +u8_t +snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip) +{ + if ((oid[0] > 0xFF) || + (oid[1] > 0xFF) || + (oid[2] > 0xFF) || + (oid[3] > 0xFF)) { + ip4_addr_copy(*ip, *IP4_ADDR_ANY4); + return 0; + } + + IP4_ADDR(ip, oid[0], oid[1], oid[2], oid[3]); + return 1; +} + +/** + * Convert ip4_addr to InetAddressIPv4 (no InetAddressType) + * @param ip points to input struct + * @param oid points to u32_t ident[4] output + */ +void +snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid) +{ + oid[0] = ip4_addr1(ip); + oid[1] = ip4_addr2(ip); + oid[2] = ip4_addr3(ip); + oid[3] = ip4_addr4(ip); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Conversion from InetAddressIPv6 oid to lwIP ip6_addr + * @param oid points to u32_t oid[16] input + * @param ip points to output struct + */ +u8_t +snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip) +{ + if ((oid[0] > 0xFF) || + (oid[1] > 0xFF) || + (oid[2] > 0xFF) || + (oid[3] > 0xFF) || + (oid[4] > 0xFF) || + (oid[5] > 0xFF) || + (oid[6] > 0xFF) || + (oid[7] > 0xFF) || + (oid[8] > 0xFF) || + (oid[9] > 0xFF) || + (oid[10] > 0xFF) || + (oid[11] > 0xFF) || + (oid[12] > 0xFF) || + (oid[13] > 0xFF) || + (oid[14] > 0xFF) || + (oid[15] > 0xFF)) { + ip6_addr_set_any(ip); + return 0; + } + + ip->addr[0] = (oid[0] << 24) | (oid[1] << 16) | (oid[2] << 8) | (oid[3] << 0); + ip->addr[1] = (oid[4] << 24) | (oid[5] << 16) | (oid[6] << 8) | (oid[7] << 0); + ip->addr[2] = (oid[8] << 24) | (oid[9] << 16) | (oid[10] << 8) | (oid[11] << 0); + ip->addr[3] = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | (oid[15] << 0); + return 1; +} + +/** + * Convert ip6_addr to InetAddressIPv6 (no InetAddressType) + * @param ip points to input struct + * @param oid points to u32_t ident[16] output + */ +void +snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid) +{ + oid[0] = (ip->addr[0] & 0xFF000000) >> 24; + oid[1] = (ip->addr[0] & 0x00FF0000) >> 16; + oid[2] = (ip->addr[0] & 0x0000FF00) >> 8; + oid[3] = (ip->addr[0] & 0x000000FF) >> 0; + oid[4] = (ip->addr[1] & 0xFF000000) >> 24; + oid[5] = (ip->addr[1] & 0x00FF0000) >> 16; + oid[6] = (ip->addr[1] & 0x0000FF00) >> 8; + oid[7] = (ip->addr[1] & 0x000000FF) >> 0; + oid[8] = (ip->addr[2] & 0xFF000000) >> 24; + oid[9] = (ip->addr[2] & 0x00FF0000) >> 16; + oid[10] = (ip->addr[2] & 0x0000FF00) >> 8; + oid[11] = (ip->addr[2] & 0x000000FF) >> 0; + oid[12] = (ip->addr[3] & 0xFF000000) >> 24; + oid[13] = (ip->addr[3] & 0x00FF0000) >> 16; + oid[14] = (ip->addr[3] & 0x0000FF00) >> 8; + oid[15] = (ip->addr[3] & 0x000000FF) >> 0; +} +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV4 || LWIP_IPV6 +/** + * Convert to InetAddressType+InetAddress+InetPortNumber + * @param ip IP address + * @param port Port + * @param oid OID + * @return OID length + */ +u8_t +snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid) +{ + u8_t idx; + + idx = snmp_ip_to_oid(ip, oid); + oid[idx] = port; + idx++; + + return idx; +} + +/** + * Convert to InetAddressType+InetAddress + * @param ip IP address + * @param oid OID + * @return OID length + */ +u8_t +snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid) +{ + if (IP_IS_ANY_TYPE_VAL(*ip)) { + oid[0] = 0; /* any */ + oid[1] = 0; /* no IP OIDs follow */ + return 2; + } else if (IP_IS_V6(ip)) { +#if LWIP_IPV6 + oid[0] = 2; /* ipv6 */ + oid[1] = 16; /* 16 InetAddressIPv6 OIDs follow */ + snmp_ip6_to_oid(ip_2_ip6(ip), &oid[2]); + return 18; +#else /* LWIP_IPV6 */ + return 0; +#endif /* LWIP_IPV6 */ + } else { +#if LWIP_IPV4 + oid[0] = 1; /* ipv4 */ + oid[1] = 4; /* 4 InetAddressIPv4 OIDs follow */ + snmp_ip4_to_oid(ip_2_ip4(ip), &oid[2]); + return 6; +#else /* LWIP_IPV4 */ + return 0; +#endif /* LWIP_IPV4 */ + } +} + +/** + * Convert from InetAddressType+InetAddress to ip_addr_t + * @param oid OID + * @param oid_len OID length + * @param ip IP address + * @return Parsed OID length + */ +u8_t +snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip) +{ + /* InetAddressType */ + if (oid_len < 1) { + return 0; + } + + if (oid[0] == 0) { /* any */ + /* 1x InetAddressType, 1x OID len */ + if (oid_len < 2) { + return 0; + } + if (oid[1] != 0) { + return 0; + } + + memset(ip, 0, sizeof(*ip)); + IP_SET_TYPE(ip, IPADDR_TYPE_ANY); + + return 2; + } else if (oid[0] == 1) { /* ipv4 */ +#if LWIP_IPV4 + /* 1x InetAddressType, 1x OID len, 4x InetAddressIPv4 */ + if (oid_len < 6) { + return 0; + } + + /* 4x ipv4 OID */ + if (oid[1] != 4) { + return 0; + } + + IP_SET_TYPE(ip, IPADDR_TYPE_V4); + if (!snmp_oid_to_ip4(&oid[2], ip_2_ip4(ip))) { + return 0; + } + + return 6; +#else /* LWIP_IPV4 */ + return 0; +#endif /* LWIP_IPV4 */ + } else if (oid[0] == 2) { /* ipv6 */ +#if LWIP_IPV6 + /* 1x InetAddressType, 1x OID len, 16x InetAddressIPv6 */ + if (oid_len < 18) { + return 0; + } + + /* 16x ipv6 OID */ + if (oid[1] != 16) { + return 0; + } + + IP_SET_TYPE(ip, IPADDR_TYPE_V6); + if (!snmp_oid_to_ip6(&oid[2], ip_2_ip6(ip))) { + return 0; + } + + return 18; +#else /* LWIP_IPV6 */ + return 0; +#endif /* LWIP_IPV6 */ + } else { /* unsupported InetAddressType */ + return 0; + } +} + +/** + * Convert from InetAddressType+InetAddress+InetPortNumber to ip_addr_t and u16_t + * @param oid OID + * @param oid_len OID length + * @param ip IP address + * @param port Port + * @return Parsed OID length + */ +u8_t +snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port) +{ + u8_t idx = 0; + + /* InetAddressType + InetAddress */ + idx += snmp_oid_to_ip(&oid[idx], oid_len-idx, ip); + if (idx == 0) { + return 0; + } + + /* InetPortNumber */ + if (oid_len < (idx+1)) { + return 0; + } + if (oid[idx] > 0xffff) { + return 0; + } + *port = (u16_t)oid[idx]; + idx++; + + return idx; +} + +#endif /* LWIP_IPV4 || LWIP_IPV6 */ + +/** + * Assign an OID to struct snmp_obj_id + * @param target Assignment target + * @param oid OID + * @param oid_len OID length + */ +void +snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) +{ + LWIP_ASSERT("oid_len <= LWIP_SNMP_OBJ_ID_LEN", oid_len <= SNMP_MAX_OBJ_ID_LEN); + + target->len = oid_len; + + if (oid_len > 0) { + MEMCPY(target->id, oid, oid_len * sizeof(u32_t)); + } +} + +/** + * Prefix an OID to OID in struct snmp_obj_id + * @param target Assignment target to prefix + * @param oid OID + * @param oid_len OID length + */ +void +snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) +{ + LWIP_ASSERT("target->len + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN); + + if (oid_len > 0) { + /* move existing OID to make room at the beginning for OID to insert */ + int i; + for (i = target->len-1; i>=0; i--) { + target->id[i + oid_len] = target->id[i]; + } + + /* paste oid at the beginning */ + MEMCPY(target->id, oid, oid_len * sizeof(u32_t)); + } +} + +/** + * Combine two OIDs into struct snmp_obj_id + * @param target Assignmet target + * @param oid1 OID 1 + * @param oid1_len OID 1 length + * @param oid2 OID 2 + * @param oid2_len OID 2 length + */ +void +snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) +{ + snmp_oid_assign(target, oid1, oid1_len); + snmp_oid_append(target, oid2, oid2_len); +} + +/** + * Append OIDs to struct snmp_obj_id + * @param target Assignment target to append to + * @param oid OID + * @param oid_len OID length + */ +void +snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) +{ + LWIP_ASSERT("offset + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN); + + if (oid_len > 0) { + MEMCPY(&target->id[target->len], oid, oid_len * sizeof(u32_t)); + target->len += oid_len; + } +} + +/** + * Compare two OIDs + * @param oid1 OID 1 + * @param oid1_len OID 1 length + * @param oid2 OID 2 + * @param oid2_len OID 2 length + * @return -1: OID1<OID2 1: OID1 >OID2 0: equal + */ +s8_t +snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) +{ + u8_t level = 0; + LWIP_ASSERT("'oid1' param must not be NULL or 'oid1_len' param be 0!", (oid1 != NULL) || (oid1_len == 0)); + LWIP_ASSERT("'oid2' param must not be NULL or 'oid2_len' param be 0!", (oid2 != NULL) || (oid2_len == 0)); + + while ((level < oid1_len) && (level < oid2_len)) { + if (*oid1 < *oid2) { + return -1; + } + if (*oid1 > *oid2) { + return 1; + } + + level++; + oid1++; + oid2++; + } + + /* common part of both OID's is equal, compare length */ + if (oid1_len < oid2_len) { + return -1; + } + if (oid1_len > oid2_len) { + return 1; + } + + /* they are equal */ + return 0; +} + + +/** + * Check of two OIDs are equal + * @param oid1 OID 1 + * @param oid1_len OID 1 length + * @param oid2 OID 2 + * @param oid2_len OID 2 length + * @return 1: equal 0: non-equal + */ +u8_t +snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) +{ + return (snmp_oid_compare(oid1, oid1_len, oid2, oid2_len) == 0)? 1 : 0; +} + +/** + * Convert netif to interface index + * @param netif netif + * @return index + */ +u8_t +netif_to_num(const struct netif *netif) +{ + u8_t result = 0; + struct netif *netif_iterator = netif_list; + + while (netif_iterator != NULL) { + result++; + + if (netif_iterator == netif) { + return result; + } + + netif_iterator = netif_iterator->next; + } + + LWIP_ASSERT("netif not found in netif_list", 0); + return 0; +} + +static const struct snmp_mib* +snmp_get_mib_from_oid(const u32_t *oid, u8_t oid_len) +{ + const u32_t* list_oid; + const u32_t* searched_oid; + u8_t i, l; + + u8_t max_match_len = 0; + const struct snmp_mib* matched_mib = NULL; + + LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL)); + + if (oid_len == 0) { + return NULL; + } + + for (i = 0; i < snmp_num_mibs; i++) { + LWIP_ASSERT("MIB array not initialized correctly", (snmp_mibs[i] != NULL)); + LWIP_ASSERT("MIB array not initialized correctly - base OID is NULL", (snmp_mibs[i]->base_oid != NULL)); + + if (oid_len >= snmp_mibs[i]->base_oid_len) { + l = snmp_mibs[i]->base_oid_len; + list_oid = snmp_mibs[i]->base_oid; + searched_oid = oid; + + while (l > 0) { + if (*list_oid != *searched_oid) { + break; + } + + l--; + list_oid++; + searched_oid++; + } + + if ((l == 0) && (snmp_mibs[i]->base_oid_len > max_match_len)) { + max_match_len = snmp_mibs[i]->base_oid_len; + matched_mib = snmp_mibs[i]; + } + } + } + + return matched_mib; +} + +static const struct snmp_mib* +snmp_get_next_mib(const u32_t *oid, u8_t oid_len) +{ + u8_t i; + const struct snmp_mib* next_mib = NULL; + + LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL)); + + if (oid_len == 0) { + return NULL; + } + + for (i = 0; i < snmp_num_mibs; i++) { + if (snmp_mibs[i]->base_oid != NULL) { + /* check if mib is located behind starting point */ + if (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, oid, oid_len) > 0) { + if ((next_mib == NULL) || + (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, + next_mib->base_oid, next_mib->base_oid_len) < 0)) { + next_mib = snmp_mibs[i]; + } + } + } + } + + return next_mib; +} + +static const struct snmp_mib* +snmp_get_mib_between(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) +{ + const struct snmp_mib* next_mib = snmp_get_next_mib(oid1, oid1_len); + + LWIP_ASSERT("'oid2' param must not be NULL!", (oid2 != NULL)); + LWIP_ASSERT("'oid2_len' param must be greater than 0!", (oid2_len > 0)); + + if (next_mib != NULL) { + if (snmp_oid_compare(next_mib->base_oid, next_mib->base_oid_len, oid2, oid2_len) < 0) { + return next_mib; + } + } + + return NULL; +} + +u8_t +snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance) +{ + u8_t result = SNMP_ERR_NOSUCHOBJECT; + const struct snmp_mib *mib; + const struct snmp_node *mn = NULL; + + mib = snmp_get_mib_from_oid(oid, oid_len); + if (mib != NULL) { + u8_t oid_instance_len; + + mn = snmp_mib_tree_resolve_exact(mib, oid, oid_len, &oid_instance_len); + if ((mn != NULL) && (mn->node_type != SNMP_NODE_TREE)) { + /* get instance */ + const struct snmp_leaf_node* leaf_node = (const struct snmp_leaf_node*)(const void*)mn; + + node_instance->node = mn; + snmp_oid_assign(&node_instance->instance_oid, oid + (oid_len - oid_instance_len), oid_instance_len); + + result = leaf_node->get_instance( + oid, + oid_len - oid_instance_len, + node_instance); + +#ifdef LWIP_DEBUG + if (result == SNMP_ERR_NOERROR) { + if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) { + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n")); + } + if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) { + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value and/or set_test function is specified\n")); + } + } +#endif + } + } + + return result; +} + +u8_t +snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance) +{ + const struct snmp_mib *mib; + const struct snmp_node *mn = NULL; + const u32_t* start_oid = NULL; + u8_t start_oid_len = 0; + + /* resolve target MIB from passed OID */ + mib = snmp_get_mib_from_oid(oid, oid_len); + if (mib == NULL) { + /* passed OID does not reference any known MIB, start at the next closest MIB */ + mib = snmp_get_next_mib(oid, oid_len); + + if (mib != NULL) { + start_oid = mib->base_oid; + start_oid_len = mib->base_oid_len; + } + } else { + start_oid = oid; + start_oid_len = oid_len; + } + + /* resolve target node from MIB, skip to next MIB if no suitable node is found in current MIB */ + while ((mib != NULL) && (mn == NULL)) { + u8_t oid_instance_len; + + /* check if OID directly references a node inside current MIB, in this case we have to ask this node for the next instance */ + mn = snmp_mib_tree_resolve_exact(mib, start_oid, start_oid_len, &oid_instance_len); + if (mn != NULL) { + snmp_oid_assign(node_oid, start_oid, start_oid_len - oid_instance_len); /* set oid to node */ + snmp_oid_assign(&node_instance->instance_oid, start_oid + (start_oid_len - oid_instance_len), oid_instance_len); /* set (relative) instance oid */ + } else { + /* OID does not reference a node, search for the next closest node inside MIB; set instance_oid.len to zero because we want the first instance of this node */ + mn = snmp_mib_tree_resolve_next(mib, start_oid, start_oid_len, node_oid); + node_instance->instance_oid.len = 0; + } + + /* validate the node; if the node has no further instance or the returned instance is invalid, search for the next in MIB and validate again */ + node_instance->node = mn; + while (mn != NULL) { + u8_t result; + + /* clear fields which may have values from previous loops */ + node_instance->asn1_type = 0; + node_instance->access = SNMP_NODE_INSTANCE_NOT_ACCESSIBLE; + node_instance->get_value = NULL; + node_instance->set_test = NULL; + node_instance->set_value = NULL; + node_instance->release_instance = NULL; + node_instance->reference.ptr = NULL; + node_instance->reference_len = 0; + + result = ((const struct snmp_leaf_node*)(const void*)mn)->get_next_instance( + node_oid->id, + node_oid->len, + node_instance); + + if (result == SNMP_ERR_NOERROR) { +#ifdef LWIP_DEBUG + if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) { + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n")); + } + if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) { + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value function is specified\n")); + } +#endif + + /* validate node because the node may be not accessible for example (but let the caller decide what is valid */ + if ((validate_node_instance_method == NULL) || + (validate_node_instance_method(node_instance, validate_node_instance_arg) == SNMP_ERR_NOERROR)) { + /* node_oid "returns" the full result OID (including the instance part) */ + snmp_oid_append(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len); + break; + } + + if (node_instance->release_instance != NULL) { + node_instance->release_instance(node_instance); + } + /* + the instance itself is not valid, ask for next instance from same node. + we don't have to change any variables because node_instance->instance_oid is used as input (starting point) + as well as output (resulting next OID), so we have to simply call get_next_instance method again + */ + } else { + if (node_instance->release_instance != NULL) { + node_instance->release_instance(node_instance); + } + + /* the node has no further instance, skip to next node */ + mn = snmp_mib_tree_resolve_next(mib, node_oid->id, node_oid->len, &node_instance->instance_oid); /* misuse node_instance->instance_oid as tmp buffer */ + if (mn != NULL) { + /* prepare for next loop */ + snmp_oid_assign(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len); + node_instance->instance_oid.len = 0; + node_instance->node = mn; + } + } + } + + if (mn != NULL) { + /* + we found a suitable next node, + now we have to check if a inner MIB is located between the searched OID and the resulting OID. + this is possible because MIB's may be located anywhere in the global tree, that means also in + the subtree of another MIB (e.g. if searched OID is .2 and resulting OID is .4, then another + MIB having .3 as root node may exist) + */ + const struct snmp_mib *intermediate_mib; + intermediate_mib = snmp_get_mib_between(start_oid, start_oid_len, node_oid->id, node_oid->len); + + if (intermediate_mib != NULL) { + /* search for first node inside intermediate mib in next loop */ + if (node_instance->release_instance != NULL) { + node_instance->release_instance(node_instance); + } + + mn = NULL; + mib = intermediate_mib; + start_oid = mib->base_oid; + start_oid_len = mib->base_oid_len; + } + /* else { we found out target node } */ + } else { + /* + there is no further (suitable) node inside this MIB, search for the next MIB with following priority + 1. search for inner MIB's (whose root is located inside tree of current MIB) + 2. search for surrouding MIB's (where the current MIB is the inner MIB) and continue there if any + 3. take the next closest MIB (not being related to the current MIB) + */ + const struct snmp_mib *next_mib; + next_mib = snmp_get_next_mib(start_oid, start_oid_len); /* returns MIB's related to point 1 and 3 */ + + /* is the found MIB an inner MIB? (point 1) */ + if ((next_mib != NULL) && (next_mib->base_oid_len > mib->base_oid_len) && + (snmp_oid_compare(next_mib->base_oid, mib->base_oid_len, mib->base_oid, mib->base_oid_len) == 0)) { + /* yes it is -> continue at inner MIB */ + mib = next_mib; + start_oid = mib->base_oid; + start_oid_len = mib->base_oid_len; + } else { + /* check if there is a surrounding mib where to continue (point 2) (only possible if OID length > 1) */ + if (mib->base_oid_len > 1) { + mib = snmp_get_mib_from_oid(mib->base_oid, mib->base_oid_len - 1); + + if (mib == NULL) { + /* no surrounding mib, use next mib encountered above (point 3) */ + mib = next_mib; + + if (mib != NULL) { + start_oid = mib->base_oid; + start_oid_len = mib->base_oid_len; + } + } + /* else { start_oid stays the same because we want to continue from current offset in surrounding mib (point 2) } */ + } + } + } + } + + if (mib == NULL) { + /* loop is only left when mib == null (error) or mib_node != NULL (success) */ + return SNMP_ERR_ENDOFMIBVIEW; + } + + return SNMP_ERR_NOERROR; +} + +/** + * Searches tree for the supplied object identifier. + * + */ +const struct snmp_node * +snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t* oid_instance_len) +{ + const struct snmp_node* const* node = &mib->root_node; + u8_t oid_offset = mib->base_oid_len; + + while ((oid_offset < oid_len) && ((*node)->node_type == SNMP_NODE_TREE)) { + /* search for matching sub node */ + u32_t subnode_oid = *(oid + oid_offset); + + u32_t i = (*(const struct snmp_tree_node* const*)node)->subnode_count; + node = (*(const struct snmp_tree_node* const*)node)->subnodes; + while ((i > 0) && ((*node)->oid != subnode_oid)) { + node++; + i--; + } + + if (i == 0) { + /* no matching subnode found */ + return NULL; + } + + oid_offset++; + } + + if ((*node)->node_type != SNMP_NODE_TREE) { + /* we found a leaf node */ + *oid_instance_len = oid_len - oid_offset; + return (*node); + } + + return NULL; +} + +const struct snmp_node* +snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret) +{ + u8_t oid_offset = mib->base_oid_len; + const struct snmp_node* const* node; + const struct snmp_tree_node* node_stack[SNMP_MAX_OBJ_ID_LEN]; + s32_t nsi = 0; /* NodeStackIndex */ + u32_t subnode_oid; + + if (mib->root_node->node_type != SNMP_NODE_TREE) { + /* a next operation on a mib with only a leaf node will always return NULL because there is no other node */ + return NULL; + } + + /* first build node stack related to passed oid (as far as possible), then go backwards to determine the next node */ + node_stack[nsi] = (const struct snmp_tree_node*)(const void*)mib->root_node; + while (oid_offset < oid_len) { + /* search for matching sub node */ + u32_t i = node_stack[nsi]->subnode_count; + node = node_stack[nsi]->subnodes; + + subnode_oid = *(oid + oid_offset); + + while ((i > 0) && ((*node)->oid != subnode_oid)) { + node++; + i--; + } + + if ((i == 0) || ((*node)->node_type != SNMP_NODE_TREE)) { + /* no (matching) tree-subnode found */ + break; + } + nsi++; + node_stack[nsi] = (const struct snmp_tree_node*)(const void*)(*node); + + oid_offset++; + } + + + if (oid_offset >= oid_len) { + /* passed oid references a tree node -> return first useable sub node of it */ + subnode_oid = 0; + } else { + subnode_oid = *(oid + oid_offset) + 1; + } + + while (nsi >= 0) { + const struct snmp_node* subnode = NULL; + + /* find next node on current level */ + s32_t i = node_stack[nsi]->subnode_count; + node = node_stack[nsi]->subnodes; + while (i > 0) { + if ((*node)->oid == subnode_oid) { + subnode = *node; + break; + } else if (((*node)->oid > subnode_oid) && ((subnode == NULL) || ((*node)->oid < subnode->oid))) { + subnode = *node; + } + + node++; + i--; + } + + if (subnode == NULL) { + /* no further node found on this level, go one level up and start searching with index of current node*/ + subnode_oid = node_stack[nsi]->node.oid + 1; + nsi--; + } else { + if (subnode->node_type == SNMP_NODE_TREE) { + /* next is a tree node, go into it and start searching */ + nsi++; + node_stack[nsi] = (const struct snmp_tree_node*)(const void*)subnode; + subnode_oid = 0; + } else { + /* we found a leaf node -> fill oidret and return it */ + snmp_oid_assign(oidret, mib->base_oid, mib->base_oid_len); + i = 1; + while (i <= nsi) { + oidret->id[oidret->len] = node_stack[i]->node.oid; + oidret->len++; + i++; + } + + oidret->id[oidret->len] = subnode->oid; + oidret->len++; + + return subnode; + } + } + } + + return NULL; +} + +/** initialize struct next_oid_state using this function before passing it to next_oid_check */ +void +snmp_next_oid_init(struct snmp_next_oid_state *state, + const u32_t *start_oid, u8_t start_oid_len, + u32_t *next_oid_buf, u8_t next_oid_max_len) +{ + state->start_oid = start_oid; + state->start_oid_len = start_oid_len; + state->next_oid = next_oid_buf; + state->next_oid_len = 0; + state->next_oid_max_len = next_oid_max_len; + state->status = SNMP_NEXT_OID_STATUS_NO_MATCH; +} + +/** checks if the passed incomplete OID may be a possible candidate for snmp_next_oid_check(); +this methid is intended if the complete OID is not yet known but it is very expensive to build it up, +so it is possible to test the starting part before building up the complete oid and pass it to snmp_next_oid_check()*/ +u8_t +snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len) +{ + if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) { + u8_t start_oid_len = (oid_len < state->start_oid_len) ? oid_len : state->start_oid_len; + + /* check passed OID is located behind start offset */ + if (snmp_oid_compare(oid, oid_len, state->start_oid, start_oid_len) >= 0) { + /* check if new oid is located closer to start oid than current closest oid */ + if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) || + (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) { + return 1; + } + } + } + + return 0; +} + +/** checks the passed OID if it is a candidate to be the next one (get_next); returns !=0 if passed oid is currently closest, otherwise 0 */ +u8_t +snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference) +{ + /* do not overwrite a fail result */ + if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) { + /* check passed OID is located behind start offset */ + if (snmp_oid_compare(oid, oid_len, state->start_oid, state->start_oid_len) > 0) { + /* check if new oid is located closer to start oid than current closest oid */ + if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) || + (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) { + if (oid_len <= state->next_oid_max_len) { + MEMCPY(state->next_oid, oid, oid_len * sizeof(u32_t)); + state->next_oid_len = oid_len; + state->status = SNMP_NEXT_OID_STATUS_SUCCESS; + state->reference = reference; + return 1; + } else { + state->status = SNMP_NEXT_OID_STATUS_BUF_TO_SMALL; + } + } + } + } + + return 0; +} + +u8_t +snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len) +{ + u8_t i; + + if (oid_len != oid_ranges_len) { + return 0; + } + + for (i = 0; i < oid_ranges_len; i++) { + if ((oid_in[i] < oid_ranges[i].min) || (oid_in[i] > oid_ranges[i].max)) { + return 0; + } + } + + return 1; +} + +snmp_err_t +snmp_set_test_ok(struct snmp_node_instance* instance, u16_t value_len, void* value) +{ + LWIP_UNUSED_ARG(instance); + LWIP_UNUSED_ARG(value_len); + LWIP_UNUSED_ARG(value); + + return SNMP_ERR_NOERROR; +} + +/** + * Decodes BITS pseudotype value from ASN.1 OctetString. + * + * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly + * be encoded/decoded by the agent. Instead call this function as required from + * get/test/set methods. + * + * @param buf points to a buffer holding the ASN1 octet string + * @param buf_len length of octet string + * @param bit_value decoded Bit value with Bit0 == LSB + * @return ERR_OK if successful, ERR_ARG if bit value contains more than 32 bit + */ +err_t +snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value) +{ + u8_t b; + u8_t bits_processed = 0; + *bit_value = 0; + + while (buf_len > 0) { + /* any bit set in this byte? */ + if (*buf != 0x00) { + if (bits_processed >= 32) { + /* accept more than 4 bytes, but only when no bits are set */ + return ERR_VAL; + } + + b = *buf; + do { + if (b & 0x80) { + *bit_value |= (1 << bits_processed); + } + bits_processed++; + b <<= 1; + } + while ((bits_processed & 0x07) != 0); /* &0x07 -> % 8 */ + } else { + bits_processed += 8; + } + + buf_len--; + buf++; + } + + return ERR_OK; +} + +err_t +snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value) +{ + /* defined by RFC1443: + TruthValue ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents a boolean value." + SYNTAX INTEGER { true(1), false(2) } + */ + + if ((asn1_value == NULL) || (bool_value == NULL)) { + return ERR_ARG; + } + + if (*asn1_value == 1) { + *bool_value = 1; + } else if (*asn1_value == 2) { + *bool_value = 0; + } else { + return ERR_VAL; + } + + return ERR_OK; +} + +/** + * Encodes BITS pseudotype value into ASN.1 OctetString. + * + * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly + * be encoded/decoded by the agent. Instead call this function as required from + * get/test/set methods. + * + * @param buf points to a buffer where the resulting ASN1 octet string is stored to + * @param buf_len max length of the bufffer + * @param bit_value Bit value to encode with Bit0 == LSB + * @param bit_count Number of possible bits for the bit value (according to rfc we have to send all bits independant from their truth value) + * @return number of bytes used from buffer to store the resulting OctetString + */ +u8_t +snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count) +{ + u8_t len = 0; + u8_t min_bytes = (bit_count + 7) >> 3; /* >>3 -> / 8 */ + + while ((buf_len > 0) && (bit_value != 0x00)) { + s8_t i = 7; + *buf = 0x00; + while (i >= 0) { + if (bit_value & 0x01) { + *buf |= 0x01; + } + + if (i > 0) { + *buf <<= 1; + } + + bit_value >>= 1; + i--; + } + + buf++; + buf_len--; + len++; + } + + if (len < min_bytes) { + buf += len; + buf_len -= len; + + while ((len < min_bytes) && (buf_len > 0)) { + *buf = 0x00; + buf++; + buf_len--; + len++; + } + } + + return len; +} + +u8_t +snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value) +{ + /* defined by RFC1443: + TruthValue ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents a boolean value." + SYNTAX INTEGER { true(1), false(2) } + */ + + if (asn1_value == NULL) { + return 0; + } + + if (bool_value) { + *asn1_value = 1; /* defined by RFC1443 */ + } else { + *asn1_value = 2; /* defined by RFC1443 */ + } + + return sizeof(s32_t); +} + +#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_core_priv.h b/components/net/lwip-2.0.3/src/apps/snmp/snmp_core_priv.h new file mode 100644 index 0000000000..5552177d74 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_core_priv.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#ifndef LWIP_HDR_APPS_SNMP_CORE_PRIV_H +#define LWIP_HDR_APPS_SNMP_CORE_PRIV_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp_core.h" +#include "snmp_asn1.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* (outdated) SNMPv1 error codes + * shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request + */ +#define SNMP_ERR_NOSUCHNAME 2 +#define SNMP_ERR_BADVALUE 3 +#define SNMP_ERR_READONLY 4 +/* error codes which are internal and shall not be used by MIBS + * shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request + */ +#define SNMP_ERR_TOOBIG 1 +#define SNMP_ERR_AUTHORIZATIONERROR 16 +#define SNMP_ERR_NOSUCHOBJECT SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT +#define SNMP_ERR_ENDOFMIBVIEW SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW + + +const struct snmp_node* snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t* oid_instance_len); +const struct snmp_node* snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret); + +typedef u8_t (*snmp_validate_node_instance_method)(struct snmp_node_instance*, void*); + +u8_t snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance); +u8_t snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_APPS_SNMP_CORE_PRIV_H */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2.c new file mode 100644 index 0000000000..9d8c43c108 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2.c @@ -0,0 +1,116 @@ +/** + * @file + * Management Information Base II (RFC1213) objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +/** + * @defgroup snmp_mib2 MIB2 + * @ingroup snmp + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP && SNMP_LWIP_MIB2 /* don't build if not configured for use in lwipopts.h */ + +#if !LWIP_STATS +#error LWIP_SNMP MIB2 needs LWIP_STATS (for MIB2) +#endif +#if !MIB2_STATS +#error LWIP_SNMP MIB2 needs MIB2_STATS (for MIB2) +#endif + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_scalar.h" + +#if SNMP_USE_NETCONN +#include "lwip/tcpip.h" +#include "lwip/priv/tcpip_priv.h" +void +snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg) +{ +#if LWIP_TCPIP_CORE_LOCKING + LOCK_TCPIP_CORE(); + fn(arg); + UNLOCK_TCPIP_CORE(); +#else + tcpip_callback(fn, arg); +#endif +} + +struct snmp_threadsync_instance snmp_mib2_lwip_locks; +#endif + +/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ +/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ +/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ + +/* --- mib-2 .1.3.6.1.2.1 ----------------------------------------------------- */ +extern const struct snmp_scalar_array_node snmp_mib2_snmp_root; +extern const struct snmp_tree_node snmp_mib2_udp_root; +extern const struct snmp_tree_node snmp_mib2_tcp_root; +extern const struct snmp_scalar_array_node snmp_mib2_icmp_root; +extern const struct snmp_tree_node snmp_mib2_interface_root; +extern const struct snmp_scalar_array_node snmp_mib2_system_node; +extern const struct snmp_tree_node snmp_mib2_at_root; +extern const struct snmp_tree_node snmp_mib2_ip_root; + +static const struct snmp_node* const mib2_nodes[] = { + &snmp_mib2_system_node.node.node, + &snmp_mib2_interface_root.node, +#if LWIP_ARP && LWIP_IPV4 + &snmp_mib2_at_root.node, +#endif /* LWIP_ARP && LWIP_IPV4 */ +#if LWIP_IPV4 + &snmp_mib2_ip_root.node, +#endif /* LWIP_IPV4 */ +#if LWIP_ICMP + &snmp_mib2_icmp_root.node.node, +#endif /* LWIP_ICMP */ +#if LWIP_TCP + &snmp_mib2_tcp_root.node, +#endif /* LWIP_TCP */ +#if LWIP_UDP + &snmp_mib2_udp_root.node, +#endif /* LWIP_UDP */ + &snmp_mib2_snmp_root.node.node +}; + +static const struct snmp_tree_node mib2_root = SNMP_CREATE_TREE_NODE(1, mib2_nodes); + +static const u32_t mib2_base_oid_arr[] = { 1,3,6,1,2,1 }; +const struct snmp_mib mib2 = SNMP_MIB_CREATE(mib2_base_oid_arr, &mib2_root.node); + +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_icmp.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_icmp.c new file mode 100644 index 0000000000..995bd320a5 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_icmp.c @@ -0,0 +1,182 @@ +/** + * @file + * Management Information Base II (RFC1213) ICMP objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/icmp.h" +#include "lwip/stats.h" + +#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + +/* --- icmp .1.3.6.1.2.1.5 ----------------------------------------------------- */ + +static s16_t +icmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + + switch (node->oid) { + case 1: /* icmpInMsgs */ + *uint_ptr = STATS_GET(mib2.icmpinmsgs); + return sizeof(*uint_ptr); + case 2: /* icmpInErrors */ + *uint_ptr = STATS_GET(mib2.icmpinerrors); + return sizeof(*uint_ptr); + case 3: /* icmpInDestUnreachs */ + *uint_ptr = STATS_GET(mib2.icmpindestunreachs); + return sizeof(*uint_ptr); + case 4: /* icmpInTimeExcds */ + *uint_ptr = STATS_GET(mib2.icmpintimeexcds); + return sizeof(*uint_ptr); + case 5: /* icmpInParmProbs */ + *uint_ptr = STATS_GET(mib2.icmpinparmprobs); + return sizeof(*uint_ptr); + case 6: /* icmpInSrcQuenchs */ + *uint_ptr = STATS_GET(mib2.icmpinsrcquenchs); + return sizeof(*uint_ptr); + case 7: /* icmpInRedirects */ + *uint_ptr = STATS_GET(mib2.icmpinredirects); + return sizeof(*uint_ptr); + case 8: /* icmpInEchos */ + *uint_ptr = STATS_GET(mib2.icmpinechos); + return sizeof(*uint_ptr); + case 9: /* icmpInEchoReps */ + *uint_ptr = STATS_GET(mib2.icmpinechoreps); + return sizeof(*uint_ptr); + case 10: /* icmpInTimestamps */ + *uint_ptr = STATS_GET(mib2.icmpintimestamps); + return sizeof(*uint_ptr); + case 11: /* icmpInTimestampReps */ + *uint_ptr = STATS_GET(mib2.icmpintimestampreps); + return sizeof(*uint_ptr); + case 12: /* icmpInAddrMasks */ + *uint_ptr = STATS_GET(mib2.icmpinaddrmasks); + return sizeof(*uint_ptr); + case 13: /* icmpInAddrMaskReps */ + *uint_ptr = STATS_GET(mib2.icmpinaddrmaskreps); + return sizeof(*uint_ptr); + case 14: /* icmpOutMsgs */ + *uint_ptr = STATS_GET(mib2.icmpoutmsgs); + return sizeof(*uint_ptr); + case 15: /* icmpOutErrors */ + *uint_ptr = STATS_GET(mib2.icmpouterrors); + return sizeof(*uint_ptr); + case 16: /* icmpOutDestUnreachs */ + *uint_ptr = STATS_GET(mib2.icmpoutdestunreachs); + return sizeof(*uint_ptr); + case 17: /* icmpOutTimeExcds */ + *uint_ptr = STATS_GET(mib2.icmpouttimeexcds); + return sizeof(*uint_ptr); + case 18: /* icmpOutParmProbs: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 19: /* icmpOutSrcQuenchs: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 20: /* icmpOutRedirects: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 21: /* icmpOutEchos */ + *uint_ptr = STATS_GET(mib2.icmpoutechos); + return sizeof(*uint_ptr); + case 22: /* icmpOutEchoReps */ + *uint_ptr = STATS_GET(mib2.icmpoutechoreps); + return sizeof(*uint_ptr); + case 23: /* icmpOutTimestamps: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 24: /* icmpOutTimestampReps: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 25: /* icmpOutAddrMasks: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 26: /* icmpOutAddrMaskReps: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_value(): unknown id: %"S32_F"\n", node->oid)); + break; + } + + return 0; +} + + +static const struct snmp_scalar_array_node_def icmp_nodes[] = { + { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 7, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {23, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} +}; + +const struct snmp_scalar_array_node snmp_mib2_icmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(5, icmp_nodes, icmp_get_value, NULL, NULL); + +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_interfaces.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_interfaces.c new file mode 100644 index 0000000000..979b5073ea --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_interfaces.c @@ -0,0 +1,375 @@ +/** + * @file + * Management Information Base II (RFC1213) INTERFACES objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/netif.h" +#include "lwip/stats.h" + +#include + +#if LWIP_SNMP && SNMP_LWIP_MIB2 + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + + +/* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */ + +static s16_t +interfaces_get_value(struct snmp_node_instance* instance, void* value) +{ + if (instance->node->oid == 1) { + s32_t *sint_ptr = (s32_t*)value; + s32_t num_netifs = 0; + + struct netif *netif = netif_list; + while (netif != NULL) { + num_netifs++; + netif = netif->next; + } + + *sint_ptr = num_netifs; + return sizeof(*sint_ptr); + } + + return 0; +} + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range interfaces_Table_oid_ranges[] = { + { 1, 0xff } /* netif->num is u8_t */ +}; + +static const u8_t iftable_ifOutQLen = 0; + +static const u8_t iftable_ifOperStatus_up = 1; +static const u8_t iftable_ifOperStatus_down = 2; + +static const u8_t iftable_ifAdminStatus_up = 1; +static const u8_t iftable_ifAdminStatus_lowerLayerDown = 7; +static const u8_t iftable_ifAdminStatus_down = 2; + +static snmp_err_t +interfaces_Table_get_cell_instance(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance) +{ + u32_t ifIndex; + struct netif *netif; + + LWIP_UNUSED_ARG(column); + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, interfaces_Table_oid_ranges, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get netif index from incoming OID */ + ifIndex = row_oid[0]; + + /* find netif with index */ + netif = netif_list; + while (netif != NULL) { + if (netif_to_num(netif) == ifIndex) { + /* store netif pointer for subsequent operations (get/test/set) */ + cell_instance->reference.ptr = netif; + return SNMP_ERR_NOERROR; + } + netif = netif->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance) +{ + struct netif *netif; + struct snmp_next_oid_state state; + u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; + + LWIP_UNUSED_ARG(column); + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)); + + /* iterate over all possible OIDs to find the next one */ + netif = netif_list; + while (netif != NULL) { + u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; + test_oid[0] = netif_to_num(netif); + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif); + + netif = netif->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* store netif pointer for subsequent operations (get/test/set) */ + cell_instance->reference.ptr = /* (struct netif*) */state.reference; + return SNMP_ERR_NOERROR; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static s16_t +interfaces_Table_get_value(struct snmp_node_instance* instance, void* value) +{ + struct netif *netif = (struct netif*)instance->reference.ptr; + u32_t* value_u32 = (u32_t*)value; + s32_t* value_s32 = (s32_t*)value; + u16_t value_len; + + switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id)) + { + case 1: /* ifIndex */ + *value_s32 = netif_to_num(netif); + value_len = sizeof(*value_s32); + break; + case 2: /* ifDescr */ + value_len = sizeof(netif->name); + MEMCPY(value, netif->name, value_len); + break; + case 3: /* ifType */ + *value_s32 = netif->link_type; + value_len = sizeof(*value_s32); + break; + case 4: /* ifMtu */ + *value_s32 = netif->mtu; + value_len = sizeof(*value_s32); + break; + case 5: /* ifSpeed */ + *value_u32 = netif->link_speed; + value_len = sizeof(*value_u32); + break; + case 6: /* ifPhysAddress */ + value_len = sizeof(netif->hwaddr); + MEMCPY(value, &netif->hwaddr, value_len); + break; + case 7: /* ifAdminStatus */ + if (netif_is_up(netif)) { + *value_s32 = iftable_ifOperStatus_up; + } else { + *value_s32 = iftable_ifOperStatus_down; + } + value_len = sizeof(*value_s32); + break; + case 8: /* ifOperStatus */ + if (netif_is_up(netif)) { + if (netif_is_link_up(netif)) { + *value_s32 = iftable_ifAdminStatus_up; + } else { + *value_s32 = iftable_ifAdminStatus_lowerLayerDown; + } + } else { + *value_s32 = iftable_ifAdminStatus_down; + } + value_len = sizeof(*value_s32); + break; + case 9: /* ifLastChange */ + *value_u32 = netif->ts; + value_len = sizeof(*value_u32); + break; + case 10: /* ifInOctets */ + *value_u32 = netif->mib2_counters.ifinoctets; + value_len = sizeof(*value_u32); + break; + case 11: /* ifInUcastPkts */ + *value_u32 = netif->mib2_counters.ifinucastpkts; + value_len = sizeof(*value_u32); + break; + case 12: /* ifInNUcastPkts */ + *value_u32 = netif->mib2_counters.ifinnucastpkts; + value_len = sizeof(*value_u32); + break; + case 13: /* ifInDiscards */ + *value_u32 = netif->mib2_counters.ifindiscards; + value_len = sizeof(*value_u32); + break; + case 14: /* ifInErrors */ + *value_u32 = netif->mib2_counters.ifinerrors; + value_len = sizeof(*value_u32); + break; + case 15: /* ifInUnkownProtos */ + *value_u32 = netif->mib2_counters.ifinunknownprotos; + value_len = sizeof(*value_u32); + break; + case 16: /* ifOutOctets */ + *value_u32 = netif->mib2_counters.ifoutoctets; + value_len = sizeof(*value_u32); + break; + case 17: /* ifOutUcastPkts */ + *value_u32 = netif->mib2_counters.ifoutucastpkts; + value_len = sizeof(*value_u32); + break; + case 18: /* ifOutNUcastPkts */ + *value_u32 = netif->mib2_counters.ifoutnucastpkts; + value_len = sizeof(*value_u32); + break; + case 19: /* ifOutDiscarts */ + *value_u32 = netif->mib2_counters.ifoutdiscards; + value_len = sizeof(*value_u32); + break; + case 20: /* ifOutErrors */ + *value_u32 = netif->mib2_counters.ifouterrors; + value_len = sizeof(*value_u32); + break; + case 21: /* ifOutQLen */ + *value_u32 = iftable_ifOutQLen; + value_len = sizeof(*value_u32); + break; + /** @note returning zeroDotZero (0.0) no media specific MIB support */ + case 22: /* ifSpecific */ + value_len = snmp_zero_dot_zero.len * sizeof(u32_t); + MEMCPY(value, snmp_zero_dot_zero.id, value_len); + break; + default: + return 0; + } + + return value_len; +} + +#if !SNMP_SAFE_REQUESTS + +static snmp_err_t +interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void *value) +{ + s32_t *sint_ptr = (s32_t*)value; + + /* stack should never call this method for another column, + because all other columns are set to readonly */ + LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); + LWIP_UNUSED_ARG(len); + + if (*sint_ptr == 1 || *sint_ptr == 2) { + return SNMP_ERR_NOERROR; + } + + return SNMP_ERR_WRONGVALUE; +} + +static snmp_err_t +interfaces_Table_set_value(struct snmp_node_instance* instance, u16_t len, void *value) +{ + struct netif *netif = (struct netif*)instance->reference.ptr; + s32_t *sint_ptr = (s32_t*)value; + + /* stack should never call this method for another column, + because all other columns are set to readonly */ + LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); + LWIP_UNUSED_ARG(len); + + if (*sint_ptr == 1) { + netif_set_up(netif); + } else if (*sint_ptr == 2) { + netif_set_down(netif); + } + + return SNMP_ERR_NOERROR; +} + +#endif /* SNMP_SAFE_REQUESTS */ + +static const struct snmp_scalar_node interfaces_Number = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, interfaces_get_value); + +static const struct snmp_table_col_def interfaces_Table_columns[] = { + { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifIndex */ + { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifDescr */ + { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifType */ + { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifMtu */ + { 5, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifSpeed */ + { 6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifPhysAddress */ +#if !SNMP_SAFE_REQUESTS + { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE }, /* ifAdminStatus */ +#else + { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifAdminStatus */ +#endif + { 8, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOperStatus */ + { 9, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifLastChange */ + { 10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInOctets */ + { 11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUcastPkts */ + { 12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInNUcastPkts */ + { 13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInDiscarts */ + { 14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInErrors */ + { 15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUnkownProtos */ + { 16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutOctets */ + { 17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutUcastPkts */ + { 18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutNUcastPkts */ + { 19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutDiscarts */ + { 20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutErrors */ + { 21, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutQLen */ + { 22, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY } /* ifSpecific */ +}; + +#if !SNMP_SAFE_REQUESTS +static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( + 2, interfaces_Table_columns, + interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, + interfaces_Table_get_value, interfaces_Table_set_test, interfaces_Table_set_value); +#else +static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( + 2, interfaces_Table_columns, + interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, + interfaces_Table_get_value, NULL, NULL); +#endif + +/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ +CREATE_LWIP_SYNC_NODE(1, interfaces_Number) +CREATE_LWIP_SYNC_NODE(2, interfaces_Table) + +static const struct snmp_node* const interface_nodes[] = { + &SYNC_NODE_NAME(interfaces_Number).node.node, + &SYNC_NODE_NAME(interfaces_Table).node.node +}; + +const struct snmp_tree_node snmp_mib2_interface_root = SNMP_CREATE_TREE_NODE(2, interface_nodes); + +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_ip.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_ip.c new file mode 100644 index 0000000000..4f05180a39 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_ip.c @@ -0,0 +1,743 @@ +/** + * @file + * Management Information Base II (RFC1213) IP objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/stats.h" +#include "lwip/netif.h" +#include "lwip/ip.h" +#include "lwip/etharp.h" + +#if LWIP_SNMP && SNMP_LWIP_MIB2 + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + +#if LWIP_IPV4 +/* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */ + +static s16_t +ip_get_value(struct snmp_node_instance* instance, void* value) +{ + s32_t* sint_ptr = (s32_t*)value; + u32_t* uint_ptr = (u32_t*)value; + + switch (instance->node->oid) { + case 1: /* ipForwarding */ +#if IP_FORWARD + /* forwarding */ + *sint_ptr = 1; +#else + /* not-forwarding */ + *sint_ptr = 2; +#endif + return sizeof(*sint_ptr); + case 2: /* ipDefaultTTL */ + *sint_ptr = IP_DEFAULT_TTL; + return sizeof(*sint_ptr); + case 3: /* ipInReceives */ + *uint_ptr = STATS_GET(mib2.ipinreceives); + return sizeof(*uint_ptr); + case 4: /* ipInHdrErrors */ + *uint_ptr = STATS_GET(mib2.ipinhdrerrors); + return sizeof(*uint_ptr); + case 5: /* ipInAddrErrors */ + *uint_ptr = STATS_GET(mib2.ipinaddrerrors); + return sizeof(*uint_ptr); + case 6: /* ipForwDatagrams */ + *uint_ptr = STATS_GET(mib2.ipforwdatagrams); + return sizeof(*uint_ptr); + case 7: /* ipInUnknownProtos */ + *uint_ptr = STATS_GET(mib2.ipinunknownprotos); + return sizeof(*uint_ptr); + case 8: /* ipInDiscards */ + *uint_ptr = STATS_GET(mib2.ipindiscards); + return sizeof(*uint_ptr); + case 9: /* ipInDelivers */ + *uint_ptr = STATS_GET(mib2.ipindelivers); + return sizeof(*uint_ptr); + case 10: /* ipOutRequests */ + *uint_ptr = STATS_GET(mib2.ipoutrequests); + return sizeof(*uint_ptr); + case 11: /* ipOutDiscards */ + *uint_ptr = STATS_GET(mib2.ipoutdiscards); + return sizeof(*uint_ptr); + case 12: /* ipOutNoRoutes */ + *uint_ptr = STATS_GET(mib2.ipoutnoroutes); + return sizeof(*uint_ptr); + case 13: /* ipReasmTimeout */ +#if IP_REASSEMBLY + *sint_ptr = IP_REASS_MAXAGE; +#else + *sint_ptr = 0; +#endif + return sizeof(*sint_ptr); + case 14: /* ipReasmReqds */ + *uint_ptr = STATS_GET(mib2.ipreasmreqds); + return sizeof(*uint_ptr); + case 15: /* ipReasmOKs */ + *uint_ptr = STATS_GET(mib2.ipreasmoks); + return sizeof(*uint_ptr); + case 16: /* ipReasmFails */ + *uint_ptr = STATS_GET(mib2.ipreasmfails); + return sizeof(*uint_ptr); + case 17: /* ipFragOKs */ + *uint_ptr = STATS_GET(mib2.ipfragoks); + return sizeof(*uint_ptr); + case 18: /* ipFragFails */ + *uint_ptr = STATS_GET(mib2.ipfragfails); + return sizeof(*uint_ptr); + case 19: /* ipFragCreates */ + *uint_ptr = STATS_GET(mib2.ipfragcreates); + return sizeof(*uint_ptr); + case 23: /* ipRoutingDiscards: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); + break; + } + + return 0; +} + +/** + * Test ip object value before setting. + * + * @param instance node instance + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value from. + * + * @note we allow set if the value matches the hardwired value, + * otherwise return badvalue. + */ +static snmp_err_t +ip_set_test(struct snmp_node_instance* instance, u16_t len, void *value) +{ + snmp_err_t ret = SNMP_ERR_WRONGVALUE; + s32_t *sint_ptr = (s32_t*)value; + + LWIP_UNUSED_ARG(len); + switch (instance->node->oid) { + case 1: /* ipForwarding */ +#if IP_FORWARD + /* forwarding */ + if (*sint_ptr == 1) +#else + /* not-forwarding */ + if (*sint_ptr == 2) +#endif + { + ret = SNMP_ERR_NOERROR; + } + break; + case 2: /* ipDefaultTTL */ + if (*sint_ptr == IP_DEFAULT_TTL) { + ret = SNMP_ERR_NOERROR; + } + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_set_test(): unknown id: %"S32_F"\n", instance->node->oid)); + break; + } + + return ret; +} + +static snmp_err_t +ip_set_value(struct snmp_node_instance* instance, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(instance); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); + /* nothing to do here because in set_test we only accept values being the same as our own stored value -> no need to store anything */ + return SNMP_ERR_NOERROR; +} + +/* --- ipAddrTable --- */ + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range ip_AddrTable_oid_ranges[] = { + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff } /* IP D */ +}; + +static snmp_err_t +ip_AddrTable_get_cell_value_core(struct netif *netif, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) +{ + LWIP_UNUSED_ARG(value_len); + + switch (*column) { + case 1: /* ipAdEntAddr */ + value->u32 = netif_ip4_addr(netif)->addr; + break; + case 2: /* ipAdEntIfIndex */ + value->u32 = netif_to_num(netif); + break; + case 3: /* ipAdEntNetMask */ + value->u32 = netif_ip4_netmask(netif)->addr; + break; + case 4: /* ipAdEntBcastAddr */ + /* lwIP oddity, there's no broadcast + address in the netif we can rely on */ + value->u32 = IPADDR_BROADCAST & 1; + break; + case 5: /* ipAdEntReasmMaxSize */ +#if IP_REASSEMBLY + /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs, + * but only if receiving one fragmented packet at a time. + * The current solution is to calculate for 2 simultaneous packets... + */ + value->u32 = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) * + (PBUF_POOL_BUFSIZE - PBUF_LINK_ENCAPSULATION_HLEN - PBUF_LINK_HLEN - IP_HLEN))); +#else + /** @todo returning MTU would be a bad thing and + returning a wild guess like '576' isn't good either */ + value->u32 = 0; +#endif + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +ip_AddrTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip4_addr_t ip; + struct netif *netif; + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, ip_AddrTable_oid_ranges, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get IP from incoming OID */ + snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ + + /* find netif with requested ip */ + netif = netif_list; + while (netif != NULL) { + if (ip4_addr_cmp(&ip, netif_ip4_addr(netif))) { + /* fill in object properties */ + return ip_AddrTable_get_cell_value_core(netif, column, value, value_len); + } + + netif = netif->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +ip_AddrTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct netif *netif; + struct snmp_next_oid_state state; + u32_t result_temp[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)); + + /* iterate over all possible OIDs to find the next one */ + netif = netif_list; + while (netif != NULL) { + u32_t test_oid[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; + snmp_ip4_to_oid(netif_ip4_addr(netif), &test_oid[0]); + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges), netif); + + netif = netif->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return ip_AddrTable_get_cell_value_core((struct netif*)state.reference, column, value, value_len); + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +/* --- ipRouteTable --- */ + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range ip_RouteTable_oid_ranges[] = { + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff }, /* IP D */ +}; + +static snmp_err_t +ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) +{ + switch (*column) { + case 1: /* ipRouteDest */ + if (default_route) { + /* default rte has 0.0.0.0 dest */ + value->u32 = IP4_ADDR_ANY4->addr; + } else { + /* netifs have netaddress dest */ + ip4_addr_t tmp; + ip4_addr_get_network(&tmp, netif_ip4_addr(netif), netif_ip4_netmask(netif)); + value->u32 = tmp.addr; + } + break; + case 2: /* ipRouteIfIndex */ + value->u32 = netif_to_num(netif); + break; + case 3: /* ipRouteMetric1 */ + if (default_route) { + value->s32 = 1; /* default */ + } else { + value->s32 = 0; /* normal */ + } + break; + case 4: /* ipRouteMetric2 */ + case 5: /* ipRouteMetric3 */ + case 6: /* ipRouteMetric4 */ + value->s32 = -1; /* none */ + break; + case 7: /* ipRouteNextHop */ + if (default_route) { + /* default rte: gateway */ + value->u32 = netif_ip4_gw(netif)->addr; + } else { + /* other rtes: netif ip_addr */ + value->u32 = netif_ip4_addr(netif)->addr; + } + break; + case 8: /* ipRouteType */ + if (default_route) { + /* default rte is indirect */ + value->u32 = 4; /* indirect */ + } else { + /* other rtes are direct */ + value->u32 = 3; /* direct */ + } + break; + case 9: /* ipRouteProto */ + /* locally defined routes */ + value->u32 = 2; /* local */ + break; + case 10: /* ipRouteAge */ + /* @todo (sysuptime - timestamp last change) / 100 */ + value->u32 = 0; + break; + case 11: /* ipRouteMask */ + if (default_route) { + /* default rte use 0.0.0.0 mask */ + value->u32 = IP4_ADDR_ANY4->addr; + } else { + /* other rtes use netmask */ + value->u32 = netif_ip4_netmask(netif)->addr; + } + break; + case 12: /* ipRouteMetric5 */ + value->s32 = -1; /* none */ + break; + case 13: /* ipRouteInfo */ + value->const_ptr = snmp_zero_dot_zero.id; + *value_len = snmp_zero_dot_zero.len * sizeof(u32_t); + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +ip_RouteTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip4_addr_t test_ip; + struct netif *netif; + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, ip_RouteTable_oid_ranges, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get IP and port from incoming OID */ + snmp_oid_to_ip4(&row_oid[0], &test_ip); /* we know it succeeds because of oid_in_range check above */ + + /* default route is on default netif */ + if (ip4_addr_isany_val(test_ip) && (netif_default != NULL)) { + /* fill in object properties */ + return ip_RouteTable_get_cell_value_core(netif_default, 1, column, value, value_len); + } + + /* find netif with requested route */ + netif = netif_list; + while (netif != NULL) { + ip4_addr_t dst; + ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); + + if (ip4_addr_cmp(&dst, &test_ip)) { + /* fill in object properties */ + return ip_RouteTable_get_cell_value_core(netif, 0, column, value, value_len); + } + + netif = netif->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +ip_RouteTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct netif *netif; + struct snmp_next_oid_state state; + u32_t result_temp[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; + u32_t test_oid[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)); + + /* check default route */ + if (netif_default != NULL) { + snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[0]); + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif_default); + } + + /* iterate over all possible OIDs to find the next one */ + netif = netif_list; + while (netif != NULL) { + ip4_addr_t dst; + ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); + + /* check generated OID: is it a candidate for the next one? */ + if (!ip4_addr_isany_val(dst)) { + snmp_ip4_to_oid(&dst, &test_oid[0]); + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif); + } + + netif = netif->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + ip4_addr_t dst; + snmp_oid_to_ip4(&result_temp[0], &dst); + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return ip_RouteTable_get_cell_value_core((struct netif*)state.reference, ip4_addr_isany_val(dst), column, value, value_len); + } else { + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; + } +} + +#if LWIP_ARP && LWIP_IPV4 +/* --- ipNetToMediaTable --- */ + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range ip_NetToMediaTable_oid_ranges[] = { + { 1, 0xff }, /* IfIndex */ + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff } /* IP D */ +}; + +static snmp_err_t +ip_NetToMediaTable_get_cell_value_core(u8_t arp_table_index, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) +{ + ip4_addr_t *ip; + struct netif *netif; + struct eth_addr *ethaddr; + + etharp_get_entry(arp_table_index, &ip, &netif, ðaddr); + + /* value */ + switch (*column) { + case 1: /* atIfIndex / ipNetToMediaIfIndex */ + value->u32 = netif_to_num(netif); + break; + case 2: /* atPhysAddress / ipNetToMediaPhysAddress */ + value->ptr = ethaddr; + *value_len = sizeof(*ethaddr); + break; + case 3: /* atNetAddress / ipNetToMediaNetAddress */ + value->u32 = ip->addr; + break; + case 4: /* ipNetToMediaType */ + value->u32 = 3; /* dynamic*/ + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +ip_NetToMediaTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip4_addr_t ip_in; + u8_t netif_index; + u8_t i; + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, ip_NetToMediaTable_oid_ranges, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get IP from incoming OID */ + netif_index = (u8_t)row_oid[0]; + snmp_oid_to_ip4(&row_oid[1], &ip_in); /* we know it succeeds because of oid_in_range check above */ + + /* find requested entry */ + for (i=0; iid, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)); + + /* iterate over all possible OIDs to find the next one */ + for (i=0; i + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_scalar.h" + +#if LWIP_SNMP && SNMP_LWIP_MIB2 + +#define MIB2_AUTH_TRAPS_ENABLED 1 +#define MIB2_AUTH_TRAPS_DISABLED 2 + +/* --- snmp .1.3.6.1.2.1.11 ----------------------------------------------------- */ +static s16_t +snmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + switch (node->oid) { + case 1: /* snmpInPkts */ + *uint_ptr = snmp_stats.inpkts; + break; + case 2: /* snmpOutPkts */ + *uint_ptr = snmp_stats.outpkts; + break; + case 3: /* snmpInBadVersions */ + *uint_ptr = snmp_stats.inbadversions; + break; + case 4: /* snmpInBadCommunityNames */ + *uint_ptr = snmp_stats.inbadcommunitynames; + break; + case 5: /* snmpInBadCommunityUses */ + *uint_ptr = snmp_stats.inbadcommunityuses; + break; + case 6: /* snmpInASNParseErrs */ + *uint_ptr = snmp_stats.inasnparseerrs; + break; + case 8: /* snmpInTooBigs */ + *uint_ptr = snmp_stats.intoobigs; + break; + case 9: /* snmpInNoSuchNames */ + *uint_ptr = snmp_stats.innosuchnames; + break; + case 10: /* snmpInBadValues */ + *uint_ptr = snmp_stats.inbadvalues; + break; + case 11: /* snmpInReadOnlys */ + *uint_ptr = snmp_stats.inreadonlys; + break; + case 12: /* snmpInGenErrs */ + *uint_ptr = snmp_stats.ingenerrs; + break; + case 13: /* snmpInTotalReqVars */ + *uint_ptr = snmp_stats.intotalreqvars; + break; + case 14: /* snmpInTotalSetVars */ + *uint_ptr = snmp_stats.intotalsetvars; + break; + case 15: /* snmpInGetRequests */ + *uint_ptr = snmp_stats.ingetrequests; + break; + case 16: /* snmpInGetNexts */ + *uint_ptr = snmp_stats.ingetnexts; + break; + case 17: /* snmpInSetRequests */ + *uint_ptr = snmp_stats.insetrequests; + break; + case 18: /* snmpInGetResponses */ + *uint_ptr = snmp_stats.ingetresponses; + break; + case 19: /* snmpInTraps */ + *uint_ptr = snmp_stats.intraps; + break; + case 20: /* snmpOutTooBigs */ + *uint_ptr = snmp_stats.outtoobigs; + break; + case 21: /* snmpOutNoSuchNames */ + *uint_ptr = snmp_stats.outnosuchnames; + break; + case 22: /* snmpOutBadValues */ + *uint_ptr = snmp_stats.outbadvalues; + break; + case 24: /* snmpOutGenErrs */ + *uint_ptr = snmp_stats.outgenerrs; + break; + case 25: /* snmpOutGetRequests */ + *uint_ptr = snmp_stats.outgetrequests; + break; + case 26: /* snmpOutGetNexts */ + *uint_ptr = snmp_stats.outgetnexts; + break; + case 27: /* snmpOutSetRequests */ + *uint_ptr = snmp_stats.outsetrequests; + break; + case 28: /* snmpOutGetResponses */ + *uint_ptr = snmp_stats.outgetresponses; + break; + case 29: /* snmpOutTraps */ + *uint_ptr = snmp_stats.outtraps; + break; + case 30: /* snmpEnableAuthenTraps */ + if (snmp_get_auth_traps_enabled() == SNMP_AUTH_TRAPS_DISABLED) { + *uint_ptr = MIB2_AUTH_TRAPS_DISABLED; + } else { + *uint_ptr = MIB2_AUTH_TRAPS_ENABLED; + } + break; + case 31: /* snmpSilentDrops */ + *uint_ptr = 0; /* not supported */ + break; + case 32: /* snmpProxyDrops */ + *uint_ptr = 0; /* not supported */ + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_value(): unknown id: %"S32_F"\n", node->oid)); + return 0; + } + + return sizeof(*uint_ptr); +} + +static snmp_err_t +snmp_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) +{ + snmp_err_t ret = SNMP_ERR_WRONGVALUE; + LWIP_UNUSED_ARG(len); + + if (node->oid == 30) { + /* snmpEnableAuthenTraps */ + s32_t *sint_ptr = (s32_t*)value; + + /* we should have writable non-volatile mem here */ + if ((*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) || (*sint_ptr == MIB2_AUTH_TRAPS_ENABLED)) { + ret = SNMP_ERR_NOERROR; + } + } + return ret; +} + +static snmp_err_t +snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(len); + + if (node->oid == 30) { + /* snmpEnableAuthenTraps */ + s32_t *sint_ptr = (s32_t*)value; + if (*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) { + snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_DISABLED); + } else { + snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_ENABLED); + } + } + + return SNMP_ERR_NOERROR; +} + +/* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */ +static const struct snmp_scalar_array_node_def snmp_nodes[] = { + { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInPkts */ + { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutPkts */ + { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadVersions */ + { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityNames */ + { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityUses */ + { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInASNParseErrs */ + { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTooBigs */ + { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInNoSuchNames */ + {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadValues */ + {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInReadOnlys */ + {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGenErrs */ + {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalReqVars */ + {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalSetVars */ + {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetRequests */ + {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetNexts */ + {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInSetRequests */ + {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetResponses */ + {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTraps */ + {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTooBigs */ + {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutNoSuchNames */ + {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutBadValues */ + {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGenErrs */ + {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetRequests */ + {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetNexts */ + {27, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutSetRequests */ + {28, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetResponses */ + {29, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTraps */ + {30, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE}, /* snmpEnableAuthenTraps */ + {31, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpSilentDrops */ + {32, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} /* snmpProxyDrops */ +}; + +const struct snmp_scalar_array_node snmp_mib2_snmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(11, snmp_nodes, snmp_get_value, snmp_set_test, snmp_set_value); + +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_system.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_system.c new file mode 100644 index 0000000000..90e57805d2 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_system.c @@ -0,0 +1,377 @@ +/** + * @file + * Management Information Base II (RFC1213) SYSTEM objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/sys.h" + +#include + +#if LWIP_SNMP && SNMP_LWIP_MIB2 + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + +/* --- system .1.3.6.1.2.1.1 ----------------------------------------------------- */ + +/** mib-2.system.sysDescr */ +static const u8_t sysdescr_default[] = SNMP_LWIP_MIB2_SYSDESC; +static const u8_t* sysdescr = sysdescr_default; +static const u16_t* sysdescr_len = NULL; /* use strlen for determining len */ + +/** mib-2.system.sysContact */ +static const u8_t syscontact_default[] = SNMP_LWIP_MIB2_SYSCONTACT; +static const u8_t* syscontact = syscontact_default; +static const u16_t* syscontact_len = NULL; /* use strlen for determining len */ +static u8_t* syscontact_wr = NULL; /* if writable, points to the same buffer as syscontact (required for correct constness) */ +static u16_t* syscontact_wr_len = NULL; /* if writable, points to the same buffer as syscontact_len (required for correct constness) */ +static u16_t syscontact_bufsize = 0; /* 0=not writable */ + +/** mib-2.system.sysName */ +static const u8_t sysname_default[] = SNMP_LWIP_MIB2_SYSNAME; +static const u8_t* sysname = sysname_default; +static const u16_t* sysname_len = NULL; /* use strlen for determining len */ +static u8_t* sysname_wr = NULL; /* if writable, points to the same buffer as sysname (required for correct constness) */ +static u16_t* sysname_wr_len = NULL; /* if writable, points to the same buffer as sysname_len (required for correct constness) */ +static u16_t sysname_bufsize = 0; /* 0=not writable */ + +/** mib-2.system.sysLocation */ +static const u8_t syslocation_default[] = SNMP_LWIP_MIB2_SYSLOCATION; +static const u8_t* syslocation = syslocation_default; +static const u16_t* syslocation_len = NULL; /* use strlen for determining len */ +static u8_t* syslocation_wr = NULL; /* if writable, points to the same buffer as syslocation (required for correct constness) */ +static u16_t* syslocation_wr_len = NULL; /* if writable, points to the same buffer as syslocation_len (required for correct constness) */ +static u16_t syslocation_bufsize = 0; /* 0=not writable */ + +/** + * @ingroup snmp_mib2 + * Initializes sysDescr pointers. + * + * @param str if non-NULL then copy str pointer + * @param len points to string length, excluding zero terminator + */ +void +snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len) +{ + if (str != NULL) { + sysdescr = str; + sysdescr_len = len; + } +} + +/** + * @ingroup snmp_mib2 + * Initializes sysContact pointers + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator. + * if set to NULL it is assumed that ocstr is NULL-terminated. + * @param bufsize size of the buffer in bytes. + * (this is required because the buffer can be overwritten by snmp-set) + * if ocstrlen is NULL buffer needs space for terminating 0 byte. + * otherwise complete buffer is used for string. + * if bufsize is set to 0, the value is regarded as read-only. + */ +void +snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) +{ + if (ocstr != NULL) { + syscontact = ocstr; + syscontact_wr = ocstr; + syscontact_len = ocstrlen; + syscontact_wr_len = ocstrlen; + syscontact_bufsize = bufsize; + } +} + +/** + * @ingroup snmp_mib2 + * see \ref snmp_mib2_set_syscontact but set pointer to readonly memory + */ +void +snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen) +{ + if (ocstr != NULL) { + syscontact = ocstr; + syscontact_len = ocstrlen; + syscontact_wr = NULL; + syscontact_wr_len = NULL; + syscontact_bufsize = 0; + } +} + + +/** + * @ingroup snmp_mib2 + * Initializes sysName pointers + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator. + * if set to NULL it is assumed that ocstr is NULL-terminated. + * @param bufsize size of the buffer in bytes. + * (this is required because the buffer can be overwritten by snmp-set) + * if ocstrlen is NULL buffer needs space for terminating 0 byte. + * otherwise complete buffer is used for string. + * if bufsize is set to 0, the value is regarded as read-only. + */ +void +snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) +{ + if (ocstr != NULL) { + sysname = ocstr; + sysname_wr = ocstr; + sysname_len = ocstrlen; + sysname_wr_len = ocstrlen; + sysname_bufsize = bufsize; + } +} + +/** + * @ingroup snmp_mib2 + * see \ref snmp_mib2_set_sysname but set pointer to readonly memory + */ +void +snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen) +{ + if (ocstr != NULL) { + sysname = ocstr; + sysname_len = ocstrlen; + sysname_wr = NULL; + sysname_wr_len = NULL; + sysname_bufsize = 0; + } +} + +/** + * @ingroup snmp_mib2 + * Initializes sysLocation pointers + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator. + * if set to NULL it is assumed that ocstr is NULL-terminated. + * @param bufsize size of the buffer in bytes. + * (this is required because the buffer can be overwritten by snmp-set) + * if ocstrlen is NULL buffer needs space for terminating 0 byte. + * otherwise complete buffer is used for string. + * if bufsize is set to 0, the value is regarded as read-only. + */ +void +snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) +{ + if (ocstr != NULL) { + syslocation = ocstr; + syslocation_wr = ocstr; + syslocation_len = ocstrlen; + syslocation_wr_len = ocstrlen; + syslocation_bufsize = bufsize; + } +} + +/** + * @ingroup snmp_mib2 + * see \ref snmp_mib2_set_syslocation but set pointer to readonly memory + */ +void +snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen) +{ + if (ocstr != NULL) { + syslocation = ocstr; + syslocation_len = ocstrlen; + syslocation_wr = NULL; + syslocation_wr_len = NULL; + syslocation_bufsize = 0; + } +} + + +static s16_t +system_get_value(const struct snmp_scalar_array_node_def *node, void *value) +{ + const u8_t* var = NULL; + const s16_t* var_len; + u16_t result; + + switch (node->oid) { + case 1: /* sysDescr */ + var = sysdescr; + var_len = (const s16_t*)sysdescr_len; + break; + case 2: /* sysObjectID */ + { + const struct snmp_obj_id* dev_enterprise_oid = snmp_get_device_enterprise_oid(); + MEMCPY(value, dev_enterprise_oid->id, dev_enterprise_oid->len * sizeof(u32_t)); + return dev_enterprise_oid->len * sizeof(u32_t); + } + case 3: /* sysUpTime */ + MIB2_COPY_SYSUPTIME_TO((u32_t*)value); + return sizeof(u32_t); + case 4: /* sysContact */ + var = syscontact; + var_len = (const s16_t*)syscontact_len; + break; + case 5: /* sysName */ + var = sysname; + var_len = (const s16_t*)sysname_len; + break; + case 6: /* sysLocation */ + var = syslocation; + var_len = (const s16_t*)syslocation_len; + break; + case 7: /* sysServices */ + *(s32_t*)value = SNMP_SYSSERVICES; + return sizeof(s32_t); + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_value(): unknown id: %"S32_F"\n", node->oid)); + return 0; + } + + /* handle string values (OID 1,4,5 and 6) */ + LWIP_ASSERT("", (value != NULL)); + if (var_len == NULL) { + result = (s16_t)strlen((const char*)var); + } else { + result = *var_len; + } + MEMCPY(value, var, result); + return result; +} + +static snmp_err_t +system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) +{ + snmp_err_t ret = SNMP_ERR_WRONGVALUE; + const u16_t* var_bufsize = NULL; + const u16_t* var_wr_len; + + LWIP_UNUSED_ARG(value); + + switch (node->oid) { + case 4: /* sysContact */ + var_bufsize = &syscontact_bufsize; + var_wr_len = syscontact_wr_len; + break; + case 5: /* sysName */ + var_bufsize = &sysname_bufsize; + var_wr_len = sysname_wr_len; + break; + case 6: /* sysLocation */ + var_bufsize = &syslocation_bufsize; + var_wr_len = syslocation_wr_len; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_test(): unknown id: %"S32_F"\n", node->oid)); + return ret; + } + + /* check if value is writable at all */ + if (*var_bufsize > 0) { + if (var_wr_len == NULL) { + /* we have to take the terminating 0 into account */ + if (len < *var_bufsize) { + ret = SNMP_ERR_NOERROR; + } + } else { + if (len <= *var_bufsize) { + ret = SNMP_ERR_NOERROR; + } + } + } else { + ret = SNMP_ERR_NOTWRITABLE; + } + + return ret; +} + +static snmp_err_t +system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) +{ + u8_t* var_wr = NULL; + u16_t* var_wr_len; + + switch (node->oid) { + case 4: /* sysContact */ + var_wr = syscontact_wr; + var_wr_len = syscontact_wr_len; + break; + case 5: /* sysName */ + var_wr = sysname_wr; + var_wr_len = sysname_wr_len; + break; + case 6: /* sysLocation */ + var_wr = syslocation_wr; + var_wr_len = syslocation_wr_len; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_value(): unknown id: %"S32_F"\n", node->oid)); + return SNMP_ERR_GENERROR; + } + + /* no need to check size of target buffer, this was already done in set_test method */ + LWIP_ASSERT("", var_wr != NULL); + MEMCPY(var_wr, value, len); + + if (var_wr_len == NULL) { + /* add terminating 0 */ + var_wr[len] = 0; + } else { + *var_wr_len = len; + } + + return SNMP_ERR_NOERROR; +} + +static const struct snmp_scalar_array_node_def system_nodes[] = { + {1, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysDescr */ + {2, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysObjectID */ + {3, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysUpTime */ + {4, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysContact */ + {5, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysName */ + {6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysLocation */ + {7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY} /* sysServices */ +}; + +const struct snmp_scalar_array_node snmp_mib2_system_node = SNMP_SCALAR_CREATE_ARRAY_NODE(1, system_nodes, system_get_value, system_set_test, system_set_value); + +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_tcp.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_tcp.c new file mode 100644 index 0000000000..21f6965662 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_tcp.c @@ -0,0 +1,594 @@ +/** + * @file + * Management Information Base II (RFC1213) TCP objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/stats.h" + +#include + +#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + +/* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */ + +static s16_t +tcp_get_value(struct snmp_node_instance* instance, void* value) +{ + u32_t *uint_ptr = (u32_t*)value; + s32_t *sint_ptr = (s32_t*)value; + + switch (instance->node->oid) { + case 1: /* tcpRtoAlgorithm, vanj(4) */ + *sint_ptr = 4; + return sizeof(*sint_ptr); + case 2: /* tcpRtoMin */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 1000; + return sizeof(*sint_ptr); + case 3: /* tcpRtoMax */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 60000; + return sizeof(*sint_ptr); + case 4: /* tcpMaxConn */ + *sint_ptr = MEMP_NUM_TCP_PCB; + return sizeof(*sint_ptr); + case 5: /* tcpActiveOpens */ + *uint_ptr = STATS_GET(mib2.tcpactiveopens); + return sizeof(*uint_ptr); + case 6: /* tcpPassiveOpens */ + *uint_ptr = STATS_GET(mib2.tcppassiveopens); + return sizeof(*uint_ptr); + case 7: /* tcpAttemptFails */ + *uint_ptr = STATS_GET(mib2.tcpattemptfails); + return sizeof(*uint_ptr); + case 8: /* tcpEstabResets */ + *uint_ptr = STATS_GET(mib2.tcpestabresets); + return sizeof(*uint_ptr); + case 9: /* tcpCurrEstab */ + { + u16_t tcpcurrestab = 0; + struct tcp_pcb *pcb = tcp_active_pcbs; + while (pcb != NULL) { + if ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT)) { + tcpcurrestab++; + } + pcb = pcb->next; + } + *uint_ptr = tcpcurrestab; + } + return sizeof(*uint_ptr); + case 10: /* tcpInSegs */ + *uint_ptr = STATS_GET(mib2.tcpinsegs); + return sizeof(*uint_ptr); + case 11: /* tcpOutSegs */ + *uint_ptr = STATS_GET(mib2.tcpoutsegs); + return sizeof(*uint_ptr); + case 12: /* tcpRetransSegs */ + *uint_ptr = STATS_GET(mib2.tcpretranssegs); + return sizeof(*uint_ptr); + case 14: /* tcpInErrs */ + *uint_ptr = STATS_GET(mib2.tcpinerrs); + return sizeof(*uint_ptr); + case 15: /* tcpOutRsts */ + *uint_ptr = STATS_GET(mib2.tcpoutrsts); + return sizeof(*uint_ptr); + case 17: /* tcpHCInSegs */ + memset(value, 0, 2*sizeof(u32_t)); /* not supported */ + return 2*sizeof(u32_t); + case 18: /* tcpHCOutSegs */ + memset(value, 0, 2*sizeof(u32_t)); /* not supported */ + return 2*sizeof(u32_t); + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); + break; + } + + return 0; +} + +/* --- tcpConnTable --- */ + +#if LWIP_IPV4 + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = { + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff }, /* IP D */ + { 0, 0xffff }, /* Port */ + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff }, /* IP D */ + { 0, 0xffff } /* Port */ +}; + +static snmp_err_t +tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) +{ + LWIP_UNUSED_ARG(value_len); + + /* value */ + switch (*column) { + case 1: /* tcpConnState */ + value->u32 = pcb->state + 1; + break; + case 2: /* tcpConnLocalAddress */ + value->u32 = ip_2_ip4(&pcb->local_ip)->addr; + break; + case 3: /* tcpConnLocalPort */ + value->u32 = pcb->local_port; + break; + case 4: /* tcpConnRemAddress */ + if (pcb->state == LISTEN) { + value->u32 = IP4_ADDR_ANY4->addr; + } else { + value->u32 = ip_2_ip4(&pcb->remote_ip)->addr; + } + break; + case 5: /* tcpConnRemPort */ + if (pcb->state == LISTEN) { + value->u32 = 0; + } else { + value->u32 = pcb->remote_port; + } + break; + default: + LWIP_ASSERT("invalid id", 0); + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +tcp_ConnTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + u8_t i; + ip4_addr_t local_ip; + ip4_addr_t remote_ip; + u16_t local_port; + u16_t remote_port; + struct tcp_pcb *pcb; + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, tcp_ConnTable_oid_ranges, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get IPs and ports from incoming OID */ + snmp_oid_to_ip4(&row_oid[0], &local_ip); /* we know it succeeds because of oid_in_range check above */ + local_port = (u16_t)row_oid[4]; + snmp_oid_to_ip4(&row_oid[5], &remote_ip); /* we know it succeeds because of oid_in_range check above */ + remote_port = (u16_t)row_oid[9]; + + /* find tcp_pcb with requested ips and ports */ + for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { + pcb = *tcp_pcb_lists[i]; + + while (pcb != NULL) { + /* do local IP and local port match? */ + if (IP_IS_V4_VAL(pcb->local_ip) && + ip4_addr_cmp(&local_ip, ip_2_ip4(&pcb->local_ip)) && (local_port == pcb->local_port)) { + + /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ + if (pcb->state == LISTEN) { + if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY4) && (remote_port == 0)) { + /* fill in object properties */ + return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); + } + } else { + if (IP_IS_V4_VAL(pcb->remote_ip) && + ip4_addr_cmp(&remote_ip, ip_2_ip4(&pcb->remote_ip)) && (remote_port == pcb->remote_port)) { + /* fill in object properties */ + return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); + } + } + } + + pcb = pcb->next; + } + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + u8_t i; + struct tcp_pcb *pcb; + struct snmp_next_oid_state state; + u32_t result_temp[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)); + + /* iterate over all possible OIDs to find the next one */ + for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { + pcb = *tcp_pcb_lists[i]; + while (pcb != NULL) { + u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; + + if (IP_IS_V4_VAL(pcb->local_ip)) { + snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); + test_oid[4] = pcb->local_port; + + /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ + if (pcb->state == LISTEN) { + snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[5]); + test_oid[9] = 0; + } else { + if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */ + continue; + } + snmp_ip4_to_oid(ip_2_ip4(&pcb->remote_ip), &test_oid[5]); + test_oid[9] = pcb->remote_port; + } + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb); + } + + pcb = pcb->next; + } + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return tcp_ConnTable_get_cell_value_core((struct tcp_pcb*)state.reference, column, value, value_len); + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +#endif /* LWIP_IPV4 */ + +/* --- tcpConnectionTable --- */ + +static snmp_err_t +tcp_ConnectionTable_get_cell_value_core(const u32_t* column, struct tcp_pcb *pcb, union snmp_variant_value* value) +{ + /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ + switch (*column) { + case 7: /* tcpConnectionState */ + value->u32 = pcb->state + 1; + break; + case 8: /* tcpConnectionProcess */ + value->u32 = 0; /* not supported */ + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip_addr_t local_ip, remote_ip; + u16_t local_port, remote_port; + struct tcp_pcb *pcb; + u8_t idx = 0; + u8_t i; + struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; + + LWIP_UNUSED_ARG(value_len); + + /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ + idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); + if (idx == 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ + idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); + if (idx == 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* find tcp_pcb with requested ip and port*/ + for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { + pcb = *tcp_pcb_nonlisten_lists[i]; + + while (pcb != NULL) { + if (ip_addr_cmp(&local_ip, &pcb->local_ip) && + (local_port == pcb->local_port) && + ip_addr_cmp(&remote_ip, &pcb->remote_ip) && + (remote_port == pcb->remote_port)) { + /* fill in object properties */ + return tcp_ConnectionTable_get_cell_value_core(column, pcb, value); + } + pcb = pcb->next; + } + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct tcp_pcb *pcb; + struct snmp_next_oid_state state; + /* 1x tcpConnectionLocalAddressType + 1x OID len + 16x tcpConnectionLocalAddress + 1x tcpConnectionLocalPort + * 1x tcpConnectionRemAddressType + 1x OID len + 16x tcpConnectionRemAddress + 1x tcpConnectionRemPort */ + u32_t result_temp[38]; + u8_t i; + struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; + + LWIP_UNUSED_ARG(value_len); + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); + + /* iterate over all possible OIDs to find the next one */ + for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { + pcb = *tcp_pcb_nonlisten_lists[i]; + + while (pcb != NULL) { + u8_t idx = 0; + u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; + + /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ + idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); + + /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ + idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, idx, pcb); + + pcb = pcb->next; + } + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return tcp_ConnectionTable_get_cell_value_core(column, (struct tcp_pcb*)state.reference, value); + } else { + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; + } +} + +/* --- tcpListenerTable --- */ + +static snmp_err_t +tcp_ListenerTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) +{ + /* all items except tcpListenerProcess are declared as not-accessible */ + switch (*column) { + case 4: /* tcpListenerProcess */ + value->u32 = 0; /* not supported */ + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +tcp_ListenerTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip_addr_t local_ip; + u16_t local_port; + struct tcp_pcb_listen *pcb; + u8_t idx = 0; + + LWIP_UNUSED_ARG(value_len); + + /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ + idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); + if (idx == 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* find tcp_pcb with requested ip and port*/ + pcb = tcp_listen_pcbs.listen_pcbs; + while (pcb != NULL) { + if (ip_addr_cmp(&local_ip, &pcb->local_ip) && + (local_port == pcb->local_port)) { + /* fill in object properties */ + return tcp_ListenerTable_get_cell_value_core(column, value); + } + pcb = pcb->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +tcp_ListenerTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct tcp_pcb_listen *pcb; + struct snmp_next_oid_state state; + /* 1x tcpListenerLocalAddressType + 1x OID len + 16x tcpListenerLocalAddress + 1x tcpListenerLocalPort */ + u32_t result_temp[19]; + + LWIP_UNUSED_ARG(value_len); + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); + + /* iterate over all possible OIDs to find the next one */ + pcb = tcp_listen_pcbs.listen_pcbs; + while (pcb != NULL) { + u8_t idx = 0; + u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; + + /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ + idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, idx, NULL); + + pcb = pcb->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return tcp_ListenerTable_get_cell_value_core(column, value); + } else { + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; + } +} + +static const struct snmp_scalar_node tcp_RtoAlgorithm = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); +static const struct snmp_scalar_node tcp_RtoMin = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); +static const struct snmp_scalar_node tcp_RtoMax = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); +static const struct snmp_scalar_node tcp_MaxConn = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); +static const struct snmp_scalar_node tcp_ActiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_PassiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_AttemptFails = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_EstabResets = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_CurrEstab = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_GAUGE, tcp_get_value); +static const struct snmp_scalar_node tcp_InSegs = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_OutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_RetransSegs = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_InErrs = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_OutRsts = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_HCInSegs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); +static const struct snmp_scalar_node tcp_HCOutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); + +#if LWIP_IPV4 +static const struct snmp_table_simple_col_def tcp_ConnTable_columns[] = { + { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnState */ + { 2, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalAddress */ + { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalPort */ + { 4, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnRemAddress */ + { 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnRemPort */ +}; + +static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIMPLE(13, tcp_ConnTable_columns, tcp_ConnTable_get_cell_value, tcp_ConnTable_get_next_cell_instance_and_value); +#endif /* LWIP_IPV4 */ + +static const struct snmp_table_simple_col_def tcp_ConnectionTable_columns[] = { + /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ + { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */ + { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */ +}; + +static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREATE_SIMPLE(19, tcp_ConnectionTable_columns, tcp_ConnectionTable_get_cell_value, tcp_ConnectionTable_get_next_cell_instance_and_value); + + +static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = { + /* all items except tcpListenerProcess are declared as not-accessible */ + { 4, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpListenerProcess */ +}; + +static const struct snmp_table_simple_node tcp_ListenerTable = SNMP_TABLE_CREATE_SIMPLE(20, tcp_ListenerTable_columns, tcp_ListenerTable_get_cell_value, tcp_ListenerTable_get_next_cell_instance_and_value); + +/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ +CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm) +CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin) +CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax) +CREATE_LWIP_SYNC_NODE( 4, tcp_MaxConn) +CREATE_LWIP_SYNC_NODE( 5, tcp_ActiveOpens) +CREATE_LWIP_SYNC_NODE( 6, tcp_PassiveOpens) +CREATE_LWIP_SYNC_NODE( 7, tcp_AttemptFails) +CREATE_LWIP_SYNC_NODE( 8, tcp_EstabResets) +CREATE_LWIP_SYNC_NODE( 9, tcp_CurrEstab) +CREATE_LWIP_SYNC_NODE(10, tcp_InSegs) +CREATE_LWIP_SYNC_NODE(11, tcp_OutSegs) +CREATE_LWIP_SYNC_NODE(12, tcp_RetransSegs) +#if LWIP_IPV4 +CREATE_LWIP_SYNC_NODE(13, tcp_ConnTable) +#endif /* LWIP_IPV4 */ +CREATE_LWIP_SYNC_NODE(14, tcp_InErrs) +CREATE_LWIP_SYNC_NODE(15, tcp_OutRsts) +CREATE_LWIP_SYNC_NODE(17, tcp_HCInSegs) +CREATE_LWIP_SYNC_NODE(18, tcp_HCOutSegs) +CREATE_LWIP_SYNC_NODE(19, tcp_ConnectionTable) +CREATE_LWIP_SYNC_NODE(20, tcp_ListenerTable) + +static const struct snmp_node* const tcp_nodes[] = { + &SYNC_NODE_NAME(tcp_RtoAlgorithm).node.node, + &SYNC_NODE_NAME(tcp_RtoMin).node.node, + &SYNC_NODE_NAME(tcp_RtoMax).node.node, + &SYNC_NODE_NAME(tcp_MaxConn).node.node, + &SYNC_NODE_NAME(tcp_ActiveOpens).node.node, + &SYNC_NODE_NAME(tcp_PassiveOpens).node.node, + &SYNC_NODE_NAME(tcp_AttemptFails).node.node, + &SYNC_NODE_NAME(tcp_EstabResets).node.node, + &SYNC_NODE_NAME(tcp_CurrEstab).node.node, + &SYNC_NODE_NAME(tcp_InSegs).node.node, + &SYNC_NODE_NAME(tcp_OutSegs).node.node, + &SYNC_NODE_NAME(tcp_RetransSegs).node.node, +#if LWIP_IPV4 + &SYNC_NODE_NAME(tcp_ConnTable).node.node, +#endif /* LWIP_IPV4 */ + &SYNC_NODE_NAME(tcp_InErrs).node.node, + &SYNC_NODE_NAME(tcp_OutRsts).node.node, + &SYNC_NODE_NAME(tcp_HCInSegs).node.node, + &SYNC_NODE_NAME(tcp_HCOutSegs).node.node, + &SYNC_NODE_NAME(tcp_ConnectionTable).node.node, + &SYNC_NODE_NAME(tcp_ListenerTable).node.node +}; + +const struct snmp_tree_node snmp_mib2_tcp_root = SNMP_CREATE_TREE_NODE(6, tcp_nodes); +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_udp.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_udp.c new file mode 100644 index 0000000000..6a983df20b --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_mib2_udp.c @@ -0,0 +1,357 @@ +/** + * @file + * Management Information Base II (RFC1213) UDP objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/udp.h" +#include "lwip/stats.h" + +#include + +#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + +/* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */ + +static s16_t +udp_get_value(struct snmp_node_instance* instance, void* value) +{ + u32_t *uint_ptr = (u32_t*)value; + + switch (instance->node->oid) { + case 1: /* udpInDatagrams */ + *uint_ptr = STATS_GET(mib2.udpindatagrams); + return sizeof(*uint_ptr); + case 2: /* udpNoPorts */ + *uint_ptr = STATS_GET(mib2.udpnoports); + return sizeof(*uint_ptr); + case 3: /* udpInErrors */ + *uint_ptr = STATS_GET(mib2.udpinerrors); + return sizeof(*uint_ptr); + case 4: /* udpOutDatagrams */ + *uint_ptr = STATS_GET(mib2.udpoutdatagrams); + return sizeof(*uint_ptr); + case 8: /* udpHCInDatagrams */ + memset(value, 0, 2*sizeof(u32_t)); /* not supported */ + return 2*sizeof(u32_t); + case 9: /* udpHCOutDatagrams */ + memset(value, 0, 2*sizeof(u32_t)); /* not supported */ + return 2*sizeof(u32_t); + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); + break; + } + + return 0; +} + +/* --- udpEndpointTable --- */ + +static snmp_err_t +udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) +{ + /* all items except udpEndpointProcess are declared as not-accessible */ + switch (*column) { + case 8: /* udpEndpointProcess */ + value->u32 = 0; /* not supported */ + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +udp_endpointTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip_addr_t local_ip, remote_ip; + u16_t local_port, remote_port; + struct udp_pcb *pcb; + u8_t idx = 0; + + LWIP_UNUSED_ARG(value_len); + + /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ + idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); + if (idx == 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ + idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); + if (idx == 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* udpEndpointInstance */ + if (row_oid_len < (idx+1)) { + return SNMP_ERR_NOSUCHINSTANCE; + } + if (row_oid[idx] != 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* find udp_pcb with requested ip and port*/ + pcb = udp_pcbs; + while (pcb != NULL) { + if (ip_addr_cmp(&local_ip, &pcb->local_ip) && + (local_port == pcb->local_port) && + ip_addr_cmp(&remote_ip, &pcb->remote_ip) && + (remote_port == pcb->remote_port)) { + /* fill in object properties */ + return udp_endpointTable_get_cell_value_core(column, value); + } + pcb = pcb->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +udp_endpointTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct udp_pcb *pcb; + struct snmp_next_oid_state state; + /* 1x udpEndpointLocalAddressType + 1x OID len + 16x udpEndpointLocalAddress + 1x udpEndpointLocalPort + + * 1x udpEndpointRemoteAddressType + 1x OID len + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort + + * 1x udpEndpointInstance = 39 + */ + u32_t result_temp[39]; + + LWIP_UNUSED_ARG(value_len); + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); + + /* iterate over all possible OIDs to find the next one */ + pcb = udp_pcbs; + while (pcb != NULL) { + u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; + u8_t idx = 0; + + /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ + idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); + + /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ + idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); + + test_oid[idx] = 0; /* udpEndpointInstance */ + idx++; + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, idx, NULL); + + pcb = pcb->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return udp_endpointTable_get_cell_value_core(column, value); + } else { + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; + } +} + +/* --- udpTable --- */ + +#if LWIP_IPV4 + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range udp_Table_oid_ranges[] = { + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff }, /* IP D */ + { 1, 0xffff } /* Port */ +}; + +static snmp_err_t +udp_Table_get_cell_value_core(struct udp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) +{ + LWIP_UNUSED_ARG(value_len); + + switch (*column) { + case 1: /* udpLocalAddress */ + /* set reference to PCB local IP and return a generic node that copies IP4 addresses */ + value->u32 = ip_2_ip4(&pcb->local_ip)->addr; + break; + case 2: /* udpLocalPort */ + /* set reference to PCB local port and return a generic node that copies u16_t values */ + value->u32 = pcb->local_port; + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +udp_Table_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip4_addr_t ip; + u16_t port; + struct udp_pcb *pcb; + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, udp_Table_oid_ranges, LWIP_ARRAYSIZE(udp_Table_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get IP and port from incoming OID */ + snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ + port = (u16_t)row_oid[4]; + + /* find udp_pcb with requested ip and port*/ + pcb = udp_pcbs; + while (pcb != NULL) { + if (IP_IS_V4_VAL(pcb->local_ip)) { + if (ip4_addr_cmp(&ip, ip_2_ip4(&pcb->local_ip)) && (port == pcb->local_port)) { + /* fill in object properties */ + return udp_Table_get_cell_value_core(pcb, column, value, value_len); + } + } + pcb = pcb->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +udp_Table_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct udp_pcb *pcb; + struct snmp_next_oid_state state; + u32_t result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges)); + + /* iterate over all possible OIDs to find the next one */ + pcb = udp_pcbs; + while (pcb != NULL) { + u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; + + if (IP_IS_V4_VAL(pcb->local_ip)) { + snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); + test_oid[4] = pcb->local_port; + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), pcb); + } + + pcb = pcb->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return udp_Table_get_cell_value_core((struct udp_pcb*)state.reference, column, value, value_len); + } else { + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; + } +} + +#endif /* LWIP_IPV4 */ + +static const struct snmp_scalar_node udp_inDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_COUNTER, udp_get_value); +static const struct snmp_scalar_node udp_noPorts = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_COUNTER, udp_get_value); +static const struct snmp_scalar_node udp_inErrors = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, udp_get_value); +static const struct snmp_scalar_node udp_outDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, udp_get_value); +static const struct snmp_scalar_node udp_HCInDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); +static const struct snmp_scalar_node udp_HCOutDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); + +#if LWIP_IPV4 +static const struct snmp_table_simple_col_def udp_Table_columns[] = { + { 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* udpLocalAddress */ + { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpLocalPort */ +}; +static const struct snmp_table_simple_node udp_Table = SNMP_TABLE_CREATE_SIMPLE(5, udp_Table_columns, udp_Table_get_cell_value, udp_Table_get_next_cell_instance_and_value); +#endif /* LWIP_IPV4 */ + +static const struct snmp_table_simple_col_def udp_endpointTable_columns[] = { + /* all items except udpEndpointProcess are declared as not-accessible */ + { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpEndpointProcess */ +}; + +static const struct snmp_table_simple_node udp_endpointTable = SNMP_TABLE_CREATE_SIMPLE(7, udp_endpointTable_columns, udp_endpointTable_get_cell_value, udp_endpointTable_get_next_cell_instance_and_value); + +/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ +CREATE_LWIP_SYNC_NODE(1, udp_inDatagrams) +CREATE_LWIP_SYNC_NODE(2, udp_noPorts) +CREATE_LWIP_SYNC_NODE(3, udp_inErrors) +CREATE_LWIP_SYNC_NODE(4, udp_outDatagrams) +#if LWIP_IPV4 +CREATE_LWIP_SYNC_NODE(5, udp_Table) +#endif /* LWIP_IPV4 */ +CREATE_LWIP_SYNC_NODE(7, udp_endpointTable) +CREATE_LWIP_SYNC_NODE(8, udp_HCInDatagrams) +CREATE_LWIP_SYNC_NODE(9, udp_HCOutDatagrams) + +static const struct snmp_node* const udp_nodes[] = { + &SYNC_NODE_NAME(udp_inDatagrams).node.node, + &SYNC_NODE_NAME(udp_noPorts).node.node, + &SYNC_NODE_NAME(udp_inErrors).node.node, + &SYNC_NODE_NAME(udp_outDatagrams).node.node, +#if LWIP_IPV4 + &SYNC_NODE_NAME(udp_Table).node.node, +#endif /* LWIP_IPV4 */ + &SYNC_NODE_NAME(udp_endpointTable).node.node, + &SYNC_NODE_NAME(udp_HCInDatagrams).node.node, + &SYNC_NODE_NAME(udp_HCOutDatagrams).node.node +}; + +const struct snmp_tree_node snmp_mib2_udp_root = SNMP_CREATE_TREE_NODE(7, udp_nodes); +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_msg.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_msg.c new file mode 100644 index 0000000000..0cb7ca997c --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_msg.c @@ -0,0 +1,1668 @@ +/** + * @file + * SNMP message processing (RFC1157). + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel + * Elias Oenal + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "snmp_msg.h" +#include "snmp_asn1.h" +#include "snmp_core_priv.h" +#include "lwip/ip_addr.h" +#include "lwip/stats.h" + +#if LWIP_SNMP_V3 +#include "lwip/apps/snmpv3.h" +#include "snmpv3_priv.h" +#ifdef LWIP_SNMPV3_INCLUDE_ENGINE +#include LWIP_SNMPV3_INCLUDE_ENGINE +#endif +#endif + +#include + +/* public (non-static) constants */ +/** SNMP community string */ +const char *snmp_community = SNMP_COMMUNITY; +/** SNMP community string for write access */ +const char *snmp_community_write = SNMP_COMMUNITY_WRITE; +/** SNMP community string for sending traps */ +const char *snmp_community_trap = SNMP_COMMUNITY_TRAP; + +snmp_write_callback_fct snmp_write_callback = NULL; +void* snmp_write_callback_arg = NULL; + +/** + * @ingroup snmp_core + * Returns current SNMP community string. + * @return current SNMP community string + */ +const char * +snmp_get_community(void) +{ + return snmp_community; +} + +/** + * @ingroup snmp_core + * Sets SNMP community string. + * The string itself (its storage) must be valid throughout the whole life of + * program (or until it is changed to sth else). + * + * @param community is a pointer to new community string + */ +void +snmp_set_community(const char * const community) +{ + LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); + snmp_community = community; +} + +/** + * @ingroup snmp_core + * Returns current SNMP write-access community string. + * @return current SNMP write-access community string + */ +const char * +snmp_get_community_write(void) +{ + return snmp_community_write; +} + +/** + * @ingroup snmp_traps + * Returns current SNMP community string used for sending traps. + * @return current SNMP community string used for sending traps + */ +const char * +snmp_get_community_trap(void) +{ + return snmp_community_trap; +} + +/** + * @ingroup snmp_core + * Sets SNMP community string for write-access. + * The string itself (its storage) must be valid throughout the whole life of + * program (or until it is changed to sth else). + * + * @param community is a pointer to new write-access community string + */ +void +snmp_set_community_write(const char * const community) +{ + LWIP_ASSERT("community string must not be NULL", community != NULL); + LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); + snmp_community_write = community; +} + +/** + * @ingroup snmp_traps + * Sets SNMP community string used for sending traps. + * The string itself (its storage) must be valid throughout the whole life of + * program (or until it is changed to sth else). + * + * @param community is a pointer to new trap community string + */ +void +snmp_set_community_trap(const char * const community) +{ + LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); + snmp_community_trap = community; +} + +/** + * @ingroup snmp_core + * Callback fired on every successful write access + */ +void +snmp_set_write_callback(snmp_write_callback_fct write_callback, void* callback_arg) +{ + snmp_write_callback = write_callback; + snmp_write_callback_arg = callback_arg; +} + +/* ----------------------------------------------------------------------- */ +/* forward declarations */ +/* ----------------------------------------------------------------------- */ + +static err_t snmp_process_get_request(struct snmp_request *request); +static err_t snmp_process_getnext_request(struct snmp_request *request); +static err_t snmp_process_getbulk_request(struct snmp_request *request); +static err_t snmp_process_set_request(struct snmp_request *request); + +static err_t snmp_parse_inbound_frame(struct snmp_request *request); +static err_t snmp_prepare_outbound_frame(struct snmp_request *request); +static err_t snmp_complete_outbound_frame(struct snmp_request *request); +static void snmp_execute_write_callbacks(struct snmp_request *request); + + +/* ----------------------------------------------------------------------- */ +/* implementation */ +/* ----------------------------------------------------------------------- */ + +void +snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port) +{ + err_t err; + struct snmp_request request; + + memset(&request, 0, sizeof(request)); + request.handle = handle; + request.source_ip = source_ip; + request.source_port = port; + request.inbound_pbuf = p; + + snmp_stats.inpkts++; + + err = snmp_parse_inbound_frame(&request); + if (err == ERR_OK) { + err = snmp_prepare_outbound_frame(&request); + if (err == ERR_OK) { + + if (request.error_status == SNMP_ERR_NOERROR) { + /* only process frame if we do not already have an error to return (e.g. all readonly) */ + if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_REQ) { + err = snmp_process_get_request(&request); + } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ) { + err = snmp_process_getnext_request(&request); + } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { + err = snmp_process_getbulk_request(&request); + } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { + err = snmp_process_set_request(&request); + } + } + + if (err == ERR_OK) { + err = snmp_complete_outbound_frame(&request); + + if (err == ERR_OK) { + err = snmp_sendto(request.handle, request.outbound_pbuf, request.source_ip, request.source_port); + + if ((request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) + && (request.error_status == SNMP_ERR_NOERROR) + && (snmp_write_callback != NULL)) { + /* raise write notification for all written objects */ + snmp_execute_write_callbacks(&request); + } + } + } + } + + if (request.outbound_pbuf != NULL) { + pbuf_free(request.outbound_pbuf); + } + } +} + +static u8_t +snmp_msg_getnext_validate_node_inst(struct snmp_node_instance* node_instance, void* validate_arg) +{ + if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != SNMP_NODE_INSTANCE_ACCESS_READ) || (node_instance->get_value == NULL)) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + if ((node_instance->asn1_type == SNMP_ASN1_TYPE_COUNTER64) && (((struct snmp_request*)validate_arg)->version == SNMP_VERSION_1)) { + /* according to RFC 2089 skip Counter64 objects in GetNext requests from v1 clients */ + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static void +snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t get_next) +{ + err_t err; + struct snmp_node_instance node_instance; + memset(&node_instance, 0, sizeof(node_instance)); + + if (get_next) { + struct snmp_obj_id result_oid; + request->error_status = snmp_get_next_node_instance_from_oid(vb->oid.id, vb->oid.len, snmp_msg_getnext_validate_node_inst, request, &result_oid, &node_instance); + + if (request->error_status == SNMP_ERR_NOERROR) { + snmp_oid_assign(&vb->oid, result_oid.id, result_oid.len); + } + } else { + request->error_status = snmp_get_node_instance_from_oid(vb->oid.id, vb->oid.len, &node_instance); + + if (request->error_status == SNMP_ERR_NOERROR) { + /* use 'getnext_validate' method for validation to avoid code duplication (some checks have to be executed here) */ + request->error_status = snmp_msg_getnext_validate_node_inst(&node_instance, request); + + if (request->error_status != SNMP_ERR_NOERROR) { + if (node_instance.release_instance != NULL) { + node_instance.release_instance(&node_instance); + } + } + } + } + + if (request->error_status != SNMP_ERR_NOERROR) { + if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { + if ((request->version == SNMP_VERSION_2c) || request->version == SNMP_VERSION_3) { + /* in SNMP v2c a varbind related exception is stored in varbind and not in frame header */ + vb->type = (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | (request->error_status & SNMP_VARBIND_EXCEPTION_MASK)); + vb->value_len = 0; + + err = snmp_append_outbound_varbind(&(request->outbound_pbuf_stream), vb); + if (err == ERR_OK) { + /* we stored the exception in varbind -> go on */ + request->error_status = SNMP_ERR_NOERROR; + } else if (err == ERR_BUF) { + request->error_status = SNMP_ERR_TOOBIG; + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } + } else { + /* according to RFC 1157/1905, all other errors only return genError */ + request->error_status = SNMP_ERR_GENERROR; + } + } else { + s16_t len = node_instance.get_value(&node_instance, vb->value); + vb->type = node_instance.asn1_type; + + if(len >= 0) { + vb->value_len = (u16_t)len; /* cast is OK because we checked >= 0 above */ + + LWIP_ASSERT("SNMP_MAX_VALUE_SIZE is configured too low", (vb->value_len & ~SNMP_GET_VALUE_RAW_DATA) <= SNMP_MAX_VALUE_SIZE); + err = snmp_append_outbound_varbind(&request->outbound_pbuf_stream, vb); + + if (err == ERR_BUF) { + request->error_status = SNMP_ERR_TOOBIG; + } else if (err != ERR_OK) { + request->error_status = SNMP_ERR_GENERROR; + } + } else { + request->error_status = SNMP_ERR_GENERROR; + } + + if (node_instance.release_instance != NULL) { + node_instance.release_instance(&node_instance); + } + } +} + + +/** + * Service an internal or external event for SNMP GET. + * + * @param request points to the associated message process state + */ +static err_t +snmp_process_get_request(struct snmp_request *request) +{ + snmp_vb_enumerator_err_t err; + struct snmp_varbind vb; + vb.value = request->value_buffer; + + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get request\n")); + + while (request->error_status == SNMP_ERR_NOERROR) { + err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_OK) { + if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { + snmp_process_varbind(request, &vb, 0); + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { + /* malformed ASN.1, don't answer */ + return ERR_ARG; + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } + + return ERR_OK; +} + +/** + * Service an internal or external event for SNMP GET. + * + * @param request points to the associated message process state + */ +static err_t +snmp_process_getnext_request(struct snmp_request *request) +{ + snmp_vb_enumerator_err_t err; + struct snmp_varbind vb; + vb.value = request->value_buffer; + + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-next request\n")); + + while (request->error_status == SNMP_ERR_NOERROR) { + err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_OK) { + if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { + snmp_process_varbind(request, &vb, 1); + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { + /* malformed ASN.1, don't answer */ + return ERR_ARG; + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } + + return ERR_OK; +} + +/** + * Service an internal or external event for SNMP GETBULKT. + * + * @param request points to the associated message process state + */ +static err_t +snmp_process_getbulk_request(struct snmp_request *request) +{ + snmp_vb_enumerator_err_t err; + s32_t non_repeaters = request->non_repeaters; + s32_t repetitions; + u16_t repetition_offset = 0; + struct snmp_varbind_enumerator repetition_varbind_enumerator; + struct snmp_varbind vb; + vb.value = request->value_buffer; + + if (SNMP_LWIP_GETBULK_MAX_REPETITIONS > 0) { + repetitions = LWIP_MIN(request->max_repetitions, SNMP_LWIP_GETBULK_MAX_REPETITIONS); + } else { + repetitions = request->max_repetitions; + } + + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-bulk request\n")); + + /* process non repeaters and first repetition */ + while (request->error_status == SNMP_ERR_NOERROR) { + if (non_repeaters == 0) { + repetition_offset = request->outbound_pbuf_stream.offset; + + if (repetitions == 0) { + /* do not resolve repeaters when repetitions is set to 0 */ + break; + } + repetitions--; + } + + err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { + /* malformed ASN.1, don't answer */ + return ERR_ARG; + } else if ((err != SNMP_VB_ENUMERATOR_ERR_OK) || (vb.type != SNMP_ASN1_TYPE_NULL) || (vb.value_len != 0)) { + request->error_status = SNMP_ERR_GENERROR; + } else { + snmp_process_varbind(request, &vb, 1); + non_repeaters--; + } + } + + /* process repetitions > 1 */ + while ((request->error_status == SNMP_ERR_NOERROR) && (repetitions > 0) && (request->outbound_pbuf_stream.offset != repetition_offset)) { + + u8_t all_endofmibview = 1; + + snmp_vb_enumerator_init(&repetition_varbind_enumerator, request->outbound_pbuf, repetition_offset, request->outbound_pbuf_stream.offset - repetition_offset); + repetition_offset = request->outbound_pbuf_stream.offset; /* for next loop */ + + while (request->error_status == SNMP_ERR_NOERROR) { + vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned) */ + err = snmp_vb_enumerator_get_next(&repetition_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_OK) { + vb.value = request->value_buffer; + snmp_process_varbind(request, &vb, 1); + + if (request->error_status != SNMP_ERR_NOERROR) { + /* already set correct error-index (here it cannot be taken from inbound varbind enumerator) */ + request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; + } else if (vb.type != (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW)) { + all_endofmibview = 0; + } + } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else { + LWIP_DEBUGF(SNMP_DEBUG, ("Very strange, we cannot parse the varbind output that we created just before!")); + request->error_status = SNMP_ERR_GENERROR; + request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; + } + } + + if ((request->error_status == SNMP_ERR_NOERROR) && all_endofmibview) { + /* stop when all varbinds in a loop return EndOfMibView */ + break; + } + + repetitions--; + } + + if (request->error_status == SNMP_ERR_TOOBIG) { + /* for GetBulk it is ok, if not all requested variables fit into the response -> just return the varbinds added so far */ + request->error_status = SNMP_ERR_NOERROR; + } + + return ERR_OK; +} + +/** + * Service an internal or external event for SNMP SET. + * + * @param request points to the associated message process state + */ +static err_t +snmp_process_set_request(struct snmp_request *request) +{ + snmp_vb_enumerator_err_t err; + struct snmp_varbind vb; + vb.value = request->value_buffer; + + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP set request\n")); + + /* perform set test on all objects */ + while (request->error_status == SNMP_ERR_NOERROR) { + err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_OK) { + struct snmp_node_instance node_instance; + memset(&node_instance, 0, sizeof(node_instance)); + + request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); + if (request->error_status == SNMP_ERR_NOERROR) { + if (node_instance.asn1_type != vb.type) { + request->error_status = SNMP_ERR_WRONGTYPE; + } else if (((node_instance.access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != SNMP_NODE_INSTANCE_ACCESS_WRITE) || (node_instance.set_value == NULL)) { + request->error_status = SNMP_ERR_NOTWRITABLE; + } else { + if (node_instance.set_test != NULL) { + request->error_status = node_instance.set_test(&node_instance, vb.value_len, vb.value); + } + } + + if (node_instance.release_instance != NULL) { + node_instance.release_instance(&node_instance); + } + } + } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else if (err == SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH) { + request->error_status = SNMP_ERR_WRONGLENGTH; + } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { + /* malformed ASN.1, don't answer */ + return ERR_ARG; + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } + + /* perform real set operation on all objects */ + if (request->error_status == SNMP_ERR_NOERROR) { + snmp_vb_enumerator_init(&request->inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); + while (request->error_status == SNMP_ERR_NOERROR) { + err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_OK) { + struct snmp_node_instance node_instance; + memset(&node_instance, 0, sizeof(node_instance)); + request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); + if (request->error_status == SNMP_ERR_NOERROR) { + if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR) { + if (request->inbound_varbind_enumerator.varbind_count == 1) { + request->error_status = SNMP_ERR_COMMITFAILED; + } else { + /* we cannot undo the set operations done so far */ + request->error_status = SNMP_ERR_UNDOFAILED; + } + } + + if (node_instance.release_instance != NULL) { + node_instance.release_instance(&node_instance); + } + } + } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else { + /* first time enumerating varbinds work but second time not, although nothing should have changed in between ??? */ + request->error_status = SNMP_ERR_GENERROR; + } + } + } + + return ERR_OK; +} + +#define PARSE_EXEC(code, retValue) \ + if ((code) != ERR_OK) { \ + LWIP_DEBUGF(SNMP_DEBUG, ("Malformed ASN.1 detected.\n")); \ + snmp_stats.inasnparseerrs++; \ + return retValue; \ + } + +#define PARSE_ASSERT(cond, retValue) \ + if (!(cond)) { \ + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP parse assertion failed!: " # cond)); \ + snmp_stats.inasnparseerrs++; \ + return retValue; \ + } + +#define BUILD_EXEC(code, retValue) \ + if ((code) != ERR_OK) { \ + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound frame!: " # code)); \ + return retValue; \ + } + +#define IF_PARSE_EXEC(code) PARSE_EXEC(code, ERR_ARG) +#define IF_PARSE_ASSERT(code) PARSE_ASSERT(code, ERR_ARG) + +/** + * Checks and decodes incoming SNMP message header, logs header errors. + * + * @param request points to the current message request state return + * @return + * - ERR_OK SNMP header is sane and accepted + * - ERR_VAL SNMP header is either malformed or rejected + */ +static err_t +snmp_parse_inbound_frame(struct snmp_request *request) +{ + struct snmp_pbuf_stream pbuf_stream; + struct snmp_asn1_tlv tlv; + s32_t parent_tlv_value_len; + s32_t s32_value; + err_t err; + + IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); + + /* decode main container consisting of version, community and PDU */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len == pbuf_stream.length)); + parent_tlv_value_len = tlv.value_len; + + /* decode version */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + if ((s32_value != SNMP_VERSION_1) && + (s32_value != SNMP_VERSION_2c) +#if LWIP_SNMP_V3 + && (s32_value != SNMP_VERSION_3) +#endif + ) + { + /* unsupported SNMP version */ + snmp_stats.inbadversions++; + return ERR_ARG; + } + request->version = (u8_t)s32_value; + +#if LWIP_SNMP_V3 + if (request->version == SNMP_VERSION_3) { + u16_t u16_value; + u16_t inbound_msgAuthenticationParameters_offset; + + /* SNMPv3 doesn't use communities */ + /* @todo: Differentiate read/write access */ + strcpy((char*)request->community, snmp_community); + request->community_strlen = (u16_t)strlen(snmp_community); + + /* RFC3414 globalData */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); + parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + /* decode msgID */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + request->msg_id = s32_value; + + /* decode msgMaxSize */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + request->msg_max_size = s32_value; + + /* decode msgFlags */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + request->msg_flags = (u8_t)s32_value; + + /* decode msgSecurityModel */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + request->msg_security_model = s32_value; + + /* RFC3414 msgSecurityParameters + * The User-based Security Model defines the contents of the OCTET + * STRING as a SEQUENCE. + * + * We skip the protective dummy OCTET STRING header + * to access the SEQUENCE header. + */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + /* msgSecurityParameters SEQUENCE header */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); + parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + /* decode msgAuthoritativeEngineID */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authoritative_engine_id, + &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); + request->msg_authoritative_engine_id_len = (u8_t)u16_value; + + /* msgAuthoritativeEngineBoots */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_boots)); + + /* msgAuthoritativeEngineTime */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_time)); + /* @todo: Implement time window checking */ + + /* msgUserName */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_user_name, + &u16_value, SNMP_V3_MAX_USER_LENGTH)); + request->msg_user_name_len = (u8_t)u16_value; + /* @todo: Implement unknown user error response */ + IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, NULL, NULL)); + + /* msgAuthenticationParameters */ + memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + /* Remember position */ + inbound_msgAuthenticationParameters_offset = pbuf_stream.offset; + LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset); + /* Read auth parameters */ + IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH); + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authentication_parameters, + &u16_value, tlv.value_len)); + +#if LWIP_SNMP_V3_CRYPTO + if (request->msg_flags & SNMP_V3_AUTH_FLAG) { + const u8_t zero_arr[SNMP_V3_MAX_AUTH_PARAM_LENGTH] = { 0 }; + u8_t key[20]; + u8_t algo; + u8_t hmac[LWIP_MAX(SNMP_V3_SHA_LEN, SNMP_V3_MD5_LEN)]; + struct snmp_pbuf_stream auth_stream; + + /* Rewind stream */ + IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); + IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&pbuf_stream, inbound_msgAuthenticationParameters_offset)); + /* Set auth parameters to zero for verification */ + IF_PARSE_EXEC(snmp_asn1_enc_raw(&pbuf_stream, zero_arr, tlv.value_len)); + + /* Verify authentication */ + IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); + + IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL)); + IF_PARSE_EXEC(snmpv3_auth(&auth_stream, request->inbound_pbuf->tot_len, key, algo, hmac)); + /* @todo: Implement error response */ + IF_PARSE_EXEC(memcmp(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); + } +#else + /* Ungraceful exit if we encounter cryptography and don't support it. + * @todo: Implement error response + */ + IF_PARSE_ASSERT(!(request->msg_flags & (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG))); +#endif + + /* msgPrivacyParameters */ + memset(request->msg_privacy_parameters, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_privacy_parameters, + &u16_value, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); + +#if LWIP_SNMP_V3_CRYPTO + /* Decrypt message */ + if (request->msg_flags & SNMP_V3_PRIV_FLAG) { + u8_t key[20]; + u8_t algo; + + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key)); + IF_PARSE_EXEC(snmpv3_crypt(&pbuf_stream, tlv.value_len, key, + request->msg_privacy_parameters, request->msg_authoritative_engine_boots, + request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_DECRYPT)); + } +#endif + + /* Scoped PDU + * Encryption context + */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); + parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + /* contextEngineID */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_engine_id, + &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); + request->context_engine_id_len = (u8_t)u16_value; + + /* contextName */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_name, + &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); + request->context_name_len = (u8_t)u16_value; + } else +#endif + { + /* decode community */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + err = snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->community, &request->community_strlen, SNMP_MAX_COMMUNITY_STR_LEN); + if (err == ERR_MEM) { + /* community string does not fit in our buffer -> its too long -> its invalid */ + request->community_strlen = 0; + snmp_pbuf_stream_seek(&pbuf_stream, tlv.value_len); + } else { + IF_PARSE_ASSERT(err == ERR_OK); + } + /* add zero terminator */ + request->community[request->community_strlen] = 0; + } + + /* decode PDU type (next container level) */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.value_len <= pbuf_stream.length); + request->inbound_padding_len = pbuf_stream.length - tlv.value_len; + parent_tlv_value_len = tlv.value_len; + + /* validate PDU type */ + switch(tlv.type) { + case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_REQ): + /* GetRequest PDU */ + snmp_stats.ingetrequests++; + break; + case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ): + /* GetNextRequest PDU */ + snmp_stats.ingetnexts++; + break; + case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ): + /* GetBulkRequest PDU */ + if (request->version < SNMP_VERSION_2c) { + /* RFC2089: invalid, drop packet */ + return ERR_ARG; + } + break; + case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_SET_REQ): + /* SetRequest PDU */ + snmp_stats.insetrequests++; + break; + default: + /* unsupported input PDU for this agent (no parse error) */ + LWIP_DEBUGF(SNMP_DEBUG, ("Unknown/Invalid SNMP PDU type received: %d", tlv.type)); \ + return ERR_ARG; + break; + } + request->request_type = tlv.type & SNMP_ASN1_DATATYPE_MASK; + + /* validate community (do this after decoding PDU type because we don't want to increase 'inbadcommunitynames' for wrong frame types */ + if (request->community_strlen == 0) { + /* community string was too long or really empty*/ + snmp_stats.inbadcommunitynames++; + snmp_authfail_trap(); + return ERR_ARG; + } else if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { + if (snmp_community_write[0] == 0) { + /* our write community is empty, that means all our objects are readonly */ + request->error_status = SNMP_ERR_NOTWRITABLE; + request->error_index = 1; + } else if (strncmp(snmp_community_write, (const char*)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { + /* community name does not match */ + snmp_stats.inbadcommunitynames++; + snmp_authfail_trap(); + return ERR_ARG; + } + } else { + if (strncmp(snmp_community, (const char*)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { + /* community name does not match */ + snmp_stats.inbadcommunitynames++; + snmp_authfail_trap(); + return ERR_ARG; + } + } + + /* decode request ID */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->request_id)); + + /* decode error status / non-repeaters */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->non_repeaters)); + if (request->non_repeaters < 0) { + /* RFC 1905, 4.2.3 */ + request->non_repeaters = 0; + } + } else { + /* only check valid value, don't touch 'request->error_status', maybe a response error status was already set to above; */ + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + IF_PARSE_ASSERT(s32_value == SNMP_ERR_NOERROR); + } + + /* decode error index / max-repetitions */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->max_repetitions)); + if (request->max_repetitions < 0) { + /* RFC 1905, 4.2.3 */ + request->max_repetitions = 0; + } + } else { + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->error_index)); + IF_PARSE_ASSERT(s32_value == 0); + } + + /* decode varbind-list type (next container level) */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= pbuf_stream.length)); + + request->inbound_varbind_offset = pbuf_stream.offset; + request->inbound_varbind_len = pbuf_stream.length - request->inbound_padding_len; + snmp_vb_enumerator_init(&(request->inbound_varbind_enumerator), request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); + + return ERR_OK; +} + +#define OF_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) + +static err_t +snmp_prepare_outbound_frame(struct snmp_request *request) +{ + struct snmp_asn1_tlv tlv; + struct snmp_pbuf_stream* pbuf_stream = &(request->outbound_pbuf_stream); + + /* try allocating pbuf(s) for maximum response size */ + request->outbound_pbuf = pbuf_alloc(PBUF_TRANSPORT, 1472, PBUF_RAM); + if (request->outbound_pbuf == NULL) { + return ERR_MEM; + } + + snmp_pbuf_stream_init(pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len); + + /* 'Message' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + + /* version */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(request->version, &tlv.value_len); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->version) ); + +#if LWIP_SNMP_V3 + if (request->version < SNMP_VERSION_3) { +#endif + /* community */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->community_strlen); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + OF_BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, request->community, request->community_strlen) ); +#if LWIP_SNMP_V3 + } else { + const char* id; + + /* globalData */ + request->outbound_msg_global_data_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + /* msgID */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); + snmp_asn1_enc_s32t_cnt(request->msg_id, &tlv.value_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_id)); + + /* msgMaxSize */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); + snmp_asn1_enc_s32t_cnt(request->msg_max_size, &tlv.value_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_max_size)); + + /* msgFlags */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 1); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, &request->msg_flags, 1)); + + /* msgSecurityModel */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); + snmp_asn1_enc_s32t_cnt(request->msg_security_model, &tlv.value_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_security_model)); + + /* end of msgGlobalData */ + request->outbound_msg_global_data_end = pbuf_stream->offset; + + /* msgSecurityParameters */ + request->outbound_msg_security_parameters_str_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + request->outbound_msg_security_parameters_seq_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + /* msgAuthoritativeEngineID */ + snmpv3_get_engine_id(&id, &request->msg_authoritative_engine_id_len); + MEMCPY(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len); + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_authoritative_engine_id_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authoritative_engine_id, request->msg_authoritative_engine_id_len)); + + request->msg_authoritative_engine_time = snmpv3_get_engine_time(); + request->msg_authoritative_engine_boots = snmpv3_get_engine_boots(); + + /* msgAuthoritativeEngineBoots */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_boots, &tlv.value_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_boots)); + + /* msgAuthoritativeEngineTime */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_time, &tlv.value_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_time)); + + /* msgUserName */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_user_name_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_user_name, request->msg_user_name_len)); + +#if LWIP_SNMP_V3_CRYPTO + /* msgAuthenticationParameters */ + if (request->msg_flags & SNMP_V3_AUTH_FLAG) { + memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); + request->outbound_msg_authentication_parameters_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); + } else +#endif + { + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + } + +#if LWIP_SNMP_V3_CRYPTO + /* msgPrivacyParameters */ + if (request->msg_flags & SNMP_V3_PRIV_FLAG) { + snmpv3_build_priv_param(request->msg_privacy_parameters); + + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_privacy_parameters, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); + } else +#endif + { + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + } + + /* End of msgSecurityParameters, so we can calculate the length of this sequence later */ + request->outbound_msg_security_parameters_end = pbuf_stream->offset; + +#if LWIP_SNMP_V3_CRYPTO + /* For encryption we have to encapsulate the payload in an octet string */ + if (request->msg_flags & SNMP_V3_PRIV_FLAG) { + request->outbound_scoped_pdu_string_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + } +#endif + /* Scoped PDU + * Encryption context + */ + request->outbound_scoped_pdu_seq_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + /* contextEngineID */ + snmpv3_get_engine_id(&id, &request->context_engine_id_len); + MEMCPY(request->context_engine_id, id, request->context_engine_id_len); + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_engine_id_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_engine_id, request->context_engine_id_len)); + + /* contextName */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_name_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_name, request->context_name_len)); + } +#endif + + /* 'PDU' sequence */ + request->outbound_pdu_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, 0); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + + /* request ID */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(request->request_id, &tlv.value_len); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->request_id) ); + + /* error status */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + request->outbound_error_status_offset = pbuf_stream->offset; + OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); + + /* error index */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + request->outbound_error_index_offset = pbuf_stream->offset; + OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); + + /* 'VarBindList' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + + request->outbound_varbind_offset = pbuf_stream->offset; + + return ERR_OK; +} + +/** Calculate the length of a varbind list */ +err_t +snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len) +{ + /* calculate required lengths */ + snmp_asn1_enc_oid_cnt(varbind->oid.id, varbind->oid.len, &len->oid_value_len); + snmp_asn1_enc_length_cnt(len->oid_value_len, &len->oid_len_len); + + if (varbind->value_len == 0) { + len->value_value_len = 0; + } else if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { + len->value_value_len = varbind->value_len & (~SNMP_GET_VALUE_RAW_DATA); + } else { + switch (varbind->type) { + case SNMP_ASN1_TYPE_INTEGER: + if (varbind->value_len != sizeof (s32_t)) { + return ERR_VAL; + } + snmp_asn1_enc_s32t_cnt(*((s32_t*) varbind->value), &len->value_value_len); + break; + case SNMP_ASN1_TYPE_COUNTER: + case SNMP_ASN1_TYPE_GAUGE: + case SNMP_ASN1_TYPE_TIMETICKS: + if (varbind->value_len != sizeof (u32_t)) { + return ERR_VAL; + } + snmp_asn1_enc_u32t_cnt(*((u32_t*) varbind->value), &len->value_value_len); + break; + case SNMP_ASN1_TYPE_OCTET_STRING: + case SNMP_ASN1_TYPE_IPADDR: + case SNMP_ASN1_TYPE_OPAQUE: + len->value_value_len = varbind->value_len; + break; + case SNMP_ASN1_TYPE_NULL: + if (varbind->value_len != 0) { + return ERR_VAL; + } + len->value_value_len = 0; + break; + case SNMP_ASN1_TYPE_OBJECT_ID: + if ((varbind->value_len & 0x03) != 0) { + return ERR_VAL; + } + snmp_asn1_enc_oid_cnt((u32_t*) varbind->value, varbind->value_len >> 2, &len->value_value_len); + break; + case SNMP_ASN1_TYPE_COUNTER64: + if (varbind->value_len != (2 * sizeof (u32_t))) { + return ERR_VAL; + } + snmp_asn1_enc_u64t_cnt((u32_t*) varbind->value, &len->value_value_len); + break; + default: + /* unsupported type */ + return ERR_VAL; + } + } + snmp_asn1_enc_length_cnt(len->value_value_len, &len->value_len_len); + + len->vb_value_len = 1 + len->oid_len_len + len->oid_value_len + 1 + len->value_len_len + len->value_value_len; + snmp_asn1_enc_length_cnt(len->vb_value_len, &len->vb_len_len); + + return ERR_OK; +} + +#define OVB_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) + +err_t +snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind) +{ + struct snmp_asn1_tlv tlv; + struct snmp_varbind_len len; + err_t err; + + err = snmp_varbind_length(varbind, &len); + + if (err != ERR_OK) { + return err; + } + + /* check length already before adding first data because in case of GetBulk, + * data added so far is returned and therefore no partial data shall be added + */ + if ((1 + len.vb_len_len + len.vb_value_len) > pbuf_stream->length) { + return ERR_BUF; + } + + /* 'VarBind' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, len.vb_len_len, len.vb_value_len); + OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + /* VarBind OID */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, len.oid_len_len, len.oid_value_len); + OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, varbind->oid.id, varbind->oid.len)); + + /* VarBind value */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, varbind->type, len.value_len_len, len.value_value_len); + OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + if (len.value_value_len > 0) { + if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { + OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t*) varbind->value, len.value_value_len)); + } else { + switch (varbind->type) { + case SNMP_ASN1_TYPE_INTEGER: + OVB_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, len.value_value_len, *((s32_t*) varbind->value))); + break; + case SNMP_ASN1_TYPE_COUNTER: + case SNMP_ASN1_TYPE_GAUGE: + case SNMP_ASN1_TYPE_TIMETICKS: + OVB_BUILD_EXEC(snmp_asn1_enc_u32t(pbuf_stream, len.value_value_len, *((u32_t*) varbind->value))); + break; + case SNMP_ASN1_TYPE_OCTET_STRING: + case SNMP_ASN1_TYPE_IPADDR: + case SNMP_ASN1_TYPE_OPAQUE: + OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t*) varbind->value, len.value_value_len)); + len.value_value_len = varbind->value_len; + break; + case SNMP_ASN1_TYPE_OBJECT_ID: + OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, (u32_t*) varbind->value, varbind->value_len / sizeof (u32_t))); + break; + case SNMP_ASN1_TYPE_COUNTER64: + OVB_BUILD_EXEC(snmp_asn1_enc_u64t(pbuf_stream, len.value_value_len, (u32_t*) varbind->value)); + break; + default: + LWIP_ASSERT("Unknown variable type", 0); + break; + } + } + } + + return ERR_OK; +} + +static err_t +snmp_complete_outbound_frame(struct snmp_request *request) +{ + struct snmp_asn1_tlv tlv; + u16_t frame_size; + u8_t outbound_padding = 0; + + if (request->version == SNMP_VERSION_1) { + if (request->error_status != SNMP_ERR_NOERROR) { + /* map v2c error codes to v1 compliant error code (according to RFC 2089) */ + switch (request->error_status) { + /* mapping of implementation specific "virtual" error codes + * (during processing of frame we already stored them in error_status field, + * so no need to check all varbinds here for those exceptions as suggested by RFC) */ + case SNMP_ERR_NOSUCHINSTANCE: + case SNMP_ERR_NOSUCHOBJECT: + case SNMP_ERR_ENDOFMIBVIEW: + request->error_status = SNMP_ERR_NOSUCHNAME; + break; + /* mapping according to RFC */ + case SNMP_ERR_WRONGVALUE: + case SNMP_ERR_WRONGENCODING: + case SNMP_ERR_WRONGTYPE: + case SNMP_ERR_WRONGLENGTH: + case SNMP_ERR_INCONSISTENTVALUE: + request->error_status = SNMP_ERR_BADVALUE; + break; + case SNMP_ERR_NOACCESS: + case SNMP_ERR_NOTWRITABLE: + case SNMP_ERR_NOCREATION: + case SNMP_ERR_INCONSISTENTNAME: + case SNMP_ERR_AUTHORIZATIONERROR: + request->error_status = SNMP_ERR_NOSUCHNAME; + break; + case SNMP_ERR_RESOURCEUNAVAILABLE: + case SNMP_ERR_COMMITFAILED: + case SNMP_ERR_UNDOFAILED: + default: + request->error_status = SNMP_ERR_GENERROR; + break; + } + } + } else { + if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { + /* map error codes to according to RFC 1905 (4.2.5. The SetRequest-PDU) return 'NotWritable' for unknown OIDs) */ + switch (request->error_status) { + case SNMP_ERR_NOSUCHINSTANCE: + case SNMP_ERR_NOSUCHOBJECT: + case SNMP_ERR_ENDOFMIBVIEW: + request->error_status = SNMP_ERR_NOTWRITABLE; + break; + default: + break; + } + } + + if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { + /* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */ + LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n")); + return ERR_ARG; + } + } + + if ((request->error_status != SNMP_ERR_NOERROR) || (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)) { + /* all inbound vars are returned in response without any modification for error responses and successful set requests*/ + struct snmp_pbuf_stream inbound_stream; + OF_BUILD_EXEC( snmp_pbuf_stream_init(&inbound_stream, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len) ); + OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, request->outbound_varbind_offset, request->outbound_pbuf->tot_len - request->outbound_varbind_offset) ); + snmp_pbuf_stream_writeto(&inbound_stream, &(request->outbound_pbuf_stream), 0); + } + + frame_size = request->outbound_pbuf_stream.offset; + +#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO + /* Calculate padding for encryption */ + if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { + u8_t i; + outbound_padding = (8 - (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x07)) & 0x07; + for (i = 0; i < outbound_padding; i++) { + snmp_pbuf_stream_write(&request->outbound_pbuf_stream, 0); + } + } +#endif + + /* complete missing length in 'Message' sequence ; 'Message' tlv is located at the beginning (offset 0) */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size + outbound_padding - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ + OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, 0, request->outbound_pbuf->tot_len) ); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); + +#if LWIP_SNMP_V3 + if (request->version == SNMP_VERSION_3) { + /* complete missing length in 'globalData' sequence */ + /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_global_data_end + - request->outbound_msg_global_data_offset - 1 - 1); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_global_data_offset)); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); + + /* complete missing length in 'msgSecurityParameters' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, request->outbound_msg_security_parameters_end + - request->outbound_msg_security_parameters_str_offset - 1 - 1); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_str_offset)); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); + + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_security_parameters_end + - request->outbound_msg_security_parameters_seq_offset - 1 - 1); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_seq_offset)); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); + + /* complete missing length in scoped PDU sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_scoped_pdu_seq_offset - 1 - 3); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_seq_offset)); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); + } +#endif + + /* complete missing length in 'PDU' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, + frame_size - request->outbound_pdu_offset - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ + OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) ); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); + + /* process and encode final error status */ + if (request->error_status != 0) { + u16_t len; + snmp_asn1_enc_s32t_cnt(request->error_status, &len); + if (len != 1) { + /* error, we only reserved one byte for it */ + return ERR_ARG; + } + OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_status_offset) ); + OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_status) ); + + /* for compatibility to v1, log statistics; in v2 (RFC 1907) these statistics are obsoleted */ + switch (request->error_status) { + case SNMP_ERR_TOOBIG: + snmp_stats.outtoobigs++; + break; + case SNMP_ERR_NOSUCHNAME: + snmp_stats.outnosuchnames++; + break; + case SNMP_ERR_BADVALUE: + snmp_stats.outbadvalues++; + break; + case SNMP_ERR_GENERROR: + default: + snmp_stats.outgenerrs++; + break; + } + + if (request->error_status == SNMP_ERR_TOOBIG) { + request->error_index = 0; /* defined by RFC 1157 */ + } else if (request->error_index == 0) { + /* set index to varbind where error occured (if not already set before, e.g. during GetBulk processing) */ + request->error_index = request->inbound_varbind_enumerator.varbind_count; + } + } else { + if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { + snmp_stats.intotalsetvars += request->inbound_varbind_enumerator.varbind_count; + } else { + snmp_stats.intotalreqvars += request->inbound_varbind_enumerator.varbind_count; + } + } + + /* encode final error index*/ + if (request->error_index != 0) { + u16_t len; + snmp_asn1_enc_s32t_cnt(request->error_index, &len); + if (len != 1) { + /* error, we only reserved one byte for it */ + return ERR_VAL; + } + OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_index_offset) ); + OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_index) ); + } + + /* complete missing length in 'VarBindList' sequence ; 'VarBindList' tlv is located directly before varbind offset */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_varbind_offset); + OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_varbind_offset - 1 - 3) ); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ + OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); + + /* Authenticate response */ +#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO + /* Encrypt response */ + if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { + u8_t key[20]; + u8_t algo; + + /* complete missing length in PDU sequence */ + OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_string_offset)); + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, frame_size + outbound_padding + - request->outbound_scoped_pdu_string_offset - 1 - 3); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); + + OF_BUILD_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key)); + + OF_BUILD_EXEC(snmpv3_crypt(&request->outbound_pbuf_stream, tlv.value_len, key, + request->msg_privacy_parameters, request->msg_authoritative_engine_boots, + request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_ENCRYPT)); + } + + if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_AUTH_FLAG)) { + u8_t key[20]; + u8_t algo; + u8_t hmac[20]; + + OF_BUILD_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL)); + OF_BUILD_EXEC(snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), + request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); + OF_BUILD_EXEC(snmpv3_auth(&request->outbound_pbuf_stream, frame_size + outbound_padding, key, algo, hmac)); + + MEMCPY(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH); + OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, + request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&request->outbound_pbuf_stream, + request->outbound_msg_authentication_parameters_offset)); + + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&request->outbound_pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(&request->outbound_pbuf_stream, + request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); + } +#endif + + pbuf_realloc(request->outbound_pbuf, frame_size + outbound_padding); + + snmp_stats.outgetresponses++; + snmp_stats.outpkts++; + + return ERR_OK; +} + +static void +snmp_execute_write_callbacks(struct snmp_request *request) +{ + struct snmp_varbind_enumerator inbound_varbind_enumerator; + struct snmp_varbind vb; + + snmp_vb_enumerator_init(&inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); + vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned, which we don't need here) */ + + while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == SNMP_VB_ENUMERATOR_ERR_OK) { + snmp_write_callback(vb.oid.id, vb.oid.len, snmp_write_callback_arg); + } +} + + +/* ----------------------------------------------------------------------- */ +/* VarBind enumerator methods */ +/* ----------------------------------------------------------------------- */ + +void +snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length) +{ + snmp_pbuf_stream_init(&(enumerator->pbuf_stream), p, offset, length); + enumerator->varbind_count = 0; +} + +#define VB_PARSE_EXEC(code) PARSE_EXEC(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) +#define VB_PARSE_ASSERT(code) PARSE_ASSERT(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) + +snmp_vb_enumerator_err_t +snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind) +{ + struct snmp_asn1_tlv tlv; + u16_t varbind_len; + err_t err; + + if (enumerator->pbuf_stream.length == 0) + { + return SNMP_VB_ENUMERATOR_ERR_EOVB; + } + enumerator->varbind_count++; + + /* decode varbind itself (parent container of a varbind) */ + VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); + VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= enumerator->pbuf_stream.length)); + varbind_len = tlv.value_len; + + /* decode varbind name (object id) */ + VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); + VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_OBJECT_ID) && (SNMP_ASN1_TLV_LENGTH(tlv) < varbind_len) && (tlv.value_len < enumerator->pbuf_stream.length)); + + VB_PARSE_EXEC(snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, varbind->oid.id, &(varbind->oid.len), SNMP_MAX_OBJ_ID_LEN)); + varbind_len -= SNMP_ASN1_TLV_LENGTH(tlv); + + /* decode varbind value (object id) */ + VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); + VB_PARSE_ASSERT((SNMP_ASN1_TLV_LENGTH(tlv) == varbind_len) && (tlv.value_len <= enumerator->pbuf_stream.length)); + varbind->type = tlv.type; + + /* shall the value be decoded ? */ + if (varbind->value != NULL) { + switch (varbind->type) { + case SNMP_ASN1_TYPE_INTEGER: + VB_PARSE_EXEC(snmp_asn1_dec_s32t(&(enumerator->pbuf_stream), tlv.value_len, (s32_t*)varbind->value)); + varbind->value_len = sizeof(s32_t*); + break; + case SNMP_ASN1_TYPE_COUNTER: + case SNMP_ASN1_TYPE_GAUGE: + case SNMP_ASN1_TYPE_TIMETICKS: + VB_PARSE_EXEC(snmp_asn1_dec_u32t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value)); + varbind->value_len = sizeof(u32_t*); + break; + case SNMP_ASN1_TYPE_OCTET_STRING: + case SNMP_ASN1_TYPE_OPAQUE: + err = snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t*)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE); + if (err == ERR_MEM) { + return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; + } + VB_PARSE_ASSERT(err == ERR_OK); + break; + case SNMP_ASN1_TYPE_NULL: + varbind->value_len = 0; + break; + case SNMP_ASN1_TYPE_OBJECT_ID: + /* misuse tlv.length_len as OID_length transporter */ + err = snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value, &tlv.length_len, SNMP_MAX_OBJ_ID_LEN); + if (err == ERR_MEM) { + return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; + } + VB_PARSE_ASSERT(err == ERR_OK); + varbind->value_len = tlv.length_len * sizeof(u32_t); + break; + case SNMP_ASN1_TYPE_IPADDR: + if (tlv.value_len == 4) { + /* must be exactly 4 octets! */ + VB_PARSE_EXEC(snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t*)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE)); + } else { + VB_PARSE_ASSERT(0); + } + break; + case SNMP_ASN1_TYPE_COUNTER64: + VB_PARSE_EXEC(snmp_asn1_dec_u64t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value)); + varbind->value_len = 2 * sizeof(u32_t*); + break; + default: + VB_PARSE_ASSERT(0); + break; + } + } else { + snmp_pbuf_stream_seek(&(enumerator->pbuf_stream), tlv.value_len); + varbind->value_len = tlv.value_len; + } + + return SNMP_VB_ENUMERATOR_ERR_OK; +} + +#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_msg.h b/components/net/lwip-2.0.3/src/apps/snmp/snmp_msg.h new file mode 100644 index 0000000000..2d01ef36eb --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_msg.h @@ -0,0 +1,194 @@ +/** + * @file + * SNMP Agent message handling structures (internal API, do not use in client code). + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel + * Elias Oenal + */ + +#ifndef LWIP_HDR_APPS_SNMP_MSG_H +#define LWIP_HDR_APPS_SNMP_MSG_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP + +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "snmp_pbuf_stream.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#if LWIP_SNMP_V3 +#include "snmpv3_priv.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* The listen port of the SNMP agent. Clients have to make their requests to + this port. Most standard clients won't work if you change this! */ +#ifndef SNMP_IN_PORT +#define SNMP_IN_PORT 161 +#endif +/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't + work if you change this! */ +#ifndef SNMP_TRAP_PORT +#define SNMP_TRAP_PORT 162 +#endif + +/* version defines used in PDU */ +#define SNMP_VERSION_1 0 +#define SNMP_VERSION_2c 1 +#define SNMP_VERSION_3 3 + +struct snmp_varbind_enumerator +{ + struct snmp_pbuf_stream pbuf_stream; + u16_t varbind_count; +}; + +typedef enum { + SNMP_VB_ENUMERATOR_ERR_OK = 0, + SNMP_VB_ENUMERATOR_ERR_EOVB = 1, + SNMP_VB_ENUMERATOR_ERR_ASN1ERROR = 2, + SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH = 3 +} snmp_vb_enumerator_err_t; + +void snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length); +snmp_vb_enumerator_err_t snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind); + +struct snmp_request +{ + /* Communication handle */ + void *handle; + /* source IP address */ + const ip_addr_t *source_ip; + /* source UDP port */ + u16_t source_port; + /* incoming snmp version */ + u8_t version; + /* community name (zero terminated) */ + u8_t community[SNMP_MAX_COMMUNITY_STR_LEN + 1]; + /* community string length (exclusive zero term) */ + u16_t community_strlen; + /* request type */ + u8_t request_type; + /* request ID */ + s32_t request_id; + /* error status */ + s32_t error_status; + /* error index */ + s32_t error_index; + /* non-repeaters (getBulkRequest (SNMPv2c)) */ + s32_t non_repeaters; + /* max-repetitions (getBulkRequest (SNMPv2c)) */ + s32_t max_repetitions; + +#if LWIP_SNMP_V3 + s32_t msg_id; + s32_t msg_max_size; + u8_t msg_flags; + s32_t msg_security_model; + u8_t msg_authoritative_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; + u8_t msg_authoritative_engine_id_len; + s32_t msg_authoritative_engine_boots; + s32_t msg_authoritative_engine_time; + u8_t msg_user_name[SNMP_V3_MAX_USER_LENGTH]; + u8_t msg_user_name_len; + u8_t msg_authentication_parameters[SNMP_V3_MAX_AUTH_PARAM_LENGTH]; + u8_t msg_privacy_parameters[SNMP_V3_MAX_PRIV_PARAM_LENGTH]; + u8_t context_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; + u8_t context_engine_id_len; + u8_t context_name[SNMP_V3_MAX_ENGINE_ID_LENGTH]; + u8_t context_name_len; +#endif + + struct pbuf *inbound_pbuf; + struct snmp_varbind_enumerator inbound_varbind_enumerator; + u16_t inbound_varbind_offset; + u16_t inbound_varbind_len; + u16_t inbound_padding_len; + + struct pbuf *outbound_pbuf; + struct snmp_pbuf_stream outbound_pbuf_stream; + u16_t outbound_pdu_offset; + u16_t outbound_error_status_offset; + u16_t outbound_error_index_offset; + u16_t outbound_varbind_offset; +#if LWIP_SNMP_V3 + u16_t outbound_msg_global_data_offset; + u16_t outbound_msg_global_data_end; + u16_t outbound_msg_security_parameters_str_offset; + u16_t outbound_msg_security_parameters_seq_offset; + u16_t outbound_msg_security_parameters_end; + u16_t outbound_msg_authentication_parameters_offset; + u16_t outbound_scoped_pdu_seq_offset; + u16_t outbound_scoped_pdu_string_offset; +#endif + + u8_t value_buffer[SNMP_MAX_VALUE_SIZE]; +}; + +/** A helper struct keeping length information about varbinds */ +struct snmp_varbind_len +{ + u8_t vb_len_len; + u16_t vb_value_len; + u8_t oid_len_len; + u16_t oid_value_len; + u8_t value_len_len; + u16_t value_value_len; +}; + +/** Agent community string */ +extern const char *snmp_community; +/** Agent community string for write access */ +extern const char *snmp_community_write; +/** handle for sending traps */ +extern void* snmp_traps_handle; + +void snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port); +err_t snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port); +u8_t snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result); +err_t snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len); +err_t snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_APPS_SNMP_MSG_H */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_netconn.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_netconn.c new file mode 100644 index 0000000000..24c3e26531 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_netconn.c @@ -0,0 +1,121 @@ +/** + * @file + * SNMP netconn frontend. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP && SNMP_USE_NETCONN + +#include +#include "lwip/api.h" +#include "lwip/ip.h" +#include "lwip/udp.h" +#include "snmp_msg.h" +#include "lwip/sys.h" + +/** SNMP netconn API worker thread */ +static void +snmp_netconn_thread(void *arg) +{ + struct netconn *conn; + struct netbuf *buf; + err_t err; + LWIP_UNUSED_ARG(arg); + + /* Bind to SNMP port with default IP address */ +#if LWIP_IPV6 + conn = netconn_new(NETCONN_UDP_IPV6); + netconn_bind(conn, IP6_ADDR_ANY, SNMP_IN_PORT); +#else /* LWIP_IPV6 */ + conn = netconn_new(NETCONN_UDP); + netconn_bind(conn, IP4_ADDR_ANY, SNMP_IN_PORT); +#endif /* LWIP_IPV6 */ + LWIP_ERROR("snmp_netconn: invalid conn", (conn != NULL), return;); + + snmp_traps_handle = conn; + + do { + err = netconn_recv(conn, &buf); + + if (err == ERR_OK) { + snmp_receive(conn, buf->p, &buf->addr, buf->port); + } + + if (buf != NULL) { + netbuf_delete(buf); + } + } while(1); +} + +err_t +snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) +{ + err_t result; + struct netbuf buf; + + memset(&buf, 0, sizeof(buf)); + buf.p = p; + result = netconn_sendto((struct netconn*)handle, &buf, dst, port); + + return result; +} + +u8_t +snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) +{ + struct netconn* conn = (struct netconn*)handle; + struct netif *dst_if; + const ip_addr_t* dst_ip; + + LWIP_UNUSED_ARG(conn); /* unused in case of IPV4 only configuration */ + + ip_route_get_local_ip(&conn->pcb.udp->local_ip, dst, dst_if, dst_ip); + + if ((dst_if != NULL) && (dst_ip != NULL)) { + ip_addr_copy(*result, *dst_ip); + return 1; + } else { + return 0; + } +} + +/** + * Starts SNMP Agent. + */ +void +snmp_init(void) +{ + sys_thread_new("snmp_netconn", snmp_netconn_thread, NULL, SNMP_STACK_SIZE, SNMP_THREAD_PRIO); +} + +#endif /* LWIP_SNMP && SNMP_USE_NETCONN */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_pbuf_stream.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_pbuf_stream.c new file mode 100644 index 0000000000..3c1217d710 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_pbuf_stream.c @@ -0,0 +1,156 @@ +/** + * @file + * SNMP pbuf stream wrapper implementation (internal API, do not use in client code). + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "snmp_pbuf_stream.h" +#include "lwip/def.h" +#include + +err_t +snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length) +{ + pbuf_stream->offset = offset; + pbuf_stream->length = length; + pbuf_stream->pbuf = p; + + return ERR_OK; +} + +err_t +snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data) +{ + if (pbuf_stream->length == 0) { + return ERR_BUF; + } + + if (pbuf_copy_partial(pbuf_stream->pbuf, data, 1, pbuf_stream->offset) == 0) { + return ERR_BUF; + } + + pbuf_stream->offset++; + pbuf_stream->length--; + + return ERR_OK; +} + +err_t +snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data) +{ + return snmp_pbuf_stream_writebuf(pbuf_stream, &data, 1); +} + +err_t +snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len) +{ + if (pbuf_stream->length < buf_len) { + return ERR_BUF; + } + + if (pbuf_take_at(pbuf_stream->pbuf, buf, buf_len, pbuf_stream->offset) != ERR_OK) { + return ERR_BUF; + } + + pbuf_stream->offset += buf_len; + pbuf_stream->length -= buf_len; + + return ERR_OK; +} + +err_t +snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len) +{ + + if ((pbuf_stream == NULL) || (target_pbuf_stream == NULL)) { + return ERR_ARG; + } + if ((len > pbuf_stream->length) || (len > target_pbuf_stream->length)) { + return ERR_ARG; + } + + if (len == 0) { + len = LWIP_MIN(pbuf_stream->length, target_pbuf_stream->length); + } + + while (len > 0) { + u16_t chunk_len; + err_t err; + u16_t target_offset; + struct pbuf* pbuf = pbuf_skip(pbuf_stream->pbuf, pbuf_stream->offset, &target_offset); + + if ((pbuf == NULL) || (pbuf->len == 0)) { + return ERR_BUF; + } + + chunk_len = LWIP_MIN(len, pbuf->len); + err = snmp_pbuf_stream_writebuf(target_pbuf_stream, &((u8_t*)pbuf->payload)[target_offset], chunk_len); + if (err != ERR_OK) { + return err; + } + + pbuf_stream->offset += chunk_len; + pbuf_stream->length -= chunk_len; + len -= chunk_len; + } + + return ERR_OK; +} + +err_t +snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset) +{ + if ((offset < 0) || (offset > pbuf_stream->length)) { + /* we cannot seek backwards or forward behind stream end */ + return ERR_ARG; + } + + pbuf_stream->offset += (u16_t)offset; + pbuf_stream->length -= (u16_t)offset; + + return ERR_OK; +} + +err_t +snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset) +{ + s32_t rel_offset = offset - pbuf_stream->offset; + return snmp_pbuf_stream_seek(pbuf_stream, rel_offset); +} + +#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_pbuf_stream.h b/components/net/lwip-2.0.3/src/apps/snmp/snmp_pbuf_stream.h new file mode 100644 index 0000000000..9778de774e --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_pbuf_stream.h @@ -0,0 +1,73 @@ +/** + * @file + * SNMP pbuf stream wrapper (internal API, do not use in client code). + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#ifndef LWIP_HDR_APPS_SNMP_PBUF_STREAM_H +#define LWIP_HDR_APPS_SNMP_PBUF_STREAM_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP + +#include "lwip/err.h" +#include "lwip/pbuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct snmp_pbuf_stream +{ + struct pbuf* pbuf; + u16_t offset; + u16_t length; +}; + +err_t snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length); +err_t snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data); +err_t snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data); +err_t snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len); +err_t snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len); +err_t snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset); +err_t snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_APPS_SNMP_PBUF_STREAM_H */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_raw.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_raw.c new file mode 100644 index 0000000000..4a40864fc9 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_raw.c @@ -0,0 +1,100 @@ +/** + * @file + * SNMP RAW API frontend. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + */ + +#include "lwip/apps/snmp_opts.h" +#include "lwip/ip_addr.h" + +#if LWIP_SNMP && SNMP_USE_RAW + +#include "lwip/udp.h" +#include "lwip/ip.h" +#include "snmp_msg.h" + +/* lwIP UDP receive callback function */ +static void +snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + LWIP_UNUSED_ARG(arg); + + snmp_receive(pcb, p, addr, port); + + pbuf_free(p); +} + +err_t +snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) +{ + return udp_sendto((struct udp_pcb*)handle, p, dst, port); +} + +u8_t +snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) +{ + struct udp_pcb* udp_pcb = (struct udp_pcb*)handle; + struct netif *dst_if; + const ip_addr_t* dst_ip; + + LWIP_UNUSED_ARG(udp_pcb); /* unused in case of IPV4 only configuration */ + + ip_route_get_local_ip(&udp_pcb->local_ip, dst, dst_if, dst_ip); + + if ((dst_if != NULL) && (dst_ip != NULL)) { + ip_addr_copy(*result, *dst_ip); + return 1; + } else { + return 0; + } +} + +/** + * @ingroup snmp_core + * Starts SNMP Agent. + * Allocates UDP pcb and binds it to IP_ANY_TYPE port 161. + */ +void +snmp_init(void) +{ + err_t err; + + struct udp_pcb *snmp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ERROR("snmp_raw: no PCB", (snmp_pcb != NULL), return;); + + snmp_traps_handle = snmp_pcb; + + udp_recv(snmp_pcb, snmp_recv, (void *)SNMP_IN_PORT); + err = udp_bind(snmp_pcb, IP_ANY_TYPE, SNMP_IN_PORT); + LWIP_ERROR("snmp_raw: Unable to bind PCB", (err == ERR_OK), return;); +} + +#endif /* LWIP_SNMP && SNMP_USE_RAW */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_scalar.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_scalar.c new file mode 100644 index 0000000000..136c9eccd0 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_scalar.c @@ -0,0 +1,220 @@ +/** + * @file + * SNMP scalar node support implementation. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp_scalar.h" +#include "lwip/apps/snmp_core.h" + +static s16_t snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value); +static snmp_err_t snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value); +static snmp_err_t snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value); + +snmp_err_t +snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + const struct snmp_scalar_node* scalar_node = (const struct snmp_scalar_node*)(const void*)instance->node; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + /* scalar only has one dedicated instance: .0 */ + if ((instance->instance_oid.len != 1) || (instance->instance_oid.id[0] != 0)) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + instance->access = scalar_node->access; + instance->asn1_type = scalar_node->asn1_type; + instance->get_value = scalar_node->get_value; + instance->set_test = scalar_node->set_test; + instance->set_value = scalar_node->set_value; + return SNMP_ERR_NOERROR; +} + +snmp_err_t +snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + /* because our only instance is .0 we can only return a next instance if no instance oid is passed */ + if (instance->instance_oid.len == 0) { + instance->instance_oid.len = 1; + instance->instance_oid.id[0] = 0; + + return snmp_scalar_get_instance(root_oid, root_oid_len, instance); + } + + return SNMP_ERR_NOSUCHINSTANCE; +} + + +snmp_err_t +snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + if ((instance->instance_oid.len == 2) && (instance->instance_oid.id[1] == 0)) { + const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; + const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes; + u32_t i = 0; + + while (i < array_node->array_node_count) { + if (array_node_def->oid == instance->instance_oid.id[0]) { + break; + } + + array_node_def++; + i++; + } + + if (i < array_node->array_node_count) { + instance->access = array_node_def->access; + instance->asn1_type = array_node_def->asn1_type; + instance->get_value = snmp_scalar_array_get_value; + instance->set_test = snmp_scalar_array_set_test; + instance->set_value = snmp_scalar_array_set_value; + instance->reference.const_ptr = array_node_def; + + return SNMP_ERR_NOERROR; + } + } + + return SNMP_ERR_NOSUCHINSTANCE; +} + +snmp_err_t +snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; + const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes; + const struct snmp_scalar_array_node_def* result = NULL; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + if ((instance->instance_oid.len == 0) && (array_node->array_node_count > 0)) { + /* return node with lowest OID */ + u16_t i = 0; + + result = array_node_def; + array_node_def++; + + for (i = 1; i < array_node->array_node_count; i++) { + if (array_node_def->oid < result->oid) { + result = array_node_def; + } + array_node_def++; + } + } else if (instance->instance_oid.len >= 1) { + if (instance->instance_oid.len == 1) { + /* if we have the requested OID we return its instance, otherwise we search for the next available */ + u16_t i = 0; + while (i < array_node->array_node_count) { + if (array_node_def->oid == instance->instance_oid.id[0]) { + result = array_node_def; + break; + } + + array_node_def++; + i++; + } + } + if (result == NULL) { + u32_t oid_dist = 0xFFFFFFFFUL; + u16_t i = 0; + array_node_def = array_node->array_nodes; /* may be already at the end when if case before was executed without result -> reinitialize to start */ + while (i < array_node->array_node_count) { + if ((array_node_def->oid > instance->instance_oid.id[0]) && + ((u32_t)(array_node_def->oid - instance->instance_oid.id[0]) < oid_dist)) { + result = array_node_def; + oid_dist = array_node_def->oid - instance->instance_oid.id[0]; + } + + array_node_def++; + i++; + } + } + } + + if (result == NULL) { + /* nothing to return */ + return SNMP_ERR_NOSUCHINSTANCE; + } + + instance->instance_oid.len = 2; + instance->instance_oid.id[0] = result->oid; + instance->instance_oid.id[1] = 0; + + instance->access = result->access; + instance->asn1_type = result->asn1_type; + instance->get_value = snmp_scalar_array_get_value; + instance->set_test = snmp_scalar_array_set_test; + instance->set_value = snmp_scalar_array_set_value; + instance->reference.const_ptr = result; + + return SNMP_ERR_NOERROR; +} + +static s16_t +snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value) +{ + const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; + const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; + + return array_node->get_value(array_node_def, value); +} + +static snmp_err_t +snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value) +{ + const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; + const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; + + return array_node->set_test(array_node_def, value_len, value); +} + +static snmp_err_t +snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value) +{ + const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; + const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; + + return array_node->set_value(array_node_def, value_len, value); +} + +#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_table.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_table.c new file mode 100644 index 0000000000..63ca595633 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_table.c @@ -0,0 +1,343 @@ +/** + * @file + * SNMP table support implementation. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_table.h" +#include + +snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; + const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ + /* fixed row entry always has oid 1 */ + if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { + /* search column */ + const struct snmp_table_col_def* col_def = table_node->columns; + u16_t i = table_node->column_count; + while (i > 0) { + if (col_def->index == instance->instance_oid.id[1]) { + break; + } + + col_def++; + i--; + } + + if (i > 0) { + /* everything may be overwritten by get_cell_instance_method() in order to implement special handling for single columns/cells */ + instance->asn1_type = col_def->asn1_type; + instance->access = col_def->access; + instance->get_value = table_node->get_value; + instance->set_test = table_node->set_test; + instance->set_value = table_node->set_value; + + ret = table_node->get_cell_instance( + &(instance->instance_oid.id[1]), + &(instance->instance_oid.id[2]), + instance->instance_oid.len-2, + instance); + } + } + + return ret; +} + +snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node; + const struct snmp_table_col_def* col_def; + struct snmp_obj_id row_oid; + u32_t column = 0; + snmp_err_t result; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + /* check that first part of id is 0 or 1, referencing fixed row entry */ + if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { + return SNMP_ERR_NOSUCHINSTANCE; + } + if (instance->instance_oid.len > 1) { + column = instance->instance_oid.id[1]; + } + if (instance->instance_oid.len > 2) { + snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); + } else { + row_oid.len = 0; + } + + instance->get_value = table_node->get_value; + instance->set_test = table_node->set_test; + instance->set_value = table_node->set_value; + + /* resolve column and value */ + do { + u16_t i; + const struct snmp_table_col_def* next_col_def = NULL; + col_def = table_node->columns; + + for (i = 0; i < table_node->column_count; i++) { + if (col_def->index == column) { + next_col_def = col_def; + break; + } else if ((col_def->index > column) && ((next_col_def == NULL) || (col_def->index < next_col_def->index))) { + next_col_def = col_def; + } + col_def++; + } + + if (next_col_def == NULL) { + /* no further column found */ + return SNMP_ERR_NOSUCHINSTANCE; + } + + instance->asn1_type = next_col_def->asn1_type; + instance->access = next_col_def->access; + + result = table_node->get_next_cell_instance( + &next_col_def->index, + &row_oid, + instance); + + if (result == SNMP_ERR_NOERROR) { + col_def = next_col_def; + break; + } + + row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ + column = next_col_def->index + 1; + } while (1); + + /* build resulting oid */ + instance->instance_oid.len = 2; + instance->instance_oid.id[0] = 1; + instance->instance_oid.id[1] = col_def->index; + snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); + + return SNMP_ERR_NOERROR; +} + + +snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; + const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ + /* fixed row entry always has oid 1 */ + if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { + ret = table_node->get_cell_value( + &(instance->instance_oid.id[1]), + &(instance->instance_oid.id[2]), + instance->instance_oid.len-2, + &instance->reference, + &instance->reference_len); + + if (ret == SNMP_ERR_NOERROR) { + /* search column */ + const struct snmp_table_simple_col_def* col_def = table_node->columns; + u32_t i = table_node->column_count; + while (i > 0) { + if (col_def->index == instance->instance_oid.id[1]) { + break; + } + + col_def++; + i--; + } + + if (i > 0) { + instance->asn1_type = col_def->asn1_type; + instance->access = SNMP_NODE_INSTANCE_READ_ONLY; + instance->set_test = NULL; + instance->set_value = NULL; + + switch (col_def->data_type) { + case SNMP_VARIANT_VALUE_TYPE_U32: + instance->get_value = snmp_table_extract_value_from_u32ref; + break; + case SNMP_VARIANT_VALUE_TYPE_S32: + instance->get_value = snmp_table_extract_value_from_s32ref; + break; + case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ + case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: + instance->get_value = snmp_table_extract_value_from_refconstptr; + break; + default: + LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); + return SNMP_ERR_GENERROR; + } + + ret = SNMP_ERR_NOERROR; + } else { + ret = SNMP_ERR_NOSUCHINSTANCE; + } + } + } + + return ret; +} + +snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node; + const struct snmp_table_simple_col_def* col_def; + struct snmp_obj_id row_oid; + u32_t column = 0; + snmp_err_t result; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + /* check that first part of id is 0 or 1, referencing fixed row entry */ + if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { + return SNMP_ERR_NOSUCHINSTANCE; + } + if (instance->instance_oid.len > 1) { + column = instance->instance_oid.id[1]; + } + if (instance->instance_oid.len > 2) { + snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); + } else { + row_oid.len = 0; + } + + /* resolve column and value */ + do { + u32_t i; + const struct snmp_table_simple_col_def* next_col_def = NULL; + col_def = table_node->columns; + + for (i = 0; i < table_node->column_count; i++) { + if (col_def->index == column) { + next_col_def = col_def; + break; + } else if ((col_def->index > column) && ((next_col_def == NULL) || + (col_def->index < next_col_def->index))) { + next_col_def = col_def; + } + col_def++; + } + + if (next_col_def == NULL) { + /* no further column found */ + return SNMP_ERR_NOSUCHINSTANCE; + } + + result = table_node->get_next_cell_instance_and_value( + &next_col_def->index, + &row_oid, + &instance->reference, + &instance->reference_len); + + if (result == SNMP_ERR_NOERROR) { + col_def = next_col_def; + break; + } + + row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ + column = next_col_def->index + 1; + } + while (1); + + instance->asn1_type = col_def->asn1_type; + instance->access = SNMP_NODE_INSTANCE_READ_ONLY; + instance->set_test = NULL; + instance->set_value = NULL; + + switch (col_def->data_type) { + case SNMP_VARIANT_VALUE_TYPE_U32: + instance->get_value = snmp_table_extract_value_from_u32ref; + break; + case SNMP_VARIANT_VALUE_TYPE_S32: + instance->get_value = snmp_table_extract_value_from_s32ref; + break; + case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ + case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: + instance->get_value = snmp_table_extract_value_from_refconstptr; + break; + default: + LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); + return SNMP_ERR_GENERROR; + } + + /* build resulting oid */ + instance->instance_oid.len = 2; + instance->instance_oid.id[0] = 1; + instance->instance_oid.id[1] = col_def->index; + snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); + + return SNMP_ERR_NOERROR; +} + + +s16_t +snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value) +{ + s32_t *dst = (s32_t*)value; + *dst = instance->reference.s32; + return sizeof(*dst); +} + +s16_t +snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value) +{ + u32_t *dst = (u32_t*)value; + *dst = instance->reference.u32; + return sizeof(*dst); +} + +s16_t +snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value) +{ + MEMCPY(value, instance->reference.const_ptr, instance->reference_len); + return (u16_t)instance->reference_len; +} + +#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_threadsync.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_threadsync.c new file mode 100644 index 0000000000..204f265dc8 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_threadsync.c @@ -0,0 +1,219 @@ +/** + * @file + * SNMP thread synchronization implementation. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP && (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp_threadsync.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/sys.h" +#include + +static void +call_synced_function(struct threadsync_data *call_data, snmp_threadsync_called_fn fn) +{ + sys_mutex_lock(&call_data->threadsync_node->instance->sem_usage_mutex); + call_data->threadsync_node->instance->sync_fn(fn, call_data); + sys_sem_wait(&call_data->threadsync_node->instance->sem); + sys_mutex_unlock(&call_data->threadsync_node->instance->sem_usage_mutex); +} + +static void +threadsync_get_value_synced(void *ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + + call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static s16_t +threadsync_get_value(struct snmp_node_instance* instance, void* value) +{ + struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; + + call_data->arg1.value = value; + call_synced_function(call_data, threadsync_get_value_synced); + + return call_data->retval.s16; +} + +static void +threadsync_set_test_synced(void *ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + + call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static snmp_err_t +threadsync_set_test(struct snmp_node_instance* instance, u16_t len, void *value) +{ + struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; + + call_data->arg1.value = value; + call_data->arg2.len = len; + call_synced_function(call_data, threadsync_set_test_synced); + + return call_data->retval.err; +} + +static void +threadsync_set_value_synced(void *ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + + call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static snmp_err_t +threadsync_set_value(struct snmp_node_instance* instance, u16_t len, void *value) +{ + struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; + + call_data->arg1.value = value; + call_data->arg2.len = len; + call_synced_function(call_data, threadsync_set_value_synced); + + return call_data->retval.err; +} + +static void +threadsync_release_instance_synced(void* ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + + call_data->proxy_instance.release_instance(&call_data->proxy_instance); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static void +threadsync_release_instance(struct snmp_node_instance *instance) +{ + struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; + + if (call_data->proxy_instance.release_instance != NULL) { + call_synced_function(call_data, threadsync_release_instance_synced); + } +} + +static void +get_instance_synced(void* ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node; + + call_data->retval.err = leaf->get_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static void +get_next_instance_synced(void* ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node; + + call_data->retval.err = leaf->get_next_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static snmp_err_t +do_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance, snmp_threadsync_called_fn fn) +{ + const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node*)(const void*)instance->node; + struct threadsync_data *call_data = &threadsync_node->instance->data; + + if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) { + LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID")); + return SNMP_ERR_NOSUCHINSTANCE; + } + + memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance)); + + instance->reference.ptr = call_data; + snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len); + + call_data->proxy_instance.node = &threadsync_node->target->node; + call_data->threadsync_node = threadsync_node; + + call_data->arg1.root_oid = root_oid; + call_data->arg2.root_oid_len = root_oid_len; + call_synced_function(call_data, fn); + + if (call_data->retval.err == SNMP_ERR_NOERROR) { + instance->access = call_data->proxy_instance.access; + instance->asn1_type = call_data->proxy_instance.asn1_type; + instance->release_instance = threadsync_release_instance; + instance->get_value = (call_data->proxy_instance.get_value != NULL)? threadsync_get_value : NULL; + instance->set_value = (call_data->proxy_instance.set_value != NULL)? threadsync_set_value : NULL; + instance->set_test = (call_data->proxy_instance.set_test != NULL)? threadsync_set_test : NULL; + snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len); + } + + return call_data->retval.err; +} + +snmp_err_t +snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + return do_sync(root_oid, root_oid_len, instance, get_instance_synced); +} + +snmp_err_t +snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + return do_sync(root_oid, root_oid_len, instance, get_next_instance_synced); +} + +/** Initializes thread synchronization instance */ +void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn) +{ + err_t err = sys_mutex_new(&instance->sem_usage_mutex); + LWIP_ASSERT("Failed to set up mutex", err == ERR_OK); + err = sys_sem_new(&instance->sem, 0); + LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK); + instance->sync_fn = sync_fn; +} + +#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmp_traps.c b/components/net/lwip-2.0.3/src/apps/snmp/snmp_traps.c new file mode 100644 index 0000000000..0d2df64991 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmp_traps.c @@ -0,0 +1,445 @@ +/** + * @file + * SNMPv1 traps implementation. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * Christiaan Simons + * + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "lwip/snmp.h" +#include "lwip/sys.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "snmp_msg.h" +#include "snmp_asn1.h" +#include "snmp_core_priv.h" + +struct snmp_msg_trap +{ + /* source enterprise ID (sysObjectID) */ + const struct snmp_obj_id *enterprise; + /* source IP address, raw network order format */ + ip_addr_t sip; + /* generic trap code */ + u32_t gen_trap; + /* specific trap code */ + u32_t spc_trap; + /* timestamp */ + u32_t ts; + /* snmp_version */ + u32_t snmp_version; + + /* output trap lengths used in ASN encoding */ + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding sequence length */ + u16_t seqlen; + /* encoding varbinds sequence length */ + u16_t vbseqlen; +}; + +static u16_t snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds); +static u16_t snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len); +static void snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream); +static void snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds); + +/** Agent community string for sending traps */ +extern const char *snmp_community_trap; + +void* snmp_traps_handle; + +struct snmp_trap_dst +{ + /* destination IP address in network order */ + ip_addr_t dip; + /* set to 0 when disabled, >0 when enabled */ + u8_t enable; +}; +static struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; + +static u8_t snmp_auth_traps_enabled = 0; + +/** + * @ingroup snmp_traps + * Sets enable switch for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param enable switch if 0 destination is disabled >0 enabled. + */ +void +snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) { + trap_dst[dst_idx].enable = enable; + } +} + +/** + * @ingroup snmp_traps + * Sets IPv4 address for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param dst IPv4 address in host order. + */ +void +snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) { + ip_addr_set(&trap_dst[dst_idx].dip, dst); + } +} + +/** + * @ingroup snmp_traps + * Enable/disable authentication traps + */ +void +snmp_set_auth_traps_enabled(u8_t enable) +{ + snmp_auth_traps_enabled = enable; +} + +/** + * @ingroup snmp_traps + * Get authentication traps enabled state + */ +u8_t +snmp_get_auth_traps_enabled(void) +{ + return snmp_auth_traps_enabled; +} + + +/** + * @ingroup snmp_traps + * Sends a generic or enterprise specific trap message. + * + * @param eoid points to enterprise object identifier + * @param generic_trap is the trap code + * @param specific_trap used for enterprise traps when generic_trap == 6 + * @param varbinds linked list of varbinds to be sent + * @return ERR_OK when success, ERR_MEM if we're out of memory + * + * @note the use of the enterprise identifier field + * is per RFC1215. + * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps + * and .iso.org.dod.internet.private.enterprises.yourenterprise + * (sysObjectID) for specific traps. + */ +err_t +snmp_send_trap(const struct snmp_obj_id* eoid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds) +{ + struct snmp_msg_trap trap_msg; + struct snmp_trap_dst *td; + struct pbuf *p; + u16_t i, tot_len; + err_t err = ERR_OK; + + trap_msg.snmp_version = 0; + + for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) { + if ((td->enable != 0) && !ip_addr_isany(&td->dip)) { + /* lookup current source address for this dst */ + if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) { + if (eoid == NULL) { + trap_msg.enterprise = snmp_get_device_enterprise_oid(); + } else { + trap_msg.enterprise = eoid; + } + + trap_msg.gen_trap = generic_trap; + if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) { + trap_msg.spc_trap = specific_trap; + } else { + trap_msg.spc_trap = 0; + } + + MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts); + + /* pass 0, calculate length fields */ + tot_len = snmp_trap_varbind_sum(&trap_msg, varbinds); + tot_len = snmp_trap_header_sum(&trap_msg, tot_len); + + /* allocate pbuf(s) */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM); + if (p != NULL) { + struct snmp_pbuf_stream pbuf_stream; + snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len); + + /* pass 1, encode packet ino the pbuf(s) */ + snmp_trap_header_enc(&trap_msg, &pbuf_stream); + snmp_trap_varbind_enc(&trap_msg, &pbuf_stream, varbinds); + + snmp_stats.outtraps++; + snmp_stats.outpkts++; + + /** send to the TRAP destination */ + snmp_sendto(snmp_traps_handle, p, &td->dip, SNMP_TRAP_PORT); + pbuf_free(p); + } else { + err = ERR_MEM; + } + } else { + /* routing error */ + err = ERR_RTE; + } + } + } + return err; +} + +/** + * @ingroup snmp_traps + * Send generic SNMP trap + */ +err_t +snmp_send_trap_generic(s32_t generic_trap) +{ + static const struct snmp_obj_id oid = { 7, { 1, 3, 6, 1, 2, 1, 11 } }; + return snmp_send_trap(&oid, generic_trap, 0, NULL); +} + +/** + * @ingroup snmp_traps + * Send specific SNMP trap with variable bindings + */ +err_t +snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds) +{ + return snmp_send_trap(NULL, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbinds); +} + +/** + * @ingroup snmp_traps + * Send coldstart trap + */ +void +snmp_coldstart_trap(void) +{ + snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART); +} + +/** + * @ingroup snmp_traps + * Send authentication failure trap (used internally by agent) + */ +void +snmp_authfail_trap(void) +{ + if (snmp_auth_traps_enabled != 0) { + snmp_send_trap_generic(SNMP_GENTRAP_AUTH_FAILURE); + } +} + +static u16_t +snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds) +{ + struct snmp_varbind *varbind; + u16_t tot_len; + u8_t tot_len_len; + + tot_len = 0; + varbind = varbinds; + while (varbind != NULL) { + struct snmp_varbind_len len; + + if (snmp_varbind_length(varbind, &len) == ERR_OK) { + tot_len += 1 + len.vb_len_len + len.vb_value_len; + } + + varbind = varbind->next; + } + + trap->vbseqlen = tot_len; + snmp_asn1_enc_length_cnt(trap->vbseqlen, &tot_len_len); + tot_len += 1 + tot_len_len; + + return tot_len; +} + +/** + * Sums trap header field lengths from tail to head and + * returns trap_header_lengths for second encoding pass. + * + * @param trap Trap message + * @param vb_len varbind-list length + * @return the required length for encoding the trap header + */ +static u16_t +snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len) +{ + u16_t tot_len; + u16_t len; + u8_t lenlen; + + tot_len = vb_len; + + snmp_asn1_enc_u32t_cnt(trap->ts, &len); + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len); + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len); + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + if (IP_IS_V6_VAL(trap->sip)) { +#if LWIP_IPV6 + len = sizeof(ip_2_ip6(&trap->sip)->addr); +#endif + } else { +#if LWIP_IPV4 + len = sizeof(ip_2_ip4(&trap->sip)->addr); +#endif + } + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len); + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + trap->pdulen = tot_len; + snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen); + tot_len += 1 + lenlen; + + trap->comlen = (u16_t)LWIP_MIN(strlen(snmp_community_trap), 0xFFFF); + snmp_asn1_enc_length_cnt(trap->comlen, &lenlen); + tot_len += 1 + lenlen + trap->comlen; + + snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len); + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + trap->seqlen = tot_len; + snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen); + tot_len += 1 + lenlen; + + return tot_len; +} + +static void +snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds) +{ + struct snmp_asn1_tlv tlv; + struct snmp_varbind *varbind; + + varbind = varbinds; + + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->vbseqlen); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + + while (varbind != NULL) { + snmp_append_outbound_varbind(pbuf_stream, varbind); + + varbind = varbind->next; + } +} + +/** + * Encodes trap header from head to tail. + */ +static void +snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream) +{ + struct snmp_asn1_tlv tlv; + + /* 'Message' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + + /* version */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version); + + /* community */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)snmp_community_trap, trap->comlen); + + /* 'PDU' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + + /* object ID */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0); + snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len); + + /* IP addr */ + if (IP_IS_V6_VAL(trap->sip)) { +#if LWIP_IPV6 + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr)); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr)); +#endif + } else { +#if LWIP_IPV4 + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr)); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr)); +#endif + } + + /* trap length */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap); + + /* specific trap */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap); + + /* timestamp */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0); + snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts); +} + +#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmpv3.c b/components/net/lwip-2.0.3/src/apps/snmp/snmpv3.c new file mode 100644 index 0000000000..69fb3a0aaf --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmpv3.c @@ -0,0 +1,136 @@ +/** + * @file + * Additional SNMPv3 functionality RFC3414 and RFC3826. + */ + +/* + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Elias Oenal + */ + +#include "snmpv3_priv.h" +#include "lwip/apps/snmpv3.h" +#include "lwip/sys.h" +#include + +#if LWIP_SNMP && LWIP_SNMP_V3 + +#ifdef LWIP_SNMPV3_INCLUDE_ENGINE +#include LWIP_SNMPV3_INCLUDE_ENGINE +#endif + +#define SNMP_MAX_TIME_BOOT 2147483647UL + +/** Call this if engine has been changed. Has to reset boots, see below */ +void +snmpv3_engine_id_changed(void) +{ + snmpv3_set_engine_boots(0); +} + +/** According to RFC3414 2.2.2. + * + * The number of times that the SNMP engine has + * (re-)initialized itself since snmpEngineID + * was last configured. + */ +u32_t +snmpv3_get_engine_boots_internal(void) +{ + if (snmpv3_get_engine_boots() == 0 || + snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT) { + return snmpv3_get_engine_boots(); + } + + snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); + return snmpv3_get_engine_boots(); +} + +/** RFC3414 2.2.2. + * + * Once the timer reaches 2147483647 it gets reset to zero and the + * engine boot ups get incremented. + */ +u32_t +snmpv3_get_engine_time_internal(void) +{ + if (snmpv3_get_engine_time() >= SNMP_MAX_TIME_BOOT) { + snmpv3_reset_engine_time(); + + if (snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT - 1) { + snmpv3_set_engine_boots(snmpv3_get_engine_boots() + 1); + } else { + snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); + } + } + + return snmpv3_get_engine_time(); +} + +#if LWIP_SNMP_V3_CRYPTO + +/* This function ignores the byte order suggestion in RFC3414 + * since it simply doesn't influence the effectiveness of an IV. + * + * Implementing RFC3826 priv param algorithm if LWIP_RAND is available. + * + * @todo: This is a potential thread safety issue. + */ +err_t +snmpv3_build_priv_param(u8_t* priv_param) +{ +#ifdef LWIP_RAND /* Based on RFC3826 */ + static u8_t init; + static u32_t priv1, priv2; + + /* Lazy initialisation */ + if (init == 0) { + init = 1; + priv1 = LWIP_RAND(); + priv2 = LWIP_RAND(); + } + + SMEMCPY(&priv_param[0], &priv1, sizeof(priv1)); + SMEMCPY(&priv_param[4], &priv2, sizeof(priv2)); + + /* Emulate 64bit increment */ + priv1++; + if (!priv1) { /* Overflow */ + priv2++; + } +#else /* Based on RFC3414 */ + static u32_t ctr; + u32_t boots = LWIP_SNMPV3_GET_ENGINE_BOOTS(); + SMEMCPY(&priv_param[0], &boots, 4); + SMEMCPY(&priv_param[4], &ctr, 4); + ctr++; +#endif + return ERR_OK; +} +#endif /* LWIP_SNMP_V3_CRYPTO */ + +#endif diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmpv3_dummy.c b/components/net/lwip-2.0.3/src/apps/snmp/snmpv3_dummy.c new file mode 100644 index 0000000000..bdfe844994 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmpv3_dummy.c @@ -0,0 +1,145 @@ +/** + * @file + * Dummy SNMPv3 functions. + */ + +/* + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Elias Oenal + * Dirk Ziegelmeier + */ + +#include "lwip/apps/snmpv3.h" +#include "snmpv3_priv.h" +#include +#include "lwip/err.h" + +#if LWIP_SNMP && LWIP_SNMP_V3 + +/** + * @param username is a pointer to a string. + * @param auth_algo is a pointer to u8_t. The implementation has to set this if user was found. + * @param auth_key is a pointer to a pointer to a string. Implementation has to set this if user was found. + * @param priv_algo is a pointer to u8_t. The implementation has to set this if user was found. + * @param priv_key is a pointer to a pointer to a string. Implementation has to set this if user was found. + */ +err_t +snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key) +{ + const char* engine_id; + u8_t engine_id_len; + + if(strlen(username) == 0) { + return ERR_OK; + } + + if(memcmp(username, "lwip", 4) != 0) { + return ERR_VAL; + } + + snmpv3_get_engine_id(&engine_id, &engine_id_len); + + if(auth_key != NULL) { + snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10, + (const u8_t*)engine_id, engine_id_len, + auth_key); + *auth_algo = SNMP_V3_AUTH_ALGO_SHA; + } + if(priv_key != NULL) { + snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10, + (const u8_t*)engine_id, engine_id_len, + priv_key); + *priv_algo = SNMP_V3_PRIV_ALGO_DES; + } + return ERR_OK; +} + +/** + * Get engine ID from persistence + * @param id + * @param len + */ +void +snmpv3_get_engine_id(const char **id, u8_t *len) +{ + *id = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"; + *len = 12; +} + +/** + * Store engine ID in persistence + * @param id + * @param len + */ +err_t +snmpv3_set_engine_id(const char *id, u8_t len) +{ + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(len); + return ERR_OK; +} + +/** + * Get engine boots from persistence. Must be increased on each boot. + * @return + */ +u32_t +snmpv3_get_engine_boots(void) +{ + return 0; +} + +/** + * Store engine boots in persistence + * @param boots + */ +void +snmpv3_set_engine_boots(u32_t boots) +{ + LWIP_UNUSED_ARG(boots); +} + +/** + * RFC3414 2.2.2. + * Once the timer reaches 2147483647 it gets reset to zero and the + * engine boot ups get incremented. + */ +u32_t +snmpv3_get_engine_time(void) +{ + return 0; +} + +/** + * Reset current engine time to 0 + */ +void +snmpv3_reset_engine_time(void) +{ +} + +#endif /* LWIP_SNMP && LWIP_SNMP_V3 */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmpv3_mbedtls.c b/components/net/lwip-2.0.3/src/apps/snmp/snmpv3_mbedtls.c new file mode 100644 index 0000000000..0b1eefb87e --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmpv3_mbedtls.c @@ -0,0 +1,331 @@ +/** + * @file + * SNMPv3 crypto/auth functions implemented for ARM mbedtls. + */ + +/* + * Copyright (c) 2016 Elias Oenal and Dirk Ziegelmeier. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Elias Oenal + * Dirk Ziegelmeier + */ + +#include "lwip/apps/snmpv3.h" +#include "snmpv3_priv.h" +#include "lwip/arch.h" +#include "snmp_msg.h" +#include "lwip/sys.h" +#include + +#if LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS + +#include "mbedtls/md.h" +#include "mbedtls/cipher.h" + +#include "mbedtls/md5.h" +#include "mbedtls/sha1.h" + +err_t +snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length, + const u8_t* key, u8_t algo, u8_t* hmac_out) +{ + u32_t i; + u8_t key_len; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t ctx; + struct snmp_pbuf_stream read_stream; + snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); + + if (algo == SNMP_V3_AUTH_ALGO_MD5) { + md_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); + key_len = SNMP_V3_MD5_LEN; + } else if (algo == SNMP_V3_AUTH_ALGO_SHA) { + md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + key_len = SNMP_V3_SHA_LEN; + } else { + return ERR_ARG; + } + + mbedtls_md_init(&ctx); + if(mbedtls_md_setup(&ctx, md_info, 1) != 0) { + return ERR_ARG; + } + + if (mbedtls_md_hmac_starts(&ctx, key, key_len) != 0) { + goto free_md; + } + + for (i = 0; i < length; i++) { + u8_t byte; + + if (snmp_pbuf_stream_read(&read_stream, &byte)) { + goto free_md; + } + + if (mbedtls_md_hmac_update(&ctx, &byte, 1) != 0) { + goto free_md; + } + } + + if (mbedtls_md_hmac_finish(&ctx, hmac_out) != 0) { + goto free_md; + } + + mbedtls_md_free(&ctx); + return ERR_OK; + +free_md: + mbedtls_md_free(&ctx); + return ERR_ARG; +} + +#if LWIP_SNMP_V3_CRYPTO + +err_t +snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, + const u8_t* key, const u8_t* priv_param, const u32_t engine_boots, + const u32_t engine_time, u8_t algo, u8_t mode) +{ + size_t i; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + + struct snmp_pbuf_stream read_stream; + struct snmp_pbuf_stream write_stream; + snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); + snmp_pbuf_stream_init(&write_stream, stream->pbuf, stream->offset, stream->length); + mbedtls_cipher_init(&ctx); + + if (algo == SNMP_V3_PRIV_ALGO_DES) { + u8_t iv_local[8]; + u8_t out_bytes[8]; + size_t out_len; + + /* RFC 3414 mandates padding for DES */ + if ((length & 0x07) != 0) { + return ERR_ARG; + } + + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_CBC); + if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) { + return ERR_ARG; + } + if(mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_NONE) != 0) { + return ERR_ARG; + } + if(mbedtls_cipher_setkey(&ctx, key, 8*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { + goto error; + } + + /* Prepare IV */ + for (i = 0; i < LWIP_ARRAYSIZE(iv_local); i++) { + iv_local[i] = priv_param[i] ^ key[i + 8]; + } + if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { + goto error; + } + + for (i = 0; i < length; i += 8) { + size_t j; + u8_t in_bytes[8]; + out_len = LWIP_ARRAYSIZE(out_bytes) ; + + for (j = 0; j < LWIP_ARRAYSIZE(in_bytes); j++) { + snmp_pbuf_stream_read(&read_stream, &in_bytes[j]); + } + + if(mbedtls_cipher_update(&ctx, in_bytes, LWIP_ARRAYSIZE(in_bytes), out_bytes, &out_len) != 0) { + goto error; + } + + snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len); + } + + out_len = LWIP_ARRAYSIZE(out_bytes); + if(mbedtls_cipher_finish(&ctx, out_bytes, &out_len) != 0) { + goto error; + } + snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len); + } else if (algo == SNMP_V3_PRIV_ALGO_AES) { + u8_t iv_local[16]; + + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CFB128); + if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) { + return ERR_ARG; + } + if(mbedtls_cipher_setkey(&ctx, key, 16*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { + goto error; + } + + /* + * IV is the big endian concatenation of boots, + * uptime and priv param - see RFC3826. + */ + iv_local[0 + 0] = (engine_boots >> 24) & 0xFF; + iv_local[0 + 1] = (engine_boots >> 16) & 0xFF; + iv_local[0 + 2] = (engine_boots >> 8) & 0xFF; + iv_local[0 + 3] = (engine_boots >> 0) & 0xFF; + iv_local[4 + 0] = (engine_time >> 24) & 0xFF; + iv_local[4 + 1] = (engine_time >> 16) & 0xFF; + iv_local[4 + 2] = (engine_time >> 8) & 0xFF; + iv_local[4 + 3] = (engine_time >> 0) & 0xFF; + SMEMCPY(iv_local + 8, priv_param, 8); + if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { + goto error; + } + + for (i = 0; i < length; i++) { + u8_t in_byte; + u8_t out_byte; + size_t out_len = sizeof(out_byte); + + snmp_pbuf_stream_read(&read_stream, &in_byte); + if(mbedtls_cipher_update(&ctx, &in_byte, sizeof(in_byte), &out_byte, &out_len) != 0) { + goto error; + } + snmp_pbuf_stream_write(&write_stream, out_byte); + } + } else { + return ERR_ARG; + } + + mbedtls_cipher_free(&ctx); + return ERR_OK; + +error: + mbedtls_cipher_free(&ctx); + return ERR_OK; +} + +#endif /* LWIP_SNMP_V3_CRYPTO */ + +/* A.2.1. Password to Key Sample Code for MD5 */ +void +snmpv3_password_to_key_md5( + const u8_t *password, /* IN */ + u8_t passwordlen, /* IN */ + const u8_t *engineID, /* IN - pointer to snmpEngineID */ + u8_t engineLength,/* IN - length of snmpEngineID */ + u8_t *key) /* OUT - pointer to caller 16-octet buffer */ +{ + mbedtls_md5_context MD; + u8_t *cp, password_buf[64]; + u32_t password_index = 0; + u8_t i; + u32_t count = 0; + + mbedtls_md5_init(&MD); /* initialize MD5 */ + mbedtls_md5_starts(&MD); + + /**********************************************/ + /* Use while loop until we've done 1 Megabyte */ + /**********************************************/ + while (count < 1048576) { + cp = password_buf; + for (i = 0; i < 64; i++) { + /*************************************************/ + /* Take the next octet of the password, wrapping */ + /* to the beginning of the password as necessary.*/ + /*************************************************/ + *cp++ = password[password_index++ % passwordlen]; + } + mbedtls_md5_update(&MD, password_buf, 64); + count += 64; + } + mbedtls_md5_finish(&MD, key); /* tell MD5 we're done */ + + /*****************************************************/ + /* Now localize the key with the engineID and pass */ + /* through MD5 to produce final key */ + /* May want to ensure that engineLength <= 32, */ + /* otherwise need to use a buffer larger than 64 */ + /*****************************************************/ + SMEMCPY(password_buf, key, 16); + MEMCPY(password_buf + 16, engineID, engineLength); + SMEMCPY(password_buf + 16 + engineLength, key, 16); + + mbedtls_md5_starts(&MD); + mbedtls_md5_update(&MD, password_buf, 32 + engineLength); + mbedtls_md5_finish(&MD, key); + + mbedtls_md5_free(&MD); + return; +} + +/* A.2.2. Password to Key Sample Code for SHA */ +void +snmpv3_password_to_key_sha( + const u8_t *password, /* IN */ + u8_t passwordlen, /* IN */ + const u8_t *engineID, /* IN - pointer to snmpEngineID */ + u8_t engineLength,/* IN - length of snmpEngineID */ + u8_t *key) /* OUT - pointer to caller 20-octet buffer */ +{ + mbedtls_sha1_context SH; + u8_t *cp, password_buf[72]; + u32_t password_index = 0; + u8_t i; + u32_t count = 0; + + mbedtls_sha1_init(&SH); /* initialize SHA */ + mbedtls_sha1_starts(&SH); + + /**********************************************/ + /* Use while loop until we've done 1 Megabyte */ + /**********************************************/ + while (count < 1048576) { + cp = password_buf; + for (i = 0; i < 64; i++) { + /*************************************************/ + /* Take the next octet of the password, wrapping */ + /* to the beginning of the password as necessary.*/ + /*************************************************/ + *cp++ = password[password_index++ % passwordlen]; + } + mbedtls_sha1_update(&SH, password_buf, 64); + count += 64; + } + mbedtls_sha1_finish(&SH, key); /* tell SHA we're done */ + + /*****************************************************/ + /* Now localize the key with the engineID and pass */ + /* through SHA to produce final key */ + /* May want to ensure that engineLength <= 32, */ + /* otherwise need to use a buffer larger than 72 */ + /*****************************************************/ + SMEMCPY(password_buf, key, 20); + MEMCPY(password_buf + 20, engineID, engineLength); + SMEMCPY(password_buf + 20 + engineLength, key, 20); + + mbedtls_sha1_starts(&SH); + mbedtls_sha1_update(&SH, password_buf, 40 + engineLength); + mbedtls_sha1_finish(&SH, key); + + mbedtls_sha1_free(&SH); + return; +} + +#endif /* LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS */ diff --git a/components/net/lwip-2.0.3/src/apps/snmp/snmpv3_priv.h b/components/net/lwip-2.0.3/src/apps/snmp/snmpv3_priv.h new file mode 100644 index 0000000000..b87666da99 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/snmp/snmpv3_priv.h @@ -0,0 +1,66 @@ +/** + * @file + * Additional SNMPv3 functionality RFC3414 and RFC3826 (internal API, do not use in client code). + */ + +/* + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Elias Oenal + */ + +#ifndef LWIP_HDR_APPS_SNMP_V3_PRIV_H +#define LWIP_HDR_APPS_SNMP_V3_PRIV_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP && LWIP_SNMP_V3 + +#include "snmp_pbuf_stream.h" + +/* According to RFC 3411 */ +#define SNMP_V3_MAX_ENGINE_ID_LENGTH 32 +#define SNMP_V3_MAX_USER_LENGTH 32 + +#define SNMP_V3_MAX_AUTH_PARAM_LENGTH 12 +#define SNMP_V3_MAX_PRIV_PARAM_LENGTH 8 + +#define SNMP_V3_AUTH_FLAG 0x01 +#define SNMP_V3_PRIV_FLAG 0x02 + +#define SNMP_V3_MD5_LEN 16 +#define SNMP_V3_SHA_LEN 20 + +u32_t snmpv3_get_engine_boots_internal(void); +u32_t snmpv3_get_engine_time_internal(void); +err_t snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key, u8_t algo, u8_t* hmac_out); +err_t snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key, + const u8_t* priv_param, const u32_t engine_boots, const u32_t engine_time, u8_t algo, u8_t mode); +err_t snmpv3_build_priv_param(u8_t* priv_param); + +#endif + +#endif /* LWIP_HDR_APPS_SNMP_V3_PRIV_H */ diff --git a/components/net/lwip-2.0.3/src/apps/sntp/sntp.c b/components/net/lwip-2.0.3/src/apps/sntp/sntp.c new file mode 100644 index 0000000000..71b2abedb8 --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/sntp/sntp.c @@ -0,0 +1,727 @@ +/** + * @file + * SNTP client module + */ + +/* + * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Frédéric Bernon, Simon Goldschmidt + */ + + +/** + * @defgroup sntp SNTP + * @ingroup apps + * + * This is simple "SNTP" client for the lwIP raw API. + * It is a minimal implementation of SNTPv4 as specified in RFC 4330. + * + * For a list of some public NTP servers, see this link : + * http://support.ntp.org/bin/view/Servers/NTPPoolServers + * + * @todo: + * - set/change servers at runtime + * - complete SNTP_CHECK_RESPONSE checks 3 and 4 + */ + +#include "lwip/apps/sntp.h" + +#include "lwip/opt.h" +#include "lwip/timeouts.h" +#include "lwip/udp.h" +#include "lwip/dns.h" +#include "lwip/ip_addr.h" +#include "lwip/pbuf.h" +#include "lwip/dhcp.h" + +#include +#include + +#if LWIP_UDP + +/* Handle support for more than one server via SNTP_MAX_SERVERS */ +#if SNTP_MAX_SERVERS > 1 +#define SNTP_SUPPORT_MULTIPLE_SERVERS 1 +#else /* NTP_MAX_SERVERS > 1 */ +#define SNTP_SUPPORT_MULTIPLE_SERVERS 0 +#endif /* NTP_MAX_SERVERS > 1 */ + +#if (SNTP_UPDATE_DELAY < 15000) && !defined(SNTP_SUPPRESS_DELAY_CHECK) +#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds (define SNTP_SUPPRESS_DELAY_CHECK to disable this error)!" +#endif + +/* Configure behaviour depending on microsecond or second precision */ +#ifdef SNTP_SET_SYSTEM_TIME_US +#define SNTP_CALC_TIME_US 1 +#define SNTP_RECEIVE_TIME_SIZE 2 +#else +#define SNTP_SET_SYSTEM_TIME_US(sec, us) +#define SNTP_CALC_TIME_US 0 +#define SNTP_RECEIVE_TIME_SIZE 1 +#endif + + +/* the various debug levels for this file */ +#define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE) +#define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE) +#define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) +#define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS) + +#define SNTP_ERR_KOD 1 + +/* SNTP protocol defines */ +#define SNTP_MSG_LEN 48 + +#define SNTP_OFFSET_LI_VN_MODE 0 +#define SNTP_LI_MASK 0xC0 +#define SNTP_LI_NO_WARNING 0x00 +#define SNTP_LI_LAST_MINUTE_61_SEC 0x01 +#define SNTP_LI_LAST_MINUTE_59_SEC 0x02 +#define SNTP_LI_ALARM_CONDITION 0x03 /* (clock not synchronized) */ + +#define SNTP_VERSION_MASK 0x38 +#define SNTP_VERSION (4/* NTP Version 4*/<<3) + +#define SNTP_MODE_MASK 0x07 +#define SNTP_MODE_CLIENT 0x03 +#define SNTP_MODE_SERVER 0x04 +#define SNTP_MODE_BROADCAST 0x05 + +#define SNTP_OFFSET_STRATUM 1 +#define SNTP_STRATUM_KOD 0x00 + +#define SNTP_OFFSET_ORIGINATE_TIME 24 +#define SNTP_OFFSET_RECEIVE_TIME 32 +#define SNTP_OFFSET_TRANSMIT_TIME 40 + +/* number of seconds between 1900 and 1970 (MSB=1)*/ +#define DIFF_SEC_1900_1970 (2208988800UL) +/* number of seconds between 1970 and Feb 7, 2036 (6:28:16 UTC) (MSB=0) */ +#define DIFF_SEC_1970_2036 (2085978496UL) + +/** + * SNTP packet format (without optional fields) + * Timestamps are coded as 64 bits: + * - 32 bits seconds since Jan 01, 1970, 00:00 + * - 32 bits seconds fraction (0-padded) + * For future use, if the MSB in the seconds part is set, seconds are based + * on Feb 07, 2036, 06:28:16. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct sntp_msg { + PACK_STRUCT_FLD_8(u8_t li_vn_mode); + PACK_STRUCT_FLD_8(u8_t stratum); + PACK_STRUCT_FLD_8(u8_t poll); + PACK_STRUCT_FLD_8(u8_t precision); + PACK_STRUCT_FIELD(u32_t root_delay); + PACK_STRUCT_FIELD(u32_t root_dispersion); + PACK_STRUCT_FIELD(u32_t reference_identifier); + PACK_STRUCT_FIELD(u32_t reference_timestamp[2]); + PACK_STRUCT_FIELD(u32_t originate_timestamp[2]); + PACK_STRUCT_FIELD(u32_t receive_timestamp[2]); + PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* function prototypes */ +static void sntp_request(void *arg); + +/** The operating mode */ +static u8_t sntp_opmode; + +/** The UDP pcb used by the SNTP client */ +static struct udp_pcb* sntp_pcb; +/** Names/Addresses of servers */ +struct sntp_server { +#if SNTP_SERVER_DNS + char* name; +#endif /* SNTP_SERVER_DNS */ + ip_addr_t addr; +}; +static struct sntp_server sntp_servers[SNTP_MAX_SERVERS]; + +#if SNTP_GET_SERVERS_FROM_DHCP +static u8_t sntp_set_servers_from_dhcp; +#endif /* SNTP_GET_SERVERS_FROM_DHCP */ +#if SNTP_SUPPORT_MULTIPLE_SERVERS +/** The currently used server (initialized to 0) */ +static u8_t sntp_current_server; +#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ +#define sntp_current_server 0 +#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ + +#if SNTP_RETRY_TIMEOUT_EXP +#define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT +/** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */ +static u32_t sntp_retry_timeout; +#else /* SNTP_RETRY_TIMEOUT_EXP */ +#define SNTP_RESET_RETRY_TIMEOUT() +#define sntp_retry_timeout SNTP_RETRY_TIMEOUT +#endif /* SNTP_RETRY_TIMEOUT_EXP */ + +#if SNTP_CHECK_RESPONSE >= 1 +/** Saves the last server address to compare with response */ +static ip_addr_t sntp_last_server_address; +#endif /* SNTP_CHECK_RESPONSE >= 1 */ + +#if SNTP_CHECK_RESPONSE >= 2 +/** Saves the last timestamp sent (which is sent back by the server) + * to compare against in response */ +static u32_t sntp_last_timestamp_sent[2]; +#endif /* SNTP_CHECK_RESPONSE >= 2 */ + +/** + * SNTP processing of received timestamp + */ +static void +sntp_process(u32_t *receive_timestamp) +{ + /* convert SNTP time (1900-based) to unix GMT time (1970-based) + * if MSB is 0, SNTP time is 2036-based! + */ + u32_t rx_secs = lwip_ntohl(receive_timestamp[0]); + int is_1900_based = ((rx_secs & 0x80000000) != 0); + u32_t t = is_1900_based ? (rx_secs - DIFF_SEC_1900_1970) : (rx_secs + DIFF_SEC_1970_2036); + time_t tim = t; + +#if SNTP_CALC_TIME_US + u32_t us = lwip_ntohl(receive_timestamp[1]) / 4295; + SNTP_SET_SYSTEM_TIME_US(t, us); + /* display local time from GMT time */ + LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&tim), us)); + +#else /* SNTP_CALC_TIME_US */ + + /* change system time and/or the update the RTC clock */ + SNTP_SET_SYSTEM_TIME(t); + /* display local time from GMT time */ + LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&tim))); +#endif /* SNTP_CALC_TIME_US */ + LWIP_UNUSED_ARG(tim); +} + +/** + * Initialize request struct to be sent to server. + */ +static void +sntp_initialize_request(struct sntp_msg *req) +{ + memset(req, 0, SNTP_MSG_LEN); + req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT; + +#if SNTP_CHECK_RESPONSE >= 2 + { + u32_t sntp_time_sec, sntp_time_us; + /* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */ + SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us); + sntp_last_timestamp_sent[0] = lwip_htonl(sntp_time_sec + DIFF_SEC_1900_1970); + req->transmit_timestamp[0] = sntp_last_timestamp_sent[0]; + /* we send/save us instead of fraction to be faster... */ + sntp_last_timestamp_sent[1] = lwip_htonl(sntp_time_us); + req->transmit_timestamp[1] = sntp_last_timestamp_sent[1]; + } +#endif /* SNTP_CHECK_RESPONSE >= 2 */ +} + +/** + * Retry: send a new request (and increase retry timeout). + * + * @param arg is unused (only necessary to conform to sys_timeout) + */ +static void +sntp_retry(void* arg) +{ + LWIP_UNUSED_ARG(arg); + + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n", + sntp_retry_timeout)); + + /* set up a timer to send a retry and increase the retry delay */ + sys_timeout(sntp_retry_timeout, sntp_request, NULL); + +#if SNTP_RETRY_TIMEOUT_EXP + { + u32_t new_retry_timeout; + /* increase the timeout for next retry */ + new_retry_timeout = sntp_retry_timeout << 1; + /* limit to maximum timeout and prevent overflow */ + if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) && + (new_retry_timeout > sntp_retry_timeout)) { + sntp_retry_timeout = new_retry_timeout; + } + } +#endif /* SNTP_RETRY_TIMEOUT_EXP */ +} + +#if SNTP_SUPPORT_MULTIPLE_SERVERS +/** + * If Kiss-of-Death is received (or another packet parsing error), + * try the next server or retry the current server and increase the retry + * timeout if only one server is available. + * (implicitly, SNTP_MAX_SERVERS > 1) + * + * @param arg is unused (only necessary to conform to sys_timeout) + */ +static void +sntp_try_next_server(void* arg) +{ + u8_t old_server, i; + LWIP_UNUSED_ARG(arg); + + old_server = sntp_current_server; + for (i = 0; i < SNTP_MAX_SERVERS - 1; i++) { + sntp_current_server++; + if (sntp_current_server >= SNTP_MAX_SERVERS) { + sntp_current_server = 0; + } + if (!ip_addr_isany(&sntp_servers[sntp_current_server].addr) +#if SNTP_SERVER_DNS + || (sntp_servers[sntp_current_server].name != NULL) +#endif + ) { + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n", + (u16_t)sntp_current_server)); + /* new server: reset retry timeout */ + SNTP_RESET_RETRY_TIMEOUT(); + /* instantly send a request to the next server */ + sntp_request(NULL); + return; + } + } + /* no other valid server found */ + sntp_current_server = old_server; + sntp_retry(NULL); +} +#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ +/* Always retry on error if only one server is supported */ +#define sntp_try_next_server sntp_retry +#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ + +/** UDP recv callback for the sntp pcb */ +static void +sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + u8_t mode; + u8_t stratum; + u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE]; + err_t err; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + + /* packet received: stop retry timeout */ + sys_untimeout(sntp_try_next_server, NULL); + sys_untimeout(sntp_request, NULL); + + err = ERR_ARG; +#if SNTP_CHECK_RESPONSE >= 1 + /* check server address and port */ + if (((sntp_opmode != SNTP_OPMODE_POLL) || ip_addr_cmp(addr, &sntp_last_server_address)) && + (port == SNTP_PORT)) +#else /* SNTP_CHECK_RESPONSE >= 1 */ + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); +#endif /* SNTP_CHECK_RESPONSE >= 1 */ + { + /* process the response */ + if (p->tot_len == SNTP_MSG_LEN) { + pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE); + mode &= SNTP_MODE_MASK; + /* if this is a SNTP response... */ + if (((sntp_opmode == SNTP_OPMODE_POLL) && (mode == SNTP_MODE_SERVER)) || + ((sntp_opmode == SNTP_OPMODE_LISTENONLY) && (mode == SNTP_MODE_BROADCAST))) { + pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM); + if (stratum == SNTP_STRATUM_KOD) { + /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ + err = SNTP_ERR_KOD; + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n")); + } else { +#if SNTP_CHECK_RESPONSE >= 2 + /* check originate_timetamp against sntp_last_timestamp_sent */ + u32_t originate_timestamp[2]; + pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME); + if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) || + (originate_timestamp[1] != sntp_last_timestamp_sent[1])) + { + LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n")); + } else +#endif /* SNTP_CHECK_RESPONSE >= 2 */ + /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */ + { + /* correct answer */ + err = ERR_OK; + pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_TRANSMIT_TIME); + } + } + } else { + LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode)); + /* wait for correct response */ + err = ERR_TIMEOUT; + } + } else { + LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len)); + } + } +#if SNTP_CHECK_RESPONSE >= 1 + else { + /* packet from wrong remote address or port, wait for correct response */ + err = ERR_TIMEOUT; + } +#endif /* SNTP_CHECK_RESPONSE >= 1 */ + pbuf_free(p); + if (err == ERR_OK) { + sntp_process(receive_timestamp); + + /* Set up timeout for next request (only if poll response was received)*/ + if (sntp_opmode == SNTP_OPMODE_POLL) { + /* Correct response, reset retry timeout */ + SNTP_RESET_RETRY_TIMEOUT(); + + sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL); + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n", + (u32_t)SNTP_UPDATE_DELAY)); + } + } else if (err != ERR_TIMEOUT) { + /* Errors are only processed in case of an explicit poll response */ + if (sntp_opmode == SNTP_OPMODE_POLL) { + if (err == SNTP_ERR_KOD) { + /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ + sntp_try_next_server(NULL); + } else { + /* another error, try the same server again */ + sntp_retry(NULL); + } + } + } +} + +/** Actually send an sntp request to a server. + * + * @param server_addr resolved IP address of the SNTP server + */ +static void +sntp_send_request(const ip_addr_t *server_addr) +{ + struct pbuf* p; + p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM); + if (p != NULL) { + struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload; + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n")); + /* initialize request message */ + sntp_initialize_request(sntpmsg); + /* send request */ + udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT); + /* free the pbuf after sending it */ + pbuf_free(p); + /* set up receive timeout: try next server or retry on timeout */ + sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL); +#if SNTP_CHECK_RESPONSE >= 1 + /* save server address to verify it in sntp_recv */ + ip_addr_set(&sntp_last_server_address, server_addr); +#endif /* SNTP_CHECK_RESPONSE >= 1 */ + } else { + LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n", + (u32_t)SNTP_RETRY_TIMEOUT)); + /* out of memory: set up a timer to send a retry */ + sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL); + } +} + +#if SNTP_SERVER_DNS +/** + * DNS found callback when using DNS names as server address. + */ +static void +sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg) +{ + LWIP_UNUSED_ARG(hostname); + LWIP_UNUSED_ARG(arg); + + if (ipaddr != NULL) { + /* Address resolved, send request */ + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n")); + sntp_send_request(ipaddr); + } else { + /* DNS resolving failed -> try another server */ + LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n")); + sntp_try_next_server(NULL); + } +} +#endif /* SNTP_SERVER_DNS */ + +/** + * Send out an sntp request. + * + * @param arg is unused (only necessary to conform to sys_timeout) + */ +static void +sntp_request(void *arg) +{ + ip_addr_t sntp_server_address; + err_t err; + + LWIP_UNUSED_ARG(arg); + + /* initialize SNTP server address */ +#if SNTP_SERVER_DNS + if (sntp_servers[sntp_current_server].name) { + /* always resolve the name and rely on dns-internal caching & timeout */ + ip_addr_set_zero(&sntp_servers[sntp_current_server].addr); + err = dns_gethostbyname(sntp_servers[sntp_current_server].name, &sntp_server_address, + sntp_dns_found, NULL); + if (err == ERR_INPROGRESS) { + /* DNS request sent, wait for sntp_dns_found being called */ + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n")); + return; + } else if (err == ERR_OK) { + sntp_servers[sntp_current_server].addr = sntp_server_address; + } + } else +#endif /* SNTP_SERVER_DNS */ + { + sntp_server_address = sntp_servers[sntp_current_server].addr; + err = (ip_addr_isany_val(sntp_server_address)) ? ERR_ARG : ERR_OK; + } + + if (err == ERR_OK) { + LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_request: current server address is %s\n", + ipaddr_ntoa(&sntp_server_address))); + sntp_send_request(&sntp_server_address); + } else { + /* address conversion failed, try another server */ + LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n")); + sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL); + } +} + +/** + * @ingroup sntp + * Initialize this module. + * Send out request instantly or after SNTP_STARTUP_DELAY(_FUNC). + */ +void +sntp_init(void) +{ +#ifdef SNTP_SERVER_ADDRESS +#if SNTP_SERVER_DNS + sntp_setservername(0, SNTP_SERVER_ADDRESS); +#else +#error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0 +#endif +#endif /* SNTP_SERVER_ADDRESS */ + + if (sntp_pcb == NULL) { + sntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL); + if (sntp_pcb != NULL) { + udp_recv(sntp_pcb, sntp_recv, NULL); + + if (sntp_opmode == SNTP_OPMODE_POLL) { + SNTP_RESET_RETRY_TIMEOUT(); +#if SNTP_STARTUP_DELAY + sys_timeout((u32_t)SNTP_STARTUP_DELAY_FUNC, sntp_request, NULL); +#else + sntp_request(NULL); +#endif + } else if (sntp_opmode == SNTP_OPMODE_LISTENONLY) { + ip_set_option(sntp_pcb, SOF_BROADCAST); + udp_bind(sntp_pcb, IP_ANY_TYPE, SNTP_PORT); + } + } + } +} + +/** + * @ingroup sntp + * Stop this module. + */ +void +sntp_stop(void) +{ + if (sntp_pcb != NULL) { + sys_untimeout(sntp_request, NULL); + sys_untimeout(sntp_try_next_server, NULL); + udp_remove(sntp_pcb); + sntp_pcb = NULL; + } +} + +/** + * @ingroup sntp + * Get enabled state. + */ +u8_t sntp_enabled(void) +{ + return (sntp_pcb != NULL)? 1 : 0; +} + +/** + * @ingroup sntp + * Sets the operating mode. + * @param operating_mode one of the available operating modes + */ +void +sntp_setoperatingmode(u8_t operating_mode) +{ + LWIP_ASSERT("Invalid operating mode", operating_mode <= SNTP_OPMODE_LISTENONLY); + LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb == NULL); + sntp_opmode = operating_mode; +} + +/** + * @ingroup sntp + * Gets the operating mode. + */ +u8_t +sntp_getoperatingmode(void) +{ + return sntp_opmode; +} + +#if SNTP_GET_SERVERS_FROM_DHCP +/** + * Config SNTP server handling by IP address, name, or DHCP; clear table + * @param set_servers_from_dhcp enable or disable getting server addresses from dhcp + */ +void +sntp_servermode_dhcp(int set_servers_from_dhcp) +{ + u8_t new_mode = set_servers_from_dhcp ? 1 : 0; + if (sntp_set_servers_from_dhcp != new_mode) { + sntp_set_servers_from_dhcp = new_mode; + } +} +#endif /* SNTP_GET_SERVERS_FROM_DHCP */ + +/** + * @ingroup sntp + * Initialize one of the NTP servers by IP address + * + * @param idx the index of the NTP server to set must be < SNTP_MAX_SERVERS + * @param server IP address of the NTP server to set + */ +void +sntp_setserver(u8_t idx, const ip_addr_t *server) +{ + if (idx < SNTP_MAX_SERVERS) { + if (server != NULL) { + sntp_servers[idx].addr = (*server); + } else { + ip_addr_set_zero(&sntp_servers[idx].addr); + } +#if SNTP_SERVER_DNS + sntp_servers[idx].name = NULL; +#endif + } +} + +#if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP +/** + * Initialize one of the NTP servers by IP address, required by DHCP + * + * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS + * @param dnsserver IP address of the NTP server to set + */ +void +dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server) +{ + LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n", + (sntp_set_servers_from_dhcp ? "Got" : "Rejected"), + ip4_addr1(server), ip4_addr2(server), ip4_addr3(server), ip4_addr4(server), num)); + if (sntp_set_servers_from_dhcp && num) { + u8_t i; + for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) { + ip_addr_t addr; + ip_addr_copy_from_ip4(addr, server[i]); + sntp_setserver(i, &addr); + } + for (i = num; i < SNTP_MAX_SERVERS; i++) { + sntp_setserver(i, NULL); + } + } +} +#endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */ + +/** + * @ingroup sntp + * Obtain one of the currently configured by IP address (or DHCP) NTP servers + * + * @param idx the index of the NTP server + * @return IP address of the indexed NTP server or "ip_addr_any" if the NTP + * server has not been configured by address (or at all). + */ +const ip_addr_t* +sntp_getserver(u8_t idx) +{ + if (idx < SNTP_MAX_SERVERS) { + return &sntp_servers[idx].addr; + } + return IP_ADDR_ANY; +} + +#if SNTP_SERVER_DNS +/** + * Initialize one of the NTP servers by name + * + * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS + * @param dnsserver DNS name of the NTP server to set, to be resolved at contact time + */ +void +sntp_setservername(u8_t idx, char *server) +{ + if (idx < SNTP_MAX_SERVERS) { + sntp_servers[idx].name = server; + } +} + +/** + * Obtain one of the currently configured by name NTP servers. + * + * @param numdns the index of the NTP server + * @return IP address of the indexed NTP server or NULL if the NTP + * server has not been configured by name (or at all) + */ +char * +sntp_getservername(u8_t idx) +{ + if (idx < SNTP_MAX_SERVERS) { + return sntp_servers[idx].name; + } + return NULL; +} +#endif /* SNTP_SERVER_DNS */ + +#endif /* LWIP_UDP */ diff --git a/components/net/lwip-2.0.3/src/apps/tftp/tftp_port.c b/components/net/lwip-2.0.3/src/apps/tftp/tftp_port.c new file mode 100644 index 0000000000..e14e34cfec --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/tftp/tftp_port.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-17 armink first version. + */ + + +#include +#include +#include + +static struct tftp_context ctx; + +static void* tftp_open(const char* fname, const char* mode, u8_t write) +{ + int fd = -1; + + if (!rt_strcmp(mode, "octet")) + { + if (write) + { + fd = open(fname, O_WRONLY | O_CREAT, 0); + } + else + { + fd = open(fname, O_RDONLY, 0); + } + } + else + { + rt_kprintf("tftp: No support this mode(%s).", mode); + } + + return (void *) fd; +} + +static int tftp_write(void* handle, struct pbuf* p) +{ + int fd = (int) handle; + + return write(fd, p->payload, p->len); +} + +#if defined(RT_USING_FINSH) +#include + +static void tftp_server(uint8_t argc, char **argv) +{ + ctx.open = tftp_open; + ctx.close = (void (*)(void *)) close; + ctx.read = (int (*)(void *, void *, int)) read; + ctx.write = tftp_write; + + if (tftp_init(&ctx) == ERR_OK) + { + rt_kprintf("TFTP server start successfully.\n"); + } + else + { + rt_kprintf("TFTP server start failed.\n"); + } +} +FINSH_FUNCTION_EXPORT(tftp_server, start tftp server.); + +#if defined(FINSH_USING_MSH) +MSH_CMD_EXPORT(tftp_server, start tftp server.); +#endif /* defined(FINSH_USING_MSH) */ + +#endif /* defined(RT_USING_FINSH) */ diff --git a/components/net/lwip-2.0.3/src/apps/tftp/tftp_server.c b/components/net/lwip-2.0.3/src/apps/tftp/tftp_server.c new file mode 100644 index 0000000000..afaa3bb08d --- /dev/null +++ b/components/net/lwip-2.0.3/src/apps/tftp/tftp_server.c @@ -0,0 +1,417 @@ +/****************************************************************//** + * + * @file tftp_server.c + * + * @author Logan Gunthorpe + * Dirk Ziegelmeier + * + * @brief Trivial File Transfer Protocol (RFC 1350) + * + * Copyright (c) Deltatee Enterprises Ltd. 2013 + * All rights reserved. + * + ********************************************************************/ + +/* + * Redistribution and use in source and binary forms, with or without + * modification,are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Logan Gunthorpe + * Dirk Ziegelmeier + * + */ + +/** + * @defgroup tftp TFTP server + * @ingroup apps + * + * This is simple TFTP server for the lwIP raw API. + */ + +#include "lwip/apps/tftp_server.h" + +#if LWIP_UDP + +#include "lwip/udp.h" +#include "lwip/timeouts.h" +#include "lwip/debug.h" + +#define TFTP_MAX_PAYLOAD_SIZE 512 +#define TFTP_HEADER_LENGTH 4 + +#define TFTP_RRQ 1 +#define TFTP_WRQ 2 +#define TFTP_DATA 3 +#define TFTP_ACK 4 +#define TFTP_ERROR 5 + +enum tftp_error { + TFTP_ERROR_FILE_NOT_FOUND = 1, + TFTP_ERROR_ACCESS_VIOLATION = 2, + TFTP_ERROR_DISK_FULL = 3, + TFTP_ERROR_ILLEGAL_OPERATION = 4, + TFTP_ERROR_UNKNOWN_TRFR_ID = 5, + TFTP_ERROR_FILE_EXISTS = 6, + TFTP_ERROR_NO_SUCH_USER = 7 +}; + +#include + +struct tftp_state { + const struct tftp_context *ctx; + void *handle; + struct pbuf *last_data; + struct udp_pcb *upcb; + ip_addr_t addr; + u16_t port; + int timer; + int last_pkt; + u16_t blknum; + u8_t retries; + u8_t mode_write; +}; + +static struct tftp_state tftp_state; + +static void tftp_tmr(void* arg); + +static void +close_handle(void) +{ + tftp_state.port = 0; + ip_addr_set_any(0, &tftp_state.addr); + + if(tftp_state.last_data != NULL) { + pbuf_free(tftp_state.last_data); + tftp_state.last_data = NULL; + } + + sys_untimeout(tftp_tmr, NULL); + + if (tftp_state.handle) { + tftp_state.ctx->close(tftp_state.handle); + tftp_state.handle = NULL; + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: closing\n")); + } +} + +static void +send_error(const ip_addr_t *addr, u16_t port, enum tftp_error code, const char *str) +{ + int str_length = strlen(str); + struct pbuf* p; + u16_t* payload; + + p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(TFTP_HEADER_LENGTH + str_length + 1), PBUF_RAM); + if(p == NULL) { + return; + } + + payload = (u16_t*) p->payload; + payload[0] = PP_HTONS(TFTP_ERROR); + payload[1] = lwip_htons(code); + MEMCPY(&payload[2], str, str_length + 1); + + udp_sendto(tftp_state.upcb, p, addr, port); + pbuf_free(p); +} + +static void +send_ack(u16_t blknum) +{ + struct pbuf* p; + u16_t* payload; + + p = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH, PBUF_RAM); + if(p == NULL) { + return; + } + payload = (u16_t*) p->payload; + + payload[0] = PP_HTONS(TFTP_ACK); + payload[1] = lwip_htons(blknum); + udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); + pbuf_free(p); +} + +static void +resend_data(void) +{ + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, tftp_state.last_data->len, PBUF_RAM); + if(p == NULL) { + return; + } + + if(pbuf_copy(p, tftp_state.last_data) != ERR_OK) { + pbuf_free(p); + return; + } + + udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); + pbuf_free(p); +} + +static void +send_data(void) +{ + u16_t *payload; + int ret; + + if(tftp_state.last_data != NULL) { + pbuf_free(tftp_state.last_data); + } + + tftp_state.last_data = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH + TFTP_MAX_PAYLOAD_SIZE, PBUF_RAM); + if(tftp_state.last_data == NULL) { + return; + } + + payload = (u16_t *) tftp_state.last_data->payload; + payload[0] = PP_HTONS(TFTP_DATA); + payload[1] = lwip_htons(tftp_state.blknum); + + ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_MAX_PAYLOAD_SIZE); + if (ret < 0) { + send_error(&tftp_state.addr, tftp_state.port, TFTP_ERROR_ACCESS_VIOLATION, "Error occured while reading the file."); + close_handle(); + return; + } + + pbuf_realloc(tftp_state.last_data, (u16_t)(TFTP_HEADER_LENGTH + ret)); + resend_data(); +} + +static void +recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + u16_t *sbuf = (u16_t *) p->payload; + int opcode; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(upcb); + + if (((tftp_state.port != 0) && (port != tftp_state.port)) || + (!ip_addr_isany_val(tftp_state.addr) && !ip_addr_cmp(&tftp_state.addr, addr))) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); + pbuf_free(p); + return; + } + + opcode = sbuf[0]; + + tftp_state.last_pkt = tftp_state.timer; + tftp_state.retries = 0; + + switch (opcode) { + case PP_HTONS(TFTP_RRQ): /* fall through */ + case PP_HTONS(TFTP_WRQ): + { + const char tftp_null = 0; + char filename[TFTP_MAX_FILENAME_LEN + 1] = { 0 }; + char mode[TFTP_MAX_MODE_LEN] = { 0 }; + u16_t filename_end_offset; + u16_t mode_end_offset; + + if(tftp_state.handle != NULL) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); + break; + } + + sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); + + /* find \0 in pbuf -> end of filename string */ + filename_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), 2); + if((u16_t)(filename_end_offset-2) > sizeof(filename)) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Filename too long/not NULL terminated"); + break; + } + pbuf_copy_partial(p, filename, filename_end_offset-2, 2); + + /* find \0 in pbuf -> end of mode string */ + mode_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), filename_end_offset+1); + if((u16_t)(mode_end_offset-filename_end_offset) > sizeof(mode)) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Mode too long/not NULL terminated"); + break; + } + pbuf_copy_partial(p, mode, mode_end_offset-filename_end_offset, filename_end_offset+1); + + tftp_state.handle = tftp_state.ctx->open(filename, mode, opcode == PP_HTONS(TFTP_WRQ)); + tftp_state.blknum = 1; + + if (!tftp_state.handle) { + send_error(addr, port, TFTP_ERROR_FILE_NOT_FOUND, "Unable to open requested file."); + break; + } + + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: %s request from ", (opcode == PP_HTONS(TFTP_WRQ)) ? "write" : "read")); + ip_addr_debug_print(TFTP_DEBUG | LWIP_DBG_STATE, addr); + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, (" for '%s' mode '%s'\n", filename, mode)); + + ip_addr_copy(tftp_state.addr, *addr); + tftp_state.port = port; + + if (opcode == PP_HTONS(TFTP_WRQ)) { + tftp_state.mode_write = 1; + send_ack(0); + } else { + tftp_state.mode_write = 0; + send_data(); + } + + break; + } + + case PP_HTONS(TFTP_DATA): + { + int ret; + u16_t blknum; + + if (tftp_state.handle == NULL) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); + break; + } + + if (tftp_state.mode_write != 1) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a write connection"); + break; + } + + blknum = lwip_ntohs(sbuf[1]); + pbuf_header(p, -TFTP_HEADER_LENGTH); + + ret = tftp_state.ctx->write(tftp_state.handle, p); + if (ret < 0) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "error writing file"); + close_handle(); + } else { + send_ack(blknum); + } + + if (p->tot_len < TFTP_MAX_PAYLOAD_SIZE) { + close_handle(); + } + break; + } + + case PP_HTONS(TFTP_ACK): + { + u16_t blknum; + int lastpkt; + + if (tftp_state.handle == NULL) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); + break; + } + + if (tftp_state.mode_write != 0) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a read connection"); + break; + } + + blknum = lwip_ntohs(sbuf[1]); + if (blknum != tftp_state.blknum) { + send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number"); + break; + } + + lastpkt = 0; + + if (tftp_state.last_data != NULL) { + lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH); + } + + if (!lastpkt) { + tftp_state.blknum++; + send_data(); + } else { + close_handle(); + } + + break; + } + + default: + send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Unknown operation"); + break; + } + + pbuf_free(p); +} + +static void +tftp_tmr(void* arg) +{ + LWIP_UNUSED_ARG(arg); + + tftp_state.timer++; + + if (tftp_state.handle == NULL) { + return; + } + + sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); + + if ((tftp_state.timer - tftp_state.last_pkt) > (TFTP_TIMEOUT_MSECS / TFTP_TIMER_MSECS)) { + if ((tftp_state.last_data != NULL) && (tftp_state.retries < TFTP_MAX_RETRIES)) { + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout, retrying\n")); + resend_data(); + tftp_state.retries++; + } else { + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout\n")); + close_handle(); + } + } +} + +/** @ingroup tftp + * Initialize TFTP server. + * @param ctx TFTP callback struct + */ +err_t +tftp_init(const struct tftp_context *ctx) +{ + err_t ret; + + struct udp_pcb *pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + if (pcb == NULL) { + return ERR_MEM; + } + + ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT); + if (ret != ERR_OK) { + udp_remove(pcb); + return ret; + } + + tftp_state.handle = NULL; + tftp_state.port = 0; + tftp_state.ctx = ctx; + tftp_state.timer = 0; + tftp_state.last_data = NULL; + tftp_state.upcb = pcb; + + udp_recv(pcb, recv, NULL); + + return ERR_OK; +} + +#endif /* LWIP_UDP */ diff --git a/components/net/lwip-2.0.3/src/arch/include/arch/bpstruct.h b/components/net/lwip-2.0.3/src/arch/include/arch/bpstruct.h new file mode 100644 index 0000000000..74ead358fa --- /dev/null +++ b/components/net/lwip-2.0.3/src/arch/include/arch/bpstruct.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__ICCARM__) +#pragma pack(1) +#endif diff --git a/components/net/lwip-2.0.3/src/arch/include/arch/cc.h b/components/net/lwip-2.0.3/src/arch/include/arch/cc.h new file mode 100644 index 0000000000..5e9a7ff722 --- /dev/null +++ b/components/net/lwip-2.0.3/src/arch/include/arch/cc.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: cc.h,v 1.1.1.1 2004/12/16 14:17:13 bear Exp $ + */ +#ifndef __ARCH_CC_H__ +#define __ARCH_CC_H__ + +#include +#include +#include + + +#define U16_F "hu" +#define S16_F "hd" +#define X16_F "hx" +#define U32_F "lu" +#define S32_F "ld" +#define X32_F "lx" + +#include +/* some errno not defined in newlib */ +#ifndef ENSRNOTFOUND +#define ENSRNOTFOUND 163 /* Domain name not found */ +/* WARNING: ESHUTDOWN also not defined in newlib. We chose + 180 here because the number "108" which is used + in arch.h has been assigned to another error code. */ +#endif + +/* LWIP_TIMEVAL_PRIVATE: provided by */ +#include +#define LWIP_TIMEVAL_PRIVATE 0 + +#if defined(__CC_ARM) /* ARMCC compiler */ +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /*Arm Compiler 6*/ +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END +#elif defined(__IAR_SYSTEMS_ICC__) /* IAR Compiler */ +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES +#elif defined(__GNUC__) /* GNU GCC Compiler */ +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END +#elif defined(_MSC_VER) +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END +#endif + +void sys_arch_assert(const char* file, int line); +#define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) +#define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) + +//#define SYS_ARCH_DECL_PROTECT(level) +//#define SYS_ARCH_PROTECT(level) rt_enter_critical() +//#define SYS_ARCH_UNPROTECT(level) rt_exit_critical() + +#define SYS_ARCH_DECL_PROTECT(level) register rt_base_t level +#define SYS_ARCH_PROTECT(level) do {level = rt_hw_interrupt_disable();} while(0) +#define SYS_ARCH_UNPROTECT(level) do {rt_hw_interrupt_enable(level);} while(0) + + +#endif /* __ARCH_CC_H__ */ + diff --git a/components/net/lwip-2.0.3/src/arch/include/arch/epstruct.h b/components/net/lwip-2.0.3/src/arch/include/arch/epstruct.h new file mode 100644 index 0000000000..f6390959ea --- /dev/null +++ b/components/net/lwip-2.0.3/src/arch/include/arch/epstruct.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__ICCARM__) +#pragma pack() +#endif diff --git a/components/net/lwip-2.0.3/src/arch/include/arch/perf.h b/components/net/lwip-2.0.3/src/arch/include/arch/perf.h new file mode 100644 index 0000000000..675f1f65dc --- /dev/null +++ b/components/net/lwip-2.0.3/src/arch/include/arch/perf.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: perf.h,v 1.1.1.1 2004/12/16 14:17:13 bear Exp $ + */ +#ifndef __ARCH_PERF_H__ +#define __ARCH_PERF_H__ + +//#include + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +/* +void perf_print(unsigned long c1l, unsigned long c1h, + unsigned long c2l, unsigned long c2h, + char *key); + +void perf_print_times(struct tms *start, struct tms *end, char *key); + +void perf_init(char *fname); +*/ +#endif /* __ARCH_PERF_H__ */ diff --git a/components/net/lwip-2.0.3/src/arch/include/arch/sys_arch.h b/components/net/lwip-2.0.3/src/arch/include/arch/sys_arch.h new file mode 100644 index 0000000000..8637cc9263 --- /dev/null +++ b/components/net/lwip-2.0.3/src/arch/include/arch/sys_arch.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: sys_arch.h,v 1.3 2005/03/13 16:03:23 bear Exp $ + */ +#ifndef __ARCH_SYS_ARCH_H__ +#define __ARCH_SYS_ARCH_H__ + +#include "arch/cc.h" + +#include + +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#define SYS_MBOX_NULL RT_NULL +#define SYS_SEM_NULL RT_NULL + +typedef u32_t sys_prot_t; + +#define SYS_MBOX_SIZE 10 +#define SYS_LWIP_TIMER_NAME "timer" +#define SYS_LWIP_MBOX_NAME "mbox" +#define SYS_LWIP_SEM_NAME "sem" +#define SYS_LWIP_MUTEX_NAME "mu" + +typedef rt_sem_t sys_sem_t; +typedef rt_mutex_t sys_mutex_t; +typedef rt_mailbox_t sys_mbox_t; +typedef rt_thread_t sys_thread_t; + +#endif /* __ARCH_SYS_ARCH_H__ */ diff --git a/components/net/lwip-2.0.3/src/arch/sys_arch.c b/components/net/lwip-2.0.3/src/arch/sys_arch.c new file mode 100644 index 0000000000..4d0c57eff9 --- /dev/null +++ b/components/net/lwip-2.0.3/src/arch/sys_arch.c @@ -0,0 +1,764 @@ +/* + * COPYRIGHT (C) 2006-2021, RT-Thread Development Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Change Logs: + * Date Author Notes + * 2012-12-8 Bernard add file header + * export bsd socket symbol for RT-Thread Application Module + * 2017-11-15 Bernard add lock for init_done callback. + */ + +#include +#include + +#include "lwip/sys.h" +#include "lwip/opt.h" +#include "lwip/stats.h" +#include "lwip/err.h" +#include "arch/sys_arch.h" +#include "lwip/debug.h" +#include "lwip/netif.h" +#include "lwip/netifapi.h" +#include "lwip/tcpip.h" +#include "netif/ethernetif.h" +#include "lwip/sio.h" +#include "lwip/init.h" +#include "lwip/dhcp.h" +#include "lwip/inet.h" + +#include + +/* + * Initialize the network interface device + * + * @return the operation status, ERR_OK on OK, ERR_IF on error + */ +static err_t netif_device_init(struct netif *netif) +{ + struct eth_device *ethif; + + ethif = (struct eth_device *)netif->state; + if (ethif != RT_NULL) + { + rt_device_t device; + + /* get device object */ + device = (rt_device_t) ethif; + if (rt_device_init(device) != RT_EOK) + { + return ERR_IF; + } + + /* copy device flags to netif flags */ + netif->flags = ethif->flags; + + return ERR_OK; + } + + return ERR_IF; +} +/* + * Initialize the ethernetif layer and set network interface device up + */ +static void tcpip_init_done_callback(void *arg) +{ + rt_device_t device; + struct eth_device *ethif; + ip4_addr_t ipaddr, netmask, gw; + struct rt_list_node* node; + struct rt_object* object; + struct rt_object_information *information; + + LWIP_ASSERT("invalid arg.\n",arg); + + IP4_ADDR(&gw, 0,0,0,0); + IP4_ADDR(&ipaddr, 0,0,0,0); + IP4_ADDR(&netmask, 0,0,0,0); + + /* enter critical */ + rt_enter_critical(); + + /* for each network interfaces */ + information = rt_object_get_information(RT_Object_Class_Device); + RT_ASSERT(information != RT_NULL); + for (node = information->object_list.next; + node != &(information->object_list); + node = node->next) + { + object = rt_list_entry(node, struct rt_object, list); + device = (rt_device_t)object; + if (device->type == RT_Device_Class_NetIf) + { + ethif = (struct eth_device *)device; + + /* leave critical */ + rt_exit_critical(); + LOCK_TCPIP_CORE(); + + netif_add(ethif->netif, &ipaddr, &netmask, &gw, + ethif, netif_device_init, tcpip_input); + + if (netif_default == RT_NULL) + netif_set_default(ethif->netif); + +#if LWIP_DHCP + /* set interface up */ + netif_set_up(ethif->netif); + /* if this interface uses DHCP, start the DHCP client */ + dhcp_start(ethif->netif); +#else + /* set interface up */ + netif_set_up(ethif->netif); +#endif + + if (ethif->flags & ETHIF_LINK_PHYUP) + { + netif_set_link_up(ethif->netif); + } + + UNLOCK_TCPIP_CORE(); + /* enter critical */ + rt_enter_critical(); + } + } + + /* leave critical */ + rt_exit_critical(); + rt_sem_release((rt_sem_t)arg); +} + +/** + * LwIP system initialization + */ +extern int eth_system_device_init_private(void); +int lwip_system_init(void) +{ + rt_err_t rc; + struct rt_semaphore done_sem; + static rt_bool_t init_ok = RT_FALSE; + + if (init_ok) + { + rt_kprintf("lwip system already init.\n"); + return 0; + } + + eth_system_device_init_private(); + + /* set default netif to NULL */ + netif_default = RT_NULL; + + rc = rt_sem_init(&done_sem, "done", 0, RT_IPC_FLAG_FIFO); + + if (rc != RT_EOK) + { + LWIP_ASSERT("Failed to create semaphore", 0); + + return -1; + } + + tcpip_init(tcpip_init_done_callback, (void *)&done_sem); + + /* waiting for initialization done */ + if (rt_sem_take(&done_sem, RT_WAITING_FOREVER) != RT_EOK) + { + rt_sem_detach(&done_sem); + + return -1; + } + rt_sem_detach(&done_sem); + + /* set default ip address */ +#if !LWIP_DHCP + if (netif_default != RT_NULL) + { + struct ip4_addr ipaddr, netmask, gw; + + ipaddr.addr = inet_addr(RT_LWIP_IPADDR); + gw.addr = inet_addr(RT_LWIP_GWADDR); + netmask.addr = inet_addr(RT_LWIP_MSKADDR); + + netifapi_netif_set_addr(netif_default, &ipaddr, &netmask, &gw); + } +#endif + rt_kprintf("lwIP-%d.%d.%d initialized!\n", LWIP_VERSION_MAJOR, LWIP_VERSION_MINOR, LWIP_VERSION_REVISION); + + init_ok = RT_TRUE; + + return 0; +} +INIT_PREV_EXPORT(lwip_system_init); + +void sys_init(void) +{ + /* nothing on RT-Thread porting */ +} + +void lwip_sys_init(void) +{ + lwip_system_init(); +} + +/* + * Create a new semaphore + * + * @return the operation status, ERR_OK on OK; others on error + */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count) +{ + static unsigned short counter = 0; + char tname[RT_NAME_MAX]; + sys_sem_t tmpsem; + + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_SEM_NAME, counter); + counter ++; + + tmpsem = rt_sem_create(tname, count, RT_IPC_FLAG_FIFO); + if (tmpsem == RT_NULL) + return ERR_MEM; + else + { + *sem = tmpsem; + + return ERR_OK; + } +} + +/* + * Deallocate a semaphore + */ +void sys_sem_free(sys_sem_t *sem) +{ + RT_DEBUG_NOT_IN_INTERRUPT; + rt_sem_delete(*sem); +} + +/* + * Signal a semaphore + */ +void sys_sem_signal(sys_sem_t *sem) +{ + rt_sem_release(*sem); +} + +/* + * Block the thread while waiting for the semaphore to be signaled + * + * @return If the timeout argument is non-zero, it will return the number of milliseconds + * spent waiting for the semaphore to be signaled; If the semaphore isn't signaled + * within the specified time, it will return SYS_ARCH_TIMEOUT; If the thread doesn't + * wait for the semaphore, it will return zero + */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ + rt_err_t ret; + s32_t t; + u32_t tick; + + RT_DEBUG_NOT_IN_INTERRUPT; + + /* get the begin tick */ + tick = rt_tick_get(); + if (timeout == 0) + t = RT_WAITING_FOREVER; + else + { + /* convert msecond to os tick */ + if (timeout < (1000/RT_TICK_PER_SECOND)) + t = 1; + else + t = timeout / (1000/RT_TICK_PER_SECOND); + } + + ret = rt_sem_take(*sem, t); + + if (ret == -RT_ETIMEOUT) + return SYS_ARCH_TIMEOUT; + else + { + if (ret == RT_EOK) + ret = 1; + } + + /* get elapse msecond */ + tick = rt_tick_get() - tick; + + /* convert tick to msecond */ + tick = tick * (1000 / RT_TICK_PER_SECOND); + if (tick == 0) + tick = 1; + + return tick; +} + +#ifndef sys_sem_valid +/** Check if a semaphore is valid/allocated: + * return 1 for valid, 0 for invalid + */ +int sys_sem_valid(sys_sem_t *sem) +{ + return (int)(*sem); +} +#endif + +#ifndef sys_sem_set_invalid +/** Set a semaphore invalid so that sys_sem_valid returns 0 + */ +void sys_sem_set_invalid(sys_sem_t *sem) +{ + *sem = RT_NULL; +} +#endif + +/* ====================== Mutex ====================== */ + +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex + */ +err_t sys_mutex_new(sys_mutex_t *mutex) +{ + static unsigned short counter = 0; + char tname[RT_NAME_MAX]; + sys_mutex_t tmpmutex; + + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MUTEX_NAME, counter); + counter ++; + + tmpmutex = rt_mutex_create(tname, RT_IPC_FLAG_FIFO); + if (tmpmutex == RT_NULL) + return ERR_MEM; + else + { + *mutex = tmpmutex; + + return ERR_OK; + } +} + +/** Lock a mutex + * @param mutex the mutex to lock + */ +void sys_mutex_lock(sys_mutex_t *mutex) +{ + RT_DEBUG_NOT_IN_INTERRUPT; + rt_mutex_take(*mutex, RT_WAITING_FOREVER); + + return; +} + +/** Unlock a mutex + * @param mutex the mutex to unlock + */ +void sys_mutex_unlock(sys_mutex_t *mutex) +{ + rt_mutex_release(*mutex); +} + +/** Delete a semaphore + * @param mutex the mutex to delete + */ +void sys_mutex_free(sys_mutex_t *mutex) +{ + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_mutex_delete(*mutex); +} + +#ifndef sys_mutex_valid +/** Check if a mutex is valid/allocated: + * return 1 for valid, 0 for invalid + */ +int sys_mutex_valid(sys_mutex_t *mutex) +{ + return (int)(*mutex); +} +#endif + +#ifndef sys_mutex_set_invalid +/** Set a mutex invalid so that sys_mutex_valid returns 0 + */ +void sys_mutex_set_invalid(sys_mutex_t *mutex) +{ + *mutex = RT_NULL; +} +#endif + +/* ====================== Mailbox ====================== */ + +/* + * Create an empty mailbox for maximum "size" elements + * + * @return the operation status, ERR_OK on OK; others on error + */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ + static unsigned short counter = 0; + char tname[RT_NAME_MAX]; + sys_mbox_t tmpmbox; + + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MBOX_NAME, counter); + counter ++; + + tmpmbox = rt_mb_create(tname, size, RT_IPC_FLAG_FIFO); + if (tmpmbox != RT_NULL) + { + *mbox = tmpmbox; + + return ERR_OK; + } + + return ERR_MEM; +} + +/* + * Deallocate a mailbox + */ +void sys_mbox_free(sys_mbox_t *mbox) +{ + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_mb_delete(*mbox); + + return; +} + +/** Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) + */ +void sys_mbox_post(sys_mbox_t *mbox, void *msg) +{ + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_mb_send_wait(*mbox, (rt_ubase_t)msg, RT_WAITING_FOREVER); + + return; +} + +/* + * Try to post the "msg" to the mailbox + * + * @return return ERR_OK if the "msg" is posted, ERR_MEM if the mailbox is full + */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ + if (rt_mb_send(*mbox, (rt_ubase_t)msg) == RT_EOK) + return ERR_OK; + + return ERR_MEM; +} + +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! + */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) +{ + rt_err_t ret; + s32_t t; + u32_t tick; + + RT_DEBUG_NOT_IN_INTERRUPT; + + /* get the begin tick */ + tick = rt_tick_get(); + + if(timeout == 0) + t = RT_WAITING_FOREVER; + else + { + /* convirt msecond to os tick */ + if (timeout < (1000/RT_TICK_PER_SECOND)) + t = 1; + else + t = timeout / (1000/RT_TICK_PER_SECOND); + } + + ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, t); + if(ret != RT_EOK) + { + return SYS_ARCH_TIMEOUT; + } + + /* get elapse msecond */ + tick = rt_tick_get() - tick; + + /* convert tick to msecond */ + tick = tick * (1000 / RT_TICK_PER_SECOND); + if (tick == 0) + tick = 1; + + return tick; +} + +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message + * @return 0 (milliseconds) if a message has been received + * or SYS_MBOX_EMPTY if the mailbox is empty + */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +{ + int ret; + + ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, 0); + + if(ret == -RT_ETIMEOUT) + return SYS_ARCH_TIMEOUT; + else + { + if (ret == RT_EOK) + ret = 1; + } + + return ret; +} + +#ifndef sys_mbox_valid +/** Check if an mbox is valid/allocated: + * return 1 for valid, 0 for invalid + */ +int sys_mbox_valid(sys_mbox_t *mbox) +{ + return (int)(*mbox); +} +#endif + +#ifndef sys_mbox_set_invalid +/** Set an mbox invalid so that sys_mbox_valid returns 0 + */ +void sys_mbox_set_invalid(sys_mbox_t *mbox) +{ + *mbox = RT_NULL; +} +#endif + +/* ====================== System ====================== */ + +/* + * Start a new thread named "name" with priority "prio" that will begin + * its execution in the function "thread()". The "arg" argument will be + * passed as an argument to the thread() function + */ +sys_thread_t sys_thread_new(const char *name, + lwip_thread_fn thread, + void *arg, + int stacksize, + int prio) +{ + rt_thread_t t; + + RT_DEBUG_NOT_IN_INTERRUPT; + + /* create thread */ + t = rt_thread_create(name, thread, arg, stacksize, prio, 20); + RT_ASSERT(t != RT_NULL); + + /* startup thread */ + rt_thread_startup(t); + + return t; +} + +sys_prot_t sys_arch_protect(void) +{ + rt_base_t level; + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + return level; +} + +void sys_arch_unprotect(sys_prot_t pval) +{ + /* enable interrupt */ + rt_hw_interrupt_enable(pval); + + return; +} + +void sys_arch_assert(const char *file, int line) +{ + rt_kprintf("\nAssertion: %d in %s, thread %s\n", + line, file, rt_thread_self()->name); + RT_ASSERT(0); +} + +u32_t sys_jiffies(void) +{ + return rt_tick_get(); +} + +u32_t sys_now(void) +{ + return rt_tick_get_millisecond(); +} + + +RT_WEAK +void mem_init(void) +{ +} + +void *mem_calloc(mem_size_t count, mem_size_t size) +{ + return rt_calloc(count, size); +} + +void *mem_trim(void *mem, mem_size_t size) +{ + // return rt_realloc(mem, size); + /* not support trim yet */ + return mem; +} + +void *mem_malloc(mem_size_t size) +{ + return rt_malloc(size); +} + +void mem_free(void *mem) +{ + rt_free(mem); +} + +#ifdef RT_LWIP_PPP +u32_t sio_read(sio_fd_t fd, u8_t *buf, u32_t size) +{ + u32_t len; + + RT_ASSERT(fd != RT_NULL); + + len = rt_device_read((rt_device_t)fd, 0, buf, size); + if (len <= 0) + return 0; + + return len; +} + +u32_t sio_write(sio_fd_t fd, u8_t *buf, u32_t size) +{ + RT_ASSERT(fd != RT_NULL); + + return rt_device_write((rt_device_t)fd, 0, buf, size); +} + +void sio_read_abort(sio_fd_t fd) +{ + rt_kprintf("read_abort\n"); +} + +void ppp_trace(int level, const char *format, ...) +{ + va_list args; + rt_size_t length; + static char rt_log_buf[RT_CONSOLEBUF_SIZE]; + + va_start(args, format); + length = rt_vsprintf(rt_log_buf, format, args); + rt_device_write((rt_device_t)rt_console_get_device(), 0, rt_log_buf, length); + va_end(args); +} +#endif + +/* + * export bsd socket symbol for RT-Thread Application Module + */ +#if LWIP_SOCKET +#include +RTM_EXPORT(lwip_accept); +RTM_EXPORT(lwip_bind); +RTM_EXPORT(lwip_shutdown); +RTM_EXPORT(lwip_getpeername); +RTM_EXPORT(lwip_getsockname); +RTM_EXPORT(lwip_getsockopt); +RTM_EXPORT(lwip_setsockopt); +RTM_EXPORT(lwip_close); +RTM_EXPORT(lwip_connect); +RTM_EXPORT(lwip_listen); +RTM_EXPORT(lwip_recv); +RTM_EXPORT(lwip_read); +RTM_EXPORT(lwip_recvfrom); +RTM_EXPORT(lwip_send); +RTM_EXPORT(lwip_sendto); +RTM_EXPORT(lwip_socket); +RTM_EXPORT(lwip_write); +RTM_EXPORT(lwip_select); +RTM_EXPORT(lwip_ioctl); +RTM_EXPORT(lwip_fcntl); + +RTM_EXPORT(lwip_htons); +RTM_EXPORT(lwip_htonl); + +#if LWIP_DNS +#include +RTM_EXPORT(lwip_gethostbyname); +RTM_EXPORT(lwip_gethostbyname_r); +RTM_EXPORT(lwip_freeaddrinfo); +RTM_EXPORT(lwip_getaddrinfo); +#endif + +#endif + +#if LWIP_DHCP +#include +RTM_EXPORT(dhcp_start); +RTM_EXPORT(dhcp_renew); +RTM_EXPORT(dhcp_stop); +#endif + +#if LWIP_NETIF_API +#include +RTM_EXPORT(netifapi_netif_set_addr); +#endif + +#if LWIP_NETIF_LINK_CALLBACK +RTM_EXPORT(netif_set_link_callback); +#endif + +#if LWIP_NETIF_STATUS_CALLBACK +RTM_EXPORT(netif_set_status_callback); +#endif + +RTM_EXPORT(netif_find); +RTM_EXPORT(netif_set_addr); +RTM_EXPORT(netif_set_ipaddr); +RTM_EXPORT(netif_set_gw); +RTM_EXPORT(netif_set_netmask); diff --git a/components/net/lwip-2.0.3/src/core/def.c b/components/net/lwip-2.0.3/src/core/def.c new file mode 100644 index 0000000000..8125313f41 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/def.c @@ -0,0 +1,222 @@ +/** + * @file + * Common functions used throughout the stack. + * + * These are reference implementations of the byte swapping functions. + * Again with the aim of being simple, correct and fully portable. + * Byte swapping is the second thing you would want to optimize. You will + * need to port it to your architecture and in your cc.h: + * + * \#define lwip_htons(x) your_htons + * \#define lwip_htonl(x) your_htonl + * + * Note lwip_ntohs() and lwip_ntohl() are merely references to the htonx counterparts. + * + * If you \#define them to htons() and htonl(), you should + * \#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from + * defining htonx/ntohx compatibility macros. + + * @defgroup sys_nonstandard Non-standard functions + * @ingroup sys_layer + * lwIP provides default implementations for non-standard functions. + * These can be mapped to OS functions to reduce code footprint if desired. + * All defines related to this section must not be placed in lwipopts.h, + * but in arch/cc.h! + * These options cannot be \#defined in lwipopts.h since they are not options + * of lwIP itself, but options of the lwIP port to your system. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/opt.h" +#include "lwip/def.h" + +#include + +#if BYTE_ORDER == LITTLE_ENDIAN + +#if !defined(lwip_htons) +/** + * Convert an u16_t from host- to network byte order. + * + * @param n u16_t in host byte order + * @return n in network byte order + */ +u16_t +lwip_htons(u16_t n) +{ + return (u16_t)PP_HTONS(n); +} +#endif /* lwip_htons */ + +#if !defined(lwip_htonl) +/** + * Convert an u32_t from host- to network byte order. + * + * @param n u32_t in host byte order + * @return n in network byte order + */ +u32_t +lwip_htonl(u32_t n) +{ + return (u32_t)PP_HTONL(n); +} +#endif /* lwip_htonl */ + +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +#ifndef lwip_strnstr +/** + * @ingroup sys_nonstandard + * lwIP default implementation for strnstr() non-standard function. + * This can be \#defined to strnstr() depending on your platform port. + */ +char* +lwip_strnstr(const char* buffer, const char* token, size_t n) +{ + const char* p; + size_t tokenlen = strlen(token); + if (tokenlen == 0) { + return LWIP_CONST_CAST(char *, buffer); + } + for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) { + if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) { + return LWIP_CONST_CAST(char *, p); + } + } + return NULL; +} +#endif + +#ifndef lwip_stricmp +/** + * @ingroup sys_nonstandard + * lwIP default implementation for stricmp() non-standard function. + * This can be \#defined to stricmp() depending on your platform port. + */ +int +lwip_stricmp(const char* str1, const char* str2) +{ + char c1, c2; + + do { + c1 = *str1++; + c2 = *str2++; + if (c1 != c2) { + char c1_upc = c1 | 0x20; + if ((c1_upc >= 'a') && (c1_upc <= 'z')) { + /* characters are not equal an one is in the alphabet range: + downcase both chars and check again */ + char c2_upc = c2 | 0x20; + if (c1_upc != c2_upc) { + /* still not equal */ + /* don't care for < or > */ + return 1; + } + } else { + /* characters are not equal but none is in the alphabet range */ + return 1; + } + } + } while (c1 != 0); + return 0; +} +#endif + +#ifndef lwip_strnicmp +/** + * @ingroup sys_nonstandard + * lwIP default implementation for strnicmp() non-standard function. + * This can be \#defined to strnicmp() depending on your platform port. + */ +int +lwip_strnicmp(const char* str1, const char* str2, size_t len) +{ + char c1, c2; + + do { + c1 = *str1++; + c2 = *str2++; + if (c1 != c2) { + char c1_upc = c1 | 0x20; + if ((c1_upc >= 'a') && (c1_upc <= 'z')) { + /* characters are not equal an one is in the alphabet range: + downcase both chars and check again */ + char c2_upc = c2 | 0x20; + if (c1_upc != c2_upc) { + /* still not equal */ + /* don't care for < or > */ + return 1; + } + } else { + /* characters are not equal but none is in the alphabet range */ + return 1; + } + } + } while (len-- && c1 != 0); + return 0; +} +#endif + +#ifndef lwip_itoa +/** + * @ingroup sys_nonstandard + * lwIP default implementation for itoa() non-standard function. + * This can be \#defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform port. + */ +void +lwip_itoa(char* result, size_t bufsize, int number) +{ + const int base = 10; + char* ptr = result, *ptr1 = result, tmp_char; + int tmp_value; + LWIP_UNUSED_ARG(bufsize); + + do { + tmp_value = number; + number /= base; + *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - number * base)]; + } while(number); + + /* Apply negative sign */ + if (tmp_value < 0) { + *ptr++ = '-'; + } + *ptr-- = '\0'; + while(ptr1 < ptr) { + tmp_char = *ptr; + *ptr--= *ptr1; + *ptr1++ = tmp_char; + } +} +#endif diff --git a/components/net/lwip-2.0.3/src/core/dns.c b/components/net/lwip-2.0.3/src/core/dns.c new file mode 100644 index 0000000000..cd4de06229 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/dns.c @@ -0,0 +1,1587 @@ +/** + * @file + * DNS - host name to IP address resolver. + * + * @defgroup dns DNS + * @ingroup callbackstyle_api + * + * Implements a DNS host name to IP address resolver. + * + * The lwIP DNS resolver functions are used to lookup a host name and + * map it to a numerical IP address. It maintains a list of resolved + * hostnames that can be queried with the dns_lookup() function. + * New hostnames can be resolved using the dns_query() function. + * + * The lwIP version of the resolver also adds a non-blocking version of + * gethostbyname() that will work with a raw API application. This function + * checks for an IP address string first and converts it if it is valid. + * gethostbyname() then does a dns_lookup() to see if the name is + * already in the table. If so, the IP is returned. If not, a query is + * issued and the function returns with a ERR_INPROGRESS status. The app + * using the dns client must then go into a waiting state. + * + * Once a hostname has been resolved (or found to be non-existent), + * the resolver code calls a specified callback function (which + * must be implemented by the module that uses the resolver). + * + * Multicast DNS queries are supported for names ending on ".local". + * However, only "One-Shot Multicast DNS Queries" are supported (RFC 6762 + * chapter 5.1), this is not a fully compliant implementation of continuous + * mDNS querying! + * + * All functions must be called from TCPIP thread. + * + * @see @ref netconn_common for thread-safe access. + */ + +/* + * Port to lwIP from uIP + * by Jim Pettinato April 2007 + * + * security fixes and more by Simon Goldschmidt + * + * uIP version Copyright (c) 2002-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*----------------------------------------------------------------------------- + * RFC 1035 - Domain names - implementation and specification + * RFC 2181 - Clarifications to the DNS Specification + *----------------------------------------------------------------------------*/ + +/** @todo: define good default values (rfc compliance) */ +/** @todo: improve answer parsing, more checkings... */ +/** @todo: check RFC1035 - 7.3. Processing responses */ +/** @todo: one-shot mDNS: dual-stack fallback to another IP version */ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/udp.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/dns.h" +#include "lwip/prot/dns.h" + +#include + +#include + +/** Random generator function to create random TXIDs and source ports for queries */ +#ifndef DNS_RAND_TXID +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_XID) != 0) +#define DNS_RAND_TXID LWIP_RAND +#else +static u16_t dns_txid; +#define DNS_RAND_TXID() (++dns_txid) +#endif +#endif + +/** Limits the source port to be >= 1024 by default */ +#ifndef DNS_PORT_ALLOWED +#define DNS_PORT_ALLOWED(port) ((port) >= 1024) +#endif + +/** DNS maximum number of retries when asking for a name, before "timeout". */ +#ifndef DNS_MAX_RETRIES +#define DNS_MAX_RETRIES 4 +#endif + +/** DNS resource record max. TTL (one week as default) */ +#ifndef DNS_MAX_TTL +#define DNS_MAX_TTL 604800 +#elif DNS_MAX_TTL > 0x7FFFFFFF +#error DNS_MAX_TTL must be a positive 32-bit value +#endif + +#if DNS_TABLE_SIZE > 255 +#error DNS_TABLE_SIZE must fit into an u8_t +#endif +#if DNS_MAX_SERVERS > 255 +#error DNS_MAX_SERVERS must fit into an u8_t +#endif + +/* The number of parallel requests (i.e. calls to dns_gethostbyname + * that cannot be answered from the DNS table. + * This is set to the table size by default. + */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) +#ifndef DNS_MAX_REQUESTS +#define DNS_MAX_REQUESTS DNS_TABLE_SIZE +#else +#if DNS_MAX_REQUESTS > 255 +#error DNS_MAX_REQUESTS must fit into an u8_t +#endif +#endif +#else +/* In this configuration, both arrays have to have the same size and are used + * like one entry (used/free) */ +#define DNS_MAX_REQUESTS DNS_TABLE_SIZE +#endif + +/* The number of UDP source ports used in parallel */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +#ifndef DNS_MAX_SOURCE_PORTS +#define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS +#else +#if DNS_MAX_SOURCE_PORTS > 255 +#error DNS_MAX_SOURCE_PORTS must fit into an u8_t +#endif +#endif +#else +#ifdef DNS_MAX_SOURCE_PORTS +#undef DNS_MAX_SOURCE_PORTS +#endif +#define DNS_MAX_SOURCE_PORTS 1 +#endif + +#if LWIP_IPV4 && LWIP_IPV6 +#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) (((t) == LWIP_DNS_ADDRTYPE_IPV6_IPV4) || ((t) == LWIP_DNS_ADDRTYPE_IPV6)) +#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) (IP_IS_V6_VAL(ip) ? LWIP_DNS_ADDRTYPE_IS_IPV6(t) : (!LWIP_DNS_ADDRTYPE_IS_IPV6(t))) +#define LWIP_DNS_ADDRTYPE_ARG(x) , x +#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) x +#define LWIP_DNS_SET_ADDRTYPE(x, y) do { x = y; } while(0) +#else +#if LWIP_IPV6 +#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 1 +#else +#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 0 +#endif +#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) 1 +#define LWIP_DNS_ADDRTYPE_ARG(x) +#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) 0 +#define LWIP_DNS_SET_ADDRTYPE(x, y) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#if LWIP_DNS_SUPPORT_MDNS_QUERIES +#define LWIP_DNS_ISMDNS_ARG(x) , x +#else +#define LWIP_DNS_ISMDNS_ARG(x) +#endif + +/** DNS query message structure. + No packing needed: only used locally on the stack. */ +struct dns_query { + /* DNS query record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; +}; +#define SIZEOF_DNS_QUERY 4 + +/** DNS answer message structure. + No packing needed: only used locally on the stack. */ +struct dns_answer { + /* DNS answer record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; + u32_t ttl; + u16_t len; +}; +#define SIZEOF_DNS_ANSWER 10 +/* maximum allowed size for the struct due to non-packed */ +#define SIZEOF_DNS_ANSWER_ASSERT 12 + +/* DNS table entry states */ +typedef enum { + DNS_STATE_UNUSED = 0, + DNS_STATE_NEW = 1, + DNS_STATE_ASKING = 2, + DNS_STATE_DONE = 3 +} dns_state_enum_t; + +/** DNS table entry */ +struct dns_table_entry { + u32_t ttl; + ip_addr_t ipaddr; + u16_t txid; + u8_t state; + u8_t server_idx; + u8_t tmr; + u8_t retries; + u8_t seqno; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + u8_t pcb_idx; +#endif + char name[DNS_MAX_NAME_LENGTH]; +#if LWIP_IPV4 && LWIP_IPV6 + u8_t reqaddrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + u8_t is_mdns; +#endif +}; + +/** DNS request table entry: used when dns_gehostbyname cannot answer the + * request from the DNS table */ +struct dns_req_entry { + /* pointer to callback on DNS query done */ + dns_found_callback found; + /* argument passed to the callback function */ + void *arg; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + u8_t dns_table_idx; +#endif +#if LWIP_IPV4 && LWIP_IPV6 + u8_t reqaddrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +}; + +#if DNS_LOCAL_HOSTLIST + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Local host-list. For hostnames in this list, no + * external name resolution is performed */ +static struct local_hostlist_entry *local_hostlist_dynamic; +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE +#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */ +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST +#define DNS_LOCAL_HOSTLIST_STORAGE_POST +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */ +DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[] + DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT; + +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +static void dns_init_local(void); +static err_t dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)); +#endif /* DNS_LOCAL_HOSTLIST */ + + +/* forward declarations */ +static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); +static void dns_check_entries(void); +static void dns_call_found(u8_t idx, ip_addr_t* addr); + +/*----------------------------------------------------------------------------- + * Globals + *----------------------------------------------------------------------------*/ + +/* DNS variables */ +static struct udp_pcb *dns_pcbs[DNS_MAX_SOURCE_PORTS]; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +static u8_t dns_last_pcb_idx; +#endif +static u8_t dns_seqno; +static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; +static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS]; +static ip_addr_t dns_servers[DNS_MAX_SERVERS]; + +#if LWIP_IPV4 +const ip_addr_t dns_mquery_v4group = DNS_MQUERY_IPV4_GROUP_INIT; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 +const ip_addr_t dns_mquery_v6group = DNS_MQUERY_IPV6_GROUP_INIT; +#endif /* LWIP_IPV6 */ + +/** + * Initialize the resolver: set up the UDP pcb and configure the default server + * (if DNS_SERVER_ADDRESS is set). + */ +void +dns_init(void) +{ +#ifdef DNS_SERVER_ADDRESS + /* initialize default DNS server address */ + ip_addr_t dnsserver; + DNS_SERVER_ADDRESS(&dnsserver); + dns_setserver(0, &dnsserver); +#endif /* DNS_SERVER_ADDRESS */ + + LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY", + sizeof(struct dns_query) == SIZEOF_DNS_QUERY); + LWIP_ASSERT("sanity check SIZEOF_DNS_ANSWER", + sizeof(struct dns_answer) <= SIZEOF_DNS_ANSWER_ASSERT); + + LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n")); + + /* if dns client not yet initialized... */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) + if (dns_pcbs[0] == NULL) { + dns_pcbs[0] = udp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ASSERT("dns_pcbs[0] != NULL", dns_pcbs[0] != NULL); + + /* initialize DNS table not needed (initialized to zero since it is a + * global variable) */ + LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0", + DNS_STATE_UNUSED == 0); + + /* initialize DNS client */ + udp_bind(dns_pcbs[0], IP_ANY_TYPE, 0); + udp_recv(dns_pcbs[0], dns_recv, NULL); + } +#endif + +#if DNS_LOCAL_HOSTLIST + dns_init_local(); +#endif +} + +/** + * @ingroup dns + * Initialize one of the DNS servers. + * + * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS + * @param dnsserver IP address of the DNS server to set + */ +void +dns_setserver(u8_t numdns, const ip_addr_t *dnsserver) +{ + if (numdns < DNS_MAX_SERVERS) { + if (dnsserver != NULL) { + dns_servers[numdns] = (*dnsserver); + +#ifdef RT_USING_NETDEV + extern struct netif *netif_list; + extern struct netdev *netdev_get_by_name(const char *name); + extern void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server); + struct netif *netif = NULL; + + /* set network interface device DNS server address */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + netdev_low_level_set_dns_server(netdev_get_by_name(netif->name), numdns, dnsserver); + } +#endif /* RT_USING_NETDEV */ + } else { + dns_servers[numdns] = *IP_ADDR_ANY; + } + } +} + +/** + * @ingroup dns + * Obtain one of the currently configured DNS server. + * + * @param numdns the index of the DNS server + * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS + * server has not been configured. + */ +const ip_addr_t* +dns_getserver(u8_t numdns) +{ + if (numdns < DNS_MAX_SERVERS) { + return &dns_servers[numdns]; + } else { + return IP_ADDR_ANY; + } +} + +/** + * The DNS resolver client timer - handle retries and timeouts and should + * be called every DNS_TMR_INTERVAL milliseconds (every second by default). + */ +void +dns_tmr(void) +{ + LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n")); + dns_check_entries(); +} + +#if DNS_LOCAL_HOSTLIST +static void +dns_init_local(void) +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) + size_t i; + struct local_hostlist_entry *entry; + /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */ + struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT; + size_t namelen; + for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_init); i++) { + struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; + LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL); + namelen = strlen(init_entry->name); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); + if (entry != NULL) { + char* entry_name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY(entry_name, init_entry->name, namelen); + entry_name[namelen] = 0; + entry->name = entry_name; + entry->addr = init_entry->addr; + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */ +} + +/** + * @ingroup dns + * Iterate the local host-list for a hostname. + * + * @param iterator_fn a function that is called for every entry in the local host-list + * @param iterator_arg 3rd argument passed to iterator_fn + * @return the number of entries in the local host-list + */ +size_t +dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg) +{ + size_t i; +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC + struct local_hostlist_entry *entry = local_hostlist_dynamic; + i = 0; + while (entry != NULL) { + if (iterator_fn != NULL) { + iterator_fn(entry->name, &entry->addr, iterator_arg); + } + i++; + entry = entry->next; + } +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) { + if (iterator_fn != NULL) { + iterator_fn(local_hostlist_static[i].name, &local_hostlist_static[i].addr, iterator_arg); + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + return i; +} + +/** + * @ingroup dns + * Scans the local host-list for a hostname. + * + * @param hostname Hostname to look for in the local host-list + * @param addr the first IP address for the hostname in the local host-list or + * IPADDR_NONE if not found. + * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 (ATTENTION: no fallback here!) + * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 (ATTENTION: no fallback here!) + * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only + * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only + * @return ERR_OK if found, ERR_ARG if not found + */ +err_t +dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype) +{ + LWIP_UNUSED_ARG(dns_addrtype); + return dns_lookup_local(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)); +} + +/* Internal implementation for dns_local_lookup and dns_lookup */ +static err_t +dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC + struct local_hostlist_entry *entry = local_hostlist_dynamic; + while (entry != NULL) { + if ((lwip_stricmp(entry->name, hostname) == 0) && + LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) { + if (addr) { + ip_addr_copy(*addr, entry->addr); + } + return ERR_OK; + } + entry = entry->next; + } +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + size_t i; + for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) { + if ((lwip_stricmp(local_hostlist_static[i].name, hostname) == 0) && + LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) { + if (addr) { + ip_addr_copy(*addr, local_hostlist_static[i].addr); + } + return ERR_OK; + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + return ERR_ARG; +} + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** + * @ingroup dns + * Remove all entries from the local host-list for a specific hostname + * and/or IP address + * + * @param hostname hostname for which entries shall be removed from the local + * host-list + * @param addr address for which entries shall be removed from the local host-list + * @return the number of removed entries + */ +int +dns_local_removehost(const char *hostname, const ip_addr_t *addr) +{ + int removed = 0; + struct local_hostlist_entry *entry = local_hostlist_dynamic; + struct local_hostlist_entry *last_entry = NULL; + while (entry != NULL) { + if (((hostname == NULL) || !lwip_stricmp(entry->name, hostname)) && + ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) { + struct local_hostlist_entry *free_entry; + if (last_entry != NULL) { + last_entry->next = entry->next; + } else { + local_hostlist_dynamic = entry->next; + } + free_entry = entry; + entry = entry->next; + memp_free(MEMP_LOCALHOSTLIST, free_entry); + removed++; + } else { + last_entry = entry; + entry = entry->next; + } + } + return removed; +} + +/** + * @ingroup dns + * Add a hostname/IP address pair to the local host-list. + * Duplicates are not checked. + * + * @param hostname hostname of the new entry + * @param addr IP address of the new entry + * @return ERR_OK if succeeded or ERR_MEM on memory error + */ +err_t +dns_local_addhost(const char *hostname, const ip_addr_t *addr) +{ + struct local_hostlist_entry *entry; + size_t namelen; + char* entry_name; + LWIP_ASSERT("invalid host name (NULL)", hostname != NULL); + namelen = strlen(hostname); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + if (entry == NULL) { + return ERR_MEM; + } + entry_name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY(entry_name, hostname, namelen); + entry_name[namelen] = 0; + entry->name = entry_name; + ip_addr_copy(entry->addr, *addr); + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + return ERR_OK; +} +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** + * @ingroup dns + * Look up a hostname in the array of known hostnames. + * + * @note This function only looks in the internal array of known + * hostnames, it does not send out a query for the hostname if none + * was found. The function dns_enqueue() can be used to send a query + * for a hostname. + * + * @param name the hostname to look up + * @param addr the hostname's IP address, as u32_t (instead of ip_addr_t to + * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname + * was not found in the cached dns_table. + * @return ERR_OK if found, ERR_ARG if not found + */ +static err_t +dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) +{ + u8_t i; +#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) +#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */ +#if DNS_LOCAL_HOSTLIST + if (dns_lookup_local(name, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { + return ERR_OK; + } +#endif /* DNS_LOCAL_HOSTLIST */ +#ifdef DNS_LOOKUP_LOCAL_EXTERN + if (DNS_LOOKUP_LOCAL_EXTERN(name, addr, LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(dns_addrtype)) == ERR_OK) { + return ERR_OK; + } +#endif /* DNS_LOOKUP_LOCAL_EXTERN */ + + /* Walk through name list, return entry if found. If not, return NULL. */ + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + if ((dns_table[i].state == DNS_STATE_DONE) && + (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0) && + LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); + ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + if (addr) { + ip_addr_copy(*addr, dns_table[i].ipaddr); + } + return ERR_OK; + } + } + + return ERR_ARG; +} + +/** + * Compare the "dotted" name "query" with the encoded name "response" + * to make sure an answer from the DNS server matches the current dns_table + * entry (otherwise, answers might arrive late for hostname not on the list + * any more). + * + * @param query hostname (not encoded) from the dns_table + * @param p pbuf containing the encoded hostname in the DNS response + * @param start_offset offset into p where the name starts + * @return 0xFFFF: names differ, other: names equal -> offset behind name + */ +static u16_t +dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset) +{ + int n; + u16_t response_offset = start_offset; + + do { + n = pbuf_try_get_at(p, response_offset++); + if (n < 0) { + return 0xFFFF; + } + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name: cannot be equal since we don't send them */ + return 0xFFFF; + } else { + /* Not compressed name */ + while (n > 0) { + int c = pbuf_try_get_at(p, response_offset); + if (c < 0) { + return 0xFFFF; + } + if ((*query) != (u8_t)c) { + return 0xFFFF; + } + ++response_offset; + ++query; + --n; + } + ++query; + } + n = pbuf_try_get_at(p, response_offset); + if (n < 0) { + return 0xFFFF; + } + } while (n != 0); + + return response_offset + 1; +} + +/** + * Walk through a compact encoded DNS name and return the end of the name. + * + * @param p pbuf containing the name + * @param query_idx start index into p pointing to encoded DNS name in the DNS server response + * @return index to end of the name + */ +static u16_t +dns_skip_name(struct pbuf* p, u16_t query_idx) +{ + int n; + u16_t offset = query_idx; + + do { + n = pbuf_try_get_at(p, offset++); + if (n < 0) { + return 0xFFFF; + } + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name: since we only want to skip it (not check it), stop here */ + break; + } else { + /* Not compressed name */ + if (offset + n >= p->tot_len) { + return 0xFFFF; + } + offset = (u16_t)(offset + n); + } + n = pbuf_try_get_at(p, offset); + if (n < 0) { + return 0xFFFF; + } + } while (n != 0); + + return offset + 1; +} + +/** + * Send a DNS query packet. + * + * @param idx the DNS table entry index for which to send a request + * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise + */ +static err_t +dns_send(u8_t idx) +{ + err_t err; + struct dns_hdr hdr; + struct dns_query qry; + struct pbuf *p; + u16_t query_idx, copy_len; + const char *hostname, *hostname_part; + u8_t n; + u8_t pcb_idx; + struct dns_table_entry* entry = &dns_table[idx]; + + LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", + (u16_t)(entry->server_idx), entry->name)); + LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS); + if (ip_addr_isany_val(dns_servers[entry->server_idx]) +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + && !entry->is_mdns +#endif + ) { + /* DNS server not valid anymore, e.g. PPP netif has been shut down */ + /* call specified callback function if provided */ + dns_call_found(idx, NULL); + /* flush this entry */ + entry->state = DNS_STATE_UNUSED; + return ERR_OK; + } + + /* if here, we have either a new query or a retry on a previous query to process */ + p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 + + SIZEOF_DNS_QUERY), PBUF_RAM); + if (p != NULL) { + const ip_addr_t* dst; + u16_t dst_port; + /* fill dns header */ + memset(&hdr, 0, SIZEOF_DNS_HDR); + hdr.id = lwip_htons(entry->txid); + hdr.flags1 = DNS_FLAG1_RD; + hdr.numquestions = PP_HTONS(1); + pbuf_take(p, &hdr, SIZEOF_DNS_HDR); + hostname = entry->name; + --hostname; + + /* convert hostname into suitable query format. */ + query_idx = SIZEOF_DNS_HDR; + do { + ++hostname; + hostname_part = hostname; + for (n = 0; *hostname != '.' && *hostname != 0; ++hostname) { + ++n; + } + copy_len = (u16_t)(hostname - hostname_part); + pbuf_put_at(p, query_idx, n); + pbuf_take_at(p, hostname_part, copy_len, query_idx + 1); + query_idx += n + 1; + } while (*hostname != 0); + pbuf_put_at(p, query_idx, 0); + query_idx++; + + /* fill dns query */ + if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) { + qry.type = PP_HTONS(DNS_RRTYPE_AAAA); + } else { + qry.type = PP_HTONS(DNS_RRTYPE_A); + } + qry.cls = PP_HTONS(DNS_RRCLASS_IN); + pbuf_take_at(p, &qry, SIZEOF_DNS_QUERY, query_idx); + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + pcb_idx = entry->pcb_idx; +#else + pcb_idx = 0; +#endif + /* send dns packet */ + LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n", + entry->txid, entry->name, entry->server_idx)); +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + if (entry->is_mdns) { + dst_port = DNS_MQUERY_PORT; +#if LWIP_IPV6 + if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) + { + dst = &dns_mquery_v6group; + } +#endif +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif +#if LWIP_IPV4 + { + dst = &dns_mquery_v4group; + } +#endif + } else +#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ + { + dst_port = DNS_SERVER_PORT; + dst = &dns_servers[entry->server_idx]; + } + err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port); + + /* free pbuf */ + pbuf_free(p); + } else { + err = ERR_MEM; + } + + return err; +} + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +static struct udp_pcb* +dns_alloc_random_port(void) +{ + err_t err; + struct udp_pcb* ret; + + ret = udp_new_ip_type(IPADDR_TYPE_ANY); + if (ret == NULL) { + /* out of memory, have to reuse an existing pcb */ + return NULL; + } + do { + u16_t port = (u16_t)DNS_RAND_TXID(); + if (!DNS_PORT_ALLOWED(port)) { + /* this port is not allowed, try again */ + err = ERR_USE; + continue; + } + err = udp_bind(ret, IP_ANY_TYPE, port); + } while (err == ERR_USE); + if (err != ERR_OK) { + udp_remove(ret); + return NULL; + } + udp_recv(ret, dns_recv, NULL); + return ret; +} + +/** + * dns_alloc_pcb() - allocates a new pcb (or reuses an existing one) to be used + * for sending a request + * + * @return an index into dns_pcbs + */ +static u8_t +dns_alloc_pcb(void) +{ + u8_t i; + u8_t idx; + + for (i = 0; i < DNS_MAX_SOURCE_PORTS; i++) { + if (dns_pcbs[i] == NULL) { + break; + } + } + if (i < DNS_MAX_SOURCE_PORTS) { + dns_pcbs[i] = dns_alloc_random_port(); + if (dns_pcbs[i] != NULL) { + /* succeeded */ + dns_last_pcb_idx = i; + return i; + } + } + /* if we come here, creating a new UDP pcb failed, so we have to use + an already existing one */ + for (i = 0, idx = dns_last_pcb_idx + 1; i < DNS_MAX_SOURCE_PORTS; i++, idx++) { + if (idx >= DNS_MAX_SOURCE_PORTS) { + idx = 0; + } + if (dns_pcbs[idx] != NULL) { + dns_last_pcb_idx = idx; + return idx; + } + } + return DNS_MAX_SOURCE_PORTS; +} +#endif /* ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) */ + +/** + * dns_call_found() - call the found callback and check if there are duplicate + * entries for the given hostname. If there are any, their found callback will + * be called and they will be removed. + * + * @param idx dns table index of the entry that is resolved or removed + * @param addr IP address for the hostname (or NULL on error or memory shortage) + */ +static void +dns_call_found(u8_t idx, ip_addr_t* addr) +{ +#if ((LWIP_DNS_SECURE & (LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT)) != 0) + u8_t i; +#endif + +#if LWIP_IPV4 && LWIP_IPV6 + if (addr != NULL) { + /* check that address type matches the request and adapt the table entry */ + if (IP_IS_V6_VAL(*addr)) { + LWIP_ASSERT("invalid response", LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype)); + dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6; + } else { + LWIP_ASSERT("invalid response", !LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype)); + dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4; + } + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + for (i = 0; i < DNS_MAX_REQUESTS; i++) { + if (dns_requests[i].found && (dns_requests[i].dns_table_idx == idx)) { + (*dns_requests[i].found)(dns_table[idx].name, addr, dns_requests[i].arg); + /* flush this entry */ + dns_requests[i].found = NULL; + } + } +#else + if (dns_requests[idx].found) { + (*dns_requests[idx].found)(dns_table[idx].name, addr, dns_requests[idx].arg); + } + dns_requests[idx].found = NULL; +#endif +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + /* close the pcb used unless other request are using it */ + for (i = 0; i < DNS_MAX_REQUESTS; i++) { + if (i == idx) { + continue; /* only check other requests */ + } + if (dns_table[i].state == DNS_STATE_ASKING) { + if (dns_table[i].pcb_idx == dns_table[idx].pcb_idx) { + /* another request is still using the same pcb */ + dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; + break; + } + } + } + if (dns_table[idx].pcb_idx < DNS_MAX_SOURCE_PORTS) { + /* if we come here, the pcb is not used any more and can be removed */ + udp_remove(dns_pcbs[dns_table[idx].pcb_idx]); + dns_pcbs[dns_table[idx].pcb_idx] = NULL; + dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; + } +#endif +} + +/* Create a query transmission ID that is unique for all outstanding queries */ +static u16_t +dns_create_txid(void) +{ + u16_t txid; + u8_t i; + +again: + txid = (u16_t)DNS_RAND_TXID(); + + /* check whether the ID is unique */ + for (i = 0; i < DNS_TABLE_SIZE; i++) { + if ((dns_table[i].state == DNS_STATE_ASKING) && + (dns_table[i].txid == txid)) { + /* ID already used by another pending query */ + goto again; + } + } + + return txid; +} + +/** + * dns_check_entry() - see if entry has not yet been queried and, if so, sends out a query. + * Check an entry in the dns_table: + * - send out query for new entries + * - retry old pending entries on timeout (also with different servers) + * - remove completed entries from the table if their TTL has expired + * + * @param i index of the dns_table entry to check + */ +static void +dns_check_entry(u8_t i) +{ + err_t err; + struct dns_table_entry *entry = &dns_table[i]; + + LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE); + + switch (entry->state) { + case DNS_STATE_NEW: + /* initialize new entry */ + entry->txid = dns_create_txid(); + entry->state = DNS_STATE_ASKING; + entry->server_idx = 0; + entry->tmr = 1; + entry->retries = 0; + + /* send DNS packet for this entry */ + err = dns_send(i); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + break; + case DNS_STATE_ASKING: + if (--entry->tmr == 0) { + if (++entry->retries == DNS_MAX_RETRIES) { + if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1]) +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + && !entry->is_mdns +#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ + ) { + /* change of server */ + entry->server_idx++; + entry->tmr = 1; + entry->retries = 0; + } else { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", entry->name)); + /* call specified callback function if provided */ + dns_call_found(i, NULL); + /* flush this entry */ + entry->state = DNS_STATE_UNUSED; + break; + } + } else { + /* wait longer for the next retry */ + entry->tmr = entry->retries; + } + + /* send DNS packet for this entry */ + err = dns_send(i); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + } + break; + case DNS_STATE_DONE: + /* if the time to live is nul */ + if ((entry->ttl == 0) || (--entry->ttl == 0)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", entry->name)); + /* flush this entry, there cannot be any related pending entries in this state */ + entry->state = DNS_STATE_UNUSED; + } + break; + case DNS_STATE_UNUSED: + /* nothing to do */ + break; + default: + LWIP_ASSERT("unknown dns_table entry state:", 0); + break; + } +} + +/** + * Call dns_check_entry for each entry in dns_table - check all entries. + */ +static void +dns_check_entries(void) +{ + u8_t i; + + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + dns_check_entry(i); + } +} + +/** + * Save TTL and call dns_call_found for correct response. + */ +static void +dns_correct_response(u8_t idx, u32_t ttl) +{ + struct dns_table_entry *entry = &dns_table[idx]; + + entry->state = DNS_STATE_DONE; + + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name)); + ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr))); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + + /* read the answer resource record's TTL, and maximize it if needed */ + entry->ttl = ttl; + if (entry->ttl > DNS_MAX_TTL) { + entry->ttl = DNS_MAX_TTL; + } + dns_call_found(idx, &entry->ipaddr); + + if (entry->ttl == 0) { + /* RFC 883, page 29: "Zero values are + interpreted to mean that the RR can only be used for the + transaction in progress, and should not be cached." + -> flush this entry now */ + /* entry reused during callback? */ + if (entry->state == DNS_STATE_DONE) { + entry->state = DNS_STATE_UNUSED; + } + } +} +/** + * Receive input function for DNS response packets arriving for the dns UDP pcb. + */ +static void +dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + u8_t i; + u16_t txid; + u16_t res_idx; + struct dns_hdr hdr; + struct dns_answer ans; + struct dns_query qry; + u16_t nquestions, nanswers; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(port); + + /* is the dns message big enough ? */ + if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n")); + /* free pbuf and return */ + goto memerr; + } + + /* copy dns payload inside static buffer for processing */ + if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) { + /* Match the ID in the DNS header with the name table. */ + txid = lwip_htons(hdr.id); + for (i = 0; i < DNS_TABLE_SIZE; i++) { + const struct dns_table_entry *entry = &dns_table[i]; + if ((entry->state == DNS_STATE_ASKING) && + (entry->txid == txid)) { + + /* We only care about the question(s) and the answers. The authrr + and the extrarr are simply discarded. */ + nquestions = lwip_htons(hdr.numquestions); + nanswers = lwip_htons(hdr.numanswers); + + /* Check for correct response. */ + if ((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": not a response\n", entry->name)); + goto memerr; /* ignore this packet */ + } + if (nquestions != 1) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); + goto memerr; /* ignore this packet */ + } + +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + if (!entry->is_mdns) +#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ + { + /* Check whether response comes from the same network address to which the + question was sent. (RFC 5452) */ + if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) { + goto memerr; /* ignore this packet */ + } + } + + /* Check if the name in the "question" part match with the name in the entry and + skip it if equal. */ + res_idx = dns_compare_name(entry->name, p, SIZEOF_DNS_HDR); + if (res_idx == 0xFFFF) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); + goto memerr; /* ignore this packet */ + } + + /* check if "question" part matches the request */ + if (pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx) != SIZEOF_DNS_QUERY) { + goto memerr; /* ignore this packet */ + } + if ((qry.cls != PP_HTONS(DNS_RRCLASS_IN)) || + (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_AAAA))) || + (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_A)))) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); + goto memerr; /* ignore this packet */ + } + /* skip the rest of the "question" part */ + res_idx += SIZEOF_DNS_QUERY; + + /* Check for error. If so, call callback to inform. */ + if (hdr.flags2 & DNS_FLAG2_ERR_MASK) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", entry->name)); + } else { + while ((nanswers > 0) && (res_idx < p->tot_len)) { + /* skip answer resource record's host name */ + res_idx = dns_skip_name(p, res_idx); + if (res_idx == 0xFFFF) { + goto memerr; /* ignore this packet */ + } + + /* Check for IP address type and Internet class. Others are discarded. */ + if (pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx) != SIZEOF_DNS_ANSWER) { + goto memerr; /* ignore this packet */ + } + res_idx += SIZEOF_DNS_ANSWER; + + if (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) { +#if LWIP_IPV4 + if ((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.len == PP_HTONS(sizeof(ip4_addr_t)))) { +#if LWIP_IPV4 && LWIP_IPV6 + if (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + { + ip4_addr_t ip4addr; + /* read the IP address after answer resource record's header */ + if (pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx) != sizeof(ip4_addr_t)) { + goto memerr; /* ignore this packet */ + } + ip_addr_copy_from_ip4(dns_table[i].ipaddr, ip4addr); + pbuf_free(p); + /* handle correct response */ + dns_correct_response(i, lwip_ntohl(ans.ttl)); + return; + } + } +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + if ((ans.type == PP_HTONS(DNS_RRTYPE_AAAA)) && (ans.len == PP_HTONS(sizeof(ip6_addr_t)))) { +#if LWIP_IPV4 && LWIP_IPV6 + if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + { + ip6_addr_t ip6addr; + /* read the IP address after answer resource record's header */ + if (pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx) != sizeof(ip6_addr_t)) { + goto memerr; /* ignore this packet */ + } + ip_addr_copy_from_ip6(dns_table[i].ipaddr, ip6addr); + pbuf_free(p); + /* handle correct response */ + dns_correct_response(i, lwip_ntohl(ans.ttl)); + return; + } + } +#endif /* LWIP_IPV6 */ + } + /* skip this answer */ + if ((int)(res_idx + lwip_htons(ans.len)) > 0xFFFF) { + goto memerr; /* ignore this packet */ + } + res_idx += lwip_htons(ans.len); + --nanswers; + } +#if LWIP_IPV4 && LWIP_IPV6 + if ((entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || + (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) { + if (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) { + /* IPv4 failed, try IPv6 */ + dns_table[i].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6; + } else { + /* IPv6 failed, try IPv4 */ + dns_table[i].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4; + } + pbuf_free(p); + dns_table[i].state = DNS_STATE_NEW; + dns_check_entry(i); + return; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", entry->name)); + } + /* call callback to indicate error, clean up memory and return */ + pbuf_free(p); + dns_call_found(i, NULL); + dns_table[i].state = DNS_STATE_UNUSED; + return; + } + } + } + +memerr: + /* deallocate memory and return */ + pbuf_free(p); + return; +} + +/** + * Queues a new hostname to resolve and sends out a DNS query for that hostname + * + * @param name the hostname that is to be queried + * @param hostnamelen length of the hostname + * @param found a callback function to be called on success, failure or timeout + * @param callback_arg argument to pass to the callback function + * @return err_t return code. + */ +static err_t +dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, + void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype) LWIP_DNS_ISMDNS_ARG(u8_t is_mdns)) +{ + u8_t i; + u8_t lseq, lseqi; + struct dns_table_entry *entry = NULL; + size_t namelen; + struct dns_req_entry* req; + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + u8_t r; + /* check for duplicate entries */ + for (i = 0; i < DNS_TABLE_SIZE; i++) { + if ((dns_table[i].state == DNS_STATE_ASKING) && + (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0)) { +#if LWIP_IPV4 && LWIP_IPV6 + if (dns_table[i].reqaddrtype != dns_addrtype) { + /* requested address types don't match + this can lead to 2 concurrent requests, but mixing the address types + for the same host should not be that common */ + continue; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + /* this is a duplicate entry, find a free request entry */ + for (r = 0; r < DNS_MAX_REQUESTS; r++) { + if (dns_requests[r].found == 0) { + dns_requests[r].found = found; + dns_requests[r].arg = callback_arg; + dns_requests[r].dns_table_idx = i; + LWIP_DNS_SET_ADDRTYPE(dns_requests[r].reqaddrtype, dns_addrtype); + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": duplicate request\n", name)); + return ERR_INPROGRESS; + } + } + } + } + /* no duplicate entries found */ +#endif + + /* search an unused entry, or the oldest one */ + lseq = 0; + lseqi = DNS_TABLE_SIZE; + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + entry = &dns_table[i]; + /* is it an unused entry ? */ + if (entry->state == DNS_STATE_UNUSED) { + break; + } + /* check if this is the oldest completed entry */ + if (entry->state == DNS_STATE_DONE) { + u8_t age = dns_seqno - entry->seqno; + if (age > lseq) { + lseq = age; + lseqi = i; + } + } + } + + /* if we don't have found an unused entry, use the oldest completed one */ + if (i == DNS_TABLE_SIZE) { + if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) { + /* no entry can be used now, table is full */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name)); + return ERR_MEM; + } else { + /* use the oldest completed one */ + i = lseqi; + entry = &dns_table[i]; + } + } + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + /* find a free request entry */ + req = NULL; + for (r = 0; r < DNS_MAX_REQUESTS; r++) { + if (dns_requests[r].found == NULL) { + req = &dns_requests[r]; + break; + } + } + if (req == NULL) { + /* no request entry can be used now, table is full */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS request entries table is full\n", name)); + return ERR_MEM; + } + req->dns_table_idx = i; +#else + /* in this configuration, the entry index is the same as the request index */ + req = &dns_requests[i]; +#endif + + /* use this entry */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); + + /* fill the entry */ + entry->state = DNS_STATE_NEW; + entry->seqno = dns_seqno; + LWIP_DNS_SET_ADDRTYPE(entry->reqaddrtype, dns_addrtype); + LWIP_DNS_SET_ADDRTYPE(req->reqaddrtype, dns_addrtype); + req->found = found; + req->arg = callback_arg; + namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH-1); + MEMCPY(entry->name, name, namelen); + entry->name[namelen] = 0; + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + entry->pcb_idx = dns_alloc_pcb(); + if (entry->pcb_idx >= DNS_MAX_SOURCE_PORTS) { + /* failed to get a UDP pcb */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": failed to allocate a pcb\n", name)); + entry->state = DNS_STATE_UNUSED; + req->found = NULL; + return ERR_MEM; + } + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx))); +#endif + +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + entry->is_mdns = is_mdns; +#endif + + dns_seqno++; + + /* force to send query without waiting timer */ + dns_check_entry(i); + + /* dns query is enqueued */ + return ERR_INPROGRESS; +} + +/** + * @ingroup dns + * Resolve a hostname (string) into an IP address. + * NON-BLOCKING callback version for use with raw API!!! + * + * Returns immediately with one of err_t return codes: + * - ERR_OK if hostname is a valid IP address string or the host + * name is already in the local names table. + * - ERR_INPROGRESS enqueue a request to be sent to the DNS server + * for resolution if no errors are present. + * - ERR_ARG: dns client not initialized or invalid hostname + * + * @param hostname the hostname that is to be queried + * @param addr pointer to a ip_addr_t where to store the address if it is already + * cached in the dns_table (only valid if ERR_OK is returned!) + * @param found a callback function to be called on success, failure or timeout (only if + * ERR_INPROGRESS is returned!) + * @param callback_arg argument to pass to the callback function + * @return a err_t return code. + */ +err_t +dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, + void *callback_arg) +{ + return dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, LWIP_DNS_ADDRTYPE_DEFAULT); +} + +/** + * @ingroup dns + * Like dns_gethostbyname, but returned address type can be controlled: + * @param hostname the hostname that is to be queried + * @param addr pointer to a ip_addr_t where to store the address if it is already + * cached in the dns_table (only valid if ERR_OK is returned!) + * @param found a callback function to be called on success, failure or timeout (only if + * ERR_INPROGRESS is returned!) + * @param callback_arg argument to pass to the callback function + * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only + * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only + * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only + * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only + */ +err_t +dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, + void *callback_arg, u8_t dns_addrtype) +{ + size_t hostnamelen; +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + u8_t is_mdns; +#endif + /* not initialized or no valid server yet, or invalid addr pointer + * or invalid hostname or invalid hostname length */ + if ((addr == NULL) || + (!hostname) || (!hostname[0])) { + return ERR_ARG; + } +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) + if (dns_pcbs[0] == NULL) { + return ERR_ARG; + } +#endif + hostnamelen = strlen(hostname); + if (hostnamelen >= DNS_MAX_NAME_LENGTH) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: name too long to resolve")); + return ERR_ARG; + } + + +#if LWIP_HAVE_LOOPIF + if (strcmp(hostname, "localhost") == 0) { + ip_addr_set_loopback(LWIP_DNS_ADDRTYPE_IS_IPV6(dns_addrtype), addr); + return ERR_OK; + } +#endif /* LWIP_HAVE_LOOPIF */ + + /* host name already in octet notation? set ip addr and return ERR_OK */ + if (ipaddr_aton(hostname, addr)) { +#if LWIP_IPV4 && LWIP_IPV6 + if ((IP_IS_V6(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV4)) || + (IP_IS_V4(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV6))) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + { + return ERR_OK; + } + } + /* already have this address cached? */ + if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { + return ERR_OK; + } +#if LWIP_IPV4 && LWIP_IPV6 + if ((dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) { + /* fallback to 2nd IP type and try again to lookup */ + u8_t fallback; + if (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) { + fallback = LWIP_DNS_ADDRTYPE_IPV6; + } else { + fallback = LWIP_DNS_ADDRTYPE_IPV4; + } + if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(fallback)) == ERR_OK) { + return ERR_OK; + } + } +#else /* LWIP_IPV4 && LWIP_IPV6 */ + LWIP_UNUSED_ARG(dns_addrtype); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + if (strstr(hostname, ".local") == &hostname[hostnamelen] - 6) { + is_mdns = 1; + } else { + is_mdns = 0; + } + + if (!is_mdns) +#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ + { + /* prevent calling found callback if no server is set, return error instead */ + if (ip_addr_isany_val(dns_servers[0])) { + return ERR_VAL; + } + } + + /* queue query with specified callback */ + return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype) + LWIP_DNS_ISMDNS_ARG(is_mdns)); +} + +#endif /* LWIP_DNS */ diff --git a/components/net/lwip-2.0.3/src/core/inet_chksum.c b/components/net/lwip-2.0.3/src/core/inet_chksum.c new file mode 100644 index 0000000000..917f3e4f1a --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/inet_chksum.c @@ -0,0 +1,609 @@ +/** + * @file + * Incluse internet checksum functions.\n + * + * These are some reference implementations of the checksum algorithm, with the + * aim of being simple, correct and fully portable. Checksumming is the + * first thing you would want to optimize for your platform. If you create + * your own version, link it in and in your cc.h put: + * + * \#define LWIP_CHKSUM your_checksum_routine + * + * Or you can select from the implementations below by defining + * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/inet_chksum.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" + +#include + +#ifndef LWIP_CHKSUM +# define LWIP_CHKSUM lwip_standard_chksum +# ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 2 +# endif +u16_t lwip_standard_chksum(const void *dataptr, int len); +#endif +/* If none set: */ +#ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 0 +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ +/** + * lwip checksum + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * @note accumulator size limits summable length to 64k + * @note host endianess is irrelevant (p3 RFC1071) + */ +u16_t +lwip_standard_chksum(const void *dataptr, int len) +{ + u32_t acc; + u16_t src; + const u8_t *octetptr; + + acc = 0; + /* dataptr may be at odd or even addresses */ + octetptr = (const u8_t*)dataptr; + while (len > 1) { + /* declare first octet as most significant + thus assume network order, ignoring host order */ + src = (*octetptr) << 8; + octetptr++; + /* declare second octet as least significant */ + src |= (*octetptr); + octetptr++; + acc += src; + len -= 2; + } + if (len > 0) { + /* accumulate remaining octet */ + src = (*octetptr) << 8; + acc += src; + } + /* add deferred carry bits */ + acc = (acc >> 16) + (acc & 0x0000ffffUL); + if ((acc & 0xffff0000UL) != 0) { + acc = (acc >> 16) + (acc & 0x0000ffffUL); + } + /* This maybe a little confusing: reorder sum using lwip_htons() + instead of lwip_ntohs() since it has a little less call overhead. + The caller must invert bits for Internet sum ! */ + return lwip_htons((u16_t)acc); +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ +/* + * Curt McDowell + * Broadcom Corp. + * csm@broadcom.com + * + * IP checksum two bytes at a time with support for + * unaligned buffer. + * Works for len up to and including 0x20000. + * by Curt McDowell, Broadcom Corp. 12/08/2005 + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + */ +u16_t +lwip_standard_chksum(const void *dataptr, int len) +{ + const u8_t *pb = (const u8_t *)dataptr; + const u16_t *ps; + u16_t t = 0; + u32_t sum = 0; + int odd = ((mem_ptr_t)pb & 1); + + /* Get aligned to u16_t */ + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + /* Add the bulk of the data */ + ps = (const u16_t *)(const void *)pb; + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* Consume left-over byte, if any */ + if (len > 0) { + ((u8_t *)&t)[0] = *(const u8_t *)ps; + } + + /* Add end bytes */ + sum += t; + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + /* Swap if alignment was odd */ + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ +/** + * An optimized checksum routine. Basically, it uses loop-unrolling on + * the checksum loop, treating the head and tail bytes specially, whereas + * the inner loop acts on 8 bytes at a time. + * + * @arg start of buffer to be checksummed. May be an odd byte address. + * @len number of bytes in the buffer to be checksummed. + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * by Curt McDowell, Broadcom Corp. December 8th, 2005 + */ +u16_t +lwip_standard_chksum(const void *dataptr, int len) +{ + const u8_t *pb = (const u8_t *)dataptr; + const u16_t *ps; + u16_t t = 0; + const u32_t *pl; + u32_t sum = 0, tmp; + /* starts at odd byte address? */ + int odd = ((mem_ptr_t)pb & 1); + + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + ps = (const u16_t *)(const void*)pb; + + if (((mem_ptr_t)ps & 3) && len > 1) { + sum += *ps++; + len -= 2; + } + + pl = (const u32_t *)(const void*)ps; + + while (len > 7) { + tmp = sum + *pl++; /* ping */ + if (tmp < sum) { + tmp++; /* add back carry */ + } + + sum = tmp + *pl++; /* pong */ + if (sum < tmp) { + sum++; /* add back carry */ + } + + len -= 8; + } + + /* make room in upper bits */ + sum = FOLD_U32T(sum); + + ps = (const u16_t *)pl; + + /* 16-bit aligned word remaining? */ + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* dangling tail byte remaining? */ + if (len > 0) { /* include odd byte */ + ((u8_t *)&t)[0] = *(const u8_t *)ps; + } + + sum += t; /* add end bytes */ + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ +static u16_t +inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc) +{ + struct pbuf *q; + u8_t swapped = 0; + + /* iterate through all pbuf in chain */ + for (q = p; q != NULL; q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + acc += LWIP_CHKSUM(q->payload, q->len); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* just executing this next line is probably faster that the if statement needed + to check whether we really need to execute it, and does no harm */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + + acc += (u32_t)lwip_htons((u16_t)proto); + acc += (u32_t)lwip_htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +#if LWIP_IPV4 +/* inet_chksum_pseudo: + * + * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip4_addr_t *src, const ip4_addr_t *dest) +{ + u32_t acc; + u32_t addr; + + addr = ip4_addr_get_u32(src); + acc = (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_base(p, proto, proto_len, acc); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. + * IPv6 addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param proto ipv6 protocol/next header (used for checksum of pseudo header) + * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) + * @param src source ipv6 address (used for checksum of pseudo header) + * @param dest destination ipv6 address (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip6_addr_t *src, const ip6_addr_t *dest) +{ + u32_t acc = 0; + u32_t addr; + u8_t addr_part; + + for (addr_part = 0; addr_part < 4; addr_part++) { + addr = src->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = dest->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + } + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_base(p, proto, proto_len, acc); +} +#endif /* LWIP_IPV6 */ + +/* ip_chksum_pseudo: + * + * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip_addr_t *src, const ip_addr_t *dest) +{ +#if LWIP_IPV6 + if (IP_IS_V6(dest)) { + return ip6_chksum_pseudo(p, proto, proto_len, ip_2_ip6(src), ip_2_ip6(dest)); + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_IPV4 + { + return inet_chksum_pseudo(p, proto, proto_len, ip_2_ip4(src), ip_2_ip4(dest)); + } +#endif /* LWIP_IPV4 */ +} + +/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ +static u16_t +inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, u32_t acc) +{ + struct pbuf *q; + u8_t swapped = 0; + u16_t chklen; + + /* iterate through all pbuf in chain */ + for (q = p; (q != NULL) && (chksum_len > 0); q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + chklen = q->len; + if (chklen > chksum_len) { + chklen = chksum_len; + } + acc += LWIP_CHKSUM(q->payload, chklen); + chksum_len -= chklen; + LWIP_ASSERT("delete me", chksum_len < 0x7fff); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* fold the upper bit down */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + + acc += (u32_t)lwip_htons((u16_t)proto); + acc += (u32_t)lwip_htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +#if LWIP_IPV4 +/* inet_chksum_pseudo_partial: + * + * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest) +{ + u32_t acc; + u32_t addr; + + addr = ip4_addr_get_u32(src); + acc = (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. + * IPv6 addresses are expected to be in network byte order. Will only compute for a + * portion of the payload. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param proto ipv6 protocol/next header (used for checksum of pseudo header) + * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) + * @param chksum_len number of payload bytes used to compute chksum + * @param src source ipv6 address (used for checksum of pseudo header) + * @param dest destination ipv6 address (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest) +{ + u32_t acc = 0; + u32_t addr; + u8_t addr_part; + + for (addr_part = 0; addr_part < 4; addr_part++) { + addr = src->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = dest->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + } + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); +} +#endif /* LWIP_IPV6 */ + +/* ip_chksum_pseudo_partial: + * + * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest) +{ +#if LWIP_IPV6 + if (IP_IS_V6(dest)) { + return ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip6(src), ip_2_ip6(dest)); + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_IPV4 + { + return inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip4(src), ip_2_ip4(dest)); + } +#endif /* LWIP_IPV4 */ +} + +/* inet_chksum: + * + * Calculates the Internet checksum over a portion of memory. Used primarily for IP + * and ICMP. + * + * @param dataptr start of the buffer to calculate the checksum (no alignment needed) + * @param len length of the buffer to calculate the checksum + * @return checksum (as u16_t) to be saved directly in the protocol header + */ + +u16_t +inet_chksum(const void *dataptr, u16_t len) +{ + return (u16_t)~(unsigned int)LWIP_CHKSUM(dataptr, len); +} + +/** + * Calculate a checksum over a chain of pbufs (without pseudo-header, much like + * inet_chksum only pbufs are used). + * + * @param p pbuf chain over that the checksum should be calculated + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pbuf(struct pbuf *p) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + for (q = p; q != NULL; q = q->next) { + acc += LWIP_CHKSUM(q->payload, q->len); + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + return (u16_t)~(acc & 0xffffUL); +} + +/* These are some implementations for LWIP_CHKSUM_COPY, which copies data + * like MEMCPY but generates a checksum at the same time. Since this is a + * performance-sensitive function, you might want to create your own version + * in assembly targeted at your hardware by defining it in lwipopts.h: + * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) + */ + +#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ +/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. + * For architectures with big caches, data might still be in cache when + * generating the checksum after copying. + */ +u16_t +lwip_chksum_copy(void *dst, const void *src, u16_t len) +{ + MEMCPY(dst, src, len); + return LWIP_CHKSUM(dst, len); +} +#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */ diff --git a/components/net/lwip-2.0.3/src/core/init.c b/components/net/lwip-2.0.3/src/core/init.c new file mode 100644 index 0000000000..ea3b5ebebf --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/init.c @@ -0,0 +1,385 @@ +/** + * @file + * Modules initialization + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +#include "lwip/opt.h" + +#include "lwip/init.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/sockets.h" +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/timeouts.h" +#include "lwip/etharp.h" +#include "lwip/ip6.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/api.h" + +#include "netif/ppp/ppp_opts.h" +#include "netif/ppp/ppp_impl.h" + +#ifndef LWIP_SKIP_PACKING_CHECK + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct packed_struct_test +{ + PACK_STRUCT_FLD_8(u8_t dummy1); + PACK_STRUCT_FIELD(u32_t dummy2); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define PACKED_STRUCT_TEST_EXPECTED_SIZE 5 + +#endif + +/* Compile-time sanity checks for configuration errors. + * These can be done independently of LWIP_DEBUG, without penalty. + */ +#ifndef BYTE_ORDER + #error "BYTE_ORDER is not defined, you have to define it in your cc.h" +#endif +#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV) + #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_UDPLITE) + #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DHCP) + #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_MULTICAST_TX_OPTIONS) + #error "If you want to use IGMP/LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DNS) + #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */ +#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0)) + #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h" +#endif +#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0)) + #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0)) + #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) + #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1)) + #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS) + #error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && !LWIP_IPV4) + #error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h" +#endif +#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4) + #error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h" +#endif +#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0)) + #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h" +#endif +/* There must be sufficient timeouts, taking into account requirements of the subsystems. */ +#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0))) + #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" +#endif +#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS)) + #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" +#endif +#endif /* !MEMP_MEM_MALLOC */ +#if LWIP_WND_SCALE +#if (LWIP_TCP && (TCP_WND > 0xffffffff)) + #error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_RCV_SCALE > 14)) + #error "The maximum valid window scale value is 14!" +#endif +#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE))) + #error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!" +#endif +#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0)) + #error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!" +#endif +#else /* LWIP_WND_SCALE */ +#if (LWIP_TCP && (TCP_WND > 0xffff)) + #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)" +#endif +#endif /* LWIP_WND_SCALE */ +#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) + #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) + #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" +#endif +#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) + #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" +#endif +#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff))) + #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" +#endif +#if (LWIP_NETIF_API && (NO_SYS==1)) + #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1)) + #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (LWIP_PPP_API && (NO_SYS==1)) + #error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (LWIP_PPP_API && (PPP_SUPPORT==0)) + #error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP) + #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK) + #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h" +#endif +#if (!LWIP_ARP && LWIP_AUTOIP) + #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API))) + #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h" +#endif +#if (MEM_LIBC_MALLOC && MEM_USE_POOLS) + #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h" +#endif +#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS) + #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h" +#endif +#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT) + #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf" +#endif +#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) + #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" +#endif +#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT + #error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on" +#endif +#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT + #error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on" +#endif +#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4 + #error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on" +#endif +#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6 + #error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on" +#endif +#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) + #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" +#endif +#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING + #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" +#endif +#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE + #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets" +#endif +#if LWIP_NETCONN && LWIP_TCP +#if NETCONN_COPY != TCP_WRITE_FLAG_COPY + #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY" +#endif +#if NETCONN_MORE != TCP_WRITE_FLAG_MORE + #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE" +#endif +#endif /* LWIP_NETCONN && LWIP_TCP */ +#if LWIP_SOCKET +/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */ +#if SO_REUSEADDR != SOF_REUSEADDR + #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR" +#endif +#if SO_KEEPALIVE != SOF_KEEPALIVE + #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE" +#endif +#if SO_BROADCAST != SOF_BROADCAST + #error "WARNING: SO_BROADCAST != SOF_BROADCAST" +#endif +#endif /* LWIP_SOCKET */ + + +/* Compile-time checks for deprecated options. + */ +#ifdef MEMP_NUM_TCPIP_MSG + #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef TCP_REXMIT_DEBUG + #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef RAW_STATS + #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_QUEUE_FIRST + #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_ALWAYS_INSERT + #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h." +#endif +#if !NO_SYS && LWIP_TCPIP_CORE_LOCKING && LWIP_COMPAT_MUTEX && !defined(LWIP_COMPAT_MUTEX_ALLOWED) + #error "LWIP_COMPAT_MUTEX cannot prevent priority inversion. It is recommended to implement priority-aware mutexes. (Define LWIP_COMPAT_MUTEX_ALLOWED to disable this error.)" +#endif + +#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS +#define LWIP_DISABLE_TCP_SANITY_CHECKS 0 +#endif +#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0 +#endif + +/* MEMP sanity checks */ +#if MEMP_MEM_MALLOC +#if !LWIP_DISABLE_MEMP_SANITY_CHECKS +#if LWIP_NETCONN || LWIP_SOCKET +#if !MEMP_NUM_NETCONN && LWIP_SOCKET +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!" +#endif +#else /* MEMP_MEM_MALLOC */ +#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB) +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* LWIP_NETCONN || LWIP_SOCKET */ +#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */ +#if MEM_USE_POOLS +#error "MEMP_MEM_MALLOC and MEM_USE_POOLS cannot be enabled at the same time" +#endif +#ifdef LWIP_HOOK_MEMP_AVAILABLE +#error "LWIP_HOOK_MEMP_AVAILABLE doesn't make sense with MEMP_MEM_MALLOC" +#endif +#endif /* MEMP_MEM_MALLOC */ + +/* TCP sanity checks */ +#if !LWIP_DISABLE_TCP_SANITY_CHECKS +#if LWIP_TCP +#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) + #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_BUF < (2 * TCP_MSS) + #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS)) + #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDLOWAT >= TCP_SND_BUF + #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS)) + #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!" +#endif +#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN + #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) + #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) + #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_WND < TCP_MSS + #error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* LWIP_TCP */ +#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */ + +/** + * @ingroup lwip_nosys + * Initialize all modules. + * Use this in NO_SYS mode. Use tcpip_init() otherwise. + */ +void +lwip_init(void) +{ +#ifndef LWIP_SKIP_CONST_CHECK + int a = 0; + LWIP_UNUSED_ARG(a); + LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a); +#endif +#ifndef LWIP_SKIP_PACKING_CHECK + LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE); +#endif + + /* Modules initialization */ + stats_init(); +#if !NO_SYS + sys_init(); +#endif /* !NO_SYS */ + mem_init(); + memp_init(); + pbuf_init(); + netif_init(); +#if LWIP_IPV4 + ip_init(); +#if LWIP_ARP + etharp_init(); +#endif /* LWIP_ARP */ +#endif /* LWIP_IPV4 */ +#if LWIP_RAW + raw_init(); +#endif /* LWIP_RAW */ +#if LWIP_UDP + udp_init(); +#endif /* LWIP_UDP */ +#if LWIP_TCP + tcp_init(); +#endif /* LWIP_TCP */ +#if LWIP_IGMP + igmp_init(); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + dns_init(); +#endif /* LWIP_DNS */ +#if PPP_SUPPORT + ppp_init(); +#endif + +#if LWIP_TIMERS + sys_timeouts_init(); +#endif /* LWIP_TIMERS */ +} diff --git a/components/net/lwip-2.0.3/src/core/ip.c b/components/net/lwip-2.0.3/src/core/ip.c new file mode 100644 index 0000000000..2e0240851f --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ip.c @@ -0,0 +1,124 @@ +/** + * @file + * Common IPv4 and IPv6 code + * + * @defgroup ip IP + * @ingroup callbackstyle_api + * + * @defgroup ip4 IPv4 + * @ingroup ip + * + * @defgroup ip6 IPv6 + * @ingroup ip + * + * @defgroup ipaddr IP address handling + * @ingroup infrastructure + * + * @defgroup ip4addr IPv4 only + * @ingroup ipaddr + * + * @defgroup ip6addr IPv6 only + * @ingroup ipaddr + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 || LWIP_IPV6 + +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +/** Global data for both IPv4 and IPv6 */ +struct ip_globals ip_data; + +#if LWIP_IPV4 && LWIP_IPV6 + +const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT; + +/** + * @ingroup ipaddr + * Convert IP address string (both versions) to numeric. + * The version is auto-detected from the string. + * + * @param cp IP address string to convert + * @param addr conversion result is stored here + * @return 1 on success, 0 on error + */ +int +ipaddr_aton(const char *cp, ip_addr_t *addr) +{ + if (cp != NULL) { + const char* c; + for (c = cp; *c != 0; c++) { + if (*c == ':') { + /* contains a colon: IPv6 address */ + if (addr) { + IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); + } + return ip6addr_aton(cp, ip_2_ip6(addr)); + } else if (*c == '.') { + /* contains a dot: IPv4 address */ + break; + } + } + /* call ip4addr_aton as fallback or if IPv4 was found */ + if (addr) { + IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); + } + return ip4addr_aton(cp, ip_2_ip4(addr)); + } + return 0; +} + +/** + * @ingroup lwip_nosys + * If both IP versions are enabled, this function can dispatch packets to the correct one. + * Don't call directly, pass to netif_add() and call netif->input(). + */ +err_t +ip_input(struct pbuf *p, struct netif *inp) +{ + if (p != NULL) { + if (IP_HDR_GET_VERSION(p->payload) == 6) { + return ip6_input(p, inp); + } + return ip4_input(p, inp); + } + return ERR_VAL; +} + +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#endif /* LWIP_IPV4 || LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.3/src/core/ipv4/autoip.c b/components/net/lwip-2.0.3/src/core/ipv4/autoip.c new file mode 100644 index 0000000000..10db8a3444 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv4/autoip.c @@ -0,0 +1,527 @@ +/** + * @file + * AutoIP Automatic LinkLocal IP Configuration + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * @defgroup autoip AUTOIP + * @ingroup ip4 + * AUTOIP related functions + * USAGE: + * + * define @ref LWIP_AUTOIP 1 in your lwipopts.h + * Options: + * AUTOIP_TMR_INTERVAL msecs, + * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. + * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... + * + * Without DHCP: + * - Call autoip_start() after netif_add(). + * + * With DHCP: + * - define @ref LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. + * - Configure your DHCP Client. + * + * @see netifapi_autoip + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +/* #include "lwip/udp.h" */ +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/autoip.h" +#include "lwip/etharp.h" +#include "lwip/prot/autoip.h" + +#include + +/** Pseudo random macro based on netif informations. + * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ +#ifndef LWIP_AUTOIP_RAND +#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ + ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ + ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ + ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ + (netif_autoip_data(netif)? netif_autoip_data(netif)->tried_llipaddr : 0)) +#endif /* LWIP_AUTOIP_RAND */ + +/** + * Macro that generates the initial IP address to be tried by AUTOIP. + * If you want to override this, define it to something else in lwipopts.h. + */ +#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR +#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ + lwip_htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ + ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) +#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ + +/* static functions */ +static err_t autoip_arp_announce(struct netif *netif); +static void autoip_start_probing(struct netif *netif); + +/** + * @ingroup autoip + * Set a statically allocated struct autoip to work with. + * Using this prevents autoip_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct autoip + * @param autoip (uninitialised) autoip struct allocated by the application + */ +void +autoip_set_struct(struct netif *netif, struct autoip *autoip) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("autoip != NULL", autoip != NULL); + LWIP_ASSERT("netif already has a struct autoip set", + netif_autoip_data(netif) == NULL); + + /* clear data structure */ + memset(autoip, 0, sizeof(struct autoip)); + /* autoip->state = AUTOIP_STATE_OFF; */ + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); +} + +/** Restart AutoIP client and check the next address (conflict detected) + * + * @param netif The netif under AutoIP control + */ +static void +autoip_restart(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + autoip->tried_llipaddr++; + autoip_start(netif); +} + +/** + * Handle a IP address conflict after an ARP conflict detection + */ +static void +autoip_handle_arp_conflict(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + + /* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where + a) means retreat on the first conflict and + b) allows to keep an already configured address when having only one + conflict in 10 seconds + We use option b) since it helps to improve the chance that one of the two + conflicting hosts may be able to retain its address. */ + + if (autoip->lastconflict > 0) { + /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); + + /* Active TCP sessions are aborted when removing the ip addresss */ + autoip_restart(netif); + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); + autoip_arp_announce(netif); + autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } +} + +/** + * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * + * @param netif network interface on which create the IP-Address + * @param ipaddr ip address to initialize + */ +static void +autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr) +{ + struct autoip* autoip = netif_autoip_data(netif); + + /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * compliant to RFC 3927 Section 2.1 + * We have 254 * 256 possibilities */ + + u32_t addr = lwip_ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); + addr += autoip->tried_llipaddr; + addr = AUTOIP_NET | (addr & 0xffff); + /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ + + if (addr < AUTOIP_RANGE_START) { + addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + if (addr > AUTOIP_RANGE_END) { + addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && + (addr <= AUTOIP_RANGE_END)); + ip4_addr_set_u32(ipaddr, lwip_htonl(addr)); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (u16_t)(autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), + ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); +} + +/** + * Sends an ARP probe from a network interface + * + * @param netif network interface used to send the probe + */ +static err_t +autoip_arp_probe(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + /* this works because netif->ip_addr is ANY */ + return etharp_request(netif, &autoip->llipaddr); +} + +/** + * Sends an ARP announce from a network interface + * + * @param netif network interface used to send the announce + */ +static err_t +autoip_arp_announce(struct netif *netif) +{ + return etharp_gratuitous(netif); +} + +/** + * Configure interface for use with current LL IP-Address + * + * @param netif network interface to configure with current LL IP-Address + */ +static err_t +autoip_bind(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + ip4_addr_t sn_mask, gw_addr; + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + + IP4_ADDR(&sn_mask, 255, 255, 0, 0); + IP4_ADDR(&gw_addr, 0, 0, 0, 0); + + netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr); + /* interface is used by routing now that an address is set */ + + return ERR_OK; +} + +/** + * @ingroup autoip + * Start AutoIP client + * + * @param netif network interface on which start the AutoIP client + */ +err_t +autoip_start(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + err_t result = ERR_OK; + + LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); + + /* Set IP-Address, Netmask and Gateway to 0 to make sure that + * ARP Packets are formed correctly + */ + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], + netif->name[1], (u16_t)netif->num)); + if (autoip == NULL) { + /* no AutoIP client attached yet? */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): starting new AUTOIP client\n")); + autoip = (struct autoip *)mem_malloc(sizeof(struct autoip)); + if (autoip == NULL) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): could not allocate autoip\n")); + return ERR_MEM; + } + memset(autoip, 0, sizeof(struct autoip)); + /* store this AutoIP client in the netif */ + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); + } else { + autoip->state = AUTOIP_STATE_OFF; + autoip->ttw = 0; + autoip->sent_num = 0; + ip4_addr_set_zero(&autoip->llipaddr); + autoip->lastconflict = 0; + } + + autoip_create_addr(netif, &(autoip->llipaddr)); + autoip_start_probing(netif); + + return result; +} + +static void +autoip_start_probing(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + + autoip->state = AUTOIP_STATE_PROBING; + autoip->sent_num = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + + /* time to wait to first probe, this is randomly + * chosen out of 0 to PROBE_WAIT seconds. + * compliant to RFC 3927 Section 2.2.1 + */ + autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND)); + + /* + * if we tried more then MAX_CONFLICTS we must limit our rate for + * acquiring and probing address + * compliant to RFC 3927 Section 2.2.1 + */ + if (autoip->tried_llipaddr > MAX_CONFLICTS) { + autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } +} + +/** + * Handle a possible change in the network configuration. + * + * If there is an AutoIP address configured, take the interface down + * and begin probing with the same address. + */ +void +autoip_network_changed(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + + if (autoip && (autoip->state != AUTOIP_STATE_OFF)) { + autoip_start_probing(netif); + } +} + +/** + * @ingroup autoip + * Stop AutoIP client + * + * @param netif network interface on which stop the AutoIP client + */ +err_t +autoip_stop(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + + if (autoip != NULL) { + autoip->state = AUTOIP_STATE_OFF; + if (ip4_addr_islinklocal(netif_ip4_addr(netif))) { + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + } + } + return ERR_OK; +} + +/** + * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds + */ +void +autoip_tmr(void) +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + struct autoip* autoip = netif_autoip_data(netif); + /* only act on AutoIP configured interfaces */ + if (autoip != NULL) { + if (autoip->lastconflict > 0) { + autoip->lastconflict--; + } + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", + (u16_t)(autoip->state), autoip->ttw)); + + if (autoip->ttw > 0) { + autoip->ttw--; + } + + switch(autoip->state) { + case AUTOIP_STATE_PROBING: + if (autoip->ttw == 0) { + if (autoip->sent_num >= PROBE_NUM) { + /* Switch to ANNOUNCING: now we can bind to an IP address and use it */ + autoip->state = AUTOIP_STATE_ANNOUNCING; + autoip_bind(netif); + /* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP + which counts as an announcement */ + autoip->sent_num = 1; + autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + } else { + autoip_arp_probe(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n")); + autoip->sent_num++; + if (autoip->sent_num == PROBE_NUM) { + /* calculate time to wait to for announce */ + autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + } else { + /* calculate time to wait to next probe */ + autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % + ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + + PROBE_MIN * AUTOIP_TICKS_PER_SECOND); + } + } + } + break; + + case AUTOIP_STATE_ANNOUNCING: + if (autoip->ttw == 0) { + autoip_arp_announce(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n")); + autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; + autoip->sent_num++; + + if (autoip->sent_num >= ANNOUNCE_NUM) { + autoip->state = AUTOIP_STATE_BOUND; + autoip->sent_num = 0; + autoip->ttw = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + } + } + break; + + default: + /* nothing to do in other states */ + break; + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * Handles every incoming ARP Packet, called by etharp_input(). + * + * @param netif network interface to use for autoip processing + * @param hdr Incoming ARP packet + */ +void +autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) +{ + struct autoip* autoip = netif_autoip_data(netif); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); + if ((autoip != NULL) && (autoip->state != AUTOIP_STATE_OFF)) { + /* when ip.src == llipaddr && hw.src != netif->hwaddr + * + * when probing ip.dst == llipaddr && hw.src != netif->hwaddr + * we have a conflict and must solve it + */ + ip4_addr_t sipaddr, dipaddr; + struct eth_addr netifaddr; + ETHADDR16_COPY(netifaddr.addr, netif->hwaddr); + + /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). + */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + if (autoip->state == AUTOIP_STATE_PROBING) { + /* RFC 3927 Section 2.2.1: + * from beginning to after ANNOUNCE_WAIT + * seconds we have a conflict if + * ip.src == llipaddr OR + * ip.dst == llipaddr && hw.src != own hwaddr + */ + if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) || + (ip4_addr_isany_val(sipaddr) && + ip4_addr_cmp(&dipaddr, &autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Probe Conflict detected\n")); + autoip_restart(netif); + } + } else { + /* RFC 3927 Section 2.5: + * in any state we have a conflict if + * ip.src == llipaddr && hw.src != own hwaddr + */ + if (ip4_addr_cmp(&sipaddr, &autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); + autoip_handle_arp_conflict(netif); + } + } + } +} + +/** check if AutoIP supplied netif->ip_addr + * + * @param netif the netif to check + * @return 1 if AutoIP supplied netif->ip_addr (state BOUND or ANNOUNCING), + * 0 otherwise + */ +u8_t +autoip_supplied_address(const struct netif *netif) +{ + if ((netif != NULL) && (netif_autoip_data(netif) != NULL)) { + struct autoip* autoip = netif_autoip_data(netif); + return (autoip->state == AUTOIP_STATE_BOUND) || (autoip->state == AUTOIP_STATE_ANNOUNCING); + } + return 0; +} + +u8_t +autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr) +{ + struct autoip* autoip = netif_autoip_data(netif); + return (autoip != NULL) && ip4_addr_cmp(addr, &(autoip->llipaddr)); +} + +#endif /* LWIP_IPV4 && LWIP_AUTOIP */ diff --git a/components/net/lwip-2.0.3/src/core/ipv4/dhcp.c b/components/net/lwip-2.0.3/src/core/ipv4/dhcp.c new file mode 100644 index 0000000000..0cf97b0340 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv4/dhcp.c @@ -0,0 +1,1951 @@ +/** + * @file + * Dynamic Host Configuration Protocol client + * + * @defgroup dhcp4 DHCPv4 + * @ingroup ip4 + * DHCP (IPv4) related functions + * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform + * with RFC 2131 and RFC 2132. + * + * @todo: + * - Support for interfaces other than Ethernet (SLIP, PPP, ...) + * + * Options: + * @ref DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) + * @ref DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) + * + * dhcp_start() starts a DHCP client instance which + * configures the interface by obtaining an IP address lease and maintaining it. + * + * Use dhcp_release() to end the lease and use dhcp_stop() + * to remove the DHCP client. + * + * @see netifapi_dhcp4 + */ + +/* + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. + * + * Author: Leon Woestenberg + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/dns.h" +#include "lwip/etharp.h" +#include "lwip/prot/dhcp.h" + +#include + +/** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using + * LWIP_RAND() (this overrides DHCP_GLOBAL_XID) + */ +#ifndef DHCP_CREATE_RAND_XID +#define DHCP_CREATE_RAND_XID 1 +#endif + +/** Default for DHCP_GLOBAL_XID is 0xABCD0000 + * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g. + * \#define DHCP_GLOBAL_XID_HEADER "stdlib.h" + * \#define DHCP_GLOBAL_XID rand() + */ +#ifdef DHCP_GLOBAL_XID_HEADER +#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */ +#endif + +/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU + * MTU is checked to be big enough in dhcp_start */ +#define DHCP_MAX_MSG_LEN(netif) (netif->mtu) +#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 +/** Minimum length for reply before packet is parsed */ +#define DHCP_MIN_REPLY_LEN 44 + +#define REBOOT_TRIES 2 + +#if LWIP_DNS && LWIP_DHCP_MAX_DNS_SERVERS +#if DNS_MAX_SERVERS > LWIP_DHCP_MAX_DNS_SERVERS +#define LWIP_DHCP_PROVIDE_DNS_SERVERS LWIP_DHCP_MAX_DNS_SERVERS +#else +#define LWIP_DHCP_PROVIDE_DNS_SERVERS DNS_MAX_SERVERS +#endif +#else +#define LWIP_DHCP_PROVIDE_DNS_SERVERS 0 +#endif + +/** Option handling: options are parsed in dhcp_parse_reply + * and saved in an array where other functions can load them from. + * This might be moved into the struct dhcp (not necessarily since + * lwIP is single-threaded and the array is only used while in recv + * callback). */ +enum dhcp_option_idx { + DHCP_OPTION_IDX_OVERLOAD = 0, + DHCP_OPTION_IDX_MSG_TYPE, + DHCP_OPTION_IDX_SERVER_ID, + DHCP_OPTION_IDX_LEASE_TIME, + DHCP_OPTION_IDX_T1, + DHCP_OPTION_IDX_T2, + DHCP_OPTION_IDX_SUBNET_MASK, + DHCP_OPTION_IDX_ROUTER, +#if LWIP_DHCP_PROVIDE_DNS_SERVERS + DHCP_OPTION_IDX_DNS_SERVER, + DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1, +#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ +#if LWIP_DHCP_GET_NTP_SRV + DHCP_OPTION_IDX_NTP_SERVER, + DHCP_OPTION_IDX_NTP_SERVER_LAST = DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS - 1, +#endif /* LWIP_DHCP_GET_NTP_SRV */ + DHCP_OPTION_IDX_MAX +}; + +/** Holds the decoded option values, only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX]; +/** Holds a flag which option was received and is contained in dhcp_rx_options_val, + only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; + +static u8_t dhcp_discover_request_options[] = { + DHCP_OPTION_SUBNET_MASK, + DHCP_OPTION_ROUTER, + DHCP_OPTION_BROADCAST +#if LWIP_DHCP_PROVIDE_DNS_SERVERS + , DHCP_OPTION_DNS_SERVER +#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ +#if LWIP_DHCP_GET_NTP_SRV + , DHCP_OPTION_NTP +#endif /* LWIP_DHCP_GET_NTP_SRV */ + }; + +#ifdef DHCP_GLOBAL_XID +static u32_t xid; +static u8_t xid_initialised; +#endif /* DHCP_GLOBAL_XID */ + +#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0) +#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1) +#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0) +#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given))) +#define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx]) +#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val)) + +static struct udp_pcb *dhcp_pcb; +static u8_t dhcp_pcb_refcount; + +/* DHCP client state machine functions */ +static err_t dhcp_discover(struct netif *netif); +static err_t dhcp_select(struct netif *netif); +static void dhcp_bind(struct netif *netif); +#if DHCP_DOES_ARP_CHECK +static err_t dhcp_decline(struct netif *netif); +#endif /* DHCP_DOES_ARP_CHECK */ +static err_t dhcp_rebind(struct netif *netif); +static err_t dhcp_reboot(struct netif *netif); +static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state); + +/* receive, unfold, parse and free incoming messages */ +static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); + +/* set the DHCP timers */ +static void dhcp_timeout(struct netif *netif); +static void dhcp_t1_timeout(struct netif *netif); +static void dhcp_t2_timeout(struct netif *netif); + +/* build outgoing messages */ +/* create a DHCP message, fill in common headers */ +static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type); +/* free a DHCP request */ +static void dhcp_delete_msg(struct dhcp *dhcp); +/* add a DHCP option (type, then length in bytes) */ +static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len); +/* add option values */ +static void dhcp_option_byte(struct dhcp *dhcp, u8_t value); +static void dhcp_option_short(struct dhcp *dhcp, u16_t value); +static void dhcp_option_long(struct dhcp *dhcp, u32_t value); +#if LWIP_NETIF_HOSTNAME +static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); +#endif /* LWIP_NETIF_HOSTNAME */ +/* always add the DHCP options trailer to end and pad */ +static void dhcp_option_trailer(struct dhcp *dhcp); + +/** Ensure DHCP PCB is allocated and bound */ +static err_t +dhcp_inc_pcb_refcount(void) +{ + if (dhcp_pcb_refcount == 0) { + LWIP_ASSERT("dhcp_inc_pcb_refcount(): memory leak", dhcp_pcb == NULL); + + /* allocate UDP PCB */ + dhcp_pcb = udp_new(); + + if (dhcp_pcb == NULL) { + return ERR_MEM; + } + + ip_set_option(dhcp_pcb, SOF_BROADCAST); + + /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */ + udp_bind(dhcp_pcb, IP4_ADDR_ANY, DHCP_CLIENT_PORT); + udp_connect(dhcp_pcb, IP4_ADDR_ANY, DHCP_SERVER_PORT); + udp_recv(dhcp_pcb, dhcp_recv, NULL); + } + + dhcp_pcb_refcount++; + + return ERR_OK; +} + +/** Free DHCP PCB if the last netif stops using it */ +static void +dhcp_dec_pcb_refcount(void) +{ + LWIP_ASSERT("dhcp_pcb_refcount(): refcount error", (dhcp_pcb_refcount > 0)); + dhcp_pcb_refcount--; + + if (dhcp_pcb_refcount == 0) { + udp_remove(dhcp_pcb); + dhcp_pcb = NULL; + } +} + +/** + * Back-off the DHCP client (because of a received NAK response). + * + * Back-off the DHCP client because of a received NAK. Receiving a + * NAK means the client asked for something non-sensible, for + * example when it tries to renew a lease obtained on another network. + * + * We clear any existing set IP address and restart DHCP negotiation + * afresh (as per RFC2131 3.2.3). + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_nak(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* Change to a defined state - set this before assigning the address + to ensure the callback can use dhcp_supplied_address() */ + dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); + /* remove IP address from interface (must no longer be used, as per RFC2131) */ + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + /* We can immediately restart discovery */ + dhcp_discover(netif); +} + +#if DHCP_DOES_ARP_CHECK +/** + * Checks if the offered IP address is already in use. + * + * It does so by sending an ARP request for the offered address and + * entering CHECKING state. If no ARP reply is received within a small + * interval, the address is assumed to be free for use by us. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_check(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], + (s16_t)netif->name[1])); + dhcp_set_state(dhcp, DHCP_STATE_CHECKING); + /* create an ARP query for the offered IP address, expecting that no host + responds, as the IP address should not be in use. */ + result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); + if (result != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = 500; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs)); +} +#endif /* DHCP_DOES_ARP_CHECK */ + +/** + * Remember the configuration offered by a DHCP server. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_offer(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* obtain the server address */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) { + ip_addr_set_ip4_u32(&dhcp->server_ip_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID))); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", + ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); + /* remember offered address */ + ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif)); + } +} + +/** + * Select a DHCP server offer out of all offers. + * + * Simply select the first offer received. + * + * @param netif the netif under DHCP control + * @return lwIP specific error (see error.h) + */ +static err_t +dhcp_select(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + u16_t msecs; + u8_t i; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + dhcp_set_state(dhcp, DHCP_STATE_REQUESTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + /* MUST request the offered IP address */ + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); + for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); + } + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + dhcp_option_trailer(dhcp); + /* shrink the pbuf to the actual content length */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* send broadcast to any DHCP server */ + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * The DHCP timer that checks for lease renewal/rebind timeouts. + * Must be called once a minute (see @ref DHCP_COARSE_TIMER_SECS). + */ +void +dhcp_coarse_tmr(void) +{ + struct netif *netif = netif_list; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n")); + /* iterate through all network interfaces */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + struct dhcp *dhcp = netif_dhcp_data(netif); + if ((dhcp != NULL) && (dhcp->state != DHCP_STATE_OFF)) { + /* compare lease time to expire timeout */ + if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t0 timeout\n")); + /* this clients' lease time has expired */ + dhcp_release(netif); + dhcp_discover(netif); + /* timer is active (non zero), and triggers (zeroes) now? */ + } else if (dhcp->t2_rebind_time && (dhcp->t2_rebind_time-- == 1)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n")); + /* this clients' rebind timeout triggered */ + dhcp_t2_timeout(netif); + /* timer is active (non zero), and triggers (zeroes) now */ + } else if (dhcp->t1_renew_time && (dhcp->t1_renew_time-- == 1)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n")); + /* this clients' renewal timeout triggered */ + dhcp_t1_timeout(netif); + } + } + /* proceed to next netif */ + netif = netif->next; + } +} + +/** + * DHCP transaction timeout handling (this function must be called every 500ms, + * see @ref DHCP_FINE_TIMER_MSECS). + * + * A DHCP server is expected to respond within a short period of time. + * This timer checks whether an outstanding DHCP request is timed out. + */ +void +dhcp_fine_tmr(void) +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + struct dhcp *dhcp = netif_dhcp_data(netif); + /* only act on DHCP configured interfaces */ + if (dhcp != NULL) { + /* timer is active (non zero), and is about to trigger now */ + if (dhcp->request_timeout > 1) { + dhcp->request_timeout--; + } + else if (dhcp->request_timeout == 1) { + dhcp->request_timeout--; + /* { netif->dhcp->request_timeout == 0 } */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); + /* this client's request timeout triggered */ + dhcp_timeout(netif); + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * A DHCP negotiation transaction, or ARP request, has timed out. + * + * The timer that was started with the DHCP or ARP request has + * timed out, indicating no response was received in time. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n")); + /* back-off period has passed, or server selection timed out */ + if ((dhcp->state == DHCP_STATE_BACKING_OFF) || (dhcp->state == DHCP_STATE_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n")); + dhcp_discover(netif); + /* receiving the requested lease timed out */ + } else if (dhcp->state == DHCP_STATE_REQUESTING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n")); + if (dhcp->tries <= 5) { + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n")); + dhcp_release(netif); + dhcp_discover(netif); + } +#if DHCP_DOES_ARP_CHECK + /* received no ARP reply for the offered address (which is good) */ + } else if (dhcp->state == DHCP_STATE_CHECKING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); + if (dhcp->tries <= 1) { + dhcp_check(netif); + /* no ARP replies on the offered address, + looks like the IP address is indeed free */ + } else { + /* bind the interface to the offered address */ + dhcp_bind(netif); + } +#endif /* DHCP_DOES_ARP_CHECK */ + } else if (dhcp->state == DHCP_STATE_REBOOTING) { + if (dhcp->tries < REBOOT_TRIES) { + dhcp_reboot(netif); + } else { + dhcp_discover(netif); + } + } +} + +/** + * The renewal period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t1_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); + if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || + (dhcp->state == DHCP_STATE_RENEWING)) { + /* just retry to renew - note that the rebind timer (t2) will + * eventually time-out if renew tries fail. */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t1_timeout(): must renew\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */ + dhcp_renew(netif); + /* Calculate next timeout */ + if (((dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + { + dhcp->t1_renew_time = ((dhcp->t2_timeout - dhcp->lease_used) / 2); + } + } +} + +/** + * The rebind period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t2_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); + if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || + (dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) { + /* just retry to rebind */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t2_timeout(): must rebind\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */ + dhcp_rebind(netif); + /* Calculate next timeout */ + if (((dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + { + dhcp->t2_rebind_time = ((dhcp->t0_timeout - dhcp->lease_used) / 2); + } + } +} + +/** + * Handle a DHCP ACK packet + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_ack(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + +#if LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV + u8_t n; +#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV */ +#if LWIP_DHCP_GET_NTP_SRV + ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS]; +#endif + + /* clear options we might not get from the ACK */ + ip4_addr_set_zero(&dhcp->offered_sn_mask); + ip4_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip4_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* lease time given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) { + /* remember offered lease time */ + dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME); + } + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) { + /* remember given renewal period */ + dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1); + } else { + /* calculate safe periods for renewal */ + dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2; + } + + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) { + /* remember given rebind period */ + dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2); + } else { + /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/ + dhcp->offered_t2_rebind = (dhcp->offered_t0_lease * 7U) / 8U; + } + + /* (y)our internet address */ + ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + +#if LWIP_DHCP_BOOTP_FILE + /* copy boot server address, + boot file name copied in dhcp_parse_reply if not overloaded */ + ip4_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* subnet mask given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) { + /* remember given subnet mask */ + ip4_addr_set_u32(&dhcp->offered_sn_mask, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK))); + dhcp->subnet_mask_given = 1; + } else { + dhcp->subnet_mask_given = 0; + } + + /* gateway router */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) { + ip4_addr_set_u32(&dhcp->offered_gw_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER))); + } + +#if LWIP_DHCP_GET_NTP_SRV + /* NTP servers */ + for (n = 0; (n < LWIP_DHCP_MAX_NTP_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n); n++) { + ip4_addr_set_u32(&ntp_server_addrs[n], lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n))); + } + dhcp_set_ntp_servers(n, ntp_server_addrs); +#endif /* LWIP_DHCP_GET_NTP_SRV */ + +#if LWIP_DHCP_PROVIDE_DNS_SERVERS + /* DNS servers */ + for (n = 0; (n < LWIP_DHCP_PROVIDE_DNS_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) { + ip_addr_t dns_addr; + ip_addr_set_ip4_u32(&dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n))); + dns_setserver(n, &dns_addr); + } +#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ +} + +/** + * @ingroup dhcp4 + * Set a statically allocated struct dhcp to work with. + * Using this prevents dhcp_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct dhcp + * @param dhcp (uninitialised) dhcp struct allocated by the application + */ +void +dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("dhcp != NULL", dhcp != NULL); + LWIP_ASSERT("netif already has a struct dhcp set", netif_dhcp_data(netif) == NULL); + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp); +} + +/** + * @ingroup dhcp4 + * Removes a struct dhcp from a netif. + * + * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the + * struct dhcp since the memory is passed back to the heap. + * + * @param netif the netif from which to remove the struct dhcp + */ +void dhcp_cleanup(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + + if (netif_dhcp_data(netif) != NULL) { + mem_free(netif_dhcp_data(netif)); + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL); + } +} + +/** + * @ingroup dhcp4 + * Start DHCP negotiation for a network interface. + * + * If no DHCP client instance was attached to this interface, + * a new client is created first. If a DHCP client instance + * was already present, it restarts negotiation. + * + * @param netif The lwIP network interface + * @return lwIP error code + * - ERR_OK - No error + * - ERR_MEM - Out of memory + */ +err_t +dhcp_start(struct netif *netif) +{ + struct dhcp *dhcp; + err_t result; + + LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); + LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); + dhcp = netif_dhcp_data(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + + /* check MTU of the netif */ + if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n")); + return ERR_MEM; + } + + /* no DHCP client attached yet? */ + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): mallocing new DHCP client\n")); + dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp)); + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); + return ERR_MEM; + } + + /* store this dhcp client in the netif */ + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp")); + /* already has DHCP client attached */ + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); + LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL); + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL ); + + if (dhcp->pcb_allocated != 0) { + dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ + } + /* dhcp is cleared below, no need to reset flag*/ + } + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); + + if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */ + return ERR_MEM; + } + dhcp->pcb_allocated = 1; + +#if LWIP_DHCP_CHECK_LINK_UP + if (!netif_is_link_up(netif)) { + /* set state INIT and wait for dhcp_network_changed() to call dhcp_discover() */ + dhcp_set_state(dhcp, DHCP_STATE_INIT); + return ERR_OK; + } +#endif /* LWIP_DHCP_CHECK_LINK_UP */ + + + /* (re)start the DHCP negotiation */ + result = dhcp_discover(netif); + if (result != ERR_OK) { + /* free resources allocated above */ + dhcp_stop(netif); + return ERR_MEM; + } + return result; +} + +/** + * @ingroup dhcp4 + * Inform a DHCP server of our manual configuration. + * + * This informs DHCP servers of our fixed IP address configuration + * by sending an INFORM message. It does not involve DHCP address + * configuration, it is just here to be nice to the network. + * + * @param netif The lwIP network interface + */ +void +dhcp_inform(struct netif *netif) +{ + struct dhcp dhcp; + err_t result = ERR_OK; + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */ + return; + } + + memset(&dhcp, 0, sizeof(struct dhcp)); + dhcp_set_state(&dhcp, DHCP_STATE_INFORMING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM); + if (result == ERR_OK) { + dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option_trailer(&dhcp); + + pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); + + udp_sendto_if(dhcp_pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + + dhcp_delete_msg(&dhcp); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n")); + } + + dhcp_dec_pcb_refcount(); /* delete DHCP PCB if not needed any more */ +} + +/** Handle a possible change in the network configuration. + * + * This enters the REBOOTING state to verify that the currently bound + * address is still valid. + */ +void +dhcp_network_changed(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + if (!dhcp) + return; + switch (dhcp->state) { + case DHCP_STATE_REBINDING: + case DHCP_STATE_RENEWING: + case DHCP_STATE_BOUND: + case DHCP_STATE_REBOOTING: + dhcp->tries = 0; + dhcp_reboot(netif); + break; + case DHCP_STATE_OFF: + /* stay off */ + break; + default: + /* INIT/REQUESTING/CHECKING/BACKING_OFF restart with new 'rid' because the + state changes, SELECTING: continue with current 'rid' as we stay in the + same state */ +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + /* ensure we start with short timeouts, even if already discovering */ + dhcp->tries = 0; + dhcp_discover(netif); + break; + } +} + +#if DHCP_DOES_ARP_CHECK +/** + * Match an ARP reply with the offered IP address: + * check whether the offered IP address is not in use using ARP + * + * @param netif the network interface on which the reply was received + * @param addr The IP address we received a reply from + */ +void +dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr) +{ + struct dhcp *dhcp; + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + dhcp = netif_dhcp_data(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); + /* is a DHCP client doing an ARP check? */ + if ((dhcp != NULL) && (dhcp->state == DHCP_STATE_CHECKING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", + ip4_addr_get_u32(addr))); + /* did a host respond with the address we + were offered by the DHCP server? */ + if (ip4_addr_cmp(addr, &dhcp->offered_ip_addr)) { + /* we will not accept the offered address */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); + dhcp_decline(netif); + } + } +} + +/** + * Decline an offered lease. + * + * Tell the DHCP server we do not accept the offered address. + * One reason to decline the lease is when we find out the address + * is already in use by another host (through ARP). + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_decline(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result = ERR_OK; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); + dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option_trailer(dhcp); + /* resize pbuf to reflect true size of options */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* per section 4.4.4, broadcast DECLINE messages */ + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_decline: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = 10*1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} +#endif /* DHCP_DOES_ARP_CHECK */ + + +/** + * Start the DHCP process, discover a DHCP server. + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_discover(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result = ERR_OK; + u16_t msecs; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); + ip4_addr_set_any(&dhcp->offered_ip_addr); + dhcp_set_state(dhcp, DHCP_STATE_SELECTING); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER); + if (result == ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); + for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); + } + dhcp_option_trailer(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) { + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON; + autoip_start(netif); + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Bind the interface to the offered IP address. + * + * @param netif network interface to bind to the offered address + */ +static void +dhcp_bind(struct netif *netif) +{ + u32_t timeout; + struct dhcp *dhcp; + ip4_addr_t sn_mask, gw_addr; + LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); + dhcp = netif_dhcp_data(netif); + LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + + /* reset time used of lease */ + dhcp->lease_used = 0; + + if (dhcp->offered_t0_lease != 0xffffffffUL) { + /* set renewal period timer */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease)); + timeout = (dhcp->offered_t0_lease + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if (timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t0_timeout = (u16_t)timeout; + if (dhcp->t0_timeout == 0) { + dhcp->t0_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease*1000)); + } + + /* temporary DHCP lease? */ + if (dhcp->offered_t1_renew != 0xffffffffUL) { + /* set renewal period timer */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); + timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if (timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t1_timeout = (u16_t)timeout; + if (dhcp->t1_timeout == 0) { + dhcp->t1_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); + dhcp->t1_renew_time = dhcp->t1_timeout; + } + /* set renewal period timer */ + if (dhcp->offered_t2_rebind != 0xffffffffUL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); + timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if (timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t2_timeout = (u16_t)timeout; + if (dhcp->t2_timeout == 0) { + dhcp->t2_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); + dhcp->t2_rebind_time = dhcp->t2_timeout; + } + + /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ + if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) { + dhcp->t1_timeout = 0; + } + + if (dhcp->subnet_mask_given) { + /* copy offered network mask */ + ip4_addr_copy(sn_mask, dhcp->offered_sn_mask); + } else { + /* subnet mask not given, choose a safe subnet mask given the network class */ + u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr); + if (first_octet <= 127) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL)); + } else if (first_octet >= 192) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL)); + } else { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL)); + } + } + + ip4_addr_copy(gw_addr, dhcp->offered_gw_addr); + /* gateway address not given? */ + if (ip4_addr_isany_val(gw_addr)) { + /* copy network address */ + ip4_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); + /* use first host address on network as gateway */ + ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); + } + +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F" SN: 0x%08"X32_F" GW: 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr), ip4_addr_get_u32(&sn_mask), ip4_addr_get_u32(&gw_addr))); + /* netif is now bound to DHCP leased address - set this before assigning the address + to ensure the callback can use dhcp_supplied_address() */ + dhcp_set_state(dhcp, DHCP_STATE_BOUND); + + netif_set_addr(netif, &dhcp->offered_ip_addr, &sn_mask, &gw_addr); + /* interface is used by routing now that an address is set */ +} + +/** + * @ingroup dhcp4 + * Renew an existing DHCP lease at the involved DHCP server. + * + * @param netif network interface which must renew its lease + */ +err_t +dhcp_renew(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + u16_t msecs; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n")); + dhcp_set_state(dhcp, DHCP_STATE_RENEWING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); + for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); + } + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + /* append DHCP message trailer */ + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp_pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + /* back-off on retries, but to a maximum of 20 seconds */ + msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Rebind with a DHCP server for an existing DHCP lease. + * + * @param netif network interface which must rebind with a DHCP server + */ +static err_t +dhcp_rebind(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + u16_t msecs; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n")); + dhcp_set_state(dhcp, DHCP_STATE_REBINDING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); + for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); + } + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Enter REBOOTING state to verify an existing lease + * + * @param netif network interface which must reboot + */ +static err_t +dhcp_reboot(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + u16_t msecs; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n")); + dhcp_set_state(dhcp, DHCP_STATE_REBOOTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN_MIN_REQUIRED); + + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); + for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); + } + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * @ingroup dhcp4 + * Release a DHCP lease (usually called before @ref dhcp_stop). + * + * @param netif network interface which must release its lease + */ +err_t +dhcp_release(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + ip_addr_t server_ip_addr; + u8_t is_dhcp_supplied_address; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); + if (dhcp == NULL) { + return ERR_ARG; + } + ip_addr_copy(server_ip_addr, dhcp->server_ip_addr); + + is_dhcp_supplied_address = dhcp_supplied_address(netif); + + /* idle DHCP client */ + dhcp_set_state(dhcp, DHCP_STATE_OFF); + /* clean old DHCP offer */ + ip_addr_set_zero_ip4(&dhcp->server_ip_addr); + ip4_addr_set_zero(&dhcp->offered_ip_addr); + ip4_addr_set_zero(&dhcp->offered_sn_mask); + ip4_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip4_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; + dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0; + + if (!is_dhcp_supplied_address) { + /* don't issue release message when address is not dhcp-assigned */ + return ERR_OK; + } + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr)))); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp_pcb, dhcp->p_out, &server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n")); + } else { + /* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); + } + /* remove IP address from interface (prevents routing from selecting this interface) */ + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + + return result; +} + +/** + * @ingroup dhcp4 + * Remove the DHCP client from the interface. + * + * @param netif The network interface to stop DHCP on + */ +void +dhcp_stop(struct netif *netif) +{ + struct dhcp *dhcp; + LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); + dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); + /* netif is DHCP configured? */ + if (dhcp != NULL) { +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + dhcp_set_state(dhcp, DHCP_STATE_OFF); + + if (dhcp->pcb_allocated != 0) { + dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ + dhcp->pcb_allocated = 0; + } + } +} + +/* + * Set the DHCP state of a DHCP client. + * + * If the state changed, reset the number of tries. + */ +static void +dhcp_set_state(struct dhcp *dhcp, u8_t new_state) +{ + if (new_state != dhcp->state) { + dhcp->state = new_state; + dhcp->tries = 0; + dhcp->request_timeout = 0; + } +} + +/* + * Concatenate an option type and length field to the outgoing + * DHCP message. + * + */ +static void +dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len) +{ + LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = option_type; + dhcp->msg_out->options[dhcp->options_out_len++] = option_len; +} +/* + * Concatenate a single byte to the outgoing DHCP message. + * + */ +static void +dhcp_option_byte(struct dhcp *dhcp, u8_t value) +{ + LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = value; +} + +static void +dhcp_option_short(struct dhcp *dhcp, u16_t value) +{ + LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU); +} + +static void +dhcp_option_long(struct dhcp *dhcp, u32_t value) +{ + LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL)); +} + +#if LWIP_NETIF_HOSTNAME +static void +dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) +{ + if (netif->hostname != NULL) { + size_t namelen = strlen(netif->hostname); + if (namelen > 0) { + size_t len; + const char *p = netif->hostname; + /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME + and 1 byte for trailer) */ + size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; + LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); + len = LWIP_MIN(namelen, available); + LWIP_ASSERT("DHCP: hostname is too long!", len <= 0xFF); + dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, (u8_t)len); + while (len--) { + dhcp_option_byte(dhcp, *p++); + } + } + } +} +#endif /* LWIP_NETIF_HOSTNAME */ + +/** + * Extract the DHCP message and the DHCP options. + * + * Extract the DHCP message and the DHCP options, each into a contiguous + * piece of memory. As a DHCP message is variable sized by its options, + * and also allows overriding some fields for options, the easy approach + * is to first unfold the options into a contiguous piece of memory, and + * use that further on. + * + */ +static err_t +dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p) +{ + u8_t *options; + u16_t offset; + u16_t offset_max; + u16_t options_idx; + u16_t options_idx_max; + struct pbuf *q; + int parse_file_as_options = 0; + int parse_sname_as_options = 0; + + /* clear received options */ + dhcp_clear_all_options(dhcp); + /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */ + if (p->len < DHCP_SNAME_OFS) { + return ERR_BUF; + } + dhcp->msg_in = (struct dhcp_msg *)p->payload; +#if LWIP_DHCP_BOOTP_FILE + /* clear boot file name */ + dhcp->boot_file_name[0] = 0; +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* parse options */ + + /* start with options field */ + options_idx = DHCP_OPTIONS_OFS; + /* parse options to the end of the received packet */ + options_idx_max = p->tot_len; +again: + q = p; + while ((q != NULL) && (options_idx >= q->len)) { + options_idx -= q->len; + options_idx_max -= q->len; + q = q->next; + } + if (q == NULL) { + return ERR_BUF; + } + offset = options_idx; + offset_max = options_idx_max; + options = (u8_t*)q->payload; + /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ + while ((q != NULL) && (offset < offset_max) && (options[offset] != DHCP_OPTION_END)) { + u8_t op = options[offset]; + u8_t len; + u8_t decode_len = 0; + int decode_idx = -1; + u16_t val_offset = offset + 2; + /* len byte might be in the next pbuf */ + if ((offset + 1) < q->len) { + len = options[offset + 1]; + } else { + len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0); + } + /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ + decode_len = len; + switch(op) { + /* case(DHCP_OPTION_END): handled above */ + case(DHCP_OPTION_PAD): + /* special option: no len encoded */ + decode_len = len = 0; + /* will be increased below */ + offset--; + break; + case(DHCP_OPTION_SUBNET_MASK): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; + break; + case(DHCP_OPTION_ROUTER): + decode_len = 4; /* only copy the first given router */ + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_ROUTER; + break; +#if LWIP_DHCP_PROVIDE_DNS_SERVERS + case(DHCP_OPTION_DNS_SERVER): + /* special case: there might be more than one server */ + LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); + /* limit number of DNS servers */ + decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_DNS_SERVER; + break; +#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ + case(DHCP_OPTION_LEASE_TIME): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_LEASE_TIME; + break; +#if LWIP_DHCP_GET_NTP_SRV + case(DHCP_OPTION_NTP): + /* special case: there might be more than one server */ + LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); + /* limit number of NTP servers */ + decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS); + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_NTP_SERVER; + break; +#endif /* LWIP_DHCP_GET_NTP_SRV*/ + case(DHCP_OPTION_OVERLOAD): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + /* decode overload only in options, not in file/sname: invalid packet */ + LWIP_ERROR("overload in file/sname", options_idx == DHCP_OPTIONS_OFS, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_OVERLOAD; + break; + case(DHCP_OPTION_MESSAGE_TYPE): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_MSG_TYPE; + break; + case(DHCP_OPTION_SERVER_ID): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SERVER_ID; + break; + case(DHCP_OPTION_T1): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T1; + break; + case(DHCP_OPTION_T2): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T2; + break; + default: + decode_len = 0; + LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", (u16_t)op)); + break; + } + offset += len + 2; + if (decode_len > 0) { + u32_t value = 0; + u16_t copy_len; +decode_next: + LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX); + if (!dhcp_option_given(dhcp, decode_idx)) { + copy_len = LWIP_MIN(decode_len, 4); + if (pbuf_copy_partial(q, &value, copy_len, val_offset) != copy_len) { + return ERR_BUF; + } + if (decode_len > 4) { + /* decode more than one u32_t */ + LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;); + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value)); + decode_len -= 4; + val_offset += 4; + decode_idx++; + goto decode_next; + } else if (decode_len == 4) { + value = lwip_ntohl(value); + } else { + LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); + value = ((u8_t*)&value)[0]; + } + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, value); + } + } + if (offset >= q->len) { + offset -= q->len; + offset_max -= q->len; + if ((offset < offset_max) && offset_max) { + q = q->next; + LWIP_ERROR("next pbuf was null", q != NULL, return ERR_VAL;); + options = (u8_t*)q->payload; + } else { + /* We've run out of bytes, probably no end marker. Don't proceed. */ + break; + } + } + } + /* is this an overloaded message? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) { + u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD); + dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD); + if (overload == DHCP_OVERLOAD_FILE) { + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME) { + parse_sname_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME_FILE) { + parse_sname_as_options = 1; + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload)); + } +#if LWIP_DHCP_BOOTP_FILE + if (!parse_file_as_options) { + /* only do this for ACK messages */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && + (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) + /* copy bootp file name, don't care for sname (server hostname) */ + if (pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS) != (DHCP_FILE_LEN-1)) { + return ERR_BUF; + } + /* make sure the string is really NULL-terminated */ + dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; + } +#endif /* LWIP_DHCP_BOOTP_FILE */ + } + if (parse_file_as_options) { + /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */ + parse_file_as_options = 0; + options_idx = DHCP_FILE_OFS; + options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; + goto again; + } else if (parse_sname_as_options) { + parse_sname_as_options = 0; + options_idx = DHCP_SNAME_OFS; + options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; + goto again; + } + return ERR_OK; +} + +/** + * If an incoming DHCP message is in response to us, then trigger the state machine + */ +static void +dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + struct netif *netif = ip_current_input_netif(); + struct dhcp *dhcp = netif_dhcp_data(netif); + struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; + u8_t msg_type; + u8_t i; + + LWIP_UNUSED_ARG(arg); + + /* Caught DHCP message from netif that does not have DHCP enabled? -> not interested */ + if ((dhcp == NULL) || (dhcp->pcb_allocated == 0)) { + goto free_pbuf_and_return; + } + + LWIP_ASSERT("invalid server address type", IP_IS_V4(addr)); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, + ip4_addr1_16(ip_2_ip4(addr)), ip4_addr2_16(ip_2_ip4(addr)), ip4_addr3_16(ip_2_ip4(addr)), ip4_addr4_16(ip_2_ip4(addr)), port)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); + /* prevent warnings about unused arguments */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + + if (p->len < DHCP_MIN_REPLY_LEN) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n")); + goto free_pbuf_and_return; + } + + if (reply_msg->op != DHCP_BOOTREPLY) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op)); + goto free_pbuf_and_return; + } + /* iterate through hardware address and match against DHCP message */ + for (i = 0; i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN && i < DHCP_CHADDR_LEN; i++) { + if (netif->hwaddr[i] != reply_msg->chaddr[i]) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", + (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); + goto free_pbuf_and_return; + } + } + /* match transaction ID against what we expected */ + if (lwip_ntohl(reply_msg->xid) != dhcp->xid) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",lwip_ntohl(reply_msg->xid),dhcp->xid)); + goto free_pbuf_and_return; + } + /* option fields could be unfold? */ + if (dhcp_parse_reply(dhcp, p) != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("problem unfolding DHCP message - too short on memory?\n")); + goto free_pbuf_and_return; + } + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); + /* obtain pointer to DHCP message type */ + if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); + goto free_pbuf_and_return; + } + + /* read DHCP message type */ + msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE); + /* message type is DHCP ACK? */ + if (msg_type == DHCP_ACK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n")); + /* in requesting state? */ + if (dhcp->state == DHCP_STATE_REQUESTING) { + dhcp_handle_ack(netif); +#if DHCP_DOES_ARP_CHECK + if ((netif->flags & NETIF_FLAG_ETHARP) != 0) { + /* check if the acknowledged lease address is already in use */ + dhcp_check(netif); + } else { + /* bind interface to the acknowledged lease address */ + dhcp_bind(netif); + } +#else + /* bind interface to the acknowledged lease address */ + dhcp_bind(netif); +#endif + } + /* already bound to the given lease address? */ + else if ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REBINDING) || + (dhcp->state == DHCP_STATE_RENEWING)) { + dhcp_handle_ack(netif); + dhcp_bind(netif); + } + } + /* received a DHCP_NAK in appropriate state? */ + else if ((msg_type == DHCP_NAK) && + ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REQUESTING) || + (dhcp->state == DHCP_STATE_REBINDING) || (dhcp->state == DHCP_STATE_RENEWING ))) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n")); + dhcp_handle_nak(netif); + } + /* received a DHCP_OFFER in DHCP_STATE_SELECTING state? */ + else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_STATE_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_STATE_SELECTING state\n")); + dhcp->request_timeout = 0; + /* remember offered lease */ + dhcp_handle_offer(netif); + } + +free_pbuf_and_return: + if (dhcp != NULL) { + dhcp->msg_in = NULL; + } + pbuf_free(p); +} + +/** + * Create a DHCP request, fill in common headers + * + * @param netif the netif under DHCP control + * @param dhcp dhcp control struct + * @param message_type message type of the request + */ +static err_t +dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) +{ + u16_t i; +#ifndef DHCP_GLOBAL_XID + /** default global transaction identifier starting value (easy to match + * with a packet analyser). We simply increment for each new request. + * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one + * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */ +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + static u32_t xid; +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + static u32_t xid = 0xABCD0000; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ +#else + if (!xid_initialised) { + xid = DHCP_GLOBAL_XID; + xid_initialised = !xid_initialised; + } +#endif + LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;); + LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;); + LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL); + LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL); + dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); + if (dhcp->p_out == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_create_msg(): could not allocate pbuf\n")); + return ERR_MEM; + } + LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg", + (dhcp->p_out->len >= sizeof(struct dhcp_msg))); + + /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */ + if ((message_type != DHCP_REQUEST) || (dhcp->state == DHCP_STATE_REBOOTING)) { + /* reuse transaction identifier in retransmissions */ + if (dhcp->tries == 0) { +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + xid = LWIP_RAND(); +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + xid++; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + } + dhcp->xid = xid; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("transaction id xid(%"X32_F")\n", xid)); + + dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; + + dhcp->msg_out->op = DHCP_BOOTREQUEST; + /* @todo: make link layer independent */ + dhcp->msg_out->htype = DHCP_HTYPE_ETH; + dhcp->msg_out->hlen = netif->hwaddr_len; + dhcp->msg_out->hops = 0; + dhcp->msg_out->xid = lwip_htonl(dhcp->xid); + dhcp->msg_out->secs = 0; + /* we don't need the broadcast flag since we can receive unicast traffic + before being fully configured! */ + dhcp->msg_out->flags = 0; + ip4_addr_set_zero(&dhcp->msg_out->ciaddr); + /* set ciaddr to netif->ip_addr based on message_type and state */ + if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || (message_type == DHCP_RELEASE) || + ((message_type == DHCP_REQUEST) && /* DHCP_STATE_BOUND not used for sending! */ + ((dhcp->state== DHCP_STATE_RENEWING) || dhcp->state== DHCP_STATE_REBINDING))) { + ip4_addr_copy(dhcp->msg_out->ciaddr, *netif_ip4_addr(netif)); + } + ip4_addr_set_zero(&dhcp->msg_out->yiaddr); + ip4_addr_set_zero(&dhcp->msg_out->siaddr); + ip4_addr_set_zero(&dhcp->msg_out->giaddr); + for (i = 0; i < DHCP_CHADDR_LEN; i++) { + /* copy netif hardware address, pad with zeroes */ + dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN) ? netif->hwaddr[i] : 0/* pad byte*/; + } + for (i = 0; i < DHCP_SNAME_LEN; i++) { + dhcp->msg_out->sname[i] = 0; + } + for (i = 0; i < DHCP_FILE_LEN; i++) { + dhcp->msg_out->file[i] = 0; + } + dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); + dhcp->options_out_len = 0; + /* fill options field with an incrementing array (for debugging purposes) */ + for (i = 0; i < DHCP_OPTIONS_LEN; i++) { + dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */ + } + /* Add option MESSAGE_TYPE */ + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, message_type); + return ERR_OK; +} + +/** + * Free previously allocated memory used to send a DHCP request. + * + * @param dhcp the dhcp struct to free the request from + */ +static void +dhcp_delete_msg(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL); + LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL); + if (dhcp->p_out != NULL) { + pbuf_free(dhcp->p_out); + } + dhcp->p_out = NULL; + dhcp->msg_out = NULL; +} + +/** + * Add a DHCP message trailer + * + * Adds the END option to the DHCP message, and if + * necessary, up to three padding bytes. + * + * @param dhcp DHCP state structure + */ +static void +dhcp_option_trailer(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL); + LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; + /* packet is too small, or not 4 byte aligned? */ + while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) && + (dhcp->options_out_len < DHCP_OPTIONS_LEN)) { + /* add a fill/padding byte */ + dhcp->msg_out->options[dhcp->options_out_len++] = 0; + } +} + +/** check if DHCP supplied netif->ip_addr + * + * @param netif the netif to check + * @return 1 if DHCP supplied netif->ip_addr (states BOUND or RENEWING), + * 0 otherwise + */ +u8_t +dhcp_supplied_address(const struct netif *netif) +{ + if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) { + struct dhcp* dhcp = netif_dhcp_data(netif); + return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING) || + (dhcp->state == DHCP_STATE_REBINDING); + } + return 0; +} + +#endif /* LWIP_IPV4 && LWIP_DHCP */ diff --git a/components/net/lwip-2.0.3/src/core/ipv4/etharp.c b/components/net/lwip-2.0.3/src/core/ipv4/etharp.c new file mode 100644 index 0000000000..3f48a9975f --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv4/etharp.c @@ -0,0 +1,1206 @@ +/** + * @file + * Address Resolution Protocol module for IP over Ethernet + * + * Functionally, ARP is divided into two parts. The first maps an IP address + * to a physical address when sending a packet, and the second part answers + * requests from other machines for our physical address. + * + * This implementation complies with RFC 826 (Ethernet ARP). It supports + * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 + * if an interface calls etharp_gratuitous(our_netif) upon address change. + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET + +#include "lwip/etharp.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "netif/ethernet.h" + +#include + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +/** Re-request a used ARP entry 1 minute before it would expire to prevent + * breaking a steadily used connection because the ARP entry timed out. */ +#define ARP_AGE_REREQUEST_USED_UNICAST (ARP_MAXAGE - 30) +#define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15) + +/** the time an ARP entry stays pending after first request, + * for ARP_TMR_INTERVAL = 1000, this is + * 10 seconds. + * + * @internal Keep this number at least 2, otherwise it might + * run out instantly if the timeout occurs directly after a request. + */ +#define ARP_MAXPENDING 5 + +/** ARP states */ +enum etharp_state { + ETHARP_STATE_EMPTY = 0, + ETHARP_STATE_PENDING, + ETHARP_STATE_STABLE, + ETHARP_STATE_STABLE_REREQUESTING_1, + ETHARP_STATE_STABLE_REREQUESTING_2 +#if ETHARP_SUPPORT_STATIC_ENTRIES + ,ETHARP_STATE_STATIC +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ +}; + +struct etharp_entry { +#if ARP_QUEUEING + /** Pointer to queue of pending outgoing packets on this ARP entry. */ + struct etharp_q_entry *q; +#else /* ARP_QUEUEING */ + /** Pointer to a single pending outgoing packet on this ARP entry. */ + struct pbuf *q; +#endif /* ARP_QUEUEING */ + ip4_addr_t ipaddr; + struct netif *netif; + struct eth_addr ethaddr; + u16_t ctime; + u8_t state; +}; + +static struct etharp_entry arp_table[ARP_TABLE_SIZE]; + +#if !LWIP_NETIF_HWADDRHINT +static u8_t etharp_cached_entry; +#endif /* !LWIP_NETIF_HWADDRHINT */ + +/** Try hard to create a new entry - we want the IP address to appear in + the cache (even if this means removing an active entry or so). */ +#define ETHARP_FLAG_TRY_HARD 1 +#define ETHARP_FLAG_FIND_ONLY 2 +#if ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_FLAG_STATIC_ENTRY 4 +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#if LWIP_NETIF_HWADDRHINT +#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ + *((netif)->addr_hint) = (hint); +#else /* LWIP_NETIF_HWADDRHINT */ +#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint)) +#endif /* LWIP_NETIF_HWADDRHINT */ + + +/* Some checks, instead of etharp_init(): */ +#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) + #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h" +#endif + + +static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr); +static err_t etharp_raw(struct netif *netif, + const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr, + const u16_t opcode); + +#if ARP_QUEUEING +/** + * Free a complete queue of etharp entries + * + * @param q a qeueue of etharp_q_entry's to free + */ +static void +free_etharp_q(struct etharp_q_entry *q) +{ + struct etharp_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ARP_QUEUE, r); + } +} +#else /* ARP_QUEUEING */ + +/** Compatibility define: free the queued pbuf */ +#define free_etharp_q(q) pbuf_free(q) + +#endif /* ARP_QUEUEING */ + +/** Clean up ARP table entries */ +static void +etharp_free_entry(int i) +{ + /* remove from SNMP ARP index tree */ + mib2_remove_arp_entry(arp_table[i].netif, &arp_table[i].ipaddr); + /* and empty packet queue */ + if (arp_table[i].q != NULL) { + /* remove all queued packets */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); + free_etharp_q(arp_table[i].q); + arp_table[i].q = NULL; + } + /* recycle entry for re-use */ + arp_table[i].state = ETHARP_STATE_EMPTY; +#ifdef LWIP_DEBUG + /* for debugging, clean out the complete entry */ + arp_table[i].ctime = 0; + arp_table[i].netif = NULL; + ip4_addr_set_zero(&arp_table[i].ipaddr); + arp_table[i].ethaddr = ethzero; +#endif /* LWIP_DEBUG */ +} + +/** + * Clears expired entries in the ARP table. + * + * This function should be called every ARP_TMR_INTERVAL milliseconds (1 second), + * in order to expire entries in the ARP table. + */ +void +etharp_tmr(void) +{ + u8_t i; + + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); + /* remove expired entries from the ARP table */ + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if (state != ETHARP_STATE_EMPTY +#if ETHARP_SUPPORT_STATIC_ENTRIES + && (state != ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + ) { + arp_table[i].ctime++; + if ((arp_table[i].ctime >= ARP_MAXAGE) || + ((arp_table[i].state == ETHARP_STATE_PENDING) && + (arp_table[i].ctime >= ARP_MAXPENDING))) { + /* pending or stable entry has become old! */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", + arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); + /* clean up entries that have just been expired */ + etharp_free_entry(i); + } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) { + /* Don't send more than one request every 2 seconds. */ + arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2; + } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) { + /* Reset state to stable, so that the next transmitted packet will + re-send an ARP request. */ + arp_table[i].state = ETHARP_STATE_STABLE; + } else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* still pending, resend an ARP query */ + etharp_request(arp_table[i].netif, &arp_table[i].ipaddr); + } + } + } +} + +/** + * Search the ARP table for a matching or new entry. + * + * If an IP address is given, return a pending or stable ARP entry that matches + * the address. If no match is found, create a new entry with this address set, + * but in state ETHARP_EMPTY. The caller must check and possibly change the + * state of the returned entry. + * + * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. + * + * In all cases, attempt to create new entries from an empty entry. If no + * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle + * old entries. Heuristic choose the least important entry for recycling. + * + * @param ipaddr IP address to find in ARP cache, or to add if not found. + * @param flags See @ref etharp_state + * @param netif netif related to this address (used for NETIF_HWADDRHINT) + * + * @return The ARP entry index that matched or is created, ERR_MEM if no + * entry is found or could be recycled. + */ +static s8_t +etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif* netif) +{ + s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; + s8_t empty = ARP_TABLE_SIZE; + u8_t i = 0; + /* oldest entry with packets on queue */ + s8_t old_queue = ARP_TABLE_SIZE; + /* its age */ + u16_t age_queue = 0, age_pending = 0, age_stable = 0; + + LWIP_UNUSED_ARG(netif); + + /** + * a) do a search through the cache, remember candidates + * b) select candidate entry + * c) create new entry + */ + + /* a) in a single search sweep, do all of this + * 1) remember the first empty entry (if any) + * 2) remember the oldest stable entry (if any) + * 3) remember the oldest pending entry without queued packets (if any) + * 4) remember the oldest pending entry with queued packets (if any) + * 5) search for a matching IP entry, either pending or stable + * until 5 matches, or all entries are searched for. + */ + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + /* no empty entry found yet and now we do find one? */ + if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i)); + /* remember first empty entry */ + empty = i; + } else if (state != ETHARP_STATE_EMPTY) { + LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE", + state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE); + /* if given, does IP address match IP address in ARP entry? */ + if (ipaddr && ip4_addr_cmp(ipaddr, &arp_table[i].ipaddr) +#if ETHARP_TABLE_MATCH_NETIF + && ((netif == NULL) || (netif == arp_table[i].netif)) +#endif /* ETHARP_TABLE_MATCH_NETIF */ + ) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i)); + /* found exact IP address match, simply bail out */ + return i; + } + /* pending entry? */ + if (state == ETHARP_STATE_PENDING) { + /* pending with queued packets? */ + if (arp_table[i].q != NULL) { + if (arp_table[i].ctime >= age_queue) { + old_queue = i; + age_queue = arp_table[i].ctime; + } + } else + /* pending without queued packets? */ + { + if (arp_table[i].ctime >= age_pending) { + old_pending = i; + age_pending = arp_table[i].ctime; + } + } + /* stable entry? */ + } else if (state >= ETHARP_STATE_STABLE) { +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* don't record old_stable for static entries since they never expire */ + if (state < ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* remember entry with oldest stable entry in oldest, its age in maxtime */ + if (arp_table[i].ctime >= age_stable) { + old_stable = i; + age_stable = arp_table[i].ctime; + } + } + } + } + } + /* { we have no match } => try to create a new entry */ + + /* don't create new entry, only search? */ + if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) || + /* or no empty entry found and not allowed to recycle? */ + ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n")); + return (s8_t)ERR_MEM; + } + + /* b) choose the least destructive entry to recycle: + * 1) empty entry + * 2) oldest stable entry + * 3) oldest pending entry without queued packets + * 4) oldest pending entry with queued packets + * + * { ETHARP_FLAG_TRY_HARD is set at this point } + */ + + /* 1) empty entry available? */ + if (empty < ARP_TABLE_SIZE) { + i = empty; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); + } else { + /* 2) found recyclable stable entry? */ + if (old_stable < ARP_TABLE_SIZE) { + /* recycle oldest stable*/ + i = old_stable; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); + /* no queued packets should exist on stable entries */ + LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); + /* 3) found recyclable pending entry without queued packets? */ + } else if (old_pending < ARP_TABLE_SIZE) { + /* recycle oldest pending */ + i = old_pending; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); + /* 4) found recyclable pending entry with queued packets? */ + } else if (old_queue < ARP_TABLE_SIZE) { + /* recycle oldest pending (queued packets are free in etharp_free_entry) */ + i = old_queue; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); + /* no empty or recyclable entries found */ + } else { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n")); + return (s8_t)ERR_MEM; + } + + /* { empty or recyclable entry found } */ + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + etharp_free_entry(i); + } + + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY", + arp_table[i].state == ETHARP_STATE_EMPTY); + + /* IP address given? */ + if (ipaddr != NULL) { + /* set IP address */ + ip4_addr_copy(arp_table[i].ipaddr, *ipaddr); + } + arp_table[i].ctime = 0; +#if ETHARP_TABLE_MATCH_NETIF + arp_table[i].netif = netif; +#endif /* ETHARP_TABLE_MATCH_NETIF*/ + return (err_t)i; +} + +/** + * Update (or insert) a IP/MAC address pair in the ARP cache. + * + * If a pending entry is resolved, any queued packets will be sent + * at this point. + * + * @param netif netif related to this entry (used for NETIF_ADDRHINT) + * @param ipaddr IP address of the inserted ARP entry. + * @param ethaddr Ethernet address of the inserted ARP entry. + * @param flags See @ref etharp_state + * + * @return + * - ERR_OK Successfully updated ARP cache. + * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + * @see pbuf_free() + */ +static err_t +etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) +{ + s8_t i; + LWIP_ASSERT("netif->hwaddr_len == ETH_HWADDR_LEN", netif->hwaddr_len == ETH_HWADDR_LEN); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2], + (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5])); + /* non-unicast address? */ + if (ip4_addr_isany(ipaddr) || + ip4_addr_isbroadcast(ipaddr, netif) || + ip4_addr_ismulticast(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, flags, netif); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + +#if ETHARP_SUPPORT_STATIC_ENTRIES + if (flags & ETHARP_FLAG_STATIC_ENTRY) { + /* record static type */ + arp_table[i].state = ETHARP_STATE_STATIC; + } else if (arp_table[i].state == ETHARP_STATE_STATIC) { + /* found entry is a static type, don't overwrite it */ + return ERR_VAL; + } else +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* mark it stable */ + arp_table[i].state = ETHARP_STATE_STABLE; + } + + /* record network interface */ + arp_table[i].netif = netif; + /* insert in SNMP ARP index tree */ + mib2_add_arp_entry(netif, &arp_table[i].ipaddr); + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); + /* update address */ + ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); + /* reset time stamp */ + arp_table[i].ctime = 0; + /* this is where we will send out queued packets! */ +#if ARP_QUEUEING + while (arp_table[i].q != NULL) { + struct pbuf *p; + /* remember remainder of queue */ + struct etharp_q_entry *q = arp_table[i].q; + /* pop first item off the queue */ + arp_table[i].q = q->next; + /* get the packet pointer */ + p = q->p; + /* now queue entry can be freed */ + memp_free(MEMP_ARP_QUEUE, q); +#else /* ARP_QUEUEING */ + if (arp_table[i].q != NULL) { + struct pbuf *p = arp_table[i].q; + arp_table[i].q = NULL; +#endif /* ARP_QUEUEING */ + /* send the queued IP packet */ + ethernet_output(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr, ETHTYPE_IP); + /* free the queued IP packet */ + pbuf_free(p); + } + return ERR_OK; +} + +#if ETHARP_SUPPORT_STATIC_ENTRIES +/** Add a new static entry to the ARP table. If an entry exists for the + * specified IP address, this entry is overwritten. + * If packets are queued for the specified IP address, they are sent out. + * + * @param ipaddr IP address for the new static entry + * @param ethaddr ethernet address for the new static entry + * @return See return values of etharp_add_static_entry + */ +err_t +etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr) +{ + struct netif *netif; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2], + (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5])); + + netif = ip4_route(ipaddr); + if (netif == NULL) { + return ERR_RTE; + } + + return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); +} + +/** Remove a static entry from the ARP table previously added with a call to + * etharp_add_static_entry. + * + * @param ipaddr IP address of the static entry to remove + * @return ERR_OK: entry removed + * ERR_MEM: entry wasn't found + * ERR_ARG: entry wasn't a static entry but a dynamic one + */ +err_t +etharp_remove_static_entry(const ip4_addr_t *ipaddr) +{ + s8_t i; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); + + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, NULL); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + + if (arp_table[i].state != ETHARP_STATE_STATIC) { + /* entry wasn't a static entry, cannot remove it */ + return ERR_ARG; + } + /* entry found, free it */ + etharp_free_entry(i); + return ERR_OK; +} +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +/** + * Remove all ARP table entries of the specified netif. + * + * @param netif points to a network interface + */ +void +etharp_cleanup_netif(struct netif *netif) +{ + u8_t i; + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) { + etharp_free_entry(i); + } + } +} + +/** + * Finds (stable) ethernet/IP address pair from ARP table + * using interface and IP address index. + * @note the addresses in the ARP table are in network order! + * + * @param netif points to interface index + * @param ipaddr points to the (network order) IP address index + * @param eth_ret points to return pointer + * @param ip_ret points to return pointer + * @return table index if found, -1 otherwise + */ +s8_t +etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr, + struct eth_addr **eth_ret, const ip4_addr_t **ip_ret) +{ + s8_t i; + + LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", + eth_ret != NULL && ip_ret != NULL); + + LWIP_UNUSED_ARG(netif); + + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, netif); + if ((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { + *eth_ret = &arp_table[i].ethaddr; + *ip_ret = &arp_table[i].ipaddr; + return i; + } + return -1; +} + +/** + * Possibility to iterate over stable ARP table entries + * + * @param i entry number, 0 to ARP_TABLE_SIZE + * @param ipaddr return value: IP address + * @param netif return value: points to interface + * @param eth_ret return value: ETH address + * @return 1 on valid index, 0 otherwise + */ +u8_t +etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret) +{ + LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("eth_ret != NULL", eth_ret != NULL); + + if((i < ARP_TABLE_SIZE) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { + *ipaddr = &arp_table[i].ipaddr; + *netif = arp_table[i].netif; + *eth_ret = &arp_table[i].ethaddr; + return 1; + } else { + return 0; + } +} + +/** + * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache + * send out queued IP packets. Updates cache with snooped address pairs. + * + * Should be called for incoming ARP packets. The pbuf in the argument + * is freed by this function. + * + * @param p The ARP packet that arrived on netif. Is freed by this function. + * @param netif The lwIP network interface on which the ARP packet pbuf arrived. + * + * @see pbuf_free() + */ +void +etharp_input(struct pbuf *p, struct netif *netif) +{ + struct etharp_hdr *hdr; + /* these are aligned properly, whereas the ARP header fields might not be */ + ip4_addr_t sipaddr, dipaddr; + u8_t for_us; + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + hdr = (struct etharp_hdr *)p->payload; + + /* RFC 826 "Packet Reception": */ + if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) || + (hdr->hwlen != ETH_HWADDR_LEN) || + (hdr->protolen != sizeof(ip4_addr_t)) || + (hdr->proto != PP_HTONS(ETHTYPE_IP))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", + hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen)); + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + ETHARP_STATS_INC(etharp.recv); + +#if LWIP_AUTOIP + /* We have to check if a host already has configured our random + * created link local address and continuously check if there is + * a host with this IP-address so we can detect collisions */ + autoip_arp_reply(netif, hdr); +#endif /* LWIP_AUTOIP */ + + /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + /* this interface is not configured? */ + if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { + for_us = 0; + } else { + /* ARP packet directed to us? */ + for_us = (u8_t)ip4_addr_cmp(&dipaddr, netif_ip4_addr(netif)); + } + + /* ARP message directed to us? + -> add IP address in ARP cache; assume requester wants to talk to us, + can result in directly sending the queued packets for this host. + ARP message not directed to us? + -> update the source IP address in the cache, if present */ + etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), + for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY); + + /* now act on the message itself */ + switch (hdr->opcode) { + /* ARP request? */ + case PP_HTONS(ARP_REQUEST): + /* ARP request. If it asked for our address, we send out a + * reply. In any case, we time-stamp any existing ARP entry, + * and possibly send out an IP packet that was queued on it. */ + + LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n")); + /* ARP request for our address? */ + if (for_us) { + /* send ARP response */ + etharp_raw(netif, + (struct eth_addr *)netif->hwaddr, &hdr->shwaddr, + (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), + &hdr->shwaddr, &sipaddr, + ARP_REPLY); + /* we are not configured? */ + } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { + /* { for_us == 0 and netif->ip_addr.addr == 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, ARP request ignored.\n")); + /* request was not directed to us */ + } else { + /* { for_us == 0 and netif->ip_addr.addr != 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP request was not for us.\n")); + } + break; + case PP_HTONS(ARP_REPLY): + /* ARP reply. We already updated the ARP cache earlier. */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP reply\n")); +#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) + /* DHCP wants to know about ARP replies from any host with an + * IP address also offered to us by the DHCP server. We do not + * want to take a duplicate IP address on a single network. + * @todo How should we handle redundant (fail-over) interfaces? */ + dhcp_arp_reply(netif, &sipaddr); +#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */ + break; + default: + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP unknown opcode type %"S16_F"\n", lwip_htons(hdr->opcode))); + ETHARP_STATS_INC(etharp.err); + break; + } + /* free ARP packet */ + pbuf_free(p); +} + +/** Just a small helper function that sends a pbuf to an ethernet address + * in the arp_table specified by the index 'arp_idx'. + */ +static err_t +etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) +{ + LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", + arp_table[arp_idx].state >= ETHARP_STATE_STABLE); + /* if arp table entry is about to expire: re-request it, + but only if its state is ETHARP_STATE_STABLE to prevent flooding the + network with ARP requests if this address is used frequently. */ + if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) { + if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) { + /* issue a standard request using broadcast */ + if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { + arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; + } + } else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) { + /* issue a unicast request (for 15 seconds) to prevent unnecessary broadcast */ + if (etharp_request_dst(netif, &arp_table[arp_idx].ipaddr, &arp_table[arp_idx].ethaddr) == ERR_OK) { + arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; + } + } + } + + return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &arp_table[arp_idx].ethaddr, ETHTYPE_IP); +} + +/** + * Resolve and fill-in Ethernet address header for outgoing IP packet. + * + * For IP multicast and broadcast, corresponding Ethernet addresses + * are selected and the packet is transmitted on the link. + * + * For unicast addresses, the packet is submitted to etharp_query(). In + * case the IP address is outside the local network, the IP address of + * the gateway is used. + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ipaddr The IP address of the packet destination. + * + * @return + * - ERR_RTE No route to destination (no gateway to external networks), + * or the return type of either etharp_query() or ethernet_output(). + */ +err_t +etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) +{ + const struct eth_addr *dest; + struct eth_addr mcastaddr; + const ip4_addr_t *dst_addr = ipaddr; + + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); + + /* Determine on destination hardware address. Broadcasts and multicasts + * are special, other IP addresses are looked up in the ARP table. */ + + /* broadcast destination IP address? */ + if (ip4_addr_isbroadcast(ipaddr, netif)) { + /* broadcast on Ethernet also */ + dest = (const struct eth_addr *)ðbroadcast; + /* multicast destination IP address? */ + } else if (ip4_addr_ismulticast(ipaddr)) { + /* Hash IP multicast address to MAC address.*/ + mcastaddr.addr[0] = LL_IP4_MULTICAST_ADDR_0; + mcastaddr.addr[1] = LL_IP4_MULTICAST_ADDR_1; + mcastaddr.addr[2] = LL_IP4_MULTICAST_ADDR_2; + mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; + mcastaddr.addr[4] = ip4_addr3(ipaddr); + mcastaddr.addr[5] = ip4_addr4(ipaddr); + /* destination Ethernet address is multicast */ + dest = &mcastaddr; + /* unicast destination IP address? */ + } else { + s8_t i; + /* outside local network? if so, this can neither be a global broadcast nor + a subnet broadcast. */ + if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) && + !ip4_addr_islinklocal(ipaddr)) { +#if LWIP_AUTOIP + struct ip_hdr *iphdr = LWIP_ALIGNMENT_CAST(struct ip_hdr*, q->payload); + /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with + a link-local source address must always be "directly to its destination + on the same physical link. The host MUST NOT send the packet to any + router for forwarding". */ + if (!ip4_addr_islinklocal(&iphdr->src)) +#endif /* LWIP_AUTOIP */ + { +#ifdef LWIP_HOOK_ETHARP_GET_GW + /* For advanced routing, a single default gateway might not be enough, so get + the IP address of the gateway to handle the current destination address. */ + dst_addr = LWIP_HOOK_ETHARP_GET_GW(netif, ipaddr); + if (dst_addr == NULL) +#endif /* LWIP_HOOK_ETHARP_GET_GW */ + { + /* interface has default gateway? */ + if (!ip4_addr_isany_val(*netif_ip4_gw(netif))) { + /* send to hardware address of default gateway IP address */ + dst_addr = netif_ip4_gw(netif); + /* no default gateway available */ + } else { + /* no route to destination error (default gateway missing) */ + return ERR_RTE; + } + } + } + } +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t etharp_cached_entry = *(netif->addr_hint); + if (etharp_cached_entry < ARP_TABLE_SIZE) { +#endif /* LWIP_NETIF_HWADDRHINT */ + if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && +#if ETHARP_TABLE_MATCH_NETIF + (arp_table[etharp_cached_entry].netif == netif) && +#endif + (ip4_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) { + /* the per-pcb-cached entry is stable and the right one! */ + ETHARP_STATS_INC(etharp.cachehit); + return etharp_output_to_arp_index(netif, q, etharp_cached_entry); + } +#if LWIP_NETIF_HWADDRHINT + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* find stable entry: do this here since this is a critical path for + throughput and etharp_find_entry() is kind of slow */ + for (i = 0; i < ARP_TABLE_SIZE; i++) { + if ((arp_table[i].state >= ETHARP_STATE_STABLE) && +#if ETHARP_TABLE_MATCH_NETIF + (arp_table[i].netif == netif) && +#endif + (ip4_addr_cmp(dst_addr, &arp_table[i].ipaddr))) { + /* found an existing, stable entry */ + ETHARP_SET_HINT(netif, i); + return etharp_output_to_arp_index(netif, q, i); + } + } + /* no stable entry found, use the (slower) query function: + queue on destination Ethernet address belonging to ipaddr */ + return etharp_query(netif, dst_addr, q); + } + + /* continuation for multicast/broadcast destinations */ + /* obtain source Ethernet address of the given interface */ + /* send packet directly on the link */ + return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), dest, ETHTYPE_IP); +} + +/** + * Send an ARP request for the given IP address and/or queue a packet. + * + * If the IP address was not yet in the cache, a pending ARP cache entry + * is added and an ARP request is sent for the given address. The packet + * is queued on this entry. + * + * If the IP address was already pending in the cache, a new ARP request + * is sent for the given address. The packet is queued on this entry. + * + * If the IP address was already stable in the cache, and a packet is + * given, it is directly sent and no ARP request is sent out. + * + * If the IP address was already stable in the cache, and no packet is + * given, an ARP request is sent out. + * + * @param netif The lwIP network interface on which ipaddr + * must be queried for. + * @param ipaddr The IP address to be resolved. + * @param q If non-NULL, a pbuf that must be delivered to the IP address. + * q is not freed by this function. + * + * @note q must only be ONE packet, not a packet queue! + * + * @return + * - ERR_BUF Could not make room for Ethernet header. + * - ERR_MEM Hardware address unknown, and no more ARP entries available + * to query for address or queue the packet. + * - ERR_MEM Could not queue packet due to memory shortage. + * - ERR_RTE No route to destination (no gateway to external networks). + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + */ +err_t +etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) +{ + struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; + err_t result = ERR_MEM; + int is_new_entry = 0; + s8_t i; /* ARP entry index */ + + /* non-unicast address? */ + if (ip4_addr_isbroadcast(ipaddr, netif) || + ip4_addr_ismulticast(ipaddr) || + ip4_addr_isany(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + + /* find entry in ARP cache, ask to create entry if queueing packet */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD, netif); + + /* could not find or create entry? */ + if (i < 0) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n")); + if (q) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n")); + ETHARP_STATS_INC(etharp.memerr); + } + return (err_t)i; + } + + /* mark a fresh entry as pending (we just sent a request) */ + if (arp_table[i].state == ETHARP_STATE_EMPTY) { + is_new_entry = 1; + arp_table[i].state = ETHARP_STATE_PENDING; + /* record network interface for re-sending arp request in etharp_tmr */ + arp_table[i].netif = netif; + } + + /* { i is either a STABLE or (new or existing) PENDING entry } */ + LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", + ((arp_table[i].state == ETHARP_STATE_PENDING) || + (arp_table[i].state >= ETHARP_STATE_STABLE))); + + /* do we have a new entry? or an implicit query request? */ + if (is_new_entry || (q == NULL)) { + /* try to resolve it; send out ARP request */ + result = etharp_request(netif, ipaddr); + if (result != ERR_OK) { + /* ARP request couldn't be sent */ + /* We don't re-send arp request in etharp_tmr, but we still queue packets, + since this failure could be temporary, and the next packet calling + etharp_query again could lead to sending the queued packets. */ + } + if (q == NULL) { + return result; + } + } + + /* packet given? */ + LWIP_ASSERT("q != NULL", q != NULL); + /* stable entry? */ + if (arp_table[i].state >= ETHARP_STATE_STABLE) { + /* we have a valid IP->Ethernet address mapping */ + ETHARP_SET_HINT(netif, i); + /* send the packet */ + result = ethernet_output(netif, q, srcaddr, &(arp_table[i].ethaddr), ETHTYPE_IP); + /* pending entry? (either just created or already pending */ + } else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* entry is still pending, queue the given packet 'q' */ + struct pbuf *p; + int copy_needed = 0; + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); + if (p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if (copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet could be taken over? */ + if (p != NULL) { + /* queue packet ... */ +#if ARP_QUEUEING + struct etharp_q_entry *new_entry; + /* allocate a new arp queue entry */ + new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); + if (new_entry != NULL) { + unsigned int qlen = 0; + new_entry->next = 0; + new_entry->p = p; + if (arp_table[i].q != NULL) { + /* queue was already existent, append the new entry to the end */ + struct etharp_q_entry *r; + r = arp_table[i].q; + qlen++; + while (r->next != NULL) { + r = r->next; + qlen++; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + arp_table[i].q = new_entry; + } +#if ARP_QUEUE_LEN + if (qlen >= ARP_QUEUE_LEN) { + struct etharp_q_entry *old; + old = arp_table[i].q; + arp_table[i].q = arp_table[i].q->next; + pbuf_free(old->p); + memp_free(MEMP_ARP_QUEUE, old); + } +#endif + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + result = ERR_OK; + } else { + /* the pool MEMP_ARP_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } +#else /* ARP_QUEUEING */ + /* always queue one packet per ARP request only, freeing a previously queued packet */ + if (arp_table[i].q != NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + pbuf_free(arp_table[i].q); + } + arp_table[i].q = p; + result = ERR_OK; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); +#endif /* ARP_QUEUEING */ + } else { + ETHARP_STATS_INC(etharp.memerr); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } + } + return result; +} + +/** + * Send a raw ARP packet (opcode and all addresses can be modified) + * + * @param netif the lwip network interface on which to send the ARP packet + * @param ethsrc_addr the source MAC address for the ethernet header + * @param ethdst_addr the destination MAC address for the ethernet header + * @param hwsrc_addr the source MAC address for the ARP protocol header + * @param ipsrc_addr the source IP address for the ARP protocol header + * @param hwdst_addr the destination MAC address for the ARP protocol header + * @param ipdst_addr the destination IP address for the ARP protocol header + * @param opcode the type of the ARP packet + * @return ERR_OK if the ARP packet has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +static err_t +etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr, + const u16_t opcode) +{ + struct pbuf *p; + err_t result = ERR_OK; + struct etharp_hdr *hdr; + + LWIP_ASSERT("netif != NULL", netif != NULL); + + /* allocate a pbuf for the outgoing ARP request packet */ + p = pbuf_alloc(PBUF_LINK, SIZEOF_ETHARP_HDR, PBUF_RAM); + /* could allocate a pbuf for an ARP request? */ + if (p == NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_raw: could not allocate pbuf for ARP request.\n")); + ETHARP_STATS_INC(etharp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", + (p->len >= SIZEOF_ETHARP_HDR)); + + hdr = (struct etharp_hdr *)p->payload; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); + hdr->opcode = lwip_htons(opcode); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETH_HWADDR_LEN)); + + /* Write the ARP MAC-Addresses */ + ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); + ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); + /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without + * structure packing. */ + IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr); + IPADDR2_COPY(&hdr->dipaddr, ipdst_addr); + + hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET); + hdr->proto = PP_HTONS(ETHTYPE_IP); + /* set hwlen and protolen */ + hdr->hwlen = ETH_HWADDR_LEN; + hdr->protolen = sizeof(ip4_addr_t); + + /* send ARP query */ +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + if(ip4_addr_islinklocal(ipsrc_addr)) { + ethernet_output(netif, p, ethsrc_addr, ðbroadcast, ETHTYPE_ARP); + } else +#endif /* LWIP_AUTOIP */ + { + ethernet_output(netif, p, ethsrc_addr, ethdst_addr, ETHTYPE_ARP); + } + + ETHARP_STATS_INC(etharp.xmit); + /* free ARP query packet */ + pbuf_free(p); + p = NULL; + /* could not allocate pbuf for ARP request */ + + return result; +} + +/** + * Send an ARP request packet asking for ipaddr to a specific eth address. + * Used to send unicast request to refresh the ARP table just before an entry + * times out + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address for which to ask + * @param hw_dst_addr the ethernet address to send this packet to + * @return ERR_OK if the request has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +static err_t +etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, hw_dst_addr, + (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), ðzero, + ipaddr, ARP_REQUEST); +} + +/** + * Send an ARP request packet asking for ipaddr. + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address for which to ask + * @return ERR_OK if the request has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +err_t +etharp_request(struct netif *netif, const ip4_addr_t *ipaddr) +{ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); + return etharp_request_dst(netif, ipaddr, ðbroadcast); +} +#endif /* LWIP_IPV4 && LWIP_ARP */ + +#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/components/net/lwip-2.0.3/src/core/ipv4/icmp.c b/components/net/lwip-2.0.3/src/core/ipv4/icmp.c new file mode 100644 index 0000000000..5ee24eedfa --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv4/icmp.c @@ -0,0 +1,397 @@ +/** + * @file + * ICMP - Internet Control Message Protocol + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* Some ICMP messages should be passed to the transport protocols. This + is not implemented. */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/stats.h" + +#include + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be + * used to modify and send a response packet (and to 1 if this is not the case, + * e.g. when link header is stripped of when receiving) */ +#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + +/* The amount of data from the original packet to return in a dest-unreachable */ +#define ICMP_DEST_UNREACH_DATASIZE 8 + +static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); + +/** + * Processes ICMP input packets, called from ip_input(). + * + * Currently only processes icmp echo requests and sends + * out the echo response. + * + * @param p the icmp echo request packet, p->payload pointing to the icmp header + * @param inp the netif on which this packet was received + */ +void +icmp_input(struct pbuf *p, struct netif *inp) +{ + u8_t type; +#ifdef LWIP_DEBUG + u8_t code; +#endif /* LWIP_DEBUG */ + struct icmp_echo_hdr *iecho; + const struct ip_hdr *iphdr_in; + u16_t hlen; + const ip4_addr_t* src; + + ICMP_STATS_INC(icmp.recv); + MIB2_STATS_INC(mib2.icmpinmsgs); + + iphdr_in = ip4_current_header(); + hlen = IPH_HL(iphdr_in) * 4; + if (hlen < IP_HLEN) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short IP header (%"S16_F" bytes) received\n", hlen)); + goto lenerr; + } + if (p->len < sizeof(u16_t)*2) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); + goto lenerr; + } + + type = *((u8_t *)p->payload); +#ifdef LWIP_DEBUG + code = *(((u8_t *)p->payload)+1); +#endif /* LWIP_DEBUG */ + switch (type) { + case ICMP_ER: + /* This is OK, echo reply might have been parsed by a raw PCB + (as obviously, an echo request has been sent, too). */ + MIB2_STATS_INC(mib2.icmpinechoreps); + break; + case ICMP_ECHO: + MIB2_STATS_INC(mib2.icmpinechos); + src = ip4_current_dest_addr(); + /* multicast destination address? */ + if (ip4_addr_ismulticast(ip4_current_dest_addr())) { +#if LWIP_MULTICAST_PING + /* For multicast, use address of receiving interface as source address */ + src = netif_ip4_addr(inp); +#else /* LWIP_MULTICAST_PING */ + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast pings\n")); + goto icmperr; +#endif /* LWIP_MULTICAST_PING */ + } + /* broadcast destination address? */ + if (ip4_addr_isbroadcast(ip4_current_dest_addr(), ip_current_netif())) { +#if LWIP_BROADCAST_PING + /* For broadcast, use address of receiving interface as source address */ + src = netif_ip4_addr(inp); +#else /* LWIP_BROADCAST_PING */ + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to broadcast pings\n")); + goto icmperr; +#endif /* LWIP_BROADCAST_PING */ + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); + if (p->tot_len < sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); + goto lenerr; + } +#if CHECKSUM_CHECK_ICMP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) { + if (inet_chksum_pbuf(p) != 0) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); + pbuf_free(p); + ICMP_STATS_INC(icmp.chkerr); + MIB2_STATS_INC(mib2.icmpinerrors); + return; + } + } +#endif +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + if (pbuf_header(p, (s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { + /* p is not big enough to contain link headers + * allocate a new one and copy p into it + */ + struct pbuf *r; + /* allocate new packet buffer with space for link headers */ + r = pbuf_alloc(PBUF_LINK, p->tot_len + hlen, PBUF_RAM); + if (r == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); + goto icmperr; + } + if (r->len < hlen + sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("first pbuf cannot hold the ICMP header")); + pbuf_free(r); + goto icmperr; + } + /* copy the ip header */ + MEMCPY(r->payload, iphdr_in, hlen); + /* switch r->payload back to icmp header (cannot fail) */ + if (pbuf_header(r, (s16_t)-hlen)) { + LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0); + pbuf_free(r); + goto icmperr; + } + /* copy the rest of the packet without ip header */ + if (pbuf_copy(r, p) != ERR_OK) { + LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("icmp_input: copying to new pbuf failed")); + pbuf_free(r); + goto icmperr; + } + /* free the original p */ + pbuf_free(p); + /* we now have an identical copy of p that has room for link headers */ + p = r; + } else { + /* restore p->payload to point to icmp header (cannot fail) */ + if (pbuf_header(p, -(s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto icmperr; + } + } +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + /* At this point, all checks are OK. */ + /* We generate an answer by switching the dest and src ip addresses, + * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ + iecho = (struct icmp_echo_hdr *)p->payload; + if (pbuf_header(p, (s16_t)hlen)) { + LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet")); + } else { + err_t ret; + struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; + ip4_addr_copy(iphdr->src, *src); + ip4_addr_copy(iphdr->dest, *ip4_current_src_addr()); + ICMPH_TYPE_SET(iecho, ICMP_ER); +#if CHECKSUM_GEN_ICMP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) { + /* adjust the checksum */ + if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1; + } else { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8); + } + } +#if LWIP_CHECKSUM_CTRL_PER_NETIF + else { + iecho->chksum = 0; + } +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#else /* CHECKSUM_GEN_ICMP */ + iecho->chksum = 0; +#endif /* CHECKSUM_GEN_ICMP */ + + /* Set the correct TTL and recalculate the header checksum. */ + IPH_TTL_SET(iphdr, ICMP_TTL); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, hlen)); + } +#endif /* CHECKSUM_GEN_IP */ + + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + MIB2_STATS_INC(mib2.icmpoutmsgs); + /* increase number of echo replies attempted to send */ + MIB2_STATS_INC(mib2.icmpoutechoreps); + + /* send an ICMP packet */ + ret = ip4_output_if(p, src, LWIP_IP_HDRINCL, + ICMP_TTL, 0, IP_PROTO_ICMP, inp); + if (ret != ERR_OK) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %s\n", lwip_strerr(ret))); + } + } + break; + default: + if (type == ICMP_DUR) { + MIB2_STATS_INC(mib2.icmpindestunreachs); + } else if (type == ICMP_TE) { + MIB2_STATS_INC(mib2.icmpintimeexcds); + } else if (type == ICMP_PP) { + MIB2_STATS_INC(mib2.icmpinparmprobs); + } else if (type == ICMP_SQ) { + MIB2_STATS_INC(mib2.icmpinsrcquenchs); + } else if (type == ICMP_RD) { + MIB2_STATS_INC(mib2.icmpinredirects); + } else if (type == ICMP_TS) { + MIB2_STATS_INC(mib2.icmpintimestamps); + } else if (type == ICMP_TSR) { + MIB2_STATS_INC(mib2.icmpintimestampreps); + } else if (type == ICMP_AM) { + MIB2_STATS_INC(mib2.icmpinaddrmasks); + } else if (type == ICMP_AMR) { + MIB2_STATS_INC(mib2.icmpinaddrmaskreps); + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", + (s16_t)type, (s16_t)code)); + ICMP_STATS_INC(icmp.proterr); + ICMP_STATS_INC(icmp.drop); + } + pbuf_free(p); + return; +lenerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.lenerr); + MIB2_STATS_INC(mib2.icmpinerrors); + return; +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING +icmperr: + pbuf_free(p); + ICMP_STATS_INC(icmp.err); + MIB2_STATS_INC(mib2.icmpinerrors); + return; +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ +} + +/** + * Send an icmp 'destination unreachable' packet, called from ip_input() if + * the transport layer protocol is unknown and from udp_input() if the local + * port is not bound. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'unreachable' packet + */ +void +icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) +{ + MIB2_STATS_INC(mib2.icmpoutdestunreachs); + icmp_send_response(p, ICMP_DUR, t); +} + +#if IP_FORWARD || IP_REASSEMBLY +/** + * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. + * + * @param p the input packet for which the 'time exceeded' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'time exceeded' packet + */ +void +icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) +{ + MIB2_STATS_INC(mib2.icmpouttimeexcds); + icmp_send_response(p, ICMP_TE, t); +} + +#endif /* IP_FORWARD || IP_REASSEMBLY */ + +/** + * Send an icmp packet in response to an incoming packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param type Type of the ICMP header + * @param code Code of the ICMP header + */ +static void +icmp_send_response(struct pbuf *p, u8_t type, u8_t code) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + /* we can use the echo header here */ + struct icmp_echo_hdr *icmphdr; + ip4_addr_t iphdr_src; + struct netif *netif; + + /* increase number of messages attempted to send */ + MIB2_STATS_INC(mib2.icmpoutmsgs); + + /* ICMP header + IP header + 8 bytes of data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); + MIB2_STATS_INC(mib2.icmpouterrors); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); + + iphdr = (struct ip_hdr *)p->payload; + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); + ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src); + LWIP_DEBUGF(ICMP_DEBUG, (" to ")); + ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->dest); + LWIP_DEBUGF(ICMP_DEBUG, ("\n")); + + icmphdr = (struct icmp_echo_hdr *)q->payload; + icmphdr->type = type; + icmphdr->code = code; + icmphdr->id = 0; + icmphdr->seqno = 0; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); + + ip4_addr_copy(iphdr_src, iphdr->src); +#ifdef LWIP_HOOK_IP4_ROUTE_SRC + { + ip4_addr_t iphdr_dst; + ip4_addr_copy(iphdr_dst, iphdr->dest); + netif = ip4_route_src(&iphdr_src, &iphdr_dst); + } +#else + netif = ip4_route(&iphdr_src); +#endif + if (netif != NULL) { + /* calculate checksum */ + icmphdr->chksum = 0; +#if CHECKSUM_GEN_ICMP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) { + icmphdr->chksum = inet_chksum(icmphdr, q->len); + } +#endif + ICMP_STATS_INC(icmp.xmit); + ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif); + } + pbuf_free(q); +} + +#endif /* LWIP_IPV4 && LWIP_ICMP */ diff --git a/components/net/lwip-2.0.3/src/core/ipv4/igmp.c b/components/net/lwip-2.0.3/src/core/ipv4/igmp.c new file mode 100644 index 0000000000..74a6c37731 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv4/igmp.c @@ -0,0 +1,800 @@ +/** + * @file + * IGMP - Internet Group Management Protocol + * + * @defgroup igmp IGMP + * @ingroup ip4 + * To be called from TCPIP thread + */ + +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +/*------------------------------------------------------------- +Note 1) +Although the rfc requires V1 AND V2 capability +we will only support v2 since now V1 is very old (August 1989) +V1 can be added if required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 2) +A query for a specific group address (as opposed to ALLHOSTS) +has now been implemented as I am unsure if it is required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 3) +The router alert rfc 2113 is implemented in outgoing packets +but not checked rigorously incoming +------------------------------------------------------------- +Steve Reynolds +------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * RFC 988 - Host extensions for IP multicasting - V0 + * RFC 1054 - Host extensions for IP multicasting - + * RFC 1112 - Host extensions for IP multicasting - V1 + * RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard) + * RFC 3376 - Internet Group Management Protocol, Version 3 - V3 + * RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+ + * RFC 2113 - IP Router Alert Option - + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/igmp.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/stats.h" +#include "lwip/prot/igmp.h" + +#include "string.h" + +static struct igmp_group *igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr); +static err_t igmp_remove_group(struct netif* netif, struct igmp_group *group); +static void igmp_timeout(struct netif *netif, struct igmp_group *group); +static void igmp_start_timer(struct igmp_group *group, u8_t max_time); +static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp); +static err_t igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif); +static void igmp_send(struct netif *netif, struct igmp_group *group, u8_t type); + +static ip4_addr_t allsystems; +static ip4_addr_t allrouters; + +/** + * Initialize the IGMP module + */ +void +igmp_init(void) +{ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n")); + + IP4_ADDR(&allsystems, 224, 0, 0, 1); + IP4_ADDR(&allrouters, 224, 0, 0, 2); +} + +/** + * Start IGMP processing on interface + * + * @param netif network interface on which start IGMP processing + */ +err_t +igmp_start(struct netif *netif) +{ + struct igmp_group* group; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", (void*)netif)); + + group = igmp_lookup_group(netif, &allsystems); + + if (group != NULL) { + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->use++; + + /* Allow the igmp messages at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD ")); + ip4_addr_debug_print_val(IGMP_DEBUG, allsystems); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, &allsystems, NETIF_ADD_MAC_FILTER); + } + + return ERR_OK; + } + + return ERR_MEM; +} + +/** + * Stop IGMP processing on interface + * + * @param netif network interface on which stop IGMP processing + */ +err_t +igmp_stop(struct netif *netif) +{ + struct igmp_group *group = netif_igmp_data(netif); + + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, NULL); + + while (group != NULL) { + struct igmp_group *next = group->next; /* avoid use-after-free below */ + + /* disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); + ip4_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER); + } + + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report IGMP memberships for this interface + * + * @param netif network interface on which report IGMP memberships + */ +void +igmp_report_groups(struct netif *netif) +{ + struct igmp_group *group = netif_igmp_data(netif); + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", (void*)netif)); + + /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ + if(group != NULL) { + group = group->next; + } + + while (group != NULL) { + igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + group = group->next; + } +} + +/** + * Search for a group in the global igmp_group_list + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search for + * @return a struct igmp_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct igmp_group * +igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr) +{ + struct igmp_group *group = netif_igmp_data(ifp); + + while (group != NULL) { + if (ip4_addr_cmp(&(group->group_address), addr)) { + return group; + } + group = group->next; + } + + /* to be clearer, we return NULL here instead of + * 'group' (which is also NULL at this point). + */ + return NULL; +} + +/** + * Search for a specific igmp group and create a new one if not found- + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search + * @return a struct igmp_group*, + * NULL on memory error. + */ +static struct igmp_group * +igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) +{ + struct igmp_group *group; + struct igmp_group *list_head = netif_igmp_data(ifp); + + /* Search if the group already exists */ + group = igmp_lookfor_group(ifp, addr); + if (group != NULL) { + /* Group already exists. */ + return group; + } + + /* Group doesn't exist yet, create a new one */ + group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP); + if (group != NULL) { + ip4_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = IGMP_GROUP_NON_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + + /* Ensure allsystems group is always first in list */ + if (list_head == NULL) { + /* this is the first entry in linked list */ + LWIP_ASSERT("igmp_lookup_group: first group must be allsystems", + (ip4_addr_cmp(addr, &allsystems) != 0)); + group->next = NULL; + netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group); + } else { + /* append _after_ first entry */ + LWIP_ASSERT("igmp_lookup_group: all except first group must not be allsystems", + (ip4_addr_cmp(addr, &allsystems) == 0)); + group->next = list_head->next; + list_head->next = group; + } + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); + ip4_addr_debug_print(IGMP_DEBUG, addr); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)ifp)); + + return group; +} + +/** + * Remove a group in the global igmp_group_list, but don't free it yet + * + * @param group the group to remove from the global igmp_group_list + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +static err_t +igmp_remove_group(struct netif* netif, struct igmp_group *group) +{ + err_t err = ERR_OK; + struct igmp_group *tmp_group; + + /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ + for (tmp_group = netif_igmp_data(netif); tmp_group != NULL; tmp_group = tmp_group->next) { + if (tmp_group->next == group) { + tmp_group->next = group->next; + break; + } + } + /* Group not found in the global igmp_group_list */ + if (tmp_group == NULL) { + err = ERR_ARG; + } + + return err; +} + +/** + * Called from ip_input() if a new IGMP packet is received. + * + * @param p received igmp packet, p->payload pointing to the igmp header + * @param inp network interface on which the packet was received + * @param dest destination ip address of the igmp packet + */ +void +igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest) +{ + struct igmp_msg* igmp; + struct igmp_group* group; + struct igmp_group* groupref; + + IGMP_STATS_INC(igmp.recv); + + /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ + if (p->len < IGMP_MINLEN) { + pbuf_free(p); + IGMP_STATS_INC(igmp.lenerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n")); + return; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from ")); + ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->src)); + LWIP_DEBUGF(IGMP_DEBUG, (" to address ")); + ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->dest)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)inp)); + + /* Now calculate and check the checksum */ + igmp = (struct igmp_msg *)p->payload; + if (inet_chksum(igmp, p->len)) { + pbuf_free(p); + IGMP_STATS_INC(igmp.chkerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n")); + return; + } + + /* Packet is ok so find an existing group */ + group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */ + + /* If group can be found or create... */ + if (!group) { + pbuf_free(p); + IGMP_STATS_INC(igmp.drop); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n")); + return; + } + + /* NOW ACT ON THE INCOMING MESSAGE TYPE... */ + switch (igmp->igmp_msgtype) { + case IGMP_MEMB_QUERY: + /* IGMP_MEMB_QUERY to the "all systems" address ? */ + if ((ip4_addr_cmp(dest, &allsystems)) && ip4_addr_isany(&igmp->igmp_group_address)) { + /* THIS IS THE GENERAL QUERY */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + + if (igmp->igmp_maxresp == 0) { + IGMP_STATS_INC(igmp.rx_v1); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n")); + igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR; + } else { + IGMP_STATS_INC(igmp.rx_general); + } + + groupref = netif_igmp_data(inp); + + /* Do not send messages on the all systems group address! */ + /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ + if(groupref != NULL) { + groupref = groupref->next; + } + + while (groupref) { + igmp_delaying_member(groupref, igmp->igmp_maxresp); + groupref = groupref->next; + } + } else { + /* IGMP_MEMB_QUERY to a specific group ? */ + if (!ip4_addr_isany(&igmp->igmp_group_address)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group ")); + ip4_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address); + if (ip4_addr_cmp(dest, &allsystems)) { + ip4_addr_t groupaddr; + LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + /* we first need to re-look for the group since we used dest last time */ + ip4_addr_copy(groupaddr, igmp->igmp_group_address); + group = igmp_lookfor_group(inp, &groupaddr); + } else { + LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + } + + if (group != NULL) { + IGMP_STATS_INC(igmp.rx_group); + igmp_delaying_member(group, igmp->igmp_maxresp); + } else { + IGMP_STATS_INC(igmp.drop); + } + } else { + IGMP_STATS_INC(igmp.proterr); + } + } + break; + case IGMP_V2_MEMB_REPORT: + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n")); + IGMP_STATS_INC(igmp.rx_report); + if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { + /* This is on a specific group we have already looked up */ + group->timer = 0; /* stopped */ + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + break; + default: + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n", + igmp->igmp_msgtype, group->group_state, (void*)&group, (void*)inp)); + IGMP_STATS_INC(igmp.proterr); + break; + } + + pbuf_free(p); + return; +} + +/** + * @ingroup igmp + * Join a group on one network interface. + * + * @param ifaddr ip address of the network interface which should join a new group + * @param groupaddr the ip address of the group which to join + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t +igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we join this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { + err = igmp_joingroup_netif(netif, groupaddr); + if (err != ERR_OK) { + /* Return an error even if some network interfaces are joined */ + /** @todo undo any other netif already joined */ + return err; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * @ingroup igmp + * Join a group on one network interface. + * + * @param netif the network interface which should join a new group + * @param groupaddr the ip address of the group which to join + * @return ERR_OK if group was joined on the netif, an err_t otherwise + */ +err_t +igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) +{ + struct igmp_group *group; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_joingroup_netif: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_joingroup_netif: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* make sure it is an igmp-enabled netif */ + LWIP_ERROR("igmp_joingroup_netif: attempt to join on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;); + + /* find group or create a new one if not found */ + group = igmp_lookup_group(netif, groupaddr); + + if (group != NULL) { + /* This should create a new group, check the state to make sure */ + if (group->group_state != IGMP_GROUP_NON_MEMBER) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to group not in state IGMP_GROUP_NON_MEMBER\n")); + } else { + /* OK - it was new group */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to new group: ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If first use of the group, allow the group at the MAC level */ + if ((group->use==0) && (netif->igmp_mac_filter != NULL)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: igmp_mac_filter(ADD ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); + } + + IGMP_STATS_INC(igmp.tx_join); + igmp_send(netif, group, IGMP_V2_MEMB_REPORT); + + igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + + /* Need to work out where this timer comes from */ + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } + /* Increment group use */ + group->use++; + /* Join on this interface */ + return ERR_OK; + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: Not enough memory to join to group\n")); + return ERR_MEM; + } +} + +/** + * @ingroup igmp + * Leave a group on one network interface. + * + * @param ifaddr ip address of the network interface which should leave a group + * @param groupaddr the ip address of the group which to leave + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t +igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we leave this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { + err_t res = igmp_leavegroup_netif(netif, groupaddr); + if (err != ERR_OK) { + /* Store this result if we have not yet gotten a success */ + err = res; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * @ingroup igmp + * Leave a group on one network interface. + * + * @param netif the network interface which should leave a group + * @param groupaddr the ip address of the group which to leave + * @return ERR_OK if group was left on the netif, an err_t otherwise + */ +err_t +igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) +{ + struct igmp_group *group; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_leavegroup_netif: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_leavegroup_netif: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* make sure it is an igmp-enabled netif */ + LWIP_ERROR("igmp_leavegroup_netif: attempt to leave on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;); + + /* find group */ + group = igmp_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Only send a leave if the flag is set according to the state diagram */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: Leaving group: ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If there is no other use of the group */ + if (group->use <= 1) { + /* Remove the group from the list */ + igmp_remove_group(netif, group); + + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: sending leaving group\n")); + IGMP_STATS_INC(igmp.tx_leave); + igmp_send(netif, group, IGMP_LEAVE_GROUP); + } + + /* Disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: igmp_mac_filter(DEL ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); + } + + /* Free group struct */ + memp_free(MEMP_IGMP_GROUP, group); + } else { + /* Decrement group use */ + group->use--; + } + return ERR_OK; + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: not member of group\n")); + return ERR_VAL; + } +} + +/** + * The igmp timer function (both for NO_SYS=1 and =0) + * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). + */ +void +igmp_tmr(void) +{ + struct netif *netif = netif_list; + + while (netif != NULL) { + struct igmp_group *group = netif_igmp_data(netif); + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + igmp_timeout(netif, group); + } + } + group = group->next; + } + netif = netif->next; + } +} + +/** + * Called if a timeout for one group is reached. + * Sends a report for this group. + * + * @param group an igmp_group for which a timeout is reached + */ +static void +igmp_timeout(struct netif *netif, struct igmp_group *group) +{ + /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group + (unless it is the allsystems group) */ + if ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && + (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); + ip4_addr_debug_print(IGMP_DEBUG, &(group->group_address)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)netif)); + + group->group_state = IGMP_GROUP_IDLE_MEMBER; + + IGMP_STATS_INC(igmp.tx_report); + igmp_send(netif, group, IGMP_V2_MEMB_REPORT); + } +} + +/** + * Start a timer for an igmp group + * + * @param group the igmp_group for which to start a timer + * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with + * every call to igmp_tmr()) + */ +static void +igmp_start_timer(struct igmp_group *group, u8_t max_time) +{ +#ifdef LWIP_RAND + group->timer = max_time > 2 ? (LWIP_RAND() % max_time) : 1; +#else /* LWIP_RAND */ + /* ATTENTION: use this only if absolutely necessary! */ + group->timer = max_time / 2; +#endif /* LWIP_RAND */ + + if (group->timer == 0) { + group->timer = 1; + } +} + +/** + * Delaying membership report for a group if necessary + * + * @param group the igmp_group for which "delaying" membership report + * @param maxresp query delay + */ +static void +igmp_delaying_member(struct igmp_group *group, u8_t maxresp) +{ + if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || + ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && + ((group->timer == 0) || (maxresp < group->timer)))) { + igmp_start_timer(group, maxresp); + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } +} + + +/** + * Sends an IP packet on a network interface. This function constructs the IP header + * and calculates the IP header checksum. If the source IP address is NULL, + * the IP address of the outgoing network interface is filled in as source address. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + */ +static err_t +igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif) +{ + /* This is the "router alert" option */ + u16_t ra[2]; + ra[0] = PP_HTONS(ROUTER_ALERT); + ra[1] = 0x0000; /* Router shall examine packet */ + IGMP_STATS_INC(igmp.xmit); + return ip4_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN); +} + +/** + * Send an igmp packet to a specific group. + * + * @param group the group to which to send the packet + * @param type the type of igmp packet to send + */ +static void +igmp_send(struct netif *netif, struct igmp_group *group, u8_t type) +{ + struct pbuf* p = NULL; + struct igmp_msg* igmp = NULL; + ip4_addr_t src = *IP4_ADDR_ANY4; + ip4_addr_t* dest = NULL; + + /* IP header + "router alert" option + IGMP header */ + p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); + + if (p) { + igmp = (struct igmp_msg *)p->payload; + LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg", + (p->len >= sizeof(struct igmp_msg))); + ip4_addr_copy(src, *netif_ip4_addr(netif)); + + if (type == IGMP_V2_MEMB_REPORT) { + dest = &(group->group_address); + ip4_addr_copy(igmp->igmp_group_address, group->group_address); + group->last_reporter_flag = 1; /* Remember we were the last to report */ + } else { + if (type == IGMP_LEAVE_GROUP) { + dest = &allrouters; + ip4_addr_copy(igmp->igmp_group_address, group->group_address); + } + } + + if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) { + igmp->igmp_msgtype = type; + igmp->igmp_maxresp = 0; + igmp->igmp_checksum = 0; + igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN); + + igmp_ip_output_if(p, &src, dest, netif); + } + + pbuf_free(p); + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n")); + IGMP_STATS_INC(igmp.memerr); + } +} + +#endif /* LWIP_IPV4 && LWIP_IGMP */ diff --git a/components/net/lwip-2.0.3/src/core/ipv4/ip4.c b/components/net/lwip-2.0.3/src/core/ipv4/ip4.c new file mode 100644 index 0000000000..4e4eb61146 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv4/ip4.c @@ -0,0 +1,1086 @@ +/** + * @file + * This is the IPv4 layer implementation for incoming and outgoing IP traffic. + * + * @see ip_frag.c + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip4_frag.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/igmp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/autoip.h" +#include "lwip/stats.h" +#include "lwip/prot/dhcp.h" + +#include + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +/** Set this to 0 in the rare case of wanting to call an extra function to + * generate the IP checksum (in contrast to calculating it on-the-fly). */ +#ifndef LWIP_INLINE_IP_CHKSUM +#if LWIP_CHECKSUM_CTRL_PER_NETIF +#define LWIP_INLINE_IP_CHKSUM 0 +#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#define LWIP_INLINE_IP_CHKSUM 1 +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#endif + +#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP_INLINE 1 +#else +#define CHECKSUM_GEN_IP_INLINE 0 +#endif + +#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT) +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1 + +/** Some defines for DHCP to let link-layer-addressed packets through while the + * netif is down. + * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT(port) + * to return 1 if the port is accepted and 0 if the port is not accepted. + */ +#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) +/* accept DHCP client port and custom port */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \ + || (LWIP_IP_ACCEPT_UDP_PORT(port))) +#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept custom port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port)) +#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept DHCP client port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT)) +#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ + +#else /* LWIP_DHCP */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0 +#endif /* LWIP_DHCP */ + +/** The IP header ID of the next outgoing IP packet */ +static u16_t ip_id; + +#if LWIP_MULTICAST_TX_OPTIONS +/** The default netif used for multicast */ +static struct netif* ip4_default_multicast_netif; + +/** + * @ingroup ip4 + * Set a default netif for IPv4 multicast. */ +void +ip4_set_default_multicast_netif(struct netif* default_multicast_netif) +{ + ip4_default_multicast_netif = default_multicast_netif; +} +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#ifdef LWIP_HOOK_IP4_ROUTE_SRC +/** + * Source based IPv4 routing must be fully implemented in + * LWIP_HOOK_IP4_ROUTE_SRC(). This function only provides he parameters. + */ +struct netif * +ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src) +{ + if (src != NULL) { + /* when src==NULL, the hook is called from ip4_route(dest) */ + struct netif *netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, src); + if (netif != NULL) { + return netif; + } + } + return ip4_route(dest); +} +#endif /* LWIP_HOOK_IP4_ROUTE_SRC */ + +/** + * Finds the appropriate network interface for a given IP address. It + * searches the list of network interfaces linearly. A match is found + * if the masked IP address of the network interface equals the masked + * IP address given to the function. + * + * @param dest the destination IP address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip4_route(const ip4_addr_t *dest) +{ + struct netif *netif; + +#if LWIP_MULTICAST_TX_OPTIONS + /* Use administratively selected interface for multicast by default */ + if (ip4_addr_ismulticast(dest) && ip4_default_multicast_netif) { + return ip4_default_multicast_netif; + } +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + + /* iterate through netifs */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + /* is the netif up, does it have a link and a valid address? */ + if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) { + /* network mask matches? */ + if (ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))) { + /* return netif on which to forward IP packet */ + return netif; + } + /* gateway matches on a non broadcast interface? (i.e. peer in a point to point interface) */ + if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_cmp(dest, netif_ip4_gw(netif))) { + /* return netif on which to forward IP packet */ + return netif; + } + } + } + +#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF + /* loopif is disabled, looopback traffic is passed through any netif */ + if (ip4_addr_isloopback(dest)) { + /* don't check for link on loopback traffic */ + if (netif_default != NULL && netif_is_up(netif_default)) { + return netif_default; + } + /* default netif is not up, just use any netif for loopback traffic */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (netif_is_up(netif)) { + return netif; + } + } + return NULL; + } +#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ + +#ifdef LWIP_HOOK_IP4_ROUTE_SRC + netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, NULL); + if (netif != NULL) { + return netif; + } +#elif defined(LWIP_HOOK_IP4_ROUTE) + netif = LWIP_HOOK_IP4_ROUTE(dest); + if (netif != NULL) { + return netif; + } +#endif + + if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) || + ip4_addr_isany_val(*netif_ip4_addr(netif_default))) { + /* No matching netif found and default netif is not usable. + If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + MIB2_STATS_INC(mib2.ipoutnoroutes); + return NULL; + } + + return netif_default; +} + +#if IP_FORWARD +/** + * Determine whether an IP address is in a reserved set of addresses + * that may not be forwarded, or whether datagrams to that destination + * may be forwarded. + * @param p the packet to forward + * @return 1: can forward 0: discard + */ +static int +ip4_canforward(struct pbuf *p) +{ + u32_t addr = lwip_htonl(ip4_addr_get_u32(ip4_current_dest_addr())); + + if (p->flags & PBUF_FLAG_LLBCAST) { + /* don't route link-layer broadcasts */ + return 0; + } + if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) { + /* don't route link-layer multicasts unless the destination address is an IP + multicast address */ + return 0; + } + if (IP_EXPERIMENTAL(addr)) { + return 0; + } + if (IP_CLASSA(addr)) { + u32_t net = addr & IP_CLASSA_NET; + if ((net == 0) || (net == ((u32_t)IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) { + /* don't route loopback packets */ + return 0; + } + } + return 1; +} + +/** + * Forwards an IP packet. It finds an appropriate route for the + * packet, decrements the TTL value of the packet, adjusts the + * checksum and outputs the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IP header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + PERF_START; + LWIP_UNUSED_ARG(inp); + + if (!ip4_canforward(p)) { + goto return_noroute; + } + + /* RFC3927 2.7: do not forward link-local addresses */ + if (ip4_addr_islinklocal(ip4_current_dest_addr())) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), + ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); + goto return_noroute; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip4_route_src(ip4_current_dest_addr(), ip4_current_src_addr()); + if (netif == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", + ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), + ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); + /* @todo: send ICMP_DUR_NET? */ + goto return_noroute; + } +#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not bouncing packets back on incoming interface.\n")); + goto return_noroute; + } +#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */ + + /* decrement TTL */ + IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); + /* send ICMP if TTL == 0 */ + if (IPH_TTL(iphdr) == 0) { + MIB2_STATS_INC(mib2.ipinhdrerrors); +#if LWIP_ICMP + /* Don't send ICMP messages in response to ICMP messages */ + if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { + icmp_time_exceeded(p, ICMP_TE_TTL); + } +#endif /* LWIP_ICMP */ + return; + } + + /* Incrementally update the IP checksum. */ + if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1); + } else { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100)); + } + + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), + ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); + + IP_STATS_INC(ip.fw); + MIB2_STATS_INC(mib2.ipforwdatagrams); + IP_STATS_INC(ip.xmit); + + PERF_STOP("ip4_forward"); + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) { +#if IP_FRAG + ip4_frag(p, netif, ip4_current_dest_addr()); +#else /* IP_FRAG */ + /* @todo: send ICMP Destination Unreachable code 13 "Communication administratively prohibited"? */ +#endif /* IP_FRAG */ + } else { +#if LWIP_ICMP + /* send ICMP Destination Unreachable code 4: "Fragmentation Needed and DF Set" */ + icmp_dest_unreach(p, ICMP_DUR_FRAG); +#endif /* LWIP_ICMP */ + } + return; + } + /* transmit pbuf on chosen interface */ + netif->output(netif, p, ip4_current_dest_addr()); + return; +return_noroute: + MIB2_STATS_INC(mib2.ipoutnoroutes); +} +#endif /* IP_FORWARD */ + +/** + * This function is called by the network interface device driver when + * an IP packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip_forward). The IP checksum is always checked. + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IP packet (p->payload points to IP header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip4_input(struct pbuf *p, struct netif *inp) +{ + struct ip_hdr *iphdr; + struct netif *netif; + u16_t iphdr_hlen; + u16_t iphdr_len; +#if IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP + int check_ip_src = 1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP */ + + IP_STATS_INC(ip.recv); + MIB2_STATS_INC(mib2.ipinreceives); + + /* identify the IP header */ + iphdr = (struct ip_hdr *)p->payload; + if (IPH_V(iphdr) != 4) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", (u16_t)IPH_V(iphdr))); + ip4_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.err); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinhdrerrors); + return ERR_OK; + } + +#ifdef LWIP_HOOK_IP4_INPUT + if (LWIP_HOOK_IP4_INPUT(p, inp)) { + /* the packet has been eaten */ + return ERR_OK; + } +#endif + + /* obtain IP header length in number of 32-bit words */ + iphdr_hlen = IPH_HL(iphdr); + /* calculate IP header length in bytes */ + iphdr_hlen *= 4; + /* obtain ip length in bytes */ + iphdr_len = lwip_ntohs(IPH_LEN(iphdr)); + + /* Trim pbuf. This is especially required for packets < 60 bytes. */ + if (iphdr_len < p->tot_len) { + pbuf_realloc(p, iphdr_len); + } + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len) || (iphdr_hlen < IP_HLEN)) { + if (iphdr_hlen < IP_HLEN) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("ip4_input: short IP header (%"U16_F" bytes) received, IP packet dropped\n", iphdr_hlen)); + } + if (iphdr_hlen > p->len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_hlen, p->len)); + } + if (iphdr_len > p->tot_len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_len, p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.lenerr); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipindiscards); + return ERR_OK; + } + + /* verify checksum */ +#if CHECKSUM_CHECK_IP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_IP) { + if (inet_chksum(iphdr, iphdr_hlen) != 0) { + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); + ip4_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.chkerr); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinhdrerrors); + return ERR_OK; + } + } +#endif + + /* copy IP addresses to aligned ip_addr_t */ + ip_addr_copy_from_ip4(ip_data.current_iphdr_dest, iphdr->dest); + ip_addr_copy_from_ip4(ip_data.current_iphdr_src, iphdr->src); + + /* match packet against an interface, i.e. is this packet for us? */ + if (ip4_addr_ismulticast(ip4_current_dest_addr())) { +#if LWIP_IGMP + if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ip4_current_dest_addr()))) { + /* IGMP snooping switches need 0.0.0.0 to be allowed as source address (RFC 4541) */ + ip4_addr_t allsystems; + IP4_ADDR(&allsystems, 224, 0, 0, 1); + if (ip4_addr_cmp(ip4_current_dest_addr(), &allsystems) && + ip4_addr_isany(ip4_current_src_addr())) { + check_ip_src = 0; + } + netif = inp; + } else { + netif = NULL; + } +#else /* LWIP_IGMP */ + if ((netif_is_up(inp)) && (!ip4_addr_isany_val(*netif_ip4_addr(inp)))) { + netif = inp; + } else { + netif = NULL; + } +#endif /* LWIP_IGMP */ + } else { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", + ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(netif_ip4_addr(netif)), + ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(netif_ip4_netmask(netif)), + ip4_addr_get_u32(netif_ip4_addr(netif)) & ip4_addr_get_u32(netif_ip4_netmask(netif)), + ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(netif_ip4_netmask(netif)))); + + /* interface is up and configured? */ + if ((netif_is_up(netif)) && (!ip4_addr_isany_val(*netif_ip4_addr(netif)))) { + /* unicast to this interface address? */ + if (ip4_addr_cmp(ip4_current_dest_addr(), netif_ip4_addr(netif)) || + /* or broadcast on this interface network address? */ + ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) +#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF + || (ip4_addr_get_u32(ip4_current_dest_addr()) == PP_HTONL(IPADDR_LOOPBACK)) +#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ + ) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#if LWIP_AUTOIP + /* connections to link-local addresses must persist after changing + the netif's address (RFC3927 ch. 1.9) */ + if (autoip_accept_packet(netif, ip4_current_dest_addr())) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: LLA packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#endif /* LWIP_AUTOIP */ + } + if (first) { +#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF + /* Packets sent to the loopback address must not be accepted on an + * interface that does not have the loopback address assigned to it, + * unless a non-loopback interface is used for loopback traffic. */ + if (ip4_addr_isloopback(ip4_current_dest_addr())) { + netif = NULL; + break; + } +#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while (netif != NULL); + } + +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed + * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. + * According to RFC 1542 section 3.1.1, referred by RFC 2131). + * + * If you want to accept private broadcast communication while a netif is down, + * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.: + * + * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345)) + */ + if (netif == NULL) { + /* remote port is DHCP server? */ + if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { + struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: UDP packet to DHCP client port %"U16_F"\n", + lwip_ntohs(udphdr->dest))); + if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: DHCP packet accepted.\n")); + netif = inp; + check_ip_src = 0; + } + } + } +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ +#if LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING + if (check_ip_src +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ + && !ip4_addr_isany_val(*ip4_current_src_addr()) +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + ) +#endif /* LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING */ + { + if ((ip4_addr_isbroadcast(ip4_current_src_addr(), inp)) || + (ip4_addr_ismulticast(ip4_current_src_addr()))) { + /* packet source is not valid */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip4_input: packet source is not valid.\n")); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinaddrerrors); + MIB2_STATS_INC(mib2.ipindiscards); + return ERR_OK; + } + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: packet not for us.\n")); +#if IP_FORWARD + /* non-broadcast packet? */ + if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), inp)) { + /* try to forward IP packet on (other) interfaces */ + ip4_forward(p, iphdr, inp); + } else +#endif /* IP_FORWARD */ + { + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinaddrerrors); + MIB2_STATS_INC(mib2.ipindiscards); + } + pbuf_free(p); + return ERR_OK; + } + /* packet consists of multiple fragments? */ + if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { +#if IP_REASSEMBLY /* packet fragment reassembly code present? */ + LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip4_reass()\n", + lwip_ntohs(IPH_ID(iphdr)), p->tot_len, lwip_ntohs(IPH_LEN(iphdr)), (u16_t)!!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (u16_t)((lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8))); + /* reassemble the packet*/ + p = ip4_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + return ERR_OK; + } + iphdr = (struct ip_hdr *)p->payload; +#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ + pbuf_free(p); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", + lwip_ntohs(IPH_OFFSET(iphdr)))); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + MIB2_STATS_INC(mib2.ipinunknownprotos); + return ERR_OK; +#endif /* IP_REASSEMBLY */ + } + +#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ + +#if LWIP_IGMP + /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ + if ((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { +#else + if (iphdr_hlen > IP_HLEN) { +#endif /* LWIP_IGMP */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); + pbuf_free(p); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + MIB2_STATS_INC(mib2.ipinunknownprotos); + return ERR_OK; + } +#endif /* IP_OPTIONS_ALLOWED == 0 */ + + /* send to upper layers */ + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: \n")); + ip4_debug_print(p); + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + + ip_data.current_netif = netif; + ip_data.current_input_netif = inp; + ip_data.current_ip4_header = iphdr; + ip_data.current_ip_header_tot_len = IPH_HL(iphdr) * 4; + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + pbuf_header(p, -(s16_t)iphdr_hlen); /* Move to payload, no check necessary. */ + + switch (IPH_PROTO(iphdr)) { +#if LWIP_UDP + case IP_PROTO_UDP: +#if LWIP_UDPLITE + case IP_PROTO_UDPLITE: +#endif /* LWIP_UDPLITE */ + MIB2_STATS_INC(mib2.ipindelivers); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP_PROTO_TCP: + MIB2_STATS_INC(mib2.ipindelivers); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP + case IP_PROTO_ICMP: + MIB2_STATS_INC(mib2.ipindelivers); + icmp_input(p, inp); + break; +#endif /* LWIP_ICMP */ +#if LWIP_IGMP + case IP_PROTO_IGMP: + igmp_input(p, inp, ip4_current_dest_addr()); + break; +#endif /* LWIP_IGMP */ + default: +#if LWIP_ICMP + /* send ICMP destination protocol unreachable unless is was a broadcast */ + if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) && + !ip4_addr_ismulticast(ip4_current_dest_addr())) { + pbuf_header_force(p, iphdr_hlen); /* Move to ip header, no check necessary. */ + p->payload = iphdr; + icmp_dest_unreach(p, ICMP_DUR_PROTO); + } +#endif /* LWIP_ICMP */ + pbuf_free(p); + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", (u16_t)IPH_PROTO(iphdr))); + + IP_STATS_INC(ip.proterr); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinunknownprotos); + } + } + + /* @todo: this is not really necessary... */ + ip_data.current_netif = NULL; + ip_data.current_input_netif = NULL; + ip_data.current_ip4_header = NULL; + ip_data.current_ip_header_tot_len = 0; + ip4_addr_set_any(ip4_current_src_addr()); + ip4_addr_set_any(ip4_current_dest_addr()); + + return ERR_OK; +} + +/** + * Sends an IP packet on a network interface. This function constructs + * the IP header and calculates the IP header checksum. If the source + * IP address is NULL, the IP address of the outgoing network + * interface is filled in as source address. + * If the destination IP address is LWIP_IP_HDRINCL, p is assumed to already + * include an IP header and p->payload points to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + * + * @note ip_id: RFC791 "some host may be able to simply use + * unique identifiers independent of destination" + */ +err_t +ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip4_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if() but with the possibility to include IP options: + * + * @ param ip_options pointer to the IP options, copied into the IP header + * @ param optlen length of ip_options + */ +err_t +ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + const ip4_addr_t *src_used = src; + if (dest != LWIP_IP_HDRINCL) { + if (ip4_addr_isany(src)) { + src_used = netif_ip4_addr(netif); + } + } + +#if IP_OPTIONS_SEND + return ip4_output_if_opt_src(p, src_used, dest, ttl, tos, proto, netif, + ip_options, optlen); +#else /* IP_OPTIONS_SEND */ + return ip4_output_if_src(p, src_used, dest, ttl, tos, proto, netif); +#endif /* IP_OPTIONS_SEND */ +} + +/** + * Same as ip_output_if() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip4_output_if_opt_src(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if_opt() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + struct ip_hdr *iphdr; + ip4_addr_t dest_addr; +#if CHECKSUM_GEN_IP_INLINE + u32_t chk_sum = 0; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + MIB2_STATS_INC(mib2.ipoutrequests); + + /* Should the IP header be generated or is it already included in p? */ + if (dest != LWIP_IP_HDRINCL) { + u16_t ip_hlen = IP_HLEN; +#if IP_OPTIONS_SEND + u16_t optlen_aligned = 0; + if (optlen != 0) { +#if CHECKSUM_GEN_IP_INLINE + int i; +#endif /* CHECKSUM_GEN_IP_INLINE */ + /* round up to a multiple of 4 */ + optlen_aligned = ((optlen + 3) & ~3); + ip_hlen += optlen_aligned; + /* First write in the IP options */ + if (pbuf_header(p, optlen_aligned)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output_if_opt: not enough room for IP options in pbuf\n")); + IP_STATS_INC(ip.err); + MIB2_STATS_INC(mib2.ipoutdiscards); + return ERR_BUF; + } + MEMCPY(p->payload, ip_options, optlen); + if (optlen < optlen_aligned) { + /* zero the remaining bytes */ + memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); + } +#if CHECKSUM_GEN_IP_INLINE + for (i = 0; i < optlen_aligned/2; i++) { + chk_sum += ((u16_t*)p->payload)[i]; + } +#endif /* CHECKSUM_GEN_IP_INLINE */ + } +#endif /* IP_OPTIONS_SEND */ + /* generate IP header */ + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output: not enough room for IP header in pbuf\n")); + + IP_STATS_INC(ip.err); + MIB2_STATS_INC(mib2.ipoutdiscards); + return ERR_BUF; + } + + iphdr = (struct ip_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", + (p->len >= sizeof(struct ip_hdr))); + + IPH_TTL_SET(iphdr, ttl); + IPH_PROTO_SET(iphdr, proto); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += PP_NTOHS(proto | (ttl << 8)); +#endif /* CHECKSUM_GEN_IP_INLINE */ + + /* dest cannot be NULL here */ + ip4_addr_copy(iphdr->dest, *dest); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + IPH_VHL_SET(iphdr, 4, ip_hlen / 4); + IPH_TOS_SET(iphdr, tos); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += PP_NTOHS(tos | (iphdr->_v_hl << 8)); +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_LEN_SET(iphdr, lwip_htons(p->tot_len)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_len; +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_OFFSET_SET(iphdr, 0); + IPH_ID_SET(iphdr, lwip_htons(ip_id)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_id; +#endif /* CHECKSUM_GEN_IP_INLINE */ + ++ip_id; + + if (src == NULL) { + ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY4); + } else { + /* src cannot be NULL here */ + ip4_addr_copy(iphdr->src, *src); + } + +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16; + chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF); + chk_sum = (chk_sum >> 16) + chk_sum; + chk_sum = ~chk_sum; + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { + iphdr->_chksum = (u16_t)chk_sum; /* network order */ + } +#if LWIP_CHECKSUM_CTRL_PER_NETIF + else { + IPH_CHKSUM_SET(iphdr, 0); + } +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ +#else /* CHECKSUM_GEN_IP_INLINE */ + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); + } +#endif /* CHECKSUM_GEN_IP */ +#endif /* CHECKSUM_GEN_IP_INLINE */ + } else { + /* IP header already included in p */ + iphdr = (struct ip_hdr *)p->payload; + ip4_addr_copy(dest_addr, iphdr->dest); + dest = &dest_addr; + } + + IP_STATS_INC(ip.xmit); + + LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); + ip4_debug_print(p); + +#if ENABLE_LOOPBACK + if (ip4_addr_cmp(dest, netif_ip4_addr(netif)) +#if !LWIP_HAVE_LOOPIF + || ip4_addr_isloopback(dest) +#endif /* !LWIP_HAVE_LOOPIF */ + ) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); + return netif_loop_output(netif, p); + } +#if LWIP_MULTICAST_TX_OPTIONS + if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { + netif_loop_output(netif, p); + } +#endif /* LWIP_MULTICAST_TX_OPTIONS */ +#endif /* ENABLE_LOOPBACK */ +#if IP_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + return ip4_frag(p, netif, dest); + } +#endif /* IP_FRAG */ + + LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: call netif->output()\n")); + return netif->output(netif, p, dest); +} + +/** + * Simple interface to ip_output_if. It finds the outgoing network + * interface and calls upon ip_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto) +{ + struct netif *netif; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if ((netif = ip4_route_src(dest, src)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + return ip4_output_if(p, src, dest, ttl, tos, proto, netif); +} + +#if LWIP_NETIF_HWADDRHINT +/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) +{ + struct netif *netif; + err_t err; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if ((netif = ip4_route_src(dest, src)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip4_output_if(p, src, dest, ttl, tos, proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if IP_DEBUG +/* Print an IP header by using LWIP_DEBUGF + * @param p an IP packet, p->payload pointing to the IP header + */ +void +ip4_debug_print(struct pbuf *p) +{ + struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; + + LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", + (u16_t)IPH_V(iphdr), + (u16_t)IPH_HL(iphdr), + (u16_t)IPH_TOS(iphdr), + lwip_ntohs(IPH_LEN(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", + lwip_ntohs(IPH_ID(iphdr)), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 15 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 14 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 13 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", + (u16_t)IPH_TTL(iphdr), + (u16_t)IPH_PROTO(iphdr), + lwip_ntohs(IPH_CHKSUM(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", + ip4_addr1_16(&iphdr->src), + ip4_addr2_16(&iphdr->src), + ip4_addr3_16(&iphdr->src), + ip4_addr4_16(&iphdr->src))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", + ip4_addr1_16(&iphdr->dest), + ip4_addr2_16(&iphdr->dest), + ip4_addr3_16(&iphdr->dest), + ip4_addr4_16(&iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP_DEBUG */ + +#endif /* LWIP_IPV4 */ diff --git a/components/net/lwip-2.0.3/src/core/ipv4/ip4_addr.c b/components/net/lwip-2.0.3/src/core/ipv4/ip4_addr.c new file mode 100644 index 0000000000..2d479923bd --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv4/ip4_addr.c @@ -0,0 +1,331 @@ +/** + * @file + * This is the IPv4 address tools implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +/* used by IP4_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ +const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY); +const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST); + +/** + * Determine if an address is a broadcast address on a network interface + * + * @param addr address to be checked + * @param netif the network interface against which the address is checked + * @return returns non-zero if the address is a broadcast address + */ +u8_t +ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif) +{ + ip4_addr_t ipaddr; + ip4_addr_set_u32(&ipaddr, addr); + + /* all ones (broadcast) or all zeroes (old skool broadcast) */ + if ((~addr == IPADDR_ANY) || + (addr == IPADDR_ANY)) { + return 1; + /* no broadcast support on this network interface? */ + } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) { + /* the given address cannot be a broadcast address + * nor can we check against any broadcast addresses */ + return 0; + /* address matches network interface address exactly? => no broadcast */ + } else if (addr == ip4_addr_get_u32(netif_ip4_addr(netif))) { + return 0; + /* on the same (sub) network... */ + } else if (ip4_addr_netcmp(&ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) + /* ...and host identifier bits are all ones? =>... */ + && ((addr & ~ip4_addr_get_u32(netif_ip4_netmask(netif))) == + (IPADDR_BROADCAST & ~ip4_addr_get_u32(netif_ip4_netmask(netif))))) { + /* => network broadcast address */ + return 1; + } else { + return 0; + } +} + +/** Checks if a netmask is valid (starting with ones, then only zeros) + * + * @param netmask the IPv4 netmask to check (in network byte order!) + * @return 1 if the netmask is valid, 0 if it is not + */ +u8_t +ip4_addr_netmask_valid(u32_t netmask) +{ + u32_t mask; + u32_t nm_hostorder = lwip_htonl(netmask); + + /* first, check for the first zero */ + for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) == 0) { + break; + } + } + /* then check that there is no one */ + for (; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) != 0) { + /* there is a one after the first zero -> invalid */ + return 0; + } + } + /* no one after the first zero -> valid */ + return 1; +} + +/* Here for now until needed in other places in lwIP */ +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif + +/** + * Ascii internet address interpretation routine. + * The value returned is in network order. + * + * @param cp IP address in ascii representation (e.g. "127.0.0.1") + * @return ip address in network order + */ +u32_t +ipaddr_addr(const char *cp) +{ + ip4_addr_t val; + + if (ip4addr_aton(cp, &val)) { + return ip4_addr_get_u32(&val); + } + return (IPADDR_NONE); +} + +/** + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + * + * @param cp IP address in ascii representation (e.g. "127.0.0.1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ip4addr_aton(const char *cp, ip4_addr_t *addr) +{ + u32_t val; + u8_t base; + char c; + u32_t parts[4]; + u32_t *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, 1-9=decimal. + */ + if (!isdigit(c)) { + return 0; + } + val = 0; + base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') { + base = 16; + c = *++cp; + } else { + base = 8; + } + } + for (;;) { + if (isdigit(c)) { + val = (val * base) + (u32_t)(c - '0'); + c = *++cp; + } else if (base == 16 && isxdigit(c)) { + val = (val << 4) | (u32_t)(c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else { + break; + } + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) { + return 0; + } + *pp++ = val; + c = *++cp; + } else { + break; + } + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) { + return 0; + } + /* + * Concoct the address according to + * the number of parts specified. + */ + switch (pp - parts + 1) { + + case 0: + return 0; /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffffUL) { + return 0; + } + if (parts[0] > 0xff) { + return 0; + } + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) { + return 0; + } + if ((parts[0] > 0xff) || (parts[1] > 0xff)) { + return 0; + } + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) { + return 0; + } + if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) { + return 0; + } + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + default: + LWIP_ASSERT("unhandled", 0); + break; + } + if (addr) { + ip4_addr_set_u32(addr, lwip_htonl(val)); + } + return 1; +} + +/** + * Convert numeric IP address into decimal dotted ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * representation of addr + */ +char* +ip4addr_ntoa(const ip4_addr_t *addr) +{ + static char str[IP4ADDR_STRLEN_MAX]; + return ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char* +ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen) +{ + u32_t s_addr; + char inv[3]; + char *rp; + u8_t *ap; + u8_t rem; + u8_t n; + u8_t i; + int len = 0; + + s_addr = ip4_addr_get_u32(addr); + + rp = buf; + ap = (u8_t *)&s_addr; + for (n = 0; n < 4; n++) { + i = 0; + do { + rem = *ap % (u8_t)10; + *ap /= (u8_t)10; + inv[i++] = (char)('0' + rem); + } while (*ap); + while (i--) { + if (len++ >= buflen) { + return NULL; + } + *rp++ = inv[i]; + } + if (len++ >= buflen) { + return NULL; + } + *rp++ = '.'; + ap++; + } + *--rp = 0; + return buf; +} + +#endif /* LWIP_IPV4 */ diff --git a/components/net/lwip-2.0.3/src/core/ipv4/ip4_frag.c b/components/net/lwip-2.0.3/src/core/ipv4/ip4_frag.c new file mode 100644 index 0000000000..fdb20886cb --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv4/ip4_frag.c @@ -0,0 +1,864 @@ +/** + * @file + * This is the IPv4 packet segmentation and reassembly implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * Simon Goldschmidt + * original reassembly code by Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/ip4_frag.h" +#include "lwip/def.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/stats.h" +#include "lwip/icmp.h" + +#include + +#if IP_REASSEMBLY +/** + * The IP reassembly code currently has the following limitations: + * - IP header options are not supported + * - fragments must not overlap (e.g. due to different routes), + * currently, overlapping or duplicate fragments are thrown away + * if IP_REASS_CHECK_OVERLAP=1 (the default)! + * + * @todo: work with IP header options + */ + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +#define IP_REASS_VALIDATE_TELEGRAM_FINISHED 1 +#define IP_REASS_VALIDATE_PBUF_QUEUED 0 +#define IP_REASS_VALIDATE_PBUF_DROPPED -1 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IP header, since it replaces + * the IP header in memory in incoming fragments (after copying it) to keep + * track of the various fragments. (-> If the IP header doesn't need packing, + * this struct doesn't need packing, too.) + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ + (ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ + ip4_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ + IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 + +/* global variables */ +static struct ip_reassdata *reassdatagrams; +static u16_t ip_reass_pbufcount; + +/* function prototypes */ +static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); +static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); + +/** + * Reassembly timer base function + * for both NO_SYS == 0 and 1 (!). + * + * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). + */ +void +ip_reass_tmr(void) +{ + struct ip_reassdata *r, *prev = NULL; + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); + prev = r; + r = r->next; + } else { + /* reassembly timed out */ + struct ip_reassdata *tmp; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip_reass_free_complete_datagram(tmp, prev); + } + } +} + +/** + * Free a datagram (struct ip_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip_reass_pbufcount), + * SNMP counters and sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + * @param prev the previous datagram in the linked list + * @return the number of pbufs freed + */ +static int +ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + u16_t pbufs_freed = 0; + u16_t clen; + struct pbuf *p; + struct ip_reass_helper *iprh; + + LWIP_ASSERT("prev != ipr", prev != ipr); + if (prev != NULL) { + LWIP_ASSERT("prev->next == ipr", prev->next == ipr); + } + + MIB2_STATS_INC(mib2.ipreasmfails); +#if LWIP_ICMP + iprh = (struct ip_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, copy the original header into it. */ + SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); + icmp_time_exceeded(p, ICMP_TE_FRAG); + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + /* Then, unchain the struct ip_reassdata from the list and free it. */ + ip_reass_dequeue_datagram(ipr, prev); + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); + ip_reass_pbufcount -= pbufs_freed; + + return pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram 'fraghdr' belongs to is not freed! + * + * @param fraghdr IP header of the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + * @return the number of pbufs freed + */ +static int +ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) +{ + /* @todo Can't we simply remove the last datagram in the + * linked list behind reassdatagrams? + */ + struct ip_reassdata *r, *oldest, *prev, *oldest_prev; + int pbufs_freed = 0, pbufs_freed_current; + int other_datagrams; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the datagram that 'fraghdr' belongs to! */ + do { + oldest = NULL; + prev = NULL; + oldest_prev = NULL; + other_datagrams = 0; + r = reassdatagrams; + while (r != NULL) { + if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { + /* Not the same datagram as fraghdr */ + other_datagrams++; + if (oldest == NULL) { + oldest = r; + oldest_prev = prev; + } else if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + oldest_prev = prev; + } + } + if (r->next != NULL) { + prev = r; + } + r = r->next; + } + if (oldest != NULL) { + pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev); + pbufs_freed += pbufs_freed_current; + } + } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); + return pbufs_freed; +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Enqueues a new fragment into the fragment queue + * @param fraghdr points to the new fragments IP hdr + * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) + * @return A pointer to the queue location into which the fragment was enqueued + */ +static struct ip_reassdata* +ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) +{ + struct ip_reassdata* ipr; +#if ! IP_REASS_FREE_OLDEST + LWIP_UNUSED_ARG(clen); +#endif + + /* No matching previous fragment found, allocate a new reassdata struct */ + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + } + if (ipr == NULL) +#endif /* IP_REASS_FREE_OLDEST */ + { + IPFRAG_STATS_INC(ip_frag.memerr); + LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); + return NULL; + } + } + memset(ipr, 0, sizeof(struct ip_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + /* copy the ip header for later tests and input */ + /* @todo: no ip options supported? */ + SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); + return ipr; +} + +/** + * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. + * @param ipr points to the queue entry to dequeue + */ +static void +ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + /* dequeue the reass struct */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", prev != NULL); + prev->next = ipr->next; + } + + /* now we can free the ip_reassdata struct */ + memp_free(MEMP_REASSDATA, ipr); +} + +/** + * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list + * will grow over time as new pbufs are rx. + * Also checks that the datagram passes basic continuity checks (if the last + * fragment was received at least once). + * @param ipr points to the reassembly state + * @param new_p points to the pbuf for the current fragment + * @param is_last is 1 if this pbuf has MF==0 (ipr->flags not updated yet) + * @return see IP_REASS_VALIDATE_* defines + */ +static int +ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p, int is_last) +{ + struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct pbuf *q; + u16_t offset, len; + struct ip_hdr *fraghdr; + int valid = 1; + + /* Extract length and fragment offset from current fragment */ + fraghdr = (struct ip_hdr*)new_p->payload; + len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + + /* overwrite the fragment's ip header from the pbuf with our helper struct, + * and setup the embedded helper structure. */ + /* make sure the struct ip_reass_helper fits into the IP header */ + LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", + sizeof(struct ip_reass_helper) <= IP_HLEN); + iprh = (struct ip_reass_helper*)new_p->payload; + iprh->next_pbuf = NULL; + iprh->start = offset; + iprh->end = offset + len; + + /* Iterate through until we either get to the end of the list (append), + * or we find one with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ +#if IP_REASS_CHECK_OVERLAP + if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { + /* fragment overlaps with previous or following, throw away */ + goto freepbuf; + } +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + if (iprh_prev->end != iprh->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + if (iprh->end > iprh_tmp->start) { + /* fragment overlaps with following, throw away */ + goto freepbuf; + } +#endif /* IP_REASS_CHECK_OVERLAP */ + /* fragment with the lowest offset */ + ipr->p = new_p; + } + break; + } else if (iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + goto freepbuf; +#if IP_REASS_CHECK_OVERLAP + } else if (iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + goto freepbuf; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no holes. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = new_p; + } + } + + /* At this point, the validation part begins: */ + /* If we already received the last fragment */ + if (is_last || ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0)) { + /* and had no holes so far */ + if (valid) { + /* then check if the rest of the fragments is here */ + /* Check if the queue starts with the first datagram */ + if ((ipr->p == NULL) || (((struct ip_reass_helper*)ipr->p->payload)->start != 0)) { + valid = 0; + } else { + /* and check that there are no holes after this datagram */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while (q != NULL) { + iprh = (struct ip_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + /* if still valid, all fragments are received + * (because to the MF==0 already arrived */ + if (valid) { + LWIP_ASSERT("sanity check", ipr->p != NULL); + LWIP_ASSERT("sanity check", + ((struct ip_reass_helper*)ipr->p->payload) != iprh); + LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", + iprh->next_pbuf == NULL); + } + } + } + /* If valid is 0 here, there are some fragments missing in the middle + * (since MF == 0 has already arrived). Such datagrams simply time out if + * no more fragments are received... */ + return valid ? IP_REASS_VALIDATE_TELEGRAM_FINISHED : IP_REASS_VALIDATE_PBUF_QUEUED; + } + /* If we come here, not all fragments were received, yet! */ + return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */ +#if IP_REASS_CHECK_OVERLAP +freepbuf: + ip_reass_pbufcount -= pbuf_clen(new_p); + pbuf_free(new_p); + return IP_REASS_VALIDATE_PBUF_DROPPED; +#endif /* IP_REASS_CHECK_OVERLAP */ +} + +/** + * Reassembles incoming IP fragments into an IP datagram. + * + * @param p points to a pbuf chain of the fragment + * @return NULL if reassembly is incomplete, ? otherwise + */ +struct pbuf * +ip4_reass(struct pbuf *p) +{ + struct pbuf *r; + struct ip_hdr *fraghdr; + struct ip_reassdata *ipr; + struct ip_reass_helper *iprh; + u16_t offset, len, clen; + int valid; + int is_last; + + IPFRAG_STATS_INC(ip_frag.recv); + MIB2_STATS_INC(mib2.ipreasmreqds); + + fraghdr = (struct ip_hdr*)p->payload; + + if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: IP options currently not supported!\n")); + IPFRAG_STATS_INC(ip_frag.err); + goto nullreturn; + } + + offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + + /* Check if we are allowed to enqueue more datagrams. */ + clen = pbuf_clen(p); + if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || + ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) +#endif /* IP_REASS_FREE_OLDEST */ + { + /* No datagram could be freed and still too many pbufs enqueued */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", + ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); + IPFRAG_STATS_INC(ip_frag.memerr); + /* @todo: send ICMP time exceeded here? */ + /* drop this pbuf */ + goto nullreturn; + } + } + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n", + lwip_ntohs(IPH_ID(fraghdr)))); + IPFRAG_STATS_INC(ip_frag.cachehit); + break; + } + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); + /* Bail if unable to enqueue */ + if (ipr == NULL) { + goto nullreturn; + } + } else { + if (((lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && + ((lwip_ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { + /* ipr->iphdr is not the header from the first fragment, but fraghdr is + * -> copy fraghdr into ipr->iphdr since we want to have the header + * of the first fragment (for ICMP time exceeded and later, for copying + * all options, if supported)*/ + SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); + } + } + + /* At this point, we have either created a new entry or pointing + * to an existing one */ + + /* check for 'no more fragments', and update queue entry*/ + is_last = (IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0; + if (is_last) { + u16_t datagram_len = (u16_t)(offset + len); + if ((datagram_len < offset) || (datagram_len > (0xFFFF - IP_HLEN))) { + /* u16_t overflow, cannot handle this */ + goto nullreturn; + } + } + /* find the right place to insert this pbuf */ + /* @todo: trim pbufs if fragments are overlapping */ + valid = ip_reass_chain_frag_into_datagram_and_validate(ipr, p, is_last); + if (valid == IP_REASS_VALIDATE_PBUF_DROPPED) { + goto nullreturn; + } + /* if we come here, the pbuf has been enqueued */ + + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time + (overflow checked by testing against IP_REASS_MAX_PBUFS) */ + ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount + clen); + if (is_last) { + u16_t datagram_len = (u16_t)(offset + len); + ipr->datagram_len = datagram_len; + ipr->flags |= IP_REASS_FLAG_LASTFRAG; + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip4_reass: last fragment seen, total len %"S16_F"\n", + ipr->datagram_len)); + } + + if (valid == IP_REASS_VALIDATE_TELEGRAM_FINISHED) { + struct ip_reassdata *ipr_prev; + /* the totally last fragment (flag more fragments = 0) was received at least + * once AND all fragments are received */ + ipr->datagram_len += IP_HLEN; + + /* save the second pbuf before copying the header over the pointer */ + r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; + + /* copy the original ip header back to the first pbuf */ + fraghdr = (struct ip_hdr*)(ipr->p->payload); + SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); + IPH_LEN_SET(fraghdr, lwip_htons(ipr->datagram_len)); + IPH_OFFSET_SET(fraghdr, 0); + IPH_CHKSUM_SET(fraghdr, 0); + /* @todo: do we need to set/calculate the correct checksum? */ +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); + } +#endif /* CHECKSUM_GEN_IP */ + + p = ipr->p; + + /* chain together the pbufs contained within the reass_data list. */ + while (r != NULL) { + iprh = (struct ip_reass_helper*)r->payload; + + /* hide the ip header for every succeeding fragment */ + pbuf_header(r, -IP_HLEN); + pbuf_cat(p, r); + r = iprh->next_pbuf; + } + + /* find the previous entry in the linked list */ + if (ipr == reassdatagrams) { + ipr_prev = NULL; + } else { + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } + + /* release the sources allocate for the fragment queue entry */ + ip_reass_dequeue_datagram(ipr, ipr_prev); + + /* and adjust the number of pbufs currently queued for reassembly. */ + ip_reass_pbufcount -= pbuf_clen(p); + + MIB2_STATS_INC(mib2.ipreasmoks); + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); + return NULL; + +nullreturn: + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: nullreturn\n")); + IPFRAG_STATS_INC(ip_frag.drop); + pbuf_free(p); + return NULL; +} +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if !LWIP_NETIF_TX_SINGLE_PBUF +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ipfrag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip_frag_free_pbuf_custom_ref(pcr); +} +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ + +/** + * Fragment an IP datagram if too large for the netif. + * + * Chop the datagram in MTU sized chunks and send them in order + * by pointing PBUF_REFs into p. + * + * @param p ip packet to send + * @param netif the netif on which to send + * @param dest destination ip address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) +{ + struct pbuf *rambuf; +#if !LWIP_NETIF_TX_SINGLE_PBUF + struct pbuf *newpbuf; + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif + struct ip_hdr *original_iphdr; + struct ip_hdr *iphdr; + const u16_t nfb = (netif->mtu - IP_HLEN) / 8; + u16_t left, fragsize; + u16_t ofo; + int last; + u16_t poff = IP_HLEN; + u16_t tmp; + + original_iphdr = (struct ip_hdr *)p->payload; + iphdr = original_iphdr; + LWIP_ERROR("ip4_frag() does not support IP options", IPH_HL(iphdr) * 4 == IP_HLEN, return ERR_VAL); + + /* Save original offset */ + tmp = lwip_ntohs(IPH_OFFSET(iphdr)); + ofo = tmp & IP_OFFMASK; + LWIP_ERROR("ip_frag(): MF already set", (tmp & IP_MF) == 0, return ERR_VAL); + + left = p->tot_len - IP_HLEN; + + while (left) { + /* Fill this fragment */ + fragsize = LWIP_MIN(left, nfb * 8); + +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, fragsize, PBUF_RAM); + if (rambuf == NULL) { + goto memerr; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, rambuf->payload, fragsize, poff); + /* make room for the IP header */ + if (pbuf_header(rambuf, IP_HLEN)) { + pbuf_free(rambuf); + goto memerr; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr*)rambuf->payload; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link and IP header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); + if (rambuf == NULL) { + goto memerr; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP_HLEN))); + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr *)rambuf->payload; + + left_to_copy = fragsize; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + u16_t plen = p->len - poff; + newpbuflen = LWIP_MIN(left_to_copy, plen); + /* Is this pbuf already empty? */ + if (!newpbuflen) { + poff = 0; + p = p->next; + continue; + } + pcr = ip_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + goto memerr; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, + (u8_t*)p->payload + poff, newpbuflen); + if (newpbuf == NULL) { + ip_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + goto memerr; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + poff = 0; + p = p->next; + } + } + poff += newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + /* Correct header */ + last = (left <= netif->mtu - IP_HLEN); + + /* Set new offset and MF flag */ + tmp = (IP_OFFMASK & (ofo)); + if (!last) { + tmp = tmp | IP_MF; + } + IPH_OFFSET_SET(iphdr, lwip_htons(tmp)); + IPH_LEN_SET(iphdr, lwip_htons(fragsize + IP_HLEN)); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + } +#endif /* CHECKSUM_GEN_IP */ + + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + netif->output(netif, rambuf, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); + left -= fragsize; + ofo += nfb; + } + MIB2_STATS_INC(mib2.ipfragoks); + return ERR_OK; +memerr: + MIB2_STATS_INC(mib2.ipfragfails); + return ERR_MEM; +} +#endif /* IP_FRAG */ + +#endif /* LWIP_IPV4 */ diff --git a/components/net/lwip-2.0.3/src/core/ipv6/dhcp6.c b/components/net/lwip-2.0.3/src/core/ipv6/dhcp6.c new file mode 100644 index 0000000000..f27a725e3a --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv6/dhcp6.c @@ -0,0 +1,50 @@ +/** + * @file + * + * DHCPv6. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/def.h" + + +#endif /* LWIP_IPV6 && LWIP_IPV6_DHCP6 */ diff --git a/components/net/lwip-2.0.3/src/core/ipv6/ethip6.c b/components/net/lwip-2.0.3/src/core/ipv6/ethip6.c new file mode 100644 index 0000000000..8f9a91b5f7 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv6/ethip6.c @@ -0,0 +1,118 @@ +/** + * @file + * + * Ethernet output for IPv6. Uses ND tables for link-layer addressing. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_ETHERNET + +#include "lwip/ethip6.h" +#include "lwip/nd6.h" +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp6.h" +#include "lwip/prot/ethernet.h" +#include "netif/ethernet.h" + +#include + +/** + * Resolve and fill-in Ethernet address header for outgoing IPv6 packet. + * + * For IPv6 multicast, corresponding Ethernet addresses + * are selected and the packet is transmitted on the link. + * + * For unicast addresses, ask the ND6 module what to do. It will either let us + * send the the packet right away, or queue the packet for later itself, unless + * an error occurs. + * + * @todo anycast addresses + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ip6addr The IP address of the packet destination. + * + * @return + * - ERR_OK or the return value of @ref nd6_get_next_hop_addr_or_queue. + */ +err_t +ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) +{ + struct eth_addr dest; + const u8_t *hwaddr; + err_t result; + + /* multicast destination IP address? */ + if (ip6_addr_ismulticast(ip6addr)) { + /* Hash IP multicast address to MAC address.*/ + dest.addr[0] = 0x33; + dest.addr[1] = 0x33; + dest.addr[2] = ((const u8_t *)(&(ip6addr->addr[3])))[0]; + dest.addr[3] = ((const u8_t *)(&(ip6addr->addr[3])))[1]; + dest.addr[4] = ((const u8_t *)(&(ip6addr->addr[3])))[2]; + dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3]; + + /* Send out. */ + return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); + } + + /* We have a unicast destination IP address */ + /* @todo anycast? */ + + /* Ask ND6 what to do with the packet. */ + result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr); + if (result != ERR_OK) { + return result; + } + + /* If no hardware address is returned, nd6 has queued the packet for later. */ + if (hwaddr == NULL) { + return ERR_OK; + } + + /* Send out the packet using the returned hardware address. */ + SMEMCPY(dest.addr, hwaddr, 6); + return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); +} + +#endif /* LWIP_IPV6 && LWIP_ETHERNET */ diff --git a/components/net/lwip-2.0.3/src/core/ipv6/icmp6.c b/components/net/lwip-2.0.3/src/core/ipv6/icmp6.c new file mode 100644 index 0000000000..323b69a2ab --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv6/icmp6.c @@ -0,0 +1,350 @@ +/** + * @file + * + * IPv6 version of ICMP, as per RFC 4443. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp6.h" +#include "lwip/prot/icmp6.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/ip.h" +#include "lwip/stats.h" + +#include + +#ifndef LWIP_ICMP6_DATASIZE +#define LWIP_ICMP6_DATASIZE 8 +#endif +#if LWIP_ICMP6_DATASIZE == 0 +#define LWIP_ICMP6_DATASIZE 8 +#endif + +/* Forward declarations */ +static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type); + + +/** + * Process an input ICMPv6 message. Called by ip6_input. + * + * Will generate a reply for echo requests. Other messages are forwarded + * to nd6_input, or mld6_input. + * + * @param p the mld packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +icmp6_input(struct pbuf *p, struct netif *inp) +{ + struct icmp6_hdr *icmp6hdr; + struct pbuf *r; + const ip6_addr_t *reply_src; + + ICMP6_STATS_INC(icmp6.recv); + + /* Check that ICMPv6 header fits in payload */ + if (p->len < sizeof(struct icmp6_hdr)) { + /* drop short packets */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.lenerr); + ICMP6_STATS_INC(icmp6.drop); + return; + } + + icmp6hdr = (struct icmp6_hdr *)p->payload; + +#if CHECKSUM_CHECK_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) { + if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(), + ip6_current_dest_addr()) != 0) { + /* Checksum failed */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.chkerr); + ICMP6_STATS_INC(icmp6.drop); + return; + } + } +#endif /* CHECKSUM_CHECK_ICMP6 */ + + switch (icmp6hdr->type) { + case ICMP6_TYPE_NA: /* Neighbor advertisement */ + case ICMP6_TYPE_NS: /* Neighbor solicitation */ + case ICMP6_TYPE_RA: /* Router advertisement */ + case ICMP6_TYPE_RD: /* Redirect */ + case ICMP6_TYPE_PTB: /* Packet too big */ + nd6_input(p, inp); + return; + break; + case ICMP6_TYPE_RS: +#if LWIP_IPV6_FORWARD + /* @todo implement router functionality */ +#endif + break; +#if LWIP_IPV6_MLD + case ICMP6_TYPE_MLQ: + case ICMP6_TYPE_MLR: + case ICMP6_TYPE_MLD: + mld6_input(p, inp); + return; + break; +#endif + case ICMP6_TYPE_EREQ: +#if !LWIP_MULTICAST_PING + /* multicast destination address? */ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* drop */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.drop); + return; + } +#endif /* LWIP_MULTICAST_PING */ + + /* Allocate reply. */ + r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM); + if (r == NULL) { + /* drop */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.memerr); + return; + } + + /* Copy echo request. */ + if (pbuf_copy(r, p) != ERR_OK) { + /* drop */ + pbuf_free(p); + pbuf_free(r); + ICMP6_STATS_INC(icmp6.err); + return; + } + + /* Determine reply source IPv6 address. */ +#if LWIP_MULTICAST_PING + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + reply_src = ip_2_ip6(ip6_select_source_address(inp, ip6_current_src_addr())); + if (reply_src == NULL) { + /* drop */ + pbuf_free(p); + pbuf_free(r); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + else +#endif /* LWIP_MULTICAST_PING */ + { + reply_src = ip6_current_dest_addr(); + } + + /* Set fields in reply. */ + ((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP; + ((struct icmp6_echo_hdr *)(r->payload))->chksum = 0; +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP6) { + ((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r, + IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr()); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send reply. */ + ICMP6_STATS_INC(icmp6.xmit); + ip6_output_if(r, reply_src, ip6_current_src_addr(), + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp); + pbuf_free(r); + + break; + default: + ICMP6_STATS_INC(icmp6.proterr); + ICMP6_STATS_INC(icmp6.drop); + break; + } + + pbuf_free(p); +} + + +/** + * Send an icmpv6 'destination unreachable' packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IPv6 header + * @param c ICMPv6 code for the unreachable type + */ +void +icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c) +{ + icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR); +} + +/** + * Send an icmpv6 'packet too big' packet. + * + * @param p the input packet for which the 'packet too big' should be sent, + * p->payload pointing to the IPv6 header + * @param mtu the maximum mtu that we can accept + */ +void +icmp6_packet_too_big(struct pbuf *p, u32_t mtu) +{ + icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB); +} + +/** + * Send an icmpv6 'time exceeded' packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IPv6 header + * @param c ICMPv6 code for the time exceeded type + */ +void +icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c) +{ + icmp6_send_response(p, c, 0, ICMP6_TYPE_TE); +} + +/** + * Send an icmpv6 'parameter problem' packet. + * + * @param p the input packet for which the 'param problem' should be sent, + * p->payload pointing to the IP header + * @param c ICMPv6 code for the param problem type + * @param pointer the pointer to the byte where the parameter is found + */ +void +icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer) +{ + icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP); +} + +/** + * Send an ICMPv6 packet in response to an incoming packet. + * + * @param p the input packet for which the response should be sent, + * p->payload pointing to the IPv6 header + * @param code Code of the ICMPv6 header + * @param data Additional 32-bit parameter in the ICMPv6 header + * @param type Type of the ICMPv6 header + */ +static void +icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type) +{ + struct pbuf *q; + struct icmp6_hdr *icmp6hdr; + const ip6_addr_t *reply_src; + ip6_addr_t *reply_dest; + ip6_addr_t reply_src_local, reply_dest_local; + struct ip6_hdr *ip6hdr; + struct netif *netif; + + /* ICMPv6 header + IPv6 header + data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); + ICMP6_STATS_INC(icmp6.memerr); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp 6message", + (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); + + icmp6hdr = (struct icmp6_hdr *)q->payload; + icmp6hdr->type = type; + icmp6hdr->code = code; + icmp6hdr->data = data; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, + IP6_HLEN + LWIP_ICMP6_DATASIZE); + + /* Get the destination address and netif for this ICMP message. */ + if ((ip_current_netif() == NULL) || + ((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) { + /* Special case, as ip6_current_xxx is either NULL, or points + * to a different packet than the one that expired. + * We must use the addresses that are stored in the expired packet. */ + ip6hdr = (struct ip6_hdr *)p->payload; + /* copy from packed address to aligned address */ + ip6_addr_copy(reply_dest_local, ip6hdr->src); + ip6_addr_copy(reply_src_local, ip6hdr->dest); + reply_dest = &reply_dest_local; + reply_src = &reply_src_local; + netif = ip6_route(reply_src, reply_dest); + if (netif == NULL) { + /* drop */ + pbuf_free(q); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + else { + netif = ip_current_netif(); + reply_dest = ip6_current_src_addr(); + + /* Select an address to use as source. */ + reply_src = ip_2_ip6(ip6_select_source_address(netif, reply_dest)); + if (reply_src == NULL) { + /* drop */ + pbuf_free(q); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + + /* calculate checksum */ + icmp6hdr->chksum = 0; +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len, + reply_src, reply_dest); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + ICMP6_STATS_INC(icmp6.xmit); + ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(q); +} + +#endif /* LWIP_ICMP6 && LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.3/src/core/ipv6/inet6.c b/components/net/lwip-2.0.3/src/core/ipv6/inet6.c new file mode 100644 index 0000000000..d9a992c22a --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv6/inet6.c @@ -0,0 +1,53 @@ +/** + * @file + * + * INET v6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/inet.h" + +/** This variable is initialized by the system to contain the wildcard IPv6 address. + */ +const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; + +#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.3/src/core/ipv6/ip6.c b/components/net/lwip-2.0.3/src/core/ipv6/ip6.c new file mode 100644 index 0000000000..f14e33424f --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv6/ip6.c @@ -0,0 +1,1122 @@ +/** + * @file + * + * IPv6 layer. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/ip.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/ip6_frag.h" +#include "lwip/icmp6.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/dhcp6.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/debug.h" +#include "lwip/stats.h" + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +/** + * Finds the appropriate network interface for a given IPv6 address. It tries to select + * a netif following a sequence of heuristics: + * 1) if there is only 1 netif, return it + * 2) if the destination is a link-local address, try to match the src address to a netif. + * this is a tricky case because with multiple netifs, link-local addresses only have + * meaning within a particular subnet/link. + * 3) tries to match the destination subnet to a configured address + * 4) tries to find a router + * 5) tries to match the source address to the netif + * 6) returns the default netif, if configured + * + * @param src the source IPv6 address, if known + * @param dest the destination IPv6 address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) +{ + struct netif *netif; + s8_t i; + + /* If single netif configuration, fast return. */ + if ((netif_list != NULL) && (netif_list->next == NULL)) { + if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list)) { + return NULL; + } + return netif_list; + } + + /* Special processing for link-local addresses. */ + if (ip6_addr_islinklocal(dest)) { + if (ip6_addr_isany(src)) { + /* Use default netif, if Up. */ + if (netif_default == NULL || !netif_is_up(netif_default) || + !netif_is_link_up(netif_default)) { + return NULL; + } + return netif_default; + } + + /* Try to find the netif for the source address, checking that link is up. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (!netif_is_up(netif) || !netif_is_link_up(netif)) { + continue; + } + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + + /* netif not found, use default netif, if up */ + if (netif_default == NULL || !netif_is_up(netif_default) || + !netif_is_link_up(netif_default)) { + return NULL; + } + return netif_default; + } + + /* we come here for non-link-local addresses */ +#ifdef LWIP_HOOK_IP6_ROUTE + netif = LWIP_HOOK_IP6_ROUTE(src, dest); + if (netif != NULL) { + return netif; + } +#endif + + /* See if the destination subnet matches a configured address. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (!netif_is_up(netif) || !netif_is_link_up(netif)) { + continue; + } + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + + /* Get the netif for a suitable router. */ + netif = nd6_find_route(dest); + if ((netif != NULL) && netif_is_up(netif) && netif_is_link_up(netif)) { + return netif; + } + + /* try with the netif that matches the source address. */ + if (!ip6_addr_isany(src)) { + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (!netif_is_up(netif) || !netif_is_link_up(netif)) { + continue; + } + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + } + +#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF + /* loopif is disabled, loopback traffic is passed through any netif */ + if (ip6_addr_isloopback(dest)) { + /* don't check for link on loopback traffic */ + if (netif_default != NULL && netif_is_up(netif_default)) { + return netif_default; + } + /* default netif is not up, just use any netif for loopback traffic */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (netif_is_up(netif)) { + return netif; + } + } + return NULL; + } +#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ + + /* no matching netif found, use default netif, if up */ + if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { + return NULL; + } + return netif_default; +} + +/** + * @ingroup ip6 + * Select the best IPv6 source address for a given destination + * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior + * is assumed. + * + * @param netif the netif on which to send a packet + * @param dest the destination we are trying to reach + * @return the most suitable source address to use, or NULL if no suitable + * source address is found + */ +const ip_addr_t * +ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest) +{ + const ip_addr_t *src = NULL; + u8_t i; + + /* If dest is link-local, choose a link-local source. */ + if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + } + + /* Choose a site-local with matching prefix. */ + if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_issitelocal(netif_ip6_addr(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + } + + /* Choose a unique-local with matching prefix. */ + if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + } + + /* Choose a global with best matching prefix. */ + if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_isglobal(netif_ip6_addr(netif, i))) { + if (src == NULL) { + src = netif_ip_addr6(netif, i); + } + else { + /* Replace src only if we find a prefix match. */ + /* @todo find longest matching prefix. */ + if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) && + ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) { + src = netif_ip_addr6(netif, i); + } + } + } + } + if (src != NULL) { + return src; + } + } + + /* Last resort: see if arbitrary prefix matches. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + + return NULL; +} + +#if LWIP_IPV6_FORWARD +/** + * Forwards an IPv6 packet. It finds an appropriate route for the + * packet, decrements the HL value of the packet, and outputs + * the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IPv6 header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + /* do not forward link-local or loopback addresses */ + if (ip6_addr_islinklocal(ip6_current_dest_addr()) || + ip6_addr_isloopback(ip6_current_dest_addr())) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr()); + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(ip6_current_dest_addr()), + IP6_ADDR_BLOCK2(ip6_current_dest_addr()), + IP6_ADDR_BLOCK3(ip6_current_dest_addr()), + IP6_ADDR_BLOCK4(ip6_current_dest_addr()), + IP6_ADDR_BLOCK5(ip6_current_dest_addr()), + IP6_ADDR_BLOCK6(ip6_current_dest_addr()), + IP6_ADDR_BLOCK7(ip6_current_dest_addr()), + IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n")); + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + + /* decrement HL */ + IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1); + /* send ICMP6 if HL == 0 */ + if (IP6H_HOPLIM(iphdr) == 0) { +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_time_exceeded(p, ICMP6_TE_HL); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.drop); + return; + } + + if (netif->mtu && (p->tot_len > netif->mtu)) { +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_packet_too_big(p, netif->mtu); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.drop); + return; + } + + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(ip6_current_dest_addr()), + IP6_ADDR_BLOCK2(ip6_current_dest_addr()), + IP6_ADDR_BLOCK3(ip6_current_dest_addr()), + IP6_ADDR_BLOCK4(ip6_current_dest_addr()), + IP6_ADDR_BLOCK5(ip6_current_dest_addr()), + IP6_ADDR_BLOCK6(ip6_current_dest_addr()), + IP6_ADDR_BLOCK7(ip6_current_dest_addr()), + IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); + + /* transmit pbuf on chosen interface */ + netif->output_ip6(netif, p, ip6_current_dest_addr()); + IP6_STATS_INC(ip6.fw); + IP6_STATS_INC(ip6.xmit); + return; +} +#endif /* LWIP_IPV6_FORWARD */ + +/** + * This function is called by the network interface device driver when + * an IPv6 packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip6_forward). + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IPv6 packet (p->payload points to IPv6 header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip6_input(struct pbuf *p, struct netif *inp) +{ + struct ip6_hdr *ip6hdr; + struct netif *netif; + u8_t nexth; + u16_t hlen; /* the current header length */ + u8_t i; +#if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/ + @todo + int check_ip_src=1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + IP6_STATS_INC(ip6.recv); + + /* identify the IP header */ + ip6hdr = (struct ip6_hdr *)p->payload; + if (IP6H_V(ip6hdr) != 6) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n", + IP6H_V(ip6hdr))); + pbuf_free(p); + IP6_STATS_INC(ip6.err); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + +#ifdef LWIP_HOOK_IP6_INPUT + if (LWIP_HOOK_IP6_INPUT(p, inp)) { + /* the packet has been eaten */ + return ERR_OK; + } +#endif + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) { + if (IP6_HLEN > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + (u16_t)IP6_HLEN, p->len)); + } + if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + + /* Trim pbuf. This should have been done at the netif layer, + * but we'll do it anyway just to be sure that its done. */ + pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr)); + + /* copy IP addresses to aligned ip6_addr_t */ + ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); + ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); + + /* Don't accept virtual IPv4 mapped IPv6 addresses. + * Don't accept multicast source addresses. */ + if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) || + ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) || + ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) { + IP6_STATS_INC(ip6.err); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + + /* current header pointer. */ + ip_data.current_ip6_header = ip6hdr; + + /* In netif, used in case we need to send ICMPv6 packets back. */ + ip_data.current_netif = inp; + ip_data.current_input_netif = inp; + + /* match packet against an interface, i.e. is this packet for us? */ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* Always joined to multicast if-local and link-local all-nodes group. */ + if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) || + ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) { + netif = inp; + } +#if LWIP_IPV6_MLD + else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) { + netif = inp; + } +#else /* LWIP_IPV6_MLD */ + else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) { + /* Filter solicited node packets when MLD is not enabled + * (for Neighbor discovery). */ + netif = NULL; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) && + ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { + netif = inp; + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + break; + } + } + } +#endif /* LWIP_IPV6_MLD */ + else { + netif = NULL; + } + } else { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + /* interface is up? */ + if (netif_is_up(netif)) { + /* unicast to this interface address? address configured? */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) { + /* exit outer loop */ + goto netif_found; + } + } + } + if (first) { + if (ip6_addr_islinklocal(ip6_current_dest_addr()) +#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF + || ip6_addr_isloopback(ip6_current_dest_addr()) +#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ + ) { + /* Do not match link-local addresses to other netifs. The loopback + * address is to be considered link-local and packets to it should be + * dropped on other interfaces, as per RFC 4291 Sec. 2.5.3. This + * requirement cannot be implemented in the case that loopback + * traffic is sent across a non-loopback interface, however. + */ + netif = NULL; + break; + } + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while (netif != NULL); +netif_found: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", + netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); + } + + /* "::" packet source address? (used in duplicate address detection) */ + if (ip6_addr_isany(ip6_current_src_addr()) && + (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) { + /* packet source is not valid */ + /* free (drop) packet pbufs */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n")); + pbuf_free(p); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); +#if LWIP_IPV6_FORWARD + /* non-multicast packet? */ + if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* try to forward IP packet on (other) interfaces */ + ip6_forward(p, ip6hdr, inp); + } +#endif /* LWIP_IPV6_FORWARD */ + pbuf_free(p); + goto ip6_input_cleanup; + } + + /* current netif pointer. */ + ip_data.current_netif = netif; + + /* Save next header type. */ + nexth = IP6H_NEXTH(ip6hdr); + + /* Init header length. */ + hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; + + /* Move to payload. */ + pbuf_header(p, -IP6_HLEN); + + /* Process known option extension headers, if present. */ + while (nexth != IP6_NEXTH_NONE) + { + switch (nexth) { + case IP6_NEXTH_HOPBYHOP: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -(s16_t)hlen); + break; + case IP6_NEXTH_DESTOPTS: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -(s16_t)hlen); + break; + case IP6_NEXTH_ROUTING: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -(s16_t)hlen); + break; + + case IP6_NEXTH_FRAGMENT: + { + struct ip6_frag_hdr *frag_hdr; + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); + + frag_hdr = (struct ip6_frag_hdr *)p->payload; + + /* Get next header type. */ + nexth = frag_hdr->_nexth; + + /* Fragment Header length. */ + hlen = 8; + ip_data.current_ip_header_tot_len += hlen; + + /* Make sure this header fits in current pbuf. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_FRAG_STATS_INC(ip6_frag.lenerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto ip6_input_cleanup; + } + + /* Offset == 0 and more_fragments == 0? */ + if ((frag_hdr->_fragment_offset & + PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) { + /* This is a 1-fragment packet, usually a packet that we have + * already reassembled. Skip this header anc continue. */ + pbuf_header(p, -(s16_t)hlen); + } else { +#if LWIP_IPV6_REASS + + /* reassemble the packet */ + p = ip6_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + goto ip6_input_cleanup; + } + + /* Returned p point to IPv6 header. + * Update all our variables and pointers and continue. */ + ip6hdr = (struct ip6_hdr *)p->payload; + nexth = IP6H_NEXTH(ip6hdr); + hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; + pbuf_header(p, -IP6_HLEN); + +#else /* LWIP_IPV6_REASS */ + /* free (drop) packet pbufs */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n")); + pbuf_free(p); + IP6_STATS_INC(ip6.opterr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; +#endif /* LWIP_IPV6_REASS */ + } + break; + } + default: + goto options_done; + break; + } + } +options_done: + + /* p points to IPv6 header again. */ + pbuf_header_force(p, (s16_t)ip_data.current_ip_header_tot_len); + + /* send to upper layers */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); + ip6_debug_print(p); + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + switch (nexth) { + case IP6_NEXTH_NONE: + pbuf_free(p); + break; +#if LWIP_UDP + case IP6_NEXTH_UDP: +#if LWIP_UDPLITE + case IP6_NEXTH_UDPLITE: +#endif /* LWIP_UDPLITE */ + /* Point to payload. */ + pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP6_NEXTH_TCP: + /* Point to payload. */ + pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP6 + case IP6_NEXTH_ICMP6: + /* Point to payload. */ + pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); + icmp6_input(p, inp); + break; +#endif /* LWIP_ICMP */ + default: +#if LWIP_ICMP6 + /* send ICMP parameter problem unless it was a multicast or ICMPv6 */ + if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) && + (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) { + icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen); + } +#endif /* LWIP_ICMP */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr))); + pbuf_free(p); + IP6_STATS_INC(ip6.proterr); + IP6_STATS_INC(ip6.drop); + break; + } + } + +ip6_input_cleanup: + ip_data.current_netif = NULL; + ip_data.current_input_netif = NULL; + ip_data.current_ip6_header = NULL; + ip_data.current_ip_header_tot_len = 0; + ip6_addr_set_zero(ip6_current_src_addr()); + ip6_addr_set_zero(ip6_current_dest_addr()); + + return ERR_OK; +} + + +/** + * Sends an IPv6 packet on a network interface. This function constructs + * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is + * used as source (usually during network startup). If the source IPv6 address it + * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network + * interface is filled in as source address. If the destination IPv6 address is + * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and + * p->payload points to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IPv6/LINK headers + * returns errors returned by netif->output + */ +err_t +ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, + u8_t nexth, struct netif *netif) +{ + const ip6_addr_t *src_used = src; + if (dest != LWIP_IP_HDRINCL) { + if (src != NULL && ip6_addr_isany(src)) { + src_used = ip_2_ip6(ip6_select_source_address(netif, dest)); + if ((src_used == NULL) || ip6_addr_isany(src_used)) { + /* No appropriate source address was found for this packet. */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + } + } + return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif); +} + +/** + * Same as ip6_output_if() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, + u8_t nexth, struct netif *netif) +{ + struct ip6_hdr *ip6hdr; + ip6_addr_t dest_addr; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + /* Should the IPv6 header be generated or is it already included in p? */ + if (dest != LWIP_IP_HDRINCL) { + /* generate IPv6 header */ + if (pbuf_header(p, IP6_HLEN)) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); + IP6_STATS_INC(ip6.err); + return ERR_BUF; + } + + ip6hdr = (struct ip6_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr", + (p->len >= sizeof(struct ip6_hdr))); + + IP6H_HOPLIM_SET(ip6hdr, hl); + IP6H_NEXTH_SET(ip6hdr, nexth); + + /* dest cannot be NULL here */ + ip6_addr_copy(ip6hdr->dest, *dest); + + IP6H_VTCFL_SET(ip6hdr, 6, tc, 0); + IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN); + + if (src == NULL) { + src = IP6_ADDR_ANY6; + } + /* src cannot be NULL here */ + ip6_addr_copy(ip6hdr->src, *src); + + } else { + /* IP header already included in p */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(dest_addr, ip6hdr->dest); + dest = &dest_addr; + } + + IP6_STATS_INC(ip6.xmit); + + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); + ip6_debug_print(p); + +#if ENABLE_LOOPBACK + { + int i; +#if !LWIP_HAVE_LOOPIF + if (ip6_addr_isloopback(dest)) { + return netif_loop_output(netif, p); + } +#endif /* !LWIP_HAVE_LOOPIF */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n")); + return netif_loop_output(netif, p); + } + } + } +#endif /* ENABLE_LOOPBACK */ +#if LWIP_IPV6_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { + return ip6_frag(p, netif, dest); + } +#endif /* LWIP_IPV6_FRAG */ + + LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n")); + return netif->output_ip6(netif, p, dest); +} + +/** + * Simple interface to ip6_output_if. It finds the outgoing network + * interface and calls upon ip6_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth) +{ + struct netif *netif; + struct ip6_hdr *ip6hdr; + ip6_addr_t src_addr, dest_addr; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if (dest != LWIP_IP_HDRINCL) { + netif = ip6_route(src, dest); + } else { + /* IP header included in p, read addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(src_addr, ip6hdr->src); + ip6_addr_copy(dest_addr, ip6hdr->dest); + netif = ip6_route(&src_addr, &dest_addr); + } + + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(dest), + IP6_ADDR_BLOCK2(dest), + IP6_ADDR_BLOCK3(dest), + IP6_ADDR_BLOCK4(dest), + IP6_ADDR_BLOCK5(dest), + IP6_ADDR_BLOCK6(dest), + IP6_ADDR_BLOCK7(dest), + IP6_ADDR_BLOCK8(dest))); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + + return ip6_output_if(p, src, dest, hl, tc, nexth, netif); +} + + +#if LWIP_NETIF_HWADDRHINT +/** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip6_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint) +{ + struct netif *netif; + struct ip6_hdr *ip6hdr; + ip6_addr_t src_addr, dest_addr; + err_t err; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if (dest != LWIP_IP_HDRINCL) { + netif = ip6_route(src, dest); + } else { + /* IP header included in p, read addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(src_addr, ip6hdr->src); + ip6_addr_copy(dest_addr, ip6hdr->dest); + netif = ip6_route(&src_addr, &dest_addr); + } + + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(dest), + IP6_ADDR_BLOCK2(dest), + IP6_ADDR_BLOCK3(dest), + IP6_ADDR_BLOCK4(dest), + IP6_ADDR_BLOCK5(dest), + IP6_ADDR_BLOCK6(dest), + IP6_ADDR_BLOCK7(dest), + IP6_ADDR_BLOCK8(dest))); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip6_output_if(p, src, dest, hl, tc, nexth, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if LWIP_IPV6_MLD +/** + * Add a hop-by-hop options header with a router alert option and padding. + * + * Used by MLD when sending a Multicast listener report/done message. + * + * @param p the packet to which we will prepend the options header + * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6) + * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD) + * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise + */ +err_t +ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value) +{ + struct ip6_hbh_hdr *hbh_hdr; + + /* Move pointer to make room for hop-by-hop options header. */ + if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n")); + IP6_STATS_INC(ip6.err); + return ERR_BUF; + } + + hbh_hdr = (struct ip6_hbh_hdr *)p->payload; + + /* Set fields. */ + hbh_hdr->_nexth = nexth; + hbh_hdr->_hlen = 0; + hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION; + hbh_hdr->_ra_opt_dlen = 2; + hbh_hdr->_ra_opt_data = value; + hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION; + hbh_hdr->_padn_opt_dlen = 0; + + return ERR_OK; +} +#endif /* LWIP_IPV6_MLD */ + +#if IP6_DEBUG +/* Print an IPv6 header by using LWIP_DEBUGF + * @param p an IPv6 packet, p->payload pointing to the IPv6 header + */ +void +ip6_debug_print(struct pbuf *p) +{ + struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; + + LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n")); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n", + IP6H_V(ip6hdr), + IP6H_TC(ip6hdr), + IP6H_FL(ip6hdr))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n", + IP6H_PLEN(ip6hdr), + IP6H_NEXTH(ip6hdr), + IP6H_HOPLIM(ip6hdr))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n", + IP6_ADDR_BLOCK1(&(ip6hdr->src)), + IP6_ADDR_BLOCK2(&(ip6hdr->src)), + IP6_ADDR_BLOCK3(&(ip6hdr->src)), + IP6_ADDR_BLOCK4(&(ip6hdr->src)))); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", + IP6_ADDR_BLOCK5(&(ip6hdr->src)), + IP6_ADDR_BLOCK6(&(ip6hdr->src)), + IP6_ADDR_BLOCK7(&(ip6hdr->src)), + IP6_ADDR_BLOCK8(&(ip6hdr->src)))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n", + IP6_ADDR_BLOCK1(&(ip6hdr->dest)), + IP6_ADDR_BLOCK2(&(ip6hdr->dest)), + IP6_ADDR_BLOCK3(&(ip6hdr->dest)), + IP6_ADDR_BLOCK4(&(ip6hdr->dest)))); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", + IP6_ADDR_BLOCK5(&(ip6hdr->dest)), + IP6_ADDR_BLOCK6(&(ip6hdr->dest)), + IP6_ADDR_BLOCK7(&(ip6hdr->dest)), + IP6_ADDR_BLOCK8(&(ip6hdr->dest)))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP6_DEBUG */ + +#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.3/src/core/ipv6/ip6_addr.c b/components/net/lwip-2.0.3/src/core/ipv6/ip6_addr.c new file mode 100644 index 0000000000..aa06659a02 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv6/ip6_addr.c @@ -0,0 +1,292 @@ +/** + * @file + * + * IPv6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * Functions for handling IPv6 addresses. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip_addr.h" +#include "lwip/def.h" + +/* used by IP6_ADDR_ANY(6) in ip6_addr.h */ +const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul); + +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) +#endif + +/** + * Check whether "cp" is a valid ascii representation + * of an IPv6 address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * + * @param cp IPv6 address in ascii representation (e.g. "FF01::1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ip6addr_aton(const char *cp, ip6_addr_t *addr) +{ + u32_t addr_index, zero_blocks, current_block_index, current_block_value; + const char *s; + + /* Count the number of colons, to count the number of blocks in a "::" sequence + zero_blocks may be 1 even if there are no :: sequences */ + zero_blocks = 8; + for (s = cp; *s != 0; s++) { + if (*s == ':') { + zero_blocks--; + } else if (!isxdigit(*s)) { + break; + } + } + + /* parse each block */ + addr_index = 0; + current_block_index = 0; + current_block_value = 0; + for (s = cp; *s != 0; s++) { + if (*s == ':') { + if (addr) { + if (current_block_index & 0x1) { + addr->addr[addr_index++] |= current_block_value; + } + else { + addr->addr[addr_index] = current_block_value << 16; + } + } + current_block_index++; + current_block_value = 0; + if (current_block_index > 7) { + /* address too long! */ + return 0; + } + if (s[1] == ':') { + if (s[2] == ':') { + /* invalid format: three successive colons */ + return 0; + } + s++; + /* "::" found, set zeros */ + while (zero_blocks > 0) { + zero_blocks--; + if (current_block_index & 0x1) { + addr_index++; + } else { + if (addr) { + addr->addr[addr_index] = 0; + } + } + current_block_index++; + if (current_block_index > 7) { + /* address too long! */ + return 0; + } + } + } + } else if (isxdigit(*s)) { + /* add current digit */ + current_block_value = (current_block_value << 4) + + (isdigit(*s) ? (u32_t)(*s - '0') : + (u32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A'))); + } else { + /* unexpected digit, space? CRLF? */ + break; + } + } + + if (addr) { + if (current_block_index & 0x1) { + addr->addr[addr_index++] |= current_block_value; + } + else { + addr->addr[addr_index] = current_block_value << 16; + } + } + + /* convert to network byte order. */ + if (addr) { + for (addr_index = 0; addr_index < 4; addr_index++) { + addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]); + } + } + + if (current_block_index != 7) { + return 0; + } + + return 1; +} + +/** + * Convert numeric IPv6 address into ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip6 address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * representation of addr + */ +char * +ip6addr_ntoa(const ip6_addr_t *addr) +{ + static char str[40]; + return ip6addr_ntoa_r(addr, str, 40); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip6 address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char * +ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) +{ + u32_t current_block_index, current_block_value, next_block_value; + s32_t i; + u8_t zero_flag, empty_block_flag; + + i = 0; + empty_block_flag = 0; /* used to indicate a zero chain for "::' */ + + for (current_block_index = 0; current_block_index < 8; current_block_index++) { + /* get the current 16-bit block */ + current_block_value = lwip_htonl(addr->addr[current_block_index >> 1]); + if ((current_block_index & 0x1) == 0) { + current_block_value = current_block_value >> 16; + } + current_block_value &= 0xffff; + + /* Check for empty block. */ + if (current_block_value == 0) { + if (current_block_index == 7 && empty_block_flag == 1) { + /* special case, we must render a ':' for the last block. */ + buf[i++] = ':'; + if (i >= buflen) { + return NULL; + } + break; + } + if (empty_block_flag == 0) { + /* generate empty block "::", but only if more than one contiguous zero block, + * according to current formatting suggestions RFC 5952. */ + next_block_value = lwip_htonl(addr->addr[(current_block_index + 1) >> 1]); + if ((current_block_index & 0x1) == 0x01) { + next_block_value = next_block_value >> 16; + } + next_block_value &= 0xffff; + if (next_block_value == 0) { + empty_block_flag = 1; + buf[i++] = ':'; + if (i >= buflen) { + return NULL; + } + continue; /* move on to next block. */ + } + } else if (empty_block_flag == 1) { + /* move on to next block. */ + continue; + } + } else if (empty_block_flag == 1) { + /* Set this flag value so we don't produce multiple empty blocks. */ + empty_block_flag = 2; + } + + if (current_block_index > 0) { + buf[i++] = ':'; + if (i >= buflen) { + return NULL; + } + } + + if ((current_block_value & 0xf000) == 0) { + zero_flag = 1; + } else { + buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); + zero_flag = 0; + if (i >= buflen) { + return NULL; + } + } + + if (((current_block_value & 0xf00) == 0) && (zero_flag)) { + /* do nothing */ + } else { + buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); + zero_flag = 0; + if (i >= buflen) { + return NULL; + } + } + + if (((current_block_value & 0xf0) == 0) && (zero_flag)) { + /* do nothing */ + } + else { + buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); + zero_flag = 0; + if (i >= buflen) { + return NULL; + } + } + + buf[i++] = xchar((current_block_value & 0xf)); + if (i >= buflen) { + return NULL; + } + } + + buf[i] = 0; + + return buf; +} + +#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.3/src/core/ipv6/ip6_frag.c b/components/net/lwip-2.0.3/src/core/ipv6/ip6_frag.c new file mode 100644 index 0000000000..ff07f71cd2 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv6/ip6_frag.c @@ -0,0 +1,805 @@ +/** + * @file + * + * IPv6 fragmentation and reassembly. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" +#include "lwip/ip6_frag.h" +#include "lwip/ip6.h" +#include "lwip/icmp6.h" +#include "lwip/nd6.h" +#include "lwip/ip.h" + +#include "lwip/pbuf.h" +#include "lwip/memp.h" +#include "lwip/stats.h" + +#include + +#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ + + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#if IPV6_FRAG_COPYHEADER +#define IPV6_FRAG_REQROOM ((s16_t)(sizeof(struct ip6_reass_helper) - IP6_FRAG_HLEN)) +#endif + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IPv6 header, since it replaces + * the Fragment Header in memory in incoming fragments to keep + * track of the various fragments. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* static variables */ +static struct ip6_reassdata *reassdatagrams; +static u16_t ip6_reass_pbufcount; + +/* Forward declarations. */ +static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr); +#if IP_REASS_FREE_OLDEST +static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed); +#endif /* IP_REASS_FREE_OLDEST */ + +void +ip6_reass_tmr(void) +{ + struct ip6_reassdata *r, *tmp; + +#if !IPV6_FRAG_COPYHEADER + LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1", + sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN); +#endif /* !IPV6_FRAG_COPYHEADER */ + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + r = r->next; + } else { + /* reassembly timed out */ + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip6_reass_free_complete_datagram(tmp); + } + } +} + +/** + * Free a datagram (struct ip6_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip6_reass_pbufcount), + * sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + */ +static void +ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) +{ + struct ip6_reassdata *prev; + u16_t pbufs_freed = 0; + u16_t clen; + struct pbuf *p; + struct ip6_reass_helper *iprh; + +#if LWIP_ICMP6 + iprh = (struct ip6_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, move back to the original ipv6 header (we are now pointing to Fragment header). + This cannot fail since we already checked when receiving this fragment. */ + if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)IPV6_FRAG_HDRREF(ipr->iphdr)))) { + LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0); + } + else { + icmp6_time_exceeded(p, ICMP6_TE_FRAG); + } + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP6 */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip6_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + + /* Then, unchain the struct ip6_reassdata from the list and free it. */ + if (ipr == reassdatagrams) { + reassdatagrams = ipr->next; + } else { + prev = reassdatagrams; + while (prev != NULL) { + if (prev->next == ipr) { + break; + } + prev = prev->next; + } + if (prev != NULL) { + prev->next = ipr->next; + } + } + memp_free(MEMP_IP6_REASSDATA, ipr); + + /* Finally, update number of pbufs in reassembly queue */ + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed); + ip6_reass_pbufcount -= pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram ipr is not freed! + * + * @param ipr ip6_reassdata for the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + */ +static void +ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed) +{ + struct ip6_reassdata *r, *oldest; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the current datagram! */ + do { + r = oldest = reassdatagrams; + while (r != NULL) { + if (r != ipr) { + if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + } + } + r = r->next; + } + if (oldest == ipr) { + /* nothing to free, ipr is the only element on the list */ + return; + } + if (oldest != NULL) { + ip6_reass_free_complete_datagram(oldest); + } + } while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (reassdatagrams != NULL)); +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Reassembles incoming IPv6 fragments into an IPv6 datagram. + * + * @param p points to the IPv6 Fragment Header + * @return NULL if reassembly is incomplete, pbuf pointing to + * IPv6 Header if reassembly is complete + */ +struct pbuf * +ip6_reass(struct pbuf *p) +{ + struct ip6_reassdata *ipr, *ipr_prev; + struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct ip6_frag_hdr *frag_hdr; + u16_t offset, len; + u16_t clen; + u8_t valid = 1; + struct pbuf *q; + + IP6_FRAG_STATS_INC(ip6_frag.recv); + + if ((const void*)ip6_current_header() != ((u8_t*)p->payload) - IP6_HLEN) { + /* ip6_frag_hdr must be in the first pbuf, not chained */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + + frag_hdr = (struct ip6_frag_hdr *) p->payload; + + clen = pbuf_clen(p); + + offset = lwip_ntohs(frag_hdr->_fragment_offset); + + /* Calculate fragment length from IPv6 payload length. + * Adjust for headers before Fragment Header. + * And finally adjust by Fragment Header length. */ + len = lwip_ntohs(ip6_current_header()->_plen); + len -= (u16_t)(((u8_t*)p->payload - (const u8_t*)ip6_current_header()) - IP6_HLEN); + len -= IP6_FRAG_HLEN; + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if ((frag_hdr->_identification == ipr->identification) && + ip6_addr_cmp(ip6_current_src_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->src)) && + ip6_addr_cmp(ip6_current_dest_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->dest))) { + IP6_FRAG_STATS_INC(ip6_frag.cachehit); + break; + } + ipr_prev = ipr; + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + /* Make room and try again. */ + ip6_reass_remove_oldest_datagram(ipr, clen); + ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); + if (ipr != NULL) { + /* re-search ipr_prev since it might have been removed */ + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } else +#endif /* IP_REASS_FREE_OLDEST */ + { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } + + memset(ipr, 0, sizeof(struct ip6_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + + /* Use the current IPv6 header for src/dest address reference. + * Eventually, we will replace it when we get the first fragment + * (it might be this one, in any case, it is done later). */ +#if IPV6_FRAG_COPYHEADER + MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN); +#else /* IPV6_FRAG_COPYHEADER */ + /* need to use the none-const pointer here: */ + ipr->iphdr = ip_data.current_ip6_header; +#endif /* IPV6_FRAG_COPYHEADER */ + + /* copy the fragmented packet id. */ + ipr->identification = frag_hdr->_identification; + + /* copy the nexth field */ + ipr->nexth = frag_hdr->_nexth; + } + + /* Check if we are allowed to enqueue more datagrams. */ + if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + ip6_reass_remove_oldest_datagram(ipr, clen); + if ((ip6_reass_pbufcount + clen) <= IP_REASS_MAX_PBUFS) { + /* re-search ipr_prev since it might have been removed */ + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } else +#endif /* IP_REASS_FREE_OLDEST */ + { + /* @todo: send ICMPv6 time exceeded here? */ + /* drop this pbuf */ + IP6_FRAG_STATS_INC(ip6_frag.memerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } + + /* Overwrite Fragment Header with our own helper struct. */ +#if IPV6_FRAG_COPYHEADER + if (IPV6_FRAG_REQROOM > 0) { + /* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4). + This cannot fail since we already checked when receiving this fragment. */ + u8_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM); + LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); + } +#else /* IPV6_FRAG_COPYHEADER */ + LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1", + sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN); +#endif /* IPV6_FRAG_COPYHEADER */ + iprh = (struct ip6_reass_helper *)p->payload; + iprh->next_pbuf = NULL; + iprh->start = (offset & IP6_FRAG_OFFSET_MASK); + iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len; + + /* find the right place to insert this pbuf */ + /* Iterate through until we either get to the end of the list (append), + * or we find on with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip6_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { +#if IP_REASS_CHECK_OVERLAP + if (iprh->end > iprh_tmp->start) { + /* fragment overlaps with following, throw away */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + if (iprh_prev != NULL) { + if (iprh->start < iprh_prev->end) { + /* fragment overlaps with previous, throw away */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } +#endif /* IP_REASS_CHECK_OVERLAP */ + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ + iprh_prev->next_pbuf = p; + } else { + /* fragment with the lowest offset */ + ipr->p = p; + } + break; + } else if (iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; +#if IP_REASS_CHECK_OVERLAP + } else if (iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no gaps. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = p; + } + } + + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip6_reass_pbufcount += clen; + + /* Remember IPv6 header if this is the first fragment. */ + if (iprh->start == 0) { +#if IPV6_FRAG_COPYHEADER + if (iprh->next_pbuf != NULL) { + MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN); + } +#else /* IPV6_FRAG_COPYHEADER */ + /* need to use the none-const pointer here: */ + ipr->iphdr = ip_data.current_ip6_header; +#endif /* IPV6_FRAG_COPYHEADER */ + } + + /* If this is the last fragment, calculate total packet length. */ + if ((offset & IP6_FRAG_MORE_FLAG) == 0) { + ipr->datagram_len = iprh->end; + } + + /* Additional validity tests: we have received first and last fragment. */ + iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload; + if (iprh_tmp->start != 0) { + valid = 0; + } + if (ipr->datagram_len == 0) { + valid = 0; + } + + /* Final validity test: no gaps between current and last fragment. */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while ((q != NULL) && valid) { + iprh = (struct ip6_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + + if (valid) { + /* All fragments have been received */ + struct ip6_hdr* iphdr_ptr; + + /* chain together the pbufs contained within the ip6_reassdata list. */ + iprh = (struct ip6_reass_helper*) ipr->p->payload; + while (iprh != NULL) { + struct pbuf* next_pbuf = iprh->next_pbuf; + if (next_pbuf != NULL) { + /* Save next helper struct (will be hidden in next step). */ + iprh_tmp = (struct ip6_reass_helper*)next_pbuf->payload; + + /* hide the fragment header for every succeeding fragment */ + pbuf_header(next_pbuf, -IP6_FRAG_HLEN); +#if IPV6_FRAG_COPYHEADER + if (IPV6_FRAG_REQROOM > 0) { + /* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */ + u8_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM)); + LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); + } +#endif + pbuf_cat(ipr->p, next_pbuf); + } + else { + iprh_tmp = NULL; + } + + iprh = iprh_tmp; + } + +#if IPV6_FRAG_COPYHEADER + if (IPV6_FRAG_REQROOM > 0) { + /* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */ + u8_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM)); + LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); + } + iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN); + MEMCPY(iphdr_ptr, &ipr->iphdr, IP6_HLEN); +#else + iphdr_ptr = ipr->iphdr; +#endif + + /* Adjust datagram length by adding header lengths. */ + ipr->datagram_len += (u16_t)(((u8_t*)ipr->p->payload - (u8_t*)iphdr_ptr) + + IP6_FRAG_HLEN + - IP6_HLEN); + + /* Set payload length in ip header. */ + iphdr_ptr->_plen = lwip_htons(ipr->datagram_len); + + /* Get the first pbuf. */ + p = ipr->p; + + /* Restore Fragment Header in first pbuf. Mark as "single fragment" + * packet. Restore nexth. */ + frag_hdr = (struct ip6_frag_hdr *) p->payload; + frag_hdr->_nexth = ipr->nexth; + frag_hdr->reserved = 0; + frag_hdr->_fragment_offset = 0; + frag_hdr->_identification = 0; + + /* release the sources allocate for the fragment queue entry */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", ipr_prev != NULL); + ipr_prev->next = ipr->next; + } + memp_free(MEMP_IP6_REASSDATA, ipr); + + /* adjust the number of pbufs currently queued for reassembly. */ + ip6_reass_pbufcount -= pbuf_clen(p); + + /* Move pbuf back to IPv6 header. + This cannot fail since we already checked when receiving this fragment. */ + if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)iphdr_ptr))) { + LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0); + pbuf_free(p); + return NULL; + } + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + return NULL; + +nullreturn: + pbuf_free(p); + return NULL; +} + +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_FRAG + +#if !LWIP_NETIF_TX_SINGLE_PBUF +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip6_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip6_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ip6_frag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip6_frag_free_pbuf_custom_ref(pcr); +} +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ + +/** + * Fragment an IPv6 datagram if too large for the netif or path MTU. + * + * Chop the datagram in MTU sized chunks and send them in order + * by pointing PBUF_REFs into p + * + * @param p ipv6 packet to send + * @param netif the netif on which to send + * @param dest destination ipv6 address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) +{ + struct ip6_hdr *original_ip6hdr; + struct ip6_hdr *ip6hdr; + struct ip6_frag_hdr *frag_hdr; + struct pbuf *rambuf; +#if !LWIP_NETIF_TX_SINGLE_PBUF + struct pbuf *newpbuf; + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif + static u32_t identification; + u16_t nfb; + u16_t left, cop; + u16_t mtu; + u16_t fragment_offset = 0; + u16_t last; + u16_t poff = IP6_HLEN; + + identification++; + + original_ip6hdr = (struct ip6_hdr *)p->payload; + + mtu = nd6_get_destination_mtu(dest, netif); + + /* @todo we assume there are no options in the unfragmentable part (IPv6 header). */ + left = p->tot_len - IP6_HLEN; + + nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK; + + while (left) { + last = (left <= nfb); + + /* Fill this fragment */ + cop = last ? left : nfb; + +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, cop + IP6_FRAG_HLEN, PBUF_RAM); + if (rambuf == NULL) { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, (u8_t*)rambuf->payload + IP6_FRAG_HLEN, cop, poff); + /* make room for the IP header */ + if (pbuf_header(rambuf, IP6_HLEN)) { + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); + ip6hdr = (struct ip6_hdr *)rambuf->payload; + frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); +#else + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link, IPv6, and Fragment header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM); + if (rambuf == NULL) { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP6_HLEN))); + SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); + ip6hdr = (struct ip6_hdr *)rambuf->payload; + frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + p->tot_len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + pcr = ip6_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip6_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + p = p->next; + } + } + poff = newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + /* Set headers */ + frag_hdr->_nexth = original_ip6hdr->_nexth; + frag_hdr->reserved = 0; + frag_hdr->_fragment_offset = lwip_htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); + frag_hdr->_identification = lwip_htonl(identification); + + IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT); + IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN); + + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + IP6_FRAG_STATS_INC(ip6_frag.xmit); + netif->output_ip6(netif, rambuf, dest); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); + left -= cop; + fragment_offset += cop; + } + return ERR_OK; +} + +#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ diff --git a/components/net/lwip-2.0.3/src/core/ipv6/mld6.c b/components/net/lwip-2.0.3/src/core/ipv6/mld6.c new file mode 100644 index 0000000000..9acb82fe24 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv6/mld6.c @@ -0,0 +1,588 @@ +/** + * @file + * Multicast listener discovery + * + * @defgroup mld6 MLD6 + * @ingroup ip6 + * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. + * No support for MLDv2.\n + * To be called from TCPIP thread + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +/* Based on igmp.c implementation of igmp v2 protocol */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mld6.h" +#include "lwip/prot/mld6.h" +#include "lwip/icmp6.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/ip.h" +#include "lwip/inet_chksum.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/memp.h" +#include "lwip/stats.h" + +#include + + +/* + * MLD constants + */ +#define MLD6_HL 1 +#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500) + +#define MLD6_GROUP_NON_MEMBER 0 +#define MLD6_GROUP_DELAYING_MEMBER 1 +#define MLD6_GROUP_IDLE_MEMBER 2 + +/* Forward declarations. */ +static struct mld_group *mld6_new_group(struct netif *ifp, const ip6_addr_t *addr); +static err_t mld6_remove_group(struct netif *netif, struct mld_group *group); +static void mld6_delayed_report(struct mld_group *group, u16_t maxresp); +static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type); + + +/** + * Stop MLD processing on interface + * + * @param netif network interface on which stop MLD processing + */ +err_t +mld6_stop(struct netif *netif) +{ + struct mld_group *group = netif_mld6_data(netif); + + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, NULL); + + while (group != NULL) { + struct mld_group *next = group->next; /* avoid use-after-free below */ + + /* disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER); + } + + /* free group */ + memp_free(MEMP_MLD6_GROUP, group); + + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report MLD memberships for this interface + * + * @param netif network interface on which report MLD memberships + */ +void +mld6_report_groups(struct netif *netif) +{ + struct mld_group *group = netif_mld6_data(netif); + + while (group != NULL) { + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + group = group->next; + } +} + +/** + * Search for a group that is joined on a netif + * + * @param ifp the network interface for which to look + * @param addr the group ipv6 address to search for + * @return a struct mld_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct mld_group * +mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr) +{ + struct mld_group *group = netif_mld6_data(ifp); + + while (group != NULL) { + if (ip6_addr_cmp(&(group->group_address), addr)) { + return group; + } + group = group->next; + } + + return NULL; +} + + +/** + * create a new group + * + * @param ifp the network interface for which to create + * @param addr the new group ipv6 + * @return a struct mld_group*, + * NULL on memory error. + */ +static struct mld_group * +mld6_new_group(struct netif *ifp, const ip6_addr_t *addr) +{ + struct mld_group *group; + + group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP); + if (group != NULL) { + ip6_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = MLD6_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + group->next = netif_mld6_data(ifp); + + netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group); + } + + return group; +} + +/** + * Remove a group from the mld_group_list, but do not free it yet + * + * @param group the group to remove + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +static err_t +mld6_remove_group(struct netif *netif, struct mld_group *group) +{ + err_t err = ERR_OK; + + /* Is it the first group? */ + if (netif_mld6_data(netif) == group) { + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group->next); + } else { + /* look for group further down the list */ + struct mld_group *tmpGroup; + for (tmpGroup = netif_mld6_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) { + if (tmpGroup->next == group) { + tmpGroup->next = group->next; + break; + } + } + /* Group not find group */ + if (tmpGroup == NULL) { + err = ERR_ARG; + } + } + + return err; +} + + +/** + * Process an input MLD message. Called by icmp6_input. + * + * @param p the mld packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +mld6_input(struct pbuf *p, struct netif *inp) +{ + struct mld_header *mld_hdr; + struct mld_group *group; + + MLD6_STATS_INC(mld6.recv); + + /* Check that mld header fits in packet. */ + if (p->len < sizeof(struct mld_header)) { + /* @todo debug message */ + pbuf_free(p); + MLD6_STATS_INC(mld6.lenerr); + MLD6_STATS_INC(mld6.drop); + return; + } + + mld_hdr = (struct mld_header *)p->payload; + + switch (mld_hdr->type) { + case ICMP6_TYPE_MLQ: /* Multicast listener query. */ + /* Is it a general query? */ + if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) && + ip6_addr_isany(&(mld_hdr->multicast_address))) { + MLD6_STATS_INC(mld6.rx_general); + /* Report all groups, except all nodes group, and if-local groups. */ + group = netif_mld6_data(inp); + while (group != NULL) { + if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && + (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) { + mld6_delayed_report(group, mld_hdr->max_resp_delay); + } + group = group->next; + } + } else { + /* Have we joined this group? + * We use IP6 destination address to have a memory aligned copy. + * mld_hdr->multicast_address should be the same. */ + MLD6_STATS_INC(mld6.rx_group); + group = mld6_lookfor_group(inp, ip6_current_dest_addr()); + if (group != NULL) { + /* Schedule a report. */ + mld6_delayed_report(group, mld_hdr->max_resp_delay); + } + } + break; /* ICMP6_TYPE_MLQ */ + case ICMP6_TYPE_MLR: /* Multicast listener report. */ + /* Have we joined this group? + * We use IP6 destination address to have a memory aligned copy. + * mld_hdr->multicast_address should be the same. */ + MLD6_STATS_INC(mld6.rx_report); + group = mld6_lookfor_group(inp, ip6_current_dest_addr()); + if (group != NULL) { + /* If we are waiting to report, cancel it. */ + if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { + group->timer = 0; /* stopped */ + group->group_state = MLD6_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + } + break; /* ICMP6_TYPE_MLR */ + case ICMP6_TYPE_MLD: /* Multicast listener done. */ + /* Do nothing, router will query us. */ + break; /* ICMP6_TYPE_MLD */ + default: + MLD6_STATS_INC(mld6.proterr); + MLD6_STATS_INC(mld6.drop); + break; + } + + pbuf_free(p); +} + +/** + * @ingroup mld6 + * Join a group on a network interface. + * + * @param srcaddr ipv6 address of the network interface which should + * join a new group. If IP6_ADDR_ANY, join on all netifs + * @param groupaddr the ipv6 address of the group to join + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t +mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we join this interface ? */ + if (ip6_addr_isany(srcaddr) || + netif_get_ip6_addr_match(netif, srcaddr) >= 0) { + err = mld6_joingroup_netif(netif, groupaddr); + if (err != ERR_OK) { + return err; + } + } + + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * @ingroup mld6 + * Join a group on a network interface. + * + * @param netif the network interface which should join a new group. + * @param groupaddr the ipv6 address of the group to join + * @return ERR_OK if group was joined on the netif, an err_t otherwise + */ +err_t +mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) +{ + struct mld_group *group; + + /* find group or create a new one if not found */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group == NULL) { + /* Joining a new group. Create a new group entry. */ + group = mld6_new_group(netif, groupaddr); + if (group == NULL) { + return ERR_MEM; + } + + /* Activate this address on the MAC layer. */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); + } + + /* Report our membership. */ + MLD6_STATS_INC(mld6.tx_report); + mld6_send(netif, group, ICMP6_TYPE_MLR); + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + } + + /* Increment group use */ + group->use++; + return ERR_OK; +} + +/** + * @ingroup mld6 + * Leave a group on a network interface. + * + * @param srcaddr ipv6 address of the network interface which should + * leave the group. If IP6_ISANY, leave on all netifs + * @param groupaddr the ipv6 address of the group to leave + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t +mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we leave this interface ? */ + if (ip6_addr_isany(srcaddr) || + netif_get_ip6_addr_match(netif, srcaddr) >= 0) { + err_t res = mld6_leavegroup_netif(netif, groupaddr); + if (err != ERR_OK) { + /* Store this result if we have not yet gotten a success */ + err = res; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * @ingroup mld6 + * Leave a group on a network interface. + * + * @param netif the network interface which should leave the group. + * @param groupaddr the ipv6 address of the group to leave + * @return ERR_OK if group was left on the netif, an err_t otherwise + */ +err_t +mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) +{ + struct mld_group *group; + + /* find group */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Leave if there is no other use of the group */ + if (group->use <= 1) { + /* Remove the group from the list */ + mld6_remove_group(netif, group); + + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + MLD6_STATS_INC(mld6.tx_leave); + mld6_send(netif, group, ICMP6_TYPE_MLD); + } + + /* Disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); + } + + /* free group struct */ + memp_free(MEMP_MLD6_GROUP, group); + } else { + /* Decrement group use */ + group->use--; + } + + /* Left group */ + return ERR_OK; + } + + /* Group not found */ + return ERR_VAL; +} + + +/** + * Periodic timer for mld processing. Must be called every + * MLD6_TMR_INTERVAL milliseconds (100). + * + * When a delaying member expires, a membership report is sent. + */ +void +mld6_tmr(void) +{ + struct netif *netif = netif_list; + + while (netif != NULL) { + struct mld_group *group = netif_mld6_data(netif); + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */ + if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { + MLD6_STATS_INC(mld6.tx_report); + mld6_send(netif, group, ICMP6_TYPE_MLR); + group->group_state = MLD6_GROUP_IDLE_MEMBER; + } + } + } + group = group->next; + } + netif = netif->next; + } +} + +/** + * Schedule a delayed membership report for a group + * + * @param group the mld_group for which "delaying" membership report + * should be sent + * @param maxresp the max resp delay provided in the query + */ +static void +mld6_delayed_report(struct mld_group *group, u16_t maxresp) +{ + /* Convert maxresp from milliseconds to tmr ticks */ + maxresp = maxresp / MLD6_TMR_INTERVAL; + if (maxresp == 0) { + maxresp = 1; + } + +#ifdef LWIP_RAND + /* Randomize maxresp. (if LWIP_RAND is supported) */ + maxresp = LWIP_RAND() % maxresp; + if (maxresp == 0) { + maxresp = 1; + } +#endif /* LWIP_RAND */ + + /* Apply timer value if no report has been scheduled already. */ + if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) || + ((group->group_state == MLD6_GROUP_DELAYING_MEMBER) && + ((group->timer == 0) || (maxresp < group->timer)))) { + group->timer = maxresp; + group->group_state = MLD6_GROUP_DELAYING_MEMBER; + } +} + +/** + * Send a MLD message (report or done). + * + * An IPv6 hop-by-hop options header with a router alert option + * is prepended. + * + * @param group the group to report or quit + * @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done) + */ +static void +mld6_send(struct netif *netif, struct mld_group *group, u8_t type) +{ + struct mld_header *mld_hdr; + struct pbuf *p; + const ip6_addr_t *src_addr; + + /* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */ + p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM); + if (p == NULL) { + MLD6_STATS_INC(mld6.memerr); + return; + } + + /* Move to make room for Hop-by-hop options header. */ + if (pbuf_header(p, -IP6_HBH_HLEN)) { + pbuf_free(p); + MLD6_STATS_INC(mld6.lenerr); + return; + } + + /* Select our source address. */ + if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { + /* This is a special case, when we are performing duplicate address detection. + * We must join the multicast group, but we don't have a valid address yet. */ + src_addr = IP6_ADDR_ANY6; + } else { + /* Use link-local address as source address. */ + src_addr = netif_ip6_addr(netif, 0); + } + + /* MLD message header pointer. */ + mld_hdr = (struct mld_header *)p->payload; + + /* Set fields. */ + mld_hdr->type = type; + mld_hdr->code = 0; + mld_hdr->chksum = 0; + mld_hdr->max_resp_delay = 0; + mld_hdr->reserved = 0; + ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address)); + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, + src_addr, &(group->group_address)); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Add hop-by-hop headers options: router alert with MLD value. */ + ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); + + if (type == ICMP6_TYPE_MLR) { + /* Remember we were the last to report */ + group->last_reporter_flag = 1; + } + + /* Send the packet out. */ + MLD6_STATS_INC(mld6.xmit); + ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address), + MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, netif); + pbuf_free(p); +} + +#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.3/src/core/ipv6/nd6.c b/components/net/lwip-2.0.3/src/core/ipv6/nd6.c new file mode 100644 index 0000000000..0b367181b2 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/ipv6/nd6.c @@ -0,0 +1,2102 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/nd6.h" +#include "lwip/priv/nd6_priv.h" +#include "lwip/prot/nd6.h" +#include "lwip/prot/icmp6.h" +#include "lwip/pbuf.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp6.h" +#include "lwip/mld6.h" +#include "lwip/ip.h" +#include "lwip/stats.h" +#include "lwip/dns.h" + +#include + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK +#error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK +#endif + +/* Router tables. */ +struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; +struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS]; +struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES]; +struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS]; + +/* Default values, can be updated by a RA message. */ +u32_t reachable_time = LWIP_ND6_REACHABLE_TIME; +u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in timer */ + +/* Index for cache entries. */ +static u8_t nd6_cached_neighbor_index; +static u8_t nd6_cached_destination_index; + +/* Multicast address holder. */ +static ip6_addr_t multicast_address; + +/* Static buffer to parse RA packet options (size of a prefix option, biggest option) */ +static u8_t nd6_ra_buffer[sizeof(struct prefix_option)]; + +/* Forward declarations. */ +static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr); +static s8_t nd6_new_neighbor_cache_entry(void); +static void nd6_free_neighbor_cache_entry(s8_t i); +static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr); +static s8_t nd6_new_destination_cache_entry(void); +static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif); +static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif); +static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif); +static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif); +static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); +static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); +static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif); +static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q); + +#define ND6_SEND_FLAG_MULTICAST_DEST 0x01 +#define ND6_SEND_FLAG_ALLNODES_DEST 0x02 +static void nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); +static void nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); +static void nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags); +#if LWIP_IPV6_SEND_ROUTER_SOLICIT +static err_t nd6_send_rs(struct netif *netif); +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +#if LWIP_ND6_QUEUEING +static void nd6_free_q(struct nd6_q_entry *q); +#else /* LWIP_ND6_QUEUEING */ +#define nd6_free_q(q) pbuf_free(q) +#endif /* LWIP_ND6_QUEUEING */ +static void nd6_send_q(s8_t i); + + +/** + * Process an incoming neighbor discovery message + * + * @param p the nd packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +nd6_input(struct pbuf *p, struct netif *inp) +{ + u8_t msg_type; + s8_t i; + + ND6_STATS_INC(nd6.recv); + + msg_type = *((u8_t *)p->payload); + switch (msg_type) { + case ICMP6_TYPE_NA: /* Neighbor Advertisement. */ + { + struct na_header *na_hdr; + struct lladdr_option *lladdr_opt; + + /* Check that na header fits in packet. */ + if (p->len < (sizeof(struct na_header))) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + na_hdr = (struct na_header *)p->payload; + + /* Unsolicited NA?*/ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + ip6_addr_t target_address; + + /* This is an unsolicited NA. + * link-layer changed? + * part of DAD mechanism? */ + + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(na_hdr->target_address)); + +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS + /* If the target address matches this netif, it is a DAD response. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && + ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { + /* We are using a duplicate address. */ + netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); + +#if LWIP_IPV6_AUTOCONFIG + /* Check to see if this address was autoconfigured. */ + if (!ip6_addr_islinklocal(&target_address)) { + i = nd6_get_onlink_prefix(&target_address, inp); + if (i >= 0) { + /* Mark this prefix as duplicate, so that we don't use it + * to generate this address again. */ + prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE; + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + + pbuf_free(p); + return; + } + } +#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ + + /* Check that link-layer address option also fits in packet. */ + if (p->len < (sizeof(struct na_header) + 2)) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + /* This is an unsolicited NA, most likely there was a LLADDR change. */ + i = nd6_find_neighbor_cache_entry(&target_address); + if (i >= 0) { + if (na_hdr->flags & ND6_FLAG_OVERRIDE) { + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + } + } + } else { + ip6_addr_t target_address; + + /* This is a solicited NA. + * neighbor address resolution response? + * neighbor unreachability detection response? */ + + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(na_hdr->target_address)); + + /* Find the cache entry corresponding to this na. */ + i = nd6_find_neighbor_cache_entry(&target_address); + if (i < 0) { + /* We no longer care about this target address. drop it. */ + pbuf_free(p); + return; + } + + /* Update cache entry. */ + if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || + (neighbor_cache[i].state == ND6_INCOMPLETE)) { + /* Check that link-layer address option also fits in packet. */ + if (p->len < (sizeof(struct na_header) + 2)) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + } + + neighbor_cache[i].netif = inp; + neighbor_cache[i].state = ND6_REACHABLE; + neighbor_cache[i].counter.reachable_time = reachable_time; + + /* Send queued packets, if any. */ + if (neighbor_cache[i].q != NULL) { + nd6_send_q(i); + } + } + + break; /* ICMP6_TYPE_NA */ + } + case ICMP6_TYPE_NS: /* Neighbor solicitation. */ + { + struct ns_header *ns_hdr; + struct lladdr_option *lladdr_opt; + u8_t accepted; + + /* Check that ns header fits in packet. */ + if (p->len < sizeof(struct ns_header)) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + ns_hdr = (struct ns_header *)p->payload; + + /* Check if there is a link-layer address provided. Only point to it if in this buffer. */ + if (p->len >= (sizeof(struct ns_header) + 2)) { + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); + if (p->len < (sizeof(struct ns_header) + (lladdr_opt->length << 3))) { + lladdr_opt = NULL; + } + } else { + lladdr_opt = NULL; + } + + /* Check if the target address is configured on the receiving netif. */ + accepted = 0; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) || + (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) && + ip6_addr_isany(ip6_current_src_addr()))) && + ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { + accepted = 1; + break; + } + } + + /* NS not for us? */ + if (!accepted) { + pbuf_free(p); + return; + } + + /* Check for ANY address in src (DAD algorithm). */ + if (ip6_addr_isany(ip6_current_src_addr())) { + /* Sender is validating this address. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && + ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { + /* Send a NA back so that the sender does not use this address. */ + nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST); + if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) { + /* We shouldn't use this address either. */ + netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); + } + } + } + } else { + ip6_addr_t target_address; + + /* Sender is trying to resolve our address. */ + /* Verify that they included their own link-layer address. */ + if (lladdr_opt == NULL) { + /* Not a valid message. */ + pbuf_free(p); + ND6_STATS_INC(nd6.proterr); + ND6_STATS_INC(nd6.drop); + return; + } + + i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); + if (i>= 0) { + /* We already have a record for the solicitor. */ + if (neighbor_cache[i].state == ND6_INCOMPLETE) { + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + + /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; + } + } else { + /* Add their IPv6 address and link-layer address to neighbor cache. + * We will need it at least to send a unicast NA message, but most + * likely we will also be communicating with this node soon. */ + i = nd6_new_neighbor_cache_entry(); + if (i < 0) { + /* We couldn't assign a cache entry for this neighbor. + * we won't be able to reply. drop it. */ + pbuf_free(p); + ND6_STATS_INC(nd6.memerr); + return; + } + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); + + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; + } + + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(ns_hdr->target_address)); + + /* Send back a NA for us. Allocate the reply pbuf. */ + nd6_send_na(inp, &target_address, ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); + } + + break; /* ICMP6_TYPE_NS */ + } + case ICMP6_TYPE_RA: /* Router Advertisement. */ + { + struct ra_header *ra_hdr; + u8_t *buffer; /* Used to copy options. */ + u16_t offset; +#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS + /* There can by multiple RDNSS options per RA */ + u8_t rdnss_server_idx = 0; +#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ + + /* Check that RA header fits in packet. */ + if (p->len < sizeof(struct ra_header)) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + ra_hdr = (struct ra_header *)p->payload; + + /* If we are sending RS messages, stop. */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* ensure at least one solicitation is sent */ + if ((inp->rs_count < LWIP_ND6_MAX_MULTICAST_SOLICIT) || + (nd6_send_rs(inp) == ERR_OK)) { + inp->rs_count = 0; + } +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + + /* Get the matching default router entry. */ + i = nd6_get_router(ip6_current_src_addr(), inp); + if (i < 0) { + /* Create a new router entry. */ + i = nd6_new_router(ip6_current_src_addr(), inp); + } + + if (i < 0) { + /* Could not create a new router entry. */ + pbuf_free(p); + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Re-set invalidation timer. */ + default_router_list[i].invalidation_timer = lwip_htons(ra_hdr->router_lifetime); + + /* Re-set default timer values. */ +#if LWIP_ND6_ALLOW_RA_UPDATES + if (ra_hdr->retrans_timer > 0) { + retrans_timer = lwip_htonl(ra_hdr->retrans_timer); + } + if (ra_hdr->reachable_time > 0) { + reachable_time = lwip_htonl(ra_hdr->reachable_time); + } +#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ + + /* @todo set default hop limit... */ + /* ra_hdr->current_hop_limit;*/ + + /* Update flags in local entry (incl. preference). */ + default_router_list[i].flags = ra_hdr->flags; + + /* Offset to options. */ + offset = sizeof(struct ra_header); + + /* Process each option. */ + while ((p->tot_len - offset) > 0) { + if (p->len == p->tot_len) { + /* no need to copy from contiguous pbuf */ + buffer = &((u8_t*)p->payload)[offset]; + } else { + buffer = nd6_ra_buffer; + if (pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset) != sizeof(struct prefix_option)) { + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + } + if (buffer[1] == 0) { + /* zero-length extension. drop packet */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + switch (buffer[0]) { + case ND6_OPTION_TYPE_SOURCE_LLADDR: + { + struct lladdr_option *lladdr_opt; + lladdr_opt = (struct lladdr_option *)buffer; + if ((default_router_list[i].neighbor_entry != NULL) && + (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) { + SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len); + default_router_list[i].neighbor_entry->state = ND6_REACHABLE; + default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time; + } + break; + } + case ND6_OPTION_TYPE_MTU: + { + struct mtu_option *mtu_opt; + mtu_opt = (struct mtu_option *)buffer; + if (lwip_htonl(mtu_opt->mtu) >= 1280) { +#if LWIP_ND6_ALLOW_RA_UPDATES + inp->mtu = (u16_t)lwip_htonl(mtu_opt->mtu); +#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ + } + break; + } + case ND6_OPTION_TYPE_PREFIX_INFO: + { + struct prefix_option *prefix_opt; + prefix_opt = (struct prefix_option *)buffer; + + if ((prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) && + (prefix_opt->prefix_length == 64) && + !ip6_addr_islinklocal(&(prefix_opt->prefix))) { + /* Add to on-link prefix list. */ + s8_t prefix; + ip6_addr_t prefix_addr; + + /* Get a memory-aligned copy of the prefix. */ + ip6_addr_set(&prefix_addr, &(prefix_opt->prefix)); + + /* find cache entry for this prefix. */ + prefix = nd6_get_onlink_prefix(&prefix_addr, inp); + if (prefix < 0) { + /* Create a new cache entry. */ + prefix = nd6_new_onlink_prefix(&prefix_addr, inp); + } + if (prefix >= 0) { + prefix_list[prefix].invalidation_timer = lwip_htonl(prefix_opt->valid_lifetime); + +#if LWIP_IPV6_AUTOCONFIG + if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { + /* Mark prefix as autonomous, so that address autoconfiguration can take place. + * Only OR flag, so that we don't over-write other flags (such as ADDRESS_DUPLICATE)*/ + prefix_list[prefix].flags |= ND6_PREFIX_AUTOCONFIG_AUTONOMOUS; + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + } + } + + break; + } + case ND6_OPTION_TYPE_ROUTE_INFO: + /* @todo implement preferred routes. + struct route_option * route_opt; + route_opt = (struct route_option *)buffer;*/ + + break; +#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS + case ND6_OPTION_TYPE_RDNSS: + { + u8_t num, n; + struct rdnss_option * rdnss_opt; + + rdnss_opt = (struct rdnss_option *)buffer; + num = (rdnss_opt->length - 1) / 2; + for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) { + ip_addr_t rdnss_address; + + /* Get a memory-aligned copy of the prefix. */ + ip_addr_copy_from_ip6(rdnss_address, rdnss_opt->rdnss_address[n]); + + if (htonl(rdnss_opt->lifetime) > 0) { + /* TODO implement Lifetime > 0 */ + dns_setserver(rdnss_server_idx++, &rdnss_address); + } else { + /* TODO implement DNS removal in dns.c */ + u8_t s; + for (s = 0; s < DNS_MAX_SERVERS; s++) { + const ip_addr_t *addr = dns_getserver(s); + if(ip_addr_cmp(addr, &rdnss_address)) { + dns_setserver(s, NULL); + } + } + } + } + break; + } +#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ + default: + /* Unrecognized option, abort. */ + ND6_STATS_INC(nd6.proterr); + break; + } + /* option length is checked earlier to be non-zero to make sure loop ends */ + offset += 8 * ((u16_t)buffer[1]); + } + + break; /* ICMP6_TYPE_RA */ + } + case ICMP6_TYPE_RD: /* Redirect */ + { + struct redirect_header *redir_hdr; + struct lladdr_option *lladdr_opt; + ip6_addr_t tmp; + + /* Check that Redir header fits in packet. */ + if (p->len < sizeof(struct redirect_header)) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + redir_hdr = (struct redirect_header *)p->payload; + + if (p->len >= (sizeof(struct redirect_header) + 2)) { + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct redirect_header)); + if (p->len < (sizeof(struct redirect_header) + (lladdr_opt->length << 3))) { + lladdr_opt = NULL; + } + } else { + lladdr_opt = NULL; + } + + /* Copy original destination address to current source address, to have an aligned copy. */ + ip6_addr_set(&tmp, &(redir_hdr->destination_address)); + + /* Find dest address in cache */ + i = nd6_find_destination_cache_entry(&tmp); + if (i < 0) { + /* Destination not in cache, drop packet. */ + pbuf_free(p); + return; + } + + /* Set the new target address. */ + ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address)); + + /* If Link-layer address of other router is given, try to add to neighbor cache. */ + if (lladdr_opt != NULL) { + if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) { + /* Copy target address to current source address, to have an aligned copy. */ + ip6_addr_set(&tmp, &(redir_hdr->target_address)); + + i = nd6_find_neighbor_cache_entry(&tmp); + if (i < 0) { + i = nd6_new_neighbor_cache_entry(); + if (i >= 0) { + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + ip6_addr_set(&(neighbor_cache[i].next_hop_address), &tmp); + + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; + } + } + if (i >= 0) { + if (neighbor_cache[i].state == ND6_INCOMPLETE) { + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; + } + } + } + } + break; /* ICMP6_TYPE_RD */ + } + case ICMP6_TYPE_PTB: /* Packet too big */ + { + struct icmp6_hdr *icmp6hdr; /* Packet too big message */ + struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ + u32_t pmtu; + ip6_addr_t tmp; + + /* Check that ICMPv6 header + IPv6 header fit in payload */ + if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { + /* drop short packets */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + icmp6hdr = (struct icmp6_hdr *)p->payload; + ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); + + /* Copy original destination address to current source address, to have an aligned copy. */ + ip6_addr_set(&tmp, &(ip6hdr->dest)); + + /* Look for entry in destination cache. */ + i = nd6_find_destination_cache_entry(&tmp); + if (i < 0) { + /* Destination not in cache, drop packet. */ + pbuf_free(p); + return; + } + + /* Change the Path MTU. */ + pmtu = lwip_htonl(icmp6hdr->data); + destination_cache[i].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF); + + break; /* ICMP6_TYPE_PTB */ + } + + default: + ND6_STATS_INC(nd6.proterr); + ND6_STATS_INC(nd6.drop); + break; /* default */ + } + + pbuf_free(p); +} + + +/** + * Periodic timer for Neighbor discovery functions: + * + * - Update neighbor reachability states + * - Update destination cache entries age + * - Update invalidation timers of default routers and on-link prefixes + * - Perform duplicate address detection (DAD) for our addresses + * - Send router solicitations + */ +void +nd6_tmr(void) +{ + s8_t i; + struct netif *netif; + + /* Process neighbor entries. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + switch (neighbor_cache[i].state) { + case ND6_INCOMPLETE: + if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && + (!neighbor_cache[i].isrouter)) { + /* Retries exceeded. */ + nd6_free_neighbor_cache_entry(i); + } else { + /* Send a NS for this entry. */ + neighbor_cache[i].counter.probes_sent++; + nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); + } + break; + case ND6_REACHABLE: + /* Send queued packets, if any are left. Should have been sent already. */ + if (neighbor_cache[i].q != NULL) { + nd6_send_q(i); + } + if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) { + /* Change to stale state. */ + neighbor_cache[i].state = ND6_STALE; + neighbor_cache[i].counter.stale_time = 0; + } else { + neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL; + } + break; + case ND6_STALE: + neighbor_cache[i].counter.stale_time++; + break; + case ND6_DELAY: + if (neighbor_cache[i].counter.delay_time <= 1) { + /* Change to PROBE state. */ + neighbor_cache[i].state = ND6_PROBE; + neighbor_cache[i].counter.probes_sent = 0; + } else { + neighbor_cache[i].counter.delay_time--; + } + break; + case ND6_PROBE: + if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && + (!neighbor_cache[i].isrouter)) { + /* Retries exceeded. */ + nd6_free_neighbor_cache_entry(i); + } else { + /* Send a NS for this entry. */ + neighbor_cache[i].counter.probes_sent++; + nd6_send_neighbor_cache_probe(&neighbor_cache[i], 0); + } + break; + case ND6_NO_ENTRY: + default: + /* Do nothing. */ + break; + } + } + + /* Process destination entries. */ + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + destination_cache[i].age++; + } + + /* Process router entries. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (default_router_list[i].neighbor_entry != NULL) { + /* Active entry. */ + if (default_router_list[i].invalidation_timer > 0) { + default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; + } + if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { + /* Less than 1 second remaining. Clear this entry. */ + default_router_list[i].neighbor_entry->isrouter = 0; + default_router_list[i].neighbor_entry = NULL; + default_router_list[i].invalidation_timer = 0; + default_router_list[i].flags = 0; + } + } + } + + /* Process prefix entries. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if (prefix_list[i].netif != NULL) { + if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { + /* Entry timed out, remove it */ + prefix_list[i].invalidation_timer = 0; + +#if LWIP_IPV6_AUTOCONFIG + /* If any addresses were configured with this prefix, remove them */ + if (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED) { + s8_t j; + + for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { + if ((netif_ip6_addr_state(prefix_list[i].netif, j) != IP6_ADDR_INVALID) && + ip6_addr_netcmp(&prefix_list[i].prefix, netif_ip6_addr(prefix_list[i].netif, j))) { + netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_INVALID); + prefix_list[i].flags = 0; + + /* Exit loop. */ + break; + } + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + + prefix_list[i].netif = NULL; + prefix_list[i].flags = 0; + } else { + prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; + +#if LWIP_IPV6_AUTOCONFIG + /* Initiate address autoconfiguration for this prefix, if conditions are met. */ + if (prefix_list[i].netif->ip6_autoconfig_enabled && + (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_AUTONOMOUS) && + !(prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)) { + s8_t j; + /* Try to get an address on this netif that is invalid. + * Skip 0 index (link-local address) */ + for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { + if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDR_INVALID) { + /* Generate an address using this prefix and interface ID from link-local address. */ + netif_ip6_addr_set_parts(prefix_list[i].netif, j, + prefix_list[i].prefix.addr[0], prefix_list[i].prefix.addr[1], + netif_ip6_addr(prefix_list[i].netif, 0)->addr[2], netif_ip6_addr(prefix_list[i].netif, 0)->addr[3]); + + /* Mark it as tentative (DAD will be performed if configured). */ + netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_TENTATIVE); + + /* Mark this prefix with ADDRESS_GENERATED, so that we don't try again. */ + prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED; + + /* Exit loop. */ + break; + } + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + } + } + } + + + /* Process our own addresses, if DAD configured. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + u8_t addr_state = netif_ip6_addr_state(netif, i); + if (ip6_addr_istentative(addr_state)) { + if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { + /* No NA received in response. Mark address as valid. */ + netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED); + /* @todo implement preferred and valid lifetimes. */ + } else if (netif->flags & NETIF_FLAG_UP) { + /* Send a NS for this address. */ + nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST); + /* tentative: set next state by increasing by one */ + netif_ip6_addr_set_state(netif, i, addr_state + 1); + /* @todo send max 1 NS per tmr call? enable return*/ + /*return;*/ + } + } + } + } + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* Send router solicitation messages, if necessary. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if ((netif->rs_count > 0) && (netif->flags & NETIF_FLAG_UP) && + (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)))) { + if (nd6_send_rs(netif) == ERR_OK) { + netif->rs_count--; + } + } + } +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +} + +/** Send a neighbor solicitation message for a specific neighbor cache entry + * + * @param entry the neightbor cache entry for wich to send the message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags) +{ + nd6_send_ns(entry->netif, &entry->next_hop_address, flags); +} + +/** + * Send a neighbor solicitation message + * + * @param netif the netif on which to send the message + * @param target_addr the IPv6 target address for the ND message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) +{ + struct ns_header *ns_hdr; + struct pbuf *p; + const ip6_addr_t *src_addr; + u16_t lladdr_opt_len; + + if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { + /* Use link-local address as source address. */ + src_addr = netif_ip6_addr(netif, 0); + /* calculate option length (in 8-byte-blocks) */ + lladdr_opt_len = ((netif->hwaddr_len + 2) + 7) >> 3; + } else { + src_addr = IP6_ADDR_ANY6; + /* Option "MUST NOT be included when the source IP address is the unspecified address." */ + lladdr_opt_len = 0; + } + + /* Allocate a packet. */ + p = pbuf_alloc(PBUF_IP, sizeof(struct ns_header) + (lladdr_opt_len << 3), PBUF_RAM); + if (p == NULL) { + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + ns_hdr = (struct ns_header *)p->payload; + + ns_hdr->type = ICMP6_TYPE_NS; + ns_hdr->code = 0; + ns_hdr->chksum = 0; + ns_hdr->reserved = 0; + ip6_addr_set(&(ns_hdr->target_address), target_addr); + + if (lladdr_opt_len != 0) { + struct lladdr_option *lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); + lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; + lladdr_opt->length = (u8_t)lladdr_opt_len; + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + } + + /* Generate the solicited node address for the target address. */ + if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { + ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); + target_addr = &multicast_address; + } + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + target_addr); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, target_addr, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} + +/** + * Send a neighbor advertisement message + * + * @param netif the netif on which to send the message + * @param target_addr the IPv6 target address for the ND message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) +{ + struct na_header *na_hdr; + struct lladdr_option *lladdr_opt; + struct pbuf *p; + const ip6_addr_t *src_addr; + const ip6_addr_t *dest_addr; + u16_t lladdr_opt_len; + + /* Use link-local address as source address. */ + /* src_addr = netif_ip6_addr(netif, 0); */ + /* Use target address as source address. */ + src_addr = target_addr; + + /* Allocate a packet. */ + lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + (lladdr_opt_len << 3), PBUF_RAM); + if (p == NULL) { + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + na_hdr = (struct na_header *)p->payload; + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + na_hdr->type = ICMP6_TYPE_NA; + na_hdr->code = 0; + na_hdr->chksum = 0; + na_hdr->flags = flags & 0xf0; + na_hdr->reserved[0] = 0; + na_hdr->reserved[1] = 0; + na_hdr->reserved[2] = 0; + ip6_addr_set(&(na_hdr->target_address), target_addr); + + lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR; + lladdr_opt->length = (u8_t)lladdr_opt_len; + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + + /* Generate the solicited node address for the target address. */ + if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { + ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); + dest_addr = &multicast_address; + } else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) { + ip6_addr_set_allnodes_linklocal(&multicast_address); + dest_addr = &multicast_address; + } else { + dest_addr = ip6_current_src_addr(); + } + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + dest_addr); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, src_addr, dest_addr, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT +/** + * Send a router solicitation message + * + * @param netif the netif on which to send the message + */ +static err_t +nd6_send_rs(struct netif *netif) +{ + struct rs_header *rs_hdr; + struct lladdr_option *lladdr_opt; + struct pbuf *p; + const ip6_addr_t *src_addr; + err_t err; + u16_t lladdr_opt_len = 0; + + /* Link-local source address, or unspecified address? */ + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { + src_addr = netif_ip6_addr(netif, 0); + } else { + src_addr = IP6_ADDR_ANY6; + } + + /* Generate the all routers target address. */ + ip6_addr_set_allrouters_linklocal(&multicast_address); + + /* Allocate a packet. */ + if (src_addr != IP6_ADDR_ANY6) { + lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + } + p = pbuf_alloc(PBUF_IP, sizeof(struct rs_header) + (lladdr_opt_len << 3), PBUF_RAM); + if (p == NULL) { + ND6_STATS_INC(nd6.memerr); + return ERR_BUF; + } + + /* Set fields. */ + rs_hdr = (struct rs_header *)p->payload; + + rs_hdr->type = ICMP6_TYPE_RS; + rs_hdr->code = 0; + rs_hdr->chksum = 0; + rs_hdr->reserved = 0; + + if (src_addr != IP6_ADDR_ANY6) { + /* Include our hw address. */ + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header)); + lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; + lladdr_opt->length = (u8_t)lladdr_opt_len; + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + } + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + &multicast_address); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + + err = ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, &multicast_address, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); + + return err; +} +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +/** + * Search for a neighbor cache entry + * + * @param ip6addr the IPv6 address of the neighbor + * @return The neighbor cache entry index that matched, -1 if no + * entry is found + */ +static s8_t +nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) { + return i; + } + } + return -1; +} + +/** + * Create a new neighbor cache entry. + * + * If no unused entry is found, will try to recycle an old entry + * according to ad-hoc "age" heuristic. + * + * @return The neighbor cache entry index that was created, -1 if no + * entry could be created + */ +static s8_t +nd6_new_neighbor_cache_entry(void) +{ + s8_t i; + s8_t j; + u32_t time; + + + /* First, try to find an empty entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (neighbor_cache[i].state == ND6_NO_ENTRY) { + return i; + } + } + + /* We need to recycle an entry. in general, do not recycle if it is a router. */ + + /* Next, try to find a Stale entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_STALE) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find a Probe entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_PROBE) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find a Delayed entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_DELAY) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find the oldest reachable entry. */ + time = 0xfffffffful; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_REACHABLE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.reachable_time < time) { + j = i; + time = neighbor_cache[i].counter.reachable_time; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* Next, find oldest incomplete entry without queued packets. */ + time = 0; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ( + (neighbor_cache[i].q == NULL) && + (neighbor_cache[i].state == ND6_INCOMPLETE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.probes_sent >= time) { + j = i; + time = neighbor_cache[i].counter.probes_sent; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* Next, find oldest incomplete entry with queued packets. */ + time = 0; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_INCOMPLETE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.probes_sent >= time) { + j = i; + time = neighbor_cache[i].counter.probes_sent; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* No more entries to try. */ + return -1; +} + +/** + * Will free any resources associated with a neighbor cache + * entry, and will mark it as unused. + * + * @param i the neighbor cache entry index to free + */ +static void +nd6_free_neighbor_cache_entry(s8_t i) +{ + if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { + return; + } + if (neighbor_cache[i].isrouter) { + /* isrouter needs to be cleared before deleting a neighbor cache entry */ + return; + } + + /* Free any queued packets. */ + if (neighbor_cache[i].q != NULL) { + nd6_free_q(neighbor_cache[i].q); + neighbor_cache[i].q = NULL; + } + + neighbor_cache[i].state = ND6_NO_ENTRY; + neighbor_cache[i].isrouter = 0; + neighbor_cache[i].netif = NULL; + neighbor_cache[i].counter.reachable_time = 0; + ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address)); +} + +/** + * Search for a destination cache entry + * + * @param ip6addr the IPv6 address of the destination + * @return The destination cache entry index that matched, -1 if no + * entry is found + */ +static s8_t +nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) { + return i; + } + } + return -1; +} + +/** + * Create a new destination cache entry. If no unused entry is found, + * will recycle oldest entry. + * + * @return The destination cache entry index that was created, -1 if no + * entry was created + */ +static s8_t +nd6_new_destination_cache_entry(void) +{ + s8_t i, j; + u32_t age; + + /* Find an empty entry. */ + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (ip6_addr_isany(&(destination_cache[i].destination_addr))) { + return i; + } + } + + /* Find oldest entry. */ + age = 0; + j = LWIP_ND6_NUM_DESTINATIONS - 1; + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (destination_cache[i].age > age) { + j = i; + } + } + + return j; +} + +/** + * Clear the destination cache. + * + * This operation may be necessary for consistency in the light of changing + * local addresses and/or use of the gateway hook. + */ +void +nd6_clear_destination_cache(void) +{ + int i; + + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + ip6_addr_set_any(&destination_cache[i].destination_addr); + } +} + +/** + * Determine whether an address matches an on-link prefix. + * + * @param ip6addr the IPv6 address to match + * @return 1 if the address is on-link, 0 otherwise + */ +static s8_t +nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if ((prefix_list[i].netif == netif) && + (prefix_list[i].invalidation_timer > 0) && + ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) { + return 1; + } + } + /* Check to see if address prefix matches a (manually?) configured address. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) { + return 1; + } + } + return 0; +} + +/** + * Select a default router for a destination. + * + * @param ip6addr the destination address + * @param netif the netif for the outgoing packet, if known + * @return the default router entry index, or -1 if no suitable + * router is found + */ +static s8_t +nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif) +{ + s8_t i; + /* last_router is used for round-robin router selection (as recommended + * in RFC). This is more robust in case one router is not reachable, + * we are not stuck trying to resolve it. */ + static s8_t last_router; + (void)ip6addr; /* @todo match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */ + + /* @todo: implement default router preference */ + + /* Look for reachable routers. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if ((default_router_list[i].neighbor_entry != NULL) && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && + (default_router_list[i].invalidation_timer > 0) && + (default_router_list[i].neighbor_entry->state == ND6_REACHABLE)) { + return i; + } + } + + /* Look for router in other reachability states, but still valid according to timer. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if ((default_router_list[i].neighbor_entry != NULL) && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && + (default_router_list[i].invalidation_timer > 0)) { + return i; + } + } + + /* Look for any router for which we have any information at all. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if (default_router_list[i].neighbor_entry != NULL && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1)) { + return i; + } + } + + /* no suitable router found. */ + return -1; +} + +/** + * Find a router-announced route to the given destination. + * + * The caller is responsible for checking whether the returned netif, if any, + * is in a suitable state (up, link up) to be used for packet transmission. + * + * @param ip6addr the destination IPv6 address + * @return the netif to use for the destination, or NULL if none found + */ +struct netif * +nd6_find_route(const ip6_addr_t *ip6addr) +{ + s8_t i; + + i = nd6_select_router(ip6addr, NULL); + if (i >= 0) { + if (default_router_list[i].neighbor_entry != NULL) { + return default_router_list[i].neighbor_entry->netif; /* may be NULL */ + } + } + + return NULL; +} + +/** + * Find an entry for a default router. + * + * @param router_addr the IPv6 address of the router + * @param netif the netif on which the router is found, if known + * @return the index of the router entry, or -1 if not found + */ +static s8_t +nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif) +{ + s8_t i; + + /* Look for router. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if ((default_router_list[i].neighbor_entry != NULL) && + ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) && + ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { + return i; + } + } + + /* router not found. */ + return -1; +} + +/** + * Create a new entry for a default router. + * + * @param router_addr the IPv6 address of the router + * @param netif the netif on which the router is connected, if known + * @return the index on the router table, or -1 if could not be created + */ +static s8_t +nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif) +{ + s8_t router_index; + s8_t free_router_index; + s8_t neighbor_index; + + /* Do we have a neighbor entry for this router? */ + neighbor_index = nd6_find_neighbor_cache_entry(router_addr); + if (neighbor_index < 0) { + /* Create a neighbor entry for this router. */ + neighbor_index = nd6_new_neighbor_cache_entry(); + if (neighbor_index < 0) { + /* Could not create neighbor entry for this router. */ + return -1; + } + ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr); + neighbor_cache[neighbor_index].netif = netif; + neighbor_cache[neighbor_index].q = NULL; + neighbor_cache[neighbor_index].state = ND6_INCOMPLETE; + neighbor_cache[neighbor_index].counter.probes_sent = 1; + nd6_send_neighbor_cache_probe(&neighbor_cache[neighbor_index], ND6_SEND_FLAG_MULTICAST_DEST); + } + + /* Mark neighbor as router. */ + neighbor_cache[neighbor_index].isrouter = 1; + + /* Look for empty entry. */ + free_router_index = LWIP_ND6_NUM_ROUTERS; + for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) { + /* check if router already exists (this is a special case for 2 netifs on the same subnet + - e.g. wifi and cable) */ + if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){ + return router_index; + } + if (default_router_list[router_index].neighbor_entry == NULL) { + /* remember lowest free index to create a new entry */ + free_router_index = router_index; + } + } + if (free_router_index < LWIP_ND6_NUM_ROUTERS) { + default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); + return free_router_index; + } + + /* Could not create a router entry. */ + + /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */ + neighbor_cache[neighbor_index].isrouter = 0; + + /* router not found. */ + return -1; +} + +/** + * Find the cached entry for an on-link prefix. + * + * @param prefix the IPv6 prefix that is on-link + * @param netif the netif on which the prefix is on-link + * @return the index on the prefix table, or -1 if not found + */ +static s8_t +nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) +{ + s8_t i; + + /* Look for prefix in list. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { + if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) && + (prefix_list[i].netif == netif)) { + return i; + } + } + + /* Entry not available. */ + return -1; +} + +/** + * Creates a new entry for an on-link prefix. + * + * @param prefix the IPv6 prefix that is on-link + * @param netif the netif on which the prefix is on-link + * @return the index on the prefix table, or -1 if not created + */ +static s8_t +nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) +{ + s8_t i; + + /* Create new entry. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { + if ((prefix_list[i].netif == NULL) || + (prefix_list[i].invalidation_timer == 0)) { + /* Found empty prefix entry. */ + prefix_list[i].netif = netif; + ip6_addr_set(&(prefix_list[i].prefix), prefix); +#if LWIP_IPV6_AUTOCONFIG + prefix_list[i].flags = 0; +#endif /* LWIP_IPV6_AUTOCONFIG */ + return i; + } + } + + /* Entry not available. */ + return -1; +} + +/** + * Determine the next hop for a destination. Will determine if the + * destination is on-link, else a suitable on-link router is selected. + * + * The last entry index is cached for fast entry search. + * + * @param ip6addr the destination address + * @param netif the netif on which the packet will be sent + * @return the neighbor cache entry for the next hop, ERR_RTE if no + * suitable next hop was found, ERR_MEM if no cache entry + * could be created + */ +static s8_t +nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) +{ +#ifdef LWIP_HOOK_ND6_GET_GW + const ip6_addr_t *next_hop_addr; +#endif /* LWIP_HOOK_ND6_GET_GW */ + s8_t i; + +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t addr_hint = *(netif->addr_hint); + if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) { + nd6_cached_destination_index = addr_hint; + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* Look for ip6addr in destination cache. */ + if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + /* the cached entry index is the right one! */ + /* do nothing. */ + ND6_STATS_INC(nd6.cachehit); + } else { + /* Search destination cache. */ + i = nd6_find_destination_cache_entry(ip6addr); + if (i >= 0) { + /* found destination entry. make it our new cached index. */ + nd6_cached_destination_index = i; + } else { + /* Not found. Create a new destination entry. */ + i = nd6_new_destination_cache_entry(); + if (i >= 0) { + /* got new destination entry. make it our new cached index. */ + nd6_cached_destination_index = i; + } else { + /* Could not create a destination cache entry. */ + return ERR_MEM; + } + + /* Copy dest address to destination cache. */ + ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr); + + /* Now find the next hop. is it a neighbor? */ + if (ip6_addr_islinklocal(ip6addr) || + nd6_is_prefix_in_netif(ip6addr, netif)) { + /* Destination in local link. */ + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; + ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); +#ifdef LWIP_HOOK_ND6_GET_GW + } else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) { + /* Next hop for destination provided by hook function. */ + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; + ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr); +#endif /* LWIP_HOOK_ND6_GET_GW */ + } else { + /* We need to select a router. */ + i = nd6_select_router(ip6addr, netif); + if (i < 0) { + /* No router found. */ + ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); + return ERR_RTE; + } + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */ + ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); + } + } + } + +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + *(netif->addr_hint) = nd6_cached_destination_index; + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* Look in neighbor cache for the next-hop address. */ + if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr), + &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { + /* Cache hit. */ + /* Do nothing. */ + ND6_STATS_INC(nd6.cachehit); + } else { + i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr)); + if (i >= 0) { + /* Found a matching record, make it new cached entry. */ + nd6_cached_neighbor_index = i; + } else { + /* Neighbor not in cache. Make a new entry. */ + i = nd6_new_neighbor_cache_entry(); + if (i >= 0) { + /* got new neighbor entry. make it our new cached index. */ + nd6_cached_neighbor_index = i; + } else { + /* Could not create a neighbor cache entry. */ + return ERR_MEM; + } + + /* Initialize fields. */ + ip6_addr_copy(neighbor_cache[i].next_hop_address, + destination_cache[nd6_cached_destination_index].next_hop_addr); + neighbor_cache[i].isrouter = 0; + neighbor_cache[i].netif = netif; + neighbor_cache[i].state = ND6_INCOMPLETE; + neighbor_cache[i].counter.probes_sent = 1; + nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); + } + } + + /* Reset this destination's age. */ + destination_cache[nd6_cached_destination_index].age = 0; + + return nd6_cached_neighbor_index; +} + +/** + * Queue a packet for a neighbor. + * + * @param neighbor_index the index in the neighbor cache table + * @param q packet to be queued + * @return ERR_OK if succeeded, ERR_MEM if out of memory + */ +static err_t +nd6_queue_packet(s8_t neighbor_index, struct pbuf *q) +{ + err_t result = ERR_MEM; + struct pbuf *p; + int copy_needed = 0; +#if LWIP_ND6_QUEUEING + struct nd6_q_entry *new_entry, *r; +#endif /* LWIP_ND6_QUEUEING */ + + if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) { + return ERR_ARG; + } + + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + if (p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if (copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); + while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { + /* Free oldest packet (as per RFC recommendation) */ +#if LWIP_ND6_QUEUEING + r = neighbor_cache[neighbor_index].q; + neighbor_cache[neighbor_index].q = r->next; + r->next = NULL; + nd6_free_q(r); +#else /* LWIP_ND6_QUEUEING */ + pbuf_free(neighbor_cache[neighbor_index].q); + neighbor_cache[neighbor_index].q = NULL; +#endif /* LWIP_ND6_QUEUEING */ + p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); + } + if (p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet was copied/ref'd? */ + if (p != NULL) { + /* queue packet ... */ +#if LWIP_ND6_QUEUEING + /* allocate a new nd6 queue entry */ + new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { + /* Free oldest packet (as per RFC recommendation) */ + r = neighbor_cache[neighbor_index].q; + neighbor_cache[neighbor_index].q = r->next; + r->next = NULL; + nd6_free_q(r); + new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + } + if (new_entry != NULL) { + new_entry->next = NULL; + new_entry->p = p; + if (neighbor_cache[neighbor_index].q != NULL) { + /* queue was already existent, append the new entry to the end */ + r = neighbor_cache[neighbor_index].q; + while (r->next != NULL) { + r = r->next; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + neighbor_cache[neighbor_index].q = new_entry; + } + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); + result = ERR_OK; + } else { + /* the pool MEMP_ND6_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p)); + /* { result == ERR_MEM } through initialization */ + } +#else /* LWIP_ND6_QUEUEING */ + /* Queue a single packet. If an older packet is already queued, free it as per RFC. */ + if (neighbor_cache[neighbor_index].q != NULL) { + pbuf_free(neighbor_cache[neighbor_index].q); + } + neighbor_cache[neighbor_index].q = p; + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); + result = ERR_OK; +#endif /* LWIP_ND6_QUEUEING */ + } else { + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q)); + /* { result == ERR_MEM } through initialization */ + } + + return result; +} + +#if LWIP_ND6_QUEUEING +/** + * Free a complete queue of nd6 q entries + * + * @param q a queue of nd6_q_entry to free + */ +static void +nd6_free_q(struct nd6_q_entry *q) +{ + struct nd6_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ND6_QUEUE, r); + } +} +#endif /* LWIP_ND6_QUEUEING */ + +/** + * Send queued packets for a neighbor + * + * @param i the neighbor to send packets to + */ +static void +nd6_send_q(s8_t i) +{ + struct ip6_hdr *ip6hdr; + ip6_addr_t dest; +#if LWIP_ND6_QUEUEING + struct nd6_q_entry *q; +#endif /* LWIP_ND6_QUEUEING */ + + if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { + return; + } + +#if LWIP_ND6_QUEUEING + while (neighbor_cache[i].q != NULL) { + /* remember first in queue */ + q = neighbor_cache[i].q; + /* pop first item off the queue */ + neighbor_cache[i].q = q->next; + /* Get ipv6 header. */ + ip6hdr = (struct ip6_hdr *)(q->p->payload); + /* Create an aligned copy. */ + ip6_addr_set(&dest, &(ip6hdr->dest)); + /* send the queued IPv6 packet */ + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, &dest); + /* free the queued IP packet */ + pbuf_free(q->p); + /* now queue entry can be freed */ + memp_free(MEMP_ND6_QUEUE, q); + } +#else /* LWIP_ND6_QUEUEING */ + if (neighbor_cache[i].q != NULL) { + /* Get ipv6 header. */ + ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); + /* Create an aligned copy. */ + ip6_addr_set(&dest, &(ip6hdr->dest)); + /* send the queued IPv6 packet */ + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, &dest); + /* free the queued IP packet */ + pbuf_free(neighbor_cache[i].q); + neighbor_cache[i].q = NULL; + } +#endif /* LWIP_ND6_QUEUEING */ +} + +/** + * A packet is to be transmitted to a specific IPv6 destination on a specific + * interface. Check if we can find the hardware address of the next hop to use + * for the packet. If so, give the hardware address to the caller, which should + * use it to send the packet right away. Otherwise, enqueue the packet for + * later transmission while looking up the hardware address, if possible. + * + * As such, this function returns one of three different possible results: + * + * - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now. + * - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later. + * - not ERR_OK: something went wrong; forward the error upward in the stack. + * + * @param netif The lwIP network interface on which the IP packet will be sent. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ip6addr The destination IPv6 address of the packet. + * @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning + * the packet has been queued). + * @return + * - ERR_OK on success, ERR_RTE if no route was found for the packet, + * or ERR_MEM if low memory conditions prohibit sending the packet at all. + */ +err_t +nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp) +{ + s8_t i; + + /* Get next hop record. */ + i = nd6_get_next_hop_entry(ip6addr, netif); + if (i < 0) { + /* failed to get a next hop neighbor record. */ + return i; + } + + /* Now that we have a destination record, send or queue the packet. */ + if (neighbor_cache[i].state == ND6_STALE) { + /* Switch to delay state. */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; + } + /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */ + if ((neighbor_cache[i].state == ND6_REACHABLE) || + (neighbor_cache[i].state == ND6_DELAY) || + (neighbor_cache[i].state == ND6_PROBE)) { + + /* Tell the caller to send out the packet now. */ + *hwaddrp = neighbor_cache[i].lladdr; + return ERR_OK; + } + + /* We should queue packet on this interface. */ + *hwaddrp = NULL; + return nd6_queue_packet(i, q); +} + + +/** + * Get the Path MTU for a destination. + * + * @param ip6addr the destination address + * @param netif the netif on which the packet will be sent + * @return the Path MTU, if known, or the netif default MTU + */ +u16_t +nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif) +{ + s8_t i; + + i = nd6_find_destination_cache_entry(ip6addr); + if (i >= 0) { + if (destination_cache[i].pmtu > 0) { + return destination_cache[i].pmtu; + } + } + + if (netif != NULL) { + return netif->mtu; + } + + return 1280; /* Minimum MTU */ +} + + +#if LWIP_ND6_TCP_REACHABILITY_HINTS +/** + * Provide the Neighbor discovery process with a hint that a + * destination is reachable. Called by tcp_receive when ACKs are + * received or sent (as per RFC). This is useful to avoid sending + * NS messages every 30 seconds. + * + * @param ip6addr the destination address which is know to be reachable + * by an upper layer protocol (TCP) + */ +void +nd6_reachability_hint(const ip6_addr_t *ip6addr) +{ + s8_t i; + + /* Find destination in cache. */ + if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + i = nd6_cached_destination_index; + ND6_STATS_INC(nd6.cachehit); + } else { + i = nd6_find_destination_cache_entry(ip6addr); + } + if (i < 0) { + return; + } + + /* Find next hop neighbor in cache. */ + if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { + i = nd6_cached_neighbor_index; + ND6_STATS_INC(nd6.cachehit); + } else { + i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr)); + } + if (i < 0) { + return; + } + + /* For safety: don't set as reachable if we don't have a LL address yet. Misuse protection. */ + if (neighbor_cache[i].state == ND6_INCOMPLETE || neighbor_cache[i].state == ND6_NO_ENTRY) { + return; + } + + /* Set reachability state. */ + neighbor_cache[i].state = ND6_REACHABLE; + neighbor_cache[i].counter.reachable_time = reachable_time; +} +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +/** + * Remove all prefix, neighbor_cache and router entries of the specified netif. + * + * @param netif points to a network interface + */ +void +nd6_cleanup_netif(struct netif *netif) +{ + u8_t i; + s8_t router_index; + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if (prefix_list[i].netif == netif) { + prefix_list[i].netif = NULL; + prefix_list[i].flags = 0; + } + } + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (neighbor_cache[i].netif == netif) { + for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) { + if (default_router_list[router_index].neighbor_entry == &neighbor_cache[i]) { + default_router_list[router_index].neighbor_entry = NULL; + default_router_list[router_index].flags = 0; + } + } + neighbor_cache[i].isrouter = 0; + nd6_free_neighbor_cache_entry(i); + } + } +} + +#if LWIP_IPV6_MLD +/** + * The state of a local IPv6 address entry is about to change. If needed, join + * or leave the solicited-node multicast group for the address. + * + * @param netif The netif that owns the address. + * @param addr_idx The index of the address. + * @param new_state The new (IP6_ADDR_) state for the address. + */ +void +nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state) +{ + u8_t old_state, old_member, new_member; + + old_state = netif_ip6_addr_state(netif, addr_idx); + + /* Determine whether we were, and should be, a member of the solicited-node + * multicast group for this address. For tentative addresses, the group is + * not joined until the address enters the TENTATIVE_1 (or VALID) state. */ + old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_TENTATIVE); + new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_TENTATIVE); + + if (old_member != new_member) { + ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]); + + if (new_member) { + mld6_joingroup_netif(netif, &multicast_address); + } else { + mld6_leavegroup_netif(netif, &multicast_address); + } + } +} +#endif /* LWIP_IPV6_MLD */ + +#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.3/src/core/mem.c b/components/net/lwip-2.0.3/src/core/mem.c new file mode 100644 index 0000000000..db3b7cc54e --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/mem.c @@ -0,0 +1,777 @@ +/** + * @file + * Dynamic memory manager + * + * This is a lightweight replacement for the standard C library malloc(). + * + * If you want to use the standard C library malloc() instead, define + * MEM_LIBC_MALLOC to 1 in your lwipopts.h + * + * To let mem_malloc() use pools (prevents fragmentation and is much faster than + * a heap but might waste some memory), define MEM_USE_POOLS to 1, define + * MEMP_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list + * of pools like this (more pools can be added between _START and _END): + * + * Define three pools with sizes 256, 512, and 1512 bytes + * LWIP_MALLOC_MEMPOOL_START + * LWIP_MALLOC_MEMPOOL(20, 256) + * LWIP_MALLOC_MEMPOOL(10, 512) + * LWIP_MALLOC_MEMPOOL(5, 1512) + * LWIP_MALLOC_MEMPOOL_END + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" +#include "lwip/mem.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/stats.h" +#include "lwip/err.h" + +#include + +#if MEM_LIBC_MALLOC +#include /* for malloc()/free() */ +#endif + +#if MEM_LIBC_MALLOC || MEM_USE_POOLS + +/** mem_init is not used when using pools instead of a heap or using + * C library malloc(). + */ +void +mem_init(void) +{ +} + +/** mem_trim is not used when using pools instead of a heap or using + * C library malloc(): we can't free part of a pool element and the stack + * support mem_trim() to return a different pointer + */ +void* +mem_trim(void *mem, mem_size_t size) +{ + LWIP_UNUSED_ARG(size); + return mem; +} +#endif /* MEM_LIBC_MALLOC || MEM_USE_POOLS */ + +#if MEM_LIBC_MALLOC +/* lwIP heap implemented using C library malloc() */ + +/* in case C library malloc() needs extra protection, + * allow these defines to be overridden. + */ +#ifndef mem_clib_free +#define mem_clib_free free +#endif +#ifndef mem_clib_malloc +#define mem_clib_malloc malloc +#endif +#ifndef mem_clib_calloc +#define mem_clib_calloc calloc +#endif + +#if LWIP_STATS && MEM_STATS +#define MEM_LIBC_STATSHELPER_SIZE LWIP_MEM_ALIGN_SIZE(sizeof(mem_size_t)) +#else +#define MEM_LIBC_STATSHELPER_SIZE 0 +#endif + +/** + * Allocate a block of memory with a minimum of 'size' bytes. + * + * @param size is the minimum size of the requested block in bytes. + * @return pointer to allocated memory or NULL if no free memory was found. + * + * Note that the returned value must always be aligned (as defined by MEM_ALIGNMENT). + */ +void * +mem_malloc(mem_size_t size) +{ + void* ret = mem_clib_malloc(size + MEM_LIBC_STATSHELPER_SIZE); + if (ret == NULL) { + MEM_STATS_INC(err); + } else { + LWIP_ASSERT("malloc() must return aligned memory", LWIP_MEM_ALIGN(ret) == ret); +#if LWIP_STATS && MEM_STATS + *(mem_size_t*)ret = size; + ret = (u8_t*)ret + MEM_LIBC_STATSHELPER_SIZE; + MEM_STATS_INC_USED(used, size); +#endif + } + return ret; +} + +/** Put memory back on the heap + * + * @param rmem is the pointer as returned by a previous call to mem_malloc() + */ +void +mem_free(void *rmem) +{ + LWIP_ASSERT("rmem != NULL", (rmem != NULL)); + LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); +#if LWIP_STATS && MEM_STATS + rmem = (u8_t*)rmem - MEM_LIBC_STATSHELPER_SIZE; + MEM_STATS_DEC_USED(used, *(mem_size_t*)rmem); +#endif + mem_clib_free(rmem); +} + +#elif MEM_USE_POOLS + +/* lwIP heap implemented with different sized pools */ + +/** + * Allocate memory: determine the smallest pool that is big enough + * to contain an element of 'size' and get an element from that pool. + * + * @param size the size in bytes of the memory needed + * @return a pointer to the allocated memory or NULL if the pool is empty + */ +void * +mem_malloc(mem_size_t size) +{ + void *ret; + struct memp_malloc_helper *element = NULL; + memp_t poolnr; + mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + + for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) { + /* is this pool big enough to hold an element of the required size + plus a struct memp_malloc_helper that saves the pool this element came from? */ + if (required_size <= memp_pools[poolnr]->size) { + element = (struct memp_malloc_helper*)memp_malloc(poolnr); + if (element == NULL) { + /* No need to DEBUGF or ASSERT: This error is already taken care of in memp.c */ +#if MEM_USE_POOLS_TRY_BIGGER_POOL + /** Try a bigger pool if this one is empty! */ + if (poolnr < MEMP_POOL_LAST) { + continue; + } +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + MEM_STATS_INC(err); + return NULL; + } + break; + } + } + if (poolnr > MEMP_POOL_LAST) { + LWIP_ASSERT("mem_malloc(): no pool is that big!", 0); + MEM_STATS_INC(err); + return NULL; + } + + /* save the pool number this element came from */ + element->poolnr = poolnr; + /* and return a pointer to the memory directly after the struct memp_malloc_helper */ + ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + +#if MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) + /* truncating to u16_t is safe because struct memp_desc::size is u16_t */ + element->size = (u16_t)size; + MEM_STATS_INC_USED(used, element->size); +#endif /* MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) */ +#if MEMP_OVERFLOW_CHECK + /* initialize unused memory (diff between requested size and selected pool's size) */ + memset((u8_t*)ret + size, 0xcd, memp_pools[poolnr]->size - size); +#endif /* MEMP_OVERFLOW_CHECK */ + return ret; +} + +/** + * Free memory previously allocated by mem_malloc. Loads the pool number + * and calls memp_free with that pool number to put the element back into + * its pool + * + * @param rmem the memory element to free + */ +void +mem_free(void *rmem) +{ + struct memp_malloc_helper *hmem; + + LWIP_ASSERT("rmem != NULL", (rmem != NULL)); + LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); + + /* get the original struct memp_malloc_helper */ + /* cast through void* to get rid of alignment warnings */ + hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))); + + LWIP_ASSERT("hmem != NULL", (hmem != NULL)); + LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem))); + LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX)); + + MEM_STATS_DEC_USED(used, hmem->size); +#if MEMP_OVERFLOW_CHECK + { + u16_t i; + LWIP_ASSERT("MEM_USE_POOLS: invalid chunk size", + hmem->size <= memp_pools[hmem->poolnr]->size); + /* check that unused memory remained untouched (diff between requested size and selected pool's size) */ + for (i = hmem->size; i < memp_pools[hmem->poolnr]->size; i++) { + u8_t data = *((u8_t*)rmem + i); + LWIP_ASSERT("MEM_USE_POOLS: mem overflow detected", data == 0xcd); + } + } +#endif /* MEMP_OVERFLOW_CHECK */ + + /* and put it in the pool we saved earlier */ + memp_free(hmem->poolnr, hmem); +} + +#else /* MEM_USE_POOLS */ +/* lwIP replacement for your libc malloc() */ + +/** + * The heap is made up as a list of structs of this type. + * This does not have to be aligned since for getting its size, + * we only use the macro SIZEOF_STRUCT_MEM, which automatically aligns. + */ +struct mem { + /** index (-> ram[next]) of the next struct */ + mem_size_t next; + /** index (-> ram[prev]) of the previous struct */ + mem_size_t prev; + /** 1: this area is used; 0: this area is unused */ + u8_t used; +}; + +/** All allocated blocks will be MIN_SIZE bytes big, at least! + * MIN_SIZE can be overridden to suit your needs. Smaller values save space, + * larger values could prevent too small blocks to fragment the RAM too much. */ +#ifndef MIN_SIZE +#define MIN_SIZE 12 +#endif /* MIN_SIZE */ +/* some alignment macros: we define them here for better source code layout */ +#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE) +#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) +#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) + +/** If you want to relocate the heap to external memory, simply define + * LWIP_RAM_HEAP_POINTER as a void-pointer to that location. + * If so, make sure the memory at that location is big enough (see below on + * how that space is calculated). */ +#ifndef LWIP_RAM_HEAP_POINTER +/** the heap. we need one struct mem at the end and some room for alignment */ +LWIP_DECLARE_MEMORY_ALIGNED(ram_heap, MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM)); +#define LWIP_RAM_HEAP_POINTER ram_heap +#endif /* LWIP_RAM_HEAP_POINTER */ + +/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */ +static u8_t *ram; +/** the last entry, always unused! */ +static struct mem *ram_end; +/** pointer to the lowest free block, this is used for faster search */ +static struct mem *lfree; + +/** concurrent access protection */ +#if !NO_SYS +static sys_mutex_t mem_mutex; +#endif + +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + +static volatile u8_t mem_free_count; + +/* Allow mem_free from other (e.g. interrupt) context */ +#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free) +#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free) +#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free) +#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc) + +#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + +/* Protect the heap only by using a semaphore */ +#define LWIP_MEM_FREE_DECL_PROTECT() +#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex) +#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex) +/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ +#define LWIP_MEM_ALLOC_DECL_PROTECT() +#define LWIP_MEM_ALLOC_PROTECT() +#define LWIP_MEM_ALLOC_UNPROTECT() + +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + +/** + * "Plug holes" by combining adjacent empty struct mems. + * After this function is through, there should not exist + * one empty struct mem pointing to another empty struct mem. + * + * @param mem this points to a struct mem which just has been freed + * @internal this function is only called by mem_free() and mem_trim() + * + * This assumes access to the heap is protected by the calling function + * already. + */ +static void +plug_holes(struct mem *mem) +{ + struct mem *nmem; + struct mem *pmem; + + LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram); + LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end); + LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0); + + /* plug hole forward */ + LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); + + nmem = (struct mem *)(void *)&ram[mem->next]; + if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { + /* if mem->next is unused and not end of ram, combine mem and mem->next */ + if (lfree == nmem) { + lfree = mem; + } + mem->next = nmem->next; + ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram); + } + + /* plug hole backward */ + pmem = (struct mem *)(void *)&ram[mem->prev]; + if (pmem != mem && pmem->used == 0) { + /* if mem->prev is unused, combine mem and mem->prev */ + if (lfree == mem) { + lfree = pmem; + } + pmem->next = mem->next; + ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram); + } +} + +/** + * Zero the heap and initialize start, end and lowest-free + */ +void +mem_init(void) +{ + struct mem *mem; + + LWIP_ASSERT("Sanity check alignment", + (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); + + /* align the heap */ + ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER); + /* initialize the start of the heap */ + mem = (struct mem *)(void *)ram; + mem->next = MEM_SIZE_ALIGNED; + mem->prev = 0; + mem->used = 0; + /* initialize the end of the heap */ + ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED]; + ram_end->used = 1; + ram_end->next = MEM_SIZE_ALIGNED; + ram_end->prev = MEM_SIZE_ALIGNED; + + /* initialize the lowest-free pointer to the start of the heap */ + lfree = (struct mem *)(void *)ram; + + MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); + + if (sys_mutex_new(&mem_mutex) != ERR_OK) { + LWIP_ASSERT("failed to create mem_mutex", 0); + } +} + +/** + * Put a struct mem back on the heap + * + * @param rmem is the data portion of a struct mem as returned by a previous + * call to mem_malloc() + */ +void +mem_free(void *rmem) +{ + struct mem *mem; + LWIP_MEM_FREE_DECL_PROTECT(); + + if (rmem == NULL) { + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n")); + return; + } + LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); + + LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return; + } + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + /* Get the corresponding struct mem ... */ + /* cast through void* to get rid of alignment warnings */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... which has to be in a used state ... */ + LWIP_ASSERT("mem_free: mem->used", mem->used); + /* ... and is now unused. */ + mem->used = 0; + + if (mem < lfree) { + /* the newly freed struct is now the lowest */ + lfree = mem; + } + + MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram))); + + /* finally, see if prev or next are free also */ + plug_holes(mem); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); +} + +/** + * Shrink memory returned by mem_malloc(). + * + * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked + * @param newsize required size after shrinking (needs to be smaller than or + * equal to the previous size) + * @return for compatibility reasons: is always == rmem, at the moment + * or NULL if newsize is > old size, in which case rmem is NOT touched + * or freed! + */ +void * +mem_trim(void *rmem, mem_size_t newsize) +{ + mem_size_t size; + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; + /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */ + LWIP_MEM_FREE_DECL_PROTECT(); + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + newsize = LWIP_MEM_ALIGN_SIZE(newsize); + + if (newsize < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + newsize = MIN_SIZE_ALIGNED; + } + + if (newsize > MEM_SIZE_ALIGNED) { + return NULL; + } + + LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return rmem; + } + /* Get the corresponding struct mem ... */ + /* cast through void* to get rid of alignment warnings */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... and its offset pointer */ + ptr = (mem_size_t)((u8_t *)mem - ram); + + size = mem->next - ptr - SIZEOF_STRUCT_MEM; + LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size); + if (newsize > size) { + /* not supported */ + return NULL; + } + if (newsize == size) { + /* No change in size, simply return */ + return rmem; + } + + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + + mem2 = (struct mem *)(void *)&ram[mem->next]; + if (mem2->used == 0) { + /* The next struct is unused, we can simply move it at little */ + mem_size_t next; + /* remember the old next pointer */ + next = mem2->next; + /* create new struct mem which is moved directly after the shrinked mem */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + if (lfree == mem2) { + lfree = (struct mem *)(void *)&ram[ptr2]; + } + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + /* restore the next pointer */ + mem2->next = next; + /* link it back to mem */ + mem2->prev = ptr; + /* link mem to it */ + mem->next = ptr2; + /* last thing to restore linked list: as we have moved mem2, + * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not + * the end of the heap */ + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* no need to plug holes, we've already done that */ + } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) { + /* Next struct is used but there's room for another struct mem with + * at least MIN_SIZE_ALIGNED of data. + * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem + * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED'). + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + mem2 = (struct mem *)(void *)&ram[ptr2]; + if (mem2 < lfree) { + lfree = mem2; + } + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + mem->next = ptr2; + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* the original mem->next is used, so no need to plug holes! */ + } + /* else { + next struct mem is used but size between mem and mem2 is not big enough + to create another struct mem + -> don't do anyhting. + -> the remaining space stays unused since it is too small + } */ +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); + return rmem; +} + +/** + * Allocate a block of memory with a minimum of 'size' bytes. + * + * @param size is the minimum size of the requested block in bytes. + * @return pointer to allocated memory or NULL if no free memory was found. + * + * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). + */ +void * +mem_malloc(mem_size_t size) +{ + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + u8_t local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_ALLOC_DECL_PROTECT(); + + if (size == 0) { + return NULL; + } + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + size = LWIP_MEM_ALIGN_SIZE(size); + + if (size < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + size = MIN_SIZE_ALIGNED; + } + + if (size > MEM_SIZE_ALIGNED) { + return NULL; + } + + /* protect the heap from concurrent access */ + sys_mutex_lock(&mem_mutex); + LWIP_MEM_ALLOC_PROTECT(); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* run as long as a mem_free disturbed mem_malloc or mem_trim */ + do { + local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + /* Scan through the heap searching for a free block that is big enough, + * beginning with the lowest free block. + */ + for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size; + ptr = ((struct mem *)(void *)&ram[ptr])->next) { + mem = (struct mem *)(void *)&ram[ptr]; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* allow mem_free or mem_trim to run */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem. */ + local_mem_free_count = 1; + break; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + if ((!mem->used) && + (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { + /* mem is not used and at least perfect fit is possible: + * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ + + if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { + /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing + * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') + * -> split large block, create empty remainder, + * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if + * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, + * struct mem would fit in but no data between mem2 and mem2->next + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory + */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + size; + /* create mem2 struct */ + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + /* and insert it between mem and mem->next */ + mem->next = ptr2; + mem->used = 1; + + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); + } else { + /* (a mem2 struct does no fit into the user data space of mem and mem->next will always + * be used at this point: if not we have 2 unused structs in a row, plug_holes should have + * take care of this). + * -> near fit or exact fit: do not split, no mem2 creation + * also can't move mem->next directly behind mem, since mem->next + * will always be used at this point! + */ + mem->used = 1; + MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram)); + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +mem_malloc_adjust_lfree: +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + if (mem == lfree) { + struct mem *cur = lfree; + /* Find next free block after mem and update lowest free pointer */ + while (cur->used && cur != ram_end) { +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* prevent high interrupt latency... */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem or lfree. */ + goto mem_malloc_adjust_lfree; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + cur = (struct mem *)(void *)&ram[cur->next]; + } + lfree = cur; + LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); + } + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", + (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); + LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", + ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); + LWIP_ASSERT("mem_malloc: sanity check alignment", + (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); + + return (u8_t *)mem + SIZEOF_STRUCT_MEM; + } + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* if we got interrupted by a mem_free, try again */ + } while (local_mem_free_count != 0); +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); + MEM_STATS_INC(err); + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + return NULL; +} + +#endif /* MEM_USE_POOLS */ + +#if MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) +void * +mem_calloc(mem_size_t count, mem_size_t size) +{ + return mem_clib_calloc(count, size); +} + +#else /* MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) */ +/** + * Contiguously allocates enough space for count objects that are size bytes + * of memory each and returns a pointer to the allocated memory. + * + * The allocated memory is filled with bytes of value zero. + * + * @param count number of objects to allocate + * @param size size of the objects to allocate + * @return pointer to allocated memory / NULL pointer if there is an error + */ +void * +mem_calloc(mem_size_t count, mem_size_t size) +{ + void *p; + + /* allocate 'count' objects of size 'size' */ + p = mem_malloc(count * size); + if (p) { + /* zero the memory */ + memset(p, 0, (size_t)count * (size_t)size); + } + return p; +} +#endif /* MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) */ diff --git a/components/net/lwip-2.0.3/src/core/memp.c b/components/net/lwip-2.0.3/src/core/memp.c new file mode 100644 index 0000000000..58fab1a20a --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/memp.c @@ -0,0 +1,496 @@ +/** + * @file + * Dynamic pool memory manager + * + * lwIP has dedicated pools for many structures (netconn, protocol control blocks, + * packet buffers, ...). All these pools are managed here. + * + * @defgroup mempool Memory pools + * @ingroup infrastructure + * Custom memory pools + + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/memp.h" +#include "lwip/sys.h" +#include "lwip/stats.h" + +#include + +/* Make sure we include everything we need for size calculation required by memp_std.h */ +#include "lwip/pbuf.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/ip4_frag.h" +#include "lwip/netbuf.h" +#include "lwip/api.h" +#include "lwip/priv/tcpip_priv.h" +#include "lwip/priv/api_msg.h" +#include "lwip/sockets.h" +#include "lwip/netifapi.h" +#include "lwip/etharp.h" +#include "lwip/igmp.h" +#include "lwip/timeouts.h" +/* needed by default MEMP_NUM_SYS_TIMEOUT */ +#include "netif/ppp/ppp_opts.h" +#include "lwip/netdb.h" +#include "lwip/dns.h" +#include "lwip/priv/nd6_priv.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" + +#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) +#include "lwip/priv/memp_std.h" + +const struct memp_desc* const memp_pools[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name, +#include "lwip/priv/memp_std.h" +}; + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +#if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2 +#undef MEMP_OVERFLOW_CHECK +/* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */ +#define MEMP_OVERFLOW_CHECK 1 +#endif + +#if MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC +/** + * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". + */ +static int +memp_sanity(const struct memp_desc *desc) +{ + struct memp *t, *h; + + t = *desc->tab; + if (t != NULL) { + for (h = t->next; (t != NULL) && (h != NULL); t = t->next, + h = ((h->next != NULL) ? h->next->next : NULL)) { + if (t == h) { + return 0; + } + } + } + + return 1; +} +#endif /* MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC */ + +#if MEMP_OVERFLOW_CHECK +/** + * Check if a memp element was victim of an overflow + * (e.g. the restricted area after it has been altered) + * + * @param p the memp element to check + * @param desc the pool p comes from + */ +static void +memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc) +{ +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + u16_t k; + u8_t *m; + m = (u8_t*)p + MEMP_SIZE + desc->size; + for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp overflow in pool "; + strcat(errstr, desc->desc); + LWIP_ASSERT(errstr, 0); + } + } +#else /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ +} + +/** + * Check if a memp element was victim of an underflow + * (e.g. the restricted area before it has been altered) + * + * @param p the memp element to check + * @param desc the pool p comes from + */ +static void +memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc) +{ +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + u16_t k; + u8_t *m; + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp underflow in pool "; + strcat(errstr, desc->desc); + LWIP_ASSERT(errstr, 0); + } + } +#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ +} + +/** + * Initialize the restricted area of on memp element. + */ +static void +memp_overflow_init_element(struct memp *p, const struct memp_desc *desc) +{ +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + u8_t *m; +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); +#endif +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + desc->size; + memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); +#endif +#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ +} + +#if MEMP_OVERFLOW_CHECK >= 2 +/** + * Do an overflow check for all elements in every pool. + * + * @see memp_overflow_check_element for a description of the check + */ +static void +memp_overflow_check_all(void) +{ + u16_t i, j; + struct memp *p; + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + + for (i = 0; i < MEMP_MAX; ++i) { + p = (struct memp*)LWIP_MEM_ALIGN(memp_pools[i]->base); + for (j = 0; j < memp_pools[i]->num; ++j) { + memp_overflow_check_element_overflow(p, memp_pools[i]); + memp_overflow_check_element_underflow(p, memp_pools[i]); + p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED)); + } + } + SYS_ARCH_UNPROTECT(old_level); +} +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ +#endif /* MEMP_OVERFLOW_CHECK */ + +/** + * Initialize custom memory pool. + * Related functions: memp_malloc_pool, memp_free_pool + * + * @param desc pool to initialize + */ +void +memp_init_pool(const struct memp_desc *desc) +{ +#if MEMP_MEM_MALLOC + LWIP_UNUSED_ARG(desc); +#else + int i; + struct memp *memp; + + *desc->tab = NULL; + memp = (struct memp*)LWIP_MEM_ALIGN(desc->base); + /* create a linked list of memp elements */ + for (i = 0; i < desc->num; ++i) { + memp->next = *desc->tab; + *desc->tab = memp; +#if MEMP_OVERFLOW_CHECK + memp_overflow_init_element(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + /* cast through void* to get rid of alignment warnings */ + memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size +#if MEMP_OVERFLOW_CHECK + + MEMP_SANITY_REGION_AFTER_ALIGNED +#endif + ); + } +#if MEMP_STATS + desc->stats->avail = desc->num; +#endif /* MEMP_STATS */ +#endif /* !MEMP_MEM_MALLOC */ + +#if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) + desc->stats->name = desc->desc; +#endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */ +} + +/** + * Initializes lwIP built-in pools. + * Related functions: memp_malloc, memp_free + * + * Carves out memp_memory into linked lists for each pool-type. + */ +void +memp_init(void) +{ + u16_t i; + + /* for every pool: */ + for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) { + memp_init_pool(memp_pools[i]); + +#if LWIP_STATS && MEMP_STATS + lwip_stats.memp[i] = memp_pools[i]->stats; +#endif + } + +#if MEMP_OVERFLOW_CHECK >= 2 + /* check everything a first time to see if it worked */ + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ +} + +static void* +#if !MEMP_OVERFLOW_CHECK +do_memp_malloc_pool(const struct memp_desc *desc) +#else +do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) +#endif +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + +#if MEMP_MEM_MALLOC + memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size)); + SYS_ARCH_PROTECT(old_level); +#else /* MEMP_MEM_MALLOC */ + SYS_ARCH_PROTECT(old_level); + + memp = *desc->tab; +#endif /* MEMP_MEM_MALLOC */ + + if (memp != NULL) { +#if !MEMP_MEM_MALLOC +#if MEMP_OVERFLOW_CHECK == 1 + memp_overflow_check_element_overflow(memp, desc); + memp_overflow_check_element_underflow(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + + *desc->tab = memp->next; +#if MEMP_OVERFLOW_CHECK + memp->next = NULL; +#endif /* MEMP_OVERFLOW_CHECK */ +#endif /* !MEMP_MEM_MALLOC */ +#if MEMP_OVERFLOW_CHECK + memp->file = file; + memp->line = line; +#if MEMP_MEM_MALLOC + memp_overflow_init_element(memp, desc); +#endif /* MEMP_MEM_MALLOC */ +#endif /* MEMP_OVERFLOW_CHECK */ + LWIP_ASSERT("memp_malloc: memp properly aligned", + ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); +#if MEMP_STATS + desc->stats->used++; + if (desc->stats->used > desc->stats->max) { + desc->stats->max = desc->stats->used; + } +#endif + SYS_ARCH_UNPROTECT(old_level); + /* cast through u8_t* to get rid of alignment warnings */ + return ((u8_t*)memp + MEMP_SIZE); + } else { + LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc)); +#if MEMP_STATS + desc->stats->err++; +#endif + } + + SYS_ARCH_UNPROTECT(old_level); + return NULL; +} + +/** + * Get an element from a custom pool. + * + * @param desc the pool to get an element from + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc_pool(const struct memp_desc *desc) +#else +memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) +#endif +{ + LWIP_ASSERT("invalid pool desc", desc != NULL); + if (desc == NULL) { + return NULL; + } + +#if !MEMP_OVERFLOW_CHECK + return do_memp_malloc_pool(desc); +#else + return do_memp_malloc_pool_fn(desc, file, line); +#endif +} + +/** + * Get an element from a specific pool. + * + * @param type the pool to get an element from + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc(memp_t type) +#else +memp_malloc_fn(memp_t type, const char* file, const int line) +#endif +{ + void *memp; + LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); + +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + +#if !MEMP_OVERFLOW_CHECK + memp = do_memp_malloc_pool(memp_pools[type]); +#else + memp = do_memp_malloc_pool_fn(memp_pools[type], file, line); +#endif + + return memp; +} + +static void +do_memp_free_pool(const struct memp_desc* desc, void *mem) +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ASSERT("memp_free: mem properly aligned", + ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); + + /* cast through void* to get rid of alignment warnings */ + memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); + + SYS_ARCH_PROTECT(old_level); + +#if MEMP_OVERFLOW_CHECK == 1 + memp_overflow_check_element_overflow(memp, desc); + memp_overflow_check_element_underflow(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + +#if MEMP_STATS + desc->stats->used--; +#endif + +#if MEMP_MEM_MALLOC + LWIP_UNUSED_ARG(desc); + SYS_ARCH_UNPROTECT(old_level); + mem_free(memp); +#else /* MEMP_MEM_MALLOC */ + memp->next = *desc->tab; + *desc->tab = memp; + +#if MEMP_SANITY_CHECK + LWIP_ASSERT("memp sanity", memp_sanity(desc)); +#endif /* MEMP_SANITY_CHECK */ + + SYS_ARCH_UNPROTECT(old_level); +#endif /* !MEMP_MEM_MALLOC */ +} + +/** + * Put a custom pool element back into its pool. + * + * @param desc the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free_pool(const struct memp_desc* desc, void *mem) +{ + LWIP_ASSERT("invalid pool desc", desc != NULL); + if ((desc == NULL) || (mem == NULL)) { + return; + } + + do_memp_free_pool(desc, mem); +} + +/** + * Put an element back into its pool. + * + * @param type the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free(memp_t type, void *mem) +{ +#ifdef LWIP_HOOK_MEMP_AVAILABLE + struct memp *old_first; +#endif + + LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;); + + if (mem == NULL) { + return; + } + +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + +#ifdef LWIP_HOOK_MEMP_AVAILABLE + old_first = *memp_pools[type]->tab; +#endif + + do_memp_free_pool(memp_pools[type], mem); + +#ifdef LWIP_HOOK_MEMP_AVAILABLE + if (old_first == NULL) { + LWIP_HOOK_MEMP_AVAILABLE(type); + } +#endif +} diff --git a/components/net/lwip-2.0.3/src/core/netif.c b/components/net/lwip-2.0.3/src/core/netif.c new file mode 100644 index 0000000000..d912cb1f11 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/netif.c @@ -0,0 +1,1318 @@ +/** + * @file + * lwIP network interface abstraction + * + * @defgroup netif Network interface (NETIF) + * @ingroup callbackstyle_api + * + * @defgroup netif_ip4 IPv4 address handling + * @ingroup netif + * + * @defgroup netif_ip6 IPv6 address handling + * @ingroup netif + * + * @defgroup netif_cd Client data handling + * Store data (void*) on a netif for application usage. + * @see @ref LWIP_NUM_NETIF_CLIENT_DATA + * @ingroup netif + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +#include "lwip/opt.h" + +#include + +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/udp.h" +#include "lwip/raw.h" +#include "lwip/snmp.h" +#include "lwip/igmp.h" +#include "lwip/etharp.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/ip.h" +#if ENABLE_LOOPBACK +#if LWIP_NETIF_LOOPBACK_MULTITHREADING +#include "lwip/tcpip.h" +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#include "netif/ethernet.h" + +#if LWIP_AUTOIP +#include "lwip/autoip.h" +#endif /* LWIP_AUTOIP */ +#if LWIP_DHCP +#include "lwip/dhcp.h" +#endif /* LWIP_DHCP */ +#if LWIP_IPV6_DHCP6 +#include "lwip/dhcp6.h" +#endif /* LWIP_IPV6_DHCP6 */ +#if LWIP_IPV6_MLD +#include "lwip/mld6.h" +#endif /* LWIP_IPV6_MLD */ +#if LWIP_IPV6 +#include "lwip/nd6.h" +#endif + +#include + +#ifdef RT_USING_NETDEV +#include "lwip/netdb.h" +#include +#endif /* RT_USING_NETDEV */ + +#if LWIP_NETIF_STATUS_CALLBACK +#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) +#else +#define NETIF_STATUS_CALLBACK(n) +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) +#else +#define NETIF_LINK_CALLBACK(n) +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +struct netif *netif_list; +struct netif *netif_default; + +static u8_t netif_num; + +#if LWIP_NUM_NETIF_CLIENT_DATA > 0 +static u8_t netif_client_id; +#endif + +#define NETIF_REPORT_TYPE_IPV4 0x01 +#define NETIF_REPORT_TYPE_IPV6 0x02 +static void netif_issue_reports(struct netif* netif, u8_t report_type); + +#if LWIP_IPV6 +static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr); +#endif /* LWIP_IPV6 */ + +#if LWIP_HAVE_LOOPIF +#if LWIP_IPV4 +static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr); +#endif +#if LWIP_IPV6 +static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr); +#endif + + +static struct netif loop_netif; + +/** + * Initialize a lwip network interface structure for a loopback interface + * + * @param netif the lwip network interface structure for this loopif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + */ +static err_t +netif_loopif_init(struct netif *netif) +{ + /* initialize the snmp variables and counters inside the struct netif + * ifSpeed: no assumption can be made! + */ + MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0); + + netif->name[0] = 'l'; + netif->name[1] = 'o'; +#if LWIP_IPV4 + netif->output = netif_loop_output_ipv4; +#endif +#if LWIP_IPV6 + netif->output_ip6 = netif_loop_output_ipv6; +#endif +#if LWIP_LOOPIF_MULTICAST + netif->flags |= NETIF_FLAG_IGMP; +#endif + return ERR_OK; +} +#endif /* LWIP_HAVE_LOOPIF */ + +void +netif_init(void) +{ +#if LWIP_HAVE_LOOPIF +#if LWIP_IPV4 +#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw, + ip4_addr_t loop_ipaddr, loop_netmask, loop_gw; + IP4_ADDR(&loop_gw, 127,0,0,1); + IP4_ADDR(&loop_ipaddr, 127,0,0,1); + IP4_ADDR(&loop_netmask, 255,0,0,0); +#else /* LWIP_IPV4 */ +#define LOOPIF_ADDRINIT +#endif /* LWIP_IPV4 */ + +#if NO_SYS + netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); +#else /* NO_SYS */ + netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); +#endif /* NO_SYS */ + +#if LWIP_IPV6 + IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL); + loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; +#endif /* LWIP_IPV6 */ + + netif_set_link_up(&loop_netif); + netif_set_up(&loop_netif); + +#endif /* LWIP_HAVE_LOOPIF */ +} + +/** + * @ingroup lwip_nosys + * Forwards a received packet for input processing with + * ethernet_input() or ip_input() depending on netif flags. + * Don't call directly, pass to netif_add() and call + * netif->input(). + * Only works if the netif driver correctly sets + * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag! + */ +err_t +netif_input(struct pbuf *p, struct netif *inp) +{ +#if LWIP_ETHERNET + if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { + return ethernet_input(p, inp); + } else +#endif /* LWIP_ETHERNET */ + return ip_input(p, inp); +} + +/** + * @ingroup netif + * Add a network interface to the list of lwIP netifs. + * + * @param netif a pre-allocated netif structure + * @param ipaddr IP address for the new netif + * @param netmask network mask for the new netif + * @param gw default gateway IP address for the new netif + * @param state opaque data passed to the new netif + * @param init callback function that initializes the interface + * @param input callback function that is called to pass + * ingress packets up in the protocol layer stack.\n + * It is recommended to use a function that passes the input directly + * to the stack (netif_input(), NO_SYS=1 mode) or via sending a + * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n + * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET + * to decide whether to forward to ethernet_input() or ip_input(). + * In other words, the functions only work when the netif + * driver is implemented correctly!\n + * Most members of struct netif should be be initialized by the + * netif init function = netif driver (init parameter of this function).\n + * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after + * setting the MAC address in struct netif.hwaddr + * (IPv6 requires a link-local address). + * + * @return netif, or NULL if failed. + */ +struct netif * +netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input) +{ +#if LWIP_IPV6 + s8_t i; +#endif + + LWIP_ASSERT("No init function given", init != NULL); + + /* reset new interface configuration state */ +#if LWIP_IPV4 + ip_addr_set_zero_ip4(&netif->ip_addr); + ip_addr_set_zero_ip4(&netif->netmask); + ip_addr_set_zero_ip4(&netif->gw); +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + ip_addr_set_zero_ip6(&netif->ip6_addr[i]); + netif->ip6_addr_state[i] = IP6_ADDR_INVALID; + } + netif->output_ip6 = netif_null_output_ip6; +#endif /* LWIP_IPV6 */ + NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); + netif->flags = 0; +#ifdef netif_get_client_data + memset(netif->client_data, 0, sizeof(netif->client_data)); +#endif /* LWIP_NUM_NETIF_CLIENT_DATA */ +#if LWIP_IPV6_AUTOCONFIG + /* IPv6 address autoconfiguration not enabled by default */ + netif->ip6_autoconfig_enabled = 0; +#endif /* LWIP_IPV6_AUTOCONFIG */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ +#if LWIP_NETIF_STATUS_CALLBACK + netif->status_callback = NULL; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + netif->link_callback = NULL; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_IGMP + netif->igmp_mac_filter = NULL; +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + netif->mld_mac_filter = NULL; +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#if ENABLE_LOOPBACK + netif->loop_first = NULL; + netif->loop_last = NULL; +#endif /* ENABLE_LOOPBACK */ + + /* remember netif specific state information data */ + netif->state = state; + netif->num = netif_num++; + netif->input = input; + + NETIF_SET_HWADDRHINT(netif, NULL); +#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS + netif->loop_cnt_current = 0; +#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ + +#if LWIP_IPV4 + netif_set_addr(netif, ipaddr, netmask, gw); +#endif /* LWIP_IPV4 */ + + /* call user specified initialization function for netif */ + if (init(netif) != ERR_OK) { + return NULL; + } + + /* add this netif to the list */ + netif->next = netif_list; + netif_list = netif; + mib2_netif_added(netif); + +#if LWIP_IGMP + /* start IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_start(netif); + } +#endif /* LWIP_IGMP */ + + LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", + netif->name[0], netif->name[1])); +#if LWIP_IPV4 + LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); + ip4_addr_debug_print(NETIF_DEBUG, ipaddr); + LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); + ip4_addr_debug_print(NETIF_DEBUG, netmask); + LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); + ip4_addr_debug_print(NETIF_DEBUG, gw); +#endif /* LWIP_IPV4 */ + LWIP_DEBUGF(NETIF_DEBUG, ("\n")); + return netif; +} + +#if LWIP_IPV4 +/** + * @ingroup netif_ip4 + * Change IP address configuration for a network interface (including netmask + * and default gateway). + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * @param netmask the new netmask + * @param gw the new default gateway + */ +void +netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, + const ip4_addr_t *gw) +{ + if (ip4_addr_isany(ipaddr)) { + /* when removing an address, we have to remove it *before* changing netmask/gw + to ensure that tcp RST segment can be sent correctly */ + netif_set_ipaddr(netif, ipaddr); + netif_set_netmask(netif, netmask); + netif_set_gw(netif, gw); + } else { + netif_set_netmask(netif, netmask); + netif_set_gw(netif, gw); + /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ + netif_set_ipaddr(netif, ipaddr); + } +} +#endif /* LWIP_IPV4*/ + +/** + * @ingroup netif + * Remove a network interface from the list of lwIP netifs. + * + * @param netif the network interface to remove + */ +void +netif_remove(struct netif *netif) +{ +#if LWIP_IPV6 + int i; +#endif + + if (netif == NULL) { + return; + } + +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); +#endif /* LWIP_RAW */ + } + +#if LWIP_IGMP + /* stop IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_stop(netif); + } +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4*/ + +#if LWIP_IPV6 + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); +#endif /* LWIP_RAW */ + } + } +#if LWIP_IPV6_MLD + /* stop MLD processing */ + mld6_stop(netif); +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ + if (netif_is_up(netif)) { + /* set netif down before removing (call callback function) */ + netif_set_down(netif); + } + + mib2_remove_ip4(netif); + + /* this netif is default? */ + if (netif_default == netif) { + /* reset default netif */ + netif_set_default(NULL); + } + /* is it the first netif? */ + if (netif_list == netif) { + netif_list = netif->next; + } else { + /* look for netif further down the list */ + struct netif * tmp_netif; + for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) { + if (tmp_netif->next == netif) { + tmp_netif->next = netif->next; + break; + } + } + if (tmp_netif == NULL) { + return; /* netif is not on the list */ + } + } + mib2_netif_removed(netif); +#if LWIP_NETIF_REMOVE_CALLBACK + if (netif->remove_callback) { + netif->remove_callback(netif); + } +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); +} + +/** + * @ingroup netif + * Find a network interface by searching for its name + * + * @param name the name of the netif (like netif->name) plus concatenated number + * in ascii representation (e.g. 'en0') + */ +struct netif * +netif_find(const char *name) +{ + struct netif *netif; + u8_t num; + + if (name == NULL) { + return NULL; + } + + num = (u8_t)(name[2] - '0'); + + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (num == netif->num && + name[0] == netif->name[0] && + name[1] == netif->name[1]) { + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); + return netif; + } + } + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); + return NULL; +} + +#if LWIP_IPV4 +/** + * @ingroup netif_ip4 + * Change the IP address of a network interface + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * + * @note call netif_set_addr() if you also want to change netmask and + * default gateway + */ +void +netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) +{ + ip_addr_t new_addr; + *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4); + IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); + + /* address is actually being changed? */ + if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) { + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); +#endif /* LWIP_RAW */ + + mib2_remove_ip4(netif); + mib2_remove_route_ip4(0, netif); + /* set new IP address to netif */ + ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); + IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); + mib2_add_ip4(netif); + mib2_add_route_ip4(0, netif); + + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); + + NETIF_STATUS_CALLBACK(netif); + +#ifdef RT_USING_NETDEV + /* rt-thread sal network interface device set IP address operations */ + netdev_low_level_set_ipaddr(netdev_get_by_name(netif->name), &netif->ip_addr); +#endif /* RT_USING_NETDEV */ + } + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(netif_ip4_addr(netif)), + ip4_addr2_16(netif_ip4_addr(netif)), + ip4_addr3_16(netif_ip4_addr(netif)), + ip4_addr4_16(netif_ip4_addr(netif)))); +} + +/** + * @ingroup netif_ip4 + * Change the default gateway for a network interface + * + * @param netif the network interface to change + * @param gw the new default gateway + * + * @note call netif_set_addr() if you also want to change ip address and netmask + */ +void +netif_set_gw(struct netif *netif, const ip4_addr_t *gw) +{ + ip4_addr_set(ip_2_ip4(&netif->gw), gw); + IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(netif_ip4_gw(netif)), + ip4_addr2_16(netif_ip4_gw(netif)), + ip4_addr3_16(netif_ip4_gw(netif)), + ip4_addr4_16(netif_ip4_gw(netif)))); + +#ifdef RT_USING_NETDEV + /* rt_thread network interface device set gateway address */ + netdev_low_level_set_gw(netdev_get_by_name(netif->name), &netif->gw); +#endif /* RT_USING_NETDEV */ +} + +/** + * @ingroup netif_ip4 + * Change the netmask of a network interface + * + * @param netif the network interface to change + * @param netmask the new netmask + * + * @note call netif_set_addr() if you also want to change ip address and + * default gateway + */ +void +netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) +{ + mib2_remove_route_ip4(0, netif); + /* set new netmask to netif */ + ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); + IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); + mib2_add_route_ip4(0, netif); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(netif_ip4_netmask(netif)), + ip4_addr2_16(netif_ip4_netmask(netif)), + ip4_addr3_16(netif_ip4_netmask(netif)), + ip4_addr4_16(netif_ip4_netmask(netif)))); + +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set netmask address */ + netdev_low_level_set_netmask(netdev_get_by_name(netif->name), &netif->netmask); +#endif /* RT_USING_NETDEV */ +} +#endif /* LWIP_IPV4 */ + +/** + * @ingroup netif + * Set a network interface as the default network interface + * (used to output all packets for which no specific route is found) + * + * @param netif the default network interface + */ +void +netif_set_default(struct netif *netif) +{ + if (netif == NULL) { + /* remove default route */ + mib2_remove_route_ip4(1, netif); + } else { + /* install default route */ + mib2_add_route_ip4(1, netif); + } + netif_default = netif; + LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", + netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); +} + +/** + * @ingroup netif + * Bring an interface up, available for processing + * traffic. + */ +void +netif_set_up(struct netif *netif) +{ + if (!(netif->flags & NETIF_FLAG_UP)) { + netif->flags |= NETIF_FLAG_UP; + + MIB2_COPY_SYSUPTIME_TO(&netif->ts); + + NETIF_STATUS_CALLBACK(netif); + + if (netif->flags & NETIF_FLAG_LINK_UP) { + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); + } + +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set up status */ + netdev_low_level_set_status(netdev_get_by_name(netif->name), RT_TRUE); +#endif /* RT_USING_NETDEV */ + } +} + +/** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change + */ +static void +netif_issue_reports(struct netif* netif, u8_t report_type) +{ +#if LWIP_IPV4 + if ((report_type & NETIF_REPORT_TYPE_IPV4) && + !ip4_addr_isany_val(*netif_ip4_addr(netif))) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & (NETIF_FLAG_ETHARP)) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups(netif); + } +#endif /* LWIP_IGMP */ + } +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 + if (report_type & NETIF_REPORT_TYPE_IPV6) { +#if LWIP_IPV6_MLD + /* send mld memberships */ + mld6_report_groups(netif); +#endif /* LWIP_IPV6_MLD */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* Send Router Solicitation messages. */ + netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + } +#endif /* LWIP_IPV6 */ +} + +/** + * @ingroup netif + * Bring an interface down, disabling any traffic processing. + */ +void +netif_set_down(struct netif *netif) +{ + if (netif->flags & NETIF_FLAG_UP) { + netif->flags &= ~NETIF_FLAG_UP; + MIB2_COPY_SYSUPTIME_TO(&netif->ts); + +#if LWIP_IPV4 && LWIP_ARP + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_cleanup_netif(netif); + } +#endif /* LWIP_IPV4 && LWIP_ARP */ + +#if LWIP_IPV6 + nd6_cleanup_netif(netif); +#endif /* LWIP_IPV6 */ + + NETIF_STATUS_CALLBACK(netif); + +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set down status */ + netdev_low_level_set_status(netdev_get_by_name(netif->name), RT_FALSE); +#endif /* RT_USING_NETDEV */ + } +} + +#if LWIP_NETIF_STATUS_CALLBACK +/** + * @ingroup netif + * Set callback to be called when interface is brought up/down or address is changed while up + */ +void +netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) +{ + if (netif) { + netif->status_callback = status_callback; + } +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_REMOVE_CALLBACK +/** + * @ingroup netif + * Set callback to be called when the interface has been removed + */ +void +netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) +{ + if (netif) { + netif->remove_callback = remove_callback; + } +} +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +/** + * @ingroup netif + * Called by a driver when its link goes up + */ +void +netif_set_link_up(struct netif *netif) +{ + if (!(netif->flags & NETIF_FLAG_LINK_UP)) { + netif->flags |= NETIF_FLAG_LINK_UP; + +#if LWIP_DHCP + dhcp_network_changed(netif); +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP + autoip_network_changed(netif); +#endif /* LWIP_AUTOIP */ + + if (netif->flags & NETIF_FLAG_UP) { + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); + } + NETIF_LINK_CALLBACK(netif); + +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set link up status */ + netdev_low_level_set_link_status(netdev_get_by_name(netif->name), RT_TRUE); +#endif /* RT_USING_NETDEV */ + } +} + +/** + * @ingroup netif + * Called by a driver when its link goes down + */ +void +netif_set_link_down(struct netif *netif ) +{ + if (netif->flags & NETIF_FLAG_LINK_UP) { + netif->flags &= ~NETIF_FLAG_LINK_UP; + NETIF_LINK_CALLBACK(netif); + +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set link down status */ + netdev_low_level_set_link_status(netdev_get_by_name(netif->name), RT_FALSE); +#endif /* RT_USING_NETDEV */ + } +} + +#if LWIP_NETIF_LINK_CALLBACK +/** + * @ingroup netif + * Set callback to be called when link is brought up/down + */ +void +netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) +{ + if (netif) { + netif->link_callback = link_callback; + } +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if ENABLE_LOOPBACK +/** + * @ingroup netif + * Send an IP packet to be received on the same netif (loopif-like). + * The pbuf is simply copied and handed back to netif->input. + * In multithreaded mode, this is done directly since netif->input must put + * the packet on a queue. + * In callback mode, the packet is put on an internal queue and is fed to + * netif->input by netif_poll(). + * + * @param netif the lwip network interface structure + * @param p the (IP) packet to 'send' + * @return ERR_OK if the packet has been sent + * ERR_MEM if the pbuf used to copy the packet couldn't be allocated + */ +err_t +netif_loop_output(struct netif *netif, struct pbuf *p) +{ + struct pbuf *r; + err_t err; + struct pbuf *last; +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t clen = 0; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if MIB2_STATS +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* MIB2_STATS */ + SYS_ARCH_DECL_PROTECT(lev); + + /* Allocate a new pbuf */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); + return ERR_MEM; + } +#if LWIP_LOOPBACK_MAX_PBUFS + clen = pbuf_clen(r); + /* check for overflow or too many pbuf on queue */ + if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || + ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); + return ERR_MEM; + } + netif->loop_cnt_current += clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* Copy the whole pbuf queue p into the single pbuf r */ + if ((err = pbuf_copy(r, p)) != ERR_OK) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); + return err; + } + + /* Put the packet on a linked list which gets emptied through calling + netif_poll(). */ + + /* let last point to the last pbuf in chain r */ + for (last = r; last->next != NULL; last = last->next) { + /* nothing to do here, just get to the last pbuf */ + } + + SYS_ARCH_PROTECT(lev); + if (netif->loop_first != NULL) { + LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); + netif->loop_last->next = r; + netif->loop_last = last; + } else { + netif->loop_first = r; + netif->loop_last = last; + } + SYS_ARCH_UNPROTECT(lev); + + LINK_STATS_INC(link.xmit); + MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len); + MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts); + +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + /* For multithreading environment, schedule a call to netif_poll */ + tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0); +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ + + return ERR_OK; +} + +#if LWIP_HAVE_LOOPIF +#if LWIP_IPV4 +static err_t +netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr) +{ + LWIP_UNUSED_ARG(addr); + return netif_loop_output(netif, p); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +static err_t +netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr) +{ + LWIP_UNUSED_ARG(addr); + return netif_loop_output(netif, p); +} +#endif /* LWIP_IPV6 */ +#endif /* LWIP_HAVE_LOOPIF */ + + +/** + * Call netif_poll() in the main loop of your application. This is to prevent + * reentering non-reentrant functions like tcp_input(). Packets passed to + * netif_loop_output() are put on a list that is passed to netif->input() by + * netif_poll(). + */ +void +netif_poll(struct netif *netif) +{ + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if MIB2_STATS +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* MIB2_STATS */ + SYS_ARCH_DECL_PROTECT(lev); + + /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ + SYS_ARCH_PROTECT(lev); + while (netif->loop_first != NULL) { + struct pbuf *in, *in_end; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = 1; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + in = in_end = netif->loop_first; + while (in_end->len != in_end->tot_len) { + LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); + in_end = in_end->next; +#if LWIP_LOOPBACK_MAX_PBUFS + clen++; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + } +#if LWIP_LOOPBACK_MAX_PBUFS + /* adjust the number of pbufs on queue */ + LWIP_ASSERT("netif->loop_cnt_current underflow", + ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); + netif->loop_cnt_current -= clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* 'in_end' now points to the last pbuf from 'in' */ + if (in_end == netif->loop_last) { + /* this was the last pbuf in the list */ + netif->loop_first = netif->loop_last = NULL; + } else { + /* pop the pbuf off the list */ + netif->loop_first = in_end->next; + LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); + } + /* De-queue the pbuf from its successors on the 'loop_' list. */ + in_end->next = NULL; + SYS_ARCH_UNPROTECT(lev); + + LINK_STATS_INC(link.recv); + MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); + MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); + /* loopback packets are always IP packets! */ + if (ip_input(in, netif) != ERR_OK) { + pbuf_free(in); + } + SYS_ARCH_PROTECT(lev); + } + SYS_ARCH_UNPROTECT(lev); +} + +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +/** + * Calls netif_poll() for every netif on the netif_list. + */ +void +netif_poll_all(void) +{ + struct netif *netif = netif_list; + /* loop through netifs */ + while (netif != NULL) { + netif_poll(netif); + /* proceed to next network interface */ + netif = netif->next; + } +} +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_NUM_NETIF_CLIENT_DATA > 0 +/** + * @ingroup netif_cd + * Allocate an index to store data in client_data member of struct netif. + * Returned value is an index in mentioned array. + * @see LWIP_NUM_NETIF_CLIENT_DATA + */ +u8_t +netif_alloc_client_data_id(void) +{ + u8_t result = netif_client_id; + netif_client_id++; + + LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA); + return result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX; +} +#endif + +#if LWIP_IPV6 +/** + * @ingroup netif_ip6 + * Change an IPv6 address of a network interface + * + * @param netif the network interface to change + * @param addr_idx index of the IPv6 address + * @param addr6 the new IPv6 address + * + * @note call netif_ip6_addr_set_state() to set the address valid/temptative + */ +void +netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) +{ + LWIP_ASSERT("addr6 != NULL", addr6 != NULL); + netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], + addr6->addr[2], addr6->addr[3]); +} + +/* + * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) + * + * @param netif the network interface to change + * @param addr_idx index of the IPv6 address + * @param i0 word0 of the new IPv6 address + * @param i1 word1 of the new IPv6 address + * @param i2 word2 of the new IPv6 address + * @param i3 word3 of the new IPv6 address + */ +void +netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) +{ + const ip6_addr_t *old_addr; + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); + + old_addr = netif_ip6_addr(netif, addr_idx); + /* address is actually being changed? */ + if ((old_addr->addr[0] != i0) || (old_addr->addr[1] != i1) || + (old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) { + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); + + if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { +#if LWIP_TCP || LWIP_UDP + ip_addr_t new_ipaddr; + IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); +#endif /* LWIP_TCP || LWIP_UDP */ +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); +#endif /* LWIP_RAW */ + } + /* @todo: remove/readd mib2 ip6 entries? */ + + IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3); + IP_SET_TYPE_VAL(netif->ip6_addr[addr_idx], IPADDR_TYPE_V6); + + if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); + NETIF_STATUS_CALLBACK(netif); + } + } + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", + addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), + netif_ip6_addr_state(netif, addr_idx))); +} + +/** + * @ingroup netif_ip6 + * Change the state of an IPv6 address of a network interface + * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE + * includes the number of checks done, see ip6_addr.h) + * + * @param netif the network interface to change + * @param addr_idx index of the IPv6 address + * @param state the new IPv6 address state + */ +void +netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state) +{ + u8_t old_state; + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); + + old_state = netif_ip6_addr_state(netif, addr_idx); + /* state is actually being changed? */ + if (old_state != state) { + u8_t old_valid = old_state & IP6_ADDR_VALID; + u8_t new_valid = state & IP6_ADDR_VALID; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); + +#if LWIP_IPV6_MLD + /* Reevaluate solicited-node multicast group membership. */ + if (netif->flags & NETIF_FLAG_MLD6) { + nd6_adjust_mld_membership(netif, addr_idx, state); + } +#endif /* LWIP_IPV6_MLD */ + + if (old_valid && !new_valid) { + /* address about to be removed by setting invalid */ +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); +#endif /* LWIP_RAW */ + /* @todo: remove mib2 ip6 entries? */ + } + netif->ip6_addr_state[addr_idx] = state; + + if (!old_valid && new_valid) { + /* address added by setting valid */ + /* @todo: add mib2 ip6 entries? */ + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); + } + if ((old_state & IP6_ADDR_PREFERRED) != (state & IP6_ADDR_PREFERRED)) { + /* address state has changed (valid flag changed or switched between + preferred and deprecated) -> call the callback function */ + NETIF_STATUS_CALLBACK(netif); + } + } + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", + addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), + netif_ip6_addr_state(netif, addr_idx))); +} + +/** + * Checks if a specific address is assigned to the netif and returns its + * index. + * + * @param netif the netif to check + * @param ip6addr the IPv6 address to find + * @return >= 0: address found, this is its index + * -1: address not found on this netif + */ +s8_t +netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) { + return i; + } + } + return -1; +} + +/** + * @ingroup netif_ip6 + * Create a link-local IPv6 address on a netif (stored in slot 0) + * + * @param netif the netif to create the address on + * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion) + * if == 0, use hwaddr directly as interface ID + */ +void +netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) +{ + u8_t i, addr_index; + + /* Link-local prefix. */ + ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); + ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; + + /* Generate interface ID. */ + if (from_mac_48bit) { + /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ + ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | + ((u32_t)(netif->hwaddr[1]) << 16) | + ((u32_t)(netif->hwaddr[2]) << 8) | + (0xff)); + ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) | + ((u32_t)(netif->hwaddr[3]) << 16) | + ((u32_t)(netif->hwaddr[4]) << 8) | + (netif->hwaddr[5])); + } else { + /* Use hwaddr directly as interface ID. */ + ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0; + ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0; + + addr_index = 3; + for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) { + if (i == 4) { + addr_index--; + } + ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)); + } + } + +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set ipv6 address */ + ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[0], netif->ip6_addr[0]); +#endif /* RT_USING_NETDEV */ + + /* Set address state. */ +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS + /* Will perform duplicate address detection (DAD). */ + netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE); +#else + /* Consider address valid. */ + netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED); +#endif /* LWIP_IPV6_AUTOCONFIG */ +} + +/** + * @ingroup netif_ip6 + * This function allows for the easy addition of a new IPv6 address to an interface. + * It takes care of finding an empty slot and then sets the address tentative + * (to make sure that all the subsequent processing happens). + * + * @param netif netif to add the address on + * @param ip6addr address to add + * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here + */ +err_t +netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx) +{ + s8_t i; + + i = netif_get_ip6_addr_match(netif, ip6addr); + if (i >= 0) { + /* Address already added */ + if (chosen_idx != NULL) { + *chosen_idx = i; + } + return ERR_OK; + } + + /* Find a free slot -- musn't be the first one (reserved for link local) */ + for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { + ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set ipv6 address */ + ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[i], netif->ip6_addr[i]); +#endif /* RT_USING_NETDEV */ + netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); + if (chosen_idx != NULL) { + *chosen_idx = i; + } + return ERR_OK; + } + } + + if (chosen_idx != NULL) { + *chosen_idx = -1; + } + return ERR_VAL; +} + +/** Dummy IPv6 output function for netifs not supporting IPv6 + */ +static err_t +netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(netif); + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(ipaddr); + + return ERR_IF; +} +#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.3/src/core/pbuf.c b/components/net/lwip-2.0.3/src/core/pbuf.c new file mode 100644 index 0000000000..059f83a571 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/pbuf.c @@ -0,0 +1,1442 @@ +/** + * @file + * Packet buffer management + */ + +/** + * @defgroup pbuf Packet buffers (PBUF) + * @ingroup infrastructure + * + * Packets are built from the pbuf data structure. It supports dynamic + * memory allocation for packet contents or can reference externally + * managed packet contents both in RAM and ROM. Quick allocation for + * incoming packets is provided through pools with fixed sized pbufs. + * + * A packet may span over multiple pbufs, chained as a singly linked + * list. This is called a "pbuf chain". + * + * Multiple packets may be queued, also using this singly linked list. + * This is called a "packet queue". + * + * So, a packet queue consists of one or more pbuf chains, each of + * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE + * NOT SUPPORTED!!! Use helper structs to queue multiple packets. + * + * The differences between a pbuf chain and a packet queue are very + * precise but subtle. + * + * The last pbuf of a packet has a ->tot_len field that equals the + * ->len field. It can be found by traversing the list. If the last + * pbuf of a packet has a ->next field other than NULL, more packets + * are on the queue. + * + * Therefore, looping through a pbuf of a single packet, has an + * loop end condition (tot_len == p->len), NOT (next == NULL). + * + * Example of custom pbuf usage for zero-copy RX: + @code{.c} +typedef struct my_custom_pbuf +{ + struct pbuf_custom p; + void* dma_descriptor; +} my_custom_pbuf_t; + +LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(my_custom_pbuf_t), "Zero-copy RX PBUF pool"); + +void my_pbuf_free_custom(void* p) +{ + my_custom_pbuf_t* my_puf = (my_custom_pbuf_t*)p; + + LOCK_INTERRUPTS(); + free_rx_dma_descriptor(my_pbuf->dma_descriptor); + LWIP_MEMPOOL_FREE(RX_POOL, my_pbuf); + UNLOCK_INTERRUPTS(); +} + +void eth_rx_irq() +{ + dma_descriptor* dma_desc = get_RX_DMA_descriptor_from_ethernet(); + my_custom_pbuf_t* my_pbuf = (my_custom_pbuf_t*)LWIP_MEMPOOL_ALLOC(RX_POOL); + + my_pbuf->p.custom_free_function = my_pbuf_free_custom; + my_pbuf->dma_descriptor = dma_desc; + + invalidate_cpu_cache(dma_desc->rx_data, dma_desc->rx_length); + + struct pbuf* p = pbuf_alloced_custom(PBUF_RAW, + dma_desc->rx_length, + PBUF_REF, + &my_pbuf->p, + dma_desc->rx_data, + dma_desc->max_buffer_size); + + if(netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } +} + @endcode + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#if LWIP_TCP && TCP_QUEUE_OOSEQ +#include "lwip/priv/tcp_priv.h" +#endif +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) +/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically + aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ +#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) + +#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_IS_EMPTY() +#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +#if !NO_SYS +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL +#include "lwip/tcpip.h" +#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \ + if (tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \ + SYS_ARCH_PROTECT(old_level); \ + pbuf_free_ooseq_pending = 0; \ + SYS_ARCH_UNPROTECT(old_level); \ + } } while(0) +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +#endif /* !NO_SYS */ + +volatile u8_t pbuf_free_ooseq_pending; +#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() + +/** + * Attempt to reclaim some memory from queued out-of-sequence TCP segments + * if we run out of pool pbufs. It's better to give priority to new packets + * if we're running out. + * + * This must be done in the correct thread context therefore this function + * can only be used with NO_SYS=0 and through tcpip_callback. + */ +#if !NO_SYS +static +#endif /* !NO_SYS */ +void +pbuf_free_ooseq(void) +{ + struct tcp_pcb* pcb; + SYS_ARCH_SET(pbuf_free_ooseq_pending, 0); + + for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { + if (NULL != pcb->ooseq) { + /** Free the ooseq pbufs of one PCB only */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n")); + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + return; + } + } +} + +#if !NO_SYS +/** + * Just a callback function for tcpip_callback() that calls pbuf_free_ooseq(). + */ +static void +pbuf_free_ooseq_callback(void *arg) +{ + LWIP_UNUSED_ARG(arg); + pbuf_free_ooseq(); +} +#endif /* !NO_SYS */ + +/** Queue a call to pbuf_free_ooseq if not already queued. */ +static void +pbuf_pool_is_empty(void) +{ +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL + SYS_ARCH_SET(pbuf_free_ooseq_pending, 1); +#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ + u8_t queued; + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + queued = pbuf_free_ooseq_pending; + pbuf_free_ooseq_pending = 1; + SYS_ARCH_UNPROTECT(old_level); + + if (!queued) { + /* queue a call to pbuf_free_ooseq if not already queued */ + PBUF_POOL_FREE_OOSEQ_QUEUE_CALL(); + } +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +} +#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +/** + * @ingroup pbuf + * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). + * + * The actual memory allocated for the pbuf is determined by the + * layer at which the pbuf is allocated and the requested size + * (from the size parameter). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type this parameter decides how and where the pbuf + * should be allocated as follows: + * + * - PBUF_RAM: buffer memory for pbuf is allocated as one large + * chunk. This includes protocol headers as well. + * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for + * protocol headers. Additional headers must be prepended + * by allocating another pbuf and chain in to the front of + * the ROM pbuf. It is assumed that the memory used is really + * similar to ROM in that it is immutable and will not be + * changed. Memory which is dynamic should generally not + * be attached to PBUF_ROM pbufs. Use PBUF_REF instead. + * - PBUF_REF: no buffer memory is allocated for the pbuf, even for + * protocol headers. It is assumed that the pbuf is only + * being used in a single thread. If the pbuf gets queued, + * then pbuf_take should be called to copy the buffer. + * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from + * the pbuf pool that is allocated during pbuf_init(). + * + * @return the allocated pbuf. If multiple pbufs where allocated, this + * is the first pbuf of a pbuf chain. + */ +struct pbuf * +pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) +{ + struct pbuf *p, *q, *r; + u16_t offset; + s32_t rem_len; /* remaining length */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (layer) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; + break; + case PBUF_RAW_TX: + /* add room for encapsulating link layer headers (e.g. 802.11) */ + offset = PBUF_LINK_ENCAPSULATION_HLEN; + break; + case PBUF_RAW: + /* no offset (e.g. RX buffers or chain successors) */ + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); + return NULL; + } + + switch (type) { + case PBUF_POOL: + /* allocate head of pbuf chain into p */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); + if (p == NULL) { + PBUF_POOL_IS_EMPTY(); + return NULL; + } + p->type = type; + p->next = NULL; + + /* make the payload pointer point 'offset' bytes into pbuf data memory */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); + LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + /* the total length of the pbuf chain is the requested size */ + p->tot_len = length; + /* set the length of the first pbuf in the chain */ + p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", + (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); + /* set reference count (needed here in case we fail) */ + p->ref = 1; + + /* now allocate the tail of the pbuf chain */ + + /* remember first pbuf for linkage in next iteration */ + r = p; + /* remaining length to be allocated */ + rem_len = length - p->len; + /* any remaining pbufs to be allocated? */ + while (rem_len > 0) { + q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + if (q == NULL) { + PBUF_POOL_IS_EMPTY(); + /* free chain so far allocated */ + pbuf_free(p); + /* bail out unsuccessfully */ + return NULL; + } + q->type = type; + q->flags = 0; + q->next = NULL; + /* make previous pbuf point to this pbuf */ + r->next = q; + /* set total length of this pbuf and next in chain */ + LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff); + q->tot_len = (u16_t)rem_len; + /* this pbuf length is pool size, unless smaller sized tail */ + q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED); + q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF); + LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", + ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + q->ref = 1; + /* calculate remaining length to be allocated */ + rem_len -= q->len; + /* remember this pbuf for linkage in next iteration */ + r = q; + } + /* end of chain */ + /*r->next = NULL;*/ + + break; + case PBUF_RAM: + { + mem_size_t alloc_len = LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length); + + /* bug #50040: Check for integer overflow when calculating alloc_len */ + if (alloc_len < LWIP_MEM_ALIGN_SIZE(length)) { + return NULL; + } + + /* If pbuf is to be allocated in RAM, allocate memory for it. */ + p = (struct pbuf*)mem_malloc(alloc_len); + } + + if (p == NULL) { + return NULL; + } + /* Set up internal structure of the pbuf. */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + + LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + break; + /* pbuf references existing (non-volatile static constant) ROM payload? */ + case PBUF_ROM: + /* pbuf references existing (externally allocated) RAM payload? */ + case PBUF_REF: + /* only allocate memory for the pbuf structure */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF); + if (p == NULL) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", + (type == PBUF_ROM) ? "ROM" : "REF")); + return NULL; + } + /* caller must set this field properly, afterwards */ + p->payload = NULL; + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + break; + default: + LWIP_ASSERT("pbuf_alloc: erroneous type", 0); + return NULL; + } + /* set reference count */ + p->ref = 1; + /* set flags */ + p->flags = 0; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); + return p; +} + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** + * @ingroup pbuf + * Initialize a custom pbuf (already allocated). + * + * @param l flag to define header size + * @param length size of the pbuf's payload + * @param type type of the pbuf (only used to treat the pbuf accordingly, as + * this function allocates no memory) + * @param p pointer to the custom pbuf to initialize (already allocated) + * @param payload_mem pointer to the buffer that is used for payload and headers, + * must be at least big enough to hold 'length' plus the header size, + * may be NULL if set later. + * ATTENTION: The caller is responsible for correct alignment of this buffer!! + * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least + * big enough to hold 'length' plus the header size + */ +struct pbuf* +pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p, + void *payload_mem, u16_t payload_mem_len) +{ + u16_t offset; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (l) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; + break; + case PBUF_RAW_TX: + /* add room for encapsulating link layer headers (e.g. 802.11) */ + offset = PBUF_LINK_ENCAPSULATION_HLEN; + break; + case PBUF_RAW: + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0); + return NULL; + } + + if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length)); + return NULL; + } + + p->pbuf.next = NULL; + if (payload_mem != NULL) { + p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset); + } else { + p->pbuf.payload = NULL; + } + p->pbuf.flags = PBUF_FLAG_IS_CUSTOM; + p->pbuf.len = p->pbuf.tot_len = length; + p->pbuf.type = type; + p->pbuf.ref = 1; + return &p->pbuf; +} +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +/** + * @ingroup pbuf + * Shrink a pbuf chain to a desired length. + * + * @param p pbuf to shrink. + * @param new_len desired new length of pbuf chain + * + * Depending on the desired length, the first few pbufs in a chain might + * be skipped and left unchanged. The new last pbuf in the chain will be + * resized, and any remaining pbufs will be freed. + * + * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. + * @note May not be called on a packet queue. + * + * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). + */ +void +pbuf_realloc(struct pbuf *p, u16_t new_len) +{ + struct pbuf *q; + u16_t rem_len; /* remaining length */ + s32_t grow; + + LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); + LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || + p->type == PBUF_ROM || + p->type == PBUF_RAM || + p->type == PBUF_REF); + + /* desired length larger than current length? */ + if (new_len >= p->tot_len) { + /* enlarging not yet supported */ + return; + } + + /* the pbuf chain grows by (new_len - p->tot_len) bytes + * (which may be negative in case of shrinking) */ + grow = new_len - p->tot_len; + + /* first, step over any pbufs that should remain in the chain */ + rem_len = new_len; + q = p; + /* should this pbuf be kept? */ + while (rem_len > q->len) { + /* decrease remaining length by pbuf length */ + rem_len -= q->len; + /* decrease total length indicator */ + LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); + q->tot_len += (u16_t)grow; + /* proceed to next pbuf in chain */ + q = q->next; + LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); + } + /* we have now reached the new last pbuf (in q) */ + /* rem_len == desired length for pbuf q */ + + /* shrink allocated memory for PBUF_RAM */ + /* (other types merely adjust their length fields */ + if ((q->type == PBUF_RAM) && (rem_len != q->len) +#if LWIP_SUPPORT_CUSTOM_PBUF + && ((q->flags & PBUF_FLAG_IS_CUSTOM) == 0) +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + ) { + /* reallocate and adjust the length of the pbuf that will be split */ + q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len); + LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); + } + /* adjust length fields for new last pbuf */ + q->len = rem_len; + q->tot_len = q->len; + + /* any remaining pbufs in chain? */ + if (q->next != NULL) { + /* free remaining pbufs in chain */ + pbuf_free(q->next); + } + /* q is last packet in chain */ + q->next = NULL; + +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * @see pbuf_header. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size. + * @param force Allow 'header_size_increment > 0' for PBUF_REF/PBUF_ROM types + * + * @return non-zero on failure, zero on success. + * + */ +static u8_t +pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force) +{ + u16_t type; + void *payload; + u16_t increment_magnitude; + + LWIP_ASSERT("p != NULL", p != NULL); + if ((header_size_increment == 0) || (p == NULL)) { + return 0; + } + + if (header_size_increment < 0) { + increment_magnitude = (u16_t)-header_size_increment; + /* Check that we aren't going to move off the end of the pbuf */ + LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;); + } else { + increment_magnitude = (u16_t)header_size_increment; +#if 0 + /* Can't assert these as some callers speculatively call + pbuf_header() to see if it's OK. Will return 1 below instead. */ + /* Check that we've got the correct type of pbuf to work with */ + LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", + p->type == PBUF_RAM || p->type == PBUF_POOL); + /* Check that we aren't going to move off the beginning of the pbuf */ + LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", + (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); +#endif + } + + type = p->type; + /* remember current payload pointer */ + payload = p->payload; + + /* pbuf types containing payloads? */ + if (type == PBUF_RAM || type == PBUF_POOL) { + /* set new payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + /* boundary check fails? */ + if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, + ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", + (void *)p->payload, (void *)((u8_t *)p + SIZEOF_STRUCT_PBUF))); + /* restore old payload pointer */ + p->payload = payload; + /* bail out unsuccessfully */ + return 1; + } + /* pbuf types referring to external payloads? */ + } else if (type == PBUF_REF || type == PBUF_ROM) { + /* hide a header in the payload? */ + if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { + /* increase payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + } else if ((header_size_increment > 0) && force) { + p->payload = (u8_t *)p->payload - header_size_increment; + } else { + /* cannot expand payload to front (yet!) + * bail out unsuccessfully */ + return 1; + } + } else { + /* Unknown type */ + LWIP_ASSERT("bad pbuf type", 0); + return 1; + } + /* modify pbuf length fields */ + p->len += header_size_increment; + p->tot_len += header_size_increment; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n", + (void *)payload, (void *)p->payload, header_size_increment)); + + return 0; +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * + * Adjusts the ->payload pointer so that space for a header + * (dis)appears in the pbuf payload. + * + * The ->payload, ->tot_len and ->len fields are adjusted. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size which + * increases the size of the pbuf. New space is on the front. + * (Using a negative value decreases the header size.) + * If hdr_size_inc is 0, this function does nothing and returns successful. + * + * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so + * the call will fail. A check is made that the increase in header size does + * not move the payload pointer in front of the start of the buffer. + * @return non-zero on failure, zero on success. + * + */ +u8_t +pbuf_header(struct pbuf *p, s16_t header_size_increment) +{ + return pbuf_header_impl(p, header_size_increment, 0); +} + +/** + * Same as pbuf_header but does not check if 'header_size > 0' is allowed. + * This is used internally only, to allow PBUF_REF for RX. + */ +u8_t +pbuf_header_force(struct pbuf *p, s16_t header_size_increment) +{ + return pbuf_header_impl(p, header_size_increment, 1); +} + +/** + * @ingroup pbuf + * Dereference a pbuf chain or queue and deallocate any no-longer-used + * pbufs at the head of this chain or queue. + * + * Decrements the pbuf reference count. If it reaches zero, the pbuf is + * deallocated. + * + * For a pbuf chain, this is repeated for each pbuf in the chain, + * up to the first pbuf which has a non-zero reference count after + * decrementing. So, when all reference counts are one, the whole + * chain is free'd. + * + * @param p The pbuf (chain) to be dereferenced. + * + * @return the number of pbufs that were de-allocated + * from the head of the chain. + * + * @note MUST NOT be called on a packet queue (Not verified to work yet). + * @note the reference counter of a pbuf equals the number of pointers + * that refer to the pbuf (or into the pbuf). + * + * @internal examples: + * + * Assuming existing chains a->b->c with the following reference + * counts, calling pbuf_free(a) results in: + * + * 1->2->3 becomes ...1->3 + * 3->3->3 becomes 2->3->3 + * 1->1->2 becomes ......1 + * 2->1->1 becomes 1->1->1 + * 1->1->1 becomes ....... + * + */ +u8_t +pbuf_free(struct pbuf *p) +{ + u16_t type; + struct pbuf *q; + u8_t count; + + if (p == NULL) { + LWIP_ASSERT("p != NULL", p != NULL); + /* if assertions are disabled, proceed with debug output */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_free(p == NULL) was called.\n")); + return 0; + } + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); + + PERF_START; + + LWIP_ASSERT("pbuf_free: sane type", + p->type == PBUF_RAM || p->type == PBUF_ROM || + p->type == PBUF_REF || p->type == PBUF_POOL); + + count = 0; + /* de-allocate all consecutive pbufs from the head of the chain that + * obtain a zero reference count after decrementing*/ + while (p != NULL) { + u16_t ref; + SYS_ARCH_DECL_PROTECT(old_level); + /* Since decrementing ref cannot be guaranteed to be a single machine operation + * we must protect it. We put the new ref into a local variable to prevent + * further protection. */ + SYS_ARCH_PROTECT(old_level); + /* all pbufs in a chain are referenced at least once */ + LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); + /* decrease reference count (number of pointers to pbuf) */ + ref = --(p->ref); + SYS_ARCH_UNPROTECT(old_level); + /* this pbuf is no longer referenced to? */ + if (ref == 0) { + /* remember next pbuf in chain for next iteration */ + q = p->next; + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); + type = p->type; +#if LWIP_SUPPORT_CUSTOM_PBUF + /* is this a custom pbuf? */ + if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { + struct pbuf_custom *pc = (struct pbuf_custom*)p; + LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); + pc->custom_free_function(p); + } else +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + { + /* is this a pbuf from the pool? */ + if (type == PBUF_POOL) { + memp_free(MEMP_PBUF_POOL, p); + /* is this a ROM or RAM referencing pbuf? */ + } else if (type == PBUF_ROM || type == PBUF_REF) { + memp_free(MEMP_PBUF, p); + /* type == PBUF_RAM */ + } else { + mem_free(p); + } + } + count++; + /* proceed to next pbuf */ + p = q; + /* p->ref > 0, this pbuf is still referenced to */ + /* (and so the remaining pbufs in chain as well) */ + } else { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref)); + /* stop walking through the chain */ + p = NULL; + } + } + PERF_STOP("pbuf_free"); + /* return number of de-allocated pbufs */ + return count; +} + +/** + * Count number of pbufs in a chain + * + * @param p first pbuf of chain + * @return the number of pbufs in a chain + */ +u16_t +pbuf_clen(const struct pbuf *p) +{ + u16_t len; + + len = 0; + while (p != NULL) { + ++len; + p = p->next; + } + return len; +} + +/** + * @ingroup pbuf + * Increment the reference count of the pbuf. + * + * @param p pbuf to increase reference counter of + * + */ +void +pbuf_ref(struct pbuf *p) +{ + /* pbuf given? */ + if (p != NULL) { + SYS_ARCH_INC(p->ref, 1); + LWIP_ASSERT("pbuf ref overflow", p->ref > 0); + } +} + +/** + * @ingroup pbuf + * Concatenate two pbufs (each may be a pbuf chain) and take over + * the caller's reference of the tail pbuf. + * + * @note The caller MAY NOT reference the tail pbuf afterwards. + * Use pbuf_chain() for that purpose. + * + * @see pbuf_chain() + */ +void +pbuf_cat(struct pbuf *h, struct pbuf *t) +{ + struct pbuf *p; + + LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", + ((h != NULL) && (t != NULL)), return;); + + /* proceed to last pbuf of chain */ + for (p = h; p->next != NULL; p = p->next) { + /* add total length of second chain to all totals of first chain */ + p->tot_len += t->tot_len; + } + /* { p is last pbuf of first h chain, p->next == NULL } */ + LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); + LWIP_ASSERT("p->next == NULL", p->next == NULL); + /* add total length of second chain to last pbuf total of first chain */ + p->tot_len += t->tot_len; + /* chain last pbuf of head (p) with first of tail (t) */ + p->next = t; + /* p->next now references t, but the caller will drop its reference to t, + * so netto there is no change to the reference count of t. + */ +} + +/** + * @ingroup pbuf + * Chain two pbufs (or pbuf chains) together. + * + * The caller MUST call pbuf_free(t) once it has stopped + * using it. Use pbuf_cat() instead if you no longer use t. + * + * @param h head pbuf (chain) + * @param t tail pbuf (chain) + * @note The pbufs MUST belong to the same packet. + * @note MAY NOT be called on a packet queue. + * + * The ->tot_len fields of all pbufs of the head chain are adjusted. + * The ->next field of the last pbuf of the head chain is adjusted. + * The ->ref field of the first pbuf of the tail chain is adjusted. + * + */ +void +pbuf_chain(struct pbuf *h, struct pbuf *t) +{ + pbuf_cat(h, t); + /* t is now referenced by h */ + pbuf_ref(t); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); +} + +/** + * Dechains the first pbuf from its succeeding pbufs in the chain. + * + * Makes p->tot_len field equal to p->len. + * @param p pbuf to dechain + * @return remainder of the pbuf chain, or NULL if it was de-allocated. + * @note May not be called on a packet queue. + */ +struct pbuf * +pbuf_dechain(struct pbuf *p) +{ + struct pbuf *q; + u8_t tail_gone = 1; + /* tail */ + q = p->next; + /* pbuf has successor in chain? */ + if (q != NULL) { + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len); + /* enforce invariant if assertion is disabled */ + q->tot_len = p->tot_len - p->len; + /* decouple pbuf from remainder */ + p->next = NULL; + /* total length of pbuf p is its own length only */ + p->tot_len = p->len; + /* q is no longer referenced by p, free it */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); + tail_gone = pbuf_free(q); + if (tail_gone > 0) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, + ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); + } + /* return remaining tail or NULL if deallocated */ + } + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len); + return ((tail_gone > 0) ? NULL : q); +} + +/** + * @ingroup pbuf + * Create PBUF_RAM copies of pbufs. + * + * Used to queue packets on behalf of the lwIP stack, such as + * ARP based queueing. + * + * @note You MUST explicitly use p = pbuf_take(p); + * + * @note Only one packet is copied, no packet queue! + * + * @param p_to pbuf destination of the copy + * @param p_from pbuf source of the copy + * + * @return ERR_OK if pbuf was copied + * ERR_ARG if one of the pbufs is NULL or p_to is not big + * enough to hold p_from + */ +err_t +pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from) +{ + u16_t offset_to=0, offset_from=0, len; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", + (const void*)p_to, (const void*)p_from)); + + /* is the target big enough to hold the source? */ + LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && + (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); + + /* iterate through pbuf chain */ + do + { + /* copy one part of the original chain */ + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { + /* complete current p_from fits into current p_to */ + len = p_from->len - offset_from; + } else { + /* current p_from does not fit into current p_to */ + len = p_to->len - offset_to; + } + MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len); + offset_to += len; + offset_from += len; + LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); + LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); + if (offset_from >= p_from->len) { + /* on to next p_from (if any) */ + offset_from = 0; + p_from = p_from->next; + } + if (offset_to == p_to->len) { + /* on to next p_to (if any) */ + offset_to = 0; + p_to = p_to->next; + LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;); + } + + if ((p_from != NULL) && (p_from->len == p_from->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!", + (p_from->next == NULL), return ERR_VAL;); + } + if ((p_to != NULL) && (p_to->len == p_to->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!", + (p_to->next == NULL), return ERR_VAL;); + } + } while (p_from); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); + return ERR_OK; +} + +/** + * @ingroup pbuf + * Copy (part of) the contents of a packet buffer + * to an application supplied buffer. + * + * @param buf the pbuf from which to copy data + * @param dataptr the application supplied buffer + * @param len length of data to copy (dataptr must be big enough). No more + * than buf->tot_len will be copied, irrespective of len + * @param offset offset into the packet buffer from where to begin copying len bytes + * @return the number of bytes copied, or 0 on failure + */ +u16_t +pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) +{ + const struct pbuf *p; + u16_t left; + u16_t buf_copy_len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); + + left = 0; + + if ((buf == NULL) || (dataptr == NULL)) { + return 0; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for (p = buf; len != 0 && p != NULL; p = p->next) { + if ((offset != 0) && (offset >= p->len)) { + /* don't copy from this buffer -> on to the next */ + offset -= p->len; + } else { + /* copy from this buffer. maybe only partially. */ + buf_copy_len = p->len - offset; + if (buf_copy_len > len) { + buf_copy_len = len; + } + /* copy the necessary parts of the buffer */ + MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); + copied_total += buf_copy_len; + left += buf_copy_len; + len -= buf_copy_len; + offset = 0; + } + } + return copied_total; +} + +#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE +/** + * This method modifies a 'pbuf chain', so that its total length is + * smaller than 64K. The remainder of the original pbuf chain is stored + * in *rest. + * This function never creates new pbufs, but splits an existing chain + * in two parts. The tot_len of the modified packet queue will likely be + * smaller than 64K. + * 'packet queues' are not supported by this function. + * + * @param p the pbuf queue to be split + * @param rest pointer to store the remainder (after the first 64K) + */ +void pbuf_split_64k(struct pbuf *p, struct pbuf **rest) +{ + *rest = NULL; + if ((p != NULL) && (p->next != NULL)) { + u16_t tot_len_front = p->len; + struct pbuf *i = p; + struct pbuf *r = p->next; + + /* continue until the total length (summed up as u16_t) overflows */ + while ((r != NULL) && ((u16_t)(tot_len_front + r->len) > tot_len_front)) { + tot_len_front += r->len; + i = r; + r = r->next; + } + /* i now points to last packet of the first segment. Set next + pointer to NULL */ + i->next = NULL; + + if (r != NULL) { + /* Update the tot_len field in the first part */ + for (i = p; i != NULL; i = i->next) { + i->tot_len -= r->tot_len; + LWIP_ASSERT("tot_len/len mismatch in last pbuf", + (i->next != NULL) || (i->tot_len == i->len)); + } + if (p->flags & PBUF_FLAG_TCP_FIN) { + r->flags |= PBUF_FLAG_TCP_FIN; + } + + /* tot_len field in rest does not need modifications */ + /* reference counters do not need modifications */ + *rest = r; + } + } +} +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + +/* Actual implementation of pbuf_skip() but returning const pointer... */ +static const struct pbuf* +pbuf_skip_const(const struct pbuf* in, u16_t in_offset, u16_t* out_offset) +{ + u16_t offset_left = in_offset; + const struct pbuf* q = in; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= offset_left)) { + offset_left -= q->len; + q = q->next; + } + if (out_offset != NULL) { + *out_offset = offset_left; + } + return q; +} + +/** + * @ingroup pbuf + * Skip a number of bytes at the start of a pbuf + * + * @param in input pbuf + * @param in_offset offset to skip + * @param out_offset resulting offset in the returned pbuf + * @return the pbuf in the queue where the offset is + */ +struct pbuf* +pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset) +{ + const struct pbuf* out = pbuf_skip_const(in, in_offset, out_offset); + return LWIP_CONST_CAST(struct pbuf*, out); +} + +/** + * @ingroup pbuf + * Copy application supplied data into a pbuf. + * This function can only be used to copy the equivalent of buf->tot_len data. + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) +{ + struct pbuf *p; + u16_t buf_copy_len; + u16_t total_copy_len = len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return ERR_ARG;); + LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return ERR_ARG;); + LWIP_ERROR("pbuf_take: buf not large enough", (buf->tot_len >= len), return ERR_MEM;); + + if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) { + return ERR_ARG; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for (p = buf; total_copy_len != 0; p = p->next) { + LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL); + buf_copy_len = total_copy_len; + if (buf_copy_len > p->len) { + /* this pbuf cannot hold all remaining data */ + buf_copy_len = p->len; + } + /* copy the necessary parts of the buffer */ + MEMCPY(p->payload, &((const char*)dataptr)[copied_total], buf_copy_len); + total_copy_len -= buf_copy_len; + copied_total += buf_copy_len; + } + LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len); + return ERR_OK; +} + +/** + * @ingroup pbuf + * Same as pbuf_take() but puts data at an offset + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * @param offset offset in pbuf where to copy dataptr to + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset) +{ + u16_t target_offset; + struct pbuf* q = pbuf_skip(buf, offset, &target_offset); + + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->tot_len >= target_offset + len)) { + u16_t remaining_len = len; + const u8_t* src_ptr = (const u8_t*)dataptr; + /* copy the part that goes into the first pbuf */ + u16_t first_copy_len = LWIP_MIN(q->len - target_offset, len); + MEMCPY(((u8_t*)q->payload) + target_offset, dataptr, first_copy_len); + remaining_len -= first_copy_len; + src_ptr += first_copy_len; + if (remaining_len > 0) { + return pbuf_take(q->next, src_ptr, remaining_len); + } + return ERR_OK; + } + return ERR_MEM; +} + +/** + * @ingroup pbuf + * Creates a single pbuf out of a queue of pbufs. + * + * @remark: Either the source pbuf 'p' is freed by this function or the original + * pbuf 'p' is returned, therefore the caller has to check the result! + * + * @param p the source pbuf + * @param layer pbuf_layer of the new pbuf + * + * @return a new, single pbuf (p->next is NULL) + * or the old pbuf if allocation fails + */ +struct pbuf* +pbuf_coalesce(struct pbuf *p, pbuf_layer layer) +{ + struct pbuf *q; + err_t err; + if (p->next == NULL) { + return p; + } + q = pbuf_alloc(layer, p->tot_len, PBUF_RAM); + if (q == NULL) { + /* @todo: what do we do now? */ + return p; + } + err = pbuf_copy(q, p); + LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); + pbuf_free(p); + return q; +} + +#if LWIP_CHECKSUM_ON_COPY +/** + * Copies data into a single pbuf (*not* into a pbuf queue!) and updates + * the checksum while copying + * + * @param p the pbuf to copy data into + * @param start_offset offset of p->payload where to copy the data to + * @param dataptr data to copy into the pbuf + * @param len length of data to copy into the pbuf + * @param chksum pointer to the checksum which is updated + * @return ERR_OK if successful, another error if the data does not fit + * within the (first) pbuf (no pbuf queues!) + */ +err_t +pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum) +{ + u32_t acc; + u16_t copy_chksum; + char *dst_ptr; + LWIP_ASSERT("p != NULL", p != NULL); + LWIP_ASSERT("dataptr != NULL", dataptr != NULL); + LWIP_ASSERT("chksum != NULL", chksum != NULL); + LWIP_ASSERT("len != 0", len != 0); + + if ((start_offset >= p->len) || (start_offset + len > p->len)) { + return ERR_ARG; + } + + dst_ptr = ((char*)p->payload) + start_offset; + copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len); + if ((start_offset & 1) != 0) { + copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum); + } + acc = *chksum; + acc += copy_chksum; + *chksum = FOLD_U32T(acc); + return ERR_OK; +} +#endif /* LWIP_CHECKSUM_ON_COPY */ + +/** + * @ingroup pbuf + * Get one byte from the specified position in a pbuf + * WARNING: returns zero for offset >= p->tot_len + * + * @param p pbuf to parse + * @param offset offset into p of the byte to return + * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len + */ +u8_t +pbuf_get_at(const struct pbuf* p, u16_t offset) +{ + int ret = pbuf_try_get_at(p, offset); + if (ret >= 0) { + return (u8_t)ret; + } + return 0; +} + +/** + * @ingroup pbuf + * Get one byte from the specified position in a pbuf + * + * @param p pbuf to parse + * @param offset offset into p of the byte to return + * @return byte at an offset into p [0..0xFF] OR negative if 'offset' >= p->tot_len + */ +int +pbuf_try_get_at(const struct pbuf* p, u16_t offset) +{ + u16_t q_idx; + const struct pbuf* q = pbuf_skip_const(p, offset, &q_idx); + + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > q_idx)) { + return ((u8_t*)q->payload)[q_idx]; + } + return -1; +} + +/** + * @ingroup pbuf + * Put one byte to the specified position in a pbuf + * WARNING: silently ignores offset >= p->tot_len + * + * @param p pbuf to fill + * @param offset offset into p of the byte to write + * @param data byte to write at an offset into p + */ +void +pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data) +{ + u16_t q_idx; + struct pbuf* q = pbuf_skip(p, offset, &q_idx); + + /* write requested data if pbuf is OK */ + if ((q != NULL) && (q->len > q_idx)) { + ((u8_t*)q->payload)[q_idx] = data; + } +} + +/** + * @ingroup pbuf + * Compare pbuf contents at specified offset with memory s2, both of length n + * + * @param p pbuf to compare + * @param offset offset into p at which to start comparing + * @param s2 buffer to compare + * @param n length of buffer to compare + * @return zero if equal, nonzero otherwise + * (0xffff if p is too short, diffoffset+1 otherwise) + */ +u16_t +pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n) +{ + u16_t start = offset; + const struct pbuf* q = p; + u16_t i; + + /* pbuf long enough to perform check? */ + if(p->tot_len < (offset + n)) { + return 0xffff; + } + + /* get the correct pbuf from chain. We know it succeeds because of p->tot_len check above. */ + while ((q != NULL) && (q->len <= start)) { + start -= q->len; + q = q->next; + } + + /* return requested data if pbuf is OK */ + for (i = 0; i < n; i++) { + /* We know pbuf_get_at() succeeds because of p->tot_len check above. */ + u8_t a = pbuf_get_at(q, start + i); + u8_t b = ((const u8_t*)s2)[i]; + if (a != b) { + return i+1; + } + } + return 0; +} + +/** + * @ingroup pbuf + * Find occurrence of mem (with length mem_len) in pbuf p, starting at offset + * start_offset. + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param mem search for the contents of this buffer + * @param mem_len length of 'mem' + * @param start_offset offset into p at which to start searching + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) +{ + u16_t i; + u16_t max = p->tot_len - mem_len; + if (p->tot_len >= mem_len + start_offset) { + for (i = start_offset; i <= max; i++) { + u16_t plus = pbuf_memcmp(p, i, mem, mem_len); + if (plus == 0) { + return i; + } + } + } + return 0xFFFF; +} + +/** + * Find occurrence of substr with length substr_len in pbuf p, start at offset + * start_offset + * WARNING: in contrast to strstr(), this one does not stop at the first \0 in + * the pbuf/source string! + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param substr string to search for in p, maximum length is 0xFFFE + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_strstr(const struct pbuf* p, const char* substr) +{ + size_t substr_len; + if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { + return 0xFFFF; + } + substr_len = strlen(substr); + if (substr_len >= 0xFFFF) { + return 0xFFFF; + } + return pbuf_memfind(p, substr, (u16_t)substr_len, 0); +} diff --git a/components/net/lwip-2.0.3/src/core/raw.c b/components/net/lwip-2.0.3/src/core/raw.c new file mode 100644 index 0000000000..80cf9ec64b --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/raw.c @@ -0,0 +1,521 @@ +/** + * @file + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP.\n + * See also @ref raw_raw + * + * @defgroup raw_raw RAW + * @ingroup callbackstyle_api + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP.\n + * @see @ref raw_api + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/raw.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" + +#include + +/** The list of RAW PCBs */ +static struct raw_pcb *raw_pcbs; + +static u8_t +raw_input_match(struct raw_pcb *pcb, u8_t broadcast) +{ + LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ + if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { +#if IP_SOF_BROADCAST_RECV + if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { + return 0; + } +#endif /* IP_SOF_BROADCAST_RECV */ + return 1; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + /* Only need to check PCB if incoming IP version matches PCB IP version */ + if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { +#if LWIP_IPV4 + /* Special case: IPv4 broadcast: receive all broadcasts + * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ + if (broadcast != 0) { +#if IP_SOF_BROADCAST_RECV + if (ip_get_option(pcb, SOF_BROADCAST)) +#endif /* IP_SOF_BROADCAST_RECV */ + { + if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip))) { + return 1; + } + } + } else +#endif /* LWIP_IPV4 */ + /* Handle IPv4 and IPv6: catch all or exact match */ + if (ip_addr_isany(&pcb->local_ip) || + ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + return 1; + } + } + + return 0; +} + +/** + * Determine if in incoming IP packet is covered by a RAW PCB + * and if so, pass it to a user-provided receive callback function. + * + * Given an incoming IP datagram (as a chain of pbufs) this function + * finds a corresponding RAW PCB and calls the corresponding receive + * callback function. + * + * @param p pbuf to be demultiplexed to a RAW PCB. + * @param inp network interface on which the datagram was received. + * @return - 1 if the packet has been eaten by a RAW PCB receive + * callback function. The caller MAY NOT not reference the + * packet any longer, and MAY NOT call pbuf_free(). + * @return - 0 if packet is not eaten (pbuf is still referenced by the + * caller). + * + */ +u8_t +raw_input(struct pbuf *p, struct netif *inp) +{ + struct raw_pcb *pcb, *prev; + s16_t proto; + u8_t eaten = 0; + u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); + + LWIP_UNUSED_ARG(inp); + +#if LWIP_IPV6 +#if LWIP_IPV4 + if (IP_HDR_GET_VERSION(p->payload) == 6) +#endif /* LWIP_IPV4 */ + { + struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; + proto = IP6H_NEXTH(ip6hdr); + } +#if LWIP_IPV4 + else +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + { + proto = IPH_PROTO((struct ip_hdr *)p->payload); + } +#endif /* LWIP_IPV4 */ + + prev = NULL; + pcb = raw_pcbs; + /* loop through all raw pcbs until the packet is eaten by one */ + /* this allows multiple pcbs to match against the packet by design */ + while ((eaten == 0) && (pcb != NULL)) { + if ((pcb->protocol == proto) && raw_input_match(pcb, broadcast)) { + /* receive callback function available? */ + if (pcb->recv != NULL) { +#ifndef LWIP_NOASSERT + void* old_payload = p->payload; +#endif + /* the receive callback function did not eat the packet? */ + eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()); + if (eaten != 0) { + /* receive function ate the packet */ + p = NULL; + eaten = 1; + if (prev != NULL) { + /* move the pcb to the front of raw_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + } else { + /* sanity-check that the receive callback did not alter the pbuf */ + LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet", + p->payload == old_payload); + } + } + /* no receive callback function was set for this raw PCB */ + } + /* drop the packet */ + prev = pcb; + pcb = pcb->next; + } + return eaten; +} + +/** + * @ingroup raw_raw + * Bind a RAW PCB. + * + * @param pcb RAW PCB to be bound with a local address ipaddr. + * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to + * bind to all local interfaces. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_USE. The specified IP address is already bound to by + * another RAW PCB. + * + * @see raw_disconnect() + */ +err_t +raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) +{ + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); + return ERR_OK; +} + +/** + * @ingroup raw_raw + * Connect an RAW PCB. This function is required by upper layers + * of lwip. Using the raw api you could use raw_sendto() instead + * + * This will associate the RAW PCB with the remote address. + * + * @param pcb RAW PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * + * @return lwIP error code + * + * @see raw_disconnect() and raw_sendto() + */ +err_t +raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) +{ + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); + return ERR_OK; +} + +/** + * @ingroup raw_raw + * Set the callback function for received packets that match the + * raw PCB's protocol and binding. + * + * The callback function MUST either + * - eat the packet by calling pbuf_free() and returning non-zero. The + * packet will not be passed to other raw PCBs or other protocol layers. + * - not free the packet, and return zero. The packet will be matched + * against further PCBs and/or forwarded to another protocol layers. + */ +void +raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * @ingroup raw_raw + * Send the raw IP packet to the given address. Note that actually you cannot + * modify the IP headers (this is inconsistent with the receive callback where + * you actually get the IP headers), you can only specify the IP payload here. + * It requires some more changes in lwIP. (there will be a raw_send() function + * then.) + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * @param ipaddr the destination address of the IP packet + * + */ +err_t +raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) +{ + err_t err; + struct netif *netif; + const ip_addr_t *src_ip; + struct pbuf *q; /* q will be sent down the stack */ + s16_t header_size; + + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { + return ERR_VAL; + } + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); + + header_size = ( +#if LWIP_IPV4 && LWIP_IPV6 + IP_IS_V6(ipaddr) ? IP6_HLEN : IP_HLEN); +#elif LWIP_IPV4 + IP_HLEN); +#else + IP6_HLEN); +#endif + + /* not enough space to add an IP header to first pbuf in given p chain? */ + if (pbuf_header(p, header_size)) { + /* allocate header in new pbuf */ + q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p */ + pbuf_chain(q, p); + } + /* { first pbuf q points to header pbuf } */ + LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* first pbuf q equals given pbuf */ + q = p; + if (pbuf_header(q, -header_size)) { + LWIP_ASSERT("Can't restore header we just removed!", 0); + return ERR_MEM; + } + } + + if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { + /* Don't call ip_route() with IP_ANY_TYPE */ + netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr); + } else { + netif = ip_route(&pcb->local_ip, ipaddr); + } + + if (netif == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to ")); + ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_RTE; + } + +#if IP_SOF_BROADCAST + if (IP_IS_V4(ipaddr)) + { + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_VAL; + } + } +#endif /* IP_SOF_BROADCAST */ + + if (ip_addr_isany(&pcb->local_ip)) { + /* use outgoing network interface IP address as source address */ + src_ip = ip_netif_get_local_ip(netif, ipaddr); +#if LWIP_IPV6 + if (src_ip == NULL) { + if (q != p) { + pbuf_free(q); + } + return ERR_RTE; + } +#endif /* LWIP_IPV6 */ + } else { + /* use RAW PCB local IP address as source address */ + src_ip = &pcb->local_ip; + } + +#if LWIP_IPV6 + /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, + compute the checksum and update the checksum in the payload. */ + if (IP_IS_V6(ipaddr) && pcb->chksum_reqd) { + u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(ipaddr)); + LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2)); + SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t)); + } +#endif + + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); + err = ip_output_if(q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + /* did we chain a header earlier? */ + if (q != p) { + /* free the header */ + pbuf_free(q); + } + return err; +} + +/** + * @ingroup raw_raw + * Send the raw IP packet to the address given by raw_connect() + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * + */ +err_t +raw_send(struct raw_pcb *pcb, struct pbuf *p) +{ + return raw_sendto(pcb, p, &pcb->remote_ip); +} + +/** + * @ingroup raw_raw + * Remove an RAW PCB. + * + * @param pcb RAW PCB to be removed. The PCB is removed from the list of + * RAW PCB's and the data structure is freed from memory. + * + * @see raw_new() + */ +void +raw_remove(struct raw_pcb *pcb) +{ + struct raw_pcb *pcb2; + /* pcb to be removed is first in list? */ + if (raw_pcbs == pcb) { + /* make list start at 2nd pcb */ + raw_pcbs = raw_pcbs->next; + /* pcb not 1st in list */ + } else { + for (pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in raw_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + break; + } + } + } + memp_free(MEMP_RAW_PCB, pcb); +} + +/** + * @ingroup raw_raw + * Create a RAW PCB. + * + * @return The RAW PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) + * + * @see raw_remove() + */ +struct raw_pcb * +raw_new(u8_t proto) +{ + struct raw_pcb *pcb; + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); + + pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); + /* could allocate RAW PCB? */ + if (pcb != NULL) { + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct raw_pcb)); + pcb->protocol = proto; + pcb->ttl = RAW_TTL; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + return pcb; +} + +/** + * @ingroup raw_raw + * Create a RAW PCB for specific IP type. + * + * @return The RAW PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @param type IP address type, see @ref lwip_ip_addr_type definitions. + * If you want to listen to IPv4 and IPv6 (dual-stack) packets, + * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. + * @param proto the protocol number (next header) of the IPv6 packet payload + * (e.g. IP6_NEXTH_ICMP6) + * + * @see raw_remove() + */ +struct raw_pcb * +raw_new_ip_type(u8_t type, u8_t proto) +{ + struct raw_pcb *pcb; + pcb = raw_new(proto); +#if LWIP_IPV4 && LWIP_IPV6 + if (pcb != NULL) { + IP_SET_TYPE_VAL(pcb->local_ip, type); + IP_SET_TYPE_VAL(pcb->remote_ip, type); + } +#else /* LWIP_IPV4 && LWIP_IPV6 */ + LWIP_UNUSED_ARG(type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + return pcb; +} + +/** This function is called from netif.c when address is changed + * + * @param old_addr IP address of the netif before change + * @param new_addr IP address of the netif after change + */ +void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) +{ + struct raw_pcb* rpcb; + + if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { + for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&rpcb->local_ip, old_addr)) { + /* The PCB is bound to the old ipaddr and + * is set to bound to the new one instead */ + ip_addr_copy(rpcb->local_ip, *new_addr); + } + } + } +} + +#endif /* LWIP_RAW */ diff --git a/components/net/lwip-2.0.3/src/core/stats.c b/components/net/lwip-2.0.3/src/core/stats.c new file mode 100644 index 0000000000..893d199c04 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/stats.c @@ -0,0 +1,169 @@ +/** + * @file + * Statistics module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/debug.h" + +#include + +struct stats_ lwip_stats; + +void +stats_init(void) +{ +#ifdef LWIP_DEBUG +#if MEM_STATS + lwip_stats.mem.name = "MEM"; +#endif /* MEM_STATS */ +#endif /* LWIP_DEBUG */ +} + +#if LWIP_STATS_DISPLAY +void +stats_display_proto(struct stats_proto *proto, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); + LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr)); + LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr)); + LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr)); + LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err)); + LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); +} + +#if IGMP_STATS || MLD6_STATS +void +stats_display_igmp(struct stats_igmp *igmp, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr)); + LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1)); + LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group)); + LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general)); + LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report)); + LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join)); + LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); + LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n", igmp->tx_report)); +} +#endif /* IGMP_STATS || MLD6_STATS */ + +#if MEM_STATS || MEMP_STATS +void +stats_display_mem(struct stats_mem *mem, const char *name) +{ + LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name)); + LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail)); + LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used)); + LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max)); + LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err)); +} + +#if MEMP_STATS +void +stats_display_memp(struct stats_mem *mem, int index) +{ + if (index < MEMP_MAX) { + stats_display_mem(mem, mem->name); + } +} +#endif /* MEMP_STATS */ +#endif /* MEM_STATS || MEMP_STATS */ + +#if SYS_STATS +void +stats_display_sys(struct stats_sys *sys) +{ + LWIP_PLATFORM_DIAG(("\nSYS\n\t")); + LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); + LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max)); + LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err)); + LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used)); + LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max)); + LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err)); + LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); + LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max)); + LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n", (u32_t)sys->mbox.err)); +} +#endif /* SYS_STATS */ + +void +stats_display(void) +{ + s16_t i; + + LINK_STATS_DISPLAY(); + ETHARP_STATS_DISPLAY(); + IPFRAG_STATS_DISPLAY(); + IP6_FRAG_STATS_DISPLAY(); + IP_STATS_DISPLAY(); + ND6_STATS_DISPLAY(); + IP6_STATS_DISPLAY(); + IGMP_STATS_DISPLAY(); + MLD6_STATS_DISPLAY(); + ICMP_STATS_DISPLAY(); + ICMP6_STATS_DISPLAY(); + UDP_STATS_DISPLAY(); + TCP_STATS_DISPLAY(); + MEM_STATS_DISPLAY(); + for (i = 0; i < MEMP_MAX; i++) { + MEMP_STATS_DISPLAY(i); + } + SYS_STATS_DISPLAY(); +} +#endif /* LWIP_STATS_DISPLAY */ + +#endif /* LWIP_STATS */ + diff --git a/components/net/lwip-2.0.3/src/core/sys.c b/components/net/lwip-2.0.3/src/core/sys.c new file mode 100644 index 0000000000..7059b4de5b --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/sys.c @@ -0,0 +1,106 @@ +/** + * @file + * lwIP Operating System abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/** + * @defgroup sys_layer Porting (system abstraction layer) + * @ingroup lwip + * @verbinclude "sys_arch.txt" + * + * @defgroup sys_os OS abstraction layer + * @ingroup sys_layer + * No need to implement functions in this section in NO_SYS mode. + * + * @defgroup sys_sem Semaphores + * @ingroup sys_os + * + * @defgroup sys_mutex Mutexes + * @ingroup sys_os + * Mutexes are recommended to correctly handle priority inversion, + * especially if you use LWIP_CORE_LOCKING . + * + * @defgroup sys_mbox Mailboxes + * @ingroup sys_os + * + * @defgroup sys_time Time + * @ingroup sys_layer + * + * @defgroup sys_prot Critical sections + * @ingroup sys_layer + * Used to protect short regions of code against concurrent access. + * - Your system is a bare-metal system (probably with an RTOS) + * and interrupts are under your control: + * Implement this as LockInterrupts() / UnlockInterrupts() + * - Your system uses an RTOS with deferred interrupt handling from a + * worker thread: Implement as a global mutex or lock/unlock scheduler + * - Your system uses a high-level OS with e.g. POSIX signals: + * Implement as a global mutex + * + * @defgroup sys_misc Misc + * @ingroup sys_os + */ + +#include "lwip/opt.h" + +#include "lwip/sys.h" + +/* Most of the functions defined in sys.h must be implemented in the + * architecture-dependent file sys_arch.c */ + +#if !NO_SYS + +#ifndef sys_msleep +/** + * Sleep for some ms. Timeouts are NOT processed while sleeping. + * + * @param ms number of milliseconds to sleep + */ +void +sys_msleep(u32_t ms) +{ + if (ms > 0) { + sys_sem_t delaysem; + err_t err = sys_sem_new(&delaysem, 0); + if (err == ERR_OK) { + sys_arch_sem_wait(&delaysem, ms); + sys_sem_free(&delaysem); + } + } +} +#endif /* sys_msleep */ + +#endif /* !NO_SYS */ diff --git a/components/net/lwip-2.0.3/src/core/tcp.c b/components/net/lwip-2.0.3/src/core/tcp.c new file mode 100644 index 0000000000..b5144d2f1f --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/tcp.c @@ -0,0 +1,2169 @@ +/** + * @file + * Transmission Control Protocol for IP + * See also @ref tcp_raw + * + * @defgroup tcp_raw TCP + * @ingroup callbackstyle_api + * Transmission Control Protocol for IP\n + * @see @ref raw_api and @ref netconn + * + * Common functions for the TCP implementation, such as functinos + * for manipulating the data structures and the TCP timer functions. TCP functions + * related to input and output is found in tcp_in.c and tcp_out.c respectively.\n + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/nd6.h" + +#include + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +#ifndef TCP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define TCP_LOCAL_PORT_RANGE_START 0xc000 +#define TCP_LOCAL_PORT_RANGE_END 0xffff +#define TCP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START)) +#endif + +#if LWIP_TCP_KEEPALIVE +#define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl) +#define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl) +#else /* LWIP_TCP_KEEPALIVE */ +#define TCP_KEEP_DUR(pcb) TCP_MAXIDLE +#define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT +#endif /* LWIP_TCP_KEEPALIVE */ + +/* As initial send MSS, we use TCP_MSS but limit it to 536. */ +#if TCP_MSS > 536 +#define INITIAL_MSS 536 +#else +#define INITIAL_MSS TCP_MSS +#endif + +static const char * const tcp_state_str[] = { + "CLOSED", + "LISTEN", + "SYN_SENT", + "SYN_RCVD", + "ESTABLISHED", + "FIN_WAIT_1", + "FIN_WAIT_2", + "CLOSE_WAIT", + "CLOSING", + "LAST_ACK", + "TIME_WAIT" +}; + +/* last local TCP port */ +static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; + +/* Incremented every coarse grained timer shot (typically every 500 ms). */ +u32_t tcp_ticks; +static const u8_t tcp_backoff[13] = + { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; + /* Times per slowtmr hits */ +static const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; + +/* The TCP PCB lists. */ + +/** List of all TCP PCBs bound but not yet (connected || listening) */ +struct tcp_pcb *tcp_bound_pcbs; +/** List of all TCP PCBs in LISTEN state */ +union tcp_listen_pcbs_t tcp_listen_pcbs; +/** List of all TCP PCBs that are in a state in which + * they accept or send data. */ +struct tcp_pcb *tcp_active_pcbs; +/** List of all TCP PCBs in TIME-WAIT state */ +struct tcp_pcb *tcp_tw_pcbs; + +/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ +struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, + &tcp_active_pcbs, &tcp_tw_pcbs}; + +u8_t tcp_active_pcbs_changed; + +/** Timer counter to handle calling slow-timer from tcp_tmr() */ +static u8_t tcp_timer; +static u8_t tcp_timer_ctr; +static u16_t tcp_new_port(void); + +static err_t tcp_close_shutdown_fin(struct tcp_pcb *pcb); + +/** + * Initialize this module. + */ +void +tcp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Called periodically to dispatch TCP timers. + */ +void +tcp_tmr(void) +{ + /* Call tcp_fasttmr() every 250 ms */ + tcp_fasttmr(); + + if (++tcp_timer & 1) { + /* Call tcp_slowtmr() every 500 ms, i.e., every other timer + tcp_tmr() is called. */ + tcp_slowtmr(); + } +} + +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG +/** Called when a listen pcb is closed. Iterates one pcb list and removes the + * closed listener pcb from pcb->listener if matching. + */ +static void +tcp_remove_listener(struct tcp_pcb *list, struct tcp_pcb_listen *lpcb) +{ + struct tcp_pcb *pcb; + for (pcb = list; pcb != NULL; pcb = pcb->next) { + if (pcb->listener == lpcb) { + pcb->listener = NULL; + } + } +} +#endif + +/** Called when a listen pcb is closed. Iterates all pcb lists and removes the + * closed listener pcb from pcb->listener if matching. + */ +static void +tcp_listen_closed(struct tcp_pcb *pcb) +{ +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG + size_t i; + LWIP_ASSERT("pcb != NULL", pcb != NULL); + LWIP_ASSERT("pcb->state == LISTEN", pcb->state == LISTEN); + for (i = 1; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { + tcp_remove_listener(*tcp_pcb_lists[i], (struct tcp_pcb_listen*)pcb); + } +#endif + LWIP_UNUSED_ARG(pcb); +} + +#if TCP_LISTEN_BACKLOG +/** @ingroup tcp_raw + * Delay accepting a connection in respect to the listen backlog: + * the number of outstanding connections is increased until + * tcp_backlog_accepted() is called. + * + * ATTENTION: the caller is responsible for calling tcp_backlog_accepted() + * or else the backlog feature will get out of sync! + * + * @param pcb the connection pcb which is not fully accepted yet + */ +void +tcp_backlog_delayed(struct tcp_pcb* pcb) +{ + LWIP_ASSERT("pcb != NULL", pcb != NULL); + if ((pcb->flags & TF_BACKLOGPEND) == 0) { + if (pcb->listener != NULL) { + pcb->listener->accepts_pending++; + LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); + pcb->flags |= TF_BACKLOGPEND; + } + } +} + +/** @ingroup tcp_raw + * A delayed-accept a connection is accepted (or closed/aborted): decreases + * the number of outstanding connections after calling tcp_backlog_delayed(). + * + * ATTENTION: the caller is responsible for calling tcp_backlog_accepted() + * or else the backlog feature will get out of sync! + * + * @param pcb the connection pcb which is now fully accepted (or closed/aborted) + */ +void +tcp_backlog_accepted(struct tcp_pcb* pcb) +{ + LWIP_ASSERT("pcb != NULL", pcb != NULL); + if ((pcb->flags & TF_BACKLOGPEND) != 0) { + if (pcb->listener != NULL) { + LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); + pcb->listener->accepts_pending--; + pcb->flags &= ~TF_BACKLOGPEND; + } + } +} +#endif /* TCP_LISTEN_BACKLOG */ + +/** + * Closes the TX side of a connection held by the PCB. + * For tcp_close(), a RST is sent if the application didn't receive all data + * (tcp_recved() not called for all data passed to recv callback). + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it. + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +static err_t +tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) +{ + if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { + if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND_MAX(pcb))) { + /* Not all data received by application, send RST to tell the remote + side about this. */ + LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED); + + /* don't call tcp_abort here: we must not deallocate the pcb since + that might not be expected when calling tcp_close */ + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + if (pcb->state == ESTABLISHED) { + /* move to TIME_WAIT since we close actively */ + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + /* CLOSE_WAIT: deallocate the pcb since we already sent a RST for it */ + if (tcp_input_pcb == pcb) { + /* prevent using a deallocated pcb: free it from tcp_input later */ + tcp_trigger_input_pcb_close(); + } else { + memp_free(MEMP_TCP_PCB, pcb); + } + } + return ERR_OK; + } + } + + /* - states which free the pcb are handled here, + - states which send FIN and change state are handled in tcp_close_shutdown_fin() */ + switch (pcb->state) { + case CLOSED: + /* Closing a pcb in the CLOSED state might seem erroneous, + * however, it is in this state once allocated and as yet unused + * and the user needs some way to free it should the need arise. + * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) + * or for a pcb that has been used and then entered the CLOSED state + * is erroneous, but this should never happen as the pcb has in those cases + * been freed, and so any remaining handles are bogus. */ + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); + break; + case LISTEN: + tcp_listen_closed(pcb); + tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); + memp_free(MEMP_TCP_PCB_LISTEN, pcb); + break; + case SYN_SENT: + TCP_PCB_REMOVE_ACTIVE(pcb); + memp_free(MEMP_TCP_PCB, pcb); + MIB2_STATS_INC(mib2.tcpattemptfails); + break; + default: + return tcp_close_shutdown_fin(pcb); + } + return ERR_OK; +} + +static err_t +tcp_close_shutdown_fin(struct tcp_pcb *pcb) +{ + err_t err; + LWIP_ASSERT("pcb != NULL", pcb != NULL); + + switch (pcb->state) { + case SYN_RCVD: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + tcp_backlog_accepted(pcb); + MIB2_STATS_INC(mib2.tcpattemptfails); + pcb->state = FIN_WAIT_1; + } + break; + case ESTABLISHED: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + MIB2_STATS_INC(mib2.tcpestabresets); + pcb->state = FIN_WAIT_1; + } + break; + case CLOSE_WAIT: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + MIB2_STATS_INC(mib2.tcpestabresets); + pcb->state = LAST_ACK; + } + break; + default: + /* Has already been closed, do nothing. */ + return ERR_OK; + } + + if (err == ERR_OK) { + /* To ensure all data has been sent when tcp_close returns, we have + to make sure tcp_output doesn't fail. + Since we don't really have to ensure all data has been sent when tcp_close + returns (unsent data is sent from tcp timer functions, also), we don't care + for the return value of tcp_output for now. */ + tcp_output(pcb); + } else if (err == ERR_MEM) { + /* Mark this pcb for closing. Closing is retried from tcp_tmr. */ + pcb->flags |= TF_CLOSEPEND; + /* We have to return ERR_OK from here to indicate to the callers that this + pcb should not be used any more as it will be freed soon via tcp_tmr. + This is OK here since sending FIN does not guarantee a time frime for + actually freeing the pcb, either (it is left in closure states for + remote ACK or timeout) */ + return ERR_OK; + } + return err; +} + +/** + * @ingroup tcp_raw + * Closes the connection held by the PCB. + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it (unless an error is returned). + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +err_t +tcp_close(struct tcp_pcb *pcb) +{ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); + tcp_debug_print_state(pcb->state); + + if (pcb->state != LISTEN) { + /* Set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + } + /* ... and close */ + return tcp_close_shutdown(pcb, 1); +} + +/** + * @ingroup tcp_raw + * Causes all or part of a full-duplex connection of this PCB to be shut down. + * This doesn't deallocate the PCB unless shutting down both sides! + * Shutting down both sides is the same as calling tcp_close, so if it succeds + * (i.e. returns ER_OK), the PCB must not be referenced any more! + * + * @param pcb PCB to shutdown + * @param shut_rx shut down receive side if this is != 0 + * @param shut_tx shut down send side if this is != 0 + * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) + * another err_t on error. + */ +err_t +tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) +{ + if (pcb->state == LISTEN) { + return ERR_CONN; + } + if (shut_rx) { + /* shut down the receive side: set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + if (shut_tx) { + /* shutting down the tx AND rx side is the same as closing for the raw API */ + return tcp_close_shutdown(pcb, 1); + } + /* ... and free buffered data */ + if (pcb->refused_data != NULL) { + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + } + if (shut_tx) { + /* This can't happen twice since if it succeeds, the pcb's state is changed. + Only close in these states as the others directly deallocate the PCB */ + switch (pcb->state) { + case SYN_RCVD: + case ESTABLISHED: + case CLOSE_WAIT: + return tcp_close_shutdown(pcb, (u8_t)shut_rx); + default: + /* Not (yet?) connected, cannot shutdown the TX side as that would bring us + into CLOSED state, where the PCB is deallocated. */ + return ERR_CONN; + } + } + return ERR_OK; +} + +/** + * Abandons a connection and optionally sends a RST to the remote + * host. Deletes the local protocol control block. This is done when + * a connection is killed because of shortage of memory. + * + * @param pcb the tcp_pcb to abort + * @param reset boolean to indicate whether a reset should be sent + */ +void +tcp_abandon(struct tcp_pcb *pcb, int reset) +{ + u32_t seqno, ackno; +#if LWIP_CALLBACK_API + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + void *errf_arg; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs", + pcb->state != LISTEN); + /* Figure out on which TCP PCB list we are, and remove us. If we + are in an active state, call the receive function associated with + the PCB with a NULL argument, and send an RST to the remote end. */ + if (pcb->state == TIME_WAIT) { + tcp_pcb_remove(&tcp_tw_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + int send_rst = 0; + u16_t local_port = 0; + enum tcp_state last_state; + seqno = pcb->snd_nxt; + ackno = pcb->rcv_nxt; +#if LWIP_CALLBACK_API + errf = pcb->errf; +#endif /* LWIP_CALLBACK_API */ + errf_arg = pcb->callback_arg; + if (pcb->state == CLOSED) { + if (pcb->local_port != 0) { + /* bound, not yet opened */ + TCP_RMV(&tcp_bound_pcbs, pcb); + } + } else { + send_rst = reset; + local_port = pcb->local_port; + TCP_PCB_REMOVE_ACTIVE(pcb); + } + if (pcb->unacked != NULL) { + tcp_segs_free(pcb->unacked); + } + if (pcb->unsent != NULL) { + tcp_segs_free(pcb->unsent); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + tcp_segs_free(pcb->ooseq); + } +#endif /* TCP_QUEUE_OOSEQ */ + tcp_backlog_accepted(pcb); + if (send_rst) { + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); + tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port); + } + last_state = pcb->state; + memp_free(MEMP_TCP_PCB, pcb); + TCP_EVENT_ERR(last_state, errf, errf_arg, ERR_ABRT); + } +} + +/** + * @ingroup tcp_raw + * Aborts the connection by sending a RST (reset) segment to the remote + * host. The pcb is deallocated. This function never fails. + * + * ATTENTION: When calling this from one of the TCP callbacks, make + * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise + * or you will risk accessing deallocated memory or memory leaks! + * + * @param pcb the tcp pcb to abort + */ +void +tcp_abort(struct tcp_pcb *pcb) +{ + tcp_abandon(pcb, 1); +} + +/** + * @ingroup tcp_raw + * Binds the connection to a local port number and IP address. If the + * IP address is not given (i.e., ipaddr == NULL), the IP address of + * the outgoing network interface is used instead. + * + * @param pcb the tcp_pcb to bind (no check is done whether this pcb is + * already bound!) + * @param ipaddr the local ip address to bind to (use IP4_ADDR_ANY to bind + * to any local address + * @param port the local port to bind to + * @return ERR_USE if the port is already in use + * ERR_VAL if bind failed because the PCB is not in a valid state + * ERR_OK if bound + */ +err_t +tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) +{ + int i; + int max_pcb_list = NUM_TCP_PCB_LISTS; + struct tcp_pcb *cpcb; + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ + if (ipaddr == NULL) { + ipaddr = IP4_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + + /* still need to check for ipaddr == NULL in IPv6 only case */ + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + + LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); + +#if SO_REUSE + /* Unless the REUSEADDR flag is set, + we have to check the pcbs in TIME-WAIT state, also. + We do not dump TIME_WAIT pcb's; they can still be matched by incoming + packets using both local and remote IP addresses and ports to distinguish. + */ + if (ip_get_option(pcb, SOF_REUSEADDR)) { + max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; + } +#endif /* SO_REUSE */ + + if (port == 0) { + port = tcp_new_port(); + if (port == 0) { + return ERR_BUF; + } + } else { + /* Check if the address already is in use (on all lists) */ + for (i = 0; i < max_pcb_list; i++) { + for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->local_port == port) { +#if SO_REUSE + /* Omit checking for the same port if both pcbs have REUSEADDR set. + For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in + tcp_connect. */ + if (!ip_get_option(pcb, SOF_REUSEADDR) || + !ip_get_option(cpcb, SOF_REUSEADDR)) +#endif /* SO_REUSE */ + { + /* @todo: check accept_any_ip_version */ + if ((IP_IS_V6(ipaddr) == IP_IS_V6_VAL(cpcb->local_ip)) && + (ip_addr_isany(&cpcb->local_ip) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&cpcb->local_ip, ipaddr))) { + return ERR_USE; + } + } + } + } + } + } + + if (!ip_addr_isany(ipaddr)) { + ip_addr_set(&pcb->local_ip, ipaddr); + } + pcb->local_port = port; + TCP_REG(&tcp_bound_pcbs, pcb); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); + return ERR_OK; +} +#if LWIP_CALLBACK_API +/** + * Default accept callback if no accept callback is specified by the user. + */ +static err_t +tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) +{ + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(err); + + tcp_abort(pcb); + + return ERR_ABRT; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * @ingroup tcp_raw + * Set the state of the connection to be LISTEN, which means that it + * is able to accept incoming connections. The protocol control block + * is reallocated in order to consume less memory. Setting the + * connection to LISTEN is an irreversible process. + * + * @param pcb the original tcp_pcb + * @param backlog the incoming connections queue limit + * @return tcp_pcb used for listening, consumes less memory. + * + * @note The original tcp_pcb is freed. This function therefore has to be + * called like this: + * tpcb = tcp_listen_with_backlog(tpcb, backlog); + */ +struct tcp_pcb * +tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) +{ + return tcp_listen_with_backlog_and_err(pcb, backlog, NULL); +} + +/** + * @ingroup tcp_raw + * Set the state of the connection to be LISTEN, which means that it + * is able to accept incoming connections. The protocol control block + * is reallocated in order to consume less memory. Setting the + * connection to LISTEN is an irreversible process. + * + * @param pcb the original tcp_pcb + * @param backlog the incoming connections queue limit + * @param err when NULL is returned, this contains the error reason + * @return tcp_pcb used for listening, consumes less memory. + * + * @note The original tcp_pcb is freed. This function therefore has to be + * called like this: + * tpcb = tcp_listen_with_backlog_and_err(tpcb, backlog, &err); + */ +struct tcp_pcb * +tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err) +{ + struct tcp_pcb_listen *lpcb = NULL; + err_t res; + + LWIP_UNUSED_ARG(backlog); + LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, res = ERR_CLSD; goto done); + + /* already listening? */ + if (pcb->state == LISTEN) { + lpcb = (struct tcp_pcb_listen*)pcb; + res = ERR_ALREADY; + goto done; + } +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage + is declared (listen-/connection-pcb), we have to make sure now that + this port is only used once for every local IP. */ + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((lpcb->local_port == pcb->local_port) && + ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) { + /* this address/port is already used */ + lpcb = NULL; + res = ERR_USE; + goto done; + } + } + } +#endif /* SO_REUSE */ + lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN); + if (lpcb == NULL) { + res = ERR_MEM; + goto done; + } + lpcb->callback_arg = pcb->callback_arg; + lpcb->local_port = pcb->local_port; + lpcb->state = LISTEN; + lpcb->prio = pcb->prio; + lpcb->so_options = pcb->so_options; + lpcb->ttl = pcb->ttl; + lpcb->tos = pcb->tos; +#if LWIP_IPV4 && LWIP_IPV6 + IP_SET_TYPE_VAL(lpcb->remote_ip, pcb->local_ip.type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + ip_addr_copy(lpcb->local_ip, pcb->local_ip); + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); +#if LWIP_CALLBACK_API + lpcb->accept = tcp_accept_null; +#endif /* LWIP_CALLBACK_API */ +#if TCP_LISTEN_BACKLOG + lpcb->accepts_pending = 0; + tcp_backlog_set(lpcb, backlog); +#endif /* TCP_LISTEN_BACKLOG */ + TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); + res = ERR_OK; +done: + if (err != NULL) { + *err = res; + } + return (struct tcp_pcb *)lpcb; +} + +/** + * Update the state that tracks the available window space to advertise. + * + * Returns how much extra window would be advertised if we sent an + * update now. + */ +u32_t +tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) +{ + u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; + + if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { + /* we can advertise more window */ + pcb->rcv_ann_wnd = pcb->rcv_wnd; + return new_right_edge - pcb->rcv_ann_right_edge; + } else { + if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { + /* Can happen due to other end sending out of advertised window, + * but within actual available (but not yet advertised) window */ + pcb->rcv_ann_wnd = 0; + } else { + /* keep the right edge of window constant */ + u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; +#if !LWIP_WND_SCALE + LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); +#endif + pcb->rcv_ann_wnd = (tcpwnd_size_t)new_rcv_ann_wnd; + } + return 0; + } +} + +/** + * @ingroup tcp_raw + * This function should be called by the application when it has + * processed the data. The purpose is to advertise a larger window + * when the data has been processed. + * + * @param pcb the tcp_pcb for which data is read + * @param len the amount of bytes that have been read by the application + */ +void +tcp_recved(struct tcp_pcb *pcb, u16_t len) +{ + int wnd_inflation; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_recved for listen-pcbs", + pcb->state != LISTEN); + + pcb->rcv_wnd += len; + if (pcb->rcv_wnd > TCP_WND_MAX(pcb)) { + pcb->rcv_wnd = TCP_WND_MAX(pcb); + } else if (pcb->rcv_wnd == 0) { + /* rcv_wnd overflowed */ + if ((pcb->state == CLOSE_WAIT) || (pcb->state == LAST_ACK)) { + /* In passive close, we allow this, since the FIN bit is added to rcv_wnd + by the stack itself, since it is not mandatory for an application + to call tcp_recved() for the FIN bit, but e.g. the netconn API does so. */ + pcb->rcv_wnd = TCP_WND_MAX(pcb); + } else { + LWIP_ASSERT("tcp_recved: len wrapped rcv_wnd\n", 0); + } + } + + wnd_inflation = tcp_update_rcv_ann_wnd(pcb); + + /* If the change in the right edge of window is significant (default + * watermark is TCP_WND/4), then send an explicit update now. + * Otherwise wait for a packet to be sent in the normal course of + * events (or more window to be available later) */ + if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { + tcp_ack_now(pcb); + tcp_output(pcb); + } + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: received %"U16_F" bytes, wnd %"TCPWNDSIZE_F" (%"TCPWNDSIZE_F").\n", + len, pcb->rcv_wnd, (u16_t)(TCP_WND_MAX(pcb) - pcb->rcv_wnd))); +} + +/** + * Allocate a new local TCP port. + * + * @return a new (free) local TCP port number + */ +static u16_t +tcp_new_port(void) +{ + u8_t i; + u16_t n = 0; + struct tcp_pcb *pcb; + +again: + if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) { + tcp_port = TCP_LOCAL_PORT_RANGE_START; + } + /* Check all PCB lists. */ + for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { + for (pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == tcp_port) { + if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + } + return tcp_port; +} + +/** + * @ingroup tcp_raw + * Connects to another host. The function given as the "connected" + * argument will be called when the connection has been established. + * + * @param pcb the tcp_pcb used to establish the connection + * @param ipaddr the remote ip address to connect to + * @param port the remote tcp port to connect to + * @param connected callback function to call when connected (on error, + the err calback will be called) + * @return ERR_VAL if invalid arguments are given + * ERR_OK if connect request has been sent + * other err_t values if connect request couldn't be sent + */ +err_t +tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port, + tcp_connected_fn connected) +{ + err_t ret; + u32_t iss; + u16_t old_local_port; + + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + + LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); + ip_addr_set(&pcb->remote_ip, ipaddr); + pcb->remote_port = port; + + /* check if we have a route to the remote host */ + if (ip_addr_isany(&pcb->local_ip)) { + /* no local IP address set, yet. */ + struct netif *netif; + const ip_addr_t *local_ip; + ip_route_get_local_ip(&pcb->local_ip, &pcb->remote_ip, netif, local_ip); + if ((netif == NULL) || (local_ip == NULL)) { + /* Don't even try to send a SYN packet if we have no route + since that will fail. */ + return ERR_RTE; + } + /* Use the address as local address of the pcb. */ + ip_addr_copy(pcb->local_ip, *local_ip); + } + + old_local_port = pcb->local_port; + if (pcb->local_port == 0) { + pcb->local_port = tcp_new_port(); + if (pcb->local_port == 0) { + return ERR_BUF; + } + } else { +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure + now that the 5-tuple is unique. */ + struct tcp_pcb *cpcb; + int i; + /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ + for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { + for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if ((cpcb->local_port == pcb->local_port) && + (cpcb->remote_port == port) && + ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) && + ip_addr_cmp(&cpcb->remote_ip, ipaddr)) { + /* linux returns EISCONN here, but ERR_USE should be OK for us */ + return ERR_USE; + } + } + } + } +#endif /* SO_REUSE */ + } + + iss = tcp_next_iss(pcb); + pcb->rcv_nxt = 0; + pcb->snd_nxt = iss; + pcb->lastack = iss - 1; + pcb->snd_wl2 = iss - 1; + pcb->snd_lbb = iss - 1; + /* Start with a window that does not need scaling. When window scaling is + enabled and used, the window is enlarged when both sides agree on scaling. */ + pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->snd_wnd = TCP_WND; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = INITIAL_MSS; +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + pcb->cwnd = 1; +#if LWIP_CALLBACK_API + pcb->connected = connected; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(connected); +#endif /* LWIP_CALLBACK_API */ + + /* Send a SYN together with the MSS option. */ + ret = tcp_enqueue_flags(pcb, TCP_SYN); + if (ret == ERR_OK) { + /* SYN segment was enqueued, changed the pcbs state now */ + pcb->state = SYN_SENT; + if (old_local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + TCP_REG_ACTIVE(pcb); + MIB2_STATS_INC(mib2.tcpactiveopens); + + tcp_output(pcb); + } + return ret; +} + +/** + * Called every 500 ms and implements the retransmission timer and the timer that + * removes PCBs that have been in TIME-WAIT for enough time. It also increments + * various timers such as the inactivity timer in each PCB. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_slowtmr(void) +{ + struct tcp_pcb *pcb, *prev; + tcpwnd_size_t eff_wnd; + u8_t pcb_remove; /* flag if a PCB should be removed */ + u8_t pcb_reset; /* flag if a RST should be sent when removing */ + err_t err; + + err = ERR_OK; + + ++tcp_ticks; + ++tcp_timer_ctr; + +tcp_slowtmr_start: + /* Steps through all of the active PCBs. */ + prev = NULL; + pcb = tcp_active_pcbs; + if (pcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); + } + while (pcb != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); + if (pcb->last_timer == tcp_timer_ctr) { + /* skip this pcb, we have already processed it */ + pcb = pcb->next; + continue; + } + pcb->last_timer = tcp_timer_ctr; + + pcb_remove = 0; + pcb_reset = 0; + + if (pcb->state == SYN_SENT && pcb->nrtx >= TCP_SYNMAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); + } + else if (pcb->nrtx >= TCP_MAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); + } else { + if (pcb->persist_backoff > 0) { + /* If snd_wnd is zero, use persist timer to send 1 byte probes + * instead of using the standard retransmission mechanism. */ + u8_t backoff_cnt = tcp_persist_backoff[pcb->persist_backoff-1]; + if (pcb->persist_cnt < backoff_cnt) { + pcb->persist_cnt++; + } + if (pcb->persist_cnt >= backoff_cnt) { + if (tcp_zero_window_probe(pcb) == ERR_OK) { + pcb->persist_cnt = 0; + if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { + pcb->persist_backoff++; + } + } + } + } else { + /* Increase the retransmission timer if it is running */ + if (pcb->rtime >= 0) { + ++pcb->rtime; + } + + if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { + /* Time for a retransmission. */ + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F + " pcb->rto %"S16_F"\n", + pcb->rtime, pcb->rto)); + + /* Double retransmission time-out unless we are trying to + * connect to somebody (i.e., we are in SYN_SENT). */ + if (pcb->state != SYN_SENT) { + u8_t backoff_idx = LWIP_MIN(pcb->nrtx, sizeof(tcp_backoff)-1); + pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[backoff_idx]; + } + + /* Reset the retransmission timer. */ + pcb->rtime = 0; + + /* Reduce congestion window and ssthresh. */ + eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); + pcb->ssthresh = eff_wnd >> 1; + if (pcb->ssthresh < (tcpwnd_size_t)(pcb->mss << 1)) { + pcb->ssthresh = (pcb->mss << 1); + } + pcb->cwnd = pcb->mss; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + + /* The following needs to be called AFTER cwnd is set to one + mss - STJ */ + tcp_rexmit_rto(pcb); + } + } + } + /* Check if this PCB has stayed too long in FIN-WAIT-2 */ + if (pcb->state == FIN_WAIT_2) { + /* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */ + if (pcb->flags & TF_RXCLOSED) { + /* PCB was fully closed (either through close() or SHUT_RDWR): + normal FIN-WAIT timeout handling. */ + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); + } + } + } + + /* Check if KEEPALIVE should be sent */ + if (ip_get_option(pcb, SOF_KEEPALIVE) && + ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT))) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) + { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to ")); + ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + ++pcb_remove; + ++pcb_reset; + } else if ((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb)) + / TCP_SLOW_INTERVAL) + { + err = tcp_keepalive(pcb); + if (err == ERR_OK) { + pcb->keep_cnt_sent++; + } + } + } + + /* If this PCB has queued out of sequence data, but has been + inactive for too long, will drop the data (it will eventually + be retransmitted). */ +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL && + (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); + } +#endif /* TCP_QUEUE_OOSEQ */ + + /* Check if this PCB has stayed too long in SYN-RCVD */ + if (pcb->state == SYN_RCVD) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); + } + } + + /* Check if this PCB has stayed too long in LAST-ACK */ + if (pcb->state == LAST_ACK) { + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); + } + } + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; +#if LWIP_CALLBACK_API + tcp_err_fn err_fn = pcb->errf; +#endif /* LWIP_CALLBACK_API */ + void *err_arg; + enum tcp_state last_state; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_active_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); + tcp_active_pcbs = pcb->next; + } + + if (pcb_reset) { + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + } + + err_arg = pcb->callback_arg; + last_state = pcb->state; + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + + tcp_active_pcbs_changed = 0; + TCP_EVENT_ERR(last_state, err_fn, err_arg, ERR_ABRT); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + } else { + /* get the 'next' element now and work with 'prev' below (in case of abort) */ + prev = pcb; + pcb = pcb->next; + + /* We check if we should poll the connection. */ + ++prev->polltmr; + if (prev->polltmr >= prev->pollinterval) { + prev->polltmr = 0; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); + tcp_active_pcbs_changed = 0; + TCP_EVENT_POLL(prev, err); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + /* if err == ERR_ABRT, 'prev' is already deallocated */ + if (err == ERR_OK) { + tcp_output(prev); + } + } + } + } + + + /* Steps through all of the TIME-WAIT PCBs. */ + prev = NULL; + pcb = tcp_tw_pcbs; + while (pcb != NULL) { + LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + pcb_remove = 0; + + /* Check if this PCB has stayed long enough in TIME-WAIT */ + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + } + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_tw_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); + tcp_tw_pcbs = pcb->next; + } + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + } else { + prev = pcb; + pcb = pcb->next; + } + } +} + +/** + * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously + * "refused" by upper layer (application) and sends delayed ACKs. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_fasttmr(void) +{ + struct tcp_pcb *pcb; + + ++tcp_timer_ctr; + +tcp_fasttmr_start: + pcb = tcp_active_pcbs; + + while (pcb != NULL) { + if (pcb->last_timer != tcp_timer_ctr) { + struct tcp_pcb *next; + pcb->last_timer = tcp_timer_ctr; + /* send delayed ACKs */ + if (pcb->flags & TF_ACK_DELAY) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); + tcp_ack_now(pcb); + tcp_output(pcb); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + /* send pending FIN */ + if (pcb->flags & TF_CLOSEPEND) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: pending FIN\n")); + pcb->flags &= ~(TF_CLOSEPEND); + tcp_close_shutdown_fin(pcb); + } + + next = pcb->next; + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + tcp_active_pcbs_changed = 0; + tcp_process_refused_data(pcb); + if (tcp_active_pcbs_changed) { + /* application callback has changed the pcb list: restart the loop */ + goto tcp_fasttmr_start; + } + } + pcb = next; + } else { + pcb = pcb->next; + } + } +} + +/** Call tcp_output for all active pcbs that have TF_NAGLEMEMERR set */ +void +tcp_txnow(void) +{ + struct tcp_pcb *pcb; + + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->flags & TF_NAGLEMEMERR) { + tcp_output(pcb); + } + } +} + +/** Pass pcb->refused_data to the recv callback */ +err_t +tcp_process_refused_data(struct tcp_pcb *pcb) +{ +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + struct pbuf *rest; + while (pcb->refused_data != NULL) +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + { + err_t err; + u8_t refused_flags = pcb->refused_data->flags; + /* set pcb->refused_data to NULL in case the callback frees it and then + closes the pcb */ + struct pbuf *refused_data = pcb->refused_data; +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + pbuf_split_64k(refused_data, &rest); + pcb->refused_data = rest; +#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = NULL; +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + /* Notify again application with data previously received. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); + TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); + if (err == ERR_OK) { + /* did refused_data include a FIN? */ + if (refused_flags & PBUF_FLAG_TCP_FIN +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + && (rest == NULL) +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + ) { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + } + } else if (err == ERR_ABRT) { + /* if err == ERR_ABRT, 'pcb' is already deallocated */ + /* Drop incoming packets because pcb is "full" (only if the incoming + segment contains data). */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); + return ERR_ABRT; + } else { + /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_cat(refused_data, rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = refused_data; + return ERR_INPROGRESS; + } + } + return ERR_OK; +} + +/** + * Deallocates a list of TCP segments (tcp_seg structures). + * + * @param seg tcp_seg list of TCP segments to free + */ +void +tcp_segs_free(struct tcp_seg *seg) +{ + while (seg != NULL) { + struct tcp_seg *next = seg->next; + tcp_seg_free(seg); + seg = next; + } +} + +/** + * Frees a TCP segment (tcp_seg structure). + * + * @param seg single tcp_seg to free + */ +void +tcp_seg_free(struct tcp_seg *seg) +{ + if (seg != NULL) { + if (seg->p != NULL) { + pbuf_free(seg->p); +#if TCP_DEBUG + seg->p = NULL; +#endif /* TCP_DEBUG */ + } + memp_free(MEMP_TCP_SEG, seg); + } +} + +/** + * Sets the priority of a connection. + * + * @param pcb the tcp_pcb to manipulate + * @param prio new priority + */ +void +tcp_setprio(struct tcp_pcb *pcb, u8_t prio) +{ + pcb->prio = prio; +} + +#if TCP_QUEUE_OOSEQ +/** + * Returns a copy of the given TCP segment. + * The pbuf and data are not copied, only the pointers + * + * @param seg the old tcp_seg + * @return a copy of seg + */ +struct tcp_seg * +tcp_seg_copy(struct tcp_seg *seg) +{ + struct tcp_seg *cseg; + + cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG); + if (cseg == NULL) { + return NULL; + } + SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); + pbuf_ref(cseg->p); + return cseg; +} +#endif /* TCP_QUEUE_OOSEQ */ + +#if LWIP_CALLBACK_API +/** + * Default receive callback that is called if the user didn't register + * a recv callback for the pcb. + */ +err_t +tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + LWIP_UNUSED_ARG(arg); + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } else if (err == ERR_OK) { + return tcp_close(pcb); + } + return ERR_OK; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Kills the oldest active connection that has the same or lower priority than + * 'prio'. + * + * @param prio minimum priority + */ +static void +tcp_kill_prio(u8_t prio) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + u8_t mprio; + + mprio = LWIP_MIN(TCP_PRIO_MAX, prio); + + /* We kill the oldest active connection that has lower priority than prio. */ + inactivity = 0; + inactive = NULL; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->prio <= mprio && + (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + mprio = pcb->prio; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Kills the oldest connection that is in specific state. + * Called from tcp_alloc() for LAST_ACK and CLOSING if no more connections are available. + */ +static void +tcp_kill_state(enum tcp_state state) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + LWIP_ASSERT("invalid state", (state == CLOSING) || (state == LAST_ACK)); + + inactivity = 0; + inactive = NULL; + /* Go through the list of active pcbs and get the oldest pcb that is in state + CLOSING/LAST_ACK. */ + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->state == state) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_closing: killing oldest %s PCB %p (%"S32_F")\n", + tcp_state_str[state], (void *)inactive, inactivity)); + /* Don't send a RST, since no data is lost. */ + tcp_abandon(inactive, 0); + } +} + +/** + * Kills the oldest connection that is in TIME_WAIT state. + * Called from tcp_alloc() if no more connections are available. + */ +static void +tcp_kill_timewait(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + inactivity = 0; + inactive = NULL; + /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Allocate a new tcp_pcb structure. + * + * @param prio priority for the new pcb + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_alloc(u8_t prio) +{ + struct tcp_pcb *pcb; + + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in TIME-WAIT. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); + tcp_kill_timewait(); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in LAST-ACK (these wouldn't go to TIME-WAIT). */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest LAST-ACK connection\n")); + tcp_kill_state(LAST_ACK); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in CLOSING. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest CLOSING connection\n")); + tcp_kill_state(CLOSING); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing active connections with lower priority than the new one. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); + tcp_kill_prio(prio); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed multiple times before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed multiple times before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed multiple times before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed above */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* zero out the whole pcb, so there is no need to initialize members to zero */ + memset(pcb, 0, sizeof(struct tcp_pcb)); + pcb->prio = prio; + pcb->snd_buf = TCP_SND_BUF; + /* Start with a window that does not need scaling. When window scaling is + enabled and used, the window is enlarged when both sides agree on scaling. */ + pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); + pcb->ttl = TCP_TTL; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = INITIAL_MSS; + pcb->rto = 3000 / TCP_SLOW_INTERVAL; + pcb->sv = 3000 / TCP_SLOW_INTERVAL; + pcb->rtime = -1; + pcb->cwnd = 1; + pcb->tmr = tcp_ticks; + pcb->last_timer = tcp_timer_ctr; + + /* RFC 5681 recommends setting ssthresh abritrarily high and gives an example + of using the largest advertised receive window. We've seen complications with + receiving TCPs that use window scaling and/or window auto-tuning where the + initial advertised window is very small and then grows rapidly once the + connection is established. To avoid these complications, we set ssthresh to the + largest effective cwnd (amount of in-flight data) that the sender can have. */ + pcb->ssthresh = TCP_SND_BUF; + +#if LWIP_CALLBACK_API + pcb->recv = tcp_recv_null; +#endif /* LWIP_CALLBACK_API */ + + /* Init KEEPALIVE timer */ + pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; + +#if LWIP_TCP_KEEPALIVE + pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; + pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; +#endif /* LWIP_TCP_KEEPALIVE */ + } + return pcb; +} + +/** + * @ingroup tcp_raw + * Creates a new TCP protocol control block but doesn't place it on + * any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @internal: Maybe there should be a idle TCP PCB list where these + * PCBs are put on. Port reservation using tcp_bind() is implemented but + * allocated pcbs that are not bound can't be killed automatically if wanting + * to allocate a pcb with higher prio (@see tcp_kill_prio()) + * + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new(void) +{ + return tcp_alloc(TCP_PRIO_NORMAL); +} + +/** + * @ingroup tcp_raw + * Creates a new TCP protocol control block but doesn't + * place it on any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @param type IP address type, see @ref lwip_ip_addr_type definitions. + * If you want to listen to IPv4 and IPv6 (dual-stack) connections, + * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new_ip_type(u8_t type) +{ + struct tcp_pcb * pcb; + pcb = tcp_alloc(TCP_PRIO_NORMAL); +#if LWIP_IPV4 && LWIP_IPV6 + if (pcb != NULL) { + IP_SET_TYPE_VAL(pcb->local_ip, type); + IP_SET_TYPE_VAL(pcb->remote_ip, type); + } +#else + LWIP_UNUSED_ARG(type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + return pcb; +} + +/** + * @ingroup tcp_raw + * Used to specify the argument that should be passed callback + * functions. + * + * @param pcb tcp_pcb to set the callback argument + * @param arg void pointer argument to pass to callback functions + */ +void +tcp_arg(struct tcp_pcb *pcb, void *arg) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + if (pcb != NULL) { + pcb->callback_arg = arg; + } +} +#if LWIP_CALLBACK_API + +/** + * @ingroup tcp_raw + * Used to specify the function that should be called when a TCP + * connection receives data. + * + * @param pcb tcp_pcb to set the recv callback + * @param recv callback function to call for this pcb when data is received + */ +void +tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) +{ + if (pcb != NULL) { + LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); + pcb->recv = recv; + } +} + +/** + * @ingroup tcp_raw + * Used to specify the function that should be called when TCP data + * has been successfully delivered to the remote host. + * + * @param pcb tcp_pcb to set the sent callback + * @param sent callback function to call for this pcb when data is successfully sent + */ +void +tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) +{ + if (pcb != NULL) { + LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); + pcb->sent = sent; + } +} + +/** + * @ingroup tcp_raw + * Used to specify the function that should be called when a fatal error + * has occurred on the connection. + * + * @note The corresponding pcb is already freed when this callback is called! + * + * @param pcb tcp_pcb to set the err callback + * @param err callback function to call for this pcb when a fatal error + * has occurred on the connection + */ +void +tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) +{ + if (pcb != NULL) { + LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); + pcb->errf = err; + } +} + +/** + * @ingroup tcp_raw + * Used for specifying the function that should be called when a + * LISTENing connection has been connected to another host. + * + * @param pcb tcp_pcb to set the accept callback + * @param accept callback function to call for this pcb when LISTENing + * connection has been connected to another host + */ +void +tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) +{ + if ((pcb != NULL) && (pcb->state == LISTEN)) { + struct tcp_pcb_listen *lpcb = (struct tcp_pcb_listen*)pcb; + lpcb->accept = accept; + } +} +#endif /* LWIP_CALLBACK_API */ + + +/** + * @ingroup tcp_raw + * Used to specify the function that should be called periodically + * from TCP. The interval is specified in terms of the TCP coarse + * timer interval, which is called twice a second. + * + */ +void +tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) +{ + LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN); +#if LWIP_CALLBACK_API + pcb->poll = poll; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(poll); +#endif /* LWIP_CALLBACK_API */ + pcb->pollinterval = interval; +} + +/** + * Purges a TCP PCB. Removes any buffered data and frees the buffer memory + * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). + * + * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! + */ +void +tcp_pcb_purge(struct tcp_pcb *pcb) +{ + if (pcb->state != CLOSED && + pcb->state != TIME_WAIT && + pcb->state != LISTEN) { + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); + + tcp_backlog_accepted(pcb); + + if (pcb->refused_data != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + if (pcb->unsent != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); + } + if (pcb->unacked != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); + } + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; +#endif /* TCP_QUEUE_OOSEQ */ + + /* Stop the retransmission timer as it will expect data on unacked + queue if it fires */ + pcb->rtime = -1; + + tcp_segs_free(pcb->unsent); + tcp_segs_free(pcb->unacked); + pcb->unacked = pcb->unsent = NULL; +#if TCP_OVERSIZE + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + } +} + +/** + * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. + * + * @param pcblist PCB list to purge. + * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! + */ +void +tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) +{ + TCP_RMV(pcblist, pcb); + + tcp_pcb_purge(pcb); + + /* if there is an outstanding delayed ACKs, send it */ + if (pcb->state != TIME_WAIT && + pcb->state != LISTEN && + pcb->flags & TF_ACK_DELAY) { + pcb->flags |= TF_ACK_NOW; + tcp_output(pcb); + } + + if (pcb->state != LISTEN) { + LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); + LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); +#if TCP_QUEUE_OOSEQ + LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); +#endif /* TCP_QUEUE_OOSEQ */ + } + + pcb->state = CLOSED; + /* reset the local port to prevent the pcb from being 'bound' */ + pcb->local_port = 0; + + LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); +} + +/** + * Calculates a new initial sequence number for new connections. + * + * @return u32_t pseudo random sequence number + */ +u32_t +tcp_next_iss(struct tcp_pcb *pcb) +{ +#ifdef LWIP_HOOK_TCP_ISN + return LWIP_HOOK_TCP_ISN(&pcb->local_ip, pcb->local_port, &pcb->remote_ip, pcb->remote_port); +#else /* LWIP_HOOK_TCP_ISN */ + static u32_t iss = 6510; + + LWIP_UNUSED_ARG(pcb); + + iss += tcp_ticks; /* XXX */ + return iss; +#endif /* LWIP_HOOK_TCP_ISN */ +} + +#if TCP_CALCULATE_EFF_SEND_MSS +/** + * Calculates the effective send mss that can be used for a specific IP address + * by using ip_route to determine the netif used to send to the address and + * calculating the minimum of TCP_MSS and that netif's mtu (if set). + */ +u16_t +tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest +#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING + , const ip_addr_t *src +#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ + ) +{ + u16_t mss_s; + struct netif *outif; + s16_t mtu; + + outif = ip_route(src, dest); +#if LWIP_IPV6 +#if LWIP_IPV4 + if (IP_IS_V6(dest)) +#endif /* LWIP_IPV4 */ + { + /* First look in destination cache, to see if there is a Path MTU. */ + mtu = nd6_get_destination_mtu(ip_2_ip6(dest), outif); + } +#if LWIP_IPV4 + else +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + { + if (outif == NULL) { + return sendmss; + } + mtu = outif->mtu; + } +#endif /* LWIP_IPV4 */ + + if (mtu != 0) { +#if LWIP_IPV6 +#if LWIP_IPV4 + if (IP_IS_V6(dest)) +#endif /* LWIP_IPV4 */ + { + mss_s = mtu - IP6_HLEN - TCP_HLEN; + } +#if LWIP_IPV4 + else +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + { + mss_s = mtu - IP_HLEN - TCP_HLEN; + } +#endif /* LWIP_IPV4 */ + /* RFC 1122, chap 4.2.2.6: + * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize + * We correct for TCP options in tcp_write(), and don't support IP options. + */ + sendmss = LWIP_MIN(sendmss, mss_s); + } + return sendmss; +} +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +/** Helper function for tcp_netif_ip_addr_changed() that iterates a pcb list */ +static void +tcp_netif_ip_addr_changed_pcblist(const ip_addr_t* old_addr, struct tcp_pcb* pcb_list) +{ + struct tcp_pcb *pcb; + pcb = pcb_list; + while (pcb != NULL) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&pcb->local_ip, old_addr) +#if LWIP_AUTOIP + /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ + && (!IP_IS_V4_VAL(pcb->local_ip) || !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip))) +#endif /* LWIP_AUTOIP */ + ) { + /* this connection must be aborted */ + struct tcp_pcb *next = pcb->next; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); + tcp_abort(pcb); + pcb = next; + } else { + pcb = pcb->next; + } + } +} + +/** This function is called from netif.c when address is changed or netif is removed + * + * @param old_addr IP address of the netif before change + * @param new_addr IP address of the netif after change or NULL if netif has been removed + */ +void +tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) +{ + struct tcp_pcb_listen *lpcb, *next; + + if (!ip_addr_isany(old_addr)) { + tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_active_pcbs); + tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_bound_pcbs); + + if (!ip_addr_isany(new_addr)) { + /* PCB bound to current local interface address? */ + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) { + next = lpcb->next; + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&lpcb->local_ip, old_addr)) { + /* The PCB is listening to the old ipaddr and + * is set to listen to the new one instead */ + ip_addr_copy(lpcb->local_ip, *new_addr); + } + } + } + } +} + +const char* +tcp_debug_state_str(enum tcp_state s) +{ + return tcp_state_str[s]; +} + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +/** + * Print a tcp header for debugging purposes. + * + * @param tcphdr pointer to a struct tcp_hdr + */ +void +tcp_debug_print(struct tcp_hdr *tcphdr) +{ + LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + lwip_ntohs(tcphdr->src), lwip_ntohs(tcphdr->dest))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", + lwip_ntohl(tcphdr->seqno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", + lwip_ntohl(tcphdr->ackno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", + TCPH_HDRLEN(tcphdr), + (u16_t)(TCPH_FLAGS(tcphdr) >> 5 & 1), + (u16_t)(TCPH_FLAGS(tcphdr) >> 4 & 1), + (u16_t)(TCPH_FLAGS(tcphdr) >> 3 & 1), + (u16_t)(TCPH_FLAGS(tcphdr) >> 2 & 1), + (u16_t)(TCPH_FLAGS(tcphdr) >> 1 & 1), + (u16_t)(TCPH_FLAGS(tcphdr) & 1), + lwip_ntohs(tcphdr->wnd))); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", + lwip_ntohs(tcphdr->chksum), lwip_ntohs(tcphdr->urgp))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); +} + +/** + * Print a tcp state for debugging purposes. + * + * @param s enum tcp_state to print + */ +void +tcp_debug_print_state(enum tcp_state s) +{ + LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); +} + +/** + * Print tcp flags for debugging purposes. + * + * @param flags tcp flags, all active flags are printed + */ +void +tcp_debug_print_flags(u8_t flags) +{ + if (flags & TCP_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); + } + if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); + } + if (flags & TCP_RST) { + LWIP_DEBUGF(TCP_DEBUG, ("RST ")); + } + if (flags & TCP_PSH) { + LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); + } + if (flags & TCP_ACK) { + LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); + } + if (flags & TCP_URG) { + LWIP_DEBUGF(TCP_DEBUG, ("URG ")); + } + if (flags & TCP_ECE) { + LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); + } + if (flags & TCP_CWR) { + LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); + } + LWIP_DEBUGF(TCP_DEBUG, ("\n")); +} + +/** + * Print all tcp_pcbs in every list for debugging purposes. + */ +void +tcp_debug_print_pcbs(void) +{ + struct tcp_pcb *pcb; + struct tcp_pcb_listen *pcbl; + + LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + + LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); + for (pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL; pcbl = pcbl->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F" ", pcbl->local_port)); + tcp_debug_print_state(pcbl->state); + } + + LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } +} + +/** + * Check state consistency of the tcp_pcb lists. + */ +s16_t +tcp_pcbs_sane(void) +{ + struct tcp_pcb *pcb; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + } + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + } + return 1; +} +#endif /* TCP_DEBUG */ + +#endif /* LWIP_TCP */ diff --git a/components/net/lwip-2.0.3/src/core/tcp_in.c b/components/net/lwip-2.0.3/src/core/tcp_in.c new file mode 100644 index 0000000000..5e839ff628 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/tcp_in.c @@ -0,0 +1,1837 @@ +/** + * @file + * Transmission Control Protocol, incoming traffic + * + * The input processing functions of the TCP layer. + * + * These functions are generally called in the order (ip_input() ->) + * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/tcp_priv.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#if LWIP_ND6_TCP_REACHABILITY_HINTS +#include "lwip/nd6.h" +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +/** Initial CWND calculation as defined RFC 2581 */ +#define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U)); + +/* These variables are global to all functions involved in the input + processing of TCP segments. They are set by the tcp_input() + function. */ +static struct tcp_seg inseg; +static struct tcp_hdr *tcphdr; +static u16_t tcphdr_optlen; +static u16_t tcphdr_opt1len; +static u8_t* tcphdr_opt2; +static u16_t tcp_optidx; +static u32_t seqno, ackno; +static tcpwnd_size_t recv_acked; +static u16_t tcplen; +static u8_t flags; + +static u8_t recv_flags; +static struct pbuf *recv_data; + +struct tcp_pcb *tcp_input_pcb; + +/* Forward declarations. */ +static err_t tcp_process(struct tcp_pcb *pcb); +static void tcp_receive(struct tcp_pcb *pcb); +static void tcp_parseopt(struct tcp_pcb *pcb); + +static void tcp_listen_input(struct tcp_pcb_listen *pcb); +static void tcp_timewait_input(struct tcp_pcb *pcb); + +static int tcp_input_delayed_close(struct tcp_pcb *pcb); + +/** + * The initial input processing of TCP. It verifies the TCP header, demultiplexes + * the segment between the PCBs and passes it on to tcp_process(), which implements + * the TCP finite state machine. This function is called by the IP layer (in + * ip_input()). + * + * @param p received TCP segment to process (p->payload pointing to the TCP header) + * @param inp network interface on which this segment was received + */ +void +tcp_input(struct pbuf *p, struct netif *inp) +{ + struct tcp_pcb *pcb, *prev; + struct tcp_pcb_listen *lpcb; +#if SO_REUSE + struct tcp_pcb *lpcb_prev = NULL; + struct tcp_pcb_listen *lpcb_any = NULL; +#endif /* SO_REUSE */ + u8_t hdrlen_bytes; + err_t err; + + LWIP_UNUSED_ARG(inp); + + PERF_START; + + TCP_STATS_INC(tcp.recv); + MIB2_STATS_INC(mib2.tcpinsegs); + + tcphdr = (struct tcp_hdr *)p->payload; + +#if TCP_INPUT_DEBUG + tcp_debug_print(tcphdr); +#endif + + /* Check that TCP header fits in payload */ + if (p->len < TCP_HLEN) { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Don't even process incoming broadcasts/multicasts. */ + if (ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()) || + ip_addr_ismulticast(ip_current_dest_addr())) { + TCP_STATS_INC(tcp.proterr); + goto dropped; + } + +#if CHECKSUM_CHECK_TCP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_TCP) { + /* Verify TCP checksum. */ + u16_t chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + ip_current_src_addr(), ip_current_dest_addr()); + if (chksum != 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", + chksum)); + tcp_debug_print(tcphdr); + TCP_STATS_INC(tcp.chkerr); + goto dropped; + } + } +#endif /* CHECKSUM_CHECK_TCP */ + + /* sanity-check header length */ + hdrlen_bytes = TCPH_HDRLEN(tcphdr) * 4; + if ((hdrlen_bytes < TCP_HLEN) || (hdrlen_bytes > p->tot_len)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: invalid header length (%"U16_F")\n", (u16_t)hdrlen_bytes)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Move the payload pointer in the pbuf so that it points to the + TCP data instead of the TCP header. */ + tcphdr_optlen = hdrlen_bytes - TCP_HLEN; + tcphdr_opt2 = NULL; + if (p->len >= hdrlen_bytes) { + /* all options are in the first pbuf */ + tcphdr_opt1len = tcphdr_optlen; + pbuf_header(p, -(s16_t)hdrlen_bytes); /* cannot fail */ + } else { + u16_t opt2len; + /* TCP header fits into first pbuf, options don't - data is in the next pbuf */ + /* there must be a next pbuf, due to hdrlen_bytes sanity check above */ + LWIP_ASSERT("p->next != NULL", p->next != NULL); + + /* advance over the TCP header (cannot fail) */ + pbuf_header(p, -TCP_HLEN); + + /* determine how long the first and second parts of the options are */ + tcphdr_opt1len = p->len; + opt2len = tcphdr_optlen - tcphdr_opt1len; + + /* options continue in the next pbuf: set p to zero length and hide the + options in the next pbuf (adjusting p->tot_len) */ + pbuf_header(p, -(s16_t)tcphdr_opt1len); + + /* check that the options fit in the second pbuf */ + if (opt2len > p->next->len) { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: options overflow second pbuf (%"U16_F" bytes)\n", p->next->len)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* remember the pointer to the second part of the options */ + tcphdr_opt2 = (u8_t*)p->next->payload; + + /* advance p->next to point after the options, and manually + adjust p->tot_len to keep it consistent with the changed p->next */ + pbuf_header(p->next, -(s16_t)opt2len); + p->tot_len -= opt2len; + + LWIP_ASSERT("p->len == 0", p->len == 0); + LWIP_ASSERT("p->tot_len == p->next->tot_len", p->tot_len == p->next->tot_len); + } + + /* Convert fields in TCP header to host byte order. */ + tcphdr->src = lwip_ntohs(tcphdr->src); + tcphdr->dest = lwip_ntohs(tcphdr->dest); + seqno = tcphdr->seqno = lwip_ntohl(tcphdr->seqno); + ackno = tcphdr->ackno = lwip_ntohl(tcphdr->ackno); + tcphdr->wnd = lwip_ntohs(tcphdr->wnd); + + flags = TCPH_FLAGS(tcphdr); + tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); + + /* Demultiplex an incoming segment. First, we check if it is destined + for an active connection. */ + prev = NULL; + + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && + ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); + if (prev != NULL) { + prev->next = pcb->next; + pcb->next = tcp_active_pcbs; + tcp_active_pcbs = pcb; + } else { + TCP_STATS_INC(tcp.cachehit); + } + LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); + break; + } + prev = pcb; + } + + if (pcb == NULL) { + /* If it did not go to an active connection, we check the connections + in the TIME-WAIT state. */ + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && + ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + /* We don't really care enough to move this PCB to the front + of the list since we are not very likely to receive that + many segments for connections in TIME-WAIT. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); + tcp_timewait_input(pcb); + pbuf_free(p); + return; + } + } + + /* Finally, if we still did not get a match, we check all PCBs that + are LISTENing for incoming connections. */ + prev = NULL; + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if (lpcb->local_port == tcphdr->dest) { + if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) { + /* found an ANY TYPE (IPv4/IPv6) match */ +#if SO_REUSE + lpcb_any = lpcb; + lpcb_prev = prev; +#else /* SO_REUSE */ + break; +#endif /* SO_REUSE */ + } else if (IP_ADDR_PCB_VERSION_MATCH_EXACT(lpcb, ip_current_dest_addr())) { + if (ip_addr_cmp(&lpcb->local_ip, ip_current_dest_addr())) { + /* found an exact match */ + break; + } else if (ip_addr_isany(&lpcb->local_ip)) { + /* found an ANY-match */ +#if SO_REUSE + lpcb_any = lpcb; + lpcb_prev = prev; +#else /* SO_REUSE */ + break; + #endif /* SO_REUSE */ + } + } + } + prev = (struct tcp_pcb *)lpcb; + } +#if SO_REUSE + /* first try specific local IP */ + if (lpcb == NULL) { + /* only pass to ANY if no specific local IP has been found */ + lpcb = lpcb_any; + prev = lpcb_prev; + } +#endif /* SO_REUSE */ + if (lpcb != NULL) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + if (prev != NULL) { + ((struct tcp_pcb_listen *)prev)->next = lpcb->next; + /* our successor is the remainder of the listening list */ + lpcb->next = tcp_listen_pcbs.listen_pcbs; + /* put this listening pcb at the head of the listening list */ + tcp_listen_pcbs.listen_pcbs = lpcb; + } else { + TCP_STATS_INC(tcp.cachehit); + } + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); + tcp_listen_input(lpcb); + pbuf_free(p); + return; + } + } + +#if TCP_INPUT_DEBUG + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); +#endif /* TCP_INPUT_DEBUG */ + + + if (pcb != NULL) { + /* The incoming segment belongs to a connection. */ +#if TCP_INPUT_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_INPUT_DEBUG */ + + /* Set up a tcp_seg structure. */ + inseg.next = NULL; + inseg.len = p->tot_len; + inseg.p = p; + inseg.tcphdr = tcphdr; + + recv_data = NULL; + recv_flags = 0; + recv_acked = 0; + + if (flags & TCP_PSH) { + p->flags |= PBUF_FLAG_PUSH; + } + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + if ((tcp_process_refused_data(pcb) == ERR_ABRT) || + ((pcb->refused_data != NULL) && (tcplen > 0))) { + /* pcb has been aborted or refused data is still refused and the new + segment contains data */ + if (pcb->rcv_ann_wnd == 0) { + /* this is a zero-window probe, we respond to it with current RCV.NXT + and drop the data segment */ + tcp_send_empty_ack(pcb); + } + TCP_STATS_INC(tcp.drop); + MIB2_STATS_INC(mib2.tcpinerrs); + goto aborted; + } + } + tcp_input_pcb = pcb; + err = tcp_process(pcb); + /* A return value of ERR_ABRT means that tcp_abort() was called + and that the pcb has been freed. If so, we don't do anything. */ + if (err != ERR_ABRT) { + if (recv_flags & TF_RESET) { + /* TF_RESET means that the connection was reset by the other + end. We then call the error callback to inform the + application that the connection is dead before we + deallocate the PCB. */ + TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_RST); + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + err = ERR_OK; + /* If the application has registered a "sent" function to be + called when new send buffer space is available, we call it + now. */ + if (recv_acked > 0) { + u16_t acked16; +#if LWIP_WND_SCALE + /* recv_acked is u32_t but the sent callback only takes a u16_t, + so we might have to call it multiple times. */ + u32_t acked = recv_acked; + while (acked > 0) { + acked16 = (u16_t)LWIP_MIN(acked, 0xffffu); + acked -= acked16; +#else + { + acked16 = recv_acked; +#endif + TCP_EVENT_SENT(pcb, (u16_t)acked16, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + recv_acked = 0; + } + if (tcp_input_delayed_close(pcb)) { + goto aborted; + } +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + while (recv_data != NULL) { + struct pbuf *rest = NULL; + pbuf_split_64k(recv_data, &rest); +#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + if (recv_data != NULL) { +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + + LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); + if (pcb->flags & TF_RXCLOSED) { + /* received data although already closed -> abort (send RST) to + notify the remote host that not all data has been processed */ + pbuf_free(recv_data); +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_free(rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + tcp_abort(pcb); + goto aborted; + } + + /* Notify application that data has been received. */ + TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); + if (err == ERR_ABRT) { +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_free(rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + goto aborted; + } + + /* If the upper layer can't receive this data, store it */ + if (err != ERR_OK) { +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_cat(recv_data, rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = recv_data; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + break; + } else { + /* Upper layer received the data, go on with the rest if > 64K */ + recv_data = rest; +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + } + } + + /* If a FIN segment was received, we call the callback + function with a NULL buffer to indicate EOF. */ + if (recv_flags & TF_GOT_FIN) { + if (pcb->refused_data != NULL) { + /* Delay this if we have refused data. */ + pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN; + } else { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + } + + tcp_input_pcb = NULL; + if (tcp_input_delayed_close(pcb)) { + goto aborted; + } + /* Try to send something out. */ + tcp_output(pcb); +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + } + } + /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()). + Below this line, 'pcb' may not be dereferenced! */ +aborted: + tcp_input_pcb = NULL; + recv_data = NULL; + + /* give up our reference to inseg.p */ + if (inseg.p != NULL) + { + pbuf_free(inseg.p); + inseg.p = NULL; + } + } else { + + /* If no matching PCB was found, send a TCP RST (reset) to the + sender. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); + if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { + TCP_STATS_INC(tcp.proterr); + TCP_STATS_INC(tcp.drop); + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } + pbuf_free(p); + } + + LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); + PERF_STOP("tcp_input"); + return; +dropped: + TCP_STATS_INC(tcp.drop); + MIB2_STATS_INC(mib2.tcpinerrs); + pbuf_free(p); +} + +/** Called from tcp_input to check for TF_CLOSED flag. This results in closing + * and deallocating a pcb at the correct place to ensure noone references it + * any more. + * @returns 1 if the pcb has been closed and deallocated, 0 otherwise + */ +static int +tcp_input_delayed_close(struct tcp_pcb *pcb) +{ + if (recv_flags & TF_CLOSED) { + /* The connection has been closed and we will deallocate the + PCB. */ + if (!(pcb->flags & TF_RXCLOSED)) { + /* Connection closed although the application has only shut down the + tx side: call the PCB's err callback and indicate the closure to + ensure the application doesn't continue using the PCB. */ + TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD); + } + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + return 1; + } + return 0; +} + +/** + * Called by tcp_input() when a segment arrives for a listening + * connection (from tcp_input()). + * + * @param pcb the tcp_pcb_listen for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static void +tcp_listen_input(struct tcp_pcb_listen *pcb) +{ + struct tcp_pcb *npcb; + u32_t iss; + err_t rc; + + if (flags & TCP_RST) { + /* An incoming RST should be ignored. Return. */ + return; + } + + /* In the LISTEN state, we check for incoming SYN segments, + creates a new PCB, and responds with a SYN|ACK. */ + if (flags & TCP_ACK) { + /* For incoming segments with the ACK flag set, respond with a + RST. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } else if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); +#if TCP_LISTEN_BACKLOG + if (pcb->accepts_pending >= pcb->backlog) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); + return; + } +#endif /* TCP_LISTEN_BACKLOG */ + npcb = tcp_alloc(pcb->prio); + /* If a new PCB could not be created (probably due to lack of memory), + we don't do anything, but rely on the sender will retransmit the + SYN at a time when we have more memory available. */ + if (npcb == NULL) { + err_t err; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); + TCP_STATS_INC(tcp.memerr); + TCP_EVENT_ACCEPT(pcb, NULL, pcb->callback_arg, ERR_MEM, err); + LWIP_UNUSED_ARG(err); /* err not useful here */ + return; + } +#if TCP_LISTEN_BACKLOG + pcb->accepts_pending++; + npcb->flags |= TF_BACKLOGPEND; +#endif /* TCP_LISTEN_BACKLOG */ + /* Set up the new PCB. */ + ip_addr_copy(npcb->local_ip, *ip_current_dest_addr()); + ip_addr_copy(npcb->remote_ip, *ip_current_src_addr()); + npcb->local_port = pcb->local_port; + npcb->remote_port = tcphdr->src; + npcb->state = SYN_RCVD; + npcb->rcv_nxt = seqno + 1; + npcb->rcv_ann_right_edge = npcb->rcv_nxt; + iss = tcp_next_iss(npcb); + npcb->snd_wl2 = iss; + npcb->snd_nxt = iss; + npcb->lastack = iss; + npcb->snd_lbb = iss; + npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ + npcb->callback_arg = pcb->callback_arg; +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG + npcb->listener = pcb; +#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ + /* inherit socket options */ + npcb->so_options = pcb->so_options & SOF_INHERITED; + /* Register the new PCB so that we can begin receiving segments + for it. */ + TCP_REG_ACTIVE(npcb); + + /* Parse any options in the SYN. */ + tcp_parseopt(npcb); + npcb->snd_wnd = tcphdr->wnd; + npcb->snd_wnd_max = npcb->snd_wnd; + +#if TCP_CALCULATE_EFF_SEND_MSS + npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + MIB2_STATS_INC(mib2.tcppassiveopens); + + /* Send a SYN|ACK together with the MSS option. */ + rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); + if (rc != ERR_OK) { + tcp_abandon(npcb, 0); + return; + } + tcp_output(npcb); + } + return; +} + +/** + * Called by tcp_input() when a segment arrives for a connection in + * TIME_WAIT. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static void +tcp_timewait_input(struct tcp_pcb *pcb) +{ + /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ + /* RFC 793 3.9 Event Processing - Segment Arrives: + * - first check sequence number - we skip that one in TIME_WAIT (always + * acceptable since we only send ACKs) + * - second check the RST bit (... return) */ + if (flags & TCP_RST) { + return; + } + /* - fourth, check the SYN bit, */ + if (flags & TCP_SYN) { + /* If an incoming segment is not acceptable, an acknowledgment + should be sent in reply */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) { + /* If the SYN is in the window it is an error, send a reset */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + return; + } + } else if (flags & TCP_FIN) { + /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. + Restart the 2 MSL time-wait timeout.*/ + pcb->tmr = tcp_ticks; + } + + if ((tcplen > 0)) { + /* Acknowledge data, FIN or out-of-window SYN */ + pcb->flags |= TF_ACK_NOW; + tcp_output(pcb); + } + return; +} + +/** + * Implements the TCP state machine. Called by tcp_input. In some + * states tcp_receive() is called to receive data. The tcp_seg + * argument will be freed by the caller (tcp_input()) unless the + * recv_data pointer in the pcb is set. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_process(struct tcp_pcb *pcb) +{ + struct tcp_seg *rseg; + u8_t acceptable = 0; + err_t err; + + err = ERR_OK; + + /* Process incoming RST segments. */ + if (flags & TCP_RST) { + /* First, determine if the reset is acceptable. */ + if (pcb->state == SYN_SENT) { + /* "In the SYN-SENT state (a RST received in response to an initial SYN), + the RST is acceptable if the ACK field acknowledges the SYN." */ + if (ackno == pcb->snd_nxt) { + acceptable = 1; + } + } else { + /* "In all states except SYN-SENT, all reset (RST) segments are validated + by checking their SEQ-fields." */ + if (seqno == pcb->rcv_nxt) { + acceptable = 1; + } else if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt + pcb->rcv_wnd)) { + /* If the sequence number is inside the window, we only send an ACK + and wait for a re-send with matching sequence number. + This violates RFC 793, but is required to protection against + CVE-2004-0230 (RST spoofing attack). */ + tcp_ack_now(pcb); + } + } + + if (acceptable) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); + LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); + recv_flags |= TF_RESET; + pcb->flags &= ~TF_ACK_DELAY; + return ERR_RST; + } else { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + return ERR_OK; + } + } + + if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { + /* Cope with new connection attempt after remote end crashed */ + tcp_ack_now(pcb); + return ERR_OK; + } + + if ((pcb->flags & TF_RXCLOSED) == 0) { + /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */ + pcb->tmr = tcp_ticks; + } + pcb->keep_cnt_sent = 0; + + tcp_parseopt(pcb); + + /* Do different things depending on the TCP state. */ + switch (pcb->state) { + case SYN_SENT: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, + pcb->snd_nxt, lwip_ntohl(pcb->unacked->tcphdr->seqno))); + /* received SYN ACK with expected sequence number? */ + if ((flags & TCP_ACK) && (flags & TCP_SYN) + && (ackno == pcb->lastack + 1)) { + pcb->rcv_nxt = seqno + 1; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->lastack = ackno; + pcb->snd_wnd = tcphdr->wnd; + pcb->snd_wnd_max = pcb->snd_wnd; + pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ + pcb->state = ESTABLISHED; + +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); + --pcb->snd_queuelen; + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); + rseg = pcb->unacked; + if (rseg == NULL) { + /* might happen if tcp_output fails in tcp_rexmit_rto() + in which case the segment is on the unsent list */ + rseg = pcb->unsent; + LWIP_ASSERT("no segment to free", rseg != NULL); + pcb->unsent = rseg->next; + } else { + pcb->unacked = rseg->next; + } + tcp_seg_free(rseg); + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if (pcb->unacked == NULL) { + pcb->rtime = -1; + } else { + pcb->rtime = 0; + pcb->nrtx = 0; + } + + /* Call the user specified function to call when successfully + * connected. */ + TCP_EVENT_CONNECTED(pcb, ERR_OK, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + tcp_ack_now(pcb); + } + /* received ACK? possibly a half-open connection */ + else if (flags & TCP_ACK) { + /* send a RST to bring the other side in a non-synchronized state. */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + /* Resend SYN immediately (don't wait for rto timeout) to establish + connection faster, but do not send more SYNs than we otherwise would + have, or we might get caught in a loop on loopback interfaces. */ + if (pcb->nrtx < TCP_SYNMAXRTX) { + pcb->rtime = 0; + tcp_rexmit_rto(pcb); + } + } + break; + case SYN_RCVD: + if (flags & TCP_ACK) { + /* expected ACK number? */ + if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { + pcb->state = ESTABLISHED; + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG +#if LWIP_CALLBACK_API + LWIP_ASSERT("pcb->listener->accept != NULL", + (pcb->listener == NULL) || (pcb->listener->accept != NULL)); +#endif + if (pcb->listener == NULL) { + /* listen pcb might be closed by now */ + err = ERR_VAL; + } else +#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ + { + tcp_backlog_accepted(pcb); + /* Call the accept function. */ + TCP_EVENT_ACCEPT(pcb->listener, pcb, pcb->callback_arg, ERR_OK, err); + } + if (err != ERR_OK) { + /* If the accept function returns with an error, we abort + * the connection. */ + /* Already aborted? */ + if (err != ERR_ABRT) { + tcp_abort(pcb); + } + return ERR_ABRT; + } + /* If there was any data contained within this ACK, + * we'd better pass it on to the application as well. */ + tcp_receive(pcb); + + /* Prevent ACK for SYN to generate a sent event */ + if (recv_acked != 0) { + recv_acked--; + } + + pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SYN_RCVD): cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + + if (recv_flags & TF_GOT_FIN) { + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + } else { + /* incorrect ACK number, send RST */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } + } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { + /* Looks like another copy of the SYN - retransmit our SYN-ACK */ + tcp_rexmit(pcb); + } + break; + case CLOSE_WAIT: + /* FALLTHROUGH */ + case ESTABLISHED: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { /* passive close */ + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + break; + case FIN_WAIT_1: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) && + pcb->unsent == NULL) { + LWIP_DEBUGF(TCP_DEBUG, + ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + tcp_ack_now(pcb); + pcb->state = CLOSING; + } + } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) && + pcb->unsent == NULL) { + pcb->state = FIN_WAIT_2; + } + break; + case FIN_WAIT_2: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case CLOSING: + tcp_receive(pcb); + if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case LAST_ACK: + tcp_receive(pcb); + if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ + recv_flags |= TF_CLOSED; + } + break; + default: + break; + } + return ERR_OK; +} + +#if TCP_QUEUE_OOSEQ +/** + * Insert segment into the list (segments covered with new one will be deleted) + * + * Called from tcp_receive() + */ +static void +tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) +{ + struct tcp_seg *old_seg; + + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + /* received segment overlaps all following segments */ + tcp_segs_free(next); + next = NULL; + } else { + /* delete some following segments + oos queue may have segments with FIN flag */ + while (next && + TCP_SEQ_GEQ((seqno + cseg->len), + (next->tcphdr->seqno + next->len))) { + /* cseg with FIN already processed */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN); + } + old_seg = next; + next = next->next; + tcp_seg_free(old_seg); + } + if (next && + TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { + /* We need to trim the incoming segment. */ + cseg->len = (u16_t)(next->tcphdr->seqno - seqno); + pbuf_realloc(cseg->p, cseg->len); + } + } + cseg->next = next; +} +#endif /* TCP_QUEUE_OOSEQ */ + +/** + * Called by tcp_process. Checks if the given segment is an ACK for outstanding + * data, and if so frees the memory of the buffered data. Next, it places the + * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment + * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until + * it has been removed from the buffer. + * + * If the incoming segment constitutes an ACK for a segment that was used for RTT + * estimation, the RTT is estimated here as well. + * + * Called from tcp_process(). + */ +static void +tcp_receive(struct tcp_pcb *pcb) +{ + struct tcp_seg *next; +#if TCP_QUEUE_OOSEQ + struct tcp_seg *prev, *cseg; +#endif /* TCP_QUEUE_OOSEQ */ + s32_t off; + s16_t m; + u32_t right_wnd_edge; + u16_t new_tot_len; + int found_dupack = 0; +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + u32_t ooseq_blen; + u16_t ooseq_qlen; +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ + + LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); + + if (flags & TCP_ACK) { + right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; + + /* Update window. */ + if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || + (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || + (pcb->snd_wl2 == ackno && (u32_t)SND_WND_SCALE(pcb, tcphdr->wnd) > pcb->snd_wnd)) { + pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd); + /* keep track of the biggest window announced by the remote host to calculate + the maximum segment size */ + if (pcb->snd_wnd_max < pcb->snd_wnd) { + pcb->snd_wnd_max = pcb->snd_wnd; + } + pcb->snd_wl1 = seqno; + pcb->snd_wl2 = ackno; + if (pcb->snd_wnd == 0) { + if (pcb->persist_backoff == 0) { + /* start persist timer */ + pcb->persist_cnt = 0; + pcb->persist_backoff = 1; + } + } else if (pcb->persist_backoff > 0) { + /* stop persist timer */ + pcb->persist_backoff = 0; + } + LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"TCPWNDSIZE_F"\n", pcb->snd_wnd)); +#if TCP_WND_DEBUG + } else { + if (pcb->snd_wnd != (tcpwnd_size_t)SND_WND_SCALE(pcb, tcphdr->wnd)) { + LWIP_DEBUGF(TCP_WND_DEBUG, + ("tcp_receive: no window update lastack %"U32_F" ackno %" + U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", + pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); + } +#endif /* TCP_WND_DEBUG */ + } + + /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a + * duplicate ack if: + * 1) It doesn't ACK new data + * 2) length of received packet is zero (i.e. no payload) + * 3) the advertised window hasn't changed + * 4) There is outstanding unacknowledged data (retransmission timer running) + * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) + * + * If it passes all five, should process as a dupack: + * a) dupacks < 3: do nothing + * b) dupacks == 3: fast retransmit + * c) dupacks > 3: increase cwnd + * + * If it only passes 1-3, should reset dupack counter (and add to + * stats, which we don't do in lwIP) + * + * If it only passes 1, should reset dupack counter + * + */ + + /* Clause 1 */ + if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { + /* Clause 2 */ + if (tcplen == 0) { + /* Clause 3 */ + if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge) { + /* Clause 4 */ + if (pcb->rtime >= 0) { + /* Clause 5 */ + if (pcb->lastack == ackno) { + found_dupack = 1; + if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { + ++pcb->dupacks; + } + if (pcb->dupacks > 3) { + /* Inflate the congestion window, but not if it means that + the value overflows. */ + if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + } else if (pcb->dupacks == 3) { + /* Do fast retransmit */ + tcp_rexmit_fast(pcb); + } + } + } + } + } + /* If Clause (1) or more is true, but not a duplicate ack, reset + * count of consecutive duplicate acks */ + if (!found_dupack) { + pcb->dupacks = 0; + } + } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { + /* We come here when the ACK acknowledges new data. */ + + /* Reset the "IN Fast Retransmit" flag, since we are no longer + in fast retransmit. Also reset the congestion window to the + slow start threshold. */ + if (pcb->flags & TF_INFR) { + pcb->flags &= ~TF_INFR; + pcb->cwnd = pcb->ssthresh; + } + + /* Reset the number of retransmissions. */ + pcb->nrtx = 0; + + /* Reset the retransmission time-out. */ + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + /* Reset the fast retransmit variables. */ + pcb->dupacks = 0; + pcb->lastack = ackno; + + /* Update the congestion control variables (cwnd and + ssthresh). */ + if (pcb->state >= ESTABLISHED) { + if (pcb->cwnd < pcb->ssthresh) { + if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); + } else { + tcpwnd_size_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); + if (new_cwnd > pcb->cwnd) { + pcb->cwnd = new_cwnd; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); + } + } + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", + ackno, + pcb->unacked != NULL? + lwip_ntohl(pcb->unacked->tcphdr->seqno): 0, + pcb->unacked != NULL? + lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); + + /* Remove segment from the unacknowledged list if the incoming + ACK acknowledges them. */ + while (pcb->unacked != NULL && + TCP_SEQ_LEQ(lwip_ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked), ackno)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", + lwip_ntohl(pcb->unacked->tcphdr->seqno), + lwip_ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked))); + + next = pcb->unacked; + pcb->unacked = pcb->unacked->next; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + + pcb->snd_queuelen -= pbuf_clen(next->p); + recv_acked += next->len; + tcp_seg_free(next); + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unacked)\n", (tcpwnd_size_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + } + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if (pcb->unacked == NULL) { + pcb->rtime = -1; + } else { + pcb->rtime = 0; + } + + pcb->polltmr = 0; + +#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS + if (ip_current_is_v6()) { + /* Inform neighbor reachability of forward progress. */ + nd6_reachability_hint(ip6_current_src_addr()); + } +#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ + } else { + /* Out of sequence ACK, didn't really ack anything */ + tcp_send_empty_ack(pcb); + } + + /* We go through the ->unsent list to see if any of the segments + on the list are acknowledged by the ACK. This may seem + strange since an "unsent" segment shouldn't be acked. The + rationale is that lwIP puts all outstanding segments on the + ->unsent list after a retransmission, so these segments may + in fact have been sent once. */ + while (pcb->unsent != NULL && + TCP_SEQ_BETWEEN(ackno, lwip_ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", + lwip_ntohl(pcb->unsent->tcphdr->seqno), lwip_ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent))); + + next = pcb->unsent; + pcb->unsent = pcb->unsent->next; +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + pcb->snd_queuelen -= pbuf_clen(next->p); + recv_acked += next->len; + tcp_seg_free(next); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unsent)\n", (tcpwnd_size_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + } + pcb->snd_buf += recv_acked; + /* End of ACK for new data processing. */ + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", + pcb->rttest, pcb->rtseq, ackno)); + + /* RTT estimation calculations. This is done by checking if the + incoming segment acknowledges the segment we use to take a + round-trip time measurement. */ + if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { + /* diff between this shouldn't exceed 32K since this are tcp timer ticks + and a round-trip shouldn't be that long... */ + m = (s16_t)(tcp_ticks - pcb->rttest); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", + m, (u16_t)(m * TCP_SLOW_INTERVAL))); + + /* This is taken directly from VJs original code in his paper */ + m = m - (pcb->sa >> 3); + pcb->sa += m; + if (m < 0) { + m = -m; + } + m = m - (pcb->sv >> 2); + pcb->sv += m; + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", + pcb->rto, (u16_t)(pcb->rto * TCP_SLOW_INTERVAL))); + + pcb->rttest = 0; + } + } + + /* If the incoming segment contains data, we must process it + further unless the pcb already received a FIN. + (RFC 793, chapter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING, + LAST-ACK and TIME-WAIT: "Ignore the segment text.") */ + if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) { + /* This code basically does three things: + + +) If the incoming segment contains data that is the next + in-sequence data, this data is passed to the application. This + might involve trimming the first edge of the data. The rcv_nxt + variable and the advertised window are adjusted. + + +) If the incoming segment has data that is above the next + sequence number expected (->rcv_nxt), the segment is placed on + the ->ooseq queue. This is done by finding the appropriate + place in the ->ooseq queue (which is ordered by sequence + number) and trim the segment in both ends if needed. An + immediate ACK is sent to indicate that we received an + out-of-sequence segment. + + +) Finally, we check if the first segment on the ->ooseq queue + now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If + rcv_nxt > ooseq->seqno, we must trim the first edge of the + segment on ->ooseq before we adjust rcv_nxt. The data in the + segments that are now on sequence are chained onto the + incoming segment so that we only need to call the application + once. + */ + + /* First, we check if we must trim the first edge. We have to do + this if the sequence number of the incoming segment is less + than rcv_nxt, and the sequence number plus the length of the + segment is larger than rcv_nxt. */ + /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) { + if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ + if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)) { + /* Trimming the first edge is done by pushing the payload + pointer in the pbuf downwards. This is somewhat tricky since + we do not want to discard the full contents of the pbuf up to + the new starting point of the data since we have to keep the + TCP header which is present in the first pbuf in the chain. + + What is done is really quite a nasty hack: the first pbuf in + the pbuf chain is pointed to by inseg.p. Since we need to be + able to deallocate the whole pbuf, we cannot change this + inseg.p pointer to point to any of the later pbufs in the + chain. Instead, we point the ->payload pointer in the first + pbuf to data in one of the later pbufs. We also set the + inseg.data pointer to point to the right place. This way, the + ->p pointer will still point to the first pbuf, but the + ->p->payload pointer will point to data in another pbuf. + + After we are done with adjusting the pbuf pointers we must + adjust the ->data pointer in the seg and the segment + length.*/ + + struct pbuf *p = inseg.p; + off = pcb->rcv_nxt - seqno; + LWIP_ASSERT("inseg.p != NULL", inseg.p); + LWIP_ASSERT("insane offset!", (off < 0x7fff)); + if (inseg.p->len < off) { + LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); + new_tot_len = (u16_t)(inseg.p->tot_len - off); + while (p->len < off) { + off -= p->len; + /* KJM following line changed (with addition of new_tot_len var) + to fix bug #9076 + inseg.p->tot_len -= p->len; */ + p->tot_len = new_tot_len; + p->len = 0; + p = p->next; + } + if (pbuf_header(p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } else { + if (pbuf_header(inseg.p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } + inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); + inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; + } + else { + if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) { + /* the whole segment is < rcv_nxt */ + /* must be a duplicate of a packet that has already been correctly handled */ + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); + tcp_ack_now(pcb); + } + } + + /* The sequence number must be within the window (above rcv_nxt + and below rcv_nxt + rcv_wnd) in order to be further + processed. */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt + pcb->rcv_wnd - 1)) { + if (pcb->rcv_nxt == seqno) { + /* The incoming segment is the next in sequence. We check if + we have to trim the end of the segment and update rcv_nxt + and pass the data to the application. */ + tcplen = TCP_TCPLEN(&inseg); + + if (tcplen > pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) & ~(unsigned int)TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + TCPWND_CHECK16(pcb->rcv_wnd); + inseg.len = (u16_t)pcb->rcv_wnd; + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } +#if TCP_QUEUE_OOSEQ + /* Received in-sequence data, adjust ooseq data if: + - FIN has been received or + - inseq overlaps with ooseq */ + if (pcb->ooseq != NULL) { + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: received in-order FIN, binning ooseq queue\n")); + /* Received in-order FIN means anything that was received + * out of order must now have been received in-order, so + * bin the ooseq queue */ + while (pcb->ooseq != NULL) { + struct tcp_seg *old_ooseq = pcb->ooseq; + pcb->ooseq = pcb->ooseq->next; + tcp_seg_free(old_ooseq); + } + } else { + next = pcb->ooseq; + /* Remove all segments on ooseq that are covered by inseg already. + * FIN is copied from ooseq to inseg if present. */ + while (next && + TCP_SEQ_GEQ(seqno + tcplen, + next->tcphdr->seqno + next->len)) { + /* inseg cannot have FIN here (already processed above) */ + if ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0 && + (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { + TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); + tcplen = TCP_TCPLEN(&inseg); + } + prev = next; + next = next->next; + tcp_seg_free(prev); + } + /* Now trim right side of inseg if it overlaps with the first + * segment on ooseq */ + if (next && + TCP_SEQ_GT(seqno + tcplen, + next->tcphdr->seqno)) { + /* inseg cannot have FIN here (already processed above) */ + inseg.len = (u16_t)(next->tcphdr->seqno - seqno); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", + (seqno + tcplen) == next->tcphdr->seqno); + } + pcb->ooseq = next; + } + } +#endif /* TCP_QUEUE_OOSEQ */ + + pcb->rcv_nxt = seqno + tcplen; + + /* Update the receiver's (our) window. */ + LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); + pcb->rcv_wnd -= tcplen; + + tcp_update_rcv_ann_wnd(pcb); + + /* If there is data in the segment, we make preparations to + pass this up to the application. The ->recv_data variable + is used for holding the pbuf that goes to the + application. The code for reassembling out-of-sequence data + chains its data on this pbuf as well. + + If the segment was a FIN, we set the TF_GOT_FIN flag that will + be used to indicate to the application that the remote side has + closed its end of the connection. */ + if (inseg.p->tot_len > 0) { + recv_data = inseg.p; + /* Since this pbuf now is the responsibility of the + application, we delete our reference to it so that we won't + (mistakingly) deallocate it. */ + inseg.p = NULL; + } + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); + recv_flags |= TF_GOT_FIN; + } + +#if TCP_QUEUE_OOSEQ + /* We now check if we have segments on the ->ooseq queue that + are now in sequence. */ + while (pcb->ooseq != NULL && + pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { + + cseg = pcb->ooseq; + seqno = pcb->ooseq->tcphdr->seqno; + + pcb->rcv_nxt += TCP_TCPLEN(cseg); + LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", + pcb->rcv_wnd >= TCP_TCPLEN(cseg)); + pcb->rcv_wnd -= TCP_TCPLEN(cseg); + + tcp_update_rcv_ann_wnd(pcb); + + if (cseg->p->tot_len > 0) { + /* Chain this pbuf onto the pbuf that we will pass to + the application. */ + /* With window scaling, this can overflow recv_data->tot_len, but + that's not a problem since we explicitly fix that before passing + recv_data to the application. */ + if (recv_data) { + pbuf_cat(recv_data, cseg->p); + } else { + recv_data = cseg->p; + } + cseg->p = NULL; + } + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); + recv_flags |= TF_GOT_FIN; + if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ + pcb->state = CLOSE_WAIT; + } + } + + pcb->ooseq = cseg->next; + tcp_seg_free(cseg); + } +#endif /* TCP_QUEUE_OOSEQ */ + + + /* Acknowledge the segment(s). */ + tcp_ack(pcb); + +#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS + if (ip_current_is_v6()) { + /* Inform neighbor reachability of forward progress. */ + nd6_reachability_hint(ip6_current_src_addr()); + } +#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ + + } else { + /* We get here if the incoming segment is out-of-sequence. */ + tcp_send_empty_ack(pcb); +#if TCP_QUEUE_OOSEQ + /* We queue the segment on the ->ooseq queue. */ + if (pcb->ooseq == NULL) { + pcb->ooseq = tcp_seg_copy(&inseg); + } else { + /* If the queue is not empty, we walk through the queue and + try to find a place where the sequence number of the + incoming segment is between the sequence numbers of the + previous and the next segment on the ->ooseq queue. That is + the place where we put the incoming segment. If needed, we + trim the second edges of the previous and the incoming + segment so that it will fit into the sequence. + + If the incoming segment has the same sequence number as a + segment on the ->ooseq queue, we discard the segment that + contains less data. */ + + prev = NULL; + for (next = pcb->ooseq; next != NULL; next = next->next) { + if (seqno == next->tcphdr->seqno) { + /* The sequence number of the incoming segment is the + same as the sequence number of the segment on + ->ooseq. We check the lengths to see which one to + discard. */ + if (inseg.len > next->len) { + /* The incoming segment is larger than the old + segment. We replace some segments with the new + one. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (prev != NULL) { + prev->next = cseg; + } else { + pcb->ooseq = cseg; + } + tcp_oos_insert_segment(cseg, next); + } + break; + } else { + /* Either the lengths are the same or the incoming + segment was smaller than the old one; in either + case, we ditch the incoming segment. */ + break; + } + } else { + if (prev == NULL) { + if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { + /* The sequence number of the incoming segment is lower + than the sequence number of the first segment on the + queue. We put the incoming segment first on the + queue. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + pcb->ooseq = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } else { + /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && + TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ + if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { + /* The sequence number of the incoming segment is in + between the sequence numbers of the previous and + the next segment on ->ooseq. We trim trim the previous + segment, delete next segments that included in received segment + and trim received, if needed. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { + /* We need to trim the prev segment. */ + prev->len = (u16_t)(seqno - prev->tcphdr->seqno); + pbuf_realloc(prev->p, prev->len); + } + prev->next = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } + /* If the "next" segment is the last segment on the + ooseq queue, we add the incoming segment to the end + of the list. */ + if (next->next == NULL && + TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + /* segment "next" already contains all data */ + break; + } + next->next = tcp_seg_copy(&inseg); + if (next->next != NULL) { + if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { + /* We need to trim the last segment. */ + next->len = (u16_t)(seqno - next->tcphdr->seqno); + pbuf_realloc(next->p, next->len); + } + /* check if the remote side overruns our receive window */ + if (TCP_SEQ_GT((u32_t)tcplen + seqno, pcb->rcv_nxt + (u32_t)pcb->rcv_wnd)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) & ~TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + next->next->len = (u16_t)(pcb->rcv_nxt + pcb->rcv_wnd - seqno); + pbuf_realloc(next->next->p, next->next->len); + tcplen = TCP_TCPLEN(next->next); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } + } + break; + } + } + prev = next; + } + } +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + /* Check that the data on ooseq doesn't exceed one of the limits + and throw away everything above that limit. */ + ooseq_blen = 0; + ooseq_qlen = 0; + prev = NULL; + for (next = pcb->ooseq; next != NULL; prev = next, next = next->next) { + struct pbuf *p = next->p; + ooseq_blen += p->tot_len; + ooseq_qlen += pbuf_clen(p); + if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) || + (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) { + /* too much ooseq data, dump this and everything after it */ + tcp_segs_free(next); + if (prev == NULL) { + /* first ooseq segment is too much, dump the whole queue */ + pcb->ooseq = NULL; + } else { + /* just dump 'next' and everything after it */ + prev->next = NULL; + } + break; + } + } +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ +#endif /* TCP_QUEUE_OOSEQ */ + } + } else { + /* The incoming segment is not within the window. */ + tcp_send_empty_ack(pcb); + } + } else { + /* Segments with length 0 is taken care of here. Segments that + fall out of the window are ACKed. */ + if (!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)) { + tcp_ack_now(pcb); + } + } +} + +static u8_t +tcp_getoptbyte(void) +{ + if ((tcphdr_opt2 == NULL) || (tcp_optidx < tcphdr_opt1len)) { + u8_t* opts = (u8_t *)tcphdr + TCP_HLEN; + return opts[tcp_optidx++]; + } else { + u8_t idx = (u8_t)(tcp_optidx++ - tcphdr_opt1len); + return tcphdr_opt2[idx]; + } +} + +/** + * Parses the options contained in the incoming segment. + * + * Called from tcp_listen_input() and tcp_process(). + * Currently, only the MSS option is supported! + * + * @param pcb the tcp_pcb for which a segment arrived + */ +static void +tcp_parseopt(struct tcp_pcb *pcb) +{ + u8_t data; + u16_t mss; +#if LWIP_TCP_TIMESTAMPS + u32_t tsval; +#endif + + /* Parse the TCP MSS option, if present. */ + if (tcphdr_optlen != 0) { + for (tcp_optidx = 0; tcp_optidx < tcphdr_optlen; ) { + u8_t opt = tcp_getoptbyte(); + switch (opt) { + case LWIP_TCP_OPT_EOL: + /* End of options. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); + return; + case LWIP_TCP_OPT_NOP: + /* NOP option. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); + break; + case LWIP_TCP_OPT_MSS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_MSS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_MSS) > tcphdr_optlen) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* An MSS option with the right option length. */ + mss = (tcp_getoptbyte() << 8); + mss |= tcp_getoptbyte(); + /* Limit the mss to the configured TCP_MSS and prevent division by zero */ + pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; + break; +#if LWIP_WND_SCALE + case LWIP_TCP_OPT_WS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: WND_SCALE\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_WS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_WS) > tcphdr_optlen) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* An WND_SCALE option with the right option length. */ + data = tcp_getoptbyte(); + /* If syn was received with wnd scale option, + activate wnd scale opt, but only if this is not a retransmission */ + if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) { + pcb->snd_scale = data; + if (pcb->snd_scale > 14U) { + pcb->snd_scale = 14U; + } + pcb->rcv_scale = TCP_RCV_SCALE; + pcb->flags |= TF_WND_SCALE; + /* window scaling is enabled, we can use the full receive window */ + LWIP_ASSERT("window not at default value", pcb->rcv_wnd == TCPWND_MIN16(TCP_WND)); + LWIP_ASSERT("window not at default value", pcb->rcv_ann_wnd == TCPWND_MIN16(TCP_WND)); + pcb->rcv_wnd = pcb->rcv_ann_wnd = TCP_WND; + } + break; +#endif +#if LWIP_TCP_TIMESTAMPS + case LWIP_TCP_OPT_TS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_TS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_TS) > tcphdr_optlen) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* TCP timestamp option with valid length */ + tsval = tcp_getoptbyte(); + tsval |= (tcp_getoptbyte() << 8); + tsval |= (tcp_getoptbyte() << 16); + tsval |= (tcp_getoptbyte() << 24); + if (flags & TCP_SYN) { + pcb->ts_recent = lwip_ntohl(tsval); + /* Enable sending timestamps in every segment now that we know + the remote host supports it. */ + pcb->flags |= TF_TIMESTAMP; + } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { + pcb->ts_recent = lwip_ntohl(tsval); + } + /* Advance to next option (6 bytes already read) */ + tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6; + break; +#endif + default: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); + data = tcp_getoptbyte(); + if (data < 2) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + /* If the length field is zero, the options are malformed + and we don't process them further. */ + return; + } + /* All other options have a length field, so that we easily + can skip past them. */ + tcp_optidx += data - 2; + } + } + } +} + +void +tcp_trigger_input_pcb_close(void) +{ + recv_flags |= TF_CLOSED; +} + +#endif /* LWIP_TCP */ diff --git a/components/net/lwip-2.0.3/src/core/tcp_out.c b/components/net/lwip-2.0.3/src/core/tcp_out.c new file mode 100644 index 0000000000..2435408aeb --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/tcp_out.c @@ -0,0 +1,1671 @@ +/** + * @file + * Transmission Control Protocol, outgoing traffic + * + * The output functions of TCP. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/tcp_priv.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#if LWIP_TCP_TIMESTAMPS +#include "lwip/sys.h" +#endif + +#include + +/* Define some copy-macros for checksum-on-copy so that the code looks + nicer by preventing too many ifdef's. */ +#if TCP_CHECKSUM_ON_COPY +#define TCP_DATA_COPY(dst, src, len, seg) do { \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ + len, &seg->chksum, &seg->chksum_swapped); \ + seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); +#else /* TCP_CHECKSUM_ON_COPY*/ +#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) +#endif /* TCP_CHECKSUM_ON_COPY*/ + +/** Define this to 1 for an extra check that the output checksum is valid + * (usefule when the checksum is generated by the application, not the stack) */ +#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK +#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 +#endif +/* Allow to override the failure of sanity check from warning to e.g. hard failure */ +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK +#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL +#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(msg) LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, msg) +#endif +#endif + +#if TCP_OVERSIZE +/** The size of segment pbufs created when TCP_OVERSIZE is enabled */ +#ifndef TCP_OVERSIZE_CALC_LENGTH +#define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE) +#endif +#endif + +/* Forward declarations.*/ +static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif); + +/** Allocate a pbuf and create a tcphdr at p->payload, used for output + * functions other than the default tcp_output -> tcp_output_segment + * (e.g. tcp_send_empty_ack, etc.) + * + * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr) + * @param optlen length of header-options + * @param datalen length of tcp data to reserve in pbuf + * @param seqno_be seqno in network byte order (big-endian) + * @return pbuf with p->payload being the tcp_hdr + */ +static struct pbuf * +tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, + u32_t seqno_be /* already in network byte order */) +{ + struct tcp_hdr *tcphdr; + struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= TCP_HLEN + optlen)); + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = lwip_htons(pcb->local_port); + tcphdr->dest = lwip_htons(pcb->remote_port); + tcphdr->seqno = seqno_be; + tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); + TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); + tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + /* If we're sending a packet, update the announced right window edge */ + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + } + return p; +} + +/** + * Called by tcp_close() to send a segment including FIN flag but not data. + * + * @param pcb the tcp_pcb over which to send a segment + * @return ERR_OK if sent, another err_t otherwise + */ +err_t +tcp_send_fin(struct tcp_pcb *pcb) +{ + /* first, try to add the fin to the last unsent segment */ + if (pcb->unsent != NULL) { + struct tcp_seg *last_unsent; + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) { + /* no SYN/FIN/RST flag in the header, we can add the FIN flag */ + TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN); + pcb->flags |= TF_FIN; + return ERR_OK; + } + } + /* no data, no length, flags, copy=1, no optdata */ + return tcp_enqueue_flags(pcb, TCP_FIN); +} + +/** + * Create a TCP segment with prefilled header. + * + * Called by tcp_write and tcp_enqueue_flags. + * + * @param pcb Protocol control block for the TCP connection. + * @param p pbuf that is used to hold the TCP header. + * @param flags TCP flags for header. + * @param seqno TCP sequence number of this packet + * @param optflags options to include in TCP header + * @return a new tcp_seg pointing to p, or NULL. + * The TCP header is filled in except ackno and wnd. + * p is freed on failure. + */ +static struct tcp_seg * +tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) +{ + struct tcp_seg *seg; + u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); + + if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no memory.\n")); + pbuf_free(p); + return NULL; + } + seg->flags = optflags; + seg->next = NULL; + seg->p = p; + LWIP_ASSERT("p->tot_len >= optlen", p->tot_len >= optlen); + seg->len = p->tot_len - optlen; +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = 0; + seg->chksum_swapped = 0; + /* check optflags */ + LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED", + (optflags & TF_SEG_DATA_CHECKSUMMED) == 0); +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* build TCP header */ + if (pbuf_header(p, TCP_HLEN)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no room for TCP header in pbuf.\n")); + TCP_STATS_INC(tcp.err); + tcp_seg_free(seg); + return NULL; + } + seg->tcphdr = (struct tcp_hdr *)seg->p->payload; + seg->tcphdr->src = lwip_htons(pcb->local_port); + seg->tcphdr->dest = lwip_htons(pcb->remote_port); + seg->tcphdr->seqno = lwip_htonl(seqno); + /* ackno is set in tcp_output */ + TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); + /* wnd and chksum are set in tcp_output */ + seg->tcphdr->urgp = 0; + return seg; +} + +/** + * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. + * + * This function is like pbuf_alloc(layer, length, PBUF_RAM) except + * there may be extra bytes available at the end. + * + * @param layer flag to define header size. + * @param length size of the pbuf's payload. + * @param max_length maximum usable size of payload+oversize. + * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. + * @param pcb The TCP connection that will enqueue the pbuf. + * @param apiflags API flags given to tcp_write. + * @param first_seg true when this pbuf will be used in the first enqueued segment. + */ +#if TCP_OVERSIZE +static struct pbuf * +tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, + u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, + u8_t first_seg) +{ + struct pbuf *p; + u16_t alloc = length; + +#if LWIP_NETIF_TX_SINGLE_PBUF + LWIP_UNUSED_ARG(max_length); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(apiflags); + LWIP_UNUSED_ARG(first_seg); + alloc = max_length; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (length < max_length) { + /* Should we allocate an oversized pbuf, or just the minimum + * length required? If tcp_write is going to be called again + * before this segment is transmitted, we want the oversized + * buffer. If the segment will be transmitted immediately, we can + * save memory by allocating only length. We use a simple + * heuristic based on the following information: + * + * Did the user set TCP_WRITE_FLAG_MORE? + * + * Will the Nagle algorithm defer transmission of this segment? + */ + if ((apiflags & TCP_WRITE_FLAG_MORE) || + (!(pcb->flags & TF_NODELAY) && + (!first_seg || + pcb->unsent != NULL || + pcb->unacked != NULL))) { + alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(TCP_OVERSIZE_CALC_LENGTH(length))); + } + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + p = pbuf_alloc(layer, alloc, PBUF_RAM); + if (p == NULL) { + return NULL; + } + LWIP_ASSERT("need unchained pbuf", p->next == NULL); + *oversize = p->len - length; + /* trim p->len to the currently used size */ + p->len = p->tot_len = length; + return p; +} +#else /* TCP_OVERSIZE */ +#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) +#endif /* TCP_OVERSIZE */ + +#if TCP_CHECKSUM_ON_COPY +/** Add a checksum of newly added data to the segment */ +static void +tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, + u8_t *seg_chksum_swapped) +{ + u32_t helper; + /* add chksum to old chksum and fold to u16_t */ + helper = chksum + *seg_chksum; + chksum = FOLD_U32T(helper); + if ((len & 1) != 0) { + *seg_chksum_swapped = 1 - *seg_chksum_swapped; + chksum = SWAP_BYTES_IN_WORD(chksum); + } + *seg_chksum = chksum; +} +#endif /* TCP_CHECKSUM_ON_COPY */ + +/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). + * + * @param pcb the tcp pcb to check for + * @param len length of data to send (checked agains snd_buf) + * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise + */ +static err_t +tcp_write_checks(struct tcp_pcb *pcb, u16_t len) +{ + /* connection is in invalid state for data transmission? */ + if ((pcb->state != ESTABLISHED) && + (pcb->state != CLOSE_WAIT) && + (pcb->state != SYN_SENT) && + (pcb->state != SYN_RCVD)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); + return ERR_CONN; + } else if (len == 0) { + return ERR_OK; + } + + /* fail on too much data */ + if (len > pcb->snd_buf) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"TCPWNDSIZE_F")\n", + len, pcb->snd_buf)); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); + + /* If total number of pbufs on the unsent/unacked queues exceeds the + * configured maximum, return an error */ + /* check for configured max queuelen and possible overflow */ + if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", + pcb->unacked != NULL || pcb->unsent != NULL); + } else { + LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", + pcb->unacked == NULL && pcb->unsent == NULL); + } + return ERR_OK; +} + +/** + * @ingroup tcp_raw + * Write data for sending (but does not send it immediately). + * + * It waits in the expectation of more data being sent soon (as + * it can send them more efficiently by combining them together). + * To prompt the system to send data now, call tcp_output() after + * calling tcp_write(). + * + * @param pcb Protocol control block for the TCP connection to enqueue data for. + * @param arg Pointer to the data to be enqueued for sending. + * @param len Data length in bytes + * @param apiflags combination of following flags : + * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack + * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will not be set on last segment sent, + * @return ERR_OK if enqueued, another err_t on error + */ +err_t +tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) +{ + struct pbuf *concat_p = NULL; + struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL; + u16_t pos = 0; /* position in 'arg' data */ + u16_t queuelen; + u8_t optlen = 0; + u8_t optflags = 0; +#if TCP_OVERSIZE + u16_t oversize = 0; + u16_t oversize_used = 0; +#if TCP_OVERSIZE_DBGCHECK + u16_t oversize_add = 0; +#endif /* TCP_OVERSIZE_DBGCHECK*/ +#endif /* TCP_OVERSIZE */ + u16_t extendlen = 0; +#if TCP_CHECKSUM_ON_COPY + u16_t concat_chksum = 0; + u8_t concat_chksum_swapped = 0; + u16_t concat_chksummed = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + err_t err; + /* don't allocate segments bigger than half the maximum window we ever received */ + u16_t mss_local = LWIP_MIN(pcb->mss, TCPWND_MIN16(pcb->snd_wnd_max/2)); + mss_local = mss_local ? mss_local : pcb->mss; + +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Always copy to try to create single pbufs for TX */ + apiflags |= TCP_WRITE_FLAG_COPY; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", + (void *)pcb, arg, len, (u16_t)apiflags)); + LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", + arg != NULL, return ERR_ARG;); + + err = tcp_write_checks(pcb, len); + if (err != ERR_OK) { + return err; + } + queuelen = pcb->snd_queuelen; + +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + /* Make sure the timestamp option is only included in data segments if we + agreed about it with the remote host. */ + optflags = TF_SEG_OPTS_TS; + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + /* ensure that segments can hold at least one data byte... */ + mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1); + } +#endif /* LWIP_TCP_TIMESTAMPS */ + + + /* + * TCP segmentation is done in three phases with increasing complexity: + * + * 1. Copy data directly into an oversized pbuf. + * 2. Chain a new pbuf to the end of pcb->unsent. + * 3. Create new segments. + * + * We may run out of memory at any point. In that case we must + * return ERR_MEM and not change anything in pcb. Therefore, all + * changes are recorded in local variables and committed at the end + * of the function. Some pcb fields are maintained in local copies: + * + * queuelen = pcb->snd_queuelen + * oversize = pcb->unsent_oversize + * + * These variables are set consistently by the phases: + * + * seg points to the last segment tampered with. + * + * pos records progress as data is segmented. + */ + + /* Find the tail of the unsent queue. */ + if (pcb->unsent != NULL) { + u16_t space; + u16_t unsent_optlen; + + /* @todo: this could be sped up by keeping last_unsent in the pcb */ + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + /* Usable space at the end of the last unsent segment */ + unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); + LWIP_ASSERT("mss_local is too small", mss_local >= last_unsent->len + unsent_optlen); + space = mss_local - (last_unsent->len + unsent_optlen); + + /* + * Phase 1: Copy data directly into an oversized pbuf. + * + * The number of bytes copied is recorded in the oversize_used + * variable. The actual copying is done at the bottom of the + * function. + */ +#if TCP_OVERSIZE +#if TCP_OVERSIZE_DBGCHECK + /* check that pcb->unsent_oversize matches last_unsent->oversize_left */ + LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", + pcb->unsent_oversize == last_unsent->oversize_left); +#endif /* TCP_OVERSIZE_DBGCHECK */ + oversize = pcb->unsent_oversize; + if (oversize > 0) { + LWIP_ASSERT("inconsistent oversize vs. space", oversize <= space); + seg = last_unsent; + oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len)); + pos += oversize_used; + oversize -= oversize_used; + space -= oversize_used; + } + /* now we are either finished or oversize is zero */ + LWIP_ASSERT("inconsistent oversize vs. len", (oversize == 0) || (pos == len)); +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: Chain a new pbuf to the end of pcb->unsent. + * + * As an exception when NOT copying the data, if the given data buffer + * directly follows the last unsent data buffer in memory, extend the last + * ROM pbuf reference to the buffer, thus saving a ROM pbuf allocation. + * + * We don't extend segments containing SYN/FIN flags or options + * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at + * the end. + */ + if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { + u16_t seglen = LWIP_MIN(space, len - pos); + seg = last_unsent; + + /* Create a pbuf with a copy or reference to seglen bytes. We + * can use PBUF_RAW here since the data appears in the middle of + * a segment. A header will never be prepended. */ + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* Data is copied */ + if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", + seglen)); + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + oversize_add = oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ + TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); +#if TCP_CHECKSUM_ON_COPY + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + queuelen += pbuf_clen(concat_p); + } else { + /* Data is not copied */ + /* If the last unsent pbuf is of type PBUF_ROM, try to extend it. */ + struct pbuf *p; + for (p = last_unsent->p; p->next != NULL; p = p->next); + if (p->type == PBUF_ROM && (const u8_t *)p->payload + p->len == (const u8_t *)arg) { + LWIP_ASSERT("tcp_write: ROM pbufs cannot be oversized", pos == 0); + extendlen = seglen; + } else { + if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } + /* reference the non-volatile payload data */ + ((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos; + queuelen += pbuf_clen(concat_p); + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + tcp_seg_add_chksum(~inet_chksum((const u8_t*)arg + pos, seglen), seglen, + &concat_chksum, &concat_chksum_swapped); + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + } + + pos += seglen; + } + } else { +#if TCP_OVERSIZE + LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)", + pcb->unsent_oversize == 0); +#endif /* TCP_OVERSIZE */ + } + + /* + * Phase 3: Create new segments. + * + * The new segments are chained together in the local 'queue' + * variable, ready to be appended to pcb->unsent. + */ + while (pos < len) { + struct pbuf *p; + u16_t left = len - pos; + u16_t max_len = mss_local - optlen; + u16_t seglen = LWIP_MIN(left, max_len); +#if TCP_CHECKSUM_ON_COPY + u16_t chksum = 0; + u8_t chksum_swapped = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* If copy is set, memory should be allocated and data copied + * into pbuf */ + if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); + goto memerr; + } + LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen", + (p->len >= seglen)); + TCP_DATA_COPY2((char *)p->payload + optlen, (const u8_t*)arg + pos, seglen, &chksum, &chksum_swapped); + } else { + /* Copy is not set: First allocate a pbuf for holding the data. + * Since the referenced data is available at least until it is + * sent out on the link (as it has to be ACKed by the remote + * party) we can safely use PBUF_ROM instead of PBUF_REF here. + */ + struct pbuf *p2; +#if TCP_OVERSIZE + LWIP_ASSERT("oversize == 0", oversize == 0); +#endif /* TCP_OVERSIZE */ + if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + chksum = ~inet_chksum((const u8_t*)arg + pos, seglen); + if (seglen & 1) { + chksum_swapped = 1; + chksum = SWAP_BYTES_IN_WORD(chksum); + } +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + ((struct pbuf_rom*)p2)->payload = (const u8_t*)arg + pos; + + /* Second, allocate a pbuf for the headers. */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + /* If allocation fails, we have to deallocate the data pbuf as + * well. */ + pbuf_free(p2); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for header pbuf\n")); + goto memerr; + } + /* Concatenate the headers and data pbufs together. */ + pbuf_cat(p/*header*/, p2/*data*/); + } + + queuelen += pbuf_clen(p); + + /* Now that there are more segments queued, we check again if the + * length of the queue exceeds the configured maximum or + * overflows. */ + if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n", + queuelen, (int)TCP_SND_QUEUELEN)); + pbuf_free(p); + goto memerr; + } + + if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) { + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = chksum; + seg->chksum_swapped = chksum_swapped; + seg->flags |= TF_SEG_DATA_CHECKSUMMED; +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* first segment of to-be-queued data? */ + if (queue == NULL) { + queue = seg; + } else { + /* Attach the segment to the end of the queued segments */ + LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); + prev_seg->next = seg; + } + /* remember last segment of to-be-queued data for next iteration */ + prev_seg = seg; + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", + lwip_ntohl(seg->tcphdr->seqno), + lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); + + pos += seglen; + } + + /* + * All three segmentation phases were successful. We can commit the + * transaction. + */ +#if TCP_OVERSIZE_DBGCHECK + if ((last_unsent != NULL) && (oversize_add != 0)) { + last_unsent->oversize_left += oversize_add; + } +#endif /* TCP_OVERSIZE_DBGCHECK */ + + /* + * Phase 1: If data has been added to the preallocated tail of + * last_unsent, we update the length fields of the pbuf chain. + */ +#if TCP_OVERSIZE + if (oversize_used > 0) { + struct pbuf *p; + /* Bump tot_len of whole chain, len of tail */ + for (p = last_unsent->p; p; p = p->next) { + p->tot_len += oversize_used; + if (p->next == NULL) { + TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); + p->len += oversize_used; + } + } + last_unsent->len += oversize_used; +#if TCP_OVERSIZE_DBGCHECK + LWIP_ASSERT("last_unsent->oversize_left >= oversize_used", + last_unsent->oversize_left >= oversize_used); + last_unsent->oversize_left -= oversize_used; +#endif /* TCP_OVERSIZE_DBGCHECK */ + } + pcb->unsent_oversize = oversize; +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: concat_p can be concatenated onto last_unsent->p, unless we + * determined that the last ROM pbuf can be extended to include the new data. + */ + if (concat_p != NULL) { + LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", + (last_unsent != NULL)); + pbuf_cat(last_unsent->p, concat_p); + last_unsent->len += concat_p->tot_len; + } else if (extendlen > 0) { + struct pbuf *p; + LWIP_ASSERT("tcp_write: extension of reference requires reference", + last_unsent != NULL && last_unsent->p != NULL); + for (p = last_unsent->p; p->next != NULL; p = p->next) { + p->tot_len += extendlen; + } + p->tot_len += extendlen; + p->len += extendlen; + last_unsent->len += extendlen; + } + +#if TCP_CHECKSUM_ON_COPY + if (concat_chksummed) { + LWIP_ASSERT("tcp_write: concat checksum needs concatenated data", + concat_p != NULL || extendlen > 0); + /*if concat checksumm swapped - swap it back */ + if (concat_chksum_swapped) { + concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum); + } + tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, + &last_unsent->chksum_swapped); + last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; + } +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* + * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that + * is harmless + */ + if (last_unsent == NULL) { + pcb->unsent = queue; + } else { + last_unsent->next = queue; + } + + /* + * Finally update the pcb state. + */ + pcb->snd_lbb += len; + pcb->snd_buf -= len; + pcb->snd_queuelen = queuelen; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", + pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + /* Set the PSH flag in the last segment that we enqueued. */ + if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { + TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); + } + + return ERR_OK; +memerr: + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + + if (concat_p != NULL) { + pbuf_free(concat_p); + } + if (queue != NULL) { + tcp_segs_free(queue); + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); + return ERR_MEM; +} + +/** + * Enqueue TCP options for transmission. + * + * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl(). + * + * @param pcb Protocol control block for the TCP connection. + * @param flags TCP header flags to set in the outgoing segment. + */ +err_t +tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) +{ + struct pbuf *p; + struct tcp_seg *seg; + u8_t optflags = 0; + u8_t optlen = 0; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", + (flags & (TCP_SYN | TCP_FIN)) != 0); + + /* check for configured max queuelen and possible overflow (FIN flag should always come through!) */ + if (((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) && + ((flags & TCP_FIN) == 0)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + if (flags & TCP_SYN) { + optflags = TF_SEG_OPTS_MSS; +#if LWIP_WND_SCALE + if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) { + /* In a (sent in state SYN_RCVD), the window scale option may only + be sent if we received a window scale option from the remote host. */ + optflags |= TF_SEG_OPTS_WND_SCALE; + } +#endif /* LWIP_WND_SCALE */ + } +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + /* Make sure the timestamp option is only included in data segments if we + agreed about it with the remote host. */ + optflags |= TF_SEG_OPTS_TS; + } +#endif /* LWIP_TCP_TIMESTAMPS */ + optlen = LWIP_TCP_OPT_LENGTH(optflags); + + /* Allocate pbuf with room for TCP header + options */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", + (p->len >= optlen)); + + /* Allocate memory for tcp_seg, and fill in fields. */ + if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % LWIP_MIN(MEM_ALIGNMENT, 4)) == 0); + LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, + ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", + lwip_ntohl(seg->tcphdr->seqno), + lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), + (u16_t)flags)); + + /* Now append seg to pcb->unsent queue */ + if (pcb->unsent == NULL) { + pcb->unsent = seg; + } else { + struct tcp_seg *useg; + for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); + useg->next = seg; + } +#if TCP_OVERSIZE + /* The new unsent tail has no space */ + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + + /* SYN and FIN bump the sequence number */ + if ((flags & TCP_SYN) || (flags & TCP_FIN)) { + pcb->snd_lbb++; + /* optlen does not influence snd_buf */ + } + if (flags & TCP_FIN) { + pcb->flags |= TF_FIN; + } + + /* update number of segments on the queues */ + pcb->snd_queuelen += pbuf_clen(seg->p); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + return ERR_OK; +} + +#if LWIP_TCP_TIMESTAMPS +/* Build a timestamp option (12 bytes long) at the specified options pointer) + * + * @param pcb tcp_pcb + * @param opts option pointer where to store the timestamp option + */ +static void +tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) +{ + /* Pad with two NOP options to make everything nicely aligned */ + opts[0] = PP_HTONL(0x0101080A); + opts[1] = lwip_htonl(sys_now()); + opts[2] = lwip_htonl(pcb->ts_recent); +} +#endif + +#if LWIP_WND_SCALE +/** Build a window scale option (3 bytes long) at the specified options pointer) + * + * @param opts option pointer where to store the window scale option + */ +static void +tcp_build_wnd_scale_option(u32_t *opts) +{ + /* Pad with one NOP option to make everything nicely aligned */ + opts[0] = PP_HTONL(0x01030300 | TCP_RCV_SCALE); +} +#endif + +/** + * Send an ACK without data. + * + * @param pcb Protocol control block for the TCP connection to send the ACK + */ +err_t +tcp_send_empty_ack(struct tcp_pcb *pcb) +{ + err_t err; + struct pbuf *p; + u8_t optlen = 0; + struct netif *netif; +#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP + struct tcp_hdr *tcphdr; +#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ + +#if LWIP_TCP_TIMESTAMPS + if (pcb->flags & TF_TIMESTAMP) { + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + } +#endif + + p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt)); + if (p == NULL) { + /* let tcp_fasttmr retry sending this ACK */ + pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); + return ERR_BUF; + } +#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP + tcphdr = (struct tcp_hdr *)p->payload; +#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, + ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); + + /* NB. MSS and window scale options are only sent on SYNs, so ignore them here */ +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (pcb->flags & TF_TIMESTAMP) { + tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); + } +#endif + + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + err = ERR_RTE; + } else { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); + } +#endif + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, + pcb->ttl, pcb->tos, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } + pbuf_free(p); + + if (err != ERR_OK) { + /* let tcp_fasttmr retry sending this ACK */ + pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); + } else { + /* remove ACK flags from the PCB, as we sent an empty ACK now */ + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + + return err; +} + +/** + * @ingroup tcp_raw + * Find out what we can send and send it + * + * @param pcb Protocol control block for the TCP connection to send data + * @return ERR_OK if data has been sent or nothing to send + * another err_t on error + */ +err_t +tcp_output(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg, *useg; + u32_t wnd, snd_nxt; + err_t err; + struct netif *netif; +#if TCP_CWND_DEBUG + s16_t i = 0; +#endif /* TCP_CWND_DEBUG */ + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_output for listen-pcbs", + pcb->state != LISTEN); + + /* First, check if we are invoked by the TCP input processing + code. If so, we do not output anything. Instead, we rely on the + input processing code to call us when input processing is done + with. */ + if (tcp_input_pcb == pcb) { + return ERR_OK; + } + + wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); + + seg = pcb->unsent; + + /* If the TF_ACK_NOW flag is set and no data will be sent (either + * because the ->unsent queue is empty or because the window does + * not allow it), construct an empty ACK segment and send it. + * + * If data is to be sent, we will just piggyback the ACK (see below). + */ + if (pcb->flags & TF_ACK_NOW && + (seg == NULL || + lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { + return tcp_send_empty_ack(pcb); + } + + /* useg should point to last segment on unacked queue */ + useg = pcb->unacked; + if (useg != NULL) { + for (; useg->next != NULL; useg = useg->next); + } + + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + return ERR_RTE; + } + + /* If we don't have a local IP address, we get one from netif */ + if (ip_addr_isany(&pcb->local_ip)) { + const ip_addr_t *local_ip = ip_netif_get_local_ip(netif, &pcb->remote_ip); + if (local_ip == NULL) { + return ERR_RTE; + } + ip_addr_copy(pcb->local_ip, *local_ip); + } + +#if TCP_OUTPUT_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", + (void*)pcb->unsent)); + } +#endif /* TCP_OUTPUT_DEBUG */ +#if TCP_CWND_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F + ", cwnd %"TCPWNDSIZE_F", wnd %"U32_F + ", seg == NULL, ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); + } else { + LWIP_DEBUGF(TCP_CWND_DEBUG, + ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F + ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, + lwip_ntohl(seg->tcphdr->seqno), pcb->lastack)); + } +#endif /* TCP_CWND_DEBUG */ + /* Check if we need to start the persistent timer when the next unsent segment + * does not fit within the remaining send window and RTO timer is not running (we + * have no in-flight data). A traditional approach would fill the remaining window + * with part of the unsent segment (which will engage zero-window probing upon + * reception of the zero window update from the receiver). This ensures the + * subsequent window update is reliably received. With the goal of being lightweight, + * we avoid splitting the unsent segment and treat the window as already zero. + */ + if (seg != NULL && + lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd && + wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked == NULL) { + /* Start the persist timer */ + if (pcb->persist_backoff == 0) { + pcb->persist_cnt = 0; + pcb->persist_backoff = 1; + } + goto output_done; + } + /* data available and window allows it to be sent? */ + while (seg != NULL && + lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { + LWIP_ASSERT("RST not expected here!", + (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); + /* Stop sending if the nagle algorithm would prevent it + * Don't stop: + * - if tcp_write had a memory error before (prevent delayed ACK timeout) or + * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - + * either seg->next != NULL or pcb->unacked == NULL; + * RST is no sent using tcp_write/tcp_output. + */ + if ((tcp_do_output_nagle(pcb) == 0) && + ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) { + break; + } +#if TCP_CWND_DEBUG + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + lwip_ntohl(seg->tcphdr->seqno) + seg->len - + pcb->lastack, + lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i)); + ++i; +#endif /* TCP_CWND_DEBUG */ + + if (pcb->state != SYN_SENT) { + TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); + } + +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ + err = tcp_output_segment(seg, pcb, netif); + if (err != ERR_OK) { + /* segment could not be sent, for whatever reason */ + pcb->flags |= TF_NAGLEMEMERR; + return err; + } + pcb->unsent = seg->next; + if (pcb->state != SYN_SENT) { + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; + } + /* put segment on unacknowledged list if length > 0 */ + if (TCP_TCPLEN(seg) > 0) { + seg->next = NULL; + /* unacked list is empty? */ + if (pcb->unacked == NULL) { + pcb->unacked = seg; + useg = seg; + /* unacked list is not empty? */ + } else { + /* In the case of fast retransmit, the packet should not go to the tail + * of the unacked queue, but rather somewhere before it. We need to check for + * this case. -STJ Jul 27, 2004 */ + if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) { + /* add segment to before tail of unacked list, keeping the list sorted */ + struct tcp_seg **cur_seg = &(pcb->unacked); + while (*cur_seg && + TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = (*cur_seg); + (*cur_seg) = seg; + } else { + /* add segment to tail of unacked list */ + useg->next = seg; + useg = useg->next; + } + } + /* do not queue empty segments on the unacked list */ + } else { + tcp_seg_free(seg); + } + seg = pcb->unsent; + } +output_done: +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + /* last unsent has been removed, reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + pcb->flags &= ~TF_NAGLEMEMERR; + return ERR_OK; +} + +/** + * Called by tcp_output() to actually send a TCP segment over IP. + * + * @param seg the tcp_seg to send + * @param pcb the tcp_pcb for the TCP connection used to send the segment + * @param netif the netif used to send the segment + */ +static err_t +tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif) +{ + err_t err; + u16_t len; + u32_t *opts; + + if (seg->p->ref != 1) { + /* This can happen if the pbuf of this segment is still referenced by the + netif driver due to deferred transmission. Since this function modifies + p->len, we must not continue in this case. */ + return ERR_OK; + } + + /* The TCP header has already been constructed, but the ackno and + wnd fields remain. */ + seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); + + /* advertise our receive window size in this TCP segment */ +#if LWIP_WND_SCALE + if (seg->flags & TF_SEG_OPTS_WND_SCALE) { + /* The Window field in a SYN segment itself (the only type where we send + the window scale option) is never scaled. */ + seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd)); + } else +#endif /* LWIP_WND_SCALE */ + { + seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); + } + + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + + /* Add any requested options. NB MSS option is only set on SYN + packets, so ignore it here */ + /* cast through void* to get rid of alignment warnings */ + opts = (u32_t *)(void *)(seg->tcphdr + 1); + if (seg->flags & TF_SEG_OPTS_MSS) { + u16_t mss; +#if TCP_CALCULATE_EFF_SEND_MSS + mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip); +#else /* TCP_CALCULATE_EFF_SEND_MSS */ + mss = TCP_MSS; +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + *opts = TCP_BUILD_MSS_OPTION(mss); + opts += 1; + } +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (seg->flags & TF_SEG_OPTS_TS) { + tcp_build_timestamp_option(pcb, opts); + opts += 3; + } +#endif +#if LWIP_WND_SCALE + if (seg->flags & TF_SEG_OPTS_WND_SCALE) { + tcp_build_wnd_scale_option(opts); + opts += 1; + } +#endif + + /* Set retransmission timer running if it is not currently enabled + This must be set before checking the route. */ + if (pcb->rtime < 0) { + pcb->rtime = 0; + } + + if (pcb->rttest == 0) { + pcb->rttest = tcp_ticks; + pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); + } + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", + lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) + + seg->len)); + + len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); + if (len == 0) { + /** Exclude retransmitted segments from this count. */ + MIB2_STATS_INC(mib2.tcpoutsegs); + } + + seg->p->len -= len; + seg->p->tot_len -= len; + + seg->p->payload = seg->tcphdr; + + seg->tcphdr->chksum = 0; +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { +#if TCP_CHECKSUM_ON_COPY + u32_t acc; +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, + seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ + if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { + LWIP_ASSERT("data included but not checksummed", + seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); + } + + /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ + acc = ip_chksum_pseudo_partial(seg->p, IP_PROTO_TCP, + seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip); + /* add payload checksum */ + if (seg->chksum_swapped) { + seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); + seg->chksum_swapped = 0; + } + acc += (u16_t)~(seg->chksum); + seg->tcphdr->chksum = FOLD_U32T(acc); +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + if (chksum_slow != seg->tcphdr->chksum) { + TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL( + ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", + seg->tcphdr->chksum, chksum_slow)); + seg->tcphdr->chksum = chksum_slow; + } +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ +#else /* TCP_CHECKSUM_ON_COPY */ + seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, + seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CHECKSUM_ON_COPY */ + } +#endif /* CHECKSUM_GEN_TCP */ + TCP_STATS_INC(tcp.xmit); + + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + pcb->tos, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + return err; +} + +/** + * Send a TCP RESET packet (empty segment with RST flag set) either to + * abort a connection or to show that there is no matching local connection + * for a received segment. + * + * Called by tcp_abort() (to abort a local connection), tcp_input() (if no + * matching local pcb was found), tcp_listen_input() (if incoming segment + * has ACK flag set) and tcp_process() (received segment in the wrong state) + * + * Since a RST segment is in most cases not sent for an active connection, + * tcp_rst() has a number of arguments that are taken from a tcp_pcb for + * most other segment output functions. + * + * @param seqno the sequence number to use for the outgoing segment + * @param ackno the acknowledge number to use for the outgoing segment + * @param local_ip the local IP address to send the segment from + * @param remote_ip the remote IP address to send the segment to + * @param local_port the local TCP port to send the segment from + * @param remote_port the remote TCP port to send the segment to + */ +void +tcp_rst(u32_t seqno, u32_t ackno, + const ip_addr_t *local_ip, const ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + struct netif *netif; + p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= sizeof(struct tcp_hdr))); + + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = lwip_htons(local_port); + tcphdr->dest = lwip_htons(remote_port); + tcphdr->seqno = lwip_htonl(seqno); + tcphdr->ackno = lwip_htonl(ackno); + TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); +#if LWIP_WND_SCALE + tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF)); +#else + tcphdr->wnd = PP_HTONS(TCP_WND); +#endif + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + TCP_STATS_INC(tcp.xmit); + MIB2_STATS_INC(mib2.tcpoutrsts); + + netif = ip_route(local_ip, remote_ip); + if (netif != NULL) { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + local_ip, remote_ip); + } +#endif + /* Send output with hardcoded TTL/HL since we have no access to the pcb */ + ip_output_if(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP, netif); + } + pbuf_free(p); + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); +} + +/** + * Requeue all unacked segments for retransmission + * + * Called by tcp_slowtmr() for slow retransmission. + * + * @param pcb the tcp_pcb for which to re-enqueue all unacked segments + */ +void +tcp_rexmit_rto(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move all unacked segments to the head of the unsent queue */ + for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); + /* concatenate unsent queue after unacked queue */ + seg->next = pcb->unsent; +#if TCP_OVERSIZE_DBGCHECK + /* if last unsent changed, we need to update unsent_oversize */ + if (pcb->unsent == NULL) { + pcb->unsent_oversize = seg->oversize_left; + } +#endif /* TCP_OVERSIZE_DBGCHECK */ + /* unsent queue is the concatenated queue (of unacked, unsent) */ + pcb->unsent = pcb->unacked; + /* unacked queue is now empty */ + pcb->unacked = NULL; + + /* increment number of retransmissions */ + if (pcb->nrtx < 0xFF) { + ++pcb->nrtx; + } + + /* Don't take any RTT measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission */ + tcp_output(pcb); +} + +/** + * Requeue the first unacked segment for retransmission + * + * Called by tcp_receive() for fast retransmit. + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + struct tcp_seg **cur_seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move the first unacked segment to the unsent queue */ + /* Keep the unsent queue sorted. */ + seg = pcb->unacked; + pcb->unacked = seg->next; + + cur_seg = &(pcb->unsent); + while (*cur_seg && + TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = *cur_seg; + *cur_seg = seg; +#if TCP_OVERSIZE + if (seg->next == NULL) { + /* the retransmitted segment is last in unsent, so reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + if (pcb->nrtx < 0xFF) { + ++pcb->nrtx; + } + + /* Don't take any rtt measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission. */ + MIB2_STATS_INC(mib2.tcpretranssegs); + /* No need to call tcp_output: we are always called from tcp_input() + and thus tcp_output directly returns. */ +} + + +/** + * Handle retransmission after three dupacks received + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit_fast(struct tcp_pcb *pcb) +{ + if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { + /* This is fast retransmit. Retransmit the first unacked segment. */ + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: dupacks %"U16_F" (%"U32_F + "), fast retransmit %"U32_F"\n", + (u16_t)pcb->dupacks, pcb->lastack, + lwip_ntohl(pcb->unacked->tcphdr->seqno))); + tcp_rexmit(pcb); + + /* Set ssthresh to half of the minimum of the current + * cwnd and the advertised window */ + pcb->ssthresh = LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2; + + /* The minimum value for ssthresh should be 2 MSS */ + if (pcb->ssthresh < (2U * pcb->mss)) { + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: The minimum value for ssthresh %"TCPWNDSIZE_F + " should be min 2 mss %"U16_F"...\n", + pcb->ssthresh, (u16_t)(2*pcb->mss))); + pcb->ssthresh = 2*pcb->mss; + } + + pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; + pcb->flags |= TF_INFR; + + /* Reset the retransmission timer to prevent immediate rto retransmissions */ + pcb->rtime = 0; + } +} + + +/** + * Send keepalive packets to keep a connection active although + * no data is sent over it. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a keepalive packet + */ +err_t +tcp_keepalive(struct tcp_pcb *pcb) +{ + err_t err; + struct pbuf *p; + struct netif *netif; + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to ")); + ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent)); + + p = tcp_output_alloc_header(pcb, 0, 0, lwip_htonl(pcb->snd_nxt - 1)); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_keepalive: could not allocate memory for pbuf\n")); + return ERR_MEM; + } + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + err = ERR_RTE; + } else { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); + } +#endif /* CHECKSUM_GEN_TCP */ + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n", + pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); + return err; +} + + +/** + * Send persist timer zero-window probes to keep a connection active + * when a window update is lost. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a zero-window probe packet + */ +err_t +tcp_zero_window_probe(struct tcp_pcb *pcb) +{ + err_t err; + struct pbuf *p; + struct tcp_hdr *tcphdr; + struct tcp_seg *seg; + u16_t len; + u8_t is_fin; + u32_t snd_nxt; + struct netif *netif; + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to ")); + ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_zero_window_probe: tcp_ticks %"U32_F + " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent)); + + seg = pcb->unacked; + + if (seg == NULL) { + seg = pcb->unsent; + } + if (seg == NULL) { + /* nothing to send, zero window probe not needed */ + return ERR_OK; + } + + is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); + /* we want to send one seqno: either FIN or data (no options) */ + len = is_fin ? 0 : 1; + + p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); + return ERR_MEM; + } + tcphdr = (struct tcp_hdr *)p->payload; + + if (is_fin) { + /* FIN segment, no data */ + TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); + } else { + /* Data segment, copy in one byte from the head of the unacked queue */ + char *d = ((char *)p->payload + TCP_HLEN); + /* Depending on whether the segment has already been sent (unacked) or not + (unsent), seg->p->payload points to the IP header or TCP header. + Ensure we copy the first TCP data byte: */ + pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); + } + + /* The byte may be acknowledged without the window being opened. */ + snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1; + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; + } + + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + err = ERR_RTE; + } else { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); + } +#endif + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + 0, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F + " ackno %"U32_F" err %d.\n", + pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); + return err; +} +#endif /* LWIP_TCP */ diff --git a/components/net/lwip-2.0.3/src/core/timeouts.c b/components/net/lwip-2.0.3/src/core/timeouts.c new file mode 100644 index 0000000000..8bf209a506 --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/timeouts.c @@ -0,0 +1,433 @@ +/** + * @file + * Stack-internal timers implementation. + * This file includes timer callbacks for stack-internal timers as well as + * functions to set up or stop timers and check for expired timers. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#include "lwip/timeouts.h" +#include "lwip/priv/tcp_priv.h" + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/priv/tcpip_priv.h" + +#include "lwip/ip4_frag.h" +#include "lwip/etharp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/nd6.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" +#include "lwip/sys.h" +#include "lwip/pbuf.h" + +#if LWIP_DEBUG_TIMERNAMES +#define HANDLER(x) x, #x +#else /* LWIP_DEBUG_TIMERNAMES */ +#define HANDLER(x) x +#endif /* LWIP_DEBUG_TIMERNAMES */ + +/** This array contains all stack-internal cyclic timers. To get the number of + * timers, use LWIP_ARRAYSIZE() */ +const struct lwip_cyclic_timer lwip_cyclic_timers[] = { +#if LWIP_TCP + /* The TCP timer is a special case: it does not have to run always and + is triggered to start from TCP using tcp_timer_needed() */ + {TCP_TMR_INTERVAL, HANDLER(tcp_tmr)}, +#endif /* LWIP_TCP */ +#if LWIP_IPV4 +#if IP_REASSEMBLY + {IP_TMR_INTERVAL, HANDLER(ip_reass_tmr)}, +#endif /* IP_REASSEMBLY */ +#if LWIP_ARP + {ARP_TMR_INTERVAL, HANDLER(etharp_tmr)}, +#endif /* LWIP_ARP */ +#if LWIP_DHCP + {DHCP_COARSE_TIMER_MSECS, HANDLER(dhcp_coarse_tmr)}, + {DHCP_FINE_TIMER_MSECS, HANDLER(dhcp_fine_tmr)}, +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + {AUTOIP_TMR_INTERVAL, HANDLER(autoip_tmr)}, +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + {IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)}, +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4 */ +#if LWIP_DNS + {DNS_TMR_INTERVAL, HANDLER(dns_tmr)}, +#endif /* LWIP_DNS */ +#if LWIP_IPV6 + {ND6_TMR_INTERVAL, HANDLER(nd6_tmr)}, +#if LWIP_IPV6_REASS + {IP6_REASS_TMR_INTERVAL, HANDLER(ip6_reass_tmr)}, +#endif /* LWIP_IPV6_REASS */ +#if LWIP_IPV6_MLD + {MLD6_TMR_INTERVAL, HANDLER(mld6_tmr)}, +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ +}; + +#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM + +/** The one and only timeout list */ +static struct sys_timeo *next_timeout; +static u32_t timeouts_last_time; + +#if LWIP_TCP +/** global variable that shows if the tcp timer is currently scheduled or not */ +static int tcpip_tcp_timer_active; + +/** + * Timer callback function that calls tcp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +tcpip_tcp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + /* call TCP timer handler */ + tcp_tmr(); + /* timer still needed? */ + if (tcp_active_pcbs || tcp_tw_pcbs) { + /* restart timer */ + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } else { + /* disable timer */ + tcpip_tcp_timer_active = 0; + } +} + +/** + * Called from TCP_REG when registering a new PCB: + * the reason is to have the TCP timer only running when + * there are active (or time-wait) PCBs. + */ +void +tcp_timer_needed(void) +{ + /* timer is off but needed again? */ + if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { + /* enable and start timer */ + tcpip_tcp_timer_active = 1; + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } +} +#endif /* LWIP_TCP */ + +/** + * Timer callback function that calls mld6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +cyclic_timer(void *arg) +{ + const struct lwip_cyclic_timer* cyclic = (const struct lwip_cyclic_timer*)arg; +#if LWIP_DEBUG_TIMERNAMES + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: %s()\n", cyclic->handler_name)); +#endif + cyclic->handler(); + sys_timeout(cyclic->interval_ms, cyclic_timer, arg); +} + +/** Initialize this module */ +void sys_timeouts_init(void) +{ + size_t i; + /* tcp_tmr() at index 0 is started on demand */ + for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) { + /* we have to cast via size_t to get rid of const warning + (this is OK as cyclic_timer() casts back to const* */ + sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i])); + } + + /* Initialise timestamp for sys_check_timeouts */ + timeouts_last_time = sys_now(); +} + +/** + * Create a one-shot timer (aka timeout). Timeouts are processed in the + * following cases: + * - while waiting for a message using sys_timeouts_mbox_fetch() + * - by calling sys_check_timeouts() (NO_SYS==1 only) + * + * @param msecs time in milliseconds after that the timer should expire + * @param handler callback function to call when msecs have elapsed + * @param arg argument to pass to the callback function + */ +#if LWIP_DEBUG_TIMERNAMES +void +sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) +#else /* LWIP_DEBUG_TIMERNAMES */ +void +sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) +#endif /* LWIP_DEBUG_TIMERNAMES */ +{ + struct sys_timeo *timeout, *t; + u32_t now, diff; + + timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); + if (timeout == NULL) { + LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); + return; + } + + now = sys_now(); + if (next_timeout == NULL) { + diff = 0; + timeouts_last_time = now; + } else { + diff = now - timeouts_last_time; + } + + timeout->next = NULL; + timeout->h = handler; + timeout->arg = arg; + timeout->time = msecs + diff; +#if LWIP_DEBUG_TIMERNAMES + timeout->handler_name = handler_name; + LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", + (void *)timeout, msecs, handler_name, (void *)arg)); +#endif /* LWIP_DEBUG_TIMERNAMES */ + + if (next_timeout == NULL) { + next_timeout = timeout; + return; + } + + if (next_timeout->time > msecs) { + next_timeout->time -= msecs; + timeout->next = next_timeout; + next_timeout = timeout; + } else { + for (t = next_timeout; t != NULL; t = t->next) { + timeout->time -= t->time; + if (t->next == NULL || t->next->time > timeout->time) { + if (t->next != NULL) { + t->next->time -= timeout->time; + } else if (timeout->time > msecs) { + /* If this is the case, 'timeouts_last_time' and 'now' differs too much. + This can be due to sys_check_timeouts() not being called at the right + times, but also when stopping in a breakpoint. Anyway, let's assume + this is not wanted, so add the first timer's time instead of 'diff' */ + timeout->time = msecs + next_timeout->time; + } + timeout->next = t->next; + t->next = timeout; + break; + } + } + } +} + +/** + * Go through timeout list (for this task only) and remove the first matching + * entry (subsequent entries remain untouched), even though the timeout has not + * triggered yet. + * + * @param handler callback function that would be called by the timeout + * @param arg callback argument that would be passed to handler +*/ +void +sys_untimeout(sys_timeout_handler handler, void *arg) +{ + struct sys_timeo *prev_t, *t; + + if (next_timeout == NULL) { + return; + } + + for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { + if ((t->h == handler) && (t->arg == arg)) { + /* We have a match */ + /* Unlink from previous in list */ + if (prev_t == NULL) { + next_timeout = t->next; + } else { + prev_t->next = t->next; + } + /* If not the last one, add time of this one back to next */ + if (t->next != NULL) { + t->next->time += t->time; + } + memp_free(MEMP_SYS_TIMEOUT, t); + return; + } + } + return; +} + +/** + * @ingroup lwip_nosys + * Handle timeouts for NO_SYS==1 (i.e. without using + * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout + * handler functions when timeouts expire. + * + * Must be called periodically from your main loop. + */ +#if !NO_SYS && !defined __DOXYGEN__ +static +#endif /* !NO_SYS */ +void +sys_check_timeouts(void) +{ + if (next_timeout) { + struct sys_timeo *tmptimeout; + u32_t diff; + sys_timeout_handler handler; + void *arg; + u8_t had_one; + u32_t now; + + now = sys_now(); + /* this cares for wraparounds */ + diff = now - timeouts_last_time; + do { + PBUF_CHECK_FREE_OOSEQ(); + had_one = 0; + tmptimeout = next_timeout; + if (tmptimeout && (tmptimeout->time <= diff)) { + /* timeout has expired */ + had_one = 1; + timeouts_last_time += tmptimeout->time; + diff -= tmptimeout->time; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { +#if !NO_SYS + /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the + timeout handler function. */ + LOCK_TCPIP_CORE(); +#endif /* !NO_SYS */ + handler(arg); +#if !NO_SYS + UNLOCK_TCPIP_CORE(); +#endif /* !NO_SYS */ + } + LWIP_TCPIP_THREAD_ALIVE(); + } + /* repeat until all expired timers have been called */ + } while (had_one); + } +} + +/** Set back the timestamp of the last call to sys_check_timeouts() + * This is necessary if sys_check_timeouts() hasn't been called for a long + * time (e.g. while saving energy) to prevent all timer functions of that + * period being called. + */ +void +sys_restart_timeouts(void) +{ + timeouts_last_time = sys_now(); +} + +/** Return the time left before the next timeout is due. If no timeouts are + * enqueued, returns 0xffffffff + */ +#if !NO_SYS +static +#endif /* !NO_SYS */ +u32_t +sys_timeouts_sleeptime(void) +{ + u32_t diff; + if (next_timeout == NULL) { + return 0xffffffff; + } + diff = sys_now() - timeouts_last_time; + if (diff > next_timeout->time) { + return 0; + } else { + return next_timeout->time - diff; + } +} + +#if !NO_SYS + +/** + * Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts are processed. + * + * @param mbox the mbox to fetch the message from + * @param msg the place to store the message + */ +void +sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) +{ + u32_t sleeptime; + +again: + if (!next_timeout) { + sys_arch_mbox_fetch(mbox, msg, 0); + return; + } + + sleeptime = sys_timeouts_sleeptime(); + if (sleeptime == 0 || sys_arch_mbox_fetch(mbox, msg, sleeptime) == SYS_ARCH_TIMEOUT) { + /* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurred + before a message could be fetched. */ + sys_check_timeouts(); + /* We try again to fetch a message from the mbox. */ + goto again; + } +} + +#endif /* NO_SYS */ + +#else /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ +/* Satisfy the TCP code which calls this function */ +void +tcp_timer_needed(void) +{ +} +#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ diff --git a/components/net/lwip-2.0.3/src/core/udp.c b/components/net/lwip-2.0.3/src/core/udp.c new file mode 100644 index 0000000000..ce2e3d295f --- /dev/null +++ b/components/net/lwip-2.0.3/src/core/udp.c @@ -0,0 +1,1191 @@ +/** + * @file + * User Datagram Protocol module\n + * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).\n + * See also @ref udp_raw + * + * @defgroup udp_raw UDP + * @ingroup callbackstyle_api + * User Datagram Protocol module\n + * @see @ref raw_api and @ref netconn + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! + */ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/icmp6.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" + +#include + +#ifndef UDP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define UDP_LOCAL_PORT_RANGE_START 0xc000 +#define UDP_LOCAL_PORT_RANGE_END 0xffff +#define UDP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START)) +#endif + +/* last local UDP port */ +static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START; + +/* The list of UDP PCBs */ +/* exported in udp.h (was static) */ +struct udp_pcb *udp_pcbs; + +/** + * Initialize this module. + */ +void +udp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Allocate a new local UDP port. + * + * @return a new (free) local UDP port number + */ +static u16_t +udp_new_port(void) +{ + u16_t n = 0; + struct udp_pcb *pcb; + +again: + if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) { + udp_port = UDP_LOCAL_PORT_RANGE_START; + } + /* Check all PCBs. */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == udp_port) { + if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + return udp_port; +} + +/** Common code to see if the current input packet matches the pcb + * (current input packet is accessed via ip(4/6)_current_* macros) + * + * @param pcb pcb to check + * @param inp network interface on which the datagram was received (only used for IPv4) + * @param broadcast 1 if his is an IPv4 broadcast (global or subnet-only), 0 otherwise (only used for IPv4) + * @return 1 on match, 0 otherwise + */ +static u8_t +udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) +{ + LWIP_UNUSED_ARG(inp); /* in IPv6 only case */ + LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ + + /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ + if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { +#if LWIP_IPV4 && IP_SOF_BROADCAST_RECV + if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { + return 0; + } +#endif /* LWIP_IPV4 && IP_SOF_BROADCAST_RECV */ + return 1; + } + + /* Only need to check PCB if incoming IP version matches PCB IP version */ + if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { +#if LWIP_IPV4 + /* Special case: IPv4 broadcast: all or broadcasts in my subnet + * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ + if (broadcast != 0) { +#if IP_SOF_BROADCAST_RECV + if (ip_get_option(pcb, SOF_BROADCAST)) +#endif /* IP_SOF_BROADCAST_RECV */ + { + if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || + ((ip4_current_dest_addr()->addr == IPADDR_BROADCAST)) || + ip4_addr_netcmp(ip_2_ip4(&pcb->local_ip), ip4_current_dest_addr(), netif_ip4_netmask(inp))) { + return 1; + } + } + } else +#endif /* LWIP_IPV4 */ + /* Handle IPv4 and IPv6: all or exact match */ + if (ip_addr_isany(&pcb->local_ip) || ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + return 1; + } + } + + return 0; +} + +/** + * Process an incoming UDP datagram. + * + * Given an incoming UDP datagram (as a chain of pbufs) this function + * finds a corresponding UDP PCB and hands over the pbuf to the pcbs + * recv function. If no pcb is found or the datagram is incorrect, the + * pbuf is freed. + * + * @param p pbuf to be demultiplexed to a UDP PCB (p->payload pointing to the UDP header) + * @param inp network interface on which the datagram was received. + * + */ +void +udp_input(struct pbuf *p, struct netif *inp) +{ + struct udp_hdr *udphdr; + struct udp_pcb *pcb, *prev; + struct udp_pcb *uncon_pcb; + u16_t src, dest; + u8_t broadcast; + u8_t for_us = 0; + + LWIP_UNUSED_ARG(inp); + + PERF_START; + + UDP_STATS_INC(udp.recv); + + /* Check minimum length (UDP header) */ + if (p->len < UDP_HLEN) { + /* drop short packets */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); + UDP_STATS_INC(udp.lenerr); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpinerrors); + pbuf_free(p); + goto end; + } + + udphdr = (struct udp_hdr *)p->payload; + + /* is broadcast packet ? */ + broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); + + LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); + + /* convert src and dest ports to host byte order */ + src = lwip_ntohs(udphdr->src); + dest = lwip_ntohs(udphdr->dest); + + udp_debug_print(udphdr); + + /* print the UDP source and destination */ + LWIP_DEBUGF(UDP_DEBUG, ("udp (")); + ip_addr_debug_print(UDP_DEBUG, ip_current_dest_addr()); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", lwip_ntohs(udphdr->dest))); + ip_addr_debug_print(UDP_DEBUG, ip_current_src_addr()); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", lwip_ntohs(udphdr->src))); + + pcb = NULL; + prev = NULL; + uncon_pcb = NULL; + /* Iterate through the UDP pcb list for a matching pcb. + * 'Perfect match' pcbs (connected to the remote port & ip address) are + * preferred. If no perfect match is found, the first unconnected pcb that + * matches the local port and ip address gets the datagram. */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + /* print the PCB local and remote address */ + LWIP_DEBUGF(UDP_DEBUG, ("pcb (")); + ip_addr_debug_print(UDP_DEBUG, &pcb->local_ip); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port)); + ip_addr_debug_print(UDP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port)); + + /* compare PCB local addr+port to UDP destination addr+port */ + if ((pcb->local_port == dest) && + (udp_input_local_match(pcb, inp, broadcast) != 0)) { + if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) && + ((uncon_pcb == NULL) +#if SO_REUSE + /* prefer specific IPs over cath-all */ + || !ip_addr_isany(&pcb->local_ip) +#endif /* SO_REUSE */ + )) { + /* the first unconnected matching PCB */ + uncon_pcb = pcb; + } + + /* compare PCB remote addr+port to UDP source addr+port */ + if ((pcb->remote_port == src) && + (ip_addr_isany_val(pcb->remote_ip) || + ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { + /* the first fully matching PCB */ + if (prev != NULL) { + /* move the pcb to the front of udp_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } else { + UDP_STATS_INC(udp.cachehit); + } + break; + } + } + + prev = pcb; + } + /* no fully matching pcb found? then look for an unconnected pcb */ + if (pcb == NULL) { + pcb = uncon_pcb; + } + + /* Check checksum if this is a match or if it was directed at us. */ + if (pcb != NULL) { + for_us = 1; + } else { +#if LWIP_IPV6 + if (ip_current_is_v6()) { + for_us = netif_get_ip6_addr_match(inp, ip6_current_dest_addr()) >= 0; + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + if (!ip_current_is_v6()) { + for_us = ip4_addr_cmp(netif_ip4_addr(inp), ip4_current_dest_addr()); + } +#endif /* LWIP_IPV4 */ + } + + if (for_us) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); +#if CHECKSUM_CHECK_UDP + IF__NETIF_CHECKSUM_ENABLED(inp, CHECKSUM_CHECK_UDP) { +#if LWIP_UDPLITE + if (ip_current_header_proto() == IP_PROTO_UDPLITE) { + /* Do the UDP Lite checksum */ + u16_t chklen = lwip_ntohs(udphdr->len); + if (chklen < sizeof(struct udp_hdr)) { + if (chklen == 0) { + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet (See RFC 3828 chap. 3.1) */ + chklen = p->tot_len; + } else { + /* At least the UDP-Lite header must be covered by the + checksum! (Again, see RFC 3828 chap. 3.1) */ + goto chkerr; + } + } + if (ip_chksum_pseudo_partial(p, IP_PROTO_UDPLITE, + p->tot_len, chklen, + ip_current_src_addr(), ip_current_dest_addr()) != 0) { + goto chkerr; + } + } else +#endif /* LWIP_UDPLITE */ + { + if (udphdr->chksum != 0) { + if (ip_chksum_pseudo(p, IP_PROTO_UDP, p->tot_len, + ip_current_src_addr(), + ip_current_dest_addr()) != 0) { + goto chkerr; + } + } + } + } +#endif /* CHECKSUM_CHECK_UDP */ + if (pbuf_header(p, -UDP_HLEN)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpinerrors); + pbuf_free(p); + goto end; + } + + if (pcb != NULL) { + MIB2_STATS_INC(mib2.udpindatagrams); +#if SO_REUSE && SO_REUSE_RXTOALL + if (ip_get_option(pcb, SOF_REUSEADDR) && + (broadcast || ip_addr_ismulticast(ip_current_dest_addr()))) { + /* pass broadcast- or multicast packets to all multicast pcbs + if SOF_REUSEADDR is set on the first match */ + struct udp_pcb *mpcb; + u8_t p_header_changed = 0; + s16_t hdrs_len = (s16_t)(ip_current_header_tot_len() + UDP_HLEN); + for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { + if (mpcb != pcb) { + /* compare PCB local addr+port to UDP destination addr+port */ + if ((mpcb->local_port == dest) && + (udp_input_local_match(mpcb, inp, broadcast) != 0)) { + /* pass a copy of the packet to all local matches */ + if (mpcb->recv != NULL) { + struct pbuf *q; + /* for that, move payload to IP header again */ + if (p_header_changed == 0) { + pbuf_header_force(p, hdrs_len); + p_header_changed = 1; + } + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + err_t err = pbuf_copy(q, p); + if (err == ERR_OK) { + /* move payload to UDP data */ + pbuf_header(q, -hdrs_len); + mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); + } + } + } + } + } + } + if (p_header_changed) { + /* and move payload to UDP data again */ + pbuf_header(p, -hdrs_len); + } + } +#endif /* SO_REUSE && SO_REUSE_RXTOALL */ + /* callback */ + if (pcb->recv != NULL) { + /* now the recv function is responsible for freeing p */ + pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); + } else { + /* no recv function registered? then we have to free the pbuf! */ + pbuf_free(p); + goto end; + } + } else { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); + +#if LWIP_ICMP || LWIP_ICMP6 + /* No match was found, send ICMP destination port unreachable unless + destination address was broadcast/multicast. */ + if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) { + /* move payload pointer back to ip header */ + pbuf_header_force(p, (s16_t)(ip_current_header_tot_len() + UDP_HLEN)); + icmp_port_unreach(ip_current_is_v6(), p); + } +#endif /* LWIP_ICMP || LWIP_ICMP6 */ + UDP_STATS_INC(udp.proterr); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpnoports); + pbuf_free(p); + } + } else { + pbuf_free(p); + } +end: + PERF_STOP("udp_input"); + return; +#if CHECKSUM_CHECK_UDP +chkerr: + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n")); + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpinerrors); + pbuf_free(p); + PERF_STOP("udp_input"); +#endif /* CHECKSUM_CHECK_UDP */ +} + +/** + * @ingroup udp_raw + * Send data using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * + * The datagram will be sent to the current remote_ip & remote_port + * stored in pcb. If the pcb is not bound to a port, it will + * automatically be bound to a random port. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_MEM. Out of memory. + * - ERR_RTE. Could not find route to destination address. + * - ERR_VAL. No PCB or PCB is dual-stack + * - More errors could be returned by lower protocol layers. + * + * @see udp_disconnect() udp_sendto() + */ +err_t +udp_send(struct udp_pcb *pcb, struct pbuf *p) +{ + if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { + return ERR_VAL; + } + + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port); +} + +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +/** @ingroup udp_raw + * Same as udp_send() but with checksum + */ +err_t +udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum) +{ + if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { + return ERR_VAL; + } + + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port, + have_chksum, chksum); +} +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + +/** + * @ingroup udp_raw + * Send data to a specified address using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * If the PCB already has a remote address association, it will + * be restored after the data is sent. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0); +} + +/** @ingroup udp_raw + * Same as udp_sendto(), but with checksum */ +err_t +udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, + u16_t dst_port, u8_t have_chksum, u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + struct netif *netif; + const ip_addr_t *dst_ip_route = dst_ip; + + if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { + return ERR_VAL; + } + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); + +#if LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) + if (ip_addr_ismulticast(dst_ip_route)) { +#if LWIP_IPV6 + if (IP_IS_V6(dst_ip)) { + /* For multicast, find a netif based on source address. */ + dst_ip_route = &pcb->local_ip; + } else +#endif /* LWIP_IPV6 */ + { +#if LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS + /* IPv4 does not use source-based routing by default, so we use an + administratively selected interface for multicast by default. + However, this can be overridden by setting an interface address + in pcb->multicast_ip that is used for routing. */ + if (!ip_addr_isany_val(pcb->multicast_ip) && + !ip4_addr_cmp(ip_2_ip4(&pcb->multicast_ip), IP4_ADDR_BROADCAST)) { + dst_ip_route = &pcb->multicast_ip; + } +#endif /* LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS */ + } + } +#endif /* LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) */ + + /* find the outgoing network interface for this packet */ + if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { + /* Don't call ip_route() with IP_ANY_TYPE */ + netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dst_ip_route)), dst_ip_route); + } else { + netif = ip_route(&pcb->local_ip, dst_ip_route); + } + + /* no outgoing network interface could be found? */ + if (netif == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, dst_ip); + LWIP_DEBUGF(UDP_DEBUG, ("\n")); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum); +#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +} + +/** + * @ingroup udp_raw + * Send data to a specified address using UDP. + * The netif used for sending can be specified. + * + * This function exists mainly for DHCP, to be able to send UDP packets + * on a netif that is still down. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * @param netif the netif used for sending. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0); +} + +/** Same as udp_sendto_if(), but with checksum */ +err_t +udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + const ip_addr_t *src_ip; + + if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { + return ERR_VAL; + } + + /* PCB local address is IP_ANY_ADDR? */ +#if LWIP_IPV6 + if (IP_IS_V6(dst_ip)) { + if (ip6_addr_isany(ip_2_ip6(&pcb->local_ip))) { + src_ip = ip6_select_source_address(netif, ip_2_ip6(dst_ip)); + if (src_ip == NULL) { + /* No suitable source address was found. */ + return ERR_RTE; + } + } else { + /* use UDP PCB local IPv6 address as source address, if still valid. */ + if (netif_get_ip6_addr_match(netif, ip_2_ip6(&pcb->local_ip)) < 0) { + /* Address isn't valid anymore. */ + return ERR_RTE; + } + src_ip = &pcb->local_ip; + } + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_IPV4 + if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || + ip4_addr_ismulticast(ip_2_ip4(&pcb->local_ip))) { + /* if the local_ip is any or multicast + * use the outgoing network interface IP address as source address */ + src_ip = netif_ip_addr4(netif); + } else { + /* check if UDP PCB local IP address is correct + * this could be an old address if netif->ip_addr has changed */ + if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) { + /* local_ip doesn't match, drop the packet */ + return ERR_RTE; + } + /* use UDP PCB local IP address as source address */ + src_ip = &pcb->local_ip; + } +#endif /* LWIP_IPV4 */ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum, src_ip); +#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + return udp_sendto_if_src(pcb, p, dst_ip, dst_port, netif, src_ip); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +} + +/** @ingroup udp_raw + * Same as @ref udp_sendto_if, but with source address */ +err_t +udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, const ip_addr_t *src_ip) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0, src_ip); +} + +/** Same as udp_sendto_if_src(), but with checksum */ +err_t +udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum, const ip_addr_t *src_ip) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + struct udp_hdr *udphdr; + err_t err; + struct pbuf *q; /* q will be sent down the stack */ + u8_t ip_proto; + u8_t ttl; + + if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, src_ip) || + !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { + return ERR_VAL; + } + +#if LWIP_IPV4 && IP_SOF_BROADCAST + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && +#if LWIP_IPV6 + IP_IS_V4(dst_ip) && +#endif /* LWIP_IPV6 */ + ip_addr_isbroadcast(dst_ip, netif)) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + return ERR_VAL; + } +#endif /* LWIP_IPV4 && IP_SOF_BROADCAST */ + + /* if the PCB is not yet bound to a port, bind it here */ + if (pcb->local_port == 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); + err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); + return err; + } + } + + /* not enough space to add an UDP header to first pbuf in given p chain? */ + if (pbuf_header(p, UDP_HLEN)) { + /* allocate header in a separate new pbuf */ + q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p (only if p contains data) */ + pbuf_chain(q, p); + } + /* first pbuf q points to header pbuf */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* adding space for header within p succeeded */ + /* first pbuf q equals given pbuf */ + q = p; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); + } + LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", + (q->len >= sizeof(struct udp_hdr))); + /* q now represents the packet to be sent */ + udphdr = (struct udp_hdr *)q->payload; + udphdr->src = lwip_htons(pcb->local_port); + udphdr->dest = lwip_htons(dst_port); + /* in UDP, 0 checksum means 'no checksum' */ + udphdr->chksum = 0x0000; + + /* Multicast Loop? */ +#if (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) + if (((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) && ip_addr_ismulticast(dst_ip)) { + q->flags |= PBUF_FLAG_MCASTLOOP; + } +#endif /* (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); + +#if LWIP_UDPLITE + /* UDP Lite protocol? */ + if (pcb->flags & UDP_FLAGS_UDPLITE) { + u16_t chklen, chklen_hdr; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); + /* set UDP message length in UDP header */ + chklen_hdr = chklen = pcb->chksum_len_tx; + if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { + if (chklen != 0) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); + } + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet. (See RFC 3828 chap. 3.1) + At least the UDP-Lite header must be covered by the + checksum, therefore, if chksum_len has an illegal + value, we generate the checksum over the complete + packet to be safe. */ + chklen_hdr = 0; + chklen = q->tot_len; + } + udphdr->len = lwip_htons(chklen_hdr); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + chklen = UDP_HLEN; + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + udphdr->chksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDPLITE, + q->tot_len, chklen, src_ip, dst_ip); +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + acc = udphdr->chksum + (u16_t)~(chksum); + udphdr->chksum = FOLD_U32T(acc); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udphdr->chksum == 0x0000) { + udphdr->chksum = 0xffff; + } + } +#endif /* CHECKSUM_GEN_UDP */ + + ip_proto = IP_PROTO_UDPLITE; + } else +#endif /* LWIP_UDPLITE */ + { /* UDP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); + udphdr->len = lwip_htons(q->tot_len); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { + /* Checksum is mandatory over IPv6. */ + if (IP_IS_V6(dst_ip) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { + u16_t udpchksum; +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + udpchksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDP, + q->tot_len, UDP_HLEN, src_ip, dst_ip); + acc = udpchksum + (u16_t)~(chksum); + udpchksum = FOLD_U32T(acc); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + udpchksum = ip_chksum_pseudo(q, IP_PROTO_UDP, q->tot_len, + src_ip, dst_ip); + } + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udpchksum == 0x0000) { + udpchksum = 0xffff; + } + udphdr->chksum = udpchksum; + } + } +#endif /* CHECKSUM_GEN_UDP */ + ip_proto = IP_PROTO_UDP; + } + + /* Determine TTL to use */ +#if LWIP_MULTICAST_TX_OPTIONS + ttl = (ip_addr_ismulticast(dst_ip) ? udp_get_multicast_ttl(pcb) : pcb->ttl); +#else /* LWIP_MULTICAST_TX_OPTIONS */ + ttl = pcb->ttl; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto)); + /* output to IP */ + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if_src(q, src_ip, dst_ip, ttl, pcb->tos, ip_proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + /* @todo: must this be increased even if error occurred? */ + MIB2_STATS_INC(mib2.udpoutdatagrams); + + /* did we chain a separate header pbuf earlier? */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + + UDP_STATS_INC(udp.xmit); + return err; +} + +/** + * @ingroup udp_raw + * Bind an UDP PCB. + * + * @param pcb UDP PCB to be bound with a local address ipaddr and port. + * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to + * bind to all local interfaces. + * @param port local UDP port to bind with. Use 0 to automatically bind + * to a random port between UDP_LOCAL_PORT_RANGE_START and + * UDP_LOCAL_PORT_RANGE_END. + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_USE. The specified ipaddr and port are already bound to by + * another UDP PCB. + * + * @see udp_disconnect() + */ +err_t +udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + u8_t rebind; + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ + if (ipaddr == NULL) { + ipaddr = IP4_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + + /* still need to check for ipaddr == NULL in IPv6 only case */ + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE, ipaddr); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); + + rebind = 0; + /* Check for double bind and rebind of the same pcb */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + /* is this UDP PCB already on active list? */ + if (pcb == ipcb) { + rebind = 1; + break; + } + } + + /* no port specified? */ + if (port == 0) { + port = udp_new_port(); + if (port == 0) { + /* no more ports available in local range */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); + return ERR_USE; + } + } else { + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + if (pcb != ipcb) { + /* By default, we don't allow to bind to a port that any other udp + PCB is already bound to, unless *all* PCBs with that port have tha + REUSEADDR flag set. */ +#if SO_REUSE + if (!ip_get_option(pcb, SOF_REUSEADDR) || + !ip_get_option(ipcb, SOF_REUSEADDR)) +#endif /* SO_REUSE */ + { + /* port matches that of PCB in list and REUSEADDR not set -> reject */ + if ((ipcb->local_port == port) && + /* IP address matches? */ + ip_addr_cmp(&ipcb->local_ip, ipaddr)) { + /* other PCB already binds to this local IP and port */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); + return ERR_USE; + } + } + } + } + } + + ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); + + pcb->local_port = port; + mib2_udp_bind(pcb); + /* pcb not active yet? */ + if (rebind == 0) { + /* place the PCB on the active list if not already there */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port)); + return ERR_OK; +} + +/** + * @ingroup udp_raw + * Connect an UDP PCB. + * + * This will associate the UDP PCB with the remote address. + * + * @param pcb UDP PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * @param port remote UDP port to connect with. + * + * @return lwIP error code + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * The udp pcb is bound to a random local port if not already bound. + * + * @see udp_disconnect() + */ +err_t +udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + + if (pcb->local_port == 0) { + err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) { + return err; + } + } + + ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); + pcb->remote_port = port; + pcb->flags |= UDP_FLAGS_CONNECTED; + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + &pcb->remote_ip); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port)); + + /* Insert UDP PCB into the list of active UDP PCBs. */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + if (pcb == ipcb) { + /* already on the list, just return */ + return ERR_OK; + } + } + /* PCB not yet on the list, add PCB now */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + return ERR_OK; +} + +/** + * @ingroup udp_raw + * Disconnect a UDP PCB + * + * @param pcb the udp pcb to disconnect. + */ +void +udp_disconnect(struct udp_pcb *pcb) +{ + /* reset remote address association */ +#if LWIP_IPV4 && LWIP_IPV6 + if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { + ip_addr_copy(pcb->remote_ip, *IP_ANY_TYPE); + } else { +#endif + ip_addr_set_any(IP_IS_V6_VAL(pcb->remote_ip), &pcb->remote_ip); +#if LWIP_IPV4 && LWIP_IPV6 + } +#endif + pcb->remote_port = 0; + /* mark PCB as unconnected */ + pcb->flags &= ~UDP_FLAGS_CONNECTED; +} + +/** + * @ingroup udp_raw + * Set a receive callback for a UDP PCB + * + * This callback will be called when receiving a datagram for the pcb. + * + * @param pcb the pcb for which to set the recv callback + * @param recv function pointer of the callback function + * @param recv_arg additional argument to pass to the callback function + */ +void +udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * @ingroup udp_raw + * Remove an UDP PCB. + * + * @param pcb UDP PCB to be removed. The PCB is removed from the list of + * UDP PCB's and the data structure is freed from memory. + * + * @see udp_new() + */ +void +udp_remove(struct udp_pcb *pcb) +{ + struct udp_pcb *pcb2; + + mib2_udp_unbind(pcb); + /* pcb to be removed is first in list? */ + if (udp_pcbs == pcb) { + /* make list start at 2nd pcb */ + udp_pcbs = udp_pcbs->next; + /* pcb not 1st in list */ + } else { + for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in udp_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + break; + } + } + } + memp_free(MEMP_UDP_PCB, pcb); +} + +/** + * @ingroup udp_raw + * Create a UDP PCB. + * + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new(void) +{ + struct udp_pcb *pcb; + pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); + /* could allocate UDP PCB? */ + if (pcb != NULL) { + /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 + * which means checksum is generated over the whole datagram per default + * (recommended as default by RFC 3828). */ + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct udp_pcb)); + pcb->ttl = UDP_TTL; +#if LWIP_MULTICAST_TX_OPTIONS + udp_set_multicast_ttl(pcb, UDP_TTL); +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + } + return pcb; +} + +/** + * @ingroup udp_raw + * Create a UDP PCB for specific IP type. + * + * @param type IP address type, see @ref lwip_ip_addr_type definitions. + * If you want to listen to IPv4 and IPv6 (dual-stack) packets, + * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new_ip_type(u8_t type) +{ + struct udp_pcb *pcb; + pcb = udp_new(); +#if LWIP_IPV4 && LWIP_IPV6 + if (pcb != NULL) { + IP_SET_TYPE_VAL(pcb->local_ip, type); + IP_SET_TYPE_VAL(pcb->remote_ip, type); + } +#else + LWIP_UNUSED_ARG(type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + return pcb; +} + +/** This function is called from netif.c when address is changed + * + * @param old_addr IP address of the netif before change + * @param new_addr IP address of the netif after change + */ +void udp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) +{ + struct udp_pcb* upcb; + + if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { + for (upcb = udp_pcbs; upcb != NULL; upcb = upcb->next) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&upcb->local_ip, old_addr)) { + /* The PCB is bound to the old ipaddr and + * is set to bound to the new one instead */ + ip_addr_copy(upcb->local_ip, *new_addr); + } + } + } +} + +#if UDP_DEBUG +/** + * Print UDP header information for debug purposes. + * + * @param udphdr pointer to the udp header in memory. + */ +void +udp_debug_print(struct udp_hdr *udphdr) +{ + LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + lwip_ntohs(udphdr->src), lwip_ntohs(udphdr->dest))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", + lwip_ntohs(udphdr->len), lwip_ntohs(udphdr->chksum))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* UDP_DEBUG */ + +#endif /* LWIP_UDP */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/api.h b/components/net/lwip-2.0.3/src/include/lwip/api.h new file mode 100644 index 0000000000..516bd163dd --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/api.h @@ -0,0 +1,400 @@ +/** + * @file + * netconn API (to be used from non-TCPIP threads) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_API_H +#define LWIP_HDR_API_H + +#include "lwip/opt.h" + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +/* Note: Netconn API is always available when sockets are enabled - + * sockets are implemented on top of them */ + +#include "lwip/arch.h" +#include "lwip/netbuf.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for netconn_write (u8_t) */ +#define NETCONN_NOFLAG 0x00 +#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ +#define NETCONN_COPY 0x01 +#define NETCONN_MORE 0x02 +#define NETCONN_DONTBLOCK 0x04 + +/* Flags for struct netconn.flags (u8_t) */ +/** Should this netconn avoid blocking? */ +#define NETCONN_FLAG_NON_BLOCKING 0x02 +/** Was the last connect action a non-blocking one? */ +#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +#define NETCONN_FLAG_CHECK_WRITESPACE 0x10 +#if LWIP_IPV6 +/** If this flag is set then only IPv6 communication is allowed on the + netconn. As per RFC#3493 this features defaults to OFF allowing + dual-stack usage by default. */ +#define NETCONN_FLAG_IPV6_V6ONLY 0x20 +#endif /* LWIP_IPV6 */ + + +/* Helpers to process several netconn_types by the same code */ +#define NETCONNTYPE_GROUP(t) ((t)&0xF0) +#define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0) +#if LWIP_IPV6 +#define NETCONN_TYPE_IPV6 0x08 +#define NETCONNTYPE_ISIPV6(t) (((t)&NETCONN_TYPE_IPV6) != 0) +#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE) +#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM) +#else /* LWIP_IPV6 */ +#define NETCONNTYPE_ISIPV6(t) (0) +#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE) +#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM) +#endif /* LWIP_IPV6 */ + +/** @ingroup netconn_common + * Protocol family and type of the netconn + */ +enum netconn_type { + NETCONN_INVALID = 0, + /** TCP IPv4 */ + NETCONN_TCP = 0x10, +#if LWIP_IPV6 + /** TCP IPv6 */ + NETCONN_TCP_IPV6 = NETCONN_TCP | NETCONN_TYPE_IPV6 /* 0x18 */, +#endif /* LWIP_IPV6 */ + /** UDP IPv4 */ + NETCONN_UDP = 0x20, + /** UDP IPv4 lite */ + NETCONN_UDPLITE = 0x21, + /** UDP IPv4 no checksum */ + NETCONN_UDPNOCHKSUM = 0x22, + +#if LWIP_IPV6 + /** UDP IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ + NETCONN_UDP_IPV6 = NETCONN_UDP | NETCONN_TYPE_IPV6 /* 0x28 */, + /** UDP IPv6 lite (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ + NETCONN_UDPLITE_IPV6 = NETCONN_UDPLITE | NETCONN_TYPE_IPV6 /* 0x29 */, + /** UDP IPv6 no checksum (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ + NETCONN_UDPNOCHKSUM_IPV6 = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_IPV6 /* 0x2a */, +#endif /* LWIP_IPV6 */ + + /** Raw connection IPv4 */ + NETCONN_RAW = 0x40 +#if LWIP_IPV6 + /** Raw connection IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ + , NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */ +#endif /* LWIP_IPV6 */ +}; + +/** Current state of the netconn. Non-TCP netconns are always + * in state NETCONN_NONE! */ +enum netconn_state { + NETCONN_NONE, + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, + NETCONN_CLOSE +}; + +/** Used to inform the callback function about changes + * + * Event explanation: + * + * In the netconn implementation, there are three ways to block a client: + * + * - accept mbox (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); in netconn_accept()) + * - receive mbox (sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); in netconn_recv_data()) + * - send queue is full (sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); in lwip_netconn_do_write()) + * + * The events have to be seen as events signaling the state of these mboxes/semaphores. For non-blocking + * connections, you need to know in advance whether a call to a netconn function call would block or not, + * and these events tell you about that. + * + * RCVPLUS events say: Safe to perform a potentially blocking call call once more. + * They are counted in sockets - three RCVPLUS events for accept mbox means you are safe + * to call netconn_accept 3 times without being blocked. + * Same thing for receive mbox. + * + * RCVMINUS events say: Your call to to a possibly blocking function is "acknowledged". + * Socket implementation decrements the counter. + * + * For TX, there is no need to count, its merely a flag. SENDPLUS means you may send something. + * SENDPLUS occurs when enough data was delivered to peer so netconn_send() can be called again. + * A SENDMINUS event occurs when the next call to a netconn_send() would be blocking. + */ +enum netconn_evt { + NETCONN_EVT_RCVPLUS, + NETCONN_EVT_RCVMINUS, + NETCONN_EVT_SENDPLUS, + NETCONN_EVT_SENDMINUS, + NETCONN_EVT_ERROR +}; + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** Used for netconn_join_leave_group() */ +enum netconn_igmp { + NETCONN_JOIN, + NETCONN_LEAVE +}; +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/* Used for netconn_gethostbyname_addrtype(), these should match the DNS_ADDRTYPE defines in dns.h */ +#define NETCONN_DNS_DEFAULT NETCONN_DNS_IPV4_IPV6 +#define NETCONN_DNS_IPV4 0 +#define NETCONN_DNS_IPV6 1 +#define NETCONN_DNS_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */ +#define NETCONN_DNS_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */ +#endif /* LWIP_DNS */ + +/* forward-declare some structs to avoid to include their headers */ +struct ip_pcb; +struct tcp_pcb; +struct udp_pcb; +struct raw_pcb; +struct netconn; +struct api_msg; + +/** A callback prototype to inform about events for a netconn */ +typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); + +/** A netconn descriptor */ +struct netconn { + /** type of the netconn (TCP, UDP or RAW) */ + enum netconn_type type; + /** current state of the netconn */ + enum netconn_state state; + /** the lwIP internal protocol control block */ + union { + struct ip_pcb *ip; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; + } pcb; + /** the last error this netconn had */ + err_t last_err; +#if !LWIP_NETCONN_SEM_PER_THREAD + /** sem that is used to synchronously execute functions in the core context */ + sys_sem_t op_completed; +#endif + /** mbox where received packets are stored until they are fetched + by the netconn application thread (can grow quite big) */ + sys_mbox_t recvmbox; +#if LWIP_TCP + /** mbox where new connections are stored until processed + by the application thread */ + sys_mbox_t acceptmbox; +#endif /* LWIP_TCP */ + /** only used for socket layer */ +#if LWIP_SOCKET + int socket; +#endif /* LWIP_SOCKET */ +#if LWIP_SO_SNDTIMEO + /** timeout to wait for sending data (which means enqueueing data for sending + in internal buffers) in milliseconds */ + s32_t send_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVTIMEO + /** timeout in milliseconds to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + /** maximum amount of bytes queued in recvmbox + not used for TCP: adjust TCP_WND instead! */ + int recv_bufsize; + /** number of bytes currently in recvmbox to be received, + tested against recv_bufsize to limit bytes on recvmbox + for UDP and RAW, used for FIONREAD */ + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + /** values <0 mean linger is disabled, values > 0 are seconds to linger */ + s16_t linger; +#endif /* LWIP_SO_LINGER */ + /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ + u8_t flags; +#if LWIP_TCP + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores how much is already sent. */ + size_t write_offset; + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores the message. + Also used during connect and close. */ + struct api_msg *current_msg; +#endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; +}; + +/** Register an Network connection event */ +#define API_EVENT(c,e,l) if (c->callback) { \ + (*c->callback)(c, e, l); \ + } + +/** Set conn->last_err to err but don't overwrite fatal errors */ +#define NETCONN_SET_SAFE_ERR(conn, err) do { if ((conn) != NULL) { \ + SYS_ARCH_DECL_PROTECT(netconn_set_safe_err_lev); \ + SYS_ARCH_PROTECT(netconn_set_safe_err_lev); \ + if (!ERR_IS_FATAL((conn)->last_err)) { \ + (conn)->last_err = err; \ + } \ + SYS_ARCH_UNPROTECT(netconn_set_safe_err_lev); \ +}} while(0); + +/* Network connection functions: */ + +/** @ingroup netconn_common + * Create new netconn connection + * @param t @ref netconn_type */ +#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) +#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) +struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, + netconn_callback callback); +err_t netconn_delete(struct netconn *conn); +/** Get the type of a netconn (as enum netconn_type). */ +#define netconn_type(conn) (conn->type) + +err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, + u16_t *port, u8_t local); +/** @ingroup netconn_common */ +#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) +/** @ingroup netconn_common */ +#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + +err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port); +err_t netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port); +err_t netconn_disconnect (struct netconn *conn); +err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); +/** @ingroup netconn_tcp */ +#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) +err_t netconn_accept(struct netconn *conn, struct netconn **new_conn); +err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf); +err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf); +err_t netconn_sendto(struct netconn *conn, struct netbuf *buf, + const ip_addr_t *addr, u16_t port); +err_t netconn_send(struct netconn *conn, struct netbuf *buf); +err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written); +/** @ingroup netconn_tcp */ +#define netconn_write(conn, dataptr, size, apiflags) \ + netconn_write_partly(conn, dataptr, size, apiflags, NULL) +err_t netconn_close(struct netconn *conn); +err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx); + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +err_t netconn_join_leave_group(struct netconn *conn, const ip_addr_t *multiaddr, + const ip_addr_t *netif_addr, enum netconn_igmp join_or_leave); +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ +#if LWIP_DNS +#if LWIP_IPV4 && LWIP_IPV6 +err_t netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype); +#define netconn_gethostbyname(name, addr) netconn_gethostbyname_addrtype(name, addr, NETCONN_DNS_DEFAULT) +#else /* LWIP_IPV4 && LWIP_IPV6 */ +err_t netconn_gethostbyname(const char *name, ip_addr_t *addr); +#define netconn_gethostbyname_addrtype(name, addr, dns_addrtype) netconn_gethostbyname(name, addr) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#endif /* LWIP_DNS */ + +#define netconn_err(conn) ((conn)->last_err) +#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) + +/** Set the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_set_nonblocking(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0) +/** Get the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0) + +#if LWIP_IPV6 +/** @ingroup netconn_common + * TCP: Set the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) + */ +#define netconn_set_ipv6only(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_IPV6_V6ONLY; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_IPV6_V6ONLY; }} while(0) +/** @ingroup netconn_common + * TCP: Get the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) + */ +#define netconn_get_ipv6only(conn) (((conn)->flags & NETCONN_FLAG_IPV6_V6ONLY) != 0) +#endif /* LWIP_IPV6 */ + +#if LWIP_SO_SNDTIMEO +/** Set the send timeout in milliseconds */ +#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout)) +/** Get the send timeout in milliseconds */ +#define netconn_get_sendtimeout(conn) ((conn)->send_timeout) +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO +/** Set the receive timeout in milliseconds */ +#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout)) +/** Get the receive timeout in milliseconds */ +#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout) +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF +/** Set the receive buffer in bytes */ +#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize)) +/** Get the receive buffer in bytes */ +#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize) +#endif /* LWIP_SO_RCVBUF*/ + +#if LWIP_NETCONN_SEM_PER_THREAD +void netconn_thread_init(void); +void netconn_thread_cleanup(void); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define netconn_thread_init() +#define netconn_thread_cleanup() +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_API_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/FILES b/components/net/lwip-2.0.3/src/include/lwip/apps/FILES new file mode 100644 index 0000000000..adfc0f3345 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/FILES @@ -0,0 +1,2 @@ +This directory contains application headers. +Every application shall provide one api file APP.h and optionally one options file APP_opts.h diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/fs.h b/components/net/lwip-2.0.3/src/include/lwip/apps/fs.h new file mode 100644 index 0000000000..bb176fa010 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/fs.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_APPS_FS_H +#define LWIP_HDR_APPS_FS_H + +#include "httpd_opts.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FS_READ_EOF -1 +#define FS_READ_DELAYED -2 + +#if HTTPD_PRECALCULATED_CHECKSUM +struct fsdata_chksum { + u32_t offset; + u16_t chksum; + u16_t len; +}; +#endif /* HTTPD_PRECALCULATED_CHECKSUM */ + +#define FS_FILE_FLAGS_HEADER_INCLUDED 0x01 +#define FS_FILE_FLAGS_HEADER_PERSISTENT 0x02 + +struct fs_file { + const char *data; + int len; + int index; + void *pextension; +#if HTTPD_PRECALCULATED_CHECKSUM + const struct fsdata_chksum *chksum; + u16_t chksum_count; +#endif /* HTTPD_PRECALCULATED_CHECKSUM */ + u8_t flags; +#if LWIP_HTTPD_CUSTOM_FILES + u8_t is_custom_file; +#endif /* LWIP_HTTPD_CUSTOM_FILES */ +#if LWIP_HTTPD_FILE_STATE + void *state; +#endif /* LWIP_HTTPD_FILE_STATE */ +}; + +#if LWIP_HTTPD_FS_ASYNC_READ +typedef void (*fs_wait_cb)(void *arg); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + +err_t fs_open(struct fs_file *file, const char *name); +void fs_close(struct fs_file *file); +#if LWIP_HTTPD_DYNAMIC_FILE_READ +#if LWIP_HTTPD_FS_ASYNC_READ +int fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg); +#else /* LWIP_HTTPD_FS_ASYNC_READ */ +int fs_read(struct fs_file *file, char *buffer, int count); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ +#if LWIP_HTTPD_FS_ASYNC_READ +int fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +int fs_bytes_left(struct fs_file *file); + +#if LWIP_HTTPD_FILE_STATE +/** This user-defined function is called when a file is opened. */ +void *fs_state_init(struct fs_file *file, const char *name); +/** This user-defined function is called when a file is closed. */ +void fs_state_free(struct fs_file *file, void *state); +#endif /* #if LWIP_HTTPD_FILE_STATE */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_FS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/httpd.h b/components/net/lwip-2.0.3/src/include/lwip/apps/httpd.h new file mode 100644 index 0000000000..40f1811e57 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/httpd.h @@ -0,0 +1,236 @@ +/** + * @file + * HTTP server + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * This version of the file has been modified by Texas Instruments to offer + * simple server-side-include (SSI) and Common Gateway Interface (CGI) + * capability. + */ + +#ifndef LWIP_HDR_APPS_HTTPD_H +#define LWIP_HDR_APPS_HTTPD_H + +#include "httpd_opts.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_HTTPD_CGI + +/* + * Function pointer for a CGI script handler. + * + * This function is called each time the HTTPD server is asked for a file + * whose name was previously registered as a CGI function using a call to + * http_set_cgi_handler. The iIndex parameter provides the index of the + * CGI within the ppcURLs array passed to http_set_cgi_handler. Parameters + * pcParam and pcValue provide access to the parameters provided along with + * the URI. iNumParams provides a count of the entries in the pcParam and + * pcValue arrays. Each entry in the pcParam array contains the name of a + * parameter with the corresponding entry in the pcValue array containing the + * value for that parameter. Note that pcParam may contain multiple elements + * with the same name if, for example, a multi-selection list control is used + * in the form generating the data. + * + * The function should return a pointer to a character string which is the + * path and filename of the response that is to be sent to the connected + * browser, for example "/thanks.htm" or "/response/error.ssi". + * + * The maximum number of parameters that will be passed to this function via + * iNumParams is defined by LWIP_HTTPD_MAX_CGI_PARAMETERS. Any parameters in the incoming + * HTTP request above this number will be discarded. + * + * Requests intended for use by this CGI mechanism must be sent using the GET + * method (which encodes all parameters within the URI rather than in a block + * later in the request). Attempts to use the POST method will result in the + * request being ignored. + * + */ +typedef const char *(*tCGIHandler)(int iIndex, int iNumParams, char *pcParam[], + char *pcValue[]); + +/* + * Structure defining the base filename (URL) of a CGI and the associated + * function which is to be called when that URL is requested. + */ +typedef struct +{ + const char *pcCGIName; + tCGIHandler pfnCGIHandler; +} tCGI; + +void http_set_cgi_handlers(const tCGI *pCGIs, int iNumHandlers); + +#endif /* LWIP_HTTPD_CGI */ + +#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI + +#if LWIP_HTTPD_CGI_SSI +/** Define this generic CGI handler in your application. + * It is called once for every URI with parameters. + * The parameters can be stored to + */ +extern void httpd_cgi_handler(const char* uri, int iNumParams, char **pcParam, char **pcValue +#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE + , void *connection_state +#endif /* LWIP_HTTPD_FILE_STATE */ + ); +#endif /* LWIP_HTTPD_CGI_SSI */ + +#endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */ + +#if LWIP_HTTPD_SSI + +/* + * Function pointer for the SSI tag handler callback. + * + * This function will be called each time the HTTPD server detects a tag of the + * form in a .shtml, .ssi or .shtm file where "name" appears as + * one of the tags supplied to http_set_ssi_handler in the ppcTags array. The + * returned insert string, which will be appended after the the string + * "" in file sent back to the client,should be written to pointer + * pcInsert. iInsertLen contains the size of the buffer pointed to by + * pcInsert. The iIndex parameter provides the zero-based index of the tag as + * found in the ppcTags array and identifies the tag that is to be processed. + * + * The handler returns the number of characters written to pcInsert excluding + * any terminating NULL or a negative number to indicate a failure (tag not + * recognized, for example). + * + * Note that the behavior of this SSI mechanism is somewhat different from the + * "normal" SSI processing as found in, for example, the Apache web server. In + * this case, the inserted text is appended following the SSI tag rather than + * replacing the tag entirely. This allows for an implementation that does not + * require significant additional buffering of output data yet which will still + * offer usable SSI functionality. One downside to this approach is when + * attempting to use SSI within JavaScript. The SSI tag is structured to + * resemble an HTML comment but this syntax does not constitute a comment + * within JavaScript and, hence, leaving the tag in place will result in + * problems in these cases. To work around this, any SSI tag which needs to + * output JavaScript code must do so in an encapsulated way, sending the whole + * HTML section as a single include. + */ +typedef u16_t (*tSSIHandler)( +#if LWIP_HTTPD_SSI_RAW + const char* ssi_tag_name, +#else /* LWIP_HTTPD_SSI_RAW */ + int iIndex, +#endif /* LWIP_HTTPD_SSI_RAW */ + char *pcInsert, int iInsertLen +#if LWIP_HTTPD_SSI_MULTIPART + , u16_t current_tag_part, u16_t *next_tag_part +#endif /* LWIP_HTTPD_SSI_MULTIPART */ +#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE + , void *connection_state +#endif /* LWIP_HTTPD_FILE_STATE */ + ); + +/** Set the SSI handler function + * (if LWIP_HTTPD_SSI_RAW==1, only the first argument is used) + */ +void http_set_ssi_handler(tSSIHandler pfnSSIHandler, + const char **ppcTags, int iNumTags); + +/** For LWIP_HTTPD_SSI_RAW==1, return this to indicate the tag is unknown. + * In this case, the webserver writes a warning into the page. + * You can also just return 0 to write nothing for unknown tags. + */ +#define HTTPD_SSI_TAG_UNKNOWN 0xFFFF + +#endif /* LWIP_HTTPD_SSI */ + +#if LWIP_HTTPD_SUPPORT_POST + +/* These functions must be implemented by the application */ + +/** Called when a POST request has been received. The application can decide + * whether to accept it or not. + * + * @param connection Unique connection identifier, valid until httpd_post_end + * is called. + * @param uri The HTTP header URI receiving the POST request. + * @param http_request The raw HTTP request (the first packet, normally). + * @param http_request_len Size of 'http_request'. + * @param content_len Content-Length from HTTP header. + * @param response_uri Filename of response file, to be filled when denying the + * request + * @param response_uri_len Size of the 'response_uri' buffer. + * @param post_auto_wnd Set this to 0 to let the callback code handle window + * updates by calling 'httpd_post_data_recved' (to throttle rx speed) + * default is 1 (httpd handles window updates automatically) + * @return ERR_OK: Accept the POST request, data may be passed in + * another err_t: Deny the POST request, send back 'bad request'. + */ +err_t httpd_post_begin(void *connection, const char *uri, const char *http_request, + u16_t http_request_len, int content_len, char *response_uri, + u16_t response_uri_len, u8_t *post_auto_wnd); + +/** Called for each pbuf of data that has been received for a POST. + * ATTENTION: The application is responsible for freeing the pbufs passed in! + * + * @param connection Unique connection identifier. + * @param p Received data. + * @return ERR_OK: Data accepted. + * another err_t: Data denied, http_post_get_response_uri will be called. + */ +err_t httpd_post_receive_data(void *connection, struct pbuf *p); + +/** Called when all data is received or when the connection is closed. + * The application must return the filename/URI of a file to send in response + * to this POST request. If the response_uri buffer is untouched, a 404 + * response is returned. + * + * @param connection Unique connection identifier. + * @param response_uri Filename of response file, to be filled when denying the request + * @param response_uri_len Size of the 'response_uri' buffer. + */ +void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len); + +#if LWIP_HTTPD_POST_MANUAL_WND +void httpd_post_data_recved(void *connection, u16_t recved_len); +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + +#endif /* LWIP_HTTPD_SUPPORT_POST */ + +void httpd_init(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HTTPD_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/httpd_opts.h b/components/net/lwip-2.0.3/src/include/lwip/apps/httpd_opts.h new file mode 100644 index 0000000000..340db15f66 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/httpd_opts.h @@ -0,0 +1,323 @@ +/** + * @file + * HTTP server options list + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * This version of the file has been modified by Texas Instruments to offer + * simple server-side-include (SSI) and Common Gateway Interface (CGI) + * capability. + */ + +#ifndef LWIP_HDR_APPS_HTTPD_OPTS_H +#define LWIP_HDR_APPS_HTTPD_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup httpd_opts Options + * @ingroup httpd + * @{ + */ + +/** Set this to 1 to support CGI (old style) */ +#if !defined LWIP_HTTPD_CGI || defined __DOXYGEN__ +#define LWIP_HTTPD_CGI 0 +#endif + +/** Set this to 1 to support CGI (new style) */ +#if !defined LWIP_HTTPD_CGI_SSI || defined __DOXYGEN__ +#define LWIP_HTTPD_CGI_SSI 0 +#endif + +/** Set this to 1 to support SSI (Server-Side-Includes) */ +#if !defined LWIP_HTTPD_SSI || defined __DOXYGEN__ +#define LWIP_HTTPD_SSI 0 +#endif + +/** Set this to 1 to implement an SSI tag handler callback that gets a const char* + * to the tag (instead of an index into a pre-registered array of known tags) */ +#if !defined LWIP_HTTPD_SSI_RAW || defined __DOXYGEN__ +#define LWIP_HTTPD_SSI_RAW 0 +#endif + +/** Set this to 1 to support HTTP POST */ +#if !defined LWIP_HTTPD_SUPPORT_POST || defined __DOXYGEN__ +#define LWIP_HTTPD_SUPPORT_POST 0 +#endif + +/* The maximum number of parameters that the CGI handler can be sent. */ +#if !defined LWIP_HTTPD_MAX_CGI_PARAMETERS || defined __DOXYGEN__ +#define LWIP_HTTPD_MAX_CGI_PARAMETERS 16 +#endif + +/** LWIP_HTTPD_SSI_MULTIPART==1: SSI handler function is called with 2 more + * arguments indicating a counter for insert string that are too long to be + * inserted at once: the SSI handler function must then set 'next_tag_part' + * which will be passed back to it in the next call. */ +#if !defined LWIP_HTTPD_SSI_MULTIPART || defined __DOXYGEN__ +#define LWIP_HTTPD_SSI_MULTIPART 0 +#endif + +/* The maximum length of the string comprising the tag name */ +#if !defined LWIP_HTTPD_MAX_TAG_NAME_LEN || defined __DOXYGEN__ +#define LWIP_HTTPD_MAX_TAG_NAME_LEN 8 +#endif + +/* The maximum length of string that can be returned to replace any given tag */ +#if !defined LWIP_HTTPD_MAX_TAG_INSERT_LEN || defined __DOXYGEN__ +#define LWIP_HTTPD_MAX_TAG_INSERT_LEN 192 +#endif + +#if !defined LWIP_HTTPD_POST_MANUAL_WND || defined __DOXYGEN__ +#define LWIP_HTTPD_POST_MANUAL_WND 0 +#endif + +/** This string is passed in the HTTP header as "Server: " */ +#if !defined HTTPD_SERVER_AGENT || defined __DOXYGEN__ +#define HTTPD_SERVER_AGENT "lwIP/" LWIP_VERSION_STRING " (http://savannah.nongnu.org/projects/lwip)" +#endif + +/** Set this to 1 if you want to include code that creates HTTP headers + * at runtime. Default is off: HTTP headers are then created statically + * by the makefsdata tool. Static headers mean smaller code size, but + * the (readonly) fsdata will grow a bit as every file includes the HTTP + * header. */ +#if !defined LWIP_HTTPD_DYNAMIC_HEADERS || defined __DOXYGEN__ +#define LWIP_HTTPD_DYNAMIC_HEADERS 0 +#endif + +#if !defined HTTPD_DEBUG || defined __DOXYGEN__ +#define HTTPD_DEBUG LWIP_DBG_OFF +#endif + +/** Set this to 1 to use a memp pool for allocating + * struct http_state instead of the heap. + */ +#if !defined HTTPD_USE_MEM_POOL || defined __DOXYGEN__ +#define HTTPD_USE_MEM_POOL 0 +#endif + +/** The server port for HTTPD to use */ +#if !defined HTTPD_SERVER_PORT || defined __DOXYGEN__ +#define HTTPD_SERVER_PORT 80 +#endif + +/** Maximum retries before the connection is aborted/closed. + * - number of times pcb->poll is called -> default is 4*500ms = 2s; + * - reset when pcb->sent is called + */ +#if !defined HTTPD_MAX_RETRIES || defined __DOXYGEN__ +#define HTTPD_MAX_RETRIES 4 +#endif + +/** The poll delay is X*500ms */ +#if !defined HTTPD_POLL_INTERVAL || defined __DOXYGEN__ +#define HTTPD_POLL_INTERVAL 4 +#endif + +/** Priority for tcp pcbs created by HTTPD (very low by default). + * Lower priorities get killed first when running out of memory. + */ +#if !defined HTTPD_TCP_PRIO || defined __DOXYGEN__ +#define HTTPD_TCP_PRIO TCP_PRIO_MIN +#endif + +/** Set this to 1 to enable timing each file sent */ +#if !defined LWIP_HTTPD_TIMING || defined __DOXYGEN__ +#define LWIP_HTTPD_TIMING 0 +#endif +/** Set this to 1 to enable timing each file sent */ +#if !defined HTTPD_DEBUG_TIMING || defined __DOXYGEN__ +#define HTTPD_DEBUG_TIMING LWIP_DBG_OFF +#endif + +/** Set this to one to show error pages when parsing a request fails instead + of simply closing the connection. */ +#if !defined LWIP_HTTPD_SUPPORT_EXTSTATUS || defined __DOXYGEN__ +#define LWIP_HTTPD_SUPPORT_EXTSTATUS 0 +#endif + +/** Set this to 0 to drop support for HTTP/0.9 clients (to save some bytes) */ +#if !defined LWIP_HTTPD_SUPPORT_V09 || defined __DOXYGEN__ +#define LWIP_HTTPD_SUPPORT_V09 1 +#endif + +/** Set this to 1 to enable HTTP/1.1 persistent connections. + * ATTENTION: If the generated file system includes HTTP headers, these must + * include the "Connection: keep-alive" header (pass argument "-11" to makefsdata). + */ +#if !defined LWIP_HTTPD_SUPPORT_11_KEEPALIVE || defined __DOXYGEN__ +#define LWIP_HTTPD_SUPPORT_11_KEEPALIVE 0 +#endif + +/** Set this to 1 to support HTTP request coming in in multiple packets/pbufs */ +#if !defined LWIP_HTTPD_SUPPORT_REQUESTLIST || defined __DOXYGEN__ +#define LWIP_HTTPD_SUPPORT_REQUESTLIST 1 +#endif + +#if LWIP_HTTPD_SUPPORT_REQUESTLIST +/** Number of rx pbufs to enqueue to parse an incoming request (up to the first + newline) */ +#if !defined LWIP_HTTPD_REQ_QUEUELEN || defined __DOXYGEN__ +#define LWIP_HTTPD_REQ_QUEUELEN 5 +#endif + +/** Number of (TCP payload-) bytes (in pbufs) to enqueue to parse and incoming + request (up to the first double-newline) */ +#if !defined LWIP_HTTPD_REQ_BUFSIZE || defined __DOXYGEN__ +#define LWIP_HTTPD_REQ_BUFSIZE LWIP_HTTPD_MAX_REQ_LENGTH +#endif + +/** Defines the maximum length of a HTTP request line (up to the first CRLF, + copied from pbuf into this a global buffer when pbuf- or packet-queues + are received - otherwise the input pbuf is used directly) */ +#if !defined LWIP_HTTPD_MAX_REQ_LENGTH || defined __DOXYGEN__ +#define LWIP_HTTPD_MAX_REQ_LENGTH LWIP_MIN(1023, (LWIP_HTTPD_REQ_QUEUELEN * PBUF_POOL_BUFSIZE)) +#endif +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + +/** This is the size of a static buffer used when URIs end with '/'. + * In this buffer, the directory requested is concatenated with all the + * configured default file names. + * Set to 0 to disable checking default filenames on non-root directories. + */ +#if !defined LWIP_HTTPD_MAX_REQUEST_URI_LEN || defined __DOXYGEN__ +#define LWIP_HTTPD_MAX_REQUEST_URI_LEN 63 +#endif + +/** Maximum length of the filename to send as response to a POST request, + * filled in by the application when a POST is finished. + */ +#if !defined LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN || defined __DOXYGEN__ +#define LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN 63 +#endif + +/** Set this to 0 to not send the SSI tag (default is on, so the tag will + * be sent in the HTML page */ +#if !defined LWIP_HTTPD_SSI_INCLUDE_TAG || defined __DOXYGEN__ +#define LWIP_HTTPD_SSI_INCLUDE_TAG 1 +#endif + +/** Set this to 1 to call tcp_abort when tcp_close fails with memory error. + * This can be used to prevent consuming all memory in situations where the + * HTTP server has low priority compared to other communication. */ +#if !defined LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR || defined __DOXYGEN__ +#define LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR 0 +#endif + +/** Set this to 1 to kill the oldest connection when running out of + * memory for 'struct http_state' or 'struct http_ssi_state'. + * ATTENTION: This puts all connections on a linked list, so may be kind of slow. + */ +#if !defined LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED || defined __DOXYGEN__ +#define LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 0 +#endif + +/** Set this to 1 to send URIs without extension without headers + * (who uses this at all??) */ +#if !defined LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI || defined __DOXYGEN__ +#define LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI 0 +#endif + +/** Default: Tags are sent from struct http_state and are therefore volatile */ +#if !defined HTTP_IS_TAG_VOLATILE || defined __DOXYGEN__ +#define HTTP_IS_TAG_VOLATILE(ptr) TCP_WRITE_FLAG_COPY +#endif + +/* By default, the httpd is limited to send 2*pcb->mss to keep resource usage low + when http is not an important protocol in the device. */ +#if !defined HTTPD_LIMIT_SENDING_TO_2MSS || defined __DOXYGEN__ +#define HTTPD_LIMIT_SENDING_TO_2MSS 1 +#endif + +/* Define this to a function that returns the maximum amount of data to enqueue. + The function have this signature: u16_t fn(struct tcp_pcb* pcb); */ +#if !defined HTTPD_MAX_WRITE_LEN || defined __DOXYGEN__ +#if HTTPD_LIMIT_SENDING_TO_2MSS +#define HTTPD_MAX_WRITE_LEN(pcb) (2 * tcp_mss(pcb)) +#endif +#endif + +/*------------------- FS OPTIONS -------------------*/ + +/** Set this to 1 and provide the functions: + * - "int fs_open_custom(struct fs_file *file, const char *name)" + * Called first for every opened file to allow opening files + * that are not included in fsdata(_custom).c + * - "void fs_close_custom(struct fs_file *file)" + * Called to free resources allocated by fs_open_custom(). + */ +#if !defined LWIP_HTTPD_CUSTOM_FILES || defined __DOXYGEN__ +#define LWIP_HTTPD_CUSTOM_FILES 0 +#endif + +/** Set this to 1 to support fs_read() to dynamically read file data. + * Without this (default=off), only one-block files are supported, + * and the contents must be ready after fs_open(). + */ +#if !defined LWIP_HTTPD_DYNAMIC_FILE_READ || defined __DOXYGEN__ +#define LWIP_HTTPD_DYNAMIC_FILE_READ 0 +#endif + +/** Set this to 1 to include an application state argument per file + * that is opened. This allows to keep a state per connection/file. + */ +#if !defined LWIP_HTTPD_FILE_STATE || defined __DOXYGEN__ +#define LWIP_HTTPD_FILE_STATE 0 +#endif + +/** HTTPD_PRECALCULATED_CHECKSUM==1: include precompiled checksums for + * predefined (MSS-sized) chunks of the files to prevent having to calculate + * the checksums at runtime. */ +#if !defined HTTPD_PRECALCULATED_CHECKSUM || defined __DOXYGEN__ +#define HTTPD_PRECALCULATED_CHECKSUM 0 +#endif + +/** LWIP_HTTPD_FS_ASYNC_READ==1: support asynchronous read operations + * (fs_read_async returns FS_READ_DELAYED and calls a callback when finished). + */ +#if !defined LWIP_HTTPD_FS_ASYNC_READ || defined __DOXYGEN__ +#define LWIP_HTTPD_FS_ASYNC_READ 0 +#endif + +/** Set this to 1 to include "fsdata_custom.c" instead of "fsdata.c" for the + * file system (to prevent changing the file included in CVS) */ +#if !defined HTTPD_USE_CUSTOM_FSDATA || defined __DOXYGEN__ +#define HTTPD_USE_CUSTOM_FSDATA 0 +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_HTTPD_OPTS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/lwiperf.h b/components/net/lwip-2.0.3/src/include/lwip/apps/lwiperf.h new file mode 100644 index 0000000000..7dbebb0826 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/lwiperf.h @@ -0,0 +1,84 @@ +/** + * @file + * lwIP iPerf server implementation + */ + +/* + * Copyright (c) 2014 Simon Goldschmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_APPS_LWIPERF_H +#define LWIP_HDR_APPS_LWIPERF_H + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWIPERF_TCP_PORT_DEFAULT 5001 + +/** lwIPerf test results */ +enum lwiperf_report_type +{ + /** The server side test is done */ + LWIPERF_TCP_DONE_SERVER, + /** The client side test is done */ + LWIPERF_TCP_DONE_CLIENT, + /** Local error lead to test abort */ + LWIPERF_TCP_ABORTED_LOCAL, + /** Data check error lead to test abort */ + LWIPERF_TCP_ABORTED_LOCAL_DATAERROR, + /** Transmit error lead to test abort */ + LWIPERF_TCP_ABORTED_LOCAL_TXERROR, + /** Remote side aborted the test */ + LWIPERF_TCP_ABORTED_REMOTE +}; + +/** Prototype of a report function that is called when a session is finished. + This report function can show the test results. + @param report_type contains the test result */ +typedef void (*lwiperf_report_fn)(void *arg, enum lwiperf_report_type report_type, + const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port, + u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec); + + +void* lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port, + lwiperf_report_fn report_fn, void* report_arg); +void* lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg); +void lwiperf_abort(void* lwiperf_session); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_LWIPERF_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/mdns.h b/components/net/lwip-2.0.3/src/include/lwip/apps/mdns.h new file mode 100644 index 0000000000..d036816115 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/mdns.h @@ -0,0 +1,69 @@ +/** + * @file + * MDNS responder + */ + + /* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ +#ifndef LWIP_HDR_MDNS_H +#define LWIP_HDR_MDNS_H + +#include "lwip/apps/mdns_opts.h" +#include "lwip/netif.h" + +#if LWIP_MDNS_RESPONDER + +enum mdns_sd_proto { + DNSSD_PROTO_UDP = 0, + DNSSD_PROTO_TCP = 1 +}; + +#define MDNS_LABEL_MAXLEN 63 + +struct mdns_host; +struct mdns_service; + +/** Callback function to add text to a reply, called when generating the reply */ +typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_userdata); + +void mdns_resp_init(void); + +err_t mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl); +err_t mdns_resp_remove_netif(struct netif *netif); + +err_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_userdata); +err_t mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len); +void mdns_resp_netif_settings_changed(struct netif *netif); + +#endif /* LWIP_MDNS_RESPONDER */ + +#endif /* LWIP_HDR_MDNS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/mdns_opts.h b/components/net/lwip-2.0.3/src/include/lwip/apps/mdns_opts.h new file mode 100644 index 0000000000..bf186bcce1 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/mdns_opts.h @@ -0,0 +1,74 @@ +/** + * @file + * MDNS responder + */ + + /* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ + +#ifndef LWIP_HDR_APPS_MDNS_OPTS_H +#define LWIP_HDR_APPS_MDNS_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup mdns_opts Options + * @ingroup mdns + * @{ + */ + +/** + * LWIP_MDNS_RESPONDER==1: Turn on multicast DNS module. UDP must be available for MDNS + * transport. IGMP is needed for IPv4 multicast. + */ +#ifndef LWIP_MDNS_RESPONDER +#define LWIP_MDNS_RESPONDER 0 +#endif /* LWIP_MDNS_RESPONDER */ + +/** The maximum number of services per netif */ +#ifndef MDNS_MAX_SERVICES +#define MDNS_MAX_SERVICES 1 +#endif + +/** + * MDNS_DEBUG: Enable debugging for multicast DNS. + */ +#ifndef MDNS_DEBUG +#define MDNS_DEBUG LWIP_DBG_OFF +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_MDNS_OPTS_H */ + diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/mdns_priv.h b/components/net/lwip-2.0.3/src/include/lwip/apps/mdns_priv.h new file mode 100644 index 0000000000..8ee6db86af --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/mdns_priv.h @@ -0,0 +1,66 @@ +/** + * @file + * MDNS responder private definitions + */ + + /* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ +#ifndef LWIP_HDR_MDNS_PRIV_H +#define LWIP_HDR_MDNS_PRIV_H + +#include "lwip/apps/mdns_opts.h" +#include "lwip/pbuf.h" + +#if LWIP_MDNS_RESPONDER + +/* Domain struct and methods - visible for unit tests */ + +#define MDNS_DOMAIN_MAXLEN 256 +#define MDNS_READNAME_ERROR 0xFFFF + +struct mdns_domain { + /* Encoded domain name */ + u8_t name[MDNS_DOMAIN_MAXLEN]; + /* Total length of domain name, including zero */ + u16_t length; + /* Set if compression of this domain is not allowed */ + u8_t skip_compression; +}; + +err_t mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len); +u16_t mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain); +int mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b); +u16_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain); + +#endif /* LWIP_MDNS_RESPONDER */ + +#endif /* LWIP_HDR_MDNS_PRIV_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/mqtt.h b/components/net/lwip-2.0.3/src/include/lwip/apps/mqtt.h new file mode 100644 index 0000000000..34b230b888 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/mqtt.h @@ -0,0 +1,244 @@ +/** + * @file + * MQTT client + */ + +/* + * Copyright (c) 2016 Erik Andersson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Andersson + * + */ +#ifndef LWIP_HDR_APPS_MQTT_CLIENT_H +#define LWIP_HDR_APPS_MQTT_CLIENT_H + +#include "lwip/apps/mqtt_opts.h" +#include "lwip/err.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mqtt_client_t mqtt_client_t; + +/** @ingroup mqtt + * Default MQTT port */ +#define MQTT_PORT 1883 + +/*---------------------------------------------------------------------------------------------- */ +/* Connection with server */ + +/** + * @ingroup mqtt + * Client information and connection parameters */ +struct mqtt_connect_client_info_t { + /** Client identifier, must be set by caller */ + const char *client_id; + /** User name and password, set to NULL if not used */ + const char* client_user; + const char* client_pass; + /** keep alive time in seconds, 0 to disable keep alive functionality*/ + u16_t keep_alive; + /** will topic, set to NULL if will is not to be used, + will_msg, will_qos and will retain are then ignored */ + const char* will_topic; + const char* will_msg; + u8_t will_qos; + u8_t will_retain; +}; + +/** + * @ingroup mqtt + * Connection status codes */ +typedef enum +{ + MQTT_CONNECT_ACCEPTED = 0, + MQTT_CONNECT_REFUSED_PROTOCOL_VERSION = 1, + MQTT_CONNECT_REFUSED_IDENTIFIER = 2, + MQTT_CONNECT_REFUSED_SERVER = 3, + MQTT_CONNECT_REFUSED_USERNAME_PASS = 4, + MQTT_CONNECT_REFUSED_NOT_AUTHORIZED_ = 5, + MQTT_CONNECT_DISCONNECTED = 256, + MQTT_CONNECT_TIMEOUT = 257 +} mqtt_connection_status_t; + +/** + * @ingroup mqtt + * Function prototype for mqtt connection status callback. Called when + * client has connected to the server after initiating a mqtt connection attempt by + * calling mqtt_connect() or when connection is closed by server or an error + * + * @param client MQTT client itself + * @param arg Additional argument to pass to the callback function + * @param status Connect result code or disconnection notification @see mqtt_connection_status_t + * + */ +typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg, mqtt_connection_status_t status); + + +/** + * @ingroup mqtt + * Data callback flags */ +enum { + /** Flag set when last fragment of data arrives in data callback */ + MQTT_DATA_FLAG_LAST = 1 +}; + +/** + * @ingroup mqtt + * Function prototype for MQTT incoming publish data callback function. Called when data + * arrives to a subscribed topic @see mqtt_subscribe + * + * @param arg Additional argument to pass to the callback function + * @param data User data, pointed object, data may not be referenced after callback return, + NULL is passed when all publish data are delivered + * @param len Length of publish data fragment + * @param flags MQTT_DATA_FLAG_LAST set when this call contains the last part of data from publish message + * + */ +typedef void (*mqtt_incoming_data_cb_t)(void *arg, const u8_t *data, u16_t len, u8_t flags); + + +/** + * @ingroup mqtt + * Function prototype for MQTT incoming publish function. Called when an incoming publish + * arrives to a subscribed topic @see mqtt_subscribe + * + * @param arg Additional argument to pass to the callback function + * @param topic Zero terminated Topic text string, topic may not be referenced after callback return + * @param tot_len Total length of publish data, if set to 0 (no publish payload) data callback will not be invoked + */ +typedef void (*mqtt_incoming_publish_cb_t)(void *arg, const char *topic, u32_t tot_len); + + +/** + * @ingroup mqtt + * Function prototype for mqtt request callback. Called when a subscribe, unsubscribe + * or publish request has completed + * @param arg Pointer to user data supplied when invoking request + * @param err ERR_OK on success + * ERR_TIMEOUT if no response was received within timeout, + * ERR_ABRT if (un)subscribe was denied + */ +typedef void (*mqtt_request_cb_t)(void *arg, err_t err); + + +/** + * Pending request item, binds application callback to pending server requests + */ +struct mqtt_request_t +{ + /** Next item in list, NULL means this is the last in chain, + next pointing at itself means request is unallocated */ + struct mqtt_request_t *next; + /** Callback to upper layer */ + mqtt_request_cb_t cb; + void *arg; + /** MQTT packet identifier */ + u16_t pkt_id; + /** Expire time relative to element before this */ + u16_t timeout_diff; +}; + +/** Ring buffer */ +struct mqtt_ringbuf_t { + u16_t put; + u16_t get; + u8_t buf[MQTT_OUTPUT_RINGBUF_SIZE]; +}; + +/** MQTT client */ +struct mqtt_client_t +{ + /** Timers and timeouts */ + u16_t cyclic_tick; + u16_t keep_alive; + u16_t server_watchdog; + /** Packet identifier generator*/ + u16_t pkt_id_seq; + /** Packet identifier of pending incoming publish */ + u16_t inpub_pkt_id; + /** Connection state */ + u8_t conn_state; + struct tcp_pcb *conn; + /** Connection callback */ + void *connect_arg; + mqtt_connection_cb_t connect_cb; + /** Pending requests to server */ + struct mqtt_request_t *pend_req_queue; + struct mqtt_request_t req_list[MQTT_REQ_MAX_IN_FLIGHT]; + void *inpub_arg; + /** Incoming data callback */ + mqtt_incoming_data_cb_t data_cb; + mqtt_incoming_publish_cb_t pub_cb; + /** Input */ + u32_t msg_idx; + u8_t rx_buffer[MQTT_VAR_HEADER_BUFFER_LEN]; + /** Output ring-buffer */ + struct mqtt_ringbuf_t output; +}; + + +/** Connect to server */ +err_t mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ipaddr, u16_t port, mqtt_connection_cb_t cb, void *arg, + const struct mqtt_connect_client_info_t *client_info); + +/** Disconnect from server */ +void mqtt_disconnect(mqtt_client_t *client); + +/** Create new client */ +mqtt_client_t *mqtt_client_new(void); + +/** Check connection status */ +u8_t mqtt_client_is_connected(mqtt_client_t *client); + +/** Set callback to call for incoming publish */ +void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t, + mqtt_incoming_data_cb_t data_cb, void *arg); + +/** Common function for subscribe and unsubscribe */ +err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub); + +/** @ingroup mqtt + *Subscribe to topic */ +#define mqtt_subscribe(client, topic, qos, cb, arg) mqtt_sub_unsub(client, topic, qos, cb, arg, 1) +/** @ingroup mqtt + * Unsubscribe to topic */ +#define mqtt_unsubscribe(client, topic, cb, arg) mqtt_sub_unsub(client, topic, 0, cb, arg, 0) + + +/** Publish data to topic */ +err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, + mqtt_request_cb_t cb, void *arg); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_MQTT_CLIENT_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/mqtt_opts.h b/components/net/lwip-2.0.3/src/include/lwip/apps/mqtt_opts.h new file mode 100644 index 0000000000..ffefacd259 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/mqtt_opts.h @@ -0,0 +1,103 @@ +/** + * @file + * MQTT client options + */ + +/* + * Copyright (c) 2016 Erik Andersson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Andersson + * + */ +#ifndef LWIP_HDR_APPS_MQTT_OPTS_H +#define LWIP_HDR_APPS_MQTT_OPTS_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup mqtt_opts Options + * @ingroup mqtt + * @{ + */ + +/** + * Output ring-buffer size, must be able to fit largest outgoing publish message topic+payloads + */ +#ifndef MQTT_OUTPUT_RINGBUF_SIZE +#define MQTT_OUTPUT_RINGBUF_SIZE 256 +#endif + +/** + * Number of bytes in receive buffer, must be at least the size of the longest incoming topic + 8 + * If one wants to avoid fragmented incoming publish, set length to max incoming topic length + max payload length + 8 + */ +#ifndef MQTT_VAR_HEADER_BUFFER_LEN +#define MQTT_VAR_HEADER_BUFFER_LEN 128 +#endif + +/** + * Maximum number of pending subscribe, unsubscribe and publish requests to server . + */ +#ifndef MQTT_REQ_MAX_IN_FLIGHT +#define MQTT_REQ_MAX_IN_FLIGHT 4 +#endif + +/** + * Seconds between each cyclic timer call. + */ +#ifndef MQTT_CYCLIC_TIMER_INTERVAL +#define MQTT_CYCLIC_TIMER_INTERVAL 5 +#endif + +/** + * Publish, subscribe and unsubscribe request timeout in seconds. + */ +#ifndef MQTT_REQ_TIMEOUT +#define MQTT_REQ_TIMEOUT 30 +#endif + +/** + * Seconds for MQTT connect response timeout after sending connect request + */ +#ifndef MQTT_CONNECT_TIMOUT +#define MQTT_CONNECT_TIMOUT 100 +#endif + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_MQTT_OPTS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/netbiosns.h b/components/net/lwip-2.0.3/src/include/lwip/apps/netbiosns.h new file mode 100644 index 0000000000..c9f68d8d12 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/netbiosns.h @@ -0,0 +1,43 @@ +/** + * @file + * NETBIOS name service responder + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ +#ifndef LWIP_HDR_APPS_NETBIOS_H +#define LWIP_HDR_APPS_NETBIOS_H + +#include "lwip/apps/netbiosns_opts.h" + +void netbiosns_init(void); +#ifndef NETBIOS_LWIP_NAME +void netbiosns_set_name(const char* hostname); +#endif +void netbiosns_stop(void); + +#endif /* LWIP_HDR_APPS_NETBIOS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/netbiosns_opts.h b/components/net/lwip-2.0.3/src/include/lwip/apps/netbiosns_opts.h new file mode 100644 index 0000000000..0909ef7b94 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/netbiosns_opts.h @@ -0,0 +1,59 @@ +/** + * @file + * NETBIOS name service responder options + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ +#ifndef LWIP_HDR_APPS_NETBIOS_OPTS_H +#define LWIP_HDR_APPS_NETBIOS_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup netbiosns_opts Options + * @ingroup netbiosns + * @{ + */ + +/** NetBIOS name of lwip device + * This must be uppercase until NETBIOS_STRCMP() is defined to a string + * comparision function that is case insensitive. + * If you want to use the netif's hostname, use this (with LWIP_NETIF_HOSTNAME): + * (ip_current_netif() != NULL ? ip_current_netif()->hostname != NULL ? ip_current_netif()->hostname : "" : "") + * + * If this is not defined, netbiosns_set_name() can be called at runtime to change the name. + */ +#ifdef __DOXYGEN__ +#define NETBIOS_LWIP_NAME "NETBIOSLWIPDEV" +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_NETBIOS_OPTS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/snmp.h b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp.h new file mode 100644 index 0000000000..10e8ff434b --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp.h @@ -0,0 +1,128 @@ +/** + * @file + * SNMP server main API - start and basic configuration + */ + +/* + * Copyright (c) 2001, 2002 Leon Woestenberg + * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * Martin Hentschel + * + */ +#ifndef LWIP_HDR_APPS_SNMP_H +#define LWIP_HDR_APPS_SNMP_H + +#include "lwip/apps/snmp_opts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/err.h" +#include "lwip/apps/snmp_core.h" + +/** SNMP variable binding descriptor (publically needed for traps) */ +struct snmp_varbind +{ + /** pointer to next varbind, NULL for last in list */ + struct snmp_varbind *next; + /** pointer to previous varbind, NULL for first in list */ + struct snmp_varbind *prev; + + /** object identifier */ + struct snmp_obj_id oid; + + /** value ASN1 type */ + u8_t type; + /** object value length */ + u16_t value_len; + /** object value */ + void *value; +}; + +/** + * @ingroup snmp_core + * Agent setup, start listening to port 161. + */ +void snmp_init(void); +void snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs); + +void snmp_set_device_enterprise_oid(const struct snmp_obj_id* device_enterprise_oid); +const struct snmp_obj_id* snmp_get_device_enterprise_oid(void); + +void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); +void snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst); + +/** Generic trap: cold start */ +#define SNMP_GENTRAP_COLDSTART 0 +/** Generic trap: warm start */ +#define SNMP_GENTRAP_WARMSTART 1 +/** Generic trap: link down */ +#define SNMP_GENTRAP_LINKDOWN 2 +/** Generic trap: link up */ +#define SNMP_GENTRAP_LINKUP 3 +/** Generic trap: authentication failure */ +#define SNMP_GENTRAP_AUTH_FAILURE 4 +/** Generic trap: EGP neighbor lost */ +#define SNMP_GENTRAP_EGP_NEIGHBOR_LOSS 5 +/** Generic trap: enterprise specific */ +#define SNMP_GENTRAP_ENTERPRISE_SPECIFIC 6 + +err_t snmp_send_trap_generic(s32_t generic_trap); +err_t snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds); +err_t snmp_send_trap(const struct snmp_obj_id* oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds); + +#define SNMP_AUTH_TRAPS_DISABLED 0 +#define SNMP_AUTH_TRAPS_ENABLED 1 +void snmp_set_auth_traps_enabled(u8_t enable); +u8_t snmp_get_auth_traps_enabled(void); + +const char * snmp_get_community(void); +const char * snmp_get_community_write(void); +const char * snmp_get_community_trap(void); +void snmp_set_community(const char * const community); +void snmp_set_community_write(const char * const community); +void snmp_set_community_trap(const char * const community); + +void snmp_coldstart_trap(void); +void snmp_authfail_trap(void); + +typedef void (*snmp_write_callback_fct)(const u32_t* oid, u8_t oid_len, void* callback_arg); +void snmp_set_write_callback(snmp_write_callback_fct write_callback, void* callback_arg); + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNMP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_core.h b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_core.h new file mode 100644 index 0000000000..e781c532b3 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_core.h @@ -0,0 +1,364 @@ +/** + * @file + * SNMP core API for implementing MIBs + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel + */ + +#ifndef LWIP_HDR_APPS_SNMP_CORE_H +#define LWIP_HDR_APPS_SNMP_CORE_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* basic ASN1 defines */ +#define SNMP_ASN1_CLASS_UNIVERSAL 0x00 +#define SNMP_ASN1_CLASS_APPLICATION 0x40 +#define SNMP_ASN1_CLASS_CONTEXT 0x80 +#define SNMP_ASN1_CLASS_PRIVATE 0xC0 + +#define SNMP_ASN1_CONTENTTYPE_PRIMITIVE 0x00 +#define SNMP_ASN1_CONTENTTYPE_CONSTRUCTED 0x20 + +/* universal tags (from ASN.1 spec.) */ +#define SNMP_ASN1_UNIVERSAL_END_OF_CONTENT 0 +#define SNMP_ASN1_UNIVERSAL_INTEGER 2 +#define SNMP_ASN1_UNIVERSAL_OCTET_STRING 4 +#define SNMP_ASN1_UNIVERSAL_NULL 5 +#define SNMP_ASN1_UNIVERSAL_OBJECT_ID 6 +#define SNMP_ASN1_UNIVERSAL_SEQUENCE_OF 16 + +/* application specific (SNMP) tags (from SNMPv2-SMI) */ +#define SNMP_ASN1_APPLICATION_IPADDR 0 /* [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4)) */ +#define SNMP_ASN1_APPLICATION_COUNTER 1 /* [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) => u32_t */ +#define SNMP_ASN1_APPLICATION_GAUGE 2 /* [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) => u32_t */ +#define SNMP_ASN1_APPLICATION_TIMETICKS 3 /* [APPLICATION 3] IMPLICIT INTEGER (0..4294967295) => u32_t */ +#define SNMP_ASN1_APPLICATION_OPAQUE 4 /* [APPLICATION 4] IMPLICIT OCTET STRING */ +#define SNMP_ASN1_APPLICATION_COUNTER64 6 /* [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615) */ + +/* context specific (SNMP) tags (from RFC 1905) */ +#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE 1 + +/* full ASN1 type defines */ +#define SNMP_ASN1_TYPE_END_OF_CONTENT (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_END_OF_CONTENT) +#define SNMP_ASN1_TYPE_INTEGER (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_INTEGER) +#define SNMP_ASN1_TYPE_OCTET_STRING (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OCTET_STRING) +#define SNMP_ASN1_TYPE_NULL (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_NULL) +#define SNMP_ASN1_TYPE_OBJECT_ID (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OBJECT_ID) +#define SNMP_ASN1_TYPE_SEQUENCE (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_UNIVERSAL_SEQUENCE_OF) +#define SNMP_ASN1_TYPE_IPADDR (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_IPADDR) +#define SNMP_ASN1_TYPE_IPADDRESS SNMP_ASN1_TYPE_IPADDR +#define SNMP_ASN1_TYPE_COUNTER (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER) +#define SNMP_ASN1_TYPE_COUNTER32 SNMP_ASN1_TYPE_COUNTER +#define SNMP_ASN1_TYPE_GAUGE (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_GAUGE) +#define SNMP_ASN1_TYPE_GAUGE32 SNMP_ASN1_TYPE_GAUGE +#define SNMP_ASN1_TYPE_UNSIGNED32 SNMP_ASN1_TYPE_GAUGE +#define SNMP_ASN1_TYPE_TIMETICKS (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_TIMETICKS) +#define SNMP_ASN1_TYPE_OPAQUE (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_OPAQUE) +#define SNMP_ASN1_TYPE_COUNTER64 (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER64) + +#define SNMP_VARBIND_EXCEPTION_OFFSET 0xF0 +#define SNMP_VARBIND_EXCEPTION_MASK 0x0F + +/** error codes predefined by SNMP prot. */ +typedef enum { + SNMP_ERR_NOERROR = 0, +/* +outdated v1 error codes. do not use anmore! +#define SNMP_ERR_NOSUCHNAME 2 use SNMP_ERR_NOSUCHINSTANCE instead +#define SNMP_ERR_BADVALUE 3 use SNMP_ERR_WRONGTYPE,SNMP_ERR_WRONGLENGTH,SNMP_ERR_WRONGENCODING or SNMP_ERR_WRONGVALUE instead +#define SNMP_ERR_READONLY 4 use SNMP_ERR_NOTWRITABLE instead +*/ + SNMP_ERR_GENERROR = 5, + SNMP_ERR_NOACCESS = 6, + SNMP_ERR_WRONGTYPE = 7, + SNMP_ERR_WRONGLENGTH = 8, + SNMP_ERR_WRONGENCODING = 9, + SNMP_ERR_WRONGVALUE = 10, + SNMP_ERR_NOCREATION = 11, + SNMP_ERR_INCONSISTENTVALUE = 12, + SNMP_ERR_RESOURCEUNAVAILABLE = 13, + SNMP_ERR_COMMITFAILED = 14, + SNMP_ERR_UNDOFAILED = 15, + SNMP_ERR_NOTWRITABLE = 17, + SNMP_ERR_INCONSISTENTNAME = 18, + + SNMP_ERR_NOSUCHINSTANCE = SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE +} snmp_err_t; + +/** internal object identifier representation */ +struct snmp_obj_id +{ + u8_t len; + u32_t id[SNMP_MAX_OBJ_ID_LEN]; +}; + +struct snmp_obj_id_const_ref +{ + u8_t len; + const u32_t* id; +}; + +extern const struct snmp_obj_id_const_ref snmp_zero_dot_zero; /* administrative identifier from SNMPv2-SMI */ + +/** SNMP variant value, used as reference in struct snmp_node_instance and table implementation */ +union snmp_variant_value +{ + void* ptr; + const void* const_ptr; + u32_t u32; + s32_t s32; +}; + + +/** +SNMP MIB node types + tree node is the only node the stack can process in order to walk the tree, + all other nodes are assumed to be leaf nodes. + This cannot be an enum because users may want to define their own node types. +*/ +#define SNMP_NODE_TREE 0x00 +/* predefined leaf node types */ +#define SNMP_NODE_SCALAR 0x01 +#define SNMP_NODE_SCALAR_ARRAY 0x02 +#define SNMP_NODE_TABLE 0x03 +#define SNMP_NODE_THREADSYNC 0x04 + +/** node "base class" layout, the mandatory fields for a node */ +struct snmp_node +{ + /** one out of SNMP_NODE_TREE or any leaf node type (like SNMP_NODE_SCALAR) */ + u8_t node_type; + /** the number assigned to this node which used as part of the full OID */ + u32_t oid; +}; + +/** SNMP node instance access types */ +typedef enum { + SNMP_NODE_INSTANCE_ACCESS_READ = 1, + SNMP_NODE_INSTANCE_ACCESS_WRITE = 2, + SNMP_NODE_INSTANCE_READ_ONLY = SNMP_NODE_INSTANCE_ACCESS_READ, + SNMP_NODE_INSTANCE_READ_WRITE = (SNMP_NODE_INSTANCE_ACCESS_READ | SNMP_NODE_INSTANCE_ACCESS_WRITE), + SNMP_NODE_INSTANCE_WRITE_ONLY = SNMP_NODE_INSTANCE_ACCESS_WRITE, + SNMP_NODE_INSTANCE_NOT_ACCESSIBLE = 0 +} snmp_access_t; + +struct snmp_node_instance; + +typedef s16_t (*node_instance_get_value_method)(struct snmp_node_instance*, void*); +typedef snmp_err_t (*node_instance_set_test_method)(struct snmp_node_instance*, u16_t, void*); +typedef snmp_err_t (*node_instance_set_value_method)(struct snmp_node_instance*, u16_t, void*); +typedef void (*node_instance_release_method)(struct snmp_node_instance*); + +#define SNMP_GET_VALUE_RAW_DATA 0x8000 + +/** SNMP node instance */ +struct snmp_node_instance +{ + /** prefilled with the node, get_instance() is called on; may be changed by user to any value to pass an arbitrary node between calls to get_instance() and get_value/test_value/set_value */ + const struct snmp_node* node; + /** prefilled with the instance id requested; for get_instance() this is the exact oid requested; for get_next_instance() this is the relative starting point, stack expects relative oid of next node here */ + struct snmp_obj_id instance_oid; + + /** ASN type for this object (see snmp_asn1.h for definitions) */ + u8_t asn1_type; + /** one out of instance access types defined above (SNMP_NODE_INSTANCE_READ_ONLY,...) */ + snmp_access_t access; + + /** returns object value for the given object identifier. Return values <0 to indicate an error */ + node_instance_get_value_method get_value; + /** tests length and/or range BEFORE setting */ + node_instance_set_test_method set_test; + /** sets object value, only called when set_test() was successful */ + node_instance_set_value_method set_value; + /** called in any case when the instance is not required anymore by stack (useful for freeing memory allocated in get_instance/get_next_instance methods) */ + node_instance_release_method release_instance; + + /** reference to pass arbitrary value between calls to get_instance() and get_value/test_value/set_value */ + union snmp_variant_value reference; + /** see reference (if reference is a pointer, the length of underlying data may be stored here or anything else) */ + u32_t reference_len; +}; + + +/** SNMP tree node */ +struct snmp_tree_node +{ + /** inherited "base class" members */ + struct snmp_node node; + u16_t subnode_count; + const struct snmp_node* const *subnodes; +}; + +#define SNMP_CREATE_TREE_NODE(oid, subnodes) \ + {{ SNMP_NODE_TREE, (oid) }, \ + (u16_t)LWIP_ARRAYSIZE(subnodes), (subnodes) } + +#define SNMP_CREATE_EMPTY_TREE_NODE(oid) \ + {{ SNMP_NODE_TREE, (oid) }, \ + 0, NULL } + +/** SNMP leaf node */ +struct snmp_leaf_node +{ + /** inherited "base class" members */ + struct snmp_node node; + snmp_err_t (*get_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + snmp_err_t (*get_next_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +}; + +/** represents a single mib with its base oid and root node */ +struct snmp_mib +{ + const u32_t *base_oid; + u8_t base_oid_len; + const struct snmp_node *root_node; +}; + +#define SNMP_MIB_CREATE(oid_list, root_node) { (oid_list), (u8_t)LWIP_ARRAYSIZE(oid_list), root_node } + +/** OID range structure */ +struct snmp_oid_range +{ + u32_t min; + u32_t max; +}; + +/** checks if incoming OID length and values are in allowed ranges */ +u8_t snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len); + +typedef enum { + SNMP_NEXT_OID_STATUS_SUCCESS, + SNMP_NEXT_OID_STATUS_NO_MATCH, + SNMP_NEXT_OID_STATUS_BUF_TO_SMALL +} snmp_next_oid_status_t; + +/** state for next_oid_init / next_oid_check functions */ +struct snmp_next_oid_state +{ + const u32_t* start_oid; + u8_t start_oid_len; + + u32_t* next_oid; + u8_t next_oid_len; + u8_t next_oid_max_len; + + snmp_next_oid_status_t status; + void* reference; +}; + +void snmp_next_oid_init(struct snmp_next_oid_state *state, + const u32_t *start_oid, u8_t start_oid_len, + u32_t *next_oid_buf, u8_t next_oid_max_len); +u8_t snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len); +u8_t snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference); + +void snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); +void snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); +void snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); +void snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); +u8_t snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); +s8_t snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); + +#if LWIP_IPV4 +u8_t snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip); +void snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid); +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 +u8_t snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip); +void snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid); +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 || LWIP_IPV6 +u8_t snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid); +u8_t snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid); + +u8_t snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip); +u8_t snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port); +#endif /* LWIP_IPV4 || LWIP_IPV6 */ + +struct netif; +u8_t netif_to_num(const struct netif *netif); + +snmp_err_t snmp_set_test_ok(struct snmp_node_instance* instance, u16_t value_len, void* value); /* generic function which can be used if test is always successful */ + +err_t snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value); +err_t snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value); +u8_t snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count); +u8_t snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value); + +struct snmp_statistics +{ + u32_t inpkts; + u32_t outpkts; + u32_t inbadversions; + u32_t inbadcommunitynames; + u32_t inbadcommunityuses; + u32_t inasnparseerrs; + u32_t intoobigs; + u32_t innosuchnames; + u32_t inbadvalues; + u32_t inreadonlys; + u32_t ingenerrs; + u32_t intotalreqvars; + u32_t intotalsetvars; + u32_t ingetrequests; + u32_t ingetnexts; + u32_t insetrequests; + u32_t ingetresponses; + u32_t intraps; + u32_t outtoobigs; + u32_t outnosuchnames; + u32_t outbadvalues; + u32_t outgenerrs; + u32_t outgetrequests; + u32_t outgetnexts; + u32_t outsetrequests; + u32_t outgetresponses; + u32_t outtraps; +}; + +extern struct snmp_statistics snmp_stats; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_APPS_SNMP_CORE_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_mib2.h b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_mib2.h new file mode 100644 index 0000000000..2f4a68935e --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_mib2.h @@ -0,0 +1,78 @@ +/** + * @file + * SNMP MIB2 API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Dirk Ziegelmeier + * + */ +#ifndef LWIP_HDR_APPS_SNMP_MIB2_H +#define LWIP_HDR_APPS_SNMP_MIB2_H + +#include "lwip/apps/snmp_opts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ +#if SNMP_LWIP_MIB2 + +#include "lwip/apps/snmp_core.h" + +extern const struct snmp_mib mib2; + +#if SNMP_USE_NETCONN +#include "lwip/apps/snmp_threadsync.h" +void snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg); +extern struct snmp_threadsync_instance snmp_mib2_lwip_locks; +#endif + +#ifndef SNMP_SYSSERVICES +#define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) +#endif + +void snmp_mib2_set_sysdescr(const u8_t* str, const u16_t* len); /* read-only be defintion */ +void snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); +void snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen); +void snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); +void snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen); +void snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); +void snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen); + +#endif /* SNMP_LWIP_MIB2 */ +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNMP_MIB2_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_opts.h b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_opts.h new file mode 100644 index 0000000000..6c9ba7beb3 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_opts.h @@ -0,0 +1,293 @@ +/** + * @file + * SNMP server options list + */ + +/* + * Copyright (c) 2015 Dirk Ziegelmeier + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Dirk Ziegelmeier + * + */ +#ifndef LWIP_HDR_SNMP_OPTS_H +#define LWIP_HDR_SNMP_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup snmp_opts Options + * @ingroup snmp + * @{ + */ + +/** + * LWIP_SNMP==1: This enables the lwIP SNMP agent. UDP must be available + * for SNMP transport. + * If you want to use your own SNMP agent, leave this disabled. + * To integrate MIB2 of an external agent, you need to enable + * LWIP_MIB2_CALLBACKS and MIB2_STATS. This will give you the callbacks + * and statistics counters you need to get MIB2 working. + */ +#if !defined LWIP_SNMP || defined __DOXYGEN__ +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_USE_NETCONN: Use netconn API instead of raw API. + * Makes SNMP agent run in a worker thread, so blocking operations + * can be done in MIB calls. + */ +#if !defined SNMP_USE_NETCONN || defined __DOXYGEN__ +#define SNMP_USE_NETCONN 0 +#endif + +/** + * SNMP_USE_RAW: Use raw API. + * SNMP agent does not run in a worker thread, so blocking operations + * should not be done in MIB calls. + */ +#if !defined SNMP_USE_RAW || defined __DOXYGEN__ +#define SNMP_USE_RAW 1 +#endif + +#if SNMP_USE_NETCONN && SNMP_USE_RAW +#error SNMP stack can use only one of the APIs {raw, netconn} +#endif + +#if LWIP_SNMP && !SNMP_USE_NETCONN && !SNMP_USE_RAW +#error SNMP stack needs a receive API and UDP {raw, netconn} +#endif + +#if SNMP_USE_NETCONN +/** + * SNMP_STACK_SIZE: Stack size of SNMP netconn worker thread + */ +#if !defined SNMP_STACK_SIZE || defined __DOXYGEN__ +#define SNMP_STACK_SIZE DEFAULT_THREAD_STACKSIZE +#endif + +/** + * SNMP_THREAD_PRIO: SNMP netconn worker thread priority + */ +#if !defined SNMP_THREAD_PRIO || defined __DOXYGEN__ +#define SNMP_THREAD_PRIO DEFAULT_THREAD_PRIO +#endif +#endif /* SNMP_USE_NETCONN */ + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#if !defined SNMP_TRAP_DESTINATIONS || defined __DOXYGEN__ +#define SNMP_TRAP_DESTINATIONS 1 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#if !defined SNMP_SAFE_REQUESTS || defined __DOXYGEN__ +#define SNMP_SAFE_REQUESTS 1 +#endif + +/** + * The maximum length of strings used. + */ +#if !defined SNMP_MAX_OCTET_STRING_LEN || defined __DOXYGEN__ +#define SNMP_MAX_OCTET_STRING_LEN 127 +#endif + +/** + * The maximum number of Sub ID's inside an object identifier. + * Indirectly this also limits the maximum depth of SNMP tree. + */ +#if !defined SNMP_MAX_OBJ_ID_LEN || defined __DOXYGEN__ +#define SNMP_MAX_OBJ_ID_LEN 50 +#endif + +#if !defined SNMP_MAX_VALUE_SIZE || defined __DOXYGEN__ +/** + * The maximum size of a value. + */ +#define SNMP_MIN_VALUE_SIZE (2 * sizeof(u32_t*)) /* size required to store the basic types (8 bytes for counter64) */ +/** + * The minimum size of a value. + */ +#define SNMP_MAX_VALUE_SIZE LWIP_MAX(LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN), sizeof(u32_t)*(SNMP_MAX_OBJ_ID_LEN)), SNMP_MIN_VALUE_SIZE) +#endif + +/** + * The snmp read-access community. Used for write-access and traps, too + * unless SNMP_COMMUNITY_WRITE or SNMP_COMMUNITY_TRAP are enabled, respectively. + */ +#if !defined SNMP_COMMUNITY || defined __DOXYGEN__ +#define SNMP_COMMUNITY "public" +#endif + +/** + * The snmp write-access community. + * Set this community to "" in order to disallow any write access. + */ +#if !defined SNMP_COMMUNITY_WRITE || defined __DOXYGEN__ +#define SNMP_COMMUNITY_WRITE "private" +#endif + +/** + * The snmp community used for sending traps. + */ +#if !defined SNMP_COMMUNITY_TRAP || defined __DOXYGEN__ +#define SNMP_COMMUNITY_TRAP "public" +#endif + +/** + * The maximum length of community string. + * If community names shall be adjusted at runtime via snmp_set_community() calls, + * enter here the possible maximum length (+1 for terminating null character). + */ +#if !defined SNMP_MAX_COMMUNITY_STR_LEN || defined __DOXYGEN__ +#define SNMP_MAX_COMMUNITY_STR_LEN LWIP_MAX(LWIP_MAX(sizeof(SNMP_COMMUNITY), sizeof(SNMP_COMMUNITY_WRITE)), sizeof(SNMP_COMMUNITY_TRAP)) +#endif + +/** + * The OID identifiying the device. This may be the enterprise OID itself or any OID located below it in tree. + */ +#if !defined SNMP_DEVICE_ENTERPRISE_OID || defined __DOXYGEN__ +#define SNMP_LWIP_ENTERPRISE_OID 26381 +/** + * IANA assigned enterprise ID for lwIP is 26381 + * @see http://www.iana.org/assignments/enterprise-numbers + * + * @note this enterprise ID is assigned to the lwIP project, + * all object identifiers living under this ID are assigned + * by the lwIP maintainers! + * @note don't change this define, use snmp_set_device_enterprise_oid() + * + * If you need to create your own private MIB you'll need + * to apply for your own enterprise ID with IANA: + * http://www.iana.org/numbers.html + */ +#define SNMP_DEVICE_ENTERPRISE_OID {1, 3, 6, 1, 4, 1, SNMP_LWIP_ENTERPRISE_OID} +/** + * Length of SNMP_DEVICE_ENTERPRISE_OID + */ +#define SNMP_DEVICE_ENTERPRISE_OID_LEN 7 +#endif + +/** + * SNMP_DEBUG: Enable debugging for SNMP messages. + */ +#if !defined SNMP_DEBUG || defined __DOXYGEN__ +#define SNMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#if !defined SNMP_MIB_DEBUG || defined __DOXYGEN__ +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * Indicates if the MIB2 implementation of LWIP SNMP stack is used. + */ +#if !defined SNMP_LWIP_MIB2 || defined __DOXYGEN__ +#define SNMP_LWIP_MIB2 LWIP_SNMP +#endif + +/** + * Value return for sysDesc field of MIB2. + */ +#if !defined SNMP_LWIP_MIB2_SYSDESC || defined __DOXYGEN__ +#define SNMP_LWIP_MIB2_SYSDESC "lwIP" +#endif + +/** + * Value return for sysName field of MIB2. + * To make sysName field settable, call snmp_mib2_set_sysname() to provide the necessary buffers. + */ +#if !defined SNMP_LWIP_MIB2_SYSNAME || defined __DOXYGEN__ +#define SNMP_LWIP_MIB2_SYSNAME "FQDN-unk" +#endif + +/** + * Value return for sysContact field of MIB2. + * To make sysContact field settable, call snmp_mib2_set_syscontact() to provide the necessary buffers. + */ +#if !defined SNMP_LWIP_MIB2_SYSCONTACT || defined __DOXYGEN__ +#define SNMP_LWIP_MIB2_SYSCONTACT "" +#endif + +/** + * Value return for sysLocation field of MIB2. + * To make sysLocation field settable, call snmp_mib2_set_syslocation() to provide the necessary buffers. + */ +#if !defined SNMP_LWIP_MIB2_SYSLOCATION || defined __DOXYGEN__ +#define SNMP_LWIP_MIB2_SYSLOCATION "" +#endif + +/** + * This value is used to limit the repetitions processed in GetBulk requests (value == 0 means no limitation). + * This may be useful to limit the load for a single request. + * According to SNMP RFC 1905 it is allowed to not return all requested variables from a GetBulk request if system load would be too high. + * so the effect is that the client will do more requests to gather all data. + * For the stack this could be useful in case that SNMP processing is done in TCP/IP thread. In this situation a request with many + * repetitions could block the thread for a longer time. Setting limit here will keep the stack more responsive. + */ +#if !defined SNMP_LWIP_GETBULK_MAX_REPETITIONS || defined __DOXYGEN__ +#define SNMP_LWIP_GETBULK_MAX_REPETITIONS 0 +#endif + +/** + * @} + */ + +/* + ------------------------------------ + ---------- SNMPv3 options ---------- + ------------------------------------ +*/ + +/** + * LWIP_SNMP_V3==1: This enables EXPERIMENTAL SNMPv3 support. LWIP_SNMP must + * also be enabled. + * THIS IS UNDER DEVELOPMENT AND SHOULD NOT BE ENABLED IN PRODUCTS. + */ +#ifndef LWIP_SNMP_V3 +#define LWIP_SNMP_V3 0 +#endif + +#ifndef LWIP_SNMP_V3_CRYPTO +#define LWIP_SNMP_V3_CRYPTO LWIP_SNMP_V3 +#endif + +#ifndef LWIP_SNMP_V3_MBEDTLS +#define LWIP_SNMP_V3_MBEDTLS LWIP_SNMP_V3 +#endif + +#endif /* LWIP_HDR_SNMP_OPTS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_scalar.h b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_scalar.h new file mode 100644 index 0000000000..40a060c640 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_scalar.h @@ -0,0 +1,113 @@ +/** + * @file + * SNMP server MIB API to implement scalar nodes + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#ifndef LWIP_HDR_APPS_SNMP_SCALAR_H +#define LWIP_HDR_APPS_SNMP_SCALAR_H + +#include "lwip/apps/snmp_opts.h" +#include "lwip/apps/snmp_core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +/** basic scalar node */ +struct snmp_scalar_node +{ + /** inherited "base class" members */ + struct snmp_leaf_node node; + u8_t asn1_type; + snmp_access_t access; + node_instance_get_value_method get_value; + node_instance_set_test_method set_test; + node_instance_set_value_method set_value; +}; + + +snmp_err_t snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +snmp_err_t snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + +#define SNMP_SCALAR_CREATE_NODE(oid, access, asn1_type, get_value_method, set_test_method, set_value_method) \ + {{{ SNMP_NODE_SCALAR, (oid) }, \ + snmp_scalar_get_instance, \ + snmp_scalar_get_next_instance }, \ + (asn1_type), (access), (get_value_method), (set_test_method), (set_value_method) } + +#define SNMP_SCALAR_CREATE_NODE_READONLY(oid, asn1_type, get_value_method) SNMP_SCALAR_CREATE_NODE(oid, SNMP_NODE_INSTANCE_READ_ONLY, asn1_type, get_value_method, NULL, NULL) + +/** scalar array node - a tree node which contains scalars only as children */ +struct snmp_scalar_array_node_def +{ + u32_t oid; + u8_t asn1_type; + snmp_access_t access; +}; + +typedef s16_t (*snmp_scalar_array_get_value_method)(const struct snmp_scalar_array_node_def*, void*); +typedef snmp_err_t (*snmp_scalar_array_set_test_method)(const struct snmp_scalar_array_node_def*, u16_t, void*); +typedef snmp_err_t (*snmp_scalar_array_set_value_method)(const struct snmp_scalar_array_node_def*, u16_t, void*); + +/** basic scalar array node */ +struct snmp_scalar_array_node +{ + /** inherited "base class" members */ + struct snmp_leaf_node node; + u16_t array_node_count; + const struct snmp_scalar_array_node_def* array_nodes; + snmp_scalar_array_get_value_method get_value; + snmp_scalar_array_set_test_method set_test; + snmp_scalar_array_set_value_method set_value; +}; + +snmp_err_t snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +snmp_err_t snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + +#define SNMP_SCALAR_CREATE_ARRAY_NODE(oid, array_nodes, get_value_method, set_test_method, set_value_method) \ + {{{ SNMP_NODE_SCALAR_ARRAY, (oid) }, \ + snmp_scalar_array_get_instance, \ + snmp_scalar_array_get_next_instance }, \ + (u16_t)LWIP_ARRAYSIZE(array_nodes), (array_nodes), (get_value_method), (set_test_method), (set_value_method) } + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNMP_SCALAR_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_table.h b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_table.h new file mode 100644 index 0000000000..4988b51c25 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_table.h @@ -0,0 +1,134 @@ +/** + * @file + * SNMP server MIB API to implement table nodes + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#ifndef LWIP_HDR_APPS_SNMP_TABLE_H +#define LWIP_HDR_APPS_SNMP_TABLE_H + +#include "lwip/apps/snmp_opts.h" +#include "lwip/apps/snmp_core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +/** default (customizable) read/write table */ +struct snmp_table_col_def +{ + u32_t index; + u8_t asn1_type; + snmp_access_t access; +}; + +/** table node */ +struct snmp_table_node +{ + /** inherited "base class" members */ + struct snmp_leaf_node node; + u16_t column_count; + const struct snmp_table_col_def* columns; + snmp_err_t (*get_cell_instance)(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance); + snmp_err_t (*get_next_cell_instance)(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance); + /** returns object value for the given object identifier */ + node_instance_get_value_method get_value; + /** tests length and/or range BEFORE setting */ + node_instance_set_test_method set_test; + /** sets object value, only called when set_test() was successful */ + node_instance_set_value_method set_value; +}; + +snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + +#define SNMP_TABLE_CREATE(oid, columns, get_cell_instance_method, get_next_cell_instance_method, get_value_method, set_test_method, set_value_method) \ + {{{ SNMP_NODE_TABLE, (oid) }, \ + snmp_table_get_instance, \ + snmp_table_get_next_instance }, \ + (u16_t)LWIP_ARRAYSIZE(columns), (columns), \ + (get_cell_instance_method), (get_next_cell_instance_method), \ + (get_value_method), (set_test_method), (set_value_method)} + +#define SNMP_TABLE_GET_COLUMN_FROM_OID(oid) ((oid)[1]) /* first array value is (fixed) row entry (fixed to 1) and 2nd value is column, follow3ed by instance */ + + +/** simple read-only table */ +typedef enum { + SNMP_VARIANT_VALUE_TYPE_U32, + SNMP_VARIANT_VALUE_TYPE_S32, + SNMP_VARIANT_VALUE_TYPE_PTR, + SNMP_VARIANT_VALUE_TYPE_CONST_PTR +} snmp_table_column_data_type_t; + +struct snmp_table_simple_col_def +{ + u32_t index; + u8_t asn1_type; + snmp_table_column_data_type_t data_type; /* depending of what union member is used to store the value*/ +}; + +/** simple read-only table node */ +struct snmp_table_simple_node +{ + /* inherited "base class" members */ + struct snmp_leaf_node node; + u16_t column_count; + const struct snmp_table_simple_col_def* columns; + snmp_err_t (*get_cell_value)(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len); + snmp_err_t (*get_next_cell_instance_and_value)(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len); +}; + +snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + +#define SNMP_TABLE_CREATE_SIMPLE(oid, columns, get_cell_value_method, get_next_cell_instance_and_value_method) \ + {{{ SNMP_NODE_TABLE, (oid) }, \ + snmp_table_simple_get_instance, \ + snmp_table_simple_get_next_instance }, \ + (u16_t)LWIP_ARRAYSIZE(columns), (columns), (get_cell_value_method), (get_next_cell_instance_and_value_method) } + +s16_t snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value); +s16_t snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value); +s16_t snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value); + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNMP_TABLE_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_threadsync.h b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_threadsync.h new file mode 100644 index 0000000000..a25dbf2d0f --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/snmp_threadsync.h @@ -0,0 +1,114 @@ +/** + * @file + * SNMP server MIB API to implement thread synchronization + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Dirk Ziegelmeier + * + */ + +#ifndef LWIP_HDR_APPS_SNMP_THREADSYNC_H +#define LWIP_HDR_APPS_SNMP_THREADSYNC_H + +#include "lwip/apps/snmp_opts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp_core.h" +#include "lwip/sys.h" + +typedef void (*snmp_threadsync_called_fn)(void* arg); +typedef void (*snmp_threadsync_synchronizer_fn)(snmp_threadsync_called_fn fn, void* arg); + + +/** Thread sync runtime data. For internal usage only. */ +struct threadsync_data +{ + union { + snmp_err_t err; + s16_t s16; + } retval; + union { + const u32_t *root_oid; + void *value; + } arg1; + union { + u8_t root_oid_len; + u16_t len; + } arg2; + const struct snmp_threadsync_node *threadsync_node; + struct snmp_node_instance proxy_instance; +}; + +/** Thread sync instance. Needed EXCATLY once for every thread to be synced into. */ +struct snmp_threadsync_instance +{ + sys_sem_t sem; + sys_mutex_t sem_usage_mutex; + snmp_threadsync_synchronizer_fn sync_fn; + struct threadsync_data data; +}; + +/** SNMP thread sync proxy leaf node */ +struct snmp_threadsync_node +{ + /* inherited "base class" members */ + struct snmp_leaf_node node; + + const struct snmp_leaf_node *target; + struct snmp_threadsync_instance *instance; +}; + +snmp_err_t snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +snmp_err_t snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + +/** Create thread sync proxy node */ +#define SNMP_CREATE_THREAD_SYNC_NODE(oid, target_leaf_node, threadsync_instance) \ + {{{ SNMP_NODE_THREADSYNC, (oid) }, \ + snmp_threadsync_get_instance, \ + snmp_threadsync_get_next_instance }, \ + (target_leaf_node), \ + (threadsync_instance) } + +/** Create thread sync instance data */ +void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn); + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNMP_THREADSYNC_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/snmpv3.h b/components/net/lwip-2.0.3/src/include/lwip/apps/snmpv3.h new file mode 100644 index 0000000000..c99fed4e10 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/snmpv3.h @@ -0,0 +1,90 @@ +/** + * @file + * Additional SNMPv3 functionality RFC3414 and RFC3826. + */ + +/* + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Elias Oenal + */ + +#ifndef LWIP_HDR_APPS_SNMP_V3_H +#define LWIP_HDR_APPS_SNMP_V3_H + +#include "lwip/apps/snmp_opts.h" +#include "lwip/err.h" + +#if LWIP_SNMP && LWIP_SNMP_V3 + +#define SNMP_V3_AUTH_ALGO_INVAL 0 +#define SNMP_V3_AUTH_ALGO_MD5 1 +#define SNMP_V3_AUTH_ALGO_SHA 2 + +#define SNMP_V3_PRIV_ALGO_INVAL 0 +#define SNMP_V3_PRIV_ALGO_DES 1 +#define SNMP_V3_PRIV_ALGO_AES 2 + +#define SNMP_V3_PRIV_MODE_DECRYPT 0 +#define SNMP_V3_PRIV_MODE_ENCRYPT 1 + +/* + * The following callback functions must be implemented by the application. + * There is a dummy implementation in snmpv3_dummy.c. + */ + +void snmpv3_get_engine_id(const char **id, u8_t *len); +err_t snmpv3_set_engine_id(const char* id, u8_t len); + +u32_t snmpv3_get_engine_boots(void); +void snmpv3_set_engine_boots(u32_t boots); + +u32_t snmpv3_get_engine_time(void); +void snmpv3_reset_engine_time(void); + +err_t snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key); + +/* The following functions are provided by the SNMPv3 agent */ + +void snmpv3_engine_id_changed(void); + +void snmpv3_password_to_key_md5( + const u8_t *password, /* IN */ + u8_t passwordlen, /* IN */ + const u8_t *engineID, /* IN - pointer to snmpEngineID */ + u8_t engineLength, /* IN - length of snmpEngineID */ + u8_t *key); /* OUT - pointer to caller 16-octet buffer */ + +void snmpv3_password_to_key_sha( + const u8_t *password, /* IN */ + u8_t passwordlen, /* IN */ + const u8_t *engineID, /* IN - pointer to snmpEngineID */ + u8_t engineLength, /* IN - length of snmpEngineID */ + u8_t *key); /* OUT - pointer to caller 20-octet buffer */ + +#endif + +#endif /* LWIP_HDR_APPS_SNMP_V3_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/sntp.h b/components/net/lwip-2.0.3/src/include/lwip/apps/sntp.h new file mode 100644 index 0000000000..40df9cc590 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/sntp.h @@ -0,0 +1,76 @@ +/** + * @file + * SNTP client API + */ + +/* + * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Frédéric Bernon, Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_APPS_SNTP_H +#define LWIP_HDR_APPS_SNTP_H + +#include "lwip/apps/sntp_opts.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* SNTP operating modes: default is to poll using unicast. + The mode has to be set before calling sntp_init(). */ +#define SNTP_OPMODE_POLL 0 +#define SNTP_OPMODE_LISTENONLY 1 +void sntp_setoperatingmode(u8_t operating_mode); +u8_t sntp_getoperatingmode(void); + +void sntp_init(void); +void sntp_stop(void); +u8_t sntp_enabled(void); + +void sntp_setserver(u8_t idx, const ip_addr_t *addr); +const ip_addr_t* sntp_getserver(u8_t idx); + +#if SNTP_SERVER_DNS +void sntp_setservername(u8_t idx, char *server); +char *sntp_getservername(u8_t idx); +#endif /* SNTP_SERVER_DNS */ + +#if SNTP_GET_SERVERS_FROM_DHCP +void sntp_servermode_dhcp(int set_servers_from_dhcp); +#else /* SNTP_GET_SERVERS_FROM_DHCP */ +#define sntp_servermode_dhcp(x) +#endif /* SNTP_GET_SERVERS_FROM_DHCP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNTP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/sntp_opts.h b/components/net/lwip-2.0.3/src/include/lwip/apps/sntp_opts.h new file mode 100644 index 0000000000..f3651f90e6 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/sntp_opts.h @@ -0,0 +1,173 @@ +/** + * @file + * SNTP client options list + */ + +/* + * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Frédéric Bernon, Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_APPS_SNTP_OPTS_H +#define LWIP_HDR_APPS_SNTP_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup sntp_opts Options + * @ingroup sntp + * @{ + */ + +/** SNTP macro to change system time in seconds + * Define SNTP_SET_SYSTEM_TIME_US(sec, us) to set the time in microseconds instead of this one + * if you need the additional precision. + */ +#if !defined SNTP_SET_SYSTEM_TIME || defined __DOXYGEN__ +#define SNTP_SET_SYSTEM_TIME(sec) LWIP_UNUSED_ARG(sec) +#endif + +/** The maximum number of SNTP servers that can be set */ +#if !defined SNTP_MAX_SERVERS || defined __DOXYGEN__ +#define SNTP_MAX_SERVERS LWIP_DHCP_MAX_NTP_SERVERS +#endif + +/** Set this to 1 to implement the callback function called by dhcp when + * NTP servers are received. */ +#if !defined SNTP_GET_SERVERS_FROM_DHCP || defined __DOXYGEN__ +#define SNTP_GET_SERVERS_FROM_DHCP LWIP_DHCP_GET_NTP_SRV +#endif + +/** Set this to 1 to support DNS names (or IP address strings) to set sntp servers + * One server address/name can be defined as default if SNTP_SERVER_DNS == 1: + * \#define SNTP_SERVER_ADDRESS "pool.ntp.org" + */ +#if !defined SNTP_SERVER_DNS || defined __DOXYGEN__ +#define SNTP_SERVER_DNS 0 +#endif + +/** + * SNTP_DEBUG: Enable debugging for SNTP. + */ +#if !defined SNTP_DEBUG || defined __DOXYGEN__ +#define SNTP_DEBUG LWIP_DBG_OFF +#endif + +/** SNTP server port */ +#if !defined SNTP_PORT || defined __DOXYGEN__ +#define SNTP_PORT 123 +#endif + +/** Set this to 1 to allow config of SNTP server(s) by DNS name */ +#if !defined SNTP_SERVER_DNS || defined __DOXYGEN__ +#define SNTP_SERVER_DNS 0 +#endif + +/** Sanity check: + * Define this to + * - 0 to turn off sanity checks (default; smaller code) + * - >= 1 to check address and port of the response packet to ensure the + * response comes from the server we sent the request to. + * - >= 2 to check returned Originate Timestamp against Transmit Timestamp + * sent to the server (to ensure response to older request). + * - >= 3 @todo: discard reply if any of the LI, Stratum, or Transmit Timestamp + * fields is 0 or the Mode field is not 4 (unicast) or 5 (broadcast). + * - >= 4 @todo: to check that the Root Delay and Root Dispersion fields are each + * greater than or equal to 0 and less than infinity, where infinity is + * currently a cozy number like one second. This check avoids using a + * server whose synchronization source has expired for a very long time. + */ +#if !defined SNTP_CHECK_RESPONSE || defined __DOXYGEN__ +#define SNTP_CHECK_RESPONSE 0 +#endif + +/** According to the RFC, this shall be a random delay + * between 1 and 5 minutes (in milliseconds) to prevent load peaks. + * This can be defined to a random generation function, + * which must return the delay in milliseconds as u32_t. + * Turned off by default. + */ +#if !defined SNTP_STARTUP_DELAY || defined __DOXYGEN__ +#define SNTP_STARTUP_DELAY 0 +#endif + +/** If you want the startup delay to be a function, define this + * to a function (including the brackets) and define SNTP_STARTUP_DELAY to 1. + */ +#if !defined SNTP_STARTUP_DELAY_FUNC || defined __DOXYGEN__ +#define SNTP_STARTUP_DELAY_FUNC SNTP_STARTUP_DELAY +#endif + +/** SNTP receive timeout - in milliseconds + * Also used as retry timeout - this shouldn't be too low. + * Default is 3 seconds. + */ +#if !defined SNTP_RECV_TIMEOUT || defined __DOXYGEN__ +#define SNTP_RECV_TIMEOUT 3000 +#endif + +/** SNTP update delay - in milliseconds + * Default is 1 hour. Must not be beolw 15 seconds by specification (i.e. 15000) + */ +#if !defined SNTP_UPDATE_DELAY || defined __DOXYGEN__ +#define SNTP_UPDATE_DELAY 3600000 +#endif + +/** SNTP macro to get system time, used with SNTP_CHECK_RESPONSE >= 2 + * to send in request and compare in response. + */ +#if !defined SNTP_GET_SYSTEM_TIME || defined __DOXYGEN__ +#define SNTP_GET_SYSTEM_TIME(sec, us) do { (sec) = 0; (us) = 0; } while(0) +#endif + +/** Default retry timeout (in milliseconds) if the response + * received is invalid. + * This is doubled with each retry until SNTP_RETRY_TIMEOUT_MAX is reached. + */ +#if !defined SNTP_RETRY_TIMEOUT || defined __DOXYGEN__ +#define SNTP_RETRY_TIMEOUT SNTP_RECV_TIMEOUT +#endif + +/** Maximum retry timeout (in milliseconds). */ +#if !defined SNTP_RETRY_TIMEOUT_MAX || defined __DOXYGEN__ +#define SNTP_RETRY_TIMEOUT_MAX (SNTP_RETRY_TIMEOUT * 10) +#endif + +/** Increase retry timeout with every retry sent + * Default is on to conform to RFC. + */ +#if !defined SNTP_RETRY_TIMEOUT_EXP || defined __DOXYGEN__ +#define SNTP_RETRY_TIMEOUT_EXP 1 +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_SNTP_OPTS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/tftp_opts.h b/components/net/lwip-2.0.3/src/include/lwip/apps/tftp_opts.h new file mode 100644 index 0000000000..6968a803b4 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/tftp_opts.h @@ -0,0 +1,105 @@ +/****************************************************************//** + * + * @file tftp_opts.h + * + * @author Logan Gunthorpe + * + * @brief Trivial File Transfer Protocol (RFC 1350) implementation options + * + * Copyright (c) Deltatee Enterprises Ltd. 2013 + * All rights reserved. + * + ********************************************************************/ + +/* + * Redistribution and use in source and binary forms, with or without + * modification,are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Logan Gunthorpe + * + */ + +#ifndef LWIP_HDR_APPS_TFTP_OPTS_H +#define LWIP_HDR_APPS_TFTP_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup tftp_opts Options + * @ingroup tftp + * @{ + */ + +/** + * Enable TFTP debug messages + */ +#if !defined TFTP_DEBUG || defined __DOXYGEN__ +#define TFTP_DEBUG LWIP_DBG_ON +#endif + +/** + * TFTP server port + */ +#if !defined TFTP_PORT || defined __DOXYGEN__ +#define TFTP_PORT 69 +#endif + +/** + * TFTP timeout + */ +#if !defined TFTP_TIMEOUT_MSECS || defined __DOXYGEN__ +#define TFTP_TIMEOUT_MSECS 10000 +#endif + +/** + * Max. number of retries when a file is read from server + */ +#if !defined TFTP_MAX_RETRIES || defined __DOXYGEN__ +#define TFTP_MAX_RETRIES 5 +#endif + +/** + * TFTP timer cyclic interval + */ +#if !defined TFTP_TIMER_MSECS || defined __DOXYGEN__ +#define TFTP_TIMER_MSECS 50 +#endif + +/** + * Max. length of TFTP filename + */ +#if !defined TFTP_MAX_FILENAME_LEN || defined __DOXYGEN__ +#define TFTP_MAX_FILENAME_LEN 20 +#endif + +/** + * Max. length of TFTP mode + */ +#if !defined TFTP_MAX_MODE_LEN || defined __DOXYGEN__ +#define TFTP_MAX_MODE_LEN 7 +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_TFTP_OPTS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/apps/tftp_server.h b/components/net/lwip-2.0.3/src/include/lwip/apps/tftp_server.h new file mode 100644 index 0000000000..3fbe701e0a --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/apps/tftp_server.h @@ -0,0 +1,94 @@ +/****************************************************************//** + * + * @file tftp_server.h + * + * @author Logan Gunthorpe + * + * @brief Trivial File Transfer Protocol (RFC 1350) + * + * Copyright (c) Deltatee Enterprises Ltd. 2013 + * All rights reserved. + * + ********************************************************************/ + +/* + * Redistribution and use in source and binary forms, with or without + * modification,are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Logan Gunthorpe + * + */ + +#ifndef LWIP_HDR_APPS_TFTP_SERVER_H +#define LWIP_HDR_APPS_TFTP_SERVER_H + +#include "lwip/apps/tftp_opts.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @ingroup tftp + * TFTP context containing callback functions for TFTP transfers + */ +struct tftp_context { + /** + * Open file for read/write. + * @param fname Filename + * @param mode Mode string from TFTP RFC 1350 (netascii, octet, mail) + * @param write Flag indicating read (0) or write (!= 0) access + * @returns File handle supplied to other functions + */ + void* (*open)(const char* fname, const char* mode, u8_t write); + /** + * Close file handle + * @param handle File handle returned by open() + */ + void (*close)(void* handle); + /** + * Read from file + * @param handle File handle returned by open() + * @param buf Target buffer to copy read data to + * @param bytes Number of bytes to copy to buf + * @returns >= 0: Success; < 0: Error + */ + int (*read)(void* handle, void* buf, int bytes); + /** + * Write to file + * @param handle File handle returned by open() + * @param pbuf PBUF adjusted such that payload pointer points + * to the beginning of write data. In other words, + * TFTP headers are stripped off. + * @returns >= 0: Success; < 0: Error + */ + int (*write)(void* handle, struct pbuf* p); +}; + +err_t tftp_init(const struct tftp_context* ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_TFTP_SERVER_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/arch.h b/components/net/lwip-2.0.3/src/include/lwip/arch.h new file mode 100644 index 0000000000..55714e1132 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/arch.h @@ -0,0 +1,319 @@ +/** + * @file + * Support for different processor and compiler architectures + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ARCH_H +#define LWIP_HDR_ARCH_H + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#include "arch/cc.h" + +/** + * @defgroup compiler_abstraction Compiler/platform abstraction + * @ingroup sys_layer + * All defines related to this section must not be placed in lwipopts.h, + * but in arch/cc.h! + * These options cannot be \#defined in lwipopts.h since they are not options + * of lwIP itself, but options of the lwIP port to your system. + * @{ + */ + +/** Define the byte order of the system. + * Needed for conversion of network data to host byte order. + * Allowed values: LITTLE_ENDIAN and BIG_ENDIAN + */ +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +/** Define random number generator function of your system */ +#ifdef __DOXYGEN__ +#define LWIP_RAND() ((u32_t)rand()) +#endif + +/** Platform specific diagnostic output.\n + * Note the default implementation pulls in printf, which may + * in turn pull in a lot of standard libary code. In resource-constrained + * systems, this should be defined to something less resource-consuming. + */ +#ifndef LWIP_PLATFORM_DIAG +#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) +#include +#include +#endif + +/** Platform specific assertion handling.\n + * Note the default implementation pulls in printf, fflush and abort, which may + * in turn pull in a lot of standard libary code. In resource-constrained + * systems, this should be defined to something less resource-consuming. + */ +#ifndef LWIP_PLATFORM_ASSERT +#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \ + x, __LINE__, __FILE__); fflush(NULL); abort();} while(0) +#include +#include +#endif + +/** Define this to 1 in arch/cc.h of your port if you do not want to + * include stddef.h header to get size_t. You need to typedef size_t + * by yourself in this case. + */ +#ifndef LWIP_NO_STDDEF_H +#define LWIP_NO_STDDEF_H 0 +#endif + +#if !LWIP_NO_STDDEF_H +#include /* for size_t */ +#endif + +/** Define this to 1 in arch/cc.h of your port if your compiler does not provide + * the stdint.h header. You need to typedef the generic types listed in + * lwip/arch.h yourself in this case (u8_t, u16_t...). + */ +#ifndef LWIP_NO_STDINT_H +#define LWIP_NO_STDINT_H 0 +#endif + +/* Define generic types used in lwIP */ +#if !LWIP_NO_STDINT_H +#include +typedef uint8_t u8_t; +typedef int8_t s8_t; +typedef uint16_t u16_t; +typedef int16_t s16_t; +typedef uint32_t u32_t; +typedef int32_t s32_t; +typedef uintptr_t mem_ptr_t; +#endif + +/** Define this to 1 in arch/cc.h of your port if your compiler does not provide + * the inttypes.h header. You need to define the format strings listed in + * lwip/arch.h yourself in this case (X8_F, U16_F...). + */ +#ifndef LWIP_NO_INTTYPES_H +#define LWIP_NO_INTTYPES_H 0 +#endif + +/* Define (sn)printf formatters for these lwIP types */ +#if !LWIP_NO_INTTYPES_H +#include +#ifndef X8_F +#define X8_F "02" PRIx8 +#endif +#ifndef U16_F +#define U16_F PRIu16 +#endif +#ifndef S16_F +#define S16_F PRId16 +#endif +#ifndef X16_F +#define X16_F PRIx16 +#endif +#ifndef U32_F +#define U32_F PRIu32 +#endif +#ifndef S32_F +#define S32_F PRId32 +#endif +#ifndef X32_F +#define X32_F PRIx32 +#endif +#ifndef SZT_F +#define SZT_F PRIuPTR +#endif +#endif + +/** Define this to 1 in arch/cc.h of your port if your compiler does not provide + * the limits.h header. You need to define the type limits yourself in this case + * (e.g. INT_MAX). + */ +#ifndef LWIP_NO_LIMITS_H +#define LWIP_NO_LIMITS_H 0 +#endif + +/* Include limits.h? */ +#if !LWIP_NO_LIMITS_H +#include +#endif + +/** C++ const_cast(val) equivalent to remove constness from a value (GCC -Wcast-qual) */ +#ifndef LWIP_CONST_CAST +#define LWIP_CONST_CAST(target_type, val) ((target_type)((ptrdiff_t)val)) +#endif + +/** Get rid of alignment cast warnings (GCC -Wcast-align) */ +#ifndef LWIP_ALIGNMENT_CAST +#define LWIP_ALIGNMENT_CAST(target_type, val) LWIP_CONST_CAST(target_type, val) +#endif + +/** Get rid of warnings related to pointer-to-numeric and vice-versa casts, + * e.g. "conversion from 'u8_t' to 'void *' of greater size" + */ +#ifndef LWIP_PTR_NUMERIC_CAST +#define LWIP_PTR_NUMERIC_CAST(target_type, val) LWIP_CONST_CAST(target_type, val) +#endif + +/** Allocates a memory buffer of specified size that is of sufficient size to align + * its start address using LWIP_MEM_ALIGN. + * You can declare your own version here e.g. to enforce alignment without adding + * trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement + * requirements.\n + * e.g. if you use gcc and need 32 bit alignment:\n + * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))\n + * or more portable:\n + * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)] + */ +#ifndef LWIP_DECLARE_MEMORY_ALIGNED +#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)] +#endif + +/** Calculate memory size for an aligned buffer - returns the next highest + * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and + * LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4). + */ +#ifndef LWIP_MEM_ALIGN_SIZE +#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1U) & ~(MEM_ALIGNMENT-1U)) +#endif + +/** Calculate safe memory size for an aligned buffer when using an unaligned + * type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the + * start (e.g. if buffer is u8_t[] and actual data will be u32_t*) + */ +#ifndef LWIP_MEM_ALIGN_BUFFER +#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1U)) +#endif + +/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT + * so that ADDR % MEM_ALIGNMENT == 0 + */ +#ifndef LWIP_MEM_ALIGN +#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** Packed structs support. + * Placed BEFORE declaration of a packed struct.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_BEGIN +#define PACK_STRUCT_BEGIN +#endif /* PACK_STRUCT_BEGIN */ + +/** Packed structs support. + * Placed AFTER declaration of a packed struct.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_END +#define PACK_STRUCT_END +#endif /* PACK_STRUCT_END */ + +/** Packed structs support. + * Placed between end of declaration of a packed struct and trailing semicolon.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_STRUCT +#if defined(__GNUC__) || defined(__clang__) +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#else +#define PACK_STRUCT_STRUCT +#endif +#endif /* PACK_STRUCT_STRUCT */ + +/** Packed structs support. + * Wraps u32_t and u16_t members.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_FIELD +#define PACK_STRUCT_FIELD(x) x +#endif /* PACK_STRUCT_FIELD */ + +/** Packed structs support. + * Wraps u8_t members, where some compilers warn that packing is not necessary.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_FLD_8 +#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x) +#endif /* PACK_STRUCT_FLD_8 */ + +/** Packed structs support. + * Wraps members that are packed structs themselves, where some compilers warn that packing is not necessary.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_FLD_S +#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x) +#endif /* PACK_STRUCT_FLD_S */ + +/** Packed structs support using \#include files before and after struct to be packed.\n + * The file included BEFORE the struct is "arch/bpstruct.h".\n + * The file included AFTER the struct is "arch/epstruct.h".\n + * This can be used to implement struct packing on MS Visual C compilers, see + * the Win32 port in the lwIP contrib repository for reference. + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifdef __DOXYGEN__ +#define PACK_STRUCT_USE_INCLUDES +#endif + +/** Eliminates compiler warning about unused arguments (GCC -Wextra -Wunused). */ +#ifndef LWIP_UNUSED_ARG +#define LWIP_UNUSED_ARG(x) (void)x +#endif /* LWIP_UNUSED_ARG */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ARCH_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/autoip.h b/components/net/lwip-2.0.3/src/include/lwip/autoip.h new file mode 100644 index 0000000000..1d85bccff8 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/autoip.h @@ -0,0 +1,99 @@ +/** + * @file + * + * AutoIP Automatic LinkLocal IP Configuration + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + */ + +#ifndef LWIP_HDR_AUTOIP_H +#define LWIP_HDR_AUTOIP_H + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +/* #include "lwip/udp.h" */ +#include "lwip/etharp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** AutoIP Timing */ +#define AUTOIP_TMR_INTERVAL 100 +#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) + +/** AutoIP state information per netif */ +struct autoip +{ + /** the currently selected, probed, announced or used LL IP-Address */ + ip4_addr_t llipaddr; + /** current AutoIP state machine state */ + u8_t state; + /** sent number of probes or announces, dependent on state */ + u8_t sent_num; + /** ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ + u16_t ttw; + /** ticks until a conflict can be solved by defending */ + u8_t lastconflict; + /** total number of probed/used Link Local IP-Addresses */ + u8_t tried_llipaddr; +}; + + +void autoip_set_struct(struct netif *netif, struct autoip *autoip); +/** Remove a struct autoip previously set to the netif using autoip_set_struct() */ +#define autoip_remove_struct(netif) do { (netif)->autoip = NULL; } while (0) +err_t autoip_start(struct netif *netif); +err_t autoip_stop(struct netif *netif); +void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); +void autoip_tmr(void); +void autoip_network_changed(struct netif *netif); +u8_t autoip_supplied_address(const struct netif *netif); + +/* for lwIP internal use by ip4.c */ +u8_t autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr); + +#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 && LWIP_AUTOIP */ + +#endif /* LWIP_HDR_AUTOIP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/debug.h b/components/net/lwip-2.0.3/src/include/lwip/debug.h new file mode 100644 index 0000000000..a142f1cff3 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/debug.h @@ -0,0 +1,167 @@ +/** + * @file + * Debug messages infrastructure + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_DEBUG_H +#define LWIP_HDR_DEBUG_H + +#include "lwip/arch.h" +#include "lwip/opt.h" + +/** + * @defgroup debugging_levels LWIP_DBG_MIN_LEVEL and LWIP_DBG_TYPES_ON values + * @ingroup lwip_opts_debugmsg + * @{ + */ + +/** @name Debug level (LWIP_DBG_MIN_LEVEL) + * @{ + */ +/** Debug level: ALL messages*/ +#define LWIP_DBG_LEVEL_ALL 0x00 +/** Debug level: Warnings. bad checksums, dropped packets, ... */ +#define LWIP_DBG_LEVEL_WARNING 0x01 +/** Debug level: Serious. memory allocation failures, ... */ +#define LWIP_DBG_LEVEL_SERIOUS 0x02 +/** Debug level: Severe */ +#define LWIP_DBG_LEVEL_SEVERE 0x03 +/** + * @} + */ + +#define LWIP_DBG_MASK_LEVEL 0x03 +/* compatibility define only */ +#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL + +/** @name Enable/disable debug messages completely (LWIP_DBG_TYPES_ON) + * @{ + */ +/** flag for LWIP_DEBUGF to enable that debug message */ +#define LWIP_DBG_ON 0x80U +/** flag for LWIP_DEBUGF to disable that debug message */ +#define LWIP_DBG_OFF 0x00U +/** + * @} + */ + +/** @name Debug message types (LWIP_DBG_TYPES_ON) + * @{ + */ +/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ +#define LWIP_DBG_TRACE 0x40U +/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ +#define LWIP_DBG_STATE 0x20U +/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ +#define LWIP_DBG_FRESH 0x10U +/** flag for LWIP_DEBUGF to halt after printing this debug message */ +#define LWIP_DBG_HALT 0x08U +/** + * @} + */ + +/** + * @} + */ + +/** + * @defgroup lwip_assertions Assertion handling + * @ingroup lwip_opts_debug + * @{ + */ +/** + * LWIP_NOASSERT: Disable LWIP_ASSERT checks: + * To disable assertions define LWIP_NOASSERT in arch/cc.h. + */ +#ifdef __DOXYGEN__ +#define LWIP_NOASSERT +#undef LWIP_NOASSERT +#endif +/** + * @} + */ + +#ifndef LWIP_NOASSERT +#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) { \ + LWIP_PLATFORM_ASSERT(message); }} while(0) +#ifndef LWIP_PLATFORM_ASSERT +#error "If you want to use LWIP_ASSERT, LWIP_PLATFORM_ASSERT(message) needs to be defined in your arch/cc.h" +#endif +#else /* LWIP_NOASSERT */ +#define LWIP_ASSERT(message, assertion) +#endif /* LWIP_NOASSERT */ + +#ifndef LWIP_ERROR +#ifndef LWIP_NOASSERT +#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message) +#elif defined LWIP_DEBUG +#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_DIAG((message)) +#else +#define LWIP_PLATFORM_ERROR(message) +#endif + +/* if "expression" isn't true, then print "message" and execute "handler" expression */ +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + LWIP_PLATFORM_ERROR(message); handler;}} while(0) +#endif /* LWIP_ERROR */ + +/** Enable debug message printing, but only if debug message type is enabled + * AND is of correct type AND is at least LWIP_DBG_LEVEL. + */ +#ifdef __DOXYGEN__ +#define LWIP_DEBUG +#undef LWIP_DEBUG +#endif + +#ifdef LWIP_DEBUG +#ifndef LWIP_PLATFORM_DIAG +#error "If you want to use LWIP_DEBUG, LWIP_PLATFORM_DIAG(message) needs to be defined in your arch/cc.h" +#endif +#define LWIP_DEBUGF(debug, message) do { \ + if ( \ + ((debug) & LWIP_DBG_ON) && \ + ((debug) & LWIP_DBG_TYPES_ON) && \ + ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ + LWIP_PLATFORM_DIAG(message); \ + if ((debug) & LWIP_DBG_HALT) { \ + while(1); \ + } \ + } \ + } while(0) + +#else /* LWIP_DEBUG */ +#define LWIP_DEBUGF(debug, message) +#endif /* LWIP_DEBUG */ + +#endif /* LWIP_HDR_DEBUG_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/def.h b/components/net/lwip-2.0.3/src/include/lwip/def.h new file mode 100644 index 0000000000..82a9d896f0 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/def.h @@ -0,0 +1,141 @@ +/** + * @file + * various utility macros + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_DEF_H +#define LWIP_HDR_DEF_H + +/* arch.h might define NULL already */ +#include "lwip/arch.h" +#include "lwip/opt.h" +#if LWIP_PERF +#include "arch/perf.h" +#else /* LWIP_PERF */ +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ +#endif /* LWIP_PERF */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y)) +#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y)) + +/* Get the number of entries in an array ('x' must NOT be a pointer!) */ +#define LWIP_ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) + +/** Create u32_t value from bytes */ +#define LWIP_MAKEU32(a,b,c,d) (((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff)) + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#if BYTE_ORDER == BIG_ENDIAN +#define lwip_htons(x) (x) +#define lwip_ntohs(x) (x) +#define lwip_htonl(x) (x) +#define lwip_ntohl(x) (x) +#define PP_HTONS(x) (x) +#define PP_NTOHS(x) (x) +#define PP_HTONL(x) (x) +#define PP_NTOHL(x) (x) +#else /* BYTE_ORDER != BIG_ENDIAN */ +#ifndef lwip_htons +u16_t lwip_htons(u16_t x); +#endif +#define lwip_ntohs(x) lwip_htons(x) + +#ifndef lwip_htonl +u32_t lwip_htonl(u32_t x); +#endif +#define lwip_ntohl(x) lwip_htonl(x) + +/* These macros should be calculated by the preprocessor and are used + with compile-time constants only (so that there is no little-endian + overhead at runtime). */ +#define PP_HTONS(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8)) +#define PP_NTOHS(x) PP_HTONS(x) +#define PP_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \ + (((x) & 0x0000ff00UL) << 8) | \ + (((x) & 0x00ff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) +#define PP_NTOHL(x) PP_HTONL(x) +#endif /* BYTE_ORDER == BIG_ENDIAN */ + +/* Provide usual function names as macros for users, but this can be turned off */ +#ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS +#define htons(x) lwip_htons(x) +#define ntohs(x) lwip_ntohs(x) +#define htonl(x) lwip_htonl(x) +#define ntohl(x) lwip_ntohl(x) +#endif + +/* Functions that are not available as standard implementations. + * In cc.h, you can #define these to implementations available on + * your platform to save some code bytes if you use these functions + * in your application, too. + */ + +#ifndef lwip_itoa +/* This can be #defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform */ +void lwip_itoa(char* result, size_t bufsize, int number); +#endif +#ifndef lwip_strnicmp +/* This can be #defined to strnicmp() or strncasecmp() depending on your platform */ +int lwip_strnicmp(const char* str1, const char* str2, size_t len); +#endif +#ifndef lwip_stricmp +/* This can be #defined to stricmp() or strcasecmp() depending on your platform */ +int lwip_stricmp(const char* str1, const char* str2); +#endif +#ifndef lwip_strnstr +/* This can be #defined to strnstr() depending on your platform */ +char* lwip_strnstr(const char* buffer, const char* token, size_t n); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_DEF_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/dhcp.h b/components/net/lwip-2.0.3/src/include/lwip/dhcp.h new file mode 100644 index 0000000000..df932afb52 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/dhcp.h @@ -0,0 +1,143 @@ +/** + * @file + * DHCP client API + */ + +/* + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + */ +#ifndef LWIP_HDR_DHCP_H +#define LWIP_HDR_DHCP_H + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** period (in seconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_SECS 60 +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +#define DHCP_FINE_TIMER_MSECS 500 + +#define DHCP_BOOT_FILE_LEN 128U + +/* AutoIP cooperation flags (struct dhcp.autoip_coop_state) */ +typedef enum { + DHCP_AUTOIP_COOP_STATE_OFF = 0, + DHCP_AUTOIP_COOP_STATE_ON = 1 +} dhcp_autoip_coop_state_enum_t; + +struct dhcp +{ + /** transaction identifier of last sent request */ + u32_t xid; + /** incoming msg */ + struct dhcp_msg *msg_in; + /** track PCB allocation state */ + u8_t pcb_allocated; + /** current DHCP state machine state */ + u8_t state; + /** retries of current request */ + u8_t tries; +#if LWIP_DHCP_AUTOIP_COOP + u8_t autoip_coop_state; +#endif + u8_t subnet_mask_given; + + struct pbuf *p_out; /* pbuf of outcoming msg */ + struct dhcp_msg *msg_out; /* outgoing msg */ + u16_t options_out_len; /* outgoing msg options length */ + u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + u16_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */ + u16_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */ + u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */ + u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */ + ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */ + ip4_addr_t offered_ip_addr; + ip4_addr_t offered_sn_mask; + ip4_addr_t offered_gw_addr; + + u32_t offered_t0_lease; /* lease period (in seconds) */ + u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + u32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period) */ +#if LWIP_DHCP_BOOTP_FILE + ip4_addr_t offered_si_addr; + char boot_file_name[DHCP_BOOT_FILE_LEN]; +#endif /* LWIP_DHCP_BOOTPFILE */ +}; + + +void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); +/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ +#define dhcp_remove_struct(netif) netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL) +void dhcp_cleanup(struct netif *netif); +err_t dhcp_start(struct netif *netif); +err_t dhcp_renew(struct netif *netif); +err_t dhcp_release(struct netif *netif); +void dhcp_stop(struct netif *netif); +void dhcp_inform(struct netif *netif); +void dhcp_network_changed(struct netif *netif); +#if DHCP_DOES_ARP_CHECK +void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr); +#endif +u8_t dhcp_supplied_address(const struct netif *netif); +/* to be called every minute */ +void dhcp_coarse_tmr(void); +/* to be called every half second */ +void dhcp_fine_tmr(void); + +#if LWIP_DHCP_GET_NTP_SRV +/** This function must exist, in other to add offered NTP servers to + * the NTP (or SNTP) engine. + * See LWIP_DHCP_MAX_NTP_SERVERS */ +extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t* ntp_server_addrs); +#endif /* LWIP_DHCP_GET_NTP_SRV */ + +#define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DHCP */ + +#endif /*LWIP_HDR_DHCP_H*/ diff --git a/components/net/lwip-2.0.3/src/include/lwip/dhcp6.h b/components/net/lwip-2.0.3/src/include/lwip/dhcp6.h new file mode 100644 index 0000000000..455336d37d --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/dhcp6.h @@ -0,0 +1,58 @@ +/** + * @file + * + * IPv6 address autoconfiguration as per RFC 4862. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * IPv6 address autoconfiguration as per RFC 4862. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_IP6_DHCP6_H +#define LWIP_HDR_IP6_DHCP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ + + +struct dhcp6 +{ + /*@todo: implement DHCP6*/ +}; + +#endif /* LWIP_IPV6_DHCP6 */ + +#endif /* LWIP_HDR_IP6_DHCP6_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/dns.h b/components/net/lwip-2.0.3/src/include/lwip/dns.h new file mode 100644 index 0000000000..1453d72341 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/dns.h @@ -0,0 +1,130 @@ +/** + * @file + * DNS API + */ + +/** + * lwip DNS resolver header file. + + * Author: Jim Pettinato + * April 2007 + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LWIP_HDR_DNS_H +#define LWIP_HDR_DNS_H + +#include "lwip/opt.h" + +#if LWIP_DNS + +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** DNS timer period */ +#define DNS_TMR_INTERVAL 1000 + +/* DNS resolve types: */ +#define LWIP_DNS_ADDRTYPE_IPV4 0 +#define LWIP_DNS_ADDRTYPE_IPV6 1 +#define LWIP_DNS_ADDRTYPE_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */ +#define LWIP_DNS_ADDRTYPE_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */ +#if LWIP_IPV4 && LWIP_IPV6 +#ifndef LWIP_DNS_ADDRTYPE_DEFAULT +#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4_IPV6 +#endif +#elif LWIP_IPV4 +#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4 +#else +#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV6 +#endif + +#if DNS_LOCAL_HOSTLIST +/** struct used for local host-list */ +struct local_hostlist_entry { + /** static hostname */ + const char *name; + /** static host address in network byteorder */ + ip_addr_t addr; + struct local_hostlist_entry *next; +}; +#define DNS_LOCAL_HOSTLIST_ELEM(name, addr_init) {name, addr_init, NULL} +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN +#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH +#endif +#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1)) +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#endif /* DNS_LOCAL_HOSTLIST */ + +#if LWIP_IPV4 +extern const ip_addr_t dns_mquery_v4group; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 +extern const ip_addr_t dns_mquery_v6group; +#endif /* LWIP_IPV6 */ + +/** Callback which is invoked when a hostname is found. + * A function of this type must be implemented by the application using the DNS resolver. + * @param name pointer to the name that was looked up. + * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname, + * or NULL if the name could not be found (or on any other error). + * @param callback_arg a user-specified callback argument passed to dns_gethostbyname +*/ +typedef void (*dns_found_callback)(const char *name, const ip_addr_t *ipaddr, void *callback_arg); + +void dns_init(void); +void dns_tmr(void); +void dns_setserver(u8_t numdns, const ip_addr_t *dnsserver); +const ip_addr_t* dns_getserver(u8_t numdns); +err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, + dns_found_callback found, void *callback_arg); +err_t dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, + dns_found_callback found, void *callback_arg, + u8_t dns_addrtype); + + +#if DNS_LOCAL_HOSTLIST +size_t dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg); +err_t dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype); +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +int dns_local_removehost(const char *hostname, const ip_addr_t *addr); +err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#endif /* DNS_LOCAL_HOSTLIST */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS */ + +#endif /* LWIP_HDR_DNS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/err.h b/components/net/lwip-2.0.3/src/include/lwip/err.h new file mode 100644 index 0000000000..84e528d1ed --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/err.h @@ -0,0 +1,119 @@ +/** + * @file + * lwIP Error codes + */ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ERR_H +#define LWIP_HDR_ERR_H + +#include "lwip/opt.h" +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup infrastructure_errors Error codes + * @ingroup infrastructure + * @{ + */ + +/** Define LWIP_ERR_T in cc.h if you want to use + * a different type for your platform (must be signed). */ +#ifdef LWIP_ERR_T +typedef LWIP_ERR_T err_t; +#else /* LWIP_ERR_T */ +typedef s8_t err_t; +#endif /* LWIP_ERR_T*/ + +/** Definitions for error constants. */ +typedef enum { +/** No error, everything OK. */ + ERR_OK = 0, +/** Out of memory error. */ + ERR_MEM = -1, +/** Buffer error. */ + ERR_BUF = -2, +/** Timeout. */ + ERR_TIMEOUT = -3, +/** Routing problem. */ + ERR_RTE = -4, +/** Operation in progress */ + ERR_INPROGRESS = -5, +/** Illegal value. */ + ERR_VAL = -6, +/** Operation would block. */ + ERR_WOULDBLOCK = -7, +/** Address in use. */ + ERR_USE = -8, +/** Already connecting. */ + ERR_ALREADY = -9, +/** Conn already established.*/ + ERR_ISCONN = -10, +/** Not connected. */ + ERR_CONN = -11, +/** Low-level netif error */ + ERR_IF = -12, + +/** Connection aborted. */ + ERR_ABRT = -13, +/** Connection reset. */ + ERR_RST = -14, +/** Connection closed. */ + ERR_CLSD = -15, +/** Illegal argument. */ + ERR_ARG = -16 +} err_enum_t; + +#define ERR_IS_FATAL(e) ((e) <= ERR_ABRT) + +/** + * @} + */ + +#ifdef LWIP_DEBUG +extern const char *lwip_strerr(err_t err); +#else +#define lwip_strerr(x) "" +#endif /* LWIP_DEBUG */ + +#if !NO_SYS +int err_to_errno(err_t err); +#endif /* !NO_SYS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ERR_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/errno.h b/components/net/lwip-2.0.3/src/include/lwip/errno.h new file mode 100644 index 0000000000..641cffb09c --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/errno.h @@ -0,0 +1,193 @@ +/** + * @file + * Posix Errno defines + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ERRNO_H +#define LWIP_HDR_ERRNO_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LWIP_PROVIDE_ERRNO + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#ifndef errno +extern int errno; +#endif + +#else /* LWIP_PROVIDE_ERRNO */ + +/* Define LWIP_ERRNO_INCLUDE to to include the error defines here */ +#ifdef LWIP_ERRNO_INCLUDE +#include LWIP_ERRNO_INCLUDE +#endif /* LWIP_ERRNO_INCLUDE */ + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ERRNO_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/etharp.h b/components/net/lwip-2.0.3/src/include/lwip/etharp.h new file mode 100644 index 0000000000..7080a19d05 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/etharp.h @@ -0,0 +1,106 @@ +/** + * @file + * Ethernet output function - handles OUTGOING ethernet level traffic, implements + * ARP resolving. + * To be used in most low-level netif implementations + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_NETIF_ETHARP_H +#define LWIP_HDR_NETIF_ETHARP_H + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip4_addr.h" +#include "lwip/netif.h" +#include "lwip/ip4.h" +#include "lwip/prot/ethernet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/prot/etharp.h" + +/** 1 seconds period */ +#define ARP_TMR_INTERVAL 1000 + +#if ARP_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct etharp_q_entry { + struct etharp_q_entry *next; + struct pbuf *p; +}; +#endif /* ARP_QUEUEING */ + +#define etharp_init() /* Compatibility define, no init needed. */ +void etharp_tmr(void); +s8_t etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr, + struct eth_addr **eth_ret, const ip4_addr_t **ip_ret); +u8_t etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret); +err_t etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr); +err_t etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q); +err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr); +/** For Ethernet network interfaces, we might want to send "gratuitous ARP"; + * this is an ARP packet sent by a node in order to spontaneously cause other + * nodes to update an entry in their ARP cache. + * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ +#define etharp_gratuitous(netif) etharp_request((netif), netif_ip4_addr(netif)) +void etharp_cleanup_netif(struct netif *netif); + +#if ETHARP_SUPPORT_STATIC_ENTRIES +err_t etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr); +err_t etharp_remove_static_entry(const ip4_addr_t *ipaddr); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#endif /* LWIP_IPV4 && LWIP_ARP */ + +void etharp_input(struct pbuf *p, struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +#endif /* LWIP_HDR_NETIF_ETHARP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/ethip6.h b/components/net/lwip-2.0.3/src/include/lwip/ethip6.h new file mode 100644 index 0000000000..5e88dffd05 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/ethip6.h @@ -0,0 +1,68 @@ +/** + * @file + * + * Ethernet output for IPv6. Uses ND tables for link-layer addressing. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_ETHIP6_H +#define LWIP_HDR_ETHIP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +err_t ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 && LWIP_ETHERNET */ + +#endif /* LWIP_HDR_ETHIP6_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/icmp.h b/components/net/lwip-2.0.3/src/include/lwip/icmp.h new file mode 100644 index 0000000000..f5a31fd4c0 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/icmp.h @@ -0,0 +1,110 @@ +/** + * @file + * ICMP API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ICMP_H +#define LWIP_HDR_ICMP_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/prot/icmp.h" + +#if LWIP_IPV6 && LWIP_ICMP6 +#include "lwip/icmp6.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** ICMP destination unreachable codes */ +enum icmp_dur_type { + /** net unreachable */ + ICMP_DUR_NET = 0, + /** host unreachable */ + ICMP_DUR_HOST = 1, + /** protocol unreachable */ + ICMP_DUR_PROTO = 2, + /** port unreachable */ + ICMP_DUR_PORT = 3, + /** fragmentation needed and DF set */ + ICMP_DUR_FRAG = 4, + /** source route failed */ + ICMP_DUR_SR = 5 +}; + +/** ICMP time exceeded codes */ +enum icmp_te_type { + /** time to live exceeded in transit */ + ICMP_TE_TTL = 0, + /** fragment reassembly time exceeded */ + ICMP_TE_FRAG = 1 +}; + +#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +void icmp_input(struct pbuf *p, struct netif *inp); +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +#endif /* LWIP_IPV4 && LWIP_ICMP */ + +#if LWIP_IPV4 && LWIP_IPV6 +#if LWIP_ICMP && LWIP_ICMP6 +#define icmp_port_unreach(isipv6, pbuf) ((isipv6) ? \ + icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) : \ + icmp_dest_unreach(pbuf, ICMP_DUR_PORT)) +#elif LWIP_ICMP +#define icmp_port_unreach(isipv6, pbuf) do{ if(!(isipv6)) { icmp_dest_unreach(pbuf, ICMP_DUR_PORT);}}while(0) +#elif LWIP_ICMP6 +#define icmp_port_unreach(isipv6, pbuf) do{ if(isipv6) { icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT);}}while(0) +#else +#define icmp_port_unreach(isipv6, pbuf) +#endif +#elif LWIP_IPV6 && LWIP_ICMP6 +#define icmp_port_unreach(isipv6, pbuf) icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) +#elif LWIP_IPV4 && LWIP_ICMP +#define icmp_port_unreach(isipv6, pbuf) icmp_dest_unreach(pbuf, ICMP_DUR_PORT) +#else /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) */ +#define icmp_port_unreach(isipv6, pbuf) +#endif /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) LWIP_IPV4*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ICMP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/icmp6.h b/components/net/lwip-2.0.3/src/include/lwip/icmp6.h new file mode 100644 index 0000000000..a29dc8c1c2 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/icmp6.h @@ -0,0 +1,70 @@ +/** + * @file + * + * IPv6 version of ICMP, as per RFC 4443. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_ICMP6_H +#define LWIP_HDR_ICMP6_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/prot/icmp6.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +void icmp6_input(struct pbuf *p, struct netif *inp); +void icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c); +void icmp6_packet_too_big(struct pbuf *p, u32_t mtu); +void icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c); +void icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer); + +#endif /* LWIP_ICMP6 && LWIP_IPV6 */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* LWIP_HDR_ICMP6_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/igmp.h b/components/net/lwip-2.0.3/src/include/lwip/igmp.h new file mode 100644 index 0000000000..ffd80e680c --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/igmp.h @@ -0,0 +1,115 @@ +/** + * @file + * IGMP API + */ + +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +#ifndef LWIP_HDR_IGMP_H +#define LWIP_HDR_IGMP_H + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" + +#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* IGMP timer */ +#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ +#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + +/* Compatibility defines (don't use for new code) */ +#define IGMP_DEL_MAC_FILTER NETIF_DEL_MAC_FILTER +#define IGMP_ADD_MAC_FILTER NETIF_ADD_MAC_FILTER + +/** + * igmp group structure - there is + * a list of groups for each interface + * these should really be linked from the interface, but + * if we keep them separate we will not affect the lwip original code + * too much + * + * There will be a group for the all systems group address but this + * will not run the state machine as it is used to kick off reports + * from all the other groups + */ +struct igmp_group { + /** next link */ + struct igmp_group *next; + /** multicast address */ + ip4_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting, negative is OFF */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +/* Prototypes */ +void igmp_init(void); +err_t igmp_start(struct netif *netif); +err_t igmp_stop(struct netif *netif); +void igmp_report_groups(struct netif *netif); +struct igmp_group *igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr); +void igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest); +err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); +err_t igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr); +err_t igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); +err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr); +void igmp_tmr(void); + +/** @ingroup igmp + * Get list head of IGMP groups for netif. + * Note: The allsystems group IP is contained in the list as first entry. + * @see @ref netif_set_igmp_mac_filter() + */ +#define netif_igmp_data(netif) ((struct igmp_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 && LWIP_IGMP */ + +#endif /* LWIP_HDR_IGMP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/inet.h b/components/net/lwip-2.0.3/src/include/lwip/inet.h new file mode 100644 index 0000000000..4a34f02653 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/inet.h @@ -0,0 +1,172 @@ +/** + * @file + * This file (together with sockets.h) aims to provide structs and functions from + * - arpa/inet.h + * - netinet/in.h + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INET_H +#define LWIP_HDR_INET_H + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) +typedef u32_t in_addr_t; +#endif + +struct in_addr { + in_addr_t s_addr; +}; + +struct in6_addr { + union { + u32_t u32_addr[4]; + u8_t u8_addr[16]; + } un; +#define s6_addr un.u8_addr +}; + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 wildcard address. */ +#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 loopback address. */ +#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} +/** This variable is initialized by the system to contain the wildcard IPv6 address. */ +extern const struct in6_addr in6addr_any; + +/* Definitions of the bits in an (IPv4) Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IN_CLASSA(a) IP_CLASSA(a) +#define IN_CLASSA_NET IP_CLASSA_NET +#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT +#define IN_CLASSA_HOST IP_CLASSA_HOST +#define IN_CLASSA_MAX IP_CLASSA_MAX + +#define IN_CLASSB(b) IP_CLASSB(b) +#define IN_CLASSB_NET IP_CLASSB_NET +#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT +#define IN_CLASSB_HOST IP_CLASSB_HOST +#define IN_CLASSB_MAX IP_CLASSB_MAX + +#define IN_CLASSC(c) IP_CLASSC(c) +#define IN_CLASSC_NET IP_CLASSC_NET +#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT +#define IN_CLASSC_HOST IP_CLASSC_HOST +#define IN_CLASSC_MAX IP_CLASSC_MAX + +#define IN_CLASSD(d) IP_CLASSD(d) +#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ +#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ +#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ +#define IN_CLASSD_MAX IP_CLASSD_MAX + +#define IN_MULTICAST(a) IP_MULTICAST(a) + +#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) +#define IN_BADCLASS(a) IP_BADCLASS(a) + +#define IN_LOOPBACKNET IP_LOOPBACKNET + + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX +#endif +#if LWIP_IPV6 +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX +#endif +#endif + +#if LWIP_IPV4 + +#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) +#define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) +/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */ +#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) + +/* directly map this to the lwip internal functions */ +#define inet_addr(cp) ipaddr_addr(cp) +#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) +#define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) +#define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) + +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ + (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ + (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ + (target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];} +#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \ + (target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \ + (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ + (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];} +/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ +#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) + +/* directly map this to the lwip internal functions */ +#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) +#define inet6_ntoa(addr) ip6addr_ntoa((const ip6_addr_t*)&(addr)) +#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) + +#endif /* LWIP_IPV6 */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INET_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/inet_chksum.h b/components/net/lwip-2.0.3/src/include/lwip/inet_chksum.h new file mode 100644 index 0000000000..4e23d7f194 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/inet_chksum.h @@ -0,0 +1,105 @@ +/** + * @file + * IP checksum calculation functions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INET_CHKSUM_H +#define LWIP_HDR_INET_CHKSUM_H + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +/** Swap the bytes in an u16_t: much like lwip_htons() for little-endian */ +#ifndef SWAP_BYTES_IN_WORD +#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) +#endif /* SWAP_BYTES_IN_WORD */ + +/** Split an u32_t in two u16_ts and add them up */ +#ifndef FOLD_U32T +#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL)) +#endif + +#if LWIP_CHECKSUM_ON_COPY +/** Function-like macro: same as MEMCPY but returns the checksum of copied data + as u16_t */ +# ifndef LWIP_CHKSUM_COPY +# define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len) +# ifndef LWIP_CHKSUM_COPY_ALGORITHM +# define LWIP_CHKSUM_COPY_ALGORITHM 1 +# endif /* LWIP_CHKSUM_COPY_ALGORITHM */ +# else /* LWIP_CHKSUM_COPY */ +# define LWIP_CHKSUM_COPY_ALGORITHM 0 +# endif /* LWIP_CHKSUM_COPY */ +#else /* LWIP_CHECKSUM_ON_COPY */ +# define LWIP_CHKSUM_COPY_ALGORITHM 0 +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(const void *dataptr, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +#if LWIP_CHKSUM_COPY_ALGORITHM +u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len); +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ + +#if LWIP_IPV4 +u16_t inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip4_addr_t *src, const ip4_addr_t *dest); +u16_t inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, + u16_t proto_len, u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest); +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +u16_t ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip6_addr_t *src, const ip6_addr_t *dest); +u16_t ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest); +#endif /* LWIP_IPV6 */ + + +u16_t ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip_addr_t *src, const ip_addr_t *dest); +u16_t ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INET_H */ + diff --git a/components/net/lwip-2.0.3/src/include/lwip/init.h b/components/net/lwip-2.0.3/src/include/lwip/init.h new file mode 100644 index 0000000000..457082f2e5 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/init.h @@ -0,0 +1,100 @@ +/** + * @file + * lwIP initialization API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INIT_H +#define LWIP_HDR_INIT_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup lwip_version Version + * @ingroup lwip + * @{ + */ + +/** X.x.x: Major version of the stack */ +#define LWIP_VERSION_MAJOR 2U +/** x.X.x: Minor version of the stack */ +#define LWIP_VERSION_MINOR 0U +/** x.x.X: Revision of the stack */ +#define LWIP_VERSION_REVISION 3U +/** For release candidates, this is set to 1..254 + * For official releases, this is set to 255 (LWIP_RC_RELEASE) + * For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */ +#define LWIP_VERSION_RC LWIP_RC_RELEASE + +/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ +#define LWIP_RC_RELEASE 255U +/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for Git versions */ +#define LWIP_RC_DEVELOPMENT 0U + +#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE) +#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) +#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) + +/* Some helper defines to get a version string */ +#define LWIP_VERSTR2(x) #x +#define LWIP_VERSTR(x) LWIP_VERSTR2(x) +#if LWIP_VERSION_IS_RELEASE +#define LWIP_VERSION_STRING_SUFFIX "" +#elif LWIP_VERSION_IS_DEVELOPMENT +#define LWIP_VERSION_STRING_SUFFIX "d" +#else +#define LWIP_VERSION_STRING_SUFFIX "rc" LWIP_VERSTR(LWIP_VERSION_RC) +#endif + +/** Provides the version of the stack */ +#define LWIP_VERSION (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 | \ + LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC) +/** Provides the version of the stack as string */ +#define LWIP_VERSION_STRING LWIP_VERSTR(LWIP_VERSION_MAJOR) "." LWIP_VERSTR(LWIP_VERSION_MINOR) "." LWIP_VERSTR(LWIP_VERSION_REVISION) LWIP_VERSION_STRING_SUFFIX + +/** + * @} + */ + +/* Modules initialization */ +void lwip_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INIT_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/ip.h b/components/net/lwip-2.0.3/src/include/lwip/ip.h new file mode 100644 index 0000000000..0673be9b4a --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/ip.h @@ -0,0 +1,319 @@ +/** + * @file + * IP API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP_H +#define LWIP_HDR_IP_H + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" +#include "lwip/ip4.h" +#include "lwip/ip6.h" +#include "lwip/prot/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#define LWIP_IP_HDRINCL NULL + +/** pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ +#ifndef LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX +#define LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p) LWIP_ASSERT("p->ref == 1", (p)->ref == 1) +#endif + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/** This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB \ + /* ip addresses in network byte order */ \ + ip_addr_t local_ip; \ + ip_addr_t remote_ip; \ + /* Socket options */ \ + u8_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + +struct ip_pcb { +/* Common members of all PCB types */ + IP_PCB; +}; + +/* + * Option flags per-socket. These are the same like SO_XXX in sockets.h + */ +#define SOF_REUSEADDR 0x04U /* allow local address reuse */ +#define SOF_KEEPALIVE 0x08U /* keep connections alive */ +#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ + +/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ +#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) + +/** Global variables of this module, kept in a struct for efficient access using base+index. */ +struct ip_globals +{ + /** The interface that accepted the packet for the current callback invocation. */ + struct netif *current_netif; + /** The interface that received the packet for the current callback invocation. */ + struct netif *current_input_netif; +#if LWIP_IPV4 + /** Header of the input packet currently being processed. */ + struct ip_hdr *current_ip4_header; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + /** Header of the input IPv6 packet currently being processed. */ + struct ip6_hdr *current_ip6_header; +#endif /* LWIP_IPV6 */ + /** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */ + u16_t current_ip_header_tot_len; + /** Source IP address of current_header */ + ip_addr_t current_iphdr_src; + /** Destination IP address of current_header */ + ip_addr_t current_iphdr_dest; +}; +extern struct ip_globals ip_data; + + +/** Get the interface that accepted the current packet. + * This may or may not be the receiving netif, depending on your netif/network setup. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_netif() (ip_data.current_netif) +/** Get the interface that received the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_input_netif() (ip_data.current_input_netif) +/** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */ +#define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len) +/** Source IP address of current_header */ +#define ip_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP address of current_header */ +#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) + +#if LWIP_IPV4 && LWIP_IPV6 +/** Get the IPv4 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) +/** Get the IPv6 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) +/** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */ +#define ip_current_is_v6() (ip6_current_header() != NULL) +/** Source IPv6 address of current_header */ +#define ip6_current_src_addr() (ip_2_ip6(&ip_data.current_iphdr_src)) +/** Destination IPv6 address of current_header */ +#define ip6_current_dest_addr() (ip_2_ip6(&ip_data.current_iphdr_dest)) +/** Get the transport layer protocol */ +#define ip_current_header_proto() (ip_current_is_v6() ? \ + IP6H_NEXTH(ip6_current_header()) :\ + IPH_PROTO(ip4_current_header())) +/** Get the transport layer header */ +#define ip_next_header_ptr() ((const void*)((ip_current_is_v6() ? \ + (const u8_t*)ip6_current_header() : (const u8_t*)ip4_current_header()) + ip_current_header_tot_len())) + +/** Source IP4 address of current_header */ +#define ip4_current_src_addr() (ip_2_ip4(&ip_data.current_iphdr_src)) +/** Destination IP4 address of current_header */ +#define ip4_current_dest_addr() (ip_2_ip4(&ip_data.current_iphdr_dest)) + +#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ + +/** Get the IPv4 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) +/** Always returns FALSE when only supporting IPv4 only */ +#define ip_current_is_v6() 0 +/** Get the transport layer protocol */ +#define ip_current_header_proto() IPH_PROTO(ip4_current_header()) +/** Get the transport layer header */ +#define ip_next_header_ptr() ((const void*)((const u8_t*)ip4_current_header() + ip_current_header_tot_len())) +/** Source IP4 address of current_header */ +#define ip4_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP4 address of current_header */ +#define ip4_current_dest_addr() (&ip_data.current_iphdr_dest) + +#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ + +/** Get the IPv6 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) +/** Always returns TRUE when only supporting IPv6 only */ +#define ip_current_is_v6() 1 +/** Get the transport layer protocol */ +#define ip_current_header_proto() IP6H_NEXTH(ip6_current_header()) +/** Get the transport layer header */ +#define ip_next_header_ptr() ((const void*)((const u8_t*)ip6_current_header())) +/** Source IP6 address of current_header */ +#define ip6_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP6 address of current_header */ +#define ip6_current_dest_addr() (&ip_data.current_iphdr_dest) + +#endif /* LWIP_IPV6 */ + +/** Union source address of current_header */ +#define ip_current_src_addr() (&ip_data.current_iphdr_src) +/** Union destination address of current_header */ +#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) + +/** Gets an IP pcb option (SOF_* flags) */ +#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) +/** Sets an IP pcb option (SOF_* flags) */ +#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) +/** Resets an IP pcb option (SOF_* flags) */ +#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) + +#if LWIP_IPV4 && LWIP_IPV6 +/** + * @ingroup ip + * Output IP packet, netif is selected by source address + */ +#define ip_output(p, src, dest, ttl, tos, proto) \ + (IP_IS_V6(dest) ? \ + ip6_output(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto) : \ + ip4_output(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto)) +/** + * @ingroup ip + * Output IP packet to specified interface + */ +#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ + (IP_IS_V6(dest) ? \ + ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ + ip4_output_if(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) +/** + * @ingroup ip + * Output IP packet to interface specifying source address + */ +#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ + (IP_IS_V6(dest) ? \ + ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ + ip4_output_if_src(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) +/** Output IP packet with addr_hint */ +#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ + (IP_IS_V6(dest) ? \ + ip6_output_hinted(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, addr_hint) : \ + ip4_output_hinted(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, addr_hint)) +/** + * @ingroup ip + * Get netif for address combination. See \ref ip6_route and \ref ip4_route + */ +#define ip_route(src, dest) \ + (IP_IS_V6(dest) ? \ + ip6_route(ip_2_ip6(src), ip_2_ip6(dest)) : \ + ip4_route_src(ip_2_ip4(dest), ip_2_ip4(src))) +/** + * @ingroup ip + * Get netif for IP. + */ +#define ip_netif_get_local_ip(netif, dest) (IP_IS_V6(dest) ? \ + ip6_netif_get_local_ip(netif, ip_2_ip6(dest)) : \ + ip4_netif_get_local_ip(netif)) +#define ip_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip4_debug_print(p)) + +err_t ip_input(struct pbuf *p, struct netif *inp); + +#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ + +#define ip_output(p, src, dest, ttl, tos, proto) \ + ip4_output(p, src, dest, ttl, tos, proto) +#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ + ip4_output_if(p, src, dest, ttl, tos, proto, netif) +#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ + ip4_output_if_src(p, src, dest, ttl, tos, proto, netif) +#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ + ip4_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) +#define ip_route(src, dest) \ + ip4_route_src(dest, src) +#define ip_netif_get_local_ip(netif, dest) \ + ip4_netif_get_local_ip(netif) +#define ip_debug_print(is_ipv6, p) ip4_debug_print(p) + +#define ip_input ip4_input + +#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ + +#define ip_output(p, src, dest, ttl, tos, proto) \ + ip6_output(p, src, dest, ttl, tos, proto) +#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ + ip6_output_if(p, src, dest, ttl, tos, proto, netif) +#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ + ip6_output_if_src(p, src, dest, ttl, tos, proto, netif) +#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ + ip6_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) +#define ip_route(src, dest) \ + ip6_route(src, dest) +#define ip_netif_get_local_ip(netif, dest) \ + ip6_netif_get_local_ip(netif, dest) +#define ip_debug_print(is_ipv6, p) ip6_debug_print(p) + +#define ip_input ip6_input + +#endif /* LWIP_IPV6 */ + +#define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ + (netif) = ip_route(src, dest); \ + (ipaddr) = ip_netif_get_local_ip(netif, dest); \ +}while(0) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP_H */ + + diff --git a/components/net/lwip-2.0.3/src/include/lwip/ip4.h b/components/net/lwip-2.0.3/src/include/lwip/ip4.h new file mode 100644 index 0000000000..48246ecc25 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/ip4.h @@ -0,0 +1,111 @@ +/** + * @file + * IPv4 API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP4_H +#define LWIP_HDR_IP4_H + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip4_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" +#include "lwip/prot/ip4.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LWIP_HOOK_IP4_ROUTE_SRC +#define LWIP_IPV4_SRC_ROUTING 1 +#else +#define LWIP_IPV4_SRC_ROUTING 0 +#endif + +/** Currently, the function ip_output_if_opt() is only used with IGMP */ +#define IP_OPTIONS_SEND (LWIP_IPV4 && LWIP_IGMP) + +#define ip_init() /* Compatibility define, no init needed. */ +struct netif *ip4_route(const ip4_addr_t *dest); +#if LWIP_IPV4_SRC_ROUTING +struct netif *ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src); +#else /* LWIP_IPV4_SRC_ROUTING */ +#define ip4_route_src(dest, src) ip4_route(dest) +#endif /* LWIP_IPV4_SRC_ROUTING */ +err_t ip4_input(struct pbuf *p, struct netif *inp); +err_t ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto); +err_t ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); +err_t ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if IP_OPTIONS_SEND +err_t ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +err_t ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +#endif /* IP_OPTIONS_SEND */ + +#if LWIP_MULTICAST_TX_OPTIONS +void ip4_set_default_multicast_netif(struct netif* default_multicast_netif); +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#define ip4_netif_get_local_ip(netif) (((netif) != NULL) ? netif_ip_addr4(netif) : NULL) + +#if IP_DEBUG +void ip4_debug_print(struct pbuf *p); +#else +#define ip4_debug_print(p) +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 */ + +#endif /* LWIP_HDR_IP_H */ + + diff --git a/components/net/lwip-2.0.3/src/include/lwip/ip4_addr.h b/components/net/lwip-2.0.3/src/include/lwip/ip4_addr.h new file mode 100644 index 0000000000..51b46b8d4c --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/ip4_addr.h @@ -0,0 +1,227 @@ +/** + * @file + * IPv4 address API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP4_ADDR_H +#define LWIP_HDR_IP4_ADDR_H + +#include "lwip/opt.h" +#include "lwip/def.h" + +#if LWIP_IPV4 + +#ifdef __cplusplus +extern "C" { +#endif + +/** This is the aligned version of ip4_addr_t, + used as local variable, on the stack, etc. */ +struct ip4_addr { + u32_t addr; +}; + +/** ip4_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip4_addr_t as well as on ip4_addr_p_t. */ +typedef struct ip4_addr ip4_addr_t; + +/** + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip4_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Forward declaration to not include netif.h */ +struct netif; + +/** 255.255.255.255 */ +#define IPADDR_NONE ((u32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) +#define IP_CLASSA_NET 0xff000000 +#define IP_CLASSA_NSHIFT 24 +#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) +#define IP_CLASSA_MAX 128 + +#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) +#define IP_CLASSB_NET 0xffff0000 +#define IP_CLASSB_NSHIFT 16 +#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) +#define IP_CLASSB_MAX 65536 + +#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) +#define IP_CLASSC_NET 0xffffff00 +#define IP_CLASSC_NSHIFT 8 +#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) + +#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) +#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ +#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ +#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ +#define IP_MULTICAST(a) IP_CLASSD(a) + +#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) +#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) + +#define IP_LOOPBACKNET 127 /* official! */ + +/** Set an IP address given by the four byte-parts */ +#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) + +/** MEMCPY-like copying of IP addresses where addresses are known to be + * 16-bit-aligned if the port is correctly configured (so a port could define + * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ +#ifndef IPADDR2_COPY +#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip4_addr_t)) +#endif + +/** Copy IP address - faster than ip4_addr_set: no NULL check */ +#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) +/** Safely copy one IP address to another (src may be NULL) */ +#define ip4_addr_set(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + (src)->addr)) +/** Set complete address to zero */ +#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) +/** Set address to IPADDR_ANY (no need for lwip_htonl()) */ +#define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) +/** Set address to loopback address */ +#define ip4_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) +/** Check if an address is in the loopback region */ +#define ip4_addr_isloopback(ipaddr) (((ipaddr)->addr & PP_HTONL(IP_CLASSA_NET)) == PP_HTONL(((u32_t)IP_LOOPBACKNET) << 24)) +/** Safely copy one IP address to another and change byte order + * from host- to network-order. */ +#define ip4_addr_set_hton(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0:\ + lwip_htonl((src)->addr))) +/** IPv4 only: set the IP address given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) +/** IPv4 only: get the IP address as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +/** Get the network address by combining host address with netmask */ +#define ip4_addr_get_network(target, host, netmask) do { ((target)->addr = ((host)->addr) & ((netmask)->addr)); } while(0) + +/** + * Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip4_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) +#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) + +#define ip4_addr_isany_val(addr1) ((addr1).addr == IPADDR_ANY) +#define ip4_addr_isany(addr1) ((addr1) == NULL || ip4_addr_isany_val(*(addr1))) + +#define ip4_addr_isbroadcast(addr1, netif) ip4_addr_isbroadcast_u32((addr1)->addr, netif) +u8_t ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif); + +#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) +u8_t ip4_addr_netmask_valid(u32_t netmask); + +#define ip4_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) + +#define ip4_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) + +#define ip4_addr_debug_print_parts(debug, a, b, c, d) \ + LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d)) +#define ip4_addr_debug_print(debug, ipaddr) \ + ip4_addr_debug_print_parts(debug, \ + (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0)) +#define ip4_addr_debug_print_val(debug, ipaddr) \ + ip4_addr_debug_print_parts(debug, \ + ip4_addr1_16(&(ipaddr)), \ + ip4_addr2_16(&(ipaddr)), \ + ip4_addr3_16(&(ipaddr)), \ + ip4_addr4_16(&(ipaddr))) + +/* Get one byte from the 4-byte address */ +#define ip4_addr1(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[0]) +#define ip4_addr2(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[1]) +#define ip4_addr3(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[2]) +#define ip4_addr4(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[3]) +/* These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) +#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) +#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) +#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) + +#define IP4ADDR_STRLEN_MAX 16 + +/** For backwards compatibility */ +#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) + +u32_t ipaddr_addr(const char *cp); +int ip4addr_aton(const char *cp, ip4_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ip4addr_ntoa(const ip4_addr_t *addr); +char *ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 */ + +#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/ip4_frag.h b/components/net/lwip-2.0.3/src/include/lwip/ip4_frag.h new file mode 100644 index 0000000000..ed5bf14a31 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/ip4_frag.h @@ -0,0 +1,100 @@ +/** + * @file + * IP fragmentation/reassembly + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * + */ + +#ifndef LWIP_HDR_IP4_FRAG_H +#define LWIP_HDR_IP4_FRAG_H + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#if LWIP_IPV4 + +#ifdef __cplusplus +extern "C" { +#endif + +#if IP_REASSEMBLY +/* The IP reassembly timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + +/** IP reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip_reassdata { + struct ip_reassdata *next; + struct pbuf *p; + struct ip_hdr iphdr; + u16_t datagram_len; + u8_t flags; + u8_t timer; +}; + +void ip_reass_init(void); +void ip_reass_tmr(void); +struct pbuf * ip4_reass(struct pbuf *p); +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if !LWIP_NETIF_TX_SINGLE_PBUF +#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED +#define LWIP_PBUF_CUSTOM_REF_DEFINED +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ + +err_t ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest); +#endif /* IP_FRAG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 */ + +#endif /* LWIP_HDR_IP4_FRAG_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/ip6.h b/components/net/lwip-2.0.3/src/include/lwip/ip6.h new file mode 100644 index 0000000000..099b94fb74 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/ip6.h @@ -0,0 +1,93 @@ +/** + * @file + * + * IPv6 layer. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_H +#define LWIP_HDR_IP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/prot/ip6.h" +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" + +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct netif *ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest); +const ip_addr_t *ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest); +err_t ip6_input(struct pbuf *p, struct netif *inp); +err_t ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth); +err_t ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); +err_t ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if LWIP_IPV6_MLD +err_t ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value); +#endif /* LWIP_IPV6_MLD */ + +#define ip6_netif_get_local_ip(netif, dest) (((netif) != NULL) ? \ + ip6_select_source_address(netif, dest) : NULL) + +#if IP6_DEBUG +void ip6_debug_print(struct pbuf *p); +#else +#define ip6_debug_print(p) +#endif /* IP6_DEBUG */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_IP6_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/ip6_addr.h b/components/net/lwip-2.0.3/src/include/lwip/ip6_addr.h new file mode 100644 index 0000000000..ee381aeb23 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/ip6_addr.h @@ -0,0 +1,285 @@ +/** + * @file + * + * IPv6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * Structs and macros for handling IPv6 addresses. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_ADDR_H +#define LWIP_HDR_IP6_ADDR_H + +#include "lwip/opt.h" +#include "def.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** This is the aligned version of ip6_addr_t, + used as local variable, on the stack, etc. */ +struct ip6_addr { + u32_t addr[4]; +}; + +/** IPv6 address */ +typedef struct ip6_addr ip6_addr_t; + +/** Set an IPv6 partial address given by byte-parts */ +#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \ + (ip6addr)->addr[index] = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) + +/** Set a full IPv6 address by passing the 4 u32_t indices in network byte order + (use PP_HTONL() for constants) */ +#define IP6_ADDR(ip6addr, idx0, idx1, idx2, idx3) do { \ + (ip6addr)->addr[0] = idx0; \ + (ip6addr)->addr[1] = idx1; \ + (ip6addr)->addr[2] = idx2; \ + (ip6addr)->addr[3] = idx3; } while(0) + +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0])) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1])) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2])) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3])) & 0xffff)) + +/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ +#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ + (dest).addr[1] = (src).addr[1]; \ + (dest).addr[2] = (src).addr[2]; \ + (dest).addr[3] = (src).addr[3];}while(0) +/** Safely copy one IPv6 address to another (src may be NULL) */ +#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ + (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ + (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ + (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) + +/** Set complete address to zero */ +#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = 0;}while(0) + +/** Set address to ipv6 'any' (no need for lwip_htonl()) */ +#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) +/** Set address to ipv6 loopback address */ +#define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) +/** Safely copy one IPv6 address to another and change byte order + * from host- to network-order. */ +#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : lwip_htonl((src)->addr[0]); \ + (dest)->addr[1] = (src) == NULL ? 0 : lwip_htonl((src)->addr[1]); \ + (dest)->addr[2] = (src) == NULL ? 0 : lwip_htonl((src)->addr[2]); \ + (dest)->addr[3] = (src) == NULL ? 0 : lwip_htonl((src)->addr[3]);}while(0) + + +/** + * Determine if two IPv6 address are on the same network. + * + * @arg addr1 IPv6 address 1 + * @arg addr2 IPv6 address 2 + * @return !0 if the network identifiers of both address match + */ +#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1])) + +#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1]) && \ + ((addr1)->addr[2] == (addr2)->addr[2]) && \ + ((addr1)->addr[3] == (addr2)->addr[3])) + +#define ip6_get_subnet_id(ip6addr) (lwip_htonl((ip6addr)->addr[2]) & 0x0000ffffUL) + +#define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \ + ((ip6addr).addr[1] == 0) && \ + ((ip6addr).addr[2] == 0) && \ + ((ip6addr).addr[3] == 0)) +#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || ip6_addr_isany_val(*(ip6addr))) + +#define ip6_addr_isloopback(ip6addr) (((ip6addr)->addr[0] == 0UL) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) + +#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL)) + +#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL)) + +#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL)) + +#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL)) + +#define ip6_addr_isipv4mappedipv6(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL))) + +#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) +#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) +#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL)) +#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL)) +#define ip6_addr_multicast_scope(ip6addr) ((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xf) +#define IP6_MULTICAST_SCOPE_RESERVED 0x0 +#define IP6_MULTICAST_SCOPE_RESERVED0 0x0 +#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1 +#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2 +#define IP6_MULTICAST_SCOPE_RESERVED3 0x3 +#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4 +#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5 +#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8 +#define IP6_MULTICAST_SCOPE_GLOBAL 0xe +#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf +#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff010000UL)) +#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff020000UL)) +#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff040000UL)) +#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff050000UL)) +#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff080000UL)) +#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff0e0000UL)) + +/* @todo define get/set for well-know multicast addresses, e.g. ff02::1 */ +#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) + +#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) +#define ip6_addr_set_allnodes_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) + +#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000002UL))) +#define ip6_addr_set_allrouters_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}while(0) + +#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + (((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) ) + +#define ip6_addr_set_solicitednode(ip6addr, if_id) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \ + (ip6addr)->addr[3] = (PP_HTONL(0xff000000UL) | (if_id));}while(0) + +#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + ((ip6addr)->addr[3] == (PP_HTONL(0xff000000UL) | (sn_addr)->addr[3]))) + +/* IPv6 address states. */ +#define IP6_ADDR_INVALID 0x00 +#define IP6_ADDR_TENTATIVE 0x08 +#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */ +#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */ +#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */ +#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */ +#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */ +#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */ +#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */ +#define IP6_ADDR_VALID 0x10 /* This bit marks an address as valid (preferred or deprecated) */ +#define IP6_ADDR_PREFERRED 0x30 +#define IP6_ADDR_DEPRECATED 0x10 /* Same as VALID (valid but not preferred) */ + +#define IP6_ADDR_TENTATIVE_COUNT_MASK 0x07 /* 1-7 probes sent */ + +#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID) +#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE) +#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */ +#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED) +#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED) + +#define ip6_addr_debug_print_parts(debug, a, b, c, d, e, f, g, h) \ + LWIP_DEBUGF(debug, ("%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F, \ + a, b, c, d, e, f, g, h)) +#define ip6_addr_debug_print(debug, ipaddr) \ + ip6_addr_debug_print_parts(debug, \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0)) +#define ip6_addr_debug_print_val(debug, ipaddr) \ + ip6_addr_debug_print_parts(debug, \ + IP6_ADDR_BLOCK1(&(ipaddr)), \ + IP6_ADDR_BLOCK2(&(ipaddr)), \ + IP6_ADDR_BLOCK3(&(ipaddr)), \ + IP6_ADDR_BLOCK4(&(ipaddr)), \ + IP6_ADDR_BLOCK5(&(ipaddr)), \ + IP6_ADDR_BLOCK6(&(ipaddr)), \ + IP6_ADDR_BLOCK7(&(ipaddr)), \ + IP6_ADDR_BLOCK8(&(ipaddr))) + +#define IP6ADDR_STRLEN_MAX 46 + +int ip6addr_aton(const char *cp, ip6_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ip6addr_ntoa(const ip6_addr_t *addr); +char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); + + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_IP6_ADDR_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/ip6_frag.h b/components/net/lwip-2.0.3/src/include/lwip/ip6_frag.h new file mode 100644 index 0000000000..6be274734b --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/ip6_frag.h @@ -0,0 +1,120 @@ +/** + * @file + * + * IPv6 fragmentation and reassembly. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_FRAG_H +#define LWIP_HDR_IP6_FRAG_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/ip6.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ + +/** IP6_FRAG_COPYHEADER==1: for platforms where sizeof(void*) > 4, this needs to + * be enabled (to not overwrite part of the data). When enabled, the IPv6 header + * is copied instead of referencing it, which gives more room for struct ip6_reass_helper */ +#ifndef IPV6_FRAG_COPYHEADER +#define IPV6_FRAG_COPYHEADER 0 +#endif + +/** The IPv6 reassembly timer interval in milliseconds. */ +#define IP6_REASS_TMR_INTERVAL 1000 + +/* Copy the complete header of the first fragment to struct ip6_reassdata + or just point to its original location in the first pbuf? */ +#if IPV6_FRAG_COPYHEADER +#define IPV6_FRAG_HDRPTR +#define IPV6_FRAG_HDRREF(hdr) (&(hdr)) +#else /* IPV6_FRAG_COPYHEADER */ +#define IPV6_FRAG_HDRPTR * +#define IPV6_FRAG_HDRREF(hdr) (hdr) +#endif /* IPV6_FRAG_COPYHEADER */ + +/** IPv6 reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip6_reassdata { + struct ip6_reassdata *next; + struct pbuf *p; + struct ip6_hdr IPV6_FRAG_HDRPTR iphdr; + u32_t identification; + u16_t datagram_len; + u8_t nexth; + u8_t timer; +}; + +#define ip6_reass_init() /* Compatibility define */ +void ip6_reass_tmr(void); +struct pbuf *ip6_reass(struct pbuf *p); + +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_FRAG /* don't build if not configured for use in lwipopts.h */ + +#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED +#define LWIP_PBUF_CUSTOM_REF_DEFINED +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ + +err_t ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest); + +#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP6_FRAG_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/ip_addr.h b/components/net/lwip-2.0.3/src/include/lwip/ip_addr.h new file mode 100644 index 0000000000..11f65d25bd --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/ip_addr.h @@ -0,0 +1,407 @@ +/** + * @file + * IP address API (common IPv4 and IPv6) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP_ADDR_H +#define LWIP_HDR_IP_ADDR_H + +#include "lwip/opt.h" +#include "lwip/def.h" + +#include "lwip/ip4_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @ingroup ipaddr + * IP address types for use in ip_addr_t.type member. + * @see tcp_new_ip_type(), udp_new_ip_type(), raw_new_ip_type(). + */ +enum lwip_ip_addr_type { + /** IPv4 */ + IPADDR_TYPE_V4 = 0U, + /** IPv6 */ + IPADDR_TYPE_V6 = 6U, + /** IPv4+IPv6 ("dual-stack") */ + IPADDR_TYPE_ANY = 46U +}; + +#if LWIP_IPV4 && LWIP_IPV6 +/** + * @ingroup ipaddr + * A union struct for both IP version's addresses. + * ATTENTION: watch out for its size when adding IPv6 address scope! + */ +typedef struct ip_addr { + union { + ip6_addr_t ip6; + ip4_addr_t ip4; + } u_addr; + /** @ref lwip_ip_addr_type */ + u8_t type; +} ip_addr_t; + +extern const ip_addr_t ip_addr_any_type; + +/** @ingroup ip4addr */ +#define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 } +/** @ingroup ip4addr */ +#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) +/** @ingroup ip6addr */ +#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 } +/** @ingroup ip6addr */ +#define IPADDR6_INIT_HOST(a, b, c, d) { { { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } }, IPADDR_TYPE_V6 } + +/** @ingroup ipaddr */ +#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY) +/** @ingroup ipaddr */ +#define IPADDR_ANY_TYPE_INIT { { { { 0ul, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_ANY } + +/** @ingroup ip4addr */ +#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4) +/** @ingroup ip6addr */ +#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) +/** @ingroup ip4addr */ +#define IP_IS_V4(ipaddr) (((ipaddr) == NULL) || IP_IS_V4_VAL(*(ipaddr))) +/** @ingroup ip6addr */ +#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr))) + +#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) +#define IP_SET_TYPE(ipaddr, iptype) do { if((ipaddr) != NULL) { IP_SET_TYPE_VAL(*(ipaddr), iptype); }}while(0) +#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) + +#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) (IP_GET_TYPE(&pcb->local_ip) == IP_GET_TYPE(ipaddr)) +#define IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr) (IP_IS_ANY_TYPE_VAL(pcb->local_ip) || IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) + +/** @ingroup ip6addr + * Convert generic ip address to specific protocol version + */ +#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) +/** @ingroup ip4addr + * Convert generic ip address to specific protocol version + */ +#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) + +/** @ingroup ip4addr */ +#define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0) +/** @ingroup ip6addr */ +#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0) +/** @ingroup ip6addr */ +#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) + +/** @ingroup ipaddr */ +#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) +/** @ingroup ip6addr */ +#define ip_addr_copy_from_ip6(dest, src) do{ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V6); }while(0) +/** @ingroup ip4addr */ +#define ip_addr_copy_from_ip4(dest, src) do{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V4); }while(0) +/** @ingroup ip4addr */ +#define ip_addr_set_ip4_u32(ipaddr, val) do{if(ipaddr){ip4_addr_set_u32(ip_2_ip4(ipaddr), val); \ + IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ip4addr */ +#define ip_addr_get_ip4_u32(ipaddr) (((ipaddr) && IP_IS_V4(ipaddr)) ? \ + ip4_addr_get_u32(ip_2_ip4(ipaddr)) : 0) +/** @ingroup ipaddr */ +#define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \ + ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \ + ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) +/** @ingroup ipaddr */ +#define ip_addr_set_zero(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) +/** @ingroup ip5addr */ +#define ip_addr_set_zero_ip4(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) +/** @ingroup ip6addr */ +#define ip_addr_set_zero_ip6(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_any(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_loopback(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_loopback(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_loopback(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_hton(dest, src) do{if(IP_IS_V6(src)){ \ + ip6_addr_set_hton(ip_2_ip6(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_hton(ip_2_ip4(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_get_network(target, host, netmask) do{if(IP_IS_V6(host)){ \ + ip4_addr_set_zero(ip_2_ip4(target)); IP_SET_TYPE(target, IPADDR_TYPE_V6); } else { \ + ip4_addr_get_network(ip_2_ip4(target), ip_2_ip4(host), ip_2_ip4(netmask)); IP_SET_TYPE(target, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_netcmp(addr1, addr2, mask) ((IP_IS_V6(addr1) && IP_IS_V6(addr2)) ? \ + 0 : \ + ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) +/** @ingroup ipaddr */ +#define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ + ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ + ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) +/** @ingroup ipaddr */ +#define ip_addr_isany(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isany(ip_2_ip6(ipaddr)) : \ + ip4_addr_isany(ip_2_ip4(ipaddr))) +/** @ingroup ipaddr */ +#define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ + ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \ + ip4_addr_isany_val(*ip_2_ip4(&(ipaddr)))) +/** @ingroup ipaddr */ +#define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ + 0 : \ + ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) +/** @ingroup ipaddr */ +#define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ + ip4_addr_ismulticast(ip_2_ip4(ipaddr))) +/** @ingroup ipaddr */ +#define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ + ip4_addr_isloopback(ip_2_ip4(ipaddr))) +/** @ingroup ipaddr */ +#define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ + ip4_addr_islinklocal(ip_2_ip4(ipaddr))) +#define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ + ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ + ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) +#define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ + ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ + ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) +/** @ingroup ipaddr */ +#define ipaddr_ntoa(addr) (((addr) == NULL) ? "NULL" : \ + ((IP_IS_V6(addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr)))) +/** @ingroup ipaddr */ +#define ipaddr_ntoa_r(addr, buf, buflen) (((addr) == NULL) ? "NULL" : \ + ((IP_IS_V6(addr)) ? ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen) : ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen))) +int ipaddr_aton(const char *cp, ip_addr_t *addr); + +/** @ingroup ipaddr */ +#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX + +/** @ingroup ipaddr */ +#define ip4_2_ipv4_mapped_ipv6(ip6addr, ip4addr) do { \ + (ip6addr)->addr[3] = (ip4addr)->addr; \ + (ip6addr)->addr[2] = PP_HTONL(0x0000FFFFUL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[0] = 0; } while(0); + +/** @ingroup ipaddr */ +#define unmap_ipv4_mapped_ipv6(ip4addr, ip6addr) \ + (ip4addr)->addr = (ip6addr)->addr[3]; + +#define IP46_ADDR_ANY(type) (((type) == IPADDR_TYPE_V6)? IP6_ADDR_ANY : IP4_ADDR_ANY) + +#else /* LWIP_IPV4 && LWIP_IPV6 */ + +#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1 +#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) 1 + +#if LWIP_IPV4 + +typedef ip4_addr_t ip_addr_t; +#define IPADDR4_INIT(u32val) { u32val } +#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) +#define IP_IS_V4_VAL(ipaddr) 1 +#define IP_IS_V6_VAL(ipaddr) 0 +#define IP_IS_V4(ipaddr) 1 +#define IP_IS_V6(ipaddr) 0 +#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4 +#define ip_2_ip4(ipaddr) (ipaddr) +#define IP_ADDR4(ipaddr,a,b,c,d) IP4_ADDR(ipaddr,a,b,c,d) + +#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) +#define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) +#define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) +#define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) +#define ip_addr_set(dest, src) ip4_addr_set(dest, src) +#define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) +#define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) +#define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) +#define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) +#define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) +#define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) +#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) +#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) +#define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) +#define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) +#define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) +#define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) +#define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) +#define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) +#define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) +#define ipaddr_ntoa(ipaddr) ip4addr_ntoa(ipaddr) +#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip4addr_ntoa_r(ipaddr, buf, buflen) +#define ipaddr_aton(cp, addr) ip4addr_aton(cp, addr) + +#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX + +#define IP46_ADDR_ANY(type) (IP4_ADDR_ANY) + +#else /* LWIP_IPV4 */ + +typedef ip6_addr_t ip_addr_t; +#define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } } +#define IPADDR6_INIT_HOST(a, b, c, d) { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } +#define IP_IS_V4_VAL(ipaddr) 0 +#define IP_IS_V6_VAL(ipaddr) 1 +#define IP_IS_V4(ipaddr) 0 +#define IP_IS_V6(ipaddr) 1 +#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6 +#define ip_2_ip6(ipaddr) (ipaddr) +#define IP_ADDR6(ipaddr,i0,i1,i2,i3) IP6_ADDR(ipaddr,i0,i1,i2,i3) +#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) + +#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src) +#define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src) +#define ip_addr_set(dest, src) ip6_addr_set(dest, src) +#define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) +#define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) +#define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) +#define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) +#define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) +#define ip_addr_netcmp(addr1, addr2, mask) 0 +#define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) +#define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) +#define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) +#define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) +#define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) +#define ip_addr_isbroadcast(addr, netif) 0 +#define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) +#define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) +#define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) +#define ipaddr_ntoa(ipaddr) ip6addr_ntoa(ipaddr) +#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip6addr_ntoa_r(ipaddr, buf, buflen) +#define ipaddr_aton(cp, addr) ip6addr_aton(cp, addr) + +#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX + +#define IP46_ADDR_ANY(type) (IP6_ADDR_ANY) + +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#if LWIP_IPV4 + +extern const ip_addr_t ip_addr_any; +extern const ip_addr_t ip_addr_broadcast; + +/** + * @ingroup ip4addr + * Can be used as a fixed/const ip_addr_t + * for the IP wildcard. + * Defined to @ref IP4_ADDR_ANY when IPv4 is enabled. + * Defined to @ref IP6_ADDR_ANY in IPv6 only systems. + * Use this if you can handle IPv4 _AND_ IPv6 addresses. + * Use @ref IP4_ADDR_ANY or @ref IP6_ADDR_ANY when the IP + * type matters. + */ +#define IP_ADDR_ANY IP4_ADDR_ANY +/** + * @ingroup ip4addr + * Can be used as a fixed/const ip_addr_t + * for the IPv4 wildcard and the broadcast address + */ +#define IP4_ADDR_ANY (&ip_addr_any) +/** + * @ingroup ip4addr + * Can be used as a fixed/const ip4_addr_t + * for the wildcard and the broadcast address + */ +#define IP4_ADDR_ANY4 (ip_2_ip4(&ip_addr_any)) + +/** @ingroup ip4addr */ +#define IP_ADDR_BROADCAST (&ip_addr_broadcast) +/** @ingroup ip4addr */ +#define IP4_ADDR_BROADCAST (ip_2_ip4(&ip_addr_broadcast)) + +#endif /* LWIP_IPV4*/ + +#if LWIP_IPV6 + +extern const ip_addr_t ip6_addr_any; + +/** + * @ingroup ip6addr + * IP6_ADDR_ANY can be used as a fixed ip_addr_t + * for the IPv6 wildcard address + */ +#define IP6_ADDR_ANY (&ip6_addr_any) +/** + * @ingroup ip6addr + * IP6_ADDR_ANY6 can be used as a fixed ip6_addr_t + * for the IPv6 wildcard address + */ +#define IP6_ADDR_ANY6 (ip_2_ip6(&ip6_addr_any)) + +#if !LWIP_IPV4 +/** IPv6-only configurations */ +#define IP_ADDR_ANY IP6_ADDR_ANY +#endif /* !LWIP_IPV4 */ + +#endif + +#if LWIP_IPV4 && LWIP_IPV6 +/** @ingroup ipaddr */ +#define IP_ANY_TYPE (&ip_addr_any_type) +#else +#define IP_ANY_TYPE IP_ADDR_ANY +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/mem.h b/components/net/lwip-2.0.3/src/include/lwip/mem.h new file mode 100644 index 0000000000..ff208d25c3 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/mem.h @@ -0,0 +1,82 @@ +/** + * @file + * Heap API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_MEM_H +#define LWIP_HDR_MEM_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MEM_LIBC_MALLOC + +#include "lwip/arch.h" + +typedef size_t mem_size_t; +#define MEM_SIZE_F SZT_F + +#elif MEM_USE_POOLS + +typedef u16_t mem_size_t; +#define MEM_SIZE_F U16_F + +#else + +/* MEM_SIZE would have to be aligned, but using 64000 here instead of + * 65535 leaves some room for alignment... + */ +#if MEM_SIZE > 64000L +typedef u32_t mem_size_t; +#define MEM_SIZE_F U32_F +#else +typedef u16_t mem_size_t; +#define MEM_SIZE_F U16_F +#endif /* MEM_SIZE > 64000 */ +#endif + +void mem_init(void); +void *mem_trim(void *mem, mem_size_t size); +void *mem_malloc(mem_size_t size); +void *mem_calloc(mem_size_t count, mem_size_t size); +void mem_free(void *mem); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEM_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/memp.h b/components/net/lwip-2.0.3/src/include/lwip/memp.h new file mode 100644 index 0000000000..562cd05bff --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/memp.h @@ -0,0 +1,155 @@ +/** + * @file + * Memory pool API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_MEMP_H +#define LWIP_HDR_MEMP_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* run once with empty definition to handle all custom includes in lwippools.h */ +#define LWIP_MEMPOOL(name,num,size,desc) +#include "lwip/priv/memp_std.h" + +/** Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ +typedef enum { +#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, +#include "lwip/priv/memp_std.h" + MEMP_MAX +} memp_t; + +#include "lwip/priv/memp_priv.h" +#include "lwip/stats.h" + +extern const struct memp_desc* const memp_pools[MEMP_MAX]; + +/** + * @ingroup mempool + * Declare prototype for private memory pool if it is used in multiple files + */ +#define LWIP_MEMPOOL_PROTOTYPE(name) extern const struct memp_desc memp_ ## name + +#if MEMP_MEM_MALLOC + +#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \ + LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \ + const struct memp_desc memp_ ## name = { \ + DECLARE_LWIP_MEMPOOL_DESC(desc) \ + LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \ + LWIP_MEM_ALIGN_SIZE(size) \ + }; + +#else /* MEMP_MEM_MALLOC */ + +/** + * @ingroup mempool + * Declare a private memory pool + * Private mempools example: + * .h: only when pool is used in multiple .c files: LWIP_MEMPOOL_PROTOTYPE(my_private_pool); + * .c: + * - in global variables section: LWIP_MEMPOOL_DECLARE(my_private_pool, 10, sizeof(foo), "Some description") + * - call ONCE before using pool (e.g. in some init() function): LWIP_MEMPOOL_INIT(my_private_pool); + * - allocate: void* my_new_mem = LWIP_MEMPOOL_ALLOC(my_private_pool); + * - free: LWIP_MEMPOOL_FREE(my_private_pool, my_new_mem); + * + * To relocate a pool, declare it as extern in cc.h. Example for GCC: + * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_my_private_pool[]; + */ +#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \ + LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_ ## name ## _base, ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))); \ + \ + LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \ + \ + static struct memp *memp_tab_ ## name; \ + \ + const struct memp_desc memp_ ## name = { \ + DECLARE_LWIP_MEMPOOL_DESC(desc) \ + LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \ + LWIP_MEM_ALIGN_SIZE(size), \ + (num), \ + memp_memory_ ## name ## _base, \ + &memp_tab_ ## name \ + }; + +#endif /* MEMP_MEM_MALLOC */ + +/** + * @ingroup mempool + * Initialize a private memory pool + */ +#define LWIP_MEMPOOL_INIT(name) memp_init_pool(&memp_ ## name) +/** + * @ingroup mempool + * Allocate from a private memory pool + */ +#define LWIP_MEMPOOL_ALLOC(name) memp_malloc_pool(&memp_ ## name) +/** + * @ingroup mempool + * Free element from a private memory pool + */ +#define LWIP_MEMPOOL_FREE(name, x) memp_free_pool(&memp_ ## name, (x)) + +#if MEM_USE_POOLS +/** This structure is used to save the pool one element came from. + * This has to be defined here as it is required for pool size calculation. */ +struct memp_malloc_helper +{ + memp_t poolnr; +#if MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) + u16_t size; +#endif /* MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) */ +}; +#endif /* MEM_USE_POOLS */ + +void memp_init(void); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_fn(memp_t type, const char* file, const int line); +#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) +#else +void *memp_malloc(memp_t type); +#endif +void memp_free(memp_t type, void *mem); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEMP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/mld6.h b/components/net/lwip-2.0.3/src/include/lwip/mld6.h new file mode 100644 index 0000000000..7fa0797f27 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/mld6.h @@ -0,0 +1,99 @@ +/** + * @file + * + * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. + * No support for MLDv2. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_MLD6_H +#define LWIP_HDR_MLD6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6_MLD && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** MLD group */ +struct mld_group { + /** next link */ + struct mld_group *next; + /** multicast address */ + ip6_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +#define MLD6_TMR_INTERVAL 100 /* Milliseconds */ + +err_t mld6_stop(struct netif *netif); +void mld6_report_groups(struct netif *netif); +void mld6_tmr(void); +struct mld_group *mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr); +void mld6_input(struct pbuf *p, struct netif *inp); +err_t mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); +err_t mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); +err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); +err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); + +/** @ingroup mld6 + * Get list head of MLD6 groups for netif. + * Note: The allnodes group IP is NOT in the list, since it must always + * be received for correct IPv6 operation. + * @see @ref netif_set_mld_mac_filter() + */ +#define netif_mld6_data(netif) ((struct mld_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6_MLD && LWIP_IPV6 */ + +#endif /* LWIP_HDR_MLD6_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/nd6.h b/components/net/lwip-2.0.3/src/include/lwip/nd6.h new file mode 100644 index 0000000000..8204fa4cce --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/nd6.h @@ -0,0 +1,84 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_ND6_H +#define LWIP_HDR_ND6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** 1 second period */ +#define ND6_TMR_INTERVAL 1000 + +struct pbuf; +struct netif; + +void nd6_tmr(void); +void nd6_input(struct pbuf *p, struct netif *inp); +void nd6_clear_destination_cache(void); +struct netif *nd6_find_route(const ip6_addr_t *ip6addr); +err_t nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp); +u16_t nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif); +#if LWIP_ND6_TCP_REACHABILITY_HINTS +void nd6_reachability_hint(const ip6_addr_t *ip6addr); +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ +void nd6_cleanup_netif(struct netif *netif); +#if LWIP_IPV6_MLD +void nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state); +#endif /* LWIP_IPV6_MLD */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_ND6_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/netbuf.h b/components/net/lwip-2.0.3/src/include/lwip/netbuf.h new file mode 100644 index 0000000000..e6865f80f9 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/netbuf.h @@ -0,0 +1,118 @@ +/** + * @file + * netbuf API (for netconn API) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETBUF_H +#define LWIP_HDR_NETBUF_H + +#include "lwip/opt.h" + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +/* Note: Netconn API is always available when sockets are enabled - + * sockets are implemented on top of them */ + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This netbuf has dest-addr/port set */ +#define NETBUF_FLAG_DESTADDR 0x01 +/** This netbuf includes a checksum */ +#define NETBUF_FLAG_CHKSUM 0x02 + +/** "Network buffer" - contains data and addressing info */ +struct netbuf { + struct pbuf *p, *ptr; + ip_addr_t addr; + u16_t port; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + u8_t flags; +#endif /* LWIP_CHECKSUM_ON_COPY */ + u16_t toport_chksum; +#if LWIP_NETBUF_RECVINFO + ip_addr_t toaddr; +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ +}; + +/* Network buffer functions: */ +struct netbuf * netbuf_new (void); +void netbuf_delete (struct netbuf *buf); +void * netbuf_alloc (struct netbuf *buf, u16_t size); +void netbuf_free (struct netbuf *buf); +err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size); +void netbuf_chain (struct netbuf *head, struct netbuf *tail); + +err_t netbuf_data (struct netbuf *buf, + void **dataptr, u16_t *len); +s8_t netbuf_next (struct netbuf *buf); +void netbuf_first (struct netbuf *buf); + + +#define netbuf_copy_partial(buf, dataptr, len, offset) \ + pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) +#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) +#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) +#define netbuf_len(buf) ((buf)->p->tot_len) +#define netbuf_fromaddr(buf) (&((buf)->addr)) +#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr) +#define netbuf_fromport(buf) ((buf)->port) +#if LWIP_NETBUF_RECVINFO +#define netbuf_destaddr(buf) (&((buf)->toaddr)) +#define netbuf_set_destaddr(buf, destaddr) ip_addr_set(&((buf)->toaddr), destaddr) +#if LWIP_CHECKSUM_ON_COPY +#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0) +#else /* LWIP_CHECKSUM_ON_COPY */ +#define netbuf_destport(buf) ((buf)->toport_chksum) +#endif /* LWIP_CHECKSUM_ON_COPY */ +#endif /* LWIP_NETBUF_RECVINFO */ +#if LWIP_CHECKSUM_ON_COPY +#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \ + (buf)->toport_chksum = chksum; } while(0) +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_NETBUF_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/netdb.h b/components/net/lwip-2.0.3/src/include/lwip/netdb.h new file mode 100644 index 0000000000..d3d15dfac5 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/netdb.h @@ -0,0 +1,150 @@ +/** + * @file + * NETDB API (sockets) + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_NETDB_H +#define LWIP_HDR_NETDB_H + +#include "lwip/opt.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include "lwip/arch.h" +#include "lwip/inet.h" +#include "lwip/sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* some rarely used options */ +#ifndef LWIP_DNS_API_DECLARE_H_ERRNO +#define LWIP_DNS_API_DECLARE_H_ERRNO 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_ERRORS +#define LWIP_DNS_API_DEFINE_ERRORS 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_FLAGS +#define LWIP_DNS_API_DEFINE_FLAGS 1 +#endif + +#ifndef LWIP_DNS_API_DECLARE_STRUCTS +#define LWIP_DNS_API_DECLARE_STRUCTS 1 +#endif + +#if LWIP_DNS_API_DEFINE_ERRORS +/** Errors used by the DNS API functions, h_errno can be one of them */ +#define EAI_NONAME 200 +#define EAI_SERVICE 201 +#define EAI_FAIL 202 +#define EAI_MEMORY 203 +#define EAI_FAMILY 204 + +#define HOST_NOT_FOUND 210 +#define NO_DATA 211 +#define NO_RECOVERY 212 +#define TRY_AGAIN 213 +#endif /* LWIP_DNS_API_DEFINE_ERRORS */ + +#if LWIP_DNS_API_DEFINE_FLAGS +/* input flags for struct addrinfo */ +#define AI_PASSIVE 0x01 +#define AI_CANONNAME 0x02 +#define AI_NUMERICHOST 0x04 +#define AI_NUMERICSERV 0x08 +#define AI_V4MAPPED 0x10 +#define AI_ALL 0x20 +#define AI_ADDRCONFIG 0x40 +#endif /* LWIP_DNS_API_DEFINE_FLAGS */ + +#if LWIP_DNS_API_DECLARE_STRUCTS +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address of socket. */ + char *ai_canonname; /* Canonical name of service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; +#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) + +#if LWIP_DNS_API_DECLARE_H_ERRNO +/* application accessible error code set by the DNS API functions */ +extern int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ + +struct hostent *lwip_gethostbyname(const char *name); +int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); +void lwip_freeaddrinfo(struct addrinfo *ai); +int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + +#if LWIP_COMPAT_SOCKETS +/** @ingroup netdbapi */ +#define gethostbyname(name) lwip_gethostbyname(name) +/** @ingroup netdbapi */ +#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ + lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) +/** @ingroup netdbapi */ +#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo) +/** @ingroup netdbapi */ +#define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS && LWIP_SOCKET */ + +#endif /* LWIP_HDR_NETDB_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/netif.h b/components/net/lwip-2.0.3/src/include/lwip/netif.h new file mode 100644 index 0000000000..67a2d24de8 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/netif.h @@ -0,0 +1,474 @@ +/** + * @file + * netif API (to be used from TCPIP thread) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETIF_H +#define LWIP_HDR_NETIF_H + +#include "lwip/opt.h" + +#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) + +#include "lwip/err.h" + +#include "lwip/ip_addr.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses are expected to be in + * the same byte order as in IP_PCB. */ + +/** Must be the maximum of all used hardware address lengths + across all types of interfaces in use. + This does not have to be changed, normally. */ +#ifndef NETIF_MAX_HWADDR_LEN +#define NETIF_MAX_HWADDR_LEN 6U +#endif + +/** + * @defgroup netif_flags Flags + * @ingroup netif + * @{ + */ + +/** Whether the network interface is 'up'. This is + * a software flag used to control whether this network + * interface is enabled and processes traffic. + * It must be set by the startup code before this netif can be used + * (also for dhcp/autoip). + */ +#define NETIF_FLAG_UP 0x01U +/** If set, the netif has broadcast capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_BROADCAST 0x02U +/** If set, the interface has an active link + * (set by the network interface driver). + * Either set by the netif driver in its init function (if the link + * is up at that time) or at a later point once the link comes up + * (if link detection is supported by the hardware). */ +#define NETIF_FLAG_LINK_UP 0x04U +/** If set, the netif is an ethernet device using ARP. + * Set by the netif driver in its init function. + * Used to check input packet types and use of DHCP. */ +#define NETIF_FLAG_ETHARP 0x08U +/** If set, the netif is an ethernet device. It might not use + * ARP or TCP/IP if it is used for PPPoE only. + */ +#define NETIF_FLAG_ETHERNET 0x10U +/** If set, the netif has IGMP capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_IGMP 0x20U +/** If set, the netif has MLD6 capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_MLD6 0x40U + +/** + * @} + */ + +enum lwip_internal_netif_client_data_index +{ +#if LWIP_DHCP + LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, +#endif +#if LWIP_AUTOIP + LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, +#endif +#if LWIP_IGMP + LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, +#endif +#if LWIP_IPV6_MLD + LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, +#endif + LWIP_NETIF_CLIENT_DATA_INDEX_MAX +}; + +#if LWIP_CHECKSUM_CTRL_PER_NETIF +#define NETIF_CHECKSUM_GEN_IP 0x0001 +#define NETIF_CHECKSUM_GEN_UDP 0x0002 +#define NETIF_CHECKSUM_GEN_TCP 0x0004 +#define NETIF_CHECKSUM_GEN_ICMP 0x0008 +#define NETIF_CHECKSUM_GEN_ICMP6 0x0010 +#define NETIF_CHECKSUM_CHECK_IP 0x0100 +#define NETIF_CHECKSUM_CHECK_UDP 0x0200 +#define NETIF_CHECKSUM_CHECK_TCP 0x0400 +#define NETIF_CHECKSUM_CHECK_ICMP 0x0800 +#define NETIF_CHECKSUM_CHECK_ICMP6 0x1000 +#define NETIF_CHECKSUM_ENABLE_ALL 0xFFFF +#define NETIF_CHECKSUM_DISABLE_ALL 0x0000 +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ + +struct netif; + +/** MAC Filter Actions, these are passed to a netif's igmp_mac_filter or + * mld_mac_filter callback function. */ +enum netif_mac_filter_action { + /** Delete a filter entry */ + NETIF_DEL_MAC_FILTER = 0, + /** Add a filter entry */ + NETIF_ADD_MAC_FILTER = 1 +}; + +/** Function prototype for netif init functions. Set up flags and output/linkoutput + * callback functions in this function. + * + * @param netif The netif to initialize + */ +typedef err_t (*netif_init_fn)(struct netif *netif); +/** Function prototype for netif->input functions. This function is saved as 'input' + * callback function in the netif struct. Call it when a packet has been received. + * + * @param p The received packet, copied into a pbuf + * @param inp The netif which received the packet + */ +typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp); + +#if LWIP_IPV4 +/** Function prototype for netif->output functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'etharp_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IP address to which the packet shall be sent + */ +typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p, + const ip4_addr_t *ipaddr); +#endif /* LWIP_IPV4*/ + +#if LWIP_IPV6 +/** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'ethip6_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IPv6 address to which the packet shall be sent + */ +typedef err_t (*netif_output_ip6_fn)(struct netif *netif, struct pbuf *p, + const ip6_addr_t *ipaddr); +#endif /* LWIP_IPV6 */ + +/** Function prototype for netif->linkoutput functions. Only used for ethernet + * netifs. This function is called by ARP when a packet shall be sent. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (raw ethernet packet) + */ +typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p); +/** Function prototype for netif status- or link-callback functions. */ +typedef void (*netif_status_callback_fn)(struct netif *netif); +#if LWIP_IPV4 && LWIP_IGMP +/** Function prototype for netif igmp_mac_filter functions */ +typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif, + const ip4_addr_t *group, enum netif_mac_filter_action action); +#endif /* LWIP_IPV4 && LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD +/** Function prototype for netif mld_mac_filter functions */ +typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif, + const ip6_addr_t *group, enum netif_mac_filter_action action); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + +#if LWIP_DHCP || LWIP_AUTOIP || LWIP_IGMP || LWIP_IPV6_MLD || (LWIP_NUM_NETIF_CLIENT_DATA > 0) +u8_t netif_alloc_client_data_id(void); +/** @ingroup netif_cd + * Set client data. Obtain ID from netif_alloc_client_data_id(). + */ +#define netif_set_client_data(netif, id, data) netif_get_client_data(netif, id) = (data) +/** @ingroup netif_cd + * Get client data. Obtain ID from netif_alloc_client_data_id(). + */ +#define netif_get_client_data(netif, id) (netif)->client_data[(id)] +#endif /* LWIP_DHCP || LWIP_AUTOIP || (LWIP_NUM_NETIF_CLIENT_DATA > 0) */ + +/** Generic data structure used for all lwIP network interfaces. + * The following fields should be filled in by the initialization + * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ +struct netif { + /** pointer to next in linked list */ + struct netif *next; + +#if LWIP_IPV4 + /** IP address configuration in network byte order */ + ip_addr_t ip_addr; + ip_addr_t netmask; + ip_addr_t gw; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + /** Array of IPv6 addresses for this netif. */ + ip_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES]; + /** The state of each IPv6 address (Tentative, Preferred, etc). + * @see ip6_addr.h */ + u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES]; +#endif /* LWIP_IPV6 */ + /** This function is called by the network device driver + * to pass a packet up the TCP/IP stack. */ + netif_input_fn input; +#if LWIP_IPV4 + /** This function is called by the IP module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. + * For ethernet physical layer, this is usually etharp_output() */ + netif_output_fn output; +#endif /* LWIP_IPV4 */ + /** This function is called by ethernet_output() when it wants + * to send a packet on the interface. This function outputs + * the pbuf as-is on the link medium. */ + netif_linkoutput_fn linkoutput; +#if LWIP_IPV6 + /** This function is called by the IPv6 module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. + * For ethernet physical layer, this is usually ethip6_output() */ + netif_output_ip6_fn output_ip6; +#endif /* LWIP_IPV6 */ +#if LWIP_NETIF_STATUS_CALLBACK + /** This function is called when the netif state is set to up or down + */ + netif_status_callback_fn status_callback; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + /** This function is called when the netif link is set to up or down + */ + netif_status_callback_fn link_callback; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK + /** This function is called when the netif has been removed */ + netif_status_callback_fn remove_callback; +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + /** This field can be set by the device driver and could point + * to state information for the device. */ + void *state; +#ifdef netif_get_client_data + void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; +#endif +#if LWIP_IPV6_AUTOCONFIG + /** is this netif enabled for IPv6 autoconfiguration */ + u8_t ip6_autoconfig_enabled; +#endif /* LWIP_IPV6_AUTOCONFIG */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /** Number of Router Solicitation messages that remain to be sent. */ + u8_t rs_count; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ +#if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ + const char* hostname; +#endif /* LWIP_NETIF_HOSTNAME */ +#if LWIP_CHECKSUM_CTRL_PER_NETIF + u16_t chksum_flags; +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ + /** maximum transfer unit (in bytes) */ + u16_t mtu; + /** number of bytes used in hwaddr */ + u8_t hwaddr_len; + /** link level hardware address of this interface */ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** flags (@see @ref netif_flags) */ + u8_t flags; + /** descriptive abbreviation */ + char name[2]; + /** number of this interface */ + u8_t num; +#if MIB2_STATS + /** link type (from "snmp_ifType" enum from snmp_mib2.h) */ + u8_t link_type; + /** (estimate) link speed */ + u32_t link_speed; + /** timestamp at last change made (up/down) */ + u32_t ts; + /** counters */ + struct stats_mib2_netif_ctrs mib2_counters; +#endif /* MIB2_STATS */ +#if LWIP_IPV4 && LWIP_IGMP + /** This function could be called to add or delete an entry in the multicast + filter table of the ethernet MAC.*/ + netif_igmp_mac_filter_fn igmp_mac_filter; +#endif /* LWIP_IPV4 && LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + /** This function could be called to add or delete an entry in the IPv6 multicast + filter table of the ethernet MAC. */ + netif_mld_mac_filter_fn mld_mac_filter; +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#if LWIP_NETIF_HWADDRHINT + u8_t *addr_hint; +#endif /* LWIP_NETIF_HWADDRHINT */ +#if ENABLE_LOOPBACK + /* List of packets to be queued for ourselves. */ + struct pbuf *loop_first; + struct pbuf *loop_last; +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t loop_cnt_current; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* ENABLE_LOOPBACK */ +}; + +#if LWIP_CHECKSUM_CTRL_PER_NETIF +#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \ + (netif)->chksum_flags = chksumflags; } while(0) +#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0)) +#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) +#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ + +/** The list of network interfaces. */ +extern struct netif *netif_list; +/** The default network interface. */ +extern struct netif *netif_default; + +void netif_init(void); + +struct netif *netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input); +#if LWIP_IPV4 +void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, + const ip4_addr_t *gw); +#endif /* LWIP_IPV4 */ +void netif_remove(struct netif * netif); + +/* Returns a network interface given its name. The name is of the form + "et0", where the first two letters are the "name" field in the + netif structure, and the digit is in the num field in the same + structure. */ +struct netif *netif_find(const char *name); + +void netif_set_default(struct netif *netif); + +#if LWIP_IPV4 +void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr); +void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); +void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); +/** @ingroup netif_ip4 */ +#define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) +/** @ingroup netif_ip4 */ +#define netif_ip4_netmask(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->netmask))) +/** @ingroup netif_ip4 */ +#define netif_ip4_gw(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->gw))) +/** @ingroup netif_ip4 */ +#define netif_ip_addr4(netif) ((const ip_addr_t*)&((netif)->ip_addr)) +/** @ingroup netif_ip4 */ +#define netif_ip_netmask4(netif) ((const ip_addr_t*)&((netif)->netmask)) +/** @ingroup netif_ip4 */ +#define netif_ip_gw4(netif) ((const ip_addr_t*)&((netif)->gw)) +#endif /* LWIP_IPV4 */ + +void netif_set_up(struct netif *netif); +void netif_set_down(struct netif *netif); +/** @ingroup netif + * Ask if an interface is up + */ +#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_STATUS_CALLBACK +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK +void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback); +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +void netif_set_link_up(struct netif *netif); +void netif_set_link_down(struct netif *netif); +/** Ask if a link is up */ +#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_LINK_CALLBACK +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if LWIP_NETIF_HOSTNAME +/** @ingroup netif */ +#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0) +/** @ingroup netif */ +#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL) +#endif /* LWIP_NETIF_HOSTNAME */ + +#if LWIP_IGMP +/** @ingroup netif */ +#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) +#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) +#endif /* LWIP_IGMP */ + +#if LWIP_IPV6 && LWIP_IPV6_MLD +/** @ingroup netif */ +#define netif_set_mld_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->mld_mac_filter = function; }}while(0) +#define netif_get_mld_mac_filter(netif) (((netif) != NULL) ? ((netif)->mld_mac_filter) : NULL) +#define netif_mld_mac_filter(netif, addr, action) do { if((netif) && (netif)->mld_mac_filter) { (netif)->mld_mac_filter((netif), (addr), (action)); }}while(0) +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + +#if ENABLE_LOOPBACK +err_t netif_loop_output(struct netif *netif, struct pbuf *p); +void netif_poll(struct netif *netif); +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +void netif_poll_all(void); +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +err_t netif_input(struct pbuf *p, struct netif *inp); + +#if LWIP_IPV6 +/** @ingroup netif_ip6 */ +#define netif_ip_addr6(netif, i) ((const ip_addr_t*)(&((netif)->ip6_addr[i]))) +/** @ingroup netif_ip6 */ +#define netif_ip6_addr(netif, i) ((const ip6_addr_t*)ip_2_ip6(&((netif)->ip6_addr[i]))) +void netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6); +void netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3); +#define netif_ip6_addr_state(netif, i) ((netif)->ip6_addr_state[i]) +void netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state); +s8_t netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr); +void netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit); +err_t netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx); +#define netif_set_ip6_autoconfig_enabled(netif, action) do { if(netif) { (netif)->ip6_autoconfig_enabled = (action); }}while(0) +#endif /* LWIP_IPV6 */ + +#if LWIP_NETIF_HWADDRHINT +#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint)) +#else /* LWIP_NETIF_HWADDRHINT */ +#define NETIF_SET_HWADDRHINT(netif, hint) +#endif /* LWIP_NETIF_HWADDRHINT */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/netifapi.h b/components/net/lwip-2.0.3/src/include/lwip/netifapi.h new file mode 100644 index 0000000000..8bd2b4f76f --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/netifapi.h @@ -0,0 +1,140 @@ +/** + * @file + * netif API (to be used from non-TCPIP threads) + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ +#ifndef LWIP_HDR_NETIFAPI_H +#define LWIP_HDR_NETIFAPI_H + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/priv/tcpip_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_MPU_COMPATIBLE +#define NETIFAPI_IPADDR_DEF(type, m) type m +#else /* LWIP_MPU_COMPATIBLE */ +#define NETIFAPI_IPADDR_DEF(type, m) const type * m +#endif /* LWIP_MPU_COMPATIBLE */ + +typedef void (*netifapi_void_fn)(struct netif *netif); +typedef err_t (*netifapi_errt_fn)(struct netif *netif); + +struct netifapi_msg { + struct tcpip_api_call_data call; + struct netif *netif; + union { + struct { +#if LWIP_IPV4 + NETIFAPI_IPADDR_DEF(ip4_addr_t, ipaddr); + NETIFAPI_IPADDR_DEF(ip4_addr_t, netmask); + NETIFAPI_IPADDR_DEF(ip4_addr_t, gw); +#endif /* LWIP_IPV4 */ + void *state; + netif_init_fn init; + netif_input_fn input; + } add; + struct { + netifapi_void_fn voidfunc; + netifapi_errt_fn errtfunc; + } common; + } msg; +}; + + +/* API for application */ +err_t netifapi_netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input); + +#if LWIP_IPV4 +err_t netifapi_netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, + const ip4_addr_t *netmask, const ip4_addr_t *gw); +#endif /* LWIP_IPV4*/ + +err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc); + +/** @ingroup netifapi_netif */ +#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL) +/** @ingroup netifapi_netif */ +#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL) +/** @ingroup netifapi_netif */ +#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL) +/** @ingroup netifapi_netif */ +#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) +/** @ingroup netifapi_netif */ +#define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL) +/** @ingroup netifapi_netif */ +#define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL) + +/** + * @defgroup netifapi_dhcp4 DHCPv4 + * @ingroup netifapi + * To be called from non-TCPIP threads + */ +/** @ingroup netifapi_dhcp4 */ +#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) +/** @ingroup netifapi_dhcp4 */ +#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) +/** @ingroup netifapi_dhcp4 */ +#define netifapi_dhcp_inform(n) netifapi_netif_common(n, dhcp_inform, NULL) +/** @ingroup netifapi_dhcp4 */ +#define netifapi_dhcp_renew(n) netifapi_netif_common(n, NULL, dhcp_renew) +/** @ingroup netifapi_dhcp4 */ +#define netifapi_dhcp_release(n) netifapi_netif_common(n, NULL, dhcp_release) + +/** + * @defgroup netifapi_autoip AUTOIP + * @ingroup netifapi + * To be called from non-TCPIP threads + */ +/** @ingroup netifapi_autoip */ +#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) +/** @ingroup netifapi_autoip */ +#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETIF_API */ + +#endif /* LWIP_HDR_NETIFAPI_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/opt.h b/components/net/lwip-2.0.3/src/include/lwip/opt.h new file mode 100644 index 0000000000..fd459af144 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/opt.h @@ -0,0 +1,2876 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * NOTE: || defined __DOXYGEN__ is a workaround for doxygen bug - + * without this, doxygen does not see the actual #define + */ + +#if !defined LWIP_HDR_OPT_H +#define LWIP_HDR_OPT_H + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you don't like! + */ +#include "lwipopts.h" +#include "lwip/debug.h" + +/** + * @defgroup lwip_opts Options (lwipopts.h) + * @ingroup lwip + * + * @defgroup lwip_opts_debug Debugging + * @ingroup lwip_opts + * + * @defgroup lwip_opts_infrastructure Infrastructure + * @ingroup lwip_opts + * + * @defgroup lwip_opts_callback Callback-style APIs + * @ingroup lwip_opts + * + * @defgroup lwip_opts_threadsafe_apis Thread-safe APIs + * @ingroup lwip_opts + */ + + /* + ------------------------------------ + -------------- NO SYS -------------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_nosys NO_SYS + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * NO_SYS==1: Use lwIP without OS-awareness (no thread, semaphores, mutexes or + * mboxes). This means threaded APIs cannot be used (socket, netconn, + * i.e. everything in the 'api' folder), only the callback-style raw API is + * available (and you have to watch out for yourself that you don't access + * lwIP functions/structures from more than one context at a time!) + */ +#if !defined NO_SYS || defined __DOXYGEN__ +#define NO_SYS 0 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_timers Timers + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_TIMERS==0: Drop support for sys_timeout and lwip-internal cyclic timers. + * (the array of lwip-internal cyclic timers is still provided) + * (check NO_SYS_NO_TIMERS for compatibility to old versions) + */ +#if !defined LWIP_TIMERS || defined __DOXYGEN__ +#ifdef NO_SYS_NO_TIMERS +#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) +#else +#define LWIP_TIMERS 1 +#endif +#endif + +/** + * LWIP_TIMERS_CUSTOM==1: Provide your own timer implementation. + * Function prototypes in timeouts.h and the array of lwip-internal cyclic timers + * are still included, but the implementation is not. The following functions + * will be required: sys_timeouts_init(), sys_timeout(), sys_untimeout(), + * sys_timeouts_mbox_fetch() + */ +#if !defined LWIP_TIMERS_CUSTOM || defined __DOXYGEN__ +#define LWIP_TIMERS_CUSTOM 0 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_memcpy memcpy + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#if !defined MEMCPY || defined __DOXYGEN__ +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#if !defined SMEMCPY || defined __DOXYGEN__ +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif +/** + * @} + */ + +/* + ------------------------------------ + ----------- Core locking ----------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_lock Core locking and MPU + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_MPU_COMPATIBLE: enables special memory management mechanism + * which makes lwip able to work on MPU (Memory Protection Unit) system + * by not passing stack-pointers to other threads + * (this decreases performance as memory is allocated from pools instead + * of keeping it on the stack) + */ +#if !defined LWIP_MPU_COMPATIBLE || defined __DOXYGEN__ +#define LWIP_MPU_COMPATIBLE 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING + * Creates a global mutex that is held during TCPIP thread operations. + * Can be locked by client code to perform lwIP operations without changing + * into TCPIP thread using callbacks. See LOCK_TCPIP_CORE() and + * UNLOCK_TCPIP_CORE(). + * Your system should provide mutexes supporting priority inversion to use this. + */ +#if !defined LWIP_TCPIP_CORE_LOCKING || defined __DOXYGEN__ +#define LWIP_TCPIP_CORE_LOCKING 1 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: when LWIP_TCPIP_CORE_LOCKING is enabled, + * this lets tcpip_input() grab the mutex for input packets as well, + * instead of allocating a message and passing it to tcpip_thread. + * + * ATTENTION: this does not work when tcpip_input() is called from + * interrupt context! + */ +#if !defined LWIP_TCPIP_CORE_LOCKING_INPUT || defined __DOXYGEN__ +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * SYS_LIGHTWEIGHT_PROT==1: enable inter-task protection (and task-vs-interrupt + * protection) for certain critical regions during buffer allocation, deallocation + * and memory allocation and deallocation. + * ATTENTION: This is required when using lwIP from more than one context! If + * you disable this, you must be sure what you are doing! + */ +#if !defined SYS_LIGHTWEIGHT_PROT || defined __DOXYGEN__ +#define SYS_LIGHTWEIGHT_PROT 1 +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_mem Heap and memory pools + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#if !defined MEM_LIBC_MALLOC || defined __DOXYGEN__ +#define MEM_LIBC_MALLOC 0 +#endif + +/** + * MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. + * Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution + * speed (heap alloc can be much slower than pool alloc) and usage from interrupts + * (especially if your netif driver allocates PBUF_POOL pbufs for received frames + * from interrupt)! + * ATTENTION: Currently, this uses the heap for ALL pools (also for private pools, + * not only for internal pools defined in memp_std.h)! + */ +#if !defined MEMP_MEM_MALLOC || defined __DOXYGEN__ +#define MEMP_MEM_MALLOC 0 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> \#define MEM_ALIGNMENT 4 + * 2 byte alignment -> \#define MEM_ALIGNMENT 2 + */ +#if !defined MEM_ALIGNMENT || defined __DOXYGEN__ +#define MEM_ALIGNMENT 1 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#if !defined MEM_SIZE || defined __DOXYGEN__ +#define MEM_SIZE 1600 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#if !defined MEMP_OVERFLOW_CHECK || defined __DOXYGEN__ +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#if !defined MEMP_SANITY_CHECK || defined __DOXYGEN__ +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#if !defined MEM_USE_POOLS || defined __DOXYGEN__ +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#if !defined MEM_USE_POOLS_TRY_BIGGER_POOL || defined __DOXYGEN__ +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * include path somewhere. + */ +#if !defined MEMP_USE_CUSTOM_POOLS || defined __DOXYGEN__ +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#if !defined LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT || defined __DOXYGEN__ +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif +/** + * @} + */ + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * @defgroup lwip_opts_memp Internal memory pools + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#if !defined MEMP_NUM_PBUF || defined __DOXYGEN__ +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#if !defined MEMP_NUM_RAW_PCB || defined __DOXYGEN__ +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#if !defined MEMP_NUM_UDP_PCB || defined __DOXYGEN__ +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. + * (requires the LWIP_TCP option) + */ +#if !defined MEMP_NUM_TCP_PCB || defined __DOXYGEN__ +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#if !defined MEMP_NUM_TCP_PCB_LISTEN || defined __DOXYGEN__ +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#if !defined MEMP_NUM_TCP_SEG || defined __DOXYGEN__ +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#if !defined MEMP_NUM_REASSDATA || defined __DOXYGEN__ +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 + * with DMA-enabled MACs where the packet is not yet sent when netif->output + * returns. + */ +#if !defined MEMP_NUM_FRAG_PBUF || defined __DOXYGEN__ +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simultaneously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#if !defined MEMP_NUM_ARP_QUEUE || defined __DOXYGEN__ +#define MEMP_NUM_ARP_QUEUE 30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members at the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#if !defined MEMP_NUM_IGMP_GROUP || defined __DOXYGEN__ +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + */ +#if !defined MEMP_NUM_SYS_TIMEOUT || defined __DOXYGEN__ +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#if !defined MEMP_NUM_NETBUF || defined __DOXYGEN__ +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#if !defined MEMP_NUM_TCPIP_MSG_API || defined __DOXYGEN__ +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#if !defined MEMP_NUM_TCPIP_MSG_INPKT || defined __DOXYGEN__ +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#if !defined MEMP_NUM_NETDB || defined __DOXYGEN__ +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#if !defined MEMP_NUM_LOCALHOSTLIST || defined __DOXYGEN__ +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#if !defined PBUF_POOL_SIZE || defined __DOXYGEN__ +#define PBUF_POOL_SIZE 16 +#endif + +/** MEMP_NUM_API_MSG: the number of concurrently active calls to various + * socket, netconn, and tcpip functions + */ +#if !defined MEMP_NUM_API_MSG || defined __DOXYGEN__ +#define MEMP_NUM_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_DNS_API_MSG: the number of concurrently active calls to netconn_gethostbyname + */ +#if !defined MEMP_NUM_DNS_API_MSG || defined __DOXYGEN__ +#define MEMP_NUM_DNS_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA: the number of concurrently active calls + * to getsockopt/setsockopt + */ +#if !defined MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA || defined __DOXYGEN__ +#define MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_NETIFAPI_MSG: the number of concurrently active calls to the + * netifapi functions + */ +#if !defined MEMP_NUM_NETIFAPI_MSG || defined __DOXYGEN__ +#define MEMP_NUM_NETIFAPI_MSG MEMP_NUM_TCPIP_MSG_API +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_arp ARP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#if !defined LWIP_ARP || defined __DOXYGEN__ +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#if !defined ARP_TABLE_SIZE || defined __DOXYGEN__ +#define ARP_TABLE_SIZE 10 +#endif + +/** the time an ARP entry stays valid after its last update, + * for ARP_TMR_INTERVAL = 1000, this is + * (60 * 5) seconds = 5 minutes. + */ +#if !defined ARP_MAXAGE || defined __DOXYGEN__ +#define ARP_MAXAGE 300 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#if !defined ARP_QUEUEING || defined __DOXYGEN__ +#define ARP_QUEUEING 0 +#endif + +/** The maximum number of packets which may be queued for each + * unresolved address by other network layers. Defaults to 3, 0 means disabled. + * Old packets are dropped, new packets are queued. + */ +#if !defined ARP_QUEUE_LEN || defined __DOXYGEN__ +#define ARP_QUEUE_LEN 3 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving and sending ethernet packets with + * VLAN header. See the description of LWIP_HOOK_VLAN_CHECK and + * LWIP_HOOK_VLAN_SET hooks to check/set VLAN headers. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) + * that returns 1 to accept a packet or 0 to drop a packet. + */ +#if !defined ETHARP_SUPPORT_VLAN || defined __DOXYGEN__ +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support even though ARP might be disabled + */ +#if !defined LWIP_ETHERNET || defined __DOXYGEN__ +#define LWIP_ETHERNET LWIP_ARP +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#if !defined ETH_PAD_SIZE || defined __DOXYGEN__ +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#if !defined ETHARP_SUPPORT_STATIC_ENTRIES || defined __DOXYGEN__ +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + +/** ETHARP_TABLE_MATCH_NETIF==1: Match netif for ARP table entries. + * If disabled, duplicate IP address on multiple netifs are not supported + * (but this should only occur for AutoIP). + */ +#if !defined ETHARP_TABLE_MATCH_NETIF || defined __DOXYGEN__ +#define ETHARP_TABLE_MATCH_NETIF 0 +#endif +/** + * @} + */ + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * @defgroup lwip_opts_ipv4 IPv4 + * @ingroup lwip_opts + * @{ + */ +/** + * LWIP_IPV4==1: Enable IPv4 + */ +#if !defined LWIP_IPV4 || defined __DOXYGEN__ +#define LWIP_IPV4 1 +#endif + +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#if !defined IP_FORWARD || defined __DOXYGEN__ +#define IP_FORWARD 0 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#if !defined IP_REASSEMBLY || defined __DOXYGEN__ +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#if !defined IP_FRAG || defined __DOXYGEN__ +#define IP_FRAG 1 +#endif + +#if !LWIP_IPV4 +/* disable IPv4 extensions when IPv4 is disabled */ +#undef IP_FORWARD +#define IP_FORWARD 0 +#undef IP_REASSEMBLY +#define IP_REASSEMBLY 0 +#undef IP_FRAG +#define IP_FRAG 0 +#endif /* !LWIP_IPV4 */ + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#if !defined IP_OPTIONS_ALLOWED || defined __DOXYGEN__ +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#if !defined IP_REASS_MAXAGE || defined __DOXYGEN__ +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#if !defined IP_REASS_MAX_PBUFS || defined __DOXYGEN__ +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#if !defined IP_DEFAULT_TTL || defined __DOXYGEN__ +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#if !defined IP_SOF_BROADCAST || defined __DOXYGEN__ +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#if !defined IP_SOF_BROADCAST_RECV || defined __DOXYGEN__ +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/** + * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back + * out on the netif where it was received. This should only be used for + * wireless networks. + * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming + * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! + */ +#if !defined IP_FORWARD_ALLOW_TX_ON_RX_NETIF || defined __DOXYGEN__ +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#endif + +/** + * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first + * local TCP/UDP pcb (default==0). This can prevent creating predictable port + * numbers after booting a device. + */ +#if !defined LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS || defined __DOXYGEN__ +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_icmp ICMP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#if !defined LWIP_ICMP || defined __DOXYGEN__ +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#if !defined ICMP_TTL || defined __DOXYGEN__ +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#if !defined LWIP_BROADCAST_PING || defined __DOXYGEN__ +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#if !defined LWIP_MULTICAST_PING || defined __DOXYGEN__ +#define LWIP_MULTICAST_PING 0 +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_raw RAW + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#if !defined LWIP_RAW || defined __DOXYGEN__ +#define LWIP_RAW 0 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#if !defined RAW_TTL || defined __DOXYGEN__ +#define RAW_TTL (IP_DEFAULT_TTL) +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_dhcp DHCP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#if !defined LWIP_DHCP || defined __DOXYGEN__ +#define LWIP_DHCP 0 +#endif +#if !LWIP_IPV4 +/* disable DHCP when IPv4 is disabled */ +#undef LWIP_DHCP +#define LWIP_DHCP 0 +#endif /* !LWIP_IPV4 */ + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#if !defined DHCP_DOES_ARP_CHECK || defined __DOXYGEN__ +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/** + * LWIP_DHCP_CHECK_LINK_UP==1: dhcp_start() only really starts if the netif has + * NETIF_FLAG_LINK_UP set in its flags. As this is only an optimization and + * netif drivers might not set this flag, the default is off. If enabled, + * netif_set_link_up() must be called to continue dhcp starting. + */ +#if !defined LWIP_DHCP_CHECK_LINK_UP +#define LWIP_DHCP_CHECK_LINK_UP 0 +#endif + +/** + * LWIP_DHCP_BOOTP_FILE==1: Store offered_si_addr and boot_file_name. + */ +#if !defined LWIP_DHCP_BOOTP_FILE || defined __DOXYGEN__ +#define LWIP_DHCP_BOOTP_FILE 0 +#endif + +/** + * LWIP_DHCP_GETS_NTP==1: Request NTP servers with discover/select. For each + * response packet, an callback is called, which has to be provided by the port: + * void dhcp_set_ntp_servers(u8_t num_ntp_servers, ip_addr_t* ntp_server_addrs); +*/ +#if !defined LWIP_DHCP_GET_NTP_SRV || defined __DOXYGEN__ +#define LWIP_DHCP_GET_NTP_SRV 0 +#endif + +/** + * The maximum of NTP servers requested + */ +#if !defined LWIP_DHCP_MAX_NTP_SERVERS || defined __DOXYGEN__ +#define LWIP_DHCP_MAX_NTP_SERVERS 1 +#endif + +/** + * LWIP_DHCP_MAX_DNS_SERVERS > 0: Request DNS servers with discover/select. + * DHCP servers received in the response are passed to DNS via @ref dns_setserver() + * (up to the maximum limit defined here). + */ +#if !defined LWIP_DHCP_MAX_DNS_SERVERS || defined __DOXYGEN__ +#define LWIP_DHCP_MAX_DNS_SERVERS DNS_MAX_SERVERS +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_autoip AUTOIP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#if !defined LWIP_AUTOIP || defined __DOXYGEN__ +#define LWIP_AUTOIP 0 +#endif +#if !LWIP_IPV4 +/* disable AUTOIP when IPv4 is disabled */ +#undef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif /* !LWIP_IPV4 */ + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#if !defined LWIP_DHCP_AUTOIP_COOP || defined __DOXYGEN__ +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP (the DHCP client keeps + * running in this case). This can be set as low as 1 to get an AutoIP address + * very quickly, but you should be prepared to handle a changing IP address + * when DHCP overrides AutoIP. + */ +#if !defined LWIP_DHCP_AUTOIP_COOP_TRIES || defined __DOXYGEN__ +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ----- SNMP MIB2 support ----- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_mib2 SNMP MIB2 callbacks + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_MIB2_CALLBACKS==1: Turn on SNMP MIB2 callbacks. + * Turn this on to get callbacks needed to implement MIB2. + * Usually MIB2_STATS should be enabled, too. + */ +#if !defined LWIP_MIB2_CALLBACKS || defined __DOXYGEN__ +#define LWIP_MIB2_CALLBACKS 0 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ----- Multicast/IGMP options ----- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_igmp IGMP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#if !defined LWIP_IGMP || defined __DOXYGEN__ +#define LWIP_IGMP 0 +#endif +#if !LWIP_IPV4 +#undef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/** + * LWIP_MULTICAST_TX_OPTIONS==1: Enable multicast TX support like the socket options + * IP_MULTICAST_TTL/IP_MULTICAST_IF/IP_MULTICAST_LOOP + */ +#if !defined LWIP_MULTICAST_TX_OPTIONS || defined __DOXYGEN__ +#define LWIP_MULTICAST_TX_OPTIONS (LWIP_IGMP && LWIP_UDP) +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_dns DNS + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#if !defined LWIP_DNS || defined __DOXYGEN__ +#define LWIP_DNS 0 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#if !defined DNS_TABLE_SIZE || defined __DOXYGEN__ +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#if !defined DNS_MAX_NAME_LENGTH || defined __DOXYGEN__ +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers + * The first server can be initialized automatically by defining + * DNS_SERVER_ADDRESS(ipaddr), where 'ipaddr' is an 'ip_addr_t*' + */ +#if !defined DNS_MAX_SERVERS || defined __DOXYGEN__ +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#if !defined DNS_DOES_NAME_CHECK || defined __DOXYGEN__ +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** LWIP_DNS_SECURE: controls the security level of the DNS implementation + * Use all DNS security features by default. + * This is overridable but should only be needed by very small targets + * or when using against non standard DNS servers. */ +#if !defined LWIP_DNS_SECURE || defined __DOXYGEN__ +#define LWIP_DNS_SECURE (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) +#endif + +/* A list of DNS security features follows */ +#define LWIP_DNS_SECURE_RAND_XID 1 +#define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2 +#define LWIP_DNS_SECURE_RAND_SRC_PORT 4 + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, you have to define an initializer: + * \#define DNS_LOCAL_HOSTLIST_INIT {DNS_LOCAL_HOSTLIST_ELEM("host_ip4", IPADDR4_INIT_BYTES(1,2,3,4)), \ + * DNS_LOCAL_HOSTLIST_ELEM("host_ip6", IPADDR6_INIT_HOST(123, 234, 345, 456)} + * + * Instead, you can also use an external function: + * \#define DNS_LOOKUP_LOCAL_EXTERN(x) extern err_t my_lookup_function(const char *name, ip_addr_t *addr, u8_t dns_addrtype) + * that looks up the IP address and returns ERR_OK if found (LWIP_DNS_ADDRTYPE_xxx is passed in dns_addrtype). + */ +#if !defined DNS_LOCAL_HOSTLIST || defined __DOXYGEN__ +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#if !defined DNS_LOCAL_HOSTLIST_IS_DYNAMIC || defined __DOXYGEN__ +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/** Set this to 1 to enable querying ".local" names via mDNS + * using a One-Shot Multicast DNS Query */ +#if !defined LWIP_DNS_SUPPORT_MDNS_QUERIES || defined __DOXYGEN__ +#define LWIP_DNS_SUPPORT_MDNS_QUERIES 0 +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_udp UDP + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#if !defined LWIP_UDP || defined __DOXYGEN__ +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#if !defined LWIP_UDPLITE || defined __DOXYGEN__ +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#if !defined UDP_TTL || defined __DOXYGEN__ +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#if !defined LWIP_NETBUF_RECVINFO || defined __DOXYGEN__ +#define LWIP_NETBUF_RECVINFO 0 +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_tcp TCP + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#if !defined LWIP_TCP || defined __DOXYGEN__ +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#if !defined TCP_TTL || defined __DOXYGEN__ +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well. + * ATTENTION: when using TCP_RCV_SCALE, TCP_WND is the total size + * with scaling applied. Maximum window value in the TCP header + * will be TCP_WND >> TCP_RCV_SCALE + */ +#if !defined TCP_WND || defined __DOXYGEN__ +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#if !defined TCP_MAXRTX || defined __DOXYGEN__ +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#if !defined TCP_SYNMAXRTX || defined __DOXYGEN__ +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#if !defined TCP_QUEUE_OOSEQ || defined __DOXYGEN__ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#if !defined TCP_MSS || defined __DOXYGEN__ +#define TCP_MSS 536 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#if !defined TCP_CALCULATE_EFF_SEND_MSS || defined __DOXYGEN__ +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#if !defined TCP_SND_BUF || defined __DOXYGEN__ +#define TCP_SND_BUF (2 * TCP_MSS) +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#if !defined TCP_SND_QUEUELEN || defined __DOXYGEN__ +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#if !defined TCP_SNDLOWAT || defined __DOXYGEN__ +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#if !defined TCP_SNDQUEUELOWAT || defined __DOXYGEN__ +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. + */ +#if !defined TCP_OOSEQ_MAX_BYTES || defined __DOXYGEN__ +#define TCP_OOSEQ_MAX_BYTES 0 +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. + */ +#if !defined TCP_OOSEQ_MAX_PBUFS || defined __DOXYGEN__ +#define TCP_OOSEQ_MAX_PBUFS 0 +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#if !defined TCP_LISTEN_BACKLOG || defined __DOXYGEN__ +#define TCP_LISTEN_BACKLOG 0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#if !defined TCP_DEFAULT_LISTEN_BACKLOG || defined __DOXYGEN__ +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#if !defined TCP_OVERSIZE || defined __DOXYGEN__ +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + * The timestamp option is currently only used to help remote hosts, it is not + * really used locally. Therefore, it is only enabled when a TS option is + * received in the initial SYN packet from a remote host. + */ +#if !defined LWIP_TCP_TIMESTAMPS || defined __DOXYGEN__ +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#if !defined TCP_WND_UPDATE_THRESHOLD || defined __DOXYGEN__ +#define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) || defined __DOXYGEN__ +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#else +#ifndef LWIP_EVENT_API +#define LWIP_EVENT_API 0 +#endif +#ifndef LWIP_CALLBACK_API +#define LWIP_CALLBACK_API 0 +#endif +#endif + +/** + * LWIP_WND_SCALE and TCP_RCV_SCALE: + * Set LWIP_WND_SCALE to 1 to enable window scaling. + * Set TCP_RCV_SCALE to the desired scaling factor (shift count in the + * range of [0..14]). + * When LWIP_WND_SCALE is enabled but TCP_RCV_SCALE is 0, we can use a large + * send window while having a small receive window only. + */ +#if !defined LWIP_WND_SCALE || defined __DOXYGEN__ +#define LWIP_WND_SCALE 0 +#define TCP_RCV_SCALE 0 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_pbuf PBUF + * @ingroup lwip_opts + * @{ + */ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#if !defined PBUF_LINK_HLEN || defined __DOXYGEN__ +#if defined LWIP_HOOK_VLAN_SET && !defined __DOXYGEN__ +#define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) +#else /* LWIP_HOOK_VLAN_SET */ +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif /* LWIP_HOOK_VLAN_SET */ +#endif + +/** + * PBUF_LINK_ENCAPSULATION_HLEN: the number of bytes that should be allocated + * for an additional encapsulation header before ethernet headers (e.g. 802.11) + */ +#if !defined PBUF_LINK_ENCAPSULATION_HLEN || defined __DOXYGEN__ +#define PBUF_LINK_ENCAPSULATION_HLEN 0u +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accommodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#if !defined PBUF_POOL_BUFSIZE || defined __DOXYGEN__ +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) +#endif +/** + * @} + */ + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * @defgroup lwip_opts_netif NETIF + * @ingroup lwip_opts + * @{ + */ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#if !defined LWIP_NETIF_HOSTNAME || defined __DOXYGEN__ +#define LWIP_NETIF_HOSTNAME 0 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#if !defined LWIP_NETIF_API || defined __DOXYGEN__ +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquisition) + */ +#if !defined LWIP_NETIF_STATUS_CALLBACK || defined __DOXYGEN__ +#define LWIP_NETIF_STATUS_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#if !defined LWIP_NETIF_LINK_CALLBACK || defined __DOXYGEN__ +#define LWIP_NETIF_LINK_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called + * when a netif has been removed + */ +#if !defined LWIP_NETIF_REMOVE_CALLBACK || defined __DOXYGEN__ +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#if !defined LWIP_NETIF_HWADDRHINT || defined __DOXYGEN__ +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#if !defined LWIP_NETIF_TX_SINGLE_PBUF || defined __DOXYGEN__ +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/** + * LWIP_NUM_NETIF_CLIENT_DATA: Number of clients that may store + * data in client_data member array of struct netif. + */ +#if !defined LWIP_NUM_NETIF_CLIENT_DATA || defined __DOXYGEN__ +#define LWIP_NUM_NETIF_CLIENT_DATA 0 +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_loop Loopback interface + * @ingroup lwip_opts_netif + * @{ + */ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1). + * This is only needed when no real netifs are available. If at least one other + * netif is available, loopback traffic uses this netif. + */ +#if !defined LWIP_HAVE_LOOPIF || defined __DOXYGEN__ +#define LWIP_HAVE_LOOPIF LWIP_NETIF_LOOPBACK +#endif + +/** + * LWIP_LOOPIF_MULTICAST==1: Support multicast/IGMP on loop interface (127.0.0.1). + */ +#if !defined LWIP_LOOPIF_MULTICAST || defined __DOXYGEN__ +#define LWIP_LOOPIF_MULTICAST 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#if !defined LWIP_NETIF_LOOPBACK || defined __DOXYGEN__ +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#if !defined LWIP_LOOPBACK_MAX_PBUFS || defined __DOXYGEN__ +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#if !defined LWIP_NETIF_LOOPBACK_MULTITHREADING || defined __DOXYGEN__ +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_thread Threading + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#if !defined TCPIP_THREAD_NAME || defined __DOXYGEN__ +#define TCPIP_THREAD_NAME "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined TCPIP_THREAD_STACKSIZE || defined __DOXYGEN__ +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined TCPIP_THREAD_PRIO || defined __DOXYGEN__ +#define TCPIP_THREAD_PRIO 1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#if !defined TCPIP_MBOX_SIZE || defined __DOXYGEN__ +#define TCPIP_MBOX_SIZE 0 +#endif + +/** + * Define this to something that triggers a watchdog. This is called from + * tcpip_thread after processing a message. + */ +#if !defined LWIP_TCPIP_THREAD_ALIVE || defined __DOXYGEN__ +#define LWIP_TCPIP_THREAD_ALIVE() +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#if !defined SLIPIF_THREAD_NAME || defined __DOXYGEN__ +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined SLIPIF_THREAD_STACKSIZE || defined __DOXYGEN__ +#define SLIPIF_THREAD_STACKSIZE 0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined SLIPIF_THREAD_PRIO || defined __DOXYGEN__ +#define SLIPIF_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#if !defined DEFAULT_THREAD_NAME || defined __DOXYGEN__ +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined DEFAULT_THREAD_STACKSIZE || defined __DOXYGEN__ +#define DEFAULT_THREAD_STACKSIZE 0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined DEFAULT_THREAD_PRIO || defined __DOXYGEN__ +#define DEFAULT_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#if !defined DEFAULT_RAW_RECVMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#if !defined DEFAULT_UDP_RECVMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#if !defined DEFAULT_TCP_RECVMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#if !defined DEFAULT_ACCEPTMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_ACCEPTMBOX_SIZE 0 +#endif +/** + * @} + */ + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * @defgroup lwip_opts_netconn Netconn + * @ingroup lwip_opts_threadsafe_apis + * @{ + */ +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#if !defined LWIP_NETCONN || defined __DOXYGEN__ +#define LWIP_NETCONN 1 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout to create + * timers running in tcpip_thread from another thread. + */ +#if !defined LWIP_TCPIP_TIMEOUT || defined __DOXYGEN__ +#define LWIP_TCPIP_TIMEOUT 0 +#endif + +/** LWIP_NETCONN_SEM_PER_THREAD==1: Use one (thread-local) semaphore per + * thread calling socket/netconn functions instead of allocating one + * semaphore per netconn (and per select etc.) + * ATTENTION: a thread-local semaphore for API calls is needed: + * - LWIP_NETCONN_THREAD_SEM_GET() returning a sys_sem_t* + * - LWIP_NETCONN_THREAD_SEM_ALLOC() creating the semaphore + * - LWIP_NETCONN_THREAD_SEM_FREE() freeing the semaphore + * The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup(). + * Ports may call these for threads created with sys_thread_new(). + */ +#if !defined LWIP_NETCONN_SEM_PER_THREAD || defined __DOXYGEN__ +#define LWIP_NETCONN_SEM_PER_THREAD 0 +#endif + +/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread, + * writing from a 2nd thread and closing from a 3rd thread at the same time. + * ATTENTION: This is currently really alpha! Some requirements: + * - LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from + * multiple threads at once + * - sys_mbox_free() has to unblock receive tasks waiting on recvmbox/acceptmbox + * and prevent a task pending on this during/after deletion + */ +#if !defined LWIP_NETCONN_FULLDUPLEX || defined __DOXYGEN__ +#define LWIP_NETCONN_FULLDUPLEX 0 +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_socket Sockets + * @ingroup lwip_opts_threadsafe_apis + * @{ + */ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#if !defined LWIP_SOCKET || defined __DOXYGEN__ +#define LWIP_SOCKET 1 +#endif + +/* LWIP_SOCKET_SET_ERRNO==1: Set errno when socket functions cannot complete + * successfully, as required by POSIX. Default is POSIX-compliant. + */ +#if !defined LWIP_SOCKET_SET_ERRNO || defined __DOXYGEN__ +#define LWIP_SOCKET_SET_ERRNO 1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names through defines. + * LWIP_COMPAT_SOCKETS==2: Same as ==1 but correctly named functions are created. + * While this helps code completion, it might conflict with existing libraries. + * (only used if you use sockets.c) + */ +#if !defined LWIP_COMPAT_SOCKETS || defined __DOXYGEN__ +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#if !defined LWIP_POSIX_SOCKETS_IO_NAMES || defined __DOXYGEN__ +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_SOCKET_OFFSET==n: Increases the file descriptor number created by LwIP with n. + * This can be useful when there are multiple APIs which create file descriptors. + * When they all start with a different offset and you won't make them overlap you can + * re implement read/write/close/ioctl/fnctl to send the requested action to the right + * library (sharing select will need more work though). + */ +#if !defined LWIP_SOCKET_OFFSET || defined __DOXYGEN__ +#define LWIP_SOCKET_OFFSET 0 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#if !defined LWIP_TCP_KEEPALIVE || defined __DOXYGEN__ +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#if !defined LWIP_SO_SNDTIMEO || defined __DOXYGEN__ +#define LWIP_SO_SNDTIMEO 0 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#if !defined LWIP_SO_RCVTIMEO || defined __DOXYGEN__ +#define LWIP_SO_RCVTIMEO 0 +#endif + +/** + * LWIP_SO_SNDRCVTIMEO_NONSTANDARD==1: SO_RCVTIMEO/SO_SNDTIMEO take an int + * (milliseconds, much like winsock does) instead of a struct timeval (default). + */ +#if !defined LWIP_SO_SNDRCVTIMEO_NONSTANDARD || defined __DOXYGEN__ +#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 0 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#if !defined LWIP_SO_RCVBUF || defined __DOXYGEN__ +#define LWIP_SO_RCVBUF 0 +#endif + +/** + * LWIP_SO_LINGER==1: Enable SO_LINGER processing. + */ +#if !defined LWIP_SO_LINGER || defined __DOXYGEN__ +#define LWIP_SO_LINGER 0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#if !defined RECV_BUFSIZE_DEFAULT || defined __DOXYGEN__ +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * By default, TCP socket/netconn close waits 20 seconds max to send the FIN + */ +#if !defined LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT || defined __DOXYGEN__ +#define LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT 20000 +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#if !defined SO_REUSE || defined __DOXYGEN__ +#define SO_REUSE 0 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#if !defined SO_REUSE_RXTOALL || defined __DOXYGEN__ +#define SO_REUSE_RXTOALL 0 +#endif + +/** + * LWIP_FIONREAD_LINUXMODE==0 (default): ioctl/FIONREAD returns the amount of + * pending data in the network buffer. This is the way windows does it. It's + * the default for lwIP since it is smaller. + * LWIP_FIONREAD_LINUXMODE==1: ioctl/FIONREAD returns the size of the next + * pending datagram in bytes. This is the way linux does it. This code is only + * here for compatibility. + */ +#if !defined LWIP_FIONREAD_LINUXMODE || defined __DOXYGEN__ +#define LWIP_FIONREAD_LINUXMODE 0 +#endif +/** + * @} + */ + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * @defgroup lwip_opts_stats Statistics + * @ingroup lwip_opts_debug + * @{ + */ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#if !defined LWIP_STATS || defined __DOXYGEN__ +#define LWIP_STATS 1 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#if !defined LWIP_STATS_DISPLAY || defined __DOXYGEN__ +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#if !defined LINK_STATS || defined __DOXYGEN__ +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#if !defined ETHARP_STATS || defined __DOXYGEN__ +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#if !defined IP_STATS || defined __DOXYGEN__ +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#if !defined IPFRAG_STATS || defined __DOXYGEN__ +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#if !defined ICMP_STATS || defined __DOXYGEN__ +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#if !defined IGMP_STATS || defined __DOXYGEN__ +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#if !defined UDP_STATS || defined __DOXYGEN__ +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#if !defined TCP_STATS || defined __DOXYGEN__ +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#if !defined MEM_STATS || defined __DOXYGEN__ +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#if !defined MEMP_STATS || defined __DOXYGEN__ +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#if !defined SYS_STATS || defined __DOXYGEN__ +#define SYS_STATS (NO_SYS == 0) +#endif + +/** + * IP6_STATS==1: Enable IPv6 stats. + */ +#if !defined IP6_STATS || defined __DOXYGEN__ +#define IP6_STATS (LWIP_IPV6) +#endif + +/** + * ICMP6_STATS==1: Enable ICMP for IPv6 stats. + */ +#if !defined ICMP6_STATS || defined __DOXYGEN__ +#define ICMP6_STATS (LWIP_IPV6 && LWIP_ICMP6) +#endif + +/** + * IP6_FRAG_STATS==1: Enable IPv6 fragmentation stats. + */ +#if !defined IP6_FRAG_STATS || defined __DOXYGEN__ +#define IP6_FRAG_STATS (LWIP_IPV6 && (LWIP_IPV6_FRAG || LWIP_IPV6_REASS)) +#endif + +/** + * MLD6_STATS==1: Enable MLD for IPv6 stats. + */ +#if !defined MLD6_STATS || defined __DOXYGEN__ +#define MLD6_STATS (LWIP_IPV6 && LWIP_IPV6_MLD) +#endif + +/** + * ND6_STATS==1: Enable Neighbor discovery for IPv6 stats. + */ +#if !defined ND6_STATS || defined __DOXYGEN__ +#define ND6_STATS (LWIP_IPV6) +#endif + +/** + * MIB2_STATS==1: Stats for SNMP MIB2. + */ +#if !defined MIB2_STATS || defined __DOXYGEN__ +#define MIB2_STATS 0 +#endif + +#else + +#define LINK_STATS 0 +#define ETHARP_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 +#define IP6_STATS 0 +#define ICMP6_STATS 0 +#define IP6_FRAG_STATS 0 +#define MLD6_STATS 0 +#define ND6_STATS 0 +#define MIB2_STATS 0 + +#endif /* LWIP_STATS */ +/** + * @} + */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * @defgroup lwip_opts_checksum Checksum + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_CHECKSUM_CTRL_PER_NETIF==1: Checksum generation/check can be enabled/disabled + * per netif. + * ATTENTION: if enabled, the CHECKSUM_GEN_* and CHECKSUM_CHECK_* defines must be enabled! + */ +#if !defined LWIP_CHECKSUM_CTRL_PER_NETIF || defined __DOXYGEN__ +#define LWIP_CHECKSUM_CTRL_PER_NETIF 0 +#endif + +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#if !defined CHECKSUM_GEN_IP || defined __DOXYGEN__ +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#if !defined CHECKSUM_GEN_UDP || defined __DOXYGEN__ +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#if !defined CHECKSUM_GEN_TCP || defined __DOXYGEN__ +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. + */ +#if !defined CHECKSUM_GEN_ICMP || defined __DOXYGEN__ +#define CHECKSUM_GEN_ICMP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP6==1: Generate checksums in software for outgoing ICMP6 packets. + */ +#if !defined CHECKSUM_GEN_ICMP6 || defined __DOXYGEN__ +#define CHECKSUM_GEN_ICMP6 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#if !defined CHECKSUM_CHECK_IP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#if !defined CHECKSUM_CHECK_UDP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#if !defined CHECKSUM_CHECK_TCP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * CHECKSUM_CHECK_ICMP==1: Check checksums in software for incoming ICMP packets. + */ +#if !defined CHECKSUM_CHECK_ICMP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_ICMP6==1: Check checksums in software for incoming ICMPv6 packets + */ +#if !defined CHECKSUM_CHECK_ICMP6 || defined __DOXYGEN__ +#define CHECKSUM_CHECK_ICMP6 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#if !defined LWIP_CHECKSUM_ON_COPY || defined __DOXYGEN__ +#define LWIP_CHECKSUM_ON_COPY 0 +#endif +/** + * @} + */ + +/* + --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- +*/ +/** + * @defgroup lwip_opts_ipv6 IPv6 + * @ingroup lwip_opts + * @{ + */ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#if !defined LWIP_IPV6 || defined __DOXYGEN__ +#define LWIP_IPV6 0 +#endif + +/** + * LWIP_IPV6_NUM_ADDRESSES: Number of IPv6 addresses per netif. + */ +#if !defined LWIP_IPV6_NUM_ADDRESSES || defined __DOXYGEN__ +#define LWIP_IPV6_NUM_ADDRESSES 3 +#endif + +/** + * LWIP_IPV6_FORWARD==1: Forward IPv6 packets across netifs + */ +#if !defined LWIP_IPV6_FORWARD || defined __DOXYGEN__ +#define LWIP_IPV6_FORWARD 0 +#endif + +/** + * LWIP_IPV6_FRAG==1: Fragment outgoing IPv6 packets that are too big. + */ +#if !defined LWIP_IPV6_FRAG || defined __DOXYGEN__ +#define LWIP_IPV6_FRAG 0 +#endif + +/** + * LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented + */ +#if !defined LWIP_IPV6_REASS || defined __DOXYGEN__ +#define LWIP_IPV6_REASS (LWIP_IPV6) +#endif + +/** + * LWIP_IPV6_SEND_ROUTER_SOLICIT==1: Send router solicitation messages during + * network startup. + */ +#if !defined LWIP_IPV6_SEND_ROUTER_SOLICIT || defined __DOXYGEN__ +#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 +#endif + +/** + * LWIP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862. + */ +#if !defined LWIP_IPV6_AUTOCONFIG || defined __DOXYGEN__ +#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6) +#endif + +/** + * LWIP_IPV6_DUP_DETECT_ATTEMPTS=[0..7]: Number of duplicate address detection attempts. + */ +#if !defined LWIP_IPV6_DUP_DETECT_ATTEMPTS || defined __DOXYGEN__ +#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_icmp6 ICMP6 + * @ingroup lwip_opts_ipv6 + * @{ + */ +/** + * LWIP_ICMP6==1: Enable ICMPv6 (mandatory per RFC) + */ +#if !defined LWIP_ICMP6 || defined __DOXYGEN__ +#define LWIP_ICMP6 (LWIP_IPV6) +#endif + +/** + * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in + * ICMPv6 error messages. + */ +#if !defined LWIP_ICMP6_DATASIZE || defined __DOXYGEN__ +#define LWIP_ICMP6_DATASIZE 8 +#endif + +/** + * LWIP_ICMP6_HL: default hop limit for ICMPv6 messages + */ +#if !defined LWIP_ICMP6_HL || defined __DOXYGEN__ +#define LWIP_ICMP6_HL 255 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_mld6 Multicast listener discovery + * @ingroup lwip_opts_ipv6 + * @{ + */ +/** + * LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol. + * If LWIP_IPV6 is enabled but this setting is disabled, the MAC layer must + * indiscriminately pass all inbound IPv6 multicast traffic to lwIP. + */ +#if !defined LWIP_IPV6_MLD || defined __DOXYGEN__ +#define LWIP_IPV6_MLD (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast groups that can be joined. + * There must be enough groups so that each netif can join the solicited-node + * multicast group for each of its local addresses, plus one for MDNS if + * applicable, plus any number of groups to be joined on UDP sockets. + */ +#if !defined MEMP_NUM_MLD6_GROUP || defined __DOXYGEN__ +#define MEMP_NUM_MLD6_GROUP 4 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_nd6 Neighbor discovery + * @ingroup lwip_opts_ipv6 + * @{ + */ +/** + * LWIP_ND6_QUEUEING==1: queue outgoing IPv6 packets while MAC address + * is being resolved. + */ +#if !defined LWIP_ND6_QUEUEING || defined __DOXYGEN__ +#define LWIP_ND6_QUEUEING (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_ND6_QUEUE: Max number of IPv6 packets to queue during MAC resolution. + */ +#if !defined MEMP_NUM_ND6_QUEUE || defined __DOXYGEN__ +#define MEMP_NUM_ND6_QUEUE 20 +#endif + +/** + * LWIP_ND6_NUM_NEIGHBORS: Number of entries in IPv6 neighbor cache + */ +#if !defined LWIP_ND6_NUM_NEIGHBORS || defined __DOXYGEN__ +#define LWIP_ND6_NUM_NEIGHBORS 10 +#endif + +/** + * LWIP_ND6_NUM_DESTINATIONS: number of entries in IPv6 destination cache + */ +#if !defined LWIP_ND6_NUM_DESTINATIONS || defined __DOXYGEN__ +#define LWIP_ND6_NUM_DESTINATIONS 10 +#endif + +/** + * LWIP_ND6_NUM_PREFIXES: number of entries in IPv6 on-link prefixes cache + */ +#if !defined LWIP_ND6_NUM_PREFIXES || defined __DOXYGEN__ +#define LWIP_ND6_NUM_PREFIXES 5 +#endif + +/** + * LWIP_ND6_NUM_ROUTERS: number of entries in IPv6 default router cache + */ +#if !defined LWIP_ND6_NUM_ROUTERS || defined __DOXYGEN__ +#define LWIP_ND6_NUM_ROUTERS 3 +#endif + +/** + * LWIP_ND6_MAX_MULTICAST_SOLICIT: max number of multicast solicit messages to send + * (neighbor solicit and router solicit) + */ +#if !defined LWIP_ND6_MAX_MULTICAST_SOLICIT || defined __DOXYGEN__ +#define LWIP_ND6_MAX_MULTICAST_SOLICIT 3 +#endif + +/** + * LWIP_ND6_MAX_UNICAST_SOLICIT: max number of unicast neighbor solicitation messages + * to send during neighbor reachability detection. + */ +#if !defined LWIP_ND6_MAX_UNICAST_SOLICIT || defined __DOXYGEN__ +#define LWIP_ND6_MAX_UNICAST_SOLICIT 3 +#endif + +/** + * Unused: See ND RFC (time in milliseconds). + */ +#if !defined LWIP_ND6_MAX_ANYCAST_DELAY_TIME || defined __DOXYGEN__ +#define LWIP_ND6_MAX_ANYCAST_DELAY_TIME 1000 +#endif + +/** + * Unused: See ND RFC + */ +#if !defined LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT || defined __DOXYGEN__ +#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT 3 +#endif + +/** + * LWIP_ND6_REACHABLE_TIME: default neighbor reachable time (in milliseconds). + * May be updated by router advertisement messages. + */ +#if !defined LWIP_ND6_REACHABLE_TIME || defined __DOXYGEN__ +#define LWIP_ND6_REACHABLE_TIME 30000 +#endif + +/** + * LWIP_ND6_RETRANS_TIMER: default retransmission timer for solicitation messages + */ +#if !defined LWIP_ND6_RETRANS_TIMER || defined __DOXYGEN__ +#define LWIP_ND6_RETRANS_TIMER 1000 +#endif + +/** + * LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation + * message is sent, during neighbor reachability detection. + */ +#if !defined LWIP_ND6_DELAY_FIRST_PROBE_TIME || defined __DOXYGEN__ +#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000 +#endif + +/** + * LWIP_ND6_ALLOW_RA_UPDATES==1: Allow Router Advertisement messages to update + * Reachable time and retransmission timers, and netif MTU. + */ +#if !defined LWIP_ND6_ALLOW_RA_UPDATES || defined __DOXYGEN__ +#define LWIP_ND6_ALLOW_RA_UPDATES 1 +#endif + +/** + * LWIP_ND6_TCP_REACHABILITY_HINTS==1: Allow TCP to provide Neighbor Discovery + * with reachability hints for connected destinations. This helps avoid sending + * unicast neighbor solicitation messages. + */ +#if !defined LWIP_ND6_TCP_REACHABILITY_HINTS || defined __DOXYGEN__ +#define LWIP_ND6_TCP_REACHABILITY_HINTS 1 +#endif + +/** + * LWIP_ND6_RDNSS_MAX_DNS_SERVERS > 0: Use IPv6 Router Advertisement Recursive + * DNS Server Option (as per RFC 6106) to copy a defined maximum number of DNS + * servers to the DNS module. + */ +#if !defined LWIP_ND6_RDNSS_MAX_DNS_SERVERS || defined __DOXYGEN__ +#define LWIP_ND6_RDNSS_MAX_DNS_SERVERS 0 +#endif +/** + * @} + */ + +/** + * LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful address autoconfiguration. + */ +#if !defined LWIP_IPV6_DHCP6 || defined __DOXYGEN__ +#define LWIP_IPV6_DHCP6 0 +#endif + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/** + * @defgroup lwip_opts_hooks Hooks + * @ingroup lwip_opts_infrastructure + * Hooks are undefined by default, define them to a function if you need them. + * @{ + */ + +/** + * LWIP_HOOK_FILENAME: Custom filename to #include in files that provide hooks. + * Declare your hook function prototypes in there, you may also #include all headers + * providing data types that are need in this file. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_FILENAME "path/to/my/lwip_hooks.h" +#endif + +/** + * LWIP_HOOK_TCP_ISN: + * Hook for generation of the Initial Sequence Number (ISN) for a new TCP + * connection. The default lwIP ISN generation algorithm is very basic and may + * allow for TCP spoofing attacks. This hook provides the means to implement + * the standardized ISN generation algorithm from RFC 6528 (see contrib/adons/tcp_isn), + * or any other desired algorithm as a replacement. + * Called from tcp_connect() and tcp_listen_input() when an ISN is needed for + * a new TCP connection, if TCP support (@ref LWIP_TCP) is enabled.\n + * Signature: u32_t my_hook_tcp_isn(const ip_addr_t* local_ip, u16_t local_port, const ip_addr_t* remote_ip, u16_t remote_port); + * - it may be necessary to use "struct ip_addr" (ip4_addr, ip6_addr) instead of "ip_addr_t" in function declarations\n + * Arguments: + * - local_ip: pointer to the local IP address of the connection + * - local_port: local port number of the connection (host-byte order) + * - remote_ip: pointer to the remote IP address of the connection + * - remote_port: remote port number of the connection (host-byte order)\n + * Return value: + * - the 32-bit Initial Sequence Number to use for the new TCP connection. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_TCP_ISN(local_ip, local_port, remote_ip, remote_port) +#endif + +/** + * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): + * - called from ip_input() (IPv4) + * - pbuf: received struct pbuf passed to ip_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP4_INPUT(pbuf, input_netif) +#endif + +/** + * LWIP_HOOK_IP4_ROUTE(dest): + * - called from ip_route() (IPv4) + * - dest: destination IPv4 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip_route() continues as normal. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP4_ROUTE() +#endif + +/** + * LWIP_HOOK_IP4_ROUTE_SRC(dest, src): + * - source-based routing for IPv4 (see LWIP_HOOK_IP4_ROUTE(), src may be NULL) + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP4_ROUTE_SRC(dest, src) +#endif + +/** + * LWIP_HOOK_ETHARP_GET_GW(netif, dest): + * - called from etharp_output() (IPv4) + * - netif: the netif used for sending + * - dest: the destination IPv4 address + * Returns the IPv4 address of the gateway to handle the specified destination + * IPv4 address. If NULL is returned, the netif's default gateway is used. + * The returned address MUST be directly reachable on the specified netif! + * This function is meant to implement advanced IPv4 routing together with + * LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is + * not part of lwIP but can e.g. be hidden in the netif's state argument. +*/ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_ETHARP_GET_GW(netif, dest) +#endif + +/** + * LWIP_HOOK_IP6_INPUT(pbuf, input_netif): + * - called from ip6_input() (IPv6) + * - pbuf: received struct pbuf passed to ip6_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP6_INPUT(pbuf, input_netif) +#endif + +/** + * LWIP_HOOK_IP6_ROUTE(src, dest): + * - called from ip6_route() (IPv6) + * - src: sourc IPv6 address + * - dest: destination IPv6 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip6_route() continues as normal. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP6_ROUTE(src, dest) +#endif + +/** + * LWIP_HOOK_ND6_GET_GW(netif, dest): + * - called from nd6_get_next_hop_entry() (IPv6) + * - netif: the netif used for sending + * - dest: the destination IPv6 address + * Returns the IPv6 address of the next hop to handle the specified destination + * IPv6 address. If NULL is returned, a NDP-discovered router is used instead. + * The returned address MUST be directly reachable on the specified netif! + * This function is meant to implement advanced IPv6 routing together with + * LWIP_HOOK_IP6_ROUTE(). The actual routing/gateway table implementation is + * not part of lwIP but can e.g. be hidden in the netif's state argument. +*/ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_ND6_GET_GW(netif, dest) +#endif + +/** + * LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr): + * - called from ethernet_input() if VLAN support is enabled + * - netif: struct netif on which the packet has been received + * - eth_hdr: struct eth_hdr of the packet + * - vlan_hdr: struct eth_vlan_hdr of the packet + * Return values: + * - 0: Packet must be dropped. + * - != 0: Packet must be accepted. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr) +#endif + +/** + * LWIP_HOOK_VLAN_SET: + * Hook can be used to set prio_vid field of vlan_hdr. If you need to store data + * on per-netif basis to implement this callback, see @ref netif_cd. + * Called from ethernet_output() if VLAN support (@ref ETHARP_SUPPORT_VLAN) is enabled.\n + * Signature: s32_t my_hook_vlan_set(struct netif* netif, struct pbuf* pbuf, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type);\n + * Arguments: + * - netif: struct netif that the packet will be sent through + * - p: struct pbuf packet to be sent + * - src: source eth address + * - dst: destination eth address + * - eth_type: ethernet type to packet to be sent\n + * + * + * Return values: + * - <0: Packet shall not contain VLAN header. + * - 0 <= return value <= 0xFFFF: Packet shall contain VLAN header. Return value is prio_vid in host byte order. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type) +#endif + +/** + * LWIP_HOOK_MEMP_AVAILABLE(memp_t_type): + * - called from memp_free() when a memp pool was empty and an item is now available + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_MEMP_AVAILABLE(memp_t_type) +#endif + +/** + * LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif): + * Called from ethernet_input() when an unknown eth type is encountered. + * Return ERR_OK if packet is accepted, any error code otherwise. + * Payload points to ethernet header! + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif) +#endif +/** + * @} + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * @defgroup lwip_opts_debugmsg Debug messages + * @ingroup lwip_opts_debug + * @{ + */ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + * @see debugging_levels + */ +#if !defined LWIP_DBG_MIN_LEVEL || defined __DOXYGEN__ +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + * @see debugging_levels + */ +#if !defined LWIP_DBG_TYPES_ON || defined __DOXYGEN__ +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#if !defined ETHARP_DEBUG || defined __DOXYGEN__ +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#if !defined NETIF_DEBUG || defined __DOXYGEN__ +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#if !defined PBUF_DEBUG || defined __DOXYGEN__ +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#if !defined API_LIB_DEBUG || defined __DOXYGEN__ +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#if !defined API_MSG_DEBUG || defined __DOXYGEN__ +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#if !defined SOCKETS_DEBUG || defined __DOXYGEN__ +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#if !defined ICMP_DEBUG || defined __DOXYGEN__ +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#if !defined IGMP_DEBUG || defined __DOXYGEN__ +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#if !defined INET_DEBUG || defined __DOXYGEN__ +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#if !defined IP_DEBUG || defined __DOXYGEN__ +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#if !defined IP_REASS_DEBUG || defined __DOXYGEN__ +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#if !defined RAW_DEBUG || defined __DOXYGEN__ +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#if !defined MEM_DEBUG || defined __DOXYGEN__ +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#if !defined MEMP_DEBUG || defined __DOXYGEN__ +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#if !defined SYS_DEBUG || defined __DOXYGEN__ +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#if !defined TIMERS_DEBUG || defined __DOXYGEN__ +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#if !defined TCP_DEBUG || defined __DOXYGEN__ +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#if !defined TCP_INPUT_DEBUG || defined __DOXYGEN__ +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#if !defined TCP_FR_DEBUG || defined __DOXYGEN__ +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#if !defined TCP_RTO_DEBUG || defined __DOXYGEN__ +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#if !defined TCP_CWND_DEBUG || defined __DOXYGEN__ +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#if !defined TCP_WND_DEBUG || defined __DOXYGEN__ +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#if !defined TCP_OUTPUT_DEBUG || defined __DOXYGEN__ +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#if !defined TCP_RST_DEBUG || defined __DOXYGEN__ +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#if !defined TCP_QLEN_DEBUG || defined __DOXYGEN__ +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#if !defined UDP_DEBUG || defined __DOXYGEN__ +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#if !defined TCPIP_DEBUG || defined __DOXYGEN__ +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#if !defined SLIP_DEBUG || defined __DOXYGEN__ +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#if !defined DHCP_DEBUG || defined __DOXYGEN__ +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#if !defined AUTOIP_DEBUG || defined __DOXYGEN__ +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#if !defined DNS_DEBUG || defined __DOXYGEN__ +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP6_DEBUG: Enable debugging for IPv6. + */ +#if !defined IP6_DEBUG || defined __DOXYGEN__ +#define IP6_DEBUG LWIP_DBG_OFF +#endif +/** + * @} + */ + +/* + -------------------------------------------------- + ---------- Performance tracking options ---------- + -------------------------------------------------- +*/ +/** + * @defgroup lwip_opts_perf Performance + * @ingroup lwip_opts_debug + * @{ + */ +/** + * LWIP_PERF: Enable performance testing for lwIP + * (if enabled, arch/perf.h is included) + */ +#if !defined LWIP_PERF || defined __DOXYGEN__ +#define LWIP_PERF 0 +#endif +/** + * @} + */ + +#endif /* LWIP_HDR_OPT_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/pbuf.h b/components/net/lwip-2.0.3/src/include/lwip/pbuf.h new file mode 100644 index 0000000000..90610461ea --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/pbuf.h @@ -0,0 +1,263 @@ +/** + * @file + * pbuf API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_PBUF_H +#define LWIP_HDR_PBUF_H + +#include "lwip/opt.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** LWIP_SUPPORT_CUSTOM_PBUF==1: Custom pbufs behave much like their pbuf type + * but they are allocated by external code (initialised by calling + * pbuf_alloced_custom()) and when pbuf_free gives up their last reference, they + * are freed by calling pbuf_custom->custom_free_function(). + * Currently, the pbuf_custom code is only needed for one specific configuration + * of IP_FRAG, unless required by external driver/application code. */ +#ifndef LWIP_SUPPORT_CUSTOM_PBUF +#define LWIP_SUPPORT_CUSTOM_PBUF ((IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG)) +#endif + +/* @todo: We need a mechanism to prevent wasting memory in every pbuf + (TCP vs. UDP, IPv4 vs. IPv6: UDP/IPv4 packets may waste up to 28 bytes) */ + +#define PBUF_TRANSPORT_HLEN 20 +#if LWIP_IPV6 +#define PBUF_IP_HLEN 40 +#else +#define PBUF_IP_HLEN 20 +#endif + +/** + * @ingroup pbuf + * Enumeration of pbuf layers + */ +typedef enum { + /** Includes spare room for transport layer header, e.g. UDP header. + * Use this if you intend to pass the pbuf to functions like udp_send(). + */ + PBUF_TRANSPORT, + /** Includes spare room for IP header. + * Use this if you intend to pass the pbuf to functions like raw_send(). + */ + PBUF_IP, + /** Includes spare room for link layer header (ethernet header). + * Use this if you intend to pass the pbuf to functions like ethernet_output(). + * @see PBUF_LINK_HLEN + */ + PBUF_LINK, + /** Includes spare room for additional encapsulation header before ethernet + * headers (e.g. 802.11). + * Use this if you intend to pass the pbuf to functions like netif->linkoutput(). + * @see PBUF_LINK_ENCAPSULATION_HLEN + */ + PBUF_RAW_TX, + /** Use this for input packets in a netif driver when calling netif->input() + * in the most common case - ethernet-layer netif driver. */ + PBUF_RAW +} pbuf_layer; + +/** + * @ingroup pbuf + * Enumeration of pbuf types + */ +typedef enum { + /** pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payload + are allocated in one piece of contiguous memory (so the first payload byte + can be calculated from struct pbuf). + pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that might + change in future versions). + This should be used for all OUTGOING packets (TX).*/ + PBUF_RAM, + /** pbuf data is stored in ROM, i.e. struct pbuf and its payload are located in + totally different memory areas. Since it points to ROM, payload does not + have to be copied when queued for transmission. */ + PBUF_ROM, + /** pbuf comes from the pbuf pool. Much like PBUF_ROM but payload might change + so it has to be duplicated when queued before transmitting, depending on + who has a 'ref' to it. */ + PBUF_REF, + /** pbuf payload refers to RAM. This one comes from a pool and should be used + for RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, struct + pbuf and its payload are allocated in one piece of contiguous memory (so + the first payload byte can be calculated from struct pbuf). + Don't use this for TX, if the pool becomes empty e.g. because of TCP queuing, + you are unable to receive TCP acks! */ + PBUF_POOL +} pbuf_type; + + +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x01U +/** indicates this is a custom pbuf: pbuf_free calls pbuf_custom->custom_free_function() + when the last reference is released (plus custom PBUF_RAM cannot be trimmed) */ +#define PBUF_FLAG_IS_CUSTOM 0x02U +/** indicates this pbuf is UDP multicast to be looped back */ +#define PBUF_FLAG_MCASTLOOP 0x04U +/** indicates this pbuf was received as link-level broadcast */ +#define PBUF_FLAG_LLBCAST 0x08U +/** indicates this pbuf was received as link-level multicast */ +#define PBUF_FLAG_LLMCAST 0x10U +/** indicates this pbuf includes a TCP FIN flag */ +#define PBUF_FLAG_TCP_FIN 0x20U + +/** Main packet buffer struct */ +struct pbuf { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + void *payload; + + /** + * total length of this buffer and all next buffers in chain + * belonging to the same packet. + * + * For non-queue packet chains this is the invariant: + * p->tot_len == p->len + (p->next? p->next->tot_len: 0) + */ + u16_t tot_len; + + /** length of this buffer */ + u16_t len; + + /** pbuf_type as u8_t instead of enum to save space */ + u8_t /*pbuf_type*/ type; + + /** misc flags */ + u8_t flags; + + /** + * the reference count always equals the number of pointers + * that refer to this pbuf. This can be pointers from an application, + * the stack itself, or pbuf->next pointers from a chain. + */ + u16_t ref; +}; + + +/** Helper struct for const-correctness only. + * The only meaning of this one is to provide a const payload pointer + * for PBUF_ROM type. + */ +struct pbuf_rom { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + const void *payload; +}; + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Prototype for a function to free a custom pbuf */ +typedef void (*pbuf_free_custom_fn)(struct pbuf *p); + +/** A custom pbuf: like a pbuf, but following a function pointer to free it. */ +struct pbuf_custom { + /** The actual pbuf */ + struct pbuf pbuf; + /** This function is called when pbuf_free deallocates this pbuf(_custom) */ + pbuf_free_custom_fn custom_free_function; +}; +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */ +#ifndef PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_FREE_OOSEQ 1 +#endif /* PBUF_POOL_FREE_OOSEQ */ +#if LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ +extern volatile u8_t pbuf_free_ooseq_pending; +void pbuf_free_ooseq(void); +/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level to check if ooseq pbufs need to be + freed! */ +#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \ + /* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \ + ooseq queued pbufs now */ \ + pbuf_free_ooseq(); }}while(0) +#else /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ */ + /* Otherwise declare an empty PBUF_CHECK_FREE_OOSEQ */ + #define PBUF_CHECK_FREE_OOSEQ() +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ*/ + +/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ +#define pbuf_init() + +struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); +#if LWIP_SUPPORT_CUSTOM_PBUF +struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, + struct pbuf_custom *p, void *payload_mem, + u16_t payload_mem_len); +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ +void pbuf_realloc(struct pbuf *p, u16_t size); +u8_t pbuf_header(struct pbuf *p, s16_t header_size); +u8_t pbuf_header_force(struct pbuf *p, s16_t header_size); +void pbuf_ref(struct pbuf *p); +u8_t pbuf_free(struct pbuf *p); +u16_t pbuf_clen(const struct pbuf *p); +void pbuf_cat(struct pbuf *head, struct pbuf *tail); +void pbuf_chain(struct pbuf *head, struct pbuf *tail); +struct pbuf *pbuf_dechain(struct pbuf *p); +err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from); +u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); +err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset); +struct pbuf *pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset); +struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); +#if LWIP_CHECKSUM_ON_COPY +err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum); +#endif /* LWIP_CHECKSUM_ON_COPY */ +#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE +void pbuf_split_64k(struct pbuf *p, struct pbuf **rest); +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + +u8_t pbuf_get_at(const struct pbuf* p, u16_t offset); +int pbuf_try_get_at(const struct pbuf* p, u16_t offset); +void pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data); +u16_t pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n); +u16_t pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); +u16_t pbuf_strstr(const struct pbuf* p, const char* substr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PBUF_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/priv/api_msg.h b/components/net/lwip-2.0.3/src/include/lwip/priv/api_msg.h new file mode 100644 index 0000000000..f12b8b7d4f --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/priv/api_msg.h @@ -0,0 +1,216 @@ +/** + * @file + * netconn API lwIP internal implementations (do not use in application code) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_API_MSG_H +#define LWIP_HDR_API_MSG_H + +#include "lwip/opt.h" + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +/* Note: Netconn API is always available when sockets are enabled - + * sockets are implemented on top of them */ + +#include "lwip/arch.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/api.h" +#include "lwip/priv/tcpip_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_MPU_COMPATIBLE +#if LWIP_NETCONN_SEM_PER_THREAD +#define API_MSG_M_DEF_SEM(m) *m +#else +#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m) +#endif +#else /* LWIP_MPU_COMPATIBLE */ +#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m) +#endif /* LWIP_MPU_COMPATIBLE */ + +/* For the netconn API, these values are use as a bitmask! */ +#define NETCONN_SHUT_RD 1 +#define NETCONN_SHUT_WR 2 +#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + +/* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +/** This struct includes everything that is necessary to execute a function + for a netconn in another thread context (mainly used to process netconns + in the tcpip_thread context to be thread safe). */ +struct api_msg { + /** The netconn which to process - always needed: it includes the semaphore + which is used to block the application thread until the function finished. */ + struct netconn *conn; + /** The return value of the function executed in tcpip_thread. */ + err_t err; + /** Depending on the executed function, one of these union members is used */ + union { + /** used for lwip_netconn_do_send */ + struct netbuf *b; + /** used for lwip_netconn_do_newconn */ + struct { + u8_t proto; + } n; + /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ + struct { + API_MSG_M_DEF_C(ip_addr_t, ipaddr); + u16_t port; + } bc; + /** used for lwip_netconn_do_getaddr */ + struct { + ip_addr_t API_MSG_M_DEF(ipaddr); + u16_t API_MSG_M_DEF(port); + u8_t local; + } ad; + /** used for lwip_netconn_do_write */ + struct { + const void *dataptr; + size_t len; + u8_t apiflags; +#if LWIP_SO_SNDTIMEO + u32_t time_started; +#endif /* LWIP_SO_SNDTIMEO */ + } w; + /** used for lwip_netconn_do_recv */ + struct { + u32_t len; + } r; +#if LWIP_TCP + /** used for lwip_netconn_do_close (/shutdown) */ + struct { + u8_t shut; +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + u32_t time_started; +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + u8_t polls_left; +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + } sd; +#endif /* LWIP_TCP */ +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) + /** used for lwip_netconn_do_join_leave_group */ + struct { + API_MSG_M_DEF_C(ip_addr_t, multiaddr); + API_MSG_M_DEF_C(ip_addr_t, netif_addr); + enum netconn_igmp join_or_leave; + } jl; +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ +#if TCP_LISTEN_BACKLOG + struct { + u8_t backlog; + } lb; +#endif /* TCP_LISTEN_BACKLOG */ + } msg; +#if LWIP_NETCONN_SEM_PER_THREAD + sys_sem_t* op_completed_sem; +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ +}; + +#if LWIP_NETCONN_SEM_PER_THREAD +#define LWIP_API_MSG_SEM(msg) ((msg)->op_completed_sem) +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define LWIP_API_MSG_SEM(msg) (&(msg)->conn->op_completed) +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + +#if LWIP_DNS +/** As lwip_netconn_do_gethostbyname requires more arguments but doesn't require a netconn, + it has its own struct (to avoid struct api_msg getting bigger than necessary). + lwip_netconn_do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg + (see netconn_gethostbyname). */ +struct dns_api_msg { + /** Hostname to query or dotted IP address string */ +#if LWIP_MPU_COMPATIBLE + char name[DNS_MAX_NAME_LENGTH]; +#else /* LWIP_MPU_COMPATIBLE */ + const char *name; +#endif /* LWIP_MPU_COMPATIBLE */ + /** The resolved address is stored here */ + ip_addr_t API_MSG_M_DEF(addr); +#if LWIP_IPV4 && LWIP_IPV6 + /** Type of resolve call */ + u8_t dns_addrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + /** This semaphore is posted when the name is resolved, the application thread + should wait on it. */ + sys_sem_t API_MSG_M_DEF_SEM(sem); + /** Errors are given back here */ + err_t API_MSG_M_DEF(err); +}; +#endif /* LWIP_DNS */ + +#if LWIP_TCP +extern u8_t netconn_aborted; +#endif /* LWIP_TCP */ + +void lwip_netconn_do_newconn (void *m); +void lwip_netconn_do_delconn (void *m); +void lwip_netconn_do_bind (void *m); +void lwip_netconn_do_connect (void *m); +void lwip_netconn_do_disconnect (void *m); +void lwip_netconn_do_listen (void *m); +void lwip_netconn_do_send (void *m); +void lwip_netconn_do_recv (void *m); +#if TCP_LISTEN_BACKLOG +void lwip_netconn_do_accepted (void *m); +#endif /* TCP_LISTEN_BACKLOG */ +void lwip_netconn_do_write (void *m); +void lwip_netconn_do_getaddr (void *m); +void lwip_netconn_do_close (void *m); +void lwip_netconn_do_shutdown (void *m); +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +void lwip_netconn_do_join_leave_group(void *m); +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +void lwip_netconn_do_gethostbyname(void *arg); +#endif /* LWIP_DNS */ + +struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +void netconn_free(struct netconn *conn); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_API_MSG_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/priv/memp_priv.h b/components/net/lwip-2.0.3/src/include/lwip/priv/memp_priv.h new file mode 100644 index 0000000000..f246061dad --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/priv/memp_priv.h @@ -0,0 +1,183 @@ +/** + * @file + * memory pools lwIP internal implementations (do not use in application code) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_MEMP_PRIV_H +#define LWIP_HDR_MEMP_PRIV_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwip/mem.h" + +#if MEMP_OVERFLOW_CHECK +/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning + * and at the end of each element, initialize them as 0xcd and check + * them later. */ +/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, + * every single element in each pool is checked! + * This is VERY SLOW but also very helpful. */ +/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in + * lwipopts.h to change the amount reserved for checking. */ +#ifndef MEMP_SANITY_REGION_BEFORE +#define MEMP_SANITY_REGION_BEFORE 16 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#if MEMP_SANITY_REGION_BEFORE > 0 +#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) +#else +#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#ifndef MEMP_SANITY_REGION_AFTER +#define MEMP_SANITY_REGION_AFTER 16 +#endif /* MEMP_SANITY_REGION_AFTER*/ +#if MEMP_SANITY_REGION_AFTER > 0 +#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) +#else +#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_AFTER*/ + +/* MEMP_SIZE: save space for struct memp and for sanity check */ +#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) + +#else /* MEMP_OVERFLOW_CHECK */ + +/* No sanity checks + * We don't need to preserve the struct memp while not allocated, so we + * can save a little space and set MEMP_SIZE to 0. + */ +#define MEMP_SIZE 0 +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_OVERFLOW_CHECK */ + +#if !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK +struct memp { + struct memp *next; +#if MEMP_OVERFLOW_CHECK + const char *file; + int line; +#endif /* MEMP_OVERFLOW_CHECK */ +}; +#endif /* !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK */ + +#if MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS +/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ +typedef enum { + /* Get the first (via: + MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ + MEMP_POOL_HELPER_FIRST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START 1 +#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 +#define LWIP_MALLOC_MEMPOOL_END +#include "lwip/priv/memp_std.h" + ) , + /* Get the last (via: + MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ + MEMP_POOL_HELPER_LAST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * +#define LWIP_MALLOC_MEMPOOL_END 1 +#include "lwip/priv/memp_std.h" + ) +} memp_pool_helper_t; + +/* The actual start and stop values are here (cast them over) + We use this helper type and these defines so we can avoid using const memp_t values */ +#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) +#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) +#endif /* MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS */ + +/** Memory pool descriptor */ +struct memp_desc { +#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY + /** Textual description */ + const char *desc; +#endif /* LWIP_DEBUG || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY */ +#if MEMP_STATS + /** Statistics */ + struct stats_mem *stats; +#endif + + /** Element size */ + u16_t size; + +#if !MEMP_MEM_MALLOC + /** Number of elements */ + u16_t num; + + /** Base address */ + u8_t *base; + + /** First free element of each pool. Elements form a linked list. */ + struct memp **tab; +#endif /* MEMP_MEM_MALLOC */ +}; + +#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY +#define DECLARE_LWIP_MEMPOOL_DESC(desc) (desc), +#else +#define DECLARE_LWIP_MEMPOOL_DESC(desc) +#endif + +#if MEMP_STATS +#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name) static struct stats_mem name; +#define LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(name) &name, +#else +#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name) +#define LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(name) +#endif + +void memp_init_pool(const struct memp_desc *desc); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_pool_fn(const struct memp_desc* desc, const char* file, const int line); +#define memp_malloc_pool(d) memp_malloc_pool_fn((d), __FILE__, __LINE__) +#else +void *memp_malloc_pool(const struct memp_desc *desc); +#endif +void memp_free_pool(const struct memp_desc* desc, void *mem); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEMP_PRIV_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/priv/memp_std.h b/components/net/lwip-2.0.3/src/include/lwip/priv/memp_std.h new file mode 100644 index 0000000000..ce9fd50031 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/priv/memp_std.h @@ -0,0 +1,146 @@ +/** + * @file + * lwIP internal memory pools (do not use in application code) + * This file is deliberately included multiple times: once with empty + * definition of LWIP_MEMPOOL() to handle all includes and multiple times + * to build up various lists of mem pools. + */ + +/* + * SETUP: Make sure we define everything we will need. + * + * We have create three types of pools: + * 1) MEMPOOL - standard pools + * 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c + * 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct + * + * If the include'r doesn't require any special treatment of each of the types + * above, then will declare #2 & #3 to be just standard mempools. + */ +#ifndef LWIP_MALLOC_MEMPOOL +/* This treats "malloc pools" just like any other pool. + The pools are a little bigger to provide 'size' as the amount of user data. */ +#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))), "MALLOC_"#size) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL_END +#endif /* LWIP_MALLOC_MEMPOOL */ + +#ifndef LWIP_PBUF_MEMPOOL +/* This treats "pbuf pools" just like any other pool. + * Allocates buffers for a pbuf struct AND a payload size */ +#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc) +#endif /* LWIP_PBUF_MEMPOOL */ + + +/* + * A list of internal pools used by LWIP. + * + * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + */ +#if LWIP_RAW +LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB") +#endif /* LWIP_RAW */ + +#if LWIP_UDP +LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB") +#endif /* LWIP_UDP */ + +#if LWIP_TCP +LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB") +LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") +LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") +#endif /* LWIP_TCP */ + +#if LWIP_IPV4 && IP_REASSEMBLY +LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA") +#endif /* LWIP_IPV4 && IP_REASSEMBLY */ +#if (IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG) +LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF") +#endif /* IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF || (LWIP_IPV6 && LWIP_IPV6_FRAG) */ + +#if LWIP_NETCONN || LWIP_SOCKET +LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") +LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN") +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#if NO_SYS==0 +LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") +#if LWIP_MPU_COMPATIBLE +LWIP_MEMPOOL(API_MSG, MEMP_NUM_API_MSG, sizeof(struct api_msg), "API_MSG") +#if LWIP_DNS +LWIP_MEMPOOL(DNS_API_MSG, MEMP_NUM_DNS_API_MSG, sizeof(struct dns_api_msg), "DNS_API_MSG") +#endif +#if LWIP_SOCKET && !LWIP_TCPIP_CORE_LOCKING +LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA") +#endif +#if LWIP_NETIF_API +LWIP_MEMPOOL(NETIFAPI_MSG, MEMP_NUM_NETIFAPI_MSG, sizeof(struct netifapi_msg), "NETIFAPI_MSG") +#endif +#endif /* LWIP_MPU_COMPATIBLE */ +#if !LWIP_TCPIP_CORE_LOCKING_INPUT +LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") +#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ +#endif /* NO_SYS==0 */ + +#if LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING +LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE") +#endif /* LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING */ + +#if LWIP_IGMP +LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP") +#endif /* LWIP_IGMP */ + +#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM +LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT") +#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ + +#if LWIP_DNS && LWIP_SOCKET +LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB") +#endif /* LWIP_DNS && LWIP_SOCKET */ +#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST") +#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#if LWIP_IPV6 && LWIP_ND6_QUEUEING +LWIP_MEMPOOL(ND6_QUEUE, MEMP_NUM_ND6_QUEUE, sizeof(struct nd6_q_entry), "ND6_QUEUE") +#endif /* LWIP_IPV6 && LWIP_ND6_QUEUEING */ + +#if LWIP_IPV6 && LWIP_IPV6_REASS +LWIP_MEMPOOL(IP6_REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip6_reassdata), "IP6_REASSDATA") +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_MLD +LWIP_MEMPOOL(MLD6_GROUP, MEMP_NUM_MLD6_GROUP, sizeof(struct mld_group), "MLD6_GROUP") +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + + +/* + * A list of pools of pbuf's used by LWIP. + * + * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + * This allocates enough space for the pbuf struct and a payload. + * (Example: pbuf_payload_size=0 allocates only size for the struct) + */ +LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM") +LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL") + + +/* + * Allow for user-defined pools; this must be explicitly set in lwipopts.h + * since the default is to NOT look for lwippools.h + */ +#if MEMP_USE_CUSTOM_POOLS +#include "lwippools.h" +#endif /* MEMP_USE_CUSTOM_POOLS */ + +/* + * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later + * (#undef is ignored for something that is not defined) + */ +#undef LWIP_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL_START +#undef LWIP_MALLOC_MEMPOOL_END +#undef LWIP_PBUF_MEMPOOL diff --git a/components/net/lwip-2.0.3/src/include/lwip/priv/nd6_priv.h b/components/net/lwip-2.0.3/src/include/lwip/priv/nd6_priv.h new file mode 100644 index 0000000000..4bda0b793a --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/priv/nd6_priv.h @@ -0,0 +1,144 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_ND6_PRIV_H +#define LWIP_HDR_ND6_PRIV_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_ND6_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct nd6_q_entry { + struct nd6_q_entry *next; + struct pbuf *p; +}; +#endif /* LWIP_ND6_QUEUEING */ + +/** Struct for tables. */ +struct nd6_neighbor_cache_entry { + ip6_addr_t next_hop_address; + struct netif *netif; + u8_t lladdr[NETIF_MAX_HWADDR_LEN]; + /*u32_t pmtu;*/ +#if LWIP_ND6_QUEUEING + /** Pointer to queue of pending outgoing packets on this entry. */ + struct nd6_q_entry *q; +#else /* LWIP_ND6_QUEUEING */ + /** Pointer to a single pending outgoing packet on this entry. */ + struct pbuf *q; +#endif /* LWIP_ND6_QUEUEING */ + u8_t state; + u8_t isrouter; + union { + u32_t reachable_time; /* in ms since value may originate from network packet */ + u32_t delay_time; /* ticks (ND6_TMR_INTERVAL) */ + u32_t probes_sent; + u32_t stale_time; /* ticks (ND6_TMR_INTERVAL) */ + } counter; +}; + +struct nd6_destination_cache_entry { + ip6_addr_t destination_addr; + ip6_addr_t next_hop_addr; + u16_t pmtu; + u32_t age; +}; + +struct nd6_prefix_list_entry { + ip6_addr_t prefix; + struct netif *netif; + u32_t invalidation_timer; /* in ms since value may originate from network packet */ +#if LWIP_IPV6_AUTOCONFIG + u8_t flags; +#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01 +#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02 +#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04 +#endif /* LWIP_IPV6_AUTOCONFIG */ +}; + +struct nd6_router_list_entry { + struct nd6_neighbor_cache_entry *neighbor_entry; + u32_t invalidation_timer; /* in ms since value may originate from network packet */ + u8_t flags; +}; + +enum nd6_neighbor_cache_entry_state { + ND6_NO_ENTRY = 0, + ND6_INCOMPLETE, + ND6_REACHABLE, + ND6_STALE, + ND6_DELAY, + ND6_PROBE +}; + +/* Router tables. */ +/* @todo make these static? and entries accessible through API? */ +extern struct nd6_neighbor_cache_entry neighbor_cache[]; +extern struct nd6_destination_cache_entry destination_cache[]; +extern struct nd6_prefix_list_entry prefix_list[]; +extern struct nd6_router_list_entry default_router_list[]; + +/* Default values, can be updated by a RA message. */ +extern u32_t reachable_time; +extern u32_t retrans_timer; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_ND6_PRIV_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/priv/tcp_priv.h b/components/net/lwip-2.0.3/src/include/lwip/priv/tcp_priv.h new file mode 100644 index 0000000000..73e8967e47 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/priv/tcp_priv.h @@ -0,0 +1,507 @@ +/** + * @file + * TCP internal implementations (do not use in application code) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCP_PRIV_H +#define LWIP_HDR_TCP_PRIV_H + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/prot/tcp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions for interfacing with TCP: */ + +/* Lower layer interface to TCP: */ +void tcp_init (void); /* Initialize this module. */ +void tcp_tmr (void); /* Must be called every + TCP_TMR_INTERVAL + ms. (Typically 250 ms). */ +/* It is also possible to call these two functions at the right + intervals (instead of calling tcp_tmr()). */ +void tcp_slowtmr (void); +void tcp_fasttmr (void); + +/* Call this from a netif driver (watch out for threading issues!) that has + returned a memory error on transmit and now has free buffers to send more. + This iterates all active pcbs that had an error and tries to call + tcp_output, so use this with care as it might slow down the system. */ +void tcp_txnow (void); + +/* Only used by IP to pass a TCP segment to TCP: */ +void tcp_input (struct pbuf *p, struct netif *inp); +/* Used within the TCP code only: */ +struct tcp_pcb * tcp_alloc (u8_t prio); +void tcp_abandon (struct tcp_pcb *pcb, int reset); +err_t tcp_send_empty_ack(struct tcp_pcb *pcb); +void tcp_rexmit (struct tcp_pcb *pcb); +void tcp_rexmit_rto (struct tcp_pcb *pcb); +void tcp_rexmit_fast (struct tcp_pcb *pcb); +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); +err_t tcp_process_refused_data(struct tcp_pcb *pcb); + +/** + * This is the Nagle algorithm: try to combine user data to send as few TCP + * segments as possible. Only send if + * - no previously transmitted data on the connection remains unacknowledged or + * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or + * - the only unsent segment is at least pcb->mss bytes long (or there is more + * than one unsent segment - with lwIP, this can happen although unsent->len < mss) + * - or if we are in fast-retransmit (TF_INFR) + */ +#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ + ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ + (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ + ((tpcb)->unsent->len >= (tpcb)->mss))) || \ + ((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \ + ) ? 1 : 0) +#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) + + +#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) +#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) +#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) +#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) +/* is b<=a<=c? */ +#if 0 /* see bug #10548 */ +#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) +#endif +#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) + +#ifndef TCP_TMR_INTERVAL +#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVAL +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ +#endif /* TCP_SLOW_INTERVAL */ + +#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ +#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ + +#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ + +#ifndef TCP_MSL +#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ +#endif + +/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ +#ifndef TCP_KEEPIDLE_DEFAULT +#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ +#endif + +#ifndef TCP_KEEPINTVL_DEFAULT +#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ +#endif + +#ifndef TCP_KEEPCNT_DEFAULT +#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ +#endif + +#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ + +#define TCP_TCPLEN(seg) ((seg)->len + (((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0) ? 1U : 0U)) + +/** Flags used on input processing, not on pcb->flags +*/ +#define TF_RESET (u8_t)0x08U /* Connection was reset. */ +#define TF_CLOSED (u8_t)0x10U /* Connection was successfully closed. */ +#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ + + +#if LWIP_EVENT_API + +#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) ret = lwip_tcp_event(arg, (pcb),\ + LWIP_EVENT_ACCEPT, NULL, 0, err) +#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_SENT, NULL, space, ERR_OK) +#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, (p), 0, (err)) +#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, NULL, 0, ERR_OK) +#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_CONNECTED, NULL, 0, (err)) +#define TCP_EVENT_POLL(pcb,ret) do { if ((pcb)->state != SYN_RCVD) { \ + ret = lwip_tcp_event((pcb)->callback_arg, (pcb), LWIP_EVENT_POLL, NULL, 0, ERR_OK); \ + } else { \ + ret = ERR_ARG; } } while(0) +#define TCP_EVENT_ERR(last_state,errf,arg,err) do { if (last_state != SYN_RCVD) { \ + lwip_tcp_event((arg), NULL, LWIP_EVENT_ERR, NULL, 0, (err)); } } while(0) + +#else /* LWIP_EVENT_API */ + +#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) \ + do { \ + if((lpcb)->accept != NULL) \ + (ret) = (lpcb)->accept((arg),(pcb),(err)); \ + else (ret) = ERR_ARG; \ + } while (0) + +#define TCP_EVENT_SENT(pcb,space,ret) \ + do { \ + if((pcb)->sent != NULL) \ + (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_RECV(pcb,p,err,ret) \ + do { \ + if((pcb)->recv != NULL) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ + } else { \ + (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ + } \ + } while (0) + +#define TCP_EVENT_CLOSED(pcb,ret) \ + do { \ + if(((pcb)->recv != NULL)) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ + } else { \ + (ret) = ERR_OK; \ + } \ + } while (0) + +#define TCP_EVENT_CONNECTED(pcb,err,ret) \ + do { \ + if((pcb)->connected != NULL) \ + (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_POLL(pcb,ret) \ + do { \ + if((pcb)->poll != NULL) \ + (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_ERR(last_state,errf,arg,err) \ + do { \ + LWIP_UNUSED_ARG(last_state); \ + if((errf) != NULL) \ + (errf)((arg),(err)); \ + } while (0) + +#endif /* LWIP_EVENT_API */ + +/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ +#if TCP_OVERSIZE && defined(LWIP_DEBUG) +#define TCP_OVERSIZE_DBGCHECK 1 +#else +#define TCP_OVERSIZE_DBGCHECK 0 +#endif + +/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ +#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) + +/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ +struct tcp_seg { + struct tcp_seg *next; /* used when putting segments on a queue */ + struct pbuf *p; /* buffer containing data + TCP header */ + u16_t len; /* the TCP length of this segment */ +#if TCP_OVERSIZE_DBGCHECK + u16_t oversize_left; /* Extra bytes available at the end of the last + pbuf in unsent (used for asserting vs. + tcp_pcb.unsent_oversize only) */ +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + u16_t chksum; + u8_t chksum_swapped; +#endif /* TCP_CHECKSUM_ON_COPY */ + u8_t flags; +#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ +#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ +#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is + checksummed into 'chksum' */ +#define TF_SEG_OPTS_WND_SCALE (u8_t)0x08U /* Include WND SCALE option */ + struct tcp_hdr *tcphdr; /* the TCP header */ +}; + +#define LWIP_TCP_OPT_EOL 0 +#define LWIP_TCP_OPT_NOP 1 +#define LWIP_TCP_OPT_MSS 2 +#define LWIP_TCP_OPT_WS 3 +#define LWIP_TCP_OPT_TS 8 + +#define LWIP_TCP_OPT_LEN_MSS 4 +#if LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_OPT_LEN_TS 10 +#define LWIP_TCP_OPT_LEN_TS_OUT 12 /* aligned for output (includes NOP padding) */ +#else +#define LWIP_TCP_OPT_LEN_TS_OUT 0 +#endif +#if LWIP_WND_SCALE +#define LWIP_TCP_OPT_LEN_WS 3 +#define LWIP_TCP_OPT_LEN_WS_OUT 4 /* aligned for output (includes NOP padding) */ +#else +#define LWIP_TCP_OPT_LEN_WS_OUT 0 +#endif + +#define LWIP_TCP_OPT_LENGTH(flags) \ + (flags & TF_SEG_OPTS_MSS ? LWIP_TCP_OPT_LEN_MSS : 0) + \ + (flags & TF_SEG_OPTS_TS ? LWIP_TCP_OPT_LEN_TS_OUT : 0) + \ + (flags & TF_SEG_OPTS_WND_SCALE ? LWIP_TCP_OPT_LEN_WS_OUT : 0) + +/** This returns a TCP header option for MSS in an u32_t */ +#define TCP_BUILD_MSS_OPTION(mss) lwip_htonl(0x02040000 | ((mss) & 0xFFFF)) + +#if LWIP_WND_SCALE +#define TCPWNDSIZE_F U32_F +#define TCPWND_MAX 0xFFFFFFFFU +#define TCPWND_CHECK16(x) LWIP_ASSERT("window size > 0xFFFF", (x) <= 0xFFFF) +#define TCPWND_MIN16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) +#else /* LWIP_WND_SCALE */ +#define TCPWNDSIZE_F U16_F +#define TCPWND_MAX 0xFFFFU +#define TCPWND_CHECK16(x) +#define TCPWND_MIN16(x) x +#endif /* LWIP_WND_SCALE */ + +/* Global variables: */ +extern struct tcp_pcb *tcp_input_pcb; +extern u32_t tcp_ticks; +extern u8_t tcp_active_pcbs_changed; + +/* The TCP PCB lists. */ +union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ + struct tcp_pcb_listen *listen_pcbs; + struct tcp_pcb *pcbs; +}; +extern struct tcp_pcb *tcp_bound_pcbs; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a + state in which they accept or send + data. */ +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ + +#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 +#define NUM_TCP_PCB_LISTS 4 +extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS]; + +/* Axioms about the above lists: + 1) Every TCP PCB that is not CLOSED is in one of the lists. + 2) A PCB is only in one of the lists. + 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. + 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. +*/ +/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB + with a PCB list or removes a PCB from a list, respectively. */ +#ifndef TCP_DEBUG_PCB_LISTS +#define TCP_DEBUG_PCB_LISTS 0 +#endif +#if TCP_DEBUG_PCB_LISTS +#define TCP_REG(pcbs, npcb) do {\ + struct tcp_pcb *tcp_tmp_pcb; \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ + for (tcp_tmp_pcb = *(pcbs); \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ + } \ + LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ + (npcb)->next = *(pcbs); \ + LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ + *(pcbs) = (npcb); \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + tcp_timer_needed(); \ + } while(0) +#define TCP_RMV(pcbs, npcb) do { \ + struct tcp_pcb *tcp_tmp_pcb; \ + LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ + if(*(pcbs) == (npcb)) { \ + *(pcbs) = (*pcbs)->next; \ + } else for (tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + (npcb)->next = NULL; \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ + } while(0) + +#else /* LWIP_DEBUG */ + +#define TCP_REG(pcbs, npcb) \ + do { \ + (npcb)->next = *pcbs; \ + *(pcbs) = (npcb); \ + tcp_timer_needed(); \ + } while (0) + +#define TCP_RMV(pcbs, npcb) \ + do { \ + if(*(pcbs) == (npcb)) { \ + (*(pcbs)) = (*pcbs)->next; \ + } \ + else { \ + struct tcp_pcb *tcp_tmp_pcb; \ + for (tcp_tmp_pcb = *pcbs; \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + } \ + (npcb)->next = NULL; \ + } while(0) + +#endif /* LWIP_DEBUG */ + +#define TCP_REG_ACTIVE(npcb) \ + do { \ + TCP_REG(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_RMV_ACTIVE(npcb) \ + do { \ + TCP_RMV(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_PCB_REMOVE_ACTIVE(pcb) \ + do { \ + tcp_pcb_remove(&tcp_active_pcbs, pcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + + +/* Internal functions: */ +struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); +void tcp_pcb_purge(struct tcp_pcb *pcb); +void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); + +void tcp_segs_free(struct tcp_seg *seg); +void tcp_seg_free(struct tcp_seg *seg); +struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); + +#define tcp_ack(pcb) \ + do { \ + if((pcb)->flags & TF_ACK_DELAY) { \ + (pcb)->flags &= ~TF_ACK_DELAY; \ + (pcb)->flags |= TF_ACK_NOW; \ + } \ + else { \ + (pcb)->flags |= TF_ACK_DELAY; \ + } \ + } while (0) + +#define tcp_ack_now(pcb) \ + do { \ + (pcb)->flags |= TF_ACK_NOW; \ + } while (0) + +err_t tcp_send_fin(struct tcp_pcb *pcb); +err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags); + +void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); + +void tcp_rst(u32_t seqno, u32_t ackno, + const ip_addr_t *local_ip, const ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port); + +u32_t tcp_next_iss(struct tcp_pcb *pcb); + +err_t tcp_keepalive(struct tcp_pcb *pcb); +err_t tcp_zero_window_probe(struct tcp_pcb *pcb); +void tcp_trigger_input_pcb_close(void); + +#if TCP_CALCULATE_EFF_SEND_MSS +u16_t tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest +#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING + , const ip_addr_t *src +#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ + ); +#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING +#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest, src) +#else /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ +#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest) +#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +#if LWIP_CALLBACK_API +err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); +#endif /* LWIP_CALLBACK_API */ + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +void tcp_debug_print(struct tcp_hdr *tcphdr); +void tcp_debug_print_flags(u8_t flags); +void tcp_debug_print_state(enum tcp_state s); +void tcp_debug_print_pcbs(void); +s16_t tcp_pcbs_sane(void); +#else +# define tcp_debug_print(tcphdr) +# define tcp_debug_print_flags(flags) +# define tcp_debug_print_state(s) +# define tcp_debug_print_pcbs() +# define tcp_pcbs_sane() 1 +#endif /* TCP_DEBUG */ + +/** External function (implemented in timers.c), called when TCP detects + * that a timer is needed (i.e. active- or time-wait-pcb found). */ +void tcp_timer_needed(void); + +void tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* LWIP_HDR_TCP_PRIV_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/priv/tcpip_priv.h b/components/net/lwip-2.0.3/src/include/lwip/priv/tcpip_priv.h new file mode 100644 index 0000000000..630efb1402 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/priv/tcpip_priv.h @@ -0,0 +1,160 @@ +/** + * @file + * TCPIP API internal implementations (do not use in application code) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCPIP_PRIV_H +#define LWIP_HDR_TCPIP_PRIV_H + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcpip.h" +#include "lwip/sys.h" +#include "lwip/timeouts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct pbuf; +struct netif; + +#if LWIP_MPU_COMPATIBLE +#define API_VAR_REF(name) (*(name)) +#define API_VAR_DECLARE(type, name) type * name +#define API_VAR_ALLOC(type, pool, name, errorval) do { \ + name = (type *)memp_malloc(pool); \ + if (name == NULL) { \ + return errorval; \ + } \ + } while(0) +#define API_VAR_ALLOC_POOL(type, pool, name, errorval) do { \ + name = (type *)LWIP_MEMPOOL_ALLOC(pool); \ + if (name == NULL) { \ + return errorval; \ + } \ + } while(0) +#define API_VAR_FREE(pool, name) memp_free(pool, name) +#define API_VAR_FREE_POOL(pool, name) LWIP_MEMPOOL_FREE(pool, name) +#define API_EXPR_REF(expr) (&(expr)) +#if LWIP_NETCONN_SEM_PER_THREAD +#define API_EXPR_REF_SEM(expr) (expr) +#else +#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr) +#endif +#define API_EXPR_DEREF(expr) expr +#define API_MSG_M_DEF(m) m +#define API_MSG_M_DEF_C(t, m) t m +#else /* LWIP_MPU_COMPATIBLE */ +#define API_VAR_REF(name) name +#define API_VAR_DECLARE(type, name) type name +#define API_VAR_ALLOC(type, pool, name, errorval) +#define API_VAR_ALLOC_POOL(type, pool, name, errorval) +#define API_VAR_FREE(pool, name) +#define API_VAR_FREE_POOL(pool, name) +#define API_EXPR_REF(expr) expr +#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr) +#define API_EXPR_DEREF(expr) (*(expr)) +#define API_MSG_M_DEF(m) *m +#define API_MSG_M_DEF_C(t, m) const t * m +#endif /* LWIP_MPU_COMPATIBLE */ + +err_t tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem); + +struct tcpip_api_call_data +{ +#if !LWIP_TCPIP_CORE_LOCKING + err_t err; +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_t sem; +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ +#else /* !LWIP_TCPIP_CORE_LOCKING */ + u8_t dummy; /* avoid empty struct :-( */ +#endif /* !LWIP_TCPIP_CORE_LOCKING */ +}; +typedef err_t (*tcpip_api_call_fn)(struct tcpip_api_call_data* call); +err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call); + +enum tcpip_msg_type { + TCPIP_MSG_API, + TCPIP_MSG_API_CALL, + TCPIP_MSG_INPKT, +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS + TCPIP_MSG_TIMEOUT, + TCPIP_MSG_UNTIMEOUT, +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ + TCPIP_MSG_CALLBACK, + TCPIP_MSG_CALLBACK_STATIC +}; + +struct tcpip_msg { + enum tcpip_msg_type type; + union { + struct { + tcpip_callback_fn function; + void* msg; + } api_msg; + struct { + tcpip_api_call_fn function; + struct tcpip_api_call_data *arg; + sys_sem_t *sem; + } api_call; + struct { + struct pbuf *p; + struct netif *netif; + netif_input_fn input_fn; + } inp; + struct { + tcpip_callback_fn function; + void *ctx; + } cb; +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS + struct { + u32_t msecs; + sys_timeout_handler h; + void *arg; + } tmo; +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ + } msg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* LWIP_HDR_TCPIP_PRIV_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/autoip.h b/components/net/lwip-2.0.3/src/include/lwip/prot/autoip.h new file mode 100644 index 0000000000..fd3af8a9fc --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/autoip.h @@ -0,0 +1,78 @@ +/** + * @file + * AutoIP protocol definitions + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + */ + +#ifndef LWIP_HDR_PROT_AUTOIP_H +#define LWIP_HDR_PROT_AUTOIP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* 169.254.0.0 */ +#define AUTOIP_NET 0xA9FE0000 +/* 169.254.1.0 */ +#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) +/* 169.254.254.255 */ +#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) + +/* RFC 3927 Constants */ +#define PROBE_WAIT 1 /* second (initial random delay) */ +#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ +#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ +#define PROBE_NUM 3 /* (number of probe packets) */ +#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ +#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ +#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ +#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ +#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ +#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ + +/* AutoIP client states */ +typedef enum { + AUTOIP_STATE_OFF = 0, + AUTOIP_STATE_PROBING = 1, + AUTOIP_STATE_ANNOUNCING = 2, + AUTOIP_STATE_BOUND = 3 +} autoip_state_enum_t; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_AUTOIP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/dhcp.h b/components/net/lwip-2.0.3/src/include/lwip/prot/dhcp.h new file mode 100644 index 0000000000..112953cb8b --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/dhcp.h @@ -0,0 +1,183 @@ +/** + * @file + * DHCP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + */ +#ifndef LWIP_HDR_PROT_DHCP_H +#define LWIP_HDR_PROT_DHCP_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 + + + /* DHCP message item offsets and length */ +#define DHCP_CHADDR_LEN 16U +#define DHCP_SNAME_OFS 44U +#define DHCP_SNAME_LEN 64U +#define DHCP_FILE_OFS 108U +#define DHCP_FILE_LEN 128U +#define DHCP_MSG_LEN 236U +#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4U) /* 4 byte: cookie */ + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** minimum set of fields of any DHCP message */ +struct dhcp_msg +{ + PACK_STRUCT_FLD_8(u8_t op); + PACK_STRUCT_FLD_8(u8_t htype); + PACK_STRUCT_FLD_8(u8_t hlen); + PACK_STRUCT_FLD_8(u8_t hops); + PACK_STRUCT_FIELD(u32_t xid); + PACK_STRUCT_FIELD(u16_t secs); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FLD_S(ip4_addr_p_t ciaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t yiaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t siaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t giaddr); + PACK_STRUCT_FLD_8(u8_t chaddr[DHCP_CHADDR_LEN]); + PACK_STRUCT_FLD_8(u8_t sname[DHCP_SNAME_LEN]); + PACK_STRUCT_FLD_8(u8_t file[DHCP_FILE_LEN]); + PACK_STRUCT_FIELD(u32_t cookie); +#define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +# undef DHCP_OPTIONS_LEN +#endif +/** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCP_OPTIONS_LEN)) +/** set this to be sufficient for your options in outgoing DHCP msgs */ +# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN +#endif + PACK_STRUCT_FLD_8(u8_t options[DHCP_OPTIONS_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +/* DHCP client states */ +typedef enum { + DHCP_STATE_OFF = 0, + DHCP_STATE_REQUESTING = 1, + DHCP_STATE_INIT = 2, + DHCP_STATE_REBOOTING = 3, + DHCP_STATE_REBINDING = 4, + DHCP_STATE_RENEWING = 5, + DHCP_STATE_SELECTING = 6, + DHCP_STATE_INFORMING = 7, + DHCP_STATE_CHECKING = 8, + DHCP_STATE_PERMANENT = 9, /* not yet implemented */ + DHCP_STATE_BOUND = 10, + DHCP_STATE_RELEASING = 11, /* not yet implemented */ + DHCP_STATE_BACKING_OFF = 12 +} dhcp_state_enum_t; + +/* DHCP op codes */ +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/* DHCP message types */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/** DHCP hardware type, currently only ethernet is supported */ +#define DHCP_HTYPE_ETH 1 + +#define DHCP_MAGIC_COOKIE 0x63825363UL + +/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ + +/* BootP options */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_HOSTNAME 12 +#define DHCP_OPTION_IP_TTL 23 +#define DHCP_OPTION_MTU 26 +#define DHCP_OPTION_BROADCAST 28 +#define DHCP_OPTION_TCP_TTL 37 +#define DHCP_OPTION_NTP 42 +#define DHCP_OPTION_END 255 + +/* DHCP options */ +#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ +#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ +#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ + +#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ +#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 + +#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ + +#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ +#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 + +#define DHCP_OPTION_T1 58 /* T1 renewal time */ +#define DHCP_OPTION_T2 59 /* T2 rebinding time */ +#define DHCP_OPTION_US 60 +#define DHCP_OPTION_CLIENT_ID 61 +#define DHCP_OPTION_TFTP_SERVERNAME 66 +#define DHCP_OPTION_BOOTFILE 67 + +/* possible combinations of overloading the file and sname fields with options */ +#define DHCP_OVERLOAD_NONE 0 +#define DHCP_OVERLOAD_FILE 1 +#define DHCP_OVERLOAD_SNAME 2 +#define DHCP_OVERLOAD_SNAME_FILE 3 + + +#ifdef __cplusplus +} +#endif + +#endif /*LWIP_HDR_PROT_DHCP_H*/ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/dns.h b/components/net/lwip-2.0.3/src/include/lwip/prot/dns.h new file mode 100644 index 0000000000..94782d6e9c --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/dns.h @@ -0,0 +1,140 @@ +/** + * @file + * DNS - host name to IP address resolver. + */ + +/* + * Port to lwIP from uIP + * by Jim Pettinato April 2007 + * + * security fixes and more by Simon Goldschmidt + * + * uIP version Copyright (c) 2002-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LWIP_HDR_PROT_DNS_H +#define LWIP_HDR_PROT_DNS_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** DNS server port address */ +#ifndef DNS_SERVER_PORT +#define DNS_SERVER_PORT 53 +#endif + +/* DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A 1 /* a host address */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS 11 /* a well known service description */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ +#define DNS_RRTYPE_HINFO 13 /* host information */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ +#define DNS_RRTYPE_MX 15 /* mail exchange */ +#define DNS_RRTYPE_TXT 16 /* text strings */ +#define DNS_RRTYPE_AAAA 28 /* IPv6 address */ +#define DNS_RRTYPE_SRV 33 /* service location */ +#define DNS_RRTYPE_ANY 255 /* any type */ + +/* DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH 3 /* the CHAOS class */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_ANY 255 /* any class */ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ + +/* DNS protocol flags */ +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + +#define DNS_HDR_GET_OPCODE(hdr) ((((hdr)->flags1) >> 3) & 0xF) + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** DNS message header */ +struct dns_hdr { + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FLD_8(u8_t flags1); + PACK_STRUCT_FLD_8(u8_t flags2); + PACK_STRUCT_FIELD(u16_t numquestions); + PACK_STRUCT_FIELD(u16_t numanswers); + PACK_STRUCT_FIELD(u16_t numauthrr); + PACK_STRUCT_FIELD(u16_t numextrarr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define SIZEOF_DNS_HDR 12 + + +/* Multicast DNS definitions */ + +/** UDP port for multicast DNS queries */ +#ifndef DNS_MQUERY_PORT +#define DNS_MQUERY_PORT 5353 +#endif + +/* IPv4 group for multicast DNS queries: 224.0.0.251 */ +#ifndef DNS_MQUERY_IPV4_GROUP_INIT +#define DNS_MQUERY_IPV4_GROUP_INIT IPADDR4_INIT_BYTES(224,0,0,251) +#endif + +/* IPv6 group for multicast DNS queries: FF02::FB */ +#ifndef DNS_MQUERY_IPV6_GROUP_INIT +#define DNS_MQUERY_IPV6_GROUP_INIT IPADDR6_INIT_HOST(0xFF020000,0,0,0xFB) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_DNS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/etharp.h b/components/net/lwip-2.0.3/src/include/lwip/prot/etharp.h new file mode 100644 index 0000000000..ec78305b82 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/etharp.h @@ -0,0 +1,91 @@ +/** + * @file + * ARP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ETHARP_H +#define LWIP_HDR_PROT_ETHARP_H + +#include "lwip/arch.h" +#include "lwip/prot/ethernet.h" +#include "lwip/ip4_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETHARP_HWADDR_LEN +#define ETHARP_HWADDR_LEN ETH_HWADDR_LEN +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** the ARP message, see RFC 826 ("Packet format") */ +struct etharp_hdr { + PACK_STRUCT_FIELD(u16_t hwtype); + PACK_STRUCT_FIELD(u16_t proto); + PACK_STRUCT_FLD_8(u8_t hwlen); + PACK_STRUCT_FLD_8(u8_t protolen); + PACK_STRUCT_FIELD(u16_t opcode); + PACK_STRUCT_FLD_S(struct eth_addr shwaddr); + PACK_STRUCT_FLD_S(struct ip4_addr2 sipaddr); + PACK_STRUCT_FLD_S(struct eth_addr dhwaddr); + PACK_STRUCT_FLD_S(struct ip4_addr2 dipaddr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETHARP_HDR 28 + +/* ARP hwtype values */ +enum etharp_hwtype { + HWTYPE_ETHERNET = 1 + /* others not used */ +}; + +/* ARP message types (opcodes) */ +enum etharp_opcode { + ARP_REQUEST = 1, + ARP_REPLY = 2 +}; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ETHARP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/ethernet.h b/components/net/lwip-2.0.3/src/include/lwip/prot/ethernet.h new file mode 100644 index 0000000000..fae4570479 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/ethernet.h @@ -0,0 +1,172 @@ +/** + * @file + * Ethernet protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ETHERNET_H +#define LWIP_HDR_PROT_ETHERNET_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETH_HWADDR_LEN +#ifdef ETHARP_HWADDR_LEN +#define ETH_HWADDR_LEN ETHARP_HWADDR_LEN /* compatibility mode */ +#else +#define ETH_HWADDR_LEN 6 +#endif +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_addr { + PACK_STRUCT_FLD_8(u8_t addr[ETH_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** Ethernet header */ +struct eth_hdr { +#if ETH_PAD_SIZE + PACK_STRUCT_FLD_8(u8_t padding[ETH_PAD_SIZE]); +#endif + PACK_STRUCT_FLD_S(struct eth_addr dest); + PACK_STRUCT_FLD_S(struct eth_addr src); + PACK_STRUCT_FIELD(u16_t type); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** VLAN header inserted between ethernet header and payload + * if 'type' in ethernet header is ETHTYPE_VLAN. + * See IEEE802.Q */ +struct eth_vlan_hdr { + PACK_STRUCT_FIELD(u16_t prio_vid); + PACK_STRUCT_FIELD(u16_t tpid); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_VLAN_HDR 4 +#define VLAN_ID(vlan_hdr) (lwip_htons((vlan_hdr)->prio_vid) & 0xFFF) + +/** + * @ingroup ethernet + * A list of often ethtypes (although lwIP does not use all of them): */ +enum eth_type { + /** Internet protocol v4 */ + ETHTYPE_IP = 0x0800U, + /** Address resolution protocol */ + ETHTYPE_ARP = 0x0806U, + /** Wake on lan */ + ETHTYPE_WOL = 0x0842U, + /** RARP */ + ETHTYPE_RARP = 0x8035U, + /** Virtual local area network */ + ETHTYPE_VLAN = 0x8100U, + /** Internet protocol v6 */ + ETHTYPE_IPV6 = 0x86DDU, + /** PPP Over Ethernet Discovery Stage */ + ETHTYPE_PPPOEDISC = 0x8863U, + /** PPP Over Ethernet Session Stage */ + ETHTYPE_PPPOE = 0x8864U, + /** Jumbo Frames */ + ETHTYPE_JUMBO = 0x8870U, + /** EAPOL, EAP over LAN */ + ETHTYPE_EAPOL = 0x888EU, + /** Process field network */ + ETHTYPE_PROFINET = 0x8892U, + /** Ethernet for control automation technology */ + ETHTYPE_ETHERCAT = 0x88A4U, + /** Link layer discovery protocol */ + ETHTYPE_LLDP = 0x88CCU, + /** Serial real-time communication system */ + ETHTYPE_SERCOS = 0x88CDU, + /** Media redundancy protocol */ + ETHTYPE_MRP = 0x88E3U, + /** Precision time protocol */ + ETHTYPE_PTP = 0x88F7U, + /** Q-in-Q, 802.1ad */ + ETHTYPE_QINQ = 0x9100U, +}; + +/** The 24-bit IANA IPv4-multicast OUI is 01-00-5e: */ +#define LL_IP4_MULTICAST_ADDR_0 0x01 +#define LL_IP4_MULTICAST_ADDR_1 0x00 +#define LL_IP4_MULTICAST_ADDR_2 0x5e + +/** IPv6 multicast uses this prefix */ +#define LL_IP6_MULTICAST_ADDR_0 0x33 +#define LL_IP6_MULTICAST_ADDR_1 0x33 + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables + * or known to be 32-bit aligned within the protocol header. */ +#ifndef ETHADDR32_COPY +#define ETHADDR32_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) +#endif + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local + * variables and known to be 16-bit aligned within the protocol header. */ +#ifndef ETHADDR16_COPY +#define ETHADDR16_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) +#endif + +#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ETHERNET_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/icmp.h b/components/net/lwip-2.0.3/src/include/lwip/prot/icmp.h new file mode 100644 index 0000000000..7d19385c72 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/icmp.h @@ -0,0 +1,91 @@ +/** + * @file + * ICMP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ICMP_H +#define LWIP_HDR_PROT_ICMP_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP_ER 0 /* echo reply */ +#define ICMP_DUR 3 /* destination unreachable */ +#define ICMP_SQ 4 /* source quench */ +#define ICMP_RD 5 /* redirect */ +#define ICMP_ECHO 8 /* echo */ +#define ICMP_TE 11 /* time exceeded */ +#define ICMP_PP 12 /* parameter problem */ +#define ICMP_TS 13 /* timestamp */ +#define ICMP_TSR 14 /* timestamp reply */ +#define ICMP_IRQ 15 /* information request */ +#define ICMP_IR 16 /* information reply */ +#define ICMP_AM 17 /* address mask request */ +#define ICMP_AMR 18 /* address mask reply */ + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + * is split to two u16_t like ICMP echo needs it. + * This header is also used for other ICMP types that do not + * use the data part. + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Compatibility defines, old versions used to combine type and code to an u16_t */ +#define ICMPH_TYPE(hdr) ((hdr)->type) +#define ICMPH_CODE(hdr) ((hdr)->code) +#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) +#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ICMP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/icmp6.h b/components/net/lwip-2.0.3/src/include/lwip/prot/icmp6.h new file mode 100644 index 0000000000..3461120421 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/icmp6.h @@ -0,0 +1,170 @@ +/** + * @file + * ICMP6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ICMP6_H +#define LWIP_HDR_PROT_ICMP6_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** ICMP type */ +enum icmp6_type { + /** Destination unreachable */ + ICMP6_TYPE_DUR = 1, + /** Packet too big */ + ICMP6_TYPE_PTB = 2, + /** Time exceeded */ + ICMP6_TYPE_TE = 3, + /** Parameter problem */ + ICMP6_TYPE_PP = 4, + /** Private experimentation */ + ICMP6_TYPE_PE1 = 100, + /** Private experimentation */ + ICMP6_TYPE_PE2 = 101, + /** Reserved for expansion of error messages */ + ICMP6_TYPE_RSV_ERR = 127, + + /** Echo request */ + ICMP6_TYPE_EREQ = 128, + /** Echo reply */ + ICMP6_TYPE_EREP = 129, + /** Multicast listener query */ + ICMP6_TYPE_MLQ = 130, + /** Multicast listener report */ + ICMP6_TYPE_MLR = 131, + /** Multicast listener done */ + ICMP6_TYPE_MLD = 132, + /** Router solicitation */ + ICMP6_TYPE_RS = 133, + /** Router advertisement */ + ICMP6_TYPE_RA = 134, + /** Neighbor solicitation */ + ICMP6_TYPE_NS = 135, + /** Neighbor advertisement */ + ICMP6_TYPE_NA = 136, + /** Redirect */ + ICMP6_TYPE_RD = 137, + /** Multicast router advertisement */ + ICMP6_TYPE_MRA = 151, + /** Multicast router solicitation */ + ICMP6_TYPE_MRS = 152, + /** Multicast router termination */ + ICMP6_TYPE_MRT = 153, + /** Private experimentation */ + ICMP6_TYPE_PE3 = 200, + /** Private experimentation */ + ICMP6_TYPE_PE4 = 201, + /** Reserved for expansion of informational messages */ + ICMP6_TYPE_RSV_INF = 255 +}; + +/** ICMP destination unreachable codes */ +enum icmp6_dur_code { + /** No route to destination */ + ICMP6_DUR_NO_ROUTE = 0, + /** Communication with destination administratively prohibited */ + ICMP6_DUR_PROHIBITED = 1, + /** Beyond scope of source address */ + ICMP6_DUR_SCOPE = 2, + /** Address unreachable */ + ICMP6_DUR_ADDRESS = 3, + /** Port unreachable */ + ICMP6_DUR_PORT = 4, + /** Source address failed ingress/egress policy */ + ICMP6_DUR_POLICY = 5, + /** Reject route to destination */ + ICMP6_DUR_REJECT_ROUTE = 6 +}; + +/** ICMP time exceeded codes */ +enum icmp6_te_code { + /** Hop limit exceeded in transit */ + ICMP6_TE_HL = 0, + /** Fragment reassembly time exceeded */ + ICMP6_TE_FRAG = 1 +}; + +/** ICMP parameter code */ +enum icmp6_pp_code { + /** Erroneous header field encountered */ + ICMP6_PP_FIELD = 0, + /** Unrecognized next header type encountered */ + ICMP6_PP_HEADER = 1, + /** Unrecognized IPv6 option encountered */ + ICMP6_PP_OPTION = 2 +}; + +/** This is the standard ICMP6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t data); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** This is the ICMP6 header adapted for echo req/resp. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_echo_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ICMP6_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/igmp.h b/components/net/lwip-2.0.3/src/include/lwip/prot/igmp.h new file mode 100644 index 0000000000..d60cb31ee7 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/igmp.h @@ -0,0 +1,90 @@ +/** + * @file + * IGMP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IGMP_H +#define LWIP_HDR_PROT_IGMP_H + +#include "lwip/arch.h" +#include "lwip/ip4_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * IGMP constants + */ +#define IGMP_TTL 1 +#define IGMP_MINLEN 8 +#define ROUTER_ALERT 0x9404U +#define ROUTER_ALERTLEN 4 + +/* + * IGMP message types, including version number. + */ +#define IGMP_MEMB_QUERY 0x11 /* Membership query */ +#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ +#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ +#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ + +/* Group membership states */ +#define IGMP_GROUP_NON_MEMBER 0 +#define IGMP_GROUP_DELAYING_MEMBER 1 +#define IGMP_GROUP_IDLE_MEMBER 2 + +/** + * IGMP packet format. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct igmp_msg { + PACK_STRUCT_FLD_8(u8_t igmp_msgtype); + PACK_STRUCT_FLD_8(u8_t igmp_maxresp); + PACK_STRUCT_FIELD(u16_t igmp_checksum); + PACK_STRUCT_FLD_S(ip4_addr_p_t igmp_group_address); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_IGMP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/ip.h b/components/net/lwip-2.0.3/src/include/lwip/prot/ip.h new file mode 100644 index 0000000000..bbfae36752 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/ip.h @@ -0,0 +1,51 @@ +/** + * @file + * IP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IP_H +#define LWIP_HDR_PROT_IP_H + +#include "lwip/arch.h" + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/** This operates on a void* by loading the first byte */ +#define IP_HDR_GET_VERSION(ptr) ((*(u8_t*)(ptr)) >> 4) + +#endif /* LWIP_HDR_PROT_IP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/ip4.h b/components/net/lwip-2.0.3/src/include/lwip/prot/ip4.h new file mode 100644 index 0000000000..bd442c6892 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/ip4.h @@ -0,0 +1,127 @@ +/** + * @file + * IPv4 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IP4_H +#define LWIP_HDR_PROT_IP4_H + +#include "lwip/arch.h" +#include "lwip/ip4_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This is the packed version of ip4_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip4_addr_packed { + PACK_STRUCT_FIELD(u32_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +typedef struct ip4_addr_packed ip4_addr_p_t; + +/* Size of the IPv4 header. Same as 'sizeof(struct ip_hdr)'. */ +#define IP_HLEN 20 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/* The IPv4 header */ +struct ip_hdr { + /* version / header length */ + PACK_STRUCT_FLD_8(u8_t _v_hl); + /* type of service */ + PACK_STRUCT_FLD_8(u8_t _tos); + /* total length */ + PACK_STRUCT_FIELD(u16_t _len); + /* identification */ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000U /* reserved fragment flag */ +#define IP_DF 0x4000U /* don't fragment flag */ +#define IP_MF 0x2000U /* more fragments flag */ +#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ + /* time to live */ + PACK_STRUCT_FLD_8(u8_t _ttl); + /* protocol*/ + PACK_STRUCT_FLD_8(u8_t _proto); + /* checksum */ + PACK_STRUCT_FIELD(u16_t _chksum); + /* source and destination IP addresses */ + PACK_STRUCT_FLD_S(ip4_addr_p_t src); + PACK_STRUCT_FLD_S(ip4_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Macros to get struct ip_hdr fields: */ +#define IPH_V(hdr) ((hdr)->_v_hl >> 4) +#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) +#define IPH_TOS(hdr) ((hdr)->_tos) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) ((hdr)->_ttl) +#define IPH_PROTO(hdr) ((hdr)->_proto) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +/* Macros to set struct ip_hdr fields: */ +#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (u8_t)((((v) << 4) | (hl))) +#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_IP4_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/ip6.h b/components/net/lwip-2.0.3/src/include/lwip/prot/ip6.h new file mode 100644 index 0000000000..6e1e2632bf --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/ip6.h @@ -0,0 +1,169 @@ +/** + * @file + * IPv6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IP6_H +#define LWIP_HDR_PROT_IP6_H + +#include "lwip/arch.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This is the packed version of ip6_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_addr_packed { + PACK_STRUCT_FIELD(u32_t addr[4]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +typedef struct ip6_addr_packed ip6_addr_p_t; + +#define IP6_HLEN 40 + +#define IP6_NEXTH_HOPBYHOP 0 +#define IP6_NEXTH_TCP 6 +#define IP6_NEXTH_UDP 17 +#define IP6_NEXTH_ENCAPS 41 +#define IP6_NEXTH_ROUTING 43 +#define IP6_NEXTH_FRAGMENT 44 +#define IP6_NEXTH_ICMP6 58 +#define IP6_NEXTH_NONE 59 +#define IP6_NEXTH_DESTOPTS 60 +#define IP6_NEXTH_UDPLITE 136 + +/** The IPv6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hdr { + /** version / traffic class / flow label */ + PACK_STRUCT_FIELD(u32_t _v_tc_fl); + /** payload length */ + PACK_STRUCT_FIELD(u16_t _plen); + /** next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /** hop limit */ + PACK_STRUCT_FLD_8(u8_t _hoplim); + /** source and destination IP addresses */ + PACK_STRUCT_FLD_S(ip6_addr_p_t src); + PACK_STRUCT_FLD_S(ip6_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Hop-by-hop router alert option. */ +#define IP6_HBH_HLEN 8 +#define IP6_PAD1_OPTION 0 +#define IP6_PADN_ALERT_OPTION 1 +#define IP6_ROUTER_ALERT_OPTION 5 +#define IP6_ROUTER_ALERT_VALUE_MLD 0 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hbh_hdr { + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* header length */ + PACK_STRUCT_FLD_8(u8_t _hlen); + /* router alert option type */ + PACK_STRUCT_FLD_8(u8_t _ra_opt_type); + /* router alert option data len */ + PACK_STRUCT_FLD_8(u8_t _ra_opt_dlen); + /* router alert option data */ + PACK_STRUCT_FIELD(u16_t _ra_opt_data); + /* PadN option type */ + PACK_STRUCT_FLD_8(u8_t _padn_opt_type); + /* PadN option data len */ + PACK_STRUCT_FLD_8(u8_t _padn_opt_dlen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Fragment header. */ +#define IP6_FRAG_HLEN 8 +#define IP6_FRAG_OFFSET_MASK 0xfff8 +#define IP6_FRAG_MORE_FLAG 0x0001 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_frag_hdr { + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* reserved */ + PACK_STRUCT_FLD_8(u8_t reserved); + /* fragment offset */ + PACK_STRUCT_FIELD(u16_t _fragment_offset); + /* fragmented packet identification */ + PACK_STRUCT_FIELD(u32_t _identification); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP6H_V(hdr) ((lwip_ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f) +#define IP6H_TC(hdr) ((lwip_ntohl((hdr)->_v_tc_fl) >> 20) & 0xff) +#define IP6H_FL(hdr) (lwip_ntohl((hdr)->_v_tc_fl) & 0x000fffff) +#define IP6H_PLEN(hdr) (lwip_ntohs((hdr)->_plen)) +#define IP6H_NEXTH(hdr) ((hdr)->_nexth) +#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6) +#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim) + +#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (lwip_htonl((((u32_t)(v)) << 28) | (((u32_t)(tc)) << 20) | (fl))) +#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = lwip_htons(plen) +#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth) +#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_IP6_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/mld6.h b/components/net/lwip-2.0.3/src/include/lwip/prot/mld6.h new file mode 100644 index 0000000000..be3a006af2 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/mld6.h @@ -0,0 +1,70 @@ +/** + * @file + * MLD6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_MLD6_H +#define LWIP_HDR_PROT_MLD6_H + +#include "lwip/arch.h" +#include "lwip/prot/ip6.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Multicast listener report/query/done message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mld_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t max_resp_delay); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t multicast_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_MLD6_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/nd6.h b/components/net/lwip-2.0.3/src/include/lwip/prot/nd6.h new file mode 100644 index 0000000000..2d4903d15b --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/nd6.h @@ -0,0 +1,277 @@ +/** + * @file + * ND6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ND6_H +#define LWIP_HDR_PROT_ND6_H + +#include "lwip/arch.h" +#include "lwip/ip6_addr.h" +#include "lwip/prot/ip6.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Neighbor solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ns_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Neighbor advertisement message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct na_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FLD_8(u8_t reserved[3]); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define ND6_FLAG_ROUTER (0x80) +#define ND6_FLAG_SOLICITED (0x40) +#define ND6_FLAG_OVERRIDE (0x20) + +/** Router solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct rs_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Router advertisement message header. */ +#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80) +#define ND6_RA_FLAG_OTHER_CONFIG (0x40) +#define ND6_RA_FLAG_HOME_AGENT (0x20) +#define ND6_RA_PREFERENCE_MASK (0x18) +#define ND6_RA_PREFERENCE_HIGH (0x08) +#define ND6_RA_PREFERENCE_MEDIUM (0x00) +#define ND6_RA_PREFERENCE_LOW (0x18) +#define ND6_RA_PREFERENCE_DISABLED (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ra_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FLD_8(u8_t current_hop_limit); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FIELD(u16_t router_lifetime); + PACK_STRUCT_FIELD(u32_t reachable_time); + PACK_STRUCT_FIELD(u32_t retrans_timer); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirect message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirect_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + PACK_STRUCT_FLD_S(ip6_addr_p_t destination_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Link-layer address option. */ +#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01) +#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct lladdr_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t addr[NETIF_MAX_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Prefix information option. */ +#define ND6_OPTION_TYPE_PREFIX_INFO (0x03) +#define ND6_PREFIX_FLAG_ON_LINK (0x80) +#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40) +#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20) +#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct prefix_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FIELD(u32_t valid_lifetime); + PACK_STRUCT_FIELD(u32_t preferred_lifetime); + PACK_STRUCT_FLD_8(u8_t reserved2[3]); + PACK_STRUCT_FLD_8(u8_t site_prefix_length); + PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirected header option. */ +#define ND6_OPTION_TYPE_REDIR_HDR (0x04) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirected_header_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t reserved[6]); + /* Portion of redirected packet follows. */ + /* PACK_STRUCT_FLD_8(u8_t redirected[8]); */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** MTU option. */ +#define ND6_OPTION_TYPE_MTU (0x05) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mtu_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FIELD(u32_t mtu); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Route information option. */ +#define ND6_OPTION_TYPE_ROUTE_INFO (24) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct route_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t preference); + PACK_STRUCT_FIELD(u32_t route_lifetime); + PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Recursive DNS Server Option. */ +#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS +#define LWIP_RDNSS_OPTION_MAX_SERVERS LWIP_ND6_RDNSS_MAX_DNS_SERVERS +#else +#define LWIP_RDNSS_OPTION_MAX_SERVERS 1 +#endif +#define ND6_OPTION_TYPE_RDNSS (25) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct rdnss_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FIELD(u32_t lifetime); + PACK_STRUCT_FLD_S(ip6_addr_p_t rdnss_address[LWIP_RDNSS_OPTION_MAX_SERVERS]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ND6_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/tcp.h b/components/net/lwip-2.0.3/src/include/lwip/prot/tcp.h new file mode 100644 index 0000000000..67fe7b9e5f --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/tcp.h @@ -0,0 +1,97 @@ +/** + * @file + * TCP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_TCP_H +#define LWIP_HDR_PROT_TCP_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Length of the TCP header, excluding options. */ +#define TCP_HLEN 20 + +/* Fields are (of course) in network byte order. + * Some fields are converted to host byte order in tcp_input(). + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct tcp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); + PACK_STRUCT_FIELD(u32_t seqno); + PACK_STRUCT_FIELD(u32_t ackno); + PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); + PACK_STRUCT_FIELD(u16_t wnd); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t urgp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* TCP header flags bits */ +#define TCP_FIN 0x01U +#define TCP_SYN 0x02U +#define TCP_RST 0x04U +#define TCP_PSH 0x08U +#define TCP_ACK 0x10U +#define TCP_URG 0x20U +#define TCP_ECE 0x40U +#define TCP_CWR 0x80U +/* Valid TCP header flags */ +#define TCP_FLAGS 0x3fU + +#define TCPH_HDRLEN(phdr) ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)) +#define TCPH_FLAGS(phdr) ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)) + +#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | TCPH_FLAGS(phdr)) +#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | lwip_htons(flags)) +#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = (u16_t)(lwip_htons((u16_t)((len) << 12) | (flags))) + +#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | lwip_htons(flags)) +#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~lwip_htons(flags)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_TCP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/prot/udp.h b/components/net/lwip-2.0.3/src/include/lwip/prot/udp.h new file mode 100644 index 0000000000..664f19a3e7 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/prot/udp.h @@ -0,0 +1,68 @@ +/** + * @file + * UDP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_UDP_H +#define LWIP_HDR_PROT_UDP_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_HLEN 8 + +/* Fields are (of course) in network byte order. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct udp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ + PACK_STRUCT_FIELD(u16_t len); + PACK_STRUCT_FIELD(u16_t chksum); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_UDP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/raw.h b/components/net/lwip-2.0.3/src/include/lwip/raw.h new file mode 100644 index 0000000000..30aa147109 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/raw.h @@ -0,0 +1,118 @@ +/** + * @file + * raw API (to be used from TCPIP thread)\n + * See also @ref raw_raw + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_RAW_H +#define LWIP_HDR_RAW_H + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct raw_pcb; + +/** Function prototype for raw pcb receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) + * @param pcb the raw_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @return 1 if the packet was 'eaten' (aka. deleted), + * 0 if the packet lives on + * If returning 1, the callback is responsible for freeing the pbuf + * if it's not used any more. + */ +typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr); + +/** the RAW protocol control block */ +struct raw_pcb { + /* Common members of all PCB types */ + IP_PCB; + + struct raw_pcb *next; + + u8_t protocol; + + /** receive callback function */ + raw_recv_fn recv; + /* user-supplied argument for the recv callback */ + void *recv_arg; +#if LWIP_IPV6 + /* fields for handling checksum computations as per RFC3542. */ + u16_t chksum_offset; + u8_t chksum_reqd; +#endif +}; + +/* The following functions is the application layer interface to the + RAW code. */ +struct raw_pcb * raw_new (u8_t proto); +struct raw_pcb * raw_new_ip_type(u8_t type, u8_t proto); +void raw_remove (struct raw_pcb *pcb); +err_t raw_bind (struct raw_pcb *pcb, const ip_addr_t *ipaddr); +err_t raw_connect (struct raw_pcb *pcb, const ip_addr_t *ipaddr); + +err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr); +err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); + +void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); + +/* The following functions are the lower layer interface to RAW. */ +u8_t raw_input (struct pbuf *p, struct netif *inp); +#define raw_init() /* Compatibility define, no init needed. */ + +void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); + +/* for compatibility with older implementation */ +#define raw_new_ip6(proto) raw_new_ip_type(IPADDR_TYPE_V6, proto) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW */ + +#endif /* LWIP_HDR_RAW_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/sio.h b/components/net/lwip-2.0.3/src/include/lwip/sio.h new file mode 100644 index 0000000000..7643e19569 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/sio.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + */ + +/* + * This is the interface to the platform specific serial IO module + * It needs to be implemented by those platforms which need SLIP or PPP + */ + +#ifndef SIO_H +#define SIO_H + +#include "lwip/arch.h" +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If you want to define sio_fd_t elsewhere or differently, + define this in your cc.h file. */ +#ifndef __sio_fd_t_defined +typedef void * sio_fd_t; +#endif + +/* The following functions can be defined to something else in your cc.h file + or be implemented in your custom sio.c file. */ + +#ifndef sio_open +/** + * Opens a serial device for communication. + * + * @param devnum device number + * @return handle to serial device if successful, NULL otherwise + */ +sio_fd_t sio_open(u8_t devnum); +#endif + +#ifndef sio_send +/** + * Sends a single character to the serial device. + * + * @param c character to send + * @param fd serial device handle + * + * @note This function will block until the character can be sent. + */ +void sio_send(u8_t c, sio_fd_t fd); +#endif + +#ifndef sio_recv +/** + * Receives a single character from the serial device. + * + * @param fd serial device handle + * + * @note This function will block until a character is received. + */ +u8_t sio_recv(sio_fd_t fd); +#endif + +#ifndef sio_read +/** + * Reads from the serial device. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received - may be 0 if aborted by sio_read_abort + * + * @note This function will block until data can be received. The blocking + * can be cancelled by calling sio_read_abort(). + */ +u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_tryread +/** + * Tries to read from the serial device. Same as sio_read but returns + * immediately if no data is available and never blocks. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received + */ +u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_write +/** + * Writes to the serial device. + * + * @param fd serial device handle + * @param data pointer to data to send + * @param len length (in bytes) of data to send + * @return number of bytes actually sent + * + * @note This function will block until all data can be sent. + */ +u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_read_abort +/** + * Aborts a blocking sio_read() call. + * + * @param fd serial device handle + */ +void sio_read_abort(sio_fd_t fd); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SIO_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/snmp.h b/components/net/lwip-2.0.3/src/include/lwip/snmp.h new file mode 100644 index 0000000000..8704d0b4d2 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/snmp.h @@ -0,0 +1,213 @@ +/** + * @file + * SNMP support API for implementing netifs and statitics for MIB2 + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Dirk Ziegelmeier + * + */ +#ifndef LWIP_HDR_SNMP_H +#define LWIP_HDR_SNMP_H + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct udp_pcb; +struct netif; + +/** + * @defgroup netif_mib2 MIB2 statistics + * @ingroup netif + */ + +/* MIB2 statistics functions */ +#if MIB2_STATS /* don't build if not configured for use in lwipopts.h */ +/** + * @ingroup netif_mib2 + * @see RFC1213, "MIB-II, 6. Definitions" + */ +enum snmp_ifType { + snmp_ifType_other=1, /* none of the following */ + snmp_ifType_regular1822, + snmp_ifType_hdh1822, + snmp_ifType_ddn_x25, + snmp_ifType_rfc877_x25, + snmp_ifType_ethernet_csmacd, + snmp_ifType_iso88023_csmacd, + snmp_ifType_iso88024_tokenBus, + snmp_ifType_iso88025_tokenRing, + snmp_ifType_iso88026_man, + snmp_ifType_starLan, + snmp_ifType_proteon_10Mbit, + snmp_ifType_proteon_80Mbit, + snmp_ifType_hyperchannel, + snmp_ifType_fddi, + snmp_ifType_lapb, + snmp_ifType_sdlc, + snmp_ifType_ds1, /* T-1 */ + snmp_ifType_e1, /* european equiv. of T-1 */ + snmp_ifType_basicISDN, + snmp_ifType_primaryISDN, /* proprietary serial */ + snmp_ifType_propPointToPointSerial, + snmp_ifType_ppp, + snmp_ifType_softwareLoopback, + snmp_ifType_eon, /* CLNP over IP [11] */ + snmp_ifType_ethernet_3Mbit, + snmp_ifType_nsip, /* XNS over IP */ + snmp_ifType_slip, /* generic SLIP */ + snmp_ifType_ultra, /* ULTRA technologies */ + snmp_ifType_ds3, /* T-3 */ + snmp_ifType_sip, /* SMDS */ + snmp_ifType_frame_relay +}; + +/** This macro has a precision of ~49 days because sys_now returns u32_t. \#define your own if you want ~490 days. */ +#ifndef MIB2_COPY_SYSUPTIME_TO +#define MIB2_COPY_SYSUPTIME_TO(ptrToVal) (*(ptrToVal) = (sys_now() / 10)) +#endif + +/** + * @ingroup netif_mib2 + * Increment stats member for SNMP MIB2 stats (struct stats_mib2_netif_ctrs) + */ +#define MIB2_STATS_NETIF_INC(n, x) do { ++(n)->mib2_counters.x; } while(0) +/** + * @ingroup netif_mib2 + * Add value to stats member for SNMP MIB2 stats (struct stats_mib2_netif_ctrs) + */ +#define MIB2_STATS_NETIF_ADD(n, x, val) do { (n)->mib2_counters.x += (val); } while(0) + +/** + * @ingroup netif_mib2 + * Init MIB2 statistic counters in netif + * @param netif Netif to init + * @param type one of enum @ref snmp_ifType + * @param speed your link speed here (units: bits per second) + */ +#define MIB2_INIT_NETIF(netif, type, speed) do { \ + (netif)->link_type = (type); \ + (netif)->link_speed = (speed);\ + (netif)->ts = 0; \ + (netif)->mib2_counters.ifinoctets = 0; \ + (netif)->mib2_counters.ifinucastpkts = 0; \ + (netif)->mib2_counters.ifinnucastpkts = 0; \ + (netif)->mib2_counters.ifindiscards = 0; \ + (netif)->mib2_counters.ifinerrors = 0; \ + (netif)->mib2_counters.ifinunknownprotos = 0; \ + (netif)->mib2_counters.ifoutoctets = 0; \ + (netif)->mib2_counters.ifoutucastpkts = 0; \ + (netif)->mib2_counters.ifoutnucastpkts = 0; \ + (netif)->mib2_counters.ifoutdiscards = 0; \ + (netif)->mib2_counters.ifouterrors = 0; } while(0) +#else /* MIB2_STATS */ +#ifndef MIB2_COPY_SYSUPTIME_TO +#define MIB2_COPY_SYSUPTIME_TO(ptrToVal) +#endif +#define MIB2_INIT_NETIF(netif, type, speed) +#define MIB2_STATS_NETIF_INC(n, x) +#define MIB2_STATS_NETIF_ADD(n, x, val) +#endif /* MIB2_STATS */ + +/* LWIP MIB2 callbacks */ +#if LWIP_MIB2_CALLBACKS /* don't build if not configured for use in lwipopts.h */ +/* network interface */ +void mib2_netif_added(struct netif *ni); +void mib2_netif_removed(struct netif *ni); + +#if LWIP_IPV4 && LWIP_ARP +/* ARP (for atTable and ipNetToMediaTable) */ +void mib2_add_arp_entry(struct netif *ni, ip4_addr_t *ip); +void mib2_remove_arp_entry(struct netif *ni, ip4_addr_t *ip); +#else /* LWIP_IPV4 && LWIP_ARP */ +#define mib2_add_arp_entry(ni,ip) +#define mib2_remove_arp_entry(ni,ip) +#endif /* LWIP_IPV4 && LWIP_ARP */ + +/* IP */ +#if LWIP_IPV4 +void mib2_add_ip4(struct netif *ni); +void mib2_remove_ip4(struct netif *ni); +void mib2_add_route_ip4(u8_t dflt, struct netif *ni); +void mib2_remove_route_ip4(u8_t dflt, struct netif *ni); +#endif /* LWIP_IPV4 */ + +/* UDP */ +#if LWIP_UDP +void mib2_udp_bind(struct udp_pcb *pcb); +void mib2_udp_unbind(struct udp_pcb *pcb); +#endif /* LWIP_UDP */ + +#else /* LWIP_MIB2_CALLBACKS */ +/* LWIP_MIB2_CALLBACKS support not available */ +/* define everything to be empty */ + +/* network interface */ +#define mib2_netif_added(ni) +#define mib2_netif_removed(ni) + +/* ARP */ +#define mib2_add_arp_entry(ni,ip) +#define mib2_remove_arp_entry(ni,ip) + +/* IP */ +#define mib2_add_ip4(ni) +#define mib2_remove_ip4(ni) +#define mib2_add_route_ip4(dflt, ni) +#define mib2_remove_route_ip4(dflt, ni) + +/* UDP */ +#define mib2_udp_bind(pcb) +#define mib2_udp_unbind(pcb) +#endif /* LWIP_MIB2_CALLBACKS */ + +/* for source-code compatibility reasons only, can be removed (not used internally) */ +#define NETIF_INIT_SNMP MIB2_INIT_NETIF +#define snmp_add_ifinoctets(ni,value) MIB2_STATS_NETIF_ADD(ni, ifinoctets, value) +#define snmp_inc_ifinucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifinucastpkts) +#define snmp_inc_ifinnucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifinnucastpkts) +#define snmp_inc_ifindiscards(ni) MIB2_STATS_NETIF_INC(ni, ifindiscards) +#define snmp_inc_ifinerrors(ni) MIB2_STATS_NETIF_INC(ni, ifinerrors) +#define snmp_inc_ifinunknownprotos(ni) MIB2_STATS_NETIF_INC(ni, ifinunknownprotos) +#define snmp_add_ifoutoctets(ni,value) MIB2_STATS_NETIF_ADD(ni, ifoutoctets, value) +#define snmp_inc_ifoutucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifoutucastpkts) +#define snmp_inc_ifoutnucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifoutnucastpkts) +#define snmp_inc_ifoutdiscards(ni) MIB2_STATS_NETIF_INC(ni, ifoutdiscards) +#define snmp_inc_ifouterrors(ni) MIB2_STATS_NETIF_INC(ni, ifouterrors) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_SNMP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/sockets.h b/components/net/lwip-2.0.3/src/include/lwip/sockets.h new file mode 100644 index 0000000000..2522056dba --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/sockets.h @@ -0,0 +1,593 @@ +/** + * @file + * Socket API (to be used from non-TCPIP threads) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +#ifndef LWIP_HDR_SOCKETS_H +#define LWIP_HDR_SOCKETS_H + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/inet.h" +#include "lwip/errno.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) +typedef u8_t sa_family_t; +#endif +/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) +typedef u16_t in_port_t; +#endif + +#if LWIP_IPV4 +/* members are in network byte order */ +struct sockaddr_in { + u8_t sin_len; + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; +#define SIN_ZERO_LEN 8 + char sin_zero[SIN_ZERO_LEN]; +}; +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +struct sockaddr_in6 { + u8_t sin6_len; /* length of this structure */ + sa_family_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* Transport layer port # */ + u32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + u32_t sin6_scope_id; /* Set of interfaces for scope */ +}; +#endif /* LWIP_IPV6 */ + +struct sockaddr { + u8_t sa_len; + sa_family_t sa_family; + char sa_data[14]; +}; + +struct sockaddr_storage { + u8_t s2_len; + sa_family_t ss_family; + char s2_data1[2]; + u32_t s2_data2[3]; +#if LWIP_IPV6 + u32_t s2_data3[3]; +#endif /* LWIP_IPV6 */ +}; + +/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) +typedef u32_t socklen_t; +#endif + +struct lwip_sock; + +#if !LWIP_TCPIP_CORE_LOCKING +/** Maximum optlen used by setsockopt/getsockopt */ +#define LWIP_SETGETSOCKOPT_MAXOPTLEN 16 + +/** This struct is used to pass data to the set/getsockopt_internal + * functions running in tcpip_thread context (only a void* is allowed) */ +struct lwip_setgetsockopt_data { + /** socket index for which to change options */ + int s; + /** level of the option to process */ + int level; + /** name of the option to process */ + int optname; + /** set: value to set the option to + * get: value of the option is stored here */ +#if LWIP_MPU_COMPATIBLE + u8_t optval[LWIP_SETGETSOCKOPT_MAXOPTLEN]; +#else + union { + void *p; + const void *pc; + } optval; +#endif + /** size of *optval */ + socklen_t optlen; + /** if an error occurs, it is temporarily stored here */ + err_t err; + /** semaphore to wake up the calling task */ + void* completed_sem; +}; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + +#if !defined(iovec) +struct iovec { + void *iov_base; + size_t iov_len; +}; +#endif + +struct msghdr { + void *msg_name; + socklen_t msg_namelen; + struct iovec *msg_iov; + int msg_iovlen; + void *msg_control; + socklen_t msg_controllen; + int msg_flags; +}; + +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ + + +/* + * Additional options, not kept in so_options. + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_DONTLINGER ((int)(~SO_LINGER)) +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time in seconds */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + + +#define AF_UNSPEC 0 +#define AF_INET 2 +#if LWIP_IPV6 +#define AF_INET6 10 +#else /* LWIP_IPV6 */ +#define AF_INET6 AF_UNSPEC +#endif /* LWIP_IPV6 */ +#define PF_INET AF_INET +#define PF_INET6 AF_INET6 +#define PF_UNSPEC AF_UNSPEC + +#define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#if LWIP_IPV6 +#define IPPROTO_IPV6 41 +#define IPPROTO_ICMPV6 58 +#endif /* LWIP_IPV6 */ +#define IPPROTO_UDPLITE 136 +#define IPPROTO_RAW 255 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + + +/* + * Options for level IPPROTO_IP + */ +#define IP_TOS 1 +#define IP_TTL 2 + +#if LWIP_TCP +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ +#endif /* LWIP_TCP */ + +#if LWIP_IPV6 +/* + * Options for level IPPROTO_IPV6 + */ +#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ +#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE +/* + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ +#endif /* LWIP_UDP && LWIP_UDPLITE*/ + + +#if LWIP_MULTICAST_TX_OPTIONS +/* + * Options and types for UDP multicast traffic handling + */ +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#if LWIP_IGMP +/* + * Options and types related to multicast membership + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 + +typedef struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; +#endif /* LWIP_IGMP */ + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* + * Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * lwip_ioctl only supports FIONREAD and FIONBIO, for now + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/* Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ +#endif + +/* commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/* File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 1 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef SHUT_RD + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 +#endif + +/* FD_SET used for lwip_select */ +#ifndef FD_SET +#undef FD_SETSIZE +/* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ +#define FD_SETSIZE MEMP_NUM_NETCONN +#define FDSETSAFESET(n, code) do { \ + if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \ + code; }} while(0) +#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ + (code) : 0) +#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) + +typedef struct fd_set +{ + unsigned char fd_bits [(FD_SETSIZE+7)/8]; +} fd_set; + +#elif LWIP_SOCKET_OFFSET +#error LWIP_SOCKET_OFFSET does not work with external FD_SET! +#elif FD_SETSIZE < MEMP_NUM_NETCONN +#error "external FD_SETSIZE too small for number of sockets" +#endif /* FD_SET */ + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif /* LWIP_TIMEVAL_PRIVATE */ + +#define lwip_socket_init() /* Compatibility define, no init needed. */ +void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ +void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ + +#if LWIP_COMPAT_SOCKETS == 2 +/* This helps code parsers/code completion by not having the COMPAT functions as defines */ +#define lwip_accept accept +#define lwip_bind bind +#define lwip_shutdown shutdown +#define lwip_getpeername getpeername +#define lwip_getsockname getsockname +#define lwip_setsockopt setsockopt +#define lwip_getsockopt getsockopt +#define lwip_close closesocket +#define lwip_connect connect +#define lwip_listen listen +#define lwip_recv recv +#define lwip_recvfrom recvfrom +#define lwip_send send +#define lwip_sendmsg sendmsg +#define lwip_sendto sendto +#define lwip_socket socket +#define lwip_select select +#define lwip_ioctlsocket ioctl + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define lwip_read read +#define lwip_write write +#define lwip_writev writev +#undef lwip_close +#define lwip_close close +#define closesocket(s) close(s) +#define lwip_fcntl fcntl +#define lwip_ioctl ioctl +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ +#endif /* LWIP_COMPAT_SOCKETS == 2 */ + +int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_shutdown(int s, int how); +int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int lwip_close(int s); +int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_listen(int s, int backlog); +int lwip_recv(int s, void *mem, size_t len, int flags); +int lwip_read(int s, void *mem, size_t len); +int lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int lwip_send(int s, const void *dataptr, size_t size, int flags); +int lwip_sendmsg(int s, const struct msghdr *message, int flags); +int lwip_sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int lwip_socket(int domain, int type, int protocol); +int lwip_write(int s, const void *dataptr, size_t size); +int lwip_writev(int s, const struct iovec *iov, int iovcnt); +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +int lwip_ioctl(int s, long cmd, void *argp); +int lwip_fcntl(int s, int cmd, int val); + +#if LWIP_COMPAT_SOCKETS +#if LWIP_COMPAT_SOCKETS != 2 +/** @ingroup socket */ +#define accept(s,addr,addrlen) lwip_accept(s,addr,addrlen) +/** @ingroup socket */ +#define bind(s,name,namelen) lwip_bind(s,name,namelen) +/** @ingroup socket */ +#define shutdown(s,how) lwip_shutdown(s,how) +/** @ingroup socket */ +#define getpeername(s,name,namelen) lwip_getpeername(s,name,namelen) +/** @ingroup socket */ +#define getsockname(s,name,namelen) lwip_getsockname(s,name,namelen) +/** @ingroup socket */ +#define setsockopt(s,level,optname,opval,optlen) lwip_setsockopt(s,level,optname,opval,optlen) +/** @ingroup socket */ +#define getsockopt(s,level,optname,opval,optlen) lwip_getsockopt(s,level,optname,opval,optlen) +/** @ingroup socket */ +#define closesocket(s) lwip_close(s) +/** @ingroup socket */ +#define connect(s,name,namelen) lwip_connect(s,name,namelen) +/** @ingroup socket */ +#define listen(s,backlog) lwip_listen(s,backlog) +/** @ingroup socket */ +#define recv(s,mem,len,flags) lwip_recv(s,mem,len,flags) +/** @ingroup socket */ +#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom(s,mem,len,flags,from,fromlen) +/** @ingroup socket */ +#define send(s,dataptr,size,flags) lwip_send(s,dataptr,size,flags) +/** @ingroup socket */ +#define sendmsg(s,message,flags) lwip_sendmsg(s,message,flags) +/** @ingroup socket */ +#define sendto(s,dataptr,size,flags,to,tolen) lwip_sendto(s,dataptr,size,flags,to,tolen) +/** @ingroup socket */ +#define socket(domain,type,protocol) lwip_socket(domain,type,protocol) +/** @ingroup socket */ +#define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) +/** @ingroup socket */ +#define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) + +#if LWIP_POSIX_SOCKETS_IO_NAMES +/** @ingroup socket */ +#define read(s,mem,len) lwip_read(s,mem,len) +/** @ingroup socket */ +#define write(s,dataptr,len) lwip_write(s,dataptr,len) +/** @ingroup socket */ +#define writev(s,iov,iovcnt) lwip_writev(s,iov,iovcnt) +/** @ingroup socket */ +#define close(s) lwip_close(s) +/** @ingroup socket */ +#define fcntl(s,cmd,val) lwip_fcntl(s,cmd,val) +/** @ingroup socket */ +#define ioctl(s,cmd,argp) lwip_ioctl(s,cmd,argp) +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ +#endif /* LWIP_COMPAT_SOCKETS != 2 */ + +#if LWIP_IPV4 && LWIP_IPV6 +/** @ingroup socket */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) \ + : (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL)) +/** @ingroup socket */ +#define inet_pton(af,src,dst) \ + (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) \ + : (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0)) +#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0) +#else /* LWIP_IPV4 && LWIP_IPV6 */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) : NULL) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) : 0) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET */ + +#endif /* LWIP_HDR_SOCKETS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/stats.h b/components/net/lwip-2.0.3/src/include/lwip/stats.h new file mode 100644 index 0000000000..5cde4a094c --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/stats.h @@ -0,0 +1,491 @@ +/** + * @file + * Statistics API (to be used from TCPIP thread) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_STATS_H +#define LWIP_HDR_STATS_H + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_STATS + +#ifndef LWIP_STATS_LARGE +#define LWIP_STATS_LARGE 0 +#endif + +#if LWIP_STATS_LARGE +#define STAT_COUNTER u32_t +#define STAT_COUNTER_F U32_F +#else +#define STAT_COUNTER u16_t +#define STAT_COUNTER_F U16_F +#endif + +/** Protocol related stats */ +struct stats_proto { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER fw; /* Forwarded packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER rterr; /* Routing error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER opterr; /* Error in options. */ + STAT_COUNTER err; /* Misc error. */ + STAT_COUNTER cachehit; +}; + +/** IGMP stats */ +struct stats_igmp { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER rx_v1; /* Received v1 frames. */ + STAT_COUNTER rx_group; /* Received group-specific queries. */ + STAT_COUNTER rx_general; /* Received general queries. */ + STAT_COUNTER rx_report; /* Received reports. */ + STAT_COUNTER tx_join; /* Sent joins. */ + STAT_COUNTER tx_leave; /* Sent leaves. */ + STAT_COUNTER tx_report; /* Sent reports. */ +}; + +/** Memory stats */ +struct stats_mem { +#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY + const char *name; +#endif /* defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY */ + STAT_COUNTER err; + mem_size_t avail; + mem_size_t used; + mem_size_t max; + STAT_COUNTER illegal; +}; + +/** System element stats */ +struct stats_syselem { + STAT_COUNTER used; + STAT_COUNTER max; + STAT_COUNTER err; +}; + +/** System stats */ +struct stats_sys { + struct stats_syselem sem; + struct stats_syselem mutex; + struct stats_syselem mbox; +}; + +/** SNMP MIB2 stats */ +struct stats_mib2 { + /* IP */ + u32_t ipinhdrerrors; + u32_t ipinaddrerrors; + u32_t ipinunknownprotos; + u32_t ipindiscards; + u32_t ipindelivers; + u32_t ipoutrequests; + u32_t ipoutdiscards; + u32_t ipoutnoroutes; + u32_t ipreasmoks; + u32_t ipreasmfails; + u32_t ipfragoks; + u32_t ipfragfails; + u32_t ipfragcreates; + u32_t ipreasmreqds; + u32_t ipforwdatagrams; + u32_t ipinreceives; + + /* TCP */ + u32_t tcpactiveopens; + u32_t tcppassiveopens; + u32_t tcpattemptfails; + u32_t tcpestabresets; + u32_t tcpoutsegs; + u32_t tcpretranssegs; + u32_t tcpinsegs; + u32_t tcpinerrs; + u32_t tcpoutrsts; + + /* UDP */ + u32_t udpindatagrams; + u32_t udpnoports; + u32_t udpinerrors; + u32_t udpoutdatagrams; + + /* ICMP */ + u32_t icmpinmsgs; + u32_t icmpinerrors; + u32_t icmpindestunreachs; + u32_t icmpintimeexcds; + u32_t icmpinparmprobs; + u32_t icmpinsrcquenchs; + u32_t icmpinredirects; + u32_t icmpinechos; + u32_t icmpinechoreps; + u32_t icmpintimestamps; + u32_t icmpintimestampreps; + u32_t icmpinaddrmasks; + u32_t icmpinaddrmaskreps; + u32_t icmpoutmsgs; + u32_t icmpouterrors; + u32_t icmpoutdestunreachs; + u32_t icmpouttimeexcds; + u32_t icmpoutechos; /* can be incremented by user application ('ping') */ + u32_t icmpoutechoreps; +}; + +/** + * @ingroup netif_mib2 + * SNMP MIB2 interface stats + */ +struct stats_mib2_netif_ctrs { + /** The total number of octets received on the interface, including framing characters */ + u32_t ifinoctets; + /** The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were + * not addressed to a multicast or broadcast address at this sub-layer */ + u32_t ifinucastpkts; + /** The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were + * addressed to a multicast or broadcast address at this sub-layer */ + u32_t ifinnucastpkts; + /** The number of inbound packets which were chosen to be discarded even though no errors had + * been detected to prevent their being deliverable to a higher-layer protocol. One possible + * reason for discarding such a packet could be to free up buffer space */ + u32_t ifindiscards; + /** For packet-oriented interfaces, the number of inbound packets that contained errors + * preventing them from being deliverable to a higher-layer protocol. For character- + * oriented or fixed-length interfaces, the number of inbound transmission units that + * contained errors preventing them from being deliverable to a higher-layer protocol. */ + u32_t ifinerrors; + /** For packet-oriented interfaces, the number of packets received via the interface which + * were discarded because of an unknown or unsupported protocol. For character-oriented + * or fixed-length interfaces that support protocol multiplexing the number of transmission + * units received via the interface which were discarded because of an unknown or unsupported + * protocol. For any interface that does not support protocol multiplexing, this counter will + * always be 0 */ + u32_t ifinunknownprotos; + /** The total number of octets transmitted out of the interface, including framing characters. */ + u32_t ifoutoctets; + /** The total number of packets that higher-level protocols requested be transmitted, and + * which were not addressed to a multicast or broadcast address at this sub-layer, including + * those that were discarded or not sent. */ + u32_t ifoutucastpkts; + /** The total number of packets that higher-level protocols requested be transmitted, and which + * were addressed to a multicast or broadcast address at this sub-layer, including + * those that were discarded or not sent. */ + u32_t ifoutnucastpkts; + /** The number of outbound packets which were chosen to be discarded even though no errors had + * been detected to prevent their being transmitted. One possible reason for discarding + * such a packet could be to free up buffer space. */ + u32_t ifoutdiscards; + /** For packet-oriented interfaces, the number of outbound packets that could not be transmitted + * because of errors. For character-oriented or fixed-length interfaces, the number of outbound + * transmission units that could not be transmitted because of errors. */ + u32_t ifouterrors; +}; + +/** lwIP stats container */ +struct stats_ { +#if LINK_STATS + /** Link level */ + struct stats_proto link; +#endif +#if ETHARP_STATS + /** ARP */ + struct stats_proto etharp; +#endif +#if IPFRAG_STATS + /** Fragmentation */ + struct stats_proto ip_frag; +#endif +#if IP_STATS + /** IP */ + struct stats_proto ip; +#endif +#if ICMP_STATS + /** ICMP */ + struct stats_proto icmp; +#endif +#if IGMP_STATS + /** IGMP */ + struct stats_igmp igmp; +#endif +#if UDP_STATS + /** UDP */ + struct stats_proto udp; +#endif +#if TCP_STATS + /** TCP */ + struct stats_proto tcp; +#endif +#if MEM_STATS + /** Heap */ + struct stats_mem mem; +#endif +#if MEMP_STATS + /** Internal memory pools */ + struct stats_mem *memp[MEMP_MAX]; +#endif +#if SYS_STATS + /** System */ + struct stats_sys sys; +#endif +#if IP6_STATS + /** IPv6 */ + struct stats_proto ip6; +#endif +#if ICMP6_STATS + /** ICMP6 */ + struct stats_proto icmp6; +#endif +#if IP6_FRAG_STATS + /** IPv6 fragmentation */ + struct stats_proto ip6_frag; +#endif +#if MLD6_STATS + /** Multicast listener discovery */ + struct stats_igmp mld6; +#endif +#if ND6_STATS + /** Neighbor discovery */ + struct stats_proto nd6; +#endif +#if MIB2_STATS + /** SNMP MIB2 */ + struct stats_mib2 mib2; +#endif +}; + +/** Global variable containing lwIP internal statistics. Add this to your debugger's watchlist. */ +extern struct stats_ lwip_stats; + +/** Init statistics */ +void stats_init(void); + +#define STATS_INC(x) ++lwip_stats.x +#define STATS_DEC(x) --lwip_stats.x +#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \ + if (lwip_stats.x.max < lwip_stats.x.used) { \ + lwip_stats.x.max = lwip_stats.x.used; \ + } \ + } while(0) +#define STATS_GET(x) lwip_stats.x +#else /* LWIP_STATS */ +#define stats_init() +#define STATS_INC(x) +#define STATS_DEC(x) +#define STATS_INC_USED(x) +#endif /* LWIP_STATS */ + +#if TCP_STATS +#define TCP_STATS_INC(x) STATS_INC(x) +#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") +#else +#define TCP_STATS_INC(x) +#define TCP_STATS_DISPLAY() +#endif + +#if UDP_STATS +#define UDP_STATS_INC(x) STATS_INC(x) +#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") +#else +#define UDP_STATS_INC(x) +#define UDP_STATS_DISPLAY() +#endif + +#if ICMP_STATS +#define ICMP_STATS_INC(x) STATS_INC(x) +#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") +#else +#define ICMP_STATS_INC(x) +#define ICMP_STATS_DISPLAY() +#endif + +#if IGMP_STATS +#define IGMP_STATS_INC(x) STATS_INC(x) +#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp, "IGMP") +#else +#define IGMP_STATS_INC(x) +#define IGMP_STATS_DISPLAY() +#endif + +#if IP_STATS +#define IP_STATS_INC(x) STATS_INC(x) +#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") +#else +#define IP_STATS_INC(x) +#define IP_STATS_DISPLAY() +#endif + +#if IPFRAG_STATS +#define IPFRAG_STATS_INC(x) STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") +#else +#define IPFRAG_STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() +#endif + +#if ETHARP_STATS +#define ETHARP_STATS_INC(x) STATS_INC(x) +#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") +#else +#define ETHARP_STATS_INC(x) +#define ETHARP_STATS_DISPLAY() +#endif + +#if LINK_STATS +#define LINK_STATS_INC(x) STATS_INC(x) +#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") +#else +#define LINK_STATS_INC(x) +#define LINK_STATS_DISPLAY() +#endif + +#if MEM_STATS +#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y +#define MEM_STATS_INC(x) SYS_ARCH_INC(lwip_stats.mem.x, 1) +#define MEM_STATS_INC_USED(x, y) SYS_ARCH_INC(lwip_stats.mem.x, y) +#define MEM_STATS_DEC_USED(x, y) SYS_ARCH_DEC(lwip_stats.mem.x, y) +#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") +#else +#define MEM_STATS_AVAIL(x, y) +#define MEM_STATS_INC(x) +#define MEM_STATS_INC_USED(x, y) +#define MEM_STATS_DEC_USED(x, y) +#define MEM_STATS_DISPLAY() +#endif + + #if MEMP_STATS +#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i]->x) +#define MEMP_STATS_DISPLAY(i) stats_display_memp(lwip_stats.memp[i], i) +#define MEMP_STATS_GET(x, i) STATS_GET(memp[i]->x) + #else +#define MEMP_STATS_DEC(x, i) +#define MEMP_STATS_DISPLAY(i) +#define MEMP_STATS_GET(x, i) 0 +#endif + +#if SYS_STATS +#define SYS_STATS_INC(x) STATS_INC(sys.x) +#define SYS_STATS_DEC(x) STATS_DEC(sys.x) +#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1) +#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) +#else +#define SYS_STATS_INC(x) +#define SYS_STATS_DEC(x) +#define SYS_STATS_INC_USED(x) +#define SYS_STATS_DISPLAY() +#endif + +#if IP6_STATS +#define IP6_STATS_INC(x) STATS_INC(x) +#define IP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6, "IPv6") +#else +#define IP6_STATS_INC(x) +#define IP6_STATS_DISPLAY() +#endif + +#if ICMP6_STATS +#define ICMP6_STATS_INC(x) STATS_INC(x) +#define ICMP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp6, "ICMPv6") +#else +#define ICMP6_STATS_INC(x) +#define ICMP6_STATS_DISPLAY() +#endif + +#if IP6_FRAG_STATS +#define IP6_FRAG_STATS_INC(x) STATS_INC(x) +#define IP6_FRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6_frag, "IPv6 FRAG") +#else +#define IP6_FRAG_STATS_INC(x) +#define IP6_FRAG_STATS_DISPLAY() +#endif + +#if MLD6_STATS +#define MLD6_STATS_INC(x) STATS_INC(x) +#define MLD6_STATS_DISPLAY() stats_display_igmp(&lwip_stats.mld6, "MLDv1") +#else +#define MLD6_STATS_INC(x) +#define MLD6_STATS_DISPLAY() +#endif + +#if ND6_STATS +#define ND6_STATS_INC(x) STATS_INC(x) +#define ND6_STATS_DISPLAY() stats_display_proto(&lwip_stats.nd6, "ND") +#else +#define ND6_STATS_INC(x) +#define ND6_STATS_DISPLAY() +#endif + +#if MIB2_STATS +#define MIB2_STATS_INC(x) STATS_INC(x) +#else +#define MIB2_STATS_INC(x) +#endif + +/* Display of statistics */ +#if LWIP_STATS_DISPLAY +void stats_display(void); +void stats_display_proto(struct stats_proto *proto, const char *name); +void stats_display_igmp(struct stats_igmp *igmp, const char *name); +void stats_display_mem(struct stats_mem *mem, const char *name); +void stats_display_memp(struct stats_mem *mem, int index); +void stats_display_sys(struct stats_sys *sys); +#else /* LWIP_STATS_DISPLAY */ +#define stats_display() +#define stats_display_proto(proto, name) +#define stats_display_igmp(igmp, name) +#define stats_display_mem(mem, name) +#define stats_display_memp(mem, index) +#define stats_display_sys(sys) +#endif /* LWIP_STATS_DISPLAY */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_STATS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/sys.h b/components/net/lwip-2.0.3/src/include/lwip/sys.h new file mode 100644 index 0000000000..d12bae0f96 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/sys.h @@ -0,0 +1,455 @@ +/** + * @file + * OS abstraction layer + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +#ifndef LWIP_HDR_SYS_H +#define LWIP_HDR_SYS_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NO_SYS + +/* For a totally minimal and standalone system, we provide null + definitions of the sys_ functions. */ +typedef u8_t sys_sem_t; +typedef u8_t sys_mutex_t; +typedef u8_t sys_mbox_t; + +#define sys_sem_new(s, c) ERR_OK +#define sys_sem_signal(s) +#define sys_sem_wait(s) +#define sys_arch_sem_wait(s,t) +#define sys_sem_free(s) +#define sys_sem_valid(s) 0 +#define sys_sem_valid_val(s) 0 +#define sys_sem_set_invalid(s) +#define sys_sem_set_invalid_val(s) +#define sys_mutex_new(mu) ERR_OK +#define sys_mutex_lock(mu) +#define sys_mutex_unlock(mu) +#define sys_mutex_free(mu) +#define sys_mutex_valid(mu) 0 +#define sys_mutex_set_invalid(mu) +#define sys_mbox_new(m, s) ERR_OK +#define sys_mbox_fetch(m,d) +#define sys_mbox_tryfetch(m,d) +#define sys_mbox_post(m,d) +#define sys_mbox_trypost(m,d) +#define sys_mbox_free(m) +#define sys_mbox_valid(m) +#define sys_mbox_valid_val(m) +#define sys_mbox_set_invalid(m) +#define sys_mbox_set_invalid_val(m) + +#define sys_thread_new(n,t,a,s,p) + +#define sys_msleep(t) + +#else /* NO_SYS */ + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +#include "lwip/err.h" +#include "arch/sys_arch.h" + +/** Function prototype for thread functions */ +typedef void (*lwip_thread_fn)(void *arg); + +/* Function prototypes for functions to be implemented by platform ports + (in sys_arch.c) */ + +/* Mutex functions: */ + +/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores + should be used instead */ +#ifndef LWIP_COMPAT_MUTEX +#define LWIP_COMPAT_MUTEX 0 +#endif + +#if LWIP_COMPAT_MUTEX +/* for old ports that don't have mutexes: define them to binary semaphores */ +#define sys_mutex_t sys_sem_t +#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) +#define sys_mutex_lock(mutex) sys_sem_wait(mutex) +#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) +#define sys_mutex_free(mutex) sys_sem_free(mutex) +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +#else /* LWIP_COMPAT_MUTEX */ + +/** + * @ingroup sys_mutex + * Create a new mutex. + * Note that mutexes are expected to not be taken recursively by the lwIP code, + * so both implementation types (recursive or non-recursive) should work. + * @param mutex pointer to the mutex to create + * @return ERR_OK if successful, another err_t otherwise + */ +err_t sys_mutex_new(sys_mutex_t *mutex); +/** + * @ingroup sys_mutex + * Lock a mutex + * @param mutex the mutex to lock + */ +void sys_mutex_lock(sys_mutex_t *mutex); +/** + * @ingroup sys_mutex + * Unlock a mutex + * @param mutex the mutex to unlock + */ +void sys_mutex_unlock(sys_mutex_t *mutex); +/** + * @ingroup sys_mutex + * Delete a semaphore + * @param mutex the mutex to delete + */ +void sys_mutex_free(sys_mutex_t *mutex); +#ifndef sys_mutex_valid +/** + * @ingroup sys_mutex + * Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid + */ +int sys_mutex_valid(sys_mutex_t *mutex); +#endif +#ifndef sys_mutex_set_invalid +/** + * @ingroup sys_mutex + * Set a mutex invalid so that sys_mutex_valid returns 0 + */ +void sys_mutex_set_invalid(sys_mutex_t *mutex); +#endif +#endif /* LWIP_COMPAT_MUTEX */ + +/* Semaphore functions: */ + +/** + * @ingroup sys_sem + * Create a new semaphore + * @param sem pointer to the semaphore to create + * @param count initial count of the semaphore + * @return ERR_OK if successful, another err_t otherwise + */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count); +/** + * @ingroup sys_sem + * Signals a semaphore + * @param sem the semaphore to signal + */ +void sys_sem_signal(sys_sem_t *sem); +/** + * @ingroup sys_sem + * Wait for a semaphore for the specified timeout + * @param sem the semaphore to wait for + * @param timeout timeout in milliseconds to wait (0 = wait forever) + * @return time (in milliseconds) waited for the semaphore + * or SYS_ARCH_TIMEOUT on timeout + */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); +/** + * @ingroup sys_sem + * Delete a semaphore + * @param sem semaphore to delete + */ +void sys_sem_free(sys_sem_t *sem); +/** Wait for a semaphore - forever/no timeout */ +#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) +#ifndef sys_sem_valid +/** + * @ingroup sys_sem + * Check if a semaphore is valid/allocated: return 1 for valid, 0 for invalid + */ +int sys_sem_valid(sys_sem_t *sem); +#endif +#ifndef sys_sem_set_invalid +/** + * @ingroup sys_sem + * Set a semaphore invalid so that sys_sem_valid returns 0 + */ +void sys_sem_set_invalid(sys_sem_t *sem); +#endif +#ifndef sys_sem_valid_val +/** + * Same as sys_sem_valid() but taking a value, not a pointer + */ +#define sys_sem_valid_val(sem) sys_sem_valid(&(sem)) +#endif +#ifndef sys_sem_set_invalid_val +/** + * Same as sys_sem_set_invalid() but taking a value, not a pointer + */ +#define sys_sem_set_invalid_val(sem) sys_sem_set_invalid(&(sem)) +#endif + +#ifndef sys_msleep +/** + * @ingroup sys_misc + * Sleep for specified number of ms + */ +void sys_msleep(u32_t ms); /* only has a (close to) 1 ms resolution. */ +#endif + +/* Mailbox functions. */ + +/** + * @ingroup sys_mbox + * Create a new mbox of specified size + * @param mbox pointer to the mbox to create + * @param size (minimum) number of messages in this mbox + * @return ERR_OK if successful, another err_t otherwise + */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size); +/** + * @ingroup sys_mbox + * Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) + */ +void sys_mbox_post(sys_mbox_t *mbox, void *msg); +/** + * @ingroup sys_mbox + * Try to post a message to an mbox - may fail if full or ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) + */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); +/** + * @ingroup sys_mbox + * Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever) + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! + */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); +/* Allow port to override with a macro, e.g. special timeout for sys_arch_mbox_fetch() */ +#ifndef sys_arch_mbox_tryfetch +/** + * @ingroup sys_mbox + * Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @return 0 (milliseconds) if a message has been received + * or SYS_MBOX_EMPTY if the mailbox is empty + */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); +#endif +/** + * For now, we map straight to sys_arch implementation. + */ +#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) +/** + * @ingroup sys_mbox + * Delete an mbox + * @param mbox mbox to delete + */ +void sys_mbox_free(sys_mbox_t *mbox); +#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) +#ifndef sys_mbox_valid +/** + * @ingroup sys_mbox + * Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid + */ +int sys_mbox_valid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_set_invalid +/** + * @ingroup sys_mbox + * Set an mbox invalid so that sys_mbox_valid returns 0 + */ +void sys_mbox_set_invalid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_valid_val +/** + * Same as sys_mbox_valid() but taking a value, not a pointer + */ +#define sys_mbox_valid_val(mbox) sys_mbox_valid(&(mbox)) +#endif +#ifndef sys_mbox_set_invalid_val +/** + * Same as sys_mbox_set_invalid() but taking a value, not a pointer + */ +#define sys_mbox_set_invalid_val(mbox) sys_mbox_set_invalid(&(mbox)) +#endif + + +/** + * @ingroup sys_misc + * The only thread function: + * Creates a new thread + * ATTENTION: although this function returns a value, it MUST NOT FAIL (ports have to assert this!) + * @param name human-readable name for the thread (used for debugging purposes) + * @param thread thread-function + * @param arg parameter passed to 'thread' + * @param stacksize stack size in bytes for the new thread (may be ignored by ports) + * @param prio priority of the new thread (may be ignored by ports) */ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio); + +#endif /* NO_SYS */ + +/* sys_init() must be called before anything else. */ +void sys_init(void); + +#ifndef sys_jiffies +/** + * Ticks/jiffies since power up. + */ +u32_t sys_jiffies(void); +#endif + +/** + * @ingroup sys_time + * Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. + */ +u32_t sys_now(void); + +/* Critical Region Protection */ +/* These functions must be implemented in the sys_arch.c file. + In some implementations they can provide a more light-weight protection + mechanism than using semaphores. Otherwise semaphores can be used for + implementation */ +#ifndef SYS_ARCH_PROTECT +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#if SYS_LIGHTWEIGHT_PROT + +/** + * @ingroup sys_prot + * SYS_ARCH_DECL_PROTECT + * declare a protection variable. This macro will default to defining a variable of + * type sys_prot_t. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h. + */ +#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev +/** + * @ingroup sys_prot + * SYS_ARCH_PROTECT + * Perform a "fast" protect. This could be implemented by + * disabling interrupts for an embedded system or by using a semaphore or + * mutex. The implementation should allow calling SYS_ARCH_PROTECT when + * already protected. The old protection level is returned in the variable + * "lev". This macro will default to calling the sys_arch_protect() function + * which should be implemented in sys_arch.c. If a particular port needs a + * different implementation, then this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() +/** + * @ingroup sys_prot + * SYS_ARCH_UNPROTECT + * Perform a "fast" set of the protection level to "lev". This could be + * implemented by setting the interrupt level to "lev" within the MACRO or by + * using a semaphore or mutex. This macro will default to calling the + * sys_arch_unprotect() function which should be implemented in + * sys_arch.c. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) +sys_prot_t sys_arch_protect(void); +void sys_arch_unprotect(sys_prot_t pval); + +#else + +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) +#define SYS_ARCH_UNPROTECT(lev) + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#endif /* SYS_ARCH_PROTECT */ + +/* + * Macros to set/get and increase/decrease variables in a thread-safe way. + * Use these for accessing variable that are used from more than one thread. + */ + +#ifndef SYS_ARCH_INC +#define SYS_ARCH_INC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var += val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_INC */ + +#ifndef SYS_ARCH_DEC +#define SYS_ARCH_DEC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var -= val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_DEC */ + +#ifndef SYS_ARCH_GET +#define SYS_ARCH_GET(var, ret) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + ret = var; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_GET */ + +#ifndef SYS_ARCH_SET +#define SYS_ARCH_SET(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var = val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_SET */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_SYS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/tcp.h b/components/net/lwip-2.0.3/src/include/lwip/tcp.h new file mode 100644 index 0000000000..34d1c10158 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/tcp.h @@ -0,0 +1,433 @@ +/** + * @file + * TCP API (to be used from TCPIP thread)\n + * See also @ref tcp_raw + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCP_H +#define LWIP_HDR_TCP_H + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct tcp_pcb; + +/** Function prototype for tcp accept callback functions. Called when a new + * connection can be accepted on a listening pcb. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param newpcb The new connection pcb + * @param err An error code if there has been an error accepting. + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err); + +/** Function prototype for tcp receive callback functions. Called when data has + * been received. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which received data + * @param p The received data (or NULL when the connection has been closed!) + * @param err An error code if there has been an error receiving + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err); + +/** Function prototype for tcp sent callback functions. Called when sent data has + * been acknowledged by the remote side. Use it to free corresponding resources. + * This also means that the pcb has now space available to send new data. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb for which data has been acknowledged + * @param len The amount of bytes acknowledged + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb, + u16_t len); + +/** Function prototype for tcp poll callback functions. Called periodically as + * specified by @see tcp_poll. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb tcp pcb + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb); + +/** Function prototype for tcp error callback functions. Called when the pcb + * receives a RST or is unexpectedly closed for any other reason. + * + * @note The corresponding pcb is already freed when this callback is called! + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param err Error code to indicate why the pcb has been closed + * ERR_ABRT: aborted through tcp_abort or by a TCP timer + * ERR_RST: the connection was reset by the remote host + */ +typedef void (*tcp_err_fn)(void *arg, err_t err); + +/** Function prototype for tcp connected callback functions. Called when a pcb + * is connected to the remote side after initiating a connection attempt by + * calling tcp_connect(). + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which is connected + * @param err An unused error code, always ERR_OK currently ;-) @todo! + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + * + * @note When a connection attempt fails, the error callback is currently called! + */ +typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); + +#if LWIP_WND_SCALE +#define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale)) +#define SND_WND_SCALE(pcb, wnd) (((wnd) << (pcb)->snd_scale)) +#define TCPWND16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) +#define TCP_WND_MAX(pcb) ((tcpwnd_size_t)(((pcb)->flags & TF_WND_SCALE) ? TCP_WND : TCPWND16(TCP_WND))) +typedef u32_t tcpwnd_size_t; +#else +#define RCV_WND_SCALE(pcb, wnd) (wnd) +#define SND_WND_SCALE(pcb, wnd) (wnd) +#define TCPWND16(x) (x) +#define TCP_WND_MAX(pcb) TCP_WND +typedef u16_t tcpwnd_size_t; +#endif + +#if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG || LWIP_TCP_TIMESTAMPS +typedef u16_t tcpflags_t; +#else +typedef u8_t tcpflags_t; +#endif + +enum tcp_state { + CLOSED = 0, + LISTEN = 1, + SYN_SENT = 2, + SYN_RCVD = 3, + ESTABLISHED = 4, + FIN_WAIT_1 = 5, + FIN_WAIT_2 = 6, + CLOSE_WAIT = 7, + CLOSING = 8, + LAST_ACK = 9, + TIME_WAIT = 10 +}; + +/** + * members common to struct tcp_pcb and struct tcp_listen_pcb + */ +#define TCP_PCB_COMMON(type) \ + type *next; /* for the linked list */ \ + void *callback_arg; \ + enum tcp_state state; /* TCP state */ \ + u8_t prio; \ + /* ports are in host byte order */ \ + u16_t local_port + + +/** the TCP protocol control block for listening pcbs */ +struct tcp_pcb_listen { +/** Common members of all PCB types */ + IP_PCB; +/** Protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb_listen); + +#if LWIP_CALLBACK_API + /* Function to call when a listener has been connected. */ + tcp_accept_fn accept; +#endif /* LWIP_CALLBACK_API */ + +#if TCP_LISTEN_BACKLOG + u8_t backlog; + u8_t accepts_pending; +#endif /* TCP_LISTEN_BACKLOG */ +}; + + +/** the TCP protocol control block */ +struct tcp_pcb { +/** common PCB members */ + IP_PCB; +/** protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb); + + /* ports are in host byte order */ + u16_t remote_port; + + tcpflags_t flags; +#define TF_ACK_DELAY 0x01U /* Delayed ACK. */ +#define TF_ACK_NOW 0x02U /* Immediate ACK. */ +#define TF_INFR 0x04U /* In fast recovery. */ +#define TF_CLOSEPEND 0x08U /* If this is set, tcp_close failed to enqueue the FIN (retried in tcp_tmr) */ +#define TF_RXCLOSED 0x10U /* rx closed by tcp_shutdown */ +#define TF_FIN 0x20U /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY 0x40U /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR 0x80U /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ +#if LWIP_WND_SCALE +#define TF_WND_SCALE 0x0100U /* Window Scale option enabled */ +#endif +#if TCP_LISTEN_BACKLOG +#define TF_BACKLOGPEND 0x0200U /* If this is set, a connection pcb has increased the backlog on its listener */ +#endif +#if LWIP_TCP_TIMESTAMPS +#define TF_TIMESTAMP 0x0400U /* Timestamp option enabled */ +#endif + + /* the rest of the fields are in host byte order + as we have to do some math with them */ + + /* Timers */ + u8_t polltmr, pollinterval; + u8_t last_timer; + u32_t tmr; + + /* receiver variables */ + u32_t rcv_nxt; /* next seqno expected */ + tcpwnd_size_t rcv_wnd; /* receiver window available */ + tcpwnd_size_t rcv_ann_wnd; /* receiver window to announce */ + u32_t rcv_ann_right_edge; /* announced right edge of window */ + + /* Retransmission timer. */ + s16_t rtime; + + u16_t mss; /* maximum segment size */ + + /* RTT (round trip time) estimation variables */ + u32_t rttest; /* RTT estimate in 500ms ticks */ + u32_t rtseq; /* sequence number being timed */ + s16_t sa, sv; /* @todo document this */ + + s16_t rto; /* retransmission time-out */ + u8_t nrtx; /* number of retransmissions */ + + /* fast retransmit/recovery */ + u8_t dupacks; + u32_t lastack; /* Highest acknowledged seqno. */ + + /* congestion avoidance/control variables */ + tcpwnd_size_t cwnd; + tcpwnd_size_t ssthresh; + + /* sender variables */ + u32_t snd_nxt; /* next new seqno to be sent */ + u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last + window update. */ + u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ + tcpwnd_size_t snd_wnd; /* sender window */ + tcpwnd_size_t snd_wnd_max; /* the maximum sender window announced by the remote host */ + + tcpwnd_size_t snd_buf; /* Available buffer space for sending (in bytes). */ +#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3) + u16_t snd_queuelen; /* Number of pbufs currently in the send buffer. */ + +#if TCP_OVERSIZE + /* Extra bytes available at the end of the last pbuf in unsent. */ + u16_t unsent_oversize; +#endif /* TCP_OVERSIZE */ + + /* These are ordered by sequence number: */ + struct tcp_seg *unsent; /* Unsent (queued) segments. */ + struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ +#if TCP_QUEUE_OOSEQ + struct tcp_seg *ooseq; /* Received out of sequence segments. */ +#endif /* TCP_QUEUE_OOSEQ */ + + struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ + +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG + struct tcp_pcb_listen* listener; +#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ + +#if LWIP_CALLBACK_API + /* Function to be called when more send buffer space is available. */ + tcp_sent_fn sent; + /* Function to be called when (in-sequence) data has arrived. */ + tcp_recv_fn recv; + /* Function to be called when a connection has been set up. */ + tcp_connected_fn connected; + /* Function which is called periodically. */ + tcp_poll_fn poll; + /* Function to be called whenever a fatal error occurs. */ + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + +#if LWIP_TCP_TIMESTAMPS + u32_t ts_lastacksent; + u32_t ts_recent; +#endif /* LWIP_TCP_TIMESTAMPS */ + + /* idle time before KEEPALIVE is sent */ + u32_t keep_idle; +#if LWIP_TCP_KEEPALIVE + u32_t keep_intvl; + u32_t keep_cnt; +#endif /* LWIP_TCP_KEEPALIVE */ + + /* Persist timer counter */ + u8_t persist_cnt; + /* Persist timer back-off */ + u8_t persist_backoff; + + /* KEEPALIVE counter */ + u8_t keep_cnt_sent; + +#if LWIP_WND_SCALE + u8_t snd_scale; + u8_t rcv_scale; +#endif +}; + +#if LWIP_EVENT_API + +enum lwip_event { + LWIP_EVENT_ACCEPT, + LWIP_EVENT_SENT, + LWIP_EVENT_RECV, + LWIP_EVENT_CONNECTED, + LWIP_EVENT_POLL, + LWIP_EVENT_ERR +}; + +err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, + enum lwip_event, + struct pbuf *p, + u16_t size, + err_t err); + +#endif /* LWIP_EVENT_API */ + +/* Application program's interface: */ +struct tcp_pcb * tcp_new (void); +struct tcp_pcb * tcp_new_ip_type (u8_t type); + +void tcp_arg (struct tcp_pcb *pcb, void *arg); +#if LWIP_CALLBACK_API +void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv); +void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent); +void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); +void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept); +#endif /* LWIP_CALLBACK_API */ +void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); + +#if LWIP_TCP_TIMESTAMPS +#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) +#else /* LWIP_TCP_TIMESTAMPS */ +#define tcp_mss(pcb) ((pcb)->mss) +#endif /* LWIP_TCP_TIMESTAMPS */ +#define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf)) +#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) +/** @ingroup tcp_raw */ +#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) +/** @ingroup tcp_raw */ +#define tcp_nagle_enable(pcb) ((pcb)->flags = (tcpflags_t)((pcb)->flags & ~TF_NODELAY)) +/** @ingroup tcp_raw */ +#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) + +#if TCP_LISTEN_BACKLOG +#define tcp_backlog_set(pcb, new_backlog) do { \ + LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", (pcb)->state == LISTEN); \ + ((struct tcp_pcb_listen *)(pcb))->backlog = ((new_backlog) ? (new_backlog) : 1); } while(0) +void tcp_backlog_delayed(struct tcp_pcb* pcb); +void tcp_backlog_accepted(struct tcp_pcb* pcb); +#else /* TCP_LISTEN_BACKLOG */ +#define tcp_backlog_set(pcb, new_backlog) +#define tcp_backlog_delayed(pcb) +#define tcp_backlog_accepted(pcb) +#endif /* TCP_LISTEN_BACKLOG */ +#define tcp_accepted(pcb) /* compatibility define, not needed any more */ + +void tcp_recved (struct tcp_pcb *pcb, u16_t len); +err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port); +err_t tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port, tcp_connected_fn connected); + +struct tcp_pcb * tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err); +struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); +/** @ingroup tcp_raw */ +#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) + +void tcp_abort (struct tcp_pcb *pcb); +err_t tcp_close (struct tcp_pcb *pcb); +err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx); + +/* Flags for "apiflags" parameter in tcp_write */ +#define TCP_WRITE_FLAG_COPY 0x01 +#define TCP_WRITE_FLAG_MORE 0x02 + +err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags); + +void tcp_setprio (struct tcp_pcb *pcb, u8_t prio); + +#define TCP_PRIO_MIN 1 +#define TCP_PRIO_NORMAL 64 +#define TCP_PRIO_MAX 127 + +err_t tcp_output (struct tcp_pcb *pcb); + + +const char* tcp_debug_state_str(enum tcp_state s); + +/* for compatibility with older implementation */ +#define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* LWIP_HDR_TCP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/tcpip.h b/components/net/lwip-2.0.3/src/include/lwip/tcpip.h new file mode 100644 index 0000000000..f2f6b469f1 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/tcpip.h @@ -0,0 +1,106 @@ +/** + * @file + * Functions to sync with TCPIP thread + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCPIP_H +#define LWIP_HDR_TCPIP_H + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/err.h" +#include "lwip/timeouts.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +extern sys_mutex_t lock_tcpip_core; +/** Lock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */ +#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) +/** Unlock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */ +#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define LOCK_TCPIP_CORE() +#define UNLOCK_TCPIP_CORE() +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +struct pbuf; +struct netif; + +/** Function prototype for the init_done function passed to tcpip_init */ +typedef void (*tcpip_init_done_fn)(void *arg); +/** Function prototype for functions passed to tcpip_callback() */ +typedef void (*tcpip_callback_fn)(void *ctx); + +/* Forward declarations */ +struct tcpip_callback_msg; + +void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg); + +err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn); +err_t tcpip_input(struct pbuf *p, struct netif *inp); + +err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block); +/** + * @ingroup lwip_os + * @see tcpip_callback_with_block + */ +#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1) + +struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx); +void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg); +err_t tcpip_trycallback(struct tcpip_callback_msg* msg); + +/* free pbufs or heap memory from another context without blocking */ +err_t pbuf_free_callback(struct pbuf *p); +err_t mem_free_callback(void *m); + +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS +err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +err_t tcpip_untimeout(sys_timeout_handler h, void *arg); +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* LWIP_HDR_TCPIP_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/timeouts.h b/components/net/lwip-2.0.3/src/include/lwip/timeouts.h new file mode 100644 index 0000000000..c9b93aa02a --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/timeouts.h @@ -0,0 +1,121 @@ +/** + * @file + * Timer implementations + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_TIMEOUTS_H +#define LWIP_HDR_TIMEOUTS_H + +#include "lwip/opt.h" +#include "lwip/err.h" +#if !NO_SYS +#include "lwip/sys.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LWIP_DEBUG_TIMERNAMES +#ifdef LWIP_DEBUG +#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG +#else /* LWIP_DEBUG */ +#define LWIP_DEBUG_TIMERNAMES 0 +#endif /* LWIP_DEBUG*/ +#endif + +/** Function prototype for a stack-internal timer function that has to be + * called at a defined interval */ +typedef void (* lwip_cyclic_timer_handler)(void); + +/** This struct contains information about a stack-internal timer function + that has to be called at a defined interval */ +struct lwip_cyclic_timer { + u32_t interval_ms; + lwip_cyclic_timer_handler handler; +#if LWIP_DEBUG_TIMERNAMES + const char* handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ +}; + +/** This array contains all stack-internal cyclic timers. To get the number of + * timers, use LWIP_ARRAYSIZE() */ +extern const struct lwip_cyclic_timer lwip_cyclic_timers[]; + +#if LWIP_TIMERS + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ +typedef void (* sys_timeout_handler)(void *arg); + +struct sys_timeo { + struct sys_timeo *next; + u32_t time; + sys_timeout_handler h; + void *arg; +#if LWIP_DEBUG_TIMERNAMES + const char* handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ +}; + +void sys_timeouts_init(void); + +#if LWIP_DEBUG_TIMERNAMES +void sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); +#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler) +#else /* LWIP_DEBUG_TIMERNAMES */ +void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg); +#endif /* LWIP_DEBUG_TIMERNAMES */ + +void sys_untimeout(sys_timeout_handler handler, void *arg); +void sys_restart_timeouts(void); +#if NO_SYS +void sys_check_timeouts(void); +u32_t sys_timeouts_sleeptime(void); +#else /* NO_SYS */ +void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg); +#endif /* NO_SYS */ + + +#endif /* LWIP_TIMERS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_TIMEOUTS_H */ diff --git a/components/net/lwip-2.0.3/src/include/lwip/udp.h b/components/net/lwip-2.0.3/src/include/lwip/udp.h new file mode 100644 index 0000000000..b929907394 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/lwip/udp.h @@ -0,0 +1,182 @@ +/** + * @file + * UDP API (to be used from TCPIP thread)\n + * See also @ref udp_raw + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_UDP_H +#define LWIP_HDR_UDP_H + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" +#include "lwip/ip6_addr.h" +#include "lwip/prot/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_FLAGS_NOCHKSUM 0x01U +#define UDP_FLAGS_UDPLITE 0x02U +#define UDP_FLAGS_CONNECTED 0x04U +#define UDP_FLAGS_MULTICAST_LOOP 0x08U + +struct udp_pcb; + +/** Function prototype for udp pcb receive callback functions + * addr and port are in same byte order as in the pcb + * The callback is responsible for freeing the pbuf + * if it's not used any more. + * + * ATTENTION: Be aware that 'addr' might point into the pbuf 'p' so freeing this pbuf + * can make 'addr' invalid, too. + * + * @param arg user supplied argument (udp_pcb.recv_arg) + * @param pcb the udp_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @param port the remote port from which the packet was received + */ +typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr, u16_t port); + +/** the UDP protocol control block */ +struct udp_pcb { +/** Common members of all PCB types */ + IP_PCB; + +/* Protocol specific PCB members */ + + struct udp_pcb *next; + + u8_t flags; + /** ports are in host byte order */ + u16_t local_port, remote_port; + +#if LWIP_MULTICAST_TX_OPTIONS + /** outgoing network interface for multicast packets */ + ip_addr_t multicast_ip; + /** TTL for outgoing multicast packets */ + u8_t mcast_ttl; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#if LWIP_UDPLITE + /** used for UDP_LITE only */ + u16_t chksum_len_rx, chksum_len_tx; +#endif /* LWIP_UDPLITE */ + + /** receive callback function */ + udp_recv_fn recv; + /** user-supplied argument for the recv callback */ + void *recv_arg; +}; +/* udp_pcbs export for external reference (e.g. SNMP agent) */ +extern struct udp_pcb *udp_pcbs; + +/* The following functions is the application layer interface to the + UDP code. */ +struct udp_pcb * udp_new (void); +struct udp_pcb * udp_new_ip_type(u8_t type); +void udp_remove (struct udp_pcb *pcb); +err_t udp_bind (struct udp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port); +err_t udp_connect (struct udp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port); +void udp_disconnect (struct udp_pcb *pcb); +void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, + void *recv_arg); +err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif); +err_t udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, const ip_addr_t *src_ip); +err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port); +err_t udp_send (struct udp_pcb *pcb, struct pbuf *p); + +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, u8_t have_chksum, + u16_t chksum); +err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + u8_t have_chksum, u16_t chksum); +err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum); +err_t udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, + u8_t have_chksum, u16_t chksum, const ip_addr_t *src_ip); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + +#define udp_flags(pcb) ((pcb)->flags) +#define udp_setflags(pcb, f) ((pcb)->flags = (f)) + +/* The following functions are the lower layer interface to UDP. */ +void udp_input (struct pbuf *p, struct netif *inp); + +void udp_init (void); + +/* for compatibility with older implementation */ +#define udp_new_ip6() udp_new_ip_type(IPADDR_TYPE_V6) + +#if LWIP_MULTICAST_TX_OPTIONS +#define udp_set_multicast_netif_addr(pcb, ip4addr) ip_addr_copy_from_ip4((pcb)->multicast_ip, *(ip4addr)) +#define udp_get_multicast_netif_addr(pcb) ip_2_ip4(&(pcb)->multicast_ip) +#define udp_set_multicast_ttl(pcb, value) do { (pcb)->mcast_ttl = value; } while(0) +#define udp_get_multicast_ttl(pcb) ((pcb)->mcast_ttl) +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#if UDP_DEBUG +void udp_debug_print(struct udp_hdr *udphdr); +#else +#define udp_debug_print(udphdr) +#endif + +void udp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_UDP */ + +#endif /* LWIP_HDR_UDP_H */ diff --git a/components/net/lwip-2.0.3/src/include/netif/etharp.h b/components/net/lwip-2.0.3/src/include/netif/etharp.h new file mode 100644 index 0000000000..b536fd280f --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/etharp.h @@ -0,0 +1,3 @@ +/* ARP has been moved to core/ipv4, provide this #include for compatibility only */ +#include "lwip/etharp.h" +#include "netif/ethernet.h" diff --git a/components/net/lwip-2.0.3/src/include/netif/ethernet.h b/components/net/lwip-2.0.3/src/include/netif/ethernet.h new file mode 100644 index 0000000000..49649cbf8b --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ethernet.h @@ -0,0 +1,77 @@ +/** + * @file + * Ethernet input function - handles INCOMING ethernet level traffic + * To be used in most low-level netif implementations + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_NETIF_ETHERNET_H +#define LWIP_HDR_NETIF_ETHERNET_H + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/prot/ethernet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_ARP || LWIP_ETHERNET + +/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) + * to a filter function that returns the correct netif when using multiple + * netifs on one hardware interface where the netif's low-level receive + * routine cannot decide for the correct netif (e.g. when mapping multiple + * IP addresses to one hardware interface). + */ +#ifndef LWIP_ARP_FILTER_NETIF +#define LWIP_ARP_FILTER_NETIF 0 +#endif + +err_t ethernet_input(struct pbuf *p, struct netif *netif); +err_t ethernet_output(struct netif* netif, struct pbuf* p, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type); + +extern const struct eth_addr ethbroadcast, ethzero; + +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_ETHERNET_H */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ethernetif.h b/components/net/lwip-2.0.3/src/include/netif/ethernetif.h new file mode 100644 index 0000000000..1459e3241d --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ethernetif.h @@ -0,0 +1,53 @@ +#ifndef __NETIF_ETHERNETIF_H__ +#define __NETIF_ETHERNETIF_H__ + +#include "lwip/netif.h" +#include + +#define NIOCTL_GADDR 0x01 +#ifndef RT_LWIP_ETH_MTU +#define ETHERNET_MTU 1500 +#else +#define ETHERNET_MTU RT_LWIP_ETH_MTU +#endif + +/* eth flag with auto_linkup or phy_linkup */ +#define ETHIF_LINK_AUTOUP 0x0000 +#define ETHIF_LINK_PHYUP 0x0100 + +struct eth_device +{ + /* inherit from rt_device */ + struct rt_device parent; + + /* network interface for lwip */ + struct netif *netif; + struct rt_semaphore tx_ack; + + rt_uint16_t flags; + rt_uint8_t link_changed; + rt_uint8_t link_status; + rt_uint8_t rx_notice; + + /* eth device interface */ + struct pbuf* (*eth_rx)(rt_device_t dev); + rt_err_t (*eth_tx)(rt_device_t dev, struct pbuf* p); +}; + +#ifdef __cplusplus +extern "C" { +#endif + + rt_err_t eth_device_ready(struct eth_device* dev); + rt_err_t eth_device_init(struct eth_device * dev, const char *name); + rt_err_t eth_device_init_with_flag(struct eth_device *dev, const char *name, rt_uint16_t flag); + rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up); + void eth_device_deinit(struct eth_device *dev); + + int eth_system_device_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __NETIF_ETHERNETIF_H__ */ diff --git a/components/net/lwip-2.0.3/src/include/netif/lowpan6.h b/components/net/lwip-2.0.3/src/include/netif/lowpan6.h new file mode 100644 index 0000000000..4174644bb3 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/lowpan6.h @@ -0,0 +1,86 @@ +/** + * @file + * + * 6LowPAN output for IPv6. Uses ND tables for link-layer addressing. Fragments packets to 6LowPAN units. + */ + +/* + * Copyright (c) 2015 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_LOWPAN6_H +#define LWIP_HDR_LOWPAN6_H + +#include "netif/lowpan6_opts.h" + +#if LWIP_IPV6 && LWIP_6LOWPAN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** 1 second period */ +#define LOWPAN6_TMR_INTERVAL 1000 + +void lowpan6_tmr(void); + +err_t lowpan6_set_context(u8_t index, const ip6_addr_t * context); +err_t lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low); + +#if LWIP_IPV4 +err_t lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr); +#endif /* LWIP_IPV4 */ +err_t lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr); +err_t lowpan6_input(struct pbuf * p, struct netif *netif); +err_t lowpan6_if_init(struct netif *netif); + +/* pan_id in network byte order. */ +err_t lowpan6_set_pan_id(u16_t pan_id); + +#if !NO_SYS +err_t tcpip_6lowpan_input(struct pbuf *p, struct netif *inp); +#endif /* !NO_SYS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 && LWIP_6LOWPAN */ + +#endif /* LWIP_HDR_LOWPAN6_H */ diff --git a/components/net/lwip-2.0.3/src/include/netif/lowpan6_opts.h b/components/net/lwip-2.0.3/src/include/netif/lowpan6_opts.h new file mode 100644 index 0000000000..fb93ea05de --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/lowpan6_opts.h @@ -0,0 +1,70 @@ +/** + * @file + * 6LowPAN options list + */ + +/* + * Copyright (c) 2015 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_LOWPAN6_OPTS_H +#define LWIP_HDR_LOWPAN6_OPTS_H + +#include "lwip/opt.h" + +#ifndef LWIP_6LOWPAN +#define LWIP_6LOWPAN 0 +#endif + +#ifndef LWIP_6LOWPAN_NUM_CONTEXTS +#define LWIP_6LOWPAN_NUM_CONTEXTS 10 +#endif + +#ifndef LWIP_6LOWPAN_INFER_SHORT_ADDRESS +#define LWIP_6LOWPAN_INFER_SHORT_ADDRESS 1 +#endif + +#ifndef LWIP_6LOWPAN_IPHC +#define LWIP_6LOWPAN_IPHC 1 +#endif + +#ifndef LWIP_6LOWPAN_HW_CRC +#define LWIP_6LOWPAN_HW_CRC 1 +#endif + +#ifndef LOWPAN6_DEBUG +#define LOWPAN6_DEBUG LWIP_DBG_OFF +#endif + +#endif /* LWIP_HDR_LOWPAN6_OPTS_H */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/ccp.h b/components/net/lwip-2.0.3/src/include/netif/ppp/ccp.h new file mode 100644 index 0000000000..14dd65962c --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/ccp.h @@ -0,0 +1,156 @@ +/* + * ccp.h - Definitions for PPP Compression Control Protocol. + * + * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ccp.h,v 1.12 2004/11/04 10:02:26 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef CCP_H +#define CCP_H + +/* + * CCP codes. + */ + +#define CCP_CONFREQ 1 +#define CCP_CONFACK 2 +#define CCP_TERMREQ 5 +#define CCP_TERMACK 6 +#define CCP_RESETREQ 14 +#define CCP_RESETACK 15 + +/* + * Max # bytes for a CCP option + */ + +#define CCP_MAX_OPTION_LENGTH 32 + +/* + * Parts of a CCP packet. + */ + +#define CCP_CODE(dp) ((dp)[0]) +#define CCP_ID(dp) ((dp)[1]) +#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3]) +#define CCP_HDRLEN 4 + +#define CCP_OPT_CODE(dp) ((dp)[0]) +#define CCP_OPT_LENGTH(dp) ((dp)[1]) +#define CCP_OPT_MINLEN 2 + +#if BSDCOMPRESS_SUPPORT +/* + * Definitions for BSD-Compress. + */ + +#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */ +#define CILEN_BSD_COMPRESS 3 /* length of config. option */ + +/* Macros for handling the 3rd byte of the BSD-Compress config option. */ +#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */ +#define BSD_VERSION(x) ((x) >> 5) /* version of option format */ +#define BSD_CURRENT_VERSION 1 /* current version number */ +#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n)) + +#define BSD_MIN_BITS 9 /* smallest code size supported */ +#define BSD_MAX_BITS 15 /* largest code size supported */ +#endif /* BSDCOMPRESS_SUPPORT */ + +#if DEFLATE_SUPPORT +/* + * Definitions for Deflate. + */ + +#define CI_DEFLATE 26 /* config option for Deflate */ +#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */ +#define CILEN_DEFLATE 4 /* length of its config option */ + +#define DEFLATE_MIN_SIZE 9 +#define DEFLATE_MAX_SIZE 15 +#define DEFLATE_METHOD_VAL 8 +#define DEFLATE_SIZE(x) (((x) >> 4) + 8) +#define DEFLATE_METHOD(x) ((x) & 0x0F) +#define DEFLATE_MAKE_OPT(w) ((((w) - 8) << 4) + DEFLATE_METHOD_VAL) +#define DEFLATE_CHK_SEQUENCE 0 +#endif /* DEFLATE_SUPPORT */ + +#if MPPE_SUPPORT +/* + * Definitions for MPPE. + */ + +#define CI_MPPE 18 /* config option for MPPE */ +#define CILEN_MPPE 6 /* length of config option */ +#endif /* MPPE_SUPPORT */ + +#if PREDICTOR_SUPPORT +/* + * Definitions for other, as yet unsupported, compression methods. + */ + +#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */ +#define CILEN_PREDICTOR_1 2 /* length of its config option */ +#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */ +#define CILEN_PREDICTOR_2 2 /* length of its config option */ +#endif /* PREDICTOR_SUPPORT */ + +typedef struct ccp_options { +#if DEFLATE_SUPPORT + unsigned int deflate :1; /* do Deflate? */ + unsigned int deflate_correct :1; /* use correct code for deflate? */ + unsigned int deflate_draft :1; /* use draft RFC code for deflate? */ +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + unsigned int bsd_compress :1; /* do BSD Compress? */ +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + unsigned int predictor_1 :1; /* do Predictor-1? */ + unsigned int predictor_2 :1; /* do Predictor-2? */ +#endif /* PREDICTOR_SUPPORT */ + +#if MPPE_SUPPORT + u8_t mppe; /* MPPE bitfield */ +#endif /* MPPE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + u_short bsd_bits; /* # bits/code for BSD Compress */ +#endif /* BSDCOMPRESS_SUPPORT */ +#if DEFLATE_SUPPORT + u_short deflate_size; /* lg(window size) for Deflate */ +#endif /* DEFLATE_SUPPORT */ + u8_t method; /* code for chosen compression method */ +} ccp_options; + +extern const struct protent ccp_protent; + +void ccp_resetrequest(ppp_pcb *pcb); /* Issue a reset-request. */ + +#endif /* CCP_H */ +#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/chap-md5.h b/components/net/lwip-2.0.3/src/include/netif/ppp/chap-md5.h new file mode 100644 index 0000000000..eb0269fe50 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/chap-md5.h @@ -0,0 +1,36 @@ +/* + * chap-md5.h - New CHAP/MD5 implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +extern const struct chap_digest_type md5_digest; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/chap-new.h b/components/net/lwip-2.0.3/src/include/netif/ppp/chap-new.h new file mode 100644 index 0000000000..64eae32202 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/chap-new.h @@ -0,0 +1,192 @@ +/* + * chap-new.c - New CHAP implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef CHAP_H +#define CHAP_H + +#include "ppp.h" + +/* + * CHAP packets begin with a standard header with code, id, len (2 bytes). + */ +#define CHAP_HDRLEN 4 + +/* + * Values for the code field. + */ +#define CHAP_CHALLENGE 1 +#define CHAP_RESPONSE 2 +#define CHAP_SUCCESS 3 +#define CHAP_FAILURE 4 + +/* + * CHAP digest codes. + */ +#define CHAP_MD5 5 +#if MSCHAP_SUPPORT +#define CHAP_MICROSOFT 0x80 +#define CHAP_MICROSOFT_V2 0x81 +#endif /* MSCHAP_SUPPORT */ + +/* + * Semi-arbitrary limits on challenge and response fields. + */ +#define MAX_CHALLENGE_LEN 64 +#define MAX_RESPONSE_LEN 64 + +/* + * These limits apply to challenge and response packets we send. + * The +4 is the +1 that we actually need rounded up. + */ +#define CHAL_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_CHALLENGE_LEN + MAXNAMELEN) +#define RESP_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_RESPONSE_LEN + MAXNAMELEN) + +/* bitmask of supported algorithms */ +#if MSCHAP_SUPPORT +#define MDTYPE_MICROSOFT_V2 0x1 +#define MDTYPE_MICROSOFT 0x2 +#endif /* MSCHAP_SUPPORT */ +#define MDTYPE_MD5 0x4 +#define MDTYPE_NONE 0 + +#if MSCHAP_SUPPORT +/* Return the digest alg. ID for the most preferred digest type. */ +#define CHAP_DIGEST(mdtype) \ + ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ + ((mdtype) & MDTYPE_MICROSOFT_V2)? CHAP_MICROSOFT_V2: \ + ((mdtype) & MDTYPE_MICROSOFT)? CHAP_MICROSOFT: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_DIGEST(mdtype) \ + ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* Return the bit flag (lsb set) for our most preferred digest type. */ +#define CHAP_MDTYPE(mdtype) ((mdtype) ^ ((mdtype) - 1)) & (mdtype) + +/* Return the bit flag for a given digest algorithm ID. */ +#if MSCHAP_SUPPORT +#define CHAP_MDTYPE_D(digest) \ + ((digest) == CHAP_MICROSOFT_V2)? MDTYPE_MICROSOFT_V2: \ + ((digest) == CHAP_MICROSOFT)? MDTYPE_MICROSOFT: \ + ((digest) == CHAP_MD5)? MDTYPE_MD5: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_MDTYPE_D(digest) \ + ((digest) == CHAP_MD5)? MDTYPE_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* Can we do the requested digest? */ +#if MSCHAP_SUPPORT +#define CHAP_CANDIGEST(mdtype, digest) \ + ((digest) == CHAP_MICROSOFT_V2)? (mdtype) & MDTYPE_MICROSOFT_V2: \ + ((digest) == CHAP_MICROSOFT)? (mdtype) & MDTYPE_MICROSOFT: \ + ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_CANDIGEST(mdtype, digest) \ + ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* + * The code for each digest type has to supply one of these. + */ +struct chap_digest_type { + int code; + +#if PPP_SERVER + /* + * Note: challenge and response arguments below are formatted as + * a length byte followed by the actual challenge/response data. + */ + void (*generate_challenge)(ppp_pcb *pcb, unsigned char *challenge); + int (*verify_response)(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space); +#endif /* PPP_SERVER */ + void (*make_response)(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *priv); + int (*check_success)(ppp_pcb *pcb, unsigned char *pkt, int len, unsigned char *priv); + void (*handle_failure)(ppp_pcb *pcb, unsigned char *pkt, int len); +}; + +/* + * Each interface is described by chap structure. + */ +#if CHAP_SUPPORT +typedef struct chap_client_state { + u8_t flags; + const char *name; + const struct chap_digest_type *digest; + unsigned char priv[64]; /* private area for digest's use */ +} chap_client_state; + +#if PPP_SERVER +typedef struct chap_server_state { + u8_t flags; + u8_t id; + const char *name; + const struct chap_digest_type *digest; + int challenge_xmits; + int challenge_pktlen; + unsigned char challenge[CHAL_MAX_PKTLEN]; +} chap_server_state; +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPORT */ + +#if 0 /* UNUSED */ +/* Hook for a plugin to validate CHAP challenge */ +extern int (*chap_verify_hook)(char *name, char *ourname, int id, + const struct chap_digest_type *digest, + unsigned char *challenge, unsigned char *response, + char *message, int message_space); +#endif /* UNUSED */ + +#if PPP_SERVER +/* Called by authentication code to start authenticating the peer. */ +extern void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code); +#endif /* PPP_SERVER */ + +/* Called by auth. code to start authenticating us to the peer. */ +extern void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code); + +/* Represents the CHAP protocol to the main pppd code */ +extern const struct protent chap_protent; + +#endif /* CHAP_H */ +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/chap_ms.h b/components/net/lwip-2.0.3/src/include/netif/ppp/chap_ms.h new file mode 100644 index 0000000000..0795291158 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/chap_ms.h @@ -0,0 +1,44 @@ +/* + * chap_ms.h - Challenge Handshake Authentication Protocol definitions. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: chap_ms.h,v 1.13 2004/11/15 22:13:26 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef CHAPMS_INCLUDE +#define CHAPMS_INCLUDE + +extern const struct chap_digest_type chapms_digest; +extern const struct chap_digest_type chapms2_digest; + +#endif /* CHAPMS_INCLUDE */ + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/eap.h b/components/net/lwip-2.0.3/src/include/netif/ppp/eap.h new file mode 100644 index 0000000000..3ee9aaf81a --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/eap.h @@ -0,0 +1,169 @@ +/* + * eap.h - Extensible Authentication Protocol for PPP (RFC 2284) + * + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + * + * Non-exclusive rights to redistribute, modify, translate, and use + * this software in source and binary forms, in whole or in part, is + * hereby granted, provided that the above copyright notice is + * duplicated in any source form, and that neither the name of the + * copyright holder nor the author is used to endorse or promote + * products derived from this software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Original version by James Carlson + * + * $Id: eap.h,v 1.2 2003/06/11 23:56:26 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_EAP_H +#define PPP_EAP_H + +#include "ppp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Packet header = Code, id, length. + */ +#define EAP_HEADERLEN 4 + + +/* EAP message codes. */ +#define EAP_REQUEST 1 +#define EAP_RESPONSE 2 +#define EAP_SUCCESS 3 +#define EAP_FAILURE 4 + +/* EAP types */ +#define EAPT_IDENTITY 1 +#define EAPT_NOTIFICATION 2 +#define EAPT_NAK 3 /* (response only) */ +#define EAPT_MD5CHAP 4 +#define EAPT_OTP 5 /* One-Time Password; RFC 1938 */ +#define EAPT_TOKEN 6 /* Generic Token Card */ +/* 7 and 8 are unassigned. */ +#define EAPT_RSA 9 /* RSA Public Key Authentication */ +#define EAPT_DSS 10 /* DSS Unilateral */ +#define EAPT_KEA 11 /* KEA */ +#define EAPT_KEA_VALIDATE 12 /* KEA-VALIDATE */ +#define EAPT_TLS 13 /* EAP-TLS */ +#define EAPT_DEFENDER 14 /* Defender Token (AXENT) */ +#define EAPT_W2K 15 /* Windows 2000 EAP */ +#define EAPT_ARCOT 16 /* Arcot Systems */ +#define EAPT_CISCOWIRELESS 17 /* Cisco Wireless */ +#define EAPT_NOKIACARD 18 /* Nokia IP smart card */ +#define EAPT_SRP 19 /* Secure Remote Password */ +/* 20 is deprecated */ + +/* EAP SRP-SHA1 Subtypes */ +#define EAPSRP_CHALLENGE 1 /* Request 1 - Challenge */ +#define EAPSRP_CKEY 1 /* Response 1 - Client Key */ +#define EAPSRP_SKEY 2 /* Request 2 - Server Key */ +#define EAPSRP_CVALIDATOR 2 /* Response 2 - Client Validator */ +#define EAPSRP_SVALIDATOR 3 /* Request 3 - Server Validator */ +#define EAPSRP_ACK 3 /* Response 3 - final ack */ +#define EAPSRP_LWRECHALLENGE 4 /* Req/resp 4 - Lightweight rechal */ + +#define SRPVAL_EBIT 0x00000001 /* Use shared key for ECP */ + +#define SRP_PSEUDO_ID "pseudo_" +#define SRP_PSEUDO_LEN 7 + +#define MD5_SIGNATURE_SIZE 16 +#define EAP_MIN_CHALLENGE_LENGTH 17 +#define EAP_MAX_CHALLENGE_LENGTH 24 +#define EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH 3 /* 2^3-1 = 7, 17+7 = 24 */ + +#define EAP_STATES \ + "Initial", "Pending", "Closed", "Listen", "Identify", \ + "SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth" + +#define eap_client_active(pcb) ((pcb)->eap.es_client.ea_state == eapListen) +#if PPP_SERVER +#define eap_server_active(pcb) \ + ((pcb)->eap.es_server.ea_state >= eapIdentify && \ + (pcb)->eap.es_server.ea_state <= eapMD5Chall) +#endif /* PPP_SERVER */ + +/* + * Complete EAP state for one PPP session. + */ +enum eap_state_code { + eapInitial = 0, /* No EAP authentication yet requested */ + eapPending, /* Waiting for LCP (no timer) */ + eapClosed, /* Authentication not in use */ + eapListen, /* Client ready (and timer running) */ + eapIdentify, /* EAP Identify sent */ + eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */ + eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */ + eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */ + eapMD5Chall, /* Sent MD5-Challenge */ + eapOpen, /* Completed authentication */ + eapSRP4, /* Sent EAP SRP-SHA1 Subtype 4 */ + eapBadAuth /* Failed authentication */ +}; + +struct eap_auth { + const char *ea_name; /* Our name */ + char ea_peer[MAXNAMELEN +1]; /* Peer's name */ + void *ea_session; /* Authentication library linkage */ + u_char *ea_skey; /* Shared encryption key */ + u_short ea_namelen; /* Length of our name */ + u_short ea_peerlen; /* Length of peer's name */ + enum eap_state_code ea_state; + u_char ea_id; /* Current id */ + u_char ea_requests; /* Number of Requests sent/received */ + u_char ea_responses; /* Number of Responses */ + u_char ea_type; /* One of EAPT_* */ + u32_t ea_keyflags; /* SRP shared key usage flags */ +}; + +#ifndef EAP_MAX_CHALLENGE_LENGTH +#define EAP_MAX_CHALLENGE_LENGTH 24 +#endif +typedef struct eap_state { + struct eap_auth es_client; /* Client (authenticatee) data */ +#if PPP_SERVER + struct eap_auth es_server; /* Server (authenticator) data */ +#endif /* PPP_SERVER */ + int es_savedtime; /* Saved timeout */ + int es_rechallenge; /* EAP rechallenge interval */ + int es_lwrechallenge; /* SRP lightweight rechallenge inter */ + u8_t es_usepseudo; /* Use SRP Pseudonym if offered one */ + int es_usedpseudo; /* Set if we already sent PN */ + int es_challen; /* Length of challenge string */ + u_char es_challenge[EAP_MAX_CHALLENGE_LENGTH]; +} eap_state; + +/* + * Timeouts. + */ +#if 0 /* moved to ppp_opts.h */ +#define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */ +#define EAP_DEFTRANSMITS 10 /* max # times to transmit */ +#define EAP_DEFREQTIME 20 /* Time to wait for peer request */ +#define EAP_DEFALLOWREQ 20 /* max # times to accept requests */ +#endif /* moved to ppp_opts.h */ + +void eap_authwithpeer(ppp_pcb *pcb, const char *localname); +void eap_authpeer(ppp_pcb *pcb, const char *localname); + +extern const struct protent eap_protent; + +#ifdef __cplusplus +} +#endif + +#endif /* PPP_EAP_H */ + +#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/ecp.h b/components/net/lwip-2.0.3/src/include/netif/ppp/ecp.h new file mode 100644 index 0000000000..5cdce29d5b --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/ecp.h @@ -0,0 +1,50 @@ +/* + * ecp.h - Definitions for PPP Encryption Control Protocol. + * + * Copyright (c) 2002 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ecp.h,v 1.2 2003/01/10 07:12:36 fcusack Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +typedef struct ecp_options { + bool required; /* Is ECP required? */ + unsigned enctype; /* Encryption type */ +} ecp_options; + +extern fsm ecp_fsm[]; +extern ecp_options ecp_wantoptions[]; +extern ecp_options ecp_gotoptions[]; +extern ecp_options ecp_allowoptions[]; +extern ecp_options ecp_hisoptions[]; + +extern const struct protent ecp_protent; + +#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/eui64.h b/components/net/lwip-2.0.3/src/include/netif/ppp/eui64.h new file mode 100644 index 0000000000..20ac22eede --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/eui64.h @@ -0,0 +1,94 @@ +/* + * eui64.h - EUI64 routines for IPv6CP. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: eui64.h,v 1.6 2002/12/04 23:03:32 paulus Exp $ +*/ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef EUI64_H +#define EUI64_H + +/* + * @todo: + * + * Maybe this should be done by processing struct in6_addr directly... + */ +typedef union +{ + u8_t e8[8]; + u16_t e16[4]; + u32_t e32[2]; +} eui64_t; + +#define eui64_iszero(e) (((e).e32[0] | (e).e32[1]) == 0) +#define eui64_equals(e, o) (((e).e32[0] == (o).e32[0]) && \ + ((e).e32[1] == (o).e32[1])) +#define eui64_zero(e) (e).e32[0] = (e).e32[1] = 0; + +#define eui64_copy(s, d) memcpy(&(d), &(s), sizeof(eui64_t)) + +#define eui64_magic(e) do { \ + (e).e32[0] = magic(); \ + (e).e32[1] = magic(); \ + (e).e8[0] &= ~2; \ + } while (0) +#define eui64_magic_nz(x) do { \ + eui64_magic(x); \ + } while (eui64_iszero(x)) +#define eui64_magic_ne(x, y) do { \ + eui64_magic(x); \ + } while (eui64_equals(x, y)) + +#define eui64_get(ll, cp) do { \ + eui64_copy((*cp), (ll)); \ + (cp) += sizeof(eui64_t); \ + } while (0) + +#define eui64_put(ll, cp) do { \ + eui64_copy((ll), (*cp)); \ + (cp) += sizeof(eui64_t); \ + } while (0) + +#define eui64_set32(e, l) do { \ + (e).e32[0] = 0; \ + (e).e32[1] = lwip_htonl(l); \ + } while (0) +#define eui64_setlo32(e, l) eui64_set32(e, l) + +char *eui64_ntoa(eui64_t); /* Returns ascii representation of id */ + +#endif /* EUI64_H */ +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/fsm.h b/components/net/lwip-2.0.3/src/include/netif/ppp/fsm.h new file mode 100644 index 0000000000..b6915d3b80 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/fsm.h @@ -0,0 +1,175 @@ +/* + * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: fsm.h,v 1.10 2004/11/13 02:28:15 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef FSM_H +#define FSM_H + +#include "ppp.h" + +/* + * Packet header = Code, id, length. + */ +#define HEADERLEN 4 + + +/* + * CP (LCP, IPCP, etc.) codes. + */ +#define CONFREQ 1 /* Configuration Request */ +#define CONFACK 2 /* Configuration Ack */ +#define CONFNAK 3 /* Configuration Nak */ +#define CONFREJ 4 /* Configuration Reject */ +#define TERMREQ 5 /* Termination Request */ +#define TERMACK 6 /* Termination Ack */ +#define CODEREJ 7 /* Code Reject */ + + +/* + * Each FSM is described by an fsm structure and fsm callbacks. + */ +typedef struct fsm { + ppp_pcb *pcb; /* PPP Interface */ + const struct fsm_callbacks *callbacks; /* Callback routines */ + const char *term_reason; /* Reason for closing protocol */ + u8_t seen_ack; /* Have received valid Ack/Nak/Rej to Req */ + /* -- This is our only flag, we might use u_int :1 if we have more flags */ + u16_t protocol; /* Data Link Layer Protocol field value */ + u8_t state; /* State */ + u8_t flags; /* Contains option bits */ + u8_t id; /* Current id */ + u8_t reqid; /* Current request id */ + u8_t retransmits; /* Number of retransmissions left */ + u8_t nakloops; /* Number of nak loops since last ack */ + u8_t rnakloops; /* Number of naks received */ + u8_t maxnakloops; /* Maximum number of nak loops tolerated + (necessary because IPCP require a custom large max nak loops value) */ + u8_t term_reason_len; /* Length of term_reason */ +} fsm; + + +typedef struct fsm_callbacks { + void (*resetci) /* Reset our Configuration Information */ + (fsm *); + int (*cilen) /* Length of our Configuration Information */ + (fsm *); + void (*addci) /* Add our Configuration Information */ + (fsm *, u_char *, int *); + int (*ackci) /* ACK our Configuration Information */ + (fsm *, u_char *, int); + int (*nakci) /* NAK our Configuration Information */ + (fsm *, u_char *, int, int); + int (*rejci) /* Reject our Configuration Information */ + (fsm *, u_char *, int); + int (*reqci) /* Request peer's Configuration Information */ + (fsm *, u_char *, int *, int); + void (*up) /* Called when fsm reaches PPP_FSM_OPENED state */ + (fsm *); + void (*down) /* Called when fsm leaves PPP_FSM_OPENED state */ + (fsm *); + void (*starting) /* Called when we want the lower layer */ + (fsm *); + void (*finished) /* Called when we don't want the lower layer */ + (fsm *); + void (*protreject) /* Called when Protocol-Reject received */ + (int); + void (*retransmit) /* Retransmission is necessary */ + (fsm *); + int (*extcode) /* Called when unknown code received */ + (fsm *, int, int, u_char *, int); + const char *proto_name; /* String name for protocol (for messages) */ +} fsm_callbacks; + + +/* + * Link states. + */ +#define PPP_FSM_INITIAL 0 /* Down, hasn't been opened */ +#define PPP_FSM_STARTING 1 /* Down, been opened */ +#define PPP_FSM_CLOSED 2 /* Up, hasn't been opened */ +#define PPP_FSM_STOPPED 3 /* Open, waiting for down event */ +#define PPP_FSM_CLOSING 4 /* Terminating the connection, not open */ +#define PPP_FSM_STOPPING 5 /* Terminating, but open */ +#define PPP_FSM_REQSENT 6 /* We've sent a Config Request */ +#define PPP_FSM_ACKRCVD 7 /* We've received a Config Ack */ +#define PPP_FSM_ACKSENT 8 /* We've sent a Config Ack */ +#define PPP_FSM_OPENED 9 /* Connection available */ + + +/* + * Flags - indicate options controlling FSM operation + */ +#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ +#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ +#define OPT_SILENT 4 /* Wait for peer to speak first */ + + +/* + * Timeouts. + */ +#if 0 /* moved to ppp_opts.h */ +#define DEFTIMEOUT 3 /* Timeout time in seconds */ +#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif /* moved to ppp_opts.h */ + + +/* + * Prototypes + */ +void fsm_init(fsm *f); +void fsm_lowerup(fsm *f); +void fsm_lowerdown(fsm *f); +void fsm_open(fsm *f); +void fsm_close(fsm *f, const char *reason); +void fsm_input(fsm *f, u_char *inpacket, int l); +void fsm_protreject(fsm *f); +void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen); + + +#endif /* FSM_H */ +#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/ipcp.h b/components/net/lwip-2.0.3/src/include/netif/ppp/ipcp.h new file mode 100644 index 0000000000..45f46b31ff --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/ipcp.h @@ -0,0 +1,126 @@ +/* + * ipcp.h - IP Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipcp.h,v 1.14 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef IPCP_H +#define IPCP_H + +/* + * Options. + */ +#define CI_ADDRS 1 /* IP Addresses */ +#if VJ_SUPPORT +#define CI_COMPRESSTYPE 2 /* Compression Type */ +#endif /* VJ_SUPPORT */ +#define CI_ADDR 3 + +#if LWIP_DNS +#define CI_MS_DNS1 129 /* Primary DNS value */ +#define CI_MS_DNS2 131 /* Secondary DNS value */ +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ +#define CI_MS_WINS1 130 /* Primary WINS value */ +#define CI_MS_WINS2 132 /* Secondary WINS value */ +#endif /* UNUSED - WINS */ + +#if VJ_SUPPORT +#define MAX_STATES 16 /* from slcompress.h */ + +#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ +#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ +#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */ + /* maxslot and slot number compression) */ + +#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/ +#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ + /* compression option*/ +#endif /* VJ_SUPPORT */ + +typedef struct ipcp_options { + unsigned int neg_addr :1; /* Negotiate IP Address? */ + unsigned int old_addrs :1; /* Use old (IP-Addresses) option? */ + unsigned int req_addr :1; /* Ask peer to send IP address? */ +#if 0 /* UNUSED */ + unsigned int default_route :1; /* Assign default route through interface? */ + unsigned int replace_default_route :1; /* Replace default route through interface? */ +#endif /* UNUSED */ +#if 0 /* UNUSED - PROXY ARP */ + unsigned int proxy_arp :1; /* Make proxy ARP entry for peer? */ +#endif /* UNUSED - PROXY ARP */ +#if VJ_SUPPORT + unsigned int neg_vj :1; /* Van Jacobson Compression? */ + unsigned int old_vj :1; /* use old (short) form of VJ option? */ + unsigned int cflag :1; +#endif /* VJ_SUPPORT */ + unsigned int accept_local :1; /* accept peer's value for ouraddr */ + unsigned int accept_remote :1; /* accept peer's value for hisaddr */ +#if LWIP_DNS + unsigned int req_dns1 :1; /* Ask peer to send primary DNS address? */ + unsigned int req_dns2 :1; /* Ask peer to send secondary DNS address? */ +#endif /* LWIP_DNS */ + + u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ +#if LWIP_DNS + u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ +#endif /* UNUSED - WINS */ + +#if VJ_SUPPORT + u16_t vj_protocol; /* protocol value to use in VJ option */ + u8_t maxslotindex; /* values for RFC1332 VJ compression neg. */ +#endif /* VJ_SUPPORT */ +} ipcp_options; + +#if 0 /* UNUSED, already defined by lwIP */ +char *ip_ntoa (u32_t); +#endif /* UNUSED, already defined by lwIP */ + +extern const struct protent ipcp_protent; + +#endif /* IPCP_H */ +#endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/ipv6cp.h b/components/net/lwip-2.0.3/src/include/netif/ppp/ipv6cp.h new file mode 100644 index 0000000000..07d1ae3186 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/ipv6cp.h @@ -0,0 +1,183 @@ +/* + * ipv6cp.h - PPP IPV6 Control Protocol. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* Original version, based on RFC2023 : + + Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt + Économique ayant pour membres BULL S.A. et l'INRIA). + + Ce logiciel informatique est disponible aux conditions + usuelles dans la recherche, c'est-à-dire qu'il peut + être utilisé, copié, modifié, distribué à l'unique + condition que ce texte soit conservé afin que + l'origine de ce logiciel soit reconnue. + + Le nom de l'Institut National de Recherche en Informatique + et en Automatique (INRIA), de l'IMAG, ou d'une personne morale + ou physique ayant participé à l'élaboration de ce logiciel ne peut + être utilisé sans son accord préalable explicite. + + Ce logiciel est fourni tel quel sans aucune garantie, + support ou responsabilité d'aucune sorte. + Ce logiciel est dérivé de sources d'origine + "University of California at Berkeley" et + "Digital Equipment Corporation" couvertes par des copyrights. + + L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) + est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National + Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant + sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). + + This work has been done in the context of GIE DYADE (joint R & D venture + between BULL S.A. and INRIA). + + This software is available with usual "research" terms + with the aim of retain credits of the software. + Permission to use, copy, modify and distribute this software for any + purpose and without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies, + and the name of INRIA, IMAG, or any contributor not be used in advertising + or publicity pertaining to this material without the prior explicit + permission. The software is provided "as is" without any + warranties, support or liabilities of any kind. + This software is derived from source code from + "University of California at Berkeley" and + "Digital Equipment Corporation" protected by copyrights. + + Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) + is a federation of seven research units funded by the CNRS, National + Polytechnic Institute of Grenoble and University Joseph Fourier. + The research unit in Software, Systems, Networks (LSR) is member of IMAG. +*/ + +/* + * Derived from : + * + * + * ipcp.h - IP Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipv6cp.h,v 1.7 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef IPV6CP_H +#define IPV6CP_H + +#include "eui64.h" + +/* + * Options. + */ +#define CI_IFACEID 1 /* Interface Identifier */ +#ifdef IPV6CP_COMP +#define CI_COMPRESSTYPE 2 /* Compression Type */ +#endif /* IPV6CP_COMP */ + +/* No compression types yet defined. + *#define IPV6CP_COMP 0x004f + */ +typedef struct ipv6cp_options { + unsigned int neg_ifaceid :1; /* Negotiate interface identifier? */ + unsigned int req_ifaceid :1; /* Ask peer to send interface identifier? */ + unsigned int accept_local :1; /* accept peer's value for iface id? */ + unsigned int opt_local :1; /* ourtoken set by option */ + unsigned int opt_remote :1; /* histoken set by option */ + unsigned int use_ip :1; /* use IP as interface identifier */ +#if 0 + unsigned int use_persistent :1; /* use uniquely persistent value for address */ +#endif +#ifdef IPV6CP_COMP + unsigned int neg_vj :1; /* Van Jacobson Compression? */ +#endif /* IPV6CP_COMP */ + +#ifdef IPV6CP_COMP + u_short vj_protocol; /* protocol value to use in VJ option */ +#endif /* IPV6CP_COMP */ + eui64_t ourid, hisid; /* Interface identifiers */ +} ipv6cp_options; + +extern const struct protent ipv6cp_protent; + +#endif /* IPV6CP_H */ +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/lcp.h b/components/net/lwip-2.0.3/src/include/netif/ppp/lcp.h new file mode 100644 index 0000000000..12e2a05fc9 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/lcp.h @@ -0,0 +1,171 @@ +/* + * lcp.h - Link Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: lcp.h,v 1.20 2004/11/14 22:53:42 carlsonj Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef LCP_H +#define LCP_H + +#include "ppp.h" + +/* + * Options. + */ +#define CI_VENDOR 0 /* Vendor Specific */ +#define CI_MRU 1 /* Maximum Receive Unit */ +#define CI_ASYNCMAP 2 /* Async Control Character Map */ +#define CI_AUTHTYPE 3 /* Authentication Type */ +#define CI_QUALITY 4 /* Quality Protocol */ +#define CI_MAGICNUMBER 5 /* Magic Number */ +#define CI_PCOMPRESSION 7 /* Protocol Field Compression */ +#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ +#define CI_FCSALTERN 9 /* FCS-Alternatives */ +#define CI_SDP 10 /* Self-Describing-Pad */ +#define CI_NUMBERED 11 /* Numbered-Mode */ +#define CI_CALLBACK 13 /* callback */ +#define CI_MRRU 17 /* max reconstructed receive unit; multilink */ +#define CI_SSNHF 18 /* short sequence numbers for multilink */ +#define CI_EPDISC 19 /* endpoint discriminator */ +#define CI_MPPLUS 22 /* Multi-Link-Plus-Procedure */ +#define CI_LDISC 23 /* Link-Discriminator */ +#define CI_LCPAUTH 24 /* LCP Authentication */ +#define CI_COBS 25 /* Consistent Overhead Byte Stuffing */ +#define CI_PREFELIS 26 /* Prefix Elision */ +#define CI_MPHDRFMT 27 /* MP Header Format */ +#define CI_I18N 28 /* Internationalization */ +#define CI_SDL 29 /* Simple Data Link */ + +/* + * LCP-specific packet types (code numbers). + */ +#define PROTREJ 8 /* Protocol Reject */ +#define ECHOREQ 9 /* Echo Request */ +#define ECHOREP 10 /* Echo Reply */ +#define DISCREQ 11 /* Discard Request */ +#define IDENTIF 12 /* Identification */ +#define TIMEREM 13 /* Time Remaining */ + +/* Value used as data for CI_CALLBACK option */ +#define CBCP_OPT 6 /* Use callback control protocol */ + +#if 0 /* moved to ppp_opts.h */ +#define DEFMRU 1500 /* Try for this */ +#define MINMRU 128 /* No MRUs below this */ +#define MAXMRU 16384 /* Normally limit MRU to this */ +#endif /* moved to ppp_opts.h */ + +/* An endpoint discriminator, used with multilink. */ +#define MAX_ENDP_LEN 20 /* maximum length of discriminator value */ +struct epdisc { + unsigned char class_; /* -- The word "class" is reserved in C++. */ + unsigned char length; + unsigned char value[MAX_ENDP_LEN]; +}; + +/* + * The state of options is described by an lcp_options structure. + */ +typedef struct lcp_options { + unsigned int passive :1; /* Don't die if we don't get a response */ + unsigned int silent :1; /* Wait for the other end to start first */ +#if 0 /* UNUSED */ + unsigned int restart :1; /* Restart vs. exit after close */ +#endif /* UNUSED */ + unsigned int neg_mru :1; /* Negotiate the MRU? */ + unsigned int neg_asyncmap :1; /* Negotiate the async map? */ +#if PAP_SUPPORT + unsigned int neg_upap :1; /* Ask for UPAP authentication? */ +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + unsigned int neg_chap :1; /* Ask for CHAP authentication? */ +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + unsigned int neg_eap :1; /* Ask for EAP authentication? */ +#endif /* EAP_SUPPORT */ + unsigned int neg_magicnumber :1; /* Ask for magic number? */ + unsigned int neg_pcompression :1; /* HDLC Protocol Field Compression? */ + unsigned int neg_accompression :1; /* HDLC Address/Control Field Compression? */ +#if LQR_SUPPORT + unsigned int neg_lqr :1; /* Negotiate use of Link Quality Reports */ +#endif /* LQR_SUPPORT */ + unsigned int neg_cbcp :1; /* Negotiate use of CBCP */ +#ifdef HAVE_MULTILINK + unsigned int neg_mrru :1; /* negotiate multilink MRRU */ +#endif /* HAVE_MULTILINK */ + unsigned int neg_ssnhf :1; /* negotiate short sequence numbers */ + unsigned int neg_endpoint :1; /* negotiate endpoint discriminator */ + + u16_t mru; /* Value of MRU */ +#ifdef HAVE_MULTILINK + u16_t mrru; /* Value of MRRU, and multilink enable */ +#endif /* MULTILINK */ +#if CHAP_SUPPORT + u8_t chap_mdtype; /* which MD types (hashing algorithm) */ +#endif /* CHAP_SUPPORT */ + u32_t asyncmap; /* Value of async map */ + u32_t magicnumber; + u8_t numloops; /* Number of loops during magic number neg. */ +#if LQR_SUPPORT + u32_t lqr_period; /* Reporting period for LQR 1/100ths second */ +#endif /* LQR_SUPPORT */ + struct epdisc endpoint; /* endpoint discriminator */ +} lcp_options; + +void lcp_open(ppp_pcb *pcb); +void lcp_close(ppp_pcb *pcb, const char *reason); +void lcp_lowerup(ppp_pcb *pcb); +void lcp_lowerdown(ppp_pcb *pcb); +void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len); /* send protocol reject */ + +extern const struct protent lcp_protent; + +#if 0 /* moved to ppp_opts.h */ +/* Default number of times we receive our magic number from the peer + before deciding the link is looped-back. */ +#define DEFLOOPBACKFAIL 10 +#endif /* moved to ppp_opts.h */ + +#endif /* LCP_H */ +#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/magic.h b/components/net/lwip-2.0.3/src/include/netif/ppp/magic.h new file mode 100644 index 0000000000..a2a9b530e5 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/magic.h @@ -0,0 +1,122 @@ +/* + * magic.h - PPP Magic Number definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: magic.h,v 1.5 2003/06/11 23:56:26 paulus Exp $ + */ +/***************************************************************************** +* randm.h - Random number generator header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-05-29 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef MAGIC_H +#define MAGIC_H + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* + * Initialize the random number generator. + */ +void magic_init(void); + +/* + * Randomize our random seed value. To be called for truely random events + * such as user operations and network traffic. + */ +void magic_randomize(void); + +/* + * Return a new random number. + */ +u32_t magic(void); /* Returns the next magic number */ + +/* + * Fill buffer with random bytes + * + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using magic_churnrand(). + * Thus it's important to make sure that the results of this are not + * published directly because one could predict the next result to at + * least some degree. Also, it's important to get a good seed before + * the first use. + */ +void magic_random_bytes(unsigned char *buf, u32_t buf_len); + +/* + * Return a new random number between 0 and (2^pow)-1 included. + */ +u32_t magic_pow(u8_t pow); + +#endif /* MAGIC_H */ + +#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/mppe.h b/components/net/lwip-2.0.3/src/include/netif/ppp/mppe.h new file mode 100644 index 0000000000..1ae8a5d924 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/mppe.h @@ -0,0 +1,173 @@ +/* + * mppe.h - Definitions for MPPE + * + * Copyright (c) 2008 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef MPPE_H +#define MPPE_H + +#include "netif/ppp/pppcrypt.h" + +#define MPPE_PAD 4 /* MPPE growth per frame */ +#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ + +/* option bits for ccp_options.mppe */ +#define MPPE_OPT_40 0x01 /* 40 bit */ +#define MPPE_OPT_128 0x02 /* 128 bit */ +#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */ +/* unsupported opts */ +#define MPPE_OPT_56 0x08 /* 56 bit */ +#define MPPE_OPT_MPPC 0x10 /* MPPC compression */ +#define MPPE_OPT_D 0x20 /* Unknown */ +#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D) +#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */ + +/* + * This is not nice ... the alternative is a bitfield struct though. + * And unfortunately, we cannot share the same bits for the option + * names above since C and H are the same bit. We could do a u_int32 + * but then we have to do a lwip_htonl() all the time and/or we still need + * to know which octet is which. + */ +#define MPPE_C_BIT 0x01 /* MPPC */ +#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */ +#define MPPE_L_BIT 0x20 /* 40-bit */ +#define MPPE_S_BIT 0x40 /* 128-bit */ +#define MPPE_M_BIT 0x80 /* 56-bit, not supported */ +#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */ + +/* Does not include H bit; used for least significant octet only. */ +#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT) + +/* Build a CI from mppe opts (see RFC 3078) */ +#define MPPE_OPTS_TO_CI(opts, ci) \ + do { \ + u_char *ptr = ci; /* u_char[4] */ \ + \ + /* H bit */ \ + if (opts & MPPE_OPT_STATEFUL) \ + *ptr++ = 0x0; \ + else \ + *ptr++ = MPPE_H_BIT; \ + *ptr++ = 0; \ + *ptr++ = 0; \ + \ + /* S,L bits */ \ + *ptr = 0; \ + if (opts & MPPE_OPT_128) \ + *ptr |= MPPE_S_BIT; \ + if (opts & MPPE_OPT_40) \ + *ptr |= MPPE_L_BIT; \ + /* M,D,C bits not supported */ \ + } while (/* CONSTCOND */ 0) + +/* The reverse of the above */ +#define MPPE_CI_TO_OPTS(ci, opts) \ + do { \ + const u_char *ptr = ci; /* u_char[4] */ \ + \ + opts = 0; \ + \ + /* H bit */ \ + if (!(ptr[0] & MPPE_H_BIT)) \ + opts |= MPPE_OPT_STATEFUL; \ + \ + /* S,L bits */ \ + if (ptr[3] & MPPE_S_BIT) \ + opts |= MPPE_OPT_128; \ + if (ptr[3] & MPPE_L_BIT) \ + opts |= MPPE_OPT_40; \ + \ + /* M,D,C bits */ \ + if (ptr[3] & MPPE_M_BIT) \ + opts |= MPPE_OPT_56; \ + if (ptr[3] & MPPE_D_BIT) \ + opts |= MPPE_OPT_D; \ + if (ptr[3] & MPPE_C_BIT) \ + opts |= MPPE_OPT_MPPC; \ + \ + /* Other bits */ \ + if (ptr[0] & ~MPPE_H_BIT) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[1] || ptr[2]) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[3] & ~MPPE_ALL_BITS) \ + opts |= MPPE_OPT_UNKNOWN; \ + } while (/* CONSTCOND */ 0) + +/* Shared MPPE padding between MSCHAP and MPPE */ +#define SHA1_PAD_SIZE 40 + +static const u8_t mppe_sha1_pad1[SHA1_PAD_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const u8_t mppe_sha1_pad2[SHA1_PAD_SIZE] = { + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 +}; + +/* + * State for an MPPE (de)compressor. + */ +typedef struct ppp_mppe_state { + lwip_arc4_context arc4; + u8_t master_key[MPPE_MAX_KEY_LEN]; + u8_t session_key[MPPE_MAX_KEY_LEN]; + u8_t keylen; /* key length in bytes */ + /* NB: 128-bit == 16, 40-bit == 8! + * If we want to support 56-bit, the unit has to change to bits + */ + u8_t bits; /* MPPE control bits */ + u16_t ccount; /* 12-bit coherency count (seqno) */ + u16_t sanity_errors; /* take down LCP if too many */ + unsigned int stateful :1; /* stateful mode flag */ + unsigned int discard :1; /* stateful mode packet loss flag */ +} ppp_mppe_state; + +void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key); +void mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options); +void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state); +err_t mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol); +void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state); +err_t mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb); + +#endif /* MPPE_H */ +#endif /* PPP_SUPPORT && MPPE_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/arc4.h b/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/arc4.h new file mode 100644 index 0000000000..4af724cd90 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/arc4.h @@ -0,0 +1,81 @@ +/** + * \file arc4.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if LWIP_INCLUDED_POLARSSL_ARC4 + +#ifndef LWIP_INCLUDED_POLARSSL_ARC4_H +#define LWIP_INCLUDED_POLARSSL_ARC4_H + +/** + * \brief ARC4 context structure + */ +typedef struct +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +arc4_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be initialized + * \param key the secret key + * \param keylen length of the key + */ +void arc4_setup( arc4_context *ctx, unsigned char *key, int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param buf buffer to be processed + * \param buflen amount of data in buf + */ +void arc4_crypt( arc4_context *ctx, unsigned char *buf, int buflen ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_ARC4_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_ARC4 */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/des.h b/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/des.h new file mode 100644 index 0000000000..e893890ed7 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/des.h @@ -0,0 +1,92 @@ +/** + * \file des.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if LWIP_INCLUDED_POLARSSL_DES + +#ifndef LWIP_INCLUDED_POLARSSL_DES_H +#define LWIP_INCLUDED_POLARSSL_DES_H + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +/** + * \brief DES context structure + */ +typedef struct +{ + int mode; /*!< encrypt/decrypt */ + unsigned long sk[32]; /*!< DES subkeys */ +} +des_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + */ +void des_setkey_enc( des_context *ctx, unsigned char key[8] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + */ +void des_setkey_dec( des_context *ctx, unsigned char key[8] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + */ +void des_crypt_ecb( des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_DES_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_DES */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/md4.h b/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/md4.h new file mode 100644 index 0000000000..570445687e --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/md4.h @@ -0,0 +1,97 @@ +/** + * \file md4.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if LWIP_INCLUDED_POLARSSL_MD4 + +#ifndef LWIP_INCLUDED_POLARSSL_MD4_H +#define LWIP_INCLUDED_POLARSSL_MD4_H + +/** + * \brief MD4 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +md4_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + */ +void md4_starts( md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md4_update( md4_context *ctx, const unsigned char *input, int ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + */ +void md4_finish( md4_context *ctx, unsigned char output[16] ); + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + */ +void md4( unsigned char *input, int ilen, unsigned char output[16] ); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_MD4_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/md5.h b/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/md5.h new file mode 100644 index 0000000000..1244011890 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/md5.h @@ -0,0 +1,96 @@ +/** + * \file md5.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if LWIP_INCLUDED_POLARSSL_MD5 + +#ifndef LWIP_INCLUDED_POLARSSL_MD5_H +#define LWIP_INCLUDED_POLARSSL_MD5_H + +/** + * \brief MD5 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +md5_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + */ +void md5_starts( md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md5_update( md5_context *ctx, const unsigned char *input, int ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ); + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + */ +void md5( unsigned char *input, int ilen, unsigned char output[16] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_MD5_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/sha1.h b/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/sha1.h new file mode 100644 index 0000000000..a4c53e07c5 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/polarssl/sha1.h @@ -0,0 +1,96 @@ +/** + * \file sha1.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if LWIP_INCLUDED_POLARSSL_SHA1 + +#ifndef LWIP_INCLUDED_POLARSSL_SHA1_H +#define LWIP_INCLUDED_POLARSSL_SHA1_H + +/** + * \brief SHA-1 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +sha1_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void sha1_starts( sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ); + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void sha1( unsigned char *input, int ilen, unsigned char output[20] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_SHA1_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/ppp.h b/components/net/lwip-2.0.3/src/include/netif/ppp/ppp.h new file mode 100644 index 0000000000..d9ea097efd --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/ppp.h @@ -0,0 +1,690 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_H +#define PPP_H + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/timeouts.h" +#if PPP_IPV6_SUPPORT +#include "lwip/ip6_addr.h" +#endif /* PPP_IPV6_SUPPORT */ + +/* Disable non-working or rarely used PPP feature, so rarely that we don't want to bloat ppp_opts.h with them */ +#ifndef PPP_OPTIONS +#define PPP_OPTIONS 0 +#endif + +#ifndef PPP_NOTIFY +#define PPP_NOTIFY 0 +#endif + +#ifndef PPP_REMOTENAME +#define PPP_REMOTENAME 0 +#endif + +#ifndef PPP_IDLETIMELIMIT +#define PPP_IDLETIMELIMIT 0 +#endif + +#ifndef PPP_LCP_ADAPTIVE +#define PPP_LCP_ADAPTIVE 0 +#endif + +#ifndef PPP_MAXCONNECT +#define PPP_MAXCONNECT 0 +#endif + +#ifndef PPP_ALLOWED_ADDRS +#define PPP_ALLOWED_ADDRS 0 +#endif + +#ifndef PPP_PROTOCOLNAME +#define PPP_PROTOCOLNAME 0 +#endif + +#ifndef PPP_STATS_SUPPORT +#define PPP_STATS_SUPPORT 0 +#endif + +#ifndef DEFLATE_SUPPORT +#define DEFLATE_SUPPORT 0 +#endif + +#ifndef BSDCOMPRESS_SUPPORT +#define BSDCOMPRESS_SUPPORT 0 +#endif + +#ifndef PREDICTOR_SUPPORT +#define PREDICTOR_SUPPORT 0 +#endif + +/************************* +*** PUBLIC DEFINITIONS *** +*************************/ + +/* + * The basic PPP frame. + */ +#define PPP_HDRLEN 4 /* octets for standard ppp header */ +#define PPP_FCSLEN 2 /* octets for FCS */ + +/* + * Values for phase. + */ +#define PPP_PHASE_DEAD 0 +#define PPP_PHASE_MASTER 1 +#define PPP_PHASE_HOLDOFF 2 +#define PPP_PHASE_INITIALIZE 3 +#define PPP_PHASE_SERIALCONN 4 +#define PPP_PHASE_DORMANT 5 +#define PPP_PHASE_ESTABLISH 6 +#define PPP_PHASE_AUTHENTICATE 7 +#define PPP_PHASE_CALLBACK 8 +#define PPP_PHASE_NETWORK 9 +#define PPP_PHASE_RUNNING 10 +#define PPP_PHASE_TERMINATE 11 +#define PPP_PHASE_DISCONNECT 12 + +/* Error codes. */ +#define PPPERR_NONE 0 /* No error. */ +#define PPPERR_PARAM 1 /* Invalid parameter. */ +#define PPPERR_OPEN 2 /* Unable to open PPP session. */ +#define PPPERR_DEVICE 3 /* Invalid I/O device for PPP. */ +#define PPPERR_ALLOC 4 /* Unable to allocate resources. */ +#define PPPERR_USER 5 /* User interrupt. */ +#define PPPERR_CONNECT 6 /* Connection lost. */ +#define PPPERR_AUTHFAIL 7 /* Failed authentication challenge. */ +#define PPPERR_PROTOCOL 8 /* Failed to meet protocol. */ +#define PPPERR_PEERDEAD 9 /* Connection timeout */ +#define PPPERR_IDLETIMEOUT 10 /* Idle Timeout */ +#define PPPERR_CONNECTTIME 11 /* Max connect time reached */ +#define PPPERR_LOOPBACK 12 /* Loopback detected */ + +/* Whether auth support is enabled at all */ +#define PPP_AUTH_SUPPORT (PAP_SUPPORT || CHAP_SUPPORT || EAP_SUPPORT) + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +/* + * Other headers require ppp_pcb definition for prototypes, but ppp_pcb + * require some structure definition from other headers as well, we are + * fixing the dependency loop here by declaring the ppp_pcb type then + * by including headers containing necessary struct definition for ppp_pcb + */ +typedef struct ppp_pcb_s ppp_pcb; + +/* Type definitions for BSD code. */ +#ifndef __u_char_defined +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef unsigned short u_short; +typedef unsigned char u_char; +#endif + +#include "fsm.h" +#include "lcp.h" +#if CCP_SUPPORT +#include "ccp.h" +#endif /* CCP_SUPPORT */ +#if MPPE_SUPPORT +#include "mppe.h" +#endif /* MPPE_SUPPORT */ +#if PPP_IPV4_SUPPORT +#include "ipcp.h" +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT +#include "ipv6cp.h" +#endif /* PPP_IPV6_SUPPORT */ +#if PAP_SUPPORT +#include "upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "eap.h" +#endif /* EAP_SUPPORT */ +#if VJ_SUPPORT +#include "vj.h" +#endif /* VJ_SUPPORT */ + +/* Link status callback function prototype */ +typedef void (*ppp_link_status_cb_fn)(ppp_pcb *pcb, int err_code, void *ctx); + +/* + * PPP configuration. + */ +typedef struct ppp_settings_s { + +#if PPP_SERVER && PPP_AUTH_SUPPORT + unsigned int auth_required :1; /* Peer is required to authenticate */ + unsigned int null_login :1; /* Username of "" and a password of "" are acceptable */ +#endif /* PPP_SERVER && PPP_AUTH_SUPPORT */ +#if PPP_REMOTENAME + unsigned int explicit_remote :1; /* remote_name specified with remotename opt */ +#endif /* PPP_REMOTENAME */ +#if PAP_SUPPORT + unsigned int refuse_pap :1; /* Don't proceed auth. with PAP */ +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + unsigned int refuse_chap :1; /* Don't proceed auth. with CHAP */ +#endif /* CHAP_SUPPORT */ +#if MSCHAP_SUPPORT + unsigned int refuse_mschap :1; /* Don't proceed auth. with MS-CHAP */ + unsigned int refuse_mschap_v2 :1; /* Don't proceed auth. with MS-CHAPv2 */ +#endif /* MSCHAP_SUPPORT */ +#if EAP_SUPPORT + unsigned int refuse_eap :1; /* Don't proceed auth. with EAP */ +#endif /* EAP_SUPPORT */ +#if LWIP_DNS + unsigned int usepeerdns :1; /* Ask peer for DNS adds */ +#endif /* LWIP_DNS */ + unsigned int persist :1; /* Persist mode, always try to open the connection */ +#if PRINTPKT_SUPPORT + unsigned int hide_password :1; /* Hide password in dumped packets */ +#endif /* PRINTPKT_SUPPORT */ + unsigned int noremoteip :1; /* Let him have no IP address */ + unsigned int lax_recv :1; /* accept control chars in asyncmap */ + unsigned int noendpoint :1; /* don't send/accept endpoint discriminator */ +#if PPP_LCP_ADAPTIVE + unsigned int lcp_echo_adaptive :1; /* request echo only if the link was idle */ +#endif /* PPP_LCP_ADAPTIVE */ +#if MPPE_SUPPORT + unsigned int require_mppe :1; /* Require MPPE (Microsoft Point to Point Encryption) */ + unsigned int refuse_mppe_40 :1; /* Allow MPPE 40-bit mode? */ + unsigned int refuse_mppe_128 :1; /* Allow MPPE 128-bit mode? */ + unsigned int refuse_mppe_stateful :1; /* Allow MPPE stateful mode? */ +#endif /* MPPE_SUPPORT */ + + u16_t listen_time; /* time to listen first (ms), waiting for peer to send LCP packet */ + +#if PPP_IDLETIMELIMIT + u16_t idle_time_limit; /* Disconnect if idle for this many seconds */ +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT + u32_t maxconnect; /* Maximum connect time (seconds) */ +#endif /* PPP_MAXCONNECT */ + +#if PPP_AUTH_SUPPORT + /* auth data */ + const char *user; /* Username for PAP */ + const char *passwd; /* Password for PAP, secret for CHAP */ +#if PPP_REMOTENAME + char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */ +#endif /* PPP_REMOTENAME */ + +#if PAP_SUPPORT + u8_t pap_timeout_time; /* Timeout (seconds) for auth-req retrans. */ + u8_t pap_max_transmits; /* Number of auth-reqs sent */ +#if PPP_SERVER + u8_t pap_req_timeout; /* Time to wait for auth-req from peer */ +#endif /* PPP_SERVER */ +#endif /* PAP_SUPPPORT */ + +#if CHAP_SUPPORT + u8_t chap_timeout_time; /* Timeout (seconds) for retransmitting req */ + u8_t chap_max_transmits; /* max # times to send challenge */ +#if PPP_SERVER + u8_t chap_rechallenge_time; /* Time to wait for auth-req from peer */ +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPPORT */ + +#if EAP_SUPPORT + u8_t eap_req_time; /* Time to wait (for retransmit/fail) */ + u8_t eap_allow_req; /* Max Requests allowed */ +#if PPP_SERVER + u8_t eap_timeout_time; /* Time to wait (for retransmit/fail) */ + u8_t eap_max_transmits; /* Max Requests allowed */ +#endif /* PPP_SERVER */ +#endif /* EAP_SUPPORT */ + +#endif /* PPP_AUTH_SUPPORT */ + + u8_t fsm_timeout_time; /* Timeout time in seconds */ + u8_t fsm_max_conf_req_transmits; /* Maximum Configure-Request transmissions */ + u8_t fsm_max_term_transmits; /* Maximum Terminate-Request transmissions */ + u8_t fsm_max_nak_loops; /* Maximum number of nak loops tolerated */ + + u8_t lcp_loopbackfail; /* Number of times we receive our magic number from the peer + before deciding the link is looped-back. */ + u8_t lcp_echo_interval; /* Interval between LCP echo-requests */ + u8_t lcp_echo_fails; /* Tolerance to unanswered echo-requests */ + +} ppp_settings; + +#if PPP_SERVER +struct ppp_addrs { +#if PPP_IPV4_SUPPORT + ip4_addr_t our_ipaddr, his_ipaddr, netmask; +#if LWIP_DNS + ip4_addr_t dns1, dns2; +#endif /* LWIP_DNS */ +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + ip6_addr_t our6_ipaddr, his6_ipaddr; +#endif /* PPP_IPV6_SUPPORT */ +}; +#endif /* PPP_SERVER */ + +/* + * PPP interface control block. + */ +struct ppp_pcb_s { + ppp_settings settings; + const struct link_callbacks *link_cb; + void *link_ctx_cb; + void (*link_status_cb)(ppp_pcb *pcb, int err_code, void *ctx); /* Status change callback */ +#if PPP_NOTIFY_PHASE + void (*notify_phase_cb)(ppp_pcb *pcb, u8_t phase, void *ctx); /* Notify phase callback */ +#endif /* PPP_NOTIFY_PHASE */ + void *ctx_cb; /* Callbacks optional pointer */ + struct netif *netif; /* PPP interface */ + u8_t phase; /* where the link is at */ + u8_t err_code; /* Code indicating why interface is down. */ + + /* flags */ +#if PPP_IPV4_SUPPORT + unsigned int ask_for_local :1; /* request our address from peer */ + unsigned int ipcp_is_open :1; /* haven't called np_finished() */ + unsigned int ipcp_is_up :1; /* have called ipcp_up() */ + unsigned int if4_up :1; /* True when the IPv4 interface is up. */ +#if 0 /* UNUSED - PROXY ARP */ + unsigned int proxy_arp_set :1; /* Have created proxy arp entry */ +#endif /* UNUSED - PROXY ARP */ +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + unsigned int ipv6cp_is_up :1; /* have called ip6cp_up() */ + unsigned int if6_up :1; /* True when the IPv6 interface is up. */ +#endif /* PPP_IPV6_SUPPORT */ + unsigned int lcp_echo_timer_running :1; /* set if a timer is running */ +#if VJ_SUPPORT + unsigned int vj_enabled :1; /* Flag indicating VJ compression enabled. */ +#endif /* VJ_SUPPORT */ +#if CCP_SUPPORT + unsigned int ccp_all_rejected :1; /* we rejected all peer's options */ +#endif /* CCP_SUPPORT */ +#if MPPE_SUPPORT + unsigned int mppe_keys_set :1; /* Have the MPPE keys been set? */ +#endif /* MPPE_SUPPORT */ + +#if PPP_AUTH_SUPPORT + /* auth data */ +#if PPP_SERVER && defined(HAVE_MULTILINK) + char peer_authname[MAXNAMELEN + 1]; /* The name by which the peer authenticated itself to us. */ +#endif /* PPP_SERVER && defined(HAVE_MULTILINK) */ + u16_t auth_pending; /* Records which authentication operations haven't completed yet. */ + u16_t auth_done; /* Records which authentication operations have been completed. */ + +#if PAP_SUPPORT + upap_state upap; /* PAP data */ +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + chap_client_state chap_client; /* CHAP client data */ +#if PPP_SERVER + chap_server_state chap_server; /* CHAP server data */ +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPORT */ + +#if EAP_SUPPORT + eap_state eap; /* EAP data */ +#endif /* EAP_SUPPORT */ +#endif /* PPP_AUTH_SUPPORT */ + + fsm lcp_fsm; /* LCP fsm structure */ + lcp_options lcp_wantoptions; /* Options that we want to request */ + lcp_options lcp_gotoptions; /* Options that peer ack'd */ + lcp_options lcp_allowoptions; /* Options we allow peer to request */ + lcp_options lcp_hisoptions; /* Options that we ack'd */ + u16_t peer_mru; /* currently negotiated peer MRU */ + u8_t lcp_echos_pending; /* Number of outstanding echo msgs */ + u8_t lcp_echo_number; /* ID number of next echo frame */ + + u8_t num_np_open; /* Number of network protocols which we have opened. */ + u8_t num_np_up; /* Number of network protocols which have come up. */ + +#if VJ_SUPPORT + struct vjcompress vj_comp; /* Van Jacobson compression header. */ +#endif /* VJ_SUPPORT */ + +#if CCP_SUPPORT + fsm ccp_fsm; /* CCP fsm structure */ + ccp_options ccp_wantoptions; /* what to request the peer to use */ + ccp_options ccp_gotoptions; /* what the peer agreed to do */ + ccp_options ccp_allowoptions; /* what we'll agree to do */ + ccp_options ccp_hisoptions; /* what we agreed to do */ + u8_t ccp_localstate; /* Local state (mainly for handling reset-reqs and reset-acks). */ + u8_t ccp_receive_method; /* Method chosen on receive path */ + u8_t ccp_transmit_method; /* Method chosen on transmit path */ +#if MPPE_SUPPORT + ppp_mppe_state mppe_comp; /* MPPE "compressor" structure */ + ppp_mppe_state mppe_decomp; /* MPPE "decompressor" structure */ +#endif /* MPPE_SUPPORT */ +#endif /* CCP_SUPPORT */ + +#if PPP_IPV4_SUPPORT + fsm ipcp_fsm; /* IPCP fsm structure */ + ipcp_options ipcp_wantoptions; /* Options that we want to request */ + ipcp_options ipcp_gotoptions; /* Options that peer ack'd */ + ipcp_options ipcp_allowoptions; /* Options we allow peer to request */ + ipcp_options ipcp_hisoptions; /* Options that we ack'd */ +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT + fsm ipv6cp_fsm; /* IPV6CP fsm structure */ + ipv6cp_options ipv6cp_wantoptions; /* Options that we want to request */ + ipv6cp_options ipv6cp_gotoptions; /* Options that peer ack'd */ + ipv6cp_options ipv6cp_allowoptions; /* Options we allow peer to request */ + ipv6cp_options ipv6cp_hisoptions; /* Options that we ack'd */ +#endif /* PPP_IPV6_SUPPORT */ +}; + +/************************ + *** PUBLIC FUNCTIONS *** + ************************/ + +/* + * WARNING: For multi-threads environment, all ppp_set_* functions most + * only be called while the PPP is in the dead phase (i.e. disconnected). + */ + +#if PPP_AUTH_SUPPORT +/* + * Set PPP authentication. + * + * Warning: Using PPPAUTHTYPE_ANY might have security consequences. + * RFC 1994 says: + * + * In practice, within or associated with each PPP server, there is a + * database which associates "user" names with authentication + * information ("secrets"). It is not anticipated that a particular + * named user would be authenticated by multiple methods. This would + * make the user vulnerable to attacks which negotiate the least secure + * method from among a set (such as PAP rather than CHAP). If the same + * secret was used, PAP would reveal the secret to be used later with + * CHAP. + * + * Instead, for each user name there should be an indication of exactly + * one method used to authenticate that user name. If a user needs to + * make use of different authentication methods under different + * circumstances, then distinct user names SHOULD be employed, each of + * which identifies exactly one authentication method. + * + * Default is none auth type, unset (NULL) user and passwd. + */ +#define PPPAUTHTYPE_NONE 0x00 +#define PPPAUTHTYPE_PAP 0x01 +#define PPPAUTHTYPE_CHAP 0x02 +#define PPPAUTHTYPE_MSCHAP 0x04 +#define PPPAUTHTYPE_MSCHAP_V2 0x08 +#define PPPAUTHTYPE_EAP 0x10 +#define PPPAUTHTYPE_ANY 0xff +void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd); + +/* + * If set, peer is required to authenticate. This is mostly necessary for PPP server support. + * + * Default is false. + */ +#define ppp_set_auth_required(ppp, boolval) (ppp->settings.auth_required = boolval) +#endif /* PPP_AUTH_SUPPORT */ + +#if PPP_IPV4_SUPPORT +/* + * Set PPP interface "our" and "his" IPv4 addresses. This is mostly necessary for PPP server + * support but it can also be used on a PPP link where each side choose its own IP address. + * + * Default is unset (0.0.0.0). + */ +#define ppp_set_ipcp_ouraddr(ppp, addr) do { ppp->ipcp_wantoptions.ouraddr = ip4_addr_get_u32(addr); \ + ppp->ask_for_local = ppp->ipcp_wantoptions.ouraddr != 0; } while(0) +#define ppp_set_ipcp_hisaddr(ppp, addr) (ppp->ipcp_wantoptions.hisaddr = ip4_addr_get_u32(addr)) +#if LWIP_DNS +/* + * Set DNS server addresses that are sent if the peer asks for them. This is mostly necessary + * for PPP server support. + * + * Default is unset (0.0.0.0). + */ +#define ppp_set_ipcp_dnsaddr(ppp, index, addr) (ppp->ipcp_allowoptions.dnsaddr[index] = ip4_addr_get_u32(addr)) + +/* + * If set, we ask the peer for up to 2 DNS server addresses. Received DNS server addresses are + * registered using the dns_setserver() function. + * + * Default is false. + */ +#define ppp_set_usepeerdns(ppp, boolval) (ppp->settings.usepeerdns = boolval) +#endif /* LWIP_DNS */ +#endif /* PPP_IPV4_SUPPORT */ + +#if MPPE_SUPPORT +/* Disable MPPE (Microsoft Point to Point Encryption). This parameter is exclusive. */ +#define PPP_MPPE_DISABLE 0x00 +/* Require the use of MPPE (Microsoft Point to Point Encryption). */ +#define PPP_MPPE_ENABLE 0x01 +/* Allow MPPE to use stateful mode. Stateless mode is still attempted first. */ +#define PPP_MPPE_ALLOW_STATEFUL 0x02 +/* Refuse the use of MPPE with 40-bit encryption. Conflict with PPP_MPPE_REFUSE_128. */ +#define PPP_MPPE_REFUSE_40 0x04 +/* Refuse the use of MPPE with 128-bit encryption. Conflict with PPP_MPPE_REFUSE_40. */ +#define PPP_MPPE_REFUSE_128 0x08 +/* + * Set MPPE configuration + * + * Default is disabled. + */ +void ppp_set_mppe(ppp_pcb *pcb, u8_t flags); +#endif /* MPPE_SUPPORT */ + +/* + * Wait for up to intval milliseconds for a valid PPP packet from the peer. + * At the end of this time, or when a valid PPP packet is received from the + * peer, we commence negotiation by sending our first LCP packet. + * + * Default is 0. + */ +#define ppp_set_listen_time(ppp, intval) (ppp->settings.listen_time = intval) + +/* + * If set, we will attempt to initiate a connection but if no reply is received from + * the peer, we will then just wait passively for a valid LCP packet from the peer. + * + * Default is false. + */ +#define ppp_set_passive(ppp, boolval) (ppp->lcp_wantoptions.passive = boolval) + +/* + * If set, we will not transmit LCP packets to initiate a connection until a valid + * LCP packet is received from the peer. This is what we usually call the server mode. + * + * Default is false. + */ +#define ppp_set_silent(ppp, boolval) (ppp->lcp_wantoptions.silent = boolval) + +/* + * If set, enable protocol field compression negotiation in both the receive and + * the transmit direction. + * + * Default is true. + */ +#define ppp_set_neg_pcomp(ppp, boolval) (ppp->lcp_wantoptions.neg_pcompression = \ + ppp->lcp_allowoptions.neg_pcompression = boolval) + +/* + * If set, enable Address/Control compression in both the receive and the transmit + * direction. + * + * Default is true. + */ +#define ppp_set_neg_accomp(ppp, boolval) (ppp->lcp_wantoptions.neg_accompression = \ + ppp->lcp_allowoptions.neg_accompression = boolval) + +/* + * If set, enable asyncmap negotiation. Otherwise forcing all control characters to + * be escaped for both the transmit and the receive direction. + * + * Default is true. + */ +#define ppp_set_neg_asyncmap(ppp, boolval) (ppp->lcp_wantoptions.neg_asyncmap = \ + ppp->lcp_allowoptions.neg_asyncmap = boolval) + +/* + * This option sets the Async-Control-Character-Map (ACCM) for this end of the link. + * The ACCM is a set of 32 bits, one for each of the ASCII control characters with + * values from 0 to 31, where a 1 bit indicates that the corresponding control + * character should not be used in PPP packets sent to this system. The map is + * an unsigned 32 bits integer where the least significant bit (00000001) represents + * character 0 and the most significant bit (80000000) represents character 31. + * We will then ask the peer to send these characters as a 2-byte escape sequence. + * + * Default is 0. + */ +#define ppp_set_asyncmap(ppp, intval) (ppp->lcp_wantoptions.asyncmap = intval) + +/* + * Set a PPP interface as the default network interface + * (used to output all packets for which no specific route is found). + */ +#define ppp_set_default(ppp) netif_set_default(ppp->netif) + +#if PPP_NOTIFY_PHASE +/* + * Set a PPP notify phase callback. + * + * This can be used for example to set a LED pattern depending on the + * current phase of the PPP session. + */ +typedef void (*ppp_notify_phase_cb_fn)(ppp_pcb *pcb, u8_t phase, void *ctx); +void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); +#endif /* PPP_NOTIFY_PHASE */ + +/* + * Initiate a PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Holdoff is the time to wait (in seconds) before initiating + * the connection. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff); + +#if PPP_SERVER +/* + * Listen for an incoming PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_listen(ppp_pcb *pcb); +#endif /* PPP_SERVER */ + +/* + * Initiate the end of a PPP connection. + * Any outstanding packets in the queues are dropped. + * + * Setting nocarrier to 1 close the PPP connection without initiating the + * shutdown procedure. Always using nocarrier = 0 is still recommended, + * this is going to take a little longer time if your link is down, but + * is a safer choice for the PPP state machine. + * + * Return 0 on success, an error code on failure. + */ +err_t ppp_close(ppp_pcb *pcb, u8_t nocarrier); + +/* + * Release the control block. + * + * This can only be called if PPP is in the dead phase. + * + * You must use ppp_close() before if you wish to terminate + * an established PPP session. + * + * Return 0 on success, an error code on failure. + */ +err_t ppp_free(ppp_pcb *pcb); + +/* + * PPP IOCTL commands. + * + * Get the up status - 0 for down, non-zero for up. The argument must + * point to an int. + */ +#define PPPCTLG_UPSTATUS 0 + +/* + * Get the PPP error code. The argument must point to an int. + * Returns a PPPERR_* value. + */ +#define PPPCTLG_ERRCODE 1 + +/* + * Get the fd associated with a PPP over serial + */ +#define PPPCTLG_FD 2 + +/* + * Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. + */ +err_t ppp_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); + +/* Get the PPP netif interface */ +#define ppp_netif(ppp) (ppp->netif) + +/* Set an lwIP-style status-callback for the selected PPP device */ +#define ppp_set_netif_statuscallback(ppp, status_cb) \ + netif_set_status_callback(ppp->netif, status_cb); + +/* Set an lwIP-style link-callback for the selected PPP device */ +#define ppp_set_netif_linkcallback(ppp, link_cb) \ + netif_set_link_callback(ppp->netif, link_cb); + +#endif /* PPP_H */ + +#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/ppp_impl.h b/components/net/lwip-2.0.3/src/include/netif/ppp/ppp_impl.h new file mode 100644 index 0000000000..1d4c7742f3 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/ppp_impl.h @@ -0,0 +1,629 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +#ifndef LWIP_HDR_PPP_IMPL_H +#define LWIP_HDR_PPP_IMPL_H + +#include "netif/ppp/ppp_opts.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifdef PPP_INCLUDE_SETTINGS_HEADER +#include "ppp_settings.h" +#endif + +#include /* formats */ +#include +#include +#include /* strtol() */ + +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/timeouts.h" + +#include "ppp.h" +#include "pppdebug.h" + +/* + * Memory used for control packets. + * + * PPP_CTRL_PBUF_MAX_SIZE is the amount of memory we allocate when we + * cannot figure out how much we are going to use before filling the buffer. + */ +#if PPP_USE_PBUF_RAM +#define PPP_CTRL_PBUF_TYPE PBUF_RAM +#define PPP_CTRL_PBUF_MAX_SIZE 512 +#else /* PPP_USE_PBUF_RAM */ +#define PPP_CTRL_PBUF_TYPE PBUF_POOL +#define PPP_CTRL_PBUF_MAX_SIZE PBUF_POOL_BUFSIZE +#endif /* PPP_USE_PBUF_RAM */ + +/* + * The basic PPP frame. + */ +#define PPP_ADDRESS(p) (((u_char *)(p))[0]) +#define PPP_CONTROL(p) (((u_char *)(p))[1]) +#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) + +/* + * Significant octet values. + */ +#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ +#define PPP_UI 0x03 /* Unnumbered Information */ +#define PPP_FLAG 0x7e /* Flag Sequence */ +#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ +#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ + +/* + * Protocol field values. + */ +#define PPP_IP 0x21 /* Internet Protocol */ +#if 0 /* UNUSED */ +#define PPP_AT 0x29 /* AppleTalk Protocol */ +#define PPP_IPX 0x2b /* IPX protocol */ +#endif /* UNUSED */ +#if VJ_SUPPORT +#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ +#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ +#endif /* VJ_SUPPORT */ +#if PPP_IPV6_SUPPORT +#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */ +#endif /* PPP_IPV6_SUPPORT */ +#if CCP_SUPPORT +#define PPP_COMP 0xfd /* compressed packet */ +#endif /* CCP_SUPPORT */ +#define PPP_IPCP 0x8021 /* IP Control Protocol */ +#if 0 /* UNUSED */ +#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ +#define PPP_IPXCP 0x802b /* IPX Control Protocol */ +#endif /* UNUSED */ +#if PPP_IPV6_SUPPORT +#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ +#endif /* PPP_IPV6_SUPPORT */ +#if CCP_SUPPORT +#define PPP_CCP 0x80fd /* Compression Control Protocol */ +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT +#define PPP_ECP 0x8053 /* Encryption Control Protocol */ +#endif /* ECP_SUPPORT */ +#define PPP_LCP 0xc021 /* Link Control Protocol */ +#if PAP_SUPPORT +#define PPP_PAP 0xc023 /* Password Authentication Protocol */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT +#define PPP_LQR 0xc025 /* Link Quality Report protocol */ +#endif /* LQR_SUPPORT */ +#if CHAP_SUPPORT +#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ +#endif /* CHAP_SUPPORT */ +#if CBCP_SUPPORT +#define PPP_CBCP 0xc029 /* Callback Control Protocol */ +#endif /* CBCP_SUPPORT */ +#if EAP_SUPPORT +#define PPP_EAP 0xc227 /* Extensible Authentication Protocol */ +#endif /* EAP_SUPPORT */ + +/* + * The following struct gives the addresses of procedures to call + * for a particular lower link level protocol. + */ +struct link_callbacks { + /* Start a connection (e.g. Initiate discovery phase) */ + void (*connect) (ppp_pcb *pcb, void *ctx); +#if PPP_SERVER + /* Listen for an incoming connection (Passive mode) */ + void (*listen) (ppp_pcb *pcb, void *ctx); +#endif /* PPP_SERVER */ + /* End a connection (i.e. initiate disconnect phase) */ + void (*disconnect) (ppp_pcb *pcb, void *ctx); + /* Free lower protocol control block */ + err_t (*free) (ppp_pcb *pcb, void *ctx); + /* Write a pbuf to a ppp link, only used from PPP functions to send PPP packets. */ + err_t (*write)(ppp_pcb *pcb, void *ctx, struct pbuf *p); + /* Send a packet from lwIP core (IPv4 or IPv6) */ + err_t (*netif_output)(ppp_pcb *pcb, void *ctx, struct pbuf *p, u_short protocol); + /* configure the transmit-side characteristics of the PPP interface */ + void (*send_config)(ppp_pcb *pcb, void *ctx, u32_t accm, int pcomp, int accomp); + /* confire the receive-side characteristics of the PPP interface */ + void (*recv_config)(ppp_pcb *pcb, void *ctx, u32_t accm, int pcomp, int accomp); +}; + +/* + * What to do with network protocol (NP) packets. + */ +enum NPmode { + NPMODE_PASS, /* pass the packet through */ + NPMODE_DROP, /* silently drop the packet */ + NPMODE_ERROR, /* return an error */ + NPMODE_QUEUE /* save it up for later. */ +}; + +/* + * Statistics. + */ +#if PPP_STATS_SUPPORT +struct pppstat { + unsigned int ppp_ibytes; /* bytes received */ + unsigned int ppp_ipackets; /* packets received */ + unsigned int ppp_ierrors; /* receive errors */ + unsigned int ppp_obytes; /* bytes sent */ + unsigned int ppp_opackets; /* packets sent */ + unsigned int ppp_oerrors; /* transmit errors */ +}; + +#if VJ_SUPPORT +struct vjstat { + unsigned int vjs_packets; /* outbound packets */ + unsigned int vjs_compressed; /* outbound compressed packets */ + unsigned int vjs_searches; /* searches for connection state */ + unsigned int vjs_misses; /* times couldn't find conn. state */ + unsigned int vjs_uncompressedin; /* inbound uncompressed packets */ + unsigned int vjs_compressedin; /* inbound compressed packets */ + unsigned int vjs_errorin; /* inbound unknown type packets */ + unsigned int vjs_tossed; /* inbound packets tossed because of error */ +}; +#endif /* VJ_SUPPORT */ + +struct ppp_stats { + struct pppstat p; /* basic PPP statistics */ +#if VJ_SUPPORT + struct vjstat vj; /* VJ header compression statistics */ +#endif /* VJ_SUPPORT */ +}; + +#if CCP_SUPPORT +struct compstat { + unsigned int unc_bytes; /* total uncompressed bytes */ + unsigned int unc_packets; /* total uncompressed packets */ + unsigned int comp_bytes; /* compressed bytes */ + unsigned int comp_packets; /* compressed packets */ + unsigned int inc_bytes; /* incompressible bytes */ + unsigned int inc_packets; /* incompressible packets */ + unsigned int ratio; /* recent compression ratio << 8 */ +}; + +struct ppp_comp_stats { + struct compstat c; /* packet compression statistics */ + struct compstat d; /* packet decompression statistics */ +}; +#endif /* CCP_SUPPORT */ + +#endif /* PPP_STATS_SUPPORT */ + +#if PPP_IDLETIMELIMIT +/* + * The following structure records the time in seconds since + * the last NP packet was sent or received. + */ +struct ppp_idle { + time_t xmit_idle; /* time since last NP packet sent */ + time_t recv_idle; /* time since last NP packet received */ +}; +#endif /* PPP_IDLETIMELIMIT */ + +/* values for epdisc.class */ +#define EPD_NULL 0 /* null discriminator, no data */ +#define EPD_LOCAL 1 +#define EPD_IP 2 +#define EPD_MAC 3 +#define EPD_MAGIC 4 +#define EPD_PHONENUM 5 + +/* + * Global variables. + */ +#ifdef HAVE_MULTILINK +extern u8_t multilink; /* enable multilink operation */ +extern u8_t doing_multilink; +extern u8_t multilink_master; +extern u8_t bundle_eof; +extern u8_t bundle_terminating; +#endif + +#ifdef MAXOCTETS +extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ +extern int maxoctets_dir; /* Direction : + 0 - in+out (default) + 1 - in + 2 - out + 3 - max(in,out) */ +extern int maxoctets_timeout; /* Timeout for check of octets limit */ +#define PPP_OCTETS_DIRECTION_SUM 0 +#define PPP_OCTETS_DIRECTION_IN 1 +#define PPP_OCTETS_DIRECTION_OUT 2 +#define PPP_OCTETS_DIRECTION_MAXOVERAL 3 +/* same as previos, but little different on RADIUS side */ +#define PPP_OCTETS_DIRECTION_MAXSESSION 4 +#endif + +/* Data input may be used by CCP and ECP, remove this entry + * from struct protent to save some flash + */ +#define PPP_DATAINPUT 0 + +/* + * The following struct gives the addresses of procedures to call + * for a particular protocol. + */ +struct protent { + u_short protocol; /* PPP protocol number */ + /* Initialization procedure */ + void (*init) (ppp_pcb *pcb); + /* Process a received packet */ + void (*input) (ppp_pcb *pcb, u_char *pkt, int len); + /* Process a received protocol-reject */ + void (*protrej) (ppp_pcb *pcb); + /* Lower layer has come up */ + void (*lowerup) (ppp_pcb *pcb); + /* Lower layer has gone down */ + void (*lowerdown) (ppp_pcb *pcb); + /* Open the protocol */ + void (*open) (ppp_pcb *pcb); + /* Close the protocol */ + void (*close) (ppp_pcb *pcb, const char *reason); +#if PRINTPKT_SUPPORT + /* Print a packet in readable form */ + int (*printpkt) (const u_char *pkt, int len, + void (*printer) (void *, const char *, ...), + void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + /* Process a received data packet */ + void (*datainput) (ppp_pcb *pcb, u_char *pkt, int len); +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + const char *name; /* Text name of protocol */ + const char *data_name; /* Text name of corresponding data protocol */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + option_t *options; /* List of command-line options */ + /* Check requested options, assign defaults */ + void (*check_options) (void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + /* Configure interface for demand-dial */ + int (*demand_conf) (int unit); + /* Say whether to bring up link for this pkt */ + int (*active_pkt) (u_char *pkt, int len); +#endif /* DEMAND_SUPPORT */ +}; + +/* Table of pointers to supported protocols */ +extern const struct protent* const protocols[]; + + +/* Values for auth_pending, auth_done */ +#if PAP_SUPPORT +#define PAP_WITHPEER 0x1 +#define PAP_PEER 0x2 +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#define CHAP_WITHPEER 0x4 +#define CHAP_PEER 0x8 +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#define EAP_WITHPEER 0x10 +#define EAP_PEER 0x20 +#endif /* EAP_SUPPORT */ + +/* Values for auth_done only */ +#if CHAP_SUPPORT +#define CHAP_MD5_WITHPEER 0x40 +#define CHAP_MD5_PEER 0x80 +#if MSCHAP_SUPPORT +#define CHAP_MS_SHIFT 8 /* LSB position for MS auths */ +#define CHAP_MS_WITHPEER 0x100 +#define CHAP_MS_PEER 0x200 +#define CHAP_MS2_WITHPEER 0x400 +#define CHAP_MS2_PEER 0x800 +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ + +/* Supported CHAP protocols */ +#if CHAP_SUPPORT + +#if MSCHAP_SUPPORT +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5) +#else /* MSCHAP_SUPPORT */ +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MD5) +#endif /* MSCHAP_SUPPORT */ + +#else /* CHAP_SUPPORT */ +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_NONE) +#endif /* CHAP_SUPPORT */ + +#if PPP_STATS_SUPPORT +/* + * PPP statistics structure + */ +struct pppd_stats { + unsigned int bytes_in; + unsigned int bytes_out; + unsigned int pkts_in; + unsigned int pkts_out; +}; +#endif /* PPP_STATS_SUPPORT */ + + +/* + * PPP private functions + */ + + +/* + * Functions called from lwIP core. + */ + +/* initialize the PPP subsystem */ +int ppp_init(void); + +/* + * Functions called from PPP link protocols. + */ + +/* Create a new PPP control block */ +ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +/* Initiate LCP open request */ +void ppp_start(ppp_pcb *pcb); + +/* Called when link failed to setup */ +void ppp_link_failed(ppp_pcb *pcb); + +/* Called when link is normally down (i.e. it was asked to end) */ +void ppp_link_end(ppp_pcb *pcb); + +/* function called to process input packet */ +void ppp_input(ppp_pcb *pcb, struct pbuf *pb); + +/* helper function, merge a pbuf chain into one pbuf */ +struct pbuf *ppp_singlebuf(struct pbuf *p); + + +/* + * Functions called by PPP protocols. + */ + +/* function called by all PPP subsystems to send packets */ +err_t ppp_write(ppp_pcb *pcb, struct pbuf *p); + +/* functions called by auth.c link_terminated() */ +void ppp_link_terminated(ppp_pcb *pcb); + +void new_phase(ppp_pcb *pcb, int p); + +int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp); +int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp); + +#if PPP_IPV4_SUPPORT +int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t netmask); +int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr); +#if 0 /* UNUSED - PROXY ARP */ +int sifproxyarp(ppp_pcb *pcb, u32_t his_adr); +int cifproxyarp(ppp_pcb *pcb, u32_t his_adr); +#endif /* UNUSED - PROXY ARP */ +#if LWIP_DNS +int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); +int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); +#endif /* LWIP_DNS */ +#if VJ_SUPPORT +int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid); +#endif /* VJ_SUPPORT */ +int sifup(ppp_pcb *pcb); +int sifdown (ppp_pcb *pcb); +u32_t get_mask(u32_t addr); +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT +int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); +int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); +int sif6up(ppp_pcb *pcb); +int sif6down (ppp_pcb *pcb); +#endif /* PPP_IPV6_SUPPORT */ + +#if DEMAND_SUPPORT +int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode); +#endif /* DEMAND_SUPPORt */ + +void netif_set_mtu(ppp_pcb *pcb, int mtu); +int netif_get_mtu(ppp_pcb *pcb); + +#if CCP_SUPPORT +#if 0 /* unused */ +int ccp_test(ppp_pcb *pcb, u_char *opt_ptr, int opt_len, int for_transmit); +#endif /* unused */ +void ccp_set(ppp_pcb *pcb, u8_t isopen, u8_t isup, u8_t receive_method, u8_t transmit_method); +void ccp_reset_comp(ppp_pcb *pcb); +void ccp_reset_decomp(ppp_pcb *pcb); +#if 0 /* unused */ +int ccp_fatal_error(ppp_pcb *pcb); +#endif /* unused */ +#endif /* CCP_SUPPORT */ + +#if PPP_IDLETIMELIMIT +int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip); +#endif /* PPP_IDLETIMELIMIT */ + +#if DEMAND_SUPPORT +int get_loop_output(void); +#endif /* DEMAND_SUPPORT */ + +/* Optional protocol names list, to make our messages a little more informative. */ +#if PPP_PROTOCOLNAME +const char * protocol_name(int proto); +#endif /* PPP_PROTOCOLNAME */ + +/* Optional stats support, to get some statistics on the PPP interface */ +#if PPP_STATS_SUPPORT +void print_link_stats(void); /* Print stats, if available */ +void reset_link_stats(int u); /* Reset (init) stats when link goes up */ +void update_link_stats(int u); /* Get stats at link termination */ +#endif /* PPP_STATS_SUPPORT */ + + + +/* + * Inline versions of get/put char/short/long. + * Pointer is advanced; we assume that both arguments + * are lvalues and will already be in registers. + * cp MUST be u_char *. + */ +#define GETCHAR(c, cp) { \ + (c) = *(cp)++; \ +} +#define PUTCHAR(c, cp) { \ + *(cp)++ = (u_char) (c); \ +} +#define GETSHORT(s, cp) { \ + (s) = *(cp)++ << 8; \ + (s) |= *(cp)++; \ +} +#define PUTSHORT(s, cp) { \ + *(cp)++ = (u_char) ((s) >> 8); \ + *(cp)++ = (u_char) (s); \ +} +#define GETLONG(l, cp) { \ + (l) = *(cp)++ << 8; \ + (l) |= *(cp)++; (l) <<= 8; \ + (l) |= *(cp)++; (l) <<= 8; \ + (l) |= *(cp)++; \ +} +#define PUTLONG(l, cp) { \ + *(cp)++ = (u_char) ((l) >> 24); \ + *(cp)++ = (u_char) ((l) >> 16); \ + *(cp)++ = (u_char) ((l) >> 8); \ + *(cp)++ = (u_char) (l); \ +} + +#define INCPTR(n, cp) ((cp) += (n)) +#define DECPTR(n, cp) ((cp) -= (n)) + +/* + * System dependent definitions for user-level 4.3BSD UNIX implementation. + */ +#define TIMEOUT(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t)*1000, (f), (a)); } while(0) +#define TIMEOUTMS(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t), (f), (a)); } while(0) +#define UNTIMEOUT(f, a) sys_untimeout((f), (a)) + +#define BZERO(s, n) memset(s, 0, n) +#define BCMP(s1, s2, l) memcmp(s1, s2, l) + +#define PRINTMSG(m, l) { ppp_info("Remote message: %0.*v", l, m); } + +/* + * MAKEHEADER - Add Header fields to a packet. + */ +#define MAKEHEADER(p, t) { \ + PUTCHAR(PPP_ALLSTATIONS, p); \ + PUTCHAR(PPP_UI, p); \ + PUTSHORT(t, p); } + +/* Procedures exported from auth.c */ +void link_required(ppp_pcb *pcb); /* we are starting to use the link */ +void link_terminated(ppp_pcb *pcb); /* we are finished with the link */ +void link_down(ppp_pcb *pcb); /* the LCP layer has left the Opened state */ +void upper_layers_down(ppp_pcb *pcb); /* take all NCPs down */ +void link_established(ppp_pcb *pcb); /* the link is up; authenticate now */ +void start_networks(ppp_pcb *pcb); /* start all the network control protos */ +void continue_networks(ppp_pcb *pcb); /* start network [ip, etc] control protos */ +#if PPP_AUTH_SUPPORT +#if PPP_SERVER +int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen); + /* check the user name and passwd against configuration */ +void auth_peer_fail(ppp_pcb *pcb, int protocol); + /* peer failed to authenticate itself */ +void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen); + /* peer successfully authenticated itself */ +#endif /* PPP_SERVER */ +void auth_withpeer_fail(ppp_pcb *pcb, int protocol); + /* we failed to authenticate ourselves */ +void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor); + /* we successfully authenticated ourselves */ +#endif /* PPP_AUTH_SUPPORT */ +void np_up(ppp_pcb *pcb, int proto); /* a network protocol has come up */ +void np_down(ppp_pcb *pcb, int proto); /* a network protocol has gone down */ +void np_finished(ppp_pcb *pcb, int proto); /* a network protocol no longer needs link */ +#if PPP_AUTH_SUPPORT +int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server); + /* get "secret" for chap */ +#endif /* PPP_AUTH_SUPPORT */ + +/* Procedures exported from ipcp.c */ +/* int parse_dotted_ip (char *, u32_t *); */ + +/* Procedures exported from demand.c */ +#if DEMAND_SUPPORT +void demand_conf (void); /* config interface(s) for demand-dial */ +void demand_block (void); /* set all NPs to queue up packets */ +void demand_unblock (void); /* set all NPs to pass packets */ +void demand_discard (void); /* set all NPs to discard packets */ +void demand_rexmit (int, u32_t); /* retransmit saved frames for an NP*/ +int loop_chars (unsigned char *, int); /* process chars from loopback */ +int loop_frame (unsigned char *, int); /* should we bring link up? */ +#endif /* DEMAND_SUPPORT */ + +/* Procedures exported from multilink.c */ +#ifdef HAVE_MULTILINK +void mp_check_options (void); /* Check multilink-related options */ +int mp_join_bundle (void); /* join our link to an appropriate bundle */ +void mp_exit_bundle (void); /* have disconnected our link from bundle */ +void mp_bundle_terminated (void); +char *epdisc_to_str (struct epdisc *); /* string from endpoint discrim. */ +int str_to_epdisc (struct epdisc *, char *); /* endpt disc. from str */ +#else +#define mp_bundle_terminated() /* nothing */ +#define mp_exit_bundle() /* nothing */ +#define doing_multilink 0 +#define multilink_master 0 +#endif + +/* Procedures exported from utils.c. */ +void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg); /* Format a string for output */ +int ppp_slprintf(char *buf, int buflen, const char *fmt, ...); /* sprintf++ */ +int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args); /* vsprintf++ */ +size_t ppp_strlcpy(char *dest, const char *src, size_t len); /* safe strcpy */ +size_t ppp_strlcat(char *dest, const char *src, size_t len); /* safe strncpy */ +void ppp_dbglog(const char *fmt, ...); /* log a debug message */ +void ppp_info(const char *fmt, ...); /* log an informational message */ +void ppp_notice(const char *fmt, ...); /* log a notice-level message */ +void ppp_warn(const char *fmt, ...); /* log a warning message */ +void ppp_error(const char *fmt, ...); /* log an error message */ +void ppp_fatal(const char *fmt, ...); /* log an error message and die(1) */ +#if PRINTPKT_SUPPORT +void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len); + /* dump packet to debug log if interesting */ +#endif /* PRINTPKT_SUPPORT */ + + +#endif /* PPP_SUPPORT */ +#endif /* LWIP_HDR_PPP_IMPL_H */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/ppp_opts.h b/components/net/lwip-2.0.3/src/include/netif/ppp/ppp_opts.h new file mode 100644 index 0000000000..fa79c090f2 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/ppp_opts.h @@ -0,0 +1,593 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef LWIP_PPP_OPTS_H +#define LWIP_PPP_OPTS_H + +#include "lwip/opt.h" + +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOL2TP_SUPPORT==1: Enable PPP Over L2TP + */ +#ifndef PPPOL2TP_SUPPORT +#define PPPOL2TP_SUPPORT 0 +#endif + +/** + * PPPOL2TP_AUTH_SUPPORT==1: Enable PPP Over L2TP Auth (enable MD5 support) + */ +#ifndef PPPOL2TP_AUTH_SUPPORT +#define PPPOL2TP_AUTH_SUPPORT PPPOL2TP_SUPPORT +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +/** + * LWIP_PPP_API==1: Enable PPP API (in pppapi.c) + */ +#ifndef LWIP_PPP_API +#define LWIP_PPP_API (PPP_SUPPORT && (NO_SYS == 0)) +#endif + +/** + * MEMP_NUM_PPP_PCB: the number of simultaneously active PPP + * connections (requires the PPP_SUPPORT option) + */ +#ifndef MEMP_NUM_PPP_PCB +#define MEMP_NUM_PPP_PCB 1 +#endif + +#if PPP_SUPPORT + +/** + * MEMP_NUM_PPPOS_INTERFACES: the number of concurrently active PPPoS + * interfaces (only used with PPPOS_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOS_INTERFACES +#define MEMP_NUM_PPPOS_INTERFACES MEMP_NUM_PPP_PCB +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 1 +#endif + +/** + * MEMP_NUM_PPPOL2TP_INTERFACES: the number of concurrently active PPPoL2TP + * interfaces (only used with PPPOL2TP_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOL2TP_INTERFACES +#define MEMP_NUM_PPPOL2TP_INTERFACES 1 +#endif + +/** + * MEMP_NUM_PPP_API_MSG: Number of concurrent PPP API messages (in pppapi.c) + */ +#ifndef MEMP_NUM_PPP_API_MSG +#define MEMP_NUM_PPP_API_MSG 5 +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_INPROC_IRQ_SAFE==1 call pppos_input() using tcpip_callback(). + * + * Please read the "PPPoS input path" chapter in the PPP documentation about this option. + */ +#ifndef PPP_INPROC_IRQ_SAFE +#define PPP_INPROC_IRQ_SAFE 0 +#endif + +/** + * PRINTPKT_SUPPORT==1: Enable PPP print packet support + * + * Mandatory for debugging, it displays exchanged packet content in debug trace. + */ +#ifndef PRINTPKT_SUPPORT +#define PRINTPKT_SUPPORT 0 +#endif + +/** + * PPP_IPV4_SUPPORT==1: Enable PPP IPv4 support + */ +#ifndef PPP_IPV4_SUPPORT +#define PPP_IPV4_SUPPORT (LWIP_IPV4) +#endif + +/** + * PPP_IPV6_SUPPORT==1: Enable PPP IPv6 support + */ +#ifndef PPP_IPV6_SUPPORT +#define PPP_IPV6_SUPPORT (LWIP_IPV6) +#endif + +/** + * PPP_NOTIFY_PHASE==1: Support PPP notify phase support + * + * PPP notify phase support allows you to set a callback which is + * called on change of the internal PPP state machine. + * + * This can be used for example to set a LED pattern depending on the + * current phase of the PPP session. + */ +#ifndef PPP_NOTIFY_PHASE +#define PPP_NOTIFY_PHASE 0 +#endif + +/** + * pbuf_type PPP is using for LCP, PAP, CHAP, EAP, CCP, IPCP and IP6CP packets. + * + * Memory allocated must be single buffered for PPP to works, it requires pbuf + * that are not going to be chained when allocated. This requires setting + * PBUF_POOL_BUFSIZE to at least 512 bytes, which is quite huge for small systems. + * + * Setting PPP_USE_PBUF_RAM to 1 makes PPP use memory from heap where continuous + * buffers are required, allowing you to use a smaller PBUF_POOL_BUFSIZE. + */ +#ifndef PPP_USE_PBUF_RAM +#define PPP_USE_PBUF_RAM 0 +#endif + +/** + * PPP_FCS_TABLE: Keep a 256*2 byte table to speed up FCS calculation for PPPoS + */ +#ifndef PPP_FCS_TABLE +#define PPP_FCS_TABLE 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif +#if MSCHAP_SUPPORT +/* MSCHAP requires CHAP support */ +#undef CHAP_SUPPORT +#define CHAP_SUPPORT 1 +#endif /* MSCHAP_SUPPORT */ + +/** + * EAP_SUPPORT==1: Support EAP. + */ +#ifndef EAP_SUPPORT +#define EAP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * MPPE_SUPPORT==1: Support MPPE. + */ +#ifndef MPPE_SUPPORT +#define MPPE_SUPPORT 0 +#endif +#if MPPE_SUPPORT +/* MPPE requires CCP support */ +#undef CCP_SUPPORT +#define CCP_SUPPORT 1 +/* MPPE requires MSCHAP support */ +#undef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 1 +/* MSCHAP requires CHAP support */ +#undef CHAP_SUPPORT +#define CHAP_SUPPORT 1 +#endif /* MPPE_SUPPORT */ + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * ECP_SUPPORT==1: Support ECP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef ECP_SUPPORT +#define ECP_SUPPORT 0 +#endif + +/** + * DEMAND_SUPPORT==1: Support dial on demand. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef DEMAND_SUPPORT +#define DEMAND_SUPPORT 0 +#endif + +/** + * LQR_SUPPORT==1: Support Link Quality Report. Do nothing except exchanging some LCP packets. + */ +#ifndef LQR_SUPPORT +#define LQR_SUPPORT 0 +#endif + +/** + * PPP_SERVER==1: Enable PPP server support (waiting for incoming PPP session). + * + * Currently only supported for PPPoS. + */ +#ifndef PPP_SERVER +#define PPP_SERVER 0 +#endif + +#if PPP_SERVER +/* + * PPP_OUR_NAME: Our name for authentication purposes + */ +#ifndef PPP_OUR_NAME +#define PPP_OUR_NAME "lwIP" +#endif +#endif /* PPP_SERVER */ + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 1 +#endif +/* VJ compression is only supported for TCP over IPv4 over PPPoS. */ +#if !PPPOS_SUPPORT || !PPP_IPV4_SUPPORT || !LWIP_TCP +#undef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif /* !PPPOS_SUPPORT */ + +/** + * PPP_MD5_RANDM==1: Use MD5 for better randomness. + * Enabled by default if CHAP, EAP, or L2TP AUTH support is enabled. + */ +#ifndef PPP_MD5_RANDM +#define PPP_MD5_RANDM (CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT) +#endif + +/** + * PolarSSL embedded library + * + * + * lwIP contains some files fetched from the latest BSD release of + * the PolarSSL project (PolarSSL 0.10.1-bsd) for ciphers and encryption + * methods we need for lwIP PPP support. + * + * The PolarSSL files were cleaned to contain only the necessary struct + * fields and functions needed for lwIP. + * + * The PolarSSL API was not changed at all, so if you are already using + * PolarSSL you can choose to skip the compilation of the included PolarSSL + * library into lwIP. + * + * If you are not using the embedded copy you must include external + * libraries into your arch/cc.h port file. + * + * Beware of the stack requirements which can be a lot larger if you are not + * using our cleaned PolarSSL library. + */ + +/** + * LWIP_USE_EXTERNAL_POLARSSL: Use external PolarSSL library + */ +#ifndef LWIP_USE_EXTERNAL_POLARSSL +#define LWIP_USE_EXTERNAL_POLARSSL 0 +#endif + +/** + * LWIP_USE_EXTERNAL_MBEDTLS: Use external mbed TLS library + */ +#ifndef LWIP_USE_EXTERNAL_MBEDTLS +#define LWIP_USE_EXTERNAL_MBEDTLS 0 +#endif + +/* + * PPP Timeouts + */ + +/** + * FSM_DEFTIMEOUT: Timeout time in seconds + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 +#endif + +/** + * FSM_DEFMAXTERMREQS: Maximum Terminate-Request transmissions + */ +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 +#endif + +/** + * FSM_DEFMAXCONFREQS: Maximum Configure-Request transmissions + */ +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 +#endif + +/** + * FSM_DEFMAXNAKLOOPS: Maximum number of nak loops + */ +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 +#endif + +/** + * UPAP_DEFTIMEOUT: Timeout (seconds) for retransmitting req + */ +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 +#endif + +/** + * UPAP_DEFTRANSMITS: Maximum number of auth-reqs to send + */ +#ifndef UPAP_DEFTRANSMITS +#define UPAP_DEFTRANSMITS 10 +#endif + +#if PPP_SERVER +/** + * UPAP_DEFREQTIME: Time to wait for auth-req from peer + */ +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 +#endif +#endif /* PPP_SERVER */ + +/** + * CHAP_DEFTIMEOUT: Timeout (seconds) for retransmitting req + */ +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 +#endif + +/** + * CHAP_DEFTRANSMITS: max # times to send challenge + */ +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 +#endif + +#if PPP_SERVER +/** + * CHAP_DEFRECHALLENGETIME: If this option is > 0, rechallenge the peer every n seconds + */ +#ifndef CHAP_DEFRECHALLENGETIME +#define CHAP_DEFRECHALLENGETIME 0 +#endif +#endif /* PPP_SERVER */ + +/** + * EAP_DEFREQTIME: Time to wait for peer request + */ +#ifndef EAP_DEFREQTIME +#define EAP_DEFREQTIME 6 +#endif + +/** + * EAP_DEFALLOWREQ: max # times to accept requests + */ +#ifndef EAP_DEFALLOWREQ +#define EAP_DEFALLOWREQ 10 +#endif + +#if PPP_SERVER +/** + * EAP_DEFTIMEOUT: Timeout (seconds) for rexmit + */ +#ifndef EAP_DEFTIMEOUT +#define EAP_DEFTIMEOUT 6 +#endif + +/** + * EAP_DEFTRANSMITS: max # times to transmit + */ +#ifndef EAP_DEFTRANSMITS +#define EAP_DEFTRANSMITS 10 +#endif +#endif /* PPP_SERVER */ + +/** + * LCP_DEFLOOPBACKFAIL: Default number of times we receive our magic number from the peer + * before deciding the link is looped-back. + */ +#ifndef LCP_DEFLOOPBACKFAIL +#define LCP_DEFLOOPBACKFAIL 10 +#endif + +/** + * LCP_ECHOINTERVAL: Interval in seconds between keepalive echo requests, 0 to disable. + */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/** + * LCP_MAXECHOFAILS: Number of unanswered echo requests before failure. + */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/** + * PPP_MAXIDLEFLAG: Max Xmit idle time (in ms) before resend flag char. + */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/** + * PPP Packet sizes + */ + +/** + * PPP_MRU: Default MRU + */ +#ifndef PPP_MRU +#define PPP_MRU 1500 +#endif + +/** + * PPP_DEFMRU: Default MRU to try + */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 1500 +#endif + +/** + * PPP_MAXMRU: Normally limit MRU to this (pppd default = 16384) + */ +#ifndef PPP_MAXMRU +#define PPP_MAXMRU 1500 +#endif + +/** + * PPP_MINMRU: No MRUs below this + */ +#ifndef PPP_MINMRU +#define PPP_MINMRU 128 +#endif + +/** + * PPPOL2TP_DEFMRU: Default MTU and MRU for L2TP + * Default = 1500 - PPPoE(6) - PPP Protocol(2) - IPv4 header(20) - UDP Header(8) + * - L2TP Header(6) - HDLC Header(2) - PPP Protocol(2) - MPPE Header(2) - PPP Protocol(2) + */ +#if PPPOL2TP_SUPPORT +#ifndef PPPOL2TP_DEFMRU +#define PPPOL2TP_DEFMRU 1450 +#endif +#endif /* PPPOL2TP_SUPPORT */ + +/** + * MAXNAMELEN: max length of hostname or name for auth + */ +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 +#endif + +/** + * MAXSECRETLEN: max length of password or secret + */ +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 +#endif + +/* ------------------------------------------------------------------------- */ + +/* + * Build triggers for embedded PolarSSL + */ +#if !LWIP_USE_EXTERNAL_POLARSSL && !LWIP_USE_EXTERNAL_MBEDTLS + +/* CHAP, EAP, L2TP AUTH and MD5 Random require MD5 support */ +#if CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM +#define LWIP_INCLUDED_POLARSSL_MD5 1 +#endif /* CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM */ + +#if MSCHAP_SUPPORT + +/* MSCHAP require MD4 support */ +#define LWIP_INCLUDED_POLARSSL_MD4 1 +/* MSCHAP require SHA1 support */ +#define LWIP_INCLUDED_POLARSSL_SHA1 1 +/* MSCHAP require DES support */ +#define LWIP_INCLUDED_POLARSSL_DES 1 + +/* MS-CHAP support is required for MPPE */ +#if MPPE_SUPPORT +/* MPPE require ARC4 support */ +#define LWIP_INCLUDED_POLARSSL_ARC4 1 +#endif /* MPPE_SUPPORT */ + +#endif /* MSCHAP_SUPPORT */ + +#endif /* !LWIP_USE_EXTERNAL_POLARSSL && !LWIP_USE_EXTERNAL_MBEDTLS */ + +/* Default value if unset */ +#ifndef LWIP_INCLUDED_POLARSSL_MD4 +#define LWIP_INCLUDED_POLARSSL_MD4 0 +#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ +#ifndef LWIP_INCLUDED_POLARSSL_MD5 +#define LWIP_INCLUDED_POLARSSL_MD5 0 +#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ +#ifndef LWIP_INCLUDED_POLARSSL_SHA1 +#define LWIP_INCLUDED_POLARSSL_SHA1 0 +#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ +#ifndef LWIP_INCLUDED_POLARSSL_DES +#define LWIP_INCLUDED_POLARSSL_DES 0 +#endif /* LWIP_INCLUDED_POLARSSL_DES */ +#ifndef LWIP_INCLUDED_POLARSSL_ARC4 +#define LWIP_INCLUDED_POLARSSL_ARC4 0 +#endif /* LWIP_INCLUDED_POLARSSL_ARC4 */ + +#endif /* PPP_SUPPORT */ + +#endif /* LWIP_PPP_OPTS_H */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/pppapi.h b/components/net/lwip-2.0.3/src/include/netif/ppp/pppapi.h new file mode 100644 index 0000000000..913d93f749 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/pppapi.h @@ -0,0 +1,137 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef LWIP_PPPAPI_H +#define LWIP_PPPAPI_H + +#include "netif/ppp/ppp_opts.h" + +#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/priv/tcpip_priv.h" +#include "netif/ppp/ppp.h" +#if PPPOS_SUPPORT +#include "netif/ppp/pppos.h" +#endif /* PPPOS_SUPPORT */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct pppapi_msg_msg { + ppp_pcb *ppp; + union { +#if PPP_NOTIFY_PHASE + struct { + ppp_notify_phase_cb_fn notify_phase_cb; + } setnotifyphasecb; +#endif /* PPP_NOTIFY_PHASE */ +#if PPPOS_SUPPORT + struct { + struct netif *pppif; + pppos_output_cb_fn output_cb; + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } serialcreate; +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT + struct { + struct netif *pppif; + struct netif *ethif; + const char *service_name; + const char *concentrator_name; + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } ethernetcreate; +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT + struct { + struct netif *pppif; + struct netif *netif; + API_MSG_M_DEF_C(ip_addr_t, ipaddr); + u16_t port; +#if PPPOL2TP_AUTH_SUPPORT + const u8_t *secret; + u8_t secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } l2tpcreate; +#endif /* PPPOL2TP_SUPPORT */ + struct { + u16_t holdoff; + } connect; + struct { + u8_t nocarrier; + } close; + struct { + u8_t cmd; + void *arg; + } ioctl; + } msg; +}; + +struct pppapi_msg { + struct tcpip_api_call_data call; + struct pppapi_msg_msg msg; +}; + +/* API for application */ +err_t pppapi_set_default(ppp_pcb *pcb); +#if PPP_NOTIFY_PHASE +err_t pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); +#endif /* PPP_NOTIFY_PHASE */ +#if PPPOS_SUPPORT +ppp_pcb *pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT +ppp_pcb *pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, + const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, + void *ctx_cb); +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT +ppp_pcb *pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOL2TP_SUPPORT */ +err_t pppapi_connect(ppp_pcb *pcb, u16_t holdoff); +#if PPP_SERVER +err_t pppapi_listen(ppp_pcb *pcb); +#endif /* PPP_SERVER */ +err_t pppapi_close(ppp_pcb *pcb, u8_t nocarrier); +err_t pppapi_free(ppp_pcb *pcb); +err_t pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_PPP_API */ + +#endif /* LWIP_PPPAPI_H */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/pppcrypt.h b/components/net/lwip-2.0.3/src/include/netif/ppp/pppcrypt.h new file mode 100644 index 0000000000..a7b2099f25 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/pppcrypt.h @@ -0,0 +1,136 @@ +/* + * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 + * + * Extracted from chap_ms.c by James Carlson. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* This header file is included in all PPP modules needing hashes and/or ciphers */ + +#ifndef PPPCRYPT_H +#define PPPCRYPT_H + +/* + * If included PolarSSL copy is not used, user is expected to include + * external libraries in arch/cc.h (which is included by lwip/arch.h). + */ +#include "lwip/arch.h" + +/* + * Map hashes and ciphers functions to PolarSSL + */ +#if !LWIP_USE_EXTERNAL_MBEDTLS + +#include "netif/ppp/polarssl/md4.h" +#define lwip_md4_context md4_context +#define lwip_md4_init(context) +#define lwip_md4_starts md4_starts +#define lwip_md4_update md4_update +#define lwip_md4_finish md4_finish +#define lwip_md4_free(context) + +#include "netif/ppp/polarssl/md5.h" +#define lwip_md5_context md5_context +#define lwip_md5_init(context) +#define lwip_md5_starts md5_starts +#define lwip_md5_update md5_update +#define lwip_md5_finish md5_finish +#define lwip_md5_free(context) + +#include "netif/ppp/polarssl/sha1.h" +#define lwip_sha1_context sha1_context +#define lwip_sha1_init(context) +#define lwip_sha1_starts sha1_starts +#define lwip_sha1_update sha1_update +#define lwip_sha1_finish sha1_finish +#define lwip_sha1_free(context) + +#include "netif/ppp/polarssl/des.h" +#define lwip_des_context des_context +#define lwip_des_init(context) +#define lwip_des_setkey_enc des_setkey_enc +#define lwip_des_crypt_ecb des_crypt_ecb +#define lwip_des_free(context) + +#include "netif/ppp/polarssl/arc4.h" +#define lwip_arc4_context arc4_context +#define lwip_arc4_init(context) +#define lwip_arc4_setup arc4_setup +#define lwip_arc4_crypt arc4_crypt +#define lwip_arc4_free(context) + +#endif /* !LWIP_USE_EXTERNAL_MBEDTLS */ + +/* + * Map hashes and ciphers functions to mbed TLS + */ +#if LWIP_USE_EXTERNAL_MBEDTLS + +#define lwip_md4_context mbedtls_md4_context +#define lwip_md4_init mbedtls_md4_init +#define lwip_md4_starts mbedtls_md4_starts +#define lwip_md4_update mbedtls_md4_update +#define lwip_md4_finish mbedtls_md4_finish +#define lwip_md4_free mbedtls_md4_free + +#define lwip_md5_context mbedtls_md5_context +#define lwip_md5_init mbedtls_md5_init +#define lwip_md5_starts mbedtls_md5_starts +#define lwip_md5_update mbedtls_md5_update +#define lwip_md5_finish mbedtls_md5_finish +#define lwip_md5_free mbedtls_md5_free + +#define lwip_sha1_context mbedtls_sha1_context +#define lwip_sha1_init mbedtls_sha1_init +#define lwip_sha1_starts mbedtls_sha1_starts +#define lwip_sha1_update mbedtls_sha1_update +#define lwip_sha1_finish mbedtls_sha1_finish +#define lwip_sha1_free mbedtls_sha1_free + +#define lwip_des_context mbedtls_des_context +#define lwip_des_init mbedtls_des_init +#define lwip_des_setkey_enc mbedtls_des_setkey_enc +#define lwip_des_crypt_ecb mbedtls_des_crypt_ecb +#define lwip_des_free mbedtls_des_free + +#define lwip_arc4_context mbedtls_arc4_context +#define lwip_arc4_init mbedtls_arc4_init +#define lwip_arc4_setup mbedtls_arc4_setup +#define lwip_arc4_crypt(context, buffer, length) mbedtls_arc4_crypt(context, length, buffer, buffer) +#define lwip_arc4_free mbedtls_arc4_free + +#endif /* LWIP_USE_EXTERNAL_MBEDTLS */ + +void pppcrypt_56_to_64_bit_key(u_char *key, u_char *des_key); + +#endif /* PPPCRYPT_H */ + +#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/pppdebug.h b/components/net/lwip-2.0.3/src/include/netif/ppp/pppdebug.h new file mode 100644 index 0000000000..7ead045910 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/pppdebug.h @@ -0,0 +1,80 @@ +/***************************************************************************** +* pppdebug.h - System debugging utilities. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* portions Copyright (c) 2001 by Cognizant Pty Ltd. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY (please don't use tabs!) +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-07-29 Guy Lancaster , Global Election Systems Inc. +* Original. +* +***************************************************************************** +*/ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPDEBUG_H +#define PPPDEBUG_H + +/* Trace levels. */ +#define LOG_CRITICAL (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_ERR (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_NOTICE (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_WARNING (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_INFO (PPP_DEBUG) +#define LOG_DETAIL (PPP_DEBUG) +#define LOG_DEBUG (PPP_DEBUG) + +#if PPP_DEBUG + +#define MAINDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define SYSDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define FSMDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define LCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define IPCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define IPV6CPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define UPAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define CHAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define PPPDEBUG(a, b) LWIP_DEBUGF(a, b) + +#else /* PPP_DEBUG */ + +#define MAINDEBUG(a) +#define SYSDEBUG(a) +#define FSMDEBUG(a) +#define LCPDEBUG(a) +#define IPCPDEBUG(a) +#define IPV6CPDEBUG(a) +#define UPAPDEBUG(a) +#define CHAPDEBUG(a) +#define PPPDEBUG(a, b) + +#endif /* PPP_DEBUG */ + +#endif /* PPPDEBUG_H */ + +#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/pppoe.h b/components/net/lwip-2.0.3/src/include/netif/ppp/pppoe.h new file mode 100644 index 0000000000..9f8f2892b4 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/pppoe.h @@ -0,0 +1,179 @@ +/***************************************************************************** +* pppoe.h - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_OE_H +#define PPP_OE_H + +#include "ppp.h" +#include "lwip/etharp.h" + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoehdr { + PACK_STRUCT_FLD_8(u8_t vertype); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t session); + PACK_STRUCT_FIELD(u16_t plen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoetag { + PACK_STRUCT_FIELD(u16_t tag); + PACK_STRUCT_FIELD(u16_t len); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +#define PPPOE_STATE_INITIAL 0 +#define PPPOE_STATE_PADI_SENT 1 +#define PPPOE_STATE_PADR_SENT 2 +#define PPPOE_STATE_SESSION 3 +/* passive */ +#define PPPOE_STATE_PADO_SENT 1 + +#define PPPOE_HEADERLEN sizeof(struct pppoehdr) +#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */ + +#define PPPOE_TAG_EOL 0x0000 /* end of list */ +#define PPPOE_TAG_SNAME 0x0101 /* service name */ +#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */ +#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */ +#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */ +#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */ +#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ +#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ +#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ +#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ + +#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ +#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ +#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ +#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ +#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ + +#ifndef PPPOE_MAX_AC_COOKIE_LEN +#define PPPOE_MAX_AC_COOKIE_LEN 64 +#endif + +struct pppoe_softc { + struct pppoe_softc *next; + struct netif *sc_ethif; /* ethernet interface we are using */ + ppp_pcb *pcb; /* PPP PCB */ + + struct eth_addr sc_dest; /* hardware address of concentrator */ + u16_t sc_session; /* PPPoE session id */ + u8_t sc_state; /* discovery phase or session connected */ + +#ifdef PPPOE_TODO + u8_t *sc_service_name; /* if != NULL: requested name of service */ + u8_t *sc_concentrator_name; /* if != NULL: requested concentrator id */ +#endif /* PPPOE_TODO */ + u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */ + u8_t sc_ac_cookie_len; /* length of cookie data */ +#ifdef PPPOE_SERVER + u8_t *sc_hunique; /* content of host unique we must echo back */ + u8_t sc_hunique_len; /* length of host unique */ +#endif + u8_t sc_padi_retried; /* number of PADI retries already done */ + u8_t sc_padr_retried; /* number of PADR retries already done */ +}; + + +#define pppoe_init() /* compatibility define, no initialization needed */ + +ppp_pcb *pppoe_create(struct netif *pppif, + struct netif *ethif, + const char *service_name, const char *concentrator_name, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +/* + * Functions called from lwIP + * DO NOT CALL FROM lwIP USER APPLICATION. + */ +void pppoe_disc_input(struct netif *netif, struct pbuf *p); +void pppoe_data_input(struct netif *netif, struct pbuf *p); + +#endif /* PPP_OE_H */ + +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/pppol2tp.h b/components/net/lwip-2.0.3/src/include/netif/ppp/pppol2tp.h new file mode 100644 index 0000000000..f03950e65d --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/pppol2tp.h @@ -0,0 +1,201 @@ +/** + * @file + * Network Point to Point Protocol over Layer 2 Tunneling Protocol header file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPOL2TP_H +#define PPPOL2TP_H + +#include "ppp.h" + +/* Timeout */ +#define PPPOL2TP_CONTROL_TIMEOUT (5*1000) /* base for quick timeout calculation */ +#define PPPOL2TP_SLOW_RETRY (60*1000) /* persistent retry interval */ + +#define PPPOL2TP_MAXSCCRQ 4 /* retry SCCRQ four times (quickly) */ +#define PPPOL2TP_MAXICRQ 4 /* retry IRCQ four times */ +#define PPPOL2TP_MAXICCN 4 /* retry ICCN four times */ + +/* L2TP header flags */ +#define PPPOL2TP_HEADERFLAG_CONTROL 0x8000 +#define PPPOL2TP_HEADERFLAG_LENGTH 0x4000 +#define PPPOL2TP_HEADERFLAG_SEQUENCE 0x0800 +#define PPPOL2TP_HEADERFLAG_OFFSET 0x0200 +#define PPPOL2TP_HEADERFLAG_PRIORITY 0x0100 +#define PPPOL2TP_HEADERFLAG_VERSION 0x0002 + +/* Mandatory bits for control: Control, Length, Sequence, Version 2 */ +#define PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY (PPPOL2TP_HEADERFLAG_CONTROL|PPPOL2TP_HEADERFLAG_LENGTH|PPPOL2TP_HEADERFLAG_SEQUENCE|PPPOL2TP_HEADERFLAG_VERSION) +/* Forbidden bits for control: Offset, Priority */ +#define PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN (PPPOL2TP_HEADERFLAG_OFFSET|PPPOL2TP_HEADERFLAG_PRIORITY) + +/* Mandatory bits for data: Version 2 */ +#define PPPOL2TP_HEADERFLAG_DATA_MANDATORY (PPPOL2TP_HEADERFLAG_VERSION) + +/* AVP (Attribute Value Pair) header */ +#define PPPOL2TP_AVPHEADERFLAG_MANDATORY 0x8000 +#define PPPOL2TP_AVPHEADERFLAG_HIDDEN 0x4000 +#define PPPOL2TP_AVPHEADERFLAG_LENGTHMASK 0x03ff + +/* -- AVP - Message type */ +#define PPPOL2TP_AVPTYPE_MESSAGE 0 /* Message type */ + +/* Control Connection Management */ +#define PPPOL2TP_MESSAGETYPE_SCCRQ 1 /* Start Control Connection Request */ +#define PPPOL2TP_MESSAGETYPE_SCCRP 2 /* Start Control Connection Reply */ +#define PPPOL2TP_MESSAGETYPE_SCCCN 3 /* Start Control Connection Connected */ +#define PPPOL2TP_MESSAGETYPE_STOPCCN 4 /* Stop Control Connection Notification */ +#define PPPOL2TP_MESSAGETYPE_HELLO 6 /* Hello */ +/* Call Management */ +#define PPPOL2TP_MESSAGETYPE_OCRQ 7 /* Outgoing Call Request */ +#define PPPOL2TP_MESSAGETYPE_OCRP 8 /* Outgoing Call Reply */ +#define PPPOL2TP_MESSAGETYPE_OCCN 9 /* Outgoing Call Connected */ +#define PPPOL2TP_MESSAGETYPE_ICRQ 10 /* Incoming Call Request */ +#define PPPOL2TP_MESSAGETYPE_ICRP 11 /* Incoming Call Reply */ +#define PPPOL2TP_MESSAGETYPE_ICCN 12 /* Incoming Call Connected */ +#define PPPOL2TP_MESSAGETYPE_CDN 14 /* Call Disconnect Notify */ +/* Error reporting */ +#define PPPOL2TP_MESSAGETYPE_WEN 15 /* WAN Error Notify */ +/* PPP Session Control */ +#define PPPOL2TP_MESSAGETYPE_SLI 16 /* Set Link Info */ + +/* -- AVP - Result code */ +#define PPPOL2TP_AVPTYPE_RESULTCODE 1 /* Result code */ +#define PPPOL2TP_RESULTCODE 1 /* General request to clear control connection */ + +/* -- AVP - Protocol version (!= L2TP Header version) */ +#define PPPOL2TP_AVPTYPE_VERSION 2 +#define PPPOL2TP_VERSION 0x0100 /* L2TP Protocol version 1, revision 0 */ + +/* -- AVP - Framing capabilities */ +#define PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES 3 /* Bearer capabilities */ +#define PPPOL2TP_FRAMINGCAPABILITIES 0x00000003 /* Async + Sync framing */ + +/* -- AVP - Bearer capabilities */ +#define PPPOL2TP_AVPTYPE_BEARERCAPABILITIES 4 /* Bearer capabilities */ +#define PPPOL2TP_BEARERCAPABILITIES 0x00000003 /* Analog + Digital Access */ + +/* -- AVP - Tie breaker */ +#define PPPOL2TP_AVPTYPE_TIEBREAKER 5 + +/* -- AVP - Host name */ +#define PPPOL2TP_AVPTYPE_HOSTNAME 7 /* Host name */ +#define PPPOL2TP_HOSTNAME "lwIP" /* FIXME: make it configurable */ + +/* -- AVP - Vendor name */ +#define PPPOL2TP_AVPTYPE_VENDORNAME 8 /* Vendor name */ +#define PPPOL2TP_VENDORNAME "lwIP" /* FIXME: make it configurable */ + +/* -- AVP - Assign tunnel ID */ +#define PPPOL2TP_AVPTYPE_TUNNELID 9 /* Assign Tunnel ID */ + +/* -- AVP - Receive window size */ +#define PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE 10 /* Receive window size */ +#define PPPOL2TP_RECEIVEWINDOWSIZE 8 /* FIXME: make it configurable */ + +/* -- AVP - Challenge */ +#define PPPOL2TP_AVPTYPE_CHALLENGE 11 /* Challenge */ + +/* -- AVP - Cause code */ +#define PPPOL2TP_AVPTYPE_CAUSECODE 12 /* Cause code*/ + +/* -- AVP - Challenge response */ +#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE 13 /* Challenge response */ +#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE 16 + +/* -- AVP - Assign session ID */ +#define PPPOL2TP_AVPTYPE_SESSIONID 14 /* Assign Session ID */ + +/* -- AVP - Call serial number */ +#define PPPOL2TP_AVPTYPE_CALLSERIALNUMBER 15 /* Call Serial Number */ + +/* -- AVP - Framing type */ +#define PPPOL2TP_AVPTYPE_FRAMINGTYPE 19 /* Framing Type */ +#define PPPOL2TP_FRAMINGTYPE 0x00000001 /* Sync framing */ + +/* -- AVP - TX Connect Speed */ +#define PPPOL2TP_AVPTYPE_TXCONNECTSPEED 24 /* TX Connect Speed */ +#define PPPOL2TP_TXCONNECTSPEED 100000000 /* Connect speed: 100 Mbits/s */ + +/* L2TP Session state */ +#define PPPOL2TP_STATE_INITIAL 0 +#define PPPOL2TP_STATE_SCCRQ_SENT 1 +#define PPPOL2TP_STATE_ICRQ_SENT 2 +#define PPPOL2TP_STATE_ICCN_SENT 3 +#define PPPOL2TP_STATE_DATA 4 + +#define PPPOL2TP_OUTPUT_DATA_HEADER_LEN 6 /* Our data header len */ + +/* + * PPPoL2TP interface control block. + */ +typedef struct pppol2tp_pcb_s pppol2tp_pcb; +struct pppol2tp_pcb_s { + ppp_pcb *ppp; /* PPP PCB */ + u8_t phase; /* L2TP phase */ + struct udp_pcb *udp; /* UDP L2TP Socket */ + struct netif *netif; /* Output interface, used as a default route */ + ip_addr_t remote_ip; /* LNS IP Address */ + u16_t remote_port; /* LNS port */ +#if PPPOL2TP_AUTH_SUPPORT + const u8_t *secret; /* Secret string */ + u8_t secret_len; /* Secret string length */ + u8_t secret_rv[16]; /* Random vector */ + u8_t challenge_hash[16]; /* Challenge response */ + u8_t send_challenge; /* Boolean whether the next sent packet should contains a challenge response */ +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + u16_t tunnel_port; /* Tunnel port */ + u16_t our_ns; /* NS to peer */ + u16_t peer_nr; /* NR from peer */ + u16_t peer_ns; /* NS from peer */ + u16_t source_tunnel_id; /* Tunnel ID assigned by peer */ + u16_t remote_tunnel_id; /* Tunnel ID assigned to peer */ + u16_t source_session_id; /* Session ID assigned by peer */ + u16_t remote_session_id; /* Session ID assigned to peer */ + + u8_t sccrq_retried; /* number of SCCRQ retries already done */ + u8_t icrq_retried; /* number of ICRQ retries already done */ + u8_t iccn_retried; /* number of ICCN retries already done */ +}; + + +/* Create a new L2TP session. */ +ppp_pcb *pppol2tp_create(struct netif *pppif, + struct netif *netif, const ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +#endif /* PPPOL2TP_H */ +#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/pppos.h b/components/net/lwip-2.0.3/src/include/netif/ppp/pppos.h new file mode 100644 index 0000000000..d924a9fc7e --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/pppos.h @@ -0,0 +1,118 @@ +/** + * @file + * Network Point to Point Protocol over Serial header file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPOS_H +#define PPPOS_H + +#include "lwip/sys.h" + +#include "ppp.h" +#include "vj.h" + +/* PPP packet parser states. Current state indicates operation yet to be + * completed. */ +enum { + PDIDLE = 0, /* Idle state - waiting. */ + PDSTART, /* Process start flag. */ + PDADDRESS, /* Process address field. */ + PDCONTROL, /* Process control field. */ + PDPROTOCOL1, /* Process protocol field 1. */ + PDPROTOCOL2, /* Process protocol field 2. */ + PDDATA /* Process data byte. */ +}; + +/* PPPoS serial output callback function prototype */ +typedef u32_t (*pppos_output_cb_fn)(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx); + +/* + * Extended asyncmap - allows any character to be escaped. + */ +typedef u8_t ext_accm[32]; + +/* + * PPPoS interface control block. + */ +typedef struct pppos_pcb_s pppos_pcb; +struct pppos_pcb_s { + /* -- below are data that will NOT be cleared between two sessions */ + ppp_pcb *ppp; /* PPP PCB */ + pppos_output_cb_fn output_cb; /* PPP serial output callback */ + + /* -- below are data that will be cleared between two sessions + * + * last_xmit must be the first member of cleared members, because it is + * used to know which part must not be cleared. + */ + u32_t last_xmit; /* Time of last transmission. */ + ext_accm out_accm; /* Async-Ctl-Char-Map for output. */ + + /* flags */ + unsigned int open :1; /* Set if PPPoS is open */ + unsigned int pcomp :1; /* Does peer accept protocol compression? */ + unsigned int accomp :1; /* Does peer accept addr/ctl compression? */ + + /* PPPoS rx */ + ext_accm in_accm; /* Async-Ctl-Char-Map for input. */ + struct pbuf *in_head, *in_tail; /* The input packet. */ + u16_t in_protocol; /* The input protocol code. */ + u16_t in_fcs; /* Input Frame Check Sequence value. */ + u8_t in_state; /* The input process state. */ + u8_t in_escaped; /* Escape next character. */ +}; + +/* Create a new PPPoS session. */ +ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +#if !NO_SYS && !PPP_INPROC_IRQ_SAFE +/* Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. */ +err_t pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l); +#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ + +/* PPP over Serial: this is the input function to be called for received data. */ +void pppos_input(ppp_pcb *ppp, u8_t* data, int len); + + +/* + * Functions called from lwIP + * DO NOT CALL FROM lwIP USER APPLICATION. + */ +#if !NO_SYS && !PPP_INPROC_IRQ_SAFE +err_t pppos_input_sys(struct pbuf *p, struct netif *inp); +#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ + +#endif /* PPPOS_H */ +#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/upap.h b/components/net/lwip-2.0.3/src/include/netif/ppp/upap.h new file mode 100644 index 0000000000..7da792ecc7 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/upap.h @@ -0,0 +1,123 @@ +/* + * upap.h - User/Password Authentication Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: upap.h,v 1.8 2002/12/04 23:03:33 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef UPAP_H +#define UPAP_H + +#include "ppp.h" + +/* + * Packet header = Code, id, length. + */ +#define UPAP_HEADERLEN 4 + + +/* + * UPAP codes. + */ +#define UPAP_AUTHREQ 1 /* Authenticate-Request */ +#define UPAP_AUTHACK 2 /* Authenticate-Ack */ +#define UPAP_AUTHNAK 3 /* Authenticate-Nak */ + + +/* + * Client states. + */ +#define UPAPCS_INITIAL 0 /* Connection down */ +#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPCS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */ +#define UPAPCS_OPEN 4 /* We've received an Ack */ +#define UPAPCS_BADAUTH 5 /* We've received a Nak */ + +/* + * Server states. + */ +#define UPAPSS_INITIAL 0 /* Connection down */ +#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPSS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */ +#define UPAPSS_OPEN 4 /* We've sent an Ack */ +#define UPAPSS_BADAUTH 5 /* We've sent a Nak */ + + +/* + * Timeouts. + */ +#if 0 /* moved to ppp_opts.h */ +#define UPAP_DEFTIMEOUT 3 /* Timeout (seconds) for retransmitting req */ +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif /* moved to ppp_opts.h */ + +/* + * Each interface is described by upap structure. + */ +#if PAP_SUPPORT +typedef struct upap_state { + const char *us_user; /* User */ + u8_t us_userlen; /* User length */ + const char *us_passwd; /* Password */ + u8_t us_passwdlen; /* Password length */ + u8_t us_clientstate; /* Client state */ +#if PPP_SERVER + u8_t us_serverstate; /* Server state */ +#endif /* PPP_SERVER */ + u8_t us_id; /* Current id */ + u8_t us_transmits; /* Number of auth-reqs sent */ +} upap_state; +#endif /* PAP_SUPPORT */ + + +void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password); +#if PPP_SERVER +void upap_authpeer(ppp_pcb *pcb); +#endif /* PPP_SERVER */ + +extern const struct protent pap_protent; + +#endif /* UPAP_H */ +#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/ppp/vj.h b/components/net/lwip-2.0.3/src/include/netif/ppp/vj.h new file mode 100644 index 0000000000..7f389c846f --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/ppp/vj.h @@ -0,0 +1,161 @@ +/* + * Definitions for tcp compression routines. + * + * $Id: vj.h,v 1.7 2010/02/22 17:52:09 goldsimon Exp $ + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * - Initial distribution. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef VJ_H +#define VJ_H + +#include "lwip/ip.h" +#include "lwip/priv/tcp_priv.h" + +#define MAX_SLOTS 16 /* must be > 2 and < 256 */ +#define MAX_HDR 128 + +/* + * Compressed packet format: + * + * The first octet contains the packet type (top 3 bits), TCP + * 'push' bit, and flags that indicate which of the 4 TCP sequence + * numbers have changed (bottom 5 bits). The next octet is a + * conversation number that associates a saved IP/TCP header with + * the compressed packet. The next two octets are the TCP checksum + * from the original datagram. The next 0 to 15 octets are + * sequence number changes, one change per bit set in the header + * (there may be no changes and there are two special cases where + * the receiver implicitly knows what changed -- see below). + * + * There are 5 numbers which can change (they are always inserted + * in the following order): TCP urgent pointer, window, + * acknowlegement, sequence number and IP ID. (The urgent pointer + * is different from the others in that its value is sent, not the + * change in value.) Since typical use of SLIP links is biased + * toward small packets (see comments on MTU/MSS below), changes + * use a variable length coding with one octet for numbers in the + * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the + * range 256 - 65535 or 0. (If the change in sequence number or + * ack is more than 65535, an uncompressed packet is sent.) + */ + +/* + * Packet types (must not conflict with IP protocol version) + * + * The top nibble of the first octet is the packet type. There are + * three possible types: IP (not proto TCP or tcp with one of the + * control flags set); uncompressed TCP (a normal IP/TCP packet but + * with the 8-bit protocol field replaced by an 8-bit connection id -- + * this type of packet syncs the sender & receiver); and compressed + * TCP (described above). + * + * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and + * is logically part of the 4-bit "changes" field that follows. Top + * three bits are actual packet type. For backward compatibility + * and in the interest of conserving bits, numbers are chosen so the + * IP protocol version number (4) which normally appears in this nibble + * means "IP packet". + */ + +/* packet types */ +#define TYPE_IP 0x40 +#define TYPE_UNCOMPRESSED_TCP 0x70 +#define TYPE_COMPRESSED_TCP 0x80 +#define TYPE_ERROR 0x00 + +/* Bits in first octet of compressed packet */ +#define NEW_C 0x40 /* flag bits for what changed in a packet */ +#define NEW_I 0x20 +#define NEW_S 0x08 +#define NEW_A 0x04 +#define NEW_W 0x02 +#define NEW_U 0x01 + +/* reserved, special-case values of above */ +#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ +#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ +#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) + +#define TCP_PUSH_BIT 0x10 + + +/* + * "state" data for each active tcp conversation on the wire. This is + * basically a copy of the entire IP/TCP header from the last packet + * we saw from the conversation together with a small identifier + * the transmit & receive ends of the line use to locate saved header. + */ +struct cstate { + struct cstate *cs_next; /* next most recently used state (xmit only) */ + u16_t cs_hlen; /* size of hdr (receive only) */ + u8_t cs_id; /* connection # associated with this state */ + u8_t cs_filler; + union { + char csu_hdr[MAX_HDR]; + struct ip_hdr csu_ip; /* ip/tcp hdr from most recent packet */ + } vjcs_u; +}; +#define cs_ip vjcs_u.csu_ip +#define cs_hdr vjcs_u.csu_hdr + + +struct vjstat { + u32_t vjs_packets; /* outbound packets */ + u32_t vjs_compressed; /* outbound compressed packets */ + u32_t vjs_searches; /* searches for connection state */ + u32_t vjs_misses; /* times couldn't find conn. state */ + u32_t vjs_uncompressedin; /* inbound uncompressed packets */ + u32_t vjs_compressedin; /* inbound compressed packets */ + u32_t vjs_errorin; /* inbound unknown type packets */ + u32_t vjs_tossed; /* inbound packets tossed because of error */ +}; + +/* + * all the state data for one serial line (we need one of these per line). + */ +struct vjcompress { + struct cstate *last_cs; /* most recently used tstate */ + u8_t last_recv; /* last rcvd conn. id */ + u8_t last_xmit; /* last sent conn. id */ + u16_t flags; + u8_t maxSlotIndex; + u8_t compressSlot; /* Flag indicating OK to compress slot ID. */ +#if LINK_STATS + struct vjstat stats; +#endif + struct cstate tstate[MAX_SLOTS]; /* xmit connection states */ + struct cstate rstate[MAX_SLOTS]; /* receive connection states */ +}; + +/* flag values */ +#define VJF_TOSS 1U /* tossing rcvd frames because of input err */ + +extern void vj_compress_init (struct vjcompress *comp); +extern u8_t vj_compress_tcp (struct vjcompress *comp, struct pbuf **pb); +extern void vj_uncompress_err (struct vjcompress *comp); +extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp); +extern int vj_uncompress_tcp (struct pbuf **nb, struct vjcompress *comp); + +#endif /* VJ_H */ + +#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/include/netif/slipif.h b/components/net/lwip-2.0.3/src/include/netif/slipif.h new file mode 100644 index 0000000000..65ba31f835 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/netif/slipif.h @@ -0,0 +1,87 @@ +/** + * @file + * + * SLIP netif API + */ + +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETIF_SLIPIF_H +#define LWIP_HDR_NETIF_SLIPIF_H + +#include "lwip/opt.h" +#include "lwip/netif.h" + +/** Set this to 1 to start a thread that blocks reading on the serial line + * (using sio_read()). + */ +#ifndef SLIP_USE_RX_THREAD +#define SLIP_USE_RX_THREAD !NO_SYS +#endif + +/** Set this to 1 to enable functions to pass in RX bytes from ISR context. + * If enabled, slipif_received_byte[s]() process incoming bytes and put assembled + * packets on a queue, which is fed into lwIP from slipif_poll(). + * If disabled, slipif_poll() polls the serial line (using sio_tryread()). + */ +#ifndef SLIP_RX_FROM_ISR +#define SLIP_RX_FROM_ISR 0 +#endif + +/** Set this to 1 (default for SLIP_RX_FROM_ISR) to queue incoming packets + * received by slipif_received_byte[s]() as long as PBUF_POOL pbufs are available. + * If disabled, packets will be dropped if more than one packet is received. + */ +#ifndef SLIP_RX_QUEUE +#define SLIP_RX_QUEUE SLIP_RX_FROM_ISR +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +err_t slipif_init(struct netif * netif); +void slipif_poll(struct netif *netif); +#if SLIP_RX_FROM_ISR +void slipif_process_rxqueue(struct netif *netif); +void slipif_received_byte(struct netif *netif, u8_t data); +void slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len); +#endif /* SLIP_RX_FROM_ISR */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_SLIPIF_H */ + diff --git a/components/net/lwip-2.0.3/src/include/posix/errno.h b/components/net/lwip-2.0.3/src/include/posix/errno.h new file mode 100644 index 0000000000..5917c75e24 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/posix/errno.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/errno.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/errno.h" diff --git a/components/net/lwip-2.0.3/src/include/posix/netdb.h b/components/net/lwip-2.0.3/src/include/posix/netdb.h new file mode 100644 index 0000000000..12d4c7f566 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/posix/netdb.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/netdb.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/netdb.h" diff --git a/components/net/lwip-2.0.3/src/include/posix/sys/socket.h b/components/net/lwip-2.0.3/src/include/posix/sys/socket.h new file mode 100644 index 0000000000..0ed9baf3d9 --- /dev/null +++ b/components/net/lwip-2.0.3/src/include/posix/sys/socket.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/sockets.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/sockets.h" diff --git a/components/net/lwip-2.0.3/src/lwipopts.h b/components/net/lwip-2.0.3/src/lwipopts.h new file mode 100644 index 0000000000..d559684c02 --- /dev/null +++ b/components/net/lwip-2.0.3/src/lwipopts.h @@ -0,0 +1,636 @@ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +#include + +#define LWIP_ERRNO_STDINCLUDE + +#define LWIP_IPV4 1 + +#ifdef RT_USING_LWIP_IPV6 +#define LWIP_IPV6 1 +#else +#define LWIP_IPV6 0 +#endif /* RT_USING_LWIP_IPV6 */ + +#define NO_SYS 0 +#define LWIP_SOCKET 1 +#define LWIP_NETCONN 1 + +#ifdef RT_LWIP_IGMP +#define LWIP_IGMP 1 +#else +#define LWIP_IGMP 0 +#endif + +#ifdef RT_LWIP_ICMP +#define LWIP_ICMP 1 +#else +#define LWIP_ICMP 0 +#endif + +#ifdef RT_LWIP_SNMP +#define LWIP_SNMP 1 +#else +#define LWIP_SNMP 0 +#endif + +#ifdef RT_LWIP_DNS +#define LWIP_DNS 1 +#else +#define LWIP_DNS 0 +#endif + +#define LWIP_HAVE_LOOPIF 0 + +#define LWIP_PLATFORM_BYTESWAP 0 + +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +/* #define RT_LWIP_DEBUG */ + +#ifdef RT_LWIP_DEBUG +#define LWIP_DEBUG +#endif + +/* ---------- Debug options ---------- */ +#ifdef LWIP_DEBUG +#ifdef RT_LWIP_SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_ON +#else +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_ON +#else +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_ON +#else +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_ON +#else +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_ON +#else +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_ON +#else +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_ON +#else +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_ON +#else +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_ON +#else +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_ON +#else +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_ON +#else +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_ON +#else +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_ON +#else +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_ON +#else +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_IP_DEBUG +#define IP_DEBUG LWIP_DBG_ON +#else +#define IP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_ON +#else +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_ON +#else +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_ON +#else +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_ON +#else +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_ON +#else +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_ON +#else +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_ON +#else +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_ON +#else +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_ON +#else +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_ON +#else +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_ON +#else +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_ON +#else +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_ON +#else +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +#endif /* LWIP_DEBUG */ + +#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT) + +/* ---------- Memory options ---------- */ +#ifdef RT_LWIP_MEM_ALIGNMENT +#define MEM_ALIGNMENT RT_LWIP_MEM_ALIGNMENT +#else +#define MEM_ALIGNMENT 4 +#endif + +#define MEMP_OVERFLOW_CHECK 1 //// +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 1 //// +//#define MEM_LIBC_MALLOC 1 +//#define MEM_USE_POOLS 1 +//#define MEMP_USE_CUSTOM_POOLS 1 +//#define MEM_SIZE (1024*64) + +#define MEMP_MEM_MALLOC 0 + +/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application + sends a lot of data out of ROM (or other static memory), this + should be set high. */ +#define MEMP_NUM_PBUF 32 //16 + +/* the number of struct netconns */ +#ifdef RT_MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN RT_MEMP_NUM_NETCONN +#endif + +/* the number of UDP protocol control blocks. One per active RAW "connection". */ +#ifdef RT_LWIP_RAW_PCB_NUM +#define MEMP_NUM_RAW_PCB RT_LWIP_RAW_PCB_NUM +#endif + +/* the number of UDP protocol control blocks. One per active UDP "connection". */ +#ifdef RT_LWIP_UDP_PCB_NUM +#define MEMP_NUM_UDP_PCB RT_LWIP_UDP_PCB_NUM +#endif + +/* the number of simulatenously active TCP connections. */ +#ifdef RT_LWIP_TCP_PCB_NUM +#define MEMP_NUM_TCP_PCB RT_LWIP_TCP_PCB_NUM +#endif + +/* the number of simultaneously queued TCP */ +#ifdef RT_LWIP_TCP_SEG_NUM +#define MEMP_NUM_TCP_SEG RT_LWIP_TCP_SEG_NUM +#else +#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN +#endif + +/* + * You can re-define following setting in rtcofnig.h to overwrite the default + * setting in the lwip opts.h + */ +/* MEMP_NUM_NETBUF: the number of struct netbufs. */ +// #define MEMP_NUM_NETBUF 2 +/* MEMP_NUM_NETCONN: the number of struct netconns. */ +// #define MEMP_NUM_NETCONN 4 + +/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used + for sequential API communication and incoming packets. Used in + src/api/tcpip.c. */ +// #define MEMP_NUM_TCPIP_MSG_API 16 +// #define MEMP_NUM_TCPIP_MSG_INPKT 16 + +/* ---------- Pbuf options ---------- */ +/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ +#ifdef RT_LWIP_PBUF_NUM +#define PBUF_POOL_SIZE RT_LWIP_PBUF_NUM +#endif + +/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ +#ifdef RT_LWIP_PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE RT_LWIP_PBUF_POOL_BUFSIZE +#endif + +/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a + link level header. */ +#define PBUF_LINK_HLEN 16 + +#ifdef RT_LWIP_ETH_PAD_SIZE +#define ETH_PAD_SIZE RT_LWIP_ETH_PAD_SIZE +#endif + +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT (NO_SYS==0) + +#ifdef LWIP_USING_NAT +#define IP_NAT 1 +#else +#define IP_NAT 0 +#endif + +/* ---------- TCP options ---------- */ +#ifdef RT_LWIP_TCP +#define LWIP_TCP 1 +#else +#define LWIP_TCP 0 +#endif + +#define TCP_TTL 255 + +/* Controls if TCP should queue segments that arrive out of + order. Define to 0 if your device is low on memory. */ +#define TCP_QUEUE_OOSEQ 1 + +/* TCP Maximum segment size. */ +#define TCP_MSS 1460 + +/* TCP sender buffer space (bytes). */ +#ifdef RT_LWIP_TCP_SND_BUF +#define TCP_SND_BUF RT_LWIP_TCP_SND_BUF +#else +#define TCP_SND_BUF (TCP_MSS * 2) +#endif + +/* TCP sender buffer space (pbufs). This must be at least = 2 * + TCP_SND_BUF/TCP_MSS for things to work. */ +#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS) + +/* TCP writable space (bytes). This must be less than or equal + to TCP_SND_BUF. It is the amount of space which must be + available in the tcp snd_buf for select to return writable */ +#define TCP_SNDLOWAT (TCP_SND_BUF/2) +#define TCP_SNDQUEUELOWAT TCP_SND_QUEUELEN/2 + +/* TCP receive window. */ +#ifdef RT_LWIP_TCP_WND +#define TCP_WND RT_LWIP_TCP_WND +#else +#define TCP_WND (TCP_MSS * 2) +#endif + +/* Maximum number of retransmissions of data segments. */ +#define TCP_MAXRTX 12 + +/* Maximum number of retransmissions of SYN segments. */ +#define TCP_SYNMAXRTX 4 + +/* tcpip thread options */ +#ifdef RT_LWIP_TCPTHREAD_PRIORITY +#define TCPIP_MBOX_SIZE RT_LWIP_TCPTHREAD_MBOX_SIZE +#define TCPIP_THREAD_PRIO RT_LWIP_TCPTHREAD_PRIORITY +#define TCPIP_THREAD_STACKSIZE RT_LWIP_TCPTHREAD_STACKSIZE +#else +#define TCPIP_MBOX_SIZE 8 +#define TCPIP_THREAD_PRIO 128 +#define TCPIP_THREAD_STACKSIZE 4096 +#endif +#define TCPIP_THREAD_NAME "tcpip" +#define DEFAULT_TCP_RECVMBOX_SIZE 10 + +/* ---------- ARP options ---------- */ +#define LWIP_ARP 1 +#define ARP_TABLE_SIZE 10 +#define ARP_QUEUEING 1 + +/* ---------- Checksum options ---------- */ +#ifdef RT_LWIP_USING_HW_CHECKSUM +#define CHECKSUM_GEN_IP 0 +#define CHECKSUM_GEN_UDP 0 +#define CHECKSUM_GEN_TCP 0 +#define CHECKSUM_GEN_ICMP 0 +#define CHECKSUM_CHECK_IP 0 +#define CHECKSUM_CHECK_UDP 0 +#define CHECKSUM_CHECK_TCP 0 +#define CHECKSUM_CHECK_ICMP 0 +#endif + +/* ---------- IP options ---------- */ +/* Define IP_FORWARD to 1 if you wish to have the ability to forward + IP packets across network interfaces. If you are going to run lwIP + on a device with only one network interface, define this to 0. */ +#define IP_FORWARD 0 + +/* IP reassembly and segmentation.These are orthogonal even + * if they both deal with IP fragments */ +#ifdef RT_LWIP_REASSEMBLY_FRAG +#define IP_REASSEMBLY 1 +#define IP_FRAG 1 +#define IP_REASS_MAX_PBUFS 10 +#define MEMP_NUM_REASSDATA 10 +#else +#define IP_REASSEMBLY 0 +#define IP_FRAG 0 +#endif + +/* ---------- ICMP options ---------- */ +#define ICMP_TTL 255 + +/* ---------- DHCP options ---------- */ +/* Define LWIP_DHCP to 1 if you want DHCP configuration of + interfaces. */ +#ifdef RT_LWIP_DHCP +#define LWIP_DHCP 1 +#else +#define LWIP_DHCP 0 +#endif + +/* 1 if you want to do an ARP check on the offered address + (recommended). */ +#define DHCP_DOES_ARP_CHECK (LWIP_DHCP) + +/* ---------- AUTOIP options ------- */ +#define LWIP_AUTOIP 0 +#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP) + +/* ---------- UDP options ---------- */ +#ifdef RT_LWIP_UDP +#define LWIP_UDP 1 +#else +#define LWIP_UDP 0 +#endif + +#define LWIP_UDPLITE 0 +#define UDP_TTL 255 +#define DEFAULT_UDP_RECVMBOX_SIZE 1 + +/* ---------- RAW options ---------- */ +#ifdef RT_LWIP_RAW +#define LWIP_RAW 1 +#else +#define LWIP_RAW 0 +#endif + +#define DEFAULT_RAW_RECVMBOX_SIZE 1 +#define DEFAULT_ACCEPTMBOX_SIZE 10 + +/* ---------- Statistics options ---------- */ +#ifdef RT_LWIP_STATS +#define LWIP_STATS 1 +#define LWIP_STATS_DISPLAY 1 +#else +#define LWIP_STATS 0 +#endif + +#if LWIP_STATS +#define LINK_STATS 1 +#define IP_STATS 1 +#define ICMP_STATS 1 +#define IGMP_STATS 1 +#define IPFRAG_STATS 1 +#define UDP_STATS 1 +#define TCP_STATS 1 +#define MEM_STATS 1 +#define MEMP_STATS 1 +#define PBUF_STATS 1 +#define SYS_STATS 1 +#define MIB2_STATS 1 +#endif /* LWIP_STATS */ + +/* ---------- PPP options ---------- */ +#ifdef RT_LWIP_PPP +#define PPP_SUPPORT 1 /* Set > 0 for PPP */ +#else +#define PPP_SUPPORT 0 /* Set > 0 for PPP */ +#endif + +#if PPP_SUPPORT +#define NUM_PPP 1 /* Max PPP sessions. */ + +/* Select modules to enable. Ideally these would be set in the makefile but + * we're limited by the command line length so you need to modify the settings + * in this file. + */ +#ifdef RT_LWIP_PPPOE +#define PPPOE_SUPPORT 1 +#else +#define PPPOE_SUPPORT 0 +#endif + +#ifdef RT_LWIP_PPPOS +#define PPPOS_SUPPORT 1 +#else +#define PPPOS_SUPPORT 0 +#endif + +#define PAP_SUPPORT 1 /* Set > 0 for PAP. */ +#define CHAP_SUPPORT 1 /* Set > 0 for CHAP. */ +#define MSCHAP_SUPPORT 0 /* Set > 0 for MSCHAP (NOT FUNCTIONAL!) */ +#define CBCP_SUPPORT 0 /* Set > 0 for CBCP (NOT FUNCTIONAL!) */ +#define CCP_SUPPORT 0 /* Set > 0 for CCP (NOT FUNCTIONAL!) */ +#define VJ_SUPPORT 1 /* Set > 0 for VJ header compression. */ +#define MD5_SUPPORT 1 /* Set > 0 for MD5 (see also CHAP) */ + +#endif /* PPP_SUPPORT */ + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 0 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 1 +#endif + +/** + * LWIP_NETIF_HOSTNAME==1: Support netif hostname + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 1 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 1 +#endif + +#ifdef LWIP_IGMP +#include +#define LWIP_RAND rand +#endif +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/* + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 1 +#endif + +/* + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifdef SAL_USING_POSIX +#define LWIP_COMPAT_SOCKETS 0 +#else +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#ifndef LWIP_SO_SNDTIMEO +#define LWIP_SO_SNDTIMEO 1 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 1 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 1 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT 8192 +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 0 +#endif + +/* + ------------------------------------ + ------- Applications options ------- + ------------------------------------ +*/ + +/** + * Max. length of TFTP filename + */ +#ifdef RT_LWIP_TFTP_MAX_FILENAME_LEN +#define TFTP_MAX_FILENAME_LEN RT_LWIP_TFTP_MAX_FILENAME_LEN +#elif defined(RT_DFS_ELM_MAX_LFN) +#define TFTP_MAX_FILENAME_LEN RT_DFS_ELM_MAX_LFN +#else +#define TFTP_MAX_FILENAME_LEN 64 +#endif + + +#endif /* __LWIPOPTS_H__ */ diff --git a/components/net/lwip-2.0.3/src/lwippools.h b/components/net/lwip-2.0.3/src/lwippools.h new file mode 100644 index 0000000000..6583863de3 --- /dev/null +++ b/components/net/lwip-2.0.3/src/lwippools.h @@ -0,0 +1,10 @@ +#if 1 + LWIP_MALLOC_MEMPOOL_START + LWIP_MALLOC_MEMPOOL((unsigned char)128, 256) + LWIP_MALLOC_MEMPOOL((unsigned char)128, 512) + LWIP_MALLOC_MEMPOOL((unsigned char)128, 1024) + LWIP_MALLOC_MEMPOOL((unsigned char)128, 1514) + LWIP_MALLOC_MEMPOOL((unsigned char)128, 1536) + LWIP_MALLOC_MEMPOOL((unsigned char)128, 4096) + LWIP_MALLOC_MEMPOOL_END +#endif diff --git a/components/net/lwip-2.0.3/src/netif/FILES b/components/net/lwip-2.0.3/src/netif/FILES new file mode 100644 index 0000000000..a3ff431d42 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/FILES @@ -0,0 +1,24 @@ +This directory contains generic network interface device drivers that +do not contain any hardware or architecture specific code. The files +are: + +ethernet.c + Shared code for Ethernet based interfaces. + +ethernetif.c + An example of how an Ethernet device driver could look. This + file can be used as a "skeleton" for developing new Ethernet + network device drivers. It uses the etharp.c ARP code. + +lowpan6.c + A 6LoWPAN implementation as a netif. + +slipif.c + A generic implementation of the SLIP (Serial Line IP) + protocol. It requires a sio (serial I/O) module to work. + +ppp/ Point-to-Point Protocol stack + The lwIP PPP support is based from pppd (http://ppp.samba.org) with + huge changes to match code size and memory requirements for embedded + devices. Please read /doc/ppp.txt and ppp/PPPD_FOLLOWUP for a detailed + explanation. diff --git a/components/net/lwip-2.0.3/src/netif/ethernet.c b/components/net/lwip-2.0.3/src/netif/ethernet.c new file mode 100644 index 0000000000..52ea4236d5 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ethernet.c @@ -0,0 +1,314 @@ +/** + * @file + * Ethernet common functions + * + * @defgroup ethernet Ethernet + * @ingroup callbackstyle_api + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET + +#include "netif/ethernet.h" +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/etharp.h" +#include "lwip/ip.h" +#include "lwip/snmp.h" + +#include + +#include "netif/ppp/ppp_opts.h" +#if PPPOE_SUPPORT +#include "netif/ppp/pppoe.h" +#endif /* PPPOE_SUPPORT */ + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; +const struct eth_addr ethzero = {{0,0,0,0,0,0}}; + +/** + * @ingroup lwip_nosys + * Process received ethernet frames. Using this function instead of directly + * calling ip_input and passing ARP frames through etharp in ethernetif_input, + * the ARP cache is protected from concurrent access.\n + * Don't call directly, pass to netif_add() and call netif->input(). + * + * @param p the received packet, p->payload pointing to the ethernet header + * @param netif the network interface on which the packet was received + * + * @see LWIP_HOOK_UNKNOWN_ETH_PROTOCOL + * @see ETHARP_SUPPORT_VLAN + * @see LWIP_HOOK_VLAN_CHECK + */ +err_t +ethernet_input(struct pbuf *p, struct netif *netif) +{ + struct eth_hdr* ethhdr; + u16_t type; +#if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6 + s16_t ip_hdr_offset = SIZEOF_ETH_HDR; +#endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ + + if (p->len <= SIZEOF_ETH_HDR) { + /* a packet with only an ethernet header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + MIB2_STATS_NETIF_INC(netif, ifinerrors); + goto free_and_return; + } + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = (struct eth_hdr *)p->payload; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, + ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", + (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], + (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], + (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], + (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], + lwip_htons(ethhdr->type))); + + type = ethhdr->type; +#if ETHARP_SUPPORT_VLAN + if (type == PP_HTONS(ETHTYPE_VLAN)) { + struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); + if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { + /* a packet with only an ethernet/vlan header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + MIB2_STATS_NETIF_INC(netif, ifinerrors); + goto free_and_return; + } +#if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ +#ifdef LWIP_HOOK_VLAN_CHECK + if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) { +#elif defined(ETHARP_VLAN_CHECK_FN) + if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { +#elif defined(ETHARP_VLAN_CHECK) + if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { +#endif + /* silently ignore this packet: not for our VLAN */ + pbuf_free(p); + return ERR_OK; + } +#endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ + type = vlan->tpid; + ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; + } +#endif /* ETHARP_SUPPORT_VLAN */ + +#if LWIP_ARP_FILTER_NETIF + netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type)); +#endif /* LWIP_ARP_FILTER_NETIF*/ + + if (ethhdr->dest.addr[0] & 1) { + /* this might be a multicast or broadcast packet */ + if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) { +#if LWIP_IPV4 + if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) && + (ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) { + /* mark the pbuf as link-layer multicast */ + p->flags |= PBUF_FLAG_LLMCAST; + } +#endif /* LWIP_IPV4 */ + } +#if LWIP_IPV6 + else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) && + (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { + /* mark the pbuf as link-layer multicast */ + p->flags |= PBUF_FLAG_LLMCAST; + } +#endif /* LWIP_IPV6 */ + else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { + /* mark the pbuf as link-layer broadcast */ + p->flags |= PBUF_FLAG_LLBCAST; + } + } + + switch (type) { +#if LWIP_IPV4 && LWIP_ARP + /* IP packet? */ + case PP_HTONS(ETHTYPE_IP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } + /* skip Ethernet header */ + if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("ethernet_input: IPv4 packet dropped, too short (%"S16_F"/%"S16_F")\n", + p->tot_len, ip_hdr_offset)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); + goto free_and_return; + } else { + /* pass to IP layer */ + ip4_input(p, netif); + } + break; + + case PP_HTONS(ETHTYPE_ARP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } + /* skip Ethernet header */ + if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("ethernet_input: ARP response packet dropped, too short (%"S16_F"/%"S16_F")\n", + p->tot_len, ip_hdr_offset)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); + ETHARP_STATS_INC(etharp.lenerr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } else { + /* pass p to ARP module */ + etharp_input(p, netif); + } + break; +#endif /* LWIP_IPV4 && LWIP_ARP */ +#if PPPOE_SUPPORT + case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ + pppoe_disc_input(netif, p); + break; + + case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ + pppoe_data_input(netif, p); + break; +#endif /* PPPOE_SUPPORT */ + +#if LWIP_IPV6 + case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ + /* skip Ethernet header */ + if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("ethernet_input: IPv6 packet dropped, too short (%"S16_F"/%"S16_F")\n", + p->tot_len, ip_hdr_offset)); + goto free_and_return; + } else { + /* pass to IPv6 layer */ + ip6_input(p, netif); + } + break; +#endif /* LWIP_IPV6 */ + + default: +#ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL + if(LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) { + break; + } +#endif + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + MIB2_STATS_NETIF_INC(netif, ifinunknownprotos); + goto free_and_return; + } + + /* This means the pbuf is freed or consumed, + so the caller doesn't have to free it again */ + return ERR_OK; + +free_and_return: + pbuf_free(p); + return ERR_OK; +} + +/** + * @ingroup ethernet + * Send an ethernet packet on the network using netif->linkoutput(). + * The ethernet header is filled in before sending. + * + * @see LWIP_HOOK_VLAN_SET + * + * @param netif the lwIP network interface on which to send the packet + * @param p the packet to send. pbuf layer must be @ref PBUF_LINK. + * @param src the source MAC address to be copied into the ethernet header + * @param dst the destination MAC address to be copied into the ethernet header + * @param eth_type ethernet type (@ref eth_type) + * @return ERR_OK if the packet was sent, any other err_t on failure + */ +err_t +ethernet_output(struct netif* netif, struct pbuf* p, + const struct eth_addr* src, const struct eth_addr* dst, + u16_t eth_type) +{ + struct eth_hdr* ethhdr; + u16_t eth_type_be = lwip_htons(eth_type); + +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + s32_t vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type); + if (vlan_prio_vid >= 0) { + struct eth_vlan_hdr* vlanhdr; + + LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF); + + if (pbuf_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) { + goto pbuf_header_failed; + } + vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)p->payload) + SIZEOF_ETH_HDR); + vlanhdr->tpid = eth_type_be; + vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid); + + eth_type_be = PP_HTONS(ETHTYPE_VLAN); + } else +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + { + if (pbuf_header(p, SIZEOF_ETH_HDR) != 0) { + goto pbuf_header_failed; + } + } + + ethhdr = (struct eth_hdr*)p->payload; + ethhdr->type = eth_type_be; + ETHADDR32_COPY(ðhdr->dest, dst); + ETHADDR16_COPY(ðhdr->src, src); + + LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!", + (netif->hwaddr_len == ETH_HWADDR_LEN)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, + ("ethernet_output: sending packet %p\n", (void *)p)); + + /* send the packet */ + return netif->linkoutput(netif, p); + +pbuf_header_failed: + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("ethernet_output: could not allocate room for header.\n")); + LINK_STATS_INC(link.lenerr); + return ERR_BUF; +} + +#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/components/net/lwip-2.0.3/src/netif/ethernetif.c b/components/net/lwip-2.0.3/src/netif/ethernetif.c new file mode 100644 index 0000000000..1c0f3ca9b2 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ethernetif.c @@ -0,0 +1,1022 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * COPYRIGHT (C) 2006-2018, RT-Thread Development Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * Change Logs: + * Date Author Notes + * 2010-07-07 Bernard fix send mail to mailbox issue. + * 2011-07-30 mbbill port lwIP 1.4.0 to RT-Thread + * 2012-04-10 Bernard add more compatible with RT-Thread. + * 2012-11-12 Bernard The network interface can be initialized + * after lwIP initialization. + * 2013-02-28 aozima fixed list_tcps bug: ipaddr_ntoa isn't reentrant. + * 2016-08-18 Bernard port to lwIP 2.0.0 + * 2020-08-10 lizhirui fixed some problems when this is running on 64-bit cpu + */ + +#include "lwip/opt.h" + +#include "lwip/opt.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/stats.h" +#include "lwip/tcpip.h" +#include "lwip/dhcp.h" +#include "lwip/netifapi.h" + +#include "netif/etharp.h" +#include "netif/ethernetif.h" + +#include "lwip/inet.h" + +#if LWIP_IPV6 +#include "lwip/ethip6.h" +#endif /* LWIP_IPV6 */ + +#define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL) +#define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL) + +#ifndef RT_LWIP_ETHTHREAD_PRIORITY +#define RT_ETHERNETIF_THREAD_PREORITY 0x90 +#else +#define RT_ETHERNETIF_THREAD_PREORITY RT_LWIP_ETHTHREAD_PRIORITY +#endif + +#ifndef LWIP_NO_TX_THREAD +/** + * Tx message structure for Ethernet interface + */ +struct eth_tx_msg +{ + struct netif *netif; + struct pbuf *buf; +}; + +static struct rt_mailbox eth_tx_thread_mb; +static struct rt_thread eth_tx_thread; +#ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE +static char eth_tx_thread_mb_pool[32 * sizeof(rt_ubase_t)]; +static char eth_tx_thread_stack[512]; +#else +static char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * sizeof(rt_ubase_t)]; +static char eth_tx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; +#endif +#endif + +#ifndef LWIP_NO_RX_THREAD +static struct rt_mailbox eth_rx_thread_mb; +static struct rt_thread eth_rx_thread; +#ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE +static char eth_rx_thread_mb_pool[48 * sizeof(rt_ubase_t)]; +static char eth_rx_thread_stack[1024]; +#else +static char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * sizeof(rt_ubase_t)]; +static char eth_rx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; +#endif +#endif + +#ifdef RT_USING_NETDEV + +#include "lwip/ip.h" +#include "lwip/init.h" +#include "lwip/netdb.h" +#include + +static int lwip_netdev_set_up(struct netdev *netif) +{ + netif_set_up((struct netif *)netif->user_data); + return ERR_OK; +} + +static int lwip_netdev_set_down(struct netdev *netif) +{ + netif_set_down((struct netif *)netif->user_data); + return ERR_OK; +} + +static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, ip_addr_t *netmask, ip_addr_t *gw) +{ + if (ip_addr && netmask && gw) + { + netif_set_addr((struct netif *)netif->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); + } + else + { + if (ip_addr) + { + netif_set_ipaddr((struct netif *)netif->user_data, ip_2_ip4(ip_addr)); + } + + if (netmask) + { + netif_set_netmask((struct netif *)netif->user_data, ip_2_ip4(netmask)); + } + + if (gw) + { + netif_set_gw((struct netif *)netif->user_data, ip_2_ip4(gw)); + } + } + + return ERR_OK; +} + +#ifdef RT_LWIP_DNS +static int lwip_netdev_set_dns_server(struct netdev *netif, uint8_t dns_num, ip_addr_t *dns_server) +{ + extern void dns_setserver(uint8_t dns_num, const ip_addr_t *dns_server); + dns_setserver(dns_num, dns_server); + return ERR_OK; +} +#endif /* RT_LWIP_DNS */ + +#ifdef RT_LWIP_DHCP +static int lwip_netdev_set_dhcp(struct netdev *netif, rt_bool_t is_enabled) +{ + netdev_low_level_set_dhcp_status(netif, is_enabled); + + /*add dhcp start or stop must call dhcp_start and dhcp_stop function*/ + if(is_enabled == RT_TRUE) + { + dhcp_start((struct netif *)netif->user_data); + } + else + { + dhcp_stop((struct netif *)netif->user_data); + } + return ERR_OK; +} +#endif /* RT_LWIP_DHCP */ + +#ifdef RT_USING_FINSH +#ifdef RT_LWIP_USING_PING +extern int lwip_ping_recv(int s, int *ttl); +extern err_t lwip_ping_send(int s, ip_addr_t *addr, int size); + +int lwip_netdev_ping(struct netdev *netif, const char *host, size_t data_len, + uint32_t timeout, struct netdev_ping_resp *ping_resp) +{ + int s, ttl, recv_len, result = 0; + int elapsed_time; + rt_tick_t recv_start_tick; +#if LWIP_VERSION_MAJOR >= 2U + struct timeval recv_timeout = { timeout / RT_TICK_PER_SECOND, timeout % RT_TICK_PER_SECOND }; +#else + int recv_timeout = timeout * 1000UL / RT_TICK_PER_SECOND; +#endif + ip_addr_t target_addr; + struct addrinfo hint, *res = RT_NULL; + struct sockaddr_in *h = RT_NULL; + struct in_addr ina; + + RT_ASSERT(netif); + RT_ASSERT(host); + RT_ASSERT(ping_resp); + + rt_memset(&hint, 0x00, sizeof(hint)); + /* convert URL to IP */ + if (lwip_getaddrinfo(host, RT_NULL, &hint, &res) != 0) + { + return -RT_ERROR; + } + rt_memcpy(&h, &res->ai_addr, sizeof(struct sockaddr_in *)); + rt_memcpy(&ina, &h->sin_addr, sizeof(ina)); + lwip_freeaddrinfo(res); + if (inet_aton(inet_ntoa(ina), &target_addr) == 0) + { + return -RT_ERROR; + } + rt_memcpy(&(ping_resp->ip_addr), &target_addr, sizeof(ip_addr_t)); + + /* new a socket */ + if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) + { + return -RT_ERROR; + } + + lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &recv_timeout, sizeof(recv_timeout)); + + if (lwip_ping_send(s, &target_addr, data_len) == ERR_OK) + { + recv_start_tick = rt_tick_get(); + if ((recv_len = lwip_ping_recv(s, &ttl)) >= 0) + { + elapsed_time = (rt_tick_get() - recv_start_tick) * 1000UL / RT_TICK_PER_SECOND; + ping_resp->data_len = recv_len; + ping_resp->ttl = ttl; + ping_resp->ticks = elapsed_time; + } + else + { + result = -RT_ETIMEOUT; + goto __exit; + } + } + else + { + result = -RT_ETIMEOUT; + goto __exit; + } + +__exit: + lwip_close(s); + + return result; +} +#endif /* RT_LWIP_USING_PING */ + +#if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP) +void lwip_netdev_netstat(struct netdev *netif) +{ + extern void list_tcps(void); + extern void list_udps(void); + +#ifdef RT_LWIP_TCP + list_tcps(); +#endif +#ifdef RT_LWIP_UDP + list_udps(); +#endif +} +#endif /* RT_LWIP_TCP || RT_LWIP_UDP */ +#endif /* RT_USING_FINSH */ + +static int lwip_netdev_set_default(struct netdev *netif) +{ + netif_set_default((struct netif *)netif->user_data); + return ERR_OK; +} + +const struct netdev_ops lwip_netdev_ops = +{ + lwip_netdev_set_up, + lwip_netdev_set_down, + + lwip_netdev_set_addr_info, +#ifdef RT_LWIP_DNS + lwip_netdev_set_dns_server, +#else + NULL, +#endif /* RT_LWIP_DNS */ + +#ifdef RT_LWIP_DHCP + lwip_netdev_set_dhcp, +#else + NULL, +#endif /* RT_LWIP_DHCP */ + +#ifdef RT_USING_FINSH +#ifdef RT_LWIP_USING_PING + lwip_netdev_ping, +#else + NULL, +#endif /* RT_LWIP_USING_PING */ + +#if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP) + lwip_netdev_netstat, +#endif /* RT_LWIP_TCP || RT_LWIP_UDP */ +#endif /* RT_USING_FINSH */ + + lwip_netdev_set_default, +}; + +static int netdev_add(struct netif *lwip_netif) +{ +#define LWIP_NETIF_NAME_LEN 2 + int result = 0; + struct netdev *netdev = RT_NULL; + char name[LWIP_NETIF_NAME_LEN + 1] = {0}; + + RT_ASSERT(lwip_netif); + + netdev = (struct netdev *)rt_calloc(1, sizeof(struct netdev)); + if (netdev == RT_NULL) + { + return -ERR_IF; + } + +#ifdef SAL_USING_LWIP + extern int sal_lwip_netdev_set_pf_info(struct netdev *netdev); + /* set the lwIP network interface device protocol family information */ + sal_lwip_netdev_set_pf_info(netdev); +#endif /* SAL_USING_LWIP */ + + rt_strncpy(name, lwip_netif->name, LWIP_NETIF_NAME_LEN); + result = netdev_register(netdev, name, (void *)lwip_netif); + + /* Update netdev info after registered */ + netdev->flags = lwip_netif->flags; + netdev->mtu = lwip_netif->mtu; + netdev->ops = &lwip_netdev_ops; + netdev->hwaddr_len = lwip_netif->hwaddr_len; + rt_memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); + netdev->ip_addr = lwip_netif->ip_addr; + netdev->gw = lwip_netif->gw; + netdev->netmask = lwip_netif->netmask; + +#ifdef RT_LWIP_DHCP + netdev_low_level_set_dhcp_status(netdev, RT_TRUE); +#endif + + return result; +} + +static void netdev_del(struct netif *lwip_netif) +{ + char name[LWIP_NETIF_NAME_LEN + 1]; + struct netdev *netdev; + + RT_ASSERT(lwip_netif); + + rt_strncpy(name, lwip_netif->name, LWIP_NETIF_NAME_LEN); + netdev = netdev_get_by_name(name); + netdev_unregister(netdev); + rt_free(netdev); +} + +/* synchronize lwIP network interface device and network interface device flags */ +static int netdev_flags_sync(struct netif *lwip_netif) +{ + struct netdev *netdev = NULL; + + RT_ASSERT(lwip_netif); + + netdev = netdev_get_by_name(lwip_netif->name); + if (netdev == RT_NULL) + { + return -ERR_IF; + } + + netdev->flags |= lwip_netif->flags; + + return ERR_OK; +} +#endif /* RT_USING_NETDEV */ + +static err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p) +{ +#ifndef LWIP_NO_TX_THREAD + struct eth_tx_msg msg; + struct eth_device* enetif; + + RT_ASSERT(netif != RT_NULL); + enetif = (struct eth_device*)netif->state; + + /* send a message to eth tx thread */ + msg.netif = netif; + msg.buf = p; + if (rt_mb_send(ð_tx_thread_mb, (rt_ubase_t) &msg) == RT_EOK) + { + /* waiting for ack */ + rt_sem_take(&(enetif->tx_ack), RT_WAITING_FOREVER); + } +#else + struct eth_device* enetif; + + RT_ASSERT(netif != RT_NULL); + enetif = (struct eth_device*)netif->state; + + if (enetif->eth_tx(&(enetif->parent), p) != RT_EOK) + { + return ERR_IF; + } +#endif + return ERR_OK; +} + +static err_t eth_netif_device_init(struct netif *netif) +{ + struct eth_device *ethif; + +#ifdef RT_USING_NETDEV + /* network interface device register */ + netdev_add(netif); +#endif /* RT_USING_NETDEV */ + + ethif = (struct eth_device*)netif->state; + if (ethif != RT_NULL) + { + rt_device_t device; + + /* get device object */ + device = (rt_device_t) ethif; + if (rt_device_init(device) != RT_EOK) + { + return ERR_IF; + } + + /* copy device flags to netif flags */ + netif->flags = (ethif->flags & 0xff); + +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; + netif->ip6_autoconfig_enabled = 1; + netif_create_ip6_linklocal_address(netif, 1); + +#if LWIP_IPV6_MLD + netif->flags |= NETIF_FLAG_MLD6; + + /* + * For hardware/netifs that implement MAC filtering. + * All-nodes link-local is handled by default, so we must let the hardware know + * to allow multicast packets in. + * Should set mld_mac_filter previously. */ + if (netif->mld_mac_filter != NULL) + { + ip6_addr_t ip6_allnodes_ll; + ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); + netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); + } +#endif /* LWIP_IPV6_MLD */ + +#endif /* LWIP_IPV6 */ + + /* set default netif */ + if (netif_default == RT_NULL) + netif_set_default(ethif->netif); + +#if LWIP_DHCP + /* set interface up */ + netif_set_up(ethif->netif); + /* if this interface uses DHCP, start the DHCP client */ + dhcp_start(ethif->netif); +#else + /* set interface up */ + netif_set_up(ethif->netif); +#endif + + if (ethif->flags & ETHIF_LINK_PHYUP) + { + /* set link_up for this netif */ + netif_set_link_up(ethif->netif); + } + + return ERR_OK; + } + + return ERR_IF; +} + +/* Keep old drivers compatible in RT-Thread */ +rt_err_t eth_device_init_with_flag(struct eth_device *dev, const char *name, rt_uint16_t flags) +{ + struct netif* netif; +#if LWIP_NETIF_HOSTNAME +#define LWIP_HOSTNAME_LEN 16 + char *hostname = RT_NULL; + netif = (struct netif*) rt_calloc (1, sizeof(struct netif) + LWIP_HOSTNAME_LEN); +#else + netif = (struct netif*) rt_calloc (1, sizeof(struct netif)); +#endif + if (netif == RT_NULL) + { + rt_kprintf("malloc netif failed\n"); + return -RT_ERROR; + } + + /* set netif */ + dev->netif = netif; + /* device flags, which will be set to netif flags when initializing */ + dev->flags = flags; + /* link changed status of device */ + dev->link_changed = 0x00; + /* avoid send the same mail to mailbox */ + dev->rx_notice = 0x00; + dev->parent.type = RT_Device_Class_NetIf; + /* register to RT-Thread device manager */ + rt_device_register(&(dev->parent), name, RT_DEVICE_FLAG_RDWR); + rt_sem_init(&(dev->tx_ack), name, 0, RT_IPC_FLAG_FIFO); + + /* set name */ + netif->name[0] = name[0]; + netif->name[1] = name[1]; + + /* set hw address to 6 */ + netif->hwaddr_len = 6; + /* maximum transfer unit */ + netif->mtu = ETHERNET_MTU; + + /* get hardware MAC address */ + rt_device_control(&(dev->parent), NIOCTL_GADDR, netif->hwaddr); + + /* set output */ + netif->output = etharp_output; + netif->linkoutput = ethernetif_linkoutput; + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + hostname = (char *)netif + sizeof(struct netif); + rt_sprintf(hostname, "rtthread_%02x%02x", name[0], name[1]); + netif->hostname = hostname; +#endif /* LWIP_NETIF_HOSTNAME */ + + /* if tcp thread has been started up, we add this netif to the system */ + if (rt_thread_find("tcpip") != RT_NULL) + { + ip4_addr_t ipaddr, netmask, gw; + +#if !LWIP_DHCP + ipaddr.addr = inet_addr(RT_LWIP_IPADDR); + gw.addr = inet_addr(RT_LWIP_GWADDR); + netmask.addr = inet_addr(RT_LWIP_MSKADDR); +#else + IP4_ADDR(&ipaddr, 0, 0, 0, 0); + IP4_ADDR(&gw, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); +#endif + netifapi_netif_add(netif, &ipaddr, &netmask, &gw, dev, eth_netif_device_init, tcpip_input); + } + +#ifdef RT_USING_NETDEV + /* network interface device flags synchronize */ + netdev_flags_sync(netif); +#endif /* RT_USING_NETDEV */ + + return RT_EOK; +} + +rt_err_t eth_device_init(struct eth_device * dev, const char *name) +{ + rt_uint16_t flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + +#if LWIP_IGMP + /* IGMP support */ + flags |= NETIF_FLAG_IGMP; +#endif + + return eth_device_init_with_flag(dev, name, flags); +} + +void eth_device_deinit(struct eth_device *dev) +{ + struct netif* netif = dev->netif; + +#if LWIP_DHCP + dhcp_stop(netif); + dhcp_cleanup(netif); +#endif + netif_set_down(netif); + netif_remove(netif); +#ifdef RT_USING_NETDEV + netdev_del(netif); +#endif + rt_device_close(&(dev->parent)); + rt_device_unregister(&(dev->parent)); + rt_sem_detach(&(dev->tx_ack)); + rt_free(netif); +} + +#ifndef LWIP_NO_RX_THREAD +rt_err_t eth_device_ready(struct eth_device* dev) +{ + if (dev->netif) + { + if(dev->rx_notice == RT_FALSE) + { + dev->rx_notice = RT_TRUE; + return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev); + } + else + return RT_EOK; + /* post message to Ethernet thread */ + } + else + return -RT_ERROR; /* netif is not initialized yet, just return. */ +} + +rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up) +{ + rt_uint32_t level; + + RT_ASSERT(dev != RT_NULL); + + level = rt_hw_interrupt_disable(); + dev->link_changed = 0x01; + if (up == RT_TRUE) + dev->link_status = 0x01; + else + dev->link_status = 0x00; + rt_hw_interrupt_enable(level); + + /* post message to ethernet thread */ + return rt_mb_send(ð_rx_thread_mb, (rt_ubase_t)dev); +} +#else +/* NOTE: please not use it in interrupt when no RxThread exist */ +rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up) +{ + if (up == RT_TRUE) + netifapi_netif_set_link_up(dev->netif); + else + netifapi_netif_set_link_down(dev->netif); + + return RT_EOK; +} +#endif + +#ifndef LWIP_NO_TX_THREAD +/* Ethernet Tx Thread */ +static void eth_tx_thread_entry(void* parameter) +{ + struct eth_tx_msg* msg; + + while (1) + { + if (rt_mb_recv(ð_tx_thread_mb, (rt_ubase_t *)&msg, RT_WAITING_FOREVER) == RT_EOK) + { + struct eth_device* enetif; + + RT_ASSERT(msg->netif != RT_NULL); + RT_ASSERT(msg->buf != RT_NULL); + + enetif = (struct eth_device*)msg->netif->state; + if (enetif != RT_NULL) + { + /* call driver's interface */ + if (enetif->eth_tx(&(enetif->parent), msg->buf) != RT_EOK) + { + /* transmit eth packet failed */ + } + } + + /* send ACK */ + rt_sem_release(&(enetif->tx_ack)); + } + } +} +#endif + +#ifndef LWIP_NO_RX_THREAD +/* Ethernet Rx Thread */ +static void eth_rx_thread_entry(void* parameter) +{ + struct eth_device* device; + + while (1) + { + if (rt_mb_recv(ð_rx_thread_mb, (rt_ubase_t *)&device, RT_WAITING_FOREVER) == RT_EOK) + { + rt_base_t level; + struct pbuf *p; + + /* check link status */ + if (device->link_changed) + { + int status; + rt_uint32_t level; + + level = rt_hw_interrupt_disable(); + status = device->link_status; + device->link_changed = 0x00; + rt_hw_interrupt_enable(level); + + if (status) + netifapi_netif_set_link_up(device->netif); + else + netifapi_netif_set_link_down(device->netif); + } + + level = rt_hw_interrupt_disable(); + /* 'rx_notice' will be modify in the interrupt or here */ + device->rx_notice = RT_FALSE; + rt_hw_interrupt_enable(level); + + /* receive all of buffer */ + while(1) + { + if(device->eth_rx == RT_NULL) break; + + p = device->eth_rx(&(device->parent)); + if (p != RT_NULL) + { + /* notify to upper layer */ + if( device->netif->input(p, device->netif) != ERR_OK ) + { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Input error\n")); + pbuf_free(p); + p = NULL; + } + } + else break; + } + } + else + { + LWIP_ASSERT("Should not happen!\n",0); + } + } +} +#endif + +/* this function does not need, + * use eth_system_device_init_private() + * call by lwip_system_init(). + */ +int eth_system_device_init(void) +{ + return 0; +} + +int eth_system_device_init_private(void) +{ + rt_err_t result = RT_EOK; + + /* initialize Rx thread. */ +#ifndef LWIP_NO_RX_THREAD + /* initialize mailbox and create Ethernet Rx thread */ + result = rt_mb_init(ð_rx_thread_mb, "erxmb", + ð_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/sizeof(rt_ubase_t), + RT_IPC_FLAG_FIFO); + RT_ASSERT(result == RT_EOK); + + result = rt_thread_init(ð_rx_thread, "erx", eth_rx_thread_entry, RT_NULL, + ð_rx_thread_stack[0], sizeof(eth_rx_thread_stack), + RT_ETHERNETIF_THREAD_PREORITY, 16); + RT_ASSERT(result == RT_EOK); + result = rt_thread_startup(ð_rx_thread); + RT_ASSERT(result == RT_EOK); +#endif + + /* initialize Tx thread */ +#ifndef LWIP_NO_TX_THREAD + /* initialize mailbox and create Ethernet Tx thread */ + result = rt_mb_init(ð_tx_thread_mb, "etxmb", + ð_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/sizeof(rt_ubase_t), + RT_IPC_FLAG_FIFO); + RT_ASSERT(result == RT_EOK); + + result = rt_thread_init(ð_tx_thread, "etx", eth_tx_thread_entry, RT_NULL, + ð_tx_thread_stack[0], sizeof(eth_tx_thread_stack), + RT_ETHERNETIF_THREAD_PREORITY, 16); + RT_ASSERT(result == RT_EOK); + + result = rt_thread_startup(ð_tx_thread); + RT_ASSERT(result == RT_EOK); +#endif + + return (int)result; +} + +void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr) +{ + ip4_addr_t *ip; + ip4_addr_t addr; + struct netif * netif = netif_list; + + if(strlen(netif_name) > sizeof(netif->name)) + { + rt_kprintf("network interface name too long!\r\n"); + return; + } + + while(netif != RT_NULL) + { + if(strncmp(netif_name, netif->name, sizeof(netif->name)) == 0) + break; + + netif = netif->next; + if( netif == RT_NULL ) + { + rt_kprintf("network interface: %s not found!\r\n", netif_name); + return; + } + } + + ip = (ip4_addr_t *)&addr; + + /* set ip address */ + if ((ip_addr != RT_NULL) && ip4addr_aton(ip_addr, &addr)) + { + netif_set_ipaddr(netif, ip); + } + + /* set gateway address */ + if ((gw_addr != RT_NULL) && ip4addr_aton(gw_addr, &addr)) + { + netif_set_gw(netif, ip); + } + + /* set netmask address */ + if ((nm_addr != RT_NULL) && ip4addr_aton(nm_addr, &addr)) + { + netif_set_netmask(netif, ip); + } +} + +#ifdef RT_USING_FINSH +#include +FINSH_FUNCTION_EXPORT(set_if, set network interface address); + +#if LWIP_DNS +#include +void set_dns(uint8_t dns_num, char* dns_server) +{ + ip_addr_t addr; + + if ((dns_server != RT_NULL) && ipaddr_aton(dns_server, &addr)) + { + dns_setserver(dns_num, &addr); + } +} +FINSH_FUNCTION_EXPORT(set_dns, set DNS server address); +#endif + +void list_if(void) +{ + rt_ubase_t index; + struct netif * netif; + + rt_enter_critical(); + + netif = netif_list; + + while( netif != RT_NULL ) + { + rt_kprintf("network interface: %c%c%s\n", + netif->name[0], + netif->name[1], + (netif == netif_default)?" (Default)":""); + rt_kprintf("MTU: %d\n", netif->mtu); + rt_kprintf("MAC: "); + for (index = 0; index < netif->hwaddr_len; index ++) + rt_kprintf("%02x ", netif->hwaddr[index]); + rt_kprintf("\nFLAGS:"); + if (netif->flags & NETIF_FLAG_UP) rt_kprintf(" UP"); + else rt_kprintf(" DOWN"); + if (netif->flags & NETIF_FLAG_LINK_UP) rt_kprintf(" LINK_UP"); + else rt_kprintf(" LINK_DOWN"); + if (netif->flags & NETIF_FLAG_ETHARP) rt_kprintf(" ETHARP"); + if (netif->flags & NETIF_FLAG_BROADCAST) rt_kprintf(" BROADCAST"); + if (netif->flags & NETIF_FLAG_IGMP) rt_kprintf(" IGMP"); + rt_kprintf("\n"); + rt_kprintf("ip address: %s\n", ipaddr_ntoa(&(netif->ip_addr))); + rt_kprintf("gw address: %s\n", ipaddr_ntoa(&(netif->gw))); + rt_kprintf("net mask : %s\n", ipaddr_ntoa(&(netif->netmask))); +#if LWIP_IPV6 + { + ip6_addr_t *addr; + int addr_state; + int i; + + addr = (ip6_addr_t *)&netif->ip6_addr[0]; + addr_state = netif->ip6_addr_state[0]; + + rt_kprintf("\nipv6 link-local: %s state:%02X %s\n", ip6addr_ntoa(addr), + addr_state, ip6_addr_isvalid(addr_state)?"VALID":"INVALID"); + + for(i=1; iip6_addr[i]; + addr_state = netif->ip6_addr_state[i]; + + rt_kprintf("ipv6[%d] address: %s state:%02X %s\n", i, ip6addr_ntoa(addr), + addr_state, ip6_addr_isvalid(addr_state)?"VALID":"INVALID"); + } + + } + rt_kprintf("\r\n"); +#endif /* LWIP_IPV6 */ + netif = netif->next; + } + +#if LWIP_DNS + { + const ip_addr_t *ip_addr; + + for(index=0; index +#include + +void list_tcps(void) +{ + rt_uint32_t num = 0; + struct tcp_pcb *pcb; + char local_ip_str[16]; + char remote_ip_str[16]; + + extern struct tcp_pcb *tcp_active_pcbs; + extern union tcp_listen_pcbs_t tcp_listen_pcbs; + extern struct tcp_pcb *tcp_tw_pcbs; + + rt_enter_critical(); + rt_kprintf("Active PCB states:\n"); + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) + { + strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); + strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); + + rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ", + num++, + local_ip_str, + pcb->local_port, + remote_ip_str, + pcb->remote_port, + pcb->snd_nxt, + pcb->rcv_nxt); + rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); + } + + rt_kprintf("Listen PCB states:\n"); + num = 0; + for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) + { + rt_kprintf("#%d local port %d ", num++, pcb->local_port); + rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); + } + + rt_kprintf("TIME-WAIT PCB states:\n"); + num = 0; + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) + { + strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); + strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); + + rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ", + num++, + local_ip_str, + pcb->local_port, + remote_ip_str, + pcb->remote_port, + pcb->snd_nxt, + pcb->rcv_nxt); + rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); + } + rt_exit_critical(); +} +FINSH_FUNCTION_EXPORT(list_tcps, list all of tcp connections); +#endif /* LWIP_TCP */ + +#if LWIP_UDP +#include "lwip/udp.h" +void list_udps(void) +{ + struct udp_pcb *pcb; + rt_uint32_t num = 0; + char local_ip_str[16]; + char remote_ip_str[16]; + + rt_enter_critical(); + rt_kprintf("Active UDP PCB states:\n"); + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) + { + strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); + strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); + + rt_kprintf("#%d %d %s:%d <==> %s:%d \n", + num, (int)pcb->flags, + local_ip_str, + pcb->local_port, + remote_ip_str, + pcb->remote_port); + + num++; + } + rt_exit_critical(); +} +FINSH_FUNCTION_EXPORT(list_udps, list all of udp connections); +#endif /* LWIP_UDP */ + +#endif diff --git a/components/net/lwip-2.0.3/src/netif/lowpan6.c b/components/net/lwip-2.0.3/src/netif/lowpan6.c new file mode 100644 index 0000000000..9a84cbccc7 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/lowpan6.c @@ -0,0 +1,1193 @@ +/** + * @file + * + * 6LowPAN output for IPv6. Uses ND tables for link-layer addressing. Fragments packets to 6LowPAN units. + */ + +/* + * Copyright (c) 2015 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +/** + * @defgroup sixlowpan 6LowPAN netif + * @ingroup addons + * 6LowPAN netif implementation + */ + +#include "netif/lowpan6.h" + +#if LWIP_IPV6 && LWIP_6LOWPAN + +#include "lwip/ip.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/nd6.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/tcpip.h" +#include "lwip/snmp.h" + +#include + +struct ieee_802154_addr { + u8_t addr_len; + u8_t addr[8]; +}; + +/** This is a helper struct. + */ +struct lowpan6_reass_helper { + struct pbuf *pbuf; + struct lowpan6_reass_helper *next_packet; + u8_t timer; + struct ieee_802154_addr sender_addr; + u16_t datagram_size; + u16_t datagram_tag; +}; + +static struct lowpan6_reass_helper * reass_list; + +#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 +static ip6_addr_t lowpan6_context[LWIP_6LOWPAN_NUM_CONTEXTS]; +#endif + +static u16_t ieee_802154_pan_id; + +static const struct ieee_802154_addr ieee_802154_broadcast = {2, {0xff, 0xff}}; + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS +static struct ieee_802154_addr short_mac_addr = {2, {0,0}}; +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + +static err_t dequeue_datagram(struct lowpan6_reass_helper *lrh); + +/** + * Periodic timer for 6LowPAN functions: + * + * - Remove incomplete/old packets + */ +void +lowpan6_tmr(void) +{ + struct lowpan6_reass_helper *lrh, *lrh_temp; + + lrh = reass_list; + while (lrh != NULL) { + lrh_temp = lrh->next_packet; + if ((--lrh->timer) == 0) { + dequeue_datagram(lrh); + pbuf_free(lrh->pbuf); + mem_free(lrh); + } + lrh = lrh_temp; + } +} + +/** + * Removes a datagram from the reassembly queue. + **/ +static err_t +dequeue_datagram(struct lowpan6_reass_helper *lrh) +{ + struct lowpan6_reass_helper *lrh_temp; + + if (reass_list == lrh) { + reass_list = reass_list->next_packet; + } else { + lrh_temp = reass_list; + while (lrh_temp != NULL) { + if (lrh_temp->next_packet == lrh) { + lrh_temp->next_packet = lrh->next_packet; + break; + } + lrh_temp = lrh_temp->next_packet; + } + } + + return ERR_OK; +} + +static s8_t +lowpan6_context_lookup(const ip6_addr_t *ip6addr) +{ + s8_t i; + + for (i = 0; i < LWIP_6LOWPAN_NUM_CONTEXTS; i++) { + if (ip6_addr_netcmp(&lowpan6_context[i], ip6addr)) { + return i; + } + } + + return -1; +} + +/* Determine compression mode for unicast address. */ +static s8_t +lowpan6_get_address_mode(const ip6_addr_t *ip6addr, const struct ieee_802154_addr *mac_addr) +{ + if (mac_addr->addr_len == 2) { + if ((ip6addr->addr[2] == (u32_t)PP_HTONL(0x000000ff)) && + ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000))) { + if ((ip6addr->addr[3] & PP_HTONL(0x0000ffff)) == lwip_ntohl((mac_addr->addr[0] << 8) | mac_addr->addr[1])) { + return 3; + } + } + } else if (mac_addr->addr_len == 8) { + if ((ip6addr->addr[2] == lwip_ntohl(((mac_addr->addr[0] ^ 2) << 24) | (mac_addr->addr[1] << 16) | mac_addr->addr[2] << 8 | mac_addr->addr[3])) && + (ip6addr->addr[3] == lwip_ntohl((mac_addr->addr[4] << 24) | (mac_addr->addr[5] << 16) | mac_addr->addr[6] << 8 | mac_addr->addr[7]))) { + return 3; + } + } + + if ((ip6addr->addr[2] == PP_HTONL(0x000000ffUL)) && + ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000UL))) { + return 2; + } + + return 1; +} + +/* Determine compression mode for multicast address. */ +static s8_t +lowpan6_get_address_mode_mc(const ip6_addr_t *ip6addr) +{ + if ((ip6addr->addr[0] == PP_HTONL(0xff020000)) && + (ip6addr->addr[1] == 0) && + (ip6addr->addr[2] == 0) && + ((ip6addr->addr[3] & PP_HTONL(0xffffff00)) == 0)) { + return 3; + } else if (((ip6addr->addr[0] & PP_HTONL(0xff00ffff)) == PP_HTONL(0xff000000)) && + (ip6addr->addr[1] == 0)) { + if ((ip6addr->addr[2] == 0) && + ((ip6addr->addr[3] & PP_HTONL(0xff000000)) == 0)) { + return 2; + } else if ((ip6addr->addr[2] & PP_HTONL(0xffffff00)) == 0) { + return 1; + } + } + + return 0; +} + +/* + * Encapsulates data into IEEE 802.15.4 frames. + * Fragments an IPv6 datagram into 6LowPAN units, which fit into IEEE 802.15.4 frames. + * If configured, will compress IPv6 and or UDP headers. + * */ +static err_t +lowpan6_frag(struct netif *netif, struct pbuf *p, const struct ieee_802154_addr *src, const struct ieee_802154_addr *dst) +{ + struct pbuf * p_frag; + u16_t frag_len, remaining_len; + u8_t * buffer; + u8_t ieee_header_len; + u8_t lowpan6_header_len; + s8_t i; + static u8_t frame_seq_num; + static u16_t datagram_tag; + u16_t datagram_offset; + err_t err = ERR_IF; + + /* We'll use a dedicated pbuf for building 6LowPAN fragments. */ + p_frag = pbuf_alloc(PBUF_RAW, 127, PBUF_RAM); + if (p_frag == NULL) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + return ERR_MEM; + } + + /* Write IEEE 802.15.4 header. */ + buffer = (u8_t*)p_frag->payload; + ieee_header_len = 0; + if (dst == &ieee_802154_broadcast) { + buffer[ieee_header_len++] = 0x01; /* data packet, no ack required. */ + } else { + buffer[ieee_header_len++] = 0x21; /* data packet, ack required. */ + } + buffer[ieee_header_len] = (0x00 << 4); /* 2003 frame version */ + buffer[ieee_header_len] |= (dst->addr_len == 2) ? (0x02 << 2) : (0x03 << 2); /* destination addressing mode */ + buffer[ieee_header_len] |= (src->addr_len == 2) ? (0x02 << 6) : (0x03 << 6); /* source addressing mode */ + ieee_header_len++; + buffer[ieee_header_len++] = frame_seq_num++; + + buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ + buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ + i = dst->addr_len; + while (i-- > 0) { + buffer[ieee_header_len++] = dst->addr[i]; + } + + buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ + buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ + i = src->addr_len; + while (i-- > 0) { + buffer[ieee_header_len++] = src->addr[i]; + } + +#if LWIP_6LOWPAN_IPHC + /* Perform 6LowPAN IPv6 header compression according to RFC 6282 */ + { + struct ip6_hdr *ip6hdr; + + /* Point to ip6 header and align copies of src/dest addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); + ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); + + /* Basic length of 6LowPAN header, set dispatch and clear fields. */ + lowpan6_header_len = 2; + buffer[ieee_header_len] = 0x60; + buffer[ieee_header_len + 1] = 0; + + /* Determine whether there will be a Context Identifier Extension byte or not. + * If so, set it already. */ +#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 + buffer[ieee_header_len + 2] = 0; + + i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_src)); + if (i >= 0) { + /* Stateful source address compression. */ + buffer[ieee_header_len + 1] |= 0x40; + buffer[ieee_header_len + 2] |= (i & 0x0f) << 4; + } + + i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_dest)); + if (i >= 0) { + /* Stateful destination address compression. */ + buffer[ieee_header_len + 1] |= 0x04; + buffer[ieee_header_len + 2] |= i & 0x0f; + } + + if (buffer[ieee_header_len + 2] != 0x00) { + /* Context identifier extension byte is appended. */ + buffer[ieee_header_len + 1] |= 0x80; + lowpan6_header_len++; + } +#endif /* LWIP_6LOWPAN_NUM_CONTEXTS > 0 */ + + /* Determine TF field: Traffic Class, Flow Label */ + if (IP6H_FL(ip6hdr) == 0) { + /* Flow label is elided. */ + buffer[ieee_header_len] |= 0x10; + if (IP6H_TC(ip6hdr) == 0) { + /* Traffic class (ECN+DSCP) elided too. */ + buffer[ieee_header_len] |= 0x08; + } else { + /* Traffic class (ECN+DSCP) appended. */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); + } + } else { + if (((IP6H_TC(ip6hdr) & 0x3f) == 0)) { + /* DSCP portion of Traffic Class is elided, ECN and FL are appended (3 bytes) */ + buffer[ieee_header_len] |= 0x08; + + buffer[ieee_header_len + lowpan6_header_len] = IP6H_TC(ip6hdr) & 0xc0; + buffer[ieee_header_len + lowpan6_header_len++] |= (IP6H_FL(ip6hdr) >> 16) & 0x0f; + buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; + } else { + /* Traffic class and flow label are appended (4 bytes) */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); + buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 16) & 0x0f; + buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; + } + } + + /* Compress NH? + * Only if UDP for now. @todo support other NH compression. */ + if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { + buffer[ieee_header_len] |= 0x04; + } else { + /* append nexth. */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_NEXTH(ip6hdr); + } + + /* Compress hop limit? */ + if (IP6H_HOPLIM(ip6hdr) == 255) { + buffer[ieee_header_len] |= 0x03; + } else if (IP6H_HOPLIM(ip6hdr) == 64) { + buffer[ieee_header_len] |= 0x02; + } else if (IP6H_HOPLIM(ip6hdr) == 1) { + buffer[ieee_header_len] |= 0x01; + } else { + /* append hop limit */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_HOPLIM(ip6hdr); + } + + /* Compress source address */ + if (((buffer[ieee_header_len + 1] & 0x40) != 0) || + (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_src)))) { + /* Context-based or link-local source address compression. */ + i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_src), src); + buffer[ieee_header_len + 1] |= (i & 0x03) << 4; + if (i == 1) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 16, 8); + lowpan6_header_len += 8; + } else if (i == 2) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 22, 2); + lowpan6_header_len += 2; + } + } else if (ip6_addr_isany(ip_2_ip6(&ip_data.current_iphdr_src))) { + /* Special case: mark SAC and leave SAM=0 */ + buffer[ieee_header_len + 1] |= 0x40; + } else { + /* Append full address. */ + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 8, 16); + lowpan6_header_len += 16; + } + + /* Compress destination address */ + if (ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_dest))) { + /* @todo support stateful multicast address compression */ + + buffer[ieee_header_len + 1] |= 0x08; + + i = lowpan6_get_address_mode_mc(ip_2_ip6(&ip_data.current_iphdr_dest)); + buffer[ieee_header_len + 1] |= i & 0x03; + if (i == 0) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); + lowpan6_header_len += 16; + } else if (i == 1) { + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 35, 5); + lowpan6_header_len += 5; + } else if (i == 2) { + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 37, 3); + lowpan6_header_len += 3; + } else if (i == 3) { + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[39]; + } + } else if (((buffer[ieee_header_len + 1] & 0x04) != 0) || + (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_dest)))) { + /* Context-based or link-local destination address compression. */ + i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_dest), dst); + buffer[ieee_header_len + 1] |= i & 0x03; + if (i == 1) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 32, 8); + lowpan6_header_len += 8; + } else if (i == 2) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 38, 2); + lowpan6_header_len += 2; + } + } else { + /* Append full address. */ + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); + lowpan6_header_len += 16; + } + + /* Move to payload. */ + pbuf_header(p, -IP6_HLEN); + + /* Compress UDP header? */ + if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { + /* @todo support optional checksum compression */ + + buffer[ieee_header_len + lowpan6_header_len] = 0xf0; + + /* determine port compression mode. */ + if ((((u8_t *)p->payload)[0] == 0xf0) && ((((u8_t *)p->payload)[1] & 0xf0) == 0xb0) && + (((u8_t *)p->payload)[2] == 0xf0) && ((((u8_t *)p->payload)[3] & 0xf0) == 0xb0)) { + /* Compress source and dest ports. */ + buffer[ieee_header_len + lowpan6_header_len++] |= 0x03; + buffer[ieee_header_len + lowpan6_header_len++] = ((((u8_t *)p->payload)[1] & 0x0f) << 4) | (((u8_t *)p->payload)[3] & 0x0f); + } else if (((u8_t *)p->payload)[0] == 0xf0) { + /* Compress source port. */ + buffer[ieee_header_len + lowpan6_header_len++] |= 0x02; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; + } else if (((u8_t *)p->payload)[2] == 0xf0) { + /* Compress dest port. */ + buffer[ieee_header_len + lowpan6_header_len++] |= 0x01; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; + } else { + /* append full ports. */ + lowpan6_header_len++; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; + } + + /* elide length and copy checksum */ + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[6]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[7]; + + pbuf_header(p, -UDP_HLEN); + } + } + +#else /* LWIP_6LOWPAN_HC */ + /* Send uncompressed IPv6 header with appropriate dispatch byte. */ + lowpan6_header_len = 1; + buffer[ieee_header_len] = 0x41; /* IPv6 dispatch */ +#endif /* LWIP_6LOWPAN_HC */ + + /* Calculate remaining packet length */ + remaining_len = p->tot_len; + + if (remaining_len > 0x7FF) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + /* datagram_size must fit into 11 bit */ + pbuf_free(p_frag); + return ERR_VAL; + } + + /* Fragment, or 1 packet? */ + if (remaining_len > (127 - ieee_header_len - lowpan6_header_len - 3)) { /* 127 - header - 1 byte dispatch - 2 bytes CRC */ + /* We must move the 6LowPAN header to make room for the FRAG header. */ + i = lowpan6_header_len; + while (i-- != 0) { + buffer[ieee_header_len + i + 4] = buffer[ieee_header_len + i]; + } + + /* Now we need to fragment the packet. FRAG1 header first */ + buffer[ieee_header_len] = 0xc0 | (((p->tot_len + lowpan6_header_len) >> 8) & 0x7); + buffer[ieee_header_len + 1] = (p->tot_len + lowpan6_header_len) & 0xff; + + datagram_tag++; + buffer[ieee_header_len + 2] = datagram_tag & 0xff; + buffer[ieee_header_len + 3] = (datagram_tag >> 8) & 0xff; + + /* Fragment follows. */ + frag_len = (127 - ieee_header_len - 4 - 2) & 0xf8; + + pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len + 4, frag_len - lowpan6_header_len, 0); + remaining_len -= frag_len - lowpan6_header_len; + datagram_offset = frag_len; + + /* 2 bytes CRC */ +#if LWIP_6LOWPAN_HW_CRC + /* Leave blank, will be filled by HW. */ +#else /* LWIP_6LOWPAN_HW_CRC */ + /* @todo calculate CRC */ +#endif /* LWIP_6LOWPAN_HW_CRC */ + + /* Calculate frame length */ + p_frag->len = p_frag->tot_len = ieee_header_len + 4 + frag_len + 2; /* add 2 dummy bytes for crc*/ + + /* send the packet */ + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); + LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); + err = netif->linkoutput(netif, p_frag); + + while ((remaining_len > 0) && (err == ERR_OK)) { + /* new frame, new seq num for ACK */ + buffer[2] = frame_seq_num++; + + buffer[ieee_header_len] |= 0x20; /* Change FRAG1 to FRAGN */ + + buffer[ieee_header_len + 4] = (u8_t)(datagram_offset >> 3); /* datagram offset in FRAGN header (datagram_offset is max. 11 bit) */ + + frag_len = (127 - ieee_header_len - 5 - 2) & 0xf8; + if (frag_len > remaining_len) { + frag_len = remaining_len; + } + + pbuf_copy_partial(p, buffer + ieee_header_len + 5, frag_len, p->tot_len - remaining_len); + remaining_len -= frag_len; + datagram_offset += frag_len; + + /* 2 bytes CRC */ +#if LWIP_6LOWPAN_HW_CRC + /* Leave blank, will be filled by HW. */ +#else /* LWIP_6LOWPAN_HW_CRC */ + /* @todo calculate CRC */ +#endif /* LWIP_6LOWPAN_HW_CRC */ + + /* Calculate frame length */ + p_frag->len = p_frag->tot_len = frag_len + 5 + ieee_header_len + 2; + + /* send the packet */ + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); + LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); + err = netif->linkoutput(netif, p_frag); + } + } else { + /* It fits in one frame. */ + frag_len = remaining_len; + + /* Copy IPv6 packet */ + pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len, frag_len, 0); + remaining_len = 0; + + /* 2 bytes CRC */ +#if LWIP_6LOWPAN_HW_CRC + /* Leave blank, will be filled by HW. */ +#else /* LWIP_6LOWPAN_HW_CRC */ + /* @todo calculate CRC */ +#endif /* LWIP_6LOWPAN_HW_CRC */ + + /* Calculate frame length */ + p_frag->len = p_frag->tot_len = frag_len + lowpan6_header_len + ieee_header_len + 2; + + /* send the packet */ + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); + LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); + err = netif->linkoutput(netif, p_frag); + } + + pbuf_free(p_frag); + + return err; +} + +err_t +lowpan6_set_context(u8_t idx, const ip6_addr_t * context) +{ + if (idx >= LWIP_6LOWPAN_NUM_CONTEXTS) { + return ERR_ARG; + } + + ip6_addr_set(&lowpan6_context[idx], context); + + return ERR_OK; +} + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS +err_t +lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low) +{ + short_mac_addr.addr[0] = addr_high; + short_mac_addr.addr[1] = addr_low; + + return ERR_OK; +} +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + +#if LWIP_IPV4 +err_t +lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) +{ + (void)netif; + (void)q; + (void)ipaddr; + + return ERR_IF; +} +#endif /* LWIP_IPV4 */ + +/** + * Resolve and fill-in IEEE 802.15.4 address header for outgoing IPv6 packet. + * + * Perform Header Compression and fragment if necessary. + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ip6addr The IP address of the packet destination. + * + * @return err_t + */ +err_t +lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) +{ + err_t result; + const u8_t *hwaddr; + struct ieee_802154_addr src, dest; +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS + ip6_addr_t ip6_src; + struct ip6_hdr * ip6_hdr; +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS + /* Check if we can compress source address (use aligned copy) */ + ip6_hdr = (struct ip6_hdr *)q->payload; + ip6_addr_set(&ip6_src, &ip6_hdr->src); + if (lowpan6_get_address_mode(&ip6_src, &short_mac_addr) == 3) { + src.addr_len = 2; + src.addr[0] = short_mac_addr.addr[0]; + src.addr[1] = short_mac_addr.addr[1]; + } else +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + { + src.addr_len = netif->hwaddr_len; + SMEMCPY(src.addr, netif->hwaddr, netif->hwaddr_len); + } + + /* multicast destination IP address? */ + if (ip6_addr_ismulticast(ip6addr)) { + MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); + /* We need to send to the broadcast address.*/ + return lowpan6_frag(netif, q, &src, &ieee_802154_broadcast); + } + + /* We have a unicast destination IP address */ + /* @todo anycast? */ + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS + if (src.addr_len == 2) { + /* If source address was compressable to short_mac_addr, and dest has same subnet and + * is also compressable to 2-bytes, assume we can infer dest as a short address too. */ + dest.addr_len = 2; + dest.addr[0] = ((u8_t *)q->payload)[38]; + dest.addr[1] = ((u8_t *)q->payload)[39]; + if ((src.addr_len == 2) && (ip6_addr_netcmp(&ip6_hdr->src, &ip6_hdr->dest)) && + (lowpan6_get_address_mode(ip6addr, &dest) == 3)) { + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + return lowpan6_frag(netif, q, &src, &dest); + } + } +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + + /* Ask ND6 what to do with the packet. */ + result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr); + if (result != ERR_OK) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + return result; + } + + /* If no hardware address is returned, nd6 has queued the packet for later. */ + if (hwaddr == NULL) { + return ERR_OK; + } + + /* Send out the packet using the returned hardware address. */ + dest.addr_len = netif->hwaddr_len; + SMEMCPY(dest.addr, hwaddr, netif->hwaddr_len); + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + return lowpan6_frag(netif, q, &src, &dest); +} + +static struct pbuf * +lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_802154_addr * dest) +{ + struct pbuf * q; + u8_t * lowpan6_buffer; + s8_t lowpan6_offset; + struct ip6_hdr *ip6hdr; + s8_t i; + s8_t ip6_offset = IP6_HLEN; + + + q = pbuf_alloc(PBUF_IP, p->len + IP6_HLEN + UDP_HLEN, PBUF_POOL); + if (q == NULL) { + pbuf_free(p); + return NULL; + } + + lowpan6_buffer = (u8_t *)p->payload; + ip6hdr = (struct ip6_hdr *)q->payload; + + lowpan6_offset = 2; + if (lowpan6_buffer[1] & 0x80) { + lowpan6_offset++; + } + + /* Set IPv6 version, traffic class and flow label. */ + if ((lowpan6_buffer[0] & 0x18) == 0x00) { + IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], ((lowpan6_buffer[lowpan6_offset+1] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset+3]); + lowpan6_offset += 4; + } else if ((lowpan6_buffer[0] & 0x18) == 0x08) { + IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset] & 0xc0, ((lowpan6_buffer[lowpan6_offset] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset+2]); + lowpan6_offset += 3; + } else if ((lowpan6_buffer[0] & 0x18) == 0x10) { + IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset],0); + lowpan6_offset += 1; + } else if ((lowpan6_buffer[0] & 0x18) == 0x18) { + IP6H_VTCFL_SET(ip6hdr, 6, 0, 0); + } + + /* Set Next Header */ + if ((lowpan6_buffer[0] & 0x04) == 0x00) { + IP6H_NEXTH_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); + } else { + /* We should fill this later with NHC decoding */ + IP6H_NEXTH_SET(ip6hdr, 0); + } + + /* Set Hop Limit */ + if ((lowpan6_buffer[0] & 0x03) == 0x00) { + IP6H_HOPLIM_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); + } else if ((lowpan6_buffer[0] & 0x03) == 0x01) { + IP6H_HOPLIM_SET(ip6hdr, 1); + } else if ((lowpan6_buffer[0] & 0x03) == 0x02) { + IP6H_HOPLIM_SET(ip6hdr, 64); + } else if ((lowpan6_buffer[0] & 0x03) == 0x03) { + IP6H_HOPLIM_SET(ip6hdr, 255); + } + + /* Source address decoding. */ + if ((lowpan6_buffer[1] & 0x40) == 0x00) { + /* Stateless compression */ + if ((lowpan6_buffer[1] & 0x30) == 0x00) { + /* copy full address */ + MEMCPY(&ip6hdr->src.addr[0], lowpan6_buffer + lowpan6_offset, 16); + lowpan6_offset += 16; + } else if ((lowpan6_buffer[1] & 0x30) == 0x10) { + ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->src.addr[1] = 0; + MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); + lowpan6_offset += 8; + } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { + ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->src.addr[1] = 0; + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | + lowpan6_buffer[lowpan6_offset+1]); + lowpan6_offset += 2; + } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { + ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->src.addr[1] = 0; + if (src->addr_len == 2) { + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); + } else { + ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | + (src->addr[2] << 8) | src->addr[3]); + ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | + (src->addr[6] << 8) | src->addr[7]); + } + } + } else { + /* Stateful compression */ + if ((lowpan6_buffer[1] & 0x30) == 0x00) { + /* ANY address */ + ip6hdr->src.addr[0] = 0; + ip6hdr->src.addr[1] = 0; + ip6hdr->src.addr[2] = 0; + ip6hdr->src.addr[3] = 0; + } else { + /* Set prefix from context info */ + if (lowpan6_buffer[1] & 0x80) { + i = (lowpan6_buffer[2] >> 4) & 0x0f; + } else { + i = 0; + } + if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { + /* Error */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + ip6hdr->src.addr[0] = lowpan6_context[i].addr[0]; + ip6hdr->src.addr[1] = lowpan6_context[i].addr[1]; + } + + if ((lowpan6_buffer[1] & 0x30) == 0x10) { + MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); + lowpan6_offset += 8; + } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset+1]); + lowpan6_offset += 2; + } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { + if (src->addr_len == 2) { + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); + } else { + ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | (src->addr[2] << 8) | src->addr[3]); + ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | (src->addr[6] << 8) | src->addr[7]); + } + } + } + + /* Destination address decoding. */ + if (lowpan6_buffer[1] & 0x08) { + /* Multicast destination */ + if (lowpan6_buffer[1] & 0x04) { + /* @todo support stateful multicast addressing */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + if ((lowpan6_buffer[1] & 0x03) == 0x00) { + /* copy full address */ + MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); + lowpan6_offset += 16; + } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { + ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | (lowpan6_buffer[lowpan6_offset++] << 16)); + ip6hdr->dest.addr[1] = 0; + ip6hdr->dest.addr[2] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]); + ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 24) | (lowpan6_buffer[lowpan6_offset + 1] << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset + 3]); + lowpan6_offset += 4; + } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { + ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | lowpan6_buffer[lowpan6_offset++]); + ip6hdr->dest.addr[1] = 0; + ip6hdr->dest.addr[2] = 0; + ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset + 2]); + lowpan6_offset += 3; + } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { + ip6hdr->dest.addr[0] = PP_HTONL(0xff020000UL); + ip6hdr->dest.addr[1] = 0; + ip6hdr->dest.addr[2] = 0; + ip6hdr->dest.addr[3] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]); + } + + } else { + if (lowpan6_buffer[1] & 0x04) { + /* Stateful destination compression */ + /* Set prefix from context info */ + if (lowpan6_buffer[1] & 0x80) { + i = lowpan6_buffer[2] & 0x0f; + } else { + i = 0; + } + if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { + /* Error */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + ip6hdr->dest.addr[0] = lowpan6_context[i].addr[0]; + ip6hdr->dest.addr[1] = lowpan6_context[i].addr[1]; + } else { + /* Link local address compression */ + ip6hdr->dest.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->dest.addr[1] = 0; + } + + if ((lowpan6_buffer[1] & 0x03) == 0x00) { + /* copy full address */ + MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); + lowpan6_offset += 16; + } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { + MEMCPY(&ip6hdr->dest.addr[2], lowpan6_buffer + lowpan6_offset, 8); + lowpan6_offset += 8; + } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { + ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset + 1]); + lowpan6_offset += 2; + } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { + if (dest->addr_len == 2) { + ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (dest->addr[0] << 8) | dest->addr[1]); + } else { + ip6hdr->dest.addr[2] = lwip_htonl(((dest->addr[0] ^ 2) << 24) | (dest->addr[1] << 16) | dest->addr[2] << 8 | dest->addr[3]); + ip6hdr->dest.addr[3] = lwip_htonl((dest->addr[4] << 24) | (dest->addr[5] << 16) | dest->addr[6] << 8 | dest->addr[7]); + } + } + } + + + /* Next Header Compression (NHC) decoding? */ + if (lowpan6_buffer[0] & 0x04) { + if ((lowpan6_buffer[lowpan6_offset] & 0xf8) == 0xf0) { + struct udp_hdr *udphdr; + + /* UDP compression */ + IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_UDP); + udphdr = (struct udp_hdr *)((u8_t *)q->payload + ip6_offset); + + if (lowpan6_buffer[lowpan6_offset] & 0x04) { + /* @todo support checksum decompress */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + /* Decompress ports */ + i = lowpan6_buffer[lowpan6_offset++] & 0x03; + if (i == 0) { + udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 2] << 8 | lowpan6_buffer[lowpan6_offset + 3]); + lowpan6_offset += 4; + } else if (i == 0x01) { + udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + udphdr->dest = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset + 2]); + lowpan6_offset += 3; + } else if (i == 0x02) { + udphdr->src = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset]); + udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 1] << 8 | lowpan6_buffer[lowpan6_offset + 2]); + lowpan6_offset += 3; + } else if (i == 0x03) { + udphdr->src = lwip_htons(0xf0b0 | ((lowpan6_buffer[lowpan6_offset] >> 4) & 0x0f)); + udphdr->dest = lwip_htons(0xf0b0 | (lowpan6_buffer[lowpan6_offset] & 0x0f)); + lowpan6_offset += 1; + } + + udphdr->chksum = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + lowpan6_offset += 2; + udphdr->len = lwip_htons(p->tot_len - lowpan6_offset + UDP_HLEN); + + ip6_offset += UDP_HLEN; + } else { + /* @todo support NHC other than UDP */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + } + + /* Now we copy leftover contents from p to q, so we have all L2 and L3 headers (and L4?) in a single PBUF. + * Replace p with q, and free p */ + pbuf_header(p, -lowpan6_offset); + MEMCPY((u8_t*)q->payload + ip6_offset, p->payload, p->len); + q->len = q->tot_len = ip6_offset + p->len; + if (p->next != NULL) { + pbuf_cat(q, p->next); + } + p->next = NULL; + pbuf_free(p); + + /* Infer IPv6 payload length for header */ + IP6H_PLEN_SET(ip6hdr, q->tot_len - IP6_HLEN); + + /* all done */ + return q; +} + +err_t +lowpan6_input(struct pbuf * p, struct netif *netif) +{ + u8_t * puc; + s8_t i; + struct ieee_802154_addr src, dest; + u16_t datagram_size, datagram_offset, datagram_tag; + struct lowpan6_reass_helper *lrh, *lrh_temp; + + MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); + + /* Analyze header. @todo validate. */ + puc = (u8_t*)p->payload; + datagram_offset = 5; + if ((puc[1] & 0x0c) == 0x0c) { + dest.addr_len = 8; + for (i = 0; i < 8; i++) { + dest.addr[i] = puc[datagram_offset + 7 - i]; + } + datagram_offset += 8; + } else { + dest.addr_len = 2; + dest.addr[0] = puc[datagram_offset + 1]; + dest.addr[1] = puc[datagram_offset]; + datagram_offset += 2; + } + + datagram_offset += 2; /* skip PAN ID. */ + + if ((puc[1] & 0xc0) == 0xc0) { + src.addr_len = 8; + for (i = 0; i < 8; i++) { + src.addr[i] = puc[datagram_offset + 7 - i]; + } + datagram_offset += 8; + } else { + src.addr_len = 2; + src.addr[0] = puc[datagram_offset + 1]; + src.addr[1] = puc[datagram_offset]; + datagram_offset += 2; + } + + pbuf_header(p, -datagram_offset); /* hide IEEE802.15.4 header. */ + + /* Check dispatch. */ + puc = (u8_t*)p->payload; + + if ((*puc & 0xf8) == 0xc0) { + /* FRAG1 dispatch. add this packet to reassembly list. */ + datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; + datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; + + /* check for duplicate */ + lrh = reass_list; + while (lrh != NULL) { + if ((lrh->sender_addr.addr_len == src.addr_len) && + (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0)) { + /* address match with packet in reassembly. */ + if ((datagram_tag == lrh->datagram_tag) && (datagram_size == lrh->datagram_size)) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + /* duplicate fragment. */ + pbuf_free(p); + return ERR_OK; + } else { + /* We are receiving the start of a new datagram. Discard old one (incomplete). */ + lrh_temp = lrh->next_packet; + dequeue_datagram(lrh); + pbuf_free(lrh->pbuf); + mem_free(lrh); + + /* Check next datagram in queue. */ + lrh = lrh_temp; + } + } else { + /* Check next datagram in queue. */ + lrh = lrh->next_packet; + } + } + + pbuf_header(p, -4); /* hide frag1 dispatch */ + + lrh = (struct lowpan6_reass_helper *) mem_malloc(sizeof(struct lowpan6_reass_helper)); + if (lrh == NULL) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + pbuf_free(p); + return ERR_MEM; + } + + lrh->sender_addr.addr_len = src.addr_len; + for (i = 0; i < src.addr_len; i++) { + lrh->sender_addr.addr[i] = src.addr[i]; + } + lrh->datagram_size = datagram_size; + lrh->datagram_tag = datagram_tag; + lrh->pbuf = p; + lrh->next_packet = reass_list; + lrh->timer = 2; + reass_list = lrh; + + return ERR_OK; + } else if ((*puc & 0xf8) == 0xe0) { + /* FRAGN dispatch, find packet being reassembled. */ + datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; + datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; + datagram_offset = (u16_t)puc[4] << 3; + pbuf_header(p, -5); /* hide frag1 dispatch */ + + for (lrh = reass_list; lrh != NULL; lrh = lrh->next_packet) { + if ((lrh->sender_addr.addr_len == src.addr_len) && + (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0) && + (datagram_tag == lrh->datagram_tag) && + (datagram_size == lrh->datagram_size)) { + break; + } + } + if (lrh == NULL) { + /* rogue fragment */ + MIB2_STATS_NETIF_INC(netif, ifindiscards); + pbuf_free(p); + return ERR_OK; + } + + if (lrh->pbuf->tot_len < datagram_offset) { + /* duplicate, ignore. */ + pbuf_free(p); + return ERR_OK; + } else if (lrh->pbuf->tot_len > datagram_offset) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + /* We have missed a fragment. Delete whole reassembly. */ + dequeue_datagram(lrh); + pbuf_free(lrh->pbuf); + mem_free(lrh); + pbuf_free(p); + return ERR_OK; + } + pbuf_cat(lrh->pbuf, p); + p = NULL; + + /* is packet now complete?*/ + if (lrh->pbuf->tot_len >= lrh->datagram_size) { + /* dequeue from reass list. */ + dequeue_datagram(lrh); + + /* get pbuf */ + p = lrh->pbuf; + + /* release helper */ + mem_free(lrh); + } else { + return ERR_OK; + } + } + + if (p == NULL) { + return ERR_OK; + } + + /* We have a complete packet, check dispatch for headers. */ + puc = (u8_t*)p->payload; + + if (*puc == 0x41) { + /* This is a complete IPv6 packet, just skip dispatch byte. */ + pbuf_header(p, -1); /* hide dispatch byte. */ + } else if ((*puc & 0xe0 )== 0x60) { + /* IPv6 headers are compressed using IPHC. */ + p = lowpan6_decompress(p, &src, &dest); + if (p == NULL) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + return ERR_OK; + } + } else { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + pbuf_free(p); + return ERR_OK; + } + + /* @todo: distinguish unicast/multicast */ + MIB2_STATS_NETIF_INC(netif, ifinucastpkts); + + return ip6_input(p, netif); +} + +err_t +lowpan6_if_init(struct netif *netif) +{ + netif->name[0] = 'L'; + netif->name[1] = '6'; +#if LWIP_IPV4 + netif->output = lowpan4_output; +#endif /* LWIP_IPV4 */ + netif->output_ip6 = lowpan6_output; + + MIB2_INIT_NETIF(netif, snmp_ifType_other, 0); + + /* maximum transfer unit */ + netif->mtu = 1280; + + /* broadcast capability */ + netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */; + + return ERR_OK; +} + +err_t +lowpan6_set_pan_id(u16_t pan_id) +{ + ieee_802154_pan_id = pan_id; + + return ERR_OK; +} + +#if !NO_SYS +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet, p->payload pointing to the + * IEEE 802.15.4 header. + * @param inp the network interface on which the packet was received + */ +err_t +tcpip_6lowpan_input(struct pbuf *p, struct netif *inp) +{ + return tcpip_inpkt(p, inp, lowpan6_input); +} +#endif /* !NO_SYS */ + +#endif /* LWIP_IPV6 && LWIP_6LOWPAN */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/PPPD_FOLLOWUP b/components/net/lwip-2.0.3/src/netif/ppp/PPPD_FOLLOWUP new file mode 100644 index 0000000000..c231982ae7 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/PPPD_FOLLOWUP @@ -0,0 +1,473 @@ +The lwIP PPP support is based from pppd 2.4.5 (http://ppp.samba.org) with +huge changes to match code size and memory requirements for embedded devices. + +Anyway, pppd has a mature codebase for years and the average commit count +is getting low on their Git repository, meaning that we can follow what +is happening on their side and merge what is relevant for lwIP. + +So, here is the pppd follow up, so that we don't get away too far from pppd. + + +== Patch fetched from from pppd Debian packages == + +This has nothing to do with pppd, but we merged some good patch from +Debian and this is a good place to be. + +- LCP adaptive echo, so that we don't send LCP echo request if we + are receiving data from peer, can be enabled by setting PPP_LCP_ADAPTIVE + to true. + +- IPCP no/replace default route option, were added in the early stage of + the ppp port, but it wasn't really helpful and was disabled when adding + the new API ppp_set_default() call, which gives the lwIP user control over + which one is the default interface, it was actually a requirement if you + are doing PPP over PPP (i.e. PPPoL2TP, VPN link, over PPPoE, ADSL link). + +- using rp-pppoe pppd exits with EXIT_OK after receiving a timeout waiting + for PADO due to no modem attached, bug reported to pppd bug tracker, fixed + in Debian but not in the latest (at the time when the port were started) + pppd release. + + +== Commits on pppd == + +2010-03-06 - Document +ipv6 and ipv6cp-accept-local + e7537958aee79b3f653c601e903cb31d78fb7dcc + +Don't care. + + +2010-03-06 - Install pppol2tp plugins with sane permissions + 406215672cfadc03017341fe03802d1c7294b903 + +Don't care. + + +2010-03-07 - pppd: Terminate correctly if lcp_lowerup delayed calling + fsm_lowerup + 3eb9e810cfa515543655659b72dde30c54fea0a5 + +Merged 2012-05-17. + + +2010-03-07 - rp_pppoe: Copy acName and pppd_pppoe_service after option parsing + cab58617fd9d328029fffabc788020264b4fa91f + +Don't care, is a patch for pppd/plugins/rp-pppoe/plugin.c which is not part +of the port. + + +2010-08-23 - set and reset options to control environment variables + for scripts. + 2b6310fd24dba8e0fca8999916a162f0a1842a84 + +We can't fork processes in embedded, therefore all the pppd process run +feature is disabled in the port, so we don't care about the new +"environment variables" pppd feature. + + +2010-08-23 - Nit: use _exit when exec fails and restrict values to 0-255 + per POSIX. + 2b4ea140432eeba5a007c0d4e6236bd0e0c12ba4 + +Again, we are not running as a heavy process, so all exit() or _exit() calls +were removed. + + +2010-08-23 - Fix quote handling in configuration files to be more like shell + quoting. + 3089132cdf5b58dbdfc2daf08ec5c08eb47f8aca + +We are not parsing config file, all the filesystem I/O stuff were disabled +in our port. + + +2010-08-24 - rp-pppoe: allow MTU to be increased up to 1500 + fd1dcdf758418f040da3ed801ab001b5e46854e7 + +Only concern changes on RP-PPPoE plugin, which we don't use. + + +2010-09-11 - chat: Allow TIMEOUT value to come from environment variable + ae80bf833e48a6202f44a935a68083ae52ad3824 + +See 2b6310fd24dba8e0fca8999916a162f0a1842a84. + + +2011-03-05 - pppdump: Fix printfs with insufficient arguments + 7b8db569642c83ba3283745034f2e2c95e459423 + +pppdump is a ppp tool outside pppd source tree. + + +2012-05-06 - pppd: Don't unconditionally disable VJ compression under Linux + d8a66adf98a0e525cf38031b42098d539da6eeb6 + +Patch for sys-linux.c, which we don't use. + + +2012-05-20 - Remove old version of Linux if_pppol2tp.h + c41092dd4c49267f232f6cba3d31c6c68bfdf68d + +Not in the port. + + +2012-05-20 - pppd: Make MSCHAP-v2 cope better with packet loss + 08ef47ca532294eb428238c831616748940e24a2 + +This is an interesting patch. However it consumes much more memory for +MSCHAP and I am not sure if the benefit worth it. The PPP client can +always start the authentication again if it failed for whatever reason. + + +2012-05-20 - scripts: Make poff ignore extra arguments to pppd + 18f515f32c9f5723a9c2c912601e04335106534b + +Again, we are not running scripts. + + +2012-05-20 - rp-pppoe plugin: Print leading zeros in MAC address + f5dda0cfc220c4b52e26144096d729e27b30f0f7 + +Again, we are not using the RP-PPPoE plugin. + + +2012-05-20 - pppd: Notify IPv6 up/down as we do for IPv4 + 845cda8fa18939cf56e60b073f63a7efa65336fc + +This is just a patch that adds plugins hooks for IPv6, the plugin interface +was disabled because we don't have .so plugins in embedded. + + +2012-05-20 - pppd: Enable IPV6 by default and fix some warnings + 0b6118239615e98959f7e0b4e746bdd197533248 + +Change on Makefile for IPv6, warnings were already cleared during port. + + +2012-05-20 - contrib: Fix pppgetpass.gtk compilation + 80a8e2ce257ca12cce723519a0f20ea1d663b14a + +Change on Makefile, don't care. + + +2012-05-20 - pppd: Don't crash if crypt() returns NULL + 04c4348108d847e034dd91066cc6843f60d71731 + +We are using the PolarSSL DES implementation that does not return NULL. + + +2012-05-20 - pppd: Eliminate some warnings + c44ae5e6a7338c96eb463881fe709b2dfaffe568 + +Again, we are handling compilation warnings on our own. + + +2012-05-20 - rp-pppoe plugin: Import some fixes from rp-pppoe-3.10 + 1817d83e51a411044e730ba89ebdb0480e1c8cd4 + +Once more, we are not using the RP-PPPoE plugin. + + +2013-01-23 - pppd: Clarify circumstances where DNS1/DNS2 environment variables are set + cf2f5c9538b9400ade23446a194729b0a4113b3a + +Documentation only. + + +2013-02-03 - ppp: ignore unrecognised radiusclient configuration directives + 7f736dde0da3c19855997d9e67370e351e15e923 + +Radius plugin, not in the port. + + +2013-02-03 - pppd: Take out unused %r conversion completely + 356d8d558d844412119aa18c8e5a113bc6459c7b + +Merged 2014-04-15. + + +2013-02-03 - pppd: Arrange to use logwtmp from libutil on Linux + 9617a7eb137f4fee62799a677a9ecf8d834db3f5 + +Patch for sys-linux.c, which we don't use. + + +2013-02-03 - pppdump: Eliminate some compiler warnings + 3e3acf1ba2b3046c072a42c19164788a9e419bd1 + +pppdump is a ppp tool outside pppd source tree. + + +2013-02-03 - chat: Correct spelling errors in the man page + 8dea1b969d266ccbf6f3a8c5474eb6dcd8838e3b + +Documentation only. + + +2013-02-03 - pppd: Fix spelling errors in man page + 9e05a25d76b3f83096c661678010320df673df6b + +Documentation only. + + +2013-02-03 - plugins/passprompt: Fix potential out-of-bounds array reference + 8edb889b753056a691a3e4b217a110a35f9fdedb + +Plugin patch, we do not have plugins. + + +2013-02-03 - chat: Fix *roff errors in the man page + a7c3489eeaf44e83ce592143c7c8a5b5c29f4c48 + +Documentation only. + + +2013-03-02 - pppd: Fix man page description of case when remote IP address isn't known + 224841f4799f4f1e2e71bc490c54448d66740f4f + +Documentation only. + + +2013-03-02 - pppd: Add master_detach option + 398ed2585640d198c53e736ee5bbd67f7ce8168e + +Option for multilink support, we do not support multilink and this option +is about detaching from the terminal, which is out of the embedded scope. + + +2013-03-11 - pppd: Default exit status to EXIT_CONNECT_FAILED during connection phase + 225361d64ae737afdc8cb57579a2f33525461bc9 + +Commented out in our port, and already fixed by a previously applied Debian patch. + + +2013-03-11 - pppstats: Fix undefined macro in man page + d16a3985eade5280b8e171f5dd0670a91cba0d39 + +Documentation only. + + +2013-05-11 - plugins/radius: Handle bindaddr keyword in radiusclient.conf + d883b2dbafeed3ebd9d7a56ab1469373bd001a3b + +Radius plugin, not in the port. + + +2013-06-09 - pppoatm: Remove explicit loading of pppoatm kernel module + 52cd43a84bea524033b918b603698104f221bbb7 + +PPPoATM plugin, not in the port. + + +2013-06-09 - pppd: Fix segfault in update_db_entry() + 37476164f15a45015310b9d4b197c2d7db1f7f8f + +We do not use the samba db. + + +2013-06-09 - chat: Fix some text that was intended to be literal + cd9683676618adcee8add2c3cfa3382341b5a1f6 + +Documentation only. + + +2013-06-09 - README.pppoe: Minor semantic fix + b5b8898af6fd3d44e873cfc66810ace5f1f47e17 + +Documentation only. + + +2013-06-10 - radius: Handle additional attributes + 2f581cd986a56f2ec4a95abad4f8297a1b10d7e2 + +Radius plugin, not in the port. + + +2013-06-10 - chat, pppd: Use \e instead of \\ in man pages + 8d6942415d22f6ca4377340ca26e345c3f5fa5db + +Documentation only. + + +2014-01-02 - pppd: Don't crash if NULL pointer passed to vslprintf for %q or %v + 906814431bddeb2061825fa1ebad1a967b6d87a9 + +Merged 2014-04-15. + + +2014-01-02 - pppd: Accept IPCP ConfAck packets containing MS-WINS options + a243f217f1c6ac1aa7793806bc88590d077f490a + +Merged 2014-04-15. + + +2014-01-02 - config: Update Solaris compiler options and enable CHAPMS and IPV6 + 99c46caaed01b7edba87962aa52b77fad61bfd7b + +Solaris port, don't care. + + +2014-01-02 - Update README and patchlevel for 2.4.6 release + 4043750fca36e7e0eb90d702e048ad1da4929418 + +Just release stuff. + + +2014-02-18 - pppd: Add option "stop-bits" to set number of serial port stop bits. + ad993a20ee485f0d0e2ac4105221641b200da6e2 + +Low level serial port, not in the port. + + +2014-03-09 - pppd: Separate IPv6 handling for sifup/sifdown + b04d2dc6df5c6b5650fea44250d58757ee3dac4a + +Reimplemented. + + +2014-03-09 - pppol2tp: Connect up/down events to notifiers and add IPv6 ones + fafbe50251efc7d6b4a8be652d085316e112b34f + +Not in the port. + + +2014-03-09 - pppd: Add declarations to eliminate compile warnings + 50967962addebe15c7a7e63116ff46a0441dc464 + +We are handling compilation warnings on our own + + +2014-03-09 - pppd: Eliminate some unnecessary ifdefs + de8da14d845ee6db9236ccfddabf1d8ebf045ddb + +We mostly did that previously. Anyway, merged 2014-12-24. + + +2014-08-01 - radius: Fix realms-config-file option + 880a81be7c8e0fe8567227bc17a1bff3ea035943 + +Radius plugin, not in the port. + + +2014-08-01 - pppd: Eliminate potential integer overflow in option parsing + 7658e8257183f062dc01f87969c140707c7e52cb + +pppd config file parser, not in the port. + + +2014-08-01 - pppd: Eliminate memory leak with multiple instances of a string option + b94b7fbbaa0589aa6ec5fdc733aeb9ff294d2656 + +pppd config file parser, not in the port. + + +2014-08-01 - pppd: Fix a stack variable overflow in MSCHAP-v2 + 36733a891fb56594fcee580f667b33a64b990981 + +This fixes a bug introduced in 08ef47ca ("pppd: Make MSCHAP-v2 cope better with packet loss"). + +We didn't merge 08ef47ca ;-) + + +2014-08-01 - winbind plugin: Add -DMPPE=1 to eliminate compiler warnings + 2b05e22c62095e97dd0a97e4b5588402c2185071 + +Linux plugin, not in the port. + + +2014-08-09 - Update README and patchlevel for 2.4.7 release + 6e8eaa7a78b31cdab2edf140a9c8afdb02ffaca5 + +Just release stuff. + + +2014-08-10 - abort on errors in subdir builds + 5e90783d11a59268e05f4cfb29ce2343b13e8ab2 + +Linux Makefile, not in the port. + + +2014-06-03 - pppd: add support for defaultroute-metric option + 35e5a569c988b1ff865b02a24d9a727a00db4da9 + +Only necessary for Linux, lwIP does not support route metrics. + + +2014-12-13 - scripts: Avoid killing wrong pppd + 67811a647d399db5d188a242827760615a0f86b5 + +pppd helper script, not in the port. + + +2014-12-20 - pppd: Fix sign-extension when displaying bytes in octal + 5e8c3cb256a7e86e3572a82a75d51c6850efdbdc + +Merged 2016-07-02. + + +2015-03-01 - Suppress false error message on PPPoE disconnect + 219aac3b53d0827549377f1bfe22853ee52d4405 + +PPPoE plugin, not in the port. + + +2015-03-01 - Send PADT on PPPoE disconnect + cd2c14f998c57bbe6a01dc5854f2763c0d7f31fb + +PPPoE plugin, not in the port. And our PPPoE implementation already does +that: pppoe_disconnect() calls pppoe_send_padt(). + + +2015-08-14 - pppd: ipxcp: Prevent buffer overrun on remote router name + fe149de624f96629a7f46732055d8f718c74b856 + +We never ported IPX support. lwIP does not support IPX. + + +2015-03-25 - pppd: Fix ccp_options.mppe type + 234edab99a6bb250cc9ecd384cca27b0c8b475ce + +We found that while working on MPPE support in lwIP, that's our patch ;-) + + +2015-03-24 - pppd: Fix ccp_cilen calculated size if both deflate_correct and deflate_draft are enabled + 094cb8ae4c61db225e67fedadb4964f846dd0c27 + +We found that while working on MPPE support in lwIP, that's our patch ;-) + + +2015-08-14 - Merge branch 'master' of https://github.com/ncopa/ppp + 3a5c9a8fbc8970375cd881151d44e4b6fe249c6a + +Merge commit, we don't care. + + +2015-08-14 - Merge branch 'master' of git://github.com/vapier/ppp + 912e4fc6665aca188dced7ea7fdc663ce5a2dd24 + +Merge commit, we don't care. + + +2015-08-14 - Merge branch 'bug_fix' of git://github.com/radaiming/ppp + dfd33d7f526ecd7b39dd1bba8101260d02af5ebb + +Merge commit, we don't care. + + +2015-08-14 - Merge branch 'master' of git://github.com/pprindeville/ppp + aa4a985f6114d08cf4e47634fb6325da71016473 + +Merge commit, we don't care. + + +2015-08-14 - Merge branch 'no-error-on-already-closed' of git://github.com/farnz/ppp + 6edf252483b30dbcdcc5059f01831455365d5b6e + +Merge commit, we don't care. + + +2015-08-14 - Merge branch 'send-padt-on-disconnect' of git://github.com/farnz/ppp + 84684243d651f55f6df69d2a6707b52fbbe62bb9 + +Merge commit, we don't care. diff --git a/components/net/lwip-2.0.3/src/netif/ppp/auth.c b/components/net/lwip-2.0.3/src/netif/ppp/auth.c new file mode 100644 index 0000000000..c8673ad0fb --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/auth.c @@ -0,0 +1,2510 @@ +/* + * auth.c - PPP authentication and phase control. + * + * Copyright (c) 1993-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Derived from main.c, which is: + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(_PATH_LASTLOG) && defined(__linux__) +#include +#endif + +#include +#include +#include + +#ifdef HAS_SHADOW +#include +#ifndef PW_PPP +#define PW_PPP PW_LOGIN +#endif +#endif + +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#if CCP_SUPPORT +#include "netif/ppp/ccp.h" +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT +#include "netif/ppp/ecp.h" +#endif /* ECP_SUPPORT */ +#include "netif/ppp/ipcp.h" +#if PAP_SUPPORT +#include "netif/ppp/upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "netif/ppp/eap.h" +#endif /* EAP_SUPPORT */ +#if CBCP_SUPPORT +#include "netif/ppp/cbcp.h" +#endif + +#if 0 /* UNUSED */ +#include "session.h" +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* Bits in scan_authfile return value */ +#define NONWILD_SERVER 1 +#define NONWILD_CLIENT 2 + +#define ISWILD(word) (word[0] == '*' && word[1] == 0) +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* List of addresses which the peer may use. */ +static struct permitted_ip *addresses[NUM_PPP]; + +/* Wordlist giving addresses which the peer may use + without authenticating itself. */ +static struct wordlist *noauth_addrs; + +/* Remote telephone number, if available */ +char remote_number[MAXNAMELEN]; + +/* Wordlist giving remote telephone numbers which may connect. */ +static struct wordlist *permitted_numbers; + +/* Extra options to apply, from the secrets file entry for the peer. */ +static struct wordlist *extra_options; +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* Set if we require authentication only because we have a default route. */ +static bool default_auth; + +/* Hook to enable a plugin to control the idle time limit */ +int (*idle_time_hook) (struct ppp_idle *) = NULL; + +/* Hook for a plugin to say whether we can possibly authenticate any peer */ +int (*pap_check_hook) (void) = NULL; + +/* Hook for a plugin to check the PAP user and password */ +int (*pap_auth_hook) (char *user, char *passwd, char **msgp, + struct wordlist **paddrs, + struct wordlist **popts) = NULL; + +/* Hook for a plugin to know about the PAP user logout */ +void (*pap_logout_hook) (void) = NULL; + +/* Hook for a plugin to get the PAP password for authenticating us */ +int (*pap_passwd_hook) (char *user, char *passwd) = NULL; + +/* Hook for a plugin to say if we can possibly authenticate a peer using CHAP */ +int (*chap_check_hook) (void) = NULL; + +/* Hook for a plugin to get the CHAP password for authenticating us */ +int (*chap_passwd_hook) (char *user, char *passwd) = NULL; + +/* Hook for a plugin to say whether it is OK if the peer + refuses to authenticate. */ +int (*null_auth_hook) (struct wordlist **paddrs, + struct wordlist **popts) = NULL; + +int (*allowed_address_hook) (u32_t addr) = NULL; +#endif /* UNUSED */ + +#ifdef HAVE_MULTILINK +/* Hook for plugin to hear when an interface joins a multilink bundle */ +void (*multilink_join_hook) (void) = NULL; +#endif + +#if PPP_NOTIFY +/* A notifier for when the peer has authenticated itself, + and we are proceeding to the network phase. */ +struct notifier *auth_up_notifier = NULL; + +/* A notifier for when the link goes down. */ +struct notifier *link_down_notifier = NULL; +#endif /* PPP_NOTIFY */ + +/* + * Option variables. + */ +#if 0 /* MOVED TO ppp_settings */ +bool uselogin = 0; /* Use /etc/passwd for checking PAP */ +bool session_mgmt = 0; /* Do session management (login records) */ +bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ +bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ +bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ +bool refuse_eap = 0; /* Don't wanna auth. ourselves with EAP */ +#if MSCHAP_SUPPORT +bool refuse_mschap = 0; /* Don't wanna auth. ourselves with MS-CHAP */ +bool refuse_mschap_v2 = 0; /* Don't wanna auth. ourselves with MS-CHAPv2 */ +#else /* MSCHAP_SUPPORT */ +bool refuse_mschap = 1; /* Don't wanna auth. ourselves with MS-CHAP */ +bool refuse_mschap_v2 = 1; /* Don't wanna auth. ourselves with MS-CHAPv2 */ +#endif /* MSCHAP_SUPPORT */ +bool usehostname = 0; /* Use hostname for our_name */ +bool auth_required = 0; /* Always require authentication from peer */ +bool allow_any_ip = 0; /* Allow peer to use any IP address */ +bool explicit_remote = 0; /* User specified explicit remote name */ +bool explicit_user = 0; /* Set if "user" option supplied */ +bool explicit_passwd = 0; /* Set if "password" option supplied */ +char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ +static char *uafname; /* name of most recent +ua file */ + +extern char *crypt (const char *, const char *); +#endif /* UNUSED */ +/* Prototypes for procedures local to this file. */ + +static void network_phase(ppp_pcb *pcb); +#if PPP_IDLETIMELIMIT +static void check_idle(void *arg); +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT +static void connect_time_expired(void *arg); +#endif /* PPP_MAXCONNECT */ +#if 0 /* UNUSED */ +static int null_login (int); +/* static int get_pap_passwd (char *); */ +static int have_pap_secret (int *); +static int have_chap_secret (char *, char *, int, int *); +static int have_srp_secret (char *client, char *server, int need_ip, + int *lacks_ipp); +static int ip_addr_check (u32_t, struct permitted_ip *); +static int scan_authfile (FILE *, char *, char *, char *, + struct wordlist **, struct wordlist **, + char *, int); +static void free_wordlist (struct wordlist *); +static void set_allowed_addrs (int, struct wordlist *, struct wordlist *); +static int some_ip_ok (struct wordlist *); +static int setupapfile (char **); +static int privgroup (char **); +static int set_noauth_addr (char **); +static int set_permitted_number (char **); +static void check_access (FILE *, char *); +static int wordlist_count (struct wordlist *); +#endif /* UNUSED */ + +#ifdef MAXOCTETS +static void check_maxoctets (void *); +#endif + +#if PPP_OPTIONS +/* + * Authentication-related options. + */ +option_t auth_options[] = { + { "auth", o_bool, &auth_required, + "Require authentication from peer", OPT_PRIO | 1 }, + { "noauth", o_bool, &auth_required, + "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV, + &allow_any_ip }, + { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", + OPT_PRIOSUB | 1, &auth_required }, + { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required }, + { "require-chap", o_bool, &auth_required, + "Require CHAP authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, + &lcp_wantoptions[0].chap_mdtype }, + { "+chap", o_bool, &auth_required, + "Require CHAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, + &lcp_wantoptions[0].chap_mdtype }, +#if MSCHAP_SUPPORT + { "require-mschap", o_bool, &auth_required, + "Require MS-CHAP authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, + &lcp_wantoptions[0].chap_mdtype }, + { "+mschap", o_bool, &auth_required, + "Require MS-CHAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, + &lcp_wantoptions[0].chap_mdtype }, + { "require-mschap-v2", o_bool, &auth_required, + "Require MS-CHAPv2 authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, + &lcp_wantoptions[0].chap_mdtype }, + { "+mschap-v2", o_bool, &auth_required, + "Require MS-CHAPv2 authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, + &lcp_wantoptions[0].chap_mdtype }, +#endif /* MSCHAP_SUPPORT */ +#if 0 + { "refuse-pap", o_bool, &refuse_pap, + "Don't agree to auth to peer with PAP", 1 }, + { "-pap", o_bool, &refuse_pap, + "Don't allow PAP authentication with peer", OPT_ALIAS | 1 }, + { "refuse-chap", o_bool, &refuse_chap, + "Don't agree to auth to peer with CHAP", + OPT_A2CLRB | MDTYPE_MD5, + &lcp_allowoptions[0].chap_mdtype }, + { "-chap", o_bool, &refuse_chap, + "Don't allow CHAP authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MD5, + &lcp_allowoptions[0].chap_mdtype }, +#endif +#if MSCHAP_SUPPORT +#if 0 + { "refuse-mschap", o_bool, &refuse_mschap, + "Don't agree to auth to peer with MS-CHAP", + OPT_A2CLRB | MDTYPE_MICROSOFT, + &lcp_allowoptions[0].chap_mdtype }, + { "-mschap", o_bool, &refuse_mschap, + "Don't allow MS-CHAP authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT, + &lcp_allowoptions[0].chap_mdtype }, + { "refuse-mschap-v2", o_bool, &refuse_mschap_v2, + "Don't agree to auth to peer with MS-CHAPv2", + OPT_A2CLRB | MDTYPE_MICROSOFT_V2, + &lcp_allowoptions[0].chap_mdtype }, + { "-mschap-v2", o_bool, &refuse_mschap_v2, + "Don't allow MS-CHAPv2 authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT_V2, + &lcp_allowoptions[0].chap_mdtype }, +#endif +#endif /* MSCHAP_SUPPORT*/ +#if EAP_SUPPORT + { "require-eap", o_bool, &lcp_wantoptions[0].neg_eap, + "Require EAP authentication from peer", OPT_PRIOSUB | 1, + &auth_required }, +#if 0 + { "refuse-eap", o_bool, &refuse_eap, + "Don't agree to authenticate to peer with EAP", 1 }, +#endif +#endif /* EAP_SUPPORT */ + { "name", o_string, our_name, + "Set local name for authentication", + OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXNAMELEN }, + + { "+ua", o_special, (void *)setupapfile, + "Get PAP user and password from file", + OPT_PRIO | OPT_A2STRVAL, &uafname }, + +#if 0 + { "user", o_string, user, + "Set name for auth with peer", OPT_PRIO | OPT_STATIC, + &explicit_user, MAXNAMELEN }, + + { "password", o_string, passwd, + "Password for authenticating us to the peer", + OPT_PRIO | OPT_STATIC | OPT_HIDE, + &explicit_passwd, MAXSECRETLEN }, +#endif + + { "usehostname", o_bool, &usehostname, + "Must use hostname for authentication", 1 }, + + { "remotename", o_string, remote_name, + "Set remote name for authentication", OPT_PRIO | OPT_STATIC, + &explicit_remote, MAXNAMELEN }, + + { "login", o_bool, &uselogin, + "Use system password database for PAP", OPT_A2COPY | 1 , + &session_mgmt }, + { "enable-session", o_bool, &session_mgmt, + "Enable session accounting for remote peers", OPT_PRIV | 1 }, + + { "papcrypt", o_bool, &cryptpap, + "PAP passwords are encrypted", 1 }, + + { "privgroup", o_special, (void *)privgroup, + "Allow group members to use privileged options", OPT_PRIV | OPT_A2LIST }, + + { "allow-ip", o_special, (void *)set_noauth_addr, + "Set IP address(es) which can be used without authentication", + OPT_PRIV | OPT_A2LIST }, + + { "remotenumber", o_string, remote_number, + "Set remote telephone number for authentication", OPT_PRIO | OPT_STATIC, + NULL, MAXNAMELEN }, + + { "allow-number", o_special, (void *)set_permitted_number, + "Set telephone number(s) which are allowed to connect", + OPT_PRIV | OPT_A2LIST }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +#if 0 /* UNUSED */ +/* + * setupapfile - specifies UPAP info for authenticating with peer. + */ +static int +setupapfile(argv) + char **argv; +{ + FILE *ufile; + int l; + uid_t euid; + char u[MAXNAMELEN], p[MAXSECRETLEN]; + char *fname; + + lcp_allowoptions[0].neg_upap = 1; + + /* open user info file */ + fname = strdup(*argv); + if (fname == NULL) + novm("+ua file name"); + euid = geteuid(); + if (seteuid(getuid()) == -1) { + option_error("unable to reset uid before opening %s: %m", fname); + return 0; + } + ufile = fopen(fname, "r"); + if (seteuid(euid) == -1) + fatal("unable to regain privileges: %m"); + if (ufile == NULL) { + option_error("unable to open user login data file %s", fname); + return 0; + } + check_access(ufile, fname); + uafname = fname; + + /* get username */ + if (fgets(u, MAXNAMELEN - 1, ufile) == NULL + || fgets(p, MAXSECRETLEN - 1, ufile) == NULL) { + fclose(ufile); + option_error("unable to read user login data file %s", fname); + return 0; + } + fclose(ufile); + + /* get rid of newlines */ + l = strlen(u); + if (l > 0 && u[l-1] == '\n') + u[l-1] = 0; + l = strlen(p); + if (l > 0 && p[l-1] == '\n') + p[l-1] = 0; + + if (override_value("user", option_priority, fname)) { + strlcpy(ppp_settings.user, u, sizeof(ppp_settings.user)); + explicit_user = 1; + } + if (override_value("passwd", option_priority, fname)) { + strlcpy(ppp_settings.passwd, p, sizeof(ppp_settings.passwd)); + explicit_passwd = 1; + } + + return (1); +} + +/* + * privgroup - allow members of the group to have privileged access. + */ +static int +privgroup(argv) + char **argv; +{ + struct group *g; + int i; + + g = getgrnam(*argv); + if (g == 0) { + option_error("group %s is unknown", *argv); + return 0; + } + for (i = 0; i < ngroups; ++i) { + if (groups[i] == g->gr_gid) { + privileged = 1; + break; + } + } + return 1; +} + + +/* + * set_noauth_addr - set address(es) that can be used without authentication. + * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. + */ +static int +set_noauth_addr(argv) + char **argv; +{ + char *addr = *argv; + int l = strlen(addr) + 1; + struct wordlist *wp; + + wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); + if (wp == NULL) + novm("allow-ip argument"); + wp->word = (char *) (wp + 1); + wp->next = noauth_addrs; + MEMCPY(wp->word, addr, l); + noauth_addrs = wp; + return 1; +} + + +/* + * set_permitted_number - set remote telephone number(s) that may connect. + */ +static int +set_permitted_number(argv) + char **argv; +{ + char *number = *argv; + int l = strlen(number) + 1; + struct wordlist *wp; + + wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); + if (wp == NULL) + novm("allow-number argument"); + wp->word = (char *) (wp + 1); + wp->next = permitted_numbers; + MEMCPY(wp->word, number, l); + permitted_numbers = wp; + return 1; +} +#endif + +/* + * An Open on LCP has requested a change from Dead to Establish phase. + */ +void link_required(ppp_pcb *pcb) { + LWIP_UNUSED_ARG(pcb); +} + +#if 0 +/* + * Bring the link up to the point of being able to do ppp. + */ +void start_link(unit) + int unit; +{ + ppp_pcb *pcb = &ppp_pcb_list[unit]; + char *msg; + + status = EXIT_NEGOTIATION_FAILED; + new_phase(pcb, PPP_PHASE_SERIALCONN); + + hungup = 0; + devfd = the_channel->connect(); + msg = "Connect script failed"; + if (devfd < 0) + goto fail; + + /* set up the serial device as a ppp interface */ + /* + * N.B. we used to do tdb_writelock/tdb_writeunlock around this + * (from establish_ppp to set_ifunit). However, we won't be + * doing the set_ifunit in multilink mode, which is the only time + * we need the atomicity that the tdb_writelock/tdb_writeunlock + * gives us. Thus we don't need the tdb_writelock/tdb_writeunlock. + */ + fd_ppp = the_channel->establish_ppp(devfd); + msg = "ppp establishment failed"; + if (fd_ppp < 0) { + status = EXIT_FATAL_ERROR; + goto disconnect; + } + + if (!demand && ifunit >= 0) + set_ifunit(1); + + /* + * Start opening the connection and wait for + * incoming events (reply, timeout, etc.). + */ + if (ifunit >= 0) + ppp_notice("Connect: %s <--> %s", ifname, ppp_devnam); + else + ppp_notice("Starting negotiation on %s", ppp_devnam); + add_fd(fd_ppp); + + new_phase(pcb, PPP_PHASE_ESTABLISH); + + lcp_lowerup(pcb); + return; + + disconnect: + new_phase(pcb, PPP_PHASE_DISCONNECT); + if (the_channel->disconnect) + the_channel->disconnect(); + + fail: + new_phase(pcb, PPP_PHASE_DEAD); + if (the_channel->cleanup) + (*the_channel->cleanup)(); +} +#endif + +/* + * LCP has terminated the link; go to the Dead phase and take the + * physical layer down. + */ +void link_terminated(ppp_pcb *pcb) { + if (pcb->phase == PPP_PHASE_DEAD +#ifdef HAVE_MULTILINK + || pcb->phase == PPP_PHASE_MASTER +#endif /* HAVE_MULTILINK */ + ) + return; + new_phase(pcb, PPP_PHASE_DISCONNECT); + +#if 0 /* UNUSED */ + if (pap_logout_hook) { + pap_logout_hook(); + } + session_end(devnam); +#endif /* UNUSED */ + + if (!doing_multilink) { + ppp_notice("Connection terminated."); +#if PPP_STATS_SUPPORT + print_link_stats(); +#endif /* PPP_STATS_SUPPORT */ + } else + ppp_notice("Link terminated."); + + lcp_lowerdown(pcb); + + ppp_link_terminated(pcb); +#if 0 + /* + * Delete pid files before disestablishing ppp. Otherwise it + * can happen that another pppd gets the same unit and then + * we delete its pid file. + */ + if (!doing_multilink && !demand) + remove_pidfiles(); + + /* + * If we may want to bring the link up again, transfer + * the ppp unit back to the loopback. Set the + * real serial device back to its normal mode of operation. + */ + if (fd_ppp >= 0) { + remove_fd(fd_ppp); + clean_check(); + the_channel->disestablish_ppp(devfd); + if (doing_multilink) + mp_exit_bundle(); + fd_ppp = -1; + } + if (!hungup) + lcp_lowerdown(pcb); + if (!doing_multilink && !demand) + script_unsetenv("IFNAME"); + + /* + * Run disconnector script, if requested. + * XXX we may not be able to do this if the line has hung up! + */ + if (devfd >= 0 && the_channel->disconnect) { + the_channel->disconnect(); + devfd = -1; + } + if (the_channel->cleanup) + (*the_channel->cleanup)(); + + if (doing_multilink && multilink_master) { + if (!bundle_terminating) + new_phase(pcb, PPP_PHASE_MASTER); + else + mp_bundle_terminated(); + } else + new_phase(pcb, PPP_PHASE_DEAD); +#endif +} + +/* + * LCP has gone down; it will either die or try to re-establish. + */ +void link_down(ppp_pcb *pcb) { +#if PPP_NOTIFY + notify(link_down_notifier, 0); +#endif /* PPP_NOTIFY */ + + if (!doing_multilink) { + upper_layers_down(pcb); + if (pcb->phase != PPP_PHASE_DEAD +#ifdef HAVE_MULTILINK + && pcb->phase != PPP_PHASE_MASTER +#endif /* HAVE_MULTILINK */ + ) + new_phase(pcb, PPP_PHASE_ESTABLISH); + } + /* XXX if doing_multilink, should do something to stop + network-layer traffic on the link */ +} + +void upper_layers_down(ppp_pcb *pcb) { + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) + (*protp->lowerdown)(pcb); + if (protp->protocol < 0xC000 && protp->close != NULL) + (*protp->close)(pcb, "LCP down"); + } + pcb->num_np_open = 0; + pcb->num_np_up = 0; +} + +/* + * The link is established. + * Proceed to the Dead, Authenticate or Network phase as appropriate. + */ +void link_established(ppp_pcb *pcb) { +#if PPP_AUTH_SUPPORT + int auth; +#if PPP_SERVER +#if PAP_SUPPORT + lcp_options *wo = &pcb->lcp_wantoptions; +#endif /* PAP_SUPPORT */ + lcp_options *go = &pcb->lcp_gotoptions; +#endif /* PPP_SERVER */ + lcp_options *ho = &pcb->lcp_hisoptions; +#endif /* PPP_AUTH_SUPPORT */ + int i; + const struct protent *protp; + + /* + * Tell higher-level protocols that LCP is up. + */ + if (!doing_multilink) { + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol != PPP_LCP + && protp->lowerup != NULL) + (*protp->lowerup)(pcb); + } + +#if PPP_AUTH_SUPPORT +#if PPP_SERVER +#if PPP_ALLOWED_ADDRS + if (!auth_required && noauth_addrs != NULL) + set_allowed_addrs(unit, NULL, NULL); +#endif /* PPP_ALLOWED_ADDRS */ + + if (pcb->settings.auth_required && !(0 +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + )) { + +#if PPP_ALLOWED_ADDRS + /* + * We wanted the peer to authenticate itself, and it refused: + * if we have some address(es) it can use without auth, fine, + * otherwise treat it as though it authenticated with PAP using + * a username of "" and a password of "". If that's not OK, + * boot it out. + */ + if (noauth_addrs != NULL) { + set_allowed_addrs(unit, NULL, NULL); + } else +#endif /* PPP_ALLOWED_ADDRS */ + if (!pcb->settings.null_login +#if PAP_SUPPORT + || !wo->neg_upap +#endif /* PAP_SUPPORT */ + ) { + ppp_warn("peer refused to authenticate: terminating link"); +#if 0 /* UNUSED */ + status = EXIT_PEER_AUTH_FAILED; +#endif /* UNUSED */ + pcb->err_code = PPPERR_AUTHFAIL; + lcp_close(pcb, "peer refused to authenticate"); + return; + } + } +#endif /* PPP_SERVER */ + + new_phase(pcb, PPP_PHASE_AUTHENTICATE); + auth = 0; +#if PPP_SERVER +#if EAP_SUPPORT + if (go->neg_eap) { + eap_authpeer(pcb, PPP_OUR_NAME); + auth |= EAP_PEER; + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (go->neg_chap) { + chap_auth_peer(pcb, PPP_OUR_NAME, CHAP_DIGEST(go->chap_mdtype)); + auth |= CHAP_PEER; + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if (go->neg_upap) { + upap_authpeer(pcb); + auth |= PAP_PEER; + } else +#endif /* PAP_SUPPORT */ + {} +#endif /* PPP_SERVER */ + +#if EAP_SUPPORT + if (ho->neg_eap) { + eap_authwithpeer(pcb, pcb->settings.user); + auth |= EAP_WITHPEER; + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (ho->neg_chap) { + chap_auth_with_peer(pcb, pcb->settings.user, CHAP_DIGEST(ho->chap_mdtype)); + auth |= CHAP_WITHPEER; + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if (ho->neg_upap) { + upap_authwithpeer(pcb, pcb->settings.user, pcb->settings.passwd); + auth |= PAP_WITHPEER; + } else +#endif /* PAP_SUPPORT */ + {} + + pcb->auth_pending = auth; + pcb->auth_done = 0; + + if (!auth) +#endif /* PPP_AUTH_SUPPORT */ + network_phase(pcb); +} + +/* + * Proceed to the network phase. + */ +static void network_phase(ppp_pcb *pcb) { +#if CBCP_SUPPORT + ppp_pcb *pcb = &ppp_pcb_list[unit]; +#endif +#if 0 /* UNUSED */ + lcp_options *go = &lcp_gotoptions[unit]; +#endif /* UNUSED */ + +#if 0 /* UNUSED */ + /* Log calling number. */ + if (*remote_number) + ppp_notice("peer from calling number %q authorized", remote_number); +#endif /* UNUSED */ + +#if PPP_NOTIFY + /* + * If the peer had to authenticate, notify it now. + */ + if (0 +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + ) { + notify(auth_up_notifier, 0); + } +#endif /* PPP_NOTIFY */ + +#if CBCP_SUPPORT + /* + * If we negotiated callback, do it now. + */ + if (go->neg_cbcp) { + new_phase(pcb, PPP_PHASE_CALLBACK); + (*cbcp_protent.open)(pcb); + return; + } +#endif + +#if PPP_OPTIONS + /* + * Process extra options from the secrets file + */ + if (extra_options) { + options_from_list(extra_options, 1); + free_wordlist(extra_options); + extra_options = 0; + } +#endif /* PPP_OPTIONS */ + start_networks(pcb); +} + +void start_networks(ppp_pcb *pcb) { +#if CCP_SUPPORT || ECP_SUPPORT + int i; + const struct protent *protp; +#endif /* CCP_SUPPORT || ECP_SUPPORT */ + + new_phase(pcb, PPP_PHASE_NETWORK); + +#ifdef HAVE_MULTILINK + if (multilink) { + if (mp_join_bundle()) { + if (multilink_join_hook) + (*multilink_join_hook)(); + if (updetach && !nodetach) + detach(); + return; + } + } +#endif /* HAVE_MULTILINK */ + +#ifdef PPP_FILTER + if (!demand) + set_filters(&pass_filter, &active_filter); +#endif +#if CCP_SUPPORT || ECP_SUPPORT + /* Start CCP and ECP */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if ( + (0 +#if ECP_SUPPORT + || protp->protocol == PPP_ECP +#endif /* ECP_SUPPORT */ +#if CCP_SUPPORT + || protp->protocol == PPP_CCP +#endif /* CCP_SUPPORT */ + ) + && protp->open != NULL) + (*protp->open)(pcb); +#endif /* CCP_SUPPORT || ECP_SUPPORT */ + + /* + * Bring up other network protocols iff encryption is not required. + */ + if (1 +#if ECP_SUPPORT + && !ecp_gotoptions[unit].required +#endif /* ECP_SUPPORT */ +#if MPPE_SUPPORT + && !pcb->ccp_gotoptions.mppe +#endif /* MPPE_SUPPORT */ + ) + continue_networks(pcb); +} + +void continue_networks(ppp_pcb *pcb) { + int i; + const struct protent *protp; + + /* + * Start the "real" network protocols. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol < 0xC000 +#if CCP_SUPPORT + && protp->protocol != PPP_CCP +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT + && protp->protocol != PPP_ECP +#endif /* ECP_SUPPORT */ + && protp->open != NULL) { + (*protp->open)(pcb); + ++pcb->num_np_open; + } + + if (pcb->num_np_open == 0) + /* nothing to do */ + lcp_close(pcb, "No network protocols running"); +} + +#if PPP_AUTH_SUPPORT +#if PPP_SERVER +/* + * auth_check_passwd - Check the user name and passwd against configuration. + * + * returns: + * 0: Authentication failed. + * 1: Authentication succeeded. + * In either case, msg points to an appropriate message and msglen to the message len. + */ +int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen) { + int secretuserlen; + int secretpasswdlen; + + if (pcb->settings.user && pcb->settings.passwd) { + secretuserlen = (int)strlen(pcb->settings.user); + secretpasswdlen = (int)strlen(pcb->settings.passwd); + if (secretuserlen == userlen + && secretpasswdlen == passwdlen + && !memcmp(auser, pcb->settings.user, userlen) + && !memcmp(apasswd, pcb->settings.passwd, passwdlen) ) { + *msg = "Login ok"; + *msglen = sizeof("Login ok")-1; + return 1; + } + } + + *msg = "Login incorrect"; + *msglen = sizeof("Login incorrect")-1; + return 0; +} + +/* + * The peer has failed to authenticate himself using `protocol'. + */ +void auth_peer_fail(ppp_pcb *pcb, int protocol) { + LWIP_UNUSED_ARG(protocol); + /* + * Authentication failure: take the link down + */ +#if 0 /* UNUSED */ + status = EXIT_PEER_AUTH_FAILED; +#endif /* UNUSED */ + pcb->err_code = PPPERR_AUTHFAIL; + lcp_close(pcb, "Authentication failed"); +} + +/* + * The peer has been successfully authenticated using `protocol'. + */ +void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen) { + int bit; +#ifndef HAVE_MULTILINK + LWIP_UNUSED_ARG(name); + LWIP_UNUSED_ARG(namelen); +#endif /* HAVE_MULTILINK */ + + switch (protocol) { +#if CHAP_SUPPORT + case PPP_CHAP: + bit = CHAP_PEER; + switch (prot_flavor) { + case CHAP_MD5: + bit |= CHAP_MD5_PEER; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + bit |= CHAP_MS_PEER; + break; + case CHAP_MICROSOFT_V2: + bit |= CHAP_MS2_PEER; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + break; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + case PPP_PAP: + bit = PAP_PEER; + break; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + bit = EAP_PEER; + break; +#endif /* EAP_SUPPORT */ + default: + ppp_warn("auth_peer_success: unknown protocol %x", protocol); + return; + } + +#ifdef HAVE_MULTILINK + /* + * Save the authenticated name of the peer for later. + */ + if (namelen > (int)sizeof(pcb->peer_authname) - 1) + namelen = (int)sizeof(pcb->peer_authname) - 1; + MEMCPY(pcb->peer_authname, name, namelen); + pcb->peer_authname[namelen] = 0; +#endif /* HAVE_MULTILINK */ +#if 0 /* UNUSED */ + script_setenv("PEERNAME", , 0); +#endif /* UNUSED */ + + /* Save the authentication method for later. */ + pcb->auth_done |= bit; + + /* + * If there is no more authentication still to be done, + * proceed to the network (or callback) phase. + */ + if ((pcb->auth_pending &= ~bit) == 0) + network_phase(pcb); +} +#endif /* PPP_SERVER */ + +/* + * We have failed to authenticate ourselves to the peer using `protocol'. + */ +void auth_withpeer_fail(ppp_pcb *pcb, int protocol) { + LWIP_UNUSED_ARG(protocol); + /* + * We've failed to authenticate ourselves to our peer. + * + * Some servers keep sending CHAP challenges, but there + * is no point in persisting without any way to get updated + * authentication secrets. + * + * He'll probably take the link down, and there's not much + * we can do except wait for that. + */ + pcb->err_code = PPPERR_AUTHFAIL; + lcp_close(pcb, "Failed to authenticate ourselves to peer"); +} + +/* + * We have successfully authenticated ourselves with the peer using `protocol'. + */ +void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor) { + int bit; + const char *prot = ""; + + switch (protocol) { +#if CHAP_SUPPORT + case PPP_CHAP: + bit = CHAP_WITHPEER; + prot = "CHAP"; + switch (prot_flavor) { + case CHAP_MD5: + bit |= CHAP_MD5_WITHPEER; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + bit |= CHAP_MS_WITHPEER; + break; + case CHAP_MICROSOFT_V2: + bit |= CHAP_MS2_WITHPEER; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + break; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + case PPP_PAP: + bit = PAP_WITHPEER; + prot = "PAP"; + break; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + bit = EAP_WITHPEER; + prot = "EAP"; + break; +#endif /* EAP_SUPPORT */ + default: + ppp_warn("auth_withpeer_success: unknown protocol %x", protocol); + bit = 0; + /* no break */ + } + + ppp_notice("%s authentication succeeded", prot); + + /* Save the authentication method for later. */ + pcb->auth_done |= bit; + + /* + * If there is no more authentication still being done, + * proceed to the network (or callback) phase. + */ + if ((pcb->auth_pending &= ~bit) == 0) + network_phase(pcb); +} +#endif /* PPP_AUTH_SUPPORT */ + + +/* + * np_up - a network protocol has come up. + */ +void np_up(ppp_pcb *pcb, int proto) { +#if PPP_IDLETIMELIMIT + int tlim; +#endif /* PPP_IDLETIMELIMIT */ + LWIP_UNUSED_ARG(proto); + + if (pcb->num_np_up == 0) { + /* + * At this point we consider that the link has come up successfully. + */ + new_phase(pcb, PPP_PHASE_RUNNING); + +#if PPP_IDLETIMELIMIT +#if 0 /* UNUSED */ + if (idle_time_hook != 0) + tlim = (*idle_time_hook)(NULL); + else +#endif /* UNUSED */ + tlim = pcb->settings.idle_time_limit; + if (tlim > 0) + TIMEOUT(check_idle, (void*)pcb, tlim); +#endif /* PPP_IDLETIMELIMIT */ + +#if PPP_MAXCONNECT + /* + * Set a timeout to close the connection once the maximum + * connect time has expired. + */ + if (pcb->settings.maxconnect > 0) + TIMEOUT(connect_time_expired, (void*)pcb, pcb->settings.maxconnect); +#endif /* PPP_MAXCONNECT */ + +#ifdef MAXOCTETS + if (maxoctets > 0) + TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); +#endif + +#if 0 /* Unused */ + /* + * Detach now, if the updetach option was given. + */ + if (updetach && !nodetach) + detach(); +#endif /* Unused */ + } + ++pcb->num_np_up; +} + +/* + * np_down - a network protocol has gone down. + */ +void np_down(ppp_pcb *pcb, int proto) { + LWIP_UNUSED_ARG(proto); + if (--pcb->num_np_up == 0) { +#if PPP_IDLETIMELIMIT + UNTIMEOUT(check_idle, (void*)pcb); +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT + UNTIMEOUT(connect_time_expired, NULL); +#endif /* PPP_MAXCONNECT */ +#ifdef MAXOCTETS + UNTIMEOUT(check_maxoctets, NULL); +#endif + new_phase(pcb, PPP_PHASE_NETWORK); + } +} + +/* + * np_finished - a network protocol has finished using the link. + */ +void np_finished(ppp_pcb *pcb, int proto) { + LWIP_UNUSED_ARG(proto); + if (--pcb->num_np_open <= 0) { + /* no further use for the link: shut up shop. */ + lcp_close(pcb, "No network protocols running"); + } +} + +#ifdef MAXOCTETS +static void +check_maxoctets(arg) + void *arg; +{ +#if PPP_STATS_SUPPORT + unsigned int used; + + update_link_stats(ifunit); + link_stats_valid=0; + + switch(maxoctets_dir) { + case PPP_OCTETS_DIRECTION_IN: + used = link_stats.bytes_in; + break; + case PPP_OCTETS_DIRECTION_OUT: + used = link_stats.bytes_out; + break; + case PPP_OCTETS_DIRECTION_MAXOVERAL: + case PPP_OCTETS_DIRECTION_MAXSESSION: + used = (link_stats.bytes_in > link_stats.bytes_out) ? link_stats.bytes_in : link_stats.bytes_out; + break; + default: + used = link_stats.bytes_in+link_stats.bytes_out; + break; + } + if (used > maxoctets) { + ppp_notice("Traffic limit reached. Limit: %u Used: %u", maxoctets, used); + status = EXIT_TRAFFIC_LIMIT; + lcp_close(pcb, "Traffic limit"); +#if 0 /* UNUSED */ + need_holdoff = 0; +#endif /* UNUSED */ + } else { + TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); + } +#endif /* PPP_STATS_SUPPORT */ +} +#endif /* MAXOCTETS */ + +#if PPP_IDLETIMELIMIT +/* + * check_idle - check whether the link has been idle for long + * enough that we can shut it down. + */ +static void check_idle(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + struct ppp_idle idle; + time_t itime; + int tlim; + + if (!get_idle_time(pcb, &idle)) + return; +#if 0 /* UNUSED */ + if (idle_time_hook != 0) { + tlim = idle_time_hook(&idle); + } else { +#endif /* UNUSED */ + itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); + tlim = pcb->settings.idle_time_limit - itime; +#if 0 /* UNUSED */ + } +#endif /* UNUSED */ + if (tlim <= 0) { + /* link is idle: shut it down. */ + ppp_notice("Terminating connection due to lack of activity."); + pcb->err_code = PPPERR_IDLETIMEOUT; + lcp_close(pcb, "Link inactive"); +#if 0 /* UNUSED */ + need_holdoff = 0; +#endif /* UNUSED */ + } else { + TIMEOUT(check_idle, (void*)pcb, tlim); + } +} +#endif /* PPP_IDLETIMELIMIT */ + +#if PPP_MAXCONNECT +/* + * connect_time_expired - log a message and close the connection. + */ +static void connect_time_expired(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + ppp_info("Connect time expired"); + pcb->err_code = PPPERR_CONNECTTIME; + lcp_close(pcb, "Connect time expired"); /* Close connection */ +} +#endif /* PPP_MAXCONNECT */ + +#if PPP_OPTIONS +/* + * auth_check_options - called to check authentication options. + */ +void +auth_check_options() +{ + lcp_options *wo = &lcp_wantoptions[0]; + int can_auth; + int lacks_ip; + + /* Default our_name to hostname, and user to our_name */ + if (our_name[0] == 0 || usehostname) + strlcpy(our_name, hostname, sizeof(our_name)); + /* If a blank username was explicitly given as an option, trust + the user and don't use our_name */ + if (ppp_settings.user[0] == 0 && !explicit_user) + strlcpy(ppp_settings.user, our_name, sizeof(ppp_settings.user)); + + /* + * If we have a default route, require the peer to authenticate + * unless the noauth option was given or the real user is root. + */ + if (!auth_required && !allow_any_ip && have_route_to(0) && !privileged) { + auth_required = 1; + default_auth = 1; + } + +#if CHAP_SUPPORT + /* If we selected any CHAP flavors, we should probably negotiate it. :-) */ + if (wo->chap_mdtype) + wo->neg_chap = 1; +#endif /* CHAP_SUPPORT */ + + /* If authentication is required, ask peer for CHAP, PAP, or EAP. */ + if (auth_required) { + allow_any_ip = 0; + if (1 +#if CHAP_SUPPORT + && !wo->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + && !wo->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + && !wo->neg_eap +#endif /* EAP_SUPPORT */ + ) { +#if CHAP_SUPPORT + wo->neg_chap = CHAP_MDTYPE_SUPPORTED != MDTYPE_NONE; + wo->chap_mdtype = CHAP_MDTYPE_SUPPORTED; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + wo->neg_upap = 1; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + wo->neg_eap = 1; +#endif /* EAP_SUPPORT */ + } + } else { +#if CHAP_SUPPORT + wo->neg_chap = 0; + wo->chap_mdtype = MDTYPE_NONE; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + wo->neg_upap = 0; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + wo->neg_eap = 0; +#endif /* EAP_SUPPORT */ + } + + /* + * Check whether we have appropriate secrets to use + * to authenticate the peer. Note that EAP can authenticate by way + * of a CHAP-like exchanges as well as SRP. + */ + lacks_ip = 0; +#if PAP_SUPPORT + can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip)); +#else + can_auth = 0; +#endif /* PAP_SUPPORT */ + if (!can_auth && (0 +#if CHAP_SUPPORT + || wo->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || wo->neg_eap +#endif /* EAP_SUPPORT */ + )) { +#if CHAP_SUPPORT + can_auth = have_chap_secret((explicit_remote? remote_name: NULL), + our_name, 1, &lacks_ip); +#else + can_auth = 0; +#endif + } + if (!can_auth +#if EAP_SUPPORT + && wo->neg_eap +#endif /* EAP_SUPPORT */ + ) { + can_auth = have_srp_secret((explicit_remote? remote_name: NULL), + our_name, 1, &lacks_ip); + } + + if (auth_required && !can_auth && noauth_addrs == NULL) { + if (default_auth) { + option_error( +"By default the remote system is required to authenticate itself"); + option_error( +"(because this system has a default route to the internet)"); + } else if (explicit_remote) + option_error( +"The remote system (%s) is required to authenticate itself", + remote_name); + else + option_error( +"The remote system is required to authenticate itself"); + option_error( +"but I couldn't find any suitable secret (password) for it to use to do so."); + if (lacks_ip) + option_error( +"(None of the available passwords would let it use an IP address.)"); + + exit(1); + } + + /* + * Early check for remote number authorization. + */ + if (!auth_number()) { + ppp_warn("calling number %q is not authorized", remote_number); + exit(EXIT_CNID_AUTH_FAILED); + } +} +#endif /* PPP_OPTIONS */ + +#if 0 /* UNUSED */ +/* + * auth_reset - called when LCP is starting negotiations to recheck + * authentication options, i.e. whether we have appropriate secrets + * to use for authenticating ourselves and/or the peer. + */ +void +auth_reset(unit) + int unit; +{ + lcp_options *go = &lcp_gotoptions[unit]; + lcp_options *ao = &lcp_allowoptions[unit]; + int hadchap; + + hadchap = -1; + ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL)); + ao->neg_chap = (!refuse_chap || !refuse_mschap || !refuse_mschap_v2) + && (passwd[0] != 0 || + (hadchap = have_chap_secret(user, (explicit_remote? remote_name: + NULL), 0, NULL))); + ao->neg_eap = !refuse_eap && ( + passwd[0] != 0 || + (hadchap == 1 || (hadchap == -1 && have_chap_secret(user, + (explicit_remote? remote_name: NULL), 0, NULL))) || + have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)); + + hadchap = -1; + if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) + go->neg_upap = 0; + if (go->neg_chap) { + if (!(hadchap = have_chap_secret((explicit_remote? remote_name: NULL), + our_name, 1, NULL))) + go->neg_chap = 0; + } + if (go->neg_eap && + (hadchap == 0 || (hadchap == -1 && + !have_chap_secret((explicit_remote? remote_name: NULL), our_name, + 1, NULL))) && + !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1, + NULL)) + go->neg_eap = 0; +} + +/* + * check_passwd - Check the user name and passwd against the PAP secrets + * file. If requested, also check against the system password database, + * and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Authentication failed. + * UPAP_AUTHACK: Authentication succeeded. + * In either case, msg points to an appropriate message. + */ +int +check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) + int unit; + char *auser; + int userlen; + char *apasswd; + int passwdlen; + char **msg; +{ + return UPAP_AUTHNAK; + int ret; + char *filename; + FILE *f; + struct wordlist *addrs = NULL, *opts = NULL; + char passwd[256], user[256]; + char secret[MAXWORDLEN]; + static int attempts = 0; + + /* + * Make copies of apasswd and auser, then null-terminate them. + * If there are unprintable characters in the password, make + * them visible. + */ + slprintf(ppp_settings.passwd, sizeof(ppp_settings.passwd), "%.*v", passwdlen, apasswd); + slprintf(ppp_settings.user, sizeof(ppp_settings.user), "%.*v", userlen, auser); + *msg = ""; + + /* + * Check if a plugin wants to handle this. + */ + if (pap_auth_hook) { + ret = (*pap_auth_hook)(ppp_settings.user, ppp_settings.passwd, msg, &addrs, &opts); + if (ret >= 0) { + /* note: set_allowed_addrs() saves opts (but not addrs): + don't free it! */ + if (ret) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); + return ret? UPAP_AUTHACK: UPAP_AUTHNAK; + } + } + + /* + * Open the file of pap secrets and scan for a suitable secret + * for authenticating this user. + */ + filename = _PATH_UPAPFILE; + addrs = opts = NULL; + ret = UPAP_AUTHNAK; + f = fopen(filename, "r"); + if (f == NULL) { + ppp_error("Can't open PAP password file %s: %m", filename); + + } else { + check_access(f, filename); + if (scan_authfile(f, ppp_settings.user, our_name, secret, &addrs, &opts, filename, 0) < 0) { + ppp_warn("no PAP secret found for %s", user); + } else { + /* + * If the secret is "@login", it means to check + * the password against the login database. + */ + int login_secret = strcmp(secret, "@login") == 0; + ret = UPAP_AUTHACK; + if (uselogin || login_secret) { + /* login option or secret is @login */ + if (session_full(ppp_settings.user, ppp_settings.passwd, devnam, msg) == 0) { + ret = UPAP_AUTHNAK; + } + } else if (session_mgmt) { + if (session_check(ppp_settings.user, NULL, devnam, NULL) == 0) { + ppp_warn("Peer %q failed PAP Session verification", user); + ret = UPAP_AUTHNAK; + } + } + if (secret[0] != 0 && !login_secret) { + /* password given in pap-secrets - must match */ + if ((cryptpap || strcmp(ppp_settings.passwd, secret) != 0) + && strcmp(crypt(ppp_settings.passwd, secret), secret) != 0) + ret = UPAP_AUTHNAK; + } + } + fclose(f); + } + + if (ret == UPAP_AUTHNAK) { + if (**msg == 0) + *msg = "Login incorrect"; + /* + * XXX can we ever get here more than once?? + * Frustrate passwd stealer programs. + * Allow 10 tries, but start backing off after 3 (stolen from login). + * On 10'th, drop the connection. + */ + if (attempts++ >= 10) { + ppp_warn("%d LOGIN FAILURES ON %s, %s", attempts, devnam, user); + lcp_close(pcb, "login failed"); + } + if (attempts > 3) + sleep((u_int) (attempts - 3) * 5); + if (opts != NULL) + free_wordlist(opts); + + } else { + attempts = 0; /* Reset count */ + if (**msg == 0) + *msg = "Login ok"; + set_allowed_addrs(unit, addrs, opts); + } + + if (addrs != NULL) + free_wordlist(addrs); + BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); + BZERO(secret, sizeof(secret)); + + return ret; +} + +/* + * null_login - Check if a username of "" and a password of "" are + * acceptable, and iff so, set the list of acceptable IP addresses + * and return 1. + */ +static int +null_login(unit) + int unit; +{ + char *filename; + FILE *f; + int i, ret; + struct wordlist *addrs, *opts; + char secret[MAXWORDLEN]; + + /* + * Check if a plugin wants to handle this. + */ + ret = -1; + if (null_auth_hook) + ret = (*null_auth_hook)(&addrs, &opts); + + /* + * Open the file of pap secrets and scan for a suitable secret. + */ + if (ret <= 0) { + filename = _PATH_UPAPFILE; + addrs = NULL; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + check_access(f, filename); + + i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename, 0); + ret = i >= 0 && secret[0] == 0; + BZERO(secret, sizeof(secret)); + fclose(f); + } + + if (ret) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + + return ret; +} + +/* + * get_pap_passwd - get a password for authenticating ourselves with + * our peer using PAP. Returns 1 on success, 0 if no suitable password + * could be found. + * Assumes passwd points to MAXSECRETLEN bytes of space (if non-null). + */ +static int +get_pap_passwd(passwd) + char *passwd; +{ + char *filename; + FILE *f; + int ret; + char secret[MAXWORDLEN]; + + /* + * Check whether a plugin wants to supply this. + */ + if (pap_passwd_hook) { + ret = (*pap_passwd_hook)(ppp_settings,user, ppp_settings.passwd); + if (ret >= 0) + return ret; + } + + filename = _PATH_UPAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + check_access(f, filename); + ret = scan_authfile(f, user, + (remote_name[0]? remote_name: NULL), + secret, NULL, NULL, filename, 0); + fclose(f); + if (ret < 0) + return 0; + if (passwd != NULL) + strlcpy(passwd, secret, MAXSECRETLEN); + BZERO(secret, sizeof(secret)); + return 1; +} + +/* + * have_pap_secret - check whether we have a PAP file with any + * secrets that we could possibly use for authenticating the peer. + */ +static int +have_pap_secret(lacks_ipp) + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + /* let the plugin decide, if there is one */ + if (pap_check_hook) { + ret = (*pap_check_hook)(); + if (ret >= 0) + return ret; + } + + filename = _PATH_UPAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + ret = scan_authfile(f, (explicit_remote? remote_name: NULL), our_name, + NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} + +/* + * have_chap_secret - check whether we have a CHAP file with a + * secret that we could possibly use for authenticating `client' + * on `server'. Either can be the null string, meaning we don't + * know the identity yet. + */ +static int +have_chap_secret(client, server, need_ip, lacks_ipp) + char *client; + char *server; + int need_ip; + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + if (chap_check_hook) { + ret = (*chap_check_hook)(); + if (ret >= 0) { + return ret; + } + } + + filename = _PATH_CHAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + if (client != NULL && client[0] == 0) + client = NULL; + else if (server != NULL && server[0] == 0) + server = NULL; + + ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} + +/* + * have_srp_secret - check whether we have a SRP file with a + * secret that we could possibly use for authenticating `client' + * on `server'. Either can be the null string, meaning we don't + * know the identity yet. + */ +static int +have_srp_secret(client, server, need_ip, lacks_ipp) + char *client; + char *server; + int need_ip; + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + filename = _PATH_SRPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + if (client != NULL && client[0] == 0) + client = NULL; + else if (server != NULL && server[0] == 0) + server = NULL; + + ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} +#endif /* UNUSED */ + +#if PPP_AUTH_SUPPORT +/* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server) { + int len; + LWIP_UNUSED_ARG(server); + LWIP_UNUSED_ARG(am_server); + + if (!client || !client[0] || !pcb->settings.user || !pcb->settings.passwd || strcmp(client, pcb->settings.user)) { + return 0; + } + + len = (int)strlen(pcb->settings.passwd); + if (len > MAXSECRETLEN) { + ppp_error("Secret for %s on %s is too long", client, server); + len = MAXSECRETLEN; + } + + MEMCPY(secret, pcb->settings.passwd, len); + *secret_len = len; + return 1; + +#if 0 /* UNUSED */ + FILE *f; + int ret, len; + char *filename; + struct wordlist *addrs, *opts; + char secbuf[MAXWORDLEN]; + struct wordlist *addrs; + addrs = NULL; + + if (!am_server && ppp_settings.passwd[0] != 0) { + strlcpy(secbuf, ppp_settings.passwd, sizeof(secbuf)); + } else if (!am_server && chap_passwd_hook) { + if ( (*chap_passwd_hook)(client, secbuf) < 0) { + ppp_error("Unable to obtain CHAP password for %s on %s from plugin", + client, server); + return 0; + } + } else { + filename = _PATH_CHAPFILE; + addrs = NULL; + secbuf[0] = 0; + + f = fopen(filename, "r"); + if (f == NULL) { + ppp_error("Can't open chap secret file %s: %m", filename); + return 0; + } + check_access(f, filename); + + ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, filename, 0); + fclose(f); + if (ret < 0) + return 0; + + if (am_server) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + } + + len = strlen(secbuf); + if (len > MAXSECRETLEN) { + ppp_error("Secret for %s on %s is too long", client, server); + len = MAXSECRETLEN; + } + MEMCPY(secret, secbuf, len); + BZERO(secbuf, sizeof(secbuf)); + *secret_len = len; + + return 1; +#endif /* UNUSED */ +} +#endif /* PPP_AUTH_SUPPORT */ + + +#if 0 /* UNUSED */ +/* + * get_srp_secret - open the SRP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int +get_srp_secret(unit, client, server, secret, am_server) + int unit; + char *client; + char *server; + char *secret; + int am_server; +{ + FILE *fp; + int ret; + char *filename; + struct wordlist *addrs, *opts; + + if (!am_server && ppp_settings.passwd[0] != '\0') { + strlcpy(secret, ppp_settings.passwd, MAXWORDLEN); + } else { + filename = _PATH_SRPFILE; + addrs = NULL; + + fp = fopen(filename, "r"); + if (fp == NULL) { + ppp_error("Can't open srp secret file %s: %m", filename); + return 0; + } + check_access(fp, filename); + + secret[0] = '\0'; + ret = scan_authfile(fp, client, server, secret, &addrs, &opts, + filename, am_server); + fclose(fp); + if (ret < 0) + return 0; + + if (am_server) + set_allowed_addrs(unit, addrs, opts); + else if (opts != NULL) + free_wordlist(opts); + if (addrs != NULL) + free_wordlist(addrs); + } + + return 1; +} + +/* + * set_allowed_addrs() - set the list of allowed addresses. + * Also looks for `--' indicating options to apply for this peer + * and leaves the following words in extra_options. + */ +static void +set_allowed_addrs(unit, addrs, opts) + int unit; + struct wordlist *addrs; + struct wordlist *opts; +{ + int n; + struct wordlist *ap, **plink; + struct permitted_ip *ip; + char *ptr_word, *ptr_mask; + struct hostent *hp; + struct netent *np; + u32_t a, mask, ah, offset; + struct ipcp_options *wo = &ipcp_wantoptions[unit]; + u32_t suggested_ip = 0; + + if (addresses[unit] != NULL) + free(addresses[unit]); + addresses[unit] = NULL; + if (extra_options != NULL) + free_wordlist(extra_options); + extra_options = opts; + + /* + * Count the number of IP addresses given. + */ + n = wordlist_count(addrs) + wordlist_count(noauth_addrs); + if (n == 0) + return; + ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip)); + if (ip == 0) + return; + + /* temporarily append the noauth_addrs list to addrs */ + for (plink = &addrs; *plink != NULL; plink = &(*plink)->next) + ; + *plink = noauth_addrs; + + n = 0; + for (ap = addrs; ap != NULL; ap = ap->next) { + /* "-" means no addresses authorized, "*" means any address allowed */ + ptr_word = ap->word; + if (strcmp(ptr_word, "-") == 0) + break; + if (strcmp(ptr_word, "*") == 0) { + ip[n].permit = 1; + ip[n].base = ip[n].mask = 0; + ++n; + break; + } + + ip[n].permit = 1; + if (*ptr_word == '!') { + ip[n].permit = 0; + ++ptr_word; + } + + mask = ~ (u32_t) 0; + offset = 0; + ptr_mask = strchr (ptr_word, '/'); + if (ptr_mask != NULL) { + int bit_count; + char *endp; + + bit_count = (int) strtol (ptr_mask+1, &endp, 10); + if (bit_count <= 0 || bit_count > 32) { + ppp_warn("invalid address length %v in auth. address list", + ptr_mask+1); + continue; + } + bit_count = 32 - bit_count; /* # bits in host part */ + if (*endp == '+') { + offset = ifunit + 1; + ++endp; + } + if (*endp != 0) { + ppp_warn("invalid address length syntax: %v", ptr_mask+1); + continue; + } + *ptr_mask = '\0'; + mask <<= bit_count; + } + + hp = gethostbyname(ptr_word); + if (hp != NULL && hp->h_addrtype == AF_INET) { + a = *(u32_t *)hp->h_addr; + } else { + np = getnetbyname (ptr_word); + if (np != NULL && np->n_addrtype == AF_INET) { + a = lwip_htonl ((u32_t)np->n_net); + if (ptr_mask == NULL) { + /* calculate appropriate mask for net */ + ah = lwip_ntohl(a); + if (IN_CLASSA(ah)) + mask = IN_CLASSA_NET; + else if (IN_CLASSB(ah)) + mask = IN_CLASSB_NET; + else if (IN_CLASSC(ah)) + mask = IN_CLASSC_NET; + } + } else { + a = inet_addr (ptr_word); + } + } + + if (ptr_mask != NULL) + *ptr_mask = '/'; + + if (a == (u32_t)-1L) { + ppp_warn("unknown host %s in auth. address list", ap->word); + continue; + } + if (offset != 0) { + if (offset >= ~mask) { + ppp_warn("interface unit %d too large for subnet %v", + ifunit, ptr_word); + continue; + } + a = lwip_htonl((lwip_ntohl(a) & mask) + offset); + mask = ~(u32_t)0; + } + ip[n].mask = lwip_htonl(mask); + ip[n].base = a & ip[n].mask; + ++n; + if (~mask == 0 && suggested_ip == 0) + suggested_ip = a; + } + *plink = NULL; + + ip[n].permit = 0; /* make the last entry forbid all addresses */ + ip[n].base = 0; /* to terminate the list */ + ip[n].mask = 0; + + addresses[unit] = ip; + + /* + * If the address given for the peer isn't authorized, or if + * the user hasn't given one, AND there is an authorized address + * which is a single host, then use that if we find one. + */ + if (suggested_ip != 0 + && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) { + wo->hisaddr = suggested_ip; + /* + * Do we insist on this address? No, if there are other + * addresses authorized than the suggested one. + */ + if (n > 1) + wo->accept_remote = 1; + } +} + +/* + * auth_ip_addr - check whether the peer is authorized to use + * a given IP address. Returns 1 if authorized, 0 otherwise. + */ +int +auth_ip_addr(unit, addr) + int unit; + u32_t addr; +{ + int ok; + + /* don't allow loopback or multicast address */ + if (bad_ip_adrs(addr)) + return 0; + + if (allowed_address_hook) { + ok = allowed_address_hook(addr); + if (ok >= 0) return ok; + } + + if (addresses[unit] != NULL) { + ok = ip_addr_check(addr, addresses[unit]); + if (ok >= 0) + return ok; + } + + if (auth_required) + return 0; /* no addresses authorized */ + return allow_any_ip || privileged || !have_route_to(addr); +} + +static int +ip_addr_check(addr, addrs) + u32_t addr; + struct permitted_ip *addrs; +{ + for (; ; ++addrs) + if ((addr & addrs->mask) == addrs->base) + return addrs->permit; +} + +/* + * bad_ip_adrs - return 1 if the IP address is one we don't want + * to use, such as an address in the loopback net or a multicast address. + * addr is in network byte order. + */ +int +bad_ip_adrs(addr) + u32_t addr; +{ + addr = lwip_ntohl(addr); + return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET + || IN_MULTICAST(addr) || IN_BADCLASS(addr); +} + +/* + * some_ip_ok - check a wordlist to see if it authorizes any + * IP address(es). + */ +static int +some_ip_ok(addrs) + struct wordlist *addrs; +{ + for (; addrs != 0; addrs = addrs->next) { + if (addrs->word[0] == '-') + break; + if (addrs->word[0] != '!') + return 1; /* some IP address is allowed */ + } + return 0; +} + +/* + * auth_number - check whether the remote number is allowed to connect. + * Returns 1 if authorized, 0 otherwise. + */ +int +auth_number() +{ + struct wordlist *wp = permitted_numbers; + int l; + + /* Allow all if no authorization list. */ + if (!wp) + return 1; + + /* Allow if we have a match in the authorization list. */ + while (wp) { + /* trailing '*' wildcard */ + l = strlen(wp->word); + if ((wp->word)[l - 1] == '*') + l--; + if (!strncasecmp(wp->word, remote_number, l)) + return 1; + wp = wp->next; + } + + return 0; +} + +/* + * check_access - complain if a secret file has too-liberal permissions. + */ +static void +check_access(f, filename) + FILE *f; + char *filename; +{ + struct stat sbuf; + + if (fstat(fileno(f), &sbuf) < 0) { + ppp_warn("cannot stat secret file %s: %m", filename); + } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { + ppp_warn("Warning - secret file %s has world and/or group access", + filename); + } +} + +/* + * scan_authfile - Scan an authorization file for a secret suitable + * for authenticating `client' on `server'. The return value is -1 + * if no secret is found, otherwise >= 0. The return value has + * NONWILD_CLIENT set if the secret didn't have "*" for the client, and + * NONWILD_SERVER set if the secret didn't have "*" for the server. + * Any following words on the line up to a "--" (i.e. address authorization + * info) are placed in a wordlist and returned in *addrs. Any + * following words (extra options) are placed in a wordlist and + * returned in *opts. + * We assume secret is NULL or points to MAXWORDLEN bytes of space. + * Flags are non-zero if we need two colons in the secret in order to + * match. + */ +static int +scan_authfile(f, client, server, secret, addrs, opts, filename, flags) + FILE *f; + char *client; + char *server; + char *secret; + struct wordlist **addrs; + struct wordlist **opts; + char *filename; + int flags; +{ + int newline, xxx; + int got_flag, best_flag; + FILE *sf; + struct wordlist *ap, *addr_list, *alist, **app; + char word[MAXWORDLEN]; + char atfile[MAXWORDLEN]; + char lsecret[MAXWORDLEN]; + char *cp; + + if (addrs != NULL) + *addrs = NULL; + if (opts != NULL) + *opts = NULL; + addr_list = NULL; + if (!getword(f, word, &newline, filename)) + return -1; /* file is empty??? */ + newline = 1; + best_flag = -1; + for (;;) { + /* + * Skip until we find a word at the start of a line. + */ + while (!newline && getword(f, word, &newline, filename)) + ; + if (!newline) + break; /* got to end of file */ + + /* + * Got a client - check if it's a match or a wildcard. + */ + got_flag = 0; + if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) { + newline = 0; + continue; + } + if (!ISWILD(word)) + got_flag = NONWILD_CLIENT; + + /* + * Now get a server and check if it matches. + */ + if (!getword(f, word, &newline, filename)) + break; + if (newline) + continue; + if (!ISWILD(word)) { + if (server != NULL && strcmp(word, server) != 0) + continue; + got_flag |= NONWILD_SERVER; + } + + /* + * Got some sort of a match - see if it's better than what + * we have already. + */ + if (got_flag <= best_flag) + continue; + + /* + * Get the secret. + */ + if (!getword(f, word, &newline, filename)) + break; + if (newline) + continue; + + /* + * SRP-SHA1 authenticator should never be reading secrets from + * a file. (Authenticatee may, though.) + */ + if (flags && ((cp = strchr(word, ':')) == NULL || + strchr(cp + 1, ':') == NULL)) + continue; + + if (secret != NULL) { + /* + * Special syntax: @/pathname means read secret from file. + */ + if (word[0] == '@' && word[1] == '/') { + strlcpy(atfile, word+1, sizeof(atfile)); + if ((sf = fopen(atfile, "r")) == NULL) { + ppp_warn("can't open indirect secret file %s", atfile); + continue; + } + check_access(sf, atfile); + if (!getword(sf, word, &xxx, atfile)) { + ppp_warn("no secret in indirect secret file %s", atfile); + fclose(sf); + continue; + } + fclose(sf); + } + strlcpy(lsecret, word, sizeof(lsecret)); + } + + /* + * Now read address authorization info and make a wordlist. + */ + app = &alist; + for (;;) { + if (!getword(f, word, &newline, filename) || newline) + break; + ap = (struct wordlist *) + malloc(sizeof(struct wordlist) + strlen(word) + 1); + if (ap == NULL) + novm("authorized addresses"); + ap->word = (char *) (ap + 1); + strcpy(ap->word, word); + *app = ap; + app = &ap->next; + } + *app = NULL; + + /* + * This is the best so far; remember it. + */ + best_flag = got_flag; + if (addr_list) + free_wordlist(addr_list); + addr_list = alist; + if (secret != NULL) + strlcpy(secret, lsecret, MAXWORDLEN); + + if (!newline) + break; + } + + /* scan for a -- word indicating the start of options */ + for (app = &addr_list; (ap = *app) != NULL; app = &ap->next) + if (strcmp(ap->word, "--") == 0) + break; + /* ap = start of options */ + if (ap != NULL) { + ap = ap->next; /* first option */ + free(*app); /* free the "--" word */ + *app = NULL; /* terminate addr list */ + } + if (opts != NULL) + *opts = ap; + else if (ap != NULL) + free_wordlist(ap); + if (addrs != NULL) + *addrs = addr_list; + else if (addr_list != NULL) + free_wordlist(addr_list); + + return best_flag; +} + +/* + * wordlist_count - return the number of items in a wordlist + */ +static int +wordlist_count(wp) + struct wordlist *wp; +{ + int n; + + for (n = 0; wp != NULL; wp = wp->next) + ++n; + return n; +} + +/* + * free_wordlist - release memory allocated for a wordlist. + */ +static void +free_wordlist(wp) + struct wordlist *wp; +{ + struct wordlist *next; + + while (wp != NULL) { + next = wp->next; + free(wp); + wp = next; + } +} +#endif /* UNUSED */ + +#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/ccp.c b/components/net/lwip-2.0.3/src/netif/ppp/ccp.c new file mode 100644 index 0000000000..f8519ebece --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/ccp.c @@ -0,0 +1,1740 @@ +/* + * ccp.c - PPP Compression Control Protocol. + * + * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ccp.h" + +#if MPPE_SUPPORT +#include "netif/ppp/lcp.h" /* lcp_close(), lcp_fsm */ +#include "netif/ppp/mppe.h" /* mppe_init() */ +#endif /* MPPE_SUPPORT */ + +/* + * Unfortunately there is a bug in zlib which means that using a + * size of 8 (window size = 256) for Deflate compression will cause + * buffer overruns and kernel crashes in the deflate module. + * Until this is fixed we only accept sizes in the range 9 .. 15. + * Thanks to James Carlson for pointing this out. + */ +#define DEFLATE_MIN_WORKS 9 + +/* + * Command-line options. + */ +#if PPP_OPTIONS +static int setbsdcomp (char **); +static int setdeflate (char **); +static char bsd_value[8]; +static char deflate_value[8]; + +/* + * Option variables. + */ +#if MPPE_SUPPORT +bool refuse_mppe_stateful = 1; /* Allow stateful mode? */ +#endif /* MPPE_SUPPORT */ + +static option_t ccp_option_list[] = { + { "noccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation" }, + { "-ccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation", OPT_ALIAS }, + + { "bsdcomp", o_special, (void *)setbsdcomp, + "Request BSD-Compress packet compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value }, + { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].bsd_compress }, + { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].bsd_compress }, + + { "deflate", o_special, (void *)setdeflate, + "request Deflate compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value }, + { "nodeflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].deflate }, + { "-deflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].deflate }, + + { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft, + "don't use draft deflate #", OPT_A2COPY, + &ccp_allowoptions[0].deflate_draft }, + + { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "request Predictor-1", OPT_PRIO | 1 }, + { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].predictor_1 }, + { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].predictor_1 }, + +#if MPPE_SUPPORT + /* MPPE options are symmetrical ... we only set wantoptions here */ + { "require-mppe", o_bool, &ccp_wantoptions[0].mppe, + "require MPPE encryption", + OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, + { "+mppe", o_bool, &ccp_wantoptions[0].mppe, + "require MPPE encryption", + OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, + { "nomppe", o_bool, &ccp_wantoptions[0].mppe, + "don't allow MPPE encryption", OPT_PRIO }, + { "-mppe", o_bool, &ccp_wantoptions[0].mppe, + "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO }, + + /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */ + { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 40-bit encryption", + OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe }, + { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 40-bit encryption", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + + { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 128-bit encryption", + OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 128-bit encryption", + OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe }, + { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 128-bit encryption", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + + /* strange one; we always request stateless, but will we allow stateful? */ + { "mppe-stateful", o_bool, &refuse_mppe_stateful, + "allow MPPE stateful mode", OPT_PRIO }, + { "nomppe-stateful", o_bool, &refuse_mppe_stateful, + "disallow MPPE stateful mode", OPT_PRIO | 1 }, +#endif /* MPPE_SUPPORT */ + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ccp_init(ppp_pcb *pcb); +static void ccp_open(ppp_pcb *pcb); +static void ccp_close(ppp_pcb *pcb, const char *reason); +static void ccp_lowerup(ppp_pcb *pcb); +static void ccp_lowerdown(ppp_pcb *pcb); +static void ccp_input(ppp_pcb *pcb, u_char *pkt, int len); +static void ccp_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT +static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len); +#endif /* PPP_DATAINPUT */ + +const struct protent ccp_protent = { + PPP_CCP, + ccp_init, + ccp_input, + ccp_protrej, + ccp_lowerup, + ccp_lowerdown, + ccp_open, + ccp_close, +#if PRINTPKT_SUPPORT + ccp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + ccp_datainput, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "CCP", + "Compressed", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ccp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +/* + * Callbacks for fsm code. + */ +static void ccp_resetci (fsm *); +static int ccp_cilen (fsm *); +static void ccp_addci (fsm *, u_char *, int *); +static int ccp_ackci (fsm *, u_char *, int); +static int ccp_nakci (fsm *, u_char *, int, int); +static int ccp_rejci (fsm *, u_char *, int); +static int ccp_reqci (fsm *, u_char *, int *, int); +static void ccp_up (fsm *); +static void ccp_down (fsm *); +static int ccp_extcode (fsm *, int, int, u_char *, int); +static void ccp_rack_timeout (void *); +static const char *method_name (ccp_options *, ccp_options *); + +static const fsm_callbacks ccp_callbacks = { + ccp_resetci, + ccp_cilen, + ccp_addci, + ccp_ackci, + ccp_nakci, + ccp_rejci, + ccp_reqci, + ccp_up, + ccp_down, + NULL, + NULL, + NULL, + NULL, + ccp_extcode, + "CCP" +}; + +/* + * Do we want / did we get any compression? + */ +static int ccp_anycompress(ccp_options *opt) { + return (0 +#if DEFLATE_SUPPORT + || (opt)->deflate +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + || (opt)->bsd_compress +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + || (opt)->predictor_1 || (opt)->predictor_2 +#endif /* PREDICTOR_SUPPORT */ +#if MPPE_SUPPORT + || (opt)->mppe +#endif /* MPPE_SUPPORT */ + ); +} + +/* + * Local state (mainly for handling reset-reqs and reset-acks). + */ +#define RACK_PENDING 1 /* waiting for reset-ack */ +#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */ + +#define RACKTIMEOUT 1 /* second */ + +#if PPP_OPTIONS +/* + * Option parsing + */ +static int +setbsdcomp(argv) + char **argv; +{ + int rbits, abits; + char *str, *endp; + + str = *argv; + abits = rbits = strtol(str, &endp, 0); + if (endp != str && *endp == ',') { + str = endp + 1; + abits = strtol(str, &endp, 0); + } + if (*endp != 0 || endp == str) { + option_error("invalid parameter '%s' for bsdcomp option", *argv); + return 0; + } + if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)) + || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) { + option_error("bsdcomp option values must be 0 or %d .. %d", + BSD_MIN_BITS, BSD_MAX_BITS); + return 0; + } + if (rbits > 0) { + ccp_wantoptions[0].bsd_compress = 1; + ccp_wantoptions[0].bsd_bits = rbits; + } else + ccp_wantoptions[0].bsd_compress = 0; + if (abits > 0) { + ccp_allowoptions[0].bsd_compress = 1; + ccp_allowoptions[0].bsd_bits = abits; + } else + ccp_allowoptions[0].bsd_compress = 0; + ppp_slprintf(bsd_value, sizeof(bsd_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + + return 1; +} + +static int +setdeflate(argv) + char **argv; +{ + int rbits, abits; + char *str, *endp; + + str = *argv; + abits = rbits = strtol(str, &endp, 0); + if (endp != str && *endp == ',') { + str = endp + 1; + abits = strtol(str, &endp, 0); + } + if (*endp != 0 || endp == str) { + option_error("invalid parameter '%s' for deflate option", *argv); + return 0; + } + if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE)) + || (abits != 0 && (abits < DEFLATE_MIN_SIZE + || abits > DEFLATE_MAX_SIZE))) { + option_error("deflate option values must be 0 or %d .. %d", + DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); + return 0; + } + if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) { + if (rbits == DEFLATE_MIN_SIZE) + rbits = DEFLATE_MIN_WORKS; + if (abits == DEFLATE_MIN_SIZE) + abits = DEFLATE_MIN_WORKS; + warn("deflate option value of %d changed to %d to avoid zlib bug", + DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS); + } + if (rbits > 0) { + ccp_wantoptions[0].deflate = 1; + ccp_wantoptions[0].deflate_size = rbits; + } else + ccp_wantoptions[0].deflate = 0; + if (abits > 0) { + ccp_allowoptions[0].deflate = 1; + ccp_allowoptions[0].deflate_size = abits; + } else + ccp_allowoptions[0].deflate = 0; + ppp_slprintf(deflate_value, sizeof(deflate_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + + return 1; +} +#endif /* PPP_OPTIONS */ + +/* + * ccp_init - initialize CCP. + */ +static void ccp_init(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + + f->pcb = pcb; + f->protocol = PPP_CCP; + f->callbacks = &ccp_callbacks; + fsm_init(f); + +#if 0 /* Not necessary, everything is cleared in ppp_new() */ + memset(wo, 0, sizeof(*wo)); + memset(go, 0, sizeof(*go)); + memset(ao, 0, sizeof(*ao)); + memset(ho, 0, sizeof(*ho)); +#endif /* 0 */ + +#if DEFLATE_SUPPORT + wo->deflate = 1; + wo->deflate_size = DEFLATE_MAX_SIZE; + wo->deflate_correct = 1; + wo->deflate_draft = 1; + ao->deflate = 1; + ao->deflate_size = DEFLATE_MAX_SIZE; + ao->deflate_correct = 1; + ao->deflate_draft = 1; +#endif /* DEFLATE_SUPPORT */ + +#if BSDCOMPRESS_SUPPORT + wo->bsd_compress = 1; + wo->bsd_bits = BSD_MAX_BITS; + ao->bsd_compress = 1; + ao->bsd_bits = BSD_MAX_BITS; +#endif /* BSDCOMPRESS_SUPPORT */ + +#if PREDICTOR_SUPPORT + ao->predictor_1 = 1; +#endif /* PREDICTOR_SUPPORT */ +} + +/* + * ccp_open - CCP is allowed to come up. + */ +static void ccp_open(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + ccp_options *go = &pcb->ccp_gotoptions; + + if (f->state != PPP_FSM_OPENED) + ccp_set(pcb, 1, 0, 0, 0); + + /* + * Find out which compressors the kernel supports before + * deciding whether to open in silent mode. + */ + ccp_resetci(f); + if (!ccp_anycompress(go)) + f->flags |= OPT_SILENT; + + fsm_open(f); +} + +/* + * ccp_close - Terminate CCP. + */ +static void ccp_close(ppp_pcb *pcb, const char *reason) { + fsm *f = &pcb->ccp_fsm; + ccp_set(pcb, 0, 0, 0, 0); + fsm_close(f, reason); +} + +/* + * ccp_lowerup - we may now transmit CCP packets. + */ +static void ccp_lowerup(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + fsm_lowerup(f); +} + +/* + * ccp_lowerdown - we may not transmit CCP packets. + */ +static void ccp_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + fsm_lowerdown(f); +} + +/* + * ccp_input - process a received CCP packet. + */ +static void ccp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->ccp_fsm; + ccp_options *go = &pcb->ccp_gotoptions; + int oldstate; + + /* + * Check for a terminate-request so we can print a message. + */ + oldstate = f->state; + fsm_input(f, p, len); + if (oldstate == PPP_FSM_OPENED && p[0] == TERMREQ && f->state != PPP_FSM_OPENED) { + ppp_notice("Compression disabled by peer."); +#if MPPE_SUPPORT + if (go->mppe) { + ppp_error("MPPE disabled, closing LCP"); + lcp_close(pcb, "MPPE disabled by peer"); + } +#endif /* MPPE_SUPPORT */ + } + + /* + * If we get a terminate-ack and we're not asking for compression, + * close CCP. + */ + if (oldstate == PPP_FSM_REQSENT && p[0] == TERMACK + && !ccp_anycompress(go)) + ccp_close(pcb, "No compression negotiated"); +} + +/* + * Handle a CCP-specific code. + */ +static int ccp_extcode(fsm *f, int code, int id, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(len); + + switch (code) { + case CCP_RESETREQ: + if (f->state != PPP_FSM_OPENED) + break; + ccp_reset_comp(pcb); + /* send a reset-ack, which the transmitter will see and + reset its compression state. */ + fsm_sdata(f, CCP_RESETACK, id, NULL, 0); + break; + + case CCP_RESETACK: + if ((pcb->ccp_localstate & RACK_PENDING) && id == f->reqid) { + pcb->ccp_localstate &= ~(RACK_PENDING | RREQ_REPEAT); + UNTIMEOUT(ccp_rack_timeout, f); + ccp_reset_decomp(pcb); + } + break; + + default: + return 0; + } + + return 1; +} + +/* + * ccp_protrej - peer doesn't talk CCP. + */ +static void ccp_protrej(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; +#if MPPE_SUPPORT + ccp_options *go = &pcb->ccp_gotoptions; +#endif /* MPPE_SUPPORT */ + + ccp_set(pcb, 0, 0, 0, 0); + fsm_lowerdown(f); + +#if MPPE_SUPPORT + if (go->mppe) { + ppp_error("MPPE required but peer negotiation failed"); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + } +#endif /* MPPE_SUPPORT */ + +} + +/* + * ccp_resetci - initialize at start of negotiation. + */ +static void ccp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options *wo = &pcb->ccp_wantoptions; +#if MPPE_SUPPORT + ccp_options *ao = &pcb->ccp_allowoptions; +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT + u_char opt_buf[CCP_MAX_OPTION_LENGTH]; +#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */ +#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT + int res; +#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */ + +#if MPPE_SUPPORT + if (pcb->settings.require_mppe) { + wo->mppe = ao->mppe = + (pcb->settings.refuse_mppe_40 ? 0 : MPPE_OPT_40) + | (pcb->settings.refuse_mppe_128 ? 0 : MPPE_OPT_128); + } +#endif /* MPPE_SUPPORT */ + + *go = *wo; + pcb->ccp_all_rejected = 0; + +#if MPPE_SUPPORT + if (go->mppe) { + int auth_mschap_bits = pcb->auth_done; + int numbits; + + /* + * Start with a basic sanity check: mschap[v2] auth must be in + * exactly one direction. RFC 3079 says that the keys are + * 'derived from the credentials of the peer that initiated the call', + * however the PPP protocol doesn't have such a concept, and pppd + * cannot get this info externally. Instead we do the best we can. + * NB: If MPPE is required, all other compression opts are invalid. + * So, we return right away if we can't do it. + */ + + /* Leave only the mschap auth bits set */ + auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER | + CHAP_MS2_WITHPEER | CHAP_MS2_PEER); + /* Count the mschap auths */ + auth_mschap_bits >>= CHAP_MS_SHIFT; + numbits = 0; + do { + numbits += auth_mschap_bits & 1; + auth_mschap_bits >>= 1; + } while (auth_mschap_bits); + if (numbits > 1) { + ppp_error("MPPE required, but auth done in both directions."); + lcp_close(pcb, "MPPE required but not available"); + return; + } + if (!numbits) { + ppp_error("MPPE required, but MS-CHAP[v2] auth not performed."); + lcp_close(pcb, "MPPE required but not available"); + return; + } + + /* A plugin (eg radius) may not have obtained key material. */ + if (!pcb->mppe_keys_set) { + ppp_error("MPPE required, but keys are not available. " + "Possible plugin problem?"); + lcp_close(pcb, "MPPE required but not available"); + return; + } + + /* LM auth not supported for MPPE */ + if (pcb->auth_done & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) { + /* This might be noise */ + if (go->mppe & MPPE_OPT_40) { + ppp_notice("Disabling 40-bit MPPE; MS-CHAP LM not supported"); + go->mppe &= ~MPPE_OPT_40; + wo->mppe &= ~MPPE_OPT_40; + } + } + + /* Last check: can we actually negotiate something? */ + if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) { + /* Could be misconfig, could be 40-bit disabled above. */ + ppp_error("MPPE required, but both 40-bit and 128-bit disabled."); + lcp_close(pcb, "MPPE required but not available"); + return; + } + + /* sync options */ + ao->mppe = go->mppe; + /* MPPE is not compatible with other compression types */ +#if BSDCOMPRESS_SUPPORT + ao->bsd_compress = go->bsd_compress = 0; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + ao->predictor_1 = go->predictor_1 = 0; + ao->predictor_2 = go->predictor_2 = 0; +#endif /* PREDICTOR_SUPPORT */ +#if DEFLATE_SUPPORT + ao->deflate = go->deflate = 0; +#endif /* DEFLATE_SUPPORT */ + } +#endif /* MPPE_SUPPORT */ + + /* + * Check whether the kernel knows about the various + * compression methods we might request. + */ +#if BSDCOMPRESS_SUPPORT + /* FIXME: we don't need to test if BSD compress is available + * if BSDCOMPRESS_SUPPORT is set, it is. + */ + if (go->bsd_compress) { + opt_buf[0] = CI_BSD_COMPRESS; + opt_buf[1] = CILEN_BSD_COMPRESS; + for (;;) { + if (go->bsd_bits < BSD_MIN_BITS) { + go->bsd_compress = 0; + break; + } + opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); + res = ccp_test(pcb, opt_buf, CILEN_BSD_COMPRESS, 0); + if (res > 0) { + break; + } else if (res < 0) { + go->bsd_compress = 0; + break; + } + go->bsd_bits--; + } + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if DEFLATE_SUPPORT + /* FIXME: we don't need to test if deflate is available + * if DEFLATE_SUPPORT is set, it is. + */ + if (go->deflate) { + if (go->deflate_correct) { + opt_buf[0] = CI_DEFLATE; + opt_buf[1] = CILEN_DEFLATE; + opt_buf[3] = DEFLATE_CHK_SEQUENCE; + for (;;) { + if (go->deflate_size < DEFLATE_MIN_WORKS) { + go->deflate_correct = 0; + break; + } + opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size); + res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0); + if (res > 0) { + break; + } else if (res < 0) { + go->deflate_correct = 0; + break; + } + go->deflate_size--; + } + } + if (go->deflate_draft) { + opt_buf[0] = CI_DEFLATE_DRAFT; + opt_buf[1] = CILEN_DEFLATE; + opt_buf[3] = DEFLATE_CHK_SEQUENCE; + for (;;) { + if (go->deflate_size < DEFLATE_MIN_WORKS) { + go->deflate_draft = 0; + break; + } + opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size); + res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0); + if (res > 0) { + break; + } else if (res < 0) { + go->deflate_draft = 0; + break; + } + go->deflate_size--; + } + } + if (!go->deflate_correct && !go->deflate_draft) + go->deflate = 0; + } +#endif /* DEFLATE_SUPPORT */ +#if PREDICTOR_SUPPORT + /* FIXME: we don't need to test if predictor is available, + * if PREDICTOR_SUPPORT is set, it is. + */ + if (go->predictor_1) { + opt_buf[0] = CI_PREDICTOR_1; + opt_buf[1] = CILEN_PREDICTOR_1; + if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_1, 0) <= 0) + go->predictor_1 = 0; + } + if (go->predictor_2) { + opt_buf[0] = CI_PREDICTOR_2; + opt_buf[1] = CILEN_PREDICTOR_2; + if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_2, 0) <= 0) + go->predictor_2 = 0; + } +#endif /* PREDICTOR_SUPPORT */ +} + +/* + * ccp_cilen - Return total length of our configuration info. + */ +static int ccp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + + return 0 +#if BSDCOMPRESS_SUPPORT + + (go->bsd_compress? CILEN_BSD_COMPRESS: 0) +#endif /* BSDCOMPRESS_SUPPORT */ +#if DEFLATE_SUPPORT + + (go->deflate && go->deflate_correct? CILEN_DEFLATE: 0) + + (go->deflate && go->deflate_draft? CILEN_DEFLATE: 0) +#endif /* DEFLATE_SUPPORT */ +#if PREDICTOR_SUPPORT + + (go->predictor_1? CILEN_PREDICTOR_1: 0) + + (go->predictor_2? CILEN_PREDICTOR_2: 0) +#endif /* PREDICTOR_SUPPORT */ +#if MPPE_SUPPORT + + (go->mppe? CILEN_MPPE: 0) +#endif /* MPPE_SUPPORT */ + ; +} + +/* + * ccp_addci - put our requests in a packet. + */ +static void ccp_addci(fsm *f, u_char *p, int *lenp) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + u_char *p0 = p; + + /* + * Add the compression types that we can receive, in decreasing + * preference order. + */ +#if MPPE_SUPPORT + if (go->mppe) { + p[0] = CI_MPPE; + p[1] = CILEN_MPPE; + MPPE_OPTS_TO_CI(go->mppe, &p[2]); + mppe_init(pcb, &pcb->mppe_decomp, go->mppe); + p += CILEN_MPPE; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate) { + if (go->deflate_correct) { + p[0] = CI_DEFLATE; + p[1] = CILEN_DEFLATE; + p[2] = DEFLATE_MAKE_OPT(go->deflate_size); + p[3] = DEFLATE_CHK_SEQUENCE; + p += CILEN_DEFLATE; + } + if (go->deflate_draft) { + p[0] = CI_DEFLATE_DRAFT; + p[1] = CILEN_DEFLATE; + p[2] = p[2 - CILEN_DEFLATE]; + p[3] = DEFLATE_CHK_SEQUENCE; + p += CILEN_DEFLATE; + } + } +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress) { + p[0] = CI_BSD_COMPRESS; + p[1] = CILEN_BSD_COMPRESS; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); + p += CILEN_BSD_COMPRESS; + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + /* XXX Should Predictor 2 be preferable to Predictor 1? */ + if (go->predictor_1) { + p[0] = CI_PREDICTOR_1; + p[1] = CILEN_PREDICTOR_1; + p += CILEN_PREDICTOR_1; + } + if (go->predictor_2) { + p[0] = CI_PREDICTOR_2; + p[1] = CILEN_PREDICTOR_2; + p += CILEN_PREDICTOR_2; + } +#endif /* PREDICTOR_SUPPORT */ + + go->method = (p > p0)? p0[0]: 0; + + *lenp = p - p0; +} + +/* + * ccp_ackci - process a received configure-ack, and return + * 1 iff the packet was OK. + */ +static int ccp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; +#if BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT + u_char *p0 = p; +#endif /* BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */ + +#if MPPE_SUPPORT + if (go->mppe) { + u_char opt_buf[CILEN_MPPE]; + + opt_buf[0] = CI_MPPE; + opt_buf[1] = CILEN_MPPE; + MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); + if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE)) + return 0; + p += CILEN_MPPE; + len -= CILEN_MPPE; + /* XXX Cope with first/fast ack */ + if (len == 0) + return 1; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate) { + if (len < CILEN_DEFLATE + || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) + || p[1] != CILEN_DEFLATE + || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + /* XXX Cope with first/fast ack */ + if (len == 0) + return 1; + if (go->deflate_correct && go->deflate_draft) { + if (len < CILEN_DEFLATE + || p[0] != CI_DEFLATE_DRAFT + || p[1] != CILEN_DEFLATE + || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + } +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress) { + if (len < CILEN_BSD_COMPRESS + || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS + || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) + return 0; + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + if (go->predictor_1) { + if (len < CILEN_PREDICTOR_1 + || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1) + return 0; + p += CILEN_PREDICTOR_1; + len -= CILEN_PREDICTOR_1; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } + if (go->predictor_2) { + if (len < CILEN_PREDICTOR_2 + || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2) + return 0; + p += CILEN_PREDICTOR_2; + len -= CILEN_PREDICTOR_2; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } +#endif /* PREDICTOR_SUPPORT */ + + if (len != 0) + return 0; + return 1; +} + +/* + * ccp_nakci - process received configure-nak. + * Returns 1 iff the nak was OK. + */ +static int ccp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options no; /* options we've seen already */ + ccp_options try_; /* options to ask for next time */ + LWIP_UNUSED_ARG(treat_as_reject); +#if !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(len); +#endif /* !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */ + + memset(&no, 0, sizeof(no)); + try_ = *go; + +#if MPPE_SUPPORT + if (go->mppe && len >= CILEN_MPPE + && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + no.mppe = 1; + /* + * Peer wants us to use a different strength or other setting. + * Fail if we aren't willing to use his suggestion. + */ + MPPE_CI_TO_OPTS(&p[2], try_.mppe); + if ((try_.mppe & MPPE_OPT_STATEFUL) && pcb->settings.refuse_mppe_stateful) { + ppp_error("Refusing MPPE stateful mode offered by peer"); + try_.mppe = 0; + } else if (((go->mppe | MPPE_OPT_STATEFUL) & try_.mppe) != try_.mppe) { + /* Peer must have set options we didn't request (suggest) */ + try_.mppe = 0; + } + + if (!try_.mppe) { + ppp_error("MPPE required but peer negotiation failed"); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + } + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate && len >= CILEN_DEFLATE + && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) + && p[1] == CILEN_DEFLATE) { + no.deflate = 1; + /* + * Peer wants us to use a different code size or something. + * Stop asking for Deflate if we don't understand his suggestion. + */ + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL + || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS + || p[3] != DEFLATE_CHK_SEQUENCE) + try_.deflate = 0; + else if (DEFLATE_SIZE(p[2]) < go->deflate_size) + try_.deflate_size = DEFLATE_SIZE(p[2]); + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + if (go->deflate_correct && go->deflate_draft + && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT + && p[1] == CILEN_DEFLATE) { + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + } +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress && len >= CILEN_BSD_COMPRESS + && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { + no.bsd_compress = 1; + /* + * Peer wants us to use a different number of bits + * or a different version. + */ + if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION) + try_.bsd_compress = 0; + else if (BSD_NBITS(p[2]) < go->bsd_bits) + try_.bsd_bits = BSD_NBITS(p[2]); + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + } +#endif /* BSDCOMPRESS_SUPPORT */ + + /* + * Predictor-1 and 2 have no options, so they can't be Naked. + * + * There may be remaining options but we ignore them. + */ + + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; +} + +/* + * ccp_rejci - reject some of our suggested compression methods. + */ +static int ccp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options try_; /* options to request next time */ + + try_ = *go; + + /* + * Cope with empty configure-rejects by ceasing to send + * configure-requests. + */ + if (len == 0 && pcb->ccp_all_rejected) + return -1; + +#if MPPE_SUPPORT + if (go->mppe && len >= CILEN_MPPE + && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + ppp_error("MPPE required but peer refused"); + lcp_close(pcb, "MPPE required but peer refused"); + p += CILEN_MPPE; + len -= CILEN_MPPE; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate_correct && len >= CILEN_DEFLATE + && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) { + if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; /* Rej is bad */ + try_.deflate_correct = 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + if (go->deflate_draft && len >= CILEN_DEFLATE + && p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) { + if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; /* Rej is bad */ + try_.deflate_draft = 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + if (!try_.deflate_correct && !try_.deflate_draft) + try_.deflate = 0; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress && len >= CILEN_BSD_COMPRESS + && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { + if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) + return 0; + try_.bsd_compress = 0; + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + if (go->predictor_1 && len >= CILEN_PREDICTOR_1 + && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) { + try_.predictor_1 = 0; + p += CILEN_PREDICTOR_1; + len -= CILEN_PREDICTOR_1; + } + if (go->predictor_2 && len >= CILEN_PREDICTOR_2 + && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) { + try_.predictor_2 = 0; + p += CILEN_PREDICTOR_2; + len -= CILEN_PREDICTOR_2; + } +#endif /* PREDICTOR_SUPPORT */ + + if (len != 0) + return 0; + + if (f->state != PPP_FSM_OPENED) + *go = try_; + + return 1; +} + +/* + * ccp_reqci - processed a received configure-request. + * Returns CONFACK, CONFNAK or CONFREJ and the packet modified + * appropriately. + */ +static int ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak) { + ppp_pcb *pcb = f->pcb; + ccp_options *ho = &pcb->ccp_hisoptions; + ccp_options *ao = &pcb->ccp_allowoptions; + int ret, newret; +#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT + int res; + int nb; +#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */ + u_char *p0, *retp; + int len, clen, type; +#if MPPE_SUPPORT + u8_t rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */ + /* CI_MPPE, or due to other options? */ +#endif /* MPPE_SUPPORT */ + + ret = CONFACK; + retp = p0 = p; + len = *lenp; + + memset(ho, 0, sizeof(ccp_options)); + ho->method = (len > 0)? p[0]: 0; + + while (len > 0) { + newret = CONFACK; + if (len < 2 || p[1] < 2 || p[1] > len) { + /* length is bad */ + clen = len; + newret = CONFREJ; + + } else { + type = p[0]; + clen = p[1]; + + switch (type) { +#if MPPE_SUPPORT + case CI_MPPE: + if (!ao->mppe || clen != CILEN_MPPE) { + newret = CONFREJ; + break; + } + MPPE_CI_TO_OPTS(&p[2], ho->mppe); + + /* Nak if anything unsupported or unknown are set. */ + if (ho->mppe & MPPE_OPT_UNSUPPORTED) { + newret = CONFNAK; + ho->mppe &= ~MPPE_OPT_UNSUPPORTED; + } + if (ho->mppe & MPPE_OPT_UNKNOWN) { + newret = CONFNAK; + ho->mppe &= ~MPPE_OPT_UNKNOWN; + } + + /* Check state opt */ + if (ho->mppe & MPPE_OPT_STATEFUL) { + /* + * We can Nak and request stateless, but it's a + * lot easier to just assume the peer will request + * it if he can do it; stateful mode is bad over + * the Internet -- which is where we expect MPPE. + */ + if (pcb->settings.refuse_mppe_stateful) { + ppp_error("Refusing MPPE stateful mode offered by peer"); + newret = CONFREJ; + break; + } + } + + /* Find out which of {S,L} are set. */ + if ((ho->mppe & MPPE_OPT_128) + && (ho->mppe & MPPE_OPT_40)) { + /* Both are set, negotiate the strongest. */ + newret = CONFNAK; + if (ao->mppe & MPPE_OPT_128) + ho->mppe &= ~MPPE_OPT_40; + else if (ao->mppe & MPPE_OPT_40) + ho->mppe &= ~MPPE_OPT_128; + else { + newret = CONFREJ; + break; + } + } else if (ho->mppe & MPPE_OPT_128) { + if (!(ao->mppe & MPPE_OPT_128)) { + newret = CONFREJ; + break; + } + } else if (ho->mppe & MPPE_OPT_40) { + if (!(ao->mppe & MPPE_OPT_40)) { + newret = CONFREJ; + break; + } + } else { + /* Neither are set. */ + /* We cannot accept this. */ + newret = CONFNAK; + /* Give the peer our idea of what can be used, + so it can choose and confirm */ + ho->mppe = ao->mppe; + } + + /* rebuild the opts */ + MPPE_OPTS_TO_CI(ho->mppe, &p[2]); + if (newret == CONFACK) { + int mtu; + + mppe_init(pcb, &pcb->mppe_comp, ho->mppe); + /* + * We need to decrease the interface MTU by MPPE_PAD + * because MPPE frames **grow**. The kernel [must] + * allocate MPPE_PAD extra bytes in xmit buffers. + */ + mtu = netif_get_mtu(pcb); + if (mtu) + netif_set_mtu(pcb, mtu - MPPE_PAD); + else + newret = CONFREJ; + } + + /* + * We have accepted MPPE or are willing to negotiate + * MPPE parameters. A CONFREJ is due to subsequent + * (non-MPPE) processing. + */ + rej_for_ci_mppe = 0; + break; +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (!ao->deflate || clen != CILEN_DEFLATE + || (!ao->deflate_correct && type == CI_DEFLATE) + || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) { + newret = CONFREJ; + break; + } + + ho->deflate = 1; + ho->deflate_size = nb = DEFLATE_SIZE(p[2]); + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL + || p[3] != DEFLATE_CHK_SEQUENCE + || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) { + newret = CONFNAK; + if (!dont_nak) { + p[2] = DEFLATE_MAKE_OPT(ao->deflate_size); + p[3] = DEFLATE_CHK_SEQUENCE; + /* fall through to test this #bits below */ + } else + break; + } + + /* + * Check whether we can do Deflate with the window + * size they want. If the window is too big, reduce + * it until the kernel can cope and nak with that. + * We only check this for the first option. + */ + if (p == p0) { + for (;;) { + res = ccp_test(pcb, p, CILEN_DEFLATE, 1); + if (res > 0) + break; /* it's OK now */ + if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) { + newret = CONFREJ; + p[2] = DEFLATE_MAKE_OPT(ho->deflate_size); + break; + } + newret = CONFNAK; + --nb; + p[2] = DEFLATE_MAKE_OPT(nb); + } + } + break; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + case CI_BSD_COMPRESS: + if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) { + newret = CONFREJ; + break; + } + + ho->bsd_compress = 1; + ho->bsd_bits = nb = BSD_NBITS(p[2]); + if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION + || nb > ao->bsd_bits || nb < BSD_MIN_BITS) { + newret = CONFNAK; + if (!dont_nak) { + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits); + /* fall through to test this #bits below */ + } else + break; + } + + /* + * Check whether we can do BSD-Compress with the code + * size they want. If the code size is too big, reduce + * it until the kernel can cope and nak with that. + * We only check this for the first option. + */ + if (p == p0) { + for (;;) { + res = ccp_test(pcb, p, CILEN_BSD_COMPRESS, 1); + if (res > 0) + break; + if (res < 0 || nb == BSD_MIN_BITS || dont_nak) { + newret = CONFREJ; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, + ho->bsd_bits); + break; + } + newret = CONFNAK; + --nb; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb); + } + } + break; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + case CI_PREDICTOR_1: + if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) { + newret = CONFREJ; + break; + } + + ho->predictor_1 = 1; + if (p == p0 + && ccp_test(pcb, p, CILEN_PREDICTOR_1, 1) <= 0) { + newret = CONFREJ; + } + break; + + case CI_PREDICTOR_2: + if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) { + newret = CONFREJ; + break; + } + + ho->predictor_2 = 1; + if (p == p0 + && ccp_test(pcb, p, CILEN_PREDICTOR_2, 1) <= 0) { + newret = CONFREJ; + } + break; +#endif /* PREDICTOR_SUPPORT */ + + default: + newret = CONFREJ; + } + } + + if (newret == CONFNAK && dont_nak) + newret = CONFREJ; + if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) { + /* we're returning this option */ + if (newret == CONFREJ && ret == CONFNAK) + retp = p0; + ret = newret; + if (p != retp) + MEMCPY(retp, p, clen); + retp += clen; + } + + p += clen; + len -= clen; + } + + if (ret != CONFACK) { + if (ret == CONFREJ && *lenp == retp - p0) + pcb->ccp_all_rejected = 1; + else + *lenp = retp - p0; + } +#if MPPE_SUPPORT + if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) { + ppp_error("MPPE required but peer negotiation failed"); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + } +#endif /* MPPE_SUPPORT */ + return ret; +} + +/* + * Make a string name for a compression method (or 2). + */ +static const char *method_name(ccp_options *opt, ccp_options *opt2) { + static char result[64]; +#if !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT + LWIP_UNUSED_ARG(opt2); +#endif /* !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */ + + if (!ccp_anycompress(opt)) + return "(none)"; + switch (opt->method) { +#if MPPE_SUPPORT + case CI_MPPE: + { + char *p = result; + char *q = result + sizeof(result); /* 1 past result */ + + ppp_slprintf(p, q - p, "MPPE "); + p += 5; + if (opt->mppe & MPPE_OPT_128) { + ppp_slprintf(p, q - p, "128-bit "); + p += 8; + } + if (opt->mppe & MPPE_OPT_40) { + ppp_slprintf(p, q - p, "40-bit "); + p += 7; + } + if (opt->mppe & MPPE_OPT_STATEFUL) + ppp_slprintf(p, q - p, "stateful"); + else + ppp_slprintf(p, q - p, "stateless"); + + break; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (opt2 != NULL && opt2->deflate_size != opt->deflate_size) + ppp_slprintf(result, sizeof(result), "Deflate%s (%d/%d)", + (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), + opt->deflate_size, opt2->deflate_size); + else + ppp_slprintf(result, sizeof(result), "Deflate%s (%d)", + (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), + opt->deflate_size); + break; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + case CI_BSD_COMPRESS: + if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) + ppp_slprintf(result, sizeof(result), "BSD-Compress (%d/%d)", + opt->bsd_bits, opt2->bsd_bits); + else + ppp_slprintf(result, sizeof(result), "BSD-Compress (%d)", + opt->bsd_bits); + break; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + case CI_PREDICTOR_1: + return "Predictor 1"; + case CI_PREDICTOR_2: + return "Predictor 2"; +#endif /* PREDICTOR_SUPPORT */ + default: + ppp_slprintf(result, sizeof(result), "Method %d", opt->method); + } + return result; +} + +/* + * CCP has come up - inform the kernel driver and log a message. + */ +static void ccp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options *ho = &pcb->ccp_hisoptions; + char method1[64]; + + ccp_set(pcb, 1, 1, go->method, ho->method); + if (ccp_anycompress(go)) { + if (ccp_anycompress(ho)) { + if (go->method == ho->method) { + ppp_notice("%s compression enabled", method_name(go, ho)); + } else { + ppp_strlcpy(method1, method_name(go, NULL), sizeof(method1)); + ppp_notice("%s / %s compression enabled", + method1, method_name(ho, NULL)); + } + } else + ppp_notice("%s receive compression enabled", method_name(go, NULL)); + } else if (ccp_anycompress(ho)) + ppp_notice("%s transmit compression enabled", method_name(ho, NULL)); +#if MPPE_SUPPORT + if (go->mppe) { + continue_networks(pcb); /* Bring up IP et al */ + } +#endif /* MPPE_SUPPORT */ +} + +/* + * CCP has gone down - inform the kernel driver. + */ +static void ccp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; +#if MPPE_SUPPORT + ccp_options *go = &pcb->ccp_gotoptions; +#endif /* MPPE_SUPPORT */ + + if (pcb->ccp_localstate & RACK_PENDING) + UNTIMEOUT(ccp_rack_timeout, f); + pcb->ccp_localstate = 0; + ccp_set(pcb, 1, 0, 0, 0); +#if MPPE_SUPPORT + if (go->mppe) { + go->mppe = 0; + if (pcb->lcp_fsm.state == PPP_FSM_OPENED) { + /* If LCP is not already going down, make sure it does. */ + ppp_error("MPPE disabled"); + lcp_close(pcb, "MPPE disabled"); + } + } +#endif /* MPPE_SUPPORT */ +} + +#if PRINTPKT_SUPPORT +/* + * Print the contents of a CCP packet. + */ +static const char* const ccp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", + NULL, NULL, NULL, NULL, NULL, NULL, + "ResetReq", "ResetAck", +}; + +static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { + const u_char *p0, *optend; + int code, id, len; + int optlen; + + p0 = p; + if (plen < HEADERLEN) + return 0; + code = p[0]; + id = p[1]; + len = (p[2] << 8) + p[3]; + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ccp_codenames) && ccp_codenames[code-1] != NULL) + printer(arg, " %s", ccp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + p += HEADERLEN; + + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print list of possible compression methods */ + while (len >= 2) { + code = p[0]; + optlen = p[1]; + if (optlen < 2 || optlen > len) + break; + printer(arg, " <"); + len -= optlen; + optend = p + optlen; + switch (code) { +#if MPPE_SUPPORT + case CI_MPPE: + if (optlen >= CILEN_MPPE) { + u_char mppe_opts; + + MPPE_CI_TO_OPTS(&p[2], mppe_opts); + printer(arg, "mppe %s %s %s %s %s %s%s", + (p[2] & MPPE_H_BIT)? "+H": "-H", + (p[5] & MPPE_M_BIT)? "+M": "-M", + (p[5] & MPPE_S_BIT)? "+S": "-S", + (p[5] & MPPE_L_BIT)? "+L": "-L", + (p[5] & MPPE_D_BIT)? "+D": "-D", + (p[5] & MPPE_C_BIT)? "+C": "-C", + (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": ""); + if (mppe_opts & MPPE_OPT_UNKNOWN) + printer(arg, " (%.2x %.2x %.2x %.2x)", + p[2], p[3], p[4], p[5]); + p += CILEN_MPPE; + } + break; +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (optlen >= CILEN_DEFLATE) { + printer(arg, "deflate%s %d", + (code == CI_DEFLATE_DRAFT? "(old#)": ""), + DEFLATE_SIZE(p[2])); + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL) + printer(arg, " method %d", DEFLATE_METHOD(p[2])); + if (p[3] != DEFLATE_CHK_SEQUENCE) + printer(arg, " check %d", p[3]); + p += CILEN_DEFLATE; + } + break; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + case CI_BSD_COMPRESS: + if (optlen >= CILEN_BSD_COMPRESS) { + printer(arg, "bsd v%d %d", BSD_VERSION(p[2]), + BSD_NBITS(p[2])); + p += CILEN_BSD_COMPRESS; + } + break; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + case CI_PREDICTOR_1: + if (optlen >= CILEN_PREDICTOR_1) { + printer(arg, "predictor 1"); + p += CILEN_PREDICTOR_1; + } + break; + case CI_PREDICTOR_2: + if (optlen >= CILEN_PREDICTOR_2) { + printer(arg, "predictor 2"); + p += CILEN_PREDICTOR_2; + } + break; +#endif /* PREDICTOR_SUPPORT */ + default: + break; + } + while (p < optend) + printer(arg, " %.2x", *p++); + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* dump out the rest of the packet in hex */ + while (--len >= 0) + printer(arg, " %.2x", *p++); + + return p - p0; +} +#endif /* PRINTPKT_SUPPORT */ + +#if PPP_DATAINPUT +/* + * We have received a packet that the decompressor failed to + * decompress. Here we would expect to issue a reset-request, but + * Motorola has a patent on resetting the compressor as a result of + * detecting an error in the decompressed data after decompression. + * (See US patent 5,130,993; international patent publication number + * WO 91/10289; Australian patent 73296/91.) + * + * So we ask the kernel whether the error was detected after + * decompression; if it was, we take CCP down, thus disabling + * compression :-(, otherwise we issue the reset-request. + */ +static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len) { + fsm *f; +#if MPPE_SUPPORT + ccp_options *go = &pcb->ccp_gotoptions; +#endif /* MPPE_SUPPORT */ + LWIP_UNUSED_ARG(pkt); + LWIP_UNUSED_ARG(len); + + f = &pcb->ccp_fsm; + if (f->state == PPP_FSM_OPENED) { + if (ccp_fatal_error(pcb)) { + /* + * Disable compression by taking CCP down. + */ + ppp_error("Lost compression sync: disabling compression"); + ccp_close(pcb, "Lost compression sync"); +#if MPPE_SUPPORT + /* + * If we were doing MPPE, we must also take the link down. + */ + if (go->mppe) { + ppp_error("Too many MPPE errors, closing LCP"); + lcp_close(pcb, "Too many MPPE errors"); + } +#endif /* MPPE_SUPPORT */ + } else { + /* + * Send a reset-request to reset the peer's compressor. + * We don't do that if we are still waiting for an + * acknowledgement to a previous reset-request. + */ + if (!(pcb->ccp_localstate & RACK_PENDING)) { + fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + pcb->ccp_localstate |= RACK_PENDING; + } else + pcb->ccp_localstate |= RREQ_REPEAT; + } + } +} +#endif /* PPP_DATAINPUT */ + +/* + * We have received a packet that the decompressor failed to + * decompress. Issue a reset-request. + */ +void ccp_resetrequest(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + + if (f->state != PPP_FSM_OPENED) + return; + + /* + * Send a reset-request to reset the peer's compressor. + * We don't do that if we are still waiting for an + * acknowledgement to a previous reset-request. + */ + if (!(pcb->ccp_localstate & RACK_PENDING)) { + fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + pcb->ccp_localstate |= RACK_PENDING; + } else + pcb->ccp_localstate |= RREQ_REPEAT; +} + +/* + * Timeout waiting for reset-ack. + */ +static void ccp_rack_timeout(void *arg) { + fsm *f = (fsm*)arg; + ppp_pcb *pcb = f->pcb; + + if (f->state == PPP_FSM_OPENED && (pcb->ccp_localstate & RREQ_REPEAT)) { + fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + pcb->ccp_localstate &= ~RREQ_REPEAT; + } else + pcb->ccp_localstate &= ~RACK_PENDING; +} + +#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/chap-md5.c b/components/net/lwip-2.0.3/src/netif/ppp/chap-md5.c new file mode 100644 index 0000000000..88f069f032 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/chap-md5.c @@ -0,0 +1,126 @@ +/* + * chap-md5.c - New CHAP/MD5 implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap-md5.h" +#include "netif/ppp/magic.h" +#include "netif/ppp/pppcrypt.h" + +#define MD5_HASH_SIZE 16 +#define MD5_MIN_CHALLENGE 17 +#define MD5_MAX_CHALLENGE 24 +#define MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE 3 /* 2^3-1 = 7, 17+7 = 24 */ + +#if PPP_SERVER +static void chap_md5_generate_challenge(ppp_pcb *pcb, unsigned char *cp) { + int clen; + LWIP_UNUSED_ARG(pcb); + + clen = MD5_MIN_CHALLENGE + magic_pow(MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE); + *cp++ = clen; + magic_random_bytes(cp, clen); +} + +static int chap_md5_verify_response(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + lwip_md5_context ctx; + unsigned char idbyte = id; + unsigned char hash[MD5_HASH_SIZE]; + int challenge_len, response_len; + LWIP_UNUSED_ARG(name); + LWIP_UNUSED_ARG(pcb); + + challenge_len = *challenge++; + response_len = *response++; + if (response_len == MD5_HASH_SIZE) { + /* Generate hash of ID, secret, challenge */ + lwip_md5_init(&ctx); + lwip_md5_starts(&ctx); + lwip_md5_update(&ctx, &idbyte, 1); + lwip_md5_update(&ctx, secret, secret_len); + lwip_md5_update(&ctx, challenge, challenge_len); + lwip_md5_finish(&ctx, hash); + lwip_md5_free(&ctx); + + /* Test if our hash matches the peer's response */ + if (memcmp(hash, response, MD5_HASH_SIZE) == 0) { + ppp_slprintf(message, message_space, "Access granted"); + return 1; + } + } + ppp_slprintf(message, message_space, "Access denied"); + return 0; +} +#endif /* PPP_SERVER */ + +static void chap_md5_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *private_) { + lwip_md5_context ctx; + unsigned char idbyte = id; + int challenge_len = *challenge++; + LWIP_UNUSED_ARG(our_name); + LWIP_UNUSED_ARG(private_); + LWIP_UNUSED_ARG(pcb); + + lwip_md5_init(&ctx); + lwip_md5_starts(&ctx); + lwip_md5_update(&ctx, &idbyte, 1); + lwip_md5_update(&ctx, (const u_char *)secret, secret_len); + lwip_md5_update(&ctx, challenge, challenge_len); + lwip_md5_finish(&ctx, &response[1]); + lwip_md5_free(&ctx); + response[0] = MD5_HASH_SIZE; +} + +const struct chap_digest_type md5_digest = { + CHAP_MD5, /* code */ +#if PPP_SERVER + chap_md5_generate_challenge, + chap_md5_verify_response, +#endif /* PPP_SERVER */ + chap_md5_make_response, + NULL, /* check_success */ + NULL, /* handle_failure */ +}; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/chap-new.c b/components/net/lwip-2.0.3/src/netif/ppp/chap-new.c new file mode 100644 index 0000000000..485122d272 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/chap-new.c @@ -0,0 +1,677 @@ +/* + * chap-new.c - New CHAP implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#if 0 /* UNUSED */ +#include "session.h" +#endif /* UNUSED */ + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap-md5.h" +#if MSCHAP_SUPPORT +#include "netif/ppp/chap_ms.h" +#endif +#include "netif/ppp/magic.h" + +#if 0 /* UNUSED */ +/* Hook for a plugin to validate CHAP challenge */ +int (*chap_verify_hook)(const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) = NULL; +#endif /* UNUSED */ + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t chap_option_list[] = { + { "chap-restart", o_int, &chap_timeout_time, + "Set timeout for CHAP", OPT_PRIO }, + { "chap-max-challenge", o_int, &pcb->settings.chap_max_transmits, + "Set max #xmits for challenge", OPT_PRIO }, + { "chap-interval", o_int, &pcb->settings.chap_rechallenge_time, + "Set interval for rechallenge", OPT_PRIO }, + { NULL } +}; +#endif /* PPP_OPTIONS */ + + +/* Values for flags in chap_client_state and chap_server_state */ +#define LOWERUP 1 +#define AUTH_STARTED 2 +#define AUTH_DONE 4 +#define AUTH_FAILED 8 +#define TIMEOUT_PENDING 0x10 +#define CHALLENGE_VALID 0x20 + +/* + * Prototypes. + */ +static void chap_init(ppp_pcb *pcb); +static void chap_lowerup(ppp_pcb *pcb); +static void chap_lowerdown(ppp_pcb *pcb); +#if PPP_SERVER +static void chap_timeout(void *arg); +static void chap_generate_challenge(ppp_pcb *pcb); +static void chap_handle_response(ppp_pcb *pcb, int code, + unsigned char *pkt, int len); +static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space); +#endif /* PPP_SERVER */ +static void chap_respond(ppp_pcb *pcb, int id, + unsigned char *pkt, int len); +static void chap_handle_status(ppp_pcb *pcb, int code, int id, + unsigned char *pkt, int len); +static void chap_protrej(ppp_pcb *pcb); +static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen); +#if PRINTPKT_SUPPORT +static int chap_print_pkt(const unsigned char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +/* List of digest types that we know about */ +static const struct chap_digest_type* const chap_digests[] = { + &md5_digest, +#if MSCHAP_SUPPORT + &chapms_digest, + &chapms2_digest, +#endif /* MSCHAP_SUPPORT */ + NULL +}; + +/* + * chap_init - reset to initial state. + */ +static void chap_init(ppp_pcb *pcb) { + LWIP_UNUSED_ARG(pcb); + +#if 0 /* Not necessary, everything is cleared in ppp_new() */ + memset(&pcb->chap_client, 0, sizeof(chap_client_state)); +#if PPP_SERVER + memset(&pcb->chap_server, 0, sizeof(chap_server_state)); +#endif /* PPP_SERVER */ +#endif /* 0 */ +} + +/* + * chap_lowerup - we can start doing stuff now. + */ +static void chap_lowerup(ppp_pcb *pcb) { + + pcb->chap_client.flags |= LOWERUP; +#if PPP_SERVER + pcb->chap_server.flags |= LOWERUP; + if (pcb->chap_server.flags & AUTH_STARTED) + chap_timeout(pcb); +#endif /* PPP_SERVER */ +} + +static void chap_lowerdown(ppp_pcb *pcb) { + + pcb->chap_client.flags = 0; +#if PPP_SERVER + if (pcb->chap_server.flags & TIMEOUT_PENDING) + UNTIMEOUT(chap_timeout, pcb); + pcb->chap_server.flags = 0; +#endif /* PPP_SERVER */ +} + +#if PPP_SERVER +/* + * chap_auth_peer - Start authenticating the peer. + * If the lower layer is already up, we start sending challenges, + * otherwise we wait for the lower layer to come up. + */ +void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { + const struct chap_digest_type *dp; + int i; + + if (pcb->chap_server.flags & AUTH_STARTED) { + ppp_error("CHAP: peer authentication already started!"); + return; + } + for (i = 0; (dp = chap_digests[i]) != NULL; ++i) + if (dp->code == digest_code) + break; + if (dp == NULL) + ppp_fatal("CHAP digest 0x%x requested but not available", + digest_code); + + pcb->chap_server.digest = dp; + pcb->chap_server.name = our_name; + /* Start with a random ID value */ + pcb->chap_server.id = magic(); + pcb->chap_server.flags |= AUTH_STARTED; + if (pcb->chap_server.flags & LOWERUP) + chap_timeout(pcb); +} +#endif /* PPP_SERVER */ + +/* + * chap_auth_with_peer - Prepare to authenticate ourselves to the peer. + * There isn't much to do until we receive a challenge. + */ +void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { + const struct chap_digest_type *dp; + int i; + + if(NULL == our_name) + return; + + if (pcb->chap_client.flags & AUTH_STARTED) { + ppp_error("CHAP: authentication with peer already started!"); + return; + } + for (i = 0; (dp = chap_digests[i]) != NULL; ++i) + if (dp->code == digest_code) + break; + + if (dp == NULL) + ppp_fatal("CHAP digest 0x%x requested but not available", + digest_code); + + pcb->chap_client.digest = dp; + pcb->chap_client.name = our_name; + pcb->chap_client.flags |= AUTH_STARTED; +} + +#if PPP_SERVER +/* + * chap_timeout - It's time to send another challenge to the peer. + * This could be either a retransmission of a previous challenge, + * or a new challenge to start re-authentication. + */ +static void chap_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + struct pbuf *p; + + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + if ((pcb->chap_server.flags & CHALLENGE_VALID) == 0) { + pcb->chap_server.challenge_xmits = 0; + chap_generate_challenge(pcb); + pcb->chap_server.flags |= CHALLENGE_VALID; + } else if (pcb->chap_server.challenge_xmits >= pcb->settings.chap_max_transmits) { + pcb->chap_server.flags &= ~CHALLENGE_VALID; + pcb->chap_server.flags |= AUTH_DONE | AUTH_FAILED; + auth_peer_fail(pcb, PPP_CHAP); + return; + } + + p = pbuf_alloc(PBUF_RAW, (u16_t)(pcb->chap_server.challenge_pktlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + MEMCPY(p->payload, pcb->chap_server.challenge, pcb->chap_server.challenge_pktlen); + ppp_write(pcb, p); + ++pcb->chap_server.challenge_xmits; + pcb->chap_server.flags |= TIMEOUT_PENDING; + TIMEOUT(chap_timeout, arg, pcb->settings.chap_timeout_time); +} + +/* + * chap_generate_challenge - generate a challenge string and format + * the challenge packet in pcb->chap_server.challenge_pkt. + */ +static void chap_generate_challenge(ppp_pcb *pcb) { + int clen = 1, nlen, len; + unsigned char *p; + + p = pcb->chap_server.challenge; + MAKEHEADER(p, PPP_CHAP); + p += CHAP_HDRLEN; + pcb->chap_server.digest->generate_challenge(pcb, p); + clen = *p; + nlen = strlen(pcb->chap_server.name); + memcpy(p + 1 + clen, pcb->chap_server.name, nlen); + + len = CHAP_HDRLEN + 1 + clen + nlen; + pcb->chap_server.challenge_pktlen = PPP_HDRLEN + len; + + p = pcb->chap_server.challenge + PPP_HDRLEN; + p[0] = CHAP_CHALLENGE; + p[1] = ++pcb->chap_server.id; + p[2] = len >> 8; + p[3] = len; +} + +/* + * chap_handle_response - check the response to our challenge. + */ +static void chap_handle_response(ppp_pcb *pcb, int id, + unsigned char *pkt, int len) { + int response_len, ok, mlen; + const unsigned char *response; + unsigned char *outp; + struct pbuf *p; + const char *name = NULL; /* initialized to shut gcc up */ +#if 0 /* UNUSED */ + int (*verifier)(const char *, const char *, int, const struct chap_digest_type *, + const unsigned char *, const unsigned char *, char *, int); +#endif /* UNUSED */ + char rname[MAXNAMELEN+1]; + char message[256]; + + if ((pcb->chap_server.flags & LOWERUP) == 0) + return; + if (id != pcb->chap_server.challenge[PPP_HDRLEN+1] || len < 2) + return; + if (pcb->chap_server.flags & CHALLENGE_VALID) { + response = pkt; + GETCHAR(response_len, pkt); + len -= response_len + 1; /* length of name */ + name = (char *)pkt + response_len; + if (len < 0) + return; + + if (pcb->chap_server.flags & TIMEOUT_PENDING) { + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + UNTIMEOUT(chap_timeout, pcb); + } +#if PPP_REMOTENAME + if (pcb->settings.explicit_remote) { + name = pcb->remote_name; + } else +#endif /* PPP_REMOTENAME */ + { + /* Null terminate and clean remote name. */ + ppp_slprintf(rname, sizeof(rname), "%.*v", len, name); + name = rname; + } + +#if 0 /* UNUSED */ + if (chap_verify_hook) + verifier = chap_verify_hook; + else + verifier = chap_verify_response; + ok = (*verifier)(name, pcb->chap_server.name, id, pcb->chap_server.digest, + pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN, + response, pcb->chap_server.message, sizeof(pcb->chap_server.message)); +#endif /* UNUSED */ + ok = chap_verify_response(pcb, name, pcb->chap_server.name, id, pcb->chap_server.digest, + pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN, + response, message, sizeof(message)); +#if 0 /* UNUSED */ + if (!ok || !auth_number()) { +#endif /* UNUSED */ + if (!ok) { + pcb->chap_server.flags |= AUTH_FAILED; + ppp_warn("Peer %q failed CHAP authentication", name); + } + } else if ((pcb->chap_server.flags & AUTH_DONE) == 0) + return; + + /* send the response */ + mlen = strlen(message); + len = CHAP_HDRLEN + mlen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +len), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (unsigned char *)p->payload; + MAKEHEADER(outp, PPP_CHAP); + + outp[0] = (pcb->chap_server.flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS; + outp[1] = id; + outp[2] = len >> 8; + outp[3] = len; + if (mlen > 0) + memcpy(outp + CHAP_HDRLEN, message, mlen); + ppp_write(pcb, p); + + if (pcb->chap_server.flags & CHALLENGE_VALID) { + pcb->chap_server.flags &= ~CHALLENGE_VALID; + if (!(pcb->chap_server.flags & AUTH_DONE) && !(pcb->chap_server.flags & AUTH_FAILED)) { + +#if 0 /* UNUSED */ + /* + * Auth is OK, so now we need to check session restrictions + * to ensure everything is OK, but only if we used a + * plugin, and only if we're configured to check. This + * allows us to do PAM checks on PPP servers that + * authenticate against ActiveDirectory, and use AD for + * account info (like when using Winbind integrated with + * PAM). + */ + if (session_mgmt && + session_check(name, NULL, devnam, NULL) == 0) { + pcb->chap_server.flags |= AUTH_FAILED; + ppp_warn("Peer %q failed CHAP Session verification", name); + } +#endif /* UNUSED */ + + } + if (pcb->chap_server.flags & AUTH_FAILED) { + auth_peer_fail(pcb, PPP_CHAP); + } else { + if ((pcb->chap_server.flags & AUTH_DONE) == 0) + auth_peer_success(pcb, PPP_CHAP, + pcb->chap_server.digest->code, + name, strlen(name)); + if (pcb->settings.chap_rechallenge_time) { + pcb->chap_server.flags |= TIMEOUT_PENDING; + TIMEOUT(chap_timeout, pcb, + pcb->settings.chap_rechallenge_time); + } + } + pcb->chap_server.flags |= AUTH_DONE; + } +} + +/* + * chap_verify_response - check whether the peer's response matches + * what we think it should be. Returns 1 if it does (authentication + * succeeded), or 0 if it doesn't. + */ +static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + int ok; + unsigned char secret[MAXSECRETLEN]; + int secret_len; + + /* Get the secret that the peer is supposed to know */ + if (!get_secret(pcb, name, ourname, (char *)secret, &secret_len, 1)) { + ppp_error("No CHAP secret found for authenticating %q", name); + return 0; + } + ok = digest->verify_response(pcb, id, name, secret, secret_len, challenge, + response, message, message_space); + memset(secret, 0, sizeof(secret)); + + return ok; +} +#endif /* PPP_SERVER */ + +/* + * chap_respond - Generate and send a response to a challenge. + */ +static void chap_respond(ppp_pcb *pcb, int id, + unsigned char *pkt, int len) { + int clen, nlen; + int secret_len; + struct pbuf *p; + u_char *outp; + char rname[MAXNAMELEN+1]; + char secret[MAXSECRETLEN+1]; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(RESP_MAX_PKTLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + if ((pcb->chap_client.flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED)) + return; /* not ready */ + if (len < 2 || len < pkt[0] + 1) + return; /* too short */ + clen = pkt[0]; + nlen = len - (clen + 1); + + /* Null terminate and clean remote name. */ + ppp_slprintf(rname, sizeof(rname), "%.*v", nlen, pkt + clen + 1); + +#if PPP_REMOTENAME + /* Microsoft doesn't send their name back in the PPP packet */ + if (pcb->settings.explicit_remote || (pcb->settings.remote_name[0] != 0 && rname[0] == 0)) + strlcpy(rname, pcb->settings.remote_name, sizeof(rname)); +#endif /* PPP_REMOTENAME */ + + /* get secret for authenticating ourselves with the specified host */ + if (!get_secret(pcb, pcb->chap_client.name, rname, secret, &secret_len, 0)) { + secret_len = 0; /* assume null secret if can't find one */ + ppp_warn("No CHAP secret found for authenticating us to %q", rname); + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_CHAP); + outp += CHAP_HDRLEN; + + pcb->chap_client.digest->make_response(pcb, outp, id, pcb->chap_client.name, pkt, + secret, secret_len, pcb->chap_client.priv); + memset(secret, 0, secret_len); + + clen = *outp; + nlen = strlen(pcb->chap_client.name); + memcpy(outp + clen + 1, pcb->chap_client.name, nlen); + + outp = (u_char*)p->payload + PPP_HDRLEN; + len = CHAP_HDRLEN + clen + 1 + nlen; + outp[0] = CHAP_RESPONSE; + outp[1] = id; + outp[2] = len >> 8; + outp[3] = len; + + pbuf_realloc(p, PPP_HDRLEN + len); + ppp_write(pcb, p); +} + +static void chap_handle_status(ppp_pcb *pcb, int code, int id, + unsigned char *pkt, int len) { + const char *msg = NULL; + LWIP_UNUSED_ARG(id); + + if ((pcb->chap_client.flags & (AUTH_DONE|AUTH_STARTED|LOWERUP)) + != (AUTH_STARTED|LOWERUP)) + return; + pcb->chap_client.flags |= AUTH_DONE; + + if (code == CHAP_SUCCESS) { + /* used for MS-CHAP v2 mutual auth, yuck */ + if (pcb->chap_client.digest->check_success != NULL) { + if (!(*pcb->chap_client.digest->check_success)(pcb, pkt, len, pcb->chap_client.priv)) + code = CHAP_FAILURE; + } else + msg = "CHAP authentication succeeded"; + } else { + if (pcb->chap_client.digest->handle_failure != NULL) + (*pcb->chap_client.digest->handle_failure)(pcb, pkt, len); + else + msg = "CHAP authentication failed"; + } + if (msg) { + if (len > 0) + ppp_info("%s: %.*v", msg, len, pkt); + else + ppp_info("%s", msg); + } + if (code == CHAP_SUCCESS) + auth_withpeer_success(pcb, PPP_CHAP, pcb->chap_client.digest->code); + else { + pcb->chap_client.flags |= AUTH_FAILED; + ppp_error("CHAP authentication failed"); + auth_withpeer_fail(pcb, PPP_CHAP); + } +} + +static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen) { + unsigned char code, id; + int len; + + if (pktlen < CHAP_HDRLEN) + return; + GETCHAR(code, pkt); + GETCHAR(id, pkt); + GETSHORT(len, pkt); + if (len < CHAP_HDRLEN || len > pktlen) + return; + len -= CHAP_HDRLEN; + + switch (code) { + case CHAP_CHALLENGE: + chap_respond(pcb, id, pkt, len); + break; +#if PPP_SERVER + case CHAP_RESPONSE: + chap_handle_response(pcb, id, pkt, len); + break; +#endif /* PPP_SERVER */ + case CHAP_FAILURE: + case CHAP_SUCCESS: + chap_handle_status(pcb, code, id, pkt, len); + break; + default: + break; + } +} + +static void chap_protrej(ppp_pcb *pcb) { + +#if PPP_SERVER + if (pcb->chap_server.flags & TIMEOUT_PENDING) { + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + UNTIMEOUT(chap_timeout, pcb); + } + if (pcb->chap_server.flags & AUTH_STARTED) { + pcb->chap_server.flags = 0; + auth_peer_fail(pcb, PPP_CHAP); + } +#endif /* PPP_SERVER */ + if ((pcb->chap_client.flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) { + pcb->chap_client.flags &= ~AUTH_STARTED; + ppp_error("CHAP authentication failed due to protocol-reject"); + auth_withpeer_fail(pcb, PPP_CHAP); + } +} + +#if PRINTPKT_SUPPORT +/* + * chap_print_pkt - print the contents of a CHAP packet. + */ +static const char* const chap_code_names[] = { + "Challenge", "Response", "Success", "Failure" +}; + +static int chap_print_pkt(const unsigned char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len; + int clen, nlen; + unsigned char x; + + if (plen < CHAP_HDRLEN) + return 0; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < CHAP_HDRLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(chap_code_names)) + printer(arg, " %s", chap_code_names[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= CHAP_HDRLEN; + switch (code) { + case CHAP_CHALLENGE: + case CHAP_RESPONSE: + if (len < 1) + break; + clen = p[0]; + if (len < clen + 1) + break; + ++p; + nlen = len - clen - 1; + printer(arg, " <"); + for (; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, "%.2x", x); + } + printer(arg, ">, name = "); + ppp_print_string(p, nlen, printer, arg); + break; + case CHAP_FAILURE: + case CHAP_SUCCESS: + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + break; + default: + for (clen = len; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } + /* no break */ + } + + return len + CHAP_HDRLEN; +} +#endif /* PRINTPKT_SUPPORT */ + +const struct protent chap_protent = { + PPP_CHAP, + chap_init, + chap_input, + chap_protrej, + chap_lowerup, + chap_lowerdown, + NULL, /* open */ + NULL, /* close */ +#if PRINTPKT_SUPPORT + chap_print_pkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, /* datainput */ +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "CHAP", /* name */ + NULL, /* data_name */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + chap_option_list, + NULL, /* check_options */ +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/chap_ms.c b/components/net/lwip-2.0.3/src/netif/ppp/chap_ms.c new file mode 100644 index 0000000000..5a989c9b7e --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/chap_ms.c @@ -0,0 +1,962 @@ +/* + * chap_ms.c - Microsoft MS-CHAP compatible implementation. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 + * + * Implemented LANManager type password response to MS-CHAP challenges. + * Now pppd provides both NT style and LANMan style blocks, and the + * prefered is set by option "ms-lanman". Default is to use NT. + * The hash text (StdText) was taken from Win95 RASAPI32.DLL. + * + * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 + */ + +/* + * Modifications by Frank Cusack, frank@google.com, March 2002. + * + * Implemented MS-CHAPv2 functionality, heavily based on sample + * implementation in RFC 2759. Implemented MPPE functionality, + * heavily based on sample implementation in RFC 3079. + * + * Copyright (c) 2002 Google, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap_ms.h" +#include "netif/ppp/pppcrypt.h" +#include "netif/ppp/magic.h" +#if MPPE_SUPPORT +#include "netif/ppp/mppe.h" /* For mppe_sha1_pad*, mppe_set_key() */ +#endif /* MPPE_SUPPORT */ + +#define SHA1_SIGNATURE_SIZE 20 +#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */ +#define MAX_NT_PASSWORD 256 /* Max (Unicode) chars in an NT pass */ + +#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ +#define MS_CHAP2_RESPONSE_LEN 49 /* Response length for MS-CHAPv2 */ +#define MS_AUTH_RESPONSE_LENGTH 40 /* MS-CHAPv2 authenticator response, */ + /* as ASCII */ + +/* Error codes for MS-CHAP failure messages. */ +#define MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS 646 +#define MS_CHAP_ERROR_ACCT_DISABLED 647 +#define MS_CHAP_ERROR_PASSWD_EXPIRED 648 +#define MS_CHAP_ERROR_NO_DIALIN_PERMISSION 649 +#define MS_CHAP_ERROR_AUTHENTICATION_FAILURE 691 +#define MS_CHAP_ERROR_CHANGING_PASSWORD 709 + +/* + * Offsets within the response field for MS-CHAP + */ +#define MS_CHAP_LANMANRESP 0 +#define MS_CHAP_LANMANRESP_LEN 24 +#define MS_CHAP_NTRESP 24 +#define MS_CHAP_NTRESP_LEN 24 +#define MS_CHAP_USENT 48 + +/* + * Offsets within the response field for MS-CHAP2 + */ +#define MS_CHAP2_PEER_CHALLENGE 0 +#define MS_CHAP2_PEER_CHAL_LEN 16 +#define MS_CHAP2_RESERVED_LEN 8 +#define MS_CHAP2_NTRESP 24 +#define MS_CHAP2_NTRESP_LEN 24 +#define MS_CHAP2_FLAGS 48 + +#if MPPE_SUPPORT +#if 0 /* UNUSED */ +/* These values are the RADIUS attribute values--see RFC 2548. */ +#define MPPE_ENC_POL_ENC_ALLOWED 1 +#define MPPE_ENC_POL_ENC_REQUIRED 2 +#define MPPE_ENC_TYPES_RC4_40 2 +#define MPPE_ENC_TYPES_RC4_128 4 + +/* used by plugins (using above values) */ +extern void set_mppe_enc_types(int, int); +#endif /* UNUSED */ +#endif /* MPPE_SUPPORT */ + +/* Are we the authenticator or authenticatee? For MS-CHAPv2 key derivation. */ +#define MS_CHAP2_AUTHENTICATEE 0 +#define MS_CHAP2_AUTHENTICATOR 1 + +static void ascii2unicode (const char[], int, u_char[]); +static void NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]); +static void ChallengeResponse (const u_char *, const u_char *, u_char[24]); +static void ChallengeHash (const u_char[16], const u_char *, const char *, u_char[8]); +static void ChapMS_NT (const u_char *, const char *, int, u_char[24]); +static void ChapMS2_NT (const u_char *, const u_char[16], const char *, const char *, int, + u_char[24]); +static void GenerateAuthenticatorResponsePlain + (const char*, int, u_char[24], const u_char[16], const u_char *, + const char *, u_char[41]); +#ifdef MSLANMAN +static void ChapMS_LANMan (u_char *, char *, int, u_char *); +#endif + +static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[24], const u_char PeerChallenge[16], + const u_char *rchallenge, const char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]); + +#if MPPE_SUPPORT +static void Set_Start_Key (ppp_pcb *pcb, const u_char *, const char *, int); +static void SetMasterKeys (ppp_pcb *pcb, const char *, int, u_char[24], int); +#endif /* MPPE_SUPPORT */ + +static void ChapMS (ppp_pcb *pcb, const u_char *, const char *, int, u_char *); +static void ChapMS2 (ppp_pcb *pcb, const u_char *, const u_char *, const char *, const char *, int, + u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int); + +#ifdef MSLANMAN +bool ms_lanman = 0; /* Use LanMan password instead of NT */ + /* Has meaning only with MS-CHAP challenges */ +#endif + +#if MPPE_SUPPORT +#ifdef DEBUGMPPEKEY +/* For MPPE debug */ +/* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */ +static char *mschap_challenge = NULL; +/* Use "!@\#$%^&*()_+:3|~" (sans quotes, backslash is to escape #) for ... */ +static char *mschap2_peer_challenge = NULL; +#endif + +#include "netif/ppp/fsm.h" /* Need to poke MPPE options */ +#include "netif/ppp/ccp.h" +#endif /* MPPE_SUPPORT */ + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t chapms_option_list[] = { +#ifdef MSLANMAN + { "ms-lanman", o_bool, &ms_lanman, + "Use LanMan passwd when using MS-CHAP", 1 }, +#endif +#ifdef DEBUGMPPEKEY + { "mschap-challenge", o_string, &mschap_challenge, + "specify CHAP challenge" }, + { "mschap2-peer-challenge", o_string, &mschap2_peer_challenge, + "specify CHAP peer challenge" }, +#endif + { NULL } +}; +#endif /* PPP_OPTIONS */ + +#if PPP_SERVER +/* + * chapms_generate_challenge - generate a challenge for MS-CHAP. + * For MS-CHAP the challenge length is fixed at 8 bytes. + * The length goes in challenge[0] and the actual challenge starts + * at challenge[1]. + */ +static void chapms_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) { + LWIP_UNUSED_ARG(pcb); + + *challenge++ = 8; +#ifdef DEBUGMPPEKEY + if (mschap_challenge && strlen(mschap_challenge) == 8) + memcpy(challenge, mschap_challenge, 8); + else +#endif + magic_random_bytes(challenge, 8); +} + +static void chapms2_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) { + LWIP_UNUSED_ARG(pcb); + + *challenge++ = 16; +#ifdef DEBUGMPPEKEY + if (mschap_challenge && strlen(mschap_challenge) == 16) + memcpy(challenge, mschap_challenge, 16); + else +#endif + magic_random_bytes(challenge, 16); +} + +static int chapms_verify_response(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + unsigned char md[MS_CHAP_RESPONSE_LEN]; + int diff; + int challenge_len, response_len; + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(name); + + challenge_len = *challenge++; /* skip length, is 8 */ + response_len = *response++; + if (response_len != MS_CHAP_RESPONSE_LEN) + goto bad; + +#ifndef MSLANMAN + if (!response[MS_CHAP_USENT]) { + /* Should really propagate this into the error packet. */ + ppp_notice("Peer request for LANMAN auth not supported"); + goto bad; + } +#endif + + /* Generate the expected response. */ + ChapMS(pcb, (const u_char *)challenge, (const char *)secret, secret_len, md); + +#ifdef MSLANMAN + /* Determine which part of response to verify against */ + if (!response[MS_CHAP_USENT]) + diff = memcmp(&response[MS_CHAP_LANMANRESP], + &md[MS_CHAP_LANMANRESP], MS_CHAP_LANMANRESP_LEN); + else +#endif + diff = memcmp(&response[MS_CHAP_NTRESP], &md[MS_CHAP_NTRESP], + MS_CHAP_NTRESP_LEN); + + if (diff == 0) { + ppp_slprintf(message, message_space, "Access granted"); + return 1; + } + + bad: + /* See comments below for MS-CHAP V2 */ + ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0", + challenge_len, challenge); + return 0; +} + +static int chapms2_verify_response(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + unsigned char md[MS_CHAP2_RESPONSE_LEN]; + char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; + int challenge_len, response_len; + LWIP_UNUSED_ARG(id); + + challenge_len = *challenge++; /* skip length, is 16 */ + response_len = *response++; + if (response_len != MS_CHAP2_RESPONSE_LEN) + goto bad; /* not even the right length */ + + /* Generate the expected response and our mutual auth. */ + ChapMS2(pcb, (const u_char*)challenge, (const u_char*)&response[MS_CHAP2_PEER_CHALLENGE], name, + (const char *)secret, secret_len, md, + (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR); + + /* compare MDs and send the appropriate status */ + /* + * Per RFC 2759, success message must be formatted as + * "S= M=" + * where + * is the Authenticator Response (mutual auth) + * is a text message + * + * However, some versions of Windows (win98 tested) do not know + * about the M= part (required per RFC 2759) and flag + * it as an error (reported incorrectly as an encryption error + * to the user). Since the RFC requires it, and it can be + * useful information, we supply it if the peer is a conforming + * system. Luckily (?), win98 sets the Flags field to 0x04 + * (contrary to RFC requirements) so we can use that to + * distinguish between conforming and non-conforming systems. + * + * Special thanks to Alex Swiridov for + * help debugging this. + */ + if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP], + MS_CHAP2_NTRESP_LEN) == 0) { + if (response[MS_CHAP2_FLAGS]) + ppp_slprintf(message, message_space, "S=%s", saresponse); + else + ppp_slprintf(message, message_space, "S=%s M=%s", + saresponse, "Access granted"); + return 1; + } + + bad: + /* + * Failure message must be formatted as + * "E=e R=r C=c V=v M=m" + * where + * e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE) + * r = retry (we use 1, ok to retry) + * c = challenge to use for next response, we reuse previous + * v = Change Password version supported, we use 0 + * m = text message + * + * The M=m part is only for MS-CHAPv2. Neither win2k nor + * win98 (others untested) display the message to the user anyway. + * They also both ignore the E=e code. + * + * Note that it's safe to reuse the same challenge as we don't + * actually accept another response based on the error message + * (and no clients try to resend a response anyway). + * + * Basically, this whole bit is useless code, even the small + * implementation here is only because of overspecification. + */ + ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s", + challenge_len, challenge, "Access denied"); + return 0; +} +#endif /* PPP_SERVER */ + +static void chapms_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *private_) { + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(our_name); + LWIP_UNUSED_ARG(private_); + challenge++; /* skip length, should be 8 */ + *response++ = MS_CHAP_RESPONSE_LEN; + ChapMS(pcb, challenge, secret, secret_len, response); +} + +static void chapms2_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *private_) { + LWIP_UNUSED_ARG(id); + challenge++; /* skip length, should be 16 */ + *response++ = MS_CHAP2_RESPONSE_LEN; + ChapMS2(pcb, challenge, +#ifdef DEBUGMPPEKEY + mschap2_peer_challenge, +#else + NULL, +#endif + our_name, secret, secret_len, response, private_, + MS_CHAP2_AUTHENTICATEE); +} + +static int chapms2_check_success(ppp_pcb *pcb, unsigned char *msg, int len, unsigned char *private_) { + LWIP_UNUSED_ARG(pcb); + + if ((len < MS_AUTH_RESPONSE_LENGTH + 2) || + strncmp((char *)msg, "S=", 2) != 0) { + /* Packet does not start with "S=" */ + ppp_error("MS-CHAPv2 Success packet is badly formed."); + return 0; + } + msg += 2; + len -= 2; + if (len < MS_AUTH_RESPONSE_LENGTH + || memcmp(msg, private_, MS_AUTH_RESPONSE_LENGTH)) { + /* Authenticator Response did not match expected. */ + ppp_error("MS-CHAPv2 mutual authentication failed."); + return 0; + } + /* Authenticator Response matches. */ + msg += MS_AUTH_RESPONSE_LENGTH; /* Eat it */ + len -= MS_AUTH_RESPONSE_LENGTH; + if ((len >= 3) && !strncmp((char *)msg, " M=", 3)) { + msg += 3; /* Eat the delimiter */ + } else if (len) { + /* Packet has extra text which does not begin " M=" */ + ppp_error("MS-CHAPv2 Success packet is badly formed."); + return 0; + } + return 1; +} + +static void chapms_handle_failure(ppp_pcb *pcb, unsigned char *inp, int len) { + int err; + const char *p; + char msg[64]; + LWIP_UNUSED_ARG(pcb); + + /* We want a null-terminated string for strxxx(). */ + len = LWIP_MIN(len, 63); + MEMCPY(msg, inp, len); + msg[len] = 0; + p = msg; + + /* + * Deal with MS-CHAP formatted failure messages; just print the + * M= part (if any). For MS-CHAP we're not really supposed + * to use M=, but it shouldn't hurt. See + * chapms[2]_verify_response. + */ + if (!strncmp(p, "E=", 2)) + err = strtol(p+2, NULL, 10); /* Remember the error code. */ + else + goto print_msg; /* Message is badly formatted. */ + + if (len && ((p = strstr(p, " M=")) != NULL)) { + /* M= field found. */ + p += 3; + } else { + /* No M=; use the error code. */ + switch (err) { + case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS: + p = "E=646 Restricted logon hours"; + break; + + case MS_CHAP_ERROR_ACCT_DISABLED: + p = "E=647 Account disabled"; + break; + + case MS_CHAP_ERROR_PASSWD_EXPIRED: + p = "E=648 Password expired"; + break; + + case MS_CHAP_ERROR_NO_DIALIN_PERMISSION: + p = "E=649 No dialin permission"; + break; + + case MS_CHAP_ERROR_AUTHENTICATION_FAILURE: + p = "E=691 Authentication failure"; + break; + + case MS_CHAP_ERROR_CHANGING_PASSWORD: + /* Should never see this, we don't support Change Password. */ + p = "E=709 Error changing password"; + break; + + default: + ppp_error("Unknown MS-CHAP authentication failure: %.*v", + len, inp); + return; + } + } +print_msg: + if (p != NULL) + ppp_error("MS-CHAP authentication failed: %v", p); +} + +static void ChallengeResponse(const u_char *challenge, + const u_char PasswordHash[MD4_SIGNATURE_SIZE], + u_char response[24]) { + u_char ZPasswordHash[21]; + lwip_des_context des; + u_char des_key[8]; + + BZERO(ZPasswordHash, sizeof(ZPasswordHash)); + MEMCPY(ZPasswordHash, PasswordHash, MD4_SIGNATURE_SIZE); + +#if 0 + dbglog("ChallengeResponse - ZPasswordHash %.*B", + sizeof(ZPasswordHash), ZPasswordHash); +#endif + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 0, des_key); + lwip_des_init(&des); + lwip_des_setkey_enc(&des, des_key); + lwip_des_crypt_ecb(&des, challenge, response +0); + lwip_des_free(&des); + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 7, des_key); + lwip_des_init(&des); + lwip_des_setkey_enc(&des, des_key); + lwip_des_crypt_ecb(&des, challenge, response +8); + lwip_des_free(&des); + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 14, des_key); + lwip_des_init(&des); + lwip_des_setkey_enc(&des, des_key); + lwip_des_crypt_ecb(&des, challenge, response +16); + lwip_des_free(&des); + +#if 0 + dbglog("ChallengeResponse - response %.24B", response); +#endif +} + +static void ChallengeHash(const u_char PeerChallenge[16], const u_char *rchallenge, + const char *username, u_char Challenge[8]) { + lwip_sha1_context sha1Context; + u_char sha1Hash[SHA1_SIGNATURE_SIZE]; + const char *user; + + /* remove domain from "domain\username" */ + if ((user = strrchr(username, '\\')) != NULL) + ++user; + else + user = username; + + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, PeerChallenge, 16); + lwip_sha1_update(&sha1Context, rchallenge, 16); + lwip_sha1_update(&sha1Context, (const unsigned char*)user, strlen(user)); + lwip_sha1_finish(&sha1Context, sha1Hash); + lwip_sha1_free(&sha1Context); + + MEMCPY(Challenge, sha1Hash, 8); +} + +/* + * Convert the ASCII version of the password to Unicode. + * This implicitly supports 8-bit ISO8859/1 characters. + * This gives us the little-endian representation, which + * is assumed by all M$ CHAP RFCs. (Unicode byte ordering + * is machine-dependent.) + */ +static void ascii2unicode(const char ascii[], int ascii_len, u_char unicode[]) { + int i; + + BZERO(unicode, ascii_len * 2); + for (i = 0; i < ascii_len; i++) + unicode[i * 2] = (u_char) ascii[i]; +} + +static void NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) { + lwip_md4_context md4Context; + + lwip_md4_init(&md4Context); + lwip_md4_starts(&md4Context); + lwip_md4_update(&md4Context, secret, secret_len); + lwip_md4_finish(&md4Context, hash); + lwip_md4_free(&md4Context); +} + +static void ChapMS_NT(const u_char *rchallenge, const char *secret, int secret_len, + u_char NTResponse[24]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + + /* Hash the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + + ChallengeResponse(rchallenge, PasswordHash, NTResponse); +} + +static void ChapMS2_NT(const u_char *rchallenge, const u_char PeerChallenge[16], const char *username, + const char *secret, int secret_len, u_char NTResponse[24]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char Challenge[8]; + + ChallengeHash(PeerChallenge, rchallenge, username, Challenge); + + /* Hash the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + + ChallengeResponse(Challenge, PasswordHash, NTResponse); +} + +#ifdef MSLANMAN +static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ + +static void ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len, + unsigned char *response) { + int i; + u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + lwip_des_context des; + u_char des_key[8]; + + /* LANMan password is case insensitive */ + BZERO(UcasePassword, sizeof(UcasePassword)); + for (i = 0; i < secret_len; i++) + UcasePassword[i] = (u_char)toupper(secret[i]); + + pppcrypt_56_to_64_bit_key(UcasePassword +0, des_key); + lwip_des_init(&des); + lwip_des_setkey_enc(&des, des_key); + lwip_des_crypt_ecb(&des, StdText, PasswordHash +0); + lwip_des_free(&des); + + pppcrypt_56_to_64_bit_key(UcasePassword +7, des_key); + lwip_des_init(&des); + lwip_des_setkey_enc(&des, des_key); + lwip_des_crypt_ecb(&des, StdText, PasswordHash +8); + lwip_des_free(&des); + + ChallengeResponse(rchallenge, PasswordHash, &response[MS_CHAP_LANMANRESP]); +} +#endif + + +static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[24], const u_char PeerChallenge[16], + const u_char *rchallenge, const char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { + /* + * "Magic" constants used in response generation, from RFC 2759. + */ + static const u_char Magic1[39] = /* "Magic server to client signing constant" */ + { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, + 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, + 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; + static const u_char Magic2[41] = /* "Pad to make it do more than one iteration" */ + { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, + 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, + 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, + 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E }; + + int i; + lwip_sha1_context sha1Context; + u_char Digest[SHA1_SIGNATURE_SIZE]; + u_char Challenge[8]; + + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + lwip_sha1_update(&sha1Context, NTResponse, 24); + lwip_sha1_update(&sha1Context, Magic1, sizeof(Magic1)); + lwip_sha1_finish(&sha1Context, Digest); + lwip_sha1_free(&sha1Context); + + ChallengeHash(PeerChallenge, rchallenge, username, Challenge); + + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, Digest, sizeof(Digest)); + lwip_sha1_update(&sha1Context, Challenge, sizeof(Challenge)); + lwip_sha1_update(&sha1Context, Magic2, sizeof(Magic2)); + lwip_sha1_finish(&sha1Context, Digest); + lwip_sha1_free(&sha1Context); + + /* Convert to ASCII hex string. */ + for (i = 0; i < LWIP_MAX((MS_AUTH_RESPONSE_LENGTH / 2), (int)sizeof(Digest)); i++) + sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]); +} + + +static void GenerateAuthenticatorResponsePlain( + const char *secret, int secret_len, + u_char NTResponse[24], const u_char PeerChallenge[16], + const u_char *rchallenge, const char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), + PasswordHashHash); + + GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge, + rchallenge, username, authResponse); +} + + +#if MPPE_SUPPORT +/* + * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079) + */ +static void Set_Start_Key(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + lwip_sha1_context sha1Context; + u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + lwip_sha1_update(&sha1Context, rchallenge, 8); + lwip_sha1_finish(&sha1Context, Digest); + lwip_sha1_free(&sha1Context); + + /* Same key in both directions. */ + mppe_set_key(pcb, &pcb->mppe_comp, Digest); + mppe_set_key(pcb, &pcb->mppe_decomp, Digest); + + pcb->mppe_keys_set = 1; +} + +/* + * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) + */ +static void SetMasterKeys(ppp_pcb *pcb, const char *secret, int secret_len, u_char NTResponse[24], int IsServer) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + lwip_sha1_context sha1Context; + u_char MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + const u_char *s; + + /* "This is the MPPE Master Key" */ + static const u_char Magic1[27] = + { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; + /* "On the client side, this is the send key; " + "on the server side, it is the receive key." */ + static const u_char Magic2[84] = + { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, + 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, + 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x2e }; + /* "On the client side, this is the receive key; " + "on the server side, it is the send key." */ + static const u_char Magic3[84] = + { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, + 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, + 0x6b, 0x65, 0x79, 0x2e }; + + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + lwip_sha1_update(&sha1Context, NTResponse, 24); + lwip_sha1_update(&sha1Context, Magic1, sizeof(Magic1)); + lwip_sha1_finish(&sha1Context, MasterKey); + lwip_sha1_free(&sha1Context); + + /* + * generate send key + */ + if (IsServer) + s = Magic3; + else + s = Magic2; + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, MasterKey, 16); + lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); + lwip_sha1_update(&sha1Context, s, 84); + lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); + lwip_sha1_finish(&sha1Context, Digest); + lwip_sha1_free(&sha1Context); + + mppe_set_key(pcb, &pcb->mppe_comp, Digest); + + /* + * generate recv key + */ + if (IsServer) + s = Magic2; + else + s = Magic3; + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, MasterKey, 16); + lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); + lwip_sha1_update(&sha1Context, s, 84); + lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); + lwip_sha1_finish(&sha1Context, Digest); + lwip_sha1_free(&sha1Context); + + mppe_set_key(pcb, &pcb->mppe_decomp, Digest); + + pcb->mppe_keys_set = 1; +} + +#endif /* MPPE_SUPPORT */ + + +static void ChapMS(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len, + unsigned char *response) { +#if !MPPE_SUPPORT + LWIP_UNUSED_ARG(pcb); +#endif /* !MPPE_SUPPORT */ + BZERO(response, MS_CHAP_RESPONSE_LEN); + + ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]); + +#ifdef MSLANMAN + ChapMS_LANMan(rchallenge, secret, secret_len, + &response[MS_CHAP_LANMANRESP]); + + /* preferred method is set by option */ + response[MS_CHAP_USENT] = !ms_lanman; +#else + response[MS_CHAP_USENT] = 1; +#endif + +#if MPPE_SUPPORT + Set_Start_Key(pcb, rchallenge, secret, secret_len); +#endif /* MPPE_SUPPORT */ +} + + +/* + * If PeerChallenge is NULL, one is generated and the PeerChallenge + * field of response is filled in. Call this way when generating a response. + * If PeerChallenge is supplied, it is copied into the PeerChallenge field. + * Call this way when verifying a response (or debugging). + * Do not call with PeerChallenge = response. + * + * The PeerChallenge field of response is then used for calculation of the + * Authenticator Response. + */ +static void ChapMS2(ppp_pcb *pcb, const u_char *rchallenge, const u_char *PeerChallenge, + const char *user, const char *secret, int secret_len, unsigned char *response, + u_char authResponse[], int authenticator) { + /* ARGSUSED */ + LWIP_UNUSED_ARG(authenticator); +#if !MPPE_SUPPORT + LWIP_UNUSED_ARG(pcb); +#endif /* !MPPE_SUPPORT */ + + BZERO(response, MS_CHAP2_RESPONSE_LEN); + + /* Generate the Peer-Challenge if requested, or copy it if supplied. */ + if (!PeerChallenge) + magic_random_bytes(&response[MS_CHAP2_PEER_CHALLENGE], MS_CHAP2_PEER_CHAL_LEN); + else + MEMCPY(&response[MS_CHAP2_PEER_CHALLENGE], PeerChallenge, + MS_CHAP2_PEER_CHAL_LEN); + + /* Generate the NT-Response */ + ChapMS2_NT(rchallenge, &response[MS_CHAP2_PEER_CHALLENGE], user, + secret, secret_len, &response[MS_CHAP2_NTRESP]); + + /* Generate the Authenticator Response. */ + GenerateAuthenticatorResponsePlain(secret, secret_len, + &response[MS_CHAP2_NTRESP], + &response[MS_CHAP2_PEER_CHALLENGE], + rchallenge, user, authResponse); + +#if MPPE_SUPPORT + SetMasterKeys(pcb, secret, secret_len, + &response[MS_CHAP2_NTRESP], authenticator); +#endif /* MPPE_SUPPORT */ +} + +#if 0 /* UNUSED */ +#if MPPE_SUPPORT +/* + * Set MPPE options from plugins. + */ +void set_mppe_enc_types(int policy, int types) { + /* Early exit for unknown policies. */ + if (policy != MPPE_ENC_POL_ENC_ALLOWED || + policy != MPPE_ENC_POL_ENC_REQUIRED) + return; + + /* Don't modify MPPE if it's optional and wasn't already configured. */ + if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe) + return; + + /* + * Disable undesirable encryption types. Note that we don't ENABLE + * any encryption types, to avoid overriding manual configuration. + */ + switch(types) { + case MPPE_ENC_TYPES_RC4_40: + ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */ + break; + case MPPE_ENC_TYPES_RC4_128: + ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */ + break; + default: + break; + } +} +#endif /* MPPE_SUPPORT */ +#endif /* UNUSED */ + +const struct chap_digest_type chapms_digest = { + CHAP_MICROSOFT, /* code */ +#if PPP_SERVER + chapms_generate_challenge, + chapms_verify_response, +#endif /* PPP_SERVER */ + chapms_make_response, + NULL, /* check_success */ + chapms_handle_failure, +}; + +const struct chap_digest_type chapms2_digest = { + CHAP_MICROSOFT_V2, /* code */ +#if PPP_SERVER + chapms2_generate_challenge, + chapms2_verify_response, +#endif /* PPP_SERVER */ + chapms2_make_response, + chapms2_check_success, + chapms_handle_failure, +}; + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/demand.c b/components/net/lwip-2.0.3/src/netif/ppp/demand.c new file mode 100644 index 0000000000..26c6c30db1 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/demand.c @@ -0,0 +1,465 @@ +/* + * demand.c - Support routines for demand-dialling. + * + * Copyright (c) 1996-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && DEMAND_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef PPP_FILTER +#include +#endif + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/lcp.h" + +char *frame; +int framelen; +int framemax; +int escape_flag; +int flush_flag; +int fcs; + +struct packet { + int length; + struct packet *next; + unsigned char data[1]; +}; + +struct packet *pend_q; +struct packet *pend_qtail; + +static int active_packet (unsigned char *, int); + +/* + * demand_conf - configure the interface for doing dial-on-demand. + */ +void +demand_conf() +{ + int i; + const struct protent *protp; + +/* framemax = lcp_allowoptions[0].mru; + if (framemax < PPP_MRU) */ + framemax = PPP_MRU; + framemax += PPP_HDRLEN + PPP_FCSLEN; + frame = malloc(framemax); + if (frame == NULL) + novm("demand frame"); + framelen = 0; + pend_q = NULL; + escape_flag = 0; + flush_flag = 0; + fcs = PPP_INITFCS; + + netif_set_mtu(pcb, LWIP_MIN(lcp_allowoptions[0].mru, PPP_MRU)); + if (ppp_send_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0 + || ppp_recv_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0) + fatal("Couldn't set up demand-dialled PPP interface: %m"); + +#ifdef PPP_FILTER + set_filters(&pass_filter, &active_filter); +#endif + + /* + * Call the demand_conf procedure for each protocol that's got one. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + ((*protp->demand_conf)(pcb)); +/* FIXME: find a way to die() here */ +#if 0 + if (!((*protp->demand_conf)(pcb))) + die(1); +#endif +} + + +/* + * demand_block - set each network protocol to block further packets. + */ +void +demand_block() +{ + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_QUEUE); + get_loop_output(); +} + +/* + * demand_discard - set each network protocol to discard packets + * with an error. + */ +void +demand_discard() +{ + struct packet *pkt, *nextpkt; + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_ERROR); + get_loop_output(); + + /* discard all saved packets */ + for (pkt = pend_q; pkt != NULL; pkt = nextpkt) { + nextpkt = pkt->next; + free(pkt); + } + pend_q = NULL; + framelen = 0; + flush_flag = 0; + escape_flag = 0; + fcs = PPP_INITFCS; +} + +/* + * demand_unblock - set each enabled network protocol to pass packets. + */ +void +demand_unblock() +{ + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_PASS); +} + +/* + * FCS lookup table as calculated by genfcstab. + */ +static u_short fcstab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +/* + * loop_chars - process characters received from the loopback. + * Calls loop_frame when a complete frame has been accumulated. + * Return value is 1 if we need to bring up the link, 0 otherwise. + */ +int +loop_chars(p, n) + unsigned char *p; + int n; +{ + int c, rv; + + rv = 0; + +/* check for synchronous connection... */ + + if ( (p[0] == 0xFF) && (p[1] == 0x03) ) { + rv = loop_frame(p,n); + return rv; + } + + for (; n > 0; --n) { + c = *p++; + if (c == PPP_FLAG) { + if (!escape_flag && !flush_flag + && framelen > 2 && fcs == PPP_GOODFCS) { + framelen -= 2; + if (loop_frame((unsigned char *)frame, framelen)) + rv = 1; + } + framelen = 0; + flush_flag = 0; + escape_flag = 0; + fcs = PPP_INITFCS; + continue; + } + if (flush_flag) + continue; + if (escape_flag) { + c ^= PPP_TRANS; + escape_flag = 0; + } else if (c == PPP_ESCAPE) { + escape_flag = 1; + continue; + } + if (framelen >= framemax) { + flush_flag = 1; + continue; + } + frame[framelen++] = c; + fcs = PPP_FCS(fcs, c); + } + return rv; +} + +/* + * loop_frame - given a frame obtained from the loopback, + * decide whether to bring up the link or not, and, if we want + * to transmit this frame later, put it on the pending queue. + * Return value is 1 if we need to bring up the link, 0 otherwise. + * We assume that the kernel driver has already applied the + * pass_filter, so we won't get packets it rejected. + * We apply the active_filter to see if we want this packet to + * bring up the link. + */ +int +loop_frame(frame, len) + unsigned char *frame; + int len; +{ + struct packet *pkt; + + /* dbglog("from loop: %P", frame, len); */ + if (len < PPP_HDRLEN) + return 0; + if ((PPP_PROTOCOL(frame) & 0x8000) != 0) + return 0; /* shouldn't get any of these anyway */ + if (!active_packet(frame, len)) + return 0; + + pkt = (struct packet *) malloc(sizeof(struct packet) + len); + if (pkt != NULL) { + pkt->length = len; + pkt->next = NULL; + memcpy(pkt->data, frame, len); + if (pend_q == NULL) + pend_q = pkt; + else + pend_qtail->next = pkt; + pend_qtail = pkt; + } + return 1; +} + +/* + * demand_rexmit - Resend all those frames which we got via the + * loopback, now that the real serial link is up. + */ +void +demand_rexmit(proto, newip) + int proto; + u32_t newip; +{ + struct packet *pkt, *prev, *nextpkt; + unsigned short checksum; + unsigned short pkt_checksum = 0; + unsigned iphdr; + struct timeval tv; + char cv = 0; + char ipstr[16]; + + prev = NULL; + pkt = pend_q; + pend_q = NULL; + tv.tv_sec = 1; + tv.tv_usec = 0; + select(0,NULL,NULL,NULL,&tv); /* Sleep for 1 Seconds */ + for (; pkt != NULL; pkt = nextpkt) { + nextpkt = pkt->next; + if (PPP_PROTOCOL(pkt->data) == proto) { + if ( (proto == PPP_IP) && newip ) { + /* Get old checksum */ + + iphdr = (pkt->data[4] & 15) << 2; + checksum = *((unsigned short *) (pkt->data+14)); + if (checksum == 0xFFFF) { + checksum = 0; + } + + + if (pkt->data[13] == 17) { + pkt_checksum = *((unsigned short *) (pkt->data+10+iphdr)); + if (pkt_checksum) { + cv = 1; + if (pkt_checksum == 0xFFFF) { + pkt_checksum = 0; + } + } + else { + cv = 0; + } + } + + if (pkt->data[13] == 6) { + pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr)); + cv = 1; + if (pkt_checksum == 0xFFFF) { + pkt_checksum = 0; + } + } + + /* Delete old Source-IP-Address */ + checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + /* Change Source-IP-Address */ + * ((u32_t *) (pkt->data + 16)) = newip; + + /* Add new Source-IP-Address */ + checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + /* Write new checksum */ + if (!checksum) { + checksum = 0xFFFF; + } + *((unsigned short *) (pkt->data+14)) = checksum; + if (pkt->data[13] == 6) { + *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum; + } + if (cv && (pkt->data[13] == 17) ) { + *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum; + } + + /* Log Packet */ + strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16)))); + if (pkt->data[13] == 1) { + syslog(LOG_INFO,"Open ICMP %s -> %s\n", + ipstr, + inet_ntoa(*( (struct in_addr *) (pkt->data+20)))); + } else { + syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n", + pkt->data[13] == 6 ? "TCP" : "UDP", + ipstr, + ntohs(*( (short *) (pkt->data+iphdr+4))), + inet_ntoa(*( (struct in_addr *) (pkt->data+20))), + ntohs(*( (short *) (pkt->data+iphdr+6)))); + } + } + output(pcb, pkt->data, pkt->length); + free(pkt); + } else { + if (prev == NULL) + pend_q = pkt; + else + prev->next = pkt; + prev = pkt; + } + } + pend_qtail = prev; + if (prev != NULL) + prev->next = NULL; +} + +/* + * Scan a packet to decide whether it is an "active" packet, + * that is, whether it is worth bringing up the link for. + */ +static int +active_packet(p, len) + unsigned char *p; + int len; +{ + int proto, i; + const struct protent *protp; + + if (len < PPP_HDRLEN) + return 0; + proto = PPP_PROTOCOL(p); +#ifdef PPP_FILTER + p[0] = 1; /* outbound packet indicator */ + if ((pass_filter.bf_len != 0 + && bpf_filter(pass_filter.bf_insns, p, len, len) == 0) + || (active_filter.bf_len != 0 + && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) { + p[0] = 0xff; + return 0; + } + p[0] = 0xff; +#endif + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) { + if (protp->active_pkt == NULL) + return 1; + return (*protp->active_pkt)(p, len); + } + } + return 0; /* not a supported protocol !!?? */ +} + +#endif /* PPP_SUPPORT && DEMAND_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/eap.c b/components/net/lwip-2.0.3/src/netif/ppp/eap.c new file mode 100644 index 0000000000..8fb56368e7 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/eap.c @@ -0,0 +1,2423 @@ +/* + * eap.c - Extensible Authentication Protocol for PPP (RFC 2284) + * + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + * + * Non-exclusive rights to redistribute, modify, translate, and use + * this software in source and binary forms, in whole or in part, is + * hereby granted, provided that the above copyright notice is + * duplicated in any source form, and that neither the name of the + * copyright holder nor the author is used to endorse or promote + * products derived from this software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Original version by James Carlson + * + * This implementation of EAP supports MD5-Challenge and SRP-SHA1 + * authentication styles. Note that support of MD5-Challenge is a + * requirement of RFC 2284, and that it's essentially just a + * reimplementation of regular RFC 1994 CHAP using EAP messages. + * + * As an authenticator ("server"), there are multiple phases for each + * style. In the first phase of each style, the unauthenticated peer + * name is queried using the EAP Identity request type. If the + * "remotename" option is used, then this phase is skipped, because + * the peer's name is presumed to be known. + * + * For MD5-Challenge, there are two phases, and the second phase + * consists of sending the challenge itself and handling the + * associated response. + * + * For SRP-SHA1, there are four phases. The second sends 's', 'N', + * and 'g'. The reply contains 'A'. The third sends 'B', and the + * reply contains 'M1'. The forth sends the 'M2' value. + * + * As an authenticatee ("client"), there's just a single phase -- + * responding to the queries generated by the peer. EAP is an + * authenticator-driven protocol. + * + * Based on draft-ietf-pppext-eap-srp-03.txt. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/eap.h" +#include "netif/ppp/magic.h" +#include "netif/ppp/pppcrypt.h" + +#ifdef USE_SRP +#include +#include +#include +#endif /* USE_SRP */ + +#ifndef SHA_DIGESTSIZE +#define SHA_DIGESTSIZE 20 +#endif + +#ifdef USE_SRP +static char *pn_secret = NULL; /* Pseudonym generating secret */ +#endif + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t eap_option_list[] = { + { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout, + "Set retransmit timeout for EAP Requests (server)" }, + { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests, + "Set max number of EAP Requests sent (server)" }, + { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout, + "Set time limit for peer EAP authentication" }, + { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests, + "Set max number of EAP Requests allows (client)" }, + { "eap-interval", o_int, &eap_states[0].es_rechallenge, + "Set interval for EAP rechallenge" }, +#ifdef USE_SRP + { "srp-interval", o_int, &eap_states[0].es_lwrechallenge, + "Set interval for SRP lightweight rechallenge" }, + { "srp-pn-secret", o_string, &pn_secret, + "Long term pseudonym generation secret" }, + { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo, + "Use pseudonym if offered one by server", 1 }, +#endif + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points. + */ +static void eap_init(ppp_pcb *pcb); +static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen); +static void eap_protrej(ppp_pcb *pcb); +static void eap_lowerup(ppp_pcb *pcb); +static void eap_lowerdown(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int eap_printpkt(const u_char *inp, int inlen, + void (*)(void *arg, const char *fmt, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent eap_protent = { + PPP_EAP, /* protocol number */ + eap_init, /* initialization procedure */ + eap_input, /* process a received packet */ + eap_protrej, /* process a received protocol-reject */ + eap_lowerup, /* lower layer has gone up */ + eap_lowerdown, /* lower layer has gone down */ + NULL, /* open the protocol */ + NULL, /* close the protocol */ +#if PRINTPKT_SUPPORT + eap_printpkt, /* print a packet in readable form */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, /* process a received data packet */ +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "EAP", /* text name of protocol */ + NULL, /* text name of corresponding data protocol */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + eap_option_list, /* list of command-line options */ + NULL, /* check requested options; assign defaults */ +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, /* configure interface for demand-dial */ + NULL /* say whether to bring up link for this pkt */ +#endif /* DEMAND_SUPPORT */ +}; + +#ifdef USE_SRP +/* + * A well-known 2048 bit modulus. + */ +static const u_char wkmodulus[] = { + 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, + 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, + 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, + 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50, + 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED, + 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D, + 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D, + 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50, + 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0, + 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, + 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, + 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, + 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA, + 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74, + 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7, + 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B, + 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16, + 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81, + 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, + 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, + 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, + 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA, + 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78, + 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6, + 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29, + 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8, + 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82, + 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, + 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, + 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, + 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2, + 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73 +}; +#endif + +#if PPP_SERVER +/* Local forward declarations. */ +static void eap_server_timeout(void *arg); +#endif /* PPP_SERVER */ + +/* + * Convert EAP state code to printable string for debug. + */ +static const char * eap_state_name(enum eap_state_code esc) +{ + static const char *state_names[] = { EAP_STATES }; + + return (state_names[(int)esc]); +} + +/* + * eap_init - Initialize state for an EAP user. This is currently + * called once by main() during start-up. + */ +static void eap_init(ppp_pcb *pcb) { + + BZERO(&pcb->eap, sizeof(eap_state)); +#if PPP_SERVER + pcb->eap.es_server.ea_id = magic(); +#endif /* PPP_SERVER */ +} + +/* + * eap_client_timeout - Give up waiting for the peer to send any + * Request messages. + */ +static void eap_client_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (!eap_client_active(pcb)) + return; + + ppp_error("EAP: timeout waiting for Request from peer"); + auth_withpeer_fail(pcb, PPP_EAP); + pcb->eap.es_client.ea_state = eapBadAuth; +} + +/* + * eap_authwithpeer - Authenticate to our peer (behave as client). + * + * Start client state and wait for requests. This is called only + * after eap_lowerup. + */ +void eap_authwithpeer(ppp_pcb *pcb, const char *localname) { + + if(NULL == localname) + return; + + /* Save the peer name we're given */ + pcb->eap.es_client.ea_name = localname; + pcb->eap.es_client.ea_namelen = strlen(localname); + + pcb->eap.es_client.ea_state = eapListen; + + /* + * Start a timer so that if the other end just goes + * silent, we don't sit here waiting forever. + */ + if (pcb->settings.eap_req_time > 0) + TIMEOUT(eap_client_timeout, pcb, + pcb->settings.eap_req_time); +} + +#if PPP_SERVER +/* + * Format a standard EAP Failure message and send it to the peer. + * (Server operation) + */ +static void eap_send_failure(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_FAILURE, outp); + pcb->eap.es_server.ea_id++; + PUTCHAR(pcb->eap.es_server.ea_id, outp); + PUTSHORT(EAP_HEADERLEN, outp); + + ppp_write(pcb, p); + + pcb->eap.es_server.ea_state = eapBadAuth; + auth_peer_fail(pcb, PPP_EAP); +} + +/* + * Format a standard EAP Success message and send it to the peer. + * (Server operation) + */ +static void eap_send_success(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_SUCCESS, outp); + pcb->eap.es_server.ea_id++; + PUTCHAR(pcb->eap.es_server.ea_id, outp); + PUTSHORT(EAP_HEADERLEN, outp); + + ppp_write(pcb, p); + + auth_peer_success(pcb, PPP_EAP, 0, + pcb->eap.es_server.ea_peer, pcb->eap.es_server.ea_peerlen); +} +#endif /* PPP_SERVER */ + +#ifdef USE_SRP +/* + * Set DES key according to pseudonym-generating secret and current + * date. + */ +static bool +pncrypt_setkey(int timeoffs) +{ + struct tm *tp; + char tbuf[9]; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + time_t reftime; + + if (pn_secret == NULL) + return (0); + reftime = time(NULL) + timeoffs; + tp = localtime(&reftime); + SHA1Init(&ctxt); + SHA1Update(&ctxt, pn_secret, strlen(pn_secret)); + strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp); + SHA1Update(&ctxt, tbuf, strlen(tbuf)); + SHA1Final(dig, &ctxt); + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + return (DesSetkey(dig)); +} + +static char base64[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +struct b64state { + u32_t bs_bits; + int bs_offs; +}; + +static int +b64enc(bs, inp, inlen, outp) +struct b64state *bs; +u_char *inp; +int inlen; +u_char *outp; +{ + int outlen = 0; + + while (inlen > 0) { + bs->bs_bits = (bs->bs_bits << 8) | *inp++; + inlen--; + bs->bs_offs += 8; + if (bs->bs_offs >= 24) { + *outp++ = base64[(bs->bs_bits >> 18) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 12) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 6) & 0x3F]; + *outp++ = base64[bs->bs_bits & 0x3F]; + outlen += 4; + bs->bs_offs = 0; + bs->bs_bits = 0; + } + } + return (outlen); +} + +static int +b64flush(bs, outp) +struct b64state *bs; +u_char *outp; +{ + int outlen = 0; + + if (bs->bs_offs == 8) { + *outp++ = base64[(bs->bs_bits >> 2) & 0x3F]; + *outp++ = base64[(bs->bs_bits << 4) & 0x3F]; + outlen = 2; + } else if (bs->bs_offs == 16) { + *outp++ = base64[(bs->bs_bits >> 10) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 4) & 0x3F]; + *outp++ = base64[(bs->bs_bits << 2) & 0x3F]; + outlen = 3; + } + bs->bs_offs = 0; + bs->bs_bits = 0; + return (outlen); +} + +static int +b64dec(bs, inp, inlen, outp) +struct b64state *bs; +u_char *inp; +int inlen; +u_char *outp; +{ + int outlen = 0; + char *cp; + + while (inlen > 0) { + if ((cp = strchr(base64, *inp++)) == NULL) + break; + bs->bs_bits = (bs->bs_bits << 6) | (cp - base64); + inlen--; + bs->bs_offs += 6; + if (bs->bs_offs >= 8) { + *outp++ = bs->bs_bits >> (bs->bs_offs - 8); + outlen++; + bs->bs_offs -= 8; + } + } + return (outlen); +} +#endif /* USE_SRP */ + +#if PPP_SERVER +/* + * Assume that current waiting server state is complete and figure + * next state to use based on available authentication data. 'status' + * indicates if there was an error in handling the last query. It is + * 0 for success and non-zero for failure. + */ +static void eap_figure_next_state(ppp_pcb *pcb, int status) { +#ifdef USE_SRP + unsigned char secbuf[MAXSECRETLEN], clear[8], *sp, *dp; + struct t_pw tpw; + struct t_confent *tce, mytce; + char *cp, *cp2; + struct t_server *ts; + int id, i, plen, toffs; + u_char vals[2]; + struct b64state bs; +#endif /* USE_SRP */ + + pcb->settings.eap_timeout_time = pcb->eap.es_savedtime; + switch (pcb->eap.es_server.ea_state) { + case eapBadAuth: + return; + + case eapIdentify: +#ifdef USE_SRP + /* Discard any previous session. */ + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0) { + pcb->eap.es_server.ea_state = eapBadAuth; + break; + } +#ifdef USE_SRP + /* If we've got a pseudonym, try to decode to real name. */ + if (pcb->eap.es_server.ea_peerlen > SRP_PSEUDO_LEN && + strncmp(pcb->eap.es_server.ea_peer, SRP_PSEUDO_ID, + SRP_PSEUDO_LEN) == 0 && + (pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 < + sizeof (secbuf)) { + BZERO(&bs, sizeof (bs)); + plen = b64dec(&bs, + pcb->eap.es_server.ea_peer + SRP_PSEUDO_LEN, + pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN, + secbuf); + toffs = 0; + for (i = 0; i < 5; i++) { + pncrypt_setkey(toffs); + toffs -= 86400; + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + if (!DesDecrypt(secbuf, clear)) { + ppp_dbglog("no DES here; cannot decode " + "pseudonym"); + return; + } + id = *(unsigned char *)clear; + if (id + 1 <= plen && id + 9 > plen) + break; + } + if (plen % 8 == 0 && i < 5) { + /* + * Note that this is always shorter than the + * original stored string, so there's no need + * to realloc. + */ + if ((i = plen = *(unsigned char *)clear) > 7) + i = 7; + pcb->eap.es_server.ea_peerlen = plen; + dp = (unsigned char *)pcb->eap.es_server.ea_peer; + MEMCPY(dp, clear + 1, i); + plen -= i; + dp += i; + sp = secbuf + 8; + while (plen > 0) { + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesDecrypt(sp, dp); + sp += 8; + dp += 8; + plen -= 8; + } + pcb->eap.es_server.ea_peer[ + pcb->eap.es_server.ea_peerlen] = '\0'; + ppp_dbglog("decoded pseudonym to \"%.*q\"", + pcb->eap.es_server.ea_peerlen, + pcb->eap.es_server.ea_peer); + } else { + ppp_dbglog("failed to decode real name"); + /* Stay in eapIdentfy state; requery */ + break; + } + } + /* Look up user in secrets database. */ + if (get_srp_secret(pcb->eap.es_unit, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_name, (char *)secbuf, 1) != 0) { + /* Set up default in case SRP entry is bad */ + pcb->eap.es_server.ea_state = eapMD5Chall; + /* Get t_confent based on index in srp-secrets */ + id = strtol((char *)secbuf, &cp, 10); + if (*cp++ != ':' || id < 0) + break; + if (id == 0) { + mytce.index = 0; + mytce.modulus.data = (u_char *)wkmodulus; + mytce.modulus.len = sizeof (wkmodulus); + mytce.generator.data = (u_char *)"\002"; + mytce.generator.len = 1; + tce = &mytce; + } else if ((tce = gettcid(id)) != NULL) { + /* + * Client will have to verify this modulus/ + * generator combination, and that will take + * a while. Lengthen the timeout here. + */ + if (pcb->settings.eap_timeout_time > 0 && + pcb->settings.eap_timeout_time < 30) + pcb->settings.eap_timeout_time = 30; + } else { + break; + } + if ((cp2 = strchr(cp, ':')) == NULL) + break; + *cp2++ = '\0'; + tpw.pebuf.name = pcb->eap.es_server.ea_peer; + tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf, + cp); + tpw.pebuf.password.data = tpw.pwbuf; + tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf, + cp2); + tpw.pebuf.salt.data = tpw.saltbuf; + if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL) + break; + pcb->eap.es_server.ea_session = (void *)ts; + pcb->eap.es_server.ea_state = eapSRP1; + vals[0] = pcb->eap.es_server.ea_id + 1; + vals[1] = EAPT_SRP; + t_serveraddexdata(ts, vals, 2); + /* Generate B; must call before t_servergetkey() */ + t_servergenexp(ts); + break; + } +#endif /* USE_SRP */ + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + + case eapSRP1: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status == 1) { + pcb->eap.es_server.ea_state = eapMD5Chall; + } else if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapSRP2; + } + break; + + case eapSRP2: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapSRP3; + } + break; + + case eapSRP3: + case eapSRP4: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapOpen; + } + break; + + case eapMD5Chall: + if (status != 0) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapOpen; + } + break; + + default: + pcb->eap.es_server.ea_state = eapBadAuth; + break; + } + if (pcb->eap.es_server.ea_state == eapBadAuth) + eap_send_failure(pcb); +} + +/* + * Format an EAP Request message and send it to the peer. Message + * type depends on current state. (Server operation) + */ +static void eap_send_request(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + u_char *lenloc; + int outlen; + int len; + const char *str; +#ifdef USE_SRP + struct t_server *ts; + u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp; + int i, j; + struct b64state b64; + SHA1_CTX ctxt; +#endif /* USE_SRP */ + + /* Handle both initial auth and restart */ + if (pcb->eap.es_server.ea_state < eapIdentify && + pcb->eap.es_server.ea_state != eapInitial) { + pcb->eap.es_server.ea_state = eapIdentify; +#if PPP_REMOTENAME + if (pcb->settings.explicit_remote && pcb->remote_name) { + /* + * If we already know the peer's + * unauthenticated name, then there's no + * reason to ask. Go to next state instead. + */ + int len = (int)strlen(pcb->remote_name); + if (len > MAXNAMELEN) { + len = MAXNAMELEN; + } + MEMCPY(pcb->eap.es_server.ea_peer, pcb->remote_name, len); + pcb->eap.es_server.ea_peer[len] = '\0'; + pcb->eap.es_server.ea_peerlen = len; + eap_figure_next_state(pcb, 0); + } +#endif /* PPP_REMOTENAME */ + } + + if (pcb->settings.eap_max_transmits > 0 && + pcb->eap.es_server.ea_requests >= pcb->settings.eap_max_transmits) { + if (pcb->eap.es_server.ea_responses > 0) + ppp_error("EAP: too many Requests sent"); + else + ppp_error("EAP: no response to Requests"); + eap_send_failure(pcb); + return; + } + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_REQUEST, outp); + PUTCHAR(pcb->eap.es_server.ea_id, outp); + lenloc = outp; + INCPTR(2, outp); + + switch (pcb->eap.es_server.ea_state) { + case eapIdentify: + PUTCHAR(EAPT_IDENTITY, outp); + str = "Name"; + len = strlen(str); + MEMCPY(outp, str, len); + INCPTR(len, outp); + break; + + case eapMD5Chall: + PUTCHAR(EAPT_MD5CHAP, outp); + /* + * pick a random challenge length between + * EAP_MIN_CHALLENGE_LENGTH and EAP_MAX_CHALLENGE_LENGTH + */ + pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + + magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); + PUTCHAR(pcb->eap.es_challen, outp); + magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); + MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); + INCPTR(pcb->eap.es_challen, outp); + MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); + INCPTR(pcb->eap.es_server.ea_namelen, outp); + break; + +#ifdef USE_SRP + case eapSRP1: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_CHALLENGE, outp); + + PUTCHAR(pcb->eap.es_server.ea_namelen, outp); + MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); + INCPTR(pcb->eap.es_server.ea_namelen, outp); + + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + PUTCHAR(ts->s.len, outp); + MEMCPY(outp, ts->s.data, ts->s.len); + INCPTR(ts->s.len, outp); + + if (ts->g.len == 1 && ts->g.data[0] == 2) { + PUTCHAR(0, outp); + } else { + PUTCHAR(ts->g.len, outp); + MEMCPY(outp, ts->g.data, ts->g.len); + INCPTR(ts->g.len, outp); + } + + if (ts->n.len != sizeof (wkmodulus) || + BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) { + MEMCPY(outp, ts->n.data, ts->n.len); + INCPTR(ts->n.len, outp); + } + break; + + case eapSRP2: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_SKEY, outp); + + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + MEMCPY(outp, ts->B.data, ts->B.len); + INCPTR(ts->B.len, outp); + break; + + case eapSRP3: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_SVALIDATOR, outp); + PUTLONG(SRPVAL_EBIT, outp); + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + MEMCPY(outp, t_serverresponse(ts), SHA_DIGESTSIZE); + INCPTR(SHA_DIGESTSIZE, outp); + + if (pncrypt_setkey(0)) { + /* Generate pseudonym */ + optr = outp; + cp = (unsigned char *)pcb->eap.es_server.ea_peer; + if ((j = i = pcb->eap.es_server.ea_peerlen) > 7) + j = 7; + clear[0] = i; + MEMCPY(clear + 1, cp, j); + i -= j; + cp += j; + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + if (!DesEncrypt(clear, cipher)) { + ppp_dbglog("no DES here; not generating pseudonym"); + break; + } + BZERO(&b64, sizeof (b64)); + outp++; /* space for pseudonym length */ + outp += b64enc(&b64, cipher, 8, outp); + while (i >= 8) { + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesEncrypt(cp, cipher); + outp += b64enc(&b64, cipher, 8, outp); + cp += 8; + i -= 8; + } + if (i > 0) { + MEMCPY(clear, cp, i); + cp += i; + magic_random_bytes(cp, 8-i); + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesEncrypt(clear, cipher); + outp += b64enc(&b64, cipher, 8, outp); + } + outp += b64flush(&b64, outp); + + /* Set length and pad out to next 20 octet boundary */ + i = outp - optr - 1; + *optr = i; + i %= SHA_DIGESTSIZE; + if (i != 0) { + magic_random_bytes(outp, SHA_DIGESTSIZE-i); + INCPTR(SHA_DIGESTSIZE-i, outp); + } + + /* Obscure the pseudonym with SHA1 hash */ + SHA1Init(&ctxt); + SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_peerlen); + while (optr < outp) { + SHA1Final(dig, &ctxt); + cp = dig; + while (cp < dig + SHA_DIGESTSIZE) + *optr++ ^= *cp++; + SHA1Init(&ctxt); + SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, optr - SHA_DIGESTSIZE, + SHA_DIGESTSIZE); + } + } + break; + + case eapSRP4: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_LWRECHALLENGE, outp); + pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + + magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); + magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); + MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); + INCPTR(pcb->eap.es_challen, outp); + break; +#endif /* USE_SRP */ + + default: + return; + } + + outlen = (outp - (unsigned char*)p->payload) - PPP_HDRLEN; + PUTSHORT(outlen, lenloc); + + pbuf_realloc(p, outlen + PPP_HDRLEN); + ppp_write(pcb, p); + + pcb->eap.es_server.ea_requests++; + + if (pcb->settings.eap_timeout_time > 0) + TIMEOUT(eap_server_timeout, pcb, pcb->settings.eap_timeout_time); +} + +/* + * eap_authpeer - Authenticate our peer (behave as server). + * + * Start server state and send first request. This is called only + * after eap_lowerup. + */ +void eap_authpeer(ppp_pcb *pcb, const char *localname) { + + /* Save the name we're given. */ + pcb->eap.es_server.ea_name = localname; + pcb->eap.es_server.ea_namelen = strlen(localname); + + pcb->eap.es_savedtime = pcb->settings.eap_timeout_time; + + /* Lower layer up yet? */ + if (pcb->eap.es_server.ea_state == eapInitial || + pcb->eap.es_server.ea_state == eapPending) { + pcb->eap.es_server.ea_state = eapPending; + return; + } + + pcb->eap.es_server.ea_state = eapPending; + + /* ID number not updated here intentionally; hashed into M1 */ + eap_send_request(pcb); +} + +/* + * eap_server_timeout - Retransmission timer for sending Requests + * expired. + */ +static void eap_server_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (!eap_server_active(pcb)) + return; + + /* EAP ID number must not change on timeout. */ + eap_send_request(pcb); +} + +/* + * When it's time to send rechallenge the peer, this timeout is + * called. Once the rechallenge is successful, the response handler + * will restart the timer. If it fails, then the link is dropped. + */ +static void eap_rechallenge(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->eap.es_server.ea_state != eapOpen && + pcb->eap.es_server.ea_state != eapSRP4) + return; + + pcb->eap.es_server.ea_requests = 0; + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); +} + +static void srp_lwrechallenge(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->eap.es_server.ea_state != eapOpen || + pcb->eap.es_server.ea_type != EAPT_SRP) + return; + + pcb->eap.es_server.ea_requests = 0; + pcb->eap.es_server.ea_state = eapSRP4; + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); +} +#endif /* PPP_SERVER */ + +/* + * eap_lowerup - The lower layer is now up. + * + * This is called before either eap_authpeer or eap_authwithpeer. See + * link_established() in auth.c. All that's necessary here is to + * return to closed state so that those two routines will do the right + * thing. + */ +static void eap_lowerup(ppp_pcb *pcb) { + pcb->eap.es_client.ea_state = eapClosed; +#if PPP_SERVER + pcb->eap.es_server.ea_state = eapClosed; +#endif /* PPP_SERVER */ +} + +/* + * eap_lowerdown - The lower layer is now down. + * + * Cancel all timeouts and return to initial state. + */ +static void eap_lowerdown(ppp_pcb *pcb) { + + if (eap_client_active(pcb) && pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } +#if PPP_SERVER + if (eap_server_active(pcb)) { + if (pcb->settings.eap_timeout_time > 0) { + UNTIMEOUT(eap_server_timeout, pcb); + } + } else { + if ((pcb->eap.es_server.ea_state == eapOpen || + pcb->eap.es_server.ea_state == eapSRP4) && + pcb->eap.es_rechallenge > 0) { + UNTIMEOUT(eap_rechallenge, (void *)pcb); + } + if (pcb->eap.es_server.ea_state == eapOpen && + pcb->eap.es_lwrechallenge > 0) { + UNTIMEOUT(srp_lwrechallenge, (void *)pcb); + } + } + + pcb->eap.es_client.ea_state = pcb->eap.es_server.ea_state = eapInitial; + pcb->eap.es_client.ea_requests = pcb->eap.es_server.ea_requests = 0; +#endif /* PPP_SERVER */ +} + +/* + * eap_protrej - Peer doesn't speak this protocol. + * + * This shouldn't happen. If it does, it represents authentication + * failure. + */ +static void eap_protrej(ppp_pcb *pcb) { + + if (eap_client_active(pcb)) { + ppp_error("EAP authentication failed due to Protocol-Reject"); + auth_withpeer_fail(pcb, PPP_EAP); + } +#if PPP_SERVER + if (eap_server_active(pcb)) { + ppp_error("EAP authentication of peer failed on Protocol-Reject"); + auth_peer_fail(pcb, PPP_EAP); + } +#endif /* PPP_SERVER */ + eap_lowerdown(pcb); +} + +/* + * Format and send a regular EAP Response message. + */ +static void eap_send_response(ppp_pcb *pcb, u_char id, u_char typenum, const u_char *str, int lenstr) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(typenum, outp); + if (lenstr > 0) { + MEMCPY(outp, str, lenstr); + } + + ppp_write(pcb, p); +} + +/* + * Format and send an MD5-Challenge EAP Response message. + */ +static void eap_chap_response(ppp_pcb *pcb, u_char id, u_char *hash, const char *name, int namelen) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE + + namelen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_MD5CHAP, outp); + PUTCHAR(MD5_SIGNATURE_SIZE, outp); + MEMCPY(outp, hash, MD5_SIGNATURE_SIZE); + INCPTR(MD5_SIGNATURE_SIZE, outp); + if (namelen > 0) { + MEMCPY(outp, name, namelen); + } + + ppp_write(pcb, p); +} + +#ifdef USE_SRP +/* + * Format and send a SRP EAP Response message. + */ +static void +eap_srp_response(esp, id, subtypenum, str, lenstr) +eap_state *esp; +u_char id; +u_char subtypenum; +u_char *str; +int lenstr; +{ + ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(subtypenum, outp); + if (lenstr > 0) { + MEMCPY(outp, str, lenstr); + } + + ppp_write(pcb, p); +} + +/* + * Format and send a SRP EAP Client Validator Response message. + */ +static void +eap_srpval_response(esp, id, flags, str) +eap_state *esp; +u_char id; +u32_t flags; +u_char *str; +{ + ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u32_t) + + SHA_DIGESTSIZE; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_CVALIDATOR, outp); + PUTLONG(flags, outp); + MEMCPY(outp, str, SHA_DIGESTSIZE); + + ppp_write(pcb, p); +} +#endif /* USE_SRP */ + +static void eap_send_nak(ppp_pcb *pcb, u_char id, u_char type) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_NAK, outp); + PUTCHAR(type, outp); + + ppp_write(pcb, p); +} + +#ifdef USE_SRP +static char * +name_of_pn_file() +{ + char *user, *path, *file; + struct passwd *pw; + size_t pl; + static bool pnlogged = 0; + + pw = getpwuid(getuid()); + if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) { + errno = EINVAL; + return (NULL); + } + file = _PATH_PSEUDONYM; + pl = strlen(user) + strlen(file) + 2; + path = malloc(pl); + if (path == NULL) + return (NULL); + (void) slprintf(path, pl, "%s/%s", user, file); + if (!pnlogged) { + ppp_dbglog("pseudonym file: %s", path); + pnlogged = 1; + } + return (path); +} + +static int +open_pn_file(modebits) +mode_t modebits; +{ + char *path; + int fd, err; + + if ((path = name_of_pn_file()) == NULL) + return (-1); + fd = open(path, modebits, S_IRUSR | S_IWUSR); + err = errno; + free(path); + errno = err; + return (fd); +} + +static void +remove_pn_file() +{ + char *path; + + if ((path = name_of_pn_file()) != NULL) { + (void) unlink(path); + (void) free(path); + } +} + +static void +write_pseudonym(esp, inp, len, id) +eap_state *esp; +u_char *inp; +int len, id; +{ + u_char val; + u_char *datp, *digp; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + int dsize, fd, olen = len; + + /* + * Do the decoding by working backwards. This eliminates the need + * to save the decoded output in a separate buffer. + */ + val = id; + while (len > 0) { + if ((dsize = len % SHA_DIGESTSIZE) == 0) + dsize = SHA_DIGESTSIZE; + len -= dsize; + datp = inp + len; + SHA1Init(&ctxt); + SHA1Update(&ctxt, &val, 1); + SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, SESSION_KEY_LEN); + if (len > 0) { + SHA1Update(&ctxt, datp, SHA_DIGESTSIZE); + } else { + SHA1Update(&ctxt, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + } + SHA1Final(dig, &ctxt); + for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++) + *datp++ ^= *digp; + } + + /* Now check that the result is sane */ + if (olen <= 0 || *inp + 1 > olen) { + ppp_dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp); + return; + } + + /* Save it away */ + fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC); + if (fd < 0) { + ppp_dbglog("EAP: error saving pseudonym: %m"); + return; + } + len = write(fd, inp + 1, *inp); + if (close(fd) != -1 && len == *inp) { + ppp_dbglog("EAP: saved pseudonym"); + pcb->eap.es_usedpseudo = 0; + } else { + ppp_dbglog("EAP: failed to save pseudonym"); + remove_pn_file(); + } +} +#endif /* USE_SRP */ + +/* + * eap_request - Receive EAP Request message (client mode). + */ +static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char typenum; + u_char vallen; + int secret_len; + char secret[MAXSECRETLEN]; + char rhostname[MAXNAMELEN]; + lwip_md5_context mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; +#ifdef USE_SRP + struct t_client *tc; + struct t_num sval, gval, Nval, *Ap, Bval; + u_char vals[2]; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + int fd; +#endif /* USE_SRP */ + + /* + * Note: we update es_client.ea_id *only if* a Response + * message is being generated. Otherwise, we leave it the + * same for duplicate detection purposes. + */ + + pcb->eap.es_client.ea_requests++; + if (pcb->settings.eap_allow_req != 0 && + pcb->eap.es_client.ea_requests > pcb->settings.eap_allow_req) { + ppp_info("EAP: received too many Request messages"); + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + auth_withpeer_fail(pcb, PPP_EAP); + return; + } + + if (len <= 0) { + ppp_error("EAP: empty Request message discarded"); + return; + } + + GETCHAR(typenum, inp); + len--; + + switch (typenum) { + case EAPT_IDENTITY: + if (len > 0) + ppp_info("EAP: Identity prompt \"%.*q\"", len, inp); +#ifdef USE_SRP + if (pcb->eap.es_usepseudo && + (pcb->eap.es_usedpseudo == 0 || + (pcb->eap.es_usedpseudo == 1 && + id == pcb->eap.es_client.ea_id))) { + pcb->eap.es_usedpseudo = 1; + /* Try to get a pseudonym */ + if ((fd = open_pn_file(O_RDONLY)) >= 0) { + strcpy(rhostname, SRP_PSEUDO_ID); + len = read(fd, rhostname + SRP_PSEUDO_LEN, + sizeof (rhostname) - SRP_PSEUDO_LEN); + /* XXX NAI unsupported */ + if (len > 0) { + eap_send_response(pcb, id, typenum, + rhostname, len + SRP_PSEUDO_LEN); + } + (void) close(fd); + if (len > 0) + break; + } + } + /* Stop using pseudonym now. */ + if (pcb->eap.es_usepseudo && pcb->eap.es_usedpseudo != 2) { + remove_pn_file(); + pcb->eap.es_usedpseudo = 2; + } +#endif /* USE_SRP */ + eap_send_response(pcb, id, typenum, (const u_char*)pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + break; + + case EAPT_NOTIFICATION: + if (len > 0) + ppp_info("EAP: Notification \"%.*q\"", len, inp); + eap_send_response(pcb, id, typenum, NULL, 0); + break; + + case EAPT_NAK: + /* + * Avoid the temptation to send Response Nak in reply + * to Request Nak here. It can only lead to trouble. + */ + ppp_warn("EAP: unexpected Nak in Request; ignored"); + /* Return because we're waiting for something real. */ + return; + + case EAPT_MD5CHAP: + if (len < 1) { + ppp_error("EAP: received MD5-Challenge with no data"); + /* Bogus request; wait for something real. */ + return; + } + GETCHAR(vallen, inp); + len--; + if (vallen < 8 || vallen > len) { + ppp_error("EAP: MD5-Challenge with bad length %d (8..%d)", + vallen, len); + /* Try something better. */ + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + + /* Not so likely to happen. */ + if (vallen >= len + sizeof (rhostname)) { + ppp_dbglog("EAP: trimming really long peer name down"); + MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); + rhostname[sizeof (rhostname) - 1] = '\0'; + } else { + MEMCPY(rhostname, inp + vallen, len - vallen); + rhostname[len - vallen] = '\0'; + } + +#if PPP_REMOTENAME + /* In case the remote doesn't give us his name. */ + if (pcb->settings.explicit_remote || + (pcb->settings.remote_name[0] != '\0' && vallen == len)) + strlcpy(rhostname, pcb->settings.remote_name, sizeof (rhostname)); +#endif /* PPP_REMOTENAME */ + + /* + * Get the secret for authenticating ourselves with + * the specified host. + */ + if (!get_secret(pcb, pcb->eap.es_client.ea_name, + rhostname, secret, &secret_len, 0)) { + ppp_dbglog("EAP: no MD5 secret for auth to %q", rhostname); + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + lwip_md5_init(&mdContext); + lwip_md5_starts(&mdContext); + typenum = id; + lwip_md5_update(&mdContext, &typenum, 1); + lwip_md5_update(&mdContext, (u_char *)secret, secret_len); + BZERO(secret, sizeof (secret)); + lwip_md5_update(&mdContext, inp, vallen); + lwip_md5_finish(&mdContext, hash); + lwip_md5_free(&mdContext); + eap_chap_response(pcb, id, hash, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + break; + +#ifdef USE_SRP + case EAPT_SRP: + if (len < 1) { + ppp_error("EAP: received empty SRP Request"); + /* Bogus request; wait for something real. */ + return; + } + + /* Get subtype */ + GETCHAR(vallen, inp); + len--; + switch (vallen) { + case EAPSRP_CHALLENGE: + tc = NULL; + if (pcb->eap.es_client.ea_session != NULL) { + tc = (struct t_client *)pcb->eap.es_client. + ea_session; + /* + * If this is a new challenge, then start + * over with a new client session context. + * Otherwise, just resend last response. + */ + if (id != pcb->eap.es_client.ea_id) { + t_clientclose(tc); + pcb->eap.es_client.ea_session = NULL; + tc = NULL; + } + } + /* No session key just yet */ + pcb->eap.es_client.ea_skey = NULL; + if (tc == NULL) { + int rhostnamelen; + + GETCHAR(vallen, inp); + len--; + if (vallen >= len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (name)"); + /* Ignore badly-formed messages */ + return; + } + MEMCPY(rhostname, inp, vallen); + rhostname[vallen] = '\0'; + INCPTR(vallen, inp); + len -= vallen; + + /* + * In case the remote doesn't give us his name, + * use configured name. + */ + if (explicit_remote || + (remote_name[0] != '\0' && vallen == 0)) { + strlcpy(rhostname, remote_name, + sizeof (rhostname)); + } + + rhostnamelen = (int)strlen(rhostname); + if (rhostnamelen > MAXNAMELEN) { + rhostnamelen = MAXNAMELEN; + } + MEMCPY(pcb->eap.es_client.ea_peer, rhostname, rhostnamelen); + pcb->eap.es_client.ea_peer[rhostnamelen] = '\0'; + pcb->eap.es_client.ea_peerlen = rhostnamelen; + + GETCHAR(vallen, inp); + len--; + if (vallen >= len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (s)"); + /* Ignore badly-formed messages */ + return; + } + sval.data = inp; + sval.len = vallen; + INCPTR(vallen, inp); + len -= vallen; + + GETCHAR(vallen, inp); + len--; + if (vallen > len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (g)"); + /* Ignore badly-formed messages */ + return; + } + /* If no generator present, then use value 2 */ + if (vallen == 0) { + gval.data = (u_char *)"\002"; + gval.len = 1; + } else { + gval.data = inp; + gval.len = vallen; + } + INCPTR(vallen, inp); + len -= vallen; + + /* + * If no modulus present, then use well-known + * value. + */ + if (len == 0) { + Nval.data = (u_char *)wkmodulus; + Nval.len = sizeof (wkmodulus); + } else { + Nval.data = inp; + Nval.len = len; + } + tc = t_clientopen(pcb->eap.es_client.ea_name, + &Nval, &gval, &sval); + if (tc == NULL) { + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + pcb->eap.es_client.ea_session = (void *)tc; + + /* Add Challenge ID & type to verifier */ + vals[0] = id; + vals[1] = EAPT_SRP; + t_clientaddexdata(tc, vals, 2); + } + Ap = t_clientgenexp(tc); + eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data, + Ap->len); + break; + + case EAPSRP_SKEY: + tc = (struct t_client *)pcb->eap.es_client.ea_session; + if (tc == NULL) { + ppp_warn("EAP: peer sent Subtype 2 without 1"); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + if (pcb->eap.es_client.ea_skey != NULL) { + /* + * ID number should not change here. Warn + * if it does (but otherwise ignore). + */ + if (id != pcb->eap.es_client.ea_id) { + ppp_warn("EAP: ID changed from %d to %d " + "in SRP Subtype 2 rexmit", + pcb->eap.es_client.ea_id, id); + } + } else { + if (get_srp_secret(pcb->eap.es_unit, + pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_peer, secret, 0) == 0) { + /* + * Can't work with this peer because + * the secret is missing. Just give + * up. + */ + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + Bval.data = inp; + Bval.len = len; + t_clientpasswd(tc, secret); + BZERO(secret, sizeof (secret)); + pcb->eap.es_client.ea_skey = + t_clientgetkey(tc, &Bval); + if (pcb->eap.es_client.ea_skey == NULL) { + /* Server is rogue; stop now */ + ppp_error("EAP: SRP server is rogue"); + goto client_failure; + } + } + eap_srpval_response(esp, id, SRPVAL_EBIT, + t_clientresponse(tc)); + break; + + case EAPSRP_SVALIDATOR: + tc = (struct t_client *)pcb->eap.es_client.ea_session; + if (tc == NULL || pcb->eap.es_client.ea_skey == NULL) { + ppp_warn("EAP: peer sent Subtype 3 without 1/2"); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + /* + * If we're already open, then this ought to be a + * duplicate. Otherwise, check that the server is + * who we think it is. + */ + if (pcb->eap.es_client.ea_state == eapOpen) { + if (id != pcb->eap.es_client.ea_id) { + ppp_warn("EAP: ID changed from %d to %d " + "in SRP Subtype 3 rexmit", + pcb->eap.es_client.ea_id, id); + } + } else { + len -= sizeof (u32_t) + SHA_DIGESTSIZE; + if (len < 0 || t_clientverify(tc, inp + + sizeof (u32_t)) != 0) { + ppp_error("EAP: SRP server verification " + "failed"); + goto client_failure; + } + GETLONG(pcb->eap.es_client.ea_keyflags, inp); + /* Save pseudonym if user wants it. */ + if (len > 0 && pcb->eap.es_usepseudo) { + INCPTR(SHA_DIGESTSIZE, inp); + write_pseudonym(esp, inp, len, id); + } + } + /* + * We've verified our peer. We're now mostly done, + * except for waiting on the regular EAP Success + * message. + */ + eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0); + break; + + case EAPSRP_LWRECHALLENGE: + if (len < 4) { + ppp_warn("EAP: malformed Lightweight rechallenge"); + return; + } + SHA1Init(&ctxt); + vals[0] = id; + SHA1Update(&ctxt, vals, 1); + SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, inp, len); + SHA1Update(&ctxt, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + SHA1Final(dig, &ctxt); + eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig, + SHA_DIGESTSIZE); + break; + + default: + ppp_error("EAP: unknown SRP Subtype %d", vallen); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + break; +#endif /* USE_SRP */ + + default: + ppp_info("EAP: unknown authentication type %d; Naking", typenum); + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + TIMEOUT(eap_client_timeout, pcb, + pcb->settings.eap_req_time); + } + return; + +#ifdef USE_SRP +client_failure: + pcb->eap.es_client.ea_state = eapBadAuth; + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, (void *)esp); + } + pcb->eap.es_client.ea_session = NULL; + t_clientclose(tc); + auth_withpeer_fail(pcb, PPP_EAP); +#endif /* USE_SRP */ +} + +#if PPP_SERVER +/* + * eap_response - Receive EAP Response message (server mode). + */ +static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char typenum; + u_char vallen; + int secret_len; + char secret[MAXSECRETLEN]; + char rhostname[MAXNAMELEN]; + lwip_md5_context mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; +#ifdef USE_SRP + struct t_server *ts; + struct t_num A; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; +#endif /* USE_SRP */ + + if (pcb->eap.es_server.ea_id != id) { + ppp_dbglog("EAP: discarding Response %d; expected ID %d", id, + pcb->eap.es_server.ea_id); + return; + } + + pcb->eap.es_server.ea_responses++; + + if (len <= 0) { + ppp_error("EAP: empty Response message discarded"); + return; + } + + GETCHAR(typenum, inp); + len--; + + switch (typenum) { + case EAPT_IDENTITY: + if (pcb->eap.es_server.ea_state != eapIdentify) { + ppp_dbglog("EAP discarding unwanted Identify \"%.q\"", len, + inp); + break; + } + ppp_info("EAP: unauthenticated peer name \"%.*q\"", len, inp); + if (len > MAXNAMELEN) { + len = MAXNAMELEN; + } + MEMCPY(pcb->eap.es_server.ea_peer, inp, len); + pcb->eap.es_server.ea_peer[len] = '\0'; + pcb->eap.es_server.ea_peerlen = len; + eap_figure_next_state(pcb, 0); + break; + + case EAPT_NOTIFICATION: + ppp_dbglog("EAP unexpected Notification; response discarded"); + break; + + case EAPT_NAK: + if (len < 1) { + ppp_info("EAP: Nak Response with no suggested protocol"); + eap_figure_next_state(pcb, 1); + break; + } + + GETCHAR(vallen, inp); + len--; + + if ( +#if PPP_REMOTENAME + !pcb->explicit_remote && +#endif /* PPP_REMOTENAME */ + pcb->eap.es_server.ea_state == eapIdentify){ + /* Peer cannot Nak Identify Request */ + eap_figure_next_state(pcb, 1); + break; + } + + switch (vallen) { + case EAPT_SRP: + /* Run through SRP validator selection again. */ + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + break; + + case EAPT_MD5CHAP: + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + + default: + ppp_dbglog("EAP: peer requesting unknown Type %d", vallen); + switch (pcb->eap.es_server.ea_state) { + case eapSRP1: + case eapSRP2: + case eapSRP3: + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + case eapMD5Chall: + case eapSRP4: + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + break; + default: + break; + } + break; + } + break; + + case EAPT_MD5CHAP: + if (pcb->eap.es_server.ea_state != eapMD5Chall) { + ppp_error("EAP: unexpected MD5-Response"); + eap_figure_next_state(pcb, 1); + break; + } + if (len < 1) { + ppp_error("EAP: received MD5-Response with no data"); + eap_figure_next_state(pcb, 1); + break; + } + GETCHAR(vallen, inp); + len--; + if (vallen != 16 || vallen > len) { + ppp_error("EAP: MD5-Response with bad length %d", vallen); + eap_figure_next_state(pcb, 1); + break; + } + + /* Not so likely to happen. */ + if (vallen >= len + sizeof (rhostname)) { + ppp_dbglog("EAP: trimming really long peer name down"); + MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); + rhostname[sizeof (rhostname) - 1] = '\0'; + } else { + MEMCPY(rhostname, inp + vallen, len - vallen); + rhostname[len - vallen] = '\0'; + } + +#if PPP_REMOTENAME + /* In case the remote doesn't give us his name. */ + if (explicit_remote || + (remote_name[0] != '\0' && vallen == len)) + strlcpy(rhostname, remote_name, sizeof (rhostname)); +#endif /* PPP_REMOTENAME */ + + /* + * Get the secret for authenticating the specified + * host. + */ + if (!get_secret(pcb, rhostname, + pcb->eap.es_server.ea_name, secret, &secret_len, 1)) { + ppp_dbglog("EAP: no MD5 secret for auth of %q", rhostname); + eap_send_failure(pcb); + break; + } + lwip_md5_init(&mdContext); + lwip_md5_starts(&mdContext); + lwip_md5_update(&mdContext, &pcb->eap.es_server.ea_id, 1); + lwip_md5_update(&mdContext, (u_char *)secret, secret_len); + BZERO(secret, sizeof (secret)); + lwip_md5_update(&mdContext, pcb->eap.es_challenge, pcb->eap.es_challen); + lwip_md5_finish(&mdContext, hash); + lwip_md5_free(&mdContext); + if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) { + eap_send_failure(pcb); + break; + } + pcb->eap.es_server.ea_type = EAPT_MD5CHAP; + eap_send_success(pcb); + eap_figure_next_state(pcb, 0); + if (pcb->eap.es_rechallenge != 0) + TIMEOUT(eap_rechallenge, pcb, pcb->eap.es_rechallenge); + break; + +#ifdef USE_SRP + case EAPT_SRP: + if (len < 1) { + ppp_error("EAP: empty SRP Response"); + eap_figure_next_state(pcb, 1); + break; + } + GETCHAR(typenum, inp); + len--; + switch (typenum) { + case EAPSRP_CKEY: + if (pcb->eap.es_server.ea_state != eapSRP1) { + ppp_error("EAP: unexpected SRP Subtype 1 Response"); + eap_figure_next_state(pcb, 1); + break; + } + A.data = inp; + A.len = len; + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + pcb->eap.es_server.ea_skey = t_servergetkey(ts, &A); + if (pcb->eap.es_server.ea_skey == NULL) { + /* Client's A value is bogus; terminate now */ + ppp_error("EAP: bogus A value from client"); + eap_send_failure(pcb); + } else { + eap_figure_next_state(pcb, 0); + } + break; + + case EAPSRP_CVALIDATOR: + if (pcb->eap.es_server.ea_state != eapSRP2) { + ppp_error("EAP: unexpected SRP Subtype 2 Response"); + eap_figure_next_state(pcb, 1); + break; + } + if (len < sizeof (u32_t) + SHA_DIGESTSIZE) { + ppp_error("EAP: M1 length %d < %d", len, + sizeof (u32_t) + SHA_DIGESTSIZE); + eap_figure_next_state(pcb, 1); + break; + } + GETLONG(pcb->eap.es_server.ea_keyflags, inp); + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + if (t_serververify(ts, inp)) { + ppp_info("EAP: unable to validate client identity"); + eap_send_failure(pcb); + break; + } + eap_figure_next_state(pcb, 0); + break; + + case EAPSRP_ACK: + if (pcb->eap.es_server.ea_state != eapSRP3) { + ppp_error("EAP: unexpected SRP Subtype 3 Response"); + eap_send_failure(esp); + break; + } + pcb->eap.es_server.ea_type = EAPT_SRP; + eap_send_success(pcb, esp); + eap_figure_next_state(pcb, 0); + if (pcb->eap.es_rechallenge != 0) + TIMEOUT(eap_rechallenge, pcb, + pcb->eap.es_rechallenge); + if (pcb->eap.es_lwrechallenge != 0) + TIMEOUT(srp_lwrechallenge, pcb, + pcb->eap.es_lwrechallenge); + break; + + case EAPSRP_LWRECHALLENGE: + if (pcb->eap.es_server.ea_state != eapSRP4) { + ppp_info("EAP: unexpected SRP Subtype 4 Response"); + return; + } + if (len != SHA_DIGESTSIZE) { + ppp_error("EAP: bad Lightweight rechallenge " + "response"); + return; + } + SHA1Init(&ctxt); + vallen = id; + SHA1Update(&ctxt, &vallen, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, pcb->eap.es_challenge, pcb->eap.es_challen); + SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_peerlen); + SHA1Final(dig, &ctxt); + if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) { + ppp_error("EAP: failed Lightweight rechallenge"); + eap_send_failure(pcb); + break; + } + pcb->eap.es_server.ea_state = eapOpen; + if (pcb->eap.es_lwrechallenge != 0) + TIMEOUT(srp_lwrechallenge, esp, + pcb->eap.es_lwrechallenge); + break; + } + break; +#endif /* USE_SRP */ + + default: + /* This can't happen. */ + ppp_error("EAP: unknown Response type %d; ignored", typenum); + return; + } + + if (pcb->settings.eap_timeout_time > 0) { + UNTIMEOUT(eap_server_timeout, pcb); + } + + if (pcb->eap.es_server.ea_state != eapBadAuth && + pcb->eap.es_server.ea_state != eapOpen) { + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); + } +} +#endif /* PPP_SERVER */ + +/* + * eap_success - Receive EAP Success message (client mode). + */ +static void eap_success(ppp_pcb *pcb, u_char *inp, int id, int len) { + LWIP_UNUSED_ARG(id); + + if (pcb->eap.es_client.ea_state != eapOpen && !eap_client_active(pcb)) { + ppp_dbglog("EAP unexpected success message in state %s (%d)", + eap_state_name(pcb->eap.es_client.ea_state), + pcb->eap.es_client.ea_state); + return; + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + + if (len > 0) { + /* This is odd. The spec doesn't allow for this. */ + PRINTMSG(inp, len); + } + + pcb->eap.es_client.ea_state = eapOpen; + auth_withpeer_success(pcb, PPP_EAP, 0); +} + +/* + * eap_failure - Receive EAP Failure message (client mode). + */ +static void eap_failure(ppp_pcb *pcb, u_char *inp, int id, int len) { + LWIP_UNUSED_ARG(id); + + if (!eap_client_active(pcb)) { + ppp_dbglog("EAP unexpected failure message in state %s (%d)", + eap_state_name(pcb->eap.es_client.ea_state), + pcb->eap.es_client.ea_state); + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + + if (len > 0) { + /* This is odd. The spec doesn't allow for this. */ + PRINTMSG(inp, len); + } + + pcb->eap.es_client.ea_state = eapBadAuth; + + ppp_error("EAP: peer reports authentication failure"); + auth_withpeer_fail(pcb, PPP_EAP); +} + +/* + * eap_input - Handle received EAP message. + */ +static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen) { + u_char code, id; + int len; + + /* + * Parse header (code, id and length). If packet too short, + * drop it. + */ + if (inlen < EAP_HEADERLEN) { + ppp_error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < EAP_HEADERLEN || len > inlen) { + ppp_error("EAP: packet has illegal length field %d (%d..%d)", len, + EAP_HEADERLEN, inlen); + return; + } + len -= EAP_HEADERLEN; + + /* Dispatch based on message code */ + switch (code) { + case EAP_REQUEST: + eap_request(pcb, inp, id, len); + break; + +#if PPP_SERVER + case EAP_RESPONSE: + eap_response(pcb, inp, id, len); + break; +#endif /* PPP_SERVER */ + + case EAP_SUCCESS: + eap_success(pcb, inp, id, len); + break; + + case EAP_FAILURE: + eap_failure(pcb, inp, id, len); + break; + + default: /* XXX Need code reject */ + /* Note: it's not legal to send EAP Nak here. */ + ppp_warn("EAP: unknown code %d received", code); + break; + } +} + +#if PRINTPKT_SUPPORT +/* + * eap_printpkt - print the contents of an EAP packet. + */ +static const char* const eap_codenames[] = { + "Request", "Response", "Success", "Failure" +}; + +static const char* const eap_typenames[] = { + "Identity", "Notification", "Nak", "MD5-Challenge", + "OTP", "Generic-Token", NULL, NULL, + "RSA", "DSS", "KEA", "KEA-Validate", + "TLS", "Defender", "Windows 2000", "Arcot", + "Cisco", "Nokia", "SRP" +}; + +static int eap_printpkt(const u_char *inp, int inlen, void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, rtype, vallen; + const u_char *pstart; + u32_t uval; + + if (inlen < EAP_HEADERLEN) + return (0); + pstart = inp; + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < EAP_HEADERLEN || len > inlen) + return (0); + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(eap_codenames)) + printer(arg, " %s", eap_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= EAP_HEADERLEN; + switch (code) { + case EAP_REQUEST: + if (len < 1) { + printer(arg, " "); + break; + } + GETCHAR(rtype, inp); + len--; + if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames)) + printer(arg, " %s", eap_typenames[rtype-1]); + else + printer(arg, " type=0x%x", rtype); + switch (rtype) { + case EAPT_IDENTITY: + case EAPT_NOTIFICATION: + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_MD5CHAP: + if (len <= 0) + break; + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_SRP: + if (len < 3) + goto truncated; + GETCHAR(vallen, inp); + len--; + printer(arg, "-%d", vallen); + switch (vallen) { + case EAPSRP_CHALLENGE: + GETCHAR(vallen, inp); + len--; + if (vallen >= len) + goto truncated; + if (vallen > 0) { + printer(arg, " "); + } else { + printer(arg, " "); + } + INCPTR(vallen, inp); + len -= vallen; + GETCHAR(vallen, inp); + len--; + if (vallen >= len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + if (vallen == 0) { + printer(arg, " "); + } else { + printer(arg, " ", vallen, inp); + } + INCPTR(vallen, inp); + len -= vallen; + if (len == 0) { + printer(arg, " "); + } else { + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPSRP_SKEY: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_SVALIDATOR: + if (len < (int)sizeof (u32_t)) + break; + GETLONG(uval, inp); + len -= sizeof (u32_t); + if (uval & SRPVAL_EBIT) { + printer(arg, " E"); + uval &= ~SRPVAL_EBIT; + } + if (uval != 0) { + printer(arg, " f<%X>", uval); + } + if ((vallen = len) > SHA_DIGESTSIZE) + vallen = SHA_DIGESTSIZE; + printer(arg, " ", len, inp, + len < SHA_DIGESTSIZE ? "?" : ""); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPSRP_LWRECHALLENGE: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + default: + break; + } + break; + default: + break; + } + break; + + case EAP_RESPONSE: + if (len < 1) + break; + GETCHAR(rtype, inp); + len--; + if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames)) + printer(arg, " %s", eap_typenames[rtype-1]); + else + printer(arg, " type=0x%x", rtype); + switch (rtype) { + case EAPT_IDENTITY: + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPT_NAK: + if (len <= 0) { + printer(arg, " "); + break; + } + GETCHAR(rtype, inp); + len--; + printer(arg, " = 1 && rtype < (int)LWIP_ARRAYSIZE(eap_typenames)) + printer(arg, " (%s)", eap_typenames[rtype-1]); + printer(arg, ">"); + break; + + case EAPT_MD5CHAP: + if (len <= 0) { + printer(arg, " "); + break; + } + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_SRP: + if (len < 1) + goto truncated; + GETCHAR(vallen, inp); + len--; + printer(arg, "-%d", vallen); + switch (vallen) { + case EAPSRP_CKEY: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_CVALIDATOR: + if (len < (int)sizeof (u32_t)) + break; + GETLONG(uval, inp); + len -= sizeof (u32_t); + if (uval & SRPVAL_EBIT) { + printer(arg, " E"); + uval &= ~SRPVAL_EBIT; + } + if (uval != 0) { + printer(arg, " f<%X>", uval); + } + printer(arg, " ", len, inp, + len == SHA_DIGESTSIZE ? "" : "?"); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_ACK: + break; + + case EAPSRP_LWRECHALLENGE: + printer(arg, " ", len, inp, + len == SHA_DIGESTSIZE ? "" : "?"); + if ((vallen = len) > SHA_DIGESTSIZE) + vallen = SHA_DIGESTSIZE; + INCPTR(vallen, inp); + len -= vallen; + break; + default: + break; + } + break; + default: + break; + } + break; + + case EAP_SUCCESS: /* No payload expected for these! */ + case EAP_FAILURE: + default: + break; + + truncated: + printer(arg, " "); + break; + } + + if (len > 8) + printer(arg, "%8B...", inp); + else if (len > 0) + printer(arg, "%.*B", len, inp); + INCPTR(len, inp); + + return (inp - pstart); +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/ecp.c b/components/net/lwip-2.0.3/src/netif/ppp/ecp.c new file mode 100644 index 0000000000..4d84f60931 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/ecp.c @@ -0,0 +1,191 @@ +/* + * ecp.c - PPP Encryption Control Protocol. + * + * Copyright (c) 2002 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Derived from ccp.c, which is: + * + * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ecp.h" + +#if PPP_OPTIONS +static option_t ecp_option_list[] = { + { "noecp", o_bool, &ecp_protent.enabled_flag, + "Disable ECP negotiation" }, + { "-ecp", o_bool, &ecp_protent.enabled_flag, + "Disable ECP negotiation", OPT_ALIAS }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ecp_init (int unit); +/* +static void ecp_open (int unit); +static void ecp_close (int unit, char *); +static void ecp_lowerup (int unit); +static void ecp_lowerdown (int); +static void ecp_input (int unit, u_char *pkt, int len); +static void ecp_protrej (int unit); +*/ +#if PRINTPKT_SUPPORT +static int ecp_printpkt (const u_char *pkt, int len, + void (*printer) (void *, char *, ...), + void *arg); +#endif /* PRINTPKT_SUPPORT */ +/* +static void ecp_datainput (int unit, u_char *pkt, int len); +*/ + +const struct protent ecp_protent = { + PPP_ECP, + ecp_init, + NULL, /* ecp_input, */ + NULL, /* ecp_protrej, */ + NULL, /* ecp_lowerup, */ + NULL, /* ecp_lowerdown, */ + NULL, /* ecp_open, */ + NULL, /* ecp_close, */ +#if PRINTPKT_SUPPORT + ecp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, /* ecp_datainput, */ +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "ECP", + "Encrypted", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ecp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +fsm ecp_fsm[NUM_PPP]; +ecp_options ecp_wantoptions[NUM_PPP]; /* what to request the peer to use */ +ecp_options ecp_gotoptions[NUM_PPP]; /* what the peer agreed to do */ +ecp_options ecp_allowoptions[NUM_PPP]; /* what we'll agree to do */ +ecp_options ecp_hisoptions[NUM_PPP]; /* what we agreed to do */ + +static const fsm_callbacks ecp_callbacks = { + NULL, /* ecp_resetci, */ + NULL, /* ecp_cilen, */ + NULL, /* ecp_addci, */ + NULL, /* ecp_ackci, */ + NULL, /* ecp_nakci, */ + NULL, /* ecp_rejci, */ + NULL, /* ecp_reqci, */ + NULL, /* ecp_up, */ + NULL, /* ecp_down, */ + NULL, + NULL, + NULL, + NULL, + NULL, /* ecp_extcode, */ + "ECP" +}; + +/* + * ecp_init - initialize ECP. + */ +static void +ecp_init(unit) + int unit; +{ + fsm *f = &ecp_fsm[unit]; + + f->unit = unit; + f->protocol = PPP_ECP; + f->callbacks = &ecp_callbacks; + fsm_init(f); + +#if 0 /* Not necessary, everything is cleared in ppp_new() */ + memset(&ecp_wantoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_gotoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_allowoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_hisoptions[unit], 0, sizeof(ecp_options)); +#endif /* 0 */ + +} + + +#if PRINTPKT_SUPPORT +static int +ecp_printpkt(p, plen, printer, arg) + const u_char *p; + int plen; + void (*printer) (void *, char *, ...); + void *arg; +{ + return 0; +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/eui64.c b/components/net/lwip-2.0.3/src/netif/ppp/eui64.c new file mode 100644 index 0000000000..01493bc1f8 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/eui64.c @@ -0,0 +1,56 @@ +/* + * eui64.c - EUI64 routines for IPv6CP. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: eui64.c,v 1.6 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/eui64.h" + +/* + * eui64_ntoa - Make an ascii representation of an interface identifier + */ +char *eui64_ntoa(eui64_t e) { + static char buf[20]; + + sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x", + e.e8[0], e.e8[1], e.e8[2], e.e8[3], + e.e8[4], e.e8[5], e.e8[6], e.e8[7]); + return buf; +} + +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/fsm.c b/components/net/lwip-2.0.3/src/netif/ppp/fsm.c new file mode 100644 index 0000000000..81eba11602 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/fsm.c @@ -0,0 +1,799 @@ +/* + * fsm.c - {Link, IP} Control Protocol Finite State Machine. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * @todo: + * Randomize fsm id on link/init. + * Deal with variable outgoing MTU. + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" + +static void fsm_timeout (void *); +static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len); +static void fsm_rconfack(fsm *f, int id, u_char *inp, int len); +static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len); +static void fsm_rtermreq(fsm *f, int id, u_char *p, int len); +static void fsm_rtermack(fsm *f); +static void fsm_rcoderej(fsm *f, u_char *inp, int len); +static void fsm_sconfreq(fsm *f, int retransmit); + +#define PROTO_NAME(f) ((f)->callbacks->proto_name) + +/* + * fsm_init - Initialize fsm. + * + * Initialize fsm state. + */ +void fsm_init(fsm *f) { + ppp_pcb *pcb = f->pcb; + f->state = PPP_FSM_INITIAL; + f->flags = 0; + f->id = 0; /* XXX Start with random id? */ + f->maxnakloops = pcb->settings.fsm_max_nak_loops; + f->term_reason_len = 0; +} + + +/* + * fsm_lowerup - The lower layer is up. + */ +void fsm_lowerup(fsm *f) { + switch( f->state ){ + case PPP_FSM_INITIAL: + f->state = PPP_FSM_CLOSED; + break; + + case PPP_FSM_STARTING: + if( f->flags & OPT_SILENT ) + f->state = PPP_FSM_STOPPED; + else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + } + break; + + default: + FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_lowerdown - The lower layer is down. + * + * Cancel all timeouts and inform upper layers. + */ +void fsm_lowerdown(fsm *f) { + switch( f->state ){ + case PPP_FSM_CLOSED: + f->state = PPP_FSM_INITIAL; + break; + + case PPP_FSM_STOPPED: + f->state = PPP_FSM_STARTING; + if( f->callbacks->starting ) + (*f->callbacks->starting)(f); + break; + + case PPP_FSM_CLOSING: + f->state = PPP_FSM_INITIAL; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case PPP_FSM_STOPPING: + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + f->state = PPP_FSM_STARTING; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case PPP_FSM_OPENED: + if( f->callbacks->down ) + (*f->callbacks->down)(f); + f->state = PPP_FSM_STARTING; + break; + + default: + FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_open - Link is allowed to come up. + */ +void fsm_open(fsm *f) { + switch( f->state ){ + case PPP_FSM_INITIAL: + f->state = PPP_FSM_STARTING; + if( f->callbacks->starting ) + (*f->callbacks->starting)(f); + break; + + case PPP_FSM_CLOSED: + if( f->flags & OPT_SILENT ) + f->state = PPP_FSM_STOPPED; + else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + } + break; + + case PPP_FSM_CLOSING: + f->state = PPP_FSM_STOPPING; + /* fall through */ + /* no break */ + case PPP_FSM_STOPPED: + case PPP_FSM_OPENED: + if( f->flags & OPT_RESTART ){ + fsm_lowerdown(f); + fsm_lowerup(f); + } + break; + default: + break; + } +} + +/* + * terminate_layer - Start process of shutting down the FSM + * + * Cancel any timeout running, notify upper layers we're done, and + * send a terminate-request message as configured. + */ +static void terminate_layer(fsm *f, int nextstate) { + ppp_pcb *pcb = f->pcb; + + if( f->state != PPP_FSM_OPENED ) + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + else if( f->callbacks->down ) + (*f->callbacks->down)(f); /* Inform upper layers we're down */ + + /* Init restart counter and send Terminate-Request */ + f->retransmits = pcb->settings.fsm_max_term_transmits; + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (const u_char *) f->term_reason, f->term_reason_len); + + if (f->retransmits == 0) { + /* + * User asked for no terminate requests at all; just close it. + * We've already fired off one Terminate-Request just to be nice + * to the peer, but we're not going to wait for a reply. + */ + f->state = nextstate == PPP_FSM_CLOSING ? PPP_FSM_CLOSED : PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + return; + } + + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + --f->retransmits; + + f->state = nextstate; +} + +/* + * fsm_close - Start closing connection. + * + * Cancel timeouts and either initiate close or possibly go directly to + * the PPP_FSM_CLOSED state. + */ +void fsm_close(fsm *f, const char *reason) { + f->term_reason = reason; + f->term_reason_len = (reason == NULL? 0: LWIP_MIN(strlen(reason), 0xFF) ); + switch( f->state ){ + case PPP_FSM_STARTING: + f->state = PPP_FSM_INITIAL; + break; + case PPP_FSM_STOPPED: + f->state = PPP_FSM_CLOSED; + break; + case PPP_FSM_STOPPING: + f->state = PPP_FSM_CLOSING; + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + case PPP_FSM_OPENED: + terminate_layer(f, PPP_FSM_CLOSING); + break; + default: + break; + } +} + + +/* + * fsm_timeout - Timeout expired. + */ +static void fsm_timeout(void *arg) { + fsm *f = (fsm *) arg; + ppp_pcb *pcb = f->pcb; + + switch (f->state) { + case PPP_FSM_CLOSING: + case PPP_FSM_STOPPING: + if( f->retransmits <= 0 ){ + /* + * We've waited for an ack long enough. Peer probably heard us. + */ + f->state = (f->state == PPP_FSM_CLOSING)? PPP_FSM_CLOSED: PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + } else { + /* Send Terminate-Request */ + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (const u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + --f->retransmits; + } + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + if (f->retransmits <= 0) { + ppp_warn("%s: timeout sending Config-Requests", PROTO_NAME(f)); + f->state = PPP_FSM_STOPPED; + if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) + (*f->callbacks->finished)(f); + + } else { + /* Retransmit the configure-request */ + if (f->callbacks->retransmit) + (*f->callbacks->retransmit)(f); + fsm_sconfreq(f, 1); /* Re-send Configure-Request */ + if( f->state == PPP_FSM_ACKRCVD ) + f->state = PPP_FSM_REQSENT; + } + break; + + default: + FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_input - Input packet. + */ +void fsm_input(fsm *f, u_char *inpacket, int l) { + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (l < HEADERLEN) { + FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol)); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < HEADERLEN) { + FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol)); + return; + } + if (len > l) { + FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol)); + return; + } + len -= HEADERLEN; /* subtract header length */ + + if( f->state == PPP_FSM_INITIAL || f->state == PPP_FSM_STARTING ){ + FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.", + f->protocol, f->state)); + return; + } + + /* + * Action depends on code. + */ + switch (code) { + case CONFREQ: + fsm_rconfreq(f, id, inp, len); + break; + + case CONFACK: + fsm_rconfack(f, id, inp, len); + break; + + case CONFNAK: + case CONFREJ: + fsm_rconfnakrej(f, code, id, inp, len); + break; + + case TERMREQ: + fsm_rtermreq(f, id, inp, len); + break; + + case TERMACK: + fsm_rtermack(f); + break; + + case CODEREJ: + fsm_rcoderej(f, inp, len); + break; + + default: + if( !f->callbacks->extcode + || !(*f->callbacks->extcode)(f, code, id, inp, len) ) + fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); + break; + } +} + + +/* + * fsm_rconfreq - Receive Configure-Request. + */ +static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) { + int code, reject_if_disagree; + + switch( f->state ){ + case PPP_FSM_CLOSED: + /* Go away, we're closed */ + fsm_sdata(f, TERMACK, id, NULL, 0); + return; + case PPP_FSM_CLOSING: + case PPP_FSM_STOPPING: + return; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if( f->callbacks->down ) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_STOPPED: + /* Negotiation started by our peer */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } + + /* + * Pass the requested configuration options + * to protocol-specific code for checking. + */ + if (f->callbacks->reqci){ /* Check CI */ + reject_if_disagree = (f->nakloops >= f->maxnakloops); + code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); + } else if (len) + code = CONFREJ; /* Reject all CI */ + else + code = CONFACK; + + /* send the Ack, Nak or Rej to the peer */ + fsm_sdata(f, code, id, inp, len); + + if (code == CONFACK) { + if (f->state == PPP_FSM_ACKRCVD) { + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = PPP_FSM_OPENED; + if (f->callbacks->up) + (*f->callbacks->up)(f); /* Inform upper layers */ + } else + f->state = PPP_FSM_ACKSENT; + f->nakloops = 0; + + } else { + /* we sent CONFACK or CONFREJ */ + if (f->state != PPP_FSM_ACKRCVD) + f->state = PPP_FSM_REQSENT; + if( code == CONFNAK ) + ++f->nakloops; + } +} + + +/* + * fsm_rconfack - Receive Configure-Ack. + */ +static void fsm_rconfack(fsm *f, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + + if (id != f->reqid || f->seen_ack) /* Expected id? */ + return; /* Nope, toss... */ + if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): + (len == 0)) ){ + /* Ack is bad - ignore it */ + ppp_error("Received bad configure-ack: %P", inp, len); + return; + } + f->seen_ack = 1; + f->rnakloops = 0; + + switch (f->state) { + case PPP_FSM_CLOSED: + case PPP_FSM_STOPPED: + fsm_sdata(f, TERMACK, id, NULL, 0); + break; + + case PPP_FSM_REQSENT: + f->state = PPP_FSM_ACKRCVD; + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + break; + + case PPP_FSM_ACKRCVD: + /* Huh? an extra valid Ack? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = PPP_FSM_OPENED; + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + if (f->callbacks->up) + (*f->callbacks->up)(f); /* Inform upper layers */ + break; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + */ +static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) { + int ret; + int treat_as_reject; + + if (id != f->reqid || f->seen_ack) /* Expected id? */ + return; /* Nope, toss... */ + + if (code == CONFNAK) { + ++f->rnakloops; + treat_as_reject = (f->rnakloops >= f->maxnakloops); + if (f->callbacks->nakci == NULL + || !(ret = f->callbacks->nakci(f, inp, len, treat_as_reject))) { + ppp_error("Received bad configure-nak: %P", inp, len); + return; + } + } else { + f->rnakloops = 0; + if (f->callbacks->rejci == NULL + || !(ret = f->callbacks->rejci(f, inp, len))) { + ppp_error("Received bad configure-rej: %P", inp, len); + return; + } + } + + f->seen_ack = 1; + + switch (f->state) { + case PPP_FSM_CLOSED: + case PPP_FSM_STOPPED: + fsm_sdata(f, TERMACK, id, NULL, 0); + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKSENT: + /* They didn't agree to what we wanted - try another request */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + if (ret < 0) + f->state = PPP_FSM_STOPPED; /* kludge for stopping CCP */ + else + fsm_sconfreq(f, 0); /* Send Configure-Request */ + break; + + case PPP_FSM_ACKRCVD: + /* Got a Nak/reject when we had already had an Ack?? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rtermreq - Receive Terminate-Req. + */ +static void fsm_rtermreq(fsm *f, int id, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + + switch (f->state) { + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + f->state = PPP_FSM_REQSENT; /* Start over but keep trying */ + break; + + case PPP_FSM_OPENED: + if (len > 0) { + ppp_info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p); + } else + ppp_info("%s terminated by peer", PROTO_NAME(f)); + f->retransmits = 0; + f->state = PPP_FSM_STOPPING; + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + break; + default: + break; + } + + fsm_sdata(f, TERMACK, id, NULL, 0); +} + + +/* + * fsm_rtermack - Receive Terminate-Ack. + */ +static void fsm_rtermack(fsm *f) { + switch (f->state) { + case PPP_FSM_CLOSING: + UNTIMEOUT(fsm_timeout, f); + f->state = PPP_FSM_CLOSED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + case PPP_FSM_STOPPING: + UNTIMEOUT(fsm_timeout, f); + f->state = PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_ACKRCVD: + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_OPENED: + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rcoderej - Receive an Code-Reject. + */ +static void fsm_rcoderej(fsm *f, u_char *inp, int len) { + u_char code, id; + + if (len < HEADERLEN) { + FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + ppp_warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id); + + if( f->state == PPP_FSM_ACKRCVD ) + f->state = PPP_FSM_REQSENT; +} + + +/* + * fsm_protreject - Peer doesn't speak this protocol. + * + * Treat this as a catastrophic error (RXJ-). + */ +void fsm_protreject(fsm *f) { + switch( f->state ){ + case PPP_FSM_CLOSING: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + /* no break */ + case PPP_FSM_CLOSED: + f->state = PPP_FSM_CLOSED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_STOPPING: + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + /* no break */ + case PPP_FSM_STOPPED: + f->state = PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_OPENED: + terminate_layer(f, PPP_FSM_STOPPING); + break; + + default: + FSMDEBUG(("%s: Protocol-reject event in state %d!", + PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_sconfreq - Send a Configure-Request. + */ +static void fsm_sconfreq(fsm *f, int retransmit) { + ppp_pcb *pcb = f->pcb; + struct pbuf *p; + u_char *outp; + int cilen; + + if( f->state != PPP_FSM_REQSENT && f->state != PPP_FSM_ACKRCVD && f->state != PPP_FSM_ACKSENT ){ + /* Not currently negotiating - reset options */ + if( f->callbacks->resetci ) + (*f->callbacks->resetci)(f); + f->nakloops = 0; + f->rnakloops = 0; + } + + if( !retransmit ){ + /* New request - reset retransmission counter, use new ID */ + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + f->reqid = ++f->id; + } + + f->seen_ack = 0; + + /* + * Make up the request packet + */ + if( f->callbacks->cilen && f->callbacks->addci ){ + cilen = (*f->callbacks->cilen)(f); + if( cilen > pcb->peer_mru - HEADERLEN ) + cilen = pcb->peer_mru - HEADERLEN; + } else + cilen = 0; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(cilen + HEADERLEN + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + /* send the request to our peer */ + outp = (u_char*)p->payload; + MAKEHEADER(outp, f->protocol); + PUTCHAR(CONFREQ, outp); + PUTCHAR(f->reqid, outp); + PUTSHORT(cilen + HEADERLEN, outp); + if (cilen != 0) { + (*f->callbacks->addci)(f, outp, &cilen); + LWIP_ASSERT("cilen == p->len - HEADERLEN - PPP_HDRLEN", cilen == p->len - HEADERLEN - PPP_HDRLEN); + } + + ppp_write(pcb, p); + + /* start the retransmit timer */ + --f->retransmits; + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); +} + + +/* + * fsm_sdata - Send some data. + * + * Used for all packets sent to our peer by this module. + */ +void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen) { + ppp_pcb *pcb = f->pcb; + struct pbuf *p; + u_char *outp; + int outlen; + + /* Adjust length to be smaller than MTU */ + if (datalen > pcb->peer_mru - HEADERLEN) + datalen = pcb->peer_mru - HEADERLEN; + outlen = datalen + HEADERLEN; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(outlen + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + if (datalen) /* && data != outp + PPP_HDRLEN + HEADERLEN) -- was only for fsm_sconfreq() */ + MEMCPY(outp + PPP_HDRLEN + HEADERLEN, data, datalen); + MAKEHEADER(outp, f->protocol); + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + ppp_write(pcb, p); +} + +#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/ipcp.c b/components/net/lwip-2.0.3/src/netif/ppp/ipcp.c new file mode 100644 index 0000000000..b7c766eb0b --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/ipcp.c @@ -0,0 +1,2418 @@ +/* + * ipcp.c - PPP IP Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * @todo: + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" + +#if 0 /* UNUSED */ +/* global vars */ +u32_t netmask = 0; /* IP netmask to set on interface */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +bool disable_defaultip = 0; /* Don't use hostname for default IP adrs */ +#endif /* UNUSED */ + +#if 0 /* moved to ppp_settings */ +bool noremoteip = 0; /* Let him have no IP address */ +#endif /* moved to ppp_setting */ + +#if 0 /* UNUSED */ +/* Hook for a plugin to know when IP protocol has come up */ +void (*ip_up_hook) (void) = NULL; + +/* Hook for a plugin to know when IP protocol has come down */ +void (*ip_down_hook) (void) = NULL; + +/* Hook for a plugin to choose the remote IP address */ +void (*ip_choose_hook) (u32_t *) = NULL; +#endif /* UNUSED */ + +#if PPP_NOTIFY +/* Notifiers for when IPCP goes up and down */ +struct notifier *ip_up_notifier = NULL; +struct notifier *ip_down_notifier = NULL; +#endif /* PPP_NOTIFY */ + +/* local vars */ +#if 0 /* moved to ppp_pcb */ +static int default_route_set[NUM_PPP]; /* Have set up a default route */ +static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ +static int ipcp_is_up; /* have called np_up() */ +static int ipcp_is_open; /* haven't called np_finished() */ +static bool ask_for_local; /* request our address from peer */ +#endif /* moved to ppp_pcb */ +#if 0 /* UNUSED */ +static char vj_value[8]; /* string form of vj option value */ +static char netmask_str[20]; /* string form of netmask value */ +#endif /* UNUSED */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipcp_resetci(fsm *f); /* Reset our CI */ +static int ipcp_cilen(fsm *f); /* Return length of our CI */ +static void ipcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ +static int ipcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject);/* Peer nak'd our CI */ +static int ipcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ +static void ipcp_up(fsm *f); /* We're UP */ +static void ipcp_down(fsm *f); /* We're DOWN */ +static void ipcp_finished(fsm *f); /* Don't need lower layer */ + +static const fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ + ipcp_resetci, /* Reset our Configuration Information */ + ipcp_cilen, /* Length of our Configuration Information */ + ipcp_addci, /* Add our Configuration Information */ + ipcp_ackci, /* ACK our Configuration Information */ + ipcp_nakci, /* NAK our Configuration Information */ + ipcp_rejci, /* Reject our Configuration Information */ + ipcp_reqci, /* Request peer's Configuration Information */ + ipcp_up, /* Called when fsm reaches OPENED state */ + ipcp_down, /* Called when fsm leaves OPENED state */ + NULL, /* Called when we want the lower layer up */ + ipcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPCP" /* String name of protocol */ +}; + +/* + * Command-line options. + */ +#if PPP_OPTIONS +static int setvjslots (char **); +static int setdnsaddr (char **); +static int setwinsaddr (char **); +static int setnetmask (char **); +int setipaddr (char *, char **, int); + +static void printipaddr (option_t *, void (*)(void *, char *,...),void *); + +static option_t ipcp_option_list[] = { + { "noip", o_bool, &ipcp_protent.enabled_flag, + "Disable IP and IPCP" }, + { "-ip", o_bool, &ipcp_protent.enabled_flag, + "Disable IP and IPCP", OPT_ALIAS }, + + { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, + "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj }, + { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, + "Disable VJ compression", OPT_ALIAS | OPT_A2CLR, + &ipcp_allowoptions[0].neg_vj }, + + { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, + "Disable VJ connection-ID compression", OPT_A2CLR, + &ipcp_allowoptions[0].cflag }, + { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, + "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR, + &ipcp_allowoptions[0].cflag }, + + { "vj-max-slots", o_special, (void *)setvjslots, + "Set maximum VJ header slots", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value }, + + { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, + "Accept peer's address for us", 1 }, + { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, + "Accept peer's address for it", 1 }, + + { "ipparam", o_string, &ipparam, + "Set ip script parameter", OPT_PRIO }, + + { "noipdefault", o_bool, &disable_defaultip, + "Don't use name for default IP adrs", 1 }, + + { "ms-dns", 1, (void *)setdnsaddr, + "DNS address for the peer's use" }, + { "ms-wins", 1, (void *)setwinsaddr, + "Nameserver for SMB over TCP/IP for peer" }, + + { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, + "Set timeout for IPCP", OPT_PRIO }, + { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, + "Set max #xmits for term-reqs", OPT_PRIO }, + { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, + "Set max #xmits for conf-reqs", OPT_PRIO }, + { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, + "Set max #conf-naks for IPCP", OPT_PRIO }, + + { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, + "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, + { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, + "disable defaultroute option", OPT_A2CLR, + &ipcp_wantoptions[0].default_route }, + { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, + "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, + &ipcp_wantoptions[0].default_route }, + + { "replacedefaultroute", o_bool, + &ipcp_wantoptions[0].replace_default_route, + "Replace default route", 1 + }, + { "noreplacedefaultroute", o_bool, + &ipcp_allowoptions[0].replace_default_route, + "Never replace default route", OPT_A2COPY, + &ipcp_wantoptions[0].replace_default_route }, + { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, + "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, + { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, + "disable proxyarp option", OPT_A2CLR, + &ipcp_wantoptions[0].proxy_arp }, + { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, + "disable proxyarp option", OPT_ALIAS | OPT_A2CLR, + &ipcp_wantoptions[0].proxy_arp }, + + { "usepeerdns", o_bool, &usepeerdns, + "Ask peer for DNS address(es)", 1 }, + + { "netmask", o_special, (void *)setnetmask, + "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str }, + + { "ipcp-no-addresses", o_bool, &ipcp_wantoptions[0].old_addrs, + "Disable old-style IP-Addresses usage", OPT_A2CLR, + &ipcp_allowoptions[0].old_addrs }, + { "ipcp-no-address", o_bool, &ipcp_wantoptions[0].neg_addr, + "Disable IP-Address usage", OPT_A2CLR, + &ipcp_allowoptions[0].neg_addr }, + + { "noremoteip", o_bool, &noremoteip, + "Allow peer to have no IP address", 1 }, + + { "nosendip", o_bool, &ipcp_wantoptions[0].neg_addr, + "Don't send our IP address to peer", OPT_A2CLR, + &ipcp_wantoptions[0].old_addrs}, + + { "IP addresses", o_wild, (void *) &setipaddr, + "set local and remote IP addresses", + OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ipcp_init(ppp_pcb *pcb); +static void ipcp_open(ppp_pcb *pcb); +static void ipcp_close(ppp_pcb *pcb, const char *reason); +static void ipcp_lowerup(ppp_pcb *pcb); +static void ipcp_lowerdown(ppp_pcb *pcb); +static void ipcp_input(ppp_pcb *pcb, u_char *p, int len); +static void ipcp_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int ipcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS +static void ip_check_options (void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT +static int ip_demand_conf (int); +static int ip_active_pkt (u_char *, int); +#endif /* DEMAND_SUPPORT */ +#if 0 /* UNUSED */ +static void create_resolv (u32_t, u32_t); +#endif /* UNUSED */ + +const struct protent ipcp_protent = { + PPP_IPCP, + ipcp_init, + ipcp_input, + ipcp_protrej, + ipcp_lowerup, + ipcp_lowerdown, + ipcp_open, + ipcp_close, +#if PRINTPKT_SUPPORT + ipcp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "IPCP", + "IP", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ipcp_option_list, + ip_check_options, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + ip_demand_conf, + ip_active_pkt +#endif /* DEMAND_SUPPORT */ +}; + +static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute); + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ +#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ +#define CILEN_ADDR 6 /* new-style single address option */ +#define CILEN_ADDRS 10 /* old-style dual address option */ + + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if 0 /* UNUSED, already defined by lwIP */ +/* + * Make a string representation of a network IP address. + */ +char * +ip_ntoa(ipaddr) +u32_t ipaddr; +{ + static char b[64]; + + slprintf(b, sizeof(b), "%I", ipaddr); + return b; +} +#endif /* UNUSED, already defined by lwIP */ + +/* + * Option parsing. + */ +#if PPP_OPTIONS +/* + * setvjslots - set maximum number of connection slots for VJ compression + */ +static int +setvjslots(argv) + char **argv; +{ + int value; + + if (!int_option(*argv, &value)) + return 0; + + if (value < 2 || value > 16) { + option_error("vj-max-slots value must be between 2 and 16"); + return 0; + } + ipcp_wantoptions [0].maxslotindex = + ipcp_allowoptions[0].maxslotindex = value - 1; + slprintf(vj_value, sizeof(vj_value), "%d", value); + return 1; +} + +/* + * setdnsaddr - set the dns address(es) + */ +static int +setdnsaddr(argv) + char **argv; +{ + u32_t dns; + struct hostent *hp; + + dns = inet_addr(*argv); + if (dns == (u32_t) -1) { + if ((hp = gethostbyname(*argv)) == NULL) { + option_error("invalid address parameter '%s' for ms-dns option", + *argv); + return 0; + } + dns = *(u32_t *)hp->h_addr; + } + + /* We take the last 2 values given, the 2nd-last as the primary + and the last as the secondary. If only one is given it + becomes both primary and secondary. */ + if (ipcp_allowoptions[0].dnsaddr[1] == 0) + ipcp_allowoptions[0].dnsaddr[0] = dns; + else + ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1]; + + /* always set the secondary address value. */ + ipcp_allowoptions[0].dnsaddr[1] = dns; + + return (1); +} + +/* + * setwinsaddr - set the wins address(es) + * This is primrarly used with the Samba package under UNIX or for pointing + * the caller to the existing WINS server on a Windows NT platform. + */ +static int +setwinsaddr(argv) + char **argv; +{ + u32_t wins; + struct hostent *hp; + + wins = inet_addr(*argv); + if (wins == (u32_t) -1) { + if ((hp = gethostbyname(*argv)) == NULL) { + option_error("invalid address parameter '%s' for ms-wins option", + *argv); + return 0; + } + wins = *(u32_t *)hp->h_addr; + } + + /* We take the last 2 values given, the 2nd-last as the primary + and the last as the secondary. If only one is given it + becomes both primary and secondary. */ + if (ipcp_allowoptions[0].winsaddr[1] == 0) + ipcp_allowoptions[0].winsaddr[0] = wins; + else + ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1]; + + /* always set the secondary address value. */ + ipcp_allowoptions[0].winsaddr[1] = wins; + + return (1); +} + +/* + * setipaddr - Set the IP address + * If doit is 0, the call is to check whether this option is + * potentially an IP address specification. + * Not static so that plugins can call it to set the addresses + */ +int +setipaddr(arg, argv, doit) + char *arg; + char **argv; + int doit; +{ + struct hostent *hp; + char *colon; + u32_t local, remote; + ipcp_options *wo = &ipcp_wantoptions[0]; + static int prio_local = 0, prio_remote = 0; + + /* + * IP address pair separated by ":". + */ + if ((colon = strchr(arg, ':')) == NULL) + return 0; + if (!doit) + return 1; + + /* + * If colon first character, then no local addr. + */ + if (colon != arg && option_priority >= prio_local) { + *colon = '\0'; + if ((local = inet_addr(arg)) == (u32_t) -1) { + if ((hp = gethostbyname(arg)) == NULL) { + option_error("unknown host: %s", arg); + return 0; + } + local = *(u32_t *)hp->h_addr; + } + if (bad_ip_adrs(local)) { + option_error("bad local IP address %s", ip_ntoa(local)); + return 0; + } + if (local != 0) + wo->ouraddr = local; + *colon = ':'; + prio_local = option_priority; + } + + /* + * If colon last character, then no remote addr. + */ + if (*++colon != '\0' && option_priority >= prio_remote) { + if ((remote = inet_addr(colon)) == (u32_t) -1) { + if ((hp = gethostbyname(colon)) == NULL) { + option_error("unknown host: %s", colon); + return 0; + } + remote = *(u32_t *)hp->h_addr; + if (remote_name[0] == 0) + strlcpy(remote_name, colon, sizeof(remote_name)); + } + if (bad_ip_adrs(remote)) { + option_error("bad remote IP address %s", ip_ntoa(remote)); + return 0; + } + if (remote != 0) + wo->hisaddr = remote; + prio_remote = option_priority; + } + + return 1; +} + +static void +printipaddr(opt, printer, arg) + option_t *opt; + void (*printer) (void *, char *, ...); + void *arg; +{ + ipcp_options *wo = &ipcp_wantoptions[0]; + + if (wo->ouraddr != 0) + printer(arg, "%I", wo->ouraddr); + printer(arg, ":"); + if (wo->hisaddr != 0) + printer(arg, "%I", wo->hisaddr); +} + +/* + * setnetmask - set the netmask to be used on the interface. + */ +static int +setnetmask(argv) + char **argv; +{ + u32_t mask; + int n; + char *p; + + /* + * Unfortunately, if we use inet_addr, we can't tell whether + * a result of all 1s is an error or a valid 255.255.255.255. + */ + p = *argv; + n = parse_dotted_ip(p, &mask); + + mask = lwip_htonl(mask); + + if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) { + option_error("invalid netmask value '%s'", *argv); + return 0; + } + + netmask = mask; + slprintf(netmask_str, sizeof(netmask_str), "%I", mask); + + return (1); +} + +int +parse_dotted_ip(p, vp) + char *p; + u32_t *vp; +{ + int n; + u32_t v, b; + char *endp, *p0 = p; + + v = 0; + for (n = 3;; --n) { + b = strtoul(p, &endp, 0); + if (endp == p) + return 0; + if (b > 255) { + if (n < 3) + return 0; + /* accept e.g. 0xffffff00 */ + *vp = b; + return endp - p0; + } + v |= b << (n * 8); + p = endp; + if (n == 0) + break; + if (*p != '.') + return 0; + ++p; + } + *vp = v; + return p - p0; +} +#endif /* PPP_OPTIONS */ + +/* + * ipcp_init - Initialize IPCP. + */ +static void ipcp_init(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_IPCP; + f->callbacks = &ipcp_callbacks; + fsm_init(f); + + /* + * Some 3G modems use repeated IPCP NAKs as a way of stalling + * until they can contact a server on the network, so we increase + * the default number of NAKs we accept before we start treating + * them as rejects. + */ + f->maxnakloops = 100; + +#if 0 /* Not necessary, everything is cleared in ppp_new() */ + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); +#endif /* 0 */ + + wo->neg_addr = wo->old_addrs = 1; +#if VJ_SUPPORT + wo->neg_vj = 1; + wo->vj_protocol = IPCP_VJ_COMP; + wo->maxslotindex = MAX_STATES - 1; /* really max index */ + wo->cflag = 1; +#endif /* VJ_SUPPORT */ + +#if 0 /* UNUSED */ + /* wanting default route by default */ + wo->default_route = 1; +#endif /* UNUSED */ + + ao->neg_addr = ao->old_addrs = 1; +#if VJ_SUPPORT + /* max slots and slot-id compression are currently hardwired in */ + /* ppp_if.c to 16 and 1, this needs to be changed (among other */ + /* things) gmc */ + + ao->neg_vj = 1; + ao->maxslotindex = MAX_STATES - 1; + ao->cflag = 1; +#endif /* #if VJ_SUPPORT */ + +#if 0 /* UNUSED */ + /* + * XXX These control whether the user may use the proxyarp + * and defaultroute options. + */ + ao->proxy_arp = 1; + ao->default_route = 1; +#endif /* UNUSED */ +} + + +/* + * ipcp_open - IPCP is allowed to come up. + */ +static void ipcp_open(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_open(f); + pcb->ipcp_is_open = 1; +} + + +/* + * ipcp_close - Take IPCP down. + */ +static void ipcp_close(ppp_pcb *pcb, const char *reason) { + fsm *f = &pcb->ipcp_fsm; + fsm_close(f, reason); +} + + +/* + * ipcp_lowerup - The lower layer is up. + */ +static void ipcp_lowerup(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerup(f); +} + + +/* + * ipcp_lowerdown - The lower layer is down. + */ +static void ipcp_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerdown(f); +} + + +/* + * ipcp_input - Input IPCP packet. + */ +static void ipcp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->ipcp_fsm; + fsm_input(f, p, len); +} + + +/* + * ipcp_protrej - A Protocol-Reject was received for IPCP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void ipcp_protrej(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerdown(f); +} + + +/* + * ipcp_resetci - Reset our CI. + * Called by fsm_sconfreq, Send Configure Request. + */ +static void ipcp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + + wo->req_addr = (wo->neg_addr || wo->old_addrs) && + (ao->neg_addr || ao->old_addrs); + if (wo->ouraddr == 0) + wo->accept_local = 1; + if (wo->hisaddr == 0) + wo->accept_remote = 1; +#if LWIP_DNS + wo->req_dns1 = wo->req_dns2 = pcb->settings.usepeerdns; /* Request DNS addresses from the peer */ +#endif /* LWIP_DNS */ + *go = *wo; + if (!pcb->ask_for_local) + go->ouraddr = 0; +#if 0 /* UNUSED */ + if (ip_choose_hook) { + ip_choose_hook(&wo->hisaddr); + if (wo->hisaddr) { + wo->accept_remote = 0; + } + } +#endif /* UNUSED */ + BZERO(&pcb->ipcp_hisoptions, sizeof(ipcp_options)); +} + + +/* + * ipcp_cilen - Return length of our CI. + * Called by fsm_sconfreq, Send Configure Request. + */ +static int ipcp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; +#if VJ_SUPPORT + ipcp_options *wo = &pcb->ipcp_wantoptions; +#endif /* VJ_SUPPORT */ + ipcp_options *ho = &pcb->ipcp_hisoptions; + +#define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0) +#if VJ_SUPPORT +#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) +#endif /* VJ_SUPPORT */ +#define LENCIADDR(neg) (neg ? CILEN_ADDR : 0) +#if LWIP_DNS +#define LENCIDNS(neg) LENCIADDR(neg) +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ +#define LENCIWINS(neg) LENCIADDR(neg) +#endif /* UNUSED - WINS */ + + /* + * First see if we want to change our options to the old + * forms because we have received old forms from the peer. + */ + if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs) + go->neg_addr = 0; + +#if VJ_SUPPORT + if (wo->neg_vj && !go->neg_vj && !go->old_vj) { + /* try an older style of VJ negotiation */ + /* use the old style only if the peer did */ + if (ho->neg_vj && ho->old_vj) { + go->neg_vj = 1; + go->old_vj = 1; + go->vj_protocol = ho->vj_protocol; + } + } +#endif /* VJ_SUPPORT */ + + return (LENCIADDRS(!go->neg_addr && go->old_addrs) + +#if VJ_SUPPORT + LENCIVJ(go->neg_vj, go->old_vj) + +#endif /* VJ_SUPPORT */ + LENCIADDR(go->neg_addr) + +#if LWIP_DNS + LENCIDNS(go->req_dns1) + + LENCIDNS(go->req_dns2) + +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + LENCIWINS(go->winsaddr[0]) + + LENCIWINS(go->winsaddr[1]) + +#endif /* UNUSED - WINS */ + 0); +} + + +/* + * ipcp_addci - Add our desired CIs to a packet. + * Called by fsm_sconfreq, Send Configure Request. + */ +static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + int len = *lenp; + +#define ADDCIADDRS(opt, neg, val1, val2) \ + if (neg) { \ + if (len >= CILEN_ADDRS) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDRS, ucp); \ + l = lwip_ntohl(val1); \ + PUTLONG(l, ucp); \ + l = lwip_ntohl(val2); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDRS; \ + } else \ + go->old_addrs = 0; \ + } + +#if VJ_SUPPORT +#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if (len >= vjlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(vjlen, ucp); \ + PUTSHORT(val, ucp); \ + if (!old) { \ + PUTCHAR(maxslotindex, ucp); \ + PUTCHAR(cflag, ucp); \ + } \ + len -= vjlen; \ + } else \ + neg = 0; \ + } +#endif /* VJ_SUPPORT */ + +#define ADDCIADDR(opt, neg, val) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = lwip_ntohl(val); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + neg = 0; \ + } + +#if LWIP_DNS +#define ADDCIDNS(opt, neg, addr) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = lwip_ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + neg = 0; \ + } +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ +#define ADDCIWINS(opt, addr) \ + if (addr) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = lwip_ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + addr = 0; \ + } +#endif /* UNUSED - WINS */ + + ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, + go->hisaddr); + +#if VJ_SUPPORT + ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); +#endif /* VJ_SUPPORT */ + + ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); + +#if LWIP_DNS + ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]); +#endif /* UNUSED - WINS */ + + *lenp -= len; +} + + +/* + * ipcp_ackci - Ack our CIs. + * Called by fsm_rconfack, Receive Configure ACK. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int ipcp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_short cilen, citype; + u32_t cilong; +#if VJ_SUPPORT + u_short cishort; + u_char cimaxslotindex, cicflag; +#endif /* VJ_SUPPORT */ + + /* + * CIs must be in exactly the same order that we sent... + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + +#define ACKCIADDRS(opt, neg, val1, val2) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDRS) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDRS || \ + citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + if (val1 != cilong) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + if (val2 != cilong) \ + goto bad; \ + } + +#if VJ_SUPPORT +#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if ((len -= vjlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != vjlen || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslotindex) \ + goto bad; \ + GETCHAR(cicflag, p); \ + if (cicflag != cflag) \ + goto bad; \ + } \ + } +#endif /* VJ_SUPPORT */ + +#define ACKCIADDR(opt, neg, val) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || \ + citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + if (val != cilong) \ + goto bad; \ + } + +#if LWIP_DNS +#define ACKCIDNS(opt, neg, addr) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + if (addr != cilong) \ + goto bad; \ + } +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ +#define ACKCIWINS(opt, addr) \ + if (addr) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + if (addr != cilong) \ + goto bad; \ + } +#endif /* UNUSED - WINS */ + + ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, + go->hisaddr); + +#if VJ_SUPPORT + ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); +#endif /* VJ_SUPPORT */ + + ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); + +#if LWIP_DNS + ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]); +#endif /* UNUSED - WINS */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); + +bad: + IPCPDEBUG(("ipcp_ackci: received bad Ack!")); + return (0); +} + +/* + * ipcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPCP is in the OPENED state. + * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_char citype, cilen, *next; +#if VJ_SUPPORT + u_char cimaxslotindex, cicflag; + u_short cishort; +#endif /* VJ_SUPPORT */ + u32_t ciaddr1, ciaddr2, l; +#if LWIP_DNS + u32_t cidnsaddr; +#endif /* LWIP_DNS */ + ipcp_options no; /* options we've seen Naks for */ + ipcp_options try_; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIADDRS(opt, neg, code) \ + if ((neg) && \ + (cilen = p[1]) == CILEN_ADDRS && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciaddr1 = lwip_htonl(l); \ + GETLONG(l, p); \ + ciaddr2 = lwip_htonl(l); \ + no.old_addrs = 1; \ + code \ + } + +#if VJ_SUPPORT +#define NAKCIVJ(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#endif /* VJ_SUPPORT */ + +#define NAKCIADDR(opt, neg, code) \ + if (go->neg && \ + (cilen = p[1]) == CILEN_ADDR && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciaddr1 = lwip_htonl(l); \ + no.neg = 1; \ + code \ + } + +#if LWIP_DNS +#define NAKCIDNS(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cidnsaddr = lwip_htonl(l); \ + no.neg = 1; \ + code \ + } +#endif /* LWIP_DNS */ + + /* + * Accept the peer's idea of {our,his} address, if different + * from our idea, only if the accept_{local,remote} flag is set. + */ + NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, + if (treat_as_reject) { + try_.old_addrs = 0; + } else { + if (go->accept_local && ciaddr1) { + /* take his idea of our address */ + try_.ouraddr = ciaddr1; + } + if (go->accept_remote && ciaddr2) { + /* take his idea of his address */ + try_.hisaddr = ciaddr2; + } + } + ); + +#if VJ_SUPPORT + /* + * Accept the peer's value of maxslotindex provided that it + * is less than what we asked for. Turn off slot-ID compression + * if the peer wants. Send old-style compress-type option if + * the peer wants. + */ + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + if (treat_as_reject) { + try_.neg_vj = 0; + } else if (cilen == CILEN_VJ) { + GETCHAR(cimaxslotindex, p); + GETCHAR(cicflag, p); + if (cishort == IPCP_VJ_COMP) { + try_.old_vj = 0; + if (cimaxslotindex < go->maxslotindex) + try_.maxslotindex = cimaxslotindex; + if (!cicflag) + try_.cflag = 0; + } else { + try_.neg_vj = 0; + } + } else { + if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { + try_.old_vj = 1; + try_.vj_protocol = cishort; + } else { + try_.neg_vj = 0; + } + } + ); +#endif /* VJ_SUPPORT */ + + NAKCIADDR(CI_ADDR, neg_addr, + if (treat_as_reject) { + try_.neg_addr = 0; + try_.old_addrs = 0; + } else if (go->accept_local && ciaddr1) { + /* take his idea of our address */ + try_.ouraddr = ciaddr1; + } + ); + +#if LWIP_DNS + NAKCIDNS(CI_MS_DNS1, req_dns1, + if (treat_as_reject) { + try_.req_dns1 = 0; + } else { + try_.dnsaddr[0] = cidnsaddr; + } + ); + + NAKCIDNS(CI_MS_DNS2, req_dns2, + if (treat_as_reject) { + try_.req_dns2 = 0; + } else { + try_.dnsaddr[1] = cidnsaddr; + } + ); +#endif /* #if LWIP_DNS */ + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If they want to negotiate about IP addresses, we comply. + * If they want us to ask for compression, we refuse. + * If they want us to ask for ms-dns, we do that, since some + * peers get huffy if we don't. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) + goto bad; + next = p + cilen - 2; + + switch (citype) { +#if VJ_SUPPORT + case CI_COMPRESSTYPE: + if (go->neg_vj || no.neg_vj || + (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) + goto bad; + no.neg_vj = 1; + break; +#endif /* VJ_SUPPORT */ + case CI_ADDRS: + if ((!go->neg_addr && go->old_addrs) || no.old_addrs + || cilen != CILEN_ADDRS) + goto bad; + try_.neg_addr = 0; + GETLONG(l, p); + ciaddr1 = lwip_htonl(l); + if (ciaddr1 && go->accept_local) + try_.ouraddr = ciaddr1; + GETLONG(l, p); + ciaddr2 = lwip_htonl(l); + if (ciaddr2 && go->accept_remote) + try_.hisaddr = ciaddr2; + no.old_addrs = 1; + break; + case CI_ADDR: + if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) + goto bad; + try_.old_addrs = 0; + GETLONG(l, p); + ciaddr1 = lwip_htonl(l); + if (ciaddr1 && go->accept_local) + try_.ouraddr = ciaddr1; + if (try_.ouraddr != 0) + try_.neg_addr = 1; + no.neg_addr = 1; + break; +#if LWIP_DNS + case CI_MS_DNS1: + if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + try_.dnsaddr[0] = lwip_htonl(l); + try_.req_dns1 = 1; + no.req_dns1 = 1; + break; + case CI_MS_DNS2: + if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + try_.dnsaddr[1] = lwip_htonl(l); + try_.req_dns2 = 1; + no.req_dns2 = 1; + break; +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + case CI_MS_WINS1: + case CI_MS_WINS2: + if (cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + ciaddr1 = lwip_htonl(l); + if (ciaddr1) + try_.winsaddr[citype == CI_MS_WINS2] = ciaddr1; + break; +#endif /* UNUSED - WINS */ + default: + break; + } + p = next; + } + + /* + * OK, the Nak is good. Now we can update state. + * If there are any remaining options, we ignore them. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + + return 1; + +bad: + IPCPDEBUG(("ipcp_nakci: received bad Nak!")); + return 0; +} + + +/* + * ipcp_rejci - Reject some of our CIs. + * Callback from fsm_rconfnakrej. + */ +static int ipcp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_char cilen; +#if VJ_SUPPORT + u_char cimaxslotindex, ciflag; + u_short cishort; +#endif /* VJ_SUPPORT */ + u32_t cilong; + ipcp_options try_; /* options to request next time */ + + try_ = *go; + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIADDRS(opt, neg, val1, val2) \ + if ((neg) && \ + (cilen = p[1]) == CILEN_ADDRS && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val1) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val2) \ + goto bad; \ + try_.old_addrs = 0; \ + } + +#if VJ_SUPPORT +#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ + if (go->neg && \ + p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ + len >= p[1] && \ + p[0] == opt) { \ + len -= p[1]; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslot) \ + goto bad; \ + GETCHAR(ciflag, p); \ + if (ciflag != cflag) \ + goto bad; \ + } \ + try_.neg = 0; \ + } +#endif /* VJ_SUPPORT */ + +#define REJCIADDR(opt, neg, val) \ + if (go->neg && \ + (cilen = p[1]) == CILEN_ADDR && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } + +#if LWIP_DNS +#define REJCIDNS(opt, neg, dnsaddr) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + /* Check rejected value. */ \ + if (cilong != dnsaddr) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ +#define REJCIWINS(opt, addr) \ + if (addr && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + /* Check rejected value. */ \ + if (cilong != addr) \ + goto bad; \ + try_.winsaddr[opt == CI_MS_WINS2] = 0; \ + } +#endif /* UNUSED - WINS */ + + REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, + go->ouraddr, go->hisaddr); + +#if VJ_SUPPORT + REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); +#endif /* VJ_SUPPORT */ + + REJCIADDR(CI_ADDR, neg_addr, go->ouraddr); + +#if LWIP_DNS + REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); + + REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + REJCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + REJCIWINS(CI_MS_WINS2, go->winsaddr[1]); +#endif /* UNUSED - WINS */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + IPCPDEBUG(("ipcp_rejci: received bad Reject!")); + return 0; +} + + +/* + * ipcp_reqci - Check the peer's requested CIs and send appropriate response. + * Callback from fsm_rconfreq, Receive Configure Request + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * len = Length of requested CIs + */ +static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ +#if VJ_SUPPORT + u_short cishort; /* Parsed short value */ +#endif /* VJ_SUPPORT */ + u32_t tl, ciaddr1, ciaddr2;/* Parsed address values */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ +#if VJ_SUPPORT + u_char maxslotindex, cflag; +#endif /* VJ_SUPPORT */ +#if LWIP_DNS + int d; +#endif /* LWIP_DNS */ + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPCPDEBUG(("ipcp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_ADDRS: + if (!ao->old_addrs || ho->neg_addr || + cilen != CILEN_ADDRS) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = lwip_htonl(tl); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = lwip_ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * If neither we nor he knows his address, reject the option. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + /* + * If he doesn't know our address, or if we both have our address + * but disagree about it, then NAK it with our idea. + */ + GETLONG(tl, p); /* Parse desination address (ours) */ + ciaddr2 = lwip_htonl(tl); + if (ciaddr2 != wo->ouraddr) { + if (ciaddr2 == 0 || !wo->accept_local) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = lwip_ntohl(wo->ouraddr); + PUTLONG(tl, p); + } + } else { + wo->ouraddr = ciaddr2; /* accept peer's idea */ + } + } + + ho->old_addrs = 1; + ho->hisaddr = ciaddr1; + ho->ouraddr = ciaddr2; + break; + + case CI_ADDR: + if (!ao->neg_addr || ho->old_addrs || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = lwip_htonl(tl); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = lwip_ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * Don't ACK an address of 0.0.0.0 - reject it instead. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + ho->neg_addr = 1; + ho->hisaddr = ciaddr1; + break; + +#if LWIP_DNS + case CI_MS_DNS1: + case CI_MS_DNS2: + /* Microsoft primary or secondary DNS request */ + d = citype == CI_MS_DNS2; + + /* If we do not have a DNS address then we cannot send it */ + if (ao->dnsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (lwip_htonl(tl) != ao->dnsaddr[d]) { + DECPTR(sizeof(u32_t), p); + tl = lwip_ntohl(ao->dnsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + case CI_MS_WINS1: + case CI_MS_WINS2: + /* Microsoft primary or secondary WINS request */ + d = citype == CI_MS_WINS2; + + /* If we do not have a DNS address then we cannot send it */ + if (ao->winsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (lwip_htonl(tl) != ao->winsaddr[d]) { + DECPTR(sizeof(u32_t), p); + tl = lwip_ntohl(ao->winsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; +#endif /* UNUSED - WINS */ + +#if VJ_SUPPORT + case CI_COMPRESSTYPE: + if (!ao->neg_vj || + (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + if (!(cishort == IPCP_VJ_COMP || + (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { + orc = CONFREJ; + break; + } + + ho->neg_vj = 1; + ho->vj_protocol = cishort; + if (cilen == CILEN_VJ) { + GETCHAR(maxslotindex, p); + if (maxslotindex > ao->maxslotindex) { + orc = CONFNAK; + if (!reject_if_disagree){ + DECPTR(1, p); + PUTCHAR(ao->maxslotindex, p); + } + } + GETCHAR(cflag, p); + if (cflag && !ao->cflag) { + orc = CONFNAK; + if (!reject_if_disagree){ + DECPTR(1, p); + PUTCHAR(wo->cflag, p); + } + } + ho->maxslotindex = maxslotindex; + ho->cflag = cflag; + } else { + ho->old_vj = 1; + ho->maxslotindex = MAX_STATES - 1; + ho->cflag = 1; + } + break; +#endif /* VJ_SUPPORT */ + + default: + orc = CONFREJ; + break; + } +endswitch: + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) /* Getting fed up with sending NAKs? */ + orc = CONFREJ; /* Get tough if so */ + else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) + MEMCPY(ucp, cip, cilen); /* Move it */ + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their address, and they didn't send their address, then we + * send a NAK with a CI_ADDR option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs && + wo->req_addr && !reject_if_disagree && !pcb->settings.noremoteip) { + if (rc == CONFACK) { + rc = CONFNAK; + ucp = inp; /* reset pointer */ + wo->req_addr = 0; /* don't ask again */ + } + PUTCHAR(CI_ADDR, ucp); + PUTCHAR(CILEN_ADDR, ucp); + tl = lwip_ntohl(wo->hisaddr); + PUTLONG(tl, ucp); + } + + *len = ucp - inp; /* Compute output length */ + IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +#if 0 /* UNUSED */ +/* + * ip_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +static void +ip_check_options() +{ + struct hostent *hp; + u32_t local; + ipcp_options *wo = &ipcp_wantoptions[0]; + + /* + * Default our local IP address based on our hostname. + * If local IP address already given, don't bother. + */ + if (wo->ouraddr == 0 && !disable_defaultip) { + /* + * Look up our hostname (possibly with domain name appended) + * and take the first IP address as our local IP address. + * If there isn't an IP address for our hostname, too bad. + */ + wo->accept_local = 1; /* don't insist on this default value */ + if ((hp = gethostbyname(hostname)) != NULL) { + local = *(u32_t *)hp->h_addr; + if (local != 0 && !bad_ip_adrs(local)) + wo->ouraddr = local; + } + } + ask_for_local = wo->ouraddr != 0 || !disable_defaultip; +} +#endif /* UNUSED */ + +#if DEMAND_SUPPORT +/* + * ip_demand_conf - configure the interface as though + * IPCP were up, for use with dial-on-demand. + */ +static int +ip_demand_conf(u) + int u; +{ + ppp_pcb *pcb = &ppp_pcb_list[u]; + ipcp_options *wo = &ipcp_wantoptions[u]; + + if (wo->hisaddr == 0 && !pcb->settings.noremoteip) { + /* make up an arbitrary address for the peer */ + wo->hisaddr = lwip_htonl(0x0a707070 + ifunit); + wo->accept_remote = 1; + } + if (wo->ouraddr == 0) { + /* make up an arbitrary address for us */ + wo->ouraddr = lwip_htonl(0x0a404040 + ifunit); + wo->accept_local = 1; + ask_for_local = 0; /* don't tell the peer this address */ + } + if (!sifaddr(pcb, wo->ouraddr, wo->hisaddr, get_mask(wo->ouraddr))) + return 0; + if (!sifup(pcb)) + return 0; + if (!sifnpmode(pcb, PPP_IP, NPMODE_QUEUE)) + return 0; +#if 0 /* UNUSED */ + if (wo->default_route) + if (sifdefaultroute(pcb, wo->ouraddr, wo->hisaddr, + wo->replace_default_route)) + default_route_set[u] = 1; +#endif /* UNUSED */ +#if 0 /* UNUSED - PROXY ARP */ + if (wo->proxy_arp) + if (sifproxyarp(pcb, wo->hisaddr)) + proxy_arp_set[u] = 1; +#endif /* UNUSED - PROXY ARP */ + + ppp_notice("local IP address %I", wo->ouraddr); + if (wo->hisaddr) + ppp_notice("remote IP address %I", wo->hisaddr); + + return 1; +} +#endif /* DEMAND_SUPPORT */ + +/* + * ipcp_up - IPCP has come UP. + * + * Configure the IP network interface appropriately and bring it up. + */ +static void ipcp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + u32_t mask; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + ipcp_options *wo = &pcb->ipcp_wantoptions; + + IPCPDEBUG(("ipcp: up")); + + /* + * We must have a non-zero IP address for both ends of the link. + */ + if (!ho->neg_addr && !ho->old_addrs) + ho->hisaddr = wo->hisaddr; + + if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs) + && wo->ouraddr != 0) { + ppp_error("Peer refused to agree to our IP address"); + ipcp_close(f->pcb, "Refused our IP address"); + return; + } + if (go->ouraddr == 0) { + ppp_error("Could not determine local IP address"); + ipcp_close(f->pcb, "Could not determine local IP address"); + return; + } + if (ho->hisaddr == 0 && !pcb->settings.noremoteip) { + ho->hisaddr = lwip_htonl(0x0a404040); + ppp_warn("Could not determine remote IP address: defaulting to %I", + ho->hisaddr); + } +#if 0 /* UNUSED */ + script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); + if (ho->hisaddr != 0) + script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1); +#endif /* UNUSED */ + +#if LWIP_DNS + if (!go->req_dns1) + go->dnsaddr[0] = 0; + if (!go->req_dns2) + go->dnsaddr[1] = 0; +#if 0 /* UNUSED */ + if (go->dnsaddr[0]) + script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); + if (go->dnsaddr[1]) + script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); +#endif /* UNUSED */ + if (pcb->settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { + sdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); +#if 0 /* UNUSED */ + script_setenv("USEPEERDNS", "1", 0); + create_resolv(go->dnsaddr[0], go->dnsaddr[1]); +#endif /* UNUSED */ + } +#endif /* LWIP_DNS */ + + /* + * Check that the peer is allowed to use the IP address it wants. + */ + if (ho->hisaddr != 0) { + u32_t addr = lwip_ntohl(ho->hisaddr); + if ((addr >> IP_CLASSA_NSHIFT) == IP_LOOPBACKNET + || IP_MULTICAST(addr) || IP_BADCLASS(addr) + /* + * For now, consider that PPP in server mode with peer required + * to authenticate must provide the peer IP address, reject any + * IP address wanted by peer different than the one we wanted. + */ +#if PPP_SERVER && PPP_AUTH_SUPPORT + || (pcb->settings.auth_required && wo->hisaddr != ho->hisaddr) +#endif /* PPP_SERVER && PPP_AUTH_SUPPORT */ + ) { + ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); + ipcp_close(pcb, "Unauthorized remote IP address"); + return; + } + } +#if 0 /* Unused */ + /* Upstream checking code */ + if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) { + ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); + ipcp_close(f->unit, "Unauthorized remote IP address"); + return; + } +#endif /* Unused */ + +#if VJ_SUPPORT + /* set tcp compression */ + sifvjcomp(pcb, ho->neg_vj, ho->cflag, ho->maxslotindex); +#endif /* VJ_SUPPORT */ + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, the interface is already + * configured, so we put out any saved-up packets, then set the + * interface to pass IP packets. + */ + if (demand) { + if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { + ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr, + wo->replace_default_route); + if (go->ouraddr != wo->ouraddr) { + ppp_warn("Local IP address changed to %I", go->ouraddr); + script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); + wo->ouraddr = go->ouraddr; + } else + script_unsetenv("OLDIPLOCAL"); + if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) { + ppp_warn("Remote IP address changed to %I", ho->hisaddr); + script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); + wo->hisaddr = ho->hisaddr; + } else + script_unsetenv("OLDIPREMOTE"); + + /* Set the interface to the new addresses */ + mask = get_mask(go->ouraddr); + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->unit, "Interface configuration failed"); + return; + } + + /* assign a default route through the interface if required */ + if (ipcp_wantoptions[f->unit].default_route) + if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, + wo->replace_default_route)) + default_route_set[f->unit] = 1; + +#if 0 /* UNUSED - PROXY ARP */ + /* Make a proxy ARP entry if requested. */ + if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp) + if (sifproxyarp(pcb, ho->hisaddr)) + proxy_arp_set[f->unit] = 1; +#endif /* UNUSED - PROXY ARP */ + + } + demand_rexmit(PPP_IP,go->ouraddr); + sifnpmode(pcb, PPP_IP, NPMODE_PASS); + + } else +#endif /* DEMAND_SUPPORT */ + { + /* + * Set IP addresses and (if specified) netmask. + */ + mask = get_mask(go->ouraddr); + +#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->pcb, "Interface configuration failed"); + return; + } +#endif + + /* bring the interface up for IP */ + if (!sifup(pcb)) { +#if PPP_DEBUG + ppp_warn("Interface failed to come up"); +#endif /* PPP_DEBUG */ + ipcp_close(f->pcb, "Interface configuration failed"); + return; + } + +#if (defined(SVR4) && (defined(SNI) || defined(__USLC__))) + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->unit, "Interface configuration failed"); + return; + } +#endif +#if DEMAND_SUPPORT + sifnpmode(pcb, PPP_IP, NPMODE_PASS); +#endif /* DEMAND_SUPPORT */ + +#if 0 /* UNUSED */ + /* assign a default route through the interface if required */ + if (wo->default_route) + if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, + wo->replace_default_route)) + pcb->default_route_set = 1; +#endif /* UNUSED */ + +#if 0 /* UNUSED - PROXY ARP */ + /* Make a proxy ARP entry if requested. */ + if (ho->hisaddr != 0 && wo->proxy_arp) + if (sifproxyarp(pcb, ho->hisaddr)) + pcb->proxy_arp_set = 1; +#endif /* UNUSED - PROXY ARP */ + + wo->ouraddr = go->ouraddr; + + ppp_notice("local IP address %I", go->ouraddr); + if (ho->hisaddr != 0) + ppp_notice("remote IP address %I", ho->hisaddr); +#if LWIP_DNS + if (go->dnsaddr[0]) + ppp_notice("primary DNS address %I", go->dnsaddr[0]); + if (go->dnsaddr[1]) + ppp_notice("secondary DNS address %I", go->dnsaddr[1]); +#endif /* LWIP_DNS */ + } + +#if PPP_STATS_SUPPORT + reset_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ + + np_up(pcb, PPP_IP); + pcb->ipcp_is_up = 1; + +#if PPP_NOTIFY + notify(ip_up_notifier, 0); +#endif /* PPP_NOTIFY */ +#if 0 /* UNUSED */ + if (ip_up_hook) + ip_up_hook(); +#endif /* UNUSED */ +} + + +/* + * ipcp_down - IPCP has gone DOWN. + * + * Take the IP network interface down, clear its addresses + * and delete routes through it. + */ +static void ipcp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + + IPCPDEBUG(("ipcp: down")); +#if PPP_STATS_SUPPORT + /* XXX a bit IPv4-centric here, we only need to get the stats + * before the interface is marked down. */ + /* XXX more correct: we must get the stats before running the notifiers, + * at least for the radius plugin */ + update_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ +#if PPP_NOTIFY + notify(ip_down_notifier, 0); +#endif /* PPP_NOTIFY */ +#if 0 /* UNUSED */ + if (ip_down_hook) + ip_down_hook(); +#endif /* UNUSED */ + if (pcb->ipcp_is_up) { + pcb->ipcp_is_up = 0; + np_down(pcb, PPP_IP); + } +#if VJ_SUPPORT + sifvjcomp(pcb, 0, 0, 0); +#endif /* VJ_SUPPORT */ + +#if PPP_STATS_SUPPORT + print_link_stats(); /* _after_ running the notifiers and ip_down_hook(), + * because print_link_stats() sets link_stats_valid + * to 0 (zero) */ +#endif /* PPP_STATS_SUPPORT */ + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, set the interface + * to queue up outgoing packets (for now). + */ + if (demand) { + sifnpmode(pcb, PPP_IP, NPMODE_QUEUE); + } else +#endif /* DEMAND_SUPPORT */ + { +#if DEMAND_SUPPORT + sifnpmode(pcb, PPP_IP, NPMODE_DROP); +#endif /* DEMAND_SUPPORT */ + sifdown(pcb); + ipcp_clear_addrs(pcb, go->ouraddr, + ho->hisaddr, 0); +#if LWIP_DNS + cdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); +#endif /* LWIP_DNS */ + } +} + + +/* + * ipcp_clear_addrs() - clear the interface addresses, routes, + * proxy arp entries, etc. + */ +static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute) { + LWIP_UNUSED_ARG(replacedefaultroute); + +#if 0 /* UNUSED - PROXY ARP */ + if (pcb->proxy_arp_set) { + cifproxyarp(pcb, hisaddr); + pcb->proxy_arp_set = 0; + } +#endif /* UNUSED - PROXY ARP */ +#if 0 /* UNUSED */ + /* If replacedefaultroute, sifdefaultroute will be called soon + * with replacedefaultroute set and that will overwrite the current + * default route. This is the case only when doing demand, otherwise + * during demand, this cifdefaultroute would restore the old default + * route which is not what we want in this case. In the non-demand + * case, we'll delete the default route and restore the old if there + * is one saved by an sifdefaultroute with replacedefaultroute. + */ + if (!replacedefaultroute && pcb->default_route_set) { + cifdefaultroute(pcb, ouraddr, hisaddr); + pcb->default_route_set = 0; + } +#endif /* UNUSED */ + cifaddr(pcb, ouraddr, hisaddr); +} + + +/* + * ipcp_finished - possibly shut down the lower layers. + */ +static void ipcp_finished(fsm *f) { + ppp_pcb *pcb = f->pcb; + if (pcb->ipcp_is_open) { + pcb->ipcp_is_open = 0; + np_finished(pcb, PPP_IP); + } +} + + +#if 0 /* UNUSED */ +/* + * create_resolv - create the replacement resolv.conf file + */ +static void +create_resolv(peerdns1, peerdns2) + u32_t peerdns1, peerdns2; +{ + +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ipcp_printpkt - print the contents of an IPCP packet. + */ +static const char* const ipcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej" +}; + +static int ipcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, olen; + const u_char *pstart, *optend; +#if VJ_SUPPORT + u_short cishort; +#endif /* VJ_SUPPORT */ + u32_t cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ipcp_codenames)) + printer(arg, " %s", ipcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_ADDRS: + if (olen == CILEN_ADDRS) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addrs %I", lwip_htonl(cilong)); + GETLONG(cilong, p); + printer(arg, " %I", lwip_htonl(cilong)); + } + break; +#if VJ_SUPPORT + case CI_COMPRESSTYPE: + if (olen >= CILEN_COMPRESS) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "compress "); + switch (cishort) { + case IPCP_VJ_COMP: + printer(arg, "VJ"); + break; + case IPCP_VJ_COMP_OLD: + printer(arg, "old-VJ"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; +#endif /* VJ_SUPPORT */ + case CI_ADDR: + if (olen == CILEN_ADDR) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addr %I", lwip_htonl(cilong)); + } + break; +#if LWIP_DNS + case CI_MS_DNS1: + case CI_MS_DNS2: + p += 2; + GETLONG(cilong, p); + printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2), + htonl(cilong)); + break; +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + case CI_MS_WINS1: + case CI_MS_WINS2: + p += 2; + GETLONG(cilong, p); + printer(arg, "ms-wins %I", lwip_htonl(cilong)); + break; +#endif /* UNUSED - WINS */ + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#if DEMAND_SUPPORT +/* + * ip_active_pkt - see if this IP packet is worth bringing the link up for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#define IP_HDRLEN 20 /* bytes */ +#define IP_OFFMASK 0x1fff +#ifndef IPPROTO_TCP +#define IPPROTO_TCP 6 +#endif +#define TCP_HDRLEN 20 +#define TH_FIN 0x01 + +/* + * We use these macros because the IP header may be at an odd address, + * and some compilers might use word loads to get th_off or ip_hl. + */ + +#define net_short(x) (((x)[0] << 8) + (x)[1]) +#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) +#define get_ipoff(x) net_short((unsigned char *)(x) + 6) +#define get_ipproto(x) (((unsigned char *)(x))[9]) +#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) +#define get_tcpflags(x) (((unsigned char *)(x))[13]) + +static int +ip_active_pkt(pkt, len) + u_char *pkt; + int len; +{ + u_char *tcp; + int hlen; + + len -= PPP_HDRLEN; + pkt += PPP_HDRLEN; + if (len < IP_HDRLEN) + return 0; + if ((get_ipoff(pkt) & IP_OFFMASK) != 0) + return 0; + if (get_ipproto(pkt) != IPPROTO_TCP) + return 1; + hlen = get_iphl(pkt) * 4; + if (len < hlen + TCP_HDRLEN) + return 0; + tcp = pkt + hlen; + if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) + return 0; + return 1; +} +#endif /* DEMAND_SUPPORT */ + +#endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/ipv6cp.c b/components/net/lwip-2.0.3/src/netif/ppp/ipv6cp.c new file mode 100644 index 0000000000..11c18df743 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/ipv6cp.c @@ -0,0 +1,1533 @@ +/* + * ipv6cp.c - PPP IPV6 Control Protocol. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* Original version, based on RFC2023 : + + Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt + Économique ayant pour membres BULL S.A. et l'INRIA). + + Ce logiciel informatique est disponible aux conditions + usuelles dans la recherche, c'est-à-dire qu'il peut + être utilisé, copié, modifié, distribué à l'unique + condition que ce texte soit conservé afin que + l'origine de ce logiciel soit reconnue. + + Le nom de l'Institut National de Recherche en Informatique + et en Automatique (INRIA), de l'IMAG, ou d'une personne morale + ou physique ayant participé à l'élaboration de ce logiciel ne peut + être utilisé sans son accord préalable explicite. + + Ce logiciel est fourni tel quel sans aucune garantie, + support ou responsabilité d'aucune sorte. + Ce logiciel est dérivé de sources d'origine + "University of California at Berkeley" et + "Digital Equipment Corporation" couvertes par des copyrights. + + L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) + est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National + Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant + sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). + + This work has been done in the context of GIE DYADE (joint R & D venture + between BULL S.A. and INRIA). + + This software is available with usual "research" terms + with the aim of retain credits of the software. + Permission to use, copy, modify and distribute this software for any + purpose and without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies, + and the name of INRIA, IMAG, or any contributor not be used in advertising + or publicity pertaining to this material without the prior explicit + permission. The software is provided "as is" without any + warranties, support or liabilities of any kind. + This software is derived from source code from + "University of California at Berkeley" and + "Digital Equipment Corporation" protected by copyrights. + + Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) + is a federation of seven research units funded by the CNRS, National + Polytechnic Institute of Grenoble and University Joseph Fourier. + The research unit in Software, Systems, Networks (LSR) is member of IMAG. +*/ + +/* + * Derived from : + * + * + * ipcp.c - PPP IP Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipv6cp.c,v 1.21 2005/08/25 23:59:34 paulus Exp $ + */ + +/* + * @todo: + * + * Proxy Neighbour Discovery. + * + * Better defines for selecting the ordering of + * interface up / set address. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/ipv6cp.h" +#include "netif/ppp/magic.h" + +/* global vars */ +#if 0 /* UNUSED */ +int no_ifaceid_neg = 0; +#endif /* UNUSED */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipv6cp_resetci(fsm *f); /* Reset our CI */ +static int ipv6cp_cilen(fsm *f); /* Return length of our CI */ +static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ +static int ipv6cp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ +static int ipv6cp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ +static void ipv6cp_up(fsm *f); /* We're UP */ +static void ipv6cp_down(fsm *f); /* We're DOWN */ +static void ipv6cp_finished(fsm *f); /* Don't need lower layer */ + +static const fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */ + ipv6cp_resetci, /* Reset our Configuration Information */ + ipv6cp_cilen, /* Length of our Configuration Information */ + ipv6cp_addci, /* Add our Configuration Information */ + ipv6cp_ackci, /* ACK our Configuration Information */ + ipv6cp_nakci, /* NAK our Configuration Information */ + ipv6cp_rejci, /* Reject our Configuration Information */ + ipv6cp_reqci, /* Request peer's Configuration Information */ + ipv6cp_up, /* Called when fsm reaches OPENED state */ + ipv6cp_down, /* Called when fsm leaves OPENED state */ + NULL, /* Called when we want the lower layer up */ + ipv6cp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPV6CP" /* String name of protocol */ +}; + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static int setifaceid(char **arg)); +static void printifaceid(option_t *, + void (*)(void *, char *, ...), void *)); + +static option_t ipv6cp_option_list[] = { + { "ipv6", o_special, (void *)setifaceid, + "Set interface identifiers for IPV6", + OPT_A2PRINTER, (void *)printifaceid }, + + { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Enable IPv6 and IPv6CP", OPT_PRIO | 1 }, + { "noipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB }, + { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB | OPT_ALIAS }, + + { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, + "Accept peer's interface identifier for us", 1 }, + + { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip, + "Use (default) IPv4 address as interface identifier", 1 }, + + { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent, + "Use uniquely-available persistent value for link local address", 1 }, + + { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime, + "Set timeout for IPv6CP", OPT_PRIO }, + { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits, + "Set max #xmits for term-reqs", OPT_PRIO }, + { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits, + "Set max #xmits for conf-reqs", OPT_PRIO }, + { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops, + "Set max #conf-naks for IPv6CP", OPT_PRIO }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ipv6cp_init(ppp_pcb *pcb); +static void ipv6cp_open(ppp_pcb *pcb); +static void ipv6cp_close(ppp_pcb *pcb, const char *reason); +static void ipv6cp_lowerup(ppp_pcb *pcb); +static void ipv6cp_lowerdown(ppp_pcb *pcb); +static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len); +static void ipv6cp_protrej(ppp_pcb *pcb); +#if PPP_OPTIONS +static void ipv6_check_options(void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT +static int ipv6_demand_conf(int u); +#endif /* DEMAND_SUPPORT */ +#if PRINTPKT_SUPPORT +static int ipv6cp_printpkt(const u_char *p, int plen, + void (*printer)(void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if DEMAND_SUPPORT +static int ipv6_active_pkt(u_char *pkt, int len); +#endif /* DEMAND_SUPPORT */ + +const struct protent ipv6cp_protent = { + PPP_IPV6CP, + ipv6cp_init, + ipv6cp_input, + ipv6cp_protrej, + ipv6cp_lowerup, + ipv6cp_lowerdown, + ipv6cp_open, + ipv6cp_close, +#if PRINTPKT_SUPPORT + ipv6cp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "IPV6CP", + "IPV6", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ipv6cp_option_list, + ipv6_check_options, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + ipv6_demand_conf, + ipv6_active_pkt +#endif /* DEMAND_SUPPORT */ +}; + +static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid); +#if 0 /* UNUSED */ +static void ipv6cp_script(char *)); +static void ipv6cp_script_done(void *)); +#endif /* UNUSED */ + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* length for RFC2023 compress opt. */ +#define CILEN_IFACEID 10 /* RFC2472, interface identifier */ + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if 0 /* UNUSED */ +/* + * This state variable is used to ensure that we don't + * run an ipcp-up/down script while one is already running. + */ +static enum script_state { + s_down, + s_up, +} ipv6cp_script_state; +static pid_t ipv6cp_script_pid; +#endif /* UNUSED */ + +static char *llv6_ntoa(eui64_t ifaceid); + +#if PPP_OPTIONS +/* + * setifaceid - set the interface identifiers manually + */ +static int +setifaceid(argv) + char **argv; +{ + char *comma, *arg, c; + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + struct in6_addr addr; + static int prio_local, prio_remote; + +#define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \ + (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) ) + + arg = *argv; + if ((comma = strchr(arg, ',')) == NULL) + comma = arg + strlen(arg); + + /* + * If comma first character, then no local identifier + */ + if (comma != arg) { + c = *comma; + *comma = '\0'; + + if (inet_pton(AF_INET6, arg, &addr) == 0 || !VALIDID(addr)) { + option_error("Illegal interface identifier (local): %s", arg); + return 0; + } + + if (option_priority >= prio_local) { + eui64_copy(addr.s6_addr32[2], wo->ourid); + wo->opt_local = 1; + prio_local = option_priority; + } + *comma = c; + } + + /* + * If comma last character, the no remote identifier + */ + if (*comma != 0 && *++comma != '\0') { + if (inet_pton(AF_INET6, comma, &addr) == 0 || !VALIDID(addr)) { + option_error("Illegal interface identifier (remote): %s", comma); + return 0; + } + if (option_priority >= prio_remote) { + eui64_copy(addr.s6_addr32[2], wo->hisid); + wo->opt_remote = 1; + prio_remote = option_priority; + } + } + + if (override_value("+ipv6", option_priority, option_source)) + ipv6cp_protent.enabled_flag = 1; + return 1; +} + +static void +printifaceid(opt, printer, arg) + option_t *opt; + void (*printer)(void *, char *, ...)); + void *arg; +{ + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + + if (wo->opt_local) + printer(arg, "%s", llv6_ntoa(wo->ourid)); + printer(arg, ","); + if (wo->opt_remote) + printer(arg, "%s", llv6_ntoa(wo->hisid)); +} +#endif /* PPP_OPTIONS */ + +/* + * Make a string representation of a network address. + */ +static char * +llv6_ntoa(eui64_t ifaceid) +{ + static char b[26]; + + sprintf(b, "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x", + ifaceid.e8[0], ifaceid.e8[1], ifaceid.e8[2], ifaceid.e8[3], + ifaceid.e8[4], ifaceid.e8[5], ifaceid.e8[6], ifaceid.e8[7]); + + return b; +} + + +/* + * ipv6cp_init - Initialize IPV6CP. + */ +static void ipv6cp_init(ppp_pcb *pcb) { + fsm *f = &pcb->ipv6cp_fsm; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_IPV6CP; + f->callbacks = &ipv6cp_callbacks; + fsm_init(f); + +#if 0 /* Not necessary, everything is cleared in ppp_new() */ + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); +#endif /* 0 */ + + wo->accept_local = 1; + wo->neg_ifaceid = 1; + ao->neg_ifaceid = 1; + +#ifdef IPV6CP_COMP + wo->neg_vj = 1; + ao->neg_vj = 1; + wo->vj_protocol = IPV6CP_COMP; +#endif + +} + + +/* + * ipv6cp_open - IPV6CP is allowed to come up. + */ +static void ipv6cp_open(ppp_pcb *pcb) { + fsm_open(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_close - Take IPV6CP down. + */ +static void ipv6cp_close(ppp_pcb *pcb, const char *reason) { + fsm_close(&pcb->ipv6cp_fsm, reason); +} + + +/* + * ipv6cp_lowerup - The lower layer is up. + */ +static void ipv6cp_lowerup(ppp_pcb *pcb) { + fsm_lowerup(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_lowerdown - The lower layer is down. + */ +static void ipv6cp_lowerdown(ppp_pcb *pcb) { + fsm_lowerdown(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_input - Input IPV6CP packet. + */ +static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm_input(&pcb->ipv6cp_fsm, p, len); +} + + +/* + * ipv6cp_protrej - A Protocol-Reject was received for IPV6CP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void ipv6cp_protrej(ppp_pcb *pcb) { + fsm_lowerdown(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_resetci - Reset our CI. + */ +static void ipv6cp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + + wo->req_ifaceid = wo->neg_ifaceid && ao->neg_ifaceid; + + if (!wo->opt_local) { + eui64_magic_nz(wo->ourid); + } + + *go = *wo; + eui64_zero(go->hisid); /* last proposed interface identifier */ +} + + +/* + * ipv6cp_cilen - Return length of our CI. + */ +static int ipv6cp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + +#ifdef IPV6CP_COMP +#define LENCIVJ(neg) (neg ? CILEN_COMPRESS : 0) +#endif /* IPV6CP_COMP */ +#define LENCIIFACEID(neg) (neg ? CILEN_IFACEID : 0) + + return (LENCIIFACEID(go->neg_ifaceid) + +#ifdef IPV6CP_COMP + LENCIVJ(go->neg_vj) + +#endif /* IPV6CP_COMP */ + 0); +} + + +/* + * ipv6cp_addci - Add our desired CIs to a packet. + */ +static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + int len = *lenp; + +#ifdef IPV6CP_COMP +#define ADDCIVJ(opt, neg, val) \ + if (neg) { \ + int vjlen = CILEN_COMPRESS; \ + if (len >= vjlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(vjlen, ucp); \ + PUTSHORT(val, ucp); \ + len -= vjlen; \ + } else \ + neg = 0; \ + } +#endif /* IPV6CP_COMP */ + +#define ADDCIIFACEID(opt, neg, val1) \ + if (neg) { \ + int idlen = CILEN_IFACEID; \ + if (len >= idlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(idlen, ucp); \ + eui64_put(val1, ucp); \ + len -= idlen; \ + } else \ + neg = 0; \ + } + + ADDCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); + +#ifdef IPV6CP_COMP + ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); +#endif /* IPV6CP_COMP */ + + *lenp -= len; +} + + +/* + * ipv6cp_ackci - Ack our CIs. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int ipv6cp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_short cilen, citype; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + + /* + * CIs must be in exactly the same order that we sent... + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + +#ifdef IPV6CP_COMP +#define ACKCIVJ(opt, neg, val) \ + if (neg) { \ + int vjlen = CILEN_COMPRESS; \ + if ((len -= vjlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != vjlen || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } +#endif /* IPV6CP_COMP */ + +#define ACKCIIFACEID(opt, neg, val1) \ + if (neg) { \ + int idlen = CILEN_IFACEID; \ + if ((len -= idlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != idlen || \ + citype != opt) \ + goto bad; \ + eui64_get(ifaceid, p); \ + if (! eui64_equals(val1, ifaceid)) \ + goto bad; \ + } + + ACKCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); + +#ifdef IPV6CP_COMP + ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); +#endif /* IPV6CP_COMP */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); + +bad: + IPV6CPDEBUG(("ipv6cp_ackci: received bad Ack!")); + return (0); +} + +/* + * ipv6cp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPV6CP is in the OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char citype, cilen, *next; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + ipv6cp_options no; /* options we've seen Naks for */ + ipv6cp_options try_; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIIFACEID(opt, neg, code) \ + if (go->neg && \ + len >= (cilen = CILEN_IFACEID) && \ + p[1] == cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + eui64_get(ifaceid, p); \ + no.neg = 1; \ + code \ + } + +#ifdef IPV6CP_COMP +#define NAKCIVJ(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_COMPRESS) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#endif /* IPV6CP_COMP */ + + /* + * Accept the peer's idea of {our,his} interface identifier, if different + * from our idea, only if the accept_{local,remote} flag is set. + */ + NAKCIIFACEID(CI_IFACEID, neg_ifaceid, + if (treat_as_reject) { + try_.neg_ifaceid = 0; + } else if (go->accept_local) { + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->hisid)) /* bad luck */ + eui64_magic(ifaceid); + try_.ourid = ifaceid; + IPV6CPDEBUG(("local LL address %s", llv6_ntoa(ifaceid))); + } + ); + +#ifdef IPV6CP_COMP + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + { + if (cishort == IPV6CP_COMP && !treat_as_reject) { + try_.vj_protocol = cishort; + } else { + try_.neg_vj = 0; + } + } + ); +#endif /* IPV6CP_COMP */ + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If they want to negotiate about interface identifier, we comply. + * If they want us to ask for compression, we refuse. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) + goto bad; + next = p + cilen - 2; + + switch (citype) { +#ifdef IPV6CP_COMP + case CI_COMPRESSTYPE: + if (go->neg_vj || no.neg_vj || + (cilen != CILEN_COMPRESS)) + goto bad; + no.neg_vj = 1; + break; +#endif /* IPV6CP_COMP */ + case CI_IFACEID: + if (go->neg_ifaceid || no.neg_ifaceid || cilen != CILEN_IFACEID) + goto bad; + try_.neg_ifaceid = 1; + eui64_get(ifaceid, p); + if (go->accept_local) { + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->hisid)) /* bad luck */ + eui64_magic(ifaceid); + try_.ourid = ifaceid; + } + no.neg_ifaceid = 1; + break; + default: + break; + } + p = next; + } + + /* If there is still anything left, this packet is bad. */ + if (len != 0) + goto bad; + + /* + * OK, the Nak is good. Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + + return 1; + +bad: + IPV6CPDEBUG(("ipv6cp_nakci: received bad Nak!")); + return 0; +} + + +/* + * ipv6cp_rejci - Reject some of our CIs. + */ +static int ipv6cp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char cilen; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + ipv6cp_options try_; /* options to request next time */ + + try_ = *go; + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIIFACEID(opt, neg, val1) \ + if (go->neg && \ + len >= (cilen = CILEN_IFACEID) && \ + p[1] == cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + eui64_get(ifaceid, p); \ + /* Check rejected value. */ \ + if (! eui64_equals(ifaceid, val1)) \ + goto bad; \ + try_.neg = 0; \ + } + +#ifdef IPV6CP_COMP +#define REJCIVJ(opt, neg, val) \ + if (go->neg && \ + p[1] == CILEN_COMPRESS && \ + len >= p[1] && \ + p[0] == opt) { \ + len -= p[1]; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* IPV6CP_COMP */ + + REJCIIFACEID(CI_IFACEID, neg_ifaceid, go->ourid); + +#ifdef IPV6CP_COMP + REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol); +#endif /* IPV6CP_COMP */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + IPV6CPDEBUG(("ipv6cp_rejci: received bad Reject!")); + return 0; +} + + +/* + * ipv6cp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * len = Length of requested CIs + * + */ +static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ +#ifdef IPV6CP_COMP + u_short cishort; /* Parsed short value */ +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; /* Parsed interface identifier */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPV6CPDEBUG(("ipv6cp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_IFACEID: + IPV6CPDEBUG(("ipv6cp: received interface identifier ")); + + if (!ao->neg_ifaceid || + cilen != CILEN_IFACEID) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no interface identifier, or if we both have same + * identifier then NAK it with new idea. + * In particular, if we don't know his identifier, but he does, + * then accept it. + */ + eui64_get(ifaceid, p); + IPV6CPDEBUG(("(%s)", llv6_ntoa(ifaceid))); + if (eui64_iszero(ifaceid) && eui64_iszero(go->ourid)) { + orc = CONFREJ; /* Reject CI */ + break; + } + if (!eui64_iszero(wo->hisid) && + !eui64_equals(ifaceid, wo->hisid) && + eui64_iszero(go->hisid)) { + + orc = CONFNAK; + ifaceid = wo->hisid; + go->hisid = ifaceid; + DECPTR(sizeof(ifaceid), p); + eui64_put(ifaceid, p); + } else + if (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->ourid)) { + orc = CONFNAK; + if (eui64_iszero(go->hisid)) /* first time, try option */ + ifaceid = wo->hisid; + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->ourid)) /* bad luck */ + eui64_magic(ifaceid); + go->hisid = ifaceid; + DECPTR(sizeof(ifaceid), p); + eui64_put(ifaceid, p); + } + + ho->neg_ifaceid = 1; + ho->hisid = ifaceid; + break; + +#ifdef IPV6CP_COMP + case CI_COMPRESSTYPE: + IPV6CPDEBUG(("ipv6cp: received COMPRESSTYPE ")); + if (!ao->neg_vj || + (cilen != CILEN_COMPRESS)) { + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + IPV6CPDEBUG(("(%d)", cishort)); + + if (!(cishort == IPV6CP_COMP)) { + orc = CONFREJ; + break; + } + + ho->neg_vj = 1; + ho->vj_protocol = cishort; + break; +#endif /* IPV6CP_COMP */ + + default: + orc = CONFREJ; + break; + } + +endswitch: + IPV6CPDEBUG((" (%s)\n", CODENAME(orc))); + + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) /* Getting fed up with sending NAKs? */ + orc = CONFREJ; /* Get tough if so */ + else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) + MEMCPY(ucp, cip, cilen); /* Move it */ + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their identifier and they didn't send their identifier, then we + * send a NAK with a CI_IFACEID option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + if (rc != CONFREJ && !ho->neg_ifaceid && + wo->req_ifaceid && !reject_if_disagree) { + if (rc == CONFACK) { + rc = CONFNAK; + ucp = inp; /* reset pointer */ + wo->req_ifaceid = 0; /* don't ask again */ + } + PUTCHAR(CI_IFACEID, ucp); + PUTCHAR(CILEN_IFACEID, ucp); + eui64_put(wo->hisid, ucp); + } + + *len = ucp - inp; /* Compute output length */ + IPV6CPDEBUG(("ipv6cp: returning Configure-%s", CODENAME(rc))); + return (rc); /* Return final code */ +} + +#if PPP_OPTIONS +/* + * ipv6_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +static void ipv6_check_options() { + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + + if (!ipv6cp_protent.enabled_flag) + return; + + /* + * Persistent link-local id is only used when user has not explicitly + * configure/hard-code the id + */ + if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) { + + /* + * On systems where there are no Ethernet interfaces used, there + * may be other ways to obtain a persistent id. Right now, it + * will fall back to using magic [see eui64_magic] below when + * an EUI-48 from MAC address can't be obtained. Other possibilities + * include obtaining EEPROM serial numbers, or some other unique + * yet persistent number. On Sparc platforms, this is possible, + * but too bad there's no standards yet for x86 machines. + */ + if (ether_to_eui64(&wo->ourid)) { + wo->opt_local = 1; + } + } + + if (!wo->opt_local) { /* init interface identifier */ + if (wo->use_ip && eui64_iszero(wo->ourid)) { + eui64_setlo32(wo->ourid, lwip_ntohl(ipcp_wantoptions[0].ouraddr)); + if (!eui64_iszero(wo->ourid)) + wo->opt_local = 1; + } + + while (eui64_iszero(wo->ourid)) + eui64_magic(wo->ourid); + } + + if (!wo->opt_remote) { + if (wo->use_ip && eui64_iszero(wo->hisid)) { + eui64_setlo32(wo->hisid, lwip_ntohl(ipcp_wantoptions[0].hisaddr)); + if (!eui64_iszero(wo->hisid)) + wo->opt_remote = 1; + } + } + + if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) { + option_error("local/remote LL address required for demand-dialling\n"); + exit(1); + } +} +#endif /* PPP_OPTIONS */ + +#if DEMAND_SUPPORT +/* + * ipv6_demand_conf - configure the interface as though + * IPV6CP were up, for use with dial-on-demand. + */ +static int ipv6_demand_conf(int u) { + ipv6cp_options *wo = &ipv6cp_wantoptions[u]; + + if (!sif6up(u)) + return 0; + + if (!sif6addr(u, wo->ourid, wo->hisid)) + return 0; + + if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) + return 0; + + ppp_notice("ipv6_demand_conf"); + ppp_notice("local LL address %s", llv6_ntoa(wo->ourid)); + ppp_notice("remote LL address %s", llv6_ntoa(wo->hisid)); + + return 1; +} +#endif /* DEMAND_SUPPORT */ + + +/* + * ipv6cp_up - IPV6CP has come UP. + * + * Configure the IPv6 network interface appropriately and bring it up. + */ +static void ipv6cp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + + IPV6CPDEBUG(("ipv6cp: up")); + + /* + * We must have a non-zero LL address for both ends of the link. + */ + if (!ho->neg_ifaceid) + ho->hisid = wo->hisid; + +#if 0 /* UNUSED */ + if(!no_ifaceid_neg) { +#endif /* UNUSED */ + if (eui64_iszero(ho->hisid)) { + ppp_error("Could not determine remote LL address"); + ipv6cp_close(f->pcb, "Could not determine remote LL address"); + return; + } + if (eui64_iszero(go->ourid)) { + ppp_error("Could not determine local LL address"); + ipv6cp_close(f->pcb, "Could not determine local LL address"); + return; + } + if (eui64_equals(go->ourid, ho->hisid)) { + ppp_error("local and remote LL addresses are equal"); + ipv6cp_close(f->pcb, "local and remote LL addresses are equal"); + return; + } +#if 0 /* UNUSED */ + } +#endif /* UNUSED */ +#if 0 /* UNUSED */ + script_setenv("LLLOCAL", llv6_ntoa(go->ourid), 0); + script_setenv("LLREMOTE", llv6_ntoa(ho->hisid), 0); +#endif /* UNUSED */ + +#ifdef IPV6CP_COMP + /* set tcp compression */ + sif6comp(f->unit, ho->neg_vj); +#endif + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, the interface is already + * configured, so we put out any saved-up packets, then set the + * interface to pass IPv6 packets. + */ + if (demand) { + if (! eui64_equals(go->ourid, wo->ourid) || + ! eui64_equals(ho->hisid, wo->hisid)) { + if (! eui64_equals(go->ourid, wo->ourid)) + warn("Local LL address changed to %s", + llv6_ntoa(go->ourid)); + if (! eui64_equals(ho->hisid, wo->hisid)) + warn("Remote LL address changed to %s", + llv6_ntoa(ho->hisid)); + ipv6cp_clear_addrs(f->pcb, go->ourid, ho->hisid); + + /* Set the interface to the new addresses */ + if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { + if (debug) + warn("sif6addr failed"); + ipv6cp_close(f->unit, "Interface configuration failed"); + return; + } + + } + demand_rexmit(PPP_IPV6); + sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); + + } else +#endif /* DEMAND_SUPPORT */ + { + /* + * Set LL addresses + */ + if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { + PPPDEBUG(LOG_DEBUG, ("sif6addr failed")); + ipv6cp_close(f->pcb, "Interface configuration failed"); + return; + } + + /* bring the interface up for IPv6 */ + if (!sif6up(f->pcb)) { + PPPDEBUG(LOG_DEBUG, ("sif6up failed (IPV6)")); + ipv6cp_close(f->pcb, "Interface configuration failed"); + return; + } +#if DEMAND_SUPPORT + sifnpmode(f->pcb, PPP_IPV6, NPMODE_PASS); +#endif /* DEMAND_SUPPORT */ + + ppp_notice("local LL address %s", llv6_ntoa(go->ourid)); + ppp_notice("remote LL address %s", llv6_ntoa(ho->hisid)); + } + + np_up(f->pcb, PPP_IPV6); + pcb->ipv6cp_is_up = 1; + +#if 0 /* UNUSED */ + /* + * Execute the ipv6-up script, like this: + * /etc/ppp/ipv6-up interface tty speed local-LL remote-LL + */ + if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) { + ipv6cp_script_state = s_up; + ipv6cp_script(_PATH_IPV6UP); + } +#endif /* UNUSED */ +} + + +/* + * ipv6cp_down - IPV6CP has gone DOWN. + * + * Take the IPv6 network interface down, clear its addresses + * and delete routes through it. + */ +static void ipv6cp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + + IPV6CPDEBUG(("ipv6cp: down")); +#if PPP_STATS_SUPPORT + update_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ + if (pcb->ipv6cp_is_up) { + pcb->ipv6cp_is_up = 0; + np_down(f->pcb, PPP_IPV6); + } +#ifdef IPV6CP_COMP + sif6comp(f->unit, 0); +#endif + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, set the interface + * to queue up outgoing packets (for now). + */ + if (demand) { + sifnpmode(f->pcb, PPP_IPV6, NPMODE_QUEUE); + } else +#endif /* DEMAND_SUPPORT */ + { +#if DEMAND_SUPPORT + sifnpmode(f->pcb, PPP_IPV6, NPMODE_DROP); +#endif /* DEMAND_SUPPORT */ + ipv6cp_clear_addrs(f->pcb, + go->ourid, + ho->hisid); + sif6down(f->pcb); + } + +#if 0 /* UNUSED */ + /* Execute the ipv6-down script */ + if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) { + ipv6cp_script_state = s_down; + ipv6cp_script(_PATH_IPV6DOWN); + } +#endif /* UNUSED */ +} + + +/* + * ipv6cp_clear_addrs() - clear the interface addresses, routes, + * proxy neighbour discovery entries, etc. + */ +static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid) { + cif6addr(pcb, ourid, hisid); +} + + +/* + * ipv6cp_finished - possibly shut down the lower layers. + */ +static void ipv6cp_finished(fsm *f) { + np_finished(f->pcb, PPP_IPV6); +} + + +#if 0 /* UNUSED */ +/* + * ipv6cp_script_done - called when the ipv6-up or ipv6-down script + * has finished. + */ +static void +ipv6cp_script_done(arg) + void *arg; +{ + ipv6cp_script_pid = 0; + switch (ipv6cp_script_state) { + case s_up: + if (ipv6cp_fsm[0].state != PPP_FSM_OPENED) { + ipv6cp_script_state = s_down; + ipv6cp_script(_PATH_IPV6DOWN); + } + break; + case s_down: + if (ipv6cp_fsm[0].state == PPP_FSM_OPENED) { + ipv6cp_script_state = s_up; + ipv6cp_script(_PATH_IPV6UP); + } + break; + } +} + + +/* + * ipv6cp_script - Execute a script with arguments + * interface-name tty-name speed local-LL remote-LL. + */ +static void +ipv6cp_script(script) + char *script; +{ + char strspeed[32], strlocal[32], strremote[32]; + char *argv[8]; + + sprintf(strspeed, "%d", baud_rate); + strcpy(strlocal, llv6_ntoa(ipv6cp_gotoptions[0].ourid)); + strcpy(strremote, llv6_ntoa(ipv6cp_hisoptions[0].hisid)); + + argv[0] = script; + argv[1] = ifname; + argv[2] = devnam; + argv[3] = strspeed; + argv[4] = strlocal; + argv[5] = strremote; + argv[6] = ipparam; + argv[7] = NULL; + + ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done, + NULL, 0); +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ipv6cp_printpkt - print the contents of an IPV6CP packet. + */ +static const char* const ipv6cp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej" +}; + +static int ipv6cp_printpkt(const u_char *p, int plen, + void (*printer)(void *, const char *, ...), void *arg) { + int code, id, len, olen; + const u_char *pstart, *optend; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ipv6cp_codenames)) + printer(arg, " %s", ipv6cp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { +#ifdef IPV6CP_COMP + case CI_COMPRESSTYPE: + if (olen >= CILEN_COMPRESS) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "compress "); + printer(arg, "0x%x", cishort); + } + break; +#endif /* IPV6CP_COMP */ + case CI_IFACEID: + if (olen == CILEN_IFACEID) { + p += 2; + eui64_get(ifaceid, p); + printer(arg, "addr %s", llv6_ntoa(ifaceid)); + } + break; + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#if DEMAND_SUPPORT +/* + * ipv6_active_pkt - see if this IP packet is worth bringing the link up for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#define IP6_HDRLEN 40 /* bytes */ +#define IP6_NHDR_FRAG 44 /* fragment IPv6 header */ +#define TCP_HDRLEN 20 +#define TH_FIN 0x01 + +/* + * We use these macros because the IP header may be at an odd address, + * and some compilers might use word loads to get th_off or ip_hl. + */ + +#define get_ip6nh(x) (((unsigned char *)(x))[6]) +#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) +#define get_tcpflags(x) (((unsigned char *)(x))[13]) + +static int ipv6_active_pkt(u_char *pkt, int len) { + u_char *tcp; + + len -= PPP_HDRLEN; + pkt += PPP_HDRLEN; + if (len < IP6_HDRLEN) + return 0; + if (get_ip6nh(pkt) == IP6_NHDR_FRAG) + return 0; + if (get_ip6nh(pkt) != IPPROTO_TCP) + return 1; + if (len < IP6_HDRLEN + TCP_HDRLEN) + return 0; + tcp = pkt + IP6_HDRLEN; + if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == IP6_HDRLEN + get_tcpoff(tcp) * 4) + return 0; + return 1; +} +#endif /* DEMAND_SUPPORT */ + +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/lcp.c b/components/net/lwip-2.0.3/src/netif/ppp/lcp.c new file mode 100644 index 0000000000..90ed183b75 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/lcp.c @@ -0,0 +1,2790 @@ +/* + * lcp.c - PPP Link Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * @todo: + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#include "netif/ppp/magic.h" + +/* + * When the link comes up we want to be able to wait for a short while, + * or until seeing some input from the peer, before starting to send + * configure-requests. We do this by delaying the fsm_lowerup call. + */ +/* steal a bit in fsm flags word */ +#define DELAYED_UP 0x80 + +static void lcp_delayed_up(void *arg); + +/* + * LCP-related command-line options. + */ +#if 0 /* UNUSED */ +int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ +int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* options */ +static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ +static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +#if PPP_LCP_ADAPTIVE +bool lcp_echo_adaptive = 0; /* request echo only if the link was idle */ +#endif +bool lax_recv = 0; /* accept control chars in asyncmap */ +bool noendpoint = 0; /* don't send/accept endpoint discriminator */ +#endif /* UNUSED */ + +#if PPP_OPTIONS +static int noopt (char **); +#endif /* PPP_OPTIONS */ + +#ifdef HAVE_MULTILINK +static int setendpoint (char **); +static void printendpoint (option_t *, void (*)(void *, char *, ...), + void *); +#endif /* HAVE_MULTILINK */ + +#if PPP_OPTIONS +static option_t lcp_option_list[] = { + /* LCP options */ + { "-all", o_special_noarg, (void *)noopt, + "Don't request/allow any LCP options" }, + + { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression, + "Disable address/control compression", + OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, + { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression, + "Disable address/control compression", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, + + { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, + "Set asyncmap (for received packets)", + OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + { "-as", o_uint32, &lcp_wantoptions[0].asyncmap, + "Set asyncmap (for received packets)", + OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + { "default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, + "Disable asyncmap negotiation", + OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, + &lcp_allowoptions[0].neg_asyncmap }, + { "-am", o_uint32, &lcp_wantoptions[0].asyncmap, + "Disable asyncmap negotiation", + OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, + &lcp_allowoptions[0].neg_asyncmap }, + + { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber, + "Disable magic number negotiation (looped-back line detection)", + OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, + { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber, + "Disable magic number negotiation (looped-back line detection)", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, + + { "mru", o_int, &lcp_wantoptions[0].mru, + "Set MRU (maximum received packet size) for negotiation", + OPT_PRIO, &lcp_wantoptions[0].neg_mru }, + { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru, + "Disable MRU negotiation (use default 1500)", + OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, + { "-mru", o_bool, &lcp_wantoptions[0].neg_mru, + "Disable MRU negotiation (use default 1500)", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, + + { "mtu", o_int, &lcp_allowoptions[0].mru, + "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU }, + + { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression, + "Disable protocol field compression", + OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, + { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression, + "Disable protocol field compression", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, + + { "passive", o_bool, &lcp_wantoptions[0].passive, + "Set passive mode", 1 }, + { "-p", o_bool, &lcp_wantoptions[0].passive, + "Set passive mode", OPT_ALIAS | 1 }, + + { "silent", o_bool, &lcp_wantoptions[0].silent, + "Set silent mode", 1 }, + + { "lcp-echo-failure", o_int, &lcp_echo_fails, + "Set number of consecutive echo failures to indicate link failure", + OPT_PRIO }, + { "lcp-echo-interval", o_int, &lcp_echo_interval, + "Set time in seconds between LCP echo requests", OPT_PRIO }, +#if PPP_LCP_ADAPTIVE + { "lcp-echo-adaptive", o_bool, &lcp_echo_adaptive, + "Suppress LCP echo requests if traffic was received", 1 }, +#endif + { "lcp-restart", o_int, &lcp_fsm[0].timeouttime, + "Set time in seconds between LCP retransmissions", OPT_PRIO }, + { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits, + "Set maximum number of LCP terminate-request transmissions", OPT_PRIO }, + { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits, + "Set maximum number of LCP configure-request transmissions", OPT_PRIO }, + { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops, + "Set limit on number of LCP configure-naks", OPT_PRIO }, + + { "receive-all", o_bool, &lax_recv, + "Accept all received control characters", 1 }, + +#ifdef HAVE_MULTILINK + { "mrru", o_int, &lcp_wantoptions[0].mrru, + "Maximum received packet size for multilink bundle", + OPT_PRIO, &lcp_wantoptions[0].neg_mrru }, + + { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, + "Use short sequence numbers in multilink headers", + OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf }, + { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, + "Don't use short sequence numbers in multilink headers", + OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf }, + + { "endpoint", o_special, (void *) setendpoint, + "Endpoint discriminator for multilink", + OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint }, +#endif /* HAVE_MULTILINK */ + + { "noendpoint", o_bool, &noendpoint, + "Don't send or accept multilink endpoint discriminator", 1 }, + + {NULL} +}; +#endif /* PPP_OPTIONS */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void lcp_resetci(fsm *f); /* Reset our CI */ +static int lcp_cilen(fsm *f); /* Return length of our CI */ +static void lcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI to pkt */ +static int lcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ +static int lcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree); /* Rcv peer CI */ +static void lcp_up(fsm *f); /* We're UP */ +static void lcp_down(fsm *f); /* We're DOWN */ +static void lcp_starting (fsm *); /* We need lower layer up */ +static void lcp_finished (fsm *); /* We need lower layer down */ +static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len); +static void lcp_rprotrej(fsm *f, u_char *inp, int len); + +/* + * routines to send LCP echos to peer + */ + +static void lcp_echo_lowerup(ppp_pcb *pcb); +static void lcp_echo_lowerdown(ppp_pcb *pcb); +static void LcpEchoTimeout(void *arg); +static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len); +static void LcpSendEchoRequest(fsm *f); +static void LcpLinkFailure(fsm *f); +static void LcpEchoCheck(fsm *f); + +static const fsm_callbacks lcp_callbacks = { /* LCP callback routines */ + lcp_resetci, /* Reset our Configuration Information */ + lcp_cilen, /* Length of our Configuration Information */ + lcp_addci, /* Add our Configuration Information */ + lcp_ackci, /* ACK our Configuration Information */ + lcp_nakci, /* NAK our Configuration Information */ + lcp_rejci, /* Reject our Configuration Information */ + lcp_reqci, /* Request peer's Configuration Information */ + lcp_up, /* Called when fsm reaches OPENED state */ + lcp_down, /* Called when fsm leaves OPENED state */ + lcp_starting, /* Called when we want the lower layer up */ + lcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + lcp_extcode, /* Called to handle LCP-specific codes */ + "LCP" /* String name of protocol */ +}; + +/* + * Protocol entry points. + * Some of these are called directly. + */ + +static void lcp_init(ppp_pcb *pcb); +static void lcp_input(ppp_pcb *pcb, u_char *p, int len); +static void lcp_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int lcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent lcp_protent = { + PPP_LCP, + lcp_init, + lcp_input, + lcp_protrej, + lcp_lowerup, + lcp_lowerdown, + lcp_open, + lcp_close, +#if PRINTPKT_SUPPORT + lcp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "LCP", + NULL, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + lcp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +/* + * Length of each type of configuration option (in octets) + */ +#define CILEN_VOID 2 +#define CILEN_CHAR 3 +#define CILEN_SHORT 4 /* CILEN_VOID + 2 */ +#if CHAP_SUPPORT +#define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */ +#endif /* CHAP_SUPPORT */ +#define CILEN_LONG 6 /* CILEN_VOID + 4 */ +#if LQR_SUPPORT +#define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */ +#endif /* LQR_SUPPORT */ +#define CILEN_CBCP 3 + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if PPP_OPTIONS +/* + * noopt - Disable all options (why?). + */ +static int +noopt(argv) + char **argv; +{ + BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options)); + BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options)); + + return (1); +} +#endif /* PPP_OPTIONS */ + +#ifdef HAVE_MULTILINK +static int +setendpoint(argv) + char **argv; +{ + if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) { + lcp_wantoptions[0].neg_endpoint = 1; + return 1; + } + option_error("Can't parse '%s' as an endpoint discriminator", *argv); + return 0; +} + +static void +printendpoint(opt, printer, arg) + option_t *opt; + void (*printer) (void *, char *, ...); + void *arg; +{ + printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint)); +} +#endif /* HAVE_MULTILINK */ + +/* + * lcp_init - Initialize LCP. + */ +static void lcp_init(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_LCP; + f->callbacks = &lcp_callbacks; + + fsm_init(f); + + BZERO(wo, sizeof(*wo)); + wo->neg_mru = 1; + wo->mru = PPP_DEFMRU; + wo->neg_asyncmap = 1; + wo->neg_magicnumber = 1; + wo->neg_pcompression = 1; + wo->neg_accompression = 1; + + BZERO(ao, sizeof(*ao)); + ao->neg_mru = 1; + ao->mru = PPP_MAXMRU; + ao->neg_asyncmap = 1; +#if CHAP_SUPPORT + ao->neg_chap = 1; + ao->chap_mdtype = CHAP_MDTYPE_SUPPORTED; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + ao->neg_upap = 1; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + ao->neg_eap = 1; +#endif /* EAP_SUPPORT */ + ao->neg_magicnumber = 1; + ao->neg_pcompression = 1; + ao->neg_accompression = 1; + ao->neg_endpoint = 1; +} + + +/* + * lcp_open - LCP is allowed to come up. + */ +void lcp_open(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + lcp_options *wo = &pcb->lcp_wantoptions; + + f->flags &= ~(OPT_PASSIVE | OPT_SILENT); + if (wo->passive) + f->flags |= OPT_PASSIVE; + if (wo->silent) + f->flags |= OPT_SILENT; + fsm_open(f); +} + + +/* + * lcp_close - Take LCP down. + */ +void lcp_close(ppp_pcb *pcb, const char *reason) { + fsm *f = &pcb->lcp_fsm; + int oldstate; + + if (pcb->phase != PPP_PHASE_DEAD +#ifdef HAVE_MULTILINK + && pcb->phase != PPP_PHASE_MASTER +#endif /* HAVE_MULTILINK */ + ) + new_phase(pcb, PPP_PHASE_TERMINATE); + + if (f->flags & DELAYED_UP) { + UNTIMEOUT(lcp_delayed_up, f); + f->state = PPP_FSM_STOPPED; + } + oldstate = f->state; + + fsm_close(f, reason); + if (oldstate == PPP_FSM_STOPPED && (f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP))) { + /* + * This action is not strictly according to the FSM in RFC1548, + * but it does mean that the program terminates if you do a + * lcp_close() when a connection hasn't been established + * because we are in passive/silent mode or because we have + * delayed the fsm_lowerup() call and it hasn't happened yet. + */ + f->flags &= ~DELAYED_UP; + lcp_finished(f); + } +} + + +/* + * lcp_lowerup - The lower layer is up. + */ +void lcp_lowerup(ppp_pcb *pcb) { + lcp_options *wo = &pcb->lcp_wantoptions; + fsm *f = &pcb->lcp_fsm; + /* + * Don't use A/C or protocol compression on transmission, + * but accept A/C and protocol compressed packets + * if we are going to ask for A/C and protocol compression. + */ + if (ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0) < 0 + || ppp_recv_config(pcb, PPP_MRU, (pcb->settings.lax_recv? 0: 0xffffffff), + wo->neg_pcompression, wo->neg_accompression) < 0) + return; + pcb->peer_mru = PPP_MRU; + + if (pcb->settings.listen_time != 0) { + f->flags |= DELAYED_UP; + TIMEOUTMS(lcp_delayed_up, f, pcb->settings.listen_time); + } else + fsm_lowerup(f); +} + + +/* + * lcp_lowerdown - The lower layer is down. + */ +void lcp_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + UNTIMEOUT(lcp_delayed_up, f); + } else + fsm_lowerdown(f); +} + + +/* + * lcp_delayed_up - Bring the lower layer up now. + */ +static void lcp_delayed_up(void *arg) { + fsm *f = (fsm*)arg; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + fsm_lowerup(f); + } +} + + +/* + * lcp_input - Input LCP packet. + */ +static void lcp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->lcp_fsm; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + UNTIMEOUT(lcp_delayed_up, f); + fsm_lowerup(f); + } + fsm_input(f, p, len); +} + +/* + * lcp_extcode - Handle a LCP-specific code. + */ +static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char *magp; + + switch( code ){ + case PROTREJ: + lcp_rprotrej(f, inp, len); + break; + + case ECHOREQ: + if (f->state != PPP_FSM_OPENED) + break; + magp = inp; + PUTLONG(go->magicnumber, magp); + fsm_sdata(f, ECHOREP, id, inp, len); + break; + + case ECHOREP: + lcp_received_echo_reply(f, id, inp, len); + break; + + case DISCREQ: + case IDENTIF: + case TIMEREM: + break; + + default: + return 0; + } + return 1; +} + + +/* + * lcp_rprotrej - Receive an Protocol-Reject. + * + * Figure out which protocol is rejected and inform it. + */ +static void lcp_rprotrej(fsm *f, u_char *inp, int len) { + int i; + const struct protent *protp; + u_short prot; +#if PPP_PROTOCOLNAME + const char *pname; +#endif /* PPP_PROTOCOLNAME */ + + if (len < 2) { + LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!")); + return; + } + + GETSHORT(prot, inp); + + /* + * Protocol-Reject packets received in any state other than the LCP + * OPENED state SHOULD be silently discarded. + */ + if( f->state != PPP_FSM_OPENED ){ + LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state)); + return; + } + +#if PPP_PROTOCOLNAME + pname = protocol_name(prot); +#endif /* PPP_PROTOCOLNAME */ + + /* + * Upcall the proper Protocol-Reject routine. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol == prot) { +#if PPP_PROTOCOLNAME + if (pname != NULL) + ppp_dbglog("Protocol-Reject for '%s' (0x%x) received", pname, + prot); + else +#endif /* PPP_PROTOCOLNAME */ + ppp_dbglog("Protocol-Reject for 0x%x received", prot); + (*protp->protrej)(f->pcb); + return; + } + +#if PPP_PROTOCOLNAME + if (pname != NULL) + ppp_warn("Protocol-Reject for unsupported protocol '%s' (0x%x)", pname, + prot); + else +#endif /* #if PPP_PROTOCOLNAME */ + ppp_warn("Protocol-Reject for unsupported protocol 0x%x", prot); +} + + +/* + * lcp_protrej - A Protocol-Reject was received. + */ +/*ARGSUSED*/ +static void lcp_protrej(ppp_pcb *pcb) { + /* + * Can't reject LCP! + */ + ppp_error("Received Protocol-Reject for LCP!"); + fsm_protreject(&pcb->lcp_fsm); +} + + +/* + * lcp_sprotrej - Send a Protocol-Reject for some protocol. + */ +void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->lcp_fsm; + /* + * Send back the protocol and the information field of the + * rejected packet. We only get here if LCP is in the OPENED state. + */ +#if 0 + p += 2; + len -= 2; +#endif + + fsm_sdata(f, PROTREJ, ++f->id, + p, len); +} + + +/* + * lcp_resetci - Reset our CI. + */ +static void lcp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + +#if PPP_AUTH_SUPPORT + + /* note: default value is true for allow options */ + if (pcb->settings.user && pcb->settings.passwd) { +#if PAP_SUPPORT + if (pcb->settings.refuse_pap) { + ao->neg_upap = 0; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (pcb->settings.refuse_chap) { + ao->chap_mdtype &= ~MDTYPE_MD5; + } +#if MSCHAP_SUPPORT + if (pcb->settings.refuse_mschap) { + ao->chap_mdtype &= ~MDTYPE_MICROSOFT; + } + if (pcb->settings.refuse_mschap_v2) { + ao->chap_mdtype &= ~MDTYPE_MICROSOFT_V2; + } +#endif /* MSCHAP_SUPPORT */ + ao->neg_chap = (ao->chap_mdtype != MDTYPE_NONE); +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + if (pcb->settings.refuse_eap) { + ao->neg_eap = 0; + } +#endif /* EAP_SUPPORT */ + +#if PPP_SERVER + /* note: default value is false for wanted options */ + if (pcb->settings.auth_required) { +#if PAP_SUPPORT + if (!pcb->settings.refuse_pap) { + wo->neg_upap = 1; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (!pcb->settings.refuse_chap) { + wo->chap_mdtype |= MDTYPE_MD5; + } +#if MSCHAP_SUPPORT + if (!pcb->settings.refuse_mschap) { + wo->chap_mdtype |= MDTYPE_MICROSOFT; + } + if (!pcb->settings.refuse_mschap_v2) { + wo->chap_mdtype |= MDTYPE_MICROSOFT_V2; + } +#endif /* MSCHAP_SUPPORT */ + wo->neg_chap = (wo->chap_mdtype != MDTYPE_NONE); +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + if (!pcb->settings.refuse_eap) { + wo->neg_eap = 1; + } +#endif /* EAP_SUPPORT */ + } +#endif /* PPP_SERVER */ + + } else { +#if PAP_SUPPORT + ao->neg_upap = 0; +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + ao->neg_chap = 0; + ao->chap_mdtype = MDTYPE_NONE; +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + ao->neg_eap = 0; +#endif /* EAP_SUPPORT */ + } + + PPPDEBUG(LOG_DEBUG, ("ppp: auth protocols:")); +#if PAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" PAP=%d", ao->neg_upap)); +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" CHAP=%d CHAP_MD5=%d", ao->neg_chap, !!(ao->chap_mdtype&MDTYPE_MD5))); +#if MSCHAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" CHAP_MS=%d CHAP_MS2=%d", !!(ao->chap_mdtype&MDTYPE_MICROSOFT), !!(ao->chap_mdtype&MDTYPE_MICROSOFT_V2))); +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" EAP=%d", ao->neg_eap)); +#endif /* EAP_SUPPORT */ + PPPDEBUG(LOG_DEBUG, ("\n")); + +#endif /* PPP_AUTH_SUPPORT */ + + wo->magicnumber = magic(); + wo->numloops = 0; + *go = *wo; +#ifdef HAVE_MULTILINK + if (!multilink) { + go->neg_mrru = 0; +#endif /* HAVE_MULTILINK */ + go->neg_ssnhf = 0; + go->neg_endpoint = 0; +#ifdef HAVE_MULTILINK + } +#endif /* HAVE_MULTILINK */ + if (pcb->settings.noendpoint) + ao->neg_endpoint = 0; + pcb->peer_mru = PPP_MRU; +#if 0 /* UNUSED */ + auth_reset(pcb); +#endif /* UNUSED */ +} + + +/* + * lcp_cilen - Return length of our CI. + */ +static int lcp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + +#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) +#if CHAP_SUPPORT +#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) +#endif /* CHAP_SUPPORT */ +#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) +#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) +#if LQR_SUPPORT +#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) +#endif /* LQR_SUPPORT */ +#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) + /* + * NB: we only ask for one of CHAP, UPAP, or EAP, even if we will + * accept more than one. We prefer EAP first, then CHAP, then + * PAP. + */ + return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) + + LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + +#if EAP_SUPPORT + LENCISHORT(go->neg_eap) + +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + LENCICHAP(!go->neg_eap && go->neg_chap) + +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + LENCICHAP(go->neg_chap) + +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) + +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + LENCISHORT(!go->neg_eap && go->neg_upap) + +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + LENCISHORT(!go->neg_chap && go->neg_upap) + +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + LENCISHORT(go->neg_upap) + +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + LENCILQR(go->neg_lqr) + +#endif /* LQR_SUPPORT */ + LENCICBCP(go->neg_cbcp) + + LENCILONG(go->neg_magicnumber) + + LENCIVOID(go->neg_pcompression) + + LENCIVOID(go->neg_accompression) + +#ifdef HAVE_MULTILINK + LENCISHORT(go->neg_mrru) + +#endif /* HAVE_MULTILINK */ + LENCIVOID(go->neg_ssnhf) + + (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0)); +} + + +/* + * lcp_addci - Add our desired CIs to a packet. + */ +static void lcp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char *start_ucp = ucp; + +#define ADDCIVOID(opt, neg) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_VOID, ucp); \ + } +#define ADDCISHORT(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_SHORT, ucp); \ + PUTSHORT(val, ucp); \ + } +#if CHAP_SUPPORT +#define ADDCICHAP(opt, neg, val) \ + if (neg) { \ + PUTCHAR((opt), ucp); \ + PUTCHAR(CILEN_CHAP, ucp); \ + PUTSHORT(PPP_CHAP, ucp); \ + PUTCHAR((CHAP_DIGEST(val)), ucp); \ + } +#endif /* CHAP_SUPPORT */ +#define ADDCILONG(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LONG, ucp); \ + PUTLONG(val, ucp); \ + } +#if LQR_SUPPORT +#define ADDCILQR(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LQR, ucp); \ + PUTSHORT(PPP_LQR, ucp); \ + PUTLONG(val, ucp); \ + } +#endif /* LQR_SUPPORT */ +#define ADDCICHAR(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAR, ucp); \ + PUTCHAR(val, ucp); \ + } +#define ADDCIENDP(opt, neg, class, val, len) \ + if (neg) { \ + int i; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAR + len, ucp); \ + PUTCHAR(class, ucp); \ + for (i = 0; i < len; ++i) \ + PUTCHAR(val[i], ucp); \ + } + + ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, + go->asyncmap); +#if EAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + ADDCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); +#ifdef HAVE_MULTILINK + ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru); +#endif + ADDCIVOID(CI_SSNHF, go->neg_ssnhf); + ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + if (ucp - start_ucp != *lenp) { + /* this should never happen, because peer_mtu should be 1500 */ + ppp_error("Bug in lcp_addci: wrong length"); + } +} + + +/* + * lcp_ackci - Ack our CIs. + * This should not modify any state if the Ack is bad. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int lcp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char cilen, citype, cichar; + u_short cishort; + u32_t cilong; + + /* + * CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define ACKCIVOID(opt, neg) \ + if (neg) { \ + if ((len -= CILEN_VOID) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_VOID || \ + citype != opt) \ + goto bad; \ + } +#define ACKCISHORT(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_SHORT) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_SHORT || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } +#define ACKCICHAR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_CHAR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAR || \ + citype != opt) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != val) \ + goto bad; \ + } +#if CHAP_SUPPORT +#define ACKCICHAP(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_CHAP) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAP || \ + citype != (opt)) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != PPP_CHAP) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != (CHAP_DIGEST(val))) \ + goto bad; \ + } +#endif /* CHAP_SUPPORT */ +#define ACKCILONG(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LONG) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LONG || \ + citype != opt) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } +#if LQR_SUPPORT +#define ACKCILQR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LQR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LQR || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != PPP_LQR) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } +#endif /* LQR_SUPPORT */ +#define ACKCIENDP(opt, neg, class, val, vlen) \ + if (neg) { \ + int i; \ + if ((len -= CILEN_CHAR + vlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAR + vlen || \ + citype != opt) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != class) \ + goto bad; \ + for (i = 0; i < vlen; ++i) { \ + GETCHAR(cichar, p); \ + if (cichar != val[i]) \ + goto bad; \ + } \ + } + + ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, + go->asyncmap); +#if EAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + ACKCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); +#ifdef HAVE_MULTILINK + ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru); +#endif /* HAVE_MULTILINK */ + ACKCIVOID(CI_SSNHF, go->neg_ssnhf); + ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); +bad: + LCPDEBUG(("lcp_acki: received bad Ack!")); + return (0); +} + + +/* + * lcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if LCP is in the OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *wo = &pcb->lcp_wantoptions; + u_char citype, cichar, *next; + u_short cishort; + u32_t cilong; + lcp_options no; /* options we've seen Naks for */ + lcp_options try_; /* options to request next time */ + int looped_back = 0; + int cilen; + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIVOID(opt, neg) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + no.neg = 1; \ + try_.neg = 0; \ + } +#if CHAP_SUPPORT +#define NAKCICHAP(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#endif /* CHAP_SUPPORT */ +#define NAKCICHAR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAR && \ + p[1] == CILEN_CHAR && \ + p[0] == opt) { \ + len -= CILEN_CHAR; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#define NAKCISHORT(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#define NAKCILONG(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } +#if LQR_SUPPORT +#define NAKCILQR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } +#endif /* LQR_SUPPORT */ +#define NAKCIENDP(opt, neg) \ + if (go->neg && \ + len >= CILEN_CHAR && \ + p[0] == opt && \ + p[1] >= CILEN_CHAR && \ + p[1] <= len) { \ + len -= p[1]; \ + INCPTR(p[1], p); \ + no.neg = 1; \ + try_.neg = 0; \ + } + + /* + * NOTE! There must be no assignments to individual fields of *go in + * the code below. Any such assignment is a BUG! + */ + /* + * We don't care if they want to send us smaller packets than + * we want. Therefore, accept any MRU less than what we asked for, + * but then ignore the new value when setting the MRU in the kernel. + * If they send us a bigger MRU than what we asked, accept it, up to + * the limit of the default MRU we'd get if we didn't negotiate. + */ + if (go->neg_mru && go->mru != PPP_DEFMRU) { + NAKCISHORT(CI_MRU, neg_mru, + if (cishort <= wo->mru || cishort <= PPP_DEFMRU) + try_.mru = cishort; + ); + } + + /* + * Add any characters they want to our (receive-side) asyncmap. + */ + if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) { + NAKCILONG(CI_ASYNCMAP, neg_asyncmap, + try_.asyncmap = go->asyncmap | cilong; + ); + } + + /* + * If they've nak'd our authentication-protocol, check whether + * they are proposing a different protocol, or a different + * hash algorithm for CHAP. + */ + if ((0 +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + ) + && len >= CILEN_SHORT + && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { + cilen = p[1]; + len -= cilen; +#if CHAP_SUPPORT + no.neg_chap = go->neg_chap; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + no.neg_upap = go->neg_upap; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + no.neg_eap = go->neg_eap; +#endif /* EAP_SUPPORT */ + INCPTR(2, p); + GETSHORT(cishort, p); + +#if PAP_SUPPORT + if (cishort == PPP_PAP && cilen == CILEN_SHORT) { +#if EAP_SUPPORT + /* If we were asking for EAP, then we need to stop that. */ + if (go->neg_eap) + try_.neg_eap = 0; + else +#endif /* EAP_SUPPORT */ + +#if CHAP_SUPPORT + /* If we were asking for CHAP, then we need to stop that. */ + if (go->neg_chap) + try_.neg_chap = 0; + else +#endif /* CHAP_SUPPORT */ + + /* + * If we weren't asking for CHAP or EAP, then we were asking for + * PAP, in which case this Nak is bad. + */ + goto bad; + } else +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { + GETCHAR(cichar, p); +#if EAP_SUPPORT + /* Stop asking for EAP, if we were. */ + if (go->neg_eap) { + try_.neg_eap = 0; + /* Try to set up to use their suggestion, if possible */ + if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) + try_.chap_mdtype = CHAP_MDTYPE_D(cichar); + } else +#endif /* EAP_SUPPORT */ + if (go->neg_chap) { + /* + * We were asking for our preferred algorithm, they must + * want something different. + */ + if (cichar != CHAP_DIGEST(go->chap_mdtype)) { + if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) { + /* Use their suggestion if we support it ... */ + try_.chap_mdtype = CHAP_MDTYPE_D(cichar); + } else { + /* ... otherwise, try our next-preferred algorithm. */ + try_.chap_mdtype &= ~(CHAP_MDTYPE(try_.chap_mdtype)); + if (try_.chap_mdtype == MDTYPE_NONE) /* out of algos */ + try_.neg_chap = 0; + } + } else { + /* + * Whoops, they Nak'd our algorithm of choice + * but then suggested it back to us. + */ + goto bad; + } + } else { + /* + * Stop asking for PAP if we were asking for it. + */ +#if PAP_SUPPORT + try_.neg_upap = 0; +#endif /* PAP_SUPPORT */ + } + + } else +#endif /* CHAP_SUPPORT */ + { + +#if EAP_SUPPORT + /* + * If we were asking for EAP, and they're Conf-Naking EAP, + * well, that's just strange. Nobody should do that. + */ + if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap) + ppp_dbglog("Unexpected Conf-Nak for EAP"); + + /* + * We don't recognize what they're suggesting. + * Stop asking for what we were asking for. + */ + if (go->neg_eap) + try_.neg_eap = 0; + else +#endif /* EAP_SUPPORT */ + +#if CHAP_SUPPORT + if (go->neg_chap) + try_.neg_chap = 0; + else +#endif /* CHAP_SUPPORT */ + +#if PAP_SUPPORT + if(1) + try_.neg_upap = 0; + else +#endif /* PAP_SUPPORT */ + {} + + p += cilen - CILEN_SHORT; + } + } + +#if LQR_SUPPORT + /* + * If they can't cope with our link quality protocol, we'll have + * to stop asking for LQR. We haven't got any other protocol. + * If they Nak the reporting period, take their value XXX ? + */ + NAKCILQR(CI_QUALITY, neg_lqr, + if (cishort != PPP_LQR) + try_.neg_lqr = 0; + else + try_.lqr_period = cilong; + ); +#endif /* LQR_SUPPORT */ + + /* + * Only implementing CBCP...not the rest of the callback options + */ + NAKCICHAR(CI_CALLBACK, neg_cbcp, + try_.neg_cbcp = 0; + (void)cichar; /* if CHAP support is not compiled, cichar is set but not used, which makes some compilers complaining */ + ); + + /* + * Check for a looped-back line. + */ + NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, + try_.magicnumber = magic(); + looped_back = 1; + ); + + /* + * Peer shouldn't send Nak for protocol compression or + * address/control compression requests; they should send + * a Reject instead. If they send a Nak, treat it as a Reject. + */ + NAKCIVOID(CI_PCOMPRESSION, neg_pcompression); + NAKCIVOID(CI_ACCOMPRESSION, neg_accompression); + +#ifdef HAVE_MULTILINK + /* + * Nak for MRRU option - accept their value if it is smaller + * than the one we want. + */ + if (go->neg_mrru) { + NAKCISHORT(CI_MRRU, neg_mrru, + if (treat_as_reject) + try_.neg_mrru = 0; + else if (cishort <= wo->mrru) + try_.mrru = cishort; + ); + } +#else /* HAVE_MULTILINK */ + LWIP_UNUSED_ARG(treat_as_reject); +#endif /* HAVE_MULTILINK */ + + /* + * Nak for short sequence numbers shouldn't be sent, treat it + * like a reject. + */ + NAKCIVOID(CI_SSNHF, neg_ssnhf); + + /* + * Nak of the endpoint discriminator option is not permitted, + * treat it like a reject. + */ + NAKCIENDP(CI_EPDISC, neg_endpoint); + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If we see an option that we requested, or one we've already seen + * in this packet, then this packet is bad. + * If we wanted to respond by starting to negotiate on the requested + * option(s), we could, but we don't, because except for the + * authentication type and quality protocol, if we are not negotiating + * an option, it is because we were told not to. + * For the authentication type, the Nak from the peer means + * `let me authenticate myself with you' which is a bit pointless. + * For the quality protocol, the Nak means `ask me to send you quality + * reports', but if we didn't ask for them, we don't want them. + * An option we don't recognize represents the peer asking to + * negotiate some option we don't support, so ignore it. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if (cilen < CILEN_VOID || (len -= cilen) < 0) + goto bad; + next = p + cilen - 2; + + switch (citype) { + case CI_MRU: + if ((go->neg_mru && go->mru != PPP_DEFMRU) + || no.neg_mru || cilen != CILEN_SHORT) + goto bad; + GETSHORT(cishort, p); + if (cishort < PPP_DEFMRU) { + try_.neg_mru = 1; + try_.mru = cishort; + } + break; + case CI_ASYNCMAP: + if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + || no.neg_asyncmap || cilen != CILEN_LONG) + goto bad; + break; + case CI_AUTHTYPE: + if (0 +#if CHAP_SUPPORT + || go->neg_chap || no.neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap || no.neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap || no.neg_eap +#endif /* EAP_SUPPORT */ + ) + goto bad; + break; + case CI_MAGICNUMBER: + if (go->neg_magicnumber || no.neg_magicnumber || + cilen != CILEN_LONG) + goto bad; + break; + case CI_PCOMPRESSION: + if (go->neg_pcompression || no.neg_pcompression + || cilen != CILEN_VOID) + goto bad; + break; + case CI_ACCOMPRESSION: + if (go->neg_accompression || no.neg_accompression + || cilen != CILEN_VOID) + goto bad; + break; +#if LQR_SUPPORT + case CI_QUALITY: + if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) + goto bad; + break; +#endif /* LQR_SUPPORT */ +#ifdef HAVE_MULTILINK + case CI_MRRU: + if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT) + goto bad; + break; +#endif /* HAVE_MULTILINK */ + case CI_SSNHF: + if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID) + goto bad; + try_.neg_ssnhf = 1; + break; + case CI_EPDISC: + if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR) + goto bad; + break; + default: + break; + } + p = next; + } + + /* + * OK, the Nak is good. Now we can update state. + * If there are any options left we ignore them. + */ + if (f->state != PPP_FSM_OPENED) { + if (looped_back) { + if (++try_.numloops >= pcb->settings.lcp_loopbackfail) { + ppp_notice("Serial line is looped back."); + pcb->err_code = PPPERR_LOOPBACK; + lcp_close(f->pcb, "Loopback detected"); + } + } else + try_.numloops = 0; + *go = try_; + } + + return 1; + +bad: + LCPDEBUG(("lcp_nakci: received bad Nak!")); + return 0; +} + + +/* + * lcp_rejci - Peer has Rejected some of our CIs. + * This should not modify any state if the Reject is bad + * or if LCP is in the OPENED state. + * + * Returns: + * 0 - Reject was bad. + * 1 - Reject was good. + */ +static int lcp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char cichar; + u_short cishort; + u32_t cilong; + lcp_options try_; /* options to request next time */ + + try_ = *go; + + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIVOID(opt, neg) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + try_.neg = 0; \ + } +#define REJCISHORT(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + try_.neg = 0; \ + } + +#if CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_eap = try_.neg_upap = 0; \ + } +#endif /* CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT */ + +#if CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_upap = 0; \ + } +#endif /* CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT */ + +#if CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_eap = 0; \ + } +#endif /* CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT */ + +#if CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT */ + +#define REJCILONG(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } +#if LQR_SUPPORT +#define REJCILQR(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cishort != PPP_LQR || cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* LQR_SUPPORT */ +#define REJCICBCP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CBCP && \ + p[1] == CILEN_CBCP && \ + p[0] == opt) { \ + len -= CILEN_CBCP; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if (cichar != val) \ + goto bad; \ + try_.neg = 0; \ + } +#define REJCIENDP(opt, neg, class, val, vlen) \ + if (go->neg && \ + len >= CILEN_CHAR + vlen && \ + p[0] == opt && \ + p[1] == CILEN_CHAR + vlen) { \ + int i; \ + len -= CILEN_CHAR + vlen; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + if (cichar != class) \ + goto bad; \ + for (i = 0; i < vlen; ++i) { \ + GETCHAR(cichar, p); \ + if (cichar != val[i]) \ + goto bad; \ + } \ + try_.neg = 0; \ + } + + REJCISHORT(CI_MRU, neg_mru, go->mru); + REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); +#if EAP_SUPPORT + REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP); + if (!go->neg_eap) { +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype); + if (!go->neg_chap) { +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + } +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + } +#endif /* EAP_SUPPORT */ +#if LQR_SUPPORT + REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); + REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); + REJCIVOID(CI_PCOMPRESSION, neg_pcompression); + REJCIVOID(CI_ACCOMPRESSION, neg_accompression); +#ifdef HAVE_MULTILINK + REJCISHORT(CI_MRRU, neg_mrru, go->mrru); +#endif /* HAVE_MULTILINK */ + REJCIVOID(CI_SSNHF, neg_ssnhf); + REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + LCPDEBUG(("lcp_rejci: received bad Reject!")); + return 0; +} + + +/* + * lcp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * lenp = Length of requested CIs + */ +static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ho = &pcb->lcp_hisoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + int cilen, citype, cichar; /* Parsed len, type, char value */ + u_short cishort; /* Parsed short value */ + u32_t cilong; /* Parse long value */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *rejp; /* Pointer to next char in reject frame */ + struct pbuf *nakp; /* Nak buffer */ + u_char *nakoutp; /* Pointer to next char in Nak frame */ + int l = *lenp; /* Length left */ + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + nakp = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); + if(NULL == nakp) + return 0; + if(nakp->tot_len != nakp->len) { + pbuf_free(nakp); + return 0; + } + + nakoutp = (u_char*)nakp->payload; + rejp = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + LCPDEBUG(("lcp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + citype = 0; + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_MRU: + if (!ao->neg_mru || /* Allow option? */ + cilen != CILEN_SHORT) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETSHORT(cishort, p); /* Parse MRU */ + + /* + * He must be able to receive at least our minimum. + * No need to check a maximum. If he sends a large number, + * we'll just ignore it. + */ + if (cishort < PPP_MINMRU) { + orc = CONFNAK; /* Nak CI */ + PUTCHAR(CI_MRU, nakoutp); + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_MINMRU, nakoutp); /* Give him a hint */ + break; + } + ho->neg_mru = 1; /* Remember he sent MRU */ + ho->mru = cishort; /* And remember value */ + break; + + case CI_ASYNCMAP: + if (!ao->neg_asyncmap || + cilen != CILEN_LONG) { + orc = CONFREJ; + break; + } + GETLONG(cilong, p); + + /* + * Asyncmap must have set at least the bits + * which are set in lcp_allowoptions[unit].asyncmap. + */ + if ((ao->asyncmap & ~cilong) != 0) { + orc = CONFNAK; + PUTCHAR(CI_ASYNCMAP, nakoutp); + PUTCHAR(CILEN_LONG, nakoutp); + PUTLONG(ao->asyncmap | cilong, nakoutp); + break; + } + ho->neg_asyncmap = 1; + ho->asyncmap = cilong; + break; + + case CI_AUTHTYPE: + if (cilen < CILEN_SHORT || + !(0 +#if PAP_SUPPORT + || ao->neg_upap +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || ao->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || ao->neg_eap +#endif /* EAP_SUPPORT */ + )) { + /* + * Reject the option if we're not willing to authenticate. + */ + ppp_dbglog("No auth is possible"); + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + /* + * Authtype must be PAP, CHAP, or EAP. + * + * Note: if more than one of ao->neg_upap, ao->neg_chap, and + * ao->neg_eap are set, and the peer sends a Configure-Request + * with two or more authenticate-protocol requests, then we will + * reject the second request. + * Whether we end up doing CHAP, UPAP, or EAP depends then on + * the ordering of the CIs in the peer's Configure-Request. + */ + +#if PAP_SUPPORT + if (cishort == PPP_PAP) { + /* we've already accepted CHAP or EAP */ + if (0 +#if CHAP_SUPPORT + || ho->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || ho->neg_eap +#endif /* EAP_SUPPORT */ + || cilen != CILEN_SHORT) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_upap) { /* we don't want to do PAP */ + orc = CONFNAK; /* NAK it and suggest CHAP or EAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_EAP, nakoutp); + } else { +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + } +#endif /* EAP_SUPPORT */ + break; + } + ho->neg_upap = 1; + break; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (cishort == PPP_CHAP) { + /* we've already accepted PAP or EAP */ + if ( +#if PAP_SUPPORT + ho->neg_upap || +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + ho->neg_eap || +#endif /* EAP_SUPPORT */ + cilen != CILEN_CHAP) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_chap) { /* we don't want to do CHAP */ + orc = CONFNAK; /* NAK it and suggest EAP or PAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); + PUTCHAR(CILEN_SHORT, nakoutp); +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTSHORT(PPP_EAP, nakoutp); + } else +#endif /* EAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTSHORT(PPP_PAP, nakoutp); + } + else +#endif /* PAP_SUPPORT */ + {} + break; + } + GETCHAR(cichar, p); /* get digest type */ + if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) { + /* + * We can't/won't do the requested type, + * suggest something else. + */ + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakoutp); + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + break; + } + ho->chap_mdtype = CHAP_MDTYPE_D(cichar); /* save md type */ + ho->neg_chap = 1; + break; + } +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + if (cishort == PPP_EAP) { + /* we've already accepted CHAP or PAP */ + if ( +#if CHAP_SUPPORT + ho->neg_chap || +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + ho->neg_upap || +#endif /* PAP_SUPPORT */ + cilen != CILEN_SHORT) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE EAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_eap) { /* we don't want to do EAP */ + orc = CONFNAK; /* NAK it and suggest CHAP or PAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); +#if CHAP_SUPPORT + if (ao->neg_chap) { + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_PAP, nakoutp); + } else +#endif /* PAP_SUPPORT */ + {} + break; + } + ho->neg_eap = 1; + break; + } +#endif /* EAP_SUPPORT */ + + /* + * We don't recognize the protocol they're asking for. + * Nak it with something we're willing to do. + * (At this point we know ao->neg_upap || ao->neg_chap || + * ao->neg_eap.) + */ + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakoutp); + +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_EAP, nakoutp); + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (ao->neg_chap) { + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_PAP, nakoutp); + } else +#endif /* PAP_SUPPORT */ + {} + break; + +#if LQR_SUPPORT + case CI_QUALITY: + if (!ao->neg_lqr || + cilen != CILEN_LQR) { + orc = CONFREJ; + break; + } + + GETSHORT(cishort, p); + GETLONG(cilong, p); + + /* + * Check the protocol and the reporting period. + * XXX When should we Nak this, and what with? + */ + if (cishort != PPP_LQR) { + orc = CONFNAK; + PUTCHAR(CI_QUALITY, nakoutp); + PUTCHAR(CILEN_LQR, nakoutp); + PUTSHORT(PPP_LQR, nakoutp); + PUTLONG(ao->lqr_period, nakoutp); + break; + } + break; +#endif /* LQR_SUPPORT */ + + case CI_MAGICNUMBER: + if (!(ao->neg_magicnumber || go->neg_magicnumber) || + cilen != CILEN_LONG) { + orc = CONFREJ; + break; + } + GETLONG(cilong, p); + + /* + * He must have a different magic number. + */ + if (go->neg_magicnumber && + cilong == go->magicnumber) { + cilong = magic(); /* Don't put magic() inside macro! */ + orc = CONFNAK; + PUTCHAR(CI_MAGICNUMBER, nakoutp); + PUTCHAR(CILEN_LONG, nakoutp); + PUTLONG(cilong, nakoutp); + break; + } + ho->neg_magicnumber = 1; + ho->magicnumber = cilong; + break; + + + case CI_PCOMPRESSION: + if (!ao->neg_pcompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_pcompression = 1; + break; + + case CI_ACCOMPRESSION: + if (!ao->neg_accompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_accompression = 1; + break; + +#ifdef HAVE_MULTILINK + case CI_MRRU: + if (!ao->neg_mrru + || !multilink + || cilen != CILEN_SHORT) { + orc = CONFREJ; + break; + } + + GETSHORT(cishort, p); + /* possibly should insist on a minimum/maximum MRRU here */ + ho->neg_mrru = 1; + ho->mrru = cishort; + break; +#endif /* HAVE_MULTILINK */ + + case CI_SSNHF: + if (!ao->neg_ssnhf +#ifdef HAVE_MULTILINK + || !multilink +#endif /* HAVE_MULTILINK */ + || cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_ssnhf = 1; + break; + + case CI_EPDISC: + if (!ao->neg_endpoint || + cilen < CILEN_CHAR || + cilen > CILEN_CHAR + MAX_ENDP_LEN) { + orc = CONFREJ; + break; + } + GETCHAR(cichar, p); + cilen -= CILEN_CHAR; + ho->neg_endpoint = 1; + ho->endpoint.class_ = cichar; + ho->endpoint.length = cilen; + MEMCPY(ho->endpoint.value, p, cilen); + INCPTR(cilen, p); + break; + + default: + LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype)); + orc = CONFREJ; + break; + } + +endswitch: + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree /* Getting fed up with sending NAKs? */ + && citype != CI_MAGICNUMBER) { + orc = CONFREJ; /* Get tough if so */ + } else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + rc = CONFNAK; + } + } + if (orc == CONFREJ) { /* Reject this CI */ + rc = CONFREJ; + if (cip != rejp) /* Need to move rejected CI? */ + MEMCPY(rejp, cip, cilen); /* Move it */ + INCPTR(cilen, rejp); /* Update output pointer */ + } + } + + /* + * If we wanted to send additional NAKs (for unsent CIs), the + * code would go here. The extra NAKs would go at *nakoutp. + * At present there are no cases where we want to ask the + * peer to negotiate an option. + */ + + switch (rc) { + case CONFACK: + *lenp = next - inp; + break; + case CONFNAK: + /* + * Copy the Nak'd options from the nak buffer to the caller's buffer. + */ + *lenp = nakoutp - (u_char*)nakp->payload; + MEMCPY(inp, nakp->payload, *lenp); + break; + case CONFREJ: + *lenp = rejp - inp; + break; + default: + break; + } + + pbuf_free(nakp); + LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +/* + * lcp_up - LCP has come UP. + */ +static void lcp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *ho = &pcb->lcp_hisoptions; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + int mtu, mru; + + if (!go->neg_magicnumber) + go->magicnumber = 0; + if (!ho->neg_magicnumber) + ho->magicnumber = 0; + + /* + * Set our MTU to the smaller of the MTU we wanted and + * the MRU our peer wanted. If we negotiated an MRU, + * set our MRU to the larger of value we wanted and + * the value we got in the negotiation. + * Note on the MTU: the link MTU can be the MRU the peer wanted, + * the interface MTU is set to the lowest of that, the + * MTU we want to use, and our link MRU. + */ + mtu = ho->neg_mru? ho->mru: PPP_MRU; + mru = go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU; +#ifdef HAVE_MULTILINK + if (!(multilink && go->neg_mrru && ho->neg_mrru)) +#endif /* HAVE_MULTILINK */ + netif_set_mtu(pcb, LWIP_MIN(LWIP_MIN(mtu, mru), ao->mru)); + ppp_send_config(pcb, mtu, + (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), + ho->neg_pcompression, ho->neg_accompression); + ppp_recv_config(pcb, mru, + (pcb->settings.lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff), + go->neg_pcompression, go->neg_accompression); + + if (ho->neg_mru) + pcb->peer_mru = ho->mru; + + lcp_echo_lowerup(f->pcb); /* Enable echo messages */ + + link_established(pcb); +} + + +/* + * lcp_down - LCP has gone DOWN. + * + * Alert other protocols. + */ +static void lcp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + + lcp_echo_lowerdown(f->pcb); + + link_down(pcb); + + ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0); + ppp_recv_config(pcb, PPP_MRU, + (go->neg_asyncmap? go->asyncmap: 0xffffffff), + go->neg_pcompression, go->neg_accompression); + pcb->peer_mru = PPP_MRU; +} + + +/* + * lcp_starting - LCP needs the lower layer up. + */ +static void lcp_starting(fsm *f) { + ppp_pcb *pcb = f->pcb; + link_required(pcb); +} + + +/* + * lcp_finished - LCP has finished with the lower layer. + */ +static void lcp_finished(fsm *f) { + ppp_pcb *pcb = f->pcb; + link_terminated(pcb); +} + + +#if PRINTPKT_SUPPORT +/* + * lcp_printpkt - print the contents of an LCP packet. + */ +static const char* const lcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", "ProtRej", + "EchoReq", "EchoRep", "DiscReq", "Ident", + "TimeRem" +}; + +static int lcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, olen, i; + const u_char *pstart, *optend; + u_short cishort; + u32_t cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(lcp_codenames)) + printer(arg, " %s", lcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_MRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mru %d", cishort); + } + break; + case CI_ASYNCMAP: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "asyncmap 0x%x", cilong); + } + break; + case CI_AUTHTYPE: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "auth "); + GETSHORT(cishort, p); + switch (cishort) { +#if PAP_SUPPORT + case PPP_PAP: + printer(arg, "pap"); + break; +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + case PPP_CHAP: + printer(arg, "chap"); + if (p < optend) { + switch (*p) { + case CHAP_MD5: + printer(arg, " MD5"); + ++p; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + printer(arg, " MS"); + ++p; + break; + + case CHAP_MICROSOFT_V2: + printer(arg, " MS-v2"); + ++p; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + } + break; +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + printer(arg, "eap"); + break; +#endif /* EAP_SUPPORT */ + default: + printer(arg, "0x%x", cishort); + } + } + break; +#if LQR_SUPPORT + case CI_QUALITY: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "quality "); + GETSHORT(cishort, p); + switch (cishort) { + case PPP_LQR: + printer(arg, "lqr"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; +#endif /* LQR_SUPPORT */ + case CI_CALLBACK: + if (olen >= CILEN_CHAR) { + p += 2; + printer(arg, "callback "); + GETCHAR(cishort, p); + switch (cishort) { + case CBCP_OPT: + printer(arg, "CBCP"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_MAGICNUMBER: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "magic 0x%x", cilong); + } + break; + case CI_PCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "pcomp"); + } + break; + case CI_ACCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "accomp"); + } + break; + case CI_MRRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mrru %d", cishort); + } + break; + case CI_SSNHF: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "ssnhf"); + } + break; + case CI_EPDISC: +#ifdef HAVE_MULTILINK + if (olen >= CILEN_CHAR) { + struct epdisc epd; + p += 2; + GETCHAR(epd.class, p); + epd.length = olen - CILEN_CHAR; + if (epd.length > MAX_ENDP_LEN) + epd.length = MAX_ENDP_LEN; + if (epd.length > 0) { + MEMCPY(epd.value, p, epd.length); + p += epd.length; + } + printer(arg, "endpoint [%s]", epdisc_to_str(&epd)); + } +#else + printer(arg, "endpoint"); +#endif + break; + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + + case ECHOREQ: + case ECHOREP: + case DISCREQ: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + len -= 4; + } + break; + + case IDENTIF: + case TIMEREM: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + len -= 4; + } + if (code == TIMEREM) { + if (len < 4) + break; + GETLONG(cilong, p); + printer(arg, " seconds=%u", cilong); + len -= 4; + } + if (len > 0) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (i = 0; i < len && i < 32; ++i) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + if (i < len) { + printer(arg, " ..."); + p += len - i; + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +/* + * Time to shut down the link because there is nothing out there. + */ + +static void LcpLinkFailure(fsm *f) { + ppp_pcb *pcb = f->pcb; + if (f->state == PPP_FSM_OPENED) { + ppp_info("No response to %d echo-requests", pcb->lcp_echos_pending); + ppp_notice("Serial link appears to be disconnected."); + pcb->err_code = PPPERR_PEERDEAD; + lcp_close(pcb, "Peer not responding"); + } +} + +/* + * Timer expired for the LCP echo requests from this process. + */ + +static void LcpEchoCheck(fsm *f) { + ppp_pcb *pcb = f->pcb; + + LcpSendEchoRequest (f); + if (f->state != PPP_FSM_OPENED) + return; + + /* + * Start the timer for the next interval. + */ + if (pcb->lcp_echo_timer_running) + ppp_warn("assertion lcp_echo_timer_running==0 failed"); + TIMEOUT (LcpEchoTimeout, f, pcb->settings.lcp_echo_interval); + pcb->lcp_echo_timer_running = 1; +} + +/* + * LcpEchoTimeout - Timer expired on the LCP echo + */ + +static void LcpEchoTimeout(void *arg) { + fsm *f = (fsm*)arg; + ppp_pcb *pcb = f->pcb; + if (pcb->lcp_echo_timer_running != 0) { + pcb->lcp_echo_timer_running = 0; + LcpEchoCheck ((fsm *) arg); + } +} + +/* + * LcpEchoReply - LCP has received a reply to the echo + */ + +static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u32_t magic_val; + LWIP_UNUSED_ARG(id); + + /* Check the magic number - don't count replies from ourselves. */ + if (len < 4) { + ppp_dbglog("lcp: received short Echo-Reply, length %d", len); + return; + } + GETLONG(magic_val, inp); + if (go->neg_magicnumber + && magic_val == go->magicnumber) { + ppp_warn("appear to have received our own echo-reply!"); + return; + } + + /* Reset the number of outstanding echo frames */ + pcb->lcp_echos_pending = 0; +} + +/* + * LcpSendEchoRequest - Send an echo request frame to the peer + */ + +static void LcpSendEchoRequest(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u32_t lcp_magic; + u_char pkt[4], *pktp; + + /* + * Detect the failure of the peer at this point. + */ + if (pcb->settings.lcp_echo_fails != 0) { + if (pcb->lcp_echos_pending >= pcb->settings.lcp_echo_fails) { + LcpLinkFailure(f); + pcb->lcp_echos_pending = 0; + } + } + +#if PPP_LCP_ADAPTIVE + /* + * If adaptive echos have been enabled, only send the echo request if + * no traffic was received since the last one. + */ + if (pcb->settings.lcp_echo_adaptive) { + static unsigned int last_pkts_in = 0; + +#if PPP_STATS_SUPPORT + update_link_stats(f->unit); + link_stats_valid = 0; +#endif /* PPP_STATS_SUPPORT */ + + if (link_stats.pkts_in != last_pkts_in) { + last_pkts_in = link_stats.pkts_in; + return; + } + } +#endif + + /* + * Make and send the echo request frame. + */ + if (f->state == PPP_FSM_OPENED) { + lcp_magic = go->magicnumber; + pktp = pkt; + PUTLONG(lcp_magic, pktp); + fsm_sdata(f, ECHOREQ, pcb->lcp_echo_number++, pkt, pktp - pkt); + ++pcb->lcp_echos_pending; + } +} + +/* + * lcp_echo_lowerup - Start the timer for the LCP frame + */ + +static void lcp_echo_lowerup(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + /* Clear the parameters for generating echo frames */ + pcb->lcp_echos_pending = 0; + pcb->lcp_echo_number = 0; + pcb->lcp_echo_timer_running = 0; + + /* If a timeout interval is specified then start the timer */ + if (pcb->settings.lcp_echo_interval != 0) + LcpEchoCheck (f); +} + +/* + * lcp_echo_lowerdown - Stop the timer for the LCP frame + */ + +static void lcp_echo_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + if (pcb->lcp_echo_timer_running != 0) { + UNTIMEOUT (LcpEchoTimeout, f); + pcb->lcp_echo_timer_running = 0; + } +} + +#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/magic.c b/components/net/lwip-2.0.3/src/netif/ppp/magic.c new file mode 100644 index 0000000000..d0d87c5e55 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/magic.c @@ -0,0 +1,294 @@ +/* + * magic.c - PPP Magic Number routines. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/***************************************************************************** +* randm.c - Random number generator program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-06-03 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/magic.h" + +#if PPP_MD5_RANDM /* Using MD5 for better randomness if enabled */ + +#include "netif/ppp/pppcrypt.h" + +#define MD5_HASH_SIZE 16 +static char magic_randpool[MD5_HASH_SIZE]; /* Pool of randomness. */ +static long magic_randcount; /* Pseudo-random incrementer */ +static u32_t magic_randomseed; /* Seed used for random number generation. */ + +/* + * Churn the randomness pool on a random event. Call this early and often + * on random and semi-random system events to build randomness in time for + * usage. For randomly timed events, pass a null pointer and a zero length + * and this will use the system timer and other sources to add randomness. + * If new random data is available, pass a pointer to that and it will be + * included. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + */ +static void magic_churnrand(char *rand_data, u32_t rand_len) { + lwip_md5_context md5_ctx; + + /* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: %u@%P\n", rand_len, rand_data)); */ + lwip_md5_init(&md5_ctx); + lwip_md5_starts(&md5_ctx); + lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); + if (rand_data) { + lwip_md5_update(&md5_ctx, (u_char *)rand_data, rand_len); + } else { + struct { + /* INCLUDE fields for any system sources of randomness */ + u32_t jiffies; +#ifdef LWIP_RAND + u32_t rand; +#endif /* LWIP_RAND */ + } sys_data; + magic_randomseed += sys_jiffies(); + sys_data.jiffies = magic_randomseed; +#ifdef LWIP_RAND + sys_data.rand = LWIP_RAND(); +#endif /* LWIP_RAND */ + /* Load sys_data fields here. */ + lwip_md5_update(&md5_ctx, (u_char *)&sys_data, sizeof(sys_data)); + } + lwip_md5_finish(&md5_ctx, (u_char *)magic_randpool); + lwip_md5_free(&md5_ctx); +/* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: -> 0\n")); */ +} + +/* + * Initialize the random number generator. + */ +void magic_init(void) { + magic_churnrand(NULL, 0); +} + +/* + * Randomize our random seed value. + */ +void magic_randomize(void) { + magic_churnrand(NULL, 0); +} + +/* + * magic_random_bytes - Fill a buffer with random bytes. + * + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using magic_churnrand(). + * Note: It's important that there be sufficient randomness in magic_randpool + * before this is called for otherwise the range of the result may be + * narrow enough to make a search feasible. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + * + * XXX Why does he not just call magic_churnrand() for each block? Probably + * so that you don't ever publish the seed which could possibly help + * predict future values. + * XXX Why don't we preserve md5 between blocks and just update it with + * magic_randcount each time? Probably there is a weakness but I wish that + * it was documented. + */ +void magic_random_bytes(unsigned char *buf, u32_t buf_len) { + lwip_md5_context md5_ctx; + u_char tmp[MD5_HASH_SIZE]; + u32_t n; + + while (buf_len > 0) { + lwip_md5_init(&md5_ctx); + lwip_md5_starts(&md5_ctx); + lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); + lwip_md5_update(&md5_ctx, (u_char *)&magic_randcount, sizeof(magic_randcount)); + lwip_md5_finish(&md5_ctx, tmp); + lwip_md5_free(&md5_ctx); + magic_randcount++; + n = LWIP_MIN(buf_len, MD5_HASH_SIZE); + MEMCPY(buf, tmp, n); + buf += n; + buf_len -= n; + } +} + +/* + * Return a new random number. + */ +u32_t magic(void) { + u32_t new_rand; + + magic_random_bytes((unsigned char *)&new_rand, sizeof(new_rand)); + + return new_rand; +} + +#else /* PPP_MD5_RANDM */ + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +#ifndef LWIP_RAND +static int magic_randomized; /* Set when truely randomized. */ +#endif /* LWIP_RAND */ +static u32_t magic_randomseed; /* Seed used for random number generation. */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ + +/* + * Initialize the random number generator. + * + * Here we attempt to compute a random number seed but even if + * it isn't random, we'll randomize it later. + * + * The current method uses the fields from the real time clock, + * the idle process counter, the millisecond counter, and the + * hardware timer tick counter. When this is invoked + * in startup(), then the idle counter and timer values may + * repeat after each boot and the real time clock may not be + * operational. Thus we call it again on the first random + * event. + */ +void magic_init(void) { + magic_randomseed += sys_jiffies(); +#ifndef LWIP_RAND + /* Initialize the Borland random number generator. */ + srand((unsigned)magic_randomseed); +#endif /* LWIP_RAND */ +} + +/* + * magic_init - Initialize the magic number generator. + * + * Randomize our random seed value. Here we use the fact that + * this function is called at *truely random* times by the polling + * and network functions. Here we only get 16 bits of new random + * value but we use the previous value to randomize the other 16 + * bits. + */ +void magic_randomize(void) { +#ifndef LWIP_RAND + if (!magic_randomized) { + magic_randomized = !0; + magic_init(); + /* The initialization function also updates the seed. */ + } else { +#endif /* LWIP_RAND */ + magic_randomseed += sys_jiffies(); +#ifndef LWIP_RAND + } +#endif /* LWIP_RAND */ +} + +/* + * Return a new random number. + * + * Here we use the Borland rand() function to supply a pseudo random + * number which we make truely random by combining it with our own + * seed which is randomized by truely random events. + * Thus the numbers will be truely random unless there have been no + * operator or network events in which case it will be pseudo random + * seeded by the real time clock. + */ +u32_t magic(void) { +#ifdef LWIP_RAND + return LWIP_RAND() + magic_randomseed; +#else /* LWIP_RAND */ + return ((u32_t)rand() << 16) + (u32_t)rand() + magic_randomseed; +#endif /* LWIP_RAND */ +} + +/* + * magic_random_bytes - Fill a buffer with random bytes. + */ +void magic_random_bytes(unsigned char *buf, u32_t buf_len) { + u32_t new_rand, n; + + while (buf_len > 0) { + new_rand = magic(); + n = LWIP_MIN(buf_len, sizeof(new_rand)); + MEMCPY(buf, &new_rand, n); + buf += n; + buf_len -= n; + } +} +#endif /* PPP_MD5_RANDM */ + +/* + * Return a new random number between 0 and (2^pow)-1 included. + */ +u32_t magic_pow(u8_t pow) { + return magic() & ~(~0UL<. + * Copyright (c) 2002,2003,2004 Google, Inc. + * All rights reserved. + * + * License: + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. + * + * Changelog: + * 08/12/05 - Matt Domsch + * Only need extra skb padding on transmit, not receive. + * 06/18/04 - Matt Domsch , Oleg Makarenko + * Use Linux kernel 2.6 arc4 and sha1 routines rather than + * providing our own. + * 2/15/04 - TS: added #include and testing for Kernel + * version before using + * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are + * deprecated in 2.6 + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "lwip/err.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/ccp.h" +#include "netif/ppp/mppe.h" +#include "netif/ppp/pppdebug.h" +#include "netif/ppp/pppcrypt.h" + +#define SHA1_SIGNATURE_SIZE 20 + +/* ppp_mppe_state.bits definitions */ +#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ +#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ +#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ +#define MPPE_BIT_D 0x10 /* This is an encrypted frame */ + +#define MPPE_BIT_FLUSHED MPPE_BIT_A +#define MPPE_BIT_ENCRYPTED MPPE_BIT_D + +#define MPPE_BITS(p) ((p)[0] & 0xf0) +#define MPPE_CCOUNT(p) ((((p)[0] & 0x0f) << 8) + (p)[1]) +#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ + +#define MPPE_OVHD 2 /* MPPE overhead/packet */ +#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ + +/* + * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. + * Well, not what's written there, but rather what they meant. + */ +static void mppe_rekey(ppp_mppe_state * state, int initial_key) +{ + lwip_sha1_context sha1_ctx; + u8_t sha1_digest[SHA1_SIGNATURE_SIZE]; + + /* + * Key Derivation, from RFC 3078, RFC 3079. + * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. + */ + lwip_sha1_init(&sha1_ctx); + lwip_sha1_starts(&sha1_ctx); + lwip_sha1_update(&sha1_ctx, state->master_key, state->keylen); + lwip_sha1_update(&sha1_ctx, mppe_sha1_pad1, SHA1_PAD_SIZE); + lwip_sha1_update(&sha1_ctx, state->session_key, state->keylen); + lwip_sha1_update(&sha1_ctx, mppe_sha1_pad2, SHA1_PAD_SIZE); + lwip_sha1_finish(&sha1_ctx, sha1_digest); + lwip_sha1_free(&sha1_ctx); + MEMCPY(state->session_key, sha1_digest, state->keylen); + + if (!initial_key) { + lwip_arc4_init(&state->arc4); + lwip_arc4_setup(&state->arc4, sha1_digest, state->keylen); + lwip_arc4_crypt(&state->arc4, state->session_key, state->keylen); + lwip_arc4_free(&state->arc4); + } + if (state->keylen == 8) { + /* See RFC 3078 */ + state->session_key[0] = 0xd1; + state->session_key[1] = 0x26; + state->session_key[2] = 0x9e; + } + lwip_arc4_init(&state->arc4); + lwip_arc4_setup(&state->arc4, state->session_key, state->keylen); +} + +/* + * Set key, used by MSCHAP before mppe_init() is actually called by CCP so we + * don't have to keep multiple copies of keys. + */ +void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key) { + LWIP_UNUSED_ARG(pcb); + MEMCPY(state->master_key, key, MPPE_MAX_KEY_LEN); +} + +/* + * Initialize (de)compressor state. + */ +void +mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options) +{ +#if PPP_DEBUG + const u8_t *debugstr = (const u8_t*)"mppe_comp_init"; + if (&pcb->mppe_decomp == state) { + debugstr = (const u8_t*)"mppe_decomp_init"; + } +#endif /* PPP_DEBUG */ + + /* Save keys. */ + MEMCPY(state->session_key, state->master_key, sizeof(state->master_key)); + + if (options & MPPE_OPT_128) + state->keylen = 16; + else if (options & MPPE_OPT_40) + state->keylen = 8; + else { + PPPDEBUG(LOG_DEBUG, ("%s[%d]: unknown key length\n", debugstr, + pcb->netif->num)); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + return; + } + if (options & MPPE_OPT_STATEFUL) + state->stateful = 1; + + /* Generate the initial session key. */ + mppe_rekey(state, 1); + +#if PPP_DEBUG + { + int i; + char mkey[sizeof(state->master_key) * 2 + 1]; + char skey[sizeof(state->session_key) * 2 + 1]; + + PPPDEBUG(LOG_DEBUG, ("%s[%d]: initialized with %d-bit %s mode\n", + debugstr, pcb->netif->num, (state->keylen == 16) ? 128 : 40, + (state->stateful) ? "stateful" : "stateless")); + + for (i = 0; i < (int)sizeof(state->master_key); i++) + sprintf(mkey + i * 2, "%02x", state->master_key[i]); + for (i = 0; i < (int)sizeof(state->session_key); i++) + sprintf(skey + i * 2, "%02x", state->session_key[i]); + PPPDEBUG(LOG_DEBUG, + ("%s[%d]: keys: master: %s initial session: %s\n", + debugstr, pcb->netif->num, mkey, skey)); + } +#endif /* PPP_DEBUG */ + + /* + * Initialize the coherency count. The initial value is not specified + * in RFC 3078, but we can make a reasonable assumption that it will + * start at 0. Setting it to the max here makes the comp/decomp code + * do the right thing (determined through experiment). + */ + state->ccount = MPPE_CCOUNT_SPACE - 1; + + /* + * Note that even though we have initialized the key table, we don't + * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. + */ + state->bits = MPPE_BIT_ENCRYPTED; +} + +/* + * We received a CCP Reset-Request (actually, we are sending a Reset-Ack), + * tell the compressor to rekey. Note that we MUST NOT rekey for + * every CCP Reset-Request; we only rekey on the next xmit packet. + * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. + * So, rekeying for every CCP Reset-Request is broken as the peer will not + * know how many times we've rekeyed. (If we rekey and THEN get another + * CCP Reset-Request, we must rekey again.) + */ +void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state) +{ + LWIP_UNUSED_ARG(pcb); + state->bits |= MPPE_BIT_FLUSHED; +} + +/* + * Compress (encrypt) a packet. + * It's strange to call this a compressor, since the output is always + * MPPE_OVHD + 2 bytes larger than the input. + */ +err_t +mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol) +{ + struct pbuf *n, *np; + u8_t *pl; + err_t err; + + LWIP_UNUSED_ARG(pcb); + + /* TCP stack requires that we don't change the packet payload, therefore we copy + * the whole packet before encryption. + */ + np = pbuf_alloc(PBUF_RAW, MPPE_OVHD + sizeof(protocol) + (*pb)->tot_len, PBUF_POOL); + if (!np) { + return ERR_MEM; + } + + /* Hide MPPE header + protocol */ + pbuf_header(np, -(s16_t)(MPPE_OVHD + sizeof(protocol))); + + if ((err = pbuf_copy(np, *pb)) != ERR_OK) { + pbuf_free(np); + return err; + } + + /* Reveal MPPE header + protocol */ + pbuf_header(np, (s16_t)(MPPE_OVHD + sizeof(protocol))); + + *pb = np; + pl = (u8_t*)np->payload; + + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: ccount %d\n", pcb->netif->num, state->ccount)); + /* FIXME: use PUT* macros */ + pl[0] = state->ccount>>8; + pl[1] = state->ccount; + + if (!state->stateful || /* stateless mode */ + ((state->ccount & 0xff) == 0xff) || /* "flag" packet */ + (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ + /* We must rekey */ + if (state->stateful) { + PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: rekeying\n", pcb->netif->num)); + } + mppe_rekey(state, 0); + state->bits |= MPPE_BIT_FLUSHED; + } + pl[0] |= state->bits; + state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ + pl += MPPE_OVHD; + + /* Add protocol */ + /* FIXME: add PFC support */ + pl[0] = protocol >> 8; + pl[1] = protocol; + + /* Hide MPPE header */ + pbuf_header(np, -(s16_t)MPPE_OVHD); + + /* Encrypt packet */ + for (n = np; n != NULL; n = n->next) { + lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); + if (n->tot_len == n->len) { + break; + } + } + + /* Reveal MPPE header */ + pbuf_header(np, (s16_t)MPPE_OVHD); + + return ERR_OK; +} + +/* + * We received a CCP Reset-Ack. Just ignore it. + */ +void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state) +{ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(state); + return; +} + +/* + * Decompress (decrypt) an MPPE packet. + */ +err_t +mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb) +{ + struct pbuf *n0 = *pb, *n; + u8_t *pl; + u16_t ccount; + u8_t flushed; + + /* MPPE Header */ + if (n0->len < MPPE_OVHD) { + PPPDEBUG(LOG_DEBUG, + ("mppe_decompress[%d]: short pkt (%d)\n", + pcb->netif->num, n0->len)); + state->sanity_errors += 100; + goto sanity_error; + } + + pl = (u8_t*)n0->payload; + flushed = MPPE_BITS(pl) & MPPE_BIT_FLUSHED; + ccount = MPPE_CCOUNT(pl); + PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: ccount %d\n", + pcb->netif->num, ccount)); + + /* sanity checks -- terminate with extreme prejudice */ + if (!(MPPE_BITS(pl) & MPPE_BIT_ENCRYPTED)) { + PPPDEBUG(LOG_DEBUG, + ("mppe_decompress[%d]: ENCRYPTED bit not set!\n", + pcb->netif->num)); + state->sanity_errors += 100; + goto sanity_error; + } + if (!state->stateful && !flushed) { + PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set in " + "stateless mode!\n", pcb->netif->num)); + state->sanity_errors += 100; + goto sanity_error; + } + if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { + PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set on " + "flag packet!\n", pcb->netif->num)); + state->sanity_errors += 100; + goto sanity_error; + } + + /* + * Check the coherency count. + */ + + if (!state->stateful) { + /* Discard late packet */ + if ((ccount - state->ccount) % MPPE_CCOUNT_SPACE > MPPE_CCOUNT_SPACE / 2) { + state->sanity_errors++; + goto sanity_error; + } + + /* RFC 3078, sec 8.1. Rekey for every packet. */ + while (state->ccount != ccount) { + mppe_rekey(state, 0); + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + } + } else { + /* RFC 3078, sec 8.2. */ + if (!state->discard) { + /* normal state */ + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + if (ccount != state->ccount) { + /* + * (ccount > state->ccount) + * Packet loss detected, enter the discard state. + * Signal the peer to rekey (by sending a CCP Reset-Request). + */ + state->discard = 1; + ccp_resetrequest(pcb); + return ERR_BUF; + } + } else { + /* discard state */ + if (!flushed) { + /* ccp.c will be silent (no additional CCP Reset-Requests). */ + return ERR_BUF; + } else { + /* Rekey for every missed "flag" packet. */ + while ((ccount & ~0xff) != + (state->ccount & ~0xff)) { + mppe_rekey(state, 0); + state->ccount = + (state->ccount + + 256) % MPPE_CCOUNT_SPACE; + } + + /* reset */ + state->discard = 0; + state->ccount = ccount; + /* + * Another problem with RFC 3078 here. It implies that the + * peer need not send a Reset-Ack packet. But RFC 1962 + * requires it. Hopefully, M$ does send a Reset-Ack; even + * though it isn't required for MPPE synchronization, it is + * required to reset CCP state. + */ + } + } + if (flushed) + mppe_rekey(state, 0); + } + + /* Hide MPPE header */ + pbuf_header(n0, -(s16_t)(MPPE_OVHD)); + + /* Decrypt the packet. */ + for (n = n0; n != NULL; n = n->next) { + lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); + if (n->tot_len == n->len) { + break; + } + } + + /* good packet credit */ + state->sanity_errors >>= 1; + + return ERR_OK; + +sanity_error: + if (state->sanity_errors >= SANITY_MAX) { + /* + * Take LCP down if the peer is sending too many bogons. + * We don't want to do this for a single or just a few + * instances since it could just be due to packet corruption. + */ + lcp_close(pcb, "Too many MPPE errors"); + } + return ERR_BUF; +} + +#endif /* PPP_SUPPORT && MPPE_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/multilink.c b/components/net/lwip-2.0.3/src/netif/ppp/multilink.c new file mode 100644 index 0000000000..62014e8c87 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/multilink.c @@ -0,0 +1,609 @@ +/* + * multilink.c - support routines for multilink. + * + * Copyright (c) 2000-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && defined(HAVE_MULTILINK) /* don't build if not configured for use in lwipopts.h */ + +/* Multilink support + * + * Multilink uses Samba TDB (Trivial Database Library), which + * we cannot port, because it needs a filesystem. + * + * We have to choose between doing a memory-shared TDB-clone, + * or dropping multilink support at all. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/tdb.h" + +bool endpoint_specified; /* user gave explicit endpoint discriminator */ +char *bundle_id; /* identifier for our bundle */ +char *blinks_id; /* key for the list of links */ +bool doing_multilink; /* multilink was enabled and agreed to */ +bool multilink_master; /* we own the multilink bundle */ + +extern TDB_CONTEXT *pppdb; +extern char db_key[]; + +static void make_bundle_links (int append); +static void remove_bundle_link (void); +static void iterate_bundle_links (void (*func) (char *)); + +static int get_default_epdisc (struct epdisc *); +static int parse_num (char *str, const char *key, int *valp); +static int owns_unit (TDB_DATA pid, int unit); + +#define set_ip_epdisc(ep, addr) do { \ + ep->length = 4; \ + ep->value[0] = addr >> 24; \ + ep->value[1] = addr >> 16; \ + ep->value[2] = addr >> 8; \ + ep->value[3] = addr; \ +} while (0) + +#define LOCAL_IP_ADDR(addr) \ + (((addr) & 0xff000000) == 0x0a000000 /* 10.x.x.x */ \ + || ((addr) & 0xfff00000) == 0xac100000 /* 172.16.x.x */ \ + || ((addr) & 0xffff0000) == 0xc0a80000) /* 192.168.x.x */ + +#define process_exists(n) (kill((n), 0) == 0 || errno != ESRCH) + +void +mp_check_options() +{ + lcp_options *wo = &lcp_wantoptions[0]; + lcp_options *ao = &lcp_allowoptions[0]; + + doing_multilink = 0; + if (!multilink) + return; + /* if we're doing multilink, we have to negotiate MRRU */ + if (!wo->neg_mrru) { + /* mrru not specified, default to mru */ + wo->mrru = wo->mru; + wo->neg_mrru = 1; + } + ao->mrru = ao->mru; + ao->neg_mrru = 1; + + if (!wo->neg_endpoint && !noendpoint) { + /* get a default endpoint value */ + wo->neg_endpoint = get_default_epdisc(&wo->endpoint); + } +} + +/* + * Make a new bundle or join us to an existing bundle + * if we are doing multilink. + */ +int +mp_join_bundle() +{ + lcp_options *go = &lcp_gotoptions[0]; + lcp_options *ho = &lcp_hisoptions[0]; + lcp_options *ao = &lcp_allowoptions[0]; + int unit, pppd_pid; + int l, mtu; + char *p; + TDB_DATA key, pid, rec; + + if (doing_multilink) { + /* have previously joined a bundle */ + if (!go->neg_mrru || !ho->neg_mrru) { + notice("oops, didn't get multilink on renegotiation"); + lcp_close(pcb, "multilink required"); + return 0; + } + /* XXX should check the peer_authname and ho->endpoint + are the same as previously */ + return 0; + } + + if (!go->neg_mrru || !ho->neg_mrru) { + /* not doing multilink */ + if (go->neg_mrru) + notice("oops, multilink negotiated only for receive"); + mtu = ho->neg_mru? ho->mru: PPP_MRU; + if (mtu > ao->mru) + mtu = ao->mru; + if (demand) { + /* already have a bundle */ + cfg_bundle(0, 0, 0, 0); + netif_set_mtu(pcb, mtu); + return 0; + } + make_new_bundle(0, 0, 0, 0); + set_ifunit(1); + netif_set_mtu(pcb, mtu); + return 0; + } + + doing_multilink = 1; + + /* + * Find the appropriate bundle or join a new one. + * First we make up a name for the bundle. + * The length estimate is worst-case assuming every + * character has to be quoted. + */ + l = 4 * strlen(peer_authname) + 10; + if (ho->neg_endpoint) + l += 3 * ho->endpoint.length + 8; + if (bundle_name) + l += 3 * strlen(bundle_name) + 2; + bundle_id = malloc(l); + if (bundle_id == 0) + novm("bundle identifier"); + + p = bundle_id; + p += slprintf(p, l-1, "BUNDLE=\"%q\"", peer_authname); + if (ho->neg_endpoint || bundle_name) + *p++ = '/'; + if (ho->neg_endpoint) + p += slprintf(p, bundle_id+l-p, "%s", + epdisc_to_str(&ho->endpoint)); + if (bundle_name) + p += slprintf(p, bundle_id+l-p, "/%v", bundle_name); + + /* Make the key for the list of links belonging to the bundle */ + l = p - bundle_id; + blinks_id = malloc(l + 7); + if (blinks_id == NULL) + novm("bundle links key"); + slprintf(blinks_id, l + 7, "BUNDLE_LINKS=%s", bundle_id + 7); + + /* + * For demand mode, we only need to configure the bundle + * and attach the link. + */ + mtu = LWIP_MIN(ho->mrru, ao->mru); + if (demand) { + cfg_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); + netif_set_mtu(pcb, mtu); + script_setenv("BUNDLE", bundle_id + 7, 1); + return 0; + } + + /* + * Check if the bundle ID is already in the database. + */ + unit = -1; + lock_db(); + key.dptr = bundle_id; + key.dsize = p - bundle_id; + pid = tdb_fetch(pppdb, key); + if (pid.dptr != NULL) { + /* bundle ID exists, see if the pppd record exists */ + rec = tdb_fetch(pppdb, pid); + if (rec.dptr != NULL && rec.dsize > 0) { + /* make sure the string is null-terminated */ + rec.dptr[rec.dsize-1] = 0; + /* parse the interface number */ + parse_num(rec.dptr, "IFNAME=ppp", &unit); + /* check the pid value */ + if (!parse_num(rec.dptr, "PPPD_PID=", &pppd_pid) + || !process_exists(pppd_pid) + || !owns_unit(pid, unit)) + unit = -1; + free(rec.dptr); + } + free(pid.dptr); + } + + if (unit >= 0) { + /* attach to existing unit */ + if (bundle_attach(unit)) { + set_ifunit(0); + script_setenv("BUNDLE", bundle_id + 7, 0); + make_bundle_links(1); + unlock_db(); + info("Link attached to %s", ifname); + return 1; + } + /* attach failed because bundle doesn't exist */ + } + + /* we have to make a new bundle */ + make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); + set_ifunit(1); + netif_set_mtu(pcb, mtu); + script_setenv("BUNDLE", bundle_id + 7, 1); + make_bundle_links(pcb); + unlock_db(); + info("New bundle %s created", ifname); + multilink_master = 1; + return 0; +} + +void mp_exit_bundle() +{ + lock_db(); + remove_bundle_link(); + unlock_db(); +} + +static void sendhup(char *str) +{ + int pid; + + if (parse_num(str, "PPPD_PID=", &pid) && pid != getpid()) { + if (debug) + dbglog("sending SIGHUP to process %d", pid); + kill(pid, SIGHUP); + } +} + +void mp_bundle_terminated() +{ + TDB_DATA key; + + bundle_terminating = 1; + upper_layers_down(pcb); + notice("Connection terminated."); +#if PPP_STATS_SUPPORT + print_link_stats(); +#endif /* PPP_STATS_SUPPORT */ + if (!demand) { + remove_pidfiles(); + script_unsetenv("IFNAME"); + } + + lock_db(); + destroy_bundle(); + iterate_bundle_links(sendhup); + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + tdb_delete(pppdb, key); + unlock_db(); + + new_phase(PPP_PHASE_DEAD); + + doing_multilink = 0; + multilink_master = 0; +} + +static void make_bundle_links(int append) +{ + TDB_DATA key, rec; + char *p; + char entry[32]; + int l; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + slprintf(entry, sizeof(entry), "%s;", db_key); + p = entry; + if (append) { + rec = tdb_fetch(pppdb, key); + if (rec.dptr != NULL && rec.dsize > 0) { + rec.dptr[rec.dsize-1] = 0; + if (strstr(rec.dptr, db_key) != NULL) { + /* already in there? strange */ + warn("link entry already exists in tdb"); + return; + } + l = rec.dsize + strlen(entry); + p = malloc(l); + if (p == NULL) + novm("bundle link list"); + slprintf(p, l, "%s%s", rec.dptr, entry); + } else { + warn("bundle link list not found"); + } + if (rec.dptr != NULL) + free(rec.dptr); + } + rec.dptr = p; + rec.dsize = strlen(p) + 1; + if (tdb_store(pppdb, key, rec, TDB_REPLACE)) + error("couldn't %s bundle link list", + append? "update": "create"); + if (p != entry) + free(p); +} + +static void remove_bundle_link() +{ + TDB_DATA key, rec; + char entry[32]; + char *p, *q; + int l; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + slprintf(entry, sizeof(entry), "%s;", db_key); + + rec = tdb_fetch(pppdb, key); + if (rec.dptr == NULL || rec.dsize <= 0) { + if (rec.dptr != NULL) + free(rec.dptr); + return; + } + rec.dptr[rec.dsize-1] = 0; + p = strstr(rec.dptr, entry); + if (p != NULL) { + q = p + strlen(entry); + l = strlen(q) + 1; + memmove(p, q, l); + rec.dsize = p - rec.dptr + l; + if (tdb_store(pppdb, key, rec, TDB_REPLACE)) + error("couldn't update bundle link list (removal)"); + } + free(rec.dptr); +} + +static void iterate_bundle_links(void (*func)(char *)) +{ + TDB_DATA key, rec, pp; + char *p, *q; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + rec = tdb_fetch(pppdb, key); + if (rec.dptr == NULL || rec.dsize <= 0) { + error("bundle link list not found (iterating list)"); + if (rec.dptr != NULL) + free(rec.dptr); + return; + } + p = rec.dptr; + p[rec.dsize-1] = 0; + while ((q = strchr(p, ';')) != NULL) { + *q = 0; + key.dptr = p; + key.dsize = q - p; + pp = tdb_fetch(pppdb, key); + if (pp.dptr != NULL && pp.dsize > 0) { + pp.dptr[pp.dsize-1] = 0; + func(pp.dptr); + } + if (pp.dptr != NULL) + free(pp.dptr); + p = q + 1; + } + free(rec.dptr); +} + +static int +parse_num(str, key, valp) + char *str; + const char *key; + int *valp; +{ + char *p, *endp; + int i; + + p = strstr(str, key); + if (p != 0) { + p += strlen(key); + i = strtol(p, &endp, 10); + if (endp != p && (*endp == 0 || *endp == ';')) { + *valp = i; + return 1; + } + } + return 0; +} + +/* + * Check whether the pppd identified by `key' still owns ppp unit `unit'. + */ +static int +owns_unit(key, unit) + TDB_DATA key; + int unit; +{ + char ifkey[32]; + TDB_DATA kd, vd; + int ret = 0; + + slprintf(ifkey, sizeof(ifkey), "IFNAME=ppp%d", unit); + kd.dptr = ifkey; + kd.dsize = strlen(ifkey); + vd = tdb_fetch(pppdb, kd); + if (vd.dptr != NULL) { + ret = vd.dsize == key.dsize + && memcmp(vd.dptr, key.dptr, vd.dsize) == 0; + free(vd.dptr); + } + return ret; +} + +static int +get_default_epdisc(ep) + struct epdisc *ep; +{ + char *p; + struct hostent *hp; + u32_t addr; + + /* First try for an ethernet MAC address */ + p = get_first_ethernet(); + if (p != 0 && get_if_hwaddr(ep->value, p) >= 0) { + ep->class = EPD_MAC; + ep->length = 6; + return 1; + } + + /* see if our hostname corresponds to a reasonable IP address */ + hp = gethostbyname(hostname); + if (hp != NULL) { + addr = *(u32_t *)hp->h_addr; + if (!bad_ip_adrs(addr)) { + addr = lwip_ntohl(addr); + if (!LOCAL_IP_ADDR(addr)) { + ep->class = EPD_IP; + set_ip_epdisc(ep, addr); + return 1; + } + } + } + + return 0; +} + +/* + * epdisc_to_str - make a printable string from an endpoint discriminator. + */ + +static char *endp_class_names[] = { + "null", "local", "IP", "MAC", "magic", "phone" +}; + +char * +epdisc_to_str(ep) + struct epdisc *ep; +{ + static char str[MAX_ENDP_LEN*3+8]; + u_char *p = ep->value; + int i, mask = 0; + char *q, c, c2; + + if (ep->class == EPD_NULL && ep->length == 0) + return "null"; + if (ep->class == EPD_IP && ep->length == 4) { + u32_t addr; + + GETLONG(addr, p); + slprintf(str, sizeof(str), "IP:%I", lwip_htonl(addr)); + return str; + } + + c = ':'; + c2 = '.'; + if (ep->class == EPD_MAC && ep->length == 6) + c2 = ':'; + else if (ep->class == EPD_MAGIC && (ep->length % 4) == 0) + mask = 3; + q = str; + if (ep->class <= EPD_PHONENUM) + q += slprintf(q, sizeof(str)-1, "%s", + endp_class_names[ep->class]); + else + q += slprintf(q, sizeof(str)-1, "%d", ep->class); + c = ':'; + for (i = 0; i < ep->length && i < MAX_ENDP_LEN; ++i) { + if ((i & mask) == 0) { + *q++ = c; + c = c2; + } + q += slprintf(q, str + sizeof(str) - q, "%.2x", ep->value[i]); + } + return str; +} + +static int hexc_val(int c) +{ + if (c >= 'a') + return c - 'a' + 10; + if (c >= 'A') + return c - 'A' + 10; + return c - '0'; +} + +int +str_to_epdisc(ep, str) + struct epdisc *ep; + char *str; +{ + int i, l; + char *p, *endp; + + for (i = EPD_NULL; i <= EPD_PHONENUM; ++i) { + int sl = strlen(endp_class_names[i]); + if (strncasecmp(str, endp_class_names[i], sl) == 0) { + str += sl; + break; + } + } + if (i > EPD_PHONENUM) { + /* not a class name, try a decimal class number */ + i = strtol(str, &endp, 10); + if (endp == str) + return 0; /* can't parse class number */ + str = endp; + } + ep->class = i; + if (*str == 0) { + ep->length = 0; + return 1; + } + if (*str != ':' && *str != '.') + return 0; + ++str; + + if (i == EPD_IP) { + u32_t addr; + i = parse_dotted_ip(str, &addr); + if (i == 0 || str[i] != 0) + return 0; + set_ip_epdisc(ep, addr); + return 1; + } + if (i == EPD_MAC && get_if_hwaddr(ep->value, str) >= 0) { + ep->length = 6; + return 1; + } + + p = str; + for (l = 0; l < MAX_ENDP_LEN; ++l) { + if (*str == 0) + break; + if (p <= str) + for (p = str; isxdigit(*p); ++p) + ; + i = p - str; + if (i == 0) + return 0; + ep->value[l] = hexc_val(*str++); + if ((i & 1) == 0) + ep->value[l] = (ep->value[l] << 4) + hexc_val(*str++); + if (*str == ':' || *str == '.') + ++str; + } + if (*str != 0 || (ep->class == EPD_MAC && l != 6)) + return 0; + ep->length = l; + return 1; +} + +#endif /* PPP_SUPPORT && HAVE_MULTILINK */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/polarssl/README b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/README new file mode 100644 index 0000000000..3fdf159ec1 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/README @@ -0,0 +1,22 @@ +About PolarSSL files into lwIP PPP support +------------------------------------------ + +This folder contains some files fetched from the latest BSD release of +the PolarSSL project (PolarSSL 0.10.1-bsd) for ciphers and encryption +methods we need for lwIP PPP support. + +The PolarSSL files were cleaned to contain only the necessary struct +fields and functions needed for lwIP. + +The PolarSSL API was not changed at all, so if you are already using +PolarSSL you can choose to skip the compilation of the included PolarSSL +library into lwIP. + +If you are not using the embedded copy you must include external +libraries into your arch/cc.h port file. + +Beware of the stack requirements which can be a lot larger if you are not +using our cleaned PolarSSL library. + + +PolarSSL project website: http://polarssl.org/ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/polarssl/arc4.c b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/arc4.c new file mode 100644 index 0000000000..6e17ec421b --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/arc4.c @@ -0,0 +1,101 @@ +/* + * An implementation of the ARCFOUR algorithm + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_ARC4 + +#include "netif/ppp/polarssl/arc4.h" +/* + * ARC4 key schedule + */ +void arc4_setup( arc4_context *ctx, unsigned char *key, int keylen ) +{ + int i, j, k, a; + unsigned char *m; + + ctx->x = 0; + ctx->y = 0; + m = ctx->m; + + for( i = 0; i < 256; i++ ) + m[i] = (unsigned char) i; + + j = k = 0; + + for( i = 0; i < 256; i++, k++ ) + { + if( k >= keylen ) k = 0; + + a = m[i]; + j = ( j + a + key[k] ) & 0xFF; + m[i] = m[j]; + m[j] = (unsigned char) a; + } +} + +/* + * ARC4 cipher function + */ +void arc4_crypt( arc4_context *ctx, unsigned char *buf, int buflen ) +{ + int i, x, y, a, b; + unsigned char *m; + + x = ctx->x; + y = ctx->y; + m = ctx->m; + + for( i = 0; i < buflen; i++ ) + { + x = ( x + 1 ) & 0xFF; a = m[x]; + y = ( y + a ) & 0xFF; b = m[y]; + + m[x] = (unsigned char) b; + m[y] = (unsigned char) a; + + buf[i] = (unsigned char) + ( buf[i] ^ m[(unsigned char)( a + b )] ); + } + + ctx->x = x; + ctx->y = y; +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/polarssl/des.c b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/des.c new file mode 100644 index 0000000000..9a89d007bd --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/des.c @@ -0,0 +1,422 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES + +#include "netif/ppp/polarssl/des.h" + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Expanded DES S-boxes + */ +static const unsigned long SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const unsigned long SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const unsigned long SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const unsigned long SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const unsigned long SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const unsigned long SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const unsigned long SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const unsigned long SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const unsigned long LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const unsigned long RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ +{ \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ + X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ +} + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ +{ \ + X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ + Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ +} + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ +{ \ + T = *SK++ ^ X; \ + Y ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ ((X << 28) | (X >> 4)); \ + Y ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ +} + +#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; } + +static void des_setkey( unsigned long SK[32], unsigned char key[8] ) +{ + int i; + unsigned long X, Y, T; + + GET_ULONG_BE( X, key, 0 ); + GET_ULONG_BE( Y, key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} + +/* + * DES key schedule (56-bit, encryption) + */ +void des_setkey_enc( des_context *ctx, unsigned char key[8] ) +{ + des_setkey( ctx->sk, key ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +void des_setkey_dec( des_context *ctx, unsigned char key[8] ) +{ + int i; + + des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } +} + +/* + * DES-ECB block encryption/decryption + */ +void des_crypt_ecb( des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + unsigned long X, Y, T, *SK; + + SK = ctx->sk; + + GET_ULONG_BE( X, input, 0 ); + GET_ULONG_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_ULONG_BE( Y, output, 0 ); + PUT_ULONG_BE( X, output, 4 ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/polarssl/md4.c b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/md4.c new file mode 100644 index 0000000000..b1701a07b9 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/md4.c @@ -0,0 +1,281 @@ +/* + * RFC 1186/1320 compliant MD4 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The MD4 algorithm was designed by Ron Rivest in 1990. + * + * http://www.ietf.org/rfc/rfc1186.txt + * http://www.ietf.org/rfc/rfc1320.txt + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 + +#include "netif/ppp/polarssl/md4.h" + +#include + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] ) \ + | ( (unsigned long) (b)[(i) + 1] << 8 ) \ + | ( (unsigned long) (b)[(i) + 2] << 16 ) \ + | ( (unsigned long) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +/* + * MD4 context setup + */ +void md4_starts( md4_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +static void md4_process( md4_context *ctx, const unsigned char data[64] ) +{ + unsigned long X[16], A, B, C, D; + + GET_ULONG_LE( X[ 0], data, 0 ); + GET_ULONG_LE( X[ 1], data, 4 ); + GET_ULONG_LE( X[ 2], data, 8 ); + GET_ULONG_LE( X[ 3], data, 12 ); + GET_ULONG_LE( X[ 4], data, 16 ); + GET_ULONG_LE( X[ 5], data, 20 ); + GET_ULONG_LE( X[ 6], data, 24 ); + GET_ULONG_LE( X[ 7], data, 28 ); + GET_ULONG_LE( X[ 8], data, 32 ); + GET_ULONG_LE( X[ 9], data, 36 ); + GET_ULONG_LE( X[10], data, 40 ); + GET_ULONG_LE( X[11], data, 44 ); + GET_ULONG_LE( X[12], data, 48 ); + GET_ULONG_LE( X[13], data, 52 ); + GET_ULONG_LE( X[14], data, 56 ); + GET_ULONG_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x, y, z) ((x & y) | ((~x) & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 1], 7 ); + P( C, D, A, B, X[ 2], 11 ); + P( B, C, D, A, X[ 3], 19 ); + P( A, B, C, D, X[ 4], 3 ); + P( D, A, B, C, X[ 5], 7 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[ 7], 19 ); + P( A, B, C, D, X[ 8], 3 ); + P( D, A, B, C, X[ 9], 7 ); + P( C, D, A, B, X[10], 11 ); + P( B, C, D, A, X[11], 19 ); + P( A, B, C, D, X[12], 3 ); + P( D, A, B, C, X[13], 7 ); + P( C, D, A, B, X[14], 11 ); + P( B, C, D, A, X[15], 19 ); + +#undef P +#undef F + +#define F(x,y,z) ((x & y) | (x & z) | (y & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 4], 5 ); + P( C, D, A, B, X[ 8], 9 ); + P( B, C, D, A, X[12], 13 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 5], 5 ); + P( C, D, A, B, X[ 9], 9 ); + P( B, C, D, A, X[13], 13 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[ 6], 5 ); + P( C, D, A, B, X[10], 9 ); + P( B, C, D, A, X[14], 13 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[ 7], 5 ); + P( C, D, A, B, X[11], 9 ); + P( B, C, D, A, X[15], 13 ); + +#undef P +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 8], 9 ); + P( C, D, A, B, X[ 4], 11 ); + P( B, C, D, A, X[12], 15 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[10], 9 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[14], 15 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 9], 9 ); + P( C, D, A, B, X[ 5], 11 ); + P( B, C, D, A, X[13], 15 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[11], 9 ); + P( C, D, A, B, X[ 7], 11 ); + P( B, C, D, A, X[15], 15 ); + +#undef F +#undef P + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD4 process buffer + */ +void md4_update( md4_context *ctx, const unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, fill ); + md4_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + md4_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, ilen ); + } +} + +static const unsigned char md4_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD4 final digest + */ +void md4_finish( md4_context *ctx, unsigned char output[16] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_LE( low, msglen, 0 ); + PUT_ULONG_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md4_update( ctx, md4_padding, padn ); + md4_update( ctx, msglen, 8 ); + + PUT_ULONG_LE( ctx->state[0], output, 0 ); + PUT_ULONG_LE( ctx->state[1], output, 4 ); + PUT_ULONG_LE( ctx->state[2], output, 8 ); + PUT_ULONG_LE( ctx->state[3], output, 12 ); +} + +/* + * output = MD4( input buffer ) + */ +void md4( unsigned char *input, int ilen, unsigned char output[16] ) +{ + md4_context ctx; + + md4_starts( &ctx ); + md4_update( &ctx, input, ilen ); + md4_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/polarssl/md5.c b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/md5.c new file mode 100644 index 0000000000..1ec4d81a69 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/md5.c @@ -0,0 +1,300 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 + +#include "netif/ppp/polarssl/md5.h" + +#include + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] ) \ + | ( (unsigned long) (b)[(i) + 1] << 8 ) \ + | ( (unsigned long) (b)[(i) + 2] << 16 ) \ + | ( (unsigned long) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +/* + * MD5 context setup + */ +void md5_starts( md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +static void md5_process( md5_context *ctx, const unsigned char data[64] ) +{ + unsigned long X[16], A, B, C, D; + + GET_ULONG_LE( X[ 0], data, 0 ); + GET_ULONG_LE( X[ 1], data, 4 ); + GET_ULONG_LE( X[ 2], data, 8 ); + GET_ULONG_LE( X[ 3], data, 12 ); + GET_ULONG_LE( X[ 4], data, 16 ); + GET_ULONG_LE( X[ 5], data, 20 ); + GET_ULONG_LE( X[ 6], data, 24 ); + GET_ULONG_LE( X[ 7], data, 28 ); + GET_ULONG_LE( X[ 8], data, 32 ); + GET_ULONG_LE( X[ 9], data, 36 ); + GET_ULONG_LE( X[10], data, 40 ); + GET_ULONG_LE( X[11], data, 44 ); + GET_ULONG_LE( X[12], data, 48 ); + GET_ULONG_LE( X[13], data, 52 ); + GET_ULONG_LE( X[14], data, 56 ); + GET_ULONG_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD5 process buffer + */ +void md5_update( md5_context *ctx, const unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, fill ); + md5_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + md5_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, ilen ); + } +} + +static const unsigned char md5_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD5 final digest + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_LE( low, msglen, 0 ); + PUT_ULONG_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md5_update( ctx, md5_padding, padn ); + md5_update( ctx, msglen, 8 ); + + PUT_ULONG_LE( ctx->state[0], output, 0 ); + PUT_ULONG_LE( ctx->state[1], output, 4 ); + PUT_ULONG_LE( ctx->state[2], output, 8 ); + PUT_ULONG_LE( ctx->state[3], output, 12 ); +} + +/* + * output = MD5( input buffer ) + */ +void md5( unsigned char *input, int ilen, unsigned char output[16] ) +{ + md5_context ctx; + + md5_starts( &ctx ); + md5_update( &ctx, input, ilen ); + md5_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/polarssl/sha1.c b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/sha1.c new file mode 100644 index 0000000000..c2192eac54 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/polarssl/sha1.c @@ -0,0 +1,335 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 + +#include "netif/ppp/polarssl/sha1.h" + +#include + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * SHA-1 context setup + */ +void sha1_starts( sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +static void sha1_process( sha1_context *ctx, const unsigned char data[64] ) +{ + unsigned long temp, W[16], A, B, C, D, E; + + GET_ULONG_BE( W[ 0], data, 0 ); + GET_ULONG_BE( W[ 1], data, 4 ); + GET_ULONG_BE( W[ 2], data, 8 ); + GET_ULONG_BE( W[ 3], data, 12 ); + GET_ULONG_BE( W[ 4], data, 16 ); + GET_ULONG_BE( W[ 5], data, 20 ); + GET_ULONG_BE( W[ 6], data, 24 ); + GET_ULONG_BE( W[ 7], data, 28 ); + GET_ULONG_BE( W[ 8], data, 32 ); + GET_ULONG_BE( W[ 9], data, 36 ); + GET_ULONG_BE( W[10], data, 40 ); + GET_ULONG_BE( W[11], data, 44 ); + GET_ULONG_BE( W[12], data, 48 ); + GET_ULONG_BE( W[13], data, 52 ); + GET_ULONG_BE( W[14], data, 56 ); + GET_ULONG_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ + W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +/* + * SHA-1 process buffer + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, fill ); + sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + sha1_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, ilen ); + } +} + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-1 final digest + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_BE( high, msglen, 0 ); + PUT_ULONG_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + sha1_update( ctx, sha1_padding, padn ); + sha1_update( ctx, msglen, 8 ); + + PUT_ULONG_BE( ctx->state[0], output, 0 ); + PUT_ULONG_BE( ctx->state[1], output, 4 ); + PUT_ULONG_BE( ctx->state[2], output, 8 ); + PUT_ULONG_BE( ctx->state[3], output, 12 ); + PUT_ULONG_BE( ctx->state[4], output, 16 ); +} + +/* + * output = SHA-1( input buffer ) + */ +void sha1( unsigned char *input, int ilen, unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_starts( &ctx ); + sha1_update( &ctx, input, ilen ); + sha1_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/ppp.c b/components/net/lwip-2.0.3/src/netif/ppp/ppp.c new file mode 100644 index 0000000000..8b77765e5a --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/ppp.c @@ -0,0 +1,1647 @@ +/***************************************************************************** +* ppp.c - Network Point to Point Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ + +/* + * ppp_defs.h - PPP definitions. + * + * if_pppvar.h - private structures and declarations for PPP. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** + * @defgroup ppp PPP netif + * @ingroup addons + * @verbinclude "ppp.txt" + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/tcpip.h" +#include "lwip/api.h" +#include "lwip/snmp.h" +#include "lwip/ip4.h" /* for ip4_input() */ +#if PPP_IPV6_SUPPORT +#include "lwip/ip6.h" /* for ip6_input() */ +#endif /* PPP_IPV6_SUPPORT */ +#include "lwip/dns.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppos.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/magic.h" + +#if PAP_SUPPORT +#include "netif/ppp/upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "netif/ppp/eap.h" +#endif /* EAP_SUPPORT */ +#if CCP_SUPPORT +#include "netif/ppp/ccp.h" +#endif /* CCP_SUPPORT */ +#if MPPE_SUPPORT +#include "netif/ppp/mppe.h" +#endif /* MPPE_SUPPORT */ +#if ECP_SUPPORT +#include "netif/ppp/ecp.h" +#endif /* EAP_SUPPORT */ +#if VJ_SUPPORT +#include "netif/ppp/vj.h" +#endif /* VJ_SUPPORT */ +#if PPP_IPV4_SUPPORT +#include "netif/ppp/ipcp.h" +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT +#include "netif/ppp/ipv6cp.h" +#endif /* PPP_IPV6_SUPPORT */ + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + +/* Memory pools */ +#if PPPOS_SUPPORT +LWIP_MEMPOOL_PROTOTYPE(PPPOS_PCB); +#endif +#if PPPOE_SUPPORT +LWIP_MEMPOOL_PROTOTYPE(PPPOE_IF); +#endif +#if PPPOL2TP_SUPPORT +LWIP_MEMPOOL_PROTOTYPE(PPPOL2TP_PCB); +#endif +#if LWIP_PPP_API && LWIP_MPU_COMPATIBLE +LWIP_MEMPOOL_PROTOTYPE(PPPAPI_MSG); +#endif +LWIP_MEMPOOL_DECLARE(PPP_PCB, MEMP_NUM_PPP_PCB, sizeof(ppp_pcb), "PPP_PCB") + +/* FIXME: add stats per PPP session */ +#if PPP_STATS_SUPPORT +static struct timeval start_time; /* Time when link was started. */ +static struct pppd_stats old_link_stats; +struct pppd_stats link_stats; +unsigned link_connect_time; +int link_stats_valid; +#endif /* PPP_STATS_SUPPORT */ + +/* + * PPP Data Link Layer "protocol" table. + * One entry per supported protocol. + * The last entry must be NULL. + */ +const struct protent* const protocols[] = { + &lcp_protent, +#if PAP_SUPPORT + &pap_protent, +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + &chap_protent, +#endif /* CHAP_SUPPORT */ +#if CBCP_SUPPORT + &cbcp_protent, +#endif /* CBCP_SUPPORT */ +#if PPP_IPV4_SUPPORT + &ipcp_protent, +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + &ipv6cp_protent, +#endif /* PPP_IPV6_SUPPORT */ +#if CCP_SUPPORT + &ccp_protent, +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT + &ecp_protent, +#endif /* ECP_SUPPORT */ +#ifdef AT_CHANGE + &atcp_protent, +#endif /* AT_CHANGE */ +#if EAP_SUPPORT + &eap_protent, +#endif /* EAP_SUPPORT */ + NULL +}; + +/* Prototypes for procedures local to this file. */ +static void ppp_do_connect(void *arg); +static err_t ppp_netif_init_cb(struct netif *netif); +#if LWIP_IPV4 +static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr); +#endif /* LWIP_IPV4 */ +#if PPP_IPV6_SUPPORT +static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr); +#endif /* PPP_IPV6_SUPPORT */ +static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol); + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +#if PPP_AUTH_SUPPORT +void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) { +#if PAP_SUPPORT + pcb->settings.refuse_pap = !(authtype & PPPAUTHTYPE_PAP); +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + pcb->settings.refuse_chap = !(authtype & PPPAUTHTYPE_CHAP); +#if MSCHAP_SUPPORT + pcb->settings.refuse_mschap = !(authtype & PPPAUTHTYPE_MSCHAP); + pcb->settings.refuse_mschap_v2 = !(authtype & PPPAUTHTYPE_MSCHAP_V2); +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + pcb->settings.refuse_eap = !(authtype & PPPAUTHTYPE_EAP); +#endif /* EAP_SUPPORT */ + pcb->settings.user = user; + pcb->settings.passwd = passwd; +} +#endif /* PPP_AUTH_SUPPORT */ + +#if MPPE_SUPPORT +/* Set MPPE configuration */ +void ppp_set_mppe(ppp_pcb *pcb, u8_t flags) { + if (flags == PPP_MPPE_DISABLE) { + pcb->settings.require_mppe = 0; + return; + } + + pcb->settings.require_mppe = 1; + pcb->settings.refuse_mppe_stateful = !(flags & PPP_MPPE_ALLOW_STATEFUL); + pcb->settings.refuse_mppe_40 = !!(flags & PPP_MPPE_REFUSE_40); + pcb->settings.refuse_mppe_128 = !!(flags & PPP_MPPE_REFUSE_128); +} +#endif /* MPPE_SUPPORT */ + +#if PPP_NOTIFY_PHASE +void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) { + pcb->notify_phase_cb = notify_phase_cb; + notify_phase_cb(pcb, pcb->phase, pcb->ctx_cb); +} +#endif /* PPP_NOTIFY_PHASE */ + +/* + * Initiate a PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Holdoff is the time to wait (in seconds) before initiating + * the connection. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff) { + if (pcb->phase != PPP_PHASE_DEAD) { + return ERR_ALREADY; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_connect[%d]: holdoff=%d\n", pcb->netif->num, holdoff)); + + if (holdoff == 0) { + ppp_do_connect(pcb); + return ERR_OK; + } + + new_phase(pcb, PPP_PHASE_HOLDOFF); + sys_timeout((u32_t)(holdoff*1000), ppp_do_connect, pcb); + return ERR_OK; +} + +#if PPP_SERVER +/* + * Listen for an incoming PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_listen(ppp_pcb *pcb) { + if (pcb->phase != PPP_PHASE_DEAD) { + return ERR_ALREADY; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_listen[%d]\n", pcb->netif->num)); + + if (pcb->link_cb->listen) { + new_phase(pcb, PPP_PHASE_INITIALIZE); + pcb->link_cb->listen(pcb, pcb->link_ctx_cb); + return ERR_OK; + } + return ERR_IF; +} +#endif /* PPP_SERVER */ + +/* + * Initiate the end of a PPP connection. + * Any outstanding packets in the queues are dropped. + * + * Setting nocarrier to 1 close the PPP connection without initiating the + * shutdown procedure. Always using nocarrier = 0 is still recommended, + * this is going to take a little longer time if your link is down, but + * is a safer choice for the PPP state machine. + * + * Return 0 on success, an error code on failure. + */ +err_t +ppp_close(ppp_pcb *pcb, u8_t nocarrier) +{ + pcb->err_code = PPPERR_USER; + + /* holdoff phase, cancel the reconnection */ + if (pcb->phase == PPP_PHASE_HOLDOFF) { + sys_untimeout(ppp_do_connect, pcb); + new_phase(pcb, PPP_PHASE_DEAD); + } + + /* dead phase, nothing to do, call the status callback to be consistent */ + if (pcb->phase == PPP_PHASE_DEAD) { + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return ERR_OK; + } + + /* Already terminating, nothing to do */ + if (pcb->phase >= PPP_PHASE_TERMINATE) { + return ERR_INPROGRESS; + } + + /* LCP not open, close link protocol */ + if (pcb->phase < PPP_PHASE_ESTABLISH) { + new_phase(pcb, PPP_PHASE_DISCONNECT); + ppp_link_terminated(pcb); + return ERR_OK; + } + + /* + * Only accept carrier lost signal on the stable running phase in order + * to prevent changing the PPP phase FSM in transition phases. + * + * Always using nocarrier = 0 is still recommended, this is going to + * take a little longer time, but is a safer choice from FSM point of view. + */ + if (nocarrier && pcb->phase == PPP_PHASE_RUNNING) { + PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: carrier lost -> lcp_lowerdown\n", pcb->netif->num)); + lcp_lowerdown(pcb); + /* forced link termination, this will force link protocol to disconnect. */ + link_terminated(pcb); + return ERR_OK; + } + + /* Disconnect */ + PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: kill_link -> lcp_close\n", pcb->netif->num)); + /* LCP soft close request. */ + lcp_close(pcb, "User request"); + return ERR_OK; +} + +/* + * Release the control block. + * + * This can only be called if PPP is in the dead phase. + * + * You must use ppp_close() before if you wish to terminate + * an established PPP session. + * + * Return 0 on success, an error code on failure. + */ +err_t ppp_free(ppp_pcb *pcb) { + err_t err; + if (pcb->phase != PPP_PHASE_DEAD) { + return ERR_CONN; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_free[%d]\n", pcb->netif->num)); + + netif_remove(pcb->netif); + + err = pcb->link_cb->free(pcb, pcb->link_ctx_cb); + + LWIP_MEMPOOL_FREE(PPP_PCB, pcb); + return err; +} + +/* Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. */ +err_t +ppp_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) +{ + if (pcb == NULL) { + return ERR_VAL; + } + + switch(cmd) { + case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ + if (!arg) { + goto fail; + } + *(int *)arg = (int)(0 +#if PPP_IPV4_SUPPORT + || pcb->if4_up +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + || pcb->if6_up +#endif /* PPP_IPV6_SUPPORT */ + ); + return ERR_OK; + + case PPPCTLG_ERRCODE: /* Get the PPP error code. */ + if (!arg) { + goto fail; + } + *(int *)arg = (int)(pcb->err_code); + return ERR_OK; + + default: + goto fail; + } + +fail: + return ERR_VAL; +} + + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ + +static void ppp_do_connect(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF", pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF); + + new_phase(pcb, PPP_PHASE_INITIALIZE); + pcb->link_cb->connect(pcb, pcb->link_ctx_cb); +} + +/* + * ppp_netif_init_cb - netif init callback + */ +static err_t ppp_netif_init_cb(struct netif *netif) { + netif->name[0] = 'p'; + netif->name[1] = 'p'; +#if LWIP_IPV4 + /* FIXME: change that when netif_null_output_ip4() will materialize */ + netif->output = ppp_netif_output_ip4; +#endif /* LWIP_IPV4 */ +#if PPP_IPV6_SUPPORT + netif->output_ip6 = ppp_netif_output_ip6; +#endif /* PPP_IPV6_SUPPORT */ + netif->flags = NETIF_FLAG_UP; +#if LWIP_NETIF_HOSTNAME + /* @todo: Initialize interface hostname */ + /* netif_set_hostname(netif, "lwip"); */ +#endif /* LWIP_NETIF_HOSTNAME */ + return ERR_OK; +} + +#if LWIP_IPV4 +/* + * Send an IPv4 packet on the given connection. + */ +static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr) { + LWIP_UNUSED_ARG(ipaddr); +#if PPP_IPV4_SUPPORT + return ppp_netif_output(netif, pb, PPP_IP); +#else /* PPP_IPV4_SUPPORT */ + LWIP_UNUSED_ARG(netif); + LWIP_UNUSED_ARG(pb); + return ERR_IF; +#endif /* PPP_IPV4_SUPPORT */ +} +#endif /* LWIP_IPV4 */ + +#if PPP_IPV6_SUPPORT +/* + * Send an IPv6 packet on the given connection. + */ +static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr) { + LWIP_UNUSED_ARG(ipaddr); + return ppp_netif_output(netif, pb, PPP_IPV6); +} +#endif /* PPP_IPV6_SUPPORT */ + +static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol) { + ppp_pcb *pcb = (ppp_pcb*)netif->state; + err_t err; + struct pbuf *fpb = NULL; + + /* Check that the link is up. */ + if (0 +#if PPP_IPV4_SUPPORT + || (protocol == PPP_IP && !pcb->if4_up) +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + || (protocol == PPP_IPV6 && !pcb->if6_up) +#endif /* PPP_IPV6_SUPPORT */ + ) { + PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: link not up\n", pcb->netif->num)); + goto err_rte_drop; + } + +#if MPPE_SUPPORT + /* If MPPE is required, refuse any IP packet until we are able to crypt them. */ + if (pcb->settings.require_mppe && pcb->ccp_transmit_method != CI_MPPE) { + PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: MPPE required, not up\n", pcb->netif->num)); + goto err_rte_drop; + } +#endif /* MPPE_SUPPORT */ + +#if VJ_SUPPORT + /* + * Attempt Van Jacobson header compression if VJ is configured and + * this is an IP packet. + */ + if (protocol == PPP_IP && pcb->vj_enabled) { + switch (vj_compress_tcp(&pcb->vj_comp, &pb)) { + case TYPE_IP: + /* No change... + protocol = PPP_IP; */ + break; + case TYPE_COMPRESSED_TCP: + /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free + * our duplicated pbuf later */ + fpb = pb; + protocol = PPP_VJC_COMP; + break; + case TYPE_UNCOMPRESSED_TCP: + /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free + * our duplicated pbuf later */ + fpb = pb; + protocol = PPP_VJC_UNCOMP; + break; + default: + PPPDEBUG(LOG_WARNING, ("ppp_netif_output[%d]: bad IP packet\n", pcb->netif->num)); + LINK_STATS_INC(link.proterr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(pcb->netif, ifoutdiscards); + return ERR_VAL; + } + } +#endif /* VJ_SUPPORT */ + +#if CCP_SUPPORT + switch (pcb->ccp_transmit_method) { + case 0: + break; /* Don't compress */ +#if MPPE_SUPPORT + case CI_MPPE: + if ((err = mppe_compress(pcb, &pcb->mppe_comp, &pb, protocol)) != ERR_OK) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + goto err; + } + /* if VJ compressor returned a new allocated pbuf, free it */ + if (fpb) { + pbuf_free(fpb); + } + /* mppe_compress() returns a new allocated pbuf, indicate we should free + * our duplicated pbuf later */ + fpb = pb; + protocol = PPP_COMP; + break; +#endif /* MPPE_SUPPORT */ + default: + PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: bad CCP transmit method\n", pcb->netif->num)); + goto err_rte_drop; /* Cannot really happen, we only negotiate what we are able to do */ + } +#endif /* CCP_SUPPORT */ + + err = pcb->link_cb->netif_output(pcb, pcb->link_ctx_cb, pb, protocol); + goto err; + +err_rte_drop: + err = ERR_RTE; + LINK_STATS_INC(link.rterr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); +err: + if (fpb) { + pbuf_free(fpb); + } + return err; +} + +/************************************/ +/*** PRIVATE FUNCTION DEFINITIONS ***/ +/************************************/ + +/* Initialize the PPP subsystem. */ +int ppp_init(void) +{ +#if PPPOS_SUPPORT + LWIP_MEMPOOL_INIT(PPPOS_PCB); +#endif +#if PPPOE_SUPPORT + LWIP_MEMPOOL_INIT(PPPOE_IF); +#endif +#if PPPOL2TP_SUPPORT + LWIP_MEMPOOL_INIT(PPPOL2TP_PCB); +#endif +#if LWIP_PPP_API && LWIP_MPU_COMPATIBLE + LWIP_MEMPOOL_INIT(PPPAPI_MSG); +#endif + + LWIP_MEMPOOL_INIT(PPP_PCB); + + /* + * Initialize magic number generator now so that protocols may + * use magic numbers in initialization. + */ + magic_init(); + + return 0; +} + +/* + * Create a new PPP control block. + * + * This initializes the PPP control block but does not + * attempt to negotiate the LCP session. + * + * Return a new PPP connection control block pointer + * on success or a null pointer on failure. + */ +ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { + ppp_pcb *pcb; + const struct protent *protp; + int i; + + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + if (link_status_cb == NULL) { + return NULL; + } + + pcb = (ppp_pcb*)LWIP_MEMPOOL_ALLOC(PPP_PCB); + if (pcb == NULL) { + return NULL; + } + + memset(pcb, 0, sizeof(ppp_pcb)); + + /* default configuration */ +#if PAP_SUPPORT + pcb->settings.pap_timeout_time = UPAP_DEFTIMEOUT; + pcb->settings.pap_max_transmits = UPAP_DEFTRANSMITS; +#if PPP_SERVER + pcb->settings.pap_req_timeout = UPAP_DEFREQTIME; +#endif /* PPP_SERVER */ +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + pcb->settings.chap_timeout_time = CHAP_DEFTIMEOUT; + pcb->settings.chap_max_transmits = CHAP_DEFTRANSMITS; +#if PPP_SERVER + pcb->settings.chap_rechallenge_time = CHAP_DEFRECHALLENGETIME; +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPPORT */ + +#if EAP_SUPPORT + pcb->settings.eap_req_time = EAP_DEFREQTIME; + pcb->settings.eap_allow_req = EAP_DEFALLOWREQ; +#if PPP_SERVER + pcb->settings.eap_timeout_time = EAP_DEFTIMEOUT; + pcb->settings.eap_max_transmits = EAP_DEFTRANSMITS; +#endif /* PPP_SERVER */ +#endif /* EAP_SUPPORT */ + + pcb->settings.lcp_loopbackfail = LCP_DEFLOOPBACKFAIL; + pcb->settings.lcp_echo_interval = LCP_ECHOINTERVAL; + pcb->settings.lcp_echo_fails = LCP_MAXECHOFAILS; + + pcb->settings.fsm_timeout_time = FSM_DEFTIMEOUT; + pcb->settings.fsm_max_conf_req_transmits = FSM_DEFMAXCONFREQS; + pcb->settings.fsm_max_term_transmits = FSM_DEFMAXTERMREQS; + pcb->settings.fsm_max_nak_loops = FSM_DEFMAXNAKLOOPS; + + pcb->netif = pppif; + MIB2_INIT_NETIF(pppif, snmp_ifType_ppp, 0); + if (!netif_add(pcb->netif, +#if LWIP_IPV4 + IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4, +#endif /* LWIP_IPV4 */ + (void *)pcb, ppp_netif_init_cb, NULL)) { + LWIP_MEMPOOL_FREE(PPP_PCB, pcb); + PPPDEBUG(LOG_ERR, ("ppp_new: netif_add failed\n")); + return NULL; + } + + pcb->link_cb = callbacks; + pcb->link_ctx_cb = link_ctx_cb; + pcb->link_status_cb = link_status_cb; + pcb->ctx_cb = ctx_cb; + + /* + * Initialize each protocol. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + (*protp->init)(pcb); + } + + new_phase(pcb, PPP_PHASE_DEAD); + return pcb; +} + +/** Initiate LCP open request */ +void ppp_start(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]\n", pcb->netif->num)); + + /* Clean data not taken care by anything else, mostly shared data. */ +#if PPP_STATS_SUPPORT + link_stats_valid = 0; +#endif /* PPP_STATS_SUPPORT */ +#if MPPE_SUPPORT + pcb->mppe_keys_set = 0; + memset(&pcb->mppe_comp, 0, sizeof(pcb->mppe_comp)); + memset(&pcb->mppe_decomp, 0, sizeof(pcb->mppe_decomp)); +#endif /* MPPE_SUPPORT */ +#if VJ_SUPPORT + vj_compress_init(&pcb->vj_comp); +#endif /* VJ_SUPPORT */ + + /* Start protocol */ + new_phase(pcb, PPP_PHASE_ESTABLISH); + lcp_open(pcb); + lcp_lowerup(pcb); + PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]: finished\n", pcb->netif->num)); +} + +/** Called when link failed to setup */ +void ppp_link_failed(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_link_failed[%d]\n", pcb->netif->num)); + new_phase(pcb, PPP_PHASE_DEAD); + pcb->err_code = PPPERR_OPEN; + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); +} + +/** Called when link is normally down (i.e. it was asked to end) */ +void ppp_link_end(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_link_end[%d]\n", pcb->netif->num)); + new_phase(pcb, PPP_PHASE_DEAD); + if (pcb->err_code == PPPERR_NONE) { + pcb->err_code = PPPERR_CONNECT; + } + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); +} + +/* + * Pass the processed input packet to the appropriate handler. + * This function and all handlers run in the context of the tcpip_thread + */ +void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { + u16_t protocol; +#if PPP_DEBUG && PPP_PROTOCOLNAME + const char *pname; +#endif /* PPP_DEBUG && PPP_PROTOCOLNAME */ + + magic_randomize(); + + if (pb->len < 2) { + PPPDEBUG(LOG_ERR, ("ppp_input[%d]: packet too short\n", pcb->netif->num)); + goto drop; + } + protocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; + +#if PRINTPKT_SUPPORT + ppp_dump_packet(pcb, "rcvd", (unsigned char *)pb->payload, pb->len); +#endif /* PRINTPKT_SUPPORT */ + + pbuf_header(pb, -(s16_t)sizeof(protocol)); + + LINK_STATS_INC(link.recv); + MIB2_STATS_NETIF_INC(pcb->netif, ifinucastpkts); + MIB2_STATS_NETIF_ADD(pcb->netif, ifinoctets, pb->tot_len); + + /* + * Toss all non-LCP packets unless LCP is OPEN. + */ + if (protocol != PPP_LCP && pcb->lcp_fsm.state != PPP_FSM_OPENED) { + ppp_dbglog("Discarded non-LCP packet when LCP not open"); + goto drop; + } + + /* + * Until we get past the authentication phase, toss all packets + * except LCP, LQR and authentication packets. + */ + if (pcb->phase <= PPP_PHASE_AUTHENTICATE + && !(protocol == PPP_LCP +#if LQR_SUPPORT + || protocol == PPP_LQR +#endif /* LQR_SUPPORT */ +#if PAP_SUPPORT + || protocol == PPP_PAP +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || protocol == PPP_CHAP +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || protocol == PPP_EAP +#endif /* EAP_SUPPORT */ + )) { + ppp_dbglog("discarding proto 0x%x in phase %d", protocol, pcb->phase); + goto drop; + } + +#if CCP_SUPPORT +#if MPPE_SUPPORT + /* + * MPPE is required and unencrypted data has arrived (this + * should never happen!). We should probably drop the link if + * the protocol is in the range of what should be encrypted. + * At the least, we drop this packet. + */ + if (pcb->settings.require_mppe && protocol != PPP_COMP && protocol < 0x8000) { + PPPDEBUG(LOG_ERR, ("ppp_input[%d]: MPPE required, received unencrypted data!\n", pcb->netif->num)); + goto drop; + } +#endif /* MPPE_SUPPORT */ + + if (protocol == PPP_COMP) { + u8_t *pl; + + switch (pcb->ccp_receive_method) { +#if MPPE_SUPPORT + case CI_MPPE: + if (mppe_decompress(pcb, &pcb->mppe_decomp, &pb) != ERR_OK) { + goto drop; + } + break; +#endif /* MPPE_SUPPORT */ + default: + PPPDEBUG(LOG_ERR, ("ppp_input[%d]: bad CCP receive method\n", pcb->netif->num)); + goto drop; /* Cannot really happen, we only negotiate what we are able to do */ + } + + /* Assume no PFC */ + if (pb->len < 2) { + goto drop; + } + + /* Extract and hide protocol (do PFC decompression if necessary) */ + pl = (u8_t*)pb->payload; + if (pl[0] & 0x01) { + protocol = pl[0]; + pbuf_header(pb, -(s16_t)1); + } else { + protocol = (pl[0] << 8) | pl[1]; + pbuf_header(pb, -(s16_t)2); + } + } +#endif /* CCP_SUPPORT */ + + switch(protocol) { + +#if PPP_IPV4_SUPPORT + case PPP_IP: /* Internet Protocol */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + ip4_input(pb, pcb->netif); + return; +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT + case PPP_IPV6: /* Internet Protocol Version 6 */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip6 in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + ip6_input(pb, pcb->netif); + return; +#endif /* PPP_IPV6_SUPPORT */ + +#if VJ_SUPPORT + case PPP_VJC_COMP: /* VJ compressed TCP */ + /* + * Clip off the VJ header and prepend the rebuilt TCP/IP header and + * pass the result to IP. + */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_comp in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + if (pcb->vj_enabled && vj_uncompress_tcp(&pb, &pcb->vj_comp) >= 0) { + ip4_input(pb, pcb->netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ compressed\n", pcb->netif->num)); + break; + + case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ + /* + * Process the TCP/IP header for VJ header compression and then pass + * the packet to IP. + */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_un in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + if (pcb->vj_enabled && vj_uncompress_uncomp(pb, &pcb->vj_comp) >= 0) { + ip4_input(pb, pcb->netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ uncompressed\n", pcb->netif->num)); + break; +#endif /* VJ_SUPPORT */ + + default: { + int i; + const struct protent *protp; + + /* + * Upcall the proper protocol input routine. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol == protocol) { + pb = ppp_singlebuf(pb); + (*protp->input)(pcb, (u8_t*)pb->payload, pb->len); + goto out; + } +#if 0 /* UNUSED + * + * This is actually a (hacked?) way for the Linux kernel to pass a data + * packet to pppd. pppd in normal condition only do signaling + * (LCP, PAP, CHAP, IPCP, ...) and does not handle any data packet at all. + * + * We don't even need this interface, which is only there because of PPP + * interface limitation between Linux kernel and pppd. For MPPE, which uses + * CCP to negotiate although it is not really a (de)compressor, we added + * ccp_resetrequest() in CCP and MPPE input data flow is calling either + * ccp_resetrequest() or lcp_close() if the issue is, respectively, non-fatal + * or fatal, this is what ccp_datainput() really do. + */ + if (protocol == (protp->protocol & ~0x8000) + && protp->datainput != NULL) { + (*protp->datainput)(pcb, pb->payload, pb->len); + goto out; + } +#endif /* UNUSED */ + } + +#if PPP_DEBUG +#if PPP_PROTOCOLNAME + pname = protocol_name(protocol); + if (pname != NULL) { + ppp_warn("Unsupported protocol '%s' (0x%x) received", pname, protocol); + } else +#endif /* PPP_PROTOCOLNAME */ + ppp_warn("Unsupported protocol 0x%x received", protocol); +#endif /* PPP_DEBUG */ + pbuf_header(pb, (s16_t)sizeof(protocol)); + lcp_sprotrej(pcb, (u8_t*)pb->payload, pb->len); + } + break; + } + +drop: + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(pcb->netif, ifindiscards); + +out: + pbuf_free(pb); +} + +/* merge a pbuf chain into one pbuf */ +struct pbuf *ppp_singlebuf(struct pbuf *p) { + struct pbuf *q, *b; + u8_t *pl; + + if(p->tot_len == p->len) { + return p; + } + + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(!q) { + PPPDEBUG(LOG_ERR, + ("ppp_singlebuf: unable to alloc new buf (%d)\n", p->tot_len)); + return p; /* live dangerously */ + } + + for(b = p, pl = (u8_t*)q->payload; b != NULL; b = b->next) { + MEMCPY(pl, b->payload, b->len); + pl += b->len; + } + + pbuf_free(p); + + return q; +} + +/* + * Write a pbuf to a ppp link, only used from PPP functions + * to send PPP packets. + * + * IPv4 and IPv6 packets from lwIP are sent, respectively, + * with ppp_netif_output_ip4() and ppp_netif_output_ip6() + * functions (which are callbacks of the netif PPP interface). + */ +err_t ppp_write(ppp_pcb *pcb, struct pbuf *p) { +#if PRINTPKT_SUPPORT + ppp_dump_packet(pcb, "sent", (unsigned char *)p->payload+2, p->len-2); +#endif /* PRINTPKT_SUPPORT */ + return pcb->link_cb->write(pcb, pcb->link_ctx_cb, p); +} + +void ppp_link_terminated(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]\n", pcb->netif->num)); + pcb->link_cb->disconnect(pcb, pcb->link_ctx_cb); + PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]: finished.\n", pcb->netif->num)); +} + + +/************************************************************************ + * Functions called by various PPP subsystems to configure + * the PPP interface or change the PPP phase. + */ + +/* + * new_phase - signal the start of a new phase of pppd's operation. + */ +void new_phase(ppp_pcb *pcb, int p) { + pcb->phase = p; + PPPDEBUG(LOG_DEBUG, ("ppp phase changed[%d]: phase=%d\n", pcb->netif->num, pcb->phase)); +#if PPP_NOTIFY_PHASE + if (pcb->notify_phase_cb != NULL) { + pcb->notify_phase_cb(pcb, p, pcb->ctx_cb); + } +#endif /* PPP_NOTIFY_PHASE */ +} + +/* + * ppp_send_config - configure the transmit-side characteristics of + * the ppp interface. + */ +int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp) { + LWIP_UNUSED_ARG(mtu); + /* pcb->mtu = mtu; -- set correctly with netif_set_mtu */ + + if (pcb->link_cb->send_config) { + pcb->link_cb->send_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); + } + + PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]\n", pcb->netif->num) ); + return 0; +} + +/* + * ppp_recv_config - configure the receive-side characteristics of + * the ppp interface. + */ +int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp) { + LWIP_UNUSED_ARG(mru); + + if (pcb->link_cb->recv_config) { + pcb->link_cb->recv_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); + } + + PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]\n", pcb->netif->num)); + return 0; +} + +#if PPP_IPV4_SUPPORT +/* + * sifaddr - Config the interface IP addresses and netmask. + */ +int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t netmask) { + ip4_addr_t ip, nm, gw; + + ip4_addr_set_u32(&ip, our_adr); + ip4_addr_set_u32(&nm, netmask); + ip4_addr_set_u32(&gw, his_adr); + netif_set_addr(pcb->netif, &ip, &nm, &gw); + return 1; +} + +/******************************************************************** + * + * cifaddr - Clear the interface IP addresses, and delete routes + * through the interface if possible. + */ +int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr) { + LWIP_UNUSED_ARG(our_adr); + LWIP_UNUSED_ARG(his_adr); + + netif_set_addr(pcb->netif, IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4); + return 1; +} + +#if 0 /* UNUSED - PROXY ARP */ +/******************************************************************** + * + * sifproxyarp - Make a proxy ARP entry for the peer. + */ + +int sifproxyarp(ppp_pcb *pcb, u32_t his_adr) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(his_adr); + return 0; +} + +/******************************************************************** + * + * cifproxyarp - Delete the proxy ARP entry for the peer. + */ + +int cifproxyarp(ppp_pcb *pcb, u32_t his_adr) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(his_adr); + return 0; +} +#endif /* UNUSED - PROXY ARP */ + +#if LWIP_DNS +/* + * sdns - Config the DNS servers + */ +int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { + ip_addr_t ns; + LWIP_UNUSED_ARG(pcb); + + ip_addr_set_ip4_u32(&ns, ns1); + dns_setserver(0, &ns); + ip_addr_set_ip4_u32(&ns, ns2); + dns_setserver(1, &ns); + return 1; +} + +/******************************************************************** + * + * cdns - Clear the DNS servers + */ +int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { + const ip_addr_t *nsa; + ip_addr_t nsb; + LWIP_UNUSED_ARG(pcb); + + nsa = dns_getserver(0); + ip_addr_set_ip4_u32(&nsb, ns1); + if (ip_addr_cmp(nsa, &nsb)) { + dns_setserver(0, IP_ADDR_ANY); + } + nsa = dns_getserver(1); + ip_addr_set_ip4_u32(&nsb, ns2); + if (ip_addr_cmp(nsa, &nsb)) { + dns_setserver(1, IP_ADDR_ANY); + } + return 1; +} +#endif /* LWIP_DNS */ + +#if VJ_SUPPORT +/******************************************************************** + * + * sifvjcomp - config tcp header compression + */ +int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid) { + pcb->vj_enabled = vjcomp; + pcb->vj_comp.compressSlot = cidcomp; + pcb->vj_comp.maxSlotIndex = maxcid; + PPPDEBUG(LOG_INFO, ("sifvjcomp[%d]: VJ compress enable=%d slot=%d max slot=%d\n", + pcb->netif->num, vjcomp, cidcomp, maxcid)); + return 0; +} +#endif /* VJ_SUPPORT */ + +/* + * sifup - Config the interface up and enable IP packets to pass. + */ +int sifup(ppp_pcb *pcb) { + pcb->if4_up = 1; + pcb->err_code = PPPERR_NONE; + netif_set_link_up(pcb->netif); + + PPPDEBUG(LOG_DEBUG, ("sifup[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return 1; +} + +/******************************************************************** + * + * sifdown - Disable the indicated protocol and config the interface + * down if there are no remaining protocols. + */ +int sifdown(ppp_pcb *pcb) { + + pcb->if4_up = 0; + + if (1 +#if PPP_IPV6_SUPPORT + /* set the interface down if IPv6 is down as well */ + && !pcb->if6_up +#endif /* PPP_IPV6_SUPPORT */ + ) { + /* make sure the netif link callback is called */ + netif_set_link_down(pcb->netif); + } + PPPDEBUG(LOG_DEBUG, ("sifdown[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + return 1; +} + +/******************************************************************** + * + * Return user specified netmask, modified by any mask we might determine + * for address `addr' (in network byte order). + * Here we scan through the system's list of interfaces, looking for + * any non-point-to-point interfaces which might appear to be on the same + * network as `addr'. If we find any, we OR in their netmask to the + * user-specified netmask. + */ +u32_t get_mask(u32_t addr) { +#if 0 + u32_t mask, nmask; + + addr = lwip_htonl(addr); + if (IP_CLASSA(addr)) { /* determine network mask for address class */ + nmask = IP_CLASSA_NET; + } else if (IP_CLASSB(addr)) { + nmask = IP_CLASSB_NET; + } else { + nmask = IP_CLASSC_NET; + } + + /* class D nets are disallowed by bad_ip_adrs */ + mask = PP_HTONL(0xffffff00UL) | lwip_htonl(nmask); + + /* XXX + * Scan through the system's network interfaces. + * Get each netmask and OR them into our mask. + */ + /* return mask; */ + return mask; +#endif /* 0 */ + LWIP_UNUSED_ARG(addr); + return IPADDR_BROADCAST; +} +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT +#define IN6_LLADDR_FROM_EUI64(ip6, eui64) do { \ + ip6.addr[0] = PP_HTONL(0xfe800000); \ + ip6.addr[1] = 0; \ + eui64_copy(eui64, ip6.addr[2]); \ + } while (0) + +/******************************************************************** + * + * sif6addr - Config the interface with an IPv6 link-local address + */ +int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { + ip6_addr_t ip6; + LWIP_UNUSED_ARG(his_eui64); + + IN6_LLADDR_FROM_EUI64(ip6, our_eui64); + netif_ip6_addr_set(pcb->netif, 0, &ip6); + netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_PREFERRED); + /* FIXME: should we add an IPv6 static neighbor using his_eui64 ? */ + return 1; +} + +/******************************************************************** + * + * cif6addr - Remove IPv6 address from interface + */ +int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { + LWIP_UNUSED_ARG(our_eui64); + LWIP_UNUSED_ARG(his_eui64); + + netif_ip6_addr_set(pcb->netif, 0, IP6_ADDR_ANY6); + netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_INVALID); + return 1; +} + +/* + * sif6up - Config the interface up and enable IPv6 packets to pass. + */ +int sif6up(ppp_pcb *pcb) { + + pcb->if6_up = 1; + pcb->err_code = PPPERR_NONE; + netif_set_link_up(pcb->netif); + + PPPDEBUG(LOG_DEBUG, ("sif6up[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return 1; +} + +/******************************************************************** + * + * sif6down - Disable the indicated protocol and config the interface + * down if there are no remaining protocols. + */ +int sif6down(ppp_pcb *pcb) { + + pcb->if6_up = 0; + + if (1 +#if PPP_IPV4_SUPPORT + /* set the interface down if IPv4 is down as well */ + && !pcb->if4_up +#endif /* PPP_IPV4_SUPPORT */ + ) { + /* make sure the netif link callback is called */ + netif_set_link_down(pcb->netif); + } + PPPDEBUG(LOG_DEBUG, ("sif6down[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + return 1; +} +#endif /* PPP_IPV6_SUPPORT */ + +#if DEMAND_SUPPORT +/* + * sifnpmode - Set the mode for handling packets for a given NP. + */ +int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(proto); + LWIP_UNUSED_ARG(mode); + return 0; +} +#endif /* DEMAND_SUPPORT */ + +/* + * netif_set_mtu - set the MTU on the PPP network interface. + */ +void netif_set_mtu(ppp_pcb *pcb, int mtu) { + + pcb->netif->mtu = mtu; + PPPDEBUG(LOG_INFO, ("netif_set_mtu[%d]: mtu=%d\n", pcb->netif->num, mtu)); +} + +/* + * netif_get_mtu - get PPP interface MTU + */ +int netif_get_mtu(ppp_pcb *pcb) { + + return pcb->netif->mtu; +} + +#if CCP_SUPPORT +#if 0 /* unused */ +/* + * ccp_test - whether a given compression method is acceptable for use. + */ +int +ccp_test(ppp_pcb *pcb, u_char *opt_ptr, int opt_len, int for_transmit) +{ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(opt_ptr); + LWIP_UNUSED_ARG(opt_len); + LWIP_UNUSED_ARG(for_transmit); + return -1; +} +#endif /* unused */ + +/* + * ccp_set - inform about the current state of CCP. + */ +void +ccp_set(ppp_pcb *pcb, u8_t isopen, u8_t isup, u8_t receive_method, u8_t transmit_method) +{ + LWIP_UNUSED_ARG(isopen); + LWIP_UNUSED_ARG(isup); + pcb->ccp_receive_method = receive_method; + pcb->ccp_transmit_method = transmit_method; + PPPDEBUG(LOG_DEBUG, ("ccp_set[%d]: is_open=%d, is_up=%d, receive_method=%u, transmit_method=%u\n", + pcb->netif->num, isopen, isup, receive_method, transmit_method)); +} + +void +ccp_reset_comp(ppp_pcb *pcb) +{ + switch (pcb->ccp_transmit_method) { +#if MPPE_SUPPORT + case CI_MPPE: + mppe_comp_reset(pcb, &pcb->mppe_comp); + break; +#endif /* MPPE_SUPPORT */ + default: + break; + } +} + +void +ccp_reset_decomp(ppp_pcb *pcb) +{ + switch (pcb->ccp_receive_method) { +#if MPPE_SUPPORT + case CI_MPPE: + mppe_decomp_reset(pcb, &pcb->mppe_decomp); + break; +#endif /* MPPE_SUPPORT */ + default: + break; + } +} + +#if 0 /* unused */ +/* + * ccp_fatal_error - returns 1 if decompression was disabled as a + * result of an error detected after decompression of a packet, + * 0 otherwise. This is necessary because of patent nonsense. + */ +int +ccp_fatal_error(ppp_pcb *pcb) +{ + LWIP_UNUSED_ARG(pcb); + return 1; +} +#endif /* unused */ +#endif /* CCP_SUPPORT */ + +#if PPP_IDLETIMELIMIT +/******************************************************************** + * + * get_idle_time - return how long the link has been idle. + */ +int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip) { + /* FIXME: add idle time support and make it optional */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(ip); + return 1; +} +#endif /* PPP_IDLETIMELIMIT */ + +#if DEMAND_SUPPORT +/******************************************************************** + * + * get_loop_output - get outgoing packets from the ppp device, + * and detect when we want to bring the real link up. + * Return value is 1 if we need to bring up the link, 0 otherwise. + */ +int get_loop_output(void) { + return 0; +} +#endif /* DEMAND_SUPPORT */ + +#if PPP_PROTOCOLNAME +/* List of protocol names, to make our messages a little more informative. */ +struct protocol_list { + u_short proto; + const char *name; +} const protocol_list[] = { + { 0x21, "IP" }, + { 0x23, "OSI Network Layer" }, + { 0x25, "Xerox NS IDP" }, + { 0x27, "DECnet Phase IV" }, + { 0x29, "Appletalk" }, + { 0x2b, "Novell IPX" }, + { 0x2d, "VJ compressed TCP/IP" }, + { 0x2f, "VJ uncompressed TCP/IP" }, + { 0x31, "Bridging PDU" }, + { 0x33, "Stream Protocol ST-II" }, + { 0x35, "Banyan Vines" }, + { 0x39, "AppleTalk EDDP" }, + { 0x3b, "AppleTalk SmartBuffered" }, + { 0x3d, "Multi-Link" }, + { 0x3f, "NETBIOS Framing" }, + { 0x41, "Cisco Systems" }, + { 0x43, "Ascom Timeplex" }, + { 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" }, + { 0x47, "DCA Remote Lan" }, + { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" }, + { 0x4b, "SNA over 802.2" }, + { 0x4d, "SNA" }, + { 0x4f, "IP6 Header Compression" }, + { 0x51, "KNX Bridging Data" }, + { 0x53, "Encryption" }, + { 0x55, "Individual Link Encryption" }, + { 0x57, "IPv6" }, + { 0x59, "PPP Muxing" }, + { 0x5b, "Vendor-Specific Network Protocol" }, + { 0x61, "RTP IPHC Full Header" }, + { 0x63, "RTP IPHC Compressed TCP" }, + { 0x65, "RTP IPHC Compressed non-TCP" }, + { 0x67, "RTP IPHC Compressed UDP 8" }, + { 0x69, "RTP IPHC Compressed RTP 8" }, + { 0x6f, "Stampede Bridging" }, + { 0x73, "MP+" }, + { 0xc1, "NTCITS IPI" }, + { 0xfb, "single-link compression" }, + { 0xfd, "Compressed Datagram" }, + { 0x0201, "802.1d Hello Packets" }, + { 0x0203, "IBM Source Routing BPDU" }, + { 0x0205, "DEC LANBridge100 Spanning Tree" }, + { 0x0207, "Cisco Discovery Protocol" }, + { 0x0209, "Netcs Twin Routing" }, + { 0x020b, "STP - Scheduled Transfer Protocol" }, + { 0x020d, "EDP - Extreme Discovery Protocol" }, + { 0x0211, "Optical Supervisory Channel Protocol" }, + { 0x0213, "Optical Supervisory Channel Protocol" }, + { 0x0231, "Luxcom" }, + { 0x0233, "Sigma Network Systems" }, + { 0x0235, "Apple Client Server Protocol" }, + { 0x0281, "MPLS Unicast" }, + { 0x0283, "MPLS Multicast" }, + { 0x0285, "IEEE p1284.4 standard - data packets" }, + { 0x0287, "ETSI TETRA Network Protocol Type 1" }, + { 0x0289, "Multichannel Flow Treatment Protocol" }, + { 0x2063, "RTP IPHC Compressed TCP No Delta" }, + { 0x2065, "RTP IPHC Context State" }, + { 0x2067, "RTP IPHC Compressed UDP 16" }, + { 0x2069, "RTP IPHC Compressed RTP 16" }, + { 0x4001, "Cray Communications Control Protocol" }, + { 0x4003, "CDPD Mobile Network Registration Protocol" }, + { 0x4005, "Expand accelerator protocol" }, + { 0x4007, "ODSICP NCP" }, + { 0x4009, "DOCSIS DLL" }, + { 0x400B, "Cetacean Network Detection Protocol" }, + { 0x4021, "Stacker LZS" }, + { 0x4023, "RefTek Protocol" }, + { 0x4025, "Fibre Channel" }, + { 0x4027, "EMIT Protocols" }, + { 0x405b, "Vendor-Specific Protocol (VSP)" }, + { 0x8021, "Internet Protocol Control Protocol" }, + { 0x8023, "OSI Network Layer Control Protocol" }, + { 0x8025, "Xerox NS IDP Control Protocol" }, + { 0x8027, "DECnet Phase IV Control Protocol" }, + { 0x8029, "Appletalk Control Protocol" }, + { 0x802b, "Novell IPX Control Protocol" }, + { 0x8031, "Bridging NCP" }, + { 0x8033, "Stream Protocol Control Protocol" }, + { 0x8035, "Banyan Vines Control Protocol" }, + { 0x803d, "Multi-Link Control Protocol" }, + { 0x803f, "NETBIOS Framing Control Protocol" }, + { 0x8041, "Cisco Systems Control Protocol" }, + { 0x8043, "Ascom Timeplex" }, + { 0x8045, "Fujitsu LBLB Control Protocol" }, + { 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" }, + { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" }, + { 0x804b, "SNA over 802.2 Control Protocol" }, + { 0x804d, "SNA Control Protocol" }, + { 0x804f, "IP6 Header Compression Control Protocol" }, + { 0x8051, "KNX Bridging Control Protocol" }, + { 0x8053, "Encryption Control Protocol" }, + { 0x8055, "Individual Link Encryption Control Protocol" }, + { 0x8057, "IPv6 Control Protocol" }, + { 0x8059, "PPP Muxing Control Protocol" }, + { 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" }, + { 0x806f, "Stampede Bridging Control Protocol" }, + { 0x8073, "MP+ Control Protocol" }, + { 0x80c1, "NTCITS IPI Control Protocol" }, + { 0x80fb, "Single Link Compression Control Protocol" }, + { 0x80fd, "Compression Control Protocol" }, + { 0x8207, "Cisco Discovery Protocol Control" }, + { 0x8209, "Netcs Twin Routing" }, + { 0x820b, "STP - Control Protocol" }, + { 0x820d, "EDPCP - Extreme Discovery Protocol Ctrl Prtcl" }, + { 0x8235, "Apple Client Server Protocol Control" }, + { 0x8281, "MPLSCP" }, + { 0x8285, "IEEE p1284.4 standard - Protocol Control" }, + { 0x8287, "ETSI TETRA TNP1 Control Protocol" }, + { 0x8289, "Multichannel Flow Treatment Protocol" }, + { 0xc021, "Link Control Protocol" }, + { 0xc023, "Password Authentication Protocol" }, + { 0xc025, "Link Quality Report" }, + { 0xc027, "Shiva Password Authentication Protocol" }, + { 0xc029, "CallBack Control Protocol (CBCP)" }, + { 0xc02b, "BACP Bandwidth Allocation Control Protocol" }, + { 0xc02d, "BAP" }, + { 0xc05b, "Vendor-Specific Authentication Protocol (VSAP)" }, + { 0xc081, "Container Control Protocol" }, + { 0xc223, "Challenge Handshake Authentication Protocol" }, + { 0xc225, "RSA Authentication Protocol" }, + { 0xc227, "Extensible Authentication Protocol" }, + { 0xc229, "Mitsubishi Security Info Exch Ptcl (SIEP)" }, + { 0xc26f, "Stampede Bridging Authorization Protocol" }, + { 0xc281, "Proprietary Authentication Protocol" }, + { 0xc283, "Proprietary Authentication Protocol" }, + { 0xc481, "Proprietary Node ID Authentication Protocol" }, + { 0, NULL }, +}; + +/* + * protocol_name - find a name for a PPP protocol. + */ +const char * protocol_name(int proto) { + const struct protocol_list *lp; + + for (lp = protocol_list; lp->proto != 0; ++lp) { + if (proto == lp->proto) { + return lp->name; + } + } + return NULL; +} +#endif /* PPP_PROTOCOLNAME */ + +#if PPP_STATS_SUPPORT + +/* ---- Note on PPP Stats support ---- + * + * The one willing link stats support should add the get_ppp_stats() + * to fetch statistics from lwIP. + */ + +/* + * reset_link_stats - "reset" stats when link goes up. + */ +void reset_link_stats(int u) { + if (!get_ppp_stats(u, &old_link_stats)) { + return; + } + gettimeofday(&start_time, NULL); +} + +/* + * update_link_stats - get stats at link termination. + */ +void update_link_stats(int u) { + struct timeval now; + char numbuf[32]; + + if (!get_ppp_stats(u, &link_stats) || gettimeofday(&now, NULL) < 0) { + return; + } + link_connect_time = now.tv_sec - start_time.tv_sec; + link_stats_valid = 1; + + link_stats.bytes_in -= old_link_stats.bytes_in; + link_stats.bytes_out -= old_link_stats.bytes_out; + link_stats.pkts_in -= old_link_stats.pkts_in; + link_stats.pkts_out -= old_link_stats.pkts_out; +} + +void print_link_stats() { + /* + * Print connect time and statistics. + */ + if (link_stats_valid) { + int t = (link_connect_time + 5) / 6; /* 1/10ths of minutes */ + info("Connect time %d.%d minutes.", t/10, t%10); + info("Sent %u bytes, received %u bytes.", link_stats.bytes_out, link_stats.bytes_in); + link_stats_valid = 0; + } +} +#endif /* PPP_STATS_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/pppapi.c b/components/net/lwip-2.0.3/src/netif/ppp/pppapi.c new file mode 100644 index 0000000000..947f7ba8c1 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/pppapi.c @@ -0,0 +1,427 @@ +/** + * @file + * Point To Point Protocol Sequential API module + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "netif/ppp/ppp_opts.h" + +#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/pppapi.h" +#include "lwip/priv/tcpip_priv.h" +#include "netif/ppp/pppoe.h" +#include "netif/ppp/pppol2tp.h" +#include "netif/ppp/pppos.h" + +#if LWIP_MPU_COMPATIBLE +LWIP_MEMPOOL_DECLARE(PPPAPI_MSG, MEMP_NUM_PPP_API_MSG, sizeof(struct pppapi_msg), "PPPAPI_MSG") +#endif + +#define PPPAPI_VAR_REF(name) API_VAR_REF(name) +#define PPPAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct pppapi_msg, name) +#define PPPAPI_VAR_ALLOC(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, ERR_MEM) +#define PPPAPI_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, NULL) +#define PPPAPI_VAR_FREE(name) API_VAR_FREE_POOL(PPPAPI_MSG, name) + +/** + * Call ppp_set_default() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_set_default(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + ppp_set_default(msg->msg.ppp); + return ERR_OK; +} + +/** + * Call ppp_set_default() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_set_default(ppp_pcb *pcb) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + err = tcpip_api_call(pppapi_do_ppp_set_default, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} + + +#if PPP_NOTIFY_PHASE +/** + * Call ppp_set_notify_phase_callback() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_set_notify_phase_callback(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + ppp_set_notify_phase_callback(msg->msg.ppp, msg->msg.msg.setnotifyphasecb.notify_phase_cb); + return ERR_OK; +} + +/** + * Call ppp_set_notify_phase_callback() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + PPPAPI_VAR_REF(msg).msg.msg.setnotifyphasecb.notify_phase_cb = notify_phase_cb; + err = tcpip_api_call(pppapi_do_ppp_set_notify_phase_callback, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} +#endif /* PPP_NOTIFY_PHASE */ + + +#if PPPOS_SUPPORT +/** + * Call pppos_create() inside the tcpip_thread context. + */ +static err_t +pppapi_do_pppos_create(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + msg->msg.ppp = pppos_create(msg->msg.msg.serialcreate.pppif, msg->msg.msg.serialcreate.output_cb, + msg->msg.msg.serialcreate.link_status_cb, msg->msg.msg.serialcreate.ctx_cb); + return ERR_OK; +} + +/** + * Call pppos_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + ppp_pcb* result; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC_RETURN_NULL(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = NULL; + PPPAPI_VAR_REF(msg).msg.msg.serialcreate.pppif = pppif; + PPPAPI_VAR_REF(msg).msg.msg.serialcreate.output_cb = output_cb; + PPPAPI_VAR_REF(msg).msg.msg.serialcreate.link_status_cb = link_status_cb; + PPPAPI_VAR_REF(msg).msg.msg.serialcreate.ctx_cb = ctx_cb; + tcpip_api_call(pppapi_do_pppos_create, &PPPAPI_VAR_REF(msg).call); + result = PPPAPI_VAR_REF(msg).msg.ppp; + PPPAPI_VAR_FREE(msg); + return result; +} +#endif /* PPPOS_SUPPORT */ + + +#if PPPOE_SUPPORT +/** + * Call pppoe_create() inside the tcpip_thread context. + */ +static err_t +pppapi_do_pppoe_create(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + msg->msg.ppp = pppoe_create(msg->msg.msg.ethernetcreate.pppif, msg->msg.msg.ethernetcreate.ethif, + msg->msg.msg.ethernetcreate.service_name, msg->msg.msg.ethernetcreate.concentrator_name, + msg->msg.msg.ethernetcreate.link_status_cb, msg->msg.msg.ethernetcreate.ctx_cb); + return ERR_OK; +} + +/** + * Call pppoe_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, + const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, + void *ctx_cb) +{ + ppp_pcb* result; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC_RETURN_NULL(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = NULL; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.pppif = pppif; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.ethif = ethif; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.service_name = service_name; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.concentrator_name = concentrator_name; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.link_status_cb = link_status_cb; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.ctx_cb = ctx_cb; + tcpip_api_call(pppapi_do_pppoe_create, &PPPAPI_VAR_REF(msg).call); + result = PPPAPI_VAR_REF(msg).msg.ppp; + PPPAPI_VAR_FREE(msg); + return result; +} +#endif /* PPPOE_SUPPORT */ + + +#if PPPOL2TP_SUPPORT +/** + * Call pppol2tp_create() inside the tcpip_thread context. + */ +static err_t +pppapi_do_pppol2tp_create(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + msg->msg.ppp = pppol2tp_create(msg->msg.msg.l2tpcreate.pppif, + msg->msg.msg.l2tpcreate.netif, API_EXPR_REF(msg->msg.msg.l2tpcreate.ipaddr), msg->msg.msg.l2tpcreate.port, +#if PPPOL2TP_AUTH_SUPPORT + msg->msg.msg.l2tpcreate.secret, + msg->msg.msg.l2tpcreate.secret_len, +#else /* PPPOL2TP_AUTH_SUPPORT */ + NULL, + 0, +#endif /* PPPOL2TP_AUTH_SUPPORT */ + msg->msg.msg.l2tpcreate.link_status_cb, msg->msg.msg.l2tpcreate.ctx_cb); + return ERR_OK; +} + +/** + * Call pppol2tp_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + ppp_pcb* result; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC_RETURN_NULL(msg); +#if !PPPOL2TP_AUTH_SUPPORT + LWIP_UNUSED_ARG(secret); + LWIP_UNUSED_ARG(secret_len); +#endif /* !PPPOL2TP_AUTH_SUPPORT */ + + PPPAPI_VAR_REF(msg).msg.ppp = NULL; + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.pppif = pppif; + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.netif = netif; + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.ipaddr = PPPAPI_VAR_REF(ipaddr); + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.port = port; +#if PPPOL2TP_AUTH_SUPPORT + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.secret = secret; + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.secret_len = secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.link_status_cb = link_status_cb; + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.ctx_cb = ctx_cb; + tcpip_api_call(pppapi_do_pppol2tp_create, &PPPAPI_VAR_REF(msg).call); + result = PPPAPI_VAR_REF(msg).msg.ppp; + PPPAPI_VAR_FREE(msg); + return result; +} +#endif /* PPPOL2TP_SUPPORT */ + + +/** + * Call ppp_connect() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_connect(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + return ppp_connect(msg->msg.ppp, msg->msg.msg.connect.holdoff); +} + +/** + * Call ppp_connect() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_connect(ppp_pcb *pcb, u16_t holdoff) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + PPPAPI_VAR_REF(msg).msg.msg.connect.holdoff = holdoff; + err = tcpip_api_call(pppapi_do_ppp_connect, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} + + +#if PPP_SERVER +/** + * Call ppp_listen() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_listen(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + return ppp_listen(msg->msg.ppp); +} + +/** + * Call ppp_listen() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_listen(ppp_pcb *pcb) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + err = tcpip_api_call(pppapi_do_ppp_listen, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} +#endif /* PPP_SERVER */ + + +/** + * Call ppp_close() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_close(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + return ppp_close(msg->msg.ppp, msg->msg.msg.close.nocarrier); +} + +/** + * Call ppp_close() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_close(ppp_pcb *pcb, u8_t nocarrier) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + PPPAPI_VAR_REF(msg).msg.msg.close.nocarrier = nocarrier; + err = tcpip_api_call(pppapi_do_ppp_close, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} + + +/** + * Call ppp_free() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_free(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + return ppp_free(msg->msg.ppp); +} + +/** + * Call ppp_free() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_free(ppp_pcb *pcb) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + err = tcpip_api_call(pppapi_do_ppp_free, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} + + +/** + * Call ppp_ioctl() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_ioctl(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + return ppp_ioctl(msg->msg.ppp, msg->msg.msg.ioctl.cmd, msg->msg.msg.ioctl.arg); +} + +/** + * Call ppp_ioctl() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + PPPAPI_VAR_REF(msg).msg.msg.ioctl.cmd = cmd; + PPPAPI_VAR_REF(msg).msg.msg.ioctl.arg = arg; + err = tcpip_api_call(pppapi_do_ppp_ioctl, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} + +#endif /* LWIP_PPP_API */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/pppcrypt.c b/components/net/lwip-2.0.3/src/netif/ppp/pppcrypt.c new file mode 100644 index 0000000000..82d78c13ac --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/pppcrypt.c @@ -0,0 +1,66 @@ +/* + * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 + * + * Extracted from chap_ms.c by James Carlson. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not necessary */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/pppcrypt.h" + + +static u_char pppcrypt_get_7bits(u_char *input, int startBit) { + unsigned int word; + + word = (unsigned)input[startBit / 8] << 8; + word |= (unsigned)input[startBit / 8 + 1]; + + word >>= 15 - (startBit % 8 + 7); + + return word & 0xFE; +} + +/* IN 56 bit DES key missing parity bits + * OUT 64 bit DES key with parity bits added + */ +void pppcrypt_56_to_64_bit_key(u_char *key, u_char * des_key) { + des_key[0] = pppcrypt_get_7bits(key, 0); + des_key[1] = pppcrypt_get_7bits(key, 7); + des_key[2] = pppcrypt_get_7bits(key, 14); + des_key[3] = pppcrypt_get_7bits(key, 21); + des_key[4] = pppcrypt_get_7bits(key, 28); + des_key[5] = pppcrypt_get_7bits(key, 35); + des_key[6] = pppcrypt_get_7bits(key, 42); + des_key[7] = pppcrypt_get_7bits(key, 49); +} + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/pppoe.c b/components/net/lwip-2.0.3/src/netif/ppp/pppoe.c new file mode 100644 index 0000000000..eabfa4d041 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/pppoe.c @@ -0,0 +1,1191 @@ +/***************************************************************************** +* pppoe.c - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "lwip/timeouts.h" +#include "lwip/memp.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" + +#include "netif/ethernet.h" +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/pppoe.h" + +/* Memory pool */ +LWIP_MEMPOOL_DECLARE(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF") + +/* Add a 16 bit unsigned value to a buffer pointed to by PTR */ +#define PPPOE_ADD_16(PTR, VAL) \ + *(PTR)++ = (u8_t)((VAL) / 256); \ + *(PTR)++ = (u8_t)((VAL) % 256) + +/* Add a complete PPPoE header to the buffer pointed to by PTR */ +#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ + *(PTR)++ = PPPOE_VERTYPE; \ + *(PTR)++ = (CODE); \ + PPPOE_ADD_16(PTR, SESS); \ + PPPOE_ADD_16(PTR, LEN) + +#define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */ +#define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */ +#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ +#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ + +#ifdef PPPOE_SERVER +#error "PPPOE_SERVER is not yet supported under lwIP!" +/* from if_spppsubr.c */ +#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ +#endif + +#define PPPOE_ERRORSTRING_LEN 64 + + +/* callbacks called from PPP core */ +static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); +static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); +static void pppoe_connect(ppp_pcb *ppp, void *ctx); +static void pppoe_disconnect(ppp_pcb *ppp, void *ctx); +static err_t pppoe_destroy(ppp_pcb *ppp, void *ctx); + +/* management routines */ +static void pppoe_abort_connect(struct pppoe_softc *); +#if 0 /* UNUSED */ +static void pppoe_clear_softc(struct pppoe_softc *, const char *); +#endif /* UNUSED */ + +/* internal timeout handling */ +static void pppoe_timeout(void *); + +/* sending actual protocol controll packets */ +static err_t pppoe_send_padi(struct pppoe_softc *); +static err_t pppoe_send_padr(struct pppoe_softc *); +#ifdef PPPOE_SERVER +static err_t pppoe_send_pado(struct pppoe_softc *); +static err_t pppoe_send_pads(struct pppoe_softc *); +#endif +static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); + +/* internal helper functions */ +static err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb); +static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif); +static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif); + +/** linked list of created pppoe interfaces */ +static struct pppoe_softc *pppoe_softc_list; + +/* Callbacks structure for PPP core */ +static const struct link_callbacks pppoe_callbacks = { + pppoe_connect, +#if PPP_SERVER + NULL, +#endif /* PPP_SERVER */ + pppoe_disconnect, + pppoe_destroy, + pppoe_write, + pppoe_netif_output, + NULL, + NULL +}; + +/* + * Create a new PPP Over Ethernet (PPPoE) connection. + * + * Return 0 on success, an error code on failure. + */ +ppp_pcb *pppoe_create(struct netif *pppif, + struct netif *ethif, + const char *service_name, const char *concentrator_name, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + ppp_pcb *ppp; + struct pppoe_softc *sc; + LWIP_UNUSED_ARG(service_name); + LWIP_UNUSED_ARG(concentrator_name); + + sc = (struct pppoe_softc *)LWIP_MEMPOOL_ALLOC(PPPOE_IF); + if (sc == NULL) { + return NULL; + } + + ppp = ppp_new(pppif, &pppoe_callbacks, sc, link_status_cb, ctx_cb); + if (ppp == NULL) { + LWIP_MEMPOOL_FREE(PPPOE_IF, sc); + return NULL; + } + + memset(sc, 0, sizeof(struct pppoe_softc)); + sc->pcb = ppp; + sc->sc_ethif = ethif; + /* put the new interface at the head of the list */ + sc->next = pppoe_softc_list; + pppoe_softc_list = sc; + return ppp; +} + +/* Called by PPP core */ +static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + struct pbuf *ph; /* Ethernet + PPPoE header */ + err_t ret; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + /* skip address & flags */ + pbuf_header(p, -(s16_t)2); + + ph = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); + if(!ph) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(p); + return ERR_MEM; + } + + pbuf_header(ph, -(s16_t)PPPOE_HEADERLEN); /* hide PPPoE header */ + pbuf_cat(ph, p); +#if MIB2_STATS + tot_len = ph->tot_len; +#endif /* MIB2_STATS */ + + ret = pppoe_xmit(sc, ph); + if (ret != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ret; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +/* Called by PPP core */ +static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) { + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + struct pbuf *pb; + u8_t *pl; + err_t err; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + /* @todo: try to use pbuf_header() here! */ + pb = pbuf_alloc(PBUF_LINK, PPPOE_HEADERLEN + sizeof(protocol), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ERR_MEM; + } + + pbuf_header(pb, -(s16_t)PPPOE_HEADERLEN); + + pl = (u8_t*)pb->payload; + PUTSHORT(protocol, pl); + + pbuf_chain(pb, p); +#if MIB2_STATS + tot_len = pb->tot_len; +#endif /* MIB2_STATS */ + + if( (err = pppoe_xmit(sc, pb)) != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return err; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +static err_t +pppoe_destroy(ppp_pcb *ppp, void *ctx) +{ + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + struct pppoe_softc **copp, *freep; + LWIP_UNUSED_ARG(ppp); + + sys_untimeout(pppoe_timeout, sc); + + /* remove interface from list */ + for (copp = &pppoe_softc_list; (freep = *copp); copp = &freep->next) { + if (freep == sc) { + *copp = freep->next; + break; + } + } + +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name) { + mem_free(sc->sc_concentrator_name); + } + if (sc->sc_service_name) { + mem_free(sc->sc_service_name); + } +#endif /* PPPOE_TODO */ + LWIP_MEMPOOL_FREE(PPPOE_IF, sc); + + return ERR_OK; +} + +/* + * Find the interface handling the specified session. + * Note: O(number of sessions open), this is a client-side only, mean + * and lean implementation, so number of open sessions typically should + * be 1. + */ +static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif) { + struct pppoe_softc *sc; + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc->sc_state == PPPOE_STATE_SESSION + && sc->sc_session == session + && sc->sc_ethif == rcvif) { + return sc; + } + } + return NULL; +} + +/* Check host unique token passed and return appropriate softc pointer, + * or NULL if token is bogus. */ +static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) { + struct pppoe_softc *sc, *t; + + if (len != sizeof sc) { + return NULL; + } + MEMCPY(&t, token, len); + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc == t) { + break; + } + } + + if (sc == NULL) { + PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n")); + return NULL; + } + + /* should be safe to access *sc now */ + if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state)); + return NULL; + } + if (sc->sc_ethif != rcvif) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": wrong interface, not accepting host unique\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + return NULL; + } + return sc; +} + +/* analyze and handle a single received packet while not in session state */ +void +pppoe_disc_input(struct netif *netif, struct pbuf *pb) +{ + u16_t tag, len; + u16_t session, plen; + struct pppoe_softc *sc; +#if PPP_DEBUG + const char *err_msg = NULL; +#endif /* PPP_DEBUG */ + u8_t *ac_cookie; + u16_t ac_cookie_len; +#ifdef PPPOE_SERVER + u8_t *hunique; + size_t hunique_len; +#endif + struct pppoehdr *ph; + struct pppoetag pt; + int off, err; + struct eth_hdr *ethhdr; + + /* don't do anything if there is not a single PPPoE instance */ + if (pppoe_softc_list == NULL) { + pbuf_free(pb); + return; + } + + pb = ppp_singlebuf(pb); + + if (pb->len < sizeof(*ethhdr)) { + goto done; + } + ethhdr = (struct eth_hdr *)pb->payload; + off = sizeof(*ethhdr); + + ac_cookie = NULL; + ac_cookie_len = 0; +#ifdef PPPOE_SERVER + hunique = NULL; + hunique_len = 0; +#endif + session = 0; + if (pb->len - off < (u16_t)PPPOE_HEADERLEN) { + PPPDEBUG(LOG_DEBUG, ("pppoe: packet too short: %d\n", pb->len)); + goto done; + } + + ph = (struct pppoehdr *) (ethhdr + 1); + if (ph->vertype != PPPOE_VERTYPE) { + PPPDEBUG(LOG_DEBUG, ("pppoe: unknown version/type packet: 0x%x\n", ph->vertype)); + goto done; + } + session = lwip_ntohs(ph->session); + plen = lwip_ntohs(ph->plen); + off += sizeof(*ph); + + if (plen + off > pb->len) { + PPPDEBUG(LOG_DEBUG, ("pppoe: packet content does not fit: data available = %d, packet size = %u\n", + pb->len - off, plen)); + goto done; + } + if(pb->tot_len == pb->len) { + pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */ + } + tag = 0; + len = 0; + sc = NULL; + while (off + sizeof(pt) <= pb->len) { + MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); + tag = lwip_ntohs(pt.tag); + len = lwip_ntohs(pt.len); + if (off + sizeof(pt) + len > pb->len) { + PPPDEBUG(LOG_DEBUG, ("pppoe: tag 0x%x len 0x%x is too long\n", tag, len)); + goto done; + } + switch (tag) { + case PPPOE_TAG_EOL: + goto breakbreak; + case PPPOE_TAG_SNAME: + break; /* ignored */ + case PPPOE_TAG_ACNAME: + break; /* ignored */ + case PPPOE_TAG_HUNIQUE: + if (sc != NULL) { + break; + } +#ifdef PPPOE_SERVER + hunique = (u8_t*)pb->payload + off + sizeof(pt); + hunique_len = len; +#endif + sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif); + break; + case PPPOE_TAG_ACCOOKIE: + if (ac_cookie == NULL) { + if (len > PPPOE_MAX_AC_COOKIE_LEN) { + PPPDEBUG(LOG_DEBUG, ("pppoe: AC cookie is too long: len = %d, max = %d\n", len, PPPOE_MAX_AC_COOKIE_LEN)); + goto done; + } + ac_cookie = (u8_t*)pb->payload + off + sizeof(pt); + ac_cookie_len = len; + } + break; +#if PPP_DEBUG + case PPPOE_TAG_SNAME_ERR: + err_msg = "SERVICE NAME ERROR"; + break; + case PPPOE_TAG_ACSYS_ERR: + err_msg = "AC SYSTEM ERROR"; + break; + case PPPOE_TAG_GENERIC_ERR: + err_msg = "GENERIC ERROR"; + break; +#endif /* PPP_DEBUG */ + default: + break; + } +#if PPP_DEBUG + if (err_msg != NULL) { + char error_tmp[PPPOE_ERRORSTRING_LEN]; + u16_t error_len = LWIP_MIN(len, sizeof(error_tmp)-1); + strncpy(error_tmp, (char*)pb->payload + off + sizeof(pt), error_len); + error_tmp[error_len] = '\0'; + if (sc) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": %s: %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err_msg, error_tmp)); + } else { + PPPDEBUG(LOG_DEBUG, ("pppoe: %s: %s\n", err_msg, error_tmp)); + } + } +#endif /* PPP_DEBUG */ + off += sizeof(pt) + len; + } + +breakbreak:; + switch (ph->code) { + case PPPOE_CODE_PADI: +#ifdef PPPOE_SERVER + /* + * got service name, concentrator name, and/or host unique. + * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP. + */ + if (LIST_EMPTY(&pppoe_softc_list)) { + goto done; + } + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) { + continue; + } + if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + continue; + } + if (sc->sc_state == PPPOE_STATE_INITIAL) { + break; + } + } + if (sc == NULL) { + /* PPPDEBUG(LOG_DEBUG, ("pppoe: free passive interface is not found\n")); */ + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); + sc->sc_state = PPPOE_STATE_PADO_SENT; + pppoe_send_pado(sc); + break; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADR: +#ifdef PPPOE_SERVER + /* + * get sc from ac_cookie if IFF_PASSIVE + */ + if (ac_cookie == NULL) { + /* be quiet if there is not a single pppoe instance */ + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but not includes ac_cookie\n")); + goto done; + } + sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif); + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (!LIST_EMPTY(&pppoe_softc_list)) { + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but could not find request for it\n")); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + pppoe_send_pads(sc); + sc->sc_state = PPPOE_STATE_SESSION; + ppp_start(sc->pcb); /* notify upper layers */ + break; +#else + /* ignore, we are no access concentrator */ + goto done; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADO: + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (pppoe_softc_list != NULL) { + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADO but could not find request for it\n")); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADI_SENT) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + goto done; + } + if (ac_cookie) { + sc->sc_ac_cookie_len = ac_cookie_len; + MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); + } + MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); + sys_untimeout(pppoe_timeout, sc); + sc->sc_padr_retried = 0; + sc->sc_state = PPPOE_STATE_PADR_SENT; + if ((err = pppoe_send_padr(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + case PPPOE_CODE_PADS: + if (sc == NULL) { + goto done; + } + sc->sc_session = session; + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); + sc->sc_state = PPPOE_STATE_SESSION; + ppp_start(sc->pcb); /* notify upper layers */ + break; + case PPPOE_CODE_PADT: + /* Don't disconnect here, we let the LCP Echo/Reply find the fact + * that PPP session is down. Asking the PPP stack to end the session + * require strict checking about the PPP phase to prevent endless + * disconnection loops. + */ +#if 0 /* UNUSED */ + if (sc == NULL) { /* PADT frames are rarely sent with a hunique tag, this is actually almost always true */ + goto done; + } + pppoe_clear_softc(sc, "received PADT"); +#endif /* UNUSED */ + break; + default: + if(sc) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + (u16_t)ph->code, session)); + } else { + PPPDEBUG(LOG_DEBUG, ("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session)); + } + break; + } + +done: + pbuf_free(pb); + return; +} + +void +pppoe_data_input(struct netif *netif, struct pbuf *pb) +{ + u16_t session, plen; + struct pppoe_softc *sc; + struct pppoehdr *ph; +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + u8_t shost[ETHER_ADDR_LEN]; +#endif + +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost)); +#endif + if (pbuf_header(pb, -(s16_t)sizeof(struct eth_hdr)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + if (pb->len < sizeof(*ph)) { + PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: could not get PPPoE header\n")); + goto drop; + } + ph = (struct pppoehdr *)pb->payload; + + if (ph->vertype != PPPOE_VERTYPE) { + PPPDEBUG(LOG_DEBUG, ("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype)); + goto drop; + } + if (ph->code != 0) { + goto drop; + } + + session = lwip_ntohs(ph->session); + sc = pppoe_find_softc_by_session(session, netif); + if (sc == NULL) { +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + PPPDEBUG(LOG_DEBUG, ("pppoe: input for unknown session 0x%x, sending PADT\n", session)); + pppoe_send_padt(netif, session, shost); +#endif + goto drop; + } + + plen = lwip_ntohs(ph->plen); + + if (pbuf_header(pb, -(s16_t)(PPPOE_HEADERLEN)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + pb->len, plen)); + + if (pb->tot_len < plen) { + goto drop; + } + + /* Dispatch the packet thereby consuming it. */ + ppp_input(sc->pcb, pb); + return; + +drop: + pbuf_free(pb); +} + +static err_t +pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) +{ + struct eth_hdr *ethhdr; + u16_t etype; + err_t res; + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(pb, (s16_t)(sizeof(struct eth_hdr))) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_output: could not allocate room for Ethernet header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + ethhdr = (struct eth_hdr *)pb->payload; + etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; + ethhdr->type = lwip_htons(etype); + MEMCPY(ðhdr->dest.addr, &sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); + MEMCPY(ðhdr->src.addr, &sc->sc_ethif->hwaddr, sizeof(ethhdr->src.addr)); + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, + sc->sc_state, sc->sc_session, + sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5], + pb->tot_len)); + + res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb); + + pbuf_free(pb); + + return res; +} + +static err_t +pppoe_send_padi(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + int len; +#ifdef PPPOE_TODO + int l1 = 0, l2 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + /* calculate length of frame (excluding ethernet header + pppoe header) */ + len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + l1 = (int)strlen(sc->sc_service_name); + len += l1; + } + if (sc->sc_concentrator_name != NULL) { + l2 = (int)strlen(sc->sc_concentrator_name); + len += 2 + 2 + l2; + } +#endif /* PPPOE_TODO */ + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name != NULL) { + PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); + PPPOE_ADD_16(p, l2); + MEMCPY(p, sc->sc_concentrator_name, l2); + p += l2; + } +#endif /* PPPOE_TODO */ + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + /* send pkt */ + return pppoe_output(sc, pb); +} + +static void +pppoe_timeout(void *arg) +{ + u32_t retry_wait; + int err; + struct pppoe_softc *sc = (struct pppoe_softc*)arg; + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + + switch (sc->sc_state) { + case PPPOE_STATE_PADI_SENT: + /* + * We have two basic ways of retrying: + * - Quick retry mode: try a few times in short sequence + * - Slow retry mode: we already had a connection successfully + * established and will try infinitely (without user + * intervention) + * We only enter slow retry mode if IFF_LINK1 (aka autodial) + * is not set. + */ + if (sc->sc_padi_retried < 0xff) { + sc->sc_padi_retried++; + } + if (!sc->pcb->settings.persist && sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { +#if 0 + if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { + /* slow retry mode */ + retry_wait = PPPOE_SLOW_RETRY; + } else +#endif + { + pppoe_abort_connect(sc); + return; + } + } + /* initialize for quick retry mode */ + retry_wait = LWIP_MIN(PPPOE_DISC_TIMEOUT * sc->sc_padi_retried, PPPOE_SLOW_RETRY); + if ((err = pppoe_send_padi(sc)) != 0) { + sc->sc_padi_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(retry_wait, pppoe_timeout, sc); + break; + + case PPPOE_STATE_PADR_SENT: + sc->sc_padr_retried++; + if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_state = PPPOE_STATE_PADI_SENT; + sc->sc_padr_retried = 0; + if ((err = pppoe_send_padi(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); + return; + } + if ((err = pppoe_send_padr(sc)) != 0) { + sc->sc_padr_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + default: + return; /* all done, work in peace */ + } +} + +/* Start a connection (i.e. initiate discovery phase) */ +static void +pppoe_connect(ppp_pcb *ppp, void *ctx) +{ + err_t err; + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + lcp_options *lcp_wo; + lcp_options *lcp_ao; +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_options *ipcp_wo; + ipcp_options *ipcp_ao; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + sc->sc_session = 0; + sc->sc_ac_cookie_len = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; + /* changed to real address later */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); +#ifdef PPPOE_SERVER + /* wait PADI if IFF_PASSIVE */ + if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + return 0; + } +#endif + + lcp_wo = &ppp->lcp_wantoptions; + lcp_wo->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ + lcp_wo->neg_asyncmap = 0; + lcp_wo->neg_pcompression = 0; + lcp_wo->neg_accompression = 0; + lcp_wo->passive = 0; + lcp_wo->silent = 0; + + lcp_ao = &ppp->lcp_allowoptions; + lcp_ao->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ + lcp_ao->neg_asyncmap = 0; + lcp_ao->neg_pcompression = 0; + lcp_ao->neg_accompression = 0; + +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_wo = &ppp->ipcp_wantoptions; + ipcp_wo->neg_vj = 0; + ipcp_wo->old_vj = 0; + + ipcp_ao = &ppp->ipcp_allowoptions; + ipcp_ao->neg_vj = 0; + ipcp_ao->old_vj = 0; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + /* save state, in case we fail to send PADI */ + sc->sc_state = PPPOE_STATE_PADI_SENT; + if ((err = pppoe_send_padi(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); +} + +/* disconnect */ +static void +pppoe_disconnect(ppp_pcb *ppp, void *ctx) +{ + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + if (sc->sc_state == PPPOE_STATE_SESSION) { + pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); + } + + /* stop any timer, disconnect can be called while initiating is in progress */ + sys_untimeout(pppoe_timeout, sc); + sc->sc_state = PPPOE_STATE_INITIAL; +#ifdef PPPOE_SERVER + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + sc->sc_hunique = NULL; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */ + } + sc->sc_hunique_len = 0; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */ +#endif + ppp_link_end(ppp); /* notify upper layers */ + return; +} + +/* Connection attempt aborted */ +static void +pppoe_abort_connect(struct pppoe_softc *sc) +{ + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + sc->sc_state = PPPOE_STATE_INITIAL; + ppp_link_failed(sc->pcb); /* notify upper layers */ +} + +/* Send a PADR packet */ +static err_t +pppoe_send_padr(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; +#ifdef PPPOE_TODO + size_t l1 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } +#endif /* PPPOE_TODO */ + if (sc->sc_ac_cookie_len > 0) { + len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ + } + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } + if (sc->sc_ac_cookie_len > 0) { + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sc->sc_ac_cookie_len); + MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); + p += sc->sc_ac_cookie_len; + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + return pppoe_output(sc, pb); +} + +/* send a PADT packet */ +static err_t +pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) +{ + struct pbuf *pb; + struct eth_hdr *ethhdr; + err_t res; + u8_t *p; + + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + pbuf_header(pb, (s16_t)sizeof(struct eth_hdr)); + ethhdr = (struct eth_hdr *)pb->payload; + ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); + MEMCPY(ðhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); + MEMCPY(ðhdr->src.addr, &outgoing_if->hwaddr, sizeof(ethhdr->src.addr)); + + p = (u8_t*)(ethhdr + 1); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); + + res = outgoing_if->linkoutput(outgoing_if, pb); + + pbuf_free(pb); + + return res; +} + +#ifdef PPPOE_SERVER +static err_t +pppoe_send_pado(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; + + /* calc length */ + len = 0; + /* include ac_cookie */ + len += 2 + 2 + sizeof(sc); + /* include hunique */ + len += 2 + 2 + sc->sc_hunique_len; + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof(sc)); + p += sizeof(sc); + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} + +static err_t +pppoe_send_pads(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len, l1 = 0; /* XXX: gcc */ + + sc->sc_session = mono_time.tv_sec % 0xff + 1; + /* calc length */ + len = 0; + /* include hunique */ + len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else { + PPPOE_ADD_16(p, 0); + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} +#endif + +static err_t +pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) +{ + u8_t *p; + size_t len; + + len = pb->tot_len; + + /* make room for PPPoE header - should not fail */ + if (pbuf_header(pb, (s16_t)(PPPOE_HEADERLEN)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for PPPoE header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); + + return pppoe_output(sc, pb); +} + +#if 0 /*def PFIL_HOOKS*/ +static int +pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir) +{ + struct pppoe_softc *sc; + int s; + + if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { + return 0; + } + + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (sc->sc_ethif != ifp) { + continue; + } + if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { + sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": ethernet interface detached, going down\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + } + sc->sc_ethif = NULL; + pppoe_clear_softc(sc, "ethernet interface detached"); + } + + return 0; +} +#endif + +#if 0 /* UNUSED */ +static void +pppoe_clear_softc(struct pppoe_softc *sc, const char *message) +{ + LWIP_UNUSED_ARG(message); + + /* stop timer */ + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); + sc->sc_state = PPPOE_STATE_INITIAL; + ppp_link_end(sc->pcb); /* notify upper layers - /!\ dangerous /!\ - see pppoe_disc_input() */ +} +#endif /* UNUSED */ +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/pppol2tp.c b/components/net/lwip-2.0.3/src/netif/ppp/pppol2tp.c new file mode 100644 index 0000000000..d44471e25f --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/pppol2tp.c @@ -0,0 +1,1131 @@ +/** + * @file + * Network Point to Point Protocol over Layer 2 Tunneling Protocol program file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +/* + * L2TP Support status: + * + * Supported: + * - L2TPv2 (PPP over L2TP, a.k.a. UDP tunnels) + * - LAC + * + * Not supported: + * - LNS (require PPP server support) + * - L2TPv3 ethernet pseudowires + * - L2TPv3 VLAN pseudowire + * - L2TPv3 PPP pseudowires + * - L2TPv3 IP encapsulation + * - L2TPv3 IP pseudowire + * - L2TP tunnel switching - http://tools.ietf.org/html/draft-ietf-l2tpext-tunnel-switching-08 + * - Multiple tunnels per UDP socket, as well as multiple sessions per tunnel + * - Hidden AVPs + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/err.h" +#include "lwip/memp.h" +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "lwip/snmp.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/pppol2tp.h" +#include "netif/ppp/pppcrypt.h" +#include "netif/ppp/magic.h" + +/* Memory pool */ +LWIP_MEMPOOL_DECLARE(PPPOL2TP_PCB, MEMP_NUM_PPPOL2TP_INTERFACES, sizeof(pppol2tp_pcb), "PPPOL2TP_PCB") + +/* callbacks called from PPP core */ +static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); +static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); +static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx); /* Destroy a L2TP control block */ +static void pppol2tp_connect(ppp_pcb *ppp, void *ctx); /* Be a LAC, connect to a LNS. */ +static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx); /* Disconnect */ + + /* Prototypes for procedures local to this file. */ +static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); +static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr); +static void pppol2tp_timeout(void *arg); +static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp); +static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp); +static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb); +static err_t pppol2tp_udp_send(pppol2tp_pcb *l2tp, struct pbuf *pb); + +/* Callbacks structure for PPP core */ +static const struct link_callbacks pppol2tp_callbacks = { + pppol2tp_connect, +#if PPP_SERVER + NULL, +#endif /* PPP_SERVER */ + pppol2tp_disconnect, + pppol2tp_destroy, + pppol2tp_write, + pppol2tp_netif_output, + NULL, + NULL +}; + + +/* Create a new L2TP session. */ +ppp_pcb *pppol2tp_create(struct netif *pppif, + struct netif *netif, const ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { + ppp_pcb *ppp; + pppol2tp_pcb *l2tp; + struct udp_pcb *udp; +#if !PPPOL2TP_AUTH_SUPPORT + LWIP_UNUSED_ARG(secret); + LWIP_UNUSED_ARG(secret_len); +#endif /* !PPPOL2TP_AUTH_SUPPORT */ + + if (ipaddr == NULL) { + goto ipaddr_check_failed; + } + + l2tp = (pppol2tp_pcb *)LWIP_MEMPOOL_ALLOC(PPPOL2TP_PCB); + if (l2tp == NULL) { + goto memp_malloc_l2tp_failed; + } + + udp = udp_new_ip_type(IP_GET_TYPE(ipaddr)); + if (udp == NULL) { + goto udp_new_failed; + } + udp_recv(udp, pppol2tp_input, l2tp); + + ppp = ppp_new(pppif, &pppol2tp_callbacks, l2tp, link_status_cb, ctx_cb); + if (ppp == NULL) { + goto ppp_new_failed; + } + + memset(l2tp, 0, sizeof(pppol2tp_pcb)); + l2tp->phase = PPPOL2TP_STATE_INITIAL; + l2tp->ppp = ppp; + l2tp->udp = udp; + l2tp->netif = netif; + ip_addr_copy(l2tp->remote_ip, *ipaddr); + l2tp->remote_port = port; +#if PPPOL2TP_AUTH_SUPPORT + l2tp->secret = secret; + l2tp->secret_len = secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + return ppp; + +ppp_new_failed: + udp_remove(udp); +udp_new_failed: + LWIP_MEMPOOL_FREE(PPPOL2TP_PCB, l2tp); +memp_malloc_l2tp_failed: +ipaddr_check_failed: + return NULL; +} + +/* Called by PPP core */ +static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + struct pbuf *ph; /* UDP + L2TP header */ + err_t ret; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + ph = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(PPPOL2TP_OUTPUT_DATA_HEADER_LEN), PBUF_RAM); + if(!ph) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(p); + return ERR_MEM; + } + + pbuf_header(ph, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); /* hide L2TP header */ + pbuf_cat(ph, p); +#if MIB2_STATS + tot_len = ph->tot_len; +#endif /* MIB2_STATS */ + + ret = pppol2tp_xmit(l2tp, ph); + if (ret != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ret; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +/* Called by PPP core */ +static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + struct pbuf *pb; + u8_t *pl; + err_t err; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + /* @todo: try to use pbuf_header() here! */ + pb = pbuf_alloc(PBUF_TRANSPORT, PPPOL2TP_OUTPUT_DATA_HEADER_LEN + sizeof(protocol), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ERR_MEM; + } + + pbuf_header(pb, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); + + pl = (u8_t*)pb->payload; + PUTSHORT(protocol, pl); + + pbuf_chain(pb, p); +#if MIB2_STATS + tot_len = pb->tot_len; +#endif /* MIB2_STATS */ + + if( (err = pppol2tp_xmit(l2tp, pb)) != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return err; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +/* Destroy a L2TP control block */ +static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + LWIP_UNUSED_ARG(ppp); + + sys_untimeout(pppol2tp_timeout, l2tp); + udp_remove(l2tp->udp); + LWIP_MEMPOOL_FREE(PPPOL2TP_PCB, l2tp); + return ERR_OK; +} + +/* Be a LAC, connect to a LNS. */ +static void pppol2tp_connect(ppp_pcb *ppp, void *ctx) { + err_t err; + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + lcp_options *lcp_wo; + lcp_options *lcp_ao; +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_options *ipcp_wo; + ipcp_options *ipcp_ao; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + l2tp->tunnel_port = l2tp->remote_port; + l2tp->our_ns = 0; + l2tp->peer_nr = 0; + l2tp->peer_ns = 0; + l2tp->source_tunnel_id = 0; + l2tp->remote_tunnel_id = 0; + l2tp->source_session_id = 0; + l2tp->remote_session_id = 0; + /* l2tp->*_retried are cleared when used */ + + lcp_wo = &ppp->lcp_wantoptions; + lcp_wo->mru = PPPOL2TP_DEFMRU; + lcp_wo->neg_asyncmap = 0; + lcp_wo->neg_pcompression = 0; + lcp_wo->neg_accompression = 0; + lcp_wo->passive = 0; + lcp_wo->silent = 0; + + lcp_ao = &ppp->lcp_allowoptions; + lcp_ao->mru = PPPOL2TP_DEFMRU; + lcp_ao->neg_asyncmap = 0; + lcp_ao->neg_pcompression = 0; + lcp_ao->neg_accompression = 0; + +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_wo = &ppp->ipcp_wantoptions; + ipcp_wo->neg_vj = 0; + ipcp_wo->old_vj = 0; + + ipcp_ao = &ppp->ipcp_allowoptions; + ipcp_ao->neg_vj = 0; + ipcp_ao->old_vj = 0; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + /* Listen to a random source port, we need to do that instead of using udp_connect() + * because the L2TP LNS might answer with its own random source port (!= 1701) + */ +#if LWIP_IPV6 + if (IP_IS_V6_VAL(l2tp->udp->local_ip)) { + udp_bind(l2tp->udp, IP6_ADDR_ANY, 0); + } else +#endif /* LWIP_IPV6 */ + udp_bind(l2tp->udp, IP_ADDR_ANY, 0); + +#if PPPOL2TP_AUTH_SUPPORT + /* Generate random vector */ + if (l2tp->secret != NULL) { + magic_random_bytes(l2tp->secret_rv, sizeof(l2tp->secret_rv)); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + do { + l2tp->remote_tunnel_id = magic(); + } while(l2tp->remote_tunnel_id == 0); + /* save state, in case we fail to send SCCRQ */ + l2tp->sccrq_retried = 0; + l2tp->phase = PPPOL2TP_STATE_SCCRQ_SENT; + if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); +} + +/* Disconnect */ +static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + + l2tp->our_ns++; + pppol2tp_send_stopccn(l2tp, l2tp->our_ns); + + /* stop any timer, disconnect can be called while initiating is in progress */ + sys_untimeout(pppol2tp_timeout, l2tp); + l2tp->phase = PPPOL2TP_STATE_INITIAL; + ppp_link_end(ppp); /* notify upper layers */ +} + +/* UDP Callback for incoming IPv4 L2TP frames */ +static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; + u16_t hflags, hlen, len=0, tunnel_id=0, session_id=0, ns=0, nr=0, offset=0; + u8_t *inp; + LWIP_UNUSED_ARG(pcb); + + /* we can't unbound a UDP pcb, thus we can still receive UDP frames after the link is closed */ + if (l2tp->phase < PPPOL2TP_STATE_SCCRQ_SENT) { + goto free_and_return; + } + + if (!ip_addr_cmp(&l2tp->remote_ip, addr)) { + goto free_and_return; + } + + /* discard packet if port mismatch, but only if we received a SCCRP */ + if (l2tp->phase > PPPOL2TP_STATE_SCCRQ_SENT && l2tp->tunnel_port != port) { + goto free_and_return; + } + + /* printf("-----------\nL2TP INPUT, %d\n", p->len); */ + + /* L2TP header */ + if (p->len < sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id) ) { + goto packet_too_short; + } + + inp = (u8_t*)p->payload; + GETSHORT(hflags, inp); + + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { + /* check mandatory flags for a control packet */ + if ( (hflags & PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY) != PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for control packet not set\n")); + goto free_and_return; + } + /* check forbidden flags for a control packet */ + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: forbidden header flags for control packet found\n")); + goto free_and_return; + } + } else { + /* check mandatory flags for a data packet */ + if ( (hflags & PPPOL2TP_HEADERFLAG_DATA_MANDATORY) != PPPOL2TP_HEADERFLAG_DATA_MANDATORY) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for data packet not set\n")); + goto free_and_return; + } + } + + /* Expected header size */ + hlen = sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id); + if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { + hlen += sizeof(len); + } + if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { + hlen += sizeof(ns) + sizeof(nr); + } + if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { + hlen += sizeof(offset); + } + if (p->len < hlen) { + goto packet_too_short; + } + + if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { + GETSHORT(len, inp); + if (p->len < len || len < hlen) { + goto packet_too_short; + } + } + GETSHORT(tunnel_id, inp); + GETSHORT(session_id, inp); + if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { + GETSHORT(ns, inp); + GETSHORT(nr, inp); + } + if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { + GETSHORT(offset, inp) + if (offset > 4096) { /* don't be fooled with large offset which might overflow hlen */ + PPPDEBUG(LOG_DEBUG, ("pppol2tp: strange packet received, offset=%d\n", offset)); + goto free_and_return; + } + hlen += offset; + if (p->len < hlen) { + goto packet_too_short; + } + INCPTR(offset, inp); + } + + /* printf("HLEN = %d\n", hlen); */ + + /* skip L2TP header */ + if (pbuf_header(p, -(s16_t)hlen) != 0) { + goto free_and_return; + } + + /* printf("LEN=%d, TUNNEL_ID=%d, SESSION_ID=%d, NS=%d, NR=%d, OFFSET=%d\n", len, tunnel_id, session_id, ns, nr, offset); */ + PPPDEBUG(LOG_DEBUG, ("pppol2tp: input packet, len=%"U16_F", tunnel=%"U16_F", session=%"U16_F", ns=%"U16_F", nr=%"U16_F"\n", + len, tunnel_id, session_id, ns, nr)); + + /* Control packet */ + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { + pppol2tp_dispatch_control_packet(l2tp, port, p, ns, nr); + goto free_and_return; + } + + /* Data packet */ + if(l2tp->phase != PPPOL2TP_STATE_DATA) { + goto free_and_return; + } + if(tunnel_id != l2tp->remote_tunnel_id) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: tunnel ID mismatch, assigned=%d, received=%d\n", l2tp->remote_tunnel_id, tunnel_id)); + goto free_and_return; + } + if(session_id != l2tp->remote_session_id) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: session ID mismatch, assigned=%d, received=%d\n", l2tp->remote_session_id, session_id)); + goto free_and_return; + } + /* + * skip address & flags if necessary + * + * RFC 2661 does not specify whether the PPP frame in the L2TP payload should + * have a HDLC header or not. We handle both cases for compatibility. + */ + if (p->len >= 2) { + GETSHORT(hflags, inp); + if (hflags == 0xff03) { + pbuf_header(p, -(s16_t)2); + } + } + /* Dispatch the packet thereby consuming it. */ + ppp_input(l2tp->ppp, p); + return; + +packet_too_short: + PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); +free_and_return: + pbuf_free(p); +} + +/* L2TP Control packet entry point */ +static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr) { + u8_t *inp; + u16_t avplen, avpflags, vendorid, attributetype, messagetype=0; + err_t err; +#if PPPOL2TP_AUTH_SUPPORT + lwip_md5_context md5_ctx; + u8_t md5_hash[16]; + u8_t challenge_id = 0; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + l2tp->peer_nr = nr; + l2tp->peer_ns = ns; + /* printf("L2TP CTRL INPUT, ns=%d, nr=%d, len=%d\n", ns, nr, p->len); */ + + /* Handle the special case of the ICCN acknowledge */ + if (l2tp->phase == PPPOL2TP_STATE_ICCN_SENT && l2tp->peer_nr > l2tp->our_ns) { + l2tp->phase = PPPOL2TP_STATE_DATA; + } + + /* ZLB packets */ + if (p->tot_len == 0) { + return; + } + + p = ppp_singlebuf(p); + inp = (u8_t*)p->payload; + /* Decode AVPs */ + while (p->len > 0) { + if (p->len < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype) ) { + goto packet_too_short; + } + GETSHORT(avpflags, inp); + avplen = avpflags & PPPOL2TP_AVPHEADERFLAG_LENGTHMASK; + /* printf("AVPLEN = %d\n", avplen); */ + if (p->len < avplen || avplen < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype)) { + goto packet_too_short; + } + GETSHORT(vendorid, inp); + GETSHORT(attributetype, inp); + avplen -= sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype); + + /* Message type must be the first AVP */ + if (messagetype == 0) { + if (attributetype != 0 || vendorid != 0 || avplen != sizeof(messagetype) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: message type must be the first AVP\n")); + return; + } + GETSHORT(messagetype, inp); + /* printf("Message type = %d\n", messagetype); */ + switch(messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + /* Only accept SCCRP packet if we sent a SCCRQ */ + if (l2tp->phase != PPPOL2TP_STATE_SCCRQ_SENT) { + goto send_zlb; + } + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + /* Only accept ICRP packet if we sent a IRCQ */ + if (l2tp->phase != PPPOL2TP_STATE_ICRQ_SENT) { + goto send_zlb; + } + break; + /* Stop Control Connection Notification */ + case PPPOL2TP_MESSAGETYPE_STOPCCN: + pppol2tp_send_zlb(l2tp, l2tp->our_ns); /* Ack the StopCCN before we switch to down state */ + if (l2tp->phase < PPPOL2TP_STATE_DATA) { + pppol2tp_abort_connect(l2tp); + } else if (l2tp->phase == PPPOL2TP_STATE_DATA) { + /* Don't disconnect here, we let the LCP Echo/Reply find the fact + * that PPP session is down. Asking the PPP stack to end the session + * require strict checking about the PPP phase to prevent endless + * disconnection loops. + */ + } + return; + default: + break; + } + goto nextavp; + } + + /* Skip proprietary L2TP extensions */ + if (vendorid != 0) { + goto skipavp; + } + + switch (messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + switch (attributetype) { + case PPPOL2TP_AVPTYPE_TUNNELID: + if (avplen != sizeof(l2tp->source_tunnel_id) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign tunnel ID length check failed\n")); + return; + } + GETSHORT(l2tp->source_tunnel_id, inp); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned tunnel ID %"U16_F"\n", l2tp->source_tunnel_id)); + goto nextavp; +#if PPPOL2TP_AUTH_SUPPORT + case PPPOL2TP_AVPTYPE_CHALLENGE: + if (avplen == 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Challenge length check failed\n")); + return; + } + if (l2tp->secret == NULL) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge from peer and no secret key available\n")); + pppol2tp_abort_connect(l2tp); + return; + } + /* Generate hash of ID, secret, challenge */ + lwip_md5_init(&md5_ctx); + lwip_md5_starts(&md5_ctx); + challenge_id = PPPOL2TP_MESSAGETYPE_SCCCN; + lwip_md5_update(&md5_ctx, &challenge_id, 1); + lwip_md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); + lwip_md5_update(&md5_ctx, inp, avplen); + lwip_md5_finish(&md5_ctx, l2tp->challenge_hash); + lwip_md5_free(&md5_ctx); + l2tp->send_challenge = 1; + goto skipavp; + case PPPOL2TP_AVPTYPE_CHALLENGERESPONSE: + if (avplen != PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Challenge Response length check failed\n")); + return; + } + /* Generate hash of ID, secret, challenge */ + lwip_md5_init(&md5_ctx); + lwip_md5_starts(&md5_ctx); + challenge_id = PPPOL2TP_MESSAGETYPE_SCCRP; + lwip_md5_update(&md5_ctx, &challenge_id, 1); + lwip_md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); + lwip_md5_update(&md5_ctx, l2tp->secret_rv, sizeof(l2tp->secret_rv)); + lwip_md5_finish(&md5_ctx, md5_hash); + lwip_md5_free(&md5_ctx); + if ( memcmp(inp, md5_hash, sizeof(md5_hash)) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge response from peer and secret key do not match\n")); + pppol2tp_abort_connect(l2tp); + return; + } + goto skipavp; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + default: + break; + } + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + switch (attributetype) { + case PPPOL2TP_AVPTYPE_SESSIONID: + if (avplen != sizeof(l2tp->source_session_id) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign session ID length check failed\n")); + return; + } + GETSHORT(l2tp->source_session_id, inp); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned session ID %"U16_F"\n", l2tp->source_session_id)); + goto nextavp; + default: + break; + } + break; + default: + break; + } + +skipavp: + INCPTR(avplen, inp); +nextavp: + /* printf("AVP Found, vendor=%d, attribute=%d, len=%d\n", vendorid, attributetype, avplen); */ + /* next AVP */ + if (pbuf_header(p, -(s16_t)(avplen + sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype)) ) != 0) { + return; + } + } + + switch(messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + do { + l2tp->remote_session_id = magic(); + } while(l2tp->remote_session_id == 0); + l2tp->tunnel_port = port; /* LNS server might have chosen its own local port */ + l2tp->icrq_retried = 0; + l2tp->phase = PPPOL2TP_STATE_ICRQ_SENT; + l2tp->our_ns++; + if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); + } + l2tp->our_ns++; + if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); + } + sys_untimeout(pppol2tp_timeout, l2tp); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + l2tp->iccn_retried = 0; + l2tp->phase = PPPOL2TP_STATE_ICCN_SENT; + l2tp->our_ns++; + ppp_start(l2tp->ppp); /* notify upper layers */ + if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); + } + sys_untimeout(pppol2tp_timeout, l2tp); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + /* Unhandled packet, send ZLB ACK */ + default: + goto send_zlb; + } + return; + +send_zlb: + pppol2tp_send_zlb(l2tp, l2tp->our_ns); + return; +packet_too_short: + PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); +} + +/* L2TP Timeout handler */ +static void pppol2tp_timeout(void *arg) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; + err_t err; + u32_t retry_wait; + + PPPDEBUG(LOG_DEBUG, ("pppol2tp: timeout\n")); + + switch (l2tp->phase) { + case PPPOL2TP_STATE_SCCRQ_SENT: + /* backoff wait */ + if (l2tp->sccrq_retried < 0xff) { + l2tp->sccrq_retried++; + } + if (!l2tp->ppp->settings.persist && l2tp->sccrq_retried >= PPPOL2TP_MAXSCCRQ) { + pppol2tp_abort_connect(l2tp); + return; + } + retry_wait = LWIP_MIN(PPPOL2TP_CONTROL_TIMEOUT * l2tp->sccrq_retried, PPPOL2TP_SLOW_RETRY); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: sccrq_retried=%d\n", l2tp->sccrq_retried)); + if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { + l2tp->sccrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); + } + sys_timeout(retry_wait, pppol2tp_timeout, l2tp); + break; + + case PPPOL2TP_STATE_ICRQ_SENT: + l2tp->icrq_retried++; + if (l2tp->icrq_retried >= PPPOL2TP_MAXICRQ) { + pppol2tp_abort_connect(l2tp); + return; + } + PPPDEBUG(LOG_DEBUG, ("pppol2tp: icrq_retried=%d\n", l2tp->icrq_retried)); + if (l2tp->peer_nr <= l2tp->our_ns -1) { /* the SCCCN was not acknowledged */ + if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns -1)) != 0) { + l2tp->icrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + } + } + if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { + l2tp->icrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + + case PPPOL2TP_STATE_ICCN_SENT: + l2tp->iccn_retried++; + if (l2tp->iccn_retried >= PPPOL2TP_MAXICCN) { + pppol2tp_abort_connect(l2tp); + return; + } + PPPDEBUG(LOG_DEBUG, ("pppol2tp: iccn_retried=%d\n", l2tp->iccn_retried)); + if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { + l2tp->iccn_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + + default: + return; /* all done, work in peace */ + } +} + +/* Connection attempt aborted */ +static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: could not establish connection\n")); + l2tp->phase = PPPOL2TP_STATE_INITIAL; + ppp_link_failed(l2tp->ppp); /* notify upper layers */ +} + +/* Initiate a new tunnel */ +static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +8 +10 +10 +6+sizeof(PPPOL2TP_HOSTNAME)-1 +6+sizeof(PPPOL2TP_VENDORNAME)-1 +8 +8; +#if PPPOL2TP_AUTH_SUPPORT + if (l2tp->secret != NULL) { + len += 6 + sizeof(l2tp->secret_rv); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(0, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(0, p); /* NS Sequence number - to peer */ + PUTSHORT(0, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCRQ, p); /* Attribute value: Message type: SCCRQ */ + + /* AVP - L2TP Version */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_VERSION, p); /* Attribute type: Version */ + PUTSHORT(PPPOL2TP_VERSION, p); /* Attribute value: L2TP Version */ + + /* AVP - Framing capabilities */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES, p); /* Attribute type: Framing capabilities */ + PUTLONG(PPPOL2TP_FRAMINGCAPABILITIES, p); /* Attribute value: Framing capabilities */ + + /* AVP - Bearer capabilities */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_BEARERCAPABILITIES, p); /* Attribute type: Bearer capabilities */ + PUTLONG(PPPOL2TP_BEARERCAPABILITIES, p); /* Attribute value: Bearer capabilities */ + + /* AVP - Host name */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6+sizeof(PPPOL2TP_HOSTNAME)-1, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_HOSTNAME, p); /* Attribute type: Hostname */ + MEMCPY(p, PPPOL2TP_HOSTNAME, sizeof(PPPOL2TP_HOSTNAME)-1); /* Attribute value: Hostname */ + INCPTR(sizeof(PPPOL2TP_HOSTNAME)-1, p); + + /* AVP - Vendor name */ + PUTSHORT(6+sizeof(PPPOL2TP_VENDORNAME)-1, p); /* len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_VENDORNAME, p); /* Attribute type: Vendor name */ + MEMCPY(p, PPPOL2TP_VENDORNAME, sizeof(PPPOL2TP_VENDORNAME)-1); /* Attribute value: Vendor name */ + INCPTR(sizeof(PPPOL2TP_VENDORNAME)-1, p); + + /* AVP - Assign tunnel ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ + PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ + + /* AVP - Receive window size */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE, p); /* Attribute type: Receive window size */ + PUTSHORT(PPPOL2TP_RECEIVEWINDOWSIZE, p); /* Attribute value: Receive window size */ + +#if PPPOL2TP_AUTH_SUPPORT + /* AVP - Challenge */ + if (l2tp->secret != NULL) { + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->secret_rv), p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGE, p); /* Attribute type: Challenge */ + MEMCPY(p, l2tp->secret_rv, sizeof(l2tp->secret_rv)); /* Attribute value: Random vector */ + INCPTR(sizeof(l2tp->secret_rv), p); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Complete tunnel establishment */ +static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8; +#if PPPOL2TP_AUTH_SUPPORT + if (l2tp->send_challenge) { + len += 6 + sizeof(l2tp->challenge_hash); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCCN, p); /* Attribute value: Message type: SCCCN */ + +#if PPPOL2TP_AUTH_SUPPORT + /* AVP - Challenge response */ + if (l2tp->send_challenge) { + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->challenge_hash), p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGERESPONSE, p); /* Attribute type: Challenge response */ + MEMCPY(p, l2tp->challenge_hash, sizeof(l2tp->challenge_hash)); /* Attribute value: Computed challenge */ + INCPTR(sizeof(l2tp->challenge_hash), p); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Initiate a new session */ +static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + u32_t serialnumber; + + /* calculate UDP packet length */ + len = 12 +8 +8 +10; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_ICRQ, p); /* Attribute value: Message type: ICRQ */ + + /* AVP - Assign session ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_SESSIONID, p); /* Attribute type: Session ID */ + PUTSHORT(l2tp->remote_session_id, p); /* Attribute value: Session ID */ + + /* AVP - Call Serial Number */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CALLSERIALNUMBER, p); /* Attribute type: Serial number */ + serialnumber = magic(); + PUTLONG(serialnumber, p); /* Attribute value: Serial number */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Complete tunnel establishment */ +static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +10 +10; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(l2tp->source_session_id, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_ICCN, p); /* Attribute value: Message type: ICCN */ + + /* AVP - Framing type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGTYPE, p); /* Attribute type: Framing type */ + PUTLONG(PPPOL2TP_FRAMINGTYPE, p); /* Attribute value: Framing type */ + + /* AVP - TX Connect speed */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TXCONNECTSPEED, p); /* Attribute type: TX Connect speed */ + PUTLONG(PPPOL2TP_TXCONNECTSPEED, p); /* Attribute value: TX Connect speed */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Send a ZLB ACK packet */ +static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Send a StopCCN packet */ +static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +8 +8; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_STOPCCN, p); /* Attribute value: Message type: StopCCN */ + + /* AVP - Assign tunnel ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ + PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ + + /* AVP - Result code */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_RESULTCODE, p); /* Attribute type: Result code */ + PUTSHORT(PPPOL2TP_RESULTCODE, p); /* Attribute value: Result code */ + + return pppol2tp_udp_send(l2tp, pb); +} + +static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb) { + u8_t *p; + + /* make room for L2TP header - should not fail */ + if (pbuf_header(pb, (s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppol2tp: pppol2tp_pcb: could not allocate room for L2TP header\n")); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + + p = (u8_t*)pb->payload; + PUTSHORT(PPPOL2TP_HEADERFLAG_DATA_MANDATORY, p); + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(l2tp->source_session_id, p); /* Session Id */ + + return pppol2tp_udp_send(l2tp, pb); +} + +static err_t pppol2tp_udp_send(pppol2tp_pcb *l2tp, struct pbuf *pb) { + err_t err; + if (l2tp->netif) { + err = udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port, l2tp->netif); + } else { + err = udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port); + } + pbuf_free(pb); + return err; +} + +#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/pppos.c b/components/net/lwip-2.0.3/src/netif/ppp/pppos.c new file mode 100644 index 0000000000..fb48df4eb8 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/pppos.c @@ -0,0 +1,875 @@ +/** + * @file + * Network Point to Point Protocol over Serial file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "lwip/arch.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/memp.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/priv/tcpip_priv.h" +#include "lwip/api.h" +#include "lwip/ip4.h" /* for ip4_input() */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppos.h" +#include "netif/ppp/vj.h" + +/* Memory pool */ +LWIP_MEMPOOL_DECLARE(PPPOS_PCB, MEMP_NUM_PPPOS_INTERFACES, sizeof(pppos_pcb), "PPPOS_PCB") + +/* callbacks called from PPP core */ +static err_t pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); +static err_t pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol); +static void pppos_connect(ppp_pcb *ppp, void *ctx); +#if PPP_SERVER +static void pppos_listen(ppp_pcb *ppp, void *ctx); +#endif /* PPP_SERVER */ +static void pppos_disconnect(ppp_pcb *ppp, void *ctx); +static err_t pppos_destroy(ppp_pcb *ppp, void *ctx); +static void pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp); +static void pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp); + +/* Prototypes for procedures local to this file. */ +#if PPP_INPROC_IRQ_SAFE +static void pppos_input_callback(void *arg); +#endif /* PPP_INPROC_IRQ_SAFE */ +static void pppos_input_free_current_packet(pppos_pcb *pppos); +static void pppos_input_drop(pppos_pcb *pppos); +static err_t pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs); +static err_t pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs); + +/* Callbacks structure for PPP core */ +static const struct link_callbacks pppos_callbacks = { + pppos_connect, +#if PPP_SERVER + pppos_listen, +#endif /* PPP_SERVER */ + pppos_disconnect, + pppos_destroy, + pppos_write, + pppos_netif_output, + pppos_send_config, + pppos_recv_config +}; + +/* PPP's Asynchronous-Control-Character-Map. The mask array is used + * to select the specific bit for a character. */ +#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & 1 << (c & 0x07)) + +#if PPP_FCS_TABLE +/* + * FCS lookup table as calculated by genfcstab. + */ +static const u16_t fcstab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) +#else /* PPP_FCS_TABLE */ +/* The HDLC polynomial: X**0 + X**5 + X**12 + X**16 (0x8408) */ +#define PPP_FCS_POLYNOMIAL 0x8408 +static u16_t +ppp_get_fcs(u8_t byte) +{ + unsigned int octet; + int bit; + octet = byte; + for (bit = 8; bit-- > 0; ) { + octet = (octet & 0x01) ? ((octet >> 1) ^ PPP_FCS_POLYNOMIAL) : (octet >> 1); + } + return octet & 0xffff; +} +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ ppp_get_fcs(((fcs) ^ (c)) & 0xff)) +#endif /* PPP_FCS_TABLE */ + +/* + * Values for FCS calculations. + */ +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ + +#if PPP_INPROC_IRQ_SAFE +#define PPPOS_DECL_PROTECT(lev) SYS_ARCH_DECL_PROTECT(lev) +#define PPPOS_PROTECT(lev) SYS_ARCH_PROTECT(lev) +#define PPPOS_UNPROTECT(lev) SYS_ARCH_UNPROTECT(lev) +#else +#define PPPOS_DECL_PROTECT(lev) +#define PPPOS_PROTECT(lev) +#define PPPOS_UNPROTECT(lev) +#endif /* PPP_INPROC_IRQ_SAFE */ + + +/* + * Create a new PPP connection using the given serial I/O device. + * + * Return 0 on success, an error code on failure. + */ +ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + pppos_pcb *pppos; + ppp_pcb *ppp; + + pppos = (pppos_pcb *)LWIP_MEMPOOL_ALLOC(PPPOS_PCB); + if (pppos == NULL) { + return NULL; + } + + ppp = ppp_new(pppif, &pppos_callbacks, pppos, link_status_cb, ctx_cb); + if (ppp == NULL) { + LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos); + return NULL; + } + + memset(pppos, 0, sizeof(pppos_pcb)); + pppos->ppp = ppp; + pppos->output_cb = output_cb; + return ppp; +} + +/* Called by PPP core */ +static err_t +pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + u8_t *s; + struct pbuf *nb; + u16_t n; + u16_t fcs_out; + err_t err; + LWIP_UNUSED_ARG(ppp); + + /* Grab an output buffer. */ + nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (nb == NULL) { + PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: alloc fail\n", ppp->netif->num)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(p); + return ERR_MEM; + } + + /* If the link has been idle, we'll send a fresh flag character to + * flush any noise. */ + err = ERR_OK; + if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) { + err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); + } + + /* Load output buffer. */ + fcs_out = PPP_INITFCS; + s = (u8_t*)p->payload; + n = p->len; + while (n-- > 0) { + err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out); + } + + err = pppos_output_last(pppos, err, nb, &fcs_out); + if (err == ERR_OK) { + PPPDEBUG(LOG_INFO, ("pppos_write[%d]: len=%d\n", ppp->netif->num, p->len)); + } else { + PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: output failed len=%d\n", ppp->netif->num, p->len)); + } + pbuf_free(p); + return err; +} + +/* Called by PPP core */ +static err_t +pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + struct pbuf *nb, *p; + u16_t fcs_out; + err_t err; + LWIP_UNUSED_ARG(ppp); + + /* Grab an output buffer. */ + nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (nb == NULL) { + PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: alloc fail\n", ppp->netif->num)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ERR_MEM; + } + + /* If the link has been idle, we'll send a fresh flag character to + * flush any noise. */ + err = ERR_OK; + if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) { + err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); + } + + fcs_out = PPP_INITFCS; + if (!pppos->accomp) { + err = pppos_output_append(pppos, err, nb, PPP_ALLSTATIONS, 1, &fcs_out); + err = pppos_output_append(pppos, err, nb, PPP_UI, 1, &fcs_out); + } + if (!pppos->pcomp || protocol > 0xFF) { + err = pppos_output_append(pppos, err, nb, (protocol >> 8) & 0xFF, 1, &fcs_out); + } + err = pppos_output_append(pppos, err, nb, protocol & 0xFF, 1, &fcs_out); + + /* Load packet. */ + for(p = pb; p; p = p->next) { + u16_t n = p->len; + u8_t *s = (u8_t*)p->payload; + + while (n-- > 0) { + err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out); + } + } + + err = pppos_output_last(pppos, err, nb, &fcs_out); + if (err == ERR_OK) { + PPPDEBUG(LOG_INFO, ("pppos_netif_output[%d]: proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len)); + } else { + PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: output failed proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len)); + } + return err; +} + +static void +pppos_connect(ppp_pcb *ppp, void *ctx) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + PPPOS_DECL_PROTECT(lev); + +#if PPP_INPROC_IRQ_SAFE + /* input pbuf left over from last session? */ + pppos_input_free_current_packet(pppos); +#endif /* PPP_INPROC_IRQ_SAFE */ + + /* reset PPPoS control block to its initial state */ + memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit)); + + /* + * Default the in and out accm so that escape and flag characters + * are always escaped. + */ + pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */ + pppos->out_accm[15] = 0x60; + PPPOS_PROTECT(lev); + pppos->open = 1; + PPPOS_UNPROTECT(lev); + + /* + * Start the connection and handle incoming events (packet or timeout). + */ + PPPDEBUG(LOG_INFO, ("pppos_connect: unit %d: connecting\n", ppp->netif->num)); + ppp_start(ppp); /* notify upper layers */ +} + +#if PPP_SERVER +static void +pppos_listen(ppp_pcb *ppp, void *ctx) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + PPPOS_DECL_PROTECT(lev); + +#if PPP_INPROC_IRQ_SAFE + /* input pbuf left over from last session? */ + pppos_input_free_current_packet(pppos); +#endif /* PPP_INPROC_IRQ_SAFE */ + + /* reset PPPoS control block to its initial state */ + memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit)); + + /* + * Default the in and out accm so that escape and flag characters + * are always escaped. + */ + pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */ + pppos->out_accm[15] = 0x60; + PPPOS_PROTECT(lev); + pppos->open = 1; + PPPOS_UNPROTECT(lev); + + /* + * Wait for something to happen. + */ + PPPDEBUG(LOG_INFO, ("pppos_listen: unit %d: listening\n", ppp->netif->num)); + ppp_start(ppp); /* notify upper layers */ +} +#endif /* PPP_SERVER */ + +static void +pppos_disconnect(ppp_pcb *ppp, void *ctx) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + PPPOS_DECL_PROTECT(lev); + + PPPOS_PROTECT(lev); + pppos->open = 0; + PPPOS_UNPROTECT(lev); + + /* If PPP_INPROC_IRQ_SAFE is used we cannot call + * pppos_input_free_current_packet() here because + * rx IRQ might still call pppos_input(). + */ +#if !PPP_INPROC_IRQ_SAFE + /* input pbuf left ? */ + pppos_input_free_current_packet(pppos); +#endif /* !PPP_INPROC_IRQ_SAFE */ + + ppp_link_end(ppp); /* notify upper layers */ +} + +static err_t +pppos_destroy(ppp_pcb *ppp, void *ctx) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + LWIP_UNUSED_ARG(ppp); + +#if PPP_INPROC_IRQ_SAFE + /* input pbuf left ? */ + pppos_input_free_current_packet(pppos); +#endif /* PPP_INPROC_IRQ_SAFE */ + + LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos); + return ERR_OK; +} + +#if !NO_SYS && !PPP_INPROC_IRQ_SAFE +/** Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. + * + * @param ppp PPP descriptor index, returned by pppos_create() + * @param s received data + * @param l length of received data + */ +err_t +pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l) +{ + struct pbuf *p; + err_t err; + + p = pbuf_alloc(PBUF_RAW, l, PBUF_POOL); + if (!p) { + return ERR_MEM; + } + pbuf_take(p, s, l); + + err = tcpip_inpkt(p, ppp_netif(ppp), pppos_input_sys); + if (err != ERR_OK) { + pbuf_free(p); + } + return err; +} + +/* called from TCPIP thread */ +err_t pppos_input_sys(struct pbuf *p, struct netif *inp) { + ppp_pcb *ppp = (ppp_pcb*)inp->state; + struct pbuf *n; + + for (n = p; n; n = n->next) { + pppos_input(ppp, (u8_t*)n->payload, n->len); + } + pbuf_free(p); + return ERR_OK; +} +#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ + +/** PPPoS input helper struct, must be packed since it is stored + * to pbuf->payload, which might be unaligned. */ +#if PPP_INPROC_IRQ_SAFE +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppos_input_header { + PACK_STRUCT_FIELD(ppp_pcb *ppp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#endif /* PPP_INPROC_IRQ_SAFE */ + +/** Pass received raw characters to PPPoS to be decoded. + * + * @param ppp PPP descriptor index, returned by pppos_create() + * @param s received data + * @param l length of received data + */ +void +pppos_input(ppp_pcb *ppp, u8_t *s, int l) +{ + pppos_pcb *pppos = (pppos_pcb *)ppp->link_ctx_cb; + struct pbuf *next_pbuf; + u8_t cur_char; + u8_t escaped; + PPPOS_DECL_PROTECT(lev); + + PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l)); + while (l-- > 0) { + cur_char = *s++; + + PPPOS_PROTECT(lev); + /* ppp_input can disconnect the interface, we need to abort to prevent a memory + * leak if there are remaining bytes because pppos_connect and pppos_listen + * functions expect input buffer to be free. Furthermore there are no real + * reason to continue reading bytes if we are disconnected. + */ + if (!pppos->open) { + PPPOS_UNPROTECT(lev); + return; + } + escaped = ESCAPE_P(pppos->in_accm, cur_char); + PPPOS_UNPROTECT(lev); + /* Handle special characters. */ + if (escaped) { + /* Check for escape sequences. */ + /* XXX Note that this does not handle an escaped 0x5d character which + * would appear as an escape character. Since this is an ASCII ']' + * and there is no reason that I know of to escape it, I won't complicate + * the code to handle this case. GLL */ + if (cur_char == PPP_ESCAPE) { + pppos->in_escaped = 1; + /* Check for the flag character. */ + } else if (cur_char == PPP_FLAG) { + /* If this is just an extra flag character, ignore it. */ + if (pppos->in_state <= PDADDRESS) { + /* ignore it */; + /* If we haven't received the packet header, drop what has come in. */ + } else if (pppos->in_state < PDDATA) { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Dropping incomplete packet %d\n", + ppp->netif->num, pppos->in_state)); + LINK_STATS_INC(link.lenerr); + pppos_input_drop(pppos); + /* If the fcs is invalid, drop the packet. */ + } else if (pppos->in_fcs != PPP_GOODFCS) { + PPPDEBUG(LOG_INFO, + ("pppos_input[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", + ppp->netif->num, pppos->in_fcs, pppos->in_protocol)); + /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ + LINK_STATS_INC(link.chkerr); + pppos_input_drop(pppos); + /* Otherwise it's a good packet so pass it on. */ + } else { + struct pbuf *inp; + /* Trim off the checksum. */ + if(pppos->in_tail->len > 2) { + pppos->in_tail->len -= 2; + + pppos->in_tail->tot_len = pppos->in_tail->len; + if (pppos->in_tail != pppos->in_head) { + pbuf_cat(pppos->in_head, pppos->in_tail); + } + } else { + pppos->in_tail->tot_len = pppos->in_tail->len; + if (pppos->in_tail != pppos->in_head) { + pbuf_cat(pppos->in_head, pppos->in_tail); + } + + pbuf_realloc(pppos->in_head, pppos->in_head->tot_len - 2); + } + + /* Dispatch the packet thereby consuming it. */ + inp = pppos->in_head; + /* Packet consumed, release our references. */ + pppos->in_head = NULL; + pppos->in_tail = NULL; +#if IP_FORWARD || LWIP_IPV6_FORWARD + /* hide the room for Ethernet forwarding header */ + pbuf_header(inp, -(s16_t)(PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN)); +#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ +#if PPP_INPROC_IRQ_SAFE + if(tcpip_callback_with_block(pppos_input_callback, inp, 0) != ERR_OK) { + PPPDEBUG(LOG_ERR, ("pppos_input[%d]: tcpip_callback() failed, dropping packet\n", ppp->netif->num)); + pbuf_free(inp); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards); + } +#else /* PPP_INPROC_IRQ_SAFE */ + ppp_input(ppp, inp); +#endif /* PPP_INPROC_IRQ_SAFE */ + } + + /* Prepare for a new packet. */ + pppos->in_fcs = PPP_INITFCS; + pppos->in_state = PDADDRESS; + pppos->in_escaped = 0; + /* Other characters are usually control characters that may have + * been inserted by the physical layer so here we just drop them. */ + } else { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Dropping ACCM char <%d>\n", ppp->netif->num, cur_char)); + } + /* Process other characters. */ + } else { + /* Unencode escaped characters. */ + if (pppos->in_escaped) { + pppos->in_escaped = 0; + cur_char ^= PPP_TRANS; + } + + /* Process character relative to current state. */ + switch(pppos->in_state) { + case PDIDLE: /* Idle state - waiting. */ + /* Drop the character if it's not 0xff + * we would have processed a flag character above. */ + if (cur_char != PPP_ALLSTATIONS) { + break; + } + /* no break */ + /* Fall through */ + + case PDSTART: /* Process start flag. */ + /* Prepare for a new packet. */ + pppos->in_fcs = PPP_INITFCS; + /* no break */ + /* Fall through */ + + case PDADDRESS: /* Process address field. */ + if (cur_char == PPP_ALLSTATIONS) { + pppos->in_state = PDCONTROL; + break; + } + /* no break */ + + /* Else assume compressed address and control fields so + * fall through to get the protocol... */ + case PDCONTROL: /* Process control field. */ + /* If we don't get a valid control code, restart. */ + if (cur_char == PPP_UI) { + pppos->in_state = PDPROTOCOL1; + break; + } + /* no break */ + +#if 0 + else { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Invalid control <%d>\n", ppp->netif->num, cur_char)); + pppos->in_state = PDSTART; + } +#endif + case PDPROTOCOL1: /* Process protocol field 1. */ + /* If the lower bit is set, this is the end of the protocol + * field. */ + if (cur_char & 1) { + pppos->in_protocol = cur_char; + pppos->in_state = PDDATA; + } else { + pppos->in_protocol = (u16_t)cur_char << 8; + pppos->in_state = PDPROTOCOL2; + } + break; + case PDPROTOCOL2: /* Process protocol field 2. */ + pppos->in_protocol |= cur_char; + pppos->in_state = PDDATA; + break; + case PDDATA: /* Process data byte. */ + /* Make space to receive processed data. */ + if (pppos->in_tail == NULL || pppos->in_tail->len == PBUF_POOL_BUFSIZE) { + u16_t pbuf_alloc_len; + if (pppos->in_tail != NULL) { + pppos->in_tail->tot_len = pppos->in_tail->len; + if (pppos->in_tail != pppos->in_head) { + pbuf_cat(pppos->in_head, pppos->in_tail); + /* give up the in_tail reference now */ + pppos->in_tail = NULL; + } + } + /* If we haven't started a packet, we need a packet header. */ + pbuf_alloc_len = 0; +#if IP_FORWARD || LWIP_IPV6_FORWARD + /* If IP forwarding is enabled we are reserving PBUF_LINK_ENCAPSULATION_HLEN + * + PBUF_LINK_HLEN bytes so the packet is being allocated with enough header + * space to be forwarded (to Ethernet for example). + */ + if (pppos->in_head == NULL) { + pbuf_alloc_len = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; + } +#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ + next_pbuf = pbuf_alloc(PBUF_RAW, pbuf_alloc_len, PBUF_POOL); + if (next_pbuf == NULL) { + /* No free buffers. Drop the input packet and let the + * higher layers deal with it. Continue processing + * the received pbuf chain in case a new packet starts. */ + PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", ppp->netif->num)); + LINK_STATS_INC(link.memerr); + pppos_input_drop(pppos); + pppos->in_state = PDSTART; /* Wait for flag sequence. */ + break; + } + if (pppos->in_head == NULL) { + u8_t *payload = ((u8_t*)next_pbuf->payload) + pbuf_alloc_len; +#if PPP_INPROC_IRQ_SAFE + ((struct pppos_input_header*)payload)->ppp = ppp; + payload += sizeof(struct pppos_input_header); + next_pbuf->len += sizeof(struct pppos_input_header); +#endif /* PPP_INPROC_IRQ_SAFE */ + next_pbuf->len += sizeof(pppos->in_protocol); + *(payload++) = pppos->in_protocol >> 8; + *(payload) = pppos->in_protocol & 0xFF; + pppos->in_head = next_pbuf; + } + pppos->in_tail = next_pbuf; + } + /* Load character into buffer. */ + ((u8_t*)pppos->in_tail->payload)[pppos->in_tail->len++] = cur_char; + break; + default: + break; + } + + /* update the frame check sequence number. */ + pppos->in_fcs = PPP_FCS(pppos->in_fcs, cur_char); + } + } /* while (l-- > 0), all bytes processed */ +} + +#if PPP_INPROC_IRQ_SAFE +/* PPPoS input callback using one input pointer + */ +static void pppos_input_callback(void *arg) { + struct pbuf *pb = (struct pbuf*)arg; + ppp_pcb *ppp; + + ppp = ((struct pppos_input_header*)pb->payload)->ppp; + if(pbuf_header(pb, -(s16_t)sizeof(struct pppos_input_header))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } + + /* Dispatch the packet thereby consuming it. */ + ppp_input(ppp, pb); + return; + +drop: + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards); + pbuf_free(pb); +} +#endif /* PPP_INPROC_IRQ_SAFE */ + +static void +pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp) +{ + int i; + pppos_pcb *pppos = (pppos_pcb *)ctx; + LWIP_UNUSED_ARG(ppp); + + pppos->pcomp = pcomp; + pppos->accomp = accomp; + + /* Load the ACCM bits for the 32 control codes. */ + for (i = 0; i < 32/8; i++) { + pppos->out_accm[i] = (u8_t)((accm >> (8 * i)) & 0xFF); + } + + PPPDEBUG(LOG_INFO, ("pppos_send_config[%d]: out_accm=%X %X %X %X\n", + pppos->ppp->netif->num, + pppos->out_accm[0], pppos->out_accm[1], pppos->out_accm[2], pppos->out_accm[3])); +} + +static void +pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp) +{ + int i; + pppos_pcb *pppos = (pppos_pcb *)ctx; + PPPOS_DECL_PROTECT(lev); + LWIP_UNUSED_ARG(ppp); + LWIP_UNUSED_ARG(pcomp); + LWIP_UNUSED_ARG(accomp); + + /* Load the ACCM bits for the 32 control codes. */ + PPPOS_PROTECT(lev); + for (i = 0; i < 32 / 8; i++) { + pppos->in_accm[i] = (u8_t)(accm >> (i * 8)); + } + PPPOS_UNPROTECT(lev); + + PPPDEBUG(LOG_INFO, ("pppos_recv_config[%d]: in_accm=%X %X %X %X\n", + pppos->ppp->netif->num, + pppos->in_accm[0], pppos->in_accm[1], pppos->in_accm[2], pppos->in_accm[3])); +} + +/* + * Drop the input packet. + */ +static void +pppos_input_free_current_packet(pppos_pcb *pppos) +{ + if (pppos->in_head != NULL) { + if (pppos->in_tail && (pppos->in_tail != pppos->in_head)) { + pbuf_free(pppos->in_tail); + } + pbuf_free(pppos->in_head); + pppos->in_head = NULL; + } + pppos->in_tail = NULL; +} + +/* + * Drop the input packet and increase error counters. + */ +static void +pppos_input_drop(pppos_pcb *pppos) +{ + if (pppos->in_head != NULL) { +#if 0 + PPPDEBUG(LOG_INFO, ("pppos_input_drop: %d:%.*H\n", pppos->in_head->len, min(60, pppos->in_head->len * 2), pppos->in_head->payload)); +#endif + PPPDEBUG(LOG_INFO, ("pppos_input_drop: pbuf len=%d, addr %p\n", pppos->in_head->len, (void*)pppos->in_head)); + } + pppos_input_free_current_packet(pppos); +#if VJ_SUPPORT + vj_uncompress_err(&pppos->ppp->vj_comp); +#endif /* VJ_SUPPORT */ + + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(pppos->ppp->netif, ifindiscards); +} + +/* + * pppos_output_append - append given character to end of given pbuf. + * If out_accm is not 0 and the character needs to be escaped, do so. + * If pbuf is full, send the pbuf and reuse it. + * Return the current pbuf. + */ +static err_t +pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs) +{ + if (err != ERR_OK) { + return err; + } + + /* Make sure there is room for the character and an escape code. + * Sure we don't quite fill the buffer if the character doesn't + * get escaped but is one character worth complicating this? */ + if ((PBUF_POOL_BUFSIZE - nb->len) < 2) { + u32_t l = pppos->output_cb(pppos->ppp, (u8_t*)nb->payload, nb->len, pppos->ppp->ctx_cb); + if (l != nb->len) { + return ERR_IF; + } + nb->len = 0; + } + + /* Update FCS before checking for special characters. */ + if (fcs) { + *fcs = PPP_FCS(*fcs, c); + } + + /* Copy to output buffer escaping special characters. */ + if (accm && ESCAPE_P(pppos->out_accm, c)) { + *((u8_t*)nb->payload + nb->len++) = PPP_ESCAPE; + *((u8_t*)nb->payload + nb->len++) = c ^ PPP_TRANS; + } else { + *((u8_t*)nb->payload + nb->len++) = c; + } + + return ERR_OK; +} + +static err_t +pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs) +{ + ppp_pcb *ppp = pppos->ppp; + + /* Add FCS and trailing flag. */ + err = pppos_output_append(pppos, err, nb, ~(*fcs) & 0xFF, 1, NULL); + err = pppos_output_append(pppos, err, nb, (~(*fcs) >> 8) & 0xFF, 1, NULL); + err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); + + if (err != ERR_OK) { + goto failed; + } + + /* Send remaining buffer if not empty */ + if (nb->len > 0) { + u32_t l = pppos->output_cb(ppp, (u8_t*)nb->payload, nb->len, ppp->ctx_cb); + if (l != nb->len) { + err = ERR_IF; + goto failed; + } + } + + pppos->last_xmit = sys_now(); + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, nb->tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + pbuf_free(nb); + return ERR_OK; + +failed: + pppos->last_xmit = 0; /* prepend PPP_FLAG to next packet */ + LINK_STATS_INC(link.err); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(nb); + return err; +} + +#endif /* PPP_SUPPORT && PPPOS_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/upap.c b/components/net/lwip-2.0.3/src/netif/ppp/upap.c new file mode 100644 index 0000000000..d00c2d76e5 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/upap.c @@ -0,0 +1,677 @@ +/* + * upap.c - User/Password Authentication Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * @todo: + */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/upap.h" + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t pap_option_list[] = { + { "hide-password", o_bool, &hide_password, + "Don't output passwords to log", OPT_PRIO | 1 }, + { "show-password", o_bool, &hide_password, + "Show password string in debug log messages", OPT_PRIOSUB | 0 }, + + { "pap-restart", o_int, &upap[0].us_timeouttime, + "Set retransmit timeout for PAP", OPT_PRIO }, + { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, + "Set max number of transmissions for auth-reqs", OPT_PRIO }, + { "pap-timeout", o_int, &upap[0].us_reqtimeout, + "Set time limit for peer PAP authentication", OPT_PRIO }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points. + */ +static void upap_init(ppp_pcb *pcb); +static void upap_lowerup(ppp_pcb *pcb); +static void upap_lowerdown(ppp_pcb *pcb); +static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l); +static void upap_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent pap_protent = { + PPP_PAP, + upap_init, + upap_input, + upap_protrej, + upap_lowerup, + upap_lowerdown, + NULL, + NULL, +#if PRINTPKT_SUPPORT + upap_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "PAP", + NULL, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + pap_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +static void upap_timeout(void *arg); +#if PPP_SERVER +static void upap_reqtimeout(void *arg); +static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len); +#endif /* PPP_SERVER */ +static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len); +static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len); +static void upap_sauthreq(ppp_pcb *pcb); +#if PPP_SERVER +static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen); +#endif /* PPP_SERVER */ + + +/* + * upap_init - Initialize a UPAP unit. + */ +static void upap_init(ppp_pcb *pcb) { + pcb->upap.us_user = NULL; + pcb->upap.us_userlen = 0; + pcb->upap.us_passwd = NULL; + pcb->upap.us_passwdlen = 0; + pcb->upap.us_clientstate = UPAPCS_INITIAL; +#if PPP_SERVER + pcb->upap.us_serverstate = UPAPSS_INITIAL; +#endif /* PPP_SERVER */ + pcb->upap.us_id = 0; +} + + +/* + * upap_authwithpeer - Authenticate us with our peer (start client). + * + * Set new state and send authenticate's. + */ +void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) { + + if(!user || !password) + return; + + /* Save the username and password we're given */ + pcb->upap.us_user = user; + pcb->upap.us_userlen = LWIP_MIN(strlen(user), 0xff); + pcb->upap.us_passwd = password; + pcb->upap.us_passwdlen = LWIP_MIN(strlen(password), 0xff); + pcb->upap.us_transmits = 0; + + /* Lower layer up yet? */ + if (pcb->upap.us_clientstate == UPAPCS_INITIAL || + pcb->upap.us_clientstate == UPAPCS_PENDING) { + pcb->upap.us_clientstate = UPAPCS_PENDING; + return; + } + + upap_sauthreq(pcb); /* Start protocol */ +} + +#if PPP_SERVER +/* + * upap_authpeer - Authenticate our peer (start server). + * + * Set new state. + */ +void upap_authpeer(ppp_pcb *pcb) { + + /* Lower layer up yet? */ + if (pcb->upap.us_serverstate == UPAPSS_INITIAL || + pcb->upap.us_serverstate == UPAPSS_PENDING) { + pcb->upap.us_serverstate = UPAPSS_PENDING; + return; + } + + pcb->upap.us_serverstate = UPAPSS_LISTEN; + if (pcb->settings.pap_req_timeout > 0) + TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); +} +#endif /* PPP_SERVER */ + +/* + * upap_timeout - Retransmission timer for sending auth-reqs expired. + */ +static void upap_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) + return; + + if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) { + /* give up in disgust */ + ppp_error("No response to PAP authenticate-requests"); + pcb->upap.us_clientstate = UPAPCS_BADAUTH; + auth_withpeer_fail(pcb, PPP_PAP); + return; + } + + upap_sauthreq(pcb); /* Send Authenticate-Request */ +} + + +#if PPP_SERVER +/* + * upap_reqtimeout - Give up waiting for the peer to send an auth-req. + */ +static void upap_reqtimeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->upap.us_serverstate != UPAPSS_LISTEN) + return; /* huh?? */ + + auth_peer_fail(pcb, PPP_PAP); + pcb->upap.us_serverstate = UPAPSS_BADAUTH; +} +#endif /* PPP_SERVER */ + + +/* + * upap_lowerup - The lower layer is up. + * + * Start authenticating if pending. + */ +static void upap_lowerup(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_INITIAL) + pcb->upap.us_clientstate = UPAPCS_CLOSED; + else if (pcb->upap.us_clientstate == UPAPCS_PENDING) { + upap_sauthreq(pcb); /* send an auth-request */ + } + +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_INITIAL) + pcb->upap.us_serverstate = UPAPSS_CLOSED; + else if (pcb->upap.us_serverstate == UPAPSS_PENDING) { + pcb->upap.us_serverstate = UPAPSS_LISTEN; + if (pcb->settings.pap_req_timeout > 0) + TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); + } +#endif /* PPP_SERVER */ +} + + +/* + * upap_lowerdown - The lower layer is down. + * + * Cancel all timeouts. + */ +static void upap_lowerdown(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */ + UNTIMEOUT(upap_timeout, pcb); /* Cancel timeout */ +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0) + UNTIMEOUT(upap_reqtimeout, pcb); +#endif /* PPP_SERVER */ + + pcb->upap.us_clientstate = UPAPCS_INITIAL; +#if PPP_SERVER + pcb->upap.us_serverstate = UPAPSS_INITIAL; +#endif /* PPP_SERVER */ +} + + +/* + * upap_protrej - Peer doesn't speak this protocol. + * + * This shouldn't happen. In any case, pretend lower layer went down. + */ +static void upap_protrej(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) { + ppp_error("PAP authentication failed due to protocol-reject"); + auth_withpeer_fail(pcb, PPP_PAP); + } +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_LISTEN) { + ppp_error("PAP authentication of peer failed (protocol-reject)"); + auth_peer_fail(pcb, PPP_PAP); + } +#endif /* PPP_SERVER */ + upap_lowerdown(pcb); +} + + +/* + * upap_input - Input UPAP packet. + */ +static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) { + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (l < UPAP_HEADERLEN) { + UPAPDEBUG(("pap_input: rcvd short header.")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < UPAP_HEADERLEN) { + UPAPDEBUG(("pap_input: rcvd illegal length.")); + return; + } + if (len > l) { + UPAPDEBUG(("pap_input: rcvd short packet.")); + return; + } + len -= UPAP_HEADERLEN; + + /* + * Action depends on code. + */ + switch (code) { + case UPAP_AUTHREQ: +#if PPP_SERVER + upap_rauthreq(pcb, inp, id, len); +#endif /* PPP_SERVER */ + break; + + case UPAP_AUTHACK: + upap_rauthack(pcb, inp, id, len); + break; + + case UPAP_AUTHNAK: + upap_rauthnak(pcb, inp, id, len); + break; + + default: /* XXX Need code reject */ + break; + } +} + +#if PPP_SERVER +/* + * upap_rauth - Receive Authenticate. + */ +static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char ruserlen, rpasswdlen; + char *ruser; + char *rpasswd; + char rhostname[256]; + int retcode; + const char *msg; + int msglen; + + if (pcb->upap.us_serverstate < UPAPSS_LISTEN) + return; + + /* + * If we receive a duplicate authenticate-request, we are + * supposed to return the same status as for the first request. + */ + if (pcb->upap.us_serverstate == UPAPSS_OPEN) { + upap_sresp(pcb, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ + return; + } + if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) { + upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ + return; + } + + /* + * Parse user/passwd. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + GETCHAR(ruserlen, inp); + len -= sizeof (u_char) + ruserlen + sizeof (u_char); + if (len < 0) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + ruser = (char *) inp; + INCPTR(ruserlen, inp); + GETCHAR(rpasswdlen, inp); + if (len < rpasswdlen) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + + rpasswd = (char *) inp; + + /* + * Check the username and password given. + */ + retcode = UPAP_AUTHNAK; + if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) { + retcode = UPAP_AUTHACK; + } + BZERO(rpasswd, rpasswdlen); + +#if 0 /* UNUSED */ + /* + * Check remote number authorization. A plugin may have filled in + * the remote number or added an allowed number, and rather than + * return an authenticate failure, is leaving it for us to verify. + */ + if (retcode == UPAP_AUTHACK) { + if (!auth_number()) { + /* We do not want to leak info about the pap result. */ + retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */ + warn("calling number %q is not authorized", remote_number); + } + } + + msglen = strlen(msg); + if (msglen > 255) + msglen = 255; +#endif /* UNUSED */ + + upap_sresp(pcb, retcode, id, msg, msglen); + + /* Null terminate and clean remote name. */ + ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser); + + if (retcode == UPAP_AUTHACK) { + pcb->upap.us_serverstate = UPAPSS_OPEN; + ppp_notice("PAP peer authentication succeeded for %q", rhostname); + auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen); + } else { + pcb->upap.us_serverstate = UPAPSS_BADAUTH; + ppp_warn("PAP peer authentication failed for %q", rhostname); + auth_peer_fail(pcb, PPP_PAP); + } + + if (pcb->settings.pap_req_timeout > 0) + UNTIMEOUT(upap_reqtimeout, pcb); +} +#endif /* PPP_SERVER */ + +/* + * upap_rauthack - Receive Authenticate-Ack. + */ +static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char msglen; + char *msg; + LWIP_UNUSED_ARG(id); + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ + return; + + /* + * Parse message. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauthack: ignoring missing msg-length.")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(("pap_rauthack: rcvd short packet.")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + + pcb->upap.us_clientstate = UPAPCS_OPEN; + + auth_withpeer_success(pcb, PPP_PAP, 0); +} + + +/* + * upap_rauthnak - Receive Authenticate-Nak. + */ +static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char msglen; + char *msg; + LWIP_UNUSED_ARG(id); + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ + return; + + /* + * Parse message. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length.")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(("pap_rauthnak: rcvd short packet.")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + + pcb->upap.us_clientstate = UPAPCS_BADAUTH; + + ppp_error("PAP authentication failed"); + auth_withpeer_fail(pcb, PPP_PAP); +} + + +/* + * upap_sauthreq - Send an Authenticate-Request. + */ +static void upap_sauthreq(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + + pcb->upap.us_userlen + pcb->upap.us_passwdlen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(UPAP_AUTHREQ, outp); + PUTCHAR(++pcb->upap.us_id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(pcb->upap.us_userlen, outp); + MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen); + INCPTR(pcb->upap.us_userlen, outp); + PUTCHAR(pcb->upap.us_passwdlen, outp); + MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen); + + ppp_write(pcb, p); + + TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time); + ++pcb->upap.us_transmits; + pcb->upap.us_clientstate = UPAPCS_AUTHREQ; +} + +#if PPP_SERVER +/* + * upap_sresp - Send a response (ack or nak). + */ +static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) { + struct pbuf *p; + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(msglen, outp); + MEMCPY(outp, msg, msglen); + + ppp_write(pcb, p); +} +#endif /* PPP_SERVER */ + +#if PRINTPKT_SUPPORT +/* + * upap_printpkt - print the contents of a PAP packet. + */ +static const char* const upap_codenames[] = { + "AuthReq", "AuthAck", "AuthNak" +}; + +static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len; + int mlen, ulen, wlen; + const u_char *user, *pwd, *msg; + const u_char *pstart; + + if (plen < UPAP_HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < UPAP_HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(upap_codenames)) + printer(arg, " %s", upap_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= UPAP_HEADERLEN; + switch (code) { + case UPAP_AUTHREQ: + if (len < 1) + break; + ulen = p[0]; + if (len < ulen + 2) + break; + wlen = p[ulen + 1]; + if (len < ulen + wlen + 2) + break; + user = (const u_char *) (p + 1); + pwd = (const u_char *) (p + ulen + 2); + p += ulen + wlen + 2; + len -= ulen + wlen + 2; + printer(arg, " user="); + ppp_print_string(user, ulen, printer, arg); + printer(arg, " password="); +/* FIXME: require ppp_pcb struct as printpkt() argument */ +#if 0 + if (!pcb->settings.hide_password) +#endif + ppp_print_string(pwd, wlen, printer, arg); +#if 0 + else + printer(arg, ""); +#endif + break; + case UPAP_AUTHACK: + case UPAP_AUTHNAK: + if (len < 1) + break; + mlen = p[0]; + if (len < mlen + 1) + break; + msg = (const u_char *) (p + 1); + p += mlen + 1; + len -= mlen + 1; + printer(arg, " "); + ppp_print_string(msg, mlen, printer, arg); + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/utils.c b/components/net/lwip-2.0.3/src/netif/ppp/utils.c new file mode 100644 index 0000000000..008c63375a --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/utils.c @@ -0,0 +1,959 @@ +/* + * utils.c - various utility functions used in pppd. + * + * Copyright (c) 1999-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SVR4 +#include +#endif +#endif /* UNUSED */ + +#include /* isdigit() */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" + +#if defined(SUNOS4) +extern char *strerror(); +#endif + +static void ppp_logit(int level, const char *fmt, va_list args); +static void ppp_log_write(int level, char *buf); +#if PRINTPKT_SUPPORT +static void ppp_vslp_printer(void *arg, const char *fmt, ...); +static void ppp_format_packet(const u_char *p, int len, + void (*printer) (void *, const char *, ...), void *arg); + +struct buffer_info { + char *ptr; + int len; +}; +#endif /* PRINTPKT_SUPPORT */ + +/* + * ppp_strlcpy - like strcpy/strncpy, doesn't overflow destination buffer, + * always leaves destination null-terminated (for len > 0). + */ +size_t ppp_strlcpy(char *dest, const char *src, size_t len) { + size_t ret = strlen(src); + + if (len != 0) { + if (ret < len) + strcpy(dest, src); + else { + strncpy(dest, src, len - 1); + dest[len-1] = 0; + } + } + return ret; +} + +/* + * ppp_strlcat - like strcat/strncat, doesn't overflow destination buffer, + * always leaves destination null-terminated (for len > 0). + */ +size_t ppp_strlcat(char *dest, const char *src, size_t len) { + size_t dlen = strlen(dest); + + return dlen + ppp_strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0)); +} + + +/* + * ppp_slprintf - format a message into a buffer. Like sprintf except we + * also specify the length of the output buffer, and we handle + * %m (error message), %v (visible string), + * %q (quoted string), %t (current time) and %I (IP address) formats. + * Doesn't do floating-point formats. + * Returns the number of chars put into buf. + */ +int ppp_slprintf(char *buf, int buflen, const char *fmt, ...) { + va_list args; + int n; + + va_start(args, fmt); + n = ppp_vslprintf(buf, buflen, fmt, args); + va_end(args); + return n; +} + +/* + * ppp_vslprintf - like ppp_slprintf, takes a va_list instead of a list of args. + */ +#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) + +int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) { + int c, i, n; + int width, prec, fillch; + int base, len, neg, quoted; + unsigned long val = 0; + const char *f; + char *str, *buf0; + const unsigned char *p; + char num[32]; +#if 0 /* need port */ + time_t t; +#endif /* need port */ + u32_t ip; + static char hexchars[] = "0123456789abcdef"; +#if PRINTPKT_SUPPORT + struct buffer_info bufinfo; +#endif /* PRINTPKT_SUPPORT */ + + buf0 = buf; + --buflen; + while (buflen > 0) { + for (f = fmt; *f != '%' && *f != 0; ++f) + ; + if (f > fmt) { + len = f - fmt; + if (len > buflen) + len = buflen; + memcpy(buf, fmt, len); + buf += len; + buflen -= len; + fmt = f; + } + if (*fmt == 0) + break; + c = *++fmt; + width = 0; + prec = -1; + fillch = ' '; + if (c == '0') { + fillch = '0'; + c = *++fmt; + } + if (c == '*') { + width = va_arg(args, int); + c = *++fmt; + } else { + while (isdigit(c)) { + width = width * 10 + c - '0'; + c = *++fmt; + } + } + if (c == '.') { + c = *++fmt; + if (c == '*') { + prec = va_arg(args, int); + c = *++fmt; + } else { + prec = 0; + while (isdigit(c)) { + prec = prec * 10 + c - '0'; + c = *++fmt; + } + } + } + str = 0; + base = 0; + neg = 0; + ++fmt; + switch (c) { + case 'l': + c = *fmt++; + switch (c) { + case 'd': + val = va_arg(args, long); + if ((long)val < 0) { + neg = 1; + val = (unsigned long)-(long)val; + } + base = 10; + break; + case 'u': + val = va_arg(args, unsigned long); + base = 10; + break; + default: + OUTCHAR('%'); + OUTCHAR('l'); + --fmt; /* so %lz outputs %lz etc. */ + continue; + } + break; + case 'd': + i = va_arg(args, int); + if (i < 0) { + neg = 1; + val = -i; + } else + val = i; + base = 10; + break; + case 'u': + val = va_arg(args, unsigned int); + base = 10; + break; + case 'o': + val = va_arg(args, unsigned int); + base = 8; + break; + case 'x': + case 'X': + val = va_arg(args, unsigned int); + base = 16; + break; +#if 0 /* unused (and wrong on LLP64 systems) */ + case 'p': + val = (unsigned long) va_arg(args, void *); + base = 16; + neg = 2; + break; +#endif /* unused (and wrong on LLP64 systems) */ + case 's': + str = va_arg(args, char *); + break; + case 'c': + num[0] = va_arg(args, int); + num[1] = 0; + str = num; + break; +#if 0 /* do we always have strerror() in embedded ? */ + case 'm': + str = strerror(errno); + break; +#endif /* do we always have strerror() in embedded ? */ + case 'I': + ip = va_arg(args, u32_t); + ip = lwip_ntohl(ip); + ppp_slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, + (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); + str = num; + break; +#if 0 /* need port */ + case 't': + time(&t); + str = ctime(&t); + str += 4; /* chop off the day name */ + str[15] = 0; /* chop off year and newline */ + break; +#endif /* need port */ + case 'v': /* "visible" string */ + case 'q': /* quoted string */ + quoted = c == 'q'; + p = va_arg(args, unsigned char *); + if (p == NULL) + p = (const unsigned char *)""; + if (fillch == '0' && prec >= 0) { + n = prec; + } else { + n = strlen((const char *)p); + if (prec >= 0 && n > prec) + n = prec; + } + while (n > 0 && buflen > 0) { + c = *p++; + --n; + if (!quoted && c >= 0x80) { + OUTCHAR('M'); + OUTCHAR('-'); + c -= 0x80; + } + if (quoted && (c == '"' || c == '\\')) + OUTCHAR('\\'); + if (c < 0x20 || (0x7f <= c && c < 0xa0)) { + if (quoted) { + OUTCHAR('\\'); + switch (c) { + case '\t': OUTCHAR('t'); break; + case '\n': OUTCHAR('n'); break; + case '\b': OUTCHAR('b'); break; + case '\f': OUTCHAR('f'); break; + default: + OUTCHAR('x'); + OUTCHAR(hexchars[c >> 4]); + OUTCHAR(hexchars[c & 0xf]); + } + } else { + if (c == '\t') + OUTCHAR(c); + else { + OUTCHAR('^'); + OUTCHAR(c ^ 0x40); + } + } + } else + OUTCHAR(c); + } + continue; +#if PRINTPKT_SUPPORT + case 'P': /* print PPP packet */ + bufinfo.ptr = buf; + bufinfo.len = buflen + 1; + p = va_arg(args, unsigned char *); + n = va_arg(args, int); + ppp_format_packet(p, n, ppp_vslp_printer, &bufinfo); + buf = bufinfo.ptr; + buflen = bufinfo.len - 1; + continue; +#endif /* PRINTPKT_SUPPORT */ + case 'B': + p = va_arg(args, unsigned char *); + for (n = prec; n > 0; --n) { + c = *p++; + if (fillch == ' ') + OUTCHAR(' '); + OUTCHAR(hexchars[(c >> 4) & 0xf]); + OUTCHAR(hexchars[c & 0xf]); + } + continue; + default: + *buf++ = '%'; + if (c != '%') + --fmt; /* so %z outputs %z etc. */ + --buflen; + continue; + } + if (base != 0) { + str = num + sizeof(num); + *--str = 0; + while (str > num + neg) { + *--str = hexchars[val % base]; + val = val / base; + if (--prec <= 0 && val == 0) + break; + } + switch (neg) { + case 1: + *--str = '-'; + break; + case 2: + *--str = 'x'; + *--str = '0'; + break; + default: + break; + } + len = num + sizeof(num) - 1 - str; + } else { + len = strlen(str); + if (prec >= 0 && len > prec) + len = prec; + } + if (width > 0) { + if (width > buflen) + width = buflen; + if ((n = width - len) > 0) { + buflen -= n; + for (; n > 0; --n) + *buf++ = fillch; + } + } + if (len > buflen) + len = buflen; + memcpy(buf, str, len); + buf += len; + buflen -= len; + } + *buf = 0; + return buf - buf0; +} + +#if PRINTPKT_SUPPORT +/* + * vslp_printer - used in processing a %P format + */ +static void ppp_vslp_printer(void *arg, const char *fmt, ...) { + int n; + va_list pvar; + struct buffer_info *bi; + + va_start(pvar, fmt); + bi = (struct buffer_info *) arg; + n = ppp_vslprintf(bi->ptr, bi->len, fmt, pvar); + va_end(pvar); + + bi->ptr += n; + bi->len -= n; +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * log_packet - format a packet and log it. + */ + +void +log_packet(p, len, prefix, level) + u_char *p; + int len; + char *prefix; + int level; +{ + init_pr_log(prefix, level); + ppp_format_packet(p, len, pr_log, &level); + end_pr_log(); +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ppp_format_packet - make a readable representation of a packet, + * calling `printer(arg, format, ...)' to output it. + */ +static void ppp_format_packet(const u_char *p, int len, + void (*printer) (void *, const char *, ...), void *arg) { + int i, n; + u_short proto; + const struct protent *protp; + + if (len >= 2) { + GETSHORT(proto, p); + len -= 2; + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (proto == protp->protocol) + break; + if (protp != NULL) { + printer(arg, "[%s", protp->name); + n = (*protp->printpkt)(p, len, printer, arg); + printer(arg, "]"); + p += n; + len -= n; + } else { + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (proto == (protp->protocol & ~0x8000)) + break; + if (protp != 0 && protp->data_name != 0) { + printer(arg, "[%s data]", protp->data_name); + if (len > 8) + printer(arg, "%.8B ...", p); + else + printer(arg, "%.*B", len, p); + len = 0; + } else + printer(arg, "[proto=0x%x]", proto); + } + } + + if (len > 32) + printer(arg, "%.32B ...", p); + else + printer(arg, "%.*B", len, p); +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * init_pr_log, end_pr_log - initialize and finish use of pr_log. + */ + +static char line[256]; /* line to be logged accumulated here */ +static char *linep; /* current pointer within line */ +static int llevel; /* level for logging */ + +void +init_pr_log(prefix, level) + const char *prefix; + int level; +{ + linep = line; + if (prefix != NULL) { + ppp_strlcpy(line, prefix, sizeof(line)); + linep = line + strlen(line); + } + llevel = level; +} + +void +end_pr_log() +{ + if (linep != line) { + *linep = 0; + ppp_log_write(llevel, line); + } +} + +/* + * pr_log - printer routine for outputting to log + */ +void +pr_log (void *arg, const char *fmt, ...) +{ + int l, n; + va_list pvar; + char *p, *eol; + char buf[256]; + + va_start(pvar, fmt); + n = ppp_vslprintf(buf, sizeof(buf), fmt, pvar); + va_end(pvar); + + p = buf; + eol = strchr(buf, '\n'); + if (linep != line) { + l = (eol == NULL)? n: eol - buf; + if (linep + l < line + sizeof(line)) { + if (l > 0) { + memcpy(linep, buf, l); + linep += l; + } + if (eol == NULL) + return; + p = eol + 1; + eol = strchr(p, '\n'); + } + *linep = 0; + ppp_log_write(llevel, line); + linep = line; + } + + while (eol != NULL) { + *eol = 0; + ppp_log_write(llevel, p); + p = eol + 1; + eol = strchr(p, '\n'); + } + + /* assumes sizeof(buf) <= sizeof(line) */ + l = buf + n - p; + if (l > 0) { + memcpy(line, p, n); + linep = line + l; + } +} +#endif /* UNUSED */ + +/* + * ppp_print_string - print a readable representation of a string using + * printer. + */ +void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg) { + int c; + + printer(arg, "\""); + for (; len > 0; --len) { + c = *p++; + if (' ' <= c && c <= '~') { + if (c == '\\' || c == '"') + printer(arg, "\\"); + printer(arg, "%c", c); + } else { + switch (c) { + case '\n': + printer(arg, "\\n"); + break; + case '\r': + printer(arg, "\\r"); + break; + case '\t': + printer(arg, "\\t"); + break; + default: + printer(arg, "\\%.3o", (u8_t)c); + /* no break */ + } + } + } + printer(arg, "\""); +} + +/* + * ppp_logit - does the hard work for fatal et al. + */ +static void ppp_logit(int level, const char *fmt, va_list args) { + char buf[1024]; + + ppp_vslprintf(buf, sizeof(buf), fmt, args); + ppp_log_write(level, buf); +} + +static void ppp_log_write(int level, char *buf) { + LWIP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */ + LWIP_UNUSED_ARG(buf); + PPPDEBUG(level, ("%s\n", buf) ); +#if 0 + if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { + int n = strlen(buf); + + if (n > 0 && buf[n-1] == '\n') + --n; + if (write(log_to_fd, buf, n) != n + || write(log_to_fd, "\n", 1) != 1) + log_to_fd = -1; + } +#endif +} + +/* + * ppp_fatal - log an error message and die horribly. + */ +void ppp_fatal(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_ERR, fmt, pvar); + va_end(pvar); + + LWIP_ASSERT("ppp_fatal", 0); /* as promised */ +} + +/* + * ppp_error - log an error message. + */ +void ppp_error(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_ERR, fmt, pvar); + va_end(pvar); +#if 0 /* UNUSED */ + ++error_count; +#endif /* UNUSED */ +} + +/* + * ppp_warn - log a warning message. + */ +void ppp_warn(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_WARNING, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_notice - log a notice-level message. + */ +void ppp_notice(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_NOTICE, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_info - log an informational message. + */ +void ppp_info(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_INFO, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_dbglog - log a debug message. + */ +void ppp_dbglog(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_DEBUG, fmt, pvar); + va_end(pvar); +} + +#if PRINTPKT_SUPPORT +/* + * ppp_dump_packet - print out a packet in readable form if it is interesting. + * Assumes len >= PPP_HDRLEN. + */ +void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len) { + int proto; + + /* + * don't print data packets, i.e. IPv4, IPv6, VJ, and compressed packets. + */ + proto = (p[0] << 8) + p[1]; + if (proto < 0xC000 && (proto & ~0x8000) == proto) + return; + + /* + * don't print valid LCP echo request/reply packets if the link is up. + */ + if (proto == PPP_LCP && pcb->phase == PPP_PHASE_RUNNING && len >= 2 + HEADERLEN) { + unsigned char *lcp = p + 2; + int l = (lcp[2] << 8) + lcp[3]; + + if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP) + && l >= HEADERLEN && l <= len - 2) + return; + } + + ppp_dbglog("%s %P", tag, p, len); +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* Unused */ + +/* + * complete_read - read a full `count' bytes from fd, + * unless end-of-file or an error other than EINTR is encountered. + */ +ssize_t +complete_read(int fd, void *buf, size_t count) +{ + size_t done; + ssize_t nb; + char *ptr = buf; + + for (done = 0; done < count; ) { + nb = read(fd, ptr, count - done); + if (nb < 0) { + if (errno == EINTR) + continue; + return -1; + } + if (nb == 0) + break; + done += nb; + ptr += nb; + } + return done; +} + +/* Procedures for locking the serial device using a lock file. */ +#ifndef LOCK_DIR +#ifdef __linux__ +#define LOCK_DIR "/var/lock" +#else +#ifdef SVR4 +#define LOCK_DIR "/var/spool/locks" +#else +#define LOCK_DIR "/var/spool/lock" +#endif +#endif +#endif /* LOCK_DIR */ + +static char lock_file[MAXPATHLEN]; + +/* + * lock - create a lock file for the named device + */ +int +lock(dev) + char *dev; +{ +#ifdef LOCKLIB + int result; + + result = mklock (dev, (void *) 0); + if (result == 0) { + ppp_strlcpy(lock_file, dev, sizeof(lock_file)); + return 0; + } + + if (result > 0) + ppp_notice("Device %s is locked by pid %d", dev, result); + else + ppp_error("Can't create lock file %s", lock_file); + return -1; + +#else /* LOCKLIB */ + + char lock_buffer[12]; + int fd, pid, n; + +#ifdef SVR4 + struct stat sbuf; + + if (stat(dev, &sbuf) < 0) { + ppp_error("Can't get device number for %s: %m", dev); + return -1; + } + if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { + ppp_error("Can't lock %s: not a character device", dev); + return -1; + } + ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", + LOCK_DIR, major(sbuf.st_dev), + major(sbuf.st_rdev), minor(sbuf.st_rdev)); +#else + char *p; + char lockdev[MAXPATHLEN]; + + if ((p = strstr(dev, "dev/")) != NULL) { + dev = p + 4; + strncpy(lockdev, dev, MAXPATHLEN-1); + lockdev[MAXPATHLEN-1] = 0; + while ((p = strrchr(lockdev, '/')) != NULL) { + *p = '_'; + } + dev = lockdev; + } else + if ((p = strrchr(dev, '/')) != NULL) + dev = p + 1; + + ppp_slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); +#endif + + while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { + if (errno != EEXIST) { + ppp_error("Can't create lock file %s: %m", lock_file); + break; + } + + /* Read the lock file to find out who has the device locked. */ + fd = open(lock_file, O_RDONLY, 0); + if (fd < 0) { + if (errno == ENOENT) /* This is just a timing problem. */ + continue; + ppp_error("Can't open existing lock file %s: %m", lock_file); + break; + } +#ifndef LOCK_BINARY + n = read(fd, lock_buffer, 11); +#else + n = read(fd, &pid, sizeof(pid)); +#endif /* LOCK_BINARY */ + close(fd); + fd = -1; + if (n <= 0) { + ppp_error("Can't read pid from lock file %s", lock_file); + break; + } + + /* See if the process still exists. */ +#ifndef LOCK_BINARY + lock_buffer[n] = 0; + pid = atoi(lock_buffer); +#endif /* LOCK_BINARY */ + if (pid == getpid()) + return 1; /* somebody else locked it for us */ + if (pid == 0 + || (kill(pid, 0) == -1 && errno == ESRCH)) { + if (unlink (lock_file) == 0) { + ppp_notice("Removed stale lock on %s (pid %d)", dev, pid); + continue; + } + ppp_warn("Couldn't remove stale lock on %s", dev); + } else + ppp_notice("Device %s is locked by pid %d", dev, pid); + break; + } + + if (fd < 0) { + lock_file[0] = 0; + return -1; + } + + pid = getpid(); +#ifndef LOCK_BINARY + ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); + write (fd, lock_buffer, 11); +#else + write(fd, &pid, sizeof (pid)); +#endif + close(fd); + return 0; + +#endif +} + +/* + * relock - called to update our lockfile when we are about to detach, + * thus changing our pid (we fork, the child carries on, and the parent dies). + * Note that this is called by the parent, with pid equal to the pid + * of the child. This avoids a potential race which would exist if + * we had the child rewrite the lockfile (the parent might die first, + * and another process could think the lock was stale if it checked + * between when the parent died and the child rewrote the lockfile). + */ +int +relock(pid) + int pid; +{ +#ifdef LOCKLIB + /* XXX is there a way to do this? */ + return -1; +#else /* LOCKLIB */ + + int fd; + char lock_buffer[12]; + + if (lock_file[0] == 0) + return -1; + fd = open(lock_file, O_WRONLY, 0); + if (fd < 0) { + ppp_error("Couldn't reopen lock file %s: %m", lock_file); + lock_file[0] = 0; + return -1; + } + +#ifndef LOCK_BINARY + ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); + write (fd, lock_buffer, 11); +#else + write(fd, &pid, sizeof(pid)); +#endif /* LOCK_BINARY */ + close(fd); + return 0; + +#endif /* LOCKLIB */ +} + +/* + * unlock - remove our lockfile + */ +void +unlock() +{ + if (lock_file[0]) { +#ifdef LOCKLIB + (void) rmlock(lock_file, (void *) 0); +#else + unlink(lock_file); +#endif + lock_file[0] = 0; + } +} + +#endif /* Unused */ + +#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/ppp/vj.c b/components/net/lwip-2.0.3/src/netif/ppp/vj.c new file mode 100644 index 0000000000..168c340055 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/ppp/vj.c @@ -0,0 +1,695 @@ +/* + * Routines to compress and uncompess tcp packets (for transmission + * over low speed serial lines. + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * Initial distribution. + * + * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au, + * so that the entire packet being decompressed doesn't have + * to be in contiguous memory (just the compressed header). + * + * Modified March 1998 by Guy Lancaster, glanca@gesn.com, + * for a 16 bit processor. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppdebug.h" + +#include "netif/ppp/vj.h" + +#include + +#if LINK_STATS +#define INCR(counter) ++comp->stats.counter +#else +#define INCR(counter) +#endif + +void +vj_compress_init(struct vjcompress *comp) +{ + u8_t i; + struct cstate *tstate = comp->tstate; + +#if MAX_SLOTS == 0 + memset((char *)comp, 0, sizeof(*comp)); +#endif + comp->maxSlotIndex = MAX_SLOTS - 1; + comp->compressSlot = 0; /* Disable slot ID compression by default. */ + for (i = MAX_SLOTS - 1; i > 0; --i) { + tstate[i].cs_id = i; + tstate[i].cs_next = &tstate[i - 1]; + } + tstate[0].cs_next = &tstate[MAX_SLOTS - 1]; + tstate[0].cs_id = 0; + comp->last_cs = &tstate[0]; + comp->last_recv = 255; + comp->last_xmit = 255; + comp->flags = VJF_TOSS; +} + + +/* ENCODE encodes a number that is known to be non-zero. ENCODEZ + * checks for zero (since zero has to be encoded in the long, 3 byte + * form). + */ +#define ENCODE(n) { \ + if ((u16_t)(n) >= 256) { \ + *cp++ = 0; \ + cp[1] = (u8_t)(n); \ + cp[0] = (u8_t)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u8_t)(n); \ + } \ +} +#define ENCODEZ(n) { \ + if ((u16_t)(n) >= 256 || (u16_t)(n) == 0) { \ + *cp++ = 0; \ + cp[1] = (u8_t)(n); \ + cp[0] = (u8_t)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u8_t)(n); \ + } \ +} + +#define DECODEL(f) { \ + if (*cp == 0) {\ + u32_t tmp_ = lwip_ntohl(f) + ((cp[1] << 8) | cp[2]); \ + (f) = lwip_htonl(tmp_); \ + cp += 3; \ + } else { \ + u32_t tmp_ = lwip_ntohl(f) + (u32_t)*cp++; \ + (f) = lwip_htonl(tmp_); \ + } \ +} + +#define DECODES(f) { \ + if (*cp == 0) {\ + u16_t tmp_ = lwip_ntohs(f) + (((u16_t)cp[1] << 8) | cp[2]); \ + (f) = lwip_htons(tmp_); \ + cp += 3; \ + } else { \ + u16_t tmp_ = lwip_ntohs(f) + (u16_t)*cp++; \ + (f) = lwip_htons(tmp_); \ + } \ +} + +#define DECODEU(f) { \ + if (*cp == 0) {\ + (f) = lwip_htons(((u16_t)cp[1] << 8) | cp[2]); \ + cp += 3; \ + } else { \ + (f) = lwip_htons((u16_t)*cp++); \ + } \ +} + +/* Helper structures for unaligned *u32_t and *u16_t accesses */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct vj_u32_t { + PACK_STRUCT_FIELD(u32_t v); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct vj_u16_t { + PACK_STRUCT_FIELD(u16_t v); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* + * vj_compress_tcp - Attempt to do Van Jacobson header compression on a + * packet. This assumes that nb and comp are not null and that the first + * buffer of the chain contains a valid IP header. + * Return the VJ type code indicating whether or not the packet was + * compressed. + */ +u8_t +vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) +{ + struct pbuf *np = *pb; + struct ip_hdr *ip = (struct ip_hdr *)np->payload; + struct cstate *cs = comp->last_cs->cs_next; + u16_t ilen = IPH_HL(ip); + u16_t hlen; + struct tcp_hdr *oth; + struct tcp_hdr *th; + u16_t deltaS, deltaA = 0; + u32_t deltaL; + u32_t changes = 0; + u8_t new_seq[16]; + u8_t *cp = new_seq; + + /* + * Check that the packet is IP proto TCP. + */ + if (IPH_PROTO(ip) != IP_PROTO_TCP) { + return (TYPE_IP); + } + + /* + * Bail if this is an IP fragment or if the TCP packet isn't + * `compressible' (i.e., ACK isn't set or some other control bit is + * set). + */ + if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || np->tot_len < 40) { + return (TYPE_IP); + } + th = (struct tcp_hdr *)&((struct vj_u32_t*)ip)[ilen]; + if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { + return (TYPE_IP); + } + + /* Check that the TCP/IP headers are contained in the first buffer. */ + hlen = ilen + TCPH_HDRLEN(th); + hlen <<= 2; + if (np->len < hlen) { + PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen)); + return (TYPE_IP); + } + + /* TCP stack requires that we don't change the packet payload, therefore we copy + * the whole packet before compression. */ + np = pbuf_alloc(PBUF_RAW, np->tot_len, PBUF_POOL); + if (!np) { + return (TYPE_IP); + } + + if (pbuf_copy(np, *pb) != ERR_OK) { + pbuf_free(np); + return (TYPE_IP); + } + + *pb = np; + ip = (struct ip_hdr *)np->payload; + + /* + * Packet is compressible -- we're going to send either a + * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need + * to locate (or create) the connection state. Special case the + * most recently used connection since it's most likely to be used + * again & we don't have to do any reordering if it's used. + */ + INCR(vjs_packets); + if (!ip4_addr_cmp(&ip->src, &cs->cs_ip.src) + || !ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) + || (*(struct vj_u32_t*)th).v != (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { + /* + * Wasn't the first -- search for it. + * + * States are kept in a circularly linked list with + * last_cs pointing to the end of the list. The + * list is kept in lru order by moving a state to the + * head of the list whenever it is referenced. Since + * the list is short and, empirically, the connection + * we want is almost always near the front, we locate + * states via linear search. If we don't find a state + * for the datagram, the oldest state is (re-)used. + */ + struct cstate *lcs; + struct cstate *lastcs = comp->last_cs; + + do { + lcs = cs; cs = cs->cs_next; + INCR(vjs_searches); + if (ip4_addr_cmp(&ip->src, &cs->cs_ip.src) + && ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) + && (*(struct vj_u32_t*)th).v == (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { + goto found; + } + } while (cs != lastcs); + + /* + * Didn't find it -- re-use oldest cstate. Send an + * uncompressed packet that tells the other side what + * connection number we're using for this conversation. + * Note that since the state list is circular, the oldest + * state points to the newest and we only need to set + * last_cs to update the lru linkage. + */ + INCR(vjs_misses); + comp->last_cs = lcs; + goto uncompressed; + + found: + /* + * Found it -- move to the front on the connection list. + */ + if (cs == lastcs) { + comp->last_cs = lcs; + } else { + lcs->cs_next = cs->cs_next; + cs->cs_next = lastcs->cs_next; + lastcs->cs_next = cs; + } + } + + oth = (struct tcp_hdr *)&((struct vj_u32_t*)&cs->cs_ip)[ilen]; + deltaS = ilen; + + /* + * Make sure that only what we expect to change changed. The first + * line of the `if' checks the IP protocol version, header length & + * type of service. The 2nd line checks the "Don't fragment" bit. + * The 3rd line checks the time-to-live and protocol (the protocol + * check is unnecessary but costless). The 4th line checks the TCP + * header length. The 5th line checks IP options, if any. The 6th + * line checks TCP options, if any. If any of these things are + * different between the previous & current datagram, we send the + * current datagram `uncompressed'. + */ + if ((((struct vj_u16_t*)ip)[0]).v != (((struct vj_u16_t*)&cs->cs_ip)[0]).v + || (((struct vj_u16_t*)ip)[3]).v != (((struct vj_u16_t*)&cs->cs_ip)[3]).v + || (((struct vj_u16_t*)ip)[4]).v != (((struct vj_u16_t*)&cs->cs_ip)[4]).v + || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth) + || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) + || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) { + goto uncompressed; + } + + /* + * Figure out which of the changing fields changed. The + * receiver expects changes in the order: urgent, window, + * ack, seq (the order minimizes the number of temporaries + * needed in this section of code). + */ + if (TCPH_FLAGS(th) & TCP_URG) { + deltaS = lwip_ntohs(th->urgp); + ENCODEZ(deltaS); + changes |= NEW_U; + } else if (th->urgp != oth->urgp) { + /* argh! URG not set but urp changed -- a sensible + * implementation should never do this but RFC793 + * doesn't prohibit the change so we have to deal + * with it. */ + goto uncompressed; + } + + if ((deltaS = (u16_t)(lwip_ntohs(th->wnd) - lwip_ntohs(oth->wnd))) != 0) { + ENCODE(deltaS); + changes |= NEW_W; + } + + if ((deltaL = lwip_ntohl(th->ackno) - lwip_ntohl(oth->ackno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaA = (u16_t)deltaL; + ENCODE(deltaA); + changes |= NEW_A; + } + + if ((deltaL = lwip_ntohl(th->seqno) - lwip_ntohl(oth->seqno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaS = (u16_t)deltaL; + ENCODE(deltaS); + changes |= NEW_S; + } + + switch(changes) { + case 0: + /* + * Nothing changed. If this packet contains data and the + * last one didn't, this is probably a data packet following + * an ack (normal on an interactive connection) and we send + * it compressed. Otherwise it's probably a retransmit, + * retransmitted ack or window probe. Send it uncompressed + * in case the other side missed the compressed version. + */ + if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && + lwip_ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { + break; + } + /* no break */ + /* fall through */ + + case SPECIAL_I: + case SPECIAL_D: + /* + * actual changes match one of our special case encodings -- + * send packet uncompressed. + */ + goto uncompressed; + + case NEW_S|NEW_A: + if (deltaS == deltaA && deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for echoed terminal traffic */ + changes = SPECIAL_I; + cp = new_seq; + } + break; + + case NEW_S: + if (deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for data xfer */ + changes = SPECIAL_D; + cp = new_seq; + } + break; + default: + break; + } + + deltaS = (u16_t)(lwip_ntohs(IPH_ID(ip)) - lwip_ntohs(IPH_ID(&cs->cs_ip))); + if (deltaS != 1) { + ENCODEZ(deltaS); + changes |= NEW_I; + } + if (TCPH_FLAGS(th) & TCP_PSH) { + changes |= TCP_PUSH_BIT; + } + /* + * Grab the cksum before we overwrite it below. Then update our + * state with this packet's header. + */ + deltaA = lwip_ntohs(th->chksum); + MEMCPY(&cs->cs_ip, ip, hlen); + + /* + * We want to use the original packet as our compressed packet. + * (cp - new_seq) is the number of bytes we need for compressed + * sequence numbers. In addition we need one byte for the change + * mask, one for the connection id and two for the tcp checksum. + * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how + * many bytes of the original packet to toss so subtract the two to + * get the new packet size. + */ + deltaS = (u16_t)(cp - new_seq); + if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { + comp->last_xmit = cs->cs_id; + hlen -= deltaS + 4; + if (pbuf_header(np, -(s16_t)hlen)){ + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u8_t*)np->payload; + *cp++ = (u8_t)(changes | NEW_C); + *cp++ = cs->cs_id; + } else { + hlen -= deltaS + 3; + if (pbuf_header(np, -(s16_t)hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u8_t*)np->payload; + *cp++ = (u8_t)changes; + } + *cp++ = (u8_t)(deltaA >> 8); + *cp++ = (u8_t)deltaA; + MEMCPY(cp, new_seq, deltaS); + INCR(vjs_compressed); + return (TYPE_COMPRESSED_TCP); + + /* + * Update connection state cs & send uncompressed packet (that is, + * a regular ip/tcp packet but with the 'conversation id' we hope + * to use on future compressed packets in the protocol field). + */ +uncompressed: + MEMCPY(&cs->cs_ip, ip, hlen); + IPH_PROTO_SET(ip, cs->cs_id); + comp->last_xmit = cs->cs_id; + return (TYPE_UNCOMPRESSED_TCP); +} + +/* + * Called when we may have missed a packet. + */ +void +vj_uncompress_err(struct vjcompress *comp) +{ + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); +} + +/* + * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. + * Return 0 on success, -1 on failure. + */ +int +vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) +{ + u32_t hlen; + struct cstate *cs; + struct ip_hdr *ip; + + ip = (struct ip_hdr *)nb->payload; + hlen = IPH_HL(ip) << 2; + if (IPH_PROTO(ip) >= MAX_SLOTS + || hlen + sizeof(struct tcp_hdr) > nb->len + || (hlen += TCPH_HDRLEN(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2) + > nb->len + || hlen > MAX_HDR) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", + IPH_PROTO(ip), hlen, nb->len)); + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return -1; + } + cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)]; + comp->flags &=~ VJF_TOSS; + IPH_PROTO_SET(ip, IP_PROTO_TCP); + MEMCPY(&cs->cs_ip, ip, hlen); + cs->cs_hlen = (u16_t)hlen; + INCR(vjs_uncompressedin); + return 0; +} + +/* + * Uncompress a packet of type TYPE_COMPRESSED_TCP. + * The packet is composed of a buffer chain and the first buffer + * must contain an accurate chain length. + * The first buffer must include the entire compressed TCP/IP header. + * This procedure replaces the compressed header with the uncompressed + * header and returns the length of the VJ header. + */ +int +vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) +{ + u8_t *cp; + struct tcp_hdr *th; + struct cstate *cs; + struct vj_u16_t *bp; + struct pbuf *n0 = *nb; + u32_t tmp; + u32_t vjlen, hlen, changes; + + INCR(vjs_compressedin); + cp = (u8_t*)n0->payload; + changes = *cp++; + if (changes & NEW_C) { + /* + * Make sure the state index is in range, then grab the state. + * If we have a good state index, clear the 'discard' flag. + */ + if (*cp >= MAX_SLOTS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp)); + goto bad; + } + + comp->flags &=~ VJF_TOSS; + comp->last_recv = *cp++; + } else { + /* + * this packet has an implicit state index. If we've + * had a line error since the last time we got an + * explicit state index, we have to toss the packet. + */ + if (comp->flags & VJF_TOSS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n")); + INCR(vjs_tossed); + return (-1); + } + } + cs = &comp->rstate[comp->last_recv]; + hlen = IPH_HL(&cs->cs_ip) << 2; + th = (struct tcp_hdr *)&((u8_t*)&cs->cs_ip)[hlen]; + th->chksum = lwip_htons((*cp << 8) | cp[1]); + cp += 2; + if (changes & TCP_PUSH_BIT) { + TCPH_SET_FLAG(th, TCP_PSH); + } else { + TCPH_UNSET_FLAG(th, TCP_PSH); + } + + switch (changes & SPECIALS_MASK) { + case SPECIAL_I: + { + u32_t i = lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + /* some compilers can't nest inline assembler.. */ + tmp = lwip_ntohl(th->ackno) + i; + th->ackno = lwip_htonl(tmp); + tmp = lwip_ntohl(th->seqno) + i; + th->seqno = lwip_htonl(tmp); + } + break; + + case SPECIAL_D: + /* some compilers can't nest inline assembler.. */ + tmp = lwip_ntohl(th->seqno) + lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + th->seqno = lwip_htonl(tmp); + break; + + default: + if (changes & NEW_U) { + TCPH_SET_FLAG(th, TCP_URG); + DECODEU(th->urgp); + } else { + TCPH_UNSET_FLAG(th, TCP_URG); + } + if (changes & NEW_W) { + DECODES(th->wnd); + } + if (changes & NEW_A) { + DECODEL(th->ackno); + } + if (changes & NEW_S) { + DECODEL(th->seqno); + } + break; + } + if (changes & NEW_I) { + DECODES(cs->cs_ip._id); + } else { + IPH_ID_SET(&cs->cs_ip, lwip_ntohs(IPH_ID(&cs->cs_ip)) + 1); + IPH_ID_SET(&cs->cs_ip, lwip_htons(IPH_ID(&cs->cs_ip))); + } + + /* + * At this point, cp points to the first byte of data in the + * packet. Fill in the IP total length and update the IP + * header checksum. + */ + vjlen = (u16_t)(cp - (u8_t*)n0->payload); + if (n0->len < vjlen) { + /* + * We must have dropped some characters (crc should detect + * this but the old slip framing won't) + */ + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", + n0->len, vjlen)); + goto bad; + } + +#if BYTE_ORDER == LITTLE_ENDIAN + tmp = n0->tot_len - vjlen + cs->cs_hlen; + IPH_LEN_SET(&cs->cs_ip, lwip_htons((u16_t)tmp)); +#else + IPH_LEN_SET(&cs->cs_ip, lwip_htons(n0->tot_len - vjlen + cs->cs_hlen)); +#endif + + /* recompute the ip header checksum */ + bp = (struct vj_u16_t*) &cs->cs_ip; + IPH_CHKSUM_SET(&cs->cs_ip, 0); + for (tmp = 0; hlen > 0; hlen -= 2) { + tmp += (*bp++).v; + } + tmp = (tmp & 0xffff) + (tmp >> 16); + tmp = (tmp & 0xffff) + (tmp >> 16); + IPH_CHKSUM_SET(&cs->cs_ip, (u16_t)(~tmp)); + + /* Remove the compressed header and prepend the uncompressed header. */ + if (pbuf_header(n0, -(s16_t)vjlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) { + struct pbuf *np, *q; + u8_t *bufptr; + +#if IP_FORWARD + /* If IP forwarding is enabled we are using a PBUF_LINK packet type so + * the packet is being allocated with enough header space to be + * forwarded (to Ethernet for example). + */ + np = pbuf_alloc(PBUF_LINK, n0->len + cs->cs_hlen, PBUF_POOL); +#else /* IP_FORWARD */ + np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); +#endif /* IP_FORWARD */ + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n")); + goto bad; + } + + if (pbuf_header(np, -(s16_t)cs->cs_hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + bufptr = (u8_t*)n0->payload; + for(q = np; q != NULL; q = q->next) { + MEMCPY(q->payload, bufptr, q->len); + bufptr += q->len; + } + + if(n0->next) { + pbuf_chain(np, n0->next); + pbuf_dechain(n0); + } + pbuf_free(n0); + n0 = np; + } + + if (pbuf_header(n0, (s16_t)cs->cs_hlen)) { + struct pbuf *np; + + LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); + np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n")); + goto bad; + } + pbuf_cat(np, n0); + n0 = np; + } + LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); + MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen); + + *nb = n0; + + return vjlen; + +bad: + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return (-1); +} + +#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/components/net/lwip-2.0.3/src/netif/slipif.c b/components/net/lwip-2.0.3/src/netif/slipif.c new file mode 100644 index 0000000000..6eb83c35a4 --- /dev/null +++ b/components/net/lwip-2.0.3/src/netif/slipif.c @@ -0,0 +1,555 @@ +/** + * @file + * SLIP Interface + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is built upon the file: src/arch/rtxc/netif/sioslip.c + * + * Author: Magnus Ivarsson + * Simon Goldschmidt + */ + + +/** + * @defgroup slipif SLIP netif + * @ingroup addons + * + * This is an arch independent SLIP netif. The specific serial hooks must be + * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send + * + * Usage: This netif can be used in three ways:\n + * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() + * until data is received.\n + * 2) In your main loop, call slipif_poll() to check for new RX bytes, + * completed packets are fed into netif->input().\n + * 3) Call slipif_received_byte[s]() from your serial RX ISR and + * slipif_process_rxqueue() from your main loop. ISR level decodes + * packets and puts completed packets on a queue which is fed into + * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for + * pbuf_alloc to work on ISR level!). + * + */ + +#include "netif/slipif.h" +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/sys.h" +#include "lwip/sio.h" + +#define SLIP_END 0xC0 /* 0300: start and end of every packet */ +#define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ +#define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ +#define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ + +/** Maximum packet size that is received by this netif */ +#ifndef SLIP_MAX_SIZE +#define SLIP_MAX_SIZE 1500 +#endif + +/** Define this to the interface speed for SNMP + * (sio_fd is the sio_fd_t returned by sio_open). + * The default value of zero means 'unknown'. + */ +#ifndef SLIP_SIO_SPEED +#define SLIP_SIO_SPEED(sio_fd) 0 +#endif + +enum slipif_recv_state { + SLIP_RECV_NORMAL, + SLIP_RECV_ESCAPE +}; + +struct slipif_priv { + sio_fd_t sd; + /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ + struct pbuf *p, *q; + u8_t state; + u16_t i, recved; +#if SLIP_RX_FROM_ISR + struct pbuf *rxpackets; +#endif +}; + +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output(struct netif *netif, struct pbuf *p) +{ + struct slipif_priv *priv; + struct pbuf *q; + u16_t i; + u8_t c; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + LWIP_ASSERT("p != NULL", (p != NULL)); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output(%"U16_F"): sending %"U16_F" bytes\n", (u16_t)netif->num, p->tot_len)); + priv = (struct slipif_priv *)netif->state; + + /* Send pbuf out on the serial I/O device. */ + /* Start with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + + for (q = p; q != NULL; q = q->next) { + for (i = 0; i < q->len; i++) { + c = ((u8_t *)q->payload)[i]; + switch (c) { + case SLIP_END: + /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_END, priv->sd); + break; + case SLIP_ESC: + /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_ESC, priv->sd); + break; + default: + /* normal byte - no need for escaping */ + sio_send(c, priv->sd); + break; + } + } + } + /* End with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + return ERR_OK; +} + +#if LWIP_IPV4 +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output_v4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(ipaddr); + return slipif_output(netif, p); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output_v6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(ipaddr); + return slipif_output(netif, p); +} +#endif /* LWIP_IPV6 */ + +/** + * Handle the incoming SLIP stream character by character + * + * @param netif the lwip network interface structure for this slipif + * @param c received character (multiple calls to this function will + * return a complete packet, NULL is returned before - used for polling) + * @return The IP packet when SLIP_END is received + */ +static struct pbuf* +slipif_rxbyte(struct netif *netif, u8_t c) +{ + struct slipif_priv *priv; + struct pbuf *t; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + switch (priv->state) { + case SLIP_RECV_NORMAL: + switch (c) { + case SLIP_END: + if (priv->recved > 0) { + /* Received whole packet. */ + /* Trim the pbuf to the size of the received packet. */ + pbuf_realloc(priv->q, priv->recved); + + LINK_STATS_INC(link.recv); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); + t = priv->q; + priv->p = priv->q = NULL; + priv->i = priv->recved = 0; + return t; + } + return NULL; + case SLIP_ESC: + priv->state = SLIP_RECV_ESCAPE; + return NULL; + default: + break; + } /* end switch (c) */ + break; + case SLIP_RECV_ESCAPE: + /* un-escape END or ESC bytes, leave other bytes + (although that would be a protocol error) */ + switch (c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + default: + break; + } + priv->state = SLIP_RECV_NORMAL; + break; + default: + break; + } /* end switch (priv->state) */ + + /* byte received, packet not yet completely received */ + if (priv->p == NULL) { + /* allocate a new pbuf */ + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); + priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - PBUF_LINK_ENCAPSULATION_HLEN), PBUF_POOL); + + if (priv->p == NULL) { + LINK_STATS_INC(link.drop); + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); + /* don't process any further since we got no pbuf to receive to */ + return NULL; + } + + if (priv->q != NULL) { + /* 'chain' the pbuf to the existing chain */ + pbuf_cat(priv->q, priv->p); + } else { + /* p is the first pbuf in the chain */ + priv->q = priv->p; + } + } + + /* this automatically drops bytes if > SLIP_MAX_SIZE */ + if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { + ((u8_t *)priv->p->payload)[priv->i] = c; + priv->recved++; + priv->i++; + if (priv->i >= priv->p->len) { + /* on to the next pbuf */ + priv->i = 0; + if (priv->p->next != NULL && priv->p->next->len > 0) { + /* p is a chain, on to the next in the chain */ + priv->p = priv->p->next; + } else { + /* p is a single pbuf, set it to NULL so next time a new + * pbuf is allocated */ + priv->p = NULL; + } + } + } + return NULL; +} + +/** Like slipif_rxbyte, but passes completed packets to netif->input + * + * @param netif The lwip network interface structure for this slipif + * @param c received character + */ +static void +slipif_rxbyte_input(struct netif *netif, u8_t c) +{ + struct pbuf *p; + p = slipif_rxbyte(netif, c); + if (p != NULL) { + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + } +} + +#if SLIP_USE_RX_THREAD +/** + * The SLIP input thread. + * + * Feed the IP layer with incoming packets + * + * @param nf the lwip network interface structure for this slipif + */ +static void +slipif_loop_thread(void *nf) +{ + u8_t c; + struct netif *netif = (struct netif *)nf; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + + while (1) { + if (sio_read(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } + } +} +#endif /* SLIP_USE_RX_THREAD */ + +/** + * SLIP netif initialization + * + * Call the arch specific sio_open and remember + * the opened device in the state field of the netif. + * + * @param netif the lwip network interface structure for this slipif + * @return ERR_OK if serial line could be opened, + * ERR_MEM if no memory could be allocated, + * ERR_IF is serial line couldn't be opened + * + * @note netif->num must contain the number of the serial port to open + * (0 by default). If netif->state is != NULL, it is interpreted as an + * u8_t pointer pointing to the serial port number instead of netif->num. + * + */ +err_t +slipif_init(struct netif *netif) +{ + struct slipif_priv *priv; + u8_t sio_num; + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); + + /* Allocate private data */ + priv = (struct slipif_priv *)mem_malloc(sizeof(struct slipif_priv)); + if (!priv) { + return ERR_MEM; + } + + netif->name[0] = 's'; + netif->name[1] = 'l'; +#if LWIP_IPV4 + netif->output = slipif_output_v4; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = slipif_output_v6; +#endif /* LWIP_IPV6 */ + netif->mtu = SLIP_MAX_SIZE; + + /* netif->state or netif->num contain the port number */ + if (netif->state != NULL) { + sio_num = *(u8_t*)netif->state; + } else { + sio_num = netif->num; + } + /* Try to open the serial port. */ + priv->sd = sio_open(sio_num); + if (!priv->sd) { + /* Opening the serial port failed. */ + mem_free(priv); + return ERR_IF; + } + + /* Initialize private data */ + priv->p = NULL; + priv->q = NULL; + priv->state = SLIP_RECV_NORMAL; + priv->i = 0; + priv->recved = 0; +#if SLIP_RX_FROM_ISR + priv->rxpackets = NULL; +#endif + + netif->state = priv; + + /* initialize the snmp variables and counters inside the struct netif */ + MIB2_INIT_NETIF(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); + +#if SLIP_USE_RX_THREAD + /* Create a thread to poll the serial line. */ + sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, + SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); +#endif /* SLIP_USE_RX_THREAD */ + return ERR_OK; +} + +/** + * Polls the serial device and feeds the IP layer with incoming packets. + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_poll(struct netif *netif) +{ + u8_t c; + struct slipif_priv *priv; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + while (sio_tryread(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } +} + +#if SLIP_RX_FROM_ISR +/** + * Feeds the IP layer with incoming packets that were receive + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_process_rxqueue(struct netif *netif) +{ + struct slipif_priv *priv; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + SYS_ARCH_PROTECT(old_level); + while (priv->rxpackets != NULL) { + struct pbuf *p = priv->rxpackets; +#if SLIP_RX_QUEUE + /* dequeue packet */ + struct pbuf *q = p; + while ((q->len != q->tot_len) && (q->next != NULL)) { + q = q->next; + } + priv->rxpackets = q->next; + q->next = NULL; +#else /* SLIP_RX_QUEUE */ + priv->rxpackets = NULL; +#endif /* SLIP_RX_QUEUE */ + SYS_ARCH_UNPROTECT(old_level); + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + SYS_ARCH_PROTECT(old_level); + } +} + +/** Like slipif_rxbyte, but queues completed packets. + * + * @param netif The lwip network interface structure for this slipif + * @param data Received serial byte + */ +static void +slipif_rxbyte_enqueue(struct netif *netif, u8_t data) +{ + struct pbuf *p; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + SYS_ARCH_DECL_PROTECT(old_level); + + p = slipif_rxbyte(netif, data); + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + if (priv->rxpackets != NULL) { +#if SLIP_RX_QUEUE + /* queue multiple pbufs */ + struct pbuf *q = p; + while (q->next != NULL) { + q = q->next; + } + q->next = p; + } else { +#else /* SLIP_RX_QUEUE */ + pbuf_free(priv->rxpackets); + } + { +#endif /* SLIP_RX_QUEUE */ + priv->rxpackets = p; + } + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Process a received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + */ +void +slipif_received_byte(struct netif *netif, u8_t data) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + slipif_rxbyte_enqueue(netif, data); +} + +/** + * Process multiple received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + * @param len Number of received characters + */ +void +slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len) +{ + u8_t i; + u8_t *rxdata = data; + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + for (i = 0; i < len; i++, rxdata++) { + slipif_rxbyte_enqueue(netif, *rxdata); + } +} +#endif /* SLIP_RX_FROM_ISR */ diff --git a/components/net/lwip-2.0.3/test/fuzz/Makefile b/components/net/lwip-2.0.3/test/fuzz/Makefile new file mode 100644 index 0000000000..67ffb1957e --- /dev/null +++ b/components/net/lwip-2.0.3/test/fuzz/Makefile @@ -0,0 +1,53 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +# OF SUCH DAMAGE. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +all compile: lwip_fuzz +.PHONY: all clean + +CC=afl-gcc +LDFLAGS=-lm +CFLAGS=-O0 + +CONTRIBDIR=../../../lwip-contrib +include $(CONTRIBDIR)/ports/unix/Common.mk + +clean: + rm -f *.o $(LWIPLIBCOMMON) lwip_fuzz *.s .depend* *.core core + +depend dep: .depend + +include .depend + +.depend: fuzz.c $(LWIPFILES) $(APPFILES) + $(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend + +lwip_fuzz: .depend $(LWIPLIBCOMMON) fuzz.o + $(CC) $(CFLAGS) -o lwip_fuzz fuzz.o $(LWIPLIBCOMMON) $(LDFLAGS) diff --git a/components/net/lwip-2.0.3/test/fuzz/README b/components/net/lwip-2.0.3/test/fuzz/README new file mode 100644 index 0000000000..1d1e3d8deb --- /dev/null +++ b/components/net/lwip-2.0.3/test/fuzz/README @@ -0,0 +1,34 @@ + +Fuzzing the lwIP stack (afl-fuzz requires linux/unix or similar) + +This directory contains a small app that reads Ethernet frames from stdin and +processes them. It is used together with the 'american fuzzy lop' tool (found +at http://lcamtuf.coredump.cx/afl/) and the sample inputs to test how +unexpected inputs are handled. The afl tool will read the known inputs, and +try to modify them to exercise as many code paths as possible, by instrumenting +the code and keeping track of which code is executed. + +Just running make will produce the test program. + +Then run afl with: + +afl-fuzz -i inputs/ -o output ./lwip_fuzz + +and it should start working. It will probably complain about CPU scheduler, +set AFL_SKIP_CPUFREQ=1 to ignore it. +If it complains about invalid "/proc/sys/kernel/core_pattern" setting, try +executing "sudo bash -c 'echo core > /proc/sys/kernel/core_pattern'". + +The input is split into different subdirectories since they test different +parts of the code, and since you want to run one instance of afl-fuzz on each +core. + +When afl finds a crash or a hang, the input that caused it will be placed in +the output directory. If you have hexdump and text2pcap tools installed, +running output_to_pcap.sh will create pcap files for each input +file to simplify viewing in wireshark. + +The lwipopts.h file needs to have checksum checking off, otherwise almost every +packet will be discarded because of that. The other options can be tuned to +expose different parts of the code. + diff --git a/components/net/lwip-2.0.3/test/fuzz/config.h b/components/net/lwip-2.0.3/test/fuzz/config.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/components/net/lwip-2.0.3/test/fuzz/fuzz.c b/components/net/lwip-2.0.3/test/fuzz/fuzz.c new file mode 100644 index 0000000000..a9157f1385 --- /dev/null +++ b/components/net/lwip-2.0.3/test/fuzz/fuzz.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ + +#include "lwip/init.h" +#include "lwip/netif.h" +#include "netif/etharp.h" +#if LWIP_IPV6 +#include "lwip/ethip6.h" +#include "lwip/nd6.h" +#endif +#include +#include + +/* no-op send function */ +static err_t lwip_tx_func(struct netif *netif, struct pbuf *p) +{ + LWIP_UNUSED_ARG(netif); + LWIP_UNUSED_ARG(p); + return ERR_OK; +} + +static err_t testif_init(struct netif *netif) +{ + netif->name[0] = 'f'; + netif->name[1] = 'z'; + netif->output = etharp_output; + netif->linkoutput = lwip_tx_func; + netif->mtu = 1500; + netif->hwaddr_len = 6; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + + netif->hwaddr[0] = 0x00; + netif->hwaddr[1] = 0x23; + netif->hwaddr[2] = 0xC1; + netif->hwaddr[3] = 0xDE; + netif->hwaddr[4] = 0xD0; + netif->hwaddr[5] = 0x0D; + +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; + netif->ip6_autoconfig_enabled = 1; + netif_create_ip6_linklocal_address(netif, 1); + netif->flags |= NETIF_FLAG_MLD6; +#endif + + return ERR_OK; +} + +static void input_pkt(struct netif *netif, const u8_t *data, size_t len) +{ + struct pbuf *p, *q; + err_t err; + + LWIP_ASSERT("pkt too big", len <= 0xFFFF); + p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL); + LWIP_ASSERT("alloc failed", p); + for(q = p; q != NULL; q = q->next) { + MEMCPY(q->payload, data, q->len); + data += q->len; + } + err = netif->input(p, netif); + if (err != ERR_OK) { + pbuf_free(p); + } +} + +int main(int argc, char** argv) +{ + struct netif net_test; + ip4_addr_t addr; + ip4_addr_t netmask; + ip4_addr_t gw; + u8_t pktbuf[2000]; + size_t len; + + lwip_init(); + + IP4_ADDR(&addr, 172, 30, 115, 84); + IP4_ADDR(&netmask, 255, 255, 255, 0); + IP4_ADDR(&gw, 172, 30, 115, 1); + + netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); + netif_set_up(&net_test); + +#if LWIP_IPV6 + nd6_tmr(); /* tick nd to join multicast groups */ +#endif + + if(argc > 1) { + FILE* f; + const char* filename; + printf("reading input from file... "); + fflush(stdout); + filename = argv[1]; + LWIP_ASSERT("invalid filename", filename != NULL); + f = fopen(filename, "rb"); + LWIP_ASSERT("open failed", f != NULL); + len = fread(pktbuf, 1, sizeof(pktbuf), f); + fclose(f); + printf("testing file: \"%s\"...\r\n", filename); + } else { + len = fread(pktbuf, 1, sizeof(pktbuf), stdin); + } + input_pkt(&net_test, pktbuf, len); + + return 0; +} diff --git a/components/net/lwip-2.0.3/test/fuzz/lwipopts.h b/components/net/lwip-2.0.3/test/fuzz/lwipopts.h new file mode 100644 index 0000000000..4aff09bad6 --- /dev/null +++ b/components/net/lwip-2.0.3/test/fuzz/lwipopts.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_LWIPOPTS_H__ +#define LWIP_HDR_LWIPOPTS_H__ + +/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ +#define NO_SYS 1 +#define LWIP_NETCONN 0 +#define LWIP_SOCKET 0 +#define SYS_LIGHTWEIGHT_PROT 0 + +#define LWIP_IPV6 1 +#define IPV6_FRAG_COPYHEADER 1 +#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0 + +/* Enable DHCP to test it */ +#define LWIP_DHCP 1 + +/* Turn off checksum verification of fuzzed data */ +#define CHECKSUM_CHECK_IP 0 +#define CHECKSUM_CHECK_UDP 0 +#define CHECKSUM_CHECK_TCP 0 +#define CHECKSUM_CHECK_ICMP 0 +#define CHECKSUM_CHECK_ICMP6 0 + +/* Minimal changes to opt.h required for tcp unit tests: */ +#define MEM_SIZE 16000 +#define TCP_SND_QUEUELEN 40 +#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN +#define TCP_SND_BUF (12 * TCP_MSS) +#define TCP_WND (10 * TCP_MSS) +#define LWIP_WND_SCALE 1 +#define TCP_RCV_SCALE 0 +#define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */ + +/* Minimal changes to opt.h required for etharp unit tests: */ +#define ETHARP_SUPPORT_STATIC_ENTRIES 1 + +#endif /* LWIP_HDR_LWIPOPTS_H__ */ diff --git a/components/net/lwip-2.0.3/test/fuzz/output_to_pcap.sh b/components/net/lwip-2.0.3/test/fuzz/output_to_pcap.sh new file mode 100644 index 0000000000..c999ff0392 --- /dev/null +++ b/components/net/lwip-2.0.3/test/fuzz/output_to_pcap.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +if [ -z "$1" ] +then + echo "This script will make pcap files from the afl-fuzz crash/hang files" + echo "It needs hexdump and text2pcap" + echo "Please give output directory as argument" + exit 2 +fi + +for i in `ls $1/crashes/id*` +do + PCAPNAME=`echo $i | grep pcap` + if [ -z "$PCAPNAME" ]; then + hexdump -C $i > $1/$$.tmp + text2pcap $1/$$.tmp ${i}.pcap + fi +done +for i in `ls $1/hangs/id*` +do + PCAPNAME=`echo $i | grep pcap` + if [ -z "$PCAPNAME" ]; then + hexdump -C $i > $1/$$.tmp + text2pcap $1/$$.tmp ${i}.pcap + fi +done +rm -f $1/$$.tmp + +echo +echo "Created pcap files:" +ls $1/*/*.pcap diff --git a/components/net/lwip-2.0.3/test/unit/core/test_mem.c b/components/net/lwip-2.0.3/test/unit/core/test_mem.c new file mode 100644 index 0000000000..66b4877e3f --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/core/test_mem.c @@ -0,0 +1,121 @@ +#include "test_mem.h" + +#include "lwip/mem.h" +#include "lwip/stats.h" + +#if !LWIP_STATS || !MEM_STATS +#error "This tests needs MEM-statistics enabled" +#endif +#if LWIP_DNS +#error "This test needs DNS turned off (as it mallocs on init)" +#endif + +/* Setups/teardown functions */ + +static void +mem_setup(void) +{ +} + +static void +mem_teardown(void) +{ +} + + +/* Test functions */ + +/** Call mem_malloc, mem_free and mem_trim and check stats */ +START_TEST(test_mem_one) +{ +#define SIZE1 16 +#define SIZE1_2 12 +#define SIZE2 16 + void *p1, *p2; + mem_size_t s1, s2; + LWIP_UNUSED_ARG(_i); + + fail_unless(lwip_stats.mem.used == 0); + + p1 = mem_malloc(SIZE1); + fail_unless(p1 != NULL); + fail_unless(lwip_stats.mem.used >= SIZE1); + s1 = lwip_stats.mem.used; + + p2 = mem_malloc(SIZE2); + fail_unless(p2 != NULL); + fail_unless(lwip_stats.mem.used >= SIZE2 + s1); + s2 = lwip_stats.mem.used; + + mem_trim(p1, SIZE1_2); + + mem_free(p2); + fail_unless(lwip_stats.mem.used <= s2 - SIZE2); + + mem_free(p1); + fail_unless(lwip_stats.mem.used == 0); +} +END_TEST + +static void malloc_keep_x(int x, int num, int size, int freestep) +{ + int i; + void* p[16]; + LWIP_ASSERT("invalid size", size >= 0 && size < (mem_size_t)-1); + memset(p, 0, sizeof(p)); + for(i = 0; i < num && i < 16; i++) { + p[i] = mem_malloc((mem_size_t)size); + fail_unless(p[i] != NULL); + } + for(i = 0; i < num && i < 16; i += freestep) { + if (i == x) { + continue; + } + mem_free(p[i]); + p[i] = NULL; + } + for(i = 0; i < num && i < 16; i++) { + if (i == x) { + continue; + } + if (p[i] != NULL) { + mem_free(p[i]); + p[i] = NULL; + } + } + fail_unless(p[x] != NULL); + mem_free(p[x]); +} + +START_TEST(test_mem_random) +{ + const int num = 16; + int x; + int size; + int freestep; + LWIP_UNUSED_ARG(_i); + + fail_unless(lwip_stats.mem.used == 0); + + for (x = 0; x < num; x++) { + for (size = 1; size < 32; size++) { + for (freestep = 1; freestep <= 3; freestep++) { + fail_unless(lwip_stats.mem.used == 0); + malloc_keep_x(x, num, size, freestep); + fail_unless(lwip_stats.mem.used == 0); + } + } + } +} +END_TEST + +/** Create the suite including all tests for this module */ +Suite * +mem_suite(void) +{ + testfunc tests[] = { + TESTFUNC(test_mem_one), + TESTFUNC(test_mem_random) + }; + return create_suite("MEM", tests, sizeof(tests)/sizeof(testfunc), mem_setup, mem_teardown); +} diff --git a/components/net/lwip-2.0.3/test/unit/core/test_mem.h b/components/net/lwip-2.0.3/test/unit/core/test_mem.h new file mode 100644 index 0000000000..325134c30a --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/core/test_mem.h @@ -0,0 +1,8 @@ +#ifndef LWIP_HDR_TEST_MEM_H +#define LWIP_HDR_TEST_MEM_H + +#include "../lwip_check.h" + +Suite *mem_suite(void); + +#endif diff --git a/components/net/lwip-2.0.3/test/unit/core/test_pbuf.c b/components/net/lwip-2.0.3/test/unit/core/test_pbuf.c new file mode 100644 index 0000000000..9315c4c635 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/core/test_pbuf.c @@ -0,0 +1,239 @@ +#include "test_pbuf.h" + +#include "lwip/pbuf.h" +#include "lwip/stats.h" + +#if !LWIP_STATS || !MEM_STATS ||!MEMP_STATS +#error "This tests needs MEM- and MEMP-statistics enabled" +#endif +#if LWIP_DNS +#error "This test needs DNS turned off (as it mallocs on init)" +#endif +#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !LWIP_WND_SCALE +#error "This test needs TCP OOSEQ queueing and window scaling enabled" +#endif + +/* Setups/teardown functions */ + +static void +pbuf_setup(void) +{ +} + +static void +pbuf_teardown(void) +{ +} + + +#define TESTBUFSIZE_1 65535 +#define TESTBUFSIZE_2 65530 +#define TESTBUFSIZE_3 50050 +static u8_t testbuf_1[TESTBUFSIZE_1]; +static u8_t testbuf_1a[TESTBUFSIZE_1]; +static u8_t testbuf_2[TESTBUFSIZE_2]; +static u8_t testbuf_2a[TESTBUFSIZE_2]; +static u8_t testbuf_3[TESTBUFSIZE_3]; +static u8_t testbuf_3a[TESTBUFSIZE_3]; + +/* Test functions */ + +/** Call pbuf_copy on a pbuf with zero length */ +START_TEST(test_pbuf_copy_zero_pbuf) +{ + struct pbuf *p1, *p2, *p3; + err_t err; + LWIP_UNUSED_ARG(_i); + + fail_unless(lwip_stats.mem.used == 0); + fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0); + + p1 = pbuf_alloc(PBUF_RAW, 1024, PBUF_RAM); + fail_unless(p1 != NULL); + fail_unless(p1->ref == 1); + + p2 = pbuf_alloc(PBUF_RAW, 2, PBUF_POOL); + fail_unless(p2 != NULL); + fail_unless(p2->ref == 1); + p2->len = p2->tot_len = 0; + + pbuf_cat(p1, p2); + fail_unless(p1->ref == 1); + fail_unless(p2->ref == 1); + + p3 = pbuf_alloc(PBUF_RAW, p1->tot_len, PBUF_POOL); + err = pbuf_copy(p3, p1); + fail_unless(err == ERR_VAL); + + pbuf_free(p1); + pbuf_free(p3); + fail_unless(lwip_stats.mem.used == 0); + + fail_unless(lwip_stats.mem.used == 0); + fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0); +} +END_TEST + +START_TEST(test_pbuf_split_64k_on_small_pbufs) +{ + struct pbuf *p, *rest=NULL; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, 1, PBUF_POOL); + pbuf_split_64k(p, &rest); + fail_unless(p->tot_len == 1); + pbuf_free(p); +} +END_TEST + +START_TEST(test_pbuf_queueing_bigger_than_64k) +{ + int i; + err_t err; + struct pbuf *p1, *p2, *p3, *rest2=NULL, *rest3=NULL; + LWIP_UNUSED_ARG(_i); + + for(i = 0; i < TESTBUFSIZE_1; i++) { + testbuf_1[i] = (u8_t)rand(); + } + for(i = 0; i < TESTBUFSIZE_2; i++) { + testbuf_2[i] = (u8_t)rand(); + } + for(i = 0; i < TESTBUFSIZE_3; i++) { + testbuf_3[i] = (u8_t)rand(); + } + + p1 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_1, PBUF_POOL); + fail_unless(p1 != NULL); + p2 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_2, PBUF_POOL); + fail_unless(p2 != NULL); + p3 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_3, PBUF_POOL); + fail_unless(p3 != NULL); + err = pbuf_take(p1, testbuf_1, TESTBUFSIZE_1); + fail_unless(err == ERR_OK); + err = pbuf_take(p2, testbuf_2, TESTBUFSIZE_2); + fail_unless(err == ERR_OK); + err = pbuf_take(p3, testbuf_3, TESTBUFSIZE_3); + fail_unless(err == ERR_OK); + + pbuf_cat(p1, p2); + pbuf_cat(p1, p3); + + pbuf_split_64k(p1, &rest2); + fail_unless(p1->tot_len == TESTBUFSIZE_1); + fail_unless(rest2->tot_len == (u16_t)((TESTBUFSIZE_2+TESTBUFSIZE_3) & 0xFFFF)); + pbuf_split_64k(rest2, &rest3); + fail_unless(rest2->tot_len == TESTBUFSIZE_2); + fail_unless(rest3->tot_len == TESTBUFSIZE_3); + + pbuf_copy_partial(p1, testbuf_1a, TESTBUFSIZE_1, 0); + pbuf_copy_partial(rest2, testbuf_2a, TESTBUFSIZE_2, 0); + pbuf_copy_partial(rest3, testbuf_3a, TESTBUFSIZE_3, 0); + for(i = 0; i < TESTBUFSIZE_1; i++) + fail_unless(testbuf_1[i] == testbuf_1a[i]); + for(i = 0; i < TESTBUFSIZE_2; i++) + fail_unless(testbuf_2[i] == testbuf_2a[i]); + for(i = 0; i < TESTBUFSIZE_3; i++) + fail_unless(testbuf_3[i] == testbuf_3a[i]); + + pbuf_free(p1); + pbuf_free(rest2); + pbuf_free(rest3); +} +END_TEST + +/* Test for bug that writing with pbuf_take_at() did nothing + * and returned ERR_OK when writing at beginning of a pbuf + * in the chain. + */ +START_TEST(test_pbuf_take_at_edge) +{ + err_t res; + u8_t *out; + int i; + u8_t testdata[] = { 0x01, 0x08, 0x82, 0x02 }; + struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL); + struct pbuf *q = p->next; + LWIP_UNUSED_ARG(_i); + /* alloc big enough to get a chain of pbufs */ + fail_if(p->tot_len == p->len); + memset(p->payload, 0, p->len); + memset(q->payload, 0, q->len); + + /* copy data to the beginning of first pbuf */ + res = pbuf_take_at(p, &testdata, sizeof(testdata), 0); + fail_unless(res == ERR_OK); + + out = (u8_t*)p->payload; + for (i = 0; i < (int)sizeof(testdata); i++) { + fail_unless(out[i] == testdata[i], + "Bad data at pos %d, was %02X, expected %02X", i, out[i], testdata[i]); + } + + /* copy data to the just before end of first pbuf */ + res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len - 1); + fail_unless(res == ERR_OK); + + out = (u8_t*)p->payload; + fail_unless(out[p->len - 1] == testdata[0], + "Bad data at pos %d, was %02X, expected %02X", p->len - 1, out[p->len - 1], testdata[0]); + out = (u8_t*)q->payload; + for (i = 1; i < (int)sizeof(testdata); i++) { + fail_unless(out[i-1] == testdata[i], + "Bad data at pos %d, was %02X, expected %02X", p->len - 1 + i, out[i-1], testdata[i]); + } + + /* copy data to the beginning of second pbuf */ + res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len); + fail_unless(res == ERR_OK); + + out = (u8_t*)p->payload; + for (i = 0; i < (int)sizeof(testdata); i++) { + fail_unless(out[i] == testdata[i], + "Bad data at pos %d, was %02X, expected %02X", p->len+i, out[i], testdata[i]); + } +} +END_TEST + +/* Verify pbuf_put_at()/pbuf_get_at() when using + * offsets equal to beginning of new pbuf in chain + */ +START_TEST(test_pbuf_get_put_at_edge) +{ + u8_t *out; + u8_t testdata = 0x01; + u8_t getdata; + struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL); + struct pbuf *q = p->next; + LWIP_UNUSED_ARG(_i); + /* alloc big enough to get a chain of pbufs */ + fail_if(p->tot_len == p->len); + memset(p->payload, 0, p->len); + memset(q->payload, 0, q->len); + + /* put byte at the beginning of second pbuf */ + pbuf_put_at(p, p->len, testdata); + + out = (u8_t*)q->payload; + fail_unless(*out == testdata, + "Bad data at pos %d, was %02X, expected %02X", p->len, *out, testdata); + + getdata = pbuf_get_at(p, p->len); + fail_unless(*out == getdata, + "pbuf_get_at() returned bad data at pos %d, was %02X, expected %02X", p->len, getdata, *out); +} +END_TEST + +/** Create the suite including all tests for this module */ +Suite * +pbuf_suite(void) +{ + testfunc tests[] = { + TESTFUNC(test_pbuf_copy_zero_pbuf), + TESTFUNC(test_pbuf_split_64k_on_small_pbufs), + TESTFUNC(test_pbuf_queueing_bigger_than_64k), + TESTFUNC(test_pbuf_take_at_edge), + TESTFUNC(test_pbuf_get_put_at_edge) + }; + return create_suite("PBUF", tests, sizeof(tests)/sizeof(testfunc), pbuf_setup, pbuf_teardown); +} diff --git a/components/net/lwip-2.0.3/test/unit/core/test_pbuf.h b/components/net/lwip-2.0.3/test/unit/core/test_pbuf.h new file mode 100644 index 0000000000..da7730a4c8 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/core/test_pbuf.h @@ -0,0 +1,8 @@ +#ifndef LWIP_HDR_TEST_PBUF_H +#define LWIP_HDR_TEST_PBUF_H + +#include "../lwip_check.h" + +Suite *pbuf_suite(void); + +#endif diff --git a/components/net/lwip-2.0.3/test/unit/dhcp/test_dhcp.c b/components/net/lwip-2.0.3/test/unit/dhcp/test_dhcp.c new file mode 100644 index 0000000000..47aaa08420 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/dhcp/test_dhcp.c @@ -0,0 +1,1024 @@ +#include "test_dhcp.h" + +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/prot/dhcp.h" +#include "lwip/etharp.h" +#include "netif/ethernet.h" + +struct netif net_test; + +static const u8_t broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + +static const u8_t magic_cookie[] = { 0x63, 0x82, 0x53, 0x63 }; + +static u8_t dhcp_offer[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */ + 0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */ + 0x08, 0x00, /* Protocol: IP */ + 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */ + 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */ + + 0x02, /* Type == Boot reply */ + 0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */ + 0x00, /* 0 hops */ + 0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */ + 0x00, 0x00, /* 0 seconds elapsed */ + 0x00, 0x00, /* Flags (unicast) */ + 0x00, 0x00, 0x00, 0x00, /* Client ip */ + 0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */ + 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */ + 0x00, 0x00, 0x00, 0x00, /* relay agent */ + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */ + + /* Empty server name and boot file name */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + 0x63, 0x82, 0x53, 0x63, /* Magic cookie */ + 0x35, 0x01, 0x02, /* Message type: Offer */ + 0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */ + 0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */ + 0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */ + 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */ + 0xff, /* End option */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */ +}; + +static u8_t dhcp_ack[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */ + 0x00, 0x0f, 0xEE, 0x30, 0xAB, 0x22, /* From remote host */ + 0x08, 0x00, /* Proto IP */ + 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */ + 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */ + 0x02, /* Bootp reply */ + 0x01, 0x06, /* Hw type Eth, len 6 */ + 0x00, /* 0 hops */ + 0xAA, 0xAA, 0xAA, 0xAA, + 0x00, 0x00, /* 0 seconds elapsed */ + 0x00, 0x00, /* Flags (unicast) */ + 0x00, 0x00, 0x00, 0x00, /* Client IP */ + 0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */ + 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server IP */ + 0x00, 0x00, 0x00, 0x00, /* Relay agent */ + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Macaddr + padding */ + + /* Empty server name and boot file name */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + 0x63, 0x82, 0x53, 0x63, /* Magic cookie */ + 0x35, 0x01, 0x05, /* Dhcp message type ack */ + 0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server identifier */ + 0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */ + 0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */ + 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Netmask */ + 0xff, /* End marker */ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */ +}; + +static const u8_t arpreply[] = { + 0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* dst mac */ + 0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* src mac */ + 0x08, 0x06, /* proto arp */ + 0x00, 0x01, /* hw eth */ + 0x08, 0x00, /* proto ip */ + 0x06, /* hw addr len 6 */ + 0x04, /* proto addr len 4 */ + 0x00, 0x02, /* arp reply */ + 0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* sender mac */ + 0xc3, 0xaa, 0xbd, 0xc8, /* sender ip */ + 0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* target mac */ + 0x00, 0x00, 0x00, 0x00, /* target ip */ +}; + +static int txpacket; +static enum tcase { + TEST_LWIP_DHCP, + TEST_LWIP_DHCP_NAK, + TEST_LWIP_DHCP_RELAY, + TEST_LWIP_DHCP_NAK_NO_ENDMARKER, + TEST_LWIP_DHCP_INVALID_OVERLOAD +} tcase; + +static int debug = 0; +static void setdebug(int a) {debug = a;} + +static int tick = 0; +static void tick_lwip(void) +{ + tick++; + if (tick % 5 == 0) { + dhcp_fine_tmr(); + } + if (tick % 600 == 0) { + dhcp_coarse_tmr(); + } +} + +static void send_pkt(struct netif *netif, const u8_t *data, size_t len) +{ + struct pbuf *p, *q; + LWIP_ASSERT("pkt too big", len <= 0xFFFF); + p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL); + + if (debug) { + /* Dump data */ + u32_t i; + printf("RX data (len %d)", p->tot_len); + for (i = 0; i < len; i++) { + printf(" %02X", data[i]); + } + printf("\n"); + } + + fail_unless(p != NULL); + for(q = p; q != NULL; q = q->next) { + memcpy(q->payload, data, q->len); + data += q->len; + } + netif->input(p, netif); +} + +static err_t lwip_tx_func(struct netif *netif, struct pbuf *p); + +static err_t testif_init(struct netif *netif) +{ + netif->name[0] = 'c'; + netif->name[1] = 'h'; + netif->output = etharp_output; + netif->linkoutput = lwip_tx_func; + netif->mtu = 1500; + netif->hwaddr_len = 6; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + + netif->hwaddr[0] = 0x00; + netif->hwaddr[1] = 0x23; + netif->hwaddr[2] = 0xC1; + netif->hwaddr[3] = 0xDE; + netif->hwaddr[4] = 0xD0; + netif->hwaddr[5] = 0x0D; + + return ERR_OK; +} + +static void dhcp_setup(void) +{ + txpacket = 0; +} + +static void dhcp_teardown(void) +{ +} + +static void check_pkt(struct pbuf *p, u32_t pos, const u8_t *mem, u32_t len) +{ + u8_t *data; + + fail_if((pos + len) > p->tot_len); + while (pos > p->len && p->next) { + pos -= p->len; + p = p->next; + } + fail_if(p == NULL); + fail_unless(pos + len <= p->len); /* All data we seek within same pbuf */ + + data = (u8_t*)p->payload; + fail_if(memcmp(&data[pos], mem, len), "data at pos %d, len %d in packet %d did not match", pos, len, txpacket); +} + +static void check_pkt_fuzzy(struct pbuf *p, u32_t startpos, const u8_t *mem, u32_t len) +{ + int found; + u32_t i; + u8_t *data; + + fail_if((startpos + len) > p->tot_len); + while (startpos > p->len && p->next) { + startpos -= p->len; + p = p->next; + } + fail_if(p == NULL); + fail_unless(startpos + len <= p->len); /* All data we seek within same pbuf */ + + found = 0; + data = (u8_t*)p->payload; + for (i = startpos; i <= (p->len - len); i++) { + if (memcmp(&data[i], mem, len) == 0) { + found = 1; + break; + } + } + fail_unless(found); +} + +static err_t lwip_tx_func(struct netif *netif, struct pbuf *p) +{ + fail_unless(netif == &net_test); + txpacket++; + + if (debug) { + struct pbuf *pp = p; + /* Dump data */ + printf("TX data (pkt %d, len %d, tick %d)", txpacket, p->tot_len, tick); + do { + int i; + for (i = 0; i < pp->len; i++) { + printf(" %02X", ((u8_t *) pp->payload)[i]); + } + if (pp->next) { + pp = pp->next; + } + } while (pp->next); + printf("\n"); + } + + switch (tcase) { + case TEST_LWIP_DHCP: + switch (txpacket) { + case 1: + case 2: + { + const u8_t ipproto[] = { 0x08, 0x00 }; + const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ + const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ + + check_pkt(p, 42, bootp_start, sizeof(bootp_start)); + + check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); + + check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ + + check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); + + /* Check dchp message type, can be at different positions */ + if (txpacket == 1) { + u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 }; + check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt)); + } else if (txpacket == 2) { + u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; + u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* Ask for offered IP */ + + check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); + check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); + } + break; + } + case 3: + case 4: + case 5: + { + const u8_t arpproto[] = { 0x08, 0x06 }; + + check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */ + break; + } + default: + fail(); + break; + } + break; + + case TEST_LWIP_DHCP_NAK: + { + const u8_t ipproto[] = { 0x08, 0x00 }; + const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ + const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const u8_t dhcp_nak_opt[] = { 0x35, 0x01, 0x04 }; + const u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* offered IP */ + + fail_unless(txpacket == 4); + check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ + + check_pkt(p, 42, bootp_start, sizeof(bootp_start)); + + check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); + + check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ + + check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); + + check_pkt_fuzzy(p, 282, dhcp_nak_opt, sizeof(dhcp_nak_opt)); /* NAK the ack */ + + check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); + break; + } + + case TEST_LWIP_DHCP_RELAY: + switch (txpacket) { + case 1: + case 2: + { + const u8_t ipproto[] = { 0x08, 0x00 }; + const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ + const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ + + check_pkt(p, 42, bootp_start, sizeof(bootp_start)); + + check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); + + check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ + + check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); + + /* Check dchp message type, can be at different positions */ + if (txpacket == 1) { + u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 }; + check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt)); + } else if (txpacket == 2) { + u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; + u8_t requested_ipaddr[] = { 0x32, 0x04, 0x4f, 0x8a, 0x33, 0x05 }; /* Ask for offered IP */ + + check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); + check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); + } + break; + } + case 3: + case 4: + case 5: + case 6: + { + const u8_t arpproto[] = { 0x08, 0x06 }; + + check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */ + break; + } + case 7: + { + const u8_t fake_arp[6] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xab }; + const u8_t ipproto[] = { 0x08, 0x00 }; + const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ + const u8_t ipaddrs[] = { 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; + + check_pkt(p, 0, fake_arp, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ + + check_pkt(p, 42, bootp_start, sizeof(bootp_start)); + + check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); + + check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ + + check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); + + /* Check dchp message type, can be at different positions */ + check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); + break; + } + default: + fail(); + break; + } + break; + + default: + break; + } + + return ERR_OK; +} + +/* + * Test basic happy flow DHCP session. + * Validate that xid is checked. + */ +START_TEST(test_dhcp) +{ + ip4_addr_t addr; + ip4_addr_t netmask; + ip4_addr_t gw; + int i; + u32_t xid; + LWIP_UNUSED_ARG(_i); + + tcase = TEST_LWIP_DHCP; + setdebug(0); + + IP4_ADDR(&addr, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); + IP4_ADDR(&gw, 0, 0, 0, 0); + + netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); + netif_set_up(&net_test); + + dhcp_start(&net_test); + + fail_unless(txpacket == 1); /* DHCP discover sent */ + xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ + memcpy(&dhcp_offer[46], &xid, 4); + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + /* IP addresses should be zero */ + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); + + fail_unless(txpacket == 1, "TX %d packets, expected 1", txpacket); /* Nothing more sent */ + xid = htonl(netif_dhcp_data(&net_test)->xid); + memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + fail_unless(txpacket == 2, "TX %d packets, expected 2", txpacket); /* DHCP request sent */ + xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ + memcpy(&dhcp_ack[46], &xid, 4); + send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); + + fail_unless(txpacket == 2, "TX %d packets, still expected 2", txpacket); /* No more sent */ + xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ + memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */ + send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); + + for (i = 0; i < 20; i++) { + tick_lwip(); + } + fail_unless(txpacket == 5, "TX %d packets, expected 5", txpacket); /* ARP requests sent */ + + /* Interface up */ + fail_unless(netif_is_up(&net_test)); + + /* Now it should have taken the IP */ + IP4_ADDR(&addr, 195, 170, 189, 200); + IP4_ADDR(&netmask, 255, 255, 255, 0); + IP4_ADDR(&gw, 195, 170, 189, 171); + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); + + netif_remove(&net_test); +} +END_TEST + +/* + * Test that IP address is not taken and NAK is sent if someone + * replies to ARP requests for the offered address. + */ +START_TEST(test_dhcp_nak) +{ + ip4_addr_t addr; + ip4_addr_t netmask; + ip4_addr_t gw; + u32_t xid; + LWIP_UNUSED_ARG(_i); + + tcase = TEST_LWIP_DHCP; + setdebug(0); + + IP4_ADDR(&addr, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); + IP4_ADDR(&gw, 0, 0, 0, 0); + + netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); + netif_set_up(&net_test); + + dhcp_start(&net_test); + + fail_unless(txpacket == 1); /* DHCP discover sent */ + xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ + memcpy(&dhcp_offer[46], &xid, 4); + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + /* IP addresses should be zero */ + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); + + fail_unless(txpacket == 1); /* Nothing more sent */ + xid = htonl(netif_dhcp_data(&net_test)->xid); + memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + fail_unless(txpacket == 2); /* DHCP request sent */ + xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ + memcpy(&dhcp_ack[46], &xid, 4); + send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); + + fail_unless(txpacket == 2); /* No more sent */ + xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ + memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */ + send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); + + fail_unless(txpacket == 3); /* ARP request sent */ + + tcase = TEST_LWIP_DHCP_NAK; /* Switch testcase */ + + /* Send arp reply, mark offered IP as taken */ + send_pkt(&net_test, arpreply, sizeof(arpreply)); + + fail_unless(txpacket == 4); /* DHCP nak sent */ + + netif_remove(&net_test); +} +END_TEST + +/* + * Test case based on captured data where + * replies are sent from a different IP than the + * one the client unicasted to. + */ +START_TEST(test_dhcp_relayed) +{ + u8_t relay_offer[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, + 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, + 0x08, 0x00, 0x45, 0x00, + 0x01, 0x38, 0xfd, 0x53, 0x00, 0x00, 0x40, 0x11, + 0x78, 0x46, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, + 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, + 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35, + 0xb6, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, + 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, + 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, + 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, + 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, + 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, + 0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x02, 0x36, + 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff + }; + + u8_t relay_ack1[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x22, + 0x93, 0x5a, 0xf7, 0x60, 0x08, 0x00, 0x45, 0x00, + 0x01, 0x38, 0xfd, 0x55, 0x00, 0x00, 0x40, 0x11, + 0x78, 0x44, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, + 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, + 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35, + 0xb6, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, + 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, + 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, + 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, + 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, + 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, + 0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x05, 0x36, + 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff + }; + + u8_t relay_ack2[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, + 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, + 0x08, 0x00, 0x45, 0x00, + 0x01, 0x38, 0xfa, 0x18, 0x00, 0x00, 0x40, 0x11, + 0x7b, 0x81, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, + 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, + 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x49, 0x8b, + 0x6e, 0xab, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x8a, + 0x33, 0x05, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, + 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, + 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, + 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, + 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, + 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, + 0x00, 0x00, 0x54, 0x60, 0x35, 0x01, 0x05, 0x36, + 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff }; + + const u8_t arp_resp[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* DEST */ + 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, /* SRC */ + 0x08, 0x06, /* Type: ARP */ + 0x00, 0x01, /* HW: Ethernet */ + 0x08, 0x00, /* PROTO: IP */ + 0x06, /* HW size */ + 0x04, /* PROTO size */ + 0x00, 0x02, /* OPCODE: Reply */ + + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, /* Target MAC */ + 0x4f, 0x8a, 0x32, 0x01, /* Target IP */ + + 0x00, 0x23, 0xc1, 0x00, 0x06, 0x50, /* src mac */ + 0x4f, 0x8a, 0x33, 0x05, /* src ip */ + + /* Padding follows.. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + + ip4_addr_t addr; + ip4_addr_t netmask; + ip4_addr_t gw; + int i; + u32_t xid; + LWIP_UNUSED_ARG(_i); + + tcase = TEST_LWIP_DHCP_RELAY; + setdebug(0); + + IP4_ADDR(&addr, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); + IP4_ADDR(&gw, 0, 0, 0, 0); + + netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); + netif_set_up(&net_test); + + dhcp_start(&net_test); + + fail_unless(txpacket == 1); /* DHCP discover sent */ + + /* IP addresses should be zero */ + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); + + fail_unless(txpacket == 1); /* Nothing more sent */ + xid = htonl(netif_dhcp_data(&net_test)->xid); + memcpy(&relay_offer[46], &xid, 4); /* insert correct transaction id */ + send_pkt(&net_test, relay_offer, sizeof(relay_offer)); + + /* request sent? */ + fail_unless(txpacket == 2, "txpkt = %d, should be 2", txpacket); + xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ + memcpy(&relay_ack1[46], &xid, 4); /* insert transaction id */ + send_pkt(&net_test, relay_ack1, sizeof(relay_ack1)); + + for (i = 0; i < 25; i++) { + tick_lwip(); + } + fail_unless(txpacket == 5, "txpkt should be 5, is %d", txpacket); /* ARP requests sent */ + + /* Interface up */ + fail_unless(netif_is_up(&net_test)); + + /* Now it should have taken the IP */ + IP4_ADDR(&addr, 79, 138, 51, 5); + IP4_ADDR(&netmask, 255, 255, 254, 0); + IP4_ADDR(&gw, 79, 138, 50, 1); + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); + + fail_unless(txpacket == 5, "txpacket = %d", txpacket); + + for (i = 0; i < 108000 - 25; i++) { + tick_lwip(); + } + + fail_unless(netif_is_up(&net_test)); + fail_unless(txpacket == 6, "txpacket = %d", txpacket); + + /* We need to send arp response here.. */ + + send_pkt(&net_test, arp_resp, sizeof(arp_resp)); + + fail_unless(txpacket == 7, "txpacket = %d", txpacket); + fail_unless(netif_is_up(&net_test)); + + xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ + memcpy(&relay_ack2[46], &xid, 4); /* insert transaction id */ + send_pkt(&net_test, relay_ack2, sizeof(relay_ack2)); + + for (i = 0; i < 100000; i++) { + tick_lwip(); + } + + fail_unless(txpacket == 7, "txpacket = %d", txpacket); + + netif_remove(&net_test); + +} +END_TEST + +START_TEST(test_dhcp_nak_no_endmarker) +{ + ip4_addr_t addr; + ip4_addr_t netmask; + ip4_addr_t gw; + + u8_t dhcp_nack_no_endmarker[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x54, 0x75, + 0xd0, 0x26, 0xd0, 0x0d, 0x08, 0x00, 0x45, 0x00, + 0x01, 0x15, 0x38, 0x86, 0x00, 0x00, 0xff, 0x11, + 0xc0, 0xa8, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x43, 0x00, 0x44, 0x01, 0x01, + 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x7a, 0xcb, + 0xba, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, + 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, + 0x53, 0x63, 0x35, 0x01, 0x06, 0x36, 0x04, 0xc0, + 0xa8, 0x01, 0x01, 0x31, 0xef, 0xad, 0x72, 0x31, + 0x43, 0x4e, 0x44, 0x30, 0x32, 0x35, 0x30, 0x43, + 0x52, 0x47, 0x44, 0x38, 0x35, 0x36, 0x3c, 0x08, + 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30, + 0x37, 0x0d, 0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e, + 0x2f, 0x1f, 0x21, 0x79, 0xf9, 0x2b, 0xfc, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x71, + 0xf3, 0x5b, 0xe2, 0x71, 0x2e, 0x01, 0x08, 0x03, + 0x04, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xeb, 0x1e, + 0x44, 0xec, 0xeb, 0x1e, 0x30, 0x37, 0x0c, 0x01, + 0x0f, 0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, 0x21, + 0x79, 0xf9, 0x2b, 0xff, 0x25, 0xc0, 0x09, 0xd6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + u32_t xid; + LWIP_UNUSED_ARG(_i); + + tcase = TEST_LWIP_DHCP_NAK_NO_ENDMARKER; + setdebug(0); + + IP4_ADDR(&addr, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); + IP4_ADDR(&gw, 0, 0, 0, 0); + + netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); + netif_set_up(&net_test); + + dhcp_start(&net_test); + + fail_unless(txpacket == 1); /* DHCP discover sent */ + xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ + memcpy(&dhcp_offer[46], &xid, 4); + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + /* IP addresses should be zero */ + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); + + fail_unless(txpacket == 1); /* Nothing more sent */ + xid = htonl(netif_dhcp_data(&net_test)->xid); + memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + fail_unless(netif_dhcp_data(&net_test)->state == DHCP_STATE_REQUESTING); + + fail_unless(txpacket == 2); /* No more sent */ + xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ + memcpy(&dhcp_nack_no_endmarker[46], &xid, 4); /* insert transaction id */ + send_pkt(&net_test, dhcp_nack_no_endmarker, sizeof(dhcp_nack_no_endmarker)); + + /* NAK should put us in another state for a while, no other way detecting it */ + fail_unless(netif_dhcp_data(&net_test)->state != DHCP_STATE_REQUESTING); + + netif_remove(&net_test); +} +END_TEST + +START_TEST(test_dhcp_invalid_overload) +{ + u8_t dhcp_offer_invalid_overload[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */ + 0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */ + 0x08, 0x00, /* Protocol: IP */ + 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */ + 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */ + + 0x02, /* Type == Boot reply */ + 0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */ + 0x00, /* 0 hops */ + 0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */ + 0x00, 0x00, /* 0 seconds elapsed */ + 0x00, 0x00, /* Flags (unicast) */ + 0x00, 0x00, 0x00, 0x00, /* Client ip */ + 0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */ + 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */ + 0x00, 0x00, 0x00, 0x00, /* relay agent */ + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */ + + /* Empty server name */ + 0x34, 0x01, 0x02, 0xff, /* Overload: SNAME + END */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Empty boot file name */ + 0x34, 0x01, 0x01, 0xff, /* Overload FILE + END */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x63, 0x82, 0x53, 0x63, /* Magic cookie */ + 0x35, 0x01, 0x02, /* Message type: Offer */ + 0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */ + 0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */ + 0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */ + 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */ + 0x34, 0x01, 0x03, /* Overload: FILE + SNAME */ + 0xff, /* End option */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */ + }; + ip4_addr_t addr; + ip4_addr_t netmask; + ip4_addr_t gw; + u32_t xid; + LWIP_UNUSED_ARG(_i); + + tcase = TEST_LWIP_DHCP_INVALID_OVERLOAD; + setdebug(0); + + IP4_ADDR(&addr, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); + IP4_ADDR(&gw, 0, 0, 0, 0); + + netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); + netif_set_up(&net_test); + + dhcp_start(&net_test); + + fail_unless(txpacket == 1); /* DHCP discover sent */ + xid = htonl(netif_dhcp_data(&net_test)->xid); + memcpy(&dhcp_offer_invalid_overload[46], &xid, 4); /* insert correct transaction id */ + dhcp_offer_invalid_overload[311] = 3; + send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload)); + /* IP addresses should be zero */ + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); + fail_unless(txpacket == 1); /* Nothing more sent */ + + dhcp_offer_invalid_overload[311] = 2; + send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload)); + /* IP addresses should be zero */ + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); + fail_unless(txpacket == 1); /* Nothing more sent */ + + dhcp_offer_invalid_overload[311] = 1; + send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload)); + /* IP addresses should be zero */ + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); + fail_unless(txpacket == 1); /* Nothing more sent */ + + dhcp_offer_invalid_overload[311] = 0; + send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer)); + + fail_unless(netif_dhcp_data(&net_test)->state == DHCP_STATE_REQUESTING); + + fail_unless(txpacket == 2); /* No more sent */ + xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ + + netif_remove(&net_test); +} +END_TEST + +/** Create the suite including all tests for this module */ +Suite * +dhcp_suite(void) +{ + testfunc tests[] = { + TESTFUNC(test_dhcp), + TESTFUNC(test_dhcp_nak), + TESTFUNC(test_dhcp_relayed), + TESTFUNC(test_dhcp_nak_no_endmarker), + TESTFUNC(test_dhcp_invalid_overload) + }; + return create_suite("DHCP", tests, sizeof(tests)/sizeof(testfunc), dhcp_setup, dhcp_teardown); +} diff --git a/components/net/lwip-2.0.3/test/unit/dhcp/test_dhcp.h b/components/net/lwip-2.0.3/test/unit/dhcp/test_dhcp.h new file mode 100644 index 0000000000..0d88fa1b69 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/dhcp/test_dhcp.h @@ -0,0 +1,8 @@ +#ifndef LWIP_HDR_TEST_DHCP_H +#define LWIP_HDR_TEST_DHCP_H + +#include "../lwip_check.h" + +Suite* dhcp_suite(void); + +#endif diff --git a/components/net/lwip-2.0.3/test/unit/etharp/test_etharp.c b/components/net/lwip-2.0.3/test/unit/etharp/test_etharp.c new file mode 100644 index 0000000000..59d73b9b45 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/etharp/test_etharp.c @@ -0,0 +1,269 @@ +#include "test_etharp.h" + +#include "lwip/udp.h" +#include "lwip/etharp.h" +#include "netif/ethernet.h" +#include "lwip/stats.h" + +#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS || !ETHARP_STATS +#error "This tests needs UDP-, MEMP- and ETHARP-statistics enabled" +#endif +#if !ETHARP_SUPPORT_STATIC_ENTRIES +#error "This test needs ETHARP_SUPPORT_STATIC_ENTRIES enabled" +#endif + +static struct netif test_netif; +static ip4_addr_t test_ipaddr, test_netmask, test_gw; +struct eth_addr test_ethaddr = {{1,1,1,1,1,1}}; +struct eth_addr test_ethaddr2 = {{1,1,1,1,1,2}}; +struct eth_addr test_ethaddr3 = {{1,1,1,1,1,3}}; +struct eth_addr test_ethaddr4 = {{1,1,1,1,1,4}}; +static int linkoutput_ctr; + +/* Helper functions */ +static void +etharp_remove_all(void) +{ + int i; + /* call etharp_tmr often enough to have all entries cleaned */ + for(i = 0; i < 0xff; i++) { + etharp_tmr(); + } +} + +static err_t +default_netif_linkoutput(struct netif *netif, struct pbuf *p) +{ + fail_unless(netif == &test_netif); + fail_unless(p != NULL); + linkoutput_ctr++; + return ERR_OK; +} + +static err_t +default_netif_init(struct netif *netif) +{ + fail_unless(netif != NULL); + netif->linkoutput = default_netif_linkoutput; + netif->output = etharp_output; + netif->mtu = 1500; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + netif->hwaddr_len = ETHARP_HWADDR_LEN; + return ERR_OK; +} + +static void +default_netif_add(void) +{ + IP4_ADDR(&test_gw, 192,168,0,1); + IP4_ADDR(&test_ipaddr, 192,168,0,1); + IP4_ADDR(&test_netmask, 255,255,0,0); + + fail_unless(netif_default == NULL); + netif_set_default(netif_add(&test_netif, &test_ipaddr, &test_netmask, + &test_gw, NULL, default_netif_init, NULL)); + netif_set_up(&test_netif); +} + +static void +default_netif_remove(void) +{ + fail_unless(netif_default == &test_netif); + netif_remove(&test_netif); +} + +static void +create_arp_response(ip4_addr_t *adr) +{ + int k; + struct eth_hdr *ethhdr; + struct etharp_hdr *etharphdr; + struct pbuf *p = pbuf_alloc(PBUF_RAW, sizeof(struct eth_hdr) + sizeof(struct etharp_hdr), PBUF_RAM); + if(p == NULL) { + FAIL_RET(); + } + ethhdr = (struct eth_hdr*)p->payload; + etharphdr = (struct etharp_hdr*)(ethhdr + 1); + + ethhdr->dest = test_ethaddr; + ethhdr->src = test_ethaddr2; + ethhdr->type = htons(ETHTYPE_ARP); + + etharphdr->hwtype = htons(/*HWTYPE_ETHERNET*/ 1); + etharphdr->proto = htons(ETHTYPE_IP); + etharphdr->hwlen = ETHARP_HWADDR_LEN; + etharphdr->protolen = sizeof(ip4_addr_t); + etharphdr->opcode = htons(ARP_REPLY); + + SMEMCPY(ðarphdr->sipaddr, adr, sizeof(ip4_addr_t)); + SMEMCPY(ðarphdr->dipaddr, &test_ipaddr, sizeof(ip4_addr_t)); + + k = 6; + while(k > 0) { + k--; + /* Write the ARP MAC-Addresses */ + etharphdr->shwaddr.addr[k] = test_ethaddr2.addr[k]; + etharphdr->dhwaddr.addr[k] = test_ethaddr.addr[k]; + /* Write the Ethernet MAC-Addresses */ + ethhdr->dest.addr[k] = test_ethaddr.addr[k]; + ethhdr->src.addr[k] = test_ethaddr2.addr[k]; + } + + ethernet_input(p, &test_netif); +} + +/* Setups/teardown functions */ + +static void +etharp_setup(void) +{ + etharp_remove_all(); + default_netif_add(); +} + +static void +etharp_teardown(void) +{ + etharp_remove_all(); + default_netif_remove(); +} + + +/* Test functions */ + +START_TEST(test_etharp_table) +{ +#if ETHARP_SUPPORT_STATIC_ENTRIES + err_t err; +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + s8_t idx; + const ip4_addr_t *unused_ipaddr; + struct eth_addr *unused_ethaddr; + struct udp_pcb* pcb; + LWIP_UNUSED_ARG(_i); + + if (netif_default != &test_netif) { + fail("This test needs a default netif"); + } + + linkoutput_ctr = 0; + + pcb = udp_new(); + fail_unless(pcb != NULL); + if (pcb != NULL) { + ip4_addr_t adrs[ARP_TABLE_SIZE + 2]; + int i; + for(i = 0; i < ARP_TABLE_SIZE + 2; i++) { + IP4_ADDR(&adrs[i], 192,168,0,i+2); + } + /* fill ARP-table with dynamic entries */ + for(i = 0; i < ARP_TABLE_SIZE; i++) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); + fail_unless(p != NULL); + if (p != NULL) { + err_t err2; + ip_addr_t dst; + ip_addr_copy_from_ip4(dst, adrs[i]); + err2 = udp_sendto(pcb, p, &dst, 123); + fail_unless(err2 == ERR_OK); + /* etharp request sent? */ + fail_unless(linkoutput_ctr == (2*i) + 1); + pbuf_free(p); + + /* create an ARP response */ + create_arp_response(&adrs[i]); + /* queued UDP packet sent? */ + fail_unless(linkoutput_ctr == (2*i) + 2); + + idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == i); + etharp_tmr(); + } + } + linkoutput_ctr = 0; +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* create one static entry */ + err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE], &test_ethaddr3); + fail_unless(err == ERR_OK); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == 0); + fail_unless(linkoutput_ctr == 0); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + + linkoutput_ctr = 0; + /* fill ARP-table with dynamic entries */ + for(i = 0; i < ARP_TABLE_SIZE; i++) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); + fail_unless(p != NULL); + if (p != NULL) { + err_t err2; + ip_addr_t dst; + ip_addr_copy_from_ip4(dst, adrs[i]); + err2 = udp_sendto(pcb, p, &dst, 123); + fail_unless(err2 == ERR_OK); + /* etharp request sent? */ + fail_unless(linkoutput_ctr == (2*i) + 1); + pbuf_free(p); + + /* create an ARP response */ + create_arp_response(&adrs[i]); + /* queued UDP packet sent? */ + fail_unless(linkoutput_ctr == (2*i) + 2); + + idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); + if (i < ARP_TABLE_SIZE - 1) { + fail_unless(idx == i+1); + } else { + /* the last entry must not overwrite the static entry! */ + fail_unless(idx == 1); + } + etharp_tmr(); + } + } +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* create a second static entry */ + err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE+1], &test_ethaddr4); + fail_unless(err == ERR_OK); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == 0); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == 2); + /* and remove it again */ + err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE+1]); + fail_unless(err == ERR_OK); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == 0); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == -1); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + + /* check that static entries don't time out */ + etharp_remove_all(); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == 0); + +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* remove the first static entry */ + err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE]); + fail_unless(err == ERR_OK); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == -1); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == -1); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + + udp_remove(pcb); + } +} +END_TEST + + +/** Create the suite including all tests for this module */ +Suite * +etharp_suite(void) +{ + testfunc tests[] = { + TESTFUNC(test_etharp_table) + }; + return create_suite("ETHARP", tests, sizeof(tests)/sizeof(testfunc), etharp_setup, etharp_teardown); +} diff --git a/components/net/lwip-2.0.3/test/unit/etharp/test_etharp.h b/components/net/lwip-2.0.3/test/unit/etharp/test_etharp.h new file mode 100644 index 0000000000..2dd772d8d0 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/etharp/test_etharp.h @@ -0,0 +1,8 @@ +#ifndef LWIP_HDR_TEST_ETHARP_H +#define LWIP_HDR_TEST_ETHARP_H + +#include "../lwip_check.h" + +Suite* etharp_suite(void); + +#endif diff --git a/components/net/lwip-2.0.3/test/unit/ip4/test_ip4.c b/components/net/lwip-2.0.3/test/unit/ip4/test_ip4.c new file mode 100644 index 0000000000..e0e82d8d55 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/ip4/test_ip4.c @@ -0,0 +1,154 @@ +#include "test_ip4.h" + +#include "lwip/ip4.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/prot/ip.h" +#include "lwip/prot/ip4.h" + +#if !LWIP_IPV4 || !IP_REASSEMBLY || !MIB2_STATS || !IPFRAG_STATS +#error "This tests needs LWIP_IPV4, IP_REASSEMBLY; MIB2- and IPFRAG-statistics enabled" +#endif + +/* Helper functions */ +static void +create_ip4_input_fragment(u16_t ip_id, u16_t start, u16_t len, int last) +{ + struct pbuf *p; + struct netif *input_netif = netif_list; /* just use any netif */ + fail_unless((start & 7) == 0); + fail_unless(((len & 7) == 0) || last); + fail_unless(input_netif != NULL); + + p = pbuf_alloc(PBUF_RAW, len + sizeof(struct ip_hdr), PBUF_RAM); + fail_unless(p != NULL); + if (p != NULL) { + err_t err; + struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; + IPH_VHL_SET(iphdr, 4, sizeof(struct ip_hdr) / 4); + IPH_TOS_SET(iphdr, 0); + IPH_LEN_SET(iphdr, lwip_htons(p->tot_len)); + IPH_ID_SET(iphdr, lwip_htons(ip_id)); + if (last) { + IPH_OFFSET_SET(iphdr, lwip_htons(start / 8)); + } else { + IPH_OFFSET_SET(iphdr, lwip_htons((start / 8) | IP_MF)); + } + IPH_TTL_SET(iphdr, 5); + IPH_PROTO_SET(iphdr, IP_PROTO_UDP); + IPH_CHKSUM_SET(iphdr, 0); + ip4_addr_copy(iphdr->src, *netif_ip4_addr(input_netif)); + iphdr->src.addr = lwip_htonl(lwip_htonl(iphdr->src.addr) + 1); + ip4_addr_copy(iphdr->dest, *netif_ip4_addr(input_netif)); + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, sizeof(struct ip_hdr))); + + err = ip4_input(p, input_netif); + if (err != ERR_OK) { + pbuf_free(p); + } + fail_unless(err == ERR_OK); + } +} + +/* Setups/teardown functions */ + +static void +ip4_setup(void) +{ +} + +static void +ip4_teardown(void) +{ + if (netif_list->loop_first != NULL) { + pbuf_free(netif_list->loop_first); + netif_list->loop_first = NULL; + } + netif_list->loop_last = NULL; +} + + +/* Test functions */ + +START_TEST(test_ip4_reass) +{ + const u16_t ip_id = 128; + LWIP_UNUSED_ARG(_i); + + memset(&lwip_stats.mib2, 0, sizeof(lwip_stats.mib2)); + + create_ip4_input_fragment(ip_id, 8*200, 200, 1); + fail_unless(lwip_stats.ip_frag.recv == 1); + fail_unless(lwip_stats.ip_frag.err == 0); + fail_unless(lwip_stats.ip_frag.memerr == 0); + fail_unless(lwip_stats.ip_frag.drop == 0); + fail_unless(lwip_stats.mib2.ipreasmoks == 0); + + create_ip4_input_fragment(ip_id, 0*200, 200, 0); + fail_unless(lwip_stats.ip_frag.recv == 2); + fail_unless(lwip_stats.ip_frag.err == 0); + fail_unless(lwip_stats.ip_frag.memerr == 0); + fail_unless(lwip_stats.ip_frag.drop == 0); + fail_unless(lwip_stats.mib2.ipreasmoks == 0); + + create_ip4_input_fragment(ip_id, 1*200, 200, 0); + fail_unless(lwip_stats.ip_frag.recv == 3); + fail_unless(lwip_stats.ip_frag.err == 0); + fail_unless(lwip_stats.ip_frag.memerr == 0); + fail_unless(lwip_stats.ip_frag.drop == 0); + fail_unless(lwip_stats.mib2.ipreasmoks == 0); + + create_ip4_input_fragment(ip_id, 2*200, 200, 0); + fail_unless(lwip_stats.ip_frag.recv == 4); + fail_unless(lwip_stats.ip_frag.err == 0); + fail_unless(lwip_stats.ip_frag.memerr == 0); + fail_unless(lwip_stats.ip_frag.drop == 0); + fail_unless(lwip_stats.mib2.ipreasmoks == 0); + + create_ip4_input_fragment(ip_id, 3*200, 200, 0); + fail_unless(lwip_stats.ip_frag.recv == 5); + fail_unless(lwip_stats.ip_frag.err == 0); + fail_unless(lwip_stats.ip_frag.memerr == 0); + fail_unless(lwip_stats.ip_frag.drop == 0); + fail_unless(lwip_stats.mib2.ipreasmoks == 0); + + create_ip4_input_fragment(ip_id, 4*200, 200, 0); + fail_unless(lwip_stats.ip_frag.recv == 6); + fail_unless(lwip_stats.ip_frag.err == 0); + fail_unless(lwip_stats.ip_frag.memerr == 0); + fail_unless(lwip_stats.ip_frag.drop == 0); + fail_unless(lwip_stats.mib2.ipreasmoks == 0); + + create_ip4_input_fragment(ip_id, 7*200, 200, 0); + fail_unless(lwip_stats.ip_frag.recv == 7); + fail_unless(lwip_stats.ip_frag.err == 0); + fail_unless(lwip_stats.ip_frag.memerr == 0); + fail_unless(lwip_stats.ip_frag.drop == 0); + fail_unless(lwip_stats.mib2.ipreasmoks == 0); + + create_ip4_input_fragment(ip_id, 6*200, 200, 0); + fail_unless(lwip_stats.ip_frag.recv == 8); + fail_unless(lwip_stats.ip_frag.err == 0); + fail_unless(lwip_stats.ip_frag.memerr == 0); + fail_unless(lwip_stats.ip_frag.drop == 0); + fail_unless(lwip_stats.mib2.ipreasmoks == 0); + + create_ip4_input_fragment(ip_id, 5*200, 200, 0); + fail_unless(lwip_stats.ip_frag.recv == 9); + fail_unless(lwip_stats.ip_frag.err == 0); + fail_unless(lwip_stats.ip_frag.memerr == 0); + fail_unless(lwip_stats.ip_frag.drop == 0); + fail_unless(lwip_stats.mib2.ipreasmoks == 1); +} +END_TEST + + +/** Create the suite including all tests for this module */ +Suite * +ip4_suite(void) +{ + testfunc tests[] = { + TESTFUNC(test_ip4_reass), + }; + return create_suite("IPv4", tests, sizeof(tests)/sizeof(testfunc), ip4_setup, ip4_teardown); +} diff --git a/components/net/lwip-2.0.3/test/unit/ip4/test_ip4.h b/components/net/lwip-2.0.3/test/unit/ip4/test_ip4.h new file mode 100644 index 0000000000..df84a69f1a --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/ip4/test_ip4.h @@ -0,0 +1,8 @@ +#ifndef LWIP_HDR_TEST_IP4_H +#define LWIP_HDR_TEST_IP4_H + +#include "../lwip_check.h" + +Suite* ip4_suite(void); + +#endif diff --git a/components/net/lwip-2.0.3/test/unit/lwip_check.h b/components/net/lwip-2.0.3/test/unit/lwip_check.h new file mode 100644 index 0000000000..0c218d1d16 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/lwip_check.h @@ -0,0 +1,37 @@ +#ifndef LWIP_HDR_LWIP_CHECK_H +#define LWIP_HDR_LWIP_CHECK_H + +/* Common header file for lwIP unit tests using the check framework */ + +#include +#include +#include + +#define FAIL_RET() do { fail(); return; } while(0) +#define EXPECT(x) fail_unless(x) +#define EXPECT_RET(x) do { fail_unless(x); if(!(x)) { return; }} while(0) +#define EXPECT_RETX(x, y) do { fail_unless(x); if(!(x)) { return y; }} while(0) +#define EXPECT_RETNULL(x) EXPECT_RETX(x, NULL) + +typedef struct { + TFun func; + const char *name; +} testfunc; + +#define TESTFUNC(x) {(x), "" # x "" } + +/* Modified function from check.h, supplying function name */ +#define tcase_add_named_test(tc,tf) \ + _tcase_add_test((tc),(tf).func,(tf).name,0, 0, 0, 1) + +/** typedef for a function returning a test suite */ +typedef Suite* (suite_getter_fn)(void); + +/** Create a test suite */ +Suite* create_suite(const char* name, testfunc *tests, size_t num_tests, SFun setup, SFun teardown); + +#ifdef LWIP_UNITTESTS_LIB +int lwip_unittests_run(void) +#endif + +#endif /* LWIP_HDR_LWIP_CHECK_H */ diff --git a/components/net/lwip-2.0.3/test/unit/lwip_unittests.c b/components/net/lwip-2.0.3/test/unit/lwip_unittests.c new file mode 100644 index 0000000000..76be87067e --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/lwip_unittests.c @@ -0,0 +1,72 @@ +#include "lwip_check.h" + +#include "ip4/test_ip4.h" +#include "udp/test_udp.h" +#include "tcp/test_tcp.h" +#include "tcp/test_tcp_oos.h" +#include "core/test_mem.h" +#include "core/test_pbuf.h" +#include "etharp/test_etharp.h" +#include "dhcp/test_dhcp.h" +#include "mdns/test_mdns.h" + +#include "lwip/init.h" + +Suite* create_suite(const char* name, testfunc *tests, size_t num_tests, SFun setup, SFun teardown) +{ + size_t i; + Suite *s = suite_create(name); + + for(i = 0; i < num_tests; i++) { + TCase *tc_core = tcase_create(name); + if ((setup != NULL) || (teardown != NULL)) { + tcase_add_checked_fixture(tc_core, setup, teardown); + } + tcase_add_named_test(tc_core, tests[i]); + suite_add_tcase(s, tc_core); + } + return s; +} + +#ifdef LWIP_UNITTESTS_LIB +int lwip_unittests_run(void) +#else +int main(void) +#endif +{ + int number_failed; + SRunner *sr; + size_t i; + suite_getter_fn* suites[] = { + ip4_suite, + udp_suite, + tcp_suite, + tcp_oos_suite, + mem_suite, + pbuf_suite, + etharp_suite, + dhcp_suite, + mdns_suite + }; + size_t num = sizeof(suites)/sizeof(void*); + LWIP_ASSERT("No suites defined", num > 0); + + lwip_init(); + + sr = srunner_create((suites[0])()); + for(i = 1; i < num; i++) { + srunner_add_suite(sr, ((suite_getter_fn*)suites[i])()); + } + +#ifdef LWIP_UNITTESTS_NOFORK + srunner_set_fork_status(sr, CK_NOFORK); +#endif +#ifdef LWIP_UNITTESTS_FORK + srunner_set_fork_status(sr, CK_FORK); +#endif + + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/components/net/lwip-2.0.3/test/unit/lwipopts.h b/components/net/lwip-2.0.3/test/unit/lwipopts.h new file mode 100644 index 0000000000..fc2ca5dec0 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/lwipopts.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_LWIPOPTS_H +#define LWIP_HDR_LWIPOPTS_H + +/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ +#define NO_SYS 1 +#define SYS_LIGHTWEIGHT_PROT 0 +#define LWIP_NETCONN 0 +#define LWIP_SOCKET 0 + +/* Enable DHCP to test it, disable UDP checksum to easier inject packets */ +#define LWIP_DHCP 1 + +/* Minimal changes to opt.h required for tcp unit tests: */ +#define MEM_SIZE 16000 +#define TCP_SND_QUEUELEN 40 +#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN +#define TCP_SND_BUF (12 * TCP_MSS) +#define TCP_WND (10 * TCP_MSS) +#define LWIP_WND_SCALE 1 +#define TCP_RCV_SCALE 0 +#define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */ + +/* Enable IGMP and MDNS for MDNS tests */ +#define LWIP_IGMP 1 +#define LWIP_MDNS_RESPONDER 1 +#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER) + +/* Minimal changes to opt.h required for etharp unit tests: */ +#define ETHARP_SUPPORT_STATIC_ENTRIES 1 + +/* MIB2 stats are required to check IPv4 reassembly results */ +#define MIB2_STATS 1 + +#endif /* LWIP_HDR_LWIPOPTS_H */ diff --git a/components/net/lwip-2.0.3/test/unit/mdns/test_mdns.c b/components/net/lwip-2.0.3/test/unit/mdns/test_mdns.c new file mode 100644 index 0000000000..ca9be64ea1 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/mdns/test_mdns.c @@ -0,0 +1,915 @@ +/* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ + +#include "test_mdns.h" + +#include "lwip/pbuf.h" +#include "lwip/apps/mdns.h" +#include "lwip/apps/mdns_priv.h" + +START_TEST(readname_basic) +{ + static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == sizeof(data)); + fail_unless(domain.length == sizeof(data)); + fail_if(memcmp(&domain.name, data, sizeof(data))); +} +END_TEST + +START_TEST(readname_anydata) +{ + static const u8_t data[] = { 0x05, 0x00, 0xFF, 0x08, 0xc0, 0x0f, 0x04, 0x7f, 0x80, 0x82, 0x88, 0x00 }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == sizeof(data)); + fail_unless(domain.length == sizeof(data)); + fail_if(memcmp(&domain.name, data, sizeof(data))); +} +END_TEST + +START_TEST(readname_short_buf) +{ + static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a' }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_long_label) +{ + static const u8_t data[] = { + 0x05, 'm', 'u', 'l', 't', 'i', + 0x52, 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_overflow) +{ + static const u8_t data[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_jump_earlier) +{ + static const u8_t data[] = { + /* Some padding needed, not supported to jump to bytes containing dns header */ + /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 10 */ 0x0f, 0x0e, 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab, + /* 20 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x0c + }; + static const u8_t fullname[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 20, &domain); + pbuf_free(p); + fail_unless(offset == sizeof(data)); + fail_unless(domain.length == sizeof(fullname)); + + fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); +} +END_TEST + +START_TEST(readname_jump_earlier_jump) +{ + static const u8_t data[] = { + /* Some padding needed, not supported to jump to bytes containing dns header */ + /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2, + /* 0x10 */ 0x04, 'c', 'a', 's', 't', 0x00, 0xc0, 0x10, + /* 0x18 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x16 + }; + static const u8_t fullname[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0x18, &domain); + pbuf_free(p); + fail_unless(offset == sizeof(data)); + fail_unless(domain.length == sizeof(fullname)); + + fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); +} +END_TEST + +START_TEST(readname_jump_maxdepth) +{ + static const u8_t data[] = { + /* Some padding needed, not supported to jump to bytes containing dns header */ + /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2, + /* 0x10 */ 0x04, 'n', 'a', 'm', 'e', 0xc0, 0x27, 0x03, + /* 0x18 */ 0x03, 'd', 'n', 's', 0xc0, 0x10, 0xc0, 0x10, + /* 0x20 */ 0x04, 'd', 'e', 'e', 'p', 0xc0, 0x18, 0x00, + /* 0x28 */ 0x04, 'c', 'a', 's', 't', 0xc0, 0x20, 0xb0, + /* 0x30 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x28 + }; + static const u8_t fullname[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', + 0x04, 'd', 'e', 'e', 'p', 0x03, 'd', 'n', 's', + 0x04, 'n', 'a', 'm', 'e', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0x30, &domain); + pbuf_free(p); + fail_unless(offset == sizeof(data)); + fail_unless(domain.length == sizeof(fullname)); + + fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); +} +END_TEST + +START_TEST(readname_jump_later) +{ + static const u8_t data[] = { + /* 0x00 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10, 0x00, 0x01, 0x40, + /* 0x10 */ 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab + }; + static const u8_t fullname[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == 13); + fail_unless(domain.length == sizeof(fullname)); + + fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); +} +END_TEST + +START_TEST(readname_half_jump) +{ + static const u8_t data[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_jump_toolong) +{ + static const u8_t data[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc2, 0x10, 0x00, 0x01, 0x40 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 0, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_jump_loop_label) +{ + static const u8_t data[] = { + /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 10, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(readname_jump_loop_jump) +{ + static const u8_t data[] = { + /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x15 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + offset = mdns_readname(p, 10, &domain); + pbuf_free(p); + fail_unless(offset == MDNS_READNAME_ERROR); +} +END_TEST + +START_TEST(add_label_basic) +{ + static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 }; + struct mdns_domain domain; + err_t res; + LWIP_UNUSED_ARG(_i); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + fail_unless(domain.length == sizeof(data)); + fail_if(memcmp(&domain.name, data, sizeof(data))); +} +END_TEST + +START_TEST(add_label_long_label) +{ + static const char *toolong = "abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-"; + struct mdns_domain domain; + err_t res; + LWIP_UNUSED_ARG(_i); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, toolong, (u8_t)strlen(toolong)); + fail_unless(res == ERR_VAL); +} +END_TEST + +START_TEST(add_label_full) +{ + static const char *label = "0123456789abcdef0123456789abcdef"; + struct mdns_domain domain; + err_t res; + LWIP_UNUSED_ARG(_i); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 33); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 66); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 99); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 132); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 165); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 198); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 231); + res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); + fail_unless(res == ERR_VAL); + fail_unless(domain.length == 231); + res = mdns_domain_add_label(&domain, label, 25); + fail_unless(res == ERR_VAL); + fail_unless(domain.length == 231); + res = mdns_domain_add_label(&domain, label, 24); + fail_unless(res == ERR_VAL); + fail_unless(domain.length == 231); + res = mdns_domain_add_label(&domain, label, 23); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 255); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + fail_unless(domain.length == 256); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_VAL); + fail_unless(domain.length == 256); +} +END_TEST + +START_TEST(domain_eq_basic) +{ + static const u8_t data[] = { + 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 + }; + struct mdns_domain domain1, domain2; + err_t res; + LWIP_UNUSED_ARG(_i); + + memset(&domain1, 0, sizeof(domain1)); + res = mdns_domain_add_label(&domain1, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, NULL, 0); + fail_unless(res == ERR_OK); + fail_unless(domain1.length == sizeof(data)); + + memset(&domain2, 0, sizeof(domain2)); + res = mdns_domain_add_label(&domain2, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, NULL, 0); + fail_unless(res == ERR_OK); + + fail_unless(mdns_domain_eq(&domain1, &domain2)); +} +END_TEST + +START_TEST(domain_eq_diff) +{ + struct mdns_domain domain1, domain2; + err_t res; + LWIP_UNUSED_ARG(_i); + + memset(&domain1, 0, sizeof(domain1)); + res = mdns_domain_add_label(&domain1, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, "base", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, NULL, 0); + fail_unless(res == ERR_OK); + + memset(&domain2, 0, sizeof(domain2)); + res = mdns_domain_add_label(&domain2, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, NULL, 0); + fail_unless(res == ERR_OK); + + fail_if(mdns_domain_eq(&domain1, &domain2)); +} +END_TEST + +START_TEST(domain_eq_case) +{ + struct mdns_domain domain1, domain2; + err_t res; + LWIP_UNUSED_ARG(_i); + + memset(&domain1, 0, sizeof(domain1)); + res = mdns_domain_add_label(&domain1, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, NULL, 0); + fail_unless(res == ERR_OK); + + memset(&domain2, 0, sizeof(domain2)); + res = mdns_domain_add_label(&domain2, "MulTI", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, "casT", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, NULL, 0); + fail_unless(res == ERR_OK); + + fail_unless(mdns_domain_eq(&domain1, &domain2)); +} +END_TEST + +START_TEST(domain_eq_anydata) +{ + static const u8_t data1[] = { 0x05, 0xcc, 0xdc, 0x00, 0xa0 }; + static const u8_t data2[] = { 0x7f, 0x8c, 0x01, 0xff, 0xcf }; + struct mdns_domain domain1, domain2; + err_t res; + LWIP_UNUSED_ARG(_i); + + memset(&domain1, 0, sizeof(domain1)); + res = mdns_domain_add_label(&domain1, (const char*)data1, sizeof(data1)); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, "cast", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, (const char*)data2, sizeof(data2)); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, NULL, 0); + fail_unless(res == ERR_OK); + + memset(&domain2, 0, sizeof(domain2)); + res = mdns_domain_add_label(&domain2, (const char*)data1, sizeof(data1)); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, "casT", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, (const char*)data2, sizeof(data2)); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, NULL, 0); + fail_unless(res == ERR_OK); + + fail_unless(mdns_domain_eq(&domain1, &domain2)); +} +END_TEST + +START_TEST(domain_eq_length) +{ + struct mdns_domain domain1, domain2; + err_t res; + LWIP_UNUSED_ARG(_i); + + memset(&domain1, 0, sizeof(domain1)); + memset(domain1.name, 0xAA, sizeof(MDNS_DOMAIN_MAXLEN)); + res = mdns_domain_add_label(&domain1, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain1, "cast", 4); + fail_unless(res == ERR_OK); + + memset(&domain2, 0, sizeof(domain2)); + memset(domain2.name, 0xBB, sizeof(MDNS_DOMAIN_MAXLEN)); + res = mdns_domain_add_label(&domain2, "multi", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain2, "cast", 4); + fail_unless(res == ERR_OK); + + fail_unless(mdns_domain_eq(&domain1, &domain2)); +} +END_TEST + +START_TEST(compress_full_match) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 0 bytes, then a jump to addr 2 */ + fail_unless(length == 0); + fail_unless(offset == 2); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_full_match_subset) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x02, 'g', 'o', 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 0 bytes, then a jump to addr 5 */ + fail_unless(length == 0); + fail_unless(offset == 5); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_full_match_jump) +{ + static const u8_t data[] = { + /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + /* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00, + /* 0x20 */ 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0xc0, 0x15 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 0x20; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 0 bytes, then a jump to addr 0x20 */ + fail_unless(length == 0); + fail_unless(offset == 0x20); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_no_match) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x04, 'l', 'w', 'i', 'p', 0x05, 'w', 'i', 'k', 'i', 'a', 0x03, 'c', 'o', 'm', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + /* Write all bytes, no jump */ + fail_unless(length == domain.length); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_2nd_label) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "lwip", 4); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 5 bytes, then a jump to addr 9 */ + fail_unless(length == 5); + fail_unless(offset == 9); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_2nd_label_short) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 5 bytes, then a jump to addr 7 */ + fail_unless(length == 7); + fail_unless(offset == 7); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_jump_to_jump) +{ + static const u8_t data[] = { + /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + /* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00, + /* 0x20 */ 0x07, 'b', 'a', 'n', 'a', 'n', 'a', 's', 0xc0, 0x15 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 0x20; + length = mdns_compress_domain(p, &offset, &domain); + /* Dont compress if jump would be to a jump */ + fail_unless(length == domain.length); + + offset = 0x10; + length = mdns_compress_domain(p, &offset, &domain); + /* Write 7 bytes, then a jump to addr 0x15 */ + fail_unless(length == 7); + fail_unless(offset == 0x15); + + pbuf_free(p); +} +END_TEST + +START_TEST(compress_long_match) +{ + static const u8_t data[] = { + 0x00, 0x00, + 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x03, 'c', 'o', 'm', 0x00 + }; + struct pbuf *p; + struct mdns_domain domain; + u16_t offset; + u16_t length; + err_t res; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); + p->payload = (void *)(size_t)data; + fail_if(p == NULL); + + memset(&domain, 0, sizeof(domain)); + res = mdns_domain_add_label(&domain, "foobar", 6); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, "local", 5); + fail_unless(res == ERR_OK); + res = mdns_domain_add_label(&domain, NULL, 0); + fail_unless(res == ERR_OK); + + offset = 2; + length = mdns_compress_domain(p, &offset, &domain); + fail_unless(length == domain.length); + + pbuf_free(p); +} +END_TEST + +Suite* mdns_suite(void) +{ + testfunc tests[] = { + TESTFUNC(readname_basic), + TESTFUNC(readname_anydata), + TESTFUNC(readname_short_buf), + TESTFUNC(readname_long_label), + TESTFUNC(readname_overflow), + TESTFUNC(readname_jump_earlier), + TESTFUNC(readname_jump_earlier_jump), + TESTFUNC(readname_jump_maxdepth), + TESTFUNC(readname_jump_later), + TESTFUNC(readname_half_jump), + TESTFUNC(readname_jump_toolong), + TESTFUNC(readname_jump_loop_label), + TESTFUNC(readname_jump_loop_jump), + + TESTFUNC(add_label_basic), + TESTFUNC(add_label_long_label), + TESTFUNC(add_label_full), + + TESTFUNC(domain_eq_basic), + TESTFUNC(domain_eq_diff), + TESTFUNC(domain_eq_case), + TESTFUNC(domain_eq_anydata), + TESTFUNC(domain_eq_length), + + TESTFUNC(compress_full_match), + TESTFUNC(compress_full_match_subset), + TESTFUNC(compress_full_match_jump), + TESTFUNC(compress_no_match), + TESTFUNC(compress_2nd_label), + TESTFUNC(compress_2nd_label_short), + TESTFUNC(compress_jump_to_jump), + TESTFUNC(compress_long_match), + }; + return create_suite("MDNS", tests, sizeof(tests)/sizeof(testfunc), NULL, NULL); +} diff --git a/components/net/lwip-2.0.3/test/unit/mdns/test_mdns.h b/components/net/lwip-2.0.3/test/unit/mdns/test_mdns.h new file mode 100644 index 0000000000..c3df339140 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/mdns/test_mdns.h @@ -0,0 +1,8 @@ +#ifndef LWIP_HDR_TEST_MDNS_H__ +#define LWIP_HDR_TEST_MDNS_H__ + +#include "../lwip_check.h" + +Suite* mdns_suite(void); + +#endif diff --git a/components/net/lwip-2.0.3/test/unit/tcp/tcp_helper.c b/components/net/lwip-2.0.3/test/unit/tcp/tcp_helper.c new file mode 100644 index 0000000000..64121ca8f3 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/tcp/tcp_helper.c @@ -0,0 +1,314 @@ +#include "tcp_helper.h" + +#include "lwip/priv/tcp_priv.h" +#include "lwip/stats.h" +#include "lwip/pbuf.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip_addr.h" + +#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS +#error "This tests needs TCP- and MEMP-statistics enabled" +#endif + +/** Remove all pcbs on the given list. */ +static void +tcp_remove(struct tcp_pcb* pcb_list) +{ + struct tcp_pcb *pcb = pcb_list; + struct tcp_pcb *pcb2; + + while(pcb != NULL) { + pcb2 = pcb; + pcb = pcb->next; + tcp_abort(pcb2); + } +} + +/** Remove all pcbs on listen-, active- and time-wait-list (bound- isn't exported). */ +void +tcp_remove_all(void) +{ + tcp_remove(tcp_listen_pcbs.pcbs); + tcp_remove(tcp_active_pcbs); + tcp_remove(tcp_tw_pcbs); + fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); + fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) == 0); + fail_unless(MEMP_STATS_GET(used, MEMP_TCP_SEG) == 0); + fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0); +} + +/** Create a TCP segment usable for passing to tcp_input */ +static struct pbuf* +tcp_create_segment_wnd(ip_addr_t* src_ip, ip_addr_t* dst_ip, + u16_t src_port, u16_t dst_port, void* data, size_t data_len, + u32_t seqno, u32_t ackno, u8_t headerflags, u16_t wnd) +{ + struct pbuf *p, *q; + struct ip_hdr* iphdr; + struct tcp_hdr* tcphdr; + u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len); + LWIP_ASSERT("data_len too big", data_len <= 0xFFFF); + + p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL); + EXPECT_RETNULL(p != NULL); + /* first pbuf must be big enough to hold the headers */ + EXPECT_RETNULL(p->len >= (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr))); + if (data_len > 0) { + /* first pbuf must be big enough to hold at least 1 data byte, too */ + EXPECT_RETNULL(p->len > (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr))); + } + + for(q = p; q != NULL; q = q->next) { + memset(q->payload, 0, q->len); + } + + iphdr = (struct ip_hdr*)p->payload; + /* fill IP header */ + iphdr->dest.addr = ip_2_ip4(dst_ip)->addr; + iphdr->src.addr = ip_2_ip4(src_ip)->addr; + IPH_VHL_SET(iphdr, 4, IP_HLEN / 4); + IPH_TOS_SET(iphdr, 0); + IPH_LEN_SET(iphdr, htons(p->tot_len)); + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + + /* let p point to TCP header */ + pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); + + tcphdr = (struct tcp_hdr*)p->payload; + tcphdr->src = htons(src_port); + tcphdr->dest = htons(dst_port); + tcphdr->seqno = htonl(seqno); + tcphdr->ackno = htonl(ackno); + TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4); + TCPH_FLAGS_SET(tcphdr, headerflags); + tcphdr->wnd = htons(wnd); + + if (data_len > 0) { + /* let p point to TCP data */ + pbuf_header(p, -(s16_t)sizeof(struct tcp_hdr)); + /* copy data */ + pbuf_take(p, data, (u16_t)data_len); + /* let p point to TCP header again */ + pbuf_header(p, sizeof(struct tcp_hdr)); + } + + /* calculate checksum */ + + tcphdr->chksum = ip_chksum_pseudo(p, + IP_PROTO_TCP, p->tot_len, src_ip, dst_ip); + + pbuf_header(p, sizeof(struct ip_hdr)); + + return p; +} + +/** Create a TCP segment usable for passing to tcp_input */ +struct pbuf* +tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip, + u16_t src_port, u16_t dst_port, void* data, size_t data_len, + u32_t seqno, u32_t ackno, u8_t headerflags) +{ + return tcp_create_segment_wnd(src_ip, dst_ip, src_port, dst_port, data, + data_len, seqno, ackno, headerflags, TCP_WND); +} + +/** Create a TCP segment usable for passing to tcp_input + * - IP-addresses, ports, seqno and ackno are taken from pcb + * - seqno and ackno can be altered with an offset + */ +struct pbuf* +tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, u32_t seqno_offset, + u32_t ackno_offset, u8_t headerflags) +{ + return tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port, + data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags); +} + +/** Create a TCP segment usable for passing to tcp_input + * - IP-addresses, ports, seqno and ackno are taken from pcb + * - seqno and ackno can be altered with an offset + * - TCP window can be adjusted + */ +struct pbuf* tcp_create_rx_segment_wnd(struct tcp_pcb* pcb, void* data, size_t data_len, + u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd) +{ + return tcp_create_segment_wnd(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port, + data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags, wnd); +} + +/** Safely bring a tcp_pcb into the requested state */ +void +tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip, + ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port) +{ + u32_t iss; + + /* @todo: are these all states? */ + /* @todo: remove from previous list */ + pcb->state = state; + + iss = tcp_next_iss(pcb); + pcb->snd_wl2 = iss; + pcb->snd_nxt = iss; + pcb->lastack = iss; + pcb->snd_lbb = iss; + + if (state == ESTABLISHED) { + TCP_REG(&tcp_active_pcbs, pcb); + ip_addr_copy(pcb->local_ip, *local_ip); + pcb->local_port = local_port; + ip_addr_copy(pcb->remote_ip, *remote_ip); + pcb->remote_port = remote_port; + } else if(state == LISTEN) { + TCP_REG(&tcp_listen_pcbs.pcbs, pcb); + ip_addr_copy(pcb->local_ip, *local_ip); + pcb->local_port = local_port; + } else if(state == TIME_WAIT) { + TCP_REG(&tcp_tw_pcbs, pcb); + ip_addr_copy(pcb->local_ip, *local_ip); + pcb->local_port = local_port; + ip_addr_copy(pcb->remote_ip, *remote_ip); + pcb->remote_port = remote_port; + } else { + fail(); + } +} + +void +test_tcp_counters_err(void* arg, err_t err) +{ + struct test_tcp_counters* counters = (struct test_tcp_counters*)arg; + EXPECT_RET(arg != NULL); + counters->err_calls++; + counters->last_err = err; +} + +static void +test_tcp_counters_check_rxdata(struct test_tcp_counters* counters, struct pbuf* p) +{ + struct pbuf* q; + u32_t i, received; + if(counters->expected_data == NULL) { + /* no data to compare */ + return; + } + EXPECT_RET(counters->recved_bytes + p->tot_len <= counters->expected_data_len); + received = counters->recved_bytes; + for(q = p; q != NULL; q = q->next) { + char *data = (char*)q->payload; + for(i = 0; i < q->len; i++) { + EXPECT_RET(data[i] == counters->expected_data[received]); + received++; + } + } + EXPECT(received == counters->recved_bytes + p->tot_len); +} + +err_t +test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err) +{ + struct test_tcp_counters* counters = (struct test_tcp_counters*)arg; + EXPECT_RETX(arg != NULL, ERR_OK); + EXPECT_RETX(pcb != NULL, ERR_OK); + EXPECT_RETX(err == ERR_OK, ERR_OK); + + if (p != NULL) { + if (counters->close_calls == 0) { + counters->recv_calls++; + test_tcp_counters_check_rxdata(counters, p); + counters->recved_bytes += p->tot_len; + } else { + counters->recv_calls_after_close++; + counters->recved_bytes_after_close += p->tot_len; + } + pbuf_free(p); + } else { + counters->close_calls++; + } + EXPECT(counters->recv_calls_after_close == 0 && counters->recved_bytes_after_close == 0); + return ERR_OK; +} + +/** Allocate a pcb and set up the test_tcp_counters_* callbacks */ +struct tcp_pcb* +test_tcp_new_counters_pcb(struct test_tcp_counters* counters) +{ + struct tcp_pcb* pcb = tcp_new(); + if (pcb != NULL) { + /* set up args and callbacks */ + tcp_arg(pcb, counters); + tcp_recv(pcb, test_tcp_counters_recv); + tcp_err(pcb, test_tcp_counters_err); + pcb->snd_wnd = TCP_WND; + pcb->snd_wnd_max = TCP_WND; + } + return pcb; +} + +/** Calls tcp_input() after adjusting current_iphdr_dest */ +void test_tcp_input(struct pbuf *p, struct netif *inp) +{ + struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; + /* these lines are a hack, don't use them as an example :-) */ + ip_addr_copy_from_ip4(*ip_current_dest_addr(), iphdr->dest); + ip_addr_copy_from_ip4(*ip_current_src_addr(), iphdr->src); + ip_current_netif() = inp; + ip_data.current_ip4_header = iphdr; + + /* since adding IPv6, p->payload must point to tcp header, not ip header */ + pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); + + tcp_input(p, inp); + + ip_addr_set_zero(ip_current_dest_addr()); + ip_addr_set_zero(ip_current_src_addr()); + ip_current_netif() = NULL; + ip_data.current_ip4_header = NULL; +} + +static err_t test_tcp_netif_output(struct netif *netif, struct pbuf *p, + const ip4_addr_t *ipaddr) +{ + struct test_tcp_txcounters *txcounters = (struct test_tcp_txcounters*)netif->state; + LWIP_UNUSED_ARG(ipaddr); + if (txcounters != NULL) + { + txcounters->num_tx_calls++; + txcounters->num_tx_bytes += p->tot_len; + if (txcounters->copy_tx_packets) { + struct pbuf *p_copy = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + err_t err; + EXPECT(p_copy != NULL); + err = pbuf_copy(p_copy, p); + EXPECT(err == ERR_OK); + if (txcounters->tx_packets == NULL) { + txcounters->tx_packets = p_copy; + } else { + pbuf_cat(txcounters->tx_packets, p_copy); + } + } + } + return ERR_OK; +} + +void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters, + ip_addr_t *ip_addr, ip_addr_t *netmask) +{ + struct netif *n; + memset(netif, 0, sizeof(struct netif)); + if (txcounters != NULL) { + memset(txcounters, 0, sizeof(struct test_tcp_txcounters)); + netif->state = txcounters; + } + netif->output = test_tcp_netif_output; + netif->flags |= NETIF_FLAG_UP | NETIF_FLAG_LINK_UP; + ip_addr_copy_from_ip4(netif->netmask, *ip_2_ip4(netmask)); + ip_addr_copy_from_ip4(netif->ip_addr, *ip_2_ip4(ip_addr)); + for (n = netif_list; n != NULL; n = n->next) { + if (n == netif) { + return; + } + } + netif->next = NULL; + netif_list = netif; +} diff --git a/components/net/lwip-2.0.3/test/unit/tcp/tcp_helper.h b/components/net/lwip-2.0.3/test/unit/tcp/tcp_helper.h new file mode 100644 index 0000000000..04974818e7 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/tcp/tcp_helper.h @@ -0,0 +1,52 @@ +#ifndef LWIP_HDR_TCP_HELPER_H +#define LWIP_HDR_TCP_HELPER_H + +#include "../lwip_check.h" +#include "lwip/arch.h" +#include "lwip/tcp.h" +#include "lwip/netif.h" + +/* counters used for test_tcp_counters_* callback functions */ +struct test_tcp_counters { + u32_t recv_calls; + u32_t recved_bytes; + u32_t recv_calls_after_close; + u32_t recved_bytes_after_close; + u32_t close_calls; + u32_t err_calls; + err_t last_err; + char* expected_data; + u32_t expected_data_len; +}; + +struct test_tcp_txcounters { + u32_t num_tx_calls; + u32_t num_tx_bytes; + u8_t copy_tx_packets; + struct pbuf *tx_packets; +}; + +/* Helper functions */ +void tcp_remove_all(void); + +struct pbuf* tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip, + u16_t src_port, u16_t dst_port, void* data, size_t data_len, + u32_t seqno, u32_t ackno, u8_t headerflags); +struct pbuf* tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, + u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags); +struct pbuf* tcp_create_rx_segment_wnd(struct tcp_pcb* pcb, void* data, size_t data_len, + u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd); +void tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip, + ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port); +void test_tcp_counters_err(void* arg, err_t err); +err_t test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err); + +struct tcp_pcb* test_tcp_new_counters_pcb(struct test_tcp_counters* counters); + +void test_tcp_input(struct pbuf *p, struct netif *inp); + +void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters, + ip_addr_t *ip_addr, ip_addr_t *netmask); + + +#endif diff --git a/components/net/lwip-2.0.3/test/unit/tcp/test_tcp.c b/components/net/lwip-2.0.3/test/unit/tcp/test_tcp.c new file mode 100644 index 0000000000..d99b807d96 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/tcp/test_tcp.c @@ -0,0 +1,744 @@ +#include "test_tcp.h" + +#include "lwip/priv/tcp_priv.h" +#include "lwip/stats.h" +#include "tcp_helper.h" +#include "lwip/inet_chksum.h" + +#ifdef _MSC_VER +#pragma warning(disable: 4307) /* we explicitly wrap around TCP seqnos */ +#endif + +#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS +#error "This tests needs TCP- and MEMP-statistics enabled" +#endif +#if TCP_SND_BUF <= TCP_WND +#error "This tests needs TCP_SND_BUF to be > TCP_WND" +#endif + +static u8_t test_tcp_timer; + +/* our own version of tcp_tmr so we can reset fast/slow timer state */ +static void +test_tcp_tmr(void) +{ + tcp_fasttmr(); + if (++test_tcp_timer & 1) { + tcp_slowtmr(); + } +} + +/* Setups/teardown functions */ + +static void +tcp_setup(void) +{ + /* reset iss to default (6510) */ + tcp_ticks = 0; + tcp_ticks = 0 - (tcp_next_iss(NULL) - 6510); + tcp_next_iss(NULL); + tcp_ticks = 0; + + test_tcp_timer = 0; + tcp_remove_all(); +} + +static void +tcp_teardown(void) +{ + netif_list = NULL; + netif_default = NULL; + tcp_remove_all(); +} + + +/* Test functions */ + +/** Call tcp_new() and tcp_abort() and test memp stats */ +START_TEST(test_tcp_new_abort) +{ + struct tcp_pcb* pcb; + LWIP_UNUSED_ARG(_i); + + fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); + + pcb = tcp_new(); + fail_unless(pcb != NULL); + if (pcb != NULL) { + fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); + } +} +END_TEST + +/** Create an ESTABLISHED pcb and check if receive callback is called */ +START_TEST(test_tcp_recv_inseq) +{ + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf* p; + char data[] = {1, 2, 3, 4}; + ip_addr_t remote_ip, local_ip, netmask; + u16_t data_len; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + struct test_tcp_txcounters txcounters; + LWIP_UNUSED_ARG(_i); + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); + data_len = sizeof(data); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = data_len; + counters.expected_data = data; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + + /* create a segment */ + p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); + EXPECT(p != NULL); + if (p != NULL) { + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 1); + EXPECT(counters.recved_bytes == data_len); + EXPECT(counters.err_calls == 0); + } + + /* make sure the pcb is freed */ + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +} +END_TEST + +/** Check that we handle malformed tcp headers, and discard the pbuf(s) */ +START_TEST(test_tcp_malformed_header) +{ + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf* p; + char data[] = {1, 2, 3, 4}; + ip_addr_t remote_ip, local_ip, netmask; + u16_t data_len, chksum; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + struct test_tcp_txcounters txcounters; + struct tcp_hdr *hdr; + LWIP_UNUSED_ARG(_i); + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); + data_len = sizeof(data); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = data_len; + counters.expected_data = data; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + + /* create a segment */ + p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); + + pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); + + hdr = (struct tcp_hdr *)p->payload; + TCPH_HDRLEN_FLAGS_SET(hdr, 15, 0x3d1); + + hdr->chksum = 0; + + chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + &remote_ip, &local_ip); + + hdr->chksum = chksum; + + pbuf_header(p, sizeof(struct ip_hdr)); + + EXPECT(p != NULL); + EXPECT(p->next == NULL); + if (p != NULL) { + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + } + + /* make sure the pcb is freed */ + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +} +END_TEST + + +/** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. + * At the end, send more data. */ +START_TEST(test_tcp_fast_retx_recover) +{ + struct netif netif; + struct test_tcp_txcounters txcounters; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf* p; + char data1[] = { 1, 2, 3, 4}; + char data2[] = { 5, 6, 7, 8}; + char data3[] = { 9, 10, 11, 12}; + char data4[] = {13, 14, 15, 16}; + char data5[] = {17, 18, 19, 20}; + char data6[TCP_MSS] = {21, 22, 23, 24}; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + err_t err; + LWIP_UNUSED_ARG(_i); + + /* initialize local vars */ + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); + memset(&counters, 0, sizeof(counters)); + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->mss = TCP_MSS; + /* disable initial congestion window (we don't send a SYN here...) */ + pcb->cwnd = pcb->snd_wnd; + + /* send data1 */ + err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT_RET(txcounters.num_tx_calls == 1); + EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr)); + memset(&txcounters, 0, sizeof(txcounters)); + /* "recv" ACK for data1 */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK); + EXPECT_RET(p != NULL); + test_tcp_input(p, &netif); + EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(pcb->unacked == NULL); + /* send data2 */ + err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT_RET(txcounters.num_tx_calls == 1); + EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr)); + memset(&txcounters, 0, sizeof(txcounters)); + /* duplicate ACK for data1 (data2 is lost) */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + EXPECT_RET(p != NULL); + test_tcp_input(p, &netif); + EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(pcb->dupacks == 1); + /* send data3 */ + err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /* nagle enabled, no tx calls */ + EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(txcounters.num_tx_bytes == 0); + memset(&txcounters, 0, sizeof(txcounters)); + /* 2nd duplicate ACK for data1 (data2 and data3 are lost) */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + EXPECT_RET(p != NULL); + test_tcp_input(p, &netif); + EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(pcb->dupacks == 2); + /* queue data4, don't send it (unsent-oversize is != 0) */ + err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + /* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + EXPECT_RET(p != NULL); + test_tcp_input(p, &netif); + /*EXPECT_RET(txcounters.num_tx_calls == 1);*/ + EXPECT_RET(pcb->dupacks == 3); + memset(&txcounters, 0, sizeof(txcounters)); + /* @todo: check expected data?*/ + + /* send data5, not output yet */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + /*err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK);*/ + EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(txcounters.num_tx_bytes == 0); + memset(&txcounters, 0, sizeof(txcounters)); + { + int i = 0; + do + { + err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY); + i++; + }while(err == ERR_OK); + EXPECT_RET(err != ERR_OK); + } + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /*EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(txcounters.num_tx_bytes == 0);*/ + memset(&txcounters, 0, sizeof(txcounters)); + + /* send even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /* ...and even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /* ...and even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /* ...and even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + + /* send ACKs for data2 and data3 */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK); + EXPECT_RET(p != NULL); + test_tcp_input(p, &netif); + /*EXPECT_RET(txcounters.num_tx_calls == 0);*/ + + /* ...and even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /* ...and even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + +#if 0 + /* create expected segment */ + p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); + EXPECT_RET(p != NULL); + if (p != NULL) { + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT_RET(counters.close_calls == 0); + EXPECT_RET(counters.recv_calls == 1); + EXPECT_RET(counters.recved_bytes == data_len); + EXPECT_RET(counters.err_calls == 0); + } +#endif + /* make sure the pcb is freed */ + EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +} +END_TEST + +static u8_t tx_data[TCP_WND*2]; + +static void +check_seqnos(struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected) +{ + struct tcp_seg *s = segs; + int i; + for (i = 0; i < num_expected; i++, s = s->next) { + EXPECT_RET(s != NULL); + EXPECT(s->tcphdr->seqno == htonl(seqnos_expected[i])); + } + EXPECT(s == NULL); +} + +/** Send data with sequence numbers that wrap around the u32_t range. + * Then, provoke fast retransmission by duplicate ACKs and check that all + * segment lists are still properly sorted. */ +START_TEST(test_tcp_fast_rexmit_wraparound) +{ + struct netif netif; + struct test_tcp_txcounters txcounters; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf* p; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + err_t err; +#define SEQNO1 (0xFFFFFF00 - TCP_MSS) +#define ISS 6510 + u16_t i, sent_total = 0; + u32_t seqnos[] = { + SEQNO1, + SEQNO1 + (1 * TCP_MSS), + SEQNO1 + (2 * TCP_MSS), + SEQNO1 + (3 * TCP_MSS), + SEQNO1 + (4 * TCP_MSS), + SEQNO1 + (5 * TCP_MSS)}; + LWIP_UNUSED_ARG(_i); + + for (i = 0; i < sizeof(tx_data); i++) { + tx_data[i] = (u8_t)i; + } + + /* initialize local vars */ + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); + memset(&counters, 0, sizeof(counters)); + + /* create and initialize the pcb */ + tcp_ticks = SEQNO1 - ISS; + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->mss = TCP_MSS; + /* disable initial congestion window (we don't send a SYN here...) */ + pcb->cwnd = 2*TCP_MSS; + /* start in congestion advoidance */ + pcb->ssthresh = pcb->cwnd; + + /* send 6 mss-sized segments */ + for (i = 0; i < 6; i++) { + err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + sent_total += TCP_MSS; + } + check_seqnos(pcb->unsent, 6, seqnos); + EXPECT(pcb->unacked == NULL); + err = tcp_output(pcb); + EXPECT(txcounters.num_tx_calls == 2); + EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U)); + memset(&txcounters, 0, sizeof(txcounters)); + + check_seqnos(pcb->unacked, 2, seqnos); + check_seqnos(pcb->unsent, 4, &seqnos[2]); + + /* ACK the first segment */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK); + test_tcp_input(p, &netif); + /* ensure this didn't trigger a retransmission. Only one + segment should be transmitted because cwnd opened up by + TCP_MSS and a fraction since we are in congestion avoidance */ + EXPECT(txcounters.num_tx_calls == 1); + EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); + memset(&txcounters, 0, sizeof(txcounters)); + check_seqnos(pcb->unacked, 2, &seqnos[1]); + check_seqnos(pcb->unsent, 3, &seqnos[3]); + + /* 3 dupacks */ + EXPECT(pcb->dupacks == 0); + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + test_tcp_input(p, &netif); + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(pcb->dupacks == 1); + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + test_tcp_input(p, &netif); + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(pcb->dupacks == 2); + /* 3rd dupack -> fast rexmit */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + test_tcp_input(p, &netif); + EXPECT(pcb->dupacks == 3); + EXPECT(txcounters.num_tx_calls == 4); + memset(&txcounters, 0, sizeof(txcounters)); + EXPECT(pcb->unsent == NULL); + check_seqnos(pcb->unacked, 5, &seqnos[1]); + + /* make sure the pcb is freed */ + EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +} +END_TEST + +/** Send data with sequence numbers that wrap around the u32_t range. + * Then, provoke RTO retransmission and check that all + * segment lists are still properly sorted. */ +START_TEST(test_tcp_rto_rexmit_wraparound) +{ + struct netif netif; + struct test_tcp_txcounters txcounters; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + err_t err; +#define SEQNO1 (0xFFFFFF00 - TCP_MSS) +#define ISS 6510 + u16_t i, sent_total = 0; + u32_t seqnos[] = { + SEQNO1, + SEQNO1 + (1 * TCP_MSS), + SEQNO1 + (2 * TCP_MSS), + SEQNO1 + (3 * TCP_MSS), + SEQNO1 + (4 * TCP_MSS), + SEQNO1 + (5 * TCP_MSS)}; + LWIP_UNUSED_ARG(_i); + + for (i = 0; i < sizeof(tx_data); i++) { + tx_data[i] = (u8_t)i; + } + + /* initialize local vars */ + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); + memset(&counters, 0, sizeof(counters)); + + /* create and initialize the pcb */ + tcp_ticks = 0; + tcp_ticks = 0 - tcp_next_iss(NULL); + tcp_ticks = SEQNO1 - tcp_next_iss(NULL); + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->mss = TCP_MSS; + /* disable initial congestion window (we don't send a SYN here...) */ + pcb->cwnd = 2*TCP_MSS; + + /* send 6 mss-sized segments */ + for (i = 0; i < 6; i++) { + err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + sent_total += TCP_MSS; + } + check_seqnos(pcb->unsent, 6, seqnos); + EXPECT(pcb->unacked == NULL); + err = tcp_output(pcb); + EXPECT(txcounters.num_tx_calls == 2); + EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U)); + memset(&txcounters, 0, sizeof(txcounters)); + + check_seqnos(pcb->unacked, 2, seqnos); + check_seqnos(pcb->unsent, 4, &seqnos[2]); + + /* call the tcp timer some times */ + for (i = 0; i < 10; i++) { + test_tcp_tmr(); + EXPECT(txcounters.num_tx_calls == 0); + } + /* 11th call to tcp_tmr: RTO rexmit fires */ + test_tcp_tmr(); + EXPECT(txcounters.num_tx_calls == 1); + check_seqnos(pcb->unacked, 1, seqnos); + check_seqnos(pcb->unsent, 5, &seqnos[1]); + + /* fake greater cwnd */ + pcb->cwnd = pcb->snd_wnd; + /* send more data */ + err = tcp_output(pcb); + EXPECT(err == ERR_OK); + /* check queues are sorted */ + EXPECT(pcb->unsent == NULL); + check_seqnos(pcb->unacked, 6, seqnos); + + /* make sure the pcb is freed */ + EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +} +END_TEST + +/** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. + * At the end, send more data. */ +static void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent) +{ + struct netif netif; + struct test_tcp_txcounters txcounters; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + err_t err; + u16_t sent_total, i; + u8_t expected = 0xFE; + + for (i = 0; i < sizeof(tx_data); i++) { + u8_t d = (u8_t)i; + if (d == 0xFE) { + d = 0xF0; + } + tx_data[i] = d; + } + if (zero_window_probe_from_unsent) { + tx_data[TCP_WND] = expected; + } else { + tx_data[0] = expected; + } + + /* initialize local vars */ + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); + memset(&counters, 0, sizeof(counters)); + memset(&txcounters, 0, sizeof(txcounters)); + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->mss = TCP_MSS; + /* disable initial congestion window (we don't send a SYN here...) */ + pcb->cwnd = pcb->snd_wnd; + + /* send a full window (minus 1 packets) of TCP data in MSS-sized chunks */ + sent_total = 0; + if ((TCP_WND - TCP_MSS) % TCP_MSS != 0) { + u16_t initial_data_len = (TCP_WND - TCP_MSS) % TCP_MSS; + err = tcp_write(pcb, &tx_data[sent_total], initial_data_len, TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT(txcounters.num_tx_calls == 1); + EXPECT(txcounters.num_tx_bytes == initial_data_len + 40U); + memset(&txcounters, 0, sizeof(txcounters)); + sent_total += initial_data_len; + } + for (; sent_total < (TCP_WND - TCP_MSS); sent_total += TCP_MSS) { + err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT(txcounters.num_tx_calls == 1); + EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); + memset(&txcounters, 0, sizeof(txcounters)); + } + EXPECT(sent_total == (TCP_WND - TCP_MSS)); + + /* now ACK the packet before the first */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + test_tcp_input(p, &netif); + /* ensure this didn't trigger a retransmission */ + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(txcounters.num_tx_bytes == 0); + + EXPECT(pcb->persist_backoff == 0); + /* send the last packet, now a complete window has been sent */ + err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); + sent_total += TCP_MSS; + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT(txcounters.num_tx_calls == 1); + EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); + memset(&txcounters, 0, sizeof(txcounters)); + EXPECT(pcb->persist_backoff == 0); + + if (zero_window_probe_from_unsent) { + /* ACK all data but close the TX window */ + p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_WND, TCP_ACK, 0); + test_tcp_input(p, &netif); + /* ensure this didn't trigger any transmission */ + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(txcounters.num_tx_bytes == 0); + EXPECT(pcb->persist_backoff == 1); + } + + /* send one byte more (out of window) -> persist timer starts */ + err = tcp_write(pcb, &tx_data[sent_total], 1, TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(txcounters.num_tx_bytes == 0); + memset(&txcounters, 0, sizeof(txcounters)); + if (!zero_window_probe_from_unsent) { + /* no persist timer unless a zero window announcement has been received */ + EXPECT(pcb->persist_backoff == 0); + } else { + EXPECT(pcb->persist_backoff == 1); + + /* call tcp_timer some more times to let persist timer count up */ + for (i = 0; i < 4; i++) { + test_tcp_tmr(); + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(txcounters.num_tx_bytes == 0); + } + + /* this should trigger the zero-window-probe */ + txcounters.copy_tx_packets = 1; + test_tcp_tmr(); + txcounters.copy_tx_packets = 0; + EXPECT(txcounters.num_tx_calls == 1); + EXPECT(txcounters.num_tx_bytes == 1 + 40U); + EXPECT(txcounters.tx_packets != NULL); + if (txcounters.tx_packets != NULL) { + u8_t sent; + u16_t ret; + ret = pbuf_copy_partial(txcounters.tx_packets, &sent, 1, 40U); + EXPECT(ret == 1); + EXPECT(sent == expected); + } + if (txcounters.tx_packets != NULL) { + pbuf_free(txcounters.tx_packets); + txcounters.tx_packets = NULL; + } + } + + /* make sure the pcb is freed */ + EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +} + +START_TEST(test_tcp_tx_full_window_lost_from_unsent) +{ + LWIP_UNUSED_ARG(_i); + test_tcp_tx_full_window_lost(1); +} +END_TEST + +START_TEST(test_tcp_tx_full_window_lost_from_unacked) +{ + LWIP_UNUSED_ARG(_i); + test_tcp_tx_full_window_lost(0); +} +END_TEST + +/** Create the suite including all tests for this module */ +Suite * +tcp_suite(void) +{ + testfunc tests[] = { + TESTFUNC(test_tcp_new_abort), + TESTFUNC(test_tcp_recv_inseq), + TESTFUNC(test_tcp_malformed_header), + TESTFUNC(test_tcp_fast_retx_recover), + TESTFUNC(test_tcp_fast_rexmit_wraparound), + TESTFUNC(test_tcp_rto_rexmit_wraparound), + TESTFUNC(test_tcp_tx_full_window_lost_from_unacked), + TESTFUNC(test_tcp_tx_full_window_lost_from_unsent) + }; + return create_suite("TCP", tests, sizeof(tests)/sizeof(testfunc), tcp_setup, tcp_teardown); +} diff --git a/components/net/lwip-2.0.3/test/unit/tcp/test_tcp.h b/components/net/lwip-2.0.3/test/unit/tcp/test_tcp.h new file mode 100644 index 0000000000..f28ee56530 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/tcp/test_tcp.h @@ -0,0 +1,8 @@ +#ifndef LWIP_HDR_TEST_TCP_H +#define LWIP_HDR_TEST_TCP_H + +#include "../lwip_check.h" + +Suite *tcp_suite(void); + +#endif diff --git a/components/net/lwip-2.0.3/test/unit/tcp/test_tcp_oos.c b/components/net/lwip-2.0.3/test/unit/tcp/test_tcp_oos.c new file mode 100644 index 0000000000..be61172251 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/tcp/test_tcp_oos.c @@ -0,0 +1,1049 @@ +#include "test_tcp_oos.h" + +#include "lwip/priv/tcp_priv.h" +#include "lwip/stats.h" +#include "tcp_helper.h" + +#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS +#error "This tests needs TCP- and MEMP-statistics enabled" +#endif +#if !TCP_QUEUE_OOSEQ +#error "This tests needs TCP_QUEUE_OOSEQ enabled" +#endif + +/** CHECK_SEGMENTS_ON_OOSEQ: + * 1: check count, seqno and len of segments on pcb->ooseq (strict) + * 0: only check that bytes are received in correct order (less strict) */ +#define CHECK_SEGMENTS_ON_OOSEQ 1 + +#if CHECK_SEGMENTS_ON_OOSEQ +#define EXPECT_OOSEQ(x) EXPECT(x) +#else +#define EXPECT_OOSEQ(x) +#endif + +/* helper functions */ + +/** Get the numbers of segments on the ooseq list */ +static int tcp_oos_count(struct tcp_pcb* pcb) +{ + int num = 0; + struct tcp_seg* seg = pcb->ooseq; + while(seg != NULL) { + num++; + seg = seg->next; + } + return num; +} + +#if TCP_OOSEQ_MAX_PBUFS && (TCP_OOSEQ_MAX_PBUFS < ((TCP_WND / TCP_MSS) + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) +/** Get the numbers of pbufs on the ooseq list */ +static int tcp_oos_pbuf_count(struct tcp_pcb* pcb) +{ + int num = 0; + struct tcp_seg* seg = pcb->ooseq; + while(seg != NULL) { + num += pbuf_clen(seg->p); + seg = seg->next; + } + return num; +} +#endif + +/** Get the seqno of a segment (by index) on the ooseq list + * + * @param pcb the pcb to check for ooseq segments + * @param seg_index index of the segment on the ooseq list + * @return seqno of the segment + */ +static u32_t +tcp_oos_seg_seqno(struct tcp_pcb* pcb, int seg_index) +{ + int num = 0; + struct tcp_seg* seg = pcb->ooseq; + + /* then check the actual segment */ + while(seg != NULL) { + if(num == seg_index) { + return seg->tcphdr->seqno; + } + num++; + seg = seg->next; + } + fail(); + return 0; +} + +/** Get the tcplen (datalen + SYN/FIN) of a segment (by index) on the ooseq list + * + * @param pcb the pcb to check for ooseq segments + * @param seg_index index of the segment on the ooseq list + * @return tcplen of the segment + */ +static int +tcp_oos_seg_tcplen(struct tcp_pcb* pcb, int seg_index) +{ + int num = 0; + struct tcp_seg* seg = pcb->ooseq; + + /* then check the actual segment */ + while(seg != NULL) { + if(num == seg_index) { + return TCP_TCPLEN(seg); + } + num++; + seg = seg->next; + } + fail(); + return -1; +} + +/** Get the tcplen (datalen + SYN/FIN) of all segments on the ooseq list + * + * @param pcb the pcb to check for ooseq segments + * @return tcplen of all segment + */ +static int +tcp_oos_tcplen(struct tcp_pcb* pcb) +{ + int len = 0; + struct tcp_seg* seg = pcb->ooseq; + + /* then check the actual segment */ + while(seg != NULL) { + len += TCP_TCPLEN(seg); + seg = seg->next; + } + return len; +} + +/* Setup/teardown functions */ + +static void +tcp_oos_setup(void) +{ + tcp_remove_all(); +} + +static void +tcp_oos_teardown(void) +{ + tcp_remove_all(); + netif_list = NULL; + netif_default = NULL; +} + + + +/* Test functions */ + +/** create multiple segments and pass them to tcp_input in a wrong + * order to see if ooseq-caching works correctly + * FIN is received in out-of-sequence segments only */ +START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ) +{ + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p_8_9, *p_4_8, *p_4_10, *p_2_14, *p_fin, *pinseq; + char data[] = { + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16}; + ip_addr_t remote_ip, local_ip, netmask; + u16_t data_len; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + LWIP_UNUSED_ARG(_i); + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + data_len = sizeof(data); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = data_len; + counters.expected_data = data; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + + /* create segments */ + /* pinseq is sent as last segment! */ + pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK); + /* p1: 8 bytes before FIN */ + /* seqno: 8..16 */ + p_8_9 = tcp_create_rx_segment(pcb, &data[8], 8, 8, 0, TCP_ACK|TCP_FIN); + /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */ + /* seqno: 4..11 */ + p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK); + /* p3: same as p2 but 2 bytes longer */ + /* seqno: 4..13 */ + p_4_10 = tcp_create_rx_segment(pcb, &data[4], 10, 4, 0, TCP_ACK); + /* p4: 14 bytes before FIN, includes data from p1 and p2, plus partly from pinseq */ + /* seqno: 2..15 */ + p_2_14 = tcp_create_rx_segment(pcb, &data[2], 14, 2, 0, TCP_ACK); + /* FIN, seqno 16 */ + p_fin = tcp_create_rx_segment(pcb, NULL, 0,16, 0, TCP_ACK|TCP_FIN); + EXPECT(pinseq != NULL); + EXPECT(p_8_9 != NULL); + EXPECT(p_4_8 != NULL); + EXPECT(p_4_10 != NULL); + EXPECT(p_2_14 != NULL); + EXPECT(p_fin != NULL); + if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) { + /* pass the segment to tcp_input */ + test_tcp_input(p_8_9, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 8); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */ + + /* pass the segment to tcp_input */ + test_tcp_input(p_4_8, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */ + + /* pass the segment to tcp_input */ + test_tcp_input(p_4_10, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* ooseq queue: unchanged */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */ + + /* pass the segment to tcp_input */ + test_tcp_input(p_2_14, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */ + + /* pass the segment to tcp_input */ + test_tcp_input(p_fin, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* ooseq queue: unchanged */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */ + + /* pass the segment to tcp_input */ + test_tcp_input(pinseq, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 1); + EXPECT(counters.recv_calls == 1); + EXPECT(counters.recved_bytes == data_len); + EXPECT(counters.err_calls == 0); + EXPECT(pcb->ooseq == NULL); + } + + /* make sure the pcb is freed */ + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +} +END_TEST + + +/** create multiple segments and pass them to tcp_input in a wrong + * order to see if ooseq-caching works correctly + * FIN is received IN-SEQUENCE at the end */ +START_TEST(test_tcp_recv_ooseq_FIN_INSEQ) +{ + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p_1_2, *p_4_8, *p_3_11, *p_2_12, *p_15_1, *p_15_1a, *pinseq, *pinseqFIN; + char data[] = { + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16}; + ip_addr_t remote_ip, local_ip, netmask; + u16_t data_len; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + LWIP_UNUSED_ARG(_i); + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + data_len = sizeof(data); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = data_len; + counters.expected_data = data; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + + /* create segments */ + /* p1: 7 bytes - 2 before FIN */ + /* seqno: 1..2 */ + p_1_2 = tcp_create_rx_segment(pcb, &data[1], 2, 1, 0, TCP_ACK); + /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */ + /* seqno: 4..11 */ + p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK); + /* p3: same as p2 but 2 bytes longer and one byte more at the front */ + /* seqno: 3..13 */ + p_3_11 = tcp_create_rx_segment(pcb, &data[3], 11, 3, 0, TCP_ACK); + /* p4: 13 bytes - 2 before FIN - should be ignored as contained in p1 and p3 */ + /* seqno: 2..13 */ + p_2_12 = tcp_create_rx_segment(pcb, &data[2], 12, 2, 0, TCP_ACK); + /* pinseq is the first segment that is held back to create ooseq! */ + /* seqno: 0..3 */ + pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK); + /* p5: last byte before FIN */ + /* seqno: 15 */ + p_15_1 = tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK); + /* p6: same as p5, should be ignored */ + p_15_1a= tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK); + /* pinseqFIN: last 2 bytes plus FIN */ + /* only segment containing seqno 14 and FIN */ + pinseqFIN = tcp_create_rx_segment(pcb, &data[14], 2, 14, 0, TCP_ACK|TCP_FIN); + EXPECT(pinseq != NULL); + EXPECT(p_1_2 != NULL); + EXPECT(p_4_8 != NULL); + EXPECT(p_3_11 != NULL); + EXPECT(p_2_12 != NULL); + EXPECT(p_15_1 != NULL); + EXPECT(p_15_1a != NULL); + EXPECT(pinseqFIN != NULL); + if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL) + && (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) { + /* pass the segment to tcp_input */ + test_tcp_input(p_1_2, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); + + /* pass the segment to tcp_input */ + test_tcp_input(p_4_8, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 4); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8); + + /* pass the segment to tcp_input */ + test_tcp_input(p_3_11, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); + /* p_3_11 has removed p_4_8 from ooseq */ + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 3); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11); + + /* pass the segment to tcp_input */ + test_tcp_input(p_2_12, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 12); + + /* pass the segment to tcp_input */ + test_tcp_input(pinseq, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 1); + EXPECT(counters.recved_bytes == 14); + EXPECT(counters.err_calls == 0); + EXPECT(pcb->ooseq == NULL); + + /* pass the segment to tcp_input */ + test_tcp_input(p_15_1, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 1); + EXPECT(counters.recved_bytes == 14); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); + + /* pass the segment to tcp_input */ + test_tcp_input(p_15_1a, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 1); + EXPECT(counters.recved_bytes == 14); + EXPECT(counters.err_calls == 0); + /* check ooseq queue: unchanged */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); + + /* pass the segment to tcp_input */ + test_tcp_input(pinseqFIN, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 1); + EXPECT(counters.recv_calls == 2); + EXPECT(counters.recved_bytes == data_len); + EXPECT(counters.err_calls == 0); + EXPECT(pcb->ooseq == NULL); + } + + /* make sure the pcb is freed */ + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +} +END_TEST + +static char data_full_wnd[TCP_WND + TCP_MSS]; + +/** create multiple segments and pass them to tcp_input with the first segment missing + * to simulate overruning the rxwin with ooseq queueing enabled */ +START_TEST(test_tcp_recv_ooseq_overrun_rxwin) +{ +#if !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS + int i, k; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *pinseq, *p_ovr; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + int datalen = 0; + int datalen2; + + for(i = 0; i < (int)sizeof(data_full_wnd); i++) { + data_full_wnd[i] = (char)i; + } + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = TCP_WND; + counters.expected_data = data_full_wnd; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->rcv_nxt = 0x8000; + + /* create segments */ + /* pinseq is sent as last segment! */ + pinseq = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK); + + for(i = TCP_MSS, k = 0; i < TCP_WND; i += TCP_MSS, k++) { + int count, expected_datalen; + struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], + TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); + EXPECT_RET(p != NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + count = tcp_oos_count(pcb); + EXPECT_OOSEQ(count == k+1); + datalen = tcp_oos_tcplen(pcb); + if (i + TCP_MSS < TCP_WND) { + expected_datalen = (k+1)*TCP_MSS; + } else { + expected_datalen = TCP_WND - TCP_MSS; + } + if (datalen != expected_datalen) { + EXPECT_OOSEQ(datalen == expected_datalen); + } + } + + /* pass in one more segment, cleary overrunning the rxwin */ + p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); + EXPECT_RET(p_ovr != NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p_ovr, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == k); + datalen2 = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(datalen == datalen2); + + /* now pass inseq */ + test_tcp_input(pinseq, &netif); + EXPECT(pcb->ooseq == NULL); + + /* make sure the pcb is freed */ + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +#endif /* !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS */ + LWIP_UNUSED_ARG(_i); +} +END_TEST + +/** similar to above test, except seqno starts near the max rxwin */ +START_TEST(test_tcp_recv_ooseq_overrun_rxwin_edge) +{ +#if !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS + int i, k; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *pinseq, *p_ovr; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + int datalen = 0; + int datalen2; + + for(i = 0; i < (int)sizeof(data_full_wnd); i++) { + data_full_wnd[i] = (char)i; + } + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = TCP_WND; + counters.expected_data = data_full_wnd; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->rcv_nxt = 0xffffffff - (TCP_WND / 2); + + /* create segments */ + /* pinseq is sent as last segment! */ + pinseq = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK); + + for(i = TCP_MSS, k = 0; i < TCP_WND; i += TCP_MSS, k++) { + int count, expected_datalen; + struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], + TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); + EXPECT_RET(p != NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + count = tcp_oos_count(pcb); + EXPECT_OOSEQ(count == k+1); + datalen = tcp_oos_tcplen(pcb); + if (i + TCP_MSS < TCP_WND) { + expected_datalen = (k+1)*TCP_MSS; + } else { + expected_datalen = TCP_WND - TCP_MSS; + } + if (datalen != expected_datalen) { + EXPECT_OOSEQ(datalen == expected_datalen); + } + } + + /* pass in one more segment, cleary overrunning the rxwin */ + p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); + EXPECT_RET(p_ovr != NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p_ovr, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == k); + datalen2 = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(datalen == datalen2); + + /* now pass inseq */ + test_tcp_input(pinseq, &netif); + EXPECT(pcb->ooseq == NULL); + + /* make sure the pcb is freed */ + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +#endif /* !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS */ + LWIP_UNUSED_ARG(_i); +} +END_TEST + +START_TEST(test_tcp_recv_ooseq_max_bytes) +{ +#if TCP_OOSEQ_MAX_BYTES && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) + int i, k; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p_ovr; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + int datalen = 0; + int datalen2; + + for(i = 0; i < sizeof(data_full_wnd); i++) { + data_full_wnd[i] = (char)i; + } + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = TCP_WND; + counters.expected_data = data_full_wnd; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->rcv_nxt = 0x8000; + + /* don't 'recv' the first segment (1 byte) so that all other segments will be ooseq */ + + /* create segments and 'recv' them */ + for(k = 1, i = 1; k < TCP_OOSEQ_MAX_BYTES; k += TCP_MSS, i++) { + int count; + struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[k], + TCP_MSS, k, 0, TCP_ACK); + EXPECT_RET(p != NULL); + EXPECT_RET(p->next == NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + count = tcp_oos_pbuf_count(pcb); + EXPECT_OOSEQ(count == i); + datalen = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(datalen == (i * TCP_MSS)); + } + + /* pass in one more segment, overrunning the limit */ + p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[k+1], 1, k+1, 0, TCP_ACK); + EXPECT_RET(p_ovr != NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p_ovr, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue (ensure the new segment was not accepted) */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == (i-1)); + datalen2 = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(datalen2 == ((i-1) * TCP_MSS)); + + /* make sure the pcb is freed */ + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +#endif /* TCP_OOSEQ_MAX_BYTES && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) */ + LWIP_UNUSED_ARG(_i); +} +END_TEST + +START_TEST(test_tcp_recv_ooseq_max_pbufs) +{ +#if TCP_OOSEQ_MAX_PBUFS && (TCP_OOSEQ_MAX_PBUFS < ((TCP_WND / TCP_MSS) + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) + int i; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p_ovr; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + int datalen = 0; + int datalen2; + + for(i = 0; i < sizeof(data_full_wnd); i++) { + data_full_wnd[i] = (char)i; + } + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = TCP_WND; + counters.expected_data = data_full_wnd; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->rcv_nxt = 0x8000; + + /* don't 'recv' the first segment (1 byte) so that all other segments will be ooseq */ + + /* create segments and 'recv' them */ + for(i = 1; i <= TCP_OOSEQ_MAX_PBUFS; i++) { + int count; + struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[i], + 1, i, 0, TCP_ACK); + EXPECT_RET(p != NULL); + EXPECT_RET(p->next == NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + count = tcp_oos_pbuf_count(pcb); + EXPECT_OOSEQ(count == i); + datalen = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(datalen == i); + } + + /* pass in one more segment, overrunning the limit */ + p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[i+1], 1, i+1, 0, TCP_ACK); + EXPECT_RET(p_ovr != NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p_ovr, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue (ensure the new segment was not accepted) */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == (i-1)); + datalen2 = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(datalen2 == (i-1)); + + /* make sure the pcb is freed */ + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +#endif /* TCP_OOSEQ_MAX_PBUFS && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) */ + LWIP_UNUSED_ARG(_i); +} +END_TEST + +static void +check_rx_counters(struct tcp_pcb *pcb, struct test_tcp_counters *counters, u32_t exp_close_calls, u32_t exp_rx_calls, + u32_t exp_rx_bytes, u32_t exp_err_calls, int exp_oos_count, int exp_oos_len) +{ + int oos_len; + EXPECT(counters->close_calls == exp_close_calls); + EXPECT(counters->recv_calls == exp_rx_calls); + EXPECT(counters->recved_bytes == exp_rx_bytes); + EXPECT(counters->err_calls == exp_err_calls); + /* check that pbuf is queued in ooseq */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == exp_oos_count); + oos_len = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(exp_oos_len == oos_len); +} + +/* this test uses 4 packets: + * - data (len=TCP_MSS) + * - FIN + * - data after FIN (len=1) (invalid) + * - 2nd FIN (invalid) + * + * the parameter 'delay_packet' is a bitmask that choses which on these packets is ooseq + */ +static void test_tcp_recv_ooseq_double_FINs(int delay_packet) +{ + int i, k; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p_normal_fin, *p_data_after_fin, *p, *p_2nd_fin_ooseq; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + u32_t exp_rx_calls = 0, exp_rx_bytes = 0, exp_close_calls = 0, exp_oos_pbufs = 0, exp_oos_tcplen = 0; + int first_dropped = 0xff; + + for(i = 0; i < (int)sizeof(data_full_wnd); i++) { + data_full_wnd[i] = (char)i; + } + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP_ADDR4(&local_ip, 192, 168, 1, 1); + IP_ADDR4(&remote_ip, 192, 168, 1, 2); + IP_ADDR4(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = TCP_WND; + counters.expected_data = data_full_wnd; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->rcv_nxt = 0x8000; + + /* create segments */ + p = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK); + p_normal_fin = tcp_create_rx_segment(pcb, NULL, 0, TCP_MSS, 0, TCP_ACK|TCP_FIN); + k = 1; + p_data_after_fin = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS+1], k, TCP_MSS+1, 0, TCP_ACK); + p_2nd_fin_ooseq = tcp_create_rx_segment(pcb, NULL, 0, TCP_MSS+1+k, 0, TCP_ACK|TCP_FIN); + + if(delay_packet & 1) { + /* drop normal data */ + first_dropped = 1; + } else { + /* send normal data */ + test_tcp_input(p, &netif); + exp_rx_calls++; + exp_rx_bytes += TCP_MSS; + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 2) { + /* drop FIN */ + if(first_dropped > 2) { + first_dropped = 2; + } + } else { + /* send FIN */ + test_tcp_input(p_normal_fin, &netif); + if (first_dropped < 2) { + /* already dropped packets, this one is ooseq */ + exp_oos_pbufs++; + exp_oos_tcplen++; + } else { + /* inseq */ + exp_close_calls++; + } + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 4) { + /* drop data-after-FIN */ + if(first_dropped > 3) { + first_dropped = 3; + } + } else { + /* send data-after-FIN */ + test_tcp_input(p_data_after_fin, &netif); + if (first_dropped < 3) { + /* already dropped packets, this one is ooseq */ + if (delay_packet & 2) { + /* correct FIN was ooseq */ + exp_oos_pbufs++; + exp_oos_tcplen += k; + } + } else { + /* inseq: no change */ + } + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 8) { + /* drop 2nd-FIN */ + if(first_dropped > 4) { + first_dropped = 4; + } + } else { + /* send 2nd-FIN */ + test_tcp_input(p_2nd_fin_ooseq, &netif); + if (first_dropped < 3) { + /* already dropped packets, this one is ooseq */ + if (delay_packet & 2) { + /* correct FIN was ooseq */ + exp_oos_pbufs++; + exp_oos_tcplen++; + } + } else { + /* inseq: no change */ + } + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 1) { + /* dropped normal data before */ + test_tcp_input(p, &netif); + exp_rx_calls++; + exp_rx_bytes += TCP_MSS; + if((delay_packet & 2) == 0) { + /* normal FIN was NOT delayed */ + exp_close_calls++; + exp_oos_pbufs = exp_oos_tcplen = 0; + } + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 2) { + /* dropped normal FIN before */ + test_tcp_input(p_normal_fin, &netif); + exp_close_calls++; + exp_oos_pbufs = exp_oos_tcplen = 0; + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 4) { + /* dropped data-after-FIN before */ + test_tcp_input(p_data_after_fin, &netif); + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 8) { + /* dropped 2nd-FIN before */ + test_tcp_input(p_2nd_fin_ooseq, &netif); + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + /* check that ooseq data has been dumped */ + EXPECT(pcb->ooseq == NULL); + + /* make sure the pcb is freed */ + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + tcp_abort(pcb); + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); +} + +/** create multiple segments and pass them to tcp_input with the first segment missing + * to simulate overruning the rxwin with ooseq queueing enabled */ +#define FIN_TEST(name, num) \ + START_TEST(name) \ + { \ + LWIP_UNUSED_ARG(_i); \ + test_tcp_recv_ooseq_double_FINs(num); \ + } \ + END_TEST +FIN_TEST(test_tcp_recv_ooseq_double_FIN_0, 0) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_1, 1) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_2, 2) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_3, 3) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_4, 4) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_5, 5) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_6, 6) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_7, 7) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_8, 8) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_9, 9) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_10, 10) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_11, 11) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_12, 12) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_13, 13) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_14, 14) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_15, 15) + + +/** Create the suite including all tests for this module */ +Suite * +tcp_oos_suite(void) +{ + testfunc tests[] = { + TESTFUNC(test_tcp_recv_ooseq_FIN_OOSEQ), + TESTFUNC(test_tcp_recv_ooseq_FIN_INSEQ), + TESTFUNC(test_tcp_recv_ooseq_overrun_rxwin), + TESTFUNC(test_tcp_recv_ooseq_overrun_rxwin_edge), + TESTFUNC(test_tcp_recv_ooseq_max_bytes), + TESTFUNC(test_tcp_recv_ooseq_max_pbufs), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_0), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_1), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_2), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_3), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_4), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_5), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_6), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_7), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_8), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_9), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_10), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_11), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_12), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_13), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_14), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_15) + }; + return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(testfunc), tcp_oos_setup, tcp_oos_teardown); +} diff --git a/components/net/lwip-2.0.3/test/unit/tcp/test_tcp_oos.h b/components/net/lwip-2.0.3/test/unit/tcp/test_tcp_oos.h new file mode 100644 index 0000000000..5b82013b73 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/tcp/test_tcp_oos.h @@ -0,0 +1,8 @@ +#ifndef LWIP_HDR_TEST_TCP_OOS_H +#define LWIP_HDR_TEST_TCP_OOS_H + +#include "../lwip_check.h" + +Suite *tcp_oos_suite(void); + +#endif diff --git a/components/net/lwip-2.0.3/test/unit/udp/test_udp.c b/components/net/lwip-2.0.3/test/unit/udp/test_udp.c new file mode 100644 index 0000000000..147822f492 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/udp/test_udp.c @@ -0,0 +1,68 @@ +#include "test_udp.h" + +#include "lwip/udp.h" +#include "lwip/stats.h" + +#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS +#error "This tests needs UDP- and MEMP-statistics enabled" +#endif + +/* Helper functions */ +static void +udp_remove_all(void) +{ + struct udp_pcb *pcb = udp_pcbs; + struct udp_pcb *pcb2; + + while(pcb != NULL) { + pcb2 = pcb; + pcb = pcb->next; + udp_remove(pcb2); + } + fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); +} + +/* Setups/teardown functions */ + +static void +udp_setup(void) +{ + udp_remove_all(); +} + +static void +udp_teardown(void) +{ + udp_remove_all(); +} + + +/* Test functions */ + +START_TEST(test_udp_new_remove) +{ + struct udp_pcb* pcb; + LWIP_UNUSED_ARG(_i); + + fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); + + pcb = udp_new(); + fail_unless(pcb != NULL); + if (pcb != NULL) { + fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 1); + udp_remove(pcb); + fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); + } +} +END_TEST + + +/** Create the suite including all tests for this module */ +Suite * +udp_suite(void) +{ + testfunc tests[] = { + TESTFUNC(test_udp_new_remove), + }; + return create_suite("UDP", tests, sizeof(tests)/sizeof(testfunc), udp_setup, udp_teardown); +} diff --git a/components/net/lwip-2.0.3/test/unit/udp/test_udp.h b/components/net/lwip-2.0.3/test/unit/udp/test_udp.h new file mode 100644 index 0000000000..5426bf42e7 --- /dev/null +++ b/components/net/lwip-2.0.3/test/unit/udp/test_udp.h @@ -0,0 +1,8 @@ +#ifndef LWIP_HDR_TEST_UDP_H +#define LWIP_HDR_TEST_UDP_H + +#include "../lwip_check.h" + +Suite* udp_suite(void); + +#endif From da1302cbda8607b1e7e4b3ead07ba515b5c878b9 Mon Sep 17 00:00:00 2001 From: liuxianliang Date: Fri, 25 Jun 2021 16:22:06 +0800 Subject: [PATCH 192/255] [update] ignore the lwip origin file format. --- .ignore_format.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.ignore_format.yml b/.ignore_format.yml index 5af47eedd4..1aa68c35d1 100644 --- a/.ignore_format.yml +++ b/.ignore_format.yml @@ -9,4 +9,5 @@ dir_path: - tools - components/net/lwip-1.4.1 - components/net/lwip-2.0.2 +- components/net/lwip-2.0.3 - components/net/lwip-2.1.2 \ No newline at end of file From b67e6bbafdf236afa41700c595d8362d543061a3 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Fri, 25 Jun 2021 21:04:48 +0800 Subject: [PATCH 193/255] [cmake] fix path issue. --- tools/cmake.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/cmake.py b/tools/cmake.py index 5b43c39409..88a95ecad8 100644 --- a/tools/cmake.py +++ b/tools/cmake.py @@ -49,10 +49,10 @@ def GenerateCFiles(env,project): cm_file.write("SET(CMAKE_SIZE \""+ SIZE + "\")\n\n") - cm_file.write("SET(CMAKE_C_FLAGS \""+ rtconfig.CFLAGS + "\")\n") - cm_file.write("SET(CMAKE_CXX_FLAGS \""+ rtconfig.CXXFLAGS + "\")\n") - cm_file.write("SET(CMAKE_ASM_FLAGS \""+ rtconfig.AFLAGS + "\")\n") - cm_file.write("SET(CMAKE_EXE_LINKER_FLAGS \""+ re.sub('-T(\s*)', '-T ${CMAKE_SOURCE_DIR}/',rtconfig.LFLAGS) + "\")\n\n") + cm_file.write("SET(CMAKE_C_FLAGS \""+ rtconfig.CFLAGS.replace('\\', "/") + "\")\n") + cm_file.write("SET(CMAKE_CXX_FLAGS \""+ rtconfig.CXXFLAGS.replace('\\', "/") + "\")\n") + cm_file.write("SET(CMAKE_ASM_FLAGS \""+ rtconfig.AFLAGS.replace('\\', "/") + "\")\n") + cm_file.write("SET(CMAKE_EXE_LINKER_FLAGS \""+ re.sub('-T(\s*)', '-T ${CMAKE_SOURCE_DIR}/',rtconfig.LFLAGS.replace('\\', "/")) + "\")\n\n") cm_file.write("SET(CMAKE_CXX_STANDARD 14)\n") cm_file.write("PROJECT(rtthread C CXX ASM)\n") From 7841aff0ca7cbdc6b9ed5b6c4572beccfc4d0b24 Mon Sep 17 00:00:00 2001 From: ArdaFu Date: Sat, 26 Jun 2021 12:37:09 +0800 Subject: [PATCH 194/255] [bsp][tm4c129x] Upgrade the Tiva Peripheral Driver Library to version 2.2.0.295. --- bsp/tm4c129x/libraries/driverlib/adc.c | 49 ++--- bsp/tm4c129x/libraries/driverlib/adc.h | 18 +- bsp/tm4c129x/libraries/driverlib/aes.c | 18 +- bsp/tm4c129x/libraries/driverlib/aes.h | 18 +- bsp/tm4c129x/libraries/driverlib/can.c | 47 ++++- bsp/tm4c129x/libraries/driverlib/can.h | 18 +- bsp/tm4c129x/libraries/driverlib/comp.c | 18 +- bsp/tm4c129x/libraries/driverlib/comp.h | 18 +- bsp/tm4c129x/libraries/driverlib/cpu.c | 18 +- bsp/tm4c129x/libraries/driverlib/cpu.h | 18 +- bsp/tm4c129x/libraries/driverlib/crc.c | 18 +- bsp/tm4c129x/libraries/driverlib/crc.h | 18 +- bsp/tm4c129x/libraries/driverlib/debug.h | 18 +- bsp/tm4c129x/libraries/driverlib/des.c | 18 +- bsp/tm4c129x/libraries/driverlib/des.h | 18 +- bsp/tm4c129x/libraries/driverlib/eeprom.c | 18 +- bsp/tm4c129x/libraries/driverlib/eeprom.h | 18 +- bsp/tm4c129x/libraries/driverlib/emac.c | 140 ++++++------- bsp/tm4c129x/libraries/driverlib/emac.h | 18 +- bsp/tm4c129x/libraries/driverlib/epi.c | 18 +- bsp/tm4c129x/libraries/driverlib/epi.h | 42 ++-- bsp/tm4c129x/libraries/driverlib/flash.c | 18 +- bsp/tm4c129x/libraries/driverlib/flash.h | 18 +- bsp/tm4c129x/libraries/driverlib/fpu.c | 18 +- bsp/tm4c129x/libraries/driverlib/fpu.h | 18 +- bsp/tm4c129x/libraries/driverlib/gpio.c | 179 +++++++++++------ bsp/tm4c129x/libraries/driverlib/gpio.h | 19 +- bsp/tm4c129x/libraries/driverlib/hibernate.c | 29 +-- bsp/tm4c129x/libraries/driverlib/hibernate.h | 19 +- bsp/tm4c129x/libraries/driverlib/i2c.c | 22 +-- bsp/tm4c129x/libraries/driverlib/i2c.h | 18 +- bsp/tm4c129x/libraries/driverlib/interrupt.c | 18 +- bsp/tm4c129x/libraries/driverlib/interrupt.h | 18 +- bsp/tm4c129x/libraries/driverlib/lcd.c | 18 +- bsp/tm4c129x/libraries/driverlib/lcd.h | 18 +- bsp/tm4c129x/libraries/driverlib/mpu.c | 18 +- bsp/tm4c129x/libraries/driverlib/mpu.h | 18 +- bsp/tm4c129x/libraries/driverlib/onewire.c | 18 +- bsp/tm4c129x/libraries/driverlib/onewire.h | 18 +- bsp/tm4c129x/libraries/driverlib/pin_map.h | 18 +- bsp/tm4c129x/libraries/driverlib/pwm.c | 29 +-- bsp/tm4c129x/libraries/driverlib/pwm.h | 18 +- bsp/tm4c129x/libraries/driverlib/qei.c | 18 +- bsp/tm4c129x/libraries/driverlib/qei.h | 18 +- bsp/tm4c129x/libraries/driverlib/readme.txt | 6 +- bsp/tm4c129x/libraries/driverlib/rom.h | 18 +- bsp/tm4c129x/libraries/driverlib/rom_map.h | 186 +++++++++++++++++- .../libraries/driverlib/rtos_bindings.h | 18 +- bsp/tm4c129x/libraries/driverlib/shamd5.c | 18 +- bsp/tm4c129x/libraries/driverlib/shamd5.h | 18 +- bsp/tm4c129x/libraries/driverlib/ssi.c | 95 +++++++-- bsp/tm4c129x/libraries/driverlib/ssi.h | 20 +- bsp/tm4c129x/libraries/driverlib/sw_crc.c | 18 +- bsp/tm4c129x/libraries/driverlib/sw_crc.h | 18 +- bsp/tm4c129x/libraries/driverlib/sysctl.c | 45 ++--- bsp/tm4c129x/libraries/driverlib/sysctl.h | 37 ++-- bsp/tm4c129x/libraries/driverlib/sysexc.c | 18 +- bsp/tm4c129x/libraries/driverlib/sysexc.h | 18 +- bsp/tm4c129x/libraries/driverlib/systick.c | 18 +- bsp/tm4c129x/libraries/driverlib/systick.h | 18 +- bsp/tm4c129x/libraries/driverlib/tiva_timer.c | 33 ++-- bsp/tm4c129x/libraries/driverlib/tiva_timer.h | 20 +- bsp/tm4c129x/libraries/driverlib/uart.c | 64 ++++-- bsp/tm4c129x/libraries/driverlib/uart.h | 18 +- bsp/tm4c129x/libraries/driverlib/udma.c | 18 +- bsp/tm4c129x/libraries/driverlib/udma.h | 18 +- bsp/tm4c129x/libraries/driverlib/usb.c | 18 +- bsp/tm4c129x/libraries/driverlib/usb.h | 18 +- bsp/tm4c129x/libraries/driverlib/watchdog.c | 20 +- bsp/tm4c129x/libraries/driverlib/watchdog.h | 18 +- bsp/tm4c129x/libraries/inc/asmdefs.h | 18 +- bsp/tm4c129x/libraries/inc/hw_adc.h | 18 +- bsp/tm4c129x/libraries/inc/hw_aes.h | 18 +- bsp/tm4c129x/libraries/inc/hw_can.h | 18 +- bsp/tm4c129x/libraries/inc/hw_ccm.h | 18 +- bsp/tm4c129x/libraries/inc/hw_comp.h | 18 +- bsp/tm4c129x/libraries/inc/hw_des.h | 18 +- bsp/tm4c129x/libraries/inc/hw_eeprom.h | 18 +- bsp/tm4c129x/libraries/inc/hw_emac.h | 18 +- bsp/tm4c129x/libraries/inc/hw_epi.h | 18 +- bsp/tm4c129x/libraries/inc/hw_fan.h | 18 +- bsp/tm4c129x/libraries/inc/hw_flash.h | 18 +- bsp/tm4c129x/libraries/inc/hw_gpio.h | 18 +- bsp/tm4c129x/libraries/inc/hw_hibernate.h | 18 +- bsp/tm4c129x/libraries/inc/hw_i2c.h | 18 +- bsp/tm4c129x/libraries/inc/hw_ints.h | 18 +- bsp/tm4c129x/libraries/inc/hw_lcd.h | 18 +- bsp/tm4c129x/libraries/inc/hw_memmap.h | 18 +- bsp/tm4c129x/libraries/inc/hw_nvic.h | 18 +- bsp/tm4c129x/libraries/inc/hw_onewire.h | 18 +- bsp/tm4c129x/libraries/inc/hw_pwm.h | 18 +- bsp/tm4c129x/libraries/inc/hw_qei.h | 18 +- bsp/tm4c129x/libraries/inc/hw_shamd5.h | 18 +- bsp/tm4c129x/libraries/inc/hw_ssi.h | 18 +- bsp/tm4c129x/libraries/inc/hw_sysctl.h | 18 +- bsp/tm4c129x/libraries/inc/hw_sysexc.h | 18 +- bsp/tm4c129x/libraries/inc/hw_timer.h | 18 +- bsp/tm4c129x/libraries/inc/hw_types.h | 20 +- bsp/tm4c129x/libraries/inc/hw_uart.h | 18 +- bsp/tm4c129x/libraries/inc/hw_udma.h | 18 +- bsp/tm4c129x/libraries/inc/hw_usb.h | 18 +- bsp/tm4c129x/libraries/inc/hw_watchdog.h | 18 +- bsp/tm4c129x/libraries/inc/tm4c1294ncpdt.h | 18 +- .../libraries/startup/startup_ewarm.c | 6 +- bsp/tm4c129x/libraries/startup/startup_gcc.c | 6 +- .../libraries/startup/startup_rvmdk.S | 6 +- 106 files changed, 1495 insertions(+), 1120 deletions(-) diff --git a/bsp/tm4c129x/libraries/driverlib/adc.c b/bsp/tm4c129x/libraries/driverlib/adc.c index 81e7dc05fc..12e8553919 100644 --- a/bsp/tm4c129x/libraries/driverlib/adc.c +++ b/bsp/tm4c129x/libraries/driverlib/adc.c @@ -2,25 +2,25 @@ // // adc.c - Driver for the ADC. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -554,7 +554,7 @@ ADCSequenceConfigure(uint32_t ui32Base, uint32_t ui32SequenceNum, // Set the shift for the module and generator // ui32Gen = (ui32Gen - ADC_TRIGGER_PWM0) * 8; - + HWREG(ui32Base + ADC_O_TSSEL) = ((HWREG(ui32Base + ADC_O_TSSEL) & ~(0x30 << ui32Gen)) | ((ui32Trigger & 0x30) << ui32Gen)); @@ -568,10 +568,15 @@ ADCSequenceConfigure(uint32_t ui32Base, uint32_t ui32SequenceNum, //! \param ui32Base is the base address of the ADC module. //! \param ui32SequenceNum is the sample sequence number. //! \param ui32Step is the step to be configured. -//! \param ui32Config is the configuration of this step; must be a logical OR +//! \param ui32Config is the configuration of this step; is a logical OR //! of \b ADC_CTL_TS, \b ADC_CTL_IE, \b ADC_CTL_END, \b ADC_CTL_D, one of the //! input channel selects (\b ADC_CTL_CH0 through \b ADC_CTL_CH23), and one of //! the digital comparator selects (\b ADC_CTL_CMP0 through \b ADC_CTL_CMP7). +//! On some parts the sample and hold time can be increased by including a +//! logical OR of one of \b ADC_CTL_SHOLD_4, \b ADC_CTL_SHOLD_8, +//! \b ADC_CTL_SHOLD_16, \b ADC_CTL_SHOLD_32, \b ADC_CTL_SHOLD_64, +//! \b ADC_CTL_SHOLD_128 or \b ADC_CTL_SHOLD_256. The default sample time is 4 +//! ADC clocks. //! //! This function configures the ADC for one step of a sample sequence. The //! ADC can be configured for single-ended or differential operation (the @@ -1010,9 +1015,9 @@ ADCSoftwareOversampleStepConfigure(uint32_t ui32Base, uint32_t ui32SequenceNum, ASSERT((ui32Base == ADC0_BASE) || (ui32Base == ADC1_BASE)); ASSERT(ui32SequenceNum < 3); ASSERT(((ui32SequenceNum == 0) && - (ui32Step < + (ui32Step < (8 >> g_pui8OversampleFactor[ui32ADCInst][ui32SequenceNum]))) || - (ui32Step < + (ui32Step < (4 >> g_pui8OversampleFactor[ui32ADCInst][ui32SequenceNum]))); // @@ -1029,7 +1034,7 @@ ADCSoftwareOversampleStepConfigure(uint32_t ui32Base, uint32_t ui32SequenceNum, // Loop through the hardware steps that make up this step of the software // oversampled sequence. // - for(ui32SequenceNum = + for(ui32SequenceNum = (1 << g_pui8OversampleFactor[ui32ADCInst][ui32SequenceNum]); ui32SequenceNum; ui32SequenceNum--) { @@ -1114,9 +1119,9 @@ ADCSoftwareOversampleDataGet(uint32_t ui32Base, uint32_t ui32SequenceNum, ASSERT((ui32Base == ADC0_BASE) || (ui32Base == ADC1_BASE)); ASSERT(ui32SequenceNum < 3); ASSERT(((ui32SequenceNum == 0) && - (ui32Count < + (ui32Count < (8 >> g_pui8OversampleFactor[ui32ADCInst][ui32SequenceNum]))) || - (ui32Count < + (ui32Count < (4 >> g_pui8OversampleFactor[ui32ADCInst][ui32SequenceNum]))); // @@ -1145,7 +1150,7 @@ ADCSoftwareOversampleDataGet(uint32_t ui32Base, uint32_t ui32SequenceNum, // // Write the averaged sample to the output buffer. // - *pui32Buffer++ = + *pui32Buffer++ = ui32Accum >> g_pui8OversampleFactor[ui32ADCInst][ui32SequenceNum]; } } @@ -1678,7 +1683,7 @@ ADCIntClearEx(uint32_t ui32Base, uint32_t ui32IntFlags) //! //! The ADC reference is set as specified by \e ui32Ref. It must be one of //! \b ADC_REF_INT, or \b ADC_REF_EXT_3V for internal or external reference -//! If \b ADC_REF_INT is chosen, then an internal 3V reference is used and +//! If \b ADC_REF_INT is chosen, then an internal 3V reference is used and //! no external reference is needed. If \b ADC_REF_EXT_3V is chosen, then //! a 3V reference must be supplied to the AVREF pin. //! @@ -1977,7 +1982,7 @@ ADCClockConfigSet(uint32_t ui32Base, uint32_t ui32Config, // // Check the argument. // - ASSERT((ui32Base == ADC0_BASE) || (ui32Base == ADC1_BASE)); + ASSERT(ui32Base == ADC0_BASE); ASSERT((ui32ClockDiv - 1) <= (ADC_CC_CLKDIV_M >> ADC_CC_CLKDIV_S)); // @@ -2036,12 +2041,12 @@ ADCClockConfigGet(uint32_t ui32Base, uint32_t *pui32ClockDiv) // // Check the argument. // - ASSERT((ui32Base == ADC0_BASE) || (ui32Base == ADC1_BASE)); + ASSERT(ui32Base == ADC0_BASE); // // Read the current configuration. // - ui32Config = HWREG(ui32Base + ADC_O_CC); + ui32Config = HWREG(ADC0_BASE + ADC_O_CC); // // If the clock divider was requested provide the current value. @@ -2060,7 +2065,7 @@ ADCClockConfigGet(uint32_t ui32Base, uint32_t *pui32ClockDiv) // // Add in the sample interval to the configuration. // - ui32Config |= (HWREG(ui32Base + ADC_O_PC) & ADC_PC_SR_M) << 4; + ui32Config |= (HWREG(ADC0_BASE + ADC_O_PC) & ADC_PC_SR_M) << 4; return(ui32Config); } diff --git a/bsp/tm4c129x/libraries/driverlib/adc.h b/bsp/tm4c129x/libraries/driverlib/adc.h index 993b6a3fb5..d2d6bcd38b 100644 --- a/bsp/tm4c129x/libraries/driverlib/adc.h +++ b/bsp/tm4c129x/libraries/driverlib/adc.h @@ -2,25 +2,25 @@ // // adc.h - ADC headers for using the ADC driver functions. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/aes.c b/bsp/tm4c129x/libraries/driverlib/aes.c index 06cf55bb0b..d15a0900e5 100644 --- a/bsp/tm4c129x/libraries/driverlib/aes.c +++ b/bsp/tm4c129x/libraries/driverlib/aes.c @@ -2,25 +2,25 @@ // // aes.c - Driver for the AES module. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/aes.h b/bsp/tm4c129x/libraries/driverlib/aes.h index 6cf44780dd..6b505f68b3 100644 --- a/bsp/tm4c129x/libraries/driverlib/aes.h +++ b/bsp/tm4c129x/libraries/driverlib/aes.h @@ -2,25 +2,25 @@ // // aes.h - Defines and Macros for the AES module. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/can.c b/bsp/tm4c129x/libraries/driverlib/can.c index d53584585c..81b05446a4 100644 --- a/bsp/tm4c129x/libraries/driverlib/can.c +++ b/bsp/tm4c129x/libraries/driverlib/can.c @@ -2,25 +2,25 @@ // // can.c - Driver for the CAN module. // -// Copyright (c) 2006-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2006-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -831,7 +831,7 @@ CANIntRegister(uint32_t ui32Base, void (*pfnHandler)(void)) IntRegister(ui8IntNumber, pfnHandler); // - // Enable the Ethernet interrupt. + // Enable the CAN interrupt. // IntEnable(ui8IntNumber); } @@ -1077,6 +1077,13 @@ CANIntStatus(uint32_t ui32Base, tCANIntStsReg eIntStsReg) //! being immediately reentered (because the interrupt controller still sees //! the interrupt source asserted). //! +//! \note The functions CANIntClear(), CANMessageSet(), and CANMessageClear() +//! are not re-entrant. If any of these functions are used in the main +//! application code and if any of them are also used within an interrupt +//! routine, then the corresponding interrupt for that interrupt routine should +//! be disabled prior to the call for any of these functions. The interrupt +//! can be re-enabled immediately after the function call has returned. +//! //! \return None. // //***************************************************************************** @@ -1470,6 +1477,13 @@ CANErrCntrGet(uint32_t ui32Base, uint32_t *pui32RxCount, //! If you specify a message object buffer that already contains a message //! definition, it is overwritten. //! +//! \note The functions CANIntClear(), CANMessageSet(), and CANMessageClear() +//! are not re-entrant. If any of these functions are used in the main +//! application code and if any of them are also used within an interrupt +//! routine, then the corresponding interrupt for that interrupt routine should +//! be disabled prior to the call for any of these functions. The interrupt +//! can be re-enabled immediately after the function call has returned. +//! //! \return None. // //***************************************************************************** @@ -1831,6 +1845,12 @@ CANMessageSet(uint32_t ui32Base, uint32_t ui32ObjID, //! - \b MSG_OBJ_DATA_LOST indicates that at least one message was received on //! this message object and not read by the host before being overwritten. //! +//! \note This function is not re-entrant. If it is used in both main +//! application code and in an interrupt routine, then the corresponding +//! interrupt should be disabled prior to the call for CANMessageGet(). +//! The interrupt can be re-enabled immediately after the function call has +//! returned. +//! //! \return None. // //***************************************************************************** @@ -2076,6 +2096,13 @@ CANMessageGet(uint32_t ui32Base, uint32_t ui32ObjID, //! object has been ``cleared,'' it no longer automatically sends or receives //! messages, nor does it generate interrupts. //! +//! \note The functions CANIntClear(), CANMessageSet(), and CANMessageClear() +//! are not re-entrant. If any of these functions are used in the main +//! application code and if any of them are also used within an interrupt +//! routine, then the corresponding interrupt for that interrupt routine should +//! be disabled prior to the call for any of these functions. The interrupt +//! can be re-enabled immediately after the function call has returned. +//! //! \return None. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/can.h b/bsp/tm4c129x/libraries/driverlib/can.h index 199721906b..c4a8b10ca2 100644 --- a/bsp/tm4c129x/libraries/driverlib/can.h +++ b/bsp/tm4c129x/libraries/driverlib/can.h @@ -2,25 +2,25 @@ // // can.h - Defines and Macros for the CAN controller. // -// Copyright (c) 2006-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2006-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/comp.c b/bsp/tm4c129x/libraries/driverlib/comp.c index 6f03b7c01a..3b4ab2042b 100644 --- a/bsp/tm4c129x/libraries/driverlib/comp.c +++ b/bsp/tm4c129x/libraries/driverlib/comp.c @@ -2,25 +2,25 @@ // // comp.c - Driver for the analog comparator. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/comp.h b/bsp/tm4c129x/libraries/driverlib/comp.h index 2f95df09c9..5f33b332a8 100644 --- a/bsp/tm4c129x/libraries/driverlib/comp.h +++ b/bsp/tm4c129x/libraries/driverlib/comp.h @@ -2,25 +2,25 @@ // // comp.h - Prototypes for the analog comparator driver. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/cpu.c b/bsp/tm4c129x/libraries/driverlib/cpu.c index 0cddffc340..fb1c9a667b 100644 --- a/bsp/tm4c129x/libraries/driverlib/cpu.c +++ b/bsp/tm4c129x/libraries/driverlib/cpu.c @@ -3,25 +3,25 @@ // cpu.c - Instruction wrappers for special CPU instructions needed by the // drivers. // -// Copyright (c) 2006-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2006-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,8 +33,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/cpu.h b/bsp/tm4c129x/libraries/driverlib/cpu.h index 11a07e88d0..4f8976e9cf 100644 --- a/bsp/tm4c129x/libraries/driverlib/cpu.h +++ b/bsp/tm4c129x/libraries/driverlib/cpu.h @@ -2,25 +2,25 @@ // // cpu.h - Prototypes for the CPU instruction wrapper functions. // -// Copyright (c) 2006-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2006-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/crc.c b/bsp/tm4c129x/libraries/driverlib/crc.c index 55bd4d6048..a4364a9b13 100644 --- a/bsp/tm4c129x/libraries/driverlib/crc.c +++ b/bsp/tm4c129x/libraries/driverlib/crc.c @@ -2,25 +2,25 @@ // // crc.c - Driver for the CRC module. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/crc.h b/bsp/tm4c129x/libraries/driverlib/crc.h index 7d33e84cb6..eff20a2f4f 100644 --- a/bsp/tm4c129x/libraries/driverlib/crc.h +++ b/bsp/tm4c129x/libraries/driverlib/crc.h @@ -2,25 +2,25 @@ // // crc.h - Defines and Macros for CRC module. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/debug.h b/bsp/tm4c129x/libraries/driverlib/debug.h index fd2e3afba1..3181b236d9 100644 --- a/bsp/tm4c129x/libraries/driverlib/debug.h +++ b/bsp/tm4c129x/libraries/driverlib/debug.h @@ -2,25 +2,25 @@ // // debug.h - Macros for assisting debug of the driver library. // -// Copyright (c) 2006-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2006-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/des.c b/bsp/tm4c129x/libraries/driverlib/des.c index 1b6e86a2a8..0b92887b5d 100644 --- a/bsp/tm4c129x/libraries/driverlib/des.c +++ b/bsp/tm4c129x/libraries/driverlib/des.c @@ -2,25 +2,25 @@ // // des.c - Driver for the DES data transformation. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/des.h b/bsp/tm4c129x/libraries/driverlib/des.h index 9f6c8d1853..54cfb50776 100644 --- a/bsp/tm4c129x/libraries/driverlib/des.h +++ b/bsp/tm4c129x/libraries/driverlib/des.h @@ -2,25 +2,25 @@ // // des.h - Defines and Macros for the DES module. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/eeprom.c b/bsp/tm4c129x/libraries/driverlib/eeprom.c index 6daae87be0..11b0635326 100644 --- a/bsp/tm4c129x/libraries/driverlib/eeprom.c +++ b/bsp/tm4c129x/libraries/driverlib/eeprom.c @@ -2,25 +2,25 @@ // // eeprom.c - Driver for programming the on-chip EEPROM. // -// Copyright (c) 2010-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2010-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/eeprom.h b/bsp/tm4c129x/libraries/driverlib/eeprom.h index 0336010e06..0df91a05e6 100644 --- a/bsp/tm4c129x/libraries/driverlib/eeprom.h +++ b/bsp/tm4c129x/libraries/driverlib/eeprom.h @@ -2,25 +2,25 @@ // // eeprom.h - Prototypes for the EEPROM driver. // -// Copyright (c) 2010-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2010-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/emac.c b/bsp/tm4c129x/libraries/driverlib/emac.c index 8c238d299e..4887f55e27 100644 --- a/bsp/tm4c129x/libraries/driverlib/emac.c +++ b/bsp/tm4c129x/libraries/driverlib/emac.c @@ -3,25 +3,25 @@ // emac.c - Driver for the Integrated Ethernet Controller on Snowflake-class // Tiva devices. // -// Copyright (c) 2013-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2013-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,8 +33,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -297,12 +297,12 @@ g_pi16MIIClockDiv[] = //! (where each descriptor includes a field that points to the next descriptor //! in the list). In ring mode, the hardware uses the \e ui32DescSkipSize to //! skip past any application-defined fields after the end of the hardware- -//! defined descriptor fields. The parameter value indicates the number of -//! 32-bit words to skip after the last field of the hardware-defined -//! descriptor to get to the first field of the next descriptor. When using -//! arrays of either the \b tEMACDMADescriptor or \b tEMACAltDMADescriptor +//! defined descriptor fields. The parameter value indicates the number of +//! 32-bit words to skip after the last field of the hardware-defined +//! descriptor to get to the first field of the next descriptor. When using +//! arrays of either the \b tEMACDMADescriptor or \b tEMACAltDMADescriptor //! types defined for this driver, \e ui32DescSkipSize must be set to 1 to skip -//! the \e pvNext pointer added to the end of each of these structures. +//! the \e pvNext pointer added to the end of each of these structures. //! Applications may modify these structure definitions to include their own //! application-specific data and modify \e ui32DescSkipSize appropriately if //! desired. @@ -419,8 +419,8 @@ EMACInit(uint32_t ui32Base, uint32_t ui32SysClk, uint32_t ui32BusConfig, //! //! \param ui32Base is the base address of the Ethernet controller. //! -//! This function performs a reset of the Ethernet MAC by resetting all logic -//! and returning all registers to their default values. The function returns +//! This function performs a reset of the Ethernet MAC by resetting all logic +//! and returning all registers to their default values. The function returns //! only after the hardware indicates that the reset has completed. //! //! \note To ensure that the reset completes, the selected PHY clock must be @@ -495,7 +495,7 @@ EMACReset(uint32_t ui32Base) //! RMII interface. //! //! If \b EMAC_PHY_TYPE_INTERNAL is selected, the following flags may be ORed -//! into \e ui32Config to control various PHY features and modes. These flags +//! into \e ui32Config to control various PHY features and modes. These flags //! are ignored if an external PHY is selected. //! //! - \b EMAC_PHY_INT_NIB_TXERR_DET_DIS disables odd nibble transmit error @@ -682,7 +682,7 @@ EMACPHYConfigSet(uint32_t ui32Base, uint32_t ui32Config) //! The back-off limit determines the range of the random time that the MAC //! delays after a collision and before attempting to retransmit a frame. One //! of the following values must be used to select this limit. In each case, -//! the retransmission delay in terms of 512 bit time slots, is the lower of +//! the retransmission delay in terms of 512 bit time slots, is the lower of //! (2 ** N) and a random number between 0 and the selected backoff-limit. //! //! - \b EMAC_CONFIG_BO_LIMIT_1024 @@ -727,10 +727,10 @@ EMACPHYConfigSet(uint32_t ui32Base, uint32_t ui32Config) //! up to 9018 (or 9022 if using VLAN tagging) to be handled without reporting //! giant frame errors. //! - \b EMAC_CONFIG_100MBPS forces the MAC to communicate with the PHY using -//! 100Mbps signaling. If this option is not specified, the MAC uses 10Mbps -//! signaling. This speed setting is important when using an external RMII -//! PHY where the selected rate must match the PHY's setting which may have -//! been made as a result of auto-negotiation. When using the internal PHY +//! 100Mbps signaling. If this option is not specified, the MAC uses 10Mbps +//! signaling. This speed setting is important when using an external RMII +//! PHY where the selected rate must match the PHY's setting which may have +//! been made as a result of auto-negotiation. When using the internal PHY //! or an external MII PHY, the signaling rate is controlled by the PHY- //! provided transmit and receive clocks. //! - \b EMAC_CONFIG_CS_DISABLE disables Carrier Sense during transmission @@ -743,15 +743,15 @@ EMACPHYConfigSet(uint32_t ui32Base, uint32_t ui32Config) //! of the checksum calculations are reported via status fields in the DMA //! receive descriptors. //! - \b EMAC_CONFIG_RETRY_DISABLE disables retransmission in cases where -//! half-duplex mode is in use and a collision occurs. This condition causes -//! the current frame to be ignored and a frame abort to be reported in the +//! half-duplex mode is in use and a collision occurs. This condition causes +//! the current frame to be ignored and a frame abort to be reported in the //! transmit frame status. //! - \b EMAC_CONFIG_AUTO_CRC_STRIPPING strips the last 4 bytes (frame check //! sequence) from all Ether type frames before forwarding the frames to the //! application. //! - \b EMAC_CONFIG_DEFERRAL_CHK_ENABLE enables transmit deferral checking -//! in half-duplex mode. When enabled, the transmitter reports an error if it -//! is unable to transmit a frame for more than 24288 bit times (or 155680 +//! in half-duplex mode. When enabled, the transmitter reports an error if it +//! is unable to transmit a frame for more than 24288 bit times (or 155680 //! bit times in Jumbo frame mode) due to an active carrier sense signal on //! the MII. //! @@ -971,14 +971,14 @@ EMACConfigSet(uint32_t ui32Base, uint32_t ui32Config, uint32_t ui32ModeFlags, //! fields in the DMA receive descriptors. //! - \b EMAC_CONFIG_RETRY_DISABLE indicates that retransmission is disabled //! in cases where half-duplex mode is in use and a collision occurs. This -//! condition causes the current frame to be ignored and a frame abort to be +//! condition causes the current frame to be ignored and a frame abort to be //! reported in the transmit frame status. //! - \b EMAC_CONFIG_AUTO_CRC_STRIPPING indicates that the last 4 bytes //! (frame check sequence) from all Ether type frames are being stripped before //! frames are forwarded to the application. //! - \b EMAC_CONFIG_DEFERRAL_CHK_ENABLE indicates that transmit deferral //! checking is disabled in half-duplex mode. When enabled, the transmitter -//! reports an error if it is unable to transmit a frame for more than 24288 +//! reports an error if it is unable to transmit a frame for more than 24288 //! bit times (or 155680 bit times in Jumbo frame mode) due to an active //! carrier sense signal on the MII. //! - \b EMAC_CONFIG_TX_ENABLED indicates that the MAC transmitter is @@ -1225,7 +1225,7 @@ EMACAddrSet(uint32_t ui32Base, uint32_t ui32Index, const uint8_t *pui8MACAddr) //! //! AC-DE-48-00-00-80 //! -//! the data is returned with 0xAC in the first byte of the array, 0xDE in +//! the data is returned with 0xAC in the first byte of the array, 0xDE in //! the second, 0x48 in the third and so on. //! //! \return None. @@ -1287,7 +1287,7 @@ EMACNumAddrGet(uint32_t ui32Base) //! addresses. //! //! \param ui32Base is the base address of the controller. -//! \param ui32Index is the index of the MAC address slot for which the filter +//! \param ui32Index is the index of the MAC address slot for which the filter //! is to be set. //! \param ui32Config sets the filter parameters for the given MAC address. //! @@ -1295,9 +1295,9 @@ EMACNumAddrGet(uint32_t ui32Base) //! address slots that the controller supports. This configuration is used //! when perfect filtering (rather than hash table filtering) is selected. //! -//! Valid values for \e ui32Index are from 1 to (number of MAC address -//! slots - 1). The number of supported MAC address slots may be found by -//! calling EMACNumAddrGet(). MAC index 0 is the local MAC address and does +//! Valid values for \e ui32Index are from 1 to (number of MAC address +//! slots - 1). The number of supported MAC address slots may be found by +//! calling EMACNumAddrGet(). MAC index 0 is the local MAC address and does //! not have filtering parameters associated with it. //! //! The \e ui32Config parameter determines how the given MAC address is used @@ -1362,16 +1362,16 @@ EMACAddrFilterSet(uint32_t ui32Base, uint32_t ui32Index, uint32_t ui32Config) //! addresses. //! //! \param ui32Base is the base address of the controller. -//! \param ui32Index is the index of the MAC address slot for which the filter +//! \param ui32Index is the index of the MAC address slot for which the filter //! is to be queried. //! //! This function returns filtering parameters associated with one of the MAC //! address slots that the controller supports. This configuration is used //! when perfect filtering (rather than hash table filtering) is selected. //! -//! Valid values for \e ui32Index are from 1 to (number of MAC address -//! slots - 1). The number of supported MAC address slots may be found by -//! calling EMACNumAddrGet(). MAC index 0 is the local MAC address and does +//! Valid values for \e ui32Index are from 1 to (number of MAC address +//! slots - 1). The number of supported MAC address slots may be found by +//! calling EMACNumAddrGet(). MAC index 0 is the local MAC address and does //! not have filtering parameters associated with it. //! //! \return Returns the filter configuration as the logical OR of the @@ -1450,7 +1450,7 @@ EMACAddrFilterGet(uint32_t ui32Base, uint32_t ui32Index) //! when the source address field in the frame does not match the values //! programmed into the enabled SA registers. //! - \b EMAC_FRMFILTER_INV_SADDR enables inverse source address filtering. -//! When this option is specified, frames for which the SA does not match the +//! When this option is specified, frames for which the SA does not match the //! SA registers are marked as passing the source address filter. //! - \b EMAC_FRMFILTER_BROADCAST configures the MAC to discard all incoming //! broadcast frames. @@ -1530,7 +1530,7 @@ EMACFrameFilterSet(uint32_t ui32Base, uint32_t ui32FilterOpts) //! received frames when the source address field in the frame does not match //! the values programmed into the enabled SA registers. //! - \b EMAC_FRMFILTER_INV_SADDR enables inverse source address filtering. -//! When this option is specified, frames for which the SA does not match the +//! When this option is specified, frames for which the SA does not match the //! SA registers are marked as passing the source address filter. //! - \b EMAC_FRMFILTER_BROADCAST indicates that the MAC is configured to //! discard all incoming broadcast frames. @@ -1621,9 +1621,9 @@ EMACHashFilterSet(uint32_t ui32Base, uint32_t ui32HashHi, uint32_t ui32HashLo) //! Returns the current MAC address hash filter table. //! //! \param ui32Base is the base address of the controller. -//! \param pui32HashHi points to storage to be written with the upper 32 bits +//! \param pui32HashHi points to storage to be written with the upper 32 bits //! of the current 64-bit hash filter table. -//! \param pui32HashLo points to storage to be written with the lower 32 bits +//! \param pui32HashLo points to storage to be written with the lower 32 bits //! of the current 64-bit hash filter table. //! //! This function may be used to retrieve the current 64-bit hash filter table @@ -1766,8 +1766,8 @@ EMACRxWatchdogTimerSet(uint32_t ui32Base, uint8_t ui8Timeout) //! - \b EMAC_STATUS_RWC_ACTIVE //! - \b EMAC_STATUS_RPE_ACTIVE //! -//! The transmit frame controller status can be extracted from the returned -//! value by ANDing with \b EMAC_STATUS_TFC_STATE_MASK and is one of the +//! The transmit frame controller status can be extracted from the returned +//! value by ANDing with \b EMAC_STATUS_TFC_STATE_MASK and is one of the //! following: //! //! - \b EMAC_STATUS_TFC_STATE_IDLE @@ -1775,8 +1775,8 @@ EMACRxWatchdogTimerSet(uint32_t ui32Base, uint8_t ui8Timeout) //! - \b EMAC_STATUS_TFC_STATE_PAUSING //! - \b EMAC_STATUS_TFC_STATE_WRITING //! -//! The transmit FIFO read controller status can be extracted from the returned -//! value by ANDing with \b EMAC_STATUS_TRC_STATE_MASK and is one of the +//! The transmit FIFO read controller status can be extracted from the returned +//! value by ANDing with \b EMAC_STATUS_TRC_STATE_MASK and is one of the //! following: //! //! - \b EMAC_STATUS_TRC_STATE_IDLE @@ -1785,7 +1785,7 @@ EMACRxWatchdogTimerSet(uint32_t ui32Base, uint8_t ui8Timeout) //! - \b EMAC_STATUS_TRC_STATE_STATUS //! //! The current receive FIFO levels can be extracted from the returned value -//! by ANDing with \b EMAC_STATUS_RX_FIFO_LEVEL_MASK and is one of the +//! by ANDing with \b EMAC_STATUS_RX_FIFO_LEVEL_MASK and is one of the //! following: //! //! - \b EMAC_STATUS_RX_FIFO_EMPTY indicating that the FIFO is empty. @@ -1796,7 +1796,7 @@ EMACRxWatchdogTimerSet(uint32_t ui32Base, uint8_t ui8Timeout) //! - \b EMAC_STATUS_RX_FIFO_FULL indicating that the FIFO is full. //! //! The current receive FIFO state can be extracted from the returned value -//! by ANDing with \b EMAC_STATUS_RX_FIFO_STATE_MASK and is one of the +//! by ANDing with \b EMAC_STATUS_RX_FIFO_STATE_MASK and is one of the //! following: //! //! - \b EMAC_STATUS_RX_FIFO_IDLE @@ -2049,7 +2049,7 @@ EMACTxDMADescriptorListSet(uint32_t ui32Base, tEMACDMADescriptor *pDescriptor) //! \param ui32Base is the base address of the controller. //! //! This function returns a pointer to the head of the Ethernet MAC's transmit -//! DMA descriptor list. This value corresponds to the pointer originally set +//! DMA descriptor list. This value corresponds to the pointer originally set //! using a call to EMACTxDMADescriptorListSet(). //! //! \return Returns a pointer to the start of the DMA transmit descriptor list. @@ -2438,8 +2438,8 @@ EMACIntUnregister(uint32_t ui32Base) //! - \b EMAC_INT_RX_OVERFLOW indicates that an overflow was experienced //! during reception. //! - \b EMAC_INT_TX_JABBER indicates that the transmit jabber timer expired. -//! This condition occurs when the frame size exceeds 2048 bytes (or 10240 -//! bytes in Jumbo Frame mode) and causes the transmit process to abort and +//! This condition occurs when the frame size exceeds 2048 bytes (or 10240 +//! bytes in Jumbo Frame mode) and causes the transmit process to abort and //! enter the Stopped state. //! - \b EMAC_INT_TX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's transmit descriptor list and that the DMA cannot, therefore, @@ -2540,8 +2540,8 @@ EMACIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags) //! - \b EMAC_INT_RX_OVERFLOW indicates that an overflow was experienced //! during reception. //! - \b EMAC_INT_TX_JABBER indicates that the transmit jabber timer expired. -//! This condition occurs when the frame size exceeds 2048 bytes (or 10240 -//! bytes in Jumbo Frame mode) and causes the transmit process to abort and +//! This condition occurs when the frame size exceeds 2048 bytes (or 10240 +//! bytes in Jumbo Frame mode) and causes the transmit process to abort and //! enter the Stopped state. //! - \b EMAC_INT_TX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's transmit descriptor list and that the DMA cannot, therefore, @@ -2660,8 +2660,8 @@ EMACIntDisable(uint32_t ui32Base, uint32_t ui32IntFlags) //! - \b EMAC_INT_RX_OVERFLOW indicates that an overflow was experienced //! during reception. //! - \b EMAC_INT_TX_JABBER indicates that the transmit jabber timer expired. -//! This condition occurs when the frame size exceeds 2048 bytes (or 10240 -//! bytes in Jumbo Frame mode) and causes the transmit process to abort and +//! This condition occurs when the frame size exceeds 2048 bytes (or 10240 +//! bytes in Jumbo Frame mode) and causes the transmit process to abort and //! enter the Stopped state. //! - \b EMAC_INT_TX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's transmit descriptor list and that the DMA cannot, therefore, @@ -2767,8 +2767,8 @@ EMACIntStatus(uint32_t ui32Base, bool bMasked) //! - \b EMAC_INT_RX_OVERFLOW indicates that an overflow was experienced //! during reception. //! - \b EMAC_INT_TX_JABBER indicates that the transmit jabber timer expired. -//! This condition occurs when the frame size exceeds 2048 bytes (or 10240 -//! bytes in Jumbo Frame mode) and causes the transmit process to abort and +//! This condition occurs when the frame size exceeds 2048 bytes (or 10240 +//! bytes in Jumbo Frame mode) and causes the transmit process to abort and //! enter the Stopped state. //! - \b EMAC_INT_TX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's transmit descriptor list and that the DMA cannot, therefore, @@ -3160,7 +3160,7 @@ EMACPHYPowerOn(uint32_t ui32Base, uint8_t ui8PhyAddr) //! simple 31-bit counter, rolling over to 0 after reaching 0x7FFFFFFF. In //! this case, each lsb of the subsecond counter represents 0.465 ns (assuming //! the definition of 1 second resolution for the seconds counter). When -//! binary rollover mode is selected, the subsecond counter acts as a +//! binary rollover mode is selected, the subsecond counter acts as a //! nanosecond counter and rolls over to 0 after reaching 999,999,999 making //! each lsb represent 1 nanosecond. //! @@ -3250,7 +3250,7 @@ EMACTimestampConfigSet(uint32_t ui32Base, uint32_t ui32Config, //! are filtered using any of the configured MAC addresses. Messages with a //! destination address programmed into the MAC address filter are passed, //! others are discarded. If this flag is absent, the MAC address is ignored. -//! - \b EMAC_TS_UPDATE_FINE implements the fine update method that causes the +//! - \b EMAC_TS_UPDATE_FINE implements the fine update method that causes the //! IEEE 1588 clock to advance by the the value returned in the //! \e *pui32SubSecondInc parameter each time a carry is generated from the //! addend accumulator register. If this flag is absent, the coarse update @@ -3689,7 +3689,7 @@ EMACTimestampTargetIntDisable(uint32_t ui32Base) ASSERT(ui32Base == EMAC0_BASE); // - // Clear the bit to disable the timestamp target interrupt. This bit + // Clear the bit to disable the timestamp target interrupt. This bit // clears automatically when the interrupt fires, so it only must be // disabled if you want to cancel a previously-set interrupt. // @@ -4022,7 +4022,7 @@ EMACTimestampPPSPeriodSet(uint32_t ui32Base, uint32_t ui32Period, //! (Type = 0x88A8) frames as valid VLAN-tagged frames. If absent, only //! frames with type 0x8100 are considered valid VLAN frames. //! - \b EMAC_VLAN_RX_INVERSE_MATCH causes the receiver to pass all VLAN -//! frames for which the tags do not match the supplied \e ui16Tag value. If +//! frames for which the tags do not match the supplied \e ui16Tag value. If //! this flag is absent, only tagged frames matching \e ui16Tag are passed. //! - \b EMAC_VLAN_RX_12BIT_TAG causes the receiver to compare only the //! bottom 12 bits of \e ui16Tag when performing either perfect or hash @@ -4082,7 +4082,7 @@ EMACVLANRxConfigSet(uint32_t ui32Base, uint16_t ui16Tag, uint32_t ui32Config) //! S-VLAN (Type = 0x88A8) frames as valid VLAN-tagged frames. If absent, only //! frames with type 0x8100 are considered valid VLAN frames. //! - \b EMAC_VLAN_RX_INVERSE_MATCH indicates that the receiver passes all -//! VLAN frames for which the tags do not match the \e *pui16Tag value. If +//! VLAN frames for which the tags do not match the \e *pui16Tag value. If //! this flag is absent, only tagged frames matching \e *pui16Tag are passed. //! - \b EMAC_VLAN_RX_12BIT_TAG indicates that the receiver is comparing only //! the bottom 12 bits of \e *pui16Tag when performing either perfect or hash @@ -4254,7 +4254,7 @@ EMACVLANTxConfigGet(uint32_t ui32Base, uint16_t *pui16Tag) //! Returns the bit number to set in the VLAN hash filter corresponding to a //! given tag. //! -//! \param ui16Tag is the VLAN tag for which the hash filter bit number is to +//! \param ui16Tag is the VLAN tag for which the hash filter bit number is to //! be determined. //! //! This function may be used to determine which bit in the VLAN hash filter @@ -4379,8 +4379,8 @@ EMACVLANHashFilterGet(uint32_t ui32Base) //! calculated on up to 31 payload bytes in the frame. The actual bytes used //! in the CRC calculation are defined by means of a bit mask where a ``1'' //! indicates that a byte in the frame should contribute to the CRC -//! calculation and a ``0'' indicates that the byte should be skipped, as well -//! as an offset from the start of the frame to the payload byte that represents +//! calculation and a ``0'' indicates that the byte should be skipped, as well +//! as an offset from the start of the frame to the payload byte that represents //! the first byte in the 31-byte CRC-checked sequence. //! //! The \e pFilter parameter points to a structure containing the information @@ -4400,7 +4400,7 @@ EMACVLANHashFilterGet(uint32_t ui32Base) //! - \b pui8Offset defines the zero-based index of the byte within the frame //! at which CRC checking defined by \b pui32ByteMask begins. //! Alternatively, this value can be thought of as the number of bytes in the -//! frame that the MAC skips before accumulating the CRC based on the pattern +//! frame that the MAC skips before accumulating the CRC based on the pattern //! in \b pui32ByteMask. //! - \b pui16CRC provides the value of the calculated CRC for a valid remote //! wake-up frame. If the incoming frame is processed according to the filter @@ -4466,7 +4466,7 @@ EMACRemoteWakeUpFrameFilterSet(uint32_t ui32Base, //! actual bytes used in the CRC calculation are defined by means of a bit mask //! where a ``1'' indicates that a byte in the frame should contribute to the //! CRC calculation and a ``0'' indicates that the byte should be skipped, and -//! an offset from the start of the frame to the payload byte that represents +//! an offset from the start of the frame to the payload byte that represents //! the first byte in the 31-byte CRC-checked sequence. //! //! The \e pFilter parameter points to storage that is written with a @@ -4756,7 +4756,7 @@ EMACWoLEnter(uint32_t ui32Base) //! This function is used to configure the LPI timer and control registers when //! the link is established as EEE mode or when the link is lost. When the link //! is established as EEE, then \e ui16LPILSTimer is programmed as the link -//! status timer value and \e ui16LPITWTimer is programmed as the transmit wait +//! status timer value and \e ui16LPITWTimer is programmed as the transmit wait //! timer value. The parameter \e bLPIConfig is used to decide if the transmit //! path must be automated or should be under user control. //! @@ -4773,7 +4773,7 @@ EMACLPIConfig(uint32_t ui32Base, bool bLPIConfig, uint16_t ui16LPILSTimer, // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); - + ui32TimerValue = ((ui16LPILSTimer << EMAC_LPITIMERCTL_LST_S) & EMAC_LPITIMERCTL_LST_M); ui32TimerValue |= ui16LPITWTimer & EMAC_LPITIMERCTL_TWT_M; @@ -4932,7 +4932,7 @@ EMACPHYMMDWrite(uint32_t ui32Base, uint8_t ui8PhyAddr, uint16_t ui16RegAddr, // // Write the extended register value. // - EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_REGCTL, + EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_REGCTL, (0x4000 | DEV_ADDR(ui16RegAddr))); EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_REGCTL, ui16Data); } @@ -4970,7 +4970,7 @@ EMACPHYMMDRead(uint32_t ui32Base, uint8_t ui8PhyAddr, uint16_t ui16RegAddr) // // Read the extended register value. // - EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_REGCTL, + EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_REGCTL, (0x4000 | DEV_ADDR(ui16RegAddr))); return(EMACPHYRead(ui32Base, ui8PhyAddr, EPHY_ADDAR)); } diff --git a/bsp/tm4c129x/libraries/driverlib/emac.h b/bsp/tm4c129x/libraries/driverlib/emac.h index f82919c8c0..4fd0811865 100644 --- a/bsp/tm4c129x/libraries/driverlib/emac.h +++ b/bsp/tm4c129x/libraries/driverlib/emac.h @@ -3,25 +3,25 @@ // emac.h - Defines and Macros for the Ethernet module on Snowflake-class // devices. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,8 +33,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/epi.c b/bsp/tm4c129x/libraries/driverlib/epi.c index c85a02621e..43f146272c 100644 --- a/bsp/tm4c129x/libraries/driverlib/epi.c +++ b/bsp/tm4c129x/libraries/driverlib/epi.c @@ -2,25 +2,25 @@ // // epi.c - Driver for the EPI module. // -// Copyright (c) 2008-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2008-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/epi.h b/bsp/tm4c129x/libraries/driverlib/epi.h index fc26a81469..9a0a8b4d0c 100644 --- a/bsp/tm4c129x/libraries/driverlib/epi.h +++ b/bsp/tm4c129x/libraries/driverlib/epi.h @@ -2,25 +2,25 @@ // // epi.h - Prototypes and macros for the EPI module. // -// Copyright (c) 2008-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2008-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -338,7 +338,7 @@ EPIWorkaroundWordWrite(uint32_t *pui32Addr, uint32_t ui32Value) __asm { // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // NOP @@ -364,7 +364,7 @@ EPIWorkaroundWordRead(uint32_t *pui32Addr) __asm { // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // NOP @@ -392,7 +392,7 @@ EPIWorkaroundHWordWrite(uint16_t *pui16Addr, uint16_t ui16Value) __asm { // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // NOP @@ -419,7 +419,7 @@ EPIWorkaroundHWordRead(uint16_t *pui16Addr) __asm { // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // NOP @@ -447,7 +447,7 @@ EPIWorkaroundByteWrite(uint8_t *pui8Addr, uint8_t ui8Value) __asm { // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // NOP @@ -474,7 +474,7 @@ EPIWorkaroundByteRead(uint8_t *pui8Addr) __asm { // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // NOP @@ -525,7 +525,7 @@ EPIWorkaroundWordWrite(uint32_t *pui32Addr, uint32_t ui32Value) __asm volatile ( // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // " NOP\n" @@ -553,7 +553,7 @@ EPIWorkaroundWordRead(uint32_t *pui32Addr) __asm volatile( // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // " NOP\n" @@ -580,7 +580,7 @@ EPIWorkaroundHWordWrite(uint16_t *pui16Addr, uint16_t ui16Value) __asm volatile ( // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // " NOP\n" @@ -610,7 +610,7 @@ EPIWorkaroundHWordRead(uint16_t *pui16Addr) __asm volatile( // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // " NOP\n" @@ -636,7 +636,7 @@ EPIWorkaroundByteWrite(uint8_t *pui8Addr, uint8_t ui8Value) __asm volatile ( // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // " NOP\n" @@ -665,7 +665,7 @@ EPIWorkaroundByteRead(uint8_t *pui8Addr) __asm volatile( // - // Add a NOP to ensure we dont have a flash read immediately before + // Add a NOP to ensure we don抰 have a flash read immediately before // the EPI read. // " NOP\n" diff --git a/bsp/tm4c129x/libraries/driverlib/flash.c b/bsp/tm4c129x/libraries/driverlib/flash.c index 158176a766..b12887e541 100644 --- a/bsp/tm4c129x/libraries/driverlib/flash.c +++ b/bsp/tm4c129x/libraries/driverlib/flash.c @@ -2,25 +2,25 @@ // // flash.c - Driver for programming the on-chip flash. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/flash.h b/bsp/tm4c129x/libraries/driverlib/flash.h index 0d20ab1c48..c36cfc18c4 100644 --- a/bsp/tm4c129x/libraries/driverlib/flash.h +++ b/bsp/tm4c129x/libraries/driverlib/flash.h @@ -2,25 +2,25 @@ // // flash.h - Prototypes for the flash driver. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/fpu.c b/bsp/tm4c129x/libraries/driverlib/fpu.c index 8e0d793da6..027323a014 100644 --- a/bsp/tm4c129x/libraries/driverlib/fpu.c +++ b/bsp/tm4c129x/libraries/driverlib/fpu.c @@ -3,25 +3,25 @@ // fpu.c - Routines for manipulating the floating-point unit in the Cortex-M // processor. // -// Copyright (c) 2011-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2011-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,8 +33,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/fpu.h b/bsp/tm4c129x/libraries/driverlib/fpu.h index c96d69a734..3e5ec4c60f 100644 --- a/bsp/tm4c129x/libraries/driverlib/fpu.h +++ b/bsp/tm4c129x/libraries/driverlib/fpu.h @@ -2,25 +2,25 @@ // // fpu.h - Prototypes for the floatint point manipulation routines. // -// Copyright (c) 2011-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2011-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/gpio.c b/bsp/tm4c129x/libraries/driverlib/gpio.c index 5e55dd7f1c..9e186e31bd 100644 --- a/bsp/tm4c129x/libraries/driverlib/gpio.c +++ b/bsp/tm4c129x/libraries/driverlib/gpio.c @@ -2,25 +2,25 @@ // // gpio.c - API for GPIO ports // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -479,8 +479,9 @@ GPIOIntTypeGet(uint32_t ui32Port, uint8_t ui8Pin) ui32IS = HWREG(ui32Port + GPIO_O_IS); ui32IEV = HWREG(ui32Port + GPIO_O_IEV); ui32SI = HWREG(ui32Port + GPIO_O_SI); + return(((ui32IBE & ui8Pin) ? 1 : 0) | ((ui32IS & ui8Pin) ? 2 : 0) | - ((ui32IEV & ui8Pin) ? 4 : 0) | (ui32SI & 0x01) ? 0x10000 : 0); + ((ui32IEV & ui8Pin) ? 4 : 0) | ((ui32SI & 0x01) ? 0x10000 : 0)); } //***************************************************************************** @@ -573,21 +574,22 @@ GPIOPadConfigSet(uint32_t ui32Port, uint8_t ui8Pins, (ui32PinType == GPIO_PIN_TYPE_WAKE_HIGH) || (ui32PinType == GPIO_PIN_TYPE_ANALOG)); - - // - // Set the GPIO peripheral configuration register first as required. This - // register only appears in TM4E111 and later device classes, but is a - // harmless write on older devices. Walk pins 0-7 and clear or set the - // provided PC[EDMn] encoding. - // - for(ui8Bit = 0; ui8Bit < 8; ui8Bit++) + if (!(CLASS_IS_TM4C123)) { - if(ui8Pins & (1 << ui8Bit)) + // + // Set the GPIO peripheral configuration register first as required. + // This register only appears in TM4C129x devices, but is a harmless + // write on older devices. + // + for(ui8Bit = 0; ui8Bit < 8; ui8Bit++) { - HWREG(ui32Port + GPIO_O_PC) = (HWREG(ui32Port + GPIO_O_PC) & - ~(0x3 << (2 * ui8Bit))); - HWREG(ui32Port + GPIO_O_PC) |= (((ui32Strength >> 5) & 0x3) << - (2 * ui8Bit)); + if(ui8Pins & (1 << ui8Bit)) + { + HWREG(ui32Port + GPIO_O_PC) = (HWREG(ui32Port + GPIO_O_PC) & + ~(0x3 << (2 * ui8Bit))); + HWREG(ui32Port + GPIO_O_PC) |= (((ui32Strength >> 5) & 0x3) << + (2 * ui8Bit)); + } } } @@ -615,56 +617,62 @@ GPIOPadConfigSet(uint32_t ui32Port, uint8_t ui8Pins, (HWREG(ui32Port + GPIO_O_SLR) & ~(ui8Pins))); - // - // Set the 12-mA drive select register. This register only appears in - // TM4E111 and later device classes, but is a harmless write on older - // devices. - // - HWREG(ui32Port + GPIO_O_DR12R) = ((ui32Strength & 0x10) ? - (HWREG(ui32Port + GPIO_O_DR12R) | - ui8Pins) : - (HWREG(ui32Port + GPIO_O_DR12R) & - ~(ui8Pins))); + if (!(CLASS_IS_TM4C123)) + { + // + // Set the 12-mA drive select register. This register only appears in + // TM4C129x and later device classes, but is a harmless write on older + // devices. + // + HWREG(ui32Port + GPIO_O_DR12R) = ((ui32Strength & 0x10) ? + (HWREG(ui32Port + GPIO_O_DR12R) | + ui8Pins) : + (HWREG(ui32Port + GPIO_O_DR12R) & + ~(ui8Pins))); + } // // Set the pin type. // HWREG(ui32Port + GPIO_O_ODR) = ((ui32PinType & 1) ? - (HWREG(ui32Port + GPIO_O_ODR) | ui8Pins) : - (HWREG(ui32Port + GPIO_O_ODR) & ~(ui8Pins))); + (HWREG(ui32Port + GPIO_O_ODR) | ui8Pins) : + (HWREG(ui32Port + GPIO_O_ODR) & ~(ui8Pins))); HWREG(ui32Port + GPIO_O_PUR) = ((ui32PinType & 2) ? - (HWREG(ui32Port + GPIO_O_PUR) | ui8Pins) : - (HWREG(ui32Port + GPIO_O_PUR) & ~(ui8Pins))); + (HWREG(ui32Port + GPIO_O_PUR) | ui8Pins) : + (HWREG(ui32Port + GPIO_O_PUR) & ~(ui8Pins))); HWREG(ui32Port + GPIO_O_PDR) = ((ui32PinType & 4) ? - (HWREG(ui32Port + GPIO_O_PDR) | ui8Pins) : - (HWREG(ui32Port + GPIO_O_PDR) & ~(ui8Pins))); + (HWREG(ui32Port + GPIO_O_PDR) | ui8Pins) : + (HWREG(ui32Port + GPIO_O_PDR) & ~(ui8Pins))); HWREG(ui32Port + GPIO_O_DEN) = ((ui32PinType & 8) ? - (HWREG(ui32Port + GPIO_O_DEN) | ui8Pins) : - (HWREG(ui32Port + GPIO_O_DEN) & ~(ui8Pins))); + (HWREG(ui32Port + GPIO_O_DEN) | ui8Pins) : + (HWREG(ui32Port + GPIO_O_DEN) & ~(ui8Pins))); - // - // Set the wake pin enable register and the wake level register. These - // registers only appear in TM4E111 and later device classes, but are - // harmless writes on older devices. - // - HWREG(ui32Port + GPIO_O_WAKELVL) = ((ui32PinType & 0x200) ? - (HWREG(ui32Port + GPIO_O_WAKELVL) | - ui8Pins) : - (HWREG(ui32Port + GPIO_O_WAKELVL) & - ~(ui8Pins))); - HWREG(ui32Port + GPIO_O_WAKEPEN) = ((ui32PinType & 0x300) ? - (HWREG(ui32Port + GPIO_O_WAKEPEN) | - ui8Pins) : - (HWREG(ui32Port + GPIO_O_WAKEPEN) & - ~(ui8Pins))); + if (!(CLASS_IS_TM4C123)) + { + // + // Set the wake pin enable register and the wake level register. These + // registers only appear in TM4C129x and later device classes, but are + // harmless writes on older devices. + // + HWREG(ui32Port + GPIO_O_WAKELVL) = ((ui32PinType & 0x200) ? + (HWREG(ui32Port + GPIO_O_WAKELVL) | + ui8Pins) : + (HWREG(ui32Port + GPIO_O_WAKELVL) & + ~(ui8Pins))); + HWREG(ui32Port + GPIO_O_WAKEPEN) = ((ui32PinType & 0x300) ? + (HWREG(ui32Port + GPIO_O_WAKEPEN) | + ui8Pins) : + (HWREG(ui32Port + GPIO_O_WAKEPEN) & + ~(ui8Pins))); + } // // Set the analog mode select register. // HWREG(ui32Port + GPIO_O_AMSEL) = - ((ui32PinType == GPIO_PIN_TYPE_ANALOG) ? - (HWREG(ui32Port + GPIO_O_AMSEL) | ui8Pins) : - (HWREG(ui32Port + GPIO_O_AMSEL) & ~(ui8Pins))); + ((ui32PinType == GPIO_PIN_TYPE_ANALOG) ? + (HWREG(ui32Port + GPIO_O_AMSEL) | ui8Pins) : + (HWREG(ui32Port + GPIO_O_AMSEL) & ~(ui8Pins))); } //***************************************************************************** @@ -710,9 +718,12 @@ GPIOPadConfigGet(uint32_t ui32Port, uint8_t ui8Pin, ui32Strength |= ((HWREG(ui32Port + GPIO_O_DR4R) & ui8Pin) ? 2 : 0); ui32Strength |= ((HWREG(ui32Port + GPIO_O_DR8R) & ui8Pin) ? 4 : 0); ui32Strength |= ((HWREG(ui32Port + GPIO_O_SLR) & ui8Pin) ? 8 : 0); - ui32Strength |= ((HWREG(ui32Port + GPIO_O_DR12R) & ui8Pin) ? 0x10 : 0); - ui32Strength |= (((HWREG(ui32Port + GPIO_O_PC) >> - (2 * ui8Pin)) & 0x3) << 5); + if (!(CLASS_IS_TM4C123)) + { + ui32Strength |= ((HWREG(ui32Port + GPIO_O_DR12R) & ui8Pin) ? 0x10 : 0); + ui32Strength |= (((HWREG(ui32Port + GPIO_O_PC) >> + (2 * ui8Pin)) & 0x3) << 5); + } *pui32Strength = ui32Strength; // @@ -722,10 +733,13 @@ GPIOPadConfigGet(uint32_t ui32Port, uint8_t ui8Pin, ui32PinType |= ((HWREG(ui32Port + GPIO_O_PUR) & ui8Pin) ? 2 : 0); ui32PinType |= ((HWREG(ui32Port + GPIO_O_PDR) & ui8Pin) ? 4 : 0); ui32PinType |= ((HWREG(ui32Port + GPIO_O_DEN) & ui8Pin) ? 8 : 0); - if(HWREG(ui32Port + GPIO_O_WAKEPEN) & ui8Pin) + if (!(CLASS_IS_TM4C123)) { - ui32PinType |= ((HWREG(ui32Port + GPIO_O_WAKELVL) & ui8Pin) ? - 0x200 : 0x100); + if(HWREG(ui32Port + GPIO_O_WAKEPEN) & ui8Pin) + { + ui32PinType |= ((HWREG(ui32Port + GPIO_O_WAKELVL) & ui8Pin) ? + 0x200 : 0x100); + } } *pui32PinType = ui32PinType; } @@ -2614,6 +2628,41 @@ GPIOADCTriggerDisable(uint32_t ui32Port, uint8_t ui8Pins) HWREG(ui32Port + GPIO_O_ADCCTL) &= (~ui8Pins); } +//***************************************************************************** +// +//! Unlocks a GPIO pin which had been previously locked. +//! +//! \param ui32Port is the base address of the GPIO port. +//! \param ui8Pins is the bit-packed representation of the pin(s). +//! +//! This function is used to unlock pins which were locked for specific +//! functionality such as JTAG operation. To be able to use pins which have +//! been locked, the following procedure is required to unlock the pin and +//! commit the change. This function will have no effect on pins which are +//! not protected by the GPIOCR register. +//! +//! \return None. +// +//***************************************************************************** +void +GPIOUnlockPin(uint32_t ui32Port, uint8_t ui8Pins) +{ + // + // Check the arguments. + // + ASSERT(_GPIOBaseValid(ui32Port)); + + // + // Unlock the port by using the device LOCK key + // + HWREG(ui32Port + GPIO_O_LOCK) = GPIO_LOCK_KEY; + + // + // Commit the pin to keep it in GPIO mode + // + HWREG(ui32Port + GPIO_O_CR) |= ui8Pins; +} + //***************************************************************************** // // Close the Doxygen group. diff --git a/bsp/tm4c129x/libraries/driverlib/gpio.h b/bsp/tm4c129x/libraries/driverlib/gpio.h index 47b0dd71b4..fc7e54278f 100644 --- a/bsp/tm4c129x/libraries/driverlib/gpio.h +++ b/bsp/tm4c129x/libraries/driverlib/gpio.h @@ -2,25 +2,25 @@ // // gpio.h - Defines and Macros for GPIO API. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -191,6 +191,7 @@ extern void GPIODMATriggerEnable(uint32_t ui32Port, uint8_t ui8Pins); extern void GPIODMATriggerDisable(uint32_t ui32Port, uint8_t ui8Pins); extern void GPIOADCTriggerEnable(uint32_t ui32Port, uint8_t ui8Pins); extern void GPIOADCTriggerDisable(uint32_t ui32Port, uint8_t ui8Pins); +extern void GPIOUnlockPin(uint32_t ui32Port, uint8_t ui8Pins); //***************************************************************************** // diff --git a/bsp/tm4c129x/libraries/driverlib/hibernate.c b/bsp/tm4c129x/libraries/driverlib/hibernate.c index a371578387..8cb6ba5eca 100644 --- a/bsp/tm4c129x/libraries/driverlib/hibernate.c +++ b/bsp/tm4c129x/libraries/driverlib/hibernate.c @@ -2,25 +2,25 @@ // // hibernate.c - Driver for the Hibernation module // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -128,7 +128,7 @@ _HibernateWriteComplete(void) //! the system clock is the value returned by SysCtlClockGet() for TM4C123x //! devices or the value returned by SysCtlClockFreqSet() for TM4C129x devices, //! or it can be explicitly hard coded if it is constant and known (to save the -//! code/execution overhead of a call to SysCtlClockGet() or fetch of the +//! code/execution overhead of a call to SysCtlClockGet() or fetch of the //! variable call holding the return value of SysCtlClockFreqSet()). //! //! \return None. @@ -272,8 +272,7 @@ HibernateClockConfig(uint32_t ui32Config) // if(HIBERNATE_CLOCK_OUTPUT) { - HWREG(HIB_CC) = ui32Config & (HIBERNATE_OUT_SYSCLK | - HIBERNATE_OUT_ALT1CLK); + HWREG(HIB_CC) = ui32Config & (HIBERNATE_OUT_SYSCLK); } } @@ -1615,6 +1614,12 @@ _HibernateCalendarSet(uint32_t ui32Reg, struct tm *psTime) //! the hibernate counter is configured in calendar mode using the //! HibernateCounterMode() function with one of the calendar modes. //! +//! The hibernate module contains a 7-bit register field to store the year with +//! valid values ranges from 0 to 99. In order to maximize the calendar +//! year up to 2099, the HibernateCalendarSet() will accept calendar year +//! after the year 2000 only. Calendar years before 2000 (i.e. 1987) will +//! produce unexpected results. +//! //! \note The hibernate calendar mode is not available on all Tiva //! devices. Please consult the data sheet to determine if the device you are //! using supports this feature in the Hibernation module. diff --git a/bsp/tm4c129x/libraries/driverlib/hibernate.h b/bsp/tm4c129x/libraries/driverlib/hibernate.h index 80633b950c..b8082d86c1 100644 --- a/bsp/tm4c129x/libraries/driverlib/hibernate.h +++ b/bsp/tm4c129x/libraries/driverlib/hibernate.h @@ -2,25 +2,25 @@ // // hibernate.h - API definition for the Hibernation module. // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -104,7 +104,6 @@ extern "C" #define HIBERNATE_OSC_DISABLE 0x00010000 #define HIBERNATE_OUT_WRSTALL 0x20000000 #define HIBERNATE_OUT_SYSCLK 0x00000001 -#define HIBERNATE_OUT_ALT1CLK 0x00000002 //***************************************************************************** // diff --git a/bsp/tm4c129x/libraries/driverlib/i2c.c b/bsp/tm4c129x/libraries/driverlib/i2c.c index 37aa1d764b..f8da84cce4 100644 --- a/bsp/tm4c129x/libraries/driverlib/i2c.c +++ b/bsp/tm4c129x/libraries/driverlib/i2c.c @@ -2,25 +2,25 @@ // // i2c.c - Driver for Inter-IC (I2C) bus block. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -194,7 +194,7 @@ _I2CIntNumberGet(uint32_t ui32Base) //! the system clock is the value returned by SysCtlClockGet() for TM4C123x //! devices or the value returned by SysCtlClockFreqSet() for TM4C129x devices, //! or it can be explicitly hard coded if it is constant and known (to save the -//! code/execution overhead of a call to SysCtlClockGet() or fetch of the +//! code/execution overhead of a call to SysCtlClockGet() or fetch of the //! variable call holding the return value of SysCtlClockFreqSet()). //! //! \return None. @@ -1782,7 +1782,7 @@ I2CRxFIFOFlush(uint32_t ui32Base) //! //! This function retrieves the status for both the transmit (TX) and receive //! (RX) FIFOs. The trigger level for the transmit FIFO is set using -//! I2CTxFIFOConfigSet() and for the receive FIFO using I2CTxFIFOConfigSet(). +//! I2CTxFIFOConfigSet() and for the receive FIFO using I2CRxFIFOConfigSet(). //! //! \note Not all Tiva devices have an I2C FIFO. Please consult the //! device data sheet to determine if this feature is supported. diff --git a/bsp/tm4c129x/libraries/driverlib/i2c.h b/bsp/tm4c129x/libraries/driverlib/i2c.h index ab7b44e4fe..709930af08 100644 --- a/bsp/tm4c129x/libraries/driverlib/i2c.h +++ b/bsp/tm4c129x/libraries/driverlib/i2c.h @@ -2,25 +2,25 @@ // // i2c.h - Prototypes for the I2C Driver. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/interrupt.c b/bsp/tm4c129x/libraries/driverlib/interrupt.c index ebf5f95bd3..12d9686ebe 100644 --- a/bsp/tm4c129x/libraries/driverlib/interrupt.c +++ b/bsp/tm4c129x/libraries/driverlib/interrupt.c @@ -2,25 +2,25 @@ // // interrupt.c - Driver for the NVIC Interrupt Controller. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/interrupt.h b/bsp/tm4c129x/libraries/driverlib/interrupt.h index effb30c88a..79d457ead2 100644 --- a/bsp/tm4c129x/libraries/driverlib/interrupt.h +++ b/bsp/tm4c129x/libraries/driverlib/interrupt.h @@ -2,25 +2,25 @@ // // interrupt.h - Prototypes for the NVIC Interrupt Controller Driver. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/lcd.c b/bsp/tm4c129x/libraries/driverlib/lcd.c index 195d0ef0ba..e14340463a 100644 --- a/bsp/tm4c129x/libraries/driverlib/lcd.c +++ b/bsp/tm4c129x/libraries/driverlib/lcd.c @@ -2,25 +2,25 @@ // // lcd.c - Defines and Macros for the LCD Controller module. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/lcd.h b/bsp/tm4c129x/libraries/driverlib/lcd.h index 766cf94361..1df72f19cf 100644 --- a/bsp/tm4c129x/libraries/driverlib/lcd.h +++ b/bsp/tm4c129x/libraries/driverlib/lcd.h @@ -2,25 +2,25 @@ // // lcd.h - Defines and Macros for the LCD Controller module. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/mpu.c b/bsp/tm4c129x/libraries/driverlib/mpu.c index 4d01f1b403..42c093e964 100644 --- a/bsp/tm4c129x/libraries/driverlib/mpu.c +++ b/bsp/tm4c129x/libraries/driverlib/mpu.c @@ -2,25 +2,25 @@ // // mpu.c - Driver for the Cortex-M3 memory protection unit (MPU). // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/mpu.h b/bsp/tm4c129x/libraries/driverlib/mpu.h index 9c8377f8ce..5fa8ad3645 100644 --- a/bsp/tm4c129x/libraries/driverlib/mpu.h +++ b/bsp/tm4c129x/libraries/driverlib/mpu.h @@ -2,25 +2,25 @@ // // mpu.h - Defines and Macros for the memory protection unit. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/onewire.c b/bsp/tm4c129x/libraries/driverlib/onewire.c index 24d671f125..09f8ef1e66 100644 --- a/bsp/tm4c129x/libraries/driverlib/onewire.c +++ b/bsp/tm4c129x/libraries/driverlib/onewire.c @@ -2,25 +2,25 @@ // // onewire.c - Driver for OneWire master module. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/onewire.h b/bsp/tm4c129x/libraries/driverlib/onewire.h index 731f3f99bb..f2ba6e70e6 100644 --- a/bsp/tm4c129x/libraries/driverlib/onewire.h +++ b/bsp/tm4c129x/libraries/driverlib/onewire.h @@ -2,25 +2,25 @@ // // onewire.h - Prototypes for the OneWire Driver. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/pin_map.h b/bsp/tm4c129x/libraries/driverlib/pin_map.h index 9d68609861..8f8f9dee1b 100644 --- a/bsp/tm4c129x/libraries/driverlib/pin_map.h +++ b/bsp/tm4c129x/libraries/driverlib/pin_map.h @@ -2,25 +2,25 @@ // // pin_map.h - Mapping of peripherals to pins for all parts. // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/pwm.c b/bsp/tm4c129x/libraries/driverlib/pwm.c index 54fbe52e5c..fdbec4e959 100644 --- a/bsp/tm4c129x/libraries/driverlib/pwm.c +++ b/bsp/tm4c129x/libraries/driverlib/pwm.c @@ -2,25 +2,25 @@ // // pwm.c - API for the PWM modules // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -1624,11 +1624,11 @@ PWMIntStatus(uint32_t ui32Base, bool bMasked) //! \e ui32FaultInts must be the logical OR of any of \b PWM_INT_FAULT0, //! \b PWM_INT_FAULT1, \b PWM_INT_FAULT2, or \b PWM_INT_FAULT3. //! -//! The fault interrupts are derived by performing a logical OR of each of the +//! The fault interrupts are derived by performing a logical OR of each of the //! configured fault trigger signals for a given generator. Therefore, these -//! interrupts are not directly related to the four possible FAULTn inputs to -//! the device but indicate that a fault has been signaled to one of the four -//! possible PWM generators. +//! interrupts are not directly related to the four possible FAULTn inputs to +//! the device but indicate that a fault has been signaled to one of the four +//! possible PWM generators. //! //! \note Because there is a write buffer in the Cortex-M processor, it may //! take several clock cycles before the interrupt source is actually cleared. @@ -1993,7 +1993,8 @@ PWMClockSet(uint32_t ui32Base, uint32_t ui32Config) // Check the arguments. // ASSERT((ui32Base == PWM0_BASE) || (ui32Base == PWM1_BASE)); - ASSERT((ui32Config == PWM_SYSCLK_DIV_2) || + ASSERT((ui32Config == PWM_SYSCLK_DIV_1) || + (ui32Config == PWM_SYSCLK_DIV_2) || (ui32Config == PWM_SYSCLK_DIV_4) || (ui32Config == PWM_SYSCLK_DIV_8) || (ui32Config == PWM_SYSCLK_DIV_16) || diff --git a/bsp/tm4c129x/libraries/driverlib/pwm.h b/bsp/tm4c129x/libraries/driverlib/pwm.h index c18d98acb2..e11cd4be3c 100644 --- a/bsp/tm4c129x/libraries/driverlib/pwm.h +++ b/bsp/tm4c129x/libraries/driverlib/pwm.h @@ -2,25 +2,25 @@ // // pwm.h - API function protoypes for Pulse Width Modulation (PWM) ports // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/qei.c b/bsp/tm4c129x/libraries/driverlib/qei.c index b4def78493..a1b0f03e61 100644 --- a/bsp/tm4c129x/libraries/driverlib/qei.c +++ b/bsp/tm4c129x/libraries/driverlib/qei.c @@ -2,25 +2,25 @@ // // qei.c - Driver for the Quadrature Encoder with Index. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/qei.h b/bsp/tm4c129x/libraries/driverlib/qei.h index 031897ae31..4b8794d8dd 100644 --- a/bsp/tm4c129x/libraries/driverlib/qei.h +++ b/bsp/tm4c129x/libraries/driverlib/qei.h @@ -2,25 +2,25 @@ // // qei.h - Prototypes for the Quadrature Encoder Driver. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/readme.txt b/bsp/tm4c129x/libraries/driverlib/readme.txt index 1f90c23656..482941f98b 100644 --- a/bsp/tm4c129x/libraries/driverlib/readme.txt +++ b/bsp/tm4c129x/libraries/driverlib/readme.txt @@ -2,7 +2,7 @@ This project will build the TivaWare Peripheral Driver Library. ------------------------------------------------------------------------------- -Copyright (c) 2006-2017 Texas Instruments Incorporated. All rights reserved. +Copyright (c) 2006-2020 Texas Instruments Incorporated. All rights reserved. Software License Agreement Redistribution and use in source and binary forms, with or without @@ -14,7 +14,7 @@ Software License Agreement Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the + documentation and/or other materials provided with the distribution. Neither the name of Texas Instruments Incorporated nor the names of @@ -33,4 +33,4 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. diff --git a/bsp/tm4c129x/libraries/driverlib/rom.h b/bsp/tm4c129x/libraries/driverlib/rom.h index 2ffdab87e5..1997e841fa 100644 --- a/bsp/tm4c129x/libraries/driverlib/rom.h +++ b/bsp/tm4c129x/libraries/driverlib/rom.h @@ -2,25 +2,25 @@ // // rom.h - Macros to facilitate calling functions in the ROM. // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/rom_map.h b/bsp/tm4c129x/libraries/driverlib/rom_map.h index e45ede445f..2a2ea9d3fd 100644 --- a/bsp/tm4c129x/libraries/driverlib/rom_map.h +++ b/bsp/tm4c129x/libraries/driverlib/rom_map.h @@ -3,25 +3,25 @@ // rom_map.h - Macros to facilitate calling functions in the ROM when they are // available and in flash otherwise. // -// Copyright (c) 2008-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2008-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,8 +33,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -1703,6 +1703,20 @@ #define MAP_FlashUserSet \ FlashUserSet #endif +#ifdef ROM_FlashAllUserRegisterGet +#define MAP_FlashAllUserRegisterGet \ + ROM_FlashAllUserRegisterGet +#else +#define MAP_FlashAllUserRegisterGet \ + FlashAllUserRegisterGet +#endif +#ifdef ROM_FlashAllUserRegisterSet +#define MAP_FlashAllUserRegisterSet \ + ROM_FlashAllUserRegisterSet +#else +#define MAP_FlashAllUserRegisterSet \ + FlashAllUserRegisterSet +#endif #ifdef ROM_FlashUserSave #define MAP_FlashUserSave \ ROM_FlashUserSave @@ -1710,6 +1724,13 @@ #define MAP_FlashUserSave \ FlashUserSave #endif +#ifdef ROM_FlashAllUserRegisterSave +#define MAP_FlashAllUserRegisterSave \ + ROM_FlashAllUserRegisterSave +#else +#define MAP_FlashAllUserRegisterSave \ + FlashAllUserRegisterSave +#endif #ifdef ROM_FlashIntEnable #define MAP_FlashIntEnable \ ROM_FlashIntEnable @@ -1883,6 +1904,41 @@ #define MAP_GPIOPinTypeComparator \ GPIOPinTypeComparator #endif +#ifdef ROM_GPIOPinTypeComparatorOutput +#define MAP_GPIOPinTypeComparatorOutput \ + ROM_GPIOPinTypeComparatorOutput +#else +#define MAP_GPIOPinTypeComparatorOutput \ + GPIOPinTypeComparatorOutput +#endif +#ifdef ROM_GPIOPinTypeDIVSCLK +#define MAP_GPIOPinTypeDIVSCLK \ + ROM_GPIOPinTypeDIVSCLK +#else +#define MAP_GPIOPinTypeDIVSCLK \ + GPIOPinTypeDIVSCLK +#endif +#ifdef ROM_GPIOPinTypeEPI +#define MAP_GPIOPinTypeEPI \ + ROM_GPIOPinTypeEPI +#else +#define MAP_GPIOPinTypeEPI \ + GPIOPinTypeEPI +#endif +#ifdef ROM_GPIOPinTypeEthernetLED +#define MAP_GPIOPinTypeEthernetLED \ + ROM_GPIOPinTypeEthernetLED +#else +#define MAP_GPIOPinTypeEthernetLED \ + GPIOPinTypeEthernetLED +#endif +#ifdef ROM_GPIOPinTypeEthernetMII +#define MAP_GPIOPinTypeEthernetMII \ + ROM_GPIOPinTypeEthernetMII +#else +#define MAP_GPIOPinTypeEthernetMII \ + GPIOPinTypeEthernetMII +#endif #ifdef ROM_GPIOPinTypeGPIOInput #define MAP_GPIOPinTypeGPIOInput \ ROM_GPIOPinTypeGPIOInput @@ -1897,6 +1953,13 @@ #define MAP_GPIOPinTypeGPIOOutput \ GPIOPinTypeGPIOOutput #endif +#ifdef ROM_GPIOPinTypeHibernateRTCCLK +#define MAP_GPIOPinTypeHibernateRTCCLK \ + ROM_GPIOPinTypeHibernateRTCCLK +#else +#define MAP_GPIOPinTypeHibernateRTCCLK \ + GPIOPinTypeHibernateRTCCLK +#endif #ifdef ROM_GPIOPinTypeI2C #define MAP_GPIOPinTypeI2C \ ROM_GPIOPinTypeI2C @@ -1932,6 +1995,13 @@ #define MAP_GPIOPinTypeTimer \ GPIOPinTypeTimer #endif +#ifdef ROM_GPIOPinTypeTrace +#define MAP_GPIOPinTypeTrace \ + ROM_GPIOPinTypeTrace +#else +#define MAP_GPIOPinTypeTrace \ + GPIOPinTypeTrace +#endif #ifdef ROM_GPIOPinTypeUART #define MAP_GPIOPinTypeUART \ ROM_GPIOPinTypeUART @@ -2058,6 +2128,34 @@ #define MAP_GPIOIntStatus \ GPIOIntStatus #endif +#ifdef ROM_GPIOIntRegister +#define MAP_GPIOIntRegiste \ + ROM_GPIOIntRegister +#else +#define MAP_GPIOIntRegister \ + GPIOIntRegister +#endif +#ifdef ROM_GPIOIntUnregister +#define MAP_GPIOIntUnregister \ + ROM_GPIOIntUnregister +#else +#define MAP_GPIOIntUnregister \ + GPIOIntUnregister +#endif +#ifdef ROM_GPIOIntRegisterPin +#define MAP_GPIOIntRegisterPin \ + ROM_GPIOIntRegisterPin +#else +#define MAP_GPIOIntRegisterPin \ + GPIOIntRegisterPin +#endif +#ifdef ROM_GPIOIntUnregisterPin +#define MAP_GPIOIntUnregisterPin \ + ROM_GPIOIntUnregisterPin +#else +#define MAP_GPIOIntUnregisterPin \ + GPIOIntUnregisterPin +#endif #ifdef ROM_GPIOPinWakeStatus #define MAP_GPIOPinWakeStatus \ ROM_GPIOPinWakeStatus @@ -2065,6 +2163,13 @@ #define MAP_GPIOPinWakeStatus \ GPIOPinWakeStatus #endif +#ifdef ROM_GPIOUnlockPin +#define MAP_GPIOUnlockPin \ + ROM_GPIOUnlockPin +#else +#define MAP_GPIOUnlockPin \ + GPIOUnlockPin +#endif //***************************************************************************** // @@ -2756,6 +2861,13 @@ #define MAP_I2CMasterGlitchFilterConfigSet \ I2CMasterGlitchFilterConfigSet #endif +#ifdef ROM_I2CLoopbackEnable +#define MAP_I2CLoopbackEnable \ + ROM_I2CLoopbackEnable +#else +#define MAP_I2CLoopbackEnable \ + I2CLoopbackEnable +#endif //***************************************************************************** // @@ -3492,6 +3604,27 @@ #define MAP_QEIErrorGet \ QEIErrorGet #endif +#ifdef ROM_QEIFilterEnable +#define MAP_QEIFilterEnable \ + ROM_QEIFilterEnable +#else +#define MAP_QEIFilterEnable \ + QEIFilterEnable +#endif +#ifdef ROM_QEIFilterDisable +#define MAP_QEIFilterDisable \ + ROM_QEIFilterDisable +#else +#define MAP_QEIFilterDisable \ + QEIFilterDisable +#endif +#ifdef ROM_QEIFilterConfigure +#define MAP_QEIFilterConfigure \ + ROM_QEIFilterConfigure +#else +#define MAP_QEIFilterConfigure \ + QEIFilterConfigure +#endif #ifdef ROM_QEIVelocityEnable #define MAP_QEIVelocityEnable \ ROM_QEIVelocityEnable @@ -4405,6 +4538,20 @@ #define MAP_SSIAdvFrameHoldDisable \ SSIAdvFrameHoldDisable #endif +#ifdef ROM_SSILoopbackEnable +#define MAP_SSILoopbackEnable \ + ROM_SSILoopbackEnable +#else +#define MAP_SSILoopbackEnable \ + SSILoopbackEnable +#endif +#ifdef ROM_SSILoopbackDisable +#define MAP_SSILoopbackDisable \ + ROM_SSILoopbackDisable +#else +#define MAP_SSILoopbackDisable \ + SSILoopbackDisable +#endif //***************************************************************************** // @@ -4726,6 +4873,13 @@ #define MAP_SysCtlAltClkConfig \ SysCtlAltClkConfig #endif +#ifdef ROM_SysCtlVCOGet +#define MAP_SysCtlVCOGet \ + ROM_SysCtlVCOGet +#else +#define MAP_SysCtlVCOGet \ + SysCtlVCOGet +#endif //***************************************************************************** // @@ -5066,6 +5220,13 @@ #define MAP_TimerSynchronize \ TimerSynchronize #endif +#ifdef ROM_TimerUpdateMode +#define MAP_TimerUpdateMode \ + ROM_TimerUpdateMode +#else +#define MAP_TimerUpdateMode \ + TimerUpdateMode +#endif //***************************************************************************** // @@ -5380,6 +5541,13 @@ #define MAP_UARTFlowControlSet \ UARTFlowControlSet #endif +#ifdef ROM_UARTLoopbackEnable +#define MAP_UARTLoopbackEnable \ + ROM_UARTLoopbackEnable +#else +#define MAP_UARTLoopbackEnable \ + UARTLoopbackEnable +#endif //***************************************************************************** // diff --git a/bsp/tm4c129x/libraries/driverlib/rtos_bindings.h b/bsp/tm4c129x/libraries/driverlib/rtos_bindings.h index 90762502c0..71c0cfaceb 100644 --- a/bsp/tm4c129x/libraries/driverlib/rtos_bindings.h +++ b/bsp/tm4c129x/libraries/driverlib/rtos_bindings.h @@ -3,25 +3,25 @@ // rtos_bindings.h - Macros intended to aid porting of TivaWare modules // for use with an RTOS. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,8 +33,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/shamd5.c b/bsp/tm4c129x/libraries/driverlib/shamd5.c index d748ac4bb5..e399699001 100644 --- a/bsp/tm4c129x/libraries/driverlib/shamd5.c +++ b/bsp/tm4c129x/libraries/driverlib/shamd5.c @@ -2,25 +2,25 @@ // // shamd5.c - Driver for the SHA/MD5 module. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/shamd5.h b/bsp/tm4c129x/libraries/driverlib/shamd5.h index 3b0e793b4f..b2b3cd0dbc 100644 --- a/bsp/tm4c129x/libraries/driverlib/shamd5.h +++ b/bsp/tm4c129x/libraries/driverlib/shamd5.h @@ -2,25 +2,25 @@ // // shamd5.h - Defines and Macros for the SHA/MD5. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/ssi.c b/bsp/tm4c129x/libraries/driverlib/ssi.c index cf7a2d3bc2..db200db903 100644 --- a/bsp/tm4c129x/libraries/driverlib/ssi.c +++ b/bsp/tm4c129x/libraries/driverlib/ssi.c @@ -2,25 +2,25 @@ // // ssi.c - Driver for Synchronous Serial Interface. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -176,9 +176,9 @@ _SSIIntNumberGet(uint32_t ui32Base) //! The \e ui32Protocol parameter defines the data frame format. The //! \e ui32Protocol parameter can be one of the following values: //! \b SSI_FRF_MOTO_MODE_0, \b SSI_FRF_MOTO_MODE_1, \b SSI_FRF_MOTO_MODE_2, -//! \b SSI_FRF_MOTO_MODE_3, \b SSI_FRF_TI, or \b SSI_FRF_NMW. Note that +//! \b SSI_FRF_MOTO_MODE_3, \b SSI_FRF_TI, or \b SSI_FRF_NMW. Note that //! the \b SSI_FRF_NMW option is only available on some devices. Refer to the -//! device data sheet to determine if the Microwire format is supported on +//! device data sheet to determine if the Microwire format is supported on //! a particular device. The Motorola frame formats encode the following //! polarity and phase configurations: //! @@ -213,7 +213,7 @@ _SSIIntNumberGet(uint32_t ui32Base) //! the system clock is the value returned by SysCtlClockGet() for TM4C123x //! devices or the value returned by SysCtlClockFreqSet() for TM4C129x devices, //! or it can be explicitly hard coded if it is constant and known (to save the -//! code/execution overhead of a call to SysCtlClockGet() or fetch of the +//! code/execution overhead of a call to SysCtlClockGet() or fetch of the //! variable call holding the return value of SysCtlClockFreqSet()). //! //! \return None. @@ -692,10 +692,10 @@ SSIDataGet(uint32_t ui32Base, uint32_t *pui32Data) //! \param pui32Data is a pointer to a storage location for data that was //! received over the SSI interface. //! -//! This function gets received data from the receive FIFO of the specified SSI -//! module and places that data into the location specified by the \e ui32Data -//! parameter. If there is no data in the FIFO, then this function returns a -//! zero. +//! This function gets one received data element from the receive FIFO of the +//! specified SSI module and places that data into the location specified by +//! the \e ui32Data parameter. If there is no data in the FIFO, then this +//! function returns a zero. //! //! \note Only the lower N bits of the value written to \e pui32Data contain //! valid data, where N is the data width as configured by @@ -703,7 +703,7 @@ SSIDataGet(uint32_t ui32Base, uint32_t *pui32Data) //! 8-bit data width, only the lower 8 bits of the value written to //! \e pui32Data contain valid data. //! -//! \return Returns the number of elements read from the SSI receive FIFO. +//! \return Returns 1 if there is data element read or 0 if no data in FIFO // //***************************************************************************** int32_t @@ -1013,7 +1013,7 @@ SSIAdvDataPutFrameEnd(uint32_t ui32Base, uint32_t ui32Data) // Check the arguments. // ASSERT(_SSIBaseValid(ui32Base)); - ASSERT((ui32Data & 0xff) == 0); + ASSERT((ui32Data & 0xffffff00) == 0); // // Wait until there is space. @@ -1058,7 +1058,7 @@ SSIAdvDataPutFrameEndNonBlocking(uint32_t ui32Base, uint32_t ui32Data) // Check the arguments. // ASSERT(_SSIBaseValid(ui32Base)); - ASSERT((ui32Data & 0xff) == 0); + ASSERT((ui32Data & 0xffffff00) == 0); // // Check for space to write. @@ -1111,7 +1111,7 @@ SSIAdvFrameHoldEnable(uint32_t ui32Base) //***************************************************************************** // -//! Configures the SSI advanced mode to de-assert the SSIFss signal after every +//! Configures the SSI advanced mode to de-assert the SSIFss signal after every //! byte transfer. //! //! \param ui32Base is the base address of the SSI module. @@ -1142,6 +1142,61 @@ SSIAdvFrameHoldDisable(uint32_t ui32Base) HWREG(ui32Base + SSI_O_CR1) &= ~(SSI_CR1_FSSHLDFRM); } +//***************************************************************************** +// +//! Enables the use of SSI Loopback mode. +//! +//! \param ui32Base is the base address of the SSI module. +//! +//! This function configures the SSI module to enter loopback mode. When in +//! loopback mode, the output of the transmit serial shift register is +//! connected internally to the input of the receive serial shift register. +//! This mode is useful for diagnostic/debug testing of the SSI module. +//! +//! \return None. +// +//***************************************************************************** +void +SSILoopbackEnable(uint32_t ui32Base) +{ + // + // Check the arguments. + // + ASSERT(_SSIBaseValid(ui32Base)); + + // + // Enable Loopback mode + // + HWREG(ui32Base + SSI_O_CR1) |= 1u; +} + +//***************************************************************************** +// +//! Disables the use of SSI Loopback mode. +//! +//! \param ui32Base is the base address of the SSI module. +//! +//! This function restores the SSI module to be in normal serial port operation +//! where the the input of the receive serial shift register is no longer +//! connected internally to the output of the transmit serial shift register. +//! +//! \return None. +// +//***************************************************************************** +void +SSILoopbackDisable(uint32_t ui32Base) +{ + // + // Check the arguments. + // + ASSERT(_SSIBaseValid(ui32Base)); + + // + // Disable Loopback mode + // + HWREG(ui32Base + SSI_O_CR1) &= ~(1u); +} + //***************************************************************************** // // Close the Doxygen group. diff --git a/bsp/tm4c129x/libraries/driverlib/ssi.h b/bsp/tm4c129x/libraries/driverlib/ssi.h index 37d928dd1b..64c18b0a17 100644 --- a/bsp/tm4c129x/libraries/driverlib/ssi.h +++ b/bsp/tm4c129x/libraries/driverlib/ssi.h @@ -2,25 +2,25 @@ // // ssi.h - Prototypes for the Synchronous Serial Interface Driver. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -144,6 +144,8 @@ extern int32_t SSIAdvDataPutFrameEndNonBlocking(uint32_t ui32Base, uint32_t ui32Data); extern void SSIAdvFrameHoldEnable(uint32_t ui32Base); extern void SSIAdvFrameHoldDisable(uint32_t ui32Base); +extern void SSILoopbackEnable(uint32_t ui32Base); +extern void SSILoopbackDisable(uint32_t ui32Base); //***************************************************************************** // diff --git a/bsp/tm4c129x/libraries/driverlib/sw_crc.c b/bsp/tm4c129x/libraries/driverlib/sw_crc.c index 0706c34d50..fc48a53740 100644 --- a/bsp/tm4c129x/libraries/driverlib/sw_crc.c +++ b/bsp/tm4c129x/libraries/driverlib/sw_crc.c @@ -2,25 +2,25 @@ // // sw_crc.c - Software CRC functions. // -// Copyright (c) 2010-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2010-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/sw_crc.h b/bsp/tm4c129x/libraries/driverlib/sw_crc.h index 0e60775ffc..c3d319d7c5 100644 --- a/bsp/tm4c129x/libraries/driverlib/sw_crc.h +++ b/bsp/tm4c129x/libraries/driverlib/sw_crc.h @@ -2,25 +2,25 @@ // // sw_crc.h - Prototypes for the software CRC functions. // -// Copyright (c) 2010-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2010-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/sysctl.c b/bsp/tm4c129x/libraries/driverlib/sysctl.c index 161b5fa6d7..2cf594a167 100644 --- a/bsp/tm4c129x/libraries/driverlib/sysctl.c +++ b/bsp/tm4c129x/libraries/driverlib/sysctl.c @@ -2,25 +2,25 @@ // // sysctl.c - Driver for the system controller. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -2216,7 +2216,7 @@ SysCtlClockFreqSet(uint32_t ui32Config, uint32_t ui32SysClock) } HWREG(SYSCTL_MOSCCTL) = ui32MOSCCTL; - + // // Timeout using the legacy delay value. // @@ -2241,7 +2241,7 @@ SysCtlClockFreqSet(uint32_t ui32Config, uint32_t ui32SysClock) return(0); } - + } else { @@ -2495,8 +2495,8 @@ SysCtlClockFreqSet(uint32_t ui32Config, uint32_t ui32SysClock) //! many of which are grouped into sets where only one can be chosen. //! //! The system clock divider is chosen with one of the following values: -//! \b SYSCTL_SYSDIV_1, \b SYSCTL_SYSDIV_2, \b SYSCTL_SYSDIV_3, ... -//! \b SYSCTL_SYSDIV_64. +//! \b SYSCTL_SYSDIV_1, \b SYSCTL_SYSDIV_2, \b SYSCTL_SYSDIV_2_5, +//! \b SYSCTL_SYSDIV_3, ... \b SYSCTL_SYSDIV_63_5, \b SYSCTL_SYSDIV_64. //! //! The use of the PLL is chosen with either \b SYSCTL_USE_PLL or //! \b SYSCTL_USE_OSC. @@ -3522,8 +3522,9 @@ SysCtlVoltageEventClear(uint32_t ui32Status) // //! Gets the effective VCO frequency. //! -//! \param ui32Crystal holds the crystal value used for the PLL. -//! \param pui32VCOFrequency is a pointer to the storage location which holds +//! \param ui32Crystal holds the crystal value definition from \b sysctl.h +//! such as \b SYSCTL_XTAL_25MHZ. +//! \param pui32VCOFrequency is a pointer to the storage location which holds //! value of the VCO computed. //! //! This function calculates the VCO of the PLL before the system divider is @@ -3566,9 +3567,9 @@ SysCtlVCOGet(uint32_t ui32Crystal, uint32_t *pui32VCOFrequency) // Return error if PLL is not used. // *pui32VCOFrequency = 0; - return(false); + return(false); } - + // // Get the index of the crystal from the ui32Config parameter. // @@ -3586,13 +3587,13 @@ SysCtlVCOGet(uint32_t ui32Crystal, uint32_t *pui32VCOFrequency) ui32PLLFreq0 = HWREG(SYSCTL_PLLFREQ0); ui32PLLFreq1 = HWREG(SYSCTL_PLLFREQ1); - ui32MInt = (ui32PLLFreq0 & SYSCTL_PLLFREQ0_MINT_M) >> + ui32MInt = (ui32PLLFreq0 & SYSCTL_PLLFREQ0_MINT_M) >> SYSCTL_PLLFREQ0_MINT_S; - ui32MFrac = (ui32PLLFreq0 & SYSCTL_PLLFREQ0_MFRAC_M) >> + ui32MFrac = (ui32PLLFreq0 & SYSCTL_PLLFREQ0_MFRAC_M) >> SYSCTL_PLLFREQ0_MFRAC_S; - ui32NDiv = (ui32PLLFreq1 & SYSCTL_PLLFREQ1_N_M) >> + ui32NDiv = (ui32PLLFreq1 & SYSCTL_PLLFREQ1_N_M) >> SYSCTL_PLLFREQ1_N_S; - ui32QDiv = (ui32PLLFreq1 & SYSCTL_PLLFREQ1_Q_M) >> + ui32QDiv = (ui32PLLFreq1 & SYSCTL_PLLFREQ1_Q_M) >> SYSCTL_PLLFREQ1_Q_S; // @@ -3600,7 +3601,7 @@ SysCtlVCOGet(uint32_t ui32Crystal, uint32_t *pui32VCOFrequency) // ui32TempVCO = (ui32Osc * ui32MInt) + ((ui32Osc * ui32MFrac) / 1024); ui32TempVCO /= ((ui32NDiv + 1) * (ui32QDiv + 1)); - + *pui32VCOFrequency = ui32TempVCO; return(true); } diff --git a/bsp/tm4c129x/libraries/driverlib/sysctl.h b/bsp/tm4c129x/libraries/driverlib/sysctl.h index 0bce4852d7..1f68c46e98 100644 --- a/bsp/tm4c129x/libraries/driverlib/sysctl.h +++ b/bsp/tm4c129x/libraries/driverlib/sysctl.h @@ -2,25 +2,25 @@ // // sysctl.h - Prototypes for the system control driver. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -344,8 +344,23 @@ extern "C" #define SYSCTL_SYSDIV_61_5 0xDE800000 // Processor clock is pll / 61.5 #define SYSCTL_SYSDIV_62_5 0xDF000000 // Processor clock is pll / 62.5 #define SYSCTL_SYSDIV_63_5 0xDF800000 // Processor clock is pll / 63.5 -#define SYSCTL_CFG_VCO_480 0xF1000000 // VCO is 480 MHz -#define SYSCTL_CFG_VCO_320 0xF0000000 // VCO is 320 MHz +// +// TivaWare 2.2.0.xxx Update +// Due to TM4C129x Errata Item SYSCTL#22, the SYSCTL_CFG_VCO_xxx configurations +// have misleading *names* as currently defined as the VCO does not run at the +// stated frequencies. To amend this, new *name* defintions are being used, +// however the register configuration remains the same. +// The old definitions will remain for compatibility with code ported from +// older versions of TivaWare. +// +#define SYSCTL_CFG_VCO_480 0xF1000000 // VCO is 480 MHz - Legacy + // Does not work @ 480, use + // SYSCTL_CFG_VCO_240 instead +#define SYSCTL_CFG_VCO_320 0xF0000000 // VCO is 320 MHz - Legacy + // Does not work @ 320, use + // SYSCTL_CFG_VCO_160 instead +#define SYSCTL_CFG_VCO_240 0xF1000000 // VCO is 240 MHz +#define SYSCTL_CFG_VCO_160 0xF0000000 // VCO is 160 MHz #define SYSCTL_USE_PLL 0x00000000 // System clock is the PLL clock #define SYSCTL_USE_OSC 0x00003800 // System clock is the osc clock #define SYSCTL_XTAL_1MHZ 0x00000000 // External crystal is 1MHz diff --git a/bsp/tm4c129x/libraries/driverlib/sysexc.c b/bsp/tm4c129x/libraries/driverlib/sysexc.c index d269b74bcd..ebf4e2e3f1 100644 --- a/bsp/tm4c129x/libraries/driverlib/sysexc.c +++ b/bsp/tm4c129x/libraries/driverlib/sysexc.c @@ -2,25 +2,25 @@ // // sysexc.c - Routines for the System Exception Module. // -// Copyright (c) 2011-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2011-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/sysexc.h b/bsp/tm4c129x/libraries/driverlib/sysexc.h index aece4409d1..0dad3df2f7 100644 --- a/bsp/tm4c129x/libraries/driverlib/sysexc.h +++ b/bsp/tm4c129x/libraries/driverlib/sysexc.h @@ -2,25 +2,25 @@ // // sysexc.h - Prototypes for the System Exception Module routines. // -// Copyright (c) 2011-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2011-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/systick.c b/bsp/tm4c129x/libraries/driverlib/systick.c index 662da1729e..174e5b889e 100644 --- a/bsp/tm4c129x/libraries/driverlib/systick.c +++ b/bsp/tm4c129x/libraries/driverlib/systick.c @@ -2,25 +2,25 @@ // // systick.c - Driver for the SysTick timer in NVIC. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/systick.h b/bsp/tm4c129x/libraries/driverlib/systick.h index 35909ee3fb..4f36568ad7 100644 --- a/bsp/tm4c129x/libraries/driverlib/systick.h +++ b/bsp/tm4c129x/libraries/driverlib/systick.h @@ -2,25 +2,25 @@ // // systick.h - Prototypes for the SysTick driver. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/tiva_timer.c b/bsp/tm4c129x/libraries/driverlib/tiva_timer.c index d348849570..f167400254 100644 --- a/bsp/tm4c129x/libraries/driverlib/tiva_timer.c +++ b/bsp/tm4c129x/libraries/driverlib/tiva_timer.c @@ -2,25 +2,25 @@ // // timer.c - Driver for the timer module. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -297,6 +297,7 @@ TimerDisable(uint32_t ui32Base, uint32_t ui32Timer) //! - \b TIMER_CFG_A_CAP_TIME - Half-width edge time capture //! - \b TIMER_CFG_A_CAP_TIME_UP - Half-width edge time capture that counts up //! instead of down (not available on all parts) +//! - \b TIMER_CFG_A_ONE_SHOT_PWM - Half-width one shot PWM output //! - \b TIMER_CFG_A_PWM - Half-width PWM output //! //! Some Tiva devices also allow configuring an action when the timers @@ -351,11 +352,11 @@ TimerConfigure(uint32_t ui32Base, uint32_t ui32Config) // Check the arguments. // ASSERT(_TimerBaseValid(ui32Base)); - ASSERT((ui32Config == TIMER_CFG_ONE_SHOT) || - (ui32Config == TIMER_CFG_ONE_SHOT_UP) || - (ui32Config == TIMER_CFG_PERIODIC) || - (ui32Config == TIMER_CFG_PERIODIC_UP) || - (ui32Config == TIMER_CFG_RTC) || + ASSERT(((ui32Config & 0xfff0ffff) == TIMER_CFG_ONE_SHOT) || + ((ui32Config & 0xfff0ffff) == TIMER_CFG_ONE_SHOT_UP) || + ((ui32Config & 0xfff0ffff) == TIMER_CFG_PERIODIC) || + ((ui32Config & 0xfff0ffff) == TIMER_CFG_PERIODIC_UP) || + ((ui32Config & 0xfff0ffff) == TIMER_CFG_RTC) || ((ui32Config & 0xff000000) == TIMER_CFG_SPLIT_PAIR)); ASSERT(((ui32Config & 0xff000000) != TIMER_CFG_SPLIT_PAIR) || ((((ui32Config & 0x000000ff) == TIMER_CFG_A_ONE_SHOT) || @@ -366,6 +367,7 @@ TimerConfigure(uint32_t ui32Base, uint32_t ui32Config) ((ui32Config & 0x000000ff) == TIMER_CFG_A_CAP_COUNT_UP) || ((ui32Config & 0x000000ff) == TIMER_CFG_A_CAP_TIME) || ((ui32Config & 0x000000ff) == TIMER_CFG_A_CAP_TIME_UP) || + ((ui32Config & 0x000000ff) == TIMER_CFG_A_ONE_SHOT_PWM) || ((ui32Config & 0x000000ff) == TIMER_CFG_A_PWM)) && (((ui32Config & 0x0000ff00) == TIMER_CFG_B_ONE_SHOT) || ((ui32Config & 0x0000ff00) == TIMER_CFG_B_ONE_SHOT_UP) || @@ -375,6 +377,7 @@ TimerConfigure(uint32_t ui32Base, uint32_t ui32Config) ((ui32Config & 0x0000ff00) == TIMER_CFG_B_CAP_COUNT_UP) || ((ui32Config & 0x0000ff00) == TIMER_CFG_B_CAP_TIME) || ((ui32Config & 0x0000ff00) == TIMER_CFG_B_CAP_TIME_UP) || + ((ui32Config & 0x0000ff00) == TIMER_CFG_B_ONE_SHOT_PWM) || ((ui32Config & 0x0000ff00) == TIMER_CFG_B_PWM)))); // @@ -1454,10 +1457,12 @@ TimerIntUnregister(uint32_t ui32Base, uint32_t ui32Timer) //! - \b TIMER_TIMA_DMA - Timer A uDMA complete //! - \b TIMER_CAPB_EVENT - Capture B event interrupt //! - \b TIMER_CAPB_MATCH - Capture B match interrupt +//! - \b TIMER_TIMB_MATCH - Timer B match interrupt //! - \b TIMER_TIMB_TIMEOUT - Timer B timeout interrupt //! - \b TIMER_RTC_MATCH - RTC interrupt mask //! - \b TIMER_CAPA_EVENT - Capture A event interrupt //! - \b TIMER_CAPA_MATCH - Capture A match interrupt +//! - \b TIMER_TIMA_MATCH - Timer A match interrupt //! - \b TIMER_TIMA_TIMEOUT - Timer A timeout interrupt //! //! \return None. diff --git a/bsp/tm4c129x/libraries/driverlib/tiva_timer.h b/bsp/tm4c129x/libraries/driverlib/tiva_timer.h index 7eb619a7e0..e23b14d752 100644 --- a/bsp/tm4c129x/libraries/driverlib/tiva_timer.h +++ b/bsp/tm4c129x/libraries/driverlib/tiva_timer.h @@ -2,25 +2,25 @@ // // timer.h - Prototypes for the timer module // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -72,6 +72,7 @@ extern "C" #define TIMER_CFG_A_CAP_COUNT_UP 0x00000013 // Timer A event up-counter #define TIMER_CFG_A_CAP_TIME 0x00000007 // Timer A event timer #define TIMER_CFG_A_CAP_TIME_UP 0x00000017 // Timer A event up-count timer +#define TIMER_CFG_A_ONE_SHOT_PWM 0x00000009 // Timer A one-shot PWM output #define TIMER_CFG_A_PWM 0x0000000A // Timer A PWM output #define TIMER_CFG_B_ONE_SHOT 0x00002100 // Timer B one-shot timer #define TIMER_CFG_B_ONE_SHOT_UP 0x00003100 // Timer B one-shot up-count timer @@ -81,6 +82,7 @@ extern "C" #define TIMER_CFG_B_CAP_COUNT_UP 0x00001300 // Timer B event up-counter #define TIMER_CFG_B_CAP_TIME 0x00000700 // Timer B event timer #define TIMER_CFG_B_CAP_TIME_UP 0x00001700 // Timer B event up-count timer +#define TIMER_CFG_B_ONE_SHOT_PWM 0x00000900 // Timer B one-shot PWM output #define TIMER_CFG_B_PWM 0x00000A00 // Timer B PWM output #define TIMER_CFG_A_ACT_TOINTD 0x00010000 // Timer A compare action disable // time-out interrupt. diff --git a/bsp/tm4c129x/libraries/driverlib/uart.c b/bsp/tm4c129x/libraries/driverlib/uart.c index 847f464cea..6690a8eb8a 100644 --- a/bsp/tm4c129x/libraries/driverlib/uart.c +++ b/bsp/tm4c129x/libraries/driverlib/uart.c @@ -2,25 +2,25 @@ // // uart.c - Driver for the UART. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -355,7 +355,7 @@ UARTFIFOLevelGet(uint32_t ui32Base, uint32_t *pui32TxLevel, //! the system clock is the value returned by SysCtlClockGet() for TM4C123x //! devices or the value returned by SysCtlClockFreqSet() for TM4C129x devices, //! or it can be explicitly hard coded if it is constant and known (to save the -//! code/execution overhead of a call to SysCtlClockGet() or fetch of the +//! code/execution overhead of a call to SysCtlClockGet() or fetch of the //! variable call holding the return value of SysCtlClockFreqSet()). //! //! The function disables the UART by calling UARTDisable() before changing the @@ -459,7 +459,7 @@ UARTConfigSetExpClk(uint32_t ui32Base, uint32_t ui32UARTClk, //! the system clock is the value returned by SysCtlClockGet() for TM4C123x //! devices or the value returned by SysCtlClockFreqSet() for TM4C129x devices, //! or it can be explicitly hard coded if it is constant and known (to save the -//! code/execution overhead of a call to SysCtlClockGet() or fetch of the +//! code/execution overhead of a call to SysCtlClockGet() or fetch of the //! variable call holding the return value of SysCtlClockFreqSet()). //! //! For Tiva parts that have the ability to specify the UART baud clock @@ -811,7 +811,17 @@ UARTModemControlSet(uint32_t ui32Base, uint32_t ui32Control) // // Check the arguments. // +#if defined(TARGET_IS_TM4C123_RA1) || defined(TARGET_IS_TM4C123_RA2) || \ + defined(TARGET_IS_TM4C123_RA3) || defined(TARGET_IS_TM4C123_RB0) || \ + defined(TARGET_IS_TM4C123_RB1) ASSERT(ui32Base == UART1_BASE); +#else + ASSERT((ui32Base == UART0_BASE) || + (ui32Base == UART1_BASE) || + (ui32Base == UART2_BASE) || + (ui32Base == UART3_BASE) || + (ui32Base == UART4_BASE)); +#endif ASSERT((ui32Control & ~(UART_OUTPUT_RTS | UART_OUTPUT_DTR)) == 0); // @@ -853,7 +863,17 @@ UARTModemControlClear(uint32_t ui32Base, uint32_t ui32Control) // // Check the arguments. // +#if defined(TARGET_IS_TM4C123_RA1) || defined(TARGET_IS_TM4C123_RA2) || \ + defined(TARGET_IS_TM4C123_RA3) || defined(TARGET_IS_TM4C123_RB0) || \ + defined(TARGET_IS_TM4C123_RB1) ASSERT(ui32Base == UART1_BASE); +#else + ASSERT((ui32Base == UART0_BASE) || + (ui32Base == UART1_BASE) || + (ui32Base == UART2_BASE) || + (ui32Base == UART3_BASE) || + (ui32Base == UART4_BASE)); +#endif ASSERT((ui32Control & ~(UART_OUTPUT_RTS | UART_OUTPUT_DTR)) == 0); // @@ -889,7 +909,17 @@ UARTModemControlGet(uint32_t ui32Base) // // Check the arguments. // +#if defined(TARGET_IS_TM4C123_RA1) || defined(TARGET_IS_TM4C123_RA2) || \ + defined(TARGET_IS_TM4C123_RA3) || defined(TARGET_IS_TM4C123_RB0) || \ + defined(TARGET_IS_TM4C123_RB1) ASSERT(ui32Base == UART1_BASE); +#else + ASSERT((ui32Base == UART0_BASE) || + (ui32Base == UART1_BASE) || + (ui32Base == UART2_BASE) || + (ui32Base == UART3_BASE) || + (ui32Base == UART4_BASE)); +#endif return(HWREG(ui32Base + UART_O_CTL) & (UART_OUTPUT_RTS | UART_OUTPUT_DTR)); } @@ -919,7 +949,17 @@ UARTModemStatusGet(uint32_t ui32Base) // // Check the arguments. // +#if defined(TARGET_IS_TM4C123_RA1) || defined(TARGET_IS_TM4C123_RA2) || \ + defined(TARGET_IS_TM4C123_RA3) || defined(TARGET_IS_TM4C123_RB0) || \ + defined(TARGET_IS_TM4C123_RB1) ASSERT(ui32Base == UART1_BASE); +#else + ASSERT((ui32Base == UART0_BASE) || + (ui32Base == UART1_BASE) || + (ui32Base == UART2_BASE) || + (ui32Base == UART3_BASE) || + (ui32Base == UART4_BASE)); +#endif return(HWREG(ui32Base + UART_O_FR) & (UART_INPUT_RI | UART_INPUT_DCD | UART_INPUT_CTS | UART_INPUT_DSR)); @@ -1967,7 +2007,7 @@ UART9BitAddrSend(uint32_t ui32Base, uint8_t ui8Addr) //! diagnostics and debug. In this mode, the transmit and receive terminals of //! the same UART port are internally connected. Hence, the data transmitted //! on the UnTx output is received on the UxRx input, without having to go -//! through I/O's. UARTCharPut(), UARTCharGet() functions can be used along +//! through I/O's. UARTCharPut(), UARTCharGet() functions can be used along //! with this function. //! //! \return None. diff --git a/bsp/tm4c129x/libraries/driverlib/uart.h b/bsp/tm4c129x/libraries/driverlib/uart.h index 3a9397550d..9fc3074fe9 100644 --- a/bsp/tm4c129x/libraries/driverlib/uart.h +++ b/bsp/tm4c129x/libraries/driverlib/uart.h @@ -2,25 +2,25 @@ // // uart.h - Defines and Macros for the UART. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/udma.c b/bsp/tm4c129x/libraries/driverlib/udma.c index bb2941af92..385553734a 100644 --- a/bsp/tm4c129x/libraries/driverlib/udma.c +++ b/bsp/tm4c129x/libraries/driverlib/udma.c @@ -2,25 +2,25 @@ // // udma.c - Driver for the micro-DMA controller. // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/udma.h b/bsp/tm4c129x/libraries/driverlib/udma.h index a8d3684489..663181fb19 100644 --- a/bsp/tm4c129x/libraries/driverlib/udma.h +++ b/bsp/tm4c129x/libraries/driverlib/udma.h @@ -2,25 +2,25 @@ // // udma.h - Prototypes and macros for the uDMA controller. // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/usb.c b/bsp/tm4c129x/libraries/driverlib/usb.c index 839a5575ed..65e2a5e839 100644 --- a/bsp/tm4c129x/libraries/driverlib/usb.c +++ b/bsp/tm4c129x/libraries/driverlib/usb.c @@ -2,25 +2,25 @@ // // usb.c - Driver for the USB Interface. // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/usb.h b/bsp/tm4c129x/libraries/driverlib/usb.h index 1fed815842..39b7c335e8 100644 --- a/bsp/tm4c129x/libraries/driverlib/usb.h +++ b/bsp/tm4c129x/libraries/driverlib/usb.h @@ -2,25 +2,25 @@ // // usb.h - Prototypes for the USB Interface Driver. // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/driverlib/watchdog.c b/bsp/tm4c129x/libraries/driverlib/watchdog.c index e1761ff747..9d09f463f1 100644 --- a/bsp/tm4c129x/libraries/driverlib/watchdog.c +++ b/bsp/tm4c129x/libraries/driverlib/watchdog.c @@ -2,25 +2,25 @@ // // watchdog.c - Driver for the Watchdog Timer Module. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** @@ -492,7 +492,7 @@ WatchdogIntStatus(uint32_t ui32Base, bool bMasked) //! actually cleared. Failure to do so may result in the interrupt handler //! being immediately reentered (because the interrupt controller still sees //! the interrupt source asserted). This function has no effect if the watchdog -//! timer has been locked. +//! timer has been locked. //! //! \return None. // diff --git a/bsp/tm4c129x/libraries/driverlib/watchdog.h b/bsp/tm4c129x/libraries/driverlib/watchdog.h index a14a4fb04c..a92ad93c1d 100644 --- a/bsp/tm4c129x/libraries/driverlib/watchdog.h +++ b/bsp/tm4c129x/libraries/driverlib/watchdog.h @@ -2,25 +2,25 @@ // // watchdog.h - Prototypes for the Watchdog Timer API // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Peripheral Driver Library. +// +// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/asmdefs.h b/bsp/tm4c129x/libraries/inc/asmdefs.h index b0e4cc217c..292815ac0f 100644 --- a/bsp/tm4c129x/libraries/inc/asmdefs.h +++ b/bsp/tm4c129x/libraries/inc/asmdefs.h @@ -2,25 +2,25 @@ // // asmdefs.h - Macros to allow assembly code be portable among toolchains. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_adc.h b/bsp/tm4c129x/libraries/inc/hw_adc.h index 41f8a33e4d..35a5ef14f4 100644 --- a/bsp/tm4c129x/libraries/inc/hw_adc.h +++ b/bsp/tm4c129x/libraries/inc/hw_adc.h @@ -2,25 +2,25 @@ // // hw_adc.h - Macros used when accessing the ADC hardware. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_aes.h b/bsp/tm4c129x/libraries/inc/hw_aes.h index 79d56113d6..4082d173f4 100644 --- a/bsp/tm4c129x/libraries/inc/hw_aes.h +++ b/bsp/tm4c129x/libraries/inc/hw_aes.h @@ -2,25 +2,25 @@ // // hw_aes.h - Macros used when accessing the AES hardware. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_can.h b/bsp/tm4c129x/libraries/inc/hw_can.h index 398a83d6cb..1e09d4f91f 100644 --- a/bsp/tm4c129x/libraries/inc/hw_can.h +++ b/bsp/tm4c129x/libraries/inc/hw_can.h @@ -2,25 +2,25 @@ // // hw_can.h - Defines and macros used when accessing the CAN controllers. // -// Copyright (c) 2006-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2006-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_ccm.h b/bsp/tm4c129x/libraries/inc/hw_ccm.h index 9664ceea75..4b415c7ae3 100644 --- a/bsp/tm4c129x/libraries/inc/hw_ccm.h +++ b/bsp/tm4c129x/libraries/inc/hw_ccm.h @@ -2,25 +2,25 @@ // // hw_ccm.h - Macros used when accessing the CCM hardware. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_comp.h b/bsp/tm4c129x/libraries/inc/hw_comp.h index 24616aa954..7212db5791 100644 --- a/bsp/tm4c129x/libraries/inc/hw_comp.h +++ b/bsp/tm4c129x/libraries/inc/hw_comp.h @@ -2,25 +2,25 @@ // // hw_comp.h - Macros used when accessing the comparator hardware. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_des.h b/bsp/tm4c129x/libraries/inc/hw_des.h index 775c3a745c..79025df33a 100644 --- a/bsp/tm4c129x/libraries/inc/hw_des.h +++ b/bsp/tm4c129x/libraries/inc/hw_des.h @@ -2,25 +2,25 @@ // // hw_des.h - Macros used when accessing the DES hardware. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_eeprom.h b/bsp/tm4c129x/libraries/inc/hw_eeprom.h index 2118c958e6..1151b7cf64 100644 --- a/bsp/tm4c129x/libraries/inc/hw_eeprom.h +++ b/bsp/tm4c129x/libraries/inc/hw_eeprom.h @@ -2,25 +2,25 @@ // // hw_eeprom.h - Macros used when accessing the EEPROM controller. // -// Copyright (c) 2011-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2011-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_emac.h b/bsp/tm4c129x/libraries/inc/hw_emac.h index a836da9d21..2ce40c2cfe 100644 --- a/bsp/tm4c129x/libraries/inc/hw_emac.h +++ b/bsp/tm4c129x/libraries/inc/hw_emac.h @@ -2,25 +2,25 @@ // // hw_emac.h - Macros used when accessing the EMAC hardware. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_epi.h b/bsp/tm4c129x/libraries/inc/hw_epi.h index ea9f065562..fb9ff83f4e 100644 --- a/bsp/tm4c129x/libraries/inc/hw_epi.h +++ b/bsp/tm4c129x/libraries/inc/hw_epi.h @@ -2,25 +2,25 @@ // // hw_epi.h - Macros for use in accessing the EPI registers. // -// Copyright (c) 2008-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2008-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_fan.h b/bsp/tm4c129x/libraries/inc/hw_fan.h index 9c191cf0af..81d0cd4582 100644 --- a/bsp/tm4c129x/libraries/inc/hw_fan.h +++ b/bsp/tm4c129x/libraries/inc/hw_fan.h @@ -2,25 +2,25 @@ // // hw_fan.h - Macros used when accessing the fan control hardware. // -// Copyright (c) 2010-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2010-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_flash.h b/bsp/tm4c129x/libraries/inc/hw_flash.h index e38e85b59d..a6590f04cf 100644 --- a/bsp/tm4c129x/libraries/inc/hw_flash.h +++ b/bsp/tm4c129x/libraries/inc/hw_flash.h @@ -2,25 +2,25 @@ // // hw_flash.h - Macros used when accessing the flash controller. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_gpio.h b/bsp/tm4c129x/libraries/inc/hw_gpio.h index 9e95aed435..679943573f 100644 --- a/bsp/tm4c129x/libraries/inc/hw_gpio.h +++ b/bsp/tm4c129x/libraries/inc/hw_gpio.h @@ -2,25 +2,25 @@ // // hw_gpio.h - Defines and Macros for GPIO hardware. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_hibernate.h b/bsp/tm4c129x/libraries/inc/hw_hibernate.h index ce469a20e1..c6ac859371 100644 --- a/bsp/tm4c129x/libraries/inc/hw_hibernate.h +++ b/bsp/tm4c129x/libraries/inc/hw_hibernate.h @@ -2,25 +2,25 @@ // // hw_hibernate.h - Defines and Macros for the Hibernation module. // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_i2c.h b/bsp/tm4c129x/libraries/inc/hw_i2c.h index d9d00b5d57..3403a969dc 100644 --- a/bsp/tm4c129x/libraries/inc/hw_i2c.h +++ b/bsp/tm4c129x/libraries/inc/hw_i2c.h @@ -2,25 +2,25 @@ // // hw_i2c.h - Macros used when accessing the I2C master and slave hardware. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_ints.h b/bsp/tm4c129x/libraries/inc/hw_ints.h index c75a84a6bb..7ecd162e7c 100644 --- a/bsp/tm4c129x/libraries/inc/hw_ints.h +++ b/bsp/tm4c129x/libraries/inc/hw_ints.h @@ -3,25 +3,25 @@ // hw_ints.h - Macros that define the interrupt assignment on Tiva C Series // MCUs. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,8 +33,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_lcd.h b/bsp/tm4c129x/libraries/inc/hw_lcd.h index bf0be0ae2f..865bfe47f6 100644 --- a/bsp/tm4c129x/libraries/inc/hw_lcd.h +++ b/bsp/tm4c129x/libraries/inc/hw_lcd.h @@ -2,25 +2,25 @@ // // hw_lcd.h - Defines and macros used when accessing the LCD controller. // -// Copyright (c) 2011-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2011-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_memmap.h b/bsp/tm4c129x/libraries/inc/hw_memmap.h index 87033ab823..882aa9de95 100644 --- a/bsp/tm4c129x/libraries/inc/hw_memmap.h +++ b/bsp/tm4c129x/libraries/inc/hw_memmap.h @@ -2,25 +2,25 @@ // // hw_memmap.h - Macros defining the memory map of the device. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_nvic.h b/bsp/tm4c129x/libraries/inc/hw_nvic.h index be8becf0fb..9d18a6929a 100644 --- a/bsp/tm4c129x/libraries/inc/hw_nvic.h +++ b/bsp/tm4c129x/libraries/inc/hw_nvic.h @@ -2,25 +2,25 @@ // // hw_nvic.h - Macros used when accessing the NVIC hardware. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_onewire.h b/bsp/tm4c129x/libraries/inc/hw_onewire.h index bf810b7ce9..8b48cd5dc6 100644 --- a/bsp/tm4c129x/libraries/inc/hw_onewire.h +++ b/bsp/tm4c129x/libraries/inc/hw_onewire.h @@ -2,25 +2,25 @@ // // hw_onewire.h - Macros used when accessing the One wire hardware. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_pwm.h b/bsp/tm4c129x/libraries/inc/hw_pwm.h index 2167aad93a..1ec5cf7796 100644 --- a/bsp/tm4c129x/libraries/inc/hw_pwm.h +++ b/bsp/tm4c129x/libraries/inc/hw_pwm.h @@ -2,25 +2,25 @@ // // hw_pwm.h - Defines and Macros for Pulse Width Modulation (PWM) ports. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_qei.h b/bsp/tm4c129x/libraries/inc/hw_qei.h index a86f5259bd..cfb8f4d203 100644 --- a/bsp/tm4c129x/libraries/inc/hw_qei.h +++ b/bsp/tm4c129x/libraries/inc/hw_qei.h @@ -2,25 +2,25 @@ // // hw_qei.h - Macros used when accessing the QEI hardware. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_shamd5.h b/bsp/tm4c129x/libraries/inc/hw_shamd5.h index d34c76092c..1fa68fa838 100644 --- a/bsp/tm4c129x/libraries/inc/hw_shamd5.h +++ b/bsp/tm4c129x/libraries/inc/hw_shamd5.h @@ -2,25 +2,25 @@ // // hw_shamd5.h - Macros used when accessing the SHA/MD5 hardware. // -// Copyright (c) 2012-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_ssi.h b/bsp/tm4c129x/libraries/inc/hw_ssi.h index 36a92cf1e4..43560acb16 100644 --- a/bsp/tm4c129x/libraries/inc/hw_ssi.h +++ b/bsp/tm4c129x/libraries/inc/hw_ssi.h @@ -2,25 +2,25 @@ // // hw_ssi.h - Macros used when accessing the SSI hardware. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_sysctl.h b/bsp/tm4c129x/libraries/inc/hw_sysctl.h index cab5049da5..d591b05c57 100644 --- a/bsp/tm4c129x/libraries/inc/hw_sysctl.h +++ b/bsp/tm4c129x/libraries/inc/hw_sysctl.h @@ -2,25 +2,25 @@ // // hw_sysctl.h - Macros used when accessing the system control hardware. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_sysexc.h b/bsp/tm4c129x/libraries/inc/hw_sysexc.h index 314d17a8a1..0be323e231 100644 --- a/bsp/tm4c129x/libraries/inc/hw_sysexc.h +++ b/bsp/tm4c129x/libraries/inc/hw_sysexc.h @@ -2,25 +2,25 @@ // // hw_sysexc.h - Macros used when accessing the system exception module. // -// Copyright (c) 2011-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2011-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_timer.h b/bsp/tm4c129x/libraries/inc/hw_timer.h index 47a857567a..08d855214c 100644 --- a/bsp/tm4c129x/libraries/inc/hw_timer.h +++ b/bsp/tm4c129x/libraries/inc/hw_timer.h @@ -2,25 +2,25 @@ // // hw_timer.h - Defines and macros used when accessing the timer. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_types.h b/bsp/tm4c129x/libraries/inc/hw_types.h index ec493b5061..9b0a5bf7b9 100644 --- a/bsp/tm4c129x/libraries/inc/hw_types.h +++ b/bsp/tm4c129x/libraries/inc/hw_types.h @@ -2,25 +2,25 @@ // // hw_types.h - Common types and macros. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** @@ -110,7 +110,7 @@ #ifndef REVISION_IS_A1 #define REVISION_IS_A1 \ ((HWREG(SYSCTL_DID0) & (SYSCTL_DID0_MAJ_M | SYSCTL_DID0_MIN_M)) == \ - (SYSCTL_DID0_MAJ_REVA | SYSCTL_DID0_MIN_0)) + (SYSCTL_DID0_MAJ_REVA | SYSCTL_DID0_MIN_1)) #endif #ifndef REVISION_IS_A2 diff --git a/bsp/tm4c129x/libraries/inc/hw_uart.h b/bsp/tm4c129x/libraries/inc/hw_uart.h index 1c40b79f3d..8d98957073 100644 --- a/bsp/tm4c129x/libraries/inc/hw_uart.h +++ b/bsp/tm4c129x/libraries/inc/hw_uart.h @@ -2,25 +2,25 @@ // // hw_uart.h - Macros and defines used when accessing the UART hardware. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_udma.h b/bsp/tm4c129x/libraries/inc/hw_udma.h index 1d52b00901..5cd8c33a3d 100644 --- a/bsp/tm4c129x/libraries/inc/hw_udma.h +++ b/bsp/tm4c129x/libraries/inc/hw_udma.h @@ -2,25 +2,25 @@ // // hw_udma.h - Macros for use in accessing the UDMA registers. // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_usb.h b/bsp/tm4c129x/libraries/inc/hw_usb.h index 7aa3b50a29..506af163f3 100644 --- a/bsp/tm4c129x/libraries/inc/hw_usb.h +++ b/bsp/tm4c129x/libraries/inc/hw_usb.h @@ -2,25 +2,25 @@ // // hw_usb.h - Macros for use in accessing the USB registers. // -// Copyright (c) 2007-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/hw_watchdog.h b/bsp/tm4c129x/libraries/inc/hw_watchdog.h index 783b6f07f6..937d5146a4 100644 --- a/bsp/tm4c129x/libraries/inc/hw_watchdog.h +++ b/bsp/tm4c129x/libraries/inc/hw_watchdog.h @@ -2,25 +2,25 @@ // // hw_watchdog.h - Macros used when accessing the Watchdog Timer hardware. // -// Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2005-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/inc/tm4c1294ncpdt.h b/bsp/tm4c129x/libraries/inc/tm4c1294ncpdt.h index 458eaac395..ef80879350 100644 --- a/bsp/tm4c129x/libraries/inc/tm4c1294ncpdt.h +++ b/bsp/tm4c129x/libraries/inc/tm4c1294ncpdt.h @@ -2,25 +2,25 @@ // // tm4c1294ncpdt.h - TM4C1294NCPDT Register Definitions // -// Copyright (c) 2013-2017 Texas Instruments Incorporated. All rights reserved. +// Copyright (c) 2013-2020 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// +// // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// +// // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the +// documentation and/or other materials provided with the // distribution. -// +// // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,8 +32,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. +// +// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/startup/startup_ewarm.c b/bsp/tm4c129x/libraries/startup/startup_ewarm.c index a5dbd78756..9542e980b6 100644 --- a/bsp/tm4c129x/libraries/startup/startup_ewarm.c +++ b/bsp/tm4c129x/libraries/startup/startup_ewarm.c @@ -5,20 +5,20 @@ // // Copyright (c) 2013-2017 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. -// +// // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. -// +// // This is part of revision 2.1.4.178 of the DK-TM4C129X Firmware Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/startup/startup_gcc.c b/bsp/tm4c129x/libraries/startup/startup_gcc.c index 3f9d93a46b..30a95d3f34 100644 --- a/bsp/tm4c129x/libraries/startup/startup_gcc.c +++ b/bsp/tm4c129x/libraries/startup/startup_gcc.c @@ -4,20 +4,20 @@ // // Copyright (c) 2013-2017 Texas Instruments Incorporated. All rights reserved. // Software License Agreement -// +// // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. -// +// // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. -// +// // This is part of revision 2.1.4.178 of the DK-TM4C129X Firmware Package. // //***************************************************************************** diff --git a/bsp/tm4c129x/libraries/startup/startup_rvmdk.S b/bsp/tm4c129x/libraries/startup/startup_rvmdk.S index 3554d00143..4754d15316 100644 --- a/bsp/tm4c129x/libraries/startup/startup_rvmdk.S +++ b/bsp/tm4c129x/libraries/startup/startup_rvmdk.S @@ -5,20 +5,20 @@ ; ; Copyright (c) 2013-2017 Texas Instruments Incorporated. All rights reserved. ; Software License Agreement -; +; ; Texas Instruments (TI) is supplying this software for use solely and ; exclusively on TI's microcontroller products. The software is owned by ; TI and/or its suppliers, and is protected under applicable copyright ; laws. You may not combine this software with "viral" open-source ; software in order to form a larger program. -; +; ; THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. ; NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT ; NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ; A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY ; CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL ; DAMAGES, FOR ANY REASON WHATSOEVER. -; +; ; This is part of revision 2.1.4.178 of the DK-TM4C129X Firmware Package. ; ;****************************************************************************** From eebb2561ec166e0016187c7b7998ada4f8212b3a Mon Sep 17 00:00:00 2001 From: ArdaFu Date: Sat, 26 Jun 2021 12:37:59 +0800 Subject: [PATCH 195/255] [bsp][tm4c129x] Do not free net driver rx pBuf in receive method when device is not ready. Fix#4625 --- bsp/tm4c129x/drivers/drv_eth.c | 128 ++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 27 deletions(-) diff --git a/bsp/tm4c129x/drivers/drv_eth.c b/bsp/tm4c129x/drivers/drv_eth.c index 12d9f88f3e..11b96a10a5 100644 --- a/bsp/tm4c129x/drivers/drv_eth.c +++ b/bsp/tm4c129x/drivers/drv_eth.c @@ -89,10 +89,12 @@ #define PHY_PHYS_ADDR 0 #endif +#if 1 #ifndef EMAC_PHY_CONFIG #define EMAC_PHY_CONFIG (EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN | \ EMAC_PHY_AN_100B_T_FULL_DUPLEX) #endif +#endif /** * If necessary, set the defaui32t number of transmit and receive DMA descriptors @@ -142,6 +144,11 @@ extern void lwIPHostGetTime(u32_t *time_s, u32_t *time_ns); #include "lwipopts.h" #include "drv_eth.h" +/* Define those to better describe your network interface. */ +#define IFNAME0 't' +#define IFNAME1 'i' + + /** * A structure used to keep track of driver state and error counts. */ @@ -233,6 +240,13 @@ static tStellarisIF g_StellarisIFData = { volatile uint32_t g_ui32NormalInts; volatile uint32_t g_ui32AbnormalInts; +/** + * Status flag for EEE link established + */ +#if EEE_SUPPORT +volatile bool g_bEEELinkActive; +#endif + /** * A macro which determines whether a pointer is within the SRAM address * space and, hence, points to a buffer that the Ethernet MAC can directly @@ -335,9 +349,35 @@ tivaif_hwinit(struct netif *psNetif) { uint16_t ui16Val; + /* clear the EEE Link Active flag */ +#if EEE_SUPPORT + g_bEEELinkActive = false; +#endif + + /* Set MAC hardware address length */ + psNetif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* Set MAC hardware address */ + EMACAddrGet(EMAC0_BASE, 0, &(psNetif->hwaddr[0])); + + /* Maximum transfer unit */ + psNetif->mtu = 1500; + + /* Device capabilities */ + psNetif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + /* Initialize the DMA descriptors. */ InitDMADescriptors(); +#if defined(EMAC_PHY_IS_EXT_MII) || defined(EMAC_PHY_IS_EXT_RMII) + /* If PHY is external then reset the PHY before configuring it */ + EMACPHYWrite(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_BMCR, + EPHY_BMCR_MIIRESET); + + while((EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_BMCR) & + EPHY_BMCR_MIIRESET) == EPHY_BMCR_MIIRESET); +#endif + /* Clear any stray PHY interrupts that may be set. */ ui16Val = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_MISR1); ui16Val = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_MISR2); @@ -398,8 +438,13 @@ tivaif_hwinit(struct netif *psNetif) IntMasterEnable(); /* Tell the PHY to start an auto-negotiation cycle. */ +#if defined(EMAC_PHY_IS_EXT_MII) || defined(EMAC_PHY_IS_EXT_RMII) + EMACPHYWrite(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_BMCR, (EPHY_BMCR_SPEED | + EPHY_BMCR_DUPLEXM | EPHY_BMCR_ANEN | EPHY_BMCR_RESTARTAN)); +#else EMACPHYWrite(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_BMCR, (EPHY_BMCR_ANEN | EPHY_BMCR_RESTARTAN)); +#endif } #ifdef DEBUG @@ -484,16 +529,16 @@ tivaif_check_pbuf(struct pbuf *p) tivaif_trace_pbuf("Copied:", pBuf); #endif DRIVER_STATS_INC(TXCopyCount); - - /* Reduce the reference count on the original pbuf since - * we're not going to hold on to it after returning from - * tivaif_transmit. Note that we already bumped - * the reference count at the top of tivaif_transmit. - */ - pbuf_free(p); } } + /* Reduce the reference count on the original pbuf since we're not + * going to hold on to it after returning from tivaif_transmit. + * Note that we already bumped the reference count at the top of + * tivaif_transmit. + */ + pbuf_free(p); + /* Send back the new pbuf pointer or NULL if an error occurred. */ return(pBuf); } @@ -573,7 +618,7 @@ tivaif_transmit(net_device_t dev, struct pbuf *p) { /** * The current write descriptor has a pbuf attached to it so this - * implies that the ring is fui32l. Reject this transmit request with a + * implies that the ring is full. Reject this transmit request with a * memory error since we can't satisfy it just now. */ pbuf_free(p); @@ -630,13 +675,8 @@ tivaif_transmit(net_device_t dev, struct pbuf *p) pDesc->Desc.ui32CtrlStatus = 0; } -#ifdef RT_LWIP_USING_HW_CHECKSUM pDesc->Desc.ui32CtrlStatus |= (DES0_TX_CTRL_IP_ALL_CKHSUMS | DES0_TX_CTRL_CHAINED); -#else - pDesc->Desc.ui32CtrlStatus |= (DES0_TX_CTRL_NO_CHKSUM | - DES0_TX_CTRL_CHAINED); -#endif /* Decrement our descriptor counter, move on to the next buffer in the * pbuf chain. */ @@ -761,7 +801,7 @@ tivaif_receive(net_device_t dev) { tDescriptorList *pDescList; tStellarisIF *pIF; - struct pbuf *pBuf; + static struct pbuf *pBuf = NULL; uint32_t ui32DescEnd; /* Get a pointer to our state data */ @@ -773,10 +813,10 @@ tivaif_receive(net_device_t dev) /* Start with a NULL pbuf so that we don't try to link chain the first * time round. */ - pBuf = NULL; + //pBuf = NULL; /* Determine where we start and end our walk of the descriptor list */ - ui32DescEnd = pDescList->ui32Read ? (pDescList->ui32Read - 1) : (pDescList->ui32NumDescs - 1); + ui32DescEnd = pDescList->ui32Read ? (pDescList->ui32Read - 1) : (pDescList->ui32NumDescs - 1); /* Step through the descriptors that are marked for CPU attention. */ while(pDescList->ui32Read != ui32DescEnd) @@ -816,7 +856,7 @@ tivaif_receive(net_device_t dev) if(pBuf) { /* Link this pbuf to the last one we looked at since this buffer - * is a continuation of an existing frame (split across mui32tiple + * is a continuation of an existing frame (split across multiple * pbufs). Note that we use pbuf_cat() here rather than * pbuf_chain() since we don't want to increase the reference * count of either pbuf - we only want to link them together. @@ -843,6 +883,7 @@ tivaif_receive(net_device_t dev) pbuf_free(pBuf); LINK_STATS_INC(link.drop); DRIVER_STATS_INC(RXPacketErrCount); + pBuf = NULL; } else { @@ -860,13 +901,11 @@ tivaif_receive(net_device_t dev) #if NO_SYS if(ethernet_input(pBuf, psNetif) != RT_EOK) - { #else - //if(tcpip_input(pBuf, psNetif) != RT_EOK) - if((rt_mb_send(dev->rx_pbuf_mb, (rt_uint32_t)pBuf) != RT_EOK) || - (eth_device_ready(&(dev->parent)) != RT_EOK)) - { + //if(tcpip_input(pBuf, psNetif) != ERR_OK) + if(rt_mb_send(dev->rx_pbuf_mb, (rt_uint32_t)pBuf) != RT_EOK) #endif + { /* drop the packet */ LWIP_DEBUGF(NETIF_DEBUG, ("tivaif_input: input error\n")); pbuf_free(pBuf); @@ -943,6 +982,9 @@ void tivaif_process_phy_interrupt(net_device_t dev) { uint16_t ui16Val, ui16Status; +#if EEE_SUPPORT + uint16_t ui16EEEStatus; +#endif uint32_t ui32Config, ui32Mode, ui32RxMaxFrameSize; /* Read the PHY interrupt status. This clears all interrupt sources. @@ -951,13 +993,16 @@ tivaif_process_phy_interrupt(net_device_t dev) */ ui16Val = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_MISR1); - /* - * Dummy read PHY REG EPHY_BMSR, it will force update the EPHY_STS register - */ - EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_BMSR); /* Read the current PHY status. */ ui16Status = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_STS); + /* If EEE mode support is requested then read the value of the Link + * partners status + */ +#if EEE_SUPPORT + ui16EEEStatus = EMACPHYMMDRead(EMAC0_BASE, PHY_PHYS_ADDR, 0x703D); +#endif + /* Has the link status changed? */ if(ui16Val & EPHY_MISR1_LINKSTAT) { @@ -972,6 +1017,19 @@ tivaif_process_phy_interrupt(net_device_t dev) eth_device_linkchange(&(dev->parent), RT_TRUE); #endif + /* if the link has been advertised as EEE capable then configure + * the MAC register for LPI timers and manually set the PHY link + * status bit + */ +#if EEE_SUPPORT + if(ui16EEEStatus & 0x2) + { + EMACLPIConfig(EMAC0_BASE, true, 1000, 36); + EMACLPILinkSet(EMAC0_BASE); + g_bEEELinkActive = true; + } +#endif + /* In this case we drop through since we may need to reconfigure * the MAC depending upon the speed and half/fui32l-duplex settings. */ @@ -985,6 +1043,16 @@ tivaif_process_phy_interrupt(net_device_t dev) //tcpip_callback((tcpip_callback_fn)netif_set_link_down, psNetif); eth_device_linkchange(&(dev->parent), RT_FALSE); #endif + + /* if the link has been advertised as EEE capable then clear the + * MAC register LPI timers and manually clear the PHY link status + * bit + */ +#if EEE_SUPPORT + g_bEEELinkActive = false; + EMACLPILinkClear(EMAC0_BASE); + EMACLPIConfig(EMAC0_BASE, false, 1000, 0); +#endif } } @@ -1061,11 +1129,17 @@ tivaif_interrupt(net_device_t dev, uint32_t ui32Status) */ if(ui32Status & EMAC_INT_TRANSMIT) { +#if EEE_SUPPORT + if(g_bEEELinkActive) + { + EMACLPIEnter(EMAC0_BASE); + } +#endif tivaif_process_transmit(dev->dma_if); } /** - * Process the receive DMA list and pass all successfui32ly received packets + * Process the receive DMA list and pass all successfully received packets * up the stack. We also call this function in cases where the receiver has * stalled due to missing buffers since the receive function will attempt to * allocate new pbufs for descriptor entries which have none. From 56815eb6f77ba48d5970133e3a27fbac37c1efd6 Mon Sep 17 00:00:00 2001 From: supperthomas <78900636@qq.com> Date: Sat, 19 Jun 2021 21:12:27 +0800 Subject: [PATCH 196/255] [bsp/nrf5x] fix the config --- bsp/nrf5x/nrf52840/.config | 138 +++++++++++++++++++++++++++++----- bsp/nrf5x/nrf52840/rtconfig.h | 20 ++++- 2 files changed, 139 insertions(+), 19 deletions(-) diff --git a/bsp/nrf5x/nrf52840/.config b/bsp/nrf5x/nrf52840/.config index 10441fdb08..ed83405af1 100644 --- a/bsp/nrf5x/nrf52840/.config +++ b/bsp/nrf5x/nrf52840/.config @@ -23,6 +23,12 @@ CONFIG_IDLE_THREAD_STACK_SIZE=256 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 is not set # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -54,6 +60,7 @@ CONFIG_RT_USING_MEMPOOL=y # CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set CONFIG_RT_USING_HEAP=y @@ -66,7 +73,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=128 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x40003 +CONFIG_RT_VER_NUM=0x40004 # CONFIG_RT_USING_CPU_FFS is not set # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set @@ -149,9 +156,9 @@ CONFIG_RT_USING_PIN=y # # POSIX layer and C standard library # -CONFIG_RT_USING_LIBC=y +# CONFIG_RT_USING_LIBC is not set # CONFIG_RT_USING_PTHREADS is not set -# CONFIG_RT_USING_MODULE is not set +# CONFIG_RT_LIBC_USING_TIME is not set # # Network @@ -188,6 +195,12 @@ CONFIG_RT_USING_LIBC=y # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set # # RT-Thread online packages @@ -256,8 +269,6 @@ CONFIG_RT_USING_LIBC=y # CONFIG_PKG_USING_LIBRWS is not set # CONFIG_PKG_USING_TCPSERVER is not set # CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set # CONFIG_PKG_USING_DLT645 is not set # CONFIG_PKG_USING_QXWZ is not set # CONFIG_PKG_USING_SMTP_CLIENT is not set @@ -271,6 +282,13 @@ CONFIG_RT_USING_LIBC=y # 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 @@ -296,7 +314,13 @@ CONFIG_RT_USING_LIBC=y # 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 +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set # # tools packages @@ -305,12 +329,16 @@ CONFIG_RT_USING_LIBC=y # 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 @@ -318,14 +346,48 @@ CONFIG_RT_USING_LIBC=y # 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_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set -# CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set # CONFIG_PKG_USING_FLASHDB is not set @@ -335,6 +397,9 @@ CONFIG_RT_USING_LIBC=y # 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 @@ -344,11 +409,12 @@ CONFIG_RT_USING_LIBC=y # CONFIG_PKG_USING_RAMDISK is not set # CONFIG_PKG_USING_MININI is not set # CONFIG_PKG_USING_QBOOT is not set -# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set -# CONFIG_PKG_USING_UC_CRC is not set -# CONFIG_PKG_USING_UC_CLK is not set -# CONFIG_PKG_USING_UC_COMMON is not set # CONFIG_PKG_USING_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 @@ -357,6 +423,7 @@ CONFIG_RT_USING_LIBC=y # 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 @@ -376,7 +443,6 @@ CONFIG_PKG_NRFX_VER="v2.1.0" # 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 @@ -407,6 +473,35 @@ CONFIG_PKG_NRFX_VER="v2.1.0" # 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 +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS 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 @@ -416,10 +511,12 @@ CONFIG_PKG_NRFX_VER="v2.1.0" # 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 @@ -436,19 +533,25 @@ CONFIG_PKG_NRFX_VER="v2.1.0" # CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set # CONFIG_PKG_USING_VI is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set # CONFIG_PKG_USING_VT100 is not set -# CONFIG_PKG_USING_TETRIS is not set -# CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set + +# +# 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_TENSORFLOWLITEMICRO 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 # # Hardware Drivers Config @@ -480,6 +583,7 @@ CONFIG_BSP_USING_UART0=y CONFIG_NRFX_UART0_ENABLED=1 CONFIG_BSP_UART0_RX_PIN=8 CONFIG_BSP_UART0_TX_PIN=6 +# CONFIG_BSP_USING_I2C is not set # CONFIG_BSP_USING_SPI is not set # CONFIG_BSP_USING_ON_CHIP_FLASH is not set diff --git a/bsp/nrf5x/nrf52840/rtconfig.h b/bsp/nrf5x/nrf52840/rtconfig.h index 9f8dc015dd..d821014dab 100644 --- a/bsp/nrf5x/nrf52840/rtconfig.h +++ b/bsp/nrf5x/nrf52840/rtconfig.h @@ -19,6 +19,9 @@ #define RT_USING_TIMER_SOFT #define RT_TIMER_THREAD_PRIO 4 #define RT_TIMER_THREAD_STACK_SIZE 512 + +/* kservice optimization */ + #define RT_DEBUG /* Inter-Thread communication */ @@ -41,7 +44,7 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40003 +#define RT_VER_NUM 0x40004 /* RT-Thread Components */ @@ -85,7 +88,6 @@ /* POSIX layer and C standard library */ -#define RT_USING_LIBC /* Network */ @@ -107,6 +109,9 @@ /* Utilities */ +/* RT-Thread Utestcases */ + + /* RT-Thread online packages */ /* IoT - internet of things */ @@ -137,18 +142,29 @@ /* system packages */ +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + /* peripheral libraries and drivers */ #define PKG_USING_NRFX #define PKG_USING_NRFX_V210 +/* AI packages */ + + /* miscellaneous packages */ /* samples: kernel and components samples */ +/* entertainment: terminal games and other interesting software packages */ + + /* Hardware Drivers Config */ #define SOC_NRF52840 From 8849d16394b819a6c1d912423b03edffe886e87b Mon Sep 17 00:00:00 2001 From: supperthomas <78900636@qq.com> Date: Sat, 19 Jun 2021 22:16:52 +0800 Subject: [PATCH 197/255] [bsp/nrf5x] rebuild nrf52840 gpio --- bsp/nrf5x/nrf52840/.config | 36 +- bsp/nrf5x/nrf52840/board/SConscript | 3 +- bsp/nrf5x/nrf52840/board/app_config.h | 4 - bsp/nrf5x/nrf52840/board/board.h | 10 + .../nrf52840/board/linker_scripts/link.lds | 1 - bsp/nrf5x/nrf52840/board/sdk_config.h | 3 - bsp/nrf5x/nrf52840/project.uvoptx | 1542 ++++++++--------- bsp/nrf5x/nrf52840/project.uvprojx | 634 ++++--- bsp/nrf5x/nrf52840/rtconfig.h | 20 +- bsp/nrf5x/nrf52840/rtconfig.py | 2 +- bsp/nrf5x/nrf52840/template.uvoptx | 2 +- bsp/nrf5x/nrf52840/template.uvprojx | 13 +- 12 files changed, 1086 insertions(+), 1184 deletions(-) delete mode 100644 bsp/nrf5x/nrf52840/board/app_config.h diff --git a/bsp/nrf5x/nrf52840/.config b/bsp/nrf5x/nrf52840/.config index ed83405af1..f9c63e767c 100644 --- a/bsp/nrf5x/nrf52840/.config +++ b/bsp/nrf5x/nrf52840/.config @@ -437,9 +437,9 @@ CONFIG_RT_USING_PIN=y # CONFIG_PKG_USING_NRF5X_SDK is not set CONFIG_PKG_USING_NRFX=y CONFIG_PKG_NRFX_PATH="/packages/peripherals/nrfx" -CONFIG_PKG_USING_NRFX_V210=y -# CONFIG_PKG_USING_NRFX_LATEST_VERSION is not set -CONFIG_PKG_NRFX_VER="v2.1.0" +# CONFIG_PKG_USING_NRFX_V210 is not set +CONFIG_PKG_USING_NRFX_LATEST_VERSION=y +CONFIG_PKG_NRFX_VER="latest" # CONFIG_PKG_USING_WM_LIBRARIES is not set # CONFIG_PKG_USING_KENDRYTE_SDK is not set # CONFIG_PKG_USING_INFRARED is not set @@ -557,35 +557,18 @@ CONFIG_PKG_NRFX_VER="v2.1.0" # Hardware Drivers Config # CONFIG_SOC_NRF52840=y -CONFIG_NRFX_CLOCK_ENABLED=1 -CONFIG_NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY=7 -CONFIG_NRFX_CLOCK_CONFIG_LF_SRC=1 CONFIG_SOC_NORDIC=y - -# -# Onboard Peripheral Drivers -# -CONFIG_BSP_USING_JLINK_TO_USART=y -# CONFIG_BSP_USING_QSPI_FLASH is not set +CONFIG_BSP_BOARD_PCA_10056=y # # On-chip Peripheral Drivers # CONFIG_BSP_USING_GPIO=y CONFIG_NRFX_GPIOTE_ENABLED=1 -# CONFIG_BSP_USING_SAADC is not set -# CONFIG_BSP_USING_PWM is not set CONFIG_BSP_USING_UART=y -CONFIG_NRFX_USING_UART=y -# CONFIG_NRFX_USING_UARTE is not set -CONFIG_NRFX_UART_ENABLED=1 CONFIG_BSP_USING_UART0=y -CONFIG_NRFX_UART0_ENABLED=1 CONFIG_BSP_UART0_RX_PIN=8 CONFIG_BSP_UART0_TX_PIN=6 -# CONFIG_BSP_USING_I2C is not set -# CONFIG_BSP_USING_SPI is not set -# CONFIG_BSP_USING_ON_CHIP_FLASH is not set # # On-chip flash config @@ -595,8 +578,9 @@ CONFIG_MCU_FLASH_SIZE_KB=1024 CONFIG_MCU_SRAM_START_ADDRESS=0x20000000 CONFIG_MCU_SRAM_SIZE_KB=256 CONFIG_MCU_FLASH_PAGE_SIZE=0x1000 -# CONFIG_BSP_USING_WDT is not set -# CONFIG_BSP_USING_ONCHIP_RTC is not set -CONFIG_BLE_STACK_USING_NULL=y -# CONFIG_BSP_USING_SOFTDEVICE is not set -# CONFIG_BSP_USING_NIMBLE is not set +CONFIG_NRFX_CLOCK_ENABLED=1 +CONFIG_NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY=7 +CONFIG_NRFX_CLOCK_CONFIG_LF_SRC=1 +CONFIG_NRFX_USING_UART=y +CONFIG_NRFX_UART_ENABLED=1 +CONFIG_NRFX_UART0_ENABLED=1 diff --git a/bsp/nrf5x/nrf52840/board/SConscript b/bsp/nrf5x/nrf52840/board/SConscript index 27bcddd310..d74f1a8861 100644 --- a/bsp/nrf5x/nrf52840/board/SConscript +++ b/bsp/nrf5x/nrf52840/board/SConscript @@ -5,7 +5,6 @@ from building import * cwd = GetCurrentDir() src = Glob('*.c') CPPPATH = [cwd] -define = ['USE_APP_CONFIG'] -group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH,CPPDEFINES = define) +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) Return('group') diff --git a/bsp/nrf5x/nrf52840/board/app_config.h b/bsp/nrf5x/nrf52840/board/app_config.h deleted file mode 100644 index 67db2eb886..0000000000 --- a/bsp/nrf5x/nrf52840/board/app_config.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef APP_CONFIG_H -#define APP_CONFIG_H - -#endif //APP_CONFIG_H diff --git a/bsp/nrf5x/nrf52840/board/board.h b/bsp/nrf5x/nrf52840/board/board.h index a3ccadfa36..edfb0b635a 100644 --- a/bsp/nrf5x/nrf52840/board/board.h +++ b/bsp/nrf5x/nrf52840/board/board.h @@ -1,3 +1,13 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-19 supperthomas first version + * + */ #ifndef _BOARD_H_ #define _BOARD_H_ diff --git a/bsp/nrf5x/nrf52840/board/linker_scripts/link.lds b/bsp/nrf5x/nrf52840/board/linker_scripts/link.lds index 9a9609eed7..f91b8466ca 100644 --- a/bsp/nrf5x/nrf52840/board/linker_scripts/link.lds +++ b/bsp/nrf5x/nrf52840/board/linker_scripts/link.lds @@ -7,7 +7,6 @@ MEMORY { FLASH (rx) : ORIGIN = 0x0, LENGTH = 0x100000 RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x40000 - CODE_RAM (rwx) : ORIGIN = 0x800000, LENGTH = 0x10000 } INCLUDE "packages/nrfx-v2.1.0/mdk/nrf_common.ld" diff --git a/bsp/nrf5x/nrf52840/board/sdk_config.h b/bsp/nrf5x/nrf52840/board/sdk_config.h index d62c024da3..25fa4938fa 100644 --- a/bsp/nrf5x/nrf52840/board/sdk_config.h +++ b/bsp/nrf5x/nrf52840/board/sdk_config.h @@ -43,9 +43,6 @@ #ifndef SDK_CONFIG_H #define SDK_CONFIG_H // <<< Use Configuration Wizard in Context Menu >>>\n -#ifdef USE_APP_CONFIG -#include "app_config.h" -#endif // nRF_BLE #include diff --git a/bsp/nrf5x/nrf52840/project.uvoptx b/bsp/nrf5x/nrf52840/project.uvoptx index ff162faafb..376d1dc34b 100644 --- a/bsp/nrf5x/nrf52840/project.uvoptx +++ b/bsp/nrf5x/nrf52840/project.uvoptx @@ -10,7 +10,7 @@ *.s*; *.src; *.a* *.obj; *.o *.lib - *.txt; *.h; *.inc + *.txt; *.h; *.inc; *.md *.plm *.cpp 0 @@ -182,7 +182,7 @@ - Kernel + Applications 0 0 0 @@ -194,182 +194,6 @@ 0 0 0 - ..\..\..\src\clock.c - clock.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\..\src\components.c - components.c - 0 - 0 - - - 1 - 3 - 1 - 0 - 0 - 0 - ..\..\..\src\device.c - device.c - 0 - 0 - - - 1 - 4 - 1 - 0 - 0 - 0 - ..\..\..\src\idle.c - idle.c - 0 - 0 - - - 1 - 5 - 1 - 0 - 0 - 0 - ..\..\..\src\ipc.c - ipc.c - 0 - 0 - - - 1 - 6 - 1 - 0 - 0 - 0 - ..\..\..\src\irq.c - irq.c - 0 - 0 - - - 1 - 7 - 1 - 0 - 0 - 0 - ..\..\..\src\kservice.c - kservice.c - 0 - 0 - - - 1 - 8 - 1 - 0 - 0 - 0 - ..\..\..\src\mem.c - mem.c - 0 - 0 - - - 1 - 9 - 1 - 0 - 0 - 0 - ..\..\..\src\mempool.c - mempool.c - 0 - 0 - - - 1 - 10 - 1 - 0 - 0 - 0 - ..\..\..\src\object.c - object.c - 0 - 0 - - - 1 - 11 - 1 - 0 - 0 - 0 - ..\..\..\src\scheduler.c - scheduler.c - 0 - 0 - - - 1 - 12 - 1 - 0 - 0 - 0 - ..\..\..\src\signal.c - signal.c - 0 - 0 - - - 1 - 13 - 1 - 0 - 0 - 0 - ..\..\..\src\thread.c - thread.c - 0 - 0 - - - 1 - 14 - 1 - 0 - 0 - 0 - ..\..\..\src\timer.c - timer.c - 0 - 0 - - - - - Applications - 0 - 0 - 0 - 0 - - 2 - 15 - 1 - 0 - 0 - 0 applications\application.c application.c 0 @@ -378,510 +202,14 @@ - Drivers + CPU 0 0 0 0 - 3 - 16 - 1 - 0 - 0 - 0 - board\board.c - board.c - 0 - 0 - - - 3 - 17 - 1 - 0 - 0 - 0 - ..\libraries\drivers\drv_uart.c - drv_uart.c - 0 - 0 - - - - - nrfx - 0 - 0 - 0 - 0 - - 4 - 18 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_adc.c - nrfx_adc.c - 0 - 0 - - - 4 - 19 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_clock.c - nrfx_clock.c - 0 - 0 - - - 4 - 20 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_comp.c - nrfx_comp.c - 0 - 0 - - - 4 - 21 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_dppi.c - nrfx_dppi.c - 0 - 0 - - - 4 - 22 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_egu.c - nrfx_egu.c - 0 - 0 - - - 4 - 23 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_gpiote.c - nrfx_gpiote.c - 0 - 0 - - - 4 - 24 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_i2s.c - nrfx_i2s.c - 0 - 0 - - - 4 - 25 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_ipc.c - nrfx_ipc.c - 0 - 0 - - - 4 - 26 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_lpcomp.c - nrfx_lpcomp.c - 0 - 0 - - - 4 - 27 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_nfct.c - nrfx_nfct.c - 0 - 0 - - - 4 - 28 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_nvmc.c - nrfx_nvmc.c - 0 - 0 - - - 4 - 29 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_pdm.c - nrfx_pdm.c - 0 - 0 - - - 4 - 30 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_power.c - nrfx_power.c - 0 - 0 - - - 4 - 31 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_ppi.c - nrfx_ppi.c - 0 - 0 - - - 4 - 32 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_pwm.c - nrfx_pwm.c - 0 - 0 - - - 4 - 33 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_qdec.c - nrfx_qdec.c - 0 - 0 - - - 4 - 34 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_qspi.c - nrfx_qspi.c - 0 - 0 - - - 4 - 35 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_rng.c - nrfx_rng.c - 0 - 0 - - - 4 - 36 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_rtc.c - nrfx_rtc.c - 0 - 0 - - - 4 - 37 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_saadc.c - nrfx_saadc.c - 0 - 0 - - - 4 - 38 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_spi.c - nrfx_spi.c - 0 - 0 - - - 4 - 39 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_spim.c - nrfx_spim.c - 0 - 0 - - - 4 - 40 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_spis.c - nrfx_spis.c - 0 - 0 - - - 4 - 41 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_systick.c - nrfx_systick.c - 0 - 0 - - - 4 - 42 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_temp.c - nrfx_temp.c - 0 - 0 - - - 4 - 43 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_timer.c - nrfx_timer.c - 0 - 0 - - - 4 - 44 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_twi.c - nrfx_twi.c - 0 - 0 - - - 4 - 45 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_twi_twim.c - nrfx_twi_twim.c - 0 - 0 - - - 4 - 46 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_twim.c - nrfx_twim.c - 0 - 0 - - - 4 - 47 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_twis.c - nrfx_twis.c - 0 - 0 - - - 4 - 48 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_uart.c - nrfx_uart.c - 0 - 0 - - - 4 - 49 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_uarte.c - nrfx_uarte.c - 0 - 0 - - - 4 - 50 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_usbd.c - nrfx_usbd.c - 0 - 0 - - - 4 - 51 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_usbreg.c - nrfx_usbreg.c - 0 - 0 - - - 4 - 52 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\drivers\src\nrfx_wdt.c - nrfx_wdt.c - 0 - 0 - - - 4 - 53 - 1 - 0 - 0 - 0 - packages\nrfx-v2.1.0\mdk\system_nrf52840.c - system_nrf52840.c - 0 - 0 - - - 4 - 54 - 2 - 0 - 0 - 0 - packages\nrfx-v2.1.0\mdk\arm_startup_nrf52840.s - arm_startup_nrf52840.s - 0 - 0 - - - - - cpu - 0 - 0 - 0 - 0 - - 5 - 55 - 1 - 0 - 0 - 0 - ..\..\..\libcpu\arm\common\backtrace.c - backtrace.c - 0 - 0 - - - 5 - 56 + 2 + 2 1 0 0 @@ -892,8 +220,8 @@ 0 - 5 - 57 + 2 + 3 1 0 0 @@ -904,20 +232,20 @@ 0 - 5 - 58 + 2 + 4 1 0 0 0 - ..\..\..\libcpu\arm\cortex-m4\cpuport.c - cpuport.c + ..\..\..\libcpu\arm\common\backtrace.c + backtrace.c 0 0 - 5 - 59 + 2 + 5 2 0 0 @@ -927,6 +255,18 @@ 0 0 + + 2 + 6 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + cpuport.c + 0 + 0 + @@ -936,8 +276,8 @@ 0 0 - 6 - 60 + 3 + 7 1 0 0 @@ -948,8 +288,8 @@ 0 - 6 - 61 + 3 + 8 1 0 0 @@ -960,56 +300,20 @@ 0 - 6 - 62 + 3 + 9 1 0 0 0 - ..\..\..\components\drivers\src\completion.c - completion.c + ..\..\..\components\drivers\src\workqueue.c + workqueue.c 0 0 - 6 - 63 - 1 - 0 - 0 - 0 - ..\..\..\components\drivers\src\dataqueue.c - dataqueue.c - 0 - 0 - - - 6 - 64 - 1 - 0 - 0 - 0 - ..\..\..\components\drivers\src\pipe.c - pipe.c - 0 - 0 - - - 6 - 65 - 1 - 0 - 0 - 0 - ..\..\..\components\drivers\src\ringblk_buf.c - ringblk_buf.c - 0 - 0 - - - 6 - 66 + 3 + 10 1 0 0 @@ -1020,8 +324,8 @@ 0 - 6 - 67 + 3 + 11 1 0 0 @@ -1032,14 +336,94 @@ 0 - 6 - 68 + 3 + 12 1 0 0 0 - ..\..\..\components\drivers\src\workqueue.c - workqueue.c + ..\..\..\components\drivers\src\completion.c + completion.c + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\dataqueue.c + dataqueue.c + 0 + 0 + + + 3 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + 3 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\pipe.c + pipe.c + 0 + 0 + + + + + Drivers + 0 + 0 + 0 + 0 + + 4 + 16 + 1 + 0 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + 4 + 17 + 1 + 0 + 0 + 0 + ..\libraries\drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 4 + 18 + 1 + 0 + 0 + 0 + ..\libraries\drivers\drv_uart.c + drv_uart.c 0 0 @@ -1052,8 +436,8 @@ 0 0 - 7 - 69 + 5 + 19 1 0 0 @@ -1064,8 +448,20 @@ 0 - 7 - 70 + 5 + 20 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 5 + 21 1 0 0 @@ -1075,6 +471,610 @@ 0 0 + + + + Kernel + 0 + 0 + 0 + 0 + + 6 + 22 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 6 + 23 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 6 + 24 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 6 + 25 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 6 + 26 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 6 + 27 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + 6 + 28 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 6 + 29 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 6 + 30 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 6 + 31 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 6 + 32 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 6 + 33 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 6 + 34 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + + + nrfx + 0 + 0 + 0 + 0 + + 7 + 35 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_ppi.c + nrfx_ppi.c + 0 + 0 + + + 7 + 36 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_twim.c + nrfx_twim.c + 0 + 0 + + + 7 + 37 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_temp.c + nrfx_temp.c + 0 + 0 + + + 7 + 38 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_rng.c + nrfx_rng.c + 0 + 0 + + + 7 + 39 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_twi.c + nrfx_twi.c + 0 + 0 + + + 7 + 40 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_spis.c + nrfx_spis.c + 0 + 0 + + + 7 + 41 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_nfct.c + nrfx_nfct.c + 0 + 0 + + + 7 + 42 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_usbd.c + nrfx_usbd.c + 0 + 0 + + + 7 + 43 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_pwm.c + nrfx_pwm.c + 0 + 0 + + + 7 + 44 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_egu.c + nrfx_egu.c + 0 + 0 + + + 7 + 45 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_adc.c + nrfx_adc.c + 0 + 0 + + + 7 + 46 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_uarte.c + nrfx_uarte.c + 0 + 0 + + + 7 + 47 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_clock.c + nrfx_clock.c + 0 + 0 + + + 7 + 48 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_pdm.c + nrfx_pdm.c + 0 + 0 + + + 7 + 49 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_rtc.c + nrfx_rtc.c + 0 + 0 + + + 7 + 50 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_dppi.c + nrfx_dppi.c + 0 + 0 + + + 7 + 51 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_twis.c + nrfx_twis.c + 0 + 0 + + + 7 + 52 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_ipc.c + nrfx_ipc.c + 0 + 0 + + + 7 + 53 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_timer.c + nrfx_timer.c + 0 + 0 + + + 7 + 54 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_nvmc.c + nrfx_nvmc.c + 0 + 0 + + + 7 + 55 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_comp.c + nrfx_comp.c + 0 + 0 + + + 7 + 56 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_systick.c + nrfx_systick.c + 0 + 0 + + + 7 + 57 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_usbreg.c + nrfx_usbreg.c + 0 + 0 + + + 7 + 58 + 2 + 0 + 0 + 0 + packages\nrfx-latest\mdk\arm_startup_nrf52840.s + arm_startup_nrf52840.s + 0 + 0 + + + 7 + 59 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_saadc.c + nrfx_saadc.c + 0 + 0 + + + 7 + 60 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_wdt.c + nrfx_wdt.c + 0 + 0 + + + 7 + 61 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_gpiote.c + nrfx_gpiote.c + 0 + 0 + + + 7 + 62 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_spi.c + nrfx_spi.c + 0 + 0 + + + 7 + 63 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_twi_twim.c + nrfx_twi_twim.c + 0 + 0 + + + 7 + 64 + 1 + 0 + 0 + 0 + packages\nrfx-latest\mdk\system_nrf52840.c + system_nrf52840.c + 0 + 0 + + + 7 + 65 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_lpcomp.c + nrfx_lpcomp.c + 0 + 0 + + + 7 + 66 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_qdec.c + nrfx_qdec.c + 0 + 0 + + + 7 + 67 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_power.c + nrfx_power.c + 0 + 0 + + + 7 + 68 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_uart.c + nrfx_uart.c + 0 + 0 + + + 7 + 69 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_i2s.c + nrfx_i2s.c + 0 + 0 + + + 7 + 70 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_spim.c + nrfx_spim.c + 0 + 0 + 7 71 @@ -1082,64 +1082,8 @@ 0 0 0 - ..\..\..\components\finsh\msh.c - msh.c - 0 - 0 - - - - - libc - 0 - 0 - 0 - 0 - - 8 - 72 - 1 - 0 - 0 - 0 - ..\..\..\components\libc\compilers\armlibc\libc.c - libc.c - 0 - 0 - - - 8 - 73 - 1 - 0 - 0 - 0 - ..\..\..\components\libc\compilers\armlibc\mem_std.c - mem_std.c - 0 - 0 - - - 8 - 74 - 1 - 0 - 0 - 0 - ..\..\..\components\libc\compilers\armlibc\stubs.c - stubs.c - 0 - 0 - - - 8 - 75 - 1 - 0 - 0 - 0 - ..\..\..\components\libc\compilers\common\time.c - time.c + packages\nrfx-latest\drivers\src\nrfx_qspi.c + nrfx_qspi.c 0 0 diff --git a/bsp/nrf5x/nrf52840/project.uvprojx b/bsp/nrf5x/nrf52840/project.uvprojx index b1bf5b73cf..be44fa7a0c 100644 --- a/bsp/nrf5x/nrf52840/project.uvprojx +++ b/bsp/nrf5x/nrf52840/project.uvprojx @@ -10,13 +10,13 @@ rtthread 0x4 ARM-ADS - 5060750::V5.06 update 6 (build 750)::ARMCC + 5060960::V5.06 update 7 (build 960)::ARMCC 0 nRF52840_xxAA Nordic Semiconductor - NordicSemiconductor.nRF_DeviceFamilyPack.8.32.1 + NordicSemiconductor.nRF_DeviceFamilyPack.8.38.0 http://developer.nordicsemi.com/nRF5_SDK/pieces/nRF_DeviceFamilyPack/ IRAM(0x20000000,0x40000) IROM(0x00000000,0x100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE @@ -185,6 +185,7 @@ 0 2 0 + 0 0 0 8 @@ -336,9 +337,9 @@ 0 --reduce_paths - NRF52840_XXAA, USE_APP_CONFIG, RT_USING_ARM_LIBC + NRF52840_XXAA, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND - .;..\..\..\include;applications;.;board;..\libraries\drivers;packages\nrfx-v2.1.0;packages\nrfx-v2.1.0\drivers;packages\nrfx-v2.1.0\drivers\include;packages\nrfx-v2.1.0\mdk;packages\nrfx-v2.1.0\hal;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\finsh;..\..\..\components\libc\compilers\armlibc;..\..\..\components\libc\compilers\common;..\libraries\cmsis\include + applications;.;..\libraries\cmsis\include;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\none-gcc;packages\nrfx-latest;packages\nrfx-latest\drivers;packages\nrfx-latest\drivers\include;packages\nrfx-latest\mdk;packages\nrfx-latest\hal;..\..\..\examples\utest\testcases\kernel @@ -351,16 +352,16 @@ 0 0 0 - 0 + 4 - --cpreproc_opts=-DBLE_STACK_SUPPORT_REQD,-DNRF_SD_BLE_API_VERSION=4,-DS132,-DSOFTDEVICE_PRESENT,-DSWI_DISABLE0,-DCONFIG_GPIO_AS_PINRESET,-DNRF52,-DNRF52832_XXAA,-DNRF52_PAN_12,-DNRF52_PAN_15,-DNRF52_PAN_20,-DNRF52_PAN_31,-DNRF52_PAN_36,-DNRF52_PAN_51,-DNRF52_PAN_54,-DNRF52_PAN_55,-DNRF52_PAN_58,-DNRF52_PAN_64,-DNRF52_PAN_74 + - 1 + 0 0 0 0 @@ -369,7 +370,7 @@ 0x00000000 0x20000000 - + .\board\linker_scripts\link.sct @@ -379,81 +380,6 @@ - - Kernel - - - clock.c - 1 - ..\..\..\src\clock.c - - - components.c - 1 - ..\..\..\src\components.c - - - device.c - 1 - ..\..\..\src\device.c - - - idle.c - 1 - ..\..\..\src\idle.c - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - irq.c - 1 - ..\..\..\src\irq.c - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - mem.c - 1 - ..\..\..\src\mem.c - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - object.c - 1 - ..\..\..\src\object.c - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - signal.c - 1 - ..\..\..\src\signal.c - - - thread.c - 1 - ..\..\..\src\thread.c - - - timer.c - 1 - ..\..\..\src\timer.c - - - Applications @@ -465,218 +391,8 @@ - Drivers + CPU - - board.c - 1 - board\board.c - - - drv_uart.c - 1 - ..\libraries\drivers\drv_uart.c - - - - - nrfx - - - nrfx_adc.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_adc.c - - - nrfx_clock.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_clock.c - - - nrfx_comp.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_comp.c - - - nrfx_dppi.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_dppi.c - - - nrfx_egu.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_egu.c - - - nrfx_gpiote.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_gpiote.c - - - nrfx_i2s.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_i2s.c - - - nrfx_ipc.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_ipc.c - - - nrfx_lpcomp.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_lpcomp.c - - - nrfx_nfct.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_nfct.c - - - nrfx_nvmc.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_nvmc.c - - - nrfx_pdm.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_pdm.c - - - nrfx_power.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_power.c - - - nrfx_ppi.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_ppi.c - - - nrfx_pwm.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_pwm.c - - - nrfx_qdec.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_qdec.c - - - nrfx_qspi.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_qspi.c - - - nrfx_rng.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_rng.c - - - nrfx_rtc.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_rtc.c - - - nrfx_saadc.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_saadc.c - - - nrfx_spi.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_spi.c - - - nrfx_spim.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_spim.c - - - nrfx_spis.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_spis.c - - - nrfx_systick.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_systick.c - - - nrfx_temp.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_temp.c - - - nrfx_timer.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_timer.c - - - nrfx_twi.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_twi.c - - - nrfx_twi_twim.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_twi_twim.c - - - nrfx_twim.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_twim.c - - - nrfx_twis.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_twis.c - - - nrfx_uart.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_uart.c - - - nrfx_uarte.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_uarte.c - - - nrfx_usbd.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_usbd.c - - - nrfx_usbreg.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_usbreg.c - - - nrfx_wdt.c - 1 - packages\nrfx-v2.1.0\drivers\src\nrfx_wdt.c - - - system_nrf52840.c - 1 - packages\nrfx-v2.1.0\mdk\system_nrf52840.c - - - arm_startup_nrf52840.s - 2 - packages\nrfx-v2.1.0\mdk\arm_startup_nrf52840.s - - - - - cpu - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - div0.c 1 @@ -688,15 +404,20 @@ ..\..\..\libcpu\arm\common\showmem.c - cpuport.c + backtrace.c 1 - ..\..\..\libcpu\arm\cortex-m4\cpuport.c + ..\..\..\libcpu\arm\common\backtrace.c context_rvds.S 2 ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + @@ -713,24 +434,9 @@ ..\..\..\components\drivers\serial\serial.c - completion.c + workqueue.c 1 - ..\..\..\components\drivers\src\completion.c - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c + ..\..\..\components\drivers\src\workqueue.c ringbuffer.c @@ -743,9 +449,44 @@ ..\..\..\components\drivers\src\waitqueue.c - workqueue.c + completion.c 1 - ..\..\..\components\drivers\src\workqueue.c + ..\..\..\components\drivers\src\completion.c + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + Drivers + + + board.c + 1 + board\board.c + + + drv_gpio.c + 1 + ..\libraries\drivers\drv_gpio.c + + + drv_uart.c + 1 + ..\libraries\drivers\drv_uart.c @@ -757,40 +498,275 @@ 1 ..\..\..\components\finsh\shell.c - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - msh.c 1 ..\..\..\components\finsh\msh.c + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + - libc + Kernel - libc.c + thread.c 1 - ..\..\..\components\libc\compilers\armlibc\libc.c + ..\..\..\src\thread.c - mem_std.c + ipc.c 1 - ..\..\..\components\libc\compilers\armlibc\mem_std.c + ..\..\..\src\ipc.c - stubs.c + device.c 1 - ..\..\..\components\libc\compilers\armlibc\stubs.c + ..\..\..\src\device.c - time.c + object.c 1 - ..\..\..\components\libc\compilers\common\time.c + ..\..\..\src\object.c + + + irq.c + 1 + ..\..\..\src\irq.c + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + clock.c + 1 + ..\..\..\src\clock.c + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + components.c + 1 + ..\..\..\src\components.c + + + mem.c + 1 + ..\..\..\src\mem.c + + + idle.c + 1 + ..\..\..\src\idle.c + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + nrfx + + + nrfx_ppi.c + 1 + packages\nrfx-latest\drivers\src\nrfx_ppi.c + + + nrfx_twim.c + 1 + packages\nrfx-latest\drivers\src\nrfx_twim.c + + + nrfx_temp.c + 1 + packages\nrfx-latest\drivers\src\nrfx_temp.c + + + nrfx_rng.c + 1 + packages\nrfx-latest\drivers\src\nrfx_rng.c + + + nrfx_twi.c + 1 + packages\nrfx-latest\drivers\src\nrfx_twi.c + + + nrfx_spis.c + 1 + packages\nrfx-latest\drivers\src\nrfx_spis.c + + + nrfx_nfct.c + 1 + packages\nrfx-latest\drivers\src\nrfx_nfct.c + + + nrfx_usbd.c + 1 + packages\nrfx-latest\drivers\src\nrfx_usbd.c + + + nrfx_pwm.c + 1 + packages\nrfx-latest\drivers\src\nrfx_pwm.c + + + nrfx_egu.c + 1 + packages\nrfx-latest\drivers\src\nrfx_egu.c + + + nrfx_adc.c + 1 + packages\nrfx-latest\drivers\src\nrfx_adc.c + + + nrfx_uarte.c + 1 + packages\nrfx-latest\drivers\src\nrfx_uarte.c + + + nrfx_clock.c + 1 + packages\nrfx-latest\drivers\src\nrfx_clock.c + + + nrfx_pdm.c + 1 + packages\nrfx-latest\drivers\src\nrfx_pdm.c + + + nrfx_rtc.c + 1 + packages\nrfx-latest\drivers\src\nrfx_rtc.c + + + nrfx_dppi.c + 1 + packages\nrfx-latest\drivers\src\nrfx_dppi.c + + + nrfx_twis.c + 1 + packages\nrfx-latest\drivers\src\nrfx_twis.c + + + nrfx_ipc.c + 1 + packages\nrfx-latest\drivers\src\nrfx_ipc.c + + + nrfx_timer.c + 1 + packages\nrfx-latest\drivers\src\nrfx_timer.c + + + nrfx_nvmc.c + 1 + packages\nrfx-latest\drivers\src\nrfx_nvmc.c + + + nrfx_comp.c + 1 + packages\nrfx-latest\drivers\src\nrfx_comp.c + + + nrfx_systick.c + 1 + packages\nrfx-latest\drivers\src\nrfx_systick.c + + + nrfx_usbreg.c + 1 + packages\nrfx-latest\drivers\src\nrfx_usbreg.c + + + arm_startup_nrf52840.s + 2 + packages\nrfx-latest\mdk\arm_startup_nrf52840.s + + + nrfx_saadc.c + 1 + packages\nrfx-latest\drivers\src\nrfx_saadc.c + + + nrfx_wdt.c + 1 + packages\nrfx-latest\drivers\src\nrfx_wdt.c + + + nrfx_gpiote.c + 1 + packages\nrfx-latest\drivers\src\nrfx_gpiote.c + + + nrfx_spi.c + 1 + packages\nrfx-latest\drivers\src\nrfx_spi.c + + + nrfx_twi_twim.c + 1 + packages\nrfx-latest\drivers\src\nrfx_twi_twim.c + + + system_nrf52840.c + 1 + packages\nrfx-latest\mdk\system_nrf52840.c + + + nrfx_lpcomp.c + 1 + packages\nrfx-latest\drivers\src\nrfx_lpcomp.c + + + nrfx_qdec.c + 1 + packages\nrfx-latest\drivers\src\nrfx_qdec.c + + + nrfx_power.c + 1 + packages\nrfx-latest\drivers\src\nrfx_power.c + + + nrfx_uart.c + 1 + packages\nrfx-latest\drivers\src\nrfx_uart.c + + + nrfx_i2s.c + 1 + packages\nrfx-latest\drivers\src\nrfx_i2s.c + + + nrfx_spim.c + 1 + packages\nrfx-latest\drivers\src\nrfx_spim.c + + + nrfx_qspi.c + 1 + packages\nrfx-latest\drivers\src\nrfx_qspi.c diff --git a/bsp/nrf5x/nrf52840/rtconfig.h b/bsp/nrf5x/nrf52840/rtconfig.h index d821014dab..7b387a4444 100644 --- a/bsp/nrf5x/nrf52840/rtconfig.h +++ b/bsp/nrf5x/nrf52840/rtconfig.h @@ -151,7 +151,7 @@ /* peripheral libraries and drivers */ #define PKG_USING_NRFX -#define PKG_USING_NRFX_V210 +#define PKG_USING_NRFX_LATEST_VERSION /* AI packages */ @@ -168,24 +168,15 @@ /* Hardware Drivers Config */ #define SOC_NRF52840 -#define NRFX_CLOCK_ENABLED 1 -#define NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY 7 -#define NRFX_CLOCK_CONFIG_LF_SRC 1 #define SOC_NORDIC - -/* Onboard Peripheral Drivers */ - -#define BSP_USING_JLINK_TO_USART +#define BSP_BOARD_PCA_10056 /* On-chip Peripheral Drivers */ #define BSP_USING_GPIO #define NRFX_GPIOTE_ENABLED 1 #define BSP_USING_UART -#define NRFX_USING_UART -#define NRFX_UART_ENABLED 1 #define BSP_USING_UART0 -#define NRFX_UART0_ENABLED 1 #define BSP_UART0_RX_PIN 8 #define BSP_UART0_TX_PIN 6 @@ -196,6 +187,11 @@ #define MCU_SRAM_START_ADDRESS 0x20000000 #define MCU_SRAM_SIZE_KB 256 #define MCU_FLASH_PAGE_SIZE 0x1000 -#define BLE_STACK_USING_NULL +#define NRFX_CLOCK_ENABLED 1 +#define NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#define NRFX_CLOCK_CONFIG_LF_SRC 1 +#define NRFX_USING_UART +#define NRFX_UART_ENABLED 1 +#define NRFX_UART0_ENABLED 1 #endif diff --git a/bsp/nrf5x/nrf52840/rtconfig.py b/bsp/nrf5x/nrf52840/rtconfig.py index 4ef29e332f..c809814516 100644 --- a/bsp/nrf5x/nrf52840/rtconfig.py +++ b/bsp/nrf5x/nrf52840/rtconfig.py @@ -40,7 +40,7 @@ if PLATFORM == 'gcc': OBJDUMP = PREFIX + 'objdump' OBJCPY = PREFIX + 'objcopy' - DEVICE = ' -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections' + DEVICE = ' -mcpu='+CPU + ' -mthumb -ffunction-sections -fdata-sections' CFLAGS = DEVICE AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp' LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.lds' diff --git a/bsp/nrf5x/nrf52840/template.uvoptx b/bsp/nrf5x/nrf52840/template.uvoptx index f567bf47e8..94da3c0c18 100644 --- a/bsp/nrf5x/nrf52840/template.uvoptx +++ b/bsp/nrf5x/nrf52840/template.uvoptx @@ -10,7 +10,7 @@ *.s*; *.src; *.a* *.obj; *.o *.lib - *.txt; *.h; *.inc + *.txt; *.h; *.inc; *.md *.plm *.cpp 0 diff --git a/bsp/nrf5x/nrf52840/template.uvprojx b/bsp/nrf5x/nrf52840/template.uvprojx index 62c5997a13..33ed1f7c16 100644 --- a/bsp/nrf5x/nrf52840/template.uvprojx +++ b/bsp/nrf5x/nrf52840/template.uvprojx @@ -16,7 +16,7 @@ nRF52840_xxAA Nordic Semiconductor - NordicSemiconductor.nRF_DeviceFamilyPack.8.32.1 + NordicSemiconductor.nRF_DeviceFamilyPack.8.38.0 http://developer.nordicsemi.com/nRF5_SDK/pieces/nRF_DeviceFamilyPack/ IRAM(0x20000000,0x40000) IROM(0x00000000,0x100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE @@ -185,6 +185,7 @@ 0 2 0 + 0 0 0 8 @@ -336,7 +337,7 @@ 0 --reduce_paths - BLE_STACK_SUPPORT_REQD NRF_SD_BLE_API_VERSION=4 S140 SOFTDEVICE_PRESENT SWI_DISABLE0 CONFIG_GPIO_AS_PINRESET NRF52 NRF52832_XXAA NRF52_PAN_12 NRF52_PAN_15 NRF52_PAN_20 NRF52_PAN_31 NRF52_PAN_36 NRF52_PAN_51 NRF52_PAN_54 NRF52_PAN_55 NRF52_PAN_58 NRF52_PAN_64 NRF52_PAN_74 + @@ -351,16 +352,16 @@ 0 0 0 - 0 + 4 - --cpreproc_opts=-DBLE_STACK_SUPPORT_REQD,-DNRF_SD_BLE_API_VERSION=4,-DS132,-DSOFTDEVICE_PRESENT,-DSWI_DISABLE0,-DCONFIG_GPIO_AS_PINRESET,-DNRF52,-DNRF52832_XXAA,-DNRF52_PAN_12,-DNRF52_PAN_15,-DNRF52_PAN_20,-DNRF52_PAN_31,-DNRF52_PAN_36,-DNRF52_PAN_51,-DNRF52_PAN_54,-DNRF52_PAN_55,-DNRF52_PAN_58,-DNRF52_PAN_64,-DNRF52_PAN_74 + - 1 + 0 0 0 0 @@ -369,7 +370,7 @@ 0x00000000 0x20000000 - + .\board\linker_scripts\link.sct --diag_suppress 6330 From 19ec36bc6ef096cc161f67341857487788464c85 Mon Sep 17 00:00:00 2001 From: supperthomas <78900636@qq.com> Date: Sat, 26 Jun 2021 07:03:45 +0800 Subject: [PATCH 198/255] rebuild the Kconfig --- bsp/nrf5x/nrf52840/.config | 44 +- bsp/nrf5x/nrf52840/board/Kconfig | 511 ++++++++------- bsp/nrf5x/nrf52840/project.uvoptx | 974 ++++++++++++++++------------- bsp/nrf5x/nrf52840/project.uvprojx | 364 ++++++----- bsp/nrf5x/nrf52840/rtconfig.h | 16 +- 5 files changed, 1081 insertions(+), 828 deletions(-) diff --git a/bsp/nrf5x/nrf52840/.config b/bsp/nrf5x/nrf52840/.config index f9c63e767c..9612d30606 100644 --- a/bsp/nrf5x/nrf52840/.config +++ b/bsp/nrf5x/nrf52840/.config @@ -15,7 +15,7 @@ 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_OVERFLOW_CHECK is not set CONFIG_RT_USING_HOOK=y CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 @@ -29,18 +29,7 @@ CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 # # 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 is not set -# CONFIG_RT_DEBUG_INIT_CONFIG is not set -# CONFIG_RT_DEBUG_THREAD_CONFIG is not set -# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set -# CONFIG_RT_DEBUG_IPC_CONFIG is not set -# CONFIG_RT_DEBUG_TIMER_CONFIG is not set -# CONFIG_RT_DEBUG_IRQ_CONFIG is not set -# CONFIG_RT_DEBUG_MEM_CONFIG is not set -# CONFIG_RT_DEBUG_SLAB_CONFIG is not set -# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set -# CONFIG_RT_DEBUG_MODULE_CONFIG is not set +# CONFIG_RT_DEBUG is not set # # Inter-Thread communication @@ -48,8 +37,8 @@ CONFIG_RT_DEBUG=y 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_MAILBOX is not set +# CONFIG_RT_USING_MESSAGEQUEUE is not set # CONFIG_RT_USING_SIGNALS is not set # @@ -106,7 +95,7 @@ CONFIG_FINSH_CMD_SIZE=80 # CONFIG_FINSH_USING_AUTH is not set CONFIG_FINSH_USING_MSH=y CONFIG_FINSH_USING_MSH_DEFAULT=y -CONFIG_FINSH_USING_MSH_ONLY=y +# CONFIG_FINSH_USING_MSH_ONLY is not set CONFIG_FINSH_ARG_MAX=10 # @@ -560,27 +549,44 @@ CONFIG_SOC_NRF52840=y CONFIG_SOC_NORDIC=y CONFIG_BSP_BOARD_PCA_10056=y +# +# Onboard Peripheral Drivers +# +CONFIG_BSP_USING_JLINK_TO_USART=y +# CONFIG_BSP_USING_QSPI_FLASH is not set + # # On-chip Peripheral Drivers # CONFIG_BSP_USING_GPIO=y -CONFIG_NRFX_GPIOTE_ENABLED=1 CONFIG_BSP_USING_UART=y +CONFIG_NRFX_USING_UART=y +# CONFIG_NRFX_USING_UARTE is not set CONFIG_BSP_USING_UART0=y CONFIG_BSP_UART0_RX_PIN=8 CONFIG_BSP_UART0_TX_PIN=6 +# CONFIG_BSP_USING_SAADC is not set +# CONFIG_BSP_USING_I2C is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_PWM is not set +# CONFIG_BSP_USING_WDT is not set +# CONFIG_BSP_USING_ONCHIP_RTC is not set +# CONFIG_BSP_USING_ON_CHIP_FLASH is not set # -# On-chip flash config +# MCU flash config # CONFIG_MCU_FLASH_START_ADDRESS=0x00000000 CONFIG_MCU_FLASH_SIZE_KB=1024 CONFIG_MCU_SRAM_START_ADDRESS=0x20000000 CONFIG_MCU_SRAM_SIZE_KB=256 CONFIG_MCU_FLASH_PAGE_SIZE=0x1000 +CONFIG_BLE_STACK_USING_NULL=y +# CONFIG_BSP_USING_SOFTDEVICE is not set +# CONFIG_BSP_USING_NIMBLE is not set CONFIG_NRFX_CLOCK_ENABLED=1 CONFIG_NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY=7 CONFIG_NRFX_CLOCK_CONFIG_LF_SRC=1 -CONFIG_NRFX_USING_UART=y CONFIG_NRFX_UART_ENABLED=1 CONFIG_NRFX_UART0_ENABLED=1 +CONFIG_NRFX_GPIOTE_ENABLED=1 diff --git a/bsp/nrf5x/nrf52840/board/Kconfig b/bsp/nrf5x/nrf52840/board/Kconfig index 71e7595048..8a2fe7d49d 100644 --- a/bsp/nrf5x/nrf52840/board/Kconfig +++ b/bsp/nrf5x/nrf52840/board/Kconfig @@ -2,31 +2,26 @@ menu "Hardware Drivers Config" config SOC_NRF52840 bool - config SOC_NRF52840 select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN default y - config NRFX_CLOCK_ENABLED - int - default 1 - config NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY - int - default 7 - config NRFX_CLOCK_CONFIG_LF_SRC - int - default 1 - config SOC_NORDIC bool - config SOC_NORDIC default y +choice + prompt "Select BSP board " + default BSP_BOARD_PCA_10056 + + config BSP_BOARD_PCA_10056 + bool "NRF52840 pca10056 " + +endchoice + menu "Onboard Peripheral Drivers" config BSP_USING_JLINK_TO_USART bool "Enable JLINK TO USART (uart0|RX_PIN:8|TX_PIN:6)" - select BSP_USING_UART - select BSP_USING_UART0 default y menuconfig BSP_USING_QSPI_FLASH @@ -68,135 +63,17 @@ menu "Onboard Peripheral Drivers" endif endmenu + menu "On-chip Peripheral Drivers" + config BSP_USING_GPIO bool "Enable GPIO" select RT_USING_PIN default y - if BSP_USING_GPIO - config NRFX_GPIOTE_ENABLED - int - default 1 - endif - config BSP_USING_SAADC - bool "Enable SAADC" - select RT_USING_ADC - default n - if BSP_USING_SAADC - config NRFX_SAADC_ENABLED - int - default 1 - endif - menuconfig BSP_USING_PWM - bool "Enable PWM" - select RT_USING_PWM - default n - if BSP_USING_PWM - config NRFX_PWM_ENABLED - int - default 1 - config BSP_USING_PWM0 - bool "Enable PWM0 bus" - default y - if BSP_USING_PWM0 - config NRFX_PWM0_ENABLED - int - default 1 - config BSP_USING_PWM0_CH0 - int "PWM0 channel 0 pin number set" - range 0 47 - default 13 - config BSP_USING_PWM0_CH1 - int "PWM0 channel 1 pin number set" - range 0 47 - default 14 - config BSP_USING_PWM0_CH2 - int "PWM0 channel 2 pin number set" - range 0 47 - default 15 - config BSP_USING_PWM0_CH3 - int "PWM0 channel 3 pin number set" - range 0 47 - default 16 - endif - config BSP_USING_PWM1 - bool "Enable PWM1 bus" - default n - if BSP_USING_PWM1 - config NRFX_PWM1_ENABLED - int - default 1 - config BSP_USING_PWM1_CH0 - int "PWM1 channel 0 pin number set" - range 0 47 - default 13 - config BSP_USING_PWM1_CH1 - int "PWM1 channel 1 pin number set" - range 0 47 - default 14 - config BSP_USING_PWM1_CH2 - int "PWM1 channel 2 pin number set" - range 0 47 - default 15 - config BSP_USING_PWM1_CH3 - int "PWM1 channel 3 pin number set" - range 0 47 - default 16 - endif - config BSP_USING_PWM2 - bool "Enable PWM2 bus" - default n - if BSP_USING_PWM2 - config NRFX_PWM2_ENABLED - int - default 1 - config BSP_USING_PWM2_CH0 - int "PWM2 channel 0 pin number set" - range 0 47 - default 13 - config BSP_USING_PWM2_CH1 - int "PWM2 channel 1 pin number set" - range 0 47 - default 14 - config BSP_USING_PWM2_CH2 - int "PWM2 channel 2 pin number set" - range 0 47 - default 15 - config BSP_USING_PWM2_CH3 - int "PWM2 channel 3 pin number set" - range 0 47 - default 16 - endif - config BSP_USING_PWM3 - bool "Enable PWM3 bus" - default n - if BSP_USING_PWM3 - config NRFX_PWM3_ENABLED - int - default 1 - config BSP_USING_PWM3_CH0 - int "PWM3 channel 0 pin number set" - range 0 47 - default 13 - config BSP_USING_PWM3_CH1 - int "PWM3 channel 1 pin number set" - range 0 47 - default 14 - config BSP_USING_PWM3_CH2 - int "PWM3 channel 2 pin number set" - range 0 47 - default 15 - config BSP_USING_PWM3_CH3 - int "PWM3 channel 3 pin number set" - range 0 47 - default 16 - endif - endif - config BSP_USING_UART bool "Enable UART" - default y + default n select RT_USING_SERIAL if BSP_USING_UART choice @@ -212,17 +89,12 @@ menu "On-chip Peripheral Drivers" endchoice endif if BSP_USING_UART&&NRFX_USING_UART - config NRFX_UART_ENABLED - int - default 1 + config BSP_USING_UART0 bool "Enable UART0" default y if BSP_USING_UART0 - config NRFX_UART0_ENABLED - int - default 1 config BSP_UART0_RX_PIN int "uart0 rx pin number" range 0 31 @@ -271,21 +143,21 @@ menu "On-chip Peripheral Drivers" default 5 endif endif - config BSP_USING_I2C + + config BSP_USING_SAADC + bool "Enable ADC" + select RT_USING_ADC + default n + + menuconfig BSP_USING_I2C bool "Enable I2C" select RT_USING_I2C default n if BSP_USING_I2C - config NRFX_TWIM_ENABLED - int - default 1 config BSP_USING_I2C0 bool "Enable I2C0 bus" - default n + default y if BSP_USING_I2C0 - config NRFX_TWIM0_ENABLED - int - default 1 config BSP_I2C0_SCL_PIN int "i2c0 scl pin number" range 0 31 @@ -299,9 +171,6 @@ menu "On-chip Peripheral Drivers" bool "Enable I2C1 bus" default n if BSP_USING_I2C1 - config NRFX_TWIM1_ENABLED - int - default 1 config BSP_I2C1_SCL_PIN int "i2c1 scl pin number" range 0 31 @@ -312,15 +181,13 @@ menu "On-chip Peripheral Drivers" default 2 endif endif - config BSP_USING_SPI + + menuconfig BSP_USING_SPI bool "Enable SPI" select RT_USING_SPI default n if BSP_USING_SPI - config NRFX_SPI_ENABLED - int - default 1 config BSP_USING_SPI0 bool "Enable SPI0 bus" default y @@ -350,9 +217,6 @@ menu "On-chip Peripheral Drivers" bool "Enable SPI1 bus" default n if BSP_USING_SPI1 - config NRFX_SPI1_ENABLED - int "Enable SPI1 instance" - default 1 config BSP_SPI1_SCK_PIN int "SPI0 sck pin number set" range 0 47 @@ -375,9 +239,6 @@ menu "On-chip Peripheral Drivers" bool "Enable SPI2 bus" default n if BSP_USING_SPI2 - config NRFX_SPI2_ENABLED - int "Enable SPI2 instance" - default 1 config BSP_SPI2_SCK_PIN int "SPI0 sck pin number set" range 0 47 @@ -397,12 +258,119 @@ menu "On-chip Peripheral Drivers" endif endif + + menuconfig BSP_USING_PWM + bool "Enable PWM" + select RT_USING_PWM + default n + if BSP_USING_PWM + config BSP_USING_PWM0 + bool "Enable PWM0 bus" + default y + if BSP_USING_PWM0 + config BSP_USING_PWM0_CH0 + int "PWM0 channel 0 pin number set" + range 0 47 + default 13 + config BSP_USING_PWM0_CH1 + int "PWM0 channel 1 pin number set" + range 0 47 + default 14 + config BSP_USING_PWM0_CH2 + int "PWM0 channel 2 pin number set" + range 0 47 + default 15 + config BSP_USING_PWM0_CH3 + int "PWM0 channel 3 pin number set" + range 0 47 + default 16 + endif + config BSP_USING_PWM1 + bool "Enable PWM1 bus" + default n + if BSP_USING_PWM1 + config NRFX_PWM1_ENABLED + int + default 1 + config BSP_USING_PWM1_CH0 + int "PWM1 channel 0 pin number set" + range 0 47 + default 13 + config BSP_USING_PWM1_CH1 + int "PWM1 channel 1 pin number set" + range 0 47 + default 14 + config BSP_USING_PWM1_CH2 + int "PWM1 channel 2 pin number set" + range 0 47 + default 15 + config BSP_USING_PWM1_CH3 + int "PWM1 channel 3 pin number set" + range 0 47 + default 16 + endif + config BSP_USING_PWM2 + bool "Enable PWM2 bus" + default n + if BSP_USING_PWM2 + config BSP_USING_PWM2_CH0 + int "PWM2 channel 0 pin number set" + range 0 47 + default 13 + config BSP_USING_PWM2_CH1 + int "PWM2 channel 1 pin number set" + range 0 47 + default 14 + config BSP_USING_PWM2_CH2 + int "PWM2 channel 2 pin number set" + range 0 47 + default 15 + config BSP_USING_PWM2_CH3 + int "PWM2 channel 3 pin number set" + range 0 47 + default 16 + endif + config BSP_USING_PWM3 + bool "Enable PWM3 bus" + default n + if BSP_USING_PWM3 + config BSP_USING_PWM3_CH0 + int "PWM3 channel 0 pin number set" + range 0 47 + default 13 + config BSP_USING_PWM3_CH1 + int "PWM3 channel 1 pin number set" + range 0 47 + default 14 + config BSP_USING_PWM3_CH2 + int "PWM3 channel 2 pin number set" + range 0 47 + default 15 + config BSP_USING_PWM3_CH3 + int "PWM3 channel 3 pin number set" + range 0 47 + default 16 + endif + endif + + config BSP_USING_WDT + bool "Enable WDT" + select RT_USING_WDT + default n + + menuconfig BSP_USING_ONCHIP_RTC + bool "Enable RTC" + select RT_USING_RTC + select RT_USING_LIBC + default n + + config BSP_USING_ON_CHIP_FLASH select PKG_USING_FAL bool "Enable on-chip FLASH" default n - menu "On-chip flash config" + menu "MCU flash config" config MCU_FLASH_START_ADDRESS hex "MCU FLASH START ADDRESS" @@ -410,71 +378,20 @@ menu "On-chip Peripheral Drivers" config MCU_FLASH_SIZE_KB int "MCU FLASH SIZE, MAX size 1024 KB" - range 1 1024 - default 1024 + default 1024 config MCU_SRAM_START_ADDRESS hex "MCU RAM START ADDRESS" default 0x20000000 - config MCU_SRAM_SIZE_KB - int "MCU RAM SIZE, MAX size 256 KB" - range 1 256 + config MCU_SRAM_SIZE_KB + int "MCU RAM SIZE" default 256 config MCU_FLASH_PAGE_SIZE hex "MCU FLASH PAGE SIZE, please not change,nrfx default is 0x1000" - range 0x1000 0x1000 default 0x1000 endmenu - config BSP_USING_WDT - bool "Enable WDT" - select RT_USING_WDT - default n - if BSP_USING_WDT - config NRFX_WDT_ENABLED - int - default 1 - config NRFX_WDT0_ENABLED - int - default 1 - config NRFX_WDT_CONFIG_NO_IRQ - int - default 1 - endif - - menuconfig BSP_USING_ONCHIP_RTC - bool "Enable RTC" - select RT_USING_RTC - select RT_USING_LIBC - default n - if BSP_USING_ONCHIP_RTC - config NRFX_CLOCK_ENABLED - int - default 1 - config NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY - int - default 7 - config NRFX_RTC_ENABLED - int - default 1 - config NRFX_RTC0_ENABLED - int - default 1 - config NRFX_RTC1_ENABLED - int - default 1 - config NRFX_RTC2_ENABLED - int - default 1 - config RTC_INSTANCE_ID - int - default 2 - config RTC_INSTANCE_ID - int "select RTC instance id, must be 0, 1, 2" - range 0 2 - default 2 - endif endmenu @@ -497,6 +414,166 @@ config BSP_USING_NIMBLE bool "use nimble stack(iot)" endchoice +if SOC_NORDIC + config NRFX_CLOCK_ENABLED + int + default 1 + config NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY + int + default 7 + config NRFX_CLOCK_CONFIG_LF_SRC + int + default 1 +endif + +if BSP_USING_UART + config NRFX_USING_UART + bool + default y + + config NRFX_UART_ENABLED + int + default 1 +if BSP_USING_UART0 + config NRFX_UART0_ENABLED + int + default 1 +endif + +if NRFX_USING_UART + config NRFX_UART_ENABLED + int + default 1 +endif + +if NRFX_USING_UARTE + config NRFX_UARTE0_ENABLED + int + default 1 +endif + + +endif + +if BSP_USING_GPIO + config NRFX_GPIOTE_ENABLED + int + default 1 +endif + +if BSP_USING_SAADC + config NRFX_SAADC_ENABLED + int + default 1 +endif + +if BSP_USING_I2C + config NRFX_TWIM_ENABLED + int + default 1 + if BSP_USING_I2C0 + config NRFX_TWIM0_ENABLED + int + default 1 + endif + + if BSP_USING_I2C1 + config NRFX_TWIM1_ENABLED + int + default 1 + endif +endif + +if BSP_USING_SPI + config NRFX_SPI_ENABLED + int + default 1 + + if BSP_USING_SPI0 + config NRFX_SPI0_ENABLED + int + default 1 + endif + + if BSP_USING_SPI1 + config NRFX_SPI1_ENABLED + int + default 1 + endif + + if BSP_USING_SPI2 + config NRFX_SPI2_ENABLED + int + default 1 + endif +endif + +if BSP_USING_PWM + config NRFX_PWM_ENABLED + int + default 1 + if BSP_USING_PWM0 + config NRFX_PWM0_ENABLED + int + default 1 + endif + if BSP_USING_PWM1 + config NRFX_PWM1_ENABLED + int + default 1 + endif + if BSP_USING_PWM2 + config NRFX_PWM2_ENABLED + int + default 1 + endif + if BSP_USING_PWM3 + config NRFX_PWM3_ENABLED + int + default 1 + endif + +endif + +if BSP_USING_WDT + config NRFX_WDT_ENABLED + int + default 1 + config NRFX_WDT0_ENABLED + int + default 1 + config NRFX_WDT_CONFIG_NO_IRQ + int + default 1 +endif + +if BSP_USING_ONCHIP_RTC + config NRFX_CLOCK_ENABLED + int + default 1 + config NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY + int + default 7 + config NRFX_RTC_ENABLED + int + default 1 + config NRFX_RTC0_ENABLED + int + default 1 + config NRFX_RTC1_ENABLED + int + default 1 + config NRFX_RTC2_ENABLED + int + default 1 + config RTC_INSTANCE_ID + int + default 2 + config RTC_INSTANCE_ID + int + range 0 2 + default 2 +endif endmenu diff --git a/bsp/nrf5x/nrf52840/project.uvoptx b/bsp/nrf5x/nrf52840/project.uvoptx index 376d1dc34b..232521460c 100644 --- a/bsp/nrf5x/nrf52840/project.uvoptx +++ b/bsp/nrf5x/nrf52840/project.uvoptx @@ -183,7 +183,7 @@ Applications - 0 + 1 0 0 0 @@ -214,8 +214,8 @@ 0 0 0 - ..\..\..\libcpu\arm\common\div0.c - div0.c + ..\..\..\libcpu\arm\common\backtrace.c + backtrace.c 0 0 @@ -238,8 +238,8 @@ 0 0 0 - ..\..\..\libcpu\arm\common\backtrace.c - backtrace.c + ..\..\..\libcpu\arm\common\div0.c + div0.c 0 0 @@ -306,8 +306,8 @@ 0 0 0 - ..\..\..\components\drivers\src\workqueue.c - workqueue.c + ..\..\..\components\drivers\src\waitqueue.c + waitqueue.c 0 0 @@ -318,8 +318,8 @@ 0 0 0 - ..\..\..\components\drivers\src\ringbuffer.c - ringbuffer.c + ..\..\..\components\drivers\src\workqueue.c + workqueue.c 0 0 @@ -330,18 +330,6 @@ 0 0 0 - ..\..\..\components\drivers\src\waitqueue.c - waitqueue.c - 0 - 0 - - - 3 - 12 - 1 - 0 - 0 - 0 ..\..\..\components\drivers\src\completion.c completion.c 0 @@ -349,7 +337,7 @@ 3 - 13 + 12 1 0 0 @@ -359,6 +347,18 @@ 0 0 + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringbuffer.c + ringbuffer.c + 0 + 0 + 3 14 @@ -387,7 +387,7 @@ Drivers - 0 + 1 0 0 0 @@ -442,8 +442,8 @@ 0 0 0 - ..\..\..\components\finsh\shell.c - shell.c + ..\..\..\components\finsh\finsh_node.c + finsh_node.c 0 0 @@ -454,8 +454,8 @@ 0 0 0 - ..\..\..\components\finsh\msh.c - msh.c + ..\..\..\components\finsh\finsh_parser.c + finsh_parser.c 0 0 @@ -471,6 +471,126 @@ 0 0 + + 5 + 22 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 5 + 23 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\finsh_vm.c + finsh_vm.c + 0 + 0 + + + 5 + 24 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 5 + 25 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\finsh_var.c + finsh_var.c + 0 + 0 + + + 5 + 26 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\finsh_compiler.c + finsh_compiler.c + 0 + 0 + + + 5 + 27 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\finsh_heap.c + finsh_heap.c + 0 + 0 + + + 5 + 28 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\finsh_ops.c + finsh_ops.c + 0 + 0 + + + 5 + 29 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\finsh_error.c + finsh_error.c + 0 + 0 + + + 5 + 30 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\finsh_token.c + finsh_token.c + 0 + 0 + + + 5 + 31 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\finsh_init.c + finsh_init.c + 0 + 0 + @@ -481,79 +601,7 @@ 0 6 - 22 - 1 - 0 - 0 - 0 - ..\..\..\src\thread.c - thread.c - 0 - 0 - - - 6 - 23 - 1 - 0 - 0 - 0 - ..\..\..\src\ipc.c - ipc.c - 0 - 0 - - - 6 - 24 - 1 - 0 - 0 - 0 - ..\..\..\src\device.c - device.c - 0 - 0 - - - 6 - 25 - 1 - 0 - 0 - 0 - ..\..\..\src\object.c - object.c - 0 - 0 - - - 6 - 26 - 1 - 0 - 0 - 0 - ..\..\..\src\irq.c - irq.c - 0 - 0 - - - 6 - 27 - 1 - 0 - 0 - 0 - ..\..\..\src\scheduler.c - scheduler.c - 0 - 0 - - - 6 - 28 + 32 1 0 0 @@ -565,7 +613,7 @@ 6 - 29 + 33 1 0 0 @@ -575,54 +623,6 @@ 0 0 - - 6 - 30 - 1 - 0 - 0 - 0 - ..\..\..\src\mempool.c - mempool.c - 0 - 0 - - - 6 - 31 - 1 - 0 - 0 - 0 - ..\..\..\src\components.c - components.c - 0 - 0 - - - 6 - 32 - 1 - 0 - 0 - 0 - ..\..\..\src\mem.c - mem.c - 0 - 0 - - - 6 - 33 - 1 - 0 - 0 - 0 - ..\..\..\src\idle.c - idle.c - 0 - 0 - 6 34 @@ -635,6 +635,126 @@ 0 0 + + 6 + 35 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + 6 + 36 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 6 + 37 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 6 + 38 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 6 + 39 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 6 + 40 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 6 + 41 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 6 + 42 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 6 + 43 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 6 + 44 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + @@ -645,67 +765,19 @@ 0 7 - 35 + 45 1 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_ppi.c - nrfx_ppi.c + packages\nrfx-latest\drivers\src\nrfx_qspi.c + nrfx_qspi.c 0 0 7 - 36 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_twim.c - nrfx_twim.c - 0 - 0 - - - 7 - 37 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_temp.c - nrfx_temp.c - 0 - 0 - - - 7 - 38 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_rng.c - nrfx_rng.c - 0 - 0 - - - 7 - 39 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_twi.c - nrfx_twi.c - 0 - 0 - - - 7 - 40 + 46 1 0 0 @@ -717,19 +789,7 @@ 7 - 41 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_nfct.c - nrfx_nfct.c - 0 - 0 - - - 7 - 42 + 47 1 0 0 @@ -741,31 +801,19 @@ 7 - 43 + 48 1 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_pwm.c - nrfx_pwm.c + packages\nrfx-latest\drivers\src\nrfx_qdec.c + nrfx_qdec.c 0 0 7 - 44 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_egu.c - nrfx_egu.c - 0 - 0 - - - 7 - 45 + 49 1 0 0 @@ -775,54 +823,6 @@ 0 0 - - 7 - 46 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_uarte.c - nrfx_uarte.c - 0 - 0 - - - 7 - 47 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_clock.c - nrfx_clock.c - 0 - 0 - - - 7 - 48 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_pdm.c - nrfx_pdm.c - 0 - 0 - - - 7 - 49 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_rtc.c - nrfx_rtc.c - 0 - 0 - 7 50 @@ -830,8 +830,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_dppi.c - nrfx_dppi.c + packages\nrfx-latest\drivers\src\nrfx_power.c + nrfx_power.c 0 0 @@ -842,8 +842,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_twis.c - nrfx_twis.c + packages\nrfx-latest\drivers\src\nrfx_egu.c + nrfx_egu.c 0 0 @@ -854,8 +854,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_ipc.c - nrfx_ipc.c + packages\nrfx-latest\drivers\src\nrfx_twim.c + nrfx_twim.c 0 0 @@ -866,8 +866,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_timer.c - nrfx_timer.c + packages\nrfx-latest\drivers\src\nrfx_nvmc.c + nrfx_nvmc.c 0 0 @@ -878,8 +878,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_nvmc.c - nrfx_nvmc.c + packages\nrfx-latest\drivers\src\nrfx_temp.c + nrfx_temp.c 0 0 @@ -902,8 +902,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_systick.c - nrfx_systick.c + packages\nrfx-latest\drivers\src\nrfx_dppi.c + nrfx_dppi.c 0 0 @@ -914,143 +914,143 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_usbreg.c - nrfx_usbreg.c - 0 - 0 - - - 7 - 58 - 2 - 0 - 0 - 0 - packages\nrfx-latest\mdk\arm_startup_nrf52840.s - arm_startup_nrf52840.s - 0 - 0 - - - 7 - 59 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_saadc.c - nrfx_saadc.c - 0 - 0 - - - 7 - 60 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_wdt.c - nrfx_wdt.c - 0 - 0 - - - 7 - 61 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_gpiote.c - nrfx_gpiote.c - 0 - 0 - - - 7 - 62 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_spi.c - nrfx_spi.c - 0 - 0 - - - 7 - 63 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_twi_twim.c - nrfx_twi_twim.c - 0 - 0 - - - 7 - 64 - 1 - 0 - 0 - 0 - packages\nrfx-latest\mdk\system_nrf52840.c - system_nrf52840.c - 0 - 0 - - - 7 - 65 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_lpcomp.c - nrfx_lpcomp.c - 0 - 0 - - - 7 - 66 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_qdec.c - nrfx_qdec.c - 0 - 0 - - - 7 - 67 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_power.c - nrfx_power.c - 0 - 0 - - - 7 - 68 - 1 - 0 - 0 - 0 packages\nrfx-latest\drivers\src\nrfx_uart.c nrfx_uart.c 0 0 + + 7 + 58 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_gpiote.c + nrfx_gpiote.c + 0 + 0 + + + 7 + 59 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_systick.c + nrfx_systick.c + 0 + 0 + + + 7 + 60 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_ipc.c + nrfx_ipc.c + 0 + 0 + + + 7 + 61 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_pwm.c + nrfx_pwm.c + 0 + 0 + + + 7 + 62 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_twi.c + nrfx_twi.c + 0 + 0 + + + 7 + 63 + 2 + 0 + 0 + 0 + packages\nrfx-latest\mdk\arm_startup_nrf52840.s + arm_startup_nrf52840.s + 0 + 0 + + + 7 + 64 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_rtc.c + nrfx_rtc.c + 0 + 0 + + + 7 + 65 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_twis.c + nrfx_twis.c + 0 + 0 + + + 7 + 66 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_nfct.c + nrfx_nfct.c + 0 + 0 + + + 7 + 67 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_usbreg.c + nrfx_usbreg.c + 0 + 0 + + + 7 + 68 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_rng.c + nrfx_rng.c + 0 + 0 + 7 69 @@ -1058,8 +1058,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_i2s.c - nrfx_i2s.c + packages\nrfx-latest\drivers\src\nrfx_wdt.c + nrfx_wdt.c 0 0 @@ -1070,6 +1070,90 @@ 0 0 0 + packages\nrfx-latest\drivers\src\nrfx_ppi.c + nrfx_ppi.c + 0 + 0 + + + 7 + 71 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_saadc.c + nrfx_saadc.c + 0 + 0 + + + 7 + 72 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_spi.c + nrfx_spi.c + 0 + 0 + + + 7 + 73 + 1 + 0 + 0 + 0 + packages\nrfx-latest\mdk\system_nrf52840.c + system_nrf52840.c + 0 + 0 + + + 7 + 74 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_lpcomp.c + nrfx_lpcomp.c + 0 + 0 + + + 7 + 75 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_twi_twim.c + nrfx_twi_twim.c + 0 + 0 + + + 7 + 76 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_clock.c + nrfx_clock.c + 0 + 0 + + + 7 + 77 + 1 + 0 + 0 + 0 packages\nrfx-latest\drivers\src\nrfx_spim.c nrfx_spim.c 0 @@ -1077,13 +1161,49 @@ 7 - 71 + 78 1 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_qspi.c - nrfx_qspi.c + packages\nrfx-latest\drivers\src\nrfx_i2s.c + nrfx_i2s.c + 0 + 0 + + + 7 + 79 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_uarte.c + nrfx_uarte.c + 0 + 0 + + + 7 + 80 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_pdm.c + nrfx_pdm.c + 0 + 0 + + + 7 + 81 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_timer.c + nrfx_timer.c 0 0 diff --git a/bsp/nrf5x/nrf52840/project.uvprojx b/bsp/nrf5x/nrf52840/project.uvprojx index be44fa7a0c..7646c98bf2 100644 --- a/bsp/nrf5x/nrf52840/project.uvprojx +++ b/bsp/nrf5x/nrf52840/project.uvprojx @@ -394,9 +394,9 @@ CPU - div0.c + backtrace.c 1 - ..\..\..\libcpu\arm\common\div0.c + ..\..\..\libcpu\arm\common\backtrace.c showmem.c @@ -404,9 +404,9 @@ ..\..\..\libcpu\arm\common\showmem.c - backtrace.c + div0.c 1 - ..\..\..\libcpu\arm\common\backtrace.c + ..\..\..\libcpu\arm\common\div0.c context_rvds.S @@ -433,21 +433,16 @@ 1 ..\..\..\components\drivers\serial\serial.c - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - waitqueue.c 1 ..\..\..\components\drivers\src\waitqueue.c + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + completion.c 1 @@ -458,6 +453,11 @@ 1 ..\..\..\components\drivers\src\dataqueue.c + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + ringblk_buf.c 1 @@ -494,9 +494,19 @@ finsh - shell.c + finsh_node.c 1 - ..\..\..\components\finsh\shell.c + ..\..\..\components\finsh\finsh_node.c + + + finsh_parser.c + 1 + ..\..\..\components\finsh\finsh_parser.c + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c msh.c @@ -504,45 +514,55 @@ ..\..\..\components\finsh\msh.c - cmd.c + finsh_vm.c 1 - ..\..\..\components\finsh\cmd.c + ..\..\..\components\finsh\finsh_vm.c + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + finsh_var.c + 1 + ..\..\..\components\finsh\finsh_var.c + + + finsh_compiler.c + 1 + ..\..\..\components\finsh\finsh_compiler.c + + + finsh_heap.c + 1 + ..\..\..\components\finsh\finsh_heap.c + + + finsh_ops.c + 1 + ..\..\..\components\finsh\finsh_ops.c + + + finsh_error.c + 1 + ..\..\..\components\finsh\finsh_error.c + + + finsh_token.c + 1 + ..\..\..\components\finsh\finsh_token.c + + + finsh_init.c + 1 + ..\..\..\components\finsh\finsh_init.c Kernel - - thread.c - 1 - ..\..\..\src\thread.c - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - device.c - 1 - ..\..\..\src\device.c - - - object.c - 1 - ..\..\..\src\object.c - - - irq.c - 1 - ..\..\..\src\irq.c - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - kservice.c 1 @@ -553,6 +573,36 @@ 1 ..\..\..\src\clock.c + + timer.c + 1 + ..\..\..\src\timer.c + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + device.c + 1 + ..\..\..\src\device.c + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + irq.c + 1 + ..\..\..\src\irq.c + + + object.c + 1 + ..\..\..\src\object.c + mempool.c 1 @@ -564,9 +614,9 @@ ..\..\..\src\components.c - mem.c + thread.c 1 - ..\..\..\src\mem.c + ..\..\..\src\thread.c idle.c @@ -574,9 +624,9 @@ ..\..\..\src\idle.c - timer.c + mem.c 1 - ..\..\..\src\timer.c + ..\..\..\src\mem.c @@ -584,54 +634,24 @@ nrfx - nrfx_ppi.c + nrfx_qspi.c 1 - packages\nrfx-latest\drivers\src\nrfx_ppi.c - - - nrfx_twim.c - 1 - packages\nrfx-latest\drivers\src\nrfx_twim.c - - - nrfx_temp.c - 1 - packages\nrfx-latest\drivers\src\nrfx_temp.c - - - nrfx_rng.c - 1 - packages\nrfx-latest\drivers\src\nrfx_rng.c - - - nrfx_twi.c - 1 - packages\nrfx-latest\drivers\src\nrfx_twi.c + packages\nrfx-latest\drivers\src\nrfx_qspi.c nrfx_spis.c 1 packages\nrfx-latest\drivers\src\nrfx_spis.c - - nrfx_nfct.c - 1 - packages\nrfx-latest\drivers\src\nrfx_nfct.c - nrfx_usbd.c 1 packages\nrfx-latest\drivers\src\nrfx_usbd.c - nrfx_pwm.c + nrfx_qdec.c 1 - packages\nrfx-latest\drivers\src\nrfx_pwm.c - - - nrfx_egu.c - 1 - packages\nrfx-latest\drivers\src\nrfx_egu.c + packages\nrfx-latest\drivers\src\nrfx_qdec.c nrfx_adc.c @@ -639,95 +659,120 @@ packages\nrfx-latest\drivers\src\nrfx_adc.c - nrfx_uarte.c + nrfx_power.c 1 - packages\nrfx-latest\drivers\src\nrfx_uarte.c + packages\nrfx-latest\drivers\src\nrfx_power.c - nrfx_clock.c + nrfx_egu.c 1 - packages\nrfx-latest\drivers\src\nrfx_clock.c + packages\nrfx-latest\drivers\src\nrfx_egu.c - nrfx_pdm.c + nrfx_twim.c 1 - packages\nrfx-latest\drivers\src\nrfx_pdm.c - - - nrfx_rtc.c - 1 - packages\nrfx-latest\drivers\src\nrfx_rtc.c - - - nrfx_dppi.c - 1 - packages\nrfx-latest\drivers\src\nrfx_dppi.c - - - nrfx_twis.c - 1 - packages\nrfx-latest\drivers\src\nrfx_twis.c - - - nrfx_ipc.c - 1 - packages\nrfx-latest\drivers\src\nrfx_ipc.c - - - nrfx_timer.c - 1 - packages\nrfx-latest\drivers\src\nrfx_timer.c + packages\nrfx-latest\drivers\src\nrfx_twim.c nrfx_nvmc.c 1 packages\nrfx-latest\drivers\src\nrfx_nvmc.c + + nrfx_temp.c + 1 + packages\nrfx-latest\drivers\src\nrfx_temp.c + nrfx_comp.c 1 packages\nrfx-latest\drivers\src\nrfx_comp.c - nrfx_systick.c + nrfx_dppi.c 1 - packages\nrfx-latest\drivers\src\nrfx_systick.c + packages\nrfx-latest\drivers\src\nrfx_dppi.c - nrfx_usbreg.c + nrfx_uart.c 1 - packages\nrfx-latest\drivers\src\nrfx_usbreg.c - - - arm_startup_nrf52840.s - 2 - packages\nrfx-latest\mdk\arm_startup_nrf52840.s - - - nrfx_saadc.c - 1 - packages\nrfx-latest\drivers\src\nrfx_saadc.c - - - nrfx_wdt.c - 1 - packages\nrfx-latest\drivers\src\nrfx_wdt.c + packages\nrfx-latest\drivers\src\nrfx_uart.c nrfx_gpiote.c 1 packages\nrfx-latest\drivers\src\nrfx_gpiote.c + + nrfx_systick.c + 1 + packages\nrfx-latest\drivers\src\nrfx_systick.c + + + nrfx_ipc.c + 1 + packages\nrfx-latest\drivers\src\nrfx_ipc.c + + + nrfx_pwm.c + 1 + packages\nrfx-latest\drivers\src\nrfx_pwm.c + + + nrfx_twi.c + 1 + packages\nrfx-latest\drivers\src\nrfx_twi.c + + + arm_startup_nrf52840.s + 2 + packages\nrfx-latest\mdk\arm_startup_nrf52840.s + + + nrfx_rtc.c + 1 + packages\nrfx-latest\drivers\src\nrfx_rtc.c + + + nrfx_twis.c + 1 + packages\nrfx-latest\drivers\src\nrfx_twis.c + + + nrfx_nfct.c + 1 + packages\nrfx-latest\drivers\src\nrfx_nfct.c + + + nrfx_usbreg.c + 1 + packages\nrfx-latest\drivers\src\nrfx_usbreg.c + + + nrfx_rng.c + 1 + packages\nrfx-latest\drivers\src\nrfx_rng.c + + + nrfx_wdt.c + 1 + packages\nrfx-latest\drivers\src\nrfx_wdt.c + + + nrfx_ppi.c + 1 + packages\nrfx-latest\drivers\src\nrfx_ppi.c + + + nrfx_saadc.c + 1 + packages\nrfx-latest\drivers\src\nrfx_saadc.c + nrfx_spi.c 1 packages\nrfx-latest\drivers\src\nrfx_spi.c - - nrfx_twi_twim.c - 1 - packages\nrfx-latest\drivers\src\nrfx_twi_twim.c - system_nrf52840.c 1 @@ -739,24 +784,14 @@ packages\nrfx-latest\drivers\src\nrfx_lpcomp.c - nrfx_qdec.c + nrfx_twi_twim.c 1 - packages\nrfx-latest\drivers\src\nrfx_qdec.c + packages\nrfx-latest\drivers\src\nrfx_twi_twim.c - nrfx_power.c + nrfx_clock.c 1 - packages\nrfx-latest\drivers\src\nrfx_power.c - - - nrfx_uart.c - 1 - packages\nrfx-latest\drivers\src\nrfx_uart.c - - - nrfx_i2s.c - 1 - packages\nrfx-latest\drivers\src\nrfx_i2s.c + packages\nrfx-latest\drivers\src\nrfx_clock.c nrfx_spim.c @@ -764,9 +799,24 @@ packages\nrfx-latest\drivers\src\nrfx_spim.c - nrfx_qspi.c + nrfx_i2s.c 1 - packages\nrfx-latest\drivers\src\nrfx_qspi.c + packages\nrfx-latest\drivers\src\nrfx_i2s.c + + + nrfx_uarte.c + 1 + packages\nrfx-latest\drivers\src\nrfx_uarte.c + + + nrfx_pdm.c + 1 + packages\nrfx-latest\drivers\src\nrfx_pdm.c + + + nrfx_timer.c + 1 + packages\nrfx-latest\drivers\src\nrfx_timer.c diff --git a/bsp/nrf5x/nrf52840/rtconfig.h b/bsp/nrf5x/nrf52840/rtconfig.h index 7b387a4444..9d269d9391 100644 --- a/bsp/nrf5x/nrf52840/rtconfig.h +++ b/bsp/nrf5x/nrf52840/rtconfig.h @@ -11,7 +11,6 @@ #define RT_THREAD_PRIORITY_32 #define RT_THREAD_PRIORITY_MAX 32 #define RT_TICK_PER_SECOND 100 -#define RT_USING_OVERFLOW_CHECK #define RT_USING_HOOK #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 @@ -22,15 +21,12 @@ /* kservice optimization */ -#define RT_DEBUG /* Inter-Thread communication */ #define RT_USING_SEMAPHORE #define RT_USING_MUTEX #define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE /* Memory Management */ @@ -69,7 +65,6 @@ #define FINSH_CMD_SIZE 80 #define FINSH_USING_MSH #define FINSH_USING_MSH_DEFAULT -#define FINSH_USING_MSH_ONLY #define FINSH_ARG_MAX 10 /* Device virtual file system */ @@ -171,27 +166,32 @@ #define SOC_NORDIC #define BSP_BOARD_PCA_10056 +/* Onboard Peripheral Drivers */ + +#define BSP_USING_JLINK_TO_USART + /* On-chip Peripheral Drivers */ #define BSP_USING_GPIO -#define NRFX_GPIOTE_ENABLED 1 #define BSP_USING_UART +#define NRFX_USING_UART #define BSP_USING_UART0 #define BSP_UART0_RX_PIN 8 #define BSP_UART0_TX_PIN 6 -/* On-chip flash config */ +/* MCU flash config */ #define MCU_FLASH_START_ADDRESS 0x00000000 #define MCU_FLASH_SIZE_KB 1024 #define MCU_SRAM_START_ADDRESS 0x20000000 #define MCU_SRAM_SIZE_KB 256 #define MCU_FLASH_PAGE_SIZE 0x1000 +#define BLE_STACK_USING_NULL #define NRFX_CLOCK_ENABLED 1 #define NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_CLOCK_CONFIG_LF_SRC 1 -#define NRFX_USING_UART #define NRFX_UART_ENABLED 1 #define NRFX_UART0_ENABLED 1 +#define NRFX_GPIOTE_ENABLED 1 #endif From c2a06c0cfb6eab4a0e8d7696bb2dc531d9595ac1 Mon Sep 17 00:00:00 2001 From: supperthomas <78900636@qq.com> Date: Sat, 26 Jun 2021 18:47:31 +0800 Subject: [PATCH 199/255] [bsp/nrf5x] add the bsp ble_nano_33 --- bsp/nrf5x/libraries/drivers/drv_uart.c | 5 +- bsp/nrf5x/libraries/drivers/drv_uart.h | 1 - bsp/nrf5x/nrf52840/.config | 100 +-- bsp/nrf5x/nrf52840/Kconfig | 5 +- bsp/nrf5x/nrf52840/applications/application.c | 9 +- bsp/nrf5x/nrf52840/board/Kconfig | 17 +- bsp/nrf5x/nrf52840/board/board.c | 8 +- bsp/nrf5x/nrf52840/project.uvoptx | 674 +++++++++--------- bsp/nrf5x/nrf52840/project.uvprojx | 328 ++++----- bsp/nrf5x/nrf52840/rtconfig.h | 69 +- 10 files changed, 614 insertions(+), 602 deletions(-) diff --git a/bsp/nrf5x/libraries/drivers/drv_uart.c b/bsp/nrf5x/libraries/drivers/drv_uart.c index 8ee6992f02..c0c50b736c 100644 --- a/bsp/nrf5x/libraries/drivers/drv_uart.c +++ b/bsp/nrf5x/libraries/drivers/drv_uart.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2020-04-28 xckhmf Modify for + * 2021-06-26 supperthomas fix rt_hw_uart_init * */ #include @@ -236,7 +237,7 @@ static struct rt_uart_ops _uart_ops = { _uart_getc }; -void rt_hw_uart_init(void) +int rt_hw_uart_init(void) { struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; @@ -249,5 +250,5 @@ void rt_hw_uart_init(void) #endif /* BSP_USING_UART0 */ } - +INIT_BOARD_EXPORT(rt_hw_uart_init); #endif /* BSP_USING_UART */ diff --git a/bsp/nrf5x/libraries/drivers/drv_uart.h b/bsp/nrf5x/libraries/drivers/drv_uart.h index da37eff016..bdffc4463c 100644 --- a/bsp/nrf5x/libraries/drivers/drv_uart.h +++ b/bsp/nrf5x/libraries/drivers/drv_uart.h @@ -13,7 +13,6 @@ // #define USE_UART0_1 0 -void rt_hw_uart_init(void); #endif diff --git a/bsp/nrf5x/nrf52840/.config b/bsp/nrf5x/nrf52840/.config index 9612d30606..1f53828ede 100644 --- a/bsp/nrf5x/nrf52840/.config +++ b/bsp/nrf5x/nrf52840/.config @@ -3,6 +3,57 @@ # RT-Thread Configuration # +# +# Hardware Drivers Config +# +CONFIG_SOC_NRF52840=y +CONFIG_SOC_NORDIC=y +CONFIG_BSP_BOARD_PCA_10056=y +# CONFIG_BSP_BOARD_ARDUINO_NANO_33_BLE is not set + +# +# Onboard Peripheral Drivers +# +CONFIG_BSP_USING_JLINK_TO_USART=y +CONFIG_RT_BSP_LED_PIN=13 +# CONFIG_BSP_USING_QSPI_FLASH is not set + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_NRFX_USING_UART=y +# CONFIG_NRFX_USING_UARTE is not set +CONFIG_BSP_USING_UART0=y +CONFIG_BSP_UART0_RX_PIN=8 +CONFIG_BSP_UART0_TX_PIN=6 +# CONFIG_BSP_USING_SAADC is not set +# CONFIG_BSP_USING_I2C is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_PWM is not set +# CONFIG_BSP_USING_WDT is not set +# CONFIG_BSP_USING_ONCHIP_RTC is not set +# CONFIG_BSP_USING_ON_CHIP_FLASH is not set + +# +# MCU flash config +# +CONFIG_MCU_FLASH_START_ADDRESS=0x00000000 +CONFIG_MCU_FLASH_SIZE_KB=1024 +CONFIG_MCU_SRAM_START_ADDRESS=0x20000000 +CONFIG_MCU_SRAM_SIZE_KB=256 +CONFIG_MCU_FLASH_PAGE_SIZE=0x1000 +CONFIG_BLE_STACK_USING_NULL=y +# CONFIG_BSP_USING_SOFTDEVICE is not set +# CONFIG_BSP_USING_NIMBLE is not set +CONFIG_NRFX_CLOCK_ENABLED=1 +CONFIG_NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY=7 +CONFIG_NRFX_CLOCK_CONFIG_LF_SRC=1 +CONFIG_NRFX_UART_ENABLED=1 +CONFIG_NRFX_UART0_ENABLED=1 +CONFIG_NRFX_GPIOTE_ENABLED=1 + # # RT-Thread Kernel # @@ -541,52 +592,3 @@ CONFIG_PKG_NRFX_VER="latest" # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_COWSAY is not set - -# -# Hardware Drivers Config -# -CONFIG_SOC_NRF52840=y -CONFIG_SOC_NORDIC=y -CONFIG_BSP_BOARD_PCA_10056=y - -# -# Onboard Peripheral Drivers -# -CONFIG_BSP_USING_JLINK_TO_USART=y -# CONFIG_BSP_USING_QSPI_FLASH is not set - -# -# On-chip Peripheral Drivers -# -CONFIG_BSP_USING_GPIO=y -CONFIG_BSP_USING_UART=y -CONFIG_NRFX_USING_UART=y -# CONFIG_NRFX_USING_UARTE is not set -CONFIG_BSP_USING_UART0=y -CONFIG_BSP_UART0_RX_PIN=8 -CONFIG_BSP_UART0_TX_PIN=6 -# CONFIG_BSP_USING_SAADC is not set -# CONFIG_BSP_USING_I2C is not set -# CONFIG_BSP_USING_SPI is not set -# CONFIG_BSP_USING_PWM is not set -# CONFIG_BSP_USING_WDT is not set -# CONFIG_BSP_USING_ONCHIP_RTC is not set -# CONFIG_BSP_USING_ON_CHIP_FLASH is not set - -# -# MCU flash config -# -CONFIG_MCU_FLASH_START_ADDRESS=0x00000000 -CONFIG_MCU_FLASH_SIZE_KB=1024 -CONFIG_MCU_SRAM_START_ADDRESS=0x20000000 -CONFIG_MCU_SRAM_SIZE_KB=256 -CONFIG_MCU_FLASH_PAGE_SIZE=0x1000 -CONFIG_BLE_STACK_USING_NULL=y -# CONFIG_BSP_USING_SOFTDEVICE is not set -# CONFIG_BSP_USING_NIMBLE is not set -CONFIG_NRFX_CLOCK_ENABLED=1 -CONFIG_NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY=7 -CONFIG_NRFX_CLOCK_CONFIG_LF_SRC=1 -CONFIG_NRFX_UART_ENABLED=1 -CONFIG_NRFX_UART0_ENABLED=1 -CONFIG_NRFX_GPIOTE_ENABLED=1 diff --git a/bsp/nrf5x/nrf52840/Kconfig b/bsp/nrf5x/nrf52840/Kconfig index 3640eaa0ed..56d486baed 100644 --- a/bsp/nrf5x/nrf52840/Kconfig +++ b/bsp/nrf5x/nrf52840/Kconfig @@ -14,8 +14,9 @@ config PKGS_DIR string option env="PKGS_ROOT" default "packages" - + +source "board/Kconfig" source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "board/Kconfig" + diff --git a/bsp/nrf5x/nrf52840/applications/application.c b/bsp/nrf5x/nrf52840/applications/application.c index f2cae69ed1..791e2af007 100644 --- a/bsp/nrf5x/nrf52840/applications/application.c +++ b/bsp/nrf5x/nrf52840/applications/application.c @@ -6,25 +6,24 @@ * Change Logs: * Date Author Notes * 2020-04-29 supperthomas first version + * 2021-06-26 supperthomas fix led * */ #include #include -#define DK_BOARD_LED_1 13 -#define DK_BOARD_LED_2 14 int main(void) { int count = 1; - rt_pin_mode(DK_BOARD_LED_1, PIN_MODE_OUTPUT); + rt_pin_mode(RT_BSP_LED_PIN, PIN_MODE_OUTPUT); while (count++) { - rt_pin_write(DK_BOARD_LED_1, PIN_HIGH); + rt_pin_write(RT_BSP_LED_PIN, PIN_HIGH); rt_thread_mdelay(500); - rt_pin_write(DK_BOARD_LED_1, PIN_LOW); + rt_pin_write(RT_BSP_LED_PIN, PIN_LOW); rt_thread_mdelay(500); } return RT_EOK; diff --git a/bsp/nrf5x/nrf52840/board/Kconfig b/bsp/nrf5x/nrf52840/board/Kconfig index 8a2fe7d49d..0a332f8bf0 100644 --- a/bsp/nrf5x/nrf52840/board/Kconfig +++ b/bsp/nrf5x/nrf52840/board/Kconfig @@ -15,19 +15,32 @@ choice default BSP_BOARD_PCA_10056 config BSP_BOARD_PCA_10056 + select BSP_USING_UART + select BSP_USING_UART0 bool "NRF52840 pca10056 " - + + config BSP_BOARD_ARDUINO_NANO_33_BLE + bool "Arduino Nano 33 BLE (Sense)" endchoice menu "Onboard Peripheral Drivers" config BSP_USING_JLINK_TO_USART bool "Enable JLINK TO USART (uart0|RX_PIN:8|TX_PIN:6)" default y + depends on BSP_BOARD_PCA_10056 + + config RT_BSP_LED_PIN + int + default 13 if BSP_BOARD_PCA_10056 + default 16 if BSP_BOARD_ARDUINO_NANO_33_BLE + depends on BSP_USING_GPIO + menuconfig BSP_USING_QSPI_FLASH select PKG_USING_FAL bool "Enable QSPI FLASH(MX25R64 8MB)" default n + depends on BSP_BOARD_PCA_10056 if BSP_USING_QSPI_FLASH config NRFX_QSPI_ENABLED @@ -89,8 +102,6 @@ menu "On-chip Peripheral Drivers" endchoice endif if BSP_USING_UART&&NRFX_USING_UART - - config BSP_USING_UART0 bool "Enable UART0" default y diff --git a/bsp/nrf5x/nrf52840/board/board.c b/bsp/nrf5x/nrf52840/board/board.c index 2cb94fb6fa..961a027e95 100644 --- a/bsp/nrf5x/nrf52840/board/board.c +++ b/bsp/nrf5x/nrf52840/board/board.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2020-04-29 supperthomas first version + * 2020-04-29 supperthomas fix component init * */ #include @@ -60,17 +61,14 @@ void rt_hw_board_init(void) rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); #endif -#ifdef RT_USING_SERIAL - rt_hw_uart_init(); +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); #endif #ifdef RT_USING_CONSOLE rt_console_set_device(RT_CONSOLE_DEVICE_NAME); #endif -#ifdef RT_USING_COMPONENTS_INIT - rt_components_board_init(); -#endif #ifdef BSP_USING_SOFTDEVICE extern uint32_t Image$$RW_IRAM1$$Base; diff --git a/bsp/nrf5x/nrf52840/project.uvoptx b/bsp/nrf5x/nrf52840/project.uvoptx index 232521460c..7bc32642ff 100644 --- a/bsp/nrf5x/nrf52840/project.uvoptx +++ b/bsp/nrf5x/nrf52840/project.uvoptx @@ -73,7 +73,7 @@ 0 - 1 + 0 0 1 @@ -183,7 +183,7 @@ Applications - 1 + 0 0 0 0 @@ -214,18 +214,6 @@ 0 0 0 - ..\..\..\libcpu\arm\common\backtrace.c - backtrace.c - 0 - 0 - - - 2 - 3 - 1 - 0 - 0 - 0 ..\..\..\libcpu\arm\common\showmem.c showmem.c 0 @@ -233,7 +221,7 @@ 2 - 4 + 3 1 0 0 @@ -245,19 +233,19 @@ 2 - 5 - 2 + 4 + 1 0 0 0 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - context_rvds.S + ..\..\..\libcpu\arm\common\backtrace.c + backtrace.c 0 0 2 - 6 + 5 1 0 0 @@ -267,6 +255,18 @@ 0 0 + + 2 + 6 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + context_rvds.S + 0 + 0 + @@ -306,8 +306,8 @@ 0 0 0 - ..\..\..\components\drivers\src\waitqueue.c - waitqueue.c + ..\..\..\components\drivers\src\workqueue.c + workqueue.c 0 0 @@ -318,8 +318,8 @@ 0 0 0 - ..\..\..\components\drivers\src\workqueue.c - workqueue.c + ..\..\..\components\drivers\src\ringblk_buf.c + ringblk_buf.c 0 0 @@ -342,8 +342,8 @@ 0 0 0 - ..\..\..\components\drivers\src\dataqueue.c - dataqueue.c + ..\..\..\components\drivers\src\waitqueue.c + waitqueue.c 0 0 @@ -354,8 +354,8 @@ 0 0 0 - ..\..\..\components\drivers\src\ringbuffer.c - ringbuffer.c + ..\..\..\components\drivers\src\pipe.c + pipe.c 0 0 @@ -366,8 +366,8 @@ 0 0 0 - ..\..\..\components\drivers\src\ringblk_buf.c - ringblk_buf.c + ..\..\..\components\drivers\src\dataqueue.c + dataqueue.c 0 0 @@ -378,8 +378,8 @@ 0 0 0 - ..\..\..\components\drivers\src\pipe.c - pipe.c + ..\..\..\components\drivers\src\ringbuffer.c + ringbuffer.c 0 0 @@ -387,7 +387,7 @@ Drivers - 1 + 0 0 0 0 @@ -442,8 +442,8 @@ 0 0 0 - ..\..\..\components\finsh\finsh_node.c - finsh_node.c + ..\..\..\components\finsh\finsh_vm.c + finsh_vm.c 0 0 @@ -454,35 +454,35 @@ 0 0 0 - ..\..\..\components\finsh\finsh_parser.c - finsh_parser.c - 0 - 0 - - - 5 - 21 - 1 - 0 - 0 - 0 - ..\..\..\components\finsh\cmd.c - cmd.c - 0 - 0 - - - 5 - 22 - 1 - 0 - 0 - 0 ..\..\..\components\finsh\msh.c msh.c 0 0 + + 5 + 21 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\finsh_parser.c + finsh_parser.c + 0 + 0 + + + 5 + 22 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + 5 23 @@ -490,8 +490,8 @@ 0 0 0 - ..\..\..\components\finsh\finsh_vm.c - finsh_vm.c + ..\..\..\components\finsh\finsh_node.c + finsh_node.c 0 0 @@ -606,42 +606,6 @@ 0 0 0 - ..\..\..\src\kservice.c - kservice.c - 0 - 0 - - - 6 - 33 - 1 - 0 - 0 - 0 - ..\..\..\src\clock.c - clock.c - 0 - 0 - - - 6 - 34 - 1 - 0 - 0 - 0 - ..\..\..\src\timer.c - timer.c - 0 - 0 - - - 6 - 35 - 1 - 0 - 0 - 0 ..\..\..\src\scheduler.c scheduler.c 0 @@ -649,7 +613,7 @@ 6 - 36 + 33 1 0 0 @@ -659,6 +623,42 @@ 0 0 + + 6 + 34 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 6 + 35 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 6 + 36 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + 6 37 @@ -666,8 +666,8 @@ 0 0 0 - ..\..\..\src\ipc.c - ipc.c + ..\..\..\src\timer.c + timer.c 0 0 @@ -690,8 +690,8 @@ 0 0 0 - ..\..\..\src\object.c - object.c + ..\..\..\src\ipc.c + ipc.c 0 0 @@ -714,8 +714,8 @@ 0 0 0 - ..\..\..\src\components.c - components.c + ..\..\..\src\object.c + object.c 0 0 @@ -738,8 +738,8 @@ 0 0 0 - ..\..\..\src\idle.c - idle.c + ..\..\..\src\components.c + components.c 0 0 @@ -750,8 +750,8 @@ 0 0 0 - ..\..\..\src\mem.c - mem.c + ..\..\..\src\idle.c + idle.c 0 0 @@ -770,8 +770,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_qspi.c - nrfx_qspi.c + packages\nrfx-latest\drivers\src\nrfx_qdec.c + nrfx_qdec.c 0 0 @@ -782,8 +782,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_spis.c - nrfx_spis.c + packages\nrfx-latest\drivers\src\nrfx_systick.c + nrfx_systick.c 0 0 @@ -794,8 +794,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_usbd.c - nrfx_usbd.c + packages\nrfx-latest\drivers\src\nrfx_dppi.c + nrfx_dppi.c 0 0 @@ -806,8 +806,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_qdec.c - nrfx_qdec.c + packages\nrfx-latest\drivers\src\nrfx_pdm.c + nrfx_pdm.c 0 0 @@ -818,8 +818,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_adc.c - nrfx_adc.c + packages\nrfx-latest\drivers\src\nrfx_ipc.c + nrfx_ipc.c 0 0 @@ -830,8 +830,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_power.c - nrfx_power.c + packages\nrfx-latest\drivers\src\nrfx_twi_twim.c + nrfx_twi_twim.c 0 0 @@ -854,8 +854,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_twim.c - nrfx_twim.c + packages\nrfx-latest\drivers\src\nrfx_qspi.c + nrfx_qspi.c 0 0 @@ -866,8 +866,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_nvmc.c - nrfx_nvmc.c + packages\nrfx-latest\drivers\src\nrfx_spis.c + nrfx_spis.c 0 0 @@ -878,23 +878,23 @@ 0 0 0 + packages\nrfx-latest\drivers\src\nrfx_lpcomp.c + nrfx_lpcomp.c + 0 + 0 + + + 7 + 55 + 1 + 0 + 0 + 0 packages\nrfx-latest\drivers\src\nrfx_temp.c nrfx_temp.c 0 0 - - 7 - 55 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_comp.c - nrfx_comp.c - 0 - 0 - 7 56 @@ -902,8 +902,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_dppi.c - nrfx_dppi.c + packages\nrfx-latest\drivers\src\nrfx_wdt.c + nrfx_wdt.c 0 0 @@ -914,74 +914,14 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_uart.c - nrfx_uart.c + packages\nrfx-latest\drivers\src\nrfx_twim.c + nrfx_twim.c 0 0 7 58 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_gpiote.c - nrfx_gpiote.c - 0 - 0 - - - 7 - 59 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_systick.c - nrfx_systick.c - 0 - 0 - - - 7 - 60 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_ipc.c - nrfx_ipc.c - 0 - 0 - - - 7 - 61 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_pwm.c - nrfx_pwm.c - 0 - 0 - - - 7 - 62 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_twi.c - nrfx_twi.c - 0 - 0 - - - 7 - 63 2 0 0 @@ -991,6 +931,66 @@ 0 0 + + 7 + 59 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_power.c + nrfx_power.c + 0 + 0 + + + 7 + 60 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_timer.c + nrfx_timer.c + 0 + 0 + + + 7 + 61 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_nvmc.c + nrfx_nvmc.c + 0 + 0 + + + 7 + 62 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_ppi.c + nrfx_ppi.c + 0 + 0 + + + 7 + 63 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_spim.c + nrfx_spim.c + 0 + 0 + 7 64 @@ -998,23 +998,23 @@ 0 0 0 + packages\nrfx-latest\drivers\src\nrfx_comp.c + nrfx_comp.c + 0 + 0 + + + 7 + 65 + 1 + 0 + 0 + 0 packages\nrfx-latest\drivers\src\nrfx_rtc.c nrfx_rtc.c 0 0 - - 7 - 65 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_twis.c - nrfx_twis.c - 0 - 0 - 7 66 @@ -1022,8 +1022,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_nfct.c - nrfx_nfct.c + packages\nrfx-latest\drivers\src\nrfx_twi.c + nrfx_twi.c 0 0 @@ -1046,102 +1046,6 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_rng.c - nrfx_rng.c - 0 - 0 - - - 7 - 69 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_wdt.c - nrfx_wdt.c - 0 - 0 - - - 7 - 70 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_ppi.c - nrfx_ppi.c - 0 - 0 - - - 7 - 71 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_saadc.c - nrfx_saadc.c - 0 - 0 - - - 7 - 72 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_spi.c - nrfx_spi.c - 0 - 0 - - - 7 - 73 - 1 - 0 - 0 - 0 - packages\nrfx-latest\mdk\system_nrf52840.c - system_nrf52840.c - 0 - 0 - - - 7 - 74 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_lpcomp.c - nrfx_lpcomp.c - 0 - 0 - - - 7 - 75 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_twi_twim.c - nrfx_twi_twim.c - 0 - 0 - - - 7 - 76 - 1 - 0 - 0 - 0 packages\nrfx-latest\drivers\src\nrfx_clock.c nrfx_clock.c 0 @@ -1149,19 +1053,7 @@ 7 - 77 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_spim.c - nrfx_spim.c - 0 - 0 - - - 7 - 78 + 69 1 0 0 @@ -1171,6 +1063,114 @@ 0 0 + + 7 + 70 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_twis.c + nrfx_twis.c + 0 + 0 + + + 7 + 71 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_adc.c + nrfx_adc.c + 0 + 0 + + + 7 + 72 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_rng.c + nrfx_rng.c + 0 + 0 + + + 7 + 73 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_usbd.c + nrfx_usbd.c + 0 + 0 + + + 7 + 74 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_uart.c + nrfx_uart.c + 0 + 0 + + + 7 + 75 + 1 + 0 + 0 + 0 + packages\nrfx-latest\mdk\system_nrf52840.c + system_nrf52840.c + 0 + 0 + + + 7 + 76 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_saadc.c + nrfx_saadc.c + 0 + 0 + + + 7 + 77 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_nfct.c + nrfx_nfct.c + 0 + 0 + + + 7 + 78 + 1 + 0 + 0 + 0 + packages\nrfx-latest\drivers\src\nrfx_gpiote.c + nrfx_gpiote.c + 0 + 0 + 7 79 @@ -1178,23 +1178,23 @@ 0 0 0 + packages\nrfx-latest\drivers\src\nrfx_spi.c + nrfx_spi.c + 0 + 0 + + + 7 + 80 + 1 + 0 + 0 + 0 packages\nrfx-latest\drivers\src\nrfx_uarte.c nrfx_uarte.c 0 0 - - 7 - 80 - 1 - 0 - 0 - 0 - packages\nrfx-latest\drivers\src\nrfx_pdm.c - nrfx_pdm.c - 0 - 0 - 7 81 @@ -1202,8 +1202,8 @@ 0 0 0 - packages\nrfx-latest\drivers\src\nrfx_timer.c - nrfx_timer.c + packages\nrfx-latest\drivers\src\nrfx_pwm.c + nrfx_pwm.c 0 0 diff --git a/bsp/nrf5x/nrf52840/project.uvprojx b/bsp/nrf5x/nrf52840/project.uvprojx index 7646c98bf2..69017ec490 100644 --- a/bsp/nrf5x/nrf52840/project.uvprojx +++ b/bsp/nrf5x/nrf52840/project.uvprojx @@ -10,7 +10,7 @@ rtthread 0x4 ARM-ADS - 5060960::V5.06 update 7 (build 960)::ARMCC + 5060422::V5.06 update 4 (build 422)::ARMCC 0 @@ -339,7 +339,7 @@ --reduce_paths NRF52840_XXAA, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND - applications;.;..\libraries\cmsis\include;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\none-gcc;packages\nrfx-latest;packages\nrfx-latest\drivers;packages\nrfx-latest\drivers\include;packages\nrfx-latest\mdk;packages\nrfx-latest\hal;..\..\..\examples\utest\testcases\kernel + applications;.;..\libraries\cmsis\include;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\none-gcc;packages\nrfx-latest;packages\nrfx-latest\drivers;packages\nrfx-latest\drivers\include;packages\nrfx-latest\mdk;packages\nrfx-latest\hal;packages\SEGGER_RTT-v1.1.0;packages\SEGGER_RTT-v1.1.0\RTT;..\..\..\examples\utest\testcases\kernel @@ -393,11 +393,6 @@ CPU - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - showmem.c 1 @@ -409,15 +404,20 @@ ..\..\..\libcpu\arm\common\div0.c - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c cpuport.c 1 ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + @@ -433,21 +433,31 @@ 1 ..\..\..\components\drivers\serial\serial.c - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - workqueue.c 1 ..\..\..\components\drivers\src\workqueue.c + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + completion.c 1 ..\..\..\components\drivers\src\completion.c + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + dataqueue.c 1 @@ -458,16 +468,6 @@ 1 ..\..\..\components\drivers\src\ringbuffer.c - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - @@ -494,9 +494,14 @@ finsh - finsh_node.c + finsh_vm.c 1 - ..\..\..\components\finsh\finsh_node.c + ..\..\..\components\finsh\finsh_vm.c + + + msh.c + 1 + ..\..\..\components\finsh\msh.c finsh_parser.c @@ -509,14 +514,9 @@ ..\..\..\components\finsh\cmd.c - msh.c + finsh_node.c 1 - ..\..\..\components\finsh\msh.c - - - finsh_vm.c - 1 - ..\..\..\components\finsh\finsh_vm.c + ..\..\..\components\finsh\finsh_node.c shell.c @@ -563,11 +563,26 @@ Kernel + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + device.c + 1 + ..\..\..\src\device.c + kservice.c 1 ..\..\..\src\kservice.c + + mem.c + 1 + ..\..\..\src\mem.c + clock.c 1 @@ -579,14 +594,9 @@ ..\..\..\src\timer.c - scheduler.c + irq.c 1 - ..\..\..\src\scheduler.c - - - device.c - 1 - ..\..\..\src\device.c + ..\..\..\src\irq.c ipc.c @@ -594,9 +604,9 @@ ..\..\..\src\ipc.c - irq.c + mempool.c 1 - ..\..\..\src\irq.c + ..\..\..\src\mempool.c object.c @@ -604,35 +614,60 @@ ..\..\..\src\object.c - mempool.c + thread.c 1 - ..\..\..\src\mempool.c + ..\..\..\src\thread.c components.c 1 ..\..\..\src\components.c - - thread.c - 1 - ..\..\..\src\thread.c - idle.c 1 ..\..\..\src\idle.c - - mem.c - 1 - ..\..\..\src\mem.c - nrfx + + nrfx_qdec.c + 1 + packages\nrfx-latest\drivers\src\nrfx_qdec.c + + + nrfx_systick.c + 1 + packages\nrfx-latest\drivers\src\nrfx_systick.c + + + nrfx_dppi.c + 1 + packages\nrfx-latest\drivers\src\nrfx_dppi.c + + + nrfx_pdm.c + 1 + packages\nrfx-latest\drivers\src\nrfx_pdm.c + + + nrfx_ipc.c + 1 + packages\nrfx-latest\drivers\src\nrfx_ipc.c + + + nrfx_twi_twim.c + 1 + packages\nrfx-latest\drivers\src\nrfx_twi_twim.c + + + nrfx_egu.c + 1 + packages\nrfx-latest\drivers\src\nrfx_egu.c + nrfx_qspi.c 1 @@ -644,39 +679,9 @@ packages\nrfx-latest\drivers\src\nrfx_spis.c - nrfx_usbd.c + nrfx_lpcomp.c 1 - packages\nrfx-latest\drivers\src\nrfx_usbd.c - - - nrfx_qdec.c - 1 - packages\nrfx-latest\drivers\src\nrfx_qdec.c - - - nrfx_adc.c - 1 - packages\nrfx-latest\drivers\src\nrfx_adc.c - - - nrfx_power.c - 1 - packages\nrfx-latest\drivers\src\nrfx_power.c - - - nrfx_egu.c - 1 - packages\nrfx-latest\drivers\src\nrfx_egu.c - - - nrfx_twim.c - 1 - packages\nrfx-latest\drivers\src\nrfx_twim.c - - - nrfx_nvmc.c - 1 - packages\nrfx-latest\drivers\src\nrfx_nvmc.c + packages\nrfx-latest\drivers\src\nrfx_lpcomp.c nrfx_temp.c @@ -684,44 +689,14 @@ packages\nrfx-latest\drivers\src\nrfx_temp.c - nrfx_comp.c + nrfx_wdt.c 1 - packages\nrfx-latest\drivers\src\nrfx_comp.c + packages\nrfx-latest\drivers\src\nrfx_wdt.c - nrfx_dppi.c + nrfx_twim.c 1 - packages\nrfx-latest\drivers\src\nrfx_dppi.c - - - nrfx_uart.c - 1 - packages\nrfx-latest\drivers\src\nrfx_uart.c - - - nrfx_gpiote.c - 1 - packages\nrfx-latest\drivers\src\nrfx_gpiote.c - - - nrfx_systick.c - 1 - packages\nrfx-latest\drivers\src\nrfx_systick.c - - - nrfx_ipc.c - 1 - packages\nrfx-latest\drivers\src\nrfx_ipc.c - - - nrfx_pwm.c - 1 - packages\nrfx-latest\drivers\src\nrfx_pwm.c - - - nrfx_twi.c - 1 - packages\nrfx-latest\drivers\src\nrfx_twi.c + packages\nrfx-latest\drivers\src\nrfx_twim.c arm_startup_nrf52840.s @@ -729,34 +704,19 @@ packages\nrfx-latest\mdk\arm_startup_nrf52840.s - nrfx_rtc.c + nrfx_power.c 1 - packages\nrfx-latest\drivers\src\nrfx_rtc.c + packages\nrfx-latest\drivers\src\nrfx_power.c - nrfx_twis.c + nrfx_timer.c 1 - packages\nrfx-latest\drivers\src\nrfx_twis.c + packages\nrfx-latest\drivers\src\nrfx_timer.c - nrfx_nfct.c + nrfx_nvmc.c 1 - packages\nrfx-latest\drivers\src\nrfx_nfct.c - - - nrfx_usbreg.c - 1 - packages\nrfx-latest\drivers\src\nrfx_usbreg.c - - - nrfx_rng.c - 1 - packages\nrfx-latest\drivers\src\nrfx_rng.c - - - nrfx_wdt.c - 1 - packages\nrfx-latest\drivers\src\nrfx_wdt.c + packages\nrfx-latest\drivers\src\nrfx_nvmc.c nrfx_ppi.c @@ -764,59 +724,99 @@ packages\nrfx-latest\drivers\src\nrfx_ppi.c - nrfx_saadc.c + nrfx_spim.c 1 - packages\nrfx-latest\drivers\src\nrfx_saadc.c + packages\nrfx-latest\drivers\src\nrfx_spim.c - nrfx_spi.c + nrfx_comp.c 1 - packages\nrfx-latest\drivers\src\nrfx_spi.c + packages\nrfx-latest\drivers\src\nrfx_comp.c - system_nrf52840.c + nrfx_rtc.c 1 - packages\nrfx-latest\mdk\system_nrf52840.c + packages\nrfx-latest\drivers\src\nrfx_rtc.c - nrfx_lpcomp.c + nrfx_twi.c 1 - packages\nrfx-latest\drivers\src\nrfx_lpcomp.c + packages\nrfx-latest\drivers\src\nrfx_twi.c - nrfx_twi_twim.c + nrfx_usbreg.c 1 - packages\nrfx-latest\drivers\src\nrfx_twi_twim.c + packages\nrfx-latest\drivers\src\nrfx_usbreg.c nrfx_clock.c 1 packages\nrfx-latest\drivers\src\nrfx_clock.c - - nrfx_spim.c - 1 - packages\nrfx-latest\drivers\src\nrfx_spim.c - nrfx_i2s.c 1 packages\nrfx-latest\drivers\src\nrfx_i2s.c + + nrfx_twis.c + 1 + packages\nrfx-latest\drivers\src\nrfx_twis.c + + + nrfx_adc.c + 1 + packages\nrfx-latest\drivers\src\nrfx_adc.c + + + nrfx_rng.c + 1 + packages\nrfx-latest\drivers\src\nrfx_rng.c + + + nrfx_usbd.c + 1 + packages\nrfx-latest\drivers\src\nrfx_usbd.c + + + nrfx_uart.c + 1 + packages\nrfx-latest\drivers\src\nrfx_uart.c + + + system_nrf52840.c + 1 + packages\nrfx-latest\mdk\system_nrf52840.c + + + nrfx_saadc.c + 1 + packages\nrfx-latest\drivers\src\nrfx_saadc.c + + + nrfx_nfct.c + 1 + packages\nrfx-latest\drivers\src\nrfx_nfct.c + + + nrfx_gpiote.c + 1 + packages\nrfx-latest\drivers\src\nrfx_gpiote.c + + + nrfx_spi.c + 1 + packages\nrfx-latest\drivers\src\nrfx_spi.c + nrfx_uarte.c 1 packages\nrfx-latest\drivers\src\nrfx_uarte.c - nrfx_pdm.c + nrfx_pwm.c 1 - packages\nrfx-latest\drivers\src\nrfx_pdm.c - - - nrfx_timer.c - 1 - packages\nrfx-latest\drivers\src\nrfx_timer.c + packages\nrfx-latest\drivers\src\nrfx_pwm.c diff --git a/bsp/nrf5x/nrf52840/rtconfig.h b/bsp/nrf5x/nrf52840/rtconfig.h index 9d269d9391..df606fc98e 100644 --- a/bsp/nrf5x/nrf52840/rtconfig.h +++ b/bsp/nrf5x/nrf52840/rtconfig.h @@ -4,6 +4,41 @@ /* Automatically generated file; DO NOT EDIT. */ /* RT-Thread Configuration */ +/* Hardware Drivers Config */ + +#define SOC_NRF52840 +#define SOC_NORDIC +#define BSP_BOARD_PCA_10056 + +/* Onboard Peripheral Drivers */ + +#define BSP_USING_JLINK_TO_USART +#define RT_BSP_LED_PIN 13 + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define NRFX_USING_UART +#define BSP_USING_UART0 +#define BSP_UART0_RX_PIN 8 +#define BSP_UART0_TX_PIN 6 + +/* MCU flash config */ + +#define MCU_FLASH_START_ADDRESS 0x00000000 +#define MCU_FLASH_SIZE_KB 1024 +#define MCU_SRAM_START_ADDRESS 0x20000000 +#define MCU_SRAM_SIZE_KB 256 +#define MCU_FLASH_PAGE_SIZE 0x1000 +#define BLE_STACK_USING_NULL +#define NRFX_CLOCK_ENABLED 1 +#define NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#define NRFX_CLOCK_CONFIG_LF_SRC 1 +#define NRFX_UART_ENABLED 1 +#define NRFX_UART0_ENABLED 1 +#define NRFX_GPIOTE_ENABLED 1 + /* RT-Thread Kernel */ #define RT_NAME_MAX 8 @@ -160,38 +195,4 @@ /* entertainment: terminal games and other interesting software packages */ -/* Hardware Drivers Config */ - -#define SOC_NRF52840 -#define SOC_NORDIC -#define BSP_BOARD_PCA_10056 - -/* Onboard Peripheral Drivers */ - -#define BSP_USING_JLINK_TO_USART - -/* On-chip Peripheral Drivers */ - -#define BSP_USING_GPIO -#define BSP_USING_UART -#define NRFX_USING_UART -#define BSP_USING_UART0 -#define BSP_UART0_RX_PIN 8 -#define BSP_UART0_TX_PIN 6 - -/* MCU flash config */ - -#define MCU_FLASH_START_ADDRESS 0x00000000 -#define MCU_FLASH_SIZE_KB 1024 -#define MCU_SRAM_START_ADDRESS 0x20000000 -#define MCU_SRAM_SIZE_KB 256 -#define MCU_FLASH_PAGE_SIZE 0x1000 -#define BLE_STACK_USING_NULL -#define NRFX_CLOCK_ENABLED 1 -#define NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY 7 -#define NRFX_CLOCK_CONFIG_LF_SRC 1 -#define NRFX_UART_ENABLED 1 -#define NRFX_UART0_ENABLED 1 -#define NRFX_GPIOTE_ENABLED 1 - #endif From 05e37a17b24fbee0a35193bf02c4671cb352365d Mon Sep 17 00:00:00 2001 From: supperthomas <78900636@qq.com> Date: Sat, 26 Jun 2021 18:59:55 +0800 Subject: [PATCH 200/255] add the gcc build --- bsp/nrf5x/nrf52840/.vscode/launch.json | 16 ++ .../nrf52840/board/linker_scripts/link.lds | 146 +++++++++++++++++- 2 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 bsp/nrf5x/nrf52840/.vscode/launch.json diff --git a/bsp/nrf5x/nrf52840/.vscode/launch.json b/bsp/nrf5x/nrf52840/.vscode/launch.json new file mode 100644 index 0000000000..0d61dd7de6 --- /dev/null +++ b/bsp/nrf5x/nrf52840/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "cwd": "${workspaceRoot}", + "executable": "rt-thread.elf", + "name": "Debug MAX", + "request": "launch", + "type": "cortex-debug", + "servertype": "jlink", + "interface": "swd", + "device": "NRF52840_XXAA", + "runToMain": true + }, + ] +} \ No newline at end of file diff --git a/bsp/nrf5x/nrf52840/board/linker_scripts/link.lds b/bsp/nrf5x/nrf52840/board/linker_scripts/link.lds index f91b8466ca..e699e0079a 100644 --- a/bsp/nrf5x/nrf52840/board/linker_scripts/link.lds +++ b/bsp/nrf5x/nrf52840/board/linker_scripts/link.lds @@ -9,7 +9,151 @@ MEMORY RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x40000 } -INCLUDE "packages/nrfx-v2.1.0/mdk/nrf_common.ld" +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + + . = ALIGN(4); + + PROVIDE(__ctors_start__ = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE(__ctors_end__ = .); + + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __HeapBase = .; + __end__ = .; + PROVIDE(end = .); + KEEP(*(.heap*)) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + KEEP(*(.stack*)) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + + /* Check if text sections + data exceeds FLASH limit */ + DataInitFlashUsed = __bss_start__ - __data_start__; + CodeFlashUsed = __etext - ORIGIN(FLASH); + TotalFlashUsed = CodeFlashUsed + DataInitFlashUsed; + ASSERT(TotalFlashUsed <= LENGTH(FLASH), "region FLASH overflowed with .data and user data") + +} + From d00c3249d47de8e420cf820dd9c7ccf314c7a434 Mon Sep 17 00:00:00 2001 From: supperthomas <78900636@qq.com> Date: Sat, 26 Jun 2021 20:01:20 +0800 Subject: [PATCH 201/255] add the readme --- bsp/nrf5x/nrf52840/README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/bsp/nrf5x/nrf52840/README.md b/bsp/nrf5x/nrf52840/README.md index c3a4a95f9f..993bf7d7ab 100644 --- a/bsp/nrf5x/nrf52840/README.md +++ b/bsp/nrf5x/nrf52840/README.md @@ -2,7 +2,20 @@ ## 简介 -该文件夹主要存放所有主芯片为nRF52840的板级支持包。目前默认支持的开发板是官方[PCA10056](https://www.nordicsemi.com/Software-and-tools/Development-Kits/nRF52840-DK) +该文件夹主要存放所有主芯片为nRF52840的板级支持包。 + +目前支持的开发板如下 + +| 支持开发板型号 | 开发板上外设 | 备注 | +| ------------------------------------------------------------ | --------------------------- | ----------------------------------- | +| [PCA10056](https://www.nordicsemi.com/Software-and-tools/Development-Kits/nRF52840-DK) | QSPI FLASH, 4 button,4 LED | UART0 | +| [ARDUINO NANO 33 BLE](https://store.arduino.cc/usa/nano-33-ble-sense-with-headers) | 3 LED | 需要连接jlink shell采用RTT 方式交互 | +| | | | + +选择开发板请使用`menuconfig` -> `Hardware Driver Config` -> `Select Bsp board` + +选择对应的开发板 + 本文主要内容如下: - 开发板资源介绍 From f9a07e40195c8ee09fac789216cae762726fd5ca Mon Sep 17 00:00:00 2001 From: supperthomas <78900636@qq.com> Date: Sat, 26 Jun 2021 22:06:42 +0800 Subject: [PATCH 202/255] add the link --- bsp/nrf5x/nrf52840/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bsp/nrf5x/nrf52840/README.md b/bsp/nrf5x/nrf52840/README.md index 993bf7d7ab..99b6882b2b 100644 --- a/bsp/nrf5x/nrf52840/README.md +++ b/bsp/nrf5x/nrf52840/README.md @@ -12,6 +12,8 @@ | [ARDUINO NANO 33 BLE](https://store.arduino.cc/usa/nano-33-ble-sense-with-headers) | 3 LED | 需要连接jlink shell采用RTT 方式交互 | | | | | +相关开发板资料原理图整理在[BSP_BOARD_NRF52840](https://github.com/supperthomas/BSP_BOARD_NRF52840) + 选择开发板请使用`menuconfig` -> `Hardware Driver Config` -> `Select Bsp board` 选择对应的开发板 From 670000dd0fae2ccf8c67821a8b551847810a6044 Mon Sep 17 00:00:00 2001 From: chenyingchun0312 Date: Mon, 28 Jun 2021 00:49:42 +0800 Subject: [PATCH 203/255] [bsp/nrf5x] fix gcc compile exception and add onchip filesystem Signed-off-by: chenyingchun0312 --- bsp/nrf5x/libraries/drivers/SConscript | 3 + bsp/nrf5x/libraries/drivers/drv_fs.c | 100 +++++++++++ bsp/nrf5x/nrf52832/board/Kconfig | 4 + bsp/nrf5x/nrf52832/board/board.c | 34 ++++ bsp/nrf5x/nrf52832/board/fal_cfg.h | 51 ++++++ .../nrf52832/board/linker_scripts/link.lds | 162 +++++++++++++++++- bsp/nrf5x/nrf52832/rtconfig.py | 11 +- 7 files changed, 357 insertions(+), 8 deletions(-) create mode 100644 bsp/nrf5x/libraries/drivers/drv_fs.c create mode 100644 bsp/nrf5x/nrf52832/board/fal_cfg.h diff --git a/bsp/nrf5x/libraries/drivers/SConscript b/bsp/nrf5x/libraries/drivers/SConscript index 7c2a47a734..1b68acd868 100644 --- a/bsp/nrf5x/libraries/drivers/SConscript +++ b/bsp/nrf5x/libraries/drivers/SConscript @@ -40,6 +40,9 @@ if GetDepend(['BSP_USING_WDT']): if GetDepend(['BSP_USING_ONCHIP_RTC']): src += ['drv_rtc.c'] +if GetDepend(['BSP_USING_ON_CHIP_FS']): + src += ['drv_fs.c'] + path = [cwd] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) diff --git a/bsp/nrf5x/libraries/drivers/drv_fs.c b/bsp/nrf5x/libraries/drivers/drv_fs.c new file mode 100644 index 0000000000..222d77e35f --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/drv_fs.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * on chip filesystem support + * Change Logs: + * Date Author Notes + * 2021-06-27 Chenyingchun first version + */ +#include "board.h" +#include +#include + +#ifdef BSP_USING_ON_CHIP_FS + +#ifndef PKG_USING_FAL +#error "if you want to use on chip filesystem, you need to enable FAL package()" +#endif + +#ifndef RT_USING_DFS +#error "if you want to use on chip filesystem, you need to enable DFS componment" +#endif + +#ifndef BSP_USING_ON_CHIP_FLASH +#error "if you want to use on chip filesystem, you need to enable on-chip flash" +#endif + +#ifndef RT_USING_MTD_NOR +#error "if you want to use on chip filesystem, you need to enable mtd nor" +#endif + +#include "fal.h" +#include + +#define LOG_TAG "drv.fs" +#define DBG_LVL DBG_LOG +#include + +#define FS_PARTITION_NAME ON_CHIP_PARTION_NAME + + +/** + * @brief on chip filesystem init + * @param void + * @retval 0: filesystem init success, -1: filesystem init failed + */ + +static int on_chip_fs_init(void) +{ + int result = 0; + + fal_init(); + + struct rt_device *flash_dev = fal_mtd_nor_device_create(FS_PARTITION_NAME); + + if (flash_dev == NULL) + { + LOG_E("Can't create a block device on '%s' partition.", FS_PARTITION_NAME); + result = -1; + goto err; + } + else + { + LOG_D("Create a block device on the %s partition of flash successful.", FS_PARTITION_NAME); + } + + if (rt_device_find(FS_PARTITION_NAME) != RT_NULL) + { + int mkfs_res = dfs_mkfs("lfs", FS_PARTITION_NAME); + + if (mkfs_res != 0) + { + LOG_E("dfs_mkfs error, errno = %d", rt_get_errno()); + result = -1; + goto err; + } + + if (dfs_mount(FS_PARTITION_NAME, "/", "lfs", 0, 0) == RT_EOK) + { + LOG_D("onchip elm filesystem mount to '/'"); + } + else + { + LOG_E("onchip elm filesystem mount to '/' failed!"); + result = -1; + goto err; + } + } + else + { + LOG_E("find filesystem portion failed"); + } +err: + return result; +} + +INIT_ENV_EXPORT(on_chip_fs_init); + +#endif /* BSP_USING_ON_CHIP_FS */ diff --git a/bsp/nrf5x/nrf52832/board/Kconfig b/bsp/nrf5x/nrf52832/board/Kconfig index e62e762509..416722fd64 100644 --- a/bsp/nrf5x/nrf52832/board/Kconfig +++ b/bsp/nrf5x/nrf52832/board/Kconfig @@ -341,6 +341,10 @@ menu "On-chip Peripheral Drivers" select PKG_USING_FAL bool "Enable on-chip FLASH" default n + + config BSP_USING_ON_CHIP_FS + bool "Enable on-chip filesystem" + default n menu "On-chip flash config" diff --git a/bsp/nrf5x/nrf52832/board/board.c b/bsp/nrf5x/nrf52832/board/board.c index 0b3a436530..26fcf8e7bb 100644 --- a/bsp/nrf5x/nrf52832/board/board.c +++ b/bsp/nrf5x/nrf52832/board/board.c @@ -49,6 +49,40 @@ void SysTick_Configuration(void) } +/** + * The time delay function. + * + * @param microseconds. + */ +void rt_hw_us_delay(rt_uint32_t us) +{ + rt_uint32_t ticks; + rt_uint32_t told, tnow, tcnt = 0; + rt_uint32_t reload = SysTick->LOAD; + + ticks = us * reload / (1000000 / RT_TICK_PER_SECOND); + told = SysTick->VAL; + while (1) + { + tnow = SysTick->VAL; + if (tnow != told) + { + if (tnow < told) + { + tcnt += told - tnow; + } + else + { + tcnt += reload - tnow + told; + } + told = tnow; + if (tcnt >= ticks) + { + break; + } + } + } +} void rt_hw_board_init(void) { diff --git a/bsp/nrf5x/nrf52832/board/fal_cfg.h b/bsp/nrf5x/nrf52832/board/fal_cfg.h new file mode 100644 index 0000000000..af373a2c80 --- /dev/null +++ b/bsp/nrf5x/nrf52832/board/fal_cfg.h @@ -0,0 +1,51 @@ +/* + * File : fal_cfg.h + * This file is part of FAL (Flash Abstraction Layer) package + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2021-06-26 chenyingchun the first version + */ + +#ifndef _FAL_CFG_H_ +#define _FAL_CFG_H_ + +#include +#include + +#define ON_CHIP_FLASH_DEV_NAME "mcu_onchip_flash" +#define ON_CHIP_PARTION_NAME "filesystem" + +/* ===================== Flash device Configuration ========================= */ +extern const struct fal_flash_dev mcu_onchip_flash; + +/* flash device table */ +#define FAL_FLASH_DEV_TABLE \ + { \ + &mcu_onchip_flash, \ + } +/* ====================== Partition Configuration ========================== */ +#ifdef FAL_PART_HAS_TABLE_CFG +/* partition table */ +#define FAL_PART_TABLE \ + { \ + {FAL_PART_MAGIC_WORD, ON_CHIP_PARTION_NAME, ON_CHIP_FLASH_DEV_NAME, 224 * 1024, 120 * 1024, 0}, \ + } +#endif /* FAL_PART_HAS_TABLE_CFG */ + +#endif /* _FAL_CFG_H_ */ diff --git a/bsp/nrf5x/nrf52832/board/linker_scripts/link.lds b/bsp/nrf5x/nrf52832/board/linker_scripts/link.lds index b1d21b531b..f436d3fcec 100644 --- a/bsp/nrf5x/nrf52832/board/linker_scripts/link.lds +++ b/bsp/nrf5x/nrf52832/board/linker_scripts/link.lds @@ -1,16 +1,164 @@ /* Linker script to configure memory regions. */ -SEARCH_DIR(.) -GROUP(-lgcc -lc -lnosys) - MEMORY { - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000 - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000 - CODE_RAM (rwx) : ORIGIN = 0x800000, LENGTH = 0x10000 + ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000 /* 512K FLASH */ + RAM (rw) : ORIGIN = 0x20000000, LENGTH = 0x10000 /* 64K RAM */ } +ENTRY(Reset_Handler) +_system_stack_size = 0x200; -INCLUDE "packages/nrfx-v2.1.0/mdk/nrf_common.ld" +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + + /* section information for modules */ + . = ALIGN(4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + + . = ALIGN(4); + + PROVIDE(__ctors_start__ = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE(__ctors_end__ = .); + + . = ALIGN(4); + + _etext = .; + } > ROM = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > ROM + __exidx_end = .; + + /* .data section which is used for initialized data */ + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >RAM + + .stack : + { + . = ALIGN(4); + _sstack = .; + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >RAM + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > RAM + __bss_end = .; + + _end = .; + + PROVIDE(__etext = __exidx_end); + PROVIDE(__data_start__ = _sdata); + PROVIDE(__bss_start__ = __bss_start); + PROVIDE(__bss_end__ = __bss_end); + PROVIDE(__StackTop = _estack); + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/nrf5x/nrf52832/rtconfig.py b/bsp/nrf5x/nrf52832/rtconfig.py index e8a959bc85..d065edfe02 100644 --- a/bsp/nrf5x/nrf52832/rtconfig.py +++ b/bsp/nrf5x/nrf52832/rtconfig.py @@ -13,7 +13,7 @@ if os.getenv('RTT_CC'): if CROSS_TOOL == 'gcc': PLATFORM = 'gcc' - EXEC_PATH = 'D:/SourceryGCC/bin' + EXEC_PATH = r'D:\RT-ThreadStudio\repo\Extract\ToolChain_Support_Packages\ARM\GNU_Tools_for_ARM_Embedded_Processors\5.4.1\bin' elif CROSS_TOOL == 'keil': PLATFORM = 'armcc' EXEC_PATH = 'C:/Keil_v5' @@ -34,17 +34,26 @@ if PLATFORM == 'gcc': CC = PREFIX + 'gcc' AS = PREFIX + 'gcc' AR = PREFIX + 'ar' + CXX= PREFIX + 'g++' LINK = PREFIX + 'gcc' TARGET_EXT = 'elf' SIZE = PREFIX + 'size' OBJDUMP = PREFIX + 'objdump' OBJCPY = PREFIX + 'objcopy' + STRIP = PREFIX + 'strip' DEVICE = ' -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections' CFLAGS = DEVICE AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp' LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.lds' + CXXFLAGS = CFLAGS + M_CFLAGS = CFLAGS + ' -mlong-calls -fPIC ' + M_CXXFLAGS = CXXFLAGS + ' -mlong-calls -fPIC' + M_LFLAGS = DEVICE + CXXFLAGS + ' -Wl,--gc-sections,-z,max-page-size=0x4' +\ + ' -shared -fPIC -nostartfiles -nostdlib -static-libgcc' + M_POST_ACTION = STRIP + ' -R .hash $TARGET\n' + SIZE + ' $TARGET \n' + CPATH = '' LPATH = '' From a1f2cdd4d6ce94da7c381dcab9534a7111b3f4ba Mon Sep 17 00:00:00 2001 From: chenyingchun0312 Date: Mon, 28 Jun 2021 11:12:09 +0800 Subject: [PATCH 204/255] [bsp/nrf5x] format drv_fs.c --- bsp/nrf5x/libraries/drivers/drv_fs.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bsp/nrf5x/libraries/drivers/drv_fs.c b/bsp/nrf5x/libraries/drivers/drv_fs.c index 222d77e35f..1576139a06 100644 --- a/bsp/nrf5x/libraries/drivers/drv_fs.c +++ b/bsp/nrf5x/libraries/drivers/drv_fs.c @@ -33,13 +33,12 @@ #include "fal.h" #include -#define LOG_TAG "drv.fs" -#define DBG_LVL DBG_LOG +#define LOG_TAG "drv.fs" +#define DBG_LVL DBG_LOG #include #define FS_PARTITION_NAME ON_CHIP_PARTION_NAME - /** * @brief on chip filesystem init * @param void @@ -49,7 +48,7 @@ static int on_chip_fs_init(void) { int result = 0; - + fal_init(); struct rt_device *flash_dev = fal_mtd_nor_device_create(FS_PARTITION_NAME); From 9f45c13ac9600caaf24c1527b7ed60e6fa00e948 Mon Sep 17 00:00:00 2001 From: liuxianliang Date: Mon, 28 Jun 2021 11:18:28 +0800 Subject: [PATCH 205/255] [update] the "event_callback" will be change by RT-Thread dfs. --- components/net/lwip-2.0.2/src/api/sockets.c | 3 ++- components/net/lwip-2.0.3/src/api/sockets.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/components/net/lwip-2.0.2/src/api/sockets.c b/components/net/lwip-2.0.2/src/api/sockets.c index dc2477b611..87e0f86dff 100644 --- a/components/net/lwip-2.0.2/src/api/sockets.c +++ b/components/net/lwip-2.0.2/src/api/sockets.c @@ -531,7 +531,8 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) return -1; } LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); - // LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); + /* RT-Thread has changed callback when using BSD socket API, so remove this assert. */ + /* LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); */ nsock = &sockets[newsock - LWIP_SOCKET_OFFSET]; /* See event_callback: If data comes in right away after an accept, even diff --git a/components/net/lwip-2.0.3/src/api/sockets.c b/components/net/lwip-2.0.3/src/api/sockets.c index d2be138be6..87e0f86dff 100644 --- a/components/net/lwip-2.0.3/src/api/sockets.c +++ b/components/net/lwip-2.0.3/src/api/sockets.c @@ -531,7 +531,8 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) return -1; } LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); - LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); + /* RT-Thread has changed callback when using BSD socket API, so remove this assert. */ + /* LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); */ nsock = &sockets[newsock - LWIP_SOCKET_OFFSET]; /* See event_callback: If data comes in right away after an accept, even From 81ccffb5e4b7bebfca18aa16e9c7262e57f98ced Mon Sep 17 00:00:00 2001 From: liuxianliang Date: Mon, 28 Jun 2021 11:44:29 +0800 Subject: [PATCH 206/255] [fix] delete useless code. --- components/net/lwip-2.0.3/src/arch/include/arch/cc.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/components/net/lwip-2.0.3/src/arch/include/arch/cc.h b/components/net/lwip-2.0.3/src/arch/include/arch/cc.h index 5e9a7ff722..c7848adfc9 100644 --- a/components/net/lwip-2.0.3/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.0.3/src/arch/include/arch/cc.h @@ -92,10 +92,6 @@ void sys_arch_assert(const char* file, int line); #define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) #define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) -//#define SYS_ARCH_DECL_PROTECT(level) -//#define SYS_ARCH_PROTECT(level) rt_enter_critical() -//#define SYS_ARCH_UNPROTECT(level) rt_exit_critical() - #define SYS_ARCH_DECL_PROTECT(level) register rt_base_t level #define SYS_ARCH_PROTECT(level) do {level = rt_hw_interrupt_disable();} while(0) #define SYS_ARCH_UNPROTECT(level) do {rt_hw_interrupt_enable(level);} while(0) From 4a884cd8ba0662e158886e598bc9456e98bcc8a5 Mon Sep 17 00:00:00 2001 From: liuxianliang Date: Mon, 28 Jun 2021 11:45:27 +0800 Subject: [PATCH 207/255] [update] change default lwip stack to lwip2.0.3 --- components/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/net/Kconfig b/components/net/Kconfig index 467002ac2e..0fede3eb90 100644 --- a/components/net/Kconfig +++ b/components/net/Kconfig @@ -114,7 +114,7 @@ config RT_USING_LWIP if RT_USING_LWIP choice prompt "lwIP version" - default RT_USING_LWIP212 + default RT_USING_LWIP203 help Select the lwIP version From 0e1266ac101c8f70a004ef0a54a97036cf8dd10f Mon Sep 17 00:00:00 2001 From: liuxianliang Date: Mon, 28 Jun 2021 11:47:13 +0800 Subject: [PATCH 208/255] [remove] redundant script. --- components/net/SConscript | 4 ---- 1 file changed, 4 deletions(-) diff --git a/components/net/SConscript b/components/net/SConscript index e3b6fef89f..031e92284c 100644 --- a/components/net/SConscript +++ b/components/net/SConscript @@ -7,10 +7,6 @@ objs = [] cwd = GetCurrentDir() list = os.listdir(cwd) -# the default version of LWIP is 2.0.2 -if not GetDepend('RT_USING_LWIP141') and not GetDepend('RT_USING_LWIP202') and not GetDepend('RT_USING_LWIP203') and not GetDepend('RT_USING_LWIP212'): - AddDepend('RT_USING_LWIP202') - for d in list: path = os.path.join(cwd, d) if os.path.isfile(os.path.join(path, 'SConscript')): From 0cbb1f08c1d22e64cbc4d1399dca25eded37af0f Mon Sep 17 00:00:00 2001 From: liuxianliang Date: Mon, 28 Jun 2021 12:39:19 +0800 Subject: [PATCH 209/255] [fix] set default lwip stack for old bsp folder. --- components/SConscript | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/SConscript b/components/SConscript index 82efd7b2fe..88927f881c 100644 --- a/components/SConscript +++ b/components/SConscript @@ -7,6 +7,11 @@ objs = [] cwd = GetCurrentDir() list = os.listdir(cwd) +# In some old bsp folder, Only define RT_USING_LWIP but not define which of LWIP stack. +# For this reason, the default lwip stack will be set LWIP2.0.3. +if not GetDepend('RT_USING_LWIP141') and not GetDepend('RT_USING_LWIP202') and not GetDepend('RT_USING_LWIP203') and not GetDepend('RT_USING_LWIP212'): + AddDepend('RT_USING_LWIP203') + for item in list: if item in remove_components: continue From 898ea9e7d4d3acf7069dc65810ff12187bd37f3c Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 28 Jun 2021 15:33:14 +0800 Subject: [PATCH 210/255] =?UTF-8?q?[components]=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E5=AF=B9=E8=80=81=E7=89=88=E6=9C=ACbsp=E7=9A=84lwip=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E9=BB=98=E8=AE=A4=E9=80=89=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/SConscript | 5 ----- 1 file changed, 5 deletions(-) diff --git a/components/SConscript b/components/SConscript index 88927f881c..82efd7b2fe 100644 --- a/components/SConscript +++ b/components/SConscript @@ -7,11 +7,6 @@ objs = [] cwd = GetCurrentDir() list = os.listdir(cwd) -# In some old bsp folder, Only define RT_USING_LWIP but not define which of LWIP stack. -# For this reason, the default lwip stack will be set LWIP2.0.3. -if not GetDepend('RT_USING_LWIP141') and not GetDepend('RT_USING_LWIP202') and not GetDepend('RT_USING_LWIP203') and not GetDepend('RT_USING_LWIP212'): - AddDepend('RT_USING_LWIP203') - for item in list: if item in remove_components: continue From c9b0876ac5cbfd9ebc81aa0599fced28eec23408 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 28 Jun 2021 16:29:26 +0800 Subject: [PATCH 211/255] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=80=81bsp=E5=B7=A5?= =?UTF-8?q?=E7=A8=8B=E5=92=8Crtconfig.h?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/CME_M7/rtconfig.h | 1 + bsp/frdm-k64f/rtconfig.h | 1 + bsp/lm3s9b9x/rtconfig.h | 1 + bsp/lpc176x/rtconfig.h | 1 + bsp/mini2440/.config | 173 ++++- bsp/mini2440/project.uvproj | 1279 ++++++++++++++++++++--------------- bsp/mini2440/rtconfig.h | 26 +- bsp/sam7x/rtconfig.h | 1 + 8 files changed, 941 insertions(+), 542 deletions(-) diff --git a/bsp/CME_M7/rtconfig.h b/bsp/CME_M7/rtconfig.h index a16dddf4d9..81d7c22eb4 100644 --- a/bsp/CME_M7/rtconfig.h +++ b/bsp/CME_M7/rtconfig.h @@ -91,6 +91,7 @@ /* SECTION: lwip, a lighwight TCP/IP protocol stack */ #define RT_USING_LWIP +#define RT_USING_LWIP203 /* Enable ICMP protocol*/ #define RT_LWIP_ICMP /* Enable UDP protocol*/ diff --git a/bsp/frdm-k64f/rtconfig.h b/bsp/frdm-k64f/rtconfig.h index 6338b39edb..81b5b29f8c 100644 --- a/bsp/frdm-k64f/rtconfig.h +++ b/bsp/frdm-k64f/rtconfig.h @@ -103,6 +103,7 @@ /* SECTION: lwip, a lighwight TCP/IP protocol stack */ #define RT_USING_LWIP +#define RT_USING_LWIP203 /* Enable LwIP debug output */ //#define RT_LWIP_DEBUG /* Enable ICMP protocol*/ diff --git a/bsp/lm3s9b9x/rtconfig.h b/bsp/lm3s9b9x/rtconfig.h index b961c26d6f..741899fb34 100644 --- a/bsp/lm3s9b9x/rtconfig.h +++ b/bsp/lm3s9b9x/rtconfig.h @@ -89,6 +89,7 @@ /* SECTION: lwip, a lighwight TCP/IP protocol stack */ /* Using lighweight TCP/IP protocol stack*/ #define RT_USING_LWIP +#define RT_USING_LWIP203 /* Trace LwIP protocol*/ /* #define RT_LWIP_DEBUG */ diff --git a/bsp/lpc176x/rtconfig.h b/bsp/lpc176x/rtconfig.h index 5096b2f71d..c15fc48ee5 100644 --- a/bsp/lpc176x/rtconfig.h +++ b/bsp/lpc176x/rtconfig.h @@ -157,6 +157,7 @@ //
#define RT_USING_LWIP +#define RT_USING_LWIP203 // #define RT_LWIP_ICMP // diff --git a/bsp/mini2440/.config b/bsp/mini2440/.config index 1e1372162c..3acbaf11a0 100644 --- a/bsp/mini2440/.config +++ b/bsp/mini2440/.config @@ -24,6 +24,12 @@ CONFIG_IDLE_THREAD_STACK_SIZE=256 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 is not set # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -56,6 +62,7 @@ CONFIG_RT_USING_MEMHEAP=y CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set # CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_USERHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set CONFIG_RT_USING_HEAP=y @@ -68,7 +75,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=128 CONFIG_RT_CONSOLE_DEVICE_NAME="uart" -CONFIG_RT_VER_NUM=0x40003 +CONFIG_RT_VER_NUM=0x40004 CONFIG_ARCH_ARM=y # CONFIG_RT_USING_CPU_FFS is not set CONFIG_ARCH_ARM_ARM9=y @@ -127,6 +134,11 @@ CONFIG_RT_DFS_ELM_WORD_ACCESS=y # 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 @@ -135,8 +147,6 @@ 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=y -# CONFIG_RT_USING_DFS_UFFS is not set -# CONFIG_RT_USING_DFS_JFFS2 is not set # CONFIG_RT_USING_DFS_NFS is not set # @@ -148,14 +158,18 @@ CONFIG_RT_USING_SYSTEM_WORKQUEUE=y CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set # CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set # CONFIG_RT_USING_PWM is not set # CONFIG_RT_USING_MTD_NOR is not set # CONFIG_RT_USING_MTD_NAND is not set @@ -193,9 +207,11 @@ CONFIG_PTHREAD_NUM_MAX=8 CONFIG_RT_USING_POSIX=y CONFIG_RT_USING_POSIX_MMAP=y CONFIG_RT_USING_POSIX_TERMIOS=y +# CONFIG_RT_USING_POSIX_GETLINE is not set CONFIG_RT_USING_POSIX_AIO=y CONFIG_RT_USING_MODULE=y CONFIG_RT_USING_CUSTOM_DLMODULE=y +CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # # Network @@ -205,6 +221,7 @@ CONFIG_RT_USING_CUSTOM_DLMODULE=y # Socket abstraction layer # CONFIG_RT_USING_SAL=y +CONFIG_SAL_INTERNET_CHECK=y # # protocol stack implement @@ -231,8 +248,10 @@ CONFIG_NETDEV_IPV6=0 CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set # CONFIG_RT_USING_LWIP202 is not set -CONFIG_RT_USING_LWIP210=y +CONFIG_RT_USING_LWIP203=y +# CONFIG_RT_USING_LWIP212 is not set # 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 @@ -274,6 +293,7 @@ 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=y CONFIG_LWIP_NETIF_LOOPBACK=1 CONFIG_RT_LWIP_STATS=y @@ -300,8 +320,14 @@ CONFIG_YMODEM_USING_CRC_TABLE=y CONFIG_YMODEM_USING_FILE_TRANSFER=y # CONFIG_RT_USING_ULOG 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 # @@ -309,12 +335,15 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # # 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 @@ -341,6 +370,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # 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 @@ -353,7 +383,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # CONFIG_PKG_USING_GAGENT_CLOUD is not set # CONFIG_PKG_USING_ALI_IOTKIT is not set # CONFIG_PKG_USING_AZURE is not set -# CONFIG_PKG_USING_TENCENT_IOTHUB is not set +# CONFIG_PKG_USING_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 @@ -365,8 +395,6 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # CONFIG_PKG_USING_LIBRWS is not set # CONFIG_PKG_USING_TCPSERVER is not set # CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set # CONFIG_PKG_USING_DLT645 is not set # CONFIG_PKG_USING_QXWZ is not set # CONFIG_PKG_USING_SMTP_CLIENT is not set @@ -375,6 +403,18 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # 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 @@ -383,6 +423,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # 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 @@ -399,6 +440,11 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # 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 @@ -410,13 +456,36 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # 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 @@ -425,21 +494,47 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set -# CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_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 + +# +# 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_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# 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 +# 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 @@ -448,6 +543,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # 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 @@ -458,6 +554,8 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # 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 @@ -475,12 +573,49 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # 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 @@ -490,10 +625,12 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # 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 @@ -510,10 +647,22 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y # CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set # CONFIG_PKG_USING_VI is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set # CONFIG_PKG_USING_VT100 is not set -# CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set +# CONFIG_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 diff --git a/bsp/mini2440/project.uvproj b/bsp/mini2440/project.uvproj index be1302e35a..860d5fe806 100644 --- a/bsp/mini2440/project.uvproj +++ b/bsp/mini2440/project.uvproj @@ -341,9 +341,9 @@ 0 --diag_suppress=870 - RT_USING_ARM_LIBC + RT_USING_ARM_LIBC, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND - .;..\..\include;applications;.;drivers;..\..\libcpu\arm\common;..\..\libcpu\arm\s3c24x0;..\..\components\dfs\include;..\..\components\dfs\filesystems\devfs;..\..\components\dfs\filesystems\elmfat;..\..\components\drivers\include;..\..\components\finsh;..\..\components\libc\compilers\armlibc;..\..\components\libc\compilers\common;..\..\components\libc\pthreads;..\..\components\libc\time;..\..\components\net\lwip-2.0.2\src;..\..\components\net\lwip-2.0.2\src\include;..\..\components\net\lwip-2.0.2\src\include\ipv4;..\..\components\net\lwip-2.0.2\src\arch\include;..\..\components\net\lwip-2.0.2\src\include\netif;..\..\components\net\lwip-2.0.2\src\include\posix + applications;.;..\..\components\cplusplus;..\..\libcpu\arm\common;..\..\libcpu\arm\s3c24x0;..\..\components\drivers\include;..\..\components\drivers\include;..\..\components\drivers\include;..\..\components\drivers\include;drivers;..\..\components\dfs\include;..\..\components\dfs\filesystems\devfs;..\..\components\dfs\filesystems\elmfat;..\..\components\dfs\filesystems\ramfs;..\..\components\finsh;.;..\..\include;..\..\components\libc\aio;..\..\components\libc\compilers\armlibc;..\..\components\libc\compilers\common;..\..\components\libc\compilers\common\none-gcc;..\..\components\libc\mmap;..\..\components\libc\pthreads;..\..\components\libc\termios;..\..\components\net\lwip-2.0.3\src;..\..\components\net\lwip-2.0.3\src\include;..\..\components\net\lwip-2.0.3\src\include\ipv4;..\..\components\net\lwip-2.0.3\src\arch\include;..\..\components\net\lwip-2.0.3\src\include\netif;..\..\components\net\netdev\include;..\..\components\net\sal_socket\include;..\..\components\net\sal_socket\include\socket;..\..\components\net\sal_socket\impl;..\..\components\net\sal_socket\include\dfs_net;..\..\components\net\sal_socket\include\dfs_net\sys_select;..\..\components\net\sal_socket\include\socket\sys_socket;..\..\examples\utest\testcases\kernel;..\..\components\utilities\ymodem @@ -380,178 +380,63 @@ - - Kernel - - - clock.c - 1 - ..\..\src\clock.c - - - - - components.c - 1 - ..\..\src\components.c - - - - - cpu.c - 1 - ..\..\src\cpu.c - - - - - device.c - 1 - ..\..\src\device.c - - - - - idle.c - 1 - ..\..\src\idle.c - - - - - ipc.c - 1 - ..\..\src\ipc.c - - - - - irq.c - 1 - ..\..\src\irq.c - - - - - kservice.c - 1 - ..\..\src\kservice.c - - - - - mem.c - 1 - ..\..\src\mem.c - - - - - mempool.c - 1 - ..\..\src\mempool.c - - - - - object.c - 1 - ..\..\src\object.c - - - - - scheduler.c - 1 - ..\..\src\scheduler.c - - - - - signal.c - 1 - ..\..\src\signal.c - - - - - thread.c - 1 - ..\..\src\thread.c - - - - - timer.c - 1 - ..\..\src\timer.c - - - Applications - application.c + mnt.c 1 - applications\application.c + applications\mnt.c - startup.c + main.c 1 - applications\startup.c + applications\main.c - Drivers + CPlusPlus - board.c - 1 - drivers\board.c + cxx_Thread.cpp + 8 + ..\..\components\cplusplus\cxx_Thread.cpp - led.c - 1 - drivers\led.c + cxx_crt.cpp + 8 + ..\..\components\cplusplus\cxx_crt.cpp - console.c + crt_init.c 1 - drivers\console.c + ..\..\components\cplusplus\crt_init.c - sdcard.c - 1 - drivers\sdcard.c + cxx_Semaphore.cpp + 8 + ..\..\components\cplusplus\cxx_Semaphore.cpp - dm9000.c - 1 - drivers\dm9000.c + cxx_Mutex.cpp + 8 + ..\..\components\cplusplus\cxx_Mutex.cpp - cpu - - - backtrace.c - 1 - ..\..\libcpu\arm\common\backtrace.c - - + CPU div0.c @@ -568,16 +453,9 @@ - s3c24x0_cpu.c + backtrace.c 1 - ..\..\libcpu\arm\s3c24x0\cpu.c - - - - - interrupt.c - 1 - ..\..\libcpu\arm\s3c24x0\interrupt.c + ..\..\libcpu\arm\common\backtrace.c @@ -587,41 +465,6 @@ ..\..\libcpu\arm\s3c24x0\mmu.c - - - rtc.c - 1 - ..\..\libcpu\arm\s3c24x0\rtc.c - - - - - serial.c - 1 - ..\..\libcpu\arm\s3c24x0\serial.c - - - - - stack.c - 1 - ..\..\libcpu\arm\s3c24x0\stack.c - - - - - system_clock.c - 1 - ..\..\libcpu\arm\s3c24x0\system_clock.c - - - - - trap.c - 1 - ..\..\libcpu\arm\s3c24x0\trap.c - - context_rvds.S @@ -636,63 +479,46 @@ ..\..\libcpu\arm\s3c24x0\start_rvds.S - - - Filesystem - dfs.c + stack.c 1 - ..\..\components\dfs\src\dfs.c + ..\..\libcpu\arm\s3c24x0\stack.c - dfs_file.c + cpu.c 1 - ..\..\components\dfs\src\dfs_file.c + ..\..\libcpu\arm\s3c24x0\cpu.c - dfs_fs.c + system_clock.c 1 - ..\..\components\dfs\src\dfs_fs.c + ..\..\libcpu\arm\s3c24x0\system_clock.c - dfs_posix.c + interrupt.c 1 - ..\..\components\dfs\src\dfs_posix.c + ..\..\libcpu\arm\s3c24x0\interrupt.c - devfs.c + rtc.c 1 - ..\..\components\dfs\filesystems\devfs\devfs.c + ..\..\libcpu\arm\s3c24x0\rtc.c - dfs_elm.c + trap.c 1 - ..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ff.c - 1 - ..\..\components\dfs\filesystems\elmfat\ff.c - - - - - cc936.c - 1 - ..\..\components\dfs\filesystems\elmfat\option\cc936.c + ..\..\libcpu\arm\s3c24x0\trap.c @@ -700,9 +526,51 @@ DeviceDrivers - completion.c + pin.c 1 - ..\..\components\drivers\src\completion.c + ..\..\components\drivers\misc\pin.c + + + + + mmc.c + 1 + ..\..\components\drivers\sdio\mmc.c + + + + + sd.c + 1 + ..\..\components\drivers\sdio\sd.c + + + + + block_dev.c + 1 + ..\..\components\drivers\sdio\block_dev.c + + + + + sdio.c + 1 + ..\..\components\drivers\sdio\sdio.c + + + + + mmcsd_core.c + 1 + ..\..\components\drivers\sdio\mmcsd_core.c + + + + + serial.c + 1 + ..\..\components\drivers\serial\serial.c @@ -714,23 +582,9 @@ - pipe.c + completion.c 1 - ..\..\components\drivers\src\pipe.c - - - - - ringblk_buf.c - 1 - ..\..\components\drivers\src\ringblk_buf.c - - - - - ringbuffer.c - 1 - ..\..\components\drivers\src\ringbuffer.c + ..\..\components\drivers\src\completion.c @@ -740,6 +594,27 @@ ..\..\components\drivers\src\waitqueue.c + + + ringblk_buf.c + 1 + ..\..\components\drivers\src\ringblk_buf.c + + + + + pipe.c + 1 + ..\..\components\drivers\src\pipe.c + + + + + ringbuffer.c + 1 + ..\..\components\drivers\src\ringbuffer.c + + workqueue.c @@ -748,50 +623,133 @@ + + Drivers + + + dm9000.c + 1 + drivers\dm9000.c + + + + + s3cmci.c + 1 + drivers\s3cmci.c + + + + + key.c + 1 + drivers\key.c + + + + + led.c + 1 + drivers\led.c + + + + + uart.c + 1 + drivers\uart.c + + + + + board.c + 1 + drivers\board.c + + + + + Filesystem + + + dfs_posix.c + 1 + ..\..\components\dfs\src\dfs_posix.c + + + + + dfs_file.c + 1 + ..\..\components\dfs\src\dfs_file.c + + + + + select.c + 1 + ..\..\components\dfs\src\select.c + + + + + dfs.c + 1 + ..\..\components\dfs\src\dfs.c + + + + + poll.c + 1 + ..\..\components\dfs\src\poll.c + + + + + dfs_fs.c + 1 + ..\..\components\dfs\src\dfs_fs.c + + + + + devfs.c + 1 + ..\..\components\dfs\filesystems\devfs\devfs.c + + + + + ff.c + 1 + ..\..\components\dfs\filesystems\elmfat\ff.c + + + + + ffunicode.c + 1 + ..\..\components\dfs\filesystems\elmfat\ffunicode.c + + + + + dfs_elm.c + 1 + ..\..\components\dfs\filesystems\elmfat\dfs_elm.c + + + + + dfs_ramfs.c + 1 + ..\..\components\dfs\filesystems\ramfs\dfs_ramfs.c + + + finsh - - - shell.c - 1 - ..\..\components\finsh\shell.c - - - - - cmd.c - 1 - ..\..\components\finsh\cmd.c - - - - - finsh_compiler.c - 1 - ..\..\components\finsh\finsh_compiler.c - - - - - finsh_error.c - 1 - ..\..\components\finsh\finsh_error.c - - - - - finsh_heap.c - 1 - ..\..\components\finsh\finsh_heap.c - - - - - finsh_init.c - 1 - ..\..\components\finsh\finsh_init.c - - finsh_node.c @@ -799,13 +757,6 @@ ..\..\components\finsh\finsh_node.c - - - finsh_ops.c - 1 - ..\..\components\finsh\finsh_ops.c - - finsh_parser.c @@ -815,9 +766,9 @@ - finsh_var.c + msh.c 1 - ..\..\components\finsh\finsh_var.c + ..\..\components\finsh\msh.c @@ -827,6 +778,62 @@ ..\..\components\finsh\finsh_vm.c + + + msh_file.c + 1 + ..\..\components\finsh\msh_file.c + + + + + shell.c + 1 + ..\..\components\finsh\shell.c + + + + + finsh_var.c + 1 + ..\..\components\finsh\finsh_var.c + + + + + finsh_compiler.c + 1 + ..\..\components\finsh\finsh_compiler.c + + + + + finsh_ops.c + 1 + ..\..\components\finsh\finsh_ops.c + + + + + finsh_heap.c + 1 + ..\..\components\finsh\finsh_heap.c + + + + + finsh_error.c + 1 + ..\..\components\finsh\finsh_error.c + + + + + cmd.c + 1 + ..\..\components\finsh\cmd.c + + finsh_token.c @@ -834,21 +841,129 @@ ..\..\components\finsh\finsh_token.c + + + finsh_init.c + 1 + ..\..\components\finsh\finsh_init.c + + + + + Kernel + + + mem.c + 1 + ..\..\src\mem.c + + + + + clock.c + 1 + ..\..\src\clock.c + + + + + scheduler.c + 1 + ..\..\src\scheduler.c + + + + + irq.c + 1 + ..\..\src\irq.c + + + + + device.c + 1 + ..\..\src\device.c + + + + + object.c + 1 + ..\..\src\object.c + + + + + thread.c + 1 + ..\..\src\thread.c + + + + + components.c + 1 + ..\..\src\components.c + + + + + kservice.c + 1 + ..\..\src\kservice.c + + + + + ipc.c + 1 + ..\..\src\ipc.c + + + + + memheap.c + 1 + ..\..\src\memheap.c + + + + + mempool.c + 1 + ..\..\src\mempool.c + + + + + timer.c + 1 + ..\..\src\timer.c + + + + + idle.c + 1 + ..\..\src\idle.c + + libc - libc.c + posix_aio.c 1 - ..\..\components\libc\compilers\armlibc\libc.c + ..\..\components\libc\aio\posix_aio.c - mem_std.c + libc.c 1 - ..\..\components\libc\compilers\armlibc\mem_std.c + ..\..\components\libc\compilers\armlibc\libc.c @@ -860,9 +975,44 @@ - stubs.c + syscalls.c 1 - ..\..\components\libc\compilers\armlibc\stubs.c + ..\..\components\libc\compilers\armlibc\syscalls.c + + + + + mem_std.c + 1 + ..\..\components\libc\compilers\armlibc\mem_std.c + + + + + libc_syms.c + 1 + ..\..\components\libc\compilers\armlibc\libc_syms.c + + + + + unistd.c + 1 + ..\..\components\libc\compilers\common\unistd.c + + + + + delay.c + 1 + ..\..\components\libc\compilers\common\delay.c + + + + + stdlib.c + 1 + ..\..\components\libc\compilers\common\stdlib.c @@ -872,49 +1022,11 @@ ..\..\components\libc\compilers\common\time.c - - - pthreads - mqueue.c + posix_mmap.c 1 - ..\..\components\libc\pthreads\mqueue.c - - - - - pthread.c - 1 - ..\..\components\libc\pthreads\pthread.c - - - - - pthread_attr.c - 1 - ..\..\components\libc\pthreads\pthread_attr.c - - - - - pthread_barrier.c - 1 - ..\..\components\libc\pthreads\pthread_barrier.c - - - - - pthread_cond.c - 1 - ..\..\components\libc\pthreads\pthread_cond.c - - - - - pthread_mutex.c - 1 - ..\..\components\libc\pthreads\pthread_mutex.c + ..\..\components\libc\mmap\posix_mmap.c @@ -924,6 +1036,13 @@ ..\..\components\libc\pthreads\pthread_rwlock.c + + + pthread_cond.c + 1 + ..\..\components\libc\pthreads\pthread_cond.c + + pthread_spin.c @@ -933,9 +1052,9 @@ - pthread_tls.c + pthread_attr.c 1 - ..\..\components\libc\pthreads\pthread_tls.c + ..\..\components\libc\pthreads\pthread_attr.c @@ -945,6 +1064,20 @@ ..\..\components\libc\pthreads\sched.c + + + pthread.c + 1 + ..\..\components\libc\pthreads\pthread.c + + + + + pthread_barrier.c + 1 + ..\..\components\libc\pthreads\pthread_barrier.c + + semaphore.c @@ -954,271 +1087,361 @@ - clock_time.c + pthread_tls.c 1 - ..\..\components\libc\time\clock_time.c + ..\..\components\libc\pthreads\pthread_tls.c - posix_sleep.c + mqueue.c 1 - ..\..\components\libc\time\posix_sleep.c + ..\..\components\libc\pthreads\mqueue.c + + + + + pthread_mutex.c + 1 + ..\..\components\libc\pthreads\pthread_mutex.c + + + + + posix_termios.c + 1 + ..\..\components\libc\termios\posix_termios.c lwIP - - - sys_arch.c - 1 - ..\..\components\net\lwip-2.0.2\src\arch\sys_arch.c - - - - - api_lib.c - 1 - ..\..\components\net\lwip-2.0.2\src\api\api_lib.c - - - - - api_msg.c - 1 - ..\..\components\net\lwip-2.0.2\src\api\api_msg.c - - - - - err.c - 1 - ..\..\components\net\lwip-2.0.2\src\api\err.c - - - - - netbuf.c - 1 - ..\..\components\net\lwip-2.0.2\src\api\netbuf.c - - netdb.c 1 - ..\..\components\net\lwip-2.0.2\src\api\netdb.c - - - - - netifapi.c - 1 - ..\..\components\net\lwip-2.0.2\src\api\netifapi.c - - - - - sockets.c - 1 - ..\..\components\net\lwip-2.0.2\src\api\sockets.c - - - - - tcpip.c - 1 - ..\..\components\net\lwip-2.0.2\src\api\tcpip.c - - - - - def.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\def.c - - - - - dns.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\dns.c - - - - - inet_chksum.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\inet_chksum.c - - - - - init.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\init.c + ..\..\components\net\lwip-2.0.3\src\api\netdb.c ip.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ip.c - - - - - memp.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\memp.c - - - - - netif.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\netif.c - - - - - pbuf.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\pbuf.c - - - - - raw.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\raw.c - - - - - stats.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\stats.c - - - - - sys.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\sys.c - - - - - tcp.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\tcp.c - - - - - tcp_in.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\tcp_in.c - - - - - tcp_out.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\tcp_out.c - - - - - timeouts.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\timeouts.c - - - - - udp.c - 1 - ..\..\components\net\lwip-2.0.2\src\core\udp.c - - - - - ethernet.c - 1 - ..\..\components\net\lwip-2.0.2\src\netif\ethernet.c - - - - - ethernetif.c - 1 - ..\..\components\net\lwip-2.0.2\src\netif\ethernetif.c - - - - - lowpan6.c - 1 - ..\..\components\net\lwip-2.0.2\src\netif\lowpan6.c + ..\..\components\net\lwip-2.0.3\src\core\ip.c autoip.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\autoip.c + ..\..\components\net\lwip-2.0.3\src\core\ipv4\autoip.c - dhcp.c + ethernet.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\dhcp.c + ..\..\components\net\lwip-2.0.3\src\netif\ethernet.c - etharp.c + netif.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\etharp.c + ..\..\components\net\lwip-2.0.3\src\core\netif.c - icmp.c + sys.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\icmp.c + ..\..\components\net\lwip-2.0.3\src\core\sys.c - igmp.c + sockets.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\igmp.c + ..\..\components\net\lwip-2.0.3\src\api\sockets.c - ip4.c + netifapi.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4.c + ..\..\components\net\lwip-2.0.3\src\api\netifapi.c + + + + + tcpip.c + 1 + ..\..\components\net\lwip-2.0.3\src\api\tcpip.c ip4_addr.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_addr.c + ..\..\components\net\lwip-2.0.3\src\core\ipv4\ip4_addr.c + + + + + dhcp.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\ipv4\dhcp.c + + + + + init.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\init.c + + + + + ethernetif.c + 1 + ..\..\components\net\lwip-2.0.3\src\netif\ethernetif.c + + + + + etharp.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\ipv4\etharp.c + + + + + memp.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\memp.c + + + + + ip4.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\ipv4\ip4.c + + + + + netbuf.c + 1 + ..\..\components\net\lwip-2.0.3\src\api\netbuf.c + + + + + raw.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\raw.c ip4_frag.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_frag.c + ..\..\components\net\lwip-2.0.3\src\core\ipv4\ip4_frag.c + + + + + tcp_out.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\tcp_out.c + + + + + lowpan6.c + 1 + ..\..\components\net\lwip-2.0.3\src\netif\lowpan6.c + + + + + icmp.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\ipv4\icmp.c + + + + + api_lib.c + 1 + ..\..\components\net\lwip-2.0.3\src\api\api_lib.c + + + + + inet_chksum.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\inet_chksum.c + + + + + stats.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\stats.c + + + + + err.c + 1 + ..\..\components\net\lwip-2.0.3\src\api\err.c + + + + + tcp_in.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\tcp_in.c + + + + + dns.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\dns.c + + + + + sys_arch.c + 1 + ..\..\components\net\lwip-2.0.3\src\arch\sys_arch.c + + + + + timeouts.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\timeouts.c + + + + + igmp.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\ipv4\igmp.c + + + + + udp.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\udp.c + + + + + pbuf.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\pbuf.c + + + + + def.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\def.c + + + + + api_msg.c + 1 + ..\..\components\net\lwip-2.0.3\src\api\api_msg.c + + + + + ping.c + 1 + ..\..\components\net\lwip-2.0.3\src\apps\ping\ping.c + + + + + tcp.c + 1 + ..\..\components\net\lwip-2.0.3\src\core\tcp.c + + + + + SAL + + + netdev.c + 1 + ..\..\components\net\netdev\src\netdev.c + + + + + netdev_ipaddr.c + 1 + ..\..\components\net\netdev\src\netdev_ipaddr.c + + + + + net_sockets.c + 1 + ..\..\components\net\sal_socket\socket\net_sockets.c + + + + + sal_socket.c + 1 + ..\..\components\net\sal_socket\src\sal_socket.c + + + + + af_inet_lwip.c + 1 + ..\..\components\net\sal_socket\impl\af_inet_lwip.c + + + + + net_netdb.c + 1 + ..\..\components\net\sal_socket\socket\net_netdb.c + + + + + dfs_net.c + 1 + ..\..\components\net\sal_socket\dfs_net\dfs_net.c + + + + + Utilities + + + ry_sy.c + 1 + ..\..\components\utilities\ymodem\ry_sy.c + + + + + ymodem.c + 1 + ..\..\components\utilities\ymodem\ymodem.c diff --git a/bsp/mini2440/rtconfig.h b/bsp/mini2440/rtconfig.h index 37c215bdd0..4cbb6227f6 100644 --- a/bsp/mini2440/rtconfig.h +++ b/bsp/mini2440/rtconfig.h @@ -21,6 +21,9 @@ #define RT_USING_TIMER_SOFT #define RT_TIMER_THREAD_PRIO 4 #define RT_TIMER_THREAD_STACK_SIZE 512 + +/* kservice optimization */ + #define RT_DEBUG /* Inter-Thread communication */ @@ -44,7 +47,7 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart" -#define RT_VER_NUM 0x40003 +#define RT_VER_NUM 0x40004 #define ARCH_ARM #define ARCH_ARM_ARM9 @@ -89,6 +92,8 @@ #define RT_DFS_ELM_WORD_ACCESS #define RT_DFS_ELM_USE_LFN_3 #define RT_DFS_ELM_USE_LFN 3 +#define RT_DFS_ELM_LFN_UNICODE_0 +#define RT_DFS_ELM_LFN_UNICODE 0 #define RT_DFS_ELM_MAX_LFN 255 #define RT_DFS_ELM_DRIVES 2 #define RT_DFS_ELM_MAX_SECTOR_SIZE 512 @@ -104,6 +109,7 @@ #define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 #define RT_SYSTEM_WORKQUEUE_PRIORITY 23 #define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 #define RT_USING_PIN @@ -128,12 +134,14 @@ #define RT_USING_POSIX_AIO #define RT_USING_MODULE #define RT_USING_CUSTOM_DLMODULE +#define RT_LIBC_FIXED_TIMEZONE 8 /* Network */ /* Socket abstraction layer */ #define RT_USING_SAL +#define SAL_INTERNET_CHECK /* protocol stack implement */ @@ -153,7 +161,8 @@ /* light weight TCP/IP stack */ #define RT_USING_LWIP -#define RT_USING_LWIP210 +#define RT_USING_LWIP203 +#define RT_LWIP_MEM_ALIGNMENT 4 #define RT_LWIP_IGMP #define RT_LWIP_ICMP #define RT_LWIP_DNS @@ -189,6 +198,7 @@ #define LWIP_SO_RCVTIMEO 1 #define LWIP_SO_SNDTIMEO 1 #define LWIP_SO_RCVBUF 1 +#define LWIP_SO_LINGER 0 #define RT_LWIP_NETIF_LOOPBACK #define LWIP_NETIF_LOOPBACK 1 #define RT_LWIP_STATS @@ -206,6 +216,9 @@ #define YMODEM_USING_CRC_TABLE #define YMODEM_USING_FILE_TRANSFER +/* RT-Thread Utestcases */ + + /* RT-Thread online packages */ /* IoT - internet of things */ @@ -237,13 +250,22 @@ /* system packages */ +/* Micrium: Micrium software products porting for RT-Thread */ + + /* peripheral libraries and drivers */ +/* AI packages */ + + /* miscellaneous packages */ /* samples: kernel and components samples */ +/* entertainment: terminal games and other interesting software packages */ + + #endif diff --git a/bsp/sam7x/rtconfig.h b/bsp/sam7x/rtconfig.h index ae74c2535e..432f347569 100644 --- a/bsp/sam7x/rtconfig.h +++ b/bsp/sam7x/rtconfig.h @@ -79,6 +79,7 @@ /* SECTION: lwip, a lighwight TCP/IP protocol stack */ /* Using lighweight TCP/IP protocol stack*/ #define RT_USING_LWIP +#define RT_USING_LWIP203 /* Trace LwIP protocol*/ /* #define RT_LWIP_DEBUG */ From 04a2434233355c874b45dc1de0d933bd8ba6b0cc Mon Sep 17 00:00:00 2001 From: chenyingchun0312 Date: Mon, 28 Jun 2021 21:07:52 +0800 Subject: [PATCH 212/255] [bsp/nrf5x] update config file --- bsp/nrf5x/nrf52832/.config | 61 ++++++++++++++++++++++++++++++++--- bsp/nrf5x/nrf52832/rtconfig.h | 14 ++++++-- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/bsp/nrf5x/nrf52832/.config b/bsp/nrf5x/nrf52832/.config index dcc634dfbc..eb4ea7ad34 100644 --- a/bsp/nrf5x/nrf52832/.config +++ b/bsp/nrf5x/nrf52832/.config @@ -23,6 +23,12 @@ CONFIG_IDLE_THREAD_STACK_SIZE=256 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 is not set # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -54,6 +60,7 @@ CONFIG_RT_USING_MEMPOOL=y # CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set CONFIG_RT_USING_HEAP=y @@ -66,7 +73,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=128 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x40003 +CONFIG_RT_VER_NUM=0x40004 # CONFIG_RT_USING_CPU_FFS is not set # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set @@ -114,6 +121,8 @@ 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_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set # CONFIG_RT_SERIAL_USING_DMA is not set CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set @@ -152,6 +161,7 @@ CONFIG_RT_USING_PIN=y CONFIG_RT_USING_LIBC=y # CONFIG_RT_USING_PTHREADS is not set # CONFIG_RT_USING_MODULE is not set +CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # # Network @@ -188,6 +198,12 @@ CONFIG_RT_USING_LIBC=y # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set # # RT-Thread online packages @@ -196,12 +212,15 @@ CONFIG_RT_USING_LIBC=y # # 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 @@ -228,6 +247,7 @@ CONFIG_RT_USING_LIBC=y # 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 @@ -240,7 +260,7 @@ CONFIG_RT_USING_LIBC=y # CONFIG_PKG_USING_GAGENT_CLOUD is not set # CONFIG_PKG_USING_ALI_IOTKIT is not set # CONFIG_PKG_USING_AZURE is not set -# CONFIG_PKG_USING_TENCENT_IOTHUB is not set +# CONFIG_PKG_USING_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 @@ -262,6 +282,11 @@ CONFIG_RT_USING_LIBC=y # CONFIG_PKG_USING_CAPNP is not set # CONFIG_PKG_USING_RT_CJSON_TOOLS is not set # CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set # # security packages @@ -270,6 +295,7 @@ CONFIG_RT_USING_LIBC=y # 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 @@ -286,6 +312,7 @@ CONFIG_RT_USING_LIBC=y # CONFIG_PKG_USING_STEMWIN is not set # CONFIG_PKG_USING_WAVPLAYER is not set # CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_HELIX is not set # # tools packages @@ -304,6 +331,9 @@ CONFIG_RT_USING_LIBC=y # 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 # # system packages @@ -314,6 +344,7 @@ CONFIG_RT_USING_LIBC=y # CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set @@ -326,6 +357,11 @@ CONFIG_RT_USING_LIBC=y # 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_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_PPOOL is not set # # peripheral libraries and drivers @@ -367,6 +403,7 @@ CONFIG_PKG_NRFX_VER="v2.1.0" # 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 @@ -374,6 +411,15 @@ CONFIG_PKG_NRFX_VER="v2.1.0" # 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 # # miscellaneous packages @@ -410,6 +456,11 @@ CONFIG_PKG_NRFX_VER="v2.1.0" # CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set # # Hardware Drivers Config @@ -440,16 +491,18 @@ CONFIG_BSP_USING_UART0=y CONFIG_NRFX_UART0_ENABLED=1 CONFIG_BSP_UART0_RX_PIN=8 CONFIG_BSP_UART0_TX_PIN=6 +# CONFIG_BSP_USING_I2C is not set # CONFIG_BSP_USING_SPI is not set # CONFIG_BSP_USING_ON_CHIP_FLASH is not set +# CONFIG_BSP_USING_ON_CHIP_FS is not set # # On-chip flash config # CONFIG_MCU_FLASH_START_ADDRESS=0x00000000 -CONFIG_MCU_FLASH_SIZE_KB=1024 +CONFIG_MCU_FLASH_SIZE_KB=512 CONFIG_MCU_SRAM_START_ADDRESS=0x20000000 -CONFIG_MCU_SRAM_SIZE_KB=256 +CONFIG_MCU_SRAM_SIZE_KB=64 CONFIG_MCU_FLASH_PAGE_SIZE=0x1000 # CONFIG_BSP_USING_WDT is not set # CONFIG_BSP_USING_ONCHIP_RTC is not set diff --git a/bsp/nrf5x/nrf52832/rtconfig.h b/bsp/nrf5x/nrf52832/rtconfig.h index 2626384351..e61abfaeda 100644 --- a/bsp/nrf5x/nrf52832/rtconfig.h +++ b/bsp/nrf5x/nrf52832/rtconfig.h @@ -19,6 +19,9 @@ #define RT_USING_TIMER_SOFT #define RT_TIMER_THREAD_PRIO 4 #define RT_TIMER_THREAD_STACK_SIZE 512 + +/* kservice optimization */ + #define RT_DEBUG /* Inter-Thread communication */ @@ -41,7 +44,7 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40003 +#define RT_VER_NUM 0x40004 /* RT-Thread Components */ @@ -77,6 +80,7 @@ #define RT_USING_DEVICE_IPC #define RT_PIPE_BUFSZ 512 #define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 #define RT_SERIAL_RB_BUFSZ 64 #define RT_USING_PIN @@ -86,6 +90,7 @@ /* POSIX layer and C standard library */ #define RT_USING_LIBC +#define RT_LIBC_FIXED_TIMEZONE 8 /* Network */ @@ -107,6 +112,9 @@ /* Utilities */ +/* RT-Thread Utestcases */ + + /* RT-Thread online packages */ /* IoT - internet of things */ @@ -175,9 +183,9 @@ /* On-chip flash config */ #define MCU_FLASH_START_ADDRESS 0x00000000 -#define MCU_FLASH_SIZE_KB 1024 +#define MCU_FLASH_SIZE_KB 512 #define MCU_SRAM_START_ADDRESS 0x20000000 -#define MCU_SRAM_SIZE_KB 256 +#define MCU_SRAM_SIZE_KB 64 #define MCU_FLASH_PAGE_SIZE 0x1000 #define BLE_STACK_USING_NULL From 0acbc36e4a383b210b8a709cc8e6697b85d7d426 Mon Sep 17 00:00:00 2001 From: chenyingchun0312 Date: Mon, 28 Jun 2021 22:34:35 +0800 Subject: [PATCH 213/255] [bsp/nrf5x] update config file --- bsp/nrf5x/libraries/drivers/drv_uart.c | 1 - bsp/nrf5x/libraries/drivers/drv_uart.h | 3 +-- bsp/nrf5x/nrf52832/.config | 6 +++--- bsp/nrf5x/nrf52832/.vscode/launch.json | 15 ++++++++------- bsp/nrf5x/nrf52832/rtconfig.h | 2 +- bsp/nrf5x/nrf52832/rtconfig.py | 2 +- bsp/nrf5x/nrf52840/board/board.c | 8 ++++++-- 7 files changed, 20 insertions(+), 17 deletions(-) diff --git a/bsp/nrf5x/libraries/drivers/drv_uart.c b/bsp/nrf5x/libraries/drivers/drv_uart.c index c0c50b736c..217d5fc3db 100644 --- a/bsp/nrf5x/libraries/drivers/drv_uart.c +++ b/bsp/nrf5x/libraries/drivers/drv_uart.c @@ -250,5 +250,4 @@ int rt_hw_uart_init(void) #endif /* BSP_USING_UART0 */ } -INIT_BOARD_EXPORT(rt_hw_uart_init); #endif /* BSP_USING_UART */ diff --git a/bsp/nrf5x/libraries/drivers/drv_uart.h b/bsp/nrf5x/libraries/drivers/drv_uart.h index bdffc4463c..3bf9a2c9b6 100644 --- a/bsp/nrf5x/libraries/drivers/drv_uart.h +++ b/bsp/nrf5x/libraries/drivers/drv_uart.h @@ -11,8 +11,7 @@ #define UART0_RB_SIZE 1024 -// #define USE_UART0_1 0 - +int rt_hw_uart_init(void); #endif diff --git a/bsp/nrf5x/nrf52832/.config b/bsp/nrf5x/nrf52832/.config index eb4ea7ad34..61769240a8 100644 --- a/bsp/nrf5x/nrf52832/.config +++ b/bsp/nrf5x/nrf52832/.config @@ -383,9 +383,9 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # CONFIG_PKG_USING_NRF5X_SDK is not set CONFIG_PKG_USING_NRFX=y CONFIG_PKG_NRFX_PATH="/packages/peripherals/nrfx" -CONFIG_PKG_USING_NRFX_V210=y -# CONFIG_PKG_USING_NRFX_LATEST_VERSION is not set -CONFIG_PKG_NRFX_VER="v2.1.0" +# CONFIG_PKG_USING_NRFX_V210 is not set +CONFIG_PKG_USING_NRFX_LATEST_VERSION=y +CONFIG_PKG_NRFX_VER="latest" # CONFIG_PKG_USING_WM_LIBRARIES is not set # CONFIG_PKG_USING_KENDRYTE_SDK is not set # CONFIG_PKG_USING_INFRARED is not set diff --git a/bsp/nrf5x/nrf52832/.vscode/launch.json b/bsp/nrf5x/nrf52832/.vscode/launch.json index c3a54b371b..9bcc1a8d86 100644 --- a/bsp/nrf5x/nrf52832/.vscode/launch.json +++ b/bsp/nrf5x/nrf52832/.vscode/launch.json @@ -2,14 +2,15 @@ "version": "0.2.0", "configurations": [ { - "type": "cortex-debug", - "request": "launch", - "servertype": "jlink", "cwd": "${workspaceRoot}", "executable": "rt-thread.elf", - "name": "Cortex Debug", - "device": "nrf52", - "interface": "swd" - } + "name": "Debug MAX", + "request": "launch", + "type": "cortex-debug", + "servertype": "jlink", + "interface": "swd", + "device": "NRF52832_XXAA", + "runToMain": true + }, ] } \ No newline at end of file diff --git a/bsp/nrf5x/nrf52832/rtconfig.h b/bsp/nrf5x/nrf52832/rtconfig.h index e61abfaeda..ee2691d102 100644 --- a/bsp/nrf5x/nrf52832/rtconfig.h +++ b/bsp/nrf5x/nrf52832/rtconfig.h @@ -149,7 +149,7 @@ /* peripheral libraries and drivers */ #define PKG_USING_NRFX -#define PKG_USING_NRFX_V210 +#define PKG_USING_NRFX_LATEST_VERSION /* miscellaneous packages */ diff --git a/bsp/nrf5x/nrf52832/rtconfig.py b/bsp/nrf5x/nrf52832/rtconfig.py index d065edfe02..805feeae54 100644 --- a/bsp/nrf5x/nrf52832/rtconfig.py +++ b/bsp/nrf5x/nrf52832/rtconfig.py @@ -13,7 +13,7 @@ if os.getenv('RTT_CC'): if CROSS_TOOL == 'gcc': PLATFORM = 'gcc' - EXEC_PATH = r'D:\RT-ThreadStudio\repo\Extract\ToolChain_Support_Packages\ARM\GNU_Tools_for_ARM_Embedded_Processors\5.4.1\bin' + EXEC_PATH = 'D:/SourceryGCC/bin' elif CROSS_TOOL == 'keil': PLATFORM = 'armcc' EXEC_PATH = 'C:/Keil_v5' diff --git a/bsp/nrf5x/nrf52840/board/board.c b/bsp/nrf5x/nrf52840/board/board.c index 961a027e95..7adafe36fe 100644 --- a/bsp/nrf5x/nrf52840/board/board.c +++ b/bsp/nrf5x/nrf52840/board/board.c @@ -61,14 +61,18 @@ void rt_hw_board_init(void) rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); #endif -#ifdef RT_USING_COMPONENTS_INIT - rt_components_board_init(); +#ifdef RT_USING_SERIAL + rt_hw_uart_init(); #endif #ifdef RT_USING_CONSOLE rt_console_set_device(RT_CONSOLE_DEVICE_NAME); #endif +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + #ifdef BSP_USING_SOFTDEVICE extern uint32_t Image$$RW_IRAM1$$Base; From 75e575476b8de3836a34c407cd26f9c6e4453cde Mon Sep 17 00:00:00 2001 From: chenyingchun0312 Date: Mon, 28 Jun 2021 22:57:40 +0800 Subject: [PATCH 214/255] [bsp/nrf5x] update link.lds --- .../nrf52832/board/linker_scripts/link.lds | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/bsp/nrf5x/nrf52832/board/linker_scripts/link.lds b/bsp/nrf5x/nrf52832/board/linker_scripts/link.lds index f436d3fcec..f4cf7ebbf7 100644 --- a/bsp/nrf5x/nrf52832/board/linker_scripts/link.lds +++ b/bsp/nrf5x/nrf52832/board/linker_scripts/link.lds @@ -127,38 +127,4 @@ SECTIONS PROVIDE(__bss_start__ = __bss_start); PROVIDE(__bss_end__ = __bss_end); PROVIDE(__StackTop = _estack); - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - * Symbols in the DWARF debugging sections are relative to the beginning - * of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } } From 551923578f65d13aed4461c7e846a7e41fd1e42f Mon Sep 17 00:00:00 2001 From: crazt Date: Tue, 29 Jun 2021 20:47:02 +0800 Subject: [PATCH 215/255] [bsp/stm32] add robomaster c board. --- bsp/stm32/stm32f407-robomaster-c/.config | 351 ++ bsp/stm32/stm32f407-robomaster-c/.gitignore | 42 + bsp/stm32/stm32f407-robomaster-c/Kconfig | 21 + bsp/stm32/stm32f407-robomaster-c/README.md | 124 + bsp/stm32/stm32f407-robomaster-c/SConscript | 15 + bsp/stm32/stm32f407-robomaster-c/SConstruct | 60 + .../applications/SConscript | 12 + .../applications/main.c | 33 + .../board/CubeMX_Config/.mxproject | 17 + .../board/CubeMX_Config/CubeMX_Config.ioc | 121 + .../board/CubeMX_Config/Inc/main.h | 91 + .../CubeMX_Config/Inc/stm32f4xx_hal_conf.h | 451 +++ .../board/CubeMX_Config/Inc/stm32f4xx_it.h | 85 + .../board/CubeMX_Config/Src/main.c | 250 ++ .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 177 + .../board/CubeMX_Config/Src/stm32f4xx_it.c | 232 ++ .../stm32f407-robomaster-c/board/Kconfig | 44 + .../stm32f407-robomaster-c/board/SConscript | 37 + .../stm32f407-robomaster-c/board/board.c | 49 + .../stm32f407-robomaster-c/board/board.h | 50 + .../board/linker_scripts/link.icf | 28 + .../board/linker_scripts/link.lds | 157 + .../board/linker_scripts/link.sct | 15 + .../stm32f407-robomaster-c/figures/board.png | Bin 0 -> 177116 bytes bsp/stm32/stm32f407-robomaster-c/project.ewd | 2834 +++++++++++++++++ bsp/stm32/stm32f407-robomaster-c/project.ewp | 2410 ++++++++++++++ bsp/stm32/stm32f407-robomaster-c/project.eww | 10 + .../stm32f407-robomaster-c/project.uvopt | 162 + .../stm32f407-robomaster-c/project.uvoptx | 191 ++ .../stm32f407-robomaster-c/project.uvproj | 1189 +++++++ .../stm32f407-robomaster-c/project.uvprojx | 1170 +++++++ bsp/stm32/stm32f407-robomaster-c/rtconfig.h | 173 + bsp/stm32/stm32f407-robomaster-c/rtconfig.py | 150 + bsp/stm32/stm32f407-robomaster-c/template.ewp | 2031 ++++++++++++ bsp/stm32/stm32f407-robomaster-c/template.eww | 10 + .../stm32f407-robomaster-c/template.uvopt | 162 + .../stm32f407-robomaster-c/template.uvoptx | 191 ++ .../stm32f407-robomaster-c/template.uvproj | 407 +++ .../stm32f407-robomaster-c/template.uvprojx | 394 +++ 39 files changed, 13946 insertions(+) create mode 100644 bsp/stm32/stm32f407-robomaster-c/.config create mode 100644 bsp/stm32/stm32f407-robomaster-c/.gitignore create mode 100644 bsp/stm32/stm32f407-robomaster-c/Kconfig create mode 100644 bsp/stm32/stm32f407-robomaster-c/README.md create mode 100644 bsp/stm32/stm32f407-robomaster-c/SConscript create mode 100644 bsp/stm32/stm32f407-robomaster-c/SConstruct create mode 100644 bsp/stm32/stm32f407-robomaster-c/applications/SConscript create mode 100644 bsp/stm32/stm32f407-robomaster-c/applications/main.c create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/.mxproject create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/main.h create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_it.h create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/main.c create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_it.c create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/Kconfig create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/SConscript create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/board.c create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/board.h create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.icf create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.lds create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.sct create mode 100644 bsp/stm32/stm32f407-robomaster-c/figures/board.png create mode 100644 bsp/stm32/stm32f407-robomaster-c/project.ewd create mode 100644 bsp/stm32/stm32f407-robomaster-c/project.ewp create mode 100644 bsp/stm32/stm32f407-robomaster-c/project.eww create mode 100644 bsp/stm32/stm32f407-robomaster-c/project.uvopt create mode 100644 bsp/stm32/stm32f407-robomaster-c/project.uvoptx create mode 100644 bsp/stm32/stm32f407-robomaster-c/project.uvproj create mode 100644 bsp/stm32/stm32f407-robomaster-c/project.uvprojx create mode 100644 bsp/stm32/stm32f407-robomaster-c/rtconfig.h create mode 100644 bsp/stm32/stm32f407-robomaster-c/rtconfig.py create mode 100644 bsp/stm32/stm32f407-robomaster-c/template.ewp create mode 100644 bsp/stm32/stm32f407-robomaster-c/template.eww create mode 100644 bsp/stm32/stm32f407-robomaster-c/template.uvopt create mode 100644 bsp/stm32/stm32f407-robomaster-c/template.uvoptx create mode 100644 bsp/stm32/stm32f407-robomaster-c/template.uvproj create mode 100644 bsp/stm32/stm32f407-robomaster-c/template.uvprojx diff --git a/bsp/stm32/stm32f407-robomaster-c/.config b/bsp/stm32/stm32f407-robomaster-c/.config new file mode 100644 index 0000000000..13a4d62a3a --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/.config @@ -0,0 +1,351 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=1000 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +CONFIG_RT_VER_NUM=0x40000 +CONFIG_ARCH_ARM=y +CONFIG_ARCH_ARM_CORTEX_M=y +CONFIG_ARCH_ARM_CORTEX_M4=y +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_CMD_SIZE=80 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +CONFIG_FINSH_USING_MSH_ONLY=y +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_SERIAL_USING_DMA=y +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_MTD is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set + +# +# Using WiFi +# +# 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 is not set +# CONFIG_RT_USING_PTHREADS is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# Modbus master and slave stack +# +# CONFIG_RT_USING_MODBUS is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_LOGTRACE is not set +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set + +# +# ARM CMSIS +# +# CONFIG_RT_USING_CMSIS_OS is not set +# CONFIG_RT_USING_RTT_CMSIS is not set +# CONFIG_RT_USING_LWP is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_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_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_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_IOTKIT is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_TINYCRYPT is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set + +# +# multimedia packages +# +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set + +# +# system packages +# +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_PERSIMMON is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_CMSIS is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_AHT10 is not set +# CONFIG_PKG_USING_AP3216C 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_MPU6XXX is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set + +# +# miscellaneous packages +# +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set + +# +# 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_SOC_FAMILY_STM32=y +CONFIG_SOC_SERIES_STM32F4=y + +# +# Hardware Drivers Config +# +CONFIG_SOC_STM32F407ZG=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_UART1_RX_USING_DMA is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_I2C1 is not set + +# +# Board extended module Drivers +# diff --git a/bsp/stm32/stm32f407-robomaster-c/.gitignore b/bsp/stm32/stm32f407-robomaster-c/.gitignore new file mode 100644 index 0000000000..7221bde019 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/.gitignore @@ -0,0 +1,42 @@ +*.pyc +*.map +*.dblite +*.elf +*.bin +*.hex +*.axf +*.exe +*.pdb +*.idb +*.ilk +*.old +build +Debug +documentation/html +packages/ +*~ +*.o +*.obj +*.out +*.bak +*.dep +*.lib +*.i +*.d +.DS_Stor* +.config 3 +.config 4 +.config 5 +Midea-X1 +*.uimg +GPATH +GRTAGS +GTAGS +.vscode +JLinkLog.txt +JLinkSettings.ini +DebugConfig/ +RTE/ +settings/ +*.uvguix* +cconfig.h diff --git a/bsp/stm32/stm32f407-robomaster-c/Kconfig b/bsp/stm32/stm32f407-robomaster-c/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread 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" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/stm32/stm32f407-robomaster-c/README.md b/bsp/stm32/stm32f407-robomaster-c/README.md new file mode 100644 index 0000000000..59fb59d3dd --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/README.md @@ -0,0 +1,124 @@ +# BSP README 模板 + +## 简介 + +本文档为 xxx 开发板的 BSP (板级支持包) 说明。 + +主要内容如下: + +- 开发板资源介绍 +- BSP 快速上手 +- 进阶使用方法 + +通过阅读快速上手章节开发者可以快速地上手该 BSP,将 RT-Thread 运行在开发板上。在进阶使用指南章节,将会介绍更多高级功能,帮助开发者利用 RT-Thread 驱动更多板载资源。 + +## 开发板介绍 + +【此处简单介绍一下开发板】 + +开发板外观如下图所示: + +![board](figures/board.png) + +该开发板常用 **板载资源** 如下: + +- MCU:STM32xxx,主频 xxxMHz,xxxKB FLASH ,xxxKB RAM +- 外部 RAM:型号,xMB +- 外部 FLASH:型号,xMB +- 常用外设 + - LED:x个,DS0(红色,PB1),DS1(绿色,PB0) + - 按键:x个,K0(兼具唤醒功能,PA0),K1(PC13) +- 常用接口:USB 转串口、SD 卡接口、以太网接口、LCD 接口等 +- 调试接口,标准 JTAG/SWD + +开发板更多详细信息请参考【厂商名】 [xxx开发板介绍](https://xxx)。 + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **板载外设** | **支持情况** | **备注** | +| :----------------- | :----------: | :------------------------------------- | +| USB 转串口 | 支持 | | +| SPI Flash | 支持 | | +| 以太网 | 支持 | | +| SD卡 | 暂不支持 | | +| CAN | 暂不支持 | | +| **片上外设** | **支持情况** | **备注** | +| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...176 | +| UART | 支持 | UART1/x/x | +| SPI | 支持 | SPI1/x/x | +| I2C | 支持 | 软件 I2C | +| SDIO | 暂不支持 | 即将支持 | +| RTC | 暂不支持 | 即将支持 | +| PWM | 暂不支持 | 即将支持 | +| USB Device | 暂不支持 | 即将支持 | +| USB Host | 暂不支持 | 即将支持 | +| IWG | 暂不支持 | 即将支持 | +| xxx | 暂不支持 | 即将支持 | +| **扩展模块** | **支持情况** | **备注** | +| xxx 模块 | 支持 | | + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + + +### 快速上手 + +本 BSP 为开发者提供 MDK4、MDK5 和 IAR 工程,并且支持 GCC 开发环境。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 xxx 仿真器下载程序,在通过 xxx 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,【这里写开发板运行起来之后的现象,如:LED 闪烁等】。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 3.1.1 build Nov 19 2018 + 2006 - 2018 Copyright by rt-thread team +msh > +``` +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1 的功能,如果需使用 SD 卡、Flash 等更多高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5/iar` 命令重新生成工程。 + +本章节更多详细的介绍请参考 [STM32 系列 BSP 外设驱动使用教程](../docs/STM32系列BSP外设驱动使用教程.md)。 + +## 注意事项 + +- xxx + +## 联系人信息 + +维护人: + +- [xxx](https://个人主页), 邮箱: \ No newline at end of file diff --git a/bsp/stm32/stm32f407-robomaster-c/SConscript b/bsp/stm32/stm32f407-robomaster-c/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/stm32/stm32f407-robomaster-c/SConstruct b/bsp/stm32/stm32f407-robomaster-c/SConstruct new file mode 100644 index 0000000000..945cb55a52 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rt-thread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rt-thread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +stm32_library = 'STM32F4xx_HAL' +rtconfig.BSP_LIBRARY_TYPE = stm32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, stm32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'HAL_Drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/stm32/stm32f407-robomaster-c/applications/SConscript b/bsp/stm32/stm32f407-robomaster-c/applications/SConscript new file mode 100644 index 0000000000..6f66f7ab73 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/applications/SConscript @@ -0,0 +1,12 @@ +import rtconfig +from building import * + +cwd = GetCurrentDir() +CPPPATH = [cwd, str(Dir('#'))] +src = Split(""" +main.c +""") + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/stm32/stm32f407-robomaster-c/applications/main.c b/bsp/stm32/stm32f407-robomaster-c/applications/main.c new file mode 100644 index 0000000000..487ddf44f6 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/applications/main.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-11-06 SummerGift first version + */ + +#include +#include +#include + +/* defined the LED0 pin: PB1 */ +#define LED0_PIN GET_PIN(B, 1) + +int main(void) +{ + int count = 1; + /* set LED0 pin mode to output */ + rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED0_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED0_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/.mxproject b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/.mxproject new file mode 100644 index 0000000000..9346fc2058 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/.mxproject @@ -0,0 +1,17 @@ +[PreviousGenFiles] +HeaderPath=E:/git_project/BspFramework/rt-thread/bsp/stm32/stm32f4xx/board/CubeMX_Config/Inc +HeaderFiles=stm32f4xx_it.h;stm32f4xx_hal_conf.h;main.h; +SourcePath=E:/git_project/BspFramework/rt-thread/bsp/stm32/stm32f4xx/board/CubeMX_Config/Src +SourceFiles=stm32f4xx_it.c;stm32f4xx_hal_msp.c;main.c; + +[PreviousLibFiles] +LibFiles=Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f407xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;Drivers/CMSIS/Include/arm_common_tables.h;Drivers/CMSIS/Include/arm_const_structs.h;Drivers/CMSIS/Include/arm_math.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/cmsis_armcc_V6.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_cm3.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_cmFunc.h;Drivers/CMSIS/Include/core_cmInstr.h;Drivers/CMSIS/Include/core_cmSimd.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/core_sc300.h; + +[PreviousUsedIarFiles] +SourceFiles=..\Src\main.c;..\Src\stm32f4xx_it.c;..\Src\stm32f4xx_hal_msp.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;null; +HeaderPath=..\Drivers\STM32F4xx_HAL_Driver\Inc;..\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32F4xx\Include;..\Drivers\CMSIS\Include;..\Inc; + +[PreviousUsedKeilFiles] +SourceFiles=..\Src\main.c;..\Src\stm32f4xx_it.c;..\Src\stm32f4xx_hal_msp.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;null; +HeaderPath=..\Drivers\STM32F4xx_HAL_Driver\Inc;..\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32F4xx\Include;..\Drivers\CMSIS\Include;..\Inc; + diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc new file mode 100644 index 0000000000..819eb4c535 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc @@ -0,0 +1,121 @@ +#MicroXplorer Configuration settings - do not modify +File.Version=6 +KeepUserPlacement=false +Mcu.Family=STM32F4 +Mcu.IP0=NVIC +Mcu.IP1=RCC +Mcu.IP2=SYS +Mcu.IP3=USART1 +Mcu.IPNb=4 +Mcu.Name=STM32F407Z(E-G)Tx +Mcu.Package=LQFP144 +Mcu.Pin0=PH0-OSC_IN +Mcu.Pin1=PH1-OSC_OUT +Mcu.Pin2=PA9 +Mcu.Pin3=PA10 +Mcu.Pin4=PA13 +Mcu.Pin5=PA14 +Mcu.Pin6=VP_SYS_VS_Systick +Mcu.PinsNb=7 +Mcu.ThirdPartyNb=0 +Mcu.UserConstants= +Mcu.UserName=STM32F407ZGTx +MxCube.Version=5.0.0 +MxDb.Version=DB.5.0.0 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false +PA10.Mode=Asynchronous +PA10.Signal=USART1_RX +PA13.Mode=Serial_Wire +PA13.Signal=SYS_JTMS-SWDIO +PA14.Mode=Serial_Wire +PA14.Signal=SYS_JTCK-SWCLK +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PCC.Checker=false +PCC.Line=STM32F407/417 +PCC.MCU=STM32F407Z(E-G)Tx +PCC.PartNumber=STM32F407ZGTx +PCC.Seq0=0 +PCC.Series=STM32F4 +PCC.Temperature=25 +PCC.Vdd=3.3 +PH0-OSC_IN.Mode=HSE-External-Oscillator +PH0-OSC_IN.Signal=RCC_OSC_IN +PH1-OSC_OUT.Mode=HSE-External-Oscillator +PH1-OSC_OUT.Signal=RCC_OSC_OUT +PinOutPanel.RotationAngle=0 +ProjectManager.AskForMigrate=true +ProjectManager.BackupPrevious=false +ProjectManager.CompilerOptimize=6 +ProjectManager.ComputerToolchain=false +ProjectManager.CoupleFile=false +ProjectManager.CustomerFirmwarePackage= +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +ProjectManager.DeviceId=STM32F407ZGTx +ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.22.0 +ProjectManager.FreePins=false +ProjectManager.HalAssertFull=false +ProjectManager.HeapSize=0x200 +ProjectManager.KeepUserCode=true +ProjectManager.LastFirmware=true +ProjectManager.LibraryCopy=0 +ProjectManager.MainLocation=Src +ProjectManager.NoMain=false +ProjectManager.PreviousToolchain= +ProjectManager.ProjectBuild=false +ProjectManager.ProjectFileName=CubeMX_Config.ioc +ProjectManager.ProjectName=CubeMX_Config +ProjectManager.StackSize=0x400 +ProjectManager.TargetToolchain=MDK-ARM V5 +ProjectManager.ToolChainLocation= +ProjectManager.UnderRoot=false +ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_USART1_UART_Init-USART1-false-HAL-true +RCC.48MHZClocksFreq_Value=84000000 +RCC.AHBFreq_Value=168000000 +RCC.APB1CLKDivider=RCC_HCLK_DIV4 +RCC.APB1Freq_Value=42000000 +RCC.APB1TimFreq_Value=84000000 +RCC.APB2CLKDivider=RCC_HCLK_DIV2 +RCC.APB2Freq_Value=84000000 +RCC.APB2TimFreq_Value=168000000 +RCC.CortexFreq_Value=168000000 +RCC.EthernetFreq_Value=168000000 +RCC.FCLKCortexFreq_Value=168000000 +RCC.FamilyName=M +RCC.HCLKFreq_Value=168000000 +RCC.HSE_VALUE=8000000 +RCC.HSI_VALUE=16000000 +RCC.I2SClocksFreq_Value=192000000 +RCC.IPParameters=48MHZClocksFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2SClocksFreq_Value,LSE_VALUE,LSI_VALUE,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLM,PLLN,PLLQCLKFreq_Value,PLLSourceVirtual,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VcooutputI2S +RCC.LSE_VALUE=32768 +RCC.LSI_VALUE=32000 +RCC.MCO2PinFreq_Value=168000000 +RCC.PLLCLKFreq_Value=168000000 +RCC.PLLM=4 +RCC.PLLN=168 +RCC.PLLQCLKFreq_Value=84000000 +RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE +RCC.RTCFreq_Value=32000 +RCC.RTCHSEDivFreq_Value=4000000 +RCC.SYSCLKFreq_VALUE=168000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +RCC.VCOI2SOutputFreq_Value=384000000 +RCC.VCOInputFreq_Value=2000000 +RCC.VCOOutputFreq_Value=336000000 +RCC.VcooutputI2S=192000000 +USART1.IPParameters=VirtualMode +USART1.VirtualMode=VM_ASYNC +VP_SYS_VS_Systick.Mode=SysTick +VP_SYS_VS_Systick.Signal=SYS_VS_Systick +board=custom diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/main.h b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/main.h new file mode 100644 index 0000000000..9d41187606 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/main.h @@ -0,0 +1,91 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + ** This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * COPYRIGHT(c) 2018 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void Error_Handler(void); + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h new file mode 100644 index 0000000000..9db422a140 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h @@ -0,0 +1,451 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2018 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_CONF_H +#define __STM32F4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED + +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +/* #define HAL_DCMI_MODULE_ENABLED */ +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_PCCARD_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +/* #define HAL_I2C_MODULE_ENABLED */ +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LTDC_MODULE_ENABLED */ +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +/* #define HAL_SAI_MODULE_ENABLED */ +/* #define HAL_SD_MODULE_ENABLED */ +/* #define HAL_MMC_MODULE_ENABLED */ +/* #define HAL_SPI_MODULE_ENABLED */ +/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +/* #define HAL_PCD_MODULE_ENABLED */ +/* #define HAL_HCD_MODULE_ENABLED */ +/* #define HAL_DSI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_CEC_MODULE_ENABLED */ +/* #define HAL_FMPI2C_MODULE_ENABLED */ +/* #define HAL_SPDIFRX_MODULE_ENABLED */ +/* #define HAL_DFSDM_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_EXTI_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x000000FFU) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU) + +#define PHY_READ_TO ((uint32_t)0x0000FFFFU) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f4xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f4xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f4xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32f4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f4xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED + #include "stm32f4xx_hal_fmpi2c.h" +#endif /* HAL_FMPI2C_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32f4xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32f4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32f4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_it.h b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_it.h new file mode 100644 index 0000000000..e3b003d9ad --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_it.h @@ -0,0 +1,85 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f4xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * + * COPYRIGHT(c) 2018 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_IT_H +#define __STM32F4xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); +void USART1_IRQHandler(void); +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_IT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/main.c b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/main.c new file mode 100644 index 0000000000..a6cbc9fece --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/main.c @@ -0,0 +1,250 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + ** This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * COPYRIGHT(c) 2018 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +UART_HandleTypeDef huart1; + +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +static void MX_GPIO_Init(void); +static void MX_USART1_UART_Init(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + + /* USER CODE BEGIN Init */ + + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_USART1_UART_Init(); + /* USER CODE BEGIN 2 */ + + /* USER CODE END 2 */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + } + /* USER CODE END 3 */ +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + + /**Configure the main internal regulator output voltage + */ + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + /**Initializes the CPU, AHB and APB busses clocks + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 4; + RCC_OscInitStruct.PLL.PLLN = 168; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 4; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + /**Initializes the CPU, AHB and APB busses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief USART1 Initialization Function + * @param None + * @retval None + */ +static void MX_USART1_UART_Init(void) +{ + + /* USER CODE BEGIN USART1_Init 0 */ + + /* USER CODE END USART1_Init 0 */ + + /* USER CODE BEGIN USART1_Init 1 */ + + /* USER CODE END USART1_Init 1 */ + huart1.Instance = USART1; + huart1.Init.BaudRate = 115200; + huart1.Init.WordLength = UART_WORDLENGTH_8B; + huart1.Init.StopBits = UART_STOPBITS_1; + huart1.Init.Parity = UART_PARITY_NONE; + huart1.Init.Mode = UART_MODE_TX_RX; + huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart1.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&huart1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN USART1_Init 2 */ + + /* USER CODE END USART1_Init 2 */ + +} + +/** + * @brief GPIO Initialization Function + * @param None + * @retval None + */ +static void MX_GPIO_Init(void) +{ + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + + /* USER CODE END Error_Handler_Debug */ +} + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c new file mode 100644 index 0000000000..e00b8556d6 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -0,0 +1,177 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : stm32f4xx_hal_msp.c + * Description : This file provides code for the MSP Initialization + * and de-Initialization codes. + ****************************************************************************** + ** This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * COPYRIGHT(c) 2018 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN Define */ + +/* USER CODE END Define */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN Macro */ + +/* USER CODE END Macro */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* External functions --------------------------------------------------------*/ +/* USER CODE BEGIN ExternalFunctions */ + +/* USER CODE END ExternalFunctions */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ +/** + * Initializes the Global MSP. + */ +void HAL_MspInit(void) +{ + /* USER CODE BEGIN MspInit 0 */ + + /* USER CODE END MspInit 0 */ + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + /* System interrupt init*/ + + /* USER CODE BEGIN MspInit 1 */ + + /* USER CODE END MspInit 1 */ +} + +/** +* @brief UART MSP Initialization +* This function configures the hardware resources used in this example +* @param huart: UART handle pointer +* @retval None +*/ +void HAL_UART_MspInit(UART_HandleTypeDef* huart) +{ + + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(huart->Instance==USART1) + { + /* USER CODE BEGIN USART1_MspInit 0 */ + + /* USER CODE END USART1_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_USART1_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USART1 GPIO Configuration + PA9 ------> USART1_TX + PA10 ------> USART1_RX + */ + GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF7_USART1; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USART1 interrupt Init */ + HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(USART1_IRQn); + /* USER CODE BEGIN USART1_MspInit 1 */ + + /* USER CODE END USART1_MspInit 1 */ + } + +} + +/** +* @brief UART MSP De-Initialization +* This function freeze the hardware resources used in this example +* @param huart: UART handle pointer +* @retval None +*/ + +void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) +{ + + if(huart->Instance==USART1) + { + /* USER CODE BEGIN USART1_MspDeInit 0 */ + + /* USER CODE END USART1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART1_CLK_DISABLE(); + + /**USART1 GPIO Configuration + PA9 ------> USART1_TX + PA10 ------> USART1_RX + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); + + /* USART1 interrupt DeInit */ + HAL_NVIC_DisableIRQ(USART1_IRQn); + /* USER CODE BEGIN USART1_MspDeInit 1 */ + + /* USER CODE END USART1_MspDeInit 1 */ + } + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_it.c b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_it.c new file mode 100644 index 0000000000..80653c5ad3 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_it.c @@ -0,0 +1,232 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f4xx_it.c + * @brief Interrupt Service Routines. + ****************************************************************************** + * + * COPYRIGHT(c) 2018 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "stm32f4xx_it.h" +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* External variables --------------------------------------------------------*/ +extern UART_HandleTypeDef huart1; +/* USER CODE BEGIN EV */ + +/* USER CODE END EV */ + +/******************************************************************************/ +/* Cortex-M4 Processor Interruption and Exception Handlers */ +/******************************************************************************/ +/** + * @brief This function handles Non maskable interrupt. + */ +void NMI_Handler(void) +{ + /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ + + /* USER CODE END NonMaskableInt_IRQn 0 */ + /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ + + /* USER CODE END NonMaskableInt_IRQn 1 */ +} + +/** + * @brief This function handles Hard fault interrupt. + */ +void HardFault_Handler(void) +{ + /* USER CODE BEGIN HardFault_IRQn 0 */ + + /* USER CODE END HardFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_HardFault_IRQn 0 */ + /* USER CODE END W1_HardFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Memory management fault. + */ +void MemManage_Handler(void) +{ + /* USER CODE BEGIN MemoryManagement_IRQn 0 */ + + /* USER CODE END MemoryManagement_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ + /* USER CODE END W1_MemoryManagement_IRQn 0 */ + } +} + +/** + * @brief This function handles Pre-fetch fault, memory access fault. + */ +void BusFault_Handler(void) +{ + /* USER CODE BEGIN BusFault_IRQn 0 */ + + /* USER CODE END BusFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_BusFault_IRQn 0 */ + /* USER CODE END W1_BusFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Undefined instruction or illegal state. + */ +void UsageFault_Handler(void) +{ + /* USER CODE BEGIN UsageFault_IRQn 0 */ + + /* USER CODE END UsageFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ + /* USER CODE END W1_UsageFault_IRQn 0 */ + } +} + +/** + * @brief This function handles System service call via SWI instruction. + */ +void SVC_Handler(void) +{ + /* USER CODE BEGIN SVCall_IRQn 0 */ + + /* USER CODE END SVCall_IRQn 0 */ + /* USER CODE BEGIN SVCall_IRQn 1 */ + + /* USER CODE END SVCall_IRQn 1 */ +} + +/** + * @brief This function handles Debug monitor. + */ +void DebugMon_Handler(void) +{ + /* USER CODE BEGIN DebugMonitor_IRQn 0 */ + + /* USER CODE END DebugMonitor_IRQn 0 */ + /* USER CODE BEGIN DebugMonitor_IRQn 1 */ + + /* USER CODE END DebugMonitor_IRQn 1 */ +} + +/** + * @brief This function handles Pendable request for system service. + */ +void PendSV_Handler(void) +{ + /* USER CODE BEGIN PendSV_IRQn 0 */ + + /* USER CODE END PendSV_IRQn 0 */ + /* USER CODE BEGIN PendSV_IRQn 1 */ + + /* USER CODE END PendSV_IRQn 1 */ +} + +/** + * @brief This function handles System tick timer. + */ +void SysTick_Handler(void) +{ + /* USER CODE BEGIN SysTick_IRQn 0 */ + + /* USER CODE END SysTick_IRQn 0 */ + HAL_IncTick(); + /* USER CODE BEGIN SysTick_IRQn 1 */ + + /* USER CODE END SysTick_IRQn 1 */ +} + +/******************************************************************************/ +/* STM32F4xx Peripheral Interrupt Handlers */ +/* Add here the Interrupt Handlers for the used peripherals. */ +/* For the available peripheral interrupt handler names, */ +/* please refer to the startup file (startup_stm32f4xx.s). */ +/******************************************************************************/ + +/** + * @brief This function handles USART1 global interrupt. + */ +void USART1_IRQHandler(void) +{ + /* USER CODE BEGIN USART1_IRQn 0 */ + + /* USER CODE END USART1_IRQn 0 */ + HAL_UART_IRQHandler(&huart1); + /* USER CODE BEGIN USART1_IRQn 1 */ + + /* USER CODE END USART1_IRQn 1 */ +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/Kconfig b/bsp/stm32/stm32f407-robomaster-c/board/Kconfig new file mode 100644 index 0000000000..24a15a4e3e --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/Kconfig @@ -0,0 +1,44 @@ +menu "Hardware Drivers Config" + +config SOC_STM32F407ZG + bool + select SOC_SERIES_STM32F4 + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + source "../libraries/HAL_Drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/stm32/stm32f407-robomaster-c/board/SConscript b/bsp/stm32/stm32f407-robomaster-c/board/SConscript new file mode 100644 index 0000000000..091f29472a --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/SConscript @@ -0,0 +1,37 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +CubeMX_Config/Src/stm32f4xx_hal_msp.c +''') + +path = [cwd] +path += [cwd + '/CubeMX_Config/Inc'] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/STM32F4xx_HAL/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f407xx.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/STM32F4xx_HAL/CMSIS/Device/ST/STM32F4xx/Source/Templates/arm/startup_stm32f407xx.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/STM32F4xx_HAL/CMSIS/Device/ST/STM32F4xx/Source/Templates/iar/startup_stm32f407xx.s'] + +# STM32F405xx) || STM32F415xx) || STM32F407xx) || STM32F417xx) +# STM32F427xx) || STM32F437xx) || STM32F429xx) || STM32F439xx) +# STM32F401xC) || STM32F401xE) || STM32F410Tx) || STM32F410Cx) +# STM32F410Rx) || STM32F411xE) || STM32F446xx) || STM32F469xx) +# STM32F479xx) || STM32F412Cx) || STM32F412Rx) || STM32F412Vx) +# STM32F412Zx) || STM32F413xx) || STM32F423xx) +# You can select chips from the list above +CPPDEFINES = ['STM32F407xx'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/stm32/stm32f407-robomaster-c/board/board.c b/bsp/stm32/stm32f407-robomaster-c/board/board.c new file mode 100644 index 0000000000..ef1f24cbb5 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/board.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-11-06 SummerGift first version + */ + +#include "board.h" + +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + + /**Configure the main internal regulator output voltage + */ + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + /**Initializes the CPU, AHB and APB busses clocks + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 4; + RCC_OscInitStruct.PLL.PLLN = 168; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 4; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + /**Initializes the CPU, AHB and APB busses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) + { + Error_Handler(); + } +} diff --git a/bsp/stm32/stm32f407-robomaster-c/board/board.h b/bsp/stm32/stm32f407-robomaster-c/board/board.h new file mode 100644 index 0000000000..514155b823 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/board.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-11-5 SummerGift first version + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include +#include +#include "drv_common.h" +#include "drv_gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define STM32_FLASH_START_ADRESS ((uint32_t)0x08000000) +#define STM32_FLASH_SIZE (1024 * 1024) +#define STM32_FLASH_END_ADDRESS ((uint32_t)(STM32_FLASH_START_ADRESS + STM32_FLASH_SIZE)) + +#define STM32_SRAM_SIZE 128 +#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024) + +#if defined(__CC_ARM) || defined(__CLANG_ARM) +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="CSTACK" +#define HEAP_BEGIN (__segment_end("CSTACK")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END STM32_SRAM_END + +void SystemClock_Config(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.icf b/bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.icf new file mode 100644 index 0000000000..067691151f --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.icf @@ -0,0 +1,28 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x080FFFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x2001FFFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x0400; +define symbol __ICFEDIT_size_heap__ = 0x0000; +/**** End of ICF editor section. ###ICF###*/ + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, last block CSTACK}; diff --git a/bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.lds b/bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.lds new file mode 100644 index 0000000000..50169db320 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.lds @@ -0,0 +1,157 @@ +/* + * linker script for STM32F4xx with GNU ld + * bernard.xiong 2009-10-14 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + ROM (rx) : ORIGIN = 0x08000000, LENGTH = 1024k /* 1024KB flash */ + RAM (rw) : ORIGIN = 0x20000000, LENGTH = 128k /* 128K sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + + . = ALIGN(4); + + PROVIDE(__ctors_start__ = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE(__ctors_end__ = .); + + . = ALIGN(4); + + _etext = .; + } > ROM = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > ROM + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >RAM + + .stack : + { + . = ALIGN(4); + _sstack = .; + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >RAM + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > RAM + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.sct b/bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.sct new file mode 100644 index 0000000000..0d7c47992d --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00100000 { ; load region size_region + ER_IROM1 0x08000000 0x00100000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00020000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/stm32/stm32f407-robomaster-c/figures/board.png b/bsp/stm32/stm32f407-robomaster-c/figures/board.png new file mode 100644 index 0000000000000000000000000000000000000000..8562ae6604128b239de0a6aeea03edc2bcb63e54 GIT binary patch literal 177116 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%0AJe|Gfm;{x`U%%z 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℘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 LtLG;6>-&EJFL|l; literal 0 HcmV?d00001 diff --git a/bsp/stm32/stm32f407-robomaster-c/project.ewd b/bsp/stm32/stm32f407-robomaster-c/project.ewd new file mode 100644 index 0000000000..e94c83ed06 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/project.ewd @@ -0,0 +1,2834 @@ + + + 3 + + rt-thread + + ARM + + 1 + + C-SPY + 2 + + 29 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 1 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 1 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 1 + + + + + + + + STLINK_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 1 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 6 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\IARProbe\IarProbePlugin.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + + Release + + ARM + + 0 + + C-SPY + 2 + + 29 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 0 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 0 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 0 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 0 + + + + + + + + STLINK_ID + 2 + + 4 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 0 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 6 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\IARProbe\IarProbePlugin.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + diff --git a/bsp/stm32/stm32f407-robomaster-c/project.ewp b/bsp/stm32/stm32f407-robomaster-c/project.ewp new file mode 100644 index 0000000000..db4161a4b3 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/project.ewp @@ -0,0 +1,2410 @@ + + 3 + + rt-thread + + ARM + + 1 + + General + 3 + + 29 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 20 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + + Release + + ARM + + 0 + + General + 3 + + 29 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 0 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 20 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 0 + + + + + + + BILINK + 0 + + + + + Applications + + $PROJ_DIR$\applications\main.c + + + + Drivers + + $PROJ_DIR$\board\board.c + + + $PROJ_DIR$\board\CubeMX_Config\Src\stm32f4xx_hal_msp.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\iar\startup_stm32f407xx.s + + + $PROJ_DIR$\..\libraries\HAL_Drivers\drv_gpio.c + + + $PROJ_DIR$\..\libraries\HAL_Drivers\drv_usart.c + + + $PROJ_DIR$\..\libraries\HAL_Drivers\drv_common.c + + + + Kernel + + $PROJ_DIR$\..\..\..\src\clock.c + + + $PROJ_DIR$\..\..\..\src\components.c + + + $PROJ_DIR$\..\..\..\src\device.c + + + $PROJ_DIR$\..\..\..\src\idle.c + + + $PROJ_DIR$\..\..\..\src\ipc.c + + + $PROJ_DIR$\..\..\..\src\irq.c + + + $PROJ_DIR$\..\..\..\src\kservice.c + + + $PROJ_DIR$\..\..\..\src\mem.c + + + $PROJ_DIR$\..\..\..\src\mempool.c + + + $PROJ_DIR$\..\..\..\src\object.c + + + $PROJ_DIR$\..\..\..\src\scheduler.c + + + $PROJ_DIR$\..\..\..\src\signal.c + + + $PROJ_DIR$\..\..\..\src\thread.c + + + $PROJ_DIR$\..\..\..\src\timer.c + + + + CORTEX-M4 + + $PROJ_DIR$\..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + $PROJ_DIR$\..\..\..\libcpu\arm\cortex-m4\context_iar.S + + + $PROJ_DIR$\..\..\..\libcpu\arm\common\backtrace.c + + + $PROJ_DIR$\..\..\..\libcpu\arm\common\div0.c + + + $PROJ_DIR$\..\..\..\libcpu\arm\common\showmem.c + + + + DeviceDrivers + + $PROJ_DIR$\..\..\..\components\drivers\misc\pin.c + + + $PROJ_DIR$\..\..\..\components\drivers\serial\serial.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\completion.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\dataqueue.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\pipe.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\ringblk_buf.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\ringbuffer.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\waitqueue.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\workqueue.c + + + + finsh + + $PROJ_DIR$\..\..\..\components\finsh\shell.c + + + $PROJ_DIR$\..\..\..\components\finsh\symbol.c + + + $PROJ_DIR$\..\..\..\components\finsh\cmd.c + + + $PROJ_DIR$\..\..\..\components\finsh\msh.c + + + $PROJ_DIR$\..\..\..\components\finsh\msh_cmd.c + + + $PROJ_DIR$\..\..\..\components\finsh\msh_file.c + + + + STM32_HAL + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_can.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cec.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_crc.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dac.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dac_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dcmi.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dcmi_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dfsdm.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma2d.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dsi.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_eth.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_fmpi2c.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_fmpi2c_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hash.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hash_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hcd.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2c.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2c_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2s.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2s_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_irda.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_iwdg.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_lptim.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_ltdc.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_ltdc_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_nand.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_nor.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pccard.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_qspi.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rng.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sai.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sai_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sd.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sdram.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_smartcard.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spdifrx.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spi.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sram.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_usart.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_wwdg.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_fmc.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_fsmc.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_sdmmc.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_usb.c + + + diff --git a/bsp/stm32/stm32f407-robomaster-c/project.eww b/bsp/stm32/stm32f407-robomaster-c/project.eww new file mode 100644 index 0000000000..c2cb02eb1e --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/project.eww @@ -0,0 +1,10 @@ + + + + + $WS_DIR$\project.ewp + + + + + diff --git a/bsp/stm32/stm32f407-robomaster-c/project.uvopt b/bsp/stm32/stm32f407-robomaster-c/project.uvopt new file mode 100644 index 0000000000..b53d69d5df --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/project.uvopt @@ -0,0 +1,162 @@ + + + + 1.0 + +

### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 25000000 + + 1 + 1 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\keil\List\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + 1 + 0 + 0 + 0 + 6 + + + + + + + + + + + Segger\JL2CM3.dll + + + + 0 + JL2CM3 + -U30000299 -O207 -S0 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8001 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 + + + 0 + UL2CM3 + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + diff --git a/bsp/stm32/stm32f407-robomaster-c/project.uvoptx b/bsp/stm32/stm32f407-robomaster-c/project.uvoptx new file mode 100644 index 0000000000..f8c4606a9e --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/project.uvoptx @@ -0,0 +1,191 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\keil\List\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 18 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 4 + + + + + + + + + + + Segger\JL2CM3.dll + + + + 0 + JL2CM3 + -U30000299 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8001 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + 1 + 0 + 2 + 10000000 + + + + + + Source Group 1 + 0 + 0 + 0 + 0 + + +
diff --git a/bsp/stm32/stm32f407-robomaster-c/project.uvproj b/bsp/stm32/stm32f407-robomaster-c/project.uvproj new file mode 100644 index 0000000000..a2c80e0594 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/project.uvproj @@ -0,0 +1,1189 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + + + STM32F407ZG + STMicroelectronics + IRAM(0x20000000-0x2001FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) CPUTYPE("Cortex-M4") FPU2 + + "Startup\ST\STM32F4xx\startup_stm32f40_41xxx.s" ("STM32F40/41xxx Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000) + 6105 + stm32f4xx.h + + + + + + + -DSTM32F40_41xxx + + + SFD\ST\STM32F4xx\STM32F40x.sfr + 0 + 0 + + + + ST\STM32F4xx\ + ST\STM32F4xx\ + + 0 + 0 + 0 + 0 + 1 + + .\build\keil\Obj\ + rt-thread + 1 + 0 + 0 + 1 + 0 + .\build\keil\List\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -MPU -REMAP + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + 0 + + 0 + 6 + + + + + + + + + + + + + + Segger\JL2CM3.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + + + USE_HAL_DRIVER, STM32F407xx + + applications;.;board;board\CubeMX_Config\Inc;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\include;..\..\..\libcpu\arm\cortex-m4;..\..\..\libcpu\arm\common;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\finsh;..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Inc;..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Include;..\libraries\STM32F4xx_HAL\CMSIS\Include + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\board\linker_scripts\link.sct + + + --keep *.o(.rti_fn.*) --keep *.o(FSymTab) + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + Drivers + + + board.c + 1 + board\board.c + + + + + stm32f4xx_hal_msp.c + 1 + board\CubeMX_Config\Src\stm32f4xx_hal_msp.c + + + + + startup_stm32f407xx.s + 2 + ..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm\startup_stm32f407xx.s + + + + + drv_gpio.c + 1 + ..\libraries\HAL_Drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\HAL_Drivers\drv_usart.c + + + + + drv_common.c + 1 + ..\libraries\HAL_Drivers\drv_common.c + + + + + Kernel + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + signal.c + 1 + ..\..\..\src\signal.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + CORTEX-M4 + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + symbol.c + 1 + ..\..\..\components\finsh\symbol.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + msh_cmd.c + 1 + ..\..\..\components\finsh\msh_cmd.c + + + + + msh_file.c + 1 + ..\..\..\components\finsh\msh_file.c + + + + + STM32_HAL + + + system_stm32f4xx.c + 1 + ..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c + + + + + stm32f4xx_hal.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c + + + + + stm32f4xx_hal_adc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c + + + + + stm32f4xx_hal_adc_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c + + + + + stm32f4xx_hal_can.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_can.c + + + + + stm32f4xx_hal_cec.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cec.c + + + + + stm32f4xx_hal_cortex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c + + + + + stm32f4xx_hal_crc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_crc.c + + + + + stm32f4xx_hal_cryp.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp.c + + + + + stm32f4xx_hal_cryp_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp_ex.c + + + + + stm32f4xx_hal_dac.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dac.c + + + + + stm32f4xx_hal_dac_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dac_ex.c + + + + + stm32f4xx_hal_dcmi.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dcmi.c + + + + + stm32f4xx_hal_dcmi_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dcmi_ex.c + + + + + stm32f4xx_hal_dfsdm.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dfsdm.c + + + + + stm32f4xx_hal_dma.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c + + + + + stm32f4xx_hal_dma2d.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma2d.c + + + + + stm32f4xx_hal_dma_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c + + + + + stm32f4xx_hal_dsi.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dsi.c + + + + + stm32f4xx_hal_eth.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_eth.c + + + + + stm32f4xx_hal_flash.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c + + + + + stm32f4xx_hal_flash_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c + + + + + stm32f4xx_hal_flash_ramfunc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c + + + + + stm32f4xx_hal_fmpi2c.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_fmpi2c.c + + + + + stm32f4xx_hal_fmpi2c_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_fmpi2c_ex.c + + + + + stm32f4xx_hal_gpio.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c + + + + + stm32f4xx_hal_hash.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hash.c + + + + + stm32f4xx_hal_hash_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hash_ex.c + + + + + stm32f4xx_hal_hcd.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hcd.c + + + + + stm32f4xx_hal_i2c.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2c.c + + + + + stm32f4xx_hal_i2c_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2c_ex.c + + + + + stm32f4xx_hal_i2s.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2s.c + + + + + stm32f4xx_hal_i2s_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2s_ex.c + + + + + stm32f4xx_hal_irda.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_irda.c + + + + + stm32f4xx_hal_iwdg.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_iwdg.c + + + + + stm32f4xx_hal_lptim.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_lptim.c + + + + + stm32f4xx_hal_ltdc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_ltdc.c + + + + + stm32f4xx_hal_ltdc_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_ltdc_ex.c + + + + + stm32f4xx_hal_nand.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_nand.c + + + + + stm32f4xx_hal_nor.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_nor.c + + + + + stm32f4xx_hal_pccard.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pccard.c + + + + + stm32f4xx_hal_pcd.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd.c + + + + + stm32f4xx_hal_pcd_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd_ex.c + + + + + stm32f4xx_hal_pwr.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c + + + + + stm32f4xx_hal_pwr_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c + + + + + stm32f4xx_hal_qspi.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_qspi.c + + + + + stm32f4xx_hal_rcc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c + + + + + stm32f4xx_hal_rcc_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c + + + + + stm32f4xx_hal_rng.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rng.c + + + + + stm32f4xx_hal_rtc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc.c + + + + + stm32f4xx_hal_rtc_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc_ex.c + + + + + stm32f4xx_hal_sai.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sai.c + + + + + stm32f4xx_hal_sai_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sai_ex.c + + + + + stm32f4xx_hal_sd.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sd.c + + + + + stm32f4xx_hal_sdram.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sdram.c + + + + + stm32f4xx_hal_smartcard.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_smartcard.c + + + + + stm32f4xx_hal_spdifrx.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spdifrx.c + + + + + stm32f4xx_hal_spi.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spi.c + + + + + stm32f4xx_hal_sram.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sram.c + + + + + stm32f4xx_hal_tim.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c + + + + + stm32f4xx_hal_tim_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c + + + + + stm32f4xx_hal_uart.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c + + + + + stm32f4xx_hal_usart.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_usart.c + + + + + stm32f4xx_hal_wwdg.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_wwdg.c + + + + + stm32f4xx_ll_fmc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_fmc.c + + + + + stm32f4xx_ll_fsmc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_fsmc.c + + + + + stm32f4xx_ll_sdmmc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_sdmmc.c + + + + + stm32f4xx_ll_usb.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_usb.c + + + + + + +
diff --git a/bsp/stm32/stm32f407-robomaster-c/project.uvprojx b/bsp/stm32/stm32f407-robomaster-c/project.uvprojx new file mode 100644 index 0000000000..88c46860e7 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/project.uvprojx @@ -0,0 +1,1170 @@ + + + 2.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::ARMCC + 0 + + + STM32F407ZGTx + STMicroelectronics + Keil.STM32F4xx_DFP.2.11.0 + http://www.keil.com/pack + IRAM(0x20000000,0x20000) IRAM2(0x10000000,0x10000) IROM(0x08000000,0x100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM)) + 0 + $$Device:STM32F407ZGTx$Drivers\CMSIS\Device\ST\STM32F4xx\Include\stm32f4xx.h + + + + + + + + + + $$Device:STM32F407ZGTx$CMSIS\SVD\STM32F40x.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\keil\Obj\ + rt-thread + 1 + 0 + 0 + 1 + 0 + .\build\keil\List\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + USE_HAL_DRIVER, STM32F407xx + + applications;.;board;board\CubeMX_Config\Inc;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\include;..\..\..\libcpu\arm\cortex-m4;..\..\..\libcpu\arm\common;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\finsh;..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Inc;..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Include;..\libraries\STM32F4xx_HAL\CMSIS\Include + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\board\linker_scripts\link.sct + + + --keep *.o(.rti_fn.*) --keep *.o(FSymTab) + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + Drivers + + + board.c + 1 + board\board.c + + + + + stm32f4xx_hal_msp.c + 1 + board\CubeMX_Config\Src\stm32f4xx_hal_msp.c + + + + + startup_stm32f407xx.s + 2 + ..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm\startup_stm32f407xx.s + + + + + drv_gpio.c + 1 + ..\libraries\HAL_Drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\HAL_Drivers\drv_usart.c + + + + + drv_common.c + 1 + ..\libraries\HAL_Drivers\drv_common.c + + + + + Kernel + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + signal.c + 1 + ..\..\..\src\signal.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + CORTEX-M4 + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + symbol.c + 1 + ..\..\..\components\finsh\symbol.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + msh_cmd.c + 1 + ..\..\..\components\finsh\msh_cmd.c + + + + + msh_file.c + 1 + ..\..\..\components\finsh\msh_file.c + + + + + STM32_HAL + + + system_stm32f4xx.c + 1 + ..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c + + + + + stm32f4xx_hal.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c + + + + + stm32f4xx_hal_adc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c + + + + + stm32f4xx_hal_adc_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c + + + + + stm32f4xx_hal_can.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_can.c + + + + + stm32f4xx_hal_cec.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cec.c + + + + + stm32f4xx_hal_cortex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c + + + + + stm32f4xx_hal_crc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_crc.c + + + + + stm32f4xx_hal_cryp.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp.c + + + + + stm32f4xx_hal_cryp_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp_ex.c + + + + + stm32f4xx_hal_dac.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dac.c + + + + + stm32f4xx_hal_dac_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dac_ex.c + + + + + stm32f4xx_hal_dcmi.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dcmi.c + + + + + stm32f4xx_hal_dcmi_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dcmi_ex.c + + + + + stm32f4xx_hal_dfsdm.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dfsdm.c + + + + + stm32f4xx_hal_dma.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c + + + + + stm32f4xx_hal_dma2d.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma2d.c + + + + + stm32f4xx_hal_dma_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c + + + + + stm32f4xx_hal_dsi.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dsi.c + + + + + stm32f4xx_hal_eth.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_eth.c + + + + + stm32f4xx_hal_flash.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c + + + + + stm32f4xx_hal_flash_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c + + + + + stm32f4xx_hal_flash_ramfunc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c + + + + + stm32f4xx_hal_fmpi2c.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_fmpi2c.c + + + + + stm32f4xx_hal_fmpi2c_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_fmpi2c_ex.c + + + + + stm32f4xx_hal_gpio.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c + + + + + stm32f4xx_hal_hash.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hash.c + + + + + stm32f4xx_hal_hash_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hash_ex.c + + + + + stm32f4xx_hal_hcd.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hcd.c + + + + + stm32f4xx_hal_i2c.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2c.c + + + + + stm32f4xx_hal_i2c_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2c_ex.c + + + + + stm32f4xx_hal_i2s.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2s.c + + + + + stm32f4xx_hal_i2s_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2s_ex.c + + + + + stm32f4xx_hal_irda.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_irda.c + + + + + stm32f4xx_hal_iwdg.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_iwdg.c + + + + + stm32f4xx_hal_lptim.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_lptim.c + + + + + stm32f4xx_hal_ltdc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_ltdc.c + + + + + stm32f4xx_hal_ltdc_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_ltdc_ex.c + + + + + stm32f4xx_hal_nand.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_nand.c + + + + + stm32f4xx_hal_nor.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_nor.c + + + + + stm32f4xx_hal_pccard.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pccard.c + + + + + stm32f4xx_hal_pcd.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd.c + + + + + stm32f4xx_hal_pcd_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd_ex.c + + + + + stm32f4xx_hal_pwr.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c + + + + + stm32f4xx_hal_pwr_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c + + + + + stm32f4xx_hal_qspi.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_qspi.c + + + + + stm32f4xx_hal_rcc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c + + + + + stm32f4xx_hal_rcc_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c + + + + + stm32f4xx_hal_rng.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rng.c + + + + + stm32f4xx_hal_rtc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc.c + + + + + stm32f4xx_hal_rtc_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc_ex.c + + + + + stm32f4xx_hal_sai.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sai.c + + + + + stm32f4xx_hal_sai_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sai_ex.c + + + + + stm32f4xx_hal_sd.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sd.c + + + + + stm32f4xx_hal_sdram.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sdram.c + + + + + stm32f4xx_hal_smartcard.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_smartcard.c + + + + + stm32f4xx_hal_spdifrx.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spdifrx.c + + + + + stm32f4xx_hal_spi.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spi.c + + + + + stm32f4xx_hal_sram.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sram.c + + + + + stm32f4xx_hal_tim.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c + + + + + stm32f4xx_hal_tim_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c + + + + + stm32f4xx_hal_uart.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c + + + + + stm32f4xx_hal_usart.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_usart.c + + + + + stm32f4xx_hal_wwdg.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_wwdg.c + + + + + stm32f4xx_ll_fmc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_fmc.c + + + + + stm32f4xx_ll_fsmc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_fsmc.c + + + + + stm32f4xx_ll_sdmmc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_sdmmc.c + + + + + stm32f4xx_ll_usb.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_usb.c + + + + + + + + + + + +
diff --git a/bsp/stm32/stm32f407-robomaster-c/rtconfig.h b/bsp/stm32/stm32f407-robomaster-c/rtconfig.h new file mode 100644 index 0000000000..7d83eb4f99 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/rtconfig.h @@ -0,0 +1,173 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 1000 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40000 +#define ARCH_ARM +#define ARCH_ARM_CORTEX_M +#define ARCH_ARM_CORTEX_M4 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_CMD_SIZE 80 +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +#define FINSH_USING_MSH_ONLY +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SERIAL +#define RT_SERIAL_USING_DMA +#define RT_USING_PIN + +/* Using WiFi */ + + +/* Using USB */ + + +/* POSIX layer and C standard library */ + + +/* Network */ + +/* Socket abstraction layer */ + + +/* light weight TCP/IP stack */ + + +/* Modbus master and slave stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* ARM CMSIS */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + + +/* tools packages */ + + +/* system packages */ + + +/* peripheral libraries and drivers */ + + +/* miscellaneous packages */ + + +/* samples: kernel and components samples */ + +#define SOC_FAMILY_STM32 +#define SOC_SERIES_STM32F4 + +/* Hardware Drivers Config */ + +#define SOC_STM32F407ZG + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/stm32/stm32f407-robomaster-c/rtconfig.py b/bsp/stm32/stm32f407-robomaster-c/rtconfig.py new file mode 100644 index 0000000000..00d5d737ac --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m4' +CROSS_TOOL='gcc' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rt-thread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.lds' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M4.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rt-thread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M4' + CFLAGS += ' -e' + CFLAGS += ' --fpu=VFPv4_sp' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M4' + AFLAGS += ' --fpu VFPv4_sp' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/stm32/stm32f407-robomaster-c/template.ewp b/bsp/stm32/stm32f407-robomaster-c/template.ewp new file mode 100644 index 0000000000..21c66ca0d0 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/template.ewp @@ -0,0 +1,2031 @@ + + + 3 + + rt-thread + + ARM + + 1 + + General + 3 + + 29 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 20 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + + Release + + ARM + + 0 + + General + 3 + + 29 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 0 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 20 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 0 + + + + + + + BILINK + 0 + + + + diff --git a/bsp/stm32/stm32f407-robomaster-c/template.eww b/bsp/stm32/stm32f407-robomaster-c/template.eww new file mode 100644 index 0000000000..bd036bb4c9 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/template.eww @@ -0,0 +1,10 @@ + + + + + $WS_DIR$\template.ewp + + + + + diff --git a/bsp/stm32/stm32f407-robomaster-c/template.uvopt b/bsp/stm32/stm32f407-robomaster-c/template.uvopt new file mode 100644 index 0000000000..b53d69d5df --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/template.uvopt @@ -0,0 +1,162 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 25000000 + + 1 + 1 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\keil\List\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + 1 + 0 + 0 + 0 + 6 + + + + + + + + + + + Segger\JL2CM3.dll + + + + 0 + JL2CM3 + -U30000299 -O207 -S0 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8001 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 + + + 0 + UL2CM3 + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + +
diff --git a/bsp/stm32/stm32f407-robomaster-c/template.uvoptx b/bsp/stm32/stm32f407-robomaster-c/template.uvoptx new file mode 100644 index 0000000000..f8c4606a9e --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/template.uvoptx @@ -0,0 +1,191 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\keil\List\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 18 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 4 + + + + + + + + + + + Segger\JL2CM3.dll + + + + 0 + JL2CM3 + -U30000299 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8001 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + 1 + 0 + 2 + 10000000 + + + + + + Source Group 1 + 0 + 0 + 0 + 0 + + +
diff --git a/bsp/stm32/stm32f407-robomaster-c/template.uvproj b/bsp/stm32/stm32f407-robomaster-c/template.uvproj new file mode 100644 index 0000000000..6ca2a92953 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/template.uvproj @@ -0,0 +1,407 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + + + STM32F407ZG + STMicroelectronics + IRAM(0x20000000-0x2001FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) CPUTYPE("Cortex-M4") FPU2 + + "Startup\ST\STM32F4xx\startup_stm32f40_41xxx.s" ("STM32F40/41xxx Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000) + 6105 + stm32f4xx.h + + + + + + + -DSTM32F40_41xxx + + + SFD\ST\STM32F4xx\STM32F40x.sfr + 0 + 0 + + + + ST\STM32F4xx\ + ST\STM32F4xx\ + + 0 + 0 + 0 + 0 + 1 + + .\build\keil\Obj\ + rt-thread + 1 + 0 + 0 + 1 + 0 + .\build\keil\List\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -MPU -REMAP + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + 0 + + 0 + 6 + + + + + + + + + + + + + + Segger\JL2CM3.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\board\linker_scripts\link.sct + + + + + + + + + + + +
diff --git a/bsp/stm32/stm32f407-robomaster-c/template.uvprojx b/bsp/stm32/stm32f407-robomaster-c/template.uvprojx new file mode 100644 index 0000000000..66fe3140e7 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/template.uvprojx @@ -0,0 +1,394 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::ARMCC + 0 + + + STM32F407ZGTx + STMicroelectronics + Keil.STM32F4xx_DFP.2.13.0 + http://www.keil.com/pack + IRAM(0x20000000,0x20000) IRAM2(0x10000000,0x10000) IROM(0x08000000,0x100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM)) + 0 + $$Device:STM32F407ZGTx$Drivers\CMSIS\Device\ST\STM32F4xx\Include\stm32f4xx.h + + + + + + + + + + $$Device:STM32F407ZGTx$CMSIS\SVD\STM32F40x.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\keil\Obj\ + rt-thread + 1 + 0 + 0 + 1 + 0 + .\build\keil\List\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\board\linker_scripts\link.sct + + + + + + + + + + + Source Group 1 + + + + + + + + + + + +
From 1d0134841439b5bcdae48e08d10bfeea5fb3159c Mon Sep 17 00:00:00 2001 From: crazt Date: Wed, 30 Jun 2021 14:51:45 +0800 Subject: [PATCH 216/255] [bsp/stm32/rmc] CubeMX config. --- .../board/CubeMX_Config/.mxproject | 21 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 71 +- .../board/CubeMX_Config/Inc/main.h | 34 +- .../CubeMX_Config/Inc/stm32f4xx_hal_conf.h | 167 ++-- .../board/CubeMX_Config/Inc/stm32f4xx_it.h | 34 +- .../board/CubeMX_Config/Src/main.c | 57 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 82 +- .../board/CubeMX_Config/Src/stm32f4xx_it.c | 53 +- .../CubeMX_Config/Src/system_stm32f4xx.c | 727 ++++++++++++++++++ 9 files changed, 952 insertions(+), 294 deletions(-) create mode 100644 bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/system_stm32f4xx.c diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/.mxproject b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/.mxproject index 9346fc2058..98680a9f77 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/.mxproject +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/.mxproject @@ -1,17 +1,14 @@ -[PreviousGenFiles] -HeaderPath=E:/git_project/BspFramework/rt-thread/bsp/stm32/stm32f4xx/board/CubeMX_Config/Inc -HeaderFiles=stm32f4xx_it.h;stm32f4xx_hal_conf.h;main.h; -SourcePath=E:/git_project/BspFramework/rt-thread/bsp/stm32/stm32f4xx/board/CubeMX_Config/Src -SourceFiles=stm32f4xx_it.c;stm32f4xx_hal_msp.c;main.c; - [PreviousLibFiles] -LibFiles=Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f407xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;Drivers/CMSIS/Include/arm_common_tables.h;Drivers/CMSIS/Include/arm_const_structs.h;Drivers/CMSIS/Include/arm_math.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/cmsis_armcc_V6.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_cm3.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_cmFunc.h;Drivers/CMSIS/Include/core_cmInstr.h;Drivers/CMSIS/Include/core_cmSimd.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/core_sc300.h; - -[PreviousUsedIarFiles] -SourceFiles=..\Src\main.c;..\Src\stm32f4xx_it.c;..\Src\stm32f4xx_hal_msp.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;null; -HeaderPath=..\Drivers\STM32F4xx_HAL_Driver\Inc;..\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32F4xx\Include;..\Drivers\CMSIS\Include;..\Inc; +LibFiles=Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f407xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/cmsis_armclang.h;Drivers/CMSIS/Include/cmsis_compiler.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/cmsis_iccarm.h;Drivers/CMSIS/Include/cmsis_version.h;Drivers/CMSIS/Include/core_armv8mbl.h;Drivers/CMSIS/Include/core_armv8mml.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_cm1.h;Drivers/CMSIS/Include/core_cm23.h;Drivers/CMSIS/Include/core_cm3.h;Drivers/CMSIS/Include/core_cm33.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/core_sc300.h;Drivers/CMSIS/Include/mpu_armv7.h;Drivers/CMSIS/Include/mpu_armv8.h;Drivers/CMSIS/Include/tz_context.h; [PreviousUsedKeilFiles] -SourceFiles=..\Src\main.c;..\Src\stm32f4xx_it.c;..\Src\stm32f4xx_hal_msp.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;null; +SourceFiles=..\Src\main.c;..\Src\stm32f4xx_it.c;..\Src\stm32f4xx_hal_msp.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c;..\\Src/system_stm32f4xx.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;..\Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c;..\\Src/system_stm32f4xx.c;..\Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;; HeaderPath=..\Drivers\STM32F4xx_HAL_Driver\Inc;..\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32F4xx\Include;..\Drivers\CMSIS\Include;..\Inc; +CDefines=USE_HAL_DRIVER;STM32F407xx;USE_HAL_DRIVER;USE_HAL_DRIVER; + +[PreviousGenFiles] +HeaderPath=C:/CraztDoc/RTT/github_repo/rt-thread/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc +HeaderFiles=stm32f4xx_it.h;stm32f4xx_hal_conf.h;main.h; +SourcePath=C:/CraztDoc/RTT/github_repo/rt-thread/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src +SourceFiles=stm32f4xx_it.c;stm32f4xx_hal_msp.c;main.c; diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc index 819eb4c535..26eba65442 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc @@ -1,5 +1,6 @@ #MicroXplorer Configuration settings - do not modify File.Version=6 +GPIO.groupedBy= KeepUserPlacement=false Mcu.Family=STM32F4 Mcu.IP0=NVIC @@ -7,52 +8,47 @@ Mcu.IP1=RCC Mcu.IP2=SYS Mcu.IP3=USART1 Mcu.IPNb=4 -Mcu.Name=STM32F407Z(E-G)Tx -Mcu.Package=LQFP144 -Mcu.Pin0=PH0-OSC_IN -Mcu.Pin1=PH1-OSC_OUT -Mcu.Pin2=PA9 -Mcu.Pin3=PA10 -Mcu.Pin4=PA13 -Mcu.Pin5=PA14 +Mcu.Name=STM32F407I(E-G)Hx +Mcu.Package=UFBGA176 +Mcu.Pin0=PA14 +Mcu.Pin1=PA13 +Mcu.Pin2=PB7 +Mcu.Pin3=PA9 +Mcu.Pin4=PH0-OSC_IN +Mcu.Pin5=PH1-OSC_OUT Mcu.Pin6=VP_SYS_VS_Systick Mcu.PinsNb=7 Mcu.ThirdPartyNb=0 Mcu.UserConstants= -Mcu.UserName=STM32F407ZGTx -MxCube.Version=5.0.0 -MxDb.Version=DB.5.0.0 -NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false +Mcu.UserName=STM32F407IGHx +MxCube.Version=6.1.2 +MxDb.Version=DB.6.0.10 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.ForceEnableDMAVector=true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 -NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true -NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false -PA10.Mode=Asynchronous -PA10.Signal=USART1_RX +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK +PA9.Locked=true PA9.Mode=Asynchronous PA9.Signal=USART1_TX -PCC.Checker=false -PCC.Line=STM32F407/417 -PCC.MCU=STM32F407Z(E-G)Tx -PCC.PartNumber=STM32F407ZGTx -PCC.Seq0=0 -PCC.Series=STM32F4 -PCC.Temperature=25 -PCC.Vdd=3.3 +PB7.Locked=true +PB7.Mode=Asynchronous +PB7.Signal=USART1_RX PH0-OSC_IN.Mode=HSE-External-Oscillator PH0-OSC_IN.Signal=RCC_OSC_IN PH1-OSC_OUT.Mode=HSE-External-Oscillator PH1-OSC_OUT.Signal=RCC_OSC_OUT +PinOutPanel.CurrentBGAView=Top PinOutPanel.RotationAngle=0 ProjectManager.AskForMigrate=true ProjectManager.BackupPrevious=false @@ -62,8 +58,8 @@ ProjectManager.CoupleFile=false ProjectManager.CustomerFirmwarePackage= ProjectManager.DefaultFWLocation=true ProjectManager.DeletePrevious=true -ProjectManager.DeviceId=STM32F407ZGTx -ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.22.0 +ProjectManager.DeviceId=STM32F407IGHx +ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.25.2 ProjectManager.FreePins=false ProjectManager.HalAssertFull=false ProjectManager.HeapSize=0x200 @@ -76,11 +72,12 @@ ProjectManager.PreviousToolchain= ProjectManager.ProjectBuild=false ProjectManager.ProjectFileName=CubeMX_Config.ioc ProjectManager.ProjectName=CubeMX_Config +ProjectManager.RegisterCallBack= ProjectManager.StackSize=0x400 ProjectManager.TargetToolchain=MDK-ARM V5 ProjectManager.ToolChainLocation= ProjectManager.UnderRoot=false -ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_USART1_UART_Init-USART1-false-HAL-true +ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false RCC.48MHZClocksFreq_Value=84000000 RCC.AHBFreq_Value=168000000 RCC.APB1CLKDivider=RCC_HCLK_DIV4 @@ -94,7 +91,7 @@ RCC.EthernetFreq_Value=168000000 RCC.FCLKCortexFreq_Value=168000000 RCC.FamilyName=M RCC.HCLKFreq_Value=168000000 -RCC.HSE_VALUE=8000000 +RCC.HSE_VALUE=12000000 RCC.HSI_VALUE=16000000 RCC.I2SClocksFreq_Value=192000000 RCC.IPParameters=48MHZClocksFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2SClocksFreq_Value,LSE_VALUE,LSI_VALUE,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLM,PLLN,PLLQCLKFreq_Value,PLLSourceVirtual,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VcooutputI2S @@ -102,12 +99,12 @@ RCC.LSE_VALUE=32768 RCC.LSI_VALUE=32000 RCC.MCO2PinFreq_Value=168000000 RCC.PLLCLKFreq_Value=168000000 -RCC.PLLM=4 +RCC.PLLM=6 RCC.PLLN=168 RCC.PLLQCLKFreq_Value=84000000 RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE RCC.RTCFreq_Value=32000 -RCC.RTCHSEDivFreq_Value=4000000 +RCC.RTCHSEDivFreq_Value=6000000 RCC.SYSCLKFreq_VALUE=168000000 RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK RCC.VCOI2SOutputFreq_Value=384000000 diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/main.h b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/main.h index 9d41187606..b905d54bd5 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/main.h +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/main.h @@ -5,35 +5,15 @@ * @brief : Header for main.c file. * This file contains the common defines of the application. ****************************************************************************** - ** This notice applies to any and all portions of this file - * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether - * inserted by the user or by software development tools - * are owned by their respective copyright owners. + * @attention * - * COPYRIGHT(c) 2018 STMicroelectronics + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h index 9db422a140..03b8ceafa2 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h @@ -1,36 +1,23 @@ /** ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @brief HAL configuration file. + * @file stm32f4xx_hal_conf_template.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32f4xx_hal_conf.h. ****************************************************************************** * @attention * - *

© COPYRIGHT(c) 2018 STMicroelectronics

+ *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** - */ + */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STM32F4xx_HAL_CONF_H @@ -45,14 +32,15 @@ /* ########################## Module Selection ############################## */ /** - * @brief This is the list of modules to be used in the HAL driver + * @brief This is the list of modules to be used in the HAL driver */ -#define HAL_MODULE_ENABLED +#define HAL_MODULE_ENABLED -/* #define HAL_ADC_MODULE_ENABLED */ + /* #define HAL_ADC_MODULE_ENABLED */ /* #define HAL_CRYP_MODULE_ENABLED */ /* #define HAL_CAN_MODULE_ENABLED */ /* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CAN_LEGACY_MODULE_ENABLED */ /* #define HAL_CRYP_MODULE_ENABLED */ /* #define HAL_DAC_MODULE_ENABLED */ /* #define HAL_DCMI_MODULE_ENABLED */ @@ -79,6 +67,7 @@ /* #define HAL_USART_MODULE_ENABLED */ /* #define HAL_IRDA_MODULE_ENABLED */ /* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_SMBUS_MODULE_ENABLED */ /* #define HAL_WWDG_MODULE_ENABLED */ /* #define HAL_PCD_MODULE_ENABLED */ /* #define HAL_HCD_MODULE_ENABLED */ @@ -90,8 +79,8 @@ /* #define HAL_SPDIFRX_MODULE_ENABLED */ /* #define HAL_DFSDM_MODULE_ENABLED */ /* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_EXTI_MODULE_ENABLED */ #define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED #define HAL_RCC_MODULE_ENABLED #define HAL_FLASH_MODULE_ENABLED @@ -102,10 +91,10 @@ /** * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). + * (when HSE is used as system clock source, directly or through the PLL). */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)12000000U) /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ #if !defined (HSE_STARTUP_TIMEOUT) @@ -115,7 +104,7 @@ /** * @brief Internal High Speed oscillator (HSI) value. * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). + * (when HSI is used as system clock source, directly or through the PLL). */ #if !defined (HSI_VALUE) #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ @@ -124,7 +113,7 @@ /** * @brief Internal Low Speed oscillator (LSI) value. */ -#if !defined (LSI_VALUE) +#if !defined (LSI_VALUE) #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ #endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz The real value may vary depending on the variations @@ -142,8 +131,8 @@ /** * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. */ #if !defined (EXTERNAL_CLOCK_VALUE) #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/ @@ -156,16 +145,55 @@ /** * @brief This is the HAL system configuration section */ -#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ -#define USE_RTOS 0U +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ +#define USE_RTOS 0U #define PREFETCH_ENABLE 1U #define INSTRUCTION_CACHE_ENABLE 1U #define DATA_CACHE_ENABLE 1U +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_FMPI2C_REGISTER_CALLBACKS 0U /* FMPI2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + /* ########################## Assert Selection ############################## */ /** - * @brief Uncomment the line below to expanse the "assert_param" macro in the + * @brief Uncomment the line below to expanse the "assert_param" macro in the * HAL drivers code */ /* #define USE_FULL_ASSERT 1U */ @@ -182,7 +210,7 @@ #define MAC_ADDR4 0U #define MAC_ADDR5 0U -/* Definition of the Ethernet driver buffers size and count */ +/* Definition of the Ethernet driver buffers size and count */ #define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ #define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ #define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ @@ -190,9 +218,9 @@ /* Section 2: PHY configuration section */ -/* DP83848_PHY_ADDRESS Address*/ +/* DP83848_PHY_ADDRESS Address*/ #define DP83848_PHY_ADDRESS 0x01U -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ #define PHY_RESET_DELAY ((uint32_t)0x000000FFU) /* PHY Configuration delay */ #define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU) @@ -204,7 +232,7 @@ #define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */ #define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ - + #define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */ #define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */ #define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */ @@ -219,7 +247,7 @@ #define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */ #define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ #define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */ - + /* Section 4: Extended PHY Registers */ #define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ @@ -237,25 +265,25 @@ /* Includes ------------------------------------------------------------------*/ /** - * @brief Include module's header file + * @brief Include module's header file */ #ifdef HAL_RCC_MODULE_ENABLED #include "stm32f4xx_hal_rcc.h" #endif /* HAL_RCC_MODULE_ENABLED */ -#ifdef HAL_EXTI_MODULE_ENABLED - #include "stm32f4xx_hal_exti.h" -#endif /* HAL_EXTI_MODULE_ENABLED */ - #ifdef HAL_GPIO_MODULE_ENABLED #include "stm32f4xx_hal_gpio.h" #endif /* HAL_GPIO_MODULE_ENABLED */ +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + #ifdef HAL_DMA_MODULE_ENABLED #include "stm32f4xx_hal_dma.h" #endif /* HAL_DMA_MODULE_ENABLED */ - + #ifdef HAL_CORTEX_MODULE_ENABLED #include "stm32f4xx_hal_cortex.h" #endif /* HAL_CORTEX_MODULE_ENABLED */ @@ -268,12 +296,16 @@ #include "stm32f4xx_hal_can.h" #endif /* HAL_CAN_MODULE_ENABLED */ +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED + #include "stm32f4xx_hal_can_legacy.h" +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ + #ifdef HAL_CRC_MODULE_ENABLED #include "stm32f4xx_hal_crc.h" #endif /* HAL_CRC_MODULE_ENABLED */ #ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" + #include "stm32f4xx_hal_cryp.h" #endif /* HAL_CRYP_MODULE_ENABLED */ #ifdef HAL_DMA2D_MODULE_ENABLED @@ -295,7 +327,7 @@ #ifdef HAL_FLASH_MODULE_ENABLED #include "stm32f4xx_hal_flash.h" #endif /* HAL_FLASH_MODULE_ENABLED */ - + #ifdef HAL_SRAM_MODULE_ENABLED #include "stm32f4xx_hal_sram.h" #endif /* HAL_SRAM_MODULE_ENABLED */ @@ -310,11 +342,11 @@ #ifdef HAL_PCCARD_MODULE_ENABLED #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - +#endif /* HAL_PCCARD_MODULE_ENABLED */ + #ifdef HAL_SDRAM_MODULE_ENABLED #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ +#endif /* HAL_SDRAM_MODULE_ENABLED */ #ifdef HAL_HASH_MODULE_ENABLED #include "stm32f4xx_hal_hash.h" @@ -324,6 +356,10 @@ #include "stm32f4xx_hal_i2c.h" #endif /* HAL_I2C_MODULE_ENABLED */ +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32f4xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + #ifdef HAL_I2S_MODULE_ENABLED #include "stm32f4xx_hal_i2s.h" #endif /* HAL_I2S_MODULE_ENABLED */ @@ -356,10 +392,6 @@ #include "stm32f4xx_hal_sd.h" #endif /* HAL_SD_MODULE_ENABLED */ -#ifdef HAL_MMC_MODULE_ENABLED - #include "stm32f4xx_hal_mmc.h" -#endif /* HAL_MMC_MODULE_ENABLED */ - #ifdef HAL_SPI_MODULE_ENABLED #include "stm32f4xx_hal_spi.h" #endif /* HAL_SPI_MODULE_ENABLED */ @@ -395,7 +427,7 @@ #ifdef HAL_HCD_MODULE_ENABLED #include "stm32f4xx_hal_hcd.h" #endif /* HAL_HCD_MODULE_ENABLED */ - + #ifdef HAL_DSI_MODULE_ENABLED #include "stm32f4xx_hal_dsi.h" #endif /* HAL_DSI_MODULE_ENABLED */ @@ -423,14 +455,18 @@ #ifdef HAL_LPTIM_MODULE_ENABLED #include "stm32f4xx_hal_lptim.h" #endif /* HAL_LPTIM_MODULE_ENABLED */ - + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f4xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + /* Exported macro ------------------------------------------------------------*/ #ifdef USE_FULL_ASSERT /** * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function + * @param expr If expr is false, it calls assert_failed function * which reports the name of the source file and the source - * line number of the call that failed. + * line number of the call that failed. * If expr is true, it returns no value. * @retval None */ @@ -439,13 +475,12 @@ void assert_failed(uint8_t* file, uint32_t line); #else #define assert_param(expr) ((void)0U) -#endif /* USE_FULL_ASSERT */ +#endif /* USE_FULL_ASSERT */ #ifdef __cplusplus } #endif #endif /* __STM32F4xx_HAL_CONF_H */ - /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_it.h b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_it.h index e3b003d9ad..e80dbbd8c1 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_it.h +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_it.h @@ -4,32 +4,17 @@ * @file stm32f4xx_it.h * @brief This file contains the headers of the interrupt handlers. ****************************************************************************** + * @attention * - * COPYRIGHT(c) 2018 STMicroelectronics + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** + ****************************************************************************** */ /* USER CODE END Header */ @@ -39,7 +24,7 @@ #ifdef __cplusplus extern "C" { -#endif +#endif /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ @@ -71,7 +56,6 @@ void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); -void USART1_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/main.c b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/main.c index a6cbc9fece..3df243a8fa 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/main.c +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/main.c @@ -4,40 +4,19 @@ * @file : main.c * @brief : Main program body ****************************************************************************** - ** This notice applies to any and all portions of this file - * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether - * inserted by the user or by software development tools - * are owned by their respective copyright owners. + * @attention * - * COPYRIGHT(c) 2018 STMicroelectronics + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* USER CODE END Header */ - /* Includes ------------------------------------------------------------------*/ #include "main.h" @@ -53,7 +32,6 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ - /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ @@ -134,17 +112,18 @@ void SystemClock_Config(void) RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - /**Configure the main internal regulator output voltage + /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); - /**Initializes the CPU, AHB and APB busses clocks + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLM = 4; + RCC_OscInitStruct.PLL.PLLM = 6; RCC_OscInitStruct.PLL.PLLN = 168; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; @@ -152,7 +131,7 @@ void SystemClock_Config(void) { Error_Handler(); } - /**Initializes the CPU, AHB and APB busses clocks + /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; @@ -209,8 +188,9 @@ static void MX_GPIO_Init(void) { /* GPIO Ports Clock Enable */ - __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); } @@ -226,7 +206,10 @@ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ - + __disable_irq(); + while (1) + { + } /* USER CODE END Error_Handler_Debug */ } @@ -239,10 +222,10 @@ void Error_Handler(void) * @retval None */ void assert_failed(uint8_t *file, uint32_t line) -{ +{ /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, - tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index e00b8556d6..54a111c524 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -1,39 +1,19 @@ /* USER CODE BEGIN Header */ /** ****************************************************************************** - * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization - * and de-Initialization codes. + * @file stm32f4xx_hal_msp.c + * @brief This file provides code for the MSP Initialization + * and de-Initialization codes. ****************************************************************************** - ** This notice applies to any and all portions of this file - * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether - * inserted by the user or by software development tools - * are owned by their respective copyright owners. + * @attention * - * COPYRIGHT(c) 2018 STMicroelectronics + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ @@ -52,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -105,7 +85,6 @@ void HAL_MspInit(void) */ void HAL_UART_MspInit(UART_HandleTypeDef* huart) { - GPIO_InitTypeDef GPIO_InitStruct = {0}; if(huart->Instance==USART1) { @@ -114,22 +93,27 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration + PB7 ------> USART1_RX PA9 ------> USART1_TX - PA10 ------> USART1_RX */ - GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; + GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF7_USART1; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - /* USART1 interrupt Init */ - HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspInit 1 */ /* USER CODE END USART1_MspInit 1 */ @@ -143,10 +127,8 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) * @param huart: UART handle pointer * @retval None */ - void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) { - if(huart->Instance==USART1) { /* USER CODE BEGIN USART1_MspDeInit 0 */ @@ -154,15 +136,15 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration - PA9 ------> USART1_TX - PA10 ------> USART1_RX - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); - /* USART1 interrupt DeInit */ - HAL_NVIC_DisableIRQ(USART1_IRQn); + /**USART1 GPIO Configuration + PB7 ------> USART1_RX + PA9 ------> USART1_TX + */ + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7); + + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9); + /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 */ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_it.c b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_it.c index 80653c5ad3..fe4ffc9dbf 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_it.c +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_it.c @@ -4,30 +4,15 @@ * @file stm32f4xx_it.c * @brief Interrupt Service Routines. ****************************************************************************** + * @attention * - * COPYRIGHT(c) 2018 STMicroelectronics + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ @@ -47,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ - + /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ @@ -71,13 +56,13 @@ /* USER CODE END 0 */ /* External variables --------------------------------------------------------*/ -extern UART_HandleTypeDef huart1; + /* USER CODE BEGIN EV */ /* USER CODE END EV */ /******************************************************************************/ -/* Cortex-M4 Processor Interruption and Exception Handlers */ +/* Cortex-M4 Processor Interruption and Exception Handlers */ /******************************************************************************/ /** * @brief This function handles Non maskable interrupt. @@ -88,7 +73,9 @@ void NMI_Handler(void) /* USER CODE END NonMaskableInt_IRQn 0 */ /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ - + while (1) + { + } /* USER CODE END NonMaskableInt_IRQn 1 */ } @@ -212,20 +199,6 @@ void SysTick_Handler(void) /* please refer to the startup file (startup_stm32f4xx.s). */ /******************************************************************************/ -/** - * @brief This function handles USART1 global interrupt. - */ -void USART1_IRQHandler(void) -{ - /* USER CODE BEGIN USART1_IRQn 0 */ - - /* USER CODE END USART1_IRQn 0 */ - HAL_UART_IRQHandler(&huart1); - /* USER CODE BEGIN USART1_IRQn 1 */ - - /* USER CODE END USART1_IRQn 1 */ -} - /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/system_stm32f4xx.c b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/system_stm32f4xx.c new file mode 100644 index 0000000000..bcb2b9f4a5 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/system_stm32f4xx.c @@ -0,0 +1,727 @@ +/** + ****************************************************************************** + * @file system_stm32f4xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f4xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f4xx_system + * @{ + */ + +/** @addtogroup STM32F4xx_System_Private_Includes + * @{ + */ + + +#include "stm32f4xx.h" + +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Defines + * @{ + */ + +/************************* Miscellaneous Configuration ************************/ +/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ + || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) +/* #define DATA_IN_ExtSRAM */ +#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\ + STM32F412Zx || STM32F412Vx */ + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +/* #define DATA_IN_ExtSDRAM */ +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\ + STM32F479xx */ + +/*!< Uncomment the following line if you need to relocate your vector Table in + Internal SRAM. */ +/* #define VECT_TAB_SRAM */ +#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +/******************************************************************************/ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Variables + * @{ + */ + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ +uint32_t SystemCoreClock = 16000000; +const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes + * @{ + */ + +#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) + static void SystemInit_ExtMemCtl(void); +#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the FPU setting, vector table location and External memory + * configuration. + * @param None + * @retval None + */ +void SystemInit(void) +{ + /* FPU settings ------------------------------------------------------------*/ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ + #endif + +#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) + SystemInit_ExtMemCtl(); +#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ + + /* Configure the Vector Table location add offset address ------------------*/ +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#else + SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +#endif +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value + * depends on the application requirements), user has to ensure that HSE_VALUE + * is same as the real frequency of the crystal used. Otherwise, this function + * may have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N + SYSCLK = PLL_VCO / PLL_P + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; + pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; + + if (pllsource != 0) + { + /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + else + { + /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + + pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; + SystemCoreClock = pllvco/pllp; + break; + default: + SystemCoreClock = HSI_VALUE; + break; + } + /* Compute HCLK frequency --------------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK frequency */ + SystemCoreClock >>= tmp; +} + +#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM) +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external memories (SRAM/SDRAM) + * This SRAM/SDRAM will be used as program data memory (including heap and stack). + * @param None + * @retval None + */ +void SystemInit_ExtMemCtl(void) +{ + __IO uint32_t tmp = 0x00; + + register uint32_t tmpreg = 0, timeout = 0xFFFF; + register __IO uint32_t index; + + /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */ + RCC->AHB1ENR |= 0x000001F8; + + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); + + /* Connect PDx pins to FMC Alternate function */ + GPIOD->AFR[0] = 0x00CCC0CC; + GPIOD->AFR[1] = 0xCCCCCCCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xAAAA0A8A; + /* Configure PDx pins speed to 100 MHz */ + GPIOD->OSPEEDR = 0xFFFF0FCF; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; + + /* Connect PEx pins to FMC Alternate function */ + GPIOE->AFR[0] = 0xC00CC0CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA828A; + /* Configure PEx pins speed to 100 MHz */ + GPIOE->OSPEEDR = 0xFFFFC3CF; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + + /* Connect PFx pins to FMC Alternate function */ + GPIOF->AFR[0] = 0xCCCCCCCC; + GPIOF->AFR[1] = 0xCCCCCCCC; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA800AAA; + /* Configure PFx pins speed to 50 MHz */ + GPIOF->OSPEEDR = 0xAA800AAA; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; + + /* Connect PGx pins to FMC Alternate function */ + GPIOG->AFR[0] = 0xCCCCCCCC; + GPIOG->AFR[1] = 0xCCCCCCCC; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0xAAAAAAAA; + /* Configure PGx pins speed to 50 MHz */ + GPIOG->OSPEEDR = 0xAAAAAAAA; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + + /* Connect PHx pins to FMC Alternate function */ + GPIOH->AFR[0] = 0x00C0CC00; + GPIOH->AFR[1] = 0xCCCCCCCC; + /* Configure PHx pins in Alternate function mode */ + GPIOH->MODER = 0xAAAA08A0; + /* Configure PHx pins speed to 50 MHz */ + GPIOH->OSPEEDR = 0xAAAA08A0; + /* Configure PHx pins Output type to push-pull */ + GPIOH->OTYPER = 0x00000000; + /* No pull-up, pull-down for PHx pins */ + GPIOH->PUPDR = 0x00000000; + + /* Connect PIx pins to FMC Alternate function */ + GPIOI->AFR[0] = 0xCCCCCCCC; + GPIOI->AFR[1] = 0x00000CC0; + /* Configure PIx pins in Alternate function mode */ + GPIOI->MODER = 0x0028AAAA; + /* Configure PIx pins speed to 50 MHz */ + GPIOI->OSPEEDR = 0x0028AAAA; + /* Configure PIx pins Output type to push-pull */ + GPIOI->OTYPER = 0x00000000; + /* No pull-up, pull-down for PIx pins */ + GPIOI->PUPDR = 0x00000000; + +/*-- FMC Configuration -------------------------------------------------------*/ + /* Enable the FMC interface clock */ + RCC->AHB3ENR |= 0x00000001; + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + + FMC_Bank5_6->SDCR[0] = 0x000019E4; + FMC_Bank5_6->SDTR[0] = 0x01115351; + + /* SDRAM initialization sequence */ + /* Clock enable command */ + FMC_Bank5_6->SDCMR = 0x00000011; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Delay */ + for (index = 0; index<1000; index++); + + /* PALL command */ + FMC_Bank5_6->SDCMR = 0x00000012; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Auto refresh command */ + FMC_Bank5_6->SDCMR = 0x00000073; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* MRD register program */ + FMC_Bank5_6->SDCMR = 0x00046014; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Set refresh count */ + tmpreg = FMC_Bank5_6->SDRTR; + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); + + /* Disable write protection */ + tmpreg = FMC_Bank5_6->SDCR[0]; + FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001011; + FMC_Bank1->BTCR[3] = 0x00000201; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ +#if defined(STM32F469xx) || defined(STM32F479xx) + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001091; + FMC_Bank1->BTCR[3] = 0x00110212; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F469xx || STM32F479xx */ + + (void)(tmp); +} +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ +#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external memories (SRAM/SDRAM) + * This SRAM/SDRAM will be used as program data memory (including heap and stack). + * @param None + * @retval None + */ +void SystemInit_ExtMemCtl(void) +{ + __IO uint32_t tmp = 0x00; +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +#if defined (DATA_IN_ExtSDRAM) + register uint32_t tmpreg = 0, timeout = 0xFFFF; + register __IO uint32_t index; + +#if defined(STM32F446xx) + /* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface + clock */ + RCC->AHB1ENR |= 0x0000007D; +#else + /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface + clock */ + RCC->AHB1ENR |= 0x000001F8; +#endif /* STM32F446xx */ + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); + +#if defined(STM32F446xx) + /* Connect PAx pins to FMC Alternate function */ + GPIOA->AFR[0] |= 0xC0000000; + GPIOA->AFR[1] |= 0x00000000; + /* Configure PDx pins in Alternate function mode */ + GPIOA->MODER |= 0x00008000; + /* Configure PDx pins speed to 50 MHz */ + GPIOA->OSPEEDR |= 0x00008000; + /* Configure PDx pins Output type to push-pull */ + GPIOA->OTYPER |= 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOA->PUPDR |= 0x00000000; + + /* Connect PCx pins to FMC Alternate function */ + GPIOC->AFR[0] |= 0x00CC0000; + GPIOC->AFR[1] |= 0x00000000; + /* Configure PDx pins in Alternate function mode */ + GPIOC->MODER |= 0x00000A00; + /* Configure PDx pins speed to 50 MHz */ + GPIOC->OSPEEDR |= 0x00000A00; + /* Configure PDx pins Output type to push-pull */ + GPIOC->OTYPER |= 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOC->PUPDR |= 0x00000000; +#endif /* STM32F446xx */ + + /* Connect PDx pins to FMC Alternate function */ + GPIOD->AFR[0] = 0x000000CC; + GPIOD->AFR[1] = 0xCC000CCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xA02A000A; + /* Configure PDx pins speed to 50 MHz */ + GPIOD->OSPEEDR = 0xA02A000A; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; + + /* Connect PEx pins to FMC Alternate function */ + GPIOE->AFR[0] = 0xC00000CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA800A; + /* Configure PEx pins speed to 50 MHz */ + GPIOE->OSPEEDR = 0xAAAA800A; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + + /* Connect PFx pins to FMC Alternate function */ + GPIOF->AFR[0] = 0xCCCCCCCC; + GPIOF->AFR[1] = 0xCCCCCCCC; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA800AAA; + /* Configure PFx pins speed to 50 MHz */ + GPIOF->OSPEEDR = 0xAA800AAA; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; + + /* Connect PGx pins to FMC Alternate function */ + GPIOG->AFR[0] = 0xCCCCCCCC; + GPIOG->AFR[1] = 0xCCCCCCCC; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0xAAAAAAAA; + /* Configure PGx pins speed to 50 MHz */ + GPIOG->OSPEEDR = 0xAAAAAAAA; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) + /* Connect PHx pins to FMC Alternate function */ + GPIOH->AFR[0] = 0x00C0CC00; + GPIOH->AFR[1] = 0xCCCCCCCC; + /* Configure PHx pins in Alternate function mode */ + GPIOH->MODER = 0xAAAA08A0; + /* Configure PHx pins speed to 50 MHz */ + GPIOH->OSPEEDR = 0xAAAA08A0; + /* Configure PHx pins Output type to push-pull */ + GPIOH->OTYPER = 0x00000000; + /* No pull-up, pull-down for PHx pins */ + GPIOH->PUPDR = 0x00000000; + + /* Connect PIx pins to FMC Alternate function */ + GPIOI->AFR[0] = 0xCCCCCCCC; + GPIOI->AFR[1] = 0x00000CC0; + /* Configure PIx pins in Alternate function mode */ + GPIOI->MODER = 0x0028AAAA; + /* Configure PIx pins speed to 50 MHz */ + GPIOI->OSPEEDR = 0x0028AAAA; + /* Configure PIx pins Output type to push-pull */ + GPIOI->OTYPER = 0x00000000; + /* No pull-up, pull-down for PIx pins */ + GPIOI->PUPDR = 0x00000000; +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ + +/*-- FMC Configuration -------------------------------------------------------*/ + /* Enable the FMC interface clock */ + RCC->AHB3ENR |= 0x00000001; + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + + /* Configure and enable SDRAM bank1 */ +#if defined(STM32F446xx) + FMC_Bank5_6->SDCR[0] = 0x00001954; +#else + FMC_Bank5_6->SDCR[0] = 0x000019E4; +#endif /* STM32F446xx */ + FMC_Bank5_6->SDTR[0] = 0x01115351; + + /* SDRAM initialization sequence */ + /* Clock enable command */ + FMC_Bank5_6->SDCMR = 0x00000011; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Delay */ + for (index = 0; index<1000; index++); + + /* PALL command */ + FMC_Bank5_6->SDCMR = 0x00000012; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Auto refresh command */ +#if defined(STM32F446xx) + FMC_Bank5_6->SDCMR = 0x000000F3; +#else + FMC_Bank5_6->SDCMR = 0x00000073; +#endif /* STM32F446xx */ + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* MRD register program */ +#if defined(STM32F446xx) + FMC_Bank5_6->SDCMR = 0x00044014; +#else + FMC_Bank5_6->SDCMR = 0x00046014; +#endif /* STM32F446xx */ + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Set refresh count */ + tmpreg = FMC_Bank5_6->SDRTR; +#if defined(STM32F446xx) + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1)); +#else + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); +#endif /* STM32F446xx */ + + /* Disable write protection */ + tmpreg = FMC_Bank5_6->SDCR[0]; + FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); +#endif /* DATA_IN_ExtSDRAM */ +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ + +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ + || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) + +#if defined(DATA_IN_ExtSRAM) +/*-- GPIOs Configuration -----------------------------------------------------*/ + /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ + RCC->AHB1ENR |= 0x00000078; + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN); + + /* Connect PDx pins to FMC Alternate function */ + GPIOD->AFR[0] = 0x00CCC0CC; + GPIOD->AFR[1] = 0xCCCCCCCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xAAAA0A8A; + /* Configure PDx pins speed to 100 MHz */ + GPIOD->OSPEEDR = 0xFFFF0FCF; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; + + /* Connect PEx pins to FMC Alternate function */ + GPIOE->AFR[0] = 0xC00CC0CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA828A; + /* Configure PEx pins speed to 100 MHz */ + GPIOE->OSPEEDR = 0xFFFFC3CF; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + + /* Connect PFx pins to FMC Alternate function */ + GPIOF->AFR[0] = 0x00CCCCCC; + GPIOF->AFR[1] = 0xCCCC0000; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA000AAA; + /* Configure PFx pins speed to 100 MHz */ + GPIOF->OSPEEDR = 0xFF000FFF; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; + + /* Connect PGx pins to FMC Alternate function */ + GPIOG->AFR[0] = 0x00CCCCCC; + GPIOG->AFR[1] = 0x000000C0; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0x00085AAA; + /* Configure PGx pins speed to 100 MHz */ + GPIOG->OSPEEDR = 0x000CAFFF; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + +/*-- FMC/FSMC Configuration --------------------------------------------------*/ + /* Enable the FMC/FSMC interface clock */ + RCC->AHB3ENR |= 0x00000001; + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001011; + FMC_Bank1->BTCR[3] = 0x00000201; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ +#if defined(STM32F469xx) || defined(STM32F479xx) + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001091; + FMC_Bank1->BTCR[3] = 0x00110212; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F469xx || STM32F479xx */ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\ + || defined(STM32F412Zx) || defined(STM32F412Vx) + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN); + /* Configure and enable Bank1_SRAM2 */ + FSMC_Bank1->BTCR[2] = 0x00001011; + FSMC_Bank1->BTCR[3] = 0x00000201; + FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF; +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */ + +#endif /* DATA_IN_ExtSRAM */ +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ + STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */ + (void)(tmp); +} +#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From 489c2f9f8d452812271ddc57b1ce70311f70b355 Mon Sep 17 00:00:00 2001 From: crazt Date: Wed, 30 Jun 2021 17:04:02 +0800 Subject: [PATCH 217/255] [bsp/stm32/rmc] Robomaster C BSP configuration. --- bsp/stm32/stm32f407-robomaster-c/.config | 261 ++++- .../applications/main.c | 11 +- .../stm32f407-robomaster-c/board/Kconfig | 2 +- .../stm32f407-robomaster-c/board/board.c | 10 +- .../stm32f407-robomaster-c/board/board.h | 1 + .../stm32f407-robomaster-c/project.uvoptx | 736 ++++++++++++- .../stm32f407-robomaster-c/project.uvprojx | 965 +++++------------- bsp/stm32/stm32f407-robomaster-c/rtconfig.h | 32 +- .../stm32f407-robomaster-c/template.uvoptx | 18 +- .../stm32f407-robomaster-c/template.uvprojx | 21 +- 10 files changed, 1277 insertions(+), 780 deletions(-) diff --git a/bsp/stm32/stm32f407-robomaster-c/.config b/bsp/stm32/stm32f407-robomaster-c/.config index 13a4d62a3a..4d8ccbfd5d 100644 --- a/bsp/stm32/stm32f407-robomaster-c/.config +++ b/bsp/stm32/stm32f407-robomaster-c/.config @@ -7,6 +7,7 @@ # RT-Thread Kernel # CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set # CONFIG_RT_USING_SMP is not set CONFIG_RT_ALIGN_SIZE=4 # CONFIG_RT_THREAD_PRIORITY_8 is not set @@ -20,6 +21,12 @@ CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 CONFIG_IDLE_THREAD_STACK_SIZE=256 # CONFIG_RT_USING_TIMER_SOFT is not set + +# +# 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 @@ -51,6 +58,7 @@ CONFIG_RT_USING_MEMPOOL=y # CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set CONFIG_RT_USING_HEAP=y @@ -63,8 +71,9 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=128 CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" -CONFIG_RT_VER_NUM=0x40000 +CONFIG_RT_VER_NUM=0x40004 CONFIG_ARCH_ARM=y +CONFIG_RT_USING_CPU_FFS=y CONFIG_ARCH_ARM_CORTEX_M=y CONFIG_ARCH_ARM_CORTEX_M4=y # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set @@ -111,28 +120,34 @@ CONFIG_FINSH_ARG_MAX=10 # 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_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set # CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set # CONFIG_RT_USING_PWM is not set # CONFIG_RT_USING_MTD_NOR is not set # CONFIG_RT_USING_MTD_NAND is not set -# CONFIG_RT_USING_MTD is not set # CONFIG_RT_USING_PM is not set # CONFIG_RT_USING_RTC is not set # CONFIG_RT_USING_SDIO is not set # CONFIG_RT_USING_SPI is not set # CONFIG_RT_USING_WDT is not set # CONFIG_RT_USING_AUDIO is not set - -# -# Using WiFi -# +# 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 # @@ -146,6 +161,8 @@ CONFIG_RT_USING_PIN=y # # CONFIG_RT_USING_LIBC is not set # CONFIG_RT_USING_PTHREADS is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # # Network @@ -156,16 +173,16 @@ CONFIG_RT_USING_PIN=y # # CONFIG_RT_USING_SAL is not set +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + # # light weight TCP/IP stack # # CONFIG_RT_USING_LWIP is not set -# -# Modbus master and slave stack -# -# CONFIG_RT_USING_MODBUS is not set - # # AT commands # @@ -179,17 +196,16 @@ CONFIG_RT_USING_PIN=y # # Utilities # -# CONFIG_RT_USING_LOGTRACE is not set # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG 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 # -# ARM CMSIS +# RT-Thread Utestcases # -# CONFIG_RT_USING_CMSIS_OS is not set -# CONFIG_RT_USING_RTT_CMSIS is not set -# CONFIG_RT_USING_LWP is not set +# CONFIG_RT_USING_UTESTCASES is not set # # RT-Thread online packages @@ -198,13 +214,20 @@ CONFIG_RT_USING_PIN=y # # 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 @@ -222,10 +245,14 @@ CONFIG_RT_USING_PIN=y # 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 # @@ -235,7 +262,36 @@ CONFIG_RT_USING_PIN=y # 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_IOTKIT 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 # # security packages @@ -243,6 +299,8 @@ CONFIG_RT_USING_PIN=y # 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 @@ -256,6 +314,13 @@ CONFIG_RT_USING_PIN=y # # 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 # # tools packages @@ -267,6 +332,33 @@ CONFIG_RT_USING_PIN=y # 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_MEM_SANDBOX is not set # # system packages @@ -275,30 +367,127 @@ CONFIG_RT_USING_PIN=y # CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set -# CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_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 + +# +# 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_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# 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 +# 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_AHT10 is not set -# CONFIG_PKG_USING_AP3216C 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_MPU6XXX 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 + +# +# 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 @@ -308,12 +497,17 @@ CONFIG_RT_USING_PIN=y # 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_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 @@ -324,13 +518,32 @@ CONFIG_RT_USING_PIN=y # 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_SOC_FAMILY_STM32=y CONFIG_SOC_SERIES_STM32F4=y # # Hardware Drivers Config # -CONFIG_SOC_STM32F407ZG=y +CONFIG_SOC_STM32F407IG=y # # Onboard Peripheral Drivers @@ -343,8 +556,8 @@ CONFIG_BSP_USING_GPIO=y CONFIG_BSP_USING_UART=y CONFIG_BSP_USING_UART1=y # CONFIG_BSP_UART1_RX_USING_DMA is not set -# CONFIG_BSP_USING_SPI is not set -# CONFIG_BSP_USING_I2C1 is not set +# CONFIG_BSP_USING_RNG is not set +# CONFIG_BSP_USING_UDID is not set # # Board extended module Drivers diff --git a/bsp/stm32/stm32f407-robomaster-c/applications/main.c b/bsp/stm32/stm32f407-robomaster-c/applications/main.c index 487ddf44f6..5a7535a144 100644 --- a/bsp/stm32/stm32f407-robomaster-c/applications/main.c +++ b/bsp/stm32/stm32f407-robomaster-c/applications/main.c @@ -6,26 +6,27 @@ * Change Logs: * Date Author Notes * 2018-11-06 SummerGift first version + * 2021-06-30 crazt modify for robomaster C board */ #include #include #include -/* defined the LED0 pin: PB1 */ -#define LED0_PIN GET_PIN(B, 1) +/* defined the LED Blue pin: PB1 */ +#define LED_B_PIN GET_PIN(H, 10) int main(void) { int count = 1; /* set LED0 pin mode to output */ - rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); + rt_pin_mode(LED_B_PIN, PIN_MODE_OUTPUT); while (count++) { - rt_pin_write(LED0_PIN, PIN_HIGH); + rt_pin_write(LED_B_PIN, PIN_HIGH); rt_thread_mdelay(500); - rt_pin_write(LED0_PIN, PIN_LOW); + rt_pin_write(LED_B_PIN, PIN_LOW); rt_thread_mdelay(500); } diff --git a/bsp/stm32/stm32f407-robomaster-c/board/Kconfig b/bsp/stm32/stm32f407-robomaster-c/board/Kconfig index 24a15a4e3e..cf0200cbaa 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/Kconfig +++ b/bsp/stm32/stm32f407-robomaster-c/board/Kconfig @@ -1,6 +1,6 @@ menu "Hardware Drivers Config" -config SOC_STM32F407ZG +config SOC_STM32F407IG bool select SOC_SERIES_STM32F4 select RT_USING_COMPONENTS_INIT diff --git a/bsp/stm32/stm32f407-robomaster-c/board/board.c b/bsp/stm32/stm32f407-robomaster-c/board/board.c index ef1f24cbb5..6a7a775832 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/board.c +++ b/bsp/stm32/stm32f407-robomaster-c/board/board.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2018-11-06 SummerGift first version + * 2021-06-30 crazt modify for robomaster C board */ #include "board.h" @@ -15,17 +16,18 @@ void SystemClock_Config(void) RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - /**Configure the main internal regulator output voltage + /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); - /**Initializes the CPU, AHB and APB busses clocks + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLM = 4; + RCC_OscInitStruct.PLL.PLLM = 6; RCC_OscInitStruct.PLL.PLLN = 168; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; @@ -33,7 +35,7 @@ void SystemClock_Config(void) { Error_Handler(); } - /**Initializes the CPU, AHB and APB busses clocks + /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; diff --git a/bsp/stm32/stm32f407-robomaster-c/board/board.h b/bsp/stm32/stm32f407-robomaster-c/board/board.h index 514155b823..3a25989bc2 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/board.h +++ b/bsp/stm32/stm32f407-robomaster-c/board/board.h @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2018-11-5 SummerGift first version + * 2021-06-30 crazt modify for robomaster C board */ #ifndef __BOARD_H__ diff --git a/bsp/stm32/stm32f407-robomaster-c/project.uvoptx b/bsp/stm32/stm32f407-robomaster-c/project.uvoptx index f8c4606a9e..01c3739c9d 100644 --- a/bsp/stm32/stm32f407-robomaster-c/project.uvoptx +++ b/bsp/stm32/stm32f407-robomaster-c/project.uvoptx @@ -73,7 +73,7 @@ 0 - 0 + 1 0 1 @@ -103,7 +103,7 @@ 1 0 0 - 4 + 6 @@ -114,18 +114,23 @@ - Segger\JL2CM3.dll + STLink\ST-LINKIII-KEIL_SWO.dll 0 - JL2CM3 - -U30000299 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8001 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM) + ST-LINKIII-KEIL_SWO + -U0674FF504955857567053730 -O206 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(2BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F407IGHx$CMSIS\Flash\STM32F4xx_1024.FLM) 0 UL2CM3 - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM)) + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0STM32F4xx_1024 -FL0100000 -FS08000000 -FP0($$Device:STM32F407IGHx$CMSIS\Flash\STM32F4xx_1024.FLM) + + + 0 + JL2CM3 + -U30000299 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8001 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F407IGHx$CMSIS\Flash\STM32F4xx_1024.FLM) @@ -173,6 +178,7 @@ 1 + 0 0 2 10000000 @@ -181,11 +187,727 @@ - Source Group 1 + Applications 0 0 0 0 + + 1 + 1 + 1 + 0 + 0 + 0 + applications\main.c + main.c + 0 + 0 + + + + + CPU + 0 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\div0.c + div0.c + 0 + 0 + + + 2 + 3 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\backtrace.c + backtrace.c + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\showmem.c + showmem.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + cpuport.c + 0 + 0 + + + 2 + 6 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + context_rvds.S + 0 + 0 + + + + + DeviceDrivers + 0 + 0 + 0 + 0 + + 3 + 7 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\serial\serial.c + serial.c + 0 + 0 + + + 3 + 9 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\dataqueue.c + dataqueue.c + 0 + 0 + + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\pipe.c + pipe.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\workqueue.c + workqueue.c + 0 + 0 + + + 3 + 12 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\waitqueue.c + waitqueue.c + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringbuffer.c + ringbuffer.c + 0 + 0 + + + 3 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\completion.c + completion.c + 0 + 0 + + + 3 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + + + Drivers + 0 + 0 + 0 + 0 + + 4 + 16 + 1 + 0 + 0 + 0 + board\CubeMX_Config\Src\stm32f4xx_hal_msp.c + stm32f4xx_hal_msp.c + 0 + 0 + + + 4 + 17 + 2 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm\startup_stm32f407xx.s + startup_stm32f407xx.s + 0 + 0 + + + 4 + 18 + 1 + 0 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + 4 + 19 + 1 + 0 + 0 + 0 + ..\libraries\HAL_Drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 4 + 20 + 1 + 0 + 0 + 0 + ..\libraries\HAL_Drivers\drv_usart.c + drv_usart.c + 0 + 0 + + + 4 + 21 + 1 + 0 + 0 + 0 + ..\libraries\HAL_Drivers\drv_common.c + drv_common.c + 0 + 0 + + + + + finsh + 0 + 0 + 0 + 0 + + 5 + 22 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 5 + 23 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 5 + 24 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + + + + + Kernel + 0 + 0 + 0 + 0 + + 6 + 25 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 6 + 26 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 6 + 27 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 6 + 28 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 6 + 29 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 6 + 30 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + 6 + 31 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 6 + 32 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 6 + 33 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 6 + 34 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 6 + 35 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 6 + 36 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 6 + 37 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + + + libc + 0 + 0 + 0 + 0 + + 7 + 38 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\time.c + time.c + 0 + 0 + + + + + Libraries + 0 + 0 + 0 + 0 + + 8 + 39 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c + stm32f4xx_hal_uart.c + 0 + 0 + + + 8 + 40 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp_ex.c + stm32f4xx_hal_cryp_ex.c + 0 + 0 + + + 8 + 41 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c + stm32f4xx_hal_pwr_ex.c + 0 + 0 + + + 8 + 42 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rng.c + stm32f4xx_hal_rng.c + 0 + 0 + + + 8 + 43 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c + stm32f4xx_hal_dma.c + 0 + 0 + + + 8 + 44 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c + stm32f4xx_hal.c + 0 + 0 + + + 8 + 45 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c + stm32f4xx_hal_rcc_ex.c + 0 + 0 + + + 8 + 46 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_usart.c + stm32f4xx_hal_usart.c + 0 + 0 + + + 8 + 47 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cec.c + stm32f4xx_hal_cec.c + 0 + 0 + + + 8 + 48 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c + stm32f4xx_hal_rcc.c + 0 + 0 + + + 8 + 49 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c + stm32f4xx_hal_dma_ex.c + 0 + 0 + + + 8 + 50 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c + stm32f4xx_hal_pwr.c + 0 + 0 + + + 8 + 51 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c + system_stm32f4xx.c + 0 + 0 + + + 8 + 52 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_crc.c + stm32f4xx_hal_crc.c + 0 + 0 + + + 8 + 53 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c + stm32f4xx_hal_cortex.c + 0 + 0 + + + 8 + 54 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp.c + stm32f4xx_hal_cryp.c + 0 + 0 + + + 8 + 55 + 1 + 0 + 0 + 0 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c + stm32f4xx_hal_gpio.c + 0 + 0 + diff --git a/bsp/stm32/stm32f407-robomaster-c/project.uvprojx b/bsp/stm32/stm32f407-robomaster-c/project.uvprojx index 88c46860e7..0fd6eafce1 100644 --- a/bsp/stm32/stm32f407-robomaster-c/project.uvprojx +++ b/bsp/stm32/stm32f407-robomaster-c/project.uvprojx @@ -1,7 +1,10 @@ + 2.1 +
### uVision Project, (C) Keil Software
+ rt-thread @@ -11,33 +14,33 @@ 0 - STM32F407ZGTx + STM32F407IGHx STMicroelectronics - Keil.STM32F4xx_DFP.2.11.0 - http://www.keil.com/pack - IRAM(0x20000000,0x20000) IRAM2(0x10000000,0x10000) IROM(0x08000000,0x100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE - - - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM)) + Keil.STM32F4xx_DFP.2.15.0 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00020000) IRAM2(0x10000000,0x00010000) IROM(0x08000000,0x00100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407IGHx$CMSIS\Flash\STM32F4xx_1024.FLM)) 0 - $$Device:STM32F407ZGTx$Drivers\CMSIS\Device\ST\STM32F4xx\Include\stm32f4xx.h - - - - - - - - - - $$Device:STM32F407ZGTx$CMSIS\SVD\STM32F40x.svd + $$Device:STM32F407IGHx$Drivers\CMSIS\Device\ST\STM32F4xx\Include\stm32f4xx.h + + + + + + + + + + $$Device:STM32F407IGHx$CMSIS\SVD\STM32F40x.svd 0 0 - - - - - + + + + + 0 0 @@ -59,8 +62,8 @@ 0 0 - - + + 0 0 0 @@ -69,8 +72,8 @@ 0 0 - - + + 0 0 0 @@ -80,14 +83,14 @@ 1 0 fromelf --bin !L --output rtthread.bin - + 0 0 0 0 0 - + 0 @@ -101,8 +104,8 @@ 0 0 3 - - + + 1 @@ -135,11 +138,11 @@ 1 BIN\UL2CM3.DLL - "" () - - - - + + + + + 0 @@ -172,7 +175,7 @@ 0 0 "Cortex-M4" - + 0 0 0 @@ -181,6 +184,7 @@ 0 0 2 + 0 1 0 8 @@ -205,8 +209,8 @@ 0 0 0 - 0 - 1 + 1 + 0 0 @@ -304,7 +308,7 @@ 0x10000 - + 1 @@ -331,10 +335,10 @@ 0 0 - - USE_HAL_DRIVER, STM32F407xx - - applications;.;board;board\CubeMX_Config\Inc;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\include;..\..\..\libcpu\arm\cortex-m4;..\..\..\libcpu\arm\common;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\finsh;..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Inc;..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Include;..\libraries\STM32F4xx_HAL\CMSIS\Include + + USE_HAL_DRIVER, STM32F407xx, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\CubeMX_Config\Inc;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\none-gcc;..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Inc;..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Include;..\libraries\STM32F4xx_HAL\CMSIS\Include;..\..\..\examples\utest\testcases\kernel @@ -349,10 +353,10 @@ 0 0 - - - - + + + + @@ -364,13 +368,13 @@ 0 0x08000000 0x20000000 - + .\board\linker_scripts\link.sct - - - --keep *.o(.rti_fn.*) --keep *.o(FSymTab) - - + + + + + @@ -386,187 +390,33 @@ - Drivers - - - board.c - 1 - board\board.c - - - - - stm32f4xx_hal_msp.c - 1 - board\CubeMX_Config\Src\stm32f4xx_hal_msp.c - - - - - startup_stm32f407xx.s - 2 - ..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm\startup_stm32f407xx.s - - - - - drv_gpio.c - 1 - ..\libraries\HAL_Drivers\drv_gpio.c - - - - - drv_usart.c - 1 - ..\libraries\HAL_Drivers\drv_usart.c - - - - - drv_common.c - 1 - ..\libraries\HAL_Drivers\drv_common.c - - - - - Kernel - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - CORTEX-M4 - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m4\cpuport.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - + CPU div0.c 1 ..\..\..\libcpu\arm\common\div0.c - - + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + showmem.c 1 ..\..\..\libcpu\arm\common\showmem.c + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + @@ -577,61 +427,80 @@ 1 ..\..\..\components\drivers\misc\pin.c - - serial.c 1 ..\..\..\components\drivers\serial\serial.c - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - dataqueue.c 1 ..\..\..\components\drivers\src\dataqueue.c - - pipe.c 1 ..\..\..\components\drivers\src\pipe.c - - + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + ringblk_buf.c 1 ..\..\..\components\drivers\src\ringblk_buf.c + + + Drivers - ringbuffer.c + stm32f4xx_hal_msp.c 1 - ..\..\..\components\drivers\src\ringbuffer.c + board\CubeMX_Config\Src\stm32f4xx_hal_msp.c - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c + startup_stm32f407xx.s + 2 + ..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm\startup_stm32f407xx.s - - - workqueue.c + board.c 1 - ..\..\..\components\drivers\src\workqueue.c + board\board.c + + + drv_gpio.c + 1 + ..\libraries\HAL_Drivers\drv_gpio.c + + + drv_usart.c + 1 + ..\libraries\HAL_Drivers\drv_usart.c + + + drv_common.c + 1 + ..\libraries\HAL_Drivers\drv_common.c @@ -643,528 +512,196 @@ 1 ..\..\..\components\finsh\shell.c - - - symbol.c + msh.c 1 - ..\..\..\components\finsh\symbol.c + ..\..\..\components\finsh\msh.c - - cmd.c 1 ..\..\..\components\finsh\cmd.c + + + Kernel - msh.c + object.c 1 - ..\..\..\components\finsh\msh.c + ..\..\..\src\object.c - - - msh_cmd.c + ipc.c 1 - ..\..\..\components\finsh\msh_cmd.c + ..\..\..\src\ipc.c - - - msh_file.c + kservice.c 1 - ..\..\..\components\finsh\msh_file.c + ..\..\..\src\kservice.c + + + clock.c + 1 + ..\..\..\src\clock.c + + + irq.c + 1 + ..\..\..\src\irq.c + + + timer.c + 1 + ..\..\..\src\timer.c + + + idle.c + 1 + ..\..\..\src\idle.c + + + thread.c + 1 + ..\..\..\src\thread.c + + + device.c + 1 + ..\..\..\src\device.c + + + mem.c + 1 + ..\..\..\src\mem.c + + + components.c + 1 + ..\..\..\src\components.c + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + scheduler.c + 1 + ..\..\..\src\scheduler.c - STM32_HAL + libc - system_stm32f4xx.c + time.c 1 - ..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c - - - - - stm32f4xx_hal.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c - - - - - stm32f4xx_hal_adc.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c - - - - - stm32f4xx_hal_adc_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c - - - - - stm32f4xx_hal_can.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_can.c - - - - - stm32f4xx_hal_cec.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cec.c - - - - - stm32f4xx_hal_cortex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c - - - - - stm32f4xx_hal_crc.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_crc.c - - - - - stm32f4xx_hal_cryp.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp.c - - - - - stm32f4xx_hal_cryp_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp_ex.c - - - - - stm32f4xx_hal_dac.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dac.c - - - - - stm32f4xx_hal_dac_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dac_ex.c - - - - - stm32f4xx_hal_dcmi.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dcmi.c - - - - - stm32f4xx_hal_dcmi_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dcmi_ex.c - - - - - stm32f4xx_hal_dfsdm.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dfsdm.c - - - - - stm32f4xx_hal_dma.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c - - - - - stm32f4xx_hal_dma2d.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma2d.c - - - - - stm32f4xx_hal_dma_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c - - - - - stm32f4xx_hal_dsi.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dsi.c - - - - - stm32f4xx_hal_eth.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_eth.c - - - - - stm32f4xx_hal_flash.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c - - - - - stm32f4xx_hal_flash_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c - - - - - stm32f4xx_hal_flash_ramfunc.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c - - - - - stm32f4xx_hal_fmpi2c.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_fmpi2c.c - - - - - stm32f4xx_hal_fmpi2c_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_fmpi2c_ex.c - - - - - stm32f4xx_hal_gpio.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c - - - - - stm32f4xx_hal_hash.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hash.c - - - - - stm32f4xx_hal_hash_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hash_ex.c - - - - - stm32f4xx_hal_hcd.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hcd.c - - - - - stm32f4xx_hal_i2c.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2c.c - - - - - stm32f4xx_hal_i2c_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2c_ex.c - - - - - stm32f4xx_hal_i2s.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2s.c - - - - - stm32f4xx_hal_i2s_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2s_ex.c - - - - - stm32f4xx_hal_irda.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_irda.c - - - - - stm32f4xx_hal_iwdg.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_iwdg.c - - - - - stm32f4xx_hal_lptim.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_lptim.c - - - - - stm32f4xx_hal_ltdc.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_ltdc.c - - - - - stm32f4xx_hal_ltdc_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_ltdc_ex.c - - - - - stm32f4xx_hal_nand.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_nand.c - - - - - stm32f4xx_hal_nor.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_nor.c - - - - - stm32f4xx_hal_pccard.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pccard.c - - - - - stm32f4xx_hal_pcd.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd.c - - - - - stm32f4xx_hal_pcd_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd_ex.c - - - - - stm32f4xx_hal_pwr.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c - - - - - stm32f4xx_hal_pwr_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c - - - - - stm32f4xx_hal_qspi.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_qspi.c - - - - - stm32f4xx_hal_rcc.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c - - - - - stm32f4xx_hal_rcc_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c - - - - - stm32f4xx_hal_rng.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rng.c - - - - - stm32f4xx_hal_rtc.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc.c - - - - - stm32f4xx_hal_rtc_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc_ex.c - - - - - stm32f4xx_hal_sai.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sai.c - - - - - stm32f4xx_hal_sai_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sai_ex.c - - - - - stm32f4xx_hal_sd.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sd.c - - - - - stm32f4xx_hal_sdram.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sdram.c - - - - - stm32f4xx_hal_smartcard.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_smartcard.c - - - - - stm32f4xx_hal_spdifrx.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spdifrx.c - - - - - stm32f4xx_hal_spi.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spi.c - - - - - stm32f4xx_hal_sram.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sram.c - - - - - stm32f4xx_hal_tim.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c - - - - - stm32f4xx_hal_tim_ex.c - 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c + ..\..\..\components\libc\compilers\common\time.c + + + Libraries stm32f4xx_hal_uart.c 1 ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c - - + + stm32f4xx_hal_cryp_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp_ex.c + + + stm32f4xx_hal_pwr_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c + + + stm32f4xx_hal_rng.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rng.c + + + stm32f4xx_hal_dma.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c + + + stm32f4xx_hal.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c + + + stm32f4xx_hal_rcc_ex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c + stm32f4xx_hal_usart.c 1 ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_usart.c - - - stm32f4xx_hal_wwdg.c + stm32f4xx_hal_cec.c 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_wwdg.c + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cec.c - - - stm32f4xx_ll_fmc.c + stm32f4xx_hal_rcc.c 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_fmc.c + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c - - - stm32f4xx_ll_fsmc.c + stm32f4xx_hal_dma_ex.c 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_fsmc.c + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c - - - stm32f4xx_ll_sdmmc.c + stm32f4xx_hal_pwr.c 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_sdmmc.c + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c - - - stm32f4xx_ll_usb.c + system_stm32f4xx.c 1 - ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_usb.c + ..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c + + + stm32f4xx_hal_crc.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_crc.c + + + stm32f4xx_hal_cortex.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c + + + stm32f4xx_hal_cryp.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp.c + + + stm32f4xx_hal_gpio.c + 1 + ..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c
+ - - - + + + + diff --git a/bsp/stm32/stm32f407-robomaster-c/rtconfig.h b/bsp/stm32/stm32f407-robomaster-c/rtconfig.h index 7d83eb4f99..78104e6805 100644 --- a/bsp/stm32/stm32f407-robomaster-c/rtconfig.h +++ b/bsp/stm32/stm32f407-robomaster-c/rtconfig.h @@ -16,6 +16,9 @@ #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 #define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + #define RT_DEBUG #define RT_DEBUG_COLOR @@ -39,8 +42,9 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart1" -#define RT_VER_NUM 0x40000 +#define RT_VER_NUM 0x40004 #define ARCH_ARM +#define RT_USING_CPU_FFS #define ARCH_ARM_CORTEX_M #define ARCH_ARM_CORTEX_M4 @@ -78,29 +82,30 @@ #define RT_USING_DEVICE_IPC #define RT_PIPE_BUFSZ 512 #define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 #define RT_USING_PIN -/* Using WiFi */ - - /* Using USB */ /* POSIX layer and C standard library */ +#define RT_LIBC_USING_TIME +#define RT_LIBC_FIXED_TIMEZONE 8 /* Network */ /* Socket abstraction layer */ +/* Network interface device */ + + /* light weight TCP/IP stack */ -/* Modbus master and slave stack */ - - /* AT commands */ @@ -110,7 +115,7 @@ /* Utilities */ -/* ARM CMSIS */ +/* RT-Thread Utestcases */ /* RT-Thread online packages */ @@ -144,20 +149,29 @@ /* system packages */ +/* Micrium: Micrium software products porting for RT-Thread */ + + /* peripheral libraries and drivers */ +/* AI packages */ + + /* miscellaneous packages */ /* samples: kernel and components samples */ + +/* entertainment: terminal games and other interesting software packages */ + #define SOC_FAMILY_STM32 #define SOC_SERIES_STM32F4 /* Hardware Drivers Config */ -#define SOC_STM32F407ZG +#define SOC_STM32F407IG /* Onboard Peripheral Drivers */ diff --git a/bsp/stm32/stm32f407-robomaster-c/template.uvoptx b/bsp/stm32/stm32f407-robomaster-c/template.uvoptx index f8c4606a9e..ab07607d4a 100644 --- a/bsp/stm32/stm32f407-robomaster-c/template.uvoptx +++ b/bsp/stm32/stm32f407-robomaster-c/template.uvoptx @@ -73,7 +73,7 @@ 0 - 0 + 1 0 1 @@ -103,7 +103,7 @@ 1 0 0 - 4 + 6 @@ -114,18 +114,23 @@ - Segger\JL2CM3.dll + STLink\ST-LINKIII-KEIL_SWO.dll 0 - JL2CM3 - -U30000299 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8001 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM) + ST-LINKIII-KEIL_SWO + -U0674FF504955857567053730 -O206 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(2BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F407IGHx$CMSIS\Flash\STM32F4xx_1024.FLM) 0 UL2CM3 - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM)) + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0STM32F4xx_1024 -FL0100000 -FS08000000 -FP0($$Device:STM32F407IGHx$CMSIS\Flash\STM32F4xx_1024.FLM) + + + 0 + JL2CM3 + -U30000299 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8001 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F407IGHx$CMSIS\Flash\STM32F4xx_1024.FLM) @@ -173,6 +178,7 @@ 1 + 0 0 2 10000000 diff --git a/bsp/stm32/stm32f407-robomaster-c/template.uvprojx b/bsp/stm32/stm32f407-robomaster-c/template.uvprojx index 66fe3140e7..90f76b3093 100644 --- a/bsp/stm32/stm32f407-robomaster-c/template.uvprojx +++ b/bsp/stm32/stm32f407-robomaster-c/template.uvprojx @@ -14,16 +14,16 @@ 0 - STM32F407ZGTx + STM32F407IGHx STMicroelectronics - Keil.STM32F4xx_DFP.2.13.0 - http://www.keil.com/pack - IRAM(0x20000000,0x20000) IRAM2(0x10000000,0x10000) IROM(0x08000000,0x100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + Keil.STM32F4xx_DFP.2.15.0 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00020000) IRAM2(0x10000000,0x00010000) IROM(0x08000000,0x00100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM)) + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407IGHx$CMSIS\Flash\STM32F4xx_1024.FLM)) 0 - $$Device:STM32F407ZGTx$Drivers\CMSIS\Device\ST\STM32F4xx\Include\stm32f4xx.h + $$Device:STM32F407IGHx$Drivers\CMSIS\Device\ST\STM32F4xx\Include\stm32f4xx.h @@ -33,7 +33,7 @@ - $$Device:STM32F407ZGTx$CMSIS\SVD\STM32F40x.svd + $$Device:STM32F407IGHx$CMSIS\SVD\STM32F40x.svd 0 0 @@ -138,7 +138,7 @@ 1 BIN\UL2CM3.DLL - "" () + @@ -184,6 +184,7 @@ 0 0 2 + 0 1 0 8 @@ -208,8 +209,8 @@ 0 0 0 - 0 - 1 + 1 + 0 0 From 892ddb247d6b5e040ebe50783f6ab8b2755c44c9 Mon Sep 17 00:00:00 2001 From: crazt Date: Wed, 30 Jun 2021 19:16:06 +0800 Subject: [PATCH 218/255] [bsp/stm32/rmc] update readme. --- bsp/stm32/stm32f407-robomaster-c/README.md | 94 +++++++++--------- .../applications/SConscript | 4 +- .../stm32f407-robomaster-c/figures/board.png | Bin 177116 -> 149250 bytes 3 files changed, 46 insertions(+), 52 deletions(-) diff --git a/bsp/stm32/stm32f407-robomaster-c/README.md b/bsp/stm32/stm32f407-robomaster-c/README.md index 59fb59d3dd..27df826341 100644 --- a/bsp/stm32/stm32f407-robomaster-c/README.md +++ b/bsp/stm32/stm32f407-robomaster-c/README.md @@ -1,8 +1,8 @@ -# BSP README 模板 +# STM32F407 Robomaster 开发板C型 BSP 说明 ## 简介 -本文档为 xxx 开发板的 BSP (板级支持包) 说明。 +本文档为 STM32F407 Robomaster 开发板C型 的 BSP (板级支持包) 说明。 主要内容如下: @@ -14,50 +14,43 @@ ## 开发板介绍 -【此处简单介绍一下开发板】 +Robomaster 开发板C型 是大疆创新科技有限公司推出的一款基于 ARM Cortex-M4 内核的开发板。开发板主控芯片为 STM32F407IGH6TR,最高主频为 168Mhz,拥有丰富的扩展接口和通信接口。板载IMU传感器,可配合RoboMaster出品的M3508、 M2006直流无刷减速电机、UWB模块以及妙算等产品使用,亦可配合DJI飞控SDK使用。 开发板外观如下图所示: -![board](figures/board.png) +image-20210630111114846 + +> 开发板 C 型具有如下外设: 该开发板常用 **板载资源** 如下: -- MCU:STM32xxx,主频 xxxMHz,xxxKB FLASH ,xxxKB RAM -- 外部 RAM:型号,xMB -- 外部 FLASH:型号,xMB -- 常用外设 - - LED:x个,DS0(红色,PB1),DS1(绿色,PB0) - - 按键:x个,K0(兼具唤醒功能,PA0),K1(PC13) -- 常用接口:USB 转串口、SD 卡接口、以太网接口、LCD 接口等 -- 调试接口,标准 JTAG/SWD +- MCU: STM32F407IGH6TR, 168MHz Freq, 1024KB FLASH, 192KB RAM(含64KB CCM RAM)。 +- 调试接口:SWD +- 常用外设:用户自定义 LED、按键、蜂鸣器、六轴惯性测量单元和磁力计、电压检测 ADC。 +- 常用接口:5V 接口、BOOT 配置接口、micro USB 接口、可配置 I/O 接口、UART 接口、CAN 总线接口、PWM 接口、DBUS接口、数字摄像头 FPC 接口。 -开发板更多详细信息请参考【厂商名】 [xxx开发板介绍](https://xxx)。 +开发板的用户手册:[RoboMaster 开发板 C 型用户手册.pdf](https://rm-static.djicdn.com/tem/35228/RoboMaster%20%20%E5%BC%80%E5%8F%91%E6%9D%BF%20C%20%E5%9E%8B%E7%94%A8%E6%88%B7%E6%89%8B%E5%86%8C.pdf) + +开发板更多详细信息请参考 RoboMaster官网:[RoboMaster开发板 C 型](https://www.robomaster.com/zh-CN/products/components/general/development-board-type-c/info) ## 外设支持 本 BSP 目前对外设的支持情况如下: -| **板载外设** | **支持情况** | **备注** | -| :----------------- | :----------: | :------------------------------------- | -| USB 转串口 | 支持 | | -| SPI Flash | 支持 | | -| 以太网 | 支持 | | -| SD卡 | 暂不支持 | | -| CAN | 暂不支持 | | -| **片上外设** | **支持情况** | **备注** | -| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...176 | -| UART | 支持 | UART1/x/x | -| SPI | 支持 | SPI1/x/x | -| I2C | 支持 | 软件 I2C | -| SDIO | 暂不支持 | 即将支持 | -| RTC | 暂不支持 | 即将支持 | -| PWM | 暂不支持 | 即将支持 | -| USB Device | 暂不支持 | 即将支持 | -| USB Host | 暂不支持 | 即将支持 | -| IWG | 暂不支持 | 即将支持 | -| xxx | 暂不支持 | 即将支持 | -| **扩展模块** | **支持情况** | **备注** | -| xxx 模块 | 支持 | | +| **板载外设** | **支持情况** | **备注** | +| :----------- | :----------: | :----------------------------------- | +| CAN | 暂不支持 | CAN1, CAN2 | +| BMI088 | 暂不支持 | 六轴惯性测量单元 | +| IST8310 | 暂不支持 | 三轴磁力计 | +| **片上外设** | **支持情况** | **备注** | +| GPIO | 支持 | PA0, PA1... PH1 ---> PIN: 0, 1...144 | +| UART | 支持 | UART1, UART3(DBUS), UART6 | +| PWM | 暂不支持 | | +| SPI | 暂不支持 | | +| I2C | 暂不支持 | | +| USB | 暂不支持 | | +| **扩展模块** | **支持情况** | **备注** | +| 无 | | | ## 使用说明 @@ -74,51 +67,54 @@ ### 快速上手 -本 BSP 为开发者提供 MDK4、MDK5 和 IAR 工程,并且支持 GCC 开发环境。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 +本 BSP 为开发者提供 MDK5 和 IAR 工程,并且支持 GCC 开发环境。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 #### 硬件连接 -使用数据线连接开发板到 PC,打开电源开关。 +将准备好的 ST-Link/JLink/DapLink 与开发板连接,开发板上的调试接口为 MX1.25 4Pin。C板上没有电源指示灯,供电可以选用:调试接口的 3.3V 输入,micro USB 接口供电,XT30 电源输入。 #### 编译下载 双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 -> 工程默认配置使用 xxx 仿真器下载程序,在通过 xxx 连接开发板的基础上,点击下载按钮即可下载程序到开发板 +> 工程默认配置使用 ST-LINK 下载程序,点击下载按钮即可下载程序到开发板。 #### 运行结果 -下载程序成功之后,系统会自动运行,【这里写开发板运行起来之后的现象,如:LED 闪烁等】。 +下载程序成功之后,系统会自动运行,观察开发板上 LED 的运行效果,LED 会以蓝光进行周期性闪烁。 -连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: +此 BSP 的 FinSH 默认使用串口 1 (C板外壳上标有UART2的4Pin接口),在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: ```bash \ | / - RT - Thread Operating System - / | \ 3.1.1 build Nov 19 2018 - 2006 - 2018 Copyright by rt-thread team + / | \ 4.0.4 build Jun 30 2021 + 2006 - 2021 Copyright by rt-thread team msh > ``` +> 终端工具推荐使用 [MobaXterm](https://mobaxterm.mobatek.net/) 或 [Xshell](https://www.netsarang.com/en/free-for-home-school/),均有免费的个人版本 + ### 进阶使用 -此 BSP 默认只开启了 GPIO 和 串口1 的功能,如果需使用 SD 卡、Flash 等更多高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: +此 BSP 默认只开启了 GPIO 和 串口 2 的功能,更多高级功能需要利用 ENV 工具对 BSP 进行配置,步骤如下: -1. 在 bsp 下打开 env 工具。 +1. 在 BSP 下打开 env 工具。 -2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 +2. 输入 `menuconfig` 命令配置工程,配置好之后保存退出。 -3. 输入`pkgs --update`命令更新软件包。 +3. 输入 `pkgs --update` 命令更新软件包。 -4. 输入`scons --target=mdk4/mdk5/iar` 命令重新生成工程。 +4. 输入 `scons --target=mdk4/mdk5/iar` 命令重新生成工程。 -本章节更多详细的介绍请参考 [STM32 系列 BSP 外设驱动使用教程](../docs/STM32系列BSP外设驱动使用教程.md)。 +本章节更多详细的介绍请参考 [STM32 系列 BSP 外设驱动使用教程](../docs/STM32 系列 BSP 外设驱动使用教程. md)。 ## 注意事项 -- xxx +- 部分外设需通过 XT30 或 USB 接口供电才能使用,包括 CAN、舵机5V供电、IMU恒温电路 +- 目前 scons 支持生成 cmake 配置文件,可以使用 CLion 进行 C板 的程序开发,推荐同学们尝试。详细步骤可参见:[在 Clion 中调试 rt-thread 工程](https://club.rt-thread.org/ask/article/2840.html),C板的 openOCD 配置文件推荐选用 `stm32f4discovery.cfg` ,并将该配置文件的最后一行改为 `reset_config none` ## 联系人信息 维护人: -- [xxx](https://个人主页), 邮箱: \ No newline at end of file +- [crazt](https://github.com/CraztTnspt) ,邮箱: \ No newline at end of file diff --git a/bsp/stm32/stm32f407-robomaster-c/applications/SConscript b/bsp/stm32/stm32f407-robomaster-c/applications/SConscript index 6f66f7ab73..1381e63e13 100644 --- a/bsp/stm32/stm32f407-robomaster-c/applications/SConscript +++ b/bsp/stm32/stm32f407-robomaster-c/applications/SConscript @@ -3,9 +3,7 @@ from building import * cwd = GetCurrentDir() CPPPATH = [cwd, str(Dir('#'))] -src = Split(""" -main.c -""") +src = Glob('*.c') group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) diff --git a/bsp/stm32/stm32f407-robomaster-c/figures/board.png b/bsp/stm32/stm32f407-robomaster-c/figures/board.png index 8562ae6604128b239de0a6aeea03edc2bcb63e54..39d13173ed47ea83cef19fefe43995493305395a 100644 GIT binary patch literal 149250 zcmeEt^;eW(*Dl>D-5~-3(!$U=lz@VChcrWXcZYz|AstG?&>cgAgmg$sch`A%zwce^ z`~m03v(~J|Vjh_Lp56P}*N*(8EQ^gnjsXV;hb=EBtqKQ+2!Vq`h(SXE-tox#qzwm0 z3nwovq2`f!&}LP|FzZ=#ZJs?+rt3Ou@EiLFyo)Ilxn6)B1`@Lq1GCIz3^*Plz~(H; z6GggLyoC;Xa2Tm{l#8pP{EH^o&&~8D{D5qzh@LTwyAWUE9RoOkUfg6CrJ3Rb|HSe? z-zJ;ovZ0}^%!~M6Nv>zpgN4b9zAdLB`21yd8ry?OY4w@>tH<|oL@-CJAX>Eld70>% ztRCUuAxZr2>-MYV>;HWeG}r(CfBAnV1858<7Hq{l6B4;AH5*8awtgj*7YqErk*1N; z#2361Y*_#8x?J5bxClLHJYQ(fU=}KBHSJKJ<*dYYKYve$7Br_ISBH-zp%|%x@-sL69zBNcT!lz2R`WB@%kIf{nw6u= zJ!rmBX{yjL?mjmvp52mdEf5{L3;D7GA0ZQ($rnU>3|PG`hOjQZ zaat%lcGt&%^cE@+N=i$d7zqm^? zr&|!>iPfhq->UC1HSvzC97(EfqGbj`S@L~8+AU_?4(ay{XzNMXTfhfaze_;m_rY|24=ek?oCYjexzpv$gd))~F&aO^Z97`Jk zk(kf=mnZZ`UGH0sS-xsrha>gy0#%A*R#LfOMe7w)?vQA4Q-|Z7+NChW%#cyvo%K#< z%SUlTkJwkUq*Al+-+h5)Tg@>8pfBP72t>D(WwL+Xz#^UAY~fqIw-CzxVx&riY?{%p z$(6d^y#m;^yjkKoXIU!iT?KOs83UPmj5@vta32H?b9mP}s~6nU+;la!B4~ zxO`PwBKu0(EMgm)Bv>(}(T6^EUjY|pkF<c^krYm~^;DM?>+ zQ?y(6{TygZFACa<*{j>ydaV)xxKl$C zi}82Q#ndIxcX_F|=s}GwbiZZrdV6D%s>BrLUPbZ(?n0t2RsJ)~OtlL*y+8292~9t{ zPH@U6z`e2u%zKb9vN2Duu}qmFl0WF?i#QMwA|gxo>Qqu+OW?T+nbE(i^eRMm0%Y^` z#ga`J%0k44E)~Ci0<1czpIMznwp>o0K8{wD>_3lLHbdVh{*=K(N-+C|@F72n7dXVx zUGmK{dJr>1<(K->Og9w)n^(4gz|qw|JZq+r(;mCtjlGFz!F)L*HKO(Gp*IV4IhQFy z_v4Ip^DE%p^(6EcPsCE`)8~2fJA*OkO<8_Rviev@yP|)&rHC(;0N$^?iu8pcq2!PB zMb2M$g!gCdr#ot(=hQzdbn9@q$jp?}@0!$*wbhGbD+nZ(sJ>1CQW{WGD(RR~L6tKL zg)b8=Ta5oOb9)H2zIVLVG_wvrRQ;6uE9cI6uplScapkk_Z4;}Y+m8p~gx6|WH8yGP zey)ncyLtq@S-6ovEK!vqqg;_kmN`R7Y{-yD{g)s0qijEBvY`ydy(=&zWS{65=dbha z@>C`n0(e9Q0pJw zKT-ZI2A27z^$Vn5Iet7Bv}>S1m@*>I^J5hy@Z`q=0$*{GJC#e6^wF{tJ0L7H;6gV@ zJaI`*KkxbXo*HyGm68spQ><#$aT2ZO%ZW#O|8Obc8#3x05z>9$dQ?z;F}xS$(WkU_ zot4j37BKThpsc&&x;!4)710$8+c7Jh>3?;uXzc&l}KgZ-gX~hdV zER;#q?;hQ{1@{83AXWx~B!Md36Fa%kq1*{>#gxEzLI=ESoj~S0&0e`%Rn$>3s>Iid zS}F&9l6sv(H}~LF1he4tn#+hoSUHCK5097HnaE70SZV z(40LvYAIg3?^3%KLl<&8=#;`03GqIf7fSX>qQ9_%)%=18;1!&IR7^VD(^7XNaFu(x zE%JYEOV_7bJS9OIrlqgnQh0Bul?q#5U!OROCgJ!yS8eLCljXkVxjbT%Y-aHkZ_0Jy zMTzNPaQKrgPJk`Ca9sU@Z?oO)U@nlu|9048J8j(9%?&!~7qHn_q1P01d3iasxD1Lx}lJM@lB~-aM*m-Ac z`N$3qZhL2^+WXpWWNd6D@mvv5iqDyYojWR!bOkSHE`dJ;jCu{YWuwn6z3}m$COnFA zY~iyLI-f08L;28*{bt}4ShXq4;b4vnDKH0v>1|0_1eg8*d;lH-6e1PzcQ(MmvW@=F zpFb!3tIwj%%Q)>feH`SW8KQVj`Xn|sHaABfR(obxHI16ZG?rjKXMZ$PhE2;Rp(_ob zIAiVP)Av&~b`8;$ewQ8nZPzO;kh0mPis+e{_Yaqb&)CYDpacQjGtc=Zj+Ww5dkPqW zWbY%iJeLCJuK6rX3OY&(g%lpDZP7e2J>$iTJ$c;uXB%b6%#7wKgf>KRVx1n^`%{QL z?v7XeUT8GCA2o%o(~G*^aJJucV}d+R){>+7Z?o)JvR{SeIyN1AoXO-5qJ@&Y7!|wJ zBfN%x#O&ErP;9F5-%e)F<&bEdQCbeLX0DNnmyH}B1NMAhLM$BlmM*3(+e(@sR( zwcDMXkEocd&ri570`oB7aP9KxKpj6{^Q6vW4l>i;g zgK^m|%Cs5C*3K&~T0(5sm@3=DyswV>K8NGtV!J5@Q;+X=A78HB`^lhTkHu?Krp3vM zpzd7>dhVAj{*;_ypuB7!dRDrxWy8#rJrU;M`8tgnIYo?_9}*O5j5d~^+rCeT&ZxhX z(pH(6Qkz3HHHu7d_L{#eHKk-MTC{OC=O@3b;!f3pO2?o4uz#_^`^_GQ^|L3M{*SZ& zJVjgt4~HZvN%bsleFzmHi_qBp*@}%vT;+}9r=#POZcL6fvBx3JD*xxFcO+8Ha#MXe z2}T@uNAzeW_b)zn#I5K)TWI7BH~}2inGflQZlv>&w01q3gP$b`N>3d6+{MpI&UYiS zH^axiB=I6wq|_d3@R=gsIDp7iSmxl2oNGfdN!ZsW3!^O?79;Y`y4B>Yg}G*o`=h(6yNNf-%uEhp)qeq3<%xfk=H;J07uoNd3Ve@9|hG#<9QkP!j`@{gm%|48YgrKGHMT2w zz+>Ec`*}V}8(Kyxij#73b1jV}unIIM0j|?}kXBfu`*r!I@Gfl2Q{P393NF0be^pe= zm+N{==y+`+H#qH6U6~wA0ZnD_Jw>5Dt)brFBT=ZZ!lw5ZLN0pgn5_(cmgo=`!uo{k z^mZS!TgHG*4}l#Nce9(KkVr?YN?}ci-u16NH^yAnXH6sR+lPO$9H!$dZ8uCEw;BDyE9IRo1g|-K zYDUnR{%b$4&bq&?_&+1+wfo>_WR#EGIXQ@0-Q>UJu&9dvV#Lt5c(6n%Jl=C{;Dv5X z+FfI7YX_aYtT1Q^`~Ka`feuf$O^<{XZfyV_R14?vPaQu;IN-=t4&Fjnd?1PM-C~&8 zd={lMGS~Ru2?MBIyTJq2J*Mf1kF+RYd1v!*#`c%&Lz-V${{r!TV9fHVW?t`eETsB*d_-P3< ztZ2+yk6n%@LhmC1P7Ph%uBKX=^_$ZMhmHQ&cOv8J&NFJ$PbD}%{6?pRh5AXeeXr17 zQse$?B^fxB9Y^$L4e?<&=jp9-jzIADEi*K_s>Vj7S=YZ5nYPY`;nA0yq4*j^oul)N z)ZP~=!uJQYH??B-&U$TL$SPmP;MF=Ttm_4dNl1WchG@vXln@a)IOw7!kPE)Bi60`2NI~#+Z|I&LM$=w<%Y5#2gI+rMD=M zi;ZFeW#!E0Xt4ozbY9@*>BpCcw5j8b>C(?|0XpU8nV7#cej2;F7W&&F7AqN`!W{9# zeoyO>Q!PUA!L4=N<~2u~z99D}gr^+)M^rX8wmgH%K(68(8jv1Xg(HZ*RCTac!7uBJ zpC7eKuWY+E7q(0(f;KUfsd6J%3U{MvC%fnD45PxJEm6C;r74J2v*L^Ba|*kDH-E=1 z4CMc$w_rya7CG#CLM!_4k1db+;Mm<}CA`Q@V5iY(3;4gLDE<`>s;szhozcS<^Z9X$ zN&CzDDApXhV$N|W*3{)&mWj_H@p&<y<{kPVo|K?H$|+p-B?x>9|s9sk`l27 zMiF=EhlVaztvBm^|K$dI95vB1CU!`SqMKufNPd0EYrXXtn8%@{J#79c13ZaP{NNiJX3c(vLpvU`bL}vC;F{Lx7h3V($Og^BQseYsd`Yv};^$+%l;-pxT;WF=54Uat3#>*A{ zM0dT;#(*+o+#{o*B*sQE_E?f=}HL33(B88pL8{o%OQls z2&7#>ytNb^*;RA-kGRnBdun8Ip4pFY;0qwcS%~^bimdi0?e|AL2^Kkh4-efFUS}Sw zBCZ%&ZWM9*MLV{3c76kg7mo&l9`Si-%XYJCwr2M#F7ISSV3R5&r?e#Rti+!6cI|Xj zwJho+1@=rY4`syo(q@Ta@-!{W)O>s>=L70*N5!zCdUd|Pr3L_%h(lDM>TZ-`&Um&Y z7lS%E6oet~8cW_8$p`cLqQONW9eDC`g&TxB;}D{cUL<*;1cNELEuW zvMuEo$7kc6;|F0?1|@2J{G-|}|L8X|Oly#a&Vr7N>1{{eJP$)>$olFj zP#-<6k5}U@azug(se~q@;)}+$NW)Ho;fx6j+3iSC6jH5gVvq0B9Gdd>bM!QYc(wv} zy~U$WS?I&LP$jV>W6l0qXoK>aS3z-r(@(n4o~4#yKppJ}2mE%&FRxQdh5diK5KYm3 zY#lV)vjMvJ-m9<|pQ8IV>R<3Qm+p6CMlF}Hm`q|)jFWmHVUuR`IjfF23Jk< za%+X}pZ~H7B~q)Y$m?v}HI!rktB2sB^>Ef!e)++^2Es}%+b{;ePOZ-=| z)aqnZkj4bMtA-xJBj+OTa6HqU$#GWBD|DsGw@u885)4*_UtPPNq$SxA9>Z8afLbJ!pQz$zdHHo9 zZ*m39K=8!^RVG-k-lJqfeCGDMOqVMq2pY-^rQHn3;-VcR=6mZjJMEg9k8@JnCmn*P zrLTk`Ilb=+szzK?keo#6Q!9`n)1=nh&W#daN1d<<1Wk^G3e) zn9&o{6VwQ@o9(FTe-sf-nkvFj>+%$v<_w!XH(JDsm3fWt@1Pp4#4(d2OXvucj1vo% zxxgcI8k~T%=1)bPa!}lSJmY^G3-57jYn|t6EjY|AGMY?2U(H{8lg%oGRhzR$nOA-! zbZo3Bp`_N{t|D6g#Zs1@u~Ua#sd;p_8YSF7ZxIjR!HqmGF?=yKFB35-pKmO_P1NWu z>v5%+=I_u9a`Ly*+&A%|0dj`?4LsJ$=(S|q>F-D0>m6ukc6l*%Zf&uryM|GnyM`o) zFJk@;cXU%-&y;vm3)yf%U{N8&*$NSeLtMQ!)8T?_qn7WpR@gzS`epJ%8%rp+{_Z$Q|RI}9@A=XT3!^w&1id3R*gGy!-J@H>lSD6Z7 z=T7fPO-0hj)z`nT)1e4JoA@HS)ErA*3pdTZKgOpwGM(67VSA%x=kEBppnkAYOM;1c z9?G7Z$)vo(8z9O6;nMswM3xx6L1K)W7HlcdgOj=2qIl>(@9ty}_|>Y( z&eJ%-6D)6e1k|{GFK!Hx)<$Fa`gq!|zLkHzO*{D;Im4%pEg3)DiJ1qxxLn1#+PONA ziCU|-3)O97MdTcGwW9v(mw(Lt)yUt-a5v-pnXZ``YQ6=} z`EFAKM2P3=GZjA>V<|mVmsL|-Pw?k#9G#z_n6j#96C2AXL0W;2Qo(;1w5=@lG3SH$ zR7=44$KiuGnK)_ZNLbNaN&AeL-~a6o?ImT(RwcNms#WvFI#*yWTm69MM>|}a$5v08 zJ}1z<#n@n}gumri*u0m*fVz1Tycg>JMPUr(LWFCqUXl7aB}It6;6O=%SVb=AxEnn=tYJB1LA6i@Oh%dBS5M6B7@1FLQDqo5Ps=?pXV+kdH z{I*;>h2@C19TEF=lvZkMaI3>mXXa$VroC9#|)IyYuIBS3-yX^(llQ&HM+4UMeCC((UT)`=+WA^=p?~QE74RiLbx2(f>k0H|B>$&?*7Rsvz zkBeLp(A|UalKUtm73Q>Lo7tfdcr)#P(={({F{79PL1gDh9p;U-A6A!a!J~|^wRnI`ouTn zk^9DaOK$gsh^iRRQRmVHuRX3hn;FCKGX7@Z{7C-hyX1W5o4P}WXReKKjDg&! z^x6LWf|IDDA;$f!==Vg!HPx+neRRzKbKAHnu3pRraSk3P&T z*>2hKqqVR-`Kk51K1W($MqnGKq6lxL2muQ~Hlg^vhoLW}DA%5bT^g0M@NllIr+W`>Ov~*@b8}6fP;vMF z-B99~R^1~j1pLPMfyHt^NRLWcTK&geZu<7uP)W1B>8`)onhr4XiLAGk2s5ccrUyVa zGIFbHDuNaGxxK;@mUI()FSj&I9zHccJ4h>} zn=r-|qpn`9>TJt4`lrhN7{Tpu6&udd)fR4W`Sdatj@o@fN4IZi#!Rophk&0Sp{{w* z(}vGtO;7}`Q?CaZuSmcS3Sr8VL7S#ZXclL&B2sKCky{nu#Qr8*9${rd*u|%oX^I)5 zbEc;(^0iL0a`tm|KjGj0R31FXbn&DaeAGO4p+PA7w&EixCrEbk(V4Q?aFd~l9seuw zKeYTn0^Zcuc8yVmRwkb3wAPaVh5*cDX;@nNAzr*N*IqJq>06*n8{wlRE81Rn707(eK1M z%LO#Xq`8Zj_>OTh%YAx1-~m(^lhnXNiAQJVNa6R8KaT7_rS=E}e-gciar{wbm^q)*?ZJFOG5)+$&kHaOBhmgSD%zt+d# zUA>+fkFymcc2vDUkQdF}2bDT}?pr)L{lH}Ba&4n`kg59IbiwMp&E+r`wi+&h7vvnL z%_PlHHDQg4(#02}Crf0XamYSqxY9Y^cH_Bp&4*_sdhT1K>H5un*mh=QQ%C#p_U;we z)`gVt2CuX>n8+Gzm*K@@W^4>^csH5iaJfg+`gpZiI7L^YD42WIs5tC6?7SFd$MRB{ zEWR}VbMzN9zgcD)&-{d$`o7s0;QmSqjM0%45p$Vz{OY*oQXrRfYo~gG{?g!VG=z+V3i*t6~{WKC{|`YkbP7GOzBXmK>;%PT$6qP{tnD&{(6dR?3=}9 zjv#Yy)y+fIL0zuS{YpE=8H=8{*0n9w7NP=%Vt$u|Dg^I7Z47A7 zxmHW(;xBKq!|6KM^cf{S*oHQ=qxDbbIWLE5vt2$0-~5#Wjh%j1s$+<*w)fsfV^G;I zDyK!DYkpxp6e*_3@obeWM>)tDd3?fP2wwDRi!*%aGwjWk3U_Llxd(7KyOq{Rd*A(! zzzKyzebPl;F*Y0RBF;CVuW{FYKKH5kT-}a$>D&;m|7n2>SiSdMTgI(i`+J{qQYw3u zyL`01=Y(q9`}^=}V$W$w@7M$~CCiWqU$j5xpdIrGor9HPqO<~wHnf{on)^sdRJ|m< z<;z}hyKi=FQL^qhG&jsOxy9;^TffSzoAVyww;6E&sk+%u(ce(Yx#6h9JwLVF0zuoN zPfgQp1e7?=c)40X{v9bAoKowLV23+vjJr-r*}{xJk%r>xPXUA6(NPUA0|FJ+9dTAs z8r5IBK}r@@bWQMe7PG=y?(hNgx#Vg`-~JXOHei!B+El?a&hAFrz7NrL7dY1&uR&0p zoS|A_=R1-TE8->@V_1T##Up;Tf9j^shSiyht?dY=2B)Ph2H-S#kha7n-q{ zBYP*}Bl)p^W_w*5D{qv`AExc40jTSfwS*R%TR05bo0o;I6eUtv_p&r`Q-#3|xX zqL>>j**jNT8z*u;e?42cPvz2E)nbd0Kqwg?fF-=X`^*#9*)GE4kRh}tJt(YifVa`D zgzHC2F)rn%twD+{`Q*X{3;XjsVM_KJmvSJ0ng6zi7(pOy&;CvoWX?uBVK@y{ysy_d zF_(U<7HIJZKv=HDF7V(wqmPl-uzlVC&B`beCF=6v$Ki&VTL(AKE9Yfkup_i`_ny_6<9ur`8806*onPF z5{1p>NZv@$6yKfA#(@~_Tl%vjc5ed`|N9295w;EC{=YpR*Hip&H79KO9FLX+9u6!j z^A`^boN?jhpVIIA-`w@d^`k4*KrmHoyUwNbbdT1yOf`R>3%If2gmhkR@geQ}^Pu~q zYoIfk6D}IW-0#ICK8}lzG_O)>iue~TEO&;4%&DEvh&E9%*TG8Ja7_F&n4>+BX^!pi znY-Hj6?$wxR{Pa{PTy3HH|M;p1=aI*hFI6|F}Xn{*GnK8H6G*usg~D1m#pDaL%9}WjRDW+x?;g3 zyqzlh4eELk^sX*HoHunuO&k_kb^i~FY+~>;g z7u1B899yr&jjGMS-cm4Zl9E@nu`569S6Oa${$?^!lWoq^#njEt^Fv4Z(w|rg{?k}{ zpZrPbB}N&?CB^-na-N|(K`=hef9mrW4w0gq_V@BUhXE@g8_&ZnB_Fmy%-!36`Ob|V zr}V(gEQ-X?2S09Oy;$t=?ZVKKMRSh^N^M%TS3wlptr&yeBsNl>oKf51#z81i2px1A2Z-HQ`K5eC|?kkKJ!xx#n4MnY%XC z2=gTweU9%TL`h4@XGE>?zCP}(%@IhYob6X)ydq@SyFgN+D#8n>y&)*&lg+R z$q4mVpGebUhSR{=+2ZEC%k0x~qrZjIs3viGKOcb#hz;vkDq@w>dko>7bU2QMmCu*o^lv~Hc76&lpXuVpn(bCmDv>%V@ zR?>+3=4oJcU$d9PcbzQQ_~*lu1FXHKp9T1!Xq(2S?#?B_y^2ufN`JrC zfwWQZ4DtIAnq`9s1KJ5p7Pv?FHio%1OeF(tYj8O%!kX zIf?m>lTS}Tm1gPOxv_@@%c8u`}Bk&cunVpiu9338R93M{kpGif;yhoJ= z6f%Gz;`ggkRmP>Es3f>P6D#uEtD;i4mr2xr5E{~ivh@){oVRIVQ|3dlQ}@~-f`NRT zsh=TMR`?%9Z;`V7pF9tMIdAsP-<#8oM!!cv(Z}778@D?haI>x_L#$%`3k%kE9$$>N zfy(3k2a5FE&23dV_x(u^^>{#+3#bH|5&~98 z(E2&(blfU-odo$cV!3!V5z@Qc^sO7`Hn@%D`|HcM=x|s~i7aVl3F$2wYM**HiI*Fj z!y3joi~`GZr}hd65@c171cbb{TQ?iA?oM;WT7r<1>s+@cm5}JdNzk+^$jzBiSGAdj zfn;nnWdXYH3Y|7?al19A=WGi9G;*<6$L(xax~@y4mkjBOgNz8kdmU;NE&m+W_mHSw zd|&3lis7wxDqN}hUeoo=>axvb%((6^2ur26dVZxBm<(SXkTrgY5twUoCP}tm5$7b> zh(slZhx)EfznN*_bmS z%`WqKwsx-F+hjIPD(?83nIRXCXO5MJ*mOIV2|)meLHBQ`(yOk7>wD=JUZMfeq)CHi z(1UqHzo#nPeq;@QSDEF;l<_T3IlG)4F|oA>s2=|A_#N$>TugmLgk#rh3;+h+h_LvM z*wIlwc7xW4mr!ST(@nD0%x>U$OSIJJX*yu`Q}EV}Ize5E0b?xItOqkm!pgZH+(1&~ zKT5{`jvImY^Ipe(XoN=$t%4rktmEXwAm=NzK8G|f*Qy+0;vEI9{%?DsWv{Eu?M5WPpFxOkL!tk$ z=zrZdBB-h9ebP!ASJkD34XDJ7SlWO6(6(C<#+Hc%%Wfy5S#5K zz&+~Kd>-cb+mz!^e(Xz_J7fL#VE(+(#p=_ZSQH2#4hoNdh_8(D#{PE;2|lJ^ZG%@6 zmCbnS$aF%2ql77eAuD=bx?F+HUlyj|6;;3WZdN5M%HTE707Pk(Aof2)nS4#kzc+X# zHT$iYDksTJaYUbQ^F5w!cdDItl_j&$Vgi^5jVYb|aXF*IptKK^nJ#h1v0RyJ6x%qdAM9*Lakc5sEph1dR+u9FD{6 z%Me}x5rf>@!tGi@BhD}Gz?rYz5?%FYLx15j2YFa$TODsfAFq zxHHk!kZ1^c_;dt+6l*5Qx=(R{G$nr-iKSweEgz! zb5NZFMV)U*oX_oFUo?mdXfQ!4TZ`3sLDBs~vG$wEZxsCKnXuFx`*r7>drE-9>Ueiy z)%tX|?{U3+jfXUUMFs0>a^5*@JAQlv2h28TV5b`}XK+TVRJo9Sa8p`ML9ib+?c{kJ zA^dC94hVqLOmT(QBG+qifr|djATC_wn$=GbN)sD5QM)?+> zd6oe`2nq?-?wOS|{1azAXL&F6h#kZ{7`Pwa-(L-9%7*>-^EmR49YyS%dzK(2aL17+ zUGuB@2<0M$qQo8Z#TqzSw93UkjO1#IaRWfn%>^$Uwl)LU?F^2c8!`@!DRbyR1Xx2IC{*+O)nQpE5y{+9!FVMGh2aTS4{c~9WK-$3Jrdb8fY(wqM z;%CpXjAA9RaK_?M=sSSl*m^d^dUG-oF124`qSQ{pgm0f823FpK!cR3x$o&`jlE(2g z`88n0^9WLwD%rg+A6l}d>Z~#?z?IHp2B?dg4(q-0t>;&ZjZMGCX3fo{Q#L@2F1y@M z>tavH*&{^J6Z=6Ok>a3NCBfG#Kjh2)M zJ~)X16=!XhxkUL8s*y&%bZinFQy^JZkOW0bSf&j%CK*^@cEsSbTbuReFOcjCsuS7X zI+t1Xad=>zpyBY4xPB!78o1ooeLoaNvEimwe-9iKOfn)O#=qml3dz6|j|B%Tj~}m7 zdytYw_jkUExHFjuf|J5Vke6co%a~Tma*NgBm!I){X;cyd+<998?cju?`t# zY%1>*z-XNp5hznx9XX=_j2_F)Y*E$}O$ zM<#4nR8d)XGV(!>#<&SC?}^)H!0dC5y$gtP+tjgQ1^0Vh_53M*2qk_z{wZ1<1RjbU z{^tCnz!)uC&CF3Q$s0&4>x5ca$gnoF(1zx9QDBFFtTk^}a`M0M)<(WgYhb-%&yeHo ziXQRnQTF|h54MZ)UBt4UqcvG0lrGi!s1x#wNe~$XqaZ|wHO}QwrIjS{GtqLcE$jhQ zel!=lR7y?%_jE>>D8tGjKNgC5O$K-Bj~LpH&jh^!2QJjR5B@3?TmO#PY*o~(!oK=` zVgId_&(n9hs?&Bw{}nwt7K)&c zd6z~~xp+vAh7e->6+bL{R_bScpvKS8Kcq9nZx92;n3V~_;6d>i`h4=gcM{LhVg$7G zmI48SGJs9Y%n-QaQV<^s*2@LjZ_e!~k@IK7`(KiKjrdTepRs zKD`y}z|2ZPotA{igj&E_4u`*^m6|2t+#kBn8Gyz4dM0BZ>+Gp|J zLI>=RyI-Q5p)(Nd90yYFCg<0oKj$1myZUet!HbF#<-FjEhRI_cC-Qjds`-y1|CLn4ls10?zHV-Qt}7%7>xKwQ3kO zm=Nr7Ig_*Iy?W33LKRImGj(*t@xDIlD;B+cODW=o6dnEHW_k5dpN(Uc(z;SnIvG9F zN+T(gw_y|*aqSiehzO2yt7{SmYa2?M#>@uldQt z`MBw9MHU>2`zjSof)Ko$-|I-p*$?>m)Z{ZGim_H0ydql|%2rdbvf0;PBu-x!f7vmf zSB}14Qfq9&L0mK6roen1I2spk$013mD@B)3Buq<`OuWKLk{1ywhiv$z6_W!a3;I{S zTFJz<(d3KzS((P4eb>ggV9uz!@0Tc4YRe4uV$H*h33<~sRJ`WoXjJ@D<~pVEeZg*9 zNb8=)F}^A9qHId|x4B^NZX_ngIb!e^HTDn`*dlljxDP2lRz&vc-6UkOo8kamNCe^W zP$HxVQ}~QhSJr#TcII_ix6(M-NQPi;gfPCzd~iFL)Zf@H=RX|X_`$OHArL7vu_oY)v~zf<3`BpF_4Pyw7)g|8fD(!uVz1NlY1bS*;pr`g(C#&y_*p*d?f6OTwE_#|v zemvQ3V>}Moc{4S;@9J|^o6{AHD;fbT;wTEm${;#BI|FM7C#`{|HC0t`z$fobzx`ES zP9CalJlSqme9K%U`KBj!@YQlM*Yk)gj) z?I?KpT-4tjY$g@dR+?@|(@lkneQ#w7*?3j;VVgCjLGK(J61(ZDCp!d9@iHmmSEt?P zr;(MPc@nV}P-kNxSN1oaz19yR2KLPoRoMt2Voi&a@;FY0|I^7qH|duYyph z5Ejx;eS`5vvGTG@f#oKL3U28t)feCcIMH~dzuy`{@ zr@>PR^ks{OjFRQcVKhj9$^uuVNWn&Y!J~5%N+cif9RsjENv;1`c|AC#!?6ysehZb0 zLefpE0+xQBZ)p69fDm`n&;Nw2oGly)q`rqM`)8ikoAqdqgKC(=S|>c5c*}CXu6@V5tWqKL$QCJ-#rlfLT@}2#nJXigD z<(6!IG`e8|l}WHJu%Hz0cfnm@*s-u`7-Es_i83yHj7(cy?YO^^r4x&LvZJQ9c4%Rv))I0VW5VOmVj(~Hsh~fycM$q` z70OYA(Ryf?H3`8|#*ueEHsI6{ofTSD8ZDA7aO`?b8j|ipTvnF%NRXVuH4jR7Uxdfg zN9pw%0p>(@sM%|oZ%`%`DHb#8Ofy|hbuX;Or0sg-C6(?IEqb)?;~~Np)~grR$*r#2X{4zEL!veTCDTW}^5k}wCl<5HV9zuV!08KIpd+OJA`01hW>Gr%<_ExLug5^#I~jpbqR zgpO{1Vw_voGP1Jbr}lqv1j=fPo5hYtI^jyx)$7ycw;YO2$NG%l1x=Hm8KX@7|)y*%Qz!5!0HU>>tg^kcp6D}th^1P$k$!`FBd>LLm_*Z z?`=NF7R*at??;!|dP18$CPEZOr<@}iTWc{6ENdY7;oe^z_9T52jr^%u32XwmPaM`& z*O{Vb0}BEN^R-Ow9ZBE%soBRxgvAeUMMkDAxal+kRE_b2&vwchhcl*AWbu7gKcc4W zI>z83yje_HEFp0INvBgN0P%HENoV81#k!mTQ?bALOWbpCGq0f<6H;A}Xv&6?8yFn) z1|0#1jiS`(LthRT$+$!!omMb%ASoYd@7jBti5%hZcbpM0hSr*#B&GrosjdC1QZx2! zAYMzu>B%wKgTj@ra$~shi;{>VtIL<@8Ip)c&=G=DRaZ3iu%t8hK|sf|zrSzEXTinK zpJK%thpbZ$WG0Har6uX{^Dt4Vy>><-NLeErfxH(NF%{jqi=QB{<^_cSl?I5|vLUHy zb1YjVdiDA7nT*Ewg07nr$rOju;)b*zUA_IgUB+9Ea+d$`jwx10Fy11izDrtf+HUob z+tkzVNn{&02|u=)Jj=|ogrdV4_!`J!gfVWU&|*z^ug1F18#~h4`@E5gu9_^D+cl4HHxmMCPdVmW17&D*->w%<^t_}j`PCZNd^Ne!$fX>ze@(eJ_Rz|W1@Gh3 zlOfUhh?U~a@76gZ>r$)RMQxIBmAReg4>%5I;DBq|+vA2)IHV#->vh`HGPeZmrkd0E ztx`8Ykj+P8JG0;Kf@s5lJ@T901QHy9vZ-WE9M4x5zPpDc5KXf*X%a2#1bnh1v~S@g z--$#LAXS;YOy(ttFrwlz45un99+X)}jA-(KAmq|ueDIpELJytm7j`2;uoZh8<(z`r zwX&dJGQ@&Wg73S*_!|q!UHPvBhA>iMi{NFQ2ymvT!Vb1vX2X-MgA`;x=pzPHQHVU5 zkxkKrWt+}?56kaMF|t(H6(DLb)^8H4vKw`M;kQTA4I;JcbY01BC8tR2@C&9uC8__1 zs<&XPtLcITad&ru69NQxcemi~?i$?P-95P5L4zHFCs=~J1PJa9ck_O8=b8BlySw+2 zT2-~iP|v1pVmNi!gn7%KQ{HR~swJX$ywqGhNU`wiJbC&QwJ-3&H0!Vn44-DU;$RIR~^Go+_q59&St@bB~K zJBOJ-Y}}>l=X{Vsj;Rb(9U3S_5XC6k_m2Kzg<-GY(pdYtDTr=hJbo^-0%|E+YfF;N zw?SpOnug7dVQ5uIoQPXcGOD*(cU*v_hna!oIF`KyYNIj^WPcG@-3hYBRF z=+#UNQ<=u>q(R00vE99<02=X|sSZIiY^_K}q;QVt7FW8;Z;z#$hemRFIDePgorD2x z5c?6GQf{H|j+uHbhrZ_#^7pK1r}4@Ojq8|nkb}kL3N`R%oCD|Lsu#yMkTeAFaMvi` zDK==X%Te70)fyiZy-;KGK7Vn&{dVv}de~zrCMnfyVjp}WIS#V|cBm1PCx@s^^@I-P z-<5oDh{m?^{7l_!YEJ0dSaq9&s!=q7UkXTD>;3Eg4!Wc;#9D-|myqO8Uh2aL7S`1w zM1SN^+lZ8%9$m2L^VrIeUO)P0{;T|j8j69ATFqq%VwcZhG6r%bBF{WH*y0klE)F}T zmXkmmy_+qRMC_9T9j+tLs#XZ2iiAZa7Jxa>E(J4p%P!pslg?UkzY9xM8RqzDn#=kF zwfr!12`huojZE9_o3YO8H9={>D;^%+`9WzSMGR$_NtAdbS;!7gR&FkMCs7!(!Kg!W z_UPt)MDA?JsHv!=*X;KkLY>NTdX_e3^QABqzaon(pBG-;9mB8+h(Fdz`Ef2=(D&%533YpTA}D{s8Z#APaE|} zs3Od+@4R?>fBMu~$uKzVQVYyD-{o$*smkRO|8Ds77k&(c!e4xT+Y1zK{rMvn|H8NL zPT17Lg9dk;Hd4uBxjKT+(LxmK#jA$l-&x)(u?#MdFXsVXK*tflysbLQ8OnJDbHtA) zV5OetW?;ZXq#h}v<@UrD)(X=XxtuI>`T>e>U}W%5h2QqgJhyznBV8_KM?Ke^i@5VV zxXXcTtUnW#*3XjBgWFvcDhqxkHG)6qmL1L8+ukS3w7}Ro85l!G@tfHt9-*gE2+rg3>I zs6O+>Ed$Q~-+nh?9+zygTU}`&-X+YcrrNEcT0UsVfh(NluaTBpE}qYKGJxfpu-5H` zt`VMgC6iMvSzlLYwM@v}N=)$C$wA+RW6TNZUG?eA9jw332U zm+QKmYJ`*9Y?wJGOgHm(2E&no1UmDDcG{C90$qp)D8zZ7Azm8C%rDoj_NUB%0ccCW z`tF)*=VAz?alyS>ECUWJj$8&>NMy|gYFTc^of2)M8BD^%0Wu+G%4hsaNd}s+UXA-dU$#@+I_;cpkE}aA+Go z$c?sbGh!ofr_!gUb=uno{t*}#*cwJ!9a4>1W68bAr{;gC2Ye>tr9L?EA_gpMULayWMk#w{PS|jk1nq;+&_bqVIkbw_?D%u&Yvo zZ3bYPPYP^I6+dy1S~PYQ15N-c*!Aok1d1z*dDJ&DtRGq7hEpT*pZ(E64&XcAL%S~R znv^-(8Tf+i?uBu?(6OLc*i9LVL>gGqZ^%{M_>!TH^{BPsK`zx{bt3u1le5)QG1@2^ z?s@r57t^oalT)0t77NTq!#_Af2@bRj7_o~5K+aS8VWIG6BYuLsfw@B9wuwxaDh+bx z%|Woj1tzJ-LqfRDYT%T8`I_54vq@(uk3>`YCtU?elPuhwF<*ztlO8$)(9-Ss%!A#* zrBA){+{#Q9!~6*D4Y-gvV>gr)j{h^f8;X`MP@DUDo(*Q-v`t=?Pzq{f&!eJhRK{Z| zb#^ZO6Xp&Su66*JMoUYyMDer&4Vl?*uIeLo^bHQ5#HmMK;#pt*CIhA$?PypILk806 z&m3R2Fy|i2LFFf{@xETJ%iHxUq-n>RKn9PzVE{mCdSC!--l?i67|eC*39ebFCthoH7itX%Z|g}C(s6NB>6|`AXNOAwRdqM472G;q|zGti?3JWp>bfCIuF6`!(MUf~TI5BmM~BYBtI(sX{ROI2%M{ zFG;-#Ksa3+&8^8k^wsKCojU2q3_eV1P)070;-s34U&UNO4<6$z#cd71lMmtdp2GsP zigLHsv4B5EoB+f|f#BzyygFGGBa|Kz4@42}ZNj?m; zFTqm*w=F!*n-BmMPMX}`d^B?M&2Jwudqq{!RaZ%G-H8bipe+&sb4M@OuKOk13I|slO)=Uaz}Py;Ye^~Az-Y~0|CJk@cebF*P_aq(}-I6Yc`yr zPxcwxZhwnHWz|XUWAW)1rrDH8q70h$OkM}qX@fNO)LMEK4*&A1)xa5J&MFdKKJL)n zM~UFb{_0>}*TKE*fk0Y&wcdTcBZ$8c5Z@CPoZ68q=EHEWINBY4k4H=TC#iezGOa+> zOi`ln`jDb$2B~+9dD>fwSGr*gr{Ys5s|#9wN21#=X(Wj5ia%W53q)fApf%*!*u}m; z;Q~Oe?NboBr<>4}!FM7*Z7aL|>G|2F1ZXM{1D^j3~krYh0! zm}6gI*kA%k`jFZx3Weg{ThIPrXl-5H!7};G^HTEfabD{I#AkUt!8bQ;Rl6;+<6@K* zhsN<&#Q#;G?~`0FSdD5O#TA=eoR`QGO&)u1UWaNPc11`C>dsG3w`-yMg>O&=KL0+} zHZ<&{YZ(pzdJ7~2(16f3hr2v_A|sJ|#?K9|MI+CWmF9=)Ad`U%J+3~}uipyT)34=! zIS_`JNAU~L75qclzRlXqlFEG>%52Bc;5gqLj+{&x{(r5Y7W&wEQ z`JEwuZkW5)2te#+?l^xAQ7^S^kbAth;WF}=l^}U8X5f}{bE5`%sC+I5DQ=)>G$aku zJ-(eM6;3_7zJ}gaR}sjPU9#_VF$4X7cqF+u&fS_9`F{dmupL0h;mZfPyfY7hCu<6X zToVFQH#cmcKV4j0Bye5V?sHBo%b(~m8$GJ=Aul_&6iYU4VI&5yuI%X%;7ZIkdi@VP zyMaOkuJ`TbYzN?HWnSc;`N3~I&KDM~oP@Ay>exF;4?nz&KA}JVDVL_wjE?0J-N!um4kHXJ_=@9`5r);TtdDj}v^i?n@rWD)9Dvb>Jz8 zKtYQ~(@xn?XHUMf+m?OV^~e7`LFyp`F+8Dyu|7b(LeVjGzg02j5MF7+3Uki&F-VmD z+YSqf&@&Fu{lp)w`JR3Mx|=NB2sFu=fT;$ZQl3crQ7|j-;pw@)mL&8?1HT^^#^>W{ z(#6qb~_Ieg^d@2cMCMXuQYAFJT1r~A(H453-tPBRiQr&+@`8H%lQz2B-I*
  • p`|u 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 z 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 z

      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%0AJe|Gfm;{x`U%%z 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

      © Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

      * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ @@ -122,21 +103,21 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA15 (JTDI) ------> USART2_RX + PA15 (JTDI) ------> USART2_RX */ GPIO_InitStruct.Pin = VCP_TX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(VCP_TX_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = VCP_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; GPIO_InitStruct.Alternate = GPIO_AF3_USART2; HAL_GPIO_Init(VCP_RX_GPIO_Port, &GPIO_InitStruct); @@ -158,10 +139,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA15 (JTDI) ------> USART2_RX + PA15 (JTDI) ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, VCP_TX_Pin|VCP_RX_Pin); diff --git a/bsp/stm32/stm32l433-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32l433-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index 6dce14b8ae..c6ebbe94cb 100644 --- a/bsp/stm32/stm32l433-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32l433-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -57,7 +57,12 @@ NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false PA1.Mode=Full_Duplex_Master PA1.Signal=SPI1_SCK -PA10.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA11.Mode=Full_Duplex_Master @@ -75,9 +80,12 @@ PA14\ (JTCK-SWCLK).Locked=true PA14\ (JTCK-SWCLK).Mode=Serial_Wire PA14\ (JTCK-SWCLK).Signal=SYS_JTCK-SWCLK PA2.Locked=true +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX -PA3.Locked=true +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX PA4.GPIOParameters=GPIO_Label @@ -100,9 +108,6 @@ PA7.GPIOParameters=GPIO_Label PA7.GPIO_Label=SMPS_SW [TS3A44159PWR_IN1_2] PA7.Locked=true PA7.Signal=GPIO_Output -PA9.Locked=true -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PB13.GPIOParameters=GPIO_Label PB13.GPIO_Label=LD4 [green Led] PB13.Locked=true diff --git a/bsp/stm32/stm32l433-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l433-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index 1ce37c7e25..140de137cc 100644 --- a/bsp/stm32/stm32l433-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l433-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -181,12 +181,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA1 ------> SPI1_SCK PA11 ------> SPI1_MISO - PA12 ------> SPI1_MOSI + PA12 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -217,11 +217,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA1 ------> SPI1_SCK PA11 ------> SPI1_MISO - PA12 ------> SPI1_MOSI + PA12 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12); @@ -292,15 +292,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -316,15 +316,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -351,10 +351,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -369,10 +369,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); diff --git a/bsp/stm32/stm32l452-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32l452-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index 0d6a6e0fcf..5ecfc94d87 100644 --- a/bsp/stm32/stm32l452-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32l452-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -46,6 +46,12 @@ NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false PA1.Mode=Full_Duplex_Master PA1.Signal=SPI1_SCK +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13\ (JTMS/SWDIO).GPIOParameters=GPIO_Label @@ -61,7 +67,7 @@ PA14\ (JTCK/SWCLK).Signal=SYS_JTCK-SWCLK PA2.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode PA2.GPIO_Label=USART_TX PA2.GPIO_Mode=GPIO_MODE_AF_PP -PA2.GPIO_PuPd=GPIO_NOPULL +PA2.GPIO_PuPd=GPIO_PULLUP PA2.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH PA2.Locked=true PA2.Mode=Asynchronous @@ -69,7 +75,7 @@ PA2.Signal=USART2_TX PA3.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode PA3.GPIO_Label=USART_RX PA3.GPIO_Mode=GPIO_MODE_AF_PP -PA3.GPIO_PuPd=GPIO_NOPULL +PA3.GPIO_PuPd=GPIO_PULLUP PA3.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH PA3.Locked=true PA3.Mode=Asynchronous @@ -85,8 +91,6 @@ PA6.Mode=Full_Duplex_Master PA6.Signal=SPI1_MISO PA7.Mode=Full_Duplex_Master PA7.Signal=SPI1_MOSI -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PB3\ (JTDO/TRACESWO).GPIOParameters=GPIO_Label PB3\ (JTDO/TRACESWO).GPIO_Label=SWO PB3\ (JTDO/TRACESWO).Locked=true diff --git a/bsp/stm32/stm32l452-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l452-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index 1d5d64d3b5..101aa6b6b1 100644 --- a/bsp/stm32/stm32l452-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l452-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -93,12 +93,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA1 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -129,11 +129,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA1 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_6|GPIO_PIN_7); @@ -160,15 +160,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -184,15 +184,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = USART_TX_Pin|USART_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -219,10 +219,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -237,10 +237,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, USART_TX_Pin|USART_RX_Pin); diff --git a/bsp/stm32/stm32l475-atk-pandora/.config b/bsp/stm32/stm32l475-atk-pandora/.config index 3420b2d793..e7dac17128 100644 --- a/bsp/stm32/stm32l475-atk-pandora/.config +++ b/bsp/stm32/stm32l475-atk-pandora/.config @@ -567,8 +567,11 @@ CONFIG_RT_USING_PIN=y # CONFIG_PKG_USING_FASTFS is not set # CONFIG_PKG_USING_RIL is not set # CONFIG_PKG_USING_WATCH_DCM_SVC is not set +# CONFIG_PKG_USING_WATCH_APP_FWK is not set # CONFIG_PKG_USING_GUI_TEST is not set # CONFIG_PKG_USING_PMEM is not set +# CONFIG_PKG_USING_LWRDP is not set +# CONFIG_PKG_USING_MASAN is not set CONFIG_SOC_FAMILY_STM32=y CONFIG_SOC_SERIES_STM32L4=y diff --git a/bsp/stm32/stm32l475-atk-pandora/board/CubeMX_Config/STM32L475VE.ioc b/bsp/stm32/stm32l475-atk-pandora/board/CubeMX_Config/STM32L475VE.ioc index 3a59471b8a..e7711fa510 100644 --- a/bsp/stm32/stm32l475-atk-pandora/board/CubeMX_Config/STM32L475VE.ioc +++ b/bsp/stm32/stm32l475-atk-pandora/board/CubeMX_Config/STM32L475VE.ioc @@ -95,8 +95,8 @@ Mcu.PinsNb=56 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32L475VETx -MxCube.Version=6.0.1 -MxDb.Version=DB.6.0.0 +MxCube.Version=6.2.1 +MxDb.Version=DB.6.0.21 NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.ForceEnableDMAVector=true @@ -109,6 +109,8 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA11.Mode=Device_Only @@ -119,8 +121,12 @@ PA13\ (JTMS-SWDIO).Mode=Serial_Wire PA13\ (JTMS-SWDIO).Signal=SYS_JTMS-SWDIO PA14\ (JTCK-SWCLK).Mode=Serial_Wire PA14\ (JTCK-SWCLK).Signal=SYS_JTCK-SWCLK +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX PA4.Signal=COMP_DAC11_group @@ -130,6 +136,8 @@ PA6.Mode=Full_Duplex_Master PA6.Signal=SPI1_MISO PA7.Mode=Full_Duplex_Master PA7.Signal=SPI1_MOSI +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP PA9.Mode=Asynchronous PA9.Signal=USART1_TX PB10.Signal=S_TIM2_CH3 @@ -211,7 +219,7 @@ ProjectManager.CustomerFirmwarePackage= ProjectManager.DefaultFWLocation=true ProjectManager.DeletePrevious=true ProjectManager.DeviceId=STM32L475VETx -ProjectManager.FirmwarePackage=STM32Cube FW_L4 V1.16.0 +ProjectManager.FirmwarePackage=STM32Cube FW_L4 V1.17.0 ProjectManager.FreePins=false ProjectManager.HalAssertFull=false ProjectManager.HeapSize=0x200 diff --git a/bsp/stm32/stm32l475-atk-pandora/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l475-atk-pandora/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index a3f28f6117..77fb0eecc6 100644 --- a/bsp/stm32/stm32l475-atk-pandora/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l475-atk-pandora/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -869,7 +869,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -893,7 +893,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); diff --git a/bsp/stm32/stm32l475-atk-pandora/project.uvprojx b/bsp/stm32/stm32l475-atk-pandora/project.uvprojx index a41acfebf1..cdeaf7aa9f 100644 --- a/bsp/stm32/stm32l475-atk-pandora/project.uvprojx +++ b/bsp/stm32/stm32l475-atk-pandora/project.uvprojx @@ -336,9 +336,9 @@ 0 - USE_HAL_DRIVER, __RTTHREAD__, STM32L475xx + USE_HAL_DRIVER, __RTTHREAD__, STM32L475xx, __CLK_TCK=RT_TICK_PER_SECOND - .;applications;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\CubeMX_Config\Inc;board\ports;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Inc;..\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Include;..\libraries\STM32L4xx_HAL\CMSIS\Include;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel + .;applications;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\CubeMX_Config\Inc;board\ports;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\none-gcc;..\libraries\STM32L4xx_HAL\STM32L4xx_HAL_Driver\Inc;..\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Include;..\libraries\STM32L4xx_HAL\CMSIS\Include;..\..\..\examples\utest\testcases\kernel @@ -387,20 +387,15 @@ 1 applications\main.c - - uart_rxblocking_txblocking.c - 1 - .\applications\uart_rxblocking_txblocking.c - CPU - backtrace.c + div0.c 1 - ..\..\..\libcpu\arm\common\backtrace.c + ..\..\..\libcpu\arm\common\div0.c showmem.c @@ -408,20 +403,20 @@ ..\..\..\libcpu\arm\common\showmem.c - div0.c + backtrace.c 1 - ..\..\..\libcpu\arm\common\div0.c - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + ..\..\..\libcpu\arm\common\backtrace.c cpuport.c 1 ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + @@ -438,14 +433,9 @@ ..\..\..\components\drivers\serial\serial_v2.c - ringblk_buf.c + dataqueue.c 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c + ..\..\..\components\drivers\src\dataqueue.c workqueue.c @@ -457,6 +447,11 @@ 1 ..\..\..\components\drivers\src\ringbuffer.c + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + pipe.c 1 @@ -468,9 +463,9 @@ ..\..\..\components\drivers\src\completion.c - dataqueue.c + waitqueue.c 1 - ..\..\..\components\drivers\src\dataqueue.c + ..\..\..\components\drivers\src\waitqueue.c @@ -517,75 +512,30 @@ 1 ..\..\..\components\finsh\shell.c - - msh.c - 1 - ..\..\..\components\finsh\msh.c - cmd.c 1 ..\..\..\components\finsh\cmd.c + + msh.c + 1 + ..\..\..\components\finsh\msh.c + Kernel - - device.c - 1 - ..\..\..\src\device.c - - - timer.c - 1 - ..\..\..\src\timer.c - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - irq.c - 1 - ..\..\..\src\irq.c - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - idle.c - 1 - ..\..\..\src\idle.c - - - mempool.c - 1 - ..\..\..\src\mempool.c - scheduler.c 1 ..\..\..\src\scheduler.c - clock.c + idle.c 1 - ..\..\..\src\clock.c - - - thread.c - 1 - ..\..\..\src\thread.c - - - mem.c - 1 - ..\..\..\src\mem.c + ..\..\..\src\idle.c object.c @@ -597,6 +547,51 @@ 1 ..\..\..\src\components.c + + thread.c + 1 + ..\..\..\src\thread.c + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + clock.c + 1 + ..\..\..\src\clock.c + + + timer.c + 1 + ..\..\..\src\timer.c + + + mem.c + 1 + ..\..\..\src\mem.c + + + device.c + 1 + ..\..\..\src\device.c + + + irq.c + 1 + ..\..\..\src\irq.c + @@ -709,16 +704,6 @@ - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - diff --git a/bsp/stm32/stm32l475-st-discovery/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l475-st-discovery/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index a7fa9c3e37..37ccf5eef2 100644 --- a/bsp/stm32/stm32l475-st-discovery/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l475-st-discovery/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -113,15 +113,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PB6 ------> USART1_TX - PB7 ------> USART1_RX + PB7 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); @@ -148,10 +148,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PB6 ------> USART1_TX - PB7 ------> USART1_RX + PB7 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7); diff --git a/bsp/stm32/stm32l476-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32l476-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index 7d78ad4047..92fbb30a7d 100644 --- a/bsp/stm32/stm32l476-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32l476-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -222,7 +222,14 @@ Mcu.Pin11=PB10 Mcu.Pin12=PB14 RCC.PLLN=10 Mcu.Pin10=PA7 +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous +PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP +PA3.Mode=Asynchronous +PA3.Signal=USART2_RX VP_LPTIM1_VS_LPTIM_counterModeInternalClock.Signal=LPTIM1_VS_LPTIM_counterModeInternalClock RCC.PWRFreq_Value=80000000 RCC.I2C2Freq_Value=80000000 diff --git a/bsp/stm32/stm32l476-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l476-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index dda464c29e..32c1642b53 100644 --- a/bsp/stm32/stm32l476-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l476-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -118,10 +118,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) if(HAL_RCC_ADC_CLK_ENABLED==1){ __HAL_RCC_ADC_CLK_ENABLE(); } - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PC0 ------> ADC1_IN1 + /**ADC1 GPIO Configuration + PC0 ------> ADC1_IN1 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL; @@ -142,10 +142,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) if(HAL_RCC_ADC_CLK_ENABLED==1){ __HAL_RCC_ADC_CLK_ENABLE(); } - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**ADC2 GPIO Configuration - PC1 ------> ADC2_IN2 + /**ADC2 GPIO Configuration + PC1 ------> ADC2_IN2 */ GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL; @@ -166,10 +166,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) if(HAL_RCC_ADC_CLK_ENABLED==1){ __HAL_RCC_ADC_CLK_ENABLE(); } - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**ADC3 GPIO Configuration - PC2 ------> ADC3_IN3 + /**ADC3 GPIO Configuration + PC2 ------> ADC3_IN3 */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL; @@ -201,9 +201,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) if(HAL_RCC_ADC_CLK_ENABLED==0){ __HAL_RCC_ADC_CLK_DISABLE(); } - - /**ADC1 GPIO Configuration - PC0 ------> ADC1_IN1 + + /**ADC1 GPIO Configuration + PC0 ------> ADC1_IN1 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0); @@ -221,9 +221,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) if(HAL_RCC_ADC_CLK_ENABLED==0){ __HAL_RCC_ADC_CLK_DISABLE(); } - - /**ADC2 GPIO Configuration - PC1 ------> ADC2_IN2 + + /**ADC2 GPIO Configuration + PC1 ------> ADC2_IN2 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1); @@ -241,9 +241,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) if(HAL_RCC_ADC_CLK_ENABLED==0){ __HAL_RCC_ADC_CLK_DISABLE(); } - - /**ADC3 GPIO Configuration - PC2 ------> ADC3_IN3 + + /**ADC3 GPIO Configuration + PC2 ------> ADC3_IN3 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_2); @@ -358,12 +358,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -383,13 +383,13 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PC3 ------> SPI2_MOSI PB10 ------> SPI2_SCK - PB14 ------> SPI2_MISO + PB14 ------> SPI2_MISO */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -416,12 +416,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI3_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**SPI3 GPIO Configuration + /**SPI3 GPIO Configuration PC10 ------> SPI3_SCK PC11 ------> SPI3_MISO - PC12 ------> SPI3_MOSI + PC12 ------> SPI3_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -452,11 +452,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); @@ -471,11 +471,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PC3 ------> SPI2_MOSI PB10 ------> SPI2_SCK - PB14 ------> SPI2_MISO + PB14 ------> SPI2_MISO */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_3); @@ -492,11 +492,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI3_CLK_DISABLE(); - - /**SPI3 GPIO Configuration + + /**SPI3 GPIO Configuration PC10 ------> SPI3_SCK PC11 ------> SPI3_MISO - PC12 ------> SPI3_MOSI + PC12 ------> SPI3_MOSI */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12); @@ -611,15 +611,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -646,10 +646,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); diff --git a/bsp/stm32/stm32l496-ali-developer/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32l496-ali-developer/board/CubeMX_Config/CubeMX_Config.ioc index 851bf513a1..f74b8b254b 100644 --- a/bsp/stm32/stm32l496-ali-developer/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32l496-ali-developer/board/CubeMX_Config/CubeMX_Config.ioc @@ -86,8 +86,12 @@ PA13\ (JTMS/SWDIO).Mode=Serial_Wire PA13\ (JTMS/SWDIO).Signal=SYS_JTMS-SWDIO PA14\ (JTCK/SWCLK).Mode=Serial_Wire PA14\ (JTCK/SWCLK).Signal=SYS_JTCK-SWCLK +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX PA5.Locked=true @@ -101,11 +105,15 @@ PA9.Locked=true PA9.Mode=Full_Duplex_Master PA9.Signal=SPI2_SCK PB10.Locked=true +PB10.GPIOParameters=GPIO_PuPd +PB10.GPIO_PuPd=GPIO_PULLUP PB10.Mode=Asynchronous PB10.Signal=LPUART1_RX PB11.Locked=true PB11.Mode=Asynchronous PB11.Signal=LPUART1_TX +PB11.GPIOParameters=GPIO_PuPd +PB11.GPIO_PuPd=GPIO_PULLUP PC1.Mode=Full_Duplex_Master PC1.Signal=SPI2_MOSI PC10.Mode=SD_4_bits_Wide_bus diff --git a/bsp/stm32/stm32l496-ali-developer/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l496-ali-developer/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index 1b769dd9c6..d3c1d9fa89 100644 --- a/bsp/stm32/stm32l496-ali-developer/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l496-ali-developer/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -116,11 +116,11 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**ADC1 GPIO Configuration + /**ADC1 GPIO Configuration PC2 ------> ADC1_IN3 - PC3 ------> ADC1_IN4 + PC3 ------> ADC1_IN4 */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL; @@ -151,10 +151,10 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC_CLK_DISABLE(); - - /**ADC1 GPIO Configuration + + /**ADC1 GPIO Configuration PC2 ------> ADC1_IN3 - PC3 ------> ADC1_IN4 + PC3 ------> ADC1_IN4 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_2|GPIO_PIN_3); @@ -182,15 +182,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END LPUART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LPUART1_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**LPUART1 GPIO Configuration + /**LPUART1 GPIO Configuration PB10 ------> LPUART1_RX - PB11 ------> LPUART1_TX + PB11 ------> LPUART1_TX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); @@ -206,15 +206,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -230,15 +230,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PC4 ------> USART3_TX - PC5 ------> USART3_RX + PC5 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); @@ -267,10 +267,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END LPUART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LPUART1_CLK_DISABLE(); - - /**LPUART1 GPIO Configuration + + /**LPUART1 GPIO Configuration PB10 ------> LPUART1_RX - PB11 ------> LPUART1_TX + PB11 ------> LPUART1_TX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); @@ -285,10 +285,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); @@ -303,10 +303,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PC4 ------> USART3_TX - PC5 ------> USART3_RX + PC5 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_4|GPIO_PIN_5); @@ -381,18 +381,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDMMC1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDMMC1 GPIO Configuration + /**SDMMC1 GPIO Configuration PC8 ------> SDMMC1_D0 PC9 ------> SDMMC1_D1 PC10 ------> SDMMC1_D2 PC11 ------> SDMMC1_D3 PC12 ------> SDMMC1_CK - PD2 ------> SDMMC1_CMD + PD2 ------> SDMMC1_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -431,16 +431,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDMMC1_CLK_DISABLE(); - - /**SDMMC1 GPIO Configuration + + /**SDMMC1 GPIO Configuration PC8 ------> SDMMC1_D0 PC9 ------> SDMMC1_D1 PC10 ------> SDMMC1_D2 PC11 ------> SDMMC1_D3 PC12 ------> SDMMC1_CK - PD2 ------> SDMMC1_CMD + PD2 ------> SDMMC1_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -469,12 +469,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -494,14 +494,14 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PC1 ------> SPI2_MOSI PA9 ------> SPI2_SCK - PD3 ------> SPI2_MISO + PD3 ------> SPI2_MISO */ GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -548,11 +548,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); @@ -567,11 +567,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PC1 ------> SPI2_MOSI PA9 ------> SPI2_SCK - PD3 ------> SPI2_MISO + PD3 ------> SPI2_MISO */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1); @@ -663,12 +663,12 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM3_MspPostInit 0 */ /* USER CODE END TIM3_MspPostInit 0 */ - + __HAL_RCC_GPIOE_CLK_ENABLE(); - /**TIM3 GPIO Configuration + /**TIM3 GPIO Configuration PE4 ------> TIM3_CH2 PE5 ------> TIM3_CH3 - PE6 ------> TIM3_CH4 + PE6 ------> TIM3_CH4 */ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; diff --git a/bsp/stm32/stm32l496-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l496-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index e93c9f5f34..2b5755574f 100644 --- a/bsp/stm32/stm32l496-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l496-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -93,16 +93,16 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END LPUART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LPUART1_CLK_ENABLE(); - + __HAL_RCC_GPIOG_CLK_ENABLE(); HAL_PWREx_EnableVddIO2(); - /**LPUART1 GPIO Configuration + /**LPUART1 GPIO Configuration PG7 ------> LPUART1_TX - PG8 ------> LPUART1_RX + PG8 ------> LPUART1_RX */ GPIO_InitStruct.Pin = STLK_RX_Pin|STLK_TX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); @@ -129,10 +129,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END LPUART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LPUART1_CLK_DISABLE(); - - /**LPUART1 GPIO Configuration + + /**LPUART1 GPIO Configuration PG7 ------> LPUART1_TX - PG8 ------> LPUART1_RX + PG8 ------> LPUART1_RX */ HAL_GPIO_DeInit(GPIOG, STLK_RX_Pin|STLK_TX_Pin); @@ -157,14 +157,14 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ /* USER CODE END USB_OTG_FS_MspInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB_OTG_FS GPIO Configuration + /**USB_OTG_FS GPIO Configuration PA8 ------> USB_OTG_FS_SOF PA9 ------> USB_OTG_FS_VBUS PA10 ------> USB_OTG_FS_ID PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ GPIO_InitStruct.Pin = USB_SOF_Pin|USB_ID_Pin|USB_DM_Pin|USB_DP_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -214,15 +214,15 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) /* USER CODE END USB_OTG_FS_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); - - /**USB_OTG_FS GPIO Configuration + + /**USB_OTG_FS GPIO Configuration PA8 ------> USB_OTG_FS_SOF PA9 ------> USB_OTG_FS_VBUS PA10 ------> USB_OTG_FS_ID PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ - HAL_GPIO_DeInit(GPIOA, USB_SOF_Pin|USB_VBUS_Pin|USB_ID_Pin|USB_DM_Pin + HAL_GPIO_DeInit(GPIOA, USB_SOF_Pin|USB_VBUS_Pin|USB_ID_Pin|USB_DM_Pin |USB_DP_Pin); /* Disable VDDUSB */ diff --git a/bsp/stm32/stm32l4r5-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l4r5-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index 7446f38eb7..8bb1c70fd9 100644 --- a/bsp/stm32/stm32l4r5-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l4r5-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -93,12 +93,12 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END LPUART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LPUART1_CLK_ENABLE(); - + __HAL_RCC_GPIOG_CLK_ENABLE(); HAL_PWREx_EnableVddIO2(); - /**LPUART1 GPIO Configuration + /**LPUART1 GPIO Configuration PG7 ------> LPUART1_TX - PG8 ------> LPUART1_RX + PG8 ------> LPUART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -118,15 +118,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PD8 ------> USART3_TX - PD9 ------> USART3_RX + PD9 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); @@ -153,10 +153,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END LPUART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LPUART1_CLK_DISABLE(); - - /**LPUART1 GPIO Configuration + + /**LPUART1 GPIO Configuration PG7 ------> LPUART1_TX - PG8 ------> LPUART1_RX + PG8 ------> LPUART1_RX */ HAL_GPIO_DeInit(GPIOG, GPIO_PIN_7|GPIO_PIN_8); @@ -171,10 +171,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PD8 ------> USART3_TX - PD9 ------> USART3_RX + PD9 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9); diff --git a/bsp/stm32/stm32l4r9-st-eval/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32l4r9-st-eval/board/CubeMX_Config/CubeMX_Config.ioc index 1ded20f423..b5a954c18e 100644 --- a/bsp/stm32/stm32l4r9-st-eval/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32l4r9-st-eval/board/CubeMX_Config/CubeMX_Config.ioc @@ -101,10 +101,12 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false -PB10.Locked=true +PB10.GPIOParameters=GPIO_PuPd +PB10.GPIO_PuPd=GPIO_PULLUP PB10.Mode=Asynchronous PB10.Signal=USART3_TX -PB11.Locked=true +PB11.GPIOParameters=GPIO_PuPd +PB11.GPIO_PuPd=GPIO_PULLUP PB11.Mode=Asynchronous PB11.Signal=USART3_RX PC14-OSC32_IN\ (PC14).Mode=LSE-External-Oscillator diff --git a/bsp/stm32/stm32l4r9-st-eval/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l4r9-st-eval/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index 0cdb9babc3..457a8f7516 100644 --- a/bsp/stm32/stm32l4r9-st-eval/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l4r9-st-eval/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -302,15 +302,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PB11 ------> USART3_RX - PB10 ------> USART3_TX + PB10 ------> USART3_TX */ GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); @@ -339,10 +339,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PB11 ------> USART3_RX - PB10 ------> USART3_TX + PB10 ------> USART3_TX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11|GPIO_PIN_10); @@ -366,8 +366,8 @@ static void HAL_FMC_MspInit(void){ FMC_Initialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_ENABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 PD0 ------> FMC_D2 @@ -412,9 +412,9 @@ static void HAL_FMC_MspInit(void){ PF12 ------> FMC_A6 PE11 ------> FMC_D8 */ - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_3 - |GPIO_PIN_5|GPIO_PIN_10|GPIO_PIN_9|GPIO_PIN_15 - |GPIO_PIN_8|GPIO_PIN_14|GPIO_PIN_7|GPIO_PIN_13 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_3 + |GPIO_PIN_5|GPIO_PIN_10|GPIO_PIN_9|GPIO_PIN_15 + |GPIO_PIN_8|GPIO_PIN_14|GPIO_PIN_7|GPIO_PIN_13 |GPIO_PIN_12|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -422,9 +422,9 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_4|GPIO_PIN_1|GPIO_PIN_5 - |GPIO_PIN_7|GPIO_PIN_13|GPIO_PIN_15|GPIO_PIN_14 - |GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_4|GPIO_PIN_1|GPIO_PIN_5 + |GPIO_PIN_7|GPIO_PIN_13|GPIO_PIN_15|GPIO_PIN_14 + |GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 |GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -432,8 +432,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_1|GPIO_PIN_0|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_15|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_1|GPIO_PIN_0|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_15|GPIO_PIN_14 |GPIO_PIN_13|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -441,7 +441,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_1 + GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_1 |GPIO_PIN_2|GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -476,8 +476,8 @@ static void HAL_FMC_MspDeInit(void){ FMC_DeInitialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_DISABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 PD0 ------> FMC_D2 @@ -522,21 +522,21 @@ static void HAL_FMC_MspDeInit(void){ PF12 ------> FMC_A6 PE11 ------> FMC_D8 */ - HAL_GPIO_DeInit(GPIOE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_3 - |GPIO_PIN_5|GPIO_PIN_10|GPIO_PIN_9|GPIO_PIN_15 - |GPIO_PIN_8|GPIO_PIN_14|GPIO_PIN_7|GPIO_PIN_13 + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_3 + |GPIO_PIN_5|GPIO_PIN_10|GPIO_PIN_9|GPIO_PIN_15 + |GPIO_PIN_8|GPIO_PIN_14|GPIO_PIN_7|GPIO_PIN_13 |GPIO_PIN_12|GPIO_PIN_11); - HAL_GPIO_DeInit(GPIOD, GPIO_PIN_0|GPIO_PIN_4|GPIO_PIN_1|GPIO_PIN_5 - |GPIO_PIN_7|GPIO_PIN_13|GPIO_PIN_15|GPIO_PIN_14 - |GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_0|GPIO_PIN_4|GPIO_PIN_1|GPIO_PIN_5 + |GPIO_PIN_7|GPIO_PIN_13|GPIO_PIN_15|GPIO_PIN_14 + |GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 |GPIO_PIN_8); - HAL_GPIO_DeInit(GPIOF, GPIO_PIN_2|GPIO_PIN_1|GPIO_PIN_0|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_15|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_2|GPIO_PIN_1|GPIO_PIN_0|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_15|GPIO_PIN_14 |GPIO_PIN_13|GPIO_PIN_12); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_1 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_1 |GPIO_PIN_2|GPIO_PIN_0); /* USER CODE BEGIN FMC_MspDeInit 1 */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c index 5ca08fbbd0..940be95f73 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32mp1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -33,7 +33,7 @@ DMA_HandleTypeDef hdma_cryp_out = {0}; /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -59,7 +59,7 @@ DMA_HandleTypeDef hdma_cryp_out = {0}; /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + /** * Initializes the Global MSP. */ @@ -74,7 +74,7 @@ void HAL_MspInit(void) /* System interrupt init*/ /* USER CODE BEGIN MspInit 1 */ - if (IS_ENGINEERING_BOOT_MODE()) + if (IS_ENGINEERING_BOOT_MODE()) { __HAL_RCC_SYSRAM_CLK_ENABLE(); } @@ -102,7 +102,7 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC2_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PER; @@ -115,10 +115,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* Peripheral clock enable */ __HAL_RCC_ADC12_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); - /**ADC2 GPIO Configuration - PF14 ------> ADC2_INP6 + /**ADC2 GPIO Configuration + PF14 ------> ADC2_INP6 */ GPIO_InitStruct.Pin = GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -145,9 +145,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC12_CLK_DISABLE(); - - /**ADC2 GPIO Configuration - PF14 ------> ADC2_INP6 + + /**ADC2 GPIO Configuration + PF14 ------> ADC2_INP6 */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_14); @@ -174,10 +174,10 @@ void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac) /* USER CODE END DAC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_DAC12_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**DAC1 GPIO Configuration - PA4 ------> DAC1_OUT1 + /**DAC1 GPIO Configuration + PA4 ------> DAC1_OUT1 */ GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -205,9 +205,9 @@ void HAL_DAC_MspDeInit(DAC_HandleTypeDef* hdac) /* USER CODE END DAC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_DAC12_CLK_DISABLE(); - - /**DAC1 GPIO Configuration - PA4 ------> DAC1_OUT1 + + /**DAC1 GPIO Configuration + PA4 ------> DAC1_OUT1 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4); @@ -287,7 +287,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) /* USER CODE END LPTIM1_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1; PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSI; @@ -315,7 +315,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM23; PeriphClkInit.Lptim23ClockSelection = RCC_LPTIM23CLKSOURCE_PCLK3; @@ -343,7 +343,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM23; PeriphClkInit.Lptim23ClockSelection = RCC_LPTIM23CLKSOURCE_PCLK3; @@ -371,7 +371,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM45; PeriphClkInit.Lptim45ClockSelection = RCC_LPTIM45CLKSOURCE_PCLK3; @@ -399,7 +399,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM45; PeriphClkInit.Lptim45ClockSelection = RCC_LPTIM45CLKSOURCE_PCLK3; @@ -520,7 +520,7 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI45; PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PCLK2; @@ -533,12 +533,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* Peripheral clock enable */ __HAL_RCC_SPI5_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); - /**SPI5 GPIO Configuration + /**SPI5 GPIO Configuration PF9 ------> SPI5_MOSI PF8 ------> SPI5_MISO - PF7 ------> SPI5_SCK + PF7 ------> SPI5_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_8|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -569,10 +569,10 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI5_CLK_DISABLE(); - - /**SPI5 GPIO Configuration + + /**SPI5 GPIO Configuration PF9 ------> SPI5_MOSI - PF7 ------> SPI5_SCK + PF7 ------> SPI5_SCK */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_9|GPIO_PIN_7); @@ -646,10 +646,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM4_MspPostInit 0 */ /* USER CODE END TIM4_MspPostInit 0 */ - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**TIM4 GPIO Configuration - PD13 ------> TIM4_CH2 + /**TIM4 GPIO Configuration + PD13 ------> TIM4_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -736,7 +736,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_UART24; PeriphClkInit.Uart24ClockSelection = RCC_UART24CLKSOURCE_HSI; @@ -749,23 +749,23 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* Peripheral clock enable */ __HAL_RCC_UART4_CLK_ENABLE(); - + __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**UART4 GPIO Configuration + /**UART4 GPIO Configuration PG11 ------> UART4_TX - PB2 ------> UART4_RX + PB2 ------> UART4_RX */ GPIO_InitStruct.Pin = STLINK_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF6_UART4; HAL_GPIO_Init(STLINK_RX_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = STLINK_TX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF8_UART4; HAL_GPIO_Init(STLINK_TX_GPIO_Port, &GPIO_InitStruct); @@ -781,7 +781,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_UART35; PeriphClkInit.Uart35ClockSelection = RCC_UART35CLKSOURCE_PCLK1; @@ -794,22 +794,22 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB12 ------> USART3_RX + PB12 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF8_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); @@ -835,10 +835,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART4_CLK_DISABLE(); - - /**UART4 GPIO Configuration + + /**UART4 GPIO Configuration PG11 ------> UART4_TX - PB2 ------> UART4_RX + PB2 ------> UART4_RX */ HAL_GPIO_DeInit(STLINK_RX_GPIO_Port, STLINK_RX_Pin); @@ -855,10 +855,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB12 ------> USART3_RX + PB12 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_12); @@ -904,12 +904,12 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hI2c) { GPIO_InitTypeDef GPIO_InitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - + if(hI2c->Instance == I2C4) { if(IS_ENGINEERING_BOOT_MODE()) { - /*** Configure the I2C peripheral clock ***/ + /*** Configure the I2C peripheral clock ***/ PeriphClkInit.I2c46ClockSelection = RCC_I2C46CLKSOURCE_HSI; PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C46; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) @@ -931,11 +931,11 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hI2c) /* Enable I2C clock */ __HAL_RCC_I2C4_CLK_ENABLE(); - /* Force the I2C peripheral clock reset */ + /* Force the I2C peripheral clock reset */ __HAL_RCC_I2C4_FORCE_RESET(); - /* Release the I2C peripheral clock reset */ + /* Release the I2C peripheral clock reset */ __HAL_RCC_I2C4_RELEASE_RESET(); - + HAL_NVIC_SetPriority(I2C4_ER_IRQn, 0, 1); HAL_NVIC_EnableIRQ(I2C4_ER_IRQn); HAL_NVIC_SetPriority(I2C4_EV_IRQn, 0, 2); @@ -953,13 +953,13 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) { GPIO_InitTypeDef GPIO_InitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - + if(hsd->Instance==SDMMC1) { /* USER CODE BEGIN SDMMC1_MspInit 0 */ if (IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.Sdmmc12ClockSelection = RCC_SDMMC12CLKSOURCE_PLL4; PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SDMMC12; @@ -971,18 +971,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDMMC1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDMMC1 GPIO Configuration + /**SDMMC1 GPIO Configuration PC8 ------> SDMMC1_D0 PC9 ------> SDMMC1_D1 PC10 ------> SDMMC1_D2 PC11 ------> SDMMC1_D3 PC12 ------> SDMMC1_CK - PD2 ------> SDMMC1_CMD + PD2 ------> SDMMC1_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -995,7 +995,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) __HAL_RCC_SDMMC1_FORCE_RESET(); __HAL_RCC_SDMMC1_RELEASE_RESET(); - + /* SDMMC1 interrupt Init */ HAL_NVIC_SetPriority(SDMMC1_IRQn, 2, 0); HAL_NVIC_EnableIRQ(SDMMC1_IRQn); @@ -1008,7 +1008,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE BEGIN SDMMC2_MspInit 0 */ if (IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.Sdmmc12ClockSelection = RCC_SDMMC12CLKSOURCE_PLL4; PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SDMMC12; @@ -1020,17 +1020,17 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDMMC2_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); - /**SDMMC2 GPIO Configuration + /**SDMMC2 GPIO Configuration PB14 ------> SDMMC2_D0 PB15 ------> SDMMC2_D1 PB3 ------> SDMMC2_D2 PB4 ------> SDMMC2_D3 PE3 ------> SDMMC2_CK - PG6 ------> SDMMC2_CMD + PG6 ------> SDMMC2_CMD */ GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -1055,7 +1055,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) __HAL_RCC_SDMMC2_FORCE_RESET(); __HAL_RCC_SDMMC2_RELEASE_RESET(); - + /* SDMMC2 interrupt Init */ HAL_NVIC_SetPriority(SDMMC2_IRQn, 2, 0); HAL_NVIC_EnableIRQ(SDMMC2_IRQn); @@ -1080,16 +1080,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDMMC1_CLK_DISABLE(); - - /**SDMMC1 GPIO Configuration + + /**SDMMC1 GPIO Configuration PC8 ------> SDMMC1_D0 PC9 ------> SDMMC1_D1 PC10 ------> SDMMC1_D2 PC11 ------> SDMMC1_D3 PC12 ------> SDMMC1_CK - PD2 ------> SDMMC1_CMD + PD2 ------> SDMMC1_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -1111,7 +1111,7 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hI2c) { GPIO_InitTypeDef GPIO_InitStruct = {0}; - + if(hI2c->Instance == I2C4) { /* Configure I2C Tx, Rx as alternate function */ @@ -1187,7 +1187,7 @@ void HAL_RNG_MspInit(RNG_HandleTypeDef* hrng) /* USER CODE END RNG2_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG2; PeriphClkInit.Rng2ClockSelection = RCC_RNG2CLKSOURCE_CSI; @@ -1243,7 +1243,7 @@ void HAL_HASH_MspInit(HASH_HandleTypeDef* hhash) __HAL_RCC_HASH2_CLK_ENABLE(); /* USER CODE BEGIN HASH2_MspInit 1 */ __HAL_RCC_DMAMUX_CLK_ENABLE(); - + /* Peripheral DMA init*/ hdma_hash_in.Instance = DMA2_Stream7; hdma_hash_in.Init.Request = DMA_REQUEST_HASH2_IN; @@ -1386,7 +1386,7 @@ void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc) /* USER CODE BEGIN SDMMC1_MspInit 0 */ if (IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC; diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c index 20f6aa2d63..6e8d4b0ca2 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32mp1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -39,7 +39,7 @@ DMA_HandleTypeDef hdma_dfsdm1_flt1 = {0}; /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -65,7 +65,7 @@ DMA_HandleTypeDef hdma_dfsdm1_flt1 = {0}; /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -85,7 +85,7 @@ void HAL_MspInit(void) { __HAL_RCC_SYSRAM_CLK_ENABLE(); } - + HAL_NVIC_SetPriority(RCC_WAKEUP_IRQn, 0, 0); HAL_NVIC_EnableIRQ(RCC_WAKEUP_IRQn); __HAL_RCC_ENABLE_IT(RCC_IT_WKUP); @@ -109,7 +109,7 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC2_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PER; @@ -122,10 +122,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* Peripheral clock enable */ __HAL_RCC_ADC12_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); - /**ADC2 GPIO Configuration - PF14 ------> ADC2_INP6 + /**ADC2 GPIO Configuration + PF14 ------> ADC2_INP6 */ GPIO_InitStruct.Pin = GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -152,9 +152,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC12_CLK_DISABLE(); - - /**ADC2 GPIO Configuration - PF14 ------> ADC2_INP6 + + /**ADC2 GPIO Configuration + PF14 ------> ADC2_INP6 */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_14); @@ -181,10 +181,10 @@ void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac) /* USER CODE END DAC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_DAC12_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**DAC1 GPIO Configuration - PA4 ------> DAC1_OUT1 + /**DAC1 GPIO Configuration + PA4 ------> DAC1_OUT1 */ GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -212,9 +212,9 @@ void HAL_DAC_MspDeInit(DAC_HandleTypeDef* hdac) /* USER CODE END DAC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_DAC12_CLK_DISABLE(); - - /**DAC1 GPIO Configuration - PA4 ------> DAC1_OUT1 + + /**DAC1 GPIO Configuration + PA4 ------> DAC1_OUT1 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4); @@ -294,7 +294,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) /* USER CODE END LPTIM1_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1; PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE; @@ -322,7 +322,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM23; PeriphClkInit.Lptim23ClockSelection = RCC_LPTIM23CLKSOURCE_PCLK3; @@ -350,7 +350,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM23; PeriphClkInit.Lptim23ClockSelection = RCC_LPTIM23CLKSOURCE_PCLK3; @@ -378,7 +378,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM45; PeriphClkInit.Lptim45ClockSelection = RCC_LPTIM45CLKSOURCE_PCLK3; @@ -406,7 +406,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM45; PeriphClkInit.Lptim45ClockSelection = RCC_LPTIM45CLKSOURCE_PCLK3; @@ -527,7 +527,7 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI1; PeriphClkInit.Spi1ClockSelection = RCC_SPI1CLKSOURCE_PLL4; @@ -540,9 +540,9 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOZ_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PZ2 ------> SPI1_MOSI PZ1 ------> SPI1_MISO PZ0 ------> SPI1_SCK @@ -576,10 +576,10 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI5_CLK_DISABLE(); - - /**SPI5 GPIO Configuration + + /**SPI5 GPIO Configuration PF9 ------> SPI5_MOSI - PF7 ------> SPI5_SCK + PF7 ------> SPI5_SCK */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_9|GPIO_PIN_7); @@ -653,10 +653,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM4_MspPostInit 0 */ /* USER CODE END TIM4_MspPostInit 0 */ - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**TIM4 GPIO Configuration - PD13 ------> TIM4_CH2 + /**TIM4 GPIO Configuration + PD13 ------> TIM4_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -743,7 +743,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_UART24; PeriphClkInit.Uart24ClockSelection = RCC_UART24CLKSOURCE_HSI; @@ -756,23 +756,23 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* Peripheral clock enable */ __HAL_RCC_UART4_CLK_ENABLE(); - + __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**UART4 GPIO Configuration + /**UART4 GPIO Configuration PG11 ------> UART4_TX - PB2 ------> UART4_RX + PB2 ------> UART4_RX */ GPIO_InitStruct.Pin = STLINK_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF6_UART4; HAL_GPIO_Init(STLINK_RX_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = STLINK_TX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF8_UART4; HAL_GPIO_Init(STLINK_TX_GPIO_Port, &GPIO_InitStruct); @@ -788,7 +788,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_UART35; PeriphClkInit.Uart35ClockSelection = RCC_UART35CLKSOURCE_PCLK1; @@ -801,22 +801,22 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB12 ------> USART3_RX + PB12 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF8_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); @@ -842,10 +842,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART4_CLK_DISABLE(); - - /**UART4 GPIO Configuration + + /**UART4 GPIO Configuration PG11 ------> UART4_TX - PB2 ------> UART4_RX + PB2 ------> UART4_RX */ HAL_GPIO_DeInit(STLINK_RX_GPIO_Port, STLINK_RX_Pin); @@ -862,10 +862,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB12 ------> USART3_RX + PB12 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_12); @@ -911,12 +911,12 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hI2c) { GPIO_InitTypeDef GPIO_InitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - + if(hI2c->Instance == I2C4) { if(IS_ENGINEERING_BOOT_MODE()) { - /*** Configure the I2C peripheral clock ***/ + /*** Configure the I2C peripheral clock ***/ PeriphClkInit.I2c46ClockSelection = RCC_I2C46CLKSOURCE_HSI; PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C46; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) @@ -938,11 +938,11 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hI2c) /* Enable I2C clock */ __HAL_RCC_I2C4_CLK_ENABLE(); - /* Force the I2C peripheral clock reset */ + /* Force the I2C peripheral clock reset */ __HAL_RCC_I2C4_FORCE_RESET(); - /* Release the I2C peripheral clock reset */ + /* Release the I2C peripheral clock reset */ __HAL_RCC_I2C4_RELEASE_RESET(); - + HAL_NVIC_SetPriority(I2C4_ER_IRQn, 0, 1); HAL_NVIC_EnableIRQ(I2C4_ER_IRQn); HAL_NVIC_SetPriority(I2C4_EV_IRQn, 0, 2); @@ -958,7 +958,7 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hI2c) void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hI2c) { GPIO_InitTypeDef GPIO_InitStruct = {0}; - + if(hI2c->Instance == I2C4) { /* Configure I2C Tx, Rx as alternate function */ @@ -990,7 +990,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE BEGIN SDMMC1_MspInit 0 */ if (IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.Sdmmc12ClockSelection = RCC_SDMMC12CLKSOURCE_PLL4; PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SDMMC12; @@ -1018,7 +1018,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) PC12 ------> SDMMC1_CK PD2 ------> SDMMC1_CMD PE4 ------> SDMMC1_CKIN - PF2 ------> SDMMC1_D0DIR + PF2 ------> SDMMC1_D0DIR */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -1033,11 +1033,11 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Alternate = GPIO_AF8_SDIO1; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - + GPIO_InitStruct.Pin = GPIO_PIN_4; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1; @@ -1056,13 +1056,13 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspInit 1 */ } - + if(hsd->Instance==SDMMC2) { /* USER CODE BEGIN SDMMC2_MspInit 0 */ if (IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.Sdmmc12ClockSelection = RCC_SDMMC12CLKSOURCE_PLL4; PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SDMMC12; @@ -1088,7 +1088,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) PA8 ------> SDMMC2_D4 PA9 ------> SDMMC2_D5 PE5 ------> SDMMC2_D6 - PD3 ------> SDMMC2_D7 + PD3 ------> SDMMC2_D7 PE3 ------> SDMMC2_CK PG6 ------> SDMMC2_CMD */ @@ -1104,10 +1104,10 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) GPIO_InitStruct.Pin = GPIO_PIN_3; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - + GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_5; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - + GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Alternate = GPIO_AF10_SDIO2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -1143,8 +1143,8 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDMMC1_CLK_DISABLE(); - - /**SDMMC1 GPIO Configuration + + /**SDMMC1 GPIO Configuration PB9 ------> SDMMC1_CDIR PC7 ------> SDMMC1_D123DIR PC8 ------> SDMMC1_D0 @@ -1154,17 +1154,17 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) PC12 ------> SDMMC1_CK PD2 ------> SDMMC1_CMD PE4 ------> SDMMC1_CKIN - PF2 ------> SDMMC1_D0DIR + PF2 ------> SDMMC1_D0DIR */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9); - + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_4); - + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_2); /* SDMMC1 interrupt DeInit */ HAL_NVIC_DisableIRQ(SDMMC1_IRQn); @@ -1172,7 +1172,7 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspDeInit 1 */ } - + if(hsd->Instance==SDMMC2) { /* USER CODE BEGIN SDMMC2_MspDeInit 0 */ @@ -1180,8 +1180,8 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDMMC2_CLK_DISABLE(); - - /**SDMMC2 GPIO Configuration + + /**SDMMC2 GPIO Configuration PB14 ------> SDMMC2_D0 PB15 ------> SDMMC2_D1 PB3 ------> SDMMC2_D2 @@ -1189,7 +1189,7 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) PA8 ------> SDMMC2_D4 PA9 ------> SDMMC2_D5 PE5 ------> SDMMC2_D6 - PD3 ------> SDMMC2_D7 + PD3 ------> SDMMC2_D7 PE3 ------> SDMMC2_CK PG6 ------> SDMMC2_CMD */ @@ -1198,9 +1198,9 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8|GPIO_PIN_9); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_3); - + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_3|GPIO_PIN_5); - + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_6); /* SDMMC2 interrupt DeInit */ HAL_NVIC_DisableIRQ(SDMMC2_IRQn); @@ -1221,7 +1221,7 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) /* Peripheral clock enable */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SAI2; PeriphClkInit.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLL3_Q; @@ -1236,7 +1236,7 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_SAI2_CLK_ENABLE(); - /**SAI2_A_Block_A GPIO Configuration + /**SAI2_A_Block_A GPIO Configuration PE0 ------> SAI2_MCLK_A PI7 ------> SAI2_FS_A PI5 ------> SAI2_SCK_A @@ -1269,7 +1269,7 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) hdma_sai2_a.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_sai2_a.Init.MemBurst = DMA_MBURST_SINGLE; hdma_sai2_a.Init.PeriphBurst = DMA_PBURST_SINGLE; - + HAL_DMA_DeInit(&hdma_sai2_a); if (HAL_DMA_Init(&hdma_sai2_a) != HAL_OK) { @@ -1277,17 +1277,17 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) } __HAL_LINKDMA(hsai,hdmatx,hdma_sai2_a); __HAL_DMA_ENABLE(&hdma_sai2_a); - + HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0x02, 0); HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn); } - + if (hsai->Instance==SAI2_Block_B) { /* Peripheral clock enable */ if (IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SAI2; PeriphClkInit.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLL3_Q; @@ -1299,8 +1299,8 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) } __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_SAI2_CLK_ENABLE(); - - /**SAI2_B_Block_B GPIO Configuration + + /**SAI2_B_Block_B GPIO Configuration PE12 ------> SAI2_MCLK_B PE13 ------> SAI2_FS_B PE14 ------> SAI2_SCK_B @@ -1313,13 +1313,13 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF10_SAI2; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); - + GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - + __HAL_RCC_DMAMUX_CLK_ENABLE(); __HAL_RCC_DMA1_CLK_ENABLE(); - + /* Peripheral DMA init*/ hdma_sai2_b.Instance = DMA1_Stream1; hdma_sai2_b.Init.Request = DMA_REQUEST_SAI2_B; @@ -1334,7 +1334,7 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) hdma_sai2_b.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_sai2_b.Init.MemBurst = DMA_MBURST_SINGLE; hdma_sai2_b.Init.PeriphBurst = DMA_PBURST_SINGLE; - + HAL_DMA_DeInit(&hdma_sai2_b); if (HAL_DMA_Init(&hdma_sai2_b) != HAL_OK) { @@ -1343,7 +1343,7 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) __HAL_LINKDMA(hsai,hdmarx,hdma_sai2_b); __HAL_DMA_ENABLE(&hdma_sai2_b); HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0x02, 0); - HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn); + HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn); } /* SAI4 */ if(hsai->Instance==SAI4_Block_A) @@ -1351,7 +1351,7 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) /* Peripheral clock enable */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SAI4; PeriphClkInit.Sai4ClockSelection = RCC_SAI4CLKSOURCE_PLL3_Q; @@ -1363,9 +1363,9 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) } __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_SAI4_CLK_ENABLE(); - - /**SAI4_A_Block_A GPIO Configuration - PB5 ------> SAI4_SD_A + + /**SAI4_A_Block_A GPIO Configuration + PB5 ------> SAI4_SD_A */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -1377,7 +1377,7 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) /* Peripheral DMA init*/ __HAL_RCC_DMAMUX_CLK_ENABLE(); __HAL_RCC_DMA1_CLK_ENABLE(); - + hdma_sai4_a.Instance = DMA1_Stream2; hdma_sai4_a.Init.Request = DMA_REQUEST_SAI4_A; hdma_sai4_a.Init.Direction = DMA_MEMORY_TO_PERIPH; @@ -1391,7 +1391,7 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) hdma_sai4_a.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_sai4_a.Init.MemBurst = DMA_MBURST_SINGLE; hdma_sai4_a.Init.PeriphBurst = DMA_PBURST_SINGLE; - + HAL_DMA_DeInit(&hdma_sai4_a); if (HAL_DMA_Init(&hdma_sai4_a) != HAL_OK) { @@ -1400,7 +1400,7 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) __HAL_LINKDMA(hsai,hdmatx,hdma_sai4_a); __HAL_DMA_ENABLE(&hdma_sai4_a); HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 0x02, 0); - HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn); + HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn); } } @@ -1420,27 +1420,27 @@ void HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi) /* USER CODE END DCMI_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_DCMI_CLK_ENABLE(); - + __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); - + /**DCMI GPIO Configuration - PH9 ------> DCMI_D0 + PH9 ------> DCMI_D0 PH10 ------> DCMI_D1 PH11 ------> DCMI_D2 PH12 ------> DCMI_D3 PH14 ------> DCMI_D4 - PI4 ------> DCMI_D5 - PB8 ------> DCMI_D6 - PE6 ------> DCMI_D7 + PI4 ------> DCMI_D5 + PB8 ------> DCMI_D6 + PE6 ------> DCMI_D7 PH8 ------> DCMI_HSYNC PB7 ------> DCMI_VSYNC PA6 ------> DCMI_PIXCLK */ - GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_8 + GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_8 |GPIO_PIN_9|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1470,10 +1470,10 @@ void HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi) GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Alternate = GPIO_AF13_DCMI; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - HAL_NVIC_SetPriority(DCMI_IRQn, 0x03, 0x00); - HAL_NVIC_EnableIRQ(DCMI_IRQn); - + + HAL_NVIC_SetPriority(DCMI_IRQn, 0x03, 0x00); + HAL_NVIC_EnableIRQ(DCMI_IRQn); + /* USER CODE BEGIN DCMI_MspInit 1 */ /* USER CODE END DCMI_MspInit 1 */ } @@ -1495,8 +1495,8 @@ void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* hdcmi) /* USER CODE END DCMI_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_DCMI_CLK_DISABLE(); - - /**DCMI GPIO Configuration + + /**DCMI GPIO Configuration PH10 ------> DCMI_D1 PH11 ------> DCMI_D2 PH14 ------> DCMI_D4 @@ -1507,9 +1507,9 @@ void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* hdcmi) PB7 ------> DCMI_VSYNC PI4 ------> DCMI_D5 PA6 ------> DCMI_PIXCLK - PB8 ------> DCMI_D6 + PB8 ------> DCMI_D6 */ - HAL_GPIO_DeInit(GPIOH, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_8 + HAL_GPIO_DeInit(GPIOH, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_8 |GPIO_PIN_9|GPIO_PIN_12); HAL_GPIO_DeInit(GPIOE, GPIO_PIN_6); @@ -1544,7 +1544,7 @@ void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan) /* USER CODE END FDCAN1_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN; PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_HSE; @@ -1557,12 +1557,12 @@ void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan) /* Peripheral clock enable */ __HAL_RCC_FDCAN_CLK_ENABLE(); - + __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); - /**FDCAN1 GPIO Configuration + /**FDCAN1 GPIO Configuration PH13 ------> FDCAN1_TX - PI9 ------> FDCAN1_RX + PI9 ------> FDCAN1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -1605,10 +1605,10 @@ void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* hfdcan) /* USER CODE END FDCAN1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_FDCAN_CLK_DISABLE(); - - /**FDCAN1 GPIO Configuration + + /**FDCAN1 GPIO Configuration PH13 ------> FDCAN1_TX - PI9 ------> FDCAN1_RX + PI9 ------> FDCAN1_RX */ HAL_GPIO_DeInit(GPIOH, GPIO_PIN_13); @@ -1655,7 +1655,7 @@ void HAL_SPDIFRX_MspInit(SPDIFRX_HandleTypeDef* hspdifrx) __HAL_RCC_DMAMUX_CLK_ENABLE(); __HAL_RCC_DMA1_CLK_ENABLE(); - + hdma_spdifrx_rx.Instance = DMA1_Stream7; hdma_spdifrx_rx.Init.Request = DMA_REQUEST_SPDIF_RX_DT; hdma_spdifrx_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; @@ -1668,8 +1668,8 @@ void HAL_SPDIFRX_MspInit(SPDIFRX_HandleTypeDef* hspdifrx) hdma_spdifrx_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; hdma_spdifrx_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_spdifrx_rx.Init.MemBurst = DMA_MBURST_SINGLE; - hdma_spdifrx_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; - + hdma_spdifrx_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; + HAL_DMA_DeInit(&hdma_spdifrx_rx); if (HAL_DMA_Init(&hdma_spdifrx_rx) != HAL_OK) { @@ -1677,7 +1677,7 @@ void HAL_SPDIFRX_MspInit(SPDIFRX_HandleTypeDef* hspdifrx) } __HAL_LINKDMA(hspdifrx, hdmaDrRx, hdma_spdifrx_rx); - + HAL_NVIC_SetPriority(DMA1_Stream7_IRQn, 0x02, 0); HAL_NVIC_EnableIRQ(DMA1_Stream7_IRQn); } @@ -1713,10 +1713,10 @@ void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef* hdfsdm_channel) __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); - /**DFSDM1 GPIO Configuration + /**DFSDM1 GPIO Configuration PC3 ------> DFSDM1_DATIN1 PB13 ------> DFSDM1_CKOUT - PF13 ------> DFSDM1_DATIN3 + PF13 ------> DFSDM1_DATIN3 */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -1724,7 +1724,7 @@ void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef* hdfsdm_channel) GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF3_DFSDM1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - + GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Alternate = GPIO_AF3_DFSDM1; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); @@ -1737,10 +1737,10 @@ void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef* hdfsdm_channel) void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef* hdfsdm_filter) { RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - + if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_DFSDM1; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) @@ -1748,12 +1748,12 @@ void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef* hdfsdm_filter) Error_Handler(); } } - + __HAL_RCC_DFSDM1_CLK_ENABLE(); /* DMA controller clock enable */ __HAL_RCC_DMAMUX_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); - + if(hdfsdm_filter->Instance == DFSDM1_Filter0) { hdma_dfsdm1_flt0.Instance = DMA2_Stream2; @@ -1777,7 +1777,7 @@ void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef* hdfsdm_filter) /* Several peripheral DMA handle pointers point to the same DMA handle. Be aware that there is only one channel to perform all the requested DMAs. */ __HAL_LINKDMA(hdfsdm_filter,hdmaReg,hdma_dfsdm1_flt0); - + HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 2, 0); HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); } @@ -1797,14 +1797,14 @@ void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef* hdfsdm_filter) hdma_dfsdm1_flt1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_dfsdm1_flt1.Init.MemBurst = DMA_MBURST_SINGLE; hdma_dfsdm1_flt1.Init.PeriphBurst = DMA_PBURST_SINGLE; - + if (HAL_DMA_Init(&hdma_dfsdm1_flt1) != HAL_OK) { Error_Handler(); } - + __HAL_LINKDMA(hdfsdm_filter,hdmaReg,hdma_dfsdm1_flt1); - + HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 2, 0); HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn); } @@ -1837,7 +1837,7 @@ void HAL_HASH_MspInit(HASH_HandleTypeDef* hhash) __HAL_RCC_HASH2_CLK_ENABLE(); /* USER CODE BEGIN HASH2_MspInit 1 */ __HAL_RCC_DMAMUX_CLK_ENABLE(); - + /* Peripheral DMA init*/ hdma_hash_in.Instance = DMA2_Stream7; hdma_hash_in.Init.Request = DMA_REQUEST_HASH2_IN; @@ -1946,7 +1946,7 @@ void HAL_RNG_MspInit(RNG_HandleTypeDef* hrng) /* USER CODE END RNG2_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG2; PeriphClkInit.Rng2ClockSelection = RCC_RNG2CLKSOURCE_LSE; diff --git a/bsp/stm32/stm32wb55-st-nucleo/board/CubeMX_Config/Src/stm32wbxx_hal_msp.c b/bsp/stm32/stm32wb55-st-nucleo/board/CubeMX_Config/Src/stm32wbxx_hal_msp.c index 208e05644a..3e44fb9be1 100644 --- a/bsp/stm32/stm32wb55-st-nucleo/board/CubeMX_Config/Src/stm32wbxx_hal_msp.c +++ b/bsp/stm32/stm32wb55-st-nucleo/board/CubeMX_Config/Src/stm32wbxx_hal_msp.c @@ -226,7 +226,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); @@ -250,7 +250,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); diff --git a/bsp/stm32/stm32wl55-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32wl55-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index 4810da4b1f..510a488e01 100644 --- a/bsp/stm32/stm32wl55-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32wl55-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -45,12 +45,14 @@ PA1.GPIOParameters=GPIO_Label PA1.GPIO_Label=BUT2 PA1.Locked=true PA1.Signal=GPIO_Input -PA2.Locked=true +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous -PA2.Signal=LPUART1_TX -PA3.Locked=true +PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous -PA3.Signal=LPUART1_RX +PA3.Signal=USART2_RX PB11.GPIOParameters=GPIO_Label PB11.GPIO_Label=LED3 PB11.Locked=true diff --git a/bsp/stm32/stm32wl55-st-nucleo/board/CubeMX_Config/Src/stm32wlxx_hal_msp.c b/bsp/stm32/stm32wl55-st-nucleo/board/CubeMX_Config/Src/stm32wlxx_hal_msp.c index 72350eda0d..798e9a7ee0 100644 --- a/bsp/stm32/stm32wl55-st-nucleo/board/CubeMX_Config/Src/stm32wlxx_hal_msp.c +++ b/bsp/stm32/stm32wl55-st-nucleo/board/CubeMX_Config/Src/stm32wlxx_hal_msp.c @@ -102,7 +102,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); From e7b63ed7ab2bed790d8b24b68333f65232f71926 Mon Sep 17 00:00:00 2001 From: malongwei <2544047213@qq.com> Date: Wed, 7 Jul 2021 23:49:42 +0800 Subject: [PATCH 250/255] fix at_vprintf and at_vprintfln and end_sign response --- components/net/at/src/at_client.c | 9 ++++++++- components/net/at/src/at_utils.c | 17 +++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/components/net/at/src/at_client.c b/components/net/at/src/at_client.c index a613ea1435..b320072b00 100644 --- a/components/net/at/src/at_client.c +++ b/components/net/at/src/at_client.c @@ -735,6 +735,8 @@ static void client_parser(at_client_t client) { at_response_t resp = client->resp; + char end_ch = client->recv_line_buf[client->recv_line_len - 1]; + /* current receive is response */ client->recv_line_buf[client->recv_line_len - 1] = '\0'; if (resp->buf_len + client->recv_line_len < resp->buf_size) @@ -752,7 +754,12 @@ static void client_parser(at_client_t client) LOG_E("Read response buffer failed. The Response buffer size is out of buffer size(%d)!", resp->buf_size); } /* check response result */ - if (rt_memcmp(client->recv_line_buf, AT_RESP_END_OK, rt_strlen(AT_RESP_END_OK)) == 0 + if ((client->end_sign != 0) && (end_ch == client->end_sign) && (resp->line_num == 0)) + { + /* get the end sign, return response state END_OK.*/ + client->resp_status = AT_RESP_OK; + } + else if (rt_memcmp(client->recv_line_buf, AT_RESP_END_OK, rt_strlen(AT_RESP_END_OK)) == 0 && resp->line_num == 0) { /* get the end data by response result, return response state END_OK. */ diff --git a/components/net/at/src/at_utils.c b/components/net/at/src/at_utils.c index 8d8887fe5e..d75ee0990e 100644 --- a/components/net/at/src/at_utils.c +++ b/components/net/at/src/at_utils.c @@ -68,21 +68,30 @@ const char *at_get_last_cmd(rt_size_t *cmd_size) rt_size_t at_vprintf(rt_device_t device, const char *format, va_list args) { last_cmd_len = vsnprintf(send_buf, sizeof(send_buf), format, args); + if(last_cmd_len > sizeof(send_buf)) + last_cmd_len = sizeof(send_buf); #ifdef AT_PRINT_RAW_CMD at_print_raw_cmd("sendline", send_buf, last_cmd_len); #endif - return rt_device_write(device, 0, send_buf, last_cmd_len); + return at_device_send(device, 0, send_buf, last_cmd_len); } rt_size_t at_vprintfln(rt_device_t device, const char *format, va_list args) { rt_size_t len; - len = at_vprintf(device, format, args); + last_cmd_len = vsnprintf(send_buf, sizeof(send_buf) - 2, format, args); + if(last_cmd_len > sizeof(send_buf) - 2) + last_cmd_len = sizeof(send_buf) - 2; + rt_memcpy(send_buf + last_cmd_len, "\r\n", 2); - rt_device_write(device, 0, "\r\n", 2); + len = last_cmd_len + 2; - return len + 2; +#ifdef AT_PRINT_RAW_CMD + at_print_raw_cmd("sendline", send_buf, len); +#endif + + return at_device_send(device, 0, send_buf, len); } From 25b9a3e321d78be07ed384d99a9fd23ef9db7c7d Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Thu, 8 Jul 2021 00:59:59 +0800 Subject: [PATCH 251/255] =?UTF-8?q?[bsp][stm32=20bluepill]=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/stm32f103-blue-pill/README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/bsp/stm32/stm32f103-blue-pill/README.md b/bsp/stm32/stm32f103-blue-pill/README.md index 8911c66fc1..e7627e64a1 100644 --- a/bsp/stm32/stm32f103-blue-pill/README.md +++ b/bsp/stm32/stm32f103-blue-pill/README.md @@ -238,6 +238,12 @@ Each peripheral supporting condition for this BSP is as follows: +### 3.9 How to create RT-Studio Project + +- [RT-Thread RTOS Tutorial #3 | Advanced Skills - YouTube](https://www.youtube.com/watch?v=k4-ArvvIiR8) + + + ## 4 **Advanced Features** This BSP only enables GPIO and USART1 by default. If you need more advanced features such as SPI, ADC, or to add software packages, you need to configure the BSP with RT-Thread [ENV tool](https://www.rt-thread.io/download.html?download=Env), as follows: @@ -292,7 +298,7 @@ Re-plug the USB cable and you will find a new serial (virtual com, 115200, 8-N-1 ### 4.2 How to extend Blue Pill board’s Flash space -According to ST official datasheet, STM32F103C8 has 64KB of Flash. However, STM32F103C8 and STM32F103CB use the same type of silicon die, which means STM32F103C8 also has 128KB ROM in theory, but ST locked the high 64KB. Basically, to force the debugger to download program can unlock the high 64KB. There is a good news that **Keil5 will help you to unlock the Blue Pill Board high 64KB block** if you use Blue Pill Board BSP as a template to create your project. You just need to press the "Flash Download" button as usual. What you only need to remember is that Blue Pill board has 128KB of Flash rather than 64KB. +According to ST official datasheet, STM32F103C8 has 64KB of Flash. However, STM32F103C8 and STM32F103CB use the same type of silicon die, which means STM32F103C8 also has 128KB ROM in theory, but ST locked the high 64KB. Basically, to force the debugger to download program can unlock the high 64KB. There is a good news that **Keil5 / IAR / RT-Studio will help you to unlock the Blue Pill Board high 64KB block** if you use this Blue Pill Board BSP as a template to create your project. You just need to press the "Flash Download" button as usual. What you only need to remember is that Blue Pill board has 128KB of Flash rather than 64KB. @@ -309,8 +315,7 @@ According to ST official datasheet, STM32F103C8 has 64KB of Flash. However, STM3 ## 6 Maintained By -Meco Man @ RT-Thread Community +[Meco Man](https://github.com/mysterywolf) @ RT-Thread Community jiantingman@foxmail.com -https://github.com/mysterywolf From 180d0e122499ad88f02558fdcab4a9e19b20bdbf Mon Sep 17 00:00:00 2001 From: malongwei <2544047213@qq.com> Date: Thu, 8 Jul 2021 12:02:29 +0800 Subject: [PATCH 252/255] add at_utils_send virtual function --- components/net/at/src/at_client.c | 16 +++++++++++++--- components/net/at/src/at_server.c | 6 +++++- components/net/at/src/at_utils.c | 12 ++++++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/components/net/at/src/at_client.c b/components/net/at/src/at_client.c index b320072b00..7904c24d92 100644 --- a/components/net/at/src/at_client.c +++ b/components/net/at/src/at_client.c @@ -8,7 +8,7 @@ * 2018-03-30 chenyong first version * 2018-04-12 chenyong add client implement * 2018-08-17 chenyong multiple client support - * 2021-03-17 Meco Man fix a buf of leaking memory + * 2021-03-17 Meco Man fix a buf of leaking memory */ #include @@ -28,6 +28,10 @@ static struct at_client at_client_table[AT_CLIENT_NUM_MAX] = { 0 }; +extern rt_size_t at_utils_send(rt_device_t dev, + rt_off_t pos, + const void *buffer, + rt_size_t size); extern rt_size_t at_vprintfln(rt_device_t device, const char *format, va_list args); extern void at_print_raw_cmd(const char *type, const char *cmd, rt_size_t size); extern const char *at_get_last_cmd(rt_size_t *cmd_size); @@ -392,7 +396,7 @@ int at_client_obj_wait_connect(at_client_t client, rt_uint32_t timeout) /* Check whether it is already connected */ resp->buf_len = 0; resp->line_counts = 0; - rt_device_write(client->device, 0, "AT\r\n", 4); + at_utils_send(client->device, 0, "AT\r\n", 4); if (rt_sem_take(client->resp_notice, resp->timeout) != RT_EOK) continue; @@ -433,7 +437,13 @@ rt_size_t at_client_obj_send(at_client_t client, const char *buf, rt_size_t size at_print_raw_cmd("sendline", buf, size); #endif - return rt_device_write(client->device, 0, buf, size); + rt_mutex_take(client->lock, RT_WAITING_FOREVER); + + rt_size_t len = at_utils_send(client->device, 0, buf, size); + + rt_mutex_release(client->lock); + + return len; } static rt_err_t at_client_getchar(at_client_t client, char *ch, rt_int32_t timeout) diff --git a/components/net/at/src/at_server.c b/components/net/at/src/at_server.c index 71435da25b..1db26a260b 100644 --- a/components/net/at/src/at_server.c +++ b/components/net/at/src/at_server.c @@ -38,6 +38,10 @@ static at_server_t at_server_local = RT_NULL; static at_cmd_t cmd_table = RT_NULL; static rt_size_t cmd_num; +extern rt_size_t at_utils_send(rt_device_t dev, + rt_off_t pos, + const void *buffer, + rt_size_t size); extern void at_vprintf(rt_device_t device, const char *format, va_list args); extern void at_vprintfln(rt_device_t device, const char *format, va_list args); @@ -187,7 +191,7 @@ rt_size_t at_server_send(at_server_t server, const char *buf, rt_size_t size) return 0; } - return rt_device_write(server->device, 0, buf, size); + return at_utils_send(server->device, 0, buf, size); } /** diff --git a/components/net/at/src/at_utils.c b/components/net/at/src/at_utils.c index d75ee0990e..028f262566 100644 --- a/components/net/at/src/at_utils.c +++ b/components/net/at/src/at_utils.c @@ -65,6 +65,14 @@ const char *at_get_last_cmd(rt_size_t *cmd_size) return send_buf; } +RT_WEAK rt_size_t at_utils_send(rt_device_t dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + return rt_device_write(dev, pos, buffer, size); +} + rt_size_t at_vprintf(rt_device_t device, const char *format, va_list args) { last_cmd_len = vsnprintf(send_buf, sizeof(send_buf), format, args); @@ -75,7 +83,7 @@ rt_size_t at_vprintf(rt_device_t device, const char *format, va_list args) at_print_raw_cmd("sendline", send_buf, last_cmd_len); #endif - return at_device_send(device, 0, send_buf, last_cmd_len); + return at_utils_send(device, 0, send_buf, last_cmd_len); } rt_size_t at_vprintfln(rt_device_t device, const char *format, va_list args) @@ -93,5 +101,5 @@ rt_size_t at_vprintfln(rt_device_t device, const char *format, va_list args) at_print_raw_cmd("sendline", send_buf, len); #endif - return at_device_send(device, 0, send_buf, len); + return at_utils_send(device, 0, send_buf, len); } From 3bc6d7c41434c2007f7ba110e209ce470f1ed046 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 8 Jul 2021 13:38:29 +0800 Subject: [PATCH 253/255] =?UTF-8?q?[utestcase]=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B=E9=9B=86=E5=90=88=E7=9A=84?= =?UTF-8?q?=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/utest/README.md | 18 ++++++------------ examples/utest/configs/kernel/mem.conf | 4 +++- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/examples/utest/README.md b/examples/utest/README.md index cc84651966..bde3bd4b80 100644 --- a/examples/utest/README.md +++ b/examples/utest/README.md @@ -54,26 +54,20 @@ msh />utest_run ### 3. 提交 -1. 如果是对已有测试集合的完善,需要把添加的测试用例的配置项添加到对应测试集合的配置文件里,如:[examples\utest\configs\utest_self\config.h](./configs/utest_self/config.h)。 +1. 如果是对已有测试集合的完善,需要把添加的测试用例的配置项,以及对应的依赖项添加到对应测试集合的配置文件里,如:[examples\utest\configs\kernel\mem.conf](./configs/kernel/mem.conf)。 ``` -/* RT-Thread Utestcases */ +CONFIG_UTEST_MEMHEAP_TC=y -#define RT_USING_UTESTCASES - -/* Utest Self Testcase */ - -#define UTEST_SELF_PASS_TC - -/* xxx Testcase */ -#define UTEST_XXX_TC +# dependencies +CONFIG_RT_USING_MEMHEAP=y ``` 2. 如果要添加新的测试集合,需要参考已有的测试集合,在 [examples\utest\configs](./configs) 目录下添加新的测试集合配置项。并更新 [.github\workflows\action_utest.yml](../../.github/workflows/action_utest.yml) 内的测试集合。 ``` -- {UTEST: "kernel/ipc", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"} -- {UTEST: "components/utest", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"} +- {UTEST: "kernel/mem", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "kernel/mem.conf", SD_FILE: "sd.bin"} +- {UTEST: "components/utest", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "utest_self/self.conf", SD_FILE: "sd.bin"} ``` 3. 向 RT-Thread 主仓库提交合并请求。 \ No newline at end of file diff --git a/examples/utest/configs/kernel/mem.conf b/examples/utest/configs/kernel/mem.conf index 80a0259a4c..1a311ab9dd 100644 --- a/examples/utest/configs/kernel/mem.conf +++ b/examples/utest/configs/kernel/mem.conf @@ -1,2 +1,4 @@ -CONFIG_RT_USING_MEMHEAP=y CONFIG_UTEST_MEMHEAP_TC=y + +# dependencies +CONFIG_RT_USING_MEMHEAP=y From 8102502b9815843bec2154b607c4f299ce179d97 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 8 Jul 2021 16:37:07 +0800 Subject: [PATCH 254/255] [devfs] F_GETFL/F_SETFL should be handled by the drivers. --- components/dfs/src/dfs_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dfs/src/dfs_file.c b/components/dfs/src/dfs_file.c index 802311b54e..fa0f6000b4 100644 --- a/components/dfs/src/dfs_file.c +++ b/components/dfs/src/dfs_file.c @@ -157,7 +157,7 @@ int dfs_file_ioctl(struct dfs_fd *fd, int cmd, void *args) return -EINVAL; /* regular file system fd */ - if (fd->type == FT_REGULAR || fd->type == FT_DEVICE) + if (fd->type == FT_REGULAR) { switch (cmd) { From 9f3e349f69c66fb27496492d0f0c3cefa0bb891b Mon Sep 17 00:00:00 2001 From: chenjh Date: Fri, 9 Jul 2021 10:54:51 +0800 Subject: [PATCH 255/255] [comment] Optimize the comment for ipc --- src/ipc.c | 1079 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 848 insertions(+), 231 deletions(-) diff --git a/src/ipc.c b/src/ipc.c index 6bc9c079b9..8acfd831d7 100755 --- a/src/ipc.c +++ b/src/ipc.c @@ -57,11 +57,16 @@ extern void (*rt_object_put_hook)(struct rt_object *object); /**@{*/ /** - * This function will initialize an IPC object + * @brief This function will initialize an IPC object, such as semaphore, mutex, messagequeue and mailbox. * - * @param ipc the IPC object + * @note Executing this function will complete an initialization of the suspend thread list of the ipc object. * - * @return the operation status, RT_EOK on successful + * @param ipc is a pointer to the IPC object. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * When the return value is any other values, it means the initialization failed. + * + * @warning This function can be called from all IPC initialization and creation. */ rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc) { @@ -71,16 +76,35 @@ rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc) return RT_EOK; } + /** - * This function will suspend a thread to a specified list. IPC object or some - * double-queue object (mailbox etc.) contains this kind of list. + * @brief This function will suspend a thread to a IPC object list. * - * @param list the IPC suspended thread list - * @param thread the thread object to be suspended - * @param flag the IPC object flag, - * which shall be RT_IPC_FLAG_FIFO/RT_IPC_FLAG_PRIO. + * @param list is a pointer to a suspended thread list of the IPC object. * - * @return the operation status, RT_EOK on successful + * @param thread is a pointer to the thread object to be suspended. + * + * @param flag is a flag for the thread object to be suspended. It determines how the thread is suspended. + * The flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to use + * RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this semaphore will become non-real-time threads. + * + * @return Return the operation status. When the return value is RT_EOK, the function is successfully executed. + * When the return value is any other values, it means the initialization failed. + * + * @warning This function can ONLY be called in the thread context, you can use RT_DEBUG_IN_THREAD_CONTEXT to + * check the context. + * In addition, this function is generally called by the following functions: + * rt_sem_take(), rt_mutex_take(), rt_event_recv(), rt_mb_send_wait(), + * rt_mb_recv(), rt_mq_recv(), rt_mq_send_wait() */ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list, struct rt_thread *thread, @@ -131,14 +155,25 @@ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list, return RT_EOK; } + /** - * This function will resume the first thread in the list of a IPC object: - * - remove the thread from suspend queue of IPC object - * - put the thread into system ready queue + * @brief This function will resume a thread. * - * @param list the thread list + * @note This function will resume the first thread in the list of a IPC object. + * 1. remove the thread from suspend queue of a IPC object. + * 2. put the thread into system ready queue. * - * @return the operation status, RT_EOK on successful + * By contrast, the rt_ipc_list_resume_all() function will resume all suspended threads + * in the list of a IPC object. + * + * @param list is a pointer to a suspended thread list of the IPC object. + * + * @return Return the operation status. When the return value is RT_EOK, the function is successfully executed. + * When the return value is any other values, it means this operation failed. + * + * @warning This function is generally called by the following functions: + * rt_sem_release(), rt_mutex_release(), rt_mb_send_wait(), rt_mq_send_wait(), + * rt_mb_urgent(), rt_mb_recv(), rt_mq_urgent(), rt_mq_recv(), */ rt_inline rt_err_t rt_ipc_list_resume(rt_list_t *list) { @@ -155,13 +190,19 @@ rt_inline rt_err_t rt_ipc_list_resume(rt_list_t *list) return RT_EOK; } + /** - * This function will resume all suspended threads in a list, including - * suspend list of IPC object and private list of mailbox etc. + * @brief This function will resume all suspended threads in the IPC object list, + * including the suspended list of IPC object, and private list of mailbox etc. * - * @param list of the threads to resume + * @note This function will resume all threads in the IPC object list. + * By contrast, the rt_ipc_list_resume() function will resume a suspended thread in the list of a IPC object. + * + * @param list is a pointer to a suspended thread list of the IPC object. + * + * @return Return the operation status. When the return value is RT_EOK, the function is successfully executed. + * When the return value is any other values, it means this operation failed. * - * @return the operation status, RT_EOK on successful */ rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list) { @@ -193,17 +234,51 @@ rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list) return RT_EOK; } +/**@}*/ + #ifdef RT_USING_SEMAPHORE /** - * This function will initialize a semaphore and put it under control of - * resource management. + * @addtogroup semaphore + */ + +/**@{*/ +/** + * @brief This function will initialize a static semaphore object. * - * @param sem the semaphore object - * @param name the name of semaphore - * @param value the initial value of semaphore - * @param flag the flag of semaphore + * @note For the static semaphore object, its memory space is allocated by the compiler during compiling, + * and shall placed on the read-write data segment or on the uninitialized data segment. + * By contrast, the rt_sem_create() function will allocate memory space automatically and initialize + * the semaphore. * - * @return the operation status, RT_EOK on successful + * @see rt_sem_create() + * + * @param sem is a pointer to the semaphore to initialize. It is assumed that storage for the semaphore will be + * allocated in your application. + * + * @param name is a pointer to the name you would like to give the semaphore. + * + * @param value is the initial value for the semaphore. + * If used to share resources, you should initialize the value as the number of available resources. + * If used to signal the occurrence of an event, you should initialize the value as 0. + * + * @param flag is the semaphore flag, which determines the queuing way of how multiple threads wait + * when the semaphore is not available. + * The semaphore flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this semaphore will become non-real-time threads. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it represents the initialization failed. + * + * @warning This function can ONLY be called from threads. */ rt_err_t rt_sem_init(rt_sem_t sem, const char *name, @@ -229,14 +304,24 @@ rt_err_t rt_sem_init(rt_sem_t sem, } RTM_EXPORT(rt_sem_init); + /** - * This function will detach a semaphore from resource management + * @brief This function will detach a static semaphore object. * - * @param sem the semaphore object + * @note This function is used to detach a static semaphore object which is initialized by rt_sem_init() function. + * By contrast, the rt_sem_delete() function will delete a semaphore object. + * When the semaphore is successfully detached, it will resume all suspended threads in the semaphore list. * - * @return the operation status, RT_EOK on successful + * @see rt_sem_delete() * - * @see rt_sem_delete + * @param sem is a pointer to a semaphore object to be detached. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it means that the semaphore detach failed. + * + * @warning This function can ONLY detach a static semaphore initialized by the rt_sem_init() function. + * If the semaphore is created by the rt_sem_create() function, you MUST NOT USE this function to detach it, + * ONLY USE the rt_sem_delete() function to complete the deletion. */ rt_err_t rt_sem_detach(rt_sem_t sem) { @@ -257,15 +342,36 @@ RTM_EXPORT(rt_sem_detach); #ifdef RT_USING_HEAP /** - * This function will create a semaphore from system resource + * @brief Creating a semaphore object. * - * @param name the name of semaphore - * @param value the initial value of semaphore - * @param flag the flag of semaphore + * @note For the semaphore object, its memory space is allocated automatically. + * By contrast, the rt_sem_init() function will initialize a static semaphore object. * - * @return the created semaphore, RT_NULL on error happen + * @see rt_sem_init() * - * @see rt_sem_init + * @param name is a pointer to the name you would like to give the semaphore. + * + * @param value is the initial value for the semaphore. + * If used to share resources, you should initialize the value as the number of available resources. + * If used to signal the occurrence of an event, you should initialize the value as 0. + * + * @param flag is the semaphore flag, which determines the queuing way of how multiple threads wait + * when the semaphore is not available. + * The semaphore flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this semaphore will become non-real-time threads. + * + * @return Return a pointer to the semaphore object. When the return value is RT_NULL, it means the creation failed. + * + * @warning This function can NOT be called in interrupt context. You can use macor RT_DEBUG_NOT_IN_INTERRUPT to check it. */ rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag) { @@ -292,14 +398,24 @@ rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag) } RTM_EXPORT(rt_sem_create); + /** - * This function will delete a semaphore object and release the memory + * @brief This function will delete a semaphore object and release the memory space. * - * @param sem the semaphore object + * @note This function is used to delete a semaphore object which is created by the rt_sem_create() function. + * By contrast, the rt_sem_detach() function will detach a static semaphore object. + * When the semaphore is successfully deleted, it will resume all suspended threads in the semaphore list. * - * @return the error code + * @see rt_sem_detach() * - * @see rt_sem_detach + * @param sem is a pointer to a semaphore object to be deleted. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the semaphore detach failed. + * + * @warning This function can ONLY delete a semaphore initialized by the rt_sem_create() function. + * If the semaphore is initialized by the rt_sem_init() function, you MUST NOT USE this function to delete it, + * ONLY USE the rt_sem_detach() function to complete the detachment. */ rt_err_t rt_sem_delete(rt_sem_t sem) { @@ -321,14 +437,29 @@ rt_err_t rt_sem_delete(rt_sem_t sem) RTM_EXPORT(rt_sem_delete); #endif /* RT_USING_HEAP */ + /** - * This function will take a semaphore, if the semaphore is unavailable, the - * thread shall wait for a specified time. + * @brief This function will take a semaphore, if the semaphore is unavailable, the thread shall wait for + * the semaphore up to a specified time. * - * @param sem the semaphore object - * @param time the waiting time + * @note When this function is called, the count value of the sem->value will decrease 1 until it is equal to 0. + * When the sem->value is 0, it means that the semaphore is unavailable. At this time, it will suspend the + * thread preparing to take the semaphore. + * On the contrary, the rt_sem_release() function will increase the count value of sem->value by 1 each time. * - * @return the error code + * @see rt_sem_trytake() + * + * @param sem is a pointer to a semaphore object. + * + * @param time is a timeout period (unit: an OS tick). If the semaphore is unavailable, the thread will wait for + * the semaphore up to the amount of time specified by the argument. + * NOTE: Generally, we use the macro RT_WAITING_FOREVER to set this parameter, which means that when the + * semaphore is unavailable, the thread will be waitting forever. + * + * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the semaphore take failed. + * + * @warning This function can ONLY be called in the thread context. It MUST NOT BE called in interrupt context. */ rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time) { @@ -418,12 +549,20 @@ rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time) } RTM_EXPORT(rt_sem_take); + /** - * This function will try to take a semaphore and immediately return + * @brief This function will try to take a semaphore, if the semaphore is unavailable, the thread returns immediately. * - * @param sem the semaphore object + * @note This function is very similar to the rt_sem_take() function, when the semaphore is not available, + * the rt_sem_trytake() function will return immediately without waiting for a timeout. + * In other words, rt_sem_trytake(sem) has the same effect as rt_sem_take(sem, 0). * - * @return the error code + * @see rt_sem_take() + * + * @param sem is a pointer to a semaphore object. + * + * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the semaphore take failed. */ rt_err_t rt_sem_trytake(rt_sem_t sem) { @@ -431,13 +570,18 @@ rt_err_t rt_sem_trytake(rt_sem_t sem) } RTM_EXPORT(rt_sem_trytake); + /** - * This function will release a semaphore, if there are threads suspended on - * semaphore, it will be waked up. + * @brief This function will release a semaphore. If there is thread suspended on the semaphore, it will get resumed. * - * @param sem the semaphore object + * @note If there are threads suspended on this semaphore, the first thread in the list of this semaphore object + * will be resumed, and a thread scheduling (rt_schedule) will be executed. + * If no threads are suspended on this semaphore, the count value sem->value of this semaphore will increase by 1. * - * @return the error code + * @param sem is a pointer to a semaphore object. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the semaphore release failed. */ rt_err_t rt_sem_release(rt_sem_t sem) { @@ -490,14 +634,20 @@ rt_err_t rt_sem_release(rt_sem_t sem) } RTM_EXPORT(rt_sem_release); + /** - * This function can get or set some extra attributions of a semaphore object. + * @brief This function will set some extra attributions of a semaphore object. * - * @param sem the semaphore object - * @param cmd the execution command - * @param arg the execution argument + * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the semaphore. * - * @return the error code + * @param sem is a pointer to a semaphore object. + * + * @param cmd is a command word used to configure some attributions of the semaphore. + * + * @param arg is the argument of the function to execute the command. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that this function failed to execute. */ rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg) { @@ -533,18 +683,41 @@ rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_sem_control); + +/**@}*/ #endif /* RT_USING_SEMAPHORE */ #ifdef RT_USING_MUTEX /** - * This function will initialize a mutex and put it under control of resource - * management. + * @addtogroup mutex + */ + +/**@{*/ + +/** + * @brief Initialize a static mutex object. * - * @param mutex the mutex object - * @param name the name of mutex - * @param flag the flag of mutex + * @note For the static mutex object, its memory space is allocated by the compiler during compiling, + * and shall placed on the read-write data segment or on the uninitialized data segment. + * By contrast, the rt_mutex_create() function will automatically allocate memory space + * and initialize the mutex. * - * @return the operation status, RT_EOK on successful + * @see rt_mutex_create() + * + * @param mutex is a pointer to the mutex to initialize. It is assumed that storage for the mutex will be + * allocated in your application. + * + * @param name is a pointer to the name that given to the mutex. + * + * @param flag is the mutex flag, which determines the queuing way of how multiple threads wait + * when the mutex is not available. + * NOTE: The mutex flag can ONLY be RT_IPC_FLAG_PRIO. Using RT_IPC_FLAG_FIFO will seriously affect + * the real-time performance of the system. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it represents the initialization failed. + * + * @warning This function can ONLY be called from threads. */ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) { @@ -571,14 +744,24 @@ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) } RTM_EXPORT(rt_mutex_init); + /** - * This function will detach a mutex from resource management + * @brief This function will detach a static mutex object. * - * @param mutex the mutex object + * @note This function is used to detach a static mutex object which is initialized by rt_mutex_init() function. + * By contrast, the rt_mutex_delete() function will delete a mutex object. + * When the mutex is successfully detached, it will resume all suspended threads in the mutex list. * - * @return the operation status, RT_EOK on successful + * @see rt_mutex_delete() * - * @see rt_mutex_delete + * @param mutex is a pointer to a mutex object to be detached. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it means that the mutex detach failed. + * + * @warning This function can ONLY detach a static mutex initialized by the rt_mutex_init() function. + * If the mutex is created by the rt_mutex_create() function, you MUST NOT USE this function to detach it, + * ONLY USE the rt_mutex_delete() function to complete the deletion. */ rt_err_t rt_mutex_detach(rt_mutex_t mutex) { @@ -599,14 +782,23 @@ RTM_EXPORT(rt_mutex_detach); #ifdef RT_USING_HEAP /** - * This function will create a mutex from system resource + * @brief This function will create a mutex object. * - * @param name the name of mutex - * @param flag the flag of mutex + * @note For the mutex object, its memory space is automatically allocated. + * By contrast, the rt_mutex_init() function will initialize a static mutex object. * - * @return the created mutex, RT_NULL on error happen + * @see rt_mutex_init() * - * @see rt_mutex_init + * @param name is a pointer to the name that given to the mutex. + * + * @param flag is the mutex flag, which determines the queuing way of how multiple threads wait + * when the mutex is not available. + * NOTE: The mutex flag can ONLY be RT_IPC_FLAG_PRIO. Using RT_IPC_FLAG_FIFO will seriously affect + * the real-time performance of the system. + * + * @return Return a pointer to the mutex object. When the return value is RT_NULL, it means the creation failed. + * + * @warning This function can ONLY be called from threads. */ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) { @@ -635,14 +827,24 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) } RTM_EXPORT(rt_mutex_create); + /** - * This function will delete a mutex object and release the memory + * @brief This function will delete a mutex object and release this memory space. * - * @param mutex the mutex object + * @note This function is used to delete a mutex object which is created by the rt_mutex_create() function. + * By contrast, the rt_mutex_detach() function will detach a static mutex object. + * When the mutex is successfully deleted, it will resume all suspended threads in the mutex list. * - * @return the error code + * @see rt_mutex_detach() * - * @see rt_mutex_detach + * @param mutex is a pointer to a mutex object to be deleted. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mutex detach failed. + * + * @warning This function can ONLY delete a mutex initialized by the rt_mutex_create() function. + * If the mutex is initialized by the rt_mutex_init() function, you MUST NOT USE this function to delete it, + * ONLY USE the rt_mutex_detach() function to complete the detachment. */ rt_err_t rt_mutex_delete(rt_mutex_t mutex) { @@ -664,14 +866,29 @@ rt_err_t rt_mutex_delete(rt_mutex_t mutex) RTM_EXPORT(rt_mutex_delete); #endif /* RT_USING_HEAP */ + /** - * This function will take a mutex, if the mutex is unavailable, the - * thread shall wait for a specified time. + * @brief This function will take a mutex, if the mutex is unavailable, the thread shall wait for + * the mutex up to a specified time. * - * @param mutex the mutex object - * @param time the waiting time + * @note When this function is called, the count value of the sem->value will decrease 1 until it is equal to 0. + * When the sem->value is 0, it means that the mutex is unavailable. At this time, it will suspend the + * thread preparing to take the mutex. + * On the contrary, the rt_sem_release() function will increase the count value of sem->value by 1 each time. * - * @return the error code + * @see rt_mutex_trytake() + * + * @param mutex is a pointer to a mutex object. + * + * @param time is a timeout period (unit: an OS tick). If the mutex is unavailable, the thread will wait for + * the mutex up to the amount of time specified by the argument. + * NOTE: Generally, we set this parameter to RT_WAITING_FOREVER, which means that when the mutex is unavailable, + * the thread will be waitting forever. + * + * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mutex take failed. + * + * @warning This function can ONLY be called in the thread context. It MUST NOT BE called in interrupt context. */ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time) { @@ -821,12 +1038,21 @@ __again: } RTM_EXPORT(rt_mutex_take); + /** - * This function will try to take a mutex and immediately return + * @brief This function will try to take a mutex, if the mutex is unavailable, the thread returns immediately. * - * @param mutex the mutex object + * @note This function is very similar to the rt_mutex_take() function, when the mutex is not available, + * except that rt_mutex_trytake() will return immediately without waiting for a timeout + * when the mutex is not available. + * In other words, rt_mutex_trytake(mutex) has the same effect as rt_mutex_take(mutex, 0). * - * @return the error code + * @see rt_mutex_take() + * + * @param mutex is a pointer to a mutex object. + * + * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mutex take failed. */ rt_err_t rt_mutex_trytake(rt_mutex_t mutex) { @@ -834,13 +1060,18 @@ rt_err_t rt_mutex_trytake(rt_mutex_t mutex) } RTM_EXPORT(rt_mutex_trytake); + /** - * This function will release a mutex, if there are threads suspended on mutex, - * it will be waked up. + * @brief This function will release a mutex. If there is thread suspended on the mutex, the thread will be resumed. * - * @param mutex the mutex object + * @note If there are threads suspended on this mutex, the first thread in the list of this mutex object + * will be resumed, and a thread scheduling (rt_schedule) will be executed. + * If no threads are suspended on this mutex, the count value mutex->value of this mutex will increase by 1. * - * @return the error code + * @param mutex is a pointer to a mutex object. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mutex release failed. */ rt_err_t rt_mutex_release(rt_mutex_t mutex) { @@ -953,14 +1184,20 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) } RTM_EXPORT(rt_mutex_release); + /** - * This function can get or set some extra attributions of a mutex object. + * @brief This function will set some extra attributions of a mutex object. * - * @param mutex the mutex object - * @param cmd the execution command - * @param arg the execution argument + * @note Currently this function does not implement the control function. * - * @return the error code + * @param mutex is a pointer to a mutex object. + * + * @param cmd is a command word used to configure some attributions of the mutex. + * + * @param arg is the argument of the function to execute the command. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that this function failed to execute. */ rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg) { @@ -971,18 +1208,54 @@ rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_mutex_control); + +/**@}*/ #endif /* RT_USING_MUTEX */ #ifdef RT_USING_EVENT /** - * This function will initialize an event and put it under control of resource - * management. + * @addtogroup event + */ + +/**@{*/ + +/** + * @brief The function will initialize a static event object. * - * @param event the event object - * @param name the name of event - * @param flag the flag of event + * @note For the static event object, its memory space is allocated by the compiler during compiling, + * and shall placed on the read-write data segment or on the uninitialized data segment. + * By contrast, the rt_event_create() function will allocate memory space automatically + * and initialize the event. * - * @return the operation status, RT_EOK on successful + * @see rt_event_create() + * + * @param event is a pointer to the event to initialize. It is assumed that storage for the event + * will be allocated in your application. + * + * @param name is a pointer to the name that given to the event. + * + * @param value is the initial value for the event. + * If want to share resources, you should initialize the value as the number of available resources. + * If want to signal the occurrence of an event, you should initialize the value as 0. + * + * @param flag is the event flag, which determines the queuing way of how multiple threads wait + * when the event is not available. + * The event flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this event will become non-real-time threads. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it represents the initialization failed. + * + * @warning This function can ONLY be called from threads. */ rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag) { @@ -1005,12 +1278,24 @@ rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag) } RTM_EXPORT(rt_event_init); + /** - * This function will detach an event object from resource management + * @brief This function will detach a static event object. * - * @param event the event object + * @note This function is used to detach a static event object which is initialized by rt_event_init() function. + * By contrast, the rt_event_delete() function will delete an event object. + * When the event is successfully detached, it will resume all suspended threads in the event list. * - * @return the operation status, RT_EOK on successful + * @see rt_event_delete() + * + * @param event is a pointer to an event object to be detached. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it means that the event detach failed. + * + * @warning This function can ONLY detach a static event initialized by the rt_event_init() function. + * If the event is created by the rt_event_create() function, you MUST NOT USE this function to detach it, + * ONLY USE the rt_event_delete() function to complete the deletion. */ rt_err_t rt_event_detach(rt_event_t event) { @@ -1031,12 +1316,32 @@ RTM_EXPORT(rt_event_detach); #ifdef RT_USING_HEAP /** - * This function will create an event object from system resource + * @brief Creating an event object. * - * @param name the name of event - * @param flag the flag of event + * @note For the event object, its memory space is allocated automatically. + * By contrast, the rt_event_init() function will initialize a static event object. * - * @return the created event, RT_NULL on error happen + * @see rt_event_init() + * + * @param name is a pointer to the name that given to the event. + * + * @param flag is the event flag, which determines the queuing way of how multiple threads wait when the event + * is not available. + * The event flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this event will become non-real-time threads. + * + * @return Return a pointer to the event object. When the return value is RT_NULL, it means the creation failed. + * + * @warning This function can ONLY be called from threads. */ rt_event_t rt_event_create(const char *name, rt_uint8_t flag) { @@ -1062,12 +1367,24 @@ rt_event_t rt_event_create(const char *name, rt_uint8_t flag) } RTM_EXPORT(rt_event_create); + /** - * This function will delete an event object and release the memory + * @brief This function will delete an event object and release the memory space. * - * @param event the event object + * @note This function is used to delete an event object which is created by the rt_event_create() function. + * By contrast, the rt_event_detach() function will detach a static event object. + * When the event is successfully deleted, it will resume all suspended threads in the event list. * - * @return the error code + * @see rt_event_detach() + * + * @param event is a pointer to an event object to be deleted. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the event detach failed. + * + * @warning This function can ONLY delete an event initialized by the rt_event_create() function. + * If the event is initialized by the rt_event_init() function, you MUST NOT USE this function to delete it, + * ONLY USE the rt_event_detach() function to complete the detachment. */ rt_err_t rt_event_delete(rt_event_t event) { @@ -1089,14 +1406,23 @@ rt_err_t rt_event_delete(rt_event_t event) RTM_EXPORT(rt_event_delete); #endif /* RT_USING_HEAP */ + /** - * This function will send an event to the event object, if there are threads - * suspended on event object, it will be waked up. + * @brief This function will send an event to the event object. + * If there is a thread suspended on the event, the thread will be resumed. * - * @param event the event object - * @param set the event set + * @note When using this function, you need to use the parameter (set) to specify the event flag of the event object, + * then the function will traverse the list of suspended threads waiting on the event object. + * If there is a thread suspended on the event, and the thread's event_info and the event flag of + * the current event object matches, the thread will be resumed. * - * @return the error code + * @param event is a pointer to the event object to be sent. + * + * @param set is a flag that you will set for this event's flag. + * You can set an event flag, or you can set multiple flags through OR logic operation. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the event detach failed. */ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set) { @@ -1190,18 +1516,38 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set) } RTM_EXPORT(rt_event_send); + /** - * This function will receive an event from event object, if the event is - * unavailable, the thread shall wait for a specified time. + * @brief This function will receive an event from event object. if the event is unavailable, the thread shall wait for + * the event up to a specified time. * - * @param event the fast event object - * @param set the interested event set - * @param option the receive option, either RT_EVENT_FLAG_AND or - * RT_EVENT_FLAG_OR should be set. - * @param timeout the waiting time - * @param recved the received event, if you don't care, RT_NULL can be set. + * @note If there are threads suspended on this semaphore, the first thread in the list of this semaphore object + * will be resumed, and a thread scheduling (rt_schedule) will be executed. + * If no threads are suspended on this semaphore, the count value sem->value of this semaphore will increase by 1. * - * @return the error code + * @param event is a pointer to the event object to be received. + * + * @param set is a flag that you will set for this event's flag. + * You can set an event flag, or you can set multiple flags through OR logic operation. + * + * @param option is the option of this receiving event, it indicates how the receiving event is operated. + * The option can be one or more of the following values, When selecting multiple values,use logical OR to operate. + * (NOTE: RT_EVENT_FLAG_OR and RT_EVENT_FLAG_AND can only select one): + * + * + * RT_EVENT_FLAG_OR The thread select to use logical OR to receive the event. + * + * RT_EVENT_FLAG_AND The thread select to use logical OR to receive the event. + * + * RT_EVENT_FLAG_CLEAR When the thread receives the corresponding event, the function + * determines whether to clear the event flag. + * + * @param timeout is a timeout period (unit: an OS tick). + * + * @param recved is a pointer to the received event. If you don't care about this value, you can use RT_NULL to set. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the semaphore release failed. */ rt_err_t rt_event_recv(rt_event_t event, rt_uint32_t set, @@ -1325,14 +1671,20 @@ rt_err_t rt_event_recv(rt_event_t event, } RTM_EXPORT(rt_event_recv); + /** - * This function can get or set some extra attributions of an event object. + * @brief This function will set some extra attributions of an event object. * - * @param event the event object - * @param cmd the execution command - * @param arg the execution argument + * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the event. * - * @return the error code + * @param event is a pointer to an event object. + * + * @param cmd is a command word used to configure some attributions of the event. + * + * @param arg is the argument of the function to execute the command. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that this function failed to execute. */ rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg) { @@ -1364,20 +1716,55 @@ rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_event_control); + +/**@}*/ #endif /* RT_USING_EVENT */ #ifdef RT_USING_MAILBOX /** - * This function will initialize a mailbox and put it under control of resource - * management. + * @addtogroup mailbox + */ + +/**@{*/ + +/** + * @brief Initialize a static mailbox object. * - * @param mb the mailbox object - * @param name the name of mailbox - * @param msgpool the begin address of buffer to save received mail - * @param size the size of mailbox - * @param flag the flag of mailbox + * @note For the static mailbox object, its memory space is allocated by the compiler during compiling, + * and shall placed on the read-write data segment or on the uninitialized data segment. + * By contrast, the rt_mb_create() function will allocate memory space automatically and initialize the mailbox. * - * @return the operation status, RT_EOK on successful + * @see rt_mb_create() + * + * @param mb is a pointer to the mailbox to initialize. + * It is assumed that storage for the mailbox will be allocated in your application. + * + * @param name is a pointer to the name that given to the mailbox. + * + * @param msgpoll is a pointer to the starting address of the memory space you allocated for the mailbox in advance. + * In other words, msgpoll is a pointer to the mailbox buffer of the starting address. + * + * @param size is the maximum number of mails in the mailbox. + * For example, when the mailbox buffer capacity is N, size is N/4. + * + * @param flag is the mailbox flag, which determines the queuing way of how multiple threads wait + * when the mailbox is not available. + * The mailbox flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this mailbox will become non-real-time threads. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it represents the initialization failed. + * + * @warning This function can ONLY be called from threads. */ rt_err_t rt_mb_init(rt_mailbox_t mb, const char *name, @@ -1410,12 +1797,24 @@ rt_err_t rt_mb_init(rt_mailbox_t mb, } RTM_EXPORT(rt_mb_init); + /** - * This function will detach a mailbox from resource management + * @brief This function will detach a static mailbox object. * - * @param mb the mailbox object + * @note This function is used to detach a static mailbox object which is initialized by rt_mb_init() function. + * By contrast, the rt_mb_delete() function will delete a mailbox object. + * When the mailbox is successfully detached, it will resume all suspended threads in the mailbox list. * - * @return the operation status, RT_EOK on successful + * @see rt_mb_delete() + * + * @param mb is a pointer to a mailbox object to be detached. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it means that the mailbox detach failed. + * + * @warning This function can ONLY detach a static mailbox initialized by the rt_mb_init() function. + * If the mailbox is created by the rt_mb_create() function, you MUST NOT USE this function to detach it, + * ONLY USE the rt_mb_delete() function to complete the deletion. */ rt_err_t rt_mb_detach(rt_mailbox_t mb) { @@ -1438,13 +1837,35 @@ RTM_EXPORT(rt_mb_detach); #ifdef RT_USING_HEAP /** - * This function will create a mailbox object from system resource + * @brief Creating a mailbox object. * - * @param name the name of mailbox - * @param size the size of mailbox - * @param flag the flag of mailbox + * @note For the mailbox object, its memory space is allocated automatically. + * By contrast, the rt_mb_init() function will initialize a static mailbox object. * - * @return the created mailbox, RT_NULL on error happen + * @see rt_mb_init() + * + * @param name is a pointer that given to the mailbox. + * + * @param size is the maximum number of mails in the mailbox. + * For example, when mailbox buffer capacity is N, size is N/4. + * + * @param flag is the mailbox flag, which determines the queuing way of how multiple threads wait + * when the mailbox is not available. + * The mailbox flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this mailbox will become non-real-time threads. + * + * @return Return a pointer to the mailbox object. When the return value is RT_NULL, it means the creation failed. + * + * @warning This function can ONLY be called from threads. */ rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag) { @@ -1484,12 +1905,24 @@ rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag) } RTM_EXPORT(rt_mb_create); + /** - * This function will delete a mailbox object and release the memory + * @brief This function will delete a mailbox object and release the memory space. * - * @param mb the mailbox object + * @note This function is used to delete a mailbox object which is created by the rt_mb_create() function. + * By contrast, the rt_mb_detach() function will detach a static mailbox object. + * When the mailbox is successfully deleted, it will resume all suspended threads in the mailbox list. * - * @return the error code + * @see rt_mb_detach() + * + * @param mb is a pointer to a mailbox object to be deleted. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox detach failed. + * + * @warning This function can only delete mailbox created by the rt_mb_create() function. + * If the mailbox is initialized by the rt_mb_init() function, you MUST NOT USE this function to delete it, + * ONLY USE the rt_mb_detach() function to complete the detachment. */ rt_err_t rt_mb_delete(rt_mailbox_t mb) { @@ -1517,15 +1950,29 @@ rt_err_t rt_mb_delete(rt_mailbox_t mb) RTM_EXPORT(rt_mb_delete); #endif /* RT_USING_HEAP */ + /** - * This function will send a mail to mailbox object. If the mailbox is full, - * current thread will be suspended until timeout. + * @brief This function will send an mail to the mailbox object. If there is a thread suspended on the mailbox, + * the thread will be resumed. * - * @param mb the mailbox object - * @param value the mail - * @param timeout the waiting time + * @note When using this function to send a mail, if the mailbox if fully used, the current thread will + * wait for a timeout. If the set timeout time is reached and there is still no space available, + * the sending thread will be resumed and an error code will be returned. + * By contrast, the rt_mb_send() function will return an error code immediately without waiting time + * when the mailbox if fully used. * - * @return the error code + * @see rt_mb_send() + * + * @param mb is a pointer to the mailbox object to be sent. + * + * @param value is a value to the content of the mail you want to send. + * + * @param timeout is a timeout period (unit: an OS tick). + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox detach failed. + * + * @warning This function can be called in interrupt context and thread context. */ rt_err_t rt_mb_send_wait(rt_mailbox_t mb, rt_ubase_t value, @@ -1657,15 +2104,23 @@ rt_err_t rt_mb_send_wait(rt_mailbox_t mb, } RTM_EXPORT(rt_mb_send_wait); + /** - * This function will send a mail to mailbox object, if there are threads - * suspended on mailbox object, it will be waked up. This function will return - * immediately, if you want blocking send, use rt_mb_send_wait instead. + * @brief This function will send an mail to the mailbox object. If there is a thread suspended on the mailbox, + * the thread will be resumed. * - * @param mb the mailbox object - * @param value the mail + * @note When using this function to send a mail, if the mailbox is fully used, this function will return an error + * code immediately without waiting time. + * By contrast, the rt_mb_send_wait() function is set a timeout to wait for the mail to be sent. * - * @return the error code + * @see rt_mb_send_wait() + * + * @param mb is a pointer to the mailbox object to be sent. + * + * @param value is a value to the content of the mail you want to send. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox detach failed. */ rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value) { @@ -1673,15 +2128,22 @@ rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value) } RTM_EXPORT(rt_mb_send); + /** - * This function will send an urgent mail to mailbox object, if there are threads - * suspended on mailbox object, it will be waked up. This function will return - * immediately. + * @brief This function will send an urgent mail to the mailbox object. * - * @param mb the mailbox object - * @param value the mail + * @note This function is almost the same as the rt_mb_send() function. The only difference is that + * when sending an urgent mail, the mail will be placed at the head of the mail queue so that + * the recipient can receive the urgent mail first. * - * @return the error code + * @see rt_mb_send() + * + * @param mb is a pointer to the mailbox object to be sent. + * + * @param value is the content of the mail you want to send. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox detach failed. */ rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value) { @@ -1738,15 +2200,24 @@ rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value) } RTM_EXPORT(rt_mb_urgent); + /** - * This function will receive a mail from mailbox object, if there is no mail - * in mailbox object, the thread shall wait for a specified time. + * @brief This function will receive a mail from mailbox object, if there is no mail in mailbox object, + * the thread shall wait for a specified time. * - * @param mb the mailbox object - * @param value the received mail will be saved in - * @param timeout the waiting time + * @note Only when there is mail in the mailbox, the receiving thread can get the mail immediately and + * return RT_EOK, otherwise the receiving thread will be suspended until the set timeout. If the mail + * is still not received within the specified time, it will return-RT_ETIMEOUT. * - * @return the error code + * @param mb is a pointer to the mailbox object to be received. + * + * @param value is a flag that you will set for this mailbox's flag. + * You can set an mailbox flag, or you can set multiple flags through OR logic operations. + * + * @param timeout is a timeout period (unit: an OS tick). + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox release failed. */ rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout) { @@ -1879,14 +2350,20 @@ rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout) } RTM_EXPORT(rt_mb_recv); + /** - * This function can get or set some extra attributions of a mailbox object. + * @brief This function will set some extra attributions of a mailbox object. * - * @param mb the mailbox object - * @param cmd the execution command - * @param arg the execution argument + * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the mailbox. * - * @return the error code + * @param mb is a pointer to a mailbox object. + * + * @param cmd is a command used to configure some attributions of the mailbox. + * + * @param arg is the argument of the function to execute the command. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that this function failed to execute. */ rt_err_t rt_mb_control(rt_mailbox_t mb, int cmd, void *arg) { @@ -1922,26 +2399,64 @@ rt_err_t rt_mb_control(rt_mailbox_t mb, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_mb_control); + +/**@}*/ #endif /* RT_USING_MAILBOX */ #ifdef RT_USING_MESSAGEQUEUE +/** + * @addtogroup messagequeue + */ + +/**@{*/ + struct rt_mq_message { struct rt_mq_message *next; }; + /** - * This function will initialize a message queue and put it under control of - * resource management. + * @brief Initialize a static messagequeue object. * - * @param mq the message object - * @param name the name of message queue - * @param msgpool the beginning address of buffer to save messages - * @param msg_size the maximum size of message - * @param pool_size the size of buffer to save messages - * @param flag the flag of message queue + * @note For the static messagequeue object, its memory space is allocated by the compiler during compiling, + * and shall placed on the read-write data segment or on the uninitialized data segment. + * By contrast, the rt_mq_create() function will allocate memory space automatically + * and initialize the messagequeue. * - * @return the operation status, RT_EOK on successful + * @see rt_mq_create() + * + * @param mq is a pointer to the messagequeue to initialize. It is assumed that storage for + * the messagequeue will be allocated in your application. + * + * @param name is a pointer to the name that given to the messagequeue. + * + * @param msgpool is a pointer to the starting address of the memory space you allocated for + * the messagequeue in advance. + * In other words, msgpool is a pointer to the messagequeue buffer of the starting address. + * + * @param msg_size is the maximum length of a message in the messagequeue (Unit: Byte). + * + * @param pool_size is the size of the memory space allocated for the messagequeue in advance. + * + * @param flag is the messagequeue flag, which determines the queuing way of how multiple threads wait + * when the messagequeue is not available. + * The messagequeue flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this messagequeue will become non-real-time threads. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it represents the initialization failed. + * + * @warning This function can ONLY be called from threads. */ rt_err_t rt_mq_init(rt_mq_t mq, const char *name, @@ -1996,12 +2511,24 @@ rt_err_t rt_mq_init(rt_mq_t mq, } RTM_EXPORT(rt_mq_init); + /** - * This function will detach a message queue object from resource management + * @brief This function will detach a static messagequeue object. * - * @param mq the message queue object + * @note This function is used to detach a static messagequeue object which is initialized by rt_mq_init() function. + * By contrast, the rt_mq_delete() function will delete a messagequeue object. + * When the messagequeue is successfully detached, it will resume all suspended threads in the messagequeue list. * - * @return the operation status, RT_EOK on successful + * @see rt_mq_delete() + * + * @param mq is a pointer to a messagequeue object to be detached. + * + * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. + * If the return value is any other values, it means that the messagequeue detach failed. + * + * @warning This function can ONLY detach a static messagequeue initialized by the rt_mq_init() function. + * If the messagequeue is created by the rt_mq_create() function, you MUST NOT USE this function to detach it, + * and ONLY USE the rt_mq_delete() function to complete the deletion. */ rt_err_t rt_mq_detach(rt_mq_t mq) { @@ -2024,14 +2551,36 @@ RTM_EXPORT(rt_mq_detach); #ifdef RT_USING_HEAP /** - * This function will create a message queue object from system resource + * @brief Creating a messagequeue object. * - * @param name the name of message queue - * @param msg_size the size of message - * @param max_msgs the maximum number of message in queue - * @param flag the flag of message queue + * @note For the messagequeue object, its memory space is allocated automatically. + * By contrast, the rt_mq_init() function will initialize a static messagequeue object. * - * @return the created message queue, RT_NULL on error happen + * @see rt_mq_init() + * + * @param name is a pointer that given to the messagequeue. + * + * @param msg_size is the maximum length of a message in the messagequeue (Unit: Byte). + * + * @param max_msgs is the maximum number of messages in the messagequeue. + * + * @param flag is the messagequeue flag, which determines the queuing way of how multiple threads wait + * when the messagequeue is not available. + * The messagequeue flag can be ONE of the following values: + * + * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority. + * + * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method + * (also known as first-come-first-served (FCFS) scheduling strategy). + * + * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to + * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about + * the first-in-first-out principle, and you clearly understand that all threads involved in + * this messagequeue will become non-real-time threads. + * + * @return Return a pointer to the messagequeue object. When the return value is RT_NULL, it means the creation failed. + * + * @warning This function can NOT be called in interrupt context. You can use macor RT_DEBUG_NOT_IN_INTERRUPT to check it. */ rt_mq_t rt_mq_create(const char *name, rt_size_t msg_size, @@ -2094,12 +2643,25 @@ rt_mq_t rt_mq_create(const char *name, } RTM_EXPORT(rt_mq_create); + /** - * This function will delete a message queue object and release the memory + * @brief This function will delete a messagequeue object and release the memory. * - * @param mq the message queue object + * @note This function is used to delete a messagequeue object which is created by the rt_mq_create() function. + * By contrast, the rt_mq_detach() function will detach a static messagequeue object. + * When the messagequeue is successfully deleted, it will resume all suspended threads in the messagequeue list. * - * @return the error code + * @see rt_mq_detach() + * + * @param mq is a pointer to a messagequeue object to be deleted. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the messagequeue detach failed. + * + * @warning This function can ONLY delete a messagequeue initialized by the rt_mq_create() function. + * If the messagequeue is initialized by the rt_mq_init() function, you MUST NOT USE this function to delete it, + * ONLY USE the rt_mq_detach() function to complete the detachment. + * for example,the rt_mq_create() function, it cannot be called in interrupt context. */ rt_err_t rt_mq_delete(rt_mq_t mq) { @@ -2126,16 +2688,35 @@ rt_err_t rt_mq_delete(rt_mq_t mq) RTM_EXPORT(rt_mq_delete); #endif /* RT_USING_HEAP */ + /** - * This function will send a message to message queue object. If the message queue is full, - * current thread will be suspended until timeout. + * @brief This function will send a message to the messagequeue object. If + * there is a thread suspended on the messagequeue, the thread will be + * resumed. * - * @param mq the message queue object - * @param buffer the message - * @param size the size of buffer - * @param timeout the waiting time + * @note When using this function to send a message, if the messagequeue is + * fully used, the current thread will wait for a timeout. If reaching + * the timeout and there is still no space available, the sending + * thread will be resumed and an error code will be returned. By + * contrast, the rt_mq_send() function will return an error code + * immediately without waiting when the messagequeue if fully used. * - * @return the error code + * @see rt_mq_send() + * + * @param mq is a pointer to the messagequeue object to be sent. + * + * @param buffer is the content of the message. + * + * @param size is the length of the message(Unit: Byte). + * + * @param timeout is a timeout period (unit: an OS tick). + * + * @return Return the operation status. When the return value is RT_EOK, the + * operation is successful. If the return value is any other values, + * it means that the messagequeue detach failed. + * + * @warning This function can be called in interrupt context and thread + * context. */ rt_err_t rt_mq_send_wait(rt_mq_t mq, const void *buffer, @@ -2298,15 +2879,28 @@ rt_err_t rt_mq_send_wait(rt_mq_t mq, } RTM_EXPORT(rt_mq_send_wait) + /** - * This function will send a message to message queue object, if there are - * threads suspended on message queue object, it will be waked up. + * @brief This function will send a message to the messagequeue object. + * If there is a thread suspended on the messagequeue, the thread will be resumed. * - * @param mq the message queue object - * @param buffer the message - * @param size the size of buffer + * @note When using this function to send a message, if the messagequeue is fully used, + * the current thread will wait for a timeout. + * By contrast, when the messagequeue is fully used, the rt_mq_send_wait() function will + * return an error code immediately without waiting. * - * @return the error code + * @see rt_mq_send_wait() + * + * @param mq is a pointer to the messagequeue object to be sent. + * + * @param buffer is the content of the message. + * + * @param size is the length of the message(Unit: Byte). + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the messagequeue detach failed. + * + * @warning This function can be called in interrupt context and thread context. */ rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size) { @@ -2314,16 +2908,24 @@ rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size) } RTM_EXPORT(rt_mq_send); + /** - * This function will send an urgent message to message queue object, which - * means the message will be inserted to the head of message queue. If there - * are threads suspended on message queue object, it will be waked up. + * @brief This function will send an urgent message to the messagequeue object. * - * @param mq the message queue object - * @param buffer the message - * @param size the size of buffer + * @note This function is almost the same as the rt_mq_send() function. The only difference is that + * when sending an urgent message, the message is placed at the head of the messagequeue so that + * the recipient can receive the urgent message first. * - * @return the error code + * @see rt_mq_send() + * + * @param mq is a pointer to the messagequeue object to be sent. + * + * @param buffer is the content of the message. + * + * @param size is the length of the message(Unit: Byte). + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox detach failed. */ rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size) { @@ -2406,17 +3008,25 @@ rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size) } RTM_EXPORT(rt_mq_urgent); + /** - * This function will receive a message from message queue object, if there is - * no message in message queue object, the thread shall wait for a specified - * time. + * @brief This function will receive a message from message queue object, + * if there is no message in messagequeue object, the thread shall wait for a specified time. * - * @param mq the message queue object - * @param buffer the received message will be saved in - * @param size the size of buffer - * @param timeout the waiting time + * @note Only when there is mail in the mailbox, the receiving thread can get the mail immediately and return RT_EOK, + * otherwise the receiving thread will be suspended until timeout. + * If the mail is not received within the specified time, it will return -RT_ETIMEOUT. * - * @return the error code + * @param mq is a pointer to the messagequeue object to be received. + * + * @param buffer is the content of the message. + * + * @param size is the length of the message(Unit: Byte). + * + * @param timeout is a timeout period (unit: an OS tick). + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that the mailbox release failed. */ rt_err_t rt_mq_recv(rt_mq_t mq, void *buffer, @@ -2568,15 +3178,20 @@ rt_err_t rt_mq_recv(rt_mq_t mq, } RTM_EXPORT(rt_mq_recv); + /** - * This function can get or set some extra attributions of a message queue - * object. + * @brief This function will set some extra attributions of a messagequeue object. * - * @param mq the message queue object - * @param cmd the execution command - * @param arg the execution argument + * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the messagequeue. * - * @return the error code + * @param mq is a pointer to a messagequeue object. + * + * @param cmd is a command used to configure some attributions of the messagequeue. + * + * @param arg is the argument of the function to execute the command. + * + * @return Return the operation status. When the return value is RT_EOK, the operation is successful. + * If the return value is any other values, it means that this function failed to execute. */ rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg) { @@ -2628,6 +3243,8 @@ rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg) return -RT_ERROR; } RTM_EXPORT(rt_mq_control); + +/**@}*/ #endif /* RT_USING_MESSAGEQUEUE */ /**@}*/

      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℘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 LtLG;6>-&EJFL|l; From b17cf429db764db0239ab66bf7260b6808ee183b Mon Sep 17 00:00:00 2001 From: luhuadong Date: Wed, 30 Jun 2021 23:38:30 +0800 Subject: [PATCH 219/255] [components][net][at] indent using 4 spaces --- components/net/at/include/at.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/net/at/include/at.h b/components/net/at/include/at.h index c6d0e3a5ce..0e93720ff0 100644 --- a/components/net/at/include/at.h +++ b/components/net/at/include/at.h @@ -113,10 +113,10 @@ typedef struct at_server *at_server_t; #ifdef AT_USING_CLIENT enum at_resp_status { - AT_RESP_OK = 0, /* AT response end is OK */ - AT_RESP_ERROR = -1, /* AT response end is ERROR */ - AT_RESP_TIMEOUT = -2, /* AT response is timeout */ - AT_RESP_BUFF_FULL= -3, /* AT response buffer is full */ + AT_RESP_OK = 0, /* AT response end is OK */ + AT_RESP_ERROR = -1, /* AT response end is ERROR */ + AT_RESP_TIMEOUT = -2, /* AT response is timeout */ + AT_RESP_BUFF_FULL= -3, /* AT response buffer is full */ }; typedef enum at_resp_status at_resp_status_t; From 194e33a7929be86e541af5172977135ce9c0f8e1 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Wed, 30 Jun 2021 19:36:24 +0800 Subject: [PATCH 220/255] [tools] add scons --target=cmake-armclang --- bsp/stm32/stm32l475-atk-pandora/rtconfig.py | 3 +- tools/building.py | 3 +- tools/cmake.py | 87 +++++++++++++++------ 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/bsp/stm32/stm32l475-atk-pandora/rtconfig.py b/bsp/stm32/stm32l475-atk-pandora/rtconfig.py index 9314a28375..b13849bb9f 100644 --- a/bsp/stm32/stm32l475-atk-pandora/rtconfig.py +++ b/bsp/stm32/stm32l475-atk-pandora/rtconfig.py @@ -105,7 +105,7 @@ elif PLATFORM == 'armclang': TARGET_EXT = 'axf' DEVICE = ' --cpu Cortex-M4.fp ' - CFLAGS = ' -xc -std=c99 --target=arm-arm-none-eabi -mcpu=cortex-m4 ' + CFLAGS = ' --target=arm-arm-none-eabi -mcpu=cortex-m4 ' CFLAGS += ' -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 ' CFLAGS += ' -mfloat-abi=hard -c -fno-rtti -funsigned-char -fshort-enums -fshort-wchar ' CFLAGS += ' -gdwarf-3 -ffunction-sections ' @@ -125,6 +125,7 @@ elif PLATFORM == 'armclang': CFLAGS += ' -O2' CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' diff --git a/tools/building.py b/tools/building.py index 32ce449622..e078c1626c 100644 --- a/tools/building.py +++ b/tools/building.py @@ -258,6 +258,7 @@ def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = [ 'eclipse':('gcc', 'gcc'), 'ses' : ('gcc', 'gcc'), 'cmake':('gcc', 'gcc'), + 'cmake-armclang':('keil', 'armclang'), 'codelite' : ('gcc', 'gcc')} tgt_name = GetOption('target') @@ -883,7 +884,7 @@ def GenTargetProject(program = None): from codelite import TargetCodelite TargetCodelite(Projects, program) - if GetOption('target') == 'cmake': + if GetOption('target') == 'cmake' or GetOption('target') == 'cmake-armclang': from cmake import CMakeProject CMakeProject(Env,Projects) diff --git a/tools/cmake.py b/tools/cmake.py index 88a95ecad8..2c27c96a18 100644 --- a/tools/cmake.py +++ b/tools/cmake.py @@ -21,9 +21,12 @@ def GenerateCFiles(env,project): AS = os.path.join(rtconfig.EXEC_PATH, rtconfig.AS).replace('\\', "/") AR = os.path.join(rtconfig.EXEC_PATH, rtconfig.AR).replace('\\', "/") LINK = os.path.join(rtconfig.EXEC_PATH, rtconfig.LINK).replace('\\', "/") - SIZE = os.path.join(rtconfig.EXEC_PATH, rtconfig.SIZE).replace('\\', "/") - OBJDUMP = os.path.join(rtconfig.EXEC_PATH, rtconfig.OBJDUMP).replace('\\', "/") - OBJCOPY = os.path.join(rtconfig.EXEC_PATH, rtconfig.OBJCPY).replace('\\', "/") + if rtconfig.PLATFORM == 'gcc': + SIZE = os.path.join(rtconfig.EXEC_PATH, rtconfig.SIZE).replace('\\', "/") + OBJDUMP = os.path.join(rtconfig.EXEC_PATH, rtconfig.OBJDUMP).replace('\\', "/") + OBJCOPY = os.path.join(rtconfig.EXEC_PATH, rtconfig.OBJCPY).replace('\\', "/") + elif rtconfig.CROSS_TOOL == 'keil': + FROMELF = os.path.join(rtconfig.EXEC_PATH, 'fromelf').replace('\\', "/") if "win32" in sys.platform: CC += ".exe" @@ -31,28 +34,56 @@ def GenerateCFiles(env,project): AS += ".exe" AR += ".exe" LINK += ".exe" - SIZE += ".exe" - OBJDUMP += ".exe" - OBJCOPY += ".exe" + if rtconfig.PLATFORM == 'gcc': + SIZE += ".exe" + OBJDUMP += ".exe" + OBJCOPY += ".exe" + elif rtconfig.CROSS_TOOL == 'keil': + FROMELF += ".exe" + + if not os.path.exists(CC) or not os.path.exists(CXX) or not os.path.exists(AS) or not os.path.exists(AR) or not os.path.exists(LINK): + print("'Cannot found toolchain directory, please check RTT_CC and RTT_EXEC_PATH'") + sys.exit(-1) cm_file = open('CMakeLists.txt', 'w') if cm_file: cm_file.write("CMAKE_MINIMUM_REQUIRED(VERSION 3.10)\n\n") cm_file.write("SET(CMAKE_SYSTEM_NAME Generic)\n") + cm_file.write("set(CMAKE_SYSTEM_PROCESSOR " + rtconfig.CPU +")\n") cm_file.write("#SET(CMAKE_VERBOSE_MAKEFILE ON)\n\n") cm_file.write("SET(CMAKE_C_COMPILER \""+ CC + "\")\n") cm_file.write("SET(CMAKE_CXX_COMPILER \""+ CXX + "\")\n") cm_file.write("SET(CMAKE_ASM_COMPILER \""+ AS + "\")\n") - cm_file.write("SET(CMAKE_OBJCOPY \""+ OBJCOPY + "\")\n") - cm_file.write("SET(CMAKE_SIZE \""+ SIZE + "\")\n\n") + cm_file.write("set(CMAKE_C_COMPILER_WORKS TRUE)\n") + cm_file.write("set(CMAKE_CXX_COMPILER_WORKS TRUE)\n\n") + if rtconfig.PLATFORM == 'gcc': + cm_file.write("SET(CMAKE_OBJCOPY \""+ OBJCOPY + "\")\n") + cm_file.write("SET(CMAKE_SIZE \""+ SIZE + "\")\n\n") + elif rtconfig.CROSS_TOOL == 'keil': + cm_file.write("SET(CMAKE_FROMELF \""+ FROMELF + "\")\n") - cm_file.write("SET(CMAKE_C_FLAGS \""+ rtconfig.CFLAGS.replace('\\', "/") + "\")\n") - cm_file.write("SET(CMAKE_CXX_FLAGS \""+ rtconfig.CXXFLAGS.replace('\\', "/") + "\")\n") - cm_file.write("SET(CMAKE_ASM_FLAGS \""+ rtconfig.AFLAGS.replace('\\', "/") + "\")\n") - cm_file.write("SET(CMAKE_EXE_LINKER_FLAGS \""+ re.sub('-T(\s*)', '-T ${CMAKE_SOURCE_DIR}/',rtconfig.LFLAGS.replace('\\', "/")) + "\")\n\n") + cm_file.write("SET(CMAKE_C_FLAGS \""+ rtconfig.CFLAGS.replace('\\', "/").replace('\"', "\\\"") + "\")\n") + cm_file.write("SET(CMAKE_CXX_FLAGS \""+ rtconfig.CXXFLAGS.replace('\\', "/").replace('\"', "\\\"") + "\")\n") + cm_file.write("SET(CMAKE_ASM_FLAGS \""+ rtconfig.AFLAGS.replace('\\', "/").replace('\"', "\\\"") + "\")\n") + + LINKER_FLAGS = '' + LINKER_LIBS = '' + if rtconfig.PLATFORM == 'gcc': + LINKER_FLAGS += '-T' + elif rtconfig.CROSS_TOOL == 'keil': + LINKER_FLAGS += '--scatter' + for group in project: + if 'LIBPATH' in group.keys(): + for f in group['LIBPATH']: + LINKER_LIBS += ' --userlibpath ' + f.replace("\\", "/") + for group in project: + if 'LIBS' in group.keys(): + for f in group['LIBS']: + LINKER_LIBS += ' ' + f.replace("\\", "/") + '.lib' + cm_file.write("SET(CMAKE_EXE_LINKER_FLAGS \""+ re.sub(LINKER_FLAGS + '(\s*)', LINKER_FLAGS + ' ${CMAKE_SOURCE_DIR}/',rtconfig.LFLAGS.replace('\\', "/").replace('\"', "\\\"")) + LINKER_LIBS + "\")\n\n") cm_file.write("SET(CMAKE_CXX_STANDARD 14)\n") cm_file.write("PROJECT(rtthread C CXX ASM)\n") @@ -74,22 +105,26 @@ def GenerateCFiles(env,project): cm_file.write( "\t" + os.path.normpath(f.rfile().abspath).replace("\\", "/") + "\n" ) cm_file.write(")\n\n") - cm_file.write("LINK_DIRECTORIES(\n") - for group in project: - if 'LIBPATH' in group.keys(): - for f in group['LIBPATH']: - cm_file.write( "\t"+ f.replace("\\", "/") + "\n" ) - cm_file.write(")\n\n") + if rtconfig.PLATFORM == 'gcc': + cm_file.write("LINK_DIRECTORIES(\n") + for group in project: + if 'LIBPATH' in group.keys(): + for f in group['LIBPATH']: + cm_file.write( "\t"+ f.replace("\\", "/") + "\n" ) + cm_file.write(")\n\n") - cm_file.write("LINK_LIBRARIES(\n") - for group in project: - if 'LIBS' in group.keys(): - for f in group['LIBS']: - cm_file.write( "\t"+ "{}\n".format(f.replace("\\", "/"))) - cm_file.write(")\n\n") + cm_file.write("LINK_LIBRARIES(\n") + for group in project: + if 'LIBS' in group.keys(): + for f in group['LIBS']: + cm_file.write( "\t"+ "{}\n".format(f.replace("\\", "/"))) + cm_file.write(")\n\n") - cm_file.write("ADD_EXECUTABLE(${CMAKE_PROJECT_NAME}.elf ${PROJECT_SOURCES})\n") - cm_file.write("ADD_CUSTOM_COMMAND(TARGET ${CMAKE_PROJECT_NAME}.elf POST_BUILD \nCOMMAND ${CMAKE_OBJCOPY} -O binary ${CMAKE_PROJECT_NAME}.elf ${CMAKE_PROJECT_NAME}.bin COMMAND ${CMAKE_SIZE} ${CMAKE_PROJECT_NAME}.elf)") + cm_file.write("ADD_EXECUTABLE(${CMAKE_PROJECT_NAME}.elf ${PROJECT_SOURCES})\n") + cm_file.write("ADD_CUSTOM_COMMAND(TARGET ${CMAKE_PROJECT_NAME}.elf POST_BUILD \nCOMMAND ${CMAKE_OBJCOPY} -O binary ${CMAKE_PROJECT_NAME}.elf ${CMAKE_PROJECT_NAME}.bin COMMAND ${CMAKE_SIZE} ${CMAKE_PROJECT_NAME}.elf)") + elif rtconfig.CROSS_TOOL == 'keil': + cm_file.write("ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${PROJECT_SOURCES})\n") + cm_file.write("ADD_CUSTOM_COMMAND(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD \nCOMMAND ${CMAKE_FROMELF} --bin ${CMAKE_PROJECT_NAME}.elf --output ${CMAKE_PROJECT_NAME}.bin COMMAND ${CMAKE_FROMELF} -z ${CMAKE_PROJECT_NAME}.elf)") cm_file.close() From 43d19a8b78227d042c8faeb9848b7f93e887d906 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 1 Jul 2021 01:30:54 +0800 Subject: [PATCH 221/255] [bsp] stm32h750-artpi-h750/stm32f412-st-nucleo support armclang. --- bsp/stm32/stm32f412-st-nucleo/rtconfig.py | 34 ++++++++++++++++++++++ bsp/stm32/stm32h750-artpi-h750/rtconfig.py | 34 ++++++++++++++++++++++ libcpu/arm/cortex-m7/SConscript | 2 +- 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/bsp/stm32/stm32f412-st-nucleo/rtconfig.py b/bsp/stm32/stm32f412-st-nucleo/rtconfig.py index 573c1f7492..9193d4a1d5 100644 --- a/bsp/stm32/stm32f412-st-nucleo/rtconfig.py +++ b/bsp/stm32/stm32f412-st-nucleo/rtconfig.py @@ -94,6 +94,40 @@ elif PLATFORM == 'armcc': POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' +elif PLATFORM == 'armclang': + # toolchains + CC = 'armclang' + CXX = 'armclang' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M4.fp ' + CFLAGS = ' --target=arm-arm-none-eabi -mcpu=cortex-m4 ' + CFLAGS += ' -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 ' + CFLAGS += ' -mfloat-abi=hard -c -fno-rtti -funsigned-char -fshort-enums -fshort-wchar ' + CFLAGS += ' -gdwarf-3 -ffunction-sections ' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers ' + LFLAGS += ' --list rt-thread.map ' + LFLAGS += r' --strict --scatter "board\linker_scripts\link.sct" ' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCLANG/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCLANG/lib' + + EXEC_PATH += '/ARM/ARMCLANG/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O1' # armclang recommend + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + elif PLATFORM == 'iar': # toolchains CC = 'iccarm' diff --git a/bsp/stm32/stm32h750-artpi-h750/rtconfig.py b/bsp/stm32/stm32h750-artpi-h750/rtconfig.py index 2c9cbdd792..13a0ebbdb9 100644 --- a/bsp/stm32/stm32h750-artpi-h750/rtconfig.py +++ b/bsp/stm32/stm32h750-artpi-h750/rtconfig.py @@ -94,6 +94,40 @@ elif PLATFORM == 'armcc': POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' +elif PLATFORM == 'armclang': + # toolchains + CC = 'armclang' + CXX = 'armclang' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M7.fp.sp ' + CFLAGS = ' --target=arm-arm-none-eabi -mcpu=cortex-M7 ' + CFLAGS += ' -mcpu=cortex-M7 -mfpu=fpv4-sp-d16 ' + CFLAGS += ' -mfloat-abi=hard -c -fno-rtti -funsigned-char -fshort-enums -fshort-wchar ' + CFLAGS += ' -gdwarf-3 -ffunction-sections ' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers ' + LFLAGS += ' --list rt-thread.map ' + LFLAGS += r' --strict --scatter "board\linker_scripts\link.sct" ' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCLANG/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCLANG/lib' + + EXEC_PATH += '/ARM/ARMCLANG/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O1' # armclang recommend + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + elif PLATFORM == 'iar': # toolchains CC = 'iccarm' diff --git a/libcpu/arm/cortex-m7/SConscript b/libcpu/arm/cortex-m7/SConscript index 28af7ba651..717823339d 100644 --- a/libcpu/arm/cortex-m7/SConscript +++ b/libcpu/arm/cortex-m7/SConscript @@ -8,7 +8,7 @@ cwd = GetCurrentDir() src = Glob('*.c') + Glob('*.cpp') CPPPATH = [cwd] -if rtconfig.PLATFORM == 'armcc': +if rtconfig.PLATFORM == 'armcc' or rtconfig.PLATFORM == 'armclang': src += Glob('*_rvds.S') if rtconfig.PLATFORM == 'gcc': From 132ecaffb7e8a1a239dc7dd856353592dfb46984 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 1 Jul 2021 01:34:12 +0800 Subject: [PATCH 222/255] [fix] stm32l475-atk-pandora armcc build error. --- bsp/stm32/stm32l475-atk-pandora/rtconfig.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bsp/stm32/stm32l475-atk-pandora/rtconfig.py b/bsp/stm32/stm32l475-atk-pandora/rtconfig.py index b13849bb9f..4250a3d152 100644 --- a/bsp/stm32/stm32l475-atk-pandora/rtconfig.py +++ b/bsp/stm32/stm32l475-atk-pandora/rtconfig.py @@ -91,7 +91,6 @@ elif PLATFORM == 'armcc': CXXFLAGS = CFLAGS - CFLAGS += ' -std=c99' POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' From d500f2dae686265bcd91b123a9badae5e6f63fa5 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 1 Jul 2021 08:13:57 +0800 Subject: [PATCH 223/255] [tools] cmake-clang compatible with bsp that does not support C++. --- tools/cmake.py | 57 +++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/tools/cmake.py b/tools/cmake.py index 2c27c96a18..811b6693cb 100644 --- a/tools/cmake.py +++ b/tools/cmake.py @@ -17,7 +17,10 @@ def GenerateCFiles(env,project): info = utils.ProjectInfo(env) CC = os.path.join(rtconfig.EXEC_PATH, rtconfig.CC).replace('\\', "/") - CXX = os.path.join(rtconfig.EXEC_PATH, rtconfig.CXX).replace('\\', "/") + if 'CXX' in dir(rtconfig): + CXX = os.path.join(rtconfig.EXEC_PATH, rtconfig.CXX).replace('\\', "/") + else: + CXX = '' AS = os.path.join(rtconfig.EXEC_PATH, rtconfig.AS).replace('\\', "/") AR = os.path.join(rtconfig.EXEC_PATH, rtconfig.AR).replace('\\', "/") LINK = os.path.join(rtconfig.EXEC_PATH, rtconfig.LINK).replace('\\', "/") @@ -28,9 +31,18 @@ def GenerateCFiles(env,project): elif rtconfig.CROSS_TOOL == 'keil': FROMELF = os.path.join(rtconfig.EXEC_PATH, 'fromelf').replace('\\', "/") + CFLAGS = rtconfig.CFLAGS.replace('\\', "/").replace('\"', "\\\"") + if 'CXXFLAGS' in dir(rtconfig): + CXXFLAGS = rtconfig.CXXFLAGS.replace('\\', "/").replace('\"', "\\\"") + else: + CXXFLAGS = CFLAGS + AFLAGS = rtconfig.AFLAGS.replace('\\', "/").replace('\"', "\\\"") + LFLAGS = rtconfig.LFLAGS.replace('\\', "/").replace('\"', "\\\"") + if "win32" in sys.platform: CC += ".exe" - CXX += ".exe" + if CXX != '': + CXX += ".exe" AS += ".exe" AR += ".exe" LINK += ".exe" @@ -41,7 +53,7 @@ def GenerateCFiles(env,project): elif rtconfig.CROSS_TOOL == 'keil': FROMELF += ".exe" - if not os.path.exists(CC) or not os.path.exists(CXX) or not os.path.exists(AS) or not os.path.exists(AR) or not os.path.exists(LINK): + if not os.path.exists(CC) or not os.path.exists(AS) or not os.path.exists(AR) or not os.path.exists(LINK): print("'Cannot found toolchain directory, please check RTT_CC and RTT_EXEC_PATH'") sys.exit(-1) @@ -50,24 +62,25 @@ def GenerateCFiles(env,project): cm_file.write("CMAKE_MINIMUM_REQUIRED(VERSION 3.10)\n\n") cm_file.write("SET(CMAKE_SYSTEM_NAME Generic)\n") - cm_file.write("set(CMAKE_SYSTEM_PROCESSOR " + rtconfig.CPU +")\n") + cm_file.write("SET(CMAKE_SYSTEM_PROCESSOR " + rtconfig.CPU +")\n") cm_file.write("#SET(CMAKE_VERBOSE_MAKEFILE ON)\n\n") cm_file.write("SET(CMAKE_C_COMPILER \""+ CC + "\")\n") - cm_file.write("SET(CMAKE_CXX_COMPILER \""+ CXX + "\")\n") cm_file.write("SET(CMAKE_ASM_COMPILER \""+ AS + "\")\n") - cm_file.write("set(CMAKE_C_COMPILER_WORKS TRUE)\n") - cm_file.write("set(CMAKE_CXX_COMPILER_WORKS TRUE)\n\n") + cm_file.write("SET(CMAKE_C_FLAGS \""+ CFLAGS + "\")\n") + cm_file.write("SET(CMAKE_ASM_FLAGS \""+ AFLAGS + "\")\n") + cm_file.write("SET(CMAKE_C_COMPILER_WORKS TRUE)\n\n") + + if CXX != '': + cm_file.write("SET(CMAKE_CXX_COMPILER \""+ CXX + "\")\n") + cm_file.write("SET(CMAKE_CXX_FLAGS \""+ CXXFLAGS + "\")\n") + cm_file.write("SET(CMAKE_CXX_COMPILER_WORKS TRUE)\n\n") if rtconfig.PLATFORM == 'gcc': cm_file.write("SET(CMAKE_OBJCOPY \""+ OBJCOPY + "\")\n") cm_file.write("SET(CMAKE_SIZE \""+ SIZE + "\")\n\n") elif rtconfig.CROSS_TOOL == 'keil': - cm_file.write("SET(CMAKE_FROMELF \""+ FROMELF + "\")\n") - - cm_file.write("SET(CMAKE_C_FLAGS \""+ rtconfig.CFLAGS.replace('\\', "/").replace('\"', "\\\"") + "\")\n") - cm_file.write("SET(CMAKE_CXX_FLAGS \""+ rtconfig.CXXFLAGS.replace('\\', "/").replace('\"', "\\\"") + "\")\n") - cm_file.write("SET(CMAKE_ASM_FLAGS \""+ rtconfig.AFLAGS.replace('\\', "/").replace('\"', "\\\"") + "\")\n") + cm_file.write("SET(CMAKE_FROMELF \""+ FROMELF + "\")\n\n") LINKER_FLAGS = '' LINKER_LIBS = '' @@ -83,20 +96,22 @@ def GenerateCFiles(env,project): if 'LIBS' in group.keys(): for f in group['LIBS']: LINKER_LIBS += ' ' + f.replace("\\", "/") + '.lib' - cm_file.write("SET(CMAKE_EXE_LINKER_FLAGS \""+ re.sub(LINKER_FLAGS + '(\s*)', LINKER_FLAGS + ' ${CMAKE_SOURCE_DIR}/',rtconfig.LFLAGS.replace('\\', "/").replace('\"', "\\\"")) + LINKER_LIBS + "\")\n\n") - - cm_file.write("SET(CMAKE_CXX_STANDARD 14)\n") - cm_file.write("PROJECT(rtthread C CXX ASM)\n") - + cm_file.write("SET(CMAKE_EXE_LINKER_FLAGS \""+ re.sub(LINKER_FLAGS + '(\s*)', LINKER_FLAGS + ' ${CMAKE_SOURCE_DIR}/', LFLAGS) + LINKER_LIBS + "\")\n\n") + + if CXX != '': + cm_file.write("SET(CMAKE_CXX_STANDARD 14)\n") + cm_file.write("PROJECT(rtthread C CXX ASM)\n") + else: + cm_file.write("PROJECT(rtthread C ASM)\n") + cm_file.write("INCLUDE_DIRECTORIES(\n") for i in info['CPPPATH']: - cm_file.write( "\t" + i.replace("\\", "/") + "\n") + cm_file.write( "\t" + i.replace("\\", "/") + "\n") cm_file.write(")\n\n") - cm_file.write("ADD_DEFINITIONS(\n") for i in info['CPPDEFINES']: - cm_file.write("\t-D" + i + "\n") + cm_file.write("\t-D" + i + "\n") cm_file.write(")\n\n") cm_file.write("SET(PROJECT_SOURCES\n") @@ -104,7 +119,7 @@ def GenerateCFiles(env,project): for f in group['src']: cm_file.write( "\t" + os.path.normpath(f.rfile().abspath).replace("\\", "/") + "\n" ) cm_file.write(")\n\n") - + if rtconfig.PLATFORM == 'gcc': cm_file.write("LINK_DIRECTORIES(\n") for group in project: From 7b9904a15279a90b128d301800e54dcf4b227f69 Mon Sep 17 00:00:00 2001 From: crazt Date: Thu, 1 Jul 2021 13:01:21 +0800 Subject: [PATCH 224/255] [bsp/stm32/rmc] support iar. --- bsp/stm32/stm32f407-robomaster-c/README.md | 14 +- .../applications/main.c | 2 +- bsp/stm32/stm32f407-robomaster-c/project.ewd | 166 +- bsp/stm32/stm32f407-robomaster-c/project.ewp | 471 +-- bsp/stm32/stm32f407-robomaster-c/template.ewd | 2966 +++++++++++++++++ bsp/stm32/stm32f407-robomaster-c/template.ewp | 75 +- 6 files changed, 3365 insertions(+), 329 deletions(-) create mode 100644 bsp/stm32/stm32f407-robomaster-c/template.ewd diff --git a/bsp/stm32/stm32f407-robomaster-c/README.md b/bsp/stm32/stm32f407-robomaster-c/README.md index 27df826341..c4f2eceb48 100644 --- a/bsp/stm32/stm32f407-robomaster-c/README.md +++ b/bsp/stm32/stm32f407-robomaster-c/README.md @@ -39,15 +39,15 @@ Robomaster 开发板C型 是大疆创新科技有限公司推出的一款基于 | **板载外设** | **支持情况** | **备注** | | :----------- | :----------: | :----------------------------------- | -| CAN | 暂不支持 | CAN1, CAN2 | -| BMI088 | 暂不支持 | 六轴惯性测量单元 | +| BMI088 | 暂不支持 | 六轴惯性测量单元(有软件包) | | IST8310 | 暂不支持 | 三轴磁力计 | | **片上外设** | **支持情况** | **备注** | | GPIO | 支持 | PA0, PA1... PH1 ---> PIN: 0, 1...144 | | UART | 支持 | UART1, UART3(DBUS), UART6 | -| PWM | 暂不支持 | | -| SPI | 暂不支持 | | -| I2C | 暂不支持 | | +| CAN | 下阶段支持 | CAN1, CAN2 | +| PWM | 下阶段支持 | | +| SPI | 下阶段支持 | BMI088, 用户SPI接口 | +| I2C | 下阶段支持 | IST8310, 用户 I2C 接口 | | USB | 暂不支持 | | | **扩展模块** | **支持情况** | **备注** | | 无 | | | @@ -62,7 +62,7 @@ Robomaster 开发板C型 是大疆创新科技有限公司推出的一款基于 - 进阶使用 - 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用[ENV 工具](https://docs.rt-thread.org/#/development-tools/env/env)对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 ### 快速上手 @@ -110,7 +110,7 @@ msh > ## 注意事项 -- 部分外设需通过 XT30 或 USB 接口供电才能使用,包括 CAN、舵机5V供电、IMU恒温电路 +- 部分外设需通过 XT30 或 USB 接口供电才能正常使用,包括 CAN、舵机5V供电、IMU恒温电路等 - 目前 scons 支持生成 cmake 配置文件,可以使用 CLion 进行 C板 的程序开发,推荐同学们尝试。详细步骤可参见:[在 Clion 中调试 rt-thread 工程](https://club.rt-thread.org/ask/article/2840.html),C板的 openOCD 配置文件推荐选用 `stm32f4discovery.cfg` ,并将该配置文件的最后一行改为 `reset_config none` ## 联系人信息 diff --git a/bsp/stm32/stm32f407-robomaster-c/applications/main.c b/bsp/stm32/stm32f407-robomaster-c/applications/main.c index 5a7535a144..0f19bddd6c 100644 --- a/bsp/stm32/stm32f407-robomaster-c/applications/main.c +++ b/bsp/stm32/stm32f407-robomaster-c/applications/main.c @@ -19,7 +19,7 @@ int main(void) { int count = 1; - /* set LED0 pin mode to output */ + /* set LED Blue pin mode to output */ rt_pin_mode(LED_B_PIN, PIN_MODE_OUTPUT); while (count++) diff --git a/bsp/stm32/stm32f407-robomaster-c/project.ewd b/bsp/stm32/stm32f407-robomaster-c/project.ewd index e94c83ed06..102e51f67a 100644 --- a/bsp/stm32/stm32f407-robomaster-c/project.ewd +++ b/bsp/stm32/stm32f407-robomaster-c/project.ewd @@ -11,7 +11,7 @@ C-SPY 2 - 29 + 30 1 1 + @@ -949,6 +953,27 @@ + + NULINK_ID + 2 + + 0 + 1 + 1 + + + + + PEMICRO_ID 2 @@ -978,7 +1003,7 @@ STLINK_ID 2 - 4 + 6 1 1 + + @@ -1189,7 +1223,7 @@ XDS100_ID 2 - 6 + 8 1 1 + + + @@ -1366,10 +1412,22 @@ $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin 0 + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\HWRTOSplugin\HWRTOSplugin.ewplugin + 0 + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin 0 + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin 0 @@ -1378,6 +1436,14 @@ $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin 0 + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8BE.ewplugin + 0 + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin 0 @@ -1403,11 +1469,11 @@ 1 - $EW_DIR$\common\plugins\IARProbe\IarProbePlugin.ENU.ewplugin + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin 0 - $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin 0 @@ -1426,7 +1492,7 @@ C-SPY 2 - 29 + 30 1 0 + @@ -2364,6 +2434,27 @@ + + NULINK_ID + 2 + + 0 + 1 + 0 + + + + + PEMICRO_ID 2 @@ -2393,7 +2484,7 @@ STLINK_ID 2 - 4 + 6 1 0 + + @@ -2604,7 +2704,7 @@ XDS100_ID 2 - 6 + 8 1 0 + + + @@ -2781,10 +2893,22 @@ $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin 0 + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\HWRTOSplugin\HWRTOSplugin.ewplugin + 0 + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin 0 + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin 0 @@ -2793,6 +2917,14 @@ $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin 0 + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8BE.ewplugin + 0 + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin 0 @@ -2818,11 +2950,11 @@ 1 - $EW_DIR$\common\plugins\IARProbe\IarProbePlugin.ENU.ewplugin + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin 0 - $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin 0 diff --git a/bsp/stm32/stm32f407-robomaster-c/project.ewp b/bsp/stm32/stm32f407-robomaster-c/project.ewp index db4161a4b3..ca8aeb43b8 100644 --- a/bsp/stm32/stm32f407-robomaster-c/project.ewp +++ b/bsp/stm32/stm32f407-robomaster-c/project.ewp @@ -10,7 +10,7 @@ General 3 - 29 + 31 1 1 + + ICCARM 2 - 34 + 35 1 1 + @@ -689,7 +706,7 @@ ILINK 0 - 20 + 22 1 1 + + @@ -1040,7 +1065,7 @@ General 3 - 29 + 31 1 0 + + ICCARM 2 - 34 + 35 1 0 + @@ -1718,7 +1761,7 @@ ILINK 0 - 20 + 22 1 0 + + @@ -2066,16 +2117,64 @@ - Drivers + CPU - $PROJ_DIR$\board\board.c + $PROJ_DIR$\..\..\..\libcpu\arm\common\backtrace.c + + $PROJ_DIR$\..\..\..\libcpu\arm\common\div0.c + + + $PROJ_DIR$\..\..\..\libcpu\arm\common\showmem.c + + + $PROJ_DIR$\..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + $PROJ_DIR$\..\..\..\libcpu\arm\cortex-m4\context_iar.S + + + + DeviceDrivers + + $PROJ_DIR$\..\..\..\components\drivers\misc\pin.c + + + $PROJ_DIR$\..\..\..\components\drivers\serial\serial.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\pipe.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\workqueue.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\waitqueue.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\ringblk_buf.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\completion.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\dataqueue.c + + + $PROJ_DIR$\..\..\..\components\drivers\src\ringbuffer.c + + + + Drivers $PROJ_DIR$\board\CubeMX_Config\Src\stm32f4xx_hal_msp.c $PROJ_DIR$\..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\iar\startup_stm32f407xx.s + + $PROJ_DIR$\board\board.c + $PROJ_DIR$\..\libraries\HAL_Drivers\drv_gpio.c @@ -2086,325 +2185,121 @@ $PROJ_DIR$\..\libraries\HAL_Drivers\drv_common.c - - Kernel - - $PROJ_DIR$\..\..\..\src\clock.c - - - $PROJ_DIR$\..\..\..\src\components.c - - - $PROJ_DIR$\..\..\..\src\device.c - - - $PROJ_DIR$\..\..\..\src\idle.c - - - $PROJ_DIR$\..\..\..\src\ipc.c - - - $PROJ_DIR$\..\..\..\src\irq.c - - - $PROJ_DIR$\..\..\..\src\kservice.c - - - $PROJ_DIR$\..\..\..\src\mem.c - - - $PROJ_DIR$\..\..\..\src\mempool.c - - - $PROJ_DIR$\..\..\..\src\object.c - - - $PROJ_DIR$\..\..\..\src\scheduler.c - - - $PROJ_DIR$\..\..\..\src\signal.c - - - $PROJ_DIR$\..\..\..\src\thread.c - - - $PROJ_DIR$\..\..\..\src\timer.c - - - - CORTEX-M4 - - $PROJ_DIR$\..\..\..\libcpu\arm\cortex-m4\cpuport.c - - - $PROJ_DIR$\..\..\..\libcpu\arm\cortex-m4\context_iar.S - - - $PROJ_DIR$\..\..\..\libcpu\arm\common\backtrace.c - - - $PROJ_DIR$\..\..\..\libcpu\arm\common\div0.c - - - $PROJ_DIR$\..\..\..\libcpu\arm\common\showmem.c - - - - DeviceDrivers - - $PROJ_DIR$\..\..\..\components\drivers\misc\pin.c - - - $PROJ_DIR$\..\..\..\components\drivers\serial\serial.c - - - $PROJ_DIR$\..\..\..\components\drivers\src\completion.c - - - $PROJ_DIR$\..\..\..\components\drivers\src\dataqueue.c - - - $PROJ_DIR$\..\..\..\components\drivers\src\pipe.c - - - $PROJ_DIR$\..\..\..\components\drivers\src\ringblk_buf.c - - - $PROJ_DIR$\..\..\..\components\drivers\src\ringbuffer.c - - - $PROJ_DIR$\..\..\..\components\drivers\src\waitqueue.c - - - $PROJ_DIR$\..\..\..\components\drivers\src\workqueue.c - - finsh $PROJ_DIR$\..\..\..\components\finsh\shell.c - $PROJ_DIR$\..\..\..\components\finsh\symbol.c + $PROJ_DIR$\..\..\..\components\finsh\msh.c $PROJ_DIR$\..\..\..\components\finsh\cmd.c + + + Kernel - $PROJ_DIR$\..\..\..\components\finsh\msh.c + $PROJ_DIR$\..\..\..\src\device.c - $PROJ_DIR$\..\..\..\components\finsh\msh_cmd.c + $PROJ_DIR$\..\..\..\src\ipc.c - $PROJ_DIR$\..\..\..\components\finsh\msh_file.c + $PROJ_DIR$\..\..\..\src\kservice.c + + + $PROJ_DIR$\..\..\..\src\idle.c + + + $PROJ_DIR$\..\..\..\src\clock.c + + + $PROJ_DIR$\..\..\..\src\mem.c + + + $PROJ_DIR$\..\..\..\src\scheduler.c + + + $PROJ_DIR$\..\..\..\src\object.c + + + $PROJ_DIR$\..\..\..\src\irq.c + + + $PROJ_DIR$\..\..\..\src\timer.c + + + $PROJ_DIR$\..\..\..\src\mempool.c + + + $PROJ_DIR$\..\..\..\src\thread.c + + + $PROJ_DIR$\..\..\..\src\components.c - STM32_HAL + libc - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c + $PROJ_DIR$\..\..\..\components\libc\compilers\common\time.c + + + Libraries - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_can.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cec.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_crc.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp.c + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp_ex.c - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dac.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dac_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dcmi.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dcmi_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dfsdm.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma2d.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dsi.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_eth.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_fmpi2c.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_fmpi2c_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hash.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hash_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_hcd.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2c.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2c_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2s.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_i2s_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_irda.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_iwdg.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_lptim.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_ltdc.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_ltdc_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_nand.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_nor.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pccard.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pcd_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_qspi.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rng.c - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc.c + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc_ex.c + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sai.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sai_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sd.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sdram.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_smartcard.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spdifrx.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spi.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_sram.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c - - - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_usart.c - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_wwdg.c + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cec.c - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_fmc.c + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_fsmc.c + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_sdmmc.c + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c - $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_usb.c + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_crc.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cryp.c + + + $PROJ_DIR$\..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c + + utestcases + diff --git a/bsp/stm32/stm32f407-robomaster-c/template.ewd b/bsp/stm32/stm32f407-robomaster-c/template.ewd new file mode 100644 index 0000000000..0328777969 --- /dev/null +++ b/bsp/stm32/stm32f407-robomaster-c/template.ewd @@ -0,0 +1,2966 @@ + + + 3 + + rt-thread + + ARM + + 1 + + C-SPY + 2 + + 30 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 1 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 1 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + NULINK_ID + 2 + + 0 + 1 + 1 + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 1 + + + + + + + + STLINK_ID + 2 + + 6 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 1 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 8 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\HWRTOSplugin\HWRTOSplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8BE.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + + Release + + ARM + + 0 + + C-SPY + 2 + + 30 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 0 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 0 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 0 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + NULINK_ID + 2 + + 0 + 1 + 0 + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 0 + + + + + + + + STLINK_ID + 2 + + 6 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 0 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 8 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\HWRTOSplugin\HWRTOSplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm8BE.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + diff --git a/bsp/stm32/stm32f407-robomaster-c/template.ewp b/bsp/stm32/stm32f407-robomaster-c/template.ewp index 21c66ca0d0..c3ce258e5c 100644 --- a/bsp/stm32/stm32f407-robomaster-c/template.ewp +++ b/bsp/stm32/stm32f407-robomaster-c/template.ewp @@ -11,7 +11,7 @@ General 3 - 29 + 31 1 1 + + ICCARM 2 - 34 + 35 1 1 + @@ -674,7 +687,7 @@ ILINK 0 - 20 + 22 1 1 + + @@ -1025,7 +1046,7 @@ General 3 - 29 + 31 1 0 + + ICCARM 2 - 34 + 35 1 0 + @@ -1687,7 +1722,7 @@ ILINK 0 - 20 + 22 1 0 + + From a245403f4df10841222b6269337218d56db21561 Mon Sep 17 00:00:00 2001 From: NightIsDark <935528249@qq.com> Date: Thu, 27 May 2021 09:56:51 +0800 Subject: [PATCH 225/255] =?UTF-8?q?=E5=A4=9A=E7=BD=91=E5=8D=A1=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E4=B8=8B=EF=BC=8Caccept=E5=88=9B=E5=BB=BA=E7=9A=84soc?= =?UTF-8?q?ket=E5=BA=94=E8=AF=A5=E5=92=8Cserver=E4=BD=BF=E7=94=A8=E4=B8=80?= =?UTF-8?q?=E6=A0=B7=E7=9A=84=E7=BD=91=E5=8D=A1=EF=BC=88=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E7=BD=91=E5=8D=A1=E4=B8=8D=E4=B8=80=E5=AE=9A=E6=AD=A3=E7=A1=AE?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/sal_socket/src/sal_socket.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/net/sal_socket/src/sal_socket.c b/components/net/sal_socket/src/sal_socket.c index 982ab2d08d..19f1af5358 100644 --- a/components/net/sal_socket/src/sal_socket.c +++ b/components/net/sal_socket/src/sal_socket.c @@ -619,7 +619,8 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) LOG_E("New socket registered failed, return error %d.", retval); return -1; } - + /* new socket create by accept should have the same netdev with server*/ + new_sock->netdev = sock->netdev; /* socket structure user_data used to store the acquired new socket */ new_sock->user_data = (void *) new_socket; From 122f90922e9b34a66ca8a753a9cbbd46a8524f73 Mon Sep 17 00:00:00 2001 From: NightIsDark <935528249@qq.com> Date: Thu, 27 May 2021 17:28:06 +0800 Subject: [PATCH 226/255] =?UTF-8?q?Revert=20"=E5=A4=9A=E7=BD=91=E5=8D=A1?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E4=B8=8B=EF=BC=8Caccept=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E7=9A=84socket=E5=BA=94=E8=AF=A5=E5=92=8Cserver=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E4=B8=80=E6=A0=B7=E7=9A=84=E7=BD=91=E5=8D=A1=EF=BC=88?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E7=BD=91=E5=8D=A1=E4=B8=8D=E4=B8=80=E5=AE=9A?= =?UTF-8?q?=E6=AD=A3=E7=A1=AE=EF=BC=89"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 05124def81684a2bf73b89513e2ffaf88a03f806. --- components/net/sal_socket/src/sal_socket.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/net/sal_socket/src/sal_socket.c b/components/net/sal_socket/src/sal_socket.c index 19f1af5358..982ab2d08d 100644 --- a/components/net/sal_socket/src/sal_socket.c +++ b/components/net/sal_socket/src/sal_socket.c @@ -619,8 +619,7 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) LOG_E("New socket registered failed, return error %d.", retval); return -1; } - /* new socket create by accept should have the same netdev with server*/ - new_sock->netdev = sock->netdev; + /* socket structure user_data used to store the acquired new socket */ new_sock->user_data = (void *) new_socket; From ce7d1c6ca6a08dcefa2b55c5c7db661f1761d775 Mon Sep 17 00:00:00 2001 From: NightIsDark <935528249@qq.com> Date: Thu, 27 May 2021 17:33:59 +0800 Subject: [PATCH 227/255] =?UTF-8?q?=E4=BF=AE=E8=AE=A2PR=E9=82=AE=E7=AE=B1?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=97=A0=E6=B3=95=E7=AD=BE=E7=BD=B2CLA?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/sal_socket/src/sal_socket.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/net/sal_socket/src/sal_socket.c b/components/net/sal_socket/src/sal_socket.c index 982ab2d08d..19f1af5358 100644 --- a/components/net/sal_socket/src/sal_socket.c +++ b/components/net/sal_socket/src/sal_socket.c @@ -619,7 +619,8 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) LOG_E("New socket registered failed, return error %d.", retval); return -1; } - + /* new socket create by accept should have the same netdev with server*/ + new_sock->netdev = sock->netdev; /* socket structure user_data used to store the acquired new socket */ new_sock->user_data = (void *) new_socket; From 550ad698e0266794c77b9710284bf29107bf7234 Mon Sep 17 00:00:00 2001 From: NightIsDark <935528249@qq.com> Date: Mon, 31 May 2021 10:17:56 +0800 Subject: [PATCH 228/255] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E4=BF=AE=E8=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/sal_socket/src/sal_socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/net/sal_socket/src/sal_socket.c b/components/net/sal_socket/src/sal_socket.c index 19f1af5358..295772bb37 100644 --- a/components/net/sal_socket/src/sal_socket.c +++ b/components/net/sal_socket/src/sal_socket.c @@ -619,8 +619,8 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) LOG_E("New socket registered failed, return error %d.", retval); return -1; } - /* new socket create by accept should have the same netdev with server*/ - new_sock->netdev = sock->netdev; + /* new socket create by accept should have the same netdev with server*/ + new_sock->netdev = sock->netdev; /* socket structure user_data used to store the acquired new socket */ new_sock->user_data = (void *) new_socket; From 247d1a50d7d4a33727b7be943b79900944cb89cb Mon Sep 17 00:00:00 2001 From: NightIsDark <935528249@qq.com> Date: Wed, 30 Jun 2021 23:01:09 +0800 Subject: [PATCH 229/255] git rebase commit --- components/net/sal_socket/src/sal_socket.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/net/sal_socket/src/sal_socket.c b/components/net/sal_socket/src/sal_socket.c index 295772bb37..dd3c5d3dc2 100644 --- a/components/net/sal_socket/src/sal_socket.c +++ b/components/net/sal_socket/src/sal_socket.c @@ -619,6 +619,7 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) LOG_E("New socket registered failed, return error %d.", retval); return -1; } + /* new socket create by accept should have the same netdev with server*/ new_sock->netdev = sock->netdev; /* socket structure user_data used to store the acquired new socket */ From 976b28660c78adbc0f9f7a99d00d6196bf4b482d Mon Sep 17 00:00:00 2001 From: crazt Date: Thu, 1 Jul 2021 14:16:56 +0800 Subject: [PATCH 230/255] [bsp/stm32/rmc] revise code format. --- .../applications/main.c | 2 +- .../CubeMX_Config/Inc/stm32f4xx_hal_conf.h | 2 +- .../CubeMX_Config/Src/system_stm32f4xx.c | 296 +++++++++--------- .../stm32f407-robomaster-c/board/board.c | 2 +- .../stm32f407-robomaster-c/board/board.h | 2 +- 5 files changed, 152 insertions(+), 152 deletions(-) diff --git a/bsp/stm32/stm32f407-robomaster-c/applications/main.c b/bsp/stm32/stm32f407-robomaster-c/applications/main.c index 0f19bddd6c..a4e03550f6 100644 --- a/bsp/stm32/stm32f407-robomaster-c/applications/main.c +++ b/bsp/stm32/stm32f407-robomaster-c/applications/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h index 03b8ceafa2..5986f8f9c9 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h @@ -145,7 +145,7 @@ /** * @brief This is the HAL system configuration section */ -#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ #define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ #define USE_RTOS 0U #define PREFETCH_ENABLE 1U diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/system_stm32f4xx.c b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/system_stm32f4xx.c index bcb2b9f4a5..449d1d9c0a 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/system_stm32f4xx.c +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/system_stm32f4xx.c @@ -4,16 +4,16 @@ * @author MCD Application Team * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. * - * This file provides two functions and one global variable to be called from + * This file provides two functions and one global variable to be called from * user application: - * - SystemInit(): This function is called at startup just after reset and + * - SystemInit(): This function is called at startup just after reset and * before branch to main program. This call is made inside * the "startup_stm32f4xx.s" file. * * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used - * by the user application to setup the SysTick + * by the user application to setup the SysTick * timer or configure other parameters. - * + * * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must * be called whenever the core clock is changed * during program execution. @@ -39,8 +39,8 @@ /** @addtogroup stm32f4xx_system * @{ - */ - + */ + /** @addtogroup STM32F4xx_System_Private_Includes * @{ */ @@ -48,7 +48,7 @@ #include "stm32f4xx.h" -#if !defined (HSE_VALUE) +#if !defined (HSE_VALUE) #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ #endif /* HSE_VALUE */ @@ -80,7 +80,7 @@ /* #define DATA_IN_ExtSRAM */ #endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\ STM32F412Zx || STM32F412Vx */ - + #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) /* #define DATA_IN_ExtSDRAM */ @@ -90,7 +90,7 @@ /*!< Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */ /* #define VECT_TAB_SRAM */ -#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. +#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. This value must be a multiple of 0x200. */ /******************************************************************************/ @@ -112,7 +112,7 @@ /* This variable is updated in three ways: 1) by calling CMSIS function SystemCoreClockUpdate() 2) by calling HAL API function HAL_RCC_GetHCLKFreq() - 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency Note: If you use this function to configure the system clock; then there is no need to call the 2 first functions listed above, since SystemCoreClock variable is updated automatically. @@ -129,7 +129,7 @@ const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; */ #if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) - static void SystemInit_ExtMemCtl(void); + static void SystemInit_ExtMemCtl(void); #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ /** @@ -142,7 +142,7 @@ const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; /** * @brief Setup the microcontroller system - * Initialize the FPU setting, vector table location and External memory + * Initialize the FPU setting, vector table location and External memory * configuration. * @param None * @retval None @@ -155,7 +155,7 @@ void SystemInit(void) #endif #if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) - SystemInit_ExtMemCtl(); + SystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ /* Configure the Vector Table location add offset address ------------------*/ @@ -171,41 +171,41 @@ void SystemInit(void) * The SystemCoreClock variable contains the core clock (HCLK), it can * be used by the user application to setup the SysTick timer or configure * other parameters. - * + * * @note Each time the core clock (HCLK) changes, this function must be called * to update SystemCoreClock variable value. Otherwise, any configuration - * based on this variable will be incorrect. - * - * @note - The system frequency computed by this function is not the real - * frequency in the chip. It is calculated based on the predefined + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined * constant and the selected clock source: - * + * * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) - * + * * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) - * - * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) * or HSI_VALUE(*) multiplied/divided by the PLL factors. - * + * * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value * 16 MHz) but the real value may vary depending on the variations - * in voltage and temperature. - * + * in voltage and temperature. + * * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value * depends on the application requirements), user has to ensure that HSE_VALUE * is same as the real frequency of the crystal used. Otherwise, this function * may have wrong result. - * + * * - The result of this function could be not correct when using fractional * value for HSE crystal. - * + * * @param None * @retval None */ void SystemCoreClockUpdate(void) { uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; - + /* Get SYSCLK source -------------------------------------------------------*/ tmp = RCC->CFGR & RCC_CFGR_SWS; @@ -221,10 +221,10 @@ void SystemCoreClockUpdate(void) /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N SYSCLK = PLL_VCO / PLL_P - */ + */ pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; - + if (pllsource != 0) { /* HSE used as PLL clock source */ @@ -273,79 +273,79 @@ void SystemInit_ExtMemCtl(void) /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); - + /* Connect PDx pins to FMC Alternate function */ GPIOD->AFR[0] = 0x00CCC0CC; GPIOD->AFR[1] = 0xCCCCCCCC; - /* Configure PDx pins in Alternate function mode */ + /* Configure PDx pins in Alternate function mode */ GPIOD->MODER = 0xAAAA0A8A; - /* Configure PDx pins speed to 100 MHz */ + /* Configure PDx pins speed to 100 MHz */ GPIOD->OSPEEDR = 0xFFFF0FCF; - /* Configure PDx pins Output type to push-pull */ + /* Configure PDx pins Output type to push-pull */ GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ + /* No pull-up, pull-down for PDx pins */ GPIOD->PUPDR = 0x00000000; /* Connect PEx pins to FMC Alternate function */ GPIOE->AFR[0] = 0xC00CC0CC; GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ + /* Configure PEx pins in Alternate function mode */ GPIOE->MODER = 0xAAAA828A; - /* Configure PEx pins speed to 100 MHz */ + /* Configure PEx pins speed to 100 MHz */ GPIOE->OSPEEDR = 0xFFFFC3CF; - /* Configure PEx pins Output type to push-pull */ + /* Configure PEx pins Output type to push-pull */ GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ + /* No pull-up, pull-down for PEx pins */ GPIOE->PUPDR = 0x00000000; - + /* Connect PFx pins to FMC Alternate function */ GPIOF->AFR[0] = 0xCCCCCCCC; GPIOF->AFR[1] = 0xCCCCCCCC; - /* Configure PFx pins in Alternate function mode */ + /* Configure PFx pins in Alternate function mode */ GPIOF->MODER = 0xAA800AAA; - /* Configure PFx pins speed to 50 MHz */ + /* Configure PFx pins speed to 50 MHz */ GPIOF->OSPEEDR = 0xAA800AAA; - /* Configure PFx pins Output type to push-pull */ + /* Configure PFx pins Output type to push-pull */ GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ + /* No pull-up, pull-down for PFx pins */ GPIOF->PUPDR = 0x00000000; /* Connect PGx pins to FMC Alternate function */ GPIOG->AFR[0] = 0xCCCCCCCC; GPIOG->AFR[1] = 0xCCCCCCCC; - /* Configure PGx pins in Alternate function mode */ + /* Configure PGx pins in Alternate function mode */ GPIOG->MODER = 0xAAAAAAAA; - /* Configure PGx pins speed to 50 MHz */ + /* Configure PGx pins speed to 50 MHz */ GPIOG->OSPEEDR = 0xAAAAAAAA; - /* Configure PGx pins Output type to push-pull */ + /* Configure PGx pins Output type to push-pull */ GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ + /* No pull-up, pull-down for PGx pins */ GPIOG->PUPDR = 0x00000000; - + /* Connect PHx pins to FMC Alternate function */ GPIOH->AFR[0] = 0x00C0CC00; GPIOH->AFR[1] = 0xCCCCCCCC; - /* Configure PHx pins in Alternate function mode */ + /* Configure PHx pins in Alternate function mode */ GPIOH->MODER = 0xAAAA08A0; - /* Configure PHx pins speed to 50 MHz */ + /* Configure PHx pins speed to 50 MHz */ GPIOH->OSPEEDR = 0xAAAA08A0; - /* Configure PHx pins Output type to push-pull */ + /* Configure PHx pins Output type to push-pull */ GPIOH->OTYPER = 0x00000000; - /* No pull-up, pull-down for PHx pins */ + /* No pull-up, pull-down for PHx pins */ GPIOH->PUPDR = 0x00000000; - + /* Connect PIx pins to FMC Alternate function */ GPIOI->AFR[0] = 0xCCCCCCCC; GPIOI->AFR[1] = 0x00000CC0; - /* Configure PIx pins in Alternate function mode */ + /* Configure PIx pins in Alternate function mode */ GPIOI->MODER = 0x0028AAAA; - /* Configure PIx pins speed to 50 MHz */ + /* Configure PIx pins speed to 50 MHz */ GPIOI->OSPEEDR = 0x0028AAAA; - /* Configure PIx pins Output type to push-pull */ + /* Configure PIx pins Output type to push-pull */ GPIOI->OTYPER = 0x00000000; - /* No pull-up, pull-down for PIx pins */ + /* No pull-up, pull-down for PIx pins */ GPIOI->PUPDR = 0x00000000; - + /*-- FMC Configuration -------------------------------------------------------*/ /* Enable the FMC interface clock */ RCC->AHB3ENR |= 0x00000001; @@ -353,50 +353,50 @@ void SystemInit_ExtMemCtl(void) tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); FMC_Bank5_6->SDCR[0] = 0x000019E4; - FMC_Bank5_6->SDTR[0] = 0x01115351; - + FMC_Bank5_6->SDTR[0] = 0x01115351; + /* SDRAM initialization sequence */ /* Clock enable command */ - FMC_Bank5_6->SDCMR = 0x00000011; - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + FMC_Bank5_6->SDCMR = 0x00000011; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; while((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } /* Delay */ for (index = 0; index<1000; index++); - + /* PALL command */ - FMC_Bank5_6->SDCMR = 0x00000012; + FMC_Bank5_6->SDCMR = 0x00000012; timeout = 0xFFFF; while((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } - + /* Auto refresh command */ FMC_Bank5_6->SDCMR = 0x00000073; timeout = 0xFFFF; while((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } - + /* MRD register program */ FMC_Bank5_6->SDCMR = 0x00046014; timeout = 0xFFFF; while((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + /* Set refresh count */ tmpreg = FMC_Bank5_6->SDRTR; FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); - + /* Disable write protection */ - tmpreg = FMC_Bank5_6->SDCR[0]; + tmpreg = FMC_Bank5_6->SDCR[0]; FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) @@ -404,7 +404,7 @@ void SystemInit_ExtMemCtl(void) FMC_Bank1->BTCR[2] = 0x00001011; FMC_Bank1->BTCR[3] = 0x00000201; FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ #if defined(STM32F469xx) || defined(STM32F479xx) /* Configure and enable Bank1_SRAM2 */ FMC_Bank1->BTCR[2] = 0x00001091; @@ -412,7 +412,7 @@ void SystemInit_ExtMemCtl(void) FMC_Bank1E->BWTR[2] = 0x0fffffff; #endif /* STM32F469xx || STM32F479xx */ - (void)(tmp); + (void)(tmp); } #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ #elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) @@ -438,13 +438,13 @@ void SystemInit_ExtMemCtl(void) clock */ RCC->AHB1ENR |= 0x0000007D; #else - /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface + /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */ RCC->AHB1ENR |= 0x000001F8; -#endif /* STM32F446xx */ +#endif /* STM32F446xx */ /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); - + #if defined(STM32F446xx) /* Connect PAx pins to FMC Alternate function */ GPIOA->AFR[0] |= 0xC0000000; @@ -474,78 +474,78 @@ void SystemInit_ExtMemCtl(void) /* Connect PDx pins to FMC Alternate function */ GPIOD->AFR[0] = 0x000000CC; GPIOD->AFR[1] = 0xCC000CCC; - /* Configure PDx pins in Alternate function mode */ + /* Configure PDx pins in Alternate function mode */ GPIOD->MODER = 0xA02A000A; - /* Configure PDx pins speed to 50 MHz */ + /* Configure PDx pins speed to 50 MHz */ GPIOD->OSPEEDR = 0xA02A000A; - /* Configure PDx pins Output type to push-pull */ + /* Configure PDx pins Output type to push-pull */ GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ + /* No pull-up, pull-down for PDx pins */ GPIOD->PUPDR = 0x00000000; /* Connect PEx pins to FMC Alternate function */ GPIOE->AFR[0] = 0xC00000CC; GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ + /* Configure PEx pins in Alternate function mode */ GPIOE->MODER = 0xAAAA800A; - /* Configure PEx pins speed to 50 MHz */ + /* Configure PEx pins speed to 50 MHz */ GPIOE->OSPEEDR = 0xAAAA800A; - /* Configure PEx pins Output type to push-pull */ + /* Configure PEx pins Output type to push-pull */ GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ + /* No pull-up, pull-down for PEx pins */ GPIOE->PUPDR = 0x00000000; /* Connect PFx pins to FMC Alternate function */ GPIOF->AFR[0] = 0xCCCCCCCC; GPIOF->AFR[1] = 0xCCCCCCCC; - /* Configure PFx pins in Alternate function mode */ + /* Configure PFx pins in Alternate function mode */ GPIOF->MODER = 0xAA800AAA; - /* Configure PFx pins speed to 50 MHz */ + /* Configure PFx pins speed to 50 MHz */ GPIOF->OSPEEDR = 0xAA800AAA; - /* Configure PFx pins Output type to push-pull */ + /* Configure PFx pins Output type to push-pull */ GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ + /* No pull-up, pull-down for PFx pins */ GPIOF->PUPDR = 0x00000000; /* Connect PGx pins to FMC Alternate function */ GPIOG->AFR[0] = 0xCCCCCCCC; GPIOG->AFR[1] = 0xCCCCCCCC; - /* Configure PGx pins in Alternate function mode */ + /* Configure PGx pins in Alternate function mode */ GPIOG->MODER = 0xAAAAAAAA; - /* Configure PGx pins speed to 50 MHz */ + /* Configure PGx pins speed to 50 MHz */ GPIOG->OSPEEDR = 0xAAAAAAAA; - /* Configure PGx pins Output type to push-pull */ + /* Configure PGx pins Output type to push-pull */ GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ + /* No pull-up, pull-down for PGx pins */ GPIOG->PUPDR = 0x00000000; #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) + || defined(STM32F469xx) || defined(STM32F479xx) /* Connect PHx pins to FMC Alternate function */ GPIOH->AFR[0] = 0x00C0CC00; GPIOH->AFR[1] = 0xCCCCCCCC; - /* Configure PHx pins in Alternate function mode */ + /* Configure PHx pins in Alternate function mode */ GPIOH->MODER = 0xAAAA08A0; - /* Configure PHx pins speed to 50 MHz */ + /* Configure PHx pins speed to 50 MHz */ GPIOH->OSPEEDR = 0xAAAA08A0; - /* Configure PHx pins Output type to push-pull */ + /* Configure PHx pins Output type to push-pull */ GPIOH->OTYPER = 0x00000000; - /* No pull-up, pull-down for PHx pins */ + /* No pull-up, pull-down for PHx pins */ GPIOH->PUPDR = 0x00000000; - + /* Connect PIx pins to FMC Alternate function */ GPIOI->AFR[0] = 0xCCCCCCCC; GPIOI->AFR[1] = 0x00000CC0; - /* Configure PIx pins in Alternate function mode */ + /* Configure PIx pins in Alternate function mode */ GPIOI->MODER = 0x0028AAAA; - /* Configure PIx pins speed to 50 MHz */ + /* Configure PIx pins speed to 50 MHz */ GPIOI->OSPEEDR = 0x0028AAAA; - /* Configure PIx pins Output type to push-pull */ + /* Configure PIx pins Output type to push-pull */ GPIOI->OTYPER = 0x00000000; - /* No pull-up, pull-down for PIx pins */ + /* No pull-up, pull-down for PIx pins */ GPIOI->PUPDR = 0x00000000; #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ - + /*-- FMC Configuration -------------------------------------------------------*/ /* Enable the FMC interface clock */ RCC->AHB3ENR |= 0x00000001; @@ -555,65 +555,65 @@ void SystemInit_ExtMemCtl(void) /* Configure and enable SDRAM bank1 */ #if defined(STM32F446xx) FMC_Bank5_6->SDCR[0] = 0x00001954; -#else +#else FMC_Bank5_6->SDCR[0] = 0x000019E4; #endif /* STM32F446xx */ - FMC_Bank5_6->SDTR[0] = 0x01115351; - + FMC_Bank5_6->SDTR[0] = 0x01115351; + /* SDRAM initialization sequence */ /* Clock enable command */ - FMC_Bank5_6->SDCMR = 0x00000011; - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + FMC_Bank5_6->SDCMR = 0x00000011; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; while((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } /* Delay */ for (index = 0; index<1000; index++); - + /* PALL command */ - FMC_Bank5_6->SDCMR = 0x00000012; + FMC_Bank5_6->SDCMR = 0x00000012; timeout = 0xFFFF; while((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } - + /* Auto refresh command */ #if defined(STM32F446xx) FMC_Bank5_6->SDCMR = 0x000000F3; -#else +#else FMC_Bank5_6->SDCMR = 0x00000073; #endif /* STM32F446xx */ timeout = 0xFFFF; while((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; } - + /* MRD register program */ #if defined(STM32F446xx) FMC_Bank5_6->SDCMR = 0x00044014; -#else +#else FMC_Bank5_6->SDCMR = 0x00046014; #endif /* STM32F446xx */ timeout = 0xFFFF; while((tmpreg != 0) && (timeout-- > 0)) { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + /* Set refresh count */ tmpreg = FMC_Bank5_6->SDRTR; #if defined(STM32F446xx) FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1)); -#else +#else FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); #endif /* STM32F446xx */ - + /* Disable write protection */ - tmpreg = FMC_Bank5_6->SDCR[0]; + tmpreg = FMC_Bank5_6->SDCR[0]; FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); #endif /* DATA_IN_ExtSDRAM */ #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ @@ -628,55 +628,55 @@ void SystemInit_ExtMemCtl(void) RCC->AHB1ENR |= 0x00000078; /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN); - + /* Connect PDx pins to FMC Alternate function */ GPIOD->AFR[0] = 0x00CCC0CC; GPIOD->AFR[1] = 0xCCCCCCCC; - /* Configure PDx pins in Alternate function mode */ + /* Configure PDx pins in Alternate function mode */ GPIOD->MODER = 0xAAAA0A8A; - /* Configure PDx pins speed to 100 MHz */ + /* Configure PDx pins speed to 100 MHz */ GPIOD->OSPEEDR = 0xFFFF0FCF; - /* Configure PDx pins Output type to push-pull */ + /* Configure PDx pins Output type to push-pull */ GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ + /* No pull-up, pull-down for PDx pins */ GPIOD->PUPDR = 0x00000000; /* Connect PEx pins to FMC Alternate function */ GPIOE->AFR[0] = 0xC00CC0CC; GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ + /* Configure PEx pins in Alternate function mode */ GPIOE->MODER = 0xAAAA828A; - /* Configure PEx pins speed to 100 MHz */ + /* Configure PEx pins speed to 100 MHz */ GPIOE->OSPEEDR = 0xFFFFC3CF; - /* Configure PEx pins Output type to push-pull */ + /* Configure PEx pins Output type to push-pull */ GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ + /* No pull-up, pull-down for PEx pins */ GPIOE->PUPDR = 0x00000000; /* Connect PFx pins to FMC Alternate function */ GPIOF->AFR[0] = 0x00CCCCCC; GPIOF->AFR[1] = 0xCCCC0000; - /* Configure PFx pins in Alternate function mode */ + /* Configure PFx pins in Alternate function mode */ GPIOF->MODER = 0xAA000AAA; - /* Configure PFx pins speed to 100 MHz */ + /* Configure PFx pins speed to 100 MHz */ GPIOF->OSPEEDR = 0xFF000FFF; - /* Configure PFx pins Output type to push-pull */ + /* Configure PFx pins Output type to push-pull */ GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ + /* No pull-up, pull-down for PFx pins */ GPIOF->PUPDR = 0x00000000; /* Connect PGx pins to FMC Alternate function */ GPIOG->AFR[0] = 0x00CCCCCC; GPIOG->AFR[1] = 0x000000C0; - /* Configure PGx pins in Alternate function mode */ + /* Configure PGx pins in Alternate function mode */ GPIOG->MODER = 0x00085AAA; - /* Configure PGx pins speed to 100 MHz */ + /* Configure PGx pins speed to 100 MHz */ GPIOG->OSPEEDR = 0x000CAFFF; - /* Configure PGx pins Output type to push-pull */ + /* Configure PGx pins Output type to push-pull */ GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ + /* No pull-up, pull-down for PGx pins */ GPIOG->PUPDR = 0x00000000; - + /*-- FMC/FSMC Configuration --------------------------------------------------*/ /* Enable the FMC/FSMC interface clock */ RCC->AHB3ENR |= 0x00000001; @@ -688,7 +688,7 @@ void SystemInit_ExtMemCtl(void) FMC_Bank1->BTCR[2] = 0x00001011; FMC_Bank1->BTCR[3] = 0x00000201; FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ #if defined(STM32F469xx) || defined(STM32F479xx) /* Delay after an RCC peripheral clock enabling */ tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); @@ -709,8 +709,8 @@ void SystemInit_ExtMemCtl(void) #endif /* DATA_IN_ExtSRAM */ #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ - STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */ - (void)(tmp); + STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */ + (void)(tmp); } #endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */ /** diff --git a/bsp/stm32/stm32f407-robomaster-c/board/board.c b/bsp/stm32/stm32f407-robomaster-c/board/board.c index 6a7a775832..d544465866 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/board.c +++ b/bsp/stm32/stm32f407-robomaster-c/board/board.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/bsp/stm32/stm32f407-robomaster-c/board/board.h b/bsp/stm32/stm32f407-robomaster-c/board/board.h index 3a25989bc2..25e4852c4c 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/board.h +++ b/bsp/stm32/stm32f407-robomaster-c/board/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * From 0fc7158ffbdae6d5c48f03f3d080ef3a825c0ed3 Mon Sep 17 00:00:00 2001 From: HubretXie Date: Mon, 8 Feb 2021 18:26:03 +0800 Subject: [PATCH 231/255] [drivers]serial.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 解决STM32串口使用DMA接收方式时,清空缓存bug --- components/drivers/serial/serial.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index 5cd44f3771..76298ea153 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -955,9 +955,7 @@ static void _tc_flush(struct rt_serial_device *serial, int queue) { RT_ASSERT(RT_NULL != rx_fifo); level = rt_hw_interrupt_disable(); - rt_memset(rx_fifo->buffer, 0, serial->config.bufsz); - rx_fifo->put_index = 0; - rx_fifo->get_index = 0; + rx_fifo->get_index = rx_fifo->put_index; rx_fifo->is_full = RT_FALSE; rt_hw_interrupt_enable(level); } From 8708808a35b029831b306863a5d520c444735892 Mon Sep 17 00:00:00 2001 From: chenyingchun0312 Date: Thu, 1 Jul 2021 22:36:30 +0800 Subject: [PATCH 232/255] [bsp/nrf5x] remove drivers/drv_fs.c to application/mnt.c --- bsp/nrf5x/libraries/drivers/SConscript | 3 - bsp/nrf5x/nrf52832/.config | 173 ++++++++++++++++-- bsp/nrf5x/nrf52832/applications/SConscript | 18 +- .../applications/{application.c => main.c} | 0 .../drv_fs.c => nrf52832/applications/mnt.c} | 4 + bsp/nrf5x/nrf52832/board/fal_cfg.h | 18 +- 6 files changed, 175 insertions(+), 41 deletions(-) rename bsp/nrf5x/nrf52832/applications/{application.c => main.c} (100%) rename bsp/nrf5x/{libraries/drivers/drv_fs.c => nrf52832/applications/mnt.c} (95%) diff --git a/bsp/nrf5x/libraries/drivers/SConscript b/bsp/nrf5x/libraries/drivers/SConscript index 1b68acd868..7c2a47a734 100644 --- a/bsp/nrf5x/libraries/drivers/SConscript +++ b/bsp/nrf5x/libraries/drivers/SConscript @@ -40,9 +40,6 @@ if GetDepend(['BSP_USING_WDT']): if GetDepend(['BSP_USING_ONCHIP_RTC']): src += ['drv_rtc.c'] -if GetDepend(['BSP_USING_ON_CHIP_FS']): - src += ['drv_fs.c'] - path = [cwd] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) diff --git a/bsp/nrf5x/nrf52832/.config b/bsp/nrf5x/nrf52832/.config index 61769240a8..5936d29741 100644 --- a/bsp/nrf5x/nrf52832/.config +++ b/bsp/nrf5x/nrf52832/.config @@ -112,7 +112,16 @@ CONFIG_FINSH_ARG_MAX=10 # # Device virtual file system # -# CONFIG_RT_USING_DFS is not set +CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_WORKDIR=y +CONFIG_DFS_FILESYSTEMS_MAX=4 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=4 +CONFIG_DFS_FD_MAX=16 +# CONFIG_RT_USING_DFS_MNTTABLE is not set +# CONFIG_RT_USING_DFS_ELMFAT is not set +CONFIG_RT_USING_DFS_DEVFS=y +# CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_RAMFS is not set # # Device Drivers @@ -134,7 +143,7 @@ CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set # CONFIG_RT_USING_DAC is not set # CONFIG_RT_USING_PWM is not set -# CONFIG_RT_USING_MTD_NOR is not set +CONFIG_RT_USING_MTD_NOR=y # CONFIG_RT_USING_MTD_NAND is not set # CONFIG_RT_USING_PM is not set # CONFIG_RT_USING_RTC is not set @@ -160,6 +169,11 @@ CONFIG_RT_USING_PIN=y # 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 @@ -272,8 +286,6 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # CONFIG_PKG_USING_LIBRWS is not set # CONFIG_PKG_USING_TCPSERVER is not set # CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set # CONFIG_PKG_USING_DLT645 is not set # CONFIG_PKG_USING_QXWZ is not set # CONFIG_PKG_USING_SMTP_CLIENT is not set @@ -287,6 +299,13 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # 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 @@ -312,7 +331,13 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # 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 +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set # # tools packages @@ -321,12 +346,16 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # 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 @@ -334,23 +363,93 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # 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_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set -# CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set -# CONFIG_PKG_USING_FAL is not set +CONFIG_PKG_USING_FAL=y +CONFIG_PKG_FAL_PATH="/packages/system/fal" +CONFIG_FAL_DEBUG_CONFIG=y +CONFIG_FAL_DEBUG=1 +CONFIG_FAL_PART_HAS_TABLE_CFG=y +# CONFIG_FAL_USING_SFUD_PORT is not set +CONFIG_PKG_USING_FAL_V00500=y +# CONFIG_PKG_USING_FAL_V00400 is not set +# CONFIG_PKG_USING_FAL_V00300 is not set +# CONFIG_PKG_USING_FAL_V00200 is not set +# CONFIG_PKG_USING_FAL_V00100 is not set +# CONFIG_PKG_USING_FAL_LATEST_VERSION is not set +CONFIG_PKG_FAL_VER="v0.5.0" +CONFIG_PKG_FAL_VER_NUM=0x00500 # 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_LITTLEFS=y +CONFIG_PKG_LITTLEFS_PATH="/packages/system/littlefs" +# CONFIG_PKG_USING_LITTLEFS_V090 is not set +# CONFIG_PKG_USING_LITTLEFS_V170 is not set +# CONFIG_PKG_USING_LITTLEFS_V172 is not set +# CONFIG_PKG_USING_LITTLEFS_V201 is not set +# CONFIG_PKG_USING_LITTLEFS_V205 is not set +# CONFIG_PKG_USING_LITTLEFS_V214 is not set +# CONFIG_PKG_USING_LITTLEFS_V220 is not set +# CONFIG_PKG_USING_LITTLEFS_V221 is not set +# CONFIG_PKG_USING_LITTLEFS_V230 is not set +CONFIG_PKG_USING_LITTLEFS_LATEST_VERSION=y +CONFIG_LFS_READ_SIZE=256 +CONFIG_LFS_PROG_SIZE=256 +CONFIG_LFS_BLOCK_SIZE=4096 +CONFIG_LFS_CACHE_SIZE=256 +CONFIG_LFS_BLOCK_CYCLES=-1 +# CONFIG_DFS_LFS_READONLY is not set +CONFIG_LFS_THREADSAFE=y +CONFIG_LFS_LOOKAHEAD_MAX=128 +CONFIG_PKG_LITTLEFS_VER="latest" +# 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 @@ -360,8 +459,12 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # CONFIG_PKG_USING_RAMDISK is not set # CONFIG_PKG_USING_MININI is not set # CONFIG_PKG_USING_QBOOT is not set -# CONFIG_PKG_USING_UCOSIII_WRAPPER 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 @@ -370,6 +473,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # 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 @@ -389,7 +493,6 @@ CONFIG_PKG_NRFX_VER="latest" # 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 @@ -420,6 +523,35 @@ CONFIG_PKG_NRFX_VER="latest" # 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 +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS 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 @@ -429,10 +561,12 @@ CONFIG_PKG_NRFX_VER="latest" # 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 @@ -449,18 +583,25 @@ CONFIG_PKG_NRFX_VER="latest" # CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set # CONFIG_PKG_USING_VI is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set # CONFIG_PKG_USING_VT100 is not set -# CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_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_TENSORFLOWLITEMICRO 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 # # Hardware Drivers Config @@ -493,8 +634,8 @@ CONFIG_BSP_UART0_RX_PIN=8 CONFIG_BSP_UART0_TX_PIN=6 # CONFIG_BSP_USING_I2C is not set # CONFIG_BSP_USING_SPI is not set -# CONFIG_BSP_USING_ON_CHIP_FLASH is not set -# CONFIG_BSP_USING_ON_CHIP_FS is not set +CONFIG_BSP_USING_ON_CHIP_FLASH=y +CONFIG_BSP_USING_ON_CHIP_FS=y # # On-chip flash config diff --git a/bsp/nrf5x/nrf52832/applications/SConscript b/bsp/nrf5x/nrf52832/applications/SConscript index fc2501998c..644eec02bf 100644 --- a/bsp/nrf5x/nrf52832/applications/SConscript +++ b/bsp/nrf5x/nrf52832/applications/SConscript @@ -1,11 +1,17 @@ -Import('RTT_ROOT') -Import('rtconfig') from building import * -cwd = os.path.join(str(Dir('#')), 'applications') -src = Glob('*.c') -CPPPATH = [cwd, str(Dir('#'))] +cwd = GetCurrentDir() + +src = Split(''' +main.c +''') + +if GetDepend(['BSP_USING_ON_CHIP_FS']): + src += ['mnt.c'] + + +CPPPATH = [str(Dir('#')), cwd] group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) -Return('group') +Return('group') \ No newline at end of file diff --git a/bsp/nrf5x/nrf52832/applications/application.c b/bsp/nrf5x/nrf52832/applications/main.c similarity index 100% rename from bsp/nrf5x/nrf52832/applications/application.c rename to bsp/nrf5x/nrf52832/applications/main.c diff --git a/bsp/nrf5x/libraries/drivers/drv_fs.c b/bsp/nrf5x/nrf52832/applications/mnt.c similarity index 95% rename from bsp/nrf5x/libraries/drivers/drv_fs.c rename to bsp/nrf5x/nrf52832/applications/mnt.c index 1576139a06..c7e4d10235 100644 --- a/bsp/nrf5x/libraries/drivers/drv_fs.c +++ b/bsp/nrf5x/nrf52832/applications/mnt.c @@ -30,6 +30,10 @@ #error "if you want to use on chip filesystem, you need to enable mtd nor" #endif +#ifndef PKG_USING_LITTLEFS +#error "if you want to use on chip filesystem, you need to enable littlefs" +#endif + #include "fal.h" #include diff --git a/bsp/nrf5x/nrf52832/board/fal_cfg.h b/bsp/nrf5x/nrf52832/board/fal_cfg.h index af373a2c80..089adcf465 100644 --- a/bsp/nrf5x/nrf52832/board/fal_cfg.h +++ b/bsp/nrf5x/nrf52832/board/fal_cfg.h @@ -1,21 +1,7 @@ /* - * File : fal_cfg.h - * This file is part of FAL (Flash Abstraction Layer) package - * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes From 7d3bac8b6ed7f7747d37c9d9e7919164e13ef305 Mon Sep 17 00:00:00 2001 From: Bernard Xiong Date: Fri, 2 Jul 2021 15:07:21 +0800 Subject: [PATCH 233/255] [libcpu] remove gtimer/pmu from cortex-a --- libcpu/arm/cortex-a/SConscript | 3 - libcpu/arm/cortex-a/armv7.h | 6 ++ libcpu/arm/cortex-a/gtimer.c | 179 --------------------------------- libcpu/arm/cortex-a/gtimer.h | 27 ----- libcpu/arm/cortex-a/pmu.c | 20 ---- libcpu/arm/cortex-a/pmu.h | 159 ----------------------------- 6 files changed, 6 insertions(+), 388 deletions(-) delete mode 100644 libcpu/arm/cortex-a/gtimer.c delete mode 100644 libcpu/arm/cortex-a/gtimer.h delete mode 100644 libcpu/arm/cortex-a/pmu.c delete mode 100644 libcpu/arm/cortex-a/pmu.h diff --git a/libcpu/arm/cortex-a/SConscript b/libcpu/arm/cortex-a/SConscript index a9fe6f0bc9..10977eb3ec 100644 --- a/libcpu/arm/cortex-a/SConscript +++ b/libcpu/arm/cortex-a/SConscript @@ -8,11 +8,8 @@ cwd = GetCurrentDir() src = Split(''' cache.c cpu.c -gtimer.c mmu.c -pmu.c stack.c - ''') CPPPATH = [cwd] diff --git a/libcpu/arm/cortex-a/armv7.h b/libcpu/arm/cortex-a/armv7.h index f284bb5255..325d0ed0ae 100644 --- a/libcpu/arm/cortex-a/armv7.h +++ b/libcpu/arm/cortex-a/armv7.h @@ -69,4 +69,10 @@ struct rt_hw_stack #define E_Bit (1<<9) #define J_Bit (1<<24) +#define PABT_EXCEPTION 0x1 +#define DABT_EXCEPTION 0x2 +#define UND_EXCEPTION 0x3 +#define SWI_EXCEPTION 0x4 +#define RESV_EXCEPTION 0xF + #endif diff --git a/libcpu/arm/cortex-a/gtimer.c b/libcpu/arm/cortex-a/gtimer.c deleted file mode 100644 index b35acc6e6f..0000000000 --- a/libcpu/arm/cortex-a/gtimer.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-03-30 huijie.feng first version - */ - -#include "cp15.h" -#include - -/** Set CNTFRQ - * This function assigns the given value to PL1 Physical Timer Counter Frequency Register (CNTFRQ). - * @param value: CNTFRQ Register value to set - */ -static inline void __set_cntfrq(rt_uint32_t value) -{ - __set_cp(15, 0, value, 14, 0, 0); -} - -/** Get CNTFRQ - * This function returns the value of the PL1 Physical Timer Counter Frequency Register (CNTFRQ). - * return CNTFRQ Register value - */ -static inline rt_uint32_t __get_cntfrq(void) -{ - rt_uint32_t result; - __get_cp(15, 0, result, 14, 0 , 0); - return result; -} - -/** Set CNTP_TVAL - * This function assigns the given value to PL1 Physical Timer Value Register (CNTP_TVAL). - * param value: CNTP_TVAL Register value to set - */ -static inline void __set_cntp_tval(rt_uint32_t value) -{ - __set_cp(15, 0, value, 14, 2, 0); -} - -/** Get CNTP_TVAL - * This function returns the value of the PL1 Physical Timer Value Register (CNTP_TVAL). - * return CNTP_TVAL Register value - */ -static inline rt_uint32_t __get_cntp_tval(void) -{ - rt_uint32_t result; - __get_cp(15, 0, result, 14, 2, 0); - return result; -} - -/** Get CNTPCT - * This function returns the value of the 64 bits PL1 Physical Count Register (CNTPCT). - * return CNTPCT Register value - */ -static inline rt_uint64_t __get_cntpct(void) -{ - rt_uint64_t result; - __get_cp64(15, 0, result, 14); - return result; -} - -/** Set CNTP_CVAL - * This function assigns the given value to 64bits PL1 Physical Timer CompareValue Register (CNTP_CVAL). - * param value: CNTP_CVAL Register value to set -*/ -static inline void __set_cntp_cval(rt_uint64_t value) -{ - __set_cp64(15, 2, value, 14); -} - -/** Get CNTP_CVAL - * This function returns the value of the 64 bits PL1 Physical Timer CompareValue Register (CNTP_CVAL). - * return CNTP_CVAL Register value - */ -static inline rt_uint64_t __get_cntp_cval(void) -{ - rt_uint64_t result; - __get_cp64(15, 2, result, 14); - return result; -} - -/** Set CNTP_CTL - * This function assigns the given value to PL1 Physical Timer Control Register (CNTP_CTL). - * param value: CNTP_CTL Register value to set - */ -static inline void __set_cntp_ctl(uint32_t value) -{ - __set_cp(15, 0, value, 14, 2, 1); -} - -/** Get CNTP_CTL register - * return CNTP_CTL Register value - */ -static inline rt_uint32_t __get_cntp_ctl(void) -{ - rt_uint32_t result; - __get_cp(15, 0, result, 14, 2, 1); - return result; -} - -/** Configures the frequency the timer shall run at. - * param value The timer frequency in Hz. - */ -void gtimer_set_counter_frequency(rt_uint32_t value) -{ - __set_cntfrq(value); - __asm__ volatile ("isb 0xF":::"memory"); -} - -/** Get the frequency the timer shall run at. - * return timer frequency in Hz. - */ -rt_uint32_t gtimer_get_counter_frequency(void) -{ - return(__get_cntfrq()); -} - -/** Sets the reset value of the timer. - * param value: The value the timer is loaded with. - */ -void gtimer_set_load_value(rt_uint32_t value) -{ - __set_cntp_tval(value); - __asm__ volatile ("isb 0xF":::"memory"); -} - -/** Get the current counter value. - * return Current counter value. - */ -rt_uint32_t gtimer_get_current_value(void) -{ - return(__get_cntp_tval()); -} - -/** Get the current physical counter value. - * return Current physical counter value. - */ -rt_uint64_t gtimer_get_current_physical_value(void) -{ - return(__get_cntpct()); -} - -/** Set the physical compare value. - * param value: New physical timer compare value. - */ -void gtimer_set_physical_compare_value(rt_uint64_t value) -{ - __set_cntp_cval(value); - __asm__ volatile ("isb 0xF":::"memory"); -} - -/** Get the physical compare value. - * return Physical compare value. - */ -rt_uint64_t gtimer_get_physical_compare_value(void) -{ - return(__get_cntp_cval()); -} - -/** Configure the timer by setting the control value. - * param value: New timer control value. - */ -void gtimer_set_control(rt_uint32_t value) -{ - __set_cntp_ctl(value); - __asm__ volatile ("isb 0xF":::"memory"); -} - -/** Get the control value. - * return Control value. - */ -rt_uint32_t gtimer_get_control(void) -{ - return(__get_cntp_ctl()); -} - diff --git a/libcpu/arm/cortex-a/gtimer.h b/libcpu/arm/cortex-a/gtimer.h deleted file mode 100644 index ec5d54127e..0000000000 --- a/libcpu/arm/cortex-a/gtimer.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-03-30 huijie.feng first version - */ - -#ifndef __GTIMER_H__ -#define __GTIMER_H__ - -#include - -void gtimer_set_counter_frequency(rt_uint32_t value); -rt_uint32_t gtimer_get_counter_frequency(void); -void gtimer_set_load_value(rt_uint32_t value); -rt_uint32_t gtimer_get_current_value(void); -rt_uint64_t gtimer_get_current_physical_value(void); -void gtimer_set_physical_compare_value(rt_uint64_t value); -rt_uint64_t gtimer_get_physical_compare_value(void); -void gtimer_set_control(rt_uint32_t value); -rt_uint32_t gtimer_get_control(void); - -#endif - diff --git a/libcpu/arm/cortex-a/pmu.c b/libcpu/arm/cortex-a/pmu.c deleted file mode 100644 index 2b9165cc8b..0000000000 --- a/libcpu/arm/cortex-a/pmu.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -#include -#include "pmu.h" - -void rt_hw_pmu_dump_feature(void) -{ - unsigned long reg; - - reg = rt_hw_pmu_get_control(); - rt_kprintf("ARM PMU Implementor: %c, ID code: %02x, %d counters\n", - reg >> 24, (reg >> 16) & 0xff, (reg >> 11) & 0x1f); - RT_ASSERT(ARM_PMU_CNTER_NR == ((reg >> 11) & 0x1f)); -} diff --git a/libcpu/arm/cortex-a/pmu.h b/libcpu/arm/cortex-a/pmu.h deleted file mode 100644 index 64a74b5d39..0000000000 --- a/libcpu/arm/cortex-a/pmu.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -#ifndef __PMU_H__ -#define __PMU_H__ - -#include "board.h" - -/* Number of counters */ -#define ARM_PMU_CNTER_NR 4 - -enum rt_hw_pmu_event_type { - ARM_PMU_EVENT_PMNC_SW_INCR = 0x00, - ARM_PMU_EVENT_L1_ICACHE_REFILL = 0x01, - ARM_PMU_EVENT_ITLB_REFILL = 0x02, - ARM_PMU_EVENT_L1_DCACHE_REFILL = 0x03, - ARM_PMU_EVENT_L1_DCACHE_ACCESS = 0x04, - ARM_PMU_EVENT_DTLB_REFILL = 0x05, - ARM_PMU_EVENT_MEM_READ = 0x06, - ARM_PMU_EVENT_MEM_WRITE = 0x07, - ARM_PMU_EVENT_INSTR_EXECUTED = 0x08, - ARM_PMU_EVENT_EXC_TAKEN = 0x09, - ARM_PMU_EVENT_EXC_EXECUTED = 0x0A, - ARM_PMU_EVENT_CID_WRITE = 0x0B, -}; - -/* Enable bit */ -#define ARM_PMU_PMCR_E (0x01 << 0) -/* Event counter reset */ -#define ARM_PMU_PMCR_P (0x01 << 1) -/* Cycle counter reset */ -#define ARM_PMU_PMCR_C (0x01 << 2) -/* Cycle counter divider */ -#define ARM_PMU_PMCR_D (0x01 << 3) - -#ifdef __GNUC__ -rt_inline void rt_hw_pmu_enable_cnt(int divide64) -{ - unsigned long pmcr; - unsigned long pmcntenset; - - asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); - pmcr |= ARM_PMU_PMCR_E | ARM_PMU_PMCR_P | ARM_PMU_PMCR_C; - if (divide64) - pmcr |= ARM_PMU_PMCR_D; - else - pmcr &= ~ARM_PMU_PMCR_D; - asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr)); - - /* enable all the counters */ - pmcntenset = ~0; - asm volatile ("mcr p15, 0, %0, c9, c12, 1" :: "r"(pmcntenset)); - /* clear overflows(just in case) */ - asm volatile ("mcr p15, 0, %0, c9, c12, 3" :: "r"(pmcntenset)); -} - -rt_inline unsigned long rt_hw_pmu_get_control(void) -{ - unsigned long pmcr; - asm ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); - return pmcr; -} - -rt_inline unsigned long rt_hw_pmu_get_ceid(void) -{ - unsigned long reg; - /* only PMCEID0 is supported, PMCEID1 is RAZ. */ - asm ("mrc p15, 0, %0, c9, c12, 6" : "=r"(reg)); - return reg; -} - -rt_inline unsigned long rt_hw_pmu_get_cnten(void) -{ - unsigned long pmcnt; - asm ("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcnt)); - return pmcnt; -} - -rt_inline void rt_hw_pmu_reset_cycle(void) -{ - unsigned long pmcr; - - asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); - pmcr |= ARM_PMU_PMCR_C; - asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr)); - asm volatile ("isb"); -} - -rt_inline void rt_hw_pmu_reset_event(void) -{ - unsigned long pmcr; - - asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); - pmcr |= ARM_PMU_PMCR_P; - asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr)); - asm volatile ("isb"); -} - -rt_inline unsigned long rt_hw_pmu_get_cycle(void) -{ - unsigned long cyc; - asm volatile ("isb"); - asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r"(cyc)); - return cyc; -} - -rt_inline void rt_hw_pmu_select_counter(int idx) -{ - RT_ASSERT(idx < ARM_PMU_CNTER_NR); - - asm volatile ("mcr p15, 0, %0, c9, c12, 5" : : "r"(idx)); - /* Linux add an isb here, don't know why here. */ - asm volatile ("isb"); -} - -rt_inline void rt_hw_pmu_select_event(int idx, - enum rt_hw_pmu_event_type eve) -{ - RT_ASSERT(idx < ARM_PMU_CNTER_NR); - - rt_hw_pmu_select_counter(idx); - asm volatile ("mcr p15, 0, %0, c9, c13, 1" : : "r"(eve)); -} - -rt_inline unsigned long rt_hw_pmu_read_counter(int idx) -{ - unsigned long reg; - - rt_hw_pmu_select_counter(idx); - asm volatile ("isb"); - asm volatile ("mrc p15, 0, %0, c9, c13, 2" : "=r"(reg)); - return reg; -} - -rt_inline unsigned long rt_hw_pmu_get_ovsr(void) -{ - unsigned long reg; - asm volatile ("isb"); - asm ("mrc p15, 0, %0, c9, c12, 3" : "=r"(reg)); - return reg; -} - -rt_inline void rt_hw_pmu_clear_ovsr(unsigned long reg) -{ - asm ("mcr p15, 0, %0, c9, c12, 3" : : "r"(reg)); - asm volatile ("isb"); -} - -#endif - -void rt_hw_pmu_dump_feature(void); - -#endif /* end of include guard: __PMU_H__ */ - From a6060a41df79353a642e9a68f0af95a2c96b49bb Mon Sep 17 00:00:00 2001 From: wanghaijing Date: Sat, 3 Jul 2021 10:19:29 +0800 Subject: [PATCH 234/255] Adjust the stack_top to bss --- libcpu/arm/cortex-a/start_gcc.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcpu/arm/cortex-a/start_gcc.S b/libcpu/arm/cortex-a/start_gcc.S index bd4bc84604..8fcf6abd2a 100644 --- a/libcpu/arm/cortex-a/start_gcc.S +++ b/libcpu/arm/cortex-a/start_gcc.S @@ -42,7 +42,7 @@ #define SUB_ISR_Stack_Size (SUB_UND_Stack_Size + SUB_SVC_Stack_Size + SUB_ABT_Stack_Size + \ SUB_RT_FIQ_STACK_PGSZ + SUB_RT_IRQ_STACK_PGSZ) -.section .data.share.isr +.section .bss.share.isr /* stack */ .globl stack_start .globl stack_top From 1b85b26eb82c8fb0bed8b73505693eea370dd2df Mon Sep 17 00:00:00 2001 From: crazt Date: Sat, 3 Jul 2021 16:23:16 +0800 Subject: [PATCH 235/255] [bsp/stm32/rmc] update ci and README, delete c99 flag in rtconfig.py. --- .github/workflows/action.yml | 1 + bsp/stm32/README.md | 1 + bsp/stm32/stm32f407-robomaster-c/rtconfig.py | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index bc9e7fe2a4..2959a63c07 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -82,6 +82,7 @@ jobs: - {RTT_BSP: "stm32/stm32f401-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "stm32/stm32f405-smdz-breadfruit", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "stm32/stm32f407-atk-explorer", RTT_TOOL_CHAIN: "sourcery-arm"} + - {RTT_BSP: "stm32/stm32f407-robomaster-c", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "stm32/stm32f407-st-discovery", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "stm32/stm32f410-st-nucleo", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "stm32/stm32f411-atk-nano", RTT_TOOL_CHAIN: "sourcery-arm"} diff --git a/bsp/stm32/README.md b/bsp/stm32/README.md index 1c355c2d1d..570604a8ba 100644 --- a/bsp/stm32/README.md +++ b/bsp/stm32/README.md @@ -26,6 +26,7 @@ STM32 系列 BSP 目前支持情况如下表所示: | [stm32f401-st-nucleo](stm32f401-st-nucleo) | ST 官方 STM32F401 Nucleo-64 开发板 | | [stm32f405-smdz-breadfruit](stm32f405-smdz-breadfruit) | 三木电子 SM1432F405 开发板 | | [stm32f407-atk-explorer](stm32f407-atk-explorer) | 正点原子 F407 探索者开发板 | +| [stm32f407-robomaster-c](stm32f407-robomaster-c) | 大疆公司 RoboMaster C型开发板 | | [stm32f407-st-discovery](stm32f407-st-discovery) | ST 官方 STM32F407-discovery 开发板 | | [stm32f410-st-nucleo](stm32f410-st-nucleo) | ST 官方 STM32F410-Nucleo-64 开发板 | | [stm32f411-atk-nano](stm32f411-atk-nano/) | 正点原子 F411 NANO 开发板 | diff --git a/bsp/stm32/stm32f407-robomaster-c/rtconfig.py b/bsp/stm32/stm32f407-robomaster-c/rtconfig.py index 00d5d737ac..b0cd716905 100644 --- a/bsp/stm32/stm32f407-robomaster-c/rtconfig.py +++ b/bsp/stm32/stm32f407-robomaster-c/rtconfig.py @@ -89,7 +89,6 @@ elif PLATFORM == 'armcc': CFLAGS += ' -O2' CXXFLAGS = CFLAGS - CFLAGS += ' -std=c99' POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' From c77ddf442a2e4eb808b1b5b500985dcd58dc79c7 Mon Sep 17 00:00:00 2001 From: fenghuijie Date: Sat, 3 Jul 2021 16:35:33 +0800 Subject: [PATCH 236/255] =?UTF-8?q?list-thread=E5=91=BD=E4=BB=A4=E9=92=88?= =?UTF-8?q?=E5=AF=B9=E5=A4=9A=E6=A0=B8=E6=B7=BB=E5=8A=A0bind=20core?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/finsh/cmd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index 4c76ab7395..9bbcc440cf 100644 --- a/components/finsh/cmd.c +++ b/components/finsh/cmd.c @@ -175,8 +175,8 @@ long list_thread(void) maxlen = RT_NAME_MAX; #ifdef RT_USING_SMP - rt_kprintf("%-*.s cpu pri status sp stack size max used left tick error\n", maxlen, item_title); object_split(maxlen); - rt_kprintf( " --- --- ------- ---------- ---------- ------ ---------- ---\n"); + rt_kprintf("%-*.s cpu bind pri status sp stack size max used left tick error\n", maxlen, item_title); object_split(maxlen); + rt_kprintf( " --- ---- --- ------- ---------- ---------- ------ ---------- ---\n"); #else rt_kprintf("%-*.s pri status sp stack size max used left tick error\n", maxlen, item_title); object_split(maxlen); rt_kprintf( " --- ------- ---------- ---------- ------ ---------- ---\n"); @@ -211,9 +211,9 @@ long list_thread(void) #ifdef RT_USING_SMP if (thread->oncpu != RT_CPU_DETACHED) - rt_kprintf("%-*.*s %3d %3d ", maxlen, RT_NAME_MAX, thread->name, thread->oncpu, thread->current_priority); + rt_kprintf("%-*.*s %3d %3d %4d ", maxlen, RT_NAME_MAX, thread->name, thread->oncpu, thread->bind_cpu, thread->current_priority); else - rt_kprintf("%-*.*s N/A %3d ", maxlen, RT_NAME_MAX, thread->name, thread->current_priority); + rt_kprintf("%-*.*s N/A %3d %4d ", maxlen, RT_NAME_MAX, thread->name, thread->bind_cpu, thread->current_priority); #else rt_kprintf("%-*.*s %3d ", maxlen, RT_NAME_MAX, thread->name, thread->current_priority); From da701d6b3a7b28d7dd2aca4897a902476b1581e4 Mon Sep 17 00:00:00 2001 From: fenghuijie Date: Sat, 3 Jul 2021 17:34:45 +0800 Subject: [PATCH 237/255] =?UTF-8?q?=E6=B7=BB=E5=8A=A0dcache=20invalidate/d?= =?UTF-8?q?cache=20clean&invalidate=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/arm/cortex-a/cache.c | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/libcpu/arm/cortex-a/cache.c b/libcpu/arm/cortex-a/cache.c index 0a7e702dbb..a6b59182a6 100644 --- a/libcpu/arm/cortex-a/cache.c +++ b/libcpu/arm/cortex-a/cache.c @@ -58,6 +58,37 @@ void rt_hw_cpu_dcache_invalidate(void *addr, int size) asm volatile ("dsb":::"memory"); } +void rt_hw_cpu_dcache_inv_range(void *addr, int size) +{ + rt_uint32_t line_size = rt_cpu_dcache_line_size(); + rt_uint32_t start_addr = (rt_uint32_t)addr; + rt_uint32_t end_addr = (rt_uint32_t)addr + size; + + asm volatile ("dmb":::"memory"); + + if ((start_addr & (line_size - 1)) != 0) + { + start_addr &= ~(line_size - 1); + asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(start_addr)); + start_addr += line_size; + asm volatile ("dsb":::"memory"); + } + + if ((end_addr & (line_size - 1)) != 0) + { + end_addr &= ~(line_size - 1); + asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(end_addr)); + asm volatile ("dsb":::"memory"); + } + + while (start_addr < end_addr) + { + asm volatile ("mcr p15, 0, %0, c7, c6, 1" :: "r"(start_addr)); /* dcimvac */ + start_addr += line_size; + } + asm volatile ("dsb":::"memory"); +} + void rt_hw_cpu_dcache_clean(void *addr, int size) { rt_uint32_t line_size = rt_cpu_dcache_line_size(); @@ -75,6 +106,23 @@ void rt_hw_cpu_dcache_clean(void *addr, int size) asm volatile ("dsb":::"memory"); } +void rt_hw_cpu_dcache_clean_inv(void *addr, int size) +{ + rt_uint32_t line_size = rt_cpu_dcache_line_size(); + rt_uint32_t start_addr = (rt_uint32_t)addr; + rt_uint32_t end_addr = (rt_uint32_t) addr + size + line_size - 1; + + asm volatile ("dmb":::"memory"); + start_addr &= ~(line_size-1); + end_addr &= ~(line_size-1); + while (start_addr < end_addr) + { + asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(start_addr)); + start_addr += line_size; + } + asm volatile ("dsb":::"memory"); +} + void rt_hw_cpu_icache_ops(int ops, void *addr, int size) { if (ops == RT_HW_CACHE_INVALIDATE) From 05bb1a50b0d26b7c60c82ccb4ff8a66a501feac3 Mon Sep 17 00:00:00 2001 From: fenghuijie Date: Sat, 3 Jul 2021 17:54:58 +0800 Subject: [PATCH 238/255] =?UTF-8?q?=E6=B7=BB=E5=8A=A0idle=E5=9B=9E?= =?UTF-8?q?=E6=94=B6=E8=B5=84=E6=BA=90=E7=9A=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/rtthread.h | 6 +- src/Kconfig | 5 ++ src/idle.c | 154 ++++++++++++++++++++++++++++++++++++++------- src/scheduler.c | 5 -- src/thread.c | 40 +++++++----- 5 files changed, 168 insertions(+), 42 deletions(-) diff --git a/include/rtthread.h b/include/rtthread.h index 0583ce6434..f9d0b45e86 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -168,7 +168,6 @@ void rt_thread_idle_init(void); rt_err_t rt_thread_idle_sethook(void (*hook)(void)); rt_err_t rt_thread_idle_delhook(void (*hook)(void)); #endif -void rt_thread_idle_excute(void); rt_thread_t rt_thread_idle_gethandler(void); /* @@ -187,6 +186,7 @@ rt_uint16_t rt_critical_level(void); #ifdef RT_USING_HOOK void rt_scheduler_sethook(void (*hook)(rt_thread_t from, rt_thread_t to)); +void rt_scheduler_switchto_sethook(void (*hook)(struct rt_thread *tid)); #endif #ifdef RT_USING_SMP @@ -396,6 +396,10 @@ rt_err_t rt_mq_recv(rt_mq_t mq, rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg); #endif +/* defunct */ +void rt_thread_defunct_enqueue(rt_thread_t thread); +rt_thread_t rt_thread_defunct_dequeue(void); + /* * spinlock */ diff --git a/src/Kconfig b/src/Kconfig index 9a49146dff..e0582f5663 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -98,6 +98,11 @@ config IDLE_THREAD_STACK_SIZE int "The stack size of idle thread" default 256 +config SYSTEM_THREAD_STACK_SIZE + int "The stack size of system thread (for defunct etc.)" + depends on RT_USING_SMP + default IDLE_THREAD_STACK_SIZE + config RT_USING_TIMER_SOFT bool "Enable software timer with a timer thread" default y diff --git a/src/idle.c b/src/idle.c index db256a6010..a571e487cf 100644 --- a/src/idle.c +++ b/src/idle.c @@ -44,12 +44,22 @@ #define _CPUS_NR 1 #endif /* RT_USING_SMP */ -extern rt_list_t rt_thread_defunct; +static rt_list_t _rt_thread_defunct = RT_LIST_OBJECT_INIT(_rt_thread_defunct);; static struct rt_thread idle[_CPUS_NR]; ALIGN(RT_ALIGN_SIZE) static rt_uint8_t rt_thread_stack[_CPUS_NR][IDLE_THREAD_STACK_SIZE]; +#ifdef RT_USING_SMP +#ifndef SYSTEM_THREAD_STACK_SIZE +#define SYSTEM_THREAD_STACK_SIZE IDLE_THREAD_STACK_SIZE +#endif +static struct rt_thread rt_system_thread; +ALIGN(RT_ALIGN_SIZE) +static rt_uint8_t rt_system_stack[SYSTEM_THREAD_STACK_SIZE]; +static struct rt_semaphore system_sem; +#endif + #ifdef RT_USING_IDLE_HOOK #ifndef RT_IDLE_HOOK_LIST_SIZE #define RT_IDLE_HOOK_LIST_SIZE 4 @@ -127,43 +137,75 @@ rt_err_t rt_thread_idle_delhook(void (*hook)(void)) #endif /* RT_USING_IDLE_HOOK */ -#ifdef RT_USING_HEAP +#ifdef RT_USING_MODULE /* Return whether there is defunctional thread to be deleted. */ rt_inline int _has_defunct_thread(void) { /* The rt_list_isempty has prototype of "int rt_list_isempty(const rt_list_t *l)". - * So the compiler has a good reason that the rt_thread_defunct list does - * not change within rt_thread_idle_excute thus optimize the "while" loop + * So the compiler has a good reason that the _rt_thread_defunct list does + * not change within rt_thread_defunct_exceute thus optimize the "while" loop * into a "if". * * So add the volatile qualifier here. */ - const volatile rt_list_t *l = (const volatile rt_list_t *)&rt_thread_defunct; + const volatile rt_list_t *l = (const volatile rt_list_t *)&_rt_thread_defunct; return l->next != l; } -#endif /* RT_USING_HEAP */ +#endif /* RT_USING_MODULE */ + +/* enqueue a thread to defunct queue + * it must be called between rt_hw_interrupt_disable and rt_hw_interrupt_enable + */ +void rt_thread_defunct_enqueue(rt_thread_t thread) +{ + rt_list_insert_after(&_rt_thread_defunct, &thread->tlist); +#ifdef RT_USING_SMP + rt_sem_release(&system_sem); +#endif +} + +/* dequeue a thread from defunct queue + * it must be called between rt_hw_interrupt_disable and rt_hw_interrupt_enable + */ +rt_thread_t rt_thread_defunct_dequeue(void) +{ + rt_thread_t thread = RT_NULL; + rt_list_t *l = &_rt_thread_defunct; + + if (l->next != l) + { + thread = rt_list_entry(l->next, + struct rt_thread, + tlist); + rt_list_remove(&(thread->tlist)); + } + return thread; +} /** * @ingroup Thread * * This function will perform system background job when system idle. */ -void rt_thread_idle_excute(void) +static void rt_defunct_execute(void) { - /* Loop until there is no dead thread. So one call to rt_thread_idle_excute + /* Loop until there is no dead thread. So one call to rt_defunct_execute * will do all the cleanups. */ - /* disable interrupt */ - - RT_DEBUG_NOT_IN_INTERRUPT; - -#ifdef RT_USING_HEAP while (1) { rt_base_t lock; rt_thread_t thread; + void (*cleanup)(struct rt_thread *tid); +#ifdef RT_USING_MODULE + struct rt_dlmodule *module = RT_NULL; +#endif + RT_DEBUG_NOT_IN_INTERRUPT; + + /* disable interrupt */ lock = rt_hw_interrupt_disable(); +#ifdef RT_USING_MODULE /* check whether list is empty */ if (!_has_defunct_thread()) { @@ -171,18 +213,56 @@ void rt_thread_idle_excute(void) break; } /* get defunct thread */ - thread = rt_list_entry(rt_thread_defunct.next, + thread = rt_list_entry(_rt_thread_defunct.next, struct rt_thread, tlist); + module = (struct rt_dlmodule*)thread->module_id; + if (module) + { + dlmodule_destroy(module); + } /* remove defunct thread */ rt_list_remove(&(thread->tlist)); - /* release thread's stack */ - RT_KERNEL_FREE(thread->stack_addr); - /* delete thread object */ - rt_object_delete((rt_object_t)thread); - rt_hw_interrupt_enable(lock); +#else + thread = rt_thread_defunct_dequeue(); + if (!thread) + { + rt_hw_interrupt_enable(lock); + break; + } +#endif + /* invoke thread cleanup */ + cleanup = thread->cleanup; + if (cleanup != RT_NULL) + { + rt_hw_interrupt_enable(lock); + cleanup(thread); + lock = rt_hw_interrupt_disable(); + } + +#ifdef RT_USING_SIGNALS + rt_thread_free_sig(thread); +#endif + + /* if it's a system object, not delete it */ + if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) + { + /* detach this object */ + rt_object_detach((rt_object_t)thread); + /* enable interrupt */ + rt_hw_interrupt_enable(lock); + } + else + { + rt_hw_interrupt_enable(lock); +#ifdef RT_USING_HEAP + /* release thread's stack */ + RT_KERNEL_FREE(thread->stack_addr); + /* delete thread object */ + rt_object_delete((rt_object_t)thread); +#endif + } } -#endif /* RT_USING_HEAP */ } extern void rt_system_power_manager(void); @@ -214,13 +294,27 @@ static void rt_thread_idle_entry(void *parameter) } #endif /* RT_USING_IDLE_HOOK */ - rt_thread_idle_excute(); +#ifndef RT_USING_SMP + rt_defunct_execute(); +#endif /* RT_USING_SMP */ + #ifdef RT_USING_PM rt_system_power_manager(); #endif /* RT_USING_PM */ } } +#ifdef RT_USING_SMP +static void rt_thread_system_entry(void *parameter) +{ + while (1) + { + rt_sem_take(&system_sem, RT_WAITING_FOREVER); + rt_defunct_execute(); + } +} +#endif + /** * @ingroup SystemInit * @@ -250,6 +344,24 @@ void rt_thread_idle_init(void) /* startup */ rt_thread_startup(&idle[i]); } + +#ifdef RT_USING_SMP + RT_ASSERT(RT_THREAD_PRIORITY_MAX > 2); + + rt_sem_init(&system_sem, "defunct", 1, RT_IPC_FLAG_FIFO); + + /* create defunct thread */ + rt_thread_init(&rt_system_thread, + "tsystem", + rt_thread_system_entry, + RT_NULL, + rt_system_stack, + sizeof(rt_system_stack), + RT_THREAD_PRIORITY_MAX - 2, + 32); + /* startup */ + rt_thread_startup(&rt_system_thread); +#endif } /** diff --git a/src/scheduler.c b/src/scheduler.c index eec660a8aa..956d95d7cc 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -47,8 +47,6 @@ struct rt_thread *rt_current_thread = RT_NULL; rt_uint8_t rt_current_priority; #endif /* RT_USING_SMP */ -rt_list_t rt_thread_defunct; - #ifdef RT_USING_HOOK static void (*rt_scheduler_hook)(struct rt_thread *from, struct rt_thread *to); @@ -224,9 +222,6 @@ void rt_system_scheduler_init(void) /* initialize ready table */ rt_memset(rt_thread_ready_table, 0, sizeof(rt_thread_ready_table)); #endif /* RT_THREAD_PRIORITY_MAX > 32 */ - - /* initialize thread defunct */ - rt_list_init(&rt_thread_defunct); } /** diff --git a/src/thread.c b/src/thread.c index c0a8f0ee74..88cc7b61ba 100644 --- a/src/thread.c +++ b/src/thread.c @@ -32,8 +32,6 @@ #include #include -extern rt_list_t rt_thread_defunct; - #ifdef RT_USING_HOOK static void (*rt_thread_suspend_hook)(rt_thread_t thread); static void (*rt_thread_resume_hook) (rt_thread_t thread); @@ -131,7 +129,7 @@ static void _rt_thread_exit(void) else { /* insert to defunct thread list */ - rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); + rt_thread_defunct_enqueue(thread); } /* switch to next task */ @@ -379,17 +377,22 @@ rt_err_t rt_thread_detach(rt_thread_t thread) /* release thread timer */ rt_timer_detach(&(thread->thread_timer)); - /* disable interrupt */ - lock = rt_hw_interrupt_disable(); - /* change stat */ thread->stat = RT_THREAD_CLOSE; - /* detach thread object */ - rt_object_detach((rt_object_t)thread); - - /* enable interrupt */ - rt_hw_interrupt_enable(lock); + if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) + { + rt_object_detach((rt_object_t)thread); + } + else + { + /* disable interrupt */ + lock = rt_hw_interrupt_disable(); + /* insert to defunct thread list */ + rt_thread_defunct_enqueue(thread); + /* enable interrupt */ + rt_hw_interrupt_enable(lock); + } return RT_EOK; } @@ -484,7 +487,7 @@ rt_err_t rt_thread_delete(rt_thread_t thread) thread->stat = RT_THREAD_CLOSE; /* insert to defunct thread list */ - rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); + rt_thread_defunct_enqueue(thread); /* enable interrupt */ rt_hw_interrupt_enable(lock); @@ -847,12 +850,12 @@ rt_err_t rt_thread_resume(rt_thread_t thread) rt_timer_stop(&thread->thread_timer); - /* enable interrupt */ - rt_hw_interrupt_enable(temp); - /* insert to schedule ready list */ rt_schedule_insert_thread(thread); + /* enable interrupt */ + rt_hw_interrupt_enable(temp); + RT_OBJECT_HOOK_CALL(rt_thread_resume_hook, (thread)); return RT_EOK; } @@ -867,6 +870,7 @@ RTM_EXPORT(rt_thread_resume); void rt_thread_timeout(void *parameter) { struct rt_thread *thread; + register rt_base_t temp; thread = (struct rt_thread *)parameter; @@ -875,6 +879,9 @@ void rt_thread_timeout(void *parameter) RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); + /* disable interrupt */ + temp = rt_hw_interrupt_disable(); + /* set error number */ thread->error = -RT_ETIMEOUT; @@ -884,6 +891,9 @@ void rt_thread_timeout(void *parameter) /* insert to schedule ready list */ rt_schedule_insert_thread(thread); + /* enable interrupt */ + rt_hw_interrupt_enable(temp); + /* do schedule */ rt_schedule(); } From 3dfebe337ab996eeaea651c3a87f06af114e9326 Mon Sep 17 00:00:00 2001 From: Bernard Xiong Date: Sat, 3 Jul 2021 18:48:15 +0800 Subject: [PATCH 239/255] [kernel] remove switchto_sethook --- include/rtthread.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/rtthread.h b/include/rtthread.h index f9d0b45e86..f2f4091b8a 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -186,7 +186,6 @@ rt_uint16_t rt_critical_level(void); #ifdef RT_USING_HOOK void rt_scheduler_sethook(void (*hook)(rt_thread_t from, rt_thread_t to)); -void rt_scheduler_switchto_sethook(void (*hook)(struct rt_thread *tid)); #endif #ifdef RT_USING_SMP From eb79a8a244d3d90665df0a5f3289f90bd1f9aeb1 Mon Sep 17 00:00:00 2001 From: fenghuijie Date: Mon, 5 Jul 2021 14:06:32 +0800 Subject: [PATCH 240/255] =?UTF-8?q?=E4=BF=AE=E6=94=B9irq=20handle=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3rt=5Fhw=5Ftrap=5Firq=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=A0=B8=E9=97=B4IPI=E4=B8=AD=E6=96=AD=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/arm/cortex-a/trap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libcpu/arm/cortex-a/trap.c b/libcpu/arm/cortex-a/trap.c index 3faa136677..f61b89871d 100644 --- a/libcpu/arm/cortex-a/trap.c +++ b/libcpu/arm/cortex-a/trap.c @@ -155,12 +155,14 @@ void rt_hw_trap_resv(struct rt_hw_exp_stack *regs) void rt_hw_trap_irq(void) { void *param; + int int_ack; int ir; rt_isr_handler_t isr_func; extern struct rt_irq_desc isr_table[]; - ir = rt_hw_interrupt_get_irq(); + int_ack = rt_hw_interrupt_get_irq(); + ir = int_ack & GIC_ACK_INTID_MASK; if (ir == 1023) { /* Spurious interrupt */ @@ -181,7 +183,7 @@ void rt_hw_trap_irq(void) } /* end of interrupt */ - rt_hw_interrupt_ack(ir); + rt_hw_interrupt_ack(int_ack); } void rt_hw_trap_fiq(void) From e933c1f6105caf4e68bd57bc5521767b32063a5f Mon Sep 17 00:00:00 2001 From: fenghuijie Date: Mon, 5 Jul 2021 14:43:33 +0800 Subject: [PATCH 241/255] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E5=A4=84=E7=90=86=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E6=94=AF=E6=8C=81backtrace=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/rtdef.h | 4 ++ libcpu/arm/cortex-a/start_gcc.S | 13 ++++- libcpu/arm/cortex-a/trap.c | 88 +++++++++++++++++++++++++-------- 3 files changed, 84 insertions(+), 21 deletions(-) diff --git a/include/rtdef.h b/include/rtdef.h index d125c970c9..2eb2cc1963 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -567,6 +567,10 @@ typedef siginfo_t rt_siginfo_t; #define RT_SCHEDULE_IPI 0 #endif +#ifndef RT_STOP_IPI +#define RT_STOP_IPI 1 +#endif + /** * CPUs definitions * diff --git a/libcpu/arm/cortex-a/start_gcc.S b/libcpu/arm/cortex-a/start_gcc.S index 8fcf6abd2a..6c5dd81785 100644 --- a/libcpu/arm/cortex-a/start_gcc.S +++ b/libcpu/arm/cortex-a/start_gcc.S @@ -373,9 +373,18 @@ rt_hw_context_switch_interrupt_do: mrs r6, spsr @/* Save CPSR */ str lr, [r0, #15*4] @/* Push PC */ str r6, [r0, #16*4] @/* Push CPSR */ - cps #Mode_SVC + mrs r5, cpsr @/* Save CPSR */ + + and r4, r6, #0x1F + cmp r4, #Mode_USR + moveq r6, #Mode_SYS + + orr r6, r6, #0x80 @/* Switch to previous mode, then save SP & PC */ + msr cpsr_c, r6 str sp, [r0, #13*4] @/* Save calling SP */ str lr, [r0, #14*4] @/* Save calling PC */ + + msr cpsr_c, r5 @/* Switch back to current mode */ .endm .align 5 @@ -482,6 +491,8 @@ secondary_cpu_start: .bss .align 2 //align to 2~2=4 +.global sub_stack_top /* used for backtrace to calculate stack top of irq mode */ + sub_stack_start: .space (SUB_ISR_Stack_Size * (RT_CPUS_NR-1)) sub_stack_top: diff --git a/libcpu/arm/cortex-a/trap.c b/libcpu/arm/cortex-a/trap.c index f61b89871d..b3efe31a64 100644 --- a/libcpu/arm/cortex-a/trap.c +++ b/libcpu/arm/cortex-a/trap.c @@ -35,6 +35,18 @@ void rt_hw_show_register(struct rt_hw_exp_stack *regs) rt_kprintf("cpsr:0x%08x\n", regs->cpsr); } +void (*rt_trap_hook)(struct rt_hw_exp_stack *regs, const char *ex, unsigned int exception_type); + +/** + * This function will set a hook function to trap handler. + * + * @param hook the hook function + */ +void rt_hw_trap_set_hook(void (*hook)(struct rt_hw_exp_stack *regs, const char *ex, unsigned int exception_type)) +{ + rt_trap_hook = hook; +} + /** * When comes across an instruction which it cannot handle, * it takes the undefined instruction trap. @@ -72,12 +84,20 @@ void rt_hw_trap_undef(struct rt_hw_exp_stack *regs) } } #endif - rt_kprintf("undefined instruction:\n"); - rt_hw_show_register(regs); + + if (rt_trap_hook == RT_NULL) + { + rt_kprintf("undefined instruction:\n"); + rt_hw_show_register(regs); #ifdef RT_USING_FINSH - list_thread(); + list_thread(); #endif - rt_hw_cpu_shutdown(); + rt_hw_cpu_shutdown(); + } + else + { + rt_trap_hook(regs, "undefined instruction", UND_EXCEPTION); + } } /** @@ -91,12 +111,19 @@ void rt_hw_trap_undef(struct rt_hw_exp_stack *regs) */ void rt_hw_trap_swi(struct rt_hw_exp_stack *regs) { - rt_kprintf("software interrupt:\n"); - rt_hw_show_register(regs); + if (rt_trap_hook == RT_NULL) + { + rt_kprintf("software interrupt:\n"); + rt_hw_show_register(regs); #ifdef RT_USING_FINSH - list_thread(); + list_thread(); #endif - rt_hw_cpu_shutdown(); + rt_hw_cpu_shutdown(); + } + else + { + rt_trap_hook(regs, "software instruction", SWI_EXCEPTION); + } } /** @@ -109,12 +136,19 @@ void rt_hw_trap_swi(struct rt_hw_exp_stack *regs) */ void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs) { - rt_kprintf("prefetch abort:\n"); - rt_hw_show_register(regs); + if (rt_trap_hook == RT_NULL) + { + rt_kprintf("prefetch abort:\n"); + rt_hw_show_register(regs); #ifdef RT_USING_FINSH - list_thread(); + list_thread(); #endif - rt_hw_cpu_shutdown(); + rt_hw_cpu_shutdown(); + } + else + { + rt_trap_hook(regs, "prefetch abort", PABT_EXCEPTION); + } } /** @@ -127,12 +161,19 @@ void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs) */ void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs) { - rt_kprintf("data abort:"); - rt_hw_show_register(regs); + if (rt_trap_hook == RT_NULL) + { + rt_kprintf("data abort:"); + rt_hw_show_register(regs); #ifdef RT_USING_FINSH - list_thread(); + list_thread(); #endif - rt_hw_cpu_shutdown(); + rt_hw_cpu_shutdown(); + } + else + { + rt_trap_hook(regs, "data abort", DABT_EXCEPTION); + } } /** @@ -144,12 +185,19 @@ void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs) */ void rt_hw_trap_resv(struct rt_hw_exp_stack *regs) { - rt_kprintf("reserved trap:\n"); - rt_hw_show_register(regs); + if (rt_trap_hook == RT_NULL) + { + rt_kprintf("reserved trap:\n"); + rt_hw_show_register(regs); #ifdef RT_USING_FINSH - list_thread(); + list_thread(); #endif - rt_hw_cpu_shutdown(); + rt_hw_cpu_shutdown(); + } + else + { + rt_trap_hook(regs, "reserved trap", RESV_EXCEPTION); + } } void rt_hw_trap_irq(void) From 0015af02e4f08ab47f2d2fefcb7c1aca1682bfda Mon Sep 17 00:00:00 2001 From: fenghuijie Date: Mon, 5 Jul 2021 18:33:22 +0800 Subject: [PATCH 242/255] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E4=BB=A5=E6=94=AF=E6=8C=81cpu=20usage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/rtdef.h | 4 ++++ include/rtthread.h | 1 + libcpu/arm/cortex-a/interrupt.c | 14 ++++++++++++++ libcpu/arm/cortex-a/start_gcc.S | 2 ++ src/irq.c | 2 +- src/scheduler.c | 13 +++++++++++++ src/thread.c | 4 ++++ 7 files changed, 39 insertions(+), 1 deletion(-) diff --git a/include/rtdef.h b/include/rtdef.h index 2eb2cc1963..e1a64a433a 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -663,6 +663,10 @@ struct rt_thread rt_ubase_t init_tick; /**< thread's initialized tick */ rt_ubase_t remaining_tick; /**< remaining tick */ +#ifdef RT_USING_CPU_USAGE + rt_uint64_t duration_tick; /**< cpu usage tick */ +#endif + struct rt_timer thread_timer; /**< built-in thread timer */ void (*cleanup)(struct rt_thread *tid); /**< cleanup function when thread exit */ diff --git a/include/rtthread.h b/include/rtthread.h index f2f4091b8a..cf47a48efe 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -186,6 +186,7 @@ rt_uint16_t rt_critical_level(void); #ifdef RT_USING_HOOK void rt_scheduler_sethook(void (*hook)(rt_thread_t from, rt_thread_t to)); +void rt_scheduler_switch_sethook(void (*hook)(struct rt_thread *tid)); #endif #ifdef RT_USING_SMP diff --git a/libcpu/arm/cortex-a/interrupt.c b/libcpu/arm/cortex-a/interrupt.c index 474a23fee1..f90f1c0094 100644 --- a/libcpu/arm/cortex-a/interrupt.c +++ b/libcpu/arm/cortex-a/interrupt.c @@ -27,6 +27,20 @@ struct rt_irq_desc isr_table[MAX_HANDLERS]; rt_uint32_t rt_interrupt_from_thread = 0; rt_uint32_t rt_interrupt_to_thread = 0; rt_uint32_t rt_thread_switch_interrupt_flag = 0; + +#ifdef RT_USING_HOOK +static void (*rt_interrupt_switch_hook)(void); + +void rt_interrupt_switch_sethook(void (*hook)(void)) +{ + rt_interrupt_switch_hook = hook; +} +#endif + +void rt_interrupt_hook(void) +{ + RT_OBJECT_HOOK_CALL(rt_interrupt_switch_hook, ()); +} #endif const unsigned int VECTOR_BASE = 0x00; diff --git a/libcpu/arm/cortex-a/start_gcc.S b/libcpu/arm/cortex-a/start_gcc.S index 6c5dd81785..908468476e 100644 --- a/libcpu/arm/cortex-a/start_gcc.S +++ b/libcpu/arm/cortex-a/start_gcc.S @@ -341,6 +341,8 @@ rt_hw_context_switch_interrupt_do: ldr r6, [r6] ldr sp, [r6] @ get new task's stack pointer + bl rt_interrupt_hook + #ifdef RT_USING_FPU /* fpu context */ ldmfd sp!, {r6} diff --git a/src/irq.c b/src/irq.c index e89b8504dc..6ddcb3dd4a 100644 --- a/src/irq.c +++ b/src/irq.c @@ -89,8 +89,8 @@ void rt_interrupt_leave(void) rt_interrupt_nest)); level = rt_hw_interrupt_disable(); - rt_interrupt_nest --; RT_OBJECT_HOOK_CALL(rt_interrupt_leave_hook,()); + rt_interrupt_nest --; rt_hw_interrupt_enable(level); } RTM_EXPORT(rt_interrupt_leave); diff --git a/src/scheduler.c b/src/scheduler.c index 956d95d7cc..353fdad5cb 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -49,6 +49,7 @@ rt_uint8_t rt_current_priority; #ifdef RT_USING_HOOK static void (*rt_scheduler_hook)(struct rt_thread *from, struct rt_thread *to); +static void (*rt_scheduler_switch_hook)(struct rt_thread *tid); /** * @addtogroup Hook @@ -68,6 +69,12 @@ rt_scheduler_sethook(void (*hook)(struct rt_thread *from, struct rt_thread *to)) rt_scheduler_hook = hook; } +void +rt_scheduler_switch_sethook(void (*hook)(struct rt_thread *tid)) +{ + rt_scheduler_switch_hook = hook; +} + /**@}*/ #endif /* RT_USING_HOOK */ @@ -364,6 +371,8 @@ void rt_schedule(void) _rt_scheduler_stack_check(to_thread); #endif /* RT_USING_OVERFLOW_CHECK */ + RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (current_thread)); + rt_hw_context_switch((rt_ubase_t)¤t_thread->sp, (rt_ubase_t)&to_thread->sp, to_thread); } @@ -473,6 +482,8 @@ void rt_schedule(void) { extern void rt_thread_handle_sig(rt_bool_t clean_state); + RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (from_thread)); + rt_hw_context_switch((rt_ubase_t)&from_thread->sp, (rt_ubase_t)&to_thread->sp); @@ -609,6 +620,8 @@ void rt_scheduler_do_irq_switch(void *context) current_thread->cpus_lock_nest--; current_thread->scheduler_lock_nest--; + RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (current_thread)); + rt_hw_context_switch_interrupt(context, (rt_ubase_t)¤t_thread->sp, (rt_ubase_t)&to_thread->sp, to_thread); } diff --git a/src/thread.c b/src/thread.c index 88cc7b61ba..60e6ab91d1 100644 --- a/src/thread.c +++ b/src/thread.c @@ -228,6 +228,10 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, thread->lwp = RT_NULL; #endif /* RT_USING_LWP */ +#ifdef RT_USING_CPU_USAGE + thread->duration_tick = 0; +#endif + RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread)); return RT_EOK; From e0b00b21f5be26e1b48fca491c65a38165e4d225 Mon Sep 17 00:00:00 2001 From: DavidLin1577 Date: Tue, 6 Jul 2021 18:03:12 +0800 Subject: [PATCH 243/255] [examples/test]update rtc_test.c --- examples/test/rtc_test.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/test/rtc_test.c b/examples/test/rtc_test.c index 4ed1349de4..79ea8450f9 100644 --- a/examples/test/rtc_test.c +++ b/examples/test/rtc_test.c @@ -20,7 +20,7 @@ int rtc_test(void) rt_kprintf("[RTC Test]RTC Test Start...\n"); rt_thread_delay(RT_TICK_PER_SECOND); - rt_kprintf("[RTC Test]Set RTC 2017-04-01 12:30:46\n\n"); + rt_kprintf("[RTC Test]Set RTC 2017-04-01 12:30:46\n"); rt_thread_delay(RT_TICK_PER_SECOND); ret = set_date(2017, 4, 1); @@ -45,7 +45,7 @@ int rtc_test(void) { rt_kprintf("[RTC Test]Read RTC Date and Time: "); now = time(RT_NULL); - rt_kprintf("%s", ctime(&now)); + rt_kprintf("%s\n", ctime(&now)); rt_thread_delay(RT_TICK_PER_SECOND); } @@ -56,6 +56,6 @@ int rtc_test(void) } #ifdef RT_USING_FINSH #include -FINSH_FUNCTION_EXPORT(rtc_test, rtc drive test. e.g: rtc_test()); -MSH_CMD_EXPORT(rtc_test, rtc drive test. e.g: rtc_test()); +FINSH_FUNCTION_EXPORT(rtc_test, rtc driver test. e.g: rtc_test()); +MSH_CMD_EXPORT(rtc_test, rtc driver test. e.g: rtc_test()); #endif From c0096e2db965838dc44f0230c4bd4d7e53b4fb04 Mon Sep 17 00:00:00 2001 From: chenjh Date: Tue, 6 Jul 2021 21:29:48 +0800 Subject: [PATCH 244/255] [uart] Modify uart pin configuration to pullup --- .../stm32f0xx/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c | 2 +- .../stm32f10x/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c | 2 +- .../stm32f7xx/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c | 2 +- .../stm32h7xx/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c | 2 +- .../stm32l4xx/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c | 2 +- .../board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c | 8 ++++---- .../stm32wbxx/board/CubeMX_Config/Src/stm32wbxx_hal_msp.c | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c index 8bdf8316f9..db20df68eb 100644 --- a/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c @@ -160,7 +160,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF1_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); diff --git a/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index 990a7ba098..20076a51b8 100644 --- a/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -130,7 +130,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1 interrupt Init */ diff --git a/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c index 14389e19c8..748daa1a43 100644 --- a/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c @@ -122,7 +122,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); diff --git a/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c index 5068dde011..67cb6361c7 100644 --- a/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c @@ -121,7 +121,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); diff --git a/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index c973d3d2c1..dcc0912216 100644 --- a/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -122,7 +122,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); diff --git a/bsp/stm32/libraries/templates/stm32mp1xx/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32mp1xx/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c index efb81996fa..dec360176a 100644 --- a/bsp/stm32/libraries/templates/stm32mp1xx/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32mp1xx/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c @@ -762,14 +762,14 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = STLINK_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF6_UART4; HAL_GPIO_Init(STLINK_RX_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = STLINK_TX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF8_UART4; HAL_GPIO_Init(STLINK_TX_GPIO_Port, &GPIO_InitStruct); @@ -806,14 +806,14 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF8_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); diff --git a/bsp/stm32/libraries/templates/stm32wbxx/board/CubeMX_Config/Src/stm32wbxx_hal_msp.c b/bsp/stm32/libraries/templates/stm32wbxx/board/CubeMX_Config/Src/stm32wbxx_hal_msp.c index 9e31cfedd8..98fd3fc9a5 100644 --- a/bsp/stm32/libraries/templates/stm32wbxx/board/CubeMX_Config/Src/stm32wbxx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32wbxx/board/CubeMX_Config/Src/stm32wbxx_hal_msp.c @@ -98,7 +98,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); From 04510cfc12a33d3faef7d096ec2f9a557ed46a76 Mon Sep 17 00:00:00 2001 From: David Lin Date: Wed, 7 Jul 2021 09:05:37 +0800 Subject: [PATCH 245/255] Update sensor.h --- components/drivers/sensors/sensor.h | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/components/drivers/sensors/sensor.h b/components/drivers/sensors/sensor.h index df70e96690..5f8b451be6 100755 --- a/components/drivers/sensors/sensor.h +++ b/components/drivers/sensors/sensor.h @@ -6,26 +6,7 @@ * Change Logs: * Date Author Notes * 2019-01-31 flybreak first version - * 2021-06-23 linpeng added function declaration */ -#ifndef __SENSOR_H__ -#define __SENSOR_H__ - #include - -#ifdef __cplusplus -extern "C" -{ -#endif - -int rt_hw_sensor_register(rt_sensor_t sensor, - const char *name, - rt_uint32_t flag, - void *data); - -#ifdef __cplusplus -} -#endif - -#endif /*__SENSOR_H__*/ +#include From bfce90ad461328f14a540ee5659a8b2b92f2b617 Mon Sep 17 00:00:00 2001 From: David Lin Date: Wed, 7 Jul 2021 09:06:44 +0800 Subject: [PATCH 246/255] Update sensor.h --- components/drivers/sensors/sensor.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/drivers/sensors/sensor.h b/components/drivers/sensors/sensor.h index 5f8b451be6..761ee49b4c 100755 --- a/components/drivers/sensors/sensor.h +++ b/components/drivers/sensors/sensor.h @@ -8,5 +8,7 @@ * 2019-01-31 flybreak first version */ + #include #include + From edcdd126edf86b9990e15449ab69c8554da9e274 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 7 Jul 2021 03:30:01 +0800 Subject: [PATCH 247/255] =?UTF-8?q?[kernel][ipc]=20=E7=A7=BB=E9=99=A4mutex?= =?UTF-8?q?=20RT=5FIPC=5FFLAG=5FFIFO=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ipc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ipc.c b/src/ipc.c index 959f0fb522..6a038cd2b6 100755 --- a/src/ipc.c +++ b/src/ipc.c @@ -548,6 +548,8 @@ RTM_EXPORT(rt_sem_control); */ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) { + (void)flag; + /* parameter check */ RT_ASSERT(mutex != RT_NULL); @@ -562,8 +564,8 @@ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) mutex->original_priority = 0xFF; mutex->hold = 0; - /* set flag */ - mutex->parent.parent.flag = flag; + /* set flag and it can only be RT_IPC_FLAG_PRIO */ + mutex->parent.parent.flag = RT_IPC_FLAG_PRIO; return RT_EOK; } @@ -609,6 +611,7 @@ RTM_EXPORT(rt_mutex_detach); rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) { struct rt_mutex *mutex; + (void)flag; RT_DEBUG_NOT_IN_INTERRUPT; @@ -625,8 +628,8 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) mutex->original_priority = 0xFF; mutex->hold = 0; - /* set flag */ - mutex->parent.parent.flag = flag; + /* set flag and it can only be RT_IPC_FLAG_PRIO */ + mutex->parent.parent.flag = RT_IPC_FLAG_PRIO; return mutex; } From 6e334416e3c855ef17a2a59eba816408ac296a75 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 7 Jul 2021 10:16:49 +0800 Subject: [PATCH 248/255] =?UTF-8?q?[ipc][mutex]=20=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ipc.c b/src/ipc.c index 6a038cd2b6..6bc9c079b9 100755 --- a/src/ipc.c +++ b/src/ipc.c @@ -564,7 +564,7 @@ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) mutex->original_priority = 0xFF; mutex->hold = 0; - /* set flag and it can only be RT_IPC_FLAG_PRIO */ + /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */ mutex->parent.parent.flag = RT_IPC_FLAG_PRIO; return RT_EOK; @@ -628,7 +628,7 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) mutex->original_priority = 0xFF; mutex->hold = 0; - /* set flag and it can only be RT_IPC_FLAG_PRIO */ + /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */ mutex->parent.parent.flag = RT_IPC_FLAG_PRIO; return mutex; From 67b86e61ba349ab63c8f21bd04b3aa5de74f2a68 Mon Sep 17 00:00:00 2001 From: chenjh Date: Wed, 7 Jul 2021 17:40:55 +0800 Subject: [PATCH 249/255] [uart] Modify the uart file to configure uart_pin for pullup --- .../board/CubeMX_Config/CubeMX_Config.ioc | 20 +- .../CubeMX_Config/Src/stm32f0xx_hal_msp.c | 28 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 8 +- .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 18 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 12 +- .../CubeMX_Config/Src/stm32f2xx_hal_msp.c | 28 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 8 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 18 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 10 +- .../CubeMX_Config/Src/stm32f7xx_hal_msp.c | 18 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 10 +- .../CubeMX_Config/Src/stm32h7xx_hal_msp.c | 18 +- .../CubeMX_Config/Src/stm32l1xx_hal_msp.c | 40 +-- .../board/CubeMX_Config/CubeMX_Config.ioc | 8 +- .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 18 +- .../CM4/Src/stm32mp1xx_hal_msp.c | 106 +++---- .../board/CubeMX_Config/CubeMX_Config.ioc | 4 +- .../CubeMX_Config/Src/stm32f0xx_hal_msp.c | 20 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 24 +- .../CubeMX_Config/Src/stm32f0xx_hal_msp.c | 165 +++++------ .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 54 ++-- .../board/CubeMX_Config/CubeMX_Config.ioc | 17 +- .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 151 +++------- .../board/CubeMX_Config/CubeMX_Config.ioc | 10 +- .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 8 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 8 +- .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 72 ++--- .../board/CubeMX_Config/CubeMX_Config.ioc | 8 +- .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 22 +- .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 122 ++++---- .../board/CubeMX_Config/CubeMX_Config.ioc | 6 +- .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 32 +-- .../board/CubeMX_Config/CubeMX_Config.ioc | 16 +- .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 100 +++---- .../board/CubeMX_Config/CubeMX_Config.ioc | 32 ++- .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 62 ++-- .../board/CubeMX_Config/CubeMX_Config.ioc | 8 +- .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 46 +-- .../CubeMX_Config/Src/stm32f1xx_hal_msp.c | 22 +- .../Core/Src/stm32f2xx_hal_msp.c | 2 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 14 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 30 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 4 + .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 18 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 12 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 92 +++--- .../board/CubeMX_Config/CubeMX_Config.ioc | 12 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 10 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 6 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 4 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 35 ++- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 68 ++--- .../board/CubeMX_Config/CubeMX_Config.ioc | 10 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 18 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 12 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 66 ++--- .../board/CubeMX_Config/CubeMX_Config.ioc | 4 + .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 50 ++-- .../board/CubeMX_Config/CubeMX_Config.ioc | 8 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 42 +-- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 30 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 88 +++--- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 136 ++++----- .../board/CubeMX_Config/CubeMX_Config.ioc | 8 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 158 +++++----- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 198 ++++++------- .../board/CubeMX_Config/CubeMX_Config.ioc | 8 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 132 ++++----- .../board/CubeMX_Config/CubeMX_Config.ioc | 12 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 92 +++--- .../board/CubeMX_Config/CubeMX_Config.ioc | 12 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 18 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 6 +- .../CubeMX_Config/Src/stm32f4xx_hal_msp.c | 138 ++++----- .../board/CubeMX_Config/CubeMX_Config.ioc | 9 +- .../CubeMX_Config/Src/stm32f7xx_hal_msp.c | 110 +++---- .../board/CubeMX_Config/CubeMX_Config.ioc | 10 +- .../CubeMX_Config/Src/stm32f7xx_hal_msp.c | 170 +++++------ .../board/CubeMX_Config/CubeMX_Config.ioc | 10 +- .../CubeMX_Config/Src/stm32f7xx_hal_msp.c | 126 ++++---- .../CubeMX_Config/Src/stm32f7xx_hal_msp.c | 46 +-- .../board/CubeMX_Config/CubeMX_Config.ioc | 10 +- .../CubeMX_Config/Src/stm32f7xx_hal_msp.c | 50 ++-- .../CubeMX_Config/Src/stm32g0xx_hal_msp.c | 90 +++--- .../CubeMX_Config/Src/stm32g0xx_hal_msp.c | 112 ++++---- .../board/CubeMX_Config/CubeMX_Config.ioc | 14 +- .../CubeMX_Config/Src/stm32g4xx_hal_msp.c | 62 ++-- .../board/CubeMX_Config/CubeMX_Config.ioc | 14 +- .../CubeMX_Config/Src/stm32h7xx_hal_msp.c | 142 ++++----- .../CubeMX_Config/Src/stm32h7xx_hal_msp.c | 18 +- .../CubeMX_Config/CM4/Src/stm32h7xx_hal_msp.c | 4 +- .../CubeMX_Config/CM7/Src/stm32h7xx_hal_msp.c | 18 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 6 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 10 +- .../CubeMX_Config/Src/stm32h7xx_hal_msp.c | 132 ++++----- bsp/stm32/stm32h750-artpi-h750/.config | 152 +++++++++- .../board/CubeMX_Config/Core/Inc/main.h | 2 +- .../Core/Src/stm32h7xx_hal_msp.c | 6 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 16 +- bsp/stm32/stm32h750-artpi-h750/rtconfig.h | 25 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 4 + .../CubeMX_Config/Src/stm32l0xx_hal_msp.c | 18 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 34 +-- .../CubeMX_Config/Src/stm32l0xx_hal_msp.c | 18 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 4 +- .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 18 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 10 +- .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 30 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 14 +- .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 57 ++-- .../board/CubeMX_Config/CubeMX_Config.ioc | 15 +- .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 44 +-- .../board/CubeMX_Config/CubeMX_Config.ioc | 12 +- .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 44 +-- bsp/stm32/stm32l475-atk-pandora/.config | 3 + .../board/CubeMX_Config/STM32L475VE.ioc | 14 +- .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 10 +- .../stm32l475-atk-pandora/project.uvprojx | 159 +++++----- .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 20 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 7 + .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 92 +++--- .../board/CubeMX_Config/CubeMX_Config.ioc | 8 + .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 108 +++---- .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 32 +-- .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 30 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 6 +- .../CubeMX_Config/Src/stm32l4xx_hal_msp.c | 64 ++--- .../CM4/Src/stm32mp1xx_hal_msp.c | 150 +++++----- .../CM4/Src/stm32mp1xx_hal_msp.c | 272 +++++++++--------- .../CubeMX_Config/Src/stm32wbxx_hal_msp.c | 4 +- .../board/CubeMX_Config/CubeMX_Config.ioc | 10 +- .../CubeMX_Config/Src/stm32wlxx_hal_msp.c | 2 +- 132 files changed, 2903 insertions(+), 2704 deletions(-) diff --git a/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/CubeMX_Config.ioc index 1094ab3d37..976274a19f 100644 --- a/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/CubeMX_Config.ioc @@ -31,20 +31,22 @@ NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.SVC_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false -PA10.Mode=Synchronous -PA10.Signal=USART1_RX -PA13.Mode=Serial_Wire -PA13.Signal=SYS_SWDIO -PA14.Mode=Serial_Wire -PA14.Signal=SYS_SWCLK +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX -PA8.Mode=Synchronous -PA8.Signal=USART1_CK -PA9.Mode=Synchronous +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP +PA10.Mode=Asynchronous +PA10.Signal=USART1_RX PCC.Checker=false PCC.Line=STM32F0x1 PCC.MCU=STM32F091R(B-C)Tx diff --git a/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c index db20df68eb..d8fd04634f 100644 --- a/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32f0xx/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f0xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -114,12 +114,11 @@ void HAL_USART_MspInit(USART_HandleTypeDef* husart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA8 ------> USART1_CK PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -152,11 +151,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -189,11 +188,11 @@ void HAL_USART_MspDeInit(USART_HandleTypeDef* husart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA8 ------> USART1_CK PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10); @@ -221,10 +220,9 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); diff --git a/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/CubeMX_Config.ioc index ebb24e61e1..fc443045df 100644 --- a/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/CubeMX_Config.ioc @@ -33,14 +33,18 @@ NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PCC.Checker=false PCC.Line=STM32F103 PCC.MCU=STM32F103R(8-B)Tx diff --git a/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index 20076a51b8..7c454fe98f 100644 --- a/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32f10x/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -92,7 +92,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled + /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); @@ -117,11 +117,10 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -158,10 +157,9 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); diff --git a/bsp/stm32/libraries/templates/stm32f2xx/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/libraries/templates/stm32f2xx/board/CubeMX_Config/CubeMX_Config.ioc index 020f6ec89f..d61f038985 100644 --- a/bsp/stm32/libraries/templates/stm32f2xx/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/libraries/templates/stm32f2xx/board/CubeMX_Config/CubeMX_Config.ioc @@ -35,16 +35,24 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX +PC6.GPIOParameters=GPIO_PuPd +PC6.GPIO_PuPd=GPIO_PULLUP PC6.Mode=Asynchronous PC6.Signal=USART6_TX +PC7.GPIOParameters=GPIO_PuPd +PC7.GPIO_PuPd=GPIO_PULLUP PC7.Mode=Asynchronous PC7.Signal=USART6_RX PCC.Checker=false diff --git a/bsp/stm32/libraries/templates/stm32f2xx/board/CubeMX_Config/Src/stm32f2xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32f2xx/board/CubeMX_Config/Src/stm32f2xx_hal_msp.c index 14b4f29801..b82ce057a6 100644 --- a/bsp/stm32/libraries/templates/stm32f2xx/board/CubeMX_Config/Src/stm32f2xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32f2xx/board/CubeMX_Config/Src/stm32f2xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f2xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -93,11 +93,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -117,11 +117,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART6_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART6_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**USART6 GPIO Configuration + /**USART6 GPIO Configuration PC6 ------> USART6_TX - PC7 ------> USART6_RX + PC7 ------> USART6_RX */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -152,10 +152,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -170,10 +170,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART6_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART6_CLK_DISABLE(); - - /**USART6 GPIO Configuration + + /**USART6 GPIO Configuration PC6 ------> USART6_TX - PC7 ------> USART6_RX + PC7 ------> USART6_RX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_6|GPIO_PIN_7); diff --git a/bsp/stm32/libraries/templates/stm32f4xx/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/libraries/templates/stm32f4xx/board/CubeMX_Config/CubeMX_Config.ioc index 819eb4c535..af20b2f559 100644 --- a/bsp/stm32/libraries/templates/stm32f4xx/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/libraries/templates/stm32f4xx/board/CubeMX_Config/CubeMX_Config.ioc @@ -33,14 +33,18 @@ NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PCC.Checker=false PCC.Line=STM32F407/417 PCC.MCU=STM32F407Z(E-G)Tx diff --git a/bsp/stm32/libraries/templates/stm32f4xx/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32f4xx/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index e00b8556d6..5317e6153f 100644 --- a/bsp/stm32/libraries/templates/stm32f4xx/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32f4xx/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -114,11 +114,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -154,10 +154,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); diff --git a/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/CubeMX_Config.ioc index f448b00af0..48a95f7173 100644 --- a/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/CubeMX_Config.ioc @@ -32,12 +32,14 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false -PA10.Locked=true -PA10.Mode=Asynchronous -PA10.Signal=USART1_RX -PA9.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP PA9.Mode=Asynchronous PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP +PA10.Mode=Asynchronous +PA10.Signal=USART1_RX PCC.Checker=false PCC.Line=STM32F7x7 PCC.MCU=STM32F767I(G-I)Tx diff --git a/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c index 748daa1a43..5d95c709fb 100644 --- a/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32f7xx/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -114,11 +114,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -151,10 +151,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); diff --git a/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/CubeMX_Config.ioc index 9e9e62d7db..714cc55bde 100644 --- a/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/CubeMX_Config.ioc @@ -34,16 +34,18 @@ NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false -PA10.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13\ (JTMS/SWDIO).Mode=Serial_Wire PA13\ (JTMS/SWDIO).Signal=SYS_JTMS-SWDIO PA14\ (JTCK/SWCLK).Mode=Serial_Wire PA14\ (JTCK/SWCLK).Signal=SYS_JTCK-SWCLK -PA9.Locked=true -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PCC.Checker=false PCC.Line=STM32H743/753 PCC.MCU=STM32H743IITx diff --git a/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c index 67cb6361c7..552069eb52 100644 --- a/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32h7xx/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32h7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -113,11 +113,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -153,10 +153,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); diff --git a/bsp/stm32/libraries/templates/stm32l1xx/board/CubeMX_Config/Src/stm32l1xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32l1xx/board/CubeMX_Config/Src/stm32l1xx_hal_msp.c index 395a337aac..b0a59f2049 100644 --- a/bsp/stm32/libraries/templates/stm32l1xx/board/CubeMX_Config/Src/stm32l1xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32l1xx/board/CubeMX_Config/Src/stm32l1xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32l1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -138,12 +138,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -174,11 +174,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); @@ -205,11 +205,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -232,11 +232,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -270,10 +270,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -290,10 +290,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); diff --git a/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/CubeMX_Config.ioc index 7cc72b8dbf..63350ae9c7 100644 --- a/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/CubeMX_Config.ioc @@ -33,14 +33,18 @@ NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13\ (JTMS-SWDIO).Mode=Serial_Wire PA13\ (JTMS-SWDIO).Signal=SYS_JTMS-SWDIO PA14\ (JTCK-SWCLK).Mode=Serial_Wire PA14\ (JTCK-SWCLK).Signal=SYS_JTCK-SWCLK -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PCC.Checker=true PCC.Line=STM32L4x5 PCC.MCU=STM32L475V(C-E-G)Tx diff --git a/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index dcc0912216..656979eb4d 100644 --- a/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32l4xx/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -114,11 +114,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -154,10 +154,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); diff --git a/bsp/stm32/libraries/templates/stm32mp1xx/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c b/bsp/stm32/libraries/templates/stm32mp1xx/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c index dec360176a..1fe94b4913 100644 --- a/bsp/stm32/libraries/templates/stm32mp1xx/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c +++ b/bsp/stm32/libraries/templates/stm32mp1xx/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32mp1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -33,7 +33,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -59,7 +59,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -77,11 +77,11 @@ void HAL_MspInit(void) /* USER CODE BEGIN MspInit 1 */ if(IS_ENGINEERING_BOOT_MODE()) { -#if defined(BSP_USING_ADC) || defined(BSP_USING_DAC) +#if defined(BSP_USING_ADC) || defined(BSP_USING_DAC) /* Configure PMIC */ BSP_PMIC_Init(); BSP_PMIC_InitRegulators(); - + __HAL_RCC_VREF_CLK_ENABLE(); HAL_SYSCFG_VREFBUF_HighImpedanceConfig(SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE); HAL_SYSCFG_EnableVREFBUF(); @@ -107,7 +107,7 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC2_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PER; @@ -120,10 +120,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* Peripheral clock enable */ __HAL_RCC_ADC12_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); - /**ADC2 GPIO Configuration - PF14 ------> ADC2_INP6 + /**ADC2 GPIO Configuration + PF14 ------> ADC2_INP6 */ GPIO_InitStruct.Pin = GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -150,9 +150,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC12_CLK_DISABLE(); - - /**ADC2 GPIO Configuration - PF14 ------> ADC2_INP6 + + /**ADC2 GPIO Configuration + PF14 ------> ADC2_INP6 */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_14); @@ -179,10 +179,10 @@ void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac) /* USER CODE END DAC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_DAC12_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**DAC1 GPIO Configuration - PA4 ------> DAC1_OUT1 + /**DAC1 GPIO Configuration + PA4 ------> DAC1_OUT1 */ GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -210,9 +210,9 @@ void HAL_DAC_MspDeInit(DAC_HandleTypeDef* hdac) /* USER CODE END DAC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_DAC12_CLK_DISABLE(); - - /**DAC1 GPIO Configuration - PA4 ------> DAC1_OUT1 + + /**DAC1 GPIO Configuration + PA4 ------> DAC1_OUT1 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4); @@ -292,7 +292,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) /* USER CODE END LPTIM1_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1; PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_PCLK1; @@ -320,7 +320,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM23; PeriphClkInit.Lptim23ClockSelection = RCC_LPTIM23CLKSOURCE_PCLK3; @@ -348,7 +348,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM23; PeriphClkInit.Lptim23ClockSelection = RCC_LPTIM23CLKSOURCE_PCLK3; @@ -376,7 +376,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM45; PeriphClkInit.Lptim45ClockSelection = RCC_LPTIM45CLKSOURCE_PCLK3; @@ -404,7 +404,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM45; PeriphClkInit.Lptim45ClockSelection = RCC_LPTIM45CLKSOURCE_PCLK3; @@ -525,7 +525,7 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI45; PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PCLK2; @@ -538,11 +538,11 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* Peripheral clock enable */ __HAL_RCC_SPI5_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); - /**SPI5 GPIO Configuration + /**SPI5 GPIO Configuration PF9 ------> SPI5_MOSI - PF7 ------> SPI5_SCK + PF7 ------> SPI5_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -573,10 +573,10 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI5_CLK_DISABLE(); - - /**SPI5 GPIO Configuration + + /**SPI5 GPIO Configuration PF9 ------> SPI5_MOSI - PF7 ------> SPI5_SCK + PF7 ------> SPI5_SCK */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_9|GPIO_PIN_7); @@ -650,10 +650,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM4_MspPostInit 0 */ /* USER CODE END TIM4_MspPostInit 0 */ - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**TIM4 GPIO Configuration - PD13 ------> TIM4_CH2 + /**TIM4 GPIO Configuration + PD13 ------> TIM4_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -740,7 +740,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspInit 0 */ if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_UART24; PeriphClkInit.Uart24ClockSelection = RCC_UART24CLKSOURCE_HSI; @@ -753,12 +753,12 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* Peripheral clock enable */ __HAL_RCC_UART4_CLK_ENABLE(); - + __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**UART4 GPIO Configuration + /**UART4 GPIO Configuration PG11 ------> UART4_TX - PB2 ------> UART4_RX + PB2 ------> UART4_RX */ GPIO_InitStruct.Pin = STLINK_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -785,7 +785,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) if(IS_ENGINEERING_BOOT_MODE()) { - /** Initializes the peripherals clock + /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_UART35; PeriphClkInit.Uart35ClockSelection = RCC_UART35CLKSOURCE_PCLK1; @@ -798,11 +798,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB12 ------> USART3_RX + PB12 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -839,10 +839,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART4_CLK_DISABLE(); - - /**UART4 GPIO Configuration + + /**UART4 GPIO Configuration PG11 ------> UART4_TX - PB2 ------> UART4_RX + PB2 ------> UART4_RX */ HAL_GPIO_DeInit(STLINK_RX_GPIO_Port, STLINK_RX_Pin); @@ -859,10 +859,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB12 ------> USART3_RX + PB12 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_12); @@ -908,12 +908,12 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hI2c) { GPIO_InitTypeDef GPIO_InitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - + if(hI2c->Instance == I2C4) { if(IS_ENGINEERING_BOOT_MODE()) { - /*** Configure the I2C peripheral clock ***/ + /*** Configure the I2C peripheral clock ***/ PeriphClkInit.I2c46ClockSelection = RCC_I2C46CLKSOURCE_HSI; PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C46; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) @@ -935,11 +935,11 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hI2c) /* Enable I2C clock */ __HAL_RCC_I2C4_CLK_ENABLE(); - /* Force the I2C peripheral clock reset */ + /* Force the I2C peripheral clock reset */ __HAL_RCC_I2C4_FORCE_RESET(); - /* Release the I2C peripheral clock reset */ + /* Release the I2C peripheral clock reset */ __HAL_RCC_I2C4_RELEASE_RESET(); - + HAL_NVIC_SetPriority(I2C4_ER_IRQn, 0, 1); HAL_NVIC_EnableIRQ(I2C4_ER_IRQn); HAL_NVIC_SetPriority(I2C4_EV_IRQn, 0, 2); @@ -955,7 +955,7 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hI2c) void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hI2c) { GPIO_InitTypeDef GPIO_InitStruct = {0}; - + if(hI2c->Instance == I2C4) { /* Configure I2C Tx, Rx as alternate function */ diff --git a/bsp/stm32/stm32f072-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f072-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index e62fa13da5..1009ded5e2 100644 --- a/bsp/stm32/stm32f072-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f072-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -44,7 +44,7 @@ PA14.Signal=SYS_SWCLK PA2.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode PA2.GPIO_Label=USART_TX PA2.GPIO_Mode=GPIO_MODE_AF_PP -PA2.GPIO_PuPd=GPIO_NOPULL +PA2.GPIO_PuPd=GPIO_PULLUP PA2.GPIO_Speed=GPIO_SPEED_FREQ_LOW PA2.Locked=true PA2.Mode=Asynchronous @@ -52,7 +52,7 @@ PA2.Signal=USART2_TX PA3.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode PA3.GPIO_Label=USART_RX PA3.GPIO_Mode=GPIO_MODE_AF_PP -PA3.GPIO_PuPd=GPIO_NOPULL +PA3.GPIO_PuPd=GPIO_PULLUP PA3.GPIO_Speed=GPIO_SPEED_FREQ_LOW PA3.Locked=true PA3.Mode=Asynchronous diff --git a/bsp/stm32/stm32f072-st-nucleo/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c b/bsp/stm32/stm32f072-st-nucleo/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c index 907465857b..7fd27fea17 100644 --- a/bsp/stm32/stm32f072-st-nucleo/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c +++ b/bsp/stm32/stm32f072-st-nucleo/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f0xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -113,15 +113,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = USART_TX_Pin|USART_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF1_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -148,10 +148,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, USART_TX_Pin|USART_RX_Pin); diff --git a/bsp/stm32/stm32f091-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f091-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index 75eb3b8646..d1e0132661 100644 --- a/bsp/stm32/stm32f091-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f091-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -37,9 +37,9 @@ Mcu.Pin4=PA3 Mcu.Pin5=PA6 Mcu.Pin6=PA7 Mcu.Pin7=PB11 -Mcu.Pin8=PA8 -Mcu.Pin9=PA9 -Mcu.PinsNb=21 +Mcu.Pin8=PA9 +Mcu.Pin9=PA10 +Mcu.PinsNb=20 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32F091RCTx @@ -52,23 +52,29 @@ NVIC.SVC_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true PA0.Mode=IN0 PA0.Signal=ADC_IN0 -PA10.Mode=Synchronous +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP +PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire PA13.Signal=SYS_SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_SWCLK +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX PA6.Mode=Full_Duplex_Master PA6.Signal=SPI1_MISO PA7.Mode=Full_Duplex_Master PA7.Signal=SPI1_MOSI -PA8.Mode=Synchronous -PA8.Signal=USART1_CK -PA9.Mode=Synchronous +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous PA9.Signal=USART1_TX PB11.Signal=S_TIM2_CH4 PB3.Locked=true @@ -147,8 +153,8 @@ SPI1.Mode=SPI_MODE_MASTER SPI1.VirtualType=VM_MASTER TIM2.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4 TIM2.IPParameters=Channel-PWM Generation4 CH4 -USART1.IPParameters=VirtualMode-Synchronous -USART1.VirtualMode-Synchronous=VM_SYNC +USART1.IPParameters=VirtualMode-Asynchronous +USART1.VirtualMode-Asynchronous=VM_ASYNC USART2.IPParameters=VirtualMode-Asynchronous USART2.VirtualMode-Asynchronous=VM_ASYNC VP_IWDG_VS_IWDG.Mode=IWDG_Activate diff --git a/bsp/stm32/stm32f091-st-nucleo/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c b/bsp/stm32/stm32f091-st-nucleo/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c index 112b9931e2..700fcc0dfd 100644 --- a/bsp/stm32/stm32f091-st-nucleo/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c +++ b/bsp/stm32/stm32f091-st-nucleo/board/CubeMX_Config/Src/stm32f0xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f0xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -115,10 +115,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**ADC GPIO Configuration - PA0 ------> ADC_IN0 + /**ADC GPIO Configuration + PA0 ------> ADC_IN0 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -147,9 +147,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC GPIO Configuration - PA0 ------> ADC_IN0 + + /**ADC GPIO Configuration + PA0 ------> ADC_IN0 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0); @@ -220,13 +220,13 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI - PB3 ------> SPI1_SCK + PB3 ------> SPI1_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -264,11 +264,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI - PB3 ------> SPI1_SCK + PB3 ------> SPI1_SCK */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_6|GPIO_PIN_7); @@ -344,10 +344,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM2_MspPostInit 0 */ /* USER CODE END TIM2_MspPostInit 0 */ - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**TIM2 GPIO Configuration - PB11 ------> TIM2_CH4 + /**TIM2 GPIO Configuration + PB11 ------> TIM2_CH4 */ GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -417,43 +417,6 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base) } -/** -* @brief USART MSP Initialization -* This function configures the hardware resources used in this example -* @param husart: USART handle pointer -* @retval None -*/ -void HAL_USART_MspInit(USART_HandleTypeDef* husart) -{ - GPIO_InitTypeDef GPIO_InitStruct = {0}; - if(husart->Instance==USART1) - { - /* USER CODE BEGIN USART1_MspInit 0 */ - - /* USER CODE END USART1_MspInit 0 */ - /* Peripheral clock enable */ - __HAL_RCC_USART1_CLK_ENABLE(); - - __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration - PA8 ------> USART1_CK - PA9 ------> USART1_TX - PA10 ------> USART1_RX - */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF1_USART1; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - /* USER CODE BEGIN USART1_MspInit 1 */ - - /* USER CODE END USART1_MspInit 1 */ - } - -} - /** * @brief UART MSP Initialization * This function configures the hardware resources used in this example @@ -463,22 +426,46 @@ void HAL_USART_MspInit(USART_HandleTypeDef* husart) void HAL_UART_MspInit(UART_HandleTypeDef* huart) { GPIO_InitTypeDef GPIO_InitStruct = {0}; - if(huart->Instance==USART2) + if(huart->Instance==USART1) + { + /* USER CODE BEGIN USART1_MspInit 0 */ + + /* USER CODE END USART1_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_USART1_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USART1 GPIO Configuration + PA9 ------> USART1_TX + PA10 ------> USART1_RX + */ + GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF1_USART1; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USER CODE BEGIN USART1_MspInit 1 */ + + /* USER CODE END USART1_MspInit 1 */ + } + else if(huart->Instance==USART2) { /* USER CODE BEGIN USART2_MspInit 0 */ /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF1_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -490,36 +477,6 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) } -/** -* @brief USART MSP De-Initialization -* This function freeze the hardware resources used in this example -* @param husart: USART handle pointer -* @retval None -*/ -void HAL_USART_MspDeInit(USART_HandleTypeDef* husart) -{ - if(husart->Instance==USART1) - { - /* USER CODE BEGIN USART1_MspDeInit 0 */ - - /* USER CODE END USART1_MspDeInit 0 */ - /* Peripheral clock disable */ - __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration - PA8 ------> USART1_CK - PA9 ------> USART1_TX - PA10 ------> USART1_RX - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10); - - /* USER CODE BEGIN USART1_MspDeInit 1 */ - - /* USER CODE END USART1_MspDeInit 1 */ - } - -} - /** * @brief UART MSP De-Initialization * This function freeze the hardware resources used in this example @@ -528,17 +485,35 @@ void HAL_USART_MspDeInit(USART_HandleTypeDef* husart) */ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) { - if(huart->Instance==USART2) + if(huart->Instance==USART1) + { + /* USER CODE BEGIN USART1_MspDeInit 0 */ + + /* USER CODE END USART1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART1_CLK_DISABLE(); + + /**USART1 GPIO Configuration + PA9 ------> USART1_TX + PA10 ------> USART1_RX + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); + + /* USER CODE BEGIN USART1_MspDeInit 1 */ + + /* USER CODE END USART1_MspDeInit 1 */ + } + else if(huart->Instance==USART2) { /* USER CODE BEGIN USART2_MspDeInit 0 */ /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); diff --git a/bsp/stm32/stm32f103-atk-nano/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/stm32f103-atk-nano/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index a38a7f26b1..e113c72475 100644 --- a/bsp/stm32/stm32f103-atk-nano/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/stm32f103-atk-nano/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -94,7 +94,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled + /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); @@ -120,10 +120,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PB1 ------> ADC1_IN9 + /**ADC1 GPIO Configuration + PB1 ------> ADC1_IN9 */ GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -153,9 +153,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration - PB1 ------> ADC1_IN9 + + /**ADC1 GPIO Configuration + PB1 ------> ADC1_IN9 */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_1); @@ -233,12 +233,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -274,11 +274,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); @@ -343,11 +343,11 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM3_MspPostInit 0 */ /* USER CODE END TIM3_MspPostInit 0 */ - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**TIM3 GPIO Configuration + /**TIM3 GPIO Configuration PC6 ------> TIM3_CH1 - PC7 ------> TIM3_CH2 + PC7 ------> TIM3_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -424,11 +424,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -437,7 +437,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1 interrupt Init */ @@ -465,10 +465,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); diff --git a/bsp/stm32/stm32f103-atk-warshipv3/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f103-atk-warshipv3/board/CubeMX_Config/CubeMX_Config.ioc index ab50887fd8..80c986136d 100644 --- a/bsp/stm32/stm32f103-atk-warshipv3/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f103-atk-warshipv3/board/CubeMX_Config/CubeMX_Config.ioc @@ -95,12 +95,16 @@ OSC_IN.Mode=HSE-External-Oscillator OSC_IN.Signal=RCC_OSC_IN OSC_OUT.Mode=HSE-External-Oscillator OSC_OUT.Signal=RCC_OSC_OUT +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP PA9.Mode=Asynchronous PA9.Signal=USART1_TX PC10.Mode=SD_4_bits_Wide_bus @@ -121,14 +125,6 @@ PC8.Mode=SD_4_bits_Wide_bus PC8.Signal=SDIO_D0 PC9.Mode=SD_4_bits_Wide_bus PC9.Signal=SDIO_D1 -PCC.Checker=false -PCC.Line=STM32F103 -PCC.MCU=STM32F103Z(C-D-E)Tx -PCC.PartNumber=STM32F103ZETx -PCC.Seq0=0 -PCC.Series=STM32F1 -PCC.Temperature=25 -PCC.Vdd=3.3 PD0.Signal=FSMC_D2_DA2 PD1.Signal=FSMC_D3_DA3 PD10.Signal=FSMC_D15_DA15 @@ -184,7 +180,7 @@ ProjectManager.CustomerFirmwarePackage= ProjectManager.DefaultFWLocation=true ProjectManager.DeletePrevious=true ProjectManager.DeviceId=STM32F103ZETx -ProjectManager.FirmwarePackage=STM32Cube FW_F1 V1.8.0 +ProjectManager.FirmwarePackage=STM32Cube FW_F1 V1.8.4 ProjectManager.FreePins=false ProjectManager.HalAssertFull=false ProjectManager.HeapSize=0x200 @@ -197,11 +193,12 @@ ProjectManager.PreviousToolchain= ProjectManager.ProjectBuild=false ProjectManager.ProjectFileName=CubeMX_Config.ioc ProjectManager.ProjectName=CubeMX_Config +ProjectManager.RegisterCallBack= ProjectManager.StackSize=0x400 ProjectManager.TargetToolchain=MDK-ARM V5 ProjectManager.ToolChainLocation= ProjectManager.UnderRoot=false -ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_USART1_UART_Init-USART1-false-HAL-true,4-MX_FSMC_Init-FSMC-false-HAL-true,5-MX_TIM3_Init-TIM3-false-HAL-true +ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_USART1_UART_Init-USART1-false-HAL-true,4-MX_FSMC_Init-FSMC-false-HAL-true,5-MX_TIM3_Init-TIM3-false-HAL-true,6-MX_SDIO_SD_Init-SDIO-false-HAL-true RCC.ADCFreqValue=36000000 RCC.AHBFreq_Value=72000000 RCC.APB1CLKDivider=RCC_HCLK_DIV2 diff --git a/bsp/stm32/stm32f103-atk-warshipv3/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/stm32f103-atk-warshipv3/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index 5a7f5eedf6..f852a2c104 100644 --- a/bsp/stm32/stm32f103-atk-warshipv3/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/stm32f103-atk-warshipv3/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -72,7 +72,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled + /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); @@ -97,18 +97,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDIO_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDIO GPIO Configuration + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; @@ -141,16 +141,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDIO_CLK_DISABLE(); - - /**SDIO GPIO Configuration + + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -178,11 +178,11 @@ void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* htim_encoder) /* USER CODE END TIM3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_TIM3_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**TIM3 GPIO Configuration + /**TIM3 GPIO Configuration PC6 ------> TIM3_CH1 - PC7 ------> TIM3_CH2 + PC7 ------> TIM3_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; @@ -213,10 +213,10 @@ void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* htim_encoder) /* USER CODE END TIM3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_TIM3_CLK_DISABLE(); - - /**TIM3 GPIO Configuration + + /**TIM3 GPIO Configuration PC6 ------> TIM3_CH1 - PC7 ------> TIM3_CH2 + PC7 ------> TIM3_CH2 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_6|GPIO_PIN_7); @@ -243,11 +243,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -256,7 +256,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART1_MspInit 1 */ @@ -281,10 +281,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -294,73 +294,6 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) } } -/** -* @brief CAN MSP Initialization -* This function configures the hardware resources used in this example -* @param hcan: CAN handle pointer -* @retval None -*/ -void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan) -{ - GPIO_InitTypeDef GPIO_InitStruct = {0}; - if(hcan->Instance==CAN1) - { - /* USER CODE BEGIN CAN1_MspInit 0 */ - - /* USER CODE END CAN1_MspInit 0 */ - /* Peripheral clock enable */ - __HAL_RCC_CAN1_CLK_ENABLE(); - - __HAL_RCC_GPIOA_CLK_ENABLE(); - /**CAN GPIO Configuration - PA11 ------> CAN_RX - PA12 ------> CAN_TX - */ - GPIO_InitStruct.Pin = GPIO_PIN_11; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = GPIO_PIN_12; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - /* USER CODE BEGIN CAN1_MspInit 1 */ - - /* USER CODE END CAN1_MspInit 1 */ - } - -} -/** -* @brief CAN MSP De-Initialization -* This function freeze the hardware resources used in this example -* @param hcan: CAN handle pointer -* @retval None -*/ -void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan) -{ - if(hcan->Instance==CAN1) - { - /* USER CODE BEGIN CAN1_MspDeInit 0 */ - - /* USER CODE END CAN1_MspDeInit 0 */ - /* Peripheral clock disable */ - __HAL_RCC_CAN1_CLK_DISABLE(); - - /**CAN GPIO Configuration - PA11 ------> CAN_RX - PA12 ------> CAN_TX - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); - - /* USER CODE BEGIN CAN1_MspDeInit 1 */ - - /* USER CODE END CAN1_MspDeInit 1 */ - } - -} - static uint32_t FSMC_Initialized = 0; @@ -376,8 +309,8 @@ static void HAL_FSMC_MspInit(void){ /* Peripheral clock enable */ __HAL_RCC_FSMC_CLK_ENABLE(); - - /** FSMC GPIO Configuration + + /** FSMC GPIO Configuration PF0 ------> FSMC_A0 PF1 ------> FSMC_A1 PF2 ------> FSMC_A2 @@ -419,28 +352,28 @@ static void HAL_FSMC_MspInit(void){ PE0 ------> FSMC_NBL0 PE1 ------> FSMC_NBL1 */ - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13 |GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 - |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15 |GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; @@ -473,8 +406,8 @@ static void HAL_FSMC_MspDeInit(void){ FSMC_DeInitialized = 1; /* Peripheral clock enable */ __HAL_RCC_FSMC_CLK_DISABLE(); - - /** FSMC GPIO Configuration + + /** FSMC GPIO Configuration PF0 ------> FSMC_A0 PF1 ------> FSMC_A1 PF2 ------> FSMC_A2 @@ -516,19 +449,19 @@ static void HAL_FSMC_MspDeInit(void){ PE0 ------> FSMC_NBL0 PE1 ------> FSMC_NBL1 */ - HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13 + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13 |GPIO_PIN_14|GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_10); - HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1); - HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 - |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15 + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15 |GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5); /* USER CODE BEGIN FSMC_MspDeInit 1 */ diff --git a/bsp/stm32/stm32f103-blue-pill/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f103-blue-pill/board/CubeMX_Config/CubeMX_Config.ioc index d9aadc3758..f3db8820e8 100644 --- a/bsp/stm32/stm32f103-blue-pill/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f103-blue-pill/board/CubeMX_Config/CubeMX_Config.ioc @@ -57,6 +57,8 @@ NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false PA1.Signal=ADCx_IN1 +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA11.Mode=Device @@ -67,8 +69,12 @@ PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX PA5.Mode=Full_Duplex_Master @@ -77,6 +83,8 @@ PA6.Mode=Full_Duplex_Master PA6.Signal=SPI1_MISO PA7.Mode=Full_Duplex_Master PA7.Signal=SPI1_MOSI +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP PA9.Mode=Asynchronous PA9.Signal=USART1_TX PC13-TAMPER-RTC.GPIOParameters=GPIO_Speed,PinState,GPIO_ModeDefaultOutputPP @@ -103,7 +111,7 @@ ProjectManager.CustomerFirmwarePackage= ProjectManager.DefaultFWLocation=true ProjectManager.DeletePrevious=true ProjectManager.DeviceId=STM32F103C8Tx -ProjectManager.FirmwarePackage=STM32Cube FW_F1 V1.8.3 +ProjectManager.FirmwarePackage=STM32Cube FW_F1 V1.8.4 ProjectManager.FreePins=false ProjectManager.HalAssertFull=false ProjectManager.HeapSize=0x200 diff --git a/bsp/stm32/stm32f103-blue-pill/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/stm32f103-blue-pill/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index d48771f71d..a6d94ecced 100644 --- a/bsp/stm32/stm32f103-blue-pill/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/stm32f103-blue-pill/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -287,7 +287,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART1_MspInit 1 */ @@ -314,7 +314,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART2_MspInit 1 */ diff --git a/bsp/stm32/stm32f103-dofly-M3S/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f103-dofly-M3S/board/CubeMX_Config/CubeMX_Config.ioc index e897be5421..80ad293e6c 100644 --- a/bsp/stm32/stm32f103-dofly-M3S/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f103-dofly-M3S/board/CubeMX_Config/CubeMX_Config.ioc @@ -57,6 +57,12 @@ OSC_IN.Mode=HSE-External-Oscillator OSC_IN.Signal=RCC_OSC_IN OSC_OUT.Mode=HSE-External-Oscillator OSC_OUT.Signal=RCC_OSC_OUT +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire @@ -69,8 +75,6 @@ PA6.Mode=Full_Duplex_Master PA6.Signal=SPI1_MISO PA7.Mode=Full_Duplex_Master PA7.Signal=SPI1_MOSI -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PB13.Mode=Full_Duplex_Master PB13.Signal=SPI2_SCK PB14.Mode=Full_Duplex_Master diff --git a/bsp/stm32/stm32f103-dofly-M3S/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/stm32f103-dofly-M3S/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index 1efbf77d5e..e076325291 100644 --- a/bsp/stm32/stm32f103-dofly-M3S/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/stm32f103-dofly-M3S/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -72,7 +72,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled + /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); @@ -97,18 +97,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDIO_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDIO GPIO Configuration + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; @@ -141,16 +141,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDIO_CLK_DISABLE(); - - /**SDIO GPIO Configuration + + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -178,12 +178,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -206,12 +206,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -234,12 +234,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI3 GPIO Configuration + /**SPI3 GPIO Configuration PB3 ------> SPI3_SCK PB4 ------> SPI3_MISO - PB5 ------> SPI3_MOSI + PB5 ------> SPI3_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -273,11 +273,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); @@ -292,11 +292,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); @@ -311,11 +311,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI3_CLK_DISABLE(); - - /**SPI3 GPIO Configuration + + /**SPI3 GPIO Configuration PB3 ------> SPI3_SCK PB4 ------> SPI3_MISO - PB5 ------> SPI3_MOSI + PB5 ------> SPI3_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5); @@ -342,11 +342,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -355,7 +355,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART1_MspInit 1 */ @@ -380,10 +380,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); diff --git a/bsp/stm32/stm32f103-dofly-lyc8/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f103-dofly-lyc8/board/CubeMX_Config/CubeMX_Config.ioc index e2768b2045..fcd3cd934e 100644 --- a/bsp/stm32/stm32f103-dofly-lyc8/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f103-dofly-lyc8/board/CubeMX_Config/CubeMX_Config.ioc @@ -34,14 +34,18 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PC14-OSC32_IN.Mode=LSE-External-Oscillator PC14-OSC32_IN.Signal=RCC_OSC32_IN PC15-OSC32_OUT.Mode=LSE-External-Oscillator diff --git a/bsp/stm32/stm32f103-dofly-lyc8/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/stm32f103-dofly-lyc8/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index b22009fcdb..87bfedec78 100644 --- a/bsp/stm32/stm32f103-dofly-lyc8/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/stm32f103-dofly-lyc8/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -92,7 +92,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled + /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); @@ -118,11 +118,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -131,7 +131,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART1_MspInit 1 */ @@ -158,10 +158,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); diff --git a/bsp/stm32/stm32f103-fire-arbitrary/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/stm32f103-fire-arbitrary/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index c27983df23..1f33ad7e90 100644 --- a/bsp/stm32/stm32f103-fire-arbitrary/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/stm32f103-fire-arbitrary/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -94,7 +94,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled + /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); @@ -119,10 +119,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PC1 ------> ADC1_IN11 + /**ADC1 GPIO Configuration + PC1 ------> ADC1_IN11 */ GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -150,9 +150,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration - PC1 ------> ADC1_IN11 + + /**ADC1 GPIO Configuration + PC1 ------> ADC1_IN11 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1); @@ -179,11 +179,11 @@ void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan) /* USER CODE END CAN1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_CAN1_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**CAN GPIO Configuration + /**CAN GPIO Configuration PB8 ------> CAN_RX - PB9 ------> CAN_TX + PB9 ------> CAN_TX */ GPIO_InitStruct.Pin = GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; @@ -219,10 +219,10 @@ void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan) /* USER CODE END CAN1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_CAN1_CLK_DISABLE(); - - /**CAN GPIO Configuration + + /**CAN GPIO Configuration PB8 ------> CAN_RX - PB9 ------> CAN_TX + PB9 ------> CAN_TX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9); @@ -296,18 +296,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDIO_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDIO GPIO Configuration + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; @@ -340,16 +340,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDIO_CLK_DISABLE(); - - /**SDIO GPIO Configuration + + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -377,12 +377,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -405,12 +405,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -444,11 +444,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); @@ -463,11 +463,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); @@ -541,12 +541,12 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM3_MspPostInit 0 */ /* USER CODE END TIM3_MspPostInit 0 */ - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**TIM3 GPIO Configuration + /**TIM3 GPIO Configuration PB0 ------> TIM3_CH3 PB1 ------> TIM3_CH4 - PB5 ------> TIM3_CH2 + PB5 ------> TIM3_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -632,11 +632,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -645,7 +645,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1 interrupt Init */ @@ -662,11 +662,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -675,7 +675,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART2_MspInit 1 */ @@ -689,11 +689,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -702,7 +702,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USER CODE BEGIN USART3_MspInit 1 */ @@ -727,10 +727,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -747,10 +747,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); @@ -765,10 +765,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); diff --git a/bsp/stm32/stm32f103-gizwits-gokitv21/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f103-gizwits-gokitv21/board/CubeMX_Config/CubeMX_Config.ioc index 360fb08070..54b134346f 100644 --- a/bsp/stm32/stm32f103-gizwits-gokitv21/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f103-gizwits-gokitv21/board/CubeMX_Config/CubeMX_Config.ioc @@ -34,6 +34,10 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX PA10.GPIOParameters=GPIO_PuPd PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous @@ -42,8 +46,6 @@ PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PC14-OSC32_IN.Mode=LSE-External-Oscillator PC14-OSC32_IN.Signal=RCC_OSC32_IN PC15-OSC32_OUT.Mode=LSE-External-Oscillator diff --git a/bsp/stm32/stm32f103-gizwits-gokitv21/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/stm32f103-gizwits-gokitv21/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index 12171ceb42..3ee3a6eac5 100644 --- a/bsp/stm32/stm32f103-gizwits-gokitv21/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/stm32f103-gizwits-gokitv21/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -72,7 +72,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled + /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); @@ -97,11 +97,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -117,7 +117,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 1 */ } - + if(huart->Instance==USART2) { /* USER CODE BEGIN USART2_MspInit 0 */ @@ -125,11 +125,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -163,10 +163,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -181,10 +181,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); diff --git a/bsp/stm32/stm32f103-hw100k-ibox/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f103-hw100k-ibox/board/CubeMX_Config/CubeMX_Config.ioc index 64b78b0f82..7f72f094c7 100644 --- a/bsp/stm32/stm32f103-hw100k-ibox/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f103-hw100k-ibox/board/CubeMX_Config/CubeMX_Config.ioc @@ -68,14 +68,24 @@ OSC_IN.Mode=HSE-External-Oscillator OSC_IN.Signal=RCC_OSC_IN OSC_OUT.Mode=HSE-External-Oscillator OSC_OUT.Signal=RCC_OSC_OUT +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX PA5.Mode=Full_Duplex_Master @@ -84,10 +94,12 @@ PA6.Mode=Full_Duplex_Master PA6.Signal=SPI1_MISO PA7.Mode=Full_Duplex_Master PA7.Signal=SPI1_MOSI -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX +PB10.GPIOParameters=GPIO_PuPd +PB10.GPIO_PuPd=GPIO_PULLUP PB10.Mode=Asynchronous PB10.Signal=USART3_TX +PB11.GPIOParameters=GPIO_PuPd +PB11.GPIO_PuPd=GPIO_PULLUP PB11.Mode=Asynchronous PB11.Signal=USART3_RX PB13.Mode=Full_Duplex_Master diff --git a/bsp/stm32/stm32f103-hw100k-ibox/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/stm32f103-hw100k-ibox/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index a70b36e9dc..18d600fd55 100644 --- a/bsp/stm32/stm32f103-hw100k-ibox/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/stm32f103-hw100k-ibox/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -92,7 +92,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled + /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); @@ -118,11 +118,11 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**ADC1 GPIO Configuration + /**ADC1 GPIO Configuration PC0 ------> ADC1_IN10 - PC1 ------> ADC1_IN11 + PC1 ------> ADC1_IN11 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -152,10 +152,10 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration + + /**ADC1 GPIO Configuration PC0 ------> ADC1_IN10 - PC1 ------> ADC1_IN11 + PC1 ------> ADC1_IN11 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_1); @@ -233,12 +233,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -261,12 +261,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -302,11 +302,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); @@ -321,11 +321,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); @@ -353,11 +353,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_UART4_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**UART4 GPIO Configuration + /**UART4 GPIO Configuration PC10 ------> UART4_TX - PC11 ------> UART4_RX + PC11 ------> UART4_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -366,7 +366,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* USER CODE BEGIN UART4_MspInit 1 */ @@ -380,11 +380,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -393,7 +393,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART1_MspInit 1 */ @@ -407,11 +407,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -420,7 +420,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART2_MspInit 1 */ @@ -434,11 +434,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -447,7 +447,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USER CODE BEGIN USART3_MspInit 1 */ @@ -474,10 +474,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART4_CLK_DISABLE(); - - /**UART4 GPIO Configuration + + /**UART4 GPIO Configuration PC10 ------> UART4_TX - PC11 ------> UART4_RX + PC11 ------> UART4_RX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11); @@ -492,10 +492,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -510,10 +510,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); @@ -528,10 +528,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); diff --git a/bsp/stm32/stm32f103-onenet-nbiot/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f103-onenet-nbiot/board/CubeMX_Config/CubeMX_Config.ioc index bea3e97feb..aa311f47f2 100644 --- a/bsp/stm32/stm32f103-onenet-nbiot/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f103-onenet-nbiot/board/CubeMX_Config/CubeMX_Config.ioc @@ -43,34 +43,42 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false -PA10.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA2.Locked=true +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX -PA3.Locked=true +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX -PA9.Locked=true -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX -PB10.Locked=true +PB10.GPIOParameters=GPIO_PuPd +PB10.GPIO_PuPd=GPIO_PULLUP PB10.Mode=Asynchronous PB10.Signal=USART3_TX -PB11.Locked=true +PB11.GPIOParameters=GPIO_PuPd +PB11.GPIO_PuPd=GPIO_PULLUP PB11.Mode=Asynchronous PB11.Signal=USART3_RX -PC10.Locked=true +PC10.GPIOParameters=GPIO_PuPd +PC10.GPIO_PuPd=GPIO_PULLUP PC10.Mode=Asynchronous -PC10.Signal=UART4_TX -PC11.Locked=true +PC10.Signal=USART4_TX +PC11.GPIOParameters=GPIO_PuPd +PC11.GPIO_PuPd=GPIO_PULLUP PC11.Mode=Asynchronous -PC11.Signal=UART4_RX +PC11.Signal=USART4_RX PD0-OSC_IN.Locked=true PD0-OSC_IN.Mode=HSE-External-Oscillator PD0-OSC_IN.Signal=RCC_OSC_IN diff --git a/bsp/stm32/stm32f103-onenet-nbiot/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/stm32f103-onenet-nbiot/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index d2471dd6da..e35fce1d80 100644 --- a/bsp/stm32/stm32f103-onenet-nbiot/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/stm32f103-onenet-nbiot/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -72,7 +72,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled + /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); @@ -97,11 +97,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_UART4_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**UART4 GPIO Configuration + /**UART4 GPIO Configuration PC10 ------> UART4_TX - PC11 ------> UART4_RX + PC11 ------> UART4_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -110,7 +110,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* USER CODE BEGIN UART4_MspInit 1 */ @@ -124,11 +124,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -137,7 +137,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART1_MspInit 1 */ @@ -151,11 +151,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -164,7 +164,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART2_MspInit 1 */ @@ -178,11 +178,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -191,7 +191,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USER CODE BEGIN USART3_MspInit 1 */ @@ -216,10 +216,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART4_CLK_DISABLE(); - - /**UART4 GPIO Configuration + + /**UART4 GPIO Configuration PC10 ------> UART4_TX - PC11 ------> UART4_RX + PC11 ------> UART4_RX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11); @@ -234,10 +234,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -252,10 +252,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); @@ -270,10 +270,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); diff --git a/bsp/stm32/stm32f103-yf-ufun/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f103-yf-ufun/board/CubeMX_Config/CubeMX_Config.ioc index 8f0ebe34a9..7a1bec1345 100644 --- a/bsp/stm32/stm32f103-yf-ufun/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f103-yf-ufun/board/CubeMX_Config/CubeMX_Config.ioc @@ -47,6 +47,12 @@ NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false PA0-WKUP.Signal=S_TIM2_CH1_ETR PA1.Signal=S_TIM2_CH2 +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire @@ -54,8 +60,6 @@ PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK PA2.Signal=S_TIM2_CH3 -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PC10.Mode=SD_4_bits_Wide_bus PC10.Signal=SDIO_D2 PC11.Mode=SD_4_bits_Wide_bus diff --git a/bsp/stm32/stm32f103-yf-ufun/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/stm32f103-yf-ufun/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index 67d2da43eb..6d50c1c47d 100644 --- a/bsp/stm32/stm32f103-yf-ufun/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/stm32f103-yf-ufun/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -94,7 +94,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled + /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); @@ -119,18 +119,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDIO_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDIO GPIO Configuration + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; @@ -163,16 +163,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDIO_CLK_DISABLE(); - - /**SDIO GPIO Configuration + + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -214,12 +214,12 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM2_MspPostInit 0 */ /* USER CODE END TIM2_MspPostInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**TIM2 GPIO Configuration + /**TIM2 GPIO Configuration PA0-WKUP ------> TIM2_CH1 PA1 ------> TIM2_CH2 - PA2 ------> TIM2_CH3 + PA2 ------> TIM2_CH3 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -269,11 +269,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -282,7 +282,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART1_MspInit 1 */ @@ -305,10 +305,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); diff --git a/bsp/stm32/stm32f107-uc-eval/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c b/bsp/stm32/stm32f107-uc-eval/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c index 03106e9008..6df0958bbd 100644 --- a/bsp/stm32/stm32f107-uc-eval/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c +++ b/bsp/stm32/stm32f107-uc-eval/board/CubeMX_Config/Src/stm32f1xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f1xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -92,7 +92,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled + /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); @@ -118,11 +118,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PD5 ------> USART2_TX - PD6 ------> USART2_RX + PD6 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -131,7 +131,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); __HAL_AFIO_REMAP_USART2_ENABLE(); @@ -163,10 +163,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PD5 ------> USART2_TX - PD6 ------> USART2_RX + PD6 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOD, GPIO_PIN_5|GPIO_PIN_6); diff --git a/bsp/stm32/stm32f207-st-nucleo/board/CubeMX_Config/Core/Src/stm32f2xx_hal_msp.c b/bsp/stm32/stm32f207-st-nucleo/board/CubeMX_Config/Core/Src/stm32f2xx_hal_msp.c index 24b027c37b..a4a60ffeb9 100644 --- a/bsp/stm32/stm32f207-st-nucleo/board/CubeMX_Config/Core/Src/stm32f2xx_hal_msp.c +++ b/bsp/stm32/stm32f207-st-nucleo/board/CubeMX_Config/Core/Src/stm32f2xx_hal_msp.c @@ -101,7 +101,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); diff --git a/bsp/stm32/stm32f401-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f401-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index e04e99534f..171ed0f617 100644 --- a/bsp/stm32/stm32f401-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f401-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -42,11 +42,13 @@ PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA2.GPIOParameters=GPIO_Speed +PA2.GPIOParameters=GPIO_Speed,GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.GPIO_Speed=GPIO_SPEED_FREQ_LOW PA2.Mode=Asynchronous PA2.Signal=USART2_TX -PA3.GPIOParameters=GPIO_Speed +PA3.GPIOParameters=GPIO_Speed,GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.GPIO_Speed=GPIO_SPEED_FREQ_LOW PA3.Mode=Asynchronous PA3.Signal=USART2_RX @@ -61,14 +63,6 @@ PC14-OSC32_IN.Mode=LSE-External-Oscillator PC14-OSC32_IN.Signal=RCC_OSC32_IN PC15-OSC32_OUT.Mode=LSE-External-Oscillator PC15-OSC32_OUT.Signal=RCC_OSC32_OUT -PCC.Checker=false -PCC.Line=STM32F401 -PCC.MCU=STM32F401R(D-E)Tx -PCC.PartNumber=STM32F401RETx -PCC.Seq0=0 -PCC.Series=STM32F4 -PCC.Temperature=25 -PCC.Vdd=null PH0\ -\ OSC_IN.Mode=HSE-External-Clock-Source PH0\ -\ OSC_IN.Signal=RCC_OSC_IN PH1\ -\ OSC_OUT.Mode=HSE-External-Clock-Source diff --git a/bsp/stm32/stm32f401-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f401-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 62e369862b..b263fd4998 100644 --- a/bsp/stm32/stm32f401-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f401-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -113,12 +113,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -149,11 +149,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); @@ -180,11 +180,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -215,10 +215,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); diff --git a/bsp/stm32/stm32f405-smdz-breadfruit/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f405-smdz-breadfruit/board/CubeMX_Config/CubeMX_Config.ioc index b4aeaf68c1..8ae3a1bccd 100644 --- a/bsp/stm32/stm32f405-smdz-breadfruit/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f405-smdz-breadfruit/board/CubeMX_Config/CubeMX_Config.ioc @@ -32,8 +32,12 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX PC14-OSC32_IN.Mode=LSE-External-Oscillator diff --git a/bsp/stm32/stm32f405-smdz-breadfruit/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f405-smdz-breadfruit/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 0b13484aba..ecc0b6d703 100644 --- a/bsp/stm32/stm32f405-smdz-breadfruit/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f405-smdz-breadfruit/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -114,11 +114,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -151,10 +151,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); diff --git a/bsp/stm32/stm32f407-armfly-v5/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f407-armfly-v5/board/CubeMX_Config/CubeMX_Config.ioc index 0777302023..6821275340 100644 --- a/bsp/stm32/stm32f407-armfly-v5/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f407-armfly-v5/board/CubeMX_Config/CubeMX_Config.ioc @@ -85,18 +85,26 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PB1.Signal=ADCx_IN9 PB12.Mode=Full_Duplex_Master PB12.Signal=I2S2_WS diff --git a/bsp/stm32/stm32f407-armfly-v5/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f407-armfly-v5/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index ab8078f4b0..5f62b1806d 100644 --- a/bsp/stm32/stm32f407-armfly-v5/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f407-armfly-v5/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -58,7 +58,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -95,10 +95,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PB1 ------> ADC1_IN9 + /**ADC1 GPIO Configuration + PB1 ------> ADC1_IN9 */ GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -127,9 +127,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration - PB1 ------> ADC1_IN9 + + /**ADC1 GPIO Configuration + PB1 ------> ADC1_IN9 */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_1); @@ -156,16 +156,16 @@ void HAL_I2S_MspInit(I2S_HandleTypeDef* hi2s) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); - /**I2S2 GPIO Configuration + /**I2S2 GPIO Configuration PB12 ------> I2S2_WS PB13 ------> I2S2_CK PB15 ------> I2S2_SD PC6 ------> I2S2_MCK - PI2 ------> I2S2_ext_SD + PI2 ------> I2S2_ext_SD */ GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -210,13 +210,13 @@ void HAL_I2S_MspDeInit(I2S_HandleTypeDef* hi2s) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**I2S2 GPIO Configuration + + /**I2S2 GPIO Configuration PB12 ------> I2S2_WS PB13 ------> I2S2_CK PB15 ------> I2S2_SD PC6 ------> I2S2_MCK - PI2 ------> I2S2_ext_SD + PI2 ------> I2S2_ext_SD */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_15); @@ -335,18 +335,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDIO_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDIO GPIO Configuration + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -383,16 +383,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDIO_CLK_DISABLE(); - - /**SDIO GPIO Configuration + + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -420,12 +420,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI3 GPIO Configuration + /**SPI3 GPIO Configuration PB3 ------> SPI3_SCK PB4 ------> SPI3_MISO - PB5 ------> SPI3_MOSI + PB5 ------> SPI3_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -456,11 +456,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI3_CLK_DISABLE(); - - /**SPI3 GPIO Configuration + + /**SPI3 GPIO Configuration PB3 ------> SPI3_SCK PB4 ------> SPI3_MISO - PB5 ------> SPI3_MOSI + PB5 ------> SPI3_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5); @@ -534,10 +534,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM10_MspPostInit 0 */ /* USER CODE END TIM10_MspPostInit 0 */ - + __HAL_RCC_GPIOF_CLK_ENABLE(); - /**TIM10 GPIO Configuration - PF6 ------> TIM10_CH1 + /**TIM10 GPIO Configuration + PF6 ------> TIM10_CH1 */ GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -623,15 +623,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -647,15 +647,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -682,10 +682,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -700,10 +700,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); diff --git a/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/CubeMX_Config.ioc index 02fb59d94c..8115bf0687 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/CubeMX_Config.ioc @@ -136,6 +136,12 @@ NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false PA1.Mode=RMII PA1.Signal=ETH_REF_CLK +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA11.Mode=Device_Only @@ -154,10 +160,12 @@ PA5.Locked=true PA5.Signal=COMP_DAC2_group PA7.Mode=RMII PA7.Signal=ETH_CRS_DV -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX +PB10.GPIOParameters=GPIO_PuPd +PB10.GPIO_PuPd=GPIO_PULLUP PB10.Mode=Asynchronous PB10.Signal=USART3_TX +PB11.GPIOParameters=GPIO_PuPd +PB11.GPIO_PuPd=GPIO_PULLUP PB11.Mode=Asynchronous PB11.Signal=USART3_RX PB13.Mode=Full_Duplex_Master diff --git a/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 08cc9f847e..34dd1ba7c7 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -741,7 +741,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -768,7 +768,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc index 26eba65442..f7c753af0a 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/CubeMX_Config.ioc @@ -38,10 +38,12 @@ PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA9.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP PA9.Mode=Asynchronous PA9.Signal=USART1_TX -PB7.Locked=true +PB7.GPIOParameters=GPIO_PuPd +PB7.GPIO_PuPd=GPIO_PULLUP PB7.Mode=Asynchronous PB7.Signal=USART1_RX PH0-OSC_IN.Mode=HSE-External-Oscillator diff --git a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 54a111c524..f2ac99095c 100644 --- a/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f407-robomaster-c/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -102,14 +102,14 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); diff --git a/bsp/stm32/stm32f407-st-discovery/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f407-st-discovery/board/CubeMX_Config/CubeMX_Config.ioc index 195ad7beb1..c208e8f6bd 100644 --- a/bsp/stm32/stm32f407-st-discovery/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f407-st-discovery/board/CubeMX_Config/CubeMX_Config.ioc @@ -25,18 +25,19 @@ Mcu.PinsNb=11 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32F407VGTx -MxCube.Version=5.0.0 -MxDb.Version=DB.5.0.0 -NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:true -NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:true -NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:true -NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:true -NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:true -NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:true +MxCube.Version=6.2.1 +MxDb.Version=DB.6.0.21 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:true\:false +NVIC.ForceEnableDMAVector=true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:true\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:true\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:true\:false NVIC.PriorityGroup=NVIC_PRIORITYGROUP_0 -NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:true -NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:true -NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:true +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:true\:false +NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:true\:true +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false PA13.GPIOParameters=GPIO_Label PA13.GPIO_Label=SWDIO PA13.Locked=true @@ -75,18 +76,14 @@ PB3.GPIOParameters=GPIO_Label PB3.GPIO_Label=SWO PB3.Locked=true PB3.Signal=SYS_JTDO-SWO +PB6.GPIOParameters=GPIO_PuPd +PB6.GPIO_PuPd=GPIO_PULLUP PB6.Mode=Asynchronous PB6.Signal=USART1_TX +PB7.GPIOParameters=GPIO_PuPd +PB7.GPIO_PuPd=GPIO_PULLUP PB7.Mode=Asynchronous PB7.Signal=USART1_RX -PCC.Checker=false -PCC.Line=STM32F407/417 -PCC.MCU=STM32F407V(E-G)Tx -PCC.PartNumber=STM32F407VGTx -PCC.Seq0=0 -PCC.Series=STM32F4 -PCC.Temperature=25 -PCC.Vdd=3.3 PH0-OSC_IN.GPIOParameters=GPIO_Label PH0-OSC_IN.GPIO_Label=PH0-OSC_IN PH0-OSC_IN.Locked=true diff --git a/bsp/stm32/stm32f407-st-discovery/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f407-st-discovery/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 2bac295eeb..e1da0e121a 100644 --- a/bsp/stm32/stm32f407-st-discovery/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f407-st-discovery/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,46 +2,46 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * - * Copyright (c) 2018 STMicroelectronics International N.V. + * Copyright (c) 2018 STMicroelectronics International N.V. * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted, provided that the following conditions are met: * - * 1. Redistribution of source code must retain the above copyright notice, + * 1. Redistribution of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this + * 4. This software, including modifications and/or derivative works of this * software, must execute solely and exclusively on microcontroller or * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @@ -62,7 +62,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -117,7 +117,6 @@ void HAL_MspInit(void) */ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) { - GPIO_InitTypeDef GPIO_InitStruct = {0}; if(hspi->Instance==SPI1) { @@ -126,12 +125,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = SPI1_SCK_Pin|SPI1_MISO_Pin|SPI1_MOSI_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -153,10 +152,8 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) * @param hspi: SPI handle pointer * @retval None */ - void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) { - if(hspi->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspDeInit 0 */ @@ -164,11 +161,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, SPI1_SCK_Pin|SPI1_MISO_Pin|SPI1_MOSI_Pin); @@ -187,7 +184,6 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) */ void HAL_UART_MspInit(UART_HandleTypeDef* huart) { - GPIO_InitTypeDef GPIO_InitStruct = {0}; if(huart->Instance==USART1) { @@ -196,11 +192,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PB6 ------> USART1_TX - PB7 ------> USART1_RX + PB7 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -222,10 +218,8 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) * @param huart: UART handle pointer * @retval None */ - void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) { - if(huart->Instance==USART1) { /* USER CODE BEGIN USART1_MspDeInit 0 */ @@ -233,10 +227,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PB6 ------> USART1_TX - PB7 ------> USART1_RX + PB7 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7); diff --git a/bsp/stm32/stm32f410-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f410-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index 2ff19285ab..daf5f74fde 100644 --- a/bsp/stm32/stm32f410-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f410-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -48,14 +48,12 @@ PA14.GPIO_Label=TCK PA14.Locked=true PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA2.GPIOParameters=GPIO_Label -PA2.GPIO_Label=USART_TX -PA2.Locked=true +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX -PA3.GPIOParameters=GPIO_Label -PA3.GPIO_Label=USART_RX -PA3.Locked=true +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX PA5.GPIOParameters=GPIO_Label diff --git a/bsp/stm32/stm32f410-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f410-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 55374ff0d2..1246457260 100644 --- a/bsp/stm32/stm32f410-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f410-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -95,15 +95,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = USART_TX_Pin|USART_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -130,10 +130,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, USART_TX_Pin|USART_RX_Pin); diff --git a/bsp/stm32/stm32f411-atk-nano/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f411-atk-nano/board/CubeMX_Config/CubeMX_Config.ioc index 1791e31d5e..397b95b06c 100644 --- a/bsp/stm32/stm32f411-atk-nano/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f411-atk-nano/board/CubeMX_Config/CubeMX_Config.ioc @@ -57,18 +57,26 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PB1.Locked=true PB1.Signal=ADCx_IN9 PB13.Locked=true diff --git a/bsp/stm32/stm32f411-atk-nano/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f411-atk-nano/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index ac3d0bf3f5..5598c57bce 100644 --- a/bsp/stm32/stm32f411-atk-nano/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f411-atk-nano/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -114,10 +114,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PB1 ------> ADC1_IN9 + /**ADC1 GPIO Configuration + PB1 ------> ADC1_IN9 */ GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -148,9 +148,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration - PB1 ------> ADC1_IN9 + + /**ADC1 GPIO Configuration + PB1 ------> ADC1_IN9 */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_1); @@ -176,11 +176,11 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) /* USER CODE BEGIN I2C1_MspInit 0 */ /* USER CODE END I2C1_MspInit 0 */ - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**I2C1 GPIO Configuration + /**I2C1 GPIO Configuration PB6 ------> I2C1_SCL - PB7 ------> I2C1_SDA + PB7 ------> I2C1_SDA */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; @@ -215,10 +215,10 @@ void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) /* USER CODE END I2C1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_I2C1_CLK_DISABLE(); - - /**I2C1 GPIO Configuration + + /**I2C1 GPIO Configuration PB6 ------> I2C1_SCL - PB7 ------> I2C1_SDA + PB7 ------> I2C1_SDA */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7); @@ -293,12 +293,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -331,11 +331,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); @@ -363,11 +363,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -387,11 +387,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -424,10 +424,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -442,10 +442,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); diff --git a/bsp/stm32/stm32f411-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f411-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index 68d45640ce..d770287e0b 100644 --- a/bsp/stm32/stm32f411-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f411-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -69,8 +69,12 @@ PA14.GPIO_Label=TCK PA14.Locked=true PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX PA5.Mode=Full_Duplex_Master diff --git a/bsp/stm32/stm32f411-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f411-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index b2c91f0c47..ff38319ce3 100644 --- a/bsp/stm32/stm32f411-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f411-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -165,13 +165,13 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PB4 ------> SPI1_MISO - PB5 ------> SPI1_MOSI + PB5 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -211,11 +211,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PB4 ------> SPI1_MISO - PB5 ------> SPI1_MOSI + PB5 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5); @@ -260,14 +260,14 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM3_MspPostInit 0 */ /* USER CODE END TIM3_MspPostInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**TIM3 GPIO Configuration + /**TIM3 GPIO Configuration PA6 ------> TIM3_CH1 PA7 ------> TIM3_CH2 PB0 ------> TIM3_CH3 - PB1 ------> TIM3_CH4 + PB1 ------> TIM3_CH4 */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -330,11 +330,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -354,11 +354,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART6_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART6_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART6 GPIO Configuration + /**USART6 GPIO Configuration PA11 ------> USART6_TX - PA12 ------> USART6_RX + PA12 ------> USART6_RX */ GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -391,10 +391,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); @@ -409,10 +409,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART6_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART6_CLK_DISABLE(); - - /**USART6 GPIO Configuration + + /**USART6 GPIO Configuration PA11 ------> USART6_TX - PA12 ------> USART6_RX + PA12 ------> USART6_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); diff --git a/bsp/stm32/stm32f411-weact-MiniF4/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f411-weact-MiniF4/board/CubeMX_Config/CubeMX_Config.ioc index 1468ade621..4bf9eb69a8 100644 --- a/bsp/stm32/stm32f411-weact-MiniF4/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f411-weact-MiniF4/board/CubeMX_Config/CubeMX_Config.ioc @@ -49,6 +49,12 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA11.Mode=Device_Only @@ -65,8 +71,6 @@ PA6.Mode=Full_Duplex_Master PA6.Signal=SPI1_MISO PA7.Mode=Full_Duplex_Master PA7.Signal=SPI1_MOSI -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PC13-ANTI_TAMP.Locked=true PC13-ANTI_TAMP.Signal=GPIO_Output PC14-OSC32_IN.Mode=LSE-External-Oscillator diff --git a/bsp/stm32/stm32f411-weact-MiniF4/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f411-weact-MiniF4/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 97a4cad91d..ff0ff3b0b6 100644 --- a/bsp/stm32/stm32f411-weact-MiniF4/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f411-weact-MiniF4/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -137,12 +137,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -173,11 +173,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI + PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); @@ -270,15 +270,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -305,10 +305,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -333,11 +333,11 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ /* USER CODE END USB_OTG_FS_MspInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB_OTG_FS GPIO Configuration + /**USB_OTG_FS GPIO Configuration PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -370,10 +370,10 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) /* USER CODE END USB_OTG_FS_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); - - /**USB_OTG_FS GPIO Configuration + + /**USB_OTG_FS GPIO Configuration PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); diff --git a/bsp/stm32/stm32f412-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f412-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 2ef6d3f970..1cb7cb865a 100644 --- a/bsp/stm32/stm32f412-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f412-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -114,11 +114,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PD8 ------> USART3_TX - PD9 ------> USART3_RX + PD9 ------> USART3_RX */ GPIO_InitStruct.Pin = STLK_RX_Pin|STLK_TX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -151,10 +151,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PD8 ------> USART3_TX - PD9 ------> USART3_RX + PD9 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOD, STLK_RX_Pin|STLK_TX_Pin); @@ -180,13 +180,13 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ /* USER CODE END USB_OTG_FS_MspInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB_OTG_FS GPIO Configuration + /**USB_OTG_FS GPIO Configuration PA8 ------> USB_OTG_FS_SOF PA10 ------> USB_OTG_FS_ID PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ GPIO_InitStruct.Pin = USB_SOF_Pin|USB_ID_Pin|USB_DM_Pin|USB_DP_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -221,12 +221,12 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) /* USER CODE END USB_OTG_FS_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); - - /**USB_OTG_FS GPIO Configuration + + /**USB_OTG_FS GPIO Configuration PA8 ------> USB_OTG_FS_SOF PA10 ------> USB_OTG_FS_ID PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ HAL_GPIO_DeInit(GPIOA, USB_SOF_Pin|USB_ID_Pin|USB_DM_Pin|USB_DP_Pin); diff --git a/bsp/stm32/stm32f413-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f413-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index b70b0c1c20..fbc3920044 100644 --- a/bsp/stm32/stm32f413-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f413-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -115,10 +115,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PA5 ------> ADC1_IN5 + /**ADC1 GPIO Configuration + PA5 ------> ADC1_IN5 */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -147,9 +147,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration - PA5 ------> ADC1_IN5 + + /**ADC1 GPIO Configuration + PA5 ------> ADC1_IN5 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5); @@ -174,11 +174,11 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) /* USER CODE BEGIN I2C1_MspInit 0 */ /* USER CODE END I2C1_MspInit 0 */ - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**I2C1 GPIO Configuration + /**I2C1 GPIO Configuration PB6 ------> I2C1_SCL - PB9 ------> I2C1_SDA + PB9 ------> I2C1_SDA */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; @@ -211,10 +211,10 @@ void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) /* USER CODE END I2C1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_I2C1_CLK_DISABLE(); - - /**I2C1 GPIO Configuration + + /**I2C1 GPIO Configuration PB6 ------> I2C1_SCL - PB9 ------> I2C1_SDA + PB9 ------> I2C1_SDA */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_9); @@ -285,13 +285,13 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PC2 ------> SPI2_MISO PC3 ------> SPI2_MOSI - PB10 ------> SPI2_SCK + PB10 ------> SPI2_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -329,11 +329,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PC2 ------> SPI2_MISO PC3 ------> SPI2_MOSI - PB10 ------> SPI2_SCK + PB10 ------> SPI2_SCK */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_2|GPIO_PIN_3); @@ -409,10 +409,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM2_MspPostInit 0 */ /* USER CODE END TIM2_MspPostInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**TIM2 GPIO Configuration - PA3 ------> TIM2_CH4 + /**TIM2 GPIO Configuration + PA3 ------> TIM2_CH4 */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -498,12 +498,12 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PD6 ------> USART2_RX + PD6 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -530,11 +530,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PD8 ------> USART3_TX - PD9 ------> USART3_RX + PD9 ------> USART3_RX */ GPIO_InitStruct.Pin = STLK_RX_Pin|STLK_TX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -565,10 +565,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PD6 ------> USART2_RX + PD6 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2); @@ -585,10 +585,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PD8 ------> USART3_TX - PD9 ------> USART3_RX + PD9 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOD, STLK_RX_Pin|STLK_TX_Pin); @@ -613,14 +613,14 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ /* USER CODE END USB_OTG_FS_MspInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB_OTG_FS GPIO Configuration + /**USB_OTG_FS GPIO Configuration PA8 ------> USB_OTG_FS_SOF PA9 ------> USB_OTG_FS_VBUS PA10 ------> USB_OTG_FS_ID PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ GPIO_InitStruct.Pin = USB_SOF_Pin|USB_ID_Pin|USB_DM_Pin|USB_DP_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -658,15 +658,15 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) /* USER CODE END USB_OTG_FS_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); - - /**USB_OTG_FS GPIO Configuration + + /**USB_OTG_FS GPIO Configuration PA8 ------> USB_OTG_FS_SOF PA9 ------> USB_OTG_FS_VBUS PA10 ------> USB_OTG_FS_ID PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ - HAL_GPIO_DeInit(GPIOA, USB_SOF_Pin|USB_VBUS_Pin|USB_ID_Pin|USB_DM_Pin + HAL_GPIO_DeInit(GPIOA, USB_SOF_Pin|USB_VBUS_Pin|USB_ID_Pin|USB_DM_Pin |USB_DP_Pin); /* USER CODE BEGIN USB_OTG_FS_MspDeInit 1 */ diff --git a/bsp/stm32/stm32f427-robomaster-a/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f427-robomaster-a/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 19b391828c..efa99aed9a 100644 --- a/bsp/stm32/stm32f427-robomaster-a/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f427-robomaster-a/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -120,11 +120,11 @@ void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan) if(HAL_RCC_CAN1_CLK_ENABLED==1){ __HAL_RCC_CAN1_CLK_ENABLE(); } - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**CAN1 GPIO Configuration + /**CAN1 GPIO Configuration PD0 ------> CAN1_RX - PD1 ------> CAN1_TX + PD1 ------> CAN1_TX */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -148,11 +148,11 @@ void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan) if(HAL_RCC_CAN1_CLK_ENABLED==1){ __HAL_RCC_CAN1_CLK_ENABLE(); } - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**CAN2 GPIO Configuration + /**CAN2 GPIO Configuration PB12 ------> CAN2_RX - PB13 ------> CAN2_TX + PB13 ------> CAN2_TX */ GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -186,10 +186,10 @@ void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan) if(HAL_RCC_CAN1_CLK_ENABLED==0){ __HAL_RCC_CAN1_CLK_DISABLE(); } - - /**CAN1 GPIO Configuration + + /**CAN1 GPIO Configuration PD0 ------> CAN1_RX - PD1 ------> CAN1_TX + PD1 ------> CAN1_TX */ HAL_GPIO_DeInit(GPIOD, GPIO_PIN_0|GPIO_PIN_1); @@ -208,10 +208,10 @@ void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan) if(HAL_RCC_CAN1_CLK_ENABLED==0){ __HAL_RCC_CAN1_CLK_DISABLE(); } - - /**CAN2 GPIO Configuration + + /**CAN2 GPIO Configuration PB12 ------> CAN2_RX - PB13 ------> CAN2_TX + PB13 ------> CAN2_TX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_12|GPIO_PIN_13); @@ -238,18 +238,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDIO_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDIO GPIO Configuration + /**SDIO GPIO Configuration PC12 ------> SDIO_CK PC11 ------> SDIO_D3 PC10 ------> SDIO_D2 PD2 ------> SDIO_CMD PC9 ------> SDIO_D1 - PC8 ------> SDIO_D0 + PC8 ------> SDIO_D0 */ - GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 + GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 |GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -286,16 +286,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDIO_CLK_DISABLE(); - - /**SDIO GPIO Configuration + + /**SDIO GPIO Configuration PC12 ------> SDIO_CK PC11 ------> SDIO_D3 PC10 ------> SDIO_D2 PD2 ------> SDIO_CMD PC9 ------> SDIO_D1 - PC8 ------> SDIO_D0 + PC8 ------> SDIO_D0 */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 |GPIO_PIN_8); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -323,12 +323,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI5_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); - /**SPI5 GPIO Configuration + /**SPI5 GPIO Configuration PF7 ------> SPI5_SCK PF9 ------> SPI5_MOSI - PF8 ------> SPI5_MISO + PF8 ------> SPI5_MISO */ GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_9|GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -359,11 +359,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI5_CLK_DISABLE(); - - /**SPI5 GPIO Configuration + + /**SPI5 GPIO Configuration PF7 ------> SPI5_SCK PF9 ------> SPI5_MOSI - PF8 ------> SPI5_MISO + PF8 ------> SPI5_MISO */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_7|GPIO_PIN_9|GPIO_PIN_8); @@ -427,11 +427,11 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE END TIM4_MspPostInit 0 */ __HAL_RCC_GPIOD_CLK_ENABLE(); - /**TIM4 GPIO Configuration + /**TIM4 GPIO Configuration PD15 ------> TIM4_CH4 PD14 ------> TIM4_CH3 PD13 ------> TIM4_CH2 - PD12 ------> TIM4_CH1 + PD12 ------> TIM4_CH1 */ GPIO_InitStruct.Pin = GPIO_PIN_15|GPIO_PIN_14|GPIO_PIN_13|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -449,14 +449,14 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM5_MspPostInit 0 */ /* USER CODE END TIM5_MspPostInit 0 */ - + __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); - /**TIM5 GPIO Configuration + /**TIM5 GPIO Configuration PI0 ------> TIM5_CH4 PH12 ------> TIM5_CH3 PH11 ------> TIM5_CH2 - PH10 ------> TIM5_CH1 + PH10 ------> TIM5_CH1 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -481,10 +481,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM12_MspPostInit 0 */ /* USER CODE END TIM12_MspPostInit 0 */ - + __HAL_RCC_GPIOH_CLK_ENABLE(); - /**TIM12 GPIO Configuration - PH6 ------> TIM12_CH1 + /**TIM12 GPIO Configuration + PH6 ------> TIM12_CH1 */ GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -559,11 +559,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END UART7_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_UART7_CLK_ENABLE(); - + __HAL_RCC_GPIOE_CLK_ENABLE(); - /**UART7 GPIO Configuration + /**UART7 GPIO Configuration PE8 ------> UART7_TX - PE7 ------> UART7_RX + PE7 ------> UART7_RX */ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -583,11 +583,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END UART8_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_UART8_CLK_ENABLE(); - + __HAL_RCC_GPIOE_CLK_ENABLE(); - /**UART8 GPIO Configuration + /**UART8 GPIO Configuration PE1 ------> UART8_TX - PE0 ------> UART8_RX + PE0 ------> UART8_RX */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -607,11 +607,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PB7 ------> USART1_RX - PB6 ------> USART1_TX + PB6 ------> USART1_TX */ GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -631,11 +631,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PD9 ------> USART3_RX - PD8 ------> USART3_TX + PD8 ------> USART3_TX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -655,11 +655,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART6_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART6_CLK_ENABLE(); - + __HAL_RCC_GPIOG_CLK_ENABLE(); - /**USART6 GPIO Configuration + /**USART6 GPIO Configuration PG14 ------> USART6_TX - PG9 ------> USART6_RX + PG9 ------> USART6_RX */ GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -693,10 +693,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END UART7_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART7_CLK_DISABLE(); - - /**UART7 GPIO Configuration + + /**UART7 GPIO Configuration PE8 ------> UART7_TX - PE7 ------> UART7_RX + PE7 ------> UART7_RX */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_8|GPIO_PIN_7); @@ -711,10 +711,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END UART8_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART8_CLK_DISABLE(); - - /**UART8 GPIO Configuration + + /**UART8 GPIO Configuration PE1 ------> UART8_TX - PE0 ------> UART8_RX + PE0 ------> UART8_RX */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_1|GPIO_PIN_0); @@ -729,10 +729,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PB7 ------> USART1_RX - PB6 ------> USART1_TX + PB6 ------> USART1_TX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7|GPIO_PIN_6); @@ -747,10 +747,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PD9 ------> USART3_RX - PD8 ------> USART3_TX + PD8 ------> USART3_TX */ HAL_GPIO_DeInit(GPIOD, GPIO_PIN_9|GPIO_PIN_8); @@ -765,10 +765,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART6_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART6_CLK_DISABLE(); - - /**USART6 GPIO Configuration + + /**USART6 GPIO Configuration PG14 ------> USART6_TX - PG9 ------> USART6_RX + PG9 ------> USART6_RX */ HAL_GPIO_DeInit(GPIOG, GPIO_PIN_14|GPIO_PIN_9); diff --git a/bsp/stm32/stm32f429-armfly-v6/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f429-armfly-v6/board/CubeMX_Config/CubeMX_Config.ioc index 713e78f639..298807cd0b 100644 --- a/bsp/stm32/stm32f429-armfly-v6/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f429-armfly-v6/board/CubeMX_Config/CubeMX_Config.ioc @@ -175,6 +175,12 @@ NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false PA0/WKUP.Signal=S_TIM2_CH1_ETR PA1.Mode=RMII PA1.Signal=ETH_REF_CLK +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire @@ -185,8 +191,6 @@ PA2.Mode=RMII PA2.Signal=ETH_MDIO PA7.Mode=RMII PA7.Signal=ETH_CRS_DV -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PB13.Mode=RMII PB13.Signal=ETH_TXD1 PB3.Locked=true diff --git a/bsp/stm32/stm32f429-armfly-v6/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f429-armfly-v6/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 5e0a3aac30..5d46a084d8 100644 --- a/bsp/stm32/stm32f429-armfly-v6/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f429-armfly-v6/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -116,11 +116,11 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**ADC1 GPIO Configuration + /**ADC1 GPIO Configuration PC0 ------> ADC1_IN10 - PC3 ------> ADC1_IN13 + PC3 ------> ADC1_IN13 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -151,10 +151,10 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration + + /**ADC1 GPIO Configuration PC0 ------> ADC1_IN10 - PC3 ------> ADC1_IN13 + PC3 ------> ADC1_IN13 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_3); @@ -229,12 +229,12 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ETH_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); - /**ETH GPIO Configuration + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -243,7 +243,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PB13 ------> ETH_TXD1 PG11 ------> ETH_TX_EN - PG13 ------> ETH_TXD0 + PG13 ------> ETH_TXD0 */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -297,8 +297,8 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ETH_CLK_DISABLE(); - - /**ETH GPIO Configuration + + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -307,7 +307,7 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PB13 ------> ETH_TXD1 PG11 ------> ETH_TX_EN - PG13 ------> ETH_TXD0 + PG13 ------> ETH_TXD0 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5); @@ -341,11 +341,11 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LTDC_CLK_ENABLE(); - + __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOJ_CLK_ENABLE(); __HAL_RCC_GPIOK_CLK_ENABLE(); - /**LTDC GPIO Configuration + /**LTDC GPIO Configuration PI12 ------> LTDC_HSYNC PI13 ------> LTDC_VSYNC PI14 ------> LTDC_CLK @@ -373,7 +373,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) PK4 ------> LTDC_B5 PK5 ------> LTDC_B6 PK6 ------> LTDC_B7 - PK7 ------> LTDC_DE + PK7 ------> LTDC_DE */ GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -382,9 +382,9 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) GPIO_InitStruct.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 - |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 + |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -392,7 +392,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) GPIO_InitStruct.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOJ, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -424,8 +424,8 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LTDC_CLK_DISABLE(); - - /**LTDC GPIO Configuration + + /**LTDC GPIO Configuration PI12 ------> LTDC_HSYNC PI13 ------> LTDC_VSYNC PI14 ------> LTDC_CLK @@ -453,16 +453,16 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) PK4 ------> LTDC_B5 PK5 ------> LTDC_B6 PK6 ------> LTDC_B7 - PK7 ------> LTDC_DE + PK7 ------> LTDC_DE */ HAL_GPIO_DeInit(GPIOI, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOJ, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 - |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOJ, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 + |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOK, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + HAL_GPIO_DeInit(GPIOK, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); /* USER CODE BEGIN LTDC_MspDeInit 1 */ @@ -536,18 +536,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDIO_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDIO GPIO Configuration + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -586,16 +586,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDIO_CLK_DISABLE(); - - /**SDIO GPIO Configuration + + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -624,12 +624,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI3 GPIO Configuration + /**SPI3 GPIO Configuration PB3 ------> SPI3_SCK PB4 ------> SPI3_MISO - PB5 ------> SPI3_MOSI + PB5 ------> SPI3_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -662,11 +662,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI3_CLK_DISABLE(); - - /**SPI3 GPIO Configuration + + /**SPI3 GPIO Configuration PB3 ------> SPI3_SCK PB4 ------> SPI3_MISO - PB5 ------> SPI3_MOSI + PB5 ------> SPI3_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5); @@ -742,10 +742,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM2_MspPostInit 0 */ /* USER CODE END TIM2_MspPostInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**TIM2 GPIO Configuration - PA0/WKUP ------> TIM2_CH1 + /**TIM2 GPIO Configuration + PA0/WKUP ------> TIM2_CH1 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -834,11 +834,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -874,10 +874,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -903,8 +903,8 @@ static void HAL_FMC_MspInit(void){ FMC_Initialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_ENABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PI9 ------> FMC_D30 PI10 ------> FMC_D31 PF0 ------> FMC_A0 @@ -965,8 +965,8 @@ static void HAL_FMC_MspInit(void){ PI6 ------> FMC_D28 PI7 ------> FMC_D29 */ - GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 - |GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5 + GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 + |GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5 |GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -974,8 +974,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -983,8 +983,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_8 - |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 + GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_8 + |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -992,7 +992,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1000,8 +1000,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1009,8 +1009,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 - |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4 |GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1055,8 +1055,8 @@ static void HAL_FMC_MspDeInit(void){ FMC_DeInitialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_DISABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PI9 ------> FMC_D30 PI10 ------> FMC_D31 PF0 ------> FMC_A0 @@ -1117,27 +1117,27 @@ static void HAL_FMC_MspDeInit(void){ PI6 ------> FMC_D28 PI7 ------> FMC_D29 */ - HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 - |GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5 + HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 + |GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5 |GPIO_PIN_6|GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOH, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_8 - |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 + HAL_GPIO_DeInit(GPIOH, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_8 + |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1); - HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 - |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4 + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4 |GPIO_PIN_5); /* USER CODE BEGIN FMC_MspDeInit 1 */ diff --git a/bsp/stm32/stm32f429-atk-apollo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f429-atk-apollo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index ad60e8e19a..0d0405b7a1 100644 --- a/bsp/stm32/stm32f429-atk-apollo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f429-atk-apollo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -115,10 +115,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PA5 ------> ADC1_IN5 + /**ADC1 GPIO Configuration + PA5 ------> ADC1_IN5 */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -147,9 +147,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration - PA5 ------> ADC1_IN5 + + /**ADC1 GPIO Configuration + PA5 ------> ADC1_IN5 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5); @@ -176,11 +176,11 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ETH_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); - /**ETH GPIO Configuration + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -189,7 +189,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PG11 ------> ETH_TX_EN PG13 ------> ETH_TXD0 - PG14 ------> ETH_TXD1 + PG14 ------> ETH_TXD1 */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -234,8 +234,8 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ETH_CLK_DISABLE(); - - /**ETH GPIO Configuration + + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -244,7 +244,7 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PG11 ------> ETH_TX_EN PG13 ------> ETH_TXD0 - PG14 ------> ETH_TXD1 + PG14 ------> ETH_TXD1 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5); @@ -319,18 +319,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDIO_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDIO GPIO Configuration + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -367,16 +367,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDIO_CLK_DISABLE(); - - /**SDIO GPIO Configuration + + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -404,13 +404,13 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA6 ------> SPI1_MISO PB3 ------> SPI1_SCK - PB5 ------> SPI1_MOSI + PB5 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -437,12 +437,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -462,12 +462,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI5_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); - /**SPI5 GPIO Configuration + /**SPI5 GPIO Configuration PF7 ------> SPI5_SCK PF8 ------> SPI5_MISO - PF9 ------> SPI5_MOSI + PF9 ------> SPI5_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -498,11 +498,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA6 ------> SPI1_MISO PB3 ------> SPI1_SCK - PB5 ------> SPI1_MOSI + PB5 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_6); @@ -519,11 +519,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); @@ -538,11 +538,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI5_CLK_DISABLE(); - - /**SPI5 GPIO Configuration + + /**SPI5 GPIO Configuration PF7 ------> SPI5_SCK PF8 ------> SPI5_MISO - PF9 ------> SPI5_MOSI + PF9 ------> SPI5_MOSI */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9); @@ -616,10 +616,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM2_MspPostInit 0 */ /* USER CODE END TIM2_MspPostInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**TIM2 GPIO Configuration - PA3 ------> TIM2_CH4 + /**TIM2 GPIO Configuration + PA3 ------> TIM2_CH4 */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -701,16 +701,16 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) if(huart->Instance==USART1) { /* USER CODE BEGIN USART1_MspInit 0 */ - + /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -733,11 +733,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PD5 ------> USART2_TX - PD6 ------> USART2_RX + PD6 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -757,11 +757,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -792,10 +792,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -812,10 +812,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PD5 ------> USART2_TX - PD6 ------> USART2_RX + PD6 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOD, GPIO_PIN_5|GPIO_PIN_6); @@ -830,10 +830,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); @@ -858,11 +858,11 @@ void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd) /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ /* USER CODE END USB_OTG_FS_MspInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB_OTG_FS GPIO Configuration + /**USB_OTG_FS GPIO Configuration PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -898,10 +898,10 @@ void HAL_HCD_MspDeInit(HCD_HandleTypeDef* hhcd) /* USER CODE END USB_OTG_FS_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); - - /**USB_OTG_FS GPIO Configuration + + /**USB_OTG_FS GPIO Configuration PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); @@ -927,8 +927,8 @@ static void HAL_FMC_MspInit(void){ FMC_Initialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_ENABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -969,8 +969,8 @@ static void HAL_FMC_MspInit(void){ PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 */ - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -985,7 +985,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 |GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -993,8 +993,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1002,7 +1002,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1037,8 +1037,8 @@ static void HAL_FMC_MspDeInit(void){ FMC_DeInitialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_DISABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -1079,20 +1079,20 @@ static void HAL_FMC_MspDeInit(void){ PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 */ - HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 |GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1); - HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1); /* USER CODE BEGIN FMC_MspDeInit 1 */ @@ -1125,12 +1125,12 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) __HAL_RCC_SAI1_CLK_ENABLE(); } SAI1_client ++; - - /**SAI1_A_Block_A GPIO Configuration + + /**SAI1_A_Block_A GPIO Configuration PE2 ------> SAI1_MCLK_A PE4 ------> SAI1_FS_A PE5 ------> SAI1_SCK_A - PE6 ------> SAI1_SD_A + PE6 ------> SAI1_SD_A */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -1148,9 +1148,9 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai) __HAL_RCC_SAI1_CLK_ENABLE(); } SAI1_client ++; - - /**SAI1_B_Block_B GPIO Configuration - PE3 ------> SAI1_SD_B + + /**SAI1_B_Block_B GPIO Configuration + PE3 ------> SAI1_SD_B */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -1171,15 +1171,15 @@ void HAL_SAI_MspDeInit(SAI_HandleTypeDef* hsai) SAI1_client --; if (SAI1_client == 0) { - /* Peripheral clock disable */ + /* Peripheral clock disable */ __HAL_RCC_SAI1_CLK_DISABLE(); } - - /**SAI1_A_Block_A GPIO Configuration + + /**SAI1_A_Block_A GPIO Configuration PE2 ------> SAI1_MCLK_A PE4 ------> SAI1_FS_A PE5 ------> SAI1_SCK_A - PE6 ------> SAI1_SD_A + PE6 ------> SAI1_SD_A */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6); @@ -1192,9 +1192,9 @@ void HAL_SAI_MspDeInit(SAI_HandleTypeDef* hsai) /* Peripheral clock disable */ __HAL_RCC_SAI1_CLK_DISABLE(); } - - /**SAI1_B_Block_B GPIO Configuration - PE3 ------> SAI1_SD_B + + /**SAI1_B_Block_B GPIO Configuration + PE3 ------> SAI1_SD_B */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_3); diff --git a/bsp/stm32/stm32f429-fire-challenger/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f429-fire-challenger/board/CubeMX_Config/CubeMX_Config.ioc index b23d058006..40485e9361 100644 --- a/bsp/stm32/stm32f429-fire-challenger/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f429-fire-challenger/board/CubeMX_Config/CubeMX_Config.ioc @@ -153,6 +153,12 @@ NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false PA1.Mode=RMII PA1.Signal=ETH_REF_CLK +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA11.Mode=RGB888 @@ -170,8 +176,6 @@ PA3.Mode=RGB888 PA3.Signal=LTDC_B5 PA7.Mode=RMII PA7.Signal=ETH_CRS_DV -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PB0.Locked=true PB0.Mode=RGB888 PB0.Signal=LTDC_R3 diff --git a/bsp/stm32/stm32f429-fire-challenger/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f429-fire-challenger/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 380fd93b83..059f740127 100644 --- a/bsp/stm32/stm32f429-fire-challenger/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f429-fire-challenger/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -116,10 +116,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PC3 ------> ADC1_IN13 + /**ADC1 GPIO Configuration + PC3 ------> ADC1_IN13 */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -150,9 +150,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration - PC3 ------> ADC1_IN13 + + /**ADC1 GPIO Configuration + PC3 ------> ADC1_IN13 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_3); @@ -227,12 +227,12 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ETH_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); - /**ETH GPIO Configuration + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -241,7 +241,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PB11 ------> ETH_TX_EN PG13 ------> ETH_TXD0 - PG14 ------> ETH_TXD1 + PG14 ------> ETH_TXD1 */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -295,8 +295,8 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ETH_CLK_DISABLE(); - - /**ETH GPIO Configuration + + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -305,7 +305,7 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PB11 ------> ETH_TX_EN PG13 ------> ETH_TXD0 - PG14 ------> ETH_TXD1 + PG14 ------> ETH_TXD1 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5); @@ -339,7 +339,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LTDC_CLK_ENABLE(); - + __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); @@ -349,7 +349,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**LTDC GPIO Configuration + /**LTDC GPIO Configuration PE4 ------> LTDC_B0 PE5 ------> LTDC_G0 PE6 ------> LTDC_G1 @@ -377,7 +377,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) PG12 ------> LTDC_B1 PB8 ------> LTDC_B6 PB9 ------> LTDC_B7 - PI4 ------> LTDC_B4 + PI4 ------> LTDC_B4 */ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -386,7 +386,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) GPIO_InitStruct.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_2 + GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_2 |GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -401,7 +401,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) GPIO_InitStruct.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_8|GPIO_PIN_13 + GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_8|GPIO_PIN_13 |GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -482,8 +482,8 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LTDC_CLK_DISABLE(); - - /**LTDC GPIO Configuration + + /**LTDC GPIO Configuration PE4 ------> LTDC_B0 PE5 ------> LTDC_G0 PE6 ------> LTDC_G1 @@ -511,23 +511,23 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) PG12 ------> LTDC_B1 PB8 ------> LTDC_B6 PB9 ------> LTDC_B7 - PI4 ------> LTDC_B4 + PI4 ------> LTDC_B4 */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6); - HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_2 + HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_2 |GPIO_PIN_4); HAL_GPIO_DeInit(GPIOF, GPIO_PIN_10); - HAL_GPIO_DeInit(GPIOH, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_8|GPIO_PIN_13 + HAL_GPIO_DeInit(GPIOH, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_8|GPIO_PIN_13 |GPIO_PIN_15); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3|GPIO_PIN_11|GPIO_PIN_12); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_8|GPIO_PIN_9); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_7); @@ -605,18 +605,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDIO_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDIO GPIO Configuration + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -655,16 +655,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDIO_CLK_DISABLE(); - - /**SDIO GPIO Configuration + + /**SDIO GPIO Configuration PC8 ------> SDIO_D0 PC9 ------> SDIO_D1 PC10 ------> SDIO_D2 PC11 ------> SDIO_D3 PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD + PD2 ------> SDIO_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -693,12 +693,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI5_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); - /**SPI5 GPIO Configuration + /**SPI5 GPIO Configuration PF7 ------> SPI5_SCK PF8 ------> SPI5_MISO - PF9 ------> SPI5_MOSI + PF9 ------> SPI5_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -731,11 +731,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI5_CLK_DISABLE(); - - /**SPI5 GPIO Configuration + + /**SPI5 GPIO Configuration PF7 ------> SPI5_SCK PF8 ------> SPI5_MISO - PF9 ------> SPI5_MOSI + PF9 ------> SPI5_MOSI */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9); @@ -811,12 +811,12 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM5_MspPostInit 0 */ /* USER CODE END TIM5_MspPostInit 0 */ - + __HAL_RCC_GPIOH_CLK_ENABLE(); - /**TIM5 GPIO Configuration + /**TIM5 GPIO Configuration PH10 ------> TIM5_CH1 PH11 ------> TIM5_CH2 - PH12 ------> TIM5_CH3 + PH12 ------> TIM5_CH3 */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -905,11 +905,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -945,10 +945,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -974,8 +974,8 @@ static void HAL_FMC_MspInit(void){ FMC_Initialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_ENABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -1015,8 +1015,8 @@ static void HAL_FMC_MspInit(void){ PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 */ - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1031,7 +1031,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 |GPIO_PIN_8|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1039,8 +1039,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1055,7 +1055,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1090,8 +1090,8 @@ static void HAL_FMC_MspDeInit(void){ FMC_DeInitialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_DISABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -1131,22 +1131,22 @@ static void HAL_FMC_MspDeInit(void){ PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 */ - HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 |GPIO_PIN_8|GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1); HAL_GPIO_DeInit(GPIOH, GPIO_PIN_6|GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1); /* USER CODE BEGIN FMC_MspDeInit 1 */ diff --git a/bsp/stm32/stm32f429-st-disco/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f429-st-disco/board/CubeMX_Config/CubeMX_Config.ioc index 235ba2c905..058533f6dd 100644 --- a/bsp/stm32/stm32f429-st-disco/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f429-st-disco/board/CubeMX_Config/CubeMX_Config.ioc @@ -194,15 +194,15 @@ PA1.GPIO_ModeDefaultEXTI=GPIO_MODE_EVT_RISING PA1.GPIO_PuPd=GPIO_NOPULL PA1.Locked=true PA1.Signal=GPXTI1 -PA10.GPIOParameters=GPIO_Label +PA10.GPIOParameters=GPIO_Label,GPIO_PuPd PA10.GPIO_Label=STLINK_TX [STM32F103CBT6_PA2] -PA10.Locked=true +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA11.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode PA11.GPIO_Label=R4 PA11.GPIO_Mode=GPIO_MODE_AF_PP -PA11.GPIO_PuPd=GPIO_NOPULL +PA11.GPIO_PuPd=GPIO_PULLUP PA11.GPIO_Speed=GPIO_SPEED_FREQ_LOW PA11.Locked=true PA11.Mode=RGB565 @@ -210,7 +210,7 @@ PA11.Signal=LTDC_R4 PA12.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode PA12.GPIO_Label=R5 PA12.GPIO_Mode=GPIO_MODE_AF_PP -PA12.GPIO_PuPd=GPIO_NOPULL +PA12.GPIO_PuPd=GPIO_PULLUP PA12.GPIO_Speed=GPIO_SPEED_FREQ_LOW PA12.Locked=true PA12.Mode=RGB565 @@ -276,9 +276,9 @@ PA8.GPIO_Speed=GPIO_SPEED_FREQ_LOW PA8.Locked=true PA8.Mode=I2C PA8.Signal=I2C3_SCL -PA9.GPIOParameters=GPIO_Label +PA9.GPIOParameters=GPIO_Label,GPIO_PULLUP PA9.GPIO_Label=STLINK_RX [STM32F103CBT6_PA3] -PA9.Locked=true +PA9.GPIO_PuPd=GPIO_PULLUP PA9.Mode=Asynchronous PA9.Signal=USART1_TX PB0.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode diff --git a/bsp/stm32/stm32f429-st-disco/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f429-st-disco/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index e4cc442eb3..ca708938e4 100644 --- a/bsp/stm32/stm32f429-st-disco/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f429-st-disco/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -187,12 +187,12 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) /* USER CODE BEGIN I2C3_MspInit 0 */ /* USER CODE END I2C3_MspInit 0 */ - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); - /**I2C3 GPIO Configuration + /**I2C3 GPIO Configuration PC9 ------> I2C3_SDA - PA8 ------> I2C3_SCL + PA8 ------> I2C3_SCL */ GPIO_InitStruct.Pin = I2C3_SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; @@ -232,10 +232,10 @@ void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) /* USER CODE END I2C3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_I2C3_CLK_DISABLE(); - - /**I2C3 GPIO Configuration + + /**I2C3 GPIO Configuration PC9 ------> I2C3_SDA - PA8 ------> I2C3_SCL + PA8 ------> I2C3_SCL */ HAL_GPIO_DeInit(I2C3_SDA_GPIO_Port, I2C3_SDA_Pin); @@ -264,14 +264,14 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LTDC_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**LTDC GPIO Configuration + /**LTDC GPIO Configuration PF10 ------> LTDC_DE PA3 ------> LTDC_B5 PA4 ------> LTDC_VSYNC @@ -293,7 +293,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) PG11 ------> LTDC_B3 PG12 ------> LTDC_B4 PB8 ------> LTDC_B6 - PB9 ------> LTDC_B7 + PB9 ------> LTDC_B7 */ GPIO_InitStruct.Pin = ENABLE_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -302,7 +302,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) GPIO_InitStruct.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(ENABLE_GPIO_Port, &GPIO_InitStruct); - GPIO_InitStruct.Pin = B5_Pin|VSYNC_Pin|G2_Pin|R4_Pin + GPIO_InitStruct.Pin = B5_Pin|VSYNC_Pin|G2_Pin|R4_Pin |R5_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -377,8 +377,8 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LTDC_CLK_DISABLE(); - - /**LTDC GPIO Configuration + + /**LTDC GPIO Configuration PF10 ------> LTDC_DE PA3 ------> LTDC_B5 PA4 ------> LTDC_VSYNC @@ -400,17 +400,17 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) PG11 ------> LTDC_B3 PG12 ------> LTDC_B4 PB8 ------> LTDC_B6 - PB9 ------> LTDC_B7 + PB9 ------> LTDC_B7 */ HAL_GPIO_DeInit(ENABLE_GPIO_Port, ENABLE_Pin); - HAL_GPIO_DeInit(GPIOA, B5_Pin|VSYNC_Pin|G2_Pin|R4_Pin + HAL_GPIO_DeInit(GPIOA, B5_Pin|VSYNC_Pin|G2_Pin|R4_Pin |R5_Pin); - HAL_GPIO_DeInit(GPIOB, R3_Pin|R6_Pin|G4_Pin|G5_Pin + HAL_GPIO_DeInit(GPIOB, R3_Pin|R6_Pin|G4_Pin|G5_Pin |B6_Pin|B7_Pin); - HAL_GPIO_DeInit(GPIOG, R7_Pin|DOTCLK_Pin|G3_Pin|B3_Pin + HAL_GPIO_DeInit(GPIOG, R7_Pin|DOTCLK_Pin|G3_Pin|B3_Pin |B4_Pin); HAL_GPIO_DeInit(GPIOC, HSYNC_Pin|G6_Pin|R2_Pin); @@ -442,12 +442,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI5_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); - /**SPI5 GPIO Configuration + /**SPI5 GPIO Configuration PF7 ------> SPI5_SCK PF8 ------> SPI5_MISO - PF9 ------> SPI5_MOSI + PF9 ------> SPI5_MOSI */ GPIO_InitStruct.Pin = SPI5_SCK_Pin|SPI5_MISO_Pin|SPI5_MOSI_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -478,11 +478,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI5_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI5_CLK_DISABLE(); - - /**SPI5 GPIO Configuration + + /**SPI5 GPIO Configuration PF7 ------> SPI5_SCK PF8 ------> SPI5_MISO - PF9 ------> SPI5_MOSI + PF9 ------> SPI5_MOSI */ HAL_GPIO_DeInit(GPIOF, SPI5_SCK_Pin|SPI5_MISO_Pin|SPI5_MOSI_Pin); @@ -553,11 +553,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = STLINK_RX_Pin|STLINK_TX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -588,10 +588,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, STLINK_RX_Pin|STLINK_TX_Pin); @@ -615,8 +615,8 @@ static void HAL_FMC_MspInit(void){ FMC_Initialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_ENABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -656,8 +656,8 @@ static void HAL_FMC_MspInit(void){ PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 */ - GPIO_InitStruct.Pin = A0_Pin|A1_Pin|A2_Pin|A3_Pin - |A4_Pin|A5_Pin|SDNRAS_Pin|A6_Pin + GPIO_InitStruct.Pin = A0_Pin|A1_Pin|A2_Pin|A3_Pin + |A4_Pin|A5_Pin|SDNRAS_Pin|A6_Pin |A7_Pin|A8_Pin|A9_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -672,7 +672,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(SDNWE_GPIO_Port, &GPIO_InitStruct); - GPIO_InitStruct.Pin = A10_Pin|A11_Pin|BA0_Pin|BA1_Pin + GPIO_InitStruct.Pin = A10_Pin|A11_Pin|BA0_Pin|BA1_Pin |SDCLK_Pin|SDNCAS_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -680,8 +680,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - GPIO_InitStruct.Pin = D4_Pin|D5_Pin|D6_Pin|D7_Pin - |D8_Pin|D9_Pin|D10_Pin|D11_Pin + GPIO_InitStruct.Pin = D4_Pin|D5_Pin|D6_Pin|D7_Pin + |D8_Pin|D9_Pin|D10_Pin|D11_Pin |D12_Pin|NBL0_Pin|NBL1_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -689,7 +689,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - GPIO_InitStruct.Pin = D13_Pin|D14_Pin|D15_Pin|D0_Pin + GPIO_InitStruct.Pin = D13_Pin|D14_Pin|D15_Pin|D0_Pin |D1_Pin|D2_Pin|D3_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -731,8 +731,8 @@ static void HAL_FMC_MspDeInit(void){ FMC_DeInitialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_DISABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -772,20 +772,20 @@ static void HAL_FMC_MspDeInit(void){ PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 */ - HAL_GPIO_DeInit(GPIOF, A0_Pin|A1_Pin|A2_Pin|A3_Pin - |A4_Pin|A5_Pin|SDNRAS_Pin|A6_Pin + HAL_GPIO_DeInit(GPIOF, A0_Pin|A1_Pin|A2_Pin|A3_Pin + |A4_Pin|A5_Pin|SDNRAS_Pin|A6_Pin |A7_Pin|A8_Pin|A9_Pin); HAL_GPIO_DeInit(SDNWE_GPIO_Port, SDNWE_Pin); - HAL_GPIO_DeInit(GPIOG, A10_Pin|A11_Pin|BA0_Pin|BA1_Pin + HAL_GPIO_DeInit(GPIOG, A10_Pin|A11_Pin|BA0_Pin|BA1_Pin |SDCLK_Pin|SDNCAS_Pin); - HAL_GPIO_DeInit(GPIOE, D4_Pin|D5_Pin|D6_Pin|D7_Pin - |D8_Pin|D9_Pin|D10_Pin|D11_Pin + HAL_GPIO_DeInit(GPIOE, D4_Pin|D5_Pin|D6_Pin|D7_Pin + |D8_Pin|D9_Pin|D10_Pin|D11_Pin |D12_Pin|NBL0_Pin|NBL1_Pin); - HAL_GPIO_DeInit(GPIOD, D13_Pin|D14_Pin|D15_Pin|D0_Pin + HAL_GPIO_DeInit(GPIOD, D13_Pin|D14_Pin|D15_Pin|D0_Pin |D1_Pin|D2_Pin|D3_Pin); HAL_GPIO_DeInit(GPIOB, SDCKE1_Pin|SDNE1_Pin); diff --git a/bsp/stm32/stm32f446-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f446-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index ea2f9755c5..6293374ccd 100644 --- a/bsp/stm32/stm32f446-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f446-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -34,14 +34,14 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false -PA10.Mode=Asynchronous -PA10.Signal=USART1_RX -PA13.Mode=Serial_Wire -PA13.Signal=SYS_JTMS-SWDIO -PA14.Mode=Serial_Wire -PA14.Signal=SYS_JTCK-SWCLK +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP PA9.Mode=Asynchronous PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP +PA10.Mode=Asynchronous +PA10.Signal=USART1_RX PC14-OSC32_IN.Mode=LSE-External-Oscillator PC14-OSC32_IN.Signal=RCC_OSC32_IN PC15-OSC32_OUT.Mode=LSE-External-Oscillator diff --git a/bsp/stm32/stm32f446-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f446-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index a299f50c87..23b216769b 100644 --- a/bsp/stm32/stm32f446-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f446-st-nucleo/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -114,11 +114,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -151,10 +151,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); diff --git a/bsp/stm32/stm32f469-st-disco/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f469-st-disco/board/CubeMX_Config/CubeMX_Config.ioc index ba698b848e..3e1042d18c 100644 --- a/bsp/stm32/stm32f469-st-disco/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f469-st-disco/board/CubeMX_Config/CubeMX_Config.ioc @@ -182,10 +182,12 @@ PA15.GPIOParameters=GPIO_Speed PA15.GPIO_Speed=GPIO_SPEED_FREQ_HIGH PA15.Mode=Half_Duplex_Master PA15.Signal=I2S3_WS -PB10.Locked=true +PB10.GPIOParameters=GPIO_PuPd +PB10.GPIO_PuPd=GPIO_PULLUP PB10.Mode=Asynchronous PB10.Signal=USART3_TX -PB11.Locked=true +PB11.GPIOParameters=GPIO_PuPd +PB11.GPIO_PuPd=GPIO_PULLUP PB11.Mode=Asynchronous PB11.Signal=USART3_RX PB3.GPIOParameters=GPIO_Speed diff --git a/bsp/stm32/stm32f469-st-disco/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c b/bsp/stm32/stm32f469-st-disco/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c index 08cb949966..4c00b2386a 100644 --- a/bsp/stm32/stm32f469-st-disco/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c +++ b/bsp/stm32/stm32f469-st-disco/board/CubeMX_Config/Src/stm32f4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -58,7 +58,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -227,14 +227,14 @@ void HAL_I2S_MspInit(I2S_HandleTypeDef* hi2s) /* USER CODE END SPI3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**I2S3 GPIO Configuration + /**I2S3 GPIO Configuration PB3 ------> I2S3_CK PA15 ------> I2S3_WS - PD6 ------> I2S3_SD + PD6 ------> I2S3_SD */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -282,11 +282,11 @@ void HAL_I2S_MspDeInit(I2S_HandleTypeDef* hi2s) /* USER CODE END SPI3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI3_CLK_DISABLE(); - - /**I2S3 GPIO Configuration + + /**I2S3 GPIO Configuration PB3 ------> I2S3_CK PA15 ------> I2S3_WS - PD6 ------> I2S3_SD + PD6 ------> I2S3_SD */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3); @@ -363,16 +363,16 @@ void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_QSPI_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); - /**QUADSPI GPIO Configuration + /**QUADSPI GPIO Configuration PB6 ------> QUADSPI_BK1_NCS PF7 ------> QUADSPI_BK1_IO2 PF6 ------> QUADSPI_BK1_IO3 PF10 ------> QUADSPI_CLK PF9 ------> QUADSPI_BK1_IO1 - PF8 ------> QUADSPI_BK1_IO0 + PF8 ------> QUADSPI_BK1_IO0 */ GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -417,18 +417,18 @@ void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_QSPI_CLK_DISABLE(); - - /**QUADSPI GPIO Configuration + + /**QUADSPI GPIO Configuration PB6 ------> QUADSPI_BK1_NCS PF7 ------> QUADSPI_BK1_IO2 PF6 ------> QUADSPI_BK1_IO3 PF10 ------> QUADSPI_CLK PF9 ------> QUADSPI_BK1_IO1 - PF8 ------> QUADSPI_BK1_IO0 + PF8 ------> QUADSPI_BK1_IO0 */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6); - HAL_GPIO_DeInit(GPIOF, GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_10|GPIO_PIN_9 + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_10|GPIO_PIN_9 |GPIO_PIN_8); /* USER CODE BEGIN QUADSPI_MspDeInit 1 */ @@ -454,18 +454,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDIO_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDIO GPIO Configuration + /**SDIO GPIO Configuration PC12 ------> SDIO_CK PC11 ------> SDIO_D3 PC10 ------> SDIO_D2 PD2 ------> SDIO_CMD PC9 ------> SDIO_D1 - PC8 ------> SDIO_D0 + PC8 ------> SDIO_D0 */ - GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 + GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 |GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -502,16 +502,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDIO_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDIO_CLK_DISABLE(); - - /**SDIO GPIO Configuration + + /**SDIO GPIO Configuration PC12 ------> SDIO_CK PC11 ------> SDIO_D3 PC10 ------> SDIO_D2 PD2 ------> SDIO_CMD PC9 ------> SDIO_D1 - PC8 ------> SDIO_D0 + PC8 ------> SDIO_D0 */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 |GPIO_PIN_8); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -539,10 +539,10 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) /* USER CODE END TIM4_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_TIM4_CLK_ENABLE(); - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**TIM4 GPIO Configuration - PD12 ------> TIM4_CH1 + /**TIM4 GPIO Configuration + PD12 ------> TIM4_CH1 */ GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -566,10 +566,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM4_MspPostInit 0 */ /* USER CODE END TIM4_MspPostInit 0 */ - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**TIM4 GPIO Configuration - PD13 ------> TIM4_CH2 + /**TIM4 GPIO Configuration + PD13 ------> TIM4_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -599,10 +599,10 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base) /* USER CODE END TIM4_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_TIM4_CLK_DISABLE(); - - /**TIM4 GPIO Configuration + + /**TIM4 GPIO Configuration PD12 ------> TIM4_CH1 - PD13 ------> TIM4_CH2 + PD13 ------> TIM4_CH2 */ HAL_GPIO_DeInit(GPIOD, GPIO_PIN_12|GPIO_PIN_13); @@ -629,11 +629,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -664,10 +664,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); @@ -692,11 +692,11 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ /* USER CODE END USB_OTG_FS_MspInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB_OTG_FS GPIO Configuration + /**USB_OTG_FS GPIO Configuration PA12 ------> USB_OTG_FS_DP - PA11 ------> USB_OTG_FS_DM + PA11 ------> USB_OTG_FS_DM */ GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -732,10 +732,10 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) /* USER CODE END USB_OTG_FS_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); - - /**USB_OTG_FS GPIO Configuration + + /**USB_OTG_FS GPIO Configuration PA12 ------> USB_OTG_FS_DP - PA11 ------> USB_OTG_FS_DM + PA11 ------> USB_OTG_FS_DM */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_12|GPIO_PIN_11); @@ -761,8 +761,8 @@ static void HAL_FMC_MspInit(void){ FMC_Initialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_ENABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PE1 ------> FMC_NBL1 PE0 ------> FMC_NBL0 PG15 ------> FMC_SDNCAS @@ -820,8 +820,8 @@ static void HAL_FMC_MspInit(void){ PE15 ------> FMC_D12 PE13 ------> FMC_D10 */ - GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0|GPIO_PIN_8|GPIO_PIN_9 - |GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_7|GPIO_PIN_10 + GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0|GPIO_PIN_8|GPIO_PIN_9 + |GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_7|GPIO_PIN_10 |GPIO_PIN_12|GPIO_PIN_15|GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -829,7 +829,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_15|GPIO_PIN_8|GPIO_PIN_1|GPIO_PIN_0 + GPIO_InitStruct.Pin = GPIO_PIN_15|GPIO_PIN_8|GPIO_PIN_1|GPIO_PIN_0 |GPIO_PIN_5|GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -837,7 +837,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_15|GPIO_PIN_10 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_15|GPIO_PIN_10 |GPIO_PIN_14|GPIO_PIN_9|GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -845,8 +845,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_5 - |GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_6|GPIO_PIN_1 + GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_5 + |GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_6|GPIO_PIN_1 |GPIO_PIN_9|GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -854,8 +854,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_15 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_15 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -863,8 +863,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_15|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_3 - |GPIO_PIN_2|GPIO_PIN_12|GPIO_PIN_9|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_15|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_3 + |GPIO_PIN_2|GPIO_PIN_12|GPIO_PIN_9|GPIO_PIN_11 |GPIO_PIN_8|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -906,8 +906,8 @@ static void HAL_FMC_MspDeInit(void){ FMC_DeInitialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_DISABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PE1 ------> FMC_NBL1 PE0 ------> FMC_NBL0 PG15 ------> FMC_SDNCAS @@ -965,26 +965,26 @@ static void HAL_FMC_MspDeInit(void){ PE15 ------> FMC_D12 PE13 ------> FMC_D10 */ - HAL_GPIO_DeInit(GPIOE, GPIO_PIN_1|GPIO_PIN_0|GPIO_PIN_8|GPIO_PIN_9 - |GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_7|GPIO_PIN_10 + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_1|GPIO_PIN_0|GPIO_PIN_8|GPIO_PIN_9 + |GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_7|GPIO_PIN_10 |GPIO_PIN_12|GPIO_PIN_15|GPIO_PIN_13); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_15|GPIO_PIN_8|GPIO_PIN_1|GPIO_PIN_0 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_15|GPIO_PIN_8|GPIO_PIN_1|GPIO_PIN_0 |GPIO_PIN_5|GPIO_PIN_4); - HAL_GPIO_DeInit(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_15|GPIO_PIN_10 + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_15|GPIO_PIN_10 |GPIO_PIN_14|GPIO_PIN_9|GPIO_PIN_8); - HAL_GPIO_DeInit(GPIOI, GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_5 - |GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_6|GPIO_PIN_1 + HAL_GPIO_DeInit(GPIOI, GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_5 + |GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_6|GPIO_PIN_1 |GPIO_PIN_9|GPIO_PIN_0); - HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_15 + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_15 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_11); - HAL_GPIO_DeInit(GPIOH, GPIO_PIN_15|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_3 - |GPIO_PIN_2|GPIO_PIN_12|GPIO_PIN_9|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOH, GPIO_PIN_15|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_3 + |GPIO_PIN_2|GPIO_PIN_12|GPIO_PIN_9|GPIO_PIN_11 |GPIO_PIN_8|GPIO_PIN_10); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0); diff --git a/bsp/stm32/stm32f746-st-disco/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f746-st-disco/board/CubeMX_Config/CubeMX_Config.ioc index 3813651ece..148a2ca783 100644 --- a/bsp/stm32/stm32f746-st-disco/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f746-st-disco/board/CubeMX_Config/CubeMX_Config.ioc @@ -142,15 +142,18 @@ PA2.Mode=RMII PA2.Signal=ETH_MDIO PA7.Mode=RMII PA7.Signal=ETH_CRS_DV -PA9.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP PA9.Mode=Asynchronous PA9.Signal=USART1_TX +PB7.GPIOParameters=GPIO_PuPd +PB7.GPIO_PuPd=GPIO_PULLUP +PB7.Mode=Asynchronous +PB7.Signal=USART1_RX PB2.Mode=Single Bank 1 PB2.Signal=QUADSPI_CLK PB6.Mode=Single Bank 1 PB6.Signal=QUADSPI_BK1_NCS -PB7.Mode=Asynchronous -PB7.Signal=USART1_RX PC1.Mode=RMII PC1.Signal=ETH_MDC PC10.Mode=SD_4_bits_Wide_bus diff --git a/bsp/stm32/stm32f746-st-disco/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c b/bsp/stm32/stm32f746-st-disco/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c index fd77b00626..8f4696a1d7 100644 --- a/bsp/stm32/stm32f746-st-disco/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c +++ b/bsp/stm32/stm32f746-st-disco/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -113,11 +113,11 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ETH_CLK_ENABLE(); - + __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); - /**ETH GPIO Configuration + /**ETH GPIO Configuration PG14 ------> ETH_TXD1 PG13 ------> ETH_TXD0 PG11 ------> ETH_TX_EN @@ -126,7 +126,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) PC4 ------> ETH_RXD0 PA2 ------> ETH_MDIO PC5 ------> ETH_RXD1 - PA7 ------> ETH_CRS_DV + PA7 ------> ETH_CRS_DV */ GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_13|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -171,8 +171,8 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ETH_CLK_DISABLE(); - - /**ETH GPIO Configuration + + /**ETH GPIO Configuration PG14 ------> ETH_TXD1 PG13 ------> ETH_TXD0 PG11 ------> ETH_TX_EN @@ -181,7 +181,7 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) PC4 ------> ETH_RXD0 PA2 ------> ETH_MDIO PC5 ------> ETH_RXD1 - PA7 ------> ETH_CRS_DV + PA7 ------> ETH_CRS_DV */ HAL_GPIO_DeInit(GPIOG, GPIO_PIN_14|GPIO_PIN_13|GPIO_PIN_11); @@ -212,13 +212,13 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LTDC_CLK_ENABLE(); - + __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOJ_CLK_ENABLE(); __HAL_RCC_GPIOK_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); - /**LTDC GPIO Configuration + /**LTDC GPIO Configuration PE4 ------> LTDC_B0 PJ13 ------> LTDC_B1 PK7 ------> LTDC_DE @@ -246,7 +246,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) PJ3 ------> LTDC_R4 PJ2 ------> LTDC_R3 PJ0 ------> LTDC_R1 - PJ1 ------> LTDC_R2 + PJ1 ------> LTDC_R2 */ GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -255,9 +255,9 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) GPIO_InitStruct.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_11 - |GPIO_PIN_8|GPIO_PIN_10|GPIO_PIN_7|GPIO_PIN_9 - |GPIO_PIN_6|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_3 + GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_11 + |GPIO_PIN_8|GPIO_PIN_10|GPIO_PIN_7|GPIO_PIN_9 + |GPIO_PIN_6|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_3 |GPIO_PIN_2|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -265,7 +265,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) GPIO_InitStruct.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOJ, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_5|GPIO_PIN_4 + GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_5|GPIO_PIN_4 |GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -309,8 +309,8 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LTDC_CLK_DISABLE(); - - /**LTDC GPIO Configuration + + /**LTDC GPIO Configuration PE4 ------> LTDC_B0 PJ13 ------> LTDC_B1 PK7 ------> LTDC_DE @@ -338,16 +338,16 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) PJ3 ------> LTDC_R4 PJ2 ------> LTDC_R3 PJ0 ------> LTDC_R1 - PJ1 ------> LTDC_R2 + PJ1 ------> LTDC_R2 */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_4); - HAL_GPIO_DeInit(GPIOJ, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_11 - |GPIO_PIN_8|GPIO_PIN_10|GPIO_PIN_7|GPIO_PIN_9 - |GPIO_PIN_6|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_3 + HAL_GPIO_DeInit(GPIOJ, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_11 + |GPIO_PIN_8|GPIO_PIN_10|GPIO_PIN_7|GPIO_PIN_9 + |GPIO_PIN_6|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_3 |GPIO_PIN_2|GPIO_PIN_0|GPIO_PIN_1); - HAL_GPIO_DeInit(GPIOK, GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_5|GPIO_PIN_4 + HAL_GPIO_DeInit(GPIOK, GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_5|GPIO_PIN_4 |GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_0); HAL_GPIO_DeInit(GPIOG, GPIO_PIN_12); @@ -377,17 +377,17 @@ void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_QSPI_CLK_ENABLE(); - + __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**QUADSPI GPIO Configuration + /**QUADSPI GPIO Configuration PE2 ------> QUADSPI_BK1_IO2 PB6 ------> QUADSPI_BK1_NCS PB2 ------> QUADSPI_CLK PD12 ------> QUADSPI_BK1_IO1 PD13 ------> QUADSPI_BK1_IO3 - PD11 ------> QUADSPI_BK1_IO0 + PD11 ------> QUADSPI_BK1_IO0 */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -439,14 +439,14 @@ void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_QSPI_CLK_DISABLE(); - - /**QUADSPI GPIO Configuration + + /**QUADSPI GPIO Configuration PE2 ------> QUADSPI_BK1_IO2 PB6 ------> QUADSPI_BK1_NCS PB2 ------> QUADSPI_CLK PD12 ------> QUADSPI_BK1_IO1 PD13 ------> QUADSPI_BK1_IO3 - PD11 ------> QUADSPI_BK1_IO0 + PD11 ------> QUADSPI_BK1_IO0 */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_2); @@ -477,18 +477,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDMMC1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDMMC1 GPIO Configuration + /**SDMMC1 GPIO Configuration PC12 ------> SDMMC1_CK PC11 ------> SDMMC1_D3 PC10 ------> SDMMC1_D2 PD2 ------> SDMMC1_CMD PC9 ------> SDMMC1_D1 - PC8 ------> SDMMC1_D0 + PC8 ------> SDMMC1_D0 */ - GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 + GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 |GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -525,16 +525,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDMMC1_CLK_DISABLE(); - - /**SDMMC1 GPIO Configuration + + /**SDMMC1 GPIO Configuration PC12 ------> SDMMC1_CK PC11 ------> SDMMC1_D3 PC10 ------> SDMMC1_D2 PD2 ------> SDMMC1_CMD PC9 ------> SDMMC1_D1 - PC8 ------> SDMMC1_D0 + PC8 ------> SDMMC1_D0 */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 |GPIO_PIN_8); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -606,23 +606,23 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PB7 ------> USART1_RX - PA9 ------> USART1_TX + PA9 ------> USART1_TX */ GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -649,10 +649,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PB7 ------> USART1_RX - PA9 ------> USART1_TX + PA9 ------> USART1_TX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7); @@ -678,8 +678,8 @@ static void HAL_FMC_MspInit(void){ FMC_Initialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_ENABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PG15 ------> FMC_SDNCAS PD0 ------> FMC_D2 PD1 ------> FMC_D3 @@ -771,8 +771,8 @@ static void HAL_FMC_MspDeInit(void){ FMC_DeInitialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_DISABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PG15 ------> FMC_SDNCAS PD0 ------> FMC_D2 PD1 ------> FMC_D3 @@ -809,22 +809,22 @@ static void HAL_FMC_MspDeInit(void){ PE15 ------> FMC_D12 PE13 ------> FMC_D10 */ - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_15|GPIO_PIN_8|GPIO_PIN_0|GPIO_PIN_5 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_15|GPIO_PIN_8|GPIO_PIN_0|GPIO_PIN_5 |GPIO_PIN_4); - HAL_GPIO_DeInit(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_15|GPIO_PIN_10 + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_15|GPIO_PIN_10 |GPIO_PIN_14|GPIO_PIN_9|GPIO_PIN_8); - HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_15 + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_15 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_11); HAL_GPIO_DeInit(GPIOH, GPIO_PIN_5|GPIO_PIN_3); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_3); - HAL_GPIO_DeInit(GPIOE, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_11|GPIO_PIN_14 - |GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_12|GPIO_PIN_15 + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_11|GPIO_PIN_14 + |GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_12|GPIO_PIN_15 |GPIO_PIN_13); /* USER CODE BEGIN FMC_MspDeInit 1 */ diff --git a/bsp/stm32/stm32f767-atk-apollo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f767-atk-apollo/board/CubeMX_Config/CubeMX_Config.ioc index 506854c422..e1b152b6e1 100644 --- a/bsp/stm32/stm32f767-atk-apollo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f767-atk-apollo/board/CubeMX_Config/CubeMX_Config.ioc @@ -161,7 +161,12 @@ NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false PA1.Mode=RMII PA1.Signal=ETH_REF_CLK -PA10.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA11.Mode=Host_Only @@ -182,9 +187,6 @@ PA7.Mode=RMII PA7.Signal=ETH_CRS_DV PA8.Mode=RGB565 PA8.Signal=LTDC_B3 -PA9.Locked=true -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PB0.Locked=true PB0.Signal=S_TIM3_CH3 PB1.Mode=RGB565 diff --git a/bsp/stm32/stm32f767-atk-apollo/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c b/bsp/stm32/stm32f767-atk-apollo/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c index 3fe29e92c9..988628d3d8 100644 --- a/bsp/stm32/stm32f767-atk-apollo/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c +++ b/bsp/stm32/stm32f767-atk-apollo/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -115,10 +115,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PA5 ------> ADC1_IN5 + /**ADC1 GPIO Configuration + PA5 ------> ADC1_IN5 */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -147,9 +147,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration - PA5 ------> ADC1_IN5 + + /**ADC1 GPIO Configuration + PA5 ------> ADC1_IN5 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5); @@ -176,12 +176,12 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ETH_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); - /**ETH GPIO Configuration + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -190,7 +190,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PB11 ------> ETH_TX_EN PG13 ------> ETH_TXD0 - PG14 ------> ETH_TXD1 + PG14 ------> ETH_TXD1 */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -242,8 +242,8 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ETH_CLK_DISABLE(); - - /**ETH GPIO Configuration + + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -252,7 +252,7 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PB11 ------> ETH_TX_EN PG13 ------> ETH_TXD0 - PG14 ------> ETH_TXD1 + PG14 ------> ETH_TXD1 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5); @@ -285,14 +285,14 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LTDC_CLK_ENABLE(); - + __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); - /**LTDC GPIO Configuration + /**LTDC GPIO Configuration PI9 ------> LTDC_VSYNC PI10 ------> LTDC_HSYNC PI11 ------> LTDC_G6 @@ -312,7 +312,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) PG12 ------> LTDC_B4 PB8 ------> LTDC_B6 PB9 ------> LTDC_B7 - PI5 ------> LTDC_B5 + PI5 ------> LTDC_B5 */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_2|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -413,8 +413,8 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LTDC_CLK_DISABLE(); - - /**LTDC GPIO Configuration + + /**LTDC GPIO Configuration PI9 ------> LTDC_VSYNC PI10 ------> LTDC_HSYNC PI11 ------> LTDC_G6 @@ -434,14 +434,14 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) PG12 ------> LTDC_B4 PB8 ------> LTDC_B6 PB9 ------> LTDC_B7 - PI5 ------> LTDC_B5 + PI5 ------> LTDC_B5 */ - HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_2 + HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_2 |GPIO_PIN_5); HAL_GPIO_DeInit(GPIOF, GPIO_PIN_10); - HAL_GPIO_DeInit(GPIOH, GPIO_PIN_4|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOH, GPIO_PIN_4|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_14); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_6|GPIO_PIN_8); @@ -473,16 +473,16 @@ void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_QSPI_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**QUADSPI GPIO Configuration + /**QUADSPI GPIO Configuration PF6 ------> QUADSPI_BK1_IO3 PF7 ------> QUADSPI_BK1_IO2 PF8 ------> QUADSPI_BK1_IO0 PF9 ------> QUADSPI_BK1_IO1 PB2 ------> QUADSPI_CLK - PB6 ------> QUADSPI_BK1_NCS + PB6 ------> QUADSPI_BK1_NCS */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -534,14 +534,14 @@ void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_QSPI_CLK_DISABLE(); - - /**QUADSPI GPIO Configuration + + /**QUADSPI GPIO Configuration PF6 ------> QUADSPI_BK1_IO3 PF7 ------> QUADSPI_BK1_IO2 PF8 ------> QUADSPI_BK1_IO0 PF9 ------> QUADSPI_BK1_IO1 PB2 ------> QUADSPI_CLK - PB6 ------> QUADSPI_BK1_NCS + PB6 ------> QUADSPI_BK1_NCS */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9); @@ -614,18 +614,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDMMC1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDMMC1 GPIO Configuration + /**SDMMC1 GPIO Configuration PC8 ------> SDMMC1_D0 PC9 ------> SDMMC1_D1 PC10 ------> SDMMC1_D2 PC11 ------> SDMMC1_D3 PC12 ------> SDMMC1_CK - PD2 ------> SDMMC1_CMD + PD2 ------> SDMMC1_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -662,16 +662,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDMMC1_CLK_DISABLE(); - - /**SDMMC1 GPIO Configuration + + /**SDMMC1 GPIO Configuration PC8 ------> SDMMC1_D0 PC9 ------> SDMMC1_D1 PC10 ------> SDMMC1_D2 PC11 ------> SDMMC1_D3 PC12 ------> SDMMC1_CK - PD2 ------> SDMMC1_CMD + PD2 ------> SDMMC1_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -699,12 +699,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -735,11 +735,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); @@ -836,8 +836,8 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE END TIM2_MspPostInit 0 */ __HAL_RCC_GPIOA_CLK_ENABLE(); - /**TIM2 GPIO Configuration - PA3 ------> TIM2_CH4 + /**TIM2 GPIO Configuration + PA3 ------> TIM2_CH4 */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -855,10 +855,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM3_MspPostInit 0 */ /* USER CODE END TIM3_MspPostInit 0 */ - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**TIM3 GPIO Configuration - PB0 ------> TIM3_CH3 + /**TIM3 GPIO Configuration + PB0 ------> TIM3_CH3 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -966,15 +966,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -990,15 +990,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PD5 ------> USART2_TX - PD6 ------> USART2_RX + PD6 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); @@ -1025,10 +1025,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -1043,10 +1043,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PD5 ------> USART2_TX - PD6 ------> USART2_RX + PD6 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOD, GPIO_PIN_5|GPIO_PIN_6); @@ -1071,11 +1071,11 @@ void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd) /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ /* USER CODE END USB_OTG_FS_MspInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB_OTG_FS GPIO Configuration + /**USB_OTG_FS GPIO Configuration PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -1111,10 +1111,10 @@ void HAL_HCD_MspDeInit(HCD_HandleTypeDef* hhcd) /* USER CODE END USB_OTG_FS_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); - - /**USB_OTG_FS GPIO Configuration + + /**USB_OTG_FS GPIO Configuration PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); @@ -1140,8 +1140,8 @@ static void HAL_FMC_MspInit(void){ FMC_Initialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_ENABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -1180,8 +1180,8 @@ static void HAL_FMC_MspInit(void){ PD1 ------> FMC_D3 PG15 ------> FMC_SDNCAS */ - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1196,7 +1196,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 |GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1204,8 +1204,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1213,7 +1213,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -1248,8 +1248,8 @@ static void HAL_FMC_MspDeInit(void){ FMC_DeInitialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_DISABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -1288,20 +1288,20 @@ static void HAL_FMC_MspDeInit(void){ PD1 ------> FMC_D3 PG15 ------> FMC_SDNCAS */ - HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 |GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1); /* USER CODE BEGIN FMC_MspDeInit 1 */ diff --git a/bsp/stm32/stm32f767-fire-challenger-v1/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f767-fire-challenger-v1/board/CubeMX_Config/CubeMX_Config.ioc index c9b386e6ca..bc1a38ca7c 100644 --- a/bsp/stm32/stm32f767-fire-challenger-v1/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f767-fire-challenger-v1/board/CubeMX_Config/CubeMX_Config.ioc @@ -138,7 +138,12 @@ NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false PA1.Mode=RMII PA1.Signal=ETH_REF_CLK -PA10.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA11.GPIOParameters=GPIO_Speed @@ -160,9 +165,6 @@ PA3.Signal=LTDC_B5 PA5.Signal=ADCx_IN5 PA7.Mode=RMII PA7.Signal=ETH_CRS_DV -PA9.Locked=true -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PB0.GPIOParameters=GPIO_Speed PB0.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH PB0.Mode=RGB888 diff --git a/bsp/stm32/stm32f767-fire-challenger-v1/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c b/bsp/stm32/stm32f767-fire-challenger-v1/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c index a395939496..785137daf5 100644 --- a/bsp/stm32/stm32f767-fire-challenger-v1/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c +++ b/bsp/stm32/stm32f767-fire-challenger-v1/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -113,10 +113,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PA5 ------> ADC1_IN5 + /**ADC1 GPIO Configuration + PA5 ------> ADC1_IN5 */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -145,9 +145,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration - PA5 ------> ADC1_IN5 + + /**ADC1 GPIO Configuration + PA5 ------> ADC1_IN5 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5); @@ -218,11 +218,11 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ETH_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**ETH GPIO Configuration + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -231,7 +231,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PB11 ------> ETH_TX_EN PB12 ------> ETH_TXD0 - PB13 ------> ETH_TXD1 + PB13 ------> ETH_TXD1 */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -276,8 +276,8 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ETH_CLK_DISABLE(); - - /**ETH GPIO Configuration + + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -286,7 +286,7 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PB11 ------> ETH_TX_EN PB12 ------> ETH_TXD0 - PB13 ------> ETH_TXD1 + PB13 ------> ETH_TXD1 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5); @@ -317,7 +317,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LTDC_CLK_ENABLE(); - + __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); @@ -327,7 +327,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**LTDC GPIO Configuration + /**LTDC GPIO Configuration PE4 ------> LTDC_B0 PE5 ------> LTDC_G0 PE6 ------> LTDC_G1 @@ -355,7 +355,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) PG12 ------> LTDC_B1 PB8 ------> LTDC_B6 PB9 ------> LTDC_B7 - PI4 ------> LTDC_B4 + PI4 ------> LTDC_B4 */ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -364,7 +364,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) GPIO_InitStruct.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_2 + GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_2 |GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -379,7 +379,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) GPIO_InitStruct.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_8|GPIO_PIN_13 + GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_8|GPIO_PIN_13 |GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -465,8 +465,8 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LTDC_CLK_DISABLE(); - - /**LTDC GPIO Configuration + + /**LTDC GPIO Configuration PE4 ------> LTDC_B0 PE5 ------> LTDC_G0 PE6 ------> LTDC_G1 @@ -494,23 +494,23 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) PG12 ------> LTDC_B1 PB8 ------> LTDC_B6 PB9 ------> LTDC_B7 - PI4 ------> LTDC_B4 + PI4 ------> LTDC_B4 */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6); - HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_2 + HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_2 |GPIO_PIN_4); HAL_GPIO_DeInit(GPIOF, GPIO_PIN_10); - HAL_GPIO_DeInit(GPIOH, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_8|GPIO_PIN_13 + HAL_GPIO_DeInit(GPIOH, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_8|GPIO_PIN_13 |GPIO_PIN_15); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3|GPIO_PIN_11|GPIO_PIN_12); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_8|GPIO_PIN_9); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_7); @@ -540,16 +540,16 @@ void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_QSPI_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**QUADSPI GPIO Configuration + /**QUADSPI GPIO Configuration PF6 ------> QUADSPI_BK1_IO3 PF7 ------> QUADSPI_BK1_IO2 PF8 ------> QUADSPI_BK1_IO0 PF9 ------> QUADSPI_BK1_IO1 PB2 ------> QUADSPI_CLK - PB6 ------> QUADSPI_BK1_NCS + PB6 ------> QUADSPI_BK1_NCS */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -601,14 +601,14 @@ void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_QSPI_CLK_DISABLE(); - - /**QUADSPI GPIO Configuration + + /**QUADSPI GPIO Configuration PF6 ------> QUADSPI_BK1_IO3 PF7 ------> QUADSPI_BK1_IO2 PF8 ------> QUADSPI_BK1_IO0 PF9 ------> QUADSPI_BK1_IO1 PB2 ------> QUADSPI_CLK - PB6 ------> QUADSPI_BK1_NCS + PB6 ------> QUADSPI_BK1_NCS */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9); @@ -637,18 +637,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDMMC1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDMMC1 GPIO Configuration + /**SDMMC1 GPIO Configuration PC8 ------> SDMMC1_D0 PC9 ------> SDMMC1_D1 PC10 ------> SDMMC1_D2 PC11 ------> SDMMC1_D3 PC12 ------> SDMMC1_CK - PD2 ------> SDMMC1_CMD + PD2 ------> SDMMC1_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -685,16 +685,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDMMC1_CLK_DISABLE(); - - /**SDMMC1 GPIO Configuration + + /**SDMMC1 GPIO Configuration PC8 ------> SDMMC1_D0 PC9 ------> SDMMC1_D1 PC10 ------> SDMMC1_D2 PC11 ------> SDMMC1_D3 PC12 ------> SDMMC1_CK - PD2 ------> SDMMC1_CMD + PD2 ------> SDMMC1_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -722,15 +722,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -757,10 +757,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -784,8 +784,8 @@ static void HAL_FMC_MspInit(void){ FMC_Initialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_ENABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -825,8 +825,8 @@ static void HAL_FMC_MspInit(void){ PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 */ - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -841,7 +841,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 |GPIO_PIN_8|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -849,8 +849,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -865,7 +865,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -900,8 +900,8 @@ static void HAL_FMC_MspDeInit(void){ FMC_DeInitialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_DISABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -941,22 +941,22 @@ static void HAL_FMC_MspDeInit(void){ PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 */ - HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 |GPIO_PIN_8|GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1); HAL_GPIO_DeInit(GPIOH, GPIO_PIN_6|GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1); /* USER CODE BEGIN FMC_MspDeInit 1 */ diff --git a/bsp/stm32/stm32f767-st-nucleo/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c b/bsp/stm32/stm32f767-st-nucleo/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c index 770d50f63e..7306fcf76f 100644 --- a/bsp/stm32/stm32f767-st-nucleo/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c +++ b/bsp/stm32/stm32f767-st-nucleo/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32f7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -114,12 +114,12 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ETH_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); - /**ETH GPIO Configuration + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -128,7 +128,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PB13 ------> ETH_TXD1 PG11 ------> ETH_TX_EN - PG13 ------> ETH_TXD0 + PG13 ------> ETH_TXD0 */ GPIO_InitStruct.Pin = RMII_MDC_Pin|RMII_RXD0_Pin|RMII_RXD1_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -182,8 +182,8 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ETH_CLK_DISABLE(); - - /**ETH GPIO Configuration + + /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO @@ -192,7 +192,7 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) PC5 ------> ETH_RXD1 PB13 ------> ETH_TXD1 PG11 ------> ETH_TX_EN - PG13 ------> ETH_TXD0 + PG13 ------> ETH_TXD0 */ HAL_GPIO_DeInit(GPIOC, RMII_MDC_Pin|RMII_RXD0_Pin|RMII_RXD1_Pin); @@ -226,15 +226,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PD8 ------> USART3_TX - PD9 ------> USART3_RX + PD9 ------> USART3_RX */ GPIO_InitStruct.Pin = STLK_RX_Pin|STLK_TX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); @@ -263,10 +263,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PD8 ------> USART3_TX - PD9 ------> USART3_RX + PD9 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOD, STLK_RX_Pin|STLK_TX_Pin); @@ -292,14 +292,14 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ /* USER CODE END USB_OTG_FS_MspInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB_OTG_FS GPIO Configuration + /**USB_OTG_FS GPIO Configuration PA8 ------> USB_OTG_FS_SOF PA9 ------> USB_OTG_FS_VBUS PA10 ------> USB_OTG_FS_ID PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ GPIO_InitStruct.Pin = USB_SOF_Pin|USB_ID_Pin|USB_DM_Pin|USB_DP_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -339,15 +339,15 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) /* USER CODE END USB_OTG_FS_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); - - /**USB_OTG_FS GPIO Configuration + + /**USB_OTG_FS GPIO Configuration PA8 ------> USB_OTG_FS_SOF PA9 ------> USB_OTG_FS_VBUS PA10 ------> USB_OTG_FS_ID PA11 ------> USB_OTG_FS_DM - PA12 ------> USB_OTG_FS_DP + PA12 ------> USB_OTG_FS_DP */ - HAL_GPIO_DeInit(GPIOA, USB_SOF_Pin|USB_VBUS_Pin|USB_ID_Pin|USB_DM_Pin + HAL_GPIO_DeInit(GPIOA, USB_SOF_Pin|USB_VBUS_Pin|USB_ID_Pin|USB_DM_Pin |USB_DP_Pin); /* USER CODE BEGIN USB_OTG_FS_MspDeInit 1 */ diff --git a/bsp/stm32/stm32f769-st-disco/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32f769-st-disco/board/CubeMX_Config/CubeMX_Config.ioc index 73e883d6c0..f4bc362e25 100644 --- a/bsp/stm32/stm32f769-st-disco/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32f769-st-disco/board/CubeMX_Config/CubeMX_Config.ioc @@ -60,7 +60,12 @@ NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false PA1.Mode=MII PA1.Signal=ETH_RX_CLK -PA10.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13.Mode=Serial_Wire @@ -71,9 +76,6 @@ PA2.Mode=MII PA2.Signal=ETH_MDIO PA7.Mode=MII PA7.Signal=ETH_RX_DV -PA9.Locked=true -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PC1.Mode=MII PC1.Signal=ETH_MDC PC12.Locked=true diff --git a/bsp/stm32/stm32f769-st-disco/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c b/bsp/stm32/stm32f769-st-disco/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c index 99a22fec0f..4f8f77a12b 100644 --- a/bsp/stm32/stm32f769-st-disco/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c +++ b/bsp/stm32/stm32f769-st-disco/board/CubeMX_Config/Src/stm32f7xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32f7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -93,13 +93,13 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ETH_CLK_ENABLE(); - + __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); - /**ETH GPIO Configuration + /**ETH GPIO Configuration PE2 ------> ETH_TXD3 PG14 ------> ETH_TXD1 PG13 ------> ETH_TXD0 @@ -115,7 +115,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) PA2 ------> ETH_MDIO PC5 ------> ETH_RXD1 PH6 ------> ETH_RXD2 - PA7 ------> ETH_RX_DV + PA7 ------> ETH_RX_DV */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -138,7 +138,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 + GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 |GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -175,8 +175,8 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) /* USER CODE END ETH_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ETH_CLK_DISABLE(); - - /**ETH GPIO Configuration + + /**ETH GPIO Configuration PE2 ------> ETH_TXD3 PG14 ------> ETH_TXD1 PG13 ------> ETH_TXD0 @@ -192,7 +192,7 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) PA2 ------> ETH_MDIO PC5 ------> ETH_RXD1 PH6 ------> ETH_RXD2 - PA7 ------> ETH_RX_DV + PA7 ------> ETH_RX_DV */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_2); @@ -200,7 +200,7 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) HAL_GPIO_DeInit(GPIOH, GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_7|GPIO_PIN_6); - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_3|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_3|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 |GPIO_PIN_5); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7); @@ -228,23 +228,23 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END UART5_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_UART5_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**UART5 GPIO Configuration + /**UART5 GPIO Configuration PC12 ------> UART5_TX - PD2 ------> UART5_RX + PD2 ------> UART5_RX */ GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF8_UART5; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF8_UART5; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); @@ -260,15 +260,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA10 ------> USART1_RX - PA9 ------> USART1_TX + PA9 ------> USART1_TX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -295,10 +295,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END UART5_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART5_CLK_DISABLE(); - - /**UART5 GPIO Configuration + + /**UART5 GPIO Configuration PC12 ------> UART5_TX - PD2 ------> UART5_RX + PD2 ------> UART5_RX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12); @@ -315,10 +315,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA10 ------> USART1_RX - PA9 ------> USART1_TX + PA9 ------> USART1_TX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_10|GPIO_PIN_9); diff --git a/bsp/stm32/stm32g070-st-nucleo/board/CubeMX_Config/Src/stm32g0xx_hal_msp.c b/bsp/stm32/stm32g070-st-nucleo/board/CubeMX_Config/Src/stm32g0xx_hal_msp.c index 7c05429633..3c74feb4d2 100644 --- a/bsp/stm32/stm32g070-st-nucleo/board/CubeMX_Config/Src/stm32g0xx_hal_msp.c +++ b/bsp/stm32/stm32g070-st-nucleo/board/CubeMX_Config/Src/stm32g0xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32g0xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -58,7 +58,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -95,10 +95,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PA0 ------> ADC1_IN0 + /**ADC1 GPIO Configuration + PA0 ------> ADC1_IN0 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -127,9 +127,9 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC_CLK_DISABLE(); - - /**ADC1 GPIO Configuration - PA0 ------> ADC1_IN0 + + /**ADC1 GPIO Configuration + PA0 ------> ADC1_IN0 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0); @@ -202,12 +202,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA1 ------> SPI1_SCK PA11 [PA9] ------> SPI1_MISO - PA12 [PA10] ------> SPI1_MOSI + PA12 [PA10] ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -227,13 +227,13 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PC2 ------> SPI2_MISO PC3 ------> SPI2_MOSI - PB10 ------> SPI2_SCK + PB10 ------> SPI2_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -271,11 +271,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA1 ------> SPI1_SCK PA11 [PA9] ------> SPI1_MISO - PA12 [PA10] ------> SPI1_MOSI + PA12 [PA10] ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12); @@ -290,11 +290,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PC2 ------> SPI2_MISO PC3 ------> SPI2_MOSI - PB10 ------> SPI2_SCK + PB10 ------> SPI2_SCK */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_2|GPIO_PIN_3); @@ -348,14 +348,14 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM3_MspPostInit 0 */ /* USER CODE END TIM3_MspPostInit 0 */ - + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**TIM3 GPIO Configuration + /**TIM3 GPIO Configuration PA6 ------> TIM3_CH1 PA7 ------> TIM3_CH2 PB0 ------> TIM3_CH3 - PB1 ------> TIM3_CH4 + PB1 ------> TIM3_CH4 */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -426,15 +426,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PC4 ------> USART1_TX - PC5 ------> USART1_RX + PC5 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF1_USART1; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); @@ -450,11 +450,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -474,23 +474,23 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PC11 ------> USART3_RX - PB2 ------> USART3_TX + PB2 ------> USART3_TX */ GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_USART3; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF4_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); @@ -517,10 +517,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PC4 ------> USART1_TX - PC5 ------> USART1_RX + PC5 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_4|GPIO_PIN_5); @@ -535,10 +535,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); @@ -553,10 +553,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PC11 ------> USART3_RX - PB2 ------> USART3_TX + PB2 ------> USART3_TX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_11); diff --git a/bsp/stm32/stm32g071-st-nucleo/board/CubeMX_Config/Src/stm32g0xx_hal_msp.c b/bsp/stm32/stm32g071-st-nucleo/board/CubeMX_Config/Src/stm32g0xx_hal_msp.c index 3cfed698d3..5dc12fb616 100644 --- a/bsp/stm32/stm32g071-st-nucleo/board/CubeMX_Config/Src/stm32g0xx_hal_msp.c +++ b/bsp/stm32/stm32g071-st-nucleo/board/CubeMX_Config/Src/stm32g0xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32g0xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -78,7 +78,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -116,11 +116,11 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**ADC1 GPIO Configuration + /**ADC1 GPIO Configuration PA0 ------> ADC1_IN0 - PA1 ------> ADC1_IN1 + PA1 ------> ADC1_IN1 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -151,10 +151,10 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC_CLK_DISABLE(); - - /**ADC1 GPIO Configuration + + /**ADC1 GPIO Configuration PA0 ------> ADC1_IN0 - PA1 ------> ADC1_IN1 + PA1 ------> ADC1_IN1 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1); @@ -182,11 +182,11 @@ void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac) /* USER CODE END DAC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_DAC1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**DAC1 GPIO Configuration + /**DAC1 GPIO Configuration PA4 ------> DAC1_OUT1 - PA5 ------> DAC1_OUT2 + PA5 ------> DAC1_OUT2 */ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -217,10 +217,10 @@ void HAL_DAC_MspDeInit(DAC_HandleTypeDef* hdac) /* USER CODE END DAC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_DAC1_CLK_DISABLE(); - - /**DAC1 GPIO Configuration + + /**DAC1 GPIO Configuration PA4 ------> DAC1_OUT1 - PA5 ------> DAC1_OUT2 + PA5 ------> DAC1_OUT2 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4|GPIO_PIN_5); @@ -248,15 +248,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END LPUART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LPUART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**LPUART1 GPIO Configuration + /**LPUART1 GPIO Configuration PA2 ------> LPUART1_TX - PA3 ------> LPUART1_RX + PA3 ------> LPUART1_RX */ GPIO_InitStruct.Pin = LPUART1_TX_Pin|LPUART1_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF6_LPUART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -275,11 +275,11 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PC4 ------> USART1_TX - PC5 ------> USART1_RX + PC5 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -299,12 +299,12 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA15 ------> USART2_RX - PD5 ------> USART2_TX + PD5 ------> USART2_TX */ GPIO_InitStruct.Pin = GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -331,12 +331,12 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PC11 ------> USART3_RX - PB2 ------> USART3_TX + PB2 ------> USART3_TX */ GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -379,10 +379,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END LPUART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LPUART1_CLK_DISABLE(); - - /**LPUART1 GPIO Configuration + + /**LPUART1 GPIO Configuration PA2 ------> LPUART1_TX - PA3 ------> LPUART1_RX + PA3 ------> LPUART1_RX */ HAL_GPIO_DeInit(GPIOA, LPUART1_TX_Pin|LPUART1_RX_Pin); @@ -406,10 +406,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PC4 ------> USART1_TX - PC5 ------> USART1_RX + PC5 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_4|GPIO_PIN_5); @@ -424,10 +424,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA15 ------> USART2_RX - PD5 ------> USART2_TX + PD5 ------> USART2_TX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_15); @@ -444,10 +444,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PC11 ------> USART3_RX - PB2 ------> USART3_TX + PB2 ------> USART3_TX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_11); @@ -486,13 +486,13 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SPI1 GPIO Configuration + /**SPI1 GPIO Configuration PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI - PD8 ------> SPI1_SCK + PD8 ------> SPI1_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -519,13 +519,13 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PC2 ------> SPI2_MISO PC3 ------> SPI2_MOSI - PB13 ------> SPI2_SCK + PB13 ------> SPI2_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -565,11 +565,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); - - /**SPI1 GPIO Configuration + + /**SPI1 GPIO Configuration PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI - PD8 ------> SPI1_SCK + PD8 ------> SPI1_SCK */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_6|GPIO_PIN_7); @@ -586,11 +586,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PC2 ------> SPI2_MISO PC3 ------> SPI2_MOSI - PB13 ------> SPI2_SCK + PB13 ------> SPI2_SCK */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_2|GPIO_PIN_3); @@ -646,14 +646,14 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM3_MspPostInit 0 */ /* USER CODE END TIM3_MspPostInit 0 */ - + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); - /**TIM3 GPIO Configuration + /**TIM3 GPIO Configuration PB0 ------> TIM3_CH3 PB1 ------> TIM3_CH4 PC6 ------> TIM3_CH1 - PC7 ------> TIM3_CH2 + PC7 ------> TIM3_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; diff --git a/bsp/stm32/stm32g431-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32g431-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index 420cba6a01..854757a8f5 100644 --- a/bsp/stm32/stm32g431-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32g431-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -57,18 +57,24 @@ PA14.GPIO_Label=T_SWCLK PA14.Locked=true PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA2.Locked=true +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous -PA2.Signal=LPUART1_TX -PA3.Locked=true +PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous -PA3.Signal=LPUART1_RX +PA3.Signal=USART2_RX PA5.GPIOParameters=GPIO_Label PA5.GPIO_Label=LD2 [green] PA5.Locked=true PA5.Signal=GPIO_Output +PB10.GPIOParameters=GPIO_PuPd +PB10.GPIO_PuPd=GPIO_PULLUP PB10.Mode=Asynchronous PB10.Signal=USART3_TX +PB11.GPIOParameters=GPIO_PuPd +PB11.GPIO_PuPd=GPIO_PULLUP PB11.Mode=Asynchronous PB11.Signal=USART3_RX PB3.GPIOParameters=GPIO_Label diff --git a/bsp/stm32/stm32g431-st-nucleo/board/CubeMX_Config/Src/stm32g4xx_hal_msp.c b/bsp/stm32/stm32g431-st-nucleo/board/CubeMX_Config/Src/stm32g4xx_hal_msp.c index 759ac0f62c..51088806a3 100644 --- a/bsp/stm32/stm32g431-st-nucleo/board/CubeMX_Config/Src/stm32g4xx_hal_msp.c +++ b/bsp/stm32/stm32g431-st-nucleo/board/CubeMX_Config/Src/stm32g4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32g4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -72,7 +72,7 @@ void HAL_MspInit(void) /* System interrupt init*/ - /** Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral + /** Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral */ LL_PWR_DisableDeadBatteryPD(); @@ -97,15 +97,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END LPUART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LPUART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**LPUART1 GPIO Configuration + /**LPUART1 GPIO Configuration PA2 ------> LPUART1_TX - PA3 ------> LPUART1_RX + PA3 ------> LPUART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF12_LPUART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -121,15 +121,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_UART4_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**UART4 GPIO Configuration + /**UART4 GPIO Configuration PC10 ------> UART4_TX - PC11 ------> UART4_RX + PC11 ------> UART4_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF5_UART4; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); @@ -145,15 +145,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PC4 ------> USART1_TX - PC5 ------> USART1_RX + PC5 ------> USART1_RX */ GPIO_InitStruct.Pin = USART1_TX_Pin|USART1_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); @@ -169,15 +169,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); @@ -204,10 +204,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END LPUART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LPUART1_CLK_DISABLE(); - - /**LPUART1 GPIO Configuration + + /**LPUART1 GPIO Configuration PA2 ------> LPUART1_TX - PA3 ------> LPUART1_RX + PA3 ------> LPUART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); @@ -222,10 +222,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART4_CLK_DISABLE(); - - /**UART4 GPIO Configuration + + /**UART4 GPIO Configuration PC10 ------> UART4_TX - PC11 ------> UART4_RX + PC11 ------> UART4_RX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11); @@ -240,10 +240,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PC4 ------> USART1_TX - PC5 ------> USART1_RX + PC5 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOC, USART1_TX_Pin|USART1_RX_Pin); @@ -258,10 +258,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PB10 ------> USART3_TX - PB11 ------> USART3_RX + PB11 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); diff --git a/bsp/stm32/stm32h743-atk-apollo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32h743-atk-apollo/board/CubeMX_Config/CubeMX_Config.ioc index fd2d5efe67..7ef3f3f109 100644 --- a/bsp/stm32/stm32h743-atk-apollo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32h743-atk-apollo/board/CubeMX_Config/CubeMX_Config.ioc @@ -161,23 +161,29 @@ NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true\:true NVIC.USART2_IRQn=true\:0\:0\:false\:false\:true\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false -PA10.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA13\ (JTMS/SWDIO).Mode=Serial_Wire PA13\ (JTMS/SWDIO).Signal=DEBUG_JTMS-SWDIO PA14\ (JTCK/SWCLK).Mode=Serial_Wire PA14\ (JTCK/SWCLK).Signal=DEBUG_JTCK-SWCLK +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX PA4.Signal=COMP_DAC11_group PA5.Locked=true PA5.Signal=ADCx_INP19 -PA9.Locked=true -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PB13.GPIOParameters=GPIO_Speed PB13.GPIO_Speed=GPIO_SPEED_FREQ_HIGH PB13.Locked=true diff --git a/bsp/stm32/stm32h743-atk-apollo/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c b/bsp/stm32/stm32h743-atk-apollo/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c index 42d6806ff0..fef02fcddd 100644 --- a/bsp/stm32/stm32h743-atk-apollo/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c +++ b/bsp/stm32/stm32h743-atk-apollo/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c @@ -2,12 +2,12 @@ /** ****************************************************************************** * File Name : stm32h7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -52,7 +52,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -278,12 +278,12 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_LTDC_CLK_ENABLE(); - + __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); - /**LTDC GPIO Configuration + /**LTDC GPIO Configuration PI9 ------> LTDC_VSYNC PI10 ------> LTDC_HSYNC PF10 ------> LTDC_DE @@ -303,10 +303,10 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) PI4 ------> LTDC_B4 PI5 ------> LTDC_B5 PI6 ------> LTDC_B6 - PI7 ------> LTDC_B7 + PI7 ------> LTDC_B7 */ - GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 - |GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6 + GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 + |GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6 |GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -321,7 +321,7 @@ void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) GPIO_InitStruct.Alternate = GPIO_AF14_LTDC; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 + GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -358,8 +358,8 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) /* USER CODE END LTDC_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_LTDC_CLK_DISABLE(); - - /**LTDC GPIO Configuration + + /**LTDC GPIO Configuration PI9 ------> LTDC_VSYNC PI10 ------> LTDC_HSYNC PF10 ------> LTDC_DE @@ -379,15 +379,15 @@ void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) PI4 ------> LTDC_B4 PI5 ------> LTDC_B5 PI6 ------> LTDC_B6 - PI7 ------> LTDC_B7 + PI7 ------> LTDC_B7 */ - HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 - |GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6 + HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 + |GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6 |GPIO_PIN_7); HAL_GPIO_DeInit(GPIOF, GPIO_PIN_10); - HAL_GPIO_DeInit(GPIOH, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 + HAL_GPIO_DeInit(GPIOH, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); HAL_GPIO_DeInit(GPIOG, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_11); @@ -415,16 +415,16 @@ void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_QSPI_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**QUADSPI GPIO Configuration + /**QUADSPI GPIO Configuration PF6 ------> QUADSPI_BK1_IO3 PF7 ------> QUADSPI_BK1_IO2 PF8 ------> QUADSPI_BK1_IO0 PF9 ------> QUADSPI_BK1_IO1 PB2 ------> QUADSPI_CLK - PB6 ------> QUADSPI_BK1_NCS + PB6 ------> QUADSPI_BK1_NCS */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -476,14 +476,14 @@ void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_QSPI_CLK_DISABLE(); - - /**QUADSPI GPIO Configuration + + /**QUADSPI GPIO Configuration PF6 ------> QUADSPI_BK1_IO3 PF7 ------> QUADSPI_BK1_IO2 PF8 ------> QUADSPI_BK1_IO0 PF9 ------> QUADSPI_BK1_IO1 PB2 ------> QUADSPI_CLK - PB6 ------> QUADSPI_BK1_NCS + PB6 ------> QUADSPI_BK1_NCS */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9); @@ -512,10 +512,10 @@ void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc) /* USER CODE END RTC_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_RTC_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); - /**RTC GPIO Configuration - PC13 ------> RTC_OUT_CALIB + /**RTC GPIO Configuration + PC13 ------> RTC_OUT_CALIB */ HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); @@ -541,9 +541,9 @@ void HAL_RTC_MspDeInit(RTC_HandleTypeDef* hrtc) /* USER CODE END RTC_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_RTC_DISABLE(); - - /**RTC GPIO Configuration - PC13 ------> RTC_OUT_CALIB + + /**RTC GPIO Configuration + PC13 ------> RTC_OUT_CALIB */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_13); @@ -570,18 +570,18 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDMMC1_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDMMC1 GPIO Configuration + /**SDMMC1 GPIO Configuration PC8 ------> SDMMC1_D0 PC9 ------> SDMMC1_D1 PC10 ------> SDMMC1_D2 PC11 ------> SDMMC1_D3 PC12 ------> SDMMC1_CK - PD2 ------> SDMMC1_CMD + PD2 ------> SDMMC1_CMD */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -621,16 +621,16 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* hsd) /* USER CODE END SDMMC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDMMC1_CLK_DISABLE(); - - /**SDMMC1 GPIO Configuration + + /**SDMMC1 GPIO Configuration PC8 ------> SDMMC1_D0 PC9 ------> SDMMC1_D1 PC10 ------> SDMMC1_D2 PC11 ------> SDMMC1_D3 PC12 ------> SDMMC1_CK - PD2 ------> SDMMC1_CMD + PD2 ------> SDMMC1_CMD */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -660,12 +660,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -696,11 +696,11 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO - PB15 ------> SPI2_MOSI + PB15 ------> SPI2_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); @@ -727,15 +727,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -754,15 +754,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -792,10 +792,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); @@ -812,10 +812,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); @@ -842,8 +842,8 @@ static void HAL_FMC_MspInit(void){ /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_ENABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -884,8 +884,8 @@ static void HAL_FMC_MspInit(void){ PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 */ - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -900,7 +900,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 |GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -908,8 +908,8 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -917,7 +917,7 @@ static void HAL_FMC_MspInit(void){ GPIO_InitStruct.Alternate = GPIO_AF12_FMC; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -952,8 +952,8 @@ static void HAL_FMC_MspDeInit(void){ FMC_DeInitialized = 1; /* Peripheral clock enable */ __HAL_RCC_FMC_CLK_DISABLE(); - - /** FMC GPIO Configuration + + /** FMC GPIO Configuration PF0 ------> FMC_A0 PF1 ------> FMC_A1 PF2 ------> FMC_A2 @@ -994,20 +994,20 @@ static void HAL_FMC_MspDeInit(void){ PE0 ------> FMC_NBL0 PE1 ------> FMC_NBL1 */ - HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 |GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_15); - HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1); - HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1); /* USER CODE BEGIN FMC_MspDeInit 1 */ diff --git a/bsp/stm32/stm32h743-st-nucleo/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c b/bsp/stm32/stm32h743-st-nucleo/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c index 60881f1c22..099374e220 100644 --- a/bsp/stm32/stm32h743-st-nucleo/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c +++ b/bsp/stm32/stm32h743-st-nucleo/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32h7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -92,15 +92,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); - + __HAL_RCC_GPIOD_CLK_ENABLE(); - /**USART3 GPIO Configuration + /**USART3 GPIO Configuration PD8 ------> USART3_TX - PD9 ------> USART3_RX + PD9 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); @@ -127,10 +127,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); - - /**USART3 GPIO Configuration + + /**USART3 GPIO Configuration PD8 ------> USART3_TX - PD9 ------> USART3_RX + PD9 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9); diff --git a/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CM4/Src/stm32h7xx_hal_msp.c b/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CM4/Src/stm32h7xx_hal_msp.c index 858912e780..c291e0ff67 100644 --- a/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CM4/Src/stm32h7xx_hal_msp.c +++ b/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CM4/Src/stm32h7xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32h7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ diff --git a/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CM7/Src/stm32h7xx_hal_msp.c b/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CM7/Src/stm32h7xx_hal_msp.c index b2f1998e9b..02fb8a88f2 100644 --- a/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CM7/Src/stm32h7xx_hal_msp.c +++ b/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CM7/Src/stm32h7xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32h7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -92,15 +92,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA10 ------> USART1_RX - PA9 ------> USART1_TX + PA9 ------> USART1_TX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -127,10 +127,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA10 ------> USART1_RX - PA9 ------> USART1_TX + PA9 ------> USART1_TX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_10|GPIO_PIN_9); diff --git a/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CubeMX_Config.ioc index 7e5db8c6e6..83eefbe36d 100644 --- a/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32h747-st-discovery/board/CubeMX_Config/CubeMX_Config.ioc @@ -52,13 +52,15 @@ NVIC2.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC2.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC2.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC2.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false -PA10.GPIOParameters=PinAttribute +PA10.GPIOParameters=PinAttribute,GPIO_PuPd PA10.Locked=true +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.PinAttribute=CortexM7 PA10.Signal=USART1_RX -PA9.GPIOParameters=PinAttribute +PA9.GPIOParameters=PinAttribute,GPIO_PuPd PA9.Locked=true +PA9.GPIO_PuPd=GPIO_PULLUP PA9.Mode=Asynchronous PA9.PinAttribute=CortexM7 PA9.Signal=USART1_TX diff --git a/bsp/stm32/stm32h750-armfly-h7-tool/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32h750-armfly-h7-tool/board/CubeMX_Config/CubeMX_Config.ioc index d7da87788c..fd677d2731 100644 --- a/bsp/stm32/stm32h750-armfly-h7-tool/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32h750-armfly-h7-tool/board/CubeMX_Config/CubeMX_Config.ioc @@ -103,7 +103,12 @@ NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false PA1.Mode=RMII PA1.Signal=ETH_REF_CLK -PA10.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA2.Mode=RMII @@ -115,9 +120,6 @@ PA5.Mode=Device_HS PA5.Signal=USB_OTG_HS_ULPI_CK PA7.Mode=RMII PA7.Signal=ETH_CRS_DV -PA9.Locked=true -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX PB0.Mode=Device_HS PB0.Signal=USB_OTG_HS_ULPI_D1 PB1.Mode=Device_HS diff --git a/bsp/stm32/stm32h750-armfly-h7-tool/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c b/bsp/stm32/stm32h750-armfly-h7-tool/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c index 690d875704..726068cad2 100644 --- a/bsp/stm32/stm32h750-armfly-h7-tool/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c +++ b/bsp/stm32/stm32h750-armfly-h7-tool/board/CubeMX_Config/Src/stm32h7xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32h7xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -58,7 +58,7 @@ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ - + void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); /** * Initializes the Global MSP. @@ -94,11 +94,11 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC3_CLK_ENABLE(); - + __HAL_RCC_GPIOF_CLK_ENABLE(); - /**ADC3 GPIO Configuration + /**ADC3 GPIO Configuration PF3 ------> ADC3_INP5 - PF8 ------> ADC3_INP7 + PF8 ------> ADC3_INP7 */ GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -127,10 +127,10 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) /* USER CODE END ADC3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC3_CLK_DISABLE(); - - /**ADC3 GPIO Configuration + + /**ADC3 GPIO Configuration PF3 ------> ADC3_INP5 - PF8 ------> ADC3_INP7 + PF8 ------> ADC3_INP7 */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_3|GPIO_PIN_8); @@ -201,10 +201,10 @@ void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac) /* USER CODE END DAC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_DAC12_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**DAC1 GPIO Configuration - PA4 ------> DAC1_OUT1 + /**DAC1 GPIO Configuration + PA4 ------> DAC1_OUT1 */ GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; @@ -233,9 +233,9 @@ void HAL_DAC_MspDeInit(DAC_HandleTypeDef* hdac) /* USER CODE END DAC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_DAC12_CLK_DISABLE(); - - /**DAC1 GPIO Configuration - PA4 ------> DAC1_OUT1 + + /**DAC1 GPIO Configuration + PA4 ------> DAC1_OUT1 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4); @@ -264,11 +264,11 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) __HAL_RCC_ETH1MAC_CLK_ENABLE(); __HAL_RCC_ETH1TX_CLK_ENABLE(); __HAL_RCC_ETH1RX_CLK_ENABLE(); - + __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); - /**ETH GPIO Configuration + /**ETH GPIO Configuration PG14 ------> ETH_TXD1 PG13 ------> ETH_TXD0 PG11 ------> ETH_TX_EN @@ -277,7 +277,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) PC4 ------> ETH_RXD0 PA2 ------> ETH_MDIO PC5 ------> ETH_RXD1 - PA7 ------> ETH_CRS_DV + PA7 ------> ETH_CRS_DV */ GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_13|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -324,8 +324,8 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) __HAL_RCC_ETH1MAC_CLK_DISABLE(); __HAL_RCC_ETH1TX_CLK_DISABLE(); __HAL_RCC_ETH1RX_CLK_DISABLE(); - - /**ETH GPIO Configuration + + /**ETH GPIO Configuration PG14 ------> ETH_TXD1 PG13 ------> ETH_TXD0 PG11 ------> ETH_TX_EN @@ -334,7 +334,7 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth) PC4 ------> ETH_RXD0 PA2 ------> ETH_MDIO PC5 ------> ETH_RXD1 - PA7 ------> ETH_CRS_DV + PA7 ------> ETH_CRS_DV */ HAL_GPIO_DeInit(GPIOG, GPIO_PIN_14|GPIO_PIN_13|GPIO_PIN_11); @@ -365,18 +365,18 @@ void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_QSPI_CLK_ENABLE(); - + __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**QUADSPI GPIO Configuration + /**QUADSPI GPIO Configuration PG6 ------> QUADSPI_BK1_NCS PF7 ------> QUADSPI_BK1_IO2 PB2 ------> QUADSPI_CLK PD13 ------> QUADSPI_BK1_IO3 PD12 ------> QUADSPI_BK1_IO1 - PD11 ------> QUADSPI_BK1_IO0 + PD11 ------> QUADSPI_BK1_IO0 */ GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -428,14 +428,14 @@ void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* hqspi) /* USER CODE END QUADSPI_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_QSPI_CLK_DISABLE(); - - /**QUADSPI GPIO Configuration + + /**QUADSPI GPIO Configuration PG6 ------> QUADSPI_BK1_NCS PF7 ------> QUADSPI_BK1_IO2 PB2 ------> QUADSPI_CLK PD13 ------> QUADSPI_BK1_IO3 PD12 ------> QUADSPI_BK1_IO1 - PD11 ------> QUADSPI_BK1_IO0 + PD11 ------> QUADSPI_BK1_IO0 */ HAL_GPIO_DeInit(GPIOG, GPIO_PIN_6); @@ -512,11 +512,11 @@ void HAL_MMC_MspInit(MMC_HandleTypeDef* hmmc) /* USER CODE END SDMMC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SDMMC1_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); - /**SDMMC1 GPIO Configuration + /**SDMMC1 GPIO Configuration PB8 ------> SDMMC1_D4 PC12 ------> SDMMC1_CK PB9 ------> SDMMC1_D5 @@ -526,7 +526,7 @@ void HAL_MMC_MspInit(MMC_HandleTypeDef* hmmc) PC9 ------> SDMMC1_D1 PC8 ------> SDMMC1_D0 PC7 ------> SDMMC1_D7 - PC6 ------> SDMMC1_D6 + PC6 ------> SDMMC1_D6 */ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -535,7 +535,7 @@ void HAL_MMC_MspInit(MMC_HandleTypeDef* hmmc) GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 + GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 |GPIO_PIN_8|GPIO_PIN_7|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -572,8 +572,8 @@ void HAL_MMC_MspDeInit(MMC_HandleTypeDef* hmmc) /* USER CODE END SDMMC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SDMMC1_CLK_DISABLE(); - - /**SDMMC1 GPIO Configuration + + /**SDMMC1 GPIO Configuration PB8 ------> SDMMC1_D4 PC12 ------> SDMMC1_CK PB9 ------> SDMMC1_D5 @@ -583,11 +583,11 @@ void HAL_MMC_MspDeInit(MMC_HandleTypeDef* hmmc) PC9 ------> SDMMC1_D1 PC8 ------> SDMMC1_D0 PC7 ------> SDMMC1_D7 - PC6 ------> SDMMC1_D6 + PC6 ------> SDMMC1_D6 */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9); - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_9 |GPIO_PIN_8|GPIO_PIN_7|GPIO_PIN_6); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); @@ -615,10 +615,10 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) /* USER CODE END TIM12_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_TIM12_CLK_ENABLE(); - + __HAL_RCC_GPIOB_CLK_ENABLE(); - /**TIM12 GPIO Configuration - PB14 ------> TIM12_CH1 + /**TIM12 GPIO Configuration + PB14 ------> TIM12_CH1 */ GPIO_InitStruct.Pin = GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -642,10 +642,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) /* USER CODE BEGIN TIM12_MspPostInit 0 */ /* USER CODE END TIM12_MspPostInit 0 */ - + __HAL_RCC_GPIOH_CLK_ENABLE(); - /**TIM12 GPIO Configuration - PH9 ------> TIM12_CH2 + /**TIM12 GPIO Configuration + PH9 ------> TIM12_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -675,10 +675,10 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base) /* USER CODE END TIM12_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_TIM12_CLK_DISABLE(); - - /**TIM12 GPIO Configuration + + /**TIM12 GPIO Configuration PH9 ------> TIM12_CH2 - PB14 ------> TIM12_CH1 + PB14 ------> TIM12_CH1 */ HAL_GPIO_DeInit(GPIOH, GPIO_PIN_9); @@ -707,15 +707,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_UART4_CLK_ENABLE(); - + __HAL_RCC_GPIOH_CLK_ENABLE(); - /**UART4 GPIO Configuration + /**UART4 GPIO Configuration PH13 ------> UART4_TX - PH14 ------> UART4_RX + PH14 ------> UART4_RX */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF8_UART4; HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); @@ -731,15 +731,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA10 ------> USART1_RX - PA9 ------> USART1_TX + PA9 ------> USART1_TX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -766,10 +766,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END UART4_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART4_CLK_DISABLE(); - - /**UART4 GPIO Configuration + + /**UART4 GPIO Configuration PH13 ------> UART4_TX - PH14 ------> UART4_RX + PH14 ------> UART4_RX */ HAL_GPIO_DeInit(GPIOH, GPIO_PIN_13|GPIO_PIN_14); @@ -784,10 +784,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA10 ------> USART1_RX - PA9 ------> USART1_TX + PA9 ------> USART1_TX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_10|GPIO_PIN_9); @@ -812,13 +812,13 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) /* USER CODE BEGIN USB_OTG_HS_MspInit 0 */ /* USER CODE END USB_OTG_HS_MspInit 0 */ - + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB_OTG_HS GPIO Configuration + /**USB_OTG_HS GPIO Configuration PB5 ------> USB_OTG_HS_ULPI_D7 PI11 ------> USB_OTG_HS_ULPI_DIR PH4 ------> USB_OTG_HS_ULPI_NXT @@ -830,9 +830,9 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) PB1 ------> USB_OTG_HS_ULPI_D2 PB0 ------> USB_OTG_HS_ULPI_D1 PB10 ------> USB_OTG_HS_ULPI_D3 - PB11 ------> USB_OTG_HS_ULPI_D4 + PB11 ------> USB_OTG_HS_ULPI_D4 */ - GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_1 + GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_1 |GPIO_PIN_0|GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; @@ -894,8 +894,8 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) /* Peripheral clock disable */ __HAL_RCC_USB_OTG_HS_CLK_DISABLE(); __HAL_RCC_USB_OTG_HS_ULPI_CLK_DISABLE(); - - /**USB_OTG_HS GPIO Configuration + + /**USB_OTG_HS GPIO Configuration PB5 ------> USB_OTG_HS_ULPI_D7 PI11 ------> USB_OTG_HS_ULPI_DIR PH4 ------> USB_OTG_HS_ULPI_NXT @@ -907,9 +907,9 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) PB1 ------> USB_OTG_HS_ULPI_D2 PB0 ------> USB_OTG_HS_ULPI_D1 PB10 ------> USB_OTG_HS_ULPI_D3 - PB11 ------> USB_OTG_HS_ULPI_D4 + PB11 ------> USB_OTG_HS_ULPI_D4 */ - HAL_GPIO_DeInit(GPIOB, GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_1 + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_1 |GPIO_PIN_0|GPIO_PIN_10|GPIO_PIN_11); HAL_GPIO_DeInit(GPIOI, GPIO_PIN_11); diff --git a/bsp/stm32/stm32h750-artpi-h750/.config b/bsp/stm32/stm32h750-artpi-h750/.config index c31157512a..3125ac5607 100644 --- a/bsp/stm32/stm32h750-artpi-h750/.config +++ b/bsp/stm32/stm32h750-artpi-h750/.config @@ -21,6 +21,12 @@ CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 CONFIG_IDLE_THREAD_STACK_SIZE=256 # CONFIG_RT_USING_TIMER_SOFT is not set + +# +# 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 is not set # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -52,6 +58,7 @@ CONFIG_RT_USING_MEMPOOL=y # CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set CONFIG_RT_USING_HEAP=y @@ -64,7 +71,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=128 CONFIG_RT_CONSOLE_DEVICE_NAME="uart4" -CONFIG_RT_VER_NUM=0x40003 +CONFIG_RT_VER_NUM=0x40004 CONFIG_ARCH_ARM=y CONFIG_RT_USING_CPU_FFS=y CONFIG_ARCH_ARM_CORTEX_M=y @@ -115,6 +122,8 @@ 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_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set # CONFIG_RT_SERIAL_USING_DMA is not set CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set @@ -153,6 +162,7 @@ CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_LIBC is not set # CONFIG_RT_USING_PTHREADS is not set CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_FIXED_TIMEZONE=8 # # Network @@ -189,8 +199,14 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_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 # @@ -258,8 +274,6 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_LIBRWS is not set # CONFIG_PKG_USING_TCPSERVER is not set # CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set # CONFIG_PKG_USING_DLT645 is not set # CONFIG_PKG_USING_QXWZ is not set # CONFIG_PKG_USING_SMTP_CLIENT is not set @@ -271,6 +285,12 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 # # security packages @@ -296,6 +316,9 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_STEMWIN is not set # CONFIG_PKG_USING_WAVPLAYER is not set # CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set # # tools packages @@ -307,9 +330,12 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 @@ -317,6 +343,18 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 # # system packages @@ -335,6 +373,8 @@ CONFIG_RT_LIBC_USING_TIME=y # 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_THREAD_POOL is not set # CONFIG_PKG_USING_ROBOTS is not set # CONFIG_PKG_USING_EV is not set @@ -344,7 +384,25 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_RAMDISK is not set # CONFIG_PKG_USING_MININI is not set # CONFIG_PKG_USING_QBOOT is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# # CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_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_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# 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 +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set # # peripheral libraries and drivers @@ -353,6 +411,7 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 @@ -397,6 +456,28 @@ CONFIG_RT_LIBC_USING_TIME=y # 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_RDA58XX 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 # # miscellaneous packages @@ -406,6 +487,7 @@ CONFIG_RT_LIBC_USING_TIME=y # 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 @@ -426,16 +508,72 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set # CONFIG_PKG_USING_VI is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set # CONFIG_PKG_USING_VT100 is not set -# CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set + +# +# games: games run on RT-Thread console +# # 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_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 + +# +# Privated Packages of RealThread +# +# CONFIG_PKG_USING_CODEC is not set +# CONFIG_PKG_USING_PLAYER is not set +# CONFIG_PKG_USING_MPLAYER is not set +# CONFIG_PKG_USING_PERSIMMON_SRC is not set +# CONFIG_PKG_USING_JS_PERSIMMON is not set +# CONFIG_PKG_USING_JERRYSCRIPT_WIN32 is not set + +# +# Network Utilities +# +# CONFIG_PKG_USING_WICED is not set +# CONFIG_PKG_USING_CLOUDSDK is not set +# CONFIG_PKG_USING_POWER_MANAGER is not set +# CONFIG_PKG_USING_RT_OTA is not set +# CONFIG_PKG_USING_RTINSIGHT is not set +# CONFIG_PKG_USING_SMARTCONFIG is not set +# CONFIG_PKG_USING_RTX is not set +# CONFIG_RT_USING_TESTCASE is not set +# CONFIG_PKG_USING_NGHTTP2 is not set +# CONFIG_PKG_USING_AVS is not set +# CONFIG_PKG_USING_ALI_LINKKIT is not set +# CONFIG_PKG_USING_STS is not set +# CONFIG_PKG_USING_DLMS is not set +# CONFIG_PKG_USING_AUDIO_FRAMEWORK is not set +# CONFIG_PKG_USING_ZBAR is not set +# CONFIG_PKG_USING_MCF is not set +# CONFIG_PKG_USING_URPC is not set +# CONFIG_PKG_USING_DCM is not set +# CONFIG_PKG_USING_EMQ is not set +# CONFIG_PKG_USING_CFGM is not set +# CONFIG_PKG_USING_RT_CMSIS_DAP is not set +# CONFIG_PKG_USING_SMODULE is not set +# CONFIG_PKG_USING_SNFD is not set +# CONFIG_PKG_USING_UDBD is not set +# CONFIG_PKG_USING_BENCHMARK is not set +# CONFIG_PKG_USING_UBJSON is not set +# CONFIG_PKG_USING_DATATYPE is not set +# CONFIG_PKG_USING_FASTFS is not set +# CONFIG_PKG_USING_RIL is not set +# CONFIG_PKG_USING_WATCH_DCM_SVC is not set +# CONFIG_PKG_USING_WATCH_APP_FWK is not set +# CONFIG_PKG_USING_GUI_TEST is not set +# CONFIG_PKG_USING_PMEM is not set +# CONFIG_PKG_USING_LWRDP is not set +# CONFIG_PKG_USING_MASAN is not set CONFIG_SOC_FAMILY_STM32=y CONFIG_SOC_SERIES_STM32H7=y diff --git a/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/Core/Inc/main.h b/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/Core/Inc/main.h index 4677beb2d9..b6b51e650c 100644 --- a/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/Core/Inc/main.h +++ b/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/Core/Inc/main.h @@ -51,7 +51,7 @@ extern "C" { /* USER CODE END EM */ /* Exported functions prototypes ---------------------------------------------*/ -void Error_Handler(void); + /* USER CODE BEGIN EFP */ diff --git a/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/Core/Src/stm32h7xx_hal_msp.c b/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/Core/Src/stm32h7xx_hal_msp.c index 77a19bb14b..cf63245b6f 100644 --- a/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/Core/Src/stm32h7xx_hal_msp.c +++ b/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/Core/Src/stm32h7xx_hal_msp.c @@ -101,14 +101,14 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF8_UART4; HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF8_UART4; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -153,7 +153,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USART3 interrupt Init */ HAL_NVIC_SetPriority(USART3_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART3_IRQn); - + NVIC_EnableIRQ(USART3_IRQn); /* USER CODE BEGIN USART3_MspInit 1 */ diff --git a/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/CubeMX_Config.ioc index a71fd18402..0c04bf4b43 100644 --- a/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32h750-artpi-h750/board/CubeMX_Config/CubeMX_Config.ioc @@ -27,8 +27,8 @@ Mcu.PinsNb=11 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32H750XBHx -MxCube.Version=6.0.1 -MxDb.Version=DB.6.0.0 +MxCube.Version=6.2.1 +MxDb.Version=DB.6.0.21 NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.ForceEnableDMAVector=true @@ -42,13 +42,17 @@ NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UART4_IRQn=true\:0\:0\:false\:false\:true\:true\:true NVIC.USART3_IRQn=true\:0\:0\:false\:false\:true\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +PA0.GPIOParameters=GPIO_PuPd +PA0.GPIO_PuPd=GPIO_PULLUP PA0.Locked=true PA0.Mode=Asynchronous PA0.Signal=UART4_TX -PB10.Locked=true +PB10.GPIOParameters=GPIO_PuPd +PB10.GPIO_PuPd=GPIO_PULLUP PB10.Mode=Asynchronous PB10.Signal=USART3_TX -PB11.Locked=true +PB11.GPIOParameters=GPIO_PuPd +PB11.GPIO_PuPd=GPIO_PULLUP PB11.Mode=Asynchronous PB11.Signal=USART3_RX PD11.Mode=CTS_RTS @@ -63,6 +67,8 @@ PI11.Locked=true PI11.Signal=GPIO_Output PI8.Locked=true PI8.Signal=GPIO_Output +PI9.GPIOParameters=GPIO_PuPd +PI9.GPIO_PuPd=GPIO_PULLUP PI9.Locked=true PI9.Mode=Asynchronous PI9.Signal=UART4_RX @@ -77,7 +83,7 @@ ProjectManager.CustomerFirmwarePackage= ProjectManager.DefaultFWLocation=true ProjectManager.DeletePrevious=true ProjectManager.DeviceId=STM32H750XBHx -ProjectManager.FirmwarePackage=STM32Cube FW_H7 V1.8.0 +ProjectManager.FirmwarePackage=STM32Cube FW_H7 V1.9.0 ProjectManager.FreePins=false ProjectManager.HalAssertFull=false ProjectManager.HeapSize=0x200 diff --git a/bsp/stm32/stm32h750-artpi-h750/rtconfig.h b/bsp/stm32/stm32h750-artpi-h750/rtconfig.h index 8d75171203..f6bda0feda 100644 --- a/bsp/stm32/stm32h750-artpi-h750/rtconfig.h +++ b/bsp/stm32/stm32h750-artpi-h750/rtconfig.h @@ -16,6 +16,9 @@ #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 #define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + #define RT_DEBUG /* Inter-Thread communication */ @@ -38,7 +41,7 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart4" -#define RT_VER_NUM 0x40003 +#define RT_VER_NUM 0x40004 #define ARCH_ARM #define RT_USING_CPU_FFS #define ARCH_ARM_CORTEX_M @@ -78,6 +81,7 @@ #define RT_USING_DEVICE_IPC #define RT_PIPE_BUFSZ 512 #define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 #define RT_SERIAL_RB_BUFSZ 64 #define RT_USING_PIN @@ -87,6 +91,7 @@ /* POSIX layer and C standard library */ #define RT_LIBC_USING_TIME +#define RT_LIBC_FIXED_TIMEZONE 8 /* Network */ @@ -108,6 +113,9 @@ /* Utilities */ +/* RT-Thread Utestcases */ + + /* RT-Thread online packages */ /* IoT - internet of things */ @@ -139,14 +147,29 @@ /* system packages */ +/* Micrium: Micrium software products porting for RT-Thread */ + + /* peripheral libraries and drivers */ +/* AI packages */ + + /* miscellaneous packages */ /* samples: kernel and components samples */ + +/* games: games run on RT-Thread console */ + + +/* Privated Packages of RealThread */ + + +/* Network Utilities */ + #define SOC_FAMILY_STM32 #define SOC_SERIES_STM32H7 diff --git a/bsp/stm32/stm32l010-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32l010-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index fd1de238ea..1305e437aa 100644 --- a/bsp/stm32/stm32l010-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32l010-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -27,8 +27,12 @@ NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SVC_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true +PA2.GPIOParameters=GPIO_PuPd +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Mode=Asynchronous PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_PuPd +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Mode=Asynchronous PA3.Signal=USART2_RX PC14-OSC32_IN.Mode=LSE-External-Oscillator diff --git a/bsp/stm32/stm32l010-st-nucleo/board/CubeMX_Config/Src/stm32l0xx_hal_msp.c b/bsp/stm32/stm32l010-st-nucleo/board/CubeMX_Config/Src/stm32l0xx_hal_msp.c index 3570c90a39..8d69a8a2f7 100644 --- a/bsp/stm32/stm32l010-st-nucleo/board/CubeMX_Config/Src/stm32l0xx_hal_msp.c +++ b/bsp/stm32/stm32l010-st-nucleo/board/CubeMX_Config/Src/stm32l0xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32l0xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -93,15 +93,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -128,10 +128,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); diff --git a/bsp/stm32/stm32l053-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32l053-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index 73cbefbcd2..e31f64da5b 100644 --- a/bsp/stm32/stm32l053-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32l053-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -24,14 +24,15 @@ Mcu.PinsNb=11 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32L053R8Tx -MxCube.Version=4.27.0 -MxDb.Version=DB.4.0.270 -NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.SVC_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.SysTick_IRQn=true\:0\:0\:true\:false\:true\:true -NVIC.USART2_IRQn=true\:0\:0\:false\:false\:true\:true +MxCube.Version=6.2.1 +MxDb.Version=DB.6.0.21 +NVIC.ForceEnableDMAVector=true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.SVC_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.SysTick_IRQn=true\:0\:0\:true\:false\:true\:true\:true +NVIC.USART2_IRQn=true\:0\:0\:false\:false\:true\:true\:true PA13.GPIOParameters=GPIO_Label PA13.GPIO_Label=TMS PA13.Locked=true @@ -42,13 +43,15 @@ PA14.GPIO_Label=TCK PA14.Locked=true PA14.Mode=Serial_Wire PA14.Signal=SYS_SWCLK -PA2.GPIOParameters=GPIO_Label +PA2.GPIOParameters=GPIO_PuPd,GPIO_Label PA2.GPIO_Label=USART_TX +PA2.GPIO_PuPd=GPIO_PULLUP PA2.Locked=true PA2.Mode=Asynchronous PA2.Signal=USART2_TX -PA3.GPIOParameters=GPIO_Label +PA3.GPIOParameters=GPIO_PuPd,GPIO_Label PA3.GPIO_Label=USART_RX +PA3.GPIO_PuPd=GPIO_PULLUP PA3.Locked=true PA3.Mode=Asynchronous PA3.Signal=USART2_RX @@ -67,14 +70,6 @@ PC14-OSC32_IN.Signal=RCC_OSC32_IN PC15-OSC32_OUT.Locked=true PC15-OSC32_OUT.Mode=LSE-External-Oscillator PC15-OSC32_OUT.Signal=RCC_OSC32_OUT -PCC.Checker=true -PCC.Line=STM32L0x3 -PCC.MCU=STM32L053R(6-8)Tx -PCC.PartNumber=STM32L053R8Tx -PCC.Seq0=0 -PCC.Series=STM32L0 -PCC.Temperature=25 -PCC.Vdd=null PH0-OSC_IN.Locked=true PH0-OSC_IN.Mode=HSE-External-Oscillator PH0-OSC_IN.Signal=RCC_OSC_IN @@ -91,7 +86,7 @@ ProjectManager.CustomerFirmwarePackage= ProjectManager.DefaultFWLocation=true ProjectManager.DeletePrevious=true ProjectManager.DeviceId=STM32L053R8Tx -ProjectManager.FirmwarePackage=STM32Cube FW_L0 V1.10.0 +ProjectManager.FirmwarePackage=STM32Cube FW_L0 V1.12.0 ProjectManager.FreePins=false ProjectManager.HalAssertFull=false ProjectManager.HeapSize=0x200 @@ -104,6 +99,7 @@ ProjectManager.PreviousToolchain= ProjectManager.ProjectBuild=false ProjectManager.ProjectFileName=CubeMX_Config.ioc ProjectManager.ProjectName=CubeMX_Config +ProjectManager.RegisterCallBack= ProjectManager.StackSize=0x400 ProjectManager.TargetToolchain=MDK-ARM V5 ProjectManager.ToolChainLocation= diff --git a/bsp/stm32/stm32l053-st-nucleo/board/CubeMX_Config/Src/stm32l0xx_hal_msp.c b/bsp/stm32/stm32l053-st-nucleo/board/CubeMX_Config/Src/stm32l0xx_hal_msp.c index 8eb266519d..ac7c1552f4 100644 --- a/bsp/stm32/stm32l053-st-nucleo/board/CubeMX_Config/Src/stm32l0xx_hal_msp.c +++ b/bsp/stm32/stm32l053-st-nucleo/board/CubeMX_Config/Src/stm32l0xx_hal_msp.c @@ -1,12 +1,12 @@ /** ****************************************************************************** * File Name : stm32l0xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether + * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * @@ -78,14 +78,14 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = USART_TX_Pin|USART_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -110,10 +110,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, USART_TX_Pin|USART_RX_Pin); diff --git a/bsp/stm32/stm32l412-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32l412-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index 4727ba50c3..355a13cc67 100644 --- a/bsp/stm32/stm32l412-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32l412-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -54,14 +54,14 @@ PA14\ (JTCK/SWCLK).Mode=Serial_Wire PA14\ (JTCK/SWCLK).Signal=SYS_JTCK-SWCLK PA2.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label PA2.GPIO_Label=USART_TX -PA2.GPIO_PuPd=GPIO_NOPULL +PA2.GPIO_PuPd=GPIO_PULLUP PA2.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH PA2.Locked=true PA2.Mode=Asynchronous PA2.Signal=USART2_TX PA3.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label PA3.GPIO_Label=USART_RX -PA3.GPIO_PuPd=GPIO_NOPULL +PA3.GPIO_PuPd=GPIO_PULLUP PA3.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH PA3.Locked=true PA3.Mode=Asynchronous diff --git a/bsp/stm32/stm32l412-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l412-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index 4e7628b29c..2361ae6c6a 100644 --- a/bsp/stm32/stm32l412-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l412-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -93,15 +93,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART2 GPIO Configuration + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = USART_TX_Pin|USART_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -128,10 +128,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); - - /**USART2 GPIO Configuration + + /**USART2 GPIO Configuration PA2 ------> USART2_TX - PA3 ------> USART2_RX + PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, USART_TX_Pin|USART_RX_Pin); diff --git a/bsp/stm32/stm32l431-BearPi/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32l431-BearPi/board/CubeMX_Config/CubeMX_Config.ioc index ce0175ce52..7600b27cb1 100644 --- a/bsp/stm32/stm32l431-BearPi/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32l431-BearPi/board/CubeMX_Config/CubeMX_Config.ioc @@ -37,12 +37,14 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false -PA10.Locked=true -PA10.Mode=Asynchronous -PA10.Signal=USART1_RX -PA9.Locked=true +PA9.GPIOParameters=GPIO_PuPd +PA9.GPIO_PuPd=GPIO_PULLUP PA9.Mode=Asynchronous PA9.Signal=USART1_TX +PA10.GPIOParameters=GPIO_PuPd +PA10.GPIO_PuPd=GPIO_PULLUP +PA10.Mode=Asynchronous +PA10.Signal=USART1_RX PB13.Locked=true PB13.Mode=Simplex_Bidirectional_Master PB13.Signal=SPI2_SCK diff --git a/bsp/stm32/stm32l431-BearPi/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l431-BearPi/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index 943aadf254..44adfa4b3b 100644 --- a/bsp/stm32/stm32l431-BearPi/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l431-BearPi/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -2,7 +2,7 @@ /** ****************************************************************************** * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization + * Description : This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention @@ -32,7 +32,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ - + /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ @@ -93,12 +93,12 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); - + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); - /**SPI2 GPIO Configuration + /**SPI2 GPIO Configuration PC3 ------> SPI2_MOSI - PB13 ------> SPI2_SCK + PB13 ------> SPI2_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -136,10 +136,10 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); - - /**SPI2 GPIO Configuration + + /**SPI2 GPIO Configuration PC3 ------> SPI2_MOSI - PB13 ------> SPI2_SCK + PB13 ------> SPI2_SCK */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_3); @@ -168,15 +168,15 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); - + __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USART1 GPIO Configuration + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -203,10 +203,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); - - /**USART1 GPIO Configuration + + /**USART1 GPIO Configuration PA9 ------> USART1_TX - PA10 ------> USART1_RX + PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); diff --git a/bsp/stm32/stm32l432-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc b/bsp/stm32/stm32l432-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc index 7304c402cd..844c31b868 100644 --- a/bsp/stm32/stm32l432-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc +++ b/bsp/stm32/stm32l432-st-nucleo/board/CubeMX_Config/CubeMX_Config.ioc @@ -54,14 +54,16 @@ PA14\ (JTCK-SWCLK).GPIO_Label=SWCLK PA14\ (JTCK-SWCLK).Locked=true PA14\ (JTCK-SWCLK).Mode=Serial_Wire PA14\ (JTCK-SWCLK).Signal=SYS_JTCK-SWCLK -PA15\ (JTDI).GPIOParameters=GPIO_Speed,GPIO_Label +PA15\ (JTDI).GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label PA15\ (JTDI).GPIO_Label=VCP_RX +PA15\ (JTDI).GPIO_PuPd=GPIO_PULLUP PA15\ (JTDI).GPIO_Speed=GPIO_SPEED_FREQ_MEDIUM PA15\ (JTDI).Locked=true PA15\ (JTDI).Mode=Asynchronous PA15\ (JTDI).Signal=USART2_RX -PA2.GPIOParameters=GPIO_Speed,GPIO_Label +PA2.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label PA2.GPIO_Label=VCP_TX +PA2.GPIO_PuPd=GPIO_PULLUP PA2.GPIO_Speed=GPIO_SPEED_FREQ_MEDIUM PA2.Locked=true PA2.Mode=Asynchronous @@ -76,14 +78,6 @@ PC14-OSC32_IN\ (PC14).Signal=RCC_OSC32_IN PC15-OSC32_OUT\ (PC15).Locked=true PC15-OSC32_OUT\ (PC15).Mode=LSE-External-Oscillator PC15-OSC32_OUT\ (PC15).Signal=RCC_OSC32_OUT -PCC.Checker=true -PCC.Line=STM32L4x2 -PCC.MCU=STM32L432K(B-C)Ux -PCC.PartNumber=STM32L432KCUx -PCC.Seq0=0 -PCC.Series=STM32L4 -PCC.Temperature=25 -PCC.Vdd=null PinOutPanel.RotationAngle=0 ProjectManager.AskForMigrate=true ProjectManager.BackupPrevious=false diff --git a/bsp/stm32/stm32l432-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c b/bsp/stm32/stm32l432-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c index 78ee2bd1f2..e778c888fa 100644 --- a/bsp/stm32/stm32l432-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c +++ b/bsp/stm32/stm32l432-st-nucleo/board/CubeMX_Config/Src/stm32l4xx_hal_msp.c @@ -1,38 +1,19 @@ +/* USER CODE BEGIN Header */ /** ****************************************************************************** - * File Name : stm32l4xx_hal_msp.c - * Description : This file provides code for the MSP Initialization - * and de-Initialization codes. + * @file stm32l4xx_hal_msp.c + * @brief This file provides code for the MSP Initialization + * and de-Initialization codes. ****************************************************************************** - ** This notice applies to any and all portions of this file - * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether - * inserted by the user or by software development tools - * are owned by their respective copyright owners. + * @attention * - * COPYRIGHT(c) 2019 STMicroelectronics + *

  • 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%0A9ln~%2~KVho4>rofPdmT2_VuWC{iH0t?+ye%0)x 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